summaryrefslogtreecommitdiff
path: root/Build/source
diff options
context:
space:
mode:
authorMartin Schröder <martin@oneiros.de>2008-03-24 15:47:15 +0000
committerMartin Schröder <martin@oneiros.de>2008-03-24 15:47:15 +0000
commit0b5550c241229764120d133af80a0cbab5937ddd (patch)
tree81309c18d6f0deba7407813cf15b9add2db375d1 /Build/source
parent51f55df6a36ce376952a1f2b30bdb4dd0e06548d (diff)
First step of importing luatex (up to r1121)
git-svn-id: svn://tug.org/texlive/trunk@7124 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source')
-rw-r--r--Build/source/libs/lua51/Makefile204
-rw-r--r--Build/source/libs/lua51/lapi.c1080
-rw-r--r--Build/source/libs/lua51/lapi.h16
-rw-r--r--Build/source/libs/lua51/lauxlib.c653
-rw-r--r--Build/source/libs/lua51/lauxlib.h174
-rw-r--r--Build/source/libs/lua51/lbaselib.c670
-rw-r--r--Build/source/libs/lua51/lcoco.c522
-rw-r--r--Build/source/libs/lua51/lcoco.h72
-rw-r--r--Build/source/libs/lua51/lcode.c839
-rw-r--r--Build/source/libs/lua51/lcode.h76
-rw-r--r--Build/source/libs/lua51/ldblib.c397
-rw-r--r--Build/source/libs/lua51/ldebug.c624
-rw-r--r--Build/source/libs/lua51/ldebug.h33
-rw-r--r--Build/source/libs/lua51/ldo.c516
-rw-r--r--Build/source/libs/lua51/ldo.h57
-rw-r--r--Build/source/libs/lua51/ldump.c164
-rw-r--r--Build/source/libs/lua51/lfunc.c174
-rw-r--r--Build/source/libs/lua51/lfunc.h34
-rw-r--r--Build/source/libs/lua51/lgc.c711
-rw-r--r--Build/source/libs/lua51/lgc.h110
-rw-r--r--Build/source/libs/lua51/linit.c38
-rw-r--r--Build/source/libs/lua51/liolib.c572
-rw-r--r--Build/source/libs/lua51/llex.c461
-rw-r--r--Build/source/libs/lua51/llex.h81
-rw-r--r--Build/source/libs/lua51/llimits.h128
-rw-r--r--Build/source/libs/lua51/lmathlib.c263
-rw-r--r--Build/source/libs/lua51/lmem.c86
-rw-r--r--Build/source/libs/lua51/lmem.h49
-rw-r--r--Build/source/libs/lua51/loadlib.c664
-rw-r--r--Build/source/libs/lua51/lobject.c214
-rw-r--r--Build/source/libs/lua51/lobject.h381
-rw-r--r--Build/source/libs/lua51/lopcodes.c102
-rw-r--r--Build/source/libs/lua51/lopcodes.h268
-rw-r--r--Build/source/libs/lua51/loslib.c244
-rw-r--r--Build/source/libs/lua51/lparser.c1337
-rw-r--r--Build/source/libs/lua51/lparser.h82
-rw-r--r--Build/source/libs/lua51/lstate.c214
-rw-r--r--Build/source/libs/lua51/lstate.h171
-rw-r--r--Build/source/libs/lua51/lstring.c111
-rw-r--r--Build/source/libs/lua51/lstring.h31
-rw-r--r--Build/source/libs/lua51/lstrlib.c1154
-rw-r--r--Build/source/libs/lua51/ltable.c588
-rw-r--r--Build/source/libs/lua51/ltable.h40
-rw-r--r--Build/source/libs/lua51/ltablib.c278
-rw-r--r--Build/source/libs/lua51/ltm.c75
-rw-r--r--Build/source/libs/lua51/ltm.h54
-rw-r--r--Build/source/libs/lua51/lua.c390
-rw-r--r--Build/source/libs/lua51/lua.h385
-rw-r--r--Build/source/libs/lua51/luac.c200
-rw-r--r--Build/source/libs/lua51/luaconf.h770
-rw-r--r--Build/source/libs/lua51/lualib.h53
-rw-r--r--Build/source/libs/lua51/lundump.c223
-rw-r--r--Build/source/libs/lua51/lundump.h36
-rw-r--r--Build/source/libs/lua51/lvm.c765
-rw-r--r--Build/source/libs/lua51/lvm.h36
-rw-r--r--Build/source/libs/lua51/lzio.c82
-rw-r--r--Build/source/libs/lua51/lzio.h67
-rw-r--r--Build/source/libs/lua51/print.c227
-rw-r--r--Build/source/libs/luafilesystem/Makefile28
-rw-r--r--Build/source/libs/luafilesystem/config20
-rw-r--r--Build/source/libs/luafilesystem/doc/us/examples.html103
-rw-r--r--Build/source/libs/luafilesystem/doc/us/index.html148
-rw-r--r--Build/source/libs/luafilesystem/doc/us/license.html122
-rw-r--r--Build/source/libs/luafilesystem/doc/us/luafilesystem.pngbin0 -> 8535 bytes
-rw-r--r--Build/source/libs/luafilesystem/doc/us/manual.html226
-rw-r--r--Build/source/libs/luafilesystem/src/lfs.c667
-rw-r--r--Build/source/libs/luafilesystem/src/lfs.h16
-rw-r--r--Build/source/libs/luafilesystem/tests/test.lua80
-rw-r--r--Build/source/libs/luafilesystem/vc6/lfs.def5
-rw-r--r--Build/source/libs/luafilesystem/vc6/luafilesystem.dsw33
-rw-r--r--Build/source/libs/luafilesystem/vc6/luafilesystem_dll.dsp127
-rw-r--r--Build/source/libs/luafontforge/Makefile24
-rw-r--r--Build/source/libs/luafontforge/fontforge/AUTHORS1
-rw-r--r--Build/source/libs/luafontforge/fontforge/INSTALL182
-rw-r--r--Build/source/libs/luafontforge/fontforge/LICENSE28
-rw-r--r--Build/source/libs/luafontforge/fontforge/Makefile112
-rw-r--r--Build/source/libs/luafontforge/fontforge/Unicode/Makefile15
-rw-r--r--Build/source/libs/luafontforge/fontforge/Unicode/alphabet.c3348
-rw-r--r--Build/source/libs/luafontforge/fontforge/Unicode/char.c103
-rw-r--r--Build/source/libs/luafontforge/fontforge/Unicode/cjk.c43041
-rw-r--r--Build/source/libs/luafontforge/fontforge/Unicode/descrip.mms27
-rw-r--r--Build/source/libs/luafontforge/fontforge/Unicode/gwwiconv.c1074
-rw-r--r--Build/source/libs/luafontforge/fontforge/Unicode/memory.c90
-rw-r--r--Build/source/libs/luafontforge/fontforge/Unicode/ustring.c885
-rw-r--r--Build/source/libs/luafontforge/fontforge/VERSION1
-rw-r--r--Build/source/libs/luafontforge/fontforge/descrip.mms9
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/Makefile36
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/autohint.c3528
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/charview.c9513
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/configure-pfaedit.h290
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/contextchain.c3032
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/descrip.mms197
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/edgelist.h146
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/edgelist2.h54
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/encoding.c3093
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/featurefile.c5539
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/fontinfo.c10184
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/fontview.c11163
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/fvfonts.c1911
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/groups.h49
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/kernclass.c3059
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/lff.opt1
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/lookups.c6916
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/macbinary.c3212
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/macenc.c3601
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/namelist.c19852
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/ofl.h7
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/parsepfa.c2762
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/parsettf.c5558
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/parsettfatt.c4635
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/parsettfvar.c778
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/pfaedit.h111
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/pfaeditui.h189
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/plugins.h99
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/prefs.c2282
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/psfont.h191
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/psread.c4671
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/pua.c1612
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/scriptfuncs.h39
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/scripting.h129
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/sd.h170
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/sfd1.h112
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/splinefill.c1864
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/splinefont.h2303
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/splineorder2.c1484
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/splineoverlap.c2527
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/splinerefigure.c101
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/splinesave.c3616
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/splinestroke.c1987
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/splineutil.c5776
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/splineutil2.c4069
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/stamp.c5
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/stamper.c20
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/start.c935
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/stemdb.c2428
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/stemdb.h153
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/tottf.c5768
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/tottfgpos.c3444
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/tottfvar.c814
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/ttf.h831
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/ttfspecial.c1067
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/unicoderange.h47
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/views.h1420
-rw-r--r--Build/source/libs/luafontforge/fontforge/fontforge/xlib.opt13
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/basics.h75
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/chardata.h78
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/charset.h71
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/dynamic.h35
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/fileutil.h43
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/gdraw.h593
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/gfile.h62
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/ggadget.h484
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/gicons.h52
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/gio.h109
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/gkeysym.h298
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/gprogress.h77
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/gresource.h58
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/gwidget.h215
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/gwwiconv.h55
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/intl.h85
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/ustring.h128
-rw-r--r--Build/source/libs/luafontforge/fontforge/inc/utype.h115
-rw-r--r--Build/source/libs/luafontforge/src/ffdummies.c5552
-rw-r--r--Build/source/libs/luafontforge/src/luafflib.c1769
-rw-r--r--Build/source/libs/luamd5/makefile23
-rw-r--r--Build/source/libs/luamd5/md5.c209
-rw-r--r--Build/source/libs/luamd5/md5.h20
-rw-r--r--Build/source/libs/luamd5/md5.html122
-rw-r--r--Build/source/libs/luamd5/md5.lua22
-rw-r--r--Build/source/libs/luamd5/md5lib.c183
-rw-r--r--Build/source/libs/luamd5/md5tests.lua78
-rw-r--r--Build/source/libs/luapeg/lpeg.c1989
-rw-r--r--Build/source/libs/luazip/Makefile24
-rw-r--r--Build/source/libs/luazip/README3
-rw-r--r--Build/source/libs/luazip/config23
-rw-r--r--Build/source/libs/luazip/doc/us/examples.html130
-rw-r--r--Build/source/libs/luazip/doc/us/index.html125
-rw-r--r--Build/source/libs/luazip/doc/us/license.html125
-rw-r--r--Build/source/libs/luazip/doc/us/luazip-128.pngbin0 -> 11156 bytes
-rw-r--r--Build/source/libs/luazip/doc/us/manual.html181
-rw-r--r--Build/source/libs/luazip/src/luazip.c533
-rw-r--r--Build/source/libs/luazip/src/luazip.h23
-rw-r--r--Build/source/libs/luazip/tests/a/b/c.zipbin0 -> 114 bytes
-rw-r--r--Build/source/libs/luazip/tests/a2/b2.ext2bin0 -> 203 bytes
-rw-r--r--Build/source/libs/luazip/tests/a2/b2.zipbin0 -> 203 bytes
-rw-r--r--Build/source/libs/luazip/tests/a3.ext3bin0 -> 299 bytes
-rw-r--r--Build/source/libs/luazip/tests/a3.zipbin0 -> 297 bytes
-rw-r--r--Build/source/libs/luazip/tests/luazip.zipbin0 -> 5062 bytes
-rw-r--r--Build/source/libs/luazip/tests/test_zip.lua76
-rw-r--r--Build/source/libs/luazip/vc6/README28
-rw-r--r--Build/source/libs/luazip/vc6/luazip.dsw29
-rw-r--r--Build/source/libs/luazip/vc6/luazip.rc109
-rw-r--r--Build/source/libs/luazip/vc6/luazip_dll.dsp163
-rw-r--r--Build/source/libs/luazip/vc6/luazip_static.dsp144
-rw-r--r--Build/source/libs/luazip/vc6/resource.h15
-rw-r--r--Build/source/libs/luazip/vc7/README27
-rw-r--r--Build/source/libs/luazip/vc7/luazip.rc103
-rw-r--r--Build/source/libs/luazip/vc7/luazip.sln29
-rw-r--r--Build/source/libs/luazip/vc7/luazip_dll.vcproj374
-rw-r--r--Build/source/libs/luazip/vc7/luazip_static.vcproj324
-rw-r--r--Build/source/libs/luazip/vc7/resource.h27
-rw-r--r--Build/source/libs/luazlib/Makefile57
-rw-r--r--Build/source/libs/luazlib/README30
-rw-r--r--Build/source/libs/luazlib/gzip.lua102
-rw-r--r--Build/source/libs/luazlib/lgzip.c373
-rw-r--r--Build/source/libs/luazlib/lzlib.c584
-rw-r--r--Build/source/libs/luazlib/test_gzip.lua96
-rw-r--r--Build/source/libs/luazlib/test_zlib.lua106
-rw-r--r--Build/source/libs/luazlib/zlib.lua105
-rw-r--r--Build/source/libs/slnunicode/slnudata.c946
-rw-r--r--Build/source/libs/slnunicode/slnunico.c1368
-rwxr-xr-xBuild/source/libs/slnunicode/unitest215
-rw-r--r--Build/source/libs/zziplib/COPYING.LIB481
-rw-r--r--Build/source/libs/zziplib/ChangeLog1194
-rw-r--r--Build/source/libs/zziplib/Makefile.am78
-rw-r--r--Build/source/libs/zziplib/Makefile.in743
-rw-r--r--Build/source/libs/zziplib/Makefile.mk73
-rw-r--r--Build/source/libs/zziplib/README47
-rw-r--r--Build/source/libs/zziplib/SDL/.deps/SDL_rwops_zzcat.Po1
-rw-r--r--Build/source/libs/zziplib/SDL/Makefile.am68
-rw-r--r--Build/source/libs/zziplib/SDL/Makefile.in588
-rw-r--r--Build/source/libs/zziplib/SDL/SDL_rwops_zzcat.c63
-rw-r--r--Build/source/libs/zziplib/SDL/SDL_rwops_zzip.c62
-rw-r--r--Build/source/libs/zziplib/SDL/SDL_rwops_zzip.h36
-rw-r--r--Build/source/libs/zziplib/SDL/zzip-sdl-config.pc10
-rw-r--r--Build/source/libs/zziplib/SDL/zzip-sdl-rwops.pc8
-rw-r--r--Build/source/libs/zziplib/TODO54
-rw-r--r--Build/source/libs/zziplib/aclocal.m47278
-rw-r--r--Build/source/libs/zziplib/bins/.deps/unzip-mem.Po1
-rw-r--r--Build/source/libs/zziplib/bins/.deps/unzzip.Po1
-rw-r--r--Build/source/libs/zziplib/bins/.deps/unzzipcat-mem.Po1
-rw-r--r--Build/source/libs/zziplib/bins/.deps/unzzipcat-seeko.Po1
-rw-r--r--Build/source/libs/zziplib/bins/.deps/unzzipcat.Po1
-rw-r--r--Build/source/libs/zziplib/bins/.deps/unzzipdir-mem.Po1
-rw-r--r--Build/source/libs/zziplib/bins/.deps/unzzipdir.Po1
-rw-r--r--Build/source/libs/zziplib/bins/.deps/zzcat.Po1
-rw-r--r--Build/source/libs/zziplib/bins/.deps/zzdir.Po1
-rw-r--r--Build/source/libs/zziplib/bins/.deps/zzip.Po1
-rw-r--r--Build/source/libs/zziplib/bins/.deps/zziptest.Po1
-rw-r--r--Build/source/libs/zziplib/bins/.deps/zzobfuscated.Po1
-rw-r--r--Build/source/libs/zziplib/bins/.deps/zzxorcat.Po1
-rw-r--r--Build/source/libs/zziplib/bins/.deps/zzxorcopy.Po1
-rw-r--r--Build/source/libs/zziplib/bins/.deps/zzxordir.Po1
-rw-r--r--Build/source/libs/zziplib/bins/Makefile.am56
-rw-r--r--Build/source/libs/zziplib/bins/Makefile.in689
-rw-r--r--Build/source/libs/zziplib/bins/unzip-mem.c420
-rw-r--r--Build/source/libs/zziplib/bins/unzzip.c111
-rw-r--r--Build/source/libs/zziplib/bins/unzzipcat-mem.c128
-rw-r--r--Build/source/libs/zziplib/bins/unzzipcat-seeko.c118
-rw-r--r--Build/source/libs/zziplib/bins/unzzipcat.c128
-rw-r--r--Build/source/libs/zziplib/bins/unzzipdir-mem.c101
-rw-r--r--Build/source/libs/zziplib/bins/unzzipdir.c104
-rw-r--r--Build/source/libs/zziplib/bins/zzcat.c74
-rw-r--r--Build/source/libs/zziplib/bins/zzdir.c86
-rw-r--r--Build/source/libs/zziplib/bins/zzip.c98
-rw-r--r--Build/source/libs/zziplib/bins/zziplib.m4105
-rw-r--r--Build/source/libs/zziplib/bins/zziptest.c153
-rw-r--r--Build/source/libs/zziplib/bins/zzobfuscated.c155
-rw-r--r--Build/source/libs/zziplib/bins/zzxorcat.c113
-rw-r--r--Build/source/libs/zziplib/bins/zzxorcopy.c112
-rw-r--r--Build/source/libs/zziplib/bins/zzxordir.c126
-rw-r--r--Build/source/libs/zziplib/config.h.in160
-rwxr-xr-xBuild/source/libs/zziplib/configure25785
-rw-r--r--Build/source/libs/zziplib/configure.ac320
-rw-r--r--Build/source/libs/zziplib/docs/64on32.htm195
-rw-r--r--Build/source/libs/zziplib/docs/COPYING.LIB481
-rw-r--r--Build/source/libs/zziplib/docs/COPYING.MPL567
-rw-r--r--Build/source/libs/zziplib/docs/COPYING.ZLIB30
-rw-r--r--Build/source/libs/zziplib/docs/Makefile.am249
-rw-r--r--Build/source/libs/zziplib/docs/Makefile.in618
-rw-r--r--Build/source/libs/zziplib/docs/README.MSVC6137
-rw-r--r--Build/source/libs/zziplib/docs/README.SDL125
-rw-r--r--Build/source/libs/zziplib/docs/body.htm98
-rw-r--r--Build/source/libs/zziplib/docs/configs.htm164
-rw-r--r--Build/source/libs/zziplib/docs/copying.htm113
-rw-r--r--Build/source/libs/zziplib/docs/developer.htm67
-rw-r--r--Build/source/libs/zziplib/docs/download.htm56
-rw-r--r--Build/source/libs/zziplib/docs/faq.htm182
-rw-r--r--Build/source/libs/zziplib/docs/fseeko.htm193
-rw-r--r--Build/source/libs/zziplib/docs/future.htm80
-rw-r--r--Build/source/libs/zziplib/docs/history.htm92
-rw-r--r--Build/source/libs/zziplib/docs/make-dbk.pl118
-rw-r--r--Build/source/libs/zziplib/docs/make-doc.pl580
-rw-r--r--Build/source/libs/zziplib/docs/make-doc.py1028
-rw-r--r--Build/source/libs/zziplib/docs/manpages.ar2719
-rw-r--r--Build/source/libs/zziplib/docs/memdisk.htm116
-rw-r--r--Build/source/libs/zziplib/docs/mksite.pl2114
-rw-r--r--Build/source/libs/zziplib/docs/mksite.sh1789
-rw-r--r--Build/source/libs/zziplib/docs/mmapped.htm226
-rw-r--r--Build/source/libs/zziplib/docs/referentials.htm65
-rw-r--r--Build/source/libs/zziplib/docs/sfx-make.htm167
-rw-r--r--Build/source/libs/zziplib/docs/zzip-api.htm30
-rw-r--r--Build/source/libs/zziplib/docs/zzip-basics.htm163
-rw-r--r--Build/source/libs/zziplib/docs/zzip-crypt.htm92
-rw-r--r--Build/source/libs/zziplib/docs/zzip-cryptoid.htm106
-rw-r--r--Build/source/libs/zziplib/docs/zzip-extio.htm188
-rw-r--r--Build/source/libs/zziplib/docs/zzip-extras.htm164
-rw-r--r--Build/source/libs/zziplib/docs/zzip-file.htm183
-rw-r--r--Build/source/libs/zziplib/docs/zzip-index.htm55
-rw-r--r--Build/source/libs/zziplib/docs/zzip-parse.htm219
-rw-r--r--Build/source/libs/zziplib/docs/zzip-sdl-rwops.htm90
-rw-r--r--Build/source/libs/zziplib/docs/zzip-xor.htm77
-rw-r--r--Build/source/libs/zziplib/docs/zzip-zip.htm146
-rw-r--r--Build/source/libs/zziplib/docs/zziplib-master.dbk59
-rw-r--r--Build/source/libs/zziplib/docs/zziplib.html3795
-rw-r--r--Build/source/libs/zziplib/m4/ac_compile_check_sizeof.m478
-rw-r--r--Build/source/libs/zziplib/m4/ac_set_default_paths_system.m4104
-rw-r--r--Build/source/libs/zziplib/m4/ac_sys_largefile_sensitive.m446
-rw-r--r--Build/source/libs/zziplib/m4/acx_restrict.m432
-rw-r--r--Build/source/libs/zziplib/m4/ax_cflags_gcc_option.m4187
-rw-r--r--Build/source/libs/zziplib/m4/ax_cflags_no_writable_strings.m4140
-rw-r--r--Build/source/libs/zziplib/m4/ax_cflags_strict_prototypes.m4127
-rw-r--r--Build/source/libs/zziplib/m4/ax_cflags_warn_all.m4118
-rw-r--r--Build/source/libs/zziplib/m4/ax_create_pkgconfig_info.m4312
-rw-r--r--Build/source/libs/zziplib/m4/ax_enable_builddir_uname.m4160
-rw-r--r--Build/source/libs/zziplib/m4/ax_expand_prefix.m433
-rw-r--r--Build/source/libs/zziplib/m4/ax_maintainer_mode_auto_silent.m438
-rw-r--r--Build/source/libs/zziplib/m4/ax_not_enable_frame_pointer.m431
-rw-r--r--Build/source/libs/zziplib/m4/ax_prefix_config_h.m4171
-rw-r--r--Build/source/libs/zziplib/m4/ax_set_version_info.m4178
-rw-r--r--Build/source/libs/zziplib/m4/ax_spec_file.m498
-rw-r--r--Build/source/libs/zziplib/m4/ax_spec_package_version.m4227
-rw-r--r--Build/source/libs/zziplib/m4/ax_warning_default_aclocaldir.m4113
-rw-r--r--Build/source/libs/zziplib/m4/ax_warning_default_pkgconfig.m4127
-rw-r--r--Build/source/libs/zziplib/m4/patch_libtool_on_darwin_zsh_overquoting.m436
-rw-r--r--Build/source/libs/zziplib/m4/patch_libtool_sys_lib_search_path_spec.m437
-rw-r--r--Build/source/libs/zziplib/m4/patch_libtool_to_add_host_cc.m464
-rw-r--r--Build/source/libs/zziplib/msvc6/zzcat.dsp98
-rw-r--r--Build/source/libs/zziplib/msvc6/zzdir.dsp98
-rw-r--r--Build/source/libs/zziplib/msvc6/zzip.dsp183
-rw-r--r--Build/source/libs/zziplib/msvc6/zziplib.dsp172
-rw-r--r--Build/source/libs/zziplib/msvc6/zziplib.dsw116
-rw-r--r--Build/source/libs/zziplib/msvc6/zziptest.dsp98
-rw-r--r--Build/source/libs/zziplib/msvc6/zzipwrap.dsp106
-rw-r--r--Build/source/libs/zziplib/msvc6/zzobfuscated.dsp98
-rw-r--r--Build/source/libs/zziplib/msvc7/test.zipbin0 -> 545 bytes
-rw-r--r--Build/source/libs/zziplib/msvc7/test1.zipbin0 -> 1183 bytes
-rw-r--r--Build/source/libs/zziplib/msvc7/zzcat.sln21
-rw-r--r--Build/source/libs/zziplib/msvc7/zzcat.vcproj202
-rw-r--r--Build/source/libs/zziplib/msvc7/zzdir.sln21
-rw-r--r--Build/source/libs/zziplib/msvc7/zzdir.vcproj202
-rw-r--r--Build/source/libs/zziplib/msvc7/zzip.sln69
-rw-r--r--Build/source/libs/zziplib/msvc7/zzip.vcproj166
-rw-r--r--Build/source/libs/zziplib/msvc7/zziplib.sln19
-rw-r--r--Build/source/libs/zziplib/msvc7/zziplib.vcproj260
-rwxr-xr-xBuild/source/libs/zziplib/msvc7/zzipself.bat18
-rw-r--r--Build/source/libs/zziplib/msvc7/zzipself.sln21
-rw-r--r--Build/source/libs/zziplib/msvc7/zzipself.txt9
-rw-r--r--Build/source/libs/zziplib/msvc7/zzipself.vcproj202
-rw-r--r--Build/source/libs/zziplib/msvc7/zzipsetstub.sln21
-rw-r--r--Build/source/libs/zziplib/msvc7/zzipsetstub.vcproj201
-rw-r--r--Build/source/libs/zziplib/msvc7/zziptest.sln21
-rw-r--r--Build/source/libs/zziplib/msvc7/zziptest.vcproj204
-rw-r--r--Build/source/libs/zziplib/msvc7/zzobfuscated.sln21
-rw-r--r--Build/source/libs/zziplib/msvc7/zzobfuscated.vcproj202
-rw-r--r--Build/source/libs/zziplib/msvc8/README.TXT31
-rw-r--r--Build/source/libs/zziplib/msvc8/test.zipbin0 -> 545 bytes
-rw-r--r--Build/source/libs/zziplib/msvc8/test1.zipbin0 -> 1183 bytes
-rw-r--r--Build/source/libs/zziplib/msvc8/zzcat.sln21
-rw-r--r--Build/source/libs/zziplib/msvc8/zzcat.vcproj202
-rw-r--r--Build/source/libs/zziplib/msvc8/zzdir.sln21
-rw-r--r--Build/source/libs/zziplib/msvc8/zzdir.vcproj202
-rw-r--r--Build/source/libs/zziplib/msvc8/zzip.sln69
-rw-r--r--Build/source/libs/zziplib/msvc8/zzip.vcproj166
-rw-r--r--Build/source/libs/zziplib/msvc8/zziplib.sln19
-rw-r--r--Build/source/libs/zziplib/msvc8/zziplib.vcproj260
-rwxr-xr-xBuild/source/libs/zziplib/msvc8/zzipself.bat18
-rw-r--r--Build/source/libs/zziplib/msvc8/zzipself.sln21
-rw-r--r--Build/source/libs/zziplib/msvc8/zzipself.txt9
-rw-r--r--Build/source/libs/zziplib/msvc8/zzipself.vcproj202
-rw-r--r--Build/source/libs/zziplib/msvc8/zzipsetstub.sln21
-rw-r--r--Build/source/libs/zziplib/msvc8/zzipsetstub.vcproj201
-rw-r--r--Build/source/libs/zziplib/msvc8/zziptest.sln21
-rw-r--r--Build/source/libs/zziplib/msvc8/zziptest.vcproj204
-rw-r--r--Build/source/libs/zziplib/msvc8/zzobfuscated.sln21
-rw-r--r--Build/source/libs/zziplib/msvc8/zzobfuscated.vcproj202
-rw-r--r--Build/source/libs/zziplib/test/.deps/zzipself.Po1
-rw-r--r--Build/source/libs/zziplib/test/.deps/zzipsetstub.Po1
-rw-r--r--Build/source/libs/zziplib/test/Makefile.am263
-rw-r--r--Build/source/libs/zziplib/test/Makefile.in737
-rw-r--r--Build/source/libs/zziplib/test/README47
-rw-r--r--Build/source/libs/zziplib/test/test.zipbin0 -> 1293 bytes
-rw-r--r--Build/source/libs/zziplib/test/test1.zipbin0 -> 1183 bytes
-rw-r--r--Build/source/libs/zziplib/test/zzipself.c87
-rw-r--r--Build/source/libs/zziplib/test/zzipsetstub.c61
-rwxr-xr-xBuild/source/libs/zziplib/uses/config.guess1473
-rwxr-xr-xBuild/source/libs/zziplib/uses/config.sub1576
-rwxr-xr-xBuild/source/libs/zziplib/uses/depcomp397
-rwxr-xr-xBuild/source/libs/zziplib/uses/install-sh251
-rw-r--r--Build/source/libs/zziplib/uses/ltmain.sh6500
-rwxr-xr-xBuild/source/libs/zziplib/uses/missing265
-rwxr-xr-xBuild/source/libs/zziplib/uses/mkinstalldirs40
-rw-r--r--Build/source/libs/zziplib/zzip/Makefile22
-rw-r--r--Build/source/libs/zziplib/zzip/Makefile.am142
-rw-r--r--Build/source/libs/zziplib/zzip/Makefile.in712
-rw-r--r--Build/source/libs/zziplib/zzip/__debug.h89
-rw-r--r--Build/source/libs/zziplib/zzip/__dirent.h393
-rw-r--r--Build/source/libs/zziplib/zzip/__fnmatch.h28
-rw-r--r--Build/source/libs/zziplib/zzip/__hints.h189
-rw-r--r--Build/source/libs/zziplib/zzip/__mmap.h107
-rw-r--r--Build/source/libs/zziplib/zzip/_config.h247
-rw-r--r--Build/source/libs/zziplib/zzip/_msvc.h211
-rw-r--r--Build/source/libs/zziplib/zzip/_msvc.sed26
-rw-r--r--Build/source/libs/zziplib/zzip/autoconf.h45
-rw-r--r--Build/source/libs/zziplib/zzip/conf.h270
-rw-r--r--Build/source/libs/zziplib/zzip/dir.c296
-rw-r--r--Build/source/libs/zziplib/zzip/err.c156
-rw-r--r--Build/source/libs/zziplib/zzip/fetch.c117
-rw-r--r--Build/source/libs/zziplib/zzip/fetch.h343
-rw-r--r--Build/source/libs/zziplib/zzip/file.c1029
-rw-r--r--Build/source/libs/zziplib/zzip/file.h81
-rw-r--r--Build/source/libs/zziplib/zzip/format.h233
-rw-r--r--Build/source/libs/zziplib/zzip/fseeko.c580
-rw-r--r--Build/source/libs/zziplib/zzip/fseeko.h116
-rw-r--r--Build/source/libs/zziplib/zzip/info.c161
-rw-r--r--Build/source/libs/zziplib/zzip/info.h25
-rw-r--r--Build/source/libs/zziplib/zzip/lib.h83
-rw-r--r--Build/source/libs/zziplib/zzip/memdisk.c394
-rw-r--r--Build/source/libs/zziplib/zzip/memdisk.h162
-rw-r--r--Build/source/libs/zziplib/zzip/mmapped.c565
-rw-r--r--Build/source/libs/zziplib/zzip/mmapped.h120
-rw-r--r--Build/source/libs/zziplib/zzip/plugin.c84
-rw-r--r--Build/source/libs/zziplib/zzip/plugin.h96
-rw-r--r--Build/source/libs/zziplib/zzip/stat.c119
-rw-r--r--Build/source/libs/zziplib/zzip/stdint.h45
-rw-r--r--Build/source/libs/zziplib/zzip/types.h51
-rw-r--r--Build/source/libs/zziplib/zzip/write.c461
-rw-r--r--Build/source/libs/zziplib/zzip/zip.c759
-rw-r--r--Build/source/libs/zziplib/zzip/zzip.h323
-rwxr-xr-xBuild/source/libs/zziplib/zzip/zziplib.wpj103
-rw-r--r--Build/source/libs/zziplib/zzipback.sed19
-rw-r--r--Build/source/libs/zziplib/zziplib.spec157
-rw-r--r--Build/source/libs/zziplib/zzipwrap/.deps/wrap.Plo1
-rw-r--r--Build/source/libs/zziplib/zzipwrap/.deps/zzipwrap.Po1
-rw-r--r--Build/source/libs/zziplib/zzipwrap/Makefile.am51
-rw-r--r--Build/source/libs/zziplib/zzipwrap/Makefile.in606
-rw-r--r--Build/source/libs/zziplib/zzipwrap/wrap.c223
-rw-r--r--Build/source/libs/zziplib/zzipwrap/wrap.h36
-rw-r--r--Build/source/libs/zziplib/zzipwrap/zzipwrap.c102
-rw-r--r--Build/source/libs/zziplib/zzipwrap/zzipwrap.pc10
-rw-r--r--Build/source/texk/web2c/Makefile.in9
-rw-r--r--Build/source/texk/web2c/luatexdir/.indent.pro12
-rw-r--r--Build/source/texk/web2c/luatexdir/ChangeLog69
-rw-r--r--Build/source/texk/web2c/luatexdir/Makefile.in141
-rw-r--r--Build/source/texk/web2c/luatexdir/NEWS537
-rw-r--r--Build/source/texk/web2c/luatexdir/README87
-rw-r--r--Build/source/texk/web2c/luatexdir/avl.c893
-rw-r--r--Build/source/texk/web2c/luatexdir/avl.h115
-rw-r--r--Build/source/texk/web2c/luatexdir/avlstuff.c180
-rw-r--r--Build/source/texk/web2c/luatexdir/avlstuff.h29
-rw-r--r--Build/source/texk/web2c/luatexdir/change-files.txt35
-rw-r--r--Build/source/texk/web2c/luatexdir/depend.mk2874
-rw-r--r--Build/source/texk/web2c/luatexdir/font/.indent.pro12
-rw-r--r--Build/source/texk/web2c/luatexdir/font/dofont.c183
-rw-r--r--Build/source/texk/web2c/luatexdir/font/luafont.c1733
-rw-r--r--Build/source/texk/web2c/luatexdir/font/macnames.c312
-rw-r--r--Build/source/texk/web2c/luatexdir/font/mapfile.c967
-rw-r--r--Build/source/texk/web2c/luatexdir/font/pkin.c439
-rw-r--r--Build/source/texk/web2c/luatexdir/font/sfnt.c647
-rw-r--r--Build/source/texk/web2c/luatexdir/font/sfnt.h197
-rw-r--r--Build/source/texk/web2c/luatexdir/font/subfont.c264
-rw-r--r--Build/source/texk/web2c/luatexdir/font/subfont.txt74
-rw-r--r--Build/source/texk/web2c/luatexdir/font/texfont.c1094
-rw-r--r--Build/source/texk/web2c/luatexdir/font/texfont.h524
-rw-r--r--Build/source/texk/web2c/luatexdir/font/tfmofm.c1005
-rw-r--r--Build/source/texk/web2c/luatexdir/font/tounicode.c604
-rw-r--r--Build/source/texk/web2c/luatexdir/font/tt_glyf.c658
-rw-r--r--Build/source/texk/web2c/luatexdir/font/tt_glyf.h60
-rw-r--r--Build/source/texk/web2c/luatexdir/font/tt_table.c483
-rw-r--r--Build/source/texk/web2c/luatexdir/font/tt_table.h193
-rw-r--r--Build/source/texk/web2c/luatexdir/font/vfovf.c1349
-rw-r--r--Build/source/texk/web2c/luatexdir/font/vfpacket.c377
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writecff.c3381
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writecff.h349
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writeenc.c183
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writefont.c885
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writet1.c1768
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writet3.c348
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writettf.c1509
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writettf.h172
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writetype0.c124
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writetype2.c422
-rw-r--r--Build/source/texk/web2c/luatexdir/hyphen.h60
-rw-r--r--Build/source/texk/web2c/luatexdir/image/.indent.pro12
-rw-r--r--Build/source/texk/web2c/luatexdir/image/epdf.c107
-rw-r--r--Build/source/texk/web2c/luatexdir/image/epdf.h125
-rw-r--r--Build/source/texk/web2c/luatexdir/image/image.h223
-rw-r--r--Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc1008
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writeimg.c677
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writejbig2.c749
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writejbig2.h151
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writejpg.c277
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writepng.c635
-rw-r--r--Build/source/texk/web2c/luatexdir/lang/hnjalloc.c72
-rw-r--r--Build/source/texk/web2c/luatexdir/lang/hnjalloc.h46
-rw-r--r--Build/source/texk/web2c/luatexdir/lang/hyphen.c830
-rw-r--r--Build/source/texk/web2c/luatexdir/lang/texlang.c825
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/.indent.pro12
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/lcallbacklib.c463
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/lfontlib.c213
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/limglib.c714
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/lkpselib.c272
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/llanglib.c219
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/llualib.c229
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/lmplib.c1251
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/lnodelib.c1967
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/loslibext.c627
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/lpdflib.c127
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/lstatslib.c211
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/ltexiolib.c117
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/ltexlib.c820
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/ltokenlib.c263
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/luainit.c520
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/luanode.c200
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/luastuff.c310
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/luatex.c343
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/luatoken.c548
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/mp.w26173
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/psout.w5697
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/texluac.c199
-rw-r--r--Build/source/texk/web2c/luatexdir/luatangle.ch492
-rw-r--r--Build/source/texk/web2c/luatexdir/luatangle.web3328
-rw-r--r--Build/source/texk/web2c/luatexdir/luatex-api.h104
-rw-r--r--Build/source/texk/web2c/luatexdir/luatex.ch2623
-rw-r--r--Build/source/texk/web2c/luatexdir/luatex.defines560
-rw-r--r--Build/source/texk/web2c/luatexdir/luatex.h173
-rw-r--r--Build/source/texk/web2c/luatexdir/luatex.mk170
-rw-r--r--Build/source/texk/web2c/luatexdir/luatex.web35760
-rw-r--r--Build/source/texk/web2c/luatexdir/luatexextra.in42
-rw-r--r--Build/source/texk/web2c/luatexdir/luatexlib.mk214
-rw-r--r--Build/source/texk/web2c/luatexdir/macnames.c312
-rw-r--r--Build/source/texk/web2c/luatexdir/makecpool.c60
-rw-r--r--Build/source/texk/web2c/luatexdir/managed-sa.c245
-rw-r--r--Build/source/texk/web2c/luatexdir/managed-sa.h74
-rw-r--r--Build/source/texk/web2c/luatexdir/mathcodes.c191
-rw-r--r--Build/source/texk/web2c/luatexdir/nodes.h648
-rw-r--r--Build/source/texk/web2c/luatexdir/pdftosrc.1219
-rw-r--r--Build/source/texk/web2c/luatexdir/pdftosrc.cc178
-rw-r--r--Build/source/texk/web2c/luatexdir/pdftosrc.rc35
-rw-r--r--Build/source/texk/web2c/luatexdir/ptexlib.h615
-rw-r--r--Build/source/texk/web2c/luatexdir/ptexmac.h236
-rw-r--r--Build/source/texk/web2c/luatexdir/svnversion.h3
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/linebreak.c2095
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/postlinebreak.c512
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/texnodes.c1694
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/texpdf.c169
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/textoken.c753
-rw-r--r--Build/source/texk/web2c/luatexdir/textcodes.c278
-rw-r--r--Build/source/texk/web2c/luatexdir/tokens.h68
-rw-r--r--Build/source/texk/web2c/luatexdir/ttf2afm.c1053
-rw-r--r--Build/source/texk/web2c/luatexdir/ttf2afm.rc35
-rw-r--r--Build/source/texk/web2c/luatexdir/utils.c1798
-rw-r--r--Build/source/texk/web2c/luatexdir/writezip.c98
-rw-r--r--Build/source/texk/web2c/web2c/coerce.h5
-rw-r--r--Build/source/texk/web2c/web2c/splitup.c7
555 files changed, 451365 insertions, 4 deletions
diff --git a/Build/source/libs/lua51/Makefile b/Build/source/libs/lua51/Makefile
new file mode 100644
index 00000000000..ad1c47b73e1
--- /dev/null
+++ b/Build/source/libs/lua51/Makefile
@@ -0,0 +1,204 @@
+# makefile for building Lua
+# see ../INSTALL for installation instructions
+# see ../Makefile and luaconf.h for further customization
+
+# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
+
+# Your platform. See PLATS for possible values.
+PLAT= none
+
+CC= gcc
+CFLAGS= -g -O2 -Wall $(XCFLAGS) $(MYCFLAGS) $(COCOFLAGS)
+AR= ar rcu
+RANLIB= ranlib
+RM= rm -f
+LIBS= $(XLDFLAGS) -lm $(MYLIBS)
+
+MYCFLAGS=
+MYLDFLAGS=
+MYLIBS=
+
+# ++ Coco =========
+# Default: autodetect gccasm/setjmp/ucontext/fibers context switch method.
+COCOCFLAGS=
+# Force use of setjmp (instead of gccasm).
+#COCOCFLAGS= -DCOCO_USE_SETJMP
+# Force use of ucontext (instead of gccasm or setjmp).
+#COCOCFLAGS= -DCOCO_USE_UCONTEXT
+# Uncomment this if you want to disable support for Coco.
+#COCOCFLAGS= -DCOCO_DISABLE
+# -- Coco =========
+
+
+# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
+
+PLATS= aix ansi bsd generic linux macosx mingw posix solaris
+
+# ++ Coco =========
+COCO_O= lcoco.o
+# -- Coco =========
+
+LUA_A= liblua.a
+CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
+ lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \
+ lundump.o lvm.o lzio.o $(COCO_O)
+LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
+ lstrlib.o loadlib.o linit.o
+
+LUA_T= lua
+LUA_O= lua.o
+
+LUAC_T= luac
+LUAC_O= luac.o print.o
+
+ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)
+ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
+ALL_A= $(LUA_A)
+
+default: $(PLAT)
+
+all: $(ALL_T)
+
+o: $(ALL_O)
+
+a: $(ALL_A)
+
+$(LUA_A): $(CORE_O) $(LIB_O)
+ $(AR) $@ $?
+ $(RANLIB) $@
+
+$(LUA_T): $(LUA_O) $(LUA_A)
+ $(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
+
+$(LUAC_T): $(LUAC_O) $(LUA_A)
+ $(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
+
+clean:
+ $(RM) $(ALL_T) $(ALL_O)
+
+depend:
+ @$(CC) $(CFLAGS) -MM l*.c print.c
+
+echo:
+ @echo "PLAT = $(PLAT)"
+ @echo "CC = $(CC)"
+ @echo "CFLAGS = $(CFLAGS)"
+ @echo "AR = $(AR)"
+ @echo "RANLIB = $(RANLIB)"
+ @echo "RM = $(RM)"
+ @echo "MYCFLAGS = $(MYCFLAGS)"
+ @echo "MYLDFLAGS = $(MYLDFLAGS)"
+ @echo "MYLIBS = $(MYLIBS)"
+
+# convenience targets for popular platforms
+
+none:
+ @echo "Please choose a platform: $(PLATS)"
+
+aix:
+ $(MAKE) a CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" MYLDFLAGS="-brtl -bexpall"
+
+ansi:
+ $(MAKE) a MYCFLAGS=-DLUA_ANSI
+
+bsd:
+ $(MAKE) a MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E"
+
+generic:
+ $(MAKE) a MYCFLAGS=
+
+linux:
+ $(MAKE) a MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
+
+macosx:
+ $(MAKE) a MYCFLAGS=-DLUA_USE_MACOSX
+# use this on Mac OS X 10.4
+# $(MAKE) a MYCFLAGS="-DLUA_USE_MACOSX -DLUA_USE_READLINE" MYLIBS="-lreadline"
+
+mingw:
+ $(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" \
+ "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
+ "MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe
+
+mingwcross:
+ $(MAKE) "LUA_A=liblua.a" "LUA_T=lua.exe" \
+ MYCFLAGS= MYLIBS= lua.exe
+
+
+posix:
+ $(MAKE) a MYCFLAGS=-DLUA_USE_POSIX
+
+solaris:
+ $(MAKE) a MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl"
+
+# list targets that do not create files (but not all makes understand .PHONY)
+.PHONY: all $(PLATS) default o a clean depend echo none
+
+# DO NOT DELETE
+
+lapi.o: lapi.c lua.h luaconf.h lapi.h lobject.h llimits.h ldebug.h \
+ lstate.h ltm.h lzio.h lmem.h lcoco.h ldo.h lfunc.h lgc.h lstring.h \
+ ltable.h lundump.h lvm.h
+lauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h
+lbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h lcoco.h
+lcoco.o: lcoco.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \
+ lzio.h lmem.h lcoco.h ldo.h lvm.h lgc.h
+lcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \
+ lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h lcoco.h \
+ ldo.h lgc.h ltable.h
+ldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h
+ldebug.o: ldebug.c lua.h luaconf.h lapi.h lobject.h llimits.h lcode.h \
+ llex.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
+ lcoco.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h
+ldo.o: ldo.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
+ lzio.h lmem.h lcoco.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h \
+ lstring.h ltable.h lundump.h lvm.h
+ldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \
+ lzio.h lmem.h lcoco.h lundump.h
+lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h lmem.h \
+ lstate.h ltm.h lzio.h lcoco.h
+lgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
+ lzio.h lmem.h lcoco.h ldo.h lfunc.h lgc.h lstring.h ltable.h
+linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h
+liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h
+llex.o: llex.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h ltm.h \
+ lzio.h lmem.h lcoco.h llex.h lparser.h lstring.h lgc.h ltable.h
+lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h
+lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
+ ltm.h lzio.h lmem.h lcoco.h ldo.h
+loadlib.o: loadlib.c lauxlib.h lua.h luaconf.h lobject.h llimits.h \
+ lualib.h
+lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \
+ ltm.h lzio.h lmem.h lcoco.h lstring.h lgc.h lvm.h
+lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h
+loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h
+lparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \
+ lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h lcoco.h \
+ ldo.h lfunc.h lstring.h lgc.h ltable.h
+lstate.o: lstate.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
+ ltm.h lzio.h lmem.h lcoco.h ldo.h lfunc.h lgc.h llex.h lstring.h \
+ ltable.h
+lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \
+ ltm.h lzio.h lcoco.h lstring.h lgc.h
+lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h
+ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
+ ltm.h lzio.h lmem.h lcoco.h ldo.h lgc.h ltable.h
+ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h
+ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \
+ lmem.h lcoco.h lstring.h lgc.h ltable.h
+lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h
+luac.o: luac.c lua.h luaconf.h lauxlib.h ldo.h lobject.h llimits.h \
+ lstate.h ltm.h lzio.h lmem.h lcoco.h lfunc.h lopcodes.h lstring.h lgc.h \
+ lundump.h
+lundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \
+ llimits.h ltm.h lzio.h lmem.h lcoco.h ldo.h lfunc.h lstring.h lgc.h \
+ lundump.h
+lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
+ lzio.h lmem.h lcoco.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h \
+ lvm.h
+lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \
+ lzio.h lcoco.h
+print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \
+ ltm.h lzio.h lmem.h lcoco.h lopcodes.h lundump.h
+
+# (end of Makefile)
diff --git a/Build/source/libs/lua51/lapi.c b/Build/source/libs/lua51/lapi.c
new file mode 100644
index 00000000000..e99ea7a31e6
--- /dev/null
+++ b/Build/source/libs/lua51/lapi.c
@@ -0,0 +1,1080 @@
+/*
+** $Id: lapi.c,v 2.55 2006/06/07 12:37:17 roberto Exp $
+** Lua API
+** See Copyright Notice in lua.h
+*/
+
+
+#include <assert.h>
+#include <math.h>
+#include <stdarg.h>
+#include <string.h>
+
+#define lapi_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lapi.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lundump.h"
+#include "lvm.h"
+
+
+
+const char lua_ident[] =
+ "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n"
+ "$Authors: " LUA_AUTHORS " $\n"
+ "$URL: www.lua.org $\n";
+
+
+
+#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
+
+#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject)
+
+#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;}
+
+
+
+static TValue *index2adr (lua_State *L, int idx) {
+ if (idx > 0) {
+ TValue *o = L->base + (idx - 1);
+ api_check(L, idx <= L->ci->top - L->base);
+ if (o >= L->top) return cast(TValue *, luaO_nilobject);
+ else return o;
+ }
+ else if (idx > LUA_REGISTRYINDEX) {
+ api_check(L, idx != 0 && -idx <= L->top - L->base);
+ return L->top + idx;
+ }
+ else switch (idx) { /* pseudo-indices */
+ case LUA_REGISTRYINDEX: return registry(L);
+ case LUA_ENVIRONINDEX: {
+ Closure *func = curr_func(L);
+ sethvalue(L, &L->env, func->c.env);
+ return &L->env;
+ }
+ case LUA_GLOBALSINDEX: return gt(L);
+ default: {
+ Closure *func = curr_func(L);
+ idx = LUA_GLOBALSINDEX - idx;
+ return (idx <= func->c.nupvalues)
+ ? &func->c.upvalue[idx-1]
+ : cast(TValue *, luaO_nilobject);
+ }
+ }
+}
+
+
+static Table *getcurrenv (lua_State *L) {
+ if (L->ci == L->base_ci) /* no enclosing function? */
+ return hvalue(gt(L)); /* use global table as environment */
+ else {
+ Closure *func = curr_func(L);
+ return func->c.env;
+ }
+}
+
+
+void luaA_pushobject (lua_State *L, const TValue *o) {
+ setobj2s(L, L->top, o);
+ api_incr_top(L);
+}
+
+
+LUA_API int lua_checkstack (lua_State *L, int size) {
+ int res;
+ lua_lock(L);
+ if ((L->top - L->base + size) > LUAI_MAXCSTACK)
+ res = 0; /* stack overflow */
+ else {
+ luaD_checkstack(L, size);
+ if (L->ci->top < L->top + size)
+ L->ci->top = L->top + size;
+ res = 1;
+ }
+ lua_unlock(L);
+ return res;
+}
+
+
+LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
+ StkId f, t;
+ if (from == to) return;
+ lua_lock(to);
+ api_checknelems(from, n);
+ api_check(from, G(from) == G(to));
+ api_check(from, to->ci->top - to->top >= n);
+ f = from->top;
+ t = to->top = to->top + n;
+ while (--n >= 0) setobj2s(to, --t, --f);
+ from->top = f;
+ lua_unlock(to);
+}
+
+
+LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
+ lua_CFunction old;
+ lua_lock(L);
+ old = G(L)->panic;
+ G(L)->panic = panicf;
+ lua_unlock(L);
+ return old;
+}
+
+
+LUA_API lua_State *lua_newthread (lua_State *L) {
+ lua_State *L1;
+ lua_lock(L);
+ luaC_checkGC(L);
+ L1 = luaE_newthread(L);
+ setthvalue(L, L->top, L1);
+ api_incr_top(L);
+ lua_unlock(L);
+ luai_userstatethread(L, L1);
+ return L1;
+}
+
+
+
+/*
+** basic stack manipulation
+*/
+
+
+LUA_API int lua_gettop (lua_State *L) {
+ return cast_int(L->top - L->base);
+}
+
+
+LUA_API void lua_settop (lua_State *L, int idx) {
+ lua_lock(L);
+ if (idx >= 0) {
+ api_check(L, idx <= L->stack_last - L->base);
+ while (L->top < L->base + idx)
+ setnilvalue(L->top++);
+ L->top = L->base + idx;
+ }
+ else {
+ api_check(L, -(idx+1) <= (L->top - L->base));
+ L->top += idx+1; /* `subtract' index (index is negative) */
+ }
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_remove (lua_State *L, int idx) {
+ StkId p;
+ lua_lock(L);
+ p = index2adr(L, idx);
+ api_checkvalidindex(L, p);
+ while (++p < L->top) setobjs2s(L, p-1, p);
+ L->top--;
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_insert (lua_State *L, int idx) {
+ StkId p;
+ StkId q;
+ lua_lock(L);
+ p = index2adr(L, idx);
+ api_checkvalidindex(L, p);
+ for (q = L->top; q>p; q--) setobjs2s(L, q, q-1);
+ setobjs2s(L, p, L->top);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_replace (lua_State *L, int idx) {
+ StkId o;
+ lua_lock(L);
+ /* explicit test for incompatible code */
+ if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci)
+ luaG_runerror(L, "no calling environment");
+ api_checknelems(L, 1);
+ o = index2adr(L, idx);
+ api_checkvalidindex(L, o);
+ if (idx == LUA_ENVIRONINDEX) {
+ Closure *func = curr_func(L);
+ api_check(L, ttistable(L->top - 1));
+ func->c.env = hvalue(L->top - 1);
+ luaC_barrier(L, func, L->top - 1);
+ }
+ else {
+ setobj(L, o, L->top - 1);
+ if (idx < LUA_GLOBALSINDEX) /* function upvalue? */
+ luaC_barrier(L, curr_func(L), L->top - 1);
+ }
+ L->top--;
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushvalue (lua_State *L, int idx) {
+ lua_lock(L);
+ setobj2s(L, L->top, index2adr(L, idx));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+
+/*
+** access functions (stack -> C)
+*/
+
+
+LUA_API int lua_type (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
+}
+
+
+LUA_API const char *lua_typename (lua_State *L, int t) {
+ UNUSED(L);
+ return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
+}
+
+
+LUA_API int lua_iscfunction (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ return iscfunction(o);
+}
+
+
+LUA_API int lua_isnumber (lua_State *L, int idx) {
+ TValue n;
+ const TValue *o = index2adr(L, idx);
+ return tonumber(o, &n);
+}
+
+
+LUA_API int lua_isstring (lua_State *L, int idx) {
+ int t = lua_type(L, idx);
+ return (t == LUA_TSTRING || t == LUA_TNUMBER);
+}
+
+
+LUA_API int lua_isuserdata (lua_State *L, int idx) {
+ const TValue *o = index2adr(L, idx);
+ return (ttisuserdata(o) || ttislightuserdata(o));
+}
+
+
+LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
+ StkId o1 = index2adr(L, index1);
+ StkId o2 = index2adr(L, index2);
+ return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0
+ : luaO_rawequalObj(o1, o2);
+}
+
+
+LUA_API int lua_equal (lua_State *L, int index1, int index2) {
+ StkId o1, o2;
+ int i;
+ lua_lock(L); /* may call tag method */
+ o1 = index2adr(L, index1);
+ o2 = index2adr(L, index2);
+ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2);
+ lua_unlock(L);
+ return i;
+}
+
+
+LUA_API int lua_lessthan (lua_State *L, int index1, int index2) {
+ StkId o1, o2;
+ int i;
+ lua_lock(L); /* may call tag method */
+ o1 = index2adr(L, index1);
+ o2 = index2adr(L, index2);
+ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0
+ : luaV_lessthan(L, o1, o2);
+ lua_unlock(L);
+ return i;
+}
+
+
+
+LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
+ TValue n;
+ const TValue *o = index2adr(L, idx);
+ if (tonumber(o, &n))
+ return nvalue(o);
+ else
+ return 0;
+}
+
+
+LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {
+ TValue n;
+ const TValue *o = index2adr(L, idx);
+ if (tonumber(o, &n)) {
+ lua_Integer res;
+ lua_Number num = nvalue(o);
+ lua_number2integer(res, num);
+ return res;
+ }
+ else
+ return 0;
+}
+
+
+LUA_API int lua_toboolean (lua_State *L, int idx) {
+ const TValue *o = index2adr(L, idx);
+ return !l_isfalse(o);
+}
+
+
+LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
+ StkId o = index2adr(L, idx);
+ if (!ttisstring(o)) {
+ lua_lock(L); /* `luaV_tostring' may create a new string */
+ if (!luaV_tostring(L, o)) { /* conversion failed? */
+ if (len != NULL) *len = 0;
+ lua_unlock(L);
+ return NULL;
+ }
+ luaC_checkGC(L);
+ o = index2adr(L, idx); /* previous call may reallocate the stack */
+ lua_unlock(L);
+ }
+ if (len != NULL) *len = tsvalue(o)->len;
+ return svalue(o);
+}
+
+
+LUA_API size_t lua_objlen (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ switch (ttype(o)) {
+ case LUA_TSTRING: return tsvalue(o)->len;
+ case LUA_TUSERDATA: return uvalue(o)->len;
+ case LUA_TTABLE: return luaH_getn(hvalue(o));
+ case LUA_TNUMBER: {
+ size_t l;
+ lua_lock(L); /* `luaV_tostring' may create a new string */
+ l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0);
+ lua_unlock(L);
+ return l;
+ }
+ default: return 0;
+ }
+}
+
+
+LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ return (!iscfunction(o)) ? NULL : clvalue(o)->c.f;
+}
+
+
+LUA_API void *lua_touserdata (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ switch (ttype(o)) {
+ case LUA_TUSERDATA: return (rawuvalue(o) + 1);
+ case LUA_TLIGHTUSERDATA: return pvalue(o);
+ default: return NULL;
+ }
+}
+
+
+LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ return (!ttisthread(o)) ? NULL : thvalue(o);
+}
+
+
+LUA_API const void *lua_topointer (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ switch (ttype(o)) {
+ case LUA_TTABLE: return hvalue(o);
+ case LUA_TFUNCTION: return clvalue(o);
+ case LUA_TTHREAD: return thvalue(o);
+ case LUA_TUSERDATA:
+ case LUA_TLIGHTUSERDATA:
+ return lua_touserdata(L, idx);
+ default: return NULL;
+ }
+}
+
+
+
+/*
+** push functions (C -> stack)
+*/
+
+
+LUA_API void lua_pushnil (lua_State *L) {
+ lua_lock(L);
+ setnilvalue(L->top);
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
+ lua_lock(L);
+ setnvalue(L->top, n);
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
+ lua_lock(L);
+ setnvalue(L->top, cast_num(n));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
+ lua_lock(L);
+ luaC_checkGC(L);
+ setsvalue2s(L, L->top, luaS_newlstr(L, s, len));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushstring (lua_State *L, const char *s) {
+ if (s == NULL)
+ lua_pushnil(L);
+ else
+ lua_pushlstring(L, s, strlen(s));
+}
+
+
+LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
+ va_list argp) {
+ const char *ret;
+ lua_lock(L);
+ luaC_checkGC(L);
+ ret = luaO_pushvfstring(L, fmt, argp);
+ lua_unlock(L);
+ return ret;
+}
+
+
+LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
+ const char *ret;
+ va_list argp;
+ lua_lock(L);
+ luaC_checkGC(L);
+ va_start(argp, fmt);
+ ret = luaO_pushvfstring(L, fmt, argp);
+ va_end(argp);
+ lua_unlock(L);
+ return ret;
+}
+
+
+LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
+ Closure *cl;
+ lua_lock(L);
+ luaC_checkGC(L);
+ api_checknelems(L, n);
+ cl = luaF_newCclosure(L, n, getcurrenv(L));
+ cl->c.f = fn;
+ L->top -= n;
+ while (n--)
+ setobj2n(L, &cl->c.upvalue[n], L->top+n);
+ setclvalue(L, L->top, cl);
+ lua_assert(iswhite(obj2gco(cl)));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushboolean (lua_State *L, int b) {
+ lua_lock(L);
+ setbvalue(L->top, (b != 0)); /* ensure that true is 1 */
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
+ lua_lock(L);
+ setpvalue(L->top, p);
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API int lua_pushthread (lua_State *L) {
+ lua_lock(L);
+ setthvalue(L, L->top, L);
+ api_incr_top(L);
+ lua_unlock(L);
+ return (G(L)->mainthread == L);
+}
+
+
+
+/*
+** get functions (Lua -> stack)
+*/
+
+
+LUA_API void lua_gettable (lua_State *L, int idx) {
+ StkId t;
+ lua_lock(L);
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
+ luaV_gettable(L, t, L->top - 1, L->top - 1);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
+ StkId t;
+ TValue key;
+ lua_lock(L);
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
+ setsvalue(L, &key, luaS_new(L, k));
+ luaV_gettable(L, t, &key, L->top);
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_rawget (lua_State *L, int idx) {
+ StkId t;
+ lua_lock(L);
+ t = index2adr(L, idx);
+ api_check(L, ttistable(t));
+ setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
+ StkId o;
+ lua_lock(L);
+ o = index2adr(L, idx);
+ api_check(L, ttistable(o));
+ setobj2s(L, L->top, luaH_getnum(hvalue(o), n));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
+ lua_lock(L);
+ luaC_checkGC(L);
+ sethvalue(L, L->top, luaH_new(L, narray, nrec));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API int lua_getmetatable (lua_State *L, int objindex) {
+ const TValue *obj;
+ Table *mt = NULL;
+ int res;
+ lua_lock(L);
+ obj = index2adr(L, objindex);
+ switch (ttype(obj)) {
+ case LUA_TTABLE:
+ mt = hvalue(obj)->metatable;
+ break;
+ case LUA_TUSERDATA:
+ mt = uvalue(obj)->metatable;
+ break;
+ default:
+ mt = G(L)->mt[ttype(obj)];
+ break;
+ }
+ if (mt == NULL)
+ res = 0;
+ else {
+ sethvalue(L, L->top, mt);
+ api_incr_top(L);
+ res = 1;
+ }
+ lua_unlock(L);
+ return res;
+}
+
+
+LUA_API void lua_getfenv (lua_State *L, int idx) {
+ StkId o;
+ lua_lock(L);
+ o = index2adr(L, idx);
+ api_checkvalidindex(L, o);
+ switch (ttype(o)) {
+ case LUA_TFUNCTION:
+ sethvalue(L, L->top, clvalue(o)->c.env);
+ break;
+ case LUA_TUSERDATA:
+ sethvalue(L, L->top, uvalue(o)->env);
+ break;
+ case LUA_TTHREAD:
+ setobj2s(L, L->top, gt(thvalue(o)));
+ break;
+ default:
+ setnilvalue(L->top);
+ break;
+ }
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+/*
+** set functions (stack -> Lua)
+*/
+
+
+LUA_API void lua_settable (lua_State *L, int idx) {
+ StkId t;
+ lua_lock(L);
+ api_checknelems(L, 2);
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
+ luaV_settable(L, t, L->top - 2, L->top - 1);
+ L->top -= 2; /* pop index and value */
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
+ StkId t;
+ TValue key;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
+ setsvalue(L, &key, luaS_new(L, k));
+ luaV_settable(L, t, &key, L->top - 1);
+ L->top--; /* pop value */
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_rawset (lua_State *L, int idx) {
+ StkId t;
+ lua_lock(L);
+ api_checknelems(L, 2);
+ t = index2adr(L, idx);
+ api_check(L, ttistable(t));
+ setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);
+ luaC_barriert(L, hvalue(t), L->top-1);
+ L->top -= 2;
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
+ StkId o;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ o = index2adr(L, idx);
+ api_check(L, ttistable(o));
+ setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
+ luaC_barriert(L, hvalue(o), L->top-1);
+ L->top--;
+ lua_unlock(L);
+}
+
+
+LUA_API int lua_setmetatable (lua_State *L, int objindex) {
+ TValue *obj;
+ Table *mt;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ obj = index2adr(L, objindex);
+ api_checkvalidindex(L, obj);
+ if (ttisnil(L->top - 1))
+ mt = NULL;
+ else {
+ api_check(L, ttistable(L->top - 1));
+ mt = hvalue(L->top - 1);
+ }
+ switch (ttype(obj)) {
+ case LUA_TTABLE: {
+ hvalue(obj)->metatable = mt;
+ if (mt)
+ luaC_objbarriert(L, hvalue(obj), mt);
+ break;
+ }
+ case LUA_TUSERDATA: {
+ uvalue(obj)->metatable = mt;
+ if (mt)
+ luaC_objbarrier(L, rawuvalue(obj), mt);
+ break;
+ }
+ default: {
+ G(L)->mt[ttype(obj)] = mt;
+ break;
+ }
+ }
+ L->top--;
+ lua_unlock(L);
+ return 1;
+}
+
+
+LUA_API int lua_setfenv (lua_State *L, int idx) {
+ StkId o;
+ int res = 1;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ o = index2adr(L, idx);
+ api_checkvalidindex(L, o);
+ api_check(L, ttistable(L->top - 1));
+ switch (ttype(o)) {
+ case LUA_TFUNCTION:
+ clvalue(o)->c.env = hvalue(L->top - 1);
+ break;
+ case LUA_TUSERDATA:
+ uvalue(o)->env = hvalue(L->top - 1);
+ break;
+ case LUA_TTHREAD:
+ sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1));
+ break;
+ default:
+ res = 0;
+ break;
+ }
+ luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));
+ L->top--;
+ lua_unlock(L);
+ return res;
+}
+
+
+/*
+** `load' and `call' functions (run Lua code)
+*/
+
+
+#define adjustresults(L,nres) \
+ { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; }
+
+
+#define checkresults(L,na,nr) \
+ api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)))
+
+
+LUA_API void lua_call (lua_State *L, int nargs, int nresults) {
+ StkId func;
+ lua_lock(L);
+ api_checknelems(L, nargs+1);
+ checkresults(L, nargs, nresults);
+ func = L->top - (nargs+1);
+ luaD_call(L, func, nresults);
+ adjustresults(L, nresults);
+ lua_unlock(L);
+}
+
+
+
+/*
+** Execute a protected call.
+*/
+struct CallS { /* data to `f_call' */
+ StkId func;
+ int nresults;
+};
+
+
+static void f_call (lua_State *L, void *ud) {
+ struct CallS *c = cast(struct CallS *, ud);
+ luaD_call(L, c->func, c->nresults);
+}
+
+
+
+LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
+ struct CallS c;
+ int status;
+ ptrdiff_t func;
+ lua_lock(L);
+ api_checknelems(L, nargs+1);
+ checkresults(L, nargs, nresults);
+ if (errfunc == 0)
+ func = 0;
+ else {
+ StkId o = index2adr(L, errfunc);
+ api_checkvalidindex(L, o);
+ func = savestack(L, o);
+ }
+ c.func = L->top - (nargs+1); /* function to be called */
+ c.nresults = nresults;
+ status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
+ adjustresults(L, nresults);
+ lua_unlock(L);
+ return status;
+}
+
+
+/*
+** Execute a protected C call.
+*/
+struct CCallS { /* data to `f_Ccall' */
+ lua_CFunction func;
+ void *ud;
+};
+
+
+static void f_Ccall (lua_State *L, void *ud) {
+ struct CCallS *c = cast(struct CCallS *, ud);
+ Closure *cl;
+ cl = luaF_newCclosure(L, 0, getcurrenv(L));
+ cl->c.f = c->func;
+ setclvalue(L, L->top, cl); /* push function */
+ api_incr_top(L);
+ setpvalue(L->top, c->ud); /* push only argument */
+ api_incr_top(L);
+ luaD_call(L, L->top - 2, 0);
+}
+
+
+LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) {
+ struct CCallS c;
+ int status;
+ lua_lock(L);
+ c.func = func;
+ c.ud = ud;
+ status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0);
+ lua_unlock(L);
+ return status;
+}
+
+
+LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
+ const char *chunkname) {
+ ZIO z;
+ int status;
+ lua_lock(L);
+ if (!chunkname) chunkname = "?";
+ luaZ_init(L, &z, reader, data);
+ status = luaD_protectedparser(L, &z, chunkname);
+ lua_unlock(L);
+ return status;
+}
+
+
+LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {
+ int status;
+ TValue *o;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ o = L->top - 1;
+ if (isLfunction(o))
+ status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0);
+ else
+ status = 1;
+ lua_unlock(L);
+ return status;
+}
+
+
+LUA_API int lua_status (lua_State *L) {
+ return L->status;
+}
+
+
+/*
+** Garbage-collection function
+*/
+
+LUA_API int lua_gc (lua_State *L, int what, int data) {
+ int res = 0;
+ global_State *g;
+ lua_lock(L);
+ g = G(L);
+ switch (what) {
+ case LUA_GCSTOP: {
+ g->GCthreshold = MAX_LUMEM;
+ break;
+ }
+ case LUA_GCRESTART: {
+ g->GCthreshold = g->totalbytes;
+ break;
+ }
+ case LUA_GCCOLLECT: {
+ luaC_fullgc(L);
+ break;
+ }
+ case LUA_GCCOUNT: {
+ /* GC values are expressed in Kbytes: #bytes/2^10 */
+ res = cast_int(g->totalbytes >> 10);
+ break;
+ }
+ case LUA_GCCOUNTB: {
+ res = cast_int(g->totalbytes & 0x3ff);
+ break;
+ }
+ case LUA_GCSTEP: {
+ lu_mem a = (cast(lu_mem, data) << 10);
+ if (a <= g->totalbytes)
+ g->GCthreshold = g->totalbytes - a;
+ else
+ g->GCthreshold = 0;
+ while (g->GCthreshold <= g->totalbytes)
+ luaC_step(L);
+ if (g->gcstate == GCSpause) /* end of cycle? */
+ res = 1; /* signal it */
+ break;
+ }
+ case LUA_GCSETPAUSE: {
+ res = g->gcpause;
+ g->gcpause = data;
+ break;
+ }
+ case LUA_GCSETSTEPMUL: {
+ res = g->gcstepmul;
+ g->gcstepmul = data;
+ break;
+ }
+ default: res = -1; /* invalid option */
+ }
+ lua_unlock(L);
+ return res;
+}
+
+
+
+/*
+** miscellaneous functions
+*/
+
+
+LUA_API int lua_error (lua_State *L) {
+ lua_lock(L);
+ api_checknelems(L, 1);
+ luaG_errormsg(L);
+ lua_unlock(L);
+ return 0; /* to avoid warnings */
+}
+
+
+LUA_API int lua_next (lua_State *L, int idx) {
+ StkId t;
+ int more;
+ lua_lock(L);
+ t = index2adr(L, idx);
+ api_check(L, ttistable(t));
+ more = luaH_next(L, hvalue(t), L->top - 1);
+ if (more) {
+ api_incr_top(L);
+ }
+ else /* no more elements */
+ L->top -= 1; /* remove key */
+ lua_unlock(L);
+ return more;
+}
+
+
+LUA_API void lua_concat (lua_State *L, int n) {
+ lua_lock(L);
+ api_checknelems(L, n);
+ if (n >= 2) {
+ luaC_checkGC(L);
+ luaV_concat(L, n, cast_int(L->top - L->base) - 1);
+ L->top -= (n-1);
+ }
+ else if (n == 0) { /* push empty string */
+ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0));
+ api_incr_top(L);
+ }
+ /* else n == 1; nothing to do */
+ lua_unlock(L);
+}
+
+
+LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {
+ lua_Alloc f;
+ lua_lock(L);
+ if (ud) *ud = G(L)->ud;
+ f = G(L)->frealloc;
+ lua_unlock(L);
+ return f;
+}
+
+
+LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
+ lua_lock(L);
+ G(L)->ud = ud;
+ G(L)->frealloc = f;
+ lua_unlock(L);
+}
+
+
+LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
+ Udata *u;
+ lua_lock(L);
+ luaC_checkGC(L);
+ u = luaS_newudata(L, size, getcurrenv(L));
+ setuvalue(L, L->top, u);
+ api_incr_top(L);
+ lua_unlock(L);
+ return u + 1;
+}
+
+
+
+
+static const char *aux_upvalue (StkId fi, int n, TValue **val) {
+ Closure *f;
+ if (!ttisfunction(fi)) return NULL;
+ f = clvalue(fi);
+ if (f->c.isC) {
+ if (!(1 <= n && n <= f->c.nupvalues)) return NULL;
+ *val = &f->c.upvalue[n-1];
+ return "";
+ }
+ else {
+ Proto *p = f->l.p;
+ if (!(1 <= n && n <= p->sizeupvalues)) return NULL;
+ *val = f->l.upvals[n-1]->v;
+ return getstr(p->upvalues[n-1]);
+ }
+}
+
+
+LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
+ const char *name;
+ TValue *val;
+ lua_lock(L);
+ name = aux_upvalue(index2adr(L, funcindex), n, &val);
+ if (name) {
+ setobj2s(L, L->top, val);
+ api_incr_top(L);
+ }
+ lua_unlock(L);
+ return name;
+}
+
+
+LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
+ const char *name;
+ TValue *val;
+ StkId fi;
+ lua_lock(L);
+ fi = index2adr(L, funcindex);
+ api_checknelems(L, 1);
+ name = aux_upvalue(fi, n, &val);
+ if (name) {
+ L->top--;
+ setobj(L, val, L->top);
+ luaC_barrier(L, clvalue(fi), L->top);
+ }
+ lua_unlock(L);
+ return name;
+}
+
diff --git a/Build/source/libs/lua51/lapi.h b/Build/source/libs/lua51/lapi.h
new file mode 100644
index 00000000000..9d1d435649c
--- /dev/null
+++ b/Build/source/libs/lua51/lapi.h
@@ -0,0 +1,16 @@
+/*
+** $Id: lapi.h,v 2.2 2005/04/25 19:24:10 roberto Exp $
+** Auxiliary functions from Lua API
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lapi_h
+#define lapi_h
+
+
+#include "lobject.h"
+
+
+LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);
+
+#endif
diff --git a/Build/source/libs/lua51/lauxlib.c b/Build/source/libs/lua51/lauxlib.c
new file mode 100644
index 00000000000..96a6b85237a
--- /dev/null
+++ b/Build/source/libs/lua51/lauxlib.c
@@ -0,0 +1,653 @@
+/*
+** $Id: lauxlib.c,v 1.159 2006/03/21 19:31:09 roberto Exp $
+** Auxiliary functions for building Lua libraries
+** See Copyright Notice in lua.h
+*/
+
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* This file uses only the official API of Lua.
+** Any function declared here could be written as an application function.
+*/
+
+#define lauxlib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+
+
+#define FREELIST_REF 0 /* free list of references */
+
+
+/* convert a stack index to positive */
+#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
+ lua_gettop(L) + (i) + 1)
+
+
+/*
+** {======================================================
+** Error-report functions
+** =======================================================
+*/
+
+
+LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
+ lua_Debug ar;
+ if (!lua_getstack(L, 0, &ar)) /* no stack frame? */
+ return luaL_error(L, "bad argument #%d (%s)", narg, extramsg);
+ lua_getinfo(L, "n", &ar);
+ if (strcmp(ar.namewhat, "method") == 0) {
+ narg--; /* do not count `self' */
+ if (narg == 0) /* error is in the self argument itself? */
+ return luaL_error(L, "calling " LUA_QS " on bad self (%s)",
+ ar.name, extramsg);
+ }
+ if (ar.name == NULL)
+ ar.name = "?";
+ return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)",
+ narg, ar.name, extramsg);
+}
+
+
+LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) {
+ const char *msg = lua_pushfstring(L, "%s expected, got %s",
+ tname, luaL_typename(L, narg));
+ return luaL_argerror(L, narg, msg);
+}
+
+
+static void tag_error (lua_State *L, int narg, int tag) {
+ luaL_typerror(L, narg, lua_typename(L, tag));
+}
+
+
+LUALIB_API void luaL_where (lua_State *L, int level) {
+ lua_Debug ar;
+ if (lua_getstack(L, level, &ar)) { /* check function at level */
+ lua_getinfo(L, "Sl", &ar); /* get info about it */
+ if (ar.currentline > 0) { /* is there info? */
+ lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
+ return;
+ }
+ }
+ lua_pushliteral(L, ""); /* else, no information available... */
+}
+
+
+LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
+ va_list argp;
+ va_start(argp, fmt);
+ luaL_where(L, 1);
+ lua_pushvfstring(L, fmt, argp);
+ va_end(argp);
+ lua_concat(L, 2);
+ return lua_error(L);
+}
+
+/* }====================================================== */
+
+
+LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,
+ const char *const lst[]) {
+ const char *name = (def) ? luaL_optstring(L, narg, def) :
+ luaL_checkstring(L, narg);
+ int i;
+ for (i=0; lst[i]; i++)
+ if (strcmp(lst[i], name) == 0)
+ return i;
+ return luaL_argerror(L, narg,
+ lua_pushfstring(L, "invalid option " LUA_QS, name));
+}
+
+
+LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
+ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */
+ if (!lua_isnil(L, -1)) /* name already in use? */
+ return 0; /* leave previous value on top, but return 0 */
+ lua_pop(L, 1);
+ lua_newtable(L); /* create metatable */
+ lua_pushvalue(L, -1);
+ lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */
+ return 1;
+}
+
+
+LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
+ void *p = lua_touserdata(L, ud);
+ if (p != NULL) { /* value is a userdata? */
+ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
+ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
+ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
+ lua_pop(L, 2); /* remove both metatables */
+ return p;
+ }
+ }
+ }
+ luaL_typerror(L, ud, tname); /* else error */
+ return NULL; /* to avoid warnings */
+}
+
+
+LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
+ if (!lua_checkstack(L, space))
+ luaL_error(L, "stack overflow (%s)", mes);
+}
+
+
+LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {
+ if (lua_type(L, narg) != t)
+ tag_error(L, narg, t);
+}
+
+
+LUALIB_API void luaL_checkany (lua_State *L, int narg) {
+ if (lua_type(L, narg) == LUA_TNONE)
+ luaL_argerror(L, narg, "value expected");
+}
+
+
+LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
+ const char *s = lua_tolstring(L, narg, len);
+ if (!s) tag_error(L, narg, LUA_TSTRING);
+ return s;
+}
+
+
+LUALIB_API const char *luaL_optlstring (lua_State *L, int narg,
+ const char *def, size_t *len) {
+ if (lua_isnoneornil(L, narg)) {
+ if (len)
+ *len = (def ? strlen(def) : 0);
+ return def;
+ }
+ else return luaL_checklstring(L, narg, len);
+}
+
+
+LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
+ lua_Number d = lua_tonumber(L, narg);
+ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
+ tag_error(L, narg, LUA_TNUMBER);
+ return d;
+}
+
+
+LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
+ return luaL_opt(L, luaL_checknumber, narg, def);
+}
+
+
+LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
+ lua_Integer d = lua_tointeger(L, narg);
+ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
+ tag_error(L, narg, LUA_TNUMBER);
+ return d;
+}
+
+
+LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
+ lua_Integer def) {
+ return luaL_opt(L, luaL_checkinteger, narg, def);
+}
+
+
+LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
+ if (!lua_getmetatable(L, obj)) /* no metatable? */
+ return 0;
+ lua_pushstring(L, event);
+ lua_rawget(L, -2);
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 2); /* remove metatable and metafield */
+ return 0;
+ }
+ else {
+ lua_remove(L, -2); /* remove only metatable */
+ return 1;
+ }
+}
+
+
+LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
+ obj = abs_index(L, obj);
+ if (!luaL_getmetafield(L, obj, event)) /* no metafield? */
+ return 0;
+ lua_pushvalue(L, obj);
+ lua_call(L, 1, 1);
+ return 1;
+}
+
+
+LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
+ const luaL_Reg *l) {
+ luaI_openlib(L, libname, l, 0);
+}
+
+
+static int libsize (const luaL_Reg *l) {
+ int size = 0;
+ for (; l->name; l++) size++;
+ return size;
+}
+
+
+LUALIB_API void luaI_openlib (lua_State *L, const char *libname,
+ const luaL_Reg *l, int nup) {
+ if (libname) {
+ int size = libsize(l);
+ /* check whether lib already exists */
+ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", size);
+ lua_getfield(L, -1, libname); /* get _LOADED[libname] */
+ if (!lua_istable(L, -1)) { /* not found? */
+ lua_pop(L, 1); /* remove previous result */
+ /* try global variable (and create one if it does not exist) */
+ if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
+ luaL_error(L, "name conflict for module " LUA_QS, libname);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
+ }
+ lua_remove(L, -2); /* remove _LOADED table */
+ lua_insert(L, -(nup+1)); /* move library table to below upvalues */
+ }
+ for (; l->name; l++) {
+ int i;
+ for (i=0; i<nup; i++) /* copy upvalues to the top */
+ lua_pushvalue(L, -nup);
+ lua_pushcclosure(L, l->func, nup);
+ lua_setfield(L, -(nup+2), l->name);
+ }
+ lua_pop(L, nup); /* remove upvalues */
+}
+
+
+
+/*
+** {======================================================
+** getn-setn: size for arrays
+** =======================================================
+*/
+
+#if defined(LUA_COMPAT_GETN)
+
+static int checkint (lua_State *L, int topop) {
+ int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1;
+ lua_pop(L, topop);
+ return n;
+}
+
+
+static void getsizes (lua_State *L) {
+ lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES");
+ if (lua_isnil(L, -1)) { /* no `size' table? */
+ lua_pop(L, 1); /* remove nil */
+ lua_newtable(L); /* create it */
+ lua_pushvalue(L, -1); /* `size' will be its own metatable */
+ lua_setmetatable(L, -2);
+ lua_pushliteral(L, "kv");
+ lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */
+ lua_pushvalue(L, -1);
+ lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */
+ }
+}
+
+
+LUALIB_API void luaL_setn (lua_State *L, int t, int n) {
+ t = abs_index(L, t);
+ lua_pushliteral(L, "n");
+ lua_rawget(L, t);
+ if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */
+ lua_pushliteral(L, "n"); /* use it */
+ lua_pushinteger(L, n);
+ lua_rawset(L, t);
+ }
+ else { /* use `sizes' */
+ getsizes(L);
+ lua_pushvalue(L, t);
+ lua_pushinteger(L, n);
+ lua_rawset(L, -3); /* sizes[t] = n */
+ lua_pop(L, 1); /* remove `sizes' */
+ }
+}
+
+
+LUALIB_API int luaL_getn (lua_State *L, int t) {
+ int n;
+ t = abs_index(L, t);
+ lua_pushliteral(L, "n"); /* try t.n */
+ lua_rawget(L, t);
+ if ((n = checkint(L, 1)) >= 0) return n;
+ getsizes(L); /* else try sizes[t] */
+ lua_pushvalue(L, t);
+ lua_rawget(L, -2);
+ if ((n = checkint(L, 2)) >= 0) return n;
+ return (int)lua_objlen(L, t);
+}
+
+#endif
+
+/* }====================================================== */
+
+
+
+LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
+ const char *r) {
+ const char *wild;
+ size_t l = strlen(p);
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ while ((wild = strstr(s, p)) != NULL) {
+ luaL_addlstring(&b, s, wild - s); /* push prefix */
+ luaL_addstring(&b, r); /* push replacement in place of pattern */
+ s = wild + l; /* continue after `p' */
+ }
+ luaL_addstring(&b, s); /* push last suffix */
+ luaL_pushresult(&b);
+ return lua_tostring(L, -1);
+}
+
+
+LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
+ const char *fname, int szhint) {
+ const char *e;
+ lua_pushvalue(L, idx);
+ do {
+ e = strchr(fname, '.');
+ if (e == NULL) e = fname + strlen(fname);
+ lua_pushlstring(L, fname, e - fname);
+ lua_rawget(L, -2);
+ if (lua_isnil(L, -1)) { /* no such field? */
+ lua_pop(L, 1); /* remove this nil */
+ lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
+ lua_pushlstring(L, fname, e - fname);
+ lua_pushvalue(L, -2);
+ lua_settable(L, -4); /* set new table into field */
+ }
+ else if (!lua_istable(L, -1)) { /* field has a non-table value? */
+ lua_pop(L, 2); /* remove table and value */
+ return fname; /* return problematic part of the name */
+ }
+ lua_remove(L, -2); /* remove previous table */
+ fname = e + 1;
+ } while (*e == '.');
+ return NULL;
+}
+
+
+
+/*
+** {======================================================
+** Generic Buffer manipulation
+** =======================================================
+*/
+
+
+#define bufflen(B) ((B)->p - (B)->buffer)
+#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
+
+#define LIMIT (LUA_MINSTACK/2)
+
+
+static int emptybuffer (luaL_Buffer *B) {
+ size_t l = bufflen(B);
+ if (l == 0) return 0; /* put nothing on stack */
+ else {
+ lua_pushlstring(B->L, B->buffer, l);
+ B->p = B->buffer;
+ B->lvl++;
+ return 1;
+ }
+}
+
+
+static void adjuststack (luaL_Buffer *B) {
+ if (B->lvl > 1) {
+ lua_State *L = B->L;
+ int toget = 1; /* number of levels to concat */
+ size_t toplen = lua_strlen(L, -1);
+ do {
+ size_t l = lua_strlen(L, -(toget+1));
+ if (B->lvl - toget + 1 >= LIMIT || toplen > l) {
+ toplen += l;
+ toget++;
+ }
+ else break;
+ } while (toget < B->lvl);
+ lua_concat(L, toget);
+ B->lvl = B->lvl - toget + 1;
+ }
+}
+
+
+LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) {
+ if (emptybuffer(B))
+ adjuststack(B);
+ return B->buffer;
+}
+
+
+LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
+ while (l--)
+ luaL_addchar(B, *s++);
+}
+
+
+LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
+ luaL_addlstring(B, s, strlen(s));
+}
+
+
+LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
+ emptybuffer(B);
+ lua_concat(B->L, B->lvl);
+ B->lvl = 1;
+}
+
+
+LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
+ lua_State *L = B->L;
+ size_t vl;
+ const char *s = lua_tolstring(L, -1, &vl);
+ if (vl <= bufffree(B)) { /* fit into buffer? */
+ memcpy(B->p, s, vl); /* put it there */
+ B->p += vl;
+ lua_pop(L, 1); /* remove from stack */
+ }
+ else {
+ if (emptybuffer(B))
+ lua_insert(L, -2); /* put buffer before new value */
+ B->lvl++; /* add new value into B stack */
+ adjuststack(B);
+ }
+}
+
+
+LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
+ B->L = L;
+ B->p = B->buffer;
+ B->lvl = 0;
+}
+
+/* }====================================================== */
+
+
+LUALIB_API int luaL_ref (lua_State *L, int t) {
+ int ref;
+ t = abs_index(L, t);
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1); /* remove from stack */
+ return LUA_REFNIL; /* `nil' has a unique fixed reference */
+ }
+ lua_rawgeti(L, t, FREELIST_REF); /* get first free element */
+ ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */
+ lua_pop(L, 1); /* remove it from stack */
+ if (ref != 0) { /* any free element? */
+ lua_rawgeti(L, t, ref); /* remove it from list */
+ lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */
+ }
+ else { /* no free elements */
+ ref = (int)lua_objlen(L, t);
+ ref++; /* create new reference */
+ }
+ lua_rawseti(L, t, ref);
+ return ref;
+}
+
+
+LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
+ if (ref >= 0) {
+ t = abs_index(L, t);
+ lua_rawgeti(L, t, FREELIST_REF);
+ lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */
+ lua_pushinteger(L, ref);
+ lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */
+ }
+}
+
+
+
+/*
+** {======================================================
+** Load functions
+** =======================================================
+*/
+
+typedef struct LoadF {
+ int extraline;
+ FILE *f;
+ char buff[LUAL_BUFFERSIZE];
+} LoadF;
+
+
+static const char *getF (lua_State *L, void *ud, size_t *size) {
+ LoadF *lf = (LoadF *)ud;
+ (void)L;
+ if (lf->extraline) {
+ lf->extraline = 0;
+ *size = 1;
+ return "\n";
+ }
+ if (feof(lf->f)) return NULL;
+ *size = fread(lf->buff, 1, LUAL_BUFFERSIZE, lf->f);
+ return (*size > 0) ? lf->buff : NULL;
+}
+
+
+static int errfile (lua_State *L, const char *what, int fnameindex) {
+ const char *serr = strerror(errno);
+ const char *filename = lua_tostring(L, fnameindex) + 1;
+ lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
+ lua_remove(L, fnameindex);
+ return LUA_ERRFILE;
+}
+
+
+LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
+ LoadF lf;
+ int status, readstatus;
+ int c;
+ int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
+ lf.extraline = 0;
+ if (filename == NULL) {
+ lua_pushliteral(L, "=stdin");
+ lf.f = stdin;
+ }
+ else {
+ lua_pushfstring(L, "@%s", filename);
+ lf.f = fopen(filename, "r");
+ if (lf.f == NULL) return errfile(L, "open", fnameindex);
+ }
+ c = getc(lf.f);
+ if (c == '#') { /* Unix exec. file? */
+ lf.extraline = 1;
+ while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */
+ if (c == '\n') c = getc(lf.f);
+ }
+ if (c == LUA_SIGNATURE[0] && lf.f != stdin) { /* binary file? */
+ fclose(lf.f);
+ lf.f = fopen(filename, "rb"); /* reopen in binary mode */
+ if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
+ /* skip eventual `#!...' */
+ while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
+ lf.extraline = 0;
+ }
+ ungetc(c, lf.f);
+ status = lua_load(L, getF, &lf, lua_tostring(L, -1));
+ readstatus = ferror(lf.f);
+ if (lf.f != stdin) fclose(lf.f); /* close file (even in case of errors) */
+ if (readstatus) {
+ lua_settop(L, fnameindex); /* ignore results from `lua_load' */
+ return errfile(L, "read", fnameindex);
+ }
+ lua_remove(L, fnameindex);
+ return status;
+}
+
+
+typedef struct LoadS {
+ const char *s;
+ size_t size;
+} LoadS;
+
+
+static const char *getS (lua_State *L, void *ud, size_t *size) {
+ LoadS *ls = (LoadS *)ud;
+ (void)L;
+ if (ls->size == 0) return NULL;
+ *size = ls->size;
+ ls->size = 0;
+ return ls->s;
+}
+
+
+LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
+ const char *name) {
+ LoadS ls;
+ ls.s = buff;
+ ls.size = size;
+ return lua_load(L, getS, &ls, name);
+}
+
+
+LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) {
+ return luaL_loadbuffer(L, s, strlen(s), s);
+}
+
+
+
+/* }====================================================== */
+
+
+static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
+ (void)ud;
+ (void)osize;
+ if (nsize == 0) {
+ free(ptr);
+ return NULL;
+ }
+ else
+ return realloc(ptr, nsize);
+}
+
+
+static int panic (lua_State *L) {
+ (void)L; /* to avoid warnings */
+ fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n",
+ lua_tostring(L, -1));
+ return 0;
+}
+
+
+LUALIB_API lua_State *luaL_newstate (void) {
+ lua_State *L = lua_newstate(l_alloc, NULL);
+ if (L) lua_atpanic(L, &panic);
+ return L;
+}
+
diff --git a/Build/source/libs/lua51/lauxlib.h b/Build/source/libs/lua51/lauxlib.h
new file mode 100644
index 00000000000..1f3430863e4
--- /dev/null
+++ b/Build/source/libs/lua51/lauxlib.h
@@ -0,0 +1,174 @@
+/*
+** $Id: lauxlib.h,v 1.88 2006/04/12 20:31:15 roberto Exp $
+** Auxiliary functions for building Lua libraries
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lauxlib_h
+#define lauxlib_h
+
+
+#include <stddef.h>
+#include <stdio.h>
+
+#include "lua.h"
+
+
+#if defined(LUA_COMPAT_GETN)
+LUALIB_API int (luaL_getn) (lua_State *L, int t);
+LUALIB_API void (luaL_setn) (lua_State *L, int t, int n);
+#else
+#define luaL_getn(L,i) ((int)lua_objlen(L, i))
+#define luaL_setn(L,i,j) ((void)0) /* no op! */
+#endif
+
+#if defined(LUA_COMPAT_OPENLIB)
+#define luaI_openlib luaL_openlib
+#endif
+
+
+/* extra error code for `luaL_load' */
+#define LUA_ERRFILE (LUA_ERRERR+1)
+
+
+typedef struct luaL_Reg {
+ const char *name;
+ lua_CFunction func;
+} luaL_Reg;
+
+
+
+LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname,
+ const luaL_Reg *l, int nup);
+LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
+ const luaL_Reg *l);
+LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
+LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
+LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);
+LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
+LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
+ size_t *l);
+LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
+ const char *def, size_t *l);
+LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
+LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
+
+LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
+LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
+ lua_Integer def);
+
+LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
+LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
+LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
+
+LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
+LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
+
+LUALIB_API void (luaL_where) (lua_State *L, int lvl);
+LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
+
+LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
+ const char *const lst[]);
+
+LUALIB_API int (luaL_ref) (lua_State *L, int t);
+LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
+
+LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
+LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
+ const char *name);
+LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
+
+LUALIB_API lua_State *(luaL_newstate) (void);
+
+
+LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
+ const char *r);
+
+LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
+ const char *fname, int szhint);
+
+
+
+
+/*
+** ===============================================================
+** some useful macros
+** ===============================================================
+*/
+
+#define luaL_argcheck(L, cond,numarg,extramsg) \
+ ((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
+#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
+#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
+#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
+#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
+#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
+#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
+
+#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
+
+#define luaL_dofile(L, fn) \
+ (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
+
+#define luaL_dostring(L, s) \
+ (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
+
+#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
+
+#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
+
+/*
+** {======================================================
+** Generic Buffer manipulation
+** =======================================================
+*/
+
+
+
+typedef struct luaL_Buffer {
+ char *p; /* current position in buffer */
+ int lvl; /* number of strings in the stack (level) */
+ lua_State *L;
+ char buffer[LUAL_BUFFERSIZE];
+} luaL_Buffer;
+
+#define luaL_addchar(B,c) \
+ ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
+ (*(B)->p++ = (char)(c)))
+
+/* compatibility only */
+#define luaL_putchar(B,c) luaL_addchar(B,c)
+
+#define luaL_addsize(B,n) ((B)->p += (n))
+
+LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
+LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);
+LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
+LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
+LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
+LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
+
+
+/* }====================================================== */
+
+
+/* compatibility with ref system */
+
+/* pre-defined references */
+#define LUA_NOREF (-2)
+#define LUA_REFNIL (-1)
+
+#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
+ (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
+
+#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref))
+
+#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))
+
+
+#define luaL_reg luaL_Reg
+
+#endif
+
+
diff --git a/Build/source/libs/lua51/lbaselib.c b/Build/source/libs/lua51/lbaselib.c
new file mode 100644
index 00000000000..a1208d670b4
--- /dev/null
+++ b/Build/source/libs/lua51/lbaselib.c
@@ -0,0 +1,670 @@
+/*
+** $Id: lbaselib.c,v 1.191a 2006/06/02 15:34:00 roberto Exp $
+** Basic library
+** See Copyright Notice in lua.h
+*/
+
+
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lbaselib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+#ifndef COCO_DISABLE
+#include "lcoco.h"
+#endif
+
+
+
+
+/*
+** If your system does not support `stdout', you can just remove this function.
+** If you need, you can define your own `print' function, following this
+** model but changing `fputs' to put the strings at a proper place
+** (a console window or a log file, for instance).
+*/
+static int luaB_print (lua_State *L) {
+ int n = lua_gettop(L); /* number of arguments */
+ int i;
+ lua_getglobal(L, "tostring");
+ for (i=1; i<=n; i++) {
+ const char *s;
+ lua_pushvalue(L, -1); /* function to be called */
+ lua_pushvalue(L, i); /* value to print */
+ lua_call(L, 1, 1);
+ s = lua_tostring(L, -1); /* get result */
+ if (s == NULL)
+ return luaL_error(L, LUA_QL("tostring") " must return a string to "
+ LUA_QL("print"));
+ if (i>1) fputs("\t", stdout);
+ fputs(s, stdout);
+ lua_pop(L, 1); /* pop result */
+ }
+ fputs("\n", stdout);
+ return 0;
+}
+
+
+static int luaB_tonumber (lua_State *L) {
+ int base = luaL_optint(L, 2, 10);
+ if (base == 10) { /* standard conversion */
+ luaL_checkany(L, 1);
+ if (lua_isnumber(L, 1)) {
+ lua_pushnumber(L, lua_tonumber(L, 1));
+ return 1;
+ }
+ }
+ else {
+ const char *s1 = luaL_checkstring(L, 1);
+ char *s2;
+ unsigned long n;
+ luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
+ n = strtoul(s1, &s2, base);
+ if (s1 != s2) { /* at least one valid digit? */
+ while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */
+ if (*s2 == '\0') { /* no invalid trailing characters? */
+ lua_pushnumber(L, (lua_Number)n);
+ return 1;
+ }
+ }
+ }
+ lua_pushnil(L); /* else not a number */
+ return 1;
+}
+
+
+static int luaB_error (lua_State *L) {
+ int level = luaL_optint(L, 2, 1);
+ lua_settop(L, 1);
+ if (lua_isstring(L, 1) && level > 0) { /* add extra information? */
+ luaL_where(L, level);
+ lua_pushvalue(L, 1);
+ lua_concat(L, 2);
+ }
+ return lua_error(L);
+}
+
+
+static int luaB_getmetatable (lua_State *L) {
+ luaL_checkany(L, 1);
+ if (!lua_getmetatable(L, 1)) {
+ lua_pushnil(L);
+ return 1; /* no metatable */
+ }
+ luaL_getmetafield(L, 1, "__metatable");
+ return 1; /* returns either __metatable field (if present) or metatable */
+}
+
+
+static int luaB_setmetatable (lua_State *L) {
+ int t = lua_type(L, 2);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
+ "nil or table expected");
+ if (luaL_getmetafield(L, 1, "__metatable"))
+ luaL_error(L, "cannot change a protected metatable");
+ lua_settop(L, 2);
+ lua_setmetatable(L, 1);
+ return 1;
+}
+
+
+static void getfunc (lua_State *L, int opt) {
+ if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
+ else {
+ lua_Debug ar;
+ int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);
+ luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
+ if (lua_getstack(L, level, &ar) == 0)
+ luaL_argerror(L, 1, "invalid level");
+ lua_getinfo(L, "f", &ar);
+ if (lua_isnil(L, -1))
+ luaL_error(L, "no function environment for tail call at level %d",
+ level);
+ }
+}
+
+
+static int luaB_getfenv (lua_State *L) {
+ getfunc(L, 1);
+ if (lua_iscfunction(L, -1)) /* is a C function? */
+ lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */
+ else
+ lua_getfenv(L, -1);
+ return 1;
+}
+
+
+static int luaB_setfenv (lua_State *L) {
+ luaL_checktype(L, 2, LUA_TTABLE);
+ getfunc(L, 0);
+ lua_pushvalue(L, 2);
+ if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
+ /* change environment of current thread */
+ lua_pushthread(L);
+ lua_insert(L, -2);
+ lua_setfenv(L, -2);
+ return 0;
+ }
+ else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)
+ luaL_error(L,
+ LUA_QL("setfenv") " cannot change environment of given object");
+ return 1;
+}
+
+
+static int luaB_rawequal (lua_State *L) {
+ luaL_checkany(L, 1);
+ luaL_checkany(L, 2);
+ lua_pushboolean(L, lua_rawequal(L, 1, 2));
+ return 1;
+}
+
+
+static int luaB_rawget (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ luaL_checkany(L, 2);
+ lua_settop(L, 2);
+ lua_rawget(L, 1);
+ return 1;
+}
+
+static int luaB_rawset (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ luaL_checkany(L, 2);
+ luaL_checkany(L, 3);
+ lua_settop(L, 3);
+ lua_rawset(L, 1);
+ return 1;
+}
+
+
+static int luaB_gcinfo (lua_State *L) {
+ lua_pushinteger(L, lua_getgccount(L));
+ return 1;
+}
+
+
+static int luaB_collectgarbage (lua_State *L) {
+ static const char *const opts[] = {"stop", "restart", "collect",
+ "count", "step", "setpause", "setstepmul", NULL};
+ static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
+ LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};
+ int o = luaL_checkoption(L, 1, "collect", opts);
+ int ex = luaL_optint(L, 2, 0);
+ int res = lua_gc(L, optsnum[o], ex);
+ switch (optsnum[o]) {
+ case LUA_GCCOUNT: {
+ int b = lua_gc(L, LUA_GCCOUNTB, 0);
+ lua_pushnumber(L, res + ((lua_Number)b/1024));
+ return 1;
+ }
+ case LUA_GCSTEP: {
+ lua_pushboolean(L, res);
+ return 1;
+ }
+ default: {
+ lua_pushnumber(L, res);
+ return 1;
+ }
+ }
+}
+
+
+static int luaB_type (lua_State *L) {
+ luaL_checkany(L, 1);
+ lua_pushstring(L, luaL_typename(L, 1));
+ return 1;
+}
+
+
+static int luaB_next (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_settop(L, 2); /* create a 2nd argument if there isn't one */
+ if (lua_next(L, 1))
+ return 2;
+ else {
+ lua_pushnil(L);
+ return 1;
+ }
+}
+
+
+static int luaB_pairs (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
+ lua_pushvalue(L, 1); /* state, */
+ lua_pushnil(L); /* and initial value */
+ return 3;
+}
+
+
+static int ipairsaux (lua_State *L) {
+ int i = luaL_checkint(L, 2);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ i++; /* next value */
+ lua_pushinteger(L, i);
+ lua_rawgeti(L, 1, i);
+ return (lua_isnil(L, -1)) ? 0 : 2;
+}
+
+
+static int luaB_ipairs (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
+ lua_pushvalue(L, 1); /* state, */
+ lua_pushinteger(L, 0); /* and initial value */
+ return 3;
+}
+
+
+static int load_aux (lua_State *L, int status) {
+ if (status == 0) /* OK? */
+ return 1;
+ else {
+ lua_pushnil(L);
+ lua_insert(L, -2); /* put before error message */
+ return 2; /* return nil plus error message */
+ }
+}
+
+
+static int luaB_loadstring (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+ const char *chunkname = luaL_optstring(L, 2, s);
+ return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
+}
+
+
+static int luaB_loadfile (lua_State *L) {
+ const char *fname = luaL_optstring(L, 1, NULL);
+ return load_aux(L, luaL_loadfile(L, fname));
+}
+
+
+/*
+** Reader for generic `load' function: `lua_load' uses the
+** stack for internal stuff, so the reader cannot change the
+** stack top. Instead, it keeps its resulting string in a
+** reserved slot inside the stack.
+*/
+static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
+ (void)ud; /* to avoid warnings */
+ luaL_checkstack(L, 2, "too many nested functions");
+ lua_pushvalue(L, 1); /* get function */
+ lua_call(L, 0, 1); /* call it */
+ if (lua_isnil(L, -1)) {
+ *size = 0;
+ return NULL;
+ }
+ else if (lua_isstring(L, -1)) {
+ lua_replace(L, 3); /* save string in a reserved stack slot */
+ return lua_tolstring(L, 3, size);
+ }
+ else luaL_error(L, "reader function must return a string");
+ return NULL; /* to avoid warnings */
+}
+
+
+static int luaB_load (lua_State *L) {
+ int status;
+ const char *cname = luaL_optstring(L, 2, "=(load)");
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ lua_settop(L, 3); /* function, eventual name, plus one reserved slot */
+ status = lua_load(L, generic_reader, NULL, cname);
+ return load_aux(L, status);
+}
+
+
+static int luaB_dofile (lua_State *L) {
+ const char *fname = luaL_optstring(L, 1, NULL);
+ int n = lua_gettop(L);
+ if (luaL_loadfile(L, fname) != 0) lua_error(L);
+ lua_call(L, 0, LUA_MULTRET);
+ return lua_gettop(L) - n;
+}
+
+
+static int luaB_assert (lua_State *L) {
+ luaL_checkany(L, 1);
+ if (!lua_toboolean(L, 1))
+ return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
+ return lua_gettop(L);
+}
+
+
+static int luaB_unpack (lua_State *L) {
+ int i, e, n;
+ luaL_checktype(L, 1, LUA_TTABLE);
+ i = luaL_optint(L, 2, 1);
+ e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
+ n = e - i + 1; /* number of elements */
+ if (n <= 0) return 0; /* empty range */
+ luaL_checkstack(L, n, "table too big to unpack");
+ for (; i<=e; i++) /* push arg[i...e] */
+ lua_rawgeti(L, 1, i);
+ return n;
+}
+
+
+static int luaB_select (lua_State *L) {
+ int n = lua_gettop(L);
+ if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
+ lua_pushinteger(L, n-1);
+ return 1;
+ }
+ else {
+ int i = luaL_checkint(L, 1);
+ if (i < 0) i = n + i;
+ else if (i > n) i = n;
+ luaL_argcheck(L, 1 <= i, 1, "index out of range");
+ return n - i;
+ }
+}
+
+
+static int luaB_pcall (lua_State *L) {
+ int status;
+ luaL_checkany(L, 1);
+ status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
+ lua_pushboolean(L, (status == 0));
+ lua_insert(L, 1);
+ return lua_gettop(L); /* return status + all results */
+}
+
+
+static int luaB_xpcall (lua_State *L) {
+ int status;
+ luaL_checkany(L, 2);
+ lua_settop(L, 2);
+ lua_insert(L, 1); /* put error function under function to be called */
+ status = lua_pcall(L, 0, LUA_MULTRET, 1);
+ lua_pushboolean(L, (status == 0));
+ lua_replace(L, 1);
+ return lua_gettop(L); /* return status + all results */
+}
+
+
+static int luaB_tostring (lua_State *L) {
+ luaL_checkany(L, 1);
+ if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */
+ return 1; /* use its value */
+ switch (lua_type(L, 1)) {
+ case LUA_TNUMBER:
+ lua_pushstring(L, lua_tostring(L, 1));
+ break;
+ case LUA_TSTRING:
+ lua_pushvalue(L, 1);
+ break;
+ case LUA_TBOOLEAN:
+ lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
+ break;
+ case LUA_TNIL:
+ lua_pushliteral(L, "nil");
+ break;
+ default:
+ lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1));
+ break;
+ }
+ return 1;
+}
+
+
+static int luaB_newproxy (lua_State *L) {
+ lua_settop(L, 1);
+ lua_newuserdata(L, 0); /* create proxy */
+ if (lua_toboolean(L, 1) == 0)
+ return 1; /* no metatable */
+ else if (lua_isboolean(L, 1)) {
+ lua_newtable(L); /* create a new metatable `m' ... */
+ lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */
+ lua_pushboolean(L, 1);
+ lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */
+ }
+ else {
+ int validproxy = 0; /* to check if weaktable[metatable(u)] == true */
+ if (lua_getmetatable(L, 1)) {
+ lua_rawget(L, lua_upvalueindex(1));
+ validproxy = lua_toboolean(L, -1);
+ lua_pop(L, 1); /* remove value */
+ }
+ luaL_argcheck(L, validproxy, 1, "boolean or proxy expected");
+ lua_getmetatable(L, 1); /* metatable is valid; get it */
+ }
+ lua_setmetatable(L, 2);
+ return 1;
+}
+
+
+static const luaL_Reg base_funcs[] = {
+ {"assert", luaB_assert},
+ {"collectgarbage", luaB_collectgarbage},
+ {"dofile", luaB_dofile},
+ {"error", luaB_error},
+ {"gcinfo", luaB_gcinfo},
+ {"getfenv", luaB_getfenv},
+ {"getmetatable", luaB_getmetatable},
+ {"loadfile", luaB_loadfile},
+ {"load", luaB_load},
+ {"loadstring", luaB_loadstring},
+ {"next", luaB_next},
+ {"pcall", luaB_pcall},
+ {"print", luaB_print},
+ {"rawequal", luaB_rawequal},
+ {"rawget", luaB_rawget},
+ {"rawset", luaB_rawset},
+ {"select", luaB_select},
+ {"setfenv", luaB_setfenv},
+ {"setmetatable", luaB_setmetatable},
+ {"tonumber", luaB_tonumber},
+ {"tostring", luaB_tostring},
+ {"type", luaB_type},
+ {"unpack", luaB_unpack},
+ {"xpcall", luaB_xpcall},
+ {NULL, NULL}
+};
+
+
+/*
+** {======================================================
+** Coroutine library
+** =======================================================
+*/
+
+static int auxresume (lua_State *L, lua_State *co, int narg) {
+ int status;
+ if (!lua_checkstack(co, narg))
+ luaL_error(L, "too many arguments to resume");
+ if (lua_status(co) == 0 && lua_gettop(co) == 0) {
+ lua_pushliteral(L, "cannot resume dead coroutine");
+ return -1; /* error flag */
+ }
+ lua_xmove(L, co, narg);
+ status = lua_resume(co, narg);
+ if (status == 0 || status == LUA_YIELD) {
+ int nres = lua_gettop(co);
+ if (!lua_checkstack(L, nres))
+ luaL_error(L, "too many results to resume");
+ lua_xmove(co, L, nres); /* move yielded values */
+ return nres;
+ }
+ else {
+ lua_xmove(co, L, 1); /* move error message */
+ return -1; /* error flag */
+ }
+}
+
+
+static int luaB_coresume (lua_State *L) {
+ lua_State *co = lua_tothread(L, 1);
+ int r;
+ luaL_argcheck(L, co, 1, "coroutine expected");
+ r = auxresume(L, co, lua_gettop(L) - 1);
+ if (r < 0) {
+ lua_pushboolean(L, 0);
+ lua_insert(L, -2);
+ return 2; /* return false + error message */
+ }
+ else {
+ lua_pushboolean(L, 1);
+ lua_insert(L, -(r + 1));
+ return r + 1; /* return true + `resume' returns */
+ }
+}
+
+
+static int luaB_auxwrap (lua_State *L) {
+ lua_State *co = lua_tothread(L, lua_upvalueindex(1));
+ int r = auxresume(L, co, lua_gettop(L));
+ if (r < 0) {
+ if (lua_isstring(L, -1)) { /* error object is a string? */
+ luaL_where(L, 1); /* add extra info */
+ lua_insert(L, -2);
+ lua_concat(L, 2);
+ }
+ lua_error(L); /* propagate error */
+ }
+ return r;
+}
+
+
+#ifndef COCO_DISABLE
+static int luaB_cstacksize (lua_State *L)
+{
+ lua_pushinteger(L, luaCOCO_cstacksize(luaL_optint(L, 1, -1)));
+ return 1;
+}
+#endif
+
+
+static int luaB_cocreate (lua_State *L) {
+#ifdef COCO_DISABLE
+ lua_State *NL = lua_newthread(L);
+ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
+ "Lua function expected");
+#else
+ int cstacksize = luaL_optint(L, 2, 0);
+ lua_State *NL = lua_newcthread(L, cstacksize);
+ luaL_argcheck(L, lua_isfunction(L, 1) &&
+ (cstacksize >= 0 ? 1 : !lua_iscfunction(L, 1)),
+ 1, "Lua function expected");
+#endif
+ lua_pushvalue(L, 1); /* move function to top */
+ lua_xmove(L, NL, 1); /* move function from L to NL */
+ return 1;
+}
+
+
+static int luaB_cowrap (lua_State *L) {
+ luaB_cocreate(L);
+ lua_pushcclosure(L, luaB_auxwrap, 1);
+ return 1;
+}
+
+
+static int luaB_yield (lua_State *L) {
+ return lua_yield(L, lua_gettop(L));
+}
+
+
+static int luaB_costatus (lua_State *L) {
+ lua_State *co = lua_tothread(L, 1);
+ luaL_argcheck(L, co, 1, "coroutine expected");
+ if (L == co) lua_pushliteral(L, "running");
+ else {
+ switch (lua_status(co)) {
+ case LUA_YIELD:
+ lua_pushliteral(L, "suspended");
+ break;
+ case 0: {
+ lua_Debug ar;
+ if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */
+ lua_pushliteral(L, "normal"); /* it is running */
+ else if (lua_gettop(co) == 0)
+ lua_pushliteral(L, "dead");
+ else
+ lua_pushliteral(L, "suspended"); /* initial state */
+ break;
+ }
+ default: /* some error occured */
+ lua_pushliteral(L, "dead");
+ break;
+ }
+ }
+ return 1;
+}
+
+
+static int luaB_corunning (lua_State *L) {
+ if (lua_pushthread(L))
+ return 0; /* main thread is not a coroutine */
+ else
+ return 1;
+}
+
+
+static const luaL_Reg co_funcs[] = {
+ {"create", luaB_cocreate},
+ {"resume", luaB_coresume},
+ {"running", luaB_corunning},
+ {"status", luaB_costatus},
+ {"wrap", luaB_cowrap},
+ {"yield", luaB_yield},
+#ifndef COCO_DISABLE
+ {"cstacksize", luaB_cstacksize},
+#endif
+ {NULL, NULL}
+};
+
+/* }====================================================== */
+
+
+static void auxopen (lua_State *L, const char *name,
+ lua_CFunction f, lua_CFunction u) {
+ lua_pushcfunction(L, u);
+ lua_pushcclosure(L, f, 1);
+ lua_setfield(L, -2, name);
+}
+
+
+static void base_open (lua_State *L) {
+ /* set global _G */
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ lua_setglobal(L, "_G");
+ /* open lib into global table */
+ luaL_register(L, "_G", base_funcs);
+ lua_pushliteral(L, LUA_VERSION);
+ lua_setglobal(L, "_VERSION"); /* set global _VERSION */
+ /* `ipairs' and `pairs' need auxliliary functions as upvalues */
+ auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
+ auxopen(L, "pairs", luaB_pairs, luaB_next);
+ /* `newproxy' needs a weaktable as upvalue */
+ lua_createtable(L, 0, 1); /* new table `w' */
+ lua_pushvalue(L, -1); /* `w' will be its own metatable */
+ lua_setmetatable(L, -2);
+ lua_pushliteral(L, "kv");
+ lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */
+ lua_pushcclosure(L, luaB_newproxy, 1);
+ lua_setglobal(L, "newproxy"); /* set global `newproxy' */
+}
+
+
+LUALIB_API int luaopen_base (lua_State *L) {
+ base_open(L);
+ luaL_register(L, LUA_COLIBNAME, co_funcs);
+#ifndef COCO_DISABLE
+ lua_pushboolean(L, 1);
+ lua_setfield(L, -2, "coco");
+#endif
+ return 2;
+}
+
diff --git a/Build/source/libs/lua51/lcoco.c b/Build/source/libs/lua51/lcoco.c
new file mode 100644
index 00000000000..87b8c6ce503
--- /dev/null
+++ b/Build/source/libs/lua51/lcoco.c
@@ -0,0 +1,522 @@
+/*
+** Copyright (C) 2004-2007 Mike Pall. All rights reserved.
+**
+** Permission is hereby granted, free of charge, to any person obtaining
+** a copy of this software and associated documentation files (the
+** "Software"), to deal in the Software without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Software, and to
+** permit persons to whom the Software is furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be
+** included in all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**
+** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
+*/
+
+/* Coco -- True C coroutines for Lua. http://luajit.org/coco.html */
+#ifndef COCO_DISABLE
+
+#define lcoco_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lobject.h"
+#include "lstate.h"
+#include "ldo.h"
+#include "lvm.h"
+#include "lgc.h"
+
+
+/*
+** Define this if you want to run Coco with valgrind. You will get random
+** errors about accessing memory from newly allocated C stacks if you don't.
+** You need at least valgrind 3.0 for this to work.
+**
+** This macro evaluates to a no-op if not run with valgrind. I.e. you can
+** use the same binary for regular runs, too (without a performance loss).
+*/
+#ifdef USE_VALGRIND
+#include <valgrind/valgrind.h>
+#define STACK_REG(coco, p, sz) (coco)->vgid = VALGRIND_STACK_REGISTER(p, p+sz);
+#define STACK_DEREG(coco) VALGRIND_STACK_DEREGISTER((coco)->vgid);
+#define STACK_VGID unsigned int vgid;
+#else
+#define STACK_REG(coco, p, sz)
+#define STACK_DEREG(id)
+#define STACK_VGID
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+/* Use Windows Fibers. */
+#if defined(COCO_USE_FIBERS)
+
+#define _WIN32_WINNT 0x0400
+#include <windows.h>
+
+#define COCO_MAIN_DECL CALLBACK
+
+typedef LPFIBER_START_ROUTINE coco_MainFunc;
+
+#define COCO_NEW(OL, NL, cstacksize, mainfunc) \
+ if ((L2COCO(NL)->fib = CreateFiber(cstacksize, mainfunc, NL)) == NULL) \
+ luaD_throw(OL, LUA_ERRMEM);
+
+#define COCO_FREE(L) \
+ DeleteFiber(L2COCO(L)->fib); \
+ L2COCO(L)->fib = NULL;
+
+/* See: http://blogs.msdn.com/oldnewthing/archive/2004/12/31/344799.aspx */
+#define COCO_JUMPIN(coco) \
+ { void *cur = GetCurrentFiber(); \
+ coco->back = (cur == NULL || cur == (void *)0x1e00) ? \
+ ConvertThreadToFiber(NULL) : cur; } \
+ SwitchToFiber(coco->fib);
+
+#define COCO_JUMPOUT(coco) \
+ SwitchToFiber(coco->back);
+
+/* CreateFiber() defaults to STACKSIZE from the Windows module .def file. */
+#define COCO_DEFAULT_CSTACKSIZE 0
+
+/* ------------------------------------------------------------------------ */
+
+#else /* !COCO_USE_FIBERS */
+
+#ifndef COCO_USE_UCONTEXT
+
+/* Try inline asm first. */
+#if __GNUC__ >= 3 && !defined(COCO_USE_SETJMP)
+
+#if defined(__i386) || defined(__i386__)
+
+#ifdef __PIC__
+typedef void *coco_ctx[4]; /* eip, esp, ebp, ebx */
+static inline void coco_switch(coco_ctx from, coco_ctx to)
+{
+ __asm__ __volatile__ (
+ "call 1f\n" "1:\tpopl %%eax\n\t" "addl $(2f-1b),%%eax\n\t"
+ "movl %%eax, (%0)\n\t" "movl %%esp, 4(%0)\n\t"
+ "movl %%ebp, 8(%0)\n\t" "movl %%ebx, 12(%0)\n\t"
+ "movl 12(%1), %%ebx\n\t" "movl 8(%1), %%ebp\n\t"
+ "movl 4(%1), %%esp\n\t" "jmp *(%1)\n" "2:\n"
+ : "+S" (from), "+D" (to) : : "eax", "ecx", "edx", "memory", "cc");
+}
+#else
+typedef void *coco_ctx[3]; /* eip, esp, ebp */
+static inline void coco_switch(coco_ctx from, coco_ctx to)
+{
+ __asm__ __volatile__ (
+ "movl $1f, (%0)\n\t" "movl %%esp, 4(%0)\n\t" "movl %%ebp, 8(%0)\n\t"
+ "movl 8(%1), %%ebp\n\t" "movl 4(%1), %%esp\n\t" "jmp *(%1)\n" "1:\n"
+ : "+S" (from), "+D" (to) : : "eax", "ebx", "ecx", "edx", "memory", "cc");
+}
+#endif
+
+#define COCO_CTX coco_ctx
+#define COCO_SWITCH(from, to) coco_switch(from, to);
+#define COCO_MAKECTX(coco, buf, func, stack, a0) \
+ buf[0] = (void *)(func); \
+ buf[1] = (void *)(stack); \
+ buf[2] = (void *)0; \
+ stack[0] = 0xdeadc0c0; /* Dummy return address. */ \
+ coco->arg0 = (size_t)(a0);
+#define COCO_STATE_HEAD size_t arg0;
+
+#elif __mips && _MIPS_SIM == _MIPS_SIM_ABI32 && !defined(__mips_eabi)
+
+/* No way to avoid the function prologue with inline assembler. So use this: */
+static const unsigned int coco_switch[] = {
+#ifdef __mips_soft_float
+#define COCO_STACKSAVE -10
+ 0x27bdffd8, /* addiu sp, sp, -(10*4) */
+#else
+#define COCO_STACKSAVE -22
+ 0x27bdffa8, /* addiu sp, sp, -(10*4+6*8) */
+ /* sdc1 {$f20-$f30}, offset(sp) */
+ 0xf7be0050, 0xf7bc0048, 0xf7ba0040, 0xf7b80038, 0xf7b60030, 0xf7b40028,
+#endif
+ /* sw {gp,s0-s8}, offset(sp) */
+ 0xafbe0024, 0xafb70020, 0xafb6001c, 0xafb50018, 0xafb40014, 0xafb30010,
+ 0xafb2000c, 0xafb10008, 0xafb00004, 0xafbc0000,
+ /* sw sp, 4(a0); sw ra, 0(a0); lw ra, 0(a1); lw sp, 4(a1); move t9, ra */
+ 0xac9d0004, 0xac9f0000, 0x8cbf0000, 0x8cbd0004, 0x03e0c821,
+ /* lw caller-saved-reg, offset(sp) */
+ 0x8fbe0024, 0x8fb70020, 0x8fb6001c, 0x8fb50018, 0x8fb40014, 0x8fb30010,
+ 0x8fb2000c, 0x8fb10008, 0x8fb00004, 0x8fbc0000,
+#ifdef __mips_soft_float
+ 0x03e00008, 0x27bd0028 /* jr ra; addiu sp, sp, 10*4 */
+#else
+ /* ldc1 {$f20-$f30}, offset(sp) */
+ 0xd7be0050, 0xd7bc0048, 0xd7ba0040, 0xd7b80038, 0xd7b60030, 0xd7b40028,
+ 0x03e00008, 0x27bd0058 /* jr ra; addiu sp, sp, 10*4+6*8 */
+#endif
+};
+
+typedef void *coco_ctx[2]; /* ra, sp */
+#define COCO_CTX coco_ctx
+#define COCO_SWITCH(from, to) \
+ ((void (*)(coco_ctx, coco_ctx))coco_switch)(from, to);
+#define COCO_MAKECTX(coco, buf, func, stack, a0) \
+ buf[0] = (void *)(func); \
+ buf[1] = (void *)&stack[COCO_STACKSAVE]; \
+ stack[4] = (size_t)(a0); /* Assumes o32 ABI. */
+#define COCO_STACKADJUST 8
+#define COCO_MAIN_PARAM int _a, int _b, int _c, int _d, lua_State *L
+
+#endif /* arch check */
+
+#endif /* !(__GNUC__ >= 3 && !defined(COCO_USE_SETJMP)) */
+
+/* Try _setjmp/_longjmp with a patched jump buffer. */
+#ifndef COCO_MAKECTX
+#include <setjmp.h>
+
+/* Check for supported CPU+OS combinations. */
+#if defined(__i386) || defined(__i386__)
+
+#define COCO_STATE_HEAD size_t arg0;
+#define COCO_SETJMP_X86(coco, stack, a0) \
+ stack[COCO_STACKADJUST-1] = 0xdeadc0c0; /* Dummy return address. */ \
+ coco->arg0 = (size_t)(a0);
+
+#if __GLIBC__ == 2 && defined(JB_SP) /* x86-linux-glibc2 */
+#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
+ buf->__jmpbuf[JB_PC] = (int)(func); \
+ buf->__jmpbuf[JB_SP] = (int)(stack); \
+ buf->__jmpbuf[JB_BP] = 0; \
+ COCO_SETJMP_X86(coco, stack, a0)
+#elif defined(__linux__) && defined(_I386_JMP_BUF_H) /* x86-linux-libc5 */
+#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
+ buf->__pc = (func); \
+ buf->__sp = (stack); \
+ buf->__bp = NULL; \
+ COCO_SETJMP_X86(coco, stack, a0)
+#elif defined(__FreeBSD__) /* x86-FreeBSD */
+#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
+ buf->_jb[0] = (long)(func); \
+ buf->_jb[2] = (long)(stack); \
+ buf->_jb[3] = 0; /* ebp */ \
+ COCO_SETJMP_X86(coco, stack, a0)
+#define COCO_STACKADJUST 2
+#elif defined(__NetBSD__) || defined(__OpenBSD__) /* x86-NetBSD, x86-OpenBSD */
+#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
+ buf[0] = (long)(func); \
+ buf[2] = (long)(stack); \
+ buf[3] = 0; /* ebp */ \
+ COCO_SETJMP_X86(coco, stack, a0)
+#define COCO_STACKADJUST 2
+#elif defined(__solaris__) && _JBLEN == 10 /* x86-solaris */
+#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
+ buf[5] = (int)(func); \
+ buf[4] = (int)(stack); \
+ buf[3] = 0; \
+ COCO_SETJMP_X86(coco, stack, a0)
+#elif defined(__MACH__) && defined(_BSD_I386_SETJMP_H_) /* x86-macosx */
+#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
+ buf[12] = (int)(func); \
+ buf[9] = (int)(stack); \
+ buf[8] = 0; /* ebp */ \
+ COCO_SETJMP_X86(coco, stack, a0)
+#endif
+
+#elif defined(__x86_64__) || defined(__x86_64)
+
+#define COCO_STATE_HEAD size_t arg0;
+
+#define COCO_MAIN_PARAM \
+ int _a, int _b, int _c, int _d, int _e, int _f, lua_State *L
+
+#if __GLIBC__ == 2 && defined(JB_RSP) /* x64-linux-glibc2 */
+#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
+ buf->__jmpbuf[JB_PC] = (long)(func); \
+ buf->__jmpbuf[JB_RSP] = (long)(stack); \
+ buf->__jmpbuf[JB_RBP] = 0; \
+ stack[0] = 0xdeadc0c0; /* Dummy return address. */ \
+ coco->arg0 = (size_t)(a0);
+#elif defined(__solaris__) && _JBLEN == 8 /* x64-solaris */
+#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
+ buf[7] = (long)(func); \
+ buf[6] = (long)(stack); \
+ buf[5] = 0; \
+ stack[0] = 0xdeadc0c0; /* Dummy return address. */ \
+ coco->arg0 = (size_t)(a0);
+#endif
+
+#elif defined(PPC) || defined(__ppc__) || defined(__PPC__) || \
+ defined(__powerpc__) || defined(__POWERPC__) || defined(_ARCH_PPC)
+
+#define COCO_STACKADJUST 16
+#define COCO_MAIN_PARAM \
+ int _a, int _b, int _c, int _d, int _e, int _f, int _g, int _h, lua_State *L
+
+#if defined(__MACH__) && defined(_BSD_PPC_SETJMP_H_) /* ppc32-macosx */
+#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
+ buf[21] = (int)(func); \
+ buf[0] = (int)(stack); \
+ stack[6+8] = (size_t)(a0);
+#endif
+
+#elif (defined(MIPS) || defined(MIPSEL) || defined(__mips)) && \
+ _MIPS_SIM == _MIPS_SIM_ABI32 && !defined(__mips_eabi)
+
+/* Stack layout for o32 ABI. */
+#define COCO_STACKADJUST 8
+#define COCO_MAIN_PARAM int _a, int _b, int _c, int _d, lua_State *L
+
+#if __GLIBC__ == 2 || defined(__UCLIBC__) /* mips32-linux-glibc2 */
+#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
+ buf->__jmpbuf->__pc = (func); /* = t9 in _longjmp. Reqd. for -mabicalls. */ \
+ buf->__jmpbuf->__sp = (stack); \
+ buf->__jmpbuf->__fp = (void *)0; \
+ stack[4] = (size_t)(a0);
+#endif
+
+#elif defined(__arm__) || defined(__ARM__)
+
+#if __GLIBC__ == 2 || defined(__UCLIBC__) /* arm-linux-glibc2 */
+#ifndef __JMP_BUF_SP
+#define __JMP_BUF_SP ((sizeof(__jmp_buf)/sizeof(int))-2)
+#endif
+#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
+ buf->__jmpbuf[__JMP_BUF_SP+1] = (int)(func); /* pc */ \
+ buf->__jmpbuf[__JMP_BUF_SP] = (int)(stack); /* sp */ \
+ buf->__jmpbuf[__JMP_BUF_SP-1] = 0; /* fp */ \
+ stack[0] = (size_t)(a0);
+#define COCO_STACKADJUST 2
+#define COCO_MAIN_PARAM int _a, int _b, int _c, int _d, lua_State *L
+#endif
+
+#endif /* arch check */
+
+#ifdef COCO_PATCHCTX
+#define COCO_CTX jmp_buf
+#define COCO_MAKECTX(coco, buf, func, stack, a0) \
+ _setjmp(buf); COCO_PATCHCTX(coco, buf, func, stack, a0)
+#define COCO_SWITCH(from, to) if (!_setjmp(from)) _longjmp(to, 1);
+#endif
+
+#endif /* !defined(COCO_MAKECTX) */
+
+#endif /* !defined(COCO_USE_UCONTEXT) */
+
+/* ------------------------------------------------------------------------ */
+
+/* Use inline asm or _setjmp/_longjmp if available. */
+#ifdef COCO_MAKECTX
+
+#ifndef COCO_STACKADJUST
+#define COCO_STACKADJUST 1
+#endif
+
+#define COCO_FILL(coco, NL, mainfunc) \
+{ /* Include the return address to get proper stack alignment. */ \
+ size_t *stackptr = &((size_t *)coco)[-COCO_STACKADJUST]; \
+ COCO_MAKECTX(coco, coco->ctx, mainfunc, stackptr, NL) \
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* Else fallback to ucontext. Slower, because it saves/restores signals. */
+#else /* !defined(COCO_MAKECTX) */
+
+#include <ucontext.h>
+
+#define COCO_CTX ucontext_t
+
+/* Ugly workaround for makecontext() deficiencies on 64 bit CPUs. */
+/* Note that WIN64 (which is LLP64) never comes here. See above. */
+#if defined(__LP64__) || defined(_LP64) || INT_MAX != LONG_MAX
+/* 64 bit CPU: split the pointer into two 32 bit ints. */
+#define COCO_MAIN_PARAM unsigned int lo, unsigned int hi
+#define COCO_MAIN_GETL \
+ lua_State *L = (lua_State *)((((unsigned long)hi)<<32)+(unsigned long)lo);
+#define COCO_MAKECTX(coco, NL, mainfunc) \
+ makecontext(&coco->ctx, mainfunc, 2, \
+ (int)(ptrdiff_t)NL, (int)((ptrdiff_t)NL>>32));
+#else
+/* 32 bit CPU: a pointer fits into an int. */
+#define COCO_MAKECTX(coco, NL, mainfunc) \
+ makecontext(&coco->ctx, mainfunc, 1, (int)NL);
+#endif
+
+#define COCO_FILL(coco, NL, mainfunc) \
+ getcontext(&coco->ctx); \
+ coco->ctx.uc_link = NULL; /* We never exit from coco_main. */ \
+ coco->ctx.uc_stack.ss_sp = coco->allocptr; \
+ coco->ctx.uc_stack.ss_size = (char *)coco - (char *)(coco->allocptr); \
+ COCO_MAKECTX(coco, NL, mainfunc)
+
+#define COCO_SWITCH(from, to) swapcontext(&(from), &(to));
+
+#endif /* !defined(COCO_MAKECTX) */
+
+
+/* Common code for inline asm/setjmp/ucontext to allocate/free the stack. */
+
+struct coco_State {
+#ifdef COCO_STATE_HEAD
+ COCO_STATE_HEAD
+#endif
+ COCO_CTX ctx; /* Own context. */
+ COCO_CTX back; /* Context to switch back to. */
+ void *allocptr; /* Pointer to allocated memory. */
+ int allocsize; /* Size of allocated memory. */
+ int nargs; /* Number of arguments to pass. */
+ STACK_VGID /* Optional valgrind stack id. See above. */
+};
+
+typedef void (*coco_MainFunc)(void);
+
+/* Put the Coco state at the end and align it downwards. */
+#define ALIGNED_END(p, s, t) \
+ ((t *)(((char *)0) + ((((char *)(p)-(char *)0)+(s)-sizeof(t)) & -16)))
+
+/* TODO: use mmap. */
+#define COCO_NEW(OL, NL, cstacksize, mainfunc) \
+{ \
+ void *ptr = luaM_malloc(OL, cstacksize); \
+ coco_State *coco = ALIGNED_END(ptr, cstacksize, coco_State); \
+ STACK_REG(coco, ptr, cstacksize) \
+ coco->allocptr = ptr; \
+ coco->allocsize = cstacksize; \
+ COCO_FILL(coco, NL, mainfunc) \
+ L2COCO(NL) = coco; \
+}
+
+#define COCO_FREE(L) \
+ STACK_DEREG(L2COCO(L)) \
+ luaM_freemem(L, L2COCO(L)->allocptr, L2COCO(L)->allocsize); \
+ L2COCO(L) = NULL;
+
+#define COCO_JUMPIN(coco) COCO_SWITCH(coco->back, coco->ctx)
+#define COCO_JUMPOUT(coco) COCO_SWITCH(coco->ctx, coco->back)
+
+#endif /* !COCO_USE_FIBERS */
+
+/* ------------------------------------------------------------------------ */
+
+#ifndef COCO_MIN_CSTACKSIZE
+#define COCO_MIN_CSTACKSIZE (32768+4096)
+#endif
+
+/* Don't use multiples of 64K to avoid D-cache aliasing conflicts. */
+#ifndef COCO_DEFAULT_CSTACKSIZE
+#define COCO_DEFAULT_CSTACKSIZE (65536-4096)
+#endif
+
+static int defaultcstacksize = COCO_DEFAULT_CSTACKSIZE;
+
+/* Start the Lua or C function. */
+static void coco_start(lua_State *L, void *ud)
+{
+ if (luaD_precall(L, (StkId)ud, LUA_MULTRET) == PCRLUA)
+ luaV_execute(L, L->ci - L->base_ci);
+}
+
+#ifndef COCO_MAIN_PARAM
+#define COCO_MAIN_PARAM lua_State *L
+#endif
+
+#ifndef COCO_MAIN_DECL
+#define COCO_MAIN_DECL
+#endif
+
+/* Toplevel function for the new coroutine stack. Never exits. */
+static void COCO_MAIN_DECL coco_main(COCO_MAIN_PARAM)
+{
+#ifdef COCO_MAIN_GETL
+ COCO_MAIN_GETL
+#endif
+ coco_State *coco = L2COCO(L);
+ for (;;) {
+ L->status = luaD_rawrunprotected(L, coco_start, L->top - (coco->nargs+1));
+ if (L->status != 0) luaD_seterrorobj(L, L->status, L->top);
+ COCO_JUMPOUT(coco)
+ }
+}
+
+/* Add a C stack to a coroutine. */
+lua_State *lua_newcthread(lua_State *OL, int cstacksize)
+{
+ lua_State *NL = lua_newthread(OL);
+
+ if (cstacksize < 0)
+ return NL;
+ if (cstacksize == 0)
+ cstacksize = defaultcstacksize;
+ else if (cstacksize < COCO_MIN_CSTACKSIZE)
+ cstacksize = COCO_MIN_CSTACKSIZE;
+ cstacksize &= -16;
+
+ COCO_NEW(OL, NL, cstacksize, ((coco_MainFunc)(coco_main)))
+
+ return NL;
+}
+
+/* Free the C stack of a coroutine. Called from lstate.c. */
+void luaCOCO_free(lua_State *L)
+{
+ COCO_FREE(L)
+}
+
+/* Resume a coroutine with a C stack. Called from ldo.c. */
+int luaCOCO_resume(lua_State *L, int nargs)
+{
+ coco_State *coco = L2COCO(L);
+ coco->nargs = nargs;
+ COCO_JUMPIN(coco)
+#ifndef COCO_DISABLE_EARLY_FREE
+ if (L->status != LUA_YIELD) {
+ COCO_FREE(L)
+ }
+#endif
+ return L->status;
+}
+
+/* Yield from a coroutine with a C stack. Called from ldo.c. */
+int luaCOCO_yield(lua_State *L)
+{
+ coco_State *coco = L2COCO(L);
+ L->status = LUA_YIELD;
+ COCO_JUMPOUT(coco)
+ L->status = 0;
+ {
+ StkId base = L->top - coco->nargs;
+ StkId rbase = L->base;
+ if (rbase < base) { /* Need to move args down? */
+ while (base < L->top)
+ setobjs2s(L, rbase++, base++);
+ L->top = rbase;
+ }
+ }
+ L->base = L->ci->base; /* Restore invariant. */
+ return coco->nargs;
+}
+
+/* Get/set the default C stack size. */
+int luaCOCO_cstacksize(int cstacksize)
+{
+ int oldsz = defaultcstacksize;
+ if (cstacksize >= 0) {
+ if (cstacksize == 0)
+ cstacksize = COCO_DEFAULT_CSTACKSIZE;
+ else if (cstacksize < COCO_MIN_CSTACKSIZE)
+ cstacksize = COCO_MIN_CSTACKSIZE;
+ defaultcstacksize = cstacksize;
+ }
+ return oldsz;
+}
+
+#endif
diff --git a/Build/source/libs/lua51/lcoco.h b/Build/source/libs/lua51/lcoco.h
new file mode 100644
index 00000000000..96858d75ca5
--- /dev/null
+++ b/Build/source/libs/lua51/lcoco.h
@@ -0,0 +1,72 @@
+/*
+** Lua/Coco glue.
+** Copyright (C) 2004-2007 Mike Pall. See copyright notice in lcoco.c
+*/
+
+#ifndef lcoco_h
+#define lcoco_h
+
+#define LUACOCO_VERSION "Coco 1.1.3"
+#define LUACOCO_VERSION_NUM 10103
+
+/* Exported C API to add a C stack to a coroutine. */
+LUA_API lua_State *lua_newcthread(lua_State *L, int cstacksize);
+
+/* Internal support routines. */
+LUAI_FUNC void luaCOCO_free(lua_State *L);
+LUAI_FUNC int luaCOCO_resume(lua_State *L, int nargs);
+LUAI_FUNC int luaCOCO_yield(lua_State *L);
+LUAI_FUNC int luaCOCO_cstacksize(int cstacksize);
+
+/* Forward declaration. */
+typedef struct coco_State coco_State;
+
+/* These are redefined below. */
+#undef LUAI_EXTRASPACE
+#undef luai_userstateopen
+/* luai_userstateclose unused */
+#undef luai_userstatethread
+#undef luai_userstatefree
+#undef luai_userstateresume
+#undef luai_userstateyield
+
+/* Use Windows Fibers (Win98+). */
+#if defined(_WIN32)
+
+/* Fibers allocate their own stack. The whole Coco state is in front of L. */
+struct coco_State {
+ void *fib; /* Own fiber (if any). */
+ void *back; /* Fiber to switch back to. */
+ int nargs; /* Number of arguments to pass. */
+ int dummy_align;
+};
+
+#define L2COCO(L) (&((coco_State *)(L))[-1])
+#define LHASCOCO(L) (L2COCO(L)->fib)
+#define LUAI_EXTRASPACE sizeof(coco_State)
+#define luai_userstateopen(L) L2COCO(L)->fib = NULL
+#define luai_userstatethread(L,L1) L2COCO(L1)->fib = NULL
+#define COCO_USE_FIBERS
+
+#else /* !defined(_WIN32) */
+
+/* The Coco state depends on the context switch method used. See lcoco.c. */
+/* It's stored at the end of the stack. Only need a pointer in front of L. */
+#define L2COCO(L) (((coco_State **)(L))[-1])
+#define LHASCOCO(L) (L2COCO(L))
+/* This wastes some space on 32 bit systems, but gets better alignment. */
+#define LUAI_EXTRASPACE sizeof(LUAI_USER_ALIGNMENT_T)
+#define luai_userstateopen(L) L2COCO(L) = NULL
+#define luai_userstatethread(L,L1) L2COCO(L1) = NULL
+
+#endif /* !defined(_WIN32) */
+
+#define luai_userstatefree(L) if (LHASCOCO(L)) luaCOCO_free(L)
+#define luai_userstateresume(L, nargs) \
+ if (LHASCOCO(L)) return luaCOCO_resume(L, nargs)
+#define luai_userstateyield(L, nresults) \
+ do { if (LHASCOCO(L)) { \
+ L->base = L->top - (nresults); /* Protect stack slots below. */ \
+ return luaCOCO_yield(L); } } while (0)
+
+#endif
diff --git a/Build/source/libs/lua51/lcode.c b/Build/source/libs/lua51/lcode.c
new file mode 100644
index 00000000000..9ce515ab648
--- /dev/null
+++ b/Build/source/libs/lua51/lcode.c
@@ -0,0 +1,839 @@
+/*
+** $Id: lcode.c,v 2.25a 2006/03/21 19:28:49 roberto Exp $
+** Code generator for Lua
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdlib.h>
+
+#define lcode_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lcode.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lgc.h"
+#include "llex.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+#include "ltable.h"
+
+
+#define hasjumps(e) ((e)->t != (e)->f)
+
+
+static int isnumeral(expdesc *e) {
+ return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
+}
+
+
+void luaK_nil (FuncState *fs, int from, int n) {
+ Instruction *previous;
+ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */
+ if (fs->pc == 0) { /* function start? */
+ if (from >= fs->nactvar)
+ return; /* positions are already clean */
+ }
+ else {
+ previous = &fs->f->code[fs->pc-1];
+ if (GET_OPCODE(*previous) == OP_LOADNIL) {
+ int pfrom = GETARG_A(*previous);
+ int pto = GETARG_B(*previous);
+ if (pfrom <= from && from <= pto+1) { /* can connect both? */
+ if (from+n-1 > pto)
+ SETARG_B(*previous, from+n-1);
+ return;
+ }
+ }
+ }
+ }
+ luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */
+}
+
+
+int luaK_jump (FuncState *fs) {
+ int jpc = fs->jpc; /* save list of jumps to here */
+ int j;
+ fs->jpc = NO_JUMP;
+ j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
+ luaK_concat(fs, &j, jpc); /* keep them on hold */
+ return j;
+}
+
+
+void luaK_ret (FuncState *fs, int first, int nret) {
+ luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
+}
+
+
+static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
+ luaK_codeABC(fs, op, A, B, C);
+ return luaK_jump(fs);
+}
+
+
+static void fixjump (FuncState *fs, int pc, int dest) {
+ Instruction *jmp = &fs->f->code[pc];
+ int offset = dest-(pc+1);
+ lua_assert(dest != NO_JUMP);
+ if (abs(offset) > MAXARG_sBx)
+ luaX_syntaxerror(fs->ls, "control structure too long");
+ SETARG_sBx(*jmp, offset);
+}
+
+
+/*
+** returns current `pc' and marks it as a jump target (to avoid wrong
+** optimizations with consecutive instructions not in the same basic block).
+*/
+int luaK_getlabel (FuncState *fs) {
+ fs->lasttarget = fs->pc;
+ return fs->pc;
+}
+
+
+static int getjump (FuncState *fs, int pc) {
+ int offset = GETARG_sBx(fs->f->code[pc]);
+ if (offset == NO_JUMP) /* point to itself represents end of list */
+ return NO_JUMP; /* end of list */
+ else
+ return (pc+1)+offset; /* turn offset into absolute position */
+}
+
+
+static Instruction *getjumpcontrol (FuncState *fs, int pc) {
+ Instruction *pi = &fs->f->code[pc];
+ if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
+ return pi-1;
+ else
+ return pi;
+}
+
+
+/*
+** check whether list has any jump that do not produce a value
+** (or produce an inverted value)
+*/
+static int need_value (FuncState *fs, int list) {
+ for (; list != NO_JUMP; list = getjump(fs, list)) {
+ Instruction i = *getjumpcontrol(fs, list);
+ if (GET_OPCODE(i) != OP_TESTSET) return 1;
+ }
+ return 0; /* not found */
+}
+
+
+static int patchtestreg (FuncState *fs, int node, int reg) {
+ Instruction *i = getjumpcontrol(fs, node);
+ if (GET_OPCODE(*i) != OP_TESTSET)
+ return 0; /* cannot patch other instructions */
+ if (reg != NO_REG && reg != GETARG_B(*i))
+ SETARG_A(*i, reg);
+ else /* no register to put value or register already has the value */
+ *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
+
+ return 1;
+}
+
+
+static void removevalues (FuncState *fs, int list) {
+ for (; list != NO_JUMP; list = getjump(fs, list))
+ patchtestreg(fs, list, NO_REG);
+}
+
+
+static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
+ int dtarget) {
+ while (list != NO_JUMP) {
+ int next = getjump(fs, list);
+ if (patchtestreg(fs, list, reg))
+ fixjump(fs, list, vtarget);
+ else
+ fixjump(fs, list, dtarget); /* jump to default target */
+ list = next;
+ }
+}
+
+
+static void dischargejpc (FuncState *fs) {
+ patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
+ fs->jpc = NO_JUMP;
+}
+
+
+void luaK_patchlist (FuncState *fs, int list, int target) {
+ if (target == fs->pc)
+ luaK_patchtohere(fs, list);
+ else {
+ lua_assert(target < fs->pc);
+ patchlistaux(fs, list, target, NO_REG, target);
+ }
+}
+
+
+void luaK_patchtohere (FuncState *fs, int list) {
+ luaK_getlabel(fs);
+ luaK_concat(fs, &fs->jpc, list);
+}
+
+
+void luaK_concat (FuncState *fs, int *l1, int l2) {
+ if (l2 == NO_JUMP) return;
+ else if (*l1 == NO_JUMP)
+ *l1 = l2;
+ else {
+ int list = *l1;
+ int next;
+ while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */
+ list = next;
+ fixjump(fs, list, l2);
+ }
+}
+
+
+void luaK_checkstack (FuncState *fs, int n) {
+ int newstack = fs->freereg + n;
+ if (newstack > fs->f->maxstacksize) {
+ if (newstack >= MAXSTACK)
+ luaX_syntaxerror(fs->ls, "function or expression too complex");
+ fs->f->maxstacksize = cast_byte(newstack);
+ }
+}
+
+
+void luaK_reserveregs (FuncState *fs, int n) {
+ luaK_checkstack(fs, n);
+ fs->freereg += n;
+}
+
+
+static void freereg (FuncState *fs, int reg) {
+ if (!ISK(reg) && reg >= fs->nactvar) {
+ fs->freereg--;
+ lua_assert(reg == fs->freereg);
+ }
+}
+
+
+static void freeexp (FuncState *fs, expdesc *e) {
+ if (e->k == VNONRELOC)
+ freereg(fs, e->u.s.info);
+}
+
+
+static int addk (FuncState *fs, TValue *k, TValue *v) {
+ lua_State *L = fs->L;
+ TValue *idx = luaH_set(L, fs->h, k);
+ Proto *f = fs->f;
+ int oldsize = f->sizek;
+ if (ttisnumber(idx)) {
+ lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
+ return cast_int(nvalue(idx));
+ }
+ else { /* constant not found; create a new entry */
+ setnvalue(idx, cast_num(fs->nk));
+ luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
+ MAXARG_Bx, "constant table overflow");
+ while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
+ setobj(L, &f->k[fs->nk], v);
+ luaC_barrier(L, f, v);
+ return fs->nk++;
+ }
+}
+
+
+int luaK_stringK (FuncState *fs, TString *s) {
+ TValue o;
+ setsvalue(fs->L, &o, s);
+ return addk(fs, &o, &o);
+}
+
+
+int luaK_numberK (FuncState *fs, lua_Number r) {
+ TValue o;
+ setnvalue(&o, r);
+ return addk(fs, &o, &o);
+}
+
+
+static int boolK (FuncState *fs, int b) {
+ TValue o;
+ setbvalue(&o, b);
+ return addk(fs, &o, &o);
+}
+
+
+static int nilK (FuncState *fs) {
+ TValue k, v;
+ setnilvalue(&v);
+ /* cannot use nil as key; instead use table itself to represent nil */
+ sethvalue(fs->L, &k, fs->h);
+ return addk(fs, &k, &v);
+}
+
+
+void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
+ if (e->k == VCALL) { /* expression is an open function call? */
+ SETARG_C(getcode(fs, e), nresults+1);
+ }
+ else if (e->k == VVARARG) {
+ SETARG_B(getcode(fs, e), nresults+1);
+ SETARG_A(getcode(fs, e), fs->freereg);
+ luaK_reserveregs(fs, 1);
+ }
+}
+
+
+void luaK_setoneret (FuncState *fs, expdesc *e) {
+ if (e->k == VCALL) { /* expression is an open function call? */
+ e->k = VNONRELOC;
+ e->u.s.info = GETARG_A(getcode(fs, e));
+ }
+ else if (e->k == VVARARG) {
+ SETARG_B(getcode(fs, e), 2);
+ e->k = VRELOCABLE; /* can relocate its simple result */
+ }
+}
+
+
+void luaK_dischargevars (FuncState *fs, expdesc *e) {
+ switch (e->k) {
+ case VLOCAL: {
+ e->k = VNONRELOC;
+ break;
+ }
+ case VUPVAL: {
+ e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);
+ e->k = VRELOCABLE;
+ break;
+ }
+ case VGLOBAL: {
+ e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);
+ e->k = VRELOCABLE;
+ break;
+ }
+ case VINDEXED: {
+ freereg(fs, e->u.s.aux);
+ freereg(fs, e->u.s.info);
+ e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);
+ e->k = VRELOCABLE;
+ break;
+ }
+ case VVARARG:
+ case VCALL: {
+ luaK_setoneret(fs, e);
+ break;
+ }
+ default: break; /* there is one value available (somewhere) */
+ }
+}
+
+
+static int code_label (FuncState *fs, int A, int b, int jump) {
+ luaK_getlabel(fs); /* those instructions may be jump targets */
+ return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
+}
+
+
+static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
+ luaK_dischargevars(fs, e);
+ switch (e->k) {
+ case VNIL: {
+ luaK_nil(fs, reg, 1);
+ break;
+ }
+ case VFALSE: case VTRUE: {
+ luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
+ break;
+ }
+ case VK: {
+ luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);
+ break;
+ }
+ case VKNUM: {
+ luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
+ break;
+ }
+ case VRELOCABLE: {
+ Instruction *pc = &getcode(fs, e);
+ SETARG_A(*pc, reg);
+ break;
+ }
+ case VNONRELOC: {
+ if (reg != e->u.s.info)
+ luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);
+ break;
+ }
+ default: {
+ lua_assert(e->k == VVOID || e->k == VJMP);
+ return; /* nothing to do... */
+ }
+ }
+ e->u.s.info = reg;
+ e->k = VNONRELOC;
+}
+
+
+static void discharge2anyreg (FuncState *fs, expdesc *e) {
+ if (e->k != VNONRELOC) {
+ luaK_reserveregs(fs, 1);
+ discharge2reg(fs, e, fs->freereg-1);
+ }
+}
+
+
+static void exp2reg (FuncState *fs, expdesc *e, int reg) {
+ discharge2reg(fs, e, reg);
+ if (e->k == VJMP)
+ luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */
+ if (hasjumps(e)) {
+ int final; /* position after whole expression */
+ int p_f = NO_JUMP; /* position of an eventual LOAD false */
+ int p_t = NO_JUMP; /* position of an eventual LOAD true */
+ if (need_value(fs, e->t) || need_value(fs, e->f)) {
+ int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
+ p_f = code_label(fs, reg, 0, 1);
+ p_t = code_label(fs, reg, 1, 0);
+ luaK_patchtohere(fs, fj);
+ }
+ final = luaK_getlabel(fs);
+ patchlistaux(fs, e->f, final, reg, p_f);
+ patchlistaux(fs, e->t, final, reg, p_t);
+ }
+ e->f = e->t = NO_JUMP;
+ e->u.s.info = reg;
+ e->k = VNONRELOC;
+}
+
+
+void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
+ luaK_dischargevars(fs, e);
+ freeexp(fs, e);
+ luaK_reserveregs(fs, 1);
+ exp2reg(fs, e, fs->freereg - 1);
+}
+
+
+int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
+ luaK_dischargevars(fs, e);
+ if (e->k == VNONRELOC) {
+ if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */
+ if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */
+ exp2reg(fs, e, e->u.s.info); /* put value on it */
+ return e->u.s.info;
+ }
+ }
+ luaK_exp2nextreg(fs, e); /* default */
+ return e->u.s.info;
+}
+
+
+void luaK_exp2val (FuncState *fs, expdesc *e) {
+ if (hasjumps(e))
+ luaK_exp2anyreg(fs, e);
+ else
+ luaK_dischargevars(fs, e);
+}
+
+
+int luaK_exp2RK (FuncState *fs, expdesc *e) {
+ luaK_exp2val(fs, e);
+ switch (e->k) {
+ case VKNUM:
+ case VTRUE:
+ case VFALSE:
+ case VNIL: {
+ if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */
+ e->u.s.info = (e->k == VNIL) ? nilK(fs) :
+ (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
+ boolK(fs, (e->k == VTRUE));
+ e->k = VK;
+ return RKASK(e->u.s.info);
+ }
+ else break;
+ }
+ case VK: {
+ if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */
+ return RKASK(e->u.s.info);
+ else break;
+ }
+ default: break;
+ }
+ /* not a constant in the right range: put it in a register */
+ return luaK_exp2anyreg(fs, e);
+}
+
+
+void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
+ switch (var->k) {
+ case VLOCAL: {
+ freeexp(fs, ex);
+ exp2reg(fs, ex, var->u.s.info);
+ return;
+ }
+ case VUPVAL: {
+ int e = luaK_exp2anyreg(fs, ex);
+ luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);
+ break;
+ }
+ case VGLOBAL: {
+ int e = luaK_exp2anyreg(fs, ex);
+ luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);
+ break;
+ }
+ case VINDEXED: {
+ int e = luaK_exp2RK(fs, ex);
+ luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);
+ break;
+ }
+ default: {
+ lua_assert(0); /* invalid var kind to store */
+ break;
+ }
+ }
+ freeexp(fs, ex);
+}
+
+
+void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
+ int func;
+ luaK_exp2anyreg(fs, e);
+ freeexp(fs, e);
+ func = fs->freereg;
+ luaK_reserveregs(fs, 2);
+ luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));
+ freeexp(fs, key);
+ e->u.s.info = func;
+ e->k = VNONRELOC;
+}
+
+
+static void invertjump (FuncState *fs, expdesc *e) {
+ Instruction *pc = getjumpcontrol(fs, e->u.s.info);
+ lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
+ GET_OPCODE(*pc) != OP_TEST);
+ SETARG_A(*pc, !(GETARG_A(*pc)));
+}
+
+
+static int jumponcond (FuncState *fs, expdesc *e, int cond) {
+ if (e->k == VRELOCABLE) {
+ Instruction ie = getcode(fs, e);
+ if (GET_OPCODE(ie) == OP_NOT) {
+ fs->pc--; /* remove previous OP_NOT */
+ return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
+ }
+ /* else go through */
+ }
+ discharge2anyreg(fs, e);
+ freeexp(fs, e);
+ return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond);
+}
+
+
+void luaK_goiftrue (FuncState *fs, expdesc *e) {
+ int pc; /* pc of last jump */
+ luaK_dischargevars(fs, e);
+ switch (e->k) {
+ case VK: case VKNUM: case VTRUE: {
+ pc = NO_JUMP; /* always true; do nothing */
+ break;
+ }
+ case VFALSE: {
+ pc = luaK_jump(fs); /* always jump */
+ break;
+ }
+ case VJMP: {
+ invertjump(fs, e);
+ pc = e->u.s.info;
+ break;
+ }
+ default: {
+ pc = jumponcond(fs, e, 0);
+ break;
+ }
+ }
+ luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */
+ luaK_patchtohere(fs, e->t);
+ e->t = NO_JUMP;
+}
+
+
+static void luaK_goiffalse (FuncState *fs, expdesc *e) {
+ int pc; /* pc of last jump */
+ luaK_dischargevars(fs, e);
+ switch (e->k) {
+ case VNIL: case VFALSE: {
+ pc = NO_JUMP; /* always false; do nothing */
+ break;
+ }
+ case VTRUE: {
+ pc = luaK_jump(fs); /* always jump */
+ break;
+ }
+ case VJMP: {
+ pc = e->u.s.info;
+ break;
+ }
+ default: {
+ pc = jumponcond(fs, e, 1);
+ break;
+ }
+ }
+ luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */
+ luaK_patchtohere(fs, e->f);
+ e->f = NO_JUMP;
+}
+
+
+static void codenot (FuncState *fs, expdesc *e) {
+ luaK_dischargevars(fs, e);
+ switch (e->k) {
+ case VNIL: case VFALSE: {
+ e->k = VTRUE;
+ break;
+ }
+ case VK: case VKNUM: case VTRUE: {
+ e->k = VFALSE;
+ break;
+ }
+ case VJMP: {
+ invertjump(fs, e);
+ break;
+ }
+ case VRELOCABLE:
+ case VNONRELOC: {
+ discharge2anyreg(fs, e);
+ freeexp(fs, e);
+ e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);
+ e->k = VRELOCABLE;
+ break;
+ }
+ default: {
+ lua_assert(0); /* cannot happen */
+ break;
+ }
+ }
+ /* interchange true and false lists */
+ { int temp = e->f; e->f = e->t; e->t = temp; }
+ removevalues(fs, e->f);
+ removevalues(fs, e->t);
+}
+
+
+void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
+ t->u.s.aux = luaK_exp2RK(fs, k);
+ t->k = VINDEXED;
+}
+
+
+static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
+ lua_Number v1, v2, r;
+ if (!isnumeral(e1) || !isnumeral(e2)) return 0;
+ v1 = e1->u.nval;
+ v2 = e2->u.nval;
+ switch (op) {
+ case OP_ADD: r = luai_numadd(v1, v2); break;
+ case OP_SUB: r = luai_numsub(v1, v2); break;
+ case OP_MUL: r = luai_nummul(v1, v2); break;
+ case OP_DIV:
+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */
+ r = luai_numdiv(v1, v2); break;
+ case OP_MOD:
+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */
+ r = luai_nummod(v1, v2); break;
+ case OP_POW: r = luai_numpow(v1, v2); break;
+ case OP_UNM: r = luai_numunm(v1); break;
+ case OP_LEN: return 0; /* no constant folding for 'len' */
+ default: lua_assert(0); r = 0; break;
+ }
+ if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */
+ e1->u.nval = r;
+ return 1;
+}
+
+
+static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
+ if (constfolding(op, e1, e2))
+ return;
+ else {
+ int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
+ int o1 = luaK_exp2RK(fs, e1);
+ if (o1 > o2) {
+ freeexp(fs, e1);
+ freeexp(fs, e2);
+ }
+ else {
+ freeexp(fs, e2);
+ freeexp(fs, e1);
+ }
+ e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);
+ e1->k = VRELOCABLE;
+ }
+}
+
+
+static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
+ expdesc *e2) {
+ int o1 = luaK_exp2RK(fs, e1);
+ int o2 = luaK_exp2RK(fs, e2);
+ freeexp(fs, e2);
+ freeexp(fs, e1);
+ if (cond == 0 && op != OP_EQ) {
+ int temp; /* exchange args to replace by `<' or `<=' */
+ temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
+ cond = 1;
+ }
+ e1->u.s.info = condjump(fs, op, cond, o1, o2);
+ e1->k = VJMP;
+}
+
+
+void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
+ expdesc e2;
+ e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
+ switch (op) {
+ case OPR_MINUS: {
+ if (e->k == VK)
+ luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
+ codearith(fs, OP_UNM, e, &e2);
+ break;
+ }
+ case OPR_NOT: codenot(fs, e); break;
+ case OPR_LEN: {
+ luaK_exp2anyreg(fs, e); /* cannot operate on constants */
+ codearith(fs, OP_LEN, e, &e2);
+ break;
+ }
+ default: lua_assert(0);
+ }
+}
+
+
+void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
+ switch (op) {
+ case OPR_AND: {
+ luaK_goiftrue(fs, v);
+ break;
+ }
+ case OPR_OR: {
+ luaK_goiffalse(fs, v);
+ break;
+ }
+ case OPR_CONCAT: {
+ luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */
+ break;
+ }
+ case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
+ case OPR_MOD: case OPR_POW: {
+ if (!isnumeral(v)) luaK_exp2RK(fs, v);
+ break;
+ }
+ default: {
+ luaK_exp2RK(fs, v);
+ break;
+ }
+ }
+}
+
+
+void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
+ switch (op) {
+ case OPR_AND: {
+ lua_assert(e1->t == NO_JUMP); /* list must be closed */
+ luaK_dischargevars(fs, e2);
+ luaK_concat(fs, &e2->f, e1->f);
+ *e1 = *e2;
+ break;
+ }
+ case OPR_OR: {
+ lua_assert(e1->f == NO_JUMP); /* list must be closed */
+ luaK_dischargevars(fs, e2);
+ luaK_concat(fs, &e2->t, e1->t);
+ *e1 = *e2;
+ break;
+ }
+ case OPR_CONCAT: {
+ luaK_exp2val(fs, e2);
+ if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
+ lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1);
+ freeexp(fs, e1);
+ SETARG_B(getcode(fs, e2), e1->u.s.info);
+ e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info;
+ }
+ else {
+ luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */
+ codearith(fs, OP_CONCAT, e1, e2);
+ }
+ break;
+ }
+ case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break;
+ case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break;
+ case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break;
+ case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break;
+ case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break;
+ case OPR_POW: codearith(fs, OP_POW, e1, e2); break;
+ case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break;
+ case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break;
+ case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break;
+ case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break;
+ case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break;
+ case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break;
+ default: lua_assert(0);
+ }
+}
+
+
+void luaK_fixline (FuncState *fs, int line) {
+ fs->f->lineinfo[fs->pc - 1] = line;
+}
+
+
+static int luaK_code (FuncState *fs, Instruction i, int line) {
+ Proto *f = fs->f;
+ dischargejpc(fs); /* `pc' will change */
+ /* put new instruction in code array */
+ luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,
+ MAX_INT, "code size overflow");
+ f->code[fs->pc] = i;
+ /* save corresponding line information */
+ luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
+ MAX_INT, "code size overflow");
+ f->lineinfo[fs->pc] = line;
+ return fs->pc++;
+}
+
+
+int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
+ lua_assert(getOpMode(o) == iABC);
+ lua_assert(getBMode(o) != OpArgN || b == 0);
+ lua_assert(getCMode(o) != OpArgN || c == 0);
+ return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);
+}
+
+
+int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
+ lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
+ lua_assert(getCMode(o) == OpArgN);
+ return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);
+}
+
+
+void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
+ int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1;
+ int b = (tostore == LUA_MULTRET) ? 0 : tostore;
+ lua_assert(tostore != 0);
+ if (c <= MAXARG_C)
+ luaK_codeABC(fs, OP_SETLIST, base, b, c);
+ else {
+ luaK_codeABC(fs, OP_SETLIST, base, b, 0);
+ luaK_code(fs, cast(Instruction, c), fs->ls->lastline);
+ }
+ fs->freereg = base + 1; /* free registers with list values */
+}
+
diff --git a/Build/source/libs/lua51/lcode.h b/Build/source/libs/lua51/lcode.h
new file mode 100644
index 00000000000..c02cb2b726f
--- /dev/null
+++ b/Build/source/libs/lua51/lcode.h
@@ -0,0 +1,76 @@
+/*
+** $Id: lcode.h,v 1.48 2006/03/21 19:28:03 roberto Exp $
+** Code generator for Lua
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lcode_h
+#define lcode_h
+
+#include "llex.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+
+
+/*
+** Marks the end of a patch list. It is an invalid value both as an absolute
+** address, and as a list link (would link an element to itself).
+*/
+#define NO_JUMP (-1)
+
+
+/*
+** grep "ORDER OPR" if you change these enums
+*/
+typedef enum BinOpr {
+ OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW,
+ OPR_CONCAT,
+ OPR_NE, OPR_EQ,
+ OPR_LT, OPR_LE, OPR_GT, OPR_GE,
+ OPR_AND, OPR_OR,
+ OPR_NOBINOPR
+} BinOpr;
+
+
+typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
+
+
+#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info])
+
+#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
+
+#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET)
+
+LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
+LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
+LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
+LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
+LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
+LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
+LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);
+LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r);
+LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
+LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
+LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
+LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
+LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);
+LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
+LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
+LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
+LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
+LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
+LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
+LUAI_FUNC int luaK_jump (FuncState *fs);
+LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
+LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
+LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
+LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
+LUAI_FUNC int luaK_getlabel (FuncState *fs);
+LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v);
+LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
+LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);
+LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
+
+
+#endif
diff --git a/Build/source/libs/lua51/ldblib.c b/Build/source/libs/lua51/ldblib.c
new file mode 100644
index 00000000000..26a19b6a6f6
--- /dev/null
+++ b/Build/source/libs/lua51/ldblib.c
@@ -0,0 +1,397 @@
+/*
+** $Id: ldblib.c,v 1.104 2005/12/29 15:32:11 roberto Exp $
+** Interface from Lua to its debug API
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ldblib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+
+static int db_getregistry (lua_State *L) {
+ lua_pushvalue(L, LUA_REGISTRYINDEX);
+ return 1;
+}
+
+
+static int db_getmetatable (lua_State *L) {
+ luaL_checkany(L, 1);
+ if (!lua_getmetatable(L, 1)) {
+ lua_pushnil(L); /* no metatable */
+ }
+ return 1;
+}
+
+
+static int db_setmetatable (lua_State *L) {
+ int t = lua_type(L, 2);
+ luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
+ "nil or table expected");
+ lua_settop(L, 2);
+ lua_pushboolean(L, lua_setmetatable(L, 1));
+ return 1;
+}
+
+
+static int db_getfenv (lua_State *L) {
+ lua_getfenv(L, 1);
+ return 1;
+}
+
+
+static int db_setfenv (lua_State *L) {
+ luaL_checktype(L, 2, LUA_TTABLE);
+ lua_settop(L, 2);
+ if (lua_setfenv(L, 1) == 0)
+ luaL_error(L, LUA_QL("setfenv")
+ " cannot change environment of given object");
+ return 1;
+}
+
+
+static void settabss (lua_State *L, const char *i, const char *v) {
+ lua_pushstring(L, v);
+ lua_setfield(L, -2, i);
+}
+
+
+static void settabsi (lua_State *L, const char *i, int v) {
+ lua_pushinteger(L, v);
+ lua_setfield(L, -2, i);
+}
+
+
+static lua_State *getthread (lua_State *L, int *arg) {
+ if (lua_isthread(L, 1)) {
+ *arg = 1;
+ return lua_tothread(L, 1);
+ }
+ else {
+ *arg = 0;
+ return L;
+ }
+}
+
+
+static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
+ if (L == L1) {
+ lua_pushvalue(L, -2);
+ lua_remove(L, -3);
+ }
+ else
+ lua_xmove(L1, L, 1);
+ lua_setfield(L, -2, fname);
+}
+
+
+static int db_getinfo (lua_State *L) {
+ lua_Debug ar;
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ const char *options = luaL_optstring(L, arg+2, "flnSu");
+ if (lua_isnumber(L, arg+1)) {
+ if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
+ lua_pushnil(L); /* level out of range */
+ return 1;
+ }
+ }
+ else if (lua_isfunction(L, arg+1)) {
+ lua_pushfstring(L, ">%s", options);
+ options = lua_tostring(L, -1);
+ lua_pushvalue(L, arg+1);
+ lua_xmove(L, L1, 1);
+ }
+ else
+ return luaL_argerror(L, arg+1, "function or level expected");
+ if (!lua_getinfo(L1, options, &ar))
+ return luaL_argerror(L, arg+2, "invalid option");
+ lua_createtable(L, 0, 2);
+ if (strchr(options, 'S')) {
+ settabss(L, "source", ar.source);
+ settabss(L, "short_src", ar.short_src);
+ settabsi(L, "linedefined", ar.linedefined);
+ settabsi(L, "lastlinedefined", ar.lastlinedefined);
+ settabss(L, "what", ar.what);
+ }
+ if (strchr(options, 'l'))
+ settabsi(L, "currentline", ar.currentline);
+ if (strchr(options, 'u'))
+ settabsi(L, "nups", ar.nups);
+ if (strchr(options, 'n')) {
+ settabss(L, "name", ar.name);
+ settabss(L, "namewhat", ar.namewhat);
+ }
+ if (strchr(options, 'L'))
+ treatstackoption(L, L1, "activelines");
+ if (strchr(options, 'f'))
+ treatstackoption(L, L1, "func");
+ return 1; /* return table */
+}
+
+
+static int db_getlocal (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ lua_Debug ar;
+ const char *name;
+ if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
+ return luaL_argerror(L, arg+1, "level out of range");
+ name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));
+ if (name) {
+ lua_xmove(L1, L, 1);
+ lua_pushstring(L, name);
+ lua_pushvalue(L, -2);
+ return 2;
+ }
+ else {
+ lua_pushnil(L);
+ return 1;
+ }
+}
+
+
+static int db_setlocal (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ lua_Debug ar;
+ if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
+ return luaL_argerror(L, arg+1, "level out of range");
+ luaL_checkany(L, arg+3);
+ lua_settop(L, arg+3);
+ lua_xmove(L, L1, 1);
+ lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));
+ return 1;
+}
+
+
+static int auxupvalue (lua_State *L, int get) {
+ const char *name;
+ int n = luaL_checkint(L, 2);
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */
+ name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
+ if (name == NULL) return 0;
+ lua_pushstring(L, name);
+ lua_insert(L, -(get+1));
+ return get + 1;
+}
+
+
+static int db_getupvalue (lua_State *L) {
+ return auxupvalue(L, 1);
+}
+
+
+static int db_setupvalue (lua_State *L) {
+ luaL_checkany(L, 3);
+ return auxupvalue(L, 0);
+}
+
+
+
+static const char KEY_HOOK = 'h';
+
+
+static void hookf (lua_State *L, lua_Debug *ar) {
+ static const char *const hooknames[] =
+ {"call", "return", "line", "count", "tail return"};
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_pushlightuserdata(L, L);
+ lua_rawget(L, -2);
+ if (lua_isfunction(L, -1)) {
+ lua_pushstring(L, hooknames[(int)ar->event]);
+ if (ar->currentline >= 0)
+ lua_pushinteger(L, ar->currentline);
+ else lua_pushnil(L);
+ lua_assert(lua_getinfo(L, "lS", ar));
+ lua_call(L, 2, 0);
+ }
+}
+
+
+static int makemask (const char *smask, int count) {
+ int mask = 0;
+ if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
+ if (strchr(smask, 'r')) mask |= LUA_MASKRET;
+ if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
+ if (count > 0) mask |= LUA_MASKCOUNT;
+ return mask;
+}
+
+
+static char *unmakemask (int mask, char *smask) {
+ int i = 0;
+ if (mask & LUA_MASKCALL) smask[i++] = 'c';
+ if (mask & LUA_MASKRET) smask[i++] = 'r';
+ if (mask & LUA_MASKLINE) smask[i++] = 'l';
+ smask[i] = '\0';
+ return smask;
+}
+
+
+static void gethooktable (lua_State *L) {
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ if (!lua_istable(L, -1)) {
+ lua_pop(L, 1);
+ lua_createtable(L, 0, 1);
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_pushvalue(L, -2);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+ }
+}
+
+
+static int db_sethook (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ if (lua_isnoneornil(L, arg+1)) {
+ lua_settop(L, arg+1);
+ lua_sethook(L1, NULL, 0, 0); /* turn off hooks */
+ }
+ else {
+ const char *smask = luaL_checkstring(L, arg+2);
+ int count = luaL_optint(L, arg+3, 0);
+ luaL_checktype(L, arg+1, LUA_TFUNCTION);
+ lua_sethook(L1, hookf, makemask(smask, count), count);
+ }
+ gethooktable(L1);
+ lua_pushlightuserdata(L1, L1);
+ lua_pushvalue(L, arg+1);
+ lua_xmove(L, L1, 1);
+ lua_rawset(L1, -3); /* set new hook */
+ lua_pop(L1, 1); /* remove hook table */
+ return 0;
+}
+
+
+static int db_gethook (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ char buff[5];
+ int mask = lua_gethookmask(L1);
+ lua_Hook hook = lua_gethook(L1);
+ if (hook != NULL && hook != hookf) /* external hook? */
+ lua_pushliteral(L, "external hook");
+ else {
+ gethooktable(L1);
+ lua_pushlightuserdata(L1, L1);
+ lua_rawget(L1, -2); /* get hook */
+ lua_remove(L1, -2); /* remove hook table */
+ lua_xmove(L1, L, 1);
+ }
+ lua_pushstring(L, unmakemask(mask, buff));
+ lua_pushinteger(L, lua_gethookcount(L1));
+ return 3;
+}
+
+
+static int db_debug (lua_State *L) {
+ for (;;) {
+ char buffer[250];
+ fputs("lua_debug> ", stderr);
+ if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
+ strcmp(buffer, "cont\n") == 0)
+ return 0;
+ if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
+ lua_pcall(L, 0, 0, 0)) {
+ fputs(lua_tostring(L, -1), stderr);
+ fputs("\n", stderr);
+ }
+ lua_settop(L, 0); /* remove eventual returns */
+ }
+}
+
+
+#define LEVELS1 12 /* size of the first part of the stack */
+#define LEVELS2 10 /* size of the second part of the stack */
+
+static int db_errorfb (lua_State *L) {
+ int level;
+ int firstpart = 1; /* still before eventual `...' */
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ lua_Debug ar;
+ if (lua_isnumber(L, arg+2)) {
+ level = (int)lua_tointeger(L, arg+2);
+ lua_pop(L, 1);
+ }
+ else
+ level = (L == L1) ? 1 : 0; /* level 0 may be this own function */
+ if (lua_gettop(L) == arg)
+ lua_pushliteral(L, "");
+ else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */
+ else lua_pushliteral(L, "\n");
+ lua_pushliteral(L, "stack traceback:");
+ while (lua_getstack(L1, level++, &ar)) {
+ if (level > LEVELS1 && firstpart) {
+ /* no more than `LEVELS2' more levels? */
+ if (!lua_getstack(L1, level+LEVELS2, &ar))
+ level--; /* keep going */
+ else {
+ lua_pushliteral(L, "\n\t..."); /* too many levels */
+ while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */
+ level++;
+ }
+ firstpart = 0;
+ continue;
+ }
+ lua_pushliteral(L, "\n\t");
+ lua_getinfo(L1, "Snl", &ar);
+ lua_pushfstring(L, "%s:", ar.short_src);
+ if (ar.currentline > 0)
+ lua_pushfstring(L, "%d:", ar.currentline);
+ if (*ar.namewhat != '\0') /* is there a name? */
+ lua_pushfstring(L, " in function " LUA_QS, ar.name);
+ else {
+ if (*ar.what == 'm') /* main? */
+ lua_pushfstring(L, " in main chunk");
+ else if (*ar.what == 'C' || *ar.what == 't')
+ lua_pushliteral(L, " ?"); /* C function or tail call */
+ else
+ lua_pushfstring(L, " in function <%s:%d>",
+ ar.short_src, ar.linedefined);
+ }
+ lua_concat(L, lua_gettop(L) - arg);
+ }
+ lua_concat(L, lua_gettop(L) - arg);
+ return 1;
+}
+
+
+static const luaL_Reg dblib[] = {
+ {"debug", db_debug},
+ {"getfenv", db_getfenv},
+ {"gethook", db_gethook},
+ {"getinfo", db_getinfo},
+ {"getlocal", db_getlocal},
+ {"getregistry", db_getregistry},
+ {"getmetatable", db_getmetatable},
+ {"getupvalue", db_getupvalue},
+ {"setfenv", db_setfenv},
+ {"sethook", db_sethook},
+ {"setlocal", db_setlocal},
+ {"setmetatable", db_setmetatable},
+ {"setupvalue", db_setupvalue},
+ {"traceback", db_errorfb},
+ {NULL, NULL}
+};
+
+
+LUALIB_API int luaopen_debug (lua_State *L) {
+ luaL_register(L, LUA_DBLIBNAME, dblib);
+ return 1;
+}
+
diff --git a/Build/source/libs/lua51/ldebug.c b/Build/source/libs/lua51/ldebug.c
new file mode 100644
index 00000000000..d956f3df058
--- /dev/null
+++ b/Build/source/libs/lua51/ldebug.c
@@ -0,0 +1,624 @@
+/*
+** $Id: ldebug.c,v 2.29a 2005/12/22 16:19:56 roberto Exp $
+** Debug Interface
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+
+
+#define ldebug_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lapi.h"
+#include "lcode.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lvm.h"
+
+#include <stdio.h>
+
+static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
+
+
+static int currentpc (lua_State *L, CallInfo *ci) {
+ if (!isLua(ci)) return -1; /* function is not a Lua function? */
+ if (ci == L->ci)
+ ci->savedpc = L->savedpc;
+ if (ci->savedpc==NULL)
+ return -1;
+ return pcRel(ci->savedpc, ci_func(ci)->l.p);
+}
+
+
+static int currentline (lua_State *L, CallInfo *ci) {
+ int pc = currentpc(L, ci);
+ if (pc < 0)
+ return -1; /* only active lua functions have current-line information */
+ else
+ return getline(ci_func(ci)->l.p, pc);
+}
+
+
+/*
+** this function can be called asynchronous (e.g. during a signal)
+*/
+LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
+ if (func == NULL || mask == 0) { /* turn off hooks? */
+ mask = 0;
+ func = NULL;
+ }
+ L->hook = func;
+ L->basehookcount = count;
+ resethookcount(L);
+ L->hookmask = cast_byte(mask);
+ return 1;
+}
+
+
+LUA_API lua_Hook lua_gethook (lua_State *L) {
+ return L->hook;
+}
+
+
+LUA_API int lua_gethookmask (lua_State *L) {
+ return L->hookmask;
+}
+
+
+LUA_API int lua_gethookcount (lua_State *L) {
+ return L->basehookcount;
+}
+
+
+LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
+ int status;
+ CallInfo *ci;
+ lua_lock(L);
+ for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {
+ level--;
+ if (f_isLua(ci)) /* Lua function? */
+ level -= ci->tailcalls; /* skip lost tail calls */
+ }
+ if (level == 0 && ci > L->base_ci) { /* level found? */
+ status = 1;
+ ar->i_ci = cast_int(ci - L->base_ci);
+ }
+ else if (level < 0) { /* level is of a lost tail call? */
+ status = 1;
+ ar->i_ci = 0;
+ }
+ else status = 0; /* no such level */
+ lua_unlock(L);
+ return status;
+}
+
+
+static Proto *getluaproto (CallInfo *ci) {
+ return (isLua(ci) ? ci_func(ci)->l.p : NULL);
+}
+
+
+static const char *findlocal (lua_State *L, CallInfo *ci, int n) {
+ const char *name;
+ Proto *fp = getluaproto(ci);
+ if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL)
+ return name; /* is a local variable in a Lua function */
+ else {
+ StkId limit = (ci == L->ci) ? L->top : (ci+1)->func;
+ if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */
+ return "(*temporary)";
+ else
+ return NULL;
+ }
+}
+
+
+LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
+ CallInfo *ci = L->base_ci + ar->i_ci;
+ const char *name = findlocal(L, ci, n);
+ lua_lock(L);
+ if (name)
+ luaA_pushobject(L, ci->base + (n - 1));
+ lua_unlock(L);
+ return name;
+}
+
+
+LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
+ CallInfo *ci = L->base_ci + ar->i_ci;
+ const char *name = findlocal(L, ci, n);
+ lua_lock(L);
+ if (name)
+ setobjs2s(L, ci->base + (n - 1), L->top - 1);
+ L->top--; /* pop value */
+ lua_unlock(L);
+ return name;
+}
+
+
+static void funcinfo (lua_Debug *ar, Closure *cl) {
+ if (cl->c.isC) {
+ ar->source = "=[C]";
+ ar->linedefined = -1;
+ ar->lastlinedefined = -1;
+ ar->what = "C";
+ }
+ else {
+ ar->source = getstr(cl->l.p->source);
+ ar->linedefined = cl->l.p->linedefined;
+ ar->lastlinedefined = cl->l.p->lastlinedefined;
+ ar->what = (ar->linedefined == 0) ? "main" : "Lua";
+ }
+ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
+}
+
+
+static void info_tailcall (lua_Debug *ar) {
+ ar->name = ar->namewhat = "";
+ ar->what = "tail";
+ ar->lastlinedefined = ar->linedefined = ar->currentline = -1;
+ ar->source = "=(tail call)";
+ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
+ ar->nups = 0;
+}
+
+
+static void collectvalidlines (lua_State *L, Closure *f) {
+ if (f == NULL || f->c.isC) {
+ setnilvalue(L->top);
+ }
+ else {
+ Table *t = luaH_new(L, 0, 0);
+ int *lineinfo = f->l.p->lineinfo;
+ int i;
+ for (i=0; i<f->l.p->sizelineinfo; i++)
+ setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
+ sethvalue(L, L->top, t);
+ }
+ incr_top(L);
+}
+
+
+static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
+ Closure *f, CallInfo *ci) {
+ int status = 1;
+ if (f == NULL) {
+ info_tailcall(ar);
+ return status;
+ }
+ for (; *what; what++) {
+ switch (*what) {
+ case 'S': {
+ funcinfo(ar, f);
+ break;
+ }
+ case 'l': {
+ ar->currentline = (ci) ? currentline(L, ci) : -1;
+ break;
+ }
+ case 'u': {
+ ar->nups = f->c.nupvalues;
+ break;
+ }
+ case 'n': {
+ ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL;
+ if (ar->namewhat == NULL) {
+ ar->namewhat = ""; /* not found */
+ ar->name = NULL;
+ }
+ break;
+ }
+ case 'L':
+ case 'f': /* handled by lua_getinfo */
+ break;
+ default: status = 0; /* invalid option */
+ }
+ }
+ return status;
+}
+
+
+LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
+ int status;
+ Closure *f = NULL;
+ CallInfo *ci = NULL;
+ lua_lock(L);
+ if (*what == '>') {
+ StkId func = L->top - 1;
+ luai_apicheck(L, ttisfunction(func));
+ what++; /* skip the '>' */
+ f = clvalue(func);
+ L->top--; /* pop function */
+ }
+ else if (ar->i_ci != 0) { /* no tail call? */
+ ci = L->base_ci + ar->i_ci;
+ lua_assert(ttisfunction(ci->func));
+ f = clvalue(ci->func);
+ }
+ status = auxgetinfo(L, what, ar, f, ci);
+ if (strchr(what, 'f')) {
+ if (f == NULL) setnilvalue(L->top);
+ else setclvalue(L, L->top, f);
+ incr_top(L);
+ }
+ if (strchr(what, 'L'))
+ collectvalidlines(L, f);
+ lua_unlock(L);
+ return status;
+}
+
+
+/*
+** {======================================================
+** Symbolic Execution and code checker
+** =======================================================
+*/
+
+#define check(x) if (!(x)) return 0;
+
+#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode)
+
+#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize)
+
+
+
+static int precheck (const Proto *pt) {
+ check(pt->maxstacksize <= MAXSTACK);
+ lua_assert(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);
+ lua_assert(!(pt->is_vararg & VARARG_NEEDSARG) ||
+ (pt->is_vararg & VARARG_HASARG));
+ check(pt->sizeupvalues <= pt->nups);
+ check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
+ check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
+ return 1;
+}
+
+
+#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1])
+
+int luaG_checkopenop (Instruction i) {
+ switch (GET_OPCODE(i)) {
+ case OP_CALL:
+ case OP_TAILCALL:
+ case OP_RETURN:
+ case OP_SETLIST: {
+ check(GETARG_B(i) == 0);
+ return 1;
+ }
+ default: return 0; /* invalid instruction after an open call */
+ }
+}
+
+
+static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) {
+ switch (mode) {
+ case OpArgN: check(r == 0); break;
+ case OpArgU: break;
+ case OpArgR: checkreg(pt, r); break;
+ case OpArgK:
+ check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize);
+ break;
+ }
+ return 1;
+}
+
+
+static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
+ int pc;
+ int last; /* stores position of last instruction that changed `reg' */
+ last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */
+ check(precheck(pt));
+ for (pc = 0; pc < lastpc; pc++) {
+ Instruction i = pt->code[pc];
+ OpCode op = GET_OPCODE(i);
+ int a = GETARG_A(i);
+ int b = 0;
+ int c = 0;
+ check(op < NUM_OPCODES);
+ checkreg(pt, a);
+ switch (getOpMode(op)) {
+ case iABC: {
+ b = GETARG_B(i);
+ c = GETARG_C(i);
+ check(checkArgMode(pt, b, getBMode(op)));
+ check(checkArgMode(pt, c, getCMode(op)));
+ break;
+ }
+ case iABx: {
+ b = GETARG_Bx(i);
+ if (getBMode(op) == OpArgK) check(b < pt->sizek);
+ break;
+ }
+ case iAsBx: {
+ b = GETARG_sBx(i);
+ if (getBMode(op) == OpArgR) {
+ int dest = pc+1+b;
+ check(0 <= dest && dest < pt->sizecode);
+ if (dest > 0) {
+ /* cannot jump to a setlist count */
+ Instruction d = pt->code[dest-1];
+ check(!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0));
+ }
+ }
+ break;
+ }
+ }
+ if (testAMode(op)) {
+ if (a == reg) last = pc; /* change register `a' */
+ }
+ if (testTMode(op)) {
+ check(pc+2 < pt->sizecode); /* check skip */
+ check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);
+ }
+ switch (op) {
+ case OP_LOADBOOL: {
+ check(c == 0 || pc+2 < pt->sizecode); /* check its jump */
+ break;
+ }
+ case OP_LOADNIL: {
+ if (a <= reg && reg <= b)
+ last = pc; /* set registers from `a' to `b' */
+ break;
+ }
+ case OP_GETUPVAL:
+ case OP_SETUPVAL: {
+ check(b < pt->nups);
+ break;
+ }
+ case OP_GETGLOBAL:
+ case OP_SETGLOBAL: {
+ check(ttisstring(&pt->k[b]));
+ break;
+ }
+ case OP_SELF: {
+ checkreg(pt, a+1);
+ if (reg == a+1) last = pc;
+ break;
+ }
+ case OP_CONCAT: {
+ check(b < c); /* at least two operands */
+ break;
+ }
+ case OP_TFORLOOP: {
+ check(c >= 1); /* at least one result (control variable) */
+ checkreg(pt, a+2+c); /* space for results */
+ if (reg >= a+2) last = pc; /* affect all regs above its base */
+ break;
+ }
+ case OP_FORLOOP:
+ case OP_FORPREP:
+ checkreg(pt, a+3);
+ /* go through */
+ case OP_JMP: {
+ int dest = pc+1+b;
+ /* not full check and jump is forward and do not skip `lastpc'? */
+ if (reg != NO_REG && pc < dest && dest <= lastpc)
+ pc += b; /* do the jump */
+ break;
+ }
+ case OP_CALL:
+ case OP_TAILCALL: {
+ if (b != 0) {
+ checkreg(pt, a+b-1);
+ }
+ c--; /* c = num. returns */
+ if (c == LUA_MULTRET) {
+ check(checkopenop(pt, pc));
+ }
+ else if (c != 0)
+ checkreg(pt, a+c-1);
+ if (reg >= a) last = pc; /* affect all registers above base */
+ break;
+ }
+ case OP_RETURN: {
+ b--; /* b = num. returns */
+ if (b > 0) checkreg(pt, a+b-1);
+ break;
+ }
+ case OP_SETLIST: {
+ if (b > 0) checkreg(pt, a + b);
+ if (c == 0) pc++;
+ break;
+ }
+ case OP_CLOSURE: {
+ int nup, j;
+ check(b < pt->sizep);
+ nup = pt->p[b]->nups;
+ check(pc + nup < pt->sizecode);
+ for (j = 1; j <= nup; j++) {
+ OpCode op1 = GET_OPCODE(pt->code[pc + j]);
+ check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
+ }
+ if (reg != NO_REG) /* tracing? */
+ pc += nup; /* do not 'execute' these pseudo-instructions */
+ break;
+ }
+ case OP_VARARG: {
+ check((pt->is_vararg & VARARG_ISVARARG) &&
+ !(pt->is_vararg & VARARG_NEEDSARG));
+ b--;
+ if (b == LUA_MULTRET) check(checkopenop(pt, pc));
+ checkreg(pt, a+b-1);
+ break;
+ }
+ default: break;
+ }
+ }
+ return pt->code[last];
+}
+
+#undef check
+#undef checkjump
+#undef checkreg
+
+/* }====================================================== */
+
+
+int luaG_checkcode (const Proto *pt) {
+ return (symbexec(pt, pt->sizecode, NO_REG) != 0);
+}
+
+
+static const char *kname (Proto *p, int c) {
+ if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))
+ return svalue(&p->k[INDEXK(c)]);
+ else
+ return "?";
+}
+
+
+static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,
+ const char **name) {
+ if (isLua(ci)) { /* a Lua function? */
+ Proto *p = ci_func(ci)->l.p;
+ int pc = currentpc(L, ci);
+ Instruction i;
+ *name = luaF_getlocalname(p, stackpos+1, pc);
+ if (*name) /* is a local? */
+ return "local";
+ i = symbexec(p, pc, stackpos); /* try symbolic execution */
+ lua_assert(pc != -1);
+ switch (GET_OPCODE(i)) {
+ case OP_GETGLOBAL: {
+ int g = GETARG_Bx(i); /* global index */
+ lua_assert(ttisstring(&p->k[g]));
+ *name = svalue(&p->k[g]);
+ return "global";
+ }
+ case OP_MOVE: {
+ int a = GETARG_A(i);
+ int b = GETARG_B(i); /* move from `b' to `a' */
+ if (b < a)
+ return getobjname(L, ci, b, name); /* get name for `b' */
+ break;
+ }
+ case OP_GETTABLE: {
+ int k = GETARG_C(i); /* key index */
+ *name = kname(p, k);
+ return "field";
+ }
+ case OP_GETUPVAL: {
+ int u = GETARG_B(i); /* upvalue index */
+ *name = p->upvalues ? getstr(p->upvalues[u]) : "?";
+ return "upvalue";
+ }
+ case OP_SELF: {
+ int k = GETARG_C(i); /* key index */
+ *name = kname(p, k);
+ return "method";
+ }
+ default: break;
+ }
+ }
+ return NULL; /* no useful name found */
+}
+
+
+static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
+ Instruction i;
+ if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1))
+ return NULL; /* calling function is not Lua (or is unknown) */
+ ci--; /* calling function */
+ i = ci_func(ci)->l.p->code[currentpc(L, ci)];
+ if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
+ GET_OPCODE(i) == OP_TFORLOOP)
+ return getobjname(L, ci, GETARG_A(i), name);
+ else
+ return NULL; /* no useful name can be found */
+}
+
+
+/* only ANSI way to check whether a pointer points to an array */
+static int isinstack (CallInfo *ci, const TValue *o) {
+ StkId p;
+ for (p = ci->base; p < ci->top; p++)
+ if (o == p) return 1;
+ return 0;
+}
+
+
+void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
+ const char *name = NULL;
+ const char *t = luaT_typenames[ttype(o)];
+ const char *kind = (isinstack(L->ci, o)) ?
+ getobjname(L, L->ci, cast_int(o - L->base), &name) :
+ NULL;
+ if (kind)
+ luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)",
+ op, kind, name, t);
+ else
+ luaG_runerror(L, "attempt to %s a %s value", op, t);
+}
+
+
+void luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
+ if (ttisstring(p1)) p1 = p2;
+ lua_assert(!ttisstring(p1));
+ luaG_typeerror(L, p1, "concatenate");
+}
+
+
+void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {
+ TValue temp;
+ if (luaV_tonumber(p1, &temp) == NULL)
+ p2 = p1; /* first operand is wrong */
+ luaG_typeerror(L, p2, "perform arithmetic on");
+}
+
+
+int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
+ const char *t1 = luaT_typenames[ttype(p1)];
+ const char *t2 = luaT_typenames[ttype(p2)];
+ if (t1[2] == t2[2])
+ luaG_runerror(L, "attempt to compare two %s values", t1);
+ else
+ luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
+ return 0;
+}
+
+
+static void addinfo (lua_State *L, const char *msg) {
+ CallInfo *ci = L->ci;
+ if (isLua(ci)) { /* is Lua code? */
+ char buff[LUA_IDSIZE]; /* add file:line information */
+ int line = currentline(L, ci);
+ luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE);
+ luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
+ }
+}
+
+
+void luaG_errormsg (lua_State *L) {
+ if (L->errfunc != 0) { /* is there an error handling function? */
+ StkId errfunc = restorestack(L, L->errfunc);
+ if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
+ setobjs2s(L, L->top, L->top - 1); /* move argument */
+ setobjs2s(L, L->top - 1, errfunc); /* push function */
+ incr_top(L);
+ luaD_call(L, L->top - 2, 1); /* call it */
+ }
+ luaD_throw(L, LUA_ERRRUN);
+}
+
+
+void luaG_runerror (lua_State *L, const char *fmt, ...) {
+ va_list argp;
+ va_start(argp, fmt);
+ addinfo(L, luaO_pushvfstring(L, fmt, argp));
+ va_end(argp);
+ luaG_errormsg(L);
+}
+
diff --git a/Build/source/libs/lua51/ldebug.h b/Build/source/libs/lua51/ldebug.h
new file mode 100644
index 00000000000..9c76aa10f0a
--- /dev/null
+++ b/Build/source/libs/lua51/ldebug.h
@@ -0,0 +1,33 @@
+/*
+** $Id: ldebug.h,v 2.3 2005/04/25 19:24:10 roberto Exp $
+** Auxiliary functions from Debug Interface module
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ldebug_h
+#define ldebug_h
+
+
+#include "lstate.h"
+
+
+#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1)
+
+#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0)
+
+#define resethookcount(L) (L->hookcount = L->basehookcount)
+
+
+LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o,
+ const char *opname);
+LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2);
+LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1,
+ const TValue *p2);
+LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1,
+ const TValue *p2);
+LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...);
+LUAI_FUNC void luaG_errormsg (lua_State *L);
+LUAI_FUNC int luaG_checkcode (const Proto *pt);
+LUAI_FUNC int luaG_checkopenop (Instruction i);
+
+#endif
diff --git a/Build/source/libs/lua51/ldo.c b/Build/source/libs/lua51/ldo.c
new file mode 100644
index 00000000000..ab86fb70e8d
--- /dev/null
+++ b/Build/source/libs/lua51/ldo.c
@@ -0,0 +1,516 @@
+/*
+** $Id: ldo.c,v 2.38 2006/06/05 19:36:14 roberto Exp $
+** Stack and Call structure of Lua
+** See Copyright Notice in lua.h
+*/
+
+
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ldo_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lundump.h"
+#include "lvm.h"
+#include "lzio.h"
+
+
+
+
+/*
+** {======================================================
+** Error-recovery functions
+** =======================================================
+*/
+
+
+/* chain list of long jump buffers */
+struct lua_longjmp {
+ struct lua_longjmp *previous;
+ luai_jmpbuf b;
+ volatile int status; /* error code */
+};
+
+
+void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
+ switch (errcode) {
+ case LUA_ERRMEM: {
+ setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG));
+ break;
+ }
+ case LUA_ERRERR: {
+ setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
+ break;
+ }
+ case LUA_ERRSYNTAX:
+ case LUA_ERRRUN: {
+ setobjs2s(L, oldtop, L->top - 1); /* error message on current top */
+ break;
+ }
+ }
+ L->top = oldtop + 1;
+}
+
+
+static void restore_stack_limit (lua_State *L) {
+ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
+ if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */
+ int inuse = cast_int(L->ci - L->base_ci);
+ if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */
+ luaD_reallocCI(L, LUAI_MAXCALLS);
+ }
+}
+
+
+static void resetstack (lua_State *L, int status) {
+ L->ci = L->base_ci;
+ L->base = L->ci->base;
+ luaF_close(L, L->base); /* close eventual pending closures */
+ luaD_seterrorobj(L, status, L->base);
+ L->nCcalls = 0;
+ L->allowhook = 1;
+ restore_stack_limit(L);
+ L->errfunc = 0;
+ L->errorJmp = NULL;
+}
+
+
+void luaD_throw (lua_State *L, int errcode) {
+ if (L->errorJmp) {
+ L->errorJmp->status = errcode;
+ LUAI_THROW(L, L->errorJmp);
+ }
+ else {
+ L->status = cast_byte(errcode);
+ if (G(L)->panic) {
+ resetstack(L, errcode);
+ lua_unlock(L);
+ G(L)->panic(L);
+ }
+ exit(EXIT_FAILURE);
+ }
+}
+
+
+int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
+ struct lua_longjmp lj;
+ lj.status = 0;
+ lj.previous = L->errorJmp; /* chain new error handler */
+ L->errorJmp = &lj;
+ LUAI_TRY(L, &lj,
+ (*f)(L, ud);
+ );
+ L->errorJmp = lj.previous; /* restore old error handler */
+ return lj.status;
+}
+
+/* }====================================================== */
+
+
+static void correctstack (lua_State *L, TValue *oldstack) {
+ CallInfo *ci;
+ GCObject *up;
+ L->top = (L->top - oldstack) + L->stack;
+ for (up = L->openupval; up != NULL; up = up->gch.next)
+ gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
+ for (ci = L->base_ci; ci <= L->ci; ci++) {
+ ci->top = (ci->top - oldstack) + L->stack;
+ ci->base = (ci->base - oldstack) + L->stack;
+ ci->func = (ci->func - oldstack) + L->stack;
+ }
+ L->base = (L->base - oldstack) + L->stack;
+}
+
+
+void luaD_reallocstack (lua_State *L, int newsize) {
+ TValue *oldstack = L->stack;
+ int realsize = newsize + 1 + EXTRA_STACK;
+ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
+ luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue);
+ L->stacksize = realsize;
+ L->stack_last = L->stack+newsize;
+ correctstack(L, oldstack);
+}
+
+
+void luaD_reallocCI (lua_State *L, int newsize) {
+ CallInfo *oldci = L->base_ci;
+ luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
+ L->size_ci = newsize;
+ L->ci = (L->ci - oldci) + L->base_ci;
+ L->end_ci = L->base_ci + L->size_ci - 1;
+}
+
+
+void luaD_growstack (lua_State *L, int n) {
+ if (n <= L->stacksize) /* double size is enough? */
+ luaD_reallocstack(L, 2*L->stacksize);
+ else
+ luaD_reallocstack(L, L->stacksize + n);
+}
+
+
+static CallInfo *growCI (lua_State *L) {
+ if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */
+ luaD_throw(L, LUA_ERRERR);
+ else {
+ luaD_reallocCI(L, 2*L->size_ci);
+ if (L->size_ci > LUAI_MAXCALLS)
+ luaG_runerror(L, "stack overflow");
+ }
+ return ++L->ci;
+}
+
+
+void luaD_callhook (lua_State *L, int event, int line) {
+ lua_Hook hook = L->hook;
+ if (hook && L->allowhook) {
+ ptrdiff_t top = savestack(L, L->top);
+ ptrdiff_t ci_top = savestack(L, L->ci->top);
+ lua_Debug ar;
+ ar.event = event;
+ ar.currentline = line;
+ if (event == LUA_HOOKTAILRET)
+ ar.i_ci = 0; /* tail call; no debug information about it */
+ else
+ ar.i_ci = cast_int(L->ci - L->base_ci);
+ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
+ L->ci->top = L->top + LUA_MINSTACK;
+ lua_assert(L->ci->top <= L->stack_last);
+ L->allowhook = 0; /* cannot call hooks inside a hook */
+ lua_unlock(L);
+ (*hook)(L, &ar);
+ lua_lock(L);
+ lua_assert(!L->allowhook);
+ L->allowhook = 1;
+ L->ci->top = restorestack(L, ci_top);
+ L->top = restorestack(L, top);
+ }
+}
+
+
+static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
+ int i;
+ int nfixargs = p->numparams;
+ Table *htab = NULL;
+ StkId base, fixed;
+ for (; actual < nfixargs; ++actual)
+ setnilvalue(L->top++);
+#if defined(LUA_COMPAT_VARARG)
+ if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */
+ int nvar = actual - nfixargs; /* number of extra arguments */
+ lua_assert(p->is_vararg & VARARG_HASARG);
+ luaC_checkGC(L);
+ htab = luaH_new(L, nvar, 1); /* create `arg' table */
+ for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
+ setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
+ /* store counter in field `n' */
+ setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
+ }
+#endif
+ /* move fixed parameters to final position */
+ fixed = L->top - actual; /* first fixed argument */
+ base = L->top; /* final position of first argument */
+ for (i=0; i<nfixargs; i++) {
+ setobjs2s(L, L->top++, fixed+i);
+ setnilvalue(fixed+i);
+ }
+ /* add `arg' parameter */
+ if (htab) {
+ sethvalue(L, L->top++, htab);
+ lua_assert(iswhite(obj2gco(htab)));
+ }
+ return base;
+}
+
+
+static StkId tryfuncTM (lua_State *L, StkId func) {
+ const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
+ StkId p;
+ ptrdiff_t funcr = savestack(L, func);
+ if (!ttisfunction(tm))
+ luaG_typeerror(L, func, "call");
+ /* Open a hole inside the stack at `func' */
+ for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);
+ incr_top(L);
+ func = restorestack(L, funcr); /* previous call may change stack */
+ setobj2s(L, func, tm); /* tag method is the new function to be called */
+ return func;
+}
+
+
+
+#define inc_ci(L) \
+ ((L->ci == L->end_ci) ? growCI(L) : \
+ (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))
+
+
+int luaD_precall (lua_State *L, StkId func, int nresults) {
+ LClosure *cl;
+ ptrdiff_t funcr;
+ if (!ttisfunction(func)) /* `func' is not a function? */
+ func = tryfuncTM(L, func); /* check the `function' tag method */
+ funcr = savestack(L, func);
+ cl = &clvalue(func)->l;
+ L->ci->savedpc = L->savedpc;
+ if (!cl->isC) { /* Lua function? prepare its call */
+ CallInfo *ci;
+ StkId st, base;
+ Proto *p = cl->p;
+ luaD_checkstack(L, p->maxstacksize);
+ func = restorestack(L, funcr);
+ if (!p->is_vararg) { /* no varargs? */
+ base = func + 1;
+ if (L->top > base + p->numparams)
+ L->top = base + p->numparams;
+ }
+ else { /* vararg function */
+ int nargs = cast_int(L->top - func) - 1;
+ base = adjust_varargs(L, p, nargs);
+ func = restorestack(L, funcr); /* previous call may change the stack */
+ }
+ ci = inc_ci(L); /* now `enter' new function */
+ ci->func = func;
+ L->base = ci->base = base;
+ ci->top = L->base + p->maxstacksize;
+ lua_assert(ci->top <= L->stack_last);
+ L->savedpc = p->code; /* starting point */
+ ci->tailcalls = 0;
+ ci->nresults = nresults;
+ for (st = L->top; st < ci->top; st++)
+ setnilvalue(st);
+ L->top = ci->top;
+ if (L->hookmask & LUA_MASKCALL) {
+ L->savedpc++; /* hooks assume 'pc' is already incremented */
+ luaD_callhook(L, LUA_HOOKCALL, -1);
+ L->savedpc--; /* correct 'pc' */
+ }
+ return PCRLUA;
+ }
+ else { /* if is a C function, call it */
+ CallInfo *ci;
+ int n;
+ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
+ ci = inc_ci(L); /* now `enter' new function */
+ ci->func = restorestack(L, funcr);
+ L->base = ci->base = ci->func + 1;
+ ci->top = L->top + LUA_MINSTACK;
+ lua_assert(ci->top <= L->stack_last);
+ ci->nresults = nresults;
+ if (L->hookmask & LUA_MASKCALL)
+ luaD_callhook(L, LUA_HOOKCALL, -1);
+ lua_unlock(L);
+ n = (*curr_func(L)->c.f)(L); /* do the actual call */
+ lua_lock(L);
+ if (n < 0) /* yielding? */
+ return PCRYIELD;
+ else {
+ luaD_poscall(L, L->top - n);
+ return PCRC;
+ }
+ }
+}
+
+
+static StkId callrethooks (lua_State *L, StkId firstResult) {
+ ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */
+ luaD_callhook(L, LUA_HOOKRET, -1);
+ if (f_isLua(L->ci)) { /* Lua function? */
+ while (L->ci->tailcalls--) /* call hook for eventual tail calls */
+ luaD_callhook(L, LUA_HOOKTAILRET, -1);
+ }
+ return restorestack(L, fr);
+}
+
+
+int luaD_poscall (lua_State *L, StkId firstResult) {
+ StkId res;
+ int wanted, i;
+ CallInfo *ci;
+ if (L->hookmask & LUA_MASKRET)
+ firstResult = callrethooks(L, firstResult);
+ ci = L->ci--;
+ res = ci->func; /* res == final position of 1st result */
+ wanted = ci->nresults;
+ L->base = (ci - 1)->base; /* restore base */
+ L->savedpc = (ci - 1)->savedpc; /* restore savedpc */
+ /* move results to correct place */
+ for (i = wanted; i != 0 && firstResult < L->top; i--)
+ setobjs2s(L, res++, firstResult++);
+ while (i-- > 0)
+ setnilvalue(res++);
+ L->top = res;
+ return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */
+}
+
+
+/*
+** Call a function (C or Lua). The function to be called is at *func.
+** The arguments are on the stack, right after the function.
+** When returns, all the results are on the stack, starting at the original
+** function position.
+*/
+void luaD_call (lua_State *L, StkId func, int nResults) {
+ if (++L->nCcalls >= LUAI_MAXCCALLS) {
+ if (L->nCcalls == LUAI_MAXCCALLS)
+ luaG_runerror(L, "C stack overflow");
+ else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
+ luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
+ }
+ if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */
+ luaV_execute(L, 1); /* call it */
+ L->nCcalls--;
+ luaC_checkGC(L);
+}
+
+
+static void resume (lua_State *L, void *ud) {
+ StkId firstArg = cast(StkId, ud);
+ CallInfo *ci = L->ci;
+ if (L->status == 0) { /* start coroutine? */
+ lua_assert(ci == L->base_ci && firstArg > L->base);
+ if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)
+ return;
+ }
+ else { /* resuming from previous yield */
+ lua_assert(L->status == LUA_YIELD);
+ L->status = 0;
+ if (!f_isLua(ci)) { /* `common' yield? */
+ /* finish interrupted execution of `OP_CALL' */
+ lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||
+ GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);
+ if (luaD_poscall(L, firstArg)) /* complete it... */
+ L->top = L->ci->top; /* and correct top if not multiple results */
+ }
+ else /* yielded inside a hook: just continue its execution */
+ L->base = L->ci->base;
+ }
+ luaV_execute(L, cast_int(L->ci - L->base_ci));
+}
+
+
+static int resume_error (lua_State *L, const char *msg) {
+ L->top = L->ci->base;
+ setsvalue2s(L, L->top, luaS_new(L, msg));
+ incr_top(L);
+ lua_unlock(L);
+ return LUA_ERRRUN;
+}
+
+
+LUA_API int lua_resume (lua_State *L, int nargs) {
+ int status;
+ lua_lock(L);
+ if (L->status != LUA_YIELD) {
+ if (L->status != 0)
+ return resume_error(L, "cannot resume dead coroutine");
+ else if (L->ci != L->base_ci)
+ return resume_error(L, "cannot resume non-suspended coroutine");
+ }
+ luai_userstateresume(L, nargs);
+ lua_assert(L->errfunc == 0 && L->nCcalls == 0);
+ status = luaD_rawrunprotected(L, resume, L->top - nargs);
+ if (status != 0) { /* error? */
+ L->status = cast_byte(status); /* mark thread as `dead' */
+ luaD_seterrorobj(L, status, L->top);
+ L->ci->top = L->top;
+ }
+ else
+ status = L->status;
+ lua_unlock(L);
+ return status;
+}
+
+
+LUA_API int lua_yield (lua_State *L, int nresults) {
+ luai_userstateyield(L, nresults);
+ lua_lock(L);
+ if (L->nCcalls > 0)
+ luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
+ L->base = L->top - nresults; /* protect stack slots below */
+ L->status = LUA_YIELD;
+ lua_unlock(L);
+ return -1;
+}
+
+
+int luaD_pcall (lua_State *L, Pfunc func, void *u,
+ ptrdiff_t old_top, ptrdiff_t ef) {
+ int status;
+ unsigned short oldnCcalls = L->nCcalls;
+ ptrdiff_t old_ci = saveci(L, L->ci);
+ lu_byte old_allowhooks = L->allowhook;
+ ptrdiff_t old_errfunc = L->errfunc;
+ L->errfunc = ef;
+ status = luaD_rawrunprotected(L, func, u);
+ if (status != 0) { /* an error occurred? */
+ StkId oldtop = restorestack(L, old_top);
+ luaF_close(L, oldtop); /* close eventual pending closures */
+ luaD_seterrorobj(L, status, oldtop);
+ L->nCcalls = oldnCcalls;
+ L->ci = restoreci(L, old_ci);
+ L->base = L->ci->base;
+ L->savedpc = L->ci->savedpc;
+ L->allowhook = old_allowhooks;
+ restore_stack_limit(L);
+ }
+ L->errfunc = old_errfunc;
+ return status;
+}
+
+
+
+/*
+** Execute a protected parser.
+*/
+struct SParser { /* data to `f_parser' */
+ ZIO *z;
+ Mbuffer buff; /* buffer to be used by the scanner */
+ const char *name;
+};
+
+static void f_parser (lua_State *L, void *ud) {
+ int i;
+ Proto *tf;
+ Closure *cl;
+ struct SParser *p = cast(struct SParser *, ud);
+ int c = luaZ_lookahead(p->z);
+ luaC_checkGC(L);
+ tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
+ &p->buff, p->name);
+ cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
+ cl->l.p = tf;
+ for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */
+ cl->l.upvals[i] = luaF_newupval(L);
+ setclvalue(L, L->top, cl);
+ incr_top(L);
+}
+
+
+int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {
+ struct SParser p;
+ int status;
+ p.z = z; p.name = name;
+ luaZ_initbuffer(L, &p.buff);
+ status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
+ luaZ_freebuffer(L, &p.buff);
+ return status;
+}
+
+
diff --git a/Build/source/libs/lua51/ldo.h b/Build/source/libs/lua51/ldo.h
new file mode 100644
index 00000000000..b2de92bb807
--- /dev/null
+++ b/Build/source/libs/lua51/ldo.h
@@ -0,0 +1,57 @@
+/*
+** $Id: ldo.h,v 2.7 2005/08/24 16:15:49 roberto Exp $
+** Stack and Call structure of Lua
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ldo_h
+#define ldo_h
+
+
+#include "lobject.h"
+#include "lstate.h"
+#include "lzio.h"
+
+
+#define luaD_checkstack(L,n) \
+ if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \
+ luaD_growstack(L, n); \
+ else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1));
+
+
+#define incr_top(L) {luaD_checkstack(L,1); L->top++;}
+
+#define savestack(L,p) ((char *)(p) - (char *)L->stack)
+#define restorestack(L,n) ((TValue *)((char *)L->stack + (n)))
+
+#define saveci(L,p) ((char *)(p) - (char *)L->base_ci)
+#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n)))
+
+
+/* results from luaD_precall */
+#define PCRLUA 0 /* initiated a call to a Lua function */
+#define PCRC 1 /* did a call to a C function */
+#define PCRYIELD 2 /* C funtion yielded */
+
+
+/* type of protected functions, to be ran by `runprotected' */
+typedef void (*Pfunc) (lua_State *L, void *ud);
+
+LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name);
+LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line);
+LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);
+LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
+LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
+ ptrdiff_t oldtop, ptrdiff_t ef);
+LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);
+LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);
+LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
+LUAI_FUNC void luaD_growstack (lua_State *L, int n);
+
+LUAI_FUNC void luaD_throw (lua_State *L, int errcode);
+LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
+
+LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);
+
+#endif
+
diff --git a/Build/source/libs/lua51/ldump.c b/Build/source/libs/lua51/ldump.c
new file mode 100644
index 00000000000..f08277d3ac4
--- /dev/null
+++ b/Build/source/libs/lua51/ldump.c
@@ -0,0 +1,164 @@
+/*
+** $Id: ldump.c,v 1.15 2006/02/16 15:53:49 lhf Exp $
+** save precompiled Lua chunks
+** See Copyright Notice in lua.h
+*/
+
+#include <stddef.h>
+
+#define ldump_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lobject.h"
+#include "lstate.h"
+#include "lundump.h"
+
+typedef struct {
+ lua_State* L;
+ lua_Writer writer;
+ void* data;
+ int strip;
+ int status;
+} DumpState;
+
+#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D)
+#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D)
+
+static void DumpBlock(const void* b, size_t size, DumpState* D)
+{
+ if (D->status==0)
+ {
+ lua_unlock(D->L);
+ D->status=(*D->writer)(D->L,b,size,D->data);
+ lua_lock(D->L);
+ }
+}
+
+static void DumpChar(int y, DumpState* D)
+{
+ char x=(char)y;
+ DumpVar(x,D);
+}
+
+static void DumpInt(int x, DumpState* D)
+{
+ DumpVar(x,D);
+}
+
+static void DumpNumber(lua_Number x, DumpState* D)
+{
+ DumpVar(x,D);
+}
+
+static void DumpVector(const void* b, int n, size_t size, DumpState* D)
+{
+ DumpInt(n,D);
+ DumpMem(b,n,size,D);
+}
+
+static void DumpString(const TString* s, DumpState* D)
+{
+ if (s==NULL || getstr(s)==NULL)
+ {
+ size_t size=0;
+ DumpVar(size,D);
+ }
+ else
+ {
+ size_t size=s->tsv.len+1; /* include trailing '\0' */
+ DumpVar(size,D);
+ DumpBlock(getstr(s),size,D);
+ }
+}
+
+#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D)
+
+static void DumpFunction(const Proto* f, const TString* p, DumpState* D);
+
+static void DumpConstants(const Proto* f, DumpState* D)
+{
+ int i,n=f->sizek;
+ DumpInt(n,D);
+ for (i=0; i<n; i++)
+ {
+ const TValue* o=&f->k[i];
+ DumpChar(ttype(o),D);
+ switch (ttype(o))
+ {
+ case LUA_TNIL:
+ break;
+ case LUA_TBOOLEAN:
+ DumpChar(bvalue(o),D);
+ break;
+ case LUA_TNUMBER:
+ DumpNumber(nvalue(o),D);
+ break;
+ case LUA_TSTRING:
+ DumpString(rawtsvalue(o),D);
+ break;
+ default:
+ lua_assert(0); /* cannot happen */
+ break;
+ }
+ }
+ n=f->sizep;
+ DumpInt(n,D);
+ for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D);
+}
+
+static void DumpDebug(const Proto* f, DumpState* D)
+{
+ int i,n;
+ n= (D->strip) ? 0 : f->sizelineinfo;
+ DumpVector(f->lineinfo,n,sizeof(int),D);
+ n= (D->strip) ? 0 : f->sizelocvars;
+ DumpInt(n,D);
+ for (i=0; i<n; i++)
+ {
+ DumpString(f->locvars[i].varname,D);
+ DumpInt(f->locvars[i].startpc,D);
+ DumpInt(f->locvars[i].endpc,D);
+ }
+ n= (D->strip) ? 0 : f->sizeupvalues;
+ DumpInt(n,D);
+ for (i=0; i<n; i++) DumpString(f->upvalues[i],D);
+}
+
+static void DumpFunction(const Proto* f, const TString* p, DumpState* D)
+{
+ DumpString((f->source==p || D->strip) ? NULL : f->source,D);
+ DumpInt(f->linedefined,D);
+ DumpInt(f->lastlinedefined,D);
+ DumpChar(f->nups,D);
+ DumpChar(f->numparams,D);
+ DumpChar(f->is_vararg,D);
+ DumpChar(f->maxstacksize,D);
+ DumpCode(f,D);
+ DumpConstants(f,D);
+ DumpDebug(f,D);
+}
+
+static void DumpHeader(DumpState* D)
+{
+ char h[LUAC_HEADERSIZE];
+ luaU_header(h);
+ DumpBlock(h,LUAC_HEADERSIZE,D);
+}
+
+/*
+** dump Lua function as precompiled chunk
+*/
+int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
+{
+ DumpState D;
+ D.L=L;
+ D.writer=w;
+ D.data=data;
+ D.strip=strip;
+ D.status=0;
+ DumpHeader(&D);
+ DumpFunction(f,NULL,&D);
+ return D.status;
+}
diff --git a/Build/source/libs/lua51/lfunc.c b/Build/source/libs/lua51/lfunc.c
new file mode 100644
index 00000000000..05bd5ff50fa
--- /dev/null
+++ b/Build/source/libs/lua51/lfunc.c
@@ -0,0 +1,174 @@
+/*
+** $Id: lfunc.c,v 2.12a 2005/12/22 16:19:56 roberto Exp $
+** Auxiliary functions to manipulate prototypes and closures
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stddef.h>
+
+#define lfunc_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+
+
+
+Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) {
+ Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
+ luaC_link(L, obj2gco(c), LUA_TFUNCTION);
+ c->c.isC = 1;
+ c->c.env = e;
+ c->c.nupvalues = cast_byte(nelems);
+ return c;
+}
+
+
+Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) {
+ Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
+ luaC_link(L, obj2gco(c), LUA_TFUNCTION);
+ c->l.isC = 0;
+ c->l.env = e;
+ c->l.nupvalues = cast_byte(nelems);
+ while (nelems--) c->l.upvals[nelems] = NULL;
+ return c;
+}
+
+
+UpVal *luaF_newupval (lua_State *L) {
+ UpVal *uv = luaM_new(L, UpVal);
+ luaC_link(L, obj2gco(uv), LUA_TUPVAL);
+ uv->v = &uv->u.value;
+ setnilvalue(uv->v);
+ return uv;
+}
+
+
+UpVal *luaF_findupval (lua_State *L, StkId level) {
+ global_State *g = G(L);
+ GCObject **pp = &L->openupval;
+ UpVal *p;
+ UpVal *uv;
+ while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) {
+ lua_assert(p->v != &p->u.value);
+ if (p->v == level) { /* found a corresponding upvalue? */
+ if (isdead(g, obj2gco(p))) /* is it dead? */
+ changewhite(obj2gco(p)); /* ressurect it */
+ return p;
+ }
+ pp = &p->next;
+ }
+ uv = luaM_new(L, UpVal); /* not found: create a new one */
+ uv->tt = LUA_TUPVAL;
+ uv->marked = luaC_white(g);
+ uv->v = level; /* current value lives in the stack */
+ uv->next = *pp; /* chain it in the proper position */
+ *pp = obj2gco(uv);
+ uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */
+ uv->u.l.next = g->uvhead.u.l.next;
+ uv->u.l.next->u.l.prev = uv;
+ g->uvhead.u.l.next = uv;
+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+ return uv;
+}
+
+
+static void unlinkupval (UpVal *uv) {
+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+ uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */
+ uv->u.l.prev->u.l.next = uv->u.l.next;
+}
+
+
+void luaF_freeupval (lua_State *L, UpVal *uv) {
+ if (uv->v != &uv->u.value) /* is it open? */
+ unlinkupval(uv); /* remove from open list */
+ luaM_free(L, uv); /* free upvalue */
+}
+
+
+void luaF_close (lua_State *L, StkId level) {
+ UpVal *uv;
+ global_State *g = G(L);
+ while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) {
+ GCObject *o = obj2gco(uv);
+ lua_assert(!isblack(o) && uv->v != &uv->u.value);
+ L->openupval = uv->next; /* remove from `open' list */
+ if (isdead(g, o))
+ luaF_freeupval(L, uv); /* free upvalue */
+ else {
+ unlinkupval(uv);
+ setobj(L, &uv->u.value, uv->v);
+ uv->v = &uv->u.value; /* now current value lives here */
+ luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */
+ }
+ }
+}
+
+
+Proto *luaF_newproto (lua_State *L) {
+ Proto *f = luaM_new(L, Proto);
+ luaC_link(L, obj2gco(f), LUA_TPROTO);
+ f->k = NULL;
+ f->sizek = 0;
+ f->p = NULL;
+ f->sizep = 0;
+ f->code = NULL;
+ f->sizecode = 0;
+ f->sizelineinfo = 0;
+ f->sizeupvalues = 0;
+ f->nups = 0;
+ f->upvalues = NULL;
+ f->numparams = 0;
+ f->is_vararg = 0;
+ f->maxstacksize = 0;
+ f->lineinfo = NULL;
+ f->sizelocvars = 0;
+ f->locvars = NULL;
+ f->linedefined = 0;
+ f->lastlinedefined = 0;
+ f->source = NULL;
+ return f;
+}
+
+
+void luaF_freeproto (lua_State *L, Proto *f) {
+ luaM_freearray(L, f->code, f->sizecode, Instruction);
+ luaM_freearray(L, f->p, f->sizep, Proto *);
+ luaM_freearray(L, f->k, f->sizek, TValue);
+ luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
+ luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
+ luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
+ luaM_free(L, f);
+}
+
+
+void luaF_freeclosure (lua_State *L, Closure *c) {
+ int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :
+ sizeLclosure(c->l.nupvalues);
+ luaM_freemem(L, c, size);
+}
+
+
+/*
+** Look for n-th local variable at line `line' in function `func'.
+** Returns NULL if not found.
+*/
+const char *luaF_getlocalname (const Proto *f, int local_number, int pc) {
+ int i;
+ for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {
+ if (pc < f->locvars[i].endpc) { /* is variable active? */
+ local_number--;
+ if (local_number == 0)
+ return getstr(f->locvars[i].varname);
+ }
+ }
+ return NULL; /* not found */
+}
+
diff --git a/Build/source/libs/lua51/lfunc.h b/Build/source/libs/lua51/lfunc.h
new file mode 100644
index 00000000000..2e02419bd6b
--- /dev/null
+++ b/Build/source/libs/lua51/lfunc.h
@@ -0,0 +1,34 @@
+/*
+** $Id: lfunc.h,v 2.4 2005/04/25 19:24:10 roberto Exp $
+** Auxiliary functions to manipulate prototypes and closures
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lfunc_h
+#define lfunc_h
+
+
+#include "lobject.h"
+
+
+#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \
+ cast(int, sizeof(TValue)*((n)-1)))
+
+#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
+ cast(int, sizeof(TValue *)*((n)-1)))
+
+
+LUAI_FUNC Proto *luaF_newproto (lua_State *L);
+LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
+LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
+LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
+LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
+LUAI_FUNC void luaF_close (lua_State *L, StkId level);
+LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
+LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c);
+LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv);
+LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
+ int pc);
+
+
+#endif
diff --git a/Build/source/libs/lua51/lgc.c b/Build/source/libs/lua51/lgc.c
new file mode 100644
index 00000000000..2d24a127ac6
--- /dev/null
+++ b/Build/source/libs/lua51/lgc.c
@@ -0,0 +1,711 @@
+/*
+** $Id: lgc.c,v 2.38 2006/05/24 14:34:06 roberto Exp $
+** Garbage Collector
+** See Copyright Notice in lua.h
+*/
+
+#include <string.h>
+
+#define lgc_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+
+
+#define GCSTEPSIZE 1024u
+#define GCSWEEPMAX 40
+#define GCSWEEPCOST 10
+#define GCFINALIZECOST 100
+
+
+#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS))
+
+#define makewhite(g,x) \
+ ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g)))
+
+#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
+#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT)
+
+#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)
+
+
+#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT)
+#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT)
+
+
+#define KEYWEAK bitmask(KEYWEAKBIT)
+#define VALUEWEAK bitmask(VALUEWEAKBIT)
+
+
+
+#define markvalue(g,o) { checkconsistency(o); \
+ if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
+
+#define markobject(g,t) { if (iswhite(obj2gco(t))) \
+ reallymarkobject(g, obj2gco(t)); }
+
+
+#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause)
+
+
+static void removeentry (Node *n) {
+ lua_assert(ttisnil(gval(n)));
+ if (iscollectable(gkey(n)))
+ setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */
+}
+
+
+static void reallymarkobject (global_State *g, GCObject *o) {
+ lua_assert(iswhite(o) && !isdead(g, o));
+ white2gray(o);
+ switch (o->gch.tt) {
+ case LUA_TSTRING: {
+ return;
+ }
+ case LUA_TUSERDATA: {
+ Table *mt = gco2u(o)->metatable;
+ gray2black(o); /* udata are never gray */
+ if (mt) markobject(g, mt);
+ markobject(g, gco2u(o)->env);
+ return;
+ }
+ case LUA_TUPVAL: {
+ UpVal *uv = gco2uv(o);
+ markvalue(g, uv->v);
+ if (uv->v == &uv->u.value) /* closed? */
+ gray2black(o); /* open upvalues are never black */
+ return;
+ }
+ case LUA_TFUNCTION: {
+ gco2cl(o)->c.gclist = g->gray;
+ g->gray = o;
+ break;
+ }
+ case LUA_TTABLE: {
+ gco2h(o)->gclist = g->gray;
+ g->gray = o;
+ break;
+ }
+ case LUA_TTHREAD: {
+ gco2th(o)->gclist = g->gray;
+ g->gray = o;
+ break;
+ }
+ case LUA_TPROTO: {
+ gco2p(o)->gclist = g->gray;
+ g->gray = o;
+ break;
+ }
+ default: lua_assert(0);
+ }
+}
+
+
+static void marktmu (global_State *g) {
+ GCObject *u = g->tmudata;
+ if (u) {
+ do {
+ u = u->gch.next;
+ makewhite(g, u); /* may be marked, if left from previous GC */
+ reallymarkobject(g, u);
+ } while (u != g->tmudata);
+ }
+}
+
+
+/* move `dead' udata that need finalization to list `tmudata' */
+size_t luaC_separateudata (lua_State *L, int all) {
+ global_State *g = G(L);
+ size_t deadmem = 0;
+ GCObject **p = &g->mainthread->next;
+ GCObject *curr;
+ while ((curr = *p) != NULL) {
+ if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
+ p = &curr->gch.next; /* don't bother with them */
+ else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {
+ markfinalized(gco2u(curr)); /* don't need finalization */
+ p = &curr->gch.next;
+ }
+ else { /* must call its gc method */
+ deadmem += sizeudata(gco2u(curr));
+ markfinalized(gco2u(curr));
+ *p = curr->gch.next;
+ /* link `curr' at the end of `tmudata' list */
+ if (g->tmudata == NULL) /* list is empty? */
+ g->tmudata = curr->gch.next = curr; /* creates a circular list */
+ else {
+ curr->gch.next = g->tmudata->gch.next;
+ g->tmudata->gch.next = curr;
+ g->tmudata = curr;
+ }
+ }
+ }
+ return deadmem;
+}
+
+
+static int traversetable (global_State *g, Table *h) {
+ int i;
+ int weakkey = 0;
+ int weakvalue = 0;
+ const TValue *mode;
+ if (h->metatable)
+ markobject(g, h->metatable);
+ mode = gfasttm(g, h->metatable, TM_MODE);
+ if (mode && ttisstring(mode)) { /* is there a weak mode? */
+ weakkey = (strchr(svalue(mode), 'k') != NULL);
+ weakvalue = (strchr(svalue(mode), 'v') != NULL);
+ if (weakkey || weakvalue) { /* is really weak? */
+ h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */
+ h->marked |= cast_byte((weakkey << KEYWEAKBIT) |
+ (weakvalue << VALUEWEAKBIT));
+ h->gclist = g->weak; /* must be cleared after GC, ... */
+ g->weak = obj2gco(h); /* ... so put in the appropriate list */
+ }
+ }
+ if (weakkey && weakvalue) return 1;
+ if (!weakvalue) {
+ i = h->sizearray;
+ while (i--)
+ markvalue(g, &h->array[i]);
+ }
+ i = sizenode(h);
+ while (i--) {
+ Node *n = gnode(h, i);
+ lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n)));
+ if (ttisnil(gval(n)))
+ removeentry(n); /* remove empty entries */
+ else {
+ lua_assert(!ttisnil(gkey(n)));
+ if (!weakkey) markvalue(g, gkey(n));
+ if (!weakvalue) markvalue(g, gval(n));
+ }
+ }
+ return weakkey || weakvalue;
+}
+
+
+/*
+** All marks are conditional because a GC may happen while the
+** prototype is still being created
+*/
+static void traverseproto (global_State *g, Proto *f) {
+ int i;
+ if (f->source) stringmark(f->source);
+ for (i=0; i<f->sizek; i++) /* mark literals */
+ markvalue(g, &f->k[i]);
+ for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */
+ if (f->upvalues[i])
+ stringmark(f->upvalues[i]);
+ }
+ for (i=0; i<f->sizep; i++) { /* mark nested protos */
+ if (f->p[i])
+ markobject(g, f->p[i]);
+ }
+ for (i=0; i<f->sizelocvars; i++) { /* mark local-variable names */
+ if (f->locvars[i].varname)
+ stringmark(f->locvars[i].varname);
+ }
+}
+
+
+
+static void traverseclosure (global_State *g, Closure *cl) {
+ markobject(g, cl->c.env);
+ if (cl->c.isC) {
+ int i;
+ for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */
+ markvalue(g, &cl->c.upvalue[i]);
+ }
+ else {
+ int i;
+ lua_assert(cl->l.nupvalues == cl->l.p->nups);
+ markobject(g, cl->l.p);
+ for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */
+ markobject(g, cl->l.upvals[i]);
+ }
+}
+
+
+static void checkstacksizes (lua_State *L, StkId max) {
+ int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */
+ int s_used = cast_int(max - L->stack); /* part of stack in use */
+ if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */
+ return; /* do not touch the stacks */
+ if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
+ luaD_reallocCI(L, L->size_ci/2); /* still big enough... */
+ condhardstacktests(luaD_reallocCI(L, ci_used + 1));
+ if (4*s_used < L->stacksize &&
+ 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
+ luaD_reallocstack(L, L->stacksize/2); /* still big enough... */
+ condhardstacktests(luaD_reallocstack(L, s_used));
+}
+
+
+static void traversestack (global_State *g, lua_State *l) {
+ StkId o, lim;
+ CallInfo *ci;
+ markvalue(g, gt(l));
+ lim = l->top;
+ for (ci = l->base_ci; ci <= l->ci; ci++) {
+ lua_assert(ci->top <= l->stack_last);
+ if (lim < ci->top) lim = ci->top;
+ }
+ for (o = l->stack; o < l->top; o++)
+ markvalue(g, o);
+ for (; o <= lim; o++)
+ setnilvalue(o);
+ checkstacksizes(l, lim);
+}
+
+
+/*
+** traverse one gray object, turning it to black.
+** Returns `quantity' traversed.
+*/
+static l_mem propagatemark (global_State *g) {
+ GCObject *o = g->gray;
+ lua_assert(isgray(o));
+ gray2black(o);
+ switch (o->gch.tt) {
+ case LUA_TTABLE: {
+ Table *h = gco2h(o);
+ g->gray = h->gclist;
+ if (traversetable(g, h)) /* table is weak? */
+ black2gray(o); /* keep it gray */
+ return sizeof(Table) + sizeof(TValue) * h->sizearray +
+ sizeof(Node) * sizenode(h);
+ }
+ case LUA_TFUNCTION: {
+ Closure *cl = gco2cl(o);
+ g->gray = cl->c.gclist;
+ traverseclosure(g, cl);
+ return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
+ sizeLclosure(cl->l.nupvalues);
+ }
+ case LUA_TTHREAD: {
+ lua_State *th = gco2th(o);
+ g->gray = th->gclist;
+ th->gclist = g->grayagain;
+ g->grayagain = o;
+ black2gray(o);
+ traversestack(g, th);
+ return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
+ sizeof(CallInfo) * th->size_ci;
+ }
+ case LUA_TPROTO: {
+ Proto *p = gco2p(o);
+ g->gray = p->gclist;
+ traverseproto(g, p);
+ return sizeof(Proto) + sizeof(Instruction) * p->sizecode +
+ sizeof(Proto *) * p->sizep +
+ sizeof(TValue) * p->sizek +
+ sizeof(int) * p->sizelineinfo +
+ sizeof(LocVar) * p->sizelocvars +
+ sizeof(TString *) * p->sizeupvalues;
+ }
+ default: lua_assert(0); return 0;
+ }
+}
+
+
+static size_t propagateall (global_State *g) {
+ size_t m = 0;
+ while (g->gray) m += propagatemark(g);
+ return m;
+}
+
+
+/*
+** The next function tells whether a key or value can be cleared from
+** a weak table. Non-collectable objects are never removed from weak
+** tables. Strings behave as `values', so are never removed too. for
+** other objects: if really collected, cannot keep them; for userdata
+** being finalized, keep them in keys, but not in values
+*/
+static int iscleared (const TValue *o, int iskey) {
+ if (!iscollectable(o)) return 0;
+ if (ttisstring(o)) {
+ stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */
+ return 0;
+ }
+ return iswhite(gcvalue(o)) ||
+ (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o))));
+}
+
+
+/*
+** clear collected entries from weaktables
+*/
+static void cleartable (GCObject *l) {
+ while (l) {
+ Table *h = gco2h(l);
+ int i = h->sizearray;
+ lua_assert(testbit(h->marked, VALUEWEAKBIT) ||
+ testbit(h->marked, KEYWEAKBIT));
+ if (testbit(h->marked, VALUEWEAKBIT)) {
+ while (i--) {
+ TValue *o = &h->array[i];
+ if (iscleared(o, 0)) /* value was collected? */
+ setnilvalue(o); /* remove value */
+ }
+ }
+ i = sizenode(h);
+ while (i--) {
+ Node *n = gnode(h, i);
+ if (!ttisnil(gval(n)) && /* non-empty entry? */
+ (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) {
+ setnilvalue(gval(n)); /* remove value ... */
+ removeentry(n); /* remove entry from table */
+ }
+ }
+ l = h->gclist;
+ }
+}
+
+
+static void freeobj (lua_State *L, GCObject *o) {
+ switch (o->gch.tt) {
+ case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
+ case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;
+ case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
+ case LUA_TTABLE: luaH_free(L, gco2h(o)); break;
+ case LUA_TTHREAD: {
+ lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread);
+ luaE_freethread(L, gco2th(o));
+ break;
+ }
+ case LUA_TSTRING: {
+ G(L)->strt.nuse--;
+ luaM_freemem(L, o, sizestring(gco2ts(o)));
+ break;
+ }
+ case LUA_TUSERDATA: {
+ luaM_freemem(L, o, sizeudata(gco2u(o)));
+ break;
+ }
+ default: lua_assert(0);
+ }
+}
+
+
+
+#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM)
+
+
+static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
+ GCObject *curr;
+ global_State *g = G(L);
+ int deadmask = otherwhite(g);
+ while ((curr = *p) != NULL && count-- > 0) {
+ if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */
+ sweepwholelist(L, &gco2th(curr)->openupval);
+ if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */
+ lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));
+ makewhite(g, curr); /* make it white (for next cycle) */
+ p = &curr->gch.next;
+ }
+ else { /* must erase `curr' */
+ lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));
+ *p = curr->gch.next;
+ if (curr == g->rootgc) /* is the first element of the list? */
+ g->rootgc = curr->gch.next; /* adjust first */
+ freeobj(L, curr);
+ }
+ }
+ return p;
+}
+
+
+static void checkSizes (lua_State *L) {
+ global_State *g = G(L);
+ /* check size of string hash */
+ if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&
+ g->strt.size > MINSTRTABSIZE*2)
+ luaS_resize(L, g->strt.size/2); /* table is too big */
+ /* check size of buffer */
+ if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
+ size_t newsize = luaZ_sizebuffer(&g->buff) / 2;
+ luaZ_resizebuffer(L, &g->buff, newsize);
+ }
+}
+
+
+static void GCTM (lua_State *L) {
+ global_State *g = G(L);
+ GCObject *o = g->tmudata->gch.next; /* get first element */
+ Udata *udata = rawgco2u(o);
+ const TValue *tm;
+ /* remove udata from `tmudata' */
+ if (o == g->tmudata) /* last element? */
+ g->tmudata = NULL;
+ else
+ g->tmudata->gch.next = udata->uv.next;
+ udata->uv.next = g->mainthread->next; /* return it to `root' list */
+ g->mainthread->next = o;
+ makewhite(g, o);
+ tm = fasttm(L, udata->uv.metatable, TM_GC);
+ if (tm != NULL) {
+ lu_byte oldah = L->allowhook;
+ lu_mem oldt = g->GCthreshold;
+ L->allowhook = 0; /* stop debug hooks during GC tag method */
+ g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */
+ setobj2s(L, L->top, tm);
+ setuvalue(L, L->top+1, udata);
+ L->top += 2;
+ luaD_call(L, L->top - 2, 0);
+ L->allowhook = oldah; /* restore hooks */
+ g->GCthreshold = oldt; /* restore threshold */
+ }
+}
+
+
+/*
+** Call all GC tag methods
+*/
+void luaC_callGCTM (lua_State *L) {
+ while (G(L)->tmudata)
+ GCTM(L);
+}
+
+
+void luaC_freeall (lua_State *L) {
+ global_State *g = G(L);
+ int i;
+ g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */
+ sweepwholelist(L, &g->rootgc);
+ for (i = 0; i < g->strt.size; i++) /* free all string lists */
+ sweepwholelist(L, &g->strt.hash[i]);
+}
+
+
+static void markmt (global_State *g) {
+ int i;
+ for (i=0; i<NUM_TAGS; i++)
+ if (g->mt[i]) markobject(g, g->mt[i]);
+}
+
+
+/* mark root set */
+static void markroot (lua_State *L) {
+ global_State *g = G(L);
+ g->gray = NULL;
+ g->grayagain = NULL;
+ g->weak = NULL;
+ markobject(g, g->mainthread);
+ /* make global table be traversed before main stack */
+ markvalue(g, gt(g->mainthread));
+ markvalue(g, registry(L));
+ markmt(g);
+ g->gcstate = GCSpropagate;
+}
+
+
+static void remarkupvals (global_State *g) {
+ UpVal *uv;
+ for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+ if (isgray(obj2gco(uv)))
+ markvalue(g, uv->v);
+ }
+}
+
+
+static void atomic (lua_State *L) {
+ global_State *g = G(L);
+ size_t udsize; /* total size of userdata to be finalized */
+ /* remark occasional upvalues of (maybe) dead threads */
+ remarkupvals(g);
+ /* traverse objects cautch by write barrier and by 'remarkupvals' */
+ propagateall(g);
+ /* remark weak tables */
+ g->gray = g->weak;
+ g->weak = NULL;
+ lua_assert(!iswhite(obj2gco(g->mainthread)));
+ markobject(g, L); /* mark running thread */
+ markmt(g); /* mark basic metatables (again) */
+ propagateall(g);
+ /* remark gray again */
+ g->gray = g->grayagain;
+ g->grayagain = NULL;
+ propagateall(g);
+ udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */
+ marktmu(g); /* mark `preserved' userdata */
+ udsize += propagateall(g); /* remark, to propagate `preserveness' */
+ cleartable(g->weak); /* remove collected objects from weak tables */
+ /* flip current white */
+ g->currentwhite = cast_byte(otherwhite(g));
+ g->sweepstrgc = 0;
+ g->sweepgc = &g->rootgc;
+ g->gcstate = GCSsweepstring;
+ g->estimate = g->totalbytes - udsize; /* first estimate */
+}
+
+
+static l_mem singlestep (lua_State *L) {
+ global_State *g = G(L);
+ /*lua_checkmemory(L);*/
+ switch (g->gcstate) {
+ case GCSpause: {
+ markroot(L); /* start a new collection */
+ return 0;
+ }
+ case GCSpropagate: {
+ if (g->gray)
+ return propagatemark(g);
+ else { /* no more `gray' objects */
+ atomic(L); /* finish mark phase */
+ return 0;
+ }
+ }
+ case GCSsweepstring: {
+ lu_mem old = g->totalbytes;
+ sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
+ if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */
+ g->gcstate = GCSsweep; /* end sweep-string phase */
+ lua_assert(old >= g->totalbytes);
+ g->estimate -= old - g->totalbytes;
+ return GCSWEEPCOST;
+ }
+ case GCSsweep: {
+ lu_mem old = g->totalbytes;
+ g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
+ if (*g->sweepgc == NULL) { /* nothing more to sweep? */
+ checkSizes(L);
+ g->gcstate = GCSfinalize; /* end sweep phase */
+ }
+ lua_assert(old >= g->totalbytes);
+ g->estimate -= old - g->totalbytes;
+ return GCSWEEPMAX*GCSWEEPCOST;
+ }
+ case GCSfinalize: {
+ if (g->tmudata) {
+ GCTM(L);
+ if (g->estimate > GCFINALIZECOST)
+ g->estimate -= GCFINALIZECOST;
+ return GCFINALIZECOST;
+ }
+ else {
+ g->gcstate = GCSpause; /* end collection */
+ g->gcdept = 0;
+ return 0;
+ }
+ }
+ default: lua_assert(0); return 0;
+ }
+}
+
+
+void luaC_step (lua_State *L) {
+ global_State *g = G(L);
+ l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
+ if (lim == 0)
+ lim = (MAX_LUMEM-1)/2; /* no limit */
+ g->gcdept += g->totalbytes - g->GCthreshold;
+ do {
+ lim -= singlestep(L);
+ if (g->gcstate == GCSpause)
+ break;
+ } while (lim > 0);
+ if (g->gcstate != GCSpause) {
+ if (g->gcdept < GCSTEPSIZE)
+ g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/
+ else {
+ g->gcdept -= GCSTEPSIZE;
+ g->GCthreshold = g->totalbytes;
+ }
+ }
+ else {
+ lua_assert(g->totalbytes >= g->estimate);
+ setthreshold(g);
+ }
+}
+
+
+void luaC_fullgc (lua_State *L) {
+ global_State *g = G(L);
+ if (g->gcstate <= GCSpropagate) {
+ /* reset sweep marks to sweep all elements (returning them to white) */
+ g->sweepstrgc = 0;
+ g->sweepgc = &g->rootgc;
+ /* reset other collector lists */
+ g->gray = NULL;
+ g->grayagain = NULL;
+ g->weak = NULL;
+ g->gcstate = GCSsweepstring;
+ }
+ lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate);
+ /* finish any pending sweep phase */
+ while (g->gcstate != GCSfinalize) {
+ lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
+ singlestep(L);
+ }
+ markroot(L);
+ while (g->gcstate != GCSpause) {
+ singlestep(L);
+ }
+ setthreshold(g);
+}
+
+
+void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
+ global_State *g = G(L);
+ lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
+ lua_assert(ttype(&o->gch) != LUA_TTABLE);
+ /* must keep invariant? */
+ if (g->gcstate == GCSpropagate)
+ reallymarkobject(g, v); /* restore invariant */
+ else /* don't mind */
+ makewhite(g, o); /* mark as white just to avoid other barriers */
+}
+
+
+void luaC_barrierback (lua_State *L, Table *t) {
+ global_State *g = G(L);
+ GCObject *o = obj2gco(t);
+ lua_assert(isblack(o) && !isdead(g, o));
+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
+ black2gray(o); /* make table gray (again) */
+ t->gclist = g->grayagain;
+ g->grayagain = o;
+}
+
+
+void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
+ global_State *g = G(L);
+ o->gch.next = g->rootgc;
+ g->rootgc = o;
+ o->gch.marked = luaC_white(g);
+ o->gch.tt = tt;
+}
+
+
+void luaC_linkupval (lua_State *L, UpVal *uv) {
+ global_State *g = G(L);
+ GCObject *o = obj2gco(uv);
+ o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */
+ g->rootgc = o;
+ if (isgray(o)) {
+ if (g->gcstate == GCSpropagate) {
+ gray2black(o); /* closed upvalues need barrier */
+ luaC_barrier(L, uv, uv->v);
+ }
+ else { /* sweep phase: sweep it (turning it into white) */
+ makewhite(g, o);
+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
+ }
+ }
+}
+
diff --git a/Build/source/libs/lua51/lgc.h b/Build/source/libs/lua51/lgc.h
new file mode 100644
index 00000000000..5f69acb1e3b
--- /dev/null
+++ b/Build/source/libs/lua51/lgc.h
@@ -0,0 +1,110 @@
+/*
+** $Id: lgc.h,v 2.15 2005/08/24 16:15:49 roberto Exp $
+** Garbage Collector
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lgc_h
+#define lgc_h
+
+
+#include "lobject.h"
+
+
+/*
+** Possible states of the Garbage Collector
+*/
+#define GCSpause 0
+#define GCSpropagate 1
+#define GCSsweepstring 2
+#define GCSsweep 3
+#define GCSfinalize 4
+
+
+/*
+** some userful bit tricks
+*/
+#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m)))
+#define setbits(x,m) ((x) |= (m))
+#define testbits(x,m) ((x) & (m))
+#define bitmask(b) (1<<(b))
+#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2))
+#define l_setbit(x,b) setbits(x, bitmask(b))
+#define resetbit(x,b) resetbits(x, bitmask(b))
+#define testbit(x,b) testbits(x, bitmask(b))
+#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2)))
+#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2)))
+#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2)))
+
+
+
+/*
+** Layout for bit use in `marked' field:
+** bit 0 - object is white (type 0)
+** bit 1 - object is white (type 1)
+** bit 2 - object is black
+** bit 3 - for userdata: has been finalized
+** bit 3 - for tables: has weak keys
+** bit 4 - for tables: has weak values
+** bit 5 - object is fixed (should not be collected)
+** bit 6 - object is "super" fixed (only the main thread)
+*/
+
+
+#define WHITE0BIT 0
+#define WHITE1BIT 1
+#define BLACKBIT 2
+#define FINALIZEDBIT 3
+#define KEYWEAKBIT 3
+#define VALUEWEAKBIT 4
+#define FIXEDBIT 5
+#define SFIXEDBIT 6
+#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
+
+
+#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
+#define isblack(x) testbit((x)->gch.marked, BLACKBIT)
+#define isgray(x) (!isblack(x) && !iswhite(x))
+
+#define otherwhite(g) (g->currentwhite ^ WHITEBITS)
+#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS)
+
+#define changewhite(x) ((x)->gch.marked ^= WHITEBITS)
+#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT)
+
+#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x)))
+
+#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
+
+
+#define luaC_checkGC(L) { \
+ condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \
+ if (G(L)->totalbytes >= G(L)->GCthreshold) \
+ luaC_step(L); }
+
+
+#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \
+ luaC_barrierf(L,obj2gco(p),gcvalue(v)); }
+
+#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \
+ luaC_barrierback(L,t); }
+
+#define luaC_objbarrier(L,p,o) \
+ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \
+ luaC_barrierf(L,obj2gco(p),obj2gco(o)); }
+
+#define luaC_objbarriert(L,t,o) \
+ { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); }
+
+LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all);
+LUAI_FUNC void luaC_callGCTM (lua_State *L);
+LUAI_FUNC void luaC_freeall (lua_State *L);
+LUAI_FUNC void luaC_step (lua_State *L);
+LUAI_FUNC void luaC_fullgc (lua_State *L);
+LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
+LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);
+LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);
+LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t);
+
+
+#endif
diff --git a/Build/source/libs/lua51/linit.c b/Build/source/libs/lua51/linit.c
new file mode 100644
index 00000000000..483d9c8c282
--- /dev/null
+++ b/Build/source/libs/lua51/linit.c
@@ -0,0 +1,38 @@
+/*
+** $Id: linit.c,v 1.14 2005/12/29 15:32:11 roberto Exp $
+** Initialization of libraries for lua.c
+** See Copyright Notice in lua.h
+*/
+
+
+#define linit_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lualib.h"
+#include "lauxlib.h"
+
+
+static const luaL_Reg lualibs[] = {
+ {"", luaopen_base},
+ {LUA_LOADLIBNAME, luaopen_package},
+ {LUA_TABLIBNAME, luaopen_table},
+ {LUA_IOLIBNAME, luaopen_io},
+ {LUA_OSLIBNAME, luaopen_os},
+ {LUA_STRLIBNAME, luaopen_string},
+ {LUA_MATHLIBNAME, luaopen_math},
+ {LUA_DBLIBNAME, luaopen_debug},
+ {NULL, NULL}
+};
+
+
+LUALIB_API void luaL_openlibs (lua_State *L) {
+ const luaL_Reg *lib = lualibs;
+ for (; lib->func; lib++) {
+ lua_pushcfunction(L, lib->func);
+ lua_pushstring(L, lib->name);
+ lua_call(L, 1, 0);
+ }
+}
+
diff --git a/Build/source/libs/lua51/liolib.c b/Build/source/libs/lua51/liolib.c
new file mode 100644
index 00000000000..c009946079e
--- /dev/null
+++ b/Build/source/libs/lua51/liolib.c
@@ -0,0 +1,572 @@
+/*
+** $Id: liolib.c,v 2.73 2006/05/08 20:14:16 roberto Exp $
+** Standard I/O (and system) library
+** See Copyright Notice in lua.h
+*/
+
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define liolib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+
+#define IO_INPUT 1
+#define IO_OUTPUT 2
+
+
+static const char *const fnames[] = {"input", "output"};
+
+
+static int pushresult (lua_State *L, int i, const char *filename) {
+ int en = errno; /* calls to Lua API may change this value */
+ if (i) {
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+ else {
+ lua_pushnil(L);
+ if (filename)
+ lua_pushfstring(L, "%s: %s", filename, strerror(en));
+ else
+ lua_pushfstring(L, "%s", strerror(en));
+ lua_pushinteger(L, en);
+ return 3;
+ }
+}
+
+
+static void fileerror (lua_State *L, int arg, const char *filename) {
+ lua_pushfstring(L, "%s: %s", filename, strerror(errno));
+ luaL_argerror(L, arg, lua_tostring(L, -1));
+}
+
+
+#define topfile(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
+
+
+static int io_type (lua_State *L) {
+ void *ud;
+ luaL_checkany(L, 1);
+ ud = lua_touserdata(L, 1);
+ lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
+ if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
+ lua_pushnil(L); /* not a file */
+ else if (*((FILE **)ud) == NULL)
+ lua_pushliteral(L, "closed file");
+ else
+ lua_pushliteral(L, "file");
+ return 1;
+}
+
+
+static FILE *tofile (lua_State *L) {
+ FILE **f = topfile(L);
+ if (*f == NULL)
+ luaL_error(L, "attempt to use a closed file");
+ return *f;
+}
+
+
+
+/*
+** When creating file handles, always creates a `closed' file handle
+** before opening the actual file; so, if there is a memory error, the
+** file is not left opened.
+*/
+static FILE **newfile (lua_State *L) {
+ FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
+ *pf = NULL; /* file handle is currently `closed' */
+ luaL_getmetatable(L, LUA_FILEHANDLE);
+ lua_setmetatable(L, -2);
+ return pf;
+}
+
+
+/*
+** this function has a separated environment, which defines the
+** correct __close for 'popen' files
+*/
+static int io_pclose (lua_State *L) {
+ FILE **p = topfile(L);
+ int ok = lua_pclose(L, *p);
+ *p = NULL;
+ return pushresult(L, ok, NULL);
+}
+
+
+static int io_fclose (lua_State *L) {
+ FILE **p = topfile(L);
+ int ok = (fclose(*p) == 0);
+ *p = NULL;
+ return pushresult(L, ok, NULL);
+}
+
+
+static int aux_close (lua_State *L) {
+ lua_getfenv(L, 1);
+ lua_getfield(L, -1, "__close");
+ return (lua_tocfunction(L, -1))(L);
+}
+
+
+static int io_close (lua_State *L) {
+ if (lua_isnone(L, 1))
+ lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);
+ tofile(L); /* make sure argument is a file */
+ return aux_close(L);
+}
+
+
+static int io_gc (lua_State *L) {
+ FILE *f = *topfile(L);
+ /* ignore closed files and standard files */
+ if (f != NULL && f != stdin && f != stdout && f != stderr)
+ aux_close(L);
+ return 0;
+}
+
+
+static int io_tostring (lua_State *L) {
+ FILE *f = *topfile(L);
+ if (f == NULL)
+ lua_pushstring(L, "file (closed)");
+ else
+ lua_pushfstring(L, "file (%p)", f);
+ return 1;
+}
+
+
+static int io_open (lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ const char *mode = luaL_optstring(L, 2, "r");
+ FILE **pf = newfile(L);
+ *pf = fopen(filename, mode);
+ return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
+}
+
+static int io_open_ro (lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ const char *mode = luaL_optstring(L, 2, "r");
+ if ((strcmp(mode,"r")!= 0)&&(strcmp(mode,"rb")!=0))
+ return pushresult(L, 0, filename);
+ FILE **pf = newfile(L);
+ *pf = fopen(filename, mode);
+ return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
+}
+
+
+
+
+
+static int io_popen (lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ const char *mode = luaL_optstring(L, 2, "r");
+ FILE **pf = newfile(L);
+ *pf = lua_popen(L, filename, mode);
+ return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
+}
+
+
+static int io_tmpfile (lua_State *L) {
+ FILE **pf = newfile(L);
+ *pf = tmpfile();
+ return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;
+}
+
+
+static FILE *getiofile (lua_State *L, int findex) {
+ FILE *f;
+ lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
+ f = *(FILE **)lua_touserdata(L, -1);
+ if (f == NULL)
+ luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
+ return f;
+}
+
+
+static int g_iofile (lua_State *L, int f, const char *mode) {
+ if (!lua_isnoneornil(L, 1)) {
+ const char *filename = lua_tostring(L, 1);
+ if (filename) {
+ FILE **pf = newfile(L);
+ *pf = fopen(filename, mode);
+ if (*pf == NULL)
+ fileerror(L, 1, filename);
+ }
+ else {
+ tofile(L); /* check that it's a valid file handle */
+ lua_pushvalue(L, 1);
+ }
+ lua_rawseti(L, LUA_ENVIRONINDEX, f);
+ }
+ /* return current value */
+ lua_rawgeti(L, LUA_ENVIRONINDEX, f);
+ return 1;
+}
+
+
+static int io_input (lua_State *L) {
+ return g_iofile(L, IO_INPUT, "r");
+}
+
+
+static int io_output (lua_State *L) {
+ return g_iofile(L, IO_OUTPUT, "w");
+}
+
+
+static int io_readline (lua_State *L);
+
+
+static void aux_lines (lua_State *L, int idx, int toclose) {
+ lua_pushvalue(L, idx);
+ lua_pushboolean(L, toclose); /* close/not close file when finished */
+ lua_pushcclosure(L, io_readline, 2);
+}
+
+
+static int f_lines (lua_State *L) {
+ tofile(L); /* check that it's a valid file handle */
+ aux_lines(L, 1, 0);
+ return 1;
+}
+
+
+static int io_lines (lua_State *L) {
+ if (lua_isnoneornil(L, 1)) { /* no arguments? */
+ /* will iterate over default input */
+ lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
+ return f_lines(L);
+ }
+ else {
+ const char *filename = luaL_checkstring(L, 1);
+ FILE **pf = newfile(L);
+ *pf = fopen(filename, "r");
+ if (*pf == NULL)
+ fileerror(L, 1, filename);
+ aux_lines(L, lua_gettop(L), 1);
+ return 1;
+ }
+}
+
+
+/*
+** {======================================================
+** READ
+** =======================================================
+*/
+
+
+static int read_number (lua_State *L, FILE *f) {
+ lua_Number d;
+ if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
+ lua_pushnumber(L, d);
+ return 1;
+ }
+ else return 0; /* read fails */
+}
+
+
+static int test_eof (lua_State *L, FILE *f) {
+ int c = getc(f);
+ ungetc(c, f);
+ lua_pushlstring(L, NULL, 0);
+ return (c != EOF);
+}
+
+#if 0
+static int read_line (lua_State *L, FILE *f) {
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ for (;;) {
+ size_t l;
+ char *p = luaL_prepbuffer(&b);
+ if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */
+ luaL_pushresult(&b); /* close buffer */
+ return (lua_strlen(L, -1) > 0); /* check whether read something */
+ }
+ l = strlen(p);
+ if (l == 0 || p[l-1] != '\n')
+ luaL_addsize(&b, l);
+ else {
+ luaL_addsize(&b, l - 1); /* do not include `eol' */
+ luaL_pushresult(&b); /* close buffer */
+ return 1; /* read at least an `eol' */
+ }
+ }
+}
+#endif
+
+/* this new version does not care wether the file has
+ line endings using an 'alien' convention */
+
+static int new_read_line (lua_State *L, FILE *f) {
+ luaL_Buffer buf;
+ int c, d;
+ luaL_buffinit(L, &buf);
+ while (1) {
+ c = fgetc(f);
+ if (c == EOF) {
+ luaL_pushresult(&buf); /* close buffer */
+ return (lua_strlen(L, -1) > 0); /* check whether read something */
+ };
+ if (c == '\n') {
+ break;
+ } else if (c == '\r') {
+ d = fgetc(f);
+ if (d != EOF && d != '\n')
+ ungetc(d,f);
+ break;
+ } else {
+ luaL_addchar(&buf,c);
+ }
+ }
+ luaL_pushresult(&buf); /* close buffer */
+ return 1;
+}
+
+
+static int read_chars (lua_State *L, FILE *f, size_t n) {
+ size_t rlen; /* how much to read */
+ size_t nr; /* number of chars actually read */
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ rlen = LUAL_BUFFERSIZE; /* try to read that much each time */
+ do {
+ char *p = luaL_prepbuffer(&b);
+ if (rlen > n) rlen = n; /* cannot read more than asked */
+ nr = fread(p, sizeof(char), rlen, f);
+ luaL_addsize(&b, nr);
+ n -= nr; /* still have to read `n' chars */
+ } while (n > 0 && nr == rlen); /* until end of count or eof */
+ luaL_pushresult(&b); /* close buffer */
+ return (n == 0 || lua_strlen(L, -1) > 0);
+}
+
+
+static int g_read (lua_State *L, FILE *f, int first) {
+ int nargs = lua_gettop(L) - 1;
+ int success;
+ int n;
+ clearerr(f);
+ if (nargs == 0) { /* no arguments? */
+ success = new_read_line(L, f);
+ n = first+1; /* to return 1 result */
+ }
+ else { /* ensure stack space for all results and for auxlib's buffer */
+ luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
+ success = 1;
+ for (n = first; nargs-- && success; n++) {
+ if (lua_type(L, n) == LUA_TNUMBER) {
+ size_t l = (size_t)lua_tointeger(L, n);
+ success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
+ }
+ else {
+ const char *p = lua_tostring(L, n);
+ luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
+ switch (p[1]) {
+ case 'n': /* number */
+ success = read_number(L, f);
+ break;
+ case 'l': /* line */
+ success = new_read_line(L, f);
+ break;
+ case 'a': /* file */
+ read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */
+ success = 1; /* always success */
+ break;
+ default:
+ return luaL_argerror(L, n, "invalid format");
+ }
+ }
+ }
+ }
+ if (ferror(f))
+ return pushresult(L, 0, NULL);
+ if (!success) {
+ lua_pop(L, 1); /* remove last result */
+ lua_pushnil(L); /* push nil instead */
+ }
+ return n - first;
+}
+
+static int io_read (lua_State *L) {
+ return g_read(L, getiofile(L, IO_INPUT), 1);
+}
+
+static int f_read (lua_State *L) {
+ return g_read(L, tofile(L), 2);
+}
+
+static int io_readline (lua_State *L) {
+ FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));
+ int sucess;
+ if (f == NULL) /* file is already closed? */
+ luaL_error(L, "file is already closed");
+ sucess = new_read_line(L, f);
+ if (ferror(f))
+ return luaL_error(L, "%s", strerror(errno));
+ if (sucess) return 1;
+ else { /* EOF */
+ if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */
+ lua_settop(L, 0);
+ lua_pushvalue(L, lua_upvalueindex(1));
+ aux_close(L); /* close it */
+ }
+ return 0;
+ }
+}
+
+/* }====================================================== */
+
+
+static int g_write (lua_State *L, FILE *f, int arg) {
+ int nargs = lua_gettop(L) - 1;
+ int status = 1;
+ for (; nargs--; arg++) {
+ if (lua_type(L, arg) == LUA_TNUMBER) {
+ /* optimization: could be done exactly as for strings */
+ status = status &&
+ fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+ }
+ else {
+ size_t l;
+ const char *s = luaL_checklstring(L, arg, &l);
+ status = status && (fwrite(s, sizeof(char), l, f) == l);
+ }
+ }
+ return pushresult(L, status, NULL);
+}
+
+
+static int io_write (lua_State *L) {
+ return g_write(L, getiofile(L, IO_OUTPUT), 1);
+}
+
+
+static int f_write (lua_State *L) {
+ return g_write(L, tofile(L), 2);
+}
+
+
+static int f_seek (lua_State *L) {
+ static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
+ static const char *const modenames[] = {"set", "cur", "end", NULL};
+ FILE *f = tofile(L);
+ int op = luaL_checkoption(L, 2, "cur", modenames);
+ long offset = luaL_optlong(L, 3, 0);
+ op = fseek(f, offset, mode[op]);
+ if (op)
+ return pushresult(L, 0, NULL); /* error */
+ else {
+ lua_pushinteger(L, ftell(f));
+ return 1;
+ }
+}
+
+
+static int f_setvbuf (lua_State *L) {
+ static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
+ static const char *const modenames[] = {"no", "full", "line", NULL};
+ FILE *f = tofile(L);
+ int op = luaL_checkoption(L, 2, NULL, modenames);
+ lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
+ int res = setvbuf(f, NULL, mode[op], sz);
+ return pushresult(L, res == 0, NULL);
+}
+
+
+
+static int io_flush (lua_State *L) {
+ return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
+}
+
+
+static int f_flush (lua_State *L) {
+ return pushresult(L, fflush(tofile(L)) == 0, NULL);
+}
+
+
+static const luaL_Reg iolib[] = {
+ {"close", io_close},
+ {"flush", io_flush},
+ {"input", io_input},
+ {"lines", io_lines},
+ {"open", io_open},
+ {"open_ro", io_open_ro},
+ {"output", io_output},
+ {"popen", io_popen},
+ {"read", io_read},
+ {"tmpfile", io_tmpfile},
+ {"type", io_type},
+ {"write", io_write},
+ {NULL, NULL}
+};
+
+
+static const luaL_Reg flib[] = {
+ {"close", io_close},
+ {"flush", f_flush},
+ {"lines", f_lines},
+ {"read", f_read},
+ {"seek", f_seek},
+ {"setvbuf", f_setvbuf},
+ {"write", f_write},
+ {"__gc", io_gc},
+ {"__tostring", io_tostring},
+ {NULL, NULL}
+};
+
+
+static void createmeta (lua_State *L) {
+ luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
+ lua_pushvalue(L, -1); /* push metatable */
+ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
+ luaL_register(L, NULL, flib); /* file methods */
+}
+
+
+static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
+ *newfile(L) = f;
+ if (k > 0) {
+ lua_pushvalue(L, -1);
+ lua_rawseti(L, LUA_ENVIRONINDEX, k);
+ }
+ lua_setfield(L, -2, fname);
+}
+
+
+LUALIB_API int luaopen_io (lua_State *L) {
+ createmeta(L);
+ /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
+ lua_createtable(L, 2, 1);
+ lua_replace(L, LUA_ENVIRONINDEX);
+ /* open library */
+ luaL_register(L, LUA_IOLIBNAME, iolib);
+ /* create (and set) default files */
+ createstdfile(L, stdin, IO_INPUT, "stdin");
+ createstdfile(L, stdout, IO_OUTPUT, "stdout");
+ createstdfile(L, stderr, 0, "stderr");
+ /* create environment for 'popen' */
+ lua_getfield(L, -1, "popen");
+ lua_createtable(L, 0, 1);
+ lua_pushcfunction(L, io_pclose);
+ lua_setfield(L, -2, "__close");
+ lua_setfenv(L, -2);
+ lua_pop(L, 1); /* pop 'popen' */
+ /* set default close function */
+ lua_pushcfunction(L, io_fclose);
+ lua_setfield(L, LUA_ENVIRONINDEX, "__close");
+ return 1;
+}
+
diff --git a/Build/source/libs/lua51/llex.c b/Build/source/libs/lua51/llex.c
new file mode 100644
index 00000000000..1c07cad9bb6
--- /dev/null
+++ b/Build/source/libs/lua51/llex.c
@@ -0,0 +1,461 @@
+/*
+** $Id: llex.c,v 2.20 2006/03/09 18:14:31 roberto Exp $
+** Lexical Analyzer
+** See Copyright Notice in lua.h
+*/
+
+
+#include <ctype.h>
+#include <locale.h>
+#include <string.h>
+
+#define llex_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldo.h"
+#include "llex.h"
+#include "lobject.h"
+#include "lparser.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "lzio.h"
+
+
+
+#define next(ls) (ls->current = zgetc(ls->z))
+
+
+
+
+#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r')
+
+
+/* ORDER RESERVED */
+const char *const luaX_tokens [] = {
+ "and", "break", "do", "else", "elseif",
+ "end", "false", "for", "function", "if",
+ "in", "local", "nil", "not", "or", "repeat",
+ "return", "then", "true", "until", "while",
+ "..", "...", "==", ">=", "<=", "~=",
+ "<number>", "<name>", "<string>", "<eof>",
+ NULL
+};
+
+
+#define save_and_next(ls) (save(ls, ls->current), next(ls))
+
+
+static void save (LexState *ls, int c) {
+ Mbuffer *b = ls->buff;
+ if (b->n + 1 > b->buffsize) {
+ size_t newsize;
+ if (b->buffsize >= MAX_SIZET/2)
+ luaX_lexerror(ls, "lexical element too long", 0);
+ newsize = b->buffsize * 2;
+ luaZ_resizebuffer(ls->L, b, newsize);
+ }
+ b->buffer[b->n++] = cast(char, c);
+}
+
+
+void luaX_init (lua_State *L) {
+ int i;
+ for (i=0; i<NUM_RESERVED; i++) {
+ TString *ts = luaS_new(L, luaX_tokens[i]);
+ luaS_fix(ts); /* reserved words are never collected */
+ lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN);
+ ts->tsv.reserved = cast_byte(i+1); /* reserved word */
+ }
+}
+
+
+#define MAXSRC 80
+
+
+const char *luaX_token2str (LexState *ls, int token) {
+ if (token < FIRST_RESERVED) {
+ lua_assert(token == cast(unsigned char, token));
+ return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) :
+ luaO_pushfstring(ls->L, "%c", token);
+ }
+ else
+ return luaX_tokens[token-FIRST_RESERVED];
+}
+
+
+static const char *txtToken (LexState *ls, int token) {
+ switch (token) {
+ case TK_NAME:
+ case TK_STRING:
+ case TK_NUMBER:
+ save(ls, '\0');
+ return luaZ_buffer(ls->buff);
+ default:
+ return luaX_token2str(ls, token);
+ }
+}
+
+
+void luaX_lexerror (LexState *ls, const char *msg, int token) {
+ char buff[MAXSRC];
+ luaO_chunkid(buff, getstr(ls->source), MAXSRC);
+ msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg);
+ if (token)
+ luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token));
+ luaD_throw(ls->L, LUA_ERRSYNTAX);
+}
+
+
+void luaX_syntaxerror (LexState *ls, const char *msg) {
+ luaX_lexerror(ls, msg, ls->t.token);
+}
+
+
+TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
+ lua_State *L = ls->L;
+ TString *ts = luaS_newlstr(L, str, l);
+ TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */
+ if (ttisnil(o))
+ setbvalue(o, 1); /* make sure `str' will not be collected */
+ return ts;
+}
+
+
+static void inclinenumber (LexState *ls) {
+ int old = ls->current;
+ lua_assert(currIsNewline(ls));
+ next(ls); /* skip `\n' or `\r' */
+ if (currIsNewline(ls) && ls->current != old)
+ next(ls); /* skip `\n\r' or `\r\n' */
+ if (++ls->linenumber >= MAX_INT)
+ luaX_syntaxerror(ls, "chunk has too many lines");
+}
+
+
+void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) {
+ ls->decpoint = '.';
+ ls->L = L;
+ ls->lookahead.token = TK_EOS; /* no look-ahead token */
+ ls->z = z;
+ ls->fs = NULL;
+ ls->linenumber = 1;
+ ls->lastline = 1;
+ ls->source = source;
+ luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */
+ next(ls); /* read first char */
+}
+
+
+
+/*
+** =======================================================
+** LEXICAL ANALYZER
+** =======================================================
+*/
+
+
+
+static int check_next (LexState *ls, const char *set) {
+ if (!strchr(set, ls->current))
+ return 0;
+ save_and_next(ls);
+ return 1;
+}
+
+
+static void buffreplace (LexState *ls, char from, char to) {
+ size_t n = luaZ_bufflen(ls->buff);
+ char *p = luaZ_buffer(ls->buff);
+ while (n--)
+ if (p[n] == from) p[n] = to;
+}
+
+
+static void trydecpoint (LexState *ls, SemInfo *seminfo) {
+ /* format error: try to update decimal point separator */
+ struct lconv *cv = localeconv();
+ char old = ls->decpoint;
+ ls->decpoint = (cv ? cv->decimal_point[0] : '.');
+ buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */
+ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
+ /* format error with correct decimal point: no more options */
+ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
+ luaX_lexerror(ls, "malformed number", TK_NUMBER);
+ }
+}
+
+
+/* LUA_NUMBER */
+static void read_numeral (LexState *ls, SemInfo *seminfo) {
+ lua_assert(isdigit(ls->current));
+ do {
+ save_and_next(ls);
+ } while (isdigit(ls->current) || ls->current == '.');
+ if (check_next(ls, "Ee")) /* `E'? */
+ check_next(ls, "+-"); /* optional exponent sign */
+ while (isalnum(ls->current) || ls->current == '_')
+ save_and_next(ls);
+ save(ls, '\0');
+ buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
+ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */
+ trydecpoint(ls, seminfo); /* try to update decimal point separator */
+}
+
+
+static int skip_sep (LexState *ls) {
+ int count = 0;
+ int s = ls->current;
+ lua_assert(s == '[' || s == ']');
+ save_and_next(ls);
+ while (ls->current == '=') {
+ save_and_next(ls);
+ count++;
+ }
+ return (ls->current == s) ? count : (-count) - 1;
+}
+
+
+static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
+ int cont = 0;
+ (void)(cont); /* avoid warnings when `cont' is not used */
+ save_and_next(ls); /* skip 2nd `[' */
+ if (currIsNewline(ls)) /* string starts with a newline? */
+ inclinenumber(ls); /* skip it */
+ for (;;) {
+ switch (ls->current) {
+ case EOZ:
+ luaX_lexerror(ls, (seminfo) ? "unfinished long string" :
+ "unfinished long comment", TK_EOS);
+ break; /* to avoid warnings */
+#if defined(LUA_COMPAT_LSTR)
+ case '[': {
+ if (skip_sep(ls) == sep) {
+ save_and_next(ls); /* skip 2nd `[' */
+ cont++;
+#if LUA_COMPAT_LSTR == 1
+ if (sep == 0)
+ luaX_lexerror(ls, "nesting of [[...]] is deprecated", '[');
+#endif
+ }
+ break;
+ }
+#endif
+ case ']': {
+ if (skip_sep(ls) == sep) {
+ save_and_next(ls); /* skip 2nd `]' */
+#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2
+ cont--;
+ if (sep == 0 && cont >= 0) break;
+#endif
+ goto endloop;
+ }
+ break;
+ }
+ case '\n':
+ case '\r': {
+ save(ls, '\n');
+ inclinenumber(ls);
+ if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */
+ break;
+ }
+ default: {
+ if (seminfo) save_and_next(ls);
+ else next(ls);
+ }
+ }
+ } endloop:
+ if (seminfo)
+ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),
+ luaZ_bufflen(ls->buff) - 2*(2 + sep));
+}
+
+
+static void read_string (LexState *ls, int del, SemInfo *seminfo) {
+ save_and_next(ls);
+ while (ls->current != del) {
+ switch (ls->current) {
+ case EOZ:
+ luaX_lexerror(ls, "unfinished string", TK_EOS);
+ continue; /* to avoid warnings */
+ case '\n':
+ case '\r':
+ luaX_lexerror(ls, "unfinished string", TK_STRING);
+ continue; /* to avoid warnings */
+ case '\\': {
+ int c;
+ next(ls); /* do not save the `\' */
+ switch (ls->current) {
+ case 'a': c = '\a'; break;
+ case 'b': c = '\b'; break;
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case 'v': c = '\v'; break;
+ case '\n': /* go through */
+ case '\r': save(ls, '\n'); inclinenumber(ls); continue;
+ case EOZ: continue; /* will raise an error next loop */
+ default: {
+ if (!isdigit(ls->current))
+ save_and_next(ls); /* handles \\, \", \', and \? */
+ else { /* \xxx */
+ int i = 0;
+ c = 0;
+ do {
+ c = 10*c + (ls->current-'0');
+ next(ls);
+ } while (++i<3 && isdigit(ls->current));
+ if (c > UCHAR_MAX)
+ luaX_lexerror(ls, "escape sequence too large", TK_STRING);
+ save(ls, c);
+ }
+ continue;
+ }
+ }
+ save(ls, c);
+ next(ls);
+ continue;
+ }
+ default:
+ save_and_next(ls);
+ }
+ }
+ save_and_next(ls); /* skip delimiter */
+ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,
+ luaZ_bufflen(ls->buff) - 2);
+}
+
+
+static int llex (LexState *ls, SemInfo *seminfo) {
+ luaZ_resetbuffer(ls->buff);
+ for (;;) {
+ switch (ls->current) {
+ case '\n':
+ case '\r': {
+ inclinenumber(ls);
+ continue;
+ }
+ case '-': {
+ next(ls);
+ if (ls->current != '-') return '-';
+ /* else is a comment */
+ next(ls);
+ if (ls->current == '[') {
+ int sep = skip_sep(ls);
+ luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */
+ if (sep >= 0) {
+ read_long_string(ls, NULL, sep); /* long comment */
+ luaZ_resetbuffer(ls->buff);
+ continue;
+ }
+ }
+ /* else short comment */
+ while (!currIsNewline(ls) && ls->current != EOZ)
+ next(ls);
+ continue;
+ }
+ case '[': {
+ int sep = skip_sep(ls);
+ if (sep >= 0) {
+ read_long_string(ls, seminfo, sep);
+ return TK_STRING;
+ }
+ else if (sep == -1) return '[';
+ else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING);
+ }
+ case '=': {
+ next(ls);
+ if (ls->current != '=') return '=';
+ else { next(ls); return TK_EQ; }
+ }
+ case '<': {
+ next(ls);
+ if (ls->current != '=') return '<';
+ else { next(ls); return TK_LE; }
+ }
+ case '>': {
+ next(ls);
+ if (ls->current != '=') return '>';
+ else { next(ls); return TK_GE; }
+ }
+ case '~': {
+ next(ls);
+ if (ls->current != '=') return '~';
+ else { next(ls); return TK_NE; }
+ }
+ case '"':
+ case '\'': {
+ read_string(ls, ls->current, seminfo);
+ return TK_STRING;
+ }
+ case '.': {
+ save_and_next(ls);
+ if (check_next(ls, ".")) {
+ if (check_next(ls, "."))
+ return TK_DOTS; /* ... */
+ else return TK_CONCAT; /* .. */
+ }
+ else if (!isdigit(ls->current)) return '.';
+ else {
+ read_numeral(ls, seminfo);
+ return TK_NUMBER;
+ }
+ }
+ case EOZ: {
+ return TK_EOS;
+ }
+ default: {
+ if (isspace(ls->current)) {
+ lua_assert(!currIsNewline(ls));
+ next(ls);
+ continue;
+ }
+ else if (isdigit(ls->current)) {
+ read_numeral(ls, seminfo);
+ return TK_NUMBER;
+ }
+ else if (isalpha(ls->current) || ls->current == '_') {
+ /* identifier or reserved word */
+ TString *ts;
+ do {
+ save_and_next(ls);
+ } while (isalnum(ls->current) || ls->current == '_');
+ ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
+ luaZ_bufflen(ls->buff));
+ if (ts->tsv.reserved > 0) /* reserved word? */
+ return ts->tsv.reserved - 1 + FIRST_RESERVED;
+ else {
+ seminfo->ts = ts;
+ return TK_NAME;
+ }
+ }
+ else {
+ int c = ls->current;
+ next(ls);
+ return c; /* single-char tokens (+ - / ...) */
+ }
+ }
+ }
+ }
+}
+
+
+void luaX_next (LexState *ls) {
+ ls->lastline = ls->linenumber;
+ if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */
+ ls->t = ls->lookahead; /* use this one */
+ ls->lookahead.token = TK_EOS; /* and discharge it */
+ }
+ else
+ ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */
+}
+
+
+void luaX_lookahead (LexState *ls) {
+ lua_assert(ls->lookahead.token == TK_EOS);
+ ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);
+}
+
diff --git a/Build/source/libs/lua51/llex.h b/Build/source/libs/lua51/llex.h
new file mode 100644
index 00000000000..ff07e83d318
--- /dev/null
+++ b/Build/source/libs/lua51/llex.h
@@ -0,0 +1,81 @@
+/*
+** $Id: llex.h,v 1.58 2006/03/23 18:23:32 roberto Exp $
+** Lexical Analyzer
+** See Copyright Notice in lua.h
+*/
+
+#ifndef llex_h
+#define llex_h
+
+#include "lobject.h"
+#include "lzio.h"
+
+
+#define FIRST_RESERVED 257
+
+/* maximum length of a reserved word */
+#define TOKEN_LEN (sizeof("function")/sizeof(char))
+
+
+/*
+* WARNING: if you change the order of this enumeration,
+* grep "ORDER RESERVED"
+*/
+enum RESERVED {
+ /* terminal symbols denoted by reserved words */
+ TK_AND = FIRST_RESERVED, TK_BREAK,
+ TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
+ TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
+ TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
+ /* other terminal symbols */
+ TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
+ TK_NAME, TK_STRING, TK_EOS
+};
+
+/* number of reserved words */
+#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1))
+
+
+/* array with token `names' */
+LUAI_DATA const char *const luaX_tokens [];
+
+
+typedef union {
+ lua_Number r;
+ TString *ts;
+} SemInfo; /* semantics information */
+
+
+typedef struct Token {
+ int token;
+ SemInfo seminfo;
+} Token;
+
+
+typedef struct LexState {
+ int current; /* current character (charint) */
+ int linenumber; /* input line counter */
+ int lastline; /* line of last token `consumed' */
+ Token t; /* current token */
+ Token lookahead; /* look ahead token */
+ struct FuncState *fs; /* `FuncState' is private to the parser */
+ struct lua_State *L;
+ ZIO *z; /* input stream */
+ Mbuffer *buff; /* buffer for tokens */
+ TString *source; /* current source name */
+ char decpoint; /* locale decimal point */
+} LexState;
+
+
+LUAI_FUNC void luaX_init (lua_State *L);
+LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z,
+ TString *source);
+LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l);
+LUAI_FUNC void luaX_next (LexState *ls);
+LUAI_FUNC void luaX_lookahead (LexState *ls);
+LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token);
+LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s);
+LUAI_FUNC const char *luaX_token2str (LexState *ls, int token);
+
+
+#endif
diff --git a/Build/source/libs/lua51/llimits.h b/Build/source/libs/lua51/llimits.h
new file mode 100644
index 00000000000..26e7c4f8cf8
--- /dev/null
+++ b/Build/source/libs/lua51/llimits.h
@@ -0,0 +1,128 @@
+/*
+** $Id: llimits.h,v 1.69 2005/12/27 17:12:00 roberto Exp $
+** Limits, basic types, and some other `installation-dependent' definitions
+** See Copyright Notice in lua.h
+*/
+
+#ifndef llimits_h
+#define llimits_h
+
+
+#include <limits.h>
+#include <stddef.h>
+
+
+#include "lua.h"
+
+
+typedef LUAI_UINT32 lu_int32;
+
+typedef LUAI_UMEM lu_mem;
+
+typedef LUAI_MEM l_mem;
+
+
+
+/* chars used as small naturals (so that `char' is reserved for characters) */
+typedef unsigned char lu_byte;
+
+
+#define MAX_SIZET ((size_t)(~(size_t)0)-2)
+
+#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2)
+
+
+#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */
+
+/*
+** conversion of pointer to integer
+** this is for hashing only; there is no problem if the integer
+** cannot hold the whole pointer value
+*/
+#define IntPoint(p) ((unsigned int)(lu_mem)(p))
+
+
+
+/* type to ensure maximum alignment */
+typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
+
+
+/* result of a `usual argument conversion' over lua_Number */
+typedef LUAI_UACNUMBER l_uacNumber;
+
+
+/* internal assertions for in-house debugging */
+#ifdef lua_assert
+
+#define check_exp(c,e) (lua_assert(c), (e))
+#define api_check(l,e) lua_assert(e)
+
+#else
+
+#define lua_assert(c) ((void)0)
+#define check_exp(c,e) (e)
+#define api_check luai_apicheck
+
+#endif
+
+
+#ifndef UNUSED
+#define UNUSED(x) ((void)(x)) /* to avoid warnings */
+#endif
+
+
+#ifndef cast
+#define cast(t, exp) ((t)(exp))
+#endif
+
+#define cast_byte(i) cast(lu_byte, (i))
+#define cast_num(i) cast(lua_Number, (i))
+#define cast_int(i) cast(int, (i))
+
+
+
+/*
+** type for virtual-machine instructions
+** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
+*/
+typedef lu_int32 Instruction;
+
+
+
+/* maximum stack for a Lua function */
+#define MAXSTACK 2000
+
+
+
+/* minimum size for the string table (must be power of 2) */
+#ifndef MINSTRTABSIZE
+#define MINSTRTABSIZE 32
+#endif
+
+
+/* minimum size for string buffer */
+#ifndef LUA_MINBUFFER
+#define LUA_MINBUFFER 32
+#endif
+
+
+#ifndef lua_lock
+#define lua_lock(L) ((void) 0)
+#define lua_unlock(L) ((void) 0)
+#endif
+
+#ifndef luai_threadyield
+#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);}
+#endif
+
+
+/*
+** macro to control inclusion of some hard tests on stack reallocation
+*/
+#ifndef HARDSTACKTESTS
+#define condhardstacktests(x) ((void)0)
+#else
+#define condhardstacktests(x) x
+#endif
+
+#endif
diff --git a/Build/source/libs/lua51/lmathlib.c b/Build/source/libs/lua51/lmathlib.c
new file mode 100644
index 00000000000..d181a731943
--- /dev/null
+++ b/Build/source/libs/lua51/lmathlib.c
@@ -0,0 +1,263 @@
+/*
+** $Id: lmathlib.c,v 1.67 2005/08/26 17:36:32 roberto Exp $
+** Standard mathematical library
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdlib.h>
+#include <math.h>
+
+#define lmathlib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+#undef PI
+#define PI (3.14159265358979323846)
+#define RADIANS_PER_DEGREE (PI/180.0)
+
+
+
+static int math_abs (lua_State *L) {
+ lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_sin (lua_State *L) {
+ lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_sinh (lua_State *L) {
+ lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_cos (lua_State *L) {
+ lua_pushnumber(L, cos(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_cosh (lua_State *L) {
+ lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_tan (lua_State *L) {
+ lua_pushnumber(L, tan(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_tanh (lua_State *L) {
+ lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_asin (lua_State *L) {
+ lua_pushnumber(L, asin(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_acos (lua_State *L) {
+ lua_pushnumber(L, acos(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_atan (lua_State *L) {
+ lua_pushnumber(L, atan(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_atan2 (lua_State *L) {
+ lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+}
+
+static int math_ceil (lua_State *L) {
+ lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_floor (lua_State *L) {
+ lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_fmod (lua_State *L) {
+ lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+}
+
+static int math_modf (lua_State *L) {
+ double ip;
+ double fp = modf(luaL_checknumber(L, 1), &ip);
+ lua_pushnumber(L, ip);
+ lua_pushnumber(L, fp);
+ return 2;
+}
+
+static int math_sqrt (lua_State *L) {
+ lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_pow (lua_State *L) {
+ lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+}
+
+static int math_log (lua_State *L) {
+ lua_pushnumber(L, log(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_log10 (lua_State *L) {
+ lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_exp (lua_State *L) {
+ lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_deg (lua_State *L) {
+ lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE);
+ return 1;
+}
+
+static int math_rad (lua_State *L) {
+ lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE);
+ return 1;
+}
+
+static int math_frexp (lua_State *L) {
+ int e;
+ lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
+ lua_pushinteger(L, e);
+ return 2;
+}
+
+static int math_ldexp (lua_State *L) {
+ lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+
+
+static int math_min (lua_State *L) {
+ int n = lua_gettop(L); /* number of arguments */
+ lua_Number dmin = luaL_checknumber(L, 1);
+ int i;
+ for (i=2; i<=n; i++) {
+ lua_Number d = luaL_checknumber(L, i);
+ if (d < dmin)
+ dmin = d;
+ }
+ lua_pushnumber(L, dmin);
+ return 1;
+}
+
+
+static int math_max (lua_State *L) {
+ int n = lua_gettop(L); /* number of arguments */
+ lua_Number dmax = luaL_checknumber(L, 1);
+ int i;
+ for (i=2; i<=n; i++) {
+ lua_Number d = luaL_checknumber(L, i);
+ if (d > dmax)
+ dmax = d;
+ }
+ lua_pushnumber(L, dmax);
+ return 1;
+}
+
+
+static int math_random (lua_State *L) {
+ /* the `%' avoids the (rare) case of r==1, and is needed also because on
+ some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
+ lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
+ switch (lua_gettop(L)) { /* check number of arguments */
+ case 0: { /* no arguments */
+ lua_pushnumber(L, r); /* Number between 0 and 1 */
+ break;
+ }
+ case 1: { /* only upper limit */
+ int u = luaL_checkint(L, 1);
+ luaL_argcheck(L, 1<=u, 1, "interval is empty");
+ lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */
+ break;
+ }
+ case 2: { /* lower and upper limits */
+ int l = luaL_checkint(L, 1);
+ int u = luaL_checkint(L, 2);
+ luaL_argcheck(L, l<=u, 2, "interval is empty");
+ lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */
+ break;
+ }
+ default: return luaL_error(L, "wrong number of arguments");
+ }
+ return 1;
+}
+
+
+static int math_randomseed (lua_State *L) {
+ srand(luaL_checkint(L, 1));
+ return 0;
+}
+
+
+static const luaL_Reg mathlib[] = {
+ {"abs", math_abs},
+ {"acos", math_acos},
+ {"asin", math_asin},
+ {"atan2", math_atan2},
+ {"atan", math_atan},
+ {"ceil", math_ceil},
+ {"cosh", math_cosh},
+ {"cos", math_cos},
+ {"deg", math_deg},
+ {"exp", math_exp},
+ {"floor", math_floor},
+ {"fmod", math_fmod},
+ {"frexp", math_frexp},
+ {"ldexp", math_ldexp},
+ {"log10", math_log10},
+ {"log", math_log},
+ {"max", math_max},
+ {"min", math_min},
+ {"modf", math_modf},
+ {"pow", math_pow},
+ {"rad", math_rad},
+ {"random", math_random},
+ {"randomseed", math_randomseed},
+ {"sinh", math_sinh},
+ {"sin", math_sin},
+ {"sqrt", math_sqrt},
+ {"tanh", math_tanh},
+ {"tan", math_tan},
+ {NULL, NULL}
+};
+
+
+/*
+** Open math library
+*/
+LUALIB_API int luaopen_math (lua_State *L) {
+ luaL_register(L, LUA_MATHLIBNAME, mathlib);
+ lua_pushnumber(L, PI);
+ lua_setfield(L, -2, "pi");
+ lua_pushnumber(L, HUGE_VAL);
+ lua_setfield(L, -2, "huge");
+#if defined(LUA_COMPAT_MOD)
+ lua_getfield(L, -1, "fmod");
+ lua_setfield(L, -2, "mod");
+#endif
+ return 1;
+}
+
diff --git a/Build/source/libs/lua51/lmem.c b/Build/source/libs/lua51/lmem.c
new file mode 100644
index 00000000000..cef2bc5f851
--- /dev/null
+++ b/Build/source/libs/lua51/lmem.c
@@ -0,0 +1,86 @@
+/*
+** $Id: lmem.c,v 1.70 2005/12/26 13:35:47 roberto Exp $
+** Interface to Memory Manager
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stddef.h>
+
+#define lmem_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+
+
+
+/*
+** About the realloc function:
+** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize);
+** (`osize' is the old size, `nsize' is the new size)
+**
+** Lua ensures that (ptr == NULL) iff (osize == 0).
+**
+** * frealloc(ud, NULL, 0, x) creates a new block of size `x'
+**
+** * frealloc(ud, p, x, 0) frees the block `p'
+** (in this specific case, frealloc must return NULL).
+** particularly, frealloc(ud, NULL, 0, 0) does nothing
+** (which is equivalent to free(NULL) in ANSI C)
+**
+** frealloc returns NULL if it cannot create or reallocate the area
+** (any reallocation to an equal or smaller size cannot fail!)
+*/
+
+
+
+#define MINSIZEARRAY 4
+
+
+void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems,
+ int limit, const char *errormsg) {
+ void *newblock;
+ int newsize;
+ if (*size >= limit/2) { /* cannot double it? */
+ if (*size >= limit) /* cannot grow even a little? */
+ luaG_runerror(L, errormsg);
+ newsize = limit; /* still have at least one free place */
+ }
+ else {
+ newsize = (*size)*2;
+ if (newsize < MINSIZEARRAY)
+ newsize = MINSIZEARRAY; /* minimum size */
+ }
+ newblock = luaM_reallocv(L, block, *size, newsize, size_elems);
+ *size = newsize; /* update only when everything else is OK */
+ return newblock;
+}
+
+
+void *luaM_toobig (lua_State *L) {
+ luaG_runerror(L, "memory allocation error: block too big");
+ return NULL; /* to avoid warnings */
+}
+
+
+
+/*
+** generic allocation routine.
+*/
+void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
+ global_State *g = G(L);
+ lua_assert((osize == 0) == (block == NULL));
+ block = (*g->frealloc)(g->ud, block, osize, nsize);
+ if (block == NULL && nsize > 0)
+ luaD_throw(L, LUA_ERRMEM);
+ lua_assert((nsize == 0) == (block == NULL));
+ g->totalbytes = (g->totalbytes - osize) + nsize;
+ return block;
+}
+
diff --git a/Build/source/libs/lua51/lmem.h b/Build/source/libs/lua51/lmem.h
new file mode 100644
index 00000000000..19df1fbb6c9
--- /dev/null
+++ b/Build/source/libs/lua51/lmem.h
@@ -0,0 +1,49 @@
+/*
+** $Id: lmem.h,v 1.31 2005/04/25 19:24:10 roberto Exp $
+** Interface to Memory Manager
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lmem_h
+#define lmem_h
+
+
+#include <stddef.h>
+
+#include "llimits.h"
+#include "lua.h"
+
+#define MEMERRMSG "not enough memory"
+
+
+#define luaM_reallocv(L,b,on,n,e) \
+ ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \
+ luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \
+ luaM_toobig(L))
+
+#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0)
+#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0)
+#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t))
+
+#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t))
+#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t)))
+#define luaM_newvector(L,n,t) \
+ cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t)))
+
+#define luaM_growvector(L,v,nelems,size,t,limit,e) \
+ if ((nelems)+1 > (size)) \
+ ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e)))
+
+#define luaM_reallocvector(L, v,oldn,n,t) \
+ ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))
+
+
+LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
+ size_t size);
+LUAI_FUNC void *luaM_toobig (lua_State *L);
+LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,
+ size_t size_elem, int limit,
+ const char *errormsg);
+
+#endif
+
diff --git a/Build/source/libs/lua51/loadlib.c b/Build/source/libs/lua51/loadlib.c
new file mode 100644
index 00000000000..808368ba431
--- /dev/null
+++ b/Build/source/libs/lua51/loadlib.c
@@ -0,0 +1,664 @@
+/*
+** $Id: loadlib.c,v 1.54a 2006/07/03 20:16:49 roberto Exp $
+** Dynamic library loader for Lua
+** See Copyright Notice in lua.h
+**
+** This module contains an implementation of loadlib for Unix systems
+** that have dlfcn, an implementation for Darwin (Mac OS X), an
+** implementation for Windows, and a stub for other systems.
+*/
+
+
+#include <stdlib.h>
+#include <string.h>
+
+
+#define loadlib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+/* prefix for open functions in C libraries */
+#define LUA_POF "luaopen_"
+
+/* separator for open functions in C libraries */
+#define LUA_OFSEP "_"
+
+
+#define LIBPREFIX "LOADLIB: "
+
+#define POF LUA_POF
+#define LIB_FAIL "open"
+
+
+/* error codes for ll_loadfunc */
+#define ERRLIB 1
+#define ERRFUNC 2
+
+#define setprogdir(L) ((void)0)
+
+
+static void ll_unloadlib (void *lib);
+static void *ll_load (lua_State *L, const char *path);
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);
+
+
+
+#if defined(LUA_DL_DLOPEN)
+/*
+** {========================================================================
+** This is an implementation of loadlib based on the dlfcn interface.
+** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
+** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
+** as an emulation layer on top of native functions.
+** =========================================================================
+*/
+
+#include <dlfcn.h>
+
+static void ll_unloadlib (void *lib) {
+ dlclose(lib);
+}
+
+
+static void *ll_load (lua_State *L, const char *path) {
+ void *lib = dlopen(path, RTLD_NOW);
+ if (lib == NULL) lua_pushstring(L, dlerror());
+ return lib;
+}
+
+
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+ lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
+ if (f == NULL) lua_pushstring(L, dlerror());
+ return f;
+}
+
+/* }====================================================== */
+
+
+
+#elif defined(LUA_DL_DLL)
+/*
+** {======================================================================
+** This is an implementation of loadlib for Windows using native functions.
+** =======================================================================
+*/
+
+#include <windows.h>
+
+
+#undef setprogdir
+
+static void setprogdir (lua_State *L) {
+ char buff[MAX_PATH + 1];
+ char *lb;
+ DWORD nsize = sizeof(buff)/sizeof(char);
+ DWORD n = GetModuleFileNameA(NULL, buff, nsize);
+ if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
+ luaL_error(L, "unable to get ModuleFileName");
+ else {
+ *lb = '\0';
+ luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff);
+ lua_remove(L, -2); /* remove original string */
+ }
+}
+
+
+static void pusherror (lua_State *L) {
+ int error = GetLastError();
+ char buffer[128];
+ if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, error, 0, buffer, sizeof(buffer), NULL))
+ lua_pushstring(L, buffer);
+ else
+ lua_pushfstring(L, "system error %d\n", error);
+}
+
+static void ll_unloadlib (void *lib) {
+ FreeLibrary((HINSTANCE)lib);
+}
+
+
+static void *ll_load (lua_State *L, const char *path) {
+ HINSTANCE lib = LoadLibraryA(path);
+ if (lib == NULL) pusherror(L);
+ return lib;
+}
+
+
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+ lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym);
+ if (f == NULL) pusherror(L);
+ return f;
+}
+
+/* }====================================================== */
+
+
+
+#elif defined(LUA_DL_DYLD)
+/*
+** {======================================================================
+** Native Mac OS X / Darwin Implementation
+** =======================================================================
+*/
+
+#include <mach-o/dyld.h>
+
+
+/* Mac appends a `_' before C function names */
+#undef POF
+#define POF "_" LUA_POF
+
+
+static void pusherror (lua_State *L) {
+ const char *err_str;
+ const char *err_file;
+ NSLinkEditErrors err;
+ int err_num;
+ NSLinkEditError(&err, &err_num, &err_file, &err_str);
+ lua_pushstring(L, err_str);
+}
+
+
+static const char *errorfromcode (NSObjectFileImageReturnCode ret) {
+ switch (ret) {
+ case NSObjectFileImageInappropriateFile:
+ return "file is not a bundle";
+ case NSObjectFileImageArch:
+ return "library is for wrong CPU type";
+ case NSObjectFileImageFormat:
+ return "bad format";
+ case NSObjectFileImageAccess:
+ return "cannot access file";
+ case NSObjectFileImageFailure:
+ default:
+ return "unable to load library";
+ }
+}
+
+
+static void ll_unloadlib (void *lib) {
+ NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
+}
+
+
+static void *ll_load (lua_State *L, const char *path) {
+ NSObjectFileImage img;
+ NSObjectFileImageReturnCode ret;
+ /* this would be a rare case, but prevents crashing if it happens */
+ if(!_dyld_present()) {
+ lua_pushliteral(L, "dyld not present");
+ return NULL;
+ }
+ ret = NSCreateObjectFileImageFromFile(path, &img);
+ if (ret == NSObjectFileImageSuccess) {
+ NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE |
+ NSLINKMODULE_OPTION_RETURN_ON_ERROR);
+ NSDestroyObjectFileImage(img);
+ if (mod == NULL) pusherror(L);
+ return mod;
+ }
+ lua_pushstring(L, errorfromcode(ret));
+ return NULL;
+}
+
+
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+ NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym);
+ if (nss == NULL) {
+ lua_pushfstring(L, "symbol " LUA_QS " not found", sym);
+ return NULL;
+ }
+ return (lua_CFunction)NSAddressOfSymbol(nss);
+}
+
+/* }====================================================== */
+
+
+
+#else
+/*
+** {======================================================
+** Fallback for other systems
+** =======================================================
+*/
+
+#undef LIB_FAIL
+#define LIB_FAIL "absent"
+
+
+#define DLMSG "dynamic libraries not enabled; check your Lua installation"
+
+
+static void ll_unloadlib (void *lib) {
+ (void)lib; /* to avoid warnings */
+}
+
+
+static void *ll_load (lua_State *L, const char *path) {
+ (void)path; /* to avoid warnings */
+ lua_pushliteral(L, DLMSG);
+ return NULL;
+}
+
+
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+ (void)lib; (void)sym; /* to avoid warnings */
+ lua_pushliteral(L, DLMSG);
+ return NULL;
+}
+
+/* }====================================================== */
+#endif
+
+
+
+static void **ll_register (lua_State *L, const char *path) {
+ void **plib;
+ lua_pushfstring(L, "%s%s", LIBPREFIX, path);
+ lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */
+ if (!lua_isnil(L, -1)) /* is there an entry? */
+ plib = (void **)lua_touserdata(L, -1);
+ else { /* no entry yet; create one */
+ lua_pop(L, 1);
+ plib = (void **)lua_newuserdata(L, sizeof(const void *));
+ *plib = NULL;
+ luaL_getmetatable(L, "_LOADLIB");
+ lua_setmetatable(L, -2);
+ lua_pushfstring(L, "%s%s", LIBPREFIX, path);
+ lua_pushvalue(L, -2);
+ lua_settable(L, LUA_REGISTRYINDEX);
+ }
+ return plib;
+}
+
+
+/*
+** __gc tag method: calls library's `ll_unloadlib' function with the lib
+** handle
+*/
+static int gctm (lua_State *L) {
+ void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB");
+ if (*lib) ll_unloadlib(*lib);
+ *lib = NULL; /* mark library as closed */
+ return 0;
+}
+
+
+static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
+ void **reg = ll_register(L, path);
+ if (*reg == NULL) *reg = ll_load(L, path);
+ if (*reg == NULL)
+ return ERRLIB; /* unable to load library */
+ else {
+ lua_CFunction f = ll_sym(L, *reg, sym);
+ if (f == NULL)
+ return ERRFUNC; /* unable to find function */
+ lua_pushcfunction(L, f);
+ return 0; /* return function */
+ }
+}
+
+
+static int ll_loadlib (lua_State *L) {
+ const char *path = luaL_checkstring(L, 1);
+ const char *init = luaL_checkstring(L, 2);
+ int stat = ll_loadfunc(L, path, init);
+ if (stat == 0) /* no errors? */
+ return 1; /* return the loaded function */
+ else { /* error; error message is on stack top */
+ lua_pushnil(L);
+ lua_insert(L, -2);
+ lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init");
+ return 3; /* return nil, error message, and where */
+ }
+}
+
+
+
+/*
+** {======================================================
+** 'require' function
+** =======================================================
+*/
+
+
+static int readable (const char *filename) {
+ FILE *f = fopen(filename, "r"); /* try to open file */
+ if (f == NULL) return 0; /* open failed */
+ fclose(f);
+ return 1;
+}
+
+
+static const char *pushnexttemplate (lua_State *L, const char *path) {
+ const char *l;
+ while (*path == *LUA_PATHSEP) path++; /* skip separators */
+ if (*path == '\0') return NULL; /* no more templates */
+ l = strchr(path, *LUA_PATHSEP); /* find next separator */
+ if (l == NULL) l = path + strlen(path);
+ lua_pushlstring(L, path, l - path); /* template */
+ return l;
+}
+
+
+static const char *findfile (lua_State *L, const char *name,
+ const char *pname) {
+ const char *path;
+ name = luaL_gsub(L, name, ".", LUA_DIRSEP);
+ lua_getfield(L, LUA_ENVIRONINDEX, pname);
+ path = lua_tostring(L, -1);
+ if (path == NULL)
+ luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
+ lua_pushliteral(L, ""); /* error accumulator */
+ while ((path = pushnexttemplate(L, path)) != NULL) {
+ const char *filename;
+ filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name);
+ lua_remove(L, -2); /* remove path template */
+ if (readable(filename)) /* does file exist and is readable? */
+ return filename; /* return that file name */
+ lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
+ lua_remove(L, -2); /* remove file name */
+ lua_concat(L, 2); /* add entry to possible error message */
+ }
+ return NULL; /* not found */
+}
+
+
+static void loaderror (lua_State *L, const char *filename) {
+ luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s",
+ lua_tostring(L, 1), filename, lua_tostring(L, -1));
+}
+
+
+static int loader_Lua (lua_State *L) {
+ const char *filename;
+ const char *name = luaL_checkstring(L, 1);
+ filename = findfile(L, name, "path");
+ if (filename == NULL) return 1; /* library not found in this path */
+ if (luaL_loadfile(L, filename) != 0)
+ loaderror(L, filename);
+ return 1; /* library loaded successfully */
+}
+
+
+static const char *mkfuncname (lua_State *L, const char *modname) {
+ const char *funcname;
+ const char *mark = strchr(modname, *LUA_IGMARK);
+ if (mark) modname = mark + 1;
+ funcname = luaL_gsub(L, modname, ".", LUA_OFSEP);
+ funcname = lua_pushfstring(L, POF"%s", funcname);
+ lua_remove(L, -2); /* remove 'gsub' result */
+ return funcname;
+}
+
+
+static int loader_C (lua_State *L) {
+ const char *funcname;
+ const char *name = luaL_checkstring(L, 1);
+ const char *filename = findfile(L, name, "cpath");
+ if (filename == NULL) return 1; /* library not found in this path */
+ funcname = mkfuncname(L, name);
+ if (ll_loadfunc(L, filename, funcname) != 0)
+ loaderror(L, filename);
+ return 1; /* library loaded successfully */
+}
+
+
+static int loader_Croot (lua_State *L) {
+ const char *funcname;
+ const char *filename;
+ const char *name = luaL_checkstring(L, 1);
+ const char *p = strchr(name, '.');
+ int stat;
+ if (p == NULL) return 0; /* is root */
+ lua_pushlstring(L, name, p - name);
+ filename = findfile(L, lua_tostring(L, -1), "cpath");
+ if (filename == NULL) return 1; /* root not found */
+ funcname = mkfuncname(L, name);
+ if ((stat = ll_loadfunc(L, filename, funcname)) != 0) {
+ if (stat != ERRFUNC) loaderror(L, filename); /* real error */
+ lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
+ name, filename);
+ return 1; /* function not found */
+ }
+ return 1;
+}
+
+
+static int loader_preload (lua_State *L) {
+ const char *name = luaL_checkstring(L, 1);
+ lua_getfield(L, LUA_ENVIRONINDEX, "preload");
+ if (!lua_istable(L, -1))
+ luaL_error(L, LUA_QL("package.preload") " must be a table");
+ lua_getfield(L, -1, name);
+ if (lua_isnil(L, -1)) /* not found? */
+ lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
+ return 1;
+}
+
+
+static const int sentinel_ = 0;
+#define sentinel ((void *)&sentinel_)
+
+
+static int ll_require (lua_State *L) {
+ const char *name = luaL_checkstring(L, 1);
+ int i;
+ lua_settop(L, 1); /* _LOADED table will be at index 2 */
+ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
+ lua_getfield(L, 2, name);
+ if (lua_toboolean(L, -1)) { /* is it there? */
+ if (lua_touserdata(L, -1) == sentinel) /* check loops */
+ luaL_error(L, "loop or previous error loading module " LUA_QS, name);
+ return 1; /* package is already loaded */
+ }
+ /* else must load it; iterate over available loaders */
+ lua_getfield(L, LUA_ENVIRONINDEX, "loaders");
+ if (!lua_istable(L, -1))
+ luaL_error(L, LUA_QL("package.loaders") " must be a table");
+ lua_pushliteral(L, ""); /* error message accumulator */
+ for (i=1; ; i++) {
+ lua_rawgeti(L, -2, i); /* get a loader */
+ if (lua_isnil(L, -1))
+ luaL_error(L, "module " LUA_QS " not found:%s",
+ name, lua_tostring(L, -2));
+ lua_pushstring(L, name);
+ lua_call(L, 1, 1); /* call it */
+ if (lua_isfunction(L, -1)) /* did it find module? */
+ break; /* module loaded successfully */
+ else if (lua_isstring(L, -1)) /* loader returned error message? */
+ lua_concat(L, 2); /* accumulate it */
+ else
+ lua_pop(L, 1);
+ }
+ lua_pushlightuserdata(L, sentinel);
+ lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */
+ lua_pushstring(L, name); /* pass name as argument to module */
+ lua_call(L, 1, 1); /* run loaded module */
+ if (!lua_isnil(L, -1)) /* non-nil return? */
+ lua_setfield(L, 2, name); /* _LOADED[name] = returned value */
+ lua_getfield(L, 2, name);
+ if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */
+ lua_pushboolean(L, 1); /* use true as result */
+ lua_pushvalue(L, -1); /* extra copy to be returned */
+ lua_setfield(L, 2, name); /* _LOADED[name] = true */
+ }
+ return 1;
+}
+
+/* }====================================================== */
+
+
+
+/*
+** {======================================================
+** 'module' function
+** =======================================================
+*/
+
+
+static void setfenv (lua_State *L) {
+ lua_Debug ar;
+ lua_getstack(L, 1, &ar);
+ lua_getinfo(L, "f", &ar);
+ lua_pushvalue(L, -2);
+ lua_setfenv(L, -2);
+ lua_pop(L, 1);
+}
+
+
+static void dooptions (lua_State *L, int n) {
+ int i;
+ for (i = 2; i <= n; i++) {
+ lua_pushvalue(L, i); /* get option (a function) */
+ lua_pushvalue(L, -2); /* module */
+ lua_call(L, 1, 0);
+ }
+}
+
+
+static void modinit (lua_State *L, const char *modname) {
+ const char *dot;
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "_M"); /* module._M = module */
+ lua_pushstring(L, modname);
+ lua_setfield(L, -2, "_NAME");
+ dot = strrchr(modname, '.'); /* look for last dot in module name */
+ if (dot == NULL) dot = modname;
+ else dot++;
+ /* set _PACKAGE as package name (full module name minus last part) */
+ lua_pushlstring(L, modname, dot - modname);
+ lua_setfield(L, -2, "_PACKAGE");
+}
+
+
+static int ll_module (lua_State *L) {
+ const char *modname = luaL_checkstring(L, 1);
+ int loaded = lua_gettop(L) + 1; /* index of _LOADED table */
+ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
+ lua_getfield(L, loaded, modname); /* get _LOADED[modname] */
+ if (!lua_istable(L, -1)) { /* not found? */
+ lua_pop(L, 1); /* remove previous result */
+ /* try global variable (and create one if it does not exist) */
+ if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)
+ return luaL_error(L, "name conflict for module " LUA_QS, modname);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */
+ }
+ /* check whether table already has a _NAME field */
+ lua_getfield(L, -1, "_NAME");
+ if (!lua_isnil(L, -1)) /* is table an initialized module? */
+ lua_pop(L, 1);
+ else { /* no; initialize it */
+ lua_pop(L, 1);
+ modinit(L, modname);
+ }
+ lua_pushvalue(L, -1);
+ setfenv(L);
+ dooptions(L, loaded - 1);
+ return 0;
+}
+
+
+static int ll_seeall (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ if (!lua_getmetatable(L, 1)) {
+ lua_createtable(L, 0, 1); /* create new metatable */
+ lua_pushvalue(L, -1);
+ lua_setmetatable(L, 1);
+ }
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ lua_setfield(L, -2, "__index"); /* mt.__index = _G */
+ return 0;
+}
+
+
+/* }====================================================== */
+
+
+
+/* auxiliary mark (for internal use) */
+#define AUXMARK "\1"
+
+static void setpath (lua_State *L, const char *fieldname, const char *envname,
+ const char *def) {
+ const char *path = getenv(envname);
+ if (path == NULL) /* no environment variable? */
+ lua_pushstring(L, def); /* use default */
+ else {
+ /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
+ path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP,
+ LUA_PATHSEP AUXMARK LUA_PATHSEP);
+ luaL_gsub(L, path, AUXMARK, def);
+ lua_remove(L, -2);
+ }
+ setprogdir(L);
+ lua_setfield(L, -2, fieldname);
+}
+
+
+static const luaL_Reg pk_funcs[] = {
+ {"loadlib", ll_loadlib},
+ {"seeall", ll_seeall},
+ {NULL, NULL}
+};
+
+
+static const luaL_Reg ll_funcs[] = {
+ {"module", ll_module},
+ {"require", ll_require},
+ {NULL, NULL}
+};
+
+
+static const lua_CFunction loaders[] =
+ {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};
+
+
+LUALIB_API int luaopen_package (lua_State *L) {
+ int i;
+ /* create new type _LOADLIB */
+ luaL_newmetatable(L, "_LOADLIB");
+ lua_pushcfunction(L, gctm);
+ lua_setfield(L, -2, "__gc");
+ /* create `package' table */
+ luaL_register(L, LUA_LOADLIBNAME, pk_funcs);
+#if defined(LUA_COMPAT_LOADLIB)
+ lua_getfield(L, -1, "loadlib");
+ lua_setfield(L, LUA_GLOBALSINDEX, "loadlib");
+#endif
+ lua_pushvalue(L, -1);
+ lua_replace(L, LUA_ENVIRONINDEX);
+ /* create `loaders' table */
+ lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1);
+ /* fill it with pre-defined loaders */
+ for (i=0; loaders[i] != NULL; i++) {
+ lua_pushcfunction(L, loaders[i]);
+ lua_rawseti(L, -2, i+1);
+ }
+ lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */
+ setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */
+ setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */
+ /* store config information */
+ lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n"
+ LUA_EXECDIR "\n" LUA_IGMARK);
+ lua_setfield(L, -2, "config");
+ /* set field `loaded' */
+ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2);
+ lua_setfield(L, -2, "loaded");
+ /* set field `preload' */
+ lua_newtable(L);
+ lua_setfield(L, -2, "preload");
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ luaL_register(L, NULL, ll_funcs); /* open lib into global table */
+ lua_pop(L, 1);
+ return 1; /* return 'package' table */
+}
+
diff --git a/Build/source/libs/lua51/lobject.c b/Build/source/libs/lua51/lobject.c
new file mode 100644
index 00000000000..acde82ccdf1
--- /dev/null
+++ b/Build/source/libs/lua51/lobject.c
@@ -0,0 +1,214 @@
+/*
+** $Id: lobject.c,v 2.22 2006/02/10 17:43:52 roberto Exp $
+** Some generic functions over Lua objects
+** See Copyright Notice in lua.h
+*/
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lobject_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldo.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "lvm.h"
+
+
+
+const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
+
+
+/*
+** converts an integer to a "floating point byte", represented as
+** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
+** eeeee != 0 and (xxx) otherwise.
+*/
+int luaO_int2fb (unsigned int x) {
+ int e = 0; /* expoent */
+ while (x >= 16) {
+ x = (x+1) >> 1;
+ e++;
+ }
+ if (x < 8) return x;
+ else return ((e+1) << 3) | (cast_int(x) - 8);
+}
+
+
+/* converts back */
+int luaO_fb2int (int x) {
+ int e = (x >> 3) & 31;
+ if (e == 0) return x;
+ else return ((x & 7)+8) << (e - 1);
+}
+
+
+int luaO_log2 (unsigned int x) {
+ static const lu_byte log_2[256] = {
+ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
+ };
+ int l = -1;
+ while (x >= 256) { l += 8; x >>= 8; }
+ return l + log_2[x];
+
+}
+
+
+int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
+ if (ttype(t1) != ttype(t2)) return 0;
+ else switch (ttype(t1)) {
+ case LUA_TNIL:
+ return 1;
+ case LUA_TNUMBER:
+ return luai_numeq(nvalue(t1), nvalue(t2));
+ case LUA_TBOOLEAN:
+ return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */
+ case LUA_TLIGHTUSERDATA:
+ return pvalue(t1) == pvalue(t2);
+ default:
+ lua_assert(iscollectable(t1));
+ return gcvalue(t1) == gcvalue(t2);
+ }
+}
+
+
+int luaO_str2d (const char *s, lua_Number *result) {
+ char *endptr;
+ *result = lua_str2number(s, &endptr);
+ if (endptr == s) return 0; /* conversion failed */
+ if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */
+ *result = cast_num(strtoul(s, &endptr, 16));
+ if (*endptr == '\0') return 1; /* most common case */
+ while (isspace(cast(unsigned char, *endptr))) endptr++;
+ if (*endptr != '\0') return 0; /* invalid trailing characters? */
+ return 1;
+}
+
+
+
+static void pushstr (lua_State *L, const char *str) {
+ setsvalue2s(L, L->top, luaS_new(L, str));
+ incr_top(L);
+}
+
+
+/* this function handles only `%d', `%c', %f, %p, and `%s' formats */
+const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
+ int n = 1;
+ pushstr(L, "");
+ for (;;) {
+ const char *e = strchr(fmt, '%');
+ if (e == NULL) break;
+ setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt));
+ incr_top(L);
+ switch (*(e+1)) {
+ case 's': {
+ const char *s = va_arg(argp, char *);
+ if (s == NULL) s = "(null)";
+ pushstr(L, s);
+ break;
+ }
+ case 'c': {
+ char buff[2];
+ buff[0] = cast(char, va_arg(argp, int));
+ buff[1] = '\0';
+ pushstr(L, buff);
+ break;
+ }
+ case 'd': {
+ setnvalue(L->top, cast_num(va_arg(argp, int)));
+ incr_top(L);
+ break;
+ }
+ case 'f': {
+ setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
+ incr_top(L);
+ break;
+ }
+ case 'p': {
+ char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */
+ sprintf(buff, "%p", va_arg(argp, void *));
+ pushstr(L, buff);
+ break;
+ }
+ case '%': {
+ pushstr(L, "%");
+ break;
+ }
+ default: {
+ char buff[3];
+ buff[0] = '%';
+ buff[1] = *(e+1);
+ buff[2] = '\0';
+ pushstr(L, buff);
+ break;
+ }
+ }
+ n += 2;
+ fmt = e+2;
+ }
+ pushstr(L, fmt);
+ luaV_concat(L, n+1, cast_int(L->top - L->base) - 1);
+ L->top -= n;
+ return svalue(L->top - 1);
+}
+
+
+const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {
+ const char *msg;
+ va_list argp;
+ va_start(argp, fmt);
+ msg = luaO_pushvfstring(L, fmt, argp);
+ va_end(argp);
+ return msg;
+}
+
+
+void luaO_chunkid (char *out, const char *source, size_t bufflen) {
+ if (*source == '=') {
+ strncpy(out, source+1, bufflen); /* remove first char */
+ out[bufflen-1] = '\0'; /* ensures null termination */
+ }
+ else { /* out = "source", or "...source" */
+ if (*source == '@') {
+ size_t l;
+ source++; /* skip the `@' */
+ bufflen -= sizeof(" '...' ");
+ l = strlen(source);
+ strcpy(out, "");
+ if (l > bufflen) {
+ source += (l-bufflen); /* get last part of file name */
+ strcat(out, "...");
+ }
+ strcat(out, source);
+ }
+ else { /* out = [string "string"] */
+ size_t len = strcspn(source, "\n\r"); /* stop at first newline */
+ bufflen -= sizeof(" [string \"...\"] ");
+ if (len > bufflen) len = bufflen;
+ strcpy(out, "[string \"");
+ if (source[len] != '\0') { /* must truncate? */
+ strncat(out, source, len);
+ strcat(out, "...");
+ }
+ else
+ strcat(out, source);
+ strcat(out, "\"]");
+ }
+ }
+}
diff --git a/Build/source/libs/lua51/lobject.h b/Build/source/libs/lua51/lobject.h
new file mode 100644
index 00000000000..8ce4405b6ae
--- /dev/null
+++ b/Build/source/libs/lua51/lobject.h
@@ -0,0 +1,381 @@
+/*
+** $Id: lobject.h,v 2.20 2006/01/18 11:37:34 roberto Exp $
+** Type definitions for Lua objects
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lobject_h
+#define lobject_h
+
+
+#include <stdarg.h>
+
+
+#include "llimits.h"
+#include "lua.h"
+
+
+/* tags for values visible from Lua */
+#define LAST_TAG LUA_TTHREAD
+
+#define NUM_TAGS (LAST_TAG+1)
+
+
+/*
+** Extra tags for non-values
+*/
+#define LUA_TPROTO (LAST_TAG+1)
+#define LUA_TUPVAL (LAST_TAG+2)
+#define LUA_TDEADKEY (LAST_TAG+3)
+
+
+/*
+** Union of all collectable objects
+*/
+typedef union GCObject GCObject;
+
+
+/*
+** Common Header for all collectable objects (in macro form, to be
+** included in other objects)
+*/
+#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
+
+
+/*
+** Common header in struct form
+*/
+typedef struct GCheader {
+ CommonHeader;
+} GCheader;
+
+
+
+
+/*
+** Union of all Lua values
+*/
+typedef union {
+ GCObject *gc;
+ void *p;
+ lua_Number n;
+ int b;
+} Value;
+
+
+/*
+** Tagged Values
+*/
+
+#define TValuefields Value value; int tt
+
+typedef struct lua_TValue {
+ TValuefields;
+} TValue;
+
+
+/* Macros to test type */
+#define ttisnil(o) (ttype(o) == LUA_TNIL)
+#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
+#define ttisstring(o) (ttype(o) == LUA_TSTRING)
+#define ttistable(o) (ttype(o) == LUA_TTABLE)
+#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
+#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
+#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
+#define ttisthread(o) (ttype(o) == LUA_TTHREAD)
+#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
+
+/* Macros to access values */
+#define ttype(o) ((o)->tt)
+#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
+#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
+#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
+#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
+#define tsvalue(o) (&rawtsvalue(o)->tsv)
+#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
+#define uvalue(o) (&rawuvalue(o)->uv)
+#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl)
+#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h)
+#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b)
+#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th)
+
+#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
+
+/*
+** for internal debug only
+*/
+#define checkconsistency(obj) \
+ lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
+
+#define checkliveness(g,obj) \
+ lua_assert(!iscollectable(obj) || \
+ ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))
+
+
+/* Macros to set values */
+#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
+
+#define setnvalue(obj,x) \
+ { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
+
+#define setpvalue(obj,x) \
+ { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }
+
+#define setbvalue(obj,x) \
+ { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; }
+
+#define setsvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \
+ checkliveness(G(L),i_o); }
+
+#define setuvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \
+ checkliveness(G(L),i_o); }
+
+#define setthvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \
+ checkliveness(G(L),i_o); }
+
+#define setclvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \
+ checkliveness(G(L),i_o); }
+
+#define sethvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \
+ checkliveness(G(L),i_o); }
+
+#define setptvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \
+ checkliveness(G(L),i_o); }
+
+
+
+
+#define setobj(L,obj1,obj2) \
+ { const TValue *o2=(obj2); TValue *o1=(obj1); \
+ o1->value = o2->value; o1->tt=o2->tt; \
+ checkliveness(G(L),o1); }
+
+
+/*
+** different types of sets, according to destination
+*/
+
+/* from stack to (same) stack */
+#define setobjs2s setobj
+/* to stack (not from same stack) */
+#define setobj2s setobj
+#define setsvalue2s setsvalue
+#define sethvalue2s sethvalue
+#define setptvalue2s setptvalue
+/* from table to same table */
+#define setobjt2t setobj
+/* to table */
+#define setobj2t setobj
+/* to new object */
+#define setobj2n setobj
+#define setsvalue2n setsvalue
+
+#define setttype(obj, tt) (ttype(obj) = (tt))
+
+
+#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
+
+
+
+typedef TValue *StkId; /* index to stack elements */
+
+
+/*
+** String headers for string table
+*/
+typedef union TString {
+ L_Umaxalign dummy; /* ensures maximum alignment for strings */
+ struct {
+ CommonHeader;
+ lu_byte reserved;
+ unsigned int hash;
+ size_t len;
+ } tsv;
+} TString;
+
+
+#define getstr(ts) cast(const char *, (ts) + 1)
+#define svalue(o) getstr(tsvalue(o))
+
+
+
+typedef union Udata {
+ L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
+ struct {
+ CommonHeader;
+ struct Table *metatable;
+ struct Table *env;
+ size_t len;
+ } uv;
+} Udata;
+
+
+
+
+/*
+** Function Prototypes
+*/
+typedef struct Proto {
+ CommonHeader;
+ TValue *k; /* constants used by the function */
+ Instruction *code;
+ struct Proto **p; /* functions defined inside the function */
+ int *lineinfo; /* map from opcodes to source lines */
+ struct LocVar *locvars; /* information about local variables */
+ TString **upvalues; /* upvalue names */
+ TString *source;
+ int sizeupvalues;
+ int sizek; /* size of `k' */
+ int sizecode;
+ int sizelineinfo;
+ int sizep; /* size of `p' */
+ int sizelocvars;
+ int linedefined;
+ int lastlinedefined;
+ GCObject *gclist;
+ lu_byte nups; /* number of upvalues */
+ lu_byte numparams;
+ lu_byte is_vararg;
+ lu_byte maxstacksize;
+} Proto;
+
+
+/* masks for new-style vararg */
+#define VARARG_HASARG 1
+#define VARARG_ISVARARG 2
+#define VARARG_NEEDSARG 4
+
+
+typedef struct LocVar {
+ TString *varname;
+ int startpc; /* first point where variable is active */
+ int endpc; /* first point where variable is dead */
+} LocVar;
+
+
+
+/*
+** Upvalues
+*/
+
+typedef struct UpVal {
+ CommonHeader;
+ TValue *v; /* points to stack or to its own value */
+ union {
+ TValue value; /* the value (when closed) */
+ struct { /* double linked list (when open) */
+ struct UpVal *prev;
+ struct UpVal *next;
+ } l;
+ } u;
+} UpVal;
+
+
+/*
+** Closures
+*/
+
+#define ClosureHeader \
+ CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \
+ struct Table *env
+
+typedef struct CClosure {
+ ClosureHeader;
+ lua_CFunction f;
+ TValue upvalue[1];
+} CClosure;
+
+
+typedef struct LClosure {
+ ClosureHeader;
+ struct Proto *p;
+ UpVal *upvals[1];
+} LClosure;
+
+
+typedef union Closure {
+ CClosure c;
+ LClosure l;
+} Closure;
+
+
+#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC)
+#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC)
+
+
+/*
+** Tables
+*/
+
+typedef union TKey {
+ struct {
+ TValuefields;
+ struct Node *next; /* for chaining */
+ } nk;
+ TValue tvk;
+} TKey;
+
+
+typedef struct Node {
+ TValue i_val;
+ TKey i_key;
+} Node;
+
+
+typedef struct Table {
+ CommonHeader;
+ lu_byte flags; /* 1<<p means tagmethod(p) is not present */
+ lu_byte lsizenode; /* log2 of size of `node' array */
+ struct Table *metatable;
+ TValue *array; /* array part */
+ Node *node;
+ Node *lastfree; /* any free position is before this position */
+ GCObject *gclist;
+ int sizearray; /* size of `array' array */
+} Table;
+
+
+
+/*
+** `module' operation for hashing (size is always a power of 2)
+*/
+#define lmod(s,size) \
+ (check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))))
+
+
+#define twoto(x) (1<<(x))
+#define sizenode(t) (twoto((t)->lsizenode))
+
+
+#define luaO_nilobject (&luaO_nilobject_)
+
+LUAI_DATA const TValue luaO_nilobject_;
+
+#define ceillog2(x) (luaO_log2((x)-1) + 1)
+
+LUAI_FUNC int luaO_log2 (unsigned int x);
+LUAI_FUNC int luaO_int2fb (unsigned int x);
+LUAI_FUNC int luaO_fb2int (int x);
+LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);
+LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);
+LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
+ va_list argp);
+LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
+LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
+
+
+#endif
+
diff --git a/Build/source/libs/lua51/lopcodes.c b/Build/source/libs/lua51/lopcodes.c
new file mode 100644
index 00000000000..bf9cd522c26
--- /dev/null
+++ b/Build/source/libs/lua51/lopcodes.c
@@ -0,0 +1,102 @@
+/*
+** $Id: lopcodes.c,v 1.37 2005/11/08 19:45:36 roberto Exp $
+** See Copyright Notice in lua.h
+*/
+
+
+#define lopcodes_c
+#define LUA_CORE
+
+
+#include "lopcodes.h"
+
+
+/* ORDER OP */
+
+const char *const luaP_opnames[NUM_OPCODES+1] = {
+ "MOVE",
+ "LOADK",
+ "LOADBOOL",
+ "LOADNIL",
+ "GETUPVAL",
+ "GETGLOBAL",
+ "GETTABLE",
+ "SETGLOBAL",
+ "SETUPVAL",
+ "SETTABLE",
+ "NEWTABLE",
+ "SELF",
+ "ADD",
+ "SUB",
+ "MUL",
+ "DIV",
+ "MOD",
+ "POW",
+ "UNM",
+ "NOT",
+ "LEN",
+ "CONCAT",
+ "JMP",
+ "EQ",
+ "LT",
+ "LE",
+ "TEST",
+ "TESTSET",
+ "CALL",
+ "TAILCALL",
+ "RETURN",
+ "FORLOOP",
+ "FORPREP",
+ "TFORLOOP",
+ "SETLIST",
+ "CLOSE",
+ "CLOSURE",
+ "VARARG",
+ NULL
+};
+
+
+#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))
+
+const lu_byte luaP_opmodes[NUM_OPCODES] = {
+/* T A B C mode opcode */
+ opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */
+ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */
+ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */
+ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */
+ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */
+ ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */
+ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */
+ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */
+ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */
+ ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */
+ ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */
+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */
+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */
+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */
+ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */
+ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */
+ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */
+ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */
+ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */
+ ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */
+ ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */
+ ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */
+ ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
+ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */
+};
+
diff --git a/Build/source/libs/lua51/lopcodes.h b/Build/source/libs/lua51/lopcodes.h
new file mode 100644
index 00000000000..48105f1e722
--- /dev/null
+++ b/Build/source/libs/lua51/lopcodes.h
@@ -0,0 +1,268 @@
+/*
+** $Id: lopcodes.h,v 1.125 2006/03/14 19:04:44 roberto Exp $
+** Opcodes for Lua virtual machine
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lopcodes_h
+#define lopcodes_h
+
+#include "llimits.h"
+
+
+/*===========================================================================
+ We assume that instructions are unsigned numbers.
+ All instructions have an opcode in the first 6 bits.
+ Instructions can have the following fields:
+ `A' : 8 bits
+ `B' : 9 bits
+ `C' : 9 bits
+ `Bx' : 18 bits (`B' and `C' together)
+ `sBx' : signed Bx
+
+ A signed argument is represented in excess K; that is, the number
+ value is the unsigned value minus K. K is exactly the maximum value
+ for that argument (so that -max is represented by 0, and +max is
+ represented by 2*max), which is half the maximum for the corresponding
+ unsigned argument.
+===========================================================================*/
+
+
+enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
+
+
+/*
+** size and position of opcode arguments.
+*/
+#define SIZE_C 9
+#define SIZE_B 9
+#define SIZE_Bx (SIZE_C + SIZE_B)
+#define SIZE_A 8
+
+#define SIZE_OP 6
+
+#define POS_OP 0
+#define POS_A (POS_OP + SIZE_OP)
+#define POS_C (POS_A + SIZE_A)
+#define POS_B (POS_C + SIZE_C)
+#define POS_Bx POS_C
+
+
+/*
+** limits for opcode arguments.
+** we use (signed) int to manipulate most arguments,
+** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
+*/
+#if SIZE_Bx < LUAI_BITSINT-1
+#define MAXARG_Bx ((1<<SIZE_Bx)-1)
+#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */
+#else
+#define MAXARG_Bx MAX_INT
+#define MAXARG_sBx MAX_INT
+#endif
+
+
+#define MAXARG_A ((1<<SIZE_A)-1)
+#define MAXARG_B ((1<<SIZE_B)-1)
+#define MAXARG_C ((1<<SIZE_C)-1)
+
+
+/* creates a mask with `n' 1 bits at position `p' */
+#define MASK1(n,p) ((~((~(Instruction)0)<<n))<<p)
+
+/* creates a mask with `n' 0 bits at position `p' */
+#define MASK0(n,p) (~MASK1(n,p))
+
+/*
+** the following macros help to manipulate instructions
+*/
+
+#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))
+#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
+ ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))
+
+#define GETARG_A(i) (cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0)))
+#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \
+ ((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))
+
+#define GETARG_B(i) (cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0)))
+#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \
+ ((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B))))
+
+#define GETARG_C(i) (cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0)))
+#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \
+ ((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C))))
+
+#define GETARG_Bx(i) (cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0)))
+#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \
+ ((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx))))
+
+#define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx)
+#define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))
+
+
+#define CREATE_ABC(o,a,b,c) ((cast(Instruction, o)<<POS_OP) \
+ | (cast(Instruction, a)<<POS_A) \
+ | (cast(Instruction, b)<<POS_B) \
+ | (cast(Instruction, c)<<POS_C))
+
+#define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \
+ | (cast(Instruction, a)<<POS_A) \
+ | (cast(Instruction, bc)<<POS_Bx))
+
+
+/*
+** Macros to operate RK indices
+*/
+
+/* this bit 1 means constant (0 means register) */
+#define BITRK (1 << (SIZE_B - 1))
+
+/* test whether value is a constant */
+#define ISK(x) ((x) & BITRK)
+
+/* gets the index of the constant */
+#define INDEXK(r) ((int)(r) & ~BITRK)
+
+#define MAXINDEXRK (BITRK - 1)
+
+/* code a constant index as a RK value */
+#define RKASK(x) ((x) | BITRK)
+
+
+/*
+** invalid register that fits in 8 bits
+*/
+#define NO_REG MAXARG_A
+
+
+/*
+** R(x) - register
+** Kst(x) - constant (in constant table)
+** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
+*/
+
+
+/*
+** grep "ORDER OP" if you change these enums
+*/
+
+typedef enum {
+/*----------------------------------------------------------------------
+name args description
+------------------------------------------------------------------------*/
+OP_MOVE,/* A B R(A) := R(B) */
+OP_LOADK,/* A Bx R(A) := Kst(Bx) */
+OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
+OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */
+OP_GETUPVAL,/* A B R(A) := UpValue[B] */
+
+OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */
+OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
+
+OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */
+OP_SETUPVAL,/* A B UpValue[B] := R(A) */
+OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */
+
+OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
+
+OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
+
+OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
+OP_SUB,/* A B C R(A) := RK(B) - RK(C) */
+OP_MUL,/* A B C R(A) := RK(B) * RK(C) */
+OP_DIV,/* A B C R(A) := RK(B) / RK(C) */
+OP_MOD,/* A B C R(A) := RK(B) % RK(C) */
+OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */
+OP_UNM,/* A B R(A) := -R(B) */
+OP_NOT,/* A B R(A) := not R(B) */
+OP_LEN,/* A B R(A) := length of R(B) */
+
+OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
+
+OP_JMP,/* sBx pc+=sBx */
+
+OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
+OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
+OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
+
+OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
+OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
+
+OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
+OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
+OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
+
+OP_FORLOOP,/* A sBx R(A)+=R(A+2);
+ if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
+OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */
+
+OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
+ if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */
+OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
+
+OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
+OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
+
+OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
+} OpCode;
+
+
+#define NUM_OPCODES (cast(int, OP_VARARG) + 1)
+
+
+
+/*===========================================================================
+ Notes:
+ (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
+ and can be 0: OP_CALL then sets `top' to last_result+1, so
+ next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
+
+ (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
+ set top (like in OP_CALL with C == 0).
+
+ (*) In OP_RETURN, if (B == 0) then return up to `top'
+
+ (*) In OP_SETLIST, if (B == 0) then B = `top';
+ if (C == 0) then next `instruction' is real C
+
+ (*) For comparisons, A specifies what condition the test should accept
+ (true or false).
+
+ (*) All `skips' (pc++) assume that next instruction is a jump
+===========================================================================*/
+
+
+/*
+** masks for instruction properties. The format is:
+** bits 0-1: op mode
+** bits 2-3: C arg mode
+** bits 4-5: B arg mode
+** bit 6: instruction set register A
+** bit 7: operator is a test
+*/
+
+enum OpArgMask {
+ OpArgN, /* argument is not used */
+ OpArgU, /* argument is used */
+ OpArgR, /* argument is a register or a jump offset */
+ OpArgK /* argument is a constant or register/constant */
+};
+
+LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES];
+
+#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3))
+#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))
+#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3))
+#define testAMode(m) (luaP_opmodes[m] & (1 << 6))
+#define testTMode(m) (luaP_opmodes[m] & (1 << 7))
+
+
+LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */
+
+
+/* number of list items to accumulate before a SETLIST instruction */
+#define LFIELDS_PER_FLUSH 50
+
+
+#endif
diff --git a/Build/source/libs/lua51/loslib.c b/Build/source/libs/lua51/loslib.c
new file mode 100644
index 00000000000..fdda47414d0
--- /dev/null
+++ b/Build/source/libs/lua51/loslib.c
@@ -0,0 +1,244 @@
+/*
+** $Id: loslib.c,v 1.20 2006/09/19 13:57:08 roberto Exp $
+** Standard Operating System library
+** See Copyright Notice in lua.h
+*/
+
+
+#include <errno.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#define loslib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+static int os_pushresult (lua_State *L, int i, const char *filename) {
+ int en = errno; /* calls to Lua API may change this value */
+ if (i) {
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+ else {
+ lua_pushnil(L);
+ lua_pushfstring(L, "%s: %s", filename, strerror(en));
+ lua_pushinteger(L, en);
+ return 3;
+ }
+}
+
+
+static int os_execute (lua_State *L) {
+ lua_pushinteger(L, system(luaL_optstring(L, 1, NULL)));
+ return 1;
+}
+
+
+static int os_remove (lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ return os_pushresult(L, remove(filename) == 0, filename);
+}
+
+
+static int os_rename (lua_State *L) {
+ const char *fromname = luaL_checkstring(L, 1);
+ const char *toname = luaL_checkstring(L, 2);
+ return os_pushresult(L, rename(fromname, toname) == 0, fromname);
+}
+
+
+static int os_tmpname (lua_State *L) {
+ char buff[LUA_TMPNAMBUFSIZE];
+ int err;
+ lua_tmpnam(buff, err);
+ if (err)
+ return luaL_error(L, "unable to generate a unique filename");
+ lua_pushstring(L, buff);
+ return 1;
+}
+
+
+static int os_getenv (lua_State *L) {
+ lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
+ return 1;
+}
+
+
+static int os_clock (lua_State *L) {
+ lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
+ return 1;
+}
+
+
+/*
+** {======================================================
+** Time/Date operations
+** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
+** wday=%w+1, yday=%j, isdst=? }
+** =======================================================
+*/
+
+static void setfield (lua_State *L, const char *key, int value) {
+ lua_pushinteger(L, value);
+ lua_setfield(L, -2, key);
+}
+
+static void setboolfield (lua_State *L, const char *key, int value) {
+ if (value < 0) /* undefined? */
+ return; /* does not set field */
+ lua_pushboolean(L, value);
+ lua_setfield(L, -2, key);
+}
+
+static int getboolfield (lua_State *L, const char *key) {
+ int res;
+ lua_getfield(L, -1, key);
+ res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
+ lua_pop(L, 1);
+ return res;
+}
+
+
+static int getfield (lua_State *L, const char *key, int d) {
+ int res;
+ lua_getfield(L, -1, key);
+ if (lua_isnumber(L, -1))
+ res = (int)lua_tointeger(L, -1);
+ else {
+ if (d < 0)
+ return luaL_error(L, "field " LUA_QS " missing in date table", key);
+ res = d;
+ }
+ lua_pop(L, 1);
+ return res;
+}
+
+
+static int os_date (lua_State *L) {
+ const char *s = luaL_optstring(L, 1, "%c");
+ time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
+ struct tm *stm;
+ if (*s == '!') { /* UTC? */
+ stm = gmtime(&t);
+ s++; /* skip `!' */
+ }
+ else
+ stm = localtime(&t);
+ if (stm == NULL) /* invalid date? */
+ lua_pushnil(L);
+ else if (strcmp(s, "*t") == 0) {
+ lua_createtable(L, 0, 9); /* 9 = number of fields */
+ setfield(L, "sec", stm->tm_sec);
+ setfield(L, "min", stm->tm_min);
+ setfield(L, "hour", stm->tm_hour);
+ setfield(L, "day", stm->tm_mday);
+ setfield(L, "month", stm->tm_mon+1);
+ setfield(L, "year", stm->tm_year+1900);
+ setfield(L, "wday", stm->tm_wday+1);
+ setfield(L, "yday", stm->tm_yday+1);
+ setboolfield(L, "isdst", stm->tm_isdst);
+ }
+ else {
+ char cc[3];
+ luaL_Buffer b;
+ cc[0] = '%'; cc[2] = '\0';
+ luaL_buffinit(L, &b);
+ for (; *s; s++) {
+ if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */
+ luaL_addchar(&b, *s);
+ else {
+ size_t reslen;
+ char buff[200]; /* should be big enough for any conversion result */
+ cc[1] = *(++s);
+ reslen = strftime(buff, sizeof(buff), cc, stm);
+ luaL_addlstring(&b, buff, reslen);
+ }
+ }
+ luaL_pushresult(&b);
+ }
+ return 1;
+}
+
+
+static int os_time (lua_State *L) {
+ time_t t;
+ if (lua_isnoneornil(L, 1)) /* called without args? */
+ t = time(NULL); /* get current time */
+ else {
+ struct tm ts;
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_settop(L, 1); /* make sure table is at the top */
+ ts.tm_sec = getfield(L, "sec", 0);
+ ts.tm_min = getfield(L, "min", 0);
+ ts.tm_hour = getfield(L, "hour", 12);
+ ts.tm_mday = getfield(L, "day", -1);
+ ts.tm_mon = getfield(L, "month", -1) - 1;
+ ts.tm_year = getfield(L, "year", -1) - 1900;
+ ts.tm_isdst = getboolfield(L, "isdst");
+ t = mktime(&ts);
+ }
+ if (t == (time_t)(-1))
+ lua_pushnil(L);
+ else
+ lua_pushnumber(L, (lua_Number)t);
+ return 1;
+}
+
+
+static int os_difftime (lua_State *L) {
+ lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
+ (time_t)(luaL_optnumber(L, 2, 0))));
+ return 1;
+}
+
+/* }====================================================== */
+
+
+static int os_setlocale (lua_State *L) {
+ static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
+ LC_NUMERIC, LC_TIME};
+ static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
+ "numeric", "time", NULL};
+ const char *l = luaL_optstring(L, 1, NULL);
+ int op = luaL_checkoption(L, 2, "all", catnames);
+ lua_pushstring(L, setlocale(cat[op], l));
+ return 1;
+}
+
+
+static int os_exit (lua_State *L) {
+ exit(luaL_optint(L, 1, EXIT_SUCCESS));
+ return 0; /* to avoid warnings */
+}
+
+static const luaL_Reg syslib[] = {
+ {"clock", os_clock},
+ {"date", os_date},
+ {"difftime", os_difftime},
+ {"execute", os_execute},
+ {"exit", os_exit},
+ {"getenv", os_getenv},
+ {"remove", os_remove},
+ {"rename", os_rename},
+ {"setlocale", os_setlocale},
+ {"time", os_time},
+ {"tmpname", os_tmpname},
+ {NULL, NULL}
+};
+
+/* }====================================================== */
+
+
+
+LUALIB_API int luaopen_os (lua_State *L) {
+ luaL_register(L, LUA_OSLIBNAME, syslib);
+ return 1;
+}
+
diff --git a/Build/source/libs/lua51/lparser.c b/Build/source/libs/lua51/lparser.c
new file mode 100644
index 00000000000..6c473c41d2f
--- /dev/null
+++ b/Build/source/libs/lua51/lparser.c
@@ -0,0 +1,1337 @@
+/*
+** $Id: lparser.c,v 2.42a 2006/06/05 15:57:59 roberto Exp $
+** Lua Parser
+** See Copyright Notice in lua.h
+*/
+
+
+#include <string.h>
+
+#define lparser_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lcode.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "llex.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+
+
+
+#define hasmultret(k) ((k) == VCALL || (k) == VVARARG)
+
+#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]])
+
+#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m)
+
+
+/*
+** nodes for block list (list of active blocks)
+*/
+typedef struct BlockCnt {
+ struct BlockCnt *previous; /* chain */
+ int breaklist; /* list of jumps out of this loop */
+ lu_byte nactvar; /* # active locals outside the breakable structure */
+ lu_byte upval; /* true if some variable in the block is an upvalue */
+ lu_byte isbreakable; /* true if `block' is a loop */
+} BlockCnt;
+
+
+
+/*
+** prototypes for recursive non-terminal functions
+*/
+static void chunk (LexState *ls);
+static void expr (LexState *ls, expdesc *v);
+
+
+static void anchor_token (LexState *ls) {
+ if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {
+ TString *ts = ls->t.seminfo.ts;
+ luaX_newstring(ls, getstr(ts), ts->tsv.len);
+ }
+}
+
+
+static void error_expected (LexState *ls, int token) {
+ luaX_syntaxerror(ls,
+ luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token)));
+}
+
+
+static void errorlimit (FuncState *fs, int limit, const char *what) {
+ const char *msg = (fs->f->linedefined == 0) ?
+ luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) :
+ luaO_pushfstring(fs->L, "function at line %d has more than %d %s",
+ fs->f->linedefined, limit, what);
+ luaX_lexerror(fs->ls, msg, 0);
+}
+
+
+static int testnext (LexState *ls, int c) {
+ if (ls->t.token == c) {
+ luaX_next(ls);
+ return 1;
+ }
+ else return 0;
+}
+
+
+static void check (LexState *ls, int c) {
+ if (ls->t.token != c)
+ error_expected(ls, c);
+}
+
+static void checknext (LexState *ls, int c) {
+ check(ls, c);
+ luaX_next(ls);
+}
+
+
+#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); }
+
+
+
+static void check_match (LexState *ls, int what, int who, int where) {
+ if (!testnext(ls, what)) {
+ if (where == ls->linenumber)
+ error_expected(ls, what);
+ else {
+ luaX_syntaxerror(ls, luaO_pushfstring(ls->L,
+ LUA_QS " expected (to close " LUA_QS " at line %d)",
+ luaX_token2str(ls, what), luaX_token2str(ls, who), where));
+ }
+ }
+}
+
+
+static TString *str_checkname (LexState *ls) {
+ TString *ts;
+ check(ls, TK_NAME);
+ ts = ls->t.seminfo.ts;
+ luaX_next(ls);
+ return ts;
+}
+
+
+static void init_exp (expdesc *e, expkind k, int i) {
+ e->f = e->t = NO_JUMP;
+ e->k = k;
+ e->u.s.info = i;
+}
+
+
+static void codestring (LexState *ls, expdesc *e, TString *s) {
+ init_exp(e, VK, luaK_stringK(ls->fs, s));
+}
+
+
+static void checkname(LexState *ls, expdesc *e) {
+ codestring(ls, e, str_checkname(ls));
+}
+
+
+static int registerlocalvar (LexState *ls, TString *varname) {
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f;
+ int oldsize = f->sizelocvars;
+ luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,
+ LocVar, SHRT_MAX, "too many local variables");
+ while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL;
+ f->locvars[fs->nlocvars].varname = varname;
+ luaC_objbarrier(ls->L, f, varname);
+ return fs->nlocvars++;
+}
+
+
+#define new_localvarliteral(ls,v,n) \
+ new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n)
+
+
+static void new_localvar (LexState *ls, TString *name, int n) {
+ FuncState *fs = ls->fs;
+ luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables");
+ fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name));
+}
+
+
+static void adjustlocalvars (LexState *ls, int nvars) {
+ FuncState *fs = ls->fs;
+ fs->nactvar = cast_byte(fs->nactvar + nvars);
+ for (; nvars; nvars--) {
+ getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc;
+ }
+}
+
+
+static void removevars (LexState *ls, int tolevel) {
+ FuncState *fs = ls->fs;
+ while (fs->nactvar > tolevel)
+ getlocvar(fs, --fs->nactvar).endpc = fs->pc;
+}
+
+
+static int indexupvalue (FuncState *fs, TString *name, expdesc *v) {
+ int i;
+ Proto *f = fs->f;
+ int oldsize = f->sizeupvalues;
+ for (i=0; i<f->nups; i++) {
+ if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) {
+ lua_assert(f->upvalues[i] == name);
+ return i;
+ }
+ }
+ /* new one */
+ luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues");
+ luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues,
+ TString *, MAX_INT, "");
+ while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL;
+ f->upvalues[f->nups] = name;
+ luaC_objbarrier(fs->L, f, name);
+ lua_assert(v->k == VLOCAL || v->k == VUPVAL);
+ fs->upvalues[f->nups].k = cast_byte(v->k);
+ fs->upvalues[f->nups].info = cast_byte(v->u.s.info);
+ return f->nups++;
+}
+
+
+static int searchvar (FuncState *fs, TString *n) {
+ int i;
+ for (i=fs->nactvar-1; i >= 0; i--) {
+ if (n == getlocvar(fs, i).varname)
+ return i;
+ }
+ return -1; /* not found */
+}
+
+
+static void markupval (FuncState *fs, int level) {
+ BlockCnt *bl = fs->bl;
+ while (bl && bl->nactvar > level) bl = bl->previous;
+ if (bl) bl->upval = 1;
+}
+
+
+static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
+ if (fs == NULL) { /* no more levels? */
+ init_exp(var, VGLOBAL, NO_REG); /* default is global variable */
+ return VGLOBAL;
+ }
+ else {
+ int v = searchvar(fs, n); /* look up at current level */
+ if (v >= 0) {
+ init_exp(var, VLOCAL, v);
+ if (!base)
+ markupval(fs, v); /* local will be used as an upval */
+ return VLOCAL;
+ }
+ else { /* not found at current level; try upper one */
+ if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL)
+ return VGLOBAL;
+ var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */
+ var->k = VUPVAL; /* upvalue in this level */
+ return VUPVAL;
+ }
+ }
+}
+
+
+static void singlevar (LexState *ls, expdesc *var) {
+ TString *varname = str_checkname(ls);
+ FuncState *fs = ls->fs;
+ if (singlevaraux(fs, varname, var, 1) == VGLOBAL)
+ var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */
+}
+
+
+static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
+ FuncState *fs = ls->fs;
+ int extra = nvars - nexps;
+ if (hasmultret(e->k)) {
+ extra++; /* includes call itself */
+ if (extra < 0) extra = 0;
+ luaK_setreturns(fs, e, extra); /* last exp. provides the difference */
+ if (extra > 1) luaK_reserveregs(fs, extra-1);
+ }
+ else {
+ if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */
+ if (extra > 0) {
+ int reg = fs->freereg;
+ luaK_reserveregs(fs, extra);
+ luaK_nil(fs, reg, extra);
+ }
+ }
+}
+
+
+static void enterlevel (LexState *ls) {
+ if (++ls->L->nCcalls > LUAI_MAXCCALLS)
+ luaX_lexerror(ls, "chunk has too many syntax levels", 0);
+}
+
+
+#define leavelevel(ls) ((ls)->L->nCcalls--)
+
+
+static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {
+ bl->breaklist = NO_JUMP;
+ bl->isbreakable = isbreakable;
+ bl->nactvar = fs->nactvar;
+ bl->upval = 0;
+ bl->previous = fs->bl;
+ fs->bl = bl;
+ lua_assert(fs->freereg == fs->nactvar);
+}
+
+
+static void leaveblock (FuncState *fs) {
+ BlockCnt *bl = fs->bl;
+ fs->bl = bl->previous;
+ removevars(fs->ls, bl->nactvar);
+ if (bl->upval)
+ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
+ /* a block either controls scope or breaks (never both) */
+ lua_assert(!bl->isbreakable || !bl->upval);
+ lua_assert(bl->nactvar == fs->nactvar);
+ fs->freereg = fs->nactvar; /* free registers */
+ luaK_patchtohere(fs, bl->breaklist);
+}
+
+
+static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f;
+ int oldsize = f->sizep;
+ int i;
+ luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,
+ MAXARG_Bx, "constant table overflow");
+ while (oldsize < f->sizep) f->p[oldsize++] = NULL;
+ f->p[fs->np++] = func->f;
+ luaC_objbarrier(ls->L, f, func->f);
+ init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
+ for (i=0; i<func->f->nups; i++) {
+ OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
+ luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0);
+ }
+}
+
+
+static void open_func (LexState *ls, FuncState *fs) {
+ lua_State *L = ls->L;
+ Proto *f = luaF_newproto(L);
+ fs->f = f;
+ fs->prev = ls->fs; /* linked list of funcstates */
+ fs->ls = ls;
+ fs->L = L;
+ ls->fs = fs;
+ fs->pc = 0;
+ fs->lasttarget = -1;
+ fs->jpc = NO_JUMP;
+ fs->freereg = 0;
+ fs->nk = 0;
+ fs->np = 0;
+ fs->nlocvars = 0;
+ fs->nactvar = 0;
+ fs->bl = NULL;
+ f->source = ls->source;
+ f->maxstacksize = 2; /* registers 0/1 are always valid */
+ fs->h = luaH_new(L, 0, 0);
+ /* anchor table of constants and prototype (to avoid being collected) */
+ sethvalue2s(L, L->top, fs->h);
+ incr_top(L);
+ setptvalue2s(L, L->top, f);
+ incr_top(L);
+}
+
+
+static void close_func (LexState *ls) {
+ lua_State *L = ls->L;
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f;
+ removevars(ls, 0);
+ luaK_ret(fs, 0, 0); /* final return */
+ luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
+ f->sizecode = fs->pc;
+ luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
+ f->sizelineinfo = fs->pc;
+ luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);
+ f->sizek = fs->nk;
+ luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);
+ f->sizep = fs->np;
+ luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);
+ f->sizelocvars = fs->nlocvars;
+ luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *);
+ f->sizeupvalues = f->nups;
+ lua_assert(luaG_checkcode(f));
+ lua_assert(fs->bl == NULL);
+ ls->fs = fs->prev;
+ L->top -= 2; /* remove table and prototype from the stack */
+ /* last token read was anchored in defunct function; must reanchor it */
+ if (fs) anchor_token(ls);
+}
+
+
+Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
+ struct LexState lexstate;
+ struct FuncState funcstate;
+ lexstate.buff = buff;
+ luaX_setinput(L, &lexstate, z, luaS_new(L, name));
+ open_func(&lexstate, &funcstate);
+ funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */
+ luaX_next(&lexstate); /* read first token */
+ chunk(&lexstate);
+ check(&lexstate, TK_EOS);
+ close_func(&lexstate);
+ lua_assert(funcstate.prev == NULL);
+ lua_assert(funcstate.f->nups == 0);
+ lua_assert(lexstate.fs == NULL);
+ return funcstate.f;
+}
+
+
+
+/*============================================================*/
+/* GRAMMAR RULES */
+/*============================================================*/
+
+
+static void field (LexState *ls, expdesc *v) {
+ /* field -> ['.' | ':'] NAME */
+ FuncState *fs = ls->fs;
+ expdesc key;
+ luaK_exp2anyreg(fs, v);
+ luaX_next(ls); /* skip the dot or colon */
+ checkname(ls, &key);
+ luaK_indexed(fs, v, &key);
+}
+
+
+static void yindex (LexState *ls, expdesc *v) {
+ /* index -> '[' expr ']' */
+ luaX_next(ls); /* skip the '[' */
+ expr(ls, v);
+ luaK_exp2val(ls->fs, v);
+ checknext(ls, ']');
+}
+
+
+/*
+** {======================================================================
+** Rules for Constructors
+** =======================================================================
+*/
+
+
+struct ConsControl {
+ expdesc v; /* last list item read */
+ expdesc *t; /* table descriptor */
+ int nh; /* total number of `record' elements */
+ int na; /* total number of array elements */
+ int tostore; /* number of array elements pending to be stored */
+};
+
+
+static void recfield (LexState *ls, struct ConsControl *cc) {
+ /* recfield -> (NAME | `['exp1`]') = exp1 */
+ FuncState *fs = ls->fs;
+ int reg = ls->fs->freereg;
+ expdesc key, val;
+ int rkkey;
+ if (ls->t.token == TK_NAME) {
+ luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
+ checkname(ls, &key);
+ }
+ else /* ls->t.token == '[' */
+ yindex(ls, &key);
+ cc->nh++;
+ checknext(ls, '=');
+ rkkey = luaK_exp2RK(fs, &key);
+ expr(ls, &val);
+ luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val));
+ fs->freereg = reg; /* free registers */
+}
+
+
+static void closelistfield (FuncState *fs, struct ConsControl *cc) {
+ if (cc->v.k == VVOID) return; /* there is no list item */
+ luaK_exp2nextreg(fs, &cc->v);
+ cc->v.k = VVOID;
+ if (cc->tostore == LFIELDS_PER_FLUSH) {
+ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */
+ cc->tostore = 0; /* no more items pending */
+ }
+}
+
+
+static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
+ if (cc->tostore == 0) return;
+ if (hasmultret(cc->v.k)) {
+ luaK_setmultret(fs, &cc->v);
+ luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET);
+ cc->na--; /* do not count last expression (unknown number of elements) */
+ }
+ else {
+ if (cc->v.k != VVOID)
+ luaK_exp2nextreg(fs, &cc->v);
+ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);
+ }
+}
+
+
+static void listfield (LexState *ls, struct ConsControl *cc) {
+ expr(ls, &cc->v);
+ luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor");
+ cc->na++;
+ cc->tostore++;
+}
+
+
+static void constructor (LexState *ls, expdesc *t) {
+ /* constructor -> ?? */
+ FuncState *fs = ls->fs;
+ int line = ls->linenumber;
+ int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
+ struct ConsControl cc;
+ cc.na = cc.nh = cc.tostore = 0;
+ cc.t = t;
+ init_exp(t, VRELOCABLE, pc);
+ init_exp(&cc.v, VVOID, 0); /* no value (yet) */
+ luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */
+ checknext(ls, '{');
+ do {
+ lua_assert(cc.v.k == VVOID || cc.tostore > 0);
+ if (ls->t.token == '}') break;
+ closelistfield(fs, &cc);
+ switch(ls->t.token) {
+ case TK_NAME: { /* may be listfields or recfields */
+ luaX_lookahead(ls);
+ if (ls->lookahead.token != '=') /* expression? */
+ listfield(ls, &cc);
+ else
+ recfield(ls, &cc);
+ break;
+ }
+ case '[': { /* constructor_item -> recfield */
+ recfield(ls, &cc);
+ break;
+ }
+ default: { /* constructor_part -> listfield */
+ listfield(ls, &cc);
+ break;
+ }
+ }
+ } while (testnext(ls, ',') || testnext(ls, ';'));
+ check_match(ls, '}', '{', line);
+ lastlistfield(fs, &cc);
+ SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
+ SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */
+}
+
+/* }====================================================================== */
+
+
+
+static void parlist (LexState *ls) {
+ /* parlist -> [ param { `,' param } ] */
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f;
+ int nparams = 0;
+ f->is_vararg = 0;
+ if (ls->t.token != ')') { /* is `parlist' not empty? */
+ do {
+ switch (ls->t.token) {
+ case TK_NAME: { /* param -> NAME */
+ new_localvar(ls, str_checkname(ls), nparams++);
+ break;
+ }
+ case TK_DOTS: { /* param -> `...' */
+ luaX_next(ls);
+#if defined(LUA_COMPAT_VARARG)
+ /* use `arg' as default name */
+ new_localvarliteral(ls, "arg", nparams++);
+ f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG;
+#endif
+ f->is_vararg |= VARARG_ISVARARG;
+ break;
+ }
+ default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected");
+ }
+ } while (!f->is_vararg && testnext(ls, ','));
+ }
+ adjustlocalvars(ls, nparams);
+ f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG));
+ luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */
+}
+
+
+static void body (LexState *ls, expdesc *e, int needself, int line) {
+ /* body -> `(' parlist `)' chunk END */
+ FuncState new_fs;
+ open_func(ls, &new_fs);
+ new_fs.f->linedefined = line;
+ checknext(ls, '(');
+ if (needself) {
+ new_localvarliteral(ls, "self", 0);
+ adjustlocalvars(ls, 1);
+ }
+ parlist(ls);
+ checknext(ls, ')');
+ chunk(ls);
+ new_fs.f->lastlinedefined = ls->linenumber;
+ check_match(ls, TK_END, TK_FUNCTION, line);
+ close_func(ls);
+ pushclosure(ls, &new_fs, e);
+}
+
+
+static int explist1 (LexState *ls, expdesc *v) {
+ /* explist1 -> expr { `,' expr } */
+ int n = 1; /* at least one expression */
+ expr(ls, v);
+ while (testnext(ls, ',')) {
+ luaK_exp2nextreg(ls->fs, v);
+ expr(ls, v);
+ n++;
+ }
+ return n;
+}
+
+
+static void funcargs (LexState *ls, expdesc *f) {
+ FuncState *fs = ls->fs;
+ expdesc args;
+ int base, nparams;
+ int line = ls->linenumber;
+ switch (ls->t.token) {
+ case '(': { /* funcargs -> `(' [ explist1 ] `)' */
+ if (line != ls->lastline)
+ luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)");
+ luaX_next(ls);
+ if (ls->t.token == ')') /* arg list is empty? */
+ args.k = VVOID;
+ else {
+ explist1(ls, &args);
+ luaK_setmultret(fs, &args);
+ }
+ check_match(ls, ')', '(', line);
+ break;
+ }
+ case '{': { /* funcargs -> constructor */
+ constructor(ls, &args);
+ break;
+ }
+ case TK_STRING: { /* funcargs -> STRING */
+ codestring(ls, &args, ls->t.seminfo.ts);
+ luaX_next(ls); /* must use `seminfo' before `next' */
+ break;
+ }
+ default: {
+ luaX_syntaxerror(ls, "function arguments expected");
+ return;
+ }
+ }
+ lua_assert(f->k == VNONRELOC);
+ base = f->u.s.info; /* base register for call */
+ if (hasmultret(args.k))
+ nparams = LUA_MULTRET; /* open call */
+ else {
+ if (args.k != VVOID)
+ luaK_exp2nextreg(fs, &args); /* close last argument */
+ nparams = fs->freereg - (base+1);
+ }
+ init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
+ luaK_fixline(fs, line);
+ fs->freereg = base+1; /* call remove function and arguments and leaves
+ (unless changed) one result */
+}
+
+
+
+
+/*
+** {======================================================================
+** Expression parsing
+** =======================================================================
+*/
+
+
+static void prefixexp (LexState *ls, expdesc *v) {
+ /* prefixexp -> NAME | '(' expr ')' */
+ switch (ls->t.token) {
+ case '(': {
+ int line = ls->linenumber;
+ luaX_next(ls);
+ expr(ls, v);
+ check_match(ls, ')', '(', line);
+ luaK_dischargevars(ls->fs, v);
+ return;
+ }
+ case TK_NAME: {
+ singlevar(ls, v);
+ return;
+ }
+ default: {
+ luaX_syntaxerror(ls, "unexpected symbol");
+ return;
+ }
+ }
+}
+
+
+static void primaryexp (LexState *ls, expdesc *v) {
+ /* primaryexp ->
+ prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */
+ FuncState *fs = ls->fs;
+ prefixexp(ls, v);
+ for (;;) {
+ switch (ls->t.token) {
+ case '.': { /* field */
+ field(ls, v);
+ break;
+ }
+ case '[': { /* `[' exp1 `]' */
+ expdesc key;
+ luaK_exp2anyreg(fs, v);
+ yindex(ls, &key);
+ luaK_indexed(fs, v, &key);
+ break;
+ }
+ case ':': { /* `:' NAME funcargs */
+ expdesc key;
+ luaX_next(ls);
+ checkname(ls, &key);
+ luaK_self(fs, v, &key);
+ funcargs(ls, v);
+ break;
+ }
+ case '(': case TK_STRING: case '{': { /* funcargs */
+ luaK_exp2nextreg(fs, v);
+ funcargs(ls, v);
+ break;
+ }
+ default: return;
+ }
+ }
+}
+
+
+static void simpleexp (LexState *ls, expdesc *v) {
+ /* simpleexp -> NUMBER | STRING | NIL | true | false | ... |
+ constructor | FUNCTION body | primaryexp */
+ switch (ls->t.token) {
+ case TK_NUMBER: {
+ init_exp(v, VKNUM, 0);
+ v->u.nval = ls->t.seminfo.r;
+ break;
+ }
+ case TK_STRING: {
+ codestring(ls, v, ls->t.seminfo.ts);
+ break;
+ }
+ case TK_NIL: {
+ init_exp(v, VNIL, 0);
+ break;
+ }
+ case TK_TRUE: {
+ init_exp(v, VTRUE, 0);
+ break;
+ }
+ case TK_FALSE: {
+ init_exp(v, VFALSE, 0);
+ break;
+ }
+ case TK_DOTS: { /* vararg */
+ FuncState *fs = ls->fs;
+ check_condition(ls, fs->f->is_vararg,
+ "cannot use " LUA_QL("...") " outside a vararg function");
+ fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */
+ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
+ break;
+ }
+ case '{': { /* constructor */
+ constructor(ls, v);
+ return;
+ }
+ case TK_FUNCTION: {
+ luaX_next(ls);
+ body(ls, v, 0, ls->linenumber);
+ return;
+ }
+ default: {
+ primaryexp(ls, v);
+ return;
+ }
+ }
+ luaX_next(ls);
+}
+
+
+static UnOpr getunopr (int op) {
+ switch (op) {
+ case TK_NOT: return OPR_NOT;
+ case '-': return OPR_MINUS;
+ case '#': return OPR_LEN;
+ default: return OPR_NOUNOPR;
+ }
+}
+
+
+static BinOpr getbinopr (int op) {
+ switch (op) {
+ case '+': return OPR_ADD;
+ case '-': return OPR_SUB;
+ case '*': return OPR_MUL;
+ case '/': return OPR_DIV;
+ case '%': return OPR_MOD;
+ case '^': return OPR_POW;
+ case TK_CONCAT: return OPR_CONCAT;
+ case TK_NE: return OPR_NE;
+ case TK_EQ: return OPR_EQ;
+ case '<': return OPR_LT;
+ case TK_LE: return OPR_LE;
+ case '>': return OPR_GT;
+ case TK_GE: return OPR_GE;
+ case TK_AND: return OPR_AND;
+ case TK_OR: return OPR_OR;
+ default: return OPR_NOBINOPR;
+ }
+}
+
+
+static const struct {
+ lu_byte left; /* left priority for each binary operator */
+ lu_byte right; /* right priority */
+} priority[] = { /* ORDER OPR */
+ {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */
+ {10, 9}, {5, 4}, /* power and concat (right associative) */
+ {3, 3}, {3, 3}, /* equality and inequality */
+ {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */
+ {2, 2}, {1, 1} /* logical (and/or) */
+};
+
+#define UNARY_PRIORITY 8 /* priority for unary operators */
+
+
+/*
+** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
+** where `binop' is any binary operator with a priority higher than `limit'
+*/
+static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) {
+ BinOpr op;
+ UnOpr uop;
+ enterlevel(ls);
+ uop = getunopr(ls->t.token);
+ if (uop != OPR_NOUNOPR) {
+ luaX_next(ls);
+ subexpr(ls, v, UNARY_PRIORITY);
+ luaK_prefix(ls->fs, uop, v);
+ }
+ else simpleexp(ls, v);
+ /* expand while operators have priorities higher than `limit' */
+ op = getbinopr(ls->t.token);
+ while (op != OPR_NOBINOPR && priority[op].left > limit) {
+ expdesc v2;
+ BinOpr nextop;
+ luaX_next(ls);
+ luaK_infix(ls->fs, op, v);
+ /* read sub-expression with higher priority */
+ nextop = subexpr(ls, &v2, priority[op].right);
+ luaK_posfix(ls->fs, op, v, &v2);
+ op = nextop;
+ }
+ leavelevel(ls);
+ return op; /* return first untreated operator */
+}
+
+
+static void expr (LexState *ls, expdesc *v) {
+ subexpr(ls, v, 0);
+}
+
+/* }==================================================================== */
+
+
+
+/*
+** {======================================================================
+** Rules for Statements
+** =======================================================================
+*/
+
+
+static int block_follow (int token) {
+ switch (token) {
+ case TK_ELSE: case TK_ELSEIF: case TK_END:
+ case TK_UNTIL: case TK_EOS:
+ return 1;
+ default: return 0;
+ }
+}
+
+
+static void block (LexState *ls) {
+ /* block -> chunk */
+ FuncState *fs = ls->fs;
+ BlockCnt bl;
+ enterblock(fs, &bl, 0);
+ chunk(ls);
+ lua_assert(bl.breaklist == NO_JUMP);
+ leaveblock(fs);
+}
+
+
+/*
+** structure to chain all variables in the left-hand side of an
+** assignment
+*/
+struct LHS_assign {
+ struct LHS_assign *prev;
+ expdesc v; /* variable (global, local, upvalue, or indexed) */
+};
+
+
+/*
+** check whether, in an assignment to a local variable, the local variable
+** is needed in a previous assignment (to a table). If so, save original
+** local value in a safe place and use this safe copy in the previous
+** assignment.
+*/
+static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
+ FuncState *fs = ls->fs;
+ int extra = fs->freereg; /* eventual position to save local variable */
+ int conflict = 0;
+ for (; lh; lh = lh->prev) {
+ if (lh->v.k == VINDEXED) {
+ if (lh->v.u.s.info == v->u.s.info) { /* conflict? */
+ conflict = 1;
+ lh->v.u.s.info = extra; /* previous assignment will use safe copy */
+ }
+ if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */
+ conflict = 1;
+ lh->v.u.s.aux = extra; /* previous assignment will use safe copy */
+ }
+ }
+ }
+ if (conflict) {
+ luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */
+ luaK_reserveregs(fs, 1);
+ }
+}
+
+
+static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
+ expdesc e;
+ check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED,
+ "syntax error");
+ if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */
+ struct LHS_assign nv;
+ nv.prev = lh;
+ primaryexp(ls, &nv.v);
+ if (nv.v.k == VLOCAL)
+ check_conflict(ls, lh, &nv.v);
+ assignment(ls, &nv, nvars+1);
+ }
+ else { /* assignment -> `=' explist1 */
+ int nexps;
+ checknext(ls, '=');
+ nexps = explist1(ls, &e);
+ if (nexps != nvars) {
+ adjust_assign(ls, nvars, nexps, &e);
+ if (nexps > nvars)
+ ls->fs->freereg -= nexps - nvars; /* remove extra values */
+ }
+ else {
+ luaK_setoneret(ls->fs, &e); /* close last expression */
+ luaK_storevar(ls->fs, &lh->v, &e);
+ return; /* avoid default */
+ }
+ }
+ init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */
+ luaK_storevar(ls->fs, &lh->v, &e);
+}
+
+
+static int cond (LexState *ls) {
+ /* cond -> exp */
+ expdesc v;
+ expr(ls, &v); /* read condition */
+ if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */
+ luaK_goiftrue(ls->fs, &v);
+ return v.f;
+}
+
+
+static void breakstat (LexState *ls) {
+ FuncState *fs = ls->fs;
+ BlockCnt *bl = fs->bl;
+ int upval = 0;
+ while (bl && !bl->isbreakable) {
+ upval |= bl->upval;
+ bl = bl->previous;
+ }
+ if (!bl)
+ luaX_syntaxerror(ls, "no loop to break");
+ if (upval)
+ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
+ luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
+}
+
+
+static void whilestat (LexState *ls, int line) {
+ /* whilestat -> WHILE cond DO block END */
+ FuncState *fs = ls->fs;
+ int whileinit;
+ int condexit;
+ BlockCnt bl;
+ luaX_next(ls); /* skip WHILE */
+ whileinit = luaK_getlabel(fs);
+ condexit = cond(ls);
+ enterblock(fs, &bl, 1);
+ checknext(ls, TK_DO);
+ block(ls);
+ luaK_patchlist(fs, luaK_jump(fs), whileinit);
+ check_match(ls, TK_END, TK_WHILE, line);
+ leaveblock(fs);
+ luaK_patchtohere(fs, condexit); /* false conditions finish the loop */
+}
+
+
+static void repeatstat (LexState *ls, int line) {
+ /* repeatstat -> REPEAT block UNTIL cond */
+ int condexit;
+ FuncState *fs = ls->fs;
+ int repeat_init = luaK_getlabel(fs);
+ BlockCnt bl1, bl2;
+ enterblock(fs, &bl1, 1); /* loop block */
+ enterblock(fs, &bl2, 0); /* scope block */
+ luaX_next(ls); /* skip REPEAT */
+ chunk(ls);
+ check_match(ls, TK_UNTIL, TK_REPEAT, line);
+ condexit = cond(ls); /* read condition (inside scope block) */
+ if (!bl2.upval) { /* no upvalues? */
+ leaveblock(fs); /* finish scope */
+ luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */
+ }
+ else { /* complete semantics when there are upvalues */
+ breakstat(ls); /* if condition then break */
+ luaK_patchtohere(ls->fs, condexit); /* else... */
+ leaveblock(fs); /* finish scope... */
+ luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */
+ }
+ leaveblock(fs); /* finish loop */
+}
+
+
+static int exp1 (LexState *ls) {
+ expdesc e;
+ int k;
+ expr(ls, &e);
+ k = e.k;
+ luaK_exp2nextreg(ls->fs, &e);
+ return k;
+}
+
+
+static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
+ /* forbody -> DO block */
+ BlockCnt bl;
+ FuncState *fs = ls->fs;
+ int prep, endfor;
+ adjustlocalvars(ls, 3); /* control variables */
+ checknext(ls, TK_DO);
+ prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);
+ enterblock(fs, &bl, 0); /* scope for declared variables */
+ adjustlocalvars(ls, nvars);
+ luaK_reserveregs(fs, nvars);
+ block(ls);
+ leaveblock(fs); /* end of scope for declared variables */
+ luaK_patchtohere(fs, prep);
+ endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :
+ luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
+ luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
+ luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);
+}
+
+
+static void fornum (LexState *ls, TString *varname, int line) {
+ /* fornum -> NAME = exp1,exp1[,exp1] forbody */
+ FuncState *fs = ls->fs;
+ int base = fs->freereg;
+ new_localvarliteral(ls, "(for index)", 0);
+ new_localvarliteral(ls, "(for limit)", 1);
+ new_localvarliteral(ls, "(for step)", 2);
+ new_localvar(ls, varname, 3);
+ checknext(ls, '=');
+ exp1(ls); /* initial value */
+ checknext(ls, ',');
+ exp1(ls); /* limit */
+ if (testnext(ls, ','))
+ exp1(ls); /* optional step */
+ else { /* default step = 1 */
+ luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
+ luaK_reserveregs(fs, 1);
+ }
+ forbody(ls, base, line, 1, 1);
+}
+
+
+static void forlist (LexState *ls, TString *indexname) {
+ /* forlist -> NAME {,NAME} IN explist1 forbody */
+ FuncState *fs = ls->fs;
+ expdesc e;
+ int nvars = 0;
+ int line;
+ int base = fs->freereg;
+ /* create control variables */
+ new_localvarliteral(ls, "(for generator)", nvars++);
+ new_localvarliteral(ls, "(for state)", nvars++);
+ new_localvarliteral(ls, "(for control)", nvars++);
+ /* create declared variables */
+ new_localvar(ls, indexname, nvars++);
+ while (testnext(ls, ','))
+ new_localvar(ls, str_checkname(ls), nvars++);
+ checknext(ls, TK_IN);
+ line = ls->linenumber;
+ adjust_assign(ls, 3, explist1(ls, &e), &e);
+ luaK_checkstack(fs, 3); /* extra space to call generator */
+ forbody(ls, base, line, nvars - 3, 0);
+}
+
+
+static void forstat (LexState *ls, int line) {
+ /* forstat -> FOR (fornum | forlist) END */
+ FuncState *fs = ls->fs;
+ TString *varname;
+ BlockCnt bl;
+ enterblock(fs, &bl, 1); /* scope for loop and control variables */
+ luaX_next(ls); /* skip `for' */
+ varname = str_checkname(ls); /* first variable name */
+ switch (ls->t.token) {
+ case '=': fornum(ls, varname, line); break;
+ case ',': case TK_IN: forlist(ls, varname); break;
+ default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected");
+ }
+ check_match(ls, TK_END, TK_FOR, line);
+ leaveblock(fs); /* loop scope (`break' jumps to this point) */
+}
+
+
+static int test_then_block (LexState *ls) {
+ /* test_then_block -> [IF | ELSEIF] cond THEN block */
+ int condexit;
+ luaX_next(ls); /* skip IF or ELSEIF */
+ condexit = cond(ls);
+ checknext(ls, TK_THEN);
+ block(ls); /* `then' part */
+ return condexit;
+}
+
+
+static void ifstat (LexState *ls, int line) {
+ /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */
+ FuncState *fs = ls->fs;
+ int flist;
+ int escapelist = NO_JUMP;
+ flist = test_then_block(ls); /* IF cond THEN block */
+ while (ls->t.token == TK_ELSEIF) {
+ luaK_concat(fs, &escapelist, luaK_jump(fs));
+ luaK_patchtohere(fs, flist);
+ flist = test_then_block(ls); /* ELSEIF cond THEN block */
+ }
+ if (ls->t.token == TK_ELSE) {
+ luaK_concat(fs, &escapelist, luaK_jump(fs));
+ luaK_patchtohere(fs, flist);
+ luaX_next(ls); /* skip ELSE (after patch, for correct line info) */
+ block(ls); /* `else' part */
+ }
+ else
+ luaK_concat(fs, &escapelist, flist);
+ luaK_patchtohere(fs, escapelist);
+ check_match(ls, TK_END, TK_IF, line);
+}
+
+
+static void localfunc (LexState *ls) {
+ expdesc v, b;
+ FuncState *fs = ls->fs;
+ new_localvar(ls, str_checkname(ls), 0);
+ init_exp(&v, VLOCAL, fs->freereg);
+ luaK_reserveregs(fs, 1);
+ adjustlocalvars(ls, 1);
+ body(ls, &b, 0, ls->linenumber);
+ luaK_storevar(fs, &v, &b);
+ /* debug information will only see the variable after this point! */
+ getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;
+}
+
+
+static void localstat (LexState *ls) {
+ /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */
+ int nvars = 0;
+ int nexps;
+ expdesc e;
+ do {
+ new_localvar(ls, str_checkname(ls), nvars++);
+ } while (testnext(ls, ','));
+ if (testnext(ls, '='))
+ nexps = explist1(ls, &e);
+ else {
+ e.k = VVOID;
+ nexps = 0;
+ }
+ adjust_assign(ls, nvars, nexps, &e);
+ adjustlocalvars(ls, nvars);
+}
+
+
+static int funcname (LexState *ls, expdesc *v) {
+ /* funcname -> NAME {field} [`:' NAME] */
+ int needself = 0;
+ singlevar(ls, v);
+ while (ls->t.token == '.')
+ field(ls, v);
+ if (ls->t.token == ':') {
+ needself = 1;
+ field(ls, v);
+ }
+ return needself;
+}
+
+
+static void funcstat (LexState *ls, int line) {
+ /* funcstat -> FUNCTION funcname body */
+ int needself;
+ expdesc v, b;
+ luaX_next(ls); /* skip FUNCTION */
+ needself = funcname(ls, &v);
+ body(ls, &b, needself, line);
+ luaK_storevar(ls->fs, &v, &b);
+ luaK_fixline(ls->fs, line); /* definition `happens' in the first line */
+}
+
+
+static void exprstat (LexState *ls) {
+ /* stat -> func | assignment */
+ FuncState *fs = ls->fs;
+ struct LHS_assign v;
+ primaryexp(ls, &v.v);
+ if (v.v.k == VCALL) /* stat -> func */
+ SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */
+ else { /* stat -> assignment */
+ v.prev = NULL;
+ assignment(ls, &v, 1);
+ }
+}
+
+
+static void retstat (LexState *ls) {
+ /* stat -> RETURN explist */
+ FuncState *fs = ls->fs;
+ expdesc e;
+ int first, nret; /* registers with returned values */
+ luaX_next(ls); /* skip RETURN */
+ if (block_follow(ls->t.token) || ls->t.token == ';')
+ first = nret = 0; /* return no values */
+ else {
+ nret = explist1(ls, &e); /* optional return values */
+ if (hasmultret(e.k)) {
+ luaK_setmultret(fs, &e);
+ if (e.k == VCALL && nret == 1) { /* tail call? */
+ SET_OPCODE(getcode(fs,&e), OP_TAILCALL);
+ lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);
+ }
+ first = fs->nactvar;
+ nret = LUA_MULTRET; /* return all values */
+ }
+ else {
+ if (nret == 1) /* only one single value? */
+ first = luaK_exp2anyreg(fs, &e);
+ else {
+ luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */
+ first = fs->nactvar; /* return all `active' values */
+ lua_assert(nret == fs->freereg - first);
+ }
+ }
+ }
+ luaK_ret(fs, first, nret);
+}
+
+
+static int statement (LexState *ls) {
+ int line = ls->linenumber; /* may be needed for error messages */
+ switch (ls->t.token) {
+ case TK_IF: { /* stat -> ifstat */
+ ifstat(ls, line);
+ return 0;
+ }
+ case TK_WHILE: { /* stat -> whilestat */
+ whilestat(ls, line);
+ return 0;
+ }
+ case TK_DO: { /* stat -> DO block END */
+ luaX_next(ls); /* skip DO */
+ block(ls);
+ check_match(ls, TK_END, TK_DO, line);
+ return 0;
+ }
+ case TK_FOR: { /* stat -> forstat */
+ forstat(ls, line);
+ return 0;
+ }
+ case TK_REPEAT: { /* stat -> repeatstat */
+ repeatstat(ls, line);
+ return 0;
+ }
+ case TK_FUNCTION: {
+ funcstat(ls, line); /* stat -> funcstat */
+ return 0;
+ }
+ case TK_LOCAL: { /* stat -> localstat */
+ luaX_next(ls); /* skip LOCAL */
+ if (testnext(ls, TK_FUNCTION)) /* local function? */
+ localfunc(ls);
+ else
+ localstat(ls);
+ return 0;
+ }
+ case TK_RETURN: { /* stat -> retstat */
+ retstat(ls);
+ return 1; /* must be last statement */
+ }
+ case TK_BREAK: { /* stat -> breakstat */
+ luaX_next(ls); /* skip BREAK */
+ breakstat(ls);
+ return 1; /* must be last statement */
+ }
+ default: {
+ exprstat(ls);
+ return 0; /* to avoid warnings */
+ }
+ }
+}
+
+
+static void chunk (LexState *ls) {
+ /* chunk -> { stat [`;'] } */
+ int islast = 0;
+ enterlevel(ls);
+ while (!islast && !block_follow(ls->t.token)) {
+ islast = statement(ls);
+ testnext(ls, ';');
+ lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&
+ ls->fs->freereg >= ls->fs->nactvar);
+ ls->fs->freereg = ls->fs->nactvar; /* free registers */
+ }
+ leavelevel(ls);
+}
+
+/* }====================================================================== */
diff --git a/Build/source/libs/lua51/lparser.h b/Build/source/libs/lua51/lparser.h
new file mode 100644
index 00000000000..e5b5b57e850
--- /dev/null
+++ b/Build/source/libs/lua51/lparser.h
@@ -0,0 +1,82 @@
+/*
+** $Id: lparser.h,v 1.57 2006/03/09 18:14:31 roberto Exp $
+** Lua Parser
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lparser_h
+#define lparser_h
+
+#include "llimits.h"
+#include "lobject.h"
+#include "lzio.h"
+
+
+/*
+** Expression descriptor
+*/
+
+typedef enum {
+ VVOID, /* no value */
+ VNIL,
+ VTRUE,
+ VFALSE,
+ VK, /* info = index of constant in `k' */
+ VKNUM, /* nval = numerical value */
+ VLOCAL, /* info = local register */
+ VUPVAL, /* info = index of upvalue in `upvalues' */
+ VGLOBAL, /* info = index of table; aux = index of global name in `k' */
+ VINDEXED, /* info = table register; aux = index register (or `k') */
+ VJMP, /* info = instruction pc */
+ VRELOCABLE, /* info = instruction pc */
+ VNONRELOC, /* info = result register */
+ VCALL, /* info = instruction pc */
+ VVARARG /* info = instruction pc */
+} expkind;
+
+typedef struct expdesc {
+ expkind k;
+ union {
+ struct { int info, aux; } s;
+ lua_Number nval;
+ } u;
+ int t; /* patch list of `exit when true' */
+ int f; /* patch list of `exit when false' */
+} expdesc;
+
+
+typedef struct upvaldesc {
+ lu_byte k;
+ lu_byte info;
+} upvaldesc;
+
+
+struct BlockCnt; /* defined in lparser.c */
+
+
+/* state needed to generate code for a given function */
+typedef struct FuncState {
+ Proto *f; /* current function header */
+ Table *h; /* table to find (and reuse) elements in `k' */
+ struct FuncState *prev; /* enclosing function */
+ struct LexState *ls; /* lexical state */
+ struct lua_State *L; /* copy of the Lua state */
+ struct BlockCnt *bl; /* chain of current blocks */
+ int pc; /* next position to code (equivalent to `ncode') */
+ int lasttarget; /* `pc' of last `jump target' */
+ int jpc; /* list of pending jumps to `pc' */
+ int freereg; /* first free register */
+ int nk; /* number of elements in `k' */
+ int np; /* number of elements in `p' */
+ short nlocvars; /* number of elements in `locvars' */
+ lu_byte nactvar; /* number of active local variables */
+ upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */
+ unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */
+} FuncState;
+
+
+LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
+ const char *name);
+
+
+#endif
diff --git a/Build/source/libs/lua51/lstate.c b/Build/source/libs/lua51/lstate.c
new file mode 100644
index 00000000000..4bcb7594ce8
--- /dev/null
+++ b/Build/source/libs/lua51/lstate.c
@@ -0,0 +1,214 @@
+/*
+** $Id: lstate.c,v 2.36 2006/05/24 14:15:50 roberto Exp $
+** Global State
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stddef.h>
+
+#define lstate_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "llex.h"
+#include "lmem.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+
+
+#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE)
+#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE)
+#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE))
+
+
+/*
+** Main thread combines a thread state and the global state
+*/
+typedef struct LG {
+ lua_State l;
+ global_State g;
+} LG;
+
+
+
+static void stack_init (lua_State *L1, lua_State *L) {
+ /* initialize CallInfo array */
+ L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
+ L1->ci = L1->base_ci;
+ L1->size_ci = BASIC_CI_SIZE;
+ L1->end_ci = L1->base_ci + L1->size_ci - 1;
+ /* initialize stack array */
+ L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue);
+ L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
+ L1->top = L1->stack;
+ L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
+ /* initialize first ci */
+ L1->ci->func = L1->top;
+ setnilvalue(L1->top++); /* `function' entry for this `ci' */
+ L1->base = L1->ci->base = L1->top;
+ L1->ci->top = L1->top + LUA_MINSTACK;
+}
+
+
+static void freestack (lua_State *L, lua_State *L1) {
+ luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);
+ luaM_freearray(L, L1->stack, L1->stacksize, TValue);
+}
+
+
+/*
+** open parts that may cause memory-allocation errors
+*/
+static void f_luaopen (lua_State *L, void *ud) {
+ global_State *g = G(L);
+ UNUSED(ud);
+ stack_init(L, L); /* init stack */
+ sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */
+ sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */
+ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
+ luaT_init(L);
+ luaX_init(L);
+ luaS_fix(luaS_newliteral(L, MEMERRMSG));
+ g->GCthreshold = 4*g->totalbytes;
+}
+
+
+static void preinit_state (lua_State *L, global_State *g) {
+ G(L) = g;
+ L->stack = NULL;
+ L->stacksize = 0;
+ L->errorJmp = NULL;
+ L->hook = NULL;
+ L->hookmask = 0;
+ L->basehookcount = 0;
+ L->allowhook = 1;
+ resethookcount(L);
+ L->openupval = NULL;
+ L->size_ci = 0;
+ L->nCcalls = 0;
+ L->status = 0;
+ L->base_ci = L->ci = NULL;
+ L->savedpc = NULL;
+ L->errfunc = 0;
+ setnilvalue(gt(L));
+}
+
+
+static void close_state (lua_State *L) {
+ global_State *g = G(L);
+ luaF_close(L, L->stack); /* close all upvalues for this thread */
+ luaC_freeall(L); /* collect all objects */
+ lua_assert(g->rootgc == obj2gco(L));
+ lua_assert(g->strt.nuse == 0);
+ luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
+ luaZ_freebuffer(L, &g->buff);
+ freestack(L, L);
+ lua_assert(g->totalbytes == sizeof(LG));
+ (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0);
+}
+
+
+lua_State *luaE_newthread (lua_State *L) {
+ lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));
+ luaC_link(L, obj2gco(L1), LUA_TTHREAD);
+ preinit_state(L1, G(L));
+ stack_init(L1, L); /* init stack */
+ setobj2n(L, gt(L1), gt(L)); /* share table of globals */
+ L1->hookmask = L->hookmask;
+ L1->basehookcount = L->basehookcount;
+ L1->hook = L->hook;
+ resethookcount(L1);
+ lua_assert(iswhite(obj2gco(L1)));
+ return L1;
+}
+
+
+void luaE_freethread (lua_State *L, lua_State *L1) {
+ luaF_close(L1, L1->stack); /* close all upvalues for this thread */
+ lua_assert(L1->openupval == NULL);
+ luai_userstatefree(L1);
+ freestack(L, L1);
+ luaM_freemem(L, fromstate(L1), state_size(lua_State));
+}
+
+
+LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
+ int i;
+ lua_State *L;
+ global_State *g;
+ void *l = (*f)(ud, NULL, 0, state_size(LG));
+ if (l == NULL) return NULL;
+ L = tostate(l);
+ g = &((LG *)L)->g;
+ L->next = NULL;
+ L->tt = LUA_TTHREAD;
+ g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
+ L->marked = luaC_white(g);
+ set2bits(L->marked, FIXEDBIT, SFIXEDBIT);
+ preinit_state(L, g);
+ g->frealloc = f;
+ g->ud = ud;
+ g->mainthread = L;
+ g->uvhead.u.l.prev = &g->uvhead;
+ g->uvhead.u.l.next = &g->uvhead;
+ g->GCthreshold = 0; /* mark it as unfinished state */
+ g->strt.size = 0;
+ g->strt.nuse = 0;
+ g->strt.hash = NULL;
+ setnilvalue(registry(L));
+ luaZ_initbuffer(L, &g->buff);
+ g->panic = NULL;
+ g->gcstate = GCSpause;
+ g->rootgc = obj2gco(L);
+ g->sweepstrgc = 0;
+ g->sweepgc = &g->rootgc;
+ g->gray = NULL;
+ g->grayagain = NULL;
+ g->weak = NULL;
+ g->tmudata = NULL;
+ g->totalbytes = sizeof(LG);
+ g->gcpause = LUAI_GCPAUSE;
+ g->gcstepmul = LUAI_GCMUL;
+ g->gcdept = 0;
+ for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;
+ if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
+ /* memory allocation error: free partial state */
+ close_state(L);
+ L = NULL;
+ }
+ else
+ luai_userstateopen(L);
+ return L;
+}
+
+
+static void callallgcTM (lua_State *L, void *ud) {
+ UNUSED(ud);
+ luaC_callGCTM(L); /* call GC metamethods for all udata */
+}
+
+
+LUA_API void lua_close (lua_State *L) {
+ L = G(L)->mainthread; /* only the main thread can be closed */
+ lua_lock(L);
+ luaF_close(L, L->stack); /* close all upvalues for this thread */
+ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */
+ L->errfunc = 0; /* no error function during GC metamethods */
+ do { /* repeat until no more errors */
+ L->ci = L->base_ci;
+ L->base = L->top = L->ci->base;
+ L->nCcalls = 0;
+ } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);
+ lua_assert(G(L)->tmudata == NULL);
+ luai_userstateclose(L);
+ close_state(L);
+}
+
diff --git a/Build/source/libs/lua51/lstate.h b/Build/source/libs/lua51/lstate.h
new file mode 100644
index 00000000000..5209e95c8ac
--- /dev/null
+++ b/Build/source/libs/lua51/lstate.h
@@ -0,0 +1,171 @@
+/*
+** $Id: lstate.h,v 2.24 2006/02/06 18:27:59 roberto Exp $
+** Global State
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lstate_h
+#define lstate_h
+
+#include "lua.h"
+
+#include "lobject.h"
+#include "ltm.h"
+#include "lzio.h"
+#ifndef COCO_DISABLE
+#include "lcoco.h"
+#endif
+
+
+
+struct lua_longjmp; /* defined in ldo.c */
+
+
+/* table of globals */
+#define gt(L) (&L->l_gt)
+
+/* registry */
+#define registry(L) (&G(L)->l_registry)
+
+
+/* extra stack space to handle TM calls and some other extras */
+#define EXTRA_STACK 5
+
+
+#define BASIC_CI_SIZE 8
+
+#define BASIC_STACK_SIZE (2*LUA_MINSTACK)
+
+
+
+typedef struct stringtable {
+ GCObject **hash;
+ lu_int32 nuse; /* number of elements */
+ int size;
+} stringtable;
+
+
+/*
+** informations about a call
+*/
+typedef struct CallInfo {
+ StkId base; /* base for this function */
+ StkId func; /* function index in the stack */
+ StkId top; /* top for this function */
+ const Instruction *savedpc;
+ int nresults; /* expected number of results from this function */
+ int tailcalls; /* number of tail calls lost under this entry */
+} CallInfo;
+
+
+
+#define curr_func(L) (clvalue(L->ci->func))
+#define ci_func(ci) (clvalue((ci)->func))
+#define f_isLua(ci) (!ci_func(ci)->c.isC)
+#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))
+
+
+/*
+** `global state', shared by all threads of this state
+*/
+typedef struct global_State {
+ stringtable strt; /* hash table for strings */
+ lua_Alloc frealloc; /* function to reallocate memory */
+ void *ud; /* auxiliary data to `frealloc' */
+ lu_byte currentwhite;
+ lu_byte gcstate; /* state of garbage collector */
+ int sweepstrgc; /* position of sweep in `strt' */
+ GCObject *rootgc; /* list of all collectable objects */
+ GCObject **sweepgc; /* position of sweep in `rootgc' */
+ GCObject *gray; /* list of gray objects */
+ GCObject *grayagain; /* list of objects to be traversed atomically */
+ GCObject *weak; /* list of weak tables (to be cleared) */
+ GCObject *tmudata; /* last element of list of userdata to be GC */
+ Mbuffer buff; /* temporary buffer for string concatentation */
+ lu_mem GCthreshold;
+ lu_mem totalbytes; /* number of bytes currently allocated */
+ lu_mem estimate; /* an estimate of number of bytes actually in use */
+ lu_mem gcdept; /* how much GC is `behind schedule' */
+ int gcpause; /* size of pause between successive GCs */
+ int gcstepmul; /* GC `granularity' */
+ lua_CFunction panic; /* to be called in unprotected errors */
+ TValue l_registry;
+ struct lua_State *mainthread;
+ UpVal uvhead; /* head of double-linked list of all open upvalues */
+ struct Table *mt[NUM_TAGS]; /* metatables for basic types */
+ TString *tmname[TM_N]; /* array with tag-method names */
+} global_State;
+
+
+/*
+** `per thread' state
+*/
+struct lua_State {
+ CommonHeader;
+ lu_byte status;
+ StkId top; /* first free slot in the stack */
+ StkId base; /* base of current function */
+ global_State *l_G;
+ CallInfo *ci; /* call info for current function */
+ const Instruction *savedpc; /* `savedpc' of current function */
+ StkId stack_last; /* last free slot in the stack */
+ StkId stack; /* stack base */
+ CallInfo *end_ci; /* points after end of ci array*/
+ CallInfo *base_ci; /* array of CallInfo's */
+ int stacksize;
+ int size_ci; /* size of array `base_ci' */
+ unsigned short nCcalls; /* number of nested C calls */
+ lu_byte hookmask;
+ lu_byte allowhook;
+ int basehookcount;
+ int hookcount;
+ lua_Hook hook;
+ TValue l_gt; /* table of globals */
+ TValue env; /* temporary place for environments */
+ GCObject *openupval; /* list of open upvalues in this stack */
+ GCObject *gclist;
+ struct lua_longjmp *errorJmp; /* current error recover point */
+ ptrdiff_t errfunc; /* current error handling function (stack index) */
+};
+
+
+#define G(L) (L->l_G)
+
+
+/*
+** Union of all collectable objects
+*/
+union GCObject {
+ GCheader gch;
+ union TString ts;
+ union Udata u;
+ union Closure cl;
+ struct Table h;
+ struct Proto p;
+ struct UpVal uv;
+ struct lua_State th; /* thread */
+};
+
+
+/* macros to convert a GCObject into a specific value */
+#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
+#define gco2ts(o) (&rawgco2ts(o)->tsv)
+#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
+#define gco2u(o) (&rawgco2u(o)->uv)
+#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
+#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
+#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
+#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
+#define ngcotouv(o) \
+ check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))
+#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
+
+/* macro to convert any Lua object into a GCObject */
+#define obj2gco(v) (cast(GCObject *, (v)))
+
+
+LUAI_FUNC lua_State *luaE_newthread (lua_State *L);
+LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
+
+#endif
+
diff --git a/Build/source/libs/lua51/lstring.c b/Build/source/libs/lua51/lstring.c
new file mode 100644
index 00000000000..4319930c96d
--- /dev/null
+++ b/Build/source/libs/lua51/lstring.c
@@ -0,0 +1,111 @@
+/*
+** $Id: lstring.c,v 2.8 2005/12/22 16:19:56 roberto Exp $
+** String table (keeps all strings handled by Lua)
+** See Copyright Notice in lua.h
+*/
+
+
+#include <string.h>
+
+#define lstring_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+
+
+
+void luaS_resize (lua_State *L, int newsize) {
+ GCObject **newhash;
+ stringtable *tb;
+ int i;
+ if (G(L)->gcstate == GCSsweepstring)
+ return; /* cannot resize during GC traverse */
+ newhash = luaM_newvector(L, newsize, GCObject *);
+ tb = &G(L)->strt;
+ for (i=0; i<newsize; i++) newhash[i] = NULL;
+ /* rehash */
+ for (i=0; i<tb->size; i++) {
+ GCObject *p = tb->hash[i];
+ while (p) { /* for each node in the list */
+ GCObject *next = p->gch.next; /* save next */
+ unsigned int h = gco2ts(p)->hash;
+ int h1 = lmod(h, newsize); /* new position */
+ lua_assert(cast_int(h%newsize) == lmod(h, newsize));
+ p->gch.next = newhash[h1]; /* chain it */
+ newhash[h1] = p;
+ p = next;
+ }
+ }
+ luaM_freearray(L, tb->hash, tb->size, TString *);
+ tb->size = newsize;
+ tb->hash = newhash;
+}
+
+
+static TString *newlstr (lua_State *L, const char *str, size_t l,
+ unsigned int h) {
+ TString *ts;
+ stringtable *tb;
+ if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
+ luaM_toobig(L);
+ ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString)));
+ ts->tsv.len = l;
+ ts->tsv.hash = h;
+ ts->tsv.marked = luaC_white(G(L));
+ ts->tsv.tt = LUA_TSTRING;
+ ts->tsv.reserved = 0;
+ memcpy(ts+1, str, l*sizeof(char));
+ ((char *)(ts+1))[l] = '\0'; /* ending 0 */
+ tb = &G(L)->strt;
+ h = lmod(h, tb->size);
+ ts->tsv.next = tb->hash[h]; /* chain new entry */
+ tb->hash[h] = obj2gco(ts);
+ tb->nuse++;
+ if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
+ luaS_resize(L, tb->size*2); /* too crowded */
+ return ts;
+}
+
+
+TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
+ GCObject *o;
+ unsigned int h = cast(unsigned int, l); /* seed */
+ size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */
+ size_t l1;
+ for (l1=l; l1>=step; l1-=step) /* compute hash */
+ h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
+ for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
+ o != NULL;
+ o = o->gch.next) {
+ TString *ts = rawgco2ts(o);
+ if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {
+ /* string may be dead */
+ if (isdead(G(L), o)) changewhite(o);
+ return ts;
+ }
+ }
+ return newlstr(L, str, l, h); /* not found */
+}
+
+
+Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
+ Udata *u;
+ if (s > MAX_SIZET - sizeof(Udata))
+ luaM_toobig(L);
+ u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata)));
+ u->uv.marked = luaC_white(G(L)); /* is not finalized */
+ u->uv.tt = LUA_TUSERDATA;
+ u->uv.len = s;
+ u->uv.metatable = NULL;
+ u->uv.env = e;
+ /* chain it on udata list (after main thread) */
+ u->uv.next = G(L)->mainthread->next;
+ G(L)->mainthread->next = obj2gco(u);
+ return u;
+}
+
diff --git a/Build/source/libs/lua51/lstring.h b/Build/source/libs/lua51/lstring.h
new file mode 100644
index 00000000000..1d2e91ea13a
--- /dev/null
+++ b/Build/source/libs/lua51/lstring.h
@@ -0,0 +1,31 @@
+/*
+** $Id: lstring.h,v 1.43 2005/04/25 19:24:10 roberto Exp $
+** String table (keep all strings handled by Lua)
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lstring_h
+#define lstring_h
+
+
+#include "lgc.h"
+#include "lobject.h"
+#include "lstate.h"
+
+
+#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char))
+
+#define sizeudata(u) (sizeof(union Udata)+(u)->len)
+
+#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s)))
+#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
+ (sizeof(s)/sizeof(char))-1))
+
+#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT)
+
+LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
+LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
+LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
+
+
+#endif
diff --git a/Build/source/libs/lua51/lstrlib.c b/Build/source/libs/lua51/lstrlib.c
new file mode 100644
index 00000000000..38c6b45c8da
--- /dev/null
+++ b/Build/source/libs/lua51/lstrlib.c
@@ -0,0 +1,1154 @@
+/*
+** $Id: lstrlib.c,v 1.132 2006/04/26 20:41:19 roberto Exp $
+** Standard library for string operations and pattern-matching
+** See Copyright Notice in lua.h
+*/
+
+
+#include <ctype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lstrlib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+/* macro to `unsign' a character */
+#define uchar(c) ((unsigned char)(c))
+
+
+
+static int str_len (lua_State *L) {
+ size_t l;
+ luaL_checklstring(L, 1, &l);
+ lua_pushinteger(L, l);
+ return 1;
+}
+
+
+static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {
+ /* relative string position: negative means back from end */
+ return (pos>=0) ? pos : (ptrdiff_t)len+pos+1;
+}
+
+
+static int str_sub (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+ ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);
+ ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);
+ if (start < 1) start = 1;
+ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
+ if (start <= end)
+ lua_pushlstring(L, s+start-1, end-start+1);
+ else lua_pushliteral(L, "");
+ return 1;
+}
+
+
+static int str_reverse (lua_State *L) {
+ size_t l;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l);
+ luaL_buffinit(L, &b);
+ while (l--) luaL_addchar(&b, s[l]);
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int str_lower (lua_State *L) {
+ size_t l;
+ size_t i;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l);
+ luaL_buffinit(L, &b);
+ for (i=0; i<l; i++)
+ luaL_addchar(&b, tolower(uchar(s[i])));
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int str_upper (lua_State *L) {
+ size_t l;
+ size_t i;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l);
+ luaL_buffinit(L, &b);
+ for (i=0; i<l; i++)
+ luaL_addchar(&b, toupper(uchar(s[i])));
+ luaL_pushresult(&b);
+ return 1;
+}
+
+static int str_rep (lua_State *L) {
+ size_t l;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l);
+ int n = luaL_checkint(L, 2);
+ luaL_buffinit(L, &b);
+ while (n-- > 0)
+ luaL_addlstring(&b, s, l);
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int str_byte (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+ ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
+ ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
+ int n, i;
+ if (posi <= 0) posi = 1;
+ if ((size_t)pose > l) pose = l;
+ if (posi > pose) return 0; /* empty interval; return no values */
+ n = (int)(pose - posi + 1);
+ if (posi + n <= pose) /* overflow? */
+ luaL_error(L, "string slice too long");
+ luaL_checkstack(L, n, "string slice too long");
+ for (i=0; i<n; i++)
+ lua_pushinteger(L, uchar(s[posi+i-1]));
+ return n;
+}
+
+
+static int str_char (lua_State *L) {
+ int n = lua_gettop(L); /* number of arguments */
+ int i;
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ for (i=1; i<=n; i++) {
+ int c = luaL_checkint(L, i);
+ luaL_argcheck(L, uchar(c) == c, i, "invalid value");
+ luaL_addchar(&b, uchar(c));
+ }
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int writer (lua_State *L, const void* b, size_t size, void* B) {
+ (void)L;
+ luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
+ return 0;
+}
+
+
+static int str_dump (lua_State *L) {
+ luaL_Buffer b;
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ lua_settop(L, 1);
+ luaL_buffinit(L,&b);
+ if (lua_dump(L, writer, &b) != 0)
+ luaL_error(L, "unable to dump given function");
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+
+/*
+** {======================================================
+** PATTERN MATCHING
+** =======================================================
+*/
+
+
+#define CAP_UNFINISHED (-1)
+#define CAP_POSITION (-2)
+
+typedef struct MatchState {
+ const char *src_init; /* init of source string */
+ const char *src_end; /* end (`\0') of source string */
+ lua_State *L;
+ int level; /* total number of captures (finished or unfinished) */
+ struct {
+ const char *init;
+ ptrdiff_t len;
+ } capture[LUA_MAXCAPTURES];
+} MatchState;
+
+
+#define L_ESC '%'
+#define SPECIALS "^$*+?.([%-"
+
+
+static int check_capture (MatchState *ms, int l) {
+ l -= '1';
+ if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
+ return luaL_error(ms->L, "invalid capture index");
+ return l;
+}
+
+
+static int capture_to_close (MatchState *ms) {
+ int level = ms->level;
+ for (level--; level>=0; level--)
+ if (ms->capture[level].len == CAP_UNFINISHED) return level;
+ return luaL_error(ms->L, "invalid pattern capture");
+}
+
+
+static const char *classend (MatchState *ms, const char *p) {
+ switch (*p++) {
+ case L_ESC: {
+ if (*p == '\0')
+ luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")");
+ return p+1;
+ }
+ case '[': {
+ if (*p == '^') p++;
+ do { /* look for a `]' */
+ if (*p == '\0')
+ luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");
+ if (*(p++) == L_ESC && *p != '\0')
+ p++; /* skip escapes (e.g. `%]') */
+ } while (*p != ']');
+ return p+1;
+ }
+ default: {
+ return p;
+ }
+ }
+}
+
+
+static int match_class (int c, int cl) {
+ int res;
+ switch (tolower(cl)) {
+ case 'a' : res = isalpha(c); break;
+ case 'c' : res = iscntrl(c); break;
+ case 'd' : res = isdigit(c); break;
+ case 'l' : res = islower(c); break;
+ case 'p' : res = ispunct(c); break;
+ case 's' : res = isspace(c); break;
+ case 'u' : res = isupper(c); break;
+ case 'w' : res = isalnum(c); break;
+ case 'x' : res = isxdigit(c); break;
+ case 'z' : res = (c == 0); break;
+ default: return (cl == c);
+ }
+ return (islower(cl) ? res : !res);
+}
+
+
+static int matchbracketclass (int c, const char *p, const char *ec) {
+ int sig = 1;
+ if (*(p+1) == '^') {
+ sig = 0;
+ p++; /* skip the `^' */
+ }
+ while (++p < ec) {
+ if (*p == L_ESC) {
+ p++;
+ if (match_class(c, uchar(*p)))
+ return sig;
+ }
+ else if ((*(p+1) == '-') && (p+2 < ec)) {
+ p+=2;
+ if (uchar(*(p-2)) <= c && c <= uchar(*p))
+ return sig;
+ }
+ else if (uchar(*p) == c) return sig;
+ }
+ return !sig;
+}
+
+
+static int singlematch (int c, const char *p, const char *ep) {
+ switch (*p) {
+ case '.': return 1; /* matches any char */
+ case L_ESC: return match_class(c, uchar(*(p+1)));
+ case '[': return matchbracketclass(c, p, ep-1);
+ default: return (uchar(*p) == c);
+ }
+}
+
+
+static const char *match (MatchState *ms, const char *s, const char *p);
+
+
+static const char *matchbalance (MatchState *ms, const char *s,
+ const char *p) {
+ if (*p == 0 || *(p+1) == 0)
+ luaL_error(ms->L, "unbalanced pattern");
+ if (*s != *p) return NULL;
+ else {
+ int b = *p;
+ int e = *(p+1);
+ int cont = 1;
+ while (++s < ms->src_end) {
+ if (*s == e) {
+ if (--cont == 0) return s+1;
+ }
+ else if (*s == b) cont++;
+ }
+ }
+ return NULL; /* string ends out of balance */
+}
+
+
+static const char *max_expand (MatchState *ms, const char *s,
+ const char *p, const char *ep) {
+ ptrdiff_t i = 0; /* counts maximum expand for item */
+ while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep))
+ i++;
+ /* keeps trying to match with the maximum repetitions */
+ while (i>=0) {
+ const char *res = match(ms, (s+i), ep+1);
+ if (res) return res;
+ i--; /* else didn't match; reduce 1 repetition to try again */
+ }
+ return NULL;
+}
+
+
+static const char *min_expand (MatchState *ms, const char *s,
+ const char *p, const char *ep) {
+ for (;;) {
+ const char *res = match(ms, s, ep+1);
+ if (res != NULL)
+ return res;
+ else if (s<ms->src_end && singlematch(uchar(*s), p, ep))
+ s++; /* try with one more repetition */
+ else return NULL;
+ }
+}
+
+
+static const char *start_capture (MatchState *ms, const char *s,
+ const char *p, int what) {
+ const char *res;
+ int level = ms->level;
+ if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");
+ ms->capture[level].init = s;
+ ms->capture[level].len = what;
+ ms->level = level+1;
+ if ((res=match(ms, s, p)) == NULL) /* match failed? */
+ ms->level--; /* undo capture */
+ return res;
+}
+
+
+static const char *end_capture (MatchState *ms, const char *s,
+ const char *p) {
+ int l = capture_to_close(ms);
+ const char *res;
+ ms->capture[l].len = s - ms->capture[l].init; /* close capture */
+ if ((res = match(ms, s, p)) == NULL) /* match failed? */
+ ms->capture[l].len = CAP_UNFINISHED; /* undo capture */
+ return res;
+}
+
+
+static const char *match_capture (MatchState *ms, const char *s, int l) {
+ size_t len;
+ l = check_capture(ms, l);
+ len = ms->capture[l].len;
+ if ((size_t)(ms->src_end-s) >= len &&
+ memcmp(ms->capture[l].init, s, len) == 0)
+ return s+len;
+ else return NULL;
+}
+
+
+static const char *match (MatchState *ms, const char *s, const char *p) {
+ init: /* using goto's to optimize tail recursion */
+ switch (*p) {
+ case '(': { /* start capture */
+ if (*(p+1) == ')') /* position capture? */
+ return start_capture(ms, s, p+2, CAP_POSITION);
+ else
+ return start_capture(ms, s, p+1, CAP_UNFINISHED);
+ }
+ case ')': { /* end capture */
+ return end_capture(ms, s, p+1);
+ }
+ case L_ESC: {
+ switch (*(p+1)) {
+ case 'b': { /* balanced string? */
+ s = matchbalance(ms, s, p+2);
+ if (s == NULL) return NULL;
+ p+=4; goto init; /* else return match(ms, s, p+4); */
+ }
+ case 'f': { /* frontier? */
+ const char *ep; char previous;
+ p += 2;
+ if (*p != '[')
+ luaL_error(ms->L, "missing " LUA_QL("[") " after "
+ LUA_QL("%%f") " in pattern");
+ ep = classend(ms, p); /* points to what is next */
+ previous = (s == ms->src_init) ? '\0' : *(s-1);
+ if (matchbracketclass(uchar(previous), p, ep-1) ||
+ !matchbracketclass(uchar(*s), p, ep-1)) return NULL;
+ p=ep; goto init; /* else return match(ms, s, ep); */
+ }
+ default: {
+ if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */
+ s = match_capture(ms, s, uchar(*(p+1)));
+ if (s == NULL) return NULL;
+ p+=2; goto init; /* else return match(ms, s, p+2) */
+ }
+ goto dflt; /* case default */
+ }
+ }
+ }
+ case '\0': { /* end of pattern */
+ return s; /* match succeeded */
+ }
+ case '$': {
+ if (*(p+1) == '\0') /* is the `$' the last char in pattern? */
+ return (s == ms->src_end) ? s : NULL; /* check end of string */
+ else goto dflt;
+ }
+ default: dflt: { /* it is a pattern item */
+ const char *ep = classend(ms, p); /* points to what is next */
+ int m = s<ms->src_end && singlematch(uchar(*s), p, ep);
+ switch (*ep) {
+ case '?': { /* optional */
+ const char *res;
+ if (m && ((res=match(ms, s+1, ep+1)) != NULL))
+ return res;
+ p=ep+1; goto init; /* else return match(ms, s, ep+1); */
+ }
+ case '*': { /* 0 or more repetitions */
+ return max_expand(ms, s, p, ep);
+ }
+ case '+': { /* 1 or more repetitions */
+ return (m ? max_expand(ms, s+1, p, ep) : NULL);
+ }
+ case '-': { /* 0 or more repetitions (minimum) */
+ return min_expand(ms, s, p, ep);
+ }
+ default: {
+ if (!m) return NULL;
+ s++; p=ep; goto init; /* else return match(ms, s+1, ep); */
+ }
+ }
+ }
+ }
+}
+
+
+
+static const char *lmemfind (const char *s1, size_t l1,
+ const char *s2, size_t l2) {
+ if (l2 == 0) return s1; /* empty strings are everywhere */
+ else if (l2 > l1) return NULL; /* avoids a negative `l1' */
+ else {
+ const char *init; /* to search for a `*s2' inside `s1' */
+ l2--; /* 1st char will be checked by `memchr' */
+ l1 = l1-l2; /* `s2' cannot be found after that */
+ while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
+ init++; /* 1st char is already checked */
+ if (memcmp(init, s2+1, l2) == 0)
+ return init-1;
+ else { /* correct `l1' and `s1' to try again */
+ l1 -= init-s1;
+ s1 = init;
+ }
+ }
+ return NULL; /* not found */
+ }
+}
+
+
+static void push_onecapture (MatchState *ms, int i, const char *s,
+ const char *e) {
+ if (i >= ms->level) {
+ if (i == 0) /* ms->level == 0, too */
+ lua_pushlstring(ms->L, s, e - s); /* add whole match */
+ else
+ luaL_error(ms->L, "invalid capture index");
+ }
+ else {
+ ptrdiff_t l = ms->capture[i].len;
+ if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
+ if (l == CAP_POSITION)
+ lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);
+ else
+ lua_pushlstring(ms->L, ms->capture[i].init, l);
+ }
+}
+
+
+static int push_captures (MatchState *ms, const char *s, const char *e) {
+ int i;
+ int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
+ luaL_checkstack(ms->L, nlevels, "too many captures");
+ for (i = 0; i < nlevels; i++)
+ push_onecapture(ms, i, s, e);
+ return nlevels; /* number of strings pushed */
+}
+
+
+static int str_find_aux (lua_State *L, int find) {
+ size_t l1, l2;
+ const char *s = luaL_checklstring(L, 1, &l1);
+ const char *p = luaL_checklstring(L, 2, &l2);
+ ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
+ if (init < 0) init = 0;
+ else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;
+ if (find && (lua_toboolean(L, 4) || /* explicit request? */
+ strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */
+ /* do a plain search */
+ const char *s2 = lmemfind(s+init, l1-init, p, l2);
+ if (s2) {
+ lua_pushinteger(L, s2-s+1);
+ lua_pushinteger(L, s2-s+l2);
+ return 2;
+ }
+ }
+ else {
+ MatchState ms;
+ int anchor = (*p == '^') ? (p++, 1) : 0;
+ const char *s1=s+init;
+ ms.L = L;
+ ms.src_init = s;
+ ms.src_end = s+l1;
+ do {
+ const char *res;
+ ms.level = 0;
+ if ((res=match(&ms, s1, p)) != NULL) {
+ if (find) {
+ lua_pushinteger(L, s1-s+1); /* start */
+ lua_pushinteger(L, res-s); /* end */
+ return push_captures(&ms, NULL, 0) + 2;
+ }
+ else
+ return push_captures(&ms, s1, res);
+ }
+ } while (s1++ < ms.src_end && !anchor);
+ }
+ lua_pushnil(L); /* not found */
+ return 1;
+}
+
+
+static int str_find (lua_State *L) {
+ return str_find_aux(L, 1);
+}
+
+
+static int str_match (lua_State *L) {
+ return str_find_aux(L, 0);
+}
+
+
+static int gmatch_aux (lua_State *L) {
+ MatchState ms;
+ size_t ls;
+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
+ const char *p = lua_tostring(L, lua_upvalueindex(2));
+ const char *src;
+ ms.L = L;
+ ms.src_init = s;
+ ms.src_end = s+ls;
+ for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
+ src <= ms.src_end;
+ src++) {
+ const char *e;
+ ms.level = 0;
+ if ((e = match(&ms, src, p)) != NULL) {
+ lua_Integer newstart = e-s;
+ if (e == src) newstart++; /* empty match? go at least one position */
+ lua_pushinteger(L, newstart);
+ lua_replace(L, lua_upvalueindex(3));
+ return push_captures(&ms, src, e);
+ }
+ }
+ return 0; /* not found */
+}
+
+
+static int gmatch (lua_State *L) {
+ luaL_checkstring(L, 1);
+ luaL_checkstring(L, 2);
+ lua_settop(L, 2);
+ lua_pushinteger(L, 0);
+ lua_pushcclosure(L, gmatch_aux, 3);
+ return 1;
+}
+
+
+static int characters_aux (lua_State *L) {
+ size_t ls;
+ char b[2];
+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
+ int ind = lua_tointeger(L, lua_upvalueindex(2));
+ if (ind<ls) {
+ lua_pushinteger(L, (ind+1)); /* iterator */
+ lua_replace(L, lua_upvalueindex(2));
+ b[0] = *(s+ind); b[1] = 0;
+ lua_pushlstring(L, b, 1);
+ return 1;
+ }
+ return 0; /* string ended */
+}
+
+
+static int str_characters (lua_State *L) {
+ luaL_checkstring(L, 1);
+ lua_settop(L, 1);
+ lua_pushinteger(L, 0);
+ lua_pushcclosure(L, characters_aux, 2);
+ return 1;
+}
+
+
+static int utf_failed(lua_State *L, int new_ind) {
+ static char fffd [3] = {0xEF,0xBF,0xBD};
+ lua_pushinteger(L, new_ind); /* iterator */
+ lua_replace(L, lua_upvalueindex(2));
+ lua_pushlstring(L, fffd, 3);
+ return 1;
+}
+
+static int utfcharacters_aux (lua_State *L) {
+ static const unsigned char mask[4] = {0x80,0xE0,0xF0,0xF8};
+ static const unsigned char mequ[4] = {0x00,0xC0,0xE0,0xF0};
+ size_t ls;
+ unsigned char c;
+ int j;
+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
+ int ind = lua_tointeger(L, lua_upvalueindex(2));
+ if (ind>=ls) return 0; /* end of string */
+ c = (unsigned) s[ind];
+ for (j=0;j<4;j++) {
+ if ((c&mask[j])==mequ[j]) {
+ int k;
+ if (ind+1+j>ls) return utf_failed(L,ls); /* will not fit */
+ for (k=1; k<=j; k++) {
+ c = (unsigned) s[ind+k];
+ if ((c&0xC0)!=0x80) return utf_failed(L,ind+k); /* bad follow */
+ }
+ lua_pushinteger(L, ind+1+j); /* iterator */
+ lua_replace(L, lua_upvalueindex(2));
+ lua_pushlstring(L, s+ind, 1+j);
+ return 1;
+ }
+ }
+ return utf_failed(L,ind+1); /* we found a follow byte! */
+}
+
+
+static int str_utfcharacters (lua_State *L) {
+ luaL_checkstring(L, 1);
+ lua_settop(L, 1);
+ lua_pushinteger(L, 0);
+ lua_pushcclosure(L, utfcharacters_aux, 2);
+ return 1;
+}
+
+
+static int utfvalues_aux (lua_State *L) {
+ size_t ls;
+ unsigned char i = 0;
+ unsigned char j = 0;
+ unsigned char k = 0;
+ unsigned char l = 0;
+ unsigned int v = 0xFFFD;
+ int numbytes = 1;
+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
+ int ind = lua_tointeger(L, lua_upvalueindex(2));
+
+ if (ind<ls) {
+ i = *(s+ind);
+ if (i<0x80) {
+ v = i;
+ } else if (i>=0xF0) {
+ if ((ind+3)<ls && ((unsigned)*(s+ind+1))>=0x80
+ && ((unsigned)*(s+ind+2))>=0x80 && ((unsigned)*(s+ind+3))>=0x80) {
+ numbytes = 4;
+ j = ((unsigned)*(s+ind+1))-128;
+ k = ((unsigned)*(s+ind+2))-128;
+ l = ((unsigned)*(s+ind+3))-128;
+ v = (((((i-0xF0)*64) + j)*64) + k)*64 + l;
+ }
+ } else if (i>=0xE0) {
+ if ((ind+2)<ls && ((unsigned)*(s+ind+1))>=0x80 && ((unsigned)*(s+ind+2))>=0x80) {
+ numbytes = 3;
+ j = ((unsigned)*(s+ind+1))-128;
+ k = ((unsigned)*(s+ind+2))-128;
+ v = (((i-0xE0)*64) + j)*64 + k;
+ }
+
+ } else if (i>=0xC0) {
+ if ((ind+1)<ls && ((unsigned)*(s+ind+1))>=0x80) {
+ numbytes = 2;
+ j = ((unsigned)*(s+ind+1))-128;
+ v = ((i-0xC0)*64) + j;
+ }
+ }
+ lua_pushinteger(L, (ind+numbytes)); /* iterator */
+ lua_replace(L, lua_upvalueindex(2));
+ lua_pushinteger(L, v);
+ return 1;
+ }
+ return 0; /* string ended */
+}
+
+
+static int str_utfvalues (lua_State *L) {
+ luaL_checkstring(L, 1);
+ lua_settop(L, 1);
+ lua_pushinteger(L, 0);
+ lua_pushcclosure(L, utfvalues_aux, 2);
+ return 1;
+}
+
+
+
+static int characterpairs_aux (lua_State *L) {
+ size_t ls;
+ char b[2];
+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
+ int ind = lua_tointeger(L, lua_upvalueindex(2));
+ if (ind<ls) {
+ if (ind+1<ls) {
+ lua_pushinteger(L, (ind+2)); /* iterator */
+ } else {
+ lua_pushinteger(L, (ind+1)); /* iterator */
+ }
+ lua_replace(L, lua_upvalueindex(2));
+ b[0] = *(s+ind); b[1] = 0;
+ lua_pushlstring(L, b, 1);
+ if (ind+1<ls) {
+ b[0] = *(s+ind+1);
+ lua_pushlstring(L, b, 1);
+ } else {
+ lua_pushlstring(L, b+1, 0);
+ }
+ return 2;
+ }
+ return 0; /* string ended */
+}
+
+
+static int str_characterpairs (lua_State *L) {
+ luaL_checkstring(L, 1);
+ lua_settop(L, 1);
+ lua_pushinteger(L, 0);
+ lua_pushcclosure(L, characterpairs_aux, 2);
+ return 1;
+}
+
+static int bytes_aux (lua_State *L) {
+ size_t ls;
+ unsigned char i;
+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
+ int ind = lua_tointeger(L, lua_upvalueindex(2));
+ if (ind<ls) {
+ lua_pushinteger(L, (ind+1)); /* iterator */
+ lua_replace(L, lua_upvalueindex(2));
+ i = (unsigned char)*(s+ind);
+ lua_pushinteger(L, i); /* byte */
+ return 1;
+ }
+ return 0; /* string ended */
+}
+
+static int str_bytes (lua_State *L) {
+ luaL_checkstring(L, 1);
+ lua_settop(L, 1);
+ lua_pushinteger(L, 0);
+ lua_pushcclosure(L, bytes_aux, 2);
+ return 1;
+}
+
+static int bytepairs_aux (lua_State *L) {
+ size_t ls;
+ unsigned char i;
+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
+ int ind = lua_tointeger(L, lua_upvalueindex(2));
+ if (ind<ls) {
+ if (ind+1<ls) {
+ lua_pushinteger(L, (ind+2)); /* iterator */
+ } else {
+ lua_pushinteger(L, (ind+1)); /* iterator */
+ }
+ lua_replace(L, lua_upvalueindex(2));
+ i = (unsigned char)*(s+ind);
+ lua_pushinteger(L, i); /* byte one */
+ if (ind+1<ls) {
+ i = (unsigned char)*(s+ind+1);
+ lua_pushinteger(L, i); /* byte two */
+ } else {
+ lua_pushnil(L); /* odd string length */
+ }
+ return 2;
+ }
+ return 0; /* string ended */
+}
+
+
+static int str_bytepairs (lua_State *L) {
+ luaL_checkstring(L, 1);
+ lua_settop(L, 1);
+ lua_pushinteger(L, 0);
+ lua_pushcclosure(L, bytepairs_aux, 2);
+ return 1;
+}
+
+
+
+
+
+static int gfind_nodef (lua_State *L) {
+ return luaL_error(L, LUA_QL("string.gfind") " was renamed to "
+ LUA_QL("string.gmatch"));
+}
+
+
+static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
+ const char *e) {
+ size_t l, i;
+ const char *news = lua_tolstring(ms->L, 3, &l);
+ for (i = 0; i < l; i++) {
+ if (news[i] != L_ESC)
+ luaL_addchar(b, news[i]);
+ else {
+ i++; /* skip ESC */
+ if (!isdigit(uchar(news[i])))
+ luaL_addchar(b, news[i]);
+ else if (news[i] == '0')
+ luaL_addlstring(b, s, e - s);
+ else {
+ push_onecapture(ms, news[i] - '1', s, e);
+ luaL_addvalue(b); /* add capture to accumulated result */
+ }
+ }
+ }
+}
+
+
+static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
+ const char *e) {
+ lua_State *L = ms->L;
+ switch (lua_type(L, 3)) {
+ case LUA_TNUMBER:
+ case LUA_TSTRING: {
+ add_s(ms, b, s, e);
+ return;
+ }
+ case LUA_TFUNCTION: {
+ int n;
+ lua_pushvalue(L, 3);
+ n = push_captures(ms, s, e);
+ lua_call(L, n, 1);
+ break;
+ }
+ case LUA_TTABLE: {
+ push_onecapture(ms, 0, s, e);
+ lua_gettable(L, 3);
+ break;
+ }
+ default: {
+ luaL_argerror(L, 3, "string/function/table expected");
+ return;
+ }
+ }
+ if (!lua_toboolean(L, -1)) { /* nil or false? */
+ lua_pop(L, 1);
+ lua_pushlstring(L, s, e - s); /* keep original text */
+ }
+ else if (!lua_isstring(L, -1))
+ luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
+ luaL_addvalue(b); /* add result to accumulator */
+}
+
+
+static int str_gsub (lua_State *L) {
+ size_t srcl;
+ const char *src = luaL_checklstring(L, 1, &srcl);
+ const char *p = luaL_checkstring(L, 2);
+ int max_s = luaL_optint(L, 4, srcl+1);
+ int anchor = (*p == '^') ? (p++, 1) : 0;
+ int n = 0;
+ MatchState ms;
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ ms.L = L;
+ ms.src_init = src;
+ ms.src_end = src+srcl;
+ while (n < max_s) {
+ const char *e;
+ ms.level = 0;
+ e = match(&ms, src, p);
+ if (e) {
+ n++;
+ add_value(&ms, &b, src, e);
+ }
+ if (e && e>src) /* non empty match? */
+ src = e; /* skip it */
+ else if (src < ms.src_end)
+ luaL_addchar(&b, *src++);
+ else break;
+ if (anchor) break;
+ }
+ luaL_addlstring(&b, src, ms.src_end-src);
+ luaL_pushresult(&b);
+ lua_pushinteger(L, n); /* number of substitutions */
+ return 2;
+}
+
+/* }====================================================== */
+
+
+/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
+#define MAX_ITEM 512
+/* valid flags in a format specification */
+#define FLAGS "-+ #0"
+/*
+** maximum size of each format specification (such as '%-099.99d')
+** (+10 accounts for %99.99x plus margin of error)
+*/
+#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
+
+
+static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
+ size_t l;
+ const char *s = luaL_checklstring(L, arg, &l);
+ luaL_addchar(b, '"');
+ while (l--) {
+ if (*s == '"' || *s == '\\' || *s == '\n') {
+ luaL_addchar(b, '\\');
+ luaL_addchar(b, *s);
+ }
+ else if (*s == '\0' || iscntrl(uchar(*s))) {
+ char buff[10];
+ if (*s != '\0' && !isdigit(uchar(*(s+1))))
+ sprintf(buff, "\\%d", uchar(*s));
+ else
+ sprintf(buff, "\\%03d", uchar(*s));
+ luaL_addstring(b, buff);
+ }
+ else
+ luaL_addchar(b, *s);
+ s++;
+ }
+ luaL_addchar(b, '"');
+}
+
+static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
+ const char *p = strfrmt;
+ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */
+ if ((size_t)(p - strfrmt) >= sizeof(FLAGS))
+ luaL_error(L, "invalid format (repeated flags)");
+ if (isdigit(uchar(*p))) p++; /* skip width */
+ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
+ if (*p == '.') {
+ p++;
+ if (isdigit(uchar(*p))) p++; /* skip precision */
+ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
+ }
+ if (isdigit(uchar(*p)))
+ luaL_error(L, "invalid format (width or precision too long)");
+ *(form++) = '%';
+ strncpy(form, strfrmt, p - strfrmt + 1);
+ form += p - strfrmt + 1;
+ *form = '\0';
+ return p;
+}
+
+
+static void addintlen (char *form) {
+ size_t l = strlen(form);
+ char spec = form[l - 1];
+ strcpy(form + l - 1, LUA_INTFRMLEN);
+ form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
+ form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
+}
+
+
+static int str_format (lua_State *L) {
+ int arg = 1;
+ size_t sfl;
+ const char *strfrmt = luaL_checklstring(L, arg, &sfl);
+ const char *strfrmt_end = strfrmt+sfl;
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ while (strfrmt < strfrmt_end) {
+ if (*strfrmt != L_ESC)
+ luaL_addchar(&b, *strfrmt++);
+ else if (*++strfrmt == L_ESC)
+ luaL_addchar(&b, *strfrmt++); /* %% */
+ else { /* format item */
+ char form[MAX_FORMAT]; /* to store the format (`%...') */
+ char buff[MAX_ITEM]; /* to store the formatted item */
+ arg++;
+ strfrmt = scanformat(L, strfrmt, form);
+ switch (*strfrmt++) {
+ case 'c': {
+ sprintf(buff, form, (int)luaL_checknumber(L, arg));
+ break;
+ }
+ case 'd': case 'i': {
+ addintlen(form);
+ sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
+ break;
+ }
+ case 'o': case 'u': case 'x': case 'X': {
+ addintlen(form);
+ sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
+ break;
+ }
+ case 'e': case 'E': case 'f':
+ case 'g': case 'G': {
+ sprintf(buff, form, (double)luaL_checknumber(L, arg));
+ break;
+ }
+ case 'q': {
+ addquoted(L, &b, arg);
+ continue; /* skip the 'addsize' at the end */
+ }
+ case 's': {
+ size_t l;
+ const char *s = luaL_checklstring(L, arg, &l);
+ if (!strchr(form, '.') && l >= 100) {
+ /* no precision and string is too long to be formatted;
+ keep original string */
+ lua_pushvalue(L, arg);
+ luaL_addvalue(&b);
+ continue; /* skip the `addsize' at the end */
+ }
+ else {
+ sprintf(buff, form, s);
+ break;
+ }
+ }
+ default: { /* also treat cases `pnLlh' */
+ return luaL_error(L, "invalid option " LUA_QL("%%%c") " to "
+ LUA_QL("format"), *(strfrmt - 1));
+ }
+ }
+ luaL_addlstring(&b, buff, strlen(buff));
+ }
+ }
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int str_split (lua_State *L) {
+ size_t l;
+ size_t i;
+ int n;
+ char *q, *p;
+ int mult = 0;
+ const char *s = luaL_checklstring(L, 1, &l);
+ const char *joiner = luaL_optstring(L, 2, " +");
+ lua_newtable(L);
+ if (l == 0) {
+ lua_pushvalue(L,1);
+ lua_rawseti(L,-2,1);
+ return 1;
+ }
+ p = malloc(l+1);
+ if (p==NULL) {
+ fprintf(stderr, "fatal: memory exhausted (malloc of %u bytes).\n",l+1);
+ exit(EXIT_FAILURE);
+ }
+ strcpy(p,s);
+ n = 1;
+ q = p;
+
+ if (*joiner == 0) {
+ for (i=0;i<l;i++) {
+ lua_pushlstring(L,q,1); q++;
+ lua_rawseti(L,-2,n); n++;
+ }
+ return 1;
+ }
+ if (*(joiner+1) == '+') {
+ mult = 1;
+ while(*p==*joiner) {
+ p++;
+ l--;
+ }
+ q = p;
+ }
+ for (i=0;i<l;i++) {
+ if (*(p+i)==*joiner) {
+ *(p+i) = 0;
+ lua_pushlstring(L,q,((p+i)-q));
+ lua_rawseti(L,-2,n); n++;
+ if (mult) {
+ while(*(p+i+1)==*joiner) {
+ i++;
+ }
+ }
+ q = p+i+1;
+ }
+ }
+ if (mult && q==(p+l)) {
+ return 1;
+ }
+ if(q<=(p+l)) {
+ lua_pushlstring(L,q,strlen(q));
+ lua_rawseti(L,-2,n);
+ }
+ return 1;
+}
+
+static const luaL_Reg strlib[] = {
+ {"byte", str_byte},
+ {"char", str_char},
+ {"dump", str_dump},
+ {"find", str_find},
+ {"format", str_format},
+ {"gfind", gfind_nodef},
+ {"gmatch", gmatch},
+ {"utfvalues", str_utfvalues},
+ {"utfcharacters", str_utfcharacters},
+ {"characters", str_characters},
+ {"characterpairs", str_characterpairs},
+ {"bytes", str_bytes},
+ {"bytepairs", str_bytepairs},
+ {"gsub", str_gsub},
+ {"len", str_len},
+ {"lower", str_lower},
+ {"match", str_match},
+ {"rep", str_rep},
+ {"reverse", str_reverse},
+ {"sub", str_sub},
+ {"upper", str_upper},
+ {"explode", str_split},
+ {NULL, NULL}
+};
+
+
+static void createmetatable (lua_State *L) {
+ lua_createtable(L, 0, 1); /* create metatable for strings */
+ lua_pushliteral(L, ""); /* dummy string */
+ lua_pushvalue(L, -2);
+ lua_setmetatable(L, -2); /* set string metatable */
+ lua_pop(L, 1); /* pop dummy string */
+ lua_pushvalue(L, -2); /* string library... */
+ lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */
+ lua_pop(L, 1); /* pop metatable */
+}
+
+
+/*
+** Open string library
+*/
+LUALIB_API int luaopen_string (lua_State *L) {
+ luaL_register(L, LUA_STRLIBNAME, strlib);
+#if defined(LUA_COMPAT_GFIND)
+ lua_getfield(L, -1, "gmatch");
+ lua_setfield(L, -2, "gfind");
+#endif
+ createmetatable(L);
+ return 1;
+}
+
diff --git a/Build/source/libs/lua51/ltable.c b/Build/source/libs/lua51/ltable.c
new file mode 100644
index 00000000000..bc91cacd637
--- /dev/null
+++ b/Build/source/libs/lua51/ltable.c
@@ -0,0 +1,588 @@
+/*
+** $Id: ltable.c,v 2.32 2006/01/18 11:49:02 roberto Exp $
+** Lua tables (hash)
+** See Copyright Notice in lua.h
+*/
+
+
+/*
+** Implementation of tables (aka arrays, objects, or hash tables).
+** Tables keep its elements in two parts: an array part and a hash part.
+** Non-negative integer keys are all candidates to be kept in the array
+** part. The actual size of the array is the largest `n' such that at
+** least half the slots between 0 and n are in use.
+** Hash uses a mix of chained scatter table with Brent's variation.
+** A main invariant of these tables is that, if an element is not
+** in its main position (i.e. the `original' position that its hash gives
+** to it), then the colliding element is in its own main position.
+** Hence even when the load factor reaches 100%, performance remains good.
+*/
+
+#include <math.h>
+#include <string.h>
+
+#define ltable_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "ltable.h"
+
+
+/*
+** max size of array part is 2^MAXBITS
+*/
+#if LUAI_BITSINT > 26
+#define MAXBITS 26
+#else
+#define MAXBITS (LUAI_BITSINT-2)
+#endif
+
+#define MAXASIZE (1 << MAXBITS)
+
+
+#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
+
+#define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
+#define hashboolean(t,p) hashpow2(t, p)
+
+
+/*
+** for some types, it is better to avoid modulus by power of 2, as
+** they tend to have many 2 factors.
+*/
+#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
+
+
+#define hashpointer(t,p) hashmod(t, IntPoint(p))
+
+
+/*
+** number of ints inside a lua_Number
+*/
+#define numints cast_int(sizeof(lua_Number)/sizeof(int))
+
+
+
+#define dummynode (&dummynode_)
+
+static const Node dummynode_ = {
+ {{NULL}, LUA_TNIL}, /* value */
+ {{{NULL}, LUA_TNIL, NULL}} /* key */
+};
+
+
+/*
+** hash for lua_Numbers
+*/
+static Node *hashnum (const Table *t, lua_Number n) {
+ unsigned int a[numints];
+ int i;
+ n += 1; /* normalize number (avoid -0) */
+ lua_assert(sizeof(a) <= sizeof(n));
+ memcpy(a, &n, sizeof(a));
+ for (i = 1; i < numints; i++) a[0] += a[i];
+ return hashmod(t, a[0]);
+}
+
+
+
+/*
+** returns the `main' position of an element in a table (that is, the index
+** of its hash value)
+*/
+static Node *mainposition (const Table *t, const TValue *key) {
+ switch (ttype(key)) {
+ case LUA_TNUMBER:
+ return hashnum(t, nvalue(key));
+ case LUA_TSTRING:
+ return hashstr(t, rawtsvalue(key));
+ case LUA_TBOOLEAN:
+ return hashboolean(t, bvalue(key));
+ case LUA_TLIGHTUSERDATA:
+ return hashpointer(t, pvalue(key));
+ default:
+ return hashpointer(t, gcvalue(key));
+ }
+}
+
+
+/*
+** returns the index for `key' if `key' is an appropriate key to live in
+** the array part of the table, -1 otherwise.
+*/
+static int arrayindex (const TValue *key) {
+ if (ttisnumber(key)) {
+ lua_Number n = nvalue(key);
+ int k;
+ lua_number2int(k, n);
+ if (luai_numeq(cast_num(k), n))
+ return k;
+ }
+ return -1; /* `key' did not match some condition */
+}
+
+
+/*
+** returns the index of a `key' for table traversals. First goes all
+** elements in the array part, then elements in the hash part. The
+** beginning of a traversal is signalled by -1.
+*/
+static int findindex (lua_State *L, Table *t, StkId key) {
+ int i;
+ if (ttisnil(key)) return -1; /* first iteration */
+ i = arrayindex(key);
+ if (0 < i && i <= t->sizearray) /* is `key' inside array part? */
+ return i-1; /* yes; that's the index (corrected to C) */
+ else {
+ Node *n = mainposition(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+ /* key may be dead already, but it is ok to use it in `next' */
+ if (luaO_rawequalObj(key2tval(n), key) ||
+ (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&
+ gcvalue(gkey(n)) == gcvalue(key))) {
+ i = cast_int(n - gnode(t, 0)); /* key index in hash table */
+ /* hash elements are numbered after array ones */
+ return i + t->sizearray;
+ }
+ else n = gnext(n);
+ } while (n);
+ luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */
+ return 0; /* to avoid warnings */
+ }
+}
+
+
+int luaH_next (lua_State *L, Table *t, StkId key) {
+ int i = findindex(L, t, key); /* find original element */
+ for (i++; i < t->sizearray; i++) { /* try first array part */
+ if (!ttisnil(&t->array[i])) { /* a non-nil value? */
+ setnvalue(key, cast_num(i+1));
+ setobj2s(L, key+1, &t->array[i]);
+ return 1;
+ }
+ }
+ for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */
+ if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */
+ setobj2s(L, key, key2tval(gnode(t, i)));
+ setobj2s(L, key+1, gval(gnode(t, i)));
+ return 1;
+ }
+ }
+ return 0; /* no more elements */
+}
+
+
+/*
+** {=============================================================
+** Rehash
+** ==============================================================
+*/
+
+
+static int computesizes (int nums[], int *narray) {
+ int i;
+ int twotoi; /* 2^i */
+ int a = 0; /* number of elements smaller than 2^i */
+ int na = 0; /* number of elements to go to array part */
+ int n = 0; /* optimal size for array part */
+ for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {
+ if (nums[i] > 0) {
+ a += nums[i];
+ if (a > twotoi/2) { /* more than half elements present? */
+ n = twotoi; /* optimal size (till now) */
+ na = a; /* all elements smaller than n will go to array part */
+ }
+ }
+ if (a == *narray) break; /* all elements already counted */
+ }
+ *narray = n;
+ lua_assert(*narray/2 <= na && na <= *narray);
+ return na;
+}
+
+
+static int countint (const TValue *key, int *nums) {
+ int k = arrayindex(key);
+ if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */
+ nums[ceillog2(k)]++; /* count as such */
+ return 1;
+ }
+ else
+ return 0;
+}
+
+
+static int numusearray (const Table *t, int *nums) {
+ int lg;
+ int ttlg; /* 2^lg */
+ int ause = 0; /* summation of `nums' */
+ int i = 1; /* count to traverse all array keys */
+ for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */
+ int lc = 0; /* counter */
+ int lim = ttlg;
+ if (lim > t->sizearray) {
+ lim = t->sizearray; /* adjust upper limit */
+ if (i > lim)
+ break; /* no more elements to count */
+ }
+ /* count elements in range (2^(lg-1), 2^lg] */
+ for (; i <= lim; i++) {
+ if (!ttisnil(&t->array[i-1]))
+ lc++;
+ }
+ nums[lg] += lc;
+ ause += lc;
+ }
+ return ause;
+}
+
+
+static int numusehash (const Table *t, int *nums, int *pnasize) {
+ int totaluse = 0; /* total number of elements */
+ int ause = 0; /* summation of `nums' */
+ int i = sizenode(t);
+ while (i--) {
+ Node *n = &t->node[i];
+ if (!ttisnil(gval(n))) {
+ ause += countint(key2tval(n), nums);
+ totaluse++;
+ }
+ }
+ *pnasize += ause;
+ return totaluse;
+}
+
+
+static void setarrayvector (lua_State *L, Table *t, int size) {
+ int i;
+ luaM_reallocvector(L, t->array, t->sizearray, size, TValue);
+ for (i=t->sizearray; i<size; i++)
+ setnilvalue(&t->array[i]);
+ t->sizearray = size;
+}
+
+
+static void setnodevector (lua_State *L, Table *t, int size) {
+ int lsize;
+ if (size == 0) { /* no elements to hash part? */
+ t->node = cast(Node *, dummynode); /* use common `dummynode' */
+ lsize = 0;
+ }
+ else {
+ int i;
+ lsize = ceillog2(size);
+ if (lsize > MAXBITS)
+ luaG_runerror(L, "table overflow");
+ size = twoto(lsize);
+ t->node = luaM_newvector(L, size, Node);
+ for (i=0; i<size; i++) {
+ Node *n = gnode(t, i);
+ gnext(n) = NULL;
+ setnilvalue(gkey(n));
+ setnilvalue(gval(n));
+ }
+ }
+ t->lsizenode = cast_byte(lsize);
+ t->lastfree = gnode(t, size); /* all positions are free */
+}
+
+
+static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
+ int i;
+ int oldasize = t->sizearray;
+ int oldhsize = t->lsizenode;
+ Node *nold = t->node; /* save old hash ... */
+ if (nasize > oldasize) /* array part must grow? */
+ setarrayvector(L, t, nasize);
+ /* create new hash part with appropriate size */
+ setnodevector(L, t, nhsize);
+ if (nasize < oldasize) { /* array part must shrink? */
+ t->sizearray = nasize;
+ /* re-insert elements from vanishing slice */
+ for (i=nasize; i<oldasize; i++) {
+ if (!ttisnil(&t->array[i]))
+ setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);
+ }
+ /* shrink array */
+ luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
+ }
+ /* re-insert elements from hash part */
+ for (i = twoto(oldhsize) - 1; i >= 0; i--) {
+ Node *old = nold+i;
+ if (!ttisnil(gval(old)))
+ setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));
+ }
+ if (nold != dummynode)
+ luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */
+}
+
+
+void luaH_resizearray (lua_State *L, Table *t, int nasize) {
+ int nsize = (t->node == dummynode) ? 0 : sizenode(t);
+ resize(L, t, nasize, nsize);
+}
+
+
+static void rehash (lua_State *L, Table *t, const TValue *ek) {
+ int nasize, na;
+ int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */
+ int i;
+ int totaluse;
+ for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */
+ nasize = numusearray(t, nums); /* count keys in array part */
+ totaluse = nasize; /* all those keys are integer keys */
+ totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */
+ /* count extra key */
+ nasize += countint(ek, nums);
+ totaluse++;
+ /* compute new size for array part */
+ na = computesizes(nums, &nasize);
+ /* resize the table to new computed sizes */
+ resize(L, t, nasize, totaluse - na);
+}
+
+
+
+/*
+** }=============================================================
+*/
+
+
+Table *luaH_new (lua_State *L, int narray, int nhash) {
+ Table *t = luaM_new(L, Table);
+ luaC_link(L, obj2gco(t), LUA_TTABLE);
+ t->metatable = NULL;
+ t->flags = cast_byte(~0);
+ /* temporary values (kept only if some malloc fails) */
+ t->array = NULL;
+ t->sizearray = 0;
+ t->lsizenode = 0;
+ t->node = cast(Node *, dummynode);
+ setarrayvector(L, t, narray);
+ setnodevector(L, t, nhash);
+ return t;
+}
+
+
+void luaH_free (lua_State *L, Table *t) {
+ if (t->node != dummynode)
+ luaM_freearray(L, t->node, sizenode(t), Node);
+ luaM_freearray(L, t->array, t->sizearray, TValue);
+ luaM_free(L, t);
+}
+
+
+static Node *getfreepos (Table *t) {
+ while (t->lastfree-- > t->node) {
+ if (ttisnil(gkey(t->lastfree)))
+ return t->lastfree;
+ }
+ return NULL; /* could not find a free place */
+}
+
+
+
+/*
+** inserts a new key into a hash table; first, check whether key's main
+** position is free. If not, check whether colliding node is in its main
+** position or not: if it is not, move colliding node to an empty place and
+** put new key in its main position; otherwise (colliding node is in its main
+** position), new key goes to an empty position.
+*/
+static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
+ Node *mp = mainposition(t, key);
+ if (!ttisnil(gval(mp)) || mp == dummynode) {
+ Node *othern;
+ Node *n = getfreepos(t); /* get a free place */
+ if (n == NULL) { /* cannot find a free place? */
+ rehash(L, t, key); /* grow table */
+ return luaH_set(L, t, key); /* re-insert key into grown table */
+ }
+ lua_assert(n != dummynode);
+ othern = mainposition(t, key2tval(mp));
+ if (othern != mp) { /* is colliding node out of its main position? */
+ /* yes; move colliding node into free position */
+ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */
+ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */
+ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */
+ gnext(mp) = NULL; /* now `mp' is free */
+ setnilvalue(gval(mp));
+ }
+ else { /* colliding node is in its own main position */
+ /* new node will go into free position */
+ gnext(n) = gnext(mp); /* chain new position */
+ gnext(mp) = n;
+ mp = n;
+ }
+ }
+ gkey(mp)->value = key->value; gkey(mp)->tt = key->tt;
+ luaC_barriert(L, t, key);
+ lua_assert(ttisnil(gval(mp)));
+ return gval(mp);
+}
+
+
+/*
+** search function for integers
+*/
+const TValue *luaH_getnum (Table *t, int key) {
+ /* (1 <= key && key <= t->sizearray) */
+ if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
+ return &t->array[key-1];
+ else {
+ lua_Number nk = cast_num(key);
+ Node *n = hashnum(t, nk);
+ do { /* check whether `key' is somewhere in the chain */
+ if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
+ return gval(n); /* that's it */
+ else n = gnext(n);
+ } while (n);
+ return luaO_nilobject;
+ }
+}
+
+
+/*
+** search function for strings
+*/
+const TValue *luaH_getstr (Table *t, TString *key) {
+ Node *n = hashstr(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+ if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)
+ return gval(n); /* that's it */
+ else n = gnext(n);
+ } while (n);
+ return luaO_nilobject;
+}
+
+
+/*
+** main search function
+*/
+const TValue *luaH_get (Table *t, const TValue *key) {
+ switch (ttype(key)) {
+ case LUA_TNIL: return luaO_nilobject;
+ case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
+ case LUA_TNUMBER: {
+ int k;
+ lua_Number n = nvalue(key);
+ lua_number2int(k, n);
+ if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
+ return luaH_getnum(t, k); /* use specialized version */
+ /* else go through */
+ }
+ default: {
+ Node *n = mainposition(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+ if (luaO_rawequalObj(key2tval(n), key))
+ return gval(n); /* that's it */
+ else n = gnext(n);
+ } while (n);
+ return luaO_nilobject;
+ }
+ }
+}
+
+
+TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
+ const TValue *p = luaH_get(t, key);
+ t->flags = 0;
+ if (p != luaO_nilobject)
+ return cast(TValue *, p);
+ else {
+ if (ttisnil(key)) luaG_runerror(L, "table index is nil");
+ else if (ttisnumber(key) && luai_numisnan(nvalue(key)))
+ luaG_runerror(L, "table index is NaN");
+ return newkey(L, t, key);
+ }
+}
+
+
+TValue *luaH_setnum (lua_State *L, Table *t, int key) {
+ const TValue *p = luaH_getnum(t, key);
+ if (p != luaO_nilobject)
+ return cast(TValue *, p);
+ else {
+ TValue k;
+ setnvalue(&k, cast_num(key));
+ return newkey(L, t, &k);
+ }
+}
+
+
+TValue *luaH_setstr (lua_State *L, Table *t, TString *key) {
+ const TValue *p = luaH_getstr(t, key);
+ if (p != luaO_nilobject)
+ return cast(TValue *, p);
+ else {
+ TValue k;
+ setsvalue(L, &k, key);
+ return newkey(L, t, &k);
+ }
+}
+
+
+static int unbound_search (Table *t, unsigned int j) {
+ unsigned int i = j; /* i is zero or a present index */
+ j++;
+ /* find `i' and `j' such that i is present and j is not */
+ while (!ttisnil(luaH_getnum(t, j))) {
+ i = j;
+ j *= 2;
+ if (j > cast(unsigned int, MAX_INT)) { /* overflow? */
+ /* table was built with bad purposes: resort to linear search */
+ i = 1;
+ while (!ttisnil(luaH_getnum(t, i))) i++;
+ return i - 1;
+ }
+ }
+ /* now do a binary search between them */
+ while (j - i > 1) {
+ unsigned int m = (i+j)/2;
+ if (ttisnil(luaH_getnum(t, m))) j = m;
+ else i = m;
+ }
+ return i;
+}
+
+
+/*
+** Try to find a boundary in table `t'. A `boundary' is an integer index
+** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
+*/
+int luaH_getn (Table *t) {
+ unsigned int j = t->sizearray;
+ if (j > 0 && ttisnil(&t->array[j - 1])) {
+ /* there is a boundary in the array part: (binary) search for it */
+ unsigned int i = 0;
+ while (j - i > 1) {
+ unsigned int m = (i+j)/2;
+ if (ttisnil(&t->array[m - 1])) j = m;
+ else i = m;
+ }
+ return i;
+ }
+ /* else must find a boundary in hash part */
+ else if (t->node == dummynode) /* hash part is empty? */
+ return j; /* that is easy... */
+ else return unbound_search(t, j);
+}
+
+
+
+#if defined(LUA_DEBUG)
+
+Node *luaH_mainposition (const Table *t, const TValue *key) {
+ return mainposition(t, key);
+}
+
+int luaH_isdummy (Node *n) { return n == dummynode; }
+
+#endif
diff --git a/Build/source/libs/lua51/ltable.h b/Build/source/libs/lua51/ltable.h
new file mode 100644
index 00000000000..09193cdbe04
--- /dev/null
+++ b/Build/source/libs/lua51/ltable.h
@@ -0,0 +1,40 @@
+/*
+** $Id: ltable.h,v 2.10 2006/01/10 13:13:06 roberto Exp $
+** Lua tables (hash)
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ltable_h
+#define ltable_h
+
+#include "lobject.h"
+
+
+#define gnode(t,i) (&(t)->node[i])
+#define gkey(n) (&(n)->i_key.nk)
+#define gval(n) (&(n)->i_val)
+#define gnext(n) ((n)->i_key.nk.next)
+
+#define key2tval(n) (&(n)->i_key.tvk)
+
+
+LUAI_FUNC const TValue *luaH_getnum (Table *t, int key);
+LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);
+LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
+LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
+LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
+LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
+LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash);
+LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);
+LUAI_FUNC void luaH_free (lua_State *L, Table *t);
+LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
+LUAI_FUNC int luaH_getn (Table *t);
+
+
+#if defined(LUA_DEBUG)
+LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
+LUAI_FUNC int luaH_isdummy (Node *n);
+#endif
+
+
+#endif
diff --git a/Build/source/libs/lua51/ltablib.c b/Build/source/libs/lua51/ltablib.c
new file mode 100644
index 00000000000..453b23b378b
--- /dev/null
+++ b/Build/source/libs/lua51/ltablib.c
@@ -0,0 +1,278 @@
+/*
+** $Id: ltablib.c,v 1.38 2005/10/23 17:38:15 roberto Exp $
+** Library for Table Manipulation
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stddef.h>
+
+#define ltablib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))
+
+
+static int foreachi (lua_State *L) {
+ int i;
+ int n = aux_getn(L, 1);
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+ for (i=1; i <= n; i++) {
+ lua_pushvalue(L, 2); /* function */
+ lua_pushinteger(L, i); /* 1st argument */
+ lua_rawgeti(L, 1, i); /* 2nd argument */
+ lua_call(L, 2, 1);
+ if (!lua_isnil(L, -1))
+ return 1;
+ lua_pop(L, 1); /* remove nil result */
+ }
+ return 0;
+}
+
+
+static int foreach (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, 1)) {
+ lua_pushvalue(L, 2); /* function */
+ lua_pushvalue(L, -3); /* key */
+ lua_pushvalue(L, -3); /* value */
+ lua_call(L, 2, 1);
+ if (!lua_isnil(L, -1))
+ return 1;
+ lua_pop(L, 2); /* remove value and result */
+ }
+ return 0;
+}
+
+
+static int maxn (lua_State *L) {
+ lua_Number max = 0;
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, 1)) {
+ lua_pop(L, 1); /* remove value */
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ lua_Number v = lua_tonumber(L, -1);
+ if (v > max) max = v;
+ }
+ }
+ lua_pushnumber(L, max);
+ return 1;
+}
+
+
+static int getn (lua_State *L) {
+ lua_pushinteger(L, aux_getn(L, 1));
+ return 1;
+}
+
+
+static int setn (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+#ifndef luaL_setn
+ luaL_setn(L, 1, luaL_checkint(L, 2));
+#else
+ luaL_error(L, LUA_QL("setn") " is obsolete");
+#endif
+ lua_pushvalue(L, 1);
+ return 1;
+}
+
+
+static int tinsert (lua_State *L) {
+ int e = aux_getn(L, 1) + 1; /* first empty element */
+ int pos; /* where to insert new element */
+ switch (lua_gettop(L)) {
+ case 2: { /* called with only 2 arguments */
+ pos = e; /* insert new element at the end */
+ break;
+ }
+ case 3: {
+ int i;
+ pos = luaL_checkint(L, 2); /* 2nd argument is the position */
+ if (pos > e) e = pos; /* `grow' array if necessary */
+ for (i = e; i > pos; i--) { /* move up elements */
+ lua_rawgeti(L, 1, i-1);
+ lua_rawseti(L, 1, i); /* t[i] = t[i-1] */
+ }
+ break;
+ }
+ default: {
+ return luaL_error(L, "wrong number of arguments to " LUA_QL("insert"));
+ }
+ }
+ luaL_setn(L, 1, e); /* new size */
+ lua_rawseti(L, 1, pos); /* t[pos] = v */
+ return 0;
+}
+
+
+static int tremove (lua_State *L) {
+ int e = aux_getn(L, 1);
+ int pos = luaL_optint(L, 2, e);
+ if (e == 0) return 0; /* table is `empty' */
+ luaL_setn(L, 1, e - 1); /* t.n = n-1 */
+ lua_rawgeti(L, 1, pos); /* result = t[pos] */
+ for ( ;pos<e; pos++) {
+ lua_rawgeti(L, 1, pos+1);
+ lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */
+ }
+ lua_pushnil(L);
+ lua_rawseti(L, 1, e); /* t[e] = nil */
+ return 1;
+}
+
+
+static int tconcat (lua_State *L) {
+ luaL_Buffer b;
+ size_t lsep;
+ int i, last;
+ const char *sep = luaL_optlstring(L, 2, "", &lsep);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ i = luaL_optint(L, 3, 1);
+ last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1));
+ luaL_buffinit(L, &b);
+ for (; i <= last; i++) {
+ lua_rawgeti(L, 1, i);
+ luaL_argcheck(L, lua_isstring(L, -1), 1, "table contains non-strings");
+ luaL_addvalue(&b);
+ if (i != last)
+ luaL_addlstring(&b, sep, lsep);
+ }
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+
+/*
+** {======================================================
+** Quicksort
+** (based on `Algorithms in MODULA-3', Robert Sedgewick;
+** Addison-Wesley, 1993.)
+*/
+
+
+static void set2 (lua_State *L, int i, int j) {
+ lua_rawseti(L, 1, i);
+ lua_rawseti(L, 1, j);
+}
+
+static int sort_comp (lua_State *L, int a, int b) {
+ if (!lua_isnil(L, 2)) { /* function? */
+ int res;
+ lua_pushvalue(L, 2);
+ lua_pushvalue(L, a-1); /* -1 to compensate function */
+ lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */
+ lua_call(L, 2, 1);
+ res = lua_toboolean(L, -1);
+ lua_pop(L, 1);
+ return res;
+ }
+ else /* a < b? */
+ return lua_lessthan(L, a, b);
+}
+
+static void auxsort (lua_State *L, int l, int u) {
+ while (l < u) { /* for tail recursion */
+ int i, j;
+ /* sort elements a[l], a[(l+u)/2] and a[u] */
+ lua_rawgeti(L, 1, l);
+ lua_rawgeti(L, 1, u);
+ if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */
+ set2(L, l, u); /* swap a[l] - a[u] */
+ else
+ lua_pop(L, 2);
+ if (u-l == 1) break; /* only 2 elements */
+ i = (l+u)/2;
+ lua_rawgeti(L, 1, i);
+ lua_rawgeti(L, 1, l);
+ if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */
+ set2(L, i, l);
+ else {
+ lua_pop(L, 1); /* remove a[l] */
+ lua_rawgeti(L, 1, u);
+ if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */
+ set2(L, i, u);
+ else
+ lua_pop(L, 2);
+ }
+ if (u-l == 2) break; /* only 3 elements */
+ lua_rawgeti(L, 1, i); /* Pivot */
+ lua_pushvalue(L, -1);
+ lua_rawgeti(L, 1, u-1);
+ set2(L, i, u-1);
+ /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
+ i = l; j = u-1;
+ for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */
+ /* repeat ++i until a[i] >= P */
+ while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {
+ if (i>u) luaL_error(L, "invalid order function for sorting");
+ lua_pop(L, 1); /* remove a[i] */
+ }
+ /* repeat --j until a[j] <= P */
+ while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {
+ if (j<l) luaL_error(L, "invalid order function for sorting");
+ lua_pop(L, 1); /* remove a[j] */
+ }
+ if (j<i) {
+ lua_pop(L, 3); /* pop pivot, a[i], a[j] */
+ break;
+ }
+ set2(L, i, j);
+ }
+ lua_rawgeti(L, 1, u-1);
+ lua_rawgeti(L, 1, i);
+ set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */
+ /* a[l..i-1] <= a[i] == P <= a[i+1..u] */
+ /* adjust so that smaller half is in [j..i] and larger one in [l..u] */
+ if (i-l < u-i) {
+ j=l; i=i-1; l=i+2;
+ }
+ else {
+ j=i+1; i=u; u=j-2;
+ }
+ auxsort(L, j, i); /* call recursively the smaller one */
+ } /* repeat the routine for the larger one */
+}
+
+static int sort (lua_State *L) {
+ int n = aux_getn(L, 1);
+ luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */
+ if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+ lua_settop(L, 2); /* make sure there is two arguments */
+ auxsort(L, 1, n);
+ return 0;
+}
+
+/* }====================================================== */
+
+
+static const luaL_Reg tab_funcs[] = {
+ {"concat", tconcat},
+ {"foreach", foreach},
+ {"foreachi", foreachi},
+ {"getn", getn},
+ {"maxn", maxn},
+ {"insert", tinsert},
+ {"remove", tremove},
+ {"setn", setn},
+ {"sort", sort},
+ {NULL, NULL}
+};
+
+
+LUALIB_API int luaopen_table (lua_State *L) {
+ luaL_register(L, LUA_TABLIBNAME, tab_funcs);
+ return 1;
+}
+
diff --git a/Build/source/libs/lua51/ltm.c b/Build/source/libs/lua51/ltm.c
new file mode 100644
index 00000000000..097b815ad3a
--- /dev/null
+++ b/Build/source/libs/lua51/ltm.c
@@ -0,0 +1,75 @@
+/*
+** $Id: ltm.c,v 2.8 2006/01/10 12:50:00 roberto Exp $
+** Tag methods
+** See Copyright Notice in lua.h
+*/
+
+
+#include <string.h>
+
+#define ltm_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+
+
+
+const char *const luaT_typenames[] = {
+ "nil", "boolean", "userdata", "number",
+ "string", "table", "function", "userdata", "thread",
+ "proto", "upval"
+};
+
+
+void luaT_init (lua_State *L) {
+ static const char *const luaT_eventname[] = { /* ORDER TM */
+ "__index", "__newindex",
+ "__gc", "__mode", "__eq",
+ "__add", "__sub", "__mul", "__div", "__mod",
+ "__pow", "__unm", "__len", "__lt", "__le",
+ "__concat", "__call"
+ };
+ int i;
+ for (i=0; i<TM_N; i++) {
+ G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);
+ luaS_fix(G(L)->tmname[i]); /* never collect these names */
+ }
+}
+
+
+/*
+** function to be used with macro "fasttm": optimized for absence of
+** tag methods
+*/
+const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
+ const TValue *tm = luaH_getstr(events, ename);
+ lua_assert(event <= TM_EQ);
+ if (ttisnil(tm)) { /* no tag method? */
+ events->flags |= cast_byte(1u<<event); /* cache this fact */
+ return NULL;
+ }
+ else return tm;
+}
+
+
+const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
+ Table *mt;
+ switch (ttype(o)) {
+ case LUA_TTABLE:
+ mt = hvalue(o)->metatable;
+ break;
+ case LUA_TUSERDATA:
+ mt = uvalue(o)->metatable;
+ break;
+ default:
+ mt = G(L)->mt[ttype(o)];
+ }
+ return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
+}
+
diff --git a/Build/source/libs/lua51/ltm.h b/Build/source/libs/lua51/ltm.h
new file mode 100644
index 00000000000..866c79668d8
--- /dev/null
+++ b/Build/source/libs/lua51/ltm.h
@@ -0,0 +1,54 @@
+/*
+** $Id: ltm.h,v 2.6 2005/06/06 13:30:25 roberto Exp $
+** Tag methods
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ltm_h
+#define ltm_h
+
+
+#include "lobject.h"
+
+
+/*
+* WARNING: if you change the order of this enumeration,
+* grep "ORDER TM"
+*/
+typedef enum {
+ TM_INDEX,
+ TM_NEWINDEX,
+ TM_GC,
+ TM_MODE,
+ TM_EQ, /* last tag method with `fast' access */
+ TM_ADD,
+ TM_SUB,
+ TM_MUL,
+ TM_DIV,
+ TM_MOD,
+ TM_POW,
+ TM_UNM,
+ TM_LEN,
+ TM_LT,
+ TM_LE,
+ TM_CONCAT,
+ TM_CALL,
+ TM_N /* number of elements in the enum */
+} TMS;
+
+
+
+#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
+ ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
+
+#define fasttm(l,et,e) gfasttm(G(l), et, e)
+
+LUAI_DATA const char *const luaT_typenames[];
+
+
+LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
+LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
+ TMS event);
+LUAI_FUNC void luaT_init (lua_State *L);
+
+#endif
diff --git a/Build/source/libs/lua51/lua.c b/Build/source/libs/lua51/lua.c
new file mode 100644
index 00000000000..5cee7fa9f0b
--- /dev/null
+++ b/Build/source/libs/lua51/lua.c
@@ -0,0 +1,390 @@
+/*
+** $Id: lua.c,v 1.160 2006/06/02 15:34:00 roberto Exp $
+** Lua stand-alone interpreter
+** See Copyright Notice in lua.h
+*/
+
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lua_c
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+
+static lua_State *globalL = NULL;
+
+static const char *progname = LUA_PROGNAME;
+
+
+
+static void lstop (lua_State *L, lua_Debug *ar) {
+ (void)ar; /* unused arg. */
+ lua_sethook(L, NULL, 0, 0);
+ luaL_error(L, "interrupted!");
+}
+
+
+static void laction (int i) {
+ signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
+ terminate process (default action) */
+ lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
+}
+
+
+static void print_usage (void) {
+ fprintf(stderr,
+ "usage: %s [options] [script [args]].\n"
+ "Available options are:\n"
+ " -e stat execute string " LUA_QL("stat") "\n"
+ " -l name require library " LUA_QL("name") "\n"
+ " -i enter interactive mode after executing " LUA_QL("script") "\n"
+ " -v show version information\n"
+ " -- stop handling options\n"
+ " - execute stdin and stop handling options\n"
+ ,
+ progname);
+ fflush(stderr);
+}
+
+
+static void l_message (const char *pname, const char *msg) {
+ if (pname) fprintf(stderr, "%s: ", pname);
+ fprintf(stderr, "%s\n", msg);
+ fflush(stderr);
+}
+
+
+static int report (lua_State *L, int status) {
+ if (status && !lua_isnil(L, -1)) {
+ const char *msg = lua_tostring(L, -1);
+ if (msg == NULL) msg = "(error object is not a string)";
+ l_message(progname, msg);
+ lua_pop(L, 1);
+ }
+ return status;
+}
+
+
+static int traceback (lua_State *L) {
+ lua_getfield(L, LUA_GLOBALSINDEX, "debug");
+ if (!lua_istable(L, -1)) {
+ lua_pop(L, 1);
+ return 1;
+ }
+ lua_getfield(L, -1, "traceback");
+ if (!lua_isfunction(L, -1)) {
+ lua_pop(L, 2);
+ return 1;
+ }
+ lua_pushvalue(L, 1); /* pass error message */
+ lua_pushinteger(L, 2); /* skip this function and traceback */
+ lua_call(L, 2, 1); /* call debug.traceback */
+ return 1;
+}
+
+
+static int docall (lua_State *L, int narg, int clear) {
+ int status;
+ int base = lua_gettop(L) - narg; /* function index */
+ lua_pushcfunction(L, traceback); /* push traceback function */
+ lua_insert(L, base); /* put it under chunk and args */
+ signal(SIGINT, laction);
+ status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
+ signal(SIGINT, SIG_DFL);
+ lua_remove(L, base); /* remove traceback function */
+ /* force a complete garbage collection in case of errors */
+ if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
+ return status;
+}
+
+
+static void print_version (void) {
+ l_message(NULL, LUA_RELEASE " " LUA_COPYRIGHT);
+}
+
+
+static int getargs (lua_State *L, char **argv, int n) {
+ int narg;
+ int i;
+ int argc = 0;
+ while (argv[argc]) argc++; /* count total number of arguments */
+ narg = argc - (n + 1); /* number of arguments to the script */
+ luaL_checkstack(L, narg + 3, "too many arguments to script");
+ for (i=n+1; i < argc; i++)
+ lua_pushstring(L, argv[i]);
+ lua_createtable(L, narg, n + 1);
+ for (i=0; i < argc; i++) {
+ lua_pushstring(L, argv[i]);
+ lua_rawseti(L, -2, i - n);
+ }
+ return narg;
+}
+
+
+static int dofile (lua_State *L, const char *name) {
+ int status = luaL_loadfile(L, name) || docall(L, 0, 1);
+ return report(L, status);
+}
+
+
+static int dostring (lua_State *L, const char *s, const char *name) {
+ int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);
+ return report(L, status);
+}
+
+
+static int dolibrary (lua_State *L, const char *name) {
+ lua_getglobal(L, "require");
+ lua_pushstring(L, name);
+ return report(L, lua_pcall(L, 1, 0, 0));
+}
+
+
+static const char *get_prompt (lua_State *L, int firstline) {
+ const char *p;
+ lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
+ p = lua_tostring(L, -1);
+ if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
+ lua_pop(L, 1); /* remove global */
+ return p;
+}
+
+
+static int incomplete (lua_State *L, int status) {
+ if (status == LUA_ERRSYNTAX) {
+ size_t lmsg;
+ const char *msg = lua_tolstring(L, -1, &lmsg);
+ const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
+ if (strstr(msg, LUA_QL("<eof>")) == tp) {
+ lua_pop(L, 1);
+ return 1;
+ }
+ }
+ return 0; /* else... */
+}
+
+
+static int pushline (lua_State *L, int firstline) {
+ char buffer[LUA_MAXINPUT];
+ char *b = buffer;
+ size_t l;
+ const char *prmt = get_prompt(L, firstline);
+ if (lua_readline(L, b, prmt) == 0)
+ return 0; /* no input */
+ l = strlen(b);
+ if (l > 0 && b[l-1] == '\n') /* line ends with newline? */
+ b[l-1] = '\0'; /* remove it */
+ if (firstline && b[0] == '=') /* first line starts with `=' ? */
+ lua_pushfstring(L, "return %s", b+1); /* change it to `return' */
+ else
+ lua_pushstring(L, b);
+ lua_freeline(L, b);
+ return 1;
+}
+
+
+static int loadline (lua_State *L) {
+ int status;
+ lua_settop(L, 0);
+ if (!pushline(L, 1))
+ return -1; /* no input */
+ for (;;) { /* repeat until gets a complete line */
+ status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
+ if (!incomplete(L, status)) break; /* cannot try to add lines? */
+ if (!pushline(L, 0)) /* no more input? */
+ return -1;
+ lua_pushliteral(L, "\n"); /* add a new line... */
+ lua_insert(L, -2); /* ...between the two lines */
+ lua_concat(L, 3); /* join them */
+ }
+ lua_saveline(L, 1);
+ lua_remove(L, 1); /* remove line */
+ return status;
+}
+
+
+static void dotty (lua_State *L) {
+ int status;
+ const char *oldprogname = progname;
+ progname = NULL;
+ while ((status = loadline(L)) != -1) {
+ if (status == 0) status = docall(L, 0, 0);
+ report(L, status);
+ if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
+ lua_getglobal(L, "print");
+ lua_insert(L, 1);
+ if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
+ l_message(progname, lua_pushfstring(L,
+ "error calling " LUA_QL("print") " (%s)",
+ lua_tostring(L, -1)));
+ }
+ }
+ lua_settop(L, 0); /* clear stack */
+ fputs("\n", stdout);
+ fflush(stdout);
+ progname = oldprogname;
+}
+
+
+static int handle_script (lua_State *L, char **argv, int n) {
+ int status;
+ const char *fname;
+ int narg = getargs(L, argv, n); /* collect arguments */
+ lua_setglobal(L, "arg");
+ fname = argv[n];
+ if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0)
+ fname = NULL; /* stdin */
+ status = luaL_loadfile(L, fname);
+ lua_insert(L, -(narg+1));
+ if (status == 0)
+ status = docall(L, narg, 0);
+ else
+ lua_pop(L, narg);
+ return report(L, status);
+}
+
+
+/* check that argument has no extra characters at the end */
+#define notail(x) {if ((x)[2] != '\0') return -1;}
+
+
+static int collectargs (char **argv, int *pi, int *pv, int *pe) {
+ int i;
+ for (i = 1; argv[i] != NULL; i++) {
+ if (argv[i][0] != '-') /* not an option? */
+ return i;
+ switch (argv[i][1]) { /* option */
+ case '-':
+ notail(argv[i]);
+ return (argv[i+1] != NULL ? i+1 : 0);
+ case '\0':
+ return i;
+ case 'i':
+ notail(argv[i]);
+ *pi = 1; /* go through */
+ case 'v':
+ notail(argv[i]);
+ *pv = 1;
+ break;
+ case 'e':
+ *pe = 1; /* go through */
+ case 'l':
+ if (argv[i][2] == '\0') {
+ i++;
+ if (argv[i] == NULL) return -1;
+ }
+ break;
+ default: return -1; /* invalid option */
+ }
+ }
+ return 0;
+}
+
+
+static int runargs (lua_State *L, char **argv, int n) {
+ int i;
+ for (i = 1; i < n; i++) {
+ if (argv[i] == NULL) continue;
+ lua_assert(argv[i][0] == '-');
+ switch (argv[i][1]) { /* option */
+ case 'e': {
+ const char *chunk = argv[i] + 2;
+ if (*chunk == '\0') chunk = argv[++i];
+ lua_assert(chunk != NULL);
+ if (dostring(L, chunk, "=(command line)") != 0)
+ return 1;
+ break;
+ }
+ case 'l': {
+ const char *filename = argv[i] + 2;
+ if (*filename == '\0') filename = argv[++i];
+ lua_assert(filename != NULL);
+ if (dolibrary(L, filename))
+ return 1; /* stop if file fails */
+ break;
+ }
+ default: break;
+ }
+ }
+ return 0;
+}
+
+
+static int handle_luainit (lua_State *L) {
+ const char *init = getenv(LUA_INIT);
+ if (init == NULL) return 0; /* status OK */
+ else if (init[0] == '@')
+ return dofile(L, init+1);
+ else
+ return dostring(L, init, "=" LUA_INIT);
+}
+
+
+struct Smain {
+ int argc;
+ char **argv;
+ int status;
+};
+
+
+static int pmain (lua_State *L) {
+ struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
+ char **argv = s->argv;
+ int script;
+ int has_i = 0, has_v = 0, has_e = 0;
+ globalL = L;
+ if (argv[0] && argv[0][0]) progname = argv[0];
+ lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */
+ luaL_openlibs(L); /* open libraries */
+ lua_gc(L, LUA_GCRESTART, 0);
+ s->status = handle_luainit(L);
+ if (s->status != 0) return 0;
+ script = collectargs(argv, &has_i, &has_v, &has_e);
+ if (script < 0) { /* invalid args? */
+ print_usage();
+ s->status = 1;
+ return 0;
+ }
+ if (has_v) print_version();
+ s->status = runargs(L, argv, (script > 0) ? script : s->argc);
+ if (s->status != 0) return 0;
+ if (script)
+ s->status = handle_script(L, argv, script);
+ if (s->status != 0) return 0;
+ if (has_i)
+ dotty(L);
+ else if (script == 0 && !has_e && !has_v) {
+ if (lua_stdin_is_tty()) {
+ print_version();
+ dotty(L);
+ }
+ else dofile(L, NULL); /* executes stdin as a file */
+ }
+ return 0;
+}
+
+
+int main (int argc, char **argv) {
+ int status;
+ struct Smain s;
+ lua_State *L = lua_open(); /* create state */
+ if (L == NULL) {
+ l_message(argv[0], "cannot create state: not enough memory");
+ return EXIT_FAILURE;
+ }
+ s.argc = argc;
+ s.argv = argv;
+ status = lua_cpcall(L, &pmain, &s);
+ report(L, status);
+ lua_close(L);
+ return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
diff --git a/Build/source/libs/lua51/lua.h b/Build/source/libs/lua51/lua.h
new file mode 100644
index 00000000000..2865a7fae96
--- /dev/null
+++ b/Build/source/libs/lua51/lua.h
@@ -0,0 +1,385 @@
+/*
+** $Id: lua.h,v 1.218a 2006/06/02 15:34:00 roberto Exp $
+** Lua - An Extensible Extension Language
+** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
+** See Copyright Notice at the end of this file
+*/
+
+
+#ifndef lua_h
+#define lua_h
+
+#include <stdarg.h>
+#include <stddef.h>
+
+
+#include "luaconf.h"
+
+
+#define LUA_VERSION "Lua 5.1"
+#define LUA_RELEASE "Lua 5.1.2"
+#define LUA_VERSION_NUM 501
+#define LUA_COPYRIGHT "Copyright (C) 1994-2007 Lua.org, PUC-Rio"
+#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
+
+
+/* mark for precompiled code (`<esc>Lua') */
+#define LUA_SIGNATURE "\033Lua"
+
+/* option for multiple returns in `lua_pcall' and `lua_call' */
+#define LUA_MULTRET (-1)
+
+
+/*
+** pseudo-indices
+*/
+#define LUA_REGISTRYINDEX (-10000)
+#define LUA_ENVIRONINDEX (-10001)
+#define LUA_GLOBALSINDEX (-10002)
+#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
+
+
+/* thread status; 0 is OK */
+#define LUA_YIELD 1
+#define LUA_ERRRUN 2
+#define LUA_ERRSYNTAX 3
+#define LUA_ERRMEM 4
+#define LUA_ERRERR 5
+
+
+typedef struct lua_State lua_State;
+
+typedef int (*lua_CFunction) (lua_State *L);
+
+
+/*
+** functions that read/write blocks when loading/dumping Lua chunks
+*/
+typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
+
+typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
+
+
+/*
+** prototype for memory-allocation functions
+*/
+typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
+
+
+/*
+** basic types
+*/
+#define LUA_TNONE (-1)
+
+#define LUA_TNIL 0
+#define LUA_TBOOLEAN 1
+#define LUA_TLIGHTUSERDATA 2
+#define LUA_TNUMBER 3
+#define LUA_TSTRING 4
+#define LUA_TTABLE 5
+#define LUA_TFUNCTION 6
+#define LUA_TUSERDATA 7
+#define LUA_TTHREAD 8
+
+
+
+/* minimum Lua stack available to a C function */
+#define LUA_MINSTACK 20
+
+
+/*
+** generic extra include file
+*/
+#if defined(LUA_USER_H)
+#include LUA_USER_H
+#endif
+
+
+/* type of numbers in Lua */
+typedef LUA_NUMBER lua_Number;
+
+
+/* type for integer functions */
+typedef LUA_INTEGER lua_Integer;
+
+
+
+/*
+** state manipulation
+*/
+LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
+LUA_API void (lua_close) (lua_State *L);
+LUA_API lua_State *(lua_newthread) (lua_State *L);
+
+LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
+
+
+/*
+** basic stack manipulation
+*/
+LUA_API int (lua_gettop) (lua_State *L);
+LUA_API void (lua_settop) (lua_State *L, int idx);
+LUA_API void (lua_pushvalue) (lua_State *L, int idx);
+LUA_API void (lua_remove) (lua_State *L, int idx);
+LUA_API void (lua_insert) (lua_State *L, int idx);
+LUA_API void (lua_replace) (lua_State *L, int idx);
+LUA_API int (lua_checkstack) (lua_State *L, int sz);
+
+LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
+
+
+/*
+** access functions (stack -> C)
+*/
+
+LUA_API int (lua_isnumber) (lua_State *L, int idx);
+LUA_API int (lua_isstring) (lua_State *L, int idx);
+LUA_API int (lua_iscfunction) (lua_State *L, int idx);
+LUA_API int (lua_isuserdata) (lua_State *L, int idx);
+LUA_API int (lua_type) (lua_State *L, int idx);
+LUA_API const char *(lua_typename) (lua_State *L, int tp);
+
+LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2);
+LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
+LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2);
+
+LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx);
+LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx);
+LUA_API int (lua_toboolean) (lua_State *L, int idx);
+LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
+LUA_API size_t (lua_objlen) (lua_State *L, int idx);
+LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
+LUA_API void *(lua_touserdata) (lua_State *L, int idx);
+LUA_API lua_State *(lua_tothread) (lua_State *L, int idx);
+LUA_API const void *(lua_topointer) (lua_State *L, int idx);
+
+
+/*
+** push functions (C -> stack)
+*/
+LUA_API void (lua_pushnil) (lua_State *L);
+LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
+LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
+LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l);
+LUA_API void (lua_pushstring) (lua_State *L, const char *s);
+LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
+ va_list argp);
+LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
+LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
+LUA_API void (lua_pushboolean) (lua_State *L, int b);
+LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
+LUA_API int (lua_pushthread) (lua_State *L);
+
+
+/*
+** get functions (Lua -> stack)
+*/
+LUA_API void (lua_gettable) (lua_State *L, int idx);
+LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);
+LUA_API void (lua_rawget) (lua_State *L, int idx);
+LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
+LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
+LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
+LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
+LUA_API void (lua_getfenv) (lua_State *L, int idx);
+
+
+/*
+** set functions (stack -> Lua)
+*/
+LUA_API void (lua_settable) (lua_State *L, int idx);
+LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
+LUA_API void (lua_rawset) (lua_State *L, int idx);
+LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
+LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
+LUA_API int (lua_setfenv) (lua_State *L, int idx);
+
+
+/*
+** `load' and `call' functions (load and run Lua code)
+*/
+LUA_API void (lua_call) (lua_State *L, int nargs, int nresults);
+LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
+LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);
+LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
+ const char *chunkname);
+
+LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
+
+
+/*
+** coroutine functions
+*/
+LUA_API int (lua_yield) (lua_State *L, int nresults);
+LUA_API int (lua_resume) (lua_State *L, int narg);
+LUA_API int (lua_status) (lua_State *L);
+
+/*
+** garbage-collection function and options
+*/
+
+#define LUA_GCSTOP 0
+#define LUA_GCRESTART 1
+#define LUA_GCCOLLECT 2
+#define LUA_GCCOUNT 3
+#define LUA_GCCOUNTB 4
+#define LUA_GCSTEP 5
+#define LUA_GCSETPAUSE 6
+#define LUA_GCSETSTEPMUL 7
+
+LUA_API int (lua_gc) (lua_State *L, int what, int data);
+
+
+/*
+** miscellaneous functions
+*/
+
+LUA_API int (lua_error) (lua_State *L);
+
+LUA_API int (lua_next) (lua_State *L, int idx);
+
+LUA_API void (lua_concat) (lua_State *L, int n);
+
+LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
+LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
+
+
+
+/*
+** ===============================================================
+** some useful macros
+** ===============================================================
+*/
+
+#define lua_pop(L,n) lua_settop(L, -(n)-1)
+
+#define lua_newtable(L) lua_createtable(L, 0, 0)
+
+#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
+
+#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
+
+#define lua_strlen(L,i) lua_objlen(L, (i))
+
+#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
+#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
+#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
+#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
+#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
+#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
+#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
+#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
+
+#define lua_pushliteral(L, s) \
+ lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
+
+#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s))
+#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s))
+
+#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
+
+
+
+/*
+** compatibility macros and functions
+*/
+
+#define lua_open() luaL_newstate()
+
+#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
+
+#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0)
+
+#define lua_Chunkreader lua_Reader
+#define lua_Chunkwriter lua_Writer
+
+
+
+/*
+** {======================================================================
+** Debug API
+** =======================================================================
+*/
+
+
+/*
+** Event codes
+*/
+#define LUA_HOOKCALL 0
+#define LUA_HOOKRET 1
+#define LUA_HOOKLINE 2
+#define LUA_HOOKCOUNT 3
+#define LUA_HOOKTAILRET 4
+
+
+/*
+** Event masks
+*/
+#define LUA_MASKCALL (1 << LUA_HOOKCALL)
+#define LUA_MASKRET (1 << LUA_HOOKRET)
+#define LUA_MASKLINE (1 << LUA_HOOKLINE)
+#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
+
+typedef struct lua_Debug lua_Debug; /* activation record */
+
+
+/* Functions to be called by the debuger in specific events */
+typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
+
+
+LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
+LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
+LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
+LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
+LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);
+LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);
+
+LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
+LUA_API lua_Hook lua_gethook (lua_State *L);
+LUA_API int lua_gethookmask (lua_State *L);
+LUA_API int lua_gethookcount (lua_State *L);
+
+
+struct lua_Debug {
+ int event;
+ const char *name; /* (n) */
+ const char *namewhat; /* (n) `global', `local', `field', `method' */
+ const char *what; /* (S) `Lua', `C', `main', `tail' */
+ const char *source; /* (S) */
+ int currentline; /* (l) */
+ int nups; /* (u) number of upvalues */
+ int linedefined; /* (S) */
+ int lastlinedefined; /* (S) */
+ char short_src[LUA_IDSIZE]; /* (S) */
+ /* private part */
+ int i_ci; /* active function */
+};
+
+/* }====================================================================== */
+
+
+/******************************************************************************
+* Copyright (C) 1994-2007 Lua.org, PUC-Rio. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************/
+
+
+#endif
diff --git a/Build/source/libs/lua51/luac.c b/Build/source/libs/lua51/luac.c
new file mode 100644
index 00000000000..d07017391bf
--- /dev/null
+++ b/Build/source/libs/lua51/luac.c
@@ -0,0 +1,200 @@
+/*
+** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $
+** Lua compiler (saves bytecodes to files; also list bytecodes)
+** See Copyright Notice in lua.h
+*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define luac_c
+#define LUA_CORE
+
+#include "lua.h"
+#include "lauxlib.h"
+
+#include "ldo.h"
+#include "lfunc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lstring.h"
+#include "lundump.h"
+
+#define PROGNAME "luac" /* default program name */
+#define OUTPUT PROGNAME ".out" /* default output file */
+
+static int listing=0; /* list bytecodes? */
+static int dumping=1; /* dump bytecodes? */
+static int stripping=0; /* strip debug information? */
+static char Output[]={ OUTPUT }; /* default output file name */
+static const char* output=Output; /* actual output file name */
+static const char* progname=PROGNAME; /* actual program name */
+
+static void fatal(const char* message)
+{
+ fprintf(stderr,"%s: %s\n",progname,message);
+ exit(EXIT_FAILURE);
+}
+
+static void cannot(const char* what)
+{
+ fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno));
+ exit(EXIT_FAILURE);
+}
+
+static void usage(const char* message)
+{
+ if (*message=='-')
+ fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message);
+ else
+ fprintf(stderr,"%s: %s\n",progname,message);
+ fprintf(stderr,
+ "usage: %s [options] [filenames].\n"
+ "Available options are:\n"
+ " - process stdin\n"
+ " -l list\n"
+ " -o name output to file " LUA_QL("name") " (default is \"%s\")\n"
+ " -p parse only\n"
+ " -s strip debug information\n"
+ " -v show version information\n"
+ " -- stop handling options\n",
+ progname,Output);
+ exit(EXIT_FAILURE);
+}
+
+#define IS(s) (strcmp(argv[i],s)==0)
+
+static int doargs(int argc, char* argv[])
+{
+ int i;
+ int version=0;
+ if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0];
+ for (i=1; i<argc; i++)
+ {
+ if (*argv[i]!='-') /* end of options; keep it */
+ break;
+ else if (IS("--")) /* end of options; skip it */
+ {
+ ++i;
+ if (version) ++version;
+ break;
+ }
+ else if (IS("-")) /* end of options; use stdin */
+ break;
+ else if (IS("-l")) /* list */
+ ++listing;
+ else if (IS("-o")) /* output file */
+ {
+ output=argv[++i];
+ if (output==NULL || *output==0) usage(LUA_QL("-o") " needs argument");
+ if (IS("-")) output=NULL;
+ }
+ else if (IS("-p")) /* parse only */
+ dumping=0;
+ else if (IS("-s")) /* strip debug information */
+ stripping=1;
+ else if (IS("-v")) /* show version */
+ ++version;
+ else /* unknown option */
+ usage(argv[i]);
+ }
+ if (i==argc && (listing || !dumping))
+ {
+ dumping=0;
+ argv[--i]=Output;
+ }
+ if (version)
+ {
+ printf("%s %s\n",LUA_RELEASE,LUA_COPYRIGHT);
+ if (version==argc-1) exit(EXIT_SUCCESS);
+ }
+ return i;
+}
+
+#define toproto(L,i) (clvalue(L->top+(i))->l.p)
+
+static const Proto* combine(lua_State* L, int n)
+{
+ if (n==1)
+ return toproto(L,-1);
+ else
+ {
+ int i,pc;
+ Proto* f=luaF_newproto(L);
+ setptvalue2s(L,L->top,f); incr_top(L);
+ f->source=luaS_newliteral(L,"=(" PROGNAME ")");
+ f->maxstacksize=1;
+ pc=2*n+1;
+ f->code=luaM_newvector(L,pc,Instruction);
+ f->sizecode=pc;
+ f->p=luaM_newvector(L,n,Proto*);
+ f->sizep=n;
+ pc=0;
+ for (i=0; i<n; i++)
+ {
+ f->p[i]=toproto(L,i-n-1);
+ f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i);
+ f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1);
+ }
+ f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0);
+ return f;
+ }
+}
+
+static int writer(lua_State* L, const void* p, size_t size, void* u)
+{
+ UNUSED(L);
+ return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);
+}
+
+struct Smain {
+ int argc;
+ char** argv;
+};
+
+static int pmain(lua_State* L)
+{
+ struct Smain* s = (struct Smain*)lua_touserdata(L, 1);
+ int argc=s->argc;
+ char** argv=s->argv;
+ const Proto* f;
+ int i;
+ if (!lua_checkstack(L,argc)) fatal("too many input files");
+ for (i=0; i<argc; i++)
+ {
+ const char* filename=IS("-") ? NULL : argv[i];
+ if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1));
+ }
+ f=combine(L,argc);
+ if (listing) luaU_print(f,listing>1);
+ if (dumping)
+ {
+ FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
+ if (D==NULL) cannot("open");
+ lua_lock(L);
+ luaU_dump(L,f,writer,D,stripping);
+ lua_unlock(L);
+ if (ferror(D)) cannot("write");
+ if (fclose(D)) cannot("close");
+ }
+ return 0;
+}
+
+int main(int argc, char* argv[])
+{
+ lua_State* L;
+ struct Smain s;
+ int i=doargs(argc,argv);
+ argc-=i; argv+=i;
+ if (argc<=0) usage("no input files given");
+ L=lua_open();
+ if (L==NULL) fatal("not enough memory for state");
+ s.argc=argc;
+ s.argv=argv;
+ if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1));
+ lua_close(L);
+ return EXIT_SUCCESS;
+}
diff --git a/Build/source/libs/lua51/luaconf.h b/Build/source/libs/lua51/luaconf.h
new file mode 100644
index 00000000000..11b002ca925
--- /dev/null
+++ b/Build/source/libs/lua51/luaconf.h
@@ -0,0 +1,770 @@
+/*
+** $Id: luaconf.h,v 1.82 2006/04/10 18:27:23 roberto Exp $
+** Configuration file for Lua
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lconfig_h
+#define lconfig_h
+
+#include <limits.h>
+#include <stddef.h>
+
+
+/*
+** ==================================================================
+** Search for "@@" to find all configurable definitions.
+** ===================================================================
+*/
+
+
+/*
+@@ LUA_ANSI controls the use of non-ansi features.
+** CHANGE it (define it) if you want Lua to avoid the use of any
+** non-ansi feature or library.
+*/
+#if defined(__STRICT_ANSI__)
+#define LUA_ANSI
+#endif
+
+
+#if !defined(LUA_ANSI) && defined(_WIN32)
+#define LUA_WIN
+#endif
+
+#if defined(LUA_USE_LINUX)
+#define LUA_USE_POSIX
+#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
+#define LUA_USE_READLINE /* needs some extra libraries */
+#endif
+
+#if defined(LUA_USE_MACOSX)
+#define LUA_USE_POSIX
+#define LUA_DL_DYLD /* does not need extra library */
+#endif
+
+
+
+/*
+@@ LUA_USE_POSIX includes all functionallity listed as X/Open System
+@* Interfaces Extension (XSI).
+** CHANGE it (define it) if your system is XSI compatible.
+*/
+#if defined(LUA_USE_POSIX)
+#define LUA_USE_MKSTEMP
+#define LUA_USE_ISATTY
+#define LUA_USE_POPEN
+#define LUA_USE_ULONGJMP
+#endif
+
+
+/*
+@@ LUA_PATH and LUA_CPATH are the names of the environment variables that
+@* Lua check to set its paths.
+@@ LUA_INIT is the name of the environment variable that Lua
+@* checks for initialization code.
+** CHANGE them if you want different names.
+*/
+#define LUA_PATH "LUA_PATH"
+#define LUA_CPATH "LUA_CPATH"
+#define LUA_INIT "LUA_INIT"
+
+
+/*
+@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
+@* Lua libraries.
+@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for
+@* C libraries.
+** CHANGE them if your machine has a non-conventional directory
+** hierarchy or if you want to install your libraries in
+** non-conventional directories.
+*/
+#if defined(_WIN32)
+/*
+** In Windows, any exclamation mark ('!') in the path is replaced by the
+** path of the directory of the executable file of the current process.
+*/
+#define LUA_LDIR "!\\lua\\"
+#define LUA_CDIR "!\\"
+#define LUA_PATH_DEFAULT \
+ ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
+ LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua"
+#define LUA_CPATH_DEFAULT \
+ ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
+
+#else
+#define LUA_ROOT "/usr/local/"
+#define LUA_LDIR LUA_ROOT "share/lua/5.1/"
+#define LUA_CDIR LUA_ROOT "lib/lua/5.1/"
+#define LUA_PATH_DEFAULT \
+ "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
+ LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua"
+#define LUA_CPATH_DEFAULT \
+ "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so"
+#endif
+
+
+/*
+@@ LUA_DIRSEP is the directory separator (for submodules).
+** CHANGE it if your machine does not use "/" as the directory separator
+** and is not Windows. (On Windows Lua automatically uses "\".)
+*/
+#if defined(_WIN32)
+#define LUA_DIRSEP "\\"
+#else
+#define LUA_DIRSEP "/"
+#endif
+
+
+/*
+@@ LUA_PATHSEP is the character that separates templates in a path.
+@@ LUA_PATH_MARK is the string that marks the substitution points in a
+@* template.
+@@ LUA_EXECDIR in a Windows path is replaced by the executable's
+@* directory.
+@@ LUA_IGMARK is a mark to ignore all before it when bulding the
+@* luaopen_ function name.
+** CHANGE them if for some reason your system cannot use those
+** characters. (E.g., if one of those characters is a common character
+** in file/directory names.) Probably you do not need to change them.
+*/
+#define LUA_PATHSEP ";"
+#define LUA_PATH_MARK "?"
+#define LUA_EXECDIR "!"
+#define LUA_IGMARK "-"
+
+
+/*
+@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
+** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
+** machines, ptrdiff_t gives a good choice between int or long.)
+*/
+#define LUA_INTEGER ptrdiff_t
+
+
+/*
+@@ LUA_API is a mark for all core API functions.
+@@ LUALIB_API is a mark for all standard library functions.
+** CHANGE them if you need to define those functions in some special way.
+** For instance, if you want to create one Windows DLL with the core and
+** the libraries, you may want to use the following definition (define
+** LUA_BUILD_AS_DLL to get it).
+*/
+#if defined(LUA_BUILD_AS_DLL)
+
+#if defined(LUA_CORE) || defined(LUA_LIB)
+#define LUA_API __declspec(dllexport)
+#else
+#define LUA_API __declspec(dllimport)
+#endif
+
+#else
+
+#define LUA_API extern
+
+#endif
+
+/* more often than not the libs go together with the core */
+#define LUALIB_API LUA_API
+
+
+/*
+@@ LUAI_FUNC is a mark for all extern functions that are not to be
+@* exported to outside modules.
+@@ LUAI_DATA is a mark for all extern (const) variables that are not to
+@* be exported to outside modules.
+** CHANGE them if you need to mark them in some special way. Elf/gcc
+** (versions 3.2 and later) mark them as "hidden" to optimize access
+** when Lua is compiled as a shared library.
+*/
+#if defined(luaall_c)
+#define LUAI_FUNC static
+#define LUAI_DATA /* empty */
+
+#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
+ defined(__ELF__)
+#define LUAI_FUNC __attribute__((visibility("hidden"))) extern
+#define LUAI_DATA LUAI_FUNC
+
+#else
+#define LUAI_FUNC extern
+#define LUAI_DATA extern
+#endif
+
+
+
+/*
+@@ LUA_QL describes how error messages quote program elements.
+** CHANGE it if you want a different appearance.
+*/
+#define LUA_QL(x) "'" x "'"
+#define LUA_QS LUA_QL("%s")
+
+
+/*
+@@ LUA_IDSIZE gives the maximum size for the description of the source
+@* of a function in debug information.
+** CHANGE it if you want a different size.
+*/
+#define LUA_IDSIZE 60
+
+
+/*
+** {==================================================================
+** Stand-alone configuration
+** ===================================================================
+*/
+
+#if defined(lua_c) || defined(luaall_c)
+
+/*
+@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that
+@* is, whether we're running lua interactively).
+** CHANGE it if you have a better definition for non-POSIX/non-Windows
+** systems.
+*/
+#if defined(LUA_USE_ISATTY)
+#include <unistd.h>
+#define lua_stdin_is_tty() isatty(0)
+#elif defined(LUA_WIN)
+#include <io.h>
+#include <stdio.h>
+#define lua_stdin_is_tty() _isatty(_fileno(stdin))
+#else
+#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
+#endif
+
+
+/*
+@@ LUA_PROMPT is the default prompt used by stand-alone Lua.
+@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua.
+** CHANGE them if you want different prompts. (You can also change the
+** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.)
+*/
+#define LUA_PROMPT "> "
+#define LUA_PROMPT2 ">> "
+
+
+/*
+@@ LUA_PROGNAME is the default name for the stand-alone Lua program.
+** CHANGE it if your stand-alone interpreter has a different name and
+** your system is not able to detect that name automatically.
+*/
+#define LUA_PROGNAME "lua"
+
+
+/*
+@@ LUA_MAXINPUT is the maximum length for an input line in the
+@* stand-alone interpreter.
+** CHANGE it if you need longer lines.
+*/
+#define LUA_MAXINPUT 512
+
+
+/*
+@@ lua_readline defines how to show a prompt and then read a line from
+@* the standard input.
+@@ lua_saveline defines how to "save" a read line in a "history".
+@@ lua_freeline defines how to free a line read by lua_readline.
+** CHANGE them if you want to improve this functionality (e.g., by using
+** GNU readline and history facilities).
+*/
+#if defined(LUA_USE_READLINE)
+#include <stdio.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
+#define lua_saveline(L,idx) \
+ if (lua_strlen(L,idx) > 0) /* non-empty line? */ \
+ add_history(lua_tostring(L, idx)); /* add it to history */
+#define lua_freeline(L,b) ((void)L, free(b))
+#else
+#define lua_readline(L,b,p) \
+ ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
+ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
+#define lua_saveline(L,idx) { (void)L; (void)idx; }
+#define lua_freeline(L,b) { (void)L; (void)b; }
+#endif
+
+#endif
+
+/* }================================================================== */
+
+
+/*
+@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles
+@* as a percentage.
+** CHANGE it if you want the GC to run faster or slower (higher values
+** mean larger pauses which mean slower collection.) You can also change
+** this value dynamically.
+*/
+#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */
+
+
+/*
+@@ LUAI_GCMUL defines the default speed of garbage collection relative to
+@* memory allocation as a percentage.
+** CHANGE it if you want to change the granularity of the garbage
+** collection. (Higher values mean coarser collections. 0 represents
+** infinity, where each step performs a full collection.) You can also
+** change this value dynamically.
+*/
+#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */
+
+
+
+/*
+@@ LUA_COMPAT_GETN controls compatibility with old getn behavior.
+** CHANGE it (define it) if you want exact compatibility with the
+** behavior of setn/getn in Lua 5.0.
+*/
+#undef LUA_COMPAT_GETN
+
+/*
+@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib.
+** CHANGE it to undefined as soon as you do not need a global 'loadlib'
+** function (the function is still available as 'package.loadlib').
+*/
+#undef LUA_COMPAT_LOADLIB
+
+/*
+@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature.
+** CHANGE it to undefined as soon as your programs use only '...' to
+** access vararg parameters (instead of the old 'arg' table).
+*/
+#define LUA_COMPAT_VARARG
+
+/*
+@@ LUA_COMPAT_MOD controls compatibility with old math.mod function.
+** CHANGE it to undefined as soon as your programs use 'math.fmod' or
+** the new '%' operator instead of 'math.mod'.
+*/
+#define LUA_COMPAT_MOD
+
+/*
+@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting
+@* facility.
+** CHANGE it to 2 if you want the old behaviour, or undefine it to turn
+** off the advisory error when nesting [[...]].
+*/
+#define LUA_COMPAT_LSTR 1
+
+/*
+@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name.
+** CHANGE it to undefined as soon as you rename 'string.gfind' to
+** 'string.gmatch'.
+*/
+#define LUA_COMPAT_GFIND
+
+/*
+@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib'
+@* behavior.
+** CHANGE it to undefined as soon as you replace to 'luaL_register'
+** your uses of 'luaL_openlib'
+*/
+#define LUA_COMPAT_OPENLIB
+
+
+
+/*
+@@ luai_apicheck is the assert macro used by the Lua-C API.
+** CHANGE luai_apicheck if you want Lua to perform some checks in the
+** parameters it gets from API calls. This may slow down the interpreter
+** a bit, but may be quite useful when debugging C code that interfaces
+** with Lua. A useful redefinition is to use assert.h.
+*/
+#if defined(LUA_USE_APICHECK)
+#include <assert.h>
+#define luai_apicheck(L,o) { (void)L; assert(o); }
+#else
+#define luai_apicheck(L,o) { (void)L; }
+#endif
+
+
+/*
+@@ LUAI_BITSINT defines the number of bits in an int.
+** CHANGE here if Lua cannot automatically detect the number of bits of
+** your machine. Probably you do not need to change this.
+*/
+/* avoid overflows in comparison */
+#if INT_MAX-20 < 32760
+#define LUAI_BITSINT 16
+#elif INT_MAX > 2147483640L
+/* int has at least 32 bits */
+#define LUAI_BITSINT 32
+#else
+#error "you must define LUA_BITSINT with number of bits in an integer"
+#endif
+
+
+/*
+@@ LUAI_UINT32 is an unsigned integer with at least 32 bits.
+@@ LUAI_INT32 is an signed integer with at least 32 bits.
+@@ LUAI_UMEM is an unsigned integer big enough to count the total
+@* memory used by Lua.
+@@ LUAI_MEM is a signed integer big enough to count the total memory
+@* used by Lua.
+** CHANGE here if for some weird reason the default definitions are not
+** good enough for your machine. (The definitions in the 'else'
+** part always works, but may waste space on machines with 64-bit
+** longs.) Probably you do not need to change this.
+*/
+#if LUAI_BITSINT >= 32
+#define LUAI_UINT32 unsigned int
+#define LUAI_INT32 int
+#define LUAI_MAXINT32 INT_MAX
+#define LUAI_UMEM size_t
+#define LUAI_MEM ptrdiff_t
+#else
+/* 16-bit ints */
+#define LUAI_UINT32 unsigned long
+#define LUAI_INT32 long
+#define LUAI_MAXINT32 LONG_MAX
+#define LUAI_UMEM unsigned long
+#define LUAI_MEM long
+#endif
+
+
+/*
+@@ LUAI_MAXCALLS limits the number of nested calls.
+** CHANGE it if you need really deep recursive calls. This limit is
+** arbitrary; its only purpose is to stop infinite recursion before
+** exhausting memory.
+*/
+#define LUAI_MAXCALLS 20000
+
+
+/*
+@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function
+@* can use.
+** CHANGE it if you need lots of (Lua) stack space for your C
+** functions. This limit is arbitrary; its only purpose is to stop C
+** functions to consume unlimited stack space.
+*/
+#define LUAI_MAXCSTACK 2048
+
+
+
+/*
+** {==================================================================
+** CHANGE (to smaller values) the following definitions if your system
+** has a small C stack. (Or you may want to change them to larger
+** values if your system has a large C stack and these limits are
+** too rigid for you.) Some of these constants control the size of
+** stack-allocated arrays used by the compiler or the interpreter, while
+** others limit the maximum number of recursive calls that the compiler
+** or the interpreter can perform. Values too large may cause a C stack
+** overflow for some forms of deep constructs.
+** ===================================================================
+*/
+
+
+/*
+@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and
+@* syntactical nested non-terminals in a program.
+*/
+#define LUAI_MAXCCALLS 2000
+
+
+/*
+@@ LUAI_MAXVARS is the maximum number of local variables per function
+@* (must be smaller than 250).
+*/
+#define LUAI_MAXVARS 200
+
+
+/*
+@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function
+@* (must be smaller than 250).
+*/
+#define LUAI_MAXUPVALUES 60
+
+
+/*
+@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
+*/
+#define LUAL_BUFFERSIZE BUFSIZ
+
+/* }================================================================== */
+
+
+
+
+/*
+** {==================================================================
+@@ LUA_NUMBER is the type of numbers in Lua.
+** CHANGE the following definitions only if you want to build Lua
+** with a number type different from double. You may also need to
+** change lua_number2int & lua_number2integer.
+** ===================================================================
+*/
+
+#define LUA_NUMBER_DOUBLE
+#define LUA_NUMBER double
+
+/*
+@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
+@* over a number.
+*/
+#define LUAI_UACNUMBER double
+
+
+/*
+@@ LUA_NUMBER_SCAN is the format for reading numbers.
+@@ LUA_NUMBER_FMT is the format for writing numbers.
+@@ lua_number2str converts a number to a string.
+@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
+@@ lua_str2number converts a string to a number.
+*/
+#define LUA_NUMBER_SCAN "%lf"
+#define LUA_NUMBER_FMT "%.14g"
+
+#define lua_number2str(s,n) if (((n)<0.000001) && ((n)>-0.000001)) \
+ sprintf((s), "0"); else if (((n)<0.0001) && ((n)>-0.0001)) { \
+ sprintf((s), "%.6f", (n)); \
+ if (n>0) { if (s[7] == '0') { s[7] = 0; } } \
+ else { if (s[8] == '0') { s[8] = 0; } } \
+ } else sprintf((s), LUA_NUMBER_FMT, (n));
+
+
+#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
+#define lua_str2number(s,p) strtod((s), (p))
+
+
+/*
+@@ The luai_num* macros define the primitive operations over numbers.
+*/
+#if defined(LUA_CORE)
+#include <math.h>
+#define luai_numadd(a,b) ((a)+(b))
+#define luai_numsub(a,b) ((a)-(b))
+#define luai_nummul(a,b) ((a)*(b))
+#define luai_numdiv(a,b) ((a)/(b))
+#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b))
+#define luai_numpow(a,b) (pow(a,b))
+#define luai_numunm(a) (-(a))
+#define luai_numeq(a,b) ((a)==(b))
+#define luai_numlt(a,b) ((a)<(b))
+#define luai_numle(a,b) ((a)<=(b))
+#define luai_numisnan(a) (!luai_numeq((a), (a)))
+#endif
+
+
+/*
+@@ lua_number2int is a macro to convert lua_Number to int.
+@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
+** CHANGE them if you know a faster way to convert a lua_Number to
+** int (with any rounding method and without throwing errors) in your
+** system. In Pentium machines, a naive typecast from double to int
+** in C is extremely slow, so any alternative is worth trying.
+*/
+
+/* On a Pentium, resort to a trick */
+#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
+ (defined(__i386) || defined (_M_IX86) || defined(__i386__))
+
+/* On a Microsoft compiler, use assembler */
+#if defined(_MSC_VER)
+
+#define lua_number2int(i,d) __asm fld d __asm fistp i
+#define lua_number2integer(i,n) lua_number2int(i, n)
+
+/* the next trick should work on any Pentium, but sometimes clashes
+ with a DirectX idiosyncrasy */
+#else
+
+union luai_Cast { double l_d; long l_l; };
+#define lua_number2int(i,d) \
+ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
+#define lua_number2integer(i,n) lua_number2int(i, n)
+
+#endif
+
+
+/* this option always works, but may be slow */
+#else
+#define lua_number2int(i,d) ((i)=(int)(d))
+#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
+
+#endif
+
+/* }================================================================== */
+
+
+/*
+@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment.
+** CHANGE it if your system requires alignments larger than double. (For
+** instance, if your system supports long doubles and they must be
+** aligned in 16-byte boundaries, then you should add long double in the
+** union.) Probably you do not need to change this.
+*/
+#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; }
+
+
+/*
+@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling.
+** CHANGE them if you prefer to use longjmp/setjmp even with C++
+** or if want/don't to use _longjmp/_setjmp instead of regular
+** longjmp/setjmp. By default, Lua handles errors with exceptions when
+** compiling as C++ code, with _longjmp/_setjmp when asked to use them,
+** and with longjmp/setjmp otherwise.
+*/
+#if defined(__cplusplus)
+/* C++ exceptions */
+#define LUAI_THROW(L,c) throw(c)
+#define LUAI_TRY(L,c,a) try { a } catch(...) \
+ { if ((c)->status == 0) (c)->status = -1; }
+#define luai_jmpbuf int /* dummy variable */
+
+#elif defined(LUA_USE_ULONGJMP)
+/* in Unix, try _longjmp/_setjmp (more efficient) */
+#define LUAI_THROW(L,c) _longjmp((c)->b, 1)
+#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a }
+#define luai_jmpbuf jmp_buf
+
+#else
+/* default handling with long jumps */
+#define LUAI_THROW(L,c) longjmp((c)->b, 1)
+#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a }
+#define luai_jmpbuf jmp_buf
+
+#endif
+
+
+/*
+@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern
+@* can do during pattern-matching.
+** CHANGE it if you need more captures. This limit is arbitrary.
+*/
+#define LUA_MAXCAPTURES 32
+
+
+/*
+@@ lua_tmpnam is the function that the OS library uses to create a
+@* temporary name.
+@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam.
+** CHANGE them if you have an alternative to tmpnam (which is considered
+** insecure) or if you want the original tmpnam anyway. By default, Lua
+** uses tmpnam except when POSIX is available, where it uses mkstemp.
+*/
+#if defined(loslib_c) || defined(luaall_c)
+
+#if defined(LUA_USE_MKSTEMP)
+#include <unistd.h>
+#define LUA_TMPNAMBUFSIZE 32
+#define lua_tmpnam(b,e) { \
+ strcpy(b, "/tmp/lua_XXXXXX"); \
+ e = mkstemp(b); \
+ if (e != -1) close(e); \
+ e = (e == -1); }
+
+#else
+#define LUA_TMPNAMBUFSIZE L_tmpnam
+#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
+#endif
+
+#endif
+
+
+/*
+@@ lua_popen spawns a new process connected to the current one through
+@* the file streams.
+** CHANGE it if you have a way to implement it in your system.
+*/
+#if defined(LUA_USE_POPEN)
+
+#define lua_popen(L,c,m) ((void)L, popen(c,m))
+#define lua_pclose(L,file) ((void)L, (pclose(file) != -1))
+
+#elif defined(LUA_WIN)
+
+#define lua_popen(L,c,m) ((void)L, _popen(c,m))
+#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1))
+
+#else
+
+#define lua_popen(L,c,m) ((void)((void)c, m), \
+ luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0)
+#define lua_pclose(L,file) ((void)((void)L, file), 0)
+
+#endif
+
+/*
+@@ LUA_DL_* define which dynamic-library system Lua should use.
+** CHANGE here if Lua has problems choosing the appropriate
+** dynamic-library system for your platform (either Windows' DLL, Mac's
+** dyld, or Unix's dlopen). If your system is some kind of Unix, there
+** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for
+** it. To use dlopen you also need to adapt the src/Makefile (probably
+** adding -ldl to the linker options), so Lua does not select it
+** automatically. (When you change the makefile to add -ldl, you must
+** also add -DLUA_USE_DLOPEN.)
+** If you do not want any kind of dynamic library, undefine all these
+** options.
+** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD.
+*/
+#if defined(LUA_USE_DLOPEN)
+#define LUA_DL_DLOPEN
+#endif
+
+#if defined(LUA_WIN)
+#define LUA_DL_DLL
+#endif
+
+
+/*
+@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State
+@* (the data goes just *before* the lua_State pointer).
+** CHANGE (define) this if you really need that. This value must be
+** a multiple of the maximum alignment required for your machine.
+*/
+#define LUAI_EXTRASPACE 0
+
+
+/*
+@@ luai_userstate* allow user-specific actions on threads.
+** CHANGE them if you defined LUAI_EXTRASPACE and need to do something
+** extra when a thread is created/deleted/resumed/yielded.
+*/
+#define luai_userstateopen(L) ((void)L)
+#define luai_userstateclose(L) ((void)L)
+#define luai_userstatethread(L,L1) ((void)L)
+#define luai_userstatefree(L) ((void)L)
+#define luai_userstateresume(L,n) ((void)L)
+#define luai_userstateyield(L,n) ((void)L)
+
+
+/*
+@@ LUA_INTFRMLEN is the length modifier for integer conversions
+@* in 'string.format'.
+@@ LUA_INTFRM_T is the integer type correspoding to the previous length
+@* modifier.
+** CHANGE them if your system supports long long or does not support long.
+*/
+
+#if defined(LUA_USELONGLONG)
+
+#define LUA_INTFRMLEN "ll"
+#define LUA_INTFRM_T long long
+
+#else
+
+#define LUA_INTFRMLEN "l"
+#define LUA_INTFRM_T long
+
+#endif
+
+
+
+/* =================================================================== */
+
+/*
+** Local configuration. You can use this space to add your redefinitions
+** without modifying the main part of the file.
+*/
+
+
+
+#endif
+
diff --git a/Build/source/libs/lua51/lualib.h b/Build/source/libs/lua51/lualib.h
new file mode 100644
index 00000000000..0c76232c0dd
--- /dev/null
+++ b/Build/source/libs/lua51/lualib.h
@@ -0,0 +1,53 @@
+/*
+** $Id: lualib.h,v 1.36 2005/12/27 17:12:00 roberto Exp $
+** Lua standard libraries
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lualib_h
+#define lualib_h
+
+#include "lua.h"
+
+
+/* Key to file-handle type */
+#define LUA_FILEHANDLE "FILE*"
+
+
+#define LUA_COLIBNAME "coroutine"
+LUALIB_API int (luaopen_base) (lua_State *L);
+
+#define LUA_TABLIBNAME "table"
+LUALIB_API int (luaopen_table) (lua_State *L);
+
+#define LUA_IOLIBNAME "io"
+LUALIB_API int (luaopen_io) (lua_State *L);
+
+#define LUA_OSLIBNAME "os"
+LUALIB_API int (luaopen_os) (lua_State *L);
+
+#define LUA_STRLIBNAME "string"
+LUALIB_API int (luaopen_string) (lua_State *L);
+
+#define LUA_MATHLIBNAME "math"
+LUALIB_API int (luaopen_math) (lua_State *L);
+
+#define LUA_DBLIBNAME "debug"
+LUALIB_API int (luaopen_debug) (lua_State *L);
+
+#define LUA_LOADLIBNAME "package"
+LUALIB_API int (luaopen_package) (lua_State *L);
+
+
+/* open all previous libraries */
+LUALIB_API void (luaL_openlibs) (lua_State *L);
+
+
+
+#ifndef lua_assert
+#define lua_assert(x) ((void)0)
+#endif
+
+
+#endif
diff --git a/Build/source/libs/lua51/lundump.c b/Build/source/libs/lua51/lundump.c
new file mode 100644
index 00000000000..7fc635eeb7b
--- /dev/null
+++ b/Build/source/libs/lua51/lundump.c
@@ -0,0 +1,223 @@
+/*
+** $Id: lundump.c,v 1.60 2006/02/16 15:53:49 lhf Exp $
+** load precompiled Lua chunks
+** See Copyright Notice in lua.h
+*/
+
+#include <string.h>
+
+#define lundump_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstring.h"
+#include "lundump.h"
+#include "lzio.h"
+
+typedef struct {
+ lua_State* L;
+ ZIO* Z;
+ Mbuffer* b;
+ const char* name;
+} LoadState;
+
+#ifdef LUAC_TRUST_BINARIES
+#define IF(c,s)
+#else
+#define IF(c,s) if (c) error(S,s)
+
+static void error(LoadState* S, const char* why)
+{
+ luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why);
+ luaD_throw(S->L,LUA_ERRSYNTAX);
+}
+#endif
+
+#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
+#define LoadByte(S) (lu_byte)LoadChar(S)
+#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
+#define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
+
+static void LoadBlock(LoadState* S, void* b, size_t size)
+{
+ size_t r=luaZ_read(S->Z,b,size);
+ IF (r!=0, "unexpected end");
+}
+
+static int LoadChar(LoadState* S)
+{
+ char x;
+ LoadVar(S,x);
+ return x;
+}
+
+static int LoadInt(LoadState* S)
+{
+ int x;
+ LoadVar(S,x);
+ IF (x<0, "bad integer");
+ return x;
+}
+
+static lua_Number LoadNumber(LoadState* S)
+{
+ lua_Number x;
+ LoadVar(S,x);
+ return x;
+}
+
+static TString* LoadString(LoadState* S)
+{
+ size_t size;
+ LoadVar(S,size);
+ if (size==0)
+ return NULL;
+ else
+ {
+ char* s=luaZ_openspace(S->L,S->b,size);
+ LoadBlock(S,s,size);
+ return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
+ }
+}
+
+static void LoadCode(LoadState* S, Proto* f)
+{
+ int n=LoadInt(S);
+ f->code=luaM_newvector(S->L,n,Instruction);
+ f->sizecode=n;
+ LoadVector(S,f->code,n,sizeof(Instruction));
+}
+
+static Proto* LoadFunction(LoadState* S, TString* p);
+
+static void LoadConstants(LoadState* S, Proto* f)
+{
+ int i,n;
+ n=LoadInt(S);
+ f->k=luaM_newvector(S->L,n,TValue);
+ f->sizek=n;
+ for (i=0; i<n; i++) setnilvalue(&f->k[i]);
+ for (i=0; i<n; i++)
+ {
+ TValue* o=&f->k[i];
+ int t=LoadChar(S);
+ switch (t)
+ {
+ case LUA_TNIL:
+ setnilvalue(o);
+ break;
+ case LUA_TBOOLEAN:
+ setbvalue(o,LoadChar(S));
+ break;
+ case LUA_TNUMBER:
+ setnvalue(o,LoadNumber(S));
+ break;
+ case LUA_TSTRING:
+ setsvalue2n(S->L,o,LoadString(S));
+ break;
+ default:
+ IF (1, "bad constant");
+ break;
+ }
+ }
+ n=LoadInt(S);
+ f->p=luaM_newvector(S->L,n,Proto*);
+ f->sizep=n;
+ for (i=0; i<n; i++) f->p[i]=NULL;
+ for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
+}
+
+static void LoadDebug(LoadState* S, Proto* f)
+{
+ int i,n;
+ n=LoadInt(S);
+ f->lineinfo=luaM_newvector(S->L,n,int);
+ f->sizelineinfo=n;
+ LoadVector(S,f->lineinfo,n,sizeof(int));
+ n=LoadInt(S);
+ f->locvars=luaM_newvector(S->L,n,LocVar);
+ f->sizelocvars=n;
+ for (i=0; i<n; i++) f->locvars[i].varname=NULL;
+ for (i=0; i<n; i++)
+ {
+ f->locvars[i].varname=LoadString(S);
+ f->locvars[i].startpc=LoadInt(S);
+ f->locvars[i].endpc=LoadInt(S);
+ }
+ n=LoadInt(S);
+ f->upvalues=luaM_newvector(S->L,n,TString*);
+ f->sizeupvalues=n;
+ for (i=0; i<n; i++) f->upvalues[i]=NULL;
+ for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
+}
+
+static Proto* LoadFunction(LoadState* S, TString* p)
+{
+ Proto* f=luaF_newproto(S->L);
+ setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
+ f->source=LoadString(S); if (f->source==NULL) f->source=p;
+ f->linedefined=LoadInt(S);
+ f->lastlinedefined=LoadInt(S);
+ f->nups=LoadByte(S);
+ f->numparams=LoadByte(S);
+ f->is_vararg=LoadByte(S);
+ f->maxstacksize=LoadByte(S);
+ LoadCode(S,f);
+ LoadConstants(S,f);
+ LoadDebug(S,f);
+ IF (!luaG_checkcode(f), "bad code");
+ S->L->top--;
+ return f;
+}
+
+static void LoadHeader(LoadState* S)
+{
+ char h[LUAC_HEADERSIZE];
+ char s[LUAC_HEADERSIZE];
+ luaU_header(h);
+ LoadBlock(S,s,LUAC_HEADERSIZE);
+ IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
+}
+
+/*
+** load precompiled chunk
+*/
+Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
+{
+ LoadState S;
+ if (*name=='@' || *name=='=')
+ S.name=name+1;
+ else if (*name==LUA_SIGNATURE[0])
+ S.name="binary string";
+ else
+ S.name=name;
+ S.L=L;
+ S.Z=Z;
+ S.b=buff;
+ LoadHeader(&S);
+ return LoadFunction(&S,luaS_newliteral(L,"=?"));
+}
+
+/*
+* make header
+*/
+void luaU_header (char* h)
+{
+ int x=1;
+ memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
+ h+=sizeof(LUA_SIGNATURE)-1;
+ *h++=(char)LUAC_VERSION;
+ *h++=(char)LUAC_FORMAT;
+ *h++=(char)*(char*)&x; /* endianness */
+ *h++=(char)sizeof(int);
+ *h++=(char)sizeof(size_t);
+ *h++=(char)sizeof(Instruction);
+ *h++=(char)sizeof(lua_Number);
+ *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
+}
diff --git a/Build/source/libs/lua51/lundump.h b/Build/source/libs/lua51/lundump.h
new file mode 100644
index 00000000000..58cca5d1908
--- /dev/null
+++ b/Build/source/libs/lua51/lundump.h
@@ -0,0 +1,36 @@
+/*
+** $Id: lundump.h,v 1.40 2005/11/11 14:03:13 lhf Exp $
+** load precompiled Lua chunks
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lundump_h
+#define lundump_h
+
+#include "lobject.h"
+#include "lzio.h"
+
+/* load one chunk; from lundump.c */
+LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);
+
+/* make header; from lundump.c */
+LUAI_FUNC void luaU_header (char* h);
+
+/* dump one chunk; from ldump.c */
+LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
+
+#ifdef luac_c
+/* print one chunk; from print.c */
+LUAI_FUNC void luaU_print (const Proto* f, int full);
+#endif
+
+/* for header of binary files -- this is Lua 5.1 */
+#define LUAC_VERSION 0x51
+
+/* for header of binary files -- this is the official format */
+#define LUAC_FORMAT 0
+
+/* size of header of binary files */
+#define LUAC_HEADERSIZE 12
+
+#endif
diff --git a/Build/source/libs/lua51/lvm.c b/Build/source/libs/lua51/lvm.c
new file mode 100644
index 00000000000..08802f440f3
--- /dev/null
+++ b/Build/source/libs/lua51/lvm.c
@@ -0,0 +1,765 @@
+/*
+** $Id: lvm.c,v 2.63a 2006/06/05 15:58:59 roberto Exp $
+** Lua virtual machine
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lvm_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lvm.h"
+
+
+
+/* limit for table tag-method chains (to avoid loops) */
+#define MAXTAGLOOP 100
+
+
+const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
+ lua_Number num;
+ if (ttisnumber(obj)) return obj;
+ if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
+ setnvalue(n, num);
+ return n;
+ }
+ else
+ return NULL;
+}
+
+
+int luaV_tostring (lua_State *L, StkId obj) {
+ if (!ttisnumber(obj))
+ return 0;
+ else {
+ char s[LUAI_MAXNUMBER2STR];
+ lua_Number n = nvalue(obj);
+ lua_number2str(s, n);
+ setsvalue2s(L, obj, luaS_new(L, s));
+ return 1;
+ }
+}
+
+
+static void traceexec (lua_State *L, const Instruction *pc) {
+ lu_byte mask = L->hookmask;
+ const Instruction *oldpc = L->savedpc;
+ L->savedpc = pc;
+ if (mask > LUA_MASKLINE) { /* instruction-hook set? */
+ if (L->hookcount == 0) {
+ resethookcount(L);
+ luaD_callhook(L, LUA_HOOKCOUNT, -1);
+ }
+ }
+ if (mask & LUA_MASKLINE) {
+ Proto *p = ci_func(L->ci)->l.p;
+ int npc = pcRel(pc, p);
+ int newline = getline(p, npc);
+ /* call linehook when enter a new function, when jump back (loop),
+ or when enter a new line */
+ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))
+ luaD_callhook(L, LUA_HOOKLINE, newline);
+ }
+}
+
+
+static void callTMres (lua_State *L, StkId res, const TValue *f,
+ const TValue *p1, const TValue *p2) {
+ ptrdiff_t result = savestack(L, res);
+ setobj2s(L, L->top, f); /* push function */
+ setobj2s(L, L->top+1, p1); /* 1st argument */
+ setobj2s(L, L->top+2, p2); /* 2nd argument */
+ luaD_checkstack(L, 3);
+ L->top += 3;
+ luaD_call(L, L->top - 3, 1);
+ res = restorestack(L, result);
+ L->top--;
+ setobjs2s(L, res, L->top);
+}
+
+
+
+static void callTM (lua_State *L, const TValue *f, const TValue *p1,
+ const TValue *p2, const TValue *p3) {
+ setobj2s(L, L->top, f); /* push function */
+ setobj2s(L, L->top+1, p1); /* 1st argument */
+ setobj2s(L, L->top+2, p2); /* 2nd argument */
+ setobj2s(L, L->top+3, p3); /* 3th argument */
+ luaD_checkstack(L, 4);
+ L->top += 4;
+ luaD_call(L, L->top - 4, 0);
+}
+
+
+void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
+ int loop;
+ for (loop = 0; loop < MAXTAGLOOP; loop++) {
+ const TValue *tm;
+ if (ttistable(t)) { /* `t' is a table? */
+ Table *h = hvalue(t);
+ const TValue *res = luaH_get(h, key); /* do a primitive get */
+ if (!ttisnil(res) || /* result is no nil? */
+ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
+ setobj2s(L, val, res);
+ return;
+ }
+ /* else will try the tag method */
+ }
+ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
+ luaG_typeerror(L, t, "index");
+ if (ttisfunction(tm)) {
+ callTMres(L, val, tm, t, key);
+ return;
+ }
+ t = tm; /* else repeat with `tm' */
+ }
+ luaG_runerror(L, "loop in gettable");
+}
+
+
+void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
+ int loop;
+ for (loop = 0; loop < MAXTAGLOOP; loop++) {
+ const TValue *tm;
+ if (ttistable(t)) { /* `t' is a table? */
+ Table *h = hvalue(t);
+ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
+ if (!ttisnil(oldval) || /* result is no nil? */
+ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
+ setobj2t(L, oldval, val);
+ luaC_barriert(L, h, val);
+ return;
+ }
+ /* else will try the tag method */
+ }
+ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
+ luaG_typeerror(L, t, "index");
+ if (ttisfunction(tm)) {
+ callTM(L, tm, t, key, val);
+ return;
+ }
+ t = tm; /* else repeat with `tm' */
+ }
+ luaG_runerror(L, "loop in settable");
+}
+
+
+static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,
+ StkId res, TMS event) {
+ const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
+ if (ttisnil(tm))
+ tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
+ if (ttisnil(tm)) return 0;
+ callTMres(L, res, tm, p1, p2);
+ return 1;
+}
+
+
+static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2,
+ TMS event) {
+ const TValue *tm1 = fasttm(L, mt1, event);
+ const TValue *tm2;
+ if (tm1 == NULL) return NULL; /* no metamethod */
+ if (mt1 == mt2) return tm1; /* same metatables => same metamethods */
+ tm2 = fasttm(L, mt2, event);
+ if (tm2 == NULL) return NULL; /* no metamethod */
+ if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */
+ return tm1;
+ return NULL;
+}
+
+
+static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,
+ TMS event) {
+ const TValue *tm1 = luaT_gettmbyobj(L, p1, event);
+ const TValue *tm2;
+ if (ttisnil(tm1)) return -1; /* no metamethod? */
+ tm2 = luaT_gettmbyobj(L, p2, event);
+ if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */
+ return -1;
+ callTMres(L, L->top, tm1, p1, p2);
+ return !l_isfalse(L->top);
+}
+
+
+static int l_strcmp (const TString *ls, const TString *rs) {
+ const char *l = getstr(ls);
+ size_t ll = ls->tsv.len;
+ const char *r = getstr(rs);
+ size_t lr = rs->tsv.len;
+ for (;;) {
+ int temp = strcoll(l, r);
+ if (temp != 0) return temp;
+ else { /* strings are equal up to a `\0' */
+ size_t len = strlen(l); /* index of first `\0' in both strings */
+ if (len == lr) /* r is finished? */
+ return (len == ll) ? 0 : 1;
+ else if (len == ll) /* l is finished? */
+ return -1; /* l is smaller than r (because r is not finished) */
+ /* both strings longer than `len'; go on comparing (after the `\0') */
+ len++;
+ l += len; ll -= len; r += len; lr -= len;
+ }
+ }
+}
+
+
+int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
+ int res;
+ if (ttype(l) != ttype(r))
+ return luaG_ordererror(L, l, r);
+ else if (ttisnumber(l))
+ return luai_numlt(nvalue(l), nvalue(r));
+ else if (ttisstring(l))
+ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
+ else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
+ return res;
+ return luaG_ordererror(L, l, r);
+}
+
+
+static int lessequal (lua_State *L, const TValue *l, const TValue *r) {
+ int res;
+ if (ttype(l) != ttype(r))
+ return luaG_ordererror(L, l, r);
+ else if (ttisnumber(l))
+ return luai_numle(nvalue(l), nvalue(r));
+ else if (ttisstring(l))
+ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
+ else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
+ return res;
+ else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */
+ return !res;
+ return luaG_ordererror(L, l, r);
+}
+
+
+int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
+ const TValue *tm;
+ lua_assert(ttype(t1) == ttype(t2));
+ switch (ttype(t1)) {
+ case LUA_TNIL: return 1;
+ case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
+ case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
+ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
+ case LUA_TUSERDATA: {
+ if (uvalue(t1) == uvalue(t2)) return 1;
+ tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,
+ TM_EQ);
+ break; /* will try TM */
+ }
+ case LUA_TTABLE: {
+ if (hvalue(t1) == hvalue(t2)) return 1;
+ tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
+ break; /* will try TM */
+ }
+ default: return gcvalue(t1) == gcvalue(t2);
+ }
+ if (tm == NULL) return 0; /* no TM? */
+ callTMres(L, L->top, tm, t1, t2); /* call TM */
+ return !l_isfalse(L->top);
+}
+
+
+void luaV_concat (lua_State *L, int total, int last) {
+ do {
+ StkId top = L->base + last + 1;
+ int n = 2; /* number of elements handled in this pass (at least 2) */
+ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
+ if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
+ luaG_concaterror(L, top-2, top-1);
+ } else if (tsvalue(top-1)->len == 0) /* second op is empty? */
+ (void)tostring(L, top - 2); /* result is first op (as string) */
+ else {
+ /* at least two string values; get as many as possible */
+ size_t tl = tsvalue(top-1)->len;
+ char *buffer;
+ int i;
+ /* collect total length */
+ for (n = 1; n < total && tostring(L, top-n-1); n++) {
+ size_t l = tsvalue(top-n-1)->len;
+ if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow");
+ tl += l;
+ }
+ buffer = luaZ_openspace(L, &G(L)->buff, tl);
+ tl = 0;
+ for (i=n; i>0; i--) { /* concat all strings */
+ size_t l = tsvalue(top-i)->len;
+ memcpy(buffer+tl, svalue(top-i), l);
+ tl += l;
+ }
+ setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
+ }
+ total -= n-1; /* got `n' strings to create 1 new */
+ last -= n-1;
+ } while (total > 1); /* repeat until only 1 result left */
+}
+
+
+static void Arith (lua_State *L, StkId ra, const TValue *rb,
+ const TValue *rc, TMS op) {
+ TValue tempb, tempc;
+ const TValue *b, *c;
+ if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
+ (c = luaV_tonumber(rc, &tempc)) != NULL) {
+ lua_Number nb = nvalue(b), nc = nvalue(c);
+ switch (op) {
+ case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;
+ case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;
+ case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;
+ case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;
+ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;
+ case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;
+ case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;
+ default: lua_assert(0); break;
+ }
+ }
+ else if (!call_binTM(L, rb, rc, ra, op))
+ luaG_aritherror(L, rb, rc);
+}
+
+
+
+/*
+** some macros for common tasks in `luaV_execute'
+*/
+
+#define runtime_check(L, c) { if (!(c)) break; }
+
+#define RA(i) (base+GETARG_A(i))
+/* to be used after possible stack reallocation */
+#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
+#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
+#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
+ ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))
+#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
+ ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))
+#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i))
+
+
+#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);}
+
+
+#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; }
+
+
+#define arith_op(op,tm) { \
+ TValue *rb = RKB(i); \
+ TValue *rc = RKC(i); \
+ if (ttisnumber(rb) && ttisnumber(rc)) { \
+ lua_Number nb = nvalue(rb), nc = nvalue(rc); \
+ setnvalue(ra, op(nb, nc)); \
+ } \
+ else \
+ Protect(Arith(L, ra, rb, rc, tm)); \
+ }
+
+
+
+void luaV_execute (lua_State *L, int nexeccalls) {
+ LClosure *cl;
+ StkId base;
+ TValue *k;
+ const Instruction *pc;
+ reentry: /* entry point */
+ lua_assert(isLua(L->ci));
+ pc = L->savedpc;
+ cl = &clvalue(L->ci->func)->l;
+ base = L->base;
+ k = cl->p->k;
+ /* main loop of interpreter */
+ for (;;) {
+ const Instruction i = *pc++;
+ StkId ra;
+ if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
+ (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
+ traceexec(L, pc);
+ if (L->status == LUA_YIELD) { /* did hook yield? */
+ L->savedpc = pc - 1;
+ return;
+ }
+ base = L->base;
+ }
+ /* warning!! several calls may realloc the stack and invalidate `ra' */
+ ra = RA(i);
+ lua_assert(base == L->base && L->base == L->ci->base);
+ lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
+ lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
+ switch (GET_OPCODE(i)) {
+ case OP_MOVE: {
+ setobjs2s(L, ra, RB(i));
+ continue;
+ }
+ case OP_LOADK: {
+ setobj2s(L, ra, KBx(i));
+ continue;
+ }
+ case OP_LOADBOOL: {
+ setbvalue(ra, GETARG_B(i));
+ if (GETARG_C(i)) pc++; /* skip next instruction (if C) */
+ continue;
+ }
+ case OP_LOADNIL: {
+ TValue *rb = RB(i);
+ do {
+ setnilvalue(rb--);
+ } while (rb >= ra);
+ continue;
+ }
+ case OP_GETUPVAL: {
+ int b = GETARG_B(i);
+ setobj2s(L, ra, cl->upvals[b]->v);
+ continue;
+ }
+ case OP_GETGLOBAL: {
+ TValue g;
+ TValue *rb = KBx(i);
+ sethvalue(L, &g, cl->env);
+ lua_assert(ttisstring(rb));
+ Protect(luaV_gettable(L, &g, rb, ra));
+ continue;
+ }
+ case OP_GETTABLE: {
+ Protect(luaV_gettable(L, RB(i), RKC(i), ra));
+ continue;
+ }
+ case OP_SETGLOBAL: {
+ TValue g;
+ sethvalue(L, &g, cl->env);
+ lua_assert(ttisstring(KBx(i)));
+ Protect(luaV_settable(L, &g, KBx(i), ra));
+ continue;
+ }
+ case OP_SETUPVAL: {
+ UpVal *uv = cl->upvals[GETARG_B(i)];
+ setobj(L, uv->v, ra);
+ luaC_barrier(L, uv, ra);
+ continue;
+ }
+ case OP_SETTABLE: {
+ Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
+ continue;
+ }
+ case OP_NEWTABLE: {
+ int b = GETARG_B(i);
+ int c = GETARG_C(i);
+ sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
+ Protect(luaC_checkGC(L));
+ continue;
+ }
+ case OP_SELF: {
+ StkId rb = RB(i);
+ setobjs2s(L, ra+1, rb);
+ Protect(luaV_gettable(L, rb, RKC(i), ra));
+ continue;
+ }
+ case OP_ADD: {
+ arith_op(luai_numadd, TM_ADD);
+ continue;
+ }
+ case OP_SUB: {
+ arith_op(luai_numsub, TM_SUB);
+ continue;
+ }
+ case OP_MUL: {
+ arith_op(luai_nummul, TM_MUL);
+ continue;
+ }
+ case OP_DIV: {
+ arith_op(luai_numdiv, TM_DIV);
+ continue;
+ }
+ case OP_MOD: {
+ arith_op(luai_nummod, TM_MOD);
+ continue;
+ }
+ case OP_POW: {
+ arith_op(luai_numpow, TM_POW);
+ continue;
+ }
+ case OP_UNM: {
+ TValue *rb = RB(i);
+ if (ttisnumber(rb)) {
+ lua_Number nb = nvalue(rb);
+ setnvalue(ra, luai_numunm(nb));
+ }
+ else {
+ Protect(Arith(L, ra, rb, rb, TM_UNM));
+ }
+ continue;
+ }
+ case OP_NOT: {
+ int res = l_isfalse(RB(i)); /* next assignment may change this value */
+ setbvalue(ra, res);
+ continue;
+ }
+ case OP_LEN: {
+ const TValue *rb = RB(i);
+ switch (ttype(rb)) {
+ case LUA_TTABLE: {
+ setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
+ break;
+ }
+ case LUA_TSTRING: {
+ setnvalue(ra, cast_num(tsvalue(rb)->len));
+ break;
+ }
+ default: { /* try metamethod */
+ Protect(
+ if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))
+ luaG_typeerror(L, rb, "get length of");
+ )
+ }
+ }
+ continue;
+ }
+ case OP_CONCAT: {
+ int b = GETARG_B(i);
+ int c = GETARG_C(i);
+ Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));
+ setobjs2s(L, RA(i), base+b);
+ continue;
+ }
+ case OP_JMP: {
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
+ }
+ case OP_EQ: {
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ Protect(
+ if (equalobj(L, rb, rc) == GETARG_A(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ )
+ pc++;
+ continue;
+ }
+ case OP_LT: {
+ Protect(
+ if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ )
+ pc++;
+ continue;
+ }
+ case OP_LE: {
+ Protect(
+ if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ )
+ pc++;
+ continue;
+ }
+ case OP_TEST: {
+ if (l_isfalse(ra) != GETARG_C(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ pc++;
+ continue;
+ }
+ case OP_TESTSET: {
+ TValue *rb = RB(i);
+ if (l_isfalse(rb) != GETARG_C(i)) {
+ setobjs2s(L, ra, rb);
+ dojump(L, pc, GETARG_sBx(*pc));
+ }
+ pc++;
+ continue;
+ }
+ case OP_CALL: {
+ int b = GETARG_B(i);
+ int nresults = GETARG_C(i) - 1;
+ if (b != 0) L->top = ra+b; /* else previous instruction set top */
+ L->savedpc = pc;
+ switch (luaD_precall(L, ra, nresults)) {
+ case PCRLUA: {
+ nexeccalls++;
+ goto reentry; /* restart luaV_execute over new Lua function */
+ }
+ case PCRC: {
+ /* it was a C function (`precall' called it); adjust results */
+ if (nresults >= 0) L->top = L->ci->top;
+ base = L->base;
+ continue;
+ }
+ default: {
+ return; /* yield */
+ }
+ }
+ }
+ case OP_TAILCALL: {
+ int b = GETARG_B(i);
+ if (b != 0) L->top = ra+b; /* else previous instruction set top */
+ L->savedpc = pc;
+ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
+ switch (luaD_precall(L, ra, LUA_MULTRET)) {
+ case PCRLUA: {
+ /* tail call: put new frame in place of previous one */
+ CallInfo *ci = L->ci - 1; /* previous frame */
+ int aux;
+ StkId func = ci->func;
+ StkId pfunc = (ci+1)->func; /* previous function index */
+ if (L->openupval) luaF_close(L, ci->base);
+ L->base = ci->base = ci->func + ((ci+1)->base - pfunc);
+ for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */
+ setobjs2s(L, func+aux, pfunc+aux);
+ ci->top = L->top = func+aux; /* correct top */
+ lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize);
+ ci->savedpc = L->savedpc;
+ ci->tailcalls++; /* one more call lost */
+ L->ci--; /* remove new frame */
+ goto reentry;
+ }
+ case PCRC: { /* it was a C function (`precall' called it) */
+ base = L->base;
+ continue;
+ }
+ default: {
+ return; /* yield */
+ }
+ }
+ }
+ case OP_RETURN: {
+ int b = GETARG_B(i);
+ if (b != 0) L->top = ra+b-1;
+ if (L->openupval) luaF_close(L, base);
+ L->savedpc = pc;
+ b = luaD_poscall(L, ra);
+ if (--nexeccalls == 0) /* was previous function running `here'? */
+ return; /* no: return */
+ else { /* yes: continue its execution */
+ if (b) L->top = L->ci->top;
+ lua_assert(isLua(L->ci));
+ lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL);
+ goto reentry;
+ }
+ }
+ case OP_FORLOOP: {
+ lua_Number step = nvalue(ra+2);
+ lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
+ lua_Number limit = nvalue(ra+1);
+ if (luai_numlt(0, step) ? luai_numle(idx, limit)
+ : luai_numle(limit, idx)) {
+ dojump(L, pc, GETARG_sBx(i)); /* jump back */
+ setnvalue(ra, idx); /* update internal index... */
+ setnvalue(ra+3, idx); /* ...and external index */
+ }
+ continue;
+ }
+ case OP_FORPREP: {
+ const TValue *init = ra;
+ const TValue *plimit = ra+1;
+ const TValue *pstep = ra+2;
+ L->savedpc = pc; /* next steps may throw errors */
+ if (!tonumber(init, ra))
+ luaG_runerror(L, LUA_QL("for") " initial value must be a number");
+ else if (!tonumber(plimit, ra+1))
+ luaG_runerror(L, LUA_QL("for") " limit must be a number");
+ else if (!tonumber(pstep, ra+2))
+ luaG_runerror(L, LUA_QL("for") " step must be a number");
+ setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
+ }
+ case OP_TFORLOOP: {
+ StkId cb = ra + 3; /* call base */
+ setobjs2s(L, cb+2, ra+2);
+ setobjs2s(L, cb+1, ra+1);
+ setobjs2s(L, cb, ra);
+ L->top = cb+3; /* func. + 2 args (state and index) */
+ Protect(luaD_call(L, cb, GETARG_C(i)));
+ L->top = L->ci->top;
+ cb = RA(i) + 3; /* previous call may change the stack */
+ if (!ttisnil(cb)) { /* continue loop? */
+ setobjs2s(L, cb-1, cb); /* save control variable */
+ dojump(L, pc, GETARG_sBx(*pc)); /* jump back */
+ }
+ pc++;
+ continue;
+ }
+ case OP_SETLIST: {
+ int n = GETARG_B(i);
+ int c = GETARG_C(i);
+ int last;
+ Table *h;
+ if (n == 0) {
+ n = cast_int(L->top - ra) - 1;
+ L->top = L->ci->top;
+ }
+ if (c == 0) c = cast_int(*pc++);
+ runtime_check(L, ttistable(ra));
+ h = hvalue(ra);
+ last = ((c-1)*LFIELDS_PER_FLUSH) + n;
+ if (last > h->sizearray) /* needs more space? */
+ luaH_resizearray(L, h, last); /* pre-alloc it at once */
+ for (; n > 0; n--) {
+ TValue *val = ra+n;
+ setobj2t(L, luaH_setnum(L, h, last--), val);
+ luaC_barriert(L, h, val);
+ }
+ continue;
+ }
+ case OP_CLOSE: {
+ luaF_close(L, ra);
+ continue;
+ }
+ case OP_CLOSURE: {
+ Proto *p;
+ Closure *ncl;
+ int nup, j;
+ p = cl->p->p[GETARG_Bx(i)];
+ nup = p->nups;
+ ncl = luaF_newLclosure(L, nup, cl->env);
+ ncl->l.p = p;
+ for (j=0; j<nup; j++, pc++) {
+ if (GET_OPCODE(*pc) == OP_GETUPVAL)
+ ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];
+ else {
+ lua_assert(GET_OPCODE(*pc) == OP_MOVE);
+ ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
+ }
+ }
+ setclvalue(L, ra, ncl);
+ Protect(luaC_checkGC(L));
+ continue;
+ }
+ case OP_VARARG: {
+ int b = GETARG_B(i) - 1;
+ int j;
+ CallInfo *ci = L->ci;
+ int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1;
+ if (b == LUA_MULTRET) {
+ Protect(luaD_checkstack(L, n));
+ ra = RA(i); /* previous call may change the stack */
+ b = n;
+ L->top = ra + n;
+ }
+ for (j = 0; j < b; j++) {
+ if (j < n) {
+ setobjs2s(L, ra + j, ci->base - n + j);
+ }
+ else {
+ setnilvalue(ra + j);
+ }
+ }
+ continue;
+ }
+ }
+ }
+}
+
diff --git a/Build/source/libs/lua51/lvm.h b/Build/source/libs/lua51/lvm.h
new file mode 100644
index 00000000000..788423f8e31
--- /dev/null
+++ b/Build/source/libs/lua51/lvm.h
@@ -0,0 +1,36 @@
+/*
+** $Id: lvm.h,v 2.5 2005/08/22 18:54:49 roberto Exp $
+** Lua virtual machine
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lvm_h
+#define lvm_h
+
+
+#include "ldo.h"
+#include "lobject.h"
+#include "ltm.h"
+
+
+#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))
+
+#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \
+ (((o) = luaV_tonumber(o,n)) != NULL))
+
+#define equalobj(L,o1,o2) \
+ (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
+
+
+LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
+LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2);
+LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n);
+LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj);
+LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
+ StkId val);
+LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
+ StkId val);
+LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls);
+LUAI_FUNC void luaV_concat (lua_State *L, int total, int last);
+
+#endif
diff --git a/Build/source/libs/lua51/lzio.c b/Build/source/libs/lua51/lzio.c
new file mode 100644
index 00000000000..5121ada8466
--- /dev/null
+++ b/Build/source/libs/lua51/lzio.c
@@ -0,0 +1,82 @@
+/*
+** $Id: lzio.c,v 1.31 2005/06/03 20:15:29 roberto Exp $
+** a generic input stream interface
+** See Copyright Notice in lua.h
+*/
+
+
+#include <string.h>
+
+#define lzio_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "llimits.h"
+#include "lmem.h"
+#include "lstate.h"
+#include "lzio.h"
+
+
+int luaZ_fill (ZIO *z) {
+ size_t size;
+ lua_State *L = z->L;
+ const char *buff;
+ lua_unlock(L);
+ buff = z->reader(L, z->data, &size);
+ lua_lock(L);
+ if (buff == NULL || size == 0) return EOZ;
+ z->n = size - 1;
+ z->p = buff;
+ return char2int(*(z->p++));
+}
+
+
+int luaZ_lookahead (ZIO *z) {
+ if (z->n == 0) {
+ if (luaZ_fill(z) == EOZ)
+ return EOZ;
+ else {
+ z->n++; /* luaZ_fill removed first byte; put back it */
+ z->p--;
+ }
+ }
+ return char2int(*z->p);
+}
+
+
+void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {
+ z->L = L;
+ z->reader = reader;
+ z->data = data;
+ z->n = 0;
+ z->p = NULL;
+}
+
+
+/* --------------------------------------------------------------- read --- */
+size_t luaZ_read (ZIO *z, void *b, size_t n) {
+ while (n) {
+ size_t m;
+ if (luaZ_lookahead(z) == EOZ)
+ return n; /* return number of missing bytes */
+ m = (n <= z->n) ? n : z->n; /* min. between n and z->n */
+ memcpy(b, z->p, m);
+ z->n -= m;
+ z->p += m;
+ b = (char *)b + m;
+ n -= m;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
+ if (n > buff->buffsize) {
+ if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
+ luaZ_resizebuffer(L, buff, n);
+ }
+ return buff->buffer;
+}
+
+
diff --git a/Build/source/libs/lua51/lzio.h b/Build/source/libs/lua51/lzio.h
new file mode 100644
index 00000000000..8f403b8e74f
--- /dev/null
+++ b/Build/source/libs/lua51/lzio.h
@@ -0,0 +1,67 @@
+/*
+** $Id: lzio.h,v 1.21 2005/05/17 19:49:15 roberto Exp $
+** Buffered streams
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lzio_h
+#define lzio_h
+
+#include "lua.h"
+
+#include "lmem.h"
+
+
+#define EOZ (-1) /* end of stream */
+
+typedef struct Zio ZIO;
+
+#define char2int(c) cast(int, cast(unsigned char, (c)))
+
+#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z))
+
+typedef struct Mbuffer {
+ char *buffer;
+ size_t n;
+ size_t buffsize;
+} Mbuffer;
+
+#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)
+
+#define luaZ_buffer(buff) ((buff)->buffer)
+#define luaZ_sizebuffer(buff) ((buff)->buffsize)
+#define luaZ_bufflen(buff) ((buff)->n)
+
+#define luaZ_resetbuffer(buff) ((buff)->n = 0)
+
+
+#define luaZ_resizebuffer(L, buff, size) \
+ (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
+ (buff)->buffsize = size)
+
+#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
+
+
+LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
+LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
+ void *data);
+LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */
+LUAI_FUNC int luaZ_lookahead (ZIO *z);
+
+
+
+/* --------- Private Part ------------------ */
+
+struct Zio {
+ size_t n; /* bytes still unread */
+ const char *p; /* current position in buffer */
+ lua_Reader reader;
+ void* data; /* additional data */
+ lua_State *L; /* Lua state (for reader) */
+};
+
+
+LUAI_FUNC int luaZ_fill (ZIO *z);
+
+#endif
diff --git a/Build/source/libs/lua51/print.c b/Build/source/libs/lua51/print.c
new file mode 100644
index 00000000000..e240cfc3c60
--- /dev/null
+++ b/Build/source/libs/lua51/print.c
@@ -0,0 +1,227 @@
+/*
+** $Id: print.c,v 1.55a 2006/05/31 13:30:05 lhf Exp $
+** print bytecodes
+** See Copyright Notice in lua.h
+*/
+
+#include <ctype.h>
+#include <stdio.h>
+
+#define luac_c
+#define LUA_CORE
+
+#include "ldebug.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lundump.h"
+
+#define PrintFunction luaU_print
+
+#define Sizeof(x) ((int)sizeof(x))
+#define VOID(p) ((const void*)(p))
+
+static void PrintString(const TString* ts)
+{
+ const char* s=getstr(ts);
+ size_t i,n=ts->tsv.len;
+ putchar('"');
+ for (i=0; i<n; i++)
+ {
+ int c=s[i];
+ switch (c)
+ {
+ case '"': printf("\\\""); break;
+ case '\\': printf("\\\\"); break;
+ case '\a': printf("\\a"); break;
+ case '\b': printf("\\b"); break;
+ case '\f': printf("\\f"); break;
+ case '\n': printf("\\n"); break;
+ case '\r': printf("\\r"); break;
+ case '\t': printf("\\t"); break;
+ case '\v': printf("\\v"); break;
+ default: if (isprint((unsigned char)c))
+ putchar(c);
+ else
+ printf("\\%03u",(unsigned char)c);
+ }
+ }
+ putchar('"');
+}
+
+static void PrintConstant(const Proto* f, int i)
+{
+ const TValue* o=&f->k[i];
+ switch (ttype(o))
+ {
+ case LUA_TNIL:
+ printf("nil");
+ break;
+ case LUA_TBOOLEAN:
+ printf(bvalue(o) ? "true" : "false");
+ break;
+ case LUA_TNUMBER:
+ printf(LUA_NUMBER_FMT,nvalue(o));
+ break;
+ case LUA_TSTRING:
+ PrintString(rawtsvalue(o));
+ break;
+ default: /* cannot happen */
+ printf("? type=%d",ttype(o));
+ break;
+ }
+}
+
+static void PrintCode(const Proto* f)
+{
+ const Instruction* code=f->code;
+ int pc,n=f->sizecode;
+ for (pc=0; pc<n; pc++)
+ {
+ Instruction i=code[pc];
+ OpCode o=GET_OPCODE(i);
+ int a=GETARG_A(i);
+ int b=GETARG_B(i);
+ int c=GETARG_C(i);
+ int bx=GETARG_Bx(i);
+ int sbx=GETARG_sBx(i);
+ int line=getline(f,pc);
+ printf("\t%d\t",pc+1);
+ if (line>0) printf("[%d]\t",line); else printf("[-]\t");
+ printf("%-9s\t",luaP_opnames[o]);
+ switch (getOpMode(o))
+ {
+ case iABC:
+ printf("%d",a);
+ if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (-1-INDEXK(b)) : b);
+ if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (-1-INDEXK(c)) : c);
+ break;
+ case iABx:
+ if (getBMode(o)==OpArgK) printf("%d %d",a,-1-bx); else printf("%d %d",a,bx);
+ break;
+ case iAsBx:
+ if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx);
+ break;
+ }
+ switch (o)
+ {
+ case OP_LOADK:
+ printf("\t; "); PrintConstant(f,bx);
+ break;
+ case OP_GETUPVAL:
+ case OP_SETUPVAL:
+ printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-");
+ break;
+ case OP_GETGLOBAL:
+ case OP_SETGLOBAL:
+ printf("\t; %s",svalue(&f->k[bx]));
+ break;
+ case OP_GETTABLE:
+ case OP_SELF:
+ if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); }
+ break;
+ case OP_SETTABLE:
+ case OP_ADD:
+ case OP_SUB:
+ case OP_MUL:
+ case OP_DIV:
+ case OP_POW:
+ case OP_EQ:
+ case OP_LT:
+ case OP_LE:
+ if (ISK(b) || ISK(c))
+ {
+ printf("\t; ");
+ if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-");
+ printf(" ");
+ if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-");
+ }
+ break;
+ case OP_JMP:
+ case OP_FORLOOP:
+ case OP_FORPREP:
+ printf("\t; to %d",sbx+pc+2);
+ break;
+ case OP_CLOSURE:
+ printf("\t; %p",VOID(f->p[bx]));
+ break;
+ case OP_SETLIST:
+ if (c==0) printf("\t; %d",(int)code[++pc]);
+ else printf("\t; %d",c);
+ break;
+ default:
+ break;
+ }
+ printf("\n");
+ }
+}
+
+#define SS(x) (x==1)?"":"s"
+#define S(x) x,SS(x)
+
+static void PrintHeader(const Proto* f)
+{
+ const char* s=getstr(f->source);
+ if (*s=='@' || *s=='=')
+ s++;
+ else if (*s==LUA_SIGNATURE[0])
+ s="(bstring)";
+ else
+ s="(string)";
+ printf("\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\n",
+ (f->linedefined==0)?"main":"function",s,
+ f->linedefined,f->lastlinedefined,
+ S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f));
+ printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
+ f->numparams,f->is_vararg?"+":"",SS(f->numparams),
+ S(f->maxstacksize),S(f->nups));
+ printf("%d local%s, %d constant%s, %d function%s\n",
+ S(f->sizelocvars),S(f->sizek),S(f->sizep));
+}
+
+static void PrintConstants(const Proto* f)
+{
+ int i,n=f->sizek;
+ printf("constants (%d) for %p:\n",n,VOID(f));
+ for (i=0; i<n; i++)
+ {
+ printf("\t%d\t",i+1);
+ PrintConstant(f,i);
+ printf("\n");
+ }
+}
+
+static void PrintLocals(const Proto* f)
+{
+ int i,n=f->sizelocvars;
+ printf("locals (%d) for %p:\n",n,VOID(f));
+ for (i=0; i<n; i++)
+ {
+ printf("\t%d\t%s\t%d\t%d\n",
+ i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);
+ }
+}
+
+static void PrintUpvalues(const Proto* f)
+{
+ int i,n=f->sizeupvalues;
+ printf("upvalues (%d) for %p:\n",n,VOID(f));
+ if (f->upvalues==NULL) return;
+ for (i=0; i<n; i++)
+ {
+ printf("\t%d\t%s\n",i,getstr(f->upvalues[i]));
+ }
+}
+
+void PrintFunction(const Proto* f, int full)
+{
+ int i,n=f->sizep;
+ PrintHeader(f);
+ PrintCode(f);
+ if (full)
+ {
+ PrintConstants(f);
+ PrintLocals(f);
+ PrintUpvalues(f);
+ }
+ for (i=0; i<n; i++) PrintFunction(f->p[i],full);
+}
diff --git a/Build/source/libs/luafilesystem/Makefile b/Build/source/libs/luafilesystem/Makefile
new file mode 100644
index 00000000000..35e7b3e9d54
--- /dev/null
+++ b/Build/source/libs/luafilesystem/Makefile
@@ -0,0 +1,28 @@
+# $Id: Makefile,v 1.26 2005/06/27 17:06:01 tomas Exp $
+
+T= lfs
+V= 1.2
+CONFIG= ./config
+
+include $(CONFIG)
+
+COMPAT_O= $(COMPAT_DIR)/compat-5.1.o
+SRCS= src/$T.c
+OBJS= src/$T.o $(COMPAT_O)
+
+
+lib: src/$(LIBNAME)
+
+src/$(LIBNAME): $(OBJS)
+ export MACOSX_DEPLOYMENT_TARGET="10.3"; $(CC) $(CFLAGS) $(LIB_OPTION) -o src/$(LIBNAME) $(OBJS)
+
+$(COMPAT_O): $(COMPAT_DIR)/compat-5.1.c
+ $(CC) -c $(CFLAGS) -o $@ $(COMPAT_DIR)/compat-5.1.c
+
+install: src/$(LIBNAME)
+ mkdir -p $(LUA_LIBDIR)
+ cp src/$(LIBNAME) $(LUA_LIBDIR)
+ cd $(LUA_LIBDIR); ln -f -s $(LIBNAME) $T.so
+
+clean:
+ rm -f src/$(LIBNAME) $(OBJS) $(COMPAT_O)
diff --git a/Build/source/libs/luafilesystem/config b/Build/source/libs/luafilesystem/config
new file mode 100644
index 00000000000..d27284333ea
--- /dev/null
+++ b/Build/source/libs/luafilesystem/config
@@ -0,0 +1,20 @@
+# Installation directories
+# System's libraries directory (where binary libraries are installed)
+LUA_LIBDIR= /usr/local/lib/lua/5.0
+# Lua includes directory
+LUA_INC= /usr/local/include
+
+# OS dependent
+LIB_OPTION= -shared #for Linux
+#LIB_OPTION= -bundle -undefined dynamic_lookup #for MacOS X
+
+LIBNAME= $T.so.$V
+COMPAT_DIR= ../compat/src
+
+# Compilation directives
+WARN= -O2 -Wall -fPIC -W -Waggregate-return -Wcast-align -Wmissing-prototypes -Wnested-externs -Wshadow -Wwrite-strings
+INCS= -I$(LUA_INC) -I$(COMPAT_DIR)
+CFLAGS= $(WARN) $(INCS)
+CC= gcc
+
+# $Id: config,v 1.14 2005/06/24 01:49:16 tomas Exp $
diff --git a/Build/source/libs/luafilesystem/doc/us/examples.html b/Build/source/libs/luafilesystem/doc/us/examples.html
new file mode 100644
index 00000000000..89f70707287
--- /dev/null
+++ b/Build/source/libs/luafilesystem/doc/us/examples.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+ <title>LuaFileSystem</title>
+ <link rel="stylesheet" href="http://www.keplerproject.org/doc.css" type="text/css"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo">
+ <a href="http://www.keplerproject.org">
+ <img alt="LuaFileSystem" src="luafilesystem.png"/>
+ </a>
+ </div>
+ <div id="product_name"><big><strong>LuaFileSystem</strong></big></div>
+ <div id="product_description">File System Library for the Lua Programming Language</div>
+</div> <!-- id="product" -->
+
+<div id="main">
+
+<div id="navigation">
+<h1>LuaFileSystem</h1>
+ <ul>
+ <li><a href="index.html">Home</a>
+ <ul>
+ <li><a href="index.html#overview">Overview</a></li>
+ <li><a href="index.html#status">Status</a></li>
+ <li><a href="index.html#download">Download</a></li>
+ <li><a href="index.html#history">History</a></li>
+ <li><a href="index.html#credits">Credits</a></li>
+ <li><a href="index.html#contact">Contact us</a></li>
+ </ul>
+ </li>
+ <li><a href="manual.html">Manual</a>
+ <ul>
+ <li><a href="manual.html#introduction">Introduction</a></li>
+ <li><a href="manual.html#installation">Installation</a></li>
+ <li><a href="manual.html#reference">Reference</a></li>
+ </ul>
+ </li>
+ <li><strong>Examples</strong></li>
+ <li><a href="http://luaforge.net/projects/luafilesystem/">Project</a>
+ <ul>
+ <li><a href="http://luaforge.net/tracker/?group_id=66">Bug Tracker</a></li>
+ <li><a href="http://luaforge.net/scm/?group_id=66">CVS</a></li>
+ </ul>
+ </li>
+ <li><a href="license.html">License</a></li>
+ </ul>
+</div> <!-- id="navigation" -->
+
+<div id="content">
+
+<h2><a name="example"></a>Examples</h2>
+
+<h3>Directory iterator</h3>
+
+<p>The following example iterates over a directory and recursively lists the
+attributes for each file inside it.</p>
+
+<pre class="example">
+require"lfs"
+
+function attrdir (path)
+ for file in lfs.dir(path) do
+ if file ~= "." and file ~= ".." then
+ local f = path..'/'..file
+ print ("\t "..f)
+ local attr = lfs.attributes (f)
+ assert (type(attr) == "table")
+ if attr.mode == "directory" then
+ attrdir (f)
+ else
+ for name, value in pairs(attr) do
+ print (name, value)
+ end
+ end
+ end
+ end
+end
+
+attrdir (".")
+</pre>
+
+</div> <!-- id="content" -->
+
+</div> <!-- id="main" -->
+
+<div id="about">
+ <p><a href="http://validator.w3.org/check?uri=referer">
+ <img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
+ <p><small>$Id: examples.html,v 1.5 2006/03/14 14:07:55 carregal Exp $</small></p>
+</div> <!-- id="about" -->
+
+</div> <!-- id="container" -->
+
+</body>
+</html>
diff --git a/Build/source/libs/luafilesystem/doc/us/index.html b/Build/source/libs/luafilesystem/doc/us/index.html
new file mode 100644
index 00000000000..15c954a1fc8
--- /dev/null
+++ b/Build/source/libs/luafilesystem/doc/us/index.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+ <title>LuaFileSystem</title>
+ <link rel="stylesheet" href="http://www.keplerproject.org/doc.css" type="text/css"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo">
+ <a href="http://www.keplerproject.org">
+ <img alt="LuaFileSystem" src="luafilesystem.png"/>
+ </a>
+ </div>
+ <div id="product_name"><big><strong>LuaFileSystem</strong></big></div>
+ <div id="product_description">File System Library for the Lua Programming Language</div>
+</div> <!-- id="product" -->
+
+<div id="main">
+
+<div id="navigation">
+<h1>LuaFileSystem</h1>
+ <ul>
+ <li><strong>Home</strong>
+ <ul>
+ <li><a href="index.html#overview">Overview</a></li>
+ <li><a href="index.html#status">Status</a></li>
+ <li><a href="index.html#download">Download</a></li>
+ <li><a href="index.html#history">History</a></li>
+ <li><a href="index.html#credits">Credits</a></li>
+ <li><a href="index.html#contact">Contact us</a></li>
+ </ul>
+ </li>
+ <li><a href="manual.html">Manual</a>
+ <ul>
+ <li><a href="manual.html#introduction">Introduction</a></li>
+ <li><a href="manual.html#installation">Installation</a></li>
+ <li><a href="manual.html#reference">Reference</a></li>
+ </ul>
+ </li>
+ <li><a href="examples.html">Examples</a></li>
+ <li><a href="http://luaforge.net/projects/luafilesystem/">Project</a>
+ <ul>
+ <li><a href="http://luaforge.net/tracker/?group_id=66">Bug Tracker</a></li>
+ <li><a href="http://luaforge.net/scm/?group_id=66">CVS</a></li>
+ </ul>
+ </li>
+ <li><a href="license.html">License</a></li>
+ </ul>
+</div> <!-- id="navigation" -->
+
+<div id="content">
+
+<h2><a name="overview"></a>Overview</h2>
+
+<p>LuaFileSystem is a <a href="http://www.lua.org">Lua</a> library
+developed to complement the set of functions related to file
+systems offered by the standard Lua distribution.</p>
+
+<p>LuaFileSystem offers a portable way to access
+the underlying directory structure and file attributes.</p>
+
+<p>LuaFileSystem is free software and uses the same
+<a href="license.html">license</a> as Lua 5.0.</p>
+
+<h2><a name="status"></a>Status</h2>
+
+<p>Current version is 1.2. It was developed for Lua 5.0.</p>
+
+<p>Version 1.2 follows the
+<a href="http://www.keplerproject.org/compat">package model</a>
+for Lua 5.1 (see section <a href="manual.html#installation">Installation</a>
+for more details).</p>
+
+
+<h2><a name="download"></a>Download</h2>
+
+<p>LuaFileSystem source can be downloaded from its
+<a href="http://luaforge.net/projects/luafilesystem/files">Lua Forge</a>
+page. If you are using
+<a href="http://luabinaries.luaforge.net">LuaBinaries</a> Release 2
+a Windows binary version of LuaFileSystem can also be found at the
+LuaForge page.</p>
+
+
+<h2><a name="history"></a>History</h2>
+
+<dl class="history">
+ <dt><strong>Version 1.2</strong> [15/Mar/2006]</dt>
+ <dd>
+ <ul>
+ <li>added optional argument to
+ <a href="manual.html#attributes"><code>lfs.attributes</code></a></li>
+ <li>added function
+ <a href="manual.html#rmdir"><code>lfs.rmdir</code></a></li>
+ <li>bug correction on <code>lfs.dir</code></li>
+ </ul>
+ </dd>
+
+ <dt><strong><a href="http://www.keplerproject.org/luafilesystem/1.1/">Version 1.1</a></strong> [30/May/2005]</dt>
+ <dd>
+ <ul>
+ <li>added function <code>lfs.touch</code>.</li>
+ </ul>
+ </dd>
+
+ <dt><strong><a href="http://www.keplerproject.org/luafilesystem/1.0/">Version 1.0</a></strong> [21/Jan/2005]</dt>
+ <dd />
+
+ <dt><strong>Version 1.0 Beta</strong> [10/Nov/2004]</dt>
+ <dd />
+</dl>
+
+<h2><a name="credits"></a>Credits</h2>
+
+<p>LuaFileSystem was designed by Roberto Ierusalimschy,
+Andr&eacute; Carregal and Tom&aacute;s Guisasola as part of the
+<a href="http://www.keplerproject.org">Kepler Project</a>,
+which holds its copyright.</p>
+
+<h2><a name="contact"></a>Contact us</h2>
+
+<p>For more information please
+<a href="mailto:info-NO-SPAM-THANKS@keplerproject.org">contact us</a>.
+Comments are welcome!</p>
+
+<p>You can also reach other Kepler developers and users on the Kepler Project
+<a href="http://luaforge.net/mail/?group_id=104">mailing list</a>.</p>
+
+</div> <!-- id="content" -->
+
+</div> <!-- id="main" -->
+
+<div id="about">
+ <p><a href="http://validator.w3.org/check?uri=referer">
+ <img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
+ <p><small>$Id: index.html,v 1.30 2006/03/15 16:44:04 carregal Exp $</small></p>
+</div> <!-- id="about" -->
+
+</div> <!-- id="container" -->
+
+</body>
+</html>
diff --git a/Build/source/libs/luafilesystem/doc/us/license.html b/Build/source/libs/luafilesystem/doc/us/license.html
new file mode 100644
index 00000000000..6bb4aaa0028
--- /dev/null
+++ b/Build/source/libs/luafilesystem/doc/us/license.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+ <title>LuaFileSystem</title>
+ <link rel="stylesheet" href="http://www.keplerproject.org/doc.css" type="text/css"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo">
+ <a href="http://www.keplerproject.org">
+ <img alt="LuaFileSystem" src="luafilesystem.png"/>
+ </a>
+ </div>
+ <div id="product_name"><big><strong>LuaFileSystem</strong></big></div>
+ <div id="product_description">File System Library for the Lua Programming Language</div>
+</div> <!-- id="product" -->
+
+<div id="main">
+
+<div id="navigation">
+<h1>LuaFileSystem</h1>
+ <ul>
+ <li><a href="index.html">Home</a>
+ <ul>
+ <li><a href="index.html#overview">Overview</a></li>
+ <li><a href="index.html#status">Status</a></li>
+ <li><a href="index.html#download">Download</a></li>
+ <li><a href="index.html#history">History</a></li>
+ <li><a href="index.html#credits">Credits</a></li>
+ <li><a href="index.html#contact">Contact us</a></li>
+ </ul>
+ </li>
+ <li><a href="manual.html">Manual</a>
+ <ul>
+ <li><a href="manual.html#introduction">Introduction</a></li>
+ <li><a href="manual.html#installation">Installation</a></li>
+ <li><a href="manual.html#reference">Reference</a></li>
+ </ul>
+ </li>
+ <li><a href="examples.html">Examples</a></li>
+ <li><a href="http://luaforge.net/projects/luafilesystem/">Project</a>
+ <ul>
+ <li><a href="http://luaforge.net/tracker/?group_id=66">Bug Tracker</a></li>
+ <li><a href="http://luaforge.net/scm/?group_id=66">CVS</a></li>
+ </ul>
+ </li>
+ <li><strong>License</strong></li>
+ </ul>
+</div> <!-- id="navigation" -->
+
+<div id="content">
+
+<h1>License</h1>
+
+<p>
+LuaFileSystem is free software: it can be used for both academic
+and commercial purposes at absolutely no cost. There are no
+royalties or GNU-like "copyleft" restrictions. LuaFileSystem
+qualifies as
+<a href="http://www.opensource.org/docs/definition.html">Open Source</a>
+software.
+Its licenses are compatible with
+<a href="http://www.gnu.org/licenses/gpl.html">GPL</a>.
+LuaFileSystem is not in the public domain and the
+<a href="http://www.keplerproject.org">Kepler Project</a>
+keep its copyright.
+The legal details are below.
+</p>
+
+<p>The spirit of the license is that you are free to use
+LuaFileSystem for any purpose at no cost without having to ask us.
+The only requirement is that if you do use LuaFileSystem, then you
+should give us credit by including the appropriate copyright notice
+somewhere in your product or its documentation.</p>
+
+<p>The LuaFileSystem library is designed and implemented by Roberto
+Ierusalimschy, Andr&eacute; Carregal and Tom&aacute;s Guisasola.
+The implementation is not derived from licensed software.</p>
+
+<hr/>
+<p>Copyright &copy; 2004-2006 The Kepler Project.</p>
+
+<p>Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use, copy,
+modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:</p>
+
+<p>The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.</p>
+
+<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.</p>
+
+</div> <!-- id="content" -->
+
+</div> <!-- id="main" -->
+
+<div id="about">
+ <p><a href="http://validator.w3.org/check?uri=referer">
+ <img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
+ <p><small>$Id: license.html,v 1.9 2006/03/14 14:07:55 carregal Exp $</small></p>
+</div><!-- id="about" -->
+
+</div><!-- id="container" -->
+
+</body>
+</html>
diff --git a/Build/source/libs/luafilesystem/doc/us/luafilesystem.png b/Build/source/libs/luafilesystem/doc/us/luafilesystem.png
new file mode 100644
index 00000000000..e1dd8c65b52
--- /dev/null
+++ b/Build/source/libs/luafilesystem/doc/us/luafilesystem.png
Binary files differ
diff --git a/Build/source/libs/luafilesystem/doc/us/manual.html b/Build/source/libs/luafilesystem/doc/us/manual.html
new file mode 100644
index 00000000000..281c06ea407
--- /dev/null
+++ b/Build/source/libs/luafilesystem/doc/us/manual.html
@@ -0,0 +1,226 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+ <title>LuaFileSystem</title>
+ <link rel="stylesheet" href="http://www.keplerproject.org/doc.css" type="text/css"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo">
+ <a href="http://www.keplerproject.org"><img alt="LuaFileSystem" src="luafilesystem.png"/></a>
+ </div>
+ <div id="product_name"><big><strong>LuaFileSystem</strong></big></div>
+ <div id="product_description">File System Library for the Lua Programming Language</div>
+</div> <!-- id="product" -->
+
+<div id="main">
+
+<div id="navigation">
+<h1>LuaFileSystem</h1>
+ <ul>
+ <li><a href="index.html">Home</a>
+ <ul>
+ <li><a href="index.html#overview">Overview</a></li>
+ <li><a href="index.html#status">Status</a></li>
+ <li><a href="index.html#download">Download</a></li>
+ <li><a href="index.html#history">History</a></li>
+ <li><a href="index.html#credits">Credits</a></li>
+ <li><a href="index.html#contact">Contact us</a></li>
+ </ul>
+ </li>
+ <li><strong>Manual</strong>
+ <ul>
+ <li><a href="manual.html#introduction">Introduction</a></li>
+ <li><a href="manual.html#installation">Installation</a></li>
+ <li><a href="manual.html#reference">Reference</a></li>
+ </ul>
+ </li>
+ <li><a href="examples.html">Examples</a></li>
+ <li><a href="http://luaforge.net/projects/luafilesystem/">Project</a>
+ <ul>
+ <li><a href="http://luaforge.net/tracker/?group_id=66">Bug Tracker</a></li>
+ <li><a href="http://luaforge.net/scm/?group_id=66">CVS</a></li>
+ </ul>
+ </li>
+ <li><a href="license.html">License</a></li>
+ </ul>
+</div> <!-- id="navigation" -->
+
+<div id="content">
+
+<h2><a name="introduction"></a>Introduction</h2>
+
+<p>LuaFileSystem is a <a href="http://www.lua.org">Lua</a> library
+developed to complement the set of functions related to file
+systems offered by the standard Lua distribution.</p>
+
+<p>LuaFileSystem offers a portable way to access
+the underlying directory structure and file attributes.</p>
+
+<h2><a name="installation"></a>Installation</h2>
+
+<p>LuaFileSystem follows the
+<a href="http://www.keplerproject.org/compat/">package model</a>
+for Lua 5.1, therefore it should be "installed". Refer to
+<a href="http://www.keplerproject.org/compat/manual.html#configuration">
+Compat-5.1 configuration</a> section about how to install the compiled
+binary properly.
+The compiled binary should be copied to a directory in your
+<code>LUA_CPATH</code>.</p>
+
+<p>Windows users can use the binary version of LuaFileSystem
+(<code>lfs.dll</code>) available at
+<a href="http://luaforge.net/projects/luafilesystem/files">LuaForge</a>.</p>
+
+<h2><a name="reference"></a>Reference</h2>
+
+<p>
+LuaFileSystem offers the following functions:
+</p>
+
+<dl class="reference">
+ <dt><a name="attributes"></a><strong><code>lfs.attributes (filepath [, aname])</code></strong></dt>
+ <dd>Returns a table with the file attributes corresponding to
+ <code>filepath</code> (or <code>nil</code> followed by an error message
+ in case of error).
+ If the second optional argument is given, then only the value of the
+ named attribute is returned (this use is equivalent to
+ <code>lfs.attributes(filepath).aname</code>, but the table is not created
+ and only one attribute is retrieved from the O.S.).
+ The attributes are described as follows;
+ attribute <code>mode</code> is a string, all the others are numbers,
+ and the time related attributes use the same time reference of
+ <a href="http://www.lua.org/manual/5.0/manual.html#5.7"><code>os.time</code></a>:
+ <dl>
+ <dt><strong><code>dev</code></strong></dt>
+ <dd>on Unix systems, this represents the device that the inode resides on. On Windows systems,
+ represents the drive number of the disk containing the file</dd>
+
+ <dt><strong><code>ino</code></strong></dt>
+ <dd>on Unix systems, this represents the inode number. On Windows systems this has no meaning</dd>
+
+ <dt><strong><code>mode</code></strong></dt>
+ <dd>string representing the associated protection mode (the values could be
+ <code>file</code>, <code>directory</code>, <code>link</code>, <code>socket</code>,
+ <code>named pipe</code>, <code>char device</code>, <code>block device</code> or
+ <code>other</code>)</dd>
+
+ <dt><strong><code>nlink</code></strong></dt>
+ <dd>number of hard links to the file</dd>
+
+ <dt><strong><code>uid</code></strong></dt>
+ <dd>user-id of owner (Unix only, always 0 on Windows)</dd>
+
+ <dt><strong><code>gid</code></strong></dt>
+ <dd>group-id of owner (Unix only, always 0 on Windows)</dd>
+
+ <dt><strong><code>rdev</code></strong></dt>
+ <dd>on Unix systems, represents the device type, for special file inodes.
+ On Windows systems represents the same as <code>dev</code></dd>
+
+ <dt><strong><code>access</code></strong></dt>
+ <dd>time of last access</dd>
+
+ <dt><strong><code>modification</code></strong></dt>
+ <dd>time of last data modification</dd>
+
+ <dt><strong><code>change</code></strong></dt>
+ <dd>time of last file status change</dd>
+
+ <dt><strong><code>size</code></strong></dt>
+ <dd>file size, in bytes</dd>
+
+ <dt><strong><code>blocks</code></strong></dt>
+ <dd>block allocated for file; (Unix only)</dd>
+
+ <dt><strong><code>blksize</code></strong></dt>
+ <dd>optimal file system I/O blocksize; (Unix only)</dd>
+ </dl>
+ </dd>
+
+ <dt><a name="chdir"></a><strong><code>lfs.chdir (path)</code></strong></dt>
+ <dd>Changes the current working directory to the given
+ <code>path</code>.<br />
+ Returns <code>true</code> in case of success or <code>nil</code> plus an
+ error string.</dd>
+
+ <dt><a name="getcwd"></a><strong><code>lfs.currentdir ()</code></strong></dt>
+ <dd>Returns a string with the current working directory or <code>nil</code>
+ plus an error string.</dd>
+
+ <dt><a name="dir"></a><strong><code>lfs.dir (path)</code></strong></dt>
+ <dd>
+ Lua iterator over the entries of a given directory.
+ Each time the iterator is called it returns a string with an entry of the
+ directory; <code>nil</code> is returned when there is no more entries.
+ Raises an error if <code>path</code> is not a directory.
+ </dd>
+
+ <dt><a name="lock"></a><strong><code>lfs.lock (filehandle, mode[, start[, length]])</code></strong></dt>
+ <dd>Locks a file or a part of it. This function works on <em>open files</em>; the
+ file handle should be specified as the first argument.
+ The string <code>mode</code> could be either
+ <code>r</code> (for a read/shared lock) or <code>w</code> (for a
+ write/exclusive lock). The optional arguments <code>start</code>
+ and <code>length</code> can be used to specify a starting point and
+ its length; both should be numbers.<br />
+ Returns <code>true</code> if the operation was successful; in
+ case of error, it returns <code>nil</code> plus an error string.
+ </dd>
+
+ <dt><a name="mkdir"></a><strong><code>lfs.mkdir (dirname)</code></strong></dt>
+ <dd>Creates a new directory. The argument is the name of the new
+ directory.<br />
+ Returns <code>true</code> if the operation was successful;
+ in case of error, it returns <code>nil</code> plus an error string.
+ </dd>
+
+ <dt><a name="rmdir"></a><strong><code>lfs.rmdir (dirname)</code></strong></dt>
+ <dd>Removes an existing directory. The argument is the name of the directory.<br />
+ Returns <code>true</code> if the operation was successful;
+ in case of error, it returns <code>nil</code> plus an error string.</dd>
+
+ <dt><a name="touch"></a><strong><code>lfs.touch (filepath [, atime [, mtime]])</code></strong></dt>
+ <dd>Set access and modification times of a file. This function is
+ a bind to <code>utime</code> function. The first argument is the
+ filename, the second argument (<code>atime</code>) is the access time,
+ and the third argument (<code>mtime</code>) is the modification time.
+ Both times are provided in seconds (which should be generated with
+ Lua standard function <code>os.date</code>).
+ If the modification time is omitted, the access time provided is used;
+ if both times are omitted, the current time is used.<br />
+ Returns <code>true</code> if the operation was successful;
+ in case of error, it returns <code>nil</code> plus an error string.
+ </dd>
+
+ <dt><a name="unlock"></a><strong><code>lfs.unlock (filehandle[, start[, length]])</code></strong></dt>
+ <dd>Unlocks a file or a part of it. This function works on
+ <em>open files</em>; the file handle should be specified as the first
+ argument. The optional arguments <code>start</code> and
+ <code>length</code> can be used to specify a starting point and its
+ length; both should be numbers.<br />
+ Returns <code>true</code> if the operation was successful;
+ in case of error, it returns <code>nil</code> plus an error string.
+ </dd>
+</dl>
+
+</div> <!-- id="content" -->
+
+</div> <!-- id="main" -->
+
+<div id="about">
+ <p><a href="http://validator.w3.org/check?uri=referer">
+ <img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
+ <p><small>$Id: manual.html,v 1.30.2.1 2006/03/15 20:30:53 carregal Exp $</small></p>
+</div> <!-- id="about" -->
+
+</div> <!-- id="container" -->
+
+</body>
+</html>
diff --git a/Build/source/libs/luafilesystem/src/lfs.c b/Build/source/libs/luafilesystem/src/lfs.c
new file mode 100644
index 00000000000..ee2920412d1
--- /dev/null
+++ b/Build/source/libs/luafilesystem/src/lfs.c
@@ -0,0 +1,667 @@
+/*
+** LuaFileSystem
+** Copyright Kepler Project 2004-2006 (http://www.keplerproject.org/luafilesystem)
+**
+** File system manipulation library.
+** This library offers these functions:
+** lfs.attributes (filepath [, attributename])
+** lfs.chdir (path)
+** lfs.currentdir ()
+** lfs.dir (path)
+** lfs.lock (fh, mode)
+** lfs.mkdir (path)
+** lfs.rmdir (path)
+** lfs.touch (filepath [, atime [, mtime]])
+** lfs.unlock (fh)
+**
+** $Id: lfs.c,v 1.32 2006/03/14 13:39:38 tomas Exp $
+*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#include <io.h>
+#include <sys/locking.h>
+#include <sys/utime.h>
+#else
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <utime.h>
+#endif
+
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+/* #include "compat-5.1.h"*/
+
+#include "lfs.h"
+
+/* Define 'strerror' for systems that do not implement it */
+#ifdef NO_STRERROR
+#define strerror(_) "System unable to describe the error"
+#endif
+
+/* Define 'getcwd' for systems that do not implement it */
+#ifdef NO_GETCWD
+#define getcwd(p,s) NULL
+#define getcwd_error "Function 'getcwd' not provided by system"
+#else
+#define getcwd_error strerror(errno)
+#endif
+
+#define DIR_METATABLE "directory metatable"
+#define MAX_DIR_LENGTH 1023
+typedef struct dir_data {
+ int closed;
+#ifdef _WIN32
+ long hFile;
+ char pattern[MAX_DIR_LENGTH+1];
+#else
+ DIR *dir;
+#endif
+} dir_data;
+
+
+/*
+** This function changes the working (current) directory
+*/
+static int change_dir (lua_State *L) {
+ const char *path = luaL_checkstring(L, 1);
+ if (chdir(path)) {
+ lua_pushnil (L);
+ lua_pushfstring (L,"Unable to change working directory to '%s'\n%s\n",
+ path, chdir_error);
+ return 2;
+ } else {
+ lua_pushboolean (L, 1);
+ return 1;
+ }
+}
+
+/*
+** This function returns the current directory
+** If unable to get the current directory, it returns nil
+** and a string describing the error
+*/
+static int get_dir (lua_State *L) {
+ char path[255+2];
+ if (getcwd(path, 255) == NULL) {
+ lua_pushnil(L);
+ lua_pushstring(L, getcwd_error);
+ return 2;
+ }
+ else {
+ lua_pushstring(L, path);
+ return 1;
+ }
+}
+
+/*
+** Check if the given element on the stack is a file and returns it.
+*/
+static FILE *check_file (lua_State *L, int idx, const char *funcname) {
+ FILE **fh = (FILE **)luaL_checkudata (L, idx, "FILE*");
+ if (fh == NULL) {
+ luaL_error (L, "%s: not a file", funcname);
+ return 0;
+ } else if (*fh == NULL) {
+ luaL_error (L, "%s: closed file", funcname);
+ return 0;
+ } else
+ return *fh;
+}
+
+
+/*
+**
+*/
+static int _file_lock (lua_State *L, FILE *fh, const char *mode, const long start, long len, const char *funcname) {
+ int code;
+#ifdef _WIN32
+ /* lkmode valid values are:
+ LK_LOCK Locks the specified bytes. If the bytes cannot be locked, the program immediately tries again after 1 second. If, after 10 attempts, the bytes cannot be locked, the constant returns an error.
+ LK_NBLCK Locks the specified bytes. If the bytes cannot be locked, the constant returns an error.
+ LK_NBRLCK Same as _LK_NBLCK.
+ LK_RLCK Same as _LK_LOCK.
+ LK_UNLCK Unlocks the specified bytes, which must have been previously locked.
+
+ Regions should be locked only briefly and should be unlocked before closing a file or exiting the program.
+
+ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__locking.asp
+ */
+ int lkmode;
+ switch (*mode) {
+ case 'r': lkmode = LK_NBLCK; break;
+ case 'w': lkmode = LK_NBLCK; break;
+ case 'u': lkmode = LK_UNLCK; break;
+ default : return luaL_error (L, "%s: invalid mode", funcname);
+ }
+ if (!len) {
+ fseek (fh, 0L, SEEK_END);
+ len = ftell (fh);
+ }
+ fseek (fh, start, SEEK_SET);
+ code = _locking (fileno(fh), lkmode, len);
+#else
+ struct flock f;
+ switch (*mode) {
+ case 'w': f.l_type = F_WRLCK; break;
+ case 'r': f.l_type = F_RDLCK; break;
+ case 'u': f.l_type = F_UNLCK; break;
+ default : return luaL_error (L, "%s: invalid mode", funcname);
+ }
+ f.l_whence = SEEK_SET;
+ f.l_start = (off_t)start;
+ f.l_len = (off_t)len;
+ code = fcntl (fileno(fh), F_SETLK, &f);
+#endif
+ return (code != -1);
+}
+
+
+/*
+** Locks a file.
+** @param #1 File handle.
+** @param #2 String with lock mode ('w'rite, 'r'ead).
+** @param #3 Number with start position (optional).
+** @param #4 Number with length (optional).
+*/
+static int file_lock (lua_State *L) {
+ FILE *fh = check_file (L, 1, "lock");
+ const char *mode = luaL_checkstring (L, 2);
+ const long start = luaL_optlong (L, 3, 0);
+ long len = luaL_optlong (L, 4, 0);
+ if (_file_lock (L, fh, mode, start, len, "lock")) {
+ lua_pushboolean (L, 1);
+ return 1;
+ } else {
+ lua_pushnil (L);
+ lua_pushfstring (L, "%s", strerror(errno));
+ return 2;
+ }
+}
+
+
+/*
+** Unlocks a file.
+** @param #1 File handle.
+** @param #2 Number with start position (optional).
+** @param #3 Number with length (optional).
+*/
+static int file_unlock (lua_State *L) {
+ FILE *fh = check_file (L, 1, "unlock");
+ const long start = luaL_optlong (L, 2, 0);
+ long len = luaL_optlong (L, 3, 0);
+ if (_file_lock (L, fh, "u", start, len, "unlock")) {
+ lua_pushboolean (L, 1);
+ return 1;
+ } else {
+ lua_pushnil (L);
+ lua_pushfstring (L, "%s", strerror(errno));
+ return 2;
+ }
+}
+
+
+static int make_dir (lua_State *L) {
+ const char *path = luaL_checkstring (L, 1);
+ int fail;
+#ifdef _WIN32
+ int oldmask = umask (0);
+ fail = _mkdir (path);
+#else
+ mode_t oldmask = umask( (mode_t)0 );
+ fail = mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
+ S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH );
+#endif
+ if (fail) {
+ lua_pushnil (L);
+ lua_pushfstring (L, "%s", strerror(errno));
+ return 2;
+ }
+ umask (oldmask);
+ lua_pushboolean (L, 1);
+ return 1;
+}
+
+/*
+** Removes a directory.
+** @param #1 Directory path.
+*/
+static int remove_dir (lua_State *L) {
+ const char *path = luaL_checkstring (L, 1);
+ int fail;
+
+ fail = rmdir (path);
+
+ if (fail) {
+ lua_pushnil (L);
+ lua_pushfstring (L, "%s", strerror(errno));
+ return 2;
+ }
+ lua_pushboolean (L, 1);
+ return 1;
+}
+
+/*
+** Directory iterator
+*/
+static int dir_iter (lua_State *L) {
+#ifdef _WIN32
+ struct _finddata_t c_file;
+#endif
+ dir_data *d = (dir_data *)lua_touserdata (L, lua_upvalueindex (1));
+ luaL_argcheck (L, !d->closed, 1, "closed directory");
+#ifdef _WIN32
+ if (d->hFile == 0L) { /* first entry */
+ if ((d->hFile = _findfirst (d->pattern, &c_file)) == -1L) {
+ lua_pushnil (L);
+ lua_pushstring (L, strerror (errno));
+ return 2;
+ } else {
+ lua_pushstring (L, c_file.name);
+ return 1;
+ }
+ } else { /* next entry */
+ if (_findnext (d->hFile, &c_file) == -1L) {
+ /* no more entries => close directory */
+ _findclose (d->hFile);
+ d->closed = 1;
+ return 0;
+ } else {
+ lua_pushstring (L, c_file.name);
+ return 1;
+ }
+ }
+#else
+ struct dirent *entry;
+ if ((entry = readdir (d->dir)) != NULL) {
+ lua_pushstring (L, entry->d_name);
+ return 1;
+ } else {
+ /* no more entries => close directory */
+ closedir (d->dir);
+ d->closed = 1;
+ return 0;
+ }
+#endif
+}
+
+
+/*
+** Closes directory iterators
+*/
+static int dir_close (lua_State *L) {
+ dir_data *d = (dir_data *)lua_touserdata (L, 1);
+#ifdef _WIN32
+ if (!d->closed && d->hFile) {
+ _findclose (d->hFile);
+ d->closed = 1;
+ }
+#else
+ if (!d->closed && d->dir) {
+ closedir (d->dir);
+ d->closed = 1;
+ }
+#endif
+ return 0;
+}
+
+
+/*
+** Factory of directory iterators
+*/
+static int dir_iter_factory (lua_State *L) {
+ const char *path = luaL_checkstring (L, 1);
+ dir_data *d = (dir_data *) lua_newuserdata (L, sizeof(dir_data));
+ d->closed = 0;
+#ifdef _WIN32
+ d->hFile = 0L;
+ luaL_getmetatable (L, DIR_METATABLE);
+ lua_setmetatable (L, -2);
+ if (strlen(path) > MAX_DIR_LENGTH)
+ luaL_error (L, "path too long: %s", path);
+ else
+ sprintf (d->pattern, "%s/*", path);
+#else
+ luaL_getmetatable (L, DIR_METATABLE);
+ lua_setmetatable (L, -2);
+ d->dir = opendir (path);
+ if (d->dir == NULL)
+ luaL_error (L, "cannot open %s: %s", path, strerror (errno));
+#endif
+ lua_pushcclosure (L, dir_iter, 1);
+ return 1;
+}
+
+
+/*
+** Creates directory metatable.
+*/
+static int dir_create_meta (lua_State *L) {
+ luaL_newmetatable (L, DIR_METATABLE);
+ /* set its __gc field */
+ lua_pushstring (L, "__gc");
+ lua_pushcfunction (L, dir_close);
+ lua_settable (L, -3);
+
+ return 1;
+}
+
+
+#ifdef _WIN32
+ #ifndef S_ISDIR
+ #define S_ISDIR(mode) (mode&_S_IFDIR)
+ #endif
+ #ifndef S_ISREG
+ #define S_ISREG(mode) (mode&_S_IFREG)
+ #endif
+ #ifndef S_ISLNK
+ #define S_ISLNK(mode) (0)
+ #endif
+ #ifndef S_ISSOCK
+ #define S_ISSOCK(mode) (0)
+ #endif
+ #ifndef S_ISFIFO
+ #define S_ISFIFO(mode) (0)
+ #endif
+ #ifndef S_ISCHR
+ #define S_ISCHR(mode) (mode&_S_IFCHR)
+ #endif
+ #ifndef S_ISBLK
+ #define S_ISBLK(mode) (0)
+ #endif
+#endif
+/*
+** Convert the inode protection mode to a string.
+*/
+#ifdef _WIN32
+static const char *mode2string (unsigned short mode) {
+#else
+static const char *mode2string (mode_t mode) {
+#endif
+ if ( S_ISREG(mode) )
+ return "file";
+ else if ( S_ISDIR(mode) )
+ return "directory";
+ else if ( S_ISLNK(mode) )
+ return "link";
+ else if ( S_ISSOCK(mode) )
+ return "socket";
+ else if ( S_ISFIFO(mode) )
+ return "named pipe";
+ else if ( S_ISCHR(mode) )
+ return "char device";
+ else if ( S_ISBLK(mode) )
+ return "block device";
+ else
+ return "other";
+}
+
+
+/*
+** Convert the inode protection mode to a permission list.
+*/
+
+#ifdef _WIN32
+static const char *perm2string (unsigned short mode) {
+ char perms[10] = "---------\0";
+ if (mode & _S_IREAD)
+ { perms[0] = 'r'; perms[3] = 'r'; perms[6] = 'r'; }
+ if (mode & _S_IWRITE)
+ { perms[1] = 'w'; perms[4] = 'w'; perms[7] = 'w'; }
+ if (mode & _S_IEXEC)
+ { perms[2] = 'x'; perms[5] = 'x'; perms[8] = 'x'; }
+ return perms;
+}
+#else
+static const char *perm2string (mode_t mode) {
+ char perms[10] = "---------\0";
+ if (mode & S_IRUSR) perms[0] = 'r';
+ if (mode & S_IWUSR) perms[1] = 'w';
+ if (mode & S_IXUSR) perms[2] = 'x';
+ if (mode & S_IRGRP) perms[3] = 'r';
+ if (mode & S_IWGRP) perms[4] = 'w';
+ if (mode & S_IXGRP) perms[5] = 'x';
+ if (mode & S_IROTH) perms[6] = 'r';
+ if (mode & S_IWOTH) perms[7] = 'w';
+ if (mode & S_IXOTH) perms[8] = 'x';
+ return perms;
+}
+#endif
+
+
+/*
+** Set access time and modification values for file
+*/
+static int file_utime (lua_State *L) {
+ const char *file = luaL_checkstring (L, 1);
+ struct utimbuf utb, *buf;
+
+ if (lua_gettop (L) == 1) /* set to current date/time */
+ buf = NULL;
+ else {
+ utb.actime = (time_t)luaL_optnumber (L, 2, 0);
+ utb.modtime = (time_t)luaL_optnumber (L, 3, utb.actime);
+ buf = &utb;
+ }
+ if (utime (file, buf)) {
+ lua_pushnil (L);
+ lua_pushfstring (L, "%s", strerror (errno));
+ return 2;
+ }
+ lua_pushboolean (L, 1);
+ return 1;
+}
+
+
+/* inode protection mode */
+static void push_st_mode (lua_State *L, struct stat *info) {
+ lua_pushstring (L, mode2string (info->st_mode));
+}
+/* device inode resides on */
+static void push_st_dev (lua_State *L, struct stat *info) {
+ lua_pushnumber (L, (lua_Number)info->st_dev);
+}
+/* inode's number */
+static void push_st_ino (lua_State *L, struct stat *info) {
+ lua_pushnumber (L, (lua_Number)info->st_ino);
+}
+/* number of hard links to the file */
+static void push_st_nlink (lua_State *L, struct stat *info) {
+ lua_pushnumber (L, (lua_Number)info->st_nlink);
+}
+/* user-id of owner */
+static void push_st_uid (lua_State *L, struct stat *info) {
+ lua_pushnumber (L, (lua_Number)info->st_uid);
+}
+/* group-id of owner */
+static void push_st_gid (lua_State *L, struct stat *info) {
+ lua_pushnumber (L, (lua_Number)info->st_gid);
+}
+/* device type, for special file inode */
+static void push_st_rdev (lua_State *L, struct stat *info) {
+ lua_pushnumber (L, (lua_Number)info->st_rdev);
+}
+/* time of last access */
+static void push_st_atime (lua_State *L, struct stat *info) {
+ lua_pushnumber (L, info->st_atime);
+}
+/* time of last data modification */
+static void push_st_mtime (lua_State *L, struct stat *info) {
+ lua_pushnumber (L, info->st_mtime);
+}
+/* time of last file status change */
+static void push_st_ctime (lua_State *L, struct stat *info) {
+ lua_pushnumber (L, info->st_ctime);
+}
+/* file size, in bytes */
+static void push_st_size (lua_State *L, struct stat *info) {
+ lua_pushnumber (L, (lua_Number)info->st_size);
+}
+/* permssions string */
+static void push_st_perm (lua_State *L, struct stat *info) {
+ lua_pushstring (L, perm2string (info->st_mode));
+}
+
+#ifndef _WIN32
+/* blocks allocated for file */
+static void push_st_blocks (lua_State *L, struct stat *info) {
+ lua_pushnumber (L, (lua_Number)info->st_blocks);
+}
+/* optimal file system I/O blocksize */
+static void push_st_blksize (lua_State *L, struct stat *info) {
+ lua_pushnumber (L, (lua_Number)info->st_blksize);
+}
+#endif
+
+typedef void (*_push_function) (lua_State *L, struct stat *info);
+
+struct _stat_members {
+ const char *name;
+ _push_function push;
+};
+
+struct _stat_members members[] = {
+ { "mode", push_st_mode },
+ { "permissions", push_st_perm },
+ { "dev", push_st_dev },
+ { "ino", push_st_ino },
+ { "nlink", push_st_nlink },
+ { "uid", push_st_uid },
+ { "gid", push_st_gid },
+ { "rdev", push_st_rdev },
+ { "access", push_st_atime },
+ { "modification", push_st_mtime },
+ { "change", push_st_ctime },
+ { "size", push_st_size },
+#ifndef _WIN32
+ { "blocks", push_st_blocks },
+ { "blksize", push_st_blksize },
+#endif
+ { NULL, NULL }
+};
+
+/*
+** Get file information
+*/
+static int file_info (lua_State *L) {
+ int i;
+ struct stat info;
+ const char *file = luaL_checkstring (L, 1);
+
+ if (stat(file, &info)) {
+ lua_pushnil (L);
+ lua_pushfstring (L, "cannot obtain information from file `%s'", file);
+ return 2;
+ }
+ if (lua_isstring (L, 2)) {
+ int v;
+ const char *member = lua_tostring (L, 2);
+ if (strcmp (member, "mode") == 0) v = 0;
+#ifndef _WIN32
+ else if (strcmp (member, "blksize") == 0) v = 12;
+#endif
+ else /* look for member */
+ for (v = 1; members[v].name; v++)
+ if (*members[v].name == *member)
+ break;
+ /* push member value and return */
+ members[v].push (L, &info);
+ return 1;
+ } else if (!lua_istable (L, 2))
+ /* creates a table if none is given */
+ lua_newtable (L);
+ /* stores all members in table on top of the stack */
+ for (i = 0; members[i].name; i++) {
+ lua_pushstring (L, members[i].name);
+ members[i].push (L, &info);
+ lua_rawset (L, -3);
+ }
+ return 1;
+}
+
+
+/*
+** Get file information
+*/
+static int file_is_directory (lua_State *L) {
+ struct stat info;
+ const char *file = luaL_checkstring (L, 1);
+
+ if (stat(file, &info)) {
+ lua_pushnil (L);
+ lua_pushfstring (L, "cannot obtain information from file `%s'", file);
+ return 2;
+ }
+ if ( S_ISDIR(info.st_mode) )
+ lua_pushboolean (L, 1);
+ else
+ lua_pushboolean (L, 0);
+
+ return 1;
+}
+
+static int file_is_file (lua_State *L) {
+ struct stat info;
+ const char *file = luaL_checkstring (L, 1);
+
+ if (stat(file, &info)) {
+ lua_pushnil (L);
+ lua_pushfstring (L, "cannot obtain information from file `%s'", file);
+ return 2;
+ }
+ if ( S_ISREG(info.st_mode) )
+ lua_pushboolean (L, 1);
+ else
+ lua_pushboolean (L, 0);
+
+ return 1;
+}
+
+
+
+/*
+** Assumes the table is on top of the stack.
+*/
+static void set_info (lua_State *L) {
+ lua_pushliteral (L, "_COPYRIGHT");
+ lua_pushliteral (L, "Copyright (C) 2003-2006 Kepler Project");
+ lua_settable (L, -3);
+ lua_pushliteral (L, "_DESCRIPTION");
+ lua_pushliteral (L, "LuaFileSystem is a Lua library developed to complement the set of functions related to file systems offered by the standard Lua distribution");
+ lua_settable (L, -3);
+ lua_pushliteral (L, "_VERSION");
+ lua_pushliteral (L, "LuaFileSystem 1.2");
+ lua_settable (L, -3);
+}
+
+
+static const struct luaL_reg fslib[] = {
+ {"attributes", file_info},
+ {"isdir", file_is_directory },
+ {"isfile", file_is_file },
+ {"chdir", change_dir},
+ {"currentdir", get_dir},
+ {"dir", dir_iter_factory},
+ {"lock", file_lock},
+ {"mkdir", make_dir},
+ {"rmdir", remove_dir},
+ {"touch", file_utime},
+ {"unlock", file_unlock},
+ {NULL, NULL},
+};
+
+int luaopen_lfs (lua_State *L) {
+ dir_create_meta (L);
+ luaL_openlib (L, "lfs", fslib, 0);
+ set_info (L);
+ return 1;
+}
diff --git a/Build/source/libs/luafilesystem/src/lfs.h b/Build/source/libs/luafilesystem/src/lfs.h
new file mode 100644
index 00000000000..62ae79fa96c
--- /dev/null
+++ b/Build/source/libs/luafilesystem/src/lfs.h
@@ -0,0 +1,16 @@
+/*
+** LuaFileSystem
+** Copyright Kepler Project 2004-2006 (http://www.keplerproject.org/luafilesystem)
+**
+** $Id: lfs.h,v 1.3 2006/03/10 23:37:32 carregal Exp $
+*/
+
+/* Define 'chdir' for systems that do not implement it */
+#ifdef NO_CHDIR
+#define chdir(p) (-1)
+#define chdir_error "Function 'chdir' not provided by system"
+#else
+#define chdir_error strerror(errno)
+#endif
+
+int luaopen_lfs (lua_State *L);
diff --git a/Build/source/libs/luafilesystem/tests/test.lua b/Build/source/libs/luafilesystem/tests/test.lua
new file mode 100644
index 00000000000..66ec52a2f8b
--- /dev/null
+++ b/Build/source/libs/luafilesystem/tests/test.lua
@@ -0,0 +1,80 @@
+#!/usr/local/bin/lua50
+
+local tmp = "/tmp"
+local sep = "/"
+local upper = ".."
+
+require"lfs"
+
+function attrdir (path)
+ for file in lfs.dir(path) do
+ if file ~= "." and file ~= ".." then
+ local f = path..sep..file
+ print ("\t=> "..f.." <=")
+ local attr = lfs.attributes (f)
+ assert (type(attr) == "table")
+ if attr.mode == "directory" then
+ attrdir (f)
+ else
+ for name, value in pairs(attr) do
+ print (name, value)
+ end
+ end
+ end
+ end
+end
+
+-- Checking changing directories
+local current = assert (lfs.currentdir())
+local reldir = string.gsub (current, "^.*%"..sep.."([^"..sep.."])$", "%1")
+assert (lfs.chdir (upper), "could not change to upper directory")
+assert (lfs.chdir (reldir), "could not change back to current directory")
+assert (lfs.currentdir() == current, "error trying to change directories")
+assert (lfs.chdir ("this couldn't be an actual directory") == nil, "could change to a non-existent directory")
+
+-- Changing creating and removing directories
+local tmpdir = tmp..sep.."lfs_tmp_dir"
+local tmpfile = tmpdir..sep.."tmp_file"
+assert (lfs.mkdir (tmpdir), "could not make a new directory")
+local attrib, errmsg = lfs.attributes (tmpdir)
+if not attrib then
+ error ("could not get attributes of file `"..tmpdir.."':\n"..errmsg)
+end
+local f = io.open(tmpfile, "w")
+f:close()
+
+-- Change access time
+assert (lfs.touch (tmpfile, 86401))
+local new_att = assert (lfs.attributes (tmpfile))
+assert (new_att.access == 86401, "could not set access time")
+assert (new_att.modification == 86401, "could not set modification time")
+
+-- Change access and modification time
+assert (lfs.touch (tmpfile, 86403, 86402))
+local new_att = assert (lfs.attributes (tmpfile))
+assert (new_att.access == 86403, "could not set access time")
+assert (new_att.modification == 86402, "could not set modification time")
+
+-- Restore access time to current value
+assert (lfs.touch (tmpfile))
+new_att = assert (lfs.attributes (tmpfile))
+assert (new_att.access == attrib.access)
+assert (new_att.modification == attrib.modification)
+
+-- Remove new file and directory
+assert (os.remove (tmpfile), "could not remove new file")
+assert (lfs.rmdir (tmpdir), "could not remove new directory")
+assert (lfs.mkdir (tmpdir..sep.."lfs_tmp_dir") == nil, "could create a directory inside a non-existent one")
+
+-- Trying to get attributes of a non-existent file
+assert (lfs.attributes ("this couldn't be an actual file") == nil, "could get attributes of a non-existent file")
+assert (type(lfs.attributes (upper)) == "table", "couldn't get attributes of upper directory")
+
+-- Stressing directory iterator
+count = 0
+for i = 1, 4000 do
+ for file in lfs.dir (tmp) do
+ count = count + 1
+ end
+end
+print"Ok!"
diff --git a/Build/source/libs/luafilesystem/vc6/lfs.def b/Build/source/libs/luafilesystem/vc6/lfs.def
new file mode 100644
index 00000000000..55ec688d3c3
--- /dev/null
+++ b/Build/source/libs/luafilesystem/vc6/lfs.def
@@ -0,0 +1,5 @@
+LIBRARY lfs.dll
+DESCRIPTION "LuaFileSystem"
+VERSION 1.2
+EXPORTS
+luaopen_lfs
diff --git a/Build/source/libs/luafilesystem/vc6/luafilesystem.dsw b/Build/source/libs/luafilesystem/vc6/luafilesystem.dsw
new file mode 100644
index 00000000000..b4bb4b310f6
--- /dev/null
+++ b/Build/source/libs/luafilesystem/vc6/luafilesystem.dsw
@@ -0,0 +1,33 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "luafilesystem_dll"=.\luafilesystem_dll.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+ begin source code control
+ luafilesystem
+ ..
+ end source code control
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/Build/source/libs/luafilesystem/vc6/luafilesystem_dll.dsp b/Build/source/libs/luafilesystem/vc6/luafilesystem_dll.dsp
new file mode 100644
index 00000000000..efe6c720b6c
--- /dev/null
+++ b/Build/source/libs/luafilesystem/vc6/luafilesystem_dll.dsp
@@ -0,0 +1,127 @@
+# Microsoft Developer Studio Project File - Name="luafilesystem_dll" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=luafilesystem_dll - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "luafilesystem_dll.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "luafilesystem_dll.mak" CFG="luafilesystem_dll - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "luafilesystem_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "luafilesystem_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "luafilesystem_dll"
+# PROP Scc_LocalPath ".."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "luafilesystem_dll - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../lib/vc6"
+# PROP Intermediate_Dir "luafilesystem_dll/Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUAFILESYSTEM_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../external-src/lua50/include" /I "../../compat/src" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUAFILESYSTEM_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x416 /d "NDEBUG"
+# ADD RSC /l 0x416 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 lua50.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../bin/vc6/lfs.dll" /libpath:"../../external-src/lua50/lib/dll"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=cd ../bin/vc6 zip.exe luafilesystem-1.2-win32.zip lfs.dll
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "luafilesystem_dll - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../lib/vc6"
+# PROP Intermediate_Dir "luafilesystem_dll/Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUAFILESYSTEM_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../external-src/lua50/include" /I "../../compat/src" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUAFILESYSTEM_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x416 /d "_DEBUG"
+# ADD RSC /l 0x416 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 lua50.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"../bin/vc6/lfsd.dll" /pdbtype:sept /libpath:"../../external-src/lua50/lib/dll"
+
+!ENDIF
+
+# Begin Target
+
+# Name "luafilesystem_dll - Win32 Release"
+# Name "luafilesystem_dll - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\..\compat\src\compat-5.1.c"
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\lfs.def
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE="..\..\compat\src\compat-5.1.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lfs.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/Build/source/libs/luafontforge/Makefile b/Build/source/libs/luafontforge/Makefile
new file mode 100644
index 00000000000..976dff883e3
--- /dev/null
+++ b/Build/source/libs/luafontforge/Makefile
@@ -0,0 +1,24 @@
+# $Id$
+
+srcdir=../../../src/libs/luafontforge
+
+FF_LIB=ffdummies.o luafflib.o
+
+MY_CFLAGS=-g -O2 -Wall -DFONTFORGE_CONFIG_NO_WINDOWING_UI=1 -DLUA_FF_LIB=1 $(CFLAGS) $(XCFLAGS)
+
+.PHONY: newfile
+
+fontforge: $(FF_LIB) newfile
+ rm -f libff.a
+ cd fontforge && $(MAKE)
+ cd Unicode && $(MAKE)
+ sh -c "ar cru libff.a fontforge/*.o Unicode/*.o $(FF_LIB)"
+ ranlib libff.a
+
+%.o: $(srcdir)/src/%.c
+ gcc $(MY_CFLAGS) -I$(srcdir)/../lua51 -I$(srcdir)/fontforge/inc -I$(srcdir)/fontforge/fontforge -c $< -o $@
+
+clean:
+ rm -f libff.a $(FF_LIB)
+ cd fontforge; $(MAKE) clean
+ cd Unicode; $(MAKE) clean \ No newline at end of file
diff --git a/Build/source/libs/luafontforge/fontforge/AUTHORS b/Build/source/libs/luafontforge/fontforge/AUTHORS
new file mode 100644
index 00000000000..9b6fb61e4f4
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/AUTHORS
@@ -0,0 +1 @@
+George Williams
diff --git a/Build/source/libs/luafontforge/fontforge/INSTALL b/Build/source/libs/luafontforge/fontforge/INSTALL
new file mode 100644
index 00000000000..b42a17ac464
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/INSTALL
@@ -0,0 +1,182 @@
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
diff --git a/Build/source/libs/luafontforge/fontforge/LICENSE b/Build/source/libs/luafontforge/fontforge/LICENSE
new file mode 100644
index 00000000000..e8c4d01364b
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/LICENSE
@@ -0,0 +1,28 @@
+PfaEdit is copyright (C) 2000,2001,2002,2003 by George Williams
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The configure script is subject to the GNU public license. See the file
+COPYING.
diff --git a/Build/source/libs/luafontforge/fontforge/Makefile b/Build/source/libs/luafontforge/fontforge/Makefile
new file mode 100644
index 00000000000..b79b39e8842
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/Makefile
@@ -0,0 +1,112 @@
+prefix = /usr/local
+exec_prefix = ${prefix}
+
+bindir = ${exec_prefix}/bin
+libdir = ${exec_prefix}/lib
+mandir = ${prefix}/man
+includedir = ${prefix}/include
+sharedir = $(prefix)/share/fontforge
+docdir = $(prefix)/share/doc/fontforge
+localedir = $(prefix)/share/locale
+
+srcdir = .
+top_builddir = .
+
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+
+all: fontforge
+
+libs: libgunicode libgdraw
+
+fontforge: libgunicode libgdraw pos
+ ( cd fontforge ; $(MAKE) )
+
+libgunicode:
+ ( cd Unicode ; $(MAKE) )
+
+libgdraw:
+ ( cd gdraw ; $(MAKE) )
+
+pos:
+ -ln -s $(srcdir)/po/*.po po
+ ( cd po ; $(MAKE) )
+
+clean:
+ ( cd fontforge ; $(MAKE) clean )
+ ( cd Unicode ; $(MAKE) clean )
+ ( cd gdraw ; $(MAKE) clean )
+ ( cd plugins ; $(MAKE) clean )
+ -( cd po ; rm *.mo )
+ -rm -rf .libs
+
+distclean cleaner:
+ ( cd fontforge ; $(MAKE) distclean )
+ ( cd Unicode ; $(MAKE) distclean )
+ ( cd gdraw ; $(MAKE) distclean )
+ ( cd plugins ; $(MAKE) distclean )
+ -( cd po ; rm *.mo Makefile* )
+ -rm -rf .libs
+ -rm Makefile config.cache config.log config.status libtool fontforge.pc systemspecific
+
+install_libs: libs
+# You may need to be root to do the install
+ mkdir -p $(libdir)
+ #-rm $(libdir)/libgdraw.so* $(libdir)/libgunicode.so.*
+ $(LIBTOOL) --mode=install $(INSTALL) -c libgunicode.la $(libdir)/libgunicode.la
+ $(LIBTOOL) --mode=install $(INSTALL) -c libgdraw.la $(libdir)/libgdraw.la
+ $(LIBTOOL) --mode=finish $(libdir)
+ mkdir -p $(libdir)/pkgconfig
+ $(INSTALL_DATA) fontforge.pc $(libdir)/pkgconfig
+
+install_docs:
+ mkdir -p $(docdir)
+ mkdir -p $(docdir)/flags $(docdir)/ja
+#explicit use of sh to make sure we don't invoke csh with different "if" syntax
+ -sh -c "if test -d $(srcdir)/htdocs/ja >/dev/null ; then mkdir -p $(docdir)/ja ; fi"
+ -$(INSTALL_DATA) $(srcdir)/htdocs/*.{html,png,gif,pdf} $(docdir)
+ -$(INSTALL_DATA) $(srcdir)/htdocs/flags/* $(docdir)/flags
+ -$(INSTALL_DATA) $(srcdir)/htdocs/ja/* $(docdir)/ja
+
+install_po:
+ ( cd po ; $(MAKE) install )
+
+install: $(sharedir) all install_libs install_po
+# You may need to be root to do the install
+ mkdir -p $(bindir)
+ mkdir -p $(mandir)/man1
+ mkdir -p $(sharedir)
+ $(LIBTOOL) --mode=install $(INSTALL) -c fontforge/fontforge $(bindir)
+ $(LIBTOOL) --mode=install $(INSTALL) -c fontforge/sfddiff $(bindir)
+ $(LIBTOOL) --mode=install $(INSTALL) -c fontforge/fontimage $(bindir)
+# -rm -f $(bindir)/pfaedit
+# (cd $(bindir) ; ln -s fontforge pfaedit)
+# $(INSTALL_DATA) fontforge/pfaedit-*.ui $(sharedir)
+#The next line will fail for most installs. If you have downloaded the cidmaps
+# this will install them. If you haven't it won't. You only need the cidmaps
+# if you are editing CID keyed files (and even then you can live without them
+ -$(INSTALL_DATA) $(srcdir)/cidmap/*.cidmap $(sharedir) >/dev/null 2>&1
+ $(INSTALL_DATA) $(srcdir)/fontforge/fontforge.1 $(mandir)/man1
+ $(INSTALL_DATA) $(srcdir)/fontforge/sfddiff.1 $(mandir)/man1
+ $(INSTALL_DATA) $(srcdir)/fontforge/fontimage.1 $(mandir)/man1
+#explicit use of sh to make sure we don't invoke csh with different "if" syntax
+ sh -c "if test -d $(srcdir)/htdocs >/dev/null ; then $(MAKE) install_docs ; fi"
+ sh < systemspecific
+
+uninstall:
+ -rm $(bindir)/fontforge
+ -rm $(bindir)/sfddiff
+ -rm $(bindir)/fontimage
+ -rm $(sharedir)/pfaedit-*.ui
+ -rm $(localedir)/*/LC_MESSAGES/FontForge.mo
+ -rm $(mandir)/man1/fontimage.1
+ -rm $(mandir)/man1/fontforge.1
+ -rm $(mandir)/man1/sfddiff.1
+ -rm $(libdir)/libgdraw.*
+ -rm $(libdir)/libgunicode.*
+ -rm $(sharedir)/*.cidmap
+ -rm -rf $(docdir)/*
+
+$(sharedir):
+ mkdir -p $(sharedir)
diff --git a/Build/source/libs/luafontforge/fontforge/Unicode/Makefile b/Build/source/libs/luafontforge/fontforge/Unicode/Makefile
new file mode 100644
index 00000000000..7fb7c8060b0
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/Unicode/Makefile
@@ -0,0 +1,15 @@
+
+top_srcdir = ../../../../src/libs/luafontforge/fontforge
+srcdir = $(top_srcdir)/Unicode
+
+CC = gcc
+
+OBJECTS = alphabet.o char.o memory.o cjk.o ustring.o gwwiconv.o
+
+CFLAGS = -I$(top_srcdir)/inc -Wall -g -O2 -DLUA_FF_LIB=1 $(XCFLAGS)
+
+all: $(OBJECTS)
+
+%.o: $(srcdir)/%.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
diff --git a/Build/source/libs/luafontforge/fontforge/Unicode/alphabet.c b/Build/source/libs/luafontforge/fontforge/Unicode/alphabet.c
new file mode 100644
index 00000000000..166a33208a7
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/Unicode/alphabet.c
@@ -0,0 +1,3348 @@
+#include <chardata.h>
+
+const unsigned char c_allzeros[256] = { 0 };
+
+const unichar_t unicode_from_i8859_1[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
+ 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
+ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
+ 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
+ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
+ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
+ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
+ 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
+};
+
+static const unsigned char i8859_1_from_unicode_0[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+static const unsigned char * const i8859_1_from_unicode_[] = {
+ i8859_1_from_unicode_0
+};
+
+struct charmap i8859_1_from_unicode = { 0, 0, (unsigned char **) i8859_1_from_unicode_, (unichar_t *) unicode_from_i8859_1 };
+
+const unichar_t unicode_from_i8859_2[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7,
+ 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b,
+ 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7,
+ 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c,
+ 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,
+ 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
+ 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,
+ 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
+ 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,
+ 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
+ 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,
+ 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9
+};
+
+static const unsigned char i8859_2_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0xa7, 0xa8, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00,
+ 0xb0, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xc1, 0xc2, 0x00, 0xc4, 0x00, 0x00, 0xc7, 0x00, 0xc9, 0x00, 0xcb, 0x00, 0xcd, 0xce, 0x00,
+ 0x00, 0x00, 0x00, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, 0x00, 0x00, 0xda, 0x00, 0xdc, 0xdd, 0x00, 0xdf,
+ 0x00, 0xe1, 0xe2, 0x00, 0xe4, 0x00, 0x00, 0xe7, 0x00, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0xee, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0xf4, 0x00, 0xf6, 0xf7, 0x00, 0x00, 0xfa, 0x00, 0xfc, 0xfd, 0x00, 0x00
+};
+
+static const unsigned char i8859_2_from_unicode_1[] = {
+ 0x00, 0x00, 0xc3, 0xe3, 0xa1, 0xb1, 0xc6, 0xe6, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0xcf, 0xef,
+ 0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xea, 0xcc, 0xec, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xe5, 0x00, 0x00, 0xa5, 0xb5, 0x00,
+ 0x00, 0xa3, 0xb3, 0xd1, 0xf1, 0x00, 0x00, 0xd2, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xd5, 0xf5, 0x00, 0x00, 0xc0, 0xe0, 0x00, 0x00, 0xd8, 0xf8, 0xa6, 0xb6, 0x00, 0x00, 0xaa, 0xba,
+ 0xa9, 0xb9, 0xde, 0xfe, 0xab, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0xf9,
+ 0xdb, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0xbc, 0xaf, 0xbf, 0xae, 0xbe, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_2_from_unicode_2[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xff, 0x00, 0xb2, 0x00, 0xbd, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const i8859_2_from_unicode_[] = {
+ i8859_2_from_unicode_0,
+ i8859_2_from_unicode_1,
+ i8859_2_from_unicode_2
+};
+
+struct charmap i8859_2_from_unicode = { 0, 2, (unsigned char **) i8859_2_from_unicode_, (unichar_t *) unicode_from_i8859_2 };
+
+const unichar_t unicode_from_i8859_3[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x0126, 0x02d8, 0x00a3, 0x00a4, 0x0000, 0x0124, 0x00a7,
+ 0x00a8, 0x0130, 0x015e, 0x011e, 0x0134, 0x00ad, 0x0000, 0x017b,
+ 0x00b0, 0x0127, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x0125, 0x00b7,
+ 0x00b8, 0x0131, 0x015f, 0x011f, 0x0135, 0x00bd, 0x0000, 0x017c,
+ 0x00c0, 0x00c1, 0x00c2, 0x0000, 0x00c4, 0x010a, 0x0108, 0x00c7,
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+ 0x0000, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x0120, 0x00d6, 0x00d7,
+ 0x011c, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x016c, 0x015c, 0x00df,
+ 0x00e0, 0x00e1, 0x00e2, 0x0000, 0x00e4, 0x010b, 0x0109, 0x00e7,
+ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x0000, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x0121, 0x00f6, 0x00f7,
+ 0x011d, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x016d, 0x015d, 0x02d9
+};
+
+static const unsigned char i8859_3_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x00, 0x00, 0xa3, 0xa4, 0x00, 0x00, 0xa7, 0xa8, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00,
+ 0xb0, 0x00, 0xb2, 0xb3, 0xb4, 0xb5, 0x00, 0xb7, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00,
+ 0xc0, 0xc1, 0xc2, 0x00, 0xc4, 0x00, 0x00, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, 0x00, 0xd9, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0x00, 0xe4, 0x00, 0x00, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0x00, 0xf6, 0xf7, 0x00, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_3_from_unicode_1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xe6, 0xc5, 0xe5, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xf8, 0xab, 0xbb,
+ 0xd5, 0xf5, 0x00, 0x00, 0xa6, 0xb6, 0xa1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa9, 0xb9, 0x00, 0x00, 0xac, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xfe, 0xaa, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, 0xfd, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0xbf, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_3_from_unicode_2[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const i8859_3_from_unicode_[] = {
+ i8859_3_from_unicode_0,
+ i8859_3_from_unicode_1,
+ i8859_3_from_unicode_2
+};
+
+struct charmap i8859_3_from_unicode = { 0, 2, (unsigned char **) i8859_3_from_unicode_, (unichar_t *) unicode_from_i8859_3 };
+
+const unichar_t unicode_from_i8859_4[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7,
+ 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af,
+ 0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7,
+ 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b,
+ 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e,
+ 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a,
+ 0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
+ 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df,
+ 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f,
+ 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b,
+ 0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
+ 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9
+};
+
+static const unsigned char i8859_4_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0xa7, 0xa8, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0xaf,
+ 0xb0, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0x00, 0x00, 0xc9, 0x00, 0xcb, 0x00, 0xcd, 0xce, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0x00, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf,
+ 0x00, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0x00, 0x00, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0xee, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0x00, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_4_from_unicode_1[] = {
+ 0xc0, 0xe0, 0x00, 0x00, 0xa1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0x00, 0x00,
+ 0xd0, 0xf0, 0xaa, 0xba, 0x00, 0x00, 0xcc, 0xec, 0xca, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xab, 0xbb, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xb5, 0xcf, 0xef, 0x00, 0x00, 0xc7, 0xe7,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xf3, 0xa2, 0x00, 0x00, 0xa6, 0xb6, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf1, 0x00, 0x00, 0x00, 0xbd, 0xbf, 0xd2, 0xf2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa9, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xac, 0xbc, 0xdd, 0xfd, 0xde, 0xfe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xd9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0xbe, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_4_from_unicode_2[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const i8859_4_from_unicode_[] = {
+ i8859_4_from_unicode_0,
+ i8859_4_from_unicode_1,
+ i8859_4_from_unicode_2
+};
+
+struct charmap i8859_4_from_unicode = { 0, 2, (unsigned char **) i8859_4_from_unicode_, (unichar_t *) unicode_from_i8859_4 };
+
+const unichar_t unicode_from_i8859_5[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
+ 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x00ad, 0x040e, 0x040f,
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+ 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+ 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
+ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+ 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
+ 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
+ 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x00a7, 0x045e, 0x045f
+};
+
+static const unsigned char i8859_5_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_5_from_unicode_4[] = {
+ 0x00, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0x00, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0xfe, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_5_from_unicode_21[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const i8859_5_from_unicode_[] = {
+ i8859_5_from_unicode_0,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ i8859_5_from_unicode_4,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ i8859_5_from_unicode_21
+};
+
+struct charmap i8859_5_from_unicode = { 0, 33, (unsigned char **) i8859_5_from_unicode_, (unichar_t *) unicode_from_i8859_5 };
+
+const unichar_t unicode_from_i8859_6[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667,
+ 0x0668, 0x0669, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x0000, 0x0000, 0x0000, 0x00a4, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x060c, 0x00ad, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x061b, 0x0000, 0x0000, 0x0000, 0x061f,
+ 0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
+ 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f,
+ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637,
+ 0x0638, 0x0639, 0x063a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647,
+ 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f,
+ 0x0650, 0x0651, 0x0652, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned char i8859_6_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_6_from_unicode_6[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xbf,
+ 0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const i8859_6_from_unicode_[] = {
+ i8859_6_from_unicode_0,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ i8859_6_from_unicode_6
+};
+
+struct charmap i8859_6_from_unicode = { 0, 6, (unsigned char **) i8859_6_from_unicode_, (unichar_t *) unicode_from_i8859_6 };
+
+const unichar_t unicode_from_i8859_7[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x02bd, 0x02bc, 0x00a3, 0x0000, 0x0000, 0x00a6, 0x00a7,
+ 0x00a8, 0x00a9, 0x0000, 0x00ab, 0x00ac, 0x00ad, 0x0000, 0x2015,
+ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x0385, 0x0386, 0x00b7,
+ 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f,
+ 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+ 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
+ 0x03a0, 0x03a1, 0x0000, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
+ 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af,
+ 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
+ 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
+ 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7,
+ 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0000
+};
+
+static const unsigned char i8859_7_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x00, 0x00, 0xa3, 0x00, 0x00, 0xa6, 0xa7, 0xa8, 0xa9, 0x00, 0xab, 0xac, 0xad, 0x00, 0x00,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0xbb, 0x00, 0xbd, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_7_from_unicode_2[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xa1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_7_from_unicode_3[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xb4, 0xb5, 0xb6, 0x00, 0xb8, 0xb9, 0xba, 0x00, 0xbc, 0x00, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0x00, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_7_from_unicode_20[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const i8859_7_from_unicode_[] = {
+ i8859_7_from_unicode_0,
+ c_allzeros,
+ i8859_7_from_unicode_2,
+ i8859_7_from_unicode_3,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ i8859_7_from_unicode_20
+};
+
+struct charmap i8859_7_from_unicode = { 0, 32, (unsigned char **) i8859_7_from_unicode_, (unichar_t *) unicode_from_i8859_7 };
+
+const unichar_t unicode_from_i8859_8[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x0000, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
+ 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x203e,
+ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
+ 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2017,
+ 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7,
+ 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df,
+ 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7,
+ 0x05e8, 0x05e9, 0x05ea, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned char i8859_8_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x00, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0x00,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0x00, 0xbb, 0xbc, 0xbd, 0xbe, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_8_from_unicode_5[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_8_from_unicode_20[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const i8859_8_from_unicode_[] = {
+ i8859_8_from_unicode_0,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ i8859_8_from_unicode_5,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ i8859_8_from_unicode_20
+};
+
+struct charmap i8859_8_from_unicode = { 0, 32, (unsigned char **) i8859_8_from_unicode_, (unichar_t *) unicode_from_i8859_8 };
+
+const unichar_t unicode_from_i8859_9[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
+ 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
+ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
+ 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
+ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+ 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df,
+ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
+ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
+ 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff
+};
+
+static const unsigned char i8859_9_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0xff
+};
+
+static const unsigned char i8859_9_from_unicode_1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xf0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xdd, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xfe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const i8859_9_from_unicode_[] = {
+ i8859_9_from_unicode_0,
+ i8859_9_from_unicode_1
+};
+
+struct charmap i8859_9_from_unicode = { 0, 1, (unsigned char **) i8859_9_from_unicode_, (unichar_t *) unicode_from_i8859_9 };
+
+const unichar_t unicode_from_i8859_10[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x0104, 0x0112, 0x0122, 0x012a, 0x0128, 0x0136, 0x00a7,
+ 0x013b, 0x0110, 0x0160, 0x0166, 0x017d, 0x00ad, 0x016a, 0x014a,
+ 0x00b0, 0x0105, 0x0113, 0x0123, 0x012b, 0x0129, 0x0137, 0x0000,
+ 0x013c, 0x0111, 0x0161, 0x0167, 0x017e, 0x00af, 0x016b, 0x014b,
+ 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e,
+ 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0112, 0x00cd, 0x00ce, 0x00cf,
+ 0x00d0, 0x0145, 0x014c, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x0168,
+ 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
+ 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f,
+ 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0113, 0x00ed, 0x00ee, 0x00ef,
+ 0x00f0, 0x0146, 0x014d, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x0169,
+ 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x0138
+};
+
+static const unsigned char i8859_10_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0xbd,
+ 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0x00, 0x00, 0xc9, 0x00, 0xcb, 0x00, 0xcd, 0xce, 0xcf,
+ 0xd0, 0x00, 0x00, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, 0xd8, 0x00, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0x00, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0x00, 0x00, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0xee, 0xef,
+ 0xf0, 0x00, 0x00, 0xf3, 0xf4, 0xf5, 0xf6, 0x00, 0xf8, 0x00, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0x00
+};
+
+static const unsigned char i8859_10_from_unicode_1[] = {
+ 0xc0, 0xe0, 0x00, 0x00, 0xa1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0x00, 0x00,
+ 0xa9, 0xb9, 0xcc, 0xec, 0x00, 0x00, 0x00, 0x00, 0xca, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xa3, 0xb3, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xb5, 0xa4, 0xb4, 0x00, 0x00, 0xc7, 0xe7,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0xb6, 0xff, 0x00, 0x00, 0xa8, 0xb8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf1, 0x00, 0x00, 0x00, 0xaf, 0xbf, 0xd2, 0xf2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xaa, 0xba, 0x00, 0x00, 0x00, 0x00, 0xab, 0xbb, 0xd7, 0xf7, 0xae, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xd9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0xbc, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const i8859_10_from_unicode_[] = {
+ i8859_10_from_unicode_0,
+ i8859_10_from_unicode_1
+};
+
+struct charmap i8859_10_from_unicode = { 0, 1, (unsigned char **) i8859_10_from_unicode_, (unichar_t *) unicode_from_i8859_10 };
+
+const unichar_t unicode_from_i8859_11[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
+ 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
+ 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
+ 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
+ 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
+ 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
+ 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
+ 0x0e38, 0x0e39, 0x0e3a, 0x0000, 0x0020, 0x0000, 0x0000, 0x0e3f,
+ 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
+ 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
+ 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
+ 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned char i8859_11_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xdc, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_11_from_unicode_e[] = {
+ 0x00, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0x00, 0x00, 0x00, 0x00, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const i8859_11_from_unicode_[] = {
+ i8859_11_from_unicode_0,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ i8859_11_from_unicode_e
+};
+
+struct charmap i8859_11_from_unicode = { 0, 14, (unsigned char **) i8859_11_from_unicode_, (unichar_t *) unicode_from_i8859_11 };
+
+const unichar_t unicode_from_i8859_13[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x201d, 0x00a2, 0x00a3, 0x00a4, 0x201e, 0x00a6, 0x00a7,
+ 0x00d8, 0x00a9, 0x0157, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6,
+ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x201c, 0x00b5, 0x00b6, 0x00b7,
+ 0x00f8, 0x00b9, 0x0000, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6,
+ 0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112,
+ 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b,
+ 0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7,
+ 0x0172, 0x0141, 0x00da, 0x00db, 0x00dc, 0x017b, 0x017d, 0x00df,
+ 0x0105, 0x012e, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113,
+ 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c,
+ 0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7,
+ 0x0173, 0x0142, 0x00fa, 0x00fb, 0x00fc, 0x017c, 0x017e, 0x2019
+};
+
+static const unsigned char i8859_13_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x00, 0xa2, 0xa3, 0xa4, 0x00, 0xa6, 0xa7, 0x00, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0x00,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0x00, 0xb5, 0xb6, 0xb7, 0x00, 0xb9, 0x00, 0xbb, 0xbc, 0xbd, 0xbe, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc4, 0xc5, 0xaf, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd3, 0x00, 0xd5, 0xd6, 0xd7, 0xa8, 0x00, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf,
+ 0x00, 0x00, 0x00, 0x00, 0xe4, 0xe5, 0xbf, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0x00, 0xf5, 0xf6, 0xf7, 0xb8, 0x00, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_13_from_unicode_1[] = {
+ 0xc2, 0xe2, 0x00, 0x00, 0xc0, 0xe0, 0xc3, 0xe3, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0x00, 0x00,
+ 0x00, 0x00, 0xc7, 0xe7, 0x00, 0x00, 0xcb, 0xeb, 0xc6, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xcc, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xee, 0x00, 0x00, 0xe1, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xed, 0x00, 0x00, 0x00, 0xcf, 0xef, 0x00, 0x00, 0x00,
+ 0x00, 0xd9, 0xf9, 0xd1, 0xf1, 0xd2, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xf4, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xd8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xea, 0xdd, 0xfd, 0xde, 0xfe, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_13_from_unicode_20[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xb4, 0xa1, 0xa5, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const i8859_13_from_unicode_[] = {
+ i8859_13_from_unicode_0,
+ i8859_13_from_unicode_1,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ i8859_13_from_unicode_20
+};
+
+struct charmap i8859_13_from_unicode = { 0, 32, (unsigned char **) i8859_13_from_unicode_, (unichar_t *) unicode_from_i8859_13 };
+
+const unichar_t unicode_from_i8859_14[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x1e02, 0x1e03, 0x00a3, 0x010a, 0x010b, 0x1e0a, 0x00a7,
+ 0x1e80, 0x00a9, 0x1e82, 0x1e0b, 0x1ef2, 0x00ad, 0x00ae, 0x0178,
+ 0x1e1e, 0x1e1f, 0x0120, 0x0121, 0x1e40, 0x1e41, 0x00b6, 0x1e56,
+ 0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61,
+ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+ 0x0174, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x1e6a,
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x0176, 0x00df,
+ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
+ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x0175, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x1e6b,
+ 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x0177, 0x00ff
+};
+
+static const unsigned char i8859_14_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa7, 0x00, 0xa9, 0x00, 0x00, 0x00, 0xad, 0xae, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0x00, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0x00, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0x00, 0xff
+};
+
+static const unsigned char i8859_14_from_unicode_1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0xa5, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xb2, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xd0, 0xf0, 0xde, 0xfe, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_14_from_unicode_1e[] = {
+ 0x00, 0x00, 0xa1, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0xab, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xb1,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xb4, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbb, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xf7, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa8, 0xb8, 0xaa, 0xba, 0xbd, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xac, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const i8859_14_from_unicode_[] = {
+ i8859_14_from_unicode_0,
+ i8859_14_from_unicode_1,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ i8859_14_from_unicode_1e
+};
+
+struct charmap i8859_14_from_unicode = { 0, 30, (unsigned char **) i8859_14_from_unicode_, (unichar_t *) unicode_from_i8859_14 };
+
+const unichar_t unicode_from_i8859_15[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0x0160, 0x00a7,
+ 0x0161, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
+ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x017d, 0x00b5, 0x00b6, 0x00b7,
+ 0x017e, 0x00b9, 0x00ba, 0x00bb, 0x0152, 0x0153, 0x0178, 0x00bf,
+ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
+ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
+ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
+ 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
+};
+
+static const unsigned char i8859_15_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0x00, 0xa5, 0x00, 0xa7, 0x00, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0x00, 0xb5, 0xb6, 0xb7, 0x00, 0xb9, 0xba, 0xbb, 0x00, 0x00, 0x00, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+static const unsigned char i8859_15_from_unicode_1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xbc, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa6, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xb4, 0xb8, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char i8859_15_from_unicode_20[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const i8859_15_from_unicode_[] = {
+ i8859_15_from_unicode_0,
+ i8859_15_from_unicode_1,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ i8859_15_from_unicode_20
+};
+
+struct charmap i8859_15_from_unicode = { 0, 32, (unsigned char **) i8859_15_from_unicode_, (unichar_t *) unicode_from_i8859_15 };
+
+const unichar_t unicode_from_koi8_r[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
+ 0x2500, 0x2502, 0x250c, 0x2510, 0x2514, 0x2518, 0x251c, 0x2524,
+ 0x252c, 0x2534, 0x253c, 0x2580, 0x2584, 0x2588, 0x258c, 0x2590,
+ 0x2591, 0x2592, 0x2593, 0x2320, 0x25a0, 0x2219, 0x221a, 0x2248,
+ 0x2264, 0x2265, 0x00a0, 0x2321, 0x00b0, 0x00b2, 0x00b7, 0x00f7,
+ 0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556,
+ 0x2557, 0x2558, 0x2559, 0x255a, 0x255b, 0x255c, 0x255d, 0x255e,
+ 0x255f, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565,
+ 0x2566, 0x2567, 0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x00a9,
+ 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
+ 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e,
+ 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
+ 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a,
+ 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
+ 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e,
+ 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
+ 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a
+};
+
+static const unsigned char koi8_r_from_unicode_0[] = {
+ 0x7f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char koi8_r_from_unicode_4[] = {
+ 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe1, 0xe2, 0xf7, 0xe7, 0xe4, 0xe5, 0xf6, 0xfa, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
+ 0xf2, 0xf3, 0xf4, 0xf5, 0xe6, 0xe8, 0xe3, 0xfe, 0xfb, 0xfd, 0xff, 0xf9, 0xf8, 0xfc, 0xe0, 0xf1,
+ 0xc1, 0xc2, 0xd7, 0xc7, 0xc4, 0xc5, 0xd6, 0xda, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
+ 0xd2, 0xd3, 0xd4, 0xd5, 0xc6, 0xc8, 0xc3, 0xde, 0xdb, 0xdd, 0xdf, 0xd9, 0xd8, 0xdc, 0xc0, 0xd1,
+ 0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char koi8_r_from_unicode_22[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x98, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char koi8_r_from_unicode_23[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x93, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char koi8_r_from_unicode_25[] = {
+ 0x80, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00,
+ 0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xa1, 0xa2, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
+ 0xb1, 0xb2, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x8b, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
+ 0x8f, 0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const koi8_r_from_unicode_[] = {
+ koi8_r_from_unicode_0,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ koi8_r_from_unicode_4,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ koi8_r_from_unicode_22,
+ koi8_r_from_unicode_23,
+ c_allzeros,
+ koi8_r_from_unicode_25
+};
+
+struct charmap koi8_r_from_unicode = { 0, 37, (unsigned char **) koi8_r_from_unicode_, (unichar_t *) unicode_from_koi8_r };
+
+const unichar_t unicode_from_jis201[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x00a5, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x203e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x0000, 0xff61, 0xff62, 0xff63, 0xff64, 0xff65, 0xff66, 0xff67,
+ 0xff68, 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f,
+ 0xff70, 0xff71, 0xff72, 0xff73, 0xff74, 0xff75, 0xff76, 0xff77,
+ 0xff78, 0xff79, 0xff7a, 0xff7b, 0xff7c, 0xff7d, 0xff7e, 0xff7f,
+ 0xff80, 0xff81, 0xff82, 0xff83, 0xff84, 0xff85, 0xff86, 0xff87,
+ 0xff88, 0xff89, 0xff8a, 0xff8b, 0xff8c, 0xff8d, 0xff8e, 0xff8f,
+ 0xff90, 0xff91, 0xff92, 0xff93, 0xff94, 0xff95, 0xff96, 0xff97,
+ 0xff98, 0xff99, 0xff9a, 0xff9b, 0xff9c, 0xff9d, 0xff9e, 0xff9f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned char jis201_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char jis201_from_unicode_20[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char jis201_from_unicode_ff[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const jis201_from_unicode_[] = {
+ jis201_from_unicode_0,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ jis201_from_unicode_20,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ jis201_from_unicode_ff
+};
+
+struct charmap jis201_from_unicode = { 0, 255, (unsigned char **) jis201_from_unicode_, (unichar_t *) unicode_from_jis201 };
+
+const unichar_t unicode_from_win[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
+ 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
+ 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178,
+ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
+ 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
+ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
+ 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
+ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
+ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
+ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
+ 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
+};
+
+static const unsigned char win_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+static const unsigned char win_from_unicode_1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x8c, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x8a, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char win_from_unicode_2[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char win_from_unicode_20[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, 0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00,
+ 0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char win_from_unicode_21[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const win_from_unicode_[] = {
+ win_from_unicode_0,
+ win_from_unicode_1,
+ win_from_unicode_2,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ win_from_unicode_20,
+ win_from_unicode_21
+};
+
+struct charmap win_from_unicode = { 0, 33, (unsigned char **) win_from_unicode_, (unichar_t *) unicode_from_win };
+
+const unichar_t unicode_from_mac[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
+ 0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
+ 0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
+ 0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
+ 0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
+ 0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8,
+ 0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211,
+ 0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x03a9, 0x00e6, 0x00f8,
+ 0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
+ 0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153,
+ 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
+ 0x00ff, 0x0178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
+ 0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1,
+ 0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4,
+ 0xf8ff, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc,
+ 0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7
+};
+
+static const unsigned char mac_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xca, 0xc1, 0xa2, 0xa3, 0x00, 0xb4, 0x00, 0xa4, 0xac, 0xa9, 0xbb, 0xc7, 0xc2, 0x00, 0xa8, 0xf8,
+ 0xa1, 0xb1, 0x00, 0x00, 0xab, 0xb5, 0xa6, 0xe1, 0xfc, 0x00, 0xbc, 0xc8, 0x00, 0x00, 0x00, 0xc0,
+ 0xcb, 0xe7, 0xe5, 0xcc, 0x80, 0x81, 0xae, 0x82, 0xe9, 0x83, 0xe6, 0xe8, 0xed, 0xea, 0xeb, 0xec,
+ 0x00, 0x84, 0xf1, 0xee, 0xef, 0xcd, 0x85, 0x00, 0xaf, 0xf4, 0xf2, 0xf3, 0x86, 0x00, 0x00, 0xa7,
+ 0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0xbe, 0x8d, 0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
+ 0x00, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0xd6, 0xbf, 0x9d, 0x9c, 0x9e, 0x9f, 0x00, 0x00, 0xd8
+};
+
+static const unsigned char mac_from_unicode_1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xce, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char mac_from_unicode_2[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xfa, 0xfb, 0xfe, 0xf7, 0xfd, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char mac_from_unicode_3[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char mac_from_unicode_20[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd0, 0xd1, 0x00, 0x00, 0x00, 0xd4, 0xd5, 0xe2, 0x00, 0xd2, 0xd3, 0xe3, 0x00,
+ 0xa0, 0xe0, 0xa5, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char mac_from_unicode_21[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char mac_from_unicode_22[] = {
+ 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8,
+ 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xb0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xad, 0x00, 0x00, 0x00, 0xb2, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char mac_from_unicode_25[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char mac_from_unicode_f8[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0
+};
+
+static const unsigned char mac_from_unicode_fb[] = {
+ 0x00, 0xde, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const mac_from_unicode_[] = {
+ mac_from_unicode_0,
+ mac_from_unicode_1,
+ mac_from_unicode_2,
+ mac_from_unicode_3,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ mac_from_unicode_20,
+ mac_from_unicode_21,
+ mac_from_unicode_22,
+ c_allzeros,
+ c_allzeros,
+ mac_from_unicode_25,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ mac_from_unicode_f8,
+ c_allzeros,
+ c_allzeros,
+ mac_from_unicode_fb
+};
+
+struct charmap mac_from_unicode = { 0, 251, (unsigned char **) mac_from_unicode_, (unichar_t *) unicode_from_mac };
+
+const unichar_t unicode_from_MacSymbol[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x2200, 0x0023, 0x2203, 0x0025, 0x0026, 0x220d,
+ 0x0028, 0x0029, 0x2217, 0x002b, 0x002c, 0x2212, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x2245, 0x0391, 0x0392, 0x03a7, 0x0394, 0x0395, 0x03a6, 0x0393,
+ 0x0397, 0x0399, 0x03d1, 0x039a, 0x039b, 0x039c, 0x039d, 0x039f,
+ 0x03a0, 0x0398, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03c2, 0x03a9,
+ 0x039e, 0x03a8, 0x0396, 0x005b, 0x2234, 0x005d, 0x22a5, 0x005f,
+ 0xf8e5, 0x03b1, 0x03b2, 0x03c7, 0x03b4, 0x03b5, 0x03c6, 0x03b3,
+ 0x03b7, 0x03b9, 0x03d5, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03bf,
+ 0x03c0, 0x03b8, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03d6, 0x03c9,
+ 0x03be, 0x03c8, 0x03b6, 0x007b, 0x007c, 0x007d, 0x223c, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x0000, 0x03d2, 0x2032, 0x2264, 0x2044, 0x221e, 0x0192, 0x2663,
+ 0x2666, 0x2665, 0x2660, 0x2194, 0x2190, 0x2191, 0x2192, 0x2193,
+ 0x00b0, 0x00b1, 0x2033, 0x2265, 0x00d7, 0x221d, 0x2202, 0x2022,
+ 0x00f7, 0x2260, 0x2261, 0x2248, 0x2026, 0xf8e6, 0xf8e7, 0x21b5,
+ 0x2135, 0x2111, 0x211c, 0x2118, 0x2297, 0x2295, 0x2205, 0x2229,
+ 0x222a, 0x2283, 0x2287, 0x2284, 0x2282, 0x2286, 0x2208, 0x2209,
+ 0x2220, 0x2207, 0x00ae, 0x00a9, 0x2122, 0x220f, 0x221a, 0x22c5,
+ 0x00ac, 0x2227, 0x2228, 0x21d4, 0x21d0, 0x21d1, 0x21d2, 0x21d3,
+ 0x22c4, 0x2329, 0xf8e8, 0xf8e9, 0xf8ea, 0x2211, 0xf8eb, 0xf8ec,
+ 0xf8ed, 0xf8ee, 0xf8ef, 0xf8f0, 0xf8f1, 0xf8f2, 0xf8f3, 0xf8f4,
+ 0xf8ff, 0x232a, 0x222b, 0x2320, 0xf8f5, 0x2321, 0xf8f6, 0xf8f7,
+ 0xf8f8, 0xf8f9, 0xf8fa, 0xf8fb, 0xf8fc, 0xf8fd, 0xf8fe, 0x02c7
+};
+
+static const unsigned char MacSymbol_from_unicode_0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x21, 0x00, 0x23, 0x00, 0x25, 0x26, 0x00, 0x28, 0x29, 0x00, 0x2b, 0x2c, 0x00, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x5d, 0x00, 0x5f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0xd8, 0x00, 0xd2, 0x00,
+ 0xb0, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char MacSymbol_from_unicode_1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char MacSymbol_from_unicode_2[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char MacSymbol_from_unicode_3[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x41, 0x42, 0x47, 0x44, 0x45, 0x5a, 0x48, 0x51, 0x49, 0x4b, 0x4c, 0x4d, 0x4e, 0x58, 0x4f,
+ 0x50, 0x52, 0x00, 0x53, 0x54, 0x55, 0x46, 0x43, 0x59, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x61, 0x62, 0x67, 0x64, 0x65, 0x7a, 0x68, 0x71, 0x69, 0x6b, 0x6c, 0x6d, 0x6e, 0x78, 0x6f,
+ 0x70, 0x72, 0x56, 0x73, 0x74, 0x75, 0x66, 0x63, 0x79, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x4a, 0xa1, 0x00, 0x00, 0x6a, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char MacSymbol_from_unicode_20[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xa2, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char MacSymbol_from_unicode_21[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xac, 0xad, 0xae, 0xaf, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xdc, 0xdd, 0xde, 0xdf, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char MacSymbol_from_unicode_22[] = {
+ 0x22, 0x00, 0xb6, 0x24, 0x00, 0xc6, 0x00, 0xd1, 0xce, 0xcf, 0x00, 0x00, 0x00, 0x27, 0x00, 0xd5,
+ 0x00, 0xe5, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0xd6, 0x00, 0x00, 0xb5, 0xa5, 0x00,
+ 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0xda, 0xc7, 0xc8, 0xf2, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xb9, 0xba, 0x00, 0x00, 0xa3, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xcc, 0xc9, 0xcb, 0x00, 0xcd, 0xca, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0xd7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char MacSymbol_from_unicode_23[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf3, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char MacSymbol_from_unicode_26[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xaa, 0x00, 0x00, 0xa7, 0x00, 0xa9, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char MacSymbol_from_unicode_f8[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xbd, 0xbe, 0xe2, 0xe3, 0xe4, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf4, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xf0
+};
+
+static const unsigned char * const MacSymbol_from_unicode_[] = {
+ MacSymbol_from_unicode_0,
+ MacSymbol_from_unicode_1,
+ MacSymbol_from_unicode_2,
+ MacSymbol_from_unicode_3,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ MacSymbol_from_unicode_20,
+ MacSymbol_from_unicode_21,
+ MacSymbol_from_unicode_22,
+ MacSymbol_from_unicode_23,
+ c_allzeros,
+ c_allzeros,
+ MacSymbol_from_unicode_26,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ c_allzeros,
+ MacSymbol_from_unicode_f8
+};
+
+struct charmap MacSymbol_from_unicode = { 0, 248, (unsigned char **) MacSymbol_from_unicode_, (unichar_t *) unicode_from_MacSymbol };
+
+const unichar_t unicode_from_ZapfDingbats[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x2701, 0x2702, 0x2703, 0x2704, 0x260e, 0x2706, 0x2707,
+ 0x2708, 0x2709, 0x261b, 0x261e, 0x270c, 0x270d, 0x270e, 0x270f,
+ 0x2710, 0x2711, 0x2712, 0x2713, 0x2714, 0x2715, 0x2716, 0x2717,
+ 0x2718, 0x2719, 0x271a, 0x271b, 0x271c, 0x271d, 0x271e, 0x271f,
+ 0x2720, 0x2721, 0x2722, 0x2723, 0x2724, 0x2725, 0x2726, 0x2727,
+ 0x2605, 0x2729, 0x272a, 0x272b, 0x272c, 0x272d, 0x272e, 0x272f,
+ 0x2730, 0x2731, 0x2732, 0x2733, 0x2734, 0x2735, 0x2736, 0x2737,
+ 0x2738, 0x2739, 0x273a, 0x273b, 0x273c, 0x273d, 0x273e, 0x273f,
+ 0x2740, 0x2741, 0x2742, 0x2743, 0x2744, 0x2745, 0x2746, 0x2747,
+ 0x2748, 0x2749, 0x274a, 0x274b, 0x25cf, 0x274d, 0x25a0, 0x274f,
+ 0x2750, 0x2751, 0x2752, 0x25b2, 0x25bc, 0x25c6, 0x2756, 0x25d7,
+ 0x2758, 0x2759, 0x275a, 0x275b, 0x275c, 0x275d, 0x275e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x0000, 0x2761, 0x2762, 0x2763, 0x2764, 0x2765, 0x2766, 0x2767,
+ 0x2663, 0x2666, 0x2665, 0x2660, 0x2460, 0x2461, 0x2462, 0x2463,
+ 0x2464, 0x2465, 0x2465, 0x2466, 0x2467, 0x2468, 0x2469, 0x2777,
+ 0x2778, 0x2779, 0x277a, 0x277b, 0x277c, 0x277d, 0x277e, 0x277f,
+ 0x2780, 0x2781, 0x2782, 0x2783, 0x2784, 0x2785, 0x2786, 0x2787,
+ 0x2788, 0x2789, 0x278a, 0x278b, 0x278c, 0x278d, 0x278e, 0x278f,
+ 0x2790, 0x2791, 0x2792, 0x2793, 0x2794, 0x2192, 0x2194, 0x2195,
+ 0x2798, 0x2799, 0x279a, 0x279b, 0x279c, 0x279d, 0x279e, 0x279f,
+ 0x27a0, 0x27a1, 0x27a2, 0x27a3, 0x27a4, 0x27a5, 0x27a6, 0x27a7,
+ 0x27a8, 0x27a9, 0x27aa, 0x27ab, 0x27ac, 0x27ad, 0x27ae, 0x27af,
+ 0x0000, 0x27b1, 0x27b2, 0x27b3, 0x27b4, 0x27b5, 0x27b6, 0x27b7,
+ 0x27b8, 0x27b9, 0x27ba, 0x27bb, 0x27bc, 0x27bd, 0x27be, 0x27bf
+};
+
+static const unsigned char ZapfDingbats_from_unicode_21[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xd5, 0x00, 0xd6, 0xd7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char ZapfDingbats_from_unicode_24[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char ZapfDingbats_from_unicode_25[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char ZapfDingbats_from_unicode_26[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2b, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xab, 0x00, 0x00, 0xa8, 0x00, 0xaa, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char ZapfDingbats_from_unicode_27[] = {
+ 0x00, 0x21, 0x22, 0x23, 0x24, 0x00, 0x26, 0x27, 0x28, 0x29, 0x00, 0x00, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x00, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x00, 0x6d, 0x00, 0x6f,
+ 0x70, 0x71, 0x72, 0x00, 0x00, 0x00, 0x76, 0x00, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
+ 0x00, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0x00, 0x00, 0x00, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char * const ZapfDingbats_from_unicode_[] = {
+ ZapfDingbats_from_unicode_21,
+ c_allzeros,
+ c_allzeros,
+ ZapfDingbats_from_unicode_24,
+ ZapfDingbats_from_unicode_25,
+ ZapfDingbats_from_unicode_26,
+ ZapfDingbats_from_unicode_27
+};
+
+struct charmap ZapfDingbats_from_unicode = { 33, 39, (unsigned char **) ZapfDingbats_from_unicode_, (unichar_t *) unicode_from_ZapfDingbats };
+
+unichar_t *unicode_from_alphabets[]={
+ (unichar_t *) unicode_from_win, 0,0,
+ (unichar_t *) unicode_from_i8859_1,
+ (unichar_t *) unicode_from_i8859_2,
+ (unichar_t *) unicode_from_i8859_3,
+ (unichar_t *) unicode_from_i8859_4,
+ (unichar_t *) unicode_from_i8859_5,
+ (unichar_t *) unicode_from_i8859_6,
+ (unichar_t *) unicode_from_i8859_7,
+ (unichar_t *) unicode_from_i8859_8,
+ (unichar_t *) unicode_from_i8859_9,
+ (unichar_t *) unicode_from_i8859_10,
+ (unichar_t *) unicode_from_i8859_11,
+ (unichar_t *) unicode_from_i8859_13,
+ (unichar_t *) unicode_from_i8859_14,
+ (unichar_t *) unicode_from_i8859_15,
+ (unichar_t *) unicode_from_koi8_r,
+ (unichar_t *) unicode_from_jis201,
+ (unichar_t *) unicode_from_win,
+ (unichar_t *) unicode_from_mac,
+ (unichar_t *) unicode_from_MacSymbol,
+ (unichar_t *) unicode_from_ZapfDingbats,
+ (unichar_t *) unicode_from_i8859_1, /* Place holder for user-defined map */
+ 0
+};
+
+struct charmap *alphabets_from_unicode[]={ 0,0,0,
+ &i8859_1_from_unicode,
+ &i8859_2_from_unicode,
+ &i8859_3_from_unicode,
+ &i8859_4_from_unicode,
+ &i8859_5_from_unicode,
+ &i8859_6_from_unicode,
+ &i8859_7_from_unicode,
+ &i8859_8_from_unicode,
+ &i8859_9_from_unicode,
+ &i8859_10_from_unicode,
+ &i8859_11_from_unicode,
+ &i8859_13_from_unicode,
+ &i8859_14_from_unicode,
+ &i8859_15_from_unicode,
+ &koi8_r_from_unicode,
+ &jis201_from_unicode,
+ &win_from_unicode,
+ &mac_from_unicode,
+ &MacSymbol_from_unicode,
+ &ZapfDingbats_from_unicode,
+ &i8859_1_from_unicode, /* Place holder for user-defined map*/
+ 0
+};
diff --git a/Build/source/libs/luafontforge/fontforge/Unicode/char.c b/Build/source/libs/luafontforge/fontforge/Unicode/char.c
new file mode 100644
index 00000000000..58efa6426de
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/Unicode/char.c
@@ -0,0 +1,103 @@
+/* Copyright (C) 2000-2002 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <utype.h>
+#include "ustring.h"
+
+#ifdef LUA_FF_LIB
+extern int unic_tolower(int);
+#define Tolower unic_tolower
+#else
+#define Tolower tolower
+#endif
+
+char *strstart(const char *initial, const char *full) {
+ int ch1, ch2;
+ for (;;) {
+ ch1 = *initial++; ch2 = *full++ ;
+ if ( ch1=='\0' )
+return( (char *) full );
+ if ( ch1!=ch2 || ch1=='\0' )
+return(NULL);
+ }
+}
+
+char *strstartmatch(const char *initial, const char *full) {
+ int ch1, ch2;
+ for (;;) {
+ ch1 = *initial++; ch2 = *full++ ;
+ if ( ch1=='\0' )
+return( (char *) full );
+ ch1 = Tolower(ch1);
+ ch2 = Tolower(ch2);
+ if ( ch1!=ch2 || ch1=='\0' )
+return(NULL);
+ }
+}
+
+int strmatch(const char *str1, const char *str2) {
+ int ch1, ch2;
+ for (;;) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ ch1 = Tolower(ch1);
+ ch2 = Tolower(ch2);
+ if ( ch1!=ch2 || ch1=='\0' )
+return(ch1-ch2);
+ }
+}
+
+int strnmatch(const char *str1, const char *str2, int n) {
+ int ch1, ch2;
+ for (;n-->0;) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ ch1 = Tolower(ch1);
+ ch2 = Tolower(ch2);
+ if ( ch1!=ch2 || ch1=='\0' )
+return(ch1-ch2);
+ }
+return(0);
+}
+
+char *strstrmatch(const char *longer, const char *substr) {
+ int ch1, ch2;
+ const char *lpt, *str1, *str2;
+
+ for ( lpt=longer; *lpt!='\0'; ++lpt ) {
+ str1 = lpt; str2 = substr;
+ for (;;) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ ch1 = Tolower(ch1);
+ ch2 = Tolower(ch2);
+ if ( ch2=='\0' )
+return((char *) lpt);
+ if ( ch1!=ch2 )
+ break;
+ }
+ }
+return( NULL );
+}
diff --git a/Build/source/libs/luafontforge/fontforge/Unicode/cjk.c b/Build/source/libs/luafontforge/fontforge/Unicode/cjk.c
new file mode 100644
index 00000000000..f3362ad43db
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/Unicode/cjk.c
@@ -0,0 +1,43041 @@
+#include <chardata.h>
+
+const unsigned short u_allzeros[256] = { 0 };
+
+const unichar_t unicode_from_jis208[] = {
+ 0x2003, 0x3001, 0x3002, 0xff0c, 0xff0e, 0x30fb, 0xff1a, 0xff1b,
+ 0xff1f, 0xff01, 0x309b, 0x309c, 0x00b4, 0xff40, 0x00a8, 0xff3e,
+ 0xffe3, 0xff3f, 0x30fd, 0x30fe, 0x309d, 0x309e, 0x3003, 0x4edd,
+ 0x3005, 0x3006, 0x3007, 0x30fc, 0x2015, 0x2010, 0xff0f, 0xff3c,
+ 0x301c, 0x2016, 0xff5c, 0x2026, 0x2025, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xff08, 0xff09, 0x3014, 0x3015, 0xff3b, 0xff3d, 0xff5b,
+ 0xff5d, 0x3008, 0x3009, 0x300a, 0x300b, 0x300c, 0x300d, 0x300e,
+ 0x300f, 0x3010, 0x3011, 0xff0b, 0x2212, 0x00b1, 0x00d7, 0x00f7,
+ 0xff1d, 0x2260, 0xff1c, 0xff1e, 0x2266, 0x2267, 0x221e, 0x2234,
+ 0x2642, 0x2640, 0x00b0, 0x2032, 0x2033, 0x2103, 0xffe5, 0xff04,
+ 0xffe0, 0xffe1, 0xff05, 0xff03, 0xff06, 0xff0a, 0xff20, 0x00a7,
+ 0x2606, 0x2605, 0x25cb, 0x25cf, 0x25ce, 0x25c7, 0x25c6, 0x25a1,
+ 0x25a0, 0x25b3, 0x25b2, 0x25bd, 0x25bc, 0x203b, 0x3012, 0x2192,
+ 0x2190, 0x2191, 0x2193, 0x3013, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2208,
+ 0x220b, 0x2286, 0x2287, 0x2282, 0x2283, 0x222a, 0x2229, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2227,
+ 0x2228, 0xffe2, 0x21d2, 0x21d4, 0x2200, 0x2203, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2220, 0x22a5, 0x2312, 0x2202, 0x2207, 0x2261, 0x2252,
+ 0x226a, 0x226b, 0x221a, 0x223d, 0x221d, 0x2235, 0x222b, 0x222c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x212b,
+ 0x2030, 0x266f, 0x266d, 0x266a, 0x2020, 0x2021, 0x00b6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x25ef, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xff10, 0xff11, 0xff12, 0xff13, 0xff14,
+ 0xff15, 0xff16, 0xff17, 0xff18, 0xff19, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xff21, 0xff22, 0xff23, 0xff24,
+ 0xff25, 0xff26, 0xff27, 0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c,
+ 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31, 0xff32, 0xff33, 0xff34,
+ 0xff35, 0xff36, 0xff37, 0xff38, 0xff39, 0xff3a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xff41, 0xff42, 0xff43, 0xff44,
+ 0xff45, 0xff46, 0xff47, 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c,
+ 0xff4d, 0xff4e, 0xff4f, 0xff50, 0xff51, 0xff52, 0xff53, 0xff54,
+ 0xff55, 0xff56, 0xff57, 0xff58, 0xff59, 0xff5a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046,
+ 0x3047, 0x3048, 0x3049, 0x304a, 0x304b, 0x304c, 0x304d, 0x304e,
+ 0x304f, 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056,
+ 0x3057, 0x3058, 0x3059, 0x305a, 0x305b, 0x305c, 0x305d, 0x305e,
+ 0x305f, 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066,
+ 0x3067, 0x3068, 0x3069, 0x306a, 0x306b, 0x306c, 0x306d, 0x306e,
+ 0x306f, 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076,
+ 0x3077, 0x3078, 0x3079, 0x307a, 0x307b, 0x307c, 0x307d, 0x307e,
+ 0x307f, 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086,
+ 0x3087, 0x3088, 0x3089, 0x308a, 0x308b, 0x308c, 0x308d, 0x308e,
+ 0x308f, 0x3090, 0x3091, 0x3092, 0x3093, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x30a1, 0x30a2, 0x30a3, 0x30a4, 0x30a5, 0x30a6, 0x30a7, 0x30a8,
+ 0x30a9, 0x30aa, 0x30ab, 0x30ac, 0x30ad, 0x30ae, 0x30af, 0x30b0,
+ 0x30b1, 0x30b2, 0x30b3, 0x30b4, 0x30b5, 0x30b6, 0x30b7, 0x30b8,
+ 0x30b9, 0x30ba, 0x30bb, 0x30bc, 0x30bd, 0x30be, 0x30bf, 0x30c0,
+ 0x30c1, 0x30c2, 0x30c3, 0x30c4, 0x30c5, 0x30c6, 0x30c7, 0x30c8,
+ 0x30c9, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, 0x30d0,
+ 0x30d1, 0x30d2, 0x30d3, 0x30d4, 0x30d5, 0x30d6, 0x30d7, 0x30d8,
+ 0x30d9, 0x30da, 0x30db, 0x30dc, 0x30dd, 0x30de, 0x30df, 0x30e0,
+ 0x30e1, 0x30e2, 0x30e3, 0x30e4, 0x30e5, 0x30e6, 0x30e7, 0x30e8,
+ 0x30e9, 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ee, 0x30ef, 0x30f0,
+ 0x30f1, 0x30f2, 0x30f3, 0x30f4, 0x30f5, 0x30f6, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0391, 0x0392,
+ 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a,
+ 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1, 0x03a3,
+ 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03b1, 0x03b2,
+ 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba,
+ 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c3,
+ 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0410, 0x0411, 0x0412, 0x0413,
+ 0x0414, 0x0415, 0x0401, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a,
+ 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, 0x0420, 0x0421, 0x0422,
+ 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a,
+ 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0430, 0x0431, 0x0432, 0x0433,
+ 0x0434, 0x0435, 0x0451, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a,
+ 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, 0x0440, 0x0441, 0x0442,
+ 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a,
+ 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2500, 0x2502, 0x250c, 0x2510, 0x2518, 0x2514,
+ 0x251c, 0x252c, 0x2524, 0x2534, 0x253c, 0x2501, 0x2503, 0x250f,
+ 0x2513, 0x251b, 0x2517, 0x2523, 0x2533, 0x252b, 0x253b, 0x254b,
+ 0x2520, 0x252f, 0x2528, 0x2537, 0x253f, 0x251d, 0x2530, 0x2525,
+ 0x2538, 0x2542, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4e9c, 0x5516, 0x5a03, 0x963f, 0x54c0, 0x611b,
+ 0x6328, 0x59f6, 0x9022, 0x8475, 0x831c, 0x7a50, 0x60aa, 0x63e1,
+ 0x6e25, 0x65ed, 0x8466, 0x82a6, 0x9bf5, 0x6893, 0x5727, 0x65a1,
+ 0x6271, 0x5b9b, 0x59d0, 0x867b, 0x98f4, 0x7d62, 0x7dbe, 0x9b8e,
+ 0x6216, 0x7c9f, 0x88b7, 0x5b89, 0x5eb5, 0x6309, 0x6697, 0x6848,
+ 0x95c7, 0x978d, 0x674f, 0x4ee5, 0x4f0a, 0x4f4d, 0x4f9d, 0x5049,
+ 0x56f2, 0x5937, 0x59d4, 0x5a01, 0x5c09, 0x60df, 0x610f, 0x6170,
+ 0x6613, 0x6905, 0x70ba, 0x754f, 0x7570, 0x79fb, 0x7dad, 0x7def,
+ 0x80c3, 0x840e, 0x8863, 0x8b02, 0x9055, 0x907a, 0x533b, 0x4e95,
+ 0x4ea5, 0x57df, 0x80b2, 0x90c1, 0x78ef, 0x4e00, 0x58f1, 0x6ea2,
+ 0x9038, 0x7a32, 0x8328, 0x828b, 0x9c2f, 0x5141, 0x5370, 0x54bd,
+ 0x54e1, 0x56e0, 0x59fb, 0x5f15, 0x98f2, 0x6deb, 0x80e4, 0x852d,
+ 0x9662, 0x9670, 0x96a0, 0x97fb, 0x540b, 0x53f3, 0x5b87, 0x70cf,
+ 0x7fbd, 0x8fc2, 0x96e8, 0x536f, 0x9d5c, 0x7aba, 0x4e11, 0x7893,
+ 0x81fc, 0x6e26, 0x5618, 0x5504, 0x6b1d, 0x851a, 0x9c3b, 0x59e5,
+ 0x53a9, 0x6d66, 0x74dc, 0x958f, 0x5642, 0x4e91, 0x904b, 0x96f2,
+ 0x834f, 0x990c, 0x53e1, 0x55b6, 0x5b30, 0x5f71, 0x6620, 0x66f3,
+ 0x6804, 0x6c38, 0x6cf3, 0x6d29, 0x745b, 0x76c8, 0x7a4e, 0x9834,
+ 0x82f1, 0x885b, 0x8a60, 0x92ed, 0x6db2, 0x75ab, 0x76ca, 0x99c5,
+ 0x60a6, 0x8b01, 0x8d8a, 0x95b2, 0x698e, 0x53ad, 0x5186, 0x5712,
+ 0x5830, 0x5944, 0x5bb4, 0x5ef6, 0x6028, 0x63a9, 0x63f4, 0x6cbf,
+ 0x6f14, 0x708e, 0x7114, 0x7159, 0x71d5, 0x733f, 0x7e01, 0x8276,
+ 0x82d1, 0x8597, 0x9060, 0x925b, 0x9d1b, 0x5869, 0x65bc, 0x6c5a,
+ 0x7525, 0x51f9, 0x592e, 0x5965, 0x5f80, 0x5fdc, 0x62bc, 0x65fa,
+ 0x6a2a, 0x6b27, 0x6bb4, 0x738b, 0x7fc1, 0x8956, 0x9d2c, 0x9d0e,
+ 0x9ec4, 0x5ca1, 0x6c96, 0x837b, 0x5104, 0x5c4b, 0x61b6, 0x81c6,
+ 0x6876, 0x7261, 0x4e59, 0x4ffa, 0x5378, 0x6069, 0x6e29, 0x7a4f,
+ 0x97f3, 0x4e0b, 0x5316, 0x4eee, 0x4f55, 0x4f3d, 0x4fa1, 0x4f73,
+ 0x52a0, 0x53ef, 0x5609, 0x590f, 0x5ac1, 0x5bb6, 0x5be1, 0x79d1,
+ 0x6687, 0x679c, 0x67b6, 0x6b4c, 0x6cb3, 0x706b, 0x73c2, 0x798d,
+ 0x79be, 0x7a3c, 0x7b87, 0x82b1, 0x82db, 0x8304, 0x8377, 0x83ef,
+ 0x83d3, 0x8766, 0x8ab2, 0x5629, 0x8ca8, 0x8fe6, 0x904e, 0x971e,
+ 0x868a, 0x4fc4, 0x5ce8, 0x6211, 0x7259, 0x753b, 0x81e5, 0x82bd,
+ 0x86fe, 0x8cc0, 0x96c5, 0x9913, 0x99d5, 0x4ecb, 0x4f1a, 0x89e3,
+ 0x56de, 0x584a, 0x58ca, 0x5efb, 0x5feb, 0x602a, 0x6094, 0x6062,
+ 0x61d0, 0x6212, 0x62d0, 0x6539, 0x9b41, 0x6666, 0x68b0, 0x6d77,
+ 0x7070, 0x754c, 0x7686, 0x7d75, 0x82a5, 0x87f9, 0x958b, 0x968e,
+ 0x8c9d, 0x51f1, 0x52be, 0x5916, 0x54b3, 0x5bb3, 0x5d16, 0x6168,
+ 0x6982, 0x6daf, 0x788d, 0x84cb, 0x8857, 0x8a72, 0x93a7, 0x9ab8,
+ 0x6d6c, 0x99a8, 0x86d9, 0x57a3, 0x67ff, 0x86ce, 0x920e, 0x5283,
+ 0x5687, 0x5404, 0x5ed3, 0x62e1, 0x64b9, 0x683c, 0x6838, 0x6bbb,
+ 0x7372, 0x78ba, 0x7a6b, 0x899a, 0x89d2, 0x8d6b, 0x8f03, 0x90ed,
+ 0x95a3, 0x9694, 0x9769, 0x5b66, 0x5cb3, 0x697d, 0x984d, 0x984e,
+ 0x639b, 0x7b20, 0x6a2b, 0x6a7f, 0x68b6, 0x9c0d, 0x6f5f, 0x5272,
+ 0x559d, 0x6070, 0x62ec, 0x6d3b, 0x6e07, 0x6ed1, 0x845b, 0x8910,
+ 0x8f44, 0x4e14, 0x9c39, 0x53f6, 0x691b, 0x6a3a, 0x9784, 0x682a,
+ 0x515c, 0x7ac3, 0x84b2, 0x91dc, 0x938c, 0x565b, 0x9d28, 0x6822,
+ 0x8305, 0x8431, 0x7ca5, 0x5208, 0x82c5, 0x74e6, 0x4e7e, 0x4f83,
+ 0x51a0, 0x5bd2, 0x520a, 0x52d8, 0x52e7, 0x5dfb, 0x559a, 0x582a,
+ 0x59e6, 0x5b8c, 0x5b98, 0x5bdb, 0x5e72, 0x5e79, 0x60a3, 0x611f,
+ 0x6163, 0x61be, 0x63db, 0x6562, 0x67d1, 0x6853, 0x68fa, 0x6b3e,
+ 0x6b53, 0x6c57, 0x6f22, 0x6f97, 0x6f45, 0x74b0, 0x7518, 0x76e3,
+ 0x770b, 0x7aff, 0x7ba1, 0x7c21, 0x7de9, 0x7f36, 0x7ff0, 0x809d,
+ 0x8266, 0x839e, 0x89b3, 0x8acc, 0x8cab, 0x9084, 0x9451, 0x9593,
+ 0x9591, 0x95a2, 0x9665, 0x97d3, 0x9928, 0x8218, 0x4e38, 0x542b,
+ 0x5cb8, 0x5dcc, 0x73a9, 0x764c, 0x773c, 0x5ca9, 0x7feb, 0x8d0b,
+ 0x96c1, 0x9811, 0x9854, 0x9858, 0x4f01, 0x4f0e, 0x5371, 0x559c,
+ 0x5668, 0x57fa, 0x5947, 0x5b09, 0x5bc4, 0x5c90, 0x5e0c, 0x5e7e,
+ 0x5fcc, 0x63ee, 0x673a, 0x65d7, 0x65e2, 0x671f, 0x68cb, 0x68c4,
+ 0x6a5f, 0x5e30, 0x6bc5, 0x6c17, 0x6c7d, 0x757f, 0x7948, 0x5b63,
+ 0x7a00, 0x7d00, 0x5fbd, 0x898f, 0x8a18, 0x8cb4, 0x8d77, 0x8ecc,
+ 0x8f1d, 0x98e2, 0x9a0e, 0x9b3c, 0x4e80, 0x507d, 0x5100, 0x5993,
+ 0x5b9c, 0x622f, 0x6280, 0x64ec, 0x6b3a, 0x72a0, 0x7591, 0x7947,
+ 0x7fa9, 0x87fb, 0x8abc, 0x8b70, 0x63ac, 0x83ca, 0x97a0, 0x5409,
+ 0x5403, 0x55ab, 0x6854, 0x6a58, 0x8a70, 0x7827, 0x6775, 0x9ecd,
+ 0x5374, 0x5ba2, 0x811a, 0x8650, 0x9006, 0x4e18, 0x4e45, 0x4ec7,
+ 0x4f11, 0x53ca, 0x5438, 0x5bae, 0x5f13, 0x6025, 0x6551, 0x673d,
+ 0x6c42, 0x6c72, 0x6ce3, 0x7078, 0x7403, 0x7a76, 0x7aae, 0x7b08,
+ 0x7d1a, 0x7cfe, 0x7d66, 0x65e7, 0x725b, 0x53bb, 0x5c45, 0x5de8,
+ 0x62d2, 0x62e0, 0x6319, 0x6e20, 0x865a, 0x8a31, 0x8ddd, 0x92f8,
+ 0x6f01, 0x79a6, 0x9b5a, 0x4ea8, 0x4eab, 0x4eac, 0x4f9b, 0x4fa0,
+ 0x50d1, 0x5147, 0x7af6, 0x5171, 0x51f6, 0x5354, 0x5321, 0x537f,
+ 0x53eb, 0x55ac, 0x5883, 0x5ce1, 0x5f37, 0x5f4a, 0x602f, 0x6050,
+ 0x606d, 0x631f, 0x6559, 0x6a4b, 0x6cc1, 0x72c2, 0x72ed, 0x77ef,
+ 0x80f8, 0x8105, 0x8208, 0x854e, 0x90f7, 0x93e1, 0x97ff, 0x9957,
+ 0x9a5a, 0x4ef0, 0x51dd, 0x5c2d, 0x6681, 0x696d, 0x5c40, 0x66f2,
+ 0x6975, 0x7389, 0x6850, 0x7c81, 0x50c5, 0x52e4, 0x5747, 0x5dfe,
+ 0x9326, 0x65a4, 0x6b23, 0x6b3d, 0x7434, 0x7981, 0x79bd, 0x7b4b,
+ 0x7dca, 0x82b9, 0x83cc, 0x887f, 0x895f, 0x8b39, 0x8fd1, 0x91d1,
+ 0x541f, 0x9280, 0x4e5d, 0x5036, 0x53e5, 0x533a, 0x72d7, 0x7396,
+ 0x77e9, 0x82e6, 0x8eaf, 0x99c6, 0x99c8, 0x99d2, 0x5177, 0x611a,
+ 0x865e, 0x55b0, 0x7a7a, 0x5076, 0x5bd3, 0x9047, 0x9685, 0x4e32,
+ 0x6adb, 0x91e7, 0x5c51, 0x5c48, 0x6398, 0x7a9f, 0x6c93, 0x9774,
+ 0x8f61, 0x7aaa, 0x718a, 0x9688, 0x7c82, 0x6817, 0x7e70, 0x6851,
+ 0x936c, 0x52f2, 0x541b, 0x85ab, 0x8a13, 0x7fa4, 0x8ecd, 0x90e1,
+ 0x5366, 0x8888, 0x7941, 0x4fc2, 0x50be, 0x5211, 0x5144, 0x5553,
+ 0x572d, 0x73ea, 0x578b, 0x5951, 0x5f62, 0x5f84, 0x6075, 0x6176,
+ 0x6167, 0x61a9, 0x63b2, 0x643a, 0x656c, 0x666f, 0x6842, 0x6e13,
+ 0x7566, 0x7a3d, 0x7cfb, 0x7d4c, 0x7d99, 0x7e4b, 0x7f6b, 0x830e,
+ 0x834a, 0x86cd, 0x8a08, 0x8a63, 0x8b66, 0x8efd, 0x981a, 0x9d8f,
+ 0x82b8, 0x8fce, 0x9be8, 0x5287, 0x621f, 0x6483, 0x6fc0, 0x9699,
+ 0x6841, 0x5091, 0x6b20, 0x6c7a, 0x6f54, 0x7a74, 0x7d50, 0x8840,
+ 0x8a23, 0x6708, 0x4ef6, 0x5039, 0x5026, 0x5065, 0x517c, 0x5238,
+ 0x5263, 0x55a7, 0x570f, 0x5805, 0x5acc, 0x5efa, 0x61b2, 0x61f8,
+ 0x62f3, 0x6372, 0x691c, 0x6a29, 0x727d, 0x72ac, 0x732e, 0x7814,
+ 0x786f, 0x7d79, 0x770c, 0x80a9, 0x898b, 0x8b19, 0x8ce2, 0x8ed2,
+ 0x9063, 0x9375, 0x967a, 0x9855, 0x9a13, 0x9e78, 0x5143, 0x539f,
+ 0x53b3, 0x5e7b, 0x5f26, 0x6e1b, 0x6e90, 0x7384, 0x73fe, 0x7d43,
+ 0x8237, 0x8a00, 0x8afa, 0x9650, 0x4e4e, 0x500b, 0x53e4, 0x547c,
+ 0x56fa, 0x59d1, 0x5b64, 0x5df1, 0x5eab, 0x5f27, 0x6238, 0x6545,
+ 0x67af, 0x6e56, 0x72d0, 0x7cca, 0x88b4, 0x80a1, 0x80e1, 0x83f0,
+ 0x864e, 0x8a87, 0x8de8, 0x9237, 0x96c7, 0x9867, 0x9f13, 0x4e94,
+ 0x4e92, 0x4f0d, 0x5348, 0x5449, 0x543e, 0x5a2f, 0x5f8c, 0x5fa1,
+ 0x609f, 0x68a7, 0x6a8e, 0x745a, 0x7881, 0x8a9e, 0x8aa4, 0x8b77,
+ 0x9190, 0x4e5e, 0x9bc9, 0x4ea4, 0x4f7c, 0x4faf, 0x5019, 0x5016,
+ 0x5149, 0x516c, 0x529f, 0x52b9, 0x52fe, 0x539a, 0x53e3, 0x5411,
+ 0x540e, 0x5589, 0x5751, 0x57a2, 0x597d, 0x5b54, 0x5b5d, 0x5b8f,
+ 0x5de5, 0x5de7, 0x5df7, 0x5e78, 0x5e83, 0x5e9a, 0x5eb7, 0x5f18,
+ 0x6052, 0x614c, 0x6297, 0x62d8, 0x63a7, 0x653b, 0x6602, 0x6643,
+ 0x66f4, 0x676d, 0x6821, 0x6897, 0x69cb, 0x6c5f, 0x6d2a, 0x6d69,
+ 0x6e2f, 0x6e9d, 0x7532, 0x7687, 0x786c, 0x7a3f, 0x7ce0, 0x7d05,
+ 0x7d18, 0x7d5e, 0x7db1, 0x8015, 0x8003, 0x80af, 0x80b1, 0x8154,
+ 0x818f, 0x822a, 0x8352, 0x884c, 0x8861, 0x8b1b, 0x8ca2, 0x8cfc,
+ 0x90ca, 0x9175, 0x9271, 0x783f, 0x92fc, 0x95a4, 0x964d, 0x9805,
+ 0x9999, 0x9ad8, 0x9d3b, 0x525b, 0x52ab, 0x53f7, 0x5408, 0x58d5,
+ 0x62f7, 0x6fe0, 0x8c6a, 0x8f5f, 0x9eb9, 0x514b, 0x523b, 0x544a,
+ 0x56fd, 0x7a40, 0x9177, 0x9d60, 0x9ed2, 0x7344, 0x6f09, 0x8170,
+ 0x7511, 0x5ffd, 0x60da, 0x9aa8, 0x72db, 0x8fbc, 0x6b64, 0x9803,
+ 0x4eca, 0x56f0, 0x5764, 0x58be, 0x5a5a, 0x6068, 0x61c7, 0x660f,
+ 0x6606, 0x6839, 0x68b1, 0x6df7, 0x75d5, 0x7d3a, 0x826e, 0x9b42,
+ 0x4e9b, 0x4f50, 0x53c9, 0x5506, 0x5d6f, 0x5de6, 0x5dee, 0x67fb,
+ 0x6c99, 0x7473, 0x7802, 0x8a50, 0x9396, 0x88df, 0x5750, 0x5ea7,
+ 0x632b, 0x50b5, 0x50ac, 0x518d, 0x6700, 0x54c9, 0x585e, 0x59bb,
+ 0x5bb0, 0x5f69, 0x624d, 0x63a1, 0x683d, 0x6b73, 0x6e08, 0x707d,
+ 0x91c7, 0x7280, 0x7815, 0x7826, 0x796d, 0x658e, 0x7d30, 0x83dc,
+ 0x88c1, 0x8f09, 0x969b, 0x5264, 0x5728, 0x6750, 0x7f6a, 0x8ca1,
+ 0x51b4, 0x5742, 0x962a, 0x583a, 0x698a, 0x80b4, 0x54b2, 0x5d0e,
+ 0x57fc, 0x7895, 0x9dfa, 0x4f5c, 0x524a, 0x548b, 0x643e, 0x6628,
+ 0x6714, 0x67f5, 0x7a84, 0x7b56, 0x7d22, 0x932f, 0x685c, 0x9bad,
+ 0x7b39, 0x5319, 0x518a, 0x5237, 0x5bdf, 0x62f6, 0x64ae, 0x64e6,
+ 0x672d, 0x6bba, 0x85a9, 0x96d1, 0x7690, 0x9bd6, 0x634c, 0x9306,
+ 0x9bab, 0x76bf, 0x6652, 0x4e09, 0x5098, 0x53c2, 0x5c71, 0x60e8,
+ 0x6492, 0x6563, 0x685f, 0x71e6, 0x73ca, 0x7523, 0x7b97, 0x7e82,
+ 0x8695, 0x8b83, 0x8cdb, 0x9178, 0x9910, 0x65ac, 0x66ab, 0x6b8b,
+ 0x4ed5, 0x4ed4, 0x4f3a, 0x4f7f, 0x523a, 0x53f8, 0x53f2, 0x55e3,
+ 0x56db, 0x58eb, 0x59cb, 0x59c9, 0x59ff, 0x5b50, 0x5c4d, 0x5e02,
+ 0x5e2b, 0x5fd7, 0x601d, 0x6307, 0x652f, 0x5b5c, 0x65af, 0x65bd,
+ 0x65e8, 0x679d, 0x6b62, 0x6b7b, 0x6c0f, 0x7345, 0x7949, 0x79c1,
+ 0x7cf8, 0x7d19, 0x7d2b, 0x80a2, 0x8102, 0x81f3, 0x8996, 0x8a5e,
+ 0x8a69, 0x8a66, 0x8a8c, 0x8aee, 0x8cc7, 0x8cdc, 0x96cc, 0x98fc,
+ 0x6b6f, 0x4e8b, 0x4f3c, 0x4f8d, 0x5150, 0x5b57, 0x5bfa, 0x6148,
+ 0x6301, 0x6642, 0x6b21, 0x6ecb, 0x6cbb, 0x723e, 0x74bd, 0x75d4,
+ 0x78c1, 0x793a, 0x800c, 0x8033, 0x81ea, 0x8494, 0x8f9e, 0x6c50,
+ 0x9e7f, 0x5f0f, 0x8b58, 0x9d2b, 0x7afa, 0x8ef8, 0x5b8d, 0x96eb,
+ 0x4e03, 0x53f1, 0x57f7, 0x5931, 0x5ac9, 0x5ba4, 0x6089, 0x6e7f,
+ 0x6f06, 0x75be, 0x8cea, 0x5b9f, 0x8500, 0x7be0, 0x5072, 0x67f4,
+ 0x829d, 0x5c61, 0x854a, 0x7e1e, 0x820e, 0x5199, 0x5c04, 0x6368,
+ 0x8d66, 0x659c, 0x716e, 0x793e, 0x7d17, 0x8005, 0x8b1d, 0x8eca,
+ 0x906e, 0x86c7, 0x90aa, 0x501f, 0x52fa, 0x5c3a, 0x6753, 0x707c,
+ 0x7235, 0x914c, 0x91c8, 0x932b, 0x82e5, 0x5bc2, 0x5f31, 0x60f9,
+ 0x4e3b, 0x53d6, 0x5b88, 0x624b, 0x6731, 0x6b8a, 0x72e9, 0x73e0,
+ 0x7a2e, 0x816b, 0x8da3, 0x9152, 0x9996, 0x5112, 0x53d7, 0x546a,
+ 0x5bff, 0x6388, 0x6a39, 0x7dac, 0x9700, 0x56da, 0x53ce, 0x5468,
+ 0x5b97, 0x5c31, 0x5dde, 0x4fee, 0x6101, 0x62fe, 0x6d32, 0x79c0,
+ 0x79cb, 0x7d42, 0x7e4d, 0x7fd2, 0x81ed, 0x821f, 0x8490, 0x8846,
+ 0x8972, 0x8b90, 0x8e74, 0x8f2f, 0x9031, 0x914b, 0x916c, 0x96c6,
+ 0x919c, 0x4ec0, 0x4f4f, 0x5145, 0x5341, 0x5f93, 0x620e, 0x67d4,
+ 0x6c41, 0x6e0b, 0x7363, 0x7e26, 0x91cd, 0x9283, 0x53d4, 0x5919,
+ 0x5bbf, 0x6dd1, 0x795d, 0x7e2e, 0x7c9b, 0x587e, 0x719f, 0x51fa,
+ 0x8853, 0x8ff0, 0x4fca, 0x5cfb, 0x6625, 0x77ac, 0x7ae3, 0x821c,
+ 0x99ff, 0x51c6, 0x5faa, 0x65ec, 0x696f, 0x6b89, 0x6df3, 0x6e96,
+ 0x6f64, 0x76fe, 0x7d14, 0x5de1, 0x9075, 0x9187, 0x9806, 0x51e6,
+ 0x521d, 0x6240, 0x6691, 0x66d9, 0x6e1a, 0x5eb6, 0x7dd2, 0x7f72,
+ 0x66f8, 0x85af, 0x85f7, 0x8af8, 0x52a9, 0x53d9, 0x5973, 0x5e8f,
+ 0x5f90, 0x6055, 0x92e4, 0x9664, 0x50b7, 0x511f, 0x52dd, 0x5320,
+ 0x5347, 0x53ec, 0x54e8, 0x5546, 0x5531, 0x5617, 0x5968, 0x59be,
+ 0x5a3c, 0x5bb5, 0x5c06, 0x5c0f, 0x5c11, 0x5c1a, 0x5e84, 0x5e8a,
+ 0x5ee0, 0x5f70, 0x627f, 0x6284, 0x62db, 0x638c, 0x6377, 0x6607,
+ 0x660c, 0x662d, 0x6676, 0x677e, 0x68a2, 0x6a1f, 0x6a35, 0x6cbc,
+ 0x6d88, 0x6e09, 0x6e58, 0x713c, 0x7126, 0x7167, 0x75c7, 0x7701,
+ 0x785d, 0x7901, 0x7965, 0x79f0, 0x7ae0, 0x7b11, 0x7ca7, 0x7d39,
+ 0x8096, 0x83d6, 0x848b, 0x8549, 0x885d, 0x88f3, 0x8a1f, 0x8a3c,
+ 0x8a54, 0x8a73, 0x8c61, 0x8cde, 0x91a4, 0x9266, 0x937e, 0x9418,
+ 0x969c, 0x9798, 0x4e0a, 0x4e08, 0x4e1e, 0x4e57, 0x5197, 0x5270,
+ 0x57ce, 0x5834, 0x58cc, 0x5b22, 0x5e38, 0x60c5, 0x64fe, 0x6761,
+ 0x6756, 0x6d44, 0x72b6, 0x7573, 0x7a63, 0x84b8, 0x8b72, 0x91b8,
+ 0x9320, 0x5631, 0x57f4, 0x98fe, 0x62ed, 0x690d, 0x6b96, 0x71ed,
+ 0x7e54, 0x8077, 0x8272, 0x89e6, 0x98df, 0x8755, 0x8fb1, 0x5c3b,
+ 0x4f38, 0x4fe1, 0x4fb5, 0x5507, 0x5a20, 0x5bdd, 0x5be9, 0x5fc3,
+ 0x614e, 0x632f, 0x65b0, 0x664b, 0x68ee, 0x699b, 0x6d78, 0x6df1,
+ 0x7533, 0x75b9, 0x771f, 0x795e, 0x79e6, 0x7d33, 0x81e3, 0x82af,
+ 0x85aa, 0x89aa, 0x8a3a, 0x8eab, 0x8f9b, 0x9032, 0x91dd, 0x9707,
+ 0x4eba, 0x4ec1, 0x5203, 0x5875, 0x58ec, 0x5c0b, 0x751a, 0x5c3d,
+ 0x814e, 0x8a0a, 0x8fc5, 0x9663, 0x976d, 0x7b25, 0x8acf, 0x9808,
+ 0x9162, 0x56f3, 0x53a8, 0x9017, 0x5439, 0x5782, 0x5e25, 0x63a8,
+ 0x6c34, 0x708a, 0x7761, 0x7c8b, 0x7fe0, 0x8870, 0x9042, 0x9154,
+ 0x9310, 0x9318, 0x968f, 0x745e, 0x9ac4, 0x5d07, 0x5d69, 0x6570,
+ 0x67a2, 0x8da8, 0x96db, 0x636e, 0x6749, 0x6919, 0x83c5, 0x9817,
+ 0x96c0, 0x88fe, 0x6f84, 0x647a, 0x5bf8, 0x4e16, 0x702c, 0x755d,
+ 0x662f, 0x51c4, 0x5236, 0x52e2, 0x59d3, 0x5f81, 0x6027, 0x6210,
+ 0x653f, 0x6574, 0x661f, 0x6674, 0x68f2, 0x6816, 0x6b63, 0x6e05,
+ 0x7272, 0x751f, 0x76db, 0x7cbe, 0x8056, 0x58f0, 0x88fd, 0x897f,
+ 0x8aa0, 0x8a93, 0x8acb, 0x901d, 0x9192, 0x9752, 0x9759, 0x6589,
+ 0x7a0e, 0x8106, 0x96bb, 0x5e2d, 0x60dc, 0x621a, 0x65a5, 0x6614,
+ 0x6790, 0x77f3, 0x7a4d, 0x7c4d, 0x7e3e, 0x810a, 0x8cac, 0x8d64,
+ 0x8de1, 0x8e5f, 0x78a9, 0x5207, 0x62d9, 0x63a5, 0x6442, 0x6298,
+ 0x8a2d, 0x7a83, 0x7bc0, 0x8aac, 0x96ea, 0x7d76, 0x820c, 0x8749,
+ 0x4ed9, 0x5148, 0x5343, 0x5360, 0x5ba3, 0x5c02, 0x5c16, 0x5ddd,
+ 0x6226, 0x6247, 0x64b0, 0x6813, 0x6834, 0x6cc9, 0x6d45, 0x6d17,
+ 0x67d3, 0x6f5c, 0x714e, 0x717d, 0x65cb, 0x7a7f, 0x7bad, 0x7dda,
+ 0x7e4a, 0x7fa8, 0x817a, 0x821b, 0x8239, 0x85a6, 0x8a6e, 0x8cce,
+ 0x8df5, 0x9078, 0x9077, 0x92ad, 0x9291, 0x9583, 0x9bae, 0x524d,
+ 0x5584, 0x6f38, 0x7136, 0x5168, 0x7985, 0x7e55, 0x81b3, 0x7cce,
+ 0x564c, 0x5851, 0x5ca8, 0x63aa, 0x66fe, 0x66fd, 0x695a, 0x72d9,
+ 0x758f, 0x758e, 0x790e, 0x7956, 0x79df, 0x7c97, 0x7d20, 0x7d44,
+ 0x8607, 0x8a34, 0x963b, 0x9061, 0x9f20, 0x50e7, 0x5275, 0x53cc,
+ 0x53e2, 0x5009, 0x55aa, 0x58ee, 0x594f, 0x723d, 0x5b8b, 0x5c64,
+ 0x531d, 0x60e3, 0x60f3, 0x635c, 0x6383, 0x633f, 0x63bb, 0x64cd,
+ 0x65e9, 0x66f9, 0x5de3, 0x69cd, 0x69fd, 0x6f15, 0x71e5, 0x4e89,
+ 0x75e9, 0x76f8, 0x7a93, 0x7cdf, 0x7dcf, 0x7d9c, 0x8061, 0x8349,
+ 0x8358, 0x846c, 0x84bc, 0x85fb, 0x88c5, 0x8d70, 0x9001, 0x906d,
+ 0x9397, 0x971c, 0x9a12, 0x50cf, 0x5897, 0x618e, 0x81d3, 0x8535,
+ 0x8d08, 0x9020, 0x4fc3, 0x5074, 0x5247, 0x5373, 0x606f, 0x6349,
+ 0x675f, 0x6e2c, 0x8db3, 0x901f, 0x4fd7, 0x5c5e, 0x8cca, 0x65cf,
+ 0x7d9a, 0x5352, 0x8896, 0x5176, 0x63c3, 0x5b58, 0x5b6b, 0x5c0a,
+ 0x640d, 0x6751, 0x905c, 0x4ed6, 0x591a, 0x592a, 0x6c70, 0x8a51,
+ 0x553e, 0x5815, 0x59a5, 0x60f0, 0x6253, 0x67c1, 0x8235, 0x6955,
+ 0x9640, 0x99c4, 0x9a28, 0x4f53, 0x5806, 0x5bfe, 0x8010, 0x5cb1,
+ 0x5e2f, 0x5f85, 0x6020, 0x614b, 0x6234, 0x66ff, 0x6cf0, 0x6ede,
+ 0x80ce, 0x817f, 0x82d4, 0x888b, 0x8cb8, 0x9000, 0x902e, 0x968a,
+ 0x9edb, 0x9bdb, 0x4ee3, 0x53f0, 0x5927, 0x7b2c, 0x918d, 0x984c,
+ 0x9df9, 0x6edd, 0x7027, 0x5353, 0x5544, 0x5b85, 0x6258, 0x629e,
+ 0x62d3, 0x6ca2, 0x6fef, 0x7422, 0x8a17, 0x9438, 0x6fc1, 0x8afe,
+ 0x8338, 0x51e7, 0x86f8, 0x53ea, 0x53e9, 0x4f46, 0x9054, 0x8fb0,
+ 0x596a, 0x8131, 0x5dfd, 0x7aea, 0x8fbf, 0x68da, 0x8c37, 0x72f8,
+ 0x9c48, 0x6a3d, 0x8ab0, 0x4e39, 0x5358, 0x5606, 0x5766, 0x62c5,
+ 0x63a2, 0x65e6, 0x6b4e, 0x6de1, 0x6e5b, 0x70ad, 0x77ed, 0x7aef,
+ 0x7baa, 0x7dbb, 0x803d, 0x80c6, 0x86cb, 0x8a95, 0x935b, 0x56e3,
+ 0x58c7, 0x5f3e, 0x65ad, 0x6696, 0x6a80, 0x6bb5, 0x7537, 0x8ac7,
+ 0x5024, 0x77e5, 0x5730, 0x5f1b, 0x6065, 0x667a, 0x6c60, 0x75f4,
+ 0x7a1a, 0x7f6e, 0x81f4, 0x8718, 0x9045, 0x99b3, 0x7bc9, 0x755c,
+ 0x7af9, 0x7b51, 0x84c4, 0x9010, 0x79e9, 0x7a92, 0x8336, 0x5ae1,
+ 0x7740, 0x4e2d, 0x4ef2, 0x5b99, 0x5fe0, 0x62bd, 0x663c, 0x67f1,
+ 0x6ce8, 0x866b, 0x8877, 0x8a3b, 0x914e, 0x92f3, 0x99d0, 0x6a17,
+ 0x7026, 0x732a, 0x82e7, 0x8457, 0x8caf, 0x4e01, 0x5146, 0x51cb,
+ 0x558b, 0x5bf5, 0x5e16, 0x5e33, 0x5e81, 0x5f14, 0x5f35, 0x5f6b,
+ 0x5fb4, 0x61f2, 0x6311, 0x66a2, 0x671d, 0x6f6e, 0x7252, 0x753a,
+ 0x773a, 0x8074, 0x8139, 0x8178, 0x8776, 0x8abf, 0x8adc, 0x8d85,
+ 0x8df3, 0x929a, 0x9577, 0x9802, 0x9ce5, 0x52c5, 0x6357, 0x76f4,
+ 0x6715, 0x6c88, 0x73cd, 0x8cc3, 0x93ae, 0x9673, 0x6d25, 0x589c,
+ 0x690e, 0x69cc, 0x8ffd, 0x939a, 0x75db, 0x901a, 0x585a, 0x6802,
+ 0x63b4, 0x69fb, 0x4f43, 0x6f2c, 0x67d8, 0x8fbb, 0x8526, 0x7db4,
+ 0x9354, 0x693f, 0x6f70, 0x576a, 0x58f7, 0x5b2c, 0x7d2c, 0x722a,
+ 0x540a, 0x91e3, 0x9db4, 0x4ead, 0x4f4e, 0x505c, 0x5075, 0x5243,
+ 0x8c9e, 0x5448, 0x5824, 0x5b9a, 0x5e1d, 0x5e95, 0x5ead, 0x5ef7,
+ 0x5f1f, 0x608c, 0x62b5, 0x633a, 0x63d0, 0x68af, 0x6c40, 0x7887,
+ 0x798e, 0x7a0b, 0x7de0, 0x8247, 0x8a02, 0x8ae6, 0x8e44, 0x9013,
+ 0x90b8, 0x912d, 0x91d8, 0x9f0e, 0x6ce5, 0x6458, 0x64e2, 0x6575,
+ 0x6ef4, 0x7684, 0x7b1b, 0x9069, 0x93d1, 0x6eba, 0x54f2, 0x5fb9,
+ 0x64a4, 0x8f4d, 0x8fed, 0x9244, 0x5178, 0x586b, 0x5929, 0x5c55,
+ 0x5e97, 0x6dfb, 0x7e8f, 0x751c, 0x8cbc, 0x8ee2, 0x985b, 0x70b9,
+ 0x4f1d, 0x6bbf, 0x6fb1, 0x7530, 0x96fb, 0x514e, 0x5410, 0x5835,
+ 0x5857, 0x59ac, 0x5c60, 0x5f92, 0x6597, 0x675c, 0x6e21, 0x767b,
+ 0x83df, 0x8ced, 0x9014, 0x90fd, 0x934d, 0x7825, 0x783a, 0x52aa,
+ 0x5ea6, 0x571f, 0x5974, 0x6012, 0x5012, 0x515a, 0x51ac, 0x51cd,
+ 0x5200, 0x5510, 0x5854, 0x5858, 0x5957, 0x5b95, 0x5cf6, 0x5d8b,
+ 0x60bc, 0x6295, 0x642d, 0x6771, 0x6843, 0x68bc, 0x68df, 0x76d7,
+ 0x6dd8, 0x6e6f, 0x6d9b, 0x706f, 0x71c8, 0x5f53, 0x75d8, 0x7977,
+ 0x7b49, 0x7b54, 0x7b52, 0x7cd6, 0x7d71, 0x5230, 0x8463, 0x8569,
+ 0x85e4, 0x8a0e, 0x8b04, 0x8c46, 0x8e0f, 0x9003, 0x900f, 0x9419,
+ 0x9676, 0x982d, 0x9a30, 0x95d8, 0x50cd, 0x52d5, 0x540c, 0x5802,
+ 0x5c0e, 0x61a7, 0x649e, 0x6d1e, 0x77b3, 0x7ae5, 0x80f4, 0x8404,
+ 0x9053, 0x9285, 0x5ce0, 0x9d07, 0x533f, 0x5f97, 0x5fb3, 0x6d9c,
+ 0x7279, 0x7763, 0x79bf, 0x7be4, 0x6bd2, 0x72ec, 0x8aad, 0x6803,
+ 0x6a61, 0x51f8, 0x7a81, 0x6934, 0x5c4a, 0x9cf6, 0x82eb, 0x5bc5,
+ 0x9149, 0x701e, 0x5678, 0x5c6f, 0x60c7, 0x6566, 0x6c8c, 0x8c5a,
+ 0x9041, 0x9813, 0x5451, 0x66c7, 0x920d, 0x5948, 0x90a3, 0x5185,
+ 0x4e4d, 0x51ea, 0x8599, 0x8b0e, 0x7058, 0x637a, 0x934b, 0x6962,
+ 0x99b4, 0x7e04, 0x7577, 0x5357, 0x6960, 0x8edf, 0x96e3, 0x6c5d,
+ 0x4e8c, 0x5c3c, 0x5f10, 0x8fe9, 0x5302, 0x8cd1, 0x8089, 0x8679,
+ 0x5eff, 0x65e5, 0x4e73, 0x5165, 0x5982, 0x5c3f, 0x97ee, 0x4efb,
+ 0x598a, 0x5fcd, 0x8a8d, 0x6fe1, 0x79b0, 0x7962, 0x5be7, 0x8471,
+ 0x732b, 0x71b1, 0x5e74, 0x5ff5, 0x637b, 0x649a, 0x71c3, 0x7c98,
+ 0x4e43, 0x5efc, 0x4e4b, 0x57dc, 0x56a2, 0x60a9, 0x6fc3, 0x7d0d,
+ 0x80fd, 0x8133, 0x81bf, 0x8fb2, 0x8997, 0x86a4, 0x5df4, 0x628a,
+ 0x64ad, 0x8987, 0x6777, 0x6ce2, 0x6d3e, 0x7436, 0x7834, 0x5a46,
+ 0x7f75, 0x82ad, 0x99ac, 0x4ff3, 0x5ec3, 0x62dd, 0x6392, 0x6557,
+ 0x676f, 0x76c3, 0x724c, 0x80cc, 0x80ba, 0x8f29, 0x914d, 0x500d,
+ 0x57f9, 0x5a92, 0x6885, 0x6973, 0x7164, 0x72fd, 0x8cb7, 0x58f2,
+ 0x8ce0, 0x966a, 0x9019, 0x877f, 0x79e4, 0x77e7, 0x8429, 0x4f2f,
+ 0x5265, 0x535a, 0x62cd, 0x67cf, 0x6cca, 0x767d, 0x7b94, 0x7c95,
+ 0x8236, 0x8584, 0x8feb, 0x66dd, 0x6f20, 0x7206, 0x7e1b, 0x83ab,
+ 0x99c1, 0x9ea6, 0x51fd, 0x7bb1, 0x7872, 0x7bb8, 0x8087, 0x7b48,
+ 0x6ae8, 0x5e61, 0x808c, 0x7551, 0x7560, 0x516b, 0x9262, 0x6e8c,
+ 0x767a, 0x9197, 0x9aea, 0x4f10, 0x7f70, 0x629c, 0x7b4f, 0x95a5,
+ 0x9ce9, 0x567a, 0x5859, 0x86e4, 0x96bc, 0x4f34, 0x5224, 0x534a,
+ 0x53cd, 0x53db, 0x5e06, 0x642c, 0x6591, 0x677f, 0x6c3e, 0x6c4e,
+ 0x7248, 0x72af, 0x73ed, 0x7554, 0x7e41, 0x822c, 0x85e9, 0x8ca9,
+ 0x7bc4, 0x91c6, 0x7169, 0x9812, 0x98ef, 0x633d, 0x6669, 0x756a,
+ 0x76e4, 0x78d0, 0x8543, 0x86ee, 0x532a, 0x5351, 0x5426, 0x5983,
+ 0x5e87, 0x5f7c, 0x60b2, 0x6249, 0x6279, 0x62ab, 0x6590, 0x6bd4,
+ 0x6ccc, 0x75b2, 0x76ae, 0x7891, 0x79d8, 0x7dcb, 0x7f77, 0x80a5,
+ 0x88ab, 0x8ab9, 0x8cbb, 0x907f, 0x975e, 0x98db, 0x6a0b, 0x7c38,
+ 0x5099, 0x5c3e, 0x5fae, 0x6787, 0x6bd8, 0x7435, 0x7709, 0x7f8e,
+ 0x9f3b, 0x67ca, 0x7a17, 0x5339, 0x758b, 0x9aed, 0x5f66, 0x819d,
+ 0x83f1, 0x8098, 0x5f3c, 0x5fc5, 0x7562, 0x7b46, 0x903c, 0x6867,
+ 0x59eb, 0x5a9b, 0x7d10, 0x767e, 0x8b2c, 0x4ff5, 0x5f6a, 0x6a19,
+ 0x6c37, 0x6f02, 0x74e2, 0x7968, 0x8868, 0x8a55, 0x8c79, 0x5edf,
+ 0x63cf, 0x75c5, 0x79d2, 0x82d7, 0x9328, 0x92f2, 0x849c, 0x86ed,
+ 0x9c2d, 0x54c1, 0x5f6c, 0x658c, 0x6d5c, 0x7015, 0x8ca7, 0x8cd3,
+ 0x983b, 0x654f, 0x74f6, 0x4e0d, 0x4ed8, 0x57e0, 0x592b, 0x5a66,
+ 0x5bcc, 0x51a8, 0x5e03, 0x5e9c, 0x6016, 0x6276, 0x6577, 0x65a7,
+ 0x666e, 0x6d6e, 0x7236, 0x7b26, 0x8150, 0x819a, 0x8299, 0x8b5c,
+ 0x8ca0, 0x8ce6, 0x8d74, 0x961c, 0x9644, 0x4fae, 0x64ab, 0x6b66,
+ 0x821e, 0x8461, 0x856a, 0x90e8, 0x5c01, 0x6953, 0x98a8, 0x847a,
+ 0x8557, 0x4f0f, 0x526f, 0x5fa9, 0x5e45, 0x670d, 0x798f, 0x8179,
+ 0x8907, 0x8986, 0x6df5, 0x5f17, 0x6255, 0x6cb8, 0x4ecf, 0x7269,
+ 0x9b92, 0x5206, 0x543b, 0x5674, 0x58b3, 0x61a4, 0x626e, 0x711a,
+ 0x596e, 0x7c89, 0x7cde, 0x7d1b, 0x96f0, 0x6587, 0x805e, 0x4e19,
+ 0x4f75, 0x5175, 0x5840, 0x5e63, 0x5e73, 0x5f0a, 0x67c4, 0x4e26,
+ 0x853d, 0x9589, 0x965b, 0x7c73, 0x9801, 0x50fb, 0x58c1, 0x7656,
+ 0x78a7, 0x5225, 0x77a5, 0x8511, 0x7b86, 0x504f, 0x5909, 0x7247,
+ 0x7bc7, 0x7de8, 0x8fba, 0x8fd4, 0x904d, 0x4fbf, 0x52c9, 0x5a29,
+ 0x5f01, 0x97ad, 0x4fdd, 0x8217, 0x92ea, 0x5703, 0x6355, 0x6b69,
+ 0x752b, 0x88dc, 0x8f14, 0x7a42, 0x52df, 0x5893, 0x6155, 0x620a,
+ 0x66ae, 0x6bcd, 0x7c3f, 0x83e9, 0x5023, 0x4ff8, 0x5305, 0x5446,
+ 0x5831, 0x5949, 0x5b9d, 0x5cf0, 0x5cef, 0x5d29, 0x5e96, 0x62b1,
+ 0x6367, 0x653e, 0x65b9, 0x670b, 0x6cd5, 0x6ce1, 0x70f9, 0x7832,
+ 0x7e2b, 0x80de, 0x82b3, 0x840c, 0x84ec, 0x8702, 0x8912, 0x8a2a,
+ 0x8c4a, 0x90a6, 0x92d2, 0x98fd, 0x9cf3, 0x9d6c, 0x4e4f, 0x4ea1,
+ 0x508d, 0x5256, 0x574a, 0x59a8, 0x5e3d, 0x5fd8, 0x5fd9, 0x623f,
+ 0x66b4, 0x671b, 0x67d0, 0x68d2, 0x5192, 0x7d21, 0x80aa, 0x81a8,
+ 0x8b00, 0x8c8c, 0x8cbf, 0x927e, 0x9632, 0x5420, 0x982c, 0x5317,
+ 0x50d5, 0x535c, 0x58a8, 0x64b2, 0x6734, 0x7267, 0x7766, 0x7a46,
+ 0x91e6, 0x52c3, 0x6ca1, 0x6b86, 0x5800, 0x5e4c, 0x5954, 0x672c,
+ 0x7ffb, 0x51e1, 0x76c6, 0x6469, 0x78e8, 0x9b54, 0x9ebb, 0x57cb,
+ 0x59b9, 0x6627, 0x679a, 0x6bce, 0x54e9, 0x69d9, 0x5e55, 0x819c,
+ 0x6795, 0x9baa, 0x67fe, 0x9c52, 0x685d, 0x4ea6, 0x4fe3, 0x53c8,
+ 0x62b9, 0x672b, 0x6cab, 0x8fc4, 0x4fad, 0x7e6d, 0x9ebf, 0x4e07,
+ 0x6162, 0x6e80, 0x6f2b, 0x8513, 0x5473, 0x672a, 0x9b45, 0x5df3,
+ 0x7b95, 0x5cac, 0x5bc6, 0x871c, 0x6e4a, 0x84d1, 0x7a14, 0x8108,
+ 0x5999, 0x7c8d, 0x6c11, 0x7720, 0x52d9, 0x5922, 0x7121, 0x725f,
+ 0x77db, 0x9727, 0x9d61, 0x690b, 0x5a7f, 0x5a18, 0x51a5, 0x540d,
+ 0x547d, 0x660e, 0x76df, 0x8ff7, 0x9298, 0x9cf4, 0x59ea, 0x725d,
+ 0x6ec5, 0x514d, 0x68c9, 0x7dbf, 0x7dec, 0x9762, 0x9eba, 0x6478,
+ 0x6a21, 0x8302, 0x5984, 0x5b5f, 0x6bdb, 0x731b, 0x76f2, 0x7db2,
+ 0x8017, 0x8499, 0x5132, 0x6728, 0x9ed9, 0x76ee, 0x6762, 0x52ff,
+ 0x9905, 0x5c24, 0x623b, 0x7c7e, 0x8cb0, 0x554f, 0x60b6, 0x7d0b,
+ 0x9580, 0x5301, 0x4e5f, 0x51b6, 0x591c, 0x723a, 0x8036, 0x91ce,
+ 0x5f25, 0x77e2, 0x5384, 0x5f79, 0x7d04, 0x85ac, 0x8a33, 0x8e8d,
+ 0x9756, 0x67f3, 0x85ae, 0x9453, 0x6109, 0x6108, 0x6cb9, 0x7652,
+ 0x8aed, 0x8f38, 0x552f, 0x4f51, 0x512a, 0x52c7, 0x53cb, 0x5ba5,
+ 0x5e7d, 0x60a0, 0x6182, 0x63d6, 0x6709, 0x67da, 0x6e67, 0x6d8c,
+ 0x7336, 0x7337, 0x7531, 0x7950, 0x88d5, 0x8a98, 0x904a, 0x9091,
+ 0x90f5, 0x96c4, 0x878d, 0x5915, 0x4e88, 0x4f59, 0x4e0e, 0x8a89,
+ 0x8f3f, 0x9810, 0x50ad, 0x5e7c, 0x5996, 0x5bb9, 0x5eb8, 0x63da,
+ 0x63fa, 0x64c1, 0x66dc, 0x694a, 0x69d8, 0x6d0b, 0x6eb6, 0x7194,
+ 0x7528, 0x7aaf, 0x7f8a, 0x8000, 0x8449, 0x84c9, 0x8981, 0x8b21,
+ 0x8e0a, 0x9065, 0x967d, 0x990a, 0x617e, 0x6291, 0x6b32, 0x6c83,
+ 0x6d74, 0x7fcc, 0x7ffc, 0x6dc0, 0x7f85, 0x87ba, 0x88f8, 0x6765,
+ 0x83b1, 0x983c, 0x96f7, 0x6d1b, 0x7d61, 0x843d, 0x916a, 0x4e71,
+ 0x5375, 0x5d50, 0x6b04, 0x6feb, 0x85cd, 0x862d, 0x89a7, 0x5229,
+ 0x540f, 0x5c65, 0x674e, 0x68a8, 0x7406, 0x7483, 0x75e2, 0x88cf,
+ 0x88e1, 0x91cc, 0x96e2, 0x9678, 0x5f8b, 0x7387, 0x7acb, 0x844e,
+ 0x63a0, 0x7565, 0x5289, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b,
+ 0x7c92, 0x9686, 0x7adc, 0x9f8d, 0x4fb6, 0x616e, 0x65c5, 0x865c,
+ 0x4e86, 0x4eae, 0x50da, 0x4e21, 0x51cc, 0x5bee, 0x6599, 0x6881,
+ 0x6dbc, 0x731f, 0x7642, 0x77ad, 0x7a1c, 0x7ce7, 0x826f, 0x8ad2,
+ 0x907c, 0x91cf, 0x9675, 0x9818, 0x529b, 0x7dd1, 0x502b, 0x5398,
+ 0x6797, 0x6dcb, 0x71d0, 0x7433, 0x81e8, 0x8f2a, 0x96a3, 0x9c57,
+ 0x9e9f, 0x7460, 0x5841, 0x6d99, 0x7d2f, 0x985e, 0x4ee4, 0x4f36,
+ 0x4f8b, 0x51b7, 0x52b1, 0x5dba, 0x601c, 0x73b2, 0x793c, 0x82d3,
+ 0x9234, 0x96b7, 0x96f6, 0x970a, 0x9e97, 0x9f62, 0x66a6, 0x6b74,
+ 0x5217, 0x52a3, 0x70c8, 0x88c2, 0x5ec9, 0x604b, 0x6190, 0x6f23,
+ 0x7149, 0x7c3e, 0x7df4, 0x806f, 0x84ee, 0x9023, 0x932c, 0x5442,
+ 0x9b6f, 0x6ad3, 0x7089, 0x8cc2, 0x8def, 0x9732, 0x52b4, 0x5a41,
+ 0x5eca, 0x5f04, 0x6717, 0x697c, 0x6994, 0x6d6a, 0x6f0f, 0x7262,
+ 0x72fc, 0x7bed, 0x8001, 0x807e, 0x874b, 0x90ce, 0x516d, 0x9e93,
+ 0x7984, 0x808b, 0x9332, 0x8ad6, 0x502d, 0x548c, 0x8a71, 0x6b6a,
+ 0x8cc4, 0x8107, 0x60d1, 0x67a0, 0x9df2, 0x4e99, 0x4e98, 0x9c10,
+ 0x8a6b, 0x85c1, 0x8568, 0x6900, 0x6e7e, 0x7897, 0x8155, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5f0c, 0x4e10, 0x4e15, 0x4e2a, 0x4e31, 0x4e36,
+ 0x4e3c, 0x4e3f, 0x4e42, 0x4e56, 0x4e58, 0x4e82, 0x4e85, 0x8c6b,
+ 0x4e8a, 0x8212, 0x5f0d, 0x4e8e, 0x4e9e, 0x4e9f, 0x4ea0, 0x4ea2,
+ 0x4eb0, 0x4eb3, 0x4eb6, 0x4ece, 0x4ecd, 0x4ec4, 0x4ec6, 0x4ec2,
+ 0x4ed7, 0x4ede, 0x4eed, 0x4edf, 0x4ef7, 0x4f09, 0x4f5a, 0x4f30,
+ 0x4f5b, 0x4f5d, 0x4f57, 0x4f47, 0x4f76, 0x4f88, 0x4f8f, 0x4f98,
+ 0x4f7b, 0x4f69, 0x4f70, 0x4f91, 0x4f6f, 0x4f86, 0x4f96, 0x5118,
+ 0x4fd4, 0x4fdf, 0x4fce, 0x4fd8, 0x4fdb, 0x4fd1, 0x4fda, 0x4fd0,
+ 0x4fe4, 0x4fe5, 0x501a, 0x5028, 0x5014, 0x502a, 0x5025, 0x5005,
+ 0x4f1c, 0x4ff6, 0x5021, 0x5029, 0x502c, 0x4ffe, 0x4fef, 0x5011,
+ 0x5006, 0x5043, 0x5047, 0x6703, 0x5055, 0x5050, 0x5048, 0x505a,
+ 0x5056, 0x506c, 0x5078, 0x5080, 0x509a, 0x5085, 0x50b4, 0x50b2,
+ 0x50c9, 0x50ca, 0x50b3, 0x50c2, 0x50d6, 0x50de, 0x50e5, 0x50ed,
+ 0x50e3, 0x50ee, 0x50f9, 0x50f5, 0x5109, 0x5101, 0x5102, 0x5116,
+ 0x5115, 0x5114, 0x511a, 0x5121, 0x513a, 0x5137, 0x513c, 0x513b,
+ 0x513f, 0x5140, 0x5152, 0x514c, 0x5154, 0x5162, 0x7af8, 0x5169,
+ 0x516a, 0x516e, 0x5180, 0x5182, 0x56d8, 0x518c, 0x5189, 0x518f,
+ 0x5191, 0x5193, 0x5195, 0x5196, 0x51a4, 0x51a6, 0x51a2, 0x51a9,
+ 0x51aa, 0x51ab, 0x51b3, 0x51b1, 0x51b2, 0x51b0, 0x51b5, 0x51bd,
+ 0x51c5, 0x51c9, 0x51db, 0x51e0, 0x8655, 0x51e9, 0x51ed, 0x51f0,
+ 0x51f5, 0x51fe, 0x5204, 0x520b, 0x5214, 0x520e, 0x5227, 0x522a,
+ 0x522e, 0x5233, 0x5239, 0x524f, 0x5244, 0x524b, 0x524c, 0x525e,
+ 0x5254, 0x526a, 0x5274, 0x5269, 0x5273, 0x527f, 0x527d, 0x528d,
+ 0x5294, 0x5292, 0x5271, 0x5288, 0x5291, 0x8fa8, 0x8fa7, 0x52ac,
+ 0x52ad, 0x52bc, 0x52b5, 0x52c1, 0x52cd, 0x52d7, 0x52de, 0x52e3,
+ 0x52e6, 0x98ed, 0x52e0, 0x52f3, 0x52f5, 0x52f8, 0x52f9, 0x5306,
+ 0x5308, 0x7538, 0x530d, 0x5310, 0x530f, 0x5315, 0x531a, 0x5323,
+ 0x532f, 0x5331, 0x5333, 0x5338, 0x5340, 0x5346, 0x5345, 0x4e17,
+ 0x5349, 0x534d, 0x51d6, 0x535e, 0x5369, 0x536e, 0x5918, 0x537b,
+ 0x5377, 0x5382, 0x5396, 0x53a0, 0x53a6, 0x53a5, 0x53ae, 0x53b0,
+ 0x53b6, 0x53c3, 0x7c12, 0x96d9, 0x53df, 0x66fc, 0x71ee, 0x53ee,
+ 0x53e8, 0x53ed, 0x53fa, 0x5401, 0x543d, 0x5440, 0x542c, 0x542d,
+ 0x543c, 0x542e, 0x5436, 0x5429, 0x541d, 0x544e, 0x548f, 0x5475,
+ 0x548e, 0x545f, 0x5471, 0x5477, 0x5470, 0x5492, 0x547b, 0x5480,
+ 0x5476, 0x5484, 0x5490, 0x5486, 0x54c7, 0x54a2, 0x54b8, 0x54a5,
+ 0x54ac, 0x54c4, 0x54c8, 0x54a8, 0x54ab, 0x54c2, 0x54a4, 0x54be,
+ 0x54bc, 0x54d8, 0x54e5, 0x54e6, 0x550f, 0x5514, 0x54fd, 0x54ee,
+ 0x54ed, 0x54fa, 0x54e2, 0x5539, 0x5540, 0x5563, 0x554c, 0x552e,
+ 0x555c, 0x5545, 0x5556, 0x5557, 0x5538, 0x5533, 0x555d, 0x5599,
+ 0x5580, 0x54af, 0x558a, 0x559f, 0x557b, 0x557e, 0x5598, 0x559e,
+ 0x55ae, 0x557c, 0x5583, 0x55a9, 0x5587, 0x55a8, 0x55da, 0x55c5,
+ 0x55df, 0x55c4, 0x55dc, 0x55e4, 0x55d4, 0x5614, 0x55f7, 0x5616,
+ 0x55fe, 0x55fd, 0x561b, 0x55f9, 0x564e, 0x5650, 0x71df, 0x5634,
+ 0x5636, 0x5632, 0x5638, 0x566b, 0x5664, 0x562f, 0x566c, 0x566a,
+ 0x5686, 0x5680, 0x568a, 0x56a0, 0x5694, 0x568f, 0x56a5, 0x56ae,
+ 0x56b6, 0x56b4, 0x56c2, 0x56bc, 0x56c1, 0x56c3, 0x56c0, 0x56c8,
+ 0x56ce, 0x56d1, 0x56d3, 0x56d7, 0x56ee, 0x56f9, 0x5700, 0x56ff,
+ 0x5704, 0x5709, 0x5708, 0x570b, 0x570d, 0x5713, 0x5718, 0x5716,
+ 0x55c7, 0x571c, 0x5726, 0x5737, 0x5738, 0x574e, 0x573b, 0x5740,
+ 0x574f, 0x5769, 0x57c0, 0x5788, 0x5761, 0x577f, 0x5789, 0x5793,
+ 0x57a0, 0x57b3, 0x57a4, 0x57aa, 0x57b0, 0x57c3, 0x57c6, 0x57d4,
+ 0x57d2, 0x57d3, 0x580a, 0x57d6, 0x57e3, 0x580b, 0x5819, 0x581d,
+ 0x5872, 0x5821, 0x5862, 0x584b, 0x5870, 0x6bc0, 0x5852, 0x583d,
+ 0x5879, 0x5885, 0x58b9, 0x589f, 0x58ab, 0x58ba, 0x58de, 0x58bb,
+ 0x58b8, 0x58ae, 0x58c5, 0x58d3, 0x58d1, 0x58d7, 0x58d9, 0x58d8,
+ 0x58e5, 0x58dc, 0x58e4, 0x58df, 0x58ef, 0x58fa, 0x58f9, 0x58fb,
+ 0x58fc, 0x58fd, 0x5902, 0x590a, 0x5910, 0x591b, 0x68a6, 0x5925,
+ 0x592c, 0x592d, 0x5932, 0x5938, 0x593e, 0x7ad2, 0x5955, 0x5950,
+ 0x594e, 0x595a, 0x5958, 0x5962, 0x5960, 0x5967, 0x596c, 0x5969,
+ 0x5978, 0x5981, 0x599d, 0x4f5e, 0x4fab, 0x59a3, 0x59b2, 0x59c6,
+ 0x59e8, 0x59dc, 0x598d, 0x59d9, 0x59da, 0x5a25, 0x5a1f, 0x5a11,
+ 0x5a1c, 0x5a09, 0x5a1a, 0x5a40, 0x5a6c, 0x5a49, 0x5a35, 0x5a36,
+ 0x5a62, 0x5a6a, 0x5a9a, 0x5abc, 0x5abe, 0x5acb, 0x5ac2, 0x5abd,
+ 0x5ae3, 0x5ad7, 0x5ae6, 0x5ae9, 0x5ad6, 0x5afa, 0x5afb, 0x5b0c,
+ 0x5b0b, 0x5b16, 0x5b32, 0x5ad0, 0x5b2a, 0x5b36, 0x5b3e, 0x5b43,
+ 0x5b45, 0x5b40, 0x5b51, 0x5b55, 0x5b5a, 0x5b5b, 0x5b65, 0x5b69,
+ 0x5b70, 0x5b73, 0x5b75, 0x5b78, 0x6588, 0x5b7a, 0x5b80, 0x5b83,
+ 0x5ba6, 0x5bb8, 0x5bc3, 0x5bc7, 0x5bc9, 0x5bd4, 0x5bd0, 0x5be4,
+ 0x5be6, 0x5be2, 0x5bde, 0x5be5, 0x5beb, 0x5bf0, 0x5bf6, 0x5bf3,
+ 0x5c05, 0x5c07, 0x5c08, 0x5c0d, 0x5c13, 0x5c20, 0x5c22, 0x5c28,
+ 0x5c38, 0x5c39, 0x5c41, 0x5c46, 0x5c4e, 0x5c53, 0x5c50, 0x5c4f,
+ 0x5b71, 0x5c6c, 0x5c6e, 0x4e62, 0x5c76, 0x5c79, 0x5c8c, 0x5c91,
+ 0x5c94, 0x599b, 0x5cab, 0x5cbb, 0x5cb6, 0x5cbc, 0x5cb7, 0x5cc5,
+ 0x5cbe, 0x5cc7, 0x5cd9, 0x5ce9, 0x5cfd, 0x5cfa, 0x5ced, 0x5d8c,
+ 0x5cea, 0x5d0b, 0x5d15, 0x5d17, 0x5d5c, 0x5d1f, 0x5d1b, 0x5d11,
+ 0x5d14, 0x5d22, 0x5d1a, 0x5d19, 0x5d18, 0x5d4c, 0x5d52, 0x5d4e,
+ 0x5d4b, 0x5d6c, 0x5d73, 0x5d76, 0x5d87, 0x5d84, 0x5d82, 0x5da2,
+ 0x5d9d, 0x5dac, 0x5dae, 0x5dbd, 0x5d90, 0x5db7, 0x5dbc, 0x5dc9,
+ 0x5dcd, 0x5dd3, 0x5dd2, 0x5dd6, 0x5ddb, 0x5deb, 0x5df2, 0x5df5,
+ 0x5e0b, 0x5e1a, 0x5e19, 0x5e11, 0x5e1b, 0x5e36, 0x5e37, 0x5e44,
+ 0x5e43, 0x5e40, 0x5e4e, 0x5e57, 0x5e54, 0x5e5f, 0x5e62, 0x5e64,
+ 0x5e47, 0x5e75, 0x5e76, 0x5e7a, 0x9ebc, 0x5e7f, 0x5ea0, 0x5ec1,
+ 0x5ec2, 0x5ec8, 0x5ed0, 0x5ecf, 0x5ed6, 0x5ee3, 0x5edd, 0x5eda,
+ 0x5edb, 0x5ee2, 0x5ee1, 0x5ee8, 0x5ee9, 0x5eec, 0x5ef1, 0x5ef3,
+ 0x5ef0, 0x5ef4, 0x5ef8, 0x5efe, 0x5f03, 0x5f09, 0x5f5d, 0x5f5c,
+ 0x5f0b, 0x5f11, 0x5f16, 0x5f29, 0x5f2d, 0x5f38, 0x5f41, 0x5f48,
+ 0x5f4c, 0x5f4e, 0x5f2f, 0x5f51, 0x5f56, 0x5f57, 0x5f59, 0x5f61,
+ 0x5f6d, 0x5f73, 0x5f77, 0x5f83, 0x5f82, 0x5f7f, 0x5f8a, 0x5f88,
+ 0x5f91, 0x5f87, 0x5f9e, 0x5f99, 0x5f98, 0x5fa0, 0x5fa8, 0x5fad,
+ 0x5fbc, 0x5fd6, 0x5ffb, 0x5fe4, 0x5ff8, 0x5ff1, 0x5fdd, 0x60b3,
+ 0x5fff, 0x6021, 0x6060, 0x6019, 0x6010, 0x6029, 0x600e, 0x6031,
+ 0x601b, 0x6015, 0x602b, 0x6026, 0x600f, 0x603a, 0x605a, 0x6041,
+ 0x606a, 0x6077, 0x605f, 0x604a, 0x6046, 0x604d, 0x6063, 0x6043,
+ 0x6064, 0x6042, 0x606c, 0x606b, 0x6059, 0x6081, 0x608d, 0x60e7,
+ 0x6083, 0x609a, 0x6084, 0x609b, 0x6096, 0x6097, 0x6092, 0x60a7,
+ 0x608b, 0x60e1, 0x60b8, 0x60e0, 0x60d3, 0x60b4, 0x5ff0, 0x60bd,
+ 0x60c6, 0x60b5, 0x60d8, 0x614d, 0x6115, 0x6106, 0x60f6, 0x60f7,
+ 0x6100, 0x60f4, 0x60fa, 0x6103, 0x6121, 0x60fb, 0x60f1, 0x610d,
+ 0x610e, 0x6147, 0x613e, 0x6128, 0x6127, 0x614a, 0x613f, 0x613c,
+ 0x612c, 0x6134, 0x613d, 0x6142, 0x6144, 0x6173, 0x6177, 0x6158,
+ 0x6159, 0x615a, 0x616b, 0x6174, 0x616f, 0x6165, 0x6171, 0x615f,
+ 0x615d, 0x6153, 0x6175, 0x6199, 0x6196, 0x6187, 0x61ac, 0x6194,
+ 0x619a, 0x618a, 0x6191, 0x61ab, 0x61ae, 0x61cc, 0x61ca, 0x61c9,
+ 0x61f7, 0x61c8, 0x61c3, 0x61c6, 0x61ba, 0x61cb, 0x7f79, 0x61cd,
+ 0x61e6, 0x61e3, 0x61f6, 0x61fa, 0x61f4, 0x61ff, 0x61fd, 0x61fc,
+ 0x61fe, 0x6200, 0x6208, 0x6209, 0x620d, 0x620c, 0x6214, 0x621b,
+ 0x621e, 0x6221, 0x622a, 0x622e, 0x6230, 0x6232, 0x6233, 0x6241,
+ 0x624e, 0x625e, 0x6263, 0x625b, 0x6260, 0x6268, 0x627c, 0x6282,
+ 0x6289, 0x627e, 0x6292, 0x6293, 0x6296, 0x62d4, 0x6283, 0x6294,
+ 0x62d7, 0x62d1, 0x62bb, 0x62cf, 0x62ff, 0x62c6, 0x64d4, 0x62c8,
+ 0x62dc, 0x62cc, 0x62ca, 0x62c2, 0x62c7, 0x629b, 0x62c9, 0x630c,
+ 0x62ee, 0x62f1, 0x6327, 0x6302, 0x6308, 0x62ef, 0x62f5, 0x6350,
+ 0x633e, 0x634d, 0x641c, 0x634f, 0x6396, 0x638e, 0x6380, 0x63ab,
+ 0x6376, 0x63a3, 0x638f, 0x6389, 0x639f, 0x63b5, 0x636b, 0x6369,
+ 0x63be, 0x63e9, 0x63c0, 0x63c6, 0x63e3, 0x63c9, 0x63d2, 0x63f6,
+ 0x63c4, 0x6416, 0x6434, 0x6406, 0x6413, 0x6426, 0x6436, 0x651d,
+ 0x6417, 0x6428, 0x640f, 0x6467, 0x646f, 0x6476, 0x644e, 0x652a,
+ 0x6495, 0x6493, 0x64a5, 0x64a9, 0x6488, 0x64bc, 0x64da, 0x64d2,
+ 0x64c5, 0x64c7, 0x64bb, 0x64d8, 0x64c2, 0x64f1, 0x64e7, 0x8209,
+ 0x64e0, 0x64e1, 0x62ac, 0x64e3, 0x64ef, 0x652c, 0x64f6, 0x64f4,
+ 0x64f2, 0x64fa, 0x6500, 0x64fd, 0x6518, 0x651c, 0x6505, 0x6524,
+ 0x6523, 0x652b, 0x6534, 0x6535, 0x6537, 0x6536, 0x6538, 0x754b,
+ 0x6548, 0x6556, 0x6555, 0x654d, 0x6558, 0x655e, 0x655d, 0x6572,
+ 0x6578, 0x6582, 0x6583, 0x8b8a, 0x659b, 0x659f, 0x65ab, 0x65b7,
+ 0x65c3, 0x65c6, 0x65c1, 0x65c4, 0x65cc, 0x65d2, 0x65db, 0x65d9,
+ 0x65e0, 0x65e1, 0x65f1, 0x6772, 0x660a, 0x6603, 0x65fb, 0x6773,
+ 0x6635, 0x6636, 0x6634, 0x661c, 0x664f, 0x6644, 0x6649, 0x6641,
+ 0x665e, 0x665d, 0x6664, 0x6667, 0x6668, 0x665f, 0x6662, 0x6670,
+ 0x6683, 0x6688, 0x668e, 0x6689, 0x6684, 0x6698, 0x669d, 0x66c1,
+ 0x66b9, 0x66c9, 0x66be, 0x66bc, 0x66c4, 0x66b8, 0x66d6, 0x66da,
+ 0x66e0, 0x663f, 0x66e6, 0x66e9, 0x66f0, 0x66f5, 0x66f7, 0x670f,
+ 0x6716, 0x671e, 0x6726, 0x6727, 0x9738, 0x672e, 0x673f, 0x6736,
+ 0x6741, 0x6738, 0x6737, 0x6746, 0x675e, 0x6760, 0x6759, 0x6763,
+ 0x6764, 0x6789, 0x6770, 0x67a9, 0x677c, 0x676a, 0x678c, 0x678b,
+ 0x67a6, 0x67a1, 0x6785, 0x67b7, 0x67ef, 0x67b4, 0x67ec, 0x67b3,
+ 0x67e9, 0x67b8, 0x67e4, 0x67de, 0x67dd, 0x67e2, 0x67ee, 0x67b9,
+ 0x67ce, 0x67c6, 0x67e7, 0x6a9c, 0x681e, 0x6846, 0x6829, 0x6840,
+ 0x684d, 0x6832, 0x684e, 0x68b3, 0x682b, 0x6859, 0x6863, 0x6877,
+ 0x687f, 0x689f, 0x688f, 0x68ad, 0x6894, 0x689d, 0x689b, 0x6883,
+ 0x6aae, 0x68b9, 0x6874, 0x68b5, 0x68a0, 0x68ba, 0x690f, 0x688d,
+ 0x687e, 0x6901, 0x68ca, 0x6908, 0x68d8, 0x6922, 0x6926, 0x68e1,
+ 0x690c, 0x68cd, 0x68d4, 0x68e7, 0x68d5, 0x6936, 0x6912, 0x6904,
+ 0x68d7, 0x68e3, 0x6925, 0x68f9, 0x68e0, 0x68ef, 0x6928, 0x692a,
+ 0x691a, 0x6923, 0x6921, 0x68c6, 0x6979, 0x6977, 0x695c, 0x6978,
+ 0x696b, 0x6954, 0x697e, 0x696e, 0x6939, 0x6974, 0x693d, 0x6959,
+ 0x6930, 0x6961, 0x695e, 0x695d, 0x6981, 0x696a, 0x69b2, 0x69ae,
+ 0x69d0, 0x69bf, 0x69c1, 0x69d3, 0x69be, 0x69ce, 0x5be8, 0x69ca,
+ 0x69dd, 0x69bb, 0x69c3, 0x69a7, 0x6a2e, 0x6991, 0x69a0, 0x699c,
+ 0x6995, 0x69b4, 0x69de, 0x69e8, 0x6a02, 0x6a1b, 0x69ff, 0x6b0a,
+ 0x69f9, 0x69f2, 0x69e7, 0x6a05, 0x69b1, 0x6a1e, 0x69ed, 0x6a14,
+ 0x69eb, 0x6a0a, 0x6a12, 0x6ac1, 0x6a23, 0x6a13, 0x6a44, 0x6a0c,
+ 0x6a72, 0x6a36, 0x6a78, 0x6a47, 0x6a62, 0x6a59, 0x6a66, 0x6a48,
+ 0x6a38, 0x6a22, 0x6a90, 0x6a8d, 0x6aa0, 0x6a84, 0x6aa2, 0x6aa3,
+ 0x6a97, 0x8617, 0x6abb, 0x6ac3, 0x6ac2, 0x6ab8, 0x6ab3, 0x6aac,
+ 0x6ade, 0x6ad1, 0x6adf, 0x6aaa, 0x6ada, 0x6aea, 0x6afb, 0x6b05,
+ 0x8616, 0x6afa, 0x6b12, 0x6b16, 0x9b31, 0x6b1f, 0x6b38, 0x6b37,
+ 0x76dc, 0x6b39, 0x98ee, 0x6b47, 0x6b43, 0x6b49, 0x6b50, 0x6b59,
+ 0x6b54, 0x6b5b, 0x6b5f, 0x6b61, 0x6b78, 0x6b79, 0x6b7f, 0x6b80,
+ 0x6b84, 0x6b83, 0x6b8d, 0x6b98, 0x6b95, 0x6b9e, 0x6ba4, 0x6baa,
+ 0x6bab, 0x6baf, 0x6bb2, 0x6bb1, 0x6bb3, 0x6bb7, 0x6bbc, 0x6bc6,
+ 0x6bcb, 0x6bd3, 0x6bdf, 0x6bec, 0x6beb, 0x6bf3, 0x6bef, 0x9ebe,
+ 0x6c08, 0x6c13, 0x6c14, 0x6c1b, 0x6c24, 0x6c23, 0x6c5e, 0x6c55,
+ 0x6c62, 0x6c6a, 0x6c82, 0x6c8d, 0x6c9a, 0x6c81, 0x6c9b, 0x6c7e,
+ 0x6c68, 0x6c73, 0x6c92, 0x6c90, 0x6cc4, 0x6cf1, 0x6cd3, 0x6cbd,
+ 0x6cd7, 0x6cc5, 0x6cdd, 0x6cae, 0x6cb1, 0x6cbe, 0x6cba, 0x6cdb,
+ 0x6cef, 0x6cd9, 0x6cea, 0x6d1f, 0x884d, 0x6d36, 0x6d2b, 0x6d3d,
+ 0x6d38, 0x6d19, 0x6d35, 0x6d33, 0x6d12, 0x6d0c, 0x6d63, 0x6d93,
+ 0x6d64, 0x6d5a, 0x6d79, 0x6d59, 0x6d8e, 0x6d95, 0x6fe4, 0x6d85,
+ 0x6df9, 0x6e15, 0x6e0a, 0x6db5, 0x6dc7, 0x6de6, 0x6db8, 0x6dc6,
+ 0x6dec, 0x6dde, 0x6dcc, 0x6de8, 0x6dd2, 0x6dc5, 0x6dfa, 0x6dd9,
+ 0x6de4, 0x6dd5, 0x6dea, 0x6dee, 0x6e2d, 0x6e6e, 0x6e2e, 0x6e19,
+ 0x6e72, 0x6e5f, 0x6e3e, 0x6e23, 0x6e6b, 0x6e2b, 0x6e76, 0x6e4d,
+ 0x6e1f, 0x6e43, 0x6e3a, 0x6e4e, 0x6e24, 0x6eff, 0x6e1d, 0x6e38,
+ 0x6e82, 0x6eaa, 0x6e98, 0x6ec9, 0x6eb7, 0x6ed3, 0x6ebd, 0x6eaf,
+ 0x6ec4, 0x6eb2, 0x6ed4, 0x6ed5, 0x6e8f, 0x6ea5, 0x6ec2, 0x6e9f,
+ 0x6f41, 0x6f11, 0x704c, 0x6eec, 0x6ef8, 0x6efe, 0x6f3f, 0x6ef2,
+ 0x6f31, 0x6eef, 0x6f32, 0x6ecc, 0x6f3e, 0x6f13, 0x6ef7, 0x6f86,
+ 0x6f7a, 0x6f78, 0x6f81, 0x6f80, 0x6f6f, 0x6f5b, 0x6ff3, 0x6f6d,
+ 0x6f82, 0x6f7c, 0x6f58, 0x6f8e, 0x6f91, 0x6fc2, 0x6f66, 0x6fb3,
+ 0x6fa3, 0x6fa1, 0x6fa4, 0x6fb9, 0x6fc6, 0x6faa, 0x6fdf, 0x6fd5,
+ 0x6fec, 0x6fd4, 0x6fd8, 0x6ff1, 0x6fee, 0x6fdb, 0x7009, 0x700b,
+ 0x6ffa, 0x7011, 0x7001, 0x700f, 0x6ffe, 0x701b, 0x701a, 0x6f74,
+ 0x701d, 0x7018, 0x701f, 0x7030, 0x703e, 0x7032, 0x7051, 0x7063,
+ 0x7099, 0x7092, 0x70af, 0x70f1, 0x70ac, 0x70b8, 0x70b3, 0x70ae,
+ 0x70df, 0x70cb, 0x70dd, 0x70d9, 0x7109, 0x70fd, 0x711c, 0x7119,
+ 0x7165, 0x7155, 0x7188, 0x7166, 0x7162, 0x714c, 0x7156, 0x716c,
+ 0x718f, 0x71fb, 0x7184, 0x7195, 0x71a8, 0x71ac, 0x71d7, 0x71b9,
+ 0x71be, 0x71d2, 0x71c9, 0x71d4, 0x71ce, 0x71e0, 0x71ec, 0x71e7,
+ 0x71f5, 0x71fc, 0x71f9, 0x71ff, 0x720d, 0x7210, 0x721b, 0x7228,
+ 0x722d, 0x722c, 0x7230, 0x7232, 0x723b, 0x723c, 0x723f, 0x7240,
+ 0x7246, 0x724b, 0x7258, 0x7274, 0x727e, 0x7282, 0x7281, 0x7287,
+ 0x7292, 0x7296, 0x72a2, 0x72a7, 0x72b9, 0x72b2, 0x72c3, 0x72c6,
+ 0x72c4, 0x72ce, 0x72d2, 0x72e2, 0x72e0, 0x72e1, 0x72f9, 0x72f7,
+ 0x500f, 0x7317, 0x730a, 0x731c, 0x7316, 0x731d, 0x7334, 0x732f,
+ 0x7329, 0x7325, 0x733e, 0x734e, 0x734f, 0x9ed8, 0x7357, 0x736a,
+ 0x7368, 0x7370, 0x7378, 0x7375, 0x737b, 0x737a, 0x73c8, 0x73b3,
+ 0x73ce, 0x73bb, 0x73c0, 0x73e5, 0x73ee, 0x73de, 0x74a2, 0x7405,
+ 0x746f, 0x7425, 0x73f8, 0x7432, 0x743a, 0x7455, 0x743f, 0x745f,
+ 0x7459, 0x7441, 0x745c, 0x7469, 0x7470, 0x7463, 0x746a, 0x7476,
+ 0x747e, 0x748b, 0x749e, 0x74a7, 0x74ca, 0x74cf, 0x74d4, 0x73f1,
+ 0x74e0, 0x74e3, 0x74e7, 0x74e9, 0x74ee, 0x74f2, 0x74f0, 0x74f1,
+ 0x74f8, 0x74f7, 0x7504, 0x7503, 0x7505, 0x750c, 0x750e, 0x750d,
+ 0x7515, 0x7513, 0x751e, 0x7526, 0x752c, 0x753c, 0x7544, 0x754d,
+ 0x754a, 0x7549, 0x755b, 0x7546, 0x755a, 0x7569, 0x7564, 0x7567,
+ 0x756b, 0x756d, 0x7578, 0x7576, 0x7586, 0x7587, 0x7574, 0x758a,
+ 0x7589, 0x7582, 0x7594, 0x759a, 0x759d, 0x75a5, 0x75a3, 0x75c2,
+ 0x75b3, 0x75c3, 0x75b5, 0x75bd, 0x75b8, 0x75bc, 0x75b1, 0x75cd,
+ 0x75ca, 0x75d2, 0x75d9, 0x75e3, 0x75de, 0x75fe, 0x75ff, 0x75fc,
+ 0x7601, 0x75f0, 0x75fa, 0x75f2, 0x75f3, 0x760b, 0x760d, 0x7609,
+ 0x761f, 0x7627, 0x7620, 0x7621, 0x7622, 0x7624, 0x7634, 0x7630,
+ 0x763b, 0x7647, 0x7648, 0x7646, 0x765c, 0x7658, 0x7661, 0x7662,
+ 0x7668, 0x7669, 0x766a, 0x7667, 0x766c, 0x7670, 0x7672, 0x7676,
+ 0x7678, 0x767c, 0x7680, 0x7683, 0x7688, 0x768b, 0x768e, 0x7696,
+ 0x7693, 0x7699, 0x769a, 0x76b0, 0x76b4, 0x76b8, 0x76b9, 0x76ba,
+ 0x76c2, 0x76cd, 0x76d6, 0x76d2, 0x76de, 0x76e1, 0x76e5, 0x76e7,
+ 0x76ea, 0x862f, 0x76fb, 0x7708, 0x7707, 0x7704, 0x7729, 0x7724,
+ 0x771e, 0x7725, 0x7726, 0x771b, 0x7737, 0x7738, 0x7747, 0x775a,
+ 0x7768, 0x776b, 0x775b, 0x7765, 0x777f, 0x777e, 0x7779, 0x778e,
+ 0x778b, 0x7791, 0x77a0, 0x779e, 0x77b0, 0x77b6, 0x77b9, 0x77bf,
+ 0x77bc, 0x77bd, 0x77bb, 0x77c7, 0x77cd, 0x77d7, 0x77da, 0x77dc,
+ 0x77e3, 0x77ee, 0x77fc, 0x780c, 0x7812, 0x7926, 0x7820, 0x792a,
+ 0x7845, 0x788e, 0x7874, 0x7886, 0x787c, 0x789a, 0x788c, 0x78a3,
+ 0x78b5, 0x78aa, 0x78af, 0x78d1, 0x78c6, 0x78cb, 0x78d4, 0x78be,
+ 0x78bc, 0x78c5, 0x78ca, 0x78ec, 0x78e7, 0x78da, 0x78fd, 0x78f4,
+ 0x7907, 0x7912, 0x7911, 0x7919, 0x792c, 0x792b, 0x7940, 0x7960,
+ 0x7957, 0x795f, 0x795a, 0x7955, 0x7953, 0x797a, 0x797f, 0x798a,
+ 0x799d, 0x79a7, 0x9f4b, 0x79aa, 0x79ae, 0x79b3, 0x79b9, 0x79ba,
+ 0x79c9, 0x79d5, 0x79e7, 0x79ec, 0x79e1, 0x79e3, 0x7a08, 0x7a0d,
+ 0x7a18, 0x7a19, 0x7a20, 0x7a1f, 0x7980, 0x7a31, 0x7a3b, 0x7a3e,
+ 0x7a37, 0x7a43, 0x7a57, 0x7a49, 0x7a61, 0x7a62, 0x7a69, 0x9f9d,
+ 0x7a70, 0x7a79, 0x7a7d, 0x7a88, 0x7a97, 0x7a95, 0x7a98, 0x7a96,
+ 0x7aa9, 0x7ac8, 0x7ab0, 0x7ab6, 0x7ac5, 0x7ac4, 0x7abf, 0x9083,
+ 0x7ac7, 0x7aca, 0x7acd, 0x7acf, 0x7ad5, 0x7ad3, 0x7ad9, 0x7ada,
+ 0x7add, 0x7ae1, 0x7ae2, 0x7ae6, 0x7aed, 0x7af0, 0x7b02, 0x7b0f,
+ 0x7b0a, 0x7b06, 0x7b33, 0x7b18, 0x7b19, 0x7b1e, 0x7b35, 0x7b28,
+ 0x7b36, 0x7b50, 0x7b7a, 0x7b04, 0x7b4d, 0x7b0b, 0x7b4c, 0x7b45,
+ 0x7b75, 0x7b65, 0x7b74, 0x7b67, 0x7b70, 0x7b71, 0x7b6c, 0x7b6e,
+ 0x7b9d, 0x7b98, 0x7b9f, 0x7b8d, 0x7b9c, 0x7b9a, 0x7b8b, 0x7b92,
+ 0x7b8f, 0x7b5d, 0x7b99, 0x7bcb, 0x7bc1, 0x7bcc, 0x7bcf, 0x7bb4,
+ 0x7bc6, 0x7bdd, 0x7be9, 0x7c11, 0x7c14, 0x7be6, 0x7be5, 0x7c60,
+ 0x7c00, 0x7c07, 0x7c13, 0x7bf3, 0x7bf7, 0x7c17, 0x7c0d, 0x7bf6,
+ 0x7c23, 0x7c27, 0x7c2a, 0x7c1f, 0x7c37, 0x7c2b, 0x7c3d, 0x7c4c,
+ 0x7c43, 0x7c54, 0x7c4f, 0x7c40, 0x7c50, 0x7c58, 0x7c5f, 0x7c64,
+ 0x7c56, 0x7c65, 0x7c6c, 0x7c75, 0x7c83, 0x7c90, 0x7ca4, 0x7cad,
+ 0x7ca2, 0x7cab, 0x7ca1, 0x7ca8, 0x7cb3, 0x7cb2, 0x7cb1, 0x7cae,
+ 0x7cb9, 0x7cbd, 0x7cc0, 0x7cc5, 0x7cc2, 0x7cd8, 0x7cd2, 0x7cdc,
+ 0x7ce2, 0x9b3b, 0x7cef, 0x7cf2, 0x7cf4, 0x7cf6, 0x7cfa, 0x7d06,
+ 0x7d02, 0x7d1c, 0x7d15, 0x7d0a, 0x7d45, 0x7d4b, 0x7d2e, 0x7d32,
+ 0x7d3f, 0x7d35, 0x7d46, 0x7d73, 0x7d56, 0x7d4e, 0x7d72, 0x7d68,
+ 0x7d6e, 0x7d4f, 0x7d63, 0x7d93, 0x7d89, 0x7d5b, 0x7d8f, 0x7d7d,
+ 0x7d9b, 0x7dba, 0x7dae, 0x7da3, 0x7db5, 0x7dc7, 0x7dbd, 0x7dab,
+ 0x7e3d, 0x7da2, 0x7daf, 0x7ddc, 0x7db8, 0x7d9f, 0x7db0, 0x7dd8,
+ 0x7ddd, 0x7de4, 0x7dde, 0x7dfb, 0x7df2, 0x7de1, 0x7e05, 0x7e0a,
+ 0x7e23, 0x7e21, 0x7e12, 0x7e31, 0x7e1f, 0x7e09, 0x7e0b, 0x7e22,
+ 0x7e46, 0x7e66, 0x7e3b, 0x7e35, 0x7e39, 0x7e43, 0x7e37, 0x7e32,
+ 0x7e3a, 0x7e67, 0x7e5d, 0x7e56, 0x7e5e, 0x7e59, 0x7e5a, 0x7e79,
+ 0x7e6a, 0x7e69, 0x7e7c, 0x7e7b, 0x7e83, 0x7dd5, 0x7e7d, 0x8fae,
+ 0x7e7f, 0x7e88, 0x7e89, 0x7e8c, 0x7e92, 0x7e90, 0x7e93, 0x7e94,
+ 0x7e96, 0x7e8e, 0x7e9b, 0x7e9c, 0x7f38, 0x7f3a, 0x7f45, 0x7f4c,
+ 0x7f4d, 0x7f4e, 0x7f50, 0x7f51, 0x7f55, 0x7f54, 0x7f58, 0x7f5f,
+ 0x7f60, 0x7f68, 0x7f69, 0x7f67, 0x7f78, 0x7f82, 0x7f86, 0x7f83,
+ 0x7f88, 0x7f87, 0x7f8c, 0x7f94, 0x7f9e, 0x7f9d, 0x7f9a, 0x7fa3,
+ 0x7faf, 0x7fb2, 0x7fb9, 0x7fae, 0x7fb6, 0x7fb8, 0x8b71, 0x7fc5,
+ 0x7fc6, 0x7fca, 0x7fd5, 0x7fd4, 0x7fe1, 0x7fe6, 0x7fe9, 0x7ff3,
+ 0x7ff9, 0x98dc, 0x8006, 0x8004, 0x800b, 0x8012, 0x8018, 0x8019,
+ 0x801c, 0x8021, 0x8028, 0x803f, 0x803b, 0x804a, 0x8046, 0x8052,
+ 0x8058, 0x805a, 0x805f, 0x8062, 0x8068, 0x8073, 0x8072, 0x8070,
+ 0x8076, 0x8079, 0x807d, 0x807f, 0x8084, 0x8086, 0x8085, 0x809b,
+ 0x8093, 0x809a, 0x80ad, 0x5190, 0x80ac, 0x80db, 0x80e5, 0x80d9,
+ 0x80dd, 0x80c4, 0x80da, 0x80d6, 0x8109, 0x80ef, 0x80f1, 0x811b,
+ 0x8129, 0x8123, 0x812f, 0x814b, 0x968b, 0x8146, 0x813e, 0x8153,
+ 0x8151, 0x80fc, 0x8171, 0x816e, 0x8165, 0x8166, 0x8174, 0x8183,
+ 0x8188, 0x818a, 0x8180, 0x8182, 0x81a0, 0x8195, 0x81a4, 0x81a3,
+ 0x815f, 0x8193, 0x81a9, 0x81b0, 0x81b5, 0x81be, 0x81b8, 0x81bd,
+ 0x81c0, 0x81c2, 0x81ba, 0x81c9, 0x81cd, 0x81d1, 0x81d9, 0x81d8,
+ 0x81c8, 0x81da, 0x81df, 0x81e0, 0x81e7, 0x81fa, 0x81fb, 0x81fe,
+ 0x8201, 0x8202, 0x8205, 0x8207, 0x820a, 0x820d, 0x8210, 0x8216,
+ 0x8229, 0x822b, 0x8238, 0x8233, 0x8240, 0x8259, 0x8258, 0x825d,
+ 0x825a, 0x825f, 0x8264, 0x8262, 0x8268, 0x826a, 0x826b, 0x822e,
+ 0x8271, 0x8277, 0x8278, 0x827e, 0x828d, 0x8292, 0x82ab, 0x829f,
+ 0x82bb, 0x82ac, 0x82e1, 0x82e3, 0x82df, 0x82d2, 0x82f4, 0x82f3,
+ 0x82fa, 0x8393, 0x8303, 0x82fb, 0x82f9, 0x82de, 0x8306, 0x82dc,
+ 0x8309, 0x82d9, 0x8335, 0x8334, 0x8316, 0x8332, 0x8331, 0x8340,
+ 0x8339, 0x8350, 0x8345, 0x832f, 0x832b, 0x8317, 0x8318, 0x8385,
+ 0x839a, 0x83aa, 0x839f, 0x83a2, 0x8396, 0x8323, 0x838e, 0x8387,
+ 0x838a, 0x837c, 0x83b5, 0x8373, 0x8375, 0x83a0, 0x8389, 0x83a8,
+ 0x83f4, 0x8413, 0x83eb, 0x83ce, 0x83fd, 0x8403, 0x83d8, 0x840b,
+ 0x83c1, 0x83f7, 0x8407, 0x83e0, 0x83f2, 0x840d, 0x8422, 0x8420,
+ 0x83bd, 0x8438, 0x8506, 0x83fb, 0x846d, 0x842a, 0x843c, 0x855a,
+ 0x8484, 0x8477, 0x846b, 0x84ad, 0x846e, 0x8482, 0x8469, 0x8446,
+ 0x842c, 0x846f, 0x8479, 0x8435, 0x84ca, 0x8462, 0x84b9, 0x84bf,
+ 0x849f, 0x84d9, 0x84cd, 0x84bb, 0x84da, 0x84d0, 0x84c1, 0x84c6,
+ 0x84d6, 0x84a1, 0x8521, 0x84ff, 0x84f4, 0x8517, 0x8518, 0x852c,
+ 0x851f, 0x8515, 0x8514, 0x84fc, 0x8540, 0x8563, 0x8558, 0x8548,
+ 0x8541, 0x8602, 0x854b, 0x8555, 0x8580, 0x85a4, 0x8588, 0x8591,
+ 0x858a, 0x85a8, 0x856d, 0x8594, 0x859b, 0x85ea, 0x8587, 0x859c,
+ 0x8577, 0x857e, 0x8590, 0x85c9, 0x85ba, 0x85cf, 0x85b9, 0x85d0,
+ 0x85d5, 0x85dd, 0x85e5, 0x85dc, 0x85f9, 0x860a, 0x8613, 0x860b,
+ 0x85fe, 0x85fa, 0x8606, 0x8622, 0x861a, 0x8630, 0x863f, 0x864d,
+ 0x4e55, 0x8654, 0x865f, 0x8667, 0x8671, 0x8693, 0x86a3, 0x86a9,
+ 0x86aa, 0x868b, 0x868c, 0x86b6, 0x86af, 0x86c4, 0x86c6, 0x86b0,
+ 0x86c9, 0x8823, 0x86ab, 0x86d4, 0x86de, 0x86e9, 0x86ec, 0x86df,
+ 0x86db, 0x86ef, 0x8712, 0x8706, 0x8708, 0x8700, 0x8703, 0x86fb,
+ 0x8711, 0x8709, 0x870d, 0x86f9, 0x870a, 0x8734, 0x873f, 0x8737,
+ 0x873b, 0x8725, 0x8729, 0x871a, 0x8760, 0x875f, 0x8778, 0x874c,
+ 0x874e, 0x8774, 0x8757, 0x8768, 0x876e, 0x8759, 0x8753, 0x8763,
+ 0x876a, 0x8805, 0x87a2, 0x879f, 0x8782, 0x87af, 0x87cb, 0x87bd,
+ 0x87c0, 0x87d0, 0x96d6, 0x87ab, 0x87c4, 0x87b3, 0x87c7, 0x87c6,
+ 0x87bb, 0x87ef, 0x87f2, 0x87e0, 0x880f, 0x880d, 0x87fe, 0x87f6,
+ 0x87f7, 0x880e, 0x87d2, 0x8811, 0x8816, 0x8815, 0x8822, 0x8821,
+ 0x8831, 0x8836, 0x8839, 0x8827, 0x883b, 0x8844, 0x8842, 0x8852,
+ 0x8859, 0x885e, 0x8862, 0x886b, 0x8881, 0x887e, 0x889e, 0x8875,
+ 0x887d, 0x88b5, 0x8872, 0x8882, 0x8897, 0x8892, 0x88ae, 0x8899,
+ 0x88a2, 0x888d, 0x88a4, 0x88b0, 0x88bf, 0x88b1, 0x88c3, 0x88c4,
+ 0x88d4, 0x88d8, 0x88d9, 0x88dd, 0x88f9, 0x8902, 0x88fc, 0x88f4,
+ 0x88e8, 0x88f2, 0x8904, 0x890c, 0x890a, 0x8913, 0x8943, 0x891e,
+ 0x8925, 0x892a, 0x892b, 0x8941, 0x8944, 0x893b, 0x8936, 0x8938,
+ 0x894c, 0x891d, 0x8960, 0x895e, 0x8966, 0x8964, 0x896d, 0x896a,
+ 0x896f, 0x8974, 0x8977, 0x897e, 0x8983, 0x8988, 0x898a, 0x8993,
+ 0x8998, 0x89a1, 0x89a9, 0x89a6, 0x89ac, 0x89af, 0x89b2, 0x89ba,
+ 0x89bd, 0x89bf, 0x89c0, 0x89da, 0x89dc, 0x89dd, 0x89e7, 0x89f4,
+ 0x89f8, 0x8a03, 0x8a16, 0x8a10, 0x8a0c, 0x8a1b, 0x8a1d, 0x8a25,
+ 0x8a36, 0x8a41, 0x8a5b, 0x8a52, 0x8a46, 0x8a48, 0x8a7c, 0x8a6d,
+ 0x8a6c, 0x8a62, 0x8a85, 0x8a82, 0x8a84, 0x8aa8, 0x8aa1, 0x8a91,
+ 0x8aa5, 0x8aa6, 0x8a9a, 0x8aa3, 0x8ac4, 0x8acd, 0x8ac2, 0x8ada,
+ 0x8aeb, 0x8af3, 0x8ae7, 0x8ae4, 0x8af1, 0x8b14, 0x8ae0, 0x8ae2,
+ 0x8af7, 0x8ade, 0x8adb, 0x8b0c, 0x8b07, 0x8b1a, 0x8ae1, 0x8b16,
+ 0x8b10, 0x8b17, 0x8b20, 0x8b33, 0x97ab, 0x8b26, 0x8b2b, 0x8b3e,
+ 0x8b28, 0x8b41, 0x8b4c, 0x8b4f, 0x8b4e, 0x8b49, 0x8b56, 0x8b5b,
+ 0x8b5a, 0x8b6b, 0x8b5f, 0x8b6c, 0x8b6f, 0x8b74, 0x8b7d, 0x8b80,
+ 0x8b8c, 0x8b8e, 0x8b92, 0x8b93, 0x8b96, 0x8b99, 0x8b9a, 0x8c3a,
+ 0x8c41, 0x8c3f, 0x8c48, 0x8c4c, 0x8c4e, 0x8c50, 0x8c55, 0x8c62,
+ 0x8c6c, 0x8c78, 0x8c7a, 0x8c82, 0x8c89, 0x8c85, 0x8c8a, 0x8c8d,
+ 0x8c8e, 0x8c94, 0x8c7c, 0x8c98, 0x621d, 0x8cad, 0x8caa, 0x8cbd,
+ 0x8cb2, 0x8cb3, 0x8cae, 0x8cb6, 0x8cc8, 0x8cc1, 0x8ce4, 0x8ce3,
+ 0x8cda, 0x8cfd, 0x8cfa, 0x8cfb, 0x8d04, 0x8d05, 0x8d0a, 0x8d07,
+ 0x8d0f, 0x8d0d, 0x8d10, 0x9f4e, 0x8d13, 0x8ccd, 0x8d14, 0x8d16,
+ 0x8d67, 0x8d6d, 0x8d71, 0x8d73, 0x8d81, 0x8d99, 0x8dc2, 0x8dbe,
+ 0x8dba, 0x8dcf, 0x8dda, 0x8dd6, 0x8dcc, 0x8ddb, 0x8dcb, 0x8dea,
+ 0x8deb, 0x8ddf, 0x8de3, 0x8dfc, 0x8e08, 0x8e09, 0x8dff, 0x8e1d,
+ 0x8e1e, 0x8e10, 0x8e1f, 0x8e42, 0x8e35, 0x8e30, 0x8e34, 0x8e4a,
+ 0x8e47, 0x8e49, 0x8e4c, 0x8e50, 0x8e48, 0x8e59, 0x8e64, 0x8e60,
+ 0x8e2a, 0x8e63, 0x8e55, 0x8e76, 0x8e72, 0x8e7c, 0x8e81, 0x8e87,
+ 0x8e85, 0x8e84, 0x8e8b, 0x8e8a, 0x8e93, 0x8e91, 0x8e94, 0x8e99,
+ 0x8eaa, 0x8ea1, 0x8eac, 0x8eb0, 0x8ec6, 0x8eb1, 0x8ebe, 0x8ec5,
+ 0x8ec8, 0x8ecb, 0x8edb, 0x8ee3, 0x8efc, 0x8efb, 0x8eeb, 0x8efe,
+ 0x8f0a, 0x8f05, 0x8f15, 0x8f12, 0x8f19, 0x8f13, 0x8f1c, 0x8f1f,
+ 0x8f1b, 0x8f0c, 0x8f26, 0x8f33, 0x8f3b, 0x8f39, 0x8f45, 0x8f42,
+ 0x8f3e, 0x8f4c, 0x8f49, 0x8f46, 0x8f4e, 0x8f57, 0x8f5c, 0x8f62,
+ 0x8f63, 0x8f64, 0x8f9c, 0x8f9f, 0x8fa3, 0x8fad, 0x8faf, 0x8fb7,
+ 0x8fda, 0x8fe5, 0x8fe2, 0x8fea, 0x8fef, 0x9087, 0x8ff4, 0x9005,
+ 0x8ff9, 0x8ffa, 0x9011, 0x9015, 0x9021, 0x900d, 0x901e, 0x9016,
+ 0x900b, 0x9027, 0x9036, 0x9035, 0x9039, 0x8ff8, 0x904f, 0x9050,
+ 0x9051, 0x9052, 0x900e, 0x9049, 0x903e, 0x9056, 0x9058, 0x905e,
+ 0x9068, 0x906f, 0x9076, 0x96a8, 0x9072, 0x9082, 0x907d, 0x9081,
+ 0x9080, 0x908a, 0x9089, 0x908f, 0x90a8, 0x90af, 0x90b1, 0x90b5,
+ 0x90e2, 0x90e4, 0x6248, 0x90db, 0x9102, 0x9112, 0x9119, 0x9132,
+ 0x9130, 0x914a, 0x9156, 0x9158, 0x9163, 0x9165, 0x9169, 0x9173,
+ 0x9172, 0x918b, 0x9189, 0x9182, 0x91a2, 0x91ab, 0x91af, 0x91aa,
+ 0x91b5, 0x91b4, 0x91ba, 0x91c0, 0x91c1, 0x91c9, 0x91cb, 0x91d0,
+ 0x91d6, 0x91df, 0x91e1, 0x91db, 0x91fc, 0x91f5, 0x91f6, 0x921e,
+ 0x91ff, 0x9214, 0x922c, 0x9215, 0x9211, 0x925e, 0x9257, 0x9245,
+ 0x9249, 0x9264, 0x9248, 0x9295, 0x923f, 0x924b, 0x9250, 0x929c,
+ 0x9296, 0x9293, 0x929b, 0x925a, 0x92cf, 0x92b9, 0x92b7, 0x92e9,
+ 0x930f, 0x92fa, 0x9344, 0x932e, 0x9319, 0x9322, 0x931a, 0x9323,
+ 0x933a, 0x9335, 0x933b, 0x935c, 0x9360, 0x937c, 0x936e, 0x9356,
+ 0x93b0, 0x93ac, 0x93ad, 0x9394, 0x93b9, 0x93d6, 0x93d7, 0x93e8,
+ 0x93e5, 0x93d8, 0x93c3, 0x93dd, 0x93d0, 0x93c8, 0x93e4, 0x941a,
+ 0x9414, 0x9413, 0x9403, 0x9407, 0x9410, 0x9436, 0x942b, 0x9435,
+ 0x9421, 0x943a, 0x9441, 0x9452, 0x9444, 0x945b, 0x9460, 0x9462,
+ 0x945e, 0x946a, 0x9229, 0x9470, 0x9475, 0x9477, 0x947d, 0x945a,
+ 0x947c, 0x947e, 0x9481, 0x947f, 0x9582, 0x9587, 0x958a, 0x9594,
+ 0x9596, 0x9598, 0x9599, 0x95a0, 0x95a8, 0x95a7, 0x95ad, 0x95bc,
+ 0x95bb, 0x95b9, 0x95be, 0x95ca, 0x6ff6, 0x95c3, 0x95cd, 0x95cc,
+ 0x95d5, 0x95d4, 0x95d6, 0x95dc, 0x95e1, 0x95e5, 0x95e2, 0x9621,
+ 0x9628, 0x962e, 0x962f, 0x9642, 0x964c, 0x964f, 0x964b, 0x9677,
+ 0x965c, 0x965e, 0x965d, 0x965f, 0x9666, 0x9672, 0x966c, 0x968d,
+ 0x9698, 0x9695, 0x9697, 0x96aa, 0x96a7, 0x96b1, 0x96b2, 0x96b0,
+ 0x96b4, 0x96b6, 0x96b8, 0x96b9, 0x96ce, 0x96cb, 0x96c9, 0x96cd,
+ 0x894d, 0x96dc, 0x970d, 0x96d5, 0x96f9, 0x9704, 0x9706, 0x9708,
+ 0x9713, 0x970e, 0x9711, 0x970f, 0x9716, 0x9719, 0x9724, 0x972a,
+ 0x9730, 0x9739, 0x973d, 0x973e, 0x9744, 0x9746, 0x9748, 0x9742,
+ 0x9749, 0x975c, 0x9760, 0x9764, 0x9766, 0x9768, 0x52d2, 0x976b,
+ 0x9771, 0x9779, 0x9785, 0x977c, 0x9781, 0x977a, 0x9786, 0x978b,
+ 0x978f, 0x9790, 0x979c, 0x97a8, 0x97a6, 0x97a3, 0x97b3, 0x97b4,
+ 0x97c3, 0x97c6, 0x97c8, 0x97cb, 0x97dc, 0x97ed, 0x9f4f, 0x97f2,
+ 0x7adf, 0x97f6, 0x97f5, 0x980f, 0x980c, 0x9838, 0x9824, 0x9821,
+ 0x9837, 0x983d, 0x9846, 0x984f, 0x984b, 0x986b, 0x986f, 0x9870,
+ 0x9871, 0x9874, 0x9873, 0x98aa, 0x98af, 0x98b1, 0x98b6, 0x98c4,
+ 0x98c3, 0x98c6, 0x98e9, 0x98eb, 0x9903, 0x9909, 0x9912, 0x9914,
+ 0x9918, 0x9921, 0x991d, 0x991e, 0x9924, 0x9920, 0x992c, 0x992e,
+ 0x993d, 0x993e, 0x9942, 0x9949, 0x9945, 0x9950, 0x994b, 0x9951,
+ 0x9952, 0x994c, 0x9955, 0x9997, 0x9998, 0x99a5, 0x99ad, 0x99ae,
+ 0x99bc, 0x99df, 0x99db, 0x99dd, 0x99d8, 0x99d1, 0x99ed, 0x99ee,
+ 0x99f1, 0x99f2, 0x99fb, 0x99f8, 0x9a01, 0x9a0f, 0x9a05, 0x99e2,
+ 0x9a19, 0x9a2b, 0x9a37, 0x9a45, 0x9a42, 0x9a40, 0x9a43, 0x9a3e,
+ 0x9a55, 0x9a4d, 0x9a5b, 0x9a57, 0x9a5f, 0x9a62, 0x9a65, 0x9a64,
+ 0x9a69, 0x9a6b, 0x9a6a, 0x9aad, 0x9ab0, 0x9abc, 0x9ac0, 0x9acf,
+ 0x9ad1, 0x9ad3, 0x9ad4, 0x9ade, 0x9adf, 0x9ae2, 0x9ae3, 0x9ae6,
+ 0x9aef, 0x9aeb, 0x9aee, 0x9af4, 0x9af1, 0x9af7, 0x9afb, 0x9b06,
+ 0x9b18, 0x9b1a, 0x9b1f, 0x9b22, 0x9b23, 0x9b25, 0x9b27, 0x9b28,
+ 0x9b29, 0x9b2a, 0x9b2e, 0x9b2f, 0x9b32, 0x9b44, 0x9b43, 0x9b4f,
+ 0x9b4d, 0x9b4e, 0x9b51, 0x9b58, 0x9b74, 0x9b93, 0x9b83, 0x9b91,
+ 0x9b96, 0x9b97, 0x9b9f, 0x9ba0, 0x9ba8, 0x9bb4, 0x9bc0, 0x9bca,
+ 0x9bb9, 0x9bc6, 0x9bcf, 0x9bd1, 0x9bd2, 0x9be3, 0x9be2, 0x9be4,
+ 0x9bd4, 0x9be1, 0x9c3a, 0x9bf2, 0x9bf1, 0x9bf0, 0x9c15, 0x9c14,
+ 0x9c09, 0x9c13, 0x9c0c, 0x9c06, 0x9c08, 0x9c12, 0x9c0a, 0x9c04,
+ 0x9c2e, 0x9c1b, 0x9c25, 0x9c24, 0x9c21, 0x9c30, 0x9c47, 0x9c32,
+ 0x9c46, 0x9c3e, 0x9c5a, 0x9c60, 0x9c67, 0x9c76, 0x9c78, 0x9ce7,
+ 0x9cec, 0x9cf0, 0x9d09, 0x9d08, 0x9ceb, 0x9d03, 0x9d06, 0x9d2a,
+ 0x9d26, 0x9daf, 0x9d23, 0x9d1f, 0x9d44, 0x9d15, 0x9d12, 0x9d41,
+ 0x9d3f, 0x9d3e, 0x9d46, 0x9d48, 0x9d5d, 0x9d5e, 0x9d64, 0x9d51,
+ 0x9d50, 0x9d59, 0x9d72, 0x9d89, 0x9d87, 0x9dab, 0x9d6f, 0x9d7a,
+ 0x9d9a, 0x9da4, 0x9da9, 0x9db2, 0x9dc4, 0x9dc1, 0x9dbb, 0x9db8,
+ 0x9dba, 0x9dc6, 0x9dcf, 0x9dc2, 0x9dd9, 0x9dd3, 0x9df8, 0x9de6,
+ 0x9ded, 0x9def, 0x9dfd, 0x9e1a, 0x9e1b, 0x9e1e, 0x9e75, 0x9e79,
+ 0x9e7d, 0x9e81, 0x9e88, 0x9e8b, 0x9e8c, 0x9e92, 0x9e95, 0x9e91,
+ 0x9e9d, 0x9ea5, 0x9ea9, 0x9eb8, 0x9eaa, 0x9ead, 0x9761, 0x9ecc,
+ 0x9ece, 0x9ecf, 0x9ed0, 0x9ed4, 0x9edc, 0x9ede, 0x9edd, 0x9ee0,
+ 0x9ee5, 0x9ee8, 0x9eef, 0x9ef4, 0x9ef6, 0x9ef7, 0x9ef9, 0x9efb,
+ 0x9efc, 0x9efd, 0x9f07, 0x9f08, 0x76b7, 0x9f15, 0x9f21, 0x9f2c,
+ 0x9f3e, 0x9f4a, 0x9f52, 0x9f54, 0x9f63, 0x9f5f, 0x9f60, 0x9f61,
+ 0x9f66, 0x9f67, 0x9f6c, 0x9f6a, 0x9f77, 0x9f72, 0x9f76, 0x9f95,
+ 0x9f9c, 0x9fa0, 0x582f, 0x69c7, 0x9059, 0x7464, 0x51dc, 0x7199,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9fa5, 0x1c2a, 0xbfffe018, 0x4204f04f,
+ 0x804ef70, 0x0000, 0x2288, 0x804f240, 0x42130a14, 0x40015360, 0xbfffe038, 0x804bcc9
+};
+
+const unichar_t unicode_from_jis212[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x02d8, 0x02c7, 0x00b8, 0x02d9,
+ 0x02dd, 0x00af, 0x02db, 0x02da, 0x007e, 0x0384, 0x0385, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00a1,
+ 0x00a6, 0x00bf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00ba, 0x00aa, 0x00a9, 0x00ae, 0x2122, 0x00a4, 0x2116, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0386, 0x0388,
+ 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c, 0x0000, 0x038e, 0x03ab,
+ 0x0000, 0x038f, 0x0000, 0x0000, 0x0000, 0x0000, 0x03ac, 0x03ad,
+ 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc, 0x03c2, 0x03cd, 0x03cb,
+ 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0402, 0x0403, 0x0404,
+ 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c,
+ 0x040e, 0x040f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0452, 0x0453, 0x0454,
+ 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045a, 0x045b, 0x045c,
+ 0x045e, 0x045f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00c6, 0x0110, 0x0000, 0x0126, 0x0000, 0x0132, 0x0000, 0x0141,
+ 0x013f, 0x0000, 0x014a, 0x00d8, 0x0152, 0x0000, 0x0166, 0x00de,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e6, 0x0111, 0x00f0, 0x0127, 0x0131, 0x0133, 0x0138, 0x0142,
+ 0x0140, 0x0149, 0x014b, 0x00f8, 0x0153, 0x00df, 0x0167, 0x00fe,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00c1, 0x00c0,
+ 0x00c4, 0x00c2, 0x0102, 0x01cd, 0x0100, 0x0104, 0x00c5, 0x00c3,
+ 0x0106, 0x0108, 0x010c, 0x00c7, 0x010a, 0x010e, 0x00c9, 0x00c8,
+ 0x00cb, 0x00ca, 0x011a, 0x0116, 0x0112, 0x0118, 0x0000, 0x011c,
+ 0x011e, 0x0122, 0x0120, 0x0124, 0x00cd, 0x00cc, 0x00cf, 0x00ce,
+ 0x01cf, 0x0130, 0x012a, 0x012e, 0x0128, 0x0134, 0x0136, 0x0139,
+ 0x013d, 0x013b, 0x0143, 0x0147, 0x0145, 0x00d1, 0x00d3, 0x00d2,
+ 0x00d6, 0x00d4, 0x01d1, 0x0150, 0x014c, 0x00d5, 0x0154, 0x0158,
+ 0x0156, 0x015a, 0x015c, 0x0160, 0x015e, 0x0164, 0x0162, 0x00da,
+ 0x00d9, 0x00dc, 0x00db, 0x016c, 0x01d3, 0x0170, 0x016a, 0x0172,
+ 0x016e, 0x0168, 0x01d7, 0x01db, 0x01d9, 0x01d5, 0x0174, 0x00dd,
+ 0x0178, 0x0176, 0x0179, 0x017d, 0x017b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x00e1, 0x00e0, 0x00e4, 0x00e2,
+ 0x0103, 0x01ce, 0x0101, 0x0105, 0x00e5, 0x00e3, 0x0107, 0x0109,
+ 0x010d, 0x00e7, 0x010b, 0x010f, 0x00e9, 0x00e8, 0x00eb, 0x00ea,
+ 0x011b, 0x0117, 0x0113, 0x0119, 0x01f5, 0x011d, 0x011f, 0x0000,
+ 0x0121, 0x0125, 0x00ed, 0x00ec, 0x00ef, 0x00ee, 0x01d0, 0x0000,
+ 0x012b, 0x012f, 0x0129, 0x0135, 0x0137, 0x013a, 0x013e, 0x013c,
+ 0x0144, 0x0148, 0x0146, 0x00f1, 0x00f3, 0x00f2, 0x00f6, 0x00f4,
+ 0x01d2, 0x0151, 0x014d, 0x00f5, 0x0155, 0x0159, 0x0157, 0x015b,
+ 0x015d, 0x0161, 0x015f, 0x0165, 0x0163, 0x00fa, 0x00f9, 0x00fc,
+ 0x00fb, 0x016d, 0x01d4, 0x0171, 0x016b, 0x0173, 0x016f, 0x0169,
+ 0x01d8, 0x01dc, 0x01da, 0x01d6, 0x0175, 0x00fd, 0x00ff, 0x0177,
+ 0x017a, 0x017e, 0x017c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4e02, 0x4e04, 0x4e05, 0x4e0c, 0x4e12, 0x4e1f,
+ 0x4e23, 0x4e24, 0x4e28, 0x4e2b, 0x4e2e, 0x4e2f, 0x4e30, 0x4e35,
+ 0x4e40, 0x4e41, 0x4e44, 0x4e47, 0x4e51, 0x4e5a, 0x4e5c, 0x4e63,
+ 0x4e68, 0x4e69, 0x4e74, 0x4e75, 0x4e79, 0x4e7f, 0x4e8d, 0x4e96,
+ 0x4e97, 0x4e9d, 0x4eaf, 0x4eb9, 0x4ec3, 0x4ed0, 0x4eda, 0x4edb,
+ 0x4ee0, 0x4ee1, 0x4ee2, 0x4ee8, 0x4eef, 0x4ef1, 0x4ef3, 0x4ef5,
+ 0x4efd, 0x4efe, 0x4eff, 0x4f00, 0x4f02, 0x4f03, 0x4f08, 0x4f0b,
+ 0x4f0c, 0x4f12, 0x4f15, 0x4f16, 0x4f17, 0x4f19, 0x4f2e, 0x4f31,
+ 0x4f60, 0x4f33, 0x4f35, 0x4f37, 0x4f39, 0x4f3b, 0x4f3e, 0x4f40,
+ 0x4f42, 0x4f48, 0x4f49, 0x4f4b, 0x4f4c, 0x4f52, 0x4f54, 0x4f56,
+ 0x4f58, 0x4f5f, 0x4f63, 0x4f6a, 0x4f6c, 0x4f6e, 0x4f71, 0x4f77,
+ 0x4f78, 0x4f79, 0x4f7a, 0x4f7d, 0x4f7e, 0x4f81, 0x4f82, 0x4f84,
+ 0x4f85, 0x4f89, 0x4f8a, 0x4f8c, 0x4f8e, 0x4f90, 0x4f92, 0x4f93,
+ 0x4f94, 0x4f97, 0x4f99, 0x4f9a, 0x4f9e, 0x4f9f, 0x4fb2, 0x4fb7,
+ 0x4fb9, 0x4fbb, 0x4fbc, 0x4fbd, 0x4fbe, 0x4fc0, 0x4fc1, 0x4fc5,
+ 0x4fc6, 0x4fc8, 0x4fc9, 0x4fcb, 0x4fcc, 0x4fcd, 0x4fcf, 0x4fd2,
+ 0x4fdc, 0x4fe0, 0x4fe2, 0x4ff0, 0x4ff2, 0x4ffc, 0x4ffd, 0x4fff,
+ 0x5000, 0x5001, 0x5004, 0x5007, 0x500a, 0x500c, 0x500e, 0x5010,
+ 0x5013, 0x5017, 0x5018, 0x501b, 0x501c, 0x501d, 0x501e, 0x5022,
+ 0x5027, 0x502e, 0x5030, 0x5032, 0x5033, 0x5035, 0x5040, 0x5041,
+ 0x5042, 0x5045, 0x5046, 0x504a, 0x504c, 0x504e, 0x5051, 0x5052,
+ 0x5053, 0x5057, 0x5059, 0x505f, 0x5060, 0x5062, 0x5063, 0x5066,
+ 0x5067, 0x506a, 0x506d, 0x5070, 0x5071, 0x503b, 0x5081, 0x5083,
+ 0x5084, 0x5086, 0x508a, 0x508e, 0x508f, 0x5090, 0x5092, 0x5093,
+ 0x5094, 0x5096, 0x509b, 0x509c, 0x509e, 0x509f, 0x50a0, 0x50a1,
+ 0x50a2, 0x50aa, 0x50af, 0x50b0, 0x50b9, 0x50ba, 0x50bd, 0x50c0,
+ 0x50c3, 0x50c4, 0x50c7, 0x50cc, 0x50ce, 0x50d0, 0x50d3, 0x50d4,
+ 0x50d8, 0x50dc, 0x50dd, 0x50df, 0x50e2, 0x50e4, 0x50e6, 0x50e8,
+ 0x50e9, 0x50ef, 0x50f1, 0x50f6, 0x50fa, 0x50fe, 0x5103, 0x5106,
+ 0x5107, 0x5108, 0x510b, 0x510c, 0x510d, 0x510e, 0x50f2, 0x5110,
+ 0x5117, 0x5119, 0x511b, 0x511c, 0x511d, 0x511e, 0x5123, 0x5127,
+ 0x5128, 0x512c, 0x512d, 0x512f, 0x5131, 0x5133, 0x5134, 0x5135,
+ 0x5138, 0x5139, 0x5142, 0x514a, 0x514f, 0x5153, 0x5155, 0x5157,
+ 0x5158, 0x515f, 0x5164, 0x5166, 0x517e, 0x5183, 0x5184, 0x518b,
+ 0x518e, 0x5198, 0x519d, 0x51a1, 0x51a3, 0x51ad, 0x51b8, 0x51ba,
+ 0x51bc, 0x51be, 0x51bf, 0x51c2, 0x51c8, 0x51cf, 0x51d1, 0x51d2,
+ 0x51d3, 0x51d5, 0x51d8, 0x51de, 0x51e2, 0x51e5, 0x51ee, 0x51f2,
+ 0x51f3, 0x51f4, 0x51f7, 0x5201, 0x5202, 0x5205, 0x5212, 0x5213,
+ 0x5215, 0x5216, 0x5218, 0x5222, 0x5228, 0x5231, 0x5232, 0x5235,
+ 0x523c, 0x5245, 0x5249, 0x5255, 0x5257, 0x5258, 0x525a, 0x525c,
+ 0x525f, 0x5260, 0x5261, 0x5266, 0x526e, 0x5277, 0x5278, 0x5279,
+ 0x5280, 0x5282, 0x5285, 0x528a, 0x528c, 0x5293, 0x5295, 0x5296,
+ 0x5297, 0x5298, 0x529a, 0x529c, 0x52a4, 0x52a5, 0x52a6, 0x52a7,
+ 0x52af, 0x52b0, 0x52b6, 0x52b7, 0x52b8, 0x52ba, 0x52bb, 0x52bd,
+ 0x52c0, 0x52c4, 0x52c6, 0x52c8, 0x52cc, 0x52cf, 0x52d1, 0x52d4,
+ 0x52d6, 0x52db, 0x52dc, 0x52e1, 0x52e5, 0x52e8, 0x52e9, 0x52ea,
+ 0x52ec, 0x52f0, 0x52f1, 0x52f4, 0x52f6, 0x52f7, 0x5300, 0x5303,
+ 0x530a, 0x530b, 0x530c, 0x5311, 0x5313, 0x5318, 0x531b, 0x531c,
+ 0x531e, 0x531f, 0x5325, 0x5327, 0x5328, 0x5329, 0x532b, 0x532c,
+ 0x532d, 0x5330, 0x5332, 0x5335, 0x533c, 0x533d, 0x533e, 0x5342,
+ 0x534c, 0x534b, 0x5359, 0x535b, 0x5361, 0x5363, 0x5365, 0x536c,
+ 0x536d, 0x5372, 0x5379, 0x537e, 0x5383, 0x5387, 0x5388, 0x538e,
+ 0x5393, 0x5394, 0x5399, 0x539d, 0x53a1, 0x53a4, 0x53aa, 0x53ab,
+ 0x53af, 0x53b2, 0x53b4, 0x53b5, 0x53b7, 0x53b8, 0x53ba, 0x53bd,
+ 0x53c0, 0x53c5, 0x53cf, 0x53d2, 0x53d3, 0x53d5, 0x53da, 0x53dd,
+ 0x53de, 0x53e0, 0x53e6, 0x53e7, 0x53f5, 0x5402, 0x5413, 0x541a,
+ 0x5421, 0x5427, 0x5428, 0x542a, 0x542f, 0x5431, 0x5434, 0x5435,
+ 0x5443, 0x5444, 0x5447, 0x544d, 0x544f, 0x545e, 0x5462, 0x5464,
+ 0x5466, 0x5467, 0x5469, 0x546b, 0x546d, 0x546e, 0x5474, 0x547f,
+ 0x5481, 0x5483, 0x5485, 0x5488, 0x5489, 0x548d, 0x5491, 0x5495,
+ 0x5496, 0x549c, 0x549f, 0x54a1, 0x54a6, 0x54a7, 0x54a9, 0x54aa,
+ 0x54ad, 0x54ae, 0x54b1, 0x54b7, 0x54b9, 0x54ba, 0x54bb, 0x54bf,
+ 0x54c6, 0x54ca, 0x54cd, 0x54ce, 0x54e0, 0x54ea, 0x54ec, 0x54ef,
+ 0x54f6, 0x54fc, 0x54fe, 0x54ff, 0x5500, 0x5501, 0x5505, 0x5508,
+ 0x5509, 0x550c, 0x550d, 0x550e, 0x5515, 0x552a, 0x552b, 0x5532,
+ 0x5535, 0x5536, 0x553b, 0x553c, 0x553d, 0x5541, 0x5547, 0x5549,
+ 0x554a, 0x554d, 0x5550, 0x5551, 0x5558, 0x555a, 0x555b, 0x555e,
+ 0x5560, 0x5561, 0x5564, 0x5566, 0x557f, 0x5581, 0x5582, 0x5586,
+ 0x5588, 0x558e, 0x558f, 0x5591, 0x5592, 0x5593, 0x5594, 0x5597,
+ 0x55a3, 0x55a4, 0x55ad, 0x55b2, 0x55bf, 0x55c1, 0x55c3, 0x55c6,
+ 0x55c9, 0x55cb, 0x55cc, 0x55ce, 0x55d1, 0x55d2, 0x55d3, 0x55d7,
+ 0x55d8, 0x55db, 0x55de, 0x55e2, 0x55e9, 0x55f6, 0x55ff, 0x5605,
+ 0x5608, 0x560a, 0x560d, 0x560e, 0x560f, 0x5610, 0x5611, 0x5612,
+ 0x5619, 0x562c, 0x5630, 0x5633, 0x5635, 0x5637, 0x5639, 0x563b,
+ 0x563c, 0x563d, 0x563f, 0x5640, 0x5641, 0x5643, 0x5644, 0x5646,
+ 0x5649, 0x564b, 0x564d, 0x564f, 0x5654, 0x565e, 0x5660, 0x5661,
+ 0x5662, 0x5663, 0x5666, 0x5669, 0x566d, 0x566f, 0x5671, 0x5672,
+ 0x5675, 0x5684, 0x5685, 0x5688, 0x568b, 0x568c, 0x5695, 0x5699,
+ 0x569a, 0x569d, 0x569e, 0x569f, 0x56a6, 0x56a7, 0x56a8, 0x56a9,
+ 0x56ab, 0x56ac, 0x56ad, 0x56b1, 0x56b3, 0x56b7, 0x56be, 0x56c5,
+ 0x56c9, 0x56ca, 0x56cb, 0x56cf, 0x56d0, 0x56cc, 0x56cd, 0x56d9,
+ 0x56dc, 0x56dd, 0x56df, 0x56e1, 0x56e4, 0x56e5, 0x56e6, 0x56e7,
+ 0x56e8, 0x56f1, 0x56eb, 0x56ed, 0x56f6, 0x56f7, 0x5701, 0x5702,
+ 0x5707, 0x570a, 0x570c, 0x5711, 0x5715, 0x571a, 0x571b, 0x571d,
+ 0x5720, 0x5722, 0x5723, 0x5724, 0x5725, 0x5729, 0x572a, 0x572c,
+ 0x572e, 0x572f, 0x5733, 0x5734, 0x573d, 0x573e, 0x573f, 0x5745,
+ 0x5746, 0x574c, 0x574d, 0x5752, 0x5762, 0x5765, 0x5767, 0x5768,
+ 0x576b, 0x576d, 0x576e, 0x576f, 0x5770, 0x5771, 0x5773, 0x5774,
+ 0x5775, 0x5777, 0x5779, 0x577a, 0x577b, 0x577c, 0x577e, 0x5781,
+ 0x5783, 0x578c, 0x5794, 0x5797, 0x5799, 0x579a, 0x579c, 0x579d,
+ 0x579e, 0x579f, 0x57a1, 0x5795, 0x57a7, 0x57a8, 0x57a9, 0x57ac,
+ 0x57b8, 0x57bd, 0x57c7, 0x57c8, 0x57cc, 0x57cf, 0x57d5, 0x57dd,
+ 0x57de, 0x57e4, 0x57e6, 0x57e7, 0x57e9, 0x57ed, 0x57f0, 0x57f5,
+ 0x57f6, 0x57f8, 0x57fd, 0x57fe, 0x57ff, 0x5803, 0x5804, 0x5808,
+ 0x5809, 0x57e1, 0x580c, 0x580d, 0x581b, 0x581e, 0x581f, 0x5820,
+ 0x5826, 0x5827, 0x582d, 0x5832, 0x5839, 0x583f, 0x5849, 0x584c,
+ 0x584d, 0x584f, 0x5850, 0x5855, 0x585f, 0x5861, 0x5864, 0x5867,
+ 0x5868, 0x5878, 0x587c, 0x587f, 0x5880, 0x5881, 0x5887, 0x5888,
+ 0x5889, 0x588a, 0x588c, 0x588d, 0x588f, 0x5890, 0x5894, 0x5896,
+ 0x589d, 0x58a0, 0x58a1, 0x58a2, 0x58a6, 0x58a9, 0x58b1, 0x58b2,
+ 0x58c4, 0x58bc, 0x58c2, 0x58c8, 0x58cd, 0x58ce, 0x58d0, 0x58d2,
+ 0x58d4, 0x58d6, 0x58da, 0x58dd, 0x58e1, 0x58e2, 0x58e9, 0x58f3,
+ 0x5905, 0x5906, 0x590b, 0x590c, 0x5912, 0x5913, 0x5914, 0x8641,
+ 0x591d, 0x5921, 0x5923, 0x5924, 0x5928, 0x592f, 0x5930, 0x5933,
+ 0x5935, 0x5936, 0x593f, 0x5943, 0x5946, 0x5952, 0x5953, 0x5959,
+ 0x595b, 0x595d, 0x595e, 0x595f, 0x5961, 0x5963, 0x596b, 0x596d,
+ 0x596f, 0x5972, 0x5975, 0x5976, 0x5979, 0x597b, 0x597c, 0x598b,
+ 0x598c, 0x598e, 0x5992, 0x5995, 0x5997, 0x599f, 0x59a4, 0x59a7,
+ 0x59ad, 0x59ae, 0x59af, 0x59b0, 0x59b3, 0x59b7, 0x59ba, 0x59bc,
+ 0x59c1, 0x59c3, 0x59c4, 0x59c8, 0x59ca, 0x59cd, 0x59d2, 0x59dd,
+ 0x59de, 0x59df, 0x59e3, 0x59e4, 0x59e7, 0x59ee, 0x59ef, 0x59f1,
+ 0x59f2, 0x59f4, 0x59f7, 0x5a00, 0x5a04, 0x5a0c, 0x5a0d, 0x5a0e,
+ 0x5a12, 0x5a13, 0x5a1e, 0x5a23, 0x5a24, 0x5a27, 0x5a28, 0x5a2a,
+ 0x5a2d, 0x5a30, 0x5a44, 0x5a45, 0x5a47, 0x5a48, 0x5a4c, 0x5a50,
+ 0x5a55, 0x5a5e, 0x5a63, 0x5a65, 0x5a67, 0x5a6d, 0x5a77, 0x5a7a,
+ 0x5a7b, 0x5a7e, 0x5a8b, 0x5a90, 0x5a93, 0x5a96, 0x5a99, 0x5a9c,
+ 0x5a9e, 0x5a9f, 0x5aa0, 0x5aa2, 0x5aa7, 0x5aac, 0x5ab1, 0x5ab2,
+ 0x5ab3, 0x5ab5, 0x5ab8, 0x5aba, 0x5abb, 0x5abf, 0x5ac4, 0x5ac6,
+ 0x5ac8, 0x5acf, 0x5ada, 0x5adc, 0x5ae0, 0x5ae5, 0x5aea, 0x5aee,
+ 0x5af5, 0x5af6, 0x5afd, 0x5b00, 0x5b01, 0x5b08, 0x5b17, 0x5b34,
+ 0x5b19, 0x5b1b, 0x5b1d, 0x5b21, 0x5b25, 0x5b2d, 0x5b38, 0x5b41,
+ 0x5b4b, 0x5b4c, 0x5b52, 0x5b56, 0x5b5e, 0x5b68, 0x5b6e, 0x5b6f,
+ 0x5b7c, 0x5b7d, 0x5b7e, 0x5b7f, 0x5b81, 0x5b84, 0x5b86, 0x5b8a,
+ 0x5b8e, 0x5b90, 0x5b91, 0x5b93, 0x5b94, 0x5b96, 0x5ba8, 0x5ba9,
+ 0x5bac, 0x5bad, 0x5baf, 0x5bb1, 0x5bb2, 0x5bb7, 0x5bba, 0x5bbc,
+ 0x5bc0, 0x5bc1, 0x5bcd, 0x5bcf, 0x5bd6, 0x5bd7, 0x5bd8, 0x5bd9,
+ 0x5bda, 0x5be0, 0x5bef, 0x5bf1, 0x5bf4, 0x5bfd, 0x5c0c, 0x5c17,
+ 0x5c1e, 0x5c1f, 0x5c23, 0x5c26, 0x5c29, 0x5c2b, 0x5c2c, 0x5c2e,
+ 0x5c30, 0x5c32, 0x5c35, 0x5c36, 0x5c59, 0x5c5a, 0x5c5c, 0x5c62,
+ 0x5c63, 0x5c67, 0x5c68, 0x5c69, 0x5c6d, 0x5c70, 0x5c74, 0x5c75,
+ 0x5c7a, 0x5c7b, 0x5c7c, 0x5c7d, 0x5c87, 0x5c88, 0x5c8a, 0x5c8f,
+ 0x5c92, 0x5c9d, 0x5c9f, 0x5ca0, 0x5ca2, 0x5ca3, 0x5ca6, 0x5caa,
+ 0x5cb2, 0x5cb4, 0x5cb5, 0x5cba, 0x5cc9, 0x5ccb, 0x5cd2, 0x5cdd,
+ 0x5cd7, 0x5cee, 0x5cf1, 0x5cf2, 0x5cf4, 0x5d01, 0x5d06, 0x5d0d,
+ 0x5d12, 0x5d2b, 0x5d23, 0x5d24, 0x5d26, 0x5d27, 0x5d31, 0x5d34,
+ 0x5d39, 0x5d3d, 0x5d3f, 0x5d42, 0x5d43, 0x5d46, 0x5d48, 0x5d55,
+ 0x5d51, 0x5d59, 0x5d4a, 0x5d5f, 0x5d60, 0x5d61, 0x5d62, 0x5d64,
+ 0x5d6a, 0x5d6d, 0x5d70, 0x5d79, 0x5d7a, 0x5d7e, 0x5d7f, 0x5d81,
+ 0x5d83, 0x5d88, 0x5d8a, 0x5d92, 0x5d93, 0x5d94, 0x5d95, 0x5d99,
+ 0x5d9b, 0x5d9f, 0x5da0, 0x5da7, 0x5dab, 0x5db0, 0x5db4, 0x5db8,
+ 0x5db9, 0x5dc3, 0x5dc7, 0x5dcb, 0x5dd0, 0x5dce, 0x5dd8, 0x5dd9,
+ 0x5de0, 0x5de4, 0x5de9, 0x5df8, 0x5df9, 0x5e00, 0x5e07, 0x5e0d,
+ 0x5e12, 0x5e14, 0x5e15, 0x5e18, 0x5e1f, 0x5e20, 0x5e2e, 0x5e28,
+ 0x5e32, 0x5e35, 0x5e3e, 0x5e4b, 0x5e50, 0x5e49, 0x5e51, 0x5e56,
+ 0x5e58, 0x5e5b, 0x5e5c, 0x5e5e, 0x5e68, 0x5e6a, 0x5e6b, 0x5e6c,
+ 0x5e6d, 0x5e6e, 0x5e70, 0x5e80, 0x5e8b, 0x5e8e, 0x5ea2, 0x5ea4,
+ 0x5ea5, 0x5ea8, 0x5eaa, 0x5eac, 0x5eb1, 0x5eb3, 0x5ebd, 0x5ebe,
+ 0x5ebf, 0x5ec6, 0x5ecc, 0x5ecb, 0x5ece, 0x5ed1, 0x5ed2, 0x5ed4,
+ 0x5ed5, 0x5edc, 0x5ede, 0x5ee5, 0x5eeb, 0x5f02, 0x5f06, 0x5f07,
+ 0x5f08, 0x5f0e, 0x5f19, 0x5f1c, 0x5f1d, 0x5f21, 0x5f22, 0x5f23,
+ 0x5f24, 0x5f28, 0x5f2b, 0x5f2c, 0x5f2e, 0x5f30, 0x5f34, 0x5f36,
+ 0x5f3b, 0x5f3d, 0x5f3f, 0x5f40, 0x5f44, 0x5f45, 0x5f47, 0x5f4d,
+ 0x5f50, 0x5f54, 0x5f58, 0x5f5b, 0x5f60, 0x5f63, 0x5f64, 0x5f67,
+ 0x5f6f, 0x5f72, 0x5f74, 0x5f75, 0x5f78, 0x5f7a, 0x5f7d, 0x5f7e,
+ 0x5f89, 0x5f8d, 0x5f8f, 0x5f96, 0x5f9c, 0x5f9d, 0x5fa2, 0x5fa7,
+ 0x5fab, 0x5fa4, 0x5fac, 0x5faf, 0x5fb0, 0x5fb1, 0x5fb8, 0x5fc4,
+ 0x5fc7, 0x5fc8, 0x5fc9, 0x5fcb, 0x5fd0, 0x5fd1, 0x5fd2, 0x5fd3,
+ 0x5fd4, 0x5fde, 0x5fe1, 0x5fe2, 0x5fe8, 0x5fe9, 0x5fea, 0x5fec,
+ 0x5fed, 0x5fee, 0x5fef, 0x5ff2, 0x5ff3, 0x5ff6, 0x5ffa, 0x5ffc,
+ 0x6007, 0x600a, 0x600d, 0x6013, 0x6014, 0x6017, 0x6018, 0x601a,
+ 0x601f, 0x6024, 0x602d, 0x6033, 0x6035, 0x6040, 0x6047, 0x6048,
+ 0x6049, 0x604c, 0x6051, 0x6054, 0x6056, 0x6057, 0x605d, 0x6061,
+ 0x6067, 0x6071, 0x607e, 0x607f, 0x6082, 0x6086, 0x6088, 0x608a,
+ 0x608e, 0x6091, 0x6093, 0x6095, 0x6098, 0x609d, 0x609e, 0x60a2,
+ 0x60a4, 0x60a5, 0x60a8, 0x60b0, 0x60b1, 0x60b7, 0x60bb, 0x60be,
+ 0x60c2, 0x60c4, 0x60c8, 0x60c9, 0x60ca, 0x60cb, 0x60ce, 0x60cf,
+ 0x60d4, 0x60d5, 0x60d9, 0x60db, 0x60dd, 0x60de, 0x60e2, 0x60e5,
+ 0x60f2, 0x60f5, 0x60f8, 0x60fc, 0x60fd, 0x6102, 0x6107, 0x610a,
+ 0x610c, 0x6110, 0x6111, 0x6112, 0x6113, 0x6114, 0x6116, 0x6117,
+ 0x6119, 0x611c, 0x611e, 0x6122, 0x612a, 0x612b, 0x6130, 0x6131,
+ 0x6135, 0x6136, 0x6137, 0x6139, 0x6141, 0x6145, 0x6146, 0x6149,
+ 0x615e, 0x6160, 0x616c, 0x6172, 0x6178, 0x617b, 0x617c, 0x617f,
+ 0x6180, 0x6181, 0x6183, 0x6184, 0x618b, 0x618d, 0x6192, 0x6193,
+ 0x6197, 0x6198, 0x619c, 0x619d, 0x619f, 0x61a0, 0x61a5, 0x61a8,
+ 0x61aa, 0x61ad, 0x61b8, 0x61b9, 0x61bc, 0x61c0, 0x61c1, 0x61c2,
+ 0x61ce, 0x61cf, 0x61d5, 0x61dc, 0x61dd, 0x61de, 0x61df, 0x61e1,
+ 0x61e2, 0x61e7, 0x61e9, 0x61e5, 0x61ec, 0x61ed, 0x61ef, 0x6201,
+ 0x6203, 0x6204, 0x6207, 0x6213, 0x6215, 0x621c, 0x6220, 0x6222,
+ 0x6223, 0x6227, 0x6229, 0x622b, 0x6239, 0x623d, 0x6242, 0x6243,
+ 0x6244, 0x6246, 0x624c, 0x6250, 0x6251, 0x6252, 0x6254, 0x6256,
+ 0x625a, 0x625c, 0x6264, 0x626d, 0x626f, 0x6273, 0x627a, 0x627d,
+ 0x628d, 0x628e, 0x628f, 0x6290, 0x62a6, 0x62a8, 0x62b3, 0x62b6,
+ 0x62b7, 0x62ba, 0x62be, 0x62bf, 0x62c4, 0x62ce, 0x62d5, 0x62d6,
+ 0x62da, 0x62ea, 0x62f2, 0x62f4, 0x62fc, 0x62fd, 0x6303, 0x6304,
+ 0x630a, 0x630b, 0x630d, 0x6310, 0x6313, 0x6316, 0x6318, 0x6329,
+ 0x632a, 0x632d, 0x6335, 0x6336, 0x6339, 0x633c, 0x6341, 0x6342,
+ 0x6343, 0x6344, 0x6346, 0x634a, 0x634b, 0x634e, 0x6352, 0x6353,
+ 0x6354, 0x6358, 0x635b, 0x6365, 0x6366, 0x636c, 0x636d, 0x6371,
+ 0x6374, 0x6375, 0x6378, 0x637c, 0x637d, 0x637f, 0x6382, 0x6384,
+ 0x6387, 0x638a, 0x6390, 0x6394, 0x6395, 0x6399, 0x639a, 0x639e,
+ 0x63a4, 0x63a6, 0x63ad, 0x63ae, 0x63af, 0x63bd, 0x63c1, 0x63c5,
+ 0x63c8, 0x63ce, 0x63d1, 0x63d3, 0x63d4, 0x63d5, 0x63dc, 0x63e0,
+ 0x63e5, 0x63ea, 0x63ec, 0x63f2, 0x63f3, 0x63f5, 0x63f8, 0x63f9,
+ 0x6409, 0x640a, 0x6410, 0x6412, 0x6414, 0x6418, 0x641e, 0x6420,
+ 0x6422, 0x6424, 0x6425, 0x6429, 0x642a, 0x642f, 0x6430, 0x6435,
+ 0x643d, 0x643f, 0x644b, 0x644f, 0x6451, 0x6452, 0x6453, 0x6454,
+ 0x645a, 0x645b, 0x645c, 0x645d, 0x645f, 0x6460, 0x6461, 0x6463,
+ 0x646d, 0x6473, 0x6474, 0x647b, 0x647d, 0x6485, 0x6487, 0x648f,
+ 0x6490, 0x6491, 0x6498, 0x6499, 0x649b, 0x649d, 0x649f, 0x64a1,
+ 0x64a3, 0x64a6, 0x64a8, 0x64ac, 0x64b3, 0x64bd, 0x64be, 0x64bf,
+ 0x64c4, 0x64c9, 0x64ca, 0x64cb, 0x64cc, 0x64ce, 0x64d0, 0x64d1,
+ 0x64d5, 0x64d7, 0x64e4, 0x64e5, 0x64e9, 0x64ea, 0x64ed, 0x64f0,
+ 0x64f5, 0x64f7, 0x64fb, 0x64ff, 0x6501, 0x6504, 0x6508, 0x6509,
+ 0x650a, 0x650f, 0x6513, 0x6514, 0x6516, 0x6519, 0x651b, 0x651e,
+ 0x651f, 0x6522, 0x6526, 0x6529, 0x652e, 0x6531, 0x653a, 0x653c,
+ 0x653d, 0x6543, 0x6547, 0x6549, 0x6550, 0x6552, 0x6554, 0x655f,
+ 0x6560, 0x6567, 0x656b, 0x657a, 0x657d, 0x6581, 0x6585, 0x658a,
+ 0x6592, 0x6595, 0x6598, 0x659d, 0x65a0, 0x65a3, 0x65a6, 0x65ae,
+ 0x65b2, 0x65b3, 0x65b4, 0x65bf, 0x65c2, 0x65c8, 0x65c9, 0x65ce,
+ 0x65d0, 0x65d4, 0x65d6, 0x65d8, 0x65df, 0x65f0, 0x65f2, 0x65f4,
+ 0x65f5, 0x65f9, 0x65fe, 0x65ff, 0x6600, 0x6604, 0x6608, 0x6609,
+ 0x660d, 0x6611, 0x6612, 0x6615, 0x6616, 0x661d, 0x661e, 0x6621,
+ 0x6622, 0x6623, 0x6624, 0x6626, 0x6629, 0x662a, 0x662b, 0x662c,
+ 0x662e, 0x6630, 0x6631, 0x6633, 0x6639, 0x6637, 0x6640, 0x6645,
+ 0x6646, 0x664a, 0x664c, 0x6651, 0x664e, 0x6657, 0x6658, 0x6659,
+ 0x665b, 0x665c, 0x6660, 0x6661, 0x66fb, 0x666a, 0x666b, 0x666c,
+ 0x667e, 0x6673, 0x6675, 0x667f, 0x6677, 0x6678, 0x6679, 0x667b,
+ 0x6680, 0x667c, 0x668b, 0x668c, 0x668d, 0x6690, 0x6692, 0x6699,
+ 0x669a, 0x669b, 0x669c, 0x669f, 0x66a0, 0x66a4, 0x66ad, 0x66b1,
+ 0x66b2, 0x66b5, 0x66bb, 0x66bf, 0x66c0, 0x66c2, 0x66c3, 0x66c8,
+ 0x66cc, 0x66ce, 0x66cf, 0x66d4, 0x66db, 0x66df, 0x66e8, 0x66eb,
+ 0x66ec, 0x66ee, 0x66fa, 0x6705, 0x6707, 0x670e, 0x6713, 0x6719,
+ 0x671c, 0x6720, 0x6722, 0x6733, 0x673e, 0x6745, 0x6747, 0x6748,
+ 0x674c, 0x6754, 0x6755, 0x675d, 0x6766, 0x676c, 0x676e, 0x6774,
+ 0x6776, 0x677b, 0x6781, 0x6784, 0x678e, 0x678f, 0x6791, 0x6793,
+ 0x6796, 0x6798, 0x6799, 0x679b, 0x67b0, 0x67b1, 0x67b2, 0x67b5,
+ 0x67bb, 0x67bc, 0x67bd, 0x67f9, 0x67c0, 0x67c2, 0x67c3, 0x67c5,
+ 0x67c8, 0x67c9, 0x67d2, 0x67d7, 0x67d9, 0x67dc, 0x67e1, 0x67e6,
+ 0x67f0, 0x67f2, 0x67f6, 0x67f7, 0x6852, 0x6814, 0x6819, 0x681d,
+ 0x681f, 0x6828, 0x6827, 0x682c, 0x682d, 0x682f, 0x6830, 0x6831,
+ 0x6833, 0x683b, 0x683f, 0x6844, 0x6845, 0x684a, 0x684c, 0x6855,
+ 0x6857, 0x6858, 0x685b, 0x686b, 0x686e, 0x686f, 0x6870, 0x6871,
+ 0x6872, 0x6875, 0x6879, 0x687a, 0x687b, 0x687c, 0x6882, 0x6884,
+ 0x6886, 0x6888, 0x6896, 0x6898, 0x689a, 0x689c, 0x68a1, 0x68a3,
+ 0x68a5, 0x68a9, 0x68aa, 0x68ae, 0x68b2, 0x68bb, 0x68c5, 0x68c8,
+ 0x68cc, 0x68cf, 0x68d0, 0x68d1, 0x68d3, 0x68d6, 0x68d9, 0x68dc,
+ 0x68dd, 0x68e5, 0x68e8, 0x68ea, 0x68eb, 0x68ec, 0x68ed, 0x68f0,
+ 0x68f1, 0x68f5, 0x68f6, 0x68fb, 0x68fc, 0x68fd, 0x6906, 0x6909,
+ 0x690a, 0x6910, 0x6911, 0x6913, 0x6916, 0x6917, 0x6931, 0x6933,
+ 0x6935, 0x6938, 0x693b, 0x6942, 0x6945, 0x6949, 0x694e, 0x6957,
+ 0x695b, 0x6963, 0x6964, 0x6965, 0x6966, 0x6968, 0x6969, 0x696c,
+ 0x6970, 0x6971, 0x6972, 0x697a, 0x697b, 0x697f, 0x6980, 0x698d,
+ 0x6992, 0x6996, 0x6998, 0x69a1, 0x69a5, 0x69a6, 0x69a8, 0x69ab,
+ 0x69ad, 0x69af, 0x69b7, 0x69b8, 0x69ba, 0x69bc, 0x69c5, 0x69c8,
+ 0x69d1, 0x69d6, 0x69d7, 0x69e2, 0x69e5, 0x69ee, 0x69ef, 0x69f1,
+ 0x69f3, 0x69f5, 0x69fe, 0x6a00, 0x6a01, 0x6a03, 0x6a0f, 0x6a11,
+ 0x6a15, 0x6a1a, 0x6a1d, 0x6a20, 0x6a24, 0x6a28, 0x6a30, 0x6a32,
+ 0x6a34, 0x6a37, 0x6a3b, 0x6a3e, 0x6a3f, 0x6a45, 0x6a46, 0x6a49,
+ 0x6a4a, 0x6a4e, 0x6a50, 0x6a51, 0x6a52, 0x6a55, 0x6a56, 0x6a5b,
+ 0x6a64, 0x6a67, 0x6a6a, 0x6a71, 0x6a73, 0x6a7e, 0x6a81, 0x6a83,
+ 0x6a86, 0x6a87, 0x6a89, 0x6a8b, 0x6a91, 0x6a9b, 0x6a9d, 0x6a9e,
+ 0x6a9f, 0x6aa5, 0x6aab, 0x6aaf, 0x6ab0, 0x6ab1, 0x6ab4, 0x6abd,
+ 0x6abe, 0x6abf, 0x6ac6, 0x6ac9, 0x6ac8, 0x6acc, 0x6ad0, 0x6ad4,
+ 0x6ad5, 0x6ad6, 0x6adc, 0x6add, 0x6ae4, 0x6ae7, 0x6aec, 0x6af0,
+ 0x6af1, 0x6af2, 0x6afc, 0x6afd, 0x6b02, 0x6b03, 0x6b06, 0x6b07,
+ 0x6b09, 0x6b0f, 0x6b10, 0x6b11, 0x6b17, 0x6b1b, 0x6b1e, 0x6b24,
+ 0x6b28, 0x6b2b, 0x6b2c, 0x6b2f, 0x6b35, 0x6b36, 0x6b3b, 0x6b3f,
+ 0x6b46, 0x6b4a, 0x6b4d, 0x6b52, 0x6b56, 0x6b58, 0x6b5d, 0x6b60,
+ 0x6b67, 0x6b6b, 0x6b6e, 0x6b70, 0x6b75, 0x6b7d, 0x6b7e, 0x6b82,
+ 0x6b85, 0x6b97, 0x6b9b, 0x6b9f, 0x6ba0, 0x6ba2, 0x6ba3, 0x6ba8,
+ 0x6ba9, 0x6bac, 0x6bad, 0x6bae, 0x6bb0, 0x6bb8, 0x6bb9, 0x6bbd,
+ 0x6bbe, 0x6bc3, 0x6bc4, 0x6bc9, 0x6bcc, 0x6bd6, 0x6bda, 0x6be1,
+ 0x6be3, 0x6be6, 0x6be7, 0x6bee, 0x6bf1, 0x6bf7, 0x6bf9, 0x6bff,
+ 0x6c02, 0x6c04, 0x6c05, 0x6c09, 0x6c0d, 0x6c0e, 0x6c10, 0x6c12,
+ 0x6c19, 0x6c1f, 0x6c26, 0x6c27, 0x6c28, 0x6c2c, 0x6c2e, 0x6c33,
+ 0x6c35, 0x6c36, 0x6c3a, 0x6c3b, 0x6c3f, 0x6c4a, 0x6c4b, 0x6c4d,
+ 0x6c4f, 0x6c52, 0x6c54, 0x6c59, 0x6c5b, 0x6c5c, 0x6c6b, 0x6c6d,
+ 0x6c6f, 0x6c74, 0x6c76, 0x6c78, 0x6c79, 0x6c7b, 0x6c85, 0x6c86,
+ 0x6c87, 0x6c89, 0x6c94, 0x6c95, 0x6c97, 0x6c98, 0x6c9c, 0x6c9f,
+ 0x6cb0, 0x6cb2, 0x6cb4, 0x6cc2, 0x6cc6, 0x6ccd, 0x6ccf, 0x6cd0,
+ 0x6cd1, 0x6cd2, 0x6cd4, 0x6cd6, 0x6cda, 0x6cdc, 0x6ce0, 0x6ce7,
+ 0x6ce9, 0x6ceb, 0x6cec, 0x6cee, 0x6cf2, 0x6cf4, 0x6d04, 0x6d07,
+ 0x6d0a, 0x6d0e, 0x6d0f, 0x6d11, 0x6d13, 0x6d1a, 0x6d26, 0x6d27,
+ 0x6d28, 0x6c67, 0x6d2e, 0x6d2f, 0x6d31, 0x6d39, 0x6d3c, 0x6d3f,
+ 0x6d57, 0x6d5e, 0x6d5f, 0x6d61, 0x6d65, 0x6d67, 0x6d6f, 0x6d70,
+ 0x6d7c, 0x6d82, 0x6d87, 0x6d91, 0x6d92, 0x6d94, 0x6d96, 0x6d97,
+ 0x6d98, 0x6daa, 0x6dac, 0x6db4, 0x6db7, 0x6db9, 0x6dbd, 0x6dbf,
+ 0x6dc4, 0x6dc8, 0x6dca, 0x6dce, 0x6dcf, 0x6dd6, 0x6ddb, 0x6ddd,
+ 0x6ddf, 0x6de0, 0x6de2, 0x6de5, 0x6de9, 0x6def, 0x6df0, 0x6df4,
+ 0x6df6, 0x6dfc, 0x6e00, 0x6e04, 0x6e1e, 0x6e22, 0x6e27, 0x6e32,
+ 0x6e36, 0x6e39, 0x6e3b, 0x6e3c, 0x6e44, 0x6e45, 0x6e48, 0x6e49,
+ 0x6e4b, 0x6e4f, 0x6e51, 0x6e52, 0x6e53, 0x6e54, 0x6e57, 0x6e5c,
+ 0x6e5d, 0x6e5e, 0x6e62, 0x6e63, 0x6e68, 0x6e73, 0x6e7b, 0x6e7d,
+ 0x6e8d, 0x6e93, 0x6e99, 0x6ea0, 0x6ea7, 0x6ead, 0x6eae, 0x6eb1,
+ 0x6eb3, 0x6ebb, 0x6ebf, 0x6ec0, 0x6ec1, 0x6ec3, 0x6ec7, 0x6ec8,
+ 0x6eca, 0x6ecd, 0x6ece, 0x6ecf, 0x6eeb, 0x6eed, 0x6eee, 0x6ef9,
+ 0x6efb, 0x6efd, 0x6f04, 0x6f08, 0x6f0a, 0x6f0c, 0x6f0d, 0x6f16,
+ 0x6f18, 0x6f1a, 0x6f1b, 0x6f26, 0x6f29, 0x6f2a, 0x6f2f, 0x6f30,
+ 0x6f33, 0x6f36, 0x6f3b, 0x6f3c, 0x6f2d, 0x6f4f, 0x6f51, 0x6f52,
+ 0x6f53, 0x6f57, 0x6f59, 0x6f5a, 0x6f5d, 0x6f5e, 0x6f61, 0x6f62,
+ 0x6f68, 0x6f6c, 0x6f7d, 0x6f7e, 0x6f83, 0x6f87, 0x6f88, 0x6f8b,
+ 0x6f8c, 0x6f8d, 0x6f90, 0x6f92, 0x6f93, 0x6f94, 0x6f96, 0x6f9a,
+ 0x6f9f, 0x6fa0, 0x6fa5, 0x6fa6, 0x6fa7, 0x6fa8, 0x6fae, 0x6faf,
+ 0x6fb0, 0x6fb5, 0x6fb6, 0x6fbc, 0x6fc5, 0x6fc7, 0x6fc8, 0x6fca,
+ 0x6fda, 0x6fde, 0x6fe8, 0x6fe9, 0x6ff0, 0x6ff5, 0x6ff9, 0x6ffc,
+ 0x6ffd, 0x7000, 0x7005, 0x7006, 0x7007, 0x700d, 0x7017, 0x7020,
+ 0x7023, 0x702f, 0x7034, 0x7037, 0x7039, 0x703c, 0x7043, 0x7044,
+ 0x7048, 0x7049, 0x704a, 0x704b, 0x7054, 0x7055, 0x705d, 0x705e,
+ 0x704e, 0x7064, 0x7065, 0x706c, 0x706e, 0x7075, 0x7076, 0x707e,
+ 0x7081, 0x7085, 0x7086, 0x7094, 0x7095, 0x7096, 0x7097, 0x7098,
+ 0x709b, 0x70a4, 0x70ab, 0x70b0, 0x70b1, 0x70b4, 0x70b7, 0x70ca,
+ 0x70d1, 0x70d3, 0x70d4, 0x70d5, 0x70d6, 0x70d8, 0x70dc, 0x70e4,
+ 0x70fa, 0x7103, 0x7104, 0x7105, 0x7106, 0x7107, 0x710b, 0x710c,
+ 0x710f, 0x711e, 0x7120, 0x712b, 0x712d, 0x712f, 0x7130, 0x7131,
+ 0x7138, 0x7141, 0x7145, 0x7146, 0x7147, 0x714a, 0x714b, 0x7150,
+ 0x7152, 0x7157, 0x715a, 0x715c, 0x715e, 0x7160, 0x7168, 0x7179,
+ 0x7180, 0x7185, 0x7187, 0x718c, 0x7192, 0x719a, 0x719b, 0x71a0,
+ 0x71a2, 0x71af, 0x71b0, 0x71b2, 0x71b3, 0x71ba, 0x71bf, 0x71c0,
+ 0x71c1, 0x71c4, 0x71cb, 0x71cc, 0x71d3, 0x71d6, 0x71d9, 0x71da,
+ 0x71dc, 0x71f8, 0x71fe, 0x7200, 0x7207, 0x7208, 0x7209, 0x7213,
+ 0x7217, 0x721a, 0x721d, 0x721f, 0x7224, 0x722b, 0x722f, 0x7234,
+ 0x7238, 0x7239, 0x7241, 0x7242, 0x7243, 0x7245, 0x724e, 0x724f,
+ 0x7250, 0x7253, 0x7255, 0x7256, 0x725a, 0x725c, 0x725e, 0x7260,
+ 0x7263, 0x7268, 0x726b, 0x726e, 0x726f, 0x7271, 0x7277, 0x7278,
+ 0x727b, 0x727c, 0x727f, 0x7284, 0x7289, 0x728d, 0x728e, 0x7293,
+ 0x729b, 0x72a8, 0x72ad, 0x72ae, 0x72b1, 0x72b4, 0x72be, 0x72c1,
+ 0x72c7, 0x72c9, 0x72cc, 0x72d5, 0x72d6, 0x72d8, 0x72df, 0x72e5,
+ 0x72f3, 0x72f4, 0x72fa, 0x72fb, 0x72fe, 0x7302, 0x7304, 0x7305,
+ 0x7307, 0x730b, 0x730d, 0x7312, 0x7313, 0x7318, 0x7319, 0x731e,
+ 0x7322, 0x7324, 0x7327, 0x7328, 0x732c, 0x7331, 0x7332, 0x7335,
+ 0x733a, 0x733b, 0x733d, 0x7343, 0x734d, 0x7350, 0x7352, 0x7356,
+ 0x7358, 0x735d, 0x735e, 0x735f, 0x7360, 0x7366, 0x7367, 0x7369,
+ 0x736b, 0x736c, 0x736e, 0x736f, 0x7371, 0x7377, 0x7379, 0x737c,
+ 0x7380, 0x7381, 0x7383, 0x7385, 0x7386, 0x738e, 0x7390, 0x7393,
+ 0x7395, 0x7397, 0x7398, 0x739c, 0x739e, 0x739f, 0x73a0, 0x73a2,
+ 0x73a5, 0x73a6, 0x73aa, 0x73ab, 0x73ad, 0x73b5, 0x73b7, 0x73b9,
+ 0x73bc, 0x73bd, 0x73bf, 0x73c5, 0x73c6, 0x73c9, 0x73cb, 0x73cc,
+ 0x73cf, 0x73d2, 0x73d3, 0x73d6, 0x73d9, 0x73dd, 0x73e1, 0x73e3,
+ 0x73e6, 0x73e7, 0x73e9, 0x73f4, 0x73f5, 0x73f7, 0x73f9, 0x73fa,
+ 0x73fb, 0x73fd, 0x73ff, 0x7400, 0x7401, 0x7404, 0x7407, 0x740a,
+ 0x7411, 0x741a, 0x741b, 0x7424, 0x7426, 0x7428, 0x7429, 0x742a,
+ 0x742b, 0x742c, 0x742d, 0x742e, 0x742f, 0x7430, 0x7431, 0x7439,
+ 0x7440, 0x7443, 0x7444, 0x7446, 0x7447, 0x744b, 0x744d, 0x7451,
+ 0x7452, 0x7457, 0x745d, 0x7462, 0x7466, 0x7467, 0x7468, 0x746b,
+ 0x746d, 0x746e, 0x7471, 0x7472, 0x7480, 0x7481, 0x7485, 0x7486,
+ 0x7487, 0x7489, 0x748f, 0x7490, 0x7491, 0x7492, 0x7498, 0x7499,
+ 0x749a, 0x749c, 0x749f, 0x74a0, 0x74a1, 0x74a3, 0x74a6, 0x74a8,
+ 0x74a9, 0x74aa, 0x74ab, 0x74ae, 0x74af, 0x74b1, 0x74b2, 0x74b5,
+ 0x74b9, 0x74bb, 0x74bf, 0x74c8, 0x74c9, 0x74cc, 0x74d0, 0x74d3,
+ 0x74d8, 0x74da, 0x74db, 0x74de, 0x74df, 0x74e4, 0x74e8, 0x74ea,
+ 0x74eb, 0x74ef, 0x74f4, 0x74fa, 0x74fb, 0x74fc, 0x74ff, 0x7506,
+ 0x7512, 0x7516, 0x7517, 0x7520, 0x7521, 0x7524, 0x7527, 0x7529,
+ 0x752a, 0x752f, 0x7536, 0x7539, 0x753d, 0x753e, 0x753f, 0x7540,
+ 0x7543, 0x7547, 0x7548, 0x754e, 0x7550, 0x7552, 0x7557, 0x755e,
+ 0x755f, 0x7561, 0x756f, 0x7571, 0x7579, 0x757a, 0x757b, 0x757c,
+ 0x757d, 0x757e, 0x7581, 0x7585, 0x7590, 0x7592, 0x7593, 0x7595,
+ 0x7599, 0x759c, 0x75a2, 0x75a4, 0x75b4, 0x75ba, 0x75bf, 0x75c0,
+ 0x75c1, 0x75c4, 0x75c6, 0x75cc, 0x75ce, 0x75cf, 0x75d7, 0x75dc,
+ 0x75df, 0x75e0, 0x75e1, 0x75e4, 0x75e7, 0x75ec, 0x75ee, 0x75ef,
+ 0x75f1, 0x75f9, 0x7600, 0x7602, 0x7603, 0x7604, 0x7607, 0x7608,
+ 0x760a, 0x760c, 0x760f, 0x7612, 0x7613, 0x7615, 0x7616, 0x7619,
+ 0x761b, 0x761c, 0x761d, 0x761e, 0x7623, 0x7625, 0x7626, 0x7629,
+ 0x762d, 0x7632, 0x7633, 0x7635, 0x7638, 0x7639, 0x763a, 0x763c,
+ 0x764a, 0x7640, 0x7641, 0x7643, 0x7644, 0x7645, 0x7649, 0x764b,
+ 0x7655, 0x7659, 0x765f, 0x7664, 0x7665, 0x766d, 0x766e, 0x766f,
+ 0x7671, 0x7674, 0x7681, 0x7685, 0x768c, 0x768d, 0x7695, 0x769b,
+ 0x769c, 0x769d, 0x769f, 0x76a0, 0x76a2, 0x76a3, 0x76a4, 0x76a5,
+ 0x76a6, 0x76a7, 0x76a8, 0x76aa, 0x76ad, 0x76bd, 0x76c1, 0x76c5,
+ 0x76c9, 0x76cb, 0x76cc, 0x76ce, 0x76d4, 0x76d9, 0x76e0, 0x76e6,
+ 0x76e8, 0x76ec, 0x76f0, 0x76f1, 0x76f6, 0x76f9, 0x76fc, 0x7700,
+ 0x7706, 0x770a, 0x770e, 0x7712, 0x7714, 0x7715, 0x7717, 0x7719,
+ 0x771a, 0x771c, 0x7722, 0x7728, 0x772d, 0x772e, 0x772f, 0x7734,
+ 0x7735, 0x7736, 0x7739, 0x773d, 0x773e, 0x7742, 0x7745, 0x7746,
+ 0x774a, 0x774d, 0x774e, 0x774f, 0x7752, 0x7756, 0x7757, 0x775c,
+ 0x775e, 0x775f, 0x7760, 0x7762, 0x7764, 0x7767, 0x776a, 0x776c,
+ 0x7770, 0x7772, 0x7773, 0x7774, 0x777a, 0x777d, 0x7780, 0x7784,
+ 0x778c, 0x778d, 0x7794, 0x7795, 0x7796, 0x779a, 0x779f, 0x77a2,
+ 0x77a7, 0x77aa, 0x77ae, 0x77af, 0x77b1, 0x77b5, 0x77be, 0x77c3,
+ 0x77c9, 0x77d1, 0x77d2, 0x77d5, 0x77d9, 0x77de, 0x77df, 0x77e0,
+ 0x77e4, 0x77e6, 0x77ea, 0x77ec, 0x77f0, 0x77f1, 0x77f4, 0x77f8,
+ 0x77fb, 0x7805, 0x7806, 0x7809, 0x780d, 0x780e, 0x7811, 0x781d,
+ 0x7821, 0x7822, 0x7823, 0x782d, 0x782e, 0x7830, 0x7835, 0x7837,
+ 0x7843, 0x7844, 0x7847, 0x7848, 0x784c, 0x784e, 0x7852, 0x785c,
+ 0x785e, 0x7860, 0x7861, 0x7863, 0x7864, 0x7868, 0x786a, 0x786e,
+ 0x787a, 0x787e, 0x788a, 0x788f, 0x7894, 0x7898, 0x78a1, 0x789d,
+ 0x789e, 0x789f, 0x78a4, 0x78a8, 0x78ac, 0x78ad, 0x78b0, 0x78b1,
+ 0x78b2, 0x78b3, 0x78bb, 0x78bd, 0x78bf, 0x78c7, 0x78c8, 0x78c9,
+ 0x78cc, 0x78ce, 0x78d2, 0x78d3, 0x78d5, 0x78d6, 0x78e4, 0x78db,
+ 0x78df, 0x78e0, 0x78e1, 0x78e6, 0x78ea, 0x78f2, 0x78f3, 0x7900,
+ 0x78f6, 0x78f7, 0x78fa, 0x78fb, 0x78ff, 0x7906, 0x790c, 0x7910,
+ 0x791a, 0x791c, 0x791e, 0x791f, 0x7920, 0x7925, 0x7927, 0x7929,
+ 0x792d, 0x7931, 0x7934, 0x7935, 0x793b, 0x793d, 0x793f, 0x7944,
+ 0x7945, 0x7946, 0x794a, 0x794b, 0x794f, 0x7951, 0x7954, 0x7958,
+ 0x795b, 0x795c, 0x7967, 0x7969, 0x796b, 0x7972, 0x7979, 0x797b,
+ 0x797c, 0x797e, 0x798b, 0x798c, 0x7991, 0x7993, 0x7994, 0x7995,
+ 0x7996, 0x7998, 0x799b, 0x799c, 0x79a1, 0x79a8, 0x79a9, 0x79ab,
+ 0x79af, 0x79b1, 0x79b4, 0x79b8, 0x79bb, 0x79c2, 0x79c4, 0x79c7,
+ 0x79c8, 0x79ca, 0x79cf, 0x79d4, 0x79d6, 0x79da, 0x79dd, 0x79de,
+ 0x79e0, 0x79e2, 0x79e5, 0x79ea, 0x79eb, 0x79ed, 0x79f1, 0x79f8,
+ 0x79fc, 0x7a02, 0x7a03, 0x7a07, 0x7a09, 0x7a0a, 0x7a0c, 0x7a11,
+ 0x7a15, 0x7a1b, 0x7a1e, 0x7a21, 0x7a27, 0x7a2b, 0x7a2d, 0x7a2f,
+ 0x7a30, 0x7a34, 0x7a35, 0x7a38, 0x7a39, 0x7a3a, 0x7a44, 0x7a45,
+ 0x7a47, 0x7a48, 0x7a4c, 0x7a55, 0x7a56, 0x7a59, 0x7a5c, 0x7a5d,
+ 0x7a5f, 0x7a60, 0x7a65, 0x7a67, 0x7a6a, 0x7a6d, 0x7a75, 0x7a78,
+ 0x7a7e, 0x7a80, 0x7a82, 0x7a85, 0x7a86, 0x7a8a, 0x7a8b, 0x7a90,
+ 0x7a91, 0x7a94, 0x7a9e, 0x7aa0, 0x7aa3, 0x7aac, 0x7ab3, 0x7ab5,
+ 0x7ab9, 0x7abb, 0x7abc, 0x7ac6, 0x7ac9, 0x7acc, 0x7ace, 0x7ad1,
+ 0x7adb, 0x7ae8, 0x7ae9, 0x7aeb, 0x7aec, 0x7af1, 0x7af4, 0x7afb,
+ 0x7afd, 0x7afe, 0x7b07, 0x7b14, 0x7b1f, 0x7b23, 0x7b27, 0x7b29,
+ 0x7b2a, 0x7b2b, 0x7b2d, 0x7b2e, 0x7b2f, 0x7b30, 0x7b31, 0x7b34,
+ 0x7b3d, 0x7b3f, 0x7b40, 0x7b41, 0x7b47, 0x7b4e, 0x7b55, 0x7b60,
+ 0x7b64, 0x7b66, 0x7b69, 0x7b6a, 0x7b6d, 0x7b6f, 0x7b72, 0x7b73,
+ 0x7b77, 0x7b84, 0x7b89, 0x7b8e, 0x7b90, 0x7b91, 0x7b96, 0x7b9b,
+ 0x7b9e, 0x7ba0, 0x7ba5, 0x7bac, 0x7baf, 0x7bb0, 0x7bb2, 0x7bb5,
+ 0x7bb6, 0x7bba, 0x7bbb, 0x7bbc, 0x7bbd, 0x7bc2, 0x7bc5, 0x7bc8,
+ 0x7bca, 0x7bd4, 0x7bd6, 0x7bd7, 0x7bd9, 0x7bda, 0x7bdb, 0x7be8,
+ 0x7bea, 0x7bf2, 0x7bf4, 0x7bf5, 0x7bf8, 0x7bf9, 0x7bfa, 0x7bfc,
+ 0x7bfe, 0x7c01, 0x7c02, 0x7c03, 0x7c04, 0x7c06, 0x7c09, 0x7c0b,
+ 0x7c0c, 0x7c0e, 0x7c0f, 0x7c19, 0x7c1b, 0x7c20, 0x7c25, 0x7c26,
+ 0x7c28, 0x7c2c, 0x7c31, 0x7c33, 0x7c34, 0x7c36, 0x7c39, 0x7c3a,
+ 0x7c46, 0x7c4a, 0x7c55, 0x7c51, 0x7c52, 0x7c53, 0x7c59, 0x7c5a,
+ 0x7c5b, 0x7c5c, 0x7c5d, 0x7c5e, 0x7c61, 0x7c63, 0x7c67, 0x7c69,
+ 0x7c6d, 0x7c6e, 0x7c70, 0x7c72, 0x7c79, 0x7c7c, 0x7c7d, 0x7c86,
+ 0x7c87, 0x7c8f, 0x7c94, 0x7c9e, 0x7ca0, 0x7ca6, 0x7cb0, 0x7cb6,
+ 0x7cb7, 0x7cba, 0x7cbb, 0x7cbc, 0x7cbf, 0x7cc4, 0x7cc7, 0x7cc8,
+ 0x7cc9, 0x7ccd, 0x7ccf, 0x7cd3, 0x7cd4, 0x7cd5, 0x7cd7, 0x7cd9,
+ 0x7cda, 0x7cdd, 0x7ce6, 0x7ce9, 0x7ceb, 0x7cf5, 0x7d03, 0x7d07,
+ 0x7d08, 0x7d09, 0x7d0f, 0x7d11, 0x7d12, 0x7d13, 0x7d16, 0x7d1d,
+ 0x7d1e, 0x7d23, 0x7d26, 0x7d2a, 0x7d2d, 0x7d31, 0x7d3c, 0x7d3d,
+ 0x7d3e, 0x7d40, 0x7d41, 0x7d47, 0x7d48, 0x7d4d, 0x7d51, 0x7d53,
+ 0x7d57, 0x7d59, 0x7d5a, 0x7d5c, 0x7d5d, 0x7d65, 0x7d67, 0x7d6a,
+ 0x7d70, 0x7d78, 0x7d7a, 0x7d7b, 0x7d7f, 0x7d81, 0x7d82, 0x7d83,
+ 0x7d85, 0x7d86, 0x7d88, 0x7d8b, 0x7d8c, 0x7d8d, 0x7d91, 0x7d96,
+ 0x7d97, 0x7d9d, 0x7d9e, 0x7da6, 0x7da7, 0x7daa, 0x7db3, 0x7db6,
+ 0x7db7, 0x7db9, 0x7dc2, 0x7dc3, 0x7dc4, 0x7dc5, 0x7dc6, 0x7dcc,
+ 0x7dcd, 0x7dce, 0x7dd7, 0x7dd9, 0x7e00, 0x7de2, 0x7de5, 0x7de6,
+ 0x7dea, 0x7deb, 0x7ded, 0x7df1, 0x7df5, 0x7df6, 0x7df9, 0x7dfa,
+ 0x7e08, 0x7e10, 0x7e11, 0x7e15, 0x7e17, 0x7e1c, 0x7e1d, 0x7e20,
+ 0x7e27, 0x7e28, 0x7e2c, 0x7e2d, 0x7e2f, 0x7e33, 0x7e36, 0x7e3f,
+ 0x7e44, 0x7e45, 0x7e47, 0x7e4e, 0x7e50, 0x7e52, 0x7e58, 0x7e5f,
+ 0x7e61, 0x7e62, 0x7e65, 0x7e6b, 0x7e6e, 0x7e6f, 0x7e73, 0x7e78,
+ 0x7e7e, 0x7e81, 0x7e86, 0x7e87, 0x7e8a, 0x7e8d, 0x7e91, 0x7e95,
+ 0x7e98, 0x7e9a, 0x7e9d, 0x7e9e, 0x7f3c, 0x7f3b, 0x7f3d, 0x7f3e,
+ 0x7f3f, 0x7f43, 0x7f44, 0x7f47, 0x7f4f, 0x7f52, 0x7f53, 0x7f5b,
+ 0x7f5c, 0x7f5d, 0x7f61, 0x7f63, 0x7f64, 0x7f65, 0x7f66, 0x7f6d,
+ 0x7f71, 0x7f7d, 0x7f7e, 0x7f7f, 0x7f80, 0x7f8b, 0x7f8d, 0x7f8f,
+ 0x7f90, 0x7f91, 0x7f96, 0x7f97, 0x7f9c, 0x7fa1, 0x7fa2, 0x7fa6,
+ 0x7faa, 0x7fad, 0x7fb4, 0x7fbc, 0x7fbf, 0x7fc0, 0x7fc3, 0x7fc8,
+ 0x7fce, 0x7fcf, 0x7fdb, 0x7fdf, 0x7fe3, 0x7fe5, 0x7fe8, 0x7fec,
+ 0x7fee, 0x7fef, 0x7ff2, 0x7ffa, 0x7ffd, 0x7ffe, 0x7fff, 0x8007,
+ 0x8008, 0x800a, 0x800d, 0x800e, 0x800f, 0x8011, 0x8013, 0x8014,
+ 0x8016, 0x801d, 0x801e, 0x801f, 0x8020, 0x8024, 0x8026, 0x802c,
+ 0x802e, 0x8030, 0x8034, 0x8035, 0x8037, 0x8039, 0x803a, 0x803c,
+ 0x803e, 0x8040, 0x8044, 0x8060, 0x8064, 0x8066, 0x806d, 0x8071,
+ 0x8075, 0x8081, 0x8088, 0x808e, 0x809c, 0x809e, 0x80a6, 0x80a7,
+ 0x80ab, 0x80b8, 0x80b9, 0x80c8, 0x80cd, 0x80cf, 0x80d2, 0x80d4,
+ 0x80d5, 0x80d7, 0x80d8, 0x80e0, 0x80ed, 0x80ee, 0x80f0, 0x80f2,
+ 0x80f3, 0x80f6, 0x80f9, 0x80fa, 0x80fe, 0x8103, 0x810b, 0x8116,
+ 0x8117, 0x8118, 0x811c, 0x811e, 0x8120, 0x8124, 0x8127, 0x812c,
+ 0x8130, 0x8135, 0x813a, 0x813c, 0x8145, 0x8147, 0x814a, 0x814c,
+ 0x8152, 0x8157, 0x8160, 0x8161, 0x8167, 0x8168, 0x8169, 0x816d,
+ 0x816f, 0x8177, 0x8181, 0x8190, 0x8184, 0x8185, 0x8186, 0x818b,
+ 0x818e, 0x8196, 0x8198, 0x819b, 0x819e, 0x81a2, 0x81ae, 0x81b2,
+ 0x81b4, 0x81bb, 0x81cb, 0x81c3, 0x81c5, 0x81ca, 0x81ce, 0x81cf,
+ 0x81d5, 0x81d7, 0x81db, 0x81dd, 0x81de, 0x81e1, 0x81e4, 0x81eb,
+ 0x81ec, 0x81f0, 0x81f1, 0x81f2, 0x81f5, 0x81f6, 0x81f8, 0x81f9,
+ 0x81fd, 0x81ff, 0x8200, 0x8203, 0x820f, 0x8213, 0x8214, 0x8219,
+ 0x821a, 0x821d, 0x8221, 0x8222, 0x8228, 0x8232, 0x8234, 0x823a,
+ 0x8243, 0x8244, 0x8245, 0x8246, 0x824b, 0x824e, 0x824f, 0x8251,
+ 0x8256, 0x825c, 0x8260, 0x8263, 0x8267, 0x826d, 0x8274, 0x827b,
+ 0x827d, 0x827f, 0x8280, 0x8281, 0x8283, 0x8284, 0x8287, 0x8289,
+ 0x828a, 0x828e, 0x8291, 0x8294, 0x8296, 0x8298, 0x829a, 0x829b,
+ 0x82a0, 0x82a1, 0x82a3, 0x82a4, 0x82a7, 0x82a8, 0x82a9, 0x82aa,
+ 0x82ae, 0x82b0, 0x82b2, 0x82b4, 0x82b7, 0x82ba, 0x82bc, 0x82be,
+ 0x82bf, 0x82c6, 0x82d0, 0x82d5, 0x82da, 0x82e0, 0x82e2, 0x82e4,
+ 0x82e8, 0x82ea, 0x82ed, 0x82ef, 0x82f6, 0x82f7, 0x82fd, 0x82fe,
+ 0x8300, 0x8301, 0x8307, 0x8308, 0x830a, 0x830b, 0x8354, 0x831b,
+ 0x831d, 0x831e, 0x831f, 0x8321, 0x8322, 0x832c, 0x832d, 0x832e,
+ 0x8330, 0x8333, 0x8337, 0x833a, 0x833c, 0x833d, 0x8342, 0x8343,
+ 0x8344, 0x8347, 0x834d, 0x834e, 0x8351, 0x8355, 0x8356, 0x8357,
+ 0x8370, 0x8378, 0x837d, 0x837f, 0x8380, 0x8382, 0x8384, 0x8386,
+ 0x838d, 0x8392, 0x8394, 0x8395, 0x8398, 0x8399, 0x839b, 0x839c,
+ 0x839d, 0x83a6, 0x83a7, 0x83a9, 0x83ac, 0x83be, 0x83bf, 0x83c0,
+ 0x83c7, 0x83c9, 0x83cf, 0x83d0, 0x83d1, 0x83d4, 0x83dd, 0x8353,
+ 0x83e8, 0x83ea, 0x83f6, 0x83f8, 0x83f9, 0x83fc, 0x8401, 0x8406,
+ 0x840a, 0x840f, 0x8411, 0x8415, 0x8419, 0x83ad, 0x842f, 0x8439,
+ 0x8445, 0x8447, 0x8448, 0x844a, 0x844d, 0x844f, 0x8451, 0x8452,
+ 0x8456, 0x8458, 0x8459, 0x845a, 0x845c, 0x8460, 0x8464, 0x8465,
+ 0x8467, 0x846a, 0x8470, 0x8473, 0x8474, 0x8476, 0x8478, 0x847c,
+ 0x847d, 0x8481, 0x8485, 0x8492, 0x8493, 0x8495, 0x849e, 0x84a6,
+ 0x84a8, 0x84a9, 0x84aa, 0x84af, 0x84b1, 0x84b4, 0x84ba, 0x84bd,
+ 0x84be, 0x84c0, 0x84c2, 0x84c7, 0x84c8, 0x84cc, 0x84cf, 0x84d3,
+ 0x84dc, 0x84e7, 0x84ea, 0x84ef, 0x84f0, 0x84f1, 0x84f2, 0x84f7,
+ 0x8532, 0x84fa, 0x84fb, 0x84fd, 0x8502, 0x8503, 0x8507, 0x850c,
+ 0x850e, 0x8510, 0x851c, 0x851e, 0x8522, 0x8523, 0x8524, 0x8525,
+ 0x8527, 0x852a, 0x852b, 0x852f, 0x8533, 0x8534, 0x8536, 0x853f,
+ 0x8546, 0x854f, 0x8550, 0x8551, 0x8552, 0x8553, 0x8556, 0x8559,
+ 0x855c, 0x855d, 0x855e, 0x855f, 0x8560, 0x8561, 0x8562, 0x8564,
+ 0x856b, 0x856f, 0x8579, 0x857a, 0x857b, 0x857d, 0x857f, 0x8581,
+ 0x8585, 0x8586, 0x8589, 0x858b, 0x858c, 0x858f, 0x8593, 0x8598,
+ 0x859d, 0x859f, 0x85a0, 0x85a2, 0x85a5, 0x85a7, 0x85b4, 0x85b6,
+ 0x85b7, 0x85b8, 0x85bc, 0x85bd, 0x85be, 0x85bf, 0x85c2, 0x85c7,
+ 0x85ca, 0x85cb, 0x85ce, 0x85ad, 0x85d8, 0x85da, 0x85df, 0x85e0,
+ 0x85e6, 0x85e8, 0x85ed, 0x85f3, 0x85f6, 0x85fc, 0x85ff, 0x8600,
+ 0x8604, 0x8605, 0x860d, 0x860e, 0x8610, 0x8611, 0x8612, 0x8618,
+ 0x8619, 0x861b, 0x861e, 0x8621, 0x8627, 0x8629, 0x8636, 0x8638,
+ 0x863a, 0x863c, 0x863d, 0x8640, 0x8642, 0x8646, 0x8652, 0x8653,
+ 0x8656, 0x8657, 0x8658, 0x8659, 0x865d, 0x8660, 0x8661, 0x8662,
+ 0x8663, 0x8664, 0x8669, 0x866c, 0x866f, 0x8675, 0x8676, 0x8677,
+ 0x867a, 0x868d, 0x8691, 0x8696, 0x8698, 0x869a, 0x869c, 0x86a1,
+ 0x86a6, 0x86a7, 0x86a8, 0x86ad, 0x86b1, 0x86b3, 0x86b4, 0x86b5,
+ 0x86b7, 0x86b8, 0x86b9, 0x86bf, 0x86c0, 0x86c1, 0x86c3, 0x86c5,
+ 0x86d1, 0x86d2, 0x86d5, 0x86d7, 0x86da, 0x86dc, 0x86e0, 0x86e3,
+ 0x86e5, 0x86e7, 0x8688, 0x86fa, 0x86fc, 0x86fd, 0x8704, 0x8705,
+ 0x8707, 0x870b, 0x870e, 0x870f, 0x8710, 0x8713, 0x8714, 0x8719,
+ 0x871e, 0x871f, 0x8721, 0x8723, 0x8728, 0x872e, 0x872f, 0x8731,
+ 0x8732, 0x8739, 0x873a, 0x873c, 0x873d, 0x873e, 0x8740, 0x8743,
+ 0x8745, 0x874d, 0x8758, 0x875d, 0x8761, 0x8764, 0x8765, 0x876f,
+ 0x8771, 0x8772, 0x877b, 0x8783, 0x8784, 0x8785, 0x8786, 0x8787,
+ 0x8788, 0x8789, 0x878b, 0x878c, 0x8790, 0x8793, 0x8795, 0x8797,
+ 0x8798, 0x8799, 0x879e, 0x87a0, 0x87a3, 0x87a7, 0x87ac, 0x87ad,
+ 0x87ae, 0x87b1, 0x87b5, 0x87be, 0x87bf, 0x87c1, 0x87c8, 0x87c9,
+ 0x87ca, 0x87ce, 0x87d5, 0x87d6, 0x87d9, 0x87da, 0x87dc, 0x87df,
+ 0x87e2, 0x87e3, 0x87e4, 0x87ea, 0x87eb, 0x87ed, 0x87f1, 0x87f3,
+ 0x87f8, 0x87fa, 0x87ff, 0x8801, 0x8803, 0x8806, 0x8809, 0x880a,
+ 0x880b, 0x8810, 0x8819, 0x8812, 0x8813, 0x8814, 0x8818, 0x881a,
+ 0x881b, 0x881c, 0x881e, 0x881f, 0x8828, 0x882d, 0x882e, 0x8830,
+ 0x8832, 0x8835, 0x883a, 0x883c, 0x8841, 0x8843, 0x8845, 0x8848,
+ 0x8849, 0x884a, 0x884b, 0x884e, 0x8851, 0x8855, 0x8856, 0x8858,
+ 0x885a, 0x885c, 0x885f, 0x8860, 0x8864, 0x8869, 0x8871, 0x8879,
+ 0x887b, 0x8880, 0x8898, 0x889a, 0x889b, 0x889c, 0x889f, 0x88a0,
+ 0x88a8, 0x88aa, 0x88ba, 0x88bd, 0x88be, 0x88c0, 0x88ca, 0x88cb,
+ 0x88cc, 0x88cd, 0x88ce, 0x88d1, 0x88d2, 0x88d3, 0x88db, 0x88de,
+ 0x88e7, 0x88ef, 0x88f0, 0x88f1, 0x88f5, 0x88f7, 0x8901, 0x8906,
+ 0x890d, 0x890e, 0x890f, 0x8915, 0x8916, 0x8918, 0x8919, 0x891a,
+ 0x891c, 0x8920, 0x8926, 0x8927, 0x8928, 0x8930, 0x8931, 0x8932,
+ 0x8935, 0x8939, 0x893a, 0x893e, 0x8940, 0x8942, 0x8945, 0x8946,
+ 0x8949, 0x894f, 0x8952, 0x8957, 0x895a, 0x895b, 0x895c, 0x8961,
+ 0x8962, 0x8963, 0x896b, 0x896e, 0x8970, 0x8973, 0x8975, 0x897a,
+ 0x897b, 0x897c, 0x897d, 0x8989, 0x898d, 0x8990, 0x8994, 0x8995,
+ 0x899b, 0x899c, 0x899f, 0x89a0, 0x89a5, 0x89b0, 0x89b4, 0x89b5,
+ 0x89b6, 0x89b7, 0x89bc, 0x89d4, 0x89d5, 0x89d6, 0x89d7, 0x89d8,
+ 0x89e5, 0x89e9, 0x89eb, 0x89ed, 0x89f1, 0x89f3, 0x89f6, 0x89f9,
+ 0x89fd, 0x89ff, 0x8a04, 0x8a05, 0x8a07, 0x8a0f, 0x8a11, 0x8a12,
+ 0x8a14, 0x8a15, 0x8a1e, 0x8a20, 0x8a22, 0x8a24, 0x8a26, 0x8a2b,
+ 0x8a2c, 0x8a2f, 0x8a35, 0x8a37, 0x8a3d, 0x8a3e, 0x8a40, 0x8a43,
+ 0x8a45, 0x8a47, 0x8a49, 0x8a4d, 0x8a4e, 0x8a53, 0x8a56, 0x8a57,
+ 0x8a58, 0x8a5c, 0x8a5d, 0x8a61, 0x8a65, 0x8a67, 0x8a75, 0x8a76,
+ 0x8a77, 0x8a79, 0x8a7a, 0x8a7b, 0x8a7e, 0x8a7f, 0x8a80, 0x8a83,
+ 0x8a86, 0x8a8b, 0x8a8f, 0x8a90, 0x8a92, 0x8a96, 0x8a97, 0x8a99,
+ 0x8a9f, 0x8aa7, 0x8aa9, 0x8aae, 0x8aaf, 0x8ab3, 0x8ab6, 0x8ab7,
+ 0x8abb, 0x8abe, 0x8ac3, 0x8ac6, 0x8ac8, 0x8ac9, 0x8aca, 0x8ad1,
+ 0x8ad3, 0x8ad4, 0x8ad5, 0x8ad7, 0x8add, 0x8adf, 0x8aec, 0x8af0,
+ 0x8af4, 0x8af5, 0x8af6, 0x8afc, 0x8aff, 0x8b05, 0x8b06, 0x8b0b,
+ 0x8b11, 0x8b1c, 0x8b1e, 0x8b1f, 0x8b0a, 0x8b2d, 0x8b30, 0x8b37,
+ 0x8b3c, 0x8b42, 0x8b43, 0x8b44, 0x8b45, 0x8b46, 0x8b48, 0x8b52,
+ 0x8b53, 0x8b54, 0x8b59, 0x8b4d, 0x8b5e, 0x8b63, 0x8b6d, 0x8b76,
+ 0x8b78, 0x8b79, 0x8b7c, 0x8b7e, 0x8b81, 0x8b84, 0x8b85, 0x8b8b,
+ 0x8b8d, 0x8b8f, 0x8b94, 0x8b95, 0x8b9c, 0x8b9e, 0x8b9f, 0x8c38,
+ 0x8c39, 0x8c3d, 0x8c3e, 0x8c45, 0x8c47, 0x8c49, 0x8c4b, 0x8c4f,
+ 0x8c51, 0x8c53, 0x8c54, 0x8c57, 0x8c58, 0x8c5b, 0x8c5d, 0x8c59,
+ 0x8c63, 0x8c64, 0x8c66, 0x8c68, 0x8c69, 0x8c6d, 0x8c73, 0x8c75,
+ 0x8c76, 0x8c7b, 0x8c7e, 0x8c86, 0x8c87, 0x8c8b, 0x8c90, 0x8c92,
+ 0x8c93, 0x8c99, 0x8c9b, 0x8c9c, 0x8ca4, 0x8cb9, 0x8cba, 0x8cc5,
+ 0x8cc6, 0x8cc9, 0x8ccb, 0x8ccf, 0x8cd6, 0x8cd5, 0x8cd9, 0x8cdd,
+ 0x8ce1, 0x8ce8, 0x8cec, 0x8cef, 0x8cf0, 0x8cf2, 0x8cf5, 0x8cf7,
+ 0x8cf8, 0x8cfe, 0x8cff, 0x8d01, 0x8d03, 0x8d09, 0x8d12, 0x8d17,
+ 0x8d1b, 0x8d65, 0x8d69, 0x8d6c, 0x8d6e, 0x8d7f, 0x8d82, 0x8d84,
+ 0x8d88, 0x8d8d, 0x8d90, 0x8d91, 0x8d95, 0x8d9e, 0x8d9f, 0x8da0,
+ 0x8da6, 0x8dab, 0x8dac, 0x8daf, 0x8db2, 0x8db5, 0x8db7, 0x8db9,
+ 0x8dbb, 0x8dc0, 0x8dc5, 0x8dc6, 0x8dc7, 0x8dc8, 0x8dca, 0x8dce,
+ 0x8dd1, 0x8dd4, 0x8dd5, 0x8dd7, 0x8dd9, 0x8de4, 0x8de5, 0x8de7,
+ 0x8dec, 0x8df0, 0x8dbc, 0x8df1, 0x8df2, 0x8df4, 0x8dfd, 0x8e01,
+ 0x8e04, 0x8e05, 0x8e06, 0x8e0b, 0x8e11, 0x8e14, 0x8e16, 0x8e20,
+ 0x8e21, 0x8e22, 0x8e23, 0x8e26, 0x8e27, 0x8e31, 0x8e33, 0x8e36,
+ 0x8e37, 0x8e38, 0x8e39, 0x8e3d, 0x8e40, 0x8e41, 0x8e4b, 0x8e4d,
+ 0x8e4e, 0x8e4f, 0x8e54, 0x8e5b, 0x8e5c, 0x8e5d, 0x8e5e, 0x8e61,
+ 0x8e62, 0x8e69, 0x8e6c, 0x8e6d, 0x8e6f, 0x8e70, 0x8e71, 0x8e79,
+ 0x8e7a, 0x8e7b, 0x8e82, 0x8e83, 0x8e89, 0x8e90, 0x8e92, 0x8e95,
+ 0x8e9a, 0x8e9b, 0x8e9d, 0x8e9e, 0x8ea2, 0x8ea7, 0x8ea9, 0x8ead,
+ 0x8eae, 0x8eb3, 0x8eb5, 0x8eba, 0x8ebb, 0x8ec0, 0x8ec1, 0x8ec3,
+ 0x8ec4, 0x8ec7, 0x8ecf, 0x8ed1, 0x8ed4, 0x8edc, 0x8ee8, 0x8eee,
+ 0x8ef0, 0x8ef1, 0x8ef7, 0x8ef9, 0x8efa, 0x8eed, 0x8f00, 0x8f02,
+ 0x8f07, 0x8f08, 0x8f0f, 0x8f10, 0x8f16, 0x8f17, 0x8f18, 0x8f1e,
+ 0x8f20, 0x8f21, 0x8f23, 0x8f25, 0x8f27, 0x8f28, 0x8f2c, 0x8f2d,
+ 0x8f2e, 0x8f34, 0x8f35, 0x8f36, 0x8f37, 0x8f3a, 0x8f40, 0x8f41,
+ 0x8f43, 0x8f47, 0x8f4f, 0x8f51, 0x8f52, 0x8f53, 0x8f54, 0x8f55,
+ 0x8f58, 0x8f5d, 0x8f5e, 0x8f65, 0x8f9d, 0x8fa0, 0x8fa1, 0x8fa4,
+ 0x8fa5, 0x8fa6, 0x8fb5, 0x8fb6, 0x8fb8, 0x8fbe, 0x8fc0, 0x8fc1,
+ 0x8fc6, 0x8fca, 0x8fcb, 0x8fcd, 0x8fd0, 0x8fd2, 0x8fd3, 0x8fd5,
+ 0x8fe0, 0x8fe3, 0x8fe4, 0x8fe8, 0x8fee, 0x8ff1, 0x8ff5, 0x8ff6,
+ 0x8ffb, 0x8ffe, 0x9002, 0x9004, 0x9008, 0x900c, 0x9018, 0x901b,
+ 0x9028, 0x9029, 0x902f, 0x902a, 0x902c, 0x902d, 0x9033, 0x9034,
+ 0x9037, 0x903f, 0x9043, 0x9044, 0x904c, 0x905b, 0x905d, 0x9062,
+ 0x9066, 0x9067, 0x906c, 0x9070, 0x9074, 0x9079, 0x9085, 0x9088,
+ 0x908b, 0x908c, 0x908e, 0x9090, 0x9095, 0x9097, 0x9098, 0x9099,
+ 0x909b, 0x90a0, 0x90a1, 0x90a2, 0x90a5, 0x90b0, 0x90b2, 0x90b3,
+ 0x90b4, 0x90b6, 0x90bd, 0x90cc, 0x90be, 0x90c3, 0x90c4, 0x90c5,
+ 0x90c7, 0x90c8, 0x90d5, 0x90d7, 0x90d8, 0x90d9, 0x90dc, 0x90dd,
+ 0x90df, 0x90e5, 0x90d2, 0x90f6, 0x90eb, 0x90ef, 0x90f0, 0x90f4,
+ 0x90fe, 0x90ff, 0x9100, 0x9104, 0x9105, 0x9106, 0x9108, 0x910d,
+ 0x9110, 0x9114, 0x9116, 0x9117, 0x9118, 0x911a, 0x911c, 0x911e,
+ 0x9120, 0x9125, 0x9122, 0x9123, 0x9127, 0x9129, 0x912e, 0x912f,
+ 0x9131, 0x9134, 0x9136, 0x9137, 0x9139, 0x913a, 0x913c, 0x913d,
+ 0x9143, 0x9147, 0x9148, 0x914f, 0x9153, 0x9157, 0x9159, 0x915a,
+ 0x915b, 0x9161, 0x9164, 0x9167, 0x916d, 0x9174, 0x9179, 0x917a,
+ 0x917b, 0x9181, 0x9183, 0x9185, 0x9186, 0x918a, 0x918e, 0x9191,
+ 0x9193, 0x9194, 0x9195, 0x9198, 0x919e, 0x91a1, 0x91a6, 0x91a8,
+ 0x91ac, 0x91ad, 0x91ae, 0x91b0, 0x91b1, 0x91b2, 0x91b3, 0x91b6,
+ 0x91bb, 0x91bc, 0x91bd, 0x91bf, 0x91c2, 0x91c3, 0x91c5, 0x91d3,
+ 0x91d4, 0x91d7, 0x91d9, 0x91da, 0x91de, 0x91e4, 0x91e5, 0x91e9,
+ 0x91ea, 0x91ec, 0x91ed, 0x91ee, 0x91ef, 0x91f0, 0x91f1, 0x91f7,
+ 0x91f9, 0x91fb, 0x91fd, 0x9200, 0x9201, 0x9204, 0x9205, 0x9206,
+ 0x9207, 0x9209, 0x920a, 0x920c, 0x9210, 0x9212, 0x9213, 0x9216,
+ 0x9218, 0x921c, 0x921d, 0x9223, 0x9224, 0x9225, 0x9226, 0x9228,
+ 0x922e, 0x922f, 0x9230, 0x9233, 0x9235, 0x9236, 0x9238, 0x9239,
+ 0x923a, 0x923c, 0x923e, 0x9240, 0x9242, 0x9243, 0x9246, 0x9247,
+ 0x924a, 0x924d, 0x924e, 0x924f, 0x9251, 0x9258, 0x9259, 0x925c,
+ 0x925d, 0x9260, 0x9261, 0x9265, 0x9267, 0x9268, 0x9269, 0x926e,
+ 0x926f, 0x9270, 0x9275, 0x9276, 0x9277, 0x9278, 0x9279, 0x927b,
+ 0x927c, 0x927d, 0x927f, 0x9288, 0x9289, 0x928a, 0x928d, 0x928e,
+ 0x9292, 0x9297, 0x9299, 0x929f, 0x92a0, 0x92a4, 0x92a5, 0x92a7,
+ 0x92a8, 0x92ab, 0x92af, 0x92b2, 0x92b6, 0x92b8, 0x92ba, 0x92bb,
+ 0x92bc, 0x92bd, 0x92bf, 0x92c0, 0x92c1, 0x92c2, 0x92c3, 0x92c5,
+ 0x92c6, 0x92c7, 0x92c8, 0x92cb, 0x92cc, 0x92cd, 0x92ce, 0x92d0,
+ 0x92d3, 0x92d5, 0x92d7, 0x92d8, 0x92d9, 0x92dc, 0x92dd, 0x92df,
+ 0x92e0, 0x92e1, 0x92e3, 0x92e5, 0x92e7, 0x92e8, 0x92ec, 0x92ee,
+ 0x92f0, 0x92f9, 0x92fb, 0x92ff, 0x9300, 0x9302, 0x9308, 0x930d,
+ 0x9311, 0x9314, 0x9315, 0x931c, 0x931d, 0x931e, 0x931f, 0x9321,
+ 0x9324, 0x9325, 0x9327, 0x9329, 0x932a, 0x9333, 0x9334, 0x9336,
+ 0x9337, 0x9347, 0x9348, 0x9349, 0x9350, 0x9351, 0x9352, 0x9355,
+ 0x9357, 0x9358, 0x935a, 0x935e, 0x9364, 0x9365, 0x9367, 0x9369,
+ 0x936a, 0x936d, 0x936f, 0x9370, 0x9371, 0x9373, 0x9374, 0x9376,
+ 0x937a, 0x937d, 0x937f, 0x9380, 0x9381, 0x9382, 0x9388, 0x938a,
+ 0x938b, 0x938d, 0x938f, 0x9392, 0x9395, 0x9398, 0x939b, 0x939e,
+ 0x93a1, 0x93a3, 0x93a4, 0x93a6, 0x93a8, 0x93ab, 0x93b4, 0x93b5,
+ 0x93b6, 0x93ba, 0x93a9, 0x93c1, 0x93c4, 0x93c5, 0x93c6, 0x93c7,
+ 0x93c9, 0x93ca, 0x93cb, 0x93cc, 0x93cd, 0x93d3, 0x93d9, 0x93dc,
+ 0x93de, 0x93df, 0x93e2, 0x93e6, 0x93e7, 0x93f9, 0x93f7, 0x93f8,
+ 0x93fa, 0x93fb, 0x93fd, 0x9401, 0x9402, 0x9404, 0x9408, 0x9409,
+ 0x940d, 0x940e, 0x940f, 0x9415, 0x9416, 0x9417, 0x941f, 0x942e,
+ 0x942f, 0x9431, 0x9432, 0x9433, 0x9434, 0x943b, 0x943f, 0x943d,
+ 0x9443, 0x9445, 0x9448, 0x944a, 0x944c, 0x9455, 0x9459, 0x945c,
+ 0x945f, 0x9461, 0x9463, 0x9468, 0x946b, 0x946d, 0x946e, 0x946f,
+ 0x9471, 0x9472, 0x9484, 0x9483, 0x9578, 0x9579, 0x957e, 0x9584,
+ 0x9588, 0x958c, 0x958d, 0x958e, 0x959d, 0x959e, 0x959f, 0x95a1,
+ 0x95a6, 0x95a9, 0x95ab, 0x95ac, 0x95b4, 0x95b6, 0x95ba, 0x95bd,
+ 0x95bf, 0x95c6, 0x95c8, 0x95c9, 0x95cb, 0x95d0, 0x95d1, 0x95d2,
+ 0x95d3, 0x95d9, 0x95da, 0x95dd, 0x95de, 0x95df, 0x95e0, 0x95e4,
+ 0x95e6, 0x961d, 0x961e, 0x9622, 0x9624, 0x9625, 0x9626, 0x962c,
+ 0x9631, 0x9633, 0x9637, 0x9638, 0x9639, 0x963a, 0x963c, 0x963d,
+ 0x9641, 0x9652, 0x9654, 0x9656, 0x9657, 0x9658, 0x9661, 0x966e,
+ 0x9674, 0x967b, 0x967c, 0x967e, 0x967f, 0x9681, 0x9682, 0x9683,
+ 0x9684, 0x9689, 0x9691, 0x9696, 0x969a, 0x969d, 0x969f, 0x96a4,
+ 0x96a5, 0x96a6, 0x96a9, 0x96ae, 0x96af, 0x96b3, 0x96ba, 0x96ca,
+ 0x96d2, 0x5db2, 0x96d8, 0x96da, 0x96dd, 0x96de, 0x96df, 0x96e9,
+ 0x96ef, 0x96f1, 0x96fa, 0x9702, 0x9703, 0x9705, 0x9709, 0x971a,
+ 0x971b, 0x971d, 0x9721, 0x9722, 0x9723, 0x9728, 0x9731, 0x9733,
+ 0x9741, 0x9743, 0x974a, 0x974e, 0x974f, 0x9755, 0x9757, 0x9758,
+ 0x975a, 0x975b, 0x9763, 0x9767, 0x976a, 0x976e, 0x9773, 0x9776,
+ 0x9777, 0x9778, 0x977b, 0x977d, 0x977f, 0x9780, 0x9789, 0x9795,
+ 0x9796, 0x9797, 0x9799, 0x979a, 0x979e, 0x979f, 0x97a2, 0x97ac,
+ 0x97ae, 0x97b1, 0x97b2, 0x97b5, 0x97b6, 0x97b8, 0x97b9, 0x97ba,
+ 0x97bc, 0x97be, 0x97bf, 0x97c1, 0x97c4, 0x97c5, 0x97c7, 0x97c9,
+ 0x97ca, 0x97cc, 0x97cd, 0x97ce, 0x97d0, 0x97d1, 0x97d4, 0x97d7,
+ 0x97d8, 0x97d9, 0x97dd, 0x97de, 0x97e0, 0x97db, 0x97e1, 0x97e4,
+ 0x97ef, 0x97f1, 0x97f4, 0x97f7, 0x97f8, 0x97fa, 0x9807, 0x980a,
+ 0x9819, 0x980d, 0x980e, 0x9814, 0x9816, 0x981c, 0x981e, 0x9820,
+ 0x9823, 0x9826, 0x982b, 0x982e, 0x982f, 0x9830, 0x9832, 0x9833,
+ 0x9835, 0x9825, 0x983e, 0x9844, 0x9847, 0x984a, 0x9851, 0x9852,
+ 0x9853, 0x9856, 0x9857, 0x9859, 0x985a, 0x9862, 0x9863, 0x9865,
+ 0x9866, 0x986a, 0x986c, 0x98ab, 0x98ad, 0x98ae, 0x98b0, 0x98b4,
+ 0x98b7, 0x98b8, 0x98ba, 0x98bb, 0x98bf, 0x98c2, 0x98c5, 0x98c8,
+ 0x98cc, 0x98e1, 0x98e3, 0x98e5, 0x98e6, 0x98e7, 0x98ea, 0x98f3,
+ 0x98f6, 0x9902, 0x9907, 0x9908, 0x9911, 0x9915, 0x9916, 0x9917,
+ 0x991a, 0x991b, 0x991c, 0x991f, 0x9922, 0x9926, 0x9927, 0x992b,
+ 0x9931, 0x9932, 0x9933, 0x9934, 0x9935, 0x9939, 0x993a, 0x993b,
+ 0x993c, 0x9940, 0x9941, 0x9946, 0x9947, 0x9948, 0x994d, 0x994e,
+ 0x9954, 0x9958, 0x9959, 0x995b, 0x995c, 0x995e, 0x995f, 0x9960,
+ 0x999b, 0x999d, 0x999f, 0x99a6, 0x99b0, 0x99b1, 0x99b2, 0x99b5,
+ 0x99b9, 0x99ba, 0x99bd, 0x99bf, 0x99c3, 0x99c9, 0x99d3, 0x99d4,
+ 0x99d9, 0x99da, 0x99dc, 0x99de, 0x99e7, 0x99ea, 0x99eb, 0x99ec,
+ 0x99f0, 0x99f4, 0x99f5, 0x99f9, 0x99fd, 0x99fe, 0x9a02, 0x9a03,
+ 0x9a04, 0x9a0b, 0x9a0c, 0x9a10, 0x9a11, 0x9a16, 0x9a1e, 0x9a20,
+ 0x9a22, 0x9a23, 0x9a24, 0x9a27, 0x9a2d, 0x9a2e, 0x9a33, 0x9a35,
+ 0x9a36, 0x9a38, 0x9a47, 0x9a41, 0x9a44, 0x9a4a, 0x9a4b, 0x9a4c,
+ 0x9a4e, 0x9a51, 0x9a54, 0x9a56, 0x9a5d, 0x9aaa, 0x9aac, 0x9aae,
+ 0x9aaf, 0x9ab2, 0x9ab4, 0x9ab5, 0x9ab6, 0x9ab9, 0x9abb, 0x9abe,
+ 0x9abf, 0x9ac1, 0x9ac3, 0x9ac6, 0x9ac8, 0x9ace, 0x9ad0, 0x9ad2,
+ 0x9ad5, 0x9ad6, 0x9ad7, 0x9adb, 0x9adc, 0x9ae0, 0x9ae4, 0x9ae5,
+ 0x9ae7, 0x9ae9, 0x9aec, 0x9af2, 0x9af3, 0x9af5, 0x9af9, 0x9afa,
+ 0x9afd, 0x9aff, 0x9b00, 0x9b01, 0x9b02, 0x9b03, 0x9b04, 0x9b05,
+ 0x9b08, 0x9b09, 0x9b0b, 0x9b0c, 0x9b0d, 0x9b0e, 0x9b10, 0x9b12,
+ 0x9b16, 0x9b19, 0x9b1b, 0x9b1c, 0x9b20, 0x9b26, 0x9b2b, 0x9b2d,
+ 0x9b33, 0x9b34, 0x9b35, 0x9b37, 0x9b39, 0x9b3a, 0x9b3d, 0x9b48,
+ 0x9b4b, 0x9b4c, 0x9b55, 0x9b56, 0x9b57, 0x9b5b, 0x9b5e, 0x9b61,
+ 0x9b63, 0x9b65, 0x9b66, 0x9b68, 0x9b6a, 0x9b6b, 0x9b6c, 0x9b6d,
+ 0x9b6e, 0x9b73, 0x9b75, 0x9b77, 0x9b78, 0x9b79, 0x9b7f, 0x9b80,
+ 0x9b84, 0x9b85, 0x9b86, 0x9b87, 0x9b89, 0x9b8a, 0x9b8b, 0x9b8d,
+ 0x9b8f, 0x9b90, 0x9b94, 0x9b9a, 0x9b9d, 0x9b9e, 0x9ba6, 0x9ba7,
+ 0x9ba9, 0x9bac, 0x9bb0, 0x9bb1, 0x9bb2, 0x9bb7, 0x9bb8, 0x9bbb,
+ 0x9bbc, 0x9bbe, 0x9bbf, 0x9bc1, 0x9bc7, 0x9bc8, 0x9bce, 0x9bd0,
+ 0x9bd7, 0x9bd8, 0x9bdd, 0x9bdf, 0x9be5, 0x9be7, 0x9bea, 0x9beb,
+ 0x9bef, 0x9bf3, 0x9bf7, 0x9bf8, 0x9bf9, 0x9bfa, 0x9bfd, 0x9bff,
+ 0x9c00, 0x9c02, 0x9c0b, 0x9c0f, 0x9c11, 0x9c16, 0x9c18, 0x9c19,
+ 0x9c1a, 0x9c1c, 0x9c1e, 0x9c22, 0x9c23, 0x9c26, 0x9c27, 0x9c28,
+ 0x9c29, 0x9c2a, 0x9c31, 0x9c35, 0x9c36, 0x9c37, 0x9c3d, 0x9c41,
+ 0x9c43, 0x9c44, 0x9c45, 0x9c49, 0x9c4a, 0x9c4e, 0x9c4f, 0x9c50,
+ 0x9c53, 0x9c54, 0x9c56, 0x9c58, 0x9c5b, 0x9c5d, 0x9c5e, 0x9c5f,
+ 0x9c63, 0x9c69, 0x9c6a, 0x9c5c, 0x9c6b, 0x9c68, 0x9c6e, 0x9c70,
+ 0x9c72, 0x9c75, 0x9c77, 0x9c7b, 0x9ce6, 0x9cf2, 0x9cf7, 0x9cf9,
+ 0x9d0b, 0x9d02, 0x9d11, 0x9d17, 0x9d18, 0x9d1c, 0x9d1d, 0x9d1e,
+ 0x9d2f, 0x9d30, 0x9d32, 0x9d33, 0x9d34, 0x9d3a, 0x9d3c, 0x9d45,
+ 0x9d3d, 0x9d42, 0x9d43, 0x9d47, 0x9d4a, 0x9d53, 0x9d54, 0x9d5f,
+ 0x9d63, 0x9d62, 0x9d65, 0x9d69, 0x9d6a, 0x9d6b, 0x9d70, 0x9d76,
+ 0x9d77, 0x9d7b, 0x9d7c, 0x9d7e, 0x9d83, 0x9d84, 0x9d86, 0x9d8a,
+ 0x9d8d, 0x9d8e, 0x9d92, 0x9d93, 0x9d95, 0x9d96, 0x9d97, 0x9d98,
+ 0x9da1, 0x9daa, 0x9dac, 0x9dae, 0x9db1, 0x9db5, 0x9db9, 0x9dbc,
+ 0x9dbf, 0x9dc3, 0x9dc7, 0x9dc9, 0x9dca, 0x9dd4, 0x9dd5, 0x9dd6,
+ 0x9dd7, 0x9dda, 0x9dde, 0x9ddf, 0x9de0, 0x9de5, 0x9de7, 0x9de9,
+ 0x9deb, 0x9dee, 0x9df0, 0x9df3, 0x9df4, 0x9dfe, 0x9e0a, 0x9e02,
+ 0x9e07, 0x9e0e, 0x9e10, 0x9e11, 0x9e12, 0x9e15, 0x9e16, 0x9e19,
+ 0x9e1c, 0x9e1d, 0x9e7a, 0x9e7b, 0x9e7c, 0x9e80, 0x9e82, 0x9e83,
+ 0x9e84, 0x9e85, 0x9e87, 0x9e8e, 0x9e8f, 0x9e96, 0x9e98, 0x9e9b,
+ 0x9e9e, 0x9ea4, 0x9ea8, 0x9eac, 0x9eae, 0x9eaf, 0x9eb0, 0x9eb3,
+ 0x9eb4, 0x9eb5, 0x9ec6, 0x9ec8, 0x9ecb, 0x9ed5, 0x9edf, 0x9ee4,
+ 0x9ee7, 0x9eec, 0x9eed, 0x9eee, 0x9ef0, 0x9ef1, 0x9ef2, 0x9ef5,
+ 0x9ef8, 0x9eff, 0x9f02, 0x9f03, 0x9f09, 0x9f0f, 0x9f10, 0x9f11,
+ 0x9f12, 0x9f14, 0x9f16, 0x9f17, 0x9f19, 0x9f1a, 0x9f1b, 0x9f1f,
+ 0x9f22, 0x9f26, 0x9f2a, 0x9f2b, 0x9f2f, 0x9f31, 0x9f32, 0x9f34,
+ 0x9f37, 0x9f39, 0x9f3a, 0x9f3c, 0x9f3d, 0x9f3f, 0x9f41, 0x9f43,
+ 0x9f44, 0x9f45, 0x9f46, 0x9f47, 0x9f53, 0x9f55, 0x9f56, 0x9f57,
+ 0x9f58, 0x9f5a, 0x9f5d, 0x9f5e, 0x9f68, 0x9f69, 0x9f6d, 0x9f6e,
+ 0x9f6f, 0x9f70, 0x9f71, 0x9f73, 0x9f75, 0x9f7a, 0x9f7d, 0x9f8f,
+ 0x9f90, 0x9f91, 0x9f92, 0x9f94, 0x9f96, 0x9f97, 0x9f9e, 0x9fa1,
+ 0x9fa2, 0x9fa3, 0x9fa5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2003, 0x3001, 0x3002, 0xff0c,
+ 0xff0e, 0x30fb, 0xff1a, 0xff1b, 0xff1f, 0xff01, 0x309b, 0x309c
+};
+
+#ifndef LUA_FF_LIB
+static const unsigned short jis_from_unicode_0[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa237, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa242, 0x0000, 0x0000, 0xa270, 0x0000, 0xa243, 0x2178,
+ 0x212f, 0xa26d, 0xa26c, 0x0000, 0x0000, 0x0000, 0xa26e, 0xa234,
+ 0x216b, 0x215e, 0x0000, 0x0000, 0x212d, 0x0000, 0x2279, 0x0000,
+ 0xa231, 0x0000, 0xa26b, 0x0000, 0x0000, 0x0000, 0x0000, 0xa244,
+ 0xaa22, 0xaa21, 0xaa24, 0xaa2a, 0xaa23, 0xaa29, 0xa921, 0xaa2e,
+ 0xaa32, 0xaa31, 0xaa34, 0xaa33, 0xaa40, 0xaa3f, 0xaa42, 0xaa41,
+ 0x0000, 0xaa50, 0xaa52, 0xaa51, 0xaa54, 0xaa58, 0xaa53, 0x215f,
+ 0xa92c, 0xaa63, 0xaa62, 0xaa65, 0xaa64, 0xaa72, 0xa930, 0xa94e,
+ 0xab22, 0xab21, 0xab24, 0xab2a, 0xab23, 0xab29, 0xa941, 0xab2e,
+ 0xab32, 0xab31, 0xab34, 0xab33, 0xab40, 0xab3f, 0xab42, 0xab41,
+ 0xa943, 0xab50, 0xab52, 0xab51, 0xab54, 0xab58, 0xab53, 0x2160,
+ 0xa94c, 0xab63, 0xab62, 0xab65, 0xab64, 0xab72, 0xa950, 0xab73
+};
+
+static const unsigned short jis_from_unicode_1[] = {
+ 0xaa27, 0xab27, 0xaa25, 0xab25, 0xaa28, 0xab28, 0xaa2b, 0xab2b,
+ 0xaa2c, 0xab2c, 0xaa2f, 0xab2f, 0xaa2d, 0xab2d, 0xaa30, 0xab30,
+ 0xa922, 0xa942, 0xaa37, 0xab37, 0x0000, 0x0000, 0xaa36, 0xab36,
+ 0xaa38, 0xab38, 0xaa35, 0xab35, 0xaa3a, 0xab3a, 0xaa3b, 0xab3b,
+ 0xaa3d, 0xab3d, 0xaa3c, 0x0000, 0xaa3e, 0xab3e, 0xa924, 0xa944,
+ 0xaa47, 0xab47, 0xaa45, 0xab45, 0x0000, 0x0000, 0xaa46, 0xab46,
+ 0xaa44, 0xa945, 0xa926, 0xa946, 0xaa48, 0xab48, 0xaa49, 0xab49,
+ 0xa947, 0xaa4a, 0xab4a, 0xaa4c, 0xab4c, 0xaa4b, 0xab4b, 0xa929,
+ 0xa949, 0xa928, 0xa948, 0xaa4d, 0xab4d, 0xaa4f, 0xab4f, 0xaa4e,
+ 0xab4e, 0xa94a, 0xa92b, 0xa94b, 0xaa57, 0xab57, 0x0000, 0x0000,
+ 0xaa56, 0xab56, 0xa92d, 0xa94d, 0xaa59, 0xab59, 0xaa5b, 0xab5b,
+ 0xaa5a, 0xab5a, 0xaa5c, 0xab5c, 0xaa5d, 0xab5d, 0xaa5f, 0xab5f,
+ 0xaa5e, 0xab5e, 0xaa61, 0xab61, 0xaa60, 0xab60, 0xa92f, 0xa94f,
+ 0xaa6c, 0xab6c, 0xaa69, 0xab69, 0xaa66, 0xab66, 0xaa6b, 0xab6b,
+ 0xaa68, 0xab68, 0xaa6a, 0xab6a, 0xaa71, 0xab71, 0xaa74, 0xab74,
+ 0xaa73, 0xaa75, 0xab75, 0xaa77, 0xab77, 0xaa76, 0xab76, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xaa26, 0xab26, 0xaa43,
+ 0xab43, 0xaa55, 0xab55, 0xaa67, 0xab67, 0xaa70, 0xab70, 0xaa6d,
+ 0xab6d, 0xaa6f, 0xab6f, 0xaa6e, 0xab6e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xab39, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_2[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa230,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa22f, 0xa232, 0xa236, 0xa235, 0x0000, 0xa233, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_3[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa238, 0xa239, 0xa661, 0x0000,
+ 0xa662, 0xa663, 0xa664, 0x0000, 0xa667, 0x0000, 0xa669, 0xa66c,
+ 0xa676, 0x2621, 0x2622, 0x2623, 0x2624, 0x2625, 0x2626, 0x2627,
+ 0x2628, 0x2629, 0x262a, 0x262b, 0x262c, 0x262d, 0x262e, 0x262f,
+ 0x2630, 0x2631, 0x0000, 0x2632, 0x2633, 0x2634, 0x2635, 0x2636,
+ 0x2637, 0x2638, 0xa665, 0xa66a, 0xa671, 0xa672, 0xa673, 0xa674,
+ 0xa67b, 0x2641, 0x2642, 0x2643, 0x2644, 0x2645, 0x2646, 0x2647,
+ 0x2648, 0x2649, 0x264a, 0x264b, 0x264c, 0x264d, 0x264e, 0x264f,
+ 0x2650, 0x2651, 0xa678, 0x2652, 0x2653, 0x2654, 0x2655, 0x2656,
+ 0x2657, 0x2658, 0xa675, 0xa67a, 0xa677, 0xa679, 0xa67c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_4[] = {
+ 0x0000, 0x2727, 0xa742, 0xa743, 0xa744, 0xa745, 0xa746, 0xa747,
+ 0xa748, 0xa749, 0xa74a, 0xa74b, 0xa74c, 0x0000, 0xa74d, 0xa74e,
+ 0x2721, 0x2722, 0x2723, 0x2724, 0x2725, 0x2726, 0x2728, 0x2729,
+ 0x272a, 0x272b, 0x272c, 0x272d, 0x272e, 0x272f, 0x2730, 0x2731,
+ 0x2732, 0x2733, 0x2734, 0x2735, 0x2736, 0x2737, 0x2738, 0x2739,
+ 0x273a, 0x273b, 0x273c, 0x273d, 0x273e, 0x273f, 0x2740, 0x2741,
+ 0x2751, 0x2752, 0x2753, 0x2754, 0x2755, 0x2756, 0x2758, 0x2759,
+ 0x275a, 0x275b, 0x275c, 0x275d, 0x275e, 0x275f, 0x2760, 0x2761,
+ 0x2762, 0x2763, 0x2764, 0x2765, 0x2766, 0x2767, 0x2768, 0x2769,
+ 0x276a, 0x276b, 0x276c, 0x276d, 0x276e, 0x276f, 0x2770, 0x2771,
+ 0x0000, 0x2757, 0xa772, 0xa773, 0xa774, 0xa775, 0xa776, 0xa777,
+ 0xa778, 0xa779, 0xa77a, 0xa77b, 0xa77c, 0x0000, 0xa77d, 0xa77e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_20[] = {
+ 0x0000, 0x0000, 0x0000, 0x2121, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x213e, 0x0000, 0x0000, 0x0000, 0x0000, 0x213d, 0x2142, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2277, 0x2278, 0x0000, 0x0000, 0x0000, 0x2145, 0x2144, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2273, 0x0000, 0x216c, 0x216d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2228, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_21[] = {
+ 0x0000, 0x0000, 0x0000, 0x216e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa271, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa26f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2272, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x222b, 0x222c, 0x222a, 0x222d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x224d, 0x0000, 0x224e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_22[] = {
+ 0x224f, 0x0000, 0x225f, 0x2250, 0x0000, 0x0000, 0x0000, 0x2260,
+ 0x223a, 0x0000, 0x0000, 0x223b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x215d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2265, 0x0000, 0x0000, 0x2267, 0x2167, 0x0000,
+ 0x225c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x224a,
+ 0x224b, 0x2241, 0x2240, 0x2269, 0x226a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2168, 0x2268, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2266, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2262, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2162, 0x2261, 0x0000, 0x0000, 0x0000, 0x0000, 0x2165, 0x2166,
+ 0x0000, 0x0000, 0x2263, 0x2264, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x223e, 0x223f, 0x0000, 0x0000, 0x223c, 0x223d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x225d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_23[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x225e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_25[] = {
+ 0x2821, 0x282c, 0x2822, 0x282d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2823, 0x0000, 0x0000, 0x282e,
+ 0x2824, 0x0000, 0x0000, 0x282f, 0x2826, 0x0000, 0x0000, 0x2831,
+ 0x2825, 0x0000, 0x0000, 0x2830, 0x2827, 0x283c, 0x0000, 0x0000,
+ 0x2837, 0x0000, 0x0000, 0x2832, 0x2829, 0x283e, 0x0000, 0x0000,
+ 0x2839, 0x0000, 0x0000, 0x2834, 0x2828, 0x0000, 0x0000, 0x2838,
+ 0x283d, 0x0000, 0x0000, 0x2833, 0x282a, 0x0000, 0x0000, 0x283a,
+ 0x283f, 0x0000, 0x0000, 0x2835, 0x282b, 0x0000, 0x0000, 0x283b,
+ 0x0000, 0x0000, 0x2840, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2836, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2223, 0x2222, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2225, 0x2224, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2227, 0x2226, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2221, 0x217e,
+ 0x0000, 0x0000, 0x0000, 0x217b, 0x0000, 0x0000, 0x217d, 0x217c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x227e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_26[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x217a, 0x2179, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x216a, 0x0000, 0x2169, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2276, 0x0000, 0x0000, 0x2275, 0x0000, 0x2274,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_30[] = {
+ 0x0000, 0x2122, 0x2123, 0x2137, 0x0000, 0x2139, 0x213a, 0x213b,
+ 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159,
+ 0x215a, 0x215b, 0x2229, 0x222e, 0x214c, 0x214d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2141, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427,
+ 0x2428, 0x2429, 0x242a, 0x242b, 0x242c, 0x242d, 0x242e, 0x242f,
+ 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437,
+ 0x2438, 0x2439, 0x243a, 0x243b, 0x243c, 0x243d, 0x243e, 0x243f,
+ 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447,
+ 0x2448, 0x2449, 0x244a, 0x244b, 0x244c, 0x244d, 0x244e, 0x244f,
+ 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457,
+ 0x2458, 0x2459, 0x245a, 0x245b, 0x245c, 0x245d, 0x245e, 0x245f,
+ 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467,
+ 0x2468, 0x2469, 0x246a, 0x246b, 0x246c, 0x246d, 0x246e, 0x246f,
+ 0x2470, 0x2471, 0x2472, 0x2473, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x212b, 0x212c, 0x2135, 0x2136, 0x0000,
+ 0x0000, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527,
+ 0x2528, 0x2529, 0x252a, 0x252b, 0x252c, 0x252d, 0x252e, 0x252f,
+ 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537,
+ 0x2538, 0x2539, 0x253a, 0x253b, 0x253c, 0x253d, 0x253e, 0x253f,
+ 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547,
+ 0x2548, 0x2549, 0x254a, 0x254b, 0x254c, 0x254d, 0x254e, 0x254f,
+ 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557,
+ 0x2558, 0x2559, 0x255a, 0x255b, 0x255c, 0x255d, 0x255e, 0x255f,
+ 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567,
+ 0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x256d, 0x256e, 0x256f,
+ 0x2570, 0x2571, 0x2572, 0x2573, 0x2574, 0x2575, 0x2576, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2126, 0x213c, 0x2133, 0x2134, 0x0000
+};
+
+static const unsigned short jis_from_unicode_4e[] = {
+ 0x306c, 0x437a, 0xb021, 0x3c37, 0xb022, 0xb023, 0x0000, 0x4b7c,
+ 0x3e66, 0x3b30, 0x3e65, 0x323c, 0xb024, 0x4954, 0x4d3f, 0x0000,
+ 0x5022, 0x312f, 0xb025, 0x0000, 0x336e, 0x5023, 0x4024, 0x5242,
+ 0x3556, 0x4a3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x3e67, 0xb026,
+ 0x0000, 0x4e3e, 0x0000, 0xb027, 0xb028, 0x0000, 0x4a42, 0x0000,
+ 0xb029, 0x0000, 0x5024, 0xb02a, 0x0000, 0x4366, 0xb02b, 0xb02c,
+ 0xb02d, 0x5025, 0x367a, 0x0000, 0x0000, 0xb02e, 0x5026, 0x0000,
+ 0x345d, 0x4330, 0x0000, 0x3c67, 0x5027, 0x0000, 0x0000, 0x5028,
+ 0xb02f, 0xb030, 0x5029, 0x4735, 0xb031, 0x3557, 0x0000, 0xb032,
+ 0x0000, 0x0000, 0x0000, 0x4737, 0x0000, 0x4663, 0x3843, 0x4b33,
+ 0x0000, 0xb033, 0x0000, 0x0000, 0x0000, 0x6949, 0x502a, 0x3e68,
+ 0x502b, 0x3235, 0xb034, 0x0000, 0xb035, 0x3665, 0x3870, 0x4c69,
+ 0x0000, 0x0000, 0x5626, 0xb036, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xb037, 0xb038, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4d70, 0x0000, 0x467d, 0xb039, 0xb03a, 0x0000, 0x0000,
+ 0x0000, 0xb03b, 0x0000, 0x0000, 0x0000, 0x0000, 0x3425, 0xb03c,
+ 0x3535, 0x0000, 0x502c, 0x0000, 0x0000, 0x502d, 0x4e3b, 0x0000,
+ 0x4d3d, 0x4168, 0x502f, 0x3b76, 0x4673, 0xb03d, 0x5032, 0x0000,
+ 0x0000, 0x313e, 0x385f, 0x0000, 0x385e, 0x3066, 0xb03e, 0xb03f,
+ 0x4f4b, 0x4f4a, 0x0000, 0x3a33, 0x3021, 0xb040, 0x5033, 0x5034,
+ 0x5035, 0x4b34, 0x5036, 0x0000, 0x3872, 0x3067, 0x4b72, 0x0000,
+ 0x357c, 0x0000, 0x0000, 0x357d, 0x357e, 0x4462, 0x4e3c, 0xb041,
+ 0x5037, 0x0000, 0x0000, 0x5038, 0x0000, 0x0000, 0x5039, 0x0000,
+ 0x0000, 0xb042, 0x3f4d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d3a, 0x3f4e, 0x503e, 0xb043, 0x503c, 0x0000, 0x503d, 0x3558,
+ 0x0000, 0x0000, 0x3a23, 0x3270, 0x0000, 0x503b, 0x503a, 0x4a29,
+ 0xb044, 0x0000, 0x0000, 0x0000, 0x3b46, 0x3b45, 0x423e, 0x503f,
+ 0x4955, 0x4067, 0xb045, 0xb046, 0x0000, 0x2138, 0x5040, 0x5042,
+ 0xb047, 0xb048, 0xb049, 0x4265, 0x4e61, 0x304a, 0x0000, 0x0000,
+ 0xb04a, 0x0000, 0x0000, 0x0000, 0x0000, 0x5041, 0x323e, 0xb04b,
+ 0x3644, 0xb04c, 0x4367, 0xb04d, 0x0000, 0xb04e, 0x376f, 0x5043,
+ 0x0000, 0x0000, 0x0000, 0x4724, 0x0000, 0xb04f, 0xb050, 0xb051
+};
+
+static const unsigned short jis_from_unicode_4f[] = {
+ 0xb052, 0x346b, 0xb053, 0xb054, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xb055, 0x5044, 0x304b, 0xb056, 0xb057, 0x3860, 0x346c, 0x497a,
+ 0x4832, 0x3559, 0xb058, 0x0000, 0x0000, 0xb059, 0xb05a, 0xb05b,
+ 0x0000, 0xb05c, 0x3271, 0x0000, 0x5067, 0x4541, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb05d, 0x476c,
+ 0x5046, 0xb05e, 0x0000, 0xb060, 0x483c, 0xb061, 0x4e62, 0xb062,
+ 0x3f2d, 0xb063, 0x3b47, 0xb064, 0x3b77, 0x3240, 0xb065, 0x0000,
+ 0xb066, 0x0000, 0xb067, 0x4451, 0x0000, 0x0000, 0x4322, 0x504a,
+ 0xb068, 0xb069, 0x0000, 0xb06a, 0xb06b, 0x304c, 0x4463, 0x3d3b,
+ 0x3a34, 0x4d24, 0xb06c, 0x424e, 0xb06d, 0x323f, 0xb06e, 0x5049,
+ 0xb06f, 0x4d3e, 0x5045, 0x5047, 0x3a6e, 0x5048, 0x5524, 0xb070,
+ 0xb05f, 0x0000, 0x0000, 0xb071, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5050, 0xb072, 0x0000, 0xb073, 0x0000, 0xb074, 0x5053,
+ 0x5051, 0xb075, 0x0000, 0x3242, 0x0000, 0x4a3b, 0x504b, 0xb076,
+ 0xb077, 0xb078, 0xb079, 0x504f, 0x3873, 0xb07a, 0xb07b, 0x3b48,
+ 0x0000, 0xb07c, 0xb07d, 0x3426, 0xb07e, 0xb121, 0x5054, 0x0000,
+ 0x504c, 0xb122, 0xb123, 0x4e63, 0xb124, 0x3b78, 0xb125, 0x504d,
+ 0xb126, 0x5052, 0xb127, 0xb128, 0xb129, 0x0000, 0x5055, 0xb12a,
+ 0x504e, 0xb12b, 0xb12c, 0x3621, 0x0000, 0x304d, 0xb12d, 0xb12e,
+ 0x3622, 0x3241, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5525, 0x0000, 0x4b79, 0x496e, 0x3874,
+ 0x0000, 0x0000, 0xb12f, 0x0000, 0x0000, 0x3f2f, 0x4e37, 0xb130,
+ 0x0000, 0xb131, 0x0000, 0xb132, 0xb133, 0xb134, 0xb135, 0x4a58,
+ 0xb136, 0xb137, 0x3738, 0x4225, 0x3264, 0xb138, 0xb139, 0x0000,
+ 0xb13a, 0xb13b, 0x3d53, 0xb13c, 0xb13d, 0xb13e, 0x5059, 0xb13f,
+ 0x505e, 0x505c, 0xb140, 0x0000, 0x5057, 0x0000, 0x0000, 0x422f,
+ 0x505a, 0x0000, 0x505d, 0x505b, 0xb141, 0x4a5d, 0x0000, 0x5058,
+ 0xb142, 0x3f2e, 0xb143, 0x4b73, 0x505f, 0x5060, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3d24, 0x506d,
+ 0xb144, 0x0000, 0xb145, 0x4750, 0x0000, 0x4936, 0x5068, 0x0000,
+ 0x4a70, 0x0000, 0x3236, 0x0000, 0xb146, 0xb147, 0x506c, 0xb148
+};
+
+static const unsigned short jis_from_unicode_50[] = {
+ 0xb149, 0xb14a, 0x0000, 0x0000, 0xb14b, 0x5066, 0x506f, 0xb14c,
+ 0x0000, 0x4152, 0xb14d, 0x3844, 0xb14e, 0x475c, 0xb14f, 0x6047,
+ 0xb150, 0x506e, 0x455d, 0xb151, 0x5063, 0x0000, 0x3876, 0xb152,
+ 0xb153, 0x3875, 0x5061, 0xb154, 0xb155, 0xb156, 0xb157, 0x3c5a,
+ 0x0000, 0x5069, 0xb158, 0x4a6f, 0x434d, 0x5065, 0x3771, 0xb159,
+ 0x5062, 0x506a, 0x5064, 0x4e51, 0x506b, 0x4f41, 0xb15a, 0x0000,
+ 0xb15b, 0x0000, 0xb15c, 0xb15d, 0x0000, 0xb15e, 0x3666, 0x0000,
+ 0x0000, 0x3770, 0x0000, 0xb176, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xb15f, 0xb160, 0xb161, 0x5070, 0x0000, 0xb162, 0xb163, 0x5071,
+ 0x5075, 0x304e, 0xb164, 0x0000, 0xb165, 0x0000, 0xb166, 0x4a50,
+ 0x5074, 0xb167, 0xb168, 0xb169, 0x0000, 0x5073, 0x5077, 0xb16a,
+ 0x0000, 0xb16b, 0x5076, 0x0000, 0x4464, 0x0000, 0x0000, 0xb16c,
+ 0xb16d, 0x0000, 0xb16e, 0xb16f, 0x0000, 0x3772, 0xb170, 0xb171,
+ 0x0000, 0x0000, 0xb172, 0x0000, 0x5078, 0xb173, 0x0000, 0x0000,
+ 0xb174, 0xb175, 0x3c45, 0x0000, 0x4226, 0x4465, 0x3676, 0x0000,
+ 0x5079, 0x0000, 0x0000, 0x0000, 0x0000, 0x3536, 0x0000, 0x0000,
+ 0x507a, 0xb177, 0x0000, 0xb178, 0xb179, 0x507c, 0xb17a, 0x0000,
+ 0x0000, 0x0000, 0xb17b, 0x0000, 0x0000, 0x4b35, 0xb17c, 0xb17d,
+ 0xb17e, 0x3766, 0xb221, 0xb222, 0xb223, 0x0000, 0xb224, 0x0000,
+ 0x3b31, 0x4877, 0x507b, 0xb225, 0xb226, 0x0000, 0xb227, 0xb228,
+ 0xb229, 0xb22a, 0xb22b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xb22c, 0x0000, 0x3a45, 0x4d43, 0x0000, 0xb22d,
+ 0xb22e, 0x0000, 0x507e, 0x5123, 0x507d, 0x3a44, 0x0000, 0x3d7d,
+ 0x0000, 0xb22f, 0xb230, 0x0000, 0x0000, 0xb231, 0x3739, 0x0000,
+ 0xb232, 0x0000, 0x5124, 0xb233, 0xb234, 0x364f, 0x0000, 0xb235,
+ 0x0000, 0x5121, 0x5122, 0x0000, 0xb236, 0x462f, 0xb237, 0x417c,
+ 0xb238, 0x3623, 0x0000, 0xb239, 0xb23a, 0x4b4d, 0x5125, 0x0000,
+ 0xb23b, 0x0000, 0x4e3d, 0x0000, 0xb23c, 0xb23d, 0x5126, 0xb23e,
+ 0x0000, 0x0000, 0xb23f, 0x5129, 0xb240, 0x5127, 0xb241, 0x414e,
+ 0xb242, 0xb243, 0x0000, 0x0000, 0x0000, 0x5128, 0x512a, 0xb244,
+ 0x0000, 0xb245, 0xb251, 0x0000, 0x0000, 0x512c, 0xb246, 0x0000,
+ 0x0000, 0x512b, 0xb247, 0x4a48, 0x0000, 0x0000, 0xb248, 0x0000
+};
+
+static const unsigned short jis_from_unicode_51[] = {
+ 0x3537, 0x512e, 0x512f, 0xb249, 0x322f, 0x0000, 0xb24a, 0xb24b,
+ 0xb24c, 0x512d, 0x0000, 0xb24d, 0xb24e, 0xb24f, 0xb250, 0x0000,
+ 0xb252, 0x0000, 0x3c74, 0x0000, 0x5132, 0x5131, 0x5130, 0xb253,
+ 0x5056, 0xb254, 0x5133, 0xb255, 0xb256, 0xb257, 0xb258, 0x3d7e,
+ 0x0000, 0x5134, 0x0000, 0xb259, 0x0000, 0x0000, 0x0000, 0xb25a,
+ 0xb25b, 0x0000, 0x4d25, 0x0000, 0xb25c, 0xb25d, 0x0000, 0xb25e,
+ 0x0000, 0xb25f, 0x4c59, 0xb260, 0xb261, 0xb262, 0x0000, 0x5136,
+ 0xb263, 0xb264, 0x5135, 0x5138, 0x5137, 0x0000, 0x0000, 0x5139,
+ 0x513a, 0x3074, 0xb265, 0x3835, 0x373b, 0x3d3c, 0x437b, 0x3624,
+ 0x4068, 0x3877, 0xb266, 0x396e, 0x513c, 0x4c48, 0x4546, 0xb267,
+ 0x3b79, 0x0000, 0x513b, 0xb268, 0x513d, 0xb269, 0x0000, 0xb26a,
+ 0xb26b, 0x0000, 0x455e, 0x0000, 0x3375, 0x0000, 0x0000, 0xb26c,
+ 0x0000, 0x0000, 0x513e, 0x0000, 0xb26d, 0x467e, 0xb26e, 0x0000,
+ 0x4134, 0x5140, 0x5141, 0x482c, 0x3878, 0x4f3b, 0x5142, 0x0000,
+ 0x0000, 0x3626, 0x0000, 0x0000, 0x0000, 0x4a3c, 0x4236, 0x3671,
+ 0x4535, 0x0000, 0x0000, 0x0000, 0x3773, 0x0000, 0xb26f, 0x0000,
+ 0x5143, 0x0000, 0x5144, 0xb270, 0xb271, 0x4662, 0x315f, 0x0000,
+ 0x0000, 0x5147, 0x3a7d, 0xb272, 0x5146, 0x3a46, 0xb273, 0x5148,
+ 0x666e, 0x5149, 0x4b41, 0x514a, 0x0000, 0x514b, 0x514c, 0x3e69,
+ 0xb274, 0x3c4c, 0x0000, 0x0000, 0x0000, 0xb275, 0x0000, 0x0000,
+ 0x3427, 0xb276, 0x514f, 0xb277, 0x514d, 0x4c3d, 0x514e, 0x0000,
+ 0x495a, 0x5150, 0x5151, 0x5152, 0x455f, 0xb278, 0x0000, 0x0000,
+ 0x5156, 0x5154, 0x5155, 0x5153, 0x3a63, 0x5157, 0x4c6a, 0x4e64,
+ 0xb279, 0x0000, 0xb27a, 0x0000, 0xb27b, 0x5158, 0xb27c, 0xb27d,
+ 0x0000, 0x0000, 0xb27e, 0x0000, 0x4028, 0x5159, 0x3d5a, 0x0000,
+ 0xb321, 0x515a, 0x0000, 0x437c, 0x4e3f, 0x4560, 0x0000, 0xb322,
+ 0x0000, 0xb323, 0xb324, 0xb325, 0x0000, 0xb326, 0x5245, 0x0000,
+ 0xb327, 0x0000, 0x0000, 0x515b, 0x7425, 0x3645, 0xb328, 0x0000,
+ 0x515c, 0x4b5e, 0xb329, 0x0000, 0x0000, 0xb32a, 0x3d68, 0x427c,
+ 0x0000, 0x515e, 0x4664, 0x0000, 0x0000, 0x515f, 0xb32b, 0x0000,
+ 0x5160, 0x332e, 0xb32c, 0xb32d, 0xb32e, 0x5161, 0x3627, 0xb32f,
+ 0x464c, 0x317a, 0x3d50, 0x0000, 0x0000, 0x4821, 0x5162, 0x0000
+};
+
+static const unsigned short jis_from_unicode_52[] = {
+ 0x4561, 0xb330, 0xb331, 0x3f4f, 0x5163, 0xb332, 0x4a2c, 0x405a,
+ 0x3422, 0x0000, 0x3429, 0x5164, 0x0000, 0x0000, 0x5166, 0x0000,
+ 0x0000, 0x373a, 0xb333, 0xb334, 0x5165, 0xb335, 0xb336, 0x4e73,
+ 0xb337, 0x0000, 0x0000, 0x0000, 0x0000, 0x3d69, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xb338, 0x0000, 0x483d, 0x4a4c, 0x0000, 0x5167,
+ 0xb339, 0x4d78, 0x5168, 0x0000, 0x0000, 0x0000, 0x5169, 0x0000,
+ 0x457e, 0xb33a, 0xb33b, 0x516a, 0x0000, 0xb33c, 0x4029, 0x3a7e,
+ 0x3774, 0x516b, 0x3b49, 0x396f, 0xb33d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4466, 0x516d, 0xb33e, 0x0000, 0x4227,
+ 0x0000, 0xb33f, 0x3a6f, 0x516e, 0x516f, 0x4130, 0x0000, 0x516c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5171, 0xb340, 0x4b36, 0xb341,
+ 0xb342, 0x0000, 0xb343, 0x3964, 0xb344, 0x0000, 0x5170, 0xb345,
+ 0xb346, 0xb347, 0x0000, 0x3775, 0x3a5e, 0x476d, 0xb348, 0x0000,
+ 0x0000, 0x5174, 0x5172, 0x0000, 0x0000, 0x0000, 0xb349, 0x497b,
+ 0x3e6a, 0x517b, 0x3364, 0x5175, 0x5173, 0x414f, 0x0000, 0xb34a,
+ 0xb34b, 0xb34c, 0x0000, 0x0000, 0x0000, 0x5177, 0x0000, 0x5176,
+ 0xb34d, 0x0000, 0xb34e, 0x3344, 0x0000, 0xb34f, 0x0000, 0x3760,
+ 0x517c, 0x4e2d, 0xb350, 0x0000, 0xb351, 0x5178, 0x0000, 0x0000,
+ 0x0000, 0x517d, 0x517a, 0xb352, 0x5179, 0xb353, 0xb354, 0xb355,
+ 0xb356, 0x0000, 0xb357, 0x4e4f, 0xb358, 0x0000, 0x0000, 0x3879,
+ 0x3243, 0x0000, 0x0000, 0x4e74, 0xb359, 0xb35a, 0xb35b, 0xb35c,
+ 0x0000, 0x3d75, 0x4558, 0x3965, 0x5222, 0x5223, 0x0000, 0xb35d,
+ 0xb35e, 0x4e65, 0x0000, 0x0000, 0x4f2b, 0x5225, 0xb35f, 0xb360,
+ 0xb361, 0x387a, 0xb362, 0xb363, 0x5224, 0xb364, 0x332f, 0x0000,
+ 0xb365, 0x5226, 0x0000, 0x4b56, 0xb366, 0x443c, 0xb367, 0x4d26,
+ 0xb368, 0x4a59, 0x0000, 0x0000, 0xb369, 0x5227, 0x0000, 0xb36a,
+ 0x0000, 0xb36b, 0x7055, 0x0000, 0xb36c, 0x4630, 0xb36d, 0x5228,
+ 0x342a, 0x4c33, 0x0000, 0xb36e, 0xb36f, 0x3e21, 0x5229, 0x4a67,
+ 0x522d, 0xb370, 0x402a, 0x522a, 0x3650, 0xb371, 0x522b, 0x342b,
+ 0xb372, 0xb373, 0xb374, 0x0000, 0xb375, 0x0000, 0x0000, 0x0000,
+ 0xb376, 0xb377, 0x372e, 0x522e, 0xb378, 0x522f, 0xb379, 0xb37a,
+ 0x5230, 0x5231, 0x3c5b, 0x0000, 0x0000, 0x0000, 0x387b, 0x4c5e
+};
+
+static const unsigned short jis_from_unicode_53[] = {
+ 0xb37b, 0x4c68, 0x4677, 0xb37c, 0x0000, 0x4a71, 0x5232, 0x0000,
+ 0x5233, 0x0000, 0xb37d, 0xb37e, 0xb421, 0x5235, 0x0000, 0x5237,
+ 0x5236, 0xb422, 0x0000, 0xb423, 0x0000, 0x5238, 0x323d, 0x4b4c,
+ 0xb424, 0x3a7c, 0x5239, 0xb425, 0xb426, 0x4159, 0xb427, 0xb428,
+ 0x3e22, 0x3629, 0x0000, 0x523a, 0x0000, 0xb429, 0x0000, 0xb42a,
+ 0xb42b, 0xb42c, 0x485b, 0xb42d, 0xb42e, 0xb42f, 0x0000, 0x523b,
+ 0xb430, 0x523c, 0xb431, 0x523d, 0x0000, 0xb432, 0x0000, 0x0000,
+ 0x523e, 0x4924, 0x3668, 0x3065, 0xb433, 0xb434, 0xb435, 0x463f,
+ 0x523f, 0x3d3d, 0xb436, 0x4069, 0x0000, 0x5241, 0x5240, 0x3e23,
+ 0x3861, 0x5243, 0x483e, 0xb438, 0xb437, 0x5244, 0x0000, 0x0000,
+ 0x0000, 0x485c, 0x4234, 0x426e, 0x3628, 0x0000, 0x0000, 0x466e,
+ 0x4331, 0xb439, 0x476e, 0xb43a, 0x4b4e, 0x0000, 0x5246, 0x0000,
+ 0x406a, 0xb43b, 0x0000, 0xb43c, 0x0000, 0xb43d, 0x3735, 0x0000,
+ 0x0000, 0x5247, 0x0000, 0x0000, 0xb43e, 0xb43f, 0x5248, 0x312c,
+ 0x3075, 0x346d, 0xb440, 0x4228, 0x3551, 0x4d71, 0x0000, 0x524b,
+ 0x3237, 0xb441, 0x0000, 0x524a, 0x0000, 0x0000, 0xb442, 0x362a,
+ 0x0000, 0x0000, 0x524c, 0xb443, 0x4c71, 0x0000, 0x0000, 0xb444,
+ 0xb445, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb446, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xb447, 0xb448, 0x0000, 0x524d, 0x0000,
+ 0x4e52, 0xb449, 0x387c, 0x0000, 0x0000, 0xb44a, 0x0000, 0x3836,
+ 0x524e, 0xb44b, 0x0000, 0x0000, 0xb44c, 0x5250, 0x524f, 0x0000,
+ 0x3f5f, 0x3139, 0xb44d, 0xb44e, 0x0000, 0x315e, 0x5251, 0xb44f,
+ 0x5252, 0x0000, 0xb450, 0x3837, 0xb451, 0xb452, 0x5253, 0xb453,
+ 0xb454, 0x0000, 0xb455, 0x356e, 0x0000, 0xb456, 0x0000, 0x0000,
+ 0xb457, 0x0000, 0x3b32, 0x5254, 0x0000, 0xb458, 0x0000, 0x0000,
+ 0x4b74, 0x3a35, 0x355a, 0x4d27, 0x4150, 0x483f, 0x3c7d, 0xb459,
+ 0x0000, 0x0000, 0xb45a, 0xb45b, 0x3d47, 0xb45c, 0x3c68, 0x3c75,
+ 0x0000, 0x3d76, 0xb45d, 0x4840, 0x0000, 0xb45e, 0xb45f, 0x5257,
+ 0xb460, 0x3143, 0x4151, 0x387d, 0x3845, 0x3667, 0xb461, 0xb462,
+ 0x525b, 0x4321, 0x427e, 0x362b, 0x3e24, 0x525c, 0x525a, 0x3244,
+ 0x4266, 0x3c38, 0x3b4b, 0x3126, 0x0000, 0xb463, 0x3370, 0x3966,
+ 0x3b4a, 0x0000, 0x525d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_54[] = {
+ 0x0000, 0x525e, 0xb464, 0x3549, 0x3346, 0x0000, 0x0000, 0x0000,
+ 0x3967, 0x3548, 0x445f, 0x3125, 0x4631, 0x4c3e, 0x3921, 0x4d79,
+ 0x4547, 0x387e, 0x0000, 0xb465, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xb466, 0x372f, 0x0000, 0x5267, 0x0000, 0x3663,
+ 0x4b4a, 0xb467, 0x0000, 0x0000, 0x0000, 0x0000, 0x485d, 0xb468,
+ 0xb469, 0x5266, 0xb46a, 0x345e, 0x5261, 0x5262, 0x5264, 0xb46b,
+ 0x0000, 0xb46c, 0x0000, 0x0000, 0xb46d, 0xb46e, 0x5265, 0x0000,
+ 0x355b, 0x3f61, 0x0000, 0x4a2d, 0x5263, 0x525f, 0x3863, 0x0000,
+ 0x5260, 0x0000, 0x4f24, 0xb46f, 0xb470, 0x0000, 0x4a72, 0xb471,
+ 0x4468, 0x3862, 0x3970, 0x0000, 0x0000, 0xb472, 0x5268, 0xb473,
+ 0x0000, 0x465d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb474, 0x526c,
+ 0x0000, 0x0000, 0xb475, 0x0000, 0xb476, 0x0000, 0xb477, 0xb478,
+ 0x3c7e, 0xb479, 0x3c76, 0xb47a, 0x0000, 0xb47b, 0xb47c, 0x0000,
+ 0x526f, 0x526d, 0x0000, 0x4c23, 0xb47d, 0x526a, 0x5273, 0x526e,
+ 0x0000, 0x0000, 0x0000, 0x5271, 0x3846, 0x4c3f, 0x0000, 0xb47e,
+ 0x5272, 0xb521, 0x0000, 0xb522, 0x5274, 0xb523, 0x5276, 0x0000,
+ 0xb524, 0xb525, 0x0000, 0x3a70, 0x4f42, 0xb526, 0x526b, 0x5269,
+ 0x5275, 0xb527, 0x5270, 0x0000, 0x0000, 0xb528, 0xb529, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xb52a, 0x0000, 0x0000, 0xb52b,
+ 0x0000, 0xb52c, 0x5278, 0x0000, 0x5323, 0x527a, 0xb52d, 0xb52e,
+ 0x527e, 0xb52f, 0xb530, 0x5321, 0x527b, 0xb531, 0xb532, 0x533e,
+ 0x0000, 0xb533, 0x3a69, 0x3331, 0x0000, 0x0000, 0x0000, 0xb534,
+ 0x5279, 0xb535, 0xb536, 0xb537, 0x5325, 0x3076, 0x5324, 0xb538,
+ 0x3025, 0x494a, 0x5322, 0x0000, 0x527c, 0x0000, 0xb539, 0x5277,
+ 0x527d, 0x3a48, 0xb53a, 0x0000, 0x0000, 0xb53b, 0xb53c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5326, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xb53d, 0x3077, 0x532f, 0x0000, 0x0000, 0x5327, 0x5328, 0x0000,
+ 0x3e25, 0x4b69, 0xb53e, 0x0000, 0xb53f, 0x532d, 0x532c, 0xb540,
+ 0x0000, 0x0000, 0x452f, 0x0000, 0x0000, 0x0000, 0xb541, 0x0000,
+ 0x0000, 0x0000, 0x532e, 0x0000, 0xb542, 0x532b, 0xb543, 0xb544
+};
+
+static const unsigned short jis_from_unicode_55[] = {
+ 0xb545, 0xb546, 0x0000, 0x0000, 0x3134, 0xb547, 0x3a36, 0x3f30,
+ 0xb548, 0xb549, 0x0000, 0x0000, 0xb54a, 0xb54b, 0xb54c, 0x5329,
+ 0x4562, 0x0000, 0x0000, 0x0000, 0x532a, 0xb54d, 0x3022, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xb54e, 0xb54f, 0x0000, 0x0000, 0x5334, 0x4d23,
+ 0x0000, 0x3e27, 0xb550, 0x533a, 0x0000, 0xb551, 0xb552, 0x0000,
+ 0x5339, 0x5330, 0x0000, 0xb553, 0xb554, 0xb555, 0x4243, 0x0000,
+ 0x5331, 0xb556, 0x0000, 0x0000, 0x426f, 0x5336, 0x3e26, 0xb557,
+ 0x0000, 0xb558, 0xb559, 0x0000, 0x5333, 0xb55a, 0x0000, 0x4c64,
+ 0xb55b, 0xb55c, 0x0000, 0x373c, 0x0000, 0x0000, 0x5337, 0x5338,
+ 0xb55d, 0x0000, 0xb55e, 0xb55f, 0x5335, 0x533b, 0xb560, 0x0000,
+ 0xb561, 0xb562, 0x0000, 0x5332, 0xb563, 0x0000, 0xb564, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5341, 0x5346, 0x0000, 0x5342, 0xb565,
+ 0x533d, 0xb566, 0xb567, 0x5347, 0x4131, 0x0000, 0xb568, 0x5349,
+ 0xb569, 0x3922, 0x533f, 0x437d, 0x0000, 0x0000, 0xb56a, 0xb56b,
+ 0x0000, 0xb56c, 0xb56d, 0xb56e, 0xb56f, 0x0000, 0x0000, 0xb570,
+ 0x5343, 0x533c, 0x342d, 0x0000, 0x346e, 0x3365, 0x5344, 0x5340,
+ 0x0000, 0x0000, 0x0000, 0xb571, 0xb572, 0x0000, 0x0000, 0x3776,
+ 0x534a, 0x5348, 0x4153, 0x354a, 0x362c, 0xb573, 0x5345, 0x0000,
+ 0x3674, 0x0000, 0xb574, 0x0000, 0x0000, 0x0000, 0x3144, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb575,
+ 0x0000, 0xb576, 0x0000, 0xb577, 0x534e, 0x534c, 0xb578, 0x5427,
+ 0x0000, 0xb579, 0x0000, 0xb57a, 0xb57b, 0x0000, 0xb57c, 0x0000,
+ 0x0000, 0xb57d, 0xb57e, 0xb621, 0x5351, 0x0000, 0x0000, 0xb622,
+ 0xb623, 0x0000, 0x534b, 0xb624, 0x534f, 0x0000, 0xb625, 0x534d,
+ 0x0000, 0x0000, 0xb626, 0x3b4c, 0x5350, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb627, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb628, 0x5353,
+ 0x0000, 0x5358, 0x0000, 0x0000, 0x0000, 0x5356, 0x5355, 0xb629
+};
+
+static const unsigned short jis_from_unicode_56[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb62a, 0x4332, 0x0000,
+ 0xb62b, 0x3245, 0xb62c, 0x0000, 0x0000, 0xb62d, 0xb62e, 0xb62f,
+ 0xb630, 0xb631, 0xb632, 0x0000, 0x5352, 0x0000, 0x5354, 0x3e28,
+ 0x3133, 0xb633, 0x0000, 0x5357, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x325e, 0x0000, 0x0000, 0xb634, 0x0000, 0x0000, 0x5362,
+ 0xb635, 0x3e7c, 0x535e, 0xb636, 0x535c, 0xb637, 0x535d, 0xb638,
+ 0x535f, 0xb639, 0x0000, 0xb63a, 0xb63b, 0xb63c, 0x0000, 0xb63d,
+ 0xb63e, 0xb63f, 0x313d, 0xb640, 0xb641, 0x0000, 0xb642, 0x0000,
+ 0x0000, 0xb643, 0x0000, 0xb644, 0x4139, 0xb645, 0x5359, 0xb646,
+ 0x535a, 0x0000, 0x0000, 0x0000, 0xb647, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x337a, 0x0000, 0x0000, 0xb648, 0x0000,
+ 0xb649, 0xb64a, 0xb64b, 0xb64c, 0x5361, 0x0000, 0xb64d, 0x0000,
+ 0x346f, 0xb64e, 0x5364, 0x5360, 0x5363, 0xb64f, 0x0000, 0xb650,
+ 0x0000, 0xb651, 0xb652, 0x0000, 0x4a2e, 0xb653, 0x0000, 0x0000,
+ 0x4655, 0x0000, 0x4838, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5366, 0x0000, 0x0000, 0x0000, 0xb654, 0xb655, 0x5365, 0x3345,
+ 0xb656, 0x0000, 0x5367, 0xb657, 0xb658, 0x0000, 0x0000, 0x536a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5369, 0xb659, 0x0000, 0x0000,
+ 0x0000, 0xb65a, 0xb65b, 0x0000, 0x0000, 0xb65c, 0xb65d, 0xb65e,
+ 0x5368, 0x0000, 0x4739, 0x0000, 0x0000, 0x536b, 0xb65f, 0xb660,
+ 0xb661, 0xb662, 0x0000, 0xb663, 0xb664, 0xb665, 0x536c, 0x0000,
+ 0x0000, 0xb666, 0x0000, 0xb667, 0x536e, 0x0000, 0x536d, 0xb668,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5370, 0x0000, 0xb669, 0x0000,
+ 0x5373, 0x5371, 0x536f, 0x5372, 0x0000, 0xb66a, 0x0000, 0x0000,
+ 0x5374, 0xb66b, 0xb66c, 0xb66d, 0xb670, 0xb671, 0x5375, 0xb66e,
+ 0xb66f, 0x5376, 0x0000, 0x5377, 0x0000, 0x0000, 0x0000, 0x5378,
+ 0x5145, 0xb672, 0x3c7c, 0x3b4d, 0xb673, 0xb674, 0x3273, 0xb675,
+ 0x3078, 0xb676, 0x0000, 0x4344, 0xb677, 0xb678, 0xb679, 0xb67a,
+ 0xb67b, 0x0000, 0x0000, 0xb67d, 0x0000, 0xb67e, 0x5379, 0x0000,
+ 0x3a24, 0xb67c, 0x304f, 0x3f5e, 0x0000, 0x0000, 0xb721, 0xb722,
+ 0x0000, 0x537a, 0x3847, 0x0000, 0x0000, 0x3971, 0x0000, 0x537c
+};
+
+static const unsigned short jis_from_unicode_57[] = {
+ 0x537b, 0xb723, 0xb724, 0x4a60, 0x537d, 0x0000, 0x0000, 0xb725,
+ 0x5421, 0x537e, 0xb726, 0x5422, 0xb727, 0x5423, 0x0000, 0x3777,
+ 0x0000, 0xb728, 0x3160, 0x5424, 0x0000, 0xb729, 0x5426, 0x0000,
+ 0x5425, 0x0000, 0xb72a, 0xb72b, 0x5428, 0xb72c, 0x0000, 0x455a,
+ 0xb72d, 0x0000, 0xb72e, 0xb72f, 0xb730, 0xb731, 0x5429, 0x3035,
+ 0x3a5f, 0xb732, 0xb733, 0x0000, 0xb734, 0x373d, 0xb735, 0xb736,
+ 0x434f, 0x0000, 0x0000, 0xb737, 0xb738, 0x0000, 0x0000, 0x542a,
+ 0x542b, 0x0000, 0x0000, 0x542d, 0x0000, 0xb739, 0xb73a, 0xb73b,
+ 0x542e, 0x0000, 0x3a64, 0x0000, 0x0000, 0xb73c, 0xb73d, 0x3651,
+ 0x0000, 0x0000, 0x4b37, 0x0000, 0xb73e, 0xb73f, 0x542c, 0x542f,
+ 0x3a41, 0x3923, 0xb740, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5433, 0xb741, 0x0000, 0x3a25, 0xb742, 0x4333, 0xb743,
+ 0xb744, 0x5430, 0x445a, 0xb745, 0x0000, 0xb746, 0xb747, 0xb748,
+ 0xb749, 0xb74a, 0x0000, 0xb74b, 0xb74c, 0xb74d, 0x0000, 0xb74e,
+ 0x0000, 0xb74f, 0xb750, 0xb751, 0xb752, 0x0000, 0xb753, 0x5434,
+ 0x0000, 0xb754, 0x3f62, 0xb755, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5432, 0x5435, 0x0000, 0x373f, 0xb756, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5436, 0xb757, 0xb760, 0x0000, 0xb758,
+ 0x0000, 0xb759, 0xb75a, 0x0000, 0xb75b, 0xb75c, 0xb75d, 0xb75e,
+ 0x5437, 0xb75f, 0x3924, 0x3340, 0x5439, 0x0000, 0x0000, 0xb761,
+ 0xb762, 0xb763, 0x543a, 0x0000, 0xb764, 0x0000, 0x0000, 0x0000,
+ 0x543b, 0x0000, 0x0000, 0x5438, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xb765, 0x0000, 0x0000, 0x0000, 0x0000, 0xb766, 0x0000, 0x0000,
+ 0x5431, 0x0000, 0x0000, 0x543c, 0x0000, 0x0000, 0x543d, 0xb767,
+ 0xb768, 0x0000, 0x0000, 0x4b64, 0xb769, 0x0000, 0x3e6b, 0xb76a,
+ 0x0000, 0x0000, 0x543f, 0x5440, 0x543e, 0xb76b, 0x5442, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4738, 0xb76c, 0xb76d, 0x3068,
+ 0x4956, 0xb77e, 0x0000, 0x5443, 0xb76e, 0x0000, 0xb76f, 0xb770,
+ 0x0000, 0xb771, 0x0000, 0x0000, 0x0000, 0xb772, 0x0000, 0x0000,
+ 0xb773, 0x0000, 0x0000, 0x0000, 0x3e7d, 0xb774, 0xb775, 0x3c39,
+ 0xb776, 0x475d, 0x3470, 0x0000, 0x3a6b, 0xb777, 0xb778, 0xb779
+};
+
+static const unsigned short jis_from_unicode_58[] = {
+ 0x4b59, 0x0000, 0x4632, 0xb77a, 0xb77b, 0x3778, 0x424f, 0x0000,
+ 0xb77c, 0xb77d, 0x5441, 0x5444, 0xb821, 0xb822, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4244, 0x0000, 0x0000,
+ 0x0000, 0x5445, 0x0000, 0xb823, 0x0000, 0x5446, 0xb824, 0xb825,
+ 0xb826, 0x5448, 0x0000, 0x0000, 0x4469, 0x0000, 0xb827, 0xb828,
+ 0x0000, 0x0000, 0x342e, 0x0000, 0x0000, 0xb829, 0x0000, 0x7421,
+ 0x3161, 0x4a73, 0xb82a, 0x0000, 0x3e6c, 0x4548, 0x0000, 0x0000,
+ 0x0000, 0xb82b, 0x3a66, 0x0000, 0x0000, 0x544e, 0x0000, 0xb82c,
+ 0x4a3d, 0x4e5d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb82d, 0x3274, 0x544a, 0xb82e, 0xb82f, 0x0000, 0xb830,
+ 0xb831, 0x413a, 0x544d, 0x0000, 0x4563, 0xb832, 0x0000, 0x4549,
+ 0x4564, 0x4839, 0x444d, 0x0000, 0x0000, 0x0000, 0x3a49, 0xb833,
+ 0x0000, 0xb834, 0x5449, 0x0000, 0xb835, 0x0000, 0x0000, 0xb836,
+ 0xb837, 0x3176, 0x0000, 0x4536, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x544b, 0x0000, 0x5447, 0x0000, 0x0000, 0x3f50, 0x0000, 0x0000,
+ 0xb838, 0x544f, 0x0000, 0x0000, 0xb839, 0x0000, 0x3d4e, 0xb83a,
+ 0xb83b, 0xb83c, 0x0000, 0x362d, 0x0000, 0x5450, 0x0000, 0xb83d,
+ 0xb83e, 0xb83f, 0xb840, 0x0000, 0xb841, 0xb842, 0x0000, 0xb843,
+ 0xb844, 0x0000, 0x0000, 0x4a68, 0xb845, 0x0000, 0xb846, 0x417d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4446, 0xb847, 0x0000, 0x5452,
+ 0xb848, 0xb849, 0xb84a, 0x0000, 0x0000, 0x0000, 0xb84b, 0x0000,
+ 0x4b4f, 0xb84c, 0x0000, 0x5453, 0x0000, 0x0000, 0x5458, 0x0000,
+ 0x0000, 0xb84d, 0xb84e, 0x4a2f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5457, 0x5451, 0x5454, 0x5456, 0xb850, 0x0000, 0x3a26, 0x0000,
+ 0x0000, 0x4a49, 0xb851, 0x0000, 0xb84f, 0x5459, 0x0000, 0x4345,
+ 0xb852, 0x0000, 0x3275, 0x0000, 0x3e6d, 0xb853, 0xb854, 0x0000,
+ 0xb855, 0x545b, 0xb856, 0x545a, 0xb857, 0x3968, 0xb858, 0x545c,
+ 0x545e, 0x545d, 0xb859, 0x0000, 0x5460, 0xb85a, 0x5455, 0x5462,
+ 0x0000, 0xb85b, 0xb85c, 0x0000, 0x5461, 0x545f, 0x0000, 0x0000,
+ 0x0000, 0xb85d, 0x0000, 0x3b4e, 0x3f51, 0x0000, 0x4154, 0x5463,
+ 0x403c, 0x306d, 0x4764, 0xb85e, 0x0000, 0x0000, 0x0000, 0x445b,
+ 0x0000, 0x5465, 0x5464, 0x5466, 0x5467, 0x5468, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_59[] = {
+ 0x0000, 0x0000, 0x5469, 0x0000, 0x0000, 0xb85f, 0xb860, 0x0000,
+ 0x0000, 0x4a51, 0x546a, 0xb861, 0xb862, 0x0000, 0x0000, 0x3246,
+ 0x546b, 0x0000, 0xb863, 0xb864, 0xb865, 0x4d3c, 0x3330, 0x0000,
+ 0x5249, 0x3d48, 0x423f, 0x546c, 0x4c6b, 0xb867, 0x0000, 0x0000,
+ 0x0000, 0xb868, 0x4c34, 0xb869, 0xb86a, 0x546e, 0x0000, 0x4267,
+ 0xb86b, 0x4537, 0x4240, 0x4957, 0x546f, 0x5470, 0x317b, 0xb86c,
+ 0xb86d, 0x3c3a, 0x5471, 0xb86e, 0x0000, 0xb86f, 0xb870, 0x3050,
+ 0x5472, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5473, 0xb871,
+ 0x0000, 0x0000, 0x0000, 0xb872, 0x3162, 0x0000, 0xb873, 0x3471,
+ 0x4660, 0x4a74, 0x0000, 0x0000, 0x0000, 0x0000, 0x5477, 0x4155,
+ 0x5476, 0x3740, 0xb874, 0xb875, 0x4b5b, 0x5475, 0x0000, 0x4565,
+ 0x5479, 0xb876, 0x5478, 0xb877, 0x0000, 0xb878, 0xb879, 0xb87a,
+ 0x547b, 0xb87b, 0x547a, 0xb87c, 0x0000, 0x317c, 0x0000, 0x547c,
+ 0x3e29, 0x547e, 0x4325, 0xb87d, 0x547d, 0xb87e, 0x4a33, 0xb921,
+ 0x0000, 0x0000, 0xb922, 0x3d77, 0x455b, 0xb923, 0xb924, 0x0000,
+ 0x5521, 0xb925, 0x0000, 0xb926, 0xb927, 0x3925, 0x0000, 0x0000,
+ 0x0000, 0x5522, 0x4721, 0x485e, 0x4c51, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4725, 0xb928, 0xb929, 0x552b, 0xb92a, 0x0000,
+ 0x0000, 0x0000, 0xb92b, 0x3538, 0x0000, 0xb92c, 0x4d45, 0xb92d,
+ 0x0000, 0x4c2f, 0x0000, 0x562c, 0x0000, 0x5523, 0x0000, 0xb92e,
+ 0x0000, 0x0000, 0x0000, 0x5526, 0xb92f, 0x4245, 0x0000, 0xb930,
+ 0x4b38, 0x0000, 0x0000, 0x0000, 0x454a, 0xb931, 0xb932, 0xb933,
+ 0xb934, 0x0000, 0x5527, 0xb935, 0x0000, 0x0000, 0x0000, 0xb936,
+ 0x0000, 0x4b65, 0xb937, 0x3a4a, 0xb938, 0x0000, 0x3e2a, 0x0000,
+ 0x0000, 0xb939, 0x0000, 0xb93a, 0xb93b, 0x0000, 0x5528, 0x0000,
+ 0xb93c, 0x3b50, 0xb93d, 0x3b4f, 0x0000, 0xb93e, 0x0000, 0x0000,
+ 0x3039, 0x3848, 0xb93f, 0x402b, 0x3051, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x552c, 0x552d, 0x0000, 0x552a, 0xb940, 0xb941, 0xb942,
+ 0x0000, 0x0000, 0x0000, 0xb943, 0xb944, 0x3138, 0x342f, 0xb945,
+ 0x5529, 0x0000, 0x4c45, 0x4931, 0x0000, 0x0000, 0xb946, 0xb947,
+ 0x0000, 0xb948, 0xb949, 0x0000, 0xb94a, 0x0000, 0x3028, 0xb94b,
+ 0x0000, 0x0000, 0x0000, 0x3079, 0x0000, 0x0000, 0x0000, 0x3b51
+};
+
+static const unsigned short jis_from_unicode_5a[] = {
+ 0xb94c, 0x3052, 0x0000, 0x3023, 0xb94d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5532, 0x0000, 0x0000, 0xb94e, 0xb94f, 0xb950, 0x0000,
+ 0x0000, 0x5530, 0xb951, 0xb952, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4c3c, 0x0000, 0x5533, 0x0000, 0x5531, 0x0000, 0xb953, 0x552f,
+ 0x3f31, 0x0000, 0x0000, 0xb954, 0xb955, 0x552e, 0x0000, 0xb956,
+ 0xb957, 0x4a5a, 0xb958, 0x0000, 0x0000, 0xb959, 0x0000, 0x3864,
+ 0xb95a, 0x0000, 0x0000, 0x0000, 0x0000, 0x5537, 0x5538, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3e2b, 0x0000, 0x0000, 0x0000,
+ 0x5534, 0x4f2c, 0x0000, 0x0000, 0xb95b, 0xb95c, 0x474c, 0xb95d,
+ 0xb95e, 0x5536, 0x0000, 0x0000, 0xb95f, 0x0000, 0x0000, 0x0000,
+ 0xb960, 0x0000, 0x0000, 0x0000, 0x0000, 0xb961, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3a27, 0x0000, 0x0000, 0x0000, 0xb962, 0x0000,
+ 0x0000, 0x0000, 0x5539, 0xb963, 0x0000, 0xb964, 0x4958, 0xb965,
+ 0x0000, 0x0000, 0x553a, 0x0000, 0x5535, 0xb966, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb967,
+ 0x0000, 0x0000, 0xb968, 0xb969, 0x0000, 0x0000, 0xb96a, 0x4c3b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xb96b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xb96c, 0x0000, 0x475e, 0xb96d, 0x0000, 0x0000, 0xb96e, 0x0000,
+ 0x0000, 0xb96f, 0x553b, 0x4932, 0xb970, 0x0000, 0xb971, 0xb972,
+ 0xb973, 0x0000, 0xb974, 0x0000, 0x0000, 0x0000, 0x0000, 0xb975,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xb976, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb977, 0xb978, 0xb979, 0x0000, 0xb97a, 0x0000, 0x0000,
+ 0xb97b, 0x0000, 0xb97c, 0xb97d, 0x553c, 0x5540, 0x553d, 0xb97e,
+ 0x0000, 0x3247, 0x553f, 0x0000, 0xba21, 0x0000, 0xba22, 0x0000,
+ 0xba23, 0x3c3b, 0x0000, 0x553e, 0x3779, 0x0000, 0x0000, 0xba24,
+ 0x554c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5545, 0x5542,
+ 0x0000, 0x0000, 0xba25, 0x0000, 0xba26, 0x0000, 0x0000, 0x0000,
+ 0xba27, 0x4364, 0x0000, 0x5541, 0x0000, 0xba28, 0x5543, 0x0000,
+ 0x0000, 0x5544, 0xba29, 0x0000, 0x0000, 0x0000, 0xba2a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xba2b, 0xba2c, 0x0000,
+ 0x0000, 0x0000, 0x5546, 0x5547, 0x0000, 0xba2d, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_5b[] = {
+ 0xba2e, 0xba2f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xba30, 0x3472, 0x0000, 0x5549, 0x5548, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x554a, 0xba31,
+ 0x0000, 0xba33, 0x0000, 0xba34, 0x0000, 0xba35, 0x0000, 0x0000,
+ 0x0000, 0xba36, 0x3e6e, 0x0000, 0x0000, 0xba37, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x554d, 0x0000, 0x445c, 0xba38, 0x0000, 0x0000,
+ 0x3145, 0x0000, 0x554b, 0x0000, 0xba32, 0x0000, 0x554e, 0x0000,
+ 0xba39, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x554f, 0x0000,
+ 0x5552, 0xba3a, 0x0000, 0x5550, 0x0000, 0x5551, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xba3b, 0xba3c, 0x0000, 0x0000, 0x0000,
+ 0x3b52, 0x5553, 0xba3d, 0x0000, 0x3926, 0x5554, 0xba3e, 0x3b7a,
+ 0x4238, 0x0000, 0x5555, 0x5556, 0x3b5a, 0x3927, 0xba3f, 0x4c52,
+ 0x0000, 0x0000, 0x0000, 0x3528, 0x3849, 0x5557, 0x3358, 0x0000,
+ 0xba40, 0x5558, 0x0000, 0x4239, 0x0000, 0x0000, 0xba41, 0xba42,
+ 0x5559, 0x5623, 0x0000, 0x555a, 0x0000, 0x555b, 0x0000, 0x0000,
+ 0x555c, 0x0000, 0x555e, 0x0000, 0xba43, 0xba44, 0xba45, 0xba46,
+ 0x555f, 0xba47, 0x0000, 0x5560, 0xba48, 0x4270, 0xba49, 0x3127,
+ 0x3c69, 0x3042, 0xba4a, 0x4157, 0x3430, 0x3c35, 0xba4b, 0x3928,
+ 0xba4c, 0xba4d, 0x0000, 0xba4e, 0xba4f, 0x4566, 0xba50, 0x3d21,
+ 0x3431, 0x4368, 0x446a, 0x3038, 0x3539, 0x4a75, 0x0000, 0x3c42,
+ 0x0000, 0x0000, 0x3552, 0x406b, 0x3c3c, 0x4d28, 0x5561, 0x0000,
+ 0xba51, 0xba52, 0x0000, 0x0000, 0xba53, 0xba54, 0x355c, 0xba55,
+ 0x3a4b, 0xba56, 0xba57, 0x3332, 0x3163, 0x3e2c, 0x3248, 0xba58,
+ 0x5562, 0x4d46, 0xba59, 0x0000, 0xba5a, 0x0000, 0x0000, 0x3d49,
+ 0xba5b, 0xba5c, 0x3c64, 0x5563, 0x3473, 0x4652, 0x4c29, 0x5564,
+ 0x0000, 0x5565, 0x0000, 0x0000, 0x4959, 0xba5d, 0x0000, 0xba5e,
+ 0x5567, 0x0000, 0x3428, 0x3677, 0x5566, 0x0000, 0xba5f, 0xba60,
+ 0xba61, 0xba62, 0xba63, 0x3432, 0x0000, 0x3f32, 0x556b, 0x3b21,
+ 0xba64, 0x3249, 0x556a, 0x0000, 0x5568, 0x556c, 0x5569, 0x472b,
+ 0x5c4d, 0x3f33, 0x0000, 0x556d, 0x0000, 0x0000, 0x4e40, 0xba65,
+ 0x556e, 0xba66, 0x0000, 0x5570, 0xba67, 0x437e, 0x556f, 0x0000,
+ 0x4023, 0x0000, 0x3b7b, 0x0000, 0x0000, 0xba68, 0x4250, 0x3c77
+};
+
+static const unsigned short jis_from_unicode_5c[] = {
+ 0x0000, 0x4975, 0x406c, 0x0000, 0x3c4d, 0x5571, 0x3e2d, 0x5572,
+ 0x5573, 0x3053, 0x423a, 0x3f52, 0xba69, 0x5574, 0x4633, 0x3e2e,
+ 0x0000, 0x3e2f, 0x0000, 0x5575, 0x0000, 0x0000, 0x406d, 0xba6a,
+ 0x0000, 0x0000, 0x3e30, 0x0000, 0x0000, 0x0000, 0xba6b, 0xba6c,
+ 0x5576, 0x0000, 0x5577, 0xba6d, 0x4c60, 0x0000, 0xba6e, 0x0000,
+ 0x5578, 0xba6f, 0x0000, 0xba70, 0xba71, 0x3646, 0xba72, 0x0000,
+ 0xba73, 0x3d22, 0xba74, 0x0000, 0x0000, 0xba75, 0xba76, 0x0000,
+ 0x5579, 0x557a, 0x3c5c, 0x3f2c, 0x4674, 0x3f54, 0x4878, 0x4722,
+ 0x3649, 0x557b, 0x0000, 0x0000, 0x0000, 0x356f, 0x557c, 0x0000,
+ 0x367e, 0x0000, 0x464f, 0x3230, 0x0000, 0x3b53, 0x557d, 0x5622,
+ 0x5621, 0x367d, 0x0000, 0x557e, 0x0000, 0x4538, 0x0000, 0x0000,
+ 0x0000, 0xba77, 0xba78, 0x0000, 0xba79, 0x0000, 0x4230, 0x0000,
+ 0x454b, 0x3c48, 0xba7a, 0xba7b, 0x4158, 0x4d7a, 0x0000, 0xba7c,
+ 0xba7d, 0xba7e, 0x0000, 0x0000, 0x5624, 0xbb21, 0x5625, 0x4656,
+ 0xbb22, 0x3b33, 0x0000, 0x0000, 0xbb23, 0xbb24, 0x5627, 0x0000,
+ 0x0000, 0x5628, 0xbb25, 0xbb26, 0xbb27, 0xbb28, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbb29,
+ 0xbb2a, 0x0000, 0xbb2b, 0x0000, 0x5629, 0x0000, 0x0000, 0xbb2c,
+ 0x3474, 0x562a, 0xbb2d, 0x0000, 0x562b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbb2e, 0x0000, 0xbb2f,
+ 0xbb30, 0x322c, 0xbb31, 0xbb32, 0x0000, 0x0000, 0xbb33, 0x0000,
+ 0x413b, 0x3464, 0xbb34, 0x562d, 0x4c28, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4252, 0xbb35, 0x3359, 0xbb36, 0xbb37, 0x562f, 0x5631,
+ 0x345f, 0x0000, 0xbb38, 0x562e, 0x5630, 0x0000, 0x5633, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5632, 0x0000, 0x5634,
+ 0x0000, 0xbb39, 0x0000, 0xbb3a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xbb3b, 0x0000, 0x0000, 0x0000, 0x0000, 0xbb3d,
+ 0x0000, 0x5635, 0x0000, 0x0000, 0x0000, 0xbb3c, 0x0000, 0x0000,
+ 0x463d, 0x362e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3265, 0x5636, 0x563b, 0x0000, 0x0000, 0x5639, 0xbb3e, 0x4a77,
+ 0x4a76, 0xbb3f, 0xbb40, 0x0000, 0xbb41, 0x0000, 0x4567, 0x0000,
+ 0x0000, 0x0000, 0x5638, 0x3d54, 0x0000, 0x5637, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_5d[] = {
+ 0x0000, 0xbb42, 0x0000, 0x0000, 0x0000, 0x0000, 0xbb43, 0x3f72,
+ 0x0000, 0x0000, 0x0000, 0x563c, 0x0000, 0xbb44, 0x3a6a, 0x0000,
+ 0x0000, 0x5642, 0xbb45, 0x0000, 0x5643, 0x563d, 0x3333, 0x563e,
+ 0x5647, 0x5646, 0x5645, 0x5641, 0x0000, 0x0000, 0x0000, 0x5640,
+ 0x0000, 0x0000, 0x5644, 0xbb47, 0xbb48, 0x0000, 0xbb49, 0xbb4a,
+ 0x0000, 0x4a78, 0x0000, 0xbb46, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xbb4b, 0x0000, 0x0000, 0xbb4c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xbb4d, 0x0000, 0x0000, 0x0000, 0xbb4e, 0x0000, 0xbb4f,
+ 0x0000, 0x0000, 0xbb50, 0xbb51, 0x0000, 0x0000, 0xbb52, 0x0000,
+ 0xbb53, 0x0000, 0xbb57, 0x564b, 0x5648, 0x0000, 0x564a, 0x0000,
+ 0x4d72, 0xbb55, 0x5649, 0x0000, 0x0000, 0xbb54, 0x0000, 0x0000,
+ 0x0000, 0xbb56, 0x0000, 0x0000, 0x563f, 0x0000, 0x0000, 0xbb58,
+ 0xbb59, 0xbb5a, 0xbb5b, 0x0000, 0xbb5c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3f73, 0xbb5d, 0x0000, 0x564c, 0xbb5e, 0x0000, 0x3a37,
+ 0xbb5f, 0x0000, 0x0000, 0x564d, 0x0000, 0x0000, 0x564e, 0x0000,
+ 0x0000, 0xbb60, 0xbb61, 0x0000, 0x0000, 0x0000, 0xbb62, 0xbb63,
+ 0x0000, 0xbb64, 0x5651, 0xbb65, 0x5650, 0x0000, 0x0000, 0x564f,
+ 0xbb66, 0x0000, 0xbb67, 0x4568, 0x563a, 0x0000, 0x0000, 0x0000,
+ 0x5657, 0x0000, 0xbb68, 0xbb69, 0xbb6a, 0xbb6b, 0x0000, 0x0000,
+ 0x0000, 0xbb6c, 0x0000, 0xbb6d, 0x0000, 0x5653, 0x0000, 0xbb6e,
+ 0xbb6f, 0x0000, 0x5652, 0x0000, 0x0000, 0x0000, 0x0000, 0xbb70,
+ 0x0000, 0x0000, 0x0000, 0xbb71, 0x5654, 0x0000, 0x5655, 0x0000,
+ 0xbb72, 0x0000, 0xe674, 0x0000, 0xbb73, 0x0000, 0x0000, 0x5658,
+ 0xbb74, 0xbb75, 0x4e66, 0x0000, 0x5659, 0x5656, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xbb76, 0x0000, 0x0000, 0x0000, 0xbb77,
+ 0x0000, 0x565a, 0x0000, 0xbb78, 0x3460, 0x565b, 0xbb7a, 0x0000,
+ 0xbb79, 0x0000, 0x565d, 0x565c, 0x0000, 0x0000, 0x565e, 0x0000,
+ 0xbb7b, 0xbb7c, 0x0000, 0x565f, 0x0000, 0x406e, 0x3d23, 0x0000,
+ 0xbb7d, 0x3d64, 0x0000, 0x4163, 0xbb7e, 0x3929, 0x3a38, 0x392a,
+ 0x3570, 0xbc21, 0x0000, 0x5660, 0x0000, 0x0000, 0x3a39, 0x0000,
+ 0x0000, 0x384a, 0x5661, 0x4c26, 0x4743, 0x5662, 0x0000, 0x392b,
+ 0xbc22, 0xbc23, 0x0000, 0x342c, 0x0000, 0x4327, 0x3652, 0x0000
+};
+
+static const unsigned short jis_from_unicode_5e[] = {
+ 0xbc24, 0x0000, 0x3b54, 0x495b, 0x0000, 0x0000, 0x4841, 0xbc25,
+ 0x0000, 0x0000, 0x0000, 0x5663, 0x3475, 0xbc26, 0x0000, 0x0000,
+ 0x0000, 0x5666, 0xbc27, 0x0000, 0xbc28, 0xbc29, 0x4421, 0x0000,
+ 0xbc2a, 0x5665, 0x5664, 0x5667, 0x0000, 0x446b, 0x0000, 0xbc2b,
+ 0xbc2c, 0x0000, 0x0000, 0x0000, 0x0000, 0x3f63, 0x0000, 0x0000,
+ 0xbc2e, 0x0000, 0x0000, 0x3b55, 0x0000, 0x404a, 0xbc2d, 0x4253,
+ 0x3522, 0x0000, 0xbc2f, 0x4422, 0x0000, 0xbc30, 0x5668, 0x5669,
+ 0x3e6f, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b39, 0xbc31, 0x0000,
+ 0x566c, 0x0000, 0x0000, 0x566b, 0x566a, 0x497d, 0x0000, 0x5673,
+ 0x0000, 0xbc34, 0x0000, 0xbc32, 0x4b5a, 0x0000, 0x566d, 0x0000,
+ 0xbc33, 0xbc35, 0x0000, 0x0000, 0x566f, 0x4b6b, 0xbc36, 0x566e,
+ 0xbc37, 0x0000, 0x0000, 0xbc38, 0xbc39, 0x0000, 0xbc3a, 0x5670,
+ 0x0000, 0x4828, 0x5671, 0x4a3e, 0x5672, 0x0000, 0x0000, 0x0000,
+ 0xbc3b, 0x0000, 0xbc3c, 0xbc3d, 0xbc3e, 0xbc3f, 0xbc40, 0x0000,
+ 0xbc41, 0x0000, 0x3433, 0x4a3f, 0x472f, 0x5674, 0x5675, 0x0000,
+ 0x392c, 0x3434, 0x5676, 0x3838, 0x4d44, 0x4d29, 0x3476, 0x5678,
+ 0xbc42, 0x4423, 0x0000, 0x392d, 0x3e31, 0x0000, 0x0000, 0x485f,
+ 0x0000, 0x0000, 0x3e32, 0xbc43, 0x0000, 0x0000, 0xbc44, 0x3d78,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x446c, 0x4a79, 0x4539,
+ 0x0000, 0x0000, 0x392e, 0x0000, 0x495c, 0x0000, 0x0000, 0x0000,
+ 0x5679, 0x0000, 0xbc45, 0x0000, 0xbc46, 0xbc47, 0x4559, 0x3a42,
+ 0xbc48, 0x0000, 0xbc49, 0x384b, 0xbc4a, 0x446d, 0x0000, 0x0000,
+ 0x0000, 0xbc4b, 0x0000, 0xbc4c, 0x0000, 0x3043, 0x3d6e, 0x392f,
+ 0x4d47, 0x0000, 0x0000, 0x0000, 0x0000, 0xbc4d, 0xbc4e, 0xbc4f,
+ 0x0000, 0x567a, 0x567b, 0x4751, 0x0000, 0x0000, 0xbc50, 0x0000,
+ 0x567c, 0x4e77, 0x4f2d, 0xbc52, 0xbc51, 0x0000, 0xbc53, 0x567e,
+ 0x567d, 0xbc54, 0xbc55, 0x3347, 0xbc56, 0xbc57, 0x5721, 0x0000,
+ 0x0000, 0x0000, 0x5724, 0x5725, 0xbc58, 0x5723, 0xbc59, 0x4940,
+ 0x3e33, 0x5727, 0x5726, 0x5722, 0x0000, 0xbc5a, 0x0000, 0x0000,
+ 0x5728, 0x5729, 0x0000, 0xbc5b, 0x572a, 0x0000, 0x0000, 0x0000,
+ 0x572d, 0x572b, 0x0000, 0x572c, 0x572e, 0x0000, 0x3164, 0x446e,
+ 0x572f, 0x0000, 0x377a, 0x3276, 0x4736, 0x0000, 0x5730, 0x467b
+};
+
+static const unsigned short jis_from_unicode_5f[] = {
+ 0x0000, 0x4a5b, 0xbc5c, 0x5731, 0x4f2e, 0x0000, 0xbc5d, 0xbc5e,
+ 0xbc5f, 0x5732, 0x4a40, 0x5735, 0x5021, 0x5031, 0xbc60, 0x3c30,
+ 0x4675, 0x5736, 0x0000, 0x355d, 0x4424, 0x307a, 0x5737, 0x4a26,
+ 0x3930, 0xbc61, 0x0000, 0x4350, 0xbc62, 0xbc63, 0x0000, 0x446f,
+ 0x0000, 0xbc64, 0xbc65, 0xbc66, 0xbc67, 0x4c6f, 0x3839, 0x384c,
+ 0xbc68, 0x5738, 0x0000, 0xbc69, 0xbc6a, 0x5739, 0xbc6b, 0x573f,
+ 0xbc6c, 0x3c65, 0x0000, 0x0000, 0xbc6d, 0x4425, 0xbc6e, 0x362f,
+ 0x573a, 0x0000, 0x0000, 0xbc6f, 0x492b, 0xbc70, 0x4346, 0xbc71,
+ 0xbc72, 0x573b, 0x0000, 0x0000, 0xbc73, 0xbc74, 0x0000, 0xbc75,
+ 0x573c, 0x0000, 0x3630, 0x0000, 0x573d, 0xbc76, 0x573e, 0x0000,
+ 0xbc77, 0x5740, 0x0000, 0x4576, 0xbc78, 0x0000, 0x5741, 0x5742,
+ 0xbc79, 0x5743, 0x0000, 0xbc7a, 0x5734, 0x5733, 0x0000, 0x0000,
+ 0xbc7b, 0x5744, 0x3741, 0xbc7c, 0xbc7d, 0x0000, 0x4927, 0xbc7e,
+ 0x0000, 0x3a4c, 0x4937, 0x4426, 0x494b, 0x5745, 0x0000, 0xbd21,
+ 0x3e34, 0x3146, 0xbd22, 0x5746, 0xbd23, 0xbd24, 0x0000, 0x5747,
+ 0xbd25, 0x4c72, 0xbd26, 0x0000, 0x4860, 0xbd27, 0xbd28, 0x574a,
+ 0x317d, 0x402c, 0x5749, 0x5748, 0x3742, 0x4254, 0x0000, 0x574e,
+ 0x574c, 0xbd29, 0x574b, 0x4e27, 0x3865, 0xbd2a, 0x0000, 0xbd2b,
+ 0x3d79, 0x574d, 0x454c, 0x3d3e, 0x0000, 0x0000, 0xbd2c, 0x4640,
+ 0x5751, 0x5750, 0x0000, 0x0000, 0xbd2d, 0xbd2e, 0x574f, 0x0000,
+ 0x5752, 0x3866, 0xbd2f, 0x0000, 0xbd32, 0x0000, 0x0000, 0xbd30,
+ 0x5753, 0x497c, 0x3d5b, 0xbd31, 0xbd33, 0x5754, 0x4879, 0xbd34,
+ 0xbd35, 0xbd36, 0x0000, 0x4641, 0x4427, 0x0000, 0x0000, 0x0000,
+ 0xbd37, 0x4530, 0x0000, 0x0000, 0x5755, 0x352b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3f34, 0xbd38, 0x492c, 0x0000, 0xbd39,
+ 0xbd3a, 0xbd3b, 0x0000, 0xbd3c, 0x3477, 0x4726, 0x0000, 0x0000,
+ 0xbd3d, 0xbd3e, 0xbd3f, 0xbd40, 0xbd41, 0x0000, 0x5756, 0x3b56,
+ 0x4b3a, 0x4b3b, 0x0000, 0x0000, 0x317e, 0x575b, 0xbd42, 0x0000,
+ 0x4369, 0xbd43, 0xbd44, 0x0000, 0x5758, 0x0000, 0x0000, 0x0000,
+ 0xbd45, 0xbd46, 0xbd47, 0x3277, 0xbd48, 0xbd49, 0xbd4a, 0xbd4b,
+ 0x582d, 0x575a, 0xbd4c, 0xbd4d, 0x0000, 0x4730, 0xbd4e, 0x0000,
+ 0x5759, 0x0000, 0xbd4f, 0x5757, 0xbd50, 0x397a, 0x0000, 0x575d
+};
+
+static const unsigned short jis_from_unicode_60[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbd51,
+ 0x0000, 0x0000, 0xbd52, 0x0000, 0x0000, 0xbd53, 0x5763, 0x5769,
+ 0x5761, 0x0000, 0x455c, 0xbd54, 0xbd55, 0x5766, 0x495d, 0xbd56,
+ 0xbd57, 0x5760, 0xbd58, 0x5765, 0x4e67, 0x3b57, 0x0000, 0xbd59,
+ 0x4255, 0x575e, 0x0000, 0x0000, 0xbd5a, 0x355e, 0x5768, 0x402d,
+ 0x3165, 0x5762, 0x3278, 0x5767, 0x0000, 0xbd5b, 0x0000, 0x3631,
+ 0x0000, 0x5764, 0x0000, 0xbd5c, 0x0000, 0xbd5d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x576a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xbd5e, 0x576c, 0x5776, 0x5774, 0x0000, 0x0000, 0x5771, 0xbd5f,
+ 0xbd60, 0xbd61, 0x5770, 0x4e78, 0xbd62, 0x5772, 0x0000, 0x0000,
+ 0x3632, 0xbd63, 0x3931, 0x0000, 0xbd64, 0x3d7a, 0xbd65, 0xbd66,
+ 0x0000, 0x5779, 0x576b, 0x0000, 0x0000, 0xbd67, 0x0000, 0x576f,
+ 0x575f, 0xbd68, 0x327a, 0x5773, 0x5775, 0x4351, 0x0000, 0xbd69,
+ 0x3a28, 0x3238, 0x576d, 0x5778, 0x5777, 0x3633, 0x0000, 0x4229,
+ 0x3366, 0xbd6a, 0x0000, 0x0000, 0x0000, 0x3743, 0x0000, 0x576e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbd6b, 0xbd6c,
+ 0x0000, 0x577a, 0xbd6d, 0x577d, 0x5821, 0x0000, 0xbd6e, 0x0000,
+ 0xbd6f, 0x3c3d, 0xbd70, 0x5827, 0x4470, 0x577b, 0xbd71, 0x0000,
+ 0x0000, 0xbd72, 0x5825, 0xbd73, 0x3279, 0xbd74, 0x5823, 0x5824,
+ 0xbd75, 0x0000, 0x577e, 0x5822, 0x0000, 0xbd76, 0xbd77, 0x3867,
+ 0x4d2a, 0x0000, 0xbd78, 0x3435, 0xbd79, 0xbd7a, 0x3159, 0x5826,
+ 0xbd7b, 0x473a, 0x302d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xbd7c, 0xbd7d, 0x4861, 0x575c, 0x582c, 0x5830, 0x4c65, 0xbd7e,
+ 0x5829, 0x0000, 0x0000, 0xbe21, 0x4569, 0x582e, 0xbe22, 0x0000,
+ 0x0000, 0x0000, 0xbe23, 0x0000, 0xbe24, 0x3e70, 0x582f, 0x4657,
+ 0xbe25, 0xbe26, 0xbe27, 0xbe28, 0x0000, 0x0000, 0xbe29, 0xbe2a,
+ 0x0000, 0x4f47, 0x0000, 0x582b, 0xbe2b, 0xbe2c, 0x0000, 0x0000,
+ 0x5831, 0xbe2d, 0x397b, 0xbe2e, 0x404b, 0xbe2f, 0xbe30, 0x3054,
+ 0x582a, 0x5828, 0xbe31, 0x415a, 0x0000, 0xbe32, 0x0000, 0x577c,
+ 0x3b34, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4246, 0x583d, 0xbe33, 0x415b, 0x5838, 0xbe34, 0x5835, 0x5836,
+ 0xbe35, 0x3c66, 0x5839, 0x583c, 0xbe36, 0xbe37, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_61[] = {
+ 0x5837, 0x3d25, 0xbe38, 0x583a, 0x0000, 0x0000, 0x5834, 0xbe39,
+ 0x4c7c, 0x4c7b, 0xbe3a, 0x0000, 0xbe3b, 0x583e, 0x583f, 0x3055,
+ 0xbe3c, 0xbe3d, 0xbe3e, 0xbe3f, 0xbe40, 0x5833, 0xbe41, 0xbe42,
+ 0x0000, 0xbe43, 0x3672, 0x3026, 0xbe44, 0x0000, 0xbe45, 0x3436,
+ 0x0000, 0x583b, 0xbe46, 0x0000, 0x0000, 0x0000, 0x0000, 0x5843,
+ 0x5842, 0x0000, 0xbe47, 0xbe48, 0x5847, 0x0000, 0x0000, 0x0000,
+ 0xbe49, 0xbe4a, 0x0000, 0x0000, 0x5848, 0xbe4b, 0xbe4c, 0xbe4d,
+ 0x0000, 0xbe4e, 0x0000, 0x0000, 0x5846, 0x5849, 0x5841, 0x5845,
+ 0x0000, 0xbe4f, 0x584a, 0x0000, 0x584b, 0xbe50, 0xbe51, 0x5840,
+ 0x3b7c, 0xbe52, 0x5844, 0x4256, 0x3932, 0x5832, 0x3f35, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5858, 0x0000, 0x4a69, 0x0000, 0x0000,
+ 0x584e, 0x584f, 0x5850, 0x0000, 0x0000, 0x5857, 0xbe53, 0x5856,
+ 0xbe54, 0x0000, 0x4b7d, 0x3437, 0x0000, 0x5854, 0x0000, 0x3745,
+ 0x3334, 0x0000, 0x0000, 0x5851, 0xbe55, 0x0000, 0x4e38, 0x5853,
+ 0x3056, 0x5855, 0xbe56, 0x584c, 0x5852, 0x5859, 0x3744, 0x584d,
+ 0xbe57, 0x0000, 0x0000, 0xbe58, 0xbe59, 0x0000, 0x4d5d, 0xbe5a,
+ 0xbe5b, 0xbe5c, 0x4d2b, 0xbe5d, 0xbe5e, 0x0000, 0x0000, 0x585c,
+ 0x0000, 0x0000, 0x5860, 0xbe5f, 0x0000, 0xbe60, 0x417e, 0x0000,
+ 0x4e79, 0x5861, 0xbe61, 0xbe62, 0x585e, 0x0000, 0x585b, 0xbe63,
+ 0xbe64, 0x585a, 0x585f, 0x0000, 0xbe65, 0xbe66, 0x0000, 0xbe67,
+ 0xbe68, 0x0000, 0x0000, 0x0000, 0x4a30, 0xbe69, 0x0000, 0x4634,
+ 0xbe6a, 0x3746, 0xbe6b, 0x5862, 0x585d, 0xbe6c, 0x5863, 0x0000,
+ 0x0000, 0x0000, 0x377b, 0x0000, 0x0000, 0x0000, 0x3231, 0x0000,
+ 0xbe6d, 0xbe6e, 0x586b, 0x0000, 0xbe6f, 0x0000, 0x3438, 0x0000,
+ 0xbe70, 0xbe71, 0xbe72, 0x5869, 0x0000, 0x0000, 0x586a, 0x3a29,
+ 0x5868, 0x5866, 0x5865, 0x586c, 0x5864, 0x586e, 0xbe73, 0xbe74,
+ 0x327b, 0x0000, 0x0000, 0x0000, 0x0000, 0xbe75, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xbe76, 0xbe77, 0xbe78, 0xbe79,
+ 0x0000, 0xbe7a, 0xbe7b, 0x5870, 0x0000, 0xbe7e, 0x586f, 0xbe7c,
+ 0x0000, 0xbe7d, 0x0000, 0x0000, 0xbf21, 0xbf22, 0x0000, 0xbf23,
+ 0x0000, 0x0000, 0x4428, 0x0000, 0x5873, 0x0000, 0x5871, 0x5867,
+ 0x377c, 0x0000, 0x5872, 0x0000, 0x5876, 0x5875, 0x5877, 0x5874
+};
+
+static const unsigned short jis_from_unicode_62[] = {
+ 0x5878, 0xbf24, 0x0000, 0xbf25, 0xbf26, 0x0000, 0x0000, 0xbf27,
+ 0x5879, 0x587a, 0x4a6a, 0x0000, 0x587c, 0x587b, 0x3d3f, 0x0000,
+ 0x402e, 0x3266, 0x327c, 0xbf28, 0x587d, 0xbf29, 0x303f, 0x0000,
+ 0x0000, 0x0000, 0x404c, 0x587e, 0xbf2a, 0x6c43, 0x5921, 0x3761,
+ 0xbf2b, 0x5922, 0xbf2c, 0xbf2d, 0x0000, 0x0000, 0x406f, 0xbf2e,
+ 0x0000, 0xbf2f, 0x5923, 0xbf30, 0x0000, 0x0000, 0x5924, 0x353a,
+ 0x5925, 0x0000, 0x5926, 0x5927, 0x4257, 0x0000, 0x0000, 0x0000,
+ 0x384d, 0xbf31, 0x0000, 0x4c61, 0x0000, 0xbf32, 0x0000, 0x4b3c,
+ 0x3d6a, 0x5928, 0xbf33, 0xbf34, 0xbf35, 0x0000, 0xbf36, 0x4070,
+ 0x6e3d, 0x4862, 0x0000, 0x3c6a, 0xbf37, 0x3a4d, 0x5929, 0x0000,
+ 0xbf38, 0xbf39, 0xbf3a, 0x4247, 0xbf3b, 0x4a27, 0xbf3c, 0x0000,
+ 0x4271, 0x0000, 0xbf3d, 0x592c, 0xbf3e, 0x0000, 0x592a, 0x0000,
+ 0x592d, 0x0000, 0x0000, 0x592b, 0xbf3f, 0x0000, 0x0000, 0x0000,
+ 0x592e, 0x0000, 0x0000, 0x0000, 0x0000, 0xbf40, 0x4a31, 0xbf41,
+ 0x0000, 0x3037, 0x0000, 0xbf42, 0x0000, 0x0000, 0x495e, 0x0000,
+ 0x0000, 0x4863, 0xbf43, 0x0000, 0x592f, 0xbf44, 0x5932, 0x3e35,
+ 0x353b, 0x0000, 0x5930, 0x5937, 0x3e36, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5931, 0x4744, 0x0000, 0x0000, 0xbf45, 0xbf46, 0xbf47,
+ 0xbf48, 0x4d5e, 0x5933, 0x5934, 0x5938, 0x456a, 0x5935, 0x3933,
+ 0x405e, 0x0000, 0x0000, 0x5946, 0x4834, 0x0000, 0x4272, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbf49, 0x0000,
+ 0xbf4a, 0x0000, 0x0000, 0x4864, 0x5a2d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4a7a, 0x0000, 0xbf4b, 0x0000, 0x4471, 0xbf4c, 0xbf4d,
+ 0x0000, 0x4b75, 0xbf4e, 0x593b, 0x3221, 0x436a, 0xbf4f, 0xbf50,
+ 0x0000, 0x0000, 0x5944, 0x0000, 0xbf51, 0x4334, 0x593e, 0x5945,
+ 0x5940, 0x5947, 0x5943, 0x0000, 0x5942, 0x476f, 0xbf52, 0x593c,
+ 0x327d, 0x593a, 0x3571, 0x4273, 0x5936, 0xbf53, 0xbf54, 0x5939,
+ 0x3934, 0x405b, 0xbf55, 0x3e37, 0x5941, 0x4752, 0x0000, 0x0000,
+ 0x3572, 0x3348, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xbf56, 0x0000, 0x3367, 0x3f21, 0x5949, 0x594e,
+ 0x0000, 0x594a, 0xbf57, 0x377d, 0xbf58, 0x594f, 0x3b22, 0x3969,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xbf59, 0xbf5a, 0x3d26, 0x593d
+};
+
+static const unsigned short jis_from_unicode_63[] = {
+ 0x0000, 0x3b7d, 0x594c, 0xbf5b, 0xbf5c, 0x0000, 0x0000, 0x3b58,
+ 0x594d, 0x3044, 0xbf5d, 0xbf5e, 0x5948, 0xbf5f, 0x0000, 0x0000,
+ 0xbf60, 0x4429, 0x0000, 0xbf61, 0x0000, 0x0000, 0xbf62, 0x0000,
+ 0xbf63, 0x3573, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3634,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x594b,
+ 0x3027, 0xbf64, 0xbf65, 0x3a43, 0x0000, 0xbf66, 0x0000, 0x3f36,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbf67, 0xbf68, 0x0000,
+ 0x0000, 0xbf69, 0x4472, 0x0000, 0xbf6a, 0x4854, 0x5951, 0x415e,
+ 0x0000, 0xbf6b, 0xbf6c, 0xbf6d, 0xbf6e, 0x0000, 0xbf6f, 0x0000,
+ 0x0000, 0x422a, 0xbf70, 0xbf71, 0x3b2b, 0x5952, 0xbf72, 0x5954,
+ 0x5950, 0x0000, 0xbf73, 0xbf74, 0xbf75, 0x4a61, 0x0000, 0x443d,
+ 0xbf76, 0x0000, 0x0000, 0xbf77, 0x415c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbf78, 0xbf79, 0x4a7b,
+ 0x3c4e, 0x5960, 0x0000, 0x595f, 0xbf7a, 0xbf7b, 0x3f78, 0x0000,
+ 0x0000, 0xbf7c, 0x377e, 0x0000, 0xbf7d, 0xbf7e, 0x5959, 0x3e39,
+ 0xc021, 0x0000, 0x4668, 0x4731, 0xc022, 0xc023, 0x0000, 0xc024,
+ 0x5957, 0x0000, 0xc025, 0x415d, 0xc026, 0x0000, 0x0000, 0xc027,
+ 0x3c78, 0x595c, 0xc028, 0x0000, 0x3e38, 0x0000, 0x5956, 0x595b,
+ 0xc029, 0x0000, 0x4753, 0x0000, 0xc02a, 0xc02b, 0x5955, 0x0000,
+ 0x3721, 0xc02c, 0xc02d, 0x335d, 0x0000, 0x0000, 0xc02e, 0x595d,
+ 0x4e2b, 0x3a4e, 0x4335, 0x595a, 0xc02f, 0x405c, 0xc030, 0x3935,
+ 0x3f64, 0x3166, 0x413c, 0x5958, 0x3545, 0xc031, 0xc032, 0xc033,
+ 0x0000, 0x0000, 0x3747, 0x0000, 0x444f, 0x595e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x415f, 0x0000, 0xc034, 0x5961, 0x0000,
+ 0x5963, 0xc035, 0x0000, 0x4237, 0x5969, 0xc036, 0x5964, 0x0000,
+ 0xc037, 0x5966, 0x0000, 0x0000, 0x0000, 0x0000, 0xc038, 0x4941,
+ 0x4473, 0xc039, 0x5967, 0xc03a, 0xc03b, 0xc03c, 0x4d2c, 0x0000,
+ 0x0000, 0x0000, 0x4d48, 0x3439, 0xc03d, 0x0000, 0x0000, 0x0000,
+ 0xc03e, 0x302e, 0x0000, 0x5965, 0x0000, 0xc03f, 0x0000, 0x0000,
+ 0x0000, 0x5962, 0xc040, 0x0000, 0xc041, 0x0000, 0x3478, 0x0000,
+ 0x0000, 0x0000, 0xc042, 0xc043, 0x3167, 0xc044, 0x5968, 0x0000,
+ 0xc045, 0xc046, 0x4d49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_64[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x596c, 0x0000,
+ 0x0000, 0xc047, 0xc048, 0x0000, 0x0000, 0x423b, 0x0000, 0x5973,
+ 0xc049, 0x0000, 0xc04a, 0x596d, 0xc04b, 0x0000, 0x596a, 0x5971,
+ 0xc04c, 0x0000, 0x0000, 0x0000, 0x5953, 0x0000, 0xc04d, 0x0000,
+ 0xc04e, 0x0000, 0xc04f, 0x0000, 0xc050, 0xc051, 0x596e, 0x0000,
+ 0x5972, 0xc052, 0xc053, 0x0000, 0x4842, 0x456b, 0x0000, 0xc054,
+ 0xc055, 0x0000, 0x0000, 0x0000, 0x596b, 0xc056, 0x596f, 0x0000,
+ 0x0000, 0x0000, 0x3748, 0x0000, 0x0000, 0xc057, 0x3a71, 0xc058,
+ 0x0000, 0x0000, 0x405d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xc059, 0x0000, 0x0000, 0x5977, 0xc05a,
+ 0x0000, 0xc05b, 0xc05c, 0xc05d, 0xc05e, 0x0000, 0x0000, 0x0000,
+ 0x4526, 0x0000, 0xc05f, 0xc060, 0xc061, 0xc062, 0x0000, 0xc063,
+ 0xc064, 0xc065, 0x0000, 0xc066, 0x0000, 0x0000, 0x0000, 0x5974,
+ 0x0000, 0x4b60, 0x0000, 0x0000, 0x0000, 0xc067, 0x0000, 0x5975,
+ 0x0000, 0x0000, 0x0000, 0xc068, 0xc069, 0x0000, 0x5976, 0x0000,
+ 0x4c4e, 0x0000, 0x4022, 0xc06a, 0x0000, 0xc06b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3762, 0x0000, 0xc06c, 0x0000, 0xc06d,
+ 0x597d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc06e,
+ 0xc06f, 0xc070, 0x3b35, 0x597a, 0x0000, 0x5979, 0x0000, 0x0000,
+ 0xc071, 0xc072, 0x4732, 0xc073, 0x0000, 0xc074, 0x4635, 0xc075,
+ 0x0000, 0xc076, 0x0000, 0xc077, 0x4531, 0x597b, 0xc078, 0x0000,
+ 0xc079, 0x597c, 0x0000, 0x496f, 0xc07a, 0x4745, 0x3b23, 0x0000,
+ 0x4071, 0x0000, 0x4b50, 0xc07b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3349, 0x0000, 0x5a25, 0x597e, 0xc07c, 0xc07d, 0xc07e,
+ 0x0000, 0x4d4a, 0x5a27, 0x0000, 0xc121, 0x5a23, 0x0000, 0x5a24,
+ 0x0000, 0xc122, 0xc123, 0xc124, 0xc125, 0x4160, 0xc126, 0x0000,
+ 0xc127, 0xc128, 0x5a22, 0x0000, 0x593f, 0xc129, 0x0000, 0xc12a,
+ 0x5a26, 0x0000, 0x5a21, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5a2b, 0x5a2c, 0x4527, 0x5a2e, 0xc12b, 0xc12c, 0x3b24, 0x5a29,
+ 0x0000, 0xc12d, 0xc12e, 0x0000, 0x353c, 0xc12f, 0x0000, 0x5a2f,
+ 0xc130, 0x5a28, 0x5a33, 0x0000, 0x5a32, 0xc131, 0x5a31, 0xc132,
+ 0x0000, 0x0000, 0x5a34, 0xc133, 0x0000, 0x5a36, 0x3e71, 0xc134
+};
+
+static const unsigned short jis_from_unicode_65[] = {
+ 0x5a35, 0xc135, 0x0000, 0x0000, 0xc136, 0x5a39, 0x0000, 0x0000,
+ 0xc137, 0xc138, 0xc139, 0x0000, 0x0000, 0x0000, 0x0000, 0xc13a,
+ 0x0000, 0x0000, 0x0000, 0xc13b, 0xc13c, 0x0000, 0xc13d, 0x0000,
+ 0x5a37, 0xc13e, 0x0000, 0xc13f, 0x5a38, 0x5970, 0xc140, 0xc141,
+ 0x0000, 0x0000, 0xc142, 0x5a3b, 0x5a3a, 0x0000, 0xc143, 0x0000,
+ 0x0000, 0xc144, 0x5978, 0x5a3c, 0x5a30, 0x0000, 0xc145, 0x3b59,
+ 0x0000, 0xc146, 0x0000, 0x0000, 0x5a3d, 0x5a3e, 0x5a40, 0x5a3f,
+ 0x5a41, 0x327e, 0xc147, 0x3936, 0xc148, 0xc149, 0x4a7c, 0x402f,
+ 0x0000, 0x0000, 0x0000, 0xc14a, 0x0000, 0x384e, 0x0000, 0xc14b,
+ 0x5a43, 0xc14c, 0x0000, 0x0000, 0x0000, 0x5a46, 0x0000, 0x4952,
+ 0xc14d, 0x355f, 0xc14e, 0x0000, 0xc14f, 0x5a45, 0x5a44, 0x4754,
+ 0x5a47, 0x3635, 0x0000, 0x0000, 0x0000, 0x5a49, 0x5a48, 0xc150,
+ 0xc151, 0x0000, 0x343a, 0x3b36, 0x0000, 0x0000, 0x4658, 0xc152,
+ 0x0000, 0x0000, 0x0000, 0xc153, 0x3749, 0x0000, 0x0000, 0x0000,
+ 0x3f74, 0x0000, 0x5a4a, 0x0000, 0x4030, 0x4528, 0x0000, 0x495f,
+ 0x5a4b, 0x0000, 0xc154, 0x0000, 0x0000, 0xc155, 0x0000, 0x0000,
+ 0x0000, 0xc156, 0x5a4c, 0x5a4d, 0x0000, 0xc157, 0x0000, 0x4a38,
+ 0x555d, 0x4046, 0xc158, 0x0000, 0x494c, 0x0000, 0x3a58, 0x0000,
+ 0x4865, 0x4843, 0xc159, 0x0000, 0x0000, 0xc15a, 0x0000, 0x454d,
+ 0xc15b, 0x4e41, 0x0000, 0x5a4f, 0x3c50, 0xc15c, 0x0000, 0x5a50,
+ 0xc15d, 0x3036, 0x0000, 0xc15e, 0x3654, 0x404d, 0xc15f, 0x4960,
+ 0x0000, 0x0000, 0x0000, 0x5a51, 0x3b42, 0x4347, 0xc160, 0x3b5b,
+ 0x3f37, 0x0000, 0xc161, 0xc162, 0xc163, 0x0000, 0x0000, 0x5a52,
+ 0x0000, 0x4a7d, 0x0000, 0x0000, 0x3177, 0x3b5c, 0x0000, 0xc164,
+ 0x0000, 0x5a55, 0xc165, 0x5a53, 0x5a56, 0x4e39, 0x5a54, 0x0000,
+ 0xc166, 0xc167, 0x0000, 0x407b, 0x5a57, 0x0000, 0xc168, 0x4232,
+ 0xc169, 0x0000, 0x5a58, 0x0000, 0xc16a, 0x0000, 0xc16b, 0x347a,
+ 0xc16c, 0x5a5a, 0x0000, 0x5a59, 0x0000, 0x0000, 0x0000, 0xc16d,
+ 0x5a5b, 0x5a5c, 0x347b, 0x0000, 0x0000, 0x467c, 0x4336, 0x356c,
+ 0x3b5d, 0x4161, 0x0000, 0x0000, 0x3d5c, 0x3030, 0x0000, 0x0000,
+ 0xc16e, 0x5a5d, 0xc16f, 0x0000, 0xc170, 0xc171, 0x0000, 0x0000,
+ 0x0000, 0xc172, 0x3222, 0x5a61, 0x0000, 0x0000, 0xc173, 0xc174
+};
+
+static const unsigned short jis_from_unicode_66[] = {
+ 0xc175, 0x0000, 0x3937, 0x5a60, 0xc176, 0x0000, 0x3a2b, 0x3e3a,
+ 0xc177, 0xc178, 0x5a5f, 0x0000, 0x3e3b, 0xc179, 0x4c40, 0x3a2a,
+ 0x0000, 0xc17a, 0xc17b, 0x3057, 0x404e, 0xc17c, 0xc17d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5a66, 0xc17e, 0xc221, 0x4031,
+ 0x3147, 0xc222, 0xc223, 0xc224, 0xc225, 0x3d55, 0xc226, 0x4b66,
+ 0x3a72, 0xc227, 0xc228, 0xc229, 0xc22a, 0x3e3c, 0xc22b, 0x4027,
+ 0xc22c, 0xc22d, 0x0000, 0xc22e, 0x5a65, 0x5a63, 0x5a64, 0xc230,
+ 0x0000, 0xc22f, 0x0000, 0x0000, 0x436b, 0x0000, 0x0000, 0x5b26,
+ 0xc231, 0x5a6a, 0x3b7e, 0x3938, 0x5a68, 0xc232, 0xc233, 0x0000,
+ 0x0000, 0x5a69, 0xc234, 0x3f38, 0xc235, 0x0000, 0xc237, 0x5a67,
+ 0x0000, 0xc236, 0x3b2f, 0x0000, 0x0000, 0x0000, 0x0000, 0xc238,
+ 0xc239, 0xc23a, 0x0000, 0xc23b, 0xc23c, 0x5a6c, 0x5a6b, 0x5a70,
+ 0xc23d, 0xc23e, 0x5a71, 0x0000, 0x5a6d, 0x0000, 0x3322, 0x5a6e,
+ 0x5a6f, 0x4855, 0xc240, 0xc241, 0xc242, 0x0000, 0x4961, 0x374a,
+ 0x5a72, 0x0000, 0x0000, 0xc244, 0x4032, 0xc245, 0x3e3d, 0xc247,
+ 0xc248, 0xc249, 0x4352, 0xc24a, 0xc24c, 0x0000, 0xc243, 0xc246,
+ 0xc24b, 0x3647, 0x0000, 0x5a73, 0x5a77, 0x0000, 0x0000, 0x324b,
+ 0x5a74, 0x5a76, 0x0000, 0xc24d, 0xc24e, 0xc24f, 0x5a75, 0x0000,
+ 0xc250, 0x3d6b, 0xc251, 0x0000, 0x0000, 0x0000, 0x4348, 0x3045,
+ 0x5a78, 0xc252, 0xc253, 0xc254, 0xc255, 0x5a79, 0x0000, 0xc256,
+ 0xc257, 0x0000, 0x442a, 0x0000, 0xc258, 0x0000, 0x4e71, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3b43, 0x0000, 0xc259, 0x4a6b, 0x0000,
+ 0x0000, 0xc25a, 0xc25b, 0x0000, 0x4b3d, 0xc25c, 0x0000, 0x0000,
+ 0x5b22, 0x5a7b, 0x0000, 0xc25d, 0x5a7e, 0x0000, 0x5a7d, 0xc25e,
+ 0xc25f, 0x5a7a, 0xc260, 0xc261, 0x5b21, 0x0000, 0x0000, 0x465e,
+ 0xc262, 0x5a7c, 0x0000, 0x0000, 0xc263, 0x0000, 0xc264, 0xc265,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xc266, 0x0000, 0x5b23, 0x0000,
+ 0x0000, 0x3d6c, 0x5b24, 0xc267, 0x4d4b, 0x4778, 0x0000, 0xc268,
+ 0x5b25, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b27, 0x0000,
+ 0xc269, 0x5b28, 0x0000, 0xc26a, 0xc26b, 0x0000, 0xc26c, 0x0000,
+ 0x5b29, 0x0000, 0x364a, 0x3148, 0x3939, 0x5b2a, 0x0000, 0x5b2b,
+ 0x3d71, 0x4162, 0xc26d, 0xc23f, 0x5258, 0x413e, 0x413d, 0x4258
+};
+
+static const unsigned short jis_from_unicode_67[] = {
+ 0x3a47, 0x0000, 0x0000, 0x5072, 0x0000, 0xc26e, 0x0000, 0xc26f,
+ 0x376e, 0x4d2d, 0x0000, 0x4a7e, 0x0000, 0x497e, 0xc270, 0x5b2c,
+ 0x0000, 0x0000, 0x0000, 0xc271, 0x3a73, 0x443f, 0x5b2d, 0x4f2f,
+ 0x0000, 0xc272, 0x0000, 0x4b3e, 0xc273, 0x442b, 0x5b2e, 0x347c,
+ 0xc274, 0x0000, 0xc275, 0x0000, 0x0000, 0x0000, 0x5b2f, 0x5b30,
+ 0x4c5a, 0x0000, 0x4c24, 0x4b76, 0x4b5c, 0x3b25, 0x5b32, 0x0000,
+ 0x0000, 0x3c6b, 0x0000, 0xc276, 0x4b51, 0x0000, 0x5b34, 0x5b37,
+ 0x5b36, 0x0000, 0x3479, 0x0000, 0x0000, 0x3560, 0xc277, 0x5b33,
+ 0x0000, 0x5b35, 0x0000, 0x0000, 0x0000, 0xc278, 0x5b38, 0xc279,
+ 0xc27a, 0x3f79, 0x0000, 0x0000, 0xc27b, 0x0000, 0x4d7b, 0x3049,
+ 0x3a60, 0x423c, 0x0000, 0x3c5d, 0xc27c, 0xc27d, 0x3e73, 0x0000,
+ 0x0000, 0x5b3b, 0x0000, 0x0000, 0x454e, 0xc27e, 0x5b39, 0x422b,
+ 0x5b3a, 0x3e72, 0x4c5d, 0x5b3c, 0x5b3d, 0x4d68, 0xc321, 0x0000,
+ 0x0000, 0x0000, 0x5b42, 0x0000, 0xc322, 0x393a, 0xc323, 0x4755,
+ 0x5b3f, 0x456c, 0x5a5e, 0x5a62, 0xc324, 0x354f, 0xc325, 0x4747,
+ 0x0000, 0x0000, 0x0000, 0xc326, 0x5b41, 0x0000, 0x3e3e, 0x4844,
+ 0x0000, 0xc327, 0x0000, 0x0000, 0xc328, 0x5b47, 0x0000, 0x487a,
+ 0x0000, 0x5b3e, 0x0000, 0x5b44, 0x5b43, 0x0000, 0xc329, 0xc32a,
+ 0x404f, 0xc32b, 0x0000, 0xc32c, 0x0000, 0x4b6d, 0xc32d, 0x4e53,
+ 0xc32e, 0xc32f, 0x4b67, 0xc330, 0x324c, 0x3b5e, 0x0000, 0x0000,
+ 0x4f48, 0x5b46, 0x3f75, 0x0000, 0x0000, 0x0000, 0x5b45, 0x0000,
+ 0x0000, 0x5b40, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x384f,
+ 0xc331, 0xc332, 0xc333, 0x5b4c, 0x5b4a, 0xc334, 0x324d, 0x5b48,
+ 0x5b4e, 0x5b54, 0x0000, 0xc335, 0xc336, 0xc337, 0x0000, 0x0000,
+ 0xc339, 0x4248, 0xc33a, 0xc33b, 0x4a41, 0xc33c, 0x5b56, 0x0000,
+ 0xc33d, 0xc33e, 0x4922, 0x0000, 0x0000, 0x0000, 0x5b55, 0x4770,
+ 0x4b3f, 0x343b, 0xc33f, 0x4077, 0x3d40, 0x0000, 0x0000, 0xc340,
+ 0x4453, 0xc341, 0x4d2e, 0x0000, 0xc342, 0x5b51, 0x5b50, 0x0000,
+ 0x0000, 0xc343, 0x5b52, 0x0000, 0x5b4f, 0x0000, 0xc344, 0x5b57,
+ 0x0000, 0x5b4d, 0x0000, 0x0000, 0x5b4b, 0x0000, 0x5b53, 0x5b49,
+ 0xc345, 0x436c, 0xc346, 0x4c78, 0x3c46, 0x3a74, 0xc347, 0xc348,
+ 0x0000, 0xc338, 0x0000, 0x3a3a, 0x0000, 0x0000, 0x4b6f, 0x3341
+};
+
+static const unsigned short jis_from_unicode_68[] = {
+ 0x0000, 0x0000, 0x444e, 0x464a, 0x3149, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4072, 0xc34a, 0x0000, 0x4034, 0x372a,
+ 0x0000, 0xc34b, 0x0000, 0x0000, 0x0000, 0xc34c, 0x5b59, 0xc34d,
+ 0x0000, 0x393b, 0x337c, 0x0000, 0x0000, 0x0000, 0x0000, 0xc34f,
+ 0xc34e, 0x5b5b, 0x3374, 0x5b61, 0xc350, 0xc351, 0x0000, 0xc352,
+ 0xc353, 0xc354, 0x5b5e, 0xc355, 0x4073, 0x0000, 0x0000, 0x0000,
+ 0x334b, 0x3a2c, 0x0000, 0xc356, 0x334a, 0x3a4f, 0x0000, 0xc357,
+ 0x5b5c, 0x3765, 0x374b, 0x456d, 0xc358, 0xc359, 0x5b5a, 0x0000,
+ 0x3046, 0x0000, 0xc35a, 0x0000, 0xc35b, 0x5b5d, 0x5b5f, 0x0000,
+ 0x364d, 0x372c, 0xc349, 0x343c, 0x354b, 0xc35c, 0x0000, 0xc35d,
+ 0xc35e, 0x5b62, 0x0000, 0xc35f, 0x3a79, 0x4b71, 0x0000, 0x3b37,
+ 0x0000, 0x0000, 0x0000, 0x5b63, 0x0000, 0x0000, 0x0000, 0x4930,
+ 0x0000, 0x0000, 0x0000, 0xc360, 0x0000, 0x0000, 0xc361, 0xc362,
+ 0xc363, 0xc364, 0xc365, 0x0000, 0x5b6f, 0xc366, 0x3233, 0x5b64,
+ 0x0000, 0xc367, 0xc368, 0xc369, 0xc36a, 0x0000, 0x5b75, 0x5b65,
+ 0x0000, 0x4e42, 0xc36b, 0x5b6c, 0xc36c, 0x475f, 0xc36d, 0x0000,
+ 0xc36e, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b74, 0x0000, 0x5b67,
+ 0x0000, 0x0000, 0x0000, 0x3034, 0x5b69, 0x0000, 0xc36f, 0x393c,
+ 0xc370, 0x0000, 0xc371, 0x5b6b, 0xc372, 0x5b6a, 0x0000, 0x5b66,
+ 0x5b71, 0xc373, 0x3e3f, 0xc374, 0x0000, 0xc375, 0x546d, 0x3868,
+ 0x4d7c, 0xc376, 0xc377, 0x0000, 0x0000, 0x5b68, 0xc378, 0x4474,
+ 0x3323, 0x3a2d, 0xc379, 0x5b60, 0x0000, 0x5b70, 0x3361, 0x0000,
+ 0x0000, 0x5b6e, 0x5b72, 0xc37a, 0x456e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x347e, 0xc37b, 0x5c32, 0x0000,
+ 0xc37c, 0x4c49, 0x5b77, 0x347d, 0xc37d, 0x5b7e, 0x0000, 0xc37e,
+ 0xc421, 0xc422, 0x4b40, 0xc423, 0x5c21, 0x5c23, 0xc424, 0x5c27,
+ 0x5b79, 0xc425, 0x432a, 0x0000, 0xc426, 0xc427, 0x0000, 0x456f,
+ 0x5c2b, 0x5b7c, 0x0000, 0x5c28, 0x0000, 0xc428, 0x0000, 0x5c22,
+ 0xc429, 0x0000, 0xc42a, 0xc42b, 0xc42c, 0xc42d, 0x3f39, 0x5c2c,
+ 0xc42e, 0xc42f, 0x4033, 0x0000, 0x0000, 0xc430, 0xc431, 0x0000,
+ 0x0000, 0x5c2a, 0x343d, 0xc432, 0xc433, 0xc434, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_69[] = {
+ 0x4f50, 0x5b76, 0x0000, 0x0000, 0x5c26, 0x3058, 0xc435, 0x0000,
+ 0x5b78, 0xc436, 0xc437, 0x4c3a, 0x5b7d, 0x3f22, 0x4447, 0x5b73,
+ 0xc438, 0xc439, 0x5c25, 0xc43a, 0x0000, 0x0000, 0xc43b, 0xc43c,
+ 0x0000, 0x3f7a, 0x5c2f, 0x3371, 0x3821, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5c31, 0x5b7a, 0x5c30, 0x0000, 0x5c29, 0x5b7b, 0x0000,
+ 0x5c2d, 0x0000, 0x5c2e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5c3f, 0xc43d, 0x0000, 0xc43e, 0x464e, 0xc43f, 0x5c24, 0x0000,
+ 0xc440, 0x5c3b, 0x0000, 0xc441, 0x0000, 0x5c3d, 0x0000, 0x4458,
+ 0x0000, 0x0000, 0xc442, 0x0000, 0x0000, 0xc443, 0x0000, 0x0000,
+ 0x0000, 0xc444, 0x4d4c, 0x0000, 0x0000, 0x0000, 0xc445, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4976, 0x5c38, 0x424a, 0x0000, 0xc446,
+ 0x0000, 0x5c3e, 0x413f, 0xc447, 0x5c35, 0x5c42, 0x5c41, 0x0000,
+ 0x466f, 0x5c40, 0x466a, 0xc448, 0xc449, 0xc44a, 0xc44b, 0x0000,
+ 0xc44c, 0xc44d, 0x5c44, 0x5c37, 0xc44e, 0x3648, 0x5c3a, 0x3d5d,
+ 0xc44f, 0xc450, 0xc451, 0x4760, 0x5c3c, 0x364b, 0x0000, 0x5c34,
+ 0x5c36, 0x5c33, 0xc452, 0xc453, 0x4f30, 0x335a, 0x5c39, 0xc454,
+ 0xc455, 0x5c43, 0x3335, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3a67, 0x0000, 0x0000, 0xc456, 0x315d, 0x0000,
+ 0x0000, 0x5c54, 0xc457, 0x0000, 0x4f31, 0x5c57, 0xc458, 0x0000,
+ 0xc459, 0x0000, 0x0000, 0x3f3a, 0x5c56, 0x0000, 0x0000, 0x0000,
+ 0x5c55, 0xc45a, 0x0000, 0x0000, 0x0000, 0xc45b, 0xc45c, 0x5c52,
+ 0xc45d, 0x0000, 0x0000, 0xc45e, 0x0000, 0xc45f, 0x5c46, 0xc460,
+ 0x0000, 0x5c63, 0x5c45, 0x0000, 0x5c58, 0x0000, 0x0000, 0xc461,
+ 0xc462, 0x0000, 0xc463, 0x5c50, 0xc464, 0x0000, 0x5c4b, 0x5c48,
+ 0x0000, 0x5c49, 0x0000, 0x5c51, 0x0000, 0xc465, 0x0000, 0x7422,
+ 0xc466, 0x0000, 0x5c4e, 0x393d, 0x4448, 0x4164, 0x5c4c, 0x0000,
+ 0x5c47, 0xc467, 0x0000, 0x5c4a, 0x0000, 0x0000, 0xc468, 0xc469,
+ 0x4d4d, 0x4b6a, 0x0000, 0x0000, 0x0000, 0x5c4f, 0x5c59, 0x0000,
+ 0x0000, 0x0000, 0xc46a, 0x0000, 0x0000, 0xc46b, 0x0000, 0x5c61,
+ 0x5c5a, 0x0000, 0x0000, 0x5c67, 0x0000, 0x5c65, 0xc46c, 0xc46d,
+ 0x0000, 0xc46e, 0x5c60, 0xc46f, 0x0000, 0xc470, 0x0000, 0x0000,
+ 0x0000, 0x5c5f, 0x0000, 0x4450, 0x0000, 0x4165, 0xc471, 0x5c5d
+};
+
+static const unsigned short jis_from_unicode_6a[] = {
+ 0xc472, 0xc473, 0x5c5b, 0xc474, 0x0000, 0x5c62, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5c68, 0x4875, 0x5c6e, 0x0000, 0x0000, 0xc475,
+ 0x0000, 0xc476, 0x5c69, 0x5c6c, 0x5c66, 0xc477, 0x0000, 0x4374,
+ 0x0000, 0x4938, 0xc478, 0x5c5c, 0x0000, 0xc479, 0x5c64, 0x3e40,
+ 0xc47a, 0x4c4f, 0x5c78, 0x5c6b, 0xc47b, 0x0000, 0x0000, 0x0000,
+ 0xc47c, 0x3822, 0x3223, 0x335f, 0x0000, 0x0000, 0x5c53, 0x0000,
+ 0xc47d, 0x0000, 0xc47e, 0x0000, 0xc521, 0x3e41, 0x5c70, 0xc522,
+ 0x5c77, 0x3c79, 0x3372, 0xc523, 0x0000, 0x432e, 0xc524, 0xc525,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5c6d, 0xc526, 0xc527, 0x5c72,
+ 0x5c76, 0xc528, 0xc529, 0x3636, 0x0000, 0x0000, 0xc52a, 0x0000,
+ 0xc52b, 0xc52c, 0xc52d, 0x0000, 0x0000, 0xc52e, 0xc52f, 0x0000,
+ 0x354c, 0x5c74, 0x0000, 0xc530, 0x0000, 0x0000, 0x0000, 0x3521,
+ 0x0000, 0x464b, 0x5c73, 0x0000, 0xc531, 0x0000, 0x5c75, 0xc532,
+ 0x0000, 0x0000, 0xc533, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc534, 0x5c6f, 0xc535, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5c71, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc536, 0x3360,
+ 0x4349, 0xc537, 0x0000, 0xc538, 0x5c7c, 0x0000, 0xc539, 0xc53a,
+ 0x0000, 0xc53b, 0x0000, 0xc53c, 0x0000, 0x5c7a, 0x3869, 0x0000,
+ 0x5c79, 0xc53d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5d21,
+ 0x0000, 0x0000, 0x0000, 0xc53e, 0x5b58, 0xc53f, 0xc540, 0xc541,
+ 0x5c7b, 0x0000, 0x5c7d, 0x5c7e, 0x0000, 0xc542, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5d2c, 0xc543, 0x5d28, 0x0000, 0x5b6d, 0xc544,
+ 0xc545, 0xc546, 0x0000, 0x5d27, 0xc547, 0x0000, 0x0000, 0x0000,
+ 0x5d26, 0x0000, 0x0000, 0x5d23, 0x0000, 0xc548, 0xc549, 0xc54a,
+ 0x0000, 0x5c6a, 0x5d25, 0x5d24, 0x0000, 0x0000, 0xc54b, 0x0000,
+ 0xc54d, 0xc54c, 0x0000, 0x0000, 0xc54e, 0x0000, 0x0000, 0x0000,
+ 0xc54f, 0x5d2a, 0x0000, 0x4f26, 0xc550, 0xc551, 0xc552, 0x0000,
+ 0x0000, 0x0000, 0x5d2d, 0x367b, 0xc553, 0xc554, 0x5d29, 0x5d2b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xc555, 0x0000, 0x0000, 0xc556,
+ 0x4827, 0x0000, 0x5d2e, 0x0000, 0xc557, 0x0000, 0x0000, 0x0000,
+ 0xc558, 0xc559, 0xc55a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5d32, 0x5d2f, 0xc55b, 0xc55c, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_6b[] = {
+ 0x0000, 0x0000, 0xc55d, 0xc55e, 0x4d73, 0x5d30, 0xc55f, 0xc560,
+ 0x0000, 0xc561, 0x5c5e, 0x0000, 0x0000, 0x0000, 0x0000, 0xc562,
+ 0xc563, 0xc564, 0x5d33, 0x0000, 0x0000, 0x0000, 0x5d34, 0xc565,
+ 0x0000, 0x0000, 0x0000, 0xc566, 0x0000, 0x3135, 0xc567, 0x5d36,
+ 0x3767, 0x3c21, 0x0000, 0x3655, 0xc568, 0x0000, 0x0000, 0x3224,
+ 0xc569, 0x0000, 0x0000, 0xc56a, 0xc56b, 0x0000, 0x0000, 0xc56c,
+ 0x0000, 0x0000, 0x4d5f, 0x0000, 0x0000, 0xc56d, 0xc56e, 0x5d38,
+ 0x5d37, 0x5d3a, 0x353d, 0xc56f, 0x0000, 0x3656, 0x343e, 0xc570,
+ 0x0000, 0x0000, 0x0000, 0x5d3d, 0x0000, 0x0000, 0xc571, 0x5d3c,
+ 0x0000, 0x5d3e, 0xc572, 0x0000, 0x324e, 0xc573, 0x4337, 0x0000,
+ 0x5d3f, 0x0000, 0xc574, 0x343f, 0x5d41, 0x0000, 0xc575, 0x0000,
+ 0xc576, 0x5d40, 0x0000, 0x5d42, 0x0000, 0xc577, 0x0000, 0x5d43,
+ 0xc578, 0x5d44, 0x3b5f, 0x4035, 0x3a21, 0x0000, 0x4970, 0xc579,
+ 0x0000, 0x4a62, 0x4f44, 0xc57a, 0x0000, 0x0000, 0xc57b, 0x3b75,
+ 0xc57c, 0x0000, 0x0000, 0x3a50, 0x4e72, 0xc57d, 0x0000, 0x0000,
+ 0x5d45, 0x5d46, 0x0000, 0x3b60, 0x0000, 0xc57e, 0xc621, 0x5d47,
+ 0x5d48, 0x0000, 0xc622, 0x5d4a, 0x5d49, 0xc623, 0x4b58, 0x0000,
+ 0x0000, 0x3d5e, 0x3c6c, 0x3b44, 0x0000, 0x5d4b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5d4d, 0x3f23, 0xc624,
+ 0x5d4c, 0x0000, 0x0000, 0xc625, 0x0000, 0x0000, 0x5d4e, 0xc626,
+ 0xc627, 0x0000, 0xc628, 0xc629, 0x5d4f, 0x0000, 0x0000, 0x0000,
+ 0xc62a, 0xc62b, 0x5d50, 0x5d51, 0xc62c, 0xc62d, 0xc62e, 0x5d52,
+ 0xc62f, 0x5d54, 0x5d53, 0x5d55, 0x3225, 0x434a, 0x0000, 0x5d56,
+ 0xc630, 0xc631, 0x3b26, 0x334c, 0x5d57, 0xc632, 0xc633, 0x4542,
+ 0x544c, 0x0000, 0x0000, 0xc634, 0xc635, 0x3523, 0x5d58, 0x0000,
+ 0x0000, 0xc636, 0x0000, 0x5d59, 0xc637, 0x4a6c, 0x4b68, 0x0000,
+ 0x0000, 0x0000, 0x4647, 0x5d5a, 0x4866, 0x0000, 0xc638, 0x0000,
+ 0x487b, 0x0000, 0xc639, 0x4c53, 0x0000, 0x0000, 0x0000, 0x5d5b,
+ 0x0000, 0xc63a, 0x0000, 0xc63b, 0x0000, 0x0000, 0xc63c, 0xc63d,
+ 0x0000, 0x0000, 0x0000, 0x5d5d, 0x5d5c, 0x0000, 0xc63e, 0x5d5f,
+ 0x0000, 0xc63f, 0x0000, 0x5d5e, 0x0000, 0x0000, 0x0000, 0xc640,
+ 0x0000, 0xc641, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc642
+};
+
+static const unsigned short jis_from_unicode_6c[] = {
+ 0x0000, 0x0000, 0xc643, 0x0000, 0xc644, 0xc645, 0x0000, 0x0000,
+ 0x5d61, 0xc646, 0x0000, 0x0000, 0x0000, 0xc647, 0xc648, 0x3b61,
+ 0xc649, 0x4c31, 0xc64a, 0x5d62, 0x5d63, 0x0000, 0x0000, 0x3524,
+ 0x0000, 0xc64b, 0x0000, 0x5d64, 0x0000, 0x0000, 0x0000, 0xc64c,
+ 0x0000, 0x0000, 0x0000, 0x5d66, 0x5d65, 0x0000, 0xc64d, 0xc64e,
+ 0xc64f, 0x0000, 0x0000, 0x0000, 0xc650, 0x0000, 0xc651, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xc652, 0x3f65, 0xc653, 0xc654, 0x4939,
+ 0x314a, 0x0000, 0xc655, 0xc656, 0x0000, 0x0000, 0x4845, 0xc657,
+ 0x4475, 0x3d41, 0x3561, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xc658, 0xc659, 0x0000, 0xc65a, 0x4846, 0xc65b,
+ 0x3c2e, 0x0000, 0xc65c, 0x0000, 0xc65d, 0x5d68, 0x0000, 0x3440,
+ 0x0000, 0xc65e, 0x3178, 0xc65f, 0xc660, 0x4672, 0x5d67, 0x393e,
+ 0x4353, 0x0000, 0x5d69, 0x0000, 0x0000, 0x0000, 0x0000, 0xc736,
+ 0x5d71, 0x0000, 0x5d6a, 0xc661, 0x0000, 0xc662, 0x0000, 0xc663,
+ 0x4241, 0x0000, 0x3562, 0x5d72, 0xc664, 0x0000, 0xc665, 0x0000,
+ 0xc666, 0xc667, 0x3768, 0xc668, 0x0000, 0x3525, 0x5d70, 0x0000,
+ 0x0000, 0x5d6e, 0x5d6b, 0x4d60, 0x0000, 0xc669, 0xc66a, 0xc66b,
+ 0x4440, 0xc66c, 0x0000, 0x0000, 0x4659, 0x5d6c, 0x0000, 0x0000,
+ 0x5d74, 0x0000, 0x5d73, 0x3723, 0xc66d, 0xc66e, 0x322d, 0xc66f,
+ 0xc670, 0x3a3b, 0x5d6d, 0x5d6f, 0xc671, 0x0000, 0x0000, 0xc672,
+ 0x0000, 0x4b57, 0x4274, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4b77, 0x0000, 0x0000, 0x5d7c, 0x0000,
+ 0xc673, 0x5d7d, 0xc674, 0x324f, 0xc675, 0x0000, 0x0000, 0x0000,
+ 0x4a28, 0x4c7d, 0x5e21, 0x3c23, 0x3e42, 0x5d78, 0x5d7e, 0x3168,
+ 0x0000, 0x3637, 0xc676, 0x0000, 0x5d75, 0x5d7a, 0xc677, 0x0000,
+ 0x0000, 0x4074, 0x4771, 0x0000, 0x4867, 0xc678, 0x0000, 0xc679,
+ 0xc67a, 0xc67b, 0xc67c, 0x5d77, 0xc67d, 0x4b21, 0xc67e, 0x5d79,
+ 0x0000, 0x5e24, 0xc721, 0x5e22, 0xc722, 0x5d7b, 0x0000, 0x0000,
+ 0xc723, 0x4b22, 0x4748, 0x3563, 0x0000, 0x4525, 0x0000, 0xc724,
+ 0x436d, 0xc725, 0x5e25, 0xc726, 0xc727, 0x0000, 0xc728, 0x5e23,
+ 0x4259, 0x5d76, 0xc729, 0x314b, 0xc72a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_6d[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xc72b, 0x0000, 0x0000, 0xc72c,
+ 0x0000, 0x0000, 0xc72d, 0x4d4e, 0x5e30, 0x0000, 0xc72e, 0xc72f,
+ 0x0000, 0xc730, 0x5e2f, 0xc731, 0x0000, 0x0000, 0x0000, 0x4076,
+ 0x0000, 0x5e2c, 0xc732, 0x4d6c, 0x0000, 0x0000, 0x4636, 0x5e26,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4445, 0xc733, 0xc734,
+ 0xc735, 0x314c, 0x393f, 0x5e29, 0x0000, 0x0000, 0xc737, 0xc738,
+ 0x0000, 0xc739, 0x3d27, 0x5e2e, 0x0000, 0x5e2d, 0x5e28, 0x0000,
+ 0x5e2b, 0xc73a, 0x0000, 0x3368, 0xc73b, 0x5e2a, 0x4749, 0xc73c,
+ 0x0000, 0x4e2e, 0x0000, 0x0000, 0x3e74, 0x4075, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc73d,
+ 0x0000, 0x5e36, 0x5e34, 0x0000, 0x494d, 0x0000, 0xc73e, 0xc73f,
+ 0x0000, 0xc740, 0x0000, 0x5e31, 0x5e33, 0xc741, 0x313a, 0xc742,
+ 0x0000, 0x3940, 0x4f32, 0x0000, 0x333d, 0x0000, 0x4962, 0xc743,
+ 0xc744, 0x0000, 0x0000, 0x0000, 0x4d61, 0x0000, 0x0000, 0x3324,
+ 0x3f3b, 0x5e35, 0x0000, 0x0000, 0xc745, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xc746, 0x0000, 0x0000, 0x5e3a, 0x0000, 0xc747,
+ 0x3e43, 0x0000, 0x0000, 0x0000, 0x4d30, 0x0000, 0x5e37, 0x0000,
+ 0x0000, 0xc748, 0xc749, 0x5e32, 0xc74a, 0x5e38, 0xc74b, 0xc74c,
+ 0xc74d, 0x4e5e, 0x0000, 0x4573, 0x4642, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xc74e, 0x0000, 0xc74f, 0x0000, 0x0000, 0x3336,
+ 0x0000, 0x0000, 0x3155, 0x0000, 0xc750, 0x5e3e, 0x0000, 0xc751,
+ 0x5e41, 0xc752, 0x0000, 0x0000, 0x4e43, 0xc753, 0x0000, 0xc754,
+ 0x4d64, 0x0000, 0x0000, 0x0000, 0xc755, 0x5e48, 0x5e42, 0x5e3f,
+ 0xc756, 0x0000, 0xc757, 0x4e54, 0x5e45, 0x0000, 0xc758, 0xc759,
+ 0x0000, 0x3d4a, 0x5e47, 0x0000, 0x0000, 0x5e4c, 0xc75a, 0x0000,
+ 0x4571, 0x5e4a, 0x0000, 0xc75b, 0x0000, 0xc75c, 0x5e44, 0xc75d,
+ 0xc75e, 0x4338, 0xc75f, 0x0000, 0x5e4b, 0xc760, 0x5e40, 0x0000,
+ 0x5e46, 0xc761, 0x5e4d, 0x307c, 0x5e43, 0x0000, 0x5e4e, 0xc762,
+ 0xc763, 0x3f3c, 0x0000, 0x3d5f, 0xc764, 0x4a25, 0xc765, 0x3a2e,
+ 0x0000, 0x5e3b, 0x5e49, 0x453a, 0xc766, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_6e[] = {
+ 0xc767, 0x0000, 0x0000, 0x0000, 0xc768, 0x4036, 0x0000, 0x3369,
+ 0x3a51, 0x3e44, 0x5e3d, 0x3d42, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x374c, 0x0000, 0x5e3c, 0x0000, 0x0000,
+ 0x0000, 0x5e52, 0x3d6d, 0x383a, 0x0000, 0x5e61, 0xc769, 0x5e5b,
+ 0x3574, 0x454f, 0xc76a, 0x5e56, 0x5e5f, 0x302f, 0x3132, 0xc76b,
+ 0x0000, 0x3239, 0x0000, 0x5e58, 0x422c, 0x5e4f, 0x5e51, 0x3941,
+ 0x0000, 0x0000, 0xc76c, 0x0000, 0x0000, 0x0000, 0xc76d, 0x0000,
+ 0x5e62, 0xc76e, 0x5e5d, 0xc76f, 0xc770, 0x0000, 0x5e55, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5e5c, 0xc771, 0xc772, 0x0000, 0x0000,
+ 0xc773, 0xc774, 0x4c2b, 0xc775, 0x0000, 0x5e5a, 0x5e5e, 0xc776,
+ 0x0000, 0xc777, 0xc778, 0xc779, 0xc77a, 0x0000, 0x3850, 0xc77b,
+ 0x3e45, 0x0000, 0x0000, 0x4339, 0xc77c, 0xc77d, 0xc77e, 0x5e54,
+ 0x0000, 0x0000, 0xc821, 0xc822, 0x0000, 0x0000, 0x0000, 0x4d2f,
+ 0xc823, 0x0000, 0x0000, 0x5e57, 0x0000, 0x0000, 0x5e50, 0x4572,
+ 0x0000, 0x0000, 0x5e53, 0xc824, 0x0000, 0x0000, 0x5e59, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xc825, 0x0000, 0xc826, 0x4f51, 0x3c3e,
+ 0x4b7e, 0x0000, 0x5e63, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x482e, 0xc827, 0x0000, 0x5e6f,
+ 0x383b, 0x0000, 0x0000, 0xc828, 0x0000, 0x0000, 0x3d60, 0x0000,
+ 0x5e65, 0xc829, 0x0000, 0x0000, 0x4e2f, 0x3942, 0x0000, 0x5e72,
+ 0xc82a, 0x0000, 0x306e, 0x0000, 0x0000, 0x5e70, 0x0000, 0xc82b,
+ 0x0000, 0x0000, 0x5e64, 0x0000, 0x0000, 0xc82c, 0xc82d, 0x5e6a,
+ 0x0000, 0xc82e, 0x5e6c, 0xc82f, 0x0000, 0x0000, 0x4d4f, 0x5e67,
+ 0x0000, 0x0000, 0x452e, 0xc830, 0x0000, 0x5e69, 0x0000, 0xc831,
+ 0xc832, 0xc833, 0x5e71, 0xc834, 0x5e6b, 0x4c47, 0x0000, 0xc835,
+ 0xc836, 0x5e66, 0xc837, 0x3c22, 0x5e7e, 0xc838, 0xc839, 0xc83a,
+ 0x0000, 0x336a, 0x0000, 0x5e68, 0x5e6d, 0x5e6e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x426c, 0x425a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xc83b, 0x5e76, 0xc83c, 0xc83d, 0x5e7c,
+ 0x0000, 0x0000, 0x5e7a, 0x0000, 0x4529, 0x0000, 0x0000, 0x5f23,
+ 0x5e77, 0xc83e, 0x0000, 0xc83f, 0x0000, 0xc840, 0x5e78, 0x5e60
+};
+
+static const unsigned short jis_from_unicode_6f[] = {
+ 0x0000, 0x3579, 0x493a, 0x0000, 0xc841, 0x0000, 0x3c3f, 0x0000,
+ 0xc842, 0x3977, 0xc843, 0x0000, 0xc844, 0xc845, 0x0000, 0x4f33,
+ 0x0000, 0x5e74, 0x0000, 0x5f22, 0x3169, 0x4166, 0xc846, 0x0000,
+ 0xc847, 0x0000, 0xc848, 0xc849, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4779, 0x0000, 0x3441, 0x4e7a, 0x0000, 0x0000, 0xc84a, 0x0000,
+ 0x0000, 0xc84b, 0xc84c, 0x4c21, 0x4452, 0xc853, 0x0000, 0xc84d,
+ 0xc84e, 0x5e7b, 0x5e7d, 0xc84f, 0x0000, 0x0000, 0xc850, 0x0000,
+ 0x4132, 0x0000, 0x0000, 0xc851, 0xc852, 0x0000, 0x5f21, 0x5e79,
+ 0x0000, 0x5e73, 0x0000, 0x0000, 0x0000, 0x3443, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc854,
+ 0x0000, 0xc855, 0xc856, 0xc857, 0x3769, 0x0000, 0x0000, 0xc858,
+ 0x5f2f, 0xc859, 0xc85a, 0x5f2a, 0x4078, 0xc85b, 0xc85c, 0x3363,
+ 0x0000, 0xc85d, 0xc85e, 0x0000, 0x3d61, 0x0000, 0x5f33, 0x0000,
+ 0xc85f, 0x0000, 0x0000, 0x0000, 0xc860, 0x5f2c, 0x442c, 0x5f29,
+ 0x4459, 0x0000, 0x0000, 0x0000, 0x5f4c, 0x0000, 0x0000, 0x0000,
+ 0x5f26, 0x0000, 0x5f25, 0x0000, 0x5f2e, 0xc861, 0xc862, 0x0000,
+ 0x5f28, 0x5f27, 0x5f2d, 0xc863, 0x4021, 0x0000, 0x5f24, 0xc864,
+ 0xc865, 0x0000, 0x0000, 0xc866, 0xc867, 0xc868, 0x5f30, 0x0000,
+ 0xc869, 0x5f31, 0xc86a, 0xc86b, 0xc86c, 0x0000, 0xc86d, 0x3442,
+ 0x0000, 0x0000, 0xc86e, 0x0000, 0x0000, 0x0000, 0x0000, 0xc86f,
+ 0xc870, 0x5f36, 0x0000, 0x5f35, 0x5f37, 0xc871, 0xc872, 0xc873,
+ 0xc874, 0x0000, 0x5f3a, 0x0000, 0x0000, 0x0000, 0xc875, 0xc876,
+ 0xc877, 0x4543, 0x0000, 0x5f34, 0x0000, 0xc878, 0xc879, 0x0000,
+ 0x0000, 0x5f38, 0x0000, 0x0000, 0xc87a, 0x0000, 0x0000, 0x0000,
+ 0x3763, 0x4279, 0x5f32, 0x473b, 0x0000, 0xc87b, 0x5f39, 0xc87c,
+ 0xc87d, 0x0000, 0xc87e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5f3e, 0x5f3c, 0x0000, 0x0000,
+ 0x5f3f, 0x0000, 0xc921, 0x5f42, 0x0000, 0x0000, 0xc922, 0x5f3b,
+ 0x396a, 0x4728, 0x0000, 0x0000, 0x5e39, 0x0000, 0x0000, 0x0000,
+ 0xc923, 0xc924, 0x0000, 0x4d74, 0x5f3d, 0x0000, 0x5f41, 0x4275,
+ 0xc925, 0x5f40, 0x0000, 0x5f2b, 0x0000, 0xc926, 0x6f69, 0x0000,
+ 0x0000, 0xc927, 0x5f45, 0x0000, 0xc928, 0xc929, 0x5f49, 0x0000
+};
+
+static const unsigned short jis_from_unicode_70[] = {
+ 0xc92a, 0x5f47, 0x0000, 0x0000, 0x0000, 0xc92b, 0xc92c, 0xc92d,
+ 0x0000, 0x5f43, 0x0000, 0x5f44, 0x0000, 0xc92e, 0x0000, 0x5f48,
+ 0x0000, 0x5f46, 0x0000, 0x0000, 0x0000, 0x494e, 0x0000, 0xc92f,
+ 0x5f4e, 0x0000, 0x5f4b, 0x5f4a, 0x0000, 0x5f4d, 0x4654, 0x5f4f,
+ 0xc930, 0x0000, 0x0000, 0xc931, 0x0000, 0x0000, 0x4375, 0x426d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4025, 0x0000, 0x0000, 0xc932,
+ 0x5f50, 0x0000, 0x5f52, 0x0000, 0xc933, 0x0000, 0x0000, 0xc934,
+ 0x0000, 0xc935, 0x0000, 0x0000, 0xc936, 0x0000, 0x5f51, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xc937, 0xc938, 0x0000, 0x0000, 0x0000,
+ 0xc939, 0xc93a, 0xc93b, 0xc93c, 0x5e75, 0x0000, 0xc941, 0x0000,
+ 0x0000, 0x5f53, 0x0000, 0x0000, 0xc93d, 0xc93e, 0x0000, 0x0000,
+ 0x4667, 0x0000, 0x0000, 0x0000, 0x0000, 0xc93f, 0xc940, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5f54, 0xc942, 0xc943, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3250, 0xc944, 0x0000, 0xc945, 0x4574,
+ 0x3325, 0x0000, 0x0000, 0x0000, 0x0000, 0xc946, 0xc947, 0x0000,
+ 0x3564, 0x0000, 0x0000, 0x0000, 0x3c5e, 0x3a52, 0xc948, 0x0000,
+ 0x0000, 0xc949, 0x0000, 0x0000, 0x0000, 0xc94a, 0xc94b, 0x0000,
+ 0x0000, 0x4f27, 0x3f66, 0x0000, 0x0000, 0x0000, 0x316a, 0x0000,
+ 0x0000, 0x0000, 0x5f56, 0x0000, 0xc94c, 0xc94d, 0xc94e, 0xc94f,
+ 0xc950, 0x5f55, 0x0000, 0xc951, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xc952, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xc953, 0x5f59, 0x433a, 0x5f5c, 0x5f57,
+ 0xc954, 0xc955, 0x0000, 0x5f5b, 0xc956, 0x0000, 0x0000, 0xc957,
+ 0x5f5a, 0x4540, 0x3059, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4e75, 0x0000, 0xc958, 0x5f5e, 0x0000, 0x0000, 0x0000, 0x3128,
+ 0x0000, 0xc959, 0x0000, 0xc95a, 0xc95b, 0xc95c, 0xc95d, 0x0000,
+ 0xc95e, 0x5f60, 0x0000, 0x0000, 0xc95f, 0x5f5f, 0x0000, 0x5f5d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xc960, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5f58, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4b23, 0xc961, 0x0000, 0x0000, 0x5f62, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_71[] = {
+ 0x0000, 0x0000, 0x0000, 0xc962, 0xc963, 0xc964, 0xc965, 0xc966,
+ 0x0000, 0x5f61, 0x0000, 0xc967, 0xc968, 0x0000, 0x0000, 0xc969,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x316b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5f64, 0x4a32, 0x0000, 0x5f63, 0x0000, 0xc96a, 0x0000,
+ 0xc96b, 0x4c35, 0x0000, 0x0000, 0x0000, 0x0000, 0x3e47, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xc96c, 0x0000, 0xc96d, 0x0000, 0xc96e,
+ 0xc96f, 0xc970, 0x0000, 0x0000, 0x0000, 0x0000, 0x4133, 0x0000,
+ 0xc971, 0x0000, 0x0000, 0x0000, 0x3e46, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc972, 0x0000, 0x0000, 0x0000, 0xc973, 0xc974, 0xc975,
+ 0x0000, 0x4e7b, 0xc976, 0xc977, 0x5f6a, 0x0000, 0x4079, 0x0000,
+ 0xc978, 0x0000, 0xc979, 0x0000, 0x0000, 0x5f66, 0x5f6b, 0xc97a,
+ 0x0000, 0x316c, 0xc97b, 0x0000, 0xc97c, 0x0000, 0xc97d, 0x0000,
+ 0xc97e, 0x0000, 0x5f69, 0x0000, 0x4761, 0x5f65, 0x5f68, 0x3e48,
+ 0xca21, 0x4851, 0x0000, 0x0000, 0x5f6c, 0x0000, 0x3c51, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xca22, 0x0000, 0x0000, 0x0000, 0x407a, 0x0000, 0x0000,
+ 0xca23, 0x0000, 0x0000, 0x0000, 0x5f6f, 0xca24, 0x0000, 0xca25,
+ 0x5f67, 0x0000, 0x3727, 0x0000, 0xca26, 0x0000, 0x0000, 0x5f6d,
+ 0x0000, 0x0000, 0xca27, 0x0000, 0x4d50, 0x5f70, 0x0000, 0x0000,
+ 0x0000, 0x7426, 0xca28, 0xca29, 0x0000, 0x0000, 0x0000, 0x3d4f,
+ 0xca2a, 0x0000, 0xca2b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5f71, 0x0000, 0x0000, 0x0000, 0x5f72, 0x0000, 0x0000, 0xca2c,
+ 0xca2d, 0x472e, 0xca2e, 0xca2f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5f74, 0xca30, 0x0000, 0x0000, 0x0000, 0x5f75, 0xca31,
+ 0xca32, 0xca33, 0x0000, 0x4733, 0xca34, 0x0000, 0x0000, 0x0000,
+ 0x4575, 0x5f77, 0x0000, 0xca35, 0xca36, 0x0000, 0x5f79, 0x0000,
+ 0x4e55, 0x0000, 0x5f76, 0xca37, 0x5f78, 0x316d, 0xca38, 0x5f73,
+ 0x0000, 0xca39, 0xca3a, 0x0000, 0xca3b, 0x0000, 0x0000, 0x535b,
+ 0x5f7a, 0x0000, 0x0000, 0x0000, 0x0000, 0x4167, 0x3b38, 0x5f7c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5f7b, 0x3f24, 0x5259, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f7d, 0x0000, 0x0000,
+ 0xca3c, 0x6021, 0x0000, 0x5f6e, 0x5f7e, 0x0000, 0xca3d, 0x6022
+};
+
+static const unsigned short jis_from_unicode_72[] = {
+ 0xca3e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x477a, 0xca3f,
+ 0xca40, 0xca41, 0x0000, 0x0000, 0x0000, 0x6023, 0x0000, 0x0000,
+ 0x6024, 0x0000, 0x0000, 0xca42, 0x0000, 0x0000, 0x0000, 0xca43,
+ 0x0000, 0x0000, 0xca44, 0x6025, 0x0000, 0xca45, 0x0000, 0xca46,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xca47, 0x0000, 0x0000, 0x0000,
+ 0x6026, 0x0000, 0x445e, 0xca48, 0x6028, 0x6027, 0x0000, 0xca49,
+ 0x6029, 0x0000, 0x602a, 0x0000, 0xca4a, 0x3c5f, 0x4963, 0x0000,
+ 0xca4b, 0xca4c, 0x4c6c, 0x602b, 0x602c, 0x4156, 0x3c24, 0x602d,
+ 0x602e, 0xca4d, 0xca4e, 0xca4f, 0x0000, 0xca50, 0x602f, 0x4a52,
+ 0x4847, 0x0000, 0x0000, 0x6030, 0x4757, 0x0000, 0xca51, 0xca52,
+ 0xca53, 0x0000, 0x442d, 0xca54, 0x0000, 0xca55, 0xca56, 0x0000,
+ 0x6031, 0x3267, 0xca57, 0x356d, 0xca58, 0x4c46, 0xca59, 0x4c36,
+ 0xca5a, 0x3234, 0x4f34, 0xca5b, 0x0000, 0x0000, 0x0000, 0x4b52,
+ 0xca5c, 0x4a2a, 0x0000, 0xca5d, 0x0000, 0x0000, 0xca5e, 0xca5f,
+ 0x0000, 0xca60, 0x4037, 0x0000, 0x6032, 0x0000, 0x0000, 0xca61,
+ 0xca62, 0x4643, 0x0000, 0xca63, 0xca64, 0x3823, 0x6033, 0xca65,
+ 0x3a54, 0x6035, 0x6034, 0x0000, 0xca66, 0x0000, 0x0000, 0x6036,
+ 0x0000, 0xca67, 0x0000, 0x0000, 0x0000, 0xca68, 0xca69, 0x0000,
+ 0x0000, 0x0000, 0x6037, 0xca6a, 0x0000, 0x0000, 0x6038, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xca6b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x353e, 0x0000, 0x6039, 0x0000, 0x0000, 0x0000, 0x0000, 0x603a,
+ 0xca6c, 0x0000, 0x0000, 0x0000, 0x3824, 0xca6d, 0xca6e, 0x4848,
+ 0x0000, 0xca6f, 0x603c, 0x0000, 0xca70, 0x0000, 0x3e75, 0x0000,
+ 0x0000, 0x603b, 0x0000, 0x0000, 0x0000, 0x0000, 0xca71, 0x0000,
+ 0x0000, 0xca72, 0x3638, 0x603d, 0x603f, 0x0000, 0x603e, 0xca73,
+ 0x0000, 0xca74, 0x0000, 0x0000, 0xca75, 0x0000, 0x6040, 0x0000,
+ 0x3851, 0x0000, 0x6041, 0x0000, 0x0000, 0xca76, 0xca77, 0x3669,
+ 0xca78, 0x4140, 0x0000, 0x397d, 0x0000, 0x0000, 0x0000, 0xca79,
+ 0x6043, 0x6044, 0x6042, 0x0000, 0x0000, 0xca7a, 0x0000, 0x0000,
+ 0x0000, 0x3c6d, 0x0000, 0x0000, 0x4648, 0x3639, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xca7b, 0xca7c, 0x0000, 0x0000, 0x6046,
+ 0x432c, 0x6045, 0xca7d, 0xca7e, 0x4f35, 0x4762, 0xcb21, 0x0000
+};
+
+static const unsigned short jis_from_unicode_73[] = {
+ 0x0000, 0x0000, 0xcb22, 0x0000, 0xcb23, 0xcb24, 0x0000, 0xcb25,
+ 0x0000, 0x0000, 0x6049, 0xcb26, 0x0000, 0xcb27, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xcb28, 0xcb29, 0x0000, 0x0000, 0x604b, 0x6048,
+ 0xcb2a, 0xcb2b, 0x0000, 0x4c54, 0x604a, 0x604c, 0xcb2c, 0x4e44,
+ 0x0000, 0x0000, 0xcb2d, 0x0000, 0xcb2e, 0x6050, 0x0000, 0xcb2f,
+ 0xcb30, 0x604f, 0x4376, 0x472d, 0xcb31, 0x0000, 0x3825, 0x604e,
+ 0x0000, 0xcb32, 0xcb33, 0x0000, 0x604d, 0xcb34, 0x4d31, 0x4d32,
+ 0x0000, 0x0000, 0xcb35, 0xcb36, 0x0000, 0xcb37, 0x6051, 0x316e,
+ 0x0000, 0x0000, 0x0000, 0xcb38, 0x3976, 0x3b62, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xcb39, 0x6052, 0x6053,
+ 0xcb3a, 0x0000, 0xcb3b, 0x0000, 0x0000, 0x0000, 0xcb3c, 0x6055,
+ 0xcb3d, 0x0000, 0x0000, 0x0000, 0x0000, 0xcb3e, 0xcb3f, 0xcb40,
+ 0xcb41, 0x0000, 0x0000, 0x3d43, 0x0000, 0x0000, 0xcb42, 0xcb43,
+ 0x6057, 0xcb44, 0x6056, 0xcb45, 0xcb46, 0x0000, 0xcb47, 0xcb48,
+ 0x6058, 0xcb49, 0x334d, 0x0000, 0x0000, 0x605a, 0x0000, 0xcb4a,
+ 0x6059, 0xcb4b, 0x605c, 0x605b, 0xcb4c, 0x0000, 0x0000, 0x0000,
+ 0xcb4d, 0xcb4e, 0x0000, 0xcb4f, 0x383c, 0xcb50, 0xcb51, 0x4e28,
+ 0x0000, 0x364c, 0x0000, 0x3226, 0x0000, 0x0000, 0xcb52, 0x0000,
+ 0xcb53, 0x0000, 0x0000, 0xcb54, 0x0000, 0xcb55, 0x366a, 0xcb56,
+ 0xcb57, 0x0000, 0x0000, 0x0000, 0xcb58, 0x0000, 0xcb59, 0xcb5a,
+ 0xcb5b, 0x0000, 0xcb5c, 0x0000, 0x0000, 0xcb5d, 0xcb5e, 0x0000,
+ 0x0000, 0x3461, 0xcb5f, 0xcb60, 0x0000, 0xcb61, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4e68, 0x605e, 0x0000, 0xcb62, 0x0000, 0xcb63,
+ 0x0000, 0xcb64, 0x0000, 0x6060, 0xcb65, 0xcb66, 0x0000, 0xcb67,
+ 0x6061, 0x0000, 0x3251, 0x0000, 0x0000, 0xcb68, 0xcb69, 0x0000,
+ 0x605d, 0xcb6a, 0x3b39, 0xcb6b, 0xcb6c, 0x4441, 0x605f, 0xcb6d,
+ 0x0000, 0x0000, 0xcb6e, 0xcb6f, 0x0000, 0x0000, 0xcb70, 0x0000,
+ 0x0000, 0xcb71, 0x0000, 0x0000, 0x0000, 0xcb72, 0x6064, 0x0000,
+ 0x3c6e, 0xcb73, 0x0000, 0xcb74, 0x0000, 0x6062, 0xcb75, 0xcb76,
+ 0x0000, 0xcb77, 0x373e, 0x0000, 0x0000, 0x4849, 0x6063, 0x0000,
+ 0x0000, 0x607e, 0x0000, 0x0000, 0xcb78, 0xcb79, 0x0000, 0xcb7a,
+ 0x6069, 0xcb7b, 0xcb7c, 0xcb7d, 0x0000, 0xcb7e, 0x383d, 0xcc21
+};
+
+static const unsigned short jis_from_unicode_74[] = {
+ 0xcc22, 0xcc23, 0x0000, 0x3565, 0xcc24, 0x6066, 0x4d7d, 0xcc25,
+ 0x0000, 0x4e30, 0xcc26, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xcc27, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xcc28, 0xcc29, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4276, 0x0000, 0xcc2a, 0x6068, 0xcc2b, 0x0000,
+ 0xcc2c, 0xcc2d, 0xcc2e, 0xcc2f, 0xcc30, 0xcc31, 0xcc32, 0xcc33,
+ 0xcc34, 0xcc35, 0x606a, 0x4e56, 0x3657, 0x487c, 0x474a, 0x0000,
+ 0x0000, 0xcc36, 0x606b, 0x0000, 0x0000, 0x0000, 0x0000, 0x606d,
+ 0xcc37, 0x6070, 0x0000, 0xcc38, 0xcc39, 0x0000, 0xcc3a, 0xcc3b,
+ 0x0000, 0x0000, 0x0000, 0xcc3c, 0x0000, 0xcc3d, 0x0000, 0x0000,
+ 0x0000, 0xcc3e, 0xcc3f, 0x0000, 0x0000, 0x606c, 0x0000, 0xcc40,
+ 0x0000, 0x606f, 0x386a, 0x314d, 0x6071, 0xcc41, 0x3f70, 0x606e,
+ 0x4e5c, 0x0000, 0xcc42, 0x6074, 0x7424, 0x0000, 0xcc43, 0xcc44,
+ 0xcc45, 0x6072, 0x6075, 0xcc46, 0x0000, 0xcc47, 0xcc48, 0x6067,
+ 0x6073, 0xcc49, 0xcc4a, 0x3a3c, 0x0000, 0x0000, 0x6076, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6077, 0x0000,
+ 0xcc4b, 0xcc4c, 0x0000, 0x4d7e, 0x0000, 0xcc4d, 0xcc4e, 0xcc4f,
+ 0x0000, 0xcc50, 0x0000, 0x6078, 0x0000, 0x0000, 0x0000, 0xcc51,
+ 0xcc52, 0xcc53, 0xcc54, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xcc55, 0xcc56, 0xcc57, 0x0000, 0xcc58, 0x0000, 0x6079, 0xcc59,
+ 0xcc5a, 0xcc5b, 0x6065, 0xcc5c, 0x0000, 0x0000, 0xcc5d, 0x607a,
+ 0xcc5e, 0xcc5f, 0xcc60, 0xcc61, 0x0000, 0x0000, 0xcc62, 0xcc63,
+ 0x3444, 0xcc64, 0xcc65, 0x0000, 0x0000, 0xcc66, 0x0000, 0x0000,
+ 0x0000, 0xcc67, 0x0000, 0xcc68, 0x0000, 0x3c25, 0x0000, 0xcc69,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xcc6a, 0xcc6b, 0x607b, 0x0000, 0xcc6c, 0x0000, 0x0000, 0x607c,
+ 0xcc6d, 0x0000, 0x0000, 0xcc6e, 0x607d, 0x0000, 0x0000, 0x0000,
+ 0xcc6f, 0x0000, 0xcc70, 0xcc71, 0x313b, 0x0000, 0xcc72, 0xcc73,
+ 0x6121, 0x0000, 0x493b, 0x6122, 0xcc74, 0x0000, 0x3424, 0x6123,
+ 0xcc75, 0x6124, 0xcc76, 0xcc77, 0x0000, 0x0000, 0x6125, 0xcc78,
+ 0x6127, 0x6128, 0x6126, 0x0000, 0xcc79, 0x0000, 0x4953, 0x612a,
+ 0x6129, 0x0000, 0xcc7a, 0xcc7b, 0xcc7c, 0x0000, 0x0000, 0xcc7d
+};
+
+static const unsigned short jis_from_unicode_75[] = {
+ 0x0000, 0x0000, 0x0000, 0x612c, 0x612b, 0x612d, 0xcc7e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x612e, 0x6130, 0x612f, 0x0000,
+ 0x0000, 0x3979, 0xcd21, 0x6132, 0x0000, 0x6131, 0xcd22, 0xcd23,
+ 0x3445, 0x0000, 0x3f53, 0x0000, 0x453c, 0x0000, 0x6133, 0x4038,
+ 0xcd24, 0xcd25, 0x0000, 0x3b3a, 0xcd26, 0x3179, 0x6134, 0xcd27,
+ 0x4d51, 0xcd28, 0xcd29, 0x4a63, 0x6135, 0x0000, 0x0000, 0xcd2a,
+ 0x4544, 0x4d33, 0x3943, 0x3f3d, 0x0000, 0x0000, 0xcd2b, 0x434b,
+ 0x5234, 0xcd2c, 0x442e, 0x3268, 0x6136, 0xcd2d, 0xcd2e, 0xcd2f,
+ 0xcd30, 0x0000, 0x0000, 0xcd31, 0x6137, 0x0000, 0x613c, 0xcd32,
+ 0xcd33, 0x613a, 0x6139, 0x5a42, 0x3326, 0x6138, 0xcd34, 0x305a,
+ 0xcd35, 0x482a, 0xcd36, 0x0000, 0x484a, 0x0000, 0x0000, 0xcd37,
+ 0x0000, 0x4e31, 0x613d, 0x613b, 0x435c, 0x4026, 0xcd38, 0xcd39,
+ 0x482b, 0xcd3a, 0x492d, 0x0000, 0x613f, 0x4e2c, 0x374d, 0x6140,
+ 0x0000, 0x613e, 0x4856, 0x6141, 0x0000, 0x6142, 0x0000, 0xcd3b,
+ 0x305b, 0xcd3c, 0x0000, 0x3e76, 0x6147, 0x0000, 0x6144, 0x466d,
+ 0x6143, 0xcd3d, 0xcd3e, 0xcd3f, 0xcd40, 0xcd41, 0xcd42, 0x3526,
+ 0x0000, 0xcd43, 0x614a, 0x0000, 0x0000, 0xcd44, 0x6145, 0x6146,
+ 0x0000, 0x6149, 0x6148, 0x4925, 0x0000, 0x0000, 0x4142, 0x4141,
+ 0xcd45, 0x353f, 0xcd46, 0xcd47, 0x614b, 0xcd48, 0x0000, 0x0000,
+ 0x0000, 0xcd49, 0x614c, 0x0000, 0xcd4a, 0x614d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xcd4b, 0x614f, 0xcd4c, 0x614e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3156, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6157, 0x4868, 0x6151, 0xcd4d, 0x6153, 0x0000, 0x0000,
+ 0x6155, 0x3f3e, 0xcd4e, 0x0000, 0x6156, 0x6154, 0x3c40, 0xcd4f,
+ 0xcd50, 0xcd51, 0x6150, 0x6152, 0xcd52, 0x4942, 0xcd53, 0x3e49,
+ 0x0000, 0x0000, 0x6159, 0x0000, 0xcd54, 0x6158, 0xcd55, 0xcd56,
+ 0x0000, 0x0000, 0x615a, 0x0000, 0x3c26, 0x3a2f, 0x0000, 0xcd57,
+ 0x4577, 0x615b, 0x0000, 0x444b, 0xcd58, 0x0000, 0x615d, 0xcd59,
+ 0xcd5a, 0xcd5b, 0x4e21, 0x615c, 0xcd5c, 0x0000, 0x0000, 0xcd5d,
+ 0x0000, 0x4169, 0x0000, 0x0000, 0xcd5e, 0x0000, 0xcd5f, 0xcd60,
+ 0x6162, 0xcd61, 0x6164, 0x6165, 0x4354, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xcd62, 0x6163, 0x0000, 0x6160, 0x0000, 0x615e, 0x615f
+};
+
+static const unsigned short jis_from_unicode_76[] = {
+ 0xcd63, 0x6161, 0xcd64, 0xcd65, 0xcd66, 0x0000, 0x0000, 0xcd67,
+ 0xcd68, 0x6168, 0xcd69, 0x6166, 0xcd6a, 0x6167, 0x0000, 0xcd6b,
+ 0x0000, 0x0000, 0xcd6c, 0xcd6d, 0x0000, 0xcd6e, 0xcd6f, 0x0000,
+ 0x0000, 0xcd70, 0x0000, 0xcd71, 0xcd72, 0xcd73, 0xcd74, 0x6169,
+ 0x616b, 0x616c, 0x616d, 0xcd75, 0x616e, 0xcd76, 0xcd77, 0x616a,
+ 0x0000, 0xcd78, 0x0000, 0x0000, 0x0000, 0xcd79, 0x0000, 0x0000,
+ 0x6170, 0x0000, 0xcd7a, 0xcd7b, 0x616f, 0xcd7c, 0x0000, 0x0000,
+ 0xcd7d, 0xcd7e, 0xce21, 0x6171, 0xce22, 0x0000, 0x0000, 0x0000,
+ 0xce24, 0xce25, 0x4e45, 0xce26, 0xce27, 0xce28, 0x6174, 0x6172,
+ 0x6173, 0xce29, 0xce23, 0xce2a, 0x3462, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4c7e, 0x0000, 0x0000, 0xce2b, 0x4a4a, 0x0000,
+ 0x6176, 0xce2c, 0x0000, 0x0000, 0x6175, 0x0000, 0x0000, 0xce2d,
+ 0x0000, 0x6177, 0x6178, 0x0000, 0xce2e, 0xce2f, 0x0000, 0x617c,
+ 0x6179, 0x617a, 0x617b, 0x0000, 0x617d, 0xce30, 0xce31, 0xce32,
+ 0x617e, 0xce33, 0x6221, 0x0000, 0xce34, 0x0000, 0x6222, 0x0000,
+ 0x6223, 0x0000, 0x482f, 0x4550, 0x6224, 0x4772, 0x4934, 0x0000,
+ 0x6225, 0xce35, 0x0000, 0x6226, 0x452a, 0xce36, 0x3327, 0x3944,
+ 0x6227, 0x0000, 0x0000, 0x6228, 0xce37, 0xce38, 0x6229, 0x0000,
+ 0x3b29, 0x0000, 0x0000, 0x622b, 0x0000, 0xce39, 0x622a, 0x0000,
+ 0x0000, 0x622c, 0x622d, 0xce3a, 0xce3b, 0xce3c, 0x0000, 0xce3d,
+ 0xce3e, 0x0000, 0xce3f, 0xce40, 0xce41, 0xce42, 0xce43, 0xce44,
+ 0xce45, 0x0000, 0xce46, 0x0000, 0x0000, 0xce47, 0x4869, 0x0000,
+ 0x622e, 0x0000, 0x0000, 0x0000, 0x622f, 0x0000, 0x0000, 0x7369,
+ 0x6230, 0x6231, 0x6232, 0x0000, 0x0000, 0xce48, 0x0000, 0x3b2e,
+ 0x0000, 0xce49, 0x6233, 0x4756, 0x0000, 0xce4a, 0x4b5f, 0x0000,
+ 0x314e, 0xce4b, 0x3157, 0xce4c, 0xce4d, 0x6234, 0xce4e, 0x0000,
+ 0x0000, 0x0000, 0x6236, 0x0000, 0xce4f, 0x0000, 0x6235, 0x4570,
+ 0x0000, 0xce50, 0x0000, 0x4039, 0x5d39, 0x0000, 0x6237, 0x4c41,
+ 0xce51, 0x6238, 0x0000, 0x3446, 0x4857, 0x6239, 0xce52, 0x623a,
+ 0xce53, 0x0000, 0x623b, 0x0000, 0xce54, 0x0000, 0x4c5c, 0x0000,
+ 0xce55, 0xce56, 0x4c55, 0x0000, 0x443e, 0x0000, 0xce57, 0x0000,
+ 0x416a, 0xce58, 0x0000, 0x623d, 0xce59, 0x0000, 0x3d62, 0x0000
+};
+
+static const unsigned short jis_from_unicode_77[] = {
+ 0xce5a, 0x3e4a, 0x0000, 0x0000, 0x6240, 0x0000, 0xce5b, 0x623f,
+ 0x623e, 0x487d, 0xce5c, 0x3447, 0x3829, 0x0000, 0xce5d, 0x0000,
+ 0x0000, 0x0000, 0xce5e, 0x0000, 0xce5f, 0xce60, 0x0000, 0xce61,
+ 0x0000, 0xce62, 0xce63, 0x6246, 0xce64, 0x0000, 0x6243, 0x3f3f,
+ 0x4c32, 0x0000, 0xce65, 0x0000, 0x6242, 0x6244, 0x6245, 0x0000,
+ 0xce66, 0x6241, 0x0000, 0x0000, 0x0000, 0xce67, 0xce68, 0xce69,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xce6a, 0xce6b, 0xce6c, 0x6247,
+ 0x6248, 0xce6d, 0x442f, 0x0000, 0x3463, 0xce6e, 0xce6f, 0x0000,
+ 0x4365, 0x0000, 0xce70, 0x0000, 0x0000, 0xce71, 0xce72, 0x6249,
+ 0x0000, 0x0000, 0xce73, 0x0000, 0x0000, 0xce74, 0xce75, 0xce76,
+ 0x0000, 0x0000, 0xce77, 0x0000, 0x0000, 0x0000, 0xce78, 0xce79,
+ 0x0000, 0x0000, 0x624a, 0x624d, 0xce7a, 0x0000, 0xce7b, 0xce7c,
+ 0xce7d, 0x3f67, 0xce7e, 0x4644, 0xcf21, 0x624e, 0x4b53, 0xcf22,
+ 0x624b, 0x0000, 0xcf23, 0x624c, 0xcf24, 0x0000, 0x0000, 0x0000,
+ 0xcf25, 0x0000, 0xcf26, 0xcf27, 0xcf28, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6251, 0xcf29, 0x0000, 0x0000, 0xcf2a, 0x6250, 0x624f,
+ 0xcf2b, 0x0000, 0x0000, 0x0000, 0xcf2c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6253, 0xcf2d, 0xcf2e, 0x6252, 0x0000,
+ 0x0000, 0x6254, 0x0000, 0x0000, 0xcf2f, 0xcf30, 0xcf31, 0x0000,
+ 0x0000, 0x0000, 0xcf32, 0x0000, 0x0000, 0x0000, 0x6256, 0xcf33,
+ 0x6255, 0x0000, 0xcf34, 0x0000, 0x0000, 0x4a4d, 0x0000, 0xcf35,
+ 0x0000, 0x0000, 0xcf36, 0x0000, 0x3d56, 0x4e46, 0xcf37, 0xcf38,
+ 0x6257, 0xcf39, 0x0000, 0x4637, 0x0000, 0xcf3a, 0x6258, 0x0000,
+ 0x0000, 0x6259, 0x0000, 0x625d, 0x625b, 0x625c, 0xcf3b, 0x625a,
+ 0x0000, 0x0000, 0x0000, 0xcf3c, 0x0000, 0x0000, 0x0000, 0x625e,
+ 0x0000, 0xcf3d, 0x0000, 0x0000, 0x0000, 0x625f, 0x0000, 0x0000,
+ 0x0000, 0xcf3e, 0xcf3f, 0x0000, 0x0000, 0xcf40, 0x0000, 0x6260,
+ 0x0000, 0xcf41, 0x6261, 0x4c37, 0x6262, 0x0000, 0xcf42, 0xcf43,
+ 0xcf44, 0x0000, 0x4c70, 0x6263, 0xcf45, 0x434e, 0xcf46, 0x476a,
+ 0x0000, 0x366b, 0xcf47, 0x0000, 0xcf48, 0x433b, 0x6264, 0x363a,
+ 0xcf49, 0xcf4a, 0x0000, 0x4050, 0xcf4b, 0x0000, 0x0000, 0x0000,
+ 0xcf4c, 0x0000, 0x0000, 0xcf4d, 0x6265, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_78[] = {
+ 0x0000, 0x0000, 0x3a3d, 0x0000, 0x0000, 0xcf4e, 0xcf4f, 0x0000,
+ 0x0000, 0xcf50, 0x0000, 0x0000, 0x6266, 0xcf51, 0xcf52, 0x0000,
+ 0x0000, 0xcf53, 0x6267, 0x0000, 0x3826, 0x3a55, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xcf54, 0x0000, 0x0000,
+ 0x6269, 0xcf55, 0xcf56, 0xcf57, 0x0000, 0x4556, 0x3a56, 0x354e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xcf58, 0xcf59, 0x0000,
+ 0xcf5a, 0x0000, 0x4b24, 0x0000, 0x474b, 0xcf5b, 0x0000, 0xcf5c,
+ 0x0000, 0x0000, 0x4557, 0x0000, 0x0000, 0x0000, 0x0000, 0x395c,
+ 0x0000, 0x0000, 0x0000, 0xcf5d, 0xcf5e, 0x626b, 0x0000, 0xcf5f,
+ 0xcf60, 0x0000, 0x0000, 0x0000, 0xcf61, 0x0000, 0xcf62, 0x0000,
+ 0x0000, 0x0000, 0xcf63, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xcf64, 0x3e4b, 0xcf65, 0x0000,
+ 0xcf66, 0xcf67, 0x0000, 0xcf68, 0xcf69, 0x0000, 0x0000, 0x0000,
+ 0xcf6a, 0x0000, 0xcf6b, 0x4e32, 0x3945, 0x0000, 0xcf6c, 0x3827,
+ 0x0000, 0x0000, 0x4823, 0x0000, 0x626d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xcf6d, 0x0000, 0x626f, 0x0000, 0xcf6e, 0x0000,
+ 0x0000, 0x386b, 0x0000, 0x0000, 0x0000, 0x0000, 0x626e, 0x4476,
+ 0x0000, 0x0000, 0xcf6f, 0x0000, 0x6271, 0x3337, 0x626c, 0xcf70,
+ 0x0000, 0x486a, 0x0000, 0x3130, 0xcf71, 0x3a6c, 0x0000, 0x4f52,
+ 0xcf72, 0x0000, 0x6270, 0x0000, 0x0000, 0xcf74, 0xcf75, 0xcf76,
+ 0x0000, 0xcf73, 0x0000, 0x6272, 0xcf77, 0x0000, 0x0000, 0x4a4b,
+ 0xcf78, 0x4059, 0x6274, 0x0000, 0xcf79, 0xcf7a, 0x0000, 0x6275,
+ 0xcf7b, 0xcf7c, 0xcf7d, 0xcf7e, 0x0000, 0x6273, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x334e, 0xd021, 0x627b, 0xd022, 0x627a, 0xd023,
+ 0x0000, 0x3c27, 0x0000, 0x0000, 0x0000, 0x627c, 0x6277, 0xd024,
+ 0xd025, 0xd026, 0x627d, 0x6278, 0xd027, 0x0000, 0xd028, 0x0000,
+ 0x4858, 0x6276, 0xd029, 0xd02a, 0x6279, 0xd02b, 0xd02c, 0x0000,
+ 0x0000, 0x0000, 0x6322, 0xd02e, 0x0000, 0x0000, 0x0000, 0xd02f,
+ 0xd030, 0xd031, 0x0000, 0x0000, 0xd02d, 0x0000, 0xd032, 0x6321,
+ 0x4b61, 0x0000, 0xd033, 0x0000, 0x627e, 0x0000, 0x0000, 0x306b,
+ 0x0000, 0x0000, 0xd034, 0xd035, 0x6324, 0x0000, 0xd037, 0xd038,
+ 0x0000, 0x0000, 0xd039, 0xd03a, 0x0000, 0x6323, 0x0000, 0xd03b
+};
+
+static const unsigned short jis_from_unicode_79[] = {
+ 0xd036, 0x3e4c, 0x0000, 0x0000, 0x0000, 0x0000, 0xd03c, 0x6325,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd03d, 0x0000, 0x4143, 0x0000,
+ 0xd03e, 0x6327, 0x6326, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6328, 0xd03f, 0x0000, 0xd040, 0x0000, 0xd041, 0xd042,
+ 0xd043, 0x0000, 0x0000, 0x0000, 0x0000, 0xd044, 0x6268, 0xd045,
+ 0x0000, 0xd046, 0x626a, 0x632a, 0x6329, 0xd047, 0x0000, 0x0000,
+ 0x0000, 0xd048, 0x0000, 0x0000, 0xd049, 0xd04a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3c28, 0xd04b, 0x4e69, 0xd04c, 0x3c52, 0xd04d,
+ 0x632b, 0x3737, 0x0000, 0x0000, 0xd04e, 0xd04f, 0xd050, 0x3540,
+ 0x3527, 0x3b63, 0xd051, 0xd052, 0x0000, 0x0000, 0x0000, 0xd053,
+ 0x4d34, 0xd054, 0x0000, 0x6331, 0xd055, 0x6330, 0x4144, 0x632d,
+ 0xd056, 0x0000, 0x632f, 0xd057, 0xd058, 0x3d4b, 0x3f40, 0x632e,
+ 0x632c, 0x0000, 0x472a, 0x0000, 0x0000, 0x3e4d, 0x0000, 0xd059,
+ 0x493c, 0xd05a, 0x0000, 0xd05b, 0x0000, 0x3a57, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd05c, 0x0000, 0x0000, 0x0000, 0x0000, 0x4578,
+ 0x0000, 0xd05d, 0x6332, 0xd05e, 0xd05f, 0x0000, 0xd060, 0x6333,
+ 0x6349, 0x3658, 0x0000, 0x0000, 0x4f3d, 0x4135, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6334, 0xd061, 0xd062, 0x3252, 0x4477, 0x4a21,
+ 0x0000, 0xd063, 0x0000, 0xd064, 0xd065, 0xd066, 0xd067, 0x0000,
+ 0xd068, 0x0000, 0x0000, 0xd069, 0xd06a, 0x6335, 0x0000, 0x0000,
+ 0x0000, 0xd06b, 0x0000, 0x0000, 0x0000, 0x0000, 0x357a, 0x6336,
+ 0xd06c, 0xd06d, 0x6338, 0xd06e, 0x0000, 0x0000, 0x6339, 0xd06f,
+ 0x4729, 0xd070, 0x0000, 0x633a, 0xd071, 0x0000, 0x0000, 0x0000,
+ 0xd072, 0x633b, 0x633c, 0xd073, 0x0000, 0x3659, 0x3253, 0x4645,
+ 0x3d28, 0x3b64, 0xd074, 0x0000, 0xd075, 0x0000, 0x0000, 0xd076,
+ 0xd077, 0x633d, 0xd078, 0x3d29, 0x0000, 0x0000, 0x0000, 0xd079,
+ 0x0000, 0x324a, 0x4943, 0x0000, 0xd07a, 0x633e, 0xd07b, 0x0000,
+ 0x486b, 0x0000, 0xd07c, 0x0000, 0x0000, 0xd07d, 0xd07e, 0x4145,
+ 0xd121, 0x6341, 0xd122, 0x6342, 0x4769, 0xd123, 0x3f41, 0x633f,
+ 0x0000, 0x4361, 0xd124, 0xd125, 0x6340, 0xd126, 0x0000, 0x0000,
+ 0x3e4e, 0xd127, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd128, 0x0000, 0x0000, 0x305c, 0xd129, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_7a[] = {
+ 0x3529, 0x0000, 0xd12a, 0xd12b, 0x0000, 0x0000, 0x0000, 0xd12c,
+ 0x6343, 0xd12d, 0xd12e, 0x4478, 0xd12f, 0x6344, 0x4047, 0x0000,
+ 0x0000, 0xd130, 0x0000, 0x0000, 0x4c2d, 0xd131, 0x0000, 0x4923,
+ 0x6345, 0x6346, 0x4355, 0xd132, 0x4e47, 0x0000, 0xd133, 0x6348,
+ 0x6347, 0xd134, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd135,
+ 0x0000, 0x0000, 0x0000, 0xd136, 0x0000, 0xd137, 0x3c6f, 0xd138,
+ 0xd139, 0x634a, 0x3070, 0x0000, 0xd13a, 0xd13b, 0x0000, 0x634d,
+ 0xd13c, 0xd13d, 0xd13e, 0x634b, 0x3254, 0x374e, 0x634c, 0x3946,
+ 0x3972, 0x0000, 0x4a66, 0x634e, 0xd13f, 0xd140, 0x4b54, 0xd141,
+ 0xd142, 0x6350, 0x0000, 0x0000, 0xd143, 0x4051, 0x314f, 0x323a,
+ 0x302c, 0x0000, 0x0000, 0x0000, 0x0000, 0xd144, 0xd145, 0x634f,
+ 0x0000, 0xd146, 0x0000, 0x0000, 0xd147, 0xd148, 0x0000, 0xd149,
+ 0xd14a, 0x6351, 0x6352, 0x3e77, 0x0000, 0xd14b, 0x0000, 0xd14c,
+ 0x0000, 0x6353, 0xd14d, 0x334f, 0x0000, 0xd14e, 0x0000, 0x0000,
+ 0x6355, 0x0000, 0x0000, 0x0000, 0x376a, 0xd14f, 0x3566, 0x0000,
+ 0xd150, 0x6356, 0x3675, 0x0000, 0x0000, 0x6357, 0xd151, 0x407c,
+ 0xd152, 0x464d, 0xd153, 0x4060, 0x3a75, 0xd154, 0xd155, 0x0000,
+ 0x6358, 0x0000, 0xd156, 0xd157, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd158, 0xd159, 0x4362, 0x416b, 0xd15a, 0x635a, 0x635c, 0x6359,
+ 0x635b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd15b, 0x3722,
+ 0xd15c, 0x0000, 0x0000, 0xd15d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x635d, 0x3726, 0x0000, 0xd15e, 0x0000, 0x3567, 0x4d52,
+ 0x635f, 0x0000, 0x0000, 0xd15f, 0x0000, 0xd160, 0x6360, 0x0000,
+ 0x0000, 0xd161, 0x312e, 0xd162, 0xd163, 0x0000, 0x0000, 0x6363,
+ 0x0000, 0x0000, 0x0000, 0x3376, 0x6362, 0x6361, 0xd164, 0x6365,
+ 0x635e, 0xd165, 0x6366, 0x4e29, 0xd166, 0x6367, 0xd167, 0x6368,
+ 0x0000, 0xd168, 0x5474, 0x636a, 0x0000, 0x6369, 0x0000, 0x0000,
+ 0x0000, 0x636b, 0x636c, 0xd169, 0x4e35, 0x636d, 0x0000, 0x706f,
+ 0x3e4f, 0x636e, 0x636f, 0x3d57, 0x0000, 0x4638, 0x6370, 0x0000,
+ 0xd16a, 0xd16b, 0x4328, 0xd16c, 0xd16d, 0x6371, 0x0000, 0x433c,
+ 0x6372, 0xd16e, 0x0000, 0x0000, 0xd16f, 0x0000, 0x3625, 0x0000,
+ 0x513f, 0x435d, 0x3c33, 0xd170, 0x0000, 0xd171, 0xd172, 0x3448
+};
+
+static const unsigned short jis_from_unicode_7b[] = {
+ 0x0000, 0x0000, 0x6373, 0x0000, 0x6422, 0x0000, 0x6376, 0xd173,
+ 0x3568, 0x0000, 0x6375, 0x6424, 0x0000, 0x0000, 0x0000, 0x6374,
+ 0x0000, 0x3e50, 0x0000, 0x0000, 0xd174, 0x0000, 0x0000, 0x0000,
+ 0x6378, 0x6379, 0x0000, 0x452b, 0x0000, 0x0000, 0x637a, 0xd175,
+ 0x335e, 0x0000, 0x0000, 0xd176, 0x0000, 0x3f5a, 0x4964, 0xd177,
+ 0x637c, 0xd178, 0xd179, 0xd17a, 0x4268, 0xd17b, 0xd17c, 0xd17d,
+ 0xd17e, 0xd221, 0x0000, 0x6377, 0xd222, 0x637b, 0x637d, 0x0000,
+ 0x0000, 0x3a7b, 0x0000, 0x0000, 0x0000, 0xd223, 0x0000, 0xd224,
+ 0xd225, 0xd226, 0x0000, 0x0000, 0x0000, 0x6426, 0x492e, 0xd227,
+ 0x4826, 0x4579, 0x0000, 0x365a, 0x6425, 0x6423, 0xd228, 0x4835,
+ 0x637e, 0x435e, 0x457b, 0x0000, 0x457a, 0xd229, 0x3a76, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6438, 0x0000, 0x0000,
+ 0xd22a, 0x0000, 0x0000, 0x0000, 0xd22b, 0x6428, 0xd22c, 0x642a,
+ 0x0000, 0xd22d, 0xd22e, 0x0000, 0x642d, 0xd22f, 0x642e, 0xd230,
+ 0x642b, 0x642c, 0xd231, 0xd232, 0x6429, 0x6427, 0x0000, 0xd233,
+ 0x0000, 0x0000, 0x6421, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd234, 0x0000, 0x4a4f, 0x3255,
+ 0x0000, 0xd235, 0x0000, 0x6435, 0x0000, 0x6432, 0xd236, 0x6437,
+ 0xd237, 0xd238, 0x6436, 0x0000, 0x4773, 0x4c27, 0xd239, 0x3b3b,
+ 0x6430, 0x6439, 0x6434, 0xd23a, 0x6433, 0x642f, 0xd23b, 0x6431,
+ 0xd23c, 0x3449, 0x0000, 0x0000, 0x0000, 0xd23d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x433d, 0x0000, 0xd23e, 0x407d, 0x0000, 0xd23f,
+ 0xd240, 0x4822, 0xd241, 0x0000, 0x643e, 0xd242, 0xd243, 0x0000,
+ 0x4824, 0x0000, 0xd244, 0xd245, 0xd246, 0xd247, 0x0000, 0x0000,
+ 0x4061, 0x643b, 0xd248, 0x0000, 0x484f, 0xd249, 0x643f, 0x4a53,
+ 0xd24a, 0x435b, 0xd24b, 0x643a, 0x643c, 0x0000, 0x0000, 0x643d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd24c, 0x0000, 0xd24d, 0xd24e,
+ 0x0000, 0xd24f, 0xd250, 0xd251, 0x0000, 0x6440, 0x0000, 0x0000,
+ 0x3c44, 0x0000, 0x0000, 0x0000, 0x4646, 0x6445, 0x6444, 0x0000,
+ 0xd252, 0x6441, 0xd253, 0x0000, 0x0000, 0x4f36, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd254, 0x644a, 0xd255, 0xd256, 0x644e, 0x644b,
+ 0xd257, 0xd258, 0xd259, 0x0000, 0xd25a, 0x0000, 0xd25b, 0x0000
+};
+
+static const unsigned short jis_from_unicode_7c[] = {
+ 0x6447, 0xd25c, 0xd25d, 0xd25e, 0xd25f, 0x0000, 0xd260, 0x6448,
+ 0x0000, 0xd261, 0x0000, 0xd262, 0xd263, 0x644d, 0xd264, 0xd265,
+ 0x0000, 0x6442, 0x5255, 0x6449, 0x6443, 0x0000, 0x0000, 0x644c,
+ 0x0000, 0xd266, 0x0000, 0xd267, 0x0000, 0x0000, 0x0000, 0x6452,
+ 0xd268, 0x344a, 0x0000, 0x644f, 0x0000, 0xd269, 0xd26a, 0x6450,
+ 0xd26b, 0x0000, 0x6451, 0x6454, 0xd26c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd26d, 0x0000, 0xd26e, 0xd26f, 0x0000, 0xd270, 0x6453,
+ 0x4876, 0xd271, 0xd272, 0x0000, 0x0000, 0x6455, 0x4e7c, 0x4a6d,
+ 0x645a, 0x0000, 0x0000, 0x6457, 0x0000, 0x0000, 0xd273, 0x0000,
+ 0x0000, 0x0000, 0xd274, 0x0000, 0x6456, 0x4052, 0x0000, 0x6459,
+ 0x645b, 0xd276, 0xd277, 0xd278, 0x6458, 0xd275, 0x645f, 0x0000,
+ 0x645c, 0xd279, 0xd27a, 0xd27b, 0xd27c, 0xd27d, 0xd27e, 0x645d,
+ 0x6446, 0xd321, 0x0000, 0xd322, 0x645e, 0x6460, 0x0000, 0xd323,
+ 0x0000, 0xd324, 0x0000, 0x0000, 0x6461, 0xd325, 0xd326, 0x0000,
+ 0xd327, 0x0000, 0xd328, 0x4a46, 0x0000, 0x6462, 0x0000, 0x0000,
+ 0x0000, 0xd329, 0x0000, 0x0000, 0xd32a, 0xd32b, 0x4c62, 0x0000,
+ 0x0000, 0x364e, 0x3729, 0x6463, 0x0000, 0x0000, 0xd32c, 0xd32d,
+ 0x0000, 0x4a34, 0x0000, 0x3f68, 0x0000, 0x4c30, 0x0000, 0xd32e,
+ 0x6464, 0x0000, 0x4e33, 0x0000, 0xd32f, 0x4774, 0x0000, 0x4146,
+ 0x4734, 0x0000, 0x0000, 0x3d4d, 0x0000, 0x0000, 0xd330, 0x3040,
+ 0xd331, 0x6469, 0x6467, 0x0000, 0x6465, 0x3421, 0xd332, 0x3e51,
+ 0x646a, 0x0000, 0x0000, 0x6468, 0x0000, 0x6466, 0x646e, 0x0000,
+ 0xd333, 0x646d, 0x646c, 0x646b, 0x0000, 0x0000, 0xd334, 0xd335,
+ 0x0000, 0x646f, 0xd336, 0xd337, 0xd338, 0x6470, 0x403a, 0xd339,
+ 0x6471, 0x0000, 0x6473, 0x0000, 0xd33a, 0x6472, 0x0000, 0xd33b,
+ 0xd33c, 0xd33d, 0x3852, 0x0000, 0x0000, 0xd33e, 0x4138, 0xd33f,
+ 0x0000, 0x0000, 0x6475, 0xd340, 0xd341, 0xd342, 0x457c, 0xd343,
+ 0x6474, 0xd344, 0xd345, 0x0000, 0x6476, 0xd346, 0x4a35, 0x416c,
+ 0x3947, 0x0000, 0x6477, 0x0000, 0x0000, 0x0000, 0xd347, 0x4e48,
+ 0x0000, 0xd348, 0x0000, 0xd349, 0x0000, 0x0000, 0x0000, 0x6479,
+ 0x0000, 0x0000, 0x647a, 0x0000, 0x647b, 0xd34a, 0x647c, 0x0000,
+ 0x3b65, 0x0000, 0x647d, 0x374f, 0x0000, 0x0000, 0x356a, 0x0000
+};
+
+static const unsigned short jis_from_unicode_7d[] = {
+ 0x352a, 0x0000, 0x6521, 0xd34b, 0x4c73, 0x3948, 0x647e, 0xd34c,
+ 0xd34d, 0xd34e, 0x6524, 0x4c66, 0x0000, 0x473c, 0x0000, 0xd34f,
+ 0x4933, 0xd350, 0xd351, 0xd352, 0x3d63, 0x6523, 0xd353, 0x3c53,
+ 0x3949, 0x3b66, 0x3569, 0x4a36, 0x6522, 0xd354, 0xd355, 0x0000,
+ 0x4147, 0x4b42, 0x3a77, 0xd356, 0x0000, 0x0000, 0xd357, 0x0000,
+ 0x0000, 0x0000, 0xd358, 0x3b67, 0x445d, 0xd359, 0x6527, 0x4e5f,
+ 0x3a59, 0xd35a, 0x6528, 0x3f42, 0x0000, 0x652a, 0x0000, 0x0000,
+ 0x0000, 0x3e52, 0x3a30, 0x0000, 0xd35b, 0xd35c, 0xd35d, 0x6529,
+ 0xd35e, 0xd35f, 0x3d2a, 0x383e, 0x4148, 0x6525, 0x652b, 0xd360,
+ 0xd361, 0x0000, 0x0000, 0x6526, 0x3750, 0xd362, 0x652e, 0x6532,
+ 0x376b, 0xd363, 0x0000, 0xd364, 0x0000, 0x0000, 0x652d, 0xd365,
+ 0x0000, 0xd366, 0xd367, 0x6536, 0xd368, 0xd369, 0x394a, 0x0000,
+ 0x0000, 0x4d6d, 0x303c, 0x6533, 0x0000, 0xd36a, 0x356b, 0xd36b,
+ 0x6530, 0x0000, 0xd36c, 0x0000, 0x0000, 0x0000, 0x6531, 0x0000,
+ 0xd36d, 0x457d, 0x652f, 0x652c, 0x0000, 0x3328, 0x4064, 0x0000,
+ 0xd36e, 0x3828, 0xd36f, 0xd370, 0x0000, 0x6538, 0x0000, 0xd371,
+ 0x0000, 0xd372, 0xd373, 0xd374, 0x0000, 0xd375, 0xd376, 0x0000,
+ 0xd377, 0x6535, 0x0000, 0xd378, 0xd379, 0xd37a, 0x0000, 0x6537,
+ 0x0000, 0xd37b, 0x0000, 0x6534, 0x0000, 0x0000, 0xd37c, 0xd37d,
+ 0x0000, 0x3751, 0x4233, 0x6539, 0x416e, 0xd37e, 0xd421, 0x6546,
+ 0x0000, 0x0000, 0x6542, 0x653c, 0x0000, 0x0000, 0xd422, 0xd423,
+ 0x0000, 0x0000, 0xd424, 0x6540, 0x3c7a, 0x305d, 0x653b, 0x6543,
+ 0x6547, 0x394b, 0x4c56, 0xd425, 0x4456, 0x653d, 0xd426, 0xd427,
+ 0x6545, 0xd428, 0x653a, 0x433e, 0x0000, 0x653f, 0x303d, 0x4c4a,
+ 0x0000, 0x0000, 0xd429, 0xd42a, 0xd42b, 0xd42c, 0xd42d, 0x653e,
+ 0x0000, 0x0000, 0x365b, 0x486c, 0xd42e, 0xd42f, 0xd430, 0x416d,
+ 0x0000, 0x4e50, 0x3d6f, 0x0000, 0x0000, 0x656e, 0x0000, 0xd431,
+ 0x6548, 0xd432, 0x407e, 0x0000, 0x6544, 0x6549, 0x654b, 0x0000,
+ 0x4479, 0x654e, 0xd434, 0x0000, 0x654a, 0xd435, 0xd436, 0x0000,
+ 0x4a54, 0x344b, 0xd437, 0xd438, 0x4c4b, 0xd439, 0x0000, 0x305e,
+ 0x0000, 0xd43a, 0x654d, 0x0000, 0x4e7d, 0xd43b, 0xd43c, 0x0000,
+ 0x0000, 0xd43d, 0xd43e, 0x654c, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_7e[] = {
+ 0xd433, 0x316f, 0x0000, 0x0000, 0x466c, 0x654f, 0x0000, 0x0000,
+ 0xd43f, 0x6556, 0x6550, 0x6557, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd440, 0xd441, 0x6553, 0x0000, 0x0000, 0xd442, 0x0000, 0xd443,
+ 0x0000, 0x0000, 0x0000, 0x477b, 0xd444, 0xd445, 0x3c4a, 0x6555,
+ 0xd446, 0x6552, 0x6558, 0x6551, 0x0000, 0x0000, 0x3d44, 0xd447,
+ 0xd448, 0x0000, 0x0000, 0x4b25, 0xd449, 0xd44a, 0x3d4c, 0xd44b,
+ 0x0000, 0x6554, 0x6560, 0xd44c, 0x0000, 0x655c, 0xd44d, 0x655f,
+ 0x0000, 0x655d, 0x6561, 0x655b, 0x0000, 0x6541, 0x4053, 0xd44e,
+ 0x0000, 0x484b, 0x0000, 0x655e, 0xd44f, 0xd450, 0x6559, 0xd451,
+ 0x0000, 0x0000, 0x4121, 0x3752, 0x0000, 0x3d2b, 0xd452, 0x0000,
+ 0xd453, 0x0000, 0xd454, 0x0000, 0x3f25, 0x4136, 0x6564, 0x0000,
+ 0xd455, 0x6566, 0x6567, 0x0000, 0x0000, 0x6563, 0x6565, 0xd456,
+ 0x0000, 0xd457, 0xd458, 0x0000, 0x0000, 0xd459, 0x655a, 0x6562,
+ 0x0000, 0x656a, 0x6569, 0xd45a, 0x0000, 0x4b7a, 0xd45b, 0xd45c,
+ 0x372b, 0x0000, 0x0000, 0xd45d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd45e, 0x6568, 0x0000, 0x656c, 0x656b, 0x656f, 0xd45f, 0x6571,
+ 0x0000, 0xd460, 0x3b3c, 0x656d, 0x0000, 0x0000, 0xd461, 0xd462,
+ 0x6572, 0x6573, 0xd463, 0x0000, 0x6574, 0xd464, 0x657a, 0x453b,
+ 0x6576, 0xd465, 0x6575, 0x6577, 0x6578, 0xd466, 0x6579, 0x0000,
+ 0xd467, 0x0000, 0xd468, 0x657b, 0x657c, 0xd469, 0xd46a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_7f[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x344c, 0x0000,
+ 0x657d, 0x0000, 0x657e, 0xd46c, 0xd46b, 0xd46d, 0xd46e, 0xd46f,
+ 0x0000, 0x0000, 0x0000, 0xd470, 0xd471, 0x6621, 0x0000, 0xd472,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6622, 0x6623, 0x6624, 0xd473,
+ 0x6625, 0x6626, 0xd474, 0xd475, 0x6628, 0x6627, 0x0000, 0x0000,
+ 0x6629, 0x0000, 0x0000, 0xd476, 0xd477, 0xd478, 0x0000, 0x662a,
+ 0x662b, 0xd479, 0x0000, 0xd47a, 0xd47b, 0xd47c, 0xd47d, 0x662e,
+ 0x662c, 0x662d, 0x3a61, 0x3753, 0x0000, 0xd47e, 0x4356, 0x0000,
+ 0x4833, 0xd521, 0x3d70, 0x0000, 0x0000, 0x474d, 0x0000, 0x486d,
+ 0x662f, 0x586d, 0x0000, 0x0000, 0x0000, 0xd522, 0xd523, 0xd524,
+ 0xd525, 0x0000, 0x6630, 0x6632, 0x0000, 0x4d65, 0x6631, 0x6634,
+ 0x6633, 0x0000, 0x4d53, 0xd526, 0x6635, 0xd527, 0x487e, 0xd528,
+ 0xd529, 0xd52a, 0x0000, 0x0000, 0x6636, 0x0000, 0xd52b, 0xd52c,
+ 0x0000, 0x0000, 0x6639, 0x0000, 0xd52d, 0x6638, 0x6637, 0x0000,
+ 0x0000, 0xd52e, 0xd52f, 0x663a, 0x3732, 0x0000, 0xd530, 0x0000,
+ 0x4122, 0x3541, 0xd531, 0x0000, 0x0000, 0xd532, 0x663e, 0x663b,
+ 0x0000, 0x0000, 0x663c, 0x0000, 0xd533, 0x0000, 0x663f, 0x0000,
+ 0x6640, 0x663d, 0x0000, 0x0000, 0xd534, 0x3129, 0x0000, 0xd535,
+ 0xd536, 0x3227, 0x0000, 0xd537, 0x0000, 0x6642, 0x6643, 0x0000,
+ 0xd538, 0x0000, 0x6644, 0x0000, 0x4d62, 0x0000, 0xd539, 0xd53a,
+ 0x0000, 0x0000, 0x3d2c, 0x0000, 0x6646, 0x6645, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xd53b, 0x0000, 0x0000, 0x0000, 0xd53c,
+ 0x3f69, 0x6647, 0x0000, 0xd53d, 0x0000, 0xd53e, 0x6648, 0x0000,
+ 0xd53f, 0x6649, 0x0000, 0x3465, 0xd540, 0x0000, 0xd541, 0xd542,
+ 0x344d, 0x0000, 0xd543, 0x664a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x664b, 0xd544, 0x4b5d, 0x4d63, 0xd545, 0xd546, 0xd547
+};
+
+static const unsigned short jis_from_unicode_80[] = {
+ 0x4d54, 0x4f37, 0x0000, 0x394d, 0x664e, 0x3c54, 0x664d, 0xd548,
+ 0xd549, 0x0000, 0xd54a, 0x664f, 0x3c29, 0xd54b, 0xd54c, 0xd54d,
+ 0x4251, 0xd54e, 0x6650, 0xd54f, 0xd550, 0x394c, 0xd551, 0x4c57,
+ 0x6651, 0x6652, 0x0000, 0x0000, 0x6653, 0xd552, 0xd553, 0xd554,
+ 0xd555, 0x6654, 0x0000, 0x0000, 0xd556, 0x0000, 0xd557, 0x0000,
+ 0x6655, 0x0000, 0x0000, 0x0000, 0xd558, 0x0000, 0xd559, 0x0000,
+ 0xd55a, 0x0000, 0x0000, 0x3c2a, 0xd55b, 0xd55c, 0x4c6d, 0xd55d,
+ 0x0000, 0xd55e, 0xd55f, 0x6657, 0xd560, 0x433f, 0xd561, 0x6656,
+ 0xd562, 0x0000, 0x0000, 0x0000, 0xd563, 0x0000, 0x6659, 0x0000,
+ 0x0000, 0x0000, 0x6658, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x665a, 0x0000, 0x0000, 0x0000, 0x403b, 0x0000,
+ 0x665b, 0x0000, 0x665c, 0x0000, 0x0000, 0x0000, 0x4a39, 0x665d,
+ 0xd564, 0x416f, 0x665e, 0x0000, 0xd565, 0x0000, 0xd566, 0x0000,
+ 0x665f, 0x0000, 0x0000, 0x0000, 0x0000, 0xd567, 0x0000, 0x4e7e,
+ 0x6662, 0xd568, 0x6661, 0x6660, 0x4430, 0xd569, 0x6663, 0x3f26,
+ 0x0000, 0x6664, 0x0000, 0x0000, 0x0000, 0x6665, 0x4f38, 0x6666,
+ 0x0000, 0xd56a, 0x0000, 0x0000, 0x6667, 0x6669, 0x6668, 0x4825,
+ 0xd56b, 0x4679, 0x0000, 0x4f3e, 0x4829, 0x0000, 0xd56c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x666b, 0x0000, 0x0000, 0x3e53, 0x0000,
+ 0x492a, 0x0000, 0x666c, 0x666a, 0xd56d, 0x344e, 0xd56e, 0x0000,
+ 0x0000, 0x3854, 0x3b68, 0x0000, 0x0000, 0x486e, 0xd56f, 0xd570,
+ 0x0000, 0x382a, 0x4b43, 0xd571, 0x666f, 0x666d, 0x0000, 0x394e,
+ 0x0000, 0x394f, 0x3069, 0x0000, 0x3a68, 0x0000, 0x0000, 0x0000,
+ 0xd572, 0xd573, 0x4759, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x305f, 0x6674, 0x0000, 0x4340, 0x0000,
+ 0xd574, 0x0000, 0x0000, 0x0000, 0x4758, 0xd575, 0x425b, 0xd576,
+ 0x0000, 0x0000, 0xd577, 0x0000, 0xd578, 0xd579, 0x6676, 0xd57a,
+ 0xd57b, 0x6672, 0x6675, 0x6670, 0x0000, 0x6673, 0x4b26, 0x0000,
+ 0xd57c, 0x3855, 0x0000, 0x0000, 0x307d, 0x6671, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd57d, 0xd57e, 0x6678,
+ 0xd621, 0x6679, 0xd622, 0xd623, 0x4639, 0x0000, 0xd624, 0x0000,
+ 0x363b, 0xd625, 0xd626, 0x0000, 0x6726, 0x473d, 0xd627, 0x0000
+};
+
+static const unsigned short jis_from_unicode_81[] = {
+ 0x0000, 0x0000, 0x3b69, 0xd628, 0x0000, 0x363c, 0x4048, 0x4f46,
+ 0x4c2e, 0x6677, 0x4054, 0xd629, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd62a, 0xd62b,
+ 0xd62c, 0x0000, 0x3553, 0x667a, 0xd62d, 0x0000, 0xd62e, 0x0000,
+ 0xd62f, 0x0000, 0x0000, 0x667c, 0xd630, 0x0000, 0x0000, 0xd631,
+ 0x0000, 0x667b, 0x0000, 0x0000, 0xd632, 0x0000, 0x0000, 0x667d,
+ 0xd633, 0x4326, 0x0000, 0x473e, 0x0000, 0xd634, 0x0000, 0x0000,
+ 0x0000, 0x4431, 0xd635, 0x0000, 0xd636, 0x0000, 0x6723, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd637, 0x6722, 0xd638,
+ 0x0000, 0x0000, 0xd639, 0x667e, 0xd63a, 0x0000, 0x3f55, 0x0000,
+ 0x4965, 0x6725, 0xd63b, 0x6724, 0x3950, 0x4f53, 0x0000, 0xd63c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6735,
+ 0xd63d, 0xd63e, 0x0000, 0x0000, 0x0000, 0x6729, 0x672a, 0xd63f,
+ 0xd640, 0xd641, 0x0000, 0x3c70, 0x0000, 0xd642, 0x6728, 0xd643,
+ 0x3978, 0x6727, 0x0000, 0x0000, 0x672b, 0x0000, 0x0000, 0xd644,
+ 0x4432, 0x4a22, 0x4123, 0x0000, 0x0000, 0x0000, 0x0000, 0x425c,
+ 0x672f, 0xd645, 0x6730, 0x672c, 0xd647, 0xd648, 0xd649, 0x0000,
+ 0x672d, 0x0000, 0x672e, 0xd64a, 0x0000, 0x0000, 0xd64b, 0x3951,
+ 0xd646, 0x0000, 0x0000, 0x6736, 0x0000, 0x6732, 0xd64c, 0x0000,
+ 0xd64d, 0x0000, 0x4966, 0xd64e, 0x4b6c, 0x4928, 0xd64f, 0x0000,
+ 0x6731, 0x0000, 0xd650, 0x6734, 0x6733, 0x0000, 0x0000, 0x0000,
+ 0x4b44, 0x6737, 0x0000, 0x0000, 0x0000, 0x0000, 0xd651, 0x0000,
+ 0x6738, 0x0000, 0xd652, 0x4137, 0xd653, 0x6739, 0x0000, 0x0000,
+ 0x673b, 0x0000, 0x673f, 0xd654, 0x0000, 0x673c, 0x673a, 0x473f,
+ 0x673d, 0x0000, 0x673e, 0xd656, 0x0000, 0xd657, 0x3232, 0x0000,
+ 0x6745, 0x6740, 0xd658, 0xd655, 0x0000, 0x6741, 0xd659, 0xd65a,
+ 0x0000, 0x6742, 0x0000, 0x4221, 0x0000, 0xd65b, 0x0000, 0xd65c,
+ 0x6744, 0x6743, 0x6746, 0xd65d, 0x0000, 0xd65e, 0xd65f, 0x6747,
+ 0x6748, 0xd660, 0x0000, 0x3f43, 0xd661, 0x3269, 0x0000, 0x6749,
+ 0x4e57, 0x0000, 0x3c2b, 0xd662, 0xd663, 0x3d2d, 0x0000, 0x0000,
+ 0xd664, 0xd665, 0xd666, 0x3b6a, 0x4357, 0xd667, 0xd668, 0x0000,
+ 0xd669, 0xd66a, 0x674a, 0x674b, 0x3131, 0xd66b, 0x674c, 0xd66c
+};
+
+static const unsigned short jis_from_unicode_82[] = {
+ 0xd66d, 0x674d, 0x674e, 0xd66e, 0x0000, 0x674f, 0x0000, 0x6750,
+ 0x363d, 0x5a2a, 0x6751, 0x0000, 0x4065, 0x6752, 0x3c4b, 0xd66f,
+ 0x6753, 0x0000, 0x5030, 0xd670, 0xd671, 0x0000, 0x6754, 0x4a5e,
+ 0x345c, 0xd672, 0xd673, 0x4124, 0x3d58, 0xd674, 0x4971, 0x3d2e,
+ 0x0000, 0xd675, 0xd676, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd677, 0x6755, 0x3952, 0x6756, 0x484c, 0x0000, 0x6764, 0x0000,
+ 0x0000, 0x0000, 0xd678, 0x6758, 0xd679, 0x4249, 0x4775, 0x383f,
+ 0x6757, 0x4125, 0xd67a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6759, 0x0000, 0x0000, 0xd67b, 0xd67c, 0xd67d, 0xd67e, 0x447a,
+ 0x0000, 0x0000, 0x0000, 0xd721, 0x0000, 0x0000, 0xd722, 0xd723,
+ 0x0000, 0xd724, 0x0000, 0x0000, 0x0000, 0x0000, 0xd725, 0x0000,
+ 0x675b, 0x675a, 0x675d, 0x0000, 0xd726, 0x675c, 0x0000, 0x675e,
+ 0xd727, 0x0000, 0x6760, 0xd728, 0x675f, 0x0000, 0x344f, 0xd729,
+ 0x6761, 0x0000, 0x6762, 0x6763, 0x0000, 0xd72a, 0x3a31, 0x4e49,
+ 0x0000, 0x6765, 0x3f27, 0x0000, 0xd72b, 0x0000, 0x3170, 0x6766,
+ 0x6767, 0x0000, 0x0000, 0xd72c, 0x0000, 0xd72d, 0x6768, 0xd72e,
+ 0xd72f, 0xd730, 0x0000, 0xd731, 0xd732, 0x0000, 0x0000, 0xd733,
+ 0x0000, 0xd734, 0xd735, 0x3072, 0x0000, 0x6769, 0xd736, 0x0000,
+ 0x0000, 0xd737, 0x676a, 0x0000, 0xd738, 0x0000, 0xd739, 0x0000,
+ 0xd73a, 0x4967, 0xd73b, 0xd73c, 0x0000, 0x3c47, 0x0000, 0x676c,
+ 0xd73d, 0xd73e, 0x0000, 0xd73f, 0xd740, 0x3329, 0x3032, 0xd741,
+ 0xd742, 0xd743, 0xd744, 0x676b, 0x676e, 0x474e, 0xd745, 0x3f44,
+ 0xd746, 0x3256, 0xd747, 0x4b27, 0xd748, 0x0000, 0x0000, 0xd749,
+ 0x375d, 0x365c, 0xd74a, 0x676d, 0xd74b, 0x326a, 0xd74c, 0xd74d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3423, 0xd74e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd74f, 0x3171, 0x6772, 0x4e6a, 0x425d, 0xd750, 0x0000, 0x4944,
+ 0x0000, 0x677e, 0xd751, 0x3257, 0x677c, 0x0000, 0x677a, 0x6771,
+ 0xd752, 0x676f, 0xd753, 0x6770, 0xd754, 0x3c63, 0x366c, 0x4377,
+ 0xd755, 0x0000, 0xd756, 0x4651, 0x0000, 0xd757, 0x0000, 0xd758,
+ 0x0000, 0x3151, 0x0000, 0x6774, 0x6773, 0x0000, 0xd759, 0xd75a,
+ 0x0000, 0x6779, 0x6775, 0x6778, 0x0000, 0xd75b, 0xd75c, 0x0000
+};
+
+static const unsigned short jis_from_unicode_83[] = {
+ 0xd75d, 0xd75e, 0x4c50, 0x6777, 0x3258, 0x337d, 0x677b, 0xd75f,
+ 0xd760, 0x677d, 0xd761, 0xd762, 0x0000, 0x0000, 0x3754, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6823, 0x682c,
+ 0x682d, 0x0000, 0x0000, 0xd764, 0x302b, 0xd765, 0xd766, 0xd767,
+ 0x0000, 0xd768, 0xd769, 0x6834, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3071, 0x0000, 0x0000, 0x682b, 0xd76a, 0xd76b, 0xd76c, 0x682a,
+ 0xd76d, 0x6825, 0x6824, 0xd76e, 0x6822, 0x6821, 0x4363, 0xd76f,
+ 0x427b, 0x6827, 0xd770, 0x0000, 0xd771, 0xd772, 0x0000, 0x0000,
+ 0x6826, 0x0000, 0xd773, 0xd774, 0xd775, 0x6829, 0x0000, 0xd776,
+ 0x0000, 0x4170, 0x3755, 0x0000, 0x0000, 0xd777, 0xd778, 0x3141,
+ 0x6828, 0xd779, 0x3953, 0xd83e, 0xd763, 0xd77a, 0xd77b, 0xd77c,
+ 0x4171, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd77d, 0x0000, 0x0000, 0x683a, 0x0000, 0x683b, 0x0000, 0x3259,
+ 0xd77e, 0x0000, 0x0000, 0x322e, 0x6838, 0xd821, 0x0000, 0xd822,
+ 0xd823, 0x0000, 0xd824, 0x0000, 0xd825, 0x682e, 0xd826, 0x6836,
+ 0x0000, 0x683d, 0x6837, 0x0000, 0x0000, 0xd827, 0x6835, 0x0000,
+ 0x0000, 0x0000, 0xd828, 0x6776, 0xd829, 0xd82a, 0x6833, 0x0000,
+ 0xd82b, 0xd82c, 0x682f, 0xd82d, 0xd82e, 0xd82f, 0x3450, 0x6831,
+ 0x683c, 0x0000, 0x6832, 0x0000, 0x0000, 0x0000, 0xd830, 0xd831,
+ 0x683e, 0xd832, 0x6830, 0x477c, 0xd833, 0xd84c, 0x0000, 0x0000,
+ 0x0000, 0x4d69, 0x0000, 0x0000, 0x0000, 0x6839, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x684f, 0xd834, 0xd835,
+ 0xd836, 0x6847, 0x0000, 0x0000, 0x0000, 0x3f7b, 0x0000, 0xd837,
+ 0x0000, 0xd838, 0x3546, 0x0000, 0x365d, 0x0000, 0x6842, 0xd839,
+ 0xd83a, 0xd83b, 0x0000, 0x325b, 0xd83c, 0x0000, 0x3e54, 0x0000,
+ 0x6845, 0x0000, 0x0000, 0x0000, 0x3a5a, 0xd83d, 0x0000, 0x4551,
+ 0x684a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd83f, 0x4a6e, 0xd840, 0x6841, 0x0000, 0x0000, 0x0000, 0x325a,
+ 0x3856, 0x4929, 0x684b, 0x0000, 0x683f, 0x0000, 0xd841, 0x6848,
+ 0xd842, 0xd843, 0x0000, 0x6852, 0xd844, 0x6843, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_84[] = {
+ 0x0000, 0xd845, 0x0000, 0x6844, 0x463a, 0x0000, 0xd846, 0x6849,
+ 0x0000, 0x0000, 0xd847, 0x6846, 0x4b28, 0x684c, 0x3060, 0xd848,
+ 0x0000, 0xd849, 0x0000, 0x6840, 0x0000, 0xd84a, 0x0000, 0x0000,
+ 0x0000, 0xd84b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x684e, 0x0000, 0x684d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x476b, 0x6854, 0x0000, 0x685f, 0x0000, 0x0000, 0xd84d,
+ 0x0000, 0x337e, 0x0000, 0x0000, 0x0000, 0x6862, 0x0000, 0x0000,
+ 0x6850, 0xd84e, 0x0000, 0x0000, 0x6855, 0x4d6e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd84f, 0x685e, 0xd850,
+ 0xd851, 0x4d55, 0xd852, 0x0000, 0x0000, 0xd853, 0x4e2a, 0xd854,
+ 0x0000, 0xd855, 0xd856, 0x0000, 0x0000, 0x0000, 0xd857, 0x4378,
+ 0xd858, 0xd859, 0xd85a, 0x336b, 0xd85b, 0x0000, 0x0000, 0x0000,
+ 0xd85c, 0x4972, 0x6864, 0x4621, 0xd85d, 0xd85e, 0x3031, 0xd85f,
+ 0x0000, 0x685d, 0xd860, 0x6859, 0x4172, 0x6853, 0x685b, 0x6860,
+ 0xd861, 0x472c, 0x0000, 0xd862, 0xd863, 0x302a, 0xd864, 0x6858,
+ 0xd865, 0x6861, 0x4978, 0x0000, 0xd866, 0xd867, 0x0000, 0x0000,
+ 0x0000, 0xd868, 0x685c, 0x0000, 0x6857, 0xd869, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3e55, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d2f, 0x0000, 0xd86a, 0xd86b, 0x3c2c, 0xd86c, 0x0000, 0x0000,
+ 0x0000, 0x4c58, 0x0000, 0x0000, 0x4947, 0x0000, 0xd86d, 0x6867,
+ 0x0000, 0x6870, 0x0000, 0x0000, 0x0000, 0x0000, 0xd86e, 0x0000,
+ 0xd86f, 0xd870, 0xd871, 0x0000, 0x0000, 0x685a, 0x0000, 0xd872,
+ 0x0000, 0xd873, 0x3377, 0x0000, 0xd874, 0x0000, 0x0000, 0x0000,
+ 0x3e78, 0x6865, 0xd875, 0x686a, 0x4173, 0xd876, 0xd877, 0x6866,
+ 0xd878, 0x686d, 0xd879, 0x0000, 0x435f, 0x0000, 0x686e, 0xd87a,
+ 0xd87b, 0x4d56, 0x6863, 0x3338, 0xd87c, 0x6869, 0x0000, 0xd87d,
+ 0x686c, 0x4c2c, 0x0000, 0xd87e, 0x0000, 0x0000, 0x686f, 0x0000,
+ 0x0000, 0x6868, 0x686b, 0x0000, 0xd921, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd922,
+ 0x0000, 0x0000, 0xd923, 0x0000, 0x4b29, 0x0000, 0x4f21, 0xd924,
+ 0xd925, 0xd926, 0xd927, 0x0000, 0x6873, 0x0000, 0x0000, 0xd928,
+ 0x0000, 0x0000, 0xd92a, 0xd92b, 0x687a, 0xd92c, 0x0000, 0x6872
+};
+
+static const unsigned short jis_from_unicode_85[] = {
+ 0x3c43, 0x0000, 0xd92d, 0xd92e, 0x0000, 0x0000, 0x6851, 0xd92f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd930, 0x0000, 0xd931, 0x0000,
+ 0xd932, 0x4a4e, 0x0000, 0x4c22, 0x6879, 0x6878, 0x0000, 0x6874,
+ 0x6875, 0x0000, 0x3136, 0x0000, 0xd933, 0x0000, 0xd934, 0x6877,
+ 0x0000, 0x6871, 0xd935, 0xd936, 0xd937, 0xd938, 0x4455, 0xd939,
+ 0x0000, 0x0000, 0xd93a, 0xd93b, 0x6876, 0x307e, 0x0000, 0xd93c,
+ 0x0000, 0x0000, 0xd929, 0xd93d, 0xd93e, 0x4222, 0xd93f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a43, 0x0000, 0xd940,
+ 0x687b, 0x6921, 0x0000, 0x4859, 0x0000, 0x0000, 0xd941, 0x0000,
+ 0x687e, 0x3e56, 0x3c49, 0x6923, 0x0000, 0x0000, 0x363e, 0xd942,
+ 0xd943, 0xd944, 0xd945, 0xd946, 0x0000, 0x6924, 0xd947, 0x4979,
+ 0x687d, 0xd948, 0x6856, 0x0000, 0xd949, 0xd94a, 0xd94b, 0xd94c,
+ 0xd94d, 0xd94e, 0xd94f, 0x687c, 0xd950, 0x0000, 0x0000, 0x0000,
+ 0x4f4f, 0x4622, 0x4973, 0xd951, 0x0000, 0x692b, 0x0000, 0xd952,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6931,
+ 0x0000, 0xd953, 0xd954, 0xd955, 0x0000, 0xd956, 0x6932, 0xd957,
+ 0x6925, 0xd958, 0x0000, 0x0000, 0x4776, 0xd959, 0xd95a, 0x692f,
+ 0x6927, 0xd95b, 0x6929, 0xd95c, 0xd95d, 0x0000, 0x0000, 0xd95e,
+ 0x6933, 0x6928, 0x0000, 0xd95f, 0x692c, 0x0000, 0x0000, 0x3172,
+ 0xd960, 0x4665, 0x0000, 0x692d, 0x6930, 0xd961, 0x0000, 0xd962,
+ 0xd963, 0x0000, 0xd964, 0x0000, 0x6926, 0xd965, 0x4126, 0xd966,
+ 0x692a, 0x3b27, 0x3f45, 0x3730, 0x4c74, 0xd974, 0x4c79, 0x3d72,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd967, 0x0000, 0xd968, 0xd969,
+ 0xd96a, 0x6937, 0x6935, 0x0000, 0xd96b, 0xd96c, 0xd96d, 0xd96e,
+ 0x0000, 0x4f4e, 0xd96f, 0x0000, 0x0000, 0x0000, 0x0000, 0xd970,
+ 0x0000, 0x6934, 0xd971, 0xd972, 0x0000, 0x4d75, 0xd973, 0x6936,
+ 0x6938, 0x0000, 0x0000, 0x0000, 0x0000, 0x6939, 0x0000, 0x0000,
+ 0xd975, 0x0000, 0xd976, 0x0000, 0x693c, 0x693a, 0x0000, 0xd977,
+ 0xd978, 0x0000, 0x0000, 0x0000, 0x4623, 0x693b, 0xd979, 0x0000,
+ 0xd97a, 0x484d, 0x692e, 0x0000, 0x0000, 0xd97b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xd97c, 0x0000, 0x0000, 0xd97d, 0x3d73,
+ 0x0000, 0x693d, 0x6942, 0x4174, 0xd97e, 0x0000, 0x6941, 0xda21
+};
+
+static const unsigned short jis_from_unicode_86[] = {
+ 0xda22, 0x0000, 0x6922, 0x0000, 0xda23, 0xda24, 0x6943, 0x4149,
+ 0x0000, 0x0000, 0x693e, 0x6940, 0x0000, 0xda25, 0xda26, 0x0000,
+ 0xda27, 0xda28, 0xda29, 0x693f, 0x0000, 0x0000, 0x5d31, 0x5d22,
+ 0xda2a, 0xda2b, 0x6945, 0xda2c, 0x0000, 0x0000, 0xda2d, 0x0000,
+ 0x0000, 0xda2e, 0x6944, 0x0000, 0x0000, 0x0000, 0x0000, 0xda2f,
+ 0x0000, 0xda30, 0x0000, 0x0000, 0x0000, 0x4d76, 0x0000, 0x623c,
+ 0x6946, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xda31, 0x0000,
+ 0xda32, 0x0000, 0xda33, 0x0000, 0xda34, 0xda35, 0x0000, 0x6947,
+ 0xda36, 0xb866, 0xda37, 0x0000, 0x0000, 0x0000, 0xda38, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6948, 0x3857, 0x0000,
+ 0x3554, 0x0000, 0xda39, 0xda3a, 0x694a, 0x515d, 0xda3b, 0xda3c,
+ 0xda3d, 0xda3e, 0x3575, 0x0000, 0x4e3a, 0xda3f, 0x3673, 0x694b,
+ 0xda40, 0xda41, 0xda42, 0xda43, 0xda44, 0x0000, 0x0000, 0x694c,
+ 0x0000, 0xda45, 0x0000, 0x436e, 0xda46, 0x0000, 0x0000, 0xda47,
+ 0x0000, 0x694d, 0x0000, 0x0000, 0x0000, 0xda48, 0xda49, 0xda4a,
+ 0x0000, 0x467a, 0xda4b, 0x303a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xda6d, 0x0000, 0x3263, 0x6952, 0x6953, 0xda4c, 0x0000, 0x0000,
+ 0x0000, 0xda4d, 0x0000, 0x694e, 0x0000, 0x3b3d, 0xda4e, 0x0000,
+ 0xda4f, 0x0000, 0xda50, 0x0000, 0xda51, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xda52, 0x0000, 0x694f, 0x4742, 0x0000, 0xda53, 0xda54,
+ 0xda55, 0x6950, 0x6951, 0x695b, 0x0000, 0xda56, 0x0000, 0x6955,
+ 0x6958, 0xda57, 0x0000, 0xda58, 0xda59, 0xda5a, 0x6954, 0xda5b,
+ 0xda5c, 0xda5d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xda5e,
+ 0xda5f, 0xda60, 0x0000, 0xda61, 0x6956, 0xda62, 0x6957, 0x3c58,
+ 0x0000, 0x6959, 0x0000, 0x4341, 0x0000, 0x3756, 0x3342, 0x0000,
+ 0x0000, 0xda63, 0xda64, 0x0000, 0x695c, 0xda65, 0x0000, 0xda66,
+ 0x0000, 0x333f, 0xda67, 0x6961, 0xda68, 0x0000, 0x695d, 0x6960,
+ 0xda69, 0x0000, 0x0000, 0xda6a, 0x483a, 0xda6b, 0x0000, 0xda6c,
+ 0x0000, 0x695e, 0x0000, 0x0000, 0x695f, 0x4948, 0x485a, 0x6962,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x427d, 0x696c, 0xda6e, 0x6968, 0xda6f, 0xda70, 0x326b, 0x0000
+};
+
+static const unsigned short jis_from_unicode_87[] = {
+ 0x6966, 0x0000, 0x4b2a, 0x6967, 0xda71, 0xda72, 0x6964, 0xda73,
+ 0x6965, 0x696a, 0x696d, 0xda74, 0x0000, 0x696b, 0xda75, 0xda76,
+ 0xda77, 0x6969, 0x6963, 0xda78, 0xda79, 0x0000, 0x0000, 0x0000,
+ 0x4358, 0xda7a, 0x6974, 0x0000, 0x4c2a, 0x0000, 0xda7b, 0xda7c,
+ 0x0000, 0xda7d, 0x0000, 0xda7e, 0x0000, 0x6972, 0x0000, 0x0000,
+ 0xdb21, 0x6973, 0x0000, 0x0000, 0x0000, 0x0000, 0xdb22, 0xdb23,
+ 0x0000, 0xdb24, 0xdb25, 0x0000, 0x696e, 0x0000, 0x0000, 0x6970,
+ 0x0000, 0xdb26, 0xdb27, 0x6971, 0xdb28, 0xdb29, 0xdb2a, 0x696f,
+ 0xdb2b, 0x0000, 0x0000, 0xdb2c, 0x0000, 0xdb2d, 0x0000, 0x0000,
+ 0x0000, 0x4066, 0x0000, 0x4f39, 0x6978, 0xdb2e, 0x6979, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6a21, 0x0000, 0x3f2a, 0x0000, 0x697b,
+ 0xdb2f, 0x697e, 0x0000, 0x0000, 0x0000, 0xdb30, 0x0000, 0x6976,
+ 0x6975, 0xdb31, 0x0000, 0x6a22, 0xdb32, 0xdb33, 0x325c, 0x0000,
+ 0x697c, 0x0000, 0x6a23, 0x0000, 0x0000, 0x0000, 0x697d, 0xdb34,
+ 0x0000, 0xdb35, 0xdb36, 0x0000, 0x697a, 0x0000, 0x4433, 0x0000,
+ 0x6977, 0x0000, 0x0000, 0xdb37, 0x0000, 0x0000, 0x0000, 0x4768,
+ 0x0000, 0x0000, 0x6a27, 0xdb38, 0xdb39, 0xdb3a, 0xdb3b, 0xdb3c,
+ 0xdb3d, 0xdb3e, 0x0000, 0xdb3f, 0xdb40, 0x4d3b, 0x0000, 0x0000,
+ 0xdb41, 0x0000, 0x0000, 0xdb42, 0x0000, 0xdb43, 0x0000, 0xdb44,
+ 0xdb45, 0xdb46, 0x0000, 0x0000, 0x0000, 0x0000, 0xdb47, 0x6a26,
+ 0xdb48, 0x0000, 0x6a25, 0xdb49, 0x0000, 0x0000, 0x0000, 0xdb4a,
+ 0x0000, 0x0000, 0x0000, 0x6a2e, 0xdb4b, 0xdb4c, 0xdb4d, 0x6a28,
+ 0x0000, 0xdb4e, 0x0000, 0x6a30, 0x0000, 0xdb4f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4d66, 0x6a33, 0x0000, 0x6a2a, 0xdb50, 0xdb51,
+ 0x6a2b, 0xdb52, 0x0000, 0x0000, 0x6a2f, 0x0000, 0x6a32, 0x6a31,
+ 0xdb53, 0xdb54, 0xdb55, 0x6a29, 0x0000, 0x0000, 0xdb56, 0x0000,
+ 0x6a2c, 0x0000, 0x6a3d, 0x0000, 0x0000, 0xdb57, 0xdb58, 0x0000,
+ 0x0000, 0xdb59, 0xdb5a, 0x0000, 0xdb5b, 0x0000, 0x0000, 0xdb5c,
+ 0x6a36, 0x0000, 0xdb5d, 0xdb5e, 0xdb5f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xdb60, 0xdb61, 0x0000, 0xdb62, 0x0000, 0x6a34,
+ 0x0000, 0xdb63, 0x6a35, 0xdb64, 0x0000, 0x0000, 0x6a3a, 0x6a3b,
+ 0xdb65, 0x332a, 0xdb66, 0x3542, 0x0000, 0x0000, 0x6a39, 0xdb67
+};
+
+static const unsigned short jis_from_unicode_88[] = {
+ 0x0000, 0xdb68, 0x0000, 0xdb69, 0x0000, 0x6a24, 0xdb6a, 0x0000,
+ 0x0000, 0xdb6b, 0xdb6c, 0xdb6d, 0x0000, 0x6a38, 0x6a3c, 0x6a37,
+ 0xdb6e, 0x6a3e, 0xdb70, 0xdb71, 0xdb72, 0x6a40, 0x6a3f, 0x0000,
+ 0xdb73, 0xdb6f, 0xdb74, 0xdb75, 0xdb76, 0x0000, 0xdb77, 0xdb78,
+ 0x0000, 0x6a42, 0x6a41, 0x695a, 0x0000, 0x0000, 0x0000, 0x6a46,
+ 0xdb79, 0x0000, 0x0000, 0x0000, 0x0000, 0xdb7a, 0xdb7b, 0x0000,
+ 0xdb7c, 0x6a43, 0xdb7d, 0x0000, 0x0000, 0xdb7e, 0x6a44, 0x0000,
+ 0x0000, 0x6a45, 0xdc21, 0x6a47, 0xdc22, 0x0000, 0x0000, 0x0000,
+ 0x376c, 0xdc23, 0x6a49, 0xdc24, 0x6a48, 0xdc25, 0x3d30, 0x0000,
+ 0xdc26, 0xdc27, 0xdc28, 0xdc29, 0x3954, 0x5e27, 0xdc2a, 0x0000,
+ 0x0000, 0xdc2b, 0x6a4a, 0x3d51, 0x0000, 0xdc2c, 0xdc2d, 0x3339,
+ 0xdc2e, 0x6a4b, 0xdc2f, 0x3152, 0xdc30, 0x3e57, 0x6a4c, 0xdc31,
+ 0xdc32, 0x3955, 0x6a4d, 0x3061, 0xdc33, 0x0000, 0x0000, 0x0000,
+ 0x493d, 0xdc34, 0x0000, 0x6a4e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3f6a, 0xdc35, 0x6a55, 0x0000, 0x0000, 0x6a52, 0x0000, 0x436f,
+ 0x0000, 0xdc36, 0x0000, 0xdc37, 0x0000, 0x6a53, 0x6a50, 0x365e,
+ 0xdc38, 0x6a4f, 0x6a56, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3736, 0x0000, 0x0000, 0x425e, 0x0000, 0x6a5c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6a58, 0x0000, 0x0000, 0x0000, 0x4235, 0x6a57,
+ 0xdc39, 0x6a5a, 0xdc3a, 0xdc3b, 0xdc3c, 0x0000, 0x6a51, 0xdc3d,
+ 0xdc3e, 0x0000, 0x6a5b, 0x0000, 0x6a5d, 0x0000, 0x0000, 0x0000,
+ 0xdc3f, 0x0000, 0xdc40, 0x486f, 0x0000, 0x0000, 0x6a59, 0x0000,
+ 0x6a5e, 0x6a60, 0x0000, 0x0000, 0x3853, 0x6a54, 0x0000, 0x3041,
+ 0x0000, 0x0000, 0xdc41, 0x0000, 0x0000, 0xdc42, 0xdc43, 0x6a5f,
+ 0xdc44, 0x3a5b, 0x4e76, 0x6a61, 0x6a62, 0x4175, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xdc45, 0xdc46, 0xdc47, 0xdc48, 0xdc49, 0x4e22,
+ 0x0000, 0xdc4a, 0xdc4b, 0xdc4c, 0x6a63, 0x4d35, 0x0000, 0x0000,
+ 0x6a64, 0x6a65, 0x0000, 0xdc4d, 0x4a64, 0x6a66, 0xdc4e, 0x3a40,
+ 0x0000, 0x4e23, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdc4f,
+ 0x6a6b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdc50,
+ 0xdc51, 0xdc52, 0x6a6c, 0x3e58, 0x6a6a, 0xdc53, 0x0000, 0xdc54,
+ 0x4d67, 0x6a67, 0x0000, 0x0000, 0x6a69, 0x403d, 0x3f7e, 0x0000
+};
+
+static const unsigned short jis_from_unicode_89[] = {
+ 0x0000, 0xdc55, 0x6a68, 0x0000, 0x6a6d, 0x0000, 0xdc56, 0x4a23,
+ 0x0000, 0x0000, 0x6a6f, 0x0000, 0x6a6e, 0xdc57, 0xdc58, 0xdc59,
+ 0x336c, 0x0000, 0x4b2b, 0x6a70, 0x0000, 0xdc5a, 0xdc5b, 0x0000,
+ 0xdc5c, 0xdc5d, 0xdc5e, 0x0000, 0xdc5f, 0x6a7c, 0x6a72, 0x0000,
+ 0xdc60, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a73, 0xdc61, 0xdc62,
+ 0xdc63, 0x0000, 0x6a74, 0x6a75, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xdc64, 0xdc65, 0xdc66, 0x0000, 0x0000, 0xdc67, 0x6a79, 0x0000,
+ 0x6a7a, 0xdc68, 0xdc69, 0x6a78, 0x0000, 0x0000, 0xdc6a, 0x0000,
+ 0xdc6b, 0x6a76, 0xdc6c, 0x6a71, 0x6a77, 0xdc6d, 0xdc6e, 0x0000,
+ 0x0000, 0xdc6f, 0x0000, 0x0000, 0x6a7b, 0x7037, 0x0000, 0xdc70,
+ 0x0000, 0x0000, 0xdc71, 0x0000, 0x0000, 0x0000, 0x3228, 0xdc72,
+ 0x0000, 0x0000, 0xdc73, 0xdc74, 0xdc75, 0x0000, 0x6a7e, 0x365f,
+ 0x6a7d, 0xdc76, 0xdc77, 0xdc78, 0x6b22, 0x0000, 0x6b21, 0x0000,
+ 0x0000, 0x0000, 0x6b24, 0xdc79, 0x0000, 0x6b23, 0xdc7a, 0x6b25,
+ 0xdc7b, 0x0000, 0x3d31, 0xdc7c, 0x6b26, 0xdc7d, 0x0000, 0x6b27,
+ 0x0000, 0x0000, 0xdc7e, 0xdd21, 0xdd22, 0xdd23, 0x6b28, 0x403e,
+ 0x0000, 0x4d57, 0x0000, 0x6b29, 0x0000, 0x0000, 0x4a24, 0x4746,
+ 0x6b2a, 0xdd24, 0x6b2b, 0x382b, 0x0000, 0xdd25, 0x0000, 0x352c,
+ 0xdd26, 0x0000, 0x0000, 0x6b2c, 0xdd27, 0xdd28, 0x3b6b, 0x4741,
+ 0x6b2d, 0x0000, 0x3350, 0xdd29, 0xdd2a, 0x0000, 0x0000, 0xdd2b,
+ 0xdd2c, 0x6b2e, 0x0000, 0x0000, 0x0000, 0xdd2d, 0x6b30, 0x4d77,
+ 0x0000, 0x6b2f, 0x3f46, 0x0000, 0x6b31, 0x0000, 0x0000, 0x6b32,
+ 0xdd2e, 0x0000, 0x6b33, 0x3451, 0xdd2f, 0xdd30, 0xdd31, 0xdd32,
+ 0x0000, 0x0000, 0x6b34, 0x0000, 0xdd33, 0x6b35, 0x0000, 0x6b36,
+ 0x6b37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3351, 0x0000, 0xdd34, 0xdd35, 0xdd36, 0xdd37,
+ 0xdd38, 0x0000, 0x6b38, 0x0000, 0x6b39, 0x6b3a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3272, 0x0000, 0xdd39, 0x3f28, 0x6b3b,
+ 0x0000, 0xdd3a, 0x0000, 0xdd3b, 0x0000, 0xdd3c, 0x0000, 0x0000,
+ 0x0000, 0xdd3d, 0x0000, 0xdd3e, 0x6b3c, 0x0000, 0xdd3f, 0x0000,
+ 0x6b3d, 0xdd40, 0x0000, 0x0000, 0x0000, 0xdd41, 0x0000, 0xdd42
+};
+
+static const unsigned short jis_from_unicode_8a[] = {
+ 0x3840, 0x0000, 0x447b, 0x6b3e, 0xdd43, 0xdd44, 0x0000, 0xdd45,
+ 0x3757, 0x0000, 0x3f56, 0x0000, 0x6b41, 0x0000, 0x4624, 0xdd46,
+ 0x6b40, 0xdd47, 0xdd48, 0x3731, 0xdd49, 0xdd4a, 0x6b3f, 0x4277,
+ 0x352d, 0x0000, 0x0000, 0x6b42, 0x0000, 0x6b43, 0xdd4b, 0x3e59,
+ 0xdd4c, 0x0000, 0xdd4d, 0x376d, 0xdd4e, 0x6b44, 0xdd4f, 0x0000,
+ 0x0000, 0x0000, 0x4b2c, 0xdd50, 0xdd51, 0x405f, 0x0000, 0xdd52,
+ 0x0000, 0x3576, 0x0000, 0x4c75, 0x414a, 0xdd53, 0x6b45, 0xdd54,
+ 0x0000, 0x0000, 0x3f47, 0x4370, 0x3e5a, 0xdd55, 0xdd56, 0x0000,
+ 0xdd57, 0x6b46, 0x0000, 0xdd58, 0x0000, 0xdd59, 0x6b49, 0xdd5a,
+ 0x6b4a, 0xdd5b, 0x0000, 0x0000, 0x0000, 0xdd5c, 0xdd5d, 0x0000,
+ 0x3a3e, 0x4242, 0x6b48, 0xdd5e, 0x3e5b, 0x493e, 0xdd5f, 0xdd60,
+ 0xdd61, 0x0000, 0x0000, 0x6b47, 0xdd62, 0xdd63, 0x3b6c, 0x0000,
+ 0x3153, 0xdd64, 0x6b4e, 0x3758, 0x0000, 0xdd65, 0x3b6e, 0xdd66,
+ 0x0000, 0x3b6d, 0x0000, 0x4f4d, 0x6b4d, 0x6b4c, 0x4127, 0x0000,
+ 0x354d, 0x4f43, 0x333a, 0x3e5c, 0x0000, 0xdd67, 0xdd68, 0xdd69,
+ 0x0000, 0xdd6a, 0xdd6b, 0xdd6c, 0x6b4b, 0x0000, 0xdd6d, 0xdd6e,
+ 0xdd6f, 0x0000, 0x6b50, 0xdd70, 0x6b51, 0x6b4f, 0xdd71, 0x3858,
+ 0x0000, 0x4d40, 0x0000, 0xdd72, 0x3b6f, 0x4727, 0x0000, 0xdd73,
+ 0xdd74, 0x6b54, 0xdd75, 0x4040, 0x0000, 0x4342, 0xdd76, 0xdd77,
+ 0x4d36, 0xdd78, 0x6b57, 0x0000, 0x0000, 0x0000, 0x386c, 0xdd79,
+ 0x403f, 0x6b53, 0x0000, 0x6b58, 0x386d, 0x6b55, 0x6b56, 0xdd7a,
+ 0x6b52, 0xdd7b, 0x0000, 0x0000, 0x4062, 0x4649, 0xdd7c, 0xdd7d,
+ 0x432f, 0x0000, 0x325d, 0xdd7e, 0x0000, 0x0000, 0xde21, 0xde22,
+ 0x0000, 0x4870, 0x0000, 0xde23, 0x3543, 0x0000, 0xde24, 0x4434,
+ 0x0000, 0x0000, 0x6b5b, 0xde25, 0x6b59, 0x0000, 0xde26, 0x434c,
+ 0xde27, 0xde28, 0xde29, 0x4041, 0x3452, 0x6b5a, 0x0000, 0x3f5b,
+ 0x0000, 0xde2a, 0x4e4a, 0xde2b, 0xde2c, 0xde2d, 0x4f40, 0xde2e,
+ 0x0000, 0x0000, 0x6b5c, 0x6b67, 0x4435, 0xde2f, 0x6b66, 0xde30,
+ 0x6b63, 0x6b6b, 0x6b64, 0x0000, 0x6b60, 0x0000, 0x447c, 0x6b5f,
+ 0x0000, 0x0000, 0x0000, 0x6b5d, 0xde31, 0x4d21, 0x3b70, 0x0000,
+ 0xde32, 0x6b61, 0x0000, 0x6b5e, 0xde33, 0xde34, 0xde35, 0x6b65,
+ 0x3d74, 0x0000, 0x3841, 0x0000, 0xde36, 0x0000, 0x427a, 0xde37
+};
+
+static const unsigned short jis_from_unicode_8b[] = {
+ 0x4b45, 0x315a, 0x3062, 0x0000, 0x4625, 0xde38, 0xde39, 0x6b69,
+ 0x0000, 0x0000, 0xde3f, 0xde3a, 0x6b68, 0x0000, 0x4666, 0x0000,
+ 0x6b6d, 0xde3b, 0x0000, 0x0000, 0x6b62, 0x0000, 0x6b6c, 0x6b6e,
+ 0x0000, 0x382c, 0x6b6a, 0x3956, 0xde3c, 0x3c55, 0xde3d, 0xde3e,
+ 0x6b6f, 0x4d58, 0x0000, 0x0000, 0x0000, 0x0000, 0x6b72, 0x0000,
+ 0x6b75, 0x0000, 0x0000, 0x6b73, 0x4935, 0xde40, 0x0000, 0x0000,
+ 0xde41, 0x0000, 0x0000, 0x6b70, 0x0000, 0x0000, 0x0000, 0xde42,
+ 0x0000, 0x3660, 0x0000, 0x0000, 0xde43, 0x0000, 0x6b74, 0x0000,
+ 0x0000, 0x6b76, 0xde44, 0xde45, 0xde46, 0xde47, 0xde48, 0x0000,
+ 0xde49, 0x6b7a, 0x0000, 0x0000, 0x6b77, 0xde4e, 0x6b79, 0x6b78,
+ 0x0000, 0x0000, 0xde4a, 0xde4b, 0xde4c, 0x0000, 0x6b7b, 0x0000,
+ 0x3c31, 0xde4d, 0x6b7d, 0x6b7c, 0x4968, 0x0000, 0xde4f, 0x6c21,
+ 0x0000, 0x0000, 0x0000, 0xde50, 0x0000, 0x0000, 0x3759, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6b7e, 0x6c22, 0xde51, 0x0000, 0x6c23,
+ 0x3544, 0x6641, 0x3e79, 0x0000, 0x6c24, 0x0000, 0xde52, 0x386e,
+ 0xde53, 0xde54, 0x0000, 0x0000, 0xde55, 0x6c25, 0xde56, 0x0000,
+ 0x6c26, 0xde57, 0x0000, 0x3b3e, 0xde58, 0xde59, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5a4e, 0xde5a, 0x6c27, 0xde5b, 0x6c28, 0xde5c,
+ 0x3d32, 0x0000, 0x6c29, 0x6c2a, 0xde5d, 0xde5e, 0x6c2b, 0x0000,
+ 0x0000, 0x6c2c, 0x6c2d, 0x0000, 0xde5f, 0x0000, 0xde60, 0xde61,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_8c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x432b,
+ 0xde62, 0xde63, 0x6c2e, 0x0000, 0x0000, 0xde64, 0xde65, 0x6c30,
+ 0x0000, 0x6c2f, 0x0000, 0x0000, 0x0000, 0xde66, 0x4626, 0xde67,
+ 0x6c31, 0xde68, 0x4b2d, 0xde69, 0x6c32, 0x0000, 0x6c33, 0xde6a,
+ 0x6c34, 0xde6b, 0x0000, 0xde6c, 0xde6d, 0x6c35, 0x0000, 0xde6e,
+ 0xde6f, 0xde72, 0x465a, 0xde70, 0x0000, 0xde71, 0x0000, 0x0000,
+ 0x0000, 0x3e5d, 0x6c36, 0xde73, 0xde74, 0x0000, 0xde75, 0x0000,
+ 0xde76, 0xde77, 0x396b, 0x502e, 0x6c37, 0xde78, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xde79, 0x0000, 0xde7a, 0xde7b, 0x0000,
+ 0x6c38, 0x493f, 0x6c39, 0xde7c, 0x6c41, 0x0000, 0xde7d, 0x0000,
+ 0x0000, 0x0000, 0x6c3a, 0x0000, 0x0000, 0x6c3c, 0xde7e, 0xdf21,
+ 0x0000, 0x6c3b, 0x6c3d, 0xdf22, 0x4b46, 0x6c3e, 0x6c3f, 0x0000,
+ 0xdf23, 0x0000, 0xdf24, 0xdf25, 0x6c40, 0x0000, 0x0000, 0x0000,
+ 0x6c42, 0xdf26, 0x0000, 0xdf27, 0xdf28, 0x332d, 0x4467, 0x0000,
+ 0x4969, 0x3a62, 0x3957, 0x0000, 0xdf29, 0x0000, 0x0000, 0x494f,
+ 0x325f, 0x484e, 0x6c45, 0x3453, 0x4055, 0x6c44, 0x6c49, 0x4379,
+ 0x4c63, 0x0000, 0x6c47, 0x6c48, 0x352e, 0x0000, 0x6c4a, 0x4763,
+ 0x425f, 0xdf2a, 0xdf2b, 0x4871, 0x453d, 0x6c46, 0x0000, 0x4b47,
+ 0x326c, 0x6c4c, 0x4f28, 0x4442, 0x4f45, 0xdf2c, 0xdf2d, 0x3b71,
+ 0x6c4b, 0xdf2e, 0x4231, 0xdf2f, 0x0000, 0x6c5c, 0x4128, 0xdf30,
+ 0x0000, 0x4678, 0x0000, 0x4950, 0x0000, 0xdf32, 0xdf31, 0x0000,
+ 0x0000, 0xdf33, 0x6c4f, 0x3b3f, 0x3b72, 0xdf34, 0x3e5e, 0x0000,
+ 0x4765, 0xdf35, 0x382d, 0x6c4e, 0x6c4d, 0x0000, 0x496a, 0x0000,
+ 0xdf36, 0x0000, 0x3c41, 0x0000, 0xdf37, 0x4552, 0x0000, 0xdf38,
+ 0xdf39, 0x0000, 0xdf3a, 0x0000, 0x0000, 0xdf3b, 0x0000, 0xdf3c,
+ 0xdf3d, 0x0000, 0x6c51, 0x6c52, 0x3958, 0x6c50, 0xdf3e, 0xdf3f
+};
+
+static const unsigned short jis_from_unicode_8d[] = {
+ 0x0000, 0xdf40, 0x0000, 0xdf41, 0x6c53, 0x6c54, 0x0000, 0x6c56,
+ 0x4223, 0xdf42, 0x6c55, 0x3466, 0x0000, 0x6c58, 0x0000, 0x6c57,
+ 0x6c59, 0x0000, 0xdf43, 0x6c5b, 0x6c5d, 0x0000, 0x6c5e, 0xdf44,
+ 0x0000, 0x0000, 0x0000, 0xdf45, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4056, 0xdf46, 0x3c4f, 0x6c5f,
+ 0x0000, 0xdf47, 0x0000, 0x3352, 0xdf48, 0x6c60, 0xdf49, 0x0000,
+ 0x4176, 0x6c61, 0x0000, 0x6c62, 0x496b, 0x0000, 0x0000, 0x352f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdf4a,
+ 0x0000, 0x6c63, 0xdf4b, 0x0000, 0xdf4c, 0x4436, 0x0000, 0x0000,
+ 0xdf4d, 0x0000, 0x315b, 0x0000, 0x0000, 0xdf4e, 0x0000, 0x0000,
+ 0xdf4f, 0xdf50, 0x0000, 0x0000, 0x0000, 0xdf51, 0x0000, 0x0000,
+ 0x0000, 0x6c64, 0x0000, 0x0000, 0x0000, 0x0000, 0xdf52, 0xdf53,
+ 0xdf54, 0x0000, 0x0000, 0x3c71, 0x0000, 0x0000, 0xdf55, 0x0000,
+ 0x3f76, 0x0000, 0x0000, 0xdf56, 0xdf57, 0x0000, 0x0000, 0xdf58,
+ 0x0000, 0x0000, 0xdf59, 0x422d, 0x0000, 0xdf5a, 0x0000, 0xdf5b,
+ 0x0000, 0xdf5c, 0x6c67, 0xdf5d, 0xdf6f, 0x0000, 0x6c66, 0x0000,
+ 0xdf5e, 0x0000, 0x6c65, 0x0000, 0x0000, 0xdf5f, 0xdf60, 0xdf61,
+ 0xdf62, 0x0000, 0xdf63, 0x6c6d, 0x6c6b, 0x0000, 0xdf64, 0x6c68,
+ 0x0000, 0xdf65, 0x0000, 0x0000, 0xdf66, 0xdf67, 0x6c6a, 0xdf68,
+ 0x0000, 0xdf69, 0x6c69, 0x6c6c, 0x0000, 0x3577, 0x0000, 0x6c70,
+ 0x0000, 0x4057, 0x0000, 0x6c71, 0xdf6a, 0xdf6b, 0x0000, 0xdf6c,
+ 0x3859, 0x0000, 0x6c6e, 0x6c6f, 0xdf6d, 0x0000, 0x0000, 0x4f29,
+ 0xdf6e, 0xdf70, 0xdf71, 0x4437, 0xdf72, 0x4129, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6c72, 0xdf73, 0x0000, 0x6c75
+};
+
+static const unsigned short jis_from_unicode_8e[] = {
+ 0x0000, 0xdf74, 0x0000, 0x0000, 0xdf75, 0xdf76, 0xdf77, 0x0000,
+ 0x6c73, 0x6c74, 0x4d59, 0xdf78, 0x0000, 0x0000, 0x0000, 0x4627,
+ 0x6c78, 0xdf79, 0x0000, 0x0000, 0xdf7a, 0x0000, 0xdf7b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6c76, 0x6c77, 0x6c79,
+ 0xdf7c, 0xdf7d, 0xdf7e, 0xe021, 0x0000, 0x0000, 0xe022, 0xe023,
+ 0x0000, 0x0000, 0x6d29, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6c7c, 0xe024, 0x0000, 0xe025, 0x6c7d, 0x6c7b, 0xe026, 0xe027,
+ 0xe028, 0xe029, 0x0000, 0x0000, 0x0000, 0xe02a, 0x0000, 0x0000,
+ 0xe02b, 0xe02c, 0x6c7a, 0x0000, 0x447d, 0x0000, 0x0000, 0x6d21,
+ 0x6d25, 0x6d22, 0x6c7e, 0xe02d, 0x6d23, 0xe02e, 0xe02f, 0xe030,
+ 0x6d24, 0x0000, 0x0000, 0x0000, 0xe031, 0x6d2b, 0x0000, 0x0000,
+ 0x0000, 0x6d26, 0x0000, 0xe032, 0xe033, 0xe034, 0xe035, 0x4058,
+ 0x6d28, 0xe036, 0xe037, 0x6d2a, 0x6d27, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe038, 0x0000, 0x0000, 0xe039, 0xe03a, 0x0000, 0xe03b,
+ 0xe03c, 0xe03d, 0x6d2d, 0x0000, 0x3d33, 0x0000, 0x6d2c, 0x0000,
+ 0x0000, 0xe03e, 0xe03f, 0xe040, 0x6d2e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6d2f, 0xe041, 0xe042, 0x6d32, 0x6d31, 0x0000, 0x6d30,
+ 0x0000, 0xe043, 0x6d34, 0x6d33, 0x0000, 0x4c76, 0x0000, 0x0000,
+ 0xe044, 0x6d36, 0xe045, 0x6d35, 0x6d37, 0xe046, 0x0000, 0x0000,
+ 0x0000, 0x6d38, 0xe047, 0xe048, 0x0000, 0xe049, 0xe04a, 0x0000,
+ 0x0000, 0x6d3a, 0xe04b, 0x0000, 0x0000, 0x0000, 0x0000, 0xe04c,
+ 0x0000, 0xe04d, 0x6d39, 0x3f48, 0x6d3b, 0xe04e, 0xe04f, 0x366d,
+ 0x6d3c, 0x6d3e, 0x0000, 0xe050, 0x0000, 0xe051, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe052, 0xe053, 0x0000, 0x0000, 0x6d3f, 0x0000,
+ 0xe054, 0xe055, 0x0000, 0xe056, 0xe057, 0x6d40, 0x6d3d, 0xe058,
+ 0x6d41, 0x0000, 0x3c56, 0x6d42, 0x3530, 0x3733, 0x0000, 0xe059,
+ 0x0000, 0xe05a, 0x382e, 0x0000, 0xe05b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6d43, 0xe05c, 0x0000, 0x0000, 0x4670,
+ 0x0000, 0x0000, 0x453e, 0x6d44, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe05d, 0x0000, 0x0000, 0x6d47, 0x0000, 0xe064, 0xe05e, 0x0000,
+ 0xe05f, 0xe060, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe061,
+ 0x3c34, 0xe062, 0xe063, 0x6d46, 0x6d45, 0x375a, 0x6d48, 0x0000
+};
+
+static const unsigned short jis_from_unicode_8f[] = {
+ 0xe065, 0x0000, 0xe066, 0x3353, 0x0000, 0x6d4a, 0x0000, 0xe067,
+ 0xe068, 0x3a5c, 0x6d49, 0x0000, 0x6d52, 0x0000, 0x0000, 0xe069,
+ 0xe06a, 0x0000, 0x6d4c, 0x6d4e, 0x4a65, 0x6d4b, 0xe06b, 0xe06c,
+ 0xe06d, 0x6d4d, 0x0000, 0x6d51, 0x6d4f, 0x3531, 0xe06e, 0x6d50,
+ 0xe06f, 0xe070, 0x0000, 0xe071, 0x0000, 0xe072, 0x6d53, 0xe073,
+ 0xe074, 0x475a, 0x4e58, 0x0000, 0xe075, 0xe076, 0xe077, 0x3d34,
+ 0x0000, 0x0000, 0x0000, 0x6d54, 0xe078, 0xe079, 0xe07a, 0xe07b,
+ 0x4d22, 0x6d56, 0xe07c, 0x6d55, 0x0000, 0x0000, 0x6d59, 0x4d41,
+ 0xe07d, 0xe07e, 0x6d58, 0xe121, 0x336d, 0x6d57, 0x6d5c, 0xe122,
+ 0x0000, 0x6d5b, 0x0000, 0x0000, 0x6d5a, 0x4532, 0x6d5d, 0xe123,
+ 0x0000, 0xe124, 0xe125, 0xe126, 0xe127, 0xe128, 0x0000, 0x6d5e,
+ 0xe129, 0x0000, 0x0000, 0x0000, 0x6d5f, 0xe12a, 0xe12b, 0x396c,
+ 0x0000, 0x3725, 0x6d60, 0x6d61, 0x6d62, 0xe12c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3f49, 0x6d63, 0xe12d, 0x3c2d, 0x6d64,
+ 0xe12e, 0xe12f, 0x0000, 0x6d65, 0xe130, 0xe131, 0xe132, 0x5221,
+ 0x517e, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d66, 0x6570, 0x6d67,
+ 0x4324, 0x3f2b, 0x4740, 0x0000, 0x0000, 0xe133, 0xe134, 0x6d68,
+ 0xe135, 0x0000, 0x4a55, 0x4454, 0x397e, 0x0000, 0xe136, 0x4329,
+ 0xe137, 0xe138, 0x312a, 0x0000, 0x4b78, 0x3f57, 0xe139, 0x0000,
+ 0x0000, 0x0000, 0xe13a, 0xe13b, 0x0000, 0xe13c, 0x375e, 0x0000,
+ 0xe13d, 0x3661, 0xe13e, 0xe13f, 0x4a56, 0xe140, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6d69, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe141, 0x0000, 0x6d6b, 0xe142, 0xe143, 0x6d6a, 0x3260, 0x0000,
+ 0xe144, 0x4676, 0x6d6c, 0x4777, 0x0000, 0x4533, 0xe145, 0x6d6d,
+ 0x3d52, 0xe146, 0x0000, 0x0000, 0x6d6f, 0xe147, 0xe148, 0x4c42,
+ 0x6d7e, 0x6d71, 0x6d72, 0xe149, 0x0000, 0x4449, 0xe14a, 0x0000
+};
+
+static const unsigned short jis_from_unicode_90[] = {
+ 0x4260, 0x4177, 0xe14b, 0x4628, 0xe14c, 0x6d70, 0x3555, 0x0000,
+ 0xe14d, 0x0000, 0x0000, 0x6d79, 0xe14e, 0x6d76, 0x6e25, 0x4629,
+ 0x4360, 0x6d73, 0x0000, 0x447e, 0x4553, 0x6d74, 0x6d78, 0x3f60,
+ 0xe14f, 0x4767, 0x444c, 0xe150, 0x0000, 0x4042, 0x6d77, 0x422e,
+ 0x4224, 0x6d75, 0x3029, 0x4f22, 0x0000, 0x0000, 0x0000, 0x6d7a,
+ 0xe151, 0xe152, 0xe154, 0x0000, 0xe155, 0xe156, 0x4261, 0xe153,
+ 0x0000, 0x3d35, 0x3f4a, 0xe157, 0xe158, 0x6d7c, 0x6d7b, 0xe159,
+ 0x306f, 0x6d7d, 0x0000, 0x0000, 0x492f, 0x0000, 0x6e27, 0xe15a,
+ 0x0000, 0x465b, 0x3f6b, 0xe15b, 0xe15c, 0x4359, 0x0000, 0x3678,
+ 0x0000, 0x6e26, 0x4d37, 0x313f, 0xe15d, 0x4a57, 0x3261, 0x6e21,
+ 0x6e22, 0x6e23, 0x6e24, 0x463b, 0x4323, 0x3063, 0x6e28, 0x0000,
+ 0x6e29, 0x7423, 0x0000, 0xe15e, 0x423d, 0xe15f, 0x6e2a, 0x0000,
+ 0x3173, 0x414c, 0xe160, 0x382f, 0x0000, 0x4d5a, 0xe161, 0xe162,
+ 0x6e2b, 0x452c, 0x0000, 0x0000, 0xe163, 0x4178, 0x3c57, 0x6e2c,
+ 0xe164, 0x0000, 0x6e2f, 0x0000, 0xe165, 0x3d65, 0x6e2d, 0x412b,
+ 0x412a, 0xe166, 0x3064, 0x0000, 0x4e4b, 0x6e31, 0x0000, 0x4872,
+ 0x6e33, 0x6e32, 0x6e30, 0x6364, 0x3454, 0xe167, 0x0000, 0x6d6e,
+ 0xe168, 0x6e35, 0x6e34, 0xe169, 0xe16a, 0x0000, 0xe16b, 0x6e36,
+ 0xe16c, 0x4d38, 0x0000, 0x0000, 0x0000, 0xe16d, 0x0000, 0xe16e,
+ 0xe16f, 0xe170, 0x0000, 0xe171, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe172, 0xe173, 0xe174, 0x4661, 0x0000, 0xe175, 0x4b2e, 0x0000,
+ 0x6e37, 0x0000, 0x3c59, 0x0000, 0x0000, 0x0000, 0x0000, 0x6e38,
+ 0xe176, 0x6e39, 0xe177, 0xe178, 0xe179, 0x6e3a, 0xe17a, 0x0000,
+ 0x4521, 0x0000, 0x0000, 0x0000, 0x0000, 0xe17b, 0xe17d, 0x0000,
+ 0x0000, 0x306a, 0x0000, 0xe17e, 0xe221, 0xe222, 0x0000, 0xe223,
+ 0xe224, 0x0000, 0x3959, 0x0000, 0xe17c, 0x0000, 0x4f3a, 0x0000,
+ 0x0000, 0x0000, 0xe22d, 0x0000, 0x0000, 0xe225, 0x0000, 0xe226,
+ 0xe227, 0xe228, 0x0000, 0x6e3e, 0xe229, 0xe22a, 0x0000, 0xe22b,
+ 0x0000, 0x3734, 0x6e3b, 0x0000, 0x6e3c, 0xe22c, 0x0000, 0x0000,
+ 0x4974, 0x0000, 0x0000, 0xe22f, 0x0000, 0x3354, 0x0000, 0xe230,
+ 0xe231, 0x0000, 0x0000, 0x0000, 0xe232, 0x4d39, 0xe22e, 0x363f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4554, 0xe233, 0xe234
+};
+
+static const unsigned short jis_from_unicode_91[] = {
+ 0xe235, 0x0000, 0x6e3f, 0x0000, 0xe236, 0xe237, 0xe238, 0x0000,
+ 0xe239, 0x0000, 0x0000, 0x0000, 0x0000, 0xe23a, 0x0000, 0x0000,
+ 0xe23b, 0x0000, 0x6e40, 0x0000, 0xe23c, 0x0000, 0xe23d, 0xe23e,
+ 0xe23f, 0x6e41, 0xe240, 0x0000, 0xe241, 0x0000, 0xe242, 0x0000,
+ 0xe243, 0x0000, 0xe245, 0xe246, 0x0000, 0xe244, 0x0000, 0xe247,
+ 0x0000, 0xe248, 0x0000, 0x0000, 0x0000, 0x4522, 0xe249, 0xe24a,
+ 0x6e43, 0xe24b, 0x6e42, 0x0000, 0xe24c, 0x0000, 0xe24d, 0xe24e,
+ 0x0000, 0xe24f, 0xe250, 0x0000, 0xe251, 0xe252, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe253, 0x0000, 0x0000, 0x0000, 0xe254,
+ 0xe255, 0x4653, 0x6e44, 0x3d36, 0x3c60, 0x475b, 0x4371, 0xe256,
+ 0x0000, 0x0000, 0x3c72, 0xe257, 0x3f6c, 0x0000, 0x6e45, 0xe258,
+ 0x6e46, 0xe259, 0xe25a, 0xe25b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe25c, 0x3f5d, 0x6e47, 0xe25d, 0x6e48, 0x0000, 0xe25e,
+ 0x0000, 0x6e49, 0x4d6f, 0x0000, 0x3d37, 0xe25f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6e4b, 0x6e4a, 0xe260, 0x395a, 0x0000, 0x3973,
+ 0x3b40, 0xe261, 0xe262, 0xe263, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe264, 0x6e4e, 0xe265, 0x0000, 0xe266, 0xe267, 0x3d66,
+ 0x0000, 0x6e4d, 0xe268, 0x6e4c, 0x0000, 0x4269, 0xe269, 0x0000,
+ 0x386f, 0xe26a, 0x4043, 0xe26b, 0xe26c, 0xe26d, 0x0000, 0x4830,
+ 0xe26e, 0x0000, 0x0000, 0x0000, 0x3d39, 0x0000, 0xe26f, 0x0000,
+ 0x0000, 0xe270, 0x6e4f, 0x0000, 0x3e5f, 0x0000, 0xe271, 0x0000,
+ 0xe272, 0x0000, 0x6e52, 0x6e50, 0xe273, 0xe274, 0xe275, 0x6e51,
+ 0xe276, 0xe277, 0xe278, 0xe279, 0x6e54, 0x6e53, 0xe27a, 0x0000,
+ 0x3e7a, 0x0000, 0x6e55, 0xe27b, 0xe27c, 0xe27d, 0x0000, 0xe27e,
+ 0x6e56, 0x6e57, 0xe321, 0xe322, 0x0000, 0xe323, 0x4850, 0x3a53,
+ 0x3c61, 0x6e58, 0x0000, 0x6e59, 0x4e24, 0x3d45, 0x4c6e, 0x4e4c,
+ 0x6e5a, 0x3662, 0x0000, 0xe324, 0xe325, 0x0000, 0x6e5b, 0xe326,
+ 0x4523, 0xe327, 0xe328, 0x6e5e, 0x3378, 0x3f4b, 0xe329, 0x6e5c,
+ 0x0000, 0x6e5d, 0x0000, 0x4460, 0xe32a, 0xe32b, 0x4b55, 0x367c,
+ 0x0000, 0xe32c, 0xe32d, 0x0000, 0xe32e, 0xe32f, 0xe330, 0xe331,
+ 0xe332, 0xe333, 0x0000, 0x0000, 0x0000, 0x6e60, 0x6e61, 0xe334,
+ 0x0000, 0xe335, 0x0000, 0xe336, 0x6e5f, 0xe337, 0x0000, 0x6e63
+};
+
+static const unsigned short jis_from_unicode_92[] = {
+ 0xe338, 0xe339, 0x0000, 0x0000, 0xe33a, 0xe33b, 0xe33c, 0xe33d,
+ 0x0000, 0xe33e, 0xe33f, 0x0000, 0xe340, 0x465f, 0x3343, 0x0000,
+ 0xe341, 0x6e67, 0xe342, 0xe343, 0x6e64, 0x6e66, 0xe344, 0x0000,
+ 0xe345, 0x0000, 0x0000, 0x0000, 0xe346, 0xe347, 0x6e62, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe348, 0xe349, 0xe34a, 0xe34b, 0x0000,
+ 0xe34c, 0x6f4f, 0x0000, 0x0000, 0x6e65, 0x0000, 0xe34d, 0xe34e,
+ 0xe34f, 0x0000, 0x0000, 0xe350, 0x4e6b, 0xe351, 0xe352, 0x385a,
+ 0xe353, 0xe354, 0xe355, 0x0000, 0xe356, 0x0000, 0xe357, 0x6e6f,
+ 0xe358, 0x0000, 0xe359, 0xe35a, 0x4534, 0x6e6a, 0xe35b, 0xe35c,
+ 0x6e6d, 0x6e6b, 0xe35d, 0x6e70, 0x0000, 0xe35e, 0xe35f, 0xe360,
+ 0x6e71, 0xe361, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6e69,
+ 0xe362, 0xe363, 0x6e76, 0x3174, 0xe364, 0xe365, 0x6e68, 0x0000,
+ 0xe366, 0xe367, 0x482d, 0x0000, 0x6e6c, 0xe368, 0x3e60, 0xe369,
+ 0xe36a, 0xe36b, 0x0000, 0x0000, 0x0000, 0x0000, 0xe36c, 0xe36d,
+ 0xe36e, 0x395b, 0x0000, 0x0000, 0x0000, 0xe36f, 0xe370, 0xe371,
+ 0xe372, 0xe373, 0x0000, 0xe374, 0xe375, 0xe376, 0x4b48, 0xe377,
+ 0x3664, 0x0000, 0x0000, 0x3d46, 0x0000, 0x463c, 0x0000, 0x0000,
+ 0xe378, 0xe379, 0xe37a, 0x0000, 0x0000, 0xe37b, 0xe37c, 0x0000,
+ 0x0000, 0x412d, 0xe37d, 0x6e74, 0x0000, 0x6e6e, 0x6e73, 0xe37e,
+ 0x4c43, 0xe421, 0x4438, 0x6e75, 0x6e72, 0x0000, 0x0000, 0xe422,
+ 0xe423, 0x0000, 0x0000, 0x0000, 0xe424, 0xe425, 0x0000, 0xe426,
+ 0xe427, 0x0000, 0x0000, 0xe428, 0x0000, 0x412c, 0x0000, 0xe429,
+ 0x0000, 0x0000, 0xe42a, 0x0000, 0x0000, 0x0000, 0xe42b, 0x6e79,
+ 0xe42c, 0x6e78, 0xe42d, 0xe42e, 0xe42f, 0xe430, 0x0000, 0xe431,
+ 0xe432, 0xe433, 0xe434, 0xe435, 0x0000, 0xe436, 0xe437, 0xe438,
+ 0xe439, 0x0000, 0x0000, 0xe43a, 0xe43b, 0xe43c, 0xe43d, 0x6e77,
+ 0xe43e, 0x0000, 0x4b2f, 0xe43f, 0x0000, 0xe440, 0x0000, 0xe441,
+ 0xe442, 0xe443, 0x0000, 0x0000, 0xe444, 0xe445, 0x0000, 0xe446,
+ 0xe447, 0xe448, 0x0000, 0xe449, 0x3d7b, 0xe44a, 0x0000, 0xe44b,
+ 0xe44c, 0x6e7a, 0x4a5f, 0x0000, 0xe44d, 0x3154, 0xe44e, 0x0000,
+ 0xe44f, 0x0000, 0x4946, 0x4372, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3578, 0xe450, 0x6e7c, 0xe451, 0x395d, 0x0000, 0x0000, 0xe452
+};
+
+static const unsigned short jis_from_unicode_93[] = {
+ 0xe453, 0x0000, 0xe454, 0x0000, 0x0000, 0x0000, 0x3b2c, 0x0000,
+ 0xe455, 0x0000, 0x0000, 0x0000, 0x0000, 0xe456, 0x0000, 0x6e7b,
+ 0x3f6d, 0xe457, 0x0000, 0x0000, 0xe458, 0xe459, 0x0000, 0x0000,
+ 0x3f6e, 0x6f21, 0x6f23, 0x0000, 0xe45a, 0xe45b, 0xe45c, 0xe45d,
+ 0x3e7b, 0xe45e, 0x6f22, 0x6f24, 0xe45f, 0xe460, 0x3653, 0xe461,
+ 0x4945, 0xe462, 0xe463, 0x3c62, 0x4f23, 0x0000, 0x6e7e, 0x3a78,
+ 0x0000, 0x0000, 0x4f3f, 0xe464, 0xe465, 0x6f26, 0xe466, 0xe467,
+ 0x0000, 0x0000, 0x6f25, 0x6f27, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6e7d, 0x0000, 0x0000, 0xe468,
+ 0xe469, 0xe46a, 0x0000, 0x4669, 0x0000, 0x4555, 0x0000, 0x0000,
+ 0xe46b, 0xe46c, 0xe46d, 0x0000, 0x4457, 0xe46e, 0x6f2c, 0xe46f,
+ 0xe470, 0x0000, 0xe471, 0x4343, 0x6f28, 0x0000, 0xe472, 0x0000,
+ 0x6f29, 0x0000, 0x0000, 0x0000, 0xe473, 0xe474, 0x0000, 0xe475,
+ 0x0000, 0xe476, 0xe477, 0x0000, 0x372d, 0xe478, 0x6f2b, 0xe479,
+ 0xe47a, 0xe47b, 0x0000, 0xe47c, 0xe47d, 0x3830, 0xe47e, 0x0000,
+ 0x0000, 0x0000, 0xe521, 0x0000, 0x6f2a, 0xe522, 0x3e61, 0xe523,
+ 0xe524, 0xe525, 0xe526, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe527, 0x0000, 0xe528, 0xe529, 0x3379, 0xe52a, 0x0000, 0xe52b,
+ 0x0000, 0x0000, 0xe52c, 0x0000, 0x6f30, 0xe52d, 0x3a3f, 0x4179,
+ 0xe52e, 0x0000, 0x444a, 0xe52f, 0x0000, 0x0000, 0xe530, 0x0000,
+ 0x0000, 0xe531, 0x0000, 0xe532, 0xe533, 0x0000, 0xe534, 0x333b,
+ 0xe535, 0xe53b, 0x0000, 0xe536, 0x6f2e, 0x6f2f, 0x4443, 0x0000,
+ 0x6f2d, 0x0000, 0x0000, 0x0000, 0xe537, 0xe538, 0xe539, 0x0000,
+ 0x0000, 0x6f31, 0xe53a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe53c, 0x0000, 0x6f37, 0xe53d, 0xe53e, 0xe53f, 0xe540,
+ 0x6f3a, 0xe541, 0xe542, 0xe543, 0xe544, 0xe545, 0x0000, 0x0000,
+ 0x6f39, 0x452d, 0x0000, 0xe546, 0x0000, 0x0000, 0x6f32, 0x6f33,
+ 0x6f36, 0xe547, 0x0000, 0x0000, 0xe548, 0x6f38, 0xe549, 0xe54a,
+ 0x0000, 0x3640, 0xe54b, 0x0000, 0x6f3b, 0x6f35, 0xe54c, 0xe54d,
+ 0x6f34, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe54f,
+ 0xe550, 0xe54e, 0xe551, 0xe552, 0x0000, 0xe553, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_94[] = {
+ 0x0000, 0xe554, 0xe555, 0x6f3f, 0xe556, 0x0000, 0x0000, 0x6f40,
+ 0xe557, 0xe558, 0x0000, 0x0000, 0x0000, 0xe559, 0xe55a, 0xe55b,
+ 0x6f41, 0x0000, 0x0000, 0x6f3e, 0x6f3d, 0xe55c, 0xe55d, 0xe55e,
+ 0x3e62, 0x462a, 0x6f3c, 0x0000, 0x0000, 0x0000, 0x0000, 0xe55f,
+ 0x0000, 0x6f45, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6f43, 0x0000, 0x0000, 0xe560, 0xe561,
+ 0x0000, 0xe562, 0xe563, 0xe564, 0xe565, 0x6f44, 0x6f42, 0x0000,
+ 0x4278, 0x0000, 0x6f46, 0xe566, 0x0000, 0xe568, 0x0000, 0xe567,
+ 0x0000, 0x6f47, 0x0000, 0xe569, 0x6f49, 0xe56a, 0x0000, 0x0000,
+ 0xe56b, 0x0000, 0xe56c, 0x0000, 0xe56d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3455, 0x6f48, 0x4c7a, 0x0000, 0xe56e, 0x0000, 0x0000,
+ 0x0000, 0xe56f, 0x6f54, 0x6f4a, 0xe570, 0x0000, 0x6f4d, 0xe571,
+ 0x6f4b, 0xe572, 0x6f4c, 0xe573, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe574, 0x0000, 0x6f4e, 0xe575, 0x0000, 0xe576, 0xe577, 0xe578,
+ 0x6f50, 0xe579, 0xe57a, 0x0000, 0x0000, 0x6f51, 0x0000, 0x6f52,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6f55, 0x6f53, 0x6f56, 0x6f58,
+ 0x0000, 0x6f57, 0x0000, 0xe57c, 0xe57b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_95[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4439,
+ 0xe57d, 0xe57e, 0x0000, 0x0000, 0x0000, 0x0000, 0xe621, 0x0000,
+ 0x4c67, 0x0000, 0x6f59, 0x412e, 0xe622, 0x0000, 0x0000, 0x6f5a,
+ 0xe623, 0x4a44, 0x6f5b, 0x332b, 0xe624, 0xe625, 0xe626, 0x313c,
+ 0x0000, 0x3457, 0x0000, 0x3456, 0x6f5c, 0x0000, 0x6f5d, 0x0000,
+ 0x6f5e, 0x6f5f, 0x0000, 0x0000, 0x0000, 0xe627, 0xe628, 0xe629,
+ 0x6f60, 0xe62a, 0x3458, 0x3355, 0x395e, 0x4836, 0xe62b, 0x6f62,
+ 0x6f61, 0xe62c, 0x0000, 0xe62d, 0xe62e, 0x6f63, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x315c, 0x0000, 0xe62f, 0x0000, 0xe630, 0x0000,
+ 0x0000, 0x6f66, 0xe631, 0x6f65, 0x6f64, 0xe632, 0x6f67, 0xe633,
+ 0x0000, 0x0000, 0x0000, 0x6f6a, 0x0000, 0x0000, 0xe634, 0x3047,
+ 0xe635, 0xe636, 0x6f68, 0xe637, 0x6f6c, 0x6f6b, 0x0000, 0x0000,
+ 0xe638, 0xe639, 0xe63a, 0xe63b, 0x6f6e, 0x6f6d, 0x6f6f, 0x0000,
+ 0x462e, 0xe63c, 0xe63d, 0x0000, 0x6f70, 0xe63e, 0xe63f, 0xe640,
+ 0xe641, 0x6f71, 0x6f73, 0x0000, 0xe642, 0x6f72, 0xe643, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_96[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x496c, 0xe644, 0xe645, 0x0000,
+ 0x0000, 0x6f74, 0xe646, 0x0000, 0xe647, 0xe648, 0xe649, 0x0000,
+ 0x6f75, 0x0000, 0x3a65, 0x0000, 0xe64a, 0x0000, 0x6f76, 0x6f77,
+ 0x0000, 0xe64b, 0x4b49, 0xe64c, 0x0000, 0x0000, 0x0000, 0xe64d,
+ 0xe64e, 0xe64f, 0xe650, 0x414b, 0xe651, 0xe652, 0x0000, 0x3024,
+ 0x424b, 0xe653, 0x6f78, 0x0000, 0x496d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6f7b, 0x6f79, 0x395f, 0x0000, 0x6f7a,
+ 0x3842, 0x0000, 0xe654, 0x0000, 0xe655, 0x0000, 0xe656, 0xe657,
+ 0xe658, 0x0000, 0x0000, 0x4a45, 0x6f7d, 0x7021, 0x6f7e, 0x7022,
+ 0x0000, 0xe659, 0x3121, 0x3f58, 0x3d7c, 0x3459, 0x7023, 0x0000,
+ 0x0000, 0x0000, 0x4766, 0x0000, 0x7025, 0x0000, 0xe65a, 0x0000,
+ 0x3122, 0x0000, 0x7024, 0x4444, 0xe65b, 0x4e4d, 0x462b, 0x6f7c,
+ 0x4e26, 0x0000, 0x3831, 0xe65c, 0xe65d, 0x4d5b, 0xe65e, 0xe65f,
+ 0x0000, 0xe660, 0xe661, 0xe662, 0xe663, 0x3679, 0x4e34, 0x0000,
+ 0x3728, 0xe664, 0x4262, 0x6721, 0x0000, 0x7026, 0x332c, 0x3f6f,
+ 0x0000, 0xe665, 0x0000, 0x0000, 0x3356, 0x7028, 0xe666, 0x7029,
+ 0x7027, 0x3764, 0xe667, 0x3a5d, 0x3e63, 0xe668, 0x0000, 0xe669,
+ 0x3123, 0x0000, 0x0000, 0x4e59, 0xe66a, 0xe66b, 0xe66c, 0x702b,
+ 0x6e2e, 0xe66d, 0x702a, 0x0000, 0x0000, 0x0000, 0xe66e, 0xe66f,
+ 0x702e, 0x702c, 0x702d, 0xe670, 0x702f, 0x0000, 0x7030, 0x4e6c,
+ 0x7031, 0x7032, 0xe671, 0x4049, 0x483b, 0x0000, 0x0000, 0x0000,
+ 0x3f7d, 0x3467, 0x0000, 0x0000, 0x4d3a, 0x326d, 0x3d38, 0x385b,
+ 0x0000, 0x7035, 0xe672, 0x7034, 0x3b73, 0x7036, 0x7033, 0x0000,
+ 0x0000, 0x3b28, 0xe673, 0x0000, 0x0000, 0x703a, 0x6a2d, 0x0000,
+ 0xe675, 0x5256, 0xe676, 0x3f77, 0x7038, 0xe677, 0xe678, 0xe679,
+ 0x0000, 0x0000, 0x4e25, 0x4671, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x312b, 0xe67a, 0x4063, 0x3c36, 0x0000, 0x0000, 0x0000, 0xe67b,
+ 0x4a37, 0xe67c, 0x3140, 0x0000, 0x0000, 0x0000, 0x4e6d, 0x4d6b,
+ 0x0000, 0x703b, 0xe67d, 0x4545, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_97[] = {
+ 0x3c7b, 0x0000, 0xe67e, 0xe721, 0x703c, 0xe722, 0x703d, 0x3f4c,
+ 0x703e, 0xe723, 0x4e6e, 0x0000, 0x0000, 0x7039, 0x7040, 0x7042,
+ 0x0000, 0x7041, 0x0000, 0x703f, 0x0000, 0x0000, 0x7043, 0x0000,
+ 0x0000, 0x7044, 0xe724, 0xe725, 0x417a, 0xe726, 0x3262, 0x0000,
+ 0x0000, 0xe727, 0xe728, 0xe729, 0x7045, 0x0000, 0x0000, 0x4c38,
+ 0xe72a, 0x0000, 0x7046, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7047, 0xe72b, 0x4f2a, 0xe72c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5b31, 0x7048, 0x0000, 0x0000, 0x0000, 0x7049, 0x704a, 0x0000,
+ 0x0000, 0xe72d, 0x704e, 0xe72e, 0x704b, 0x0000, 0x704c, 0x0000,
+ 0x704d, 0x704f, 0xe72f, 0x0000, 0x0000, 0x0000, 0xe730, 0xe731,
+ 0x0000, 0x0000, 0x4044, 0x0000, 0x0000, 0xe732, 0x4c77, 0xe733,
+ 0xe734, 0x4045, 0xe735, 0xe736, 0x7050, 0x0000, 0x4873, 0x0000,
+ 0x7051, 0x7353, 0x4c4c, 0xe737, 0x7052, 0x0000, 0x7053, 0xe738,
+ 0x7054, 0x3357, 0xe739, 0x7056, 0x0000, 0x3f59, 0xe73a, 0x0000,
+ 0x0000, 0x7057, 0x0000, 0xe73b, 0x3724, 0x0000, 0xe73c, 0xe73d,
+ 0xe73e, 0x7058, 0x705c, 0xe73f, 0x705a, 0xe740, 0x0000, 0xe741,
+ 0xe742, 0x705b, 0x0000, 0x0000, 0x3373, 0x7059, 0x705d, 0x0000,
+ 0x0000, 0xe743, 0x0000, 0x705e, 0x0000, 0x3048, 0x0000, 0x705f,
+ 0x7060, 0x0000, 0x0000, 0x0000, 0x0000, 0xe744, 0xe745, 0xe746,
+ 0x3e64, 0xe747, 0xe748, 0x0000, 0x7061, 0x0000, 0xe749, 0xe74a,
+ 0x3547, 0x0000, 0xe74b, 0x7064, 0x0000, 0x0000, 0x7063, 0x0000,
+ 0x7062, 0x0000, 0x0000, 0x6b71, 0xe74c, 0x4a5c, 0xe74d, 0x0000,
+ 0x0000, 0xe74e, 0xe74f, 0x7065, 0x7066, 0xe750, 0xe751, 0x0000,
+ 0xe752, 0xe753, 0xe754, 0x0000, 0xe755, 0x0000, 0xe756, 0xe757,
+ 0x0000, 0xe758, 0x0000, 0x7067, 0xe759, 0xe75a, 0x7068, 0xe75b,
+ 0x7069, 0xe75c, 0xe75d, 0x706a, 0xe75e, 0xe75f, 0xe760, 0x0000,
+ 0xe761, 0xe762, 0x0000, 0x345a, 0xe763, 0x0000, 0x0000, 0xe764,
+ 0xe765, 0xe766, 0x0000, 0xe76a, 0x706b, 0xe767, 0xe768, 0x0000,
+ 0xe769, 0xe76b, 0x0000, 0x0000, 0xe76c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x706c, 0x4723, 0xe76d,
+ 0x0000, 0xe76e, 0x706e, 0x323b, 0xe76f, 0x7071, 0x7070, 0xe770,
+ 0xe771, 0x0000, 0xe772, 0x3124, 0x0000, 0x0000, 0x0000, 0x3641
+};
+
+static const unsigned short jis_from_unicode_98[] = {
+ 0x0000, 0x4a47, 0x443a, 0x3a22, 0x0000, 0x3960, 0x3d67, 0xe773,
+ 0x3f5c, 0x0000, 0xe774, 0x0000, 0x7073, 0xe776, 0xe777, 0x7072,
+ 0x4d42, 0x3468, 0x4852, 0x465c, 0xe778, 0x0000, 0xe779, 0x3f7c,
+ 0x4e4e, 0xe775, 0x375b, 0x0000, 0xe77a, 0x0000, 0xe77b, 0x0000,
+ 0xe77c, 0x7076, 0x0000, 0xe77d, 0x7075, 0xe828, 0xe77e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe821, 0x4b4b, 0x462c, 0xe822, 0xe823,
+ 0xe824, 0x0000, 0xe825, 0xe826, 0x3150, 0xe827, 0x0000, 0x7077,
+ 0x7074, 0x0000, 0x0000, 0x4951, 0x4d6a, 0x7078, 0xe829, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe82a, 0x0000, 0x7079, 0xe82b,
+ 0x0000, 0x0000, 0xe82c, 0x707b, 0x426a, 0x335b, 0x335c, 0x707a,
+ 0x0000, 0xe82d, 0xe82e, 0xe82f, 0x3469, 0x3832, 0xe830, 0xe831,
+ 0x346a, 0xe832, 0xe833, 0x453f, 0x0000, 0x0000, 0x4e60, 0x0000,
+ 0x0000, 0x0000, 0xe834, 0xe835, 0x0000, 0xe836, 0xe837, 0x385c,
+ 0x0000, 0x0000, 0xe838, 0x707c, 0xe839, 0x0000, 0x0000, 0x707d,
+ 0x707e, 0x7121, 0x0000, 0x7123, 0x7122, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4977, 0x0000, 0x7124, 0xe83a, 0x0000, 0xe83b, 0xe83c, 0x7125,
+ 0xe83d, 0x7126, 0x0000, 0x0000, 0xe83e, 0x0000, 0x7127, 0xe83f,
+ 0xe840, 0x0000, 0xe841, 0xe842, 0x0000, 0x0000, 0x0000, 0xe843,
+ 0x0000, 0x0000, 0xe844, 0x7129, 0x7128, 0xe845, 0x712a, 0x0000,
+ 0xe846, 0x0000, 0x0000, 0x0000, 0xe847, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4874, 0x664c, 0x0000, 0x0000, 0x3f29,
+ 0x0000, 0xe848, 0x3532, 0xe849, 0x0000, 0xe84a, 0xe84b, 0xe84c,
+ 0x0000, 0x712b, 0xe84d, 0x712c, 0x0000, 0x522c, 0x5d3b, 0x4853,
+ 0x0000, 0x0000, 0x307b, 0xe84e, 0x303b, 0x0000, 0xe84f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3b74, 0x4b30, 0x3e7e, 0x0000
+};
+
+static const unsigned short jis_from_unicode_99[] = {
+ 0x0000, 0x0000, 0xe850, 0x712d, 0x0000, 0x4c5f, 0x0000, 0xe851,
+ 0xe852, 0x712e, 0x4d5c, 0x0000, 0x3142, 0x0000, 0x0000, 0x0000,
+ 0x3b41, 0xe853, 0x712f, 0x326e, 0x7130, 0xe854, 0xe855, 0xe856,
+ 0x7131, 0x0000, 0xe857, 0xe858, 0xe859, 0x7133, 0x7134, 0xe85a,
+ 0x7136, 0x7132, 0xe85b, 0x0000, 0x7135, 0x0000, 0xe85c, 0xe85d,
+ 0x345b, 0x0000, 0x0000, 0xe85e, 0x7137, 0x0000, 0x7138, 0x0000,
+ 0x0000, 0xe85f, 0xe860, 0xe861, 0xe862, 0xe863, 0x0000, 0x0000,
+ 0x0000, 0xe864, 0xe865, 0xe866, 0xe867, 0x7139, 0x713a, 0x0000,
+ 0xe868, 0xe869, 0x713b, 0x0000, 0x0000, 0x713d, 0xe86a, 0xe86b,
+ 0xe86c, 0x713c, 0x0000, 0x713f, 0x7142, 0xe86d, 0xe86e, 0x0000,
+ 0x713e, 0x7140, 0x7141, 0x0000, 0xe86f, 0x7143, 0x0000, 0x3642,
+ 0xe870, 0xe871, 0x0000, 0xe872, 0xe873, 0x0000, 0xe874, 0xe875,
+ 0xe876, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3c73, 0x7144,
+ 0x7145, 0x3961, 0x0000, 0xe877, 0x0000, 0xe878, 0x0000, 0xe879,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7146, 0xe87a, 0x0000,
+ 0x333e, 0x0000, 0x0000, 0x0000, 0x474f, 0x7147, 0x7148, 0x0000,
+ 0xe87b, 0xe87c, 0xe87d, 0x435a, 0x466b, 0xe87e, 0x0000, 0x0000,
+ 0x0000, 0xe921, 0xe922, 0x0000, 0x7149, 0xe923, 0x0000, 0xe924,
+ 0x0000, 0x477d, 0x0000, 0xe925, 0x424c, 0x3158, 0x366e, 0x0000,
+ 0x366f, 0xe926, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4373, 0x714e, 0x3670, 0xe927, 0xe928, 0x326f, 0x0000, 0x0000,
+ 0x714d, 0xe929, 0xe92a, 0x714b, 0xe92b, 0x714c, 0xe92c, 0x714a,
+ 0x0000, 0x0000, 0x7158, 0x0000, 0x0000, 0x0000, 0x0000, 0xe92d,
+ 0x0000, 0x0000, 0xe92e, 0xe92f, 0xe930, 0x714f, 0x7150, 0x0000,
+ 0xe931, 0x7151, 0x7152, 0x0000, 0xe932, 0xe933, 0x0000, 0x0000,
+ 0x7154, 0xe934, 0x0000, 0x7153, 0x0000, 0xe935, 0xe936, 0x3d59
+};
+
+static const unsigned short jis_from_unicode_9a[] = {
+ 0x0000, 0x7155, 0xe937, 0xe938, 0xe939, 0x7157, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe93a, 0xe93b, 0x0000, 0x3533, 0x7156,
+ 0xe93c, 0xe93d, 0x417b, 0x3833, 0x0000, 0x0000, 0xe93e, 0x0000,
+ 0x0000, 0x7159, 0x0000, 0x0000, 0x0000, 0x0000, 0xe93f, 0x0000,
+ 0xe940, 0x0000, 0xe941, 0xe942, 0xe943, 0x0000, 0x0000, 0xe944,
+ 0x424d, 0x0000, 0x0000, 0x715a, 0x0000, 0xe945, 0xe946, 0x0000,
+ 0x462d, 0x0000, 0x0000, 0xe947, 0x0000, 0xe948, 0xe949, 0x715b,
+ 0xe94a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7160, 0x0000,
+ 0x715e, 0xe94c, 0x715d, 0x715f, 0xe94d, 0x715c, 0x0000, 0xe94b,
+ 0x0000, 0x0000, 0xe94e, 0xe94f, 0xe950, 0x7162, 0xe951, 0x0000,
+ 0x0000, 0xe952, 0x0000, 0x0000, 0xe953, 0x7161, 0xe954, 0x7164,
+ 0x0000, 0x0000, 0x3643, 0x7163, 0x0000, 0xe955, 0x0000, 0x7165,
+ 0x0000, 0x0000, 0x7166, 0x0000, 0x7168, 0x7167, 0x0000, 0x0000,
+ 0x0000, 0x7169, 0x716b, 0x716a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x397c, 0x0000, 0xe956, 0x0000, 0xe957, 0x716c, 0xe958, 0xe959,
+ 0x716d, 0x0000, 0xe95a, 0x0000, 0xe95b, 0xe95c, 0xe95d, 0x0000,
+ 0x333c, 0xe95e, 0x0000, 0xe95f, 0x716e, 0x0000, 0xe960, 0xe961,
+ 0x716f, 0xe962, 0x0000, 0xe963, 0x3f71, 0x0000, 0xe964, 0x0000,
+ 0xe965, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe966, 0x7170,
+ 0xe967, 0x7171, 0xe968, 0x7172, 0x7173, 0xe969, 0xe96a, 0xe96b,
+ 0x3962, 0x0000, 0x0000, 0xe96c, 0xe96d, 0x0000, 0x7174, 0x7175,
+ 0xe96e, 0x0000, 0x7176, 0x7177, 0xe96f, 0xe970, 0x7178, 0xe971,
+ 0x0000, 0xe972, 0x4831, 0x717a, 0xe973, 0x4926, 0x717b, 0x7179,
+ 0x0000, 0x717d, 0xe974, 0xe975, 0x717c, 0xe976, 0x0000, 0x717e,
+ 0x0000, 0xe977, 0xe978, 0x7221, 0x0000, 0xe979, 0x0000, 0xe97a
+};
+
+static const unsigned short jis_from_unicode_9b[] = {
+ 0xe97b, 0xe97c, 0xe97d, 0xe97e, 0xea21, 0xea22, 0x7222, 0x0000,
+ 0xea23, 0xea24, 0x0000, 0xea25, 0xea26, 0xea27, 0xea28, 0x0000,
+ 0xea29, 0x0000, 0xea2a, 0x0000, 0x0000, 0x0000, 0xea2b, 0x0000,
+ 0x7223, 0xea2c, 0x7224, 0xea2d, 0xea2e, 0x0000, 0x0000, 0x7225,
+ 0xea2f, 0x0000, 0x7226, 0x7227, 0x0000, 0x7228, 0xea30, 0x7229,
+ 0x722a, 0x722b, 0x722c, 0xea31, 0x0000, 0xea32, 0x722d, 0x722e,
+ 0x0000, 0x5d35, 0x722f, 0xea33, 0xea34, 0xea35, 0x0000, 0xea36,
+ 0x0000, 0xea37, 0xea38, 0x6478, 0x3534, 0xea39, 0x0000, 0x0000,
+ 0x0000, 0x3321, 0x3a32, 0x7231, 0x7230, 0x4c25, 0x0000, 0x0000,
+ 0xea3a, 0x0000, 0x0000, 0xea3b, 0xea3c, 0x7233, 0x7234, 0x7232,
+ 0x0000, 0x7235, 0x0000, 0x0000, 0x4b62, 0xea3d, 0xea3e, 0xea3f,
+ 0x7236, 0x0000, 0x357b, 0xea40, 0x0000, 0x0000, 0xea41, 0x0000,
+ 0x0000, 0xea42, 0x0000, 0xea43, 0x0000, 0xea44, 0xea45, 0x0000,
+ 0xea46, 0x0000, 0xea47, 0xea48, 0xea49, 0xea4a, 0xea4b, 0x4f25,
+ 0x0000, 0x0000, 0x0000, 0xea4c, 0x7237, 0xea4d, 0x0000, 0xea4e,
+ 0xea4f, 0xea50, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xea51,
+ 0xea52, 0x0000, 0x0000, 0x7239, 0xea53, 0xea54, 0xea55, 0xea56,
+ 0x0000, 0xea57, 0xea58, 0xea59, 0x0000, 0xea5a, 0x303e, 0xea5b,
+ 0xea5c, 0x723a, 0x4a2b, 0x7238, 0xea5d, 0x0000, 0x723b, 0x723c,
+ 0x0000, 0x0000, 0xea5e, 0x0000, 0x0000, 0xea5f, 0xea60, 0x723d,
+ 0x723e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xea61, 0xea62,
+ 0x723f, 0xea63, 0x4b6e, 0x3b2d, 0xea64, 0x3a7a, 0x412f, 0x0000,
+ 0xea65, 0xea66, 0xea67, 0x0000, 0x7240, 0x0000, 0x0000, 0xea68,
+ 0xea69, 0x7243, 0x0000, 0xea6a, 0xea6b, 0x0000, 0xea6c, 0xea6d,
+ 0x7241, 0xea6e, 0x0000, 0x0000, 0x0000, 0x0000, 0x7244, 0xea6f,
+ 0xea70, 0x3871, 0x7242, 0x0000, 0x0000, 0x0000, 0xea71, 0x7245,
+ 0xea72, 0x7246, 0x7247, 0x0000, 0x724b, 0x0000, 0x3b2a, 0xea73,
+ 0xea74, 0x0000, 0x0000, 0x4264, 0x0000, 0xea75, 0x0000, 0xea76,
+ 0x0000, 0x724c, 0x7249, 0x7248, 0x724a, 0xea77, 0x0000, 0xea78,
+ 0x375f, 0x0000, 0xea79, 0xea7a, 0x0000, 0x0000, 0x0000, 0xea7b,
+ 0x7250, 0x724f, 0x724e, 0xea7c, 0x0000, 0x3033, 0x0000, 0xea7d,
+ 0xea7e, 0xeb21, 0xeb22, 0x0000, 0x0000, 0xeb23, 0x0000, 0xeb24
+};
+
+static const unsigned short jis_from_unicode_9c[] = {
+ 0xeb25, 0x0000, 0xeb26, 0x0000, 0x725a, 0x0000, 0x7256, 0x0000,
+ 0x7257, 0x7253, 0x7259, 0xeb27, 0x7255, 0x3362, 0x0000, 0xeb28,
+ 0x4f4c, 0xeb29, 0x7258, 0x7254, 0x7252, 0x7251, 0xeb2a, 0x0000,
+ 0xeb2b, 0xeb2c, 0xeb2d, 0x725c, 0xeb2e, 0x0000, 0xeb2f, 0x0000,
+ 0x0000, 0x725f, 0xeb30, 0xeb31, 0x725e, 0x725d, 0xeb32, 0xeb33,
+ 0xeb34, 0xeb35, 0xeb36, 0x0000, 0x0000, 0x4949, 0x725b, 0x3073,
+ 0x7260, 0xeb37, 0x7262, 0x0000, 0x0000, 0xeb38, 0xeb39, 0xeb3a,
+ 0x0000, 0x336f, 0x724d, 0x3137, 0x0000, 0xeb3b, 0x7264, 0x0000,
+ 0x0000, 0xeb3c, 0x0000, 0xeb3d, 0xeb3e, 0xeb3f, 0x7263, 0x7261,
+ 0x432d, 0xeb40, 0xeb41, 0x0000, 0x0000, 0x0000, 0xeb42, 0xeb43,
+ 0xeb44, 0x0000, 0x4b70, 0xeb45, 0xeb46, 0x0000, 0xeb47, 0x4e5a,
+ 0xeb48, 0x0000, 0x7265, 0xeb49, 0xeb50, 0xeb4a, 0xeb4b, 0xeb4c,
+ 0x7266, 0x0000, 0x0000, 0xeb4d, 0x0000, 0x0000, 0x0000, 0x7267,
+ 0xeb52, 0xeb4e, 0xeb4f, 0xeb51, 0x0000, 0x0000, 0xeb53, 0x0000,
+ 0xeb54, 0x0000, 0xeb55, 0x0000, 0x0000, 0xeb56, 0x7268, 0xeb57,
+ 0x7269, 0x0000, 0x0000, 0xeb58, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x443b, 0xeb59, 0x726a,
+ 0x0000, 0x4837, 0x0000, 0x726f, 0x726b, 0x0000, 0x0000, 0x0000,
+ 0x726c, 0x0000, 0xeb5a, 0x4b31, 0x4c44, 0x0000, 0x4650, 0xeb5b,
+ 0x0000, 0xeb5c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_9d[] = {
+ 0x0000, 0x0000, 0xeb5e, 0x7270, 0x0000, 0x0000, 0x7271, 0x463e,
+ 0x726e, 0x726d, 0x0000, 0xeb5d, 0x0000, 0x0000, 0x322a, 0x0000,
+ 0x0000, 0xeb5f, 0x7279, 0x0000, 0x0000, 0x7278, 0x0000, 0xeb60,
+ 0xeb61, 0x0000, 0x0000, 0x3175, 0xeb62, 0xeb63, 0xeb64, 0x7276,
+ 0x0000, 0x0000, 0x0000, 0x7275, 0x0000, 0x0000, 0x7273, 0x0000,
+ 0x337b, 0x0000, 0x7272, 0x3c32, 0x3229, 0x0000, 0x0000, 0xeb65,
+ 0xeb66, 0x0000, 0xeb67, 0xeb68, 0xeb69, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xeb6a, 0x3963, 0xeb6b, 0xeb6d, 0x727c, 0x727b,
+ 0x0000, 0x727a, 0xeb6e, 0xeb6f, 0x7277, 0xeb6c, 0x727d, 0xeb70,
+ 0x727e, 0x0000, 0xeb71, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7325, 0x7324, 0x0000, 0xeb72, 0xeb73, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7326, 0x0000, 0x0000, 0x312d, 0x7321, 0x7322, 0xeb74,
+ 0x3974, 0x4c39, 0xeb76, 0xeb75, 0x7323, 0xeb77, 0x0000, 0x0000,
+ 0x0000, 0xeb78, 0xeb79, 0xeb7a, 0x4b32, 0x0000, 0x0000, 0x732b,
+ 0xeb7b, 0x0000, 0x7327, 0x0000, 0x0000, 0x0000, 0xeb7c, 0xeb7d,
+ 0x0000, 0x0000, 0x732c, 0xeb7e, 0xec21, 0x0000, 0xec22, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xec23, 0xec24, 0x0000, 0xec25, 0x7329,
+ 0x0000, 0x7328, 0xec26, 0x0000, 0x0000, 0xec27, 0xec28, 0x375c,
+ 0x0000, 0x0000, 0xec29, 0xec2a, 0x0000, 0xec2b, 0xec2c, 0xec2d,
+ 0xec2e, 0x0000, 0x732d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xec2f, 0x0000, 0x0000, 0x732e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x732f, 0xec30, 0x732a, 0xec31, 0x0000, 0xec32, 0x7274,
+ 0x0000, 0xec33, 0x7330, 0x0000, 0x4461, 0xec34, 0x0000, 0x0000,
+ 0x7334, 0xec35, 0x7335, 0x7333, 0xec36, 0x0000, 0x0000, 0xec37,
+ 0x0000, 0x7332, 0x7338, 0xec38, 0x7331, 0x0000, 0x7336, 0xec39,
+ 0x0000, 0xec3a, 0xec3b, 0x0000, 0x0000, 0x0000, 0x0000, 0x7337,
+ 0x0000, 0x0000, 0x0000, 0x733a, 0xec3c, 0xec3d, 0xec3e, 0xec3f,
+ 0x0000, 0x7339, 0xec40, 0x0000, 0x0000, 0x0000, 0xec41, 0xec42,
+ 0xec43, 0x0000, 0x0000, 0x0000, 0x0000, 0xec44, 0x733c, 0xec45,
+ 0x0000, 0xec46, 0x0000, 0xec47, 0x0000, 0x733d, 0xec48, 0x733e,
+ 0xec49, 0x0000, 0x4f49, 0xec4a, 0xec4b, 0x0000, 0x0000, 0x0000,
+ 0x733b, 0x426b, 0x3a6d, 0x0000, 0x0000, 0x733f, 0xec4c, 0x0000
+};
+
+static const unsigned short jis_from_unicode_9e[] = {
+ 0x0000, 0x0000, 0xec4e, 0x0000, 0x0000, 0x0000, 0x0000, 0xec4f,
+ 0x0000, 0x0000, 0xec4d, 0x0000, 0x0000, 0x0000, 0xec50, 0x0000,
+ 0xec51, 0xec52, 0xec53, 0x0000, 0x0000, 0xec54, 0xec55, 0x0000,
+ 0x0000, 0xec56, 0x7340, 0x7341, 0xec57, 0xec58, 0x7342, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7343, 0x0000, 0x0000,
+ 0x3834, 0x7344, 0xec59, 0xec5a, 0xec5b, 0x7345, 0x0000, 0x3c2f,
+ 0xec5c, 0x7346, 0xec5d, 0xec5e, 0xec5f, 0xec60, 0x0000, 0xec61,
+ 0x7347, 0x0000, 0x0000, 0x7348, 0x7349, 0x0000, 0xec62, 0xec63,
+ 0x0000, 0x734c, 0x734a, 0x4f3c, 0x0000, 0x734b, 0xec64, 0x4e6f,
+ 0xec65, 0x0000, 0x0000, 0xec66, 0x0000, 0x734d, 0xec67, 0x4e5b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xec68, 0x734e, 0x477e, 0x0000,
+ 0xec69, 0x734f, 0x7351, 0x0000, 0xec6a, 0x7352, 0xec6b, 0xec6c,
+ 0xec6d, 0x0000, 0x0000, 0xec6e, 0xec6f, 0xec70, 0x0000, 0x0000,
+ 0x7350, 0x396d, 0x4c4d, 0x4b63, 0x5677, 0x0000, 0x5d60, 0x4b7b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x322b, 0x0000, 0xec71, 0x0000,
+ 0xec72, 0x0000, 0x0000, 0xec73, 0x7354, 0x3550, 0x7355, 0x7356,
+ 0x7357, 0x0000, 0x3975, 0x0000, 0x7358, 0xec74, 0x0000, 0x0000,
+ 0x6054, 0x4c5b, 0x0000, 0x4263, 0x7359, 0x735b, 0x735a, 0xec75,
+ 0x735c, 0x0000, 0x0000, 0x0000, 0xec76, 0x735d, 0x0000, 0xec77,
+ 0x735e, 0x0000, 0x0000, 0x0000, 0xec78, 0xec79, 0xec7a, 0x735f,
+ 0xec7b, 0xec7c, 0xec7d, 0x0000, 0x7360, 0xec7e, 0x7361, 0x7362,
+ 0xed21, 0x7363, 0x0000, 0x7364, 0x7365, 0x7366, 0x0000, 0xed22
+};
+
+static const unsigned short jis_from_unicode_9f[] = {
+ 0x0000, 0x0000, 0xed23, 0xed24, 0x0000, 0x0000, 0x0000, 0x7367,
+ 0x7368, 0xed25, 0x0000, 0x0000, 0x0000, 0x0000, 0x4524, 0xed26,
+ 0xed27, 0xed28, 0xed29, 0x385d, 0xed2a, 0x736a, 0xed2b, 0xed2c,
+ 0x0000, 0xed2d, 0xed2e, 0xed2f, 0x0000, 0x0000, 0x0000, 0xed30,
+ 0x414d, 0x736b, 0xed31, 0x0000, 0x0000, 0x0000, 0xed32, 0x0000,
+ 0x0000, 0x0000, 0xed33, 0xed34, 0x736c, 0x0000, 0x0000, 0xed35,
+ 0x0000, 0xed36, 0xed37, 0x0000, 0xed38, 0x0000, 0x0000, 0xed39,
+ 0x0000, 0xed3a, 0xed3b, 0x4921, 0xed3c, 0xed3d, 0x736d, 0xed3e,
+ 0x0000, 0xed3f, 0x0000, 0xed40, 0xed41, 0xed42, 0xed43, 0xed44,
+ 0x0000, 0x0000, 0x736e, 0x6337, 0x0000, 0x0000, 0x6c5a, 0x706d,
+ 0x0000, 0x0000, 0x736f, 0xed45, 0x7370, 0xed46, 0xed47, 0xed48,
+ 0xed49, 0x0000, 0xed4a, 0x0000, 0x0000, 0xed4b, 0xed4c, 0x7372,
+ 0x7373, 0x7374, 0x4e70, 0x7371, 0x0000, 0x0000, 0x7375, 0x7376,
+ 0xed4d, 0xed4e, 0x7378, 0x0000, 0x7377, 0xed4f, 0xed50, 0xed51,
+ 0xed52, 0xed53, 0x737a, 0xed54, 0x0000, 0xed55, 0x737b, 0x7379,
+ 0x0000, 0x0000, 0xed56, 0x0000, 0x0000, 0xed57, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e36, 0x0000, 0xed58,
+ 0xed59, 0xed5a, 0xed5b, 0x0000, 0xed5c, 0x737c, 0xed5d, 0xed5e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x737d, 0x6354, 0xed5f, 0x0000,
+ 0x737e, 0xed60, 0xed61, 0xed62, 0x0000, 0xed63, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short jis_from_unicode_ff[] = {
+ 0x0000, 0x212a, 0x0000, 0x2174, 0x2170, 0x2173, 0x2175, 0x0000,
+ 0x214a, 0x214b, 0x2176, 0x215c, 0x2124, 0x0000, 0x2125, 0x213f,
+ 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337,
+ 0x2338, 0x2339, 0x2127, 0x2128, 0x2163, 0x2161, 0x2164, 0x2129,
+ 0x2177, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347,
+ 0x2348, 0x2349, 0x234a, 0x234b, 0x234c, 0x234d, 0x234e, 0x234f,
+ 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357,
+ 0x2358, 0x2359, 0x235a, 0x214e, 0x2140, 0x214f, 0x2130, 0x2132,
+ 0x212e, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367,
+ 0x2368, 0x2369, 0x236a, 0x236b, 0x236c, 0x236d, 0x236e, 0x236f,
+ 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377,
+ 0x2378, 0x2379, 0x237a, 0x2150, 0x2143, 0x2151, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2171, 0x2172, 0x224c, 0x2131, 0x0000, 0x216f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short * const jis_from_unicode_[] = {
+ jis_from_unicode_0,
+ jis_from_unicode_1,
+ jis_from_unicode_2,
+ jis_from_unicode_3,
+ jis_from_unicode_4,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ jis_from_unicode_20,
+ jis_from_unicode_21,
+ jis_from_unicode_22,
+ jis_from_unicode_23,
+ u_allzeros,
+ jis_from_unicode_25,
+ jis_from_unicode_26,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ jis_from_unicode_30,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ jis_from_unicode_4e,
+ jis_from_unicode_4f,
+ jis_from_unicode_50,
+ jis_from_unicode_51,
+ jis_from_unicode_52,
+ jis_from_unicode_53,
+ jis_from_unicode_54,
+ jis_from_unicode_55,
+ jis_from_unicode_56,
+ jis_from_unicode_57,
+ jis_from_unicode_58,
+ jis_from_unicode_59,
+ jis_from_unicode_5a,
+ jis_from_unicode_5b,
+ jis_from_unicode_5c,
+ jis_from_unicode_5d,
+ jis_from_unicode_5e,
+ jis_from_unicode_5f,
+ jis_from_unicode_60,
+ jis_from_unicode_61,
+ jis_from_unicode_62,
+ jis_from_unicode_63,
+ jis_from_unicode_64,
+ jis_from_unicode_65,
+ jis_from_unicode_66,
+ jis_from_unicode_67,
+ jis_from_unicode_68,
+ jis_from_unicode_69,
+ jis_from_unicode_6a,
+ jis_from_unicode_6b,
+ jis_from_unicode_6c,
+ jis_from_unicode_6d,
+ jis_from_unicode_6e,
+ jis_from_unicode_6f,
+ jis_from_unicode_70,
+ jis_from_unicode_71,
+ jis_from_unicode_72,
+ jis_from_unicode_73,
+ jis_from_unicode_74,
+ jis_from_unicode_75,
+ jis_from_unicode_76,
+ jis_from_unicode_77,
+ jis_from_unicode_78,
+ jis_from_unicode_79,
+ jis_from_unicode_7a,
+ jis_from_unicode_7b,
+ jis_from_unicode_7c,
+ jis_from_unicode_7d,
+ jis_from_unicode_7e,
+ jis_from_unicode_7f,
+ jis_from_unicode_80,
+ jis_from_unicode_81,
+ jis_from_unicode_82,
+ jis_from_unicode_83,
+ jis_from_unicode_84,
+ jis_from_unicode_85,
+ jis_from_unicode_86,
+ jis_from_unicode_87,
+ jis_from_unicode_88,
+ jis_from_unicode_89,
+ jis_from_unicode_8a,
+ jis_from_unicode_8b,
+ jis_from_unicode_8c,
+ jis_from_unicode_8d,
+ jis_from_unicode_8e,
+ jis_from_unicode_8f,
+ jis_from_unicode_90,
+ jis_from_unicode_91,
+ jis_from_unicode_92,
+ jis_from_unicode_93,
+ jis_from_unicode_94,
+ jis_from_unicode_95,
+ jis_from_unicode_96,
+ jis_from_unicode_97,
+ jis_from_unicode_98,
+ jis_from_unicode_99,
+ jis_from_unicode_9a,
+ jis_from_unicode_9b,
+ jis_from_unicode_9c,
+ jis_from_unicode_9d,
+ jis_from_unicode_9e,
+ jis_from_unicode_9f,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ jis_from_unicode_ff
+};
+
+
+struct charmap2 jis_from_unicode = { 0, 255, (unsigned short **) jis_from_unicode_, (unichar_t *) unicode_from_jis212 };
+
+#endif
+
+const unichar_t unicode_from_big5[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3000, 0xff0c, 0x3001, 0x3002, 0xff0e, 0x2022, 0xff1b, 0xff1a,
+ 0xff1f, 0xff01, 0xfe30, 0x2026, 0x2025, 0xfe50, 0xff64, 0xfe52,
+ 0x00b7, 0xfe54, 0xfe55, 0xfe56, 0xfe57, 0xff5c, 0x2013, 0xfe31,
+ 0x2014, 0xfe33, 0x2574, 0xfe34, 0xfe4f, 0xff08, 0xff09, 0xfe35,
+ 0xfe36, 0xff5b, 0xff5d, 0xfe37, 0xfe38, 0x3014, 0x3015, 0xfe39,
+ 0xfe3a, 0x3010, 0x3011, 0xfe3b, 0xfe3c, 0x300a, 0x300b, 0xfe3d,
+ 0xfe3e, 0x3008, 0x3009, 0xfe3f, 0xfe40, 0x300c, 0x300d, 0xfe41,
+ 0xfe42, 0x300e, 0x300f, 0xfe43, 0xfe44, 0xfe59, 0xfe5a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xfe5b, 0xfe5c, 0xfe5d, 0xfe5e, 0x2018, 0x2019, 0x201c,
+ 0x201d, 0x301d, 0x301e, 0x2035, 0x2032, 0xff03, 0xff06, 0xff0a,
+ 0x203b, 0x00a7, 0x3003, 0x25cb, 0x25cf, 0x25b3, 0x25b2, 0x25ce,
+ 0x2606, 0x2605, 0x25c7, 0x25c6, 0x25a1, 0x25a0, 0x25bd, 0x25bc,
+ 0x32a3, 0x2105, 0x00af, 0xffe3, 0xff3f, 0x02cd, 0xfe49, 0xfe4a,
+ 0xfe4d, 0xfe4e, 0xfe4b, 0xfe4c, 0xfe5f, 0xfe60, 0xfe61, 0xff0b,
+ 0xff0d, 0x00d7, 0x00f7, 0x00b1, 0x221a, 0xff1c, 0xff1e, 0xff1d,
+ 0x2266, 0x2267, 0x2260, 0x221e, 0x2252, 0x2261, 0xfe62, 0xfe63,
+ 0xfe64, 0xfe65, 0xfe66, 0x223c, 0x2229, 0x222a, 0x22a5, 0x2220,
+ 0x221f, 0x22bf, 0x33d2, 0x33d1, 0x222b, 0x222e, 0x2235, 0x2234,
+ 0x2640, 0x2642, 0x2295, 0x2299, 0x2191, 0x2193, 0x2190, 0x2192,
+ 0x2196, 0x2197, 0x2199, 0x2198, 0x2225, 0x2223, 0xff0f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xff3c, 0x2215, 0xfe68, 0xff04, 0x00a5, 0x3012, 0x00a2, 0x00a3,
+ 0xff05, 0xff20, 0x2103, 0x2109, 0xfe69, 0xfe6a, 0xfe6b, 0x33d5,
+ 0x339c, 0x339d, 0x339e, 0x33ce, 0x33a1, 0x338e, 0x338f, 0x33c4,
+ 0x00b0, 0x5159, 0x515b, 0x515e, 0x515d, 0x5161, 0x5163, 0x55e7,
+ 0x74e9, 0x7cce, 0x2581, 0x2582, 0x2583, 0x2584, 0x2585, 0x2586,
+ 0x2587, 0x2588, 0x258f, 0x258e, 0x258d, 0x258c, 0x258b, 0x258a,
+ 0x2589, 0x253c, 0x2534, 0x252c, 0x2524, 0x251c, 0x2594, 0x2500,
+ 0x2502, 0x2595, 0x250c, 0x2510, 0x2514, 0x2518, 0x256d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x256e, 0x2570, 0x256f, 0x2550, 0x255e, 0x256a, 0x2561,
+ 0x25e2, 0x25e3, 0x25e5, 0x25e4, 0x2571, 0x2572, 0x2573, 0xff10,
+ 0xff11, 0xff12, 0xff13, 0xff14, 0xff15, 0xff16, 0xff17, 0xff18,
+ 0xff19, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166,
+ 0x2167, 0x2168, 0x2169, 0x3021, 0x3022, 0x3023, 0x3024, 0x3025,
+ 0x3026, 0x3027, 0x3028, 0x3029, 0x3038, 0x5344, 0x303a, 0xff21,
+ 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 0xff29,
+ 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31,
+ 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 0xff39,
+ 0xff3a, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47,
+ 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f,
+ 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xff57, 0xff58, 0xff59, 0xff5a, 0x0391, 0x0392, 0x0393, 0x0394,
+ 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c,
+ 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1, 0x03a3, 0x03a4, 0x03a5,
+ 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03b1, 0x03b2, 0x03b3, 0x03b4,
+ 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc,
+ 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5,
+ 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x3105, 0x3106, 0x3107, 0x3108,
+ 0x3109, 0x310a, 0x310b, 0x310c, 0x310d, 0x310e, 0x310f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3110, 0x3111, 0x3112, 0x3113, 0x3114, 0x3115, 0x3116,
+ 0x3117, 0x3118, 0x3119, 0x311a, 0x311b, 0x311c, 0x311d, 0x311e,
+ 0x311f, 0x3120, 0x3121, 0x3122, 0x3123, 0x3124, 0x3125, 0x3126,
+ 0x3127, 0x3128, 0x3129, 0x02d9, 0x0000, 0x02ca, 0x02c7, 0x02cb,
+ 0x2400, 0x2401, 0x2402, 0x2403, 0x2404, 0x2405, 0x2406, 0x2407,
+ 0x2408, 0x2409, 0x240a, 0x240b, 0x240c, 0x240d, 0x240e, 0x240f,
+ 0x2410, 0x2411, 0x2412, 0x2413, 0x2414, 0x2415, 0x2416, 0x2417,
+ 0x2418, 0x2419, 0x241a, 0x241b, 0x241c, 0x241d, 0x241e, 0x241f,
+ 0x2421, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4e00, 0x4e59, 0x4e01, 0x4e03, 0x4e43, 0x4e5d, 0x4e86, 0x4e8c,
+ 0x4eba, 0x513f, 0x5165, 0x516b, 0x51e0, 0x5200, 0x5201, 0x529b,
+ 0x5315, 0x5341, 0x535c, 0x53c8, 0x4e09, 0x4e0b, 0x4e08, 0x4e0a,
+ 0x4e2b, 0x4e38, 0x51e1, 0x4e45, 0x4e48, 0x4e5f, 0x4e5e, 0x4e8e,
+ 0x4ea1, 0x5140, 0x5203, 0x52fa, 0x5343, 0x53c9, 0x53e3, 0x571f,
+ 0x58eb, 0x5915, 0x5927, 0x5973, 0x5b50, 0x5b51, 0x5b53, 0x5bf8,
+ 0x5c0f, 0x5c22, 0x5c38, 0x5c71, 0x5ddd, 0x5de5, 0x5df1, 0x5df2,
+ 0x5df3, 0x5dfe, 0x5e72, 0x5efe, 0x5f0b, 0x5f13, 0x624d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4e11, 0x4e10, 0x4e0d, 0x4e2d, 0x4e30, 0x4e39, 0x4e4b,
+ 0x5c39, 0x4e88, 0x4e91, 0x4e95, 0x4e92, 0x4e94, 0x4ea2, 0x4ec1,
+ 0x4ec0, 0x4ec3, 0x4ec6, 0x4ec7, 0x4ecd, 0x4eca, 0x4ecb, 0x4ec4,
+ 0x5143, 0x5141, 0x5167, 0x516d, 0x516e, 0x516c, 0x5197, 0x51f6,
+ 0x5206, 0x5207, 0x5208, 0x52fb, 0x52fe, 0x52ff, 0x5316, 0x5339,
+ 0x5348, 0x5347, 0x5345, 0x535e, 0x5384, 0x53cb, 0x53ca, 0x53cd,
+ 0x58ec, 0x5929, 0x592b, 0x592a, 0x592d, 0x5b54, 0x5c11, 0x5c24,
+ 0x5c3a, 0x5c6f, 0x5df4, 0x5e7b, 0x5eff, 0x5f14, 0x5f15, 0x5fc3,
+ 0x6208, 0x6236, 0x624b, 0x624e, 0x652f, 0x6587, 0x6597, 0x65a4,
+ 0x65b9, 0x65e5, 0x66f0, 0x6708, 0x6728, 0x6b20, 0x6b62, 0x6b79,
+ 0x6bcb, 0x6bd4, 0x6bdb, 0x6c0f, 0x6c34, 0x706b, 0x722a, 0x7236,
+ 0x723b, 0x7247, 0x7259, 0x725b, 0x72ac, 0x738b, 0x4e19, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4e16, 0x4e15, 0x4e14, 0x4e18, 0x4e3b, 0x4e4d, 0x4e4f, 0x4e4e,
+ 0x4ee5, 0x4ed8, 0x4ed4, 0x4ed5, 0x4ed6, 0x4ed7, 0x4ee3, 0x4ee4,
+ 0x4ed9, 0x4ede, 0x5145, 0x5144, 0x5189, 0x518a, 0x51ac, 0x51f9,
+ 0x51fa, 0x51f8, 0x520a, 0x52a0, 0x529f, 0xe05b, 0x5306, 0x5317,
+ 0x531d, 0x4edf, 0x534a, 0x5349, 0x5361, 0x5360, 0x536f, 0x536e,
+ 0x53bb, 0x53ef, 0x53e4, 0x53f3, 0x53ec, 0x53ee, 0x53e9, 0x53e8,
+ 0x53fc, 0x53f8, 0x53f5, 0x53eb, 0x53e6, 0x53ea, 0x53f2, 0x53f1,
+ 0x53f0, 0x53e5, 0x53ed, 0x53fb, 0x56db, 0x56da, 0x5916, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x592e, 0x5931, 0x5974, 0x5976, 0x5b55, 0x5b83, 0x5c3c,
+ 0x5de8, 0x5de7, 0x5de6, 0x5e02, 0x5e03, 0x5e73, 0x5e7c, 0x5f01,
+ 0x5f18, 0x5f17, 0x5fc5, 0x620a, 0x6253, 0x6254, 0x6252, 0x6251,
+ 0x65a5, 0x65e6, 0x672e, 0x672c, 0x672a, 0x672b, 0x672d, 0x6b63,
+ 0x6bcd, 0x6c11, 0x6c10, 0x6c38, 0x6c41, 0x6c40, 0x6c3e, 0x72af,
+ 0x7384, 0x7389, 0x74dc, 0x74e6, 0x7518, 0x751f, 0x7528, 0x7529,
+ 0x7530, 0x7531, 0x7532, 0x7533, 0x758b, 0x767d, 0x76ae, 0x76bf,
+ 0x76ee, 0x77db, 0x77e2, 0x77f3, 0x793a, 0x79be, 0x7a74, 0x7acb,
+ 0x4e1e, 0x4e1f, 0x4e52, 0x4e53, 0x4e69, 0x4e99, 0x4ea4, 0x4ea6,
+ 0x4ea5, 0x4eff, 0x4f09, 0x4f19, 0x4f0a, 0x4f15, 0x4f0d, 0x4f10,
+ 0x4f11, 0x4f0f, 0x4ef2, 0x4ef6, 0x4efb, 0x4ef0, 0x4ef3, 0x4efd,
+ 0x4f01, 0x4f0b, 0x5149, 0x5147, 0x5146, 0x5148, 0x5168, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5171, 0x518d, 0x51b0, 0x5217, 0x5211, 0x5212, 0x520e, 0x5216,
+ 0x52a3, 0x5308, 0x5321, 0x5320, 0x5370, 0x5371, 0x5409, 0x540f,
+ 0x540c, 0x540a, 0x5410, 0x5401, 0x540b, 0x5404, 0x5411, 0x540d,
+ 0x5408, 0x5403, 0x540e, 0x5406, 0x5412, 0x56e0, 0x56de, 0x56dd,
+ 0x5733, 0x5730, 0x5728, 0x572d, 0x572c, 0x572f, 0x5729, 0x5919,
+ 0x591a, 0x5937, 0x5938, 0x5984, 0x5978, 0x5983, 0x597d, 0x5979,
+ 0x5982, 0x5981, 0x5b57, 0x5b58, 0x5b87, 0x5b88, 0x5b85, 0x5b89,
+ 0x5bfa, 0x5c16, 0x5c79, 0x5dde, 0x5e06, 0x5e76, 0x5e74, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5f0f, 0x5f1b, 0x5fd9, 0x5fd6, 0x620e, 0x620c, 0x620d,
+ 0x6210, 0x6263, 0x625b, 0x6258, 0x6536, 0x65e9, 0x65e8, 0x65ec,
+ 0x65ed, 0x66f2, 0x66f3, 0x6709, 0x673d, 0x6734, 0x6731, 0x6735,
+ 0x6b21, 0x6b64, 0x6b7b, 0x6c16, 0x6c5d, 0x6c57, 0x6c59, 0x6c5f,
+ 0x6c60, 0x6c50, 0x6c55, 0x6c61, 0x6c5b, 0x6c4d, 0x6c4e, 0x7070,
+ 0x725f, 0x725d, 0x767e, 0x7af9, 0x7c73, 0x7cf8, 0x7f36, 0x7f8a,
+ 0x7fbd, 0x8001, 0x8003, 0x800c, 0x8012, 0x8033, 0x807f, 0x8089,
+ 0x808b, 0x808c, 0x81e3, 0x81ea, 0x81f3, 0x81fc, 0x820c, 0x821b,
+ 0x821f, 0x826e, 0x8272, 0x827e, 0x866b, 0x8840, 0x884c, 0x8863,
+ 0x897f, 0x9621, 0x4e32, 0x4ea8, 0x4f4d, 0x4f4f, 0x4f47, 0x4f57,
+ 0x4f5e, 0x4f34, 0x4f5b, 0x4f55, 0x4f30, 0x4f50, 0x4f51, 0x4f3d,
+ 0x4f3a, 0x4f38, 0x4f43, 0x4f54, 0x4f3c, 0x4f46, 0x4f63, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4f5c, 0x4f60, 0x4f2f, 0x4f4e, 0x4f36, 0x4f59, 0x4f5d, 0x4f48,
+ 0x4f5a, 0x514c, 0x514b, 0x514d, 0x5175, 0x51b6, 0x51b7, 0x5225,
+ 0x5224, 0x5229, 0x522a, 0x5228, 0x52ab, 0x52a9, 0x52aa, 0x52ac,
+ 0x5323, 0x5373, 0x5375, 0x541d, 0x542d, 0x541e, 0x543e, 0x5426,
+ 0x544e, 0x5427, 0x5446, 0x5443, 0x5433, 0x5448, 0x5442, 0x541b,
+ 0x5429, 0x544a, 0x5439, 0x543b, 0x5438, 0x542e, 0x5435, 0x5436,
+ 0x5420, 0x543c, 0x5440, 0x5431, 0x542b, 0x541f, 0x542c, 0x56ea,
+ 0x56f0, 0x56e4, 0x56eb, 0x574a, 0x5751, 0x5740, 0x574d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5747, 0x574e, 0x573e, 0x5750, 0x574f, 0x573b, 0x58ef,
+ 0x593e, 0x599d, 0x5992, 0x59a8, 0x599e, 0x59a3, 0x5999, 0x5996,
+ 0x598d, 0x59a4, 0x5993, 0x598a, 0x59a5, 0x5b5d, 0x5b5c, 0x5b5a,
+ 0x5b5b, 0x5b8c, 0x5b8b, 0x5b8f, 0x5c2c, 0x5c40, 0x5c41, 0x5c3f,
+ 0x5c3e, 0x5c90, 0x5c91, 0x5c94, 0x5c8c, 0x5deb, 0x5e0c, 0x5e8f,
+ 0x5e87, 0x5e8a, 0x5ef7, 0x5f04, 0x5f1f, 0x5f64, 0x5f62, 0x5f77,
+ 0x5f79, 0x5fd8, 0x5fcc, 0x5fd7, 0x5fcd, 0x5ff1, 0x5feb, 0x5ff8,
+ 0x5fea, 0x6212, 0x6211, 0x6284, 0x6297, 0x6296, 0x6280, 0x6276,
+ 0x6289, 0x626d, 0x628a, 0x627c, 0x627e, 0x6279, 0x6273, 0x6292,
+ 0x626f, 0x6298, 0x626e, 0x6295, 0x6293, 0x6291, 0x6286, 0x6539,
+ 0x653b, 0x6538, 0x65f1, 0x66f4, 0x675f, 0x674e, 0x674f, 0x6750,
+ 0x6751, 0x675c, 0x6756, 0x675e, 0x6749, 0x6746, 0x6760, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6753, 0x6757, 0x6b65, 0x6bcf, 0x6c42, 0x6c5e, 0x6c99, 0x6c81,
+ 0x6c88, 0x6c89, 0x6c85, 0x6c9b, 0x6c6a, 0x6c7a, 0x6c90, 0x6c70,
+ 0x6c8c, 0x6c68, 0x6c96, 0x6c92, 0x6c7d, 0x6c83, 0x6c72, 0x6c7e,
+ 0x6c74, 0x6c86, 0x6c76, 0x6c8d, 0x6c94, 0x6c98, 0x6c82, 0x7076,
+ 0x707c, 0x707d, 0x7078, 0x7262, 0x7261, 0x7260, 0x72c4, 0x72c2,
+ 0x7396, 0x752c, 0x752b, 0x7537, 0x7538, 0x7682, 0x76ef, 0x77e3,
+ 0x79c1, 0x79c0, 0x79bf, 0x7a76, 0x7cfb, 0x7f55, 0x8096, 0x8093,
+ 0x809d, 0x8098, 0x809b, 0x809a, 0x80b2, 0x826f, 0x8292, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x828b, 0x828d, 0x898b, 0x89d2, 0x8a00, 0x8c37, 0x8c46,
+ 0x8c55, 0x8c9d, 0x8d64, 0x8d70, 0x8db3, 0x8eab, 0x8eca, 0x8f9b,
+ 0x8fb0, 0x8fc2, 0x8fc6, 0x8fc5, 0x8fc4, 0x5de1, 0x9091, 0x90a2,
+ 0x90aa, 0x90a6, 0x90a3, 0x9149, 0x91c6, 0x91cc, 0x9632, 0x962e,
+ 0x9631, 0x962a, 0x962c, 0x4e26, 0x4e56, 0x4e73, 0x4e8b, 0x4e9b,
+ 0x4e9e, 0x4eab, 0x4eac, 0x4f6f, 0x4f9d, 0x4f8d, 0x4f73, 0x4f7f,
+ 0x4f6c, 0x4f9b, 0x4f8b, 0x4f86, 0x4f83, 0x4f70, 0x4f75, 0x4f88,
+ 0x4f69, 0x4f7b, 0x4f96, 0x4f7e, 0x4f8f, 0x4f91, 0x4f7a, 0x5154,
+ 0x5152, 0x5155, 0x5169, 0x5177, 0x5176, 0x5178, 0x51bd, 0x51fd,
+ 0x523b, 0x5238, 0x5237, 0x523a, 0x5230, 0x522e, 0x5236, 0x5241,
+ 0x52be, 0x52bb, 0x5352, 0x5354, 0x5353, 0x5351, 0x5366, 0x5377,
+ 0x5378, 0x5379, 0x53d6, 0x53d4, 0x53d7, 0x5473, 0x5475, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5496, 0x5478, 0x5495, 0x5480, 0x547b, 0x5477, 0x5484, 0x5492,
+ 0x5486, 0x547c, 0x5490, 0x5471, 0x5476, 0x548c, 0x549a, 0x5462,
+ 0x5468, 0x548b, 0x547d, 0x548e, 0x56fa, 0x5783, 0x5777, 0x576a,
+ 0x5769, 0x5761, 0x5766, 0x5764, 0x577c, 0x591c, 0x5949, 0x5947,
+ 0x5948, 0x5944, 0x5954, 0x59be, 0x59bb, 0x59d4, 0x59b9, 0x59ae,
+ 0x59d1, 0x59c6, 0x59d0, 0x59cd, 0x59cb, 0x59d3, 0x59ca, 0x59af,
+ 0x59b3, 0x59d2, 0x59c5, 0x5b5f, 0x5b64, 0x5b63, 0x5b97, 0x5b9a,
+ 0x5b98, 0x5b9c, 0x5b99, 0x5b9b, 0x5c1a, 0x5c48, 0x5c45, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5c46, 0x5cb7, 0x5ca1, 0x5cb8, 0x5ca9, 0x5cab, 0x5cb1,
+ 0x5cb3, 0x5e18, 0x5e1a, 0x5e16, 0x5e15, 0x5e1b, 0x5e11, 0x5e78,
+ 0x5e9a, 0x5e97, 0x5e9c, 0x5e95, 0x5e96, 0x5ef6, 0x5f26, 0x5f27,
+ 0x5f29, 0x5f80, 0x5f81, 0x5f7f, 0x5f7c, 0x5fdd, 0x5fe0, 0x5ffd,
+ 0x5ff5, 0x5fff, 0x600f, 0x6014, 0x602f, 0x6035, 0x6016, 0x602a,
+ 0x6015, 0x6021, 0x6027, 0x6029, 0x602b, 0x601b, 0x6216, 0x6215,
+ 0x623f, 0x623e, 0x6240, 0x627f, 0x62c9, 0x62cc, 0x62c4, 0x62bf,
+ 0x62c2, 0x62b9, 0x62d2, 0x62db, 0x62ab, 0x62d3, 0x62d4, 0x62cb,
+ 0x62c8, 0x62a8, 0x62bd, 0x62bc, 0x62d0, 0x62d9, 0x62c7, 0x62cd,
+ 0x62b5, 0x62da, 0x62b1, 0x62d8, 0x62d6, 0x62d7, 0x62c6, 0x62ac,
+ 0x62ce, 0x653e, 0x65a7, 0x65bc, 0x65fa, 0x6614, 0x6613, 0x660c,
+ 0x6606, 0x6602, 0x660e, 0x6600, 0x660f, 0x6615, 0x660a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6607, 0x670d, 0x670b, 0x676d, 0x678b, 0x6795, 0x6771, 0x679c,
+ 0x6773, 0x6777, 0x6787, 0x679d, 0x6797, 0x676f, 0x6770, 0x677f,
+ 0x6789, 0x677e, 0x6790, 0x6775, 0x679a, 0x6793, 0x677c, 0x676a,
+ 0x6772, 0x6b23, 0x6b66, 0x6b67, 0x6b7f, 0x6c13, 0x6c1b, 0x6ce3,
+ 0x6ce8, 0x6cf3, 0x6cb1, 0x6ccc, 0x6ce5, 0x6cb3, 0x6cbd, 0x6cbe,
+ 0x6cbc, 0x6ce2, 0x6cab, 0x6cd5, 0x6cd3, 0x6cb8, 0x6cc4, 0x6cb9,
+ 0x6cc1, 0x6cae, 0x6cd7, 0x6cc5, 0x6cf1, 0x6cbf, 0x6cbb, 0x6ce1,
+ 0x6cdb, 0x6cca, 0x6cac, 0x6cef, 0x6cdc, 0x6cd6, 0x6ce0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7095, 0x708e, 0x7092, 0x708a, 0x7099, 0x722c, 0x722d,
+ 0x7238, 0x7248, 0x7267, 0x7269, 0x72c0, 0x72ce, 0x72d9, 0x72d7,
+ 0x72d0, 0x73a9, 0x73a8, 0x739f, 0x73ab, 0x73a5, 0x753d, 0x759d,
+ 0x7599, 0x759a, 0x7684, 0x76c2, 0x76f2, 0x76f4, 0x77e5, 0x77fd,
+ 0x793e, 0x7940, 0x7941, 0x79c9, 0x79c8, 0x7a7a, 0x7a79, 0x7afa,
+ 0x7cfe, 0x7f54, 0x7f8c, 0x7f8b, 0x8005, 0x80ba, 0x80a5, 0x80a2,
+ 0x80b1, 0x80a1, 0x80ab, 0x80a9, 0x80b4, 0x80aa, 0x80af, 0x81e5,
+ 0x81fe, 0x820d, 0x82b3, 0x829d, 0x8299, 0x82ad, 0x82bd, 0x829f,
+ 0x82b9, 0x82b1, 0x82ac, 0x82a5, 0x82af, 0x82b8, 0x82a3, 0x82b0,
+ 0x82be, 0x82b7, 0x864e, 0x8671, 0x521d, 0x8868, 0x8ecb, 0x8fce,
+ 0x8fd4, 0x8fd1, 0x90b5, 0x90b8, 0x90b1, 0x90b6, 0x91c7, 0x91d1,
+ 0x9577, 0x9580, 0x961c, 0x9640, 0x963f, 0x963b, 0x9644, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9642, 0x96b9, 0x96e8, 0x9752, 0x975e, 0x4e9f, 0x4ead, 0x4eae,
+ 0x4fe1, 0x4fb5, 0x4faf, 0x4fbf, 0x4fe0, 0x4fd1, 0x4fcf, 0x4fdd,
+ 0x4fc3, 0x4fb6, 0x4fd8, 0x4fdf, 0x4fca, 0x4fd7, 0x4fae, 0x4fd0,
+ 0x4fc4, 0x4fc2, 0x4fda, 0x4fce, 0x4fde, 0x4fb7, 0x5157, 0x5192,
+ 0x5191, 0x51a0, 0x524e, 0x5243, 0x524a, 0x524d, 0x524c, 0x524b,
+ 0x5247, 0x52c7, 0x52c9, 0x52c3, 0x52c1, 0x530d, 0x5357, 0x537b,
+ 0x539a, 0x53db, 0x54ac, 0x54c0, 0x54a8, 0x54ce, 0x54c9, 0x54b8,
+ 0x54a6, 0x54b3, 0x54c7, 0x54c2, 0x54bd, 0x54aa, 0x54c1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x54c4, 0x54c8, 0x54af, 0x54ab, 0x54b1, 0x54bb, 0x54a9,
+ 0x54a7, 0x54bf, 0x56ff, 0x5782, 0x578b, 0x57a0, 0x57a3, 0x57a2,
+ 0x57ce, 0x57ae, 0x5793, 0x5955, 0x5951, 0x594f, 0x594e, 0x5950,
+ 0x59dc, 0x59d8, 0x59ff, 0x59e3, 0x59e8, 0x5a03, 0x59e5, 0x59ea,
+ 0x59da, 0x59e6, 0x5a01, 0x59fb, 0x5b69, 0x5ba3, 0x5ba6, 0x5ba4,
+ 0x5ba2, 0x5ba5, 0x5c01, 0x5c4e, 0x5c4f, 0x5c4d, 0x5c4b, 0x5cd9,
+ 0x5cd2, 0x5df7, 0x5e1d, 0x5e25, 0x5e1f, 0x5e7d, 0x5ea0, 0x5ea6,
+ 0x5efa, 0x5f08, 0x5f2d, 0x5f65, 0x5f88, 0x5f85, 0x5f8a, 0x5f8b,
+ 0x5f87, 0x5f8c, 0x5f89, 0x6012, 0x601d, 0x6020, 0x6025, 0x600e,
+ 0x6028, 0x604d, 0x6070, 0x6068, 0x6062, 0x6046, 0x6043, 0x606c,
+ 0x606b, 0x606a, 0x6064, 0x6241, 0x62dc, 0x6316, 0x6309, 0x62fc,
+ 0x62ed, 0x6301, 0x62ee, 0x62fd, 0x6307, 0x62f1, 0x62f7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x62ef, 0x62ec, 0x62fe, 0x62f4, 0x6311, 0x6302, 0x653f, 0x6545,
+ 0x65ab, 0x65bd, 0x65e2, 0x6625, 0x662d, 0x6620, 0x6627, 0x662f,
+ 0x661f, 0x6628, 0x6631, 0x6624, 0x66f7, 0x67ff, 0x67d3, 0x67f1,
+ 0x67d4, 0x67d0, 0x67ec, 0x67b6, 0x67af, 0x67f5, 0x67e9, 0x67ef,
+ 0x67c4, 0x67d1, 0x67b4, 0x67da, 0x67e5, 0x67b8, 0x67cf, 0x67de,
+ 0x67f3, 0x67b0, 0x67d9, 0x67e2, 0x67dd, 0x67d2, 0x6b6a, 0x6b83,
+ 0x6b86, 0x6bb5, 0x6bd2, 0x6bd7, 0x6c1f, 0x6cc9, 0x6d0b, 0x6d32,
+ 0x6d2a, 0x6d41, 0x6d25, 0x6d0c, 0x6d31, 0x6d1e, 0x6d17, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6d3b, 0x6d3d, 0x6d3e, 0x6d36, 0x6d1b, 0x6cf5, 0x6d39,
+ 0x6d27, 0x6d38, 0x6d29, 0x6d2e, 0x6d35, 0x6d0e, 0x6d2b, 0x70ab,
+ 0x70ba, 0x70b3, 0x70ac, 0x70af, 0x70ad, 0x70b8, 0x70ae, 0x70a4,
+ 0x7230, 0x7272, 0x726f, 0x7274, 0x72e9, 0x72e0, 0x72e1, 0x73b7,
+ 0x73ca, 0x73bb, 0x73b2, 0x73cd, 0x73c0, 0x73b3, 0x751a, 0x752d,
+ 0x754f, 0x754c, 0x754e, 0x754b, 0x75ab, 0x75a4, 0x75a5, 0x75a2,
+ 0x75a3, 0x7678, 0x7686, 0x7687, 0x7688, 0x76c8, 0x76c6, 0x76c3,
+ 0x76c5, 0x7701, 0x76f9, 0x76f8, 0x7709, 0x770b, 0x76fe, 0x76fc,
+ 0x7707, 0x77dc, 0x7802, 0x7814, 0x780c, 0x780d, 0x7946, 0x7949,
+ 0x7948, 0x7947, 0x79b9, 0x79ba, 0x79d1, 0x79d2, 0x79cb, 0x7a7f,
+ 0x7a81, 0x7aff, 0x7afd, 0x7c7d, 0x7d02, 0x7d05, 0x7d00, 0x7d09,
+ 0x7d07, 0x7d04, 0x7d06, 0x7f38, 0x7f8e, 0x7fbf, 0x8004, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8010, 0x800d, 0x8011, 0x8036, 0x80d6, 0x80e5, 0x80da, 0x80c3,
+ 0x80c4, 0x80cc, 0x80e1, 0x80db, 0x80ce, 0x80de, 0x80e4, 0x80dd,
+ 0x81f4, 0x8222, 0x82e7, 0x8303, 0x8305, 0x82e3, 0x82db, 0x82e6,
+ 0x8304, 0x82e5, 0x8302, 0x8309, 0x82d2, 0x82d7, 0x82f1, 0x8301,
+ 0x82dc, 0x82d4, 0x82d1, 0x82de, 0x82d3, 0x82df, 0x82ef, 0x8306,
+ 0x8650, 0x8679, 0x867b, 0x867a, 0x884d, 0x886b, 0x8981, 0x89d4,
+ 0x8a08, 0x8a02, 0x8a03, 0x8c9e, 0x8ca0, 0x8d74, 0x8d73, 0x8db4,
+ 0x8ecd, 0x8ecc, 0x8ff0, 0x8fe6, 0x8fe2, 0x8fea, 0x8fe5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8fed, 0x8feb, 0x8fe4, 0x8fe8, 0x90ca, 0x90ce, 0x90c1,
+ 0x90c3, 0x914b, 0x914a, 0x91cd, 0x9582, 0x9650, 0x964b, 0x964c,
+ 0x964d, 0x9762, 0x9769, 0x97cb, 0x97ed, 0x97f3, 0x9801, 0x98a8,
+ 0x98db, 0x98df, 0x9996, 0x9999, 0x4e58, 0x4eb3, 0x500c, 0x500d,
+ 0x5023, 0x4fef, 0x5026, 0x5025, 0x4ff8, 0x5029, 0x5016, 0x5006,
+ 0x503c, 0x501f, 0x501a, 0x5012, 0x5011, 0x4ffa, 0x5000, 0x5014,
+ 0x5028, 0x4ff1, 0x5021, 0x500b, 0x5019, 0x5018, 0x4ff3, 0x4fee,
+ 0x502d, 0x502a, 0x4ffe, 0x502b, 0x5009, 0x517c, 0x51a4, 0x51a5,
+ 0x51a2, 0x51cd, 0x51cc, 0x51c6, 0x51cb, 0x5256, 0x525c, 0x5254,
+ 0x525b, 0x525d, 0x532a, 0x537f, 0x539f, 0x539d, 0x53df, 0x54e8,
+ 0x5510, 0x5501, 0x5537, 0x54fc, 0x54e5, 0x54f2, 0x5506, 0x54fa,
+ 0x5514, 0x54e9, 0x54ed, 0x54e1, 0x5509, 0x54ee, 0x54ea, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x54e6, 0x5527, 0x5507, 0x54fd, 0x550f, 0x5703, 0x5704, 0x57c2,
+ 0x57d4, 0x57cb, 0x57c3, 0x5809, 0x590f, 0x5957, 0x5958, 0x595a,
+ 0x5a11, 0x5a18, 0x5a1c, 0x5a1f, 0x5a1b, 0x5a13, 0x59ec, 0x5a20,
+ 0x5a23, 0x5a29, 0x5a25, 0x5a0c, 0x5a09, 0x5b6b, 0x5c58, 0x5bb0,
+ 0x5bb3, 0x5bb6, 0x5bb4, 0x5bae, 0x5bb5, 0x5bb9, 0x5bb8, 0x5c04,
+ 0x5c51, 0x5c55, 0x5c50, 0x5ced, 0x5cfd, 0x5cfb, 0x5cea, 0x5ce8,
+ 0x5cf0, 0x5cf6, 0x5d01, 0x5cf4, 0x5dee, 0x5e2d, 0x5e2b, 0x5eab,
+ 0x5ead, 0x5ea7, 0x5f31, 0x5f92, 0x5f91, 0x5f90, 0x6059, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6063, 0x6065, 0x6050, 0x6055, 0x606d, 0x6069, 0x606f,
+ 0x6084, 0x609f, 0x609a, 0x608d, 0x6094, 0x608c, 0x6085, 0x6096,
+ 0x6247, 0x62f3, 0x6308, 0x62ff, 0x634e, 0x633e, 0x632f, 0x6355,
+ 0x6342, 0x6346, 0x634f, 0x6349, 0x633a, 0x6350, 0x633d, 0x632a,
+ 0x632b, 0x6328, 0x634d, 0x634c, 0x6548, 0x6549, 0x6599, 0x65c1,
+ 0x65c5, 0x6642, 0x6649, 0x664f, 0x6643, 0x6652, 0x664c, 0x6645,
+ 0x6641, 0x66f8, 0x6714, 0x6715, 0x6717, 0x6821, 0x6838, 0x6848,
+ 0x6846, 0x6853, 0x6839, 0x6842, 0x6854, 0x6829, 0x68b3, 0x6817,
+ 0x684c, 0x6851, 0x683d, 0x67f4, 0x6850, 0x6840, 0x683c, 0x6843,
+ 0x682a, 0x6845, 0x6813, 0x6818, 0x6841, 0x6b8a, 0x6b89, 0x6bb7,
+ 0x6c23, 0x6c27, 0x6c28, 0x6c26, 0x6c24, 0x6cf0, 0x6d6a, 0x6d95,
+ 0x6d88, 0x6d87, 0x6d66, 0x6d78, 0x6d77, 0x6d59, 0x6d93, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6d6c, 0x6d89, 0x6d6e, 0x6d5a, 0x6d74, 0x6d69, 0x6d8c, 0x6d8a,
+ 0x6d79, 0x6d85, 0x6d65, 0x6d94, 0x70ca, 0x70d8, 0x70e4, 0x70d9,
+ 0x70c8, 0x70cf, 0x7239, 0x7279, 0x72fc, 0x72f9, 0x72fd, 0x72f8,
+ 0x72f7, 0x7386, 0x73ed, 0x7409, 0x73ee, 0x73e0, 0x73ea, 0x73de,
+ 0x7554, 0x755d, 0x755c, 0x755a, 0x7559, 0x75be, 0x75c5, 0x75c7,
+ 0x75b2, 0x75b3, 0x75bd, 0x75bc, 0x75b9, 0x75c2, 0x75b8, 0x768b,
+ 0x76b0, 0x76ca, 0x76cd, 0x76ce, 0x7729, 0x771f, 0x7720, 0x7728,
+ 0x77e9, 0x7830, 0x7827, 0x7838, 0x781d, 0x7834, 0x7837, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7825, 0x782d, 0x7820, 0x781f, 0x7832, 0x7955, 0x7950,
+ 0x7960, 0x795f, 0x7956, 0x795e, 0x795d, 0x7957, 0x795a, 0x79e4,
+ 0x79e3, 0x79e7, 0x79df, 0x79e6, 0x79e9, 0x79d8, 0x7a84, 0x7a88,
+ 0x7ad9, 0x7b06, 0x7b11, 0x7c89, 0x7d21, 0x7d17, 0x7d0b, 0x7d0a,
+ 0x7d20, 0x7d22, 0x7d14, 0x7d10, 0x7d15, 0x7d1a, 0x7d1c, 0x7d0d,
+ 0x7d19, 0x7d1b, 0x7f3a, 0x7f5f, 0x7f94, 0x7fc5, 0x7fc1, 0x8006,
+ 0x8018, 0x8015, 0x8019, 0x8017, 0x803d, 0x803f, 0x80f1, 0x8102,
+ 0x80f0, 0x8105, 0x80ed, 0x80f4, 0x8106, 0x80f8, 0x80f3, 0x8108,
+ 0x80fd, 0x810a, 0x80fc, 0x80ef, 0x81ed, 0x81ec, 0x8200, 0x8210,
+ 0x822a, 0x822b, 0x8228, 0x822c, 0x82bb, 0x832b, 0x8352, 0x8354,
+ 0x834a, 0x8338, 0x8350, 0x8349, 0x8335, 0x8334, 0x834f, 0x8332,
+ 0x8339, 0x8336, 0x8317, 0x8340, 0x8331, 0x8328, 0x8343, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8654, 0x868a, 0x86aa, 0x8693, 0x86a4, 0x86a9, 0x868c, 0x86a3,
+ 0x869c, 0x8870, 0x8877, 0x8881, 0x8882, 0x887d, 0x8879, 0x8a18,
+ 0x8a10, 0x8a0e, 0x8a0c, 0x8a15, 0x8a0a, 0x8a17, 0x8a13, 0x8a16,
+ 0x8a0f, 0x8a11, 0x8c48, 0x8c7a, 0x8c79, 0x8ca1, 0x8ca2, 0x8d77,
+ 0x8eac, 0x8ed2, 0x8ed4, 0x8ecf, 0x8fb1, 0x9001, 0x9006, 0x8ff7,
+ 0x9000, 0x8ffa, 0x8ff4, 0x9003, 0x8ffd, 0x9005, 0x8ff8, 0x9095,
+ 0x90e1, 0x90dd, 0x90e2, 0x9152, 0x914d, 0x914c, 0x91d8, 0x91dd,
+ 0x91d7, 0x91dc, 0x91d9, 0x9583, 0x9662, 0x9663, 0x9661, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x965b, 0x965d, 0x9664, 0x9658, 0x965e, 0x96bb, 0x98e2,
+ 0x99ac, 0x9aa8, 0x9ad8, 0x9b25, 0x9b32, 0x9b3c, 0x4e7e, 0x507a,
+ 0x507d, 0x505c, 0x5047, 0x5043, 0x504c, 0x505a, 0x5049, 0x5065,
+ 0x5076, 0x504e, 0x5055, 0x5075, 0x5074, 0x5077, 0x504f, 0x500f,
+ 0x506f, 0x506d, 0x515c, 0x5195, 0x51f0, 0x526a, 0x526f, 0x52d2,
+ 0x52d9, 0x52d8, 0x52d5, 0x5310, 0x530f, 0x5319, 0x533f, 0x5340,
+ 0x533e, 0x53c3, 0x66fc, 0x5546, 0x556a, 0x5566, 0x5544, 0x555e,
+ 0x5561, 0x5543, 0x554a, 0x5531, 0x5556, 0x554f, 0x5555, 0x552f,
+ 0x5564, 0x5538, 0x552e, 0x555c, 0x552c, 0x5563, 0x5533, 0x5541,
+ 0x5557, 0x5708, 0x570b, 0x5709, 0x57df, 0x5805, 0x580a, 0x5806,
+ 0x57e0, 0x57e4, 0x57fa, 0x5802, 0x5835, 0x57f7, 0x57f9, 0x5920,
+ 0x5962, 0x5a36, 0x5a41, 0x5a49, 0x5a66, 0x5a6a, 0x5a40, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5a3c, 0x5a62, 0x5a5a, 0x5a46, 0x5a4a, 0x5b70, 0x5bc7, 0x5bc5,
+ 0x5bc4, 0x5bc2, 0x5bbf, 0x5bc6, 0x5c09, 0x5c08, 0x5c07, 0x5c60,
+ 0x5c5c, 0x5c5d, 0x5d07, 0x5d06, 0x5d0e, 0x5d1b, 0x5d16, 0x5d22,
+ 0x5d11, 0x5d29, 0x5d14, 0x5d19, 0x5d24, 0x5d27, 0x5d17, 0x5de2,
+ 0x5e38, 0x5e36, 0x5e33, 0x5e37, 0x5eb7, 0x5eb8, 0x5eb6, 0x5eb5,
+ 0x5ebe, 0x5f35, 0x5f37, 0x5f57, 0x5f6c, 0x5f69, 0x5f6b, 0x5f97,
+ 0x5f99, 0x5f9e, 0x5f98, 0x5fa1, 0x5fa0, 0x5f9c, 0x607f, 0x60a3,
+ 0x6089, 0x60a0, 0x60a8, 0x60cb, 0x60b4, 0x60e6, 0x60bd, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x60c5, 0x60bb, 0x60b5, 0x60dc, 0x60bc, 0x60d8, 0x60d5,
+ 0x60c6, 0x60df, 0x60b8, 0x60da, 0x60c7, 0x621a, 0x621b, 0x6248,
+ 0x63a0, 0x63a7, 0x6372, 0x6396, 0x63a2, 0x63a5, 0x6377, 0x6367,
+ 0x6398, 0x63aa, 0x6371, 0x63a9, 0x6389, 0x6383, 0x639b, 0x636b,
+ 0x63a8, 0x6384, 0x6388, 0x6399, 0x63a1, 0x63ac, 0x6392, 0x638f,
+ 0x6380, 0x637b, 0x6369, 0x6368, 0x637a, 0x655d, 0x6556, 0x6551,
+ 0x6559, 0x6557, 0x555f, 0x654f, 0x6558, 0x6555, 0x6554, 0x659c,
+ 0x659b, 0x65ac, 0x65cf, 0x65cb, 0x65cc, 0x65ce, 0x665d, 0x665a,
+ 0x6664, 0x6668, 0x6666, 0x665e, 0x66f9, 0x52d7, 0x671b, 0x6881,
+ 0x68af, 0x68a2, 0x6893, 0x68b5, 0x687f, 0x6876, 0x68b1, 0x68a7,
+ 0x6897, 0x68b0, 0x6883, 0x68c4, 0x68ad, 0x6886, 0x6885, 0x6894,
+ 0x689d, 0x68a8, 0x689f, 0x68a1, 0x6882, 0x6b32, 0x6bba, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6beb, 0x6bec, 0x6c2b, 0x6d8e, 0x6dbc, 0x6df3, 0x6dd9, 0x6db2,
+ 0x6de1, 0x6dcc, 0x6de4, 0x6dfb, 0x6dfa, 0x6e05, 0x6dc7, 0x6dcb,
+ 0x6daf, 0x6dd1, 0x6dae, 0x6dde, 0x6df9, 0x6db8, 0x6df7, 0x6df5,
+ 0x6dc5, 0x6dd2, 0x6e1a, 0x6db5, 0x6dda, 0x6deb, 0x6dd8, 0x6dea,
+ 0x6df1, 0x6dee, 0x6de8, 0x6dc6, 0x6dc4, 0x6daa, 0x6dec, 0x6dbf,
+ 0x6de6, 0x70f9, 0x7109, 0x710a, 0x70fd, 0x70ef, 0x723d, 0x727d,
+ 0x7281, 0x731c, 0x731b, 0x7316, 0x7313, 0x7319, 0x7387, 0x7405,
+ 0x740a, 0x7403, 0x7406, 0x73fe, 0x740d, 0x74e0, 0x74f6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x74f7, 0x751c, 0x7522, 0x7565, 0x7566, 0x7562, 0x7570,
+ 0x758f, 0x75d4, 0x75d5, 0x75b5, 0x75ca, 0x75cd, 0x768e, 0x76d4,
+ 0x76d2, 0x76db, 0x7737, 0x773e, 0x773c, 0x7736, 0x7738, 0x773a,
+ 0x786b, 0x7843, 0x784e, 0x7965, 0x7968, 0x796d, 0x79fb, 0x7a92,
+ 0x7a95, 0x7b20, 0x7b28, 0x7b1b, 0x7b2c, 0x7b26, 0x7b19, 0x7b1e,
+ 0x7b2e, 0x7c92, 0x7c97, 0x7c95, 0x7d46, 0x7d43, 0x7d71, 0x7d2e,
+ 0x7d39, 0x7d3c, 0x7d40, 0x7d30, 0x7d33, 0x7d44, 0x7d2f, 0x7d42,
+ 0x7d32, 0x7d31, 0x7f3d, 0x7f9e, 0x7f9a, 0x7fcc, 0x7fce, 0x7fd2,
+ 0x801c, 0x804a, 0x8046, 0x812f, 0x8116, 0x8123, 0x812b, 0x8129,
+ 0x8130, 0x8124, 0x8202, 0x8235, 0x8237, 0x8236, 0x8239, 0x838e,
+ 0x839e, 0x8398, 0x8378, 0x83a2, 0x8396, 0x83bd, 0x83ab, 0x8392,
+ 0x838a, 0x8393, 0x8389, 0x83a0, 0x8377, 0x837b, 0x837c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8386, 0x83a7, 0x8655, 0x5f6a, 0x86c7, 0x86c0, 0x86b6, 0x86c4,
+ 0x86b5, 0x86c6, 0x86cb, 0x86b1, 0x86af, 0x86c9, 0x8853, 0x889e,
+ 0x8888, 0x88ab, 0x8892, 0x8896, 0x888d, 0x888b, 0x8993, 0x898f,
+ 0x8a2a, 0x8a1d, 0x8a23, 0x8a25, 0x8a31, 0x8a2d, 0x8a1f, 0x8a1b,
+ 0x8a22, 0x8c49, 0x8c5a, 0x8ca9, 0x8cac, 0x8cab, 0x8ca8, 0x8caa,
+ 0x8ca7, 0x8d67, 0x8d66, 0x8dbe, 0x8dba, 0x8edb, 0x8edf, 0x9019,
+ 0x900d, 0x901a, 0x9017, 0x9023, 0x901f, 0x901d, 0x9010, 0x9015,
+ 0x901e, 0x9020, 0x900f, 0x9022, 0x9016, 0x901b, 0x9014, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x90e8, 0x90ed, 0x90fd, 0x9157, 0x91ce, 0x91f5, 0x91e6,
+ 0x91e3, 0x91e7, 0x91ed, 0x91e9, 0x9589, 0x966a, 0x9675, 0x9673,
+ 0x9678, 0x9670, 0x9674, 0x9676, 0x9677, 0x966c, 0x96c0, 0x96ea,
+ 0x96e9, 0x7ae0, 0x7adf, 0x9802, 0x9803, 0x9b5a, 0x9ce5, 0x9e75,
+ 0x9e7f, 0x9ea5, 0x9ebb, 0x50a2, 0x508d, 0x5085, 0x5099, 0x5091,
+ 0x5080, 0x5096, 0x5098, 0x509a, 0x6700, 0x51f1, 0x5272, 0x5274,
+ 0x5275, 0x5269, 0x52de, 0x52dd, 0x52db, 0x535a, 0x53a5, 0x557b,
+ 0x5580, 0x55a7, 0x557c, 0x558a, 0x559d, 0x5598, 0x5582, 0x559c,
+ 0x55aa, 0x5594, 0x5587, 0x558b, 0x5583, 0x55b3, 0x55ae, 0x559f,
+ 0x553e, 0x55b2, 0x559a, 0x55bb, 0x55ac, 0x55b1, 0x557e, 0x5589,
+ 0x55ab, 0x5599, 0x570d, 0x582f, 0x582a, 0x5834, 0x5824, 0x5830,
+ 0x5831, 0x5821, 0x581d, 0x5820, 0x58f9, 0x58fa, 0x5960, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5a77, 0x5a9a, 0x5a7f, 0x5a92, 0x5a9b, 0x5aa7, 0x5b73, 0x5b71,
+ 0x5bd2, 0x5bcc, 0x5bd3, 0x5bd0, 0x5c0a, 0x5c0b, 0x5c31, 0x5d4c,
+ 0x5d50, 0x5d34, 0x5d47, 0x5dfd, 0x5e45, 0x5e3d, 0x5e40, 0x5e43,
+ 0x5e7e, 0x5eca, 0x5ec1, 0x5ec2, 0x5ec4, 0x5f3c, 0x5f6d, 0x5fa9,
+ 0x5faa, 0x5fa8, 0x60d1, 0x60e1, 0x60b2, 0x60b6, 0x60e0, 0x611c,
+ 0x6123, 0x60fa, 0x6115, 0x60f0, 0x60fb, 0x60f4, 0x6168, 0x60f1,
+ 0x610e, 0x60f6, 0x6109, 0x6100, 0x6112, 0x621f, 0x6249, 0x63a3,
+ 0x638c, 0x63cf, 0x63c0, 0x63e9, 0x63c9, 0x63c6, 0x63cd, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x63d2, 0x63e3, 0x63d0, 0x63e1, 0x63d6, 0x63ed, 0x63ee,
+ 0x6376, 0x63f4, 0x63ea, 0x63db, 0x6452, 0x63da, 0x63f9, 0x655e,
+ 0x6566, 0x6562, 0x6563, 0x6591, 0x6590, 0x65af, 0x666e, 0x6670,
+ 0x6674, 0x6676, 0x666f, 0x6691, 0x667a, 0x667e, 0x6677, 0x66fe,
+ 0x66ff, 0x671f, 0x671d, 0x68fa, 0x68d5, 0x68e0, 0x68d8, 0x68d7,
+ 0x6905, 0x68df, 0x68f5, 0x68ee, 0x68e7, 0x68f9, 0x68d2, 0x68f2,
+ 0x68e3, 0x68cb, 0x68cd, 0x690d, 0x6912, 0x690e, 0x68c9, 0x68da,
+ 0x696e, 0x68fb, 0x6b3e, 0x6b3a, 0x6b3d, 0x6b98, 0x6b96, 0x6bbc,
+ 0x6bef, 0x6c2e, 0x6c2f, 0x6c2c, 0x6e2f, 0x6e38, 0x6e54, 0x6e21,
+ 0x6e32, 0x6e67, 0x6e4a, 0x6e20, 0x6e25, 0x6e23, 0x6e1b, 0x6e5b,
+ 0x6e58, 0x6e24, 0x6e56, 0x6e6e, 0x6e2d, 0x6e26, 0x6e6f, 0x6e34,
+ 0x6e4d, 0x6e3a, 0x6e2c, 0x6e43, 0x6e1d, 0x6e3e, 0x6ecb, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6e89, 0x6e19, 0x6e4e, 0x6e63, 0x6e44, 0x6e72, 0x6e69, 0x6e5f,
+ 0x7119, 0x711a, 0x7126, 0x7130, 0x7121, 0x7136, 0x716e, 0x711c,
+ 0x724c, 0x7284, 0x7280, 0x7336, 0x7325, 0x7334, 0x7329, 0x743a,
+ 0x742a, 0x7433, 0x7422, 0x7425, 0x7435, 0x7436, 0x7434, 0x742f,
+ 0x741b, 0x7426, 0x7428, 0x7525, 0x7526, 0x756b, 0x756a, 0x75e2,
+ 0x75db, 0x75e3, 0x75d9, 0x75d8, 0x75de, 0x75e0, 0x767b, 0x767c,
+ 0x7696, 0x7693, 0x76b4, 0x76dc, 0x774f, 0x77ed, 0x785d, 0x786c,
+ 0x786f, 0x7a0d, 0x7a08, 0x7a0b, 0x7a05, 0x7a00, 0x7a98, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7a97, 0x7a96, 0x7ae5, 0x7ae3, 0x7b49, 0x7b56, 0x7b46,
+ 0x7b50, 0x7b52, 0x7b54, 0x7b4d, 0x7b4b, 0x7b4f, 0x7b51, 0x7c9f,
+ 0x7ca5, 0x7d5e, 0x7d50, 0x7d68, 0x7d55, 0x7d2b, 0x7d6e, 0x7d72,
+ 0x7d61, 0x7d66, 0x7d62, 0x7d70, 0x7d73, 0x5584, 0x7fd4, 0x7fd5,
+ 0x800b, 0x8052, 0x8085, 0x8155, 0x8154, 0x814b, 0x8151, 0x814e,
+ 0x8139, 0x8146, 0x813e, 0x814c, 0x8153, 0x8174, 0x8212, 0x821c,
+ 0x83e9, 0x8403, 0x83f8, 0x840d, 0x83e0, 0x83c5, 0x840b, 0x83c1,
+ 0x83ef, 0x83f1, 0x83f4, 0x8457, 0x840a, 0x83f0, 0x840c, 0x83cc,
+ 0x83fd, 0x83f2, 0x83ca, 0x8438, 0x840e, 0x8404, 0x83dc, 0x8407,
+ 0x83d4, 0x83df, 0x865b, 0x86df, 0x86d9, 0x86ed, 0x86d4, 0x86db,
+ 0x86e4, 0x86d0, 0x86de, 0x8857, 0x88c1, 0x88c2, 0x88b1, 0x8983,
+ 0x8996, 0x8a3b, 0x8a60, 0x8a55, 0x8a5e, 0x8a3c, 0x8a41, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8a54, 0x8a5b, 0x8a50, 0x8a46, 0x8a34, 0x8a3a, 0x8a36, 0x8a56,
+ 0x8c61, 0x8c82, 0x8caf, 0x8cbc, 0x8cb3, 0x8cbd, 0x8cc1, 0x8cbb,
+ 0x8cc0, 0x8cb4, 0x8cb7, 0x8cb6, 0x8cbf, 0x8cb8, 0x8d8a, 0x8d85,
+ 0x8d81, 0x8dce, 0x8ddd, 0x8dcb, 0x8dda, 0x8dd1, 0x8dcc, 0x8ddb,
+ 0x8dc6, 0x8efb, 0x8ef8, 0x8efc, 0x8f9c, 0x902e, 0x9035, 0x9031,
+ 0x9038, 0x9032, 0x9036, 0x9102, 0x90f5, 0x9109, 0x90fe, 0x9163,
+ 0x9165, 0x91cf, 0x9214, 0x9215, 0x9223, 0x9209, 0x921e, 0x920d,
+ 0x9210, 0x9207, 0x9211, 0x9594, 0x958f, 0x958b, 0x9591, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9593, 0x9592, 0x958e, 0x968a, 0x968e, 0x968b, 0x967d,
+ 0x9685, 0x9686, 0x968d, 0x9672, 0x9684, 0x96c1, 0x96c5, 0x96c4,
+ 0x96c6, 0x96c7, 0x96ef, 0x96f2, 0x97cc, 0x9805, 0x9806, 0x9808,
+ 0x98e7, 0x98ea, 0x98ef, 0x98e9, 0x98f2, 0x98ed, 0x99ae, 0x99ad,
+ 0x9ec3, 0x9ecd, 0x9ed1, 0x4e82, 0x50ad, 0x50b5, 0x50b2, 0x50b3,
+ 0x50c5, 0x50be, 0x50ac, 0x50b7, 0x50bb, 0x50af, 0x50c7, 0x527f,
+ 0x5277, 0x527d, 0x52df, 0x52e6, 0x52e4, 0x52e2, 0x52e3, 0x532f,
+ 0x55df, 0x55e8, 0x55d3, 0x55e6, 0x55ce, 0x55dc, 0x55c7, 0x55d1,
+ 0x55e3, 0x55e4, 0x55ef, 0x55da, 0x55e1, 0x55c5, 0x55c6, 0x55e5,
+ 0x55c9, 0x5712, 0x5713, 0x585e, 0x5851, 0x5858, 0x5857, 0x585a,
+ 0x5854, 0x586b, 0x584c, 0x586d, 0x584a, 0x5862, 0x5852, 0x584b,
+ 0x5967, 0x5ac1, 0x5ac9, 0x5acc, 0x5abe, 0x5abd, 0x5abc, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5ab3, 0x5ac2, 0x5ab2, 0x5d69, 0x5d6f, 0x5e4c, 0x5e79, 0x5ec9,
+ 0x5ec8, 0x5f12, 0x5f59, 0x5fac, 0x5fae, 0x611a, 0x610f, 0x6148,
+ 0x611f, 0x60f3, 0x611b, 0x60f9, 0x6101, 0x6108, 0x614e, 0x614c,
+ 0x6144, 0x614d, 0x613e, 0x6134, 0x6127, 0x610d, 0x6106, 0x6137,
+ 0x6221, 0x6222, 0x6413, 0x643e, 0x641e, 0x642a, 0x642d, 0x643d,
+ 0x642c, 0x640f, 0x641c, 0x6414, 0x640d, 0x6436, 0x6416, 0x6417,
+ 0x6406, 0x656c, 0x659f, 0x65b0, 0x6697, 0x6689, 0x6687, 0x6688,
+ 0x6696, 0x6684, 0x6698, 0x668d, 0x6703, 0x6994, 0x696d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x695a, 0x6977, 0x6960, 0x6954, 0x6975, 0x6930, 0x6982,
+ 0x694a, 0x6968, 0x696b, 0x695e, 0x6953, 0x6979, 0x6986, 0x695d,
+ 0x6963, 0x695b, 0x6b47, 0x6b72, 0x6bc0, 0x6bbf, 0x6bd3, 0x6bfd,
+ 0x6ea2, 0x6eaf, 0x6ed3, 0x6eb6, 0x6ec2, 0x6e90, 0x6e9d, 0x6ec7,
+ 0x6ec5, 0x6ea5, 0x6e98, 0x6ebc, 0x6eba, 0x6eab, 0x6ed1, 0x6e96,
+ 0x6e9c, 0x6ec4, 0x6ed4, 0x6eaa, 0x6ea7, 0x6eb4, 0x714e, 0x7159,
+ 0x7169, 0x7164, 0x7149, 0x7167, 0x715c, 0x716c, 0x7166, 0x714c,
+ 0x7165, 0x715e, 0x7146, 0x7168, 0x7156, 0x723a, 0x7252, 0x7337,
+ 0x7345, 0x733f, 0x733e, 0x746f, 0x745a, 0x7455, 0x745f, 0x745e,
+ 0x7441, 0x743f, 0x7459, 0x745b, 0xe2a3, 0x7576, 0x7578, 0x7600,
+ 0x75f0, 0x7601, 0x75f2, 0x75f1, 0x75fa, 0x75ff, 0x75f4, 0x75f3,
+ 0x76de, 0x76df, 0x775b, 0x776b, 0x7766, 0x775e, 0x7763, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7779, 0x776a, 0x776c, 0x775c, 0x7765, 0x7768, 0x7762, 0x77ee,
+ 0x788e, 0x78b0, 0x7897, 0x7898, 0x788c, 0x7889, 0x787c, 0x7891,
+ 0x7893, 0x787f, 0x797a, 0x797f, 0x7981, 0x842c, 0x79bd, 0x7a1c,
+ 0x7a1a, 0x7a20, 0x7a14, 0x7a1f, 0x7a1e, 0x7a9f, 0x7aa0, 0x7b77,
+ 0x7bc0, 0x7b60, 0x7b6e, 0x7b67, 0x7cb1, 0x7cb3, 0x7cb5, 0x7d93,
+ 0x7d79, 0x7d91, 0x7d81, 0x7d8f, 0x7d5b, 0x7f6e, 0x7f69, 0x7f6a,
+ 0x7f72, 0x7fa9, 0x7fa8, 0x7fa4, 0x8056, 0x8058, 0x8086, 0x8084,
+ 0x8171, 0x8170, 0x8178, 0x8165, 0x816e, 0x8173, 0x816b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8179, 0x817a, 0x8166, 0x8205, 0x8247, 0x8482, 0x8477,
+ 0x843d, 0x8431, 0x8475, 0x8466, 0x846b, 0x8449, 0x846c, 0x845b,
+ 0x843c, 0x8435, 0x8461, 0x8463, 0x8469, 0x846d, 0x8446, 0x865e,
+ 0x865c, 0x865f, 0x86f9, 0x8713, 0x8708, 0x8707, 0x8700, 0x86fe,
+ 0x86fb, 0x8702, 0x8703, 0x8706, 0x870a, 0x8859, 0x88df, 0x88d4,
+ 0x88d9, 0x88dc, 0x88d8, 0x88dd, 0x88e1, 0x88ca, 0x88d5, 0x88d2,
+ 0x899c, 0x89e3, 0x8a6b, 0x8a72, 0x8a73, 0x8a66, 0x8a69, 0x8a70,
+ 0x8a87, 0x8a7c, 0x8a63, 0x8aa0, 0x8a71, 0x8a85, 0x8a6d, 0x8a62,
+ 0x8a6e, 0x8a6c, 0x8a79, 0x8a7b, 0x8a3e, 0x8a68, 0x8c62, 0x8c8a,
+ 0x8c89, 0x8cca, 0x8cc7, 0x8cc8, 0x8cc4, 0x8cb2, 0x8cc3, 0x8cc2,
+ 0x8cc5, 0x8de1, 0x8ddf, 0x8de8, 0x8def, 0x8df3, 0x8dfa, 0x8dea,
+ 0x8de4, 0x8de6, 0x8eb2, 0x8f03, 0x8f09, 0x8efe, 0x8f0a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8f9f, 0x8fb2, 0x904b, 0x904a, 0x9053, 0x9042, 0x9054, 0x903c,
+ 0x9055, 0x9050, 0x9047, 0x904f, 0x904e, 0x904d, 0x9051, 0x903e,
+ 0x9041, 0x9112, 0x9117, 0x916c, 0x916a, 0x9169, 0x91c9, 0x9237,
+ 0x9257, 0x9238, 0x923d, 0x9240, 0x923e, 0x925b, 0x924b, 0x9264,
+ 0x9251, 0x9234, 0x9249, 0x924d, 0x9245, 0x9239, 0x923f, 0x925a,
+ 0x9598, 0x9698, 0x9694, 0x9695, 0x96cd, 0x96cb, 0x96c9, 0x96ca,
+ 0x96f7, 0x96fb, 0x96f9, 0x96f6, 0x9756, 0x9774, 0x9776, 0x9810,
+ 0x9811, 0x9813, 0x980a, 0x9812, 0x980c, 0x98fc, 0x98f4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x98fd, 0x98fe, 0x99b3, 0x99b1, 0x99b4, 0x9ae1, 0x9ce9,
+ 0x9e82, 0x9f0e, 0x9f13, 0x9f20, 0x50e7, 0x50ee, 0x50e5, 0x50d6,
+ 0x50ed, 0x50da, 0x50d5, 0x50cf, 0x50d1, 0x50f1, 0x50ce, 0x50e9,
+ 0x5162, 0x51f3, 0x5283, 0x5282, 0x5331, 0x53ad, 0x55fe, 0x5600,
+ 0x561b, 0x5617, 0x55fd, 0x5614, 0x5606, 0x5609, 0x560d, 0x560e,
+ 0x55f7, 0x5616, 0x561f, 0x5608, 0x5610, 0x55f6, 0x5718, 0x5716,
+ 0x5875, 0x587e, 0x5883, 0x5893, 0x588a, 0x5879, 0x5885, 0x587d,
+ 0x58fd, 0x5925, 0x5922, 0x5924, 0x596a, 0x5969, 0x5ae1, 0x5ae6,
+ 0x5ae9, 0x5ad7, 0x5ad6, 0x5ad8, 0x5ae3, 0x5b75, 0x5bde, 0x5be7,
+ 0x5be1, 0x5be5, 0x5be6, 0x5be8, 0x5be2, 0x5be4, 0x5bdf, 0x5c0d,
+ 0x5c62, 0x5d84, 0x5d87, 0x5e5b, 0x5e63, 0x5e55, 0x5e57, 0x5e54,
+ 0x5ed3, 0x5ed6, 0x5f0a, 0x5f46, 0x5f70, 0x5fb9, 0x6147, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x613f, 0x614b, 0x6177, 0x6162, 0x6163, 0x615f, 0x615a, 0x6158,
+ 0x6175, 0x622a, 0x6487, 0x6458, 0x6454, 0x64a4, 0x6478, 0x645f,
+ 0x647a, 0x6451, 0x6467, 0x6434, 0x646d, 0x647b, 0x6572, 0x65a1,
+ 0x65d7, 0x65d6, 0x66a2, 0x66a8, 0x669d, 0x699c, 0x69a8, 0x6995,
+ 0x69c1, 0x69ae, 0x69d3, 0x69cb, 0x699b, 0x69b7, 0x69bb, 0x69ab,
+ 0x69b4, 0x69d0, 0x69cd, 0x69ad, 0x69cc, 0x69a6, 0x69c3, 0x69a3,
+ 0x6b49, 0x6b4c, 0x6c33, 0x6f33, 0x6f14, 0x6efe, 0x6f13, 0x6ef4,
+ 0x6f29, 0x6f3e, 0x6f20, 0x6f2c, 0x6f0f, 0x6f02, 0x6f22, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6eff, 0x6eef, 0x6f06, 0x6f31, 0x6f38, 0x6f32, 0x6f23,
+ 0x6f15, 0x6f2b, 0x6f2f, 0x6f88, 0x6f2a, 0x6eec, 0x6f01, 0x6ef2,
+ 0x6ecc, 0x6ef7, 0x7194, 0x7199, 0x717d, 0x718a, 0x7184, 0x7192,
+ 0x723e, 0x7292, 0x7296, 0x7344, 0x7350, 0x7464, 0x7463, 0x746a,
+ 0x7470, 0x746d, 0x7504, 0x7591, 0x7627, 0x760d, 0x760b, 0x7609,
+ 0x7613, 0x76e1, 0x76e3, 0x7784, 0x777d, 0x777f, 0x7761, 0x78c1,
+ 0x789f, 0x78a7, 0x78b3, 0x78a9, 0x78a3, 0x798e, 0x798f, 0x798d,
+ 0x7a2e, 0x7a31, 0x7aaa, 0x7aa9, 0x7aed, 0x7aef, 0x7ba1, 0x7b95,
+ 0x7b8b, 0x7b75, 0x7b97, 0x7b9d, 0x7b94, 0x7b8f, 0x7bb8, 0x7b87,
+ 0x7b84, 0x7cb9, 0x7cbd, 0x7cbe, 0x7dbb, 0x7db0, 0x7d9c, 0x7dbd,
+ 0x7dbe, 0x7da0, 0x7dca, 0x7db4, 0x7db2, 0x7db1, 0x7dba, 0x7da2,
+ 0x7dbf, 0x7db5, 0x7db8, 0x7dad, 0x7dd2, 0x7dc7, 0x7dac, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7f70, 0x7fe0, 0x7fe1, 0x7fdf, 0x805e, 0x805a, 0x8087, 0x8150,
+ 0x8180, 0x818f, 0x8188, 0x818a, 0x817f, 0x8182, 0x81e7, 0x81fa,
+ 0x8207, 0x8214, 0x821e, 0x824b, 0x84c9, 0x84bf, 0x84c6, 0x84c4,
+ 0x8499, 0x849e, 0x84b2, 0x849c, 0x84cb, 0x84b8, 0x84c0, 0x84d3,
+ 0x8490, 0x84bc, 0x84d1, 0x84ca, 0x873f, 0x871c, 0x873b, 0x8722,
+ 0x8725, 0x8734, 0x8718, 0x8755, 0x8737, 0x8729, 0x88f3, 0x8902,
+ 0x88f4, 0x88f9, 0x88f8, 0x88fd, 0x88e8, 0x891a, 0x88ef, 0x8aa6,
+ 0x8a8c, 0x8a9e, 0x8aa3, 0x8a8d, 0x8aa1, 0x8a93, 0x8aa4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8aaa, 0x8aa5, 0x8aa8, 0x8a98, 0x8a91, 0x8a9a, 0x8aa7,
+ 0x8c6a, 0x8c8d, 0x8c8c, 0x8cd3, 0x8cd1, 0x8cd2, 0x8d6b, 0x8d99,
+ 0x8d95, 0x8dfc, 0x8f14, 0x8f12, 0x8f15, 0x8f13, 0x8fa3, 0x9060,
+ 0x9058, 0x905c, 0x9063, 0x9059, 0x905e, 0x9062, 0x905d, 0x905b,
+ 0x9119, 0x9118, 0x911e, 0x9175, 0x9178, 0x9177, 0x9174, 0x9278,
+ 0x9280, 0x9285, 0x9298, 0x9296, 0x927b, 0x9293, 0x929c, 0x92a8,
+ 0x927c, 0x9291, 0x95a1, 0x95a8, 0x95a9, 0x95a3, 0x95a5, 0x95a4,
+ 0x9699, 0x969c, 0x969b, 0x96cc, 0x96d2, 0x9700, 0x977c, 0x9785,
+ 0x97f6, 0x9817, 0x9818, 0x98af, 0x98b1, 0x9903, 0x9905, 0x990c,
+ 0x9909, 0x99c1, 0x9aaf, 0x9ab0, 0x9ae6, 0x9b41, 0x9b42, 0x9cf4,
+ 0x9cf6, 0x9cf3, 0x9ebc, 0x9f3b, 0x9f4a, 0x5104, 0x5100, 0x50fb,
+ 0x50f5, 0x50f9, 0x5102, 0x5108, 0x5109, 0x5105, 0x51dc, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5287, 0x5288, 0x5289, 0x528d, 0x528a, 0x52f0, 0x53b2, 0x562e,
+ 0x563b, 0x5639, 0x5632, 0x563f, 0x5634, 0x5629, 0x5653, 0x564e,
+ 0x5657, 0x5674, 0x5636, 0x562f, 0x5630, 0x5880, 0x589f, 0x589e,
+ 0x58b3, 0x589c, 0x58ae, 0x58a9, 0x58a6, 0x596d, 0x5b09, 0x5afb,
+ 0x5b0b, 0x5af5, 0x5b0c, 0x5b08, 0x5bee, 0x5bec, 0x5be9, 0x5beb,
+ 0x5c64, 0x5c65, 0x5d9d, 0x5d94, 0x5e62, 0x5e5f, 0x5e61, 0x5ee2,
+ 0x5eda, 0x5edf, 0x5edd, 0x5ee3, 0x5ee0, 0x5f48, 0x5f71, 0x5fb7,
+ 0x5fb5, 0x6176, 0x6167, 0x616e, 0x615d, 0x6155, 0x6182, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x617c, 0x6170, 0x616b, 0x617e, 0x61a7, 0x6190, 0x61ab,
+ 0x618e, 0x61ac, 0x619a, 0x61a4, 0x6194, 0x61ae, 0x622e, 0x6469,
+ 0x646f, 0x6479, 0x649e, 0x64b2, 0x6488, 0x6490, 0x64b0, 0x64a5,
+ 0x6493, 0x6495, 0x64a9, 0x6492, 0x64ae, 0x64ad, 0x64ab, 0x649a,
+ 0x64ac, 0x6499, 0x64a2, 0x64b3, 0x6575, 0x6577, 0x6578, 0x66ae,
+ 0x66ab, 0x66b4, 0x66b1, 0x6a23, 0x6a1f, 0x69e8, 0x6a01, 0x6a1e,
+ 0x6a19, 0x69fd, 0x6a21, 0x6a13, 0x6a0a, 0x69f3, 0x6a02, 0x6a05,
+ 0x69ed, 0x6a11, 0x6b50, 0x6b4e, 0x6ba4, 0x6bc5, 0x6bc6, 0x6f3f,
+ 0x6f7c, 0x6f84, 0x6f51, 0x6f66, 0x6f54, 0x6f86, 0x6f6d, 0x6f5b,
+ 0x6f78, 0x6f6e, 0x6f8e, 0x6f7a, 0x6f70, 0x6f64, 0x6f97, 0x6f58,
+ 0x6ed5, 0x6f6f, 0x6f60, 0x6f5f, 0x719f, 0x71ac, 0x71b1, 0x71a8,
+ 0x7256, 0x729b, 0x734e, 0x7357, 0x7469, 0x748b, 0x7483, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x747e, 0x7480, 0x757f, 0x7620, 0x7629, 0x761f, 0x7624, 0x7626,
+ 0x7621, 0x7622, 0x769a, 0x76ba, 0x76e4, 0x778e, 0x7787, 0x778c,
+ 0x7791, 0x778b, 0x78cb, 0x78c5, 0x78ba, 0x78ca, 0x78be, 0x78d5,
+ 0x78bc, 0x78d0, 0x7a3f, 0x7a3c, 0x7a40, 0x7a3d, 0x7a37, 0x7a3b,
+ 0x7aaf, 0x7aae, 0x7bad, 0x7bb1, 0x7bc4, 0x7bb4, 0x7bc6, 0x7bc7,
+ 0x7bc1, 0x7ba0, 0x7bcc, 0x7cca, 0x7de0, 0x7df4, 0x7def, 0x7dfb,
+ 0x7dd8, 0x7dec, 0x7ddd, 0x7de8, 0x7de3, 0x7dda, 0x7dde, 0x7de9,
+ 0x7d9e, 0x7dd9, 0x7df2, 0x7df9, 0x7f75, 0x7f77, 0x7faf, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7fe9, 0x8026, 0x819b, 0x819c, 0x819d, 0x81a0, 0x819a,
+ 0x8198, 0x8517, 0x853d, 0x851a, 0x84ee, 0x852c, 0x852d, 0x8513,
+ 0x8511, 0x8523, 0x8521, 0x8514, 0x84ec, 0x8525, 0x84ff, 0x8506,
+ 0x8782, 0x8774, 0x8776, 0x8760, 0x8766, 0x8778, 0x8768, 0x8759,
+ 0x8757, 0x874c, 0x8753, 0x885b, 0x885d, 0x8910, 0x8907, 0x8912,
+ 0x8913, 0x8915, 0x890a, 0x8abc, 0x8ad2, 0x8ac7, 0x8ac4, 0x8a95,
+ 0x8acb, 0x8af8, 0x8ab2, 0x8ac9, 0x8ac2, 0x8abf, 0x8ab0, 0x8ad6,
+ 0x8acd, 0x8ab6, 0x8ab9, 0x8adb, 0x8c4c, 0x8c4e, 0x8c6c, 0x8ce0,
+ 0x8cde, 0x8ce6, 0x8ce4, 0x8cec, 0x8ced, 0x8ce2, 0x8ce3, 0x8cdc,
+ 0x8cea, 0x8ce1, 0x8d6d, 0x8d9f, 0x8da3, 0x8e2b, 0x8e10, 0x8e1d,
+ 0x8e22, 0x8e0f, 0x8e29, 0x8e1f, 0x8e21, 0x8e1e, 0x8eba, 0x8f1d,
+ 0x8f1b, 0x8f1f, 0x8f29, 0x8f26, 0x8f2a, 0x8f1c, 0x8f1e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8f25, 0x9069, 0x906e, 0x9068, 0x906d, 0x9077, 0x9130, 0x912d,
+ 0x9127, 0x9131, 0x9187, 0x9189, 0x918b, 0x9183, 0x92c5, 0x92bb,
+ 0x92b7, 0x92ea, 0x92ac, 0x92e4, 0x92c1, 0x92b3, 0x92bc, 0x92d2,
+ 0x92c7, 0x92f0, 0x92b2, 0x95ad, 0x95b1, 0x9704, 0x9706, 0x9707,
+ 0x9709, 0x9760, 0x978d, 0x978b, 0x978f, 0x9821, 0x982b, 0x981c,
+ 0x98b3, 0x990a, 0x9913, 0x9912, 0x9918, 0x99dd, 0x99d0, 0x99df,
+ 0x99db, 0x99d1, 0x99d5, 0x99d2, 0x99d9, 0x9ab7, 0x9aee, 0x9aef,
+ 0x9b27, 0x9b45, 0x9b44, 0x9b77, 0x9b6f, 0x9d06, 0x9d09, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9d03, 0x9ea9, 0x9ebe, 0x9ece, 0x58a8, 0x9f52, 0x5112,
+ 0x5118, 0x5114, 0x5110, 0x5115, 0x5180, 0x51aa, 0x51dd, 0x5291,
+ 0x5293, 0x52f3, 0x5659, 0x566b, 0x5679, 0x5669, 0x5664, 0x5678,
+ 0x566a, 0x5668, 0x5665, 0x5671, 0x566f, 0x566c, 0x5662, 0x5676,
+ 0x58c1, 0x58be, 0x58c7, 0x58c5, 0x596e, 0x5b1d, 0x5b34, 0x5b78,
+ 0x5bf0, 0x5c0e, 0x5f4a, 0x61b2, 0x6191, 0x61a9, 0x618a, 0x61cd,
+ 0x61b6, 0x61be, 0x61ca, 0x61c8, 0x6230, 0x64c5, 0x64c1, 0x64cb,
+ 0x64bb, 0x64bc, 0x64da, 0x64c4, 0x64c7, 0x64c2, 0x64cd, 0x64bf,
+ 0x64d2, 0x64d4, 0x64be, 0x6574, 0x66c6, 0x66c9, 0x66b9, 0x66c4,
+ 0x66c7, 0x66b8, 0x6a3d, 0x6a38, 0x6a3a, 0x6a59, 0x6a6b, 0x6a58,
+ 0x6a39, 0x6a44, 0x6a62, 0x6a61, 0x6a4b, 0x6a47, 0x6a35, 0x6a5f,
+ 0x6a48, 0x6b59, 0x6b77, 0x6c05, 0x6fc2, 0x6fb1, 0x6fa1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6fc3, 0x6fa4, 0x6fc1, 0x6fa7, 0x6fb3, 0x6fc0, 0x6fb9, 0x6fb6,
+ 0x6fa6, 0x6fa0, 0x6fb4, 0x71be, 0x71c9, 0x71d0, 0x71d2, 0x71c8,
+ 0x71d5, 0x71b9, 0x71ce, 0x71d9, 0x71dc, 0x71c3, 0x71c4, 0x7368,
+ 0x749c, 0x74a3, 0x7498, 0x749f, 0x749e, 0x74e2, 0x750c, 0x750d,
+ 0x7634, 0x7638, 0x763a, 0x76e7, 0x76e5, 0x77a0, 0x779e, 0x779f,
+ 0x77a5, 0x78e8, 0x78da, 0x78ec, 0x78e7, 0x79a6, 0x7a4d, 0x7a4e,
+ 0x7a46, 0x7a4c, 0x7a4b, 0x7aba, 0x7bd9, 0x7c11, 0x7bc9, 0x7be4,
+ 0x7bdb, 0x7be1, 0x7be9, 0x7be6, 0x7cd5, 0x7cd6, 0x7e0a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7e11, 0x7e08, 0x7e1b, 0x7e23, 0x7e1e, 0x7e1d, 0x7e09,
+ 0x7e10, 0x7f79, 0x7fb2, 0x7ff0, 0x7ff1, 0x7fee, 0x8028, 0x81b3,
+ 0x81a9, 0x81a8, 0x81fb, 0x8208, 0x8258, 0x8259, 0x854a, 0x8559,
+ 0x8548, 0x8568, 0x8569, 0x8543, 0x8549, 0x856d, 0x856a, 0x855e,
+ 0x8783, 0x879f, 0x879e, 0x87a2, 0x878d, 0x8861, 0x892a, 0x8932,
+ 0x8925, 0x892b, 0x8921, 0x89aa, 0x89a6, 0x8ae6, 0x8afa, 0x8aeb,
+ 0x8af1, 0x8b00, 0x8adc, 0x8ae7, 0x8aee, 0x8afe, 0x8b01, 0x8b02,
+ 0x8af7, 0x8aed, 0x8af3, 0x8af6, 0x8afc, 0x8c6b, 0x8c6d, 0x8c93,
+ 0x8cf4, 0x8e44, 0x8e31, 0x8e34, 0x8e42, 0x8e39, 0x8e35, 0x8f3b,
+ 0x8f2f, 0x8f38, 0x8f33, 0x8fa8, 0x8fa6, 0x9075, 0x9074, 0x9078,
+ 0x9072, 0x907c, 0x907a, 0x9134, 0x9192, 0x9320, 0x9336, 0x92f8,
+ 0x9333, 0x932f, 0x9322, 0x92fc, 0x932b, 0x9304, 0x931a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9310, 0x9326, 0x9321, 0x9315, 0x932e, 0x9319, 0x95bb, 0x96a7,
+ 0x96a8, 0x96aa, 0x96d5, 0x970e, 0x9711, 0x9716, 0x970d, 0x9713,
+ 0x970f, 0x975b, 0xe4c5, 0x9766, 0x9798, 0x9830, 0x9838, 0x983b,
+ 0x9837, 0x982d, 0x9839, 0x9824, 0x9910, 0x9928, 0x991e, 0x991b,
+ 0x9921, 0x991a, 0x99ed, 0x99e2, 0x99f1, 0x9ab8, 0x9abc, 0x9afb,
+ 0x9aed, 0x9b28, 0x9b91, 0x9d15, 0x9d23, 0x9d26, 0x9d28, 0x9d12,
+ 0x9d1b, 0x9ed8, 0x9ed4, 0x9f8d, 0x9f9c, 0x512a, 0x511f, 0x5121,
+ 0x5132, 0x52f5, 0x568e, 0x5680, 0x5690, 0x5685, 0x5687, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x568f, 0x58d5, 0x58d3, 0x58d1, 0x58ce, 0x5b30, 0x5b2a,
+ 0x5b24, 0x5b7a, 0x5c37, 0x5c68, 0x5dbc, 0x5dba, 0x5dbd, 0x5db8,
+ 0x5e6b, 0x5f4c, 0x5fbd, 0x61c9, 0x61c2, 0x61c7, 0x61e6, 0x61cb,
+ 0x6232, 0x6234, 0x64ce, 0x64ca, 0x64d8, 0x64e0, 0x64f0, 0x64e6,
+ 0x64ec, 0x64f1, 0x64e2, 0x64ed, 0x6582, 0x6583, 0x66d9, 0x66d6,
+ 0x6a80, 0x6a94, 0x6a84, 0x6aa2, 0x6a9c, 0x6adb, 0x6aa3, 0x6a7e,
+ 0x6a97, 0x6a90, 0x6aa0, 0x6b5c, 0x6bae, 0x6bda, 0x6c08, 0x6fd8,
+ 0x6ff1, 0x6fdf, 0x6fe0, 0x6fdb, 0x6fe4, 0x6feb, 0x6fef, 0x6f80,
+ 0x6fec, 0x6fe1, 0x6fe9, 0x6fd5, 0x6fee, 0x6ff0, 0x71e7, 0x71df,
+ 0x71ee, 0x71e6, 0x71e5, 0x71ed, 0x71ec, 0x71f4, 0x71e0, 0x7235,
+ 0x7246, 0x7370, 0x7372, 0x74a9, 0x74b0, 0x74a6, 0x74a8, 0x7646,
+ 0x7642, 0x764c, 0x76ea, 0x77b3, 0x77aa, 0x77b0, 0x77ac, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x77a7, 0x77ad, 0x77ef, 0x78f7, 0x78fa, 0x78f4, 0x78ef, 0x7901,
+ 0x79a7, 0x79aa, 0x7a57, 0x7abf, 0x7c07, 0x7c0d, 0x7bfe, 0x7bf7,
+ 0x7c0c, 0x7be0, 0x7ce0, 0x7cdc, 0x7cde, 0x7ce2, 0x7cdf, 0x7cd9,
+ 0x7cdd, 0x7e2e, 0x7e3e, 0x7e46, 0x7e37, 0x7e32, 0x7e43, 0x7e2b,
+ 0x7e3d, 0x7e31, 0x7e45, 0x7e41, 0x7e34, 0x7e39, 0x7e48, 0x7e35,
+ 0x7e3f, 0x7e2f, 0x7f44, 0x7ff3, 0x7ffc, 0x8071, 0x8072, 0x8070,
+ 0x806f, 0x8073, 0x81c6, 0x81c3, 0x81ba, 0x81c2, 0x81c0, 0x81bf,
+ 0x81bd, 0x81c9, 0x81be, 0x81e8, 0x8209, 0x8271, 0x85aa, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8584, 0x857e, 0x859c, 0x8591, 0x8594, 0x85af, 0x859b,
+ 0x8587, 0x85a8, 0x858a, 0x8667, 0x87c0, 0x87d1, 0x87b3, 0x87d2,
+ 0x87c6, 0x87ab, 0x87bb, 0x87ba, 0x87c8, 0x87cb, 0x893b, 0x8936,
+ 0x8944, 0x8938, 0x893d, 0x89ac, 0x8b0e, 0x8b17, 0x8b19, 0x8b1b,
+ 0x8b0a, 0x8b20, 0x8b1d, 0x8b04, 0x8b10, 0x8c41, 0x8c3f, 0x8c73,
+ 0x8cfa, 0x8cfd, 0x8cfc, 0x8cf8, 0x8cfb, 0x8da8, 0x8e49, 0x8e4b,
+ 0x8e48, 0x8e4a, 0x8f44, 0x8f3e, 0x8f42, 0x8f45, 0x8f3f, 0x907f,
+ 0x907d, 0x9084, 0x9081, 0x9082, 0x9080, 0x9139, 0x91a3, 0x919e,
+ 0x919c, 0x934d, 0x9382, 0x9328, 0x9375, 0x934a, 0x9365, 0x934b,
+ 0x9318, 0x937e, 0x936c, 0x935b, 0x9370, 0x935a, 0x9354, 0x95ca,
+ 0x95cb, 0x95cc, 0x95c8, 0x95c6, 0x96b1, 0x96b8, 0x96d6, 0x971c,
+ 0x971e, 0x97a0, 0x97d3, 0x9846, 0x98b6, 0x9935, 0x9a01, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x99ff, 0x9bae, 0x9bab, 0x9baa, 0x9bad, 0x9d3b, 0x9d3f, 0x9e8b,
+ 0x9ecf, 0x9ede, 0x9edc, 0x9edd, 0x9edb, 0x9f3e, 0x9f4b, 0x53e2,
+ 0x5695, 0x56ae, 0x58d9, 0x58d8, 0x5b38, 0x5f5d, 0x61e3, 0x6233,
+ 0x64f4, 0x64f2, 0x64fe, 0x6506, 0x64fa, 0x64fb, 0x64f7, 0x65b7,
+ 0x66dc, 0x6726, 0x6ab3, 0x6aac, 0x6ac3, 0x6abb, 0x6ab8, 0x6ac2,
+ 0x6aae, 0x6aaf, 0x6b5f, 0x6b78, 0x6baf, 0x7009, 0x700b, 0x6ffe,
+ 0x7006, 0x6ffa, 0x7011, 0x700f, 0x71fb, 0x71fc, 0x71fe, 0x71f8,
+ 0x7377, 0x7375, 0x74a7, 0x74bf, 0x7515, 0x7656, 0x7658, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7652, 0x77bd, 0x77bf, 0x77bb, 0x77bc, 0x790e, 0x79ae,
+ 0x7a61, 0x7a62, 0x7a60, 0x7ac4, 0x7ac5, 0x7c2b, 0x7c27, 0x7c2a,
+ 0x7c1e, 0x7c23, 0x7c21, 0x7ce7, 0x7e54, 0x7e55, 0x7e5e, 0x7e5a,
+ 0x7e61, 0x7e52, 0x7e59, 0x7f48, 0x7ff9, 0x7ffb, 0x8077, 0x8076,
+ 0x81cd, 0x81cf, 0x820a, 0x85cf, 0x85a9, 0x85cd, 0x85d0, 0x85c9,
+ 0x85b0, 0x85ba, 0x85b9, 0x85a6, 0x87ef, 0x87ec, 0x87f2, 0x87e0,
+ 0x8986, 0x89b2, 0x89f4, 0x8b28, 0x8b39, 0x8b2c, 0x8b2b, 0x8c50,
+ 0x8d05, 0x8e59, 0x8e63, 0x8e66, 0x8e64, 0x8e5f, 0x8e55, 0x8ec0,
+ 0x8f49, 0x8f4d, 0x9087, 0x9083, 0x9088, 0x91ab, 0x91ac, 0x91d0,
+ 0x9394, 0x938a, 0x9396, 0x93a2, 0x93b3, 0x93ae, 0x93ac, 0x93b0,
+ 0x9398, 0x939a, 0x9397, 0x95d4, 0x95d6, 0x95d0, 0x95d5, 0x96e2,
+ 0x96dc, 0x96d9, 0x96db, 0x96de, 0x9724, 0x97a3, 0x97a6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x97ad, 0x97f9, 0x984d, 0x984f, 0x984c, 0x984e, 0x9853, 0x98ba,
+ 0x993e, 0x993f, 0x993d, 0x992e, 0x99a5, 0x9a0e, 0x9ac1, 0x9b03,
+ 0x9b06, 0x9b4f, 0x9b4e, 0x9b4d, 0x9bca, 0x9bc9, 0x9bfd, 0x9bc8,
+ 0x9bc0, 0x9d51, 0x9d5d, 0x9d60, 0x9ee0, 0x9f15, 0x9f2c, 0x5133,
+ 0x56a5, 0x58de, 0x58df, 0x58e2, 0x5bf5, 0x9f90, 0x5eec, 0x61f2,
+ 0x61f7, 0x61f6, 0x61f5, 0x6500, 0x650f, 0x66e0, 0x66dd, 0x6ae5,
+ 0x6add, 0x6ada, 0x6ad3, 0x701b, 0x701f, 0x7028, 0x701a, 0x701d,
+ 0x7015, 0x7018, 0x7206, 0x720d, 0x7258, 0x72a2, 0x7378, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x737a, 0x74bd, 0x74ca, 0x74e3, 0x7587, 0x7586, 0x765f,
+ 0x7661, 0x77c7, 0x7919, 0x79b1, 0x7a6b, 0x7a69, 0x7c3e, 0x7c3f,
+ 0x7c38, 0x7c3d, 0x7c37, 0x7c40, 0x7e6b, 0x7e6d, 0x7e79, 0x7e69,
+ 0x7e6a, 0x7f85, 0x7e73, 0x7fb6, 0x7fb9, 0x7fb8, 0x81d8, 0x85e9,
+ 0x85dd, 0x85ea, 0x85d5, 0x85e4, 0x85e5, 0x85f7, 0x87fb, 0x8805,
+ 0x880d, 0x87f9, 0x87fe, 0x8960, 0x895f, 0x8956, 0x895e, 0x8b41,
+ 0x8b5c, 0x8b58, 0x8b49, 0x8b5a, 0x8b4e, 0x8b4f, 0x8b46, 0x8b59,
+ 0x8d08, 0x8d0a, 0x8e7c, 0x8e72, 0x8e87, 0x8e76, 0x8e6c, 0x8e7a,
+ 0x8e74, 0x8f54, 0x8f4e, 0x8fad, 0x908a, 0x908b, 0x91b1, 0x91ae,
+ 0x93e1, 0x93d1, 0x93df, 0x93c3, 0x93c8, 0x93dc, 0x93dd, 0x93d6,
+ 0x93e2, 0x93cd, 0x93d8, 0x93e4, 0x93d7, 0x93e8, 0x95dc, 0x96b4,
+ 0x96e3, 0x972a, 0x9727, 0x9761, 0x97dc, 0x97fb, 0x985e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9858, 0x985b, 0x98bc, 0x9945, 0x9949, 0x9a16, 0x9a19, 0x9b0d,
+ 0x9be8, 0x9be7, 0x9bd6, 0x9bdb, 0x9d89, 0x9d61, 0x9d72, 0x9d6a,
+ 0x9d6c, 0x9e92, 0x9e97, 0x9e93, 0x9eb4, 0x52f8, 0x56a8, 0x56b7,
+ 0x56b6, 0x56b4, 0x56bc, 0x58e4, 0x5b40, 0x5b43, 0x5b7d, 0x5bf6,
+ 0x5dc9, 0x61f8, 0x61fa, 0x6518, 0x6514, 0x6519, 0x66e6, 0x6727,
+ 0x6aec, 0x703e, 0x7030, 0x7032, 0x7210, 0x737b, 0x74cf, 0x7662,
+ 0x7665, 0x7926, 0x792a, 0x792c, 0x792b, 0x7ac7, 0x7af6, 0x7c4c,
+ 0x7c43, 0x7c4d, 0x7cef, 0x7cf0, 0x8fae, 0x7e7d, 0x7e7c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7e82, 0x7f4c, 0x8000, 0x81da, 0x8266, 0x85fb, 0x85f9,
+ 0x8611, 0x85fa, 0x8606, 0x860b, 0x8607, 0x860a, 0x8814, 0x8815,
+ 0x8964, 0x89ba, 0x89f8, 0x8b70, 0x8b6c, 0x8b66, 0x8b6f, 0x8b5f,
+ 0x8b6b, 0x8d0f, 0x8d0d, 0x8e89, 0x8e81, 0x8e85, 0x8e82, 0x91b4,
+ 0x91cb, 0x9418, 0x9403, 0x93fd, 0x95e1, 0x9730, 0x98c4, 0x9952,
+ 0x9951, 0x99a8, 0x9a2b, 0x9a30, 0x9a37, 0x9a35, 0x9c13, 0x9c0d,
+ 0x9e79, 0x9eb5, 0x9ee8, 0x9f2f, 0x9f5f, 0x9f63, 0x9f61, 0x5137,
+ 0x5138, 0x56c1, 0x56c0, 0x56c2, 0x5914, 0x5c6c, 0x5dcd, 0x61fc,
+ 0x61fe, 0x651d, 0x651c, 0x6595, 0x66e9, 0x6afb, 0x6b04, 0x6afa,
+ 0x6bb2, 0x704c, 0x721b, 0x72a7, 0x74d6, 0x74d4, 0x7669, 0x77d3,
+ 0x7c50, 0x7e8f, 0x7e8c, 0x7fbc, 0x8617, 0x862d, 0x861a, 0x8823,
+ 0x8822, 0x8821, 0x881f, 0x896a, 0x896c, 0x89bd, 0x8b74, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8b77, 0x8b7d, 0x8d13, 0x8e8a, 0x8e8d, 0x8e8b, 0x8f5f, 0x8faf,
+ 0x91ba, 0x942e, 0x9433, 0x9435, 0x943a, 0x9438, 0x9432, 0x942b,
+ 0x95e2, 0x9738, 0x9739, 0x9732, 0x97ff, 0x9867, 0x9865, 0x9957,
+ 0x9a45, 0x9a43, 0x9a40, 0x9a3e, 0x9acf, 0x9b54, 0x9b51, 0x9c2d,
+ 0x9c25, 0x9daf, 0x9db4, 0x9dc2, 0x9db8, 0x9e9d, 0x9eef, 0x9f19,
+ 0x9f5c, 0x9f66, 0x9f67, 0x513c, 0x513b, 0x56c8, 0x56ca, 0x56c9,
+ 0x5b7f, 0x5dd4, 0x5dd2, 0x5f4e, 0x61ff, 0x6524, 0x6b0a, 0x6b61,
+ 0x7051, 0x7058, 0x7380, 0x74e4, 0x758a, 0x766e, 0x766c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x79b3, 0x7c60, 0x7c5f, 0x807e, 0x807d, 0x81df, 0x8972,
+ 0x896f, 0x89fc, 0x8b80, 0x8d16, 0x8d17, 0x8e91, 0x8e93, 0x8f61,
+ 0x9148, 0x9444, 0x9451, 0x9452, 0x973d, 0x973e, 0x97c3, 0x97c1,
+ 0x986b, 0x9955, 0x9a55, 0x9a4d, 0x9ad2, 0x9b1a, 0x9c49, 0x9c31,
+ 0x9c3e, 0x9c3b, 0x9dd3, 0x9dd7, 0x9f34, 0x9f6c, 0x9f6a, 0x9f94,
+ 0x56cc, 0x5dd6, 0x6200, 0x6523, 0x652b, 0x652a, 0x66ec, 0x6b10,
+ 0x74da, 0x7aca, 0x7c64, 0x7c63, 0x7c65, 0x7e93, 0x7e96, 0x7e94,
+ 0x81e2, 0x8638, 0x863f, 0x8831, 0x8b8a, 0x9090, 0x908f, 0x9463,
+ 0x9460, 0x9464, 0x9768, 0x986f, 0x995c, 0x9a5a, 0x9a5b, 0x9a57,
+ 0x9ad3, 0x9ad4, 0x9ad1, 0x9c54, 0x9c57, 0x9c56, 0x9de5, 0x9e9f,
+ 0x9ef4, 0x56d1, 0x58e9, 0x652c, 0x705e, 0x7671, 0x7672, 0x77d7,
+ 0x7f50, 0x7f88, 0x8836, 0x8839, 0x8862, 0x8b93, 0x8b92, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8b96, 0x8277, 0x8d1b, 0x91c0, 0x946a, 0x9742, 0x9748, 0x9744,
+ 0x97c6, 0x9870, 0x9a5f, 0x9b22, 0x9b58, 0x9c5f, 0x9df9, 0x9dfa,
+ 0x9e7c, 0x9e7d, 0x9f07, 0x9f77, 0x9f72, 0x5ef3, 0x6b16, 0x7063,
+ 0x7c6c, 0x7c6e, 0x883b, 0x89c0, 0x8ea1, 0x91c1, 0x9472, 0x9470,
+ 0x9871, 0x995e, 0x9ad6, 0x9b23, 0x9ecc, 0x7064, 0x77da, 0x8b9a,
+ 0x9477, 0x97c9, 0x9a62, 0x9a65, 0x7e9c, 0x8b9c, 0x8eaa, 0x91c5,
+ 0x947d, 0x947e, 0x947c, 0x9c77, 0x9c78, 0x9ef7, 0x8c54, 0x947f,
+ 0x9e1a, 0x7228, 0x9a6a, 0x9b31, 0x9e1b, 0x9e1e, 0x7c72, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4e42, 0x4e5c, 0x51f5, 0x531a, 0x5382, 0x4e07, 0x4e0c, 0x4e47,
+ 0x4e8d, 0x56d7, 0x0000, 0x5c6e, 0x5f73, 0x4e0f, 0x5187, 0x4e0e,
+ 0x4e2e, 0x4e93, 0x4ec2, 0x4ec9, 0x4ec8, 0x5198, 0x52fc, 0x536c,
+ 0x53b9, 0x5720, 0x5903, 0x592c, 0x5c10, 0x5dff, 0x65e1, 0x6bb3,
+ 0x6bcc, 0x6c14, 0x723f, 0x4e31, 0x4e3c, 0x4ee8, 0x4edc, 0x4ee9,
+ 0x4ee1, 0x4edd, 0x4eda, 0x520c, 0x531c, 0x534c, 0x5722, 0x5723,
+ 0x5917, 0x592f, 0x5b81, 0x5b84, 0x5c12, 0x5c3b, 0x5c74, 0x5c73,
+ 0x5e04, 0x5e80, 0x5e82, 0x5fc9, 0x6209, 0x6250, 0x6c15, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6c36, 0x6c43, 0x6c3f, 0x6c3b, 0x72ae, 0x72b0, 0x738a,
+ 0x79b8, 0x808a, 0x961e, 0x4f0e, 0x4f18, 0x4f2c, 0x4ef5, 0x4f14,
+ 0x4ef1, 0x4f00, 0x4ef7, 0x4f08, 0x4f1d, 0x4f02, 0x4f05, 0x4f22,
+ 0x4f13, 0x4f04, 0x4ef4, 0x4f12, 0x51b1, 0x5213, 0x5209, 0x5210,
+ 0x52a6, 0x5322, 0x531f, 0x534d, 0x538a, 0x5407, 0x56e1, 0x56df,
+ 0x572e, 0x572a, 0x5734, 0x593c, 0x5980, 0x597c, 0x5985, 0x597b,
+ 0x597e, 0x5977, 0x597f, 0x5b56, 0x5c15, 0x5c25, 0x5c7c, 0x5c7a,
+ 0x5c7b, 0x5c7e, 0x5ddf, 0x5e75, 0x5e84, 0x5f02, 0x5f1a, 0x5f74,
+ 0x5fd5, 0x5fd4, 0x5fcf, 0x625c, 0x625e, 0x6264, 0x6261, 0x6266,
+ 0x6262, 0x6259, 0x6260, 0x625a, 0x6265, 0x65ef, 0x65ee, 0x673e,
+ 0x6739, 0x6738, 0x673b, 0x673a, 0x673f, 0x673c, 0x6733, 0x6c18,
+ 0x6c46, 0x6c52, 0x6c5c, 0x6c4f, 0x6c4a, 0x6c54, 0x6c4b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6c4c, 0x7071, 0x725e, 0x72b4, 0x72b5, 0x738e, 0x752a, 0x767f,
+ 0x7a75, 0x7f51, 0x8278, 0x827c, 0x8280, 0x827d, 0x827f, 0x864d,
+ 0x897e, 0x9099, 0xe7d3, 0x9098, 0x909b, 0x9094, 0x9622, 0x9624,
+ 0x9620, 0x9623, 0x4f56, 0x4f3b, 0x4f62, 0x4f49, 0x4f53, 0x4f64,
+ 0x4f3e, 0x4f67, 0x4f52, 0x4f5f, 0x4f41, 0x4f58, 0x4f2d, 0x4f33,
+ 0x4f3f, 0x4f61, 0x518f, 0x51b9, 0x521c, 0x521e, 0x5221, 0x52ad,
+ 0x52ae, 0x5309, 0x5363, 0x5372, 0x538e, 0x538f, 0x5430, 0x5437,
+ 0x542a, 0x5454, 0x5445, 0x5419, 0x541c, 0x5425, 0x5418, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x543d, 0x544f, 0x5441, 0x5428, 0x5424, 0x5447, 0x56ee,
+ 0x56e7, 0x56e5, 0x5741, 0x5745, 0x574c, 0x5749, 0x574b, 0x5752,
+ 0x5906, 0x5940, 0x59a6, 0x5998, 0x59a0, 0x5997, 0x598e, 0x59a2,
+ 0x5990, 0x598f, 0x59a7, 0x59a1, 0x5b8e, 0x5b92, 0x5c28, 0x5c2a,
+ 0x5c8d, 0x5c8f, 0x5c88, 0x5c8b, 0x5c89, 0x5c92, 0x5c8a, 0x5c86,
+ 0x5c93, 0x5c95, 0x5de0, 0x5e0a, 0x5e0e, 0x5e8b, 0x5e89, 0x5e8c,
+ 0x5e88, 0x5e8d, 0x5f05, 0x5f1d, 0x5f78, 0x5f76, 0x5fd2, 0x5fd1,
+ 0x5fd0, 0x5fed, 0x5fe8, 0x5fee, 0x5ff3, 0x5fe1, 0x5fe4, 0x5fe3,
+ 0x5ffa, 0x5fef, 0x5ff7, 0x5ffb, 0x6000, 0x5ff4, 0x623a, 0x6283,
+ 0x628c, 0x628e, 0x628f, 0x6294, 0x6287, 0x6271, 0x627b, 0x627a,
+ 0x6270, 0x6281, 0x6288, 0x6277, 0x627d, 0x6272, 0x6274, 0x6537,
+ 0x65f0, 0x65f4, 0x65f3, 0x65f2, 0x65f5, 0x6745, 0x6747, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6759, 0x6755, 0x674c, 0x6748, 0x675d, 0x674d, 0x675a, 0x674b,
+ 0x6bd0, 0x6c19, 0x6c1a, 0x6c78, 0x6c67, 0x6c6b, 0x6c84, 0x6c8b,
+ 0x6c8f, 0x6c71, 0x6c6f, 0x6c69, 0x6c9a, 0x6c6d, 0x6c87, 0x6c95,
+ 0x6c9c, 0x6c66, 0x6c73, 0x6c65, 0x6c7b, 0x6c8e, 0x7074, 0x707a,
+ 0x7263, 0x72bf, 0x72bd, 0x72c3, 0x72c6, 0x72c1, 0x72ba, 0x72c5,
+ 0x7395, 0x7397, 0x7393, 0x7394, 0x7392, 0x753a, 0x7539, 0x7594,
+ 0x7595, 0x7681, 0x793d, 0x8034, 0x8095, 0x8099, 0x8090, 0x8092,
+ 0x809c, 0x8290, 0x828f, 0x8285, 0x828e, 0x8291, 0x8293, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x828a, 0x8283, 0x8284, 0x8c78, 0x8fc9, 0x8fbf, 0x909f,
+ 0x90a1, 0x90a5, 0x909e, 0x90a7, 0x90a0, 0x9630, 0x9628, 0x962f,
+ 0x962d, 0x4e33, 0x4f98, 0x4f7c, 0x4f85, 0x4f7d, 0x4f80, 0x4f87,
+ 0x4f76, 0x4f74, 0x4f89, 0x4f84, 0x4f77, 0x4f4c, 0x4f97, 0x4f6a,
+ 0x4f9a, 0x4f79, 0x4f81, 0x4f78, 0x4f90, 0x4f9c, 0x4f94, 0x4f9e,
+ 0x4f92, 0x4f82, 0x4f95, 0x4f6b, 0x4f6e, 0x519e, 0x51bc, 0x51be,
+ 0x5235, 0x5232, 0x5233, 0x5246, 0x5231, 0x52bc, 0x530a, 0x530b,
+ 0x533c, 0x5392, 0x5394, 0x5487, 0x547f, 0x5481, 0x5491, 0x5482,
+ 0x5488, 0x546b, 0x547a, 0x547e, 0x5465, 0x546c, 0x5474, 0x5466,
+ 0x548d, 0x546f, 0x5461, 0x5460, 0x5498, 0x5463, 0x5467, 0x5464,
+ 0x56f7, 0x56f9, 0x576f, 0x5772, 0x576d, 0x576b, 0x5771, 0x5770,
+ 0x5776, 0x5780, 0x5775, 0x577b, 0x5773, 0x5774, 0x5762, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5768, 0x577d, 0x590c, 0x5945, 0x59b5, 0x59ba, 0x59cf, 0x59ce,
+ 0x59b2, 0x59cc, 0x59c1, 0x59b6, 0x59bc, 0x59c3, 0x59d6, 0x59b1,
+ 0x59bd, 0x59c0, 0x59c8, 0x59b4, 0x59c7, 0x5b62, 0x5b65, 0x5b93,
+ 0x5b95, 0x5c44, 0x5c47, 0x5cae, 0x5ca4, 0x5ca0, 0x5cb5, 0x5caf,
+ 0x5ca8, 0x5cac, 0x5c9f, 0x5ca3, 0x5cad, 0x5ca2, 0x5caa, 0x5ca7,
+ 0x5c9d, 0x5ca5, 0x5cb6, 0x5cb0, 0x5ca6, 0x5e17, 0x5e14, 0x5e19,
+ 0x5f28, 0x5f22, 0x5f23, 0x5f24, 0x5f54, 0x5f82, 0x5f7e, 0x5f7d,
+ 0x5fde, 0x5fe5, 0x602d, 0x6026, 0x6019, 0x6032, 0x600b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6034, 0x600a, 0x6017, 0x6033, 0x601a, 0x601e, 0x602c,
+ 0x6022, 0x600d, 0x6010, 0x602e, 0x6013, 0x6011, 0x600c, 0x6009,
+ 0x601c, 0x6214, 0x623d, 0x62ad, 0x62b4, 0x62d1, 0x62be, 0x62aa,
+ 0x62b6, 0x62ca, 0x62ae, 0x62b3, 0x62af, 0x62bb, 0x62a9, 0x62b0,
+ 0x62b8, 0x653d, 0x65a8, 0x65bb, 0x6609, 0x65fc, 0x6604, 0x6612,
+ 0x6608, 0x65fb, 0x6603, 0x660b, 0x660d, 0x6605, 0x65fd, 0x6611,
+ 0x6610, 0x66f6, 0x670a, 0x6785, 0x676c, 0x678e, 0x6792, 0x6776,
+ 0x677b, 0x6798, 0x6786, 0x6784, 0x6774, 0x678d, 0x678c, 0x677a,
+ 0x679f, 0x6791, 0x6799, 0x6783, 0x677d, 0x6781, 0x6778, 0x6779,
+ 0x6794, 0x6b25, 0x6b80, 0x6b7e, 0x6bde, 0x6c1d, 0x6c93, 0x6cec,
+ 0x6ceb, 0x6cee, 0x6cd9, 0x6cb6, 0x6cd4, 0x6cad, 0x6ce7, 0x6cb7,
+ 0x6cd0, 0x6cc2, 0x6cba, 0x6cc3, 0x6cc6, 0x6ced, 0x6cf2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6cd2, 0x6cdd, 0x6cb4, 0x6c8a, 0x6c9d, 0x6c80, 0x6cde, 0x6cc0,
+ 0x6d30, 0x6ccd, 0x6cc7, 0x6cb0, 0x6cf9, 0x6ccf, 0x6ce9, 0x6cd1,
+ 0x7094, 0x7098, 0x7085, 0x7093, 0x7086, 0x7084, 0x7091, 0x7096,
+ 0x7082, 0x709a, 0x7083, 0x726a, 0x72d6, 0x72cb, 0x72d8, 0x72c9,
+ 0x72dc, 0x72d2, 0x72d4, 0x72da, 0x72cc, 0x72d1, 0x73a4, 0x73a1,
+ 0x73ad, 0x73a6, 0x73a2, 0x73a0, 0x73ac, 0x739d, 0x74dd, 0x74e8,
+ 0x753f, 0x7540, 0x753e, 0x758c, 0x7598, 0x76af, 0x76f3, 0x76f1,
+ 0x76f0, 0x76f5, 0x77f8, 0x77fc, 0x77f9, 0x77fb, 0x77fa, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x77f7, 0x7942, 0x793f, 0x79c5, 0x7a78, 0x7a7b, 0x7afb,
+ 0x7c75, 0x7cfd, 0x8035, 0x808f, 0x80ae, 0x80a3, 0x80b8, 0x80b5,
+ 0x80ad, 0x8220, 0x82a0, 0x82c0, 0x82ab, 0x829a, 0x8298, 0x829b,
+ 0x82b5, 0x82a7, 0x82ae, 0x82bc, 0x829e, 0x82ba, 0x82b4, 0x82a8,
+ 0x82a1, 0x82a9, 0x82c2, 0x82a4, 0x82c3, 0x82b6, 0x82a2, 0x8670,
+ 0x866f, 0x866d, 0x866e, 0x8c56, 0x8fd2, 0x8fcb, 0x8fd3, 0x8fcd,
+ 0x8fd6, 0x8fd5, 0x8fd7, 0x90b2, 0x90b4, 0x90af, 0x90b3, 0x90b0,
+ 0x9639, 0x963d, 0x963c, 0x963a, 0x9643, 0x4fcd, 0x4fc5, 0x4fd3,
+ 0x4fb2, 0x4fc9, 0x4fcb, 0x4fc1, 0x4fd4, 0x4fdc, 0x4fd9, 0x4fbb,
+ 0x4fb3, 0x4fdb, 0x4fc7, 0x4fd6, 0x4fba, 0x4fc0, 0x4fb9, 0x4fec,
+ 0x5244, 0x5249, 0x52c0, 0x52c2, 0x533d, 0x537c, 0x5397, 0x5396,
+ 0x5399, 0x5398, 0x54ba, 0x54a1, 0x54ad, 0x54a5, 0x54cf, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x54c3, 0x830d, 0x54b7, 0x54ae, 0x54d6, 0x54b6, 0x54c5, 0x54c6,
+ 0x54a0, 0x5470, 0x54bc, 0x54a2, 0x54be, 0x5472, 0x54de, 0x54b0,
+ 0x57b5, 0x579e, 0x579f, 0x57a4, 0x578c, 0x5797, 0x579d, 0x579b,
+ 0x5794, 0x5798, 0x578f, 0x5799, 0x57a5, 0x579a, 0x5795, 0x58f4,
+ 0x590d, 0x5953, 0x59e1, 0x59de, 0x59ee, 0x5a00, 0x59f1, 0x59dd,
+ 0x59fa, 0x59fd, 0x59fc, 0x59f6, 0x59e4, 0x59f2, 0x59f7, 0x59db,
+ 0x59e9, 0x59f3, 0x59f5, 0x59e0, 0x59fe, 0x59f4, 0x59ed, 0x5ba8,
+ 0x5c4c, 0x5cd0, 0x5cd8, 0x5ccc, 0x5cd7, 0x5ccb, 0x5cdb, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5cde, 0x5cda, 0x5cc9, 0x5cc7, 0x5cca, 0x5cd6, 0x5cd3,
+ 0x5cd4, 0x5ccf, 0x5cc8, 0x5cc6, 0x5cce, 0x5cdf, 0x5cf8, 0x5df9,
+ 0x5e21, 0x5e22, 0x5e23, 0x5e20, 0x5e24, 0x5eb0, 0x5ea4, 0x5ea2,
+ 0x5e9b, 0x5ea3, 0x5ea5, 0x5f07, 0x5f2e, 0x5f56, 0x5f86, 0x6037,
+ 0x6039, 0x6054, 0x6072, 0x605e, 0x6045, 0x6053, 0x6047, 0x6049,
+ 0x605b, 0x604c, 0x6040, 0x6042, 0x605f, 0x6024, 0x6044, 0x6058,
+ 0x6066, 0x606e, 0x6242, 0x6243, 0x62cf, 0x630d, 0x630b, 0x62f5,
+ 0x630e, 0x6303, 0x62eb, 0x62f9, 0x630f, 0x630c, 0x62f8, 0x62f6,
+ 0x6300, 0x6313, 0x6314, 0x62fa, 0x6315, 0x62fb, 0x62f0, 0x6541,
+ 0x6543, 0x65aa, 0x65bf, 0x6636, 0x6621, 0x6632, 0x6635, 0x661c,
+ 0x6626, 0x6622, 0x6633, 0x662b, 0x663a, 0x661d, 0x6634, 0x6639,
+ 0x662e, 0x670f, 0x6710, 0x67c1, 0x67f2, 0x67c8, 0x67ba, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x67dc, 0x67bb, 0x67f8, 0x67d8, 0x67c0, 0x67b7, 0x67c5, 0x67eb,
+ 0x67e4, 0x67df, 0x67b5, 0x67cd, 0x67b3, 0x67f7, 0x67f6, 0x67ee,
+ 0x67e3, 0x67c2, 0x67b9, 0x67ce, 0x67e7, 0x67f0, 0x67b2, 0x67fc,
+ 0x67c6, 0x67ed, 0x67cc, 0x67ae, 0x67e6, 0x67db, 0x67fa, 0x67c9,
+ 0x67ca, 0x67c3, 0x67ea, 0x67cb, 0x6b28, 0x6b82, 0x6b84, 0x6bb6,
+ 0x6bd6, 0x6bd8, 0x6be0, 0x6c20, 0x6c21, 0x6d28, 0x6d34, 0x6d2d,
+ 0x6d1f, 0x6d3c, 0x6d3f, 0x6d12, 0x6d0a, 0x6cda, 0x6d33, 0x6d04,
+ 0x6d19, 0x6d3a, 0x6d1a, 0x6d11, 0x6d00, 0x6d1d, 0x6d42, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6d01, 0x6d18, 0x6d37, 0x6d03, 0x6d0f, 0x6d40, 0x6d07,
+ 0x6d20, 0x6d2c, 0x6d08, 0x6d22, 0x6d09, 0x6d10, 0x70b7, 0x709f,
+ 0x70be, 0x70b1, 0x70b0, 0x70a1, 0x70b4, 0x70b5, 0x70a9, 0x7241,
+ 0x7249, 0x724a, 0x726c, 0x7270, 0x7273, 0x726e, 0x72ca, 0x72e4,
+ 0x72e8, 0x72eb, 0x72df, 0x72ea, 0x72e6, 0x72e3, 0x7385, 0x73cc,
+ 0x73c2, 0x73c8, 0x73c5, 0x73b9, 0x73b6, 0x73b5, 0x73b4, 0x73eb,
+ 0x73bf, 0x73c7, 0x73be, 0x73c3, 0x73c6, 0x73b8, 0x73cb, 0x74ec,
+ 0x74ee, 0x752e, 0x7547, 0x7548, 0x75a7, 0x75aa, 0x7679, 0x76c4,
+ 0x7708, 0x7703, 0x7704, 0x7705, 0x770a, 0x76f7, 0x76fb, 0x76fa,
+ 0x77e7, 0x77e8, 0x7806, 0x7811, 0x7812, 0x7805, 0x7810, 0x780f,
+ 0x780e, 0x7809, 0x7803, 0x7813, 0x794a, 0x794c, 0x794b, 0x7945,
+ 0x7944, 0x79d5, 0x79cd, 0x79cf, 0x79d6, 0x79ce, 0x7a80, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7a7e, 0x7ad1, 0x7b00, 0x7b01, 0x7c7a, 0x7c78, 0x7c79, 0x7c7f,
+ 0x7c80, 0x7c81, 0x7d03, 0x7d08, 0x7d01, 0x7f58, 0x7f91, 0x7f8d,
+ 0x7fbe, 0x8007, 0x800e, 0x800f, 0x8014, 0x8037, 0x80d8, 0x80c7,
+ 0x80e0, 0x80d1, 0x80c8, 0x80c2, 0x80d0, 0x80c5, 0x80e3, 0x80d9,
+ 0x80dc, 0x80ca, 0x80d5, 0x80c9, 0x80cf, 0x80d7, 0x80e6, 0x80cd,
+ 0x81ff, 0x8221, 0x8294, 0x82d9, 0x82fe, 0x82f9, 0x8307, 0x82e8,
+ 0x8300, 0x82d5, 0x833a, 0x82eb, 0x82d6, 0x82f4, 0x82ec, 0x82e1,
+ 0x82f2, 0x82f5, 0x830c, 0x82fb, 0x82f6, 0x82f0, 0x82ea, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x82e4, 0x82e0, 0x82fa, 0x82f3, 0x82ed, 0x8677, 0x8674,
+ 0x867c, 0x8673, 0x8841, 0x884e, 0x8867, 0x886a, 0x8869, 0x89d3,
+ 0x8a04, 0x8a07, 0x8d72, 0x8fe3, 0x8fe1, 0x8fee, 0x8fe0, 0x90f1,
+ 0x90bd, 0x90bf, 0x90d5, 0x90c5, 0x90be, 0x90c7, 0x90cb, 0x90c8,
+ 0x91d4, 0x91d3, 0x9654, 0x964f, 0x9651, 0x9653, 0x964a, 0x964e,
+ 0x501e, 0x5005, 0x5007, 0x5013, 0x5022, 0x5030, 0x501b, 0x4ff5,
+ 0x4ff4, 0x5033, 0x5037, 0x502c, 0x4ff6, 0x4ff7, 0x5017, 0x501c,
+ 0x5020, 0x5027, 0x5035, 0x502f, 0x5031, 0x500e, 0x515a, 0x5194,
+ 0x5193, 0x51ca, 0x51c4, 0x51c5, 0x51c8, 0x51ce, 0x5261, 0x525a,
+ 0x5252, 0x525e, 0x525f, 0x5255, 0x5262, 0x52cd, 0x530e, 0x539e,
+ 0x5526, 0x54e2, 0x5517, 0x5512, 0x54e7, 0x54f3, 0x54e4, 0x551a,
+ 0x54ff, 0x5504, 0x5508, 0x54eb, 0x5511, 0x5505, 0x54f1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x550a, 0x54fb, 0x54f7, 0x54f8, 0x54e0, 0x550e, 0x5503, 0x550b,
+ 0x5701, 0x5702, 0x57cc, 0x5832, 0x57d5, 0x57d2, 0x57ba, 0x57c6,
+ 0x57bd, 0x57bc, 0x57b8, 0x57b6, 0x57bf, 0x57c7, 0x57d0, 0x57b9,
+ 0x57c1, 0x590e, 0x594a, 0x5a19, 0x5a16, 0x5a2d, 0x5a2e, 0x5a15,
+ 0x5a0f, 0x5a17, 0x5a0a, 0x5a1e, 0x5a33, 0x5b6c, 0x5ba7, 0x5bad,
+ 0x5bac, 0x5c03, 0x5c56, 0x5c54, 0x5cec, 0x5cff, 0x5cee, 0x5cf1,
+ 0x5cf7, 0x5d00, 0x5cf9, 0x5e29, 0x5e28, 0x5ea8, 0x5eae, 0x5eaa,
+ 0x5eac, 0x5f33, 0x5f30, 0x5f67, 0x605d, 0x605a, 0x6067, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6041, 0x60a2, 0x6088, 0x6080, 0x6092, 0x6081, 0x609d,
+ 0x6083, 0x6095, 0x609b, 0x6097, 0x6087, 0x609c, 0x608e, 0x6219,
+ 0x6246, 0x62f2, 0x6310, 0x6356, 0x632c, 0x6344, 0x6345, 0x6336,
+ 0x6343, 0x63e4, 0x6339, 0x634b, 0x634a, 0x633c, 0x6329, 0x6341,
+ 0x6334, 0x6358, 0x6354, 0x6359, 0x632d, 0x6347, 0x6333, 0x635a,
+ 0x6351, 0x6338, 0x6357, 0x6340, 0x6348, 0x654a, 0x6546, 0x65c6,
+ 0x65c3, 0x65c4, 0x65c2, 0x664a, 0x665f, 0x6647, 0x6651, 0x6712,
+ 0x6713, 0x681f, 0x681a, 0x6849, 0x6832, 0x6833, 0x683b, 0x684b,
+ 0x684f, 0x6816, 0x6831, 0x681c, 0x6835, 0x682b, 0x682d, 0x682f,
+ 0x684e, 0x6844, 0x6834, 0x681d, 0x6812, 0x6814, 0x6826, 0x6828,
+ 0x682e, 0x684d, 0x683a, 0x6825, 0x6820, 0x6b2c, 0x6b2f, 0x6b2d,
+ 0x6b31, 0x6b34, 0x6b6d, 0x8082, 0x6b88, 0x6be6, 0x6be4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6be8, 0x6be3, 0x6be2, 0x6be7, 0x6c25, 0x6d7a, 0x6d63, 0x6d64,
+ 0x6d76, 0x6d0d, 0x6d61, 0x6d92, 0x6d58, 0x6d62, 0x6d6d, 0x6d6f,
+ 0x6d91, 0x6d8d, 0x6def, 0x6d7f, 0x6d86, 0x6d5e, 0x6d67, 0x6d60,
+ 0x6d97, 0x6d70, 0x6d7c, 0x6d5f, 0x6d82, 0x6d98, 0x6d2f, 0x6d68,
+ 0x6d8b, 0x6d7e, 0x6d80, 0x6d84, 0x6d16, 0x6d83, 0x6d7b, 0x6d7d,
+ 0x6d75, 0x6d90, 0x70dc, 0x70d3, 0x70d1, 0x70dd, 0x70cb, 0x7f39,
+ 0x70e2, 0x70d7, 0x70d2, 0x70de, 0x70e0, 0x70d4, 0x70cd, 0x70c5,
+ 0x70c6, 0x70c7, 0x70da, 0x70ce, 0x70e1, 0x7242, 0x7278, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7277, 0x7276, 0x7300, 0x72fa, 0x72f4, 0x72fe, 0x72f6,
+ 0x72f3, 0x72fb, 0x7301, 0x73d3, 0x73d9, 0x73e5, 0x73d6, 0x73bc,
+ 0x73e7, 0x73e3, 0x73e9, 0x73dc, 0x73d2, 0x73db, 0x73d4, 0x73dd,
+ 0x73da, 0x73d7, 0x73d8, 0x73e8, 0x74de, 0x74df, 0x74f4, 0x74f5,
+ 0x7521, 0x755b, 0x755f, 0x75b0, 0x75c1, 0x75bb, 0x75c4, 0x75c0,
+ 0x75bf, 0x75b6, 0x75ba, 0x768a, 0x76c9, 0x771d, 0x771b, 0x7710,
+ 0x7713, 0x7712, 0x7723, 0x7711, 0x7715, 0x7719, 0x771a, 0x7722,
+ 0x7727, 0x7823, 0x782c, 0x7822, 0x7835, 0x782f, 0x7828, 0x782e,
+ 0x782b, 0x7821, 0x7829, 0x7833, 0x782a, 0x7831, 0x7954, 0x795b,
+ 0x794f, 0x795c, 0x7953, 0x7952, 0x7951, 0x79eb, 0x79ec, 0x79e0,
+ 0x79ee, 0x79ed, 0x79ea, 0x79dc, 0x79de, 0x79dd, 0x7a86, 0x7a89,
+ 0x7a85, 0x7a8b, 0x7a8c, 0x7a8a, 0x7a87, 0x7ad8, 0x7b10, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7b04, 0x7b13, 0x7b05, 0x7b0f, 0x7b08, 0x7b0a, 0x7b0e, 0x7b09,
+ 0x7b12, 0x7c84, 0x7c91, 0x7c8a, 0x7c8c, 0x7c88, 0x7c8d, 0x7c85,
+ 0x7d1e, 0x7d1d, 0x7d11, 0x7d0e, 0x7d18, 0x7d16, 0x7d13, 0x7d1f,
+ 0x7d12, 0x7d0f, 0x7d0c, 0x7f5c, 0x7f61, 0x7f5e, 0x7f60, 0x7f5d,
+ 0x7f5b, 0x7f96, 0x7f92, 0x7fc3, 0x7fc2, 0x7fc0, 0x8016, 0x803e,
+ 0x8039, 0x80fa, 0x80f2, 0x80f9, 0x80f5, 0x8101, 0x80fb, 0x8100,
+ 0x8201, 0x822f, 0x8225, 0x8333, 0x832d, 0x8344, 0x8319, 0x8351,
+ 0x8325, 0x8356, 0x833f, 0x8341, 0x8326, 0x831c, 0x8322, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8342, 0x834e, 0x831b, 0x832a, 0x8308, 0x833c, 0x834d,
+ 0x8316, 0x8324, 0x8320, 0x8337, 0x832f, 0x8329, 0x8347, 0x8345,
+ 0x834c, 0x8353, 0x831e, 0x832c, 0x834b, 0x8327, 0x8348, 0x8653,
+ 0x8652, 0x86a2, 0x86a8, 0x8696, 0x868d, 0x8691, 0x869e, 0x8687,
+ 0x8697, 0x8686, 0x868b, 0x869a, 0x8685, 0x86a5, 0x8699, 0x86a1,
+ 0x86a7, 0x8695, 0x8698, 0x868e, 0x869d, 0x8690, 0x8694, 0x8843,
+ 0x8844, 0x886d, 0x8875, 0x8876, 0x8872, 0x8880, 0x8871, 0x887f,
+ 0x886f, 0x8883, 0x887e, 0x8874, 0x887c, 0x8a12, 0x8c47, 0x8c57,
+ 0x8c7b, 0x8ca4, 0x8ca3, 0x8d76, 0x8d78, 0x8db5, 0x8db7, 0x8db6,
+ 0x8ed1, 0x8ed3, 0x8ffe, 0x8ff5, 0x9002, 0x8fff, 0x8ffb, 0x9004,
+ 0x8ffc, 0x8ff6, 0x90d6, 0x90e0, 0x90d9, 0x90da, 0x90e3, 0x90df,
+ 0x90e5, 0x90d8, 0x90db, 0x90d7, 0x90dc, 0x90e4, 0x9150, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x914e, 0x914f, 0x91d5, 0x91e2, 0x91da, 0x965c, 0x965f, 0x96bc,
+ 0x98e3, 0x9adf, 0x9b2f, 0x4e7f, 0x5070, 0x506a, 0x5061, 0x505e,
+ 0x5060, 0x5053, 0x504b, 0x505d, 0x5072, 0x5048, 0x504d, 0x5041,
+ 0x505b, 0x504a, 0x5062, 0x5015, 0x5045, 0x505f, 0x5069, 0x506b,
+ 0x5063, 0x5064, 0x5046, 0x5040, 0x506e, 0x5073, 0x5057, 0x5051,
+ 0x51d0, 0x526b, 0x526d, 0x526c, 0x526e, 0x52d6, 0x52d3, 0x532d,
+ 0x539c, 0x5575, 0x5576, 0x553c, 0x554d, 0x5550, 0x5534, 0x552a,
+ 0x5551, 0x5562, 0x5536, 0x5535, 0x5530, 0x5552, 0x5545, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x550c, 0x5532, 0x5565, 0x554e, 0x5539, 0x5548, 0x552d,
+ 0x553b, 0x5540, 0x554b, 0x570a, 0x5707, 0x57fb, 0x5814, 0x57e2,
+ 0x57f6, 0x57dc, 0x57f4, 0x5800, 0x57ed, 0x57fd, 0x5808, 0x57f8,
+ 0x580b, 0x57f3, 0x57cf, 0x5807, 0x57ee, 0x57e3, 0x57f2, 0x57e5,
+ 0x57ec, 0x57e1, 0x580e, 0x57fc, 0x5810, 0x57e7, 0x5801, 0x580c,
+ 0x57f1, 0x57e9, 0x57f0, 0x580d, 0x5804, 0x595c, 0x5a60, 0x5a58,
+ 0x5a55, 0x5a67, 0x5a5e, 0x5a38, 0x5a35, 0x5a6d, 0x5a50, 0x5a5f,
+ 0x5a65, 0x5a6c, 0x5a53, 0x5a64, 0x5a57, 0x5a43, 0x5a5d, 0x5a52,
+ 0x5a44, 0x5a5b, 0x5a48, 0x5a8e, 0x5a3e, 0x5a4d, 0x5a39, 0x5a4c,
+ 0x5a70, 0x5a69, 0x5a47, 0x5a51, 0x5a56, 0x5a42, 0x5a5c, 0x5b72,
+ 0x5b6e, 0x5bc1, 0x5bc0, 0x5c59, 0x5d1e, 0x5d0b, 0x5d1d, 0x5d1a,
+ 0x5d20, 0x5d0c, 0x5d28, 0x5d0d, 0x5d26, 0x5d25, 0x5d0f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5d30, 0x5d12, 0x5d23, 0x5d1f, 0x5d2e, 0x5e3e, 0x5e34, 0x5eb1,
+ 0x5eb4, 0x5eb9, 0x5eb2, 0x5eb3, 0x5f36, 0x5f38, 0x5f9b, 0x5f96,
+ 0x5f9f, 0x608a, 0x6090, 0x6086, 0x60be, 0x60b0, 0x60ba, 0x60d3,
+ 0x60d4, 0x60cf, 0x60e4, 0x60d9, 0x60dd, 0x60c8, 0x60b1, 0x60db,
+ 0x60b7, 0x60ca, 0x60bf, 0x60c3, 0x60cd, 0x60c0, 0x6332, 0x6365,
+ 0x638a, 0x6382, 0x637d, 0x63bd, 0x639e, 0x63ad, 0x639d, 0x6397,
+ 0x63ab, 0x638e, 0x636f, 0x6387, 0x6390, 0x636e, 0x63af, 0x6375,
+ 0x639c, 0x636d, 0x63ae, 0x637c, 0x63a4, 0x633b, 0x639f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6378, 0x6385, 0x6381, 0x6391, 0x638d, 0x6370, 0x6553,
+ 0x65cd, 0x6665, 0x6661, 0x665b, 0x6659, 0x665c, 0x6662, 0x6718,
+ 0x6879, 0x6887, 0x6890, 0x689c, 0x686d, 0x686e, 0x68ae, 0x68ab,
+ 0x6956, 0x686f, 0x68a3, 0x68ac, 0x68a9, 0x6875, 0x6874, 0x68b2,
+ 0x688f, 0x6877, 0x6892, 0x687c, 0x686b, 0x6872, 0x68aa, 0x6880,
+ 0x6871, 0x687e, 0x689b, 0x6896, 0x688b, 0x68a0, 0x6889, 0x68a4,
+ 0x6878, 0x687b, 0x6891, 0x688c, 0x688a, 0x687d, 0x6b36, 0x6b33,
+ 0x6b37, 0x6b38, 0x6b91, 0x6b8f, 0x6b8d, 0x6b8e, 0x6b8c, 0x6c2a,
+ 0x6dc0, 0x6dab, 0x6db4, 0x6db3, 0x6e74, 0x6dac, 0x6de9, 0x6de2,
+ 0x6db7, 0x6df6, 0x6dd4, 0x6e00, 0x6dc8, 0x6de0, 0x6ddf, 0x6dd6,
+ 0x6dbe, 0x6de5, 0x6ddc, 0x6ddd, 0x6ddb, 0x6df4, 0x6dca, 0x6dbd,
+ 0x6ded, 0x6df0, 0x6dba, 0x6dd5, 0x6dc2, 0x6dcf, 0x6dc9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6dd0, 0x6df2, 0x6dd3, 0x6dfd, 0x6dd7, 0x6dcd, 0x6de3, 0x6dbb,
+ 0x70fa, 0x710d, 0x70f7, 0x7117, 0x70f4, 0x710c, 0x70f0, 0x7104,
+ 0x70f3, 0x7110, 0x70fc, 0x70ff, 0x7106, 0x7113, 0x7100, 0x70f8,
+ 0x70f6, 0x710b, 0x7102, 0x710e, 0x727e, 0x727b, 0x727c, 0x727f,
+ 0x731d, 0x7317, 0x7307, 0x7311, 0x7318, 0x730a, 0x7308, 0x72ff,
+ 0x730f, 0x731e, 0x7388, 0x73f6, 0x73f8, 0x73f5, 0x7404, 0x7401,
+ 0x73fd, 0x7407, 0x7400, 0x73fa, 0x73fc, 0x73ff, 0x740c, 0x740b,
+ 0x73f4, 0x7408, 0x7564, 0x7563, 0x75ce, 0x75d2, 0x75cf, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x75cb, 0x75cc, 0x75d1, 0x75d0, 0x768f, 0x7689, 0x76d3,
+ 0x7739, 0x772f, 0x772d, 0x7731, 0x7732, 0x7734, 0x7733, 0x773d,
+ 0x7725, 0x773b, 0x7735, 0x7848, 0x7852, 0x7849, 0x784d, 0x784a,
+ 0x784c, 0x7826, 0x7845, 0x7850, 0x7964, 0x7967, 0x7969, 0x796a,
+ 0x7963, 0x796b, 0x7961, 0x79bb, 0x79fa, 0x79f8, 0x79f6, 0x79f7,
+ 0x7a8f, 0x7a94, 0x7a90, 0x7b35, 0x7b47, 0x7b34, 0x7b25, 0x7b30,
+ 0x7b22, 0x7b24, 0x7b33, 0x7b18, 0x7b2a, 0x7b1d, 0x7b31, 0x7b2b,
+ 0x7b2d, 0x7b2f, 0x7b32, 0x7b38, 0x7b1a, 0x7b23, 0x7c94, 0x7c98,
+ 0x7c96, 0x7ca3, 0x7d35, 0x7d3d, 0x7d38, 0x7d36, 0x7d3a, 0x7d45,
+ 0x7d2c, 0x7d29, 0x7d41, 0x7d47, 0x7d3e, 0x7d3f, 0x7d4a, 0x7d3b,
+ 0x7d28, 0x7f63, 0x7f95, 0x7f9c, 0x7f9d, 0x7f9b, 0x7fca, 0x7fcb,
+ 0x7fcd, 0x7fd0, 0x7fd1, 0x7fc7, 0x7fcf, 0x7fc9, 0x801f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x801e, 0x801b, 0x8047, 0x8043, 0x8048, 0x8118, 0x8125, 0x8119,
+ 0x811b, 0x812d, 0x811f, 0x812c, 0x811e, 0x8121, 0x8115, 0x8127,
+ 0x811d, 0x8122, 0x8211, 0x8238, 0x8233, 0x823a, 0x8234, 0x8232,
+ 0x8274, 0x8390, 0x83a3, 0x83a8, 0x838d, 0x837a, 0x8373, 0x83a4,
+ 0x8374, 0x838f, 0x8381, 0x8395, 0x8399, 0x8375, 0x8394, 0x83a9,
+ 0x837d, 0x8383, 0x838c, 0x839d, 0x839b, 0x83aa, 0x838b, 0x837e,
+ 0x83a5, 0x83af, 0x8388, 0x8397, 0x83b0, 0x837f, 0x83a6, 0x8387,
+ 0x83ae, 0x8376, 0x839a, 0x8659, 0x8656, 0x86bf, 0x86b7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x86c2, 0x86c1, 0x86c5, 0x86ba, 0x86b0, 0x86c8, 0x86b9,
+ 0x86b3, 0x86b8, 0x86cc, 0x86b4, 0x86bb, 0x86bc, 0x86c3, 0x86bd,
+ 0x86be, 0x8852, 0x8889, 0x8895, 0x88a8, 0x88a2, 0x88aa, 0x889a,
+ 0x8891, 0x88a1, 0x889f, 0x8898, 0x88a7, 0x8899, 0x889b, 0x8897,
+ 0x88a4, 0x88ac, 0x888c, 0x8893, 0x888e, 0x8982, 0x89d6, 0x89d9,
+ 0x89d5, 0x8a30, 0x8a27, 0x8a2c, 0x8a1e, 0x8c39, 0x8c3b, 0x8c5c,
+ 0x8c5d, 0x8c7d, 0x8ca5, 0x8d7d, 0x8d7b, 0x8d79, 0x8dbc, 0x8dc2,
+ 0x8db9, 0x8dbf, 0x8dc1, 0x8ed8, 0x8ede, 0x8edd, 0x8edc, 0x8ed7,
+ 0x8ee0, 0x8ee1, 0x9024, 0x900b, 0x9011, 0x901c, 0x900c, 0x9021,
+ 0x90ef, 0x90ea, 0x90f0, 0x90f4, 0x90f2, 0x90f3, 0x90d4, 0x90eb,
+ 0x90ec, 0x90e9, 0x9156, 0x9158, 0x915a, 0x9153, 0x9155, 0x91ec,
+ 0x91f4, 0x91f1, 0x91f3, 0x91f8, 0x91e4, 0x91f9, 0x91ea, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x91eb, 0x91f7, 0x91e8, 0x91ee, 0x957a, 0x9586, 0x9588, 0x967c,
+ 0x966d, 0x966b, 0x9671, 0x966f, 0x96bf, 0x976a, 0x9804, 0x98e5,
+ 0x9997, 0x509b, 0x5095, 0x5094, 0x509e, 0x508b, 0x50a3, 0x5083,
+ 0x508c, 0x508e, 0x509d, 0x5068, 0x509c, 0x5092, 0x5082, 0x5087,
+ 0x515f, 0x51d4, 0x5312, 0x5311, 0x53a4, 0x53a7, 0x5591, 0x55a8,
+ 0x55a5, 0x55ad, 0x5577, 0x5645, 0x55a2, 0x5593, 0x5588, 0x558f,
+ 0x55b5, 0x5581, 0x55a3, 0x5592, 0x55a4, 0x557d, 0x558c, 0x55a6,
+ 0x557f, 0x5595, 0x55a1, 0x558e, 0x570c, 0x5829, 0x5837, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5819, 0x581e, 0x5827, 0x5823, 0x5828, 0x57f5, 0x5848,
+ 0x5825, 0x581c, 0x581b, 0x5833, 0x583f, 0x5836, 0x582e, 0x5839,
+ 0x5838, 0x582d, 0x582c, 0x583b, 0x5961, 0x5aaf, 0x5a94, 0x5a9f,
+ 0x5a7a, 0x5aa2, 0x5a9e, 0x5a78, 0x5aa6, 0x5a7c, 0x5aa5, 0x5aac,
+ 0x5a95, 0x5aae, 0x5a37, 0x5a84, 0x5a8a, 0x5a97, 0x5a83, 0x5a8b,
+ 0x5aa9, 0x5a7b, 0x5a7d, 0x5a8c, 0x5a9c, 0x5a8f, 0x5a93, 0x5a9d,
+ 0x5bea, 0x5bcd, 0x5bcb, 0x5bd4, 0x5bd1, 0x5bca, 0x5bce, 0x5c0c,
+ 0x5c30, 0x5d37, 0x5d43, 0x5d6b, 0x5d41, 0x5d4b, 0x5d3f, 0x5d35,
+ 0x5d51, 0x5d4e, 0x5d55, 0x5d33, 0x5d3a, 0x5d52, 0x5d3d, 0x5d31,
+ 0x5d59, 0x5d42, 0x5d39, 0x5d49, 0x5d38, 0x5d3c, 0x5d32, 0x5d36,
+ 0x5d40, 0x5d45, 0x5e44, 0x5e41, 0x5f58, 0x5fa6, 0x5fa5, 0x5fab,
+ 0x60c9, 0x60b9, 0x60cc, 0x60e2, 0x60ce, 0x60c4, 0x6114, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x60f2, 0x610a, 0x6116, 0x6105, 0x60f5, 0x6113, 0x60f8, 0x60fc,
+ 0x60fe, 0x60c1, 0x6103, 0x6118, 0x611d, 0x6110, 0x60ff, 0x6104,
+ 0x610b, 0x624a, 0x6394, 0x63b1, 0x63b0, 0x63ce, 0x63e5, 0x63e8,
+ 0x63ef, 0x63c3, 0x649d, 0x63f3, 0x63ca, 0x63e0, 0x63f6, 0x63d5,
+ 0x63f2, 0x63f5, 0x6461, 0x63df, 0x63be, 0x63dd, 0x63dc, 0x63c4,
+ 0x63d8, 0x63d3, 0x63c2, 0x63c7, 0x63cc, 0x63cb, 0x63c8, 0x63f0,
+ 0x63d7, 0x63d9, 0x6532, 0x6567, 0x656a, 0x6564, 0x655c, 0x6568,
+ 0x6565, 0x658c, 0x659d, 0x659e, 0x65ae, 0x65d0, 0x65d2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x667c, 0x666c, 0x667b, 0x6680, 0x6671, 0x6679, 0x666a,
+ 0x6672, 0x6701, 0x690c, 0x68d3, 0x6904, 0x68dc, 0x692a, 0x68ec,
+ 0x68ea, 0x68f1, 0x690f, 0x68d6, 0x68f7, 0x68eb, 0x68e4, 0x68f6,
+ 0x6913, 0x6910, 0x68f3, 0x68e1, 0x6907, 0x68cc, 0x6908, 0x6970,
+ 0x68b4, 0x6911, 0x68ef, 0x68c6, 0x6914, 0x68f8, 0x68d0, 0x68fd,
+ 0x68fc, 0x68e8, 0x690b, 0x690a, 0x6917, 0x68ce, 0x68c8, 0x68dd,
+ 0x68de, 0x68e6, 0x68f4, 0x68d1, 0x6906, 0x68d4, 0x68e9, 0x6915,
+ 0x6925, 0x68c7, 0x6b39, 0x6b3b, 0x6b3f, 0x6b3c, 0x6b94, 0x6b97,
+ 0x6b99, 0x6b95, 0x6bbd, 0x6bf0, 0x6bf2, 0x6bf3, 0x6c30, 0x6dfc,
+ 0x6e46, 0x6e47, 0x6e1f, 0x6e49, 0x6e88, 0x6e3c, 0x6e3d, 0x6e45,
+ 0x6e62, 0x6e2b, 0x6e3f, 0x6e41, 0x6e5d, 0x6e73, 0x6e1c, 0x6e33,
+ 0x6e4b, 0x6e40, 0x6e51, 0x6e3b, 0x6e03, 0x6e2e, 0x6e5e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6e68, 0x6e5c, 0x6e61, 0x6e31, 0x6e28, 0x6e60, 0x6e71, 0x6e6b,
+ 0x6e39, 0x6e22, 0x6e30, 0x6e53, 0x6e65, 0x6e27, 0x6e78, 0x6e64,
+ 0x6e77, 0x6e55, 0x6e79, 0x6e52, 0x6e66, 0x6e35, 0x6e36, 0x6e5a,
+ 0x7120, 0x711e, 0x712f, 0x70fb, 0x712e, 0x7131, 0x7123, 0x7125,
+ 0x7122, 0x7132, 0x711f, 0x7128, 0x713a, 0x711b, 0x724b, 0x725a,
+ 0x7288, 0x7289, 0x7286, 0x7285, 0x728b, 0x7312, 0x730b, 0x7330,
+ 0x7322, 0x7331, 0x7333, 0x7327, 0x7332, 0x732d, 0x7326, 0x7323,
+ 0x7335, 0x730c, 0x742e, 0x742c, 0x7430, 0x742b, 0x7416, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x741a, 0x7421, 0x742d, 0x7431, 0x7424, 0x7423, 0x741d,
+ 0x7429, 0x7420, 0x7432, 0x74fb, 0x752f, 0x756f, 0x756c, 0x75e7,
+ 0x75da, 0x75e1, 0x75e6, 0x75dd, 0x75df, 0x75e4, 0x75d7, 0x7695,
+ 0x7692, 0x76da, 0x7746, 0x7747, 0x7744, 0x774d, 0x7745, 0x774a,
+ 0x774e, 0x774b, 0x774c, 0x77de, 0x77ec, 0x7860, 0x7864, 0x7865,
+ 0x785c, 0x786d, 0x7871, 0x786a, 0x786e, 0x7870, 0x7869, 0x7868,
+ 0x785e, 0x7862, 0x7974, 0x7973, 0x7972, 0x7970, 0x7a02, 0x7a0a,
+ 0x7a03, 0x7a0c, 0x7a04, 0x7a99, 0x7ae6, 0x7ae4, 0x7b4a, 0x7b3b,
+ 0x7b44, 0x7b48, 0x7b4c, 0x7b4e, 0x7b40, 0x7b58, 0x7b45, 0x7ca2,
+ 0x7c9e, 0x7ca8, 0x7ca1, 0x7d58, 0x7d6f, 0x7d63, 0x7d53, 0x7d56,
+ 0x7d67, 0x7d6a, 0x7d4f, 0x7d6d, 0x7d5c, 0x7d6b, 0x7d52, 0x7d54,
+ 0x7d69, 0x7d51, 0x7d5f, 0x7d4e, 0x7f3e, 0x7f3f, 0x7f65, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7f66, 0x7fa2, 0x7fa0, 0x7fa1, 0x7fd7, 0x8051, 0x804f, 0x8050,
+ 0x80fe, 0x80d4, 0x8143, 0x814a, 0x8152, 0x814f, 0x8147, 0x813d,
+ 0x814d, 0x813a, 0x81e6, 0x81ee, 0x81f7, 0x81f8, 0x81f9, 0x8204,
+ 0x823c, 0x823d, 0x823f, 0x8275, 0x833b, 0x83cf, 0x83f9, 0x8423,
+ 0x83c0, 0x83e8, 0x8412, 0x83e7, 0x83e4, 0x83fc, 0x83f6, 0x8410,
+ 0x83c6, 0x83c8, 0x83eb, 0x83e3, 0x83bf, 0x8401, 0x83dd, 0x83e5,
+ 0x83d8, 0x83ff, 0x83e1, 0x83cb, 0x83ce, 0x83d6, 0x83f5, 0x83c9,
+ 0x8409, 0x840f, 0x83de, 0x8411, 0x8406, 0x83c2, 0x83f3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x83d5, 0x83fa, 0x83c7, 0x83d1, 0x83ea, 0x8413, 0x83c3,
+ 0x83ec, 0x83ee, 0x83c4, 0x83fb, 0x83d7, 0x83e2, 0x841b, 0x83db,
+ 0x83fe, 0x86d8, 0x86e2, 0x86e6, 0x86d3, 0x86e3, 0x86da, 0x86ea,
+ 0x86dd, 0x86eb, 0x86dc, 0x86ec, 0x86e9, 0x86d7, 0x86e8, 0x86d1,
+ 0x8848, 0x8856, 0x8855, 0x88ba, 0x88d7, 0x88b9, 0x88b8, 0x88c0,
+ 0x88be, 0x88b6, 0x88bc, 0x88b7, 0x88bd, 0x88b2, 0x8901, 0x88c9,
+ 0x8995, 0x8998, 0x8997, 0x89dd, 0x89da, 0x89db, 0x8a4e, 0x8a4d,
+ 0x8a39, 0x8a59, 0x8a40, 0x8a57, 0x8a58, 0x8a44, 0x8a45, 0x8a52,
+ 0x8a48, 0x8a51, 0x8a4a, 0x8a4c, 0x8a4f, 0x8c5f, 0x8c81, 0x8c80,
+ 0x8cba, 0x8cbe, 0x8cb0, 0x8cb9, 0x8cb5, 0x8d84, 0x8d80, 0x8d89,
+ 0x8dd8, 0x8dd3, 0x8dcd, 0x8dc7, 0x8dd6, 0x8ddc, 0x8dcf, 0x8dd5,
+ 0x8dd9, 0x8dc8, 0x8dd7, 0x8dc5, 0x8eef, 0x8ef7, 0x8efa, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8ef9, 0x8ee6, 0x8eee, 0x8ee5, 0x8ef5, 0x8ee7, 0x8ee8, 0x8ef6,
+ 0x8eeb, 0x8ef1, 0x8eec, 0x8ef4, 0x8ee9, 0x902d, 0x9034, 0x902f,
+ 0x9106, 0x912c, 0x9104, 0x90ff, 0x90fc, 0x9108, 0x90f9, 0x90fb,
+ 0x9101, 0x9100, 0x9107, 0x9105, 0x9103, 0x9161, 0x9164, 0x915f,
+ 0x9162, 0x9160, 0x9201, 0x920a, 0x9225, 0x9203, 0x921a, 0x9226,
+ 0x920f, 0x920c, 0x9200, 0x9212, 0x91ff, 0x91fd, 0x9206, 0x9204,
+ 0x9227, 0x9202, 0x921c, 0x9224, 0x9219, 0x9217, 0x9205, 0x9216,
+ 0x957b, 0x958d, 0x958c, 0x9590, 0x9687, 0x967e, 0x9688, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9689, 0x9683, 0x9680, 0x96c2, 0x96c8, 0x96c3, 0x96f1,
+ 0x96f0, 0x976c, 0x9770, 0x976e, 0x9807, 0x98a9, 0x98eb, 0x9ce6,
+ 0x9ef9, 0x4e83, 0x4e84, 0x4eb6, 0x50bd, 0x50bf, 0x50c6, 0x50ae,
+ 0x50c4, 0x50ca, 0x50b4, 0x50c8, 0x50c2, 0x50b0, 0x50c1, 0x50ba,
+ 0x50b1, 0x50cb, 0x50c9, 0x50b6, 0x50b8, 0x51d7, 0x527a, 0x5278,
+ 0x527b, 0x527c, 0x55c3, 0x55db, 0x55cc, 0x55d0, 0x55cb, 0x55ca,
+ 0x55dd, 0x55c0, 0x55d4, 0x55c4, 0x55e9, 0x55bf, 0x55d2, 0x558d,
+ 0x55cf, 0x55d5, 0x55e2, 0x55d6, 0x55c8, 0x55f2, 0x55cd, 0x55d9,
+ 0x55c2, 0x5714, 0x5853, 0x5868, 0x5864, 0x584f, 0x584d, 0x5849,
+ 0x586f, 0x5855, 0x584e, 0x585d, 0x5859, 0x5865, 0x585b, 0x583d,
+ 0x5863, 0x5871, 0x58fc, 0x5ac7, 0x5ac4, 0x5acb, 0x5aba, 0x5ab8,
+ 0x5ab1, 0x5ab5, 0x5ab0, 0x5abf, 0x5ac8, 0x5abb, 0x5ac6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5ab7, 0x5ac0, 0x5aca, 0x5ab4, 0x5ab6, 0x5acd, 0x5ab9, 0x5a90,
+ 0x5bd6, 0x5bd8, 0x5bd9, 0x5c1f, 0x5c33, 0x5d71, 0x5d63, 0x5d4a,
+ 0x5d65, 0x5d72, 0x5d6c, 0x5d5e, 0x5d68, 0x5d67, 0x5d62, 0x5df0,
+ 0x5e4f, 0x5e4e, 0x5e4a, 0x5e4d, 0x5e4b, 0x5ec5, 0x5ecc, 0x5ec6,
+ 0x5ecb, 0x5ec7, 0x5f40, 0x5faf, 0x5fad, 0x60f7, 0x6149, 0x614a,
+ 0x612b, 0x6145, 0x6136, 0x6132, 0x612e, 0x6146, 0x612f, 0x614f,
+ 0x6129, 0x6140, 0x6220, 0x9168, 0x6223, 0x6225, 0x6224, 0x63c5,
+ 0x63f1, 0x63eb, 0x6410, 0x6412, 0x6409, 0x6420, 0x6424, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6433, 0x6443, 0x641f, 0x6415, 0x6418, 0x6439, 0x6437,
+ 0x6422, 0x6423, 0x640c, 0x6426, 0x6430, 0x6428, 0x6441, 0x6435,
+ 0x642f, 0x640a, 0x641a, 0x6440, 0x6425, 0x6427, 0x640b, 0x63e7,
+ 0x641b, 0x642e, 0x6421, 0x640e, 0x656f, 0x6592, 0x65d3, 0x6686,
+ 0x668c, 0x6695, 0x6690, 0x668b, 0x668a, 0x6699, 0x6694, 0x6678,
+ 0x6720, 0x6966, 0x695f, 0x6938, 0x694e, 0x6962, 0x6971, 0x693f,
+ 0x6945, 0x696a, 0x6939, 0x6942, 0x6957, 0x6959, 0x697a, 0x6948,
+ 0x6949, 0x6935, 0x696c, 0x6933, 0x693d, 0x6965, 0x68f0, 0x6978,
+ 0x6934, 0x6969, 0x6940, 0x696f, 0x6944, 0x6976, 0x6958, 0x6941,
+ 0x6974, 0x694c, 0x693b, 0x694b, 0x6937, 0x695c, 0x694f, 0x6951,
+ 0x6932, 0x6952, 0x692f, 0x697b, 0x693c, 0x6b46, 0x6b45, 0x6b43,
+ 0x6b42, 0x6b48, 0x6b41, 0x6b9b, 0x0000, 0x6bfb, 0x6bfc, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6bf9, 0x6bf7, 0x6bf8, 0x6e9b, 0x6ed6, 0x6ec8, 0x6e8f, 0x6ec0,
+ 0x6e9f, 0x6e93, 0x6e94, 0x6ea0, 0x6eb1, 0x6eb9, 0x6ec6, 0x6ed2,
+ 0x6ebd, 0x6ec1, 0x6e9e, 0x6ec9, 0x6eb7, 0x6eb0, 0x6ecd, 0x6ea6,
+ 0x6ecf, 0x6eb2, 0x6ebe, 0x6ec3, 0x6edc, 0x6ed8, 0x6e99, 0x6e92,
+ 0x6e8e, 0x6e8d, 0x6ea4, 0x6ea1, 0x6ebf, 0x6eb3, 0x6ed0, 0x6eca,
+ 0x6e97, 0x6eae, 0x6ea3, 0x7147, 0x7154, 0x7152, 0x7163, 0x7160,
+ 0x7141, 0x715d, 0x7162, 0x7172, 0x7178, 0x716a, 0x7161, 0x7142,
+ 0x7158, 0x7143, 0x714b, 0x7170, 0x715f, 0x7150, 0x7153, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7144, 0x714d, 0x715a, 0x724f, 0x728d, 0x728c, 0x7291,
+ 0x7290, 0x728e, 0x733c, 0x7342, 0x733b, 0x733a, 0x7340, 0x734a,
+ 0x7349, 0x7444, 0x744a, 0x744b, 0x7452, 0x7451, 0x7457, 0x7440,
+ 0x744f, 0x7450, 0x744e, 0x7442, 0x7446, 0x744d, 0x7454, 0x74e1,
+ 0x74ff, 0x74fe, 0x74fd, 0x751d, 0x7579, 0x7577, 0x6983, 0x75ef,
+ 0x760f, 0x7603, 0x75f7, 0x75fe, 0x75fc, 0x75f9, 0x75f8, 0x7610,
+ 0x75fb, 0x75f6, 0x75ed, 0x75f5, 0x75fd, 0x7699, 0x76b5, 0x76dd,
+ 0x7755, 0x775f, 0x7760, 0x7752, 0x7756, 0x775a, 0x7769, 0x7767,
+ 0x7754, 0x7759, 0x776d, 0x77e0, 0x7887, 0x789a, 0x7894, 0x788f,
+ 0x7884, 0x7895, 0x7885, 0x7886, 0x78a1, 0x7883, 0x7879, 0x7899,
+ 0x7880, 0x7896, 0x787b, 0x797c, 0x7982, 0x797d, 0x7979, 0x7a11,
+ 0x7a18, 0x7a19, 0x7a12, 0x7a17, 0x7a15, 0x7a22, 0x7a13, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7a1b, 0x7a10, 0x7aa3, 0x7aa2, 0x7a9e, 0x7aeb, 0x7b66, 0x7b64,
+ 0x7b6d, 0x7b74, 0x7b69, 0x7b72, 0x7b65, 0x7b73, 0x7b71, 0x7b70,
+ 0x7b61, 0x7b78, 0x7b76, 0x7b63, 0x7cb2, 0x7cb4, 0x7caf, 0x7d88,
+ 0x7d86, 0x7d80, 0x7d8d, 0x7d7f, 0x7d85, 0x7d7a, 0x7d8e, 0x7d7b,
+ 0x7d83, 0x7d7c, 0x7d8c, 0x7d94, 0x7d84, 0x7d7d, 0x7d92, 0x7f6d,
+ 0x7f6b, 0x7f67, 0x7f68, 0x7f6c, 0x7fa6, 0x7fa5, 0x7fa7, 0x7fdb,
+ 0x7fdc, 0x8021, 0x8164, 0x8160, 0x8177, 0x815c, 0x8169, 0x815b,
+ 0x8162, 0x8172, 0x6721, 0x815e, 0x8176, 0x8167, 0x816f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8144, 0x8161, 0x821d, 0x8249, 0x8244, 0x8240, 0x8242,
+ 0x8245, 0x84f1, 0x843f, 0x8456, 0x8476, 0x8479, 0x848f, 0x848d,
+ 0x8465, 0x8451, 0x8440, 0x8486, 0x8467, 0x8430, 0x844d, 0x847d,
+ 0x845a, 0x8459, 0x8474, 0x8473, 0x845d, 0x8507, 0x845e, 0x8437,
+ 0x843a, 0x8434, 0x847a, 0x8443, 0x8478, 0x8432, 0x8445, 0x8429,
+ 0x83d9, 0x844b, 0x842f, 0x8442, 0x842d, 0x845f, 0x8470, 0x8439,
+ 0x844e, 0x844c, 0x8452, 0x846f, 0x84c5, 0x848e, 0x843b, 0x8447,
+ 0x8436, 0x8433, 0x8468, 0x847e, 0x8444, 0x842b, 0x8460, 0x8454,
+ 0x846e, 0x8450, 0x870b, 0x8704, 0x86f7, 0x870c, 0x86fa, 0x86d6,
+ 0x86f5, 0x874d, 0x86f8, 0x870e, 0x8709, 0x8701, 0x86f6, 0x870d,
+ 0x8705, 0x88d6, 0x88cb, 0x88cd, 0x88ce, 0x88de, 0x88db, 0x88da,
+ 0x88cc, 0x88d0, 0x8985, 0x899b, 0x89df, 0x89e5, 0x89e4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x89e1, 0x89e0, 0x89e2, 0x89dc, 0x89e6, 0x8a76, 0x8a86, 0x8a7f,
+ 0x8a61, 0x8a3f, 0x8a77, 0x8a82, 0x8a84, 0x8a75, 0x8a83, 0x8a81,
+ 0x8a74, 0x8a7a, 0x8c3c, 0x8c4b, 0x8c4a, 0x8c65, 0x8c64, 0x8c66,
+ 0x8c86, 0x8c84, 0x8c85, 0x8ccc, 0x8d68, 0x8d69, 0x8d91, 0x8d8c,
+ 0x8d8e, 0x8d8f, 0x8d8d, 0x8d93, 0x8d94, 0x8d90, 0x8d92, 0x8df0,
+ 0x8de0, 0x8dec, 0x8df1, 0x8dee, 0x8dd0, 0x8de9, 0x8de3, 0x8de2,
+ 0x8de7, 0x8df2, 0x8deb, 0x8df4, 0x8f06, 0x8eff, 0x8f01, 0x8f00,
+ 0x8f05, 0x8f07, 0x8f08, 0x8f02, 0x8f0b, 0x9052, 0x903f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9044, 0x9049, 0x903d, 0x9110, 0x910d, 0x910f, 0x9111,
+ 0x9116, 0x9114, 0x910b, 0x910e, 0x916e, 0x916f, 0x9248, 0x9252,
+ 0x9230, 0x923a, 0x9266, 0x9233, 0x9265, 0x925e, 0x9283, 0x922e,
+ 0x924a, 0x9246, 0x926d, 0x926c, 0x924f, 0x9260, 0x9267, 0x926f,
+ 0x9236, 0x9261, 0x9270, 0x9231, 0x9254, 0x9263, 0x9250, 0x9272,
+ 0x924e, 0x9253, 0x924c, 0x9256, 0x9232, 0x959f, 0x959c, 0x959e,
+ 0x959b, 0x9692, 0x9693, 0x9691, 0x9697, 0x96ce, 0x96fa, 0x96fd,
+ 0x96f8, 0x96f5, 0x9773, 0x9777, 0x9778, 0x9772, 0x980f, 0x980d,
+ 0x980e, 0x98ac, 0x98f6, 0x98f9, 0x99af, 0x99b2, 0x99b0, 0x99b5,
+ 0x9aad, 0x9aab, 0x9b5b, 0x9cea, 0x9ced, 0x9ce7, 0x9e80, 0x9efd,
+ 0x50e6, 0x50d4, 0x50d7, 0x50e8, 0x50f3, 0x50db, 0x50ea, 0x50dd,
+ 0x50e4, 0x50d3, 0x50ec, 0x50f0, 0x50ef, 0x50e3, 0x50e0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x51d8, 0x5280, 0x5281, 0x52e9, 0x52eb, 0x5330, 0x53ac, 0x5627,
+ 0x5615, 0x560c, 0x5612, 0x55fc, 0x560f, 0x561c, 0x5601, 0x5613,
+ 0x5602, 0x55fa, 0x561d, 0x5604, 0x55ff, 0x55f9, 0x5889, 0x587c,
+ 0x5890, 0x5898, 0x5886, 0x5881, 0x587f, 0x5874, 0x588b, 0x587a,
+ 0x5887, 0x5891, 0x588e, 0x5876, 0x5882, 0x5888, 0x587b, 0x5894,
+ 0x588f, 0x58fe, 0x596b, 0x5adc, 0x5aee, 0x5ae5, 0x5ad5, 0x5aea,
+ 0x5ada, 0x5aed, 0x5aeb, 0x5af3, 0x5ae2, 0x5ae0, 0x5adb, 0x5aec,
+ 0x5ade, 0x5add, 0x5ad9, 0x5ae8, 0x5adf, 0x5b77, 0x5be0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5be3, 0x5c63, 0x5d82, 0x5d80, 0x5d7d, 0x5d86, 0x5d7a,
+ 0x5d81, 0x5d77, 0x5d8a, 0x5d89, 0x5d88, 0x5d7e, 0x5d7c, 0x5d8d,
+ 0x5d79, 0x5d7f, 0x5e58, 0x5e59, 0x5e53, 0x5ed8, 0x5ed1, 0x5ed7,
+ 0x5ece, 0x5edc, 0x5ed5, 0x5ed9, 0x5ed2, 0x5ed4, 0x5f44, 0x5f43,
+ 0x5f6f, 0x5fb6, 0x612c, 0x6128, 0x6141, 0x615e, 0x6171, 0x6173,
+ 0x6152, 0x6153, 0x6172, 0x616c, 0x6180, 0x6174, 0x6154, 0x617a,
+ 0x615b, 0x6165, 0x613b, 0x616a, 0x6161, 0x6156, 0x6229, 0x6227,
+ 0x622b, 0x642b, 0x644d, 0x645b, 0x645d, 0x6474, 0x6476, 0x6472,
+ 0x6473, 0x647d, 0x6475, 0x6466, 0x64a6, 0x644e, 0x6482, 0x645e,
+ 0x645c, 0x644b, 0x6453, 0x6460, 0x6450, 0x647f, 0x643f, 0x646c,
+ 0x646b, 0x6459, 0x6465, 0x6477, 0x6573, 0x65a0, 0x66a1, 0x66a0,
+ 0x669f, 0x6705, 0x6704, 0x6722, 0x69b1, 0x69b6, 0x69c9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x69a0, 0x69ce, 0x6996, 0x69b0, 0x69ac, 0x69bc, 0x6991, 0x6999,
+ 0x698e, 0x69a7, 0x698d, 0x69a9, 0x69be, 0x69af, 0x69bf, 0x69c4,
+ 0x69bd, 0x69a4, 0x69d4, 0x69b9, 0x69ca, 0x699a, 0x69cf, 0x69b3,
+ 0x6993, 0x69aa, 0x69a1, 0x699e, 0x69d9, 0x6997, 0x6990, 0x69c2,
+ 0x69b5, 0x69a5, 0x69c6, 0x6b4a, 0x6b4d, 0x6b4b, 0x6b9e, 0x6b9f,
+ 0x6ba0, 0x6bc3, 0x6bc4, 0x6bfe, 0x6ece, 0x6ef5, 0x6ef1, 0x6f03,
+ 0x6f25, 0x6ef8, 0x6f37, 0x6efb, 0x6f2e, 0x6f09, 0x6f4e, 0x6f19,
+ 0x6f1a, 0x6f27, 0x6f18, 0x6f3b, 0x6f12, 0x6eed, 0x6f0a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6f36, 0x6f73, 0x6ef9, 0x6eee, 0x6f2d, 0x6f40, 0x6f30,
+ 0x6f3c, 0x6f35, 0x6eeb, 0x6f07, 0x6f0e, 0x6f43, 0x6f05, 0x6efd,
+ 0x6ef6, 0x6f39, 0x6f1c, 0x6efc, 0x6f3a, 0x6f1f, 0x6f0d, 0x6f1e,
+ 0x6f08, 0x6f21, 0x7187, 0x7190, 0x7189, 0x7180, 0x7185, 0x7182,
+ 0x718f, 0x717b, 0x7186, 0x7181, 0x7197, 0x7244, 0x7253, 0x7297,
+ 0x7295, 0x7293, 0x7343, 0x734d, 0x7351, 0x734c, 0x7462, 0x7473,
+ 0x7471, 0x7475, 0x7472, 0x7467, 0x746e, 0x7500, 0x7502, 0x7503,
+ 0x757d, 0x7590, 0x7616, 0x7608, 0x760c, 0x7615, 0x7611, 0x760a,
+ 0x7614, 0x76b8, 0x7781, 0x777c, 0x7785, 0x7782, 0x776e, 0x7780,
+ 0x776f, 0x777e, 0x7783, 0x78b2, 0x78aa, 0x78b4, 0x78ad, 0x78a8,
+ 0x787e, 0x78ab, 0x789e, 0x78a5, 0x78a0, 0x78ac, 0x78a2, 0x78a4,
+ 0x7998, 0x798a, 0x798b, 0x7996, 0x7995, 0x7994, 0x7993, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7997, 0x7988, 0x7992, 0x7990, 0x7a2b, 0x7a4a, 0x7a30, 0x7a2f,
+ 0x7a28, 0x7a26, 0x7aa8, 0x7aab, 0x7aac, 0x7aee, 0x7b88, 0x7b9c,
+ 0x7b8a, 0x7b91, 0x7b90, 0x7b96, 0x7b8d, 0x7b8c, 0x7b9b, 0x7b8e,
+ 0x7b85, 0x7b98, 0x5284, 0x7b99, 0x7ba4, 0x7b82, 0x7cbb, 0x7cbf,
+ 0x7cbc, 0x7cba, 0x7da7, 0x7db7, 0x7dc2, 0x7da3, 0x7daa, 0x7dc1,
+ 0x7dc0, 0x7dc5, 0x7d9d, 0x7dce, 0x7dc4, 0x7dc6, 0x7dcb, 0x7dcc,
+ 0x7daf, 0x7db9, 0x7d96, 0x7dbc, 0x7d9f, 0x7da6, 0x7dae, 0x7da9,
+ 0x7da1, 0x7dc9, 0x7f73, 0x7fe2, 0x7fe3, 0x7fe5, 0x7fde, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8024, 0x805d, 0x805c, 0x8189, 0x8186, 0x8183, 0x8187,
+ 0x818d, 0x818c, 0x818b, 0x8215, 0x8497, 0x84a4, 0x84a1, 0x849f,
+ 0x84ba, 0x84ce, 0x84c2, 0x84ac, 0x84ae, 0x84ab, 0x84b9, 0x84b4,
+ 0x84c1, 0x84cd, 0x84aa, 0x849a, 0x84b1, 0x84d0, 0x849d, 0x84a7,
+ 0x84bb, 0x84a2, 0x8494, 0x84c7, 0x84cc, 0x849b, 0x84a9, 0x84af,
+ 0x84a8, 0x84d6, 0x8498, 0x84b6, 0x84cf, 0x84a0, 0x84d7, 0x84d4,
+ 0x84d2, 0x84db, 0x84b0, 0x8491, 0x8661, 0x8733, 0x8723, 0x8728,
+ 0x876b, 0x8740, 0x872e, 0x871e, 0x8721, 0x8719, 0x871b, 0x8743,
+ 0x872c, 0x8741, 0x873e, 0x8746, 0x8720, 0x8732, 0x872a, 0x872d,
+ 0x873c, 0x8712, 0x873a, 0x8731, 0x8735, 0x8742, 0x8726, 0x8727,
+ 0x8738, 0x8724, 0x871a, 0x8730, 0x8711, 0x88f7, 0x88e7, 0x88f1,
+ 0x88f2, 0x88fa, 0x88fe, 0x88ee, 0x88fc, 0x88f6, 0x88fb, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x88f0, 0x88ec, 0x88eb, 0x899d, 0x89a1, 0x899f, 0x899e, 0x89e9,
+ 0x89eb, 0x89e8, 0x8aab, 0x8a99, 0x8a8b, 0x8a92, 0x8a8f, 0x8a96,
+ 0x8c3d, 0x8c68, 0x8c69, 0x8cd5, 0x8ccf, 0x8cd7, 0x8d96, 0x8e09,
+ 0x8e02, 0x8dff, 0x8e0d, 0x8dfd, 0x8e0a, 0x8e03, 0x8e07, 0x8e06,
+ 0x8e05, 0x8dfe, 0x8e00, 0x8e04, 0x8f10, 0x8f11, 0x8f0e, 0x8f0d,
+ 0x9123, 0x911c, 0x9120, 0x9122, 0x911f, 0x911d, 0x911a, 0x9124,
+ 0x9121, 0x911b, 0x917a, 0x9172, 0x9179, 0x9173, 0x92a5, 0x92a4,
+ 0x9276, 0x929b, 0x927a, 0x92a0, 0x9294, 0x92aa, 0x928d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x92a6, 0x929a, 0x92ab, 0x9279, 0x9297, 0x927f, 0x92a3,
+ 0x92ee, 0x928e, 0x9282, 0x9295, 0x92a2, 0x927d, 0x9288, 0x92a1,
+ 0x928a, 0x9286, 0x928c, 0x9299, 0x92a7, 0x927e, 0x9287, 0x92a9,
+ 0x929d, 0x928b, 0x922d, 0x969e, 0x96a1, 0x96ff, 0x9758, 0x977d,
+ 0x977a, 0x977e, 0x9783, 0x9780, 0x9782, 0x977b, 0x9784, 0x9781,
+ 0x977f, 0x97ce, 0x97cd, 0x9816, 0x98ad, 0x98ae, 0x9902, 0x9900,
+ 0x9907, 0x999d, 0x999c, 0x99c3, 0x99b9, 0x99bb, 0x99ba, 0x99c2,
+ 0x99bd, 0x99c7, 0x9ab1, 0x9ae3, 0x9ae7, 0x9b3e, 0x9b3f, 0x9b60,
+ 0x9b61, 0x9b5f, 0x9cf1, 0x9cf2, 0x9cf5, 0x9ea7, 0x50ff, 0x5103,
+ 0x5130, 0x50f8, 0x5106, 0x5107, 0x50f6, 0x50fe, 0x510b, 0x510c,
+ 0x50fd, 0x510a, 0x528b, 0x528c, 0x52f1, 0x52ef, 0x5648, 0x5642,
+ 0x564c, 0x5635, 0x5641, 0x564a, 0x5649, 0x5646, 0x5658, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x565a, 0x5640, 0x5633, 0x563d, 0x562c, 0x563e, 0x5638, 0x562a,
+ 0x563a, 0x571a, 0x58ab, 0x589d, 0x58b1, 0x58a0, 0x58a3, 0x58af,
+ 0x58ac, 0x58a5, 0x58a1, 0x58ff, 0x5aff, 0x5af4, 0x5afd, 0x5af7,
+ 0x5af6, 0x5b03, 0x5af8, 0x5b02, 0x5af9, 0x5b01, 0x5b07, 0x5b05,
+ 0x5b0f, 0x5c67, 0x5d99, 0x5d97, 0x5d9f, 0x5d92, 0x5da2, 0x5d93,
+ 0x5d95, 0x5da0, 0x5d9c, 0x5da1, 0x5d9a, 0x5d9e, 0x5e69, 0x5e5d,
+ 0x5e60, 0x5e5c, 0x7df3, 0x5edb, 0x5ede, 0x5ee1, 0x5f49, 0x5fb2,
+ 0x618b, 0x6183, 0x6179, 0x61b1, 0x61b0, 0x61a2, 0x6189, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x619b, 0x6193, 0x61af, 0x61ad, 0x619f, 0x6192, 0x61aa,
+ 0x61a1, 0x618d, 0x6166, 0x61b3, 0x622d, 0x646e, 0x6470, 0x6496,
+ 0x64a0, 0x6485, 0x6497, 0x649c, 0x648f, 0x648b, 0x648a, 0x648c,
+ 0x64a3, 0x649f, 0x6468, 0x64b1, 0x6498, 0x6576, 0x657a, 0x6579,
+ 0x657b, 0x65b2, 0x65b3, 0x66b5, 0x66b0, 0x66a9, 0x66b2, 0x66b7,
+ 0x66aa, 0x66af, 0x6a00, 0x6a06, 0x6a17, 0x69e5, 0x69f8, 0x6a15,
+ 0x69f1, 0x69e4, 0x6a20, 0x69ff, 0x69ec, 0x69e2, 0x6a1b, 0x6a1d,
+ 0x69fe, 0x6a27, 0x69f2, 0x69ee, 0x6a14, 0x69f7, 0x69e7, 0x6a40,
+ 0x6a08, 0x69e6, 0x69fb, 0x6a0d, 0x69fc, 0x69eb, 0x6a09, 0x6a04,
+ 0x6a18, 0x6a25, 0x6a0f, 0x69f6, 0x6a26, 0x6a07, 0x69f4, 0x6a16,
+ 0x6b51, 0x6ba5, 0x6ba3, 0x6ba2, 0x6ba6, 0x6c01, 0x6c00, 0x6bff,
+ 0x6c02, 0x6f41, 0x6f26, 0x6f7e, 0x6f87, 0x6fc6, 0x6f92, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6f8d, 0x6f89, 0x6f8c, 0x6f62, 0x6f4f, 0x6f85, 0x6f5a, 0x6f96,
+ 0x6f76, 0x6f6c, 0x6f82, 0x6f55, 0x6f72, 0x6f52, 0x6f50, 0x6f57,
+ 0x6f94, 0x6f93, 0x6f5d, 0x6f00, 0x6f61, 0x6f6b, 0x6f7d, 0x6f67,
+ 0x6f90, 0x6f53, 0x6f8b, 0x6f69, 0x6f7f, 0x6f95, 0x6f63, 0x6f77,
+ 0x6f6a, 0x6f7b, 0x71b2, 0x71af, 0x719b, 0x71b0, 0x71a0, 0x719a,
+ 0x71a9, 0x71b5, 0x719d, 0x71a5, 0x719e, 0x71a4, 0x71a1, 0x71aa,
+ 0x719c, 0x71a7, 0x71b3, 0x7298, 0x729a, 0x7358, 0x7352, 0x735e,
+ 0x735f, 0x7360, 0x735d, 0x735b, 0x7361, 0x735a, 0x7359, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7362, 0x7487, 0x7489, 0x748a, 0x7486, 0x7481, 0x747d,
+ 0x7485, 0x7488, 0x747c, 0x7479, 0x7508, 0x7507, 0x757e, 0x7625,
+ 0x761e, 0x7619, 0x761d, 0x761c, 0x7623, 0x761a, 0x7628, 0x761b,
+ 0x769c, 0x769d, 0x769e, 0x769b, 0x778d, 0x778f, 0x7789, 0x7788,
+ 0x78cd, 0x78bb, 0x78cf, 0x78cc, 0x78d1, 0x78ce, 0x78d4, 0x78c8,
+ 0x78c3, 0x78c4, 0x78c9, 0x799a, 0x79a1, 0x79a0, 0x799c, 0x79a2,
+ 0x799b, 0x6b76, 0x7a39, 0x7ab2, 0x7ab4, 0x7ab3, 0x7bb7, 0x7bcb,
+ 0x7bbe, 0x7bac, 0x7bce, 0x7baf, 0x7bb9, 0x7bca, 0x7bb5, 0x7cc5,
+ 0x7cc8, 0x7ccc, 0x7ccb, 0x7df7, 0x7ddb, 0x7dea, 0x7de7, 0x7dd7,
+ 0x7de1, 0x7e03, 0x7dfa, 0x7de6, 0x7df6, 0x7df1, 0x7df0, 0x7dee,
+ 0x7ddf, 0x7f76, 0x7fac, 0x7fb0, 0x7fad, 0x7fed, 0x7feb, 0x7fea,
+ 0x7fec, 0x7fe6, 0x7fe8, 0x8064, 0x8067, 0x81a3, 0x819f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x819e, 0x8195, 0x81a2, 0x8199, 0x8197, 0x8216, 0x824f, 0x8253,
+ 0x8252, 0x8250, 0x824e, 0x8251, 0x8524, 0x853b, 0x850f, 0x8500,
+ 0x8529, 0x850e, 0x8509, 0x850d, 0x851f, 0x850a, 0x8527, 0x851c,
+ 0x84fb, 0x852b, 0x84fa, 0x8508, 0x850c, 0x84f4, 0x852a, 0x84f2,
+ 0x8515, 0x84f7, 0x84eb, 0x84f3, 0x84fc, 0x8512, 0x84ea, 0x84e9,
+ 0x8516, 0x84fe, 0x8528, 0x851d, 0x852e, 0x8502, 0x84fd, 0x851e,
+ 0x84f6, 0x8531, 0x8526, 0x84e7, 0x84e8, 0x84f0, 0x84ef, 0x84f9,
+ 0x8518, 0x8520, 0x8530, 0x850b, 0x8519, 0x852f, 0x8662, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8756, 0x8763, 0x8764, 0x8777, 0x87e1, 0x8773, 0x8758,
+ 0x8754, 0x875b, 0x8752, 0x8761, 0x875a, 0x8751, 0x875e, 0x876d,
+ 0x876a, 0x8750, 0x874e, 0x875f, 0x875d, 0x876f, 0x876c, 0x877a,
+ 0x876e, 0x875c, 0x8765, 0x874f, 0x877b, 0x8775, 0x8762, 0x8767,
+ 0x8769, 0x885a, 0x8905, 0x890c, 0x8914, 0x890b, 0x8917, 0x8918,
+ 0x8919, 0x8906, 0x8916, 0x8911, 0x890e, 0x8909, 0x89a2, 0x89a4,
+ 0x89a3, 0x89ed, 0x89f0, 0x89ec, 0x8acf, 0x8ac6, 0x8ab8, 0x8ad3,
+ 0x8ad1, 0x8ad4, 0x8ad5, 0x8abb, 0x8ad7, 0x8abe, 0x8ac0, 0x8ac5,
+ 0x8ad8, 0x8ac3, 0x8aba, 0x8abd, 0x8ad9, 0x8c3e, 0x8c4d, 0x8c8f,
+ 0x8ce5, 0x8cdf, 0x8cd9, 0x8ce8, 0x8cda, 0x8cdd, 0x8ce7, 0x8da0,
+ 0x8d9c, 0x8da1, 0x8d9b, 0x8e20, 0x8e23, 0x8e25, 0x8e24, 0x8e2e,
+ 0x8e15, 0x8e1b, 0x8e16, 0x8e11, 0x8e19, 0x8e26, 0x8e27, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8e14, 0x8e12, 0x8e18, 0x8e13, 0x8e1c, 0x8e17, 0x8e1a, 0x8f2c,
+ 0x8f24, 0x8f18, 0x8f1a, 0x8f20, 0x8f23, 0x8f16, 0x8f17, 0x9073,
+ 0x9070, 0x906f, 0x9067, 0x906b, 0x912f, 0x912b, 0x9129, 0x912a,
+ 0x9132, 0x9126, 0x912e, 0x9185, 0x9186, 0x918a, 0x9181, 0x9182,
+ 0x9184, 0x9180, 0x92d0, 0x92c3, 0x92c4, 0x92c0, 0x92d9, 0x92b6,
+ 0x92cf, 0x92f1, 0x92df, 0x92d8, 0x92e9, 0x92d7, 0x92dd, 0x92cc,
+ 0x92ef, 0x92c2, 0x92e8, 0x92ca, 0x92c8, 0x92ce, 0x92e6, 0x92cd,
+ 0x92d5, 0x92c9, 0x92e0, 0x92de, 0x92e7, 0x92d1, 0x92d3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x92b5, 0x92e1, 0x92c6, 0x92b4, 0x957c, 0x95ac, 0x95ab,
+ 0x95ae, 0x95b0, 0x96a4, 0x96a2, 0x96d3, 0x9705, 0x9708, 0x9702,
+ 0x975a, 0x978a, 0x978e, 0x9788, 0x97d0, 0x97cf, 0x981e, 0x981d,
+ 0x9826, 0x9829, 0x9828, 0x9820, 0x981b, 0x9827, 0x98b2, 0x9908,
+ 0x98fa, 0x9911, 0x9914, 0x9916, 0x9917, 0x9915, 0x99dc, 0x99cd,
+ 0x99cf, 0x99d3, 0x99d4, 0x99ce, 0x99c9, 0x99d6, 0x99d8, 0x99cb,
+ 0x99d7, 0x99cc, 0x9ab3, 0x9aec, 0x9aeb, 0x9af3, 0x9af2, 0x9af1,
+ 0x9b46, 0x9b43, 0x9b67, 0x9b74, 0x9b71, 0x9b66, 0x9b76, 0x9b75,
+ 0x9b70, 0x9b68, 0x9b64, 0x9b6c, 0x9cfc, 0x9cfa, 0x9cfd, 0x9cff,
+ 0x9cf7, 0x9d07, 0x9d00, 0x9cf9, 0x9cfb, 0x9d08, 0x9d05, 0x9d04,
+ 0x9e83, 0x9ed3, 0x9f0f, 0x9f10, 0x511c, 0x5113, 0x5117, 0x511a,
+ 0x5111, 0x51de, 0x5334, 0x53e1, 0x5670, 0x5660, 0x566e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5673, 0x5666, 0x5663, 0x566d, 0x5672, 0x565e, 0x5677, 0x571c,
+ 0x571b, 0x58c8, 0x58bd, 0x58c9, 0x58bf, 0x58ba, 0x58c2, 0x58bc,
+ 0x58c6, 0x5b17, 0x5b19, 0x5b1b, 0x5b21, 0x5b14, 0x5b13, 0x5b10,
+ 0x5b16, 0x5b28, 0x5b1a, 0x5b20, 0x5b1e, 0x5bef, 0x5dac, 0x5db1,
+ 0x5da9, 0x5da7, 0x5db5, 0x5db0, 0x5dae, 0x5daa, 0x5da8, 0x5db2,
+ 0x5dad, 0x5daf, 0x5db4, 0x5e67, 0x5e68, 0x5e66, 0x5e6f, 0x5ee9,
+ 0x5ee7, 0x5ee6, 0x5ee8, 0x5ee5, 0x5f4b, 0x5fbc, 0x619d, 0x61a8,
+ 0x6196, 0x61c5, 0x61b4, 0x61c6, 0x61c1, 0x61cc, 0x61ba, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x61bf, 0x61b8, 0x618c, 0x64d7, 0x64d6, 0x64d0, 0x64cf,
+ 0x64c9, 0x64bd, 0x6489, 0x64c3, 0x64db, 0x64f3, 0x64d9, 0x6533,
+ 0x657f, 0x657c, 0x65a2, 0x66c8, 0x66be, 0x66c0, 0x66ca, 0x66cb,
+ 0x66cf, 0x66bd, 0x66bb, 0x66ba, 0x66cc, 0x6723, 0x6a34, 0x6a66,
+ 0x6a49, 0x6a67, 0x6a32, 0x6a68, 0x6a3e, 0x6a5d, 0x6a6d, 0x6a76,
+ 0x6a5b, 0x6a51, 0x6a28, 0x6a5a, 0x6a3b, 0x6a3f, 0x6a41, 0x6a6a,
+ 0x6a64, 0x6a50, 0x6a4f, 0x6a54, 0x6a6f, 0x6a69, 0x6a60, 0x6a3c,
+ 0x6a5e, 0x6a56, 0x6a55, 0x6a4d, 0x6a4e, 0x6a46, 0x6b55, 0x6b54,
+ 0x6b56, 0x6ba7, 0x6baa, 0x6bab, 0x6bc8, 0x6bc7, 0x6c04, 0x6c03,
+ 0x6c06, 0x6fad, 0x6fcb, 0x6fa3, 0x6fc7, 0x6fbc, 0x6fce, 0x6fc8,
+ 0x6f5e, 0x6fc4, 0x6fbd, 0x6f9e, 0x6fca, 0x6fa8, 0x7004, 0x6fa5,
+ 0x6fae, 0x6fba, 0x6fac, 0x6faa, 0x6fcf, 0x6fbf, 0x6fb8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6fa2, 0x6fc9, 0x6fab, 0x6fcd, 0x6faf, 0x6fb2, 0x6fb0, 0x71c5,
+ 0x71c2, 0x71bf, 0x71b8, 0x71d6, 0x71c0, 0x71c1, 0x71cb, 0x71d4,
+ 0x71ca, 0x71c7, 0x71cf, 0x71bd, 0x71d8, 0x71bc, 0x71c6, 0x71da,
+ 0x71db, 0x729d, 0x729e, 0x7369, 0x7366, 0x7367, 0x736c, 0x7365,
+ 0x736b, 0x736a, 0x747f, 0x749a, 0x74a0, 0x7494, 0x7492, 0x7495,
+ 0x74a1, 0x750b, 0x7580, 0x762f, 0x762d, 0x7631, 0x763d, 0x7633,
+ 0x763c, 0x7635, 0x7632, 0x7630, 0x76bb, 0x76e6, 0x779a, 0x779d,
+ 0x77a1, 0x779c, 0x779b, 0x77a2, 0x77a3, 0x7795, 0x7799, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7797, 0x78dd, 0x78e9, 0x78e5, 0x78ea, 0x78de, 0x78e3,
+ 0x78db, 0x78e1, 0x78e2, 0x78ed, 0x78df, 0x78e0, 0x79a4, 0x7a44,
+ 0x7a48, 0x7a47, 0x7ab6, 0x7ab8, 0x7ab5, 0x7ab1, 0x7ab7, 0x7bde,
+ 0x7be3, 0x7be7, 0x7bdd, 0x7bd5, 0x7be5, 0x7bda, 0x7be8, 0x7bf9,
+ 0x7bd4, 0x7bea, 0x7be2, 0x7bdc, 0x7beb, 0x7bd8, 0x7bdf, 0x7cd2,
+ 0x7cd4, 0x7cd7, 0x7cd0, 0x7cd1, 0x7e12, 0x7e21, 0x7e17, 0x7e0c,
+ 0x7e1f, 0x7e20, 0x7e13, 0x7e0e, 0x7e1c, 0x7e15, 0x7e1a, 0x7e22,
+ 0x7e0b, 0x7e0f, 0x7e16, 0x7e0d, 0x7e14, 0x7e25, 0x7e24, 0x7f43,
+ 0x7f7b, 0x7f7c, 0x7f7a, 0x7fb1, 0x7fef, 0x802a, 0x8029, 0x806c,
+ 0x81b1, 0x81a6, 0x81ae, 0x81b9, 0x81b5, 0x81ab, 0x81b0, 0x81ac,
+ 0x81b4, 0x81b2, 0x81b7, 0x81a7, 0x81f2, 0x8255, 0x8256, 0x8257,
+ 0x8556, 0x8545, 0x856b, 0x854d, 0x8553, 0x8561, 0x8558, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8540, 0x8546, 0x8564, 0x8541, 0x8562, 0x8544, 0x8551, 0x8547,
+ 0x8563, 0x853e, 0x855b, 0x8571, 0x854e, 0x856e, 0x8575, 0x8555,
+ 0x8567, 0x8560, 0x858c, 0x8566, 0x855d, 0x8554, 0x8565, 0x856c,
+ 0x8663, 0x8665, 0x8664, 0x879b, 0x878f, 0x8797, 0x8793, 0x8792,
+ 0x8788, 0x8781, 0x8796, 0x8798, 0x8779, 0x8787, 0x87a3, 0x8785,
+ 0x8790, 0x8791, 0x879d, 0x8784, 0x8794, 0x879c, 0x879a, 0x8789,
+ 0x891e, 0x8926, 0x8930, 0x892d, 0x892e, 0x8927, 0x8931, 0x8922,
+ 0x8929, 0x8923, 0x892f, 0x892c, 0x891f, 0x89f1, 0x8ae0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8ae2, 0x8af2, 0x8af4, 0x8af5, 0x8add, 0x8b14, 0x8ae4,
+ 0x8adf, 0x8af0, 0x8ac8, 0x8ade, 0x8ae1, 0x8ae8, 0x8aff, 0x8aef,
+ 0x8afb, 0x8c91, 0x8c92, 0x8c90, 0x8cf5, 0x8cee, 0x8cf1, 0x8cf0,
+ 0x8cf3, 0x8d6c, 0x8d6e, 0x8da5, 0x8da7, 0x8e33, 0x8e3e, 0x8e38,
+ 0x8e40, 0x8e45, 0x8e36, 0x8e3c, 0x8e3d, 0x8e41, 0x8e30, 0x8e3f,
+ 0x8ebd, 0x8f36, 0x8f2e, 0x8f35, 0x8f32, 0x8f39, 0x8f37, 0x8f34,
+ 0x9076, 0x9079, 0x907b, 0x9086, 0x90fa, 0x9133, 0x9135, 0x9136,
+ 0x9193, 0x9190, 0x9191, 0x918d, 0x918f, 0x9327, 0x931e, 0x9308,
+ 0x931f, 0x9306, 0x930f, 0x937a, 0x9338, 0x933c, 0x931b, 0x9323,
+ 0x9312, 0x9301, 0x9346, 0x932d, 0x930e, 0x930d, 0x92cb, 0x931d,
+ 0x92fa, 0x9325, 0x9313, 0x92f9, 0x92f7, 0x9334, 0x9302, 0x9324,
+ 0x92ff, 0x9329, 0x9339, 0x9335, 0x932a, 0x9314, 0x930c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x930b, 0x92fe, 0x9309, 0x9300, 0x92fb, 0x9316, 0x95bc, 0x95cd,
+ 0x95be, 0x95b9, 0x95ba, 0x95b6, 0x95bf, 0x95b5, 0x95bd, 0x96a9,
+ 0x96d4, 0x970b, 0x9712, 0x9710, 0x9799, 0x9797, 0x9794, 0x97f0,
+ 0x97f8, 0x9835, 0x982f, 0x9832, 0x9924, 0x991f, 0x9927, 0x9929,
+ 0x999e, 0x99ee, 0x99ec, 0x99e5, 0x99e4, 0x99f0, 0x99e3, 0x99ea,
+ 0x99e9, 0x99e7, 0x9ab9, 0x9abf, 0x9ab4, 0x9abb, 0x9af6, 0x9afa,
+ 0x9af9, 0x9af7, 0x9b33, 0x9b80, 0x9b85, 0x9b87, 0x9b7c, 0x9b7e,
+ 0x9b7b, 0x9b82, 0x9b93, 0x9b92, 0x9b90, 0x9b7a, 0x9b95, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9b7d, 0x9b88, 0x9d25, 0x9d17, 0x9d20, 0x9d1e, 0x9d14,
+ 0x9d29, 0x9d1d, 0x9d18, 0x9d22, 0x9d10, 0x9d19, 0x9d1f, 0x9e88,
+ 0x9e86, 0x9e87, 0x9eae, 0x9ead, 0x9ed5, 0x9ed6, 0x9efa, 0x9f12,
+ 0x9f3d, 0x5126, 0x5125, 0x5122, 0x5124, 0x5120, 0x5129, 0x52f4,
+ 0x5693, 0x568c, 0x568d, 0x5686, 0x5684, 0x5683, 0x567e, 0x5682,
+ 0x567f, 0x5681, 0x58d6, 0x58d4, 0x58cf, 0x58d2, 0x5b2d, 0x5b25,
+ 0x5b32, 0x5b23, 0x5b2c, 0x5b27, 0x5b26, 0x5b2f, 0x5b2e, 0x5b7b,
+ 0x5bf1, 0x5bf2, 0x5db7, 0x5e6c, 0x5e6a, 0x5fbe, 0x5fbb, 0x61c3,
+ 0x61b5, 0x61bc, 0x61e7, 0x61e0, 0x61e5, 0x61e4, 0x61e8, 0x61de,
+ 0x64ef, 0x64e9, 0x64e3, 0x64eb, 0x64e4, 0x64e8, 0x6581, 0x6580,
+ 0x65b6, 0x65da, 0x66d2, 0x6a8d, 0x6a96, 0x6a81, 0x6aa5, 0x6a89,
+ 0x6a9f, 0x6a9b, 0x6aa1, 0x6a9e, 0x6a87, 0x6a93, 0x6a8e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6a95, 0x6a83, 0x6aa8, 0x6aa4, 0x6a91, 0x6a7f, 0x6aa6, 0x6a9a,
+ 0x6a85, 0x6a8c, 0x6a92, 0x6b5b, 0x6bad, 0x6c09, 0x6fcc, 0x6fa9,
+ 0x6ff4, 0x6fd4, 0x6fe3, 0x6fdc, 0x6fed, 0x6fe7, 0x6fe6, 0x6fde,
+ 0x6ff2, 0x6fdd, 0x6fe2, 0x6fe8, 0x71e1, 0x71f1, 0x71e8, 0x71f2,
+ 0x71e4, 0x71f0, 0x71e2, 0x7373, 0x736e, 0x736f, 0x7497, 0x74b2,
+ 0x74ab, 0x7490, 0x74aa, 0x74ad, 0x74b1, 0x74a5, 0x74af, 0x7510,
+ 0x7511, 0x7512, 0x750f, 0x7584, 0x7643, 0x7648, 0x7649, 0x7647,
+ 0x76a4, 0x76e9, 0x77b5, 0x77ab, 0x77b2, 0x77b7, 0x77b6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x77b4, 0x77b1, 0x77a8, 0x77f0, 0x78f3, 0x78fd, 0x7902,
+ 0x78fb, 0x78fc, 0x78f2, 0x7905, 0x78f9, 0x78fe, 0x7904, 0x79ab,
+ 0x79a8, 0x7a5c, 0x7a5b, 0x7a56, 0x7a58, 0x7a54, 0x7a5a, 0x7abe,
+ 0x7ac0, 0x7ac1, 0x7c05, 0x7c0f, 0x7bf2, 0x7c00, 0x7bff, 0x7bfb,
+ 0x7c0e, 0x7bf4, 0x7c0b, 0x7bf3, 0x7c02, 0x7c09, 0x7c03, 0x7c01,
+ 0x7bf8, 0x7bfd, 0x7c06, 0x7bf0, 0x7bf1, 0x7c10, 0x7c0a, 0x7ce8,
+ 0x7e2d, 0x7e3c, 0x7e42, 0x7e33, 0x9848, 0x7e38, 0x7e2a, 0x7e49,
+ 0x7e40, 0x7e47, 0x7e29, 0x7e4c, 0x7e30, 0x7e3b, 0x7e36, 0x7e44,
+ 0x7e3a, 0x7f45, 0x7f7f, 0x7f7e, 0x7f7d, 0x7ff4, 0x7ff2, 0x802c,
+ 0x81bb, 0x81c4, 0x81cc, 0x81ca, 0x81c5, 0x81c7, 0x81bc, 0x81e9,
+ 0x825b, 0x825a, 0x825c, 0x8583, 0x8580, 0x858f, 0x85a7, 0x8595,
+ 0x85a0, 0x858b, 0x85a3, 0x857b, 0x85a4, 0x859a, 0x859e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8577, 0x857c, 0x8589, 0x85a1, 0x857a, 0x8578, 0x8557, 0x858e,
+ 0x8596, 0x8586, 0x858d, 0x8599, 0x859d, 0x8581, 0x85a2, 0x8582,
+ 0x8588, 0x8585, 0x8579, 0x8576, 0x8598, 0x8590, 0x859f, 0x8668,
+ 0x87be, 0x87aa, 0x87ad, 0x87c5, 0x87b0, 0x87ac, 0x87b9, 0x87b5,
+ 0x87bc, 0x87ae, 0x87c9, 0x87c3, 0x87c2, 0x87cc, 0x87b7, 0x87af,
+ 0x87c4, 0x87ca, 0x87b4, 0x87b6, 0x87bf, 0x87b8, 0x87bd, 0x87de,
+ 0x87b2, 0x8935, 0x8933, 0x893c, 0x893e, 0x8941, 0x8952, 0x8937,
+ 0x8942, 0x89ad, 0x89af, 0x89ae, 0x89f2, 0x89f3, 0x8b1e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8b18, 0x8b16, 0x8b11, 0x8b05, 0x8b0b, 0x8b22, 0x8b0f,
+ 0x8b12, 0x8b15, 0x8b07, 0x8b0d, 0x8b08, 0x8b06, 0x8b1c, 0x8b13,
+ 0x8b1a, 0x8c4f, 0x8c70, 0x8c72, 0x8c71, 0x8c6f, 0x8c95, 0x8c94,
+ 0x8cf9, 0x8d6f, 0x8e4e, 0x8e4d, 0x8e53, 0x8e50, 0x8e4c, 0x8e47,
+ 0x8f43, 0x8f40, 0x9085, 0x907e, 0x9138, 0x919a, 0x91a2, 0x919b,
+ 0x9199, 0x919f, 0x91a1, 0x919d, 0x91a0, 0x93a1, 0x9383, 0x93af,
+ 0x9364, 0x9356, 0x9347, 0x937c, 0x9358, 0x935c, 0x9376, 0x9349,
+ 0x9350, 0x9351, 0x9360, 0x936d, 0x938f, 0x934c, 0x936a, 0x9379,
+ 0x9357, 0x9355, 0x9352, 0x934f, 0x9371, 0x9377, 0x937b, 0x9361,
+ 0x935e, 0x9363, 0x9367, 0x9380, 0x934e, 0x9359, 0x95c7, 0x95c0,
+ 0x95c9, 0x95c3, 0x95c5, 0x95b7, 0x96ae, 0x96b0, 0x96ac, 0x9720,
+ 0x971f, 0x9718, 0x971d, 0x9719, 0x979a, 0x97a1, 0x979c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x979e, 0x979d, 0x97d5, 0x97d4, 0x97f1, 0x9841, 0x9844, 0x984a,
+ 0x9849, 0x9845, 0x9843, 0x9925, 0x992b, 0x992c, 0x992a, 0x9933,
+ 0x9932, 0x992f, 0x992d, 0x9931, 0x9930, 0x9998, 0x99a3, 0x99a1,
+ 0x9a02, 0x99fa, 0x99f4, 0x99f7, 0x99f9, 0x99f8, 0x99f6, 0x99fb,
+ 0x99fd, 0x99fe, 0x99fc, 0x9a03, 0x9abe, 0x9afe, 0x9afd, 0x9b01,
+ 0x9afc, 0x9b48, 0x9b9a, 0x9ba8, 0x9b9e, 0x9b9b, 0x9ba6, 0x9ba1,
+ 0x9ba5, 0x9ba4, 0x9b86, 0x9ba2, 0x9ba0, 0x9baf, 0x9d33, 0x9d41,
+ 0x9d67, 0x9d36, 0x9d2e, 0x9d2f, 0x9d31, 0x9d38, 0x9d30, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9d45, 0x9d42, 0x9d43, 0x9d3e, 0x9d37, 0x9d40, 0x9d3d,
+ 0x7ff5, 0x9d2d, 0x9e8a, 0x9e89, 0x9e8d, 0x9eb0, 0x9ec8, 0x9eda,
+ 0x9efb, 0x9eff, 0x9f24, 0x9f23, 0x9f22, 0x9f54, 0x9fa0, 0x5131,
+ 0x512d, 0x512e, 0x5698, 0x569c, 0x5697, 0x569a, 0x569d, 0x5699,
+ 0x5970, 0x5b3c, 0x5c69, 0x5c6a, 0x5dc0, 0x5e6d, 0x5e6e, 0x61d8,
+ 0x61df, 0x61ed, 0x61ee, 0x61f1, 0x61ea, 0x61f0, 0x61eb, 0x61d6,
+ 0x61e9, 0x64ff, 0x6504, 0x64fd, 0x64f8, 0x6501, 0x6503, 0x64fc,
+ 0x6594, 0x65db, 0x66da, 0x66db, 0x66d8, 0x6ac5, 0x6ab9, 0x6abd,
+ 0x6ae1, 0x6ac6, 0x6aba, 0x6ab6, 0x6ab7, 0x6ac7, 0x6ab4, 0x6aad,
+ 0x6b5e, 0x6bc9, 0x6c0b, 0x7007, 0x700c, 0x700d, 0x7001, 0x7005,
+ 0x7014, 0x700e, 0x6fff, 0x7000, 0x6ffb, 0x7026, 0x6ffc, 0x6ff7,
+ 0x700a, 0x7201, 0x71ff, 0x71f9, 0x7203, 0x71fd, 0x7376, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x74b8, 0x74c0, 0x74b5, 0x74c1, 0x74be, 0x74b6, 0x74bb, 0x74c2,
+ 0x7514, 0x7513, 0x765c, 0x7664, 0x7659, 0x7650, 0x7653, 0x7657,
+ 0x765a, 0x76a6, 0x76bd, 0x76ec, 0x77c2, 0x77ba, 0x78ff, 0x790c,
+ 0x7913, 0x7914, 0x7909, 0x7910, 0x7912, 0x7911, 0x79ad, 0x79ac,
+ 0x7a5f, 0x7c1c, 0x7c29, 0x7c19, 0x7c20, 0x7c1f, 0x7c2d, 0x7c1d,
+ 0x7c26, 0x7c28, 0x7c22, 0x7c25, 0x7c30, 0x7e5c, 0x7e50, 0x7e56,
+ 0x7e63, 0x7e58, 0x7e62, 0x7e5f, 0x7e51, 0x7e60, 0x7e57, 0x7e53,
+ 0x7fb5, 0x7fb3, 0x7ff7, 0x7ff8, 0x8075, 0x81d1, 0x81d2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x81d0, 0x825f, 0x825e, 0x85b4, 0x85c6, 0x85c0, 0x85c3,
+ 0x85c2, 0x85b3, 0x85b5, 0x85bd, 0x85c7, 0x85c4, 0x85bf, 0x85cb,
+ 0x85ce, 0x85c8, 0x85c5, 0x85b1, 0x85b6, 0x85d2, 0x8624, 0x85b8,
+ 0x85b7, 0x85be, 0x8669, 0x87e7, 0x87e6, 0x87e2, 0x87db, 0x87eb,
+ 0x87ea, 0x87e5, 0x87df, 0x87f3, 0x87e4, 0x87d4, 0x87dc, 0x87d3,
+ 0x87ed, 0x87d8, 0x87e3, 0x87a4, 0x87d7, 0x87d9, 0x8801, 0x87f4,
+ 0x87e8, 0x87dd, 0x8953, 0x894b, 0x894f, 0x894c, 0x8946, 0x8950,
+ 0x8951, 0x8949, 0x8b2a, 0x8b27, 0x8b23, 0x8b33, 0x8b30, 0x8b35,
+ 0x8b47, 0x8b2f, 0x8b3c, 0x8b3e, 0x8b31, 0x8b25, 0x8b37, 0x8b26,
+ 0x8b36, 0x8b2e, 0x8b24, 0x8b3b, 0x8b3d, 0x8b3a, 0x8c42, 0x8c75,
+ 0x8c99, 0x8c98, 0x8c97, 0x8cfe, 0x8d04, 0x8d02, 0x8d00, 0x8e5c,
+ 0x8e62, 0x8e60, 0x8e57, 0x8e56, 0x8e5e, 0x8e65, 0x8e67, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8e5b, 0x8e5a, 0x8e61, 0x8e5d, 0x8e69, 0x8e54, 0x8f46, 0x8f47,
+ 0x8f48, 0x8f4b, 0x9128, 0x913a, 0x913b, 0x913e, 0x91a8, 0x91a5,
+ 0x91a7, 0x91af, 0x91aa, 0x93b5, 0x938c, 0x9392, 0x93b7, 0x939b,
+ 0x939d, 0x9389, 0x93a7, 0x938e, 0x93aa, 0x939e, 0x93a6, 0x9395,
+ 0x9388, 0x9399, 0x939f, 0x938d, 0x93b1, 0x9391, 0x93b2, 0x93a4,
+ 0x93a8, 0x93b4, 0x93a3, 0x93a5, 0x95d2, 0x95d3, 0x95d1, 0x96b3,
+ 0x96d7, 0x96da, 0x5dc2, 0x96df, 0x96d8, 0x96dd, 0x9723, 0x9722,
+ 0x9725, 0x97ac, 0x97ae, 0x97a8, 0x97ab, 0x97a4, 0x97aa, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x97a2, 0x97a5, 0x97d7, 0x97d9, 0x97d6, 0x97d8, 0x97fa,
+ 0x9850, 0x9851, 0x9852, 0x98b8, 0x9941, 0x993c, 0x993a, 0x9a0f,
+ 0x9a0b, 0x9a09, 0x9a0d, 0x9a04, 0x9a11, 0x9a0a, 0x9a05, 0x9a07,
+ 0x9a06, 0x9ac0, 0x9adc, 0x9b08, 0x9b04, 0x9b05, 0x9b29, 0x9b35,
+ 0x9b4a, 0x9b4c, 0x9b4b, 0x9bc7, 0x9bc6, 0x9bc3, 0x9bbf, 0x9bc1,
+ 0x9bb5, 0x9bb8, 0x9bd3, 0x9bb6, 0x9bc4, 0x9bb9, 0x9bbd, 0x9d5c,
+ 0x9d53, 0x9d4f, 0x9d4a, 0x9d5b, 0x9d4b, 0x9d59, 0x9d56, 0x9d4c,
+ 0x9d57, 0x9d52, 0x9d54, 0x9d5f, 0x9d58, 0x9d5a, 0x9e8e, 0x9e8c,
+ 0x9edf, 0x9f01, 0x9f00, 0x9f16, 0x9f25, 0x9f2b, 0x9f2a, 0x9f29,
+ 0x9f28, 0x9f4c, 0x9f55, 0x5134, 0x5135, 0x5296, 0x52f7, 0x53b4,
+ 0x56ab, 0x56ad, 0x56a6, 0x56a7, 0x56aa, 0x56ac, 0x58da, 0x58dd,
+ 0x58db, 0x5912, 0x5b3d, 0x5b3e, 0x5b3f, 0x5dc3, 0x5e70, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5fbf, 0x61fb, 0x6507, 0x6510, 0x650d, 0x6509, 0x650c, 0x650e,
+ 0x6584, 0x65de, 0x65dd, 0x66de, 0x6ae7, 0x6ae0, 0x6acc, 0x6ad1,
+ 0x6ad9, 0x6acb, 0x6adf, 0x6adc, 0x6ad0, 0x6aeb, 0x6acf, 0x6acd,
+ 0x6ade, 0x6b60, 0x6bb0, 0x6c0c, 0x7019, 0x7027, 0x7020, 0x7016,
+ 0x702b, 0x7021, 0x7022, 0x7023, 0x7029, 0x7017, 0x7024, 0x701c,
+ 0x702a, 0x720c, 0x720a, 0x7207, 0x7202, 0x7205, 0x72a5, 0x72a6,
+ 0x72a4, 0x72a3, 0x72a1, 0x74cb, 0x74c5, 0x74b7, 0x74c3, 0x7516,
+ 0x7660, 0x77c9, 0x77ca, 0x77c4, 0x77f1, 0x791d, 0x791b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7921, 0x791c, 0x7917, 0x791e, 0x79b0, 0x7a67, 0x7a68,
+ 0x7c33, 0x7c3c, 0x7c39, 0x7c2c, 0x7c3b, 0x7cec, 0x7cea, 0x7e76,
+ 0x7e75, 0x7e78, 0x7e70, 0x7e77, 0x7e6f, 0x7e7a, 0x7e72, 0x7e74,
+ 0x7e68, 0x7f4b, 0x7f4a, 0x7f83, 0x7f86, 0x7fb7, 0x7ffd, 0x7ffe,
+ 0x8078, 0x81d7, 0x81d5, 0x8264, 0x8261, 0x8263, 0x85eb, 0x85f1,
+ 0x85ed, 0x85d9, 0x85e1, 0x85e8, 0x85da, 0x85d7, 0x85ec, 0x85f2,
+ 0x85f8, 0x85d8, 0x85df, 0x85e3, 0x85dc, 0x85d1, 0x85f0, 0x85e6,
+ 0x85ef, 0x85de, 0x85e2, 0x8800, 0x87fa, 0x8803, 0x87f6, 0x87f7,
+ 0x8809, 0x880c, 0x880b, 0x8806, 0x87fc, 0x8808, 0x87ff, 0x880a,
+ 0x8802, 0x8962, 0x895a, 0x895b, 0x8957, 0x8961, 0x895c, 0x8958,
+ 0x895d, 0x8959, 0x8988, 0x89b7, 0x89b6, 0x89f6, 0x8b50, 0x8b48,
+ 0x8b4a, 0x8b40, 0x8b53, 0x8b56, 0x8b54, 0x8b4b, 0x8b55, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8b51, 0x8b42, 0x8b52, 0x8b57, 0x8c43, 0x8c77, 0x8c76, 0x8c9a,
+ 0x8d06, 0x8d07, 0x8d09, 0x8dac, 0x8daa, 0x8dad, 0x8dab, 0x8e6d,
+ 0x8e78, 0x8e73, 0x8e6a, 0x8e6f, 0x8e7b, 0x8ec2, 0x8f52, 0x8f51,
+ 0x8f4f, 0x8f50, 0x8f53, 0x8fb4, 0x9140, 0x913f, 0x91b0, 0x91ad,
+ 0x93de, 0x93c7, 0x93cf, 0x93c2, 0x93da, 0x93d0, 0x93f9, 0x93ec,
+ 0x93cc, 0x93d9, 0x93a9, 0x93e6, 0x93ca, 0x93d4, 0x93ee, 0x93e3,
+ 0x93d5, 0x93c4, 0x93ce, 0x93c0, 0x93d2, 0x93e7, 0x957d, 0x95da,
+ 0x95db, 0x96e1, 0x9729, 0x972b, 0x972c, 0x9728, 0x9726, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x97b3, 0x97b7, 0x97b6, 0x97dd, 0x97de, 0x97df, 0x985c,
+ 0x9859, 0x985d, 0x9857, 0x98bf, 0x98bd, 0x98bb, 0x98be, 0x9948,
+ 0x9947, 0x9943, 0x99a6, 0x99a7, 0x9a1a, 0x9a15, 0x9a25, 0x9a1d,
+ 0x9a24, 0x9a1b, 0x9a22, 0x9a20, 0x9a27, 0x9a23, 0x9a1e, 0x9a1c,
+ 0x9a14, 0x9ac2, 0x9b0b, 0x9b0a, 0x9b0e, 0x9b0c, 0x9b37, 0x9bea,
+ 0x9beb, 0x9be0, 0x9bde, 0x9be4, 0x9be6, 0x9be2, 0x9bf0, 0x9bd4,
+ 0x9bd7, 0x9bec, 0x9bdc, 0x9bd9, 0x9be5, 0x9bd5, 0x9be1, 0x9bda,
+ 0x9d77, 0x9d81, 0x9d8a, 0x9d84, 0x9d88, 0x9d71, 0x9d80, 0x9d78,
+ 0x9d86, 0x9d8b, 0x9d8c, 0x9d7d, 0x9d6b, 0x9d74, 0x9d75, 0x9d70,
+ 0x9d69, 0x9d85, 0x9d73, 0x9d7b, 0x9d82, 0x9d6f, 0x9d79, 0x9d7f,
+ 0x9d87, 0x9d68, 0x9e94, 0x9e91, 0x9ec0, 0x9efc, 0x9f2d, 0x9f40,
+ 0x9f41, 0x9f4d, 0x9f56, 0x9f57, 0x9f58, 0x5337, 0x56b2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x56b5, 0x56b3, 0x58e3, 0x5b45, 0x5dc6, 0x5dc7, 0x5eee, 0x5eef,
+ 0x5fc0, 0x5fc1, 0x61f9, 0x6517, 0x6516, 0x6515, 0x6513, 0x65df,
+ 0x66e8, 0x66e3, 0x66e4, 0x6af3, 0x6af0, 0x6aea, 0x6ae8, 0x6af9,
+ 0x6af1, 0x6aee, 0x6aef, 0x703c, 0x7035, 0x702f, 0x7037, 0x7034,
+ 0x7031, 0x7042, 0x7038, 0x703f, 0x703a, 0x7039, 0x7040, 0x703b,
+ 0x7033, 0x7041, 0x7213, 0x7214, 0x72a8, 0x737d, 0x737c, 0x74ba,
+ 0x76ab, 0x76aa, 0x76be, 0x76ed, 0x77cc, 0x77ce, 0x77cf, 0x77cd,
+ 0x77f2, 0x7925, 0x7923, 0x7927, 0x7928, 0x7924, 0x7929, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x79b2, 0x7a6e, 0x7a6c, 0x7a6d, 0x7af7, 0x7c49, 0x7c48,
+ 0x7c4a, 0x7c47, 0x7c45, 0x7cee, 0x7e7b, 0x7e7e, 0x7e81, 0x7e80,
+ 0x7fba, 0x7fff, 0x8079, 0x81db, 0x81d9, 0x820b, 0x8268, 0x8269,
+ 0x8622, 0x85ff, 0x8601, 0x85fe, 0x861b, 0x8600, 0x85f6, 0x8604,
+ 0x8609, 0x8605, 0x860c, 0x85fd, 0x8819, 0x8810, 0x8811, 0x8817,
+ 0x8813, 0x8816, 0x8963, 0x8966, 0x89b9, 0x89f7, 0x8b60, 0x8b6a,
+ 0x8b5d, 0x8b68, 0x8b63, 0x8b65, 0x8b67, 0x8b6d, 0x8dae, 0x8e86,
+ 0x8e88, 0x8e84, 0x8f59, 0x8f56, 0x8f57, 0x8f55, 0x8f58, 0x8f5a,
+ 0x908d, 0x9143, 0x9141, 0x91b7, 0x91b5, 0x91b2, 0x91b3, 0x940b,
+ 0x9413, 0x93fb, 0x9420, 0x940f, 0x9414, 0x93fe, 0x9415, 0x9410,
+ 0x9428, 0x9419, 0x940d, 0x93f5, 0x9400, 0x93f7, 0x9407, 0x940e,
+ 0x9416, 0x9412, 0x93fa, 0x9409, 0x93f8, 0x940a, 0x93ff, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x93fc, 0x940c, 0x93f6, 0x9411, 0x9406, 0x95de, 0x95e0, 0x95df,
+ 0x972e, 0x972f, 0x97b9, 0x97bb, 0x97fd, 0x97fe, 0x9860, 0x9862,
+ 0x9863, 0x985f, 0x98c1, 0x98c2, 0x9950, 0x994e, 0x9959, 0x994c,
+ 0x994b, 0x9953, 0x9a32, 0x9a34, 0x9a31, 0x9a2c, 0x9a2a, 0x9a36,
+ 0x9a29, 0x9a2e, 0x9a38, 0x9a2d, 0x9ac7, 0x9aca, 0x9ac6, 0x9b10,
+ 0x9b12, 0x9b11, 0x9c0b, 0x9c08, 0x9bf7, 0x9c05, 0x9c12, 0x9bf8,
+ 0x9c40, 0x9c07, 0x9c0e, 0x9c06, 0x9c17, 0x9c14, 0x9c09, 0x9d9f,
+ 0x9d99, 0x9da4, 0x9d9d, 0x9d92, 0x9d98, 0x9d90, 0x9d9b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9da0, 0x9d94, 0x9d9c, 0x9daa, 0x9d97, 0x9da1, 0x9d9a,
+ 0x9da2, 0x9da8, 0x9d9e, 0x9da3, 0x9dbf, 0x9da9, 0x9d96, 0x9da6,
+ 0x9da7, 0x9e99, 0x9e9b, 0x9e9a, 0x9ee5, 0x9ee4, 0x9ee7, 0x9ee6,
+ 0x9f30, 0x9f2e, 0x9f5b, 0x9f60, 0x9f5e, 0x9f5d, 0x9f59, 0x9f91,
+ 0x513a, 0x5139, 0x5298, 0x5297, 0x56c3, 0x56bd, 0x56be, 0x5b48,
+ 0x5b47, 0x5dcb, 0x5dcf, 0x5ef1, 0x61fd, 0x651b, 0x6b02, 0x6afc,
+ 0x6b03, 0x6af8, 0x6b00, 0x7043, 0x7044, 0x704a, 0x7048, 0x7049,
+ 0x7045, 0x7046, 0x721d, 0x721a, 0x7219, 0x737e, 0x7517, 0x766a,
+ 0x77d0, 0x792d, 0x7931, 0x792f, 0x7c54, 0x7c53, 0x7cf2, 0x7e8a,
+ 0xeb45, 0x7e88, 0x7e8b, 0x7e86, 0x7e8d, 0x7f4d, 0x7fbb, 0x8030,
+ 0x81dd, 0x8618, 0x862a, 0x8626, 0x861f, 0x8623, 0x861c, 0x8619,
+ 0x8627, 0x862e, 0x8621, 0x8620, 0x8629, 0x861e, 0x8625, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8829, 0x881d, 0x881b, 0x8820, 0x8824, 0x881c, 0x882b, 0x884a,
+ 0x896d, 0x8969, 0x896e, 0x896b, 0x89fa, 0x8b79, 0x8b78, 0x8b45,
+ 0x8b7a, 0x8b7b, 0x8d10, 0x8d14, 0x8daf, 0x8e8e, 0x8e8c, 0x8f5e,
+ 0x8f5b, 0x8f5d, 0x9146, 0x9144, 0x9145, 0x91b9, 0x943f, 0x943b,
+ 0x9436, 0x9429, 0x943d, 0x943c, 0x9430, 0x9439, 0x942a, 0x9437,
+ 0x942c, 0x9440, 0x9431, 0x95e5, 0x95e4, 0x95e3, 0x9735, 0x973a,
+ 0x97bf, 0x97e1, 0x9864, 0x98c9, 0x98c6, 0x98c0, 0x9958, 0x9956,
+ 0x9a39, 0x9a3d, 0x9a46, 0x9a44, 0x9a42, 0x9a41, 0x9a3a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9a3f, 0x9acd, 0x9b15, 0x9b17, 0x9b18, 0x9b16, 0x9b3a,
+ 0x9b52, 0x9c2b, 0x9c1d, 0x9c1c, 0x9c2c, 0x9c23, 0x9c28, 0x9c29,
+ 0x9c24, 0x9c21, 0x9db7, 0x9db6, 0x9dbc, 0x9dc1, 0x9dc7, 0x9dca,
+ 0x9dcf, 0x9dbe, 0x9dc5, 0x9dc3, 0x9dbb, 0x9db5, 0x9dce, 0x9db9,
+ 0x9dba, 0x9dac, 0x9dc8, 0x9db1, 0x9dad, 0x9dcc, 0x9db3, 0x9dcd,
+ 0x9db2, 0x9e7a, 0x9e9c, 0x9eeb, 0x9eee, 0x9eed, 0x9f1b, 0x9f18,
+ 0x9f1a, 0x9f31, 0x9f4e, 0x9f65, 0x9f64, 0x9f92, 0x4eb9, 0x56c6,
+ 0x56c5, 0x56cb, 0x5971, 0x5b4b, 0x5b4c, 0x5dd5, 0x5dd1, 0x5ef2,
+ 0x6521, 0x6520, 0x6526, 0x6522, 0x6b0b, 0x6b08, 0x6b09, 0x6c0d,
+ 0x7055, 0x7056, 0x7057, 0x7052, 0x721e, 0x721f, 0x72a9, 0x737f,
+ 0x74d8, 0x74d5, 0x74d9, 0x74d7, 0x766d, 0x76ad, 0x7935, 0x79b4,
+ 0x7a70, 0x7a71, 0x7c57, 0x7c5c, 0x7c59, 0x7c5b, 0x7c5a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7cf4, 0x7cf1, 0x7e91, 0x7f4f, 0x7f87, 0x81de, 0x826b, 0x8634,
+ 0x8635, 0x8633, 0x862c, 0x8632, 0x8636, 0x882c, 0x8828, 0x8826,
+ 0x882a, 0x8825, 0x8971, 0x89bf, 0x89be, 0x89fb, 0x8b7e, 0x8b84,
+ 0x8b82, 0x8b86, 0x8b85, 0x8b7f, 0x8d15, 0x8e95, 0x8e94, 0x8e9a,
+ 0x8e92, 0x8e90, 0x8e96, 0x8e97, 0x8f60, 0x8f62, 0x9147, 0x944c,
+ 0x9450, 0x944a, 0x944b, 0x944f, 0x9447, 0x9445, 0x9448, 0x9449,
+ 0x9446, 0x973f, 0x97e3, 0x986a, 0x9869, 0x98cb, 0x9954, 0x995b,
+ 0x9a4e, 0x9a53, 0x9a54, 0x9a4c, 0x9a4f, 0x9a48, 0x9a4a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9a49, 0x9a52, 0x9a50, 0x9ad0, 0x9b19, 0x9b2b, 0x9b3b,
+ 0x9b56, 0x9b55, 0x9c46, 0x9c48, 0x9c3f, 0x9c44, 0x9c39, 0x9c33,
+ 0x9c41, 0x9c3c, 0x9c37, 0x9c34, 0x9c32, 0x9c3d, 0x9c36, 0x9ddb,
+ 0x9dd2, 0x9dde, 0x9dda, 0x9dcb, 0x9dd0, 0x9ddc, 0x9dd1, 0x9ddf,
+ 0x9de9, 0x9dd9, 0x9dd8, 0x9dd6, 0x9df5, 0x9dd5, 0x9ddd, 0x9eb6,
+ 0x9ef0, 0x9f35, 0x9f33, 0x9f32, 0x9f42, 0x9f6b, 0x9f95, 0x9fa2,
+ 0x513d, 0x5299, 0x58e8, 0x58e7, 0x5972, 0x5b4d, 0x5dd8, 0x882f,
+ 0x5f4f, 0x6201, 0x6203, 0x6204, 0x6529, 0x6525, 0x6596, 0x66eb,
+ 0x6b11, 0x6b12, 0x6b0f, 0x6bca, 0x705b, 0x705a, 0x7222, 0x7382,
+ 0x7381, 0x7383, 0x7670, 0x77d4, 0x7c67, 0x7c66, 0x7e95, 0x826c,
+ 0x863a, 0x8640, 0x8639, 0x863c, 0x8631, 0x863b, 0x863e, 0x8830,
+ 0x8832, 0x882e, 0x8833, 0x8976, 0x8974, 0x8973, 0x89fe, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8b8c, 0x8b8e, 0x8b8b, 0x8b88, 0x8c45, 0x8d19, 0x8e98, 0x8f64,
+ 0x8f63, 0x91bc, 0x9462, 0x9455, 0x945d, 0x9457, 0x945e, 0x97c4,
+ 0x97c5, 0x9800, 0x9a56, 0x9a59, 0x9b1e, 0x9b1f, 0x9b20, 0x9c52,
+ 0x9c58, 0x9c50, 0x9c4a, 0x9c4d, 0x9c4b, 0x9c55, 0x9c59, 0x9c4c,
+ 0x9c4e, 0x9dfb, 0x9df7, 0x9def, 0x9de3, 0x9deb, 0x9df8, 0x9de4,
+ 0x9df6, 0x9de1, 0x9dee, 0x9de6, 0x9df2, 0x9df0, 0x9de2, 0x9dec,
+ 0x9df4, 0x9df3, 0x9de8, 0x9ded, 0x9ec2, 0x9ed0, 0x9ef2, 0x9ef3,
+ 0x9f06, 0x9f1c, 0x9f38, 0x9f37, 0x9f36, 0x9f43, 0x9f4f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9f71, 0x9f70, 0x9f6e, 0x9f6f, 0x56d3, 0x56cd, 0x5b4e,
+ 0x5c6d, 0x652d, 0x66ed, 0x66ee, 0x6b13, 0x705f, 0x7061, 0x705d,
+ 0x7060, 0x7223, 0x74db, 0x74e5, 0x77d5, 0x7938, 0x79b7, 0x79b6,
+ 0x7c6a, 0x7e97, 0x7f89, 0x826d, 0x8643, 0x8838, 0x8837, 0x8835,
+ 0x884b, 0x8b94, 0x8b95, 0x8e9e, 0x8e9f, 0x8ea0, 0x8e9d, 0x91be,
+ 0x91bd, 0x91c2, 0x946b, 0x9468, 0x9469, 0x96e5, 0x9746, 0x9743,
+ 0x9747, 0x97c7, 0x97e5, 0x9a5e, 0x9ad5, 0x9b59, 0x9c63, 0x9c67,
+ 0x9c66, 0x9c62, 0x9c5e, 0x9c60, 0x9e02, 0x9dfe, 0x9e07, 0x9e03,
+ 0x9e06, 0x9e05, 0x9e00, 0x9e01, 0x9e09, 0x9dff, 0x9dfd, 0x9e04,
+ 0x9ea0, 0x9f1e, 0x9f46, 0x9f74, 0x9f75, 0x9f76, 0x56d4, 0x652e,
+ 0x65b8, 0x6b18, 0x6b19, 0x6b17, 0x6b1a, 0x7062, 0x7226, 0x72aa,
+ 0x77d8, 0x77d9, 0x7939, 0x7c69, 0x7c6b, 0x7cf6, 0x7e9a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7e98, 0x7e9b, 0x7e99, 0x81e0, 0x81e1, 0x8646, 0x8647, 0x8648,
+ 0x8979, 0x897a, 0x897c, 0x897b, 0x89ff, 0x8b98, 0x8b99, 0x8ea5,
+ 0x8ea4, 0x8ea3, 0x946e, 0x946d, 0x946f, 0x9471, 0x9473, 0x9749,
+ 0x9872, 0x995f, 0x9c68, 0x9c6e, 0x9c6d, 0x9e0b, 0x9e0d, 0x9e10,
+ 0x9e0f, 0x9e12, 0x9e11, 0x9ea1, 0x9ef5, 0x9f09, 0x9f47, 0x9f78,
+ 0x9f7b, 0x9f7a, 0x9f79, 0x571e, 0x7066, 0x7c6f, 0x883c, 0x8db2,
+ 0x8ea6, 0x91c3, 0x9474, 0x9478, 0x9476, 0x9475, 0x9a60, 0x9c74,
+ 0x9c73, 0x9c71, 0x9c75, 0x9e14, 0x9e13, 0x9ef6, 0x9f0a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9fa4, 0x7068, 0x7065, 0x7cf7, 0x866a, 0x883e, 0x883d,
+ 0x883f, 0x8b9e, 0x8c9c, 0x8ea9, 0x8ec9, 0x974b, 0x9873, 0x9874,
+ 0x98cc, 0x9961, 0x99ab, 0x9a64, 0x9a66, 0x9a67, 0x9b24, 0x9e15,
+ 0x9e17, 0x9f48, 0x6207, 0x6b1e, 0x7227, 0x864c, 0x8ea8, 0x9482,
+ 0x9480, 0x9481, 0x9a69, 0x9a68, 0x9b2e, 0x9e19, 0x7229, 0x864b,
+ 0x8b9f, 0x9483, 0x9c79, 0x9eb7, 0x7675, 0x9a6b, 0x9c7a, 0x9e1d,
+ 0x7069, 0x706a, 0x9ea4, 0x9f7e, 0x9f49, 0x9f98, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfe4f, 0xffffffff, 0x00ff, 0x0000, 0x0100, 0x0002, 0x6000, 0x804f240
+};
+
+#ifndef LUA_FF_LIB
+static const unsigned short big5_from_unicode_0[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa246, 0xa247, 0x0000, 0xa244, 0x0000, 0xa1b1,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1c2,
+ 0xa258, 0xa1d3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa150,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1d1,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1d2,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_2[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa3be,
+ 0x0000, 0x0000, 0xa3bd, 0xa3bf, 0x0000, 0xa1c5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa3bb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_3[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa344, 0xa345, 0xa346, 0xa347, 0xa348, 0xa349, 0xa34a,
+ 0xa34b, 0xa34c, 0xa34d, 0xa34e, 0xa34f, 0xa350, 0xa351, 0xa352,
+ 0xa353, 0xa354, 0x0000, 0xa355, 0xa356, 0xa357, 0xa358, 0xa359,
+ 0xa35a, 0xa35b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa35c, 0xa35d, 0xa35e, 0xa35f, 0xa360, 0xa361, 0xa362,
+ 0xa363, 0xa364, 0xa365, 0xa366, 0xa367, 0xa368, 0xa369, 0xa36a,
+ 0xa36b, 0xa36c, 0x0000, 0xa36d, 0xa36e, 0xa36f, 0xa370, 0xa371,
+ 0xa372, 0xa373, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_20[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa156, 0xa158, 0x0000, 0x0000, 0x0000,
+ 0xa1a5, 0xa1a6, 0x0000, 0x0000, 0xa1a7, 0xa1a8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa145, 0x0000, 0x0000, 0xa14c, 0xa14b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa1ac, 0x0000, 0x0000, 0xa1ab, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa1b0, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_21[] = {
+ 0x0000, 0x0000, 0x0000, 0xa24a, 0x0000, 0xa1c1, 0x0000, 0x0000,
+ 0x0000, 0xa24b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa2b9, 0xa2ba, 0xa2bb, 0xa2bc, 0xa2bd, 0xa2be, 0xa2bf, 0xa2c0,
+ 0xa2c1, 0xa2c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa1f6, 0xa1f4, 0xa1f7, 0xa1f5, 0x0000, 0x0000, 0xa1f8, 0xa1f9,
+ 0xa1fb, 0xa1fa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_22[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa241, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa1d4, 0x0000, 0x0000, 0x0000, 0xa1db, 0xa1e8,
+ 0xa1e7, 0x0000, 0x0000, 0xa1fd, 0x0000, 0xa1fc, 0x0000, 0x0000,
+ 0x0000, 0xa1e4, 0xa1e5, 0xa1ec, 0x0000, 0x0000, 0xa1ed, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa1ef, 0xa1ee, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa1e3, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa1dc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa1da, 0xa1dd, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1d8, 0xa1d9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1f2, 0x0000, 0x0000,
+ 0x0000, 0xa1f3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1e6, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1e9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_24[] = {
+ 0xa3c0, 0xa3c1, 0xa3c2, 0xa3c3, 0xa3c4, 0xa3c5, 0xa3c6, 0xa3c7,
+ 0xa3c8, 0xa3c9, 0xa3ca, 0xa3cb, 0xa3cc, 0xa3cd, 0xa3ce, 0xa3cf,
+ 0xa3d0, 0xa3d1, 0xa3d2, 0xa3d3, 0xa3d4, 0xa3d5, 0xa3d6, 0xa3d7,
+ 0xa3d8, 0xa3d9, 0xa3da, 0xa3db, 0xa3dc, 0xa3dd, 0xa3de, 0xa3df,
+ 0x0000, 0xa3e0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_25[] = {
+ 0xa277, 0x0000, 0xa278, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa27a, 0x0000, 0x0000, 0x0000,
+ 0xa27b, 0x0000, 0x0000, 0x0000, 0xa27c, 0x0000, 0x0000, 0x0000,
+ 0xa27d, 0x0000, 0x0000, 0x0000, 0xa275, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa274, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa273, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa272, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa271, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa2a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa2a5, 0x0000,
+ 0x0000, 0xa2a7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa2a6, 0x0000, 0x0000, 0xa27e, 0xa2a1, 0xa2a3,
+ 0xa2a2, 0xa2ac, 0xa2ad, 0xa2ae, 0xa15a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa262, 0xa263, 0xa264, 0xa265, 0xa266, 0xa267, 0xa268,
+ 0xa269, 0xa270, 0xa26f, 0xa26e, 0xa26d, 0xa26c, 0xa26b, 0xa26a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa276, 0xa279, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa1bd, 0xa1bc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa1b6, 0xa1b5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa1bf, 0xa1be, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1bb, 0xa1ba,
+ 0x0000, 0x0000, 0x0000, 0xa1b3, 0x0000, 0x0000, 0xa1b7, 0xa1b4,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa2a8, 0xa2a9, 0xa2ab, 0xa2aa, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_26[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1b9, 0xa1b8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa1f0, 0x0000, 0xa1f1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_30[] = {
+ 0xa140, 0xa142, 0xa143, 0xa1b2, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa171, 0xa172, 0xa16d, 0xa16e, 0xa175, 0xa176, 0xa179, 0xa17a,
+ 0xa169, 0xa16a, 0xa245, 0x0000, 0xa165, 0xa166, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1a9, 0xa1aa, 0x0000,
+ 0x0000, 0xa2c3, 0xa2c4, 0xa2c5, 0xa2c6, 0xa2c7, 0xa2c8, 0xa2c9,
+ 0xa2ca, 0xa2cb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa2cc, 0x0000, 0xa2ce, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_31[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa374, 0xa375, 0xa376,
+ 0xa377, 0xa378, 0xa379, 0xa37a, 0xa37b, 0xa37c, 0xa37d, 0xa37e,
+ 0xa3a1, 0xa3a2, 0xa3a3, 0xa3a4, 0xa3a5, 0xa3a6, 0xa3a7, 0xa3a8,
+ 0xa3a9, 0xa3aa, 0xa3ab, 0xa3ac, 0xa3ad, 0xa3ae, 0xa3af, 0xa3b0,
+ 0xa3b1, 0xa3b2, 0xa3b3, 0xa3b4, 0xa3b5, 0xa3b6, 0xa3b7, 0xa3b8,
+ 0xa3b9, 0xa3ba, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_32[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa1c0, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_33[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa255, 0xa256,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa250, 0xa251, 0xa252, 0x0000,
+ 0x0000, 0xa254, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa257, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa253, 0x0000,
+ 0x0000, 0xa1eb, 0xa1ea, 0x0000, 0x0000, 0xa24f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_4e[] = {
+ 0xa440, 0xa442, 0x0000, 0xa443, 0x0000, 0x0000, 0x0000, 0xc945,
+ 0xa456, 0xa454, 0xa457, 0xa455, 0xc946, 0xa4a3, 0xc94f, 0xc94d,
+ 0xa4a2, 0xa4a1, 0x0000, 0x0000, 0xa542, 0xa541, 0xa540, 0x0000,
+ 0xa543, 0xa4fe, 0x0000, 0x0000, 0x0000, 0x0000, 0xa5e0, 0xa5e1,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa8c3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa458, 0x0000, 0xa4a4, 0xc950, 0x0000,
+ 0xa4a5, 0xc963, 0xa6ea, 0xcbb1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa459, 0xa4a6, 0x0000, 0xa544, 0xc964, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xc940, 0xa444, 0x0000, 0xa45b, 0x0000, 0xc947,
+ 0xa45c, 0x0000, 0x0000, 0xa4a7, 0x0000, 0xa545, 0xa547, 0xa546,
+ 0x0000, 0x0000, 0xa5e2, 0xa5e3, 0x0000, 0x0000, 0xa8c4, 0x0000,
+ 0xadbc, 0xa441, 0x0000, 0x0000, 0xc941, 0xa445, 0xa45e, 0xa45d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa5e4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa8c5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb0ae, 0xd44b,
+ 0x0000, 0x0000, 0xb6c3, 0xdcb1, 0xdcb2, 0x0000, 0xa446, 0x0000,
+ 0xa4a9, 0x0000, 0x0000, 0xa8c6, 0xa447, 0xc948, 0xa45f, 0x0000,
+ 0x0000, 0xa4aa, 0xa4ac, 0xc951, 0xa4ad, 0xa4ab, 0x0000, 0x0000,
+ 0x0000, 0xa5e5, 0x0000, 0xa8c7, 0x0000, 0x0000, 0xa8c8, 0xab45,
+ 0x0000, 0xa460, 0xa4ae, 0x0000, 0xa5e6, 0xa5e8, 0xa5e7, 0x0000,
+ 0xa6eb, 0x0000, 0x0000, 0xa8c9, 0xa8ca, 0xab46, 0xab47, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xadbd, 0x0000, 0x0000, 0xdcb3, 0x0000,
+ 0x0000, 0xf6d6, 0xa448, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa4b0, 0xa4af, 0xc952, 0xa4b1, 0xa4b7, 0x0000, 0xa4b2, 0xa4b3,
+ 0xc954, 0xc953, 0xa4b5, 0xa4b6, 0x0000, 0xa4b4, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa54a, 0xa54b, 0xa54c, 0xa54d,
+ 0xa549, 0xa550, 0xc96a, 0x0000, 0xc966, 0xc969, 0xa551, 0xa561,
+ 0x0000, 0xc968, 0x0000, 0xa54e, 0xa54f, 0xa548, 0x0000, 0x0000,
+ 0xc965, 0xc967, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa5f5, 0xc9b0, 0xa5f2, 0xa5f6, 0xc9ba, 0xc9ae, 0xa5f3, 0xc9b2,
+ 0x0000, 0x0000, 0x0000, 0xa5f4, 0x0000, 0xa5f7, 0x0000, 0xa5e9
+};
+
+static const unsigned short big5_from_unicode_4f[] = {
+ 0xc9b1, 0xa5f8, 0xc9b5, 0x0000, 0xc9b9, 0xc9b6, 0x0000, 0x0000,
+ 0xc9b3, 0xa5ea, 0xa5ec, 0xa5f9, 0x0000, 0xa5ee, 0xc9ab, 0xa5f1,
+ 0xa5ef, 0xa5f0, 0xc9bb, 0xc9b8, 0xc9af, 0xa5ed, 0x0000, 0x0000,
+ 0xc9ac, 0xa5eb, 0x0000, 0x0000, 0x0000, 0xc9b4, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xc9b7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xc9ad, 0xca66, 0x0000, 0xa742,
+ 0xa6f4, 0x0000, 0x0000, 0xca67, 0xa6f1, 0x0000, 0xa744, 0x0000,
+ 0xa6f9, 0x0000, 0xa6f8, 0xca5b, 0xa6fc, 0xa6f7, 0xca60, 0xca68,
+ 0x0000, 0xca64, 0x0000, 0xa6fa, 0x0000, 0x0000, 0xa6fd, 0xa6ee,
+ 0xa747, 0xca5d, 0x0000, 0x0000, 0xcbbd, 0xa6ec, 0xa743, 0xa6ed,
+ 0xa6f5, 0xa6f6, 0xca62, 0xca5e, 0xa6fb, 0xa6f3, 0xca5a, 0xa6ef,
+ 0xca65, 0xa745, 0xa748, 0xa6f2, 0xa740, 0xa746, 0xa6f0, 0xca63,
+ 0xa741, 0xca69, 0xca5c, 0xa6fe, 0xca5f, 0x0000, 0x0000, 0xca61,
+ 0x0000, 0xa8d8, 0xcbbf, 0xcbcb, 0xa8d0, 0x0000, 0xcbcc, 0xa8cb,
+ 0xa8d5, 0x0000, 0x0000, 0xa8ce, 0xcbb9, 0xa8d6, 0xcbb8, 0xcbbc,
+ 0xcbc3, 0xcbc1, 0xa8de, 0xa8d9, 0xcbb3, 0xcbb5, 0xa8db, 0xa8cf,
+ 0xcbb6, 0xcbc2, 0xcbc9, 0xa8d4, 0xcbbb, 0xcbb4, 0xa8d3, 0xcbb7,
+ 0xa8d7, 0xcbba, 0x0000, 0xa8d2, 0x0000, 0xa8cd, 0x0000, 0xa8dc,
+ 0xcbc4, 0xa8dd, 0xcbc8, 0x0000, 0xcbc6, 0xcbca, 0xa8da, 0xcbbe,
+ 0xcbb2, 0x0000, 0xcbc0, 0xa8d1, 0xcbc5, 0xa8cc, 0xcbc7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xab56, 0xab4a,
+ 0x0000, 0x0000, 0xcde0, 0xcde8, 0x0000, 0xab49, 0xab51, 0xab5d,
+ 0x0000, 0xcdee, 0xcdec, 0xcde7, 0x0000, 0x0000, 0x0000, 0xab4b,
+ 0xcded, 0xcde3, 0xab59, 0xab50, 0xab58, 0xcdde, 0x0000, 0xcdea,
+ 0x0000, 0xcde1, 0xab54, 0xcde2, 0x0000, 0xcddd, 0xab5b, 0xab4e,
+ 0xab57, 0xab4d, 0x0000, 0xcddf, 0xcde4, 0x0000, 0xcdeb, 0xab55,
+ 0xab52, 0xcde6, 0xab5a, 0xcde9, 0xcde5, 0xab4f, 0xab5c, 0xab53,
+ 0xab4c, 0xab48, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xcdef, 0x0000, 0xadd7, 0xadc1,
+ 0x0000, 0xadd1, 0x0000, 0xadd6, 0xd0d0, 0xd0cf, 0xd0d4, 0xd0d5,
+ 0xadc4, 0x0000, 0xadcd, 0x0000, 0x0000, 0x0000, 0xadda, 0x0000
+};
+
+static const unsigned short big5_from_unicode_50[] = {
+ 0xadce, 0x0000, 0x0000, 0x0000, 0x0000, 0xd0c9, 0xadc7, 0xd0ca,
+ 0x0000, 0xaddc, 0x0000, 0xadd3, 0xadbe, 0xadbf, 0xd0dd, 0xb0bf,
+ 0x0000, 0xadcc, 0xadcb, 0xd0cb, 0xadcf, 0xd45b, 0xadc6, 0xd0d6,
+ 0xadd5, 0xadd4, 0xadca, 0xd0ce, 0xd0d7, 0x0000, 0xd0c8, 0xadc9,
+ 0xd0d8, 0xadd2, 0xd0cc, 0xadc0, 0x0000, 0xadc3, 0xadc2, 0xd0d9,
+ 0xadd0, 0xadc5, 0xadd9, 0xaddb, 0xd0d3, 0xadd8, 0x0000, 0xd0db,
+ 0xd0cd, 0xd0dc, 0x0000, 0xd0d1, 0x0000, 0xd0da, 0x0000, 0xd0d2,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xadc8, 0x0000, 0x0000, 0x0000,
+ 0xd463, 0xd457, 0x0000, 0xb0b3, 0x0000, 0xd45c, 0xd462, 0xb0b2,
+ 0xd455, 0xb0b6, 0xd459, 0xd452, 0xb0b4, 0xd456, 0xb0b9, 0xb0be,
+ 0x0000, 0xd467, 0x0000, 0xd451, 0x0000, 0xb0ba, 0x0000, 0xd466,
+ 0x0000, 0x0000, 0xb0b5, 0xd458, 0xb0b1, 0xd453, 0xd44f, 0xd45d,
+ 0xd450, 0xd44e, 0xd45a, 0xd460, 0xd461, 0xb0b7, 0x0000, 0x0000,
+ 0xd85b, 0xd45e, 0xd44d, 0xd45f, 0x0000, 0xb0c1, 0xd464, 0xb0c0,
+ 0xd44c, 0x0000, 0xd454, 0xd465, 0xb0bc, 0xb0bb, 0xb0b8, 0xb0bd,
+ 0x0000, 0x0000, 0xb0af, 0x0000, 0x0000, 0xb0b0, 0x0000, 0x0000,
+ 0xb3c8, 0x0000, 0xd85e, 0xd857, 0x0000, 0xb3c5, 0x0000, 0xd85f,
+ 0x0000, 0x0000, 0x0000, 0xd855, 0xd858, 0xb3c4, 0xd859, 0x0000,
+ 0x0000, 0xb3c7, 0xd85d, 0x0000, 0xd853, 0xd852, 0xb3c9, 0x0000,
+ 0xb3ca, 0xb3c6, 0xb3cb, 0xd851, 0xd85c, 0xd85a, 0xd854, 0x0000,
+ 0x0000, 0x0000, 0xb3c3, 0xd856, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xb6ca, 0xb6c4, 0xdcb7, 0xb6cd,
+ 0xdcbd, 0xdcc0, 0xb6c6, 0xb6c7, 0xdcba, 0xb6c5, 0xdcc3, 0xb6cb,
+ 0xdcc4, 0x0000, 0xdcbf, 0xb6cc, 0x0000, 0xdcb4, 0xb6c9, 0xdcb5,
+ 0x0000, 0xdcbe, 0xdcbc, 0x0000, 0xdcb8, 0xb6c8, 0xdcb6, 0xb6ce,
+ 0xdcbb, 0xdcc2, 0xdcb9, 0xdcc1, 0x0000, 0x0000, 0xb9b6, 0xb9b3,
+ 0x0000, 0xb9b4, 0x0000, 0xe0f9, 0xe0f1, 0xb9b2, 0xb9af, 0xe0f2,
+ 0x0000, 0x0000, 0xb9b1, 0xe0f5, 0x0000, 0xe0f7, 0x0000, 0x0000,
+ 0xe0fe, 0x0000, 0x0000, 0xe0fd, 0xe0f8, 0xb9ae, 0xe0f0, 0xb9ac,
+ 0xe0f3, 0xb9b7, 0xe0f6, 0x0000, 0xe0fa, 0xb9b0, 0xb9ad, 0xe0fc,
+ 0xe0fb, 0xb9b5, 0x0000, 0xe0f4, 0x0000, 0xbbf8, 0xe4ec, 0x0000,
+ 0xe4e9, 0xbbf9, 0x0000, 0xbbf7, 0x0000, 0xe4f0, 0xe4ed, 0xe4e6
+};
+
+static const unsigned short big5_from_unicode_51[] = {
+ 0xbbf6, 0x0000, 0xbbfa, 0xe4e7, 0xbbf5, 0xbbfd, 0xe4ea, 0xe4eb,
+ 0xbbfb, 0xbbfc, 0xe4f1, 0xe4ee, 0xe4ef, 0x0000, 0x0000, 0x0000,
+ 0xbeaa, 0xe8f8, 0xbea7, 0xe8f5, 0xbea9, 0xbeab, 0x0000, 0xe8f6,
+ 0xbea8, 0x0000, 0xe8f7, 0x0000, 0xe8f4, 0x0000, 0x0000, 0xc076,
+ 0xecbd, 0xc077, 0xecbb, 0x0000, 0xecbc, 0xecba, 0xecb9, 0x0000,
+ 0x0000, 0xecbe, 0xc075, 0x0000, 0x0000, 0xefb8, 0xefb9, 0x0000,
+ 0xe4e8, 0xefb7, 0xc078, 0xc35f, 0xf1eb, 0xf1ec, 0x0000, 0xc4d7,
+ 0xc4d8, 0xf5c1, 0xf5c0, 0xc56c, 0xc56b, 0xf7d0, 0x0000, 0xa449,
+ 0xa461, 0xa4b9, 0x0000, 0xa4b8, 0xa553, 0xa552, 0xa5fc, 0xa5fb,
+ 0xa5fd, 0xa5fa, 0x0000, 0xa74a, 0xa749, 0xa74b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa8e0, 0x0000, 0xa8df, 0xa8e1, 0x0000, 0xab5e,
+ 0x0000, 0xa259, 0xd0de, 0xa25a, 0xb0c2, 0xa25c, 0xa25b, 0xd860,
+ 0x0000, 0xa25d, 0xb9b8, 0xa25e, 0x0000, 0xa44a, 0x0000, 0xa4ba,
+ 0xa5fe, 0xa8e2, 0x0000, 0xa44b, 0xa4bd, 0xa4bb, 0xa4bc, 0x0000,
+ 0x0000, 0xa640, 0x0000, 0x0000, 0x0000, 0xa74c, 0xa8e4, 0xa8e3,
+ 0xa8e5, 0x0000, 0x0000, 0x0000, 0xaddd, 0x0000, 0x0000, 0x0000,
+ 0xbeac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc94e,
+ 0x0000, 0xa554, 0xa555, 0x0000, 0x0000, 0xa641, 0x0000, 0xca6a,
+ 0x0000, 0xab60, 0xab5f, 0xd0e0, 0xd0df, 0xb0c3, 0x0000, 0xa4be,
+ 0xc955, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xcbcd, 0x0000,
+ 0xab61, 0x0000, 0xade0, 0x0000, 0xadde, 0xaddf, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xbead, 0x0000, 0xa556, 0x0000, 0x0000, 0x0000,
+ 0xa642, 0xc9bc, 0x0000, 0x0000, 0x0000, 0x0000, 0xa74d, 0xa74e,
+ 0x0000, 0xca6b, 0x0000, 0x0000, 0xcbce, 0xa8e6, 0xcbcf, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd0e2, 0xd0e3, 0xade3, 0x0000,
+ 0xd0e4, 0x0000, 0xd0e1, 0xade4, 0xade2, 0xade1, 0xd0e5, 0x0000,
+ 0xd468, 0x0000, 0x0000, 0x0000, 0xd861, 0x0000, 0x0000, 0xdcc5,
+ 0xe140, 0x0000, 0x0000, 0x0000, 0xbbfe, 0xbeae, 0xe8f9, 0x0000,
+ 0xa44c, 0xa45a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xb0c4, 0xb3cd, 0x0000, 0xb9b9, 0x0000, 0xc942, 0xa4bf, 0x0000,
+ 0xa559, 0xa557, 0xa558, 0x0000, 0x0000, 0xa8e7, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_52[] = {
+ 0xa44d, 0xa44e, 0x0000, 0xa462, 0x0000, 0x0000, 0xa4c0, 0xa4c1,
+ 0xa4c2, 0xc9be, 0xa55a, 0x0000, 0xc96b, 0x0000, 0xa646, 0x0000,
+ 0xc9bf, 0xa644, 0xa645, 0xc9bd, 0x0000, 0x0000, 0xa647, 0xa643,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xca6c, 0xaaec, 0xca6d, 0x0000,
+ 0x0000, 0xca6e, 0x0000, 0x0000, 0xa750, 0xa74f, 0x0000, 0x0000,
+ 0xa753, 0xa751, 0xa752, 0x0000, 0x0000, 0x0000, 0xa8ed, 0x0000,
+ 0xa8ec, 0xcbd4, 0xcbd1, 0xcbd2, 0x0000, 0xcbd0, 0xa8ee, 0xa8ea,
+ 0xa8e9, 0x0000, 0xa8eb, 0xa8e8, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa8ef, 0x0000, 0xab63, 0xcdf0, 0x0000, 0xcbd3, 0xab68,
+ 0x0000, 0xcdf1, 0xab64, 0xab67, 0xab66, 0xab65, 0xab62, 0x0000,
+ 0x0000, 0x0000, 0xd0e8, 0x0000, 0xade7, 0xd0eb, 0xade5, 0x0000,
+ 0x0000, 0x0000, 0xd0e7, 0xade8, 0xade6, 0xade9, 0xd0e9, 0xd0ea,
+ 0x0000, 0xd0e6, 0xd0ec, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb3d1, 0xb0c5, 0xd469, 0xd46b, 0xd46a, 0xd46c, 0xb0c6,
+ 0x0000, 0x0000, 0xb3ce, 0x0000, 0xb3cf, 0xb3d0, 0x0000, 0xb6d0,
+ 0xdcc7, 0x0000, 0xdcc6, 0xdcc8, 0xdcc9, 0xb6d1, 0x0000, 0xb6cf,
+ 0xe141, 0xe142, 0xb9bb, 0xb9ba, 0xe35a, 0x0000, 0x0000, 0xbc40,
+ 0xbc41, 0xbc42, 0xbc44, 0xe4f2, 0xe4f3, 0xbc43, 0x0000, 0x0000,
+ 0x0000, 0xbeaf, 0x0000, 0xbeb0, 0x0000, 0x0000, 0xf1ed, 0xf5c3,
+ 0xf5c2, 0xf7d1, 0x0000, 0xa44f, 0x0000, 0x0000, 0x0000, 0xa55c,
+ 0xa55b, 0x0000, 0x0000, 0xa648, 0x0000, 0x0000, 0xc9c0, 0x0000,
+ 0x0000, 0xa755, 0xa756, 0xa754, 0xa757, 0xca6f, 0xca70, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa8f1, 0xcbd5, 0x0000, 0xa8f0, 0x0000,
+ 0xcdf2, 0xab6c, 0xcdf3, 0xab6b, 0x0000, 0x0000, 0x0000, 0xab69,
+ 0x0000, 0xab6a, 0x0000, 0x0000, 0x0000, 0xd0ed, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xb0c7, 0xd46e, 0x0000, 0xb0ca, 0xd46d, 0xb1e5,
+ 0xb0c9, 0xb0c8, 0x0000, 0xb3d4, 0x0000, 0xb3d3, 0xb3d2, 0xb6d2,
+ 0x0000, 0x0000, 0xb6d5, 0xb6d6, 0xb6d4, 0x0000, 0xb6d3, 0x0000,
+ 0x0000, 0xe143, 0x0000, 0xe144, 0x0000, 0x0000, 0x0000, 0xe4f5,
+ 0xbc45, 0xe4f4, 0x0000, 0xbeb1, 0xecbf, 0xc079, 0x0000, 0xf1ee,
+ 0xc455, 0x0000, 0xa463, 0xa4c3, 0xc956, 0x0000, 0xa4c4, 0xa4c5
+};
+
+static const unsigned short big5_from_unicode_53[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa55e, 0x0000,
+ 0xa649, 0xca71, 0xcbd6, 0xcbd7, 0x0000, 0xab6d, 0xd0ee, 0xb0cc,
+ 0xb0cb, 0xd863, 0xd862, 0x0000, 0x0000, 0xa450, 0xa4c6, 0xa55f,
+ 0x0000, 0xb0cd, 0xc943, 0x0000, 0xc96c, 0xa560, 0x0000, 0xc9c2,
+ 0xa64b, 0xa64a, 0xc9c1, 0xa758, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xadea, 0x0000, 0x0000, 0xd46f, 0x0000, 0xb6d7,
+ 0xe145, 0xb9bc, 0x0000, 0x0000, 0xe8fa, 0x0000, 0x0000, 0xf3fd,
+ 0x0000, 0xa4c7, 0x0000, 0x0000, 0xcbd8, 0xcdf4, 0xb0d0, 0xb0ce,
+ 0xb0cf, 0xa451, 0x0000, 0xa464, 0xa2cd, 0xa4ca, 0x0000, 0xa4c9,
+ 0xa4c8, 0xa563, 0xa562, 0x0000, 0xc96d, 0xc9c3, 0x0000, 0x0000,
+ 0x0000, 0xa8f5, 0xa8f2, 0xa8f4, 0xa8f3, 0x0000, 0x0000, 0xab6e,
+ 0x0000, 0x0000, 0xb3d5, 0x0000, 0xa452, 0x0000, 0xa4cb, 0x0000,
+ 0xa565, 0xa564, 0x0000, 0xca72, 0x0000, 0x0000, 0xa8f6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xc957, 0x0000, 0xa567, 0xa566,
+ 0xa64c, 0xa64d, 0xca73, 0xa759, 0x0000, 0xa75a, 0x0000, 0xa8f7,
+ 0xa8f8, 0xa8f9, 0x0000, 0xab6f, 0xcdf5, 0x0000, 0x0000, 0xadeb,
+ 0x0000, 0x0000, 0xc944, 0x0000, 0xa4cc, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xc9c4, 0x0000, 0x0000, 0x0000, 0xca74, 0xca75,
+ 0x0000, 0x0000, 0xcbd9, 0x0000, 0xcbda, 0x0000, 0xcdf7, 0xcdf6,
+ 0xcdf9, 0xcdf8, 0xab70, 0x0000, 0xd470, 0xaded, 0xd0ef, 0xadec,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd864, 0xb3d6, 0x0000, 0xd865,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe146, 0xb9bd, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xbc46, 0x0000, 0xf1ef, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc958, 0x0000, 0xa568, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xb0d1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa453, 0xa465, 0xa4ce, 0xa4cd, 0x0000, 0xa4cf, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa8fb, 0x0000, 0xa8fa, 0xa8fc,
+ 0x0000, 0x0000, 0x0000, 0xab71, 0x0000, 0x0000, 0x0000, 0xadee,
+ 0x0000, 0xe8fb, 0xc24f, 0xa466, 0xa56a, 0xa579, 0xa574, 0x0000,
+ 0xa56f, 0xa56e, 0xa575, 0xa573, 0xa56c, 0xa57a, 0xa56d, 0xa569,
+ 0xa578, 0xa577, 0xa576, 0xa56b, 0x0000, 0xa572, 0x0000, 0x0000,
+ 0xa571, 0x0000, 0x0000, 0xa57b, 0xa570, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_54[] = {
+ 0x0000, 0xa653, 0x0000, 0xa659, 0xa655, 0x0000, 0xa65b, 0xc9c5,
+ 0xa658, 0xa64e, 0xa651, 0xa654, 0xa650, 0xa657, 0xa65a, 0xa64f,
+ 0xa652, 0xa656, 0xa65c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xca7e, 0xca7b, 0x0000, 0xa767, 0xca7c, 0xa75b, 0xa75d, 0xa775,
+ 0xa770, 0x0000, 0x0000, 0x0000, 0xcaa5, 0xca7d, 0xa75f, 0xa761,
+ 0xcaa4, 0xa768, 0xca78, 0xa774, 0xa776, 0xa75c, 0xa76d, 0x0000,
+ 0xca76, 0xa773, 0x0000, 0xa764, 0x0000, 0xa76e, 0xa76f, 0xca77,
+ 0xa76c, 0xa76a, 0x0000, 0xa76b, 0xa771, 0xcaa1, 0xa75e, 0x0000,
+ 0xa772, 0xcaa3, 0xa766, 0xa763, 0x0000, 0xca7a, 0xa762, 0xcaa6,
+ 0xa765, 0x0000, 0xa769, 0x0000, 0x0000, 0x0000, 0xa760, 0xcaa2,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xca79, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xcbeb, 0xcbea, 0xa94f, 0xcbed, 0xcbef, 0xcbe4, 0xcbe7, 0xcbee,
+ 0xa950, 0x0000, 0x0000, 0xcbe1, 0xcbe5, 0x0000, 0x0000, 0xcbe9,
+ 0xce49, 0xa94b, 0xce4d, 0xa8fd, 0xcbe6, 0xa8fe, 0xa94c, 0xa945,
+ 0xa941, 0x0000, 0xcbe2, 0xa944, 0xa949, 0xa952, 0xcbe3, 0xcbdc,
+ 0xa943, 0xcbdd, 0xcbdf, 0x0000, 0xa946, 0x0000, 0xa948, 0xcbdb,
+ 0xcbe0, 0x0000, 0x0000, 0xa951, 0xa94d, 0xcbe8, 0xa953, 0x0000,
+ 0xa94a, 0xcbde, 0xa947, 0x0000, 0x0000, 0xa942, 0xa940, 0x0000,
+ 0xcbec, 0x0000, 0xa94e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xce48, 0xcdfb, 0xce4b, 0x0000, 0x0000, 0xcdfd, 0xab78, 0xaba8,
+ 0xab74, 0xaba7, 0xab7d, 0xaba4, 0xab72, 0xcdfc, 0xce43, 0xaba3,
+ 0xce4f, 0xaba5, 0x0000, 0xab79, 0x0000, 0x0000, 0xce45, 0xce42,
+ 0xab77, 0x0000, 0xcdfa, 0xaba6, 0xce4a, 0xab7c, 0xce4c, 0xaba9,
+ 0xab73, 0xab7e, 0xab7b, 0xce40, 0xaba1, 0xce46, 0xce47, 0xab7a,
+ 0xaba2, 0xab76, 0x0000, 0x0000, 0x0000, 0x0000, 0xab75, 0xcdfe,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xce44, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xce4e, 0x0000,
+ 0xd144, 0xadfb, 0xd0f1, 0x0000, 0xd0f6, 0xadf4, 0xae40, 0xd0f4,
+ 0xadef, 0xadf9, 0xadfe, 0xd0fb, 0x0000, 0xadfa, 0xadfd, 0x0000,
+ 0x0000, 0xd0fe, 0xadf5, 0xd0f5, 0x0000, 0x0000, 0x0000, 0xd142,
+ 0xd143, 0x0000, 0xadf7, 0xd141, 0xadf3, 0xae43, 0x0000, 0xd0f8
+};
+
+static const unsigned short big5_from_unicode_55[] = {
+ 0x0000, 0xadf1, 0x0000, 0xd146, 0xd0f9, 0xd0fd, 0xadf6, 0xae42,
+ 0xd0fa, 0xadfc, 0xd140, 0xd147, 0xd4a1, 0x0000, 0xd145, 0xae44,
+ 0xadf0, 0xd0fc, 0xd0f3, 0x0000, 0xadf8, 0x0000, 0x0000, 0xd0f2,
+ 0x0000, 0x0000, 0xd0f7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd0f0, 0xae41,
+ 0x0000, 0x0000, 0xd477, 0x0000, 0xb0e4, 0xd4a7, 0xb0e2, 0xb0df,
+ 0xd47c, 0xb0db, 0xd4a2, 0xb0e6, 0xd476, 0xd47b, 0xd47a, 0xadf2,
+ 0xb0e1, 0xd4a5, 0x0000, 0xd4a8, 0xd473, 0x0000, 0xb3e8, 0x0000,
+ 0xd4a9, 0xb0e7, 0x0000, 0xb0d9, 0xb0d6, 0xd47e, 0xb0d3, 0x0000,
+ 0xd4a6, 0x0000, 0xb0da, 0xd4aa, 0x0000, 0xd474, 0xd4a4, 0xb0dd,
+ 0xd475, 0xd478, 0xd47d, 0x0000, 0x0000, 0xb0de, 0xb0dc, 0xb0e8,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xb0e3, 0x0000, 0xb0d7, 0xb1d2,
+ 0x0000, 0xb0d8, 0xd479, 0xb0e5, 0xb0e0, 0xd4a3, 0xb0d5, 0x0000,
+ 0x0000, 0x0000, 0xb0d4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd471, 0xd472, 0xd86a,
+ 0x0000, 0x0000, 0x0000, 0xb3d7, 0xb3da, 0xd875, 0xb3ee, 0xd878,
+ 0xb3d8, 0xd871, 0xb3de, 0xb3e4, 0xb5bd, 0x0000, 0x0000, 0xb3e2,
+ 0xd86e, 0xb3ef, 0xb3db, 0xb3e3, 0xd876, 0xdcd7, 0xd87b, 0xd86f,
+ 0x0000, 0xd866, 0xd873, 0xd86d, 0xb3e1, 0xd879, 0x0000, 0x0000,
+ 0xb3dd, 0xb3f1, 0xb3ea, 0x0000, 0xb3df, 0xb3dc, 0x0000, 0xb3e7,
+ 0x0000, 0xd87a, 0xd86c, 0xd872, 0xd874, 0xd868, 0xd877, 0xb3d9,
+ 0xd867, 0x0000, 0xb3e0, 0xb3f0, 0xb3ec, 0xd869, 0xb3e6, 0x0000,
+ 0x0000, 0xb3ed, 0xb3e9, 0xb3e5, 0x0000, 0xd870, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xb3eb, 0x0000, 0x0000, 0x0000, 0xdcd5,
+ 0xdcd1, 0x0000, 0xdce0, 0xdcca, 0xdcd3, 0xb6e5, 0xb6e6, 0xb6de,
+ 0xdcdc, 0xb6e8, 0xdccf, 0xdcce, 0xdccc, 0xdcde, 0xb6dc, 0xdcd8,
+ 0xdccd, 0xb6df, 0xdcd6, 0xb6da, 0xdcd2, 0xdcd9, 0xdcdb, 0x0000,
+ 0x0000, 0xdcdf, 0xb6e3, 0xdccb, 0xb6dd, 0xdcd0, 0x0000, 0xb6d8,
+ 0x0000, 0xb6e4, 0xdcda, 0xb6e0, 0xb6e1, 0xb6e7, 0xb6db, 0xa25f,
+ 0xb6d9, 0xdcd4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb6e2,
+ 0x0000, 0x0000, 0xdcdd, 0x0000, 0x0000, 0x0000, 0xb9cd, 0xb9c8,
+ 0x0000, 0xe155, 0xe151, 0x0000, 0xe14b, 0xb9c2, 0xb9be, 0xe154
+};
+
+static const unsigned short big5_from_unicode_56[] = {
+ 0xb9bf, 0xe14e, 0xe150, 0x0000, 0xe153, 0x0000, 0xb9c4, 0x0000,
+ 0xb9cb, 0xb9c5, 0x0000, 0x0000, 0xe149, 0xb9c6, 0xb9c7, 0xe14c,
+ 0xb9cc, 0x0000, 0xe14a, 0xe14f, 0xb9c3, 0xe148, 0xb9c9, 0xb9c1,
+ 0x0000, 0x0000, 0x0000, 0xb9c0, 0xe14d, 0xe152, 0x0000, 0xb9ca,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe147,
+ 0x0000, 0xbc4d, 0xe547, 0x0000, 0xe544, 0x0000, 0xbc47, 0xbc53,
+ 0xbc54, 0x0000, 0xbc4a, 0xe542, 0xbc4c, 0xe4f9, 0xbc52, 0x0000,
+ 0xe546, 0xbc49, 0xe548, 0xbc48, 0x0000, 0xe543, 0xe545, 0xbc4b,
+ 0xe541, 0xe4fa, 0xe4f7, 0x0000, 0x0000, 0xd86b, 0xe4fd, 0x0000,
+ 0xe4f6, 0xe4fc, 0xe4fb, 0x0000, 0xe4f8, 0x0000, 0xbc4f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xbc4e, 0x0000, 0x0000, 0x0000, 0xbc50,
+ 0xe4fe, 0xbeb2, 0xe540, 0x0000, 0x0000, 0x0000, 0xe945, 0x0000,
+ 0xe8fd, 0x0000, 0xbebe, 0xe942, 0xbeb6, 0xbeba, 0xe941, 0x0000,
+ 0xbeb9, 0xbeb5, 0xbeb8, 0xbeb3, 0xbebd, 0xe943, 0xe8fe, 0xbebc,
+ 0xe8fc, 0xbebb, 0xe944, 0xe940, 0xbc51, 0x0000, 0xbebf, 0xe946,
+ 0xbeb7, 0xbeb4, 0x0000, 0x0000, 0x0000, 0x0000, 0xecc6, 0xecc8,
+ 0xc07b, 0xecc9, 0xecc7, 0xecc5, 0xecc4, 0xc07d, 0xecc3, 0xc07e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xecc1, 0xecc2, 0xc07a, 0xc0a1,
+ 0xc07c, 0x0000, 0x0000, 0xecc0, 0x0000, 0xc250, 0x0000, 0xefbc,
+ 0xefba, 0xefbf, 0xefbd, 0x0000, 0xefbb, 0xefbe, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc360, 0xf1f2, 0xf1f3,
+ 0xc456, 0x0000, 0xf1f4, 0xf1f0, 0xf1f5, 0xf1f1, 0xc251, 0x0000,
+ 0x0000, 0x0000, 0xf3fe, 0xf441, 0xc459, 0xf440, 0xc458, 0xc457,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xc45a, 0xf5c5, 0xf5c6, 0x0000,
+ 0xc4da, 0xc4d9, 0xc4db, 0xf5c4, 0x0000, 0xf6d8, 0xf6d7, 0x0000,
+ 0xc56d, 0xc56f, 0xc56e, 0xf6d9, 0xc5c8, 0xf8a6, 0x0000, 0x0000,
+ 0x0000, 0xc5f1, 0x0000, 0xf8a5, 0xf8ee, 0x0000, 0x0000, 0xc949,
+ 0x0000, 0x0000, 0xa57d, 0xa57c, 0x0000, 0xa65f, 0xa65e, 0xc9c7,
+ 0xa65d, 0xc9c6, 0x0000, 0x0000, 0xa779, 0xcaa9, 0x0000, 0xcaa8,
+ 0x0000, 0x0000, 0xa777, 0xa77a, 0x0000, 0x0000, 0xcaa7, 0x0000,
+ 0xa778, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xcbf0,
+ 0x0000, 0xcbf1, 0xa954, 0x0000, 0x0000, 0x0000, 0x0000, 0xabaa
+};
+
+static const unsigned short big5_from_unicode_57[] = {
+ 0x0000, 0xd148, 0xd149, 0xae45, 0xae46, 0x0000, 0x0000, 0xd4ac,
+ 0xb0e9, 0xb0eb, 0xd4ab, 0xb0ea, 0xd87c, 0xb3f2, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xb6e9, 0xb6ea, 0xdce1, 0x0000, 0xb9cf, 0x0000,
+ 0xb9ce, 0x0000, 0xe549, 0xe948, 0xe947, 0x0000, 0xf96b, 0xa467,
+ 0xc959, 0x0000, 0xc96e, 0xc96f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa662, 0xa666, 0xc9c9, 0x0000, 0xa664, 0xa663, 0xc9c8, 0xa665,
+ 0xa661, 0x0000, 0x0000, 0xa660, 0xc9ca, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa7a6, 0x0000, 0x0000, 0xa7a3, 0x0000,
+ 0xa77d, 0xcaaa, 0x0000, 0x0000, 0x0000, 0xcaab, 0x0000, 0xa7a1,
+ 0x0000, 0xcaad, 0xa77b, 0xcaae, 0xcaac, 0xa77e, 0xa7a2, 0xa7a5,
+ 0xa7a4, 0xa77c, 0xcaaf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa959, 0xcbfe, 0x0000, 0xa95b, 0x0000, 0xa95a, 0x0000,
+ 0xcc40, 0xa958, 0xa957, 0xcbf5, 0x0000, 0xcbf4, 0x0000, 0xcbf2,
+ 0xcbf7, 0xcbf6, 0xcbf3, 0xcbfc, 0xcbfd, 0xcbfa, 0xcbf8, 0xa956,
+ 0x0000, 0x0000, 0x0000, 0xcbfb, 0xa95c, 0xcc41, 0x0000, 0x0000,
+ 0xcbf9, 0x0000, 0xabab, 0xa955, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xabac, 0xce54, 0x0000, 0x0000, 0xce5a,
+ 0x0000, 0x0000, 0x0000, 0xabb2, 0xce58, 0xce5e, 0x0000, 0xce55,
+ 0xce59, 0xce5b, 0xce5d, 0xce57, 0x0000, 0xce56, 0xce51, 0xce52,
+ 0xabad, 0x0000, 0xabaf, 0xabae, 0xce53, 0xce5c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xabb1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xce50, 0xd153, 0x0000,
+ 0xd152, 0xd157, 0xd14e, 0x0000, 0xd151, 0xd150, 0x0000, 0xd154,
+ 0x0000, 0xd158, 0xae47, 0xae4a, 0x0000, 0x0000, 0xd14f, 0xd155,
+ 0x0000, 0x0000, 0x0000, 0xae49, 0xd14a, 0x0000, 0xabb0, 0xd4ba,
+ 0xd156, 0x0000, 0xd14d, 0x0000, 0xae48, 0xd14c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd4b1, 0x0000, 0x0000, 0xb0ec,
+ 0xb0f0, 0xd4c1, 0xd4af, 0xd4bd, 0xb0f1, 0xd4bf, 0x0000, 0xd4c5,
+ 0x0000, 0xd4c9, 0x0000, 0x0000, 0xd4c0, 0xd4b4, 0xd4bc, 0x0000,
+ 0xd4ca, 0xd4c8, 0xd4be, 0xd4b9, 0xd4b2, 0xd8a6, 0xd4b0, 0xb0f5,
+ 0xd4b7, 0xb0f6, 0xb0f2, 0xd4ad, 0xd4c3, 0xd4b5, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_58[] = {
+ 0xd4b3, 0xd4c6, 0xb0f3, 0x0000, 0xd4cc, 0xb0ed, 0xb0ef, 0xd4bb,
+ 0xd4b6, 0xae4b, 0xb0ee, 0xd4b8, 0xd4c7, 0xd4cb, 0xd4c2, 0x0000,
+ 0xd4c4, 0x0000, 0x0000, 0x0000, 0xd4ae, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd8a1, 0x0000, 0xd8aa, 0xd8a9, 0xb3fa, 0xd8a2, 0x0000,
+ 0xb3fb, 0xb3f9, 0x0000, 0xd8a4, 0xb3f6, 0xd8a8, 0x0000, 0xd8a3,
+ 0xd8a5, 0xd87d, 0xb3f4, 0x0000, 0xd8b2, 0xd8b1, 0xd8ae, 0xb3f3,
+ 0xb3f7, 0xb3f8, 0xd14b, 0xd8ab, 0xb3f5, 0xb0f4, 0xd8ad, 0xd87e,
+ 0xd8b0, 0xd8af, 0x0000, 0xd8b3, 0x0000, 0xdcef, 0x0000, 0xd8ac,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd8a7, 0xdce7, 0xb6f4, 0xb6f7, 0xb6f2, 0xdce6, 0xdcea, 0xdce5,
+ 0x0000, 0xb6ec, 0xb6f6, 0xdce2, 0xb6f0, 0xdce9, 0x0000, 0xb6ee,
+ 0xb6ed, 0xdcec, 0xb6ef, 0xdcee, 0x0000, 0xdceb, 0xb6eb, 0x0000,
+ 0x0000, 0x0000, 0xb6f5, 0xdcf0, 0xdce4, 0xdced, 0x0000, 0x0000,
+ 0xdce3, 0x0000, 0x0000, 0xb6f1, 0x0000, 0xb6f3, 0x0000, 0xdce8,
+ 0x0000, 0xdcf1, 0x0000, 0x0000, 0xe15d, 0xb9d0, 0xe163, 0x0000,
+ 0x0000, 0xb9d5, 0xe15f, 0xe166, 0xe157, 0xb9d7, 0xb9d1, 0xe15c,
+ 0xbc55, 0xe15b, 0xe164, 0xb9d2, 0x0000, 0xb9d6, 0xe15a, 0xe160,
+ 0xe165, 0xe156, 0xb9d4, 0xe15e, 0x0000, 0x0000, 0xe162, 0xe168,
+ 0xe158, 0xe161, 0x0000, 0xb9d3, 0xe167, 0x0000, 0x0000, 0x0000,
+ 0xe159, 0x0000, 0x0000, 0x0000, 0xbc59, 0xe54b, 0xbc57, 0xbc56,
+ 0xe54d, 0xe552, 0x0000, 0xe54e, 0x0000, 0xe551, 0xbc5c, 0x0000,
+ 0xbea5, 0xbc5b, 0x0000, 0xe54a, 0xe550, 0x0000, 0xbc5a, 0xe54f,
+ 0x0000, 0xe54c, 0x0000, 0xbc58, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe94d, 0x0000, 0xe94f, 0xe94a, 0xbec1, 0xe94c,
+ 0x0000, 0xbec0, 0xe94e, 0x0000, 0x0000, 0xbec3, 0xe950, 0xbec2,
+ 0xe949, 0xe94b, 0x0000, 0x0000, 0x0000, 0x0000, 0xc0a5, 0xeccc,
+ 0x0000, 0xc0a4, 0xeccd, 0xc0a3, 0xeccb, 0xc0a2, 0xecca, 0x0000,
+ 0xc253, 0xc252, 0xf1f6, 0xf1f8, 0x0000, 0xf1f7, 0xc361, 0xc362,
+ 0x0000, 0x0000, 0xc363, 0xf442, 0xc45b, 0x0000, 0x0000, 0xf7d3,
+ 0xf7d2, 0xc5f2, 0x0000, 0xa468, 0xa4d0, 0x0000, 0x0000, 0xa7a7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xce5f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb3fc, 0xb3fd, 0x0000, 0xdcf2, 0xb9d8, 0xe169, 0xe553
+};
+
+static const unsigned short big5_from_unicode_59[] = {
+ 0x0000, 0x0000, 0x0000, 0xc95a, 0x0000, 0x0000, 0xcab0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xcc42, 0xce60, 0xd159, 0xae4c,
+ 0x0000, 0x0000, 0xf1f9, 0x0000, 0xc4dc, 0xa469, 0xa57e, 0xc970,
+ 0x0000, 0xa667, 0xa668, 0x0000, 0xa95d, 0x0000, 0x0000, 0x0000,
+ 0xb0f7, 0x0000, 0xb9da, 0x0000, 0xb9db, 0xb9d9, 0x0000, 0xa46a,
+ 0x0000, 0xa4d1, 0xa4d3, 0xa4d2, 0xc95b, 0xa4d4, 0xa5a1, 0xc971,
+ 0x0000, 0xa5a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa669,
+ 0xa66a, 0x0000, 0x0000, 0x0000, 0xc9cb, 0x0000, 0xa7a8, 0x0000,
+ 0xcab1, 0x0000, 0x0000, 0x0000, 0xa961, 0xcc43, 0x0000, 0xa95f,
+ 0xa960, 0xa95e, 0xd15a, 0x0000, 0x0000, 0x0000, 0xabb6, 0xabb5,
+ 0xabb7, 0xabb4, 0x0000, 0xce61, 0xa962, 0xabb3, 0x0000, 0xae4d,
+ 0xae4e, 0x0000, 0xae4f, 0x0000, 0xd4cd, 0x0000, 0x0000, 0x0000,
+ 0xb3fe, 0xd8b4, 0xb0f8, 0x0000, 0x0000, 0x0000, 0x0000, 0xb6f8,
+ 0x0000, 0xb9dd, 0xb9dc, 0xe16a, 0x0000, 0xbc5d, 0xbec4, 0x0000,
+ 0xefc0, 0xf6da, 0xf7d4, 0xa46b, 0xa5a3, 0x0000, 0xa5a4, 0xc9d1,
+ 0xa66c, 0xa66f, 0x0000, 0xc9cf, 0xc9cd, 0xa66e, 0xc9d0, 0xc9d2,
+ 0xc9cc, 0xa671, 0xa670, 0xa66d, 0xa66b, 0xc9ce, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa7b3, 0x0000, 0x0000, 0xa7b0, 0xcab6, 0xcab9,
+ 0xcab8, 0x0000, 0xa7aa, 0xa7b2, 0x0000, 0x0000, 0xa7af, 0xcab5,
+ 0xcab3, 0xa7ae, 0x0000, 0x0000, 0x0000, 0xa7a9, 0xa7ac, 0x0000,
+ 0xcab4, 0xcabb, 0xcab7, 0xa7ad, 0xa7b1, 0xa7b4, 0xcab2, 0xcaba,
+ 0xa7ab, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa967, 0xa96f,
+ 0x0000, 0xcc4f, 0xcc48, 0xa970, 0xcc53, 0xcc44, 0xcc4b, 0x0000,
+ 0x0000, 0xa966, 0xcc45, 0xa964, 0xcc4c, 0xcc50, 0xa963, 0x0000,
+ 0xcc51, 0xcc4a, 0x0000, 0xcc4d, 0x0000, 0xa972, 0xa969, 0xcc54,
+ 0xcc52, 0x0000, 0xa96e, 0xa96c, 0xcc49, 0xa96b, 0xcc47, 0xcc46,
+ 0xa96a, 0xa968, 0xa971, 0xa96d, 0xa965, 0x0000, 0xcc4e, 0x0000,
+ 0xabb9, 0x0000, 0xabc0, 0xce6f, 0xabb8, 0xce67, 0xce63, 0x0000,
+ 0xce73, 0xce62, 0x0000, 0xabbb, 0xce6c, 0xabbe, 0xabc1, 0x0000,
+ 0xabbc, 0xce70, 0xabbf, 0x0000, 0xae56, 0xce76, 0xce64, 0x0000,
+ 0x0000, 0xce66, 0xce6d, 0xce71, 0xce75, 0xce72, 0xce6b, 0xce6e,
+ 0x0000, 0x0000, 0xce68, 0xabc3, 0xce6a, 0xce69, 0xce74, 0xabba
+};
+
+static const unsigned short big5_from_unicode_5a[] = {
+ 0xce65, 0xabc2, 0x0000, 0xabbd, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xae5c, 0xd162, 0x0000, 0xae5b, 0x0000, 0x0000, 0xd160,
+ 0x0000, 0xae50, 0x0000, 0xae55, 0x0000, 0xd15f, 0xd15c, 0xd161,
+ 0xae51, 0xd15b, 0x0000, 0xae54, 0xae52, 0x0000, 0xd163, 0xae53,
+ 0xae57, 0x0000, 0x0000, 0xae58, 0x0000, 0xae5a, 0x0000, 0x0000,
+ 0x0000, 0xae59, 0x0000, 0x0000, 0x0000, 0xd15d, 0xd15e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xd164, 0x0000, 0xd4d4, 0xb0f9, 0xd8c2,
+ 0xd4d3, 0xd4e6, 0x0000, 0x0000, 0xb140, 0x0000, 0xd4e4, 0x0000,
+ 0xb0fe, 0xb0fa, 0xd4ed, 0xd4dd, 0xd4e0, 0x0000, 0xb143, 0xd4ea,
+ 0xd4e2, 0xb0fb, 0xb144, 0x0000, 0xd4e7, 0xd4e5, 0x0000, 0x0000,
+ 0xd4d6, 0xd4eb, 0xd4df, 0xd4da, 0x0000, 0xd4d0, 0xd4ec, 0xd4dc,
+ 0xd4cf, 0x0000, 0xb142, 0xd4e1, 0xd4ee, 0xd4de, 0xd4d2, 0xd4d7,
+ 0xd4ce, 0x0000, 0xb141, 0x0000, 0xd4db, 0xd4d8, 0xb0fc, 0xd4d1,
+ 0x0000, 0xd4e9, 0xb0fd, 0x0000, 0xd4d9, 0xd4d5, 0x0000, 0x0000,
+ 0xd4e8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb440,
+ 0xd8bb, 0x0000, 0xd8b8, 0xd8c9, 0xd8bd, 0xd8ca, 0x0000, 0xb442,
+ 0x0000, 0x0000, 0x0000, 0xd8c6, 0xd8c3, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd8c4, 0xd8c7, 0xd8cb, 0x0000, 0xd4e3, 0xd8cd,
+ 0xdd47, 0x0000, 0xb443, 0xd8ce, 0xd8b6, 0xd8c0, 0x0000, 0xd8c5,
+ 0x0000, 0x0000, 0xb441, 0xb444, 0xd8cc, 0xd8cf, 0xd8ba, 0xd8b7,
+ 0x0000, 0x0000, 0xd8b9, 0x0000, 0x0000, 0xd8be, 0xd8bc, 0xb445,
+ 0x0000, 0xd8c8, 0x0000, 0x0000, 0xd8bf, 0x0000, 0xd8c1, 0xd8b5,
+ 0xdcfa, 0xdcf8, 0xb742, 0xb740, 0xdd43, 0xdcf9, 0xdd44, 0xdd40,
+ 0xdcf7, 0xdd46, 0xdcf6, 0xdcfd, 0xb6fe, 0xb6fd, 0xb6fc, 0xdcfb,
+ 0xdd41, 0xb6f9, 0xb741, 0x0000, 0xdcf4, 0x0000, 0xdcfe, 0xdcf3,
+ 0xdcfc, 0xb6fa, 0xdd42, 0xdcf5, 0xb6fb, 0xdd45, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe16e, 0xb9e2, 0xb9e1,
+ 0xb9e3, 0xe17a, 0xe170, 0xe176, 0xe16b, 0xe179, 0xe178, 0xe17c,
+ 0xe175, 0xb9de, 0xe174, 0xb9e4, 0x0000, 0xe16d, 0xb9df, 0x0000,
+ 0xe17b, 0xb9e0, 0xe16f, 0xe172, 0xe177, 0xe171, 0xe16c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe173, 0xe555, 0xbc61, 0xe558, 0xe557,
+ 0xe55a, 0xe55c, 0x0000, 0xbc5f, 0x0000, 0xe556, 0x0000, 0xe554
+};
+
+static const unsigned short big5_from_unicode_5b[] = {
+ 0x0000, 0xe55d, 0xe55b, 0xe559, 0x0000, 0xe55f, 0x0000, 0xe55e,
+ 0xbc63, 0xbc5e, 0x0000, 0xbc60, 0xbc62, 0x0000, 0x0000, 0xe560,
+ 0xe957, 0x0000, 0x0000, 0xe956, 0xe955, 0x0000, 0xe958, 0xe951,
+ 0x0000, 0xe952, 0xe95a, 0xe953, 0x0000, 0xbec5, 0xe95c, 0x0000,
+ 0xe95b, 0xe954, 0x0000, 0xecd1, 0xc0a8, 0xeccf, 0xecd4, 0xecd3,
+ 0xe959, 0x0000, 0xc0a7, 0x0000, 0xecd2, 0xecce, 0xecd6, 0xecd5,
+ 0xc0a6, 0x0000, 0xecd0, 0x0000, 0xbec6, 0x0000, 0x0000, 0x0000,
+ 0xc254, 0x0000, 0x0000, 0x0000, 0xefc1, 0xf1fa, 0xf1fb, 0xf1fc,
+ 0xc45c, 0x0000, 0x0000, 0xc45d, 0x0000, 0xf443, 0x0000, 0xf5c8,
+ 0xf5c7, 0x0000, 0x0000, 0xf6db, 0xf6dc, 0xf7d5, 0xf8a7, 0x0000,
+ 0xa46c, 0xa46d, 0x0000, 0xa46e, 0xa4d5, 0xa5a5, 0xc9d3, 0xa672,
+ 0xa673, 0x0000, 0xa7b7, 0xa7b8, 0xa7b6, 0xa7b5, 0x0000, 0xa973,
+ 0x0000, 0x0000, 0xcc55, 0xa975, 0xa974, 0xcc56, 0x0000, 0x0000,
+ 0x0000, 0xabc4, 0x0000, 0xae5d, 0xd165, 0x0000, 0xd4f0, 0x0000,
+ 0xb145, 0xb447, 0xd4ef, 0xb446, 0x0000, 0xb9e5, 0x0000, 0xe17d,
+ 0xbec7, 0x0000, 0xc0a9, 0xecd7, 0x0000, 0xc45e, 0x0000, 0xc570,
+ 0x0000, 0xc972, 0x0000, 0xa5a6, 0xc973, 0xa676, 0x0000, 0xa674,
+ 0xa675, 0xa677, 0x0000, 0xa7ba, 0xa7b9, 0x0000, 0xcabc, 0xa7bb,
+ 0x0000, 0x0000, 0xcabd, 0xcc57, 0x0000, 0xcc58, 0x0000, 0xa976,
+ 0xa978, 0xa97a, 0xa977, 0xa97b, 0xa979, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xabc8, 0xabc5, 0xabc7, 0xabc9, 0xabc6, 0xd166,
+ 0xce77, 0x0000, 0x0000, 0x0000, 0xd168, 0xd167, 0xae63, 0x0000,
+ 0xae5f, 0x0000, 0x0000, 0xae60, 0xae62, 0xae64, 0xae61, 0x0000,
+ 0xae66, 0xae65, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb14a,
+ 0xd4f2, 0xd4f1, 0xb149, 0x0000, 0xb148, 0xb147, 0xb14b, 0xb146,
+ 0x0000, 0x0000, 0xd8d5, 0xd8d2, 0xb449, 0xd8d1, 0xd8d6, 0x0000,
+ 0xb44b, 0xd8d4, 0xb448, 0xb44a, 0xd8d3, 0x0000, 0xdd48, 0x0000,
+ 0xdd49, 0xdd4a, 0x0000, 0x0000, 0x0000, 0x0000, 0xb9e6, 0xb9ee,
+ 0xe17e, 0xb9e8, 0xb9ec, 0xe1a1, 0xb9ed, 0xb9e9, 0xb9ea, 0xb9e7,
+ 0xb9eb, 0xbc66, 0xd8d0, 0xbc67, 0xbc65, 0x0000, 0xbc64, 0xe95d,
+ 0xbec8, 0xecd8, 0xecd9, 0x0000, 0x0000, 0xc364, 0xc45f, 0x0000,
+ 0xa46f, 0x0000, 0xa678, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_5c[] = {
+ 0x0000, 0xabca, 0x0000, 0xd169, 0xae67, 0x0000, 0x0000, 0xb14e,
+ 0xb14d, 0xb14c, 0xb44c, 0xb44d, 0xd8d7, 0xb9ef, 0xbec9, 0xa470,
+ 0xc95c, 0xa4d6, 0xc974, 0x0000, 0x0000, 0xc9d4, 0xa679, 0x0000,
+ 0x0000, 0x0000, 0xa97c, 0x0000, 0x0000, 0x0000, 0x0000, 0xdd4b,
+ 0x0000, 0x0000, 0xa471, 0x0000, 0xa4d7, 0xc9d5, 0x0000, 0x0000,
+ 0xcabe, 0x0000, 0xcabf, 0x0000, 0xa7bc, 0x0000, 0x0000, 0x0000,
+ 0xd8d8, 0xb44e, 0x0000, 0xdd4c, 0x0000, 0x0000, 0x0000, 0xc0aa,
+ 0xa472, 0xa4a8, 0xa4d8, 0xc975, 0xa5a7, 0x0000, 0xa7c0, 0xa7bf,
+ 0xa7bd, 0xa7be, 0x0000, 0x0000, 0xcc59, 0xa97e, 0xa9a1, 0xcc5a,
+ 0xa97d, 0x0000, 0x0000, 0xabce, 0xce78, 0xabcd, 0xabcb, 0xabcc,
+ 0xae6a, 0xae68, 0x0000, 0x0000, 0xd16b, 0xae69, 0xd16a, 0x0000,
+ 0xae5e, 0xd4f3, 0x0000, 0x0000, 0xb150, 0xb151, 0x0000, 0x0000,
+ 0xb14f, 0x0000, 0xb9f0, 0xe1a2, 0xbc68, 0xbc69, 0x0000, 0xe561,
+ 0xc0ab, 0xefc2, 0xefc3, 0x0000, 0xc4dd, 0xf8a8, 0xc94b, 0xa4d9,
+ 0x0000, 0xa473, 0x0000, 0xc977, 0xc976, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa67a, 0xc9d7, 0xc9d8, 0xc9d6, 0x0000, 0xc9d9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xcac7, 0x0000,
+ 0xcac2, 0xcac4, 0xcac6, 0xcac3, 0xa7c4, 0xcac0, 0x0000, 0xcac1,
+ 0xa7c1, 0xa7c2, 0xcac5, 0xcac8, 0xa7c3, 0xcac9, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xcc68, 0x0000, 0xcc62,
+ 0xcc5d, 0xa9a3, 0xcc65, 0xcc63, 0xcc5c, 0xcc69, 0xcc6c, 0xcc67,
+ 0xcc60, 0xa9a5, 0xcc66, 0xa9a6, 0xcc61, 0xcc64, 0xcc5b, 0xcc5f,
+ 0xcc6b, 0xa9a7, 0x0000, 0xa9a8, 0x0000, 0xcc5e, 0xcc6a, 0xa9a2,
+ 0xa9a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xceab, 0xcea4,
+ 0xceaa, 0xcea3, 0xcea5, 0xce7d, 0xce7b, 0x0000, 0xceac, 0xcea9,
+ 0xce79, 0x0000, 0xabd0, 0xcea7, 0xcea8, 0x0000, 0xcea6, 0xce7c,
+ 0xce7a, 0xabcf, 0xcea2, 0xce7e, 0x0000, 0x0000, 0xcea1, 0xcead,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xae6f, 0x0000, 0xae6e, 0x0000, 0xd16c, 0xae6b, 0xd16e, 0x0000,
+ 0xae70, 0xd16f, 0x0000, 0x0000, 0xae73, 0x0000, 0xae71, 0xd170,
+ 0xceae, 0xd172, 0x0000, 0xae6d, 0x0000, 0xae6c, 0x0000, 0xd16d
+};
+
+static const unsigned short big5_from_unicode_5d[] = {
+ 0xd171, 0xae72, 0x0000, 0x0000, 0x0000, 0x0000, 0xb153, 0xb152,
+ 0x0000, 0x0000, 0x0000, 0xd4f5, 0xd4f9, 0xd4fb, 0xb154, 0xd4fe,
+ 0x0000, 0xb158, 0xd541, 0x0000, 0xb15a, 0x0000, 0xb156, 0xb15e,
+ 0x0000, 0xb15b, 0xd4f7, 0xb155, 0x0000, 0xd4f6, 0xd4f4, 0xd543,
+ 0xd4f8, 0x0000, 0xb157, 0xd542, 0xb15c, 0xd4fd, 0xd4fc, 0xb15d,
+ 0xd4fa, 0xb159, 0x0000, 0x0000, 0x0000, 0x0000, 0xd544, 0x0000,
+ 0xd540, 0xd8e7, 0xd8ee, 0xd8e3, 0xb451, 0xd8df, 0xd8ef, 0xd8d9,
+ 0xd8ec, 0xd8ea, 0xd8e4, 0x0000, 0xd8ed, 0xd8e6, 0x0000, 0xd8de,
+ 0xd8f0, 0xd8dc, 0xd8e9, 0xd8da, 0x0000, 0xd8f1, 0x0000, 0xb452,
+ 0x0000, 0xd8eb, 0xdd4f, 0xd8dd, 0xb44f, 0x0000, 0xd8e1, 0x0000,
+ 0xb450, 0xd8e0, 0xd8e5, 0x0000, 0x0000, 0xd8e2, 0x0000, 0x0000,
+ 0x0000, 0xd8e8, 0x0000, 0x0000, 0x0000, 0x0000, 0xdd53, 0x0000,
+ 0x0000, 0x0000, 0xdd56, 0xdd4e, 0x0000, 0xdd50, 0x0000, 0xdd55,
+ 0xdd54, 0xb743, 0x0000, 0xd8db, 0xdd52, 0x0000, 0x0000, 0xb744,
+ 0x0000, 0xdd4d, 0xdd51, 0x0000, 0x0000, 0x0000, 0x0000, 0xe1a9,
+ 0x0000, 0xe1b0, 0xe1a7, 0x0000, 0xe1ae, 0xe1a5, 0xe1ad, 0xe1b1,
+ 0xe1a4, 0xe1a8, 0xe1a3, 0x0000, 0xb9f1, 0x0000, 0xe1a6, 0xb9f2,
+ 0xe1ac, 0xe1ab, 0xe1aa, 0x0000, 0x0000, 0xe1af, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe565, 0xe567, 0xbc6b, 0xe568, 0x0000, 0xe563,
+ 0x0000, 0xe562, 0xe56c, 0x0000, 0xe56a, 0xbc6a, 0xe56d, 0xe564,
+ 0xe569, 0xe56b, 0xe566, 0x0000, 0x0000, 0x0000, 0x0000, 0xe961,
+ 0xe966, 0xe960, 0xe965, 0x0000, 0xe95e, 0xe968, 0xe964, 0xe969,
+ 0xe963, 0xe95f, 0xe967, 0x0000, 0xe96a, 0xe962, 0x0000, 0xecda,
+ 0xc0af, 0x0000, 0xc0ad, 0x0000, 0xc0ac, 0xc0ae, 0x0000, 0x0000,
+ 0xefc4, 0x0000, 0xf172, 0xf1fd, 0x0000, 0x0000, 0xf444, 0xf445,
+ 0x0000, 0xc460, 0x0000, 0xf5c9, 0x0000, 0xc4de, 0x0000, 0xf5ca,
+ 0x0000, 0xf6de, 0xc572, 0x0000, 0xc571, 0xf6dd, 0xc5c9, 0x0000,
+ 0xf7d6, 0x0000, 0x0000, 0x0000, 0x0000, 0xa474, 0xa67b, 0xc9da,
+ 0xcaca, 0xa8b5, 0xb15f, 0x0000, 0x0000, 0xa475, 0xa5aa, 0xa5a9,
+ 0xa5a8, 0x0000, 0x0000, 0xa7c5, 0x0000, 0x0000, 0xae74, 0x0000,
+ 0xdd57, 0xa476, 0xa477, 0xa478, 0xa4da, 0x0000, 0x0000, 0xabd1,
+ 0x0000, 0xceaf, 0x0000, 0x0000, 0x0000, 0xb453, 0xa479, 0xc95d
+};
+
+static const unsigned short big5_from_unicode_5e[] = {
+ 0x0000, 0x0000, 0xa5ab, 0xa5ac, 0xc978, 0x0000, 0xa67c, 0x0000,
+ 0x0000, 0x0000, 0xcacb, 0x0000, 0xa7c6, 0x0000, 0xcacc, 0x0000,
+ 0x0000, 0xa9ae, 0x0000, 0x0000, 0xcc6e, 0xa9ac, 0xa9ab, 0xcc6d,
+ 0xa9a9, 0xcc6f, 0xa9aa, 0xa9ad, 0x0000, 0xabd2, 0x0000, 0xabd4,
+ 0xceb3, 0xceb0, 0xceb1, 0xceb2, 0xceb4, 0xabd3, 0x0000, 0x0000,
+ 0xd174, 0xd173, 0x0000, 0xae76, 0x0000, 0xae75, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xb162, 0xd546, 0x0000, 0xb161, 0xb163,
+ 0xb160, 0x0000, 0x0000, 0x0000, 0x0000, 0xb455, 0xd545, 0x0000,
+ 0xb456, 0xd8f3, 0x0000, 0xb457, 0xd8f2, 0xb454, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xdd5a, 0xdd5c, 0xb745, 0xdd5b, 0xdd59, 0xdd58,
+ 0x0000, 0x0000, 0x0000, 0xe1b4, 0xb9f7, 0xb9f5, 0x0000, 0xb9f6,
+ 0xe1b2, 0xe1b3, 0x0000, 0xb9f3, 0xe571, 0xe56f, 0x0000, 0xbc6d,
+ 0xe570, 0xbc6e, 0xbc6c, 0xb9f4, 0x0000, 0x0000, 0xe96d, 0xe96b,
+ 0xe96c, 0xe56e, 0xecdc, 0xc0b0, 0xecdb, 0xefc5, 0xefc6, 0xe96e,
+ 0xf1fe, 0x0000, 0xa47a, 0xa5ad, 0xa67e, 0xc9db, 0xa67d, 0x0000,
+ 0xa9af, 0xb746, 0x0000, 0xa4db, 0xa5ae, 0xabd5, 0xb458, 0x0000,
+ 0xc979, 0x0000, 0xc97a, 0x0000, 0xc9dc, 0x0000, 0x0000, 0xa7c8,
+ 0xcad0, 0xcace, 0xa7c9, 0xcacd, 0xcacf, 0xcad1, 0x0000, 0xa7c7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa9b3, 0xa9b4, 0xa9b1,
+ 0x0000, 0x0000, 0xa9b0, 0xceb8, 0xa9b2, 0x0000, 0x0000, 0x0000,
+ 0xabd6, 0x0000, 0xceb7, 0xceb9, 0xceb6, 0xceba, 0xabd7, 0xae79,
+ 0xd175, 0x0000, 0xd177, 0xae77, 0xd178, 0xae78, 0xd176, 0x0000,
+ 0xceb5, 0xd547, 0xd54a, 0xd54b, 0xd548, 0xb167, 0xb166, 0xb164,
+ 0xb165, 0xd549, 0x0000, 0x0000, 0x0000, 0x0000, 0xb168, 0x0000,
+ 0x0000, 0xb45a, 0xb45b, 0x0000, 0xb45c, 0xdd5d, 0xdd5f, 0xdd61,
+ 0xb748, 0xb747, 0xb459, 0xdd60, 0xdd5e, 0x0000, 0xe1b8, 0x0000,
+ 0x0000, 0xe1b6, 0xe1bc, 0xb9f8, 0xe1bd, 0xe1ba, 0xb9f9, 0xe1b7,
+ 0xe1b5, 0xe1bb, 0xbc70, 0xe573, 0xe1b9, 0xbc72, 0xe574, 0xbc71,
+ 0xbc74, 0xe575, 0xbc6f, 0xbc73, 0x0000, 0xe973, 0xe971, 0xe970,
+ 0xe972, 0xe96f, 0x0000, 0x0000, 0xc366, 0x0000, 0xf446, 0xf447,
+ 0x0000, 0xf5cb, 0xf6df, 0xc655, 0x0000, 0x0000, 0xa9b5, 0xa7ca,
+ 0x0000, 0x0000, 0xabd8, 0x0000, 0x0000, 0x0000, 0xa47b, 0xa4dc
+};
+
+static const unsigned short big5_from_unicode_5f[] = {
+ 0x0000, 0xa5af, 0xc9dd, 0x0000, 0xa7cb, 0xcad2, 0x0000, 0xcebb,
+ 0xabd9, 0x0000, 0xb9fa, 0xa47c, 0x0000, 0x0000, 0x0000, 0xa6a1,
+ 0x0000, 0x0000, 0xb749, 0xa47d, 0xa4dd, 0xa4de, 0x0000, 0xa5b1,
+ 0xa5b0, 0x0000, 0xc9de, 0xa6a2, 0x0000, 0xcad3, 0x0000, 0xa7cc,
+ 0x0000, 0x0000, 0xcc71, 0xcc72, 0xcc73, 0x0000, 0xa9b6, 0xa9b7,
+ 0xcc70, 0xa9b8, 0x0000, 0x0000, 0x0000, 0xabda, 0xcebc, 0x0000,
+ 0xd17a, 0xae7a, 0x0000, 0xd179, 0x0000, 0xb169, 0xd54c, 0xb16a,
+ 0xd54d, 0x0000, 0x0000, 0x0000, 0xb45d, 0x0000, 0x0000, 0x0000,
+ 0xdd62, 0x0000, 0x0000, 0xe1bf, 0xe1be, 0x0000, 0xb9fb, 0x0000,
+ 0xbc75, 0xe576, 0xbeca, 0xe974, 0xc0b1, 0x0000, 0xc573, 0xf7d8,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xcc74, 0x0000, 0xcebd, 0xb16b,
+ 0xd8f4, 0xb74a, 0x0000, 0x0000, 0x0000, 0xc255, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa7ce, 0x0000, 0xa7cd, 0xabdb, 0x0000, 0xd17b,
+ 0x0000, 0xb16d, 0xb343, 0xb16e, 0xb16c, 0xb45e, 0x0000, 0xe1c0,
+ 0xb9fc, 0xbc76, 0x0000, 0xc94c, 0xc9df, 0x0000, 0xcad5, 0xa7cf,
+ 0xcad4, 0xa7d0, 0x0000, 0x0000, 0xa9bc, 0xcc77, 0xcc76, 0xa9bb,
+ 0xa9b9, 0xa9ba, 0xcc75, 0x0000, 0x0000, 0xabdd, 0xcebe, 0xabe0,
+ 0xabdc, 0xabe2, 0xabde, 0xabdf, 0xabe1, 0x0000, 0x0000, 0x0000,
+ 0xae7d, 0xae7c, 0xae7b, 0x0000, 0x0000, 0x0000, 0xd54f, 0xb16f,
+ 0xb172, 0xb170, 0x0000, 0xd54e, 0xb175, 0x0000, 0xb171, 0xd550,
+ 0xb174, 0xb173, 0x0000, 0x0000, 0x0000, 0xd8f6, 0xd8f5, 0x0000,
+ 0xb461, 0xb45f, 0xb460, 0xd8f7, 0xb74b, 0xdd64, 0xb74c, 0xdd63,
+ 0x0000, 0x0000, 0xe577, 0x0000, 0x0000, 0xbc78, 0xe1c1, 0xbc77,
+ 0x0000, 0xb9fd, 0x0000, 0xecde, 0xe975, 0xc0b2, 0xecdd, 0xf240,
+ 0xf448, 0xf449, 0x0000, 0xa4df, 0x0000, 0xa5b2, 0x0000, 0x0000,
+ 0x0000, 0xc97b, 0x0000, 0x0000, 0xa7d2, 0xa7d4, 0x0000, 0xc9e2,
+ 0xcad8, 0xcad7, 0xcad6, 0x0000, 0xc9e1, 0xc9e0, 0xa6a4, 0xa7d3,
+ 0xa7d1, 0xa6a3, 0x0000, 0x0000, 0x0000, 0xa9bd, 0xcc78, 0x0000,
+ 0xa9be, 0xcadd, 0x0000, 0xcadf, 0xcade, 0xcc79, 0x0000, 0x0000,
+ 0xcada, 0x0000, 0xa7d8, 0xa7d6, 0x0000, 0xcad9, 0xcadb, 0xcae1,
+ 0x0000, 0xa7d5, 0x0000, 0xcadc, 0xcae5, 0xa9c0, 0x0000, 0xcae2,
+ 0xa7d7, 0x0000, 0xcae0, 0xcae3, 0x0000, 0xa9bf, 0x0000, 0xa9c1
+};
+
+static const unsigned short big5_from_unicode_60[] = {
+ 0xcae4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xccaf, 0xcca2, 0xcc7e, 0xccae, 0xcca9, 0xabe7, 0xa9c2,
+ 0xccaa, 0xccad, 0xabe3, 0xccac, 0xa9c3, 0xa9c8, 0xa9c6, 0xcca3,
+ 0x0000, 0xcc7c, 0xcca5, 0xa9cd, 0xccb0, 0xabe4, 0xcca6, 0x0000,
+ 0xabe5, 0xa9c9, 0xcca8, 0x0000, 0xcecd, 0xabe6, 0xcc7b, 0xa9ca,
+ 0xabe8, 0xa9cb, 0xa9c7, 0xa9cc, 0xcca7, 0xcc7a, 0xccab, 0xa9c4,
+ 0x0000, 0x0000, 0xcc7d, 0xcca4, 0xcca1, 0xa9c5, 0x0000, 0xcebf,
+ 0x0000, 0xcec0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xceca, 0xd1a1, 0xcecb, 0xabee, 0xcece, 0xcec4, 0xabed, 0xcec6,
+ 0x0000, 0xcec7, 0x0000, 0x0000, 0xcec9, 0xabe9, 0x0000, 0x0000,
+ 0xaea3, 0x0000, 0x0000, 0xcec5, 0xcec1, 0xaea4, 0x0000, 0x0000,
+ 0xcecf, 0xae7e, 0xd17d, 0xcec8, 0x0000, 0xd17c, 0xcec3, 0xcecc,
+ 0x0000, 0x0000, 0xabec, 0xaea1, 0xabf2, 0xaea2, 0xced0, 0xd17e,
+ 0xabeb, 0xaea6, 0xabf1, 0xabf0, 0xabef, 0xaea5, 0xced1, 0xaea7,
+ 0xabea, 0x0000, 0xcec2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb176,
+ 0xd1a4, 0xd1a6, 0x0000, 0xd1a8, 0xaea8, 0xaeae, 0xd553, 0xd1ac,
+ 0xd1a3, 0xb178, 0xd551, 0x0000, 0xaead, 0xaeab, 0xd1ae, 0x0000,
+ 0xd552, 0x0000, 0xd1a5, 0x0000, 0xaeac, 0xd1a9, 0xaeaf, 0xd1ab,
+ 0x0000, 0x0000, 0xaeaa, 0xd1aa, 0xd1ad, 0xd1a7, 0x0000, 0xaea9,
+ 0xb179, 0x0000, 0xd1a2, 0xb177, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xb17a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd555, 0xd55e, 0xb464, 0x0000, 0xb17c, 0xb1a3, 0xb465, 0xd560,
+ 0xb1aa, 0xd8f9, 0xd556, 0xb1a2, 0xb1a5, 0xb17e, 0xd554, 0xd562,
+ 0xd565, 0xd949, 0x0000, 0xd563, 0xd8fd, 0xb1a1, 0xb1a8, 0xb1ac,
+ 0xd55d, 0xd8f8, 0xd561, 0xb17b, 0xd8fa, 0xd564, 0xd8fc, 0xd559,
+ 0x0000, 0xb462, 0x0000, 0xd557, 0xd558, 0xb1a7, 0x0000, 0x0000,
+ 0xb1a6, 0xd55b, 0xb1ab, 0xd55f, 0xb1a4, 0xd55c, 0x0000, 0xb1a9,
+ 0xb466, 0xb463, 0xd8fb, 0x0000, 0xd55a, 0x0000, 0xb17d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xb46b, 0xb46f, 0xd940, 0xb751, 0xb46d, 0xd944, 0xb471, 0xdd65,
+ 0xd946, 0xb753, 0xb469, 0xb46c, 0xd947, 0x0000, 0xd948, 0xd94e
+};
+
+static const unsigned short big5_from_unicode_61[] = {
+ 0xb473, 0xb754, 0x0000, 0xd94a, 0xd94f, 0xd943, 0xb75e, 0x0000,
+ 0xb755, 0xb472, 0xd941, 0xd950, 0x0000, 0xb75d, 0xb470, 0xb74e,
+ 0xd94d, 0x0000, 0xb474, 0xd945, 0xd8fe, 0xb46a, 0xd942, 0x0000,
+ 0xd94b, 0x0000, 0xb74d, 0xb752, 0xb467, 0xd94c, 0x0000, 0xb750,
+ 0x0000, 0x0000, 0x0000, 0xb468, 0x0000, 0x0000, 0x0000, 0xb75c,
+ 0xe1c3, 0xdd70, 0x0000, 0xdd68, 0xe1c2, 0x0000, 0xdd6c, 0xdd6e,
+ 0x0000, 0x0000, 0xdd6b, 0x0000, 0xb75b, 0x0000, 0xdd6a, 0xb75f,
+ 0x0000, 0x0000, 0x0000, 0xe1d2, 0x0000, 0x0000, 0xb75a, 0xba40,
+ 0xdd71, 0xe1c4, 0x0000, 0x0000, 0xb758, 0xdd69, 0xdd6d, 0xb9fe,
+ 0xb74f, 0xdd66, 0xdd67, 0xba41, 0xb757, 0xb759, 0xb756, 0xdd6f,
+ 0x0000, 0x0000, 0xe1c8, 0xe1c9, 0xe1ce, 0xbc7d, 0xe1d5, 0x0000,
+ 0xba47, 0x0000, 0xba46, 0xe1d0, 0x0000, 0xbc7c, 0xe1c5, 0xba45,
+ 0x0000, 0xe1d4, 0xba43, 0xba44, 0x0000, 0xe1d1, 0xe5aa, 0xbc7a,
+ 0xb46e, 0x0000, 0xe1d3, 0xbca3, 0xe1cb, 0x0000, 0xbc7b, 0x0000,
+ 0xbca2, 0xe1c6, 0xe1ca, 0xe1c7, 0xe1cd, 0xba48, 0xbc79, 0xba42,
+ 0x0000, 0xe57a, 0xe1cf, 0x0000, 0xbca1, 0x0000, 0xbca4, 0x0000,
+ 0xe1cc, 0x0000, 0xbc7e, 0xe579, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe57e, 0xbece, 0xe578, 0xe9a3, 0xe5a9, 0xbca8, 0x0000,
+ 0xbca6, 0xbecc, 0xe5a6, 0xe5a2, 0xbcac, 0x0000, 0xe978, 0x0000,
+ 0x0000, 0x0000, 0xbcaa, 0xe5a1, 0x0000, 0xe976, 0x0000, 0xe5a5,
+ 0x0000, 0xe5a8, 0xe57d, 0x0000, 0xbcab, 0x0000, 0x0000, 0xbca5,
+ 0xe977, 0xbecd, 0xe5a7, 0xbca7, 0xbca9, 0xe5a4, 0xbcad, 0xe5a3,
+ 0xe57c, 0xe57b, 0xbecb, 0xe5ab, 0xe97a, 0xece0, 0xbed0, 0x0000,
+ 0xe9a2, 0x0000, 0xe97e, 0x0000, 0xece1, 0x0000, 0xbed1, 0xe9a1,
+ 0x0000, 0xe97c, 0xc0b4, 0xecdf, 0x0000, 0xe979, 0xe97b, 0xc0b5,
+ 0xbed3, 0xc0b3, 0xbed2, 0xc0b7, 0xe97d, 0xbecf, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xefcf, 0x0000,
+ 0xefc7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xece7, 0xefc8,
+ 0xece3, 0x0000, 0x0000, 0xc256, 0xece5, 0xece4, 0xc0b6, 0xece2,
+ 0xece6, 0xefd0, 0xefcc, 0xefce, 0x0000, 0xefc9, 0xefca, 0x0000,
+ 0xefcd, 0xefcb, 0xc367, 0x0000, 0x0000, 0xc36a, 0xc369, 0xc368,
+ 0xc461, 0xf44a, 0xc462, 0xf241, 0xc4df, 0xf5cc, 0xc4e0, 0xc574
+};
+
+static const unsigned short big5_from_unicode_62[] = {
+ 0xc5ca, 0xf7d9, 0x0000, 0xf7da, 0xf7db, 0x0000, 0x0000, 0xf9ba,
+ 0xa4e0, 0xc97c, 0xa5b3, 0x0000, 0xa6a6, 0xa6a7, 0xa6a5, 0x0000,
+ 0xa6a8, 0xa7da, 0xa7d9, 0x0000, 0xccb1, 0xa9cf, 0xa9ce, 0x0000,
+ 0x0000, 0xd1af, 0xb1ad, 0xb1ae, 0x0000, 0x0000, 0x0000, 0xb475,
+ 0xdd72, 0xb760, 0xb761, 0xdd74, 0xdd76, 0xdd75, 0x0000, 0xe1d7,
+ 0x0000, 0xe1d6, 0xba49, 0xe1d8, 0x0000, 0xe5ac, 0xbcae, 0x0000,
+ 0xbed4, 0x0000, 0xc0b8, 0xc257, 0xc0b9, 0x0000, 0xa4e1, 0x0000,
+ 0x0000, 0x0000, 0xcae6, 0x0000, 0x0000, 0xccb2, 0xa9d1, 0xa9d0,
+ 0xa9d2, 0xabf3, 0xced2, 0xced3, 0x0000, 0x0000, 0xd1b0, 0xaeb0,
+ 0xb1af, 0xb476, 0xd951, 0xa4e2, 0x0000, 0xa47e, 0xa4e3, 0x0000,
+ 0xc97d, 0xa5b7, 0xa5b6, 0xa5b4, 0xa5b5, 0x0000, 0x0000, 0x0000,
+ 0xa6ab, 0xc9e9, 0xc9eb, 0xa6aa, 0xc9e3, 0x0000, 0xc9e4, 0x0000,
+ 0xc9ea, 0xc9e6, 0xc9e8, 0xa6a9, 0xc9e5, 0xc9ec, 0xc9e7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa7e1, 0xa7ea, 0xa7e8,
+ 0xcaf0, 0xcaed, 0xcaf5, 0xa7e6, 0xcaf6, 0x0000, 0xa7df, 0xcaf3,
+ 0x0000, 0xa7e5, 0xcaef, 0xcaee, 0xa7e3, 0xcaf4, 0xa7e4, 0xa9d3,
+ 0xa7de, 0xcaf1, 0x0000, 0xcae7, 0xa7db, 0x0000, 0xa7ee, 0xcaec,
+ 0xcaf2, 0xa7e0, 0xa7e2, 0x0000, 0xcae8, 0x0000, 0xcae9, 0xcaea,
+ 0x0000, 0xa7ed, 0xa7e7, 0xa7ec, 0xcaeb, 0xa7eb, 0xa7dd, 0xa7dc,
+ 0xa7e9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa9e1, 0xccbe, 0xccb7, 0xa9dc, 0xa9ef, 0xccb3, 0xccba, 0xccbc,
+ 0xccbf, 0xa9ea, 0x0000, 0xccbb, 0xccb4, 0xa9e8, 0xccb8, 0x0000,
+ 0xccc0, 0xa9d9, 0x0000, 0xccbd, 0xa9e3, 0xa9e2, 0xccb6, 0xa9d7,
+ 0x0000, 0x0000, 0xa9d8, 0x0000, 0xa9d6, 0x0000, 0xa9ee, 0xa9e6,
+ 0xa9e0, 0xa9d4, 0xccb9, 0xa9df, 0xa9d5, 0xa9e7, 0xa9f0, 0xced4,
+ 0xa9e4, 0xccb5, 0xa9da, 0xa9dd, 0xa9de, 0x0000, 0xa9ec, 0xa9ed,
+ 0xa9eb, 0xa9e5, 0xa9e9, 0xa9db, 0xabf4, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xceda, 0xac41, 0xabf8, 0xabfa, 0xac40,
+ 0xcee6, 0xabfd, 0xd1b1, 0xaeb1, 0xac43, 0xced7, 0xcedf, 0xabfe,
+ 0xcede, 0xcedb, 0xcee3, 0xcee5, 0xabf7, 0xabfb, 0xac42, 0xaeb3
+};
+
+static const unsigned short big5_from_unicode_63[] = {
+ 0xcee0, 0xabf9, 0xac45, 0xced9, 0x0000, 0x0000, 0x0000, 0xabfc,
+ 0xaeb2, 0xabf6, 0x0000, 0xced6, 0xcedd, 0xced5, 0xced8, 0xcedc,
+ 0xd1b2, 0xac44, 0x0000, 0xcee1, 0xcee2, 0xcee4, 0xabf5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xaec1, 0xd1be, 0xaebf, 0xaec0, 0xd1b4, 0xd1c4, 0x0000, 0xaeb6,
+ 0x0000, 0x0000, 0xd566, 0xd1c6, 0xd1c0, 0x0000, 0xd1b7, 0x0000,
+ 0xd1c9, 0xd1ba, 0xaebc, 0xd57d, 0xd1bd, 0xaebe, 0xaeb5, 0x0000,
+ 0xd1cb, 0xd1bf, 0xaeb8, 0xd1b8, 0xd1b5, 0xd1b6, 0xaeb9, 0xd1c5,
+ 0xd1cc, 0xaebb, 0xd1bc, 0xd1bb, 0xaec3, 0xaec2, 0xaeb4, 0xaeba,
+ 0xaebd, 0xd1c8, 0x0000, 0x0000, 0xd1c2, 0xaeb7, 0xd1b3, 0xd1ca,
+ 0xd1c1, 0xd1c3, 0xd1c7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd567, 0x0000, 0xb1b7,
+ 0xb1cb, 0xb1ca, 0x0000, 0xb1bf, 0x0000, 0xd579, 0xd575, 0xd572,
+ 0xd5a6, 0xb1ba, 0xb1b2, 0x0000, 0x0000, 0xd577, 0xb4a8, 0xb1b6,
+ 0xd5a1, 0x0000, 0xb1cc, 0xb1c9, 0xd57b, 0xd56a, 0x0000, 0x0000,
+ 0xb1c8, 0xd5a3, 0xd569, 0xb1bd, 0xb1c1, 0xd5a2, 0x0000, 0xd573,
+ 0xb1c2, 0xb1bc, 0xd568, 0x0000, 0xb478, 0xd5a5, 0xd571, 0xb1c7,
+ 0xd574, 0xd5a4, 0xb1c6, 0x0000, 0xd952, 0x0000, 0xb1b3, 0xd56f,
+ 0xb1b8, 0xb1c3, 0x0000, 0xb1be, 0xd578, 0xd56e, 0xd56c, 0xd57e,
+ 0xb1b0, 0xb1c4, 0xb1b4, 0xb477, 0xd57c, 0xb1b5, 0x0000, 0xb1b1,
+ 0xb1c0, 0xb1bb, 0xb1b9, 0xd570, 0xb1c5, 0xd56d, 0xd57a, 0xd576,
+ 0xd954, 0xd953, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd56b, 0xd964, 0x0000,
+ 0xb47a, 0x0000, 0xd96a, 0xd959, 0xd967, 0xdd77, 0xb47d, 0xd96b,
+ 0xd96e, 0xb47c, 0xd95c, 0xd96d, 0xd96c, 0xb47e, 0xd955, 0xb479,
+ 0xb4a3, 0x0000, 0xb4a1, 0xd969, 0x0000, 0xd95f, 0xb4a5, 0xd970,
+ 0xd968, 0xd971, 0xb4ad, 0xb4ab, 0xd966, 0xd965, 0x0000, 0xd963,
+ 0xd95d, 0xb4a4, 0x0000, 0xb4a2, 0xd1b9, 0xd956, 0x0000, 0xddb7,
+ 0xd957, 0xb47b, 0xb4aa, 0xdd79, 0x0000, 0xb4a6, 0xb4a7, 0xd958,
+ 0xd96f, 0xdd78, 0xd960, 0xd95b, 0xb4a9, 0xd961, 0xd95e, 0x0000,
+ 0x0000, 0xb4ae, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_64[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb770, 0x0000,
+ 0x0000, 0xdd7c, 0xddb1, 0xddb6, 0xddaa, 0xb76c, 0xddbb, 0xb769,
+ 0xdd7a, 0x0000, 0xdd7b, 0xb762, 0xb76b, 0xdda4, 0xb76e, 0xb76f,
+ 0xdda5, 0x0000, 0xddb2, 0xddb8, 0xb76a, 0x0000, 0xb764, 0xdda3,
+ 0xdd7d, 0xddba, 0xdda8, 0xdda9, 0xdd7e, 0xddb4, 0xddab, 0xddb5,
+ 0xddad, 0x0000, 0xb765, 0xe1d9, 0xb768, 0xb766, 0xddb9, 0xddb0,
+ 0xddac, 0x0000, 0x0000, 0xdda1, 0xba53, 0xddaf, 0xb76d, 0xdda7,
+ 0x0000, 0xdda6, 0x0000, 0x0000, 0x0000, 0xb767, 0xb763, 0xe1ee,
+ 0xddb3, 0xddae, 0x0000, 0xdda2, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe1e9, 0x0000, 0xe1da, 0xe1e5, 0x0000,
+ 0xe1ec, 0xba51, 0xb4ac, 0xe1ea, 0xba4c, 0x0000, 0x0000, 0x0000,
+ 0xba4b, 0xe1f1, 0x0000, 0xe1db, 0xe1e8, 0xe1dc, 0xe1e7, 0xba4f,
+ 0xe1eb, 0xd962, 0x0000, 0x0000, 0x0000, 0xe1f2, 0xe1e3, 0xba52,
+ 0xe5ba, 0xbcaf, 0x0000, 0xe1f0, 0xe1ef, 0xba54, 0xe5ad, 0xbcb0,
+ 0xe5ae, 0x0000, 0xe1df, 0xe1e0, 0xe1dd, 0xe1e2, 0xe1de, 0xe1f3,
+ 0xba4e, 0xbcb1, 0xba50, 0xba55, 0x0000, 0xe1e1, 0x0000, 0xe1ed,
+ 0x0000, 0x0000, 0xe1e6, 0x0000, 0x0000, 0xe5b1, 0x0000, 0xba4a,
+ 0xbcb4, 0xe9aa, 0xe5b6, 0xe5b5, 0xe5b7, 0x0000, 0x0000, 0xe5b4,
+ 0xbcb5, 0x0000, 0xbcbb, 0xbcb8, 0x0000, 0xbcb9, 0xe5af, 0xe5b2,
+ 0xe5bc, 0xbcc1, 0xbcbf, 0x0000, 0xe5b3, 0xd95a, 0xbcb2, 0xe5b9,
+ 0xe5b0, 0x0000, 0xbcc2, 0xe5b8, 0xba4d, 0xbcb7, 0xe1e4, 0x0000,
+ 0x0000, 0xbcba, 0x0000, 0xbcbe, 0xbcc0, 0xbcbd, 0xbcbc, 0x0000,
+ 0xbcb6, 0xe5bb, 0xbcb3, 0xbcc3, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xbed8, 0xbed9, 0xe9a9, 0xbee2, 0xbedf,
+ 0x0000, 0xbed6, 0xbedd, 0xe9ab, 0xbedb, 0xbed5, 0x0000, 0xbedc,
+ 0x0000, 0xe9a8, 0xc0bb, 0xbed7, 0x0000, 0xbede, 0xc0ba, 0xe9a7,
+ 0xe9a6, 0x0000, 0xbee0, 0x0000, 0xbee1, 0x0000, 0xe9a5, 0xe9a4,
+ 0xc0bc, 0xe9ae, 0xbeda, 0xe9ac, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xc0bd, 0x0000, 0xc0c2, 0xecea, 0xecec, 0x0000, 0xc0bf, 0x0000,
+ 0xeced, 0xece9, 0x0000, 0xeceb, 0xc0c0, 0xc0c3, 0x0000, 0xece8,
+ 0xc0be, 0xc0c1, 0xc259, 0xe9ad, 0xc258, 0x0000, 0x0000, 0xc25e,
+ 0xefd4, 0x0000, 0xc25c, 0xc25d, 0xefd7, 0xefd3, 0xc25a, 0xefd1
+};
+
+static const unsigned short big5_from_unicode_65[] = {
+ 0xc36b, 0xefd5, 0x0000, 0xefd6, 0xefd2, 0x0000, 0xc25b, 0xf242,
+ 0x0000, 0xf245, 0x0000, 0x0000, 0xf246, 0xf244, 0xf247, 0xc36c,
+ 0xf243, 0x0000, 0x0000, 0xf44e, 0xc464, 0xf44d, 0xf44c, 0xf44b,
+ 0xc463, 0xc465, 0x0000, 0xf5cd, 0xc4e2, 0xc4e1, 0x0000, 0x0000,
+ 0xf6e1, 0xf6e0, 0xf6e3, 0xc5cb, 0xc575, 0xf7dd, 0xf6e2, 0x0000,
+ 0x0000, 0xf7dc, 0xc5cd, 0xc5cc, 0xc5f3, 0xf8a9, 0xf8ef, 0xa4e4,
+ 0x0000, 0x0000, 0xd972, 0xe9af, 0x0000, 0x0000, 0xa6ac, 0xcaf7,
+ 0xa7f1, 0xa7ef, 0x0000, 0xa7f0, 0x0000, 0xccc1, 0xa9f1, 0xac46,
+ 0x0000, 0xcee7, 0x0000, 0xcee8, 0x0000, 0xac47, 0xd1ce, 0x0000,
+ 0xaec4, 0xaec5, 0xd1cd, 0x0000, 0x0000, 0x0000, 0x0000, 0xb1d3,
+ 0x0000, 0xb1cf, 0x0000, 0xd5a7, 0xb1d6, 0xb1d5, 0xb1ce, 0xb1d1,
+ 0xb1d4, 0xb1d0, 0x0000, 0x0000, 0xd976, 0xb1cd, 0xb4af, 0x0000,
+ 0x0000, 0x0000, 0xb4b1, 0xb4b2, 0xd975, 0xd978, 0xb4b0, 0xd973,
+ 0xd977, 0x0000, 0xd974, 0x0000, 0xb771, 0x0000, 0x0000, 0xddbc,
+ 0x0000, 0x0000, 0xba56, 0xe1f4, 0xbee3, 0xbcc4, 0xe5bd, 0xbcc5,
+ 0xbcc6, 0xe5bf, 0xe5be, 0xe5c0, 0xe9b1, 0x0000, 0x0000, 0xe9b0,
+ 0xecef, 0xecee, 0xc0c4, 0xc0c5, 0xf248, 0x0000, 0x0000, 0xa4e5,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd979, 0x0000, 0x0000, 0x0000,
+ 0xb4b4, 0xb4b3, 0xddbd, 0x0000, 0xefd8, 0xc4e3, 0xf7de, 0xa4e6,
+ 0x0000, 0xaec6, 0x0000, 0xb1d8, 0xb1d7, 0xd97a, 0xd97b, 0xb772,
+ 0xe1f5, 0xba57, 0xe9b2, 0x0000, 0xa4e7, 0xa5b8, 0x0000, 0xa9f2,
+ 0xccc2, 0x0000, 0xcee9, 0xac48, 0xb1d9, 0x0000, 0xd97c, 0xb4b5,
+ 0xb773, 0x0000, 0xe5c1, 0xe5c2, 0x0000, 0x0000, 0xecf0, 0xc25f,
+ 0xf8f0, 0xa4e8, 0x0000, 0xccc3, 0xa9f3, 0xac49, 0x0000, 0xceea,
+ 0x0000, 0xaec7, 0xd1d2, 0xd1d0, 0xd1d1, 0xaec8, 0xd1cf, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xb1db, 0xb1dc, 0xd5a8, 0xb1dd, 0xb1da,
+ 0xd97d, 0x0000, 0xd97e, 0xddbe, 0x0000, 0x0000, 0xba59, 0xba58,
+ 0x0000, 0x0000, 0xecf1, 0xefd9, 0x0000, 0xf24a, 0xf249, 0xf44f,
+ 0x0000, 0xc95e, 0xac4a, 0x0000, 0x0000, 0xa4e9, 0xa5b9, 0x0000,
+ 0xa6ae, 0xa6ad, 0x0000, 0x0000, 0xa6af, 0xa6b0, 0xc9ee, 0xc9ed,
+ 0xcaf8, 0xa7f2, 0xcafb, 0xcafa, 0xcaf9, 0xcafc, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa9f4, 0xccc9, 0xccc5, 0xccce, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_66[] = {
+ 0xa9fb, 0x0000, 0xa9f9, 0xccca, 0xccc6, 0xcccd, 0xa9f8, 0xaa40,
+ 0xccc8, 0xccc4, 0xa9fe, 0xcccb, 0xa9f7, 0xcccc, 0xa9fa, 0xa9fc,
+ 0xccd0, 0xcccf, 0xccc7, 0xa9f6, 0xa9f5, 0xa9fd, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xceef, 0xcef5, 0x0000, 0xac50,
+ 0xac4d, 0xceec, 0xcef1, 0x0000, 0xac53, 0xac4b, 0xcef0, 0xac4e,
+ 0xac51, 0x0000, 0x0000, 0xcef3, 0x0000, 0xac4c, 0xcef8, 0xac4f,
+ 0x0000, 0xac52, 0xceed, 0xcef2, 0xcef6, 0xceee, 0xceeb, 0x0000,
+ 0x0000, 0xcef7, 0xcef4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xaed0, 0xaec9, 0xaecc, 0x0000, 0xaecf, 0x0000, 0xd1d5,
+ 0x0000, 0xaeca, 0xd1d3, 0x0000, 0xaece, 0x0000, 0x0000, 0xaecb,
+ 0x0000, 0xd1d6, 0xaecd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd5ac, 0xb1df, 0xd5ab, 0xd5ad, 0xb1de, 0xb1e3, 0xd1d4,
+ 0x0000, 0xd5aa, 0xd5ae, 0x0000, 0xb1e0, 0xd5a9, 0xb1e2, 0x0000,
+ 0xb1e1, 0x0000, 0xd9a7, 0x0000, 0xd9a2, 0x0000, 0xb4b6, 0xb4ba,
+ 0xb4b7, 0xd9a5, 0xd9a8, 0x0000, 0xb4b8, 0x0000, 0xb4b9, 0xb4be,
+ 0xddc7, 0xd9a6, 0xb4bc, 0xd9a3, 0xd9a1, 0x0000, 0xb4bd, 0x0000,
+ 0xd9a4, 0x0000, 0x0000, 0x0000, 0xb779, 0x0000, 0xddbf, 0xb776,
+ 0xb777, 0xb775, 0xddc4, 0xddc3, 0xddc0, 0xb77b, 0x0000, 0x0000,
+ 0xddc2, 0xb4bb, 0x0000, 0x0000, 0xddc6, 0xddc1, 0xb778, 0xb774,
+ 0xb77a, 0xddc5, 0x0000, 0x0000, 0x0000, 0xba5c, 0x0000, 0xe1f8,
+ 0xe1f7, 0xe1f6, 0xba5a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xba5b, 0xe5c5, 0xe5c8, 0xbcc8, 0x0000, 0x0000, 0xbcc7, 0xe5c9,
+ 0xe5c4, 0xbcca, 0xe5c6, 0x0000, 0xbcc9, 0xe5c3, 0x0000, 0xe5c7,
+ 0xbee9, 0xbee6, 0xe9bb, 0xe9ba, 0x0000, 0xe9b9, 0xe9b4, 0x0000,
+ 0xe9b5, 0x0000, 0x0000, 0x0000, 0xbee7, 0x0000, 0xbee4, 0xbee8,
+ 0xe9b3, 0xbee5, 0xe9b6, 0xe9b7, 0xe9bc, 0x0000, 0x0000, 0xe9b8,
+ 0x0000, 0x0000, 0xecf2, 0x0000, 0x0000, 0x0000, 0xc0c7, 0x0000,
+ 0xefdc, 0xc0c6, 0xefda, 0xefdb, 0xc260, 0xc36e, 0xf24b, 0x0000,
+ 0xc36d, 0x0000, 0x0000, 0xf451, 0xf452, 0x0000, 0xc466, 0x0000,
+ 0xf450, 0xc4e4, 0x0000, 0xf7df, 0xc5ce, 0xf8aa, 0xf8ab, 0x0000,
+ 0xa4ea, 0x0000, 0xa6b1, 0xa6b2, 0xa7f3, 0x0000, 0xccd1, 0xac54,
+ 0xaed1, 0xb1e4, 0x0000, 0x0000, 0xb0d2, 0x0000, 0xb4bf, 0xb4c0
+};
+
+static const unsigned short big5_from_unicode_67[] = {
+ 0xb3cc, 0xd9a9, 0x0000, 0xb77c, 0xe1fa, 0xe1f9, 0x0000, 0x0000,
+ 0xa4eb, 0xa6b3, 0xccd2, 0xaa42, 0x0000, 0xaa41, 0x0000, 0xcef9,
+ 0xcefa, 0x0000, 0xd1d7, 0xd1d8, 0xaed2, 0xaed3, 0x0000, 0xaed4,
+ 0xd5af, 0x0000, 0x0000, 0xb1e6, 0x0000, 0xb4c2, 0x0000, 0xb4c1,
+ 0xddc8, 0xdf7a, 0xe1fb, 0xe9bd, 0x0000, 0x0000, 0xc261, 0xc467,
+ 0xa4ec, 0x0000, 0xa5bc, 0xa5bd, 0xa5bb, 0xa5be, 0xa5ba, 0x0000,
+ 0x0000, 0xa6b6, 0x0000, 0xc9f6, 0xa6b5, 0xa6b7, 0x0000, 0x0000,
+ 0xc9f1, 0xc9f0, 0xc9f3, 0xc9f2, 0xc9f5, 0xa6b4, 0xc9ef, 0xc9f4,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xcafd, 0xa7fd, 0xcafe,
+ 0xcb43, 0xa7fc, 0x0000, 0xcb47, 0xcb42, 0xcb45, 0xa7f5, 0xa7f6,
+ 0xa7f7, 0xa7f8, 0x0000, 0xa840, 0x0000, 0xcb41, 0xa7fa, 0xa841,
+ 0x0000, 0xcb40, 0xcb46, 0x0000, 0xa7f9, 0xcb44, 0xa7fb, 0xa7f4,
+ 0xa7fe, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xaa57, 0x0000, 0xccd4, 0xaa43, 0x0000, 0xaa4d,
+ 0xaa4e, 0xaa46, 0xaa58, 0xaa48, 0xccdc, 0xaa53, 0xccd7, 0xaa49,
+ 0xcce6, 0xcce7, 0xccdf, 0xccd8, 0xaa56, 0xcce4, 0xaa51, 0xaa4f,
+ 0x0000, 0xcce5, 0x0000, 0xcce3, 0xccdb, 0xccd3, 0xccda, 0xaa4a,
+ 0x0000, 0xaa50, 0x0000, 0xaa44, 0xccde, 0xccdd, 0xccd5, 0x0000,
+ 0xaa52, 0xcce1, 0xccd6, 0xaa55, 0xcce8, 0xaa45, 0x0000, 0xaa4c,
+ 0xccd9, 0xcce2, 0xaa54, 0x0000, 0xaa47, 0xaa4b, 0x0000, 0xcce0,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xcf5b, 0xac5c,
+ 0xac69, 0x0000, 0xcf56, 0xcf4c, 0xac62, 0xcf4a, 0xac5b, 0xcf45,
+ 0xac65, 0xcf52, 0xcefe, 0xcf41, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xcf44, 0xcefb, 0xcf51, 0xcf61, 0xac60, 0xcf46, 0xcf58, 0x0000,
+ 0xcefd, 0xcf5f, 0xcf60, 0xcf63, 0xcf5a, 0xcf4b, 0xcf53, 0xac66,
+ 0xac59, 0xac61, 0xac6d, 0xac56, 0xac58, 0x0000, 0x0000, 0x0000,
+ 0xcf43, 0xac6a, 0xac63, 0xcf5d, 0xcf40, 0xac6c, 0xac67, 0xcf49,
+ 0x0000, 0x0000, 0xac6b, 0xcf50, 0xcf48, 0xac64, 0xcf5c, 0xcf54,
+ 0x0000, 0xac5e, 0xcf62, 0xcf47, 0xac5a, 0xcf59, 0xcf4f, 0xac5f,
+ 0xcf55, 0xac57, 0xcefc, 0xac68, 0xaee3, 0xac5d, 0xcf4e, 0xcf4d,
+ 0xcf42, 0x0000, 0xcf5e, 0x0000, 0xcf57, 0x0000, 0x0000, 0xac55
+};
+
+static const unsigned short big5_from_unicode_68[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd1ec, 0xaeea, 0xd1ed, 0x0000, 0xd1e1, 0xaedf,
+ 0xaeeb, 0x0000, 0xd1da, 0x0000, 0xd1e3, 0xd1eb, 0x0000, 0xd1d9,
+ 0xd1f4, 0xaed5, 0x0000, 0x0000, 0x0000, 0xd1f3, 0xd1ee, 0x0000,
+ 0xd1ef, 0xaedd, 0xaee8, 0xd1e5, 0x0000, 0xd1e6, 0xd1f0, 0xd1e7,
+ 0x0000, 0xd1e2, 0xd1dc, 0xd1dd, 0xd1ea, 0xd1e4, 0x0000, 0x0000,
+ 0xaed6, 0xaeda, 0xd1f2, 0xd1de, 0xaee6, 0xaee2, 0x0000, 0x0000,
+ 0xaee5, 0xaeec, 0xaedb, 0xaee7, 0xd1e9, 0xaee9, 0xaed8, 0x0000,
+ 0xaed7, 0xd1db, 0x0000, 0xd1df, 0xaee0, 0xd1f1, 0xd1e8, 0xd1e0,
+ 0xaee4, 0xaee1, 0x0000, 0xaed9, 0xaedc, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xd5c4, 0x0000, 0xd5b4, 0xd5b5, 0xd5b9,
+ 0x0000, 0xd5c8, 0xd5c5, 0x0000, 0xd5be, 0xd5bd, 0xb1ed, 0xd5c1,
+ 0xd5d0, 0xd5b0, 0x0000, 0xd5d1, 0xd5c3, 0xd5d5, 0xd5c9, 0xb1ec,
+ 0xd5c7, 0xb1e7, 0xb1fc, 0xb1f2, 0x0000, 0xb1f6, 0xb1f5, 0xd5b1,
+ 0x0000, 0xd5ce, 0xd5d4, 0xd5cc, 0xd5d3, 0x0000, 0x0000, 0xd5c0,
+ 0xd5b2, 0xd5d2, 0xd5c2, 0xb1ea, 0xb1f7, 0x0000, 0xd5cb, 0xb1f0,
+ 0x0000, 0x0000, 0x0000, 0xd5ca, 0xd5b3, 0xb1f8, 0x0000, 0xb1fa,
+ 0xd5cd, 0xb1fb, 0xb1e9, 0xd5ba, 0xd5cf, 0x0000, 0x0000, 0xb1ef,
+ 0xb1f9, 0xd5bc, 0xd5c6, 0xd5b7, 0xd5bb, 0xb1f4, 0xd5b6, 0xb1e8,
+ 0xb1f1, 0xb1ee, 0xd5bf, 0xaede, 0xd9c0, 0xb1eb, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xb1f3, 0x0000, 0xd9c3, 0xd9d9,
+ 0xd9ce, 0xb4d6, 0x0000, 0xb4d1, 0xd9bd, 0xb4d2, 0xd9cd, 0x0000,
+ 0xd9c6, 0xd9d3, 0xb4ce, 0xd9ab, 0xd9d5, 0xb4c4, 0xd9b3, 0xb4c7,
+ 0xb4c6, 0x0000, 0xb4d7, 0x0000, 0xd9ad, 0xd9cf, 0xd9d0, 0xb4c9,
+ 0xb4c5, 0xd9bb, 0x0000, 0xb4d0, 0xd9b6, 0x0000, 0xd9d1, 0xb4cc,
+ 0xd9c9, 0xd9d6, 0xd9b0, 0xd9b5, 0xd9af, 0x0000, 0xb4cb, 0xd9c2,
+ 0xddde, 0xd9b1, 0xb4cf, 0xd9ba, 0xd9d2, 0xb4ca, 0xd9b7, 0xd9b4,
+ 0xd9c5, 0xb4cd, 0xb4c3, 0xb4d9, 0xd9c8, 0xd9c7, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_69[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd9ac, 0xb4c8, 0xd9d4, 0xd9bc,
+ 0xd9be, 0x0000, 0xd9cb, 0xd9ca, 0xd9aa, 0xb4d3, 0xb4d5, 0xd9b2,
+ 0xd9b9, 0xd9c1, 0xb4d4, 0xd9b8, 0xd9c4, 0xd9d7, 0x0000, 0xd9cc,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd9d8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd9ae, 0x0000, 0x0000, 0x0000, 0x0000, 0xddf2,
+ 0xb7a6, 0x0000, 0xddf0, 0xdddb, 0xdde0, 0xddd9, 0x0000, 0xddec,
+ 0xddcb, 0xddd2, 0x0000, 0xddea, 0xddf4, 0xdddc, 0x0000, 0xddcf,
+ 0xdde2, 0xdde7, 0xddd3, 0x0000, 0xdde4, 0xddd0, 0x0000, 0x0000,
+ 0xddd7, 0xddd8, 0xb7a8, 0xddeb, 0xdde9, 0x0000, 0xddcc, 0xddee,
+ 0x0000, 0xddef, 0xddf1, 0xb7ac, 0xb7a4, 0x0000, 0xd5b8, 0xddd4,
+ 0xdde6, 0xddd5, 0xb7a1, 0xb7b1, 0xdded, 0xb7af, 0xb7ab, 0xddca,
+ 0xb7a3, 0x0000, 0xddcd, 0xb7b0, 0x0000, 0xdddd, 0xddc9, 0x0000,
+ 0xb7a9, 0xdde1, 0xddd1, 0xb7aa, 0xddda, 0xb77e, 0xb4d8, 0xdde3,
+ 0xd9bf, 0xddce, 0x0000, 0x0000, 0xdde8, 0xb7a5, 0xdde5, 0xb7a2,
+ 0xdddf, 0xb7ad, 0xddd6, 0xddf3, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xb7a7, 0xdec6, 0x0000, 0x0000, 0xb7ae, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe24a, 0xe248, 0x0000,
+ 0xe25e, 0xe246, 0x0000, 0xe258, 0xb77d, 0xba5f, 0xe242, 0xe25d,
+ 0x0000, 0xe247, 0xe255, 0xba64, 0xba5d, 0x0000, 0xe25b, 0x0000,
+ 0xe240, 0xe25a, 0x0000, 0xba6f, 0xe251, 0xe261, 0xba6d, 0xe249,
+ 0xba5e, 0xe24b, 0xe259, 0xba67, 0xe244, 0xba6b, 0xba61, 0xe24d,
+ 0xe243, 0xe1fc, 0x0000, 0xe257, 0xba68, 0xe260, 0xe1fd, 0xba65,
+ 0x0000, 0xe253, 0x0000, 0xba66, 0xe245, 0xe250, 0xe24c, 0xe24e,
+ 0x0000, 0xba60, 0xe25f, 0xba6e, 0xe24f, 0x0000, 0xe262, 0x0000,
+ 0x0000, 0xe1fe, 0xe254, 0xba63, 0xba6c, 0xba6a, 0xe241, 0xe256,
+ 0xba69, 0x0000, 0x0000, 0xba62, 0xe252, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe25c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe5d5, 0x0000, 0xe5d1, 0xe5cd, 0xe5e1, 0xe5de,
+ 0xbccd, 0x0000, 0x0000, 0xe5e5, 0xe5d4, 0xbcd8, 0xe5db, 0x0000,
+ 0x0000, 0xe5d0, 0xe5da, 0xbcd5, 0xe5ee, 0x0000, 0xe5eb, 0xe5dd,
+ 0xe5ce, 0x0000, 0x0000, 0xe5e2, 0xe5e4, 0xbcd1, 0xe5d8, 0xe5d3
+};
+
+static const unsigned short big5_from_unicode_6a[] = {
+ 0xe5ca, 0xbcce, 0xbcd6, 0x0000, 0xe5e7, 0xbcd7, 0xe5cb, 0xe5ed,
+ 0xe5e0, 0xe5e6, 0xbcd4, 0x0000, 0x0000, 0xe5e3, 0x0000, 0xe5ea,
+ 0x0000, 0xbcd9, 0x0000, 0xbcd3, 0xe5dc, 0xe5cf, 0xe5ef, 0xe5cc,
+ 0xe5e8, 0xbcd0, 0x0000, 0xe5d6, 0x0000, 0xe5d7, 0xbccf, 0xbccc,
+ 0xe5d2, 0xbcd2, 0x0000, 0xbccb, 0x0000, 0xe5e9, 0xe5ec, 0xe5d9,
+ 0xe9ca, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe9c2, 0x0000, 0xe9be, 0xbef6, 0x0000, 0x0000,
+ 0xbeeb, 0xbef0, 0xbeec, 0xe9cc, 0xe9d7, 0xbeea, 0xe9c4, 0xe9cd,
+ 0xe5df, 0xe9ce, 0x0000, 0x0000, 0xbef1, 0x0000, 0xe9dd, 0xbef5,
+ 0xbef8, 0xe9c0, 0x0000, 0xbef4, 0x0000, 0xe9db, 0xe9dc, 0xe9d2,
+ 0xe9d1, 0xe9c9, 0x0000, 0x0000, 0xe9d3, 0xe9da, 0xe9d9, 0x0000,
+ 0xbeef, 0xbeed, 0xe9cb, 0xe9c8, 0x0000, 0xe9c5, 0xe9d8, 0xbef7,
+ 0xe9d6, 0xbef3, 0xbef2, 0x0000, 0xe9d0, 0x0000, 0xe9bf, 0xe9c1,
+ 0xe9c3, 0xe9d5, 0xe9cf, 0xbeee, 0x0000, 0xe9c6, 0x0000, 0xe9d4,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe9c7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc0cf, 0xed45,
+ 0xc0c8, 0xecf5, 0x0000, 0xed41, 0xc0ca, 0xed48, 0x0000, 0xecfc,
+ 0x0000, 0xecf7, 0x0000, 0x0000, 0xed49, 0xecf3, 0xecfe, 0x0000,
+ 0xc0d1, 0xed44, 0xed4a, 0xecfd, 0xc0c9, 0xed40, 0xecf4, 0xc0d0,
+ 0x0000, 0x0000, 0xed47, 0xecf9, 0xc0cc, 0x0000, 0xecfb, 0xecf8,
+ 0xc0d2, 0xecfa, 0xc0cb, 0xc0ce, 0xed43, 0xecf6, 0xed46, 0x0000,
+ 0xed42, 0x0000, 0x0000, 0x0000, 0xc263, 0xefe7, 0xc268, 0xc269,
+ 0x0000, 0x0000, 0x0000, 0xc262, 0xefe6, 0x0000, 0xefe3, 0xefe4,
+ 0xc266, 0xefde, 0xefe2, 0xc265, 0x0000, 0xefdf, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xc267, 0xc264, 0x0000, 0xefdd, 0xefe1, 0xefe5,
+ 0x0000, 0x0000, 0x0000, 0xf251, 0xf24e, 0xf257, 0x0000, 0xf256,
+ 0xf254, 0xf24f, 0x0000, 0xc372, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf250, 0xc371, 0xc0cd, 0xf253, 0xc370, 0xf258, 0xf252,
+ 0xf24d, 0xefe0, 0x0000, 0x0000, 0x0000, 0xc36f, 0x0000, 0xf24c,
+ 0xf456, 0x0000, 0xf455, 0xf255, 0xc468, 0x0000, 0xf459, 0xf45a,
+ 0xf454, 0xf458, 0x0000, 0xf453, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf5d1, 0xf457, 0xc4e7, 0xc4e5, 0xf5cf, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_6b[] = {
+ 0xf5d2, 0x0000, 0xf5ce, 0xf5d0, 0xc4e6, 0x0000, 0x0000, 0x0000,
+ 0xf6e5, 0xf6e6, 0xc576, 0xf6e4, 0x0000, 0x0000, 0x0000, 0xf7e2,
+ 0xc5cf, 0xf7e0, 0xf7e1, 0xf8ac, 0x0000, 0x0000, 0xc656, 0xf8f3,
+ 0xf8f1, 0xf8f2, 0xf8f4, 0x0000, 0x0000, 0x0000, 0xf9bb, 0x0000,
+ 0xa4ed, 0xa6b8, 0x0000, 0xaa59, 0x0000, 0xcce9, 0x0000, 0x0000,
+ 0xcf64, 0x0000, 0x0000, 0x0000, 0xd1f5, 0xd1f7, 0x0000, 0xd1f6,
+ 0x0000, 0xd1f8, 0xb1fd, 0xd5d7, 0xd1f9, 0x0000, 0xd5d6, 0xd5d8,
+ 0xd5d9, 0xd9da, 0xb4db, 0xd9db, 0xd9dd, 0xb4dc, 0xb4da, 0xd9dc,
+ 0x0000, 0xddfa, 0xddf8, 0xddf7, 0x0000, 0xddf6, 0xddf5, 0xb7b2,
+ 0xddf9, 0xba70, 0xe263, 0xe265, 0xba71, 0xe264, 0xbcdb, 0x0000,
+ 0xbcda, 0xe5f0, 0x0000, 0x0000, 0xe9df, 0xe9de, 0xe9e0, 0x0000,
+ 0x0000, 0xbef9, 0x0000, 0xed4b, 0xc0d3, 0x0000, 0xefe8, 0xc26a,
+ 0xf259, 0xc577, 0xa4ee, 0xa5bf, 0xa6b9, 0xa842, 0xaa5a, 0xaa5b,
+ 0x0000, 0x0000, 0xac6e, 0x0000, 0x0000, 0xd1fa, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xb7b3, 0x0000, 0x0000, 0x0000, 0xe6d1, 0xbefa,
+ 0xc26b, 0xa4ef, 0x0000, 0xa6ba, 0x0000, 0x0000, 0xcceb, 0xaa5c,
+ 0xccea, 0x0000, 0xcf65, 0xac6f, 0xcf66, 0x0000, 0xac70, 0x0000,
+ 0xd1fc, 0xaeee, 0xaeed, 0x0000, 0xd5de, 0xd5dc, 0xd5dd, 0xd5db,
+ 0x0000, 0xd5da, 0x0000, 0x0000, 0xd9de, 0xd9e1, 0xb4de, 0xd9df,
+ 0xb4dd, 0xd9e0, 0x0000, 0xddfb, 0x0000, 0x0000, 0xe266, 0xe267,
+ 0xe268, 0x0000, 0xe5f3, 0xe5f2, 0xbcdc, 0xe5f1, 0xe5f4, 0xe9e1,
+ 0x0000, 0x0000, 0xe9e2, 0xe9e3, 0x0000, 0xed4c, 0xc0d4, 0xc26c,
+ 0xf25a, 0x0000, 0xc4e8, 0xc95f, 0x0000, 0xac71, 0xcf67, 0xaeef,
+ 0x0000, 0x0000, 0xb1fe, 0x0000, 0xb4df, 0xd9e2, 0x0000, 0xb7b5,
+ 0xb7b4, 0x0000, 0x0000, 0xe269, 0xe26a, 0xbcdd, 0xbcde, 0xe9e5,
+ 0xe9e4, 0xefe9, 0xf7e3, 0xa4f0, 0xc960, 0xa5c0, 0x0000, 0xa843,
+ 0xcb48, 0x0000, 0xac72, 0xb7b6, 0xa4f1, 0x0000, 0xcf68, 0xac73,
+ 0xcf69, 0x0000, 0xc0d5, 0xa4f2, 0x0000, 0x0000, 0xccec, 0x0000,
+ 0xcf6a, 0x0000, 0xd242, 0xd241, 0xd1fe, 0x0000, 0xd1fd, 0xd243,
+ 0xd240, 0x0000, 0x0000, 0xb240, 0xb241, 0x0000, 0x0000, 0xb4e0,
+ 0xd9e3, 0x0000, 0xd9e4, 0xd9e5, 0x0000, 0x0000, 0x0000, 0xde41,
+ 0xde42, 0xde40, 0x0000, 0xddfd, 0xddfe, 0xb7b7, 0xe26b, 0xe5f7
+};
+
+static const unsigned short big5_from_unicode_6c[] = {
+ 0xe5f6, 0xe5f5, 0xe5f8, 0xe9e7, 0xe9e6, 0xbefb, 0xe9e8, 0x0000,
+ 0xc0d6, 0xed4d, 0x0000, 0xefea, 0xf25b, 0xf6e7, 0x0000, 0xa4f3,
+ 0xa5c2, 0xa5c1, 0x0000, 0xaa5d, 0xc961, 0xc97e, 0xa6bb, 0x0000,
+ 0xc9f7, 0xcb49, 0xcb4a, 0xaa5e, 0x0000, 0xcced, 0x0000, 0xac74,
+ 0xcf6b, 0xcf6c, 0x0000, 0xaef0, 0xaef4, 0xd244, 0xaef3, 0xaef1,
+ 0xaef2, 0x0000, 0xd5df, 0xb242, 0xb4e3, 0x0000, 0xb4e1, 0xb4e2,
+ 0xd9e6, 0x0000, 0x0000, 0xba72, 0xa4f4, 0x0000, 0xc9a1, 0x0000,
+ 0xa5c3, 0x0000, 0x0000, 0xc9a4, 0x0000, 0x0000, 0xa5c6, 0xc9a3,
+ 0xa5c5, 0xa5c4, 0xa844, 0xc9a2, 0x0000, 0x0000, 0xc9f8, 0x0000,
+ 0x0000, 0x0000, 0xc9fc, 0xc9fe, 0xca40, 0xa6c5, 0xa6c6, 0xc9fb,
+ 0xa6c1, 0x0000, 0xc9f9, 0x0000, 0xc9fd, 0xa6c2, 0x0000, 0xa6bd,
+ 0x0000, 0xa6be, 0x0000, 0xa6c4, 0xc9fa, 0xa6bc, 0xa845, 0xa6bf,
+ 0xa6c0, 0xa6c3, 0x0000, 0x0000, 0x0000, 0xcb5b, 0xcb59, 0xcb4c,
+ 0xa851, 0xcb53, 0xa84c, 0xcb4d, 0x0000, 0xcb55, 0x0000, 0xcb52,
+ 0xa84f, 0xcb51, 0xa856, 0xcb5a, 0xa858, 0x0000, 0xa85a, 0x0000,
+ 0xcb4b, 0x0000, 0xa84d, 0xcb5c, 0x0000, 0xa854, 0xa857, 0x0000,
+ 0xcd45, 0xa847, 0xa85e, 0xa855, 0xcb4e, 0xa84a, 0xa859, 0xcb56,
+ 0xa848, 0xa849, 0xcd43, 0xcb4f, 0xa850, 0xa85b, 0xcb5d, 0xcb50,
+ 0xa84e, 0x0000, 0xa853, 0xccee, 0xa85c, 0xcb57, 0xa852, 0x0000,
+ 0xa85d, 0xa846, 0xcb54, 0xa84b, 0xcb58, 0xcd44, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xaa6a, 0xaa7a, 0xccf5, 0xaa71, 0x0000,
+ 0xcd4b, 0xaa62, 0x0000, 0xaa65, 0xcd42, 0x0000, 0xccf3, 0xccf7,
+ 0xaa6d, 0xaa6f, 0xccfa, 0xaa76, 0xaa68, 0xaa66, 0xaa67, 0xaa75,
+ 0xcd47, 0xaa70, 0xccf9, 0xccfb, 0xaa6e, 0xaa73, 0xccfc, 0xcd4a,
+ 0x0000, 0xac75, 0xaa79, 0x0000, 0xaa63, 0xcd49, 0x0000, 0xcd4d,
+ 0xccf8, 0xcd4f, 0xcd40, 0xaa6c, 0xccf4, 0xaa6b, 0xaa7d, 0xaa72,
+ 0x0000, 0xccf2, 0xcf75, 0xaa78, 0xaa7c, 0xcd41, 0xcd46, 0x0000,
+ 0xaa7e, 0xaa77, 0xaa69, 0xaa5f, 0x0000, 0xaa64, 0x0000, 0xccf6,
+ 0xaa60, 0xcd4e, 0x0000, 0xccf0, 0xccef, 0xccfd, 0xccf1, 0xaa7b,
+ 0xaef5, 0xaa74, 0xccfe, 0xaa61, 0x0000, 0xaca6, 0x0000, 0x0000,
+ 0x0000, 0xcd4c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_6d[] = {
+ 0xcf7c, 0xcfa1, 0x0000, 0xcfa4, 0xcf77, 0x0000, 0x0000, 0xcfa7,
+ 0xcfaa, 0xcfac, 0xcf74, 0xac76, 0xac7b, 0xd249, 0xacad, 0xcfa5,
+ 0xcfad, 0xcf7b, 0xcf73, 0x0000, 0x0000, 0x0000, 0xd264, 0xac7e,
+ 0xcfa2, 0xcf78, 0xcf7a, 0xaca5, 0x0000, 0xcf7d, 0xac7d, 0xcf70,
+ 0xcfa8, 0x0000, 0xcfab, 0x0000, 0x0000, 0xac7a, 0x0000, 0xaca8,
+ 0xcf6d, 0xacaa, 0xac78, 0xacae, 0xcfa9, 0xcf6f, 0xacab, 0xd25e,
+ 0xcd48, 0xac7c, 0xac77, 0xcf76, 0xcf6e, 0xacac, 0xaca4, 0xcfa3,
+ 0xaca9, 0xaca7, 0xcf79, 0xaca1, 0xcf71, 0xaca2, 0xaca3, 0xcf72,
+ 0xcfa6, 0xac79, 0xcf7e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd24c, 0xaefd, 0xaf43, 0x0000, 0x0000, 0x0000, 0xd255, 0xd25b,
+ 0xd257, 0xd24a, 0xd24d, 0xd246, 0xd247, 0xaf4a, 0xaefa, 0xd256,
+ 0xd25f, 0xaf45, 0xaef6, 0x0000, 0xaf40, 0xd24e, 0xaf42, 0xd24f,
+ 0xd259, 0x0000, 0x0000, 0x0000, 0xaf44, 0xd268, 0xd248, 0xaefc,
+ 0xaefb, 0xaf48, 0xd245, 0xd266, 0xd25a, 0xd267, 0xd261, 0xd253,
+ 0xd262, 0x0000, 0xd25c, 0xd265, 0xd263, 0xaf49, 0xd254, 0xaef9,
+ 0xaef8, 0xaf41, 0xaf47, 0xd260, 0xaf46, 0xd251, 0xb243, 0x0000,
+ 0xd269, 0xd250, 0xd24b, 0xaefe, 0xaf4b, 0xaef7, 0x0000, 0xd258,
+ 0xd25d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xb265, 0xd5e1, 0xd5e5, 0x0000, 0xb252, 0xb250,
+ 0x0000, 0x0000, 0xb247, 0xd5e3, 0xd5e2, 0xb25b, 0x0000, 0xd5e8,
+ 0xb255, 0x0000, 0xd5fa, 0xd647, 0xb244, 0xd5f7, 0xd5f0, 0xb267,
+ 0xd5e0, 0x0000, 0xd5fc, 0x0000, 0xb264, 0xb258, 0xb263, 0xb24e,
+ 0xd5ec, 0xd5fe, 0xd5f6, 0xb24f, 0xb249, 0xd645, 0x0000, 0xd5fd,
+ 0xd640, 0xb251, 0xb259, 0xd642, 0xd5ea, 0xd5fb, 0xd5ef, 0xd644,
+ 0xb25e, 0xb246, 0xb25c, 0xd5f4, 0xd5f2, 0xd5f3, 0xb253, 0xd5ee,
+ 0xd5ed, 0xb248, 0xd5e7, 0xd646, 0xb24a, 0xd5f1, 0xb268, 0x0000,
+ 0xb262, 0xd5e6, 0xb25f, 0xb25d, 0xb266, 0xd5f8, 0xb261, 0xd252,
+ 0xd5f9, 0xb260, 0xd641, 0xb245, 0xd5f5, 0xb257, 0xd5e9, 0xb256,
+ 0x0000, 0xb254, 0xb24c, 0xb24b, 0xd9e7, 0xd643, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_6e[] = {
+ 0xd5eb, 0x0000, 0x0000, 0xd9fc, 0x0000, 0xb24d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb541, 0xb25a, 0xb4ee, 0xd9f6, 0xb4fc, 0x0000, 0xd9ea,
+ 0xb4eb, 0xb4e7, 0xda49, 0xb4ed, 0xb4f1, 0xb4ec, 0xb4f5, 0xda4d,
+ 0xda44, 0x0000, 0x0000, 0xd9f1, 0xb4fa, 0xb4f4, 0xd9fd, 0xb4e4,
+ 0xda4a, 0xda43, 0xb4e8, 0xd9f7, 0xb4f7, 0xda55, 0xda56, 0x0000,
+ 0xb4e5, 0xda48, 0xb4f9, 0xd9fb, 0xd9ed, 0xd9ee, 0xb4fd, 0xd9f2,
+ 0xd9f9, 0xd9f3, 0x0000, 0xb4fb, 0xb544, 0xd9ef, 0xd9e8, 0xd9e9,
+ 0x0000, 0xd9eb, 0xb4ea, 0xd9f8, 0x0000, 0xb4f8, 0xb542, 0x0000,
+ 0x0000, 0xd9fa, 0xda53, 0xda4b, 0xb4e6, 0xda51, 0xb4f2, 0x0000,
+ 0xb4f0, 0x0000, 0xda57, 0xb4ef, 0xda41, 0xd9f4, 0xd9fe, 0xb547,
+ 0xda45, 0xda42, 0xd9f0, 0xb543, 0xda4f, 0xda4c, 0xda54, 0xb4e9,
+ 0xda40, 0xb546, 0x0000, 0xda47, 0x0000, 0x0000, 0xb4f3, 0xb4f6,
+ 0x0000, 0xda46, 0xb545, 0xd9f5, 0xd5e4, 0x0000, 0x0000, 0xda50,
+ 0xda4e, 0xda52, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd9ec, 0xb540, 0x0000, 0x0000, 0x0000, 0xde61, 0xde60, 0xde46,
+ 0xb7bd, 0x0000, 0xde5f, 0xde49, 0xde4a, 0x0000, 0xb7c7, 0xde68,
+ 0xb7c2, 0xde5e, 0x0000, 0xde43, 0xb7c8, 0xb7be, 0xde52, 0xde48,
+ 0xde4b, 0xde63, 0xb7b8, 0xde6a, 0xde62, 0xb7c1, 0xde57, 0xb7cc,
+ 0x0000, 0x0000, 0xb7cb, 0xb7c5, 0x0000, 0x0000, 0xde69, 0xb7b9,
+ 0xde55, 0xde4c, 0xde59, 0xde65, 0xb7cd, 0x0000, 0xb7bb, 0xde54,
+ 0x0000, 0xde4d, 0xb7c4, 0x0000, 0xb7c3, 0xde50, 0xde5a, 0xde64,
+ 0xde47, 0xde51, 0xb7bc, 0xde5b, 0xb7c9, 0xb7c0, 0xde4e, 0xb7bf,
+ 0xde45, 0xde53, 0xde67, 0xb4fe, 0xbab0, 0xde56, 0xe26c, 0xde58,
+ 0xde66, 0xb7c6, 0xde4f, 0xb7ba, 0xb7ca, 0xbcf0, 0xde44, 0x0000,
+ 0xde5d, 0x0000, 0x0000, 0x0000, 0xde5c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe2aa, 0xbaad, 0xe27d, 0xe2a4, 0xbaa2,
+ 0x0000, 0xe26e, 0xbaaf, 0x0000, 0xba77, 0xe26d, 0xe2b0, 0xbab1,
+ 0xe271, 0xe2a3, 0x0000, 0xe273, 0xe2b3, 0xe2af, 0xba75, 0xbaa1
+};
+
+static const unsigned short big5_from_unicode_6f[] = {
+ 0xe653, 0xbaae, 0xba7d, 0xe26f, 0x0000, 0xe2ae, 0xbaa3, 0xe2ab,
+ 0xe2b8, 0xe275, 0xe27e, 0x0000, 0x0000, 0xe2b6, 0xe2ac, 0xba7c,
+ 0x0000, 0x0000, 0xe27c, 0xba76, 0xba74, 0xbaa8, 0x0000, 0x0000,
+ 0xe27a, 0xe277, 0xe278, 0x0000, 0xe2b2, 0x0000, 0xe2b7, 0xe2b5,
+ 0xba7a, 0xe2b9, 0xba7e, 0xbaa7, 0x0000, 0xe270, 0xe5fa, 0xe279,
+ 0x0000, 0xba78, 0xbaac, 0xbaa9, 0xba7b, 0xe2a5, 0xe274, 0xbaaa,
+ 0xe2a7, 0xbaa4, 0xbaa6, 0xba73, 0x0000, 0xe2a9, 0xe2a1, 0xe272,
+ 0xbaa5, 0xe2b1, 0xe2b4, 0xe27b, 0xe2a8, 0x0000, 0xba79, 0xbcdf,
+ 0xe2a6, 0xe5f9, 0x0000, 0xe2ad, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe276, 0xe644,
+ 0xe64e, 0xbce2, 0xe64d, 0xe659, 0xbce4, 0xe64b, 0x0000, 0xe64f,
+ 0xbcef, 0x0000, 0xe646, 0xbce7, 0x0000, 0xe652, 0xe9f0, 0xbcf3,
+ 0xbcf2, 0xe654, 0xe643, 0xe65e, 0xbced, 0x0000, 0xbce3, 0xe657,
+ 0x0000, 0xe65b, 0xe660, 0xe655, 0xe649, 0xbce6, 0xbce9, 0xbcf1,
+ 0xbcec, 0x0000, 0xe64c, 0xe2a2, 0x0000, 0x0000, 0xe648, 0xe65f,
+ 0xbce8, 0x0000, 0xbceb, 0xe661, 0xbce0, 0xe656, 0xe5fb, 0xe65c,
+ 0xc0df, 0x0000, 0xe64a, 0x0000, 0xbce1, 0xe645, 0xbce5, 0xe5fc,
+ 0xbaab, 0xe641, 0x0000, 0xe65a, 0xe642, 0xe640, 0xbcea, 0x0000,
+ 0xe658, 0x0000, 0xe5fe, 0xe651, 0xe650, 0xe65d, 0xe647, 0xbcee,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe9f3, 0x0000,
+ 0xbf49, 0xbefe, 0xea40, 0xe9eb, 0xbf41, 0xe9f7, 0xbf48, 0xbf43,
+ 0xe9f5, 0xed4f, 0xe9fb, 0xea42, 0xe9fa, 0xe9e9, 0xe9f8, 0xea44,
+ 0xea46, 0xbefd, 0xea45, 0xbf44, 0xbf4a, 0x0000, 0xbf47, 0x0000,
+ 0xe9fe, 0xbf46, 0xe9f9, 0x0000, 0xe9ed, 0xe9f2, 0x0000, 0xe9fd,
+ 0xbf45, 0xbf42, 0xbefc, 0xbf40, 0xe9f1, 0x0000, 0xe5fd, 0xe9ec,
+ 0xe9ef, 0xea41, 0xe9f4, 0xe9ea, 0xed4e, 0xea43, 0xe9ee, 0xe9fc,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xed51, 0xc0e3, 0x0000, 0x0000,
+ 0xc0d7, 0x0000, 0x0000, 0xc0db, 0xed53, 0xed59, 0xed57, 0xc0d9,
+ 0xc0da, 0xc0e1, 0xed5a, 0xed52, 0xc0dc, 0x0000, 0xed56, 0xed55,
+ 0xed5b, 0xc0e2, 0x0000, 0xc0dd, 0xc0e0, 0xed54, 0xc0e4, 0xc0de,
+ 0xc0e5, 0xc0d8, 0xed58, 0x0000, 0xed50, 0x0000, 0x0000, 0xeff7,
+ 0x0000, 0x0000, 0xc271, 0xeff4, 0xeff6, 0x0000, 0xc26f, 0xeff2
+};
+
+static const unsigned short big5_from_unicode_70[] = {
+ 0xeff3, 0xefee, 0x0000, 0x0000, 0xe9f6, 0xefef, 0xc270, 0xefeb,
+ 0x0000, 0xc26d, 0xeff8, 0xc26e, 0xefec, 0xefed, 0xeff1, 0xc273,
+ 0x0000, 0xc272, 0x0000, 0x0000, 0xeff0, 0xc378, 0xf25f, 0xf265,
+ 0xc379, 0xf25c, 0xc376, 0xc373, 0xf267, 0xc377, 0x0000, 0xc374,
+ 0xf25e, 0xf261, 0xf262, 0xf263, 0xf266, 0x0000, 0xeff5, 0xf25d,
+ 0xc375, 0xf264, 0xf268, 0xf260, 0x0000, 0x0000, 0x0000, 0xf45d,
+ 0xc46a, 0xf460, 0xc46b, 0xf468, 0xf45f, 0xf45c, 0x0000, 0xf45e,
+ 0xf462, 0xf465, 0xf464, 0xf467, 0xf45b, 0x0000, 0xc469, 0xf463,
+ 0xf466, 0xf469, 0xf461, 0xf5d3, 0xf5d4, 0xf5d8, 0xf5d9, 0x0000,
+ 0xf5d6, 0xf5d7, 0xf5d5, 0x0000, 0xc4e9, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc578, 0xf6eb, 0x0000, 0x0000, 0xf6e8, 0xf6e9, 0xf6ea,
+ 0xc579, 0x0000, 0xf7e5, 0xf7e4, 0x0000, 0xf8af, 0xc5f4, 0xf8ad,
+ 0xf8b0, 0xf8ae, 0xf8f5, 0xc657, 0xc665, 0xf9a3, 0xf96c, 0x0000,
+ 0xf9a2, 0xf9d0, 0xf9d1, 0xa4f5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa6c7, 0xca41, 0x0000, 0x0000, 0xcb5e, 0x0000, 0xa85f, 0x0000,
+ 0xa862, 0x0000, 0xcb5f, 0x0000, 0xa860, 0xa861, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xcd58, 0xcd5a, 0xcd55, 0xcd52, 0xcd54, 0x0000,
+ 0x0000, 0x0000, 0xaaa4, 0x0000, 0x0000, 0x0000, 0xaaa2, 0x0000,
+ 0x0000, 0xcd56, 0xaaa3, 0xcd53, 0xcd50, 0xaaa1, 0xcd57, 0x0000,
+ 0xcd51, 0xaaa5, 0xcd59, 0x0000, 0x0000, 0x0000, 0x0000, 0xcfaf,
+ 0x0000, 0xcfb3, 0x0000, 0x0000, 0xacb7, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xcfb6, 0x0000, 0xacaf, 0xacb2, 0xacb4, 0xacb6, 0xacb3,
+ 0xcfb2, 0xcfb1, 0x0000, 0xacb1, 0xcfb4, 0xcfb5, 0x0000, 0xcfae,
+ 0xacb5, 0x0000, 0xacb0, 0x0000, 0x0000, 0x0000, 0xcfb0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd277, 0xd278, 0xd279,
+ 0xaf50, 0x0000, 0xaf4c, 0xd26e, 0x0000, 0xd276, 0xd27b, 0xaf51,
+ 0x0000, 0xd26c, 0xd272, 0xd26b, 0xd275, 0x0000, 0x0000, 0xd271,
+ 0xaf4d, 0xaf4f, 0xd27a, 0x0000, 0xd26a, 0xd26d, 0xd273, 0x0000,
+ 0xd274, 0xd27c, 0xd270, 0x0000, 0xaf4e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb26d,
+ 0xd64e, 0x0000, 0x0000, 0xd650, 0xd64c, 0x0000, 0xd658, 0xd64a,
+ 0xd657, 0xb269, 0xd648, 0xda5b, 0xd652, 0xb26c, 0x0000, 0xd653
+};
+
+static const unsigned short big5_from_unicode_71[] = {
+ 0xd656, 0x0000, 0xd65a, 0x0000, 0xd64f, 0x0000, 0xd654, 0x0000,
+ 0x0000, 0xb26a, 0xb26b, 0xd659, 0xd64d, 0xd649, 0xd65b, 0x0000,
+ 0xd651, 0x0000, 0x0000, 0xd655, 0x0000, 0x0000, 0x0000, 0xd64b,
+ 0x0000, 0xb548, 0xb549, 0xda65, 0xb54f, 0x0000, 0xda59, 0xda62,
+ 0xda58, 0xb54c, 0xda60, 0xda5e, 0x0000, 0xda5f, 0xb54a, 0x0000,
+ 0xda63, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xda5c, 0xda5a,
+ 0xb54b, 0xda5d, 0xda61, 0x0000, 0x0000, 0x0000, 0xb54d, 0x0000,
+ 0x0000, 0x0000, 0xda64, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xde70, 0xde77, 0xde79, 0xdea1, 0x0000, 0xb7da, 0xde6b,
+ 0x0000, 0xb7d2, 0x0000, 0xde7a, 0xb7d7, 0xdea2, 0xb7ce, 0x0000,
+ 0xde7d, 0x0000, 0xde6d, 0xde7e, 0xde6c, 0x0000, 0xb7dc, 0x0000,
+ 0xde78, 0xb7cf, 0xdea3, 0x0000, 0xb7d4, 0xde71, 0xb7d9, 0xde7c,
+ 0xde6f, 0xde76, 0xde72, 0xde6e, 0xb7d1, 0xb7d8, 0xb7d6, 0xb7d3,
+ 0xb7db, 0xb7d0, 0xde75, 0x0000, 0xb7d5, 0x0000, 0xb54e, 0x0000,
+ 0xde7b, 0x0000, 0xde73, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xde74, 0x0000, 0x0000, 0xe2c1, 0x0000, 0xbab4, 0x0000, 0x0000,
+ 0xe2bd, 0xe2c3, 0xe2bf, 0x0000, 0xbab6, 0xe2be, 0xe2c2, 0xe2ba,
+ 0x0000, 0xe2bc, 0xbab5, 0x0000, 0x0000, 0x0000, 0x0000, 0xe2c0,
+ 0xe2bb, 0x0000, 0xbab7, 0x0000, 0xbab2, 0x0000, 0x0000, 0xe2c4,
+ 0x0000, 0xbab3, 0xe667, 0xe664, 0xe670, 0xe66a, 0xe66c, 0xbcf4,
+ 0xe666, 0xe66e, 0x0000, 0x0000, 0xe66d, 0xe66b, 0x0000, 0xe671,
+ 0xbcf7, 0xe668, 0xe66f, 0x0000, 0xbcf5, 0x0000, 0x0000, 0xe663,
+ 0xe665, 0xbcf6, 0xe662, 0xe672, 0x0000, 0xe669, 0x0000, 0x0000,
+ 0xea4a, 0xbf51, 0x0000, 0x0000, 0xea55, 0xea53, 0xbf4b, 0xea49,
+ 0xea4c, 0xea4d, 0xea48, 0xbf55, 0xbf56, 0xea47, 0xea56, 0xea51,
+ 0xbf4f, 0xbf4c, 0xea50, 0xea4e, 0x0000, 0x0000, 0xbf52, 0xea52,
+ 0xbf4d, 0x0000, 0xbf4e, 0x0000, 0xea4f, 0xbf50, 0xea4b, 0x0000,
+ 0xea54, 0xbf53, 0xea57, 0xea58, 0xbf54, 0x0000, 0x0000, 0xc0e7,
+ 0xc0ee, 0xed5c, 0xed62, 0x0000, 0xed60, 0xc0ea, 0xc0e9, 0xc0e6,
+ 0xed5e, 0x0000, 0x0000, 0x0000, 0xc0ec, 0xc0eb, 0xc0e8, 0x0000,
+ 0xed61, 0xed5d, 0xed5f, 0x0000, 0xc0ed, 0x0000, 0x0000, 0x0000,
+ 0xc277, 0xeffb, 0x0000, 0xc274, 0xc275, 0xeffd, 0xc276, 0xeffa
+};
+
+static const unsigned short big5_from_unicode_72[] = {
+ 0x0000, 0xeff9, 0xf26c, 0xeffc, 0x0000, 0xf26d, 0xc37a, 0xf26b,
+ 0x0000, 0x0000, 0xf26a, 0x0000, 0xf269, 0xc37b, 0x0000, 0x0000,
+ 0xc46c, 0x0000, 0x0000, 0xf46a, 0xf46b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf5dc, 0xf5db, 0xc4ea, 0x0000, 0xf5da, 0xf6ec, 0xf6ed,
+ 0x0000, 0x0000, 0xf7e6, 0xf8b1, 0x0000, 0x0000, 0xf8f6, 0xf9bc,
+ 0xc679, 0xf9c6, 0xa4f6, 0x0000, 0xaaa6, 0xaaa7, 0x0000, 0x0000,
+ 0xacb8, 0x0000, 0x0000, 0x0000, 0x0000, 0xc0ef, 0xa4f7, 0x0000,
+ 0xaaa8, 0xaf52, 0xb7dd, 0xa4f8, 0x0000, 0xb26e, 0xbab8, 0xc962,
+ 0x0000, 0xcfb7, 0xd27d, 0x0000, 0xe2c5, 0x0000, 0xc0f0, 0xa4f9,
+ 0xaaa9, 0xcfb8, 0xcfb9, 0xda66, 0xb550, 0x0000, 0x0000, 0xdea4,
+ 0x0000, 0x0000, 0xb7de, 0xe2c6, 0x0000, 0x0000, 0xbcf8, 0x0000,
+ 0xc37c, 0xa4fa, 0xda67, 0xa4fb, 0x0000, 0xa6c9, 0xca42, 0xa6c8,
+ 0xa865, 0xa864, 0xa863, 0xcb60, 0x0000, 0x0000, 0x0000, 0xaaaa,
+ 0x0000, 0xaaab, 0xcd5b, 0x0000, 0xcfba, 0x0000, 0xcfbd, 0xacba,
+ 0xcfbb, 0x0000, 0xacb9, 0xcfbc, 0xacbb, 0x0000, 0xd2a2, 0xd2a1,
+ 0xd27e, 0xaf53, 0x0000, 0xd65d, 0xd65e, 0xb26f, 0xd65c, 0xd65f,
+ 0xb552, 0xb270, 0x0000, 0x0000, 0xb551, 0xda6b, 0xda6a, 0x0000,
+ 0xda68, 0xda69, 0x0000, 0xda6c, 0xdea6, 0xdea5, 0xdea9, 0x0000,
+ 0xdea8, 0xdea7, 0xbab9, 0xe2c9, 0x0000, 0xe2c8, 0xbaba, 0xe2c7,
+ 0xe673, 0x0000, 0xe674, 0xbcf9, 0x0000, 0xea59, 0xea5a, 0x0000,
+ 0x0000, 0xf272, 0xc37d, 0xf271, 0xf270, 0xf26e, 0xf26f, 0xc4eb,
+ 0xf46c, 0xf6ee, 0xf8f7, 0x0000, 0xa4fc, 0x0000, 0xc9a5, 0xa5c7,
+ 0xc9a6, 0x0000, 0x0000, 0x0000, 0xca43, 0xca44, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xcb66, 0x0000, 0x0000, 0xcb62, 0x0000, 0xcb61,
+ 0xaaac, 0xcb65, 0xa867, 0xcb63, 0xa866, 0xcb67, 0xcb64, 0x0000,
+ 0x0000, 0xcd5f, 0xcfbe, 0xcd5d, 0xcd64, 0x0000, 0xaaad, 0x0000,
+ 0xaab0, 0xcd65, 0xcd61, 0x0000, 0xcd62, 0x0000, 0xcd5c, 0xaaaf,
+ 0xcd5e, 0xaaae, 0xcd63, 0x0000, 0xcd60, 0x0000, 0x0000, 0xcfc2,
+ 0xacbd, 0xacbe, 0x0000, 0xcfc5, 0xcfbf, 0x0000, 0xcfc4, 0x0000,
+ 0xcfc0, 0xacbc, 0xcfc3, 0xcfc1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xd2a8, 0xd2a5, 0x0000, 0xd2a7, 0xaf58,
+ 0xaf57, 0xaf55, 0xd2a4, 0xd2a9, 0xaf54, 0xaf56, 0xd2a6, 0xd667
+};
+
+static const unsigned short big5_from_unicode_73[] = {
+ 0xd2a3, 0xd2aa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd662,
+ 0xd666, 0x0000, 0xd665, 0xda6e, 0xda79, 0x0000, 0x0000, 0xd668,
+ 0x0000, 0xd663, 0xda6d, 0xb274, 0x0000, 0x0000, 0xb273, 0xd661,
+ 0xd664, 0xb275, 0x0000, 0xb272, 0xb271, 0xd660, 0xd669, 0x0000,
+ 0x0000, 0x0000, 0xda70, 0xda77, 0x0000, 0xb554, 0xda76, 0xda73,
+ 0x0000, 0xb556, 0x0000, 0x0000, 0x0000, 0xda75, 0x0000, 0x0000,
+ 0xda6f, 0xda71, 0xda74, 0xda72, 0xb555, 0xda78, 0xb553, 0xb7df,
+ 0x0000, 0x0000, 0xdead, 0xdeac, 0xdeaa, 0x0000, 0xb7e2, 0xb7e1,
+ 0xdeae, 0x0000, 0xdeab, 0xe2ca, 0xbabb, 0xb7e0, 0x0000, 0x0000,
+ 0x0000, 0xdeb0, 0xdeaf, 0x0000, 0xe2cd, 0xe2cb, 0xbcfa, 0x0000,
+ 0xbabc, 0xe2cc, 0xe676, 0x0000, 0x0000, 0x0000, 0x0000, 0xbcfb,
+ 0xe675, 0xe67e, 0xe67d, 0xe67b, 0x0000, 0xe67a, 0xe677, 0xe678,
+ 0xe679, 0xe67c, 0xe6a1, 0x0000, 0x0000, 0xea5f, 0xea5c, 0xea5d,
+ 0xbf57, 0xea5b, 0xea61, 0xea60, 0xea5e, 0x0000, 0xed64, 0xed65,
+ 0xc0f1, 0x0000, 0xc0f2, 0xed63, 0x0000, 0xc279, 0xeffe, 0xc278,
+ 0xc37e, 0x0000, 0xc3a1, 0xc46d, 0xf46e, 0xf46d, 0xf5dd, 0xf6ef,
+ 0xc57a, 0xf7e8, 0xf7e7, 0xf7e9, 0xa5c8, 0xcfc6, 0xaf59, 0xb276,
+ 0xd66a, 0xa5c9, 0xc9a7, 0xa4fd, 0x0000, 0x0000, 0xca45, 0x0000,
+ 0x0000, 0x0000, 0xcb6c, 0xcb6a, 0xcb6b, 0xcb68, 0xa868, 0xcb69,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xcd6d, 0x0000, 0xaab3,
+ 0xcd6b, 0xcd67, 0xcd6a, 0x0000, 0xcd66, 0xaab5, 0xcd69, 0x0000,
+ 0xaab2, 0xaab1, 0x0000, 0xaab4, 0xcd6c, 0xcd68, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xacc2, 0xacc5, 0xcfce, 0xcfcd, 0xcfcc, 0xacbf,
+ 0xcfd5, 0xcfcb, 0x0000, 0xacc1, 0xd2af, 0x0000, 0xcfd2, 0xcfd0,
+ 0xacc4, 0x0000, 0xcfc8, 0xcfd3, 0x0000, 0xcfca, 0xcfd4, 0xcfd1,
+ 0xcfc9, 0x0000, 0xacc0, 0xcfd6, 0xcfc7, 0xacc3, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd2b4, 0xd2ab, 0xd2b6, 0x0000, 0xd2ae, 0xd2b9,
+ 0xd2ba, 0xd2ac, 0xd2b8, 0xd2b5, 0xd2b3, 0xd2b7, 0xaf5f, 0x0000,
+ 0xaf5d, 0x0000, 0x0000, 0xd2b1, 0x0000, 0xd2ad, 0x0000, 0xd2b0,
+ 0xd2bb, 0xd2b2, 0xaf5e, 0xcfcf, 0x0000, 0xaf5a, 0xaf5c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd678, 0xd66d, 0xd66b, 0x0000,
+ 0xd66c, 0x0000, 0xd673, 0x0000, 0xd674, 0xd670, 0xb27b, 0xd675
+};
+
+static const unsigned short big5_from_unicode_74[] = {
+ 0xd672, 0xd66f, 0x0000, 0xb279, 0xd66e, 0xb277, 0xb27a, 0xd671,
+ 0xd679, 0xaf5b, 0xb278, 0xd677, 0xd676, 0xb27c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xda7e, 0x0000,
+ 0x0000, 0x0000, 0xdaa1, 0xb560, 0x0000, 0xdaa7, 0x0000, 0x0000,
+ 0xdaa9, 0xdaa2, 0xb55a, 0xdaa6, 0xdaa5, 0xb55b, 0xb561, 0x0000,
+ 0xb562, 0xdaa8, 0xb558, 0xda7d, 0xda7b, 0xdaa3, 0xda7a, 0xb55f,
+ 0xda7c, 0xdaa4, 0xdaaa, 0xb559, 0xb55e, 0xb55c, 0xb55d, 0x0000,
+ 0x0000, 0x0000, 0xb557, 0x0000, 0x0000, 0x0000, 0x0000, 0xb7e9,
+ 0xdeb7, 0xb7e8, 0xdebb, 0x0000, 0xdeb1, 0x0000, 0xdebc, 0x0000,
+ 0x0000, 0x0000, 0xdeb2, 0xdeb3, 0x0000, 0xdebd, 0xdeba, 0xdeb8,
+ 0xdeb9, 0xdeb5, 0xdeb4, 0x0000, 0xdebe, 0xb7e5, 0x0000, 0xdeb6,
+ 0x0000, 0xb7ea, 0xb7e4, 0xb7eb, 0x0000, 0x0000, 0xb7e7, 0xb7e6,
+ 0x0000, 0x0000, 0xe2ce, 0xbabe, 0xbabd, 0x0000, 0x0000, 0xe2d3,
+ 0x0000, 0xbcfc, 0xbabf, 0x0000, 0x0000, 0xbac1, 0xe2d4, 0xb7e3,
+ 0xbac0, 0xe2d0, 0xe2d2, 0xe2cf, 0x0000, 0xe2d1, 0x0000, 0x0000,
+ 0x0000, 0xe6ab, 0x0000, 0x0000, 0xe6aa, 0xe6a7, 0xbd40, 0xea62,
+ 0xbd41, 0xe6a6, 0x0000, 0xbcfe, 0x0000, 0xe6a8, 0xe6a5, 0xe6a2,
+ 0xe6a9, 0xe6a3, 0xe6a4, 0xbcfd, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xed69, 0x0000, 0xea66, 0x0000, 0xea65, 0xea67, 0x0000, 0xed66,
+ 0xbf5a, 0x0000, 0xea63, 0x0000, 0xbf58, 0x0000, 0xbf5c, 0xbf5b,
+ 0xea64, 0xea68, 0x0000, 0xbf59, 0x0000, 0xed6d, 0xc0f5, 0xc27a,
+ 0xc0f6, 0xc0f3, 0xed6a, 0xed68, 0x0000, 0xed6b, 0x0000, 0xed6e,
+ 0xc0f4, 0xed6c, 0xed67, 0x0000, 0x0000, 0xf042, 0xf045, 0xf275,
+ 0xf040, 0x0000, 0xf46f, 0xf046, 0x0000, 0xc3a2, 0xf044, 0xc27b,
+ 0xf041, 0xf043, 0xf047, 0xf276, 0x0000, 0xf274, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xc3a3, 0xf273, 0x0000, 0x0000, 0x0000, 0xc46e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xc4ed, 0xf6f1, 0xc4ec, 0xf6f3,
+ 0xf6f0, 0xf6f2, 0xc5d0, 0xf8b2, 0xa5ca, 0xcd6e, 0xd2bc, 0xd2bd,
+ 0xb27d, 0xdebf, 0xbf5d, 0xc3a4, 0xc57b, 0xf8b3, 0xa5cb, 0x0000,
+ 0xcd6f, 0xa260, 0x0000, 0x0000, 0xcfd7, 0x0000, 0xcfd8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd2be, 0xd2bf, 0xb27e, 0xb2a1,
+ 0x0000, 0x0000, 0x0000, 0xdaab, 0x0000, 0xdec2, 0xdec1, 0xdec0
+};
+
+static const unsigned short big5_from_unicode_75[] = {
+ 0xe2d5, 0x0000, 0xe2d6, 0xe2d7, 0xbac2, 0x0000, 0x0000, 0xe6ad,
+ 0xe6ac, 0x0000, 0x0000, 0xea69, 0xbf5e, 0xbf5f, 0x0000, 0xed72,
+ 0xed6f, 0xed70, 0xed71, 0xf049, 0xf048, 0xc27c, 0xf277, 0xf5de,
+ 0xa5cc, 0x0000, 0xacc6, 0x0000, 0xb2a2, 0xdec3, 0x0000, 0xa5cd,
+ 0x0000, 0xd2c0, 0xb2a3, 0x0000, 0x0000, 0xb563, 0xb564, 0x0000,
+ 0xa5ce, 0xa5cf, 0xca46, 0xa86a, 0xa869, 0xacc7, 0xcfd9, 0xdaac,
+ 0xa5d0, 0xa5d1, 0xa5d2, 0xa5d3, 0x0000, 0x0000, 0x0000, 0xa86b,
+ 0xa86c, 0xcb6e, 0xcb6d, 0x0000, 0x0000, 0xaab6, 0xcd72, 0xcd70,
+ 0xcd71, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xcfda,
+ 0xcfdb, 0x0000, 0x0000, 0xaccb, 0xacc9, 0x0000, 0xacca, 0xacc8,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xaf60, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xaf64, 0xaf63, 0xd2c1, 0xaf62, 0xaf61, 0x0000, 0xd2c2,
+ 0x0000, 0x0000, 0xb2a6, 0xd67b, 0xd67a, 0xb2a4, 0xb2a5, 0x0000,
+ 0x0000, 0x0000, 0xb566, 0xb565, 0xdaae, 0x0000, 0x0000, 0xdaad,
+ 0xb2a7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb7ed, 0xdec5,
+ 0xb7ee, 0xdec4, 0x0000, 0x0000, 0x0000, 0xe2d8, 0xe6ae, 0xbd42,
+ 0xea6a, 0x0000, 0x0000, 0x0000, 0xed73, 0x0000, 0xc3a6, 0xc3a5,
+ 0x0000, 0x0000, 0xc57c, 0xa5d4, 0xcd73, 0x0000, 0x0000, 0xb2a8,
+ 0xe2d9, 0xbac3, 0x0000, 0x0000, 0xcb6f, 0xcb70, 0x0000, 0x0000,
+ 0xcd74, 0xaab8, 0xaab9, 0x0000, 0x0000, 0xaab7, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xaccf, 0xacd0, 0xaccd, 0xacce, 0x0000, 0xcfdc,
+ 0x0000, 0x0000, 0xcfdd, 0xaccc, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd2c3, 0x0000, 0xaf68, 0xaf69, 0x0000, 0xb2ab, 0xd2c9, 0x0000,
+ 0xaf6e, 0xaf6c, 0xd2ca, 0xd2c5, 0xaf6b, 0xaf6a, 0xaf65, 0xd2c8,
+ 0xd2c7, 0xd2c4, 0xaf6d, 0x0000, 0xd2c6, 0xaf66, 0x0000, 0xaf67,
+ 0x0000, 0x0000, 0xb2ac, 0xd6a1, 0xd6a2, 0xb2ad, 0xd67c, 0xd67e,
+ 0xd6a4, 0xd6a3, 0xd67d, 0x0000, 0xb2a9, 0xb2aa, 0x0000, 0xdab6,
+ 0xb56b, 0xb56a, 0xdab0, 0xb568, 0x0000, 0xdab3, 0xb56c, 0xdab4,
+ 0xb56d, 0xdab1, 0xb567, 0xb569, 0xdab5, 0x0000, 0xdab2, 0xdaaf,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xded2, 0x0000, 0xdec7,
+ 0xb7f0, 0xb7f3, 0xb7f2, 0xb7f7, 0xb7f6, 0xded3, 0xded1, 0xdeca,
+ 0xdece, 0xdecd, 0xb7f4, 0xded0, 0xdecc, 0xded4, 0xdecb, 0xb7f5
+};
+
+static const unsigned short big5_from_unicode_76[] = {
+ 0xb7ef, 0xb7f1, 0x0000, 0xdec9, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe2db, 0xbac7, 0xe2df, 0xbac6, 0xe2dc, 0xbac5, 0x0000, 0xdec8,
+ 0xdecf, 0xe2de, 0x0000, 0xbac8, 0xe2e0, 0xe2dd, 0xe2da, 0x0000,
+ 0x0000, 0xe6b1, 0xe6b5, 0xe6b7, 0xe6b3, 0xe6b2, 0xe6b0, 0xbd45,
+ 0xbd43, 0xbd48, 0xbd49, 0xe6b4, 0xbd46, 0xe6af, 0xbd47, 0xbac4,
+ 0xe6b6, 0xbd44, 0x0000, 0x0000, 0x0000, 0xea6c, 0x0000, 0xea6b,
+ 0xea73, 0xea6d, 0xea72, 0xea6f, 0xbf60, 0xea71, 0x0000, 0x0000,
+ 0xbf61, 0x0000, 0xbf62, 0x0000, 0xea70, 0xea6e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xc0f8, 0xed74, 0x0000, 0x0000, 0xc0f7, 0xed77,
+ 0xed75, 0xed76, 0x0000, 0x0000, 0xc0f9, 0x0000, 0x0000, 0x0000,
+ 0xf04d, 0x0000, 0xc2a1, 0xf04e, 0x0000, 0x0000, 0xc27d, 0xf04f,
+ 0xc27e, 0xf04c, 0xf050, 0x0000, 0xf04a, 0x0000, 0x0000, 0xc3a7,
+ 0xf278, 0xc3a8, 0xc46f, 0x0000, 0xf04b, 0xc470, 0x0000, 0x0000,
+ 0x0000, 0xc4ee, 0xf5df, 0x0000, 0xc57e, 0xf6f4, 0xc57d, 0x0000,
+ 0xf7ea, 0xc5f5, 0xc5f6, 0x0000, 0x0000, 0xf9cc, 0x0000, 0x0000,
+ 0xacd1, 0xcfde, 0x0000, 0xb56e, 0xb56f, 0xa5d5, 0xa6ca, 0xca47,
+ 0x0000, 0xcb71, 0xa86d, 0x0000, 0xaaba, 0x0000, 0xacd2, 0xacd3,
+ 0xacd4, 0xd6a6, 0xd2cb, 0xaf6f, 0x0000, 0x0000, 0xb2ae, 0xd6a5,
+ 0x0000, 0x0000, 0xdab8, 0xb571, 0x0000, 0xdab7, 0xb570, 0x0000,
+ 0x0000, 0xded5, 0xbd4a, 0xe6bb, 0xe6b8, 0xe6b9, 0xe6ba, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xed78, 0x0000, 0xf051, 0x0000,
+ 0x0000, 0x0000, 0xf471, 0xf470, 0x0000, 0xf6f5, 0xa5d6, 0xcd75,
+ 0xaf70, 0x0000, 0x0000, 0x0000, 0xb572, 0xded6, 0x0000, 0x0000,
+ 0xe2e1, 0x0000, 0xbd4b, 0xea74, 0x0000, 0xf052, 0xf472, 0xa5d7,
+ 0x0000, 0x0000, 0xaabb, 0xacd7, 0xcfdf, 0xacd8, 0xacd6, 0x0000,
+ 0xacd5, 0xd2cc, 0xaf71, 0x0000, 0x0000, 0xaf72, 0xaf73, 0x0000,
+ 0x0000, 0x0000, 0xb2b0, 0xd6a7, 0xb2af, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xdab9, 0xb2b1, 0xb573, 0xded7, 0xb7f8, 0xb7f9,
+ 0x0000, 0xbac9, 0x0000, 0xbaca, 0xbd4c, 0xbf64, 0xea75, 0xbf63,
+ 0x0000, 0xed79, 0xc0fa, 0x0000, 0xf053, 0xf473, 0xa5d8, 0xa86e,
+ 0xcd78, 0xcd77, 0xaabc, 0xcd76, 0xaabd, 0xcd79, 0x0000, 0xcfe5,
+ 0xacdb, 0xacda, 0xcfe7, 0xcfe6, 0xacdf, 0x0000, 0xacde, 0x0000
+};
+
+static const unsigned short big5_from_unicode_77[] = {
+ 0x0000, 0xacd9, 0x0000, 0xcfe1, 0xcfe2, 0xcfe3, 0x0000, 0xace0,
+ 0xcfe0, 0xacdc, 0xcfe4, 0xacdd, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd2cf, 0xd2d3, 0xd2d1, 0xd2d0, 0x0000, 0xd2d4, 0x0000, 0x0000,
+ 0x0000, 0xd2d5, 0xd2d6, 0xd2ce, 0x0000, 0xd2cd, 0x0000, 0xaf75,
+ 0xaf76, 0x0000, 0xd2d7, 0xd2d2, 0x0000, 0xd6b0, 0x0000, 0xd2d8,
+ 0xaf77, 0xaf74, 0x0000, 0x0000, 0x0000, 0xd6aa, 0x0000, 0xd6a9,
+ 0x0000, 0xd6ab, 0xd6ac, 0xd6ae, 0xd6ad, 0xd6b2, 0xb2b5, 0xb2b2,
+ 0xb2b6, 0xd6a8, 0xb2b7, 0xd6b1, 0xb2b4, 0xd6af, 0xb2b3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xdabc, 0xdabe, 0xdaba, 0xdabb,
+ 0x0000, 0x0000, 0xdabf, 0xdac1, 0xdac2, 0xdabd, 0xdac0, 0xb574,
+ 0x0000, 0x0000, 0xdedb, 0x0000, 0xdee0, 0xded8, 0xdedc, 0x0000,
+ 0x0000, 0xdee1, 0xdedd, 0xb7fa, 0xb843, 0x0000, 0xb7fd, 0xded9,
+ 0xdeda, 0xbace, 0xb846, 0xb7fe, 0x0000, 0xb844, 0xb7fc, 0xdedf,
+ 0xb845, 0xdede, 0xb841, 0xb7fb, 0xb842, 0xdee2, 0xe2e6, 0xe2e8,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb840, 0x0000, 0x0000, 0xe2e3, 0xbacc, 0xe2e9, 0xbacd,
+ 0xe2e7, 0xe2e2, 0xe2e5, 0xe2ea, 0xbacb, 0xe2e4, 0x0000, 0xbd4e,
+ 0xe6bf, 0xe6be, 0x0000, 0xbd51, 0xbd4f, 0xe6bc, 0xbd4d, 0xe6bd,
+ 0x0000, 0xbd50, 0x0000, 0x0000, 0x0000, 0xea7d, 0x0000, 0xeaa1,
+ 0x0000, 0xea7e, 0xea76, 0xea7a, 0xea79, 0xea77, 0xbf66, 0xbf67,
+ 0xbf65, 0xea78, 0xea7b, 0xea7c, 0x0000, 0xbf68, 0x0000, 0xc140,
+ 0xeda3, 0x0000, 0xc0fc, 0xed7b, 0xc0fe, 0xc141, 0x0000, 0x0000,
+ 0xc0fd, 0xeda2, 0xed7c, 0xc0fb, 0xeda1, 0xed7a, 0xed7e, 0xed7d,
+ 0x0000, 0x0000, 0xf055, 0xc2a4, 0xc2a5, 0xc2a2, 0x0000, 0xc2a3,
+ 0x0000, 0x0000, 0xf054, 0x0000, 0xf27b, 0x0000, 0x0000, 0xc3a9,
+ 0x0000, 0xf279, 0xf27a, 0x0000, 0xf474, 0xf477, 0xf475, 0xf476,
+ 0xf5e0, 0x0000, 0x0000, 0xc4ef, 0xf7eb, 0xf8b4, 0x0000, 0xc5f7,
+ 0xf8f8, 0xf8f9, 0xc666, 0xa5d9, 0xace1, 0x0000, 0xdac3, 0x0000,
+ 0xdee3, 0x0000, 0xa5da, 0xa86f, 0x0000, 0xaabe, 0x0000, 0xcfe8,
+ 0xcfe9, 0xaf78, 0x0000, 0x0000, 0xdac4, 0xb575, 0xb847, 0xc142,
+ 0xeda4, 0xf27c, 0xf478, 0xa5db, 0x0000, 0x0000, 0x0000, 0xcda1,
+ 0xcd7a, 0xcd7c, 0xcd7e, 0xcd7d, 0xcd7b, 0xaabf, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_78[] = {
+ 0x0000, 0x0000, 0xace2, 0xcff2, 0x0000, 0xcfed, 0xcfea, 0x0000,
+ 0x0000, 0xcff1, 0x0000, 0x0000, 0xace4, 0xace5, 0xcff0, 0xcfef,
+ 0xcfee, 0xcfeb, 0xcfec, 0xcff3, 0xace3, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xaf7c, 0x0000, 0xafa4,
+ 0xafa3, 0xd2e1, 0xd2db, 0xd2d9, 0x0000, 0xafa1, 0xd6b9, 0xaf7a,
+ 0xd2de, 0xd2e2, 0xd2e4, 0xd2e0, 0xd2da, 0xafa2, 0xd2df, 0xd2dd,
+ 0xaf79, 0xd2e5, 0xafa5, 0xd2e3, 0xaf7d, 0xd2dc, 0x0000, 0xaf7e,
+ 0xaf7b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xb2b9, 0x0000, 0xd6ba, 0x0000, 0x0000,
+ 0xd6b3, 0xd6b5, 0xd6b7, 0x0000, 0xd6b8, 0xd6b6, 0xb2ba, 0x0000,
+ 0xd6bb, 0x0000, 0xd6b4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xdac8, 0xb576, 0xdad0, 0x0000,
+ 0xdac5, 0x0000, 0xdad1, 0x0000, 0xdac6, 0xdac7, 0x0000, 0x0000,
+ 0xdacf, 0xdace, 0xdacb, 0xb2b8, 0xb577, 0xdac9, 0xdacc, 0xb578,
+ 0xdacd, 0xdaca, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xdeee, 0x0000, 0xdef2, 0xb84e, 0x0000, 0xe2f0, 0xb851,
+ 0xdef0, 0x0000, 0x0000, 0xdeed, 0xdee8, 0xdeea, 0xdeeb, 0xdee4,
+ 0x0000, 0xb84d, 0x0000, 0x0000, 0xb84c, 0x0000, 0xb848, 0xdee7,
+ 0x0000, 0xb84f, 0x0000, 0xb850, 0xdee6, 0xdee9, 0xdef1, 0xb84a,
+ 0xb84b, 0xdeef, 0xdee5, 0x0000, 0x0000, 0x0000, 0xe2f2, 0xbad0,
+ 0xe2f4, 0xdeec, 0xe2f6, 0xbad4, 0xe2f7, 0xe2f3, 0x0000, 0xbad1,
+ 0xe2ef, 0xbad3, 0xe2ec, 0xe2f1, 0xe2f5, 0xe2ee, 0x0000, 0x0000,
+ 0xb849, 0x0000, 0xe2eb, 0xbad2, 0xe2ed, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xbd54, 0xe6c1, 0xbd58, 0x0000, 0xbd56, 0x0000,
+ 0x0000, 0xbacf, 0x0000, 0xe6c8, 0xe6c9, 0xbd53, 0x0000, 0x0000,
+ 0xe6c7, 0xe6ca, 0xbd55, 0xbd52, 0xe6c3, 0xe6c0, 0xe6c5, 0xe6c2,
+ 0xbd59, 0xe6c4, 0x0000, 0x0000, 0xe6c6, 0xbd57, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xbf6a, 0xeaa8, 0x0000, 0xeaa2, 0xeaa6, 0xeaac,
+ 0xeaad, 0xeaa9, 0xeaaa, 0xeaa7, 0x0000, 0xeaa4, 0x0000, 0xbf6c,
+ 0xbf69, 0xeaa3, 0xeaa5, 0x0000, 0xbf6b, 0xeaab, 0x0000, 0xc146,
+ 0x0000, 0x0000, 0xedaa, 0xeda5, 0xc145, 0x0000, 0x0000, 0xc143,
+ 0x0000, 0xedac, 0xc144, 0xeda8, 0xeda9, 0xeda6, 0xedad, 0xf056
+};
+
+static const unsigned short big5_from_unicode_79[] = {
+ 0x0000, 0xc147, 0xeda7, 0x0000, 0xedae, 0xedab, 0x0000, 0x0000,
+ 0x0000, 0xf05a, 0x0000, 0x0000, 0xf057, 0x0000, 0xc2a6, 0x0000,
+ 0xf05b, 0xf05d, 0xf05c, 0xf058, 0xf059, 0x0000, 0x0000, 0xf2a3,
+ 0x0000, 0xc3aa, 0x0000, 0xf27e, 0xf2a2, 0xf27d, 0xf2a4, 0x0000,
+ 0x0000, 0xf2a1, 0x0000, 0xf47a, 0xf47d, 0xf479, 0xc471, 0xf47b,
+ 0xf47c, 0xf47e, 0xc472, 0xc474, 0xc473, 0xf5e1, 0x0000, 0xf5e3,
+ 0x0000, 0xf5e2, 0x0000, 0x0000, 0x0000, 0xf6f6, 0x0000, 0x0000,
+ 0xf8b5, 0xf8fa, 0xa5dc, 0x0000, 0x0000, 0xcb72, 0xaac0, 0xcda3,
+ 0xaac1, 0xaac2, 0xcda2, 0x0000, 0xcff8, 0xcff7, 0xace6, 0xace9,
+ 0xace8, 0xace7, 0xcff4, 0xcff6, 0xcff5, 0x0000, 0x0000, 0xd2e8,
+ 0xafa7, 0xd2ec, 0xd2eb, 0xd2ea, 0xd2e6, 0xafa6, 0xafaa, 0xafad,
+ 0x0000, 0x0000, 0xafae, 0xd2e7, 0xd2e9, 0xafac, 0xafab, 0xafa9,
+ 0xafa8, 0xd6c2, 0x0000, 0xd6c0, 0xd6bc, 0xb2bb, 0x0000, 0xd6bd,
+ 0xb2bc, 0xd6be, 0xd6bf, 0xd6c1, 0x0000, 0xb2bd, 0x0000, 0x0000,
+ 0xdad5, 0x0000, 0xdad4, 0xdad3, 0xdad2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xdef6, 0xb852, 0x0000, 0xdef3, 0xdef5, 0x0000, 0xb853,
+ 0x0000, 0xb854, 0xdef4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe341, 0x0000, 0xe2f9, 0xe2fa, 0x0000, 0xbad7, 0xbad5, 0xbad6,
+ 0xe343, 0x0000, 0xe342, 0xe2fe, 0xe2fd, 0xe2fc, 0xe2fb, 0xe340,
+ 0xe2f8, 0x0000, 0xe6cb, 0xe6d0, 0xe6ce, 0x0000, 0x0000, 0x0000,
+ 0xe6cd, 0xe6cc, 0xe6cf, 0x0000, 0xeaae, 0x0000, 0xbf6d, 0xc148,
+ 0xedb0, 0x0000, 0xc149, 0xedaf, 0xf05f, 0xf05e, 0xc2a7, 0x0000,
+ 0xf2a5, 0xc3ab, 0xf4a1, 0xc5a1, 0xf6f7, 0x0000, 0xf8b7, 0xf8b6,
+ 0xc9a8, 0xacea, 0xaceb, 0xd6c3, 0x0000, 0xb856, 0xa5dd, 0xa872,
+ 0xa871, 0xa870, 0x0000, 0x0000, 0x0000, 0xcda4, 0x0000, 0x0000,
+ 0xaac4, 0xaac3, 0x0000, 0xacee, 0x0000, 0xcffa, 0xcffd, 0xcffb,
+ 0x0000, 0xacec, 0xaced, 0x0000, 0x0000, 0xcff9, 0xcffc, 0x0000,
+ 0xafb5, 0x0000, 0x0000, 0x0000, 0xd2f3, 0xd2f5, 0xd2f4, 0xafb2,
+ 0xd2ef, 0x0000, 0x0000, 0xafb0, 0xafaf, 0x0000, 0xafb3, 0xafb1,
+ 0x0000, 0xafb4, 0xd2f2, 0xd2ed, 0xd2ee, 0xd2f1, 0xd2f0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd6c6, 0xd6c7,
+ 0xd6c5, 0x0000, 0xd6c4, 0xb2be, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_7a[] = {
+ 0xb57d, 0x0000, 0xdad6, 0xdad8, 0xdada, 0xb57c, 0x0000, 0x0000,
+ 0xb57a, 0x0000, 0xdad7, 0xb57b, 0xdad9, 0xb579, 0x0000, 0x0000,
+ 0xdf41, 0xdef7, 0xdefa, 0xdefe, 0xb85a, 0xdefc, 0x0000, 0xdefb,
+ 0xdef8, 0xdef9, 0xb858, 0xdf40, 0xb857, 0x0000, 0xb85c, 0xb85b,
+ 0xb859, 0x0000, 0xdefd, 0x0000, 0x0000, 0x0000, 0xe349, 0x0000,
+ 0xe348, 0x0000, 0x0000, 0xe344, 0x0000, 0x0000, 0xbad8, 0xe347,
+ 0xe346, 0xbad9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbd5e,
+ 0x0000, 0xe6d2, 0x0000, 0xbd5f, 0xbd5b, 0xbd5d, 0x0000, 0xbd5a,
+ 0xbd5c, 0x0000, 0x0000, 0x0000, 0xeaaf, 0x0000, 0xbf70, 0xeab1,
+ 0xeab0, 0x0000, 0xe345, 0xbf72, 0xbf71, 0xbf6e, 0xbf6f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xedb5, 0x0000, 0xedb3, 0xc14a,
+ 0xedb4, 0x0000, 0xedb6, 0xedb2, 0xedb1, 0x0000, 0x0000, 0xf060,
+ 0xc2aa, 0xc2a8, 0xc2a9, 0x0000, 0x0000, 0x0000, 0x0000, 0xf2a6,
+ 0xf2a7, 0xc3ad, 0x0000, 0xc3ac, 0xf4a3, 0xf4a4, 0xf4a2, 0x0000,
+ 0xf6f8, 0xf6f9, 0x0000, 0x0000, 0xa5de, 0xca48, 0xa873, 0x0000,
+ 0xcda5, 0xaac6, 0xaac5, 0xcda6, 0x0000, 0x0000, 0xd040, 0xacef,
+ 0xcffe, 0xacf0, 0x0000, 0x0000, 0xafb6, 0xd2f8, 0xd2f6, 0xd2fc,
+ 0xafb7, 0xd2f7, 0xd2fb, 0xd2f9, 0xd2fa, 0x0000, 0x0000, 0xd6c8,
+ 0xd6ca, 0x0000, 0xb2bf, 0x0000, 0xd6c9, 0xb2c0, 0xb5a2, 0xb5a1,
+ 0xb57e, 0xdadb, 0x0000, 0x0000, 0x0000, 0x0000, 0xdf44, 0xb85d,
+ 0xb85e, 0x0000, 0xdf43, 0xdf42, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe34a, 0xbadb, 0xbada, 0xe34b, 0xe34c, 0x0000, 0xbd61, 0xbd60,
+ 0x0000, 0xeab5, 0xe6d3, 0xe6d5, 0xe6d4, 0xeab4, 0xeab2, 0xeab6,
+ 0xeab3, 0x0000, 0xbf73, 0x0000, 0x0000, 0x0000, 0xedb7, 0xc14b,
+ 0xedb8, 0xedb9, 0x0000, 0x0000, 0xc2ab, 0xc2ac, 0x0000, 0xc475,
+ 0x0000, 0x0000, 0xc5d1, 0xa5df, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd041, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd2fd, 0xafb8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb3ba,
+ 0xb3b9, 0x0000, 0x0000, 0xb5a4, 0xdadd, 0xb5a3, 0xdadc, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xdf45, 0x0000, 0xbadc, 0xe34d, 0xbadd,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc476, 0xf4a5,
+ 0x0000, 0xa6cb, 0xaac7, 0xcda7, 0x0000, 0xacf2, 0x0000, 0xacf1
+};
+
+static const unsigned short big5_from_unicode_7b[] = {
+ 0xd042, 0xd043, 0x0000, 0x0000, 0xd340, 0xd342, 0xafb9, 0x0000,
+ 0xd344, 0xd347, 0xd345, 0x0000, 0x0000, 0x0000, 0xd346, 0xd343,
+ 0xd2fe, 0xafba, 0xd348, 0xd341, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd6d3, 0xb2c6, 0xd6dc, 0xb2c3, 0x0000, 0xd6d5, 0xb2c7, 0x0000,
+ 0xb2c1, 0x0000, 0xd6d0, 0xd6dd, 0xd6d1, 0xd6ce, 0xb2c5, 0x0000,
+ 0xb2c2, 0x0000, 0xd6d4, 0xd6d7, 0xb2c4, 0xd6d8, 0xb2c8, 0xd6d9,
+ 0xd6cf, 0xd6d6, 0xd6da, 0xd6d2, 0xd6cd, 0xd6cb, 0x0000, 0x0000,
+ 0xd6db, 0x0000, 0x0000, 0xdadf, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xdae4, 0x0000, 0x0000, 0x0000, 0xdae0, 0xdae6, 0xb5a7, 0xd6cc,
+ 0xdae1, 0xb5a5, 0xdade, 0xb5ac, 0xdae2, 0xb5ab, 0xdae3, 0xb5ad,
+ 0xb5a8, 0xb5ae, 0xb5a9, 0x0000, 0xb5aa, 0x0000, 0xb5a6, 0x0000,
+ 0xdae5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xb861, 0xdf50, 0x0000, 0xdf53, 0xdf47, 0xdf4c, 0xdf46, 0xb863,
+ 0x0000, 0xdf4a, 0x0000, 0x0000, 0x0000, 0xdf48, 0xb862, 0x0000,
+ 0xdf4f, 0xdf4e, 0xdf4b, 0xdf4d, 0xdf49, 0xbae1, 0xdf52, 0xb85f,
+ 0xdf51, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe35d, 0x0000, 0xbae8, 0xe358, 0x0000, 0xbae7,
+ 0xe34e, 0x0000, 0xe350, 0xbae0, 0xe355, 0xe354, 0xe357, 0xbae5,
+ 0xe352, 0xe351, 0x0000, 0x0000, 0xbae4, 0xbadf, 0xe353, 0xbae2,
+ 0xe359, 0xe35b, 0x0000, 0xe356, 0xe34f, 0xbae3, 0x0000, 0x0000,
+ 0xbd69, 0xbade, 0x0000, 0x0000, 0xe35c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe6d9, 0xbd62, 0x0000, 0xe6db,
+ 0x0000, 0xbd63, 0x0000, 0x0000, 0xbd65, 0xe6de, 0x0000, 0xe6d6,
+ 0xbae6, 0xe6dc, 0x0000, 0x0000, 0x0000, 0x0000, 0xe6d8, 0x0000,
+ 0xb860, 0xbd68, 0x0000, 0x0000, 0xbd64, 0x0000, 0xbd66, 0xbd67,
+ 0x0000, 0xbf76, 0xe6dd, 0xe6d7, 0xbd6a, 0x0000, 0xe6da, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xeac0, 0xeabb, 0x0000, 0x0000,
+ 0xeac5, 0xbf74, 0xeabd, 0xbf78, 0xeac3, 0xeaba, 0xeab7, 0xeac6,
+ 0xc151, 0xbf79, 0xeac2, 0xeab8, 0xbf77, 0xeabc, 0xbf7b, 0xeab9,
+ 0xeabe, 0xbf7a, 0xeac1, 0xeac4, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xedcb, 0xedcc, 0xedbc, 0xedc3, 0xedc1, 0x0000, 0x0000, 0xc14f,
+ 0xedc8, 0xeabf, 0x0000, 0xedbf, 0x0000, 0xedc9, 0xc14e, 0xedbe
+};
+
+static const unsigned short big5_from_unicode_7c[] = {
+ 0xedbd, 0xedc7, 0xedc4, 0xedc6, 0x0000, 0xedba, 0xedca, 0xc14c,
+ 0x0000, 0xedc5, 0xedce, 0xedc2, 0xc150, 0xc14d, 0xedc0, 0xedbb,
+ 0xedcd, 0xbf75, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf063, 0x0000, 0x0000, 0xf061, 0xf067, 0xc2b0, 0xf065,
+ 0xf064, 0xc2b2, 0xf06a, 0xc2b1, 0x0000, 0xf06b, 0xf068, 0xc2ae,
+ 0xf069, 0xf062, 0xc2af, 0xc2ad, 0xf2ab, 0xf066, 0x0000, 0x0000,
+ 0xf06c, 0x0000, 0x0000, 0xf2a8, 0x0000, 0x0000, 0x0000, 0xc3b2,
+ 0xc3b0, 0xf2aa, 0x0000, 0xf2ac, 0xf2a9, 0xc3b1, 0xc3ae, 0xc3af,
+ 0xc3b3, 0x0000, 0x0000, 0xc478, 0x0000, 0xf4aa, 0x0000, 0xf4a9,
+ 0xf4a7, 0xf4a6, 0xf4a8, 0x0000, 0xc477, 0xc479, 0x0000, 0x0000,
+ 0xc4f0, 0x0000, 0x0000, 0xf5e5, 0xf5e4, 0x0000, 0x0000, 0xf6fa,
+ 0x0000, 0xf6fc, 0xf6fe, 0xf6fd, 0xf6fb, 0x0000, 0x0000, 0xc5a3,
+ 0xc5a2, 0x0000, 0x0000, 0xc5d3, 0xc5d2, 0xc5d4, 0xf7ed, 0xf7ec,
+ 0x0000, 0xf8fb, 0xf8b8, 0xf8fc, 0xc658, 0x0000, 0xc659, 0xf96d,
+ 0x0000, 0x0000, 0xc67e, 0xa6cc, 0x0000, 0xcda8, 0x0000, 0x0000,
+ 0xd045, 0xd046, 0xd044, 0x0000, 0x0000, 0xacf3, 0x0000, 0xd047,
+ 0xd048, 0xd049, 0x0000, 0x0000, 0xd349, 0xd34f, 0x0000, 0x0000,
+ 0xd34d, 0xafbb, 0xd34b, 0x0000, 0xd34c, 0xd34e, 0x0000, 0x0000,
+ 0x0000, 0xd34a, 0xb2c9, 0x0000, 0xd6de, 0xb2cb, 0xd6e0, 0xb2ca,
+ 0xd6df, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdae8, 0xb5af,
+ 0x0000, 0xdaea, 0xdae7, 0xd6e1, 0x0000, 0xb5b0, 0x0000, 0x0000,
+ 0xdae9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdf56,
+ 0x0000, 0xb864, 0xdf54, 0xb865, 0xdf55, 0xb866, 0x0000, 0x0000,
+ 0x0000, 0xbae9, 0xe361, 0xe35e, 0xe360, 0xbaea, 0xbaeb, 0xe35f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe6df, 0x0000, 0x0000,
+ 0xe6e0, 0x0000, 0xbd6b, 0xe6e2, 0xe6e1, 0x0000, 0xa261, 0x0000,
+ 0xeaca, 0xeacb, 0xeac7, 0x0000, 0xeac8, 0xbf7c, 0xbf7d, 0xeac9,
+ 0x0000, 0xc157, 0x0000, 0x0000, 0xc153, 0xc158, 0xc154, 0xc156,
+ 0xc152, 0x0000, 0xc155, 0x0000, 0x0000, 0x0000, 0x0000, 0xc2b3,
+ 0xedcf, 0x0000, 0xf2ae, 0x0000, 0xf2ad, 0x0000, 0xf4ab, 0xc47a,
+ 0xc47b, 0xf741, 0xf5e6, 0x0000, 0xf740, 0x0000, 0xf8fd, 0xf9a4,
+ 0xa6cd, 0x0000, 0x0000, 0xa874, 0x0000, 0xcda9, 0xaac8, 0x0000
+};
+
+static const unsigned short big5_from_unicode_7d[] = {
+ 0xacf6, 0xd04c, 0xacf4, 0xd04a, 0xacf9, 0xacf5, 0xacfa, 0xacf8,
+ 0xd04b, 0xacf7, 0xafbf, 0xafbe, 0xd35a, 0xafc7, 0xd353, 0xd359,
+ 0xafc3, 0xd352, 0xd358, 0xd356, 0xafc2, 0xafc4, 0xd355, 0xafbd,
+ 0xd354, 0xafc8, 0xafc5, 0xafc9, 0xafc6, 0xd351, 0xd350, 0xd357,
+ 0xafc0, 0xafbc, 0xafc1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd6f0, 0xd6e9, 0x0000, 0xb5b5, 0xd6e8, 0x0000, 0xb2cf, 0xb2d6,
+ 0xb2d3, 0xb2d9, 0xb2d8, 0xb2d4, 0x0000, 0xd6e2, 0xd6e5, 0x0000,
+ 0xd6e4, 0xb2d0, 0xd6e6, 0xd6ef, 0xb2d1, 0xd6e3, 0xd6ec, 0xd6ed,
+ 0xb2d2, 0xd6ea, 0xb2d7, 0xb2cd, 0xb2d5, 0xd6e7, 0xb2cc, 0xd6eb,
+ 0x0000, 0x0000, 0xd6ee, 0x0000, 0x0000, 0x0000, 0xdafb, 0xdaf2,
+ 0xb5b2, 0xdaf9, 0xdaf6, 0xdaee, 0xdaf7, 0xb5b4, 0xdaef, 0x0000,
+ 0xdaeb, 0x0000, 0x0000, 0xb86c, 0xdaf4, 0x0000, 0xb5b1, 0xdafa,
+ 0x0000, 0xb5b8, 0xb5ba, 0xdaed, 0x0000, 0x0000, 0xb5b9, 0xdaf0,
+ 0xb5b3, 0xdaf8, 0xdaf1, 0xdaf5, 0x0000, 0xdaf3, 0xb5b6, 0xdaec,
+ 0xb5bb, 0xb2ce, 0xb5b7, 0xb5bc, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb868, 0xdf5d, 0xdf5f, 0xdf61, 0xdf65, 0x0000, 0xdf5b,
+ 0xdf59, 0xb86a, 0x0000, 0xdf60, 0xdf64, 0xdf5c, 0xdf58, 0x0000,
+ 0xdf57, 0x0000, 0x0000, 0x0000, 0xdf62, 0xdf5a, 0xdf5e, 0xb86b,
+ 0x0000, 0xb869, 0xdf66, 0xb867, 0xdf63, 0x0000, 0xe372, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xbaee, 0xe36a, 0xbd78, 0xe374,
+ 0xbaf1, 0xe378, 0xbaf7, 0xe365, 0x0000, 0x0000, 0xe375, 0xe362,
+ 0x0000, 0xe377, 0xe366, 0x0000, 0xbafe, 0xbafb, 0xe376, 0xe370,
+ 0xbaed, 0xbaf5, 0xbaf4, 0x0000, 0xbaf3, 0xbaf9, 0x0000, 0xe363,
+ 0xbafa, 0xe371, 0xbaf6, 0xbaec, 0xe373, 0xbaef, 0xbaf0, 0xbaf8,
+ 0xe368, 0xe367, 0xe364, 0x0000, 0xe36c, 0xe369, 0xe36d, 0xbafd,
+ 0x0000, 0xe379, 0xbaf2, 0xe36e, 0xe36f, 0x0000, 0xe36b, 0x0000,
+ 0x0000, 0x0000, 0xbafc, 0x0000, 0x0000, 0x0000, 0x0000, 0xe6e7,
+ 0xbd70, 0xbd79, 0xbd75, 0xe6e4, 0x0000, 0xbd72, 0xbd76, 0xe6f0,
+ 0xbd6c, 0xe6e8, 0x0000, 0xbd74, 0x0000, 0x0000, 0xe6eb, 0xe6e6,
+ 0xbd73, 0xbd77, 0xe6e5, 0x0000, 0xbd71, 0x0000, 0xe6ef, 0xbd6e,
+ 0xe6ee, 0xe6ed, 0xbd7a, 0xe572, 0xbd6d, 0x0000, 0xe6ec, 0xe6e3,
+ 0x0000, 0xbd7b, 0xe6ea, 0xbd6f, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_7e[] = {
+ 0x0000, 0x0000, 0x0000, 0xe6e9, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xbfa2, 0xbfa7, 0xbf7e, 0xead8, 0xeacf, 0xeadb, 0xead3, 0xead9,
+ 0xbfa8, 0xbfa1, 0xeacc, 0xead2, 0xeadc, 0xead5, 0xeada, 0xeace,
+ 0x0000, 0x0000, 0xead6, 0xbfa3, 0xead4, 0xbfa6, 0xbfa5, 0xead0,
+ 0xead1, 0xeacd, 0xead7, 0xbfa4, 0xeade, 0xeadd, 0x0000, 0x0000,
+ 0x0000, 0xedda, 0xedd6, 0xc15f, 0x0000, 0xedd0, 0xc159, 0xc169,
+ 0xeddc, 0xc161, 0xc15d, 0xedd3, 0xc164, 0xc167, 0xedde, 0xc15c,
+ 0xedd5, 0xc165, 0xede0, 0xeddd, 0xedd1, 0xc160, 0xc15a, 0xc168,
+ 0xedd8, 0xc163, 0xedd2, 0xc15e, 0xeddf, 0xc162, 0xc15b, 0xedd9,
+ 0xc166, 0xedd7, 0x0000, 0x0000, 0xeddb, 0x0000, 0x0000, 0x0000,
+ 0xf06e, 0xf074, 0xc2b9, 0xf077, 0xc2b4, 0xc2b5, 0xf06f, 0xf076,
+ 0xf071, 0xc2ba, 0xc2b7, 0x0000, 0xf06d, 0x0000, 0xc2b6, 0xf073,
+ 0xf075, 0xc2b8, 0xf072, 0xf070, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf2b8, 0xc3b7, 0xc3b8, 0xc3b4, 0x0000, 0xc3b5, 0x0000, 0xf2b4,
+ 0xf2b2, 0x0000, 0xf2b6, 0xc3ba, 0xf2b7, 0xf2b0, 0xf2af, 0xf2b3,
+ 0xf2b1, 0xc3b6, 0xf2b5, 0xf4ac, 0xc47e, 0xc47d, 0xf4ad, 0x0000,
+ 0xf4af, 0xf4ae, 0xc4a1, 0x0000, 0x0000, 0x0000, 0xf5eb, 0x0000,
+ 0xf5e9, 0x0000, 0xf5e7, 0xf5ea, 0xc4f2, 0xf5ec, 0x0000, 0xc4f1,
+ 0x0000, 0xf742, 0x0000, 0xc5d5, 0xc5d7, 0xf7ee, 0xc5d6, 0xf8b9,
+ 0xf940, 0xf942, 0xf8fe, 0xf941, 0xc66c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_7f[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa6ce, 0x0000,
+ 0xacfb, 0xd26f, 0xafca, 0x0000, 0x0000, 0xb2da, 0xdafc, 0xdafd,
+ 0x0000, 0x0000, 0x0000, 0xeadf, 0xc16a, 0xede1, 0x0000, 0x0000,
+ 0xc2bb, 0x0000, 0xf2ba, 0xf2b9, 0xc4a2, 0xf5ed, 0x0000, 0xf743,
+ 0xc5f8, 0xca49, 0x0000, 0x0000, 0xaac9, 0xa875, 0x0000, 0x0000,
+ 0xd04d, 0x0000, 0x0000, 0xd360, 0xd35b, 0xd35f, 0xd35d, 0xafcb,
+ 0xd35e, 0xd35c, 0x0000, 0xd6f1, 0x0000, 0xdafe, 0xdb40, 0xdf69,
+ 0xdf6a, 0xb86e, 0xb86f, 0xdf68, 0xdf6b, 0xdf67, 0xb86d, 0x0000,
+ 0xbb40, 0x0000, 0xb870, 0xe37a, 0x0000, 0xbd7c, 0xe6f1, 0xbd7d,
+ 0x0000, 0xbfa9, 0xeae2, 0xeae0, 0xeae1, 0xede4, 0xede3, 0xede2,
+ 0x0000, 0x0000, 0x0000, 0xf2bb, 0x0000, 0xc3b9, 0xf2bc, 0xf744,
+ 0xc5f9, 0xf8ba, 0xa6cf, 0xaacb, 0xaaca, 0xd04f, 0xacfc, 0x0000,
+ 0x0000, 0xd04e, 0xd362, 0x0000, 0xafcc, 0xd6f2, 0xd361, 0x0000,
+ 0x0000, 0x0000, 0xb2dc, 0xd6f5, 0xd6f3, 0xd6f4, 0xb2db, 0x0000,
+ 0xdb42, 0xdb43, 0xdb41, 0x0000, 0xb873, 0xdf6d, 0xdf6c, 0xdf6e,
+ 0xb872, 0xb871, 0x0000, 0x0000, 0xe6f2, 0xe6f4, 0x0000, 0xbd7e,
+ 0xe6f3, 0xeae3, 0xbfaa, 0xf079, 0x0000, 0xf078, 0xc3bb, 0xf2bd,
+ 0xc3bd, 0xc3bc, 0xf4b0, 0xf5ee, 0xc4f3, 0xa6d0, 0xd050, 0xacfd,
+ 0xd365, 0xafce, 0xd364, 0xd363, 0x0000, 0xafcd, 0x0000, 0xd6fb,
+ 0x0000, 0xd6fd, 0xd6f6, 0xd6f7, 0xb2dd, 0xd6f8, 0xb2de, 0xd6fc,
+ 0xd6f9, 0xd6fa, 0xb2df, 0x0000, 0xb5be, 0xb5bf, 0x0000, 0xdb44,
+ 0x0000, 0x0000, 0x0000, 0xdf6f, 0xdf70, 0x0000, 0xe37e, 0xbb43,
+ 0xbb41, 0xbb42, 0xe37b, 0xe37c, 0x0000, 0xe37d, 0xe6f9, 0x0000,
+ 0xe6fa, 0xbda1, 0xe6f7, 0xe6f6, 0xe6f8, 0xe6f5, 0xbfad, 0xeae4,
+ 0xbfab, 0xbfac, 0xede6, 0xc16b, 0xede5, 0xefa8, 0x0000, 0xf07a,
+ 0xf07b, 0xc2bc, 0x0000, 0xc2bd, 0xc16c, 0xf2be, 0xf2bf, 0xf4b1
+};
+
+static const unsigned short big5_from_unicode_80[] = {
+ 0xc4a3, 0xa6d1, 0x0000, 0xa6d2, 0xacfe, 0xaacc, 0xafcf, 0xd051,
+ 0x0000, 0x0000, 0x0000, 0xb5c0, 0xa6d3, 0xad41, 0xd052, 0xd053,
+ 0xad40, 0xad42, 0xa6d4, 0x0000, 0xd054, 0xafd1, 0xd366, 0xafd3,
+ 0xafd0, 0xafd2, 0x0000, 0xd741, 0xb2e0, 0x0000, 0xd740, 0xd6fe,
+ 0x0000, 0xdf71, 0x0000, 0x0000, 0xe3a1, 0x0000, 0xbda2, 0x0000,
+ 0xbfae, 0xeae6, 0xeae5, 0x0000, 0xede7, 0x0000, 0x0000, 0x0000,
+ 0xf5ef, 0x0000, 0x0000, 0xa6d5, 0xcb73, 0xcdaa, 0xad43, 0xd055,
+ 0x0000, 0xd368, 0x0000, 0x0000, 0x0000, 0xafd4, 0xd367, 0xafd5,
+ 0x0000, 0x0000, 0x0000, 0xd743, 0x0000, 0x0000, 0xb2e2, 0xd742,
+ 0xd744, 0x0000, 0xb2e1, 0x0000, 0x0000, 0x0000, 0x0000, 0xdb46,
+ 0xdb47, 0xdb45, 0xb5c1, 0x0000, 0x0000, 0x0000, 0xb874, 0x0000,
+ 0xb875, 0x0000, 0xbb45, 0x0000, 0xe3a3, 0xe3a2, 0xbb44, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe6fb, 0x0000, 0x0000, 0xe6fc,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xeae7, 0x0000, 0x0000, 0xc170,
+ 0xc16f, 0xc16d, 0xc16e, 0xc171, 0x0000, 0xf07c, 0xc2bf, 0xc2be,
+ 0xf2c0, 0xf4b2, 0x0000, 0x0000, 0x0000, 0xc5a5, 0xc5a4, 0xa6d6,
+ 0x0000, 0x0000, 0xd1fb, 0x0000, 0xb877, 0xb5c2, 0xb876, 0xbb46,
+ 0x0000, 0xa6d7, 0xc9a9, 0xa6d8, 0xa6d9, 0x0000, 0x0000, 0xcdab,
+ 0xcb76, 0x0000, 0xcb77, 0xa877, 0x0000, 0xcb74, 0xa876, 0x0000,
+ 0xa879, 0xcb75, 0xa87b, 0xa87a, 0xcb78, 0xa878, 0x0000, 0x0000,
+ 0x0000, 0xaad1, 0xaacf, 0xcdad, 0x0000, 0xaace, 0x0000, 0x0000,
+ 0x0000, 0xaad3, 0xaad5, 0xaad2, 0x0000, 0xcdb0, 0xcdac, 0xaad6,
+ 0x0000, 0xaad0, 0xa87c, 0x0000, 0xaad4, 0xcdaf, 0x0000, 0x0000,
+ 0xcdae, 0x0000, 0xaacd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd05b, 0xad47, 0xad48, 0xd05d, 0x0000, 0xd057,
+ 0xd05a, 0xd063, 0xd061, 0x0000, 0xad49, 0xd067, 0xad4c, 0xd064,
+ 0xd05c, 0xd059, 0x0000, 0x0000, 0xdb49, 0xd062, 0xad44, 0xd065,
+ 0xd056, 0xd05f, 0xad46, 0xad4b, 0xd060, 0xad4f, 0xad4d, 0x0000,
+ 0xd058, 0xad4a, 0x0000, 0xd05e, 0xad4e, 0xad45, 0xd066, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xafda, 0x0000, 0xafe3,
+ 0xafd8, 0xafd6, 0xd36a, 0xafde, 0xafdb, 0xd36c, 0x0000, 0x0000,
+ 0xafdd, 0xd36b, 0xd369, 0xd36e, 0xafe2, 0xafe0, 0xdb48, 0x0000
+};
+
+static const unsigned short big5_from_unicode_81[] = {
+ 0xd36f, 0xd36d, 0xafd7, 0x0000, 0x0000, 0xafd9, 0xafdc, 0x0000,
+ 0xafdf, 0x0000, 0xafe1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd74e, 0xb2e4, 0x0000,
+ 0xd745, 0xd747, 0x0000, 0xd748, 0x0000, 0xd750, 0xd74c, 0xd74a,
+ 0x0000, 0xd74d, 0xd751, 0xb2e5, 0xb2e9, 0xd746, 0x0000, 0xd74f,
+ 0x0000, 0xb2e7, 0x0000, 0xb2e6, 0xd74b, 0xd749, 0x0000, 0xb2e3,
+ 0xb2e8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb5c8, 0xdb51, 0x0000, 0x0000, 0xdb4f, 0xb5ca, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xdb4a, 0xdfa1, 0x0000, 0xb5c9, 0xdb4e,
+ 0x0000, 0x0000, 0xdb4b, 0xb5c5, 0xb5cb, 0xdb50, 0xb5c7, 0xdb4d,
+ 0xbb47, 0xb5c6, 0xdb4c, 0xb5cc, 0xb5c4, 0xb5c3, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xdf77, 0xdf75, 0x0000, 0xdf7b, 0x0000,
+ 0xdf73, 0xdfa2, 0xdf78, 0x0000, 0xdf72, 0xb87b, 0xb8a3, 0xdf7d,
+ 0x0000, 0xdf76, 0x0000, 0xb87e, 0x0000, 0x0000, 0xb87c, 0xdf7e,
+ 0xb879, 0xb878, 0xdf79, 0xb87d, 0xb5cd, 0x0000, 0xdf7c, 0xdf74,
+ 0xb87a, 0xb8a1, 0xb8a2, 0x0000, 0x0000, 0x0000, 0x0000, 0xbb4c,
+ 0xbb48, 0x0000, 0xbb4d, 0xe3a6, 0x0000, 0x0000, 0xe3a5, 0xe3a7,
+ 0xbb4a, 0xe3a4, 0xbb4b, 0xe3aa, 0xe3a9, 0xe3a8, 0x0000, 0xbb49,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe741, 0x0000, 0xe744,
+ 0xbda8, 0xe743, 0xbda7, 0xbda3, 0xbda4, 0xbda5, 0xe740, 0xe6fe,
+ 0xbda6, 0x0000, 0xe742, 0xe6fd, 0x0000, 0x0000, 0xeae9, 0xeaf3,
+ 0xbfb1, 0xbfb0, 0x0000, 0xeaed, 0xeaef, 0x0000, 0xeaea, 0x0000,
+ 0xeaee, 0xeae8, 0xeaf1, 0xbfaf, 0xeaf0, 0xeaec, 0x0000, 0xeaf2,
+ 0x0000, 0xeaeb, 0xc174, 0xede8, 0xedee, 0xc178, 0xc17a, 0xc177,
+ 0xc176, 0x0000, 0xc175, 0xc173, 0xede9, 0xedec, 0xc172, 0xeded,
+ 0x0000, 0xc179, 0xedeb, 0x0000, 0xedea, 0xc2c0, 0x0000, 0xc2c1,
+ 0xf0a1, 0xf07d, 0xf07e, 0x0000, 0x0000, 0xf2c2, 0x0000, 0xf2c1,
+ 0xc3be, 0xf4b4, 0xc4a4, 0xf4b3, 0x0000, 0xf5f0, 0xf745, 0xc5a6,
+ 0xf943, 0xf944, 0xc5d8, 0xa6da, 0x0000, 0xaad7, 0xdb52, 0xbb4e,
+ 0xc17b, 0xedef, 0xa6db, 0x0000, 0xafe5, 0xafe4, 0xdb53, 0x0000,
+ 0x0000, 0x0000, 0xeaf4, 0xa6dc, 0xad50, 0x0000, 0x0000, 0xdb54,
+ 0xdb55, 0xdb56, 0xbb4f, 0xbfb2, 0xa6dd, 0x0000, 0xaad8, 0xd068
+};
+
+static const unsigned short big5_from_unicode_82[] = {
+ 0xafe6, 0xd370, 0xb2ea, 0x0000, 0xdb57, 0xb8a4, 0x0000, 0xbb50,
+ 0xbfb3, 0xc17c, 0xc2c2, 0xf4b5, 0xa6de, 0xaad9, 0x0000, 0x0000,
+ 0xafe7, 0xd752, 0xb5ce, 0x0000, 0xbb51, 0xe3ab, 0xe745, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa6df, 0xb5cf, 0xdfa3, 0xbb52, 0xa6e0,
+ 0xcdb1, 0xd069, 0xad51, 0x0000, 0x0000, 0xd372, 0x0000, 0x0000,
+ 0xafea, 0x0000, 0xafe8, 0xafe9, 0xafeb, 0x0000, 0x0000, 0xd371,
+ 0x0000, 0x0000, 0xd757, 0xd754, 0xd756, 0xb2eb, 0xb2ed, 0xb2ec,
+ 0xd753, 0xb2ee, 0xd755, 0x0000, 0xdb58, 0xdb59, 0x0000, 0xdb5a,
+ 0xdfa6, 0x0000, 0xdfa7, 0x0000, 0xdfa5, 0xdfa8, 0x0000, 0xb8a5,
+ 0x0000, 0xdfa4, 0x0000, 0xbb53, 0x0000, 0x0000, 0xe74a, 0xe746,
+ 0xe749, 0xe74b, 0xe748, 0xe747, 0x0000, 0xeaf5, 0xeaf6, 0xeaf7,
+ 0xbfb4, 0xbfb5, 0xedf1, 0xedf0, 0xedf2, 0x0000, 0xf0a3, 0xf0a2,
+ 0x0000, 0xf2c4, 0x0000, 0xf2c5, 0xf2c3, 0x0000, 0xc4a5, 0x0000,
+ 0xf4b6, 0xf4b7, 0x0000, 0xf746, 0xf7ef, 0xf8bb, 0xa6e1, 0xa87d,
+ 0x0000, 0xc17d, 0xa6e2, 0x0000, 0xd758, 0xdb5b, 0x0000, 0xc641,
+ 0xca4a, 0x0000, 0x0000, 0x0000, 0xca4b, 0xca4d, 0xa6e3, 0xca4e,
+ 0xca4c, 0x0000, 0x0000, 0xcba2, 0xcba3, 0xcb7b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xcba1, 0xa8a1, 0x0000, 0xa8a2, 0xcb7c, 0xcb7a,
+ 0xcb79, 0xcb7d, 0xa87e, 0xcb7e, 0xd06a, 0x0000, 0x0000, 0x0000,
+ 0xcdb6, 0xaadc, 0xcdb5, 0xcdb7, 0x0000, 0xaadb, 0xcdbc, 0xaadf,
+ 0xcdb2, 0xcdc0, 0xcdc6, 0xaae6, 0xcdc3, 0xaae3, 0x0000, 0xcdb9,
+ 0xcdbf, 0xcdc1, 0x0000, 0xcdb4, 0xaae2, 0xaadd, 0xcdba, 0xaae4,
+ 0xaae7, 0xaae1, 0x0000, 0xaada, 0xcdbe, 0xcdb8, 0xcdc5, 0xaae9,
+ 0xaae5, 0xaae0, 0xcdbd, 0xafec, 0xcdbb, 0xaade, 0xaae8, 0x0000,
+ 0xcdb3, 0x0000, 0xcdc2, 0xcdc4, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xad62, 0xad5c, 0xad64, 0xad61, 0xd071, 0xd074, 0xad5d,
+ 0x0000, 0xd06b, 0x0000, 0xad56, 0xad60, 0x0000, 0xad63, 0xad65,
+ 0xd0a2, 0xd077, 0x0000, 0xad55, 0xd0a1, 0xad59, 0xad57, 0xad52,
+ 0xd06f, 0x0000, 0xd07e, 0xd073, 0xd076, 0xd0a5, 0x0000, 0xad66,
+ 0xd07d, 0xad5e, 0xd078, 0xd0a4, 0xd075, 0xd079, 0xd07c, 0x0000,
+ 0x0000, 0xd06d, 0xd0a3, 0xd07b, 0x0000, 0x0000, 0xd06c, 0x0000
+};
+
+static const unsigned short big5_from_unicode_83[] = {
+ 0xd070, 0xad5f, 0xad5a, 0xad53, 0xad58, 0xad54, 0xad67, 0xd06e,
+ 0xd3a5, 0xad5b, 0x0000, 0x0000, 0xd07a, 0xce41, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd3a8, 0xaffa,
+ 0x0000, 0xd376, 0x0000, 0xd3a3, 0xd37d, 0x0000, 0xd3b2, 0x0000,
+ 0xd3aa, 0x0000, 0xd37e, 0x0000, 0xd3a9, 0xd378, 0xd37c, 0xd3b5,
+ 0xaffd, 0xd3ad, 0xd3a4, 0xafed, 0xd3b3, 0xd374, 0x0000, 0xd3ac,
+ 0x0000, 0xaffc, 0xaff7, 0xd373, 0xaff5, 0xaff4, 0xaff9, 0xd3ab,
+ 0xaff1, 0xaff8, 0xd072, 0xdb5c, 0xd3a6, 0x0000, 0x0000, 0xd37a,
+ 0xaffb, 0xd37b, 0xd3a1, 0xaffe, 0xd375, 0xd3af, 0x0000, 0xd3ae,
+ 0xd3b6, 0xaff3, 0xaff0, 0xd3b4, 0xd3b0, 0xd3a7, 0xd3a2, 0xaff6,
+ 0xaff2, 0xd377, 0xafee, 0xd3b1, 0xafef, 0x0000, 0xd379, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xd75e, 0xd760, 0xd765, 0xd779, 0xb2fc,
+ 0xb2f2, 0x0000, 0xd75d, 0xb2fd, 0xb2fe, 0xd768, 0xd76f, 0xd775,
+ 0x0000, 0xd762, 0x0000, 0xd769, 0x0000, 0x0000, 0xb340, 0xd777,
+ 0xd772, 0xb2fa, 0xb2f8, 0xd76e, 0xd76a, 0xd75c, 0xb2ef, 0xd761,
+ 0xd759, 0x0000, 0xb2f7, 0xb2f9, 0xd766, 0xd763, 0xb2f4, 0xd773,
+ 0xb2f1, 0xd764, 0xd77a, 0xd76c, 0x0000, 0xd76b, 0xb2f0, 0x0000,
+ 0xb2fb, 0x0000, 0xb2f3, 0xd75a, 0xd75f, 0xd770, 0xd776, 0xb341,
+ 0xd75b, 0xd767, 0xd76d, 0xb2f6, 0x0000, 0x0000, 0xd778, 0xd771,
+ 0xd774, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb2f5, 0x0000, 0xdb6c,
+ 0xdb60, 0xb5d7, 0xdb7d, 0xdba7, 0xdbaa, 0xb5d5, 0xdb68, 0xdba3,
+ 0xdb69, 0xdb77, 0xb5e2, 0xdb73, 0xb5df, 0x0000, 0xdb74, 0xdb5d,
+ 0x0000, 0xdba4, 0x0000, 0x0000, 0xb5e8, 0xdba1, 0xdb75, 0xdbac,
+ 0xdb70, 0xdfc8, 0x0000, 0xdbaf, 0xb5e6, 0xdb6e, 0xdb7a, 0xb5e9,
+ 0xb5d4, 0xdb72, 0xdbad, 0xdb6b, 0xdb64, 0xdb6f, 0x0000, 0xdb63,
+ 0xdb61, 0xb5d0, 0xdba5, 0xdb6a, 0xdba8, 0x0000, 0xdba9, 0xb5d8,
+ 0xb5dd, 0xb5d9, 0xb5e1, 0xdb7e, 0xb5da, 0xdb76, 0xdb66, 0x0000,
+ 0xb5d2, 0xdb5e, 0xdba2, 0xdbab, 0xdb65, 0xb5e0, 0xdbb0, 0xdb71
+};
+
+static const unsigned short big5_from_unicode_84[] = {
+ 0x0000, 0xdb6d, 0x0000, 0xb5d1, 0xb5e5, 0x0000, 0xdb7c, 0xb5e7,
+ 0x0000, 0xdb78, 0xb5dc, 0xb5d6, 0xb5de, 0xb5d3, 0xb5e4, 0xdb79,
+ 0xdb67, 0xdb7b, 0xdb62, 0xdba6, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xdbae, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xdb5f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xdfc7, 0x0000, 0xdfdd, 0xb855, 0xdfcc, 0x0000, 0xdfca,
+ 0xdfb5, 0xb8a9, 0xdfc5, 0xdfd9, 0xdfc1, 0xb8b1, 0xdfd8, 0xdfbf,
+ 0xb5e3, 0xdfcf, 0xdfc0, 0xdfd6, 0xb8b0, 0xb8a8, 0x0000, 0xdfaa,
+ 0xdfb2, 0x0000, 0xdfcb, 0xdfc3, 0xdfdc, 0xdfc6, 0xb8b6, 0xdfd7,
+ 0x0000, 0xb8ad, 0x0000, 0xdfc9, 0xdfd1, 0xdfb6, 0xdfd0, 0x0000,
+ 0xdfe1, 0xdfb1, 0xdfd2, 0x0000, 0xdfdf, 0x0000, 0xdfab, 0xb5db,
+ 0x0000, 0xdfb9, 0xdfb8, 0xb8af, 0x0000, 0xdfbc, 0xdfbe, 0xdfcd,
+ 0xdfde, 0xb8b2, 0x0000, 0xb8b3, 0x0000, 0xdfb0, 0xb8ab, 0xdfb4,
+ 0xdfda, 0xb8b4, 0x0000, 0xb8ac, 0xb8ae, 0xb8b5, 0xdfe0, 0xdfd3,
+ 0xdfce, 0x0000, 0x0000, 0xdfbb, 0xdfba, 0xb8aa, 0xdfac, 0xb8a7,
+ 0xdfc4, 0xdfad, 0xdfc2, 0x0000, 0x0000, 0xdfb7, 0xdfdb, 0x0000,
+ 0x0000, 0x0000, 0xb8a6, 0x0000, 0x0000, 0x0000, 0xdfb3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdfaf, 0xdfd5, 0xdfae,
+ 0xbb60, 0xe3d3, 0x0000, 0x0000, 0xe3c2, 0x0000, 0x0000, 0xe3ac,
+ 0xe3ca, 0xbb58, 0xe3bb, 0xe3c5, 0xbb5b, 0xe3be, 0xbb59, 0xe3af,
+ 0xe3cd, 0xe3ae, 0xe3c1, 0x0000, 0xe3ad, 0x0000, 0x0000, 0xe3bf,
+ 0xe3c8, 0xe3c6, 0xe3ba, 0xe3b5, 0xe3b3, 0x0000, 0xe3b4, 0xe3c7,
+ 0xe3d2, 0xe3bc, 0xbb5a, 0x0000, 0xe3b7, 0x0000, 0xe3cb, 0x0000,
+ 0xbb5d, 0xe3b6, 0xe3b0, 0xe3c0, 0xbb61, 0x0000, 0x0000, 0xbb55,
+ 0xbb5e, 0xe3b8, 0xe3b2, 0x0000, 0xbb57, 0xdfd4, 0xbb56, 0xe3c3,
+ 0x0000, 0xbb54, 0xbb63, 0xbb5c, 0xe3c4, 0xe3b9, 0xe3b1, 0xe3cc,
+ 0xe3bd, 0xbb62, 0xe3d0, 0xbb5f, 0xe3cf, 0x0000, 0xe3c9, 0xe3ce,
+ 0x0000, 0x0000, 0x0000, 0xe3d1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe773,
+ 0xe774, 0xe767, 0xe766, 0xe762, 0xbdb4, 0x0000, 0xbdac, 0xe776,
+ 0xe775, 0xdfa9, 0xe75f, 0xe763, 0xe75d, 0x0000, 0xe770, 0xe761,
+ 0x0000, 0xe777, 0xe75a, 0xe758, 0xe764, 0xe76e, 0xe769, 0xbdb6
+};
+
+static const unsigned short big5_from_unicode_85[] = {
+ 0xe74f, 0x0000, 0xe76d, 0x0000, 0x0000, 0x0000, 0xbdb7, 0xdfbd,
+ 0xe75b, 0xe752, 0xe755, 0xe77b, 0xe75c, 0xe753, 0xe751, 0xe74e,
+ 0x0000, 0xbdb0, 0xe765, 0xbdaf, 0xbdb3, 0xe760, 0xe768, 0xbda9,
+ 0xe778, 0xe77c, 0xbdab, 0x0000, 0xe757, 0xe76b, 0xe76f, 0xe754,
+ 0xe779, 0xbdb2, 0x0000, 0xbdb1, 0xe74c, 0xbdb5, 0xe772, 0xe756,
+ 0xe76a, 0xe750, 0xe75e, 0xe759, 0xbdad, 0xbdae, 0xe76c, 0xe77d,
+ 0xe77a, 0xe771, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe74d, 0x0000, 0xbdaa, 0xeb49, 0x0000,
+ 0xeb40, 0xeb43, 0x0000, 0xbfbb, 0xeb45, 0xeaf9, 0xeb41, 0xeb47,
+ 0xbfb8, 0xbfbc, 0xbfb6, 0x0000, 0x0000, 0xeafb, 0xeb4c, 0x0000,
+ 0x0000, 0xeb46, 0x0000, 0xeafc, 0xeb55, 0xeb4f, 0xeaf8, 0xee46,
+ 0xeafe, 0xbfb7, 0x0000, 0xeb4a, 0x0000, 0xeb54, 0xbfbf, 0x0000,
+ 0xeb51, 0xeafd, 0xeb44, 0xeb48, 0xeb42, 0xeb56, 0xeb53, 0xeb50,
+ 0xbfb9, 0xbfba, 0xbfbe, 0xeafa, 0xeb57, 0xbfbd, 0xeb4d, 0x0000,
+ 0x0000, 0xeb4b, 0x0000, 0x0000, 0x0000, 0xeb4e, 0xee53, 0xee40,
+ 0xee45, 0xee52, 0xee44, 0xedfb, 0xee41, 0x0000, 0xc1a2, 0x0000,
+ 0xedf4, 0xee4d, 0xee4f, 0xedf3, 0xc1a1, 0xee51, 0xee49, 0xc1a8,
+ 0xee50, 0xee42, 0xc1aa, 0xedf9, 0xeb52, 0xee4a, 0xee47, 0xedf5,
+ 0xee55, 0xc1a4, 0x0000, 0x0000, 0xc1a5, 0xedf7, 0xee48, 0x0000,
+ 0xee54, 0xee4b, 0xedfd, 0xc1a7, 0xc1a3, 0xee4c, 0xedfe, 0xee56,
+ 0xedf8, 0xee43, 0xee4e, 0xedfa, 0xedfc, 0x0000, 0xc2cb, 0xedf6,
+ 0xc1a9, 0xc2c4, 0xc17e, 0x0000, 0x0000, 0x0000, 0x0000, 0xc1a6,
+ 0xc2c8, 0xf0b3, 0x0000, 0xf0a9, 0xf0a4, 0xf0aa, 0xf0b4, 0xf0b8,
+ 0xf0b7, 0xc2ca, 0xc2c9, 0x0000, 0x0000, 0xf0ab, 0xf0b9, 0xf0ae,
+ 0xf0a6, 0x0000, 0xf0a8, 0xf0a7, 0xf0ad, 0xf0b2, 0xf0a5, 0xf0ac,
+ 0xf0b1, 0xc2c7, 0x0000, 0xf0af, 0x0000, 0xc2c5, 0xf0b0, 0xc2c3,
+ 0xc2c6, 0xf2d5, 0xf0b5, 0x0000, 0x0000, 0xc3c2, 0x0000, 0xf2cd,
+ 0xf2d1, 0xf2c9, 0xf2cc, 0x0000, 0xf2d4, 0xc3c0, 0xf2d9, 0xf2d2,
+ 0x0000, 0xf2ca, 0xf2da, 0xf2d3, 0xc3c3, 0xc3c4, 0xf2d7, 0x0000,
+ 0xf2cb, 0xc3bf, 0xc3c1, 0xf2c6, 0xf2ce, 0xf2c8, 0x0000, 0xf2d8,
+ 0xf2d6, 0xf2c7, 0xf2cf, 0x0000, 0x0000, 0x0000, 0xf4be, 0xc3c5,
+ 0xf2d0, 0xc4a7, 0xc4a9, 0xc4a6, 0x0000, 0xf4c3, 0xf4bb, 0xf4b9
+};
+
+static const unsigned short big5_from_unicode_86[] = {
+ 0xf4bd, 0xf4ba, 0x0000, 0x0000, 0xf4bf, 0xf4c1, 0xc4aa, 0xc4ac,
+ 0x0000, 0xf4c0, 0xc4ad, 0xc4ab, 0xf4c2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc4a8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc4f4,
+ 0xf5f1, 0xf5f7, 0xc4f6, 0xf4bc, 0xf5f6, 0x0000, 0xf5fd, 0xf5f4,
+ 0xf5fb, 0xf5fa, 0xf4b8, 0xf5f5, 0xf0b6, 0xf5fe, 0xf5f3, 0xf5f8,
+ 0x0000, 0xf5fc, 0xf5f2, 0x0000, 0xf74a, 0xc4f5, 0xf5f9, 0x0000,
+ 0x0000, 0xf7f4, 0xf74b, 0xf749, 0xf747, 0xf748, 0xf74c, 0x0000,
+ 0xc5d9, 0xf7f2, 0xf7f0, 0xf7f5, 0xf7f3, 0x0000, 0xf7f6, 0xc5da,
+ 0xf7f1, 0x0000, 0x0000, 0xf8bc, 0x0000, 0x0000, 0xf945, 0xf946,
+ 0xf947, 0x0000, 0x0000, 0xf9c7, 0xf9bd, 0xca4f, 0xaaea, 0x0000,
+ 0xad68, 0x0000, 0xd3b8, 0xd3b7, 0xb040, 0xb342, 0xd77c, 0x0000,
+ 0x0000, 0xd77b, 0x0000, 0xb5ea, 0xb8b8, 0x0000, 0xb8b7, 0xb8b9,
+ 0x0000, 0xe3d4, 0xe77e, 0xeb58, 0xeb5a, 0xeb59, 0x0000, 0xc1ab,
+ 0xee57, 0xf0ba, 0xf9a5, 0xa6e4, 0x0000, 0xcdc9, 0xcdca, 0xcdc8,
+ 0xcdc7, 0xaaeb, 0x0000, 0xd0a9, 0xd0a7, 0x0000, 0x0000, 0xd0a6,
+ 0x0000, 0xad69, 0xad6b, 0xad6a, 0xd0a8, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd3c4, 0xd3c1, 0xd3bf,
+ 0x0000, 0x0000, 0xb041, 0xd3c2, 0xb046, 0xd3bc, 0xd3cb, 0x0000,
+ 0xd3cd, 0xd3bd, 0x0000, 0xb043, 0xd3ce, 0xd3c9, 0xd3bb, 0xd3c0,
+ 0xd3ca, 0xd3c6, 0xd3c3, 0x0000, 0xb048, 0xd3cc, 0xd3be, 0x0000,
+ 0x0000, 0xd3c7, 0xd3b9, 0xb047, 0xb044, 0xd3c5, 0x0000, 0xd3c8,
+ 0xd3ba, 0xb045, 0xb042, 0x0000, 0x0000, 0x0000, 0x0000, 0xb34c,
+ 0xd7a5, 0xb34b, 0x0000, 0xd7a8, 0xd7ab, 0xb348, 0xb346, 0xd77e,
+ 0xd7a9, 0xd7a7, 0xd7a4, 0xd7ac, 0xd7ad, 0xd7af, 0xd7b0, 0xd77d,
+ 0xb345, 0xd7a2, 0xd7a1, 0xd7ae, 0xb347, 0xd7a3, 0xb349, 0xb344,
+ 0xd7a6, 0xb34d, 0x0000, 0xb34a, 0xd7aa, 0x0000, 0x0000, 0x0000,
+ 0xb5f1, 0xdbbf, 0x0000, 0xdbb4, 0xb5ee, 0x0000, 0xdfe7, 0xdbbd,
+ 0xdbb1, 0xb5ec, 0xdbb6, 0xb5ef, 0xdbba, 0xdbb8, 0xb5f2, 0xb5eb,
+ 0x0000, 0x0000, 0xdbb2, 0xdbb5, 0xb5f0, 0x0000, 0xdbb3, 0x0000,
+ 0xdbbe, 0xdbbc, 0xdbb7, 0xdbb9, 0xdbbb, 0xb5ed, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdfe8, 0xdfee, 0xdfe4,
+ 0xdfea, 0xb8ba, 0xdfe6, 0xb8c0, 0x0000, 0x0000, 0xb8bf, 0x0000
+};
+
+static const unsigned short big5_from_unicode_87[] = {
+ 0xb8be, 0xdfed, 0xb8c1, 0xb8c2, 0xdfe3, 0xdff0, 0xb8c3, 0xb8bd,
+ 0xb8bc, 0xdfec, 0xb8c4, 0xdfe2, 0xdfe5, 0xdfef, 0xdfeb, 0x0000,
+ 0x0000, 0xe3f4, 0xe3e9, 0xb8bb, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xbb6a, 0xe3dd, 0xe3f2, 0xe3de, 0xbb65, 0x0000, 0xe3db, 0x0000,
+ 0xe3e4, 0xe3dc, 0xbb67, 0xe3d6, 0xe3f1, 0xbb68, 0xe3ee, 0xe3ef,
+ 0xe3d7, 0xbb6d, 0xe3e6, 0x0000, 0xe3e0, 0xe3e7, 0xe3da, 0x0000,
+ 0xe3f3, 0xe3eb, 0xe3e5, 0xe3d5, 0xbb69, 0xe3ec, 0x0000, 0xbb6c,
+ 0xe3f0, 0x0000, 0xe3ea, 0xbb66, 0xe3e8, 0x0000, 0xe3e2, 0xbb64,
+ 0xe3d9, 0xe3e1, 0xe3ed, 0xe3df, 0x0000, 0x0000, 0xe3e3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xbdc1, 0xdfe9, 0xe7b2, 0xe7bb,
+ 0xe7b1, 0xe7ad, 0xe7aa, 0xbdc2, 0xe7a8, 0xbb6b, 0xe7a1, 0xbdc0,
+ 0xe7a7, 0xbdbf, 0xe7ac, 0xe7a9, 0xe7b9, 0xe7b4, 0xe7ae, 0xe7b3,
+ 0xbdbb, 0xe7ab, 0xe7be, 0xe7a2, 0xe7a3, 0xe7ba, 0xbdbc, 0xe7bf,
+ 0xbdbe, 0xe7c0, 0xe7b0, 0xe3d8, 0xe7b6, 0xe7af, 0xe7b8, 0xe7b5,
+ 0x0000, 0x0000, 0x0000, 0xe7a6, 0xbdb9, 0xe7bd, 0xbdba, 0xe7a4,
+ 0xbdbd, 0xeb64, 0xe7b7, 0xe7bc, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeb61, 0xbdb8, 0xbfc0, 0xeb6b, 0xeb67, 0x0000, 0xeb65,
+ 0xeb60, 0xeb6f, 0x0000, 0x0000, 0x0000, 0xbfc4, 0x0000, 0xeb5c,
+ 0xeb68, 0xeb69, 0xeb5f, 0xeb5e, 0xeb6c, 0x0000, 0xeb62, 0xeb5d,
+ 0xeb63, 0x0000, 0xeb6e, 0xeb5b, 0xeb6d, 0xeb6a, 0xbfc2, 0xbfc1,
+ 0x0000, 0x0000, 0xbfc3, 0xeb66, 0xf0cb, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xee59, 0xc1b1, 0xee5d, 0xee5a, 0xee61, 0xee67,
+ 0xee5c, 0x0000, 0xee70, 0xc1ae, 0xee6a, 0xee5f, 0xee6b, 0xee66,
+ 0xee6d, 0xee5e, 0xc1b3, 0xc1b2, 0xee60, 0xee6e, 0xee58, 0xee6c,
+ 0xc1ac, 0x0000, 0xee64, 0xee63, 0xee68, 0xee5b, 0xc1b0, 0x0000,
+ 0xc1b4, 0xee62, 0xee69, 0xc1b5, 0xee65, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc1ad, 0xc1af, 0xf0c7, 0xf0c5, 0x0000, 0x0000, 0xf0cc,
+ 0xf0c9, 0xf0cd, 0x0000, 0xf0be, 0xf0c6, 0xf0d1, 0xee6f, 0xf0c2,
+ 0xc2cf, 0xe7a5, 0xf0bd, 0xf0ca, 0xf0c4, 0xf0c1, 0xf0bc, 0xf0bb,
+ 0xf0d0, 0x0000, 0xf0c0, 0xf0bf, 0xc2cd, 0xf0c8, 0x0000, 0xc2cc,
+ 0x0000, 0x0000, 0xc2ce, 0xf0c3, 0xf0cf, 0x0000, 0xf2de, 0xf2df,
+ 0x0000, 0xc3c9, 0xf2dc, 0xc3c6, 0xf2e4, 0x0000, 0xc3ca, 0xf2e6
+};
+
+static const unsigned short big5_from_unicode_88[] = {
+ 0xf2db, 0xf0ce, 0xf2e8, 0xf2dd, 0x0000, 0xc3c7, 0xf2e3, 0x0000,
+ 0xf2e5, 0xf2e0, 0xf2e7, 0xf2e2, 0xf2e1, 0xc3c8, 0x0000, 0x0000,
+ 0xf4c5, 0xf4c6, 0x0000, 0xf4c8, 0xc4ae, 0xc4af, 0xf4c9, 0xf4c7,
+ 0x0000, 0xf4c4, 0x0000, 0xf642, 0xf645, 0xf641, 0x0000, 0xc4fa,
+ 0xf643, 0xc4f9, 0xc4f8, 0xc4f7, 0xf644, 0xf751, 0xf74f, 0x0000,
+ 0xf74e, 0xf640, 0xf750, 0xf646, 0xf74d, 0x0000, 0xf7f9, 0xf7d7,
+ 0xf7f7, 0xc5db, 0xf7f8, 0xf7fa, 0x0000, 0xf8bf, 0xc5fa, 0xf8be,
+ 0xf8bd, 0xc5fb, 0x0000, 0xc65a, 0xf96e, 0xf9a7, 0xf9a6, 0xf9a8,
+ 0xa6e5, 0xd0aa, 0x0000, 0xd3cf, 0xd3d0, 0x0000, 0x0000, 0x0000,
+ 0xdbc0, 0x0000, 0xf647, 0xf8c0, 0xa6e6, 0xad6c, 0xd0ab, 0x0000,
+ 0x0000, 0x0000, 0xd7b1, 0xb34e, 0x0000, 0xdbc2, 0xdbc1, 0xb5f3,
+ 0x0000, 0xb8c5, 0xe7c1, 0xbdc3, 0x0000, 0xbdc4, 0x0000, 0x0000,
+ 0x0000, 0xbfc5, 0xc5fc, 0xa6e7, 0x0000, 0x0000, 0x0000, 0xd0ac,
+ 0xaaed, 0xd0ae, 0xd0ad, 0xad6d, 0x0000, 0xd3d1, 0x0000, 0xd3d8,
+ 0xb049, 0xd3d6, 0xd3d4, 0x0000, 0xd3db, 0xd3d2, 0xd3d3, 0xb04a,
+ 0x0000, 0xb04e, 0x0000, 0x0000, 0xd3dc, 0xb04d, 0xd3da, 0xd3d7,
+ 0xd3d5, 0xb04b, 0xb04c, 0xd3d9, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xb350, 0xd7b2, 0x0000, 0xb355, 0xd7c2, 0xb354, 0xd7c4, 0x0000,
+ 0x0000, 0xd7b8, 0xb352, 0xd7c3, 0x0000, 0xd7b3, 0xb353, 0xd7bf,
+ 0xd7bb, 0xd7bd, 0xd7b7, 0xd7be, 0x0000, 0x0000, 0xb34f, 0xd7ba,
+ 0x0000, 0xd7b9, 0xd7b5, 0x0000, 0xd7c0, 0x0000, 0x0000, 0xd7bc,
+ 0xd7b4, 0x0000, 0xd7b6, 0xb351, 0xd7c1, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb5f6, 0xdbcd, 0x0000, 0x0000, 0x0000, 0xdbc9, 0xdbcb,
+ 0xdbc6, 0xdbc5, 0xdbc3, 0x0000, 0xdbca, 0xdbcc, 0xdbc8, 0x0000,
+ 0xdbc7, 0xb5f4, 0xb5f5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xdbcf, 0xb8cd, 0xdff2, 0xdff8, 0xdff3, 0xdff4, 0x0000,
+ 0xdff9, 0x0000, 0xb8cf, 0x0000, 0xb8c7, 0xb8ce, 0xdff1, 0xdbc4,
+ 0xb8ca, 0xb8c8, 0xdff7, 0xdff6, 0xb8c9, 0xb8cb, 0xdff5, 0xb8c6,
+ 0x0000, 0xb8cc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3f6,
+ 0xbb74, 0x0000, 0x0000, 0xe442, 0xe441, 0x0000, 0xe3fb, 0xbb76,
+ 0xe440, 0xe3f7, 0xe3f8, 0xbb6e, 0xbb70, 0x0000, 0xe3fd, 0xe3f5,
+ 0xbb72, 0xbb71, 0xe3f9, 0xe3fe, 0xe3fc, 0xbb73, 0xe3fa, 0x0000
+};
+
+static const unsigned short big5_from_unicode_89[] = {
+ 0x0000, 0xdbce, 0xbb6f, 0x0000, 0x0000, 0xe7c2, 0xe7c9, 0xbdc6,
+ 0x0000, 0xe7cd, 0xbdca, 0xe7c5, 0xe7c3, 0x0000, 0xe7cc, 0x0000,
+ 0xbdc5, 0xe7cb, 0xbdc7, 0xbdc8, 0xe7c4, 0xbdc9, 0xe7ca, 0xe7c6,
+ 0xe7c7, 0xe7c8, 0xbb75, 0x0000, 0x0000, 0x0000, 0xeb70, 0xeb7c,
+ 0x0000, 0xbfca, 0xeb77, 0xeb79, 0x0000, 0xbfc8, 0xeb71, 0xeb75,
+ 0x0000, 0xeb78, 0xbfc6, 0xbfc9, 0xeb7b, 0xeb73, 0xeb74, 0xeb7a,
+ 0xeb72, 0xeb76, 0xbfc7, 0xee72, 0x0000, 0xee71, 0xc1b7, 0xee77,
+ 0xc1b9, 0x0000, 0x0000, 0xc1b6, 0xee73, 0xc1ba, 0xee74, 0x0000,
+ 0x0000, 0xee75, 0xee78, 0x0000, 0xc1b8, 0x0000, 0xf0d6, 0x0000,
+ 0x0000, 0xf0d9, 0x0000, 0xf0d3, 0xf0d5, 0x0000, 0x0000, 0xf0d4,
+ 0xf0d7, 0xf0d8, 0xee76, 0xf0d2, 0x0000, 0x0000, 0xc3cd, 0xf2ec,
+ 0xf2ef, 0xf2f1, 0xf2ea, 0xf2eb, 0xf2ee, 0xf2f0, 0xc3ce, 0xc3cc,
+ 0xc3cb, 0xf2ed, 0xf2e9, 0xf4ca, 0xc4b0, 0x0000, 0xf4cb, 0x0000,
+ 0x0000, 0xf649, 0xc4fb, 0xf64b, 0xc4fc, 0xf648, 0xf64a, 0xc5a8,
+ 0x0000, 0xf752, 0xc5a7, 0xf7fd, 0xf7fc, 0x0000, 0xf7fb, 0x0000,
+ 0x0000, 0xf948, 0xf949, 0xf94b, 0xf94a, 0x0000, 0xca50, 0xa6e8,
+ 0x0000, 0xad6e, 0xd7c5, 0xb5f7, 0x0000, 0xdffa, 0xc2d0, 0x0000,
+ 0xf2f2, 0x0000, 0x0000, 0xa8a3, 0x0000, 0x0000, 0x0000, 0xb357,
+ 0x0000, 0x0000, 0x0000, 0xb356, 0x0000, 0xdbd0, 0xb5f8, 0xdbd2,
+ 0xdbd1, 0x0000, 0x0000, 0xdffb, 0xb8d0, 0xe443, 0xe446, 0xe445,
+ 0x0000, 0xe444, 0xe7ce, 0xe7d0, 0xe7cf, 0x0000, 0xbfcc, 0x0000,
+ 0x0000, 0x0000, 0xbfcb, 0x0000, 0xc1bb, 0xee79, 0xee7b, 0xee7a,
+ 0x0000, 0x0000, 0xc2d1, 0x0000, 0x0000, 0x0000, 0xf2f4, 0xf2f3,
+ 0x0000, 0xf4cc, 0xc4b1, 0x0000, 0x0000, 0xc4fd, 0xf754, 0xf753,
+ 0xc65b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa8a4, 0xd0af, 0xad6f, 0xd7c8, 0xd7c6, 0x0000,
+ 0x0000, 0xd7c7, 0xdbd4, 0xdbd5, 0xe043, 0xdbd3, 0x0000, 0xdffc,
+ 0xe041, 0xe040, 0xe042, 0xb8d1, 0xdffe, 0xdffd, 0xe044, 0x0000,
+ 0xe449, 0xe447, 0x0000, 0xe448, 0xe7d3, 0xe7d1, 0x0000, 0x0000,
+ 0xe7d2, 0xeb7d, 0xee7c, 0xee7d, 0xc2d2, 0x0000, 0xf2f5, 0xf4cd,
+ 0xc4b2, 0x0000, 0xf64c, 0xf755, 0xc5a9, 0x0000, 0xf7fe, 0xf94c
+};
+
+static const unsigned short big5_from_unicode_8a[] = {
+ 0xa8a5, 0x0000, 0xad71, 0xad72, 0xd0b0, 0x0000, 0x0000, 0xd0b1,
+ 0xad70, 0x0000, 0xb054, 0x0000, 0xb052, 0x0000, 0xb051, 0xb058,
+ 0xb050, 0xb059, 0xd3dd, 0xb056, 0x0000, 0xb053, 0xb057, 0xb055,
+ 0xb04f, 0x0000, 0x0000, 0xb35f, 0x0000, 0xb359, 0xd7cc, 0xb35e,
+ 0x0000, 0x0000, 0xb360, 0xb35a, 0x0000, 0xb35b, 0x0000, 0xd7ca,
+ 0x0000, 0x0000, 0xb358, 0x0000, 0xd7cb, 0xb35d, 0x0000, 0x0000,
+ 0xd7c9, 0xb35c, 0x0000, 0x0000, 0xb644, 0x0000, 0xb646, 0x0000,
+ 0x0000, 0xdbd8, 0xb645, 0xb5f9, 0xb5fd, 0x0000, 0xb8e4, 0xe049,
+ 0xdbda, 0xb5fe, 0x0000, 0x0000, 0xdbdd, 0xdbde, 0xb643, 0x0000,
+ 0xdbe0, 0x0000, 0xdbe2, 0x0000, 0xdbe3, 0xdbd7, 0xdbd6, 0xdbe4,
+ 0xb642, 0xdbe1, 0xdbdf, 0x0000, 0xb640, 0xb5fb, 0xb647, 0xdbdb,
+ 0xdbdc, 0xdbd9, 0x0000, 0xb641, 0x0000, 0x0000, 0xb5fc, 0x0000,
+ 0xb5fa, 0xe048, 0xb8df, 0xb8da, 0x0000, 0x0000, 0xb8d5, 0x0000,
+ 0xb8e5, 0xb8d6, 0x0000, 0xb8d2, 0xb8e1, 0xb8de, 0xb8e0, 0x0000,
+ 0xb8d7, 0xb8dc, 0xb8d3, 0xb8d4, 0xe050, 0xe04d, 0xe045, 0xe04a,
+ 0x0000, 0xb8e2, 0xe051, 0xb8e3, 0xb8d9, 0x0000, 0x0000, 0xe047,
+ 0x0000, 0xe04f, 0xe04b, 0xe04e, 0xe04c, 0xb8dd, 0xe046, 0xb8d8,
+ 0x0000, 0x0000, 0x0000, 0xe44c, 0xbb78, 0xbb7b, 0x0000, 0xe44e,
+ 0x0000, 0xbba5, 0xe44d, 0xbb7d, 0x0000, 0xbdcf, 0xe44f, 0x0000,
+ 0xbba4, 0xe44b, 0xbba6, 0x0000, 0x0000, 0x0000, 0xbb79, 0x0000,
+ 0xb8db, 0xbb7c, 0x0000, 0xbb7a, 0xbb7e, 0xbba2, 0xbb77, 0xbba7,
+ 0xbba3, 0x0000, 0xbba1, 0xe44a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xbdd6, 0x0000, 0xbdd2, 0x0000, 0x0000, 0x0000, 0xbdd9, 0x0000,
+ 0xe7d6, 0xbdda, 0xe7e2, 0xe7db, 0xbdcb, 0xe7e3, 0xe7dd, 0xbdd5,
+ 0xe7de, 0x0000, 0xbdd4, 0xe7e1, 0xbdce, 0xe7df, 0xe7d5, 0xbdcd,
+ 0xebaa, 0xbdd3, 0x0000, 0xbdd0, 0x0000, 0xbdd8, 0x0000, 0xe7d4,
+ 0x0000, 0xe7d8, 0xbdcc, 0xe7d7, 0xe7d9, 0xe7da, 0xbdd7, 0xe7dc,
+ 0xe7e0, 0xe7e4, 0x0000, 0xbddb, 0xbfd2, 0xeba5, 0xebab, 0xeba8,
+ 0xeb7e, 0xebac, 0xeba1, 0x0000, 0xeba7, 0x0000, 0xbfcd, 0xbfd3,
+ 0xebad, 0x0000, 0x0000, 0xbfcf, 0x0000, 0xbfd9, 0xbfd4, 0xebaf,
+ 0xeba9, 0xbfd0, 0xeba2, 0xbfda, 0xeba3, 0xeba4, 0xbfdb, 0xbfd8,
+ 0xbdd1, 0x0000, 0xbfce, 0xebb0, 0xbfdc, 0x0000, 0xbfd5, 0xebae
+};
+
+static const unsigned short big5_from_unicode_8b[] = {
+ 0xbfd1, 0xbfd6, 0xbfd7, 0x0000, 0xc1c3, 0xeea4, 0xeead, 0xeeaa,
+ 0xeeac, 0x0000, 0xc1c0, 0xeea5, 0x0000, 0xeeab, 0xc1bc, 0xeea7,
+ 0xc1c4, 0xeea3, 0xeea8, 0xeeaf, 0xeba6, 0xeea9, 0xeea2, 0xc1bd,
+ 0xeea1, 0xc1be, 0xeeb0, 0xc1bf, 0xeeae, 0xc1c2, 0xee7e, 0x0000,
+ 0xc1c1, 0x0000, 0xeea6, 0xf0dc, 0xf0ea, 0xf0e5, 0xf0e7, 0xf0db,
+ 0xc2d3, 0x0000, 0xf0da, 0xc2d6, 0xc2d5, 0x0000, 0xf0e9, 0xf0e1,
+ 0xf0de, 0xf0e4, 0x0000, 0xf0dd, 0x0000, 0xf0df, 0xf0e8, 0xf0e6,
+ 0x0000, 0xc2d4, 0xf0ed, 0xf0eb, 0xf0e2, 0xf0ec, 0xf0e3, 0x0000,
+ 0xf2f9, 0xc3cf, 0xf341, 0x0000, 0x0000, 0xf64f, 0xc3d6, 0xf0e0,
+ 0xf2f7, 0xc3d2, 0xf2f8, 0xf2fd, 0x0000, 0x0000, 0xc3d4, 0xc3d5,
+ 0xf2f6, 0xf340, 0xf342, 0xf2fa, 0xf2fc, 0xf2fe, 0xf2fb, 0xf343,
+ 0xc3d1, 0xc3d7, 0xc3d3, 0x0000, 0xc3d0, 0xf4d0, 0x0000, 0xc4b7,
+ 0xf4ce, 0x0000, 0x0000, 0xf4d2, 0x0000, 0xf4d3, 0xc4b5, 0xf4d4,
+ 0xf4d1, 0x0000, 0xf4cf, 0xc4b8, 0xc4b4, 0xf4d5, 0x0000, 0xc4b6,
+ 0xc4b3, 0x0000, 0x0000, 0x0000, 0xc4fe, 0x0000, 0x0000, 0xc540,
+ 0xf64e, 0xf64d, 0xf650, 0xf651, 0x0000, 0xc541, 0xf756, 0xf75b,
+ 0xc5aa, 0x0000, 0xf758, 0x0000, 0xf757, 0xf75a, 0xf759, 0x0000,
+ 0xf843, 0x0000, 0xc5dc, 0xf842, 0xf840, 0x0000, 0xf841, 0x0000,
+ 0x0000, 0x0000, 0xc5fe, 0xc5fd, 0xf8c1, 0xf8c2, 0xc640, 0x0000,
+ 0xf94d, 0xf94e, 0xc667, 0x0000, 0xc66d, 0x0000, 0xf9a9, 0xf9c8,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_8c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa8a6,
+ 0x0000, 0xd7cd, 0x0000, 0xd7ce, 0xe052, 0xe450, 0xe7e5, 0xc1c6,
+ 0x0000, 0xc1c5, 0xf0ee, 0xf344, 0x0000, 0xf844, 0xa8a7, 0xd3de,
+ 0xb05a, 0xb361, 0xe054, 0xe053, 0xbddc, 0xe7e6, 0xbddd, 0xeeb1,
+ 0xc2d7, 0x0000, 0x0000, 0x0000, 0xc676, 0xa8a8, 0xcdcb, 0xd3df,
+ 0x0000, 0x0000, 0xb362, 0x0000, 0xd7cf, 0xd7d0, 0x0000, 0xdbe5,
+ 0x0000, 0xb648, 0xb8e6, 0x0000, 0xe056, 0xe055, 0xe057, 0x0000,
+ 0xe451, 0xe452, 0xbba8, 0xbfdd, 0xbdde, 0xbfde, 0x0000, 0xeeb5,
+ 0xeeb2, 0xeeb4, 0xeeb3, 0xc1c7, 0x0000, 0xf0ef, 0xf346, 0xf345,
+ 0xcba4, 0xb05c, 0xb05b, 0xd3e0, 0x0000, 0xd7d1, 0x0000, 0x0000,
+ 0xdbe7, 0xdbe6, 0xb649, 0x0000, 0xe059, 0xe05a, 0xe058, 0x0000,
+ 0x0000, 0xb8e8, 0xb8e7, 0x0000, 0xbbaa, 0xbba9, 0x0000, 0xe7e7,
+ 0xebb3, 0xebb1, 0xebb2, 0xbfdf, 0xeeb7, 0xeeb6, 0x0000, 0xf0f2,
+ 0xf0f1, 0xf0f0, 0xf347, 0x0000, 0xf9aa, 0xa8a9, 0xad73, 0x0000,
+ 0xad74, 0xb05d, 0xb05e, 0xd3e2, 0xd3e1, 0xd7d2, 0x0000, 0xb368,
+ 0xb366, 0xb363, 0xb367, 0xb365, 0xb364, 0x0000, 0x0000, 0xb64a,
+ 0xdbea, 0x0000, 0xb8ed, 0xb64c, 0xb651, 0xdbec, 0xb653, 0xb652,
+ 0xb655, 0xdbeb, 0xdbe8, 0xb64f, 0xb64b, 0xb64d, 0xdbe9, 0xb654,
+ 0xb650, 0xb64e, 0xb8ef, 0xb8ee, 0xb8ec, 0xb8f0, 0x0000, 0xb8ea,
+ 0xb8eb, 0x0000, 0xb8e9, 0x0000, 0xe05b, 0x0000, 0x0000, 0xe454,
+ 0x0000, 0xbbac, 0xbbad, 0xbbab, 0x0000, 0xe453, 0x0000, 0xe455,
+ 0x0000, 0xe7ea, 0xe7ec, 0x0000, 0xbde7, 0xe7ed, 0xbde0, 0xe7e9,
+ 0xbddf, 0xbde9, 0xbde5, 0xbde6, 0xbde2, 0xe7e8, 0xbde1, 0xe7ee,
+ 0xe7eb, 0x0000, 0xbde8, 0x0000, 0xbde3, 0xbde4, 0xebb5, 0x0000,
+ 0xebb7, 0xebb6, 0x0000, 0xebb8, 0xbfe0, 0xebb4, 0x0000, 0x0000,
+ 0xc1cb, 0xeeb8, 0xc1c8, 0xc1cc, 0xc1ca, 0xc1c9, 0xf0f3, 0x0000
+};
+
+static const unsigned short big5_from_unicode_8d[] = {
+ 0xf0f6, 0x0000, 0xf0f5, 0x0000, 0xf0f4, 0xc2d8, 0xf348, 0xf349,
+ 0xc3d8, 0xf34a, 0xc3d9, 0x0000, 0x0000, 0xc4ba, 0x0000, 0xc4b9,
+ 0xf652, 0x0000, 0x0000, 0xc542, 0xf653, 0xf75c, 0xc5ab, 0xc5ac,
+ 0x0000, 0xf845, 0x0000, 0xc642, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa8aa, 0x0000, 0xb36a, 0xb369,
+ 0xe05c, 0xe05d, 0x0000, 0xbbae, 0xebb9, 0xbdea, 0xebba, 0xeeb9,
+ 0xa8ab, 0x0000, 0xd0b2, 0xad76, 0xad75, 0x0000, 0xd3e3, 0xb05f,
+ 0xd3e4, 0xd7d5, 0x0000, 0xd7d4, 0x0000, 0xd7d3, 0x0000, 0x0000,
+ 0xdbee, 0xb658, 0x0000, 0x0000, 0xdbed, 0xb657, 0x0000, 0x0000,
+ 0x0000, 0xdbef, 0xb656, 0x0000, 0xe05f, 0xe062, 0xe060, 0xe061,
+ 0xe065, 0xe05e, 0xe066, 0xe063, 0xe064, 0xbbb0, 0xe456, 0x0000,
+ 0x0000, 0xbbaf, 0x0000, 0xe7f2, 0xe7f0, 0x0000, 0x0000, 0xbdeb,
+ 0xe7ef, 0xe7f1, 0x0000, 0xbdec, 0x0000, 0xebbb, 0x0000, 0xebbc,
+ 0xc1cd, 0x0000, 0xf34c, 0xf34e, 0xf34b, 0xf34d, 0xf4d6, 0xf654,
+ 0x0000, 0x0000, 0xf96f, 0xa8ac, 0xad77, 0xd3e5, 0xd3e7, 0xd3e6,
+ 0x0000, 0xd7d8, 0xb36c, 0x0000, 0xd7d6, 0x0000, 0xb36b, 0xd7d9,
+ 0x0000, 0xd7da, 0xd7d7, 0x0000, 0x0000, 0xdbfb, 0xb660, 0xdbf3,
+ 0xdbf9, 0x0000, 0x0000, 0xb65b, 0xb65e, 0xdbf2, 0xb659, 0xdbf6,
+ 0xe06c, 0xb65d, 0x0000, 0xdbf1, 0x0000, 0xdbf7, 0xdbf4, 0xdbfa,
+ 0xdbf0, 0xdbf8, 0xb65c, 0xb65f, 0xdbf5, 0xb65a, 0x0000, 0xb8f2,
+ 0xe068, 0xb8f1, 0xe06f, 0xe06e, 0xb8f8, 0x0000, 0xb8f9, 0xe070,
+ 0xb8f3, 0xe06d, 0xb8f7, 0xe072, 0xe069, 0x0000, 0xe06b, 0xb8f4,
+ 0xe067, 0xe06a, 0xe071, 0xb8f5, 0xe073, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xb8f6, 0x0000, 0xbbb1, 0xe45b, 0xe461, 0xe459
+};
+
+static const unsigned short big5_from_unicode_8e[] = {
+ 0xe462, 0x0000, 0xe458, 0xe45d, 0xe463, 0xe460, 0xe45f, 0xe45e,
+ 0x0000, 0xe457, 0xe45c, 0x0000, 0x0000, 0xe45a, 0x0000, 0xbdf1,
+ 0xbdee, 0xe7fb, 0xe841, 0xe843, 0xe840, 0xe7f8, 0xe7fa, 0xe845,
+ 0xe842, 0xe7fc, 0xe846, 0xe7f9, 0xe844, 0xbdef, 0xbdf5, 0xbdf3,
+ 0xe7f3, 0xbdf4, 0xbdf0, 0xe7f4, 0xe7f6, 0xe7f5, 0xe7fd, 0xe7fe,
+ 0x0000, 0xbdf2, 0x0000, 0xbded, 0x0000, 0x0000, 0xe7f7, 0x0000,
+ 0xebc6, 0xbfe2, 0x0000, 0xebbd, 0xbfe3, 0xbfe6, 0xebc2, 0x0000,
+ 0xebbf, 0xbfe5, 0x0000, 0x0000, 0xebc3, 0xebc4, 0xebbe, 0xebc7,
+ 0xebc0, 0xebc5, 0xbfe4, 0x0000, 0xbfe1, 0xebc1, 0x0000, 0xeebf,
+ 0xc1d0, 0xc1ce, 0xc1d1, 0xc1cf, 0xeebe, 0xeebb, 0xeeba, 0x0000,
+ 0xeebd, 0x0000, 0x0000, 0xeebc, 0xf145, 0xc2de, 0xf0fb, 0xf0fa,
+ 0x0000, 0xc2d9, 0xf141, 0xf140, 0xf0f7, 0xf143, 0xf0fc, 0xc2dd,
+ 0xf0f9, 0xf142, 0xf0f8, 0xc2da, 0xc2dc, 0xf0fd, 0xc2db, 0xf0fe,
+ 0x0000, 0xf144, 0xf352, 0x0000, 0xc3de, 0xf34f, 0x0000, 0xf353,
+ 0x0000, 0x0000, 0xc3db, 0xf351, 0xc3e0, 0x0000, 0xc3dd, 0x0000,
+ 0xf350, 0x0000, 0xc3df, 0xf354, 0xc3da, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc4bc, 0xc4be, 0x0000, 0xf4d9, 0xc4bd, 0xf4d7, 0xc3dc,
+ 0xf4d8, 0xc4bb, 0xc543, 0xc545, 0xf656, 0xc544, 0xf655, 0x0000,
+ 0xf761, 0xc5ad, 0xf760, 0xc5ae, 0xf75e, 0xf75d, 0xf762, 0xf763,
+ 0xf846, 0x0000, 0xf75f, 0x0000, 0x0000, 0xf8c6, 0xf8c3, 0xf8c4,
+ 0xf8c5, 0xc65c, 0x0000, 0xf951, 0xf950, 0xf94f, 0xf970, 0x0000,
+ 0xf9be, 0xf9ab, 0xc66e, 0xa8ad, 0xb060, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xb8fa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xbdf6, 0x0000, 0x0000, 0xebc8, 0x0000, 0x0000,
+ 0xc2df, 0x0000, 0xf355, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf9ac, 0xa8ae, 0xaaee, 0xad79, 0xad78, 0x0000, 0xb063,
+ 0x0000, 0xd3e8, 0xb061, 0xd3e9, 0xb062, 0x0000, 0x0000, 0xd7df,
+ 0xd7db, 0x0000, 0x0000, 0xb36d, 0xd7de, 0xd7dd, 0xd7dc, 0xb36e,
+ 0xd7e0, 0xd7e1, 0x0000, 0x0000, 0x0000, 0xdc43, 0xdc41, 0xdc45,
+ 0xdc46, 0xdc4c, 0x0000, 0xdc48, 0xdc4a, 0x0000, 0xdc42, 0xdbfc,
+ 0x0000, 0xdc49, 0x0000, 0x0000, 0xdc4b, 0xdc44, 0xdc47, 0xdbfd,
+ 0xb662, 0xdc40, 0xdbfe, 0xb661, 0xb663, 0x0000, 0xb8fd, 0xe075
+};
+
+static const unsigned short big5_from_unicode_8f[] = {
+ 0xe077, 0xe076, 0xe07b, 0xb8fb, 0x0000, 0xe078, 0xe074, 0xe079,
+ 0xe07a, 0xb8fc, 0xb8fe, 0xe07c, 0x0000, 0xe467, 0xe466, 0x0000,
+ 0xe464, 0xe465, 0xbbb3, 0xbbb5, 0xbbb2, 0xbbb4, 0xe84d, 0xe84e,
+ 0xe849, 0x0000, 0xe84a, 0xbdf8, 0xbdfd, 0xbdf7, 0xbdfe, 0xbdf9,
+ 0xe84b, 0x0000, 0x0000, 0xe84c, 0xe848, 0xbe40, 0xbdfb, 0x0000,
+ 0x0000, 0xbdfa, 0xbdfc, 0x0000, 0xe847, 0x0000, 0xebca, 0xbfe8,
+ 0x0000, 0x0000, 0xebcc, 0xbfea, 0xebcf, 0xebcb, 0xebc9, 0xebce,
+ 0xbfe9, 0xebcd, 0x0000, 0xbfe7, 0x0000, 0x0000, 0xc1d3, 0xc1d6,
+ 0xeec1, 0x0000, 0xc1d4, 0xeec0, 0xc1d2, 0xc1d5, 0xf146, 0xf147,
+ 0xf148, 0xc2e0, 0x0000, 0xf149, 0x0000, 0xc2e1, 0xc3e2, 0xf358,
+ 0xf359, 0xf357, 0xf356, 0xf35a, 0xc3e1, 0xf4dd, 0xf4db, 0xf4dc,
+ 0xf4de, 0xf4da, 0xf4df, 0xf658, 0x0000, 0xf659, 0xf657, 0xc546,
+ 0xf764, 0xc5af, 0xf765, 0xf848, 0xf847, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa8af, 0xb664, 0x0000, 0x0000, 0xb940,
+ 0x0000, 0x0000, 0x0000, 0xbbb6, 0x0000, 0x0000, 0xbfec, 0x0000,
+ 0xbfeb, 0x0000, 0x0000, 0x0000, 0x0000, 0xc3e3, 0xc47c, 0xc547,
+ 0xa8b0, 0xb064, 0xb941, 0x0000, 0xf35b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xcba6,
+ 0x0000, 0x0000, 0xa8b1, 0x0000, 0xa8b4, 0xa8b3, 0xa8b2, 0x0000,
+ 0x0000, 0xcba5, 0x0000, 0xcdcd, 0x0000, 0xcdcf, 0xaaef, 0x0000,
+ 0x0000, 0xaaf1, 0xcdcc, 0xcdce, 0xaaf0, 0xcdd1, 0xcdd0, 0xcdd2,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd0b6, 0xd0b4, 0xad7c, 0xd0b3, 0xada3, 0xad7e, 0xad7b, 0x0000,
+ 0xada4, 0x0000, 0xad7d, 0xada2, 0x0000, 0xada1, 0xd0b5, 0x0000,
+ 0xad7a, 0x0000, 0x0000, 0x0000, 0xb06a, 0xd3eb, 0xd3f1, 0xb067,
+ 0xb06e, 0x0000, 0xb069, 0xd3ee, 0xd3f0, 0xb06c, 0xd3ea, 0xd3ed
+};
+
+static const unsigned short big5_from_unicode_90[] = {
+ 0xb068, 0xb065, 0xd3ec, 0xb06b, 0xd3ef, 0xb06d, 0xb066, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xd7e3, 0xd7e6, 0xb370, 0x0000, 0xb37a,
+ 0xb376, 0xd7e4, 0x0000, 0x0000, 0xb37e, 0xb377, 0xb37c, 0xb372,
+ 0x0000, 0xb36f, 0xb371, 0xb37d, 0xd7e5, 0xb375, 0xb378, 0xb374,
+ 0xb379, 0xd7e7, 0xb37b, 0xb373, 0xd7e2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdc4d, 0xb665, 0xdc4f,
+ 0x0000, 0xb667, 0xb669, 0x0000, 0xdc4e, 0xb666, 0xb66a, 0x0000,
+ 0xb668, 0x0000, 0x0000, 0x0000, 0xb947, 0xe0a3, 0xb94f, 0xe07e,
+ 0x0000, 0xb950, 0xb945, 0x0000, 0xe0a1, 0x0000, 0x0000, 0xb94a,
+ 0x0000, 0xe0a2, 0xb943, 0xb942, 0x0000, 0xb94d, 0xb94c, 0xb94b,
+ 0xb949, 0xb94e, 0xe07d, 0xb944, 0xb946, 0xb948, 0x0000, 0x0000,
+ 0xbbb8, 0xbbbb, 0x0000, 0xbbbf, 0xbbb9, 0xbbbe, 0xbbbc, 0x0000,
+ 0xbbb7, 0x0000, 0xbbbd, 0xbbba, 0x0000, 0x0000, 0x0000, 0xe852,
+ 0xbe43, 0xbe41, 0x0000, 0xe853, 0x0000, 0xbe44, 0xbe42, 0xe851,
+ 0xe850, 0x0000, 0xbff0, 0xe84f, 0xbfee, 0xbfed, 0xebd0, 0xbe45,
+ 0xbfef, 0xebd1, 0xbff2, 0xebd2, 0xbff1, 0xc1d8, 0xeec3, 0xc1d7,
+ 0xc1dc, 0xc1da, 0xc1db, 0xc2e3, 0xc1d9, 0xeec2, 0xebd3, 0xc2e2,
+ 0xc2e4, 0x0000, 0xc3e4, 0xc3e5, 0x0000, 0xf4e0, 0x0000, 0xc5de,
+ 0xc5dd, 0xa8b6, 0x0000, 0x0000, 0xca55, 0xb06f, 0x0000, 0x0000,
+ 0xca53, 0xca51, 0x0000, 0xca54, 0x0000, 0x0000, 0xcbaa, 0xcba7,
+ 0xcbac, 0xcba8, 0xa8b7, 0xa8ba, 0x0000, 0xcba9, 0xa8b9, 0xcbab,
+ 0x0000, 0x0000, 0xa8b8, 0x0000, 0x0000, 0x0000, 0x0000, 0xcdd5,
+ 0xcdd7, 0xaaf4, 0xcdd3, 0xcdd6, 0xcdd4, 0xaaf2, 0xaaf5, 0x0000,
+ 0xaaf3, 0x0000, 0x0000, 0x0000, 0x0000, 0xd0b8, 0xd0bc, 0xd0b9,
+ 0x0000, 0xada7, 0x0000, 0xada8, 0x0000, 0xd0bb, 0x0000, 0xd0bd,
+ 0xd0bf, 0x0000, 0xada5, 0xd0be, 0x0000, 0x0000, 0xada6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd7ee, 0xd0ba, 0xd3f2, 0xd3fb,
+ 0xd3f9, 0xd3f4, 0xd3f5, 0xd3fa, 0xd3fc, 0xb071, 0x0000, 0xd3f7,
+ 0xd3f3, 0xb070, 0xb072, 0xd3f6, 0xd3fd, 0xd3f8, 0x0000, 0x0000,
+ 0xb3a1, 0xd7f1, 0xd7e9, 0xd7ef, 0xd7f0, 0xb3a2, 0x0000, 0xd7e8,
+ 0xd7ea, 0xd0b7, 0xd7ec, 0xd7ed, 0xd7eb, 0xb66c, 0x0000, 0x0000,
+ 0x0000, 0xdc56, 0xebd4, 0xdc57, 0xdc54, 0xb3a3, 0xb66e, 0xdc53
+};
+
+static const unsigned short big5_from_unicode_91[] = {
+ 0xdc59, 0xdc58, 0xb66b, 0xdc5c, 0xdc52, 0xdc5b, 0xdc50, 0xdc5a,
+ 0xdc55, 0xb66d, 0x0000, 0xe0aa, 0x0000, 0xe0a5, 0xe0ab, 0xe0a6,
+ 0xe0a4, 0xe0a7, 0xb951, 0x0000, 0xe0a9, 0x0000, 0xe0a8, 0xb952,
+ 0xbbc1, 0xbbc0, 0xe46e, 0xe471, 0xe469, 0xe46d, 0xbbc2, 0xe46c,
+ 0xe46a, 0xe470, 0xe46b, 0xe468, 0xe46f, 0x0000, 0xe859, 0xbe48,
+ 0xf14a, 0xe856, 0xe857, 0xe855, 0xdc51, 0xbe47, 0xe85a, 0xe854,
+ 0xbe46, 0xbe49, 0xe858, 0xebd5, 0xbff3, 0xebd6, 0xebd7, 0x0000,
+ 0xeec4, 0xc1dd, 0xf14b, 0xf14c, 0x0000, 0x0000, 0xf14d, 0xf35d,
+ 0xf35c, 0xf4e2, 0x0000, 0xf4e1, 0xf65b, 0xf65c, 0xf65a, 0xf766,
+ 0xc5b0, 0xa8bb, 0xadaa, 0xada9, 0xb075, 0xb074, 0xd440, 0xd441,
+ 0xd3fe, 0x0000, 0xb073, 0xd7f5, 0x0000, 0xd7f6, 0xd7f2, 0xb3a4,
+ 0xd7f3, 0x0000, 0xd7f4, 0x0000, 0x0000, 0x0000, 0x0000, 0xdc5f,
+ 0xdc61, 0xdc5d, 0xdc60, 0xb66f, 0xdc5e, 0xb670, 0x0000, 0x0000,
+ 0xdd73, 0xb955, 0xb954, 0x0000, 0xb953, 0x0000, 0xe0ac, 0xe0ad,
+ 0x0000, 0x0000, 0xe473, 0xe475, 0xbbc6, 0xbbc3, 0x0000, 0xbbc5,
+ 0xbbc4, 0xe474, 0xe472, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe861, 0xe85e, 0xe85f, 0xbe4d, 0xe860, 0xe85b, 0xe85c, 0xbe4a,
+ 0x0000, 0xbe4b, 0xe85d, 0xbe4c, 0x0000, 0xebdb, 0x0000, 0xebdc,
+ 0xebd9, 0xebda, 0xbff4, 0xebd8, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeec8, 0xeec5, 0xeec7, 0xc1e0, 0xeecb, 0xc1df, 0xeec9,
+ 0xeecc, 0xeeca, 0xeec6, 0xc1de, 0x0000, 0xf14f, 0x0000, 0xf150,
+ 0xf14e, 0x0000, 0xf152, 0xc2e5, 0xc2e6, 0xf35f, 0xc3e7, 0xf151,
+ 0xf35e, 0xc3e6, 0xf4e5, 0xf4e6, 0xc4bf, 0xf4e4, 0x0000, 0xf4e3,
+ 0x0000, 0xf65d, 0xc548, 0x0000, 0xf849, 0xf8c8, 0xf8c7, 0x0000,
+ 0xc643, 0xc65d, 0xf8c9, 0xf971, 0x0000, 0xc66f, 0xa8bc, 0xaaf6,
+ 0x0000, 0xb956, 0x0000, 0xc4c0, 0xa8bd, 0xadab, 0xb3a5, 0xb671,
+ 0xc2e7, 0xaaf7, 0x0000, 0xd0c1, 0xd0c0, 0xd442, 0x0000, 0xb078,
+ 0xb076, 0xb07a, 0xd444, 0x0000, 0xb079, 0xb077, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd443, 0xb3a8, 0xd7fc, 0x0000, 0xb3a7, 0xb3a9,
+ 0xd842, 0xb3ab, 0xd7fe, 0xd840, 0xd7f7, 0xb3aa, 0xd843, 0x0000,
+ 0x0000, 0xd7f9, 0x0000, 0xd7fa, 0xd7f8, 0xb3a6, 0x0000, 0xd841,
+ 0xd7fb, 0xd7fd, 0x0000, 0x0000, 0x0000, 0xdc6d, 0x0000, 0xdc6c
+};
+
+static const unsigned short big5_from_unicode_92[] = {
+ 0xdc6a, 0xdc62, 0xdc71, 0xdc65, 0xdc6f, 0xdc76, 0xdc6e, 0xb679,
+ 0x0000, 0xb675, 0xdc63, 0x0000, 0xdc69, 0xb677, 0x0000, 0xdc68,
+ 0xb678, 0xb67a, 0xdc6b, 0x0000, 0xb672, 0xb673, 0xdc77, 0xdc75,
+ 0x0000, 0xdc74, 0xdc66, 0x0000, 0xdc72, 0x0000, 0xb676, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xb674, 0xdc73, 0xdc64, 0xdc67, 0xdc70,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe4ba, 0xe0b7, 0x0000,
+ 0xe0b0, 0xe0c3, 0xe0cc, 0xe0b3, 0xb961, 0x0000, 0xe0c0, 0xb957,
+ 0xb959, 0xb965, 0xe0b1, 0x0000, 0x0000, 0xb95a, 0xb95c, 0xb966,
+ 0xb95b, 0x0000, 0x0000, 0x0000, 0x0000, 0xb964, 0xe0b9, 0x0000,
+ 0xe0ae, 0xb962, 0xe0b8, 0xb95e, 0xe0ca, 0xb963, 0xe0c8, 0xe0bc,
+ 0xe0c6, 0xb960, 0xe0af, 0xe0c9, 0xe0c4, 0x0000, 0xe0cb, 0xb958,
+ 0x0000, 0x0000, 0xb967, 0xb95d, 0x0000, 0x0000, 0xe0b5, 0x0000,
+ 0xe0bd, 0xe0c1, 0x0000, 0xe0c5, 0xb95f, 0xe0b4, 0xe0b2, 0xe0be,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe0bb, 0xe0ba, 0x0000, 0xe0bf,
+ 0xe0c2, 0x0000, 0xe0c7, 0x0000, 0x0000, 0x0000, 0xe478, 0x0000,
+ 0xbbc7, 0xe4a4, 0xe47a, 0xbbcc, 0xbbd0, 0xe4ad, 0xe4b5, 0xe4a6,
+ 0xbbc8, 0x0000, 0xe4aa, 0xe0b6, 0x0000, 0xbbc9, 0xe4b1, 0xe4b6,
+ 0xe4ae, 0x0000, 0xe4b0, 0xe4b9, 0xe4b2, 0xe47e, 0xe4a9, 0x0000,
+ 0x0000, 0xbbd1, 0x0000, 0xbbcd, 0xe47c, 0xe4ab, 0xbbcb, 0xe4a5,
+ 0xbbca, 0xe4b3, 0xe4a2, 0xe479, 0xbbce, 0xe4b8, 0x0000, 0x0000,
+ 0xe47b, 0xe4af, 0xe4ac, 0xe4a7, 0xe477, 0xe476, 0xe4a1, 0xe4b4,
+ 0xbbcf, 0xe4b7, 0xe47d, 0xe4a3, 0xbe52, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xbe5a, 0xbe55, 0xe8a4, 0xe8a1, 0xe867, 0xbe50,
+ 0x0000, 0x0000, 0x0000, 0xbe4f, 0xbe56, 0x0000, 0x0000, 0x0000,
+ 0xe865, 0xbe54, 0xe871, 0xe863, 0xe864, 0xbe4e, 0xe8a3, 0xbe58,
+ 0xe874, 0xe879, 0xe873, 0xebee, 0xe86f, 0xe877, 0xe875, 0xe868,
+ 0xe862, 0xe87d, 0xbe57, 0xe87e, 0x0000, 0xe878, 0x0000, 0xe86d,
+ 0xe86b, 0xe866, 0x0000, 0x0000, 0x0000, 0xe86e, 0xe87b, 0xe86a,
+ 0xe87a, 0xe8a2, 0x0000, 0x0000, 0xbe53, 0x0000, 0xe876, 0xe87c,
+ 0xe872, 0xe86c, 0xbe51, 0x0000, 0x0000, 0x0000, 0xe4a8, 0xe870,
+ 0xbe59, 0xe869, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xebf4,
+ 0xbff7, 0xebf3, 0xebf0, 0xec44, 0xbffb, 0x0000, 0xec41, 0xebf8
+};
+
+static const unsigned short big5_from_unicode_93[] = {
+ 0xec43, 0xebe9, 0xebf6, 0x0000, 0xbffd, 0x0000, 0xebe1, 0x0000,
+ 0xebdf, 0xec42, 0x0000, 0xec40, 0xebfe, 0xebed, 0xebec, 0xebe2,
+ 0xc040, 0x0000, 0xebe8, 0xebf2, 0xebfd, 0xc043, 0xec45, 0x0000,
+ 0xc1e8, 0xc045, 0xbffe, 0xebe6, 0x0000, 0xebef, 0xebde, 0xebe0,
+ 0xbff5, 0xc042, 0xbffa, 0xebe7, 0xebf7, 0xebf1, 0xc041, 0xebdd,
+ 0xc1e3, 0xebf9, 0xebfc, 0xbffc, 0x0000, 0xebeb, 0xc044, 0xbff9,
+ 0x0000, 0x0000, 0x0000, 0xbff8, 0xebf5, 0xebfb, 0xbff6, 0x0000,
+ 0xebe4, 0xebfa, 0x0000, 0x0000, 0xebe5, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xebea, 0xeed2,
+ 0x0000, 0xeed7, 0xc1e5, 0xc1e7, 0xeedd, 0xc1e1, 0xeeec, 0xeee3,
+ 0xeed8, 0xeed9, 0xeee2, 0x0000, 0xc1ee, 0xeee1, 0xeed1, 0xeee0,
+ 0xeed4, 0xeeed, 0xc1ed, 0xc1eb, 0xeed5, 0x0000, 0xeee8, 0x0000,
+ 0xeeda, 0xeee7, 0x0000, 0xeee9, 0xeed0, 0xc1e6, 0x0000, 0xeeea,
+ 0x0000, 0x0000, 0xeede, 0x0000, 0xc1ea, 0xeedb, 0x0000, 0x0000,
+ 0xc1ec, 0xeee4, 0x0000, 0x0000, 0x0000, 0xc1e4, 0xeed6, 0xeee5,
+ 0x0000, 0xeedf, 0xebe3, 0xeee6, 0xeed3, 0x0000, 0xc1e9, 0x0000,
+ 0xeeeb, 0x0000, 0xc1e2, 0xeece, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf160, 0xf159, 0xc2e9, 0x0000, 0xf154, 0xf163, 0xf15b, 0xeedc,
+ 0x0000, 0xf165, 0xf155, 0x0000, 0xc2e8, 0xf15f, 0xc2ea, 0xc2f2,
+ 0xc2f0, 0xf161, 0xc2f1, 0xf157, 0x0000, 0xf158, 0xf15d, 0xf162,
+ 0x0000, 0xeecd, 0xc2eb, 0xf16a, 0xf167, 0xf16b, 0xf15e, 0xf15a,
+ 0xf168, 0xf36a, 0xf15c, 0x0000, 0xc2ee, 0x0000, 0xc2ed, 0xeecf,
+ 0xc2ef, 0xf164, 0xf166, 0xc2ec, 0xf169, 0xf153, 0x0000, 0xf156,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf373, 0x0000, 0xf363, 0xc3eb, 0xf371, 0x0000, 0x0000, 0xf361,
+ 0xc3ec, 0x0000, 0xf36c, 0x0000, 0xf368, 0xc3f1, 0xf372, 0xf362,
+ 0xf365, 0xc3e9, 0xf374, 0x0000, 0xf36d, 0xf370, 0xc3ef, 0xc3f4,
+ 0xc3f2, 0xf369, 0xf364, 0x0000, 0xc3ed, 0xc3ee, 0xf360, 0xc3ea,
+ 0x0000, 0xc3e8, 0xc3f0, 0xf36f, 0xc3f3, 0x0000, 0xf36b, 0xf375,
+ 0xc3f5, 0x0000, 0x0000, 0x0000, 0xf367, 0x0000, 0xf36e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf4f3, 0xf542, 0xf4f5,
+ 0xf4fc, 0xf366, 0xf4fa, 0xf4e9, 0xf540, 0xc4c3, 0xf4ed, 0xf4fe
+};
+
+static const unsigned short big5_from_unicode_94[] = {
+ 0xf4f4, 0x0000, 0x0000, 0xc4c2, 0x0000, 0x0000, 0xf544, 0xf4f6,
+ 0x0000, 0xf4fb, 0xf4fd, 0xf4e7, 0xf541, 0xf4f2, 0xf4f7, 0xf4eb,
+ 0xf4ef, 0xf543, 0xf4f9, 0xf4e8, 0xf4ec, 0xf4ee, 0xf4f8, 0x0000,
+ 0xc4c1, 0xf4f1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf4ea, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf4f0, 0xf661, 0xf666, 0xc54f, 0xf668, 0x0000, 0xc549, 0x0000,
+ 0xf664, 0xf66a, 0xc54e, 0xc54a, 0x0000, 0xc54b, 0xf660, 0xf667,
+ 0xc54d, 0xf665, 0xc54c, 0xf65f, 0xf663, 0xf662, 0x0000, 0xf65e,
+ 0xf669, 0x0000, 0x0000, 0x0000, 0xc5b1, 0xf76d, 0xf770, 0xf76c,
+ 0xf76e, 0xf76f, 0xf769, 0xf76a, 0xf767, 0x0000, 0x0000, 0xf76b,
+ 0xf768, 0xc5b2, 0xc5b3, 0x0000, 0x0000, 0xf84b, 0x0000, 0xf84d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf84c, 0xf84e, 0x0000,
+ 0xc5e0, 0x0000, 0xf84a, 0xc5df, 0xc5e1, 0x0000, 0x0000, 0x0000,
+ 0xf8cb, 0xf8cc, 0xc644, 0xf8ca, 0x0000, 0xf953, 0xf952, 0xf954,
+ 0xc65f, 0xf955, 0xc65e, 0xf956, 0xf972, 0xf975, 0xf974, 0xc668,
+ 0xf973, 0x0000, 0x0000, 0x0000, 0xc672, 0xc670, 0xc671, 0xc677,
+ 0xf9c0, 0xf9c1, 0xf9bf, 0xf9c9, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_95[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xaaf8,
+ 0x0000, 0x0000, 0xd844, 0xdc78, 0xe8a5, 0xf376, 0x0000, 0x0000,
+ 0xaaf9, 0x0000, 0xadac, 0xb07b, 0x0000, 0x0000, 0xd845, 0x0000,
+ 0xd846, 0xb3ac, 0x0000, 0xb67d, 0xdc7a, 0xdc79, 0xb6a3, 0xb67c,
+ 0xdc7b, 0xb67e, 0xb6a2, 0xb6a1, 0xb67b, 0x0000, 0x0000, 0x0000,
+ 0xb968, 0x0000, 0x0000, 0xe0d0, 0xe0ce, 0x0000, 0xe0cf, 0xe0cd,
+ 0x0000, 0xbbd2, 0x0000, 0xbbd5, 0xbbd7, 0xbbd6, 0x0000, 0x0000,
+ 0xbbd3, 0xbbd4, 0x0000, 0xe8a7, 0xe8a6, 0xbe5b, 0xe8a8, 0x0000,
+ 0xe8a9, 0xbe5c, 0x0000, 0x0000, 0x0000, 0xec4d, 0xec4b, 0xeef3,
+ 0x0000, 0xec49, 0xec4a, 0xc046, 0xec46, 0xec4e, 0xec48, 0xec4c,
+ 0xeeef, 0x0000, 0x0000, 0xeef1, 0x0000, 0xeef2, 0xc1f3, 0xeeee,
+ 0xc1f2, 0xeef0, 0xc1ef, 0xc1f0, 0xc1f1, 0xec47, 0x0000, 0x0000,
+ 0xc2f5, 0xf16e, 0xf16c, 0xf16d, 0xc2f3, 0xc2f6, 0xc2f4, 0x0000,
+ 0x0000, 0x0000, 0xf377, 0xf378, 0xc3f6, 0x0000, 0xf545, 0xf547,
+ 0xf546, 0xc4c4, 0xc550, 0xf66d, 0xf66c, 0xf66b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_96[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xaafa, 0x0000, 0xc9aa, 0x0000,
+ 0xca58, 0xa6e9, 0xca56, 0xca59, 0xca57, 0x0000, 0x0000, 0x0000,
+ 0xcbae, 0x0000, 0xa8c1, 0x0000, 0xa8c2, 0xcbb0, 0xa8bf, 0xcbaf,
+ 0xcbad, 0xa8c0, 0xa8be, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xcdd8, 0xcddb, 0xaafd, 0xcdda, 0xcdd9, 0x0000, 0xaafc,
+ 0xaafb, 0x0000, 0xab40, 0xcddc, 0xaafe, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd0c6, 0xadae, 0xadaf, 0xadb0, 0xd0c7, 0xd0c3,
+ 0xadad, 0xd0c4, 0x0000, 0xd0c5, 0xd0c2, 0x0000, 0x0000, 0x0000,
+ 0xb0a4, 0x0000, 0x0000, 0xb0a1, 0xd445, 0xb0a2, 0xb0a5, 0xd446,
+ 0x0000, 0xb07e, 0xb07c, 0xb07d, 0xb0a3, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xb3ad, 0xd849, 0xb3b5, 0xd848, 0x0000, 0xd84b,
+ 0xb3b1, 0xd84a, 0xb6ab, 0xb3af, 0xb3b2, 0xb3ae, 0xb3b3, 0xb3b4,
+ 0xb3b0, 0x0000, 0x0000, 0x0000, 0xd847, 0xb6a7, 0xdc7d, 0x0000,
+ 0xdca3, 0x0000, 0x0000, 0xdca2, 0xb6ac, 0xb6a8, 0xb6a9, 0xdc7c,
+ 0xdc7e, 0xdca1, 0xb6a4, 0xb6a6, 0x0000, 0xb6aa, 0xb6a5, 0x0000,
+ 0x0000, 0xe0d3, 0xe0d1, 0xe0d2, 0xb96a, 0xb96b, 0x0000, 0xe0d4,
+ 0xb969, 0xbbd8, 0x0000, 0xbbda, 0xbbd9, 0x0000, 0xe4bb, 0x0000,
+ 0x0000, 0xe4bc, 0xe8ab, 0x0000, 0xe8aa, 0x0000, 0x0000, 0xc047,
+ 0xc048, 0xec4f, 0xc049, 0x0000, 0xeef6, 0x0000, 0xeef4, 0x0000,
+ 0xeef5, 0xc1f4, 0x0000, 0xf16f, 0xc3f7, 0x0000, 0x0000, 0x0000,
+ 0xc1f5, 0xab41, 0x0000, 0xb0a6, 0xd447, 0x0000, 0x0000, 0xd84c,
+ 0xb3b6, 0xb6ad, 0xdca4, 0xdca6, 0xb6af, 0xb6ae, 0xb6b0, 0xb6b1,
+ 0xdca5, 0xb96e, 0xb96f, 0xb96d, 0xbbdb, 0xb96c, 0xe0d5, 0x0000,
+ 0x0000, 0x0000, 0xbbdc, 0xe8ac, 0xec50, 0xc04a, 0xc1f6, 0xf170,
+ 0xf174, 0xc2f9, 0xf171, 0xc2fa, 0xc2f8, 0xf175, 0xc2fb, 0xf173,
+ 0x0000, 0xf379, 0xc2f7, 0xc3f8, 0x0000, 0xf8cd, 0x0000, 0x0000,
+ 0xab42, 0xb3b8, 0xb3b7, 0x0000, 0x0000, 0x0000, 0x0000, 0xb6b2,
+ 0xdca8, 0xdca7, 0xb6b3, 0x0000, 0x0000, 0xe0d9, 0xb973, 0xb970,
+ 0xe0d8, 0xb972, 0xe0d6, 0xb971, 0x0000, 0xe0d7, 0x0000, 0xe4bd
+};
+
+static const unsigned short big5_from_unicode_97[] = {
+ 0xbbdd, 0x0000, 0xe8af, 0x0000, 0xbe5d, 0xe8ad, 0xbe5e, 0xbe5f,
+ 0xe8ae, 0xbe60, 0x0000, 0xec51, 0x0000, 0xc04e, 0xc04b, 0xc050,
+ 0xec53, 0xc04c, 0xec52, 0xc04f, 0x0000, 0x0000, 0xc04d, 0x0000,
+ 0xeef9, 0xeefb, 0x0000, 0x0000, 0xc1f7, 0xeefa, 0xc1f8, 0xeef8,
+ 0xeef7, 0x0000, 0xf177, 0xf176, 0xc2fc, 0xf178, 0xf37e, 0xc3fa,
+ 0xf37d, 0xf37a, 0xc3f9, 0xf37b, 0xf37c, 0x0000, 0xf548, 0xf549,
+ 0xc4c5, 0x0000, 0xc553, 0x0000, 0x0000, 0xf66e, 0x0000, 0x0000,
+ 0xc551, 0xc552, 0xf66f, 0x0000, 0x0000, 0xc5b4, 0xc5b5, 0xf771,
+ 0x0000, 0x0000, 0xc645, 0xf8cf, 0xc647, 0x0000, 0xf8ce, 0xf8d0,
+ 0xc646, 0xf957, 0x0000, 0xf9ad, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xab43, 0x0000, 0x0000, 0x0000, 0xb974, 0x0000,
+ 0xe4be, 0x0000, 0xe8b0, 0xc051, 0x0000, 0x0000, 0xab44, 0x0000,
+ 0xbe61, 0xc3fb, 0xadb1, 0x0000, 0x0000, 0x0000, 0xc053, 0x0000,
+ 0xc5e2, 0xadb2, 0xd84d, 0x0000, 0xdca9, 0x0000, 0xdcab, 0x0000,
+ 0xdcaa, 0x0000, 0xe0dd, 0xe0da, 0xb975, 0x0000, 0xb976, 0xe0db,
+ 0xe0dc, 0x0000, 0xe4c0, 0xe4c5, 0xbbde, 0xe4bf, 0xe4c1, 0xe4c8,
+ 0xe4c3, 0xe4c7, 0xe4c4, 0xe4c2, 0xe4c6, 0xbbdf, 0x0000, 0x0000,
+ 0xe8b3, 0x0000, 0xe8b1, 0xbe63, 0x0000, 0xbe62, 0xe8b2, 0xbe64,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xec56, 0x0000, 0x0000, 0xec55,
+ 0xc054, 0xec54, 0xeefc, 0x0000, 0xeefe, 0xef41, 0xef40, 0x0000,
+ 0xc1f9, 0xeefd, 0xf1a1, 0xc2fd, 0xf17d, 0xf1a2, 0xc2fe, 0x0000,
+ 0xf17b, 0x0000, 0xf17e, 0xf17c, 0xf179, 0xc340, 0xf17a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf3a1, 0x0000, 0x0000, 0xf3a3, 0xf3a2,
+ 0x0000, 0xf54a, 0x0000, 0xf54b, 0x0000, 0x0000, 0x0000, 0xf670,
+ 0x0000, 0xc5b7, 0x0000, 0xc5b6, 0xf84f, 0xf850, 0xc648, 0xf8d1,
+ 0x0000, 0xc669, 0x0000, 0xadb3, 0xb6b4, 0xe4ca, 0xe4c9, 0xe8b5,
+ 0xe8b4, 0x0000, 0x0000, 0xc1fa, 0xef43, 0xef42, 0xf1a5, 0xf1a3,
+ 0xf1a6, 0xf1a4, 0x0000, 0x0000, 0xc3fc, 0xf3a4, 0xf3a5, 0xf3a6,
+ 0x0000, 0xf671, 0x0000, 0xf772, 0x0000, 0xf8d2, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xadb4, 0x0000, 0x0000,
+ 0xec57, 0xef44, 0x0000, 0xadb5, 0x0000, 0x0000, 0xbbe0, 0x0000,
+ 0xec58, 0xc341, 0xf1a7, 0xc3fd, 0x0000, 0xf54c, 0xf54d, 0xc554
+};
+
+static const unsigned short big5_from_unicode_98[] = {
+ 0xf851, 0xadb6, 0xb3bb, 0xb3bc, 0xd84e, 0xb6b5, 0xb6b6, 0xdcac,
+ 0xb6b7, 0x0000, 0xb97a, 0x0000, 0xb97c, 0xe0df, 0xe0e0, 0xe0de,
+ 0xb977, 0xb978, 0xb97b, 0xb979, 0x0000, 0x0000, 0xe4cb, 0xbbe1,
+ 0xbbe2, 0x0000, 0x0000, 0xe8bc, 0xbe67, 0xe8b7, 0xe8b6, 0x0000,
+ 0xe8bb, 0xbe65, 0x0000, 0x0000, 0xc05b, 0x0000, 0xe8b8, 0xe8bd,
+ 0xe8ba, 0xe8b9, 0x0000, 0xbe66, 0x0000, 0xc059, 0x0000, 0xec5a,
+ 0xc055, 0x0000, 0xec5b, 0x0000, 0x0000, 0xec59, 0x0000, 0xc058,
+ 0xc056, 0xc05a, 0x0000, 0xc057, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xef45, 0x0000, 0xef4a, 0xef46, 0xef49, 0xc1fb, 0x0000,
+ 0xedd4, 0xef48, 0xef47, 0x0000, 0xc344, 0xc342, 0xc345, 0xc343,
+ 0xf1a8, 0xf1a9, 0xf1aa, 0xc346, 0x0000, 0x0000, 0x0000, 0xf3aa,
+ 0xc440, 0xf3a8, 0x0000, 0xc441, 0xf3a7, 0xf3a9, 0xc3fe, 0xf551,
+ 0xf54e, 0x0000, 0xf54f, 0xf550, 0xf672, 0xc556, 0x0000, 0xc555,
+ 0x0000, 0xf774, 0xf773, 0xc5b8, 0x0000, 0x0000, 0x0000, 0xc5e3,
+ 0xc649, 0xc660, 0xf958, 0xf9ae, 0xf9af, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xadb7, 0xdcad, 0x0000, 0x0000, 0xe0e1, 0xe4cc, 0xe4cd, 0xbbe3,
+ 0x0000, 0xbbe4, 0xe8be, 0xbe68, 0x0000, 0x0000, 0xc1fc, 0x0000,
+ 0xf1ab, 0x0000, 0xc347, 0xf3ad, 0xc442, 0xf3ac, 0xf3ae, 0xf3ab,
+ 0xf675, 0xf552, 0xf553, 0x0000, 0xc4c6, 0x0000, 0xf674, 0x0000,
+ 0x0000, 0xf673, 0x0000, 0xf775, 0xf9b0, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xadb8, 0x0000, 0x0000, 0x0000, 0xadb9,
+ 0x0000, 0x0000, 0xb0a7, 0xd448, 0x0000, 0xd84f, 0x0000, 0xb6b8,
+ 0x0000, 0xb6bb, 0xb6b9, 0xdcae, 0x0000, 0xb6bd, 0x0000, 0xb6ba,
+ 0x0000, 0x0000, 0xb6bc, 0x0000, 0xb97e, 0x0000, 0xe0e2, 0x0000,
+ 0x0000, 0xe0e3, 0xe8c0, 0x0000, 0xb97d, 0xb9a1, 0xb9a2, 0x0000
+};
+
+static const unsigned short big5_from_unicode_99[] = {
+ 0xe4cf, 0x0000, 0xe4ce, 0xbbe5, 0x0000, 0xbbe6, 0x0000, 0xe4d0,
+ 0xe8bf, 0xbbe8, 0xbe69, 0x0000, 0xbbe7, 0x0000, 0x0000, 0x0000,
+ 0xc05c, 0xe8c1, 0xbe6b, 0xbe6a, 0xe8c2, 0xe8c5, 0xe8c3, 0xe8c4,
+ 0xbe6c, 0x0000, 0xc061, 0xc05f, 0x0000, 0x0000, 0xc05e, 0xec5d,
+ 0x0000, 0xc060, 0x0000, 0x0000, 0xec5c, 0xef4b, 0x0000, 0xec5e,
+ 0xc05d, 0xec5f, 0xef4e, 0xef4c, 0xef4d, 0xef52, 0xc34b, 0xef51,
+ 0xef54, 0xef53, 0xef50, 0xef4f, 0x0000, 0xc1fd, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf1ae, 0x0000, 0xf1ad, 0xc34a, 0xc348, 0xc349,
+ 0x0000, 0xf1ac, 0x0000, 0xf3b1, 0x0000, 0xc443, 0x0000, 0xf3b0,
+ 0xf3af, 0xc444, 0x0000, 0xf558, 0xf557, 0x0000, 0xf555, 0x0000,
+ 0xf554, 0xc4c8, 0xc4c7, 0xf559, 0xf776, 0xc5b9, 0xf677, 0xc557,
+ 0xf676, 0xf556, 0x0000, 0xf777, 0xc5e4, 0x0000, 0xc661, 0xf959,
+ 0x0000, 0xf9b1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xadba, 0xd850,
+ 0xef55, 0xadbb, 0x0000, 0x0000, 0xe4d2, 0xe4d1, 0xec60, 0x0000,
+ 0x0000, 0xef57, 0x0000, 0xef56, 0x0000, 0xc34c, 0xf3b2, 0xf3b3,
+ 0xc4c9, 0x0000, 0x0000, 0xf9b2, 0xb0a8, 0xb6bf, 0xb6be, 0xe0e4,
+ 0xe0e6, 0xb9a4, 0xe0e5, 0xb9a3, 0xb9a5, 0xe0e7, 0x0000, 0x0000,
+ 0x0000, 0xe4d4, 0xe4d6, 0xe4d5, 0x0000, 0xe4d8, 0x0000, 0x0000,
+ 0x0000, 0xbbe9, 0xe4d7, 0xe4d3, 0x0000, 0x0000, 0x0000, 0xe4d9,
+ 0x0000, 0xe8cc, 0x0000, 0xe8cf, 0xe8d1, 0xe8c7, 0xe8cb, 0xe8c8,
+ 0xbe6e, 0xbe71, 0xbe73, 0xe8c9, 0xe8ca, 0xbe72, 0xe8cd, 0xe8d0,
+ 0xe8ce, 0xbe74, 0x0000, 0xbe70, 0xe8c6, 0xbe6d, 0x0000, 0xbe6f,
+ 0x0000, 0x0000, 0xc063, 0xec66, 0xec64, 0xec63, 0x0000, 0xec69,
+ 0x0000, 0xec68, 0xec67, 0x0000, 0xec62, 0xc062, 0xec61, 0x0000,
+ 0xec65, 0xc064, 0x0000, 0x0000, 0xef5a, 0x0000, 0xef5e, 0xef5b,
+ 0xef5d, 0xef5c, 0xef59, 0xef5f, 0xef62, 0xef60, 0xef61, 0xc240
+};
+
+static const unsigned short big5_from_unicode_9a[] = {
+ 0x0000, 0xc1fe, 0xef58, 0xef63, 0xf1b3, 0xf1b6, 0xf1b8, 0xf1b7,
+ 0x0000, 0xf1b1, 0xf1b5, 0xf1b0, 0x0000, 0xf1b2, 0xc34d, 0xf1af,
+ 0x0000, 0xf1b4, 0x0000, 0x0000, 0xf3c0, 0xf3b5, 0xc445, 0x0000,
+ 0x0000, 0xc446, 0xf3b4, 0xf3b9, 0xf3bf, 0xf3b7, 0xf3be, 0x0000,
+ 0xf3bb, 0x0000, 0xf3ba, 0xf3bd, 0xf3b8, 0xf3b6, 0x0000, 0xf3bc,
+ 0x0000, 0xf560, 0xf55e, 0xc4ca, 0xf55d, 0xf563, 0xf561, 0x0000,
+ 0xc4cb, 0xf55c, 0xf55a, 0x0000, 0xf55b, 0xc4cd, 0xf55f, 0xc4cc,
+ 0xf562, 0xf678, 0xf67e, 0x0000, 0x0000, 0xf679, 0xc55b, 0xf6a1,
+ 0xc55a, 0xf67d, 0xf67c, 0xc559, 0xf67b, 0xc558, 0xf67a, 0x0000,
+ 0xf77d, 0xf7a1, 0xf77e, 0x0000, 0xf77b, 0xc5bb, 0xf778, 0xf77c,
+ 0xf7a3, 0x0000, 0xf7a2, 0xf779, 0xf77a, 0xc5ba, 0xf852, 0xc5e7,
+ 0x0000, 0xf853, 0xc5e5, 0xc5e6, 0x0000, 0x0000, 0xf8d3, 0xc64a,
+ 0xf976, 0x0000, 0xc66a, 0x0000, 0xf9b3, 0xc66b, 0xf9b4, 0xf9b5,
+ 0xf9c3, 0xf9c2, 0xc67a, 0xf9cd, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xb0a9, 0x0000, 0x0000, 0xe0e9, 0x0000, 0xe0e8, 0x0000, 0xbbea,
+ 0xbbeb, 0xe4da, 0x0000, 0xe8d2, 0xec6c, 0x0000, 0x0000, 0xbe75,
+ 0xc065, 0xec6a, 0x0000, 0xec6d, 0xc066, 0x0000, 0xef64, 0xec6b,
+ 0xf1b9, 0xc34e, 0xf3c1, 0x0000, 0x0000, 0x0000, 0xf566, 0xf564,
+ 0x0000, 0x0000, 0xf565, 0x0000, 0x0000, 0xf6a2, 0x0000, 0xc55c,
+ 0xf7a4, 0xc5ea, 0xc5bc, 0xc5e8, 0xc5e9, 0xf8d4, 0xc662, 0x0000,
+ 0xb0aa, 0x0000, 0x0000, 0x0000, 0xf1ba, 0x0000, 0x0000, 0xd449,
+ 0x0000, 0xb9a6, 0x0000, 0xe4db, 0x0000, 0x0000, 0xbbec, 0xe4dc,
+ 0x0000, 0x0000, 0x0000, 0xe8d4, 0xe8d3, 0xc068, 0xbe76, 0xbe77,
+ 0x0000, 0xe8d7, 0xe8d6, 0xe8d5, 0x0000, 0x0000, 0xec6e, 0xec71,
+ 0x0000, 0xec70, 0xec6f, 0xc067, 0xef68, 0xef66, 0xef65, 0x0000
+};
+
+static const unsigned short big5_from_unicode_9b[] = {
+ 0x0000, 0xef67, 0x0000, 0xc34f, 0xf1bc, 0xf1bd, 0xc350, 0x0000,
+ 0xf1bb, 0x0000, 0xf3c3, 0xf3c2, 0xf3c5, 0xc447, 0xf3c4, 0x0000,
+ 0xf567, 0xf569, 0xf568, 0x0000, 0x0000, 0xf6a3, 0xf6a6, 0xf6a4,
+ 0xf6a5, 0xf7a5, 0xc5bd, 0x0000, 0x0000, 0x0000, 0xf854, 0xf855,
+ 0xf856, 0x0000, 0xc64b, 0xc663, 0xf9b6, 0xb0ab, 0x0000, 0xbe78,
+ 0xc069, 0xf1be, 0x0000, 0xf7a6, 0x0000, 0x0000, 0xf9c4, 0xd44a,
+ 0x0000, 0xc67b, 0xb0ac, 0xec72, 0x0000, 0xf1bf, 0x0000, 0xf3c6,
+ 0x0000, 0x0000, 0xf6a7, 0xf7a7, 0xb0ad, 0x0000, 0xe4dd, 0xe4de,
+ 0x0000, 0xbbed, 0xbbee, 0xe8d9, 0xbe7a, 0xbe79, 0xe8d8, 0x0000,
+ 0xef69, 0x0000, 0xf1c0, 0xf1c2, 0xf1c1, 0xc353, 0xc352, 0xc351,
+ 0x0000, 0xc55e, 0xf6a8, 0x0000, 0xc55d, 0xf7a9, 0xf7a8, 0x0000,
+ 0xc64c, 0xf8d5, 0xb3bd, 0xe0ea, 0x0000, 0x0000, 0x0000, 0xe4e1,
+ 0xe4df, 0xe4e0, 0x0000, 0x0000, 0xe8e2, 0x0000, 0xe8dd, 0xe8da,
+ 0xe8e1, 0x0000, 0x0000, 0x0000, 0xe8e3, 0x0000, 0x0000, 0xbe7c,
+ 0xe8e0, 0xe8dc, 0x0000, 0x0000, 0xe8db, 0xe8df, 0xe8de, 0xbe7b,
+ 0x0000, 0x0000, 0xec7d, 0xec78, 0xec76, 0xeca1, 0xec77, 0x0000,
+ 0xec73, 0x0000, 0xec79, 0x0000, 0x0000, 0xec74, 0xef72, 0xec75,
+ 0xeca2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xec7c, 0xc06a, 0xec7b, 0xec7a, 0x0000, 0xec7e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xef6a, 0xef6d, 0x0000, 0x0000, 0xef6c, 0x0000,
+ 0xef74, 0xef6f, 0xef73, 0x0000, 0xef71, 0xef70, 0xef6e, 0x0000,
+ 0xef6b, 0x0000, 0xc243, 0xc242, 0x0000, 0xc244, 0xc241, 0xef75,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf1c8, 0xf1cb, 0x0000,
+ 0xf1c9, 0xf1cd, 0x0000, 0x0000, 0x0000, 0xf1ce, 0x0000, 0xf1c6,
+ 0xc358, 0xf1c7, 0x0000, 0xf1c5, 0xf1cc, 0x0000, 0xf1c4, 0xf1c3,
+ 0xc357, 0xc355, 0xc354, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf1ca, 0xf3cf, 0xf3d5, 0xc44a, 0xf3d0,
+ 0x0000, 0xf3d3, 0xf3d7, 0xc44b, 0xf3d2, 0x0000, 0xf3ca, 0x0000,
+ 0xf3c9, 0xf3d6, 0xf3cd, 0x0000, 0xf3cb, 0xf3d4, 0xf3cc, 0xc449,
+ 0xc448, 0x0000, 0xf3c7, 0xf3c8, 0xf3d1, 0x0000, 0x0000, 0x0000,
+ 0xf3ce, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf56c,
+ 0xf56f, 0x0000, 0x0000, 0x0000, 0x0000, 0xc356, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_9c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf56d, 0xf573, 0xf571,
+ 0xf56b, 0xf576, 0x0000, 0xf56a, 0x0000, 0xc4cf, 0xf572, 0x0000,
+ 0x0000, 0x0000, 0xf56e, 0xc4ce, 0xf575, 0x0000, 0x0000, 0xf574,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf6ab, 0xf6aa, 0x0000, 0x0000,
+ 0x0000, 0xf6b1, 0x0000, 0xf6ad, 0xf6b0, 0xc560, 0x0000, 0x0000,
+ 0xf6ae, 0xf6af, 0x0000, 0xf6a9, 0xf6ac, 0xc55f, 0x0000, 0x0000,
+ 0x0000, 0xc5bf, 0xf7b4, 0xf7af, 0xf7b3, 0x0000, 0xf7b6, 0xf7b2,
+ 0x0000, 0xf7ae, 0x0000, 0xc5c1, 0xf7b1, 0xf7b5, 0xc5c0, 0xf7ac,
+ 0xf570, 0xf7b0, 0x0000, 0x0000, 0xf7ad, 0x0000, 0xf7aa, 0x0000,
+ 0xf7ab, 0xc5be, 0xf85a, 0xf85c, 0xf85f, 0xf85b, 0xf860, 0x0000,
+ 0xf859, 0x0000, 0xf857, 0x0000, 0xc5eb, 0xf85d, 0xc5ed, 0xc5ec,
+ 0xf858, 0xf85e, 0x0000, 0x0000, 0x0000, 0x0000, 0xf8da, 0xc64d,
+ 0xf8db, 0x0000, 0xf8d9, 0xf8d6, 0x0000, 0x0000, 0xf8d8, 0xf8d7,
+ 0xf95a, 0x0000, 0x0000, 0x0000, 0x0000, 0xf95c, 0xf95b, 0x0000,
+ 0x0000, 0xf979, 0x0000, 0xf978, 0xf977, 0xf97a, 0x0000, 0xc673,
+ 0xc674, 0xf9ca, 0xf9ce, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb3be, 0xdcaf, 0xe0ed,
+ 0x0000, 0xb9a7, 0xe0eb, 0x0000, 0x0000, 0xe0ec, 0x0000, 0x0000,
+ 0x0000, 0xe4e2, 0xe4e3, 0xbbf1, 0xbbef, 0xe4e4, 0xbbf0, 0xe8e8,
+ 0x0000, 0xe8eb, 0xe8e5, 0xe8ec, 0xe8e4, 0xe8e6, 0x0000, 0xe8e7
+};
+
+static const unsigned short big5_from_unicode_9d[] = {
+ 0xe8ea, 0x0000, 0x0000, 0xbea1, 0xe8ef, 0xe8ee, 0xbe7d, 0xe8e9,
+ 0xe8ed, 0xbe7e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xecac, 0x0000, 0xc06f, 0x0000, 0xeca7, 0xc06b, 0x0000, 0xeca4,
+ 0xecaa, 0xecad, 0x0000, 0xc070, 0x0000, 0xeca9, 0xeca6, 0xecae,
+ 0xeca5, 0x0000, 0xecab, 0xc06c, 0x0000, 0xeca3, 0xc06d, 0x0000,
+ 0xc06e, 0xeca8, 0x0000, 0x0000, 0x0000, 0xefa9, 0xef7a, 0xef7b,
+ 0xef7e, 0xef7c, 0x0000, 0xef76, 0x0000, 0x0000, 0xef79, 0xefa5,
+ 0xef7d, 0x0000, 0x0000, 0xc245, 0x0000, 0xefa7, 0xefa4, 0xc246,
+ 0xefa6, 0xef77, 0xefa2, 0xefa3, 0x0000, 0xefa1, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf1d2, 0xf1d4, 0xf1d7, 0x0000, 0x0000, 0xf1d1,
+ 0x0000, 0xc359, 0xf1d9, 0xf1d0, 0xf1da, 0x0000, 0xf1d6, 0xf1d8,
+ 0xf1dc, 0xf1d5, 0xf1dd, 0xf1d3, 0xf1cf, 0xc35a, 0x0000, 0xf1db,
+ 0xc35b, 0xc44d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xef78,
+ 0xf3f1, 0xf3e8, 0xc44f, 0xf3e4, 0xc450, 0x0000, 0x0000, 0xf3ed,
+ 0xf3e7, 0xf3dd, 0xc44e, 0xf3ea, 0xf3e5, 0xf3e6, 0x0000, 0xf3d8,
+ 0xf3df, 0xf3ee, 0x0000, 0xf3eb, 0x0000, 0xf3e3, 0x0000, 0xf3ef,
+ 0xf3de, 0xf3d9, 0xf3ec, 0x0000, 0xf3db, 0xf3e9, 0xf3e0, 0xf3f0,
+ 0xf3dc, 0xc44c, 0xf3da, 0xf3e1, 0xf3e2, 0x0000, 0x0000, 0x0000,
+ 0xf57d, 0x0000, 0xf57b, 0x0000, 0xf5a2, 0x0000, 0xf5ae, 0xf5a5,
+ 0xf57c, 0xf578, 0xf5a7, 0xf57e, 0xf5a3, 0xf57a, 0xf5aa, 0xf577,
+ 0xf5a1, 0xf5a6, 0xf5a8, 0xf5ab, 0xf579, 0x0000, 0xf5af, 0xf5b0,
+ 0xf5a9, 0xf5ad, 0xf5a4, 0x0000, 0xf6c1, 0xf6c4, 0x0000, 0xc561,
+ 0x0000, 0xf6c3, 0xf6c8, 0xf6c6, 0xc562, 0xf6bd, 0xf6b3, 0xf6b2,
+ 0xc564, 0xf6bf, 0xf6c0, 0xf6bc, 0xf6b4, 0x0000, 0xf6b9, 0xf5ac,
+ 0x0000, 0xf6b5, 0xc563, 0xf6bb, 0x0000, 0xf6ba, 0x0000, 0xf6b6,
+ 0xf6c2, 0x0000, 0xf6b7, 0xf7bb, 0xf6c5, 0xf6c7, 0xf6be, 0xf6b8,
+ 0xf7bc, 0xf7be, 0xf7b8, 0xc5c2, 0x0000, 0xf7c5, 0xf7c3, 0xc5c3,
+ 0xf7c2, 0xf7c1, 0xf7ba, 0xf7b7, 0xf7bd, 0xf7c6, 0xf7b9, 0xf7bf,
+ 0x0000, 0xf869, 0xf86e, 0xf864, 0xf867, 0xc5ee, 0xf86b, 0x0000,
+ 0xf872, 0xf7c0, 0x0000, 0xf865, 0xf86f, 0xf873, 0xf86a, 0xf863,
+ 0xf86d, 0x0000, 0xf86c, 0xf871, 0xf870, 0xf7c4, 0xf868, 0xf862,
+ 0xf866, 0xc64e, 0xc64f, 0xf861, 0x0000, 0xf8e6, 0xf8dd, 0xf8e5
+};
+
+static const unsigned short big5_from_unicode_9e[] = {
+ 0xf8e2, 0xf8e3, 0xf8dc, 0xf8df, 0xf8e7, 0xf8e1, 0xf8e0, 0xf8de,
+ 0x0000, 0xf8e4, 0x0000, 0xf95d, 0x0000, 0xf95e, 0x0000, 0xf960,
+ 0xf95f, 0xf962, 0xf961, 0xf97c, 0xf97b, 0xf9b7, 0x0000, 0xf9b8,
+ 0x0000, 0xf9c5, 0xc678, 0xc67c, 0x0000, 0xf9cf, 0xc67d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb3bf, 0x0000, 0x0000,
+ 0x0000, 0xc4d0, 0xf6c9, 0x0000, 0xc650, 0xc651, 0x0000, 0xb3c0,
+ 0xe0ee, 0x0000, 0xb9a8, 0xe8f0, 0x0000, 0x0000, 0xecb0, 0xecb1,
+ 0xecaf, 0xefab, 0xefaa, 0xc247, 0xf1df, 0xefac, 0xf1de, 0x0000,
+ 0x0000, 0xf3f3, 0xc451, 0xc453, 0xf3f2, 0x0000, 0x0000, 0xc452,
+ 0x0000, 0xf5b1, 0xf5b3, 0xf5b2, 0xf6ca, 0xc565, 0x0000, 0xc5ef,
+ 0xf8e8, 0xf963, 0x0000, 0x0000, 0xf9d2, 0xb3c1, 0x0000, 0xe4e5,
+ 0x0000, 0xbea2, 0x0000, 0x0000, 0x0000, 0xecb3, 0xecb2, 0x0000,
+ 0xefad, 0x0000, 0x0000, 0x0000, 0xc454, 0xc4d1, 0xf7c7, 0xf9cb,
+ 0x0000, 0x0000, 0x0000, 0xb3c2, 0xbbf2, 0x0000, 0xbea3, 0x0000,
+ 0xf3f4, 0x0000, 0xf874, 0xb6c0, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xefae, 0x0000, 0x0000, 0x0000, 0xc664, 0xb6c1, 0xbea4, 0xc248,
+ 0xf875, 0xb6c2, 0x0000, 0xe8f1, 0xc072, 0xecb4, 0xecb5, 0x0000,
+ 0xc071, 0x0000, 0xefaf, 0xc24c, 0xc24a, 0xc24b, 0xc249, 0xf1e0,
+ 0xc35c, 0x0000, 0x0000, 0x0000, 0xf5b5, 0xf5b4, 0xf5b7, 0xf5b6,
+ 0xc4d2, 0x0000, 0x0000, 0xf6cb, 0x0000, 0xf6cd, 0xf6cc, 0xc566,
+ 0xf7c8, 0x0000, 0xf876, 0xf877, 0xc5f0, 0xf964, 0xf97d, 0xc675,
+ 0x0000, 0xdcb0, 0xecb6, 0xefb0, 0xf3f5, 0xe0ef, 0x0000, 0xefb1
+};
+
+static const unsigned short big5_from_unicode_9f[] = {
+ 0xf1e2, 0xf1e1, 0x0000, 0x0000, 0x0000, 0x0000, 0xf878, 0xc652,
+ 0x0000, 0xf965, 0xf97e, 0x0000, 0x0000, 0x0000, 0xb9a9, 0xe8f2,
+ 0xe8f3, 0x0000, 0xecb7, 0xb9aa, 0x0000, 0xc35d, 0xf1e3, 0x0000,
+ 0xf6cf, 0xc567, 0xf6d0, 0xf6ce, 0xf879, 0x0000, 0xf8e9, 0x0000,
+ 0xb9ab, 0x0000, 0xefb4, 0xefb3, 0xefb2, 0xf1e4, 0x0000, 0x0000,
+ 0xf1e8, 0xf1e7, 0xf1e6, 0xf1e5, 0xc35e, 0xf3f6, 0xf5b9, 0xc4d3,
+ 0xf5b8, 0xf6d1, 0xf7cb, 0xf7ca, 0xc5c4, 0xf7c9, 0xf87c, 0xf87b,
+ 0xf87a, 0x0000, 0x0000, 0xbbf3, 0x0000, 0xecb8, 0xc24d, 0x0000,
+ 0xf3f7, 0xf3f8, 0xf7cc, 0xf87d, 0x0000, 0x0000, 0xf8ea, 0xf966,
+ 0xf9b9, 0xf9d4, 0xbbf4, 0xc24e, 0xf1e9, 0xf3f9, 0xf6d2, 0xf87e,
+ 0x0000, 0x0000, 0xbea6, 0x0000, 0xefb5, 0xf1ea, 0xf3fa, 0xf3fb,
+ 0xf3fc, 0xf5be, 0x0000, 0xf5ba, 0xc568, 0xf5bd, 0xf5bc, 0xc4d4,
+ 0xf5bb, 0xc4d6, 0x0000, 0xc4d5, 0xf6d4, 0xf6d3, 0xc569, 0xc56a,
+ 0x0000, 0x0000, 0xc5c6, 0xf7cd, 0xc5c5, 0x0000, 0xf8a3, 0xf8a4,
+ 0xf8a2, 0xf8a1, 0xc654, 0x0000, 0xf8eb, 0xf8ec, 0xf8ed, 0xc653,
+ 0xf967, 0xf96a, 0xf969, 0xf968, 0x0000, 0x0000, 0xf9d3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc073, 0x0000, 0x0000,
+ 0xc365, 0xf5bf, 0xf6d5, 0x0000, 0xc5c7, 0xf7ce, 0x0000, 0x0000,
+ 0xf9d5, 0x0000, 0x0000, 0x0000, 0xc074, 0x0000, 0x0000, 0x0000,
+ 0xefb6, 0x0000, 0xf7cf, 0x0000, 0xf9a1, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_e0[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa55d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_e2[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xb7ec, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_e4[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc052, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_e7[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xca52, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_eb[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5e8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_fe[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa14a, 0xa157, 0x0000, 0xa159, 0xa15b, 0xa15f, 0xa160, 0xa163,
+ 0xa164, 0xa167, 0xa168, 0xa16b, 0xa16c, 0xa16f, 0xa170, 0xa173,
+ 0xa174, 0xa177, 0xa178, 0xa17b, 0xa17c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa1c6, 0xa1c7, 0xa1ca, 0xa1cb, 0xa1c8, 0xa1c9, 0xa15c,
+ 0xa14d, 0x0000, 0xa14f, 0x0000, 0xa151, 0xa152, 0xa153, 0xa154,
+ 0x0000, 0xa17d, 0xa17e, 0xa1a1, 0xa1a2, 0xa1a3, 0xa1a4, 0xa1cc,
+ 0xa1cd, 0xa1ce, 0xa1de, 0xa1df, 0xa1e0, 0xa1e1, 0xa1e2, 0x0000,
+ 0xa242, 0xa24c, 0xa24d, 0xa24e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5_from_unicode_ff[] = {
+ 0x0000, 0xa149, 0x0000, 0xa1ad, 0xa243, 0xa248, 0xa1ae, 0x0000,
+ 0xa15d, 0xa15e, 0xa1af, 0xa1cf, 0xa141, 0xa1d0, 0xa144, 0xa1fe,
+ 0xa2af, 0xa2b0, 0xa2b1, 0xa2b2, 0xa2b3, 0xa2b4, 0xa2b5, 0xa2b6,
+ 0xa2b7, 0xa2b8, 0xa147, 0xa146, 0xa1d5, 0xa1d7, 0xa1d6, 0xa148,
+ 0xa249, 0xa2cf, 0xa2d0, 0xa2d1, 0xa2d2, 0xa2d3, 0xa2d4, 0xa2d5,
+ 0xa2d6, 0xa2d7, 0xa2d8, 0xa2d9, 0xa2da, 0xa2db, 0xa2dc, 0xa2dd,
+ 0xa2de, 0xa2df, 0xa2e0, 0xa2e1, 0xa2e2, 0xa2e3, 0xa2e4, 0xa2e5,
+ 0xa2e6, 0xa2e7, 0xa2e8, 0x0000, 0xa240, 0x0000, 0x0000, 0xa1c4,
+ 0x0000, 0xa2e9, 0xa2ea, 0xa2eb, 0xa2ec, 0xa2ed, 0xa2ee, 0xa2ef,
+ 0xa2f0, 0xa2f1, 0xa2f2, 0xa2f3, 0xa2f4, 0xa2f5, 0xa2f6, 0xa2f7,
+ 0xa2f8, 0xa2f9, 0xa2fa, 0xa2fb, 0xa2fc, 0xa2fd, 0xa2fe, 0xa340,
+ 0xa341, 0xa342, 0xa343, 0xa161, 0xa155, 0xa162, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa14e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa1c3, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short * const big5_from_unicode_[] = {
+ big5_from_unicode_0,
+ u_allzeros,
+ big5_from_unicode_2,
+ big5_from_unicode_3,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ big5_from_unicode_20,
+ big5_from_unicode_21,
+ big5_from_unicode_22,
+ u_allzeros,
+ big5_from_unicode_24,
+ big5_from_unicode_25,
+ big5_from_unicode_26,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ big5_from_unicode_30,
+ big5_from_unicode_31,
+ big5_from_unicode_32,
+ big5_from_unicode_33,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ big5_from_unicode_4e,
+ big5_from_unicode_4f,
+ big5_from_unicode_50,
+ big5_from_unicode_51,
+ big5_from_unicode_52,
+ big5_from_unicode_53,
+ big5_from_unicode_54,
+ big5_from_unicode_55,
+ big5_from_unicode_56,
+ big5_from_unicode_57,
+ big5_from_unicode_58,
+ big5_from_unicode_59,
+ big5_from_unicode_5a,
+ big5_from_unicode_5b,
+ big5_from_unicode_5c,
+ big5_from_unicode_5d,
+ big5_from_unicode_5e,
+ big5_from_unicode_5f,
+ big5_from_unicode_60,
+ big5_from_unicode_61,
+ big5_from_unicode_62,
+ big5_from_unicode_63,
+ big5_from_unicode_64,
+ big5_from_unicode_65,
+ big5_from_unicode_66,
+ big5_from_unicode_67,
+ big5_from_unicode_68,
+ big5_from_unicode_69,
+ big5_from_unicode_6a,
+ big5_from_unicode_6b,
+ big5_from_unicode_6c,
+ big5_from_unicode_6d,
+ big5_from_unicode_6e,
+ big5_from_unicode_6f,
+ big5_from_unicode_70,
+ big5_from_unicode_71,
+ big5_from_unicode_72,
+ big5_from_unicode_73,
+ big5_from_unicode_74,
+ big5_from_unicode_75,
+ big5_from_unicode_76,
+ big5_from_unicode_77,
+ big5_from_unicode_78,
+ big5_from_unicode_79,
+ big5_from_unicode_7a,
+ big5_from_unicode_7b,
+ big5_from_unicode_7c,
+ big5_from_unicode_7d,
+ big5_from_unicode_7e,
+ big5_from_unicode_7f,
+ big5_from_unicode_80,
+ big5_from_unicode_81,
+ big5_from_unicode_82,
+ big5_from_unicode_83,
+ big5_from_unicode_84,
+ big5_from_unicode_85,
+ big5_from_unicode_86,
+ big5_from_unicode_87,
+ big5_from_unicode_88,
+ big5_from_unicode_89,
+ big5_from_unicode_8a,
+ big5_from_unicode_8b,
+ big5_from_unicode_8c,
+ big5_from_unicode_8d,
+ big5_from_unicode_8e,
+ big5_from_unicode_8f,
+ big5_from_unicode_90,
+ big5_from_unicode_91,
+ big5_from_unicode_92,
+ big5_from_unicode_93,
+ big5_from_unicode_94,
+ big5_from_unicode_95,
+ big5_from_unicode_96,
+ big5_from_unicode_97,
+ big5_from_unicode_98,
+ big5_from_unicode_99,
+ big5_from_unicode_9a,
+ big5_from_unicode_9b,
+ big5_from_unicode_9c,
+ big5_from_unicode_9d,
+ big5_from_unicode_9e,
+ big5_from_unicode_9f,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ big5_from_unicode_e0,
+ u_allzeros,
+ big5_from_unicode_e2,
+ u_allzeros,
+ big5_from_unicode_e4,
+ u_allzeros,
+ u_allzeros,
+ big5_from_unicode_e7,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ big5_from_unicode_eb,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ big5_from_unicode_fe,
+ big5_from_unicode_ff
+};
+
+struct charmap2 big5_from_unicode = { 0, 255, (unsigned short **) big5_from_unicode_, (unichar_t *) unicode_from_big5 };
+
+#endif
+
+const unichar_t unicode_from_big5hkscs[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xeeb8, 0xeeb9, 0xeeba, 0xeebb, 0xeebc, 0xeebd, 0xeebe, 0xeebf,
+ 0xeec0, 0xeec1, 0xeec2, 0xeec3, 0xeec4, 0xeec5, 0xeec6, 0xeec7,
+ 0xeec8, 0xeec9, 0xeeca, 0xeecb, 0xeecc, 0xeecd, 0xeece, 0xeecf,
+ 0xeed0, 0xeed1, 0xeed2, 0xeed3, 0xeed4, 0xeed5, 0xeed6, 0xeed7,
+ 0xeed8, 0xeed9, 0xeeda, 0xeedb, 0xeedc, 0xeedd, 0xeede, 0xeedf,
+ 0xeee0, 0xeee1, 0xeee2, 0xeee3, 0xeee4, 0xeee5, 0xeee6, 0xeee7,
+ 0xeee8, 0xeee9, 0xeeea, 0xeeeb, 0xeeec, 0xeeed, 0xeeee, 0xeeef,
+ 0xeef0, 0xeef1, 0xeef2, 0xeef3, 0xeef4, 0xeef5, 0xeef6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeef7, 0xeef8, 0xeef9, 0xeefa, 0xeefb, 0xeefc, 0xeefd,
+ 0xeefe, 0xeeff, 0xef00, 0xef01, 0xef02, 0xef03, 0xef04, 0xef05,
+ 0xef06, 0xef07, 0xef08, 0xef09, 0xef0a, 0xef0b, 0xef0c, 0xef0d,
+ 0xef0e, 0xef0f, 0xef10, 0xef11, 0xef12, 0xef13, 0xef14, 0xef15,
+ 0xef16, 0xef17, 0xef18, 0xef19, 0xef1a, 0xef1b, 0xef1c, 0xef1d,
+ 0xef1e, 0xef1f, 0xef20, 0xef21, 0xef22, 0xef23, 0xef24, 0xef25,
+ 0xef26, 0xef27, 0xef28, 0xef29, 0xef2a, 0xef2b, 0xef2c, 0xef2d,
+ 0xef2e, 0xef2f, 0xef30, 0xef31, 0xef32, 0xef33, 0xef34, 0xef35,
+ 0xef36, 0xef37, 0xef38, 0xef39, 0xef3a, 0xef3b, 0xef3c, 0xef3d,
+ 0xef3e, 0xef3f, 0xef40, 0xef41, 0xef42, 0xef43, 0xef44, 0xef45,
+ 0xef46, 0xef47, 0xef48, 0xef49, 0xef4a, 0xef4b, 0xef4c, 0xef4d,
+ 0xef4e, 0xef4f, 0xef50, 0xef51, 0xef52, 0xef53, 0xef54, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xef55, 0xef56, 0xef57, 0xef58, 0xef59, 0xef5a, 0xef5b, 0xef5c,
+ 0xef5d, 0xef5e, 0xef5f, 0xef60, 0xef61, 0xef62, 0xef63, 0xef64,
+ 0xef65, 0xef66, 0xef67, 0xef68, 0xef69, 0xef6a, 0xef6b, 0xef6c,
+ 0xef6d, 0xef6e, 0xef6f, 0xef70, 0xef71, 0xef72, 0xef73, 0xef74,
+ 0xef75, 0xef76, 0xef77, 0xef78, 0xef79, 0xef7a, 0xef7b, 0xef7c,
+ 0xef7d, 0xef7e, 0xef7f, 0xef80, 0xef81, 0xef82, 0xef83, 0xef84,
+ 0xef85, 0xef86, 0xef87, 0xef88, 0xef89, 0xef8a, 0xef8b, 0xef8c,
+ 0xef8d, 0xef8e, 0xef8f, 0xef90, 0xef91, 0xef92, 0xef93, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xef94, 0xef95, 0xef96, 0xef97, 0xef98, 0xef99, 0xef9a,
+ 0xef9b, 0xef9c, 0xef9d, 0xef9e, 0xef9f, 0xefa0, 0xefa1, 0xefa2,
+ 0xefa3, 0xefa4, 0xefa5, 0xefa6, 0xefa7, 0xefa8, 0xefa9, 0xefaa,
+ 0xefab, 0xefac, 0xefad, 0xefae, 0xefaf, 0xefb0, 0xefb1, 0xefb2,
+ 0xefb3, 0xefb4, 0xefb5, 0xefb6, 0xefb7, 0xefb8, 0xefb9, 0xefba,
+ 0xefbb, 0xefbc, 0xefbd, 0xefbe, 0xefbf, 0xefc0, 0xefc1, 0xefc2,
+ 0xefc3, 0xefc4, 0xefc5, 0xefc6, 0xefc7, 0xefc8, 0xefc9, 0xefca,
+ 0xefcb, 0xefcc, 0xefcd, 0xefce, 0xefcf, 0xefd0, 0xefd1, 0xefd2,
+ 0xefd3, 0xefd4, 0xefd5, 0xefd6, 0xefd7, 0xefd8, 0xefd9, 0xefda,
+ 0xefdb, 0xefdc, 0xefdd, 0xefde, 0xefdf, 0xefe0, 0xefe1, 0xefe2,
+ 0xefe3, 0xefe4, 0xefe5, 0xefe6, 0xefe7, 0xefe8, 0xefe9, 0xefea,
+ 0xefeb, 0xefec, 0xefed, 0xefee, 0xefef, 0xeff0, 0xeff1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xeff2, 0xeff3, 0xeff4, 0xeff5, 0xeff6, 0xeff7, 0xeff8, 0xeff9,
+ 0xeffa, 0xeffb, 0xeffc, 0xeffd, 0xeffe, 0xefff, 0xf000, 0xf001,
+ 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007, 0xf008, 0xf009,
+ 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f, 0xf010, 0xf011,
+ 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017, 0xf018, 0xf019,
+ 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f, 0xf020, 0xf021,
+ 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027, 0xf028, 0xf029,
+ 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f, 0xf030, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
+ 0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
+ 0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
+ 0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
+ 0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
+ 0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
+ 0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
+ 0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
+ 0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
+ 0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
+ 0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
+ 0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf08f, 0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096,
+ 0xf097, 0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e,
+ 0xf09f, 0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6,
+ 0xf0a7, 0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae,
+ 0xf0af, 0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6,
+ 0xf0b7, 0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be,
+ 0xf0bf, 0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6,
+ 0xf0c7, 0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf0ce, 0xf0cf, 0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4,
+ 0xf0d5, 0xf0d6, 0xf0d7, 0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc,
+ 0xf0dd, 0xf0de, 0xf0df, 0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4,
+ 0xf0e5, 0xf0e6, 0xf0e7, 0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec,
+ 0xf0ed, 0xf0ee, 0xf0ef, 0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4,
+ 0xf0f5, 0xf0f6, 0xf0f7, 0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc,
+ 0xf0fd, 0xf0fe, 0xf0ff, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
+ 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf10a, 0xf10b, 0xf10c,
+ 0xf10d, 0xf10e, 0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf114,
+ 0xf115, 0xf116, 0xf117, 0xf118, 0xf119, 0xf11a, 0xf11b, 0xf11c,
+ 0xf11d, 0xf11e, 0xf11f, 0xf120, 0xf121, 0xf122, 0xf123, 0xf124,
+ 0xf125, 0xf126, 0xf127, 0xf128, 0xf129, 0xf12a, 0xf12b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf12c, 0xf12d, 0xf12e, 0xf12f, 0xf130, 0xf131, 0xf132, 0xf133,
+ 0xf134, 0xf135, 0xf136, 0xf137, 0xf138, 0xf139, 0xf13a, 0xf13b,
+ 0xf13c, 0xf13d, 0xf13e, 0xf13f, 0xf140, 0xf141, 0xf142, 0xf143,
+ 0xf144, 0xf145, 0xf146, 0xf147, 0xf148, 0xf149, 0xf14a, 0xf14b,
+ 0xf14c, 0xf14d, 0xf14e, 0xf14f, 0xf150, 0xf151, 0xf152, 0xf153,
+ 0xf154, 0xf155, 0xf156, 0xf157, 0xf158, 0xf159, 0xf15a, 0xf15b,
+ 0xf15c, 0xf15d, 0xf15e, 0xf15f, 0xf160, 0xf161, 0xf162, 0xf163,
+ 0xf164, 0xf165, 0xf166, 0xf167, 0xf168, 0xf169, 0xf16a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf16b, 0xf16c, 0xf16d, 0xf16e, 0xf16f, 0xf170, 0xf171,
+ 0xf172, 0xf173, 0xf174, 0xf175, 0xf176, 0xf177, 0xf178, 0xf179,
+ 0xf17a, 0xf17b, 0xf17c, 0xf17d, 0xf17e, 0xf17f, 0xf180, 0xf181,
+ 0xf182, 0xf183, 0xf184, 0xf185, 0xf186, 0xf187, 0xf188, 0xf189,
+ 0xf18a, 0xf18b, 0xf18c, 0xf18d, 0xf18e, 0xf18f, 0xf190, 0xf191,
+ 0xf192, 0xf193, 0xf194, 0xf195, 0xf196, 0xf197, 0xf198, 0xf199,
+ 0xf19a, 0xf19b, 0xf19c, 0xf19d, 0xf19e, 0xf19f, 0xf1a0, 0xf1a1,
+ 0xf1a2, 0xf1a3, 0xf1a4, 0xf1a5, 0xf1a6, 0xf1a7, 0xf1a8, 0xf1a9,
+ 0xf1aa, 0xf1ab, 0xf1ac, 0xf1ad, 0xf1ae, 0xf1af, 0xf1b0, 0xf1b1,
+ 0xf1b2, 0xf1b3, 0xf1b4, 0xf1b5, 0xf1b6, 0xf1b7, 0xf1b8, 0xf1b9,
+ 0xf1ba, 0xf1bb, 0xf1bc, 0xf1bd, 0xf1be, 0xf1bf, 0xf1c0, 0xf1c1,
+ 0xf1c2, 0xf1c3, 0xf1c4, 0xf1c5, 0xf1c6, 0xf1c7, 0xf1c8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf1c9, 0xf1ca, 0xf1cb, 0xf1cc, 0xf1cd, 0xf1ce, 0xf1cf, 0xf1d0,
+ 0xf1d1, 0xf1d2, 0xf1d3, 0xf1d4, 0xf1d5, 0xf1d6, 0xf1d7, 0xf1d8,
+ 0xf1d9, 0xf1da, 0xf1db, 0xf1dc, 0xf1dd, 0xf1de, 0xf1df, 0xf1e0,
+ 0xf1e1, 0xf1e2, 0xf1e3, 0xf1e4, 0xf1e5, 0xf1e6, 0xf1e7, 0xf1e8,
+ 0xf1e9, 0xf1ea, 0xf1eb, 0xf1ec, 0xf1ed, 0xf1ee, 0xf1ef, 0xf1f0,
+ 0xf1f1, 0xf1f2, 0xf1f3, 0xf1f4, 0xf1f5, 0xf1f6, 0xf1f7, 0xf1f8,
+ 0xf1f9, 0xf1fa, 0xf1fb, 0xf1fc, 0xf1fd, 0xf1fe, 0xf1ff, 0xf200,
+ 0xf201, 0xf202, 0xf203, 0xf204, 0xf205, 0xf206, 0xf207, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf208, 0xf209, 0xf20a, 0xf20b, 0xf20c, 0xf20d, 0xf20e,
+ 0xf20f, 0xf210, 0xf211, 0xf212, 0xf213, 0xf214, 0xf215, 0xf216,
+ 0xf217, 0xf218, 0xf219, 0xf21a, 0xf21b, 0xf21c, 0xf21d, 0xf21e,
+ 0xf21f, 0xf220, 0xf221, 0xf222, 0xf223, 0xf224, 0xf225, 0xf226,
+ 0xf227, 0xf228, 0xf229, 0xf22a, 0xf22b, 0xf22c, 0xf22d, 0xf22e,
+ 0xf22f, 0xf230, 0xf231, 0xf232, 0xf233, 0xf234, 0xf235, 0xf236,
+ 0xf237, 0xf238, 0xf239, 0xf23a, 0xf23b, 0xf23c, 0xf23d, 0xf23e,
+ 0xf23f, 0xf240, 0xf241, 0xf242, 0xf243, 0xf244, 0xf245, 0xf246,
+ 0xf247, 0xf248, 0xf249, 0xf24a, 0xf24b, 0xf24c, 0xf24d, 0xf24e,
+ 0xf24f, 0xf250, 0xf251, 0xf252, 0xf253, 0xf254, 0xf255, 0xf256,
+ 0xf257, 0xf258, 0xf259, 0xf25a, 0xf25b, 0xf25c, 0xf25d, 0xf25e,
+ 0xf25f, 0xf260, 0xf261, 0xf262, 0xf263, 0xf264, 0xf265, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf266, 0xf267, 0xf268, 0xf269, 0xf26a, 0xf26b, 0xf26c, 0xf26d,
+ 0xf26e, 0xf26f, 0xf270, 0xf271, 0xf272, 0xf273, 0xf274, 0xf275,
+ 0xf276, 0xf277, 0xf278, 0xf279, 0xf27a, 0xf27b, 0xf27c, 0xf27d,
+ 0xf27e, 0xf27f, 0xf280, 0xf281, 0xf282, 0xf283, 0xf284, 0xf285,
+ 0xf286, 0xf287, 0xf288, 0xf289, 0xf28a, 0xf28b, 0xf28c, 0xf28d,
+ 0xf28e, 0xf28f, 0xf290, 0xf291, 0xf292, 0xf293, 0xf294, 0xf295,
+ 0xf296, 0xf297, 0xf298, 0xf299, 0xf29a, 0xf29b, 0xf29c, 0xf29d,
+ 0xf29e, 0xf29f, 0xf2a0, 0xf2a1, 0xf2a2, 0xf2a3, 0xf2a4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf2a5, 0xf2a6, 0xf2a7, 0xf2a8, 0xf2a9, 0xf2aa, 0xf2ab,
+ 0xf2ac, 0xf2ad, 0xf2ae, 0xf2af, 0xf2b0, 0xf2b1, 0xf2b2, 0xf2b3,
+ 0xf2b4, 0xf2b5, 0xf2b6, 0xf2b7, 0xf2b8, 0xf2b9, 0xf2ba, 0xf2bb,
+ 0xf2bc, 0xf2bd, 0xf2be, 0xf2bf, 0xf2c0, 0xf2c1, 0xf2c2, 0xf2c3,
+ 0xf2c4, 0xf2c5, 0xf2c6, 0xf2c7, 0xf2c8, 0xf2c9, 0xf2ca, 0xf2cb,
+ 0xf2cc, 0xf2cd, 0xf2ce, 0xf2cf, 0xf2d0, 0xf2d1, 0xf2d2, 0xf2d3,
+ 0xf2d4, 0xf2d5, 0xf2d6, 0xf2d7, 0xf2d8, 0xf2d9, 0xf2da, 0xf2db,
+ 0xf2dc, 0xf2dd, 0xf2de, 0xf2df, 0xf2e0, 0xf2e1, 0xf2e2, 0xf2e3,
+ 0xf2e4, 0xf2e5, 0xf2e6, 0xf2e7, 0xf2e8, 0xf2e9, 0xf2ea, 0xf2eb,
+ 0xf2ec, 0xf2ed, 0xf2ee, 0xf2ef, 0xf2f0, 0xf2f1, 0xf2f2, 0xf2f3,
+ 0xf2f4, 0xf2f5, 0xf2f6, 0xf2f7, 0xf2f8, 0xf2f9, 0xf2fa, 0xf2fb,
+ 0xf2fc, 0xf2fd, 0xf2fe, 0xf2ff, 0xf300, 0xf301, 0xf302, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf303, 0xf304, 0xf305, 0xf306, 0xf307, 0xf308, 0xf309, 0xf30a,
+ 0xf30b, 0xf30c, 0xf30d, 0xf30e, 0xf30f, 0xf310, 0xf311, 0xf312,
+ 0xf313, 0xf314, 0xf315, 0xf316, 0xf317, 0xf318, 0x0100, 0x00c1,
+ 0x01cd, 0x00c0, 0x0112, 0x00c9, 0x011a, 0x00c8, 0x014c, 0x00d3,
+ 0x01d1, 0x00d2, 0xf325, 0x1ebe, 0xf327, 0x1ec0, 0x00ca, 0x0101,
+ 0x00e1, 0x01ce, 0x00e0, 0x0251, 0x0113, 0x00e9, 0x011b, 0x00e8,
+ 0x012b, 0x00ed, 0x01d0, 0x00ec, 0x014d, 0x00f3, 0x01d2, 0x00f2,
+ 0x016b, 0x00fa, 0x01d4, 0x00f9, 0x01d6, 0x01d8, 0x01da, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x01dc, 0x00fc, 0xf344, 0x1ebf, 0xf346, 0x1ec1, 0x00ea,
+ 0x0261, 0xf34a, 0xf34b, 0xf34c, 0xf34d, 0xf34e, 0xf34f, 0xf350,
+ 0xf351, 0xf352, 0xf353, 0xf354, 0xf355, 0xf356, 0xf357, 0xf358,
+ 0xf359, 0xf35a, 0xf35b, 0xf35c, 0xf35d, 0xf35e, 0xf35f, 0xf360,
+ 0xf361, 0xf362, 0xf363, 0xf364, 0xf365, 0xf366, 0xf367, 0xf368,
+ 0xf369, 0xf36a, 0xf36b, 0xf36c, 0xf36d, 0xf36e, 0xf36f, 0xf370,
+ 0xf371, 0xf372, 0xf373, 0xf374, 0xf375, 0xf376, 0xf377, 0xf378,
+ 0xf379, 0xf37a, 0xf37b, 0xf37c, 0xf37d, 0xf37e, 0xf37f, 0xf380,
+ 0xf381, 0xf382, 0xf383, 0xf384, 0xf385, 0xf386, 0xf387, 0xf388,
+ 0xf389, 0xf38a, 0xf38b, 0xf38c, 0xf38d, 0xf38e, 0xf38f, 0xf390,
+ 0xf391, 0xf392, 0xf393, 0xf394, 0xf395, 0xf396, 0xf397, 0xf398,
+ 0xf399, 0xf39a, 0xf39b, 0xf39c, 0xf39d, 0xf39e, 0xf39f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf3a0, 0xf3a1, 0xf3a2, 0x650a, 0xf3a4, 0xf3a5, 0x4e3d, 0x6edd,
+ 0x9d4e, 0x91df, 0xf3aa, 0xf3ab, 0xf3ac, 0x6491, 0x4f1a, 0x4f28,
+ 0x4fa8, 0x5156, 0x5174, 0x519c, 0x51e4, 0x52a1, 0x52a8, 0x533b,
+ 0x534e, 0x53d1, 0x53d8, 0x56e2, 0x58f0, 0x5904, 0x5907, 0x5932,
+ 0x5934, 0x5b66, 0x5b9e, 0x5b9f, 0x5c9a, 0x5e86, 0x603b, 0x6589,
+ 0x67fe, 0x6804, 0x6865, 0x6d4e, 0x70bc, 0x7535, 0x7ea4, 0x7eac,
+ 0x7eba, 0x7ec7, 0x7ecf, 0x7edf, 0x7f06, 0x7f37, 0x827a, 0x82cf,
+ 0x836f, 0x89c6, 0x8bbe, 0x8be2, 0x8f66, 0x8f67, 0x8f6e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7411, 0x7cfc, 0x7dcd, 0x6946, 0x7ac9, 0x5227, 0xf3e5,
+ 0xf3e6, 0xf3e7, 0xf3e8, 0x918c, 0x78b8, 0x915e, 0x80bc, 0xf3ed,
+ 0x8d0b, 0x80f6, 0xf3f0, 0xf3f1, 0xf3f2, 0x809f, 0x9ec7, 0x4ccd,
+ 0x9dc9, 0x9e0c, 0x4c3e, 0xf3f9, 0xf3fa, 0x9e0a, 0xf3fc, 0x35c1,
+ 0xf3fe, 0x6e9a, 0x823e, 0x7519, 0xf402, 0x4911, 0x9a6c, 0x9a8f,
+ 0x9f99, 0x7987, 0xf408, 0xf409, 0xf40a, 0xf40b, 0x4e24, 0x4e81,
+ 0x4e80, 0x4e87, 0x4ebf, 0x4eeb, 0x4f37, 0x344c, 0x4fbd, 0x3e48,
+ 0x5003, 0x5088, 0x347d, 0x3493, 0x34a5, 0x5186, 0x5905, 0x51db,
+ 0x51fc, 0x5205, 0x4e89, 0x5279, 0x5290, 0x5327, 0x35c7, 0x53a9,
+ 0x3551, 0x53b0, 0x3553, 0x53c2, 0x5423, 0x356d, 0x3572, 0x3681,
+ 0x5493, 0x54a3, 0x54b4, 0x54b9, 0x54d0, 0x54ef, 0x5518, 0x5523,
+ 0x5528, 0x3598, 0x553f, 0x35a5, 0x35bf, 0x55d7, 0x35c5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf43d, 0x5525, 0xf43f, 0xf440, 0xf441, 0xf442, 0x5590, 0xf444,
+ 0x39ec, 0xf446, 0x8e46, 0xf448, 0xf449, 0x4053, 0xf44b, 0x777a,
+ 0xf44d, 0x3a34, 0x47d5, 0xf450, 0xf451, 0xf452, 0x64dd, 0xf454,
+ 0xf455, 0xf456, 0xf457, 0x648d, 0x8e7e, 0xf45a, 0xf45b, 0xf45c,
+ 0xf45d, 0xf45e, 0xf45f, 0xf460, 0xf461, 0xf462, 0xf463, 0x47f4,
+ 0xf465, 0xf466, 0x9ab2, 0x3a67, 0xf469, 0x3fed, 0x3506, 0xf46c,
+ 0xf46d, 0xf46e, 0xf46f, 0x9d6e, 0x9815, 0xf472, 0x43d9, 0xf474,
+ 0x64b4, 0x54e3, 0xf477, 0xf478, 0xf479, 0x39fb, 0xf47b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf47c, 0xf47d, 0xf47e, 0x64ea, 0xf480, 0xf481, 0x8e68,
+ 0xf483, 0xf484, 0xf485, 0xf486, 0x480b, 0xf488, 0x3ffa, 0x5873,
+ 0xf48b, 0xf48c, 0xf48d, 0xf48e, 0xf48f, 0xf490, 0xf491, 0x5579,
+ 0x40bb, 0x43ba, 0xf495, 0x4ab4, 0xf497, 0xf498, 0x81aa, 0x98f5,
+ 0xf49b, 0x6379, 0x39fe, 0xf49e, 0x8dc0, 0x56a1, 0x647c, 0x3e43,
+ 0xf4a3, 0xf4a4, 0xf4a5, 0xf4a6, 0xf4a7, 0xf4a8, 0xf4a9, 0xf4aa,
+ 0x3992, 0x3a06, 0xf4ad, 0x3578, 0xf4af, 0xf4b0, 0x5652, 0xf4b2,
+ 0xf4b3, 0xf4b4, 0x34bc, 0x6c3d, 0xf4b7, 0xf4b8, 0xf4b9, 0xf4ba,
+ 0xf4bb, 0xf4bc, 0xf4bd, 0xf4be, 0xf4bf, 0xf4c0, 0xf4c1, 0x7f93,
+ 0xf4c3, 0xf4c4, 0xf4c5, 0x35fb, 0xf4c7, 0xf4c8, 0xf4c9, 0xf4ca,
+ 0x3f93, 0xf4cc, 0xf4cd, 0xf4ce, 0xf4cf, 0xf4d0, 0xf4d1, 0xf4d2,
+ 0xf4d3, 0xf4d4, 0xf4d5, 0x3ff9, 0xf4d7, 0x6432, 0xf4d9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf4da, 0xf4db, 0xf4dc, 0xf4dd, 0xf4de, 0xf4df, 0xf4e0, 0x3a18,
+ 0xf4e2, 0xf4e3, 0xf4e4, 0xf4e5, 0xf4e6, 0xf4e7, 0xf4e8, 0xf4e9,
+ 0x95aa, 0x54cc, 0x82c4, 0x55b9, 0xf4ee, 0xf4ef, 0x9c26, 0x9ab6,
+ 0xf4f2, 0xf4f3, 0x7140, 0x816d, 0x80ec, 0x5c1c, 0xf4f8, 0x8134,
+ 0x3797, 0x535f, 0xf4fc, 0x91b6, 0xf4fe, 0xf4ff, 0xf500, 0xf501,
+ 0x35dd, 0xf503, 0x3609, 0xf505, 0x56af, 0xf507, 0xf508, 0xf509,
+ 0xf50a, 0xf50b, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510, 0xf511,
+ 0x5a54, 0xf513, 0xf514, 0xf515, 0xf516, 0x579c, 0xf518, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf519, 0xf51a, 0xf51b, 0xf51c, 0xf51d, 0x3703, 0xf51f,
+ 0xf520, 0xf521, 0xf522, 0xf523, 0xf524, 0xf525, 0xf526, 0x5899,
+ 0x5268, 0x361a, 0xf52a, 0x7bb2, 0x5b68, 0x4800, 0x4b2c, 0x9f27,
+ 0x49e7, 0x9c1f, 0x9b8d, 0xf533, 0xf534, 0x55fb, 0x35f2, 0x5689,
+ 0x4e28, 0x5902, 0xf53a, 0xf53b, 0x9751, 0xf53d, 0x4e5b, 0x4ebb,
+ 0x353e, 0x5c23, 0x5f51, 0x5fc4, 0x38fa, 0x624c, 0x6535, 0x6b7a,
+ 0x6c35, 0x6c3a, 0x706c, 0x722b, 0x4e2c, 0x72ad, 0xf54e, 0x7f52,
+ 0x793b, 0x7cf9, 0x7f53, 0xf553, 0x34c1, 0xf555, 0xf556, 0x8002,
+ 0x8080, 0xf559, 0xf55a, 0x535d, 0x8864, 0x89c1, 0xf55e, 0x8ba0,
+ 0x8d1d, 0x9485, 0x9578, 0x957f, 0x95e8, 0xf565, 0x97e6, 0x9875,
+ 0x98ce, 0x98de, 0x9963, 0xf56b, 0x9c7c, 0x9e1f, 0x9ec4, 0x6b6f,
+ 0xf907, 0x4e37, 0xf572, 0x961d, 0x6237, 0x94a2, 0xf576, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x503b, 0x6dfe, 0xf579, 0xf57a, 0x3dc9, 0x888f, 0xf57d, 0x7077,
+ 0x5cf5, 0x4b20, 0xf581, 0x3559, 0xf583, 0x6122, 0xf585, 0x8fa7,
+ 0x91f6, 0x7191, 0x6719, 0x73ba, 0xf58b, 0xf58c, 0x3c8b, 0xf58e,
+ 0x4b10, 0x78e4, 0x7402, 0x51ae, 0xf593, 0x4009, 0x6a63, 0xf596,
+ 0x4223, 0x860f, 0xf599, 0x7a2a, 0xf59b, 0xf59c, 0x9755, 0x704d,
+ 0x5324, 0xf5a0, 0x93f4, 0x76d9, 0xf5a3, 0xf5a4, 0x77dd, 0x4ea3,
+ 0x4ff0, 0x50bc, 0x4e2f, 0x4f17, 0xf5ab, 0x5434, 0x7d8b, 0x5892,
+ 0x58d0, 0xf5b0, 0x5e92, 0x5e99, 0x5fc2, 0xf5b4, 0x658b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf5b6, 0x6919, 0x6a43, 0xf5b9, 0x6cff, 0xf5bb, 0x7200,
+ 0xf5bd, 0x738c, 0x3edb, 0xf5c0, 0x5b15, 0x74b9, 0x8b83, 0xf5c4,
+ 0xf5c5, 0x7a93, 0x7bec, 0x7cc3, 0x7e6c, 0x82f8, 0x8597, 0xf5cc,
+ 0x8890, 0xf5ce, 0x8eb9, 0xf5d0, 0x8fcf, 0x855f, 0x99e0, 0x9221,
+ 0xf5d5, 0xf5d6, 0xf5d7, 0x4071, 0x42a2, 0x5a1a, 0xf5db, 0xf5dc,
+ 0xf5dd, 0x9868, 0x676b, 0x4276, 0x573d, 0xf5e2, 0x85d6, 0xf5e4,
+ 0x82bf, 0xf5e6, 0x4c81, 0xf5e8, 0x5d7b, 0xf5ea, 0xf5eb, 0xf5ec,
+ 0xf5ed, 0x5b96, 0xf5ef, 0xf5f0, 0x7e5b, 0xf5f2, 0xf5f3, 0xf5f4,
+ 0xf5f5, 0xf5f6, 0xf5f7, 0xf5f8, 0xf5f9, 0xf5fa, 0xf5fb, 0xf5fc,
+ 0xf5fd, 0xf5fe, 0xf5ff, 0xf600, 0xf601, 0xf602, 0xf603, 0xf604,
+ 0xf605, 0xf606, 0xf607, 0xf608, 0xf609, 0xf60a, 0xf60b, 0xf60c,
+ 0xf60d, 0xf60e, 0xf60f, 0xf610, 0xf611, 0xf612, 0xf613, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf614, 0xf615, 0xf616, 0xf617, 0xf618, 0xf619, 0xf61a, 0xf61b,
+ 0xf61c, 0xf61d, 0xf61e, 0xf61f, 0xf620, 0xf621, 0xf622, 0xf623,
+ 0xf624, 0xf625, 0xf626, 0xf627, 0xf628, 0xf629, 0xf62a, 0xf62b,
+ 0xf62c, 0xf62d, 0xf62e, 0xf62f, 0xf630, 0xf631, 0xf632, 0xf633,
+ 0x5d3e, 0x5d48, 0x5d56, 0x3dfc, 0x380f, 0x5da4, 0x5db9, 0x3820,
+ 0x3838, 0x5e42, 0x5ebd, 0x5f25, 0x5f83, 0x3908, 0x3914, 0x393f,
+ 0x394d, 0x60d7, 0x613d, 0x5ce5, 0x3989, 0x61b7, 0x61b9, 0x61cf,
+ 0x39b8, 0x622c, 0x6290, 0x62e5, 0x6318, 0x39f8, 0x56b1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3a03, 0x63e2, 0x63fb, 0x6407, 0x645a, 0x3a4b, 0x64c0,
+ 0x5d15, 0x5621, 0x9f9f, 0x3a97, 0x6586, 0x3abd, 0x65ff, 0x6653,
+ 0x3af2, 0x6692, 0x3b22, 0x6716, 0x3b42, 0x67a4, 0x6800, 0x3b58,
+ 0x684a, 0x6884, 0x3b72, 0x3b71, 0x3b7b, 0x6909, 0x6943, 0x725c,
+ 0x6964, 0x699f, 0x6985, 0x3bbc, 0x69d6, 0x3bdd, 0x6a65, 0x6a74,
+ 0x6a71, 0x6a82, 0x3bec, 0x6a99, 0x3bf2, 0x6aab, 0x6ab5, 0x6ad4,
+ 0x6af6, 0x6b81, 0x6bc1, 0x6bea, 0x6c75, 0x6caa, 0x3ccb, 0x6d02,
+ 0x6d06, 0x6d26, 0x6d81, 0x3cef, 0x6da4, 0x6db1, 0x6e15, 0x6e18,
+ 0x6e29, 0x6e86, 0xf694, 0x6ebb, 0x6ee2, 0x6eda, 0x9f7f, 0x6ee8,
+ 0x6ee9, 0x6f24, 0x6f34, 0x3d46, 0xf69e, 0x6f81, 0x6fbe, 0x3d6a,
+ 0x3d75, 0x71b7, 0x5c99, 0x3d8a, 0x702c, 0x3d91, 0x7050, 0x7054,
+ 0x706f, 0x707f, 0x7089, 0xf6ad, 0x43c1, 0x35f1, 0xf6b0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe311, 0x57be, 0xe313, 0x713e, 0xe315, 0x364e, 0x69a2, 0xe318,
+ 0x5b74, 0x7a49, 0xe31b, 0xe31c, 0x7a65, 0x7a7d, 0xe31f, 0x7abb,
+ 0x7ab0, 0x7ac2, 0x7ac3, 0x71d1, 0xe325, 0x41ca, 0x7ada, 0x7add,
+ 0x7aea, 0x41ef, 0x54b2, 0xe32c, 0x7b0b, 0x7b55, 0x7b29, 0xe330,
+ 0xe331, 0x7ba2, 0x7b6f, 0x839c, 0xe335, 0xe336, 0x7bd0, 0x8421,
+ 0x7b92, 0x7bb8, 0xe33b, 0x3dad, 0xe33d, 0x8492, 0x7bfa, 0x7c06,
+ 0x7c35, 0xe342, 0x7c44, 0x7c83, 0xe345, 0x7ca6, 0x667d, 0xe348,
+ 0x7cc9, 0x7cc7, 0x7ce6, 0x7c74, 0x7cf3, 0x7cf5, 0x7cce, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7e67, 0x451d, 0xe352, 0x7d5d, 0xe354, 0x748d, 0x7d89,
+ 0x7dab, 0x7135, 0x7db3, 0x7dd2, 0xe35b, 0xe35c, 0x7de4, 0x3d13,
+ 0x7df5, 0xe360, 0x7de5, 0xe362, 0x7e1d, 0xe364, 0xe365, 0x7e6e,
+ 0x7e92, 0x432b, 0x946c, 0x7e27, 0x7f40, 0x7f41, 0x7f47, 0x7936,
+ 0xe36f, 0x99e1, 0x7f97, 0xe372, 0x7fa3, 0xe374, 0xe375, 0x455c,
+ 0xe377, 0x4503, 0xe379, 0x7ffa, 0xe37b, 0x8005, 0x8008, 0x801d,
+ 0x8028, 0x802f, 0xe381, 0xe382, 0x803b, 0x803c, 0x8061, 0xe386,
+ 0x4989, 0xe388, 0xe389, 0xe38a, 0x6725, 0x80a7, 0xe38d, 0x8107,
+ 0x811a, 0x58b0, 0xe391, 0x6c7f, 0xe393, 0xe394, 0x64e7, 0xe396,
+ 0x8218, 0xe398, 0x6a53, 0xe39a, 0xe39b, 0x447a, 0x8229, 0xe39e,
+ 0xe39f, 0xe3a0, 0x4ff9, 0xe3a2, 0x84e2, 0x8362, 0xe3a5, 0xe3a6,
+ 0xe3a7, 0xe3a8, 0xe3a9, 0x82aa, 0x691b, 0xe3ac, 0x41db, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x854b, 0x82d0, 0x831a, 0xe3b1, 0xe3b2, 0x36c1, 0xe3b4, 0xe3b5,
+ 0x827b, 0x82e2, 0x8318, 0xe3b9, 0xe3ba, 0xe3bb, 0xe3bc, 0xe3bd,
+ 0x3dbf, 0x831d, 0x55ec, 0x8385, 0x450b, 0xe3c3, 0x83ac, 0x83c1,
+ 0x83d3, 0x347e, 0xe3c8, 0x6a57, 0x855a, 0x3496, 0xe3cc, 0xe3cd,
+ 0x8458, 0xe3cf, 0x8471, 0x3dd3, 0x44e4, 0x6aa7, 0x844a, 0xe3d5,
+ 0x7958, 0x84a8, 0xe3d8, 0xe3d9, 0xe3da, 0x84de, 0x840f, 0x8391,
+ 0x44a0, 0x8493, 0x84e4, 0xe3e1, 0x4240, 0xe3e3, 0x4543, 0x8534,
+ 0x5af2, 0xe3e7, 0x4527, 0x8573, 0x4516, 0x67bf, 0x8616, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe3ed, 0xe3ee, 0x85c1, 0xe3f0, 0x8602, 0xe3f2, 0xe3f3,
+ 0xe3f4, 0x456a, 0x8628, 0x3648, 0xe3f8, 0x53f7, 0xe3fa, 0x867e,
+ 0x8771, 0xe3fd, 0x87ee, 0xe3ff, 0x87b1, 0x87da, 0x880f, 0x5661,
+ 0x866c, 0x6856, 0x460f, 0x8845, 0x8846, 0xe409, 0xe40a, 0xe40b,
+ 0x885e, 0x889c, 0x465b, 0x88b4, 0x88b5, 0x63c1, 0x88c5, 0x7777,
+ 0xe414, 0x8987, 0x898a, 0x89a6, 0x89a9, 0x89a7, 0x89bc, 0xe41b,
+ 0x89e7, 0xe41d, 0xe41e, 0x8a9c, 0x7793, 0x91fe, 0x8a90, 0xe423,
+ 0x7ae9, 0xe425, 0xe426, 0x4713, 0xe428, 0x717c, 0x8b0c, 0x8b1f,
+ 0xe42c, 0xe42d, 0x8b3f, 0x8b4c, 0x8b4d, 0x8aa9, 0xe432, 0x8b90,
+ 0x8b9b, 0x8aaf, 0xe436, 0x4615, 0x884f, 0x8c9b, 0xe43a, 0xe43b,
+ 0xe43c, 0x3725, 0xe43e, 0x8cd6, 0xe440, 0xe441, 0x8d12, 0x8d03,
+ 0xe444, 0x8cdb, 0x705c, 0x8d11, 0xe448, 0x3ed0, 0x8d77, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8da9, 0xe44c, 0xe44d, 0xe44e, 0x3b7c, 0xe450, 0xe451, 0x7ae7,
+ 0x8ead, 0x8eb6, 0x8ec3, 0x92d4, 0x8f19, 0x8f2d, 0xe459, 0xe45a,
+ 0x8fa5, 0x9303, 0xe45d, 0xe45e, 0x8fb3, 0x492a, 0xe461, 0xe462,
+ 0xe463, 0x5ef8, 0xe465, 0x8ff9, 0xe467, 0xe468, 0xe469, 0xe46a,
+ 0x3980, 0xe46c, 0x9037, 0xe46e, 0xe46f, 0x9061, 0xe471, 0xe472,
+ 0x90a8, 0xe474, 0x90c4, 0xe476, 0x90ae, 0x90fd, 0x9167, 0x3af0,
+ 0x91a9, 0x91c4, 0x7cac, 0xe47e, 0xe47f, 0x920e, 0x6c9f, 0x9241,
+ 0x9262, 0xe484, 0x92b9, 0xe486, 0xe487, 0xe488, 0xe489, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe48a, 0x932c, 0x936b, 0xe48d, 0xe48e, 0x708f, 0x5ac3,
+ 0xe491, 0xe492, 0x4965, 0x9244, 0xe495, 0xe496, 0xe497, 0x9373,
+ 0x945b, 0x8ebc, 0x9585, 0x95a6, 0x9426, 0x95a0, 0x6ff6, 0x42b9,
+ 0xe4a1, 0xe4a2, 0xe4a3, 0xe4a4, 0x49df, 0x6c1c, 0x967b, 0x9696,
+ 0x416c, 0x96a3, 0xe4ab, 0x61da, 0x96b6, 0x78f5, 0xe4af, 0x96bd,
+ 0x53cc, 0x49a1, 0xe4b3, 0xe4b4, 0xe4b5, 0xe4b6, 0xe4b7, 0xe4b8,
+ 0xe4b9, 0xe4ba, 0x9731, 0x8642, 0x9736, 0x4a0f, 0x453d, 0x4585,
+ 0xe4c1, 0x7075, 0x5b41, 0x971b, 0x975c, 0xe4c6, 0x9757, 0x5b4a,
+ 0xe4c9, 0x975f, 0x9425, 0x50d0, 0xe4cd, 0xe4ce, 0x9789, 0x979f,
+ 0x97b1, 0x97be, 0x97c0, 0x97d2, 0x97e0, 0xe4d6, 0x97ee, 0x741c,
+ 0xe4d9, 0x97ff, 0x97f5, 0xe4dc, 0xe4dd, 0x4ad1, 0x9834, 0x9833,
+ 0x984b, 0x9866, 0x3b0e, 0xe4e4, 0x3d51, 0xe4e6, 0xe4e7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe4e8, 0x98ca, 0x98b7, 0x98c8, 0x98c7, 0x4aff, 0xe4ee, 0xe4ef,
+ 0x55b0, 0x98e1, 0x98e6, 0x98ec, 0x9378, 0x9939, 0xe4f6, 0x4b72,
+ 0xe4f8, 0xe4f9, 0x99f5, 0x9a0c, 0x9a3b, 0x9a10, 0x9a58, 0xe4ff,
+ 0x36c4, 0xe501, 0xe502, 0x9ae0, 0x9ae2, 0xe505, 0x9af4, 0x4c0e,
+ 0x9b14, 0x9b2d, 0xe50a, 0x5034, 0x9b34, 0xe50d, 0x38c3, 0xe50f,
+ 0x9b50, 0x9b40, 0xe512, 0x5a45, 0xe514, 0x9b8e, 0xe516, 0x9c02,
+ 0x9bff, 0x9c0c, 0xe51a, 0x9dd4, 0xe51c, 0xe51d, 0xe51e, 0xe51f,
+ 0xe520, 0xe521, 0x9d7e, 0x9d83, 0xe524, 0x9e0e, 0x6888, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9dc4, 0xe528, 0xe529, 0xe52a, 0xe52b, 0xe52c, 0x9d39,
+ 0xe52e, 0xe52f, 0x9e90, 0x9e95, 0x9e9e, 0x9ea2, 0x4d34, 0x9eaa,
+ 0x9eaf, 0xe537, 0x9ec1, 0x3b60, 0x39e5, 0x3d1d, 0x4f32, 0x37be,
+ 0xe53e, 0x9f02, 0x9f08, 0x4b96, 0x9424, 0xe543, 0x9f17, 0x9f16,
+ 0x9f39, 0x569f, 0x568a, 0x9f45, 0x99b8, 0xe54b, 0x97f2, 0x847f,
+ 0x9f62, 0x9f69, 0x7adc, 0x9f8e, 0x7216, 0x4bbe, 0xe554, 0xe555,
+ 0x7177, 0xe557, 0xe558, 0xe559, 0x739e, 0xe55b, 0xe55c, 0x799f,
+ 0xe55e, 0xe55f, 0x9369, 0x93f3, 0xe562, 0x92ec, 0x9381, 0x93cb,
+ 0xe566, 0xe567, 0x7217, 0x3eeb, 0x7772, 0x7a43, 0x70d0, 0xe56d,
+ 0xe56e, 0x717e, 0xe570, 0x70a3, 0xe572, 0xe573, 0x3ec7, 0xe575,
+ 0xe576, 0xe577, 0x3722, 0xe579, 0xe57a, 0x36e1, 0xe57c, 0xe57d,
+ 0xe57e, 0x3723, 0xe580, 0x575b, 0xe582, 0xe583, 0xe584, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe585, 0xe586, 0x8503, 0xe588, 0x8503, 0x8455, 0xe58b, 0xe58c,
+ 0xe58d, 0xe58e, 0xe58f, 0xe590, 0x44f4, 0xe592, 0xe593, 0xe594,
+ 0x67f9, 0x3733, 0x3c15, 0x3de7, 0x586c, 0xe59a, 0x6810, 0x4057,
+ 0xe59d, 0xe59e, 0xe59f, 0xe5a0, 0xe5a1, 0x54cb, 0x569e, 0xe5a4,
+ 0x5692, 0xe5a6, 0xe5a7, 0xe5a8, 0x93c6, 0xe5aa, 0x939c, 0x4ef8,
+ 0x512b, 0x3819, 0xe5af, 0x4ebc, 0xe5b1, 0xe5b2, 0x4f4b, 0x4f8a,
+ 0xe5b5, 0x5a68, 0xe5b7, 0xe5b8, 0x3999, 0xe5ba, 0xe5bb, 0x3435,
+ 0x4f29, 0xe5be, 0xe5bf, 0xe5c0, 0x8ada, 0xe5c2, 0x4e98, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x50cd, 0x510d, 0x4fa2, 0x4f03, 0xe5c8, 0xe5c9, 0x4f42,
+ 0x502e, 0x506c, 0x5081, 0x4fcc, 0x4fe5, 0x5058, 0x50fc, 0x5159,
+ 0x515b, 0x515d, 0x515e, 0x6e76, 0xe5d7, 0xe5d8, 0xe5d9, 0x6d72,
+ 0xe5db, 0xe5dc, 0x51a8, 0x51c3, 0xe5df, 0x44dd, 0xe5e1, 0xe5e2,
+ 0xe5e3, 0x8d7a, 0xe5e5, 0xe5e6, 0x5259, 0x52a4, 0xe5e9, 0x52e1,
+ 0x936e, 0x467a, 0x718c, 0xe5ee, 0xe5ef, 0xe5f0, 0xe5f1, 0x69d1,
+ 0xe5f3, 0x7479, 0x3ede, 0x7499, 0x7414, 0x7456, 0x7398, 0x4b8e,
+ 0xe5fb, 0xe5fc, 0x53d0, 0x3584, 0x720f, 0xe600, 0x55b4, 0xe602,
+ 0x54cd, 0xe604, 0x571d, 0x925d, 0x96f4, 0x9366, 0x57dd, 0x578d,
+ 0x577f, 0x363e, 0x58cb, 0x5a99, 0xe60f, 0xe610, 0xe611, 0xe612,
+ 0x5a2c, 0x59b8, 0x928f, 0x5a7e, 0x5acf, 0x5a12, 0xe619, 0xe61a,
+ 0xe61b, 0xe61c, 0x36f5, 0x6d05, 0x7443, 0x5a21, 0xe621, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5a81, 0xe623, 0xe624, 0x93e0, 0x748c, 0xe627, 0x7105, 0x4972,
+ 0x9408, 0xe62b, 0x93bd, 0x37a0, 0x5c1e, 0x5c9e, 0x5e5e, 0x5e48,
+ 0xe632, 0xe633, 0xe634, 0x5ecd, 0x5b4f, 0xe637, 0xe638, 0x3701,
+ 0xe63a, 0x36dd, 0xe63c, 0x36d3, 0x812a, 0xe63f, 0xe640, 0xe641,
+ 0xe642, 0x5f0c, 0x5f0e, 0xe645, 0xe646, 0x5a6b, 0xe648, 0x5b44,
+ 0x8614, 0xe64b, 0x8860, 0x607e, 0xe64e, 0xe64f, 0x5fdb, 0x3eb8,
+ 0xe652, 0xe653, 0xe654, 0xe655, 0x61c0, 0xe657, 0xe658, 0xe659,
+ 0x6199, 0x6198, 0x6075, 0xe65d, 0xe65e, 0xe65f, 0xe660, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6471, 0xe662, 0xe663, 0x3a29, 0xe665, 0xe666, 0xe667,
+ 0xe668, 0x6337, 0xe66a, 0x64b6, 0x6331, 0x63d1, 0xe66e, 0xe66f,
+ 0x62a4, 0xe671, 0x643b, 0x656b, 0x6972, 0x3bf4, 0xe676, 0xe677,
+ 0xe678, 0xe679, 0x550d, 0xe67b, 0xe67c, 0xe67d, 0x66ce, 0xe67f,
+ 0xe680, 0x3ae0, 0x4190, 0xe683, 0xe684, 0xe685, 0xe686, 0xe687,
+ 0xe688, 0x78ee, 0xe68a, 0xe68b, 0xe68c, 0x3464, 0xe68e, 0xe68f,
+ 0xe690, 0x668e, 0xe692, 0x666b, 0x4b93, 0x6630, 0xe696, 0xe697,
+ 0x6663, 0xe699, 0xe69a, 0x661e, 0xe69c, 0x38d1, 0xe69e, 0xe69f,
+ 0x3b99, 0xe6a1, 0xe6a2, 0x74d0, 0x3b96, 0x678f, 0xe6a6, 0x68b6,
+ 0x681e, 0x3bc4, 0x6abe, 0x3863, 0xe6ac, 0xe6ad, 0x6a33, 0x6a52,
+ 0x6ac9, 0x6b05, 0xe6b2, 0x6511, 0x6898, 0x6a4c, 0x3bd7, 0x6a7a,
+ 0x6b57, 0xe6b9, 0xe6ba, 0x93a0, 0x92f2, 0xe6bd, 0xe6be, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9289, 0xe6c0, 0xe6c1, 0x9467, 0x6da5, 0x6f0b, 0xe6c5, 0x6d67,
+ 0xe6c7, 0x3d8f, 0x6e04, 0xe6ca, 0x5a3d, 0x6e0a, 0x5847, 0x6d24,
+ 0x7842, 0x713b, 0xe6d1, 0xe6d2, 0x70f1, 0x7250, 0x7287, 0x7294,
+ 0xe6d7, 0xe6d8, 0x5179, 0xe6da, 0xe6db, 0x747a, 0xe6dd, 0xe6de,
+ 0xe6df, 0xe6e0, 0xe6e1, 0x3f06, 0x3eb1, 0xe6e4, 0xe6e5, 0xe6e6,
+ 0x60a7, 0x3ef3, 0x74cc, 0x743c, 0x9387, 0x7437, 0x449f, 0xe6ee,
+ 0x4551, 0x7583, 0x3f63, 0xe6f2, 0xe6f3, 0x3f58, 0x7555, 0x7673,
+ 0xe6f7, 0x3b19, 0x7468, 0xe6fa, 0xe6fb, 0xe6fc, 0x3afb, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3dcd, 0xe6ff, 0x3eff, 0xe701, 0xe702, 0x91fa, 0x5732,
+ 0x9342, 0xe706, 0xe707, 0x50df, 0xe709, 0xe70a, 0x7778, 0xe70c,
+ 0x770e, 0x770f, 0x777b, 0xe710, 0xe711, 0x3a5e, 0xe713, 0x7438,
+ 0x749b, 0x3ebf, 0xe717, 0xe718, 0x40c8, 0xe71a, 0xe71b, 0x9307,
+ 0xe71d, 0x781e, 0x788d, 0x7888, 0x78d2, 0x73d0, 0x7959, 0xe724,
+ 0xe725, 0x410e, 0x799b, 0x8496, 0x79a5, 0x6a2d, 0xe72b, 0x7a3a,
+ 0x79f4, 0x416e, 0xe72f, 0x4132, 0x9235, 0x79f1, 0xe733, 0xe734,
+ 0xe735, 0xe736, 0xe737, 0x3597, 0x556b, 0x3570, 0x36aa, 0xe73c,
+ 0xe73d, 0x7ae2, 0x5a59, 0xe740, 0xe741, 0xe742, 0x5a0d, 0xe744,
+ 0x78f0, 0x5a2a, 0xe747, 0x7afe, 0x41f9, 0x7c5d, 0x7c6d, 0x4211,
+ 0xe74d, 0xe74e, 0xe74f, 0x7ccd, 0xe751, 0xe752, 0x7c8e, 0x7c7c,
+ 0x7cae, 0x6ab2, 0x7ddc, 0x7e07, 0x7dd3, 0x7f4e, 0xe75b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe75c, 0xe75d, 0x7d97, 0xe75f, 0x426a, 0xe761, 0xe762, 0x67d6,
+ 0xe764, 0xe765, 0x57c4, 0xe767, 0xe768, 0xe769, 0x7fdd, 0x7b27,
+ 0xe76c, 0xe76d, 0xe76e, 0x7b0c, 0xe770, 0x99e6, 0x8645, 0x9a63,
+ 0x6a1c, 0xe775, 0x39e2, 0xe777, 0xe778, 0x9a1f, 0xe77a, 0x8480,
+ 0xe77c, 0xe77d, 0x44ea, 0x8137, 0x4402, 0x80c6, 0x8109, 0x8142,
+ 0xe784, 0x98c3, 0xe786, 0x8262, 0x8265, 0xe789, 0x8453, 0xe78b,
+ 0x8610, 0xe78d, 0x5a86, 0x417f, 0xe790, 0x5b2b, 0xe792, 0x5ae4,
+ 0xe794, 0x86a0, 0xe796, 0xe797, 0x882d, 0xe799, 0x5a02, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x886e, 0x4f45, 0x8887, 0x88bf, 0x88e6, 0x8965, 0x894d,
+ 0xe7a2, 0x8954, 0xe7a4, 0xe7a5, 0xe7a6, 0xe7a7, 0xe7a8, 0xe7a9,
+ 0x3ead, 0x84a3, 0x46f5, 0x46cf, 0x37f2, 0x8a3d, 0x8a1c, 0xe7b1,
+ 0x5f4d, 0x922b, 0xe7b4, 0x65d4, 0x7129, 0x70c4, 0xe7b8, 0x9d6d,
+ 0x8c9f, 0x8ce9, 0xe7bc, 0x599a, 0x77c3, 0x59f0, 0x436e, 0x36d4,
+ 0x8e2a, 0x8ea7, 0xe7c4, 0x8f30, 0x8f4a, 0x42f4, 0x6c58, 0x6fbb,
+ 0xe7ca, 0x489b, 0x6f79, 0x6e8b, 0xe7ce, 0x9be9, 0x36b5, 0xe7d1,
+ 0x90bb, 0x9097, 0x5571, 0x4906, 0x91bb, 0x9404, 0xe7d8, 0x4062,
+ 0xe7da, 0x9427, 0xe7dc, 0xe7dd, 0x84e5, 0x8a2b, 0x9599, 0x95a7,
+ 0x9597, 0x9596, 0xe7e4, 0x7445, 0x3ec2, 0xe7e7, 0xe7e8, 0xe7e9,
+ 0x3ee7, 0xe7eb, 0x968f, 0xe7ed, 0xe7ee, 0xe7ef, 0x3ecc, 0xe7f1,
+ 0xe7f2, 0xe7f3, 0x7412, 0x746b, 0x3efc, 0x9741, 0xe7f8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6847, 0x4a1d, 0xe7fb, 0xe7fc, 0x975d, 0x9368, 0xe7ff, 0xe800,
+ 0xe801, 0xe802, 0x92ba, 0x5b11, 0x8b69, 0x493c, 0x73f9, 0xe808,
+ 0x979b, 0x9771, 0x9938, 0xe80c, 0x5dc1, 0xe80e, 0xe80f, 0x981f,
+ 0xe811, 0x92f6, 0xe813, 0x91e5, 0x44c0, 0xe816, 0xe817, 0xe818,
+ 0x98dc, 0xe81a, 0x3f00, 0x922a, 0x4925, 0x8414, 0x993b, 0x994d,
+ 0xe821, 0x3dfd, 0x999b, 0x4b6f, 0x99aa, 0x9a5c, 0xe827, 0xe828,
+ 0x6a8f, 0x9a21, 0x5afe, 0x9a2f, 0xe82d, 0x4b90, 0xe82f, 0x99bc,
+ 0x4bbd, 0x4b97, 0x937d, 0x5872, 0xe835, 0x5822, 0xe837, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe838, 0x7844, 0xe83a, 0xe83b, 0x68c5, 0x3d7d, 0x9458,
+ 0x3927, 0x6150, 0xe841, 0xe842, 0x6107, 0x9c4f, 0x9c53, 0x9c7b,
+ 0x9c35, 0x9c10, 0x9b7f, 0x9bcf, 0xe84b, 0x9b9f, 0xe84d, 0xe84e,
+ 0x9d21, 0x4cae, 0xe851, 0x9e18, 0x4cb0, 0x9d0c, 0xe855, 0xe856,
+ 0xe857, 0xe858, 0x9da5, 0x84bd, 0xe85b, 0xe85c, 0xe85d, 0x85fc,
+ 0x4533, 0xe860, 0xe861, 0xe862, 0x8420, 0x85ee, 0xe865, 0xe866,
+ 0xe867, 0x79e2, 0xe869, 0xe86a, 0x492d, 0xe86c, 0x3d62, 0x93db,
+ 0x92be, 0x9348, 0xe871, 0x78b9, 0x9277, 0x944d, 0x4fe4, 0x3440,
+ 0x9064, 0xe878, 0x783d, 0x7854, 0x78b6, 0x784b, 0xe87d, 0xe87e,
+ 0xe87f, 0x369a, 0x4f72, 0x6fda, 0x6fd9, 0x701e, 0x701e, 0x5414,
+ 0xe887, 0x57bb, 0x58f3, 0x578a, 0x9d16, 0x57d7, 0x7134, 0x34af,
+ 0xe88f, 0x71eb, 0xe891, 0xe892, 0x5b28, 0xe894, 0xe895, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x610c, 0x5ace, 0x5a0b, 0x42bc, 0xe89a, 0x372c, 0x4b7b, 0xe89d,
+ 0x93bb, 0x93b8, 0xe8a0, 0xe8a1, 0x8472, 0xe8a3, 0xe8a4, 0xe8a5,
+ 0xe8a6, 0xe8a7, 0x5994, 0xe8a9, 0xe8aa, 0x7da8, 0xe8ac, 0xe8ad,
+ 0xe8ae, 0xe8af, 0xe8b0, 0x92e5, 0x73e2, 0x3ee9, 0x74b4, 0xe8b5,
+ 0xe8b6, 0x3ee1, 0xe8b8, 0x6ad8, 0x73f3, 0x73fb, 0x3ed6, 0xe8bd,
+ 0xe8be, 0xe8bf, 0xe8c0, 0xe8c1, 0xe8c2, 0xe8c3, 0x7448, 0xe8c5,
+ 0x70a5, 0xe8c7, 0x9284, 0x73e6, 0x935f, 0xe8cb, 0x9331, 0xe8cd,
+ 0xe8ce, 0x9386, 0xe8d0, 0xe8d1, 0x4935, 0xe8d3, 0x716b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe8d5, 0xe8d6, 0x56a4, 0xe8d8, 0xe8d9, 0xe8da, 0x5502,
+ 0x79c4, 0xe8dd, 0x7dfe, 0xe8df, 0xe8e0, 0xe8e1, 0x452e, 0x9401,
+ 0x370a, 0xe8e5, 0xe8e6, 0x59b0, 0xe8e8, 0xe8e9, 0xe8ea, 0x5aa1,
+ 0x36e2, 0xe8ed, 0x36b0, 0x925f, 0x5a79, 0xe8f1, 0xe8f2, 0x9374,
+ 0x3ccd, 0xe8f5, 0x4a96, 0x398a, 0x50f4, 0x3d69, 0x3d4c, 0xe8fb,
+ 0x7175, 0x42fb, 0xe8fe, 0x6e0f, 0xe900, 0x44eb, 0x6d57, 0xe903,
+ 0x7067, 0x6caf, 0x3cd6, 0xe907, 0xe908, 0x6e02, 0x6f0c, 0x3d6f,
+ 0xe90c, 0x7551, 0x36bc, 0x34c8, 0x4680, 0x3eda, 0x4871, 0x59c4,
+ 0x926e, 0x493e, 0x8f41, 0xe917, 0xe918, 0x5812, 0x57c8, 0x36d6,
+ 0xe91c, 0x70fe, 0xe91e, 0xe91f, 0xe920, 0xe921, 0xe922, 0x68b9,
+ 0x6967, 0xe925, 0xe926, 0xe927, 0xe928, 0xe929, 0xe92a, 0xe92b,
+ 0xe92c, 0x6a1a, 0xe92e, 0xe92f, 0x843e, 0x44df, 0x44ce, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe933, 0xe934, 0xe935, 0xe936, 0x6f17, 0xe938, 0x833d, 0xe93a,
+ 0x83ed, 0xe93c, 0xe93d, 0xe93e, 0x5989, 0x5a82, 0xe941, 0x5a61,
+ 0x5a71, 0xe944, 0xe945, 0x372d, 0x59ef, 0xe948, 0x36c7, 0x718e,
+ 0x9390, 0x669a, 0xe94d, 0x5a6e, 0x5a2b, 0xe950, 0x6a2b, 0xe952,
+ 0xe953, 0xe954, 0xe955, 0x711d, 0xe957, 0xe958, 0x4fb0, 0xe95a,
+ 0x5cc2, 0xe95c, 0xe95d, 0xe95e, 0x6a0c, 0xe960, 0xe961, 0x70a6,
+ 0x7133, 0xe964, 0x3da5, 0x6cdf, 0xe967, 0xe968, 0x7e65, 0x59eb,
+ 0x5d2f, 0x3df3, 0x5f5c, 0xe96e, 0xe96f, 0x7da4, 0x8426, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5485, 0xe973, 0xe974, 0xe975, 0x577e, 0xe977, 0xe978,
+ 0x3fe5, 0xe97a, 0xe97b, 0x7003, 0xe97d, 0x5d70, 0x738f, 0x7cd3,
+ 0xe981, 0xe982, 0x4fc8, 0x7fe7, 0x72cd, 0x7310, 0xe987, 0x7338,
+ 0x7339, 0xe98a, 0x7341, 0x7348, 0x3ea9, 0xe98e, 0x906c, 0x71f5,
+ 0xe991, 0x73e1, 0x81f6, 0x3eca, 0x770c, 0x3ed1, 0x6ca2, 0x56fd,
+ 0x7419, 0x741e, 0x741f, 0x3ee2, 0x3ef0, 0x3ef4, 0x3efa, 0x74d3,
+ 0x3f0e, 0x3f53, 0x7542, 0x756d, 0x7572, 0x758d, 0x3f7c, 0x75c8,
+ 0x75dc, 0x3fc0, 0x764d, 0x3fd7, 0x7674, 0x3fdc, 0x767a, 0xe9b0,
+ 0x7188, 0x5623, 0x8980, 0x5869, 0x401d, 0x7743, 0x4039, 0x6761,
+ 0x4045, 0x35db, 0x7798, 0x406a, 0x406f, 0x5c5e, 0x77be, 0x77cb,
+ 0x58f2, 0x7818, 0x70b9, 0x781c, 0x40a8, 0x7839, 0x7847, 0x7851,
+ 0x7866, 0x8448, 0xe9cb, 0x7933, 0x6803, 0x7932, 0x4103, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4109, 0x7991, 0x7999, 0x8fbb, 0x7a06, 0x8fbc, 0x4167, 0x7a91,
+ 0x41b2, 0x7abc, 0x8279, 0x41c4, 0x7acf, 0x7adb, 0x41cf, 0x4e21,
+ 0x7b62, 0x7b6c, 0x7b7b, 0x7c12, 0x7c1b, 0x4260, 0x427a, 0x7c7b,
+ 0x7c9c, 0x428c, 0x7cb8, 0x4294, 0x7ced, 0x8f93, 0x70c0, 0xe9ef,
+ 0x7dcf, 0x7dd4, 0x7dd0, 0x7dfd, 0x7fae, 0x7fb4, 0x729f, 0x4397,
+ 0x8020, 0x8025, 0x7b39, 0x802e, 0x8031, 0x8054, 0x3dcc, 0x57b4,
+ 0x70a0, 0x80b7, 0x80e9, 0x43ed, 0x810c, 0x732a, 0x810e, 0x8112,
+ 0x7560, 0x8114, 0x4401, 0x3b39, 0x8156, 0x8159, 0x815a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4413, 0x583a, 0x817c, 0x8184, 0x4425, 0x8193, 0x442d,
+ 0x81a5, 0x57ef, 0x81c1, 0x81e4, 0x8254, 0x448f, 0x82a6, 0x8276,
+ 0x82ca, 0x82d8, 0x82ff, 0x44b0, 0x8357, 0x9669, 0x698a, 0x8405,
+ 0x70f5, 0x8464, 0x60e3, 0x8488, 0x4504, 0x84be, 0x84e1, 0x84f8,
+ 0x8510, 0x8538, 0x8552, 0x453b, 0x856f, 0x8570, 0x85e0, 0x4577,
+ 0x8672, 0x8692, 0x86b2, 0x86ef, 0x9645, 0x878b, 0x4606, 0x4617,
+ 0x88ae, 0x88ff, 0x8924, 0x8947, 0x8991, 0xea43, 0x8a29, 0x8a38,
+ 0x8a94, 0x8ab4, 0x8c51, 0x8cd4, 0x8cf2, 0x8d1c, 0x4798, 0x585f,
+ 0x8dc3, 0x47ed, 0x4eee, 0x8e3a, 0x55d8, 0x5754, 0x8e71, 0x55f5,
+ 0x8eb0, 0x4837, 0x8ece, 0x8ee2, 0x8ee4, 0x8eed, 0x8ef2, 0x8fb7,
+ 0x8fc1, 0x8fca, 0x8fcc, 0x9033, 0x99c4, 0x48ad, 0x98e0, 0x9213,
+ 0x491e, 0x9228, 0x9258, 0x926b, 0x92b1, 0x92ae, 0x92bf, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x92e3, 0x92eb, 0x92f3, 0x92f4, 0x92fd, 0x9343, 0x9384, 0x93ad,
+ 0x4945, 0x4951, 0x9ebf, 0x9417, 0x5301, 0x941d, 0x942d, 0x943e,
+ 0x496a, 0x9454, 0x9479, 0x952d, 0x95a2, 0x49a7, 0x95f4, 0x9633,
+ 0x49e5, 0x67a0, 0x4a24, 0x9740, 0x4a35, 0x97b2, 0x97c2, 0x5654,
+ 0x4ae4, 0x60e8, 0x98b9, 0x4b19, 0x98f1, 0x5844, 0x990e, 0x9919,
+ 0x51b4, 0x991c, 0x9937, 0x9942, 0x995d, 0x9962, 0x4b70, 0x99c5,
+ 0x4b9d, 0x9a3c, 0x9b0f, 0x7a83, 0x9b69, 0x9b81, 0x9bdd, 0x9bf1,
+ 0x9bf4, 0x4c6d, 0x9c20, 0x376f, 0xeaa9, 0x9d49, 0x9c3a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9efe, 0x5650, 0x9d93, 0x9dbd, 0x9dc0, 0x9dfc, 0x94f6,
+ 0x8fb6, 0x9e7b, 0x9eac, 0x9eb1, 0x9ebd, 0x9ec6, 0x94dc, 0x9ee2,
+ 0x9ef1, 0x9ef8, 0x7ac8, 0x9f44, 0xeabf, 0xeac0, 0xeac1, 0x691a,
+ 0x94c3, 0x59ac, 0xeac5, 0x5840, 0x94c1, 0x37b9, 0xeac9, 0xeaca,
+ 0xeacb, 0xeacc, 0x5757, 0x7173, 0xeacf, 0xead0, 0xead1, 0x546a,
+ 0xead3, 0xead4, 0x549e, 0xead6, 0xead7, 0xead8, 0xead9, 0xeada,
+ 0x60e7, 0xeadc, 0x567a, 0xeade, 0xeadf, 0xeae0, 0xeae1, 0xeae2,
+ 0xeae3, 0x6955, 0x9c2f, 0x87a5, 0xeae7, 0xeae8, 0xeae9, 0xeaea,
+ 0xeaeb, 0xeaec, 0x5c20, 0xeaee, 0x5e0b, 0xeaf0, 0xeaf1, 0xeaf2,
+ 0x671e, 0xeaf4, 0xeaf5, 0xeaf6, 0x3647, 0xeaf8, 0xeaf9, 0xeafa,
+ 0xeafb, 0x5364, 0x84ad, 0xeafe, 0xeaff, 0xeb00, 0x8b81, 0xeb02,
+ 0xeb03, 0xeb04, 0xeb05, 0x4e78, 0x70bb, 0xeb08, 0xeb09, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xeb0a, 0xeb0b, 0xeb0c, 0xeb0d, 0xeb0e, 0xeb0f, 0x62c3, 0xeb11,
+ 0xeb12, 0x7198, 0x6855, 0xeb15, 0x69e9, 0x36c8, 0xeb18, 0xeb19,
+ 0xeb1a, 0xeb1b, 0xeb1c, 0xeb1d, 0x82fd, 0xeb1f, 0xeb20, 0xeb21,
+ 0x89a5, 0xeb23, 0x8fa0, 0xeb25, 0x97b8, 0xeb27, 0x9847, 0x9abd,
+ 0xeb2a, 0xeb2b, 0xeb2c, 0xeb2d, 0xeb2e, 0xeb2f, 0xeb30, 0xeb31,
+ 0xeb32, 0xeb33, 0xeb34, 0xeb35, 0xeb36, 0xeb37, 0xeb38, 0xeb39,
+ 0x5fb1, 0x6648, 0x66bf, 0xeb3d, 0xeb3e, 0xeb3f, 0x7201, 0xeb41,
+ 0x77d7, 0xeb43, 0xeb44, 0x7e87, 0xeb46, 0x58b5, 0x670e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6918, 0xeb4a, 0xeb4b, 0xeb4c, 0xeb4d, 0xeb4e, 0xeb4f,
+ 0xeb50, 0x48d0, 0x4ab8, 0xeb53, 0xeb54, 0xeb55, 0xeb56, 0xeb57,
+ 0xeb58, 0xeb59, 0xeb5a, 0xeb5b, 0x51d2, 0xeb5d, 0x599f, 0xeb5f,
+ 0x3bbe, 0xeb61, 0xeb62, 0xeb63, 0x5788, 0xeb65, 0x399b, 0xeb67,
+ 0xeb68, 0xeb69, 0x3762, 0xeb6b, 0x8b5e, 0xeb6d, 0x99d6, 0xeb6f,
+ 0xeb70, 0xeb71, 0x7209, 0xeb73, 0xeb74, 0x5965, 0xeb76, 0xeb77,
+ 0xeb78, 0x8eda, 0xeb7a, 0x528f, 0x573f, 0x7171, 0xeb7e, 0xeb7f,
+ 0xeb80, 0xeb81, 0x55bc, 0xeb83, 0xeb84, 0xeb85, 0x91d4, 0x3473,
+ 0xeb88, 0xeb89, 0xeb8a, 0x4718, 0xeb8c, 0xeb8d, 0xeb8e, 0xeb8f,
+ 0xeb90, 0x5066, 0x34fb, 0xeb93, 0x60de, 0xeb95, 0x477c, 0xeb97,
+ 0xeb98, 0xeb99, 0xeb9a, 0xeb9b, 0x57a1, 0x7151, 0x6fb6, 0xeb9f,
+ 0xeba0, 0x9056, 0xeba2, 0xeba3, 0x8b62, 0xeba5, 0xeba6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5d5b, 0xeba8, 0x8f36, 0xebaa, 0xebab, 0x8aea, 0xebad, 0xebae,
+ 0xebaf, 0xebb0, 0x4bc0, 0xebb2, 0xebb3, 0xebb4, 0x9465, 0xebb6,
+ 0x6195, 0x5a27, 0xebb9, 0x4fbb, 0x56b9, 0xebbc, 0xebbd, 0x4e6a,
+ 0xebbf, 0x9656, 0x6d8f, 0xebc2, 0x3618, 0x8977, 0xebc5, 0xebc6,
+ 0xebc7, 0xebc8, 0x71df, 0xebca, 0x7b42, 0xebcc, 0xebcd, 0xebce,
+ 0x9104, 0xebd0, 0x7a45, 0x9df0, 0xebd3, 0x9a26, 0xebd5, 0x365f,
+ 0xebd7, 0xebd8, 0x7983, 0xebda, 0xebdb, 0x5d2c, 0xebdd, 0x83cf,
+ 0xebdf, 0x46d0, 0xebe1, 0x753b, 0x8865, 0xebe4, 0x58b6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x371c, 0xebe7, 0xebe8, 0xebe9, 0x3c54, 0xebeb, 0xebec,
+ 0x9281, 0xebee, 0xebef, 0x9330, 0xebf1, 0xebf2, 0x6c39, 0x949f,
+ 0xebf5, 0xebf6, 0x8827, 0x88f5, 0xebf9, 0xebfa, 0xebfb, 0x6eb8,
+ 0xebfd, 0xebfe, 0x39a4, 0x36b9, 0x5c10, 0x79e3, 0x453f, 0x66b6,
+ 0xec05, 0xec06, 0x8943, 0xec08, 0xec09, 0x56d6, 0x40df, 0xec0c,
+ 0x39a1, 0xec0e, 0xec0f, 0xec10, 0x71ad, 0x8366, 0xec13, 0xec14,
+ 0x5a67, 0x4cb7, 0xec17, 0xec18, 0xec19, 0xec1a, 0xec1b, 0xec1c,
+ 0xec1d, 0x7b43, 0x797e, 0xec20, 0x6fb5, 0xec22, 0x6a03, 0xec24,
+ 0x53a2, 0xec26, 0x93bf, 0x6836, 0x975d, 0xec2a, 0xec2b, 0xec2c,
+ 0xec2d, 0xec2e, 0xec2f, 0x5d85, 0xec31, 0xec32, 0x5715, 0x9823,
+ 0xec35, 0x5dab, 0xec37, 0x65be, 0x69d5, 0x53d2, 0xec3b, 0xec3c,
+ 0x3c11, 0x6736, 0xec3f, 0xec40, 0xec41, 0xec42, 0xec43, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xec44, 0xec45, 0xec46, 0xec47, 0xec48, 0xec49, 0x35ca, 0xec4b,
+ 0xec4c, 0x48fa, 0x63e6, 0xec4f, 0x7808, 0x9255, 0xec52, 0x43f2,
+ 0xec54, 0x43df, 0xec56, 0xec57, 0xec58, 0x59f8, 0xec5a, 0x8f0b,
+ 0xec5c, 0xec5d, 0x7b51, 0xec5f, 0xec60, 0x3df7, 0xec62, 0xec63,
+ 0x8fd0, 0x728f, 0x568b, 0xec67, 0xec68, 0xec69, 0xec6a, 0xec6b,
+ 0xec6c, 0xec6d, 0xec6e, 0xec6f, 0xec70, 0xec71, 0xec72, 0xec73,
+ 0x7e9f, 0xec75, 0xec76, 0x4ca4, 0x9547, 0xec79, 0x71a2, 0xec7b,
+ 0x4d91, 0x9012, 0xec7e, 0x4d9c, 0xec80, 0x8fbe, 0x55c1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8fba, 0xec84, 0x8fb9, 0xec86, 0x4509, 0x7e7f, 0x6f56,
+ 0x6ab1, 0x4eea, 0x34e4, 0xec8d, 0xec8e, 0x373a, 0x8e80, 0xec91,
+ 0xec92, 0xec93, 0xec94, 0xec95, 0xec96, 0x3deb, 0xec98, 0xec99,
+ 0xec9a, 0xec9b, 0x4e9a, 0xec9d, 0xec9e, 0x56bf, 0xeca0, 0x8e0e,
+ 0x5b6d, 0xeca3, 0xeca4, 0x63de, 0x62d0, 0xeca7, 0xeca8, 0x6530,
+ 0x562d, 0xecab, 0x541a, 0xecad, 0x3dc6, 0xecaf, 0x4c7d, 0x5622,
+ 0x561e, 0x7f49, 0xecb4, 0x5975, 0xecb6, 0x8770, 0x4e1c, 0xecb9,
+ 0xecba, 0xecbb, 0x8117, 0x9d5e, 0x8d18, 0x763b, 0x9c45, 0x764e,
+ 0x77b9, 0x9345, 0x5432, 0x8148, 0x82f7, 0x5625, 0x8132, 0x8418,
+ 0x80bd, 0x55ea, 0x7962, 0x5643, 0x5416, 0xeccf, 0x35ce, 0x5605,
+ 0x55f1, 0x66f1, 0xecd4, 0x362d, 0x7534, 0x55f0, 0x55ba, 0x5497,
+ 0x5572, 0xecdb, 0xecdc, 0x5ed0, 0xecde, 0xecdf, 0xece0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xece1, 0x9eab, 0x7d5a, 0x55de, 0xece5, 0x629d, 0x976d, 0x5494,
+ 0x8ccd, 0x71f6, 0x9176, 0x63fc, 0x63b9, 0x63fe, 0x5569, 0xecf0,
+ 0x9c72, 0xecf2, 0x519a, 0x34df, 0xecf5, 0x51a7, 0x544d, 0x551e,
+ 0x5513, 0x7666, 0x8e2d, 0xecfc, 0x75b1, 0x80b6, 0x8804, 0x8786,
+ 0x88c7, 0x81b6, 0x841c, 0xed04, 0x44ec, 0x7304, 0xed07, 0x5b90,
+ 0x830b, 0xed0a, 0x567b, 0xed0c, 0xed0d, 0xed0e, 0xed0f, 0xed10,
+ 0xed11, 0x9170, 0xed13, 0x9208, 0xed15, 0xed16, 0xed17, 0xed18,
+ 0x7266, 0xed1a, 0x474e, 0xed1c, 0xed1d, 0xed1e, 0x40fa, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9c5d, 0x651f, 0xed22, 0x48f3, 0xed24, 0xed25, 0xed26,
+ 0xed27, 0x6062, 0xed29, 0xed2a, 0xed2b, 0xed2c, 0xed2d, 0x71a3,
+ 0x7e8e, 0x9d50, 0x4e1a, 0x4e04, 0x3577, 0x5b0d, 0x6cb2, 0x5367,
+ 0x36ac, 0x39dc, 0x537d, 0x36a5, 0xed3b, 0x589a, 0xed3d, 0x822d,
+ 0x544b, 0x57aa, 0xed41, 0xed42, 0xed43, 0x3a52, 0xed45, 0x7374,
+ 0xed47, 0x4d09, 0x9bed, 0xed4a, 0xed4b, 0x4c5b, 0xed4d, 0xed4e,
+ 0xed4f, 0x845c, 0xed51, 0xed52, 0xed53, 0xed54, 0x632e, 0x7d25,
+ 0xed57, 0xed58, 0x3a2a, 0x9008, 0x52cc, 0x3e74, 0x367a, 0x45e9,
+ 0xed5f, 0x7640, 0x5af0, 0xed62, 0x787a, 0x47b6, 0x58a7, 0x40bf,
+ 0x567c, 0x9b8b, 0x5d74, 0x7654, 0xed6b, 0x9e85, 0x4ce1, 0x75f9,
+ 0x37fb, 0x6119, 0xed71, 0xed72, 0xed73, 0x565d, 0xed75, 0x57a7,
+ 0xed77, 0xed78, 0x5234, 0xed7a, 0x35ad, 0x6c4a, 0x9d7c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7c56, 0x9b39, 0x57de, 0xed81, 0x5c53, 0x64d3, 0xed84, 0xed85,
+ 0xed86, 0x86ad, 0xed88, 0xed89, 0xed8a, 0xed8b, 0xed8c, 0x51fe,
+ 0xed8e, 0x5d8e, 0x9703, 0xed91, 0x9e81, 0x904c, 0x7b1f, 0x9b02,
+ 0x5cd1, 0x7ba3, 0x6268, 0x6335, 0x9aff, 0x7bcf, 0x9b2a, 0x7c7e,
+ 0x9b2e, 0x7c42, 0x7c86, 0x9c15, 0x7bfc, 0x9b09, 0x9f17, 0x9c1b,
+ 0xeda6, 0x9f5a, 0x5573, 0x5bc3, 0x4ffd, 0x9e98, 0x4ff2, 0x5260,
+ 0x3e06, 0x52d1, 0x5767, 0x5056, 0x59b7, 0x5e12, 0x97c8, 0x9dab,
+ 0x8f5c, 0x5469, 0x97b4, 0x9940, 0x97ba, 0x532c, 0x6130, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x692c, 0x53da, 0x9c0a, 0x9d02, 0x4c3b, 0x9641, 0x6980,
+ 0x50a6, 0x7546, 0xedc6, 0x99da, 0x5273, 0xedc9, 0x9159, 0x9681,
+ 0x915c, 0xedcd, 0x9151, 0xedcf, 0x637f, 0xedd1, 0x6aca, 0x5611,
+ 0x918e, 0x757a, 0x6285, 0xedd7, 0x734f, 0x7c70, 0xedda, 0xeddb,
+ 0xeddc, 0xeddd, 0x76d6, 0x9b9d, 0x4e2a, 0xede1, 0x83be, 0x8842,
+ 0xede4, 0x5c4a, 0x69c0, 0x50ed, 0x577a, 0x521f, 0x5df5, 0x4ece,
+ 0x6c31, 0xeded, 0x4f39, 0x549c, 0x54da, 0x529a, 0x8d82, 0x35fe,
+ 0x5f0c, 0x35f3, 0xedf6, 0x6b52, 0x917c, 0x9fa5, 0x9b97, 0x982e,
+ 0x98b4, 0x9aba, 0x9ea8, 0x9e84, 0x717a, 0x7b14, 0xee02, 0x6bfa,
+ 0x8818, 0x7f78, 0xee06, 0x5620, 0xee08, 0x8e77, 0x9f53, 0xee0b,
+ 0x8dd4, 0x8e4f, 0x9e1c, 0x8e01, 0x6282, 0xee11, 0x8e28, 0x8e75,
+ 0x7ad3, 0xee15, 0x7a3e, 0x78d8, 0x6cea, 0x8a67, 0x7607, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xee1b, 0x9f26, 0x6cce, 0x87d6, 0x75c3, 0xee20, 0x7853, 0xee22,
+ 0x8d0c, 0x72e2, 0x7371, 0x8b2d, 0x7302, 0x74f1, 0x8ceb, 0xee2a,
+ 0x862f, 0x5fba, 0x88a0, 0x44b7, 0xee2f, 0xee30, 0xee31, 0xee32,
+ 0x8a7e, 0xee34, 0xee35, 0x60fd, 0x7667, 0x9ad7, 0x9d44, 0x936e,
+ 0x9b8f, 0x87f5, 0xee3d, 0x880f, 0x8cf7, 0x732c, 0x9721, 0x9bb0,
+ 0x35d6, 0x72b2, 0x4c07, 0x7c51, 0x994a, 0xee48, 0x6159, 0x4c04,
+ 0x9e96, 0x617d, 0xee4d, 0x575f, 0x616f, 0x62a6, 0x6239, 0x62ce,
+ 0x3a5c, 0x61e2, 0x53aa, 0xee56, 0x6364, 0x6802, 0x35d2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5d57, 0xee5b, 0x8fda, 0xee5d, 0xee5e, 0x50d9, 0xee60,
+ 0x7906, 0x5332, 0x9638, 0xee64, 0x4065, 0xee66, 0x77fe, 0xee68,
+ 0x7cc2, 0xee6a, 0x7cda, 0x7a2d, 0x8066, 0x8063, 0x7d4d, 0x7505,
+ 0x74f2, 0x8994, 0x821a, 0x670c, 0x8062, 0xee76, 0x805b, 0x74f0,
+ 0x8103, 0x7724, 0x8989, 0xee7c, 0x7553, 0xee7e, 0x87a9, 0x87ce,
+ 0x81c8, 0x878c, 0x8a49, 0x8cad, 0x8b43, 0x772b, 0x74f8, 0x84da,
+ 0x3635, 0x69b2, 0x8da6, 0xee8c, 0x89a9, 0x7468, 0x6db9, 0x87c1,
+ 0xee91, 0x74e7, 0x3ddb, 0x7176, 0x60a4, 0x619c, 0x3cd1, 0x7162,
+ 0x6077, 0xee9a, 0x7f71, 0xee9c, 0x7250, 0x60e9, 0x4b7e, 0x5220,
+ 0x3c18, 0xeea2, 0xeea3, 0xeea4, 0xeea5, 0xeea6, 0xeea7, 0xeea8,
+ 0xeea9, 0xeeaa, 0x5cc1, 0xeeac, 0xeead, 0xeeae, 0xeeaf, 0xeeb0,
+ 0xeeb1, 0x4562, 0x5b1f, 0xeeb4, 0x9f50, 0x9ea6, 0xeeb7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3000, 0xff0c, 0x3001, 0x3002, 0xff0e, 0x2027, 0xff1b, 0xff1a,
+ 0xff1f, 0xff01, 0xfe30, 0x2026, 0x2025, 0xfe50, 0xfe51, 0xfe52,
+ 0x00b7, 0xfe54, 0xfe55, 0xfe56, 0xfe57, 0xff5c, 0x2013, 0xfe31,
+ 0x2014, 0xfe33, 0x2574, 0xfe34, 0xfe4f, 0xff08, 0xff09, 0xfe35,
+ 0xfe36, 0xff5b, 0xff5d, 0xfe37, 0xfe38, 0x3014, 0x3015, 0xfe39,
+ 0xfe3a, 0x3010, 0x3011, 0xfe3b, 0xfe3c, 0x300a, 0x300b, 0xfe3d,
+ 0xfe3e, 0x3008, 0x3009, 0xfe3f, 0xfe40, 0x300c, 0x300d, 0xfe41,
+ 0xfe42, 0x300e, 0x300f, 0xfe43, 0xfe44, 0xfe59, 0xfe5a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xfe5b, 0xfe5c, 0xfe5d, 0xfe5e, 0x2018, 0x2019, 0x201c,
+ 0x201d, 0x301d, 0x301e, 0x2035, 0x2032, 0xff03, 0xff06, 0xff0a,
+ 0x203b, 0x00a7, 0x3003, 0x25cb, 0x25cf, 0x25b3, 0x25b2, 0x25ce,
+ 0x2606, 0x2605, 0x25c7, 0x25c6, 0x25a1, 0x25a0, 0x25bd, 0x25bc,
+ 0x32a3, 0x2105, 0x00af, 0xffe3, 0xff3f, 0x02cd, 0xfe49, 0xfe4a,
+ 0xfe4d, 0xfe4e, 0xfe4b, 0xfe4c, 0xfe5f, 0xfe60, 0xfe61, 0xff0b,
+ 0xff0d, 0x00d7, 0x00f7, 0x00b1, 0x221a, 0xff1c, 0xff1e, 0xff1d,
+ 0x2266, 0x2267, 0x2260, 0x221e, 0x2252, 0x2261, 0xfe62, 0xfe63,
+ 0xfe64, 0xfe65, 0xfe66, 0xff5e, 0x2229, 0x222a, 0x22a5, 0x2220,
+ 0x221f, 0x22bf, 0x33d2, 0x33d1, 0x222b, 0x222e, 0x2235, 0x2234,
+ 0x2640, 0x2642, 0x2295, 0x2299, 0x2191, 0x2193, 0x2190, 0x2192,
+ 0x2196, 0x2197, 0x2199, 0x2198, 0x2225, 0x2223, 0xff0f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xff3c, 0x2215, 0xfe68, 0xff04, 0xffe5, 0x3012, 0xffe0, 0xffe1,
+ 0xff05, 0xff20, 0x2103, 0x2109, 0xfe69, 0xfe6a, 0xfe6b, 0x33d5,
+ 0x339c, 0x339d, 0x339e, 0x33ce, 0x33a1, 0x338e, 0x338f, 0x33c4,
+ 0x00b0, 0x5159, 0x515b, 0x515e, 0x515d, 0x5161, 0x5163, 0x55e7,
+ 0x74e9, 0x7cce, 0x2581, 0x2582, 0x2583, 0x2584, 0x2585, 0x2586,
+ 0x2587, 0x2588, 0x258f, 0x258e, 0x258d, 0x258c, 0x258b, 0x258a,
+ 0x2589, 0x253c, 0x2534, 0x252c, 0x2524, 0x251c, 0x2594, 0x2500,
+ 0x2502, 0x2595, 0x250c, 0x2510, 0x2514, 0x2518, 0x256d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x256e, 0x2570, 0x256f, 0x2550, 0x255e, 0x256a, 0x2561,
+ 0x25e2, 0x25e3, 0x25e5, 0x25e4, 0x2571, 0x2572, 0x2573, 0xff10,
+ 0xff11, 0xff12, 0xff13, 0xff14, 0xff15, 0xff16, 0xff17, 0xff18,
+ 0xff19, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166,
+ 0x2167, 0x2168, 0x2169, 0x3021, 0x3022, 0x3023, 0x3024, 0x3025,
+ 0x3026, 0x3027, 0x3028, 0x3029, 0x5341, 0x5344, 0x5345, 0xff21,
+ 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 0xff29,
+ 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31,
+ 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 0xff39,
+ 0xff3a, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47,
+ 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f,
+ 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xff57, 0xff58, 0xff59, 0xff5a, 0x0391, 0x0392, 0x0393, 0x0394,
+ 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c,
+ 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1, 0x03a3, 0x03a4, 0x03a5,
+ 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03b1, 0x03b2, 0x03b3, 0x03b4,
+ 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc,
+ 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5,
+ 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x3105, 0x3106, 0x3107, 0x3108,
+ 0x3109, 0x310a, 0x310b, 0x310c, 0x310d, 0x310e, 0x310f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3110, 0x3111, 0x3112, 0x3113, 0x3114, 0x3115, 0x3116,
+ 0x3117, 0x3118, 0x3119, 0x311a, 0x311b, 0x311c, 0x311d, 0x311e,
+ 0x311f, 0x3120, 0x3121, 0x3122, 0x3123, 0x3124, 0x3125, 0x3126,
+ 0x3127, 0x3128, 0x3129, 0x02d9, 0x02c9, 0x02ca, 0x02c7, 0x02cb,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4e00, 0x4e59, 0x4e01, 0x4e03, 0x4e43, 0x4e5d, 0x4e86, 0x4e8c,
+ 0x4eba, 0x513f, 0x5165, 0x516b, 0x51e0, 0x5200, 0x5201, 0x529b,
+ 0x5315, 0x5341, 0x535c, 0x53c8, 0x4e09, 0x4e0b, 0x4e08, 0x4e0a,
+ 0x4e2b, 0x4e38, 0x51e1, 0x4e45, 0x4e48, 0x4e5f, 0x4e5e, 0x4e8e,
+ 0x4ea1, 0x5140, 0x5203, 0x52fa, 0x5343, 0x53c9, 0x53e3, 0x571f,
+ 0x58eb, 0x5915, 0x5927, 0x5973, 0x5b50, 0x5b51, 0x5b53, 0x5bf8,
+ 0x5c0f, 0x5c22, 0x5c38, 0x5c71, 0x5ddd, 0x5de5, 0x5df1, 0x5df2,
+ 0x5df3, 0x5dfe, 0x5e72, 0x5efe, 0x5f0b, 0x5f13, 0x624d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4e11, 0x4e10, 0x4e0d, 0x4e2d, 0x4e30, 0x4e39, 0x4e4b,
+ 0x5c39, 0x4e88, 0x4e91, 0x4e95, 0x4e92, 0x4e94, 0x4ea2, 0x4ec1,
+ 0x4ec0, 0x4ec3, 0x4ec6, 0x4ec7, 0x4ecd, 0x4eca, 0x4ecb, 0x4ec4,
+ 0x5143, 0x5141, 0x5167, 0x516d, 0x516e, 0x516c, 0x5197, 0x51f6,
+ 0x5206, 0x5207, 0x5208, 0x52fb, 0x52fe, 0x52ff, 0x5316, 0x5339,
+ 0x5348, 0x5347, 0x5345, 0x535e, 0x5384, 0x53cb, 0x53ca, 0x53cd,
+ 0x58ec, 0x5929, 0x592b, 0x592a, 0x592d, 0x5b54, 0x5c11, 0x5c24,
+ 0x5c3a, 0x5c6f, 0x5df4, 0x5e7b, 0x5eff, 0x5f14, 0x5f15, 0x5fc3,
+ 0x6208, 0x6236, 0x624b, 0x624e, 0x652f, 0x6587, 0x6597, 0x65a4,
+ 0x65b9, 0x65e5, 0x66f0, 0x6708, 0x6728, 0x6b20, 0x6b62, 0x6b79,
+ 0x6bcb, 0x6bd4, 0x6bdb, 0x6c0f, 0x6c34, 0x706b, 0x722a, 0x7236,
+ 0x723b, 0x7247, 0x7259, 0x725b, 0x72ac, 0x738b, 0x4e19, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4e16, 0x4e15, 0x4e14, 0x4e18, 0x4e3b, 0x4e4d, 0x4e4f, 0x4e4e,
+ 0x4ee5, 0x4ed8, 0x4ed4, 0x4ed5, 0x4ed6, 0x4ed7, 0x4ee3, 0x4ee4,
+ 0x4ed9, 0x4ede, 0x5145, 0x5144, 0x5189, 0x518a, 0x51ac, 0x51f9,
+ 0x51fa, 0x51f8, 0x520a, 0x52a0, 0x529f, 0x5305, 0x5306, 0x5317,
+ 0x531d, 0x4edf, 0x534a, 0x5349, 0x5361, 0x5360, 0x536f, 0x536e,
+ 0x53bb, 0x53ef, 0x53e4, 0x53f3, 0x53ec, 0x53ee, 0x53e9, 0x53e8,
+ 0x53fc, 0x53f8, 0x53f5, 0x53eb, 0x53e6, 0x53ea, 0x53f2, 0x53f1,
+ 0x53f0, 0x53e5, 0x53ed, 0x53fb, 0x56db, 0x56da, 0x5916, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x592e, 0x5931, 0x5974, 0x5976, 0x5b55, 0x5b83, 0x5c3c,
+ 0x5de8, 0x5de7, 0x5de6, 0x5e02, 0x5e03, 0x5e73, 0x5e7c, 0x5f01,
+ 0x5f18, 0x5f17, 0x5fc5, 0x620a, 0x6253, 0x6254, 0x6252, 0x6251,
+ 0x65a5, 0x65e6, 0x672e, 0x672c, 0x672a, 0x672b, 0x672d, 0x6b63,
+ 0x6bcd, 0x6c11, 0x6c10, 0x6c38, 0x6c41, 0x6c40, 0x6c3e, 0x72af,
+ 0x7384, 0x7389, 0x74dc, 0x74e6, 0x7518, 0x751f, 0x7528, 0x7529,
+ 0x7530, 0x7531, 0x7532, 0x7533, 0x758b, 0x767d, 0x76ae, 0x76bf,
+ 0x76ee, 0x77db, 0x77e2, 0x77f3, 0x793a, 0x79be, 0x7a74, 0x7acb,
+ 0x4e1e, 0x4e1f, 0x4e52, 0x4e53, 0x4e69, 0x4e99, 0x4ea4, 0x4ea6,
+ 0x4ea5, 0x4eff, 0x4f09, 0x4f19, 0x4f0a, 0x4f15, 0x4f0d, 0x4f10,
+ 0x4f11, 0x4f0f, 0x4ef2, 0x4ef6, 0x4efb, 0x4ef0, 0x4ef3, 0x4efd,
+ 0x4f01, 0x4f0b, 0x5149, 0x5147, 0x5146, 0x5148, 0x5168, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5171, 0x518d, 0x51b0, 0x5217, 0x5211, 0x5212, 0x520e, 0x5216,
+ 0x52a3, 0x5308, 0x5321, 0x5320, 0x5370, 0x5371, 0x5409, 0x540f,
+ 0x540c, 0x540a, 0x5410, 0x5401, 0x540b, 0x5404, 0x5411, 0x540d,
+ 0x5408, 0x5403, 0x540e, 0x5406, 0x5412, 0x56e0, 0x56de, 0x56dd,
+ 0x5733, 0x5730, 0x5728, 0x572d, 0x572c, 0x572f, 0x5729, 0x5919,
+ 0x591a, 0x5937, 0x5938, 0x5984, 0x5978, 0x5983, 0x597d, 0x5979,
+ 0x5982, 0x5981, 0x5b57, 0x5b58, 0x5b87, 0x5b88, 0x5b85, 0x5b89,
+ 0x5bfa, 0x5c16, 0x5c79, 0x5dde, 0x5e06, 0x5e76, 0x5e74, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5f0f, 0x5f1b, 0x5fd9, 0x5fd6, 0x620e, 0x620c, 0x620d,
+ 0x6210, 0x6263, 0x625b, 0x6258, 0x6536, 0x65e9, 0x65e8, 0x65ec,
+ 0x65ed, 0x66f2, 0x66f3, 0x6709, 0x673d, 0x6734, 0x6731, 0x6735,
+ 0x6b21, 0x6b64, 0x6b7b, 0x6c16, 0x6c5d, 0x6c57, 0x6c59, 0x6c5f,
+ 0x6c60, 0x6c50, 0x6c55, 0x6c61, 0x6c5b, 0x6c4d, 0x6c4e, 0x7070,
+ 0x725f, 0x725d, 0x767e, 0x7af9, 0x7c73, 0x7cf8, 0x7f36, 0x7f8a,
+ 0x7fbd, 0x8001, 0x8003, 0x800c, 0x8012, 0x8033, 0x807f, 0x8089,
+ 0x808b, 0x808c, 0x81e3, 0x81ea, 0x81f3, 0x81fc, 0x820c, 0x821b,
+ 0x821f, 0x826e, 0x8272, 0x827e, 0x866b, 0x8840, 0x884c, 0x8863,
+ 0x897f, 0x9621, 0x4e32, 0x4ea8, 0x4f4d, 0x4f4f, 0x4f47, 0x4f57,
+ 0x4f5e, 0x4f34, 0x4f5b, 0x4f55, 0x4f30, 0x4f50, 0x4f51, 0x4f3d,
+ 0x4f3a, 0x4f38, 0x4f43, 0x4f54, 0x4f3c, 0x4f46, 0x4f63, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4f5c, 0x4f60, 0x4f2f, 0x4f4e, 0x4f36, 0x4f59, 0x4f5d, 0x4f48,
+ 0x4f5a, 0x514c, 0x514b, 0x514d, 0x5175, 0x51b6, 0x51b7, 0x5225,
+ 0x5224, 0x5229, 0x522a, 0x5228, 0x52ab, 0x52a9, 0x52aa, 0x52ac,
+ 0x5323, 0x5373, 0x5375, 0x541d, 0x542d, 0x541e, 0x543e, 0x5426,
+ 0x544e, 0x5427, 0x5446, 0x5443, 0x5433, 0x5448, 0x5442, 0x541b,
+ 0x5429, 0x544a, 0x5439, 0x543b, 0x5438, 0x542e, 0x5435, 0x5436,
+ 0x5420, 0x543c, 0x5440, 0x5431, 0x542b, 0x541f, 0x542c, 0x56ea,
+ 0x56f0, 0x56e4, 0x56eb, 0x574a, 0x5751, 0x5740, 0x574d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5747, 0x574e, 0x573e, 0x5750, 0x574f, 0x573b, 0x58ef,
+ 0x593e, 0x599d, 0x5992, 0x59a8, 0x599e, 0x59a3, 0x5999, 0x5996,
+ 0x598d, 0x59a4, 0x5993, 0x598a, 0x59a5, 0x5b5d, 0x5b5c, 0x5b5a,
+ 0x5b5b, 0x5b8c, 0x5b8b, 0x5b8f, 0x5c2c, 0x5c40, 0x5c41, 0x5c3f,
+ 0x5c3e, 0x5c90, 0x5c91, 0x5c94, 0x5c8c, 0x5deb, 0x5e0c, 0x5e8f,
+ 0x5e87, 0x5e8a, 0x5ef7, 0x5f04, 0x5f1f, 0x5f64, 0x5f62, 0x5f77,
+ 0x5f79, 0x5fd8, 0x5fcc, 0x5fd7, 0x5fcd, 0x5ff1, 0x5feb, 0x5ff8,
+ 0x5fea, 0x6212, 0x6211, 0x6284, 0x6297, 0x6296, 0x6280, 0x6276,
+ 0x6289, 0x626d, 0x628a, 0x627c, 0x627e, 0x6279, 0x6273, 0x6292,
+ 0x626f, 0x6298, 0x626e, 0x6295, 0x6293, 0x6291, 0x6286, 0x6539,
+ 0x653b, 0x6538, 0x65f1, 0x66f4, 0x675f, 0x674e, 0x674f, 0x6750,
+ 0x6751, 0x675c, 0x6756, 0x675e, 0x6749, 0x6746, 0x6760, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6753, 0x6757, 0x6b65, 0x6bcf, 0x6c42, 0x6c5e, 0x6c99, 0x6c81,
+ 0x6c88, 0x6c89, 0x6c85, 0x6c9b, 0x6c6a, 0x6c7a, 0x6c90, 0x6c70,
+ 0x6c8c, 0x6c68, 0x6c96, 0x6c92, 0x6c7d, 0x6c83, 0x6c72, 0x6c7e,
+ 0x6c74, 0x6c86, 0x6c76, 0x6c8d, 0x6c94, 0x6c98, 0x6c82, 0x7076,
+ 0x707c, 0x707d, 0x7078, 0x7262, 0x7261, 0x7260, 0x72c4, 0x72c2,
+ 0x7396, 0x752c, 0x752b, 0x7537, 0x7538, 0x7682, 0x76ef, 0x77e3,
+ 0x79c1, 0x79c0, 0x79bf, 0x7a76, 0x7cfb, 0x7f55, 0x8096, 0x8093,
+ 0x809d, 0x8098, 0x809b, 0x809a, 0x80b2, 0x826f, 0x8292, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x828b, 0x828d, 0x898b, 0x89d2, 0x8a00, 0x8c37, 0x8c46,
+ 0x8c55, 0x8c9d, 0x8d64, 0x8d70, 0x8db3, 0x8eab, 0x8eca, 0x8f9b,
+ 0x8fb0, 0x8fc2, 0x8fc6, 0x8fc5, 0x8fc4, 0x5de1, 0x9091, 0x90a2,
+ 0x90aa, 0x90a6, 0x90a3, 0x9149, 0x91c6, 0x91cc, 0x9632, 0x962e,
+ 0x9631, 0x962a, 0x962c, 0x4e26, 0x4e56, 0x4e73, 0x4e8b, 0x4e9b,
+ 0x4e9e, 0x4eab, 0x4eac, 0x4f6f, 0x4f9d, 0x4f8d, 0x4f73, 0x4f7f,
+ 0x4f6c, 0x4f9b, 0x4f8b, 0x4f86, 0x4f83, 0x4f70, 0x4f75, 0x4f88,
+ 0x4f69, 0x4f7b, 0x4f96, 0x4f7e, 0x4f8f, 0x4f91, 0x4f7a, 0x5154,
+ 0x5152, 0x5155, 0x5169, 0x5177, 0x5176, 0x5178, 0x51bd, 0x51fd,
+ 0x523b, 0x5238, 0x5237, 0x523a, 0x5230, 0x522e, 0x5236, 0x5241,
+ 0x52be, 0x52bb, 0x5352, 0x5354, 0x5353, 0x5351, 0x5366, 0x5377,
+ 0x5378, 0x5379, 0x53d6, 0x53d4, 0x53d7, 0x5473, 0x5475, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5496, 0x5478, 0x5495, 0x5480, 0x547b, 0x5477, 0x5484, 0x5492,
+ 0x5486, 0x547c, 0x5490, 0x5471, 0x5476, 0x548c, 0x549a, 0x5462,
+ 0x5468, 0x548b, 0x547d, 0x548e, 0x56fa, 0x5783, 0x5777, 0x576a,
+ 0x5769, 0x5761, 0x5766, 0x5764, 0x577c, 0x591c, 0x5949, 0x5947,
+ 0x5948, 0x5944, 0x5954, 0x59be, 0x59bb, 0x59d4, 0x59b9, 0x59ae,
+ 0x59d1, 0x59c6, 0x59d0, 0x59cd, 0x59cb, 0x59d3, 0x59ca, 0x59af,
+ 0x59b3, 0x59d2, 0x59c5, 0x5b5f, 0x5b64, 0x5b63, 0x5b97, 0x5b9a,
+ 0x5b98, 0x5b9c, 0x5b99, 0x5b9b, 0x5c1a, 0x5c48, 0x5c45, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5c46, 0x5cb7, 0x5ca1, 0x5cb8, 0x5ca9, 0x5cab, 0x5cb1,
+ 0x5cb3, 0x5e18, 0x5e1a, 0x5e16, 0x5e15, 0x5e1b, 0x5e11, 0x5e78,
+ 0x5e9a, 0x5e97, 0x5e9c, 0x5e95, 0x5e96, 0x5ef6, 0x5f26, 0x5f27,
+ 0x5f29, 0x5f80, 0x5f81, 0x5f7f, 0x5f7c, 0x5fdd, 0x5fe0, 0x5ffd,
+ 0x5ff5, 0x5fff, 0x600f, 0x6014, 0x602f, 0x6035, 0x6016, 0x602a,
+ 0x6015, 0x6021, 0x6027, 0x6029, 0x602b, 0x601b, 0x6216, 0x6215,
+ 0x623f, 0x623e, 0x6240, 0x627f, 0x62c9, 0x62cc, 0x62c4, 0x62bf,
+ 0x62c2, 0x62b9, 0x62d2, 0x62db, 0x62ab, 0x62d3, 0x62d4, 0x62cb,
+ 0x62c8, 0x62a8, 0x62bd, 0x62bc, 0x62d0, 0x62d9, 0x62c7, 0x62cd,
+ 0x62b5, 0x62da, 0x62b1, 0x62d8, 0x62d6, 0x62d7, 0x62c6, 0x62ac,
+ 0x62ce, 0x653e, 0x65a7, 0x65bc, 0x65fa, 0x6614, 0x6613, 0x660c,
+ 0x6606, 0x6602, 0x660e, 0x6600, 0x660f, 0x6615, 0x660a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6607, 0x670d, 0x670b, 0x676d, 0x678b, 0x6795, 0x6771, 0x679c,
+ 0x6773, 0x6777, 0x6787, 0x679d, 0x6797, 0x676f, 0x6770, 0x677f,
+ 0x6789, 0x677e, 0x6790, 0x6775, 0x679a, 0x6793, 0x677c, 0x676a,
+ 0x6772, 0x6b23, 0x6b66, 0x6b67, 0x6b7f, 0x6c13, 0x6c1b, 0x6ce3,
+ 0x6ce8, 0x6cf3, 0x6cb1, 0x6ccc, 0x6ce5, 0x6cb3, 0x6cbd, 0x6cbe,
+ 0x6cbc, 0x6ce2, 0x6cab, 0x6cd5, 0x6cd3, 0x6cb8, 0x6cc4, 0x6cb9,
+ 0x6cc1, 0x6cae, 0x6cd7, 0x6cc5, 0x6cf1, 0x6cbf, 0x6cbb, 0x6ce1,
+ 0x6cdb, 0x6cca, 0x6cac, 0x6cef, 0x6cdc, 0x6cd6, 0x6ce0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7095, 0x708e, 0x7092, 0x708a, 0x7099, 0x722c, 0x722d,
+ 0x7238, 0x7248, 0x7267, 0x7269, 0x72c0, 0x72ce, 0x72d9, 0x72d7,
+ 0x72d0, 0x73a9, 0x73a8, 0x739f, 0x73ab, 0x73a5, 0x753d, 0x759d,
+ 0x7599, 0x759a, 0x7684, 0x76c2, 0x76f2, 0x76f4, 0x77e5, 0x77fd,
+ 0x793e, 0x7940, 0x7941, 0x79c9, 0x79c8, 0x7a7a, 0x7a79, 0x7afa,
+ 0x7cfe, 0x7f54, 0x7f8c, 0x7f8b, 0x8005, 0x80ba, 0x80a5, 0x80a2,
+ 0x80b1, 0x80a1, 0x80ab, 0x80a9, 0x80b4, 0x80aa, 0x80af, 0x81e5,
+ 0x81fe, 0x820d, 0x82b3, 0x829d, 0x8299, 0x82ad, 0x82bd, 0x829f,
+ 0x82b9, 0x82b1, 0x82ac, 0x82a5, 0x82af, 0x82b8, 0x82a3, 0x82b0,
+ 0x82be, 0x82b7, 0x864e, 0x8671, 0x521d, 0x8868, 0x8ecb, 0x8fce,
+ 0x8fd4, 0x8fd1, 0x90b5, 0x90b8, 0x90b1, 0x90b6, 0x91c7, 0x91d1,
+ 0x9577, 0x9580, 0x961c, 0x9640, 0x963f, 0x963b, 0x9644, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9642, 0x96b9, 0x96e8, 0x9752, 0x975e, 0x4e9f, 0x4ead, 0x4eae,
+ 0x4fe1, 0x4fb5, 0x4faf, 0x4fbf, 0x4fe0, 0x4fd1, 0x4fcf, 0x4fdd,
+ 0x4fc3, 0x4fb6, 0x4fd8, 0x4fdf, 0x4fca, 0x4fd7, 0x4fae, 0x4fd0,
+ 0x4fc4, 0x4fc2, 0x4fda, 0x4fce, 0x4fde, 0x4fb7, 0x5157, 0x5192,
+ 0x5191, 0x51a0, 0x524e, 0x5243, 0x524a, 0x524d, 0x524c, 0x524b,
+ 0x5247, 0x52c7, 0x52c9, 0x52c3, 0x52c1, 0x530d, 0x5357, 0x537b,
+ 0x539a, 0x53db, 0x54ac, 0x54c0, 0x54a8, 0x54ce, 0x54c9, 0x54b8,
+ 0x54a6, 0x54b3, 0x54c7, 0x54c2, 0x54bd, 0x54aa, 0x54c1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x54c4, 0x54c8, 0x54af, 0x54ab, 0x54b1, 0x54bb, 0x54a9,
+ 0x54a7, 0x54bf, 0x56ff, 0x5782, 0x578b, 0x57a0, 0x57a3, 0x57a2,
+ 0x57ce, 0x57ae, 0x5793, 0x5955, 0x5951, 0x594f, 0x594e, 0x5950,
+ 0x59dc, 0x59d8, 0x59ff, 0x59e3, 0x59e8, 0x5a03, 0x59e5, 0x59ea,
+ 0x59da, 0x59e6, 0x5a01, 0x59fb, 0x5b69, 0x5ba3, 0x5ba6, 0x5ba4,
+ 0x5ba2, 0x5ba5, 0x5c01, 0x5c4e, 0x5c4f, 0x5c4d, 0x5c4b, 0x5cd9,
+ 0x5cd2, 0x5df7, 0x5e1d, 0x5e25, 0x5e1f, 0x5e7d, 0x5ea0, 0x5ea6,
+ 0x5efa, 0x5f08, 0x5f2d, 0x5f65, 0x5f88, 0x5f85, 0x5f8a, 0x5f8b,
+ 0x5f87, 0x5f8c, 0x5f89, 0x6012, 0x601d, 0x6020, 0x6025, 0x600e,
+ 0x6028, 0x604d, 0x6070, 0x6068, 0x6062, 0x6046, 0x6043, 0x606c,
+ 0x606b, 0x606a, 0x6064, 0x6241, 0x62dc, 0x6316, 0x6309, 0x62fc,
+ 0x62ed, 0x6301, 0x62ee, 0x62fd, 0x6307, 0x62f1, 0x62f7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x62ef, 0x62ec, 0x62fe, 0x62f4, 0x6311, 0x6302, 0x653f, 0x6545,
+ 0x65ab, 0x65bd, 0x65e2, 0x6625, 0x662d, 0x6620, 0x6627, 0x662f,
+ 0x661f, 0x6628, 0x6631, 0x6624, 0x66f7, 0x67ff, 0x67d3, 0x67f1,
+ 0x67d4, 0x67d0, 0x67ec, 0x67b6, 0x67af, 0x67f5, 0x67e9, 0x67ef,
+ 0x67c4, 0x67d1, 0x67b4, 0x67da, 0x67e5, 0x67b8, 0x67cf, 0x67de,
+ 0x67f3, 0x67b0, 0x67d9, 0x67e2, 0x67dd, 0x67d2, 0x6b6a, 0x6b83,
+ 0x6b86, 0x6bb5, 0x6bd2, 0x6bd7, 0x6c1f, 0x6cc9, 0x6d0b, 0x6d32,
+ 0x6d2a, 0x6d41, 0x6d25, 0x6d0c, 0x6d31, 0x6d1e, 0x6d17, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6d3b, 0x6d3d, 0x6d3e, 0x6d36, 0x6d1b, 0x6cf5, 0x6d39,
+ 0x6d27, 0x6d38, 0x6d29, 0x6d2e, 0x6d35, 0x6d0e, 0x6d2b, 0x70ab,
+ 0x70ba, 0x70b3, 0x70ac, 0x70af, 0x70ad, 0x70b8, 0x70ae, 0x70a4,
+ 0x7230, 0x7272, 0x726f, 0x7274, 0x72e9, 0x72e0, 0x72e1, 0x73b7,
+ 0x73ca, 0x73bb, 0x73b2, 0x73cd, 0x73c0, 0x73b3, 0x751a, 0x752d,
+ 0x754f, 0x754c, 0x754e, 0x754b, 0x75ab, 0x75a4, 0x75a5, 0x75a2,
+ 0x75a3, 0x7678, 0x7686, 0x7687, 0x7688, 0x76c8, 0x76c6, 0x76c3,
+ 0x76c5, 0x7701, 0x76f9, 0x76f8, 0x7709, 0x770b, 0x76fe, 0x76fc,
+ 0x7707, 0x77dc, 0x7802, 0x7814, 0x780c, 0x780d, 0x7946, 0x7949,
+ 0x7948, 0x7947, 0x79b9, 0x79ba, 0x79d1, 0x79d2, 0x79cb, 0x7a7f,
+ 0x7a81, 0x7aff, 0x7afd, 0x7c7d, 0x7d02, 0x7d05, 0x7d00, 0x7d09,
+ 0x7d07, 0x7d04, 0x7d06, 0x7f38, 0x7f8e, 0x7fbf, 0x8004, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8010, 0x800d, 0x8011, 0x8036, 0x80d6, 0x80e5, 0x80da, 0x80c3,
+ 0x80c4, 0x80cc, 0x80e1, 0x80db, 0x80ce, 0x80de, 0x80e4, 0x80dd,
+ 0x81f4, 0x8222, 0x82e7, 0x8303, 0x8305, 0x82e3, 0x82db, 0x82e6,
+ 0x8304, 0x82e5, 0x8302, 0x8309, 0x82d2, 0x82d7, 0x82f1, 0x8301,
+ 0x82dc, 0x82d4, 0x82d1, 0x82de, 0x82d3, 0x82df, 0x82ef, 0x8306,
+ 0x8650, 0x8679, 0x867b, 0x867a, 0x884d, 0x886b, 0x8981, 0x89d4,
+ 0x8a08, 0x8a02, 0x8a03, 0x8c9e, 0x8ca0, 0x8d74, 0x8d73, 0x8db4,
+ 0x8ecd, 0x8ecc, 0x8ff0, 0x8fe6, 0x8fe2, 0x8fea, 0x8fe5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8fed, 0x8feb, 0x8fe4, 0x8fe8, 0x90ca, 0x90ce, 0x90c1,
+ 0x90c3, 0x914b, 0x914a, 0x91cd, 0x9582, 0x9650, 0x964b, 0x964c,
+ 0x964d, 0x9762, 0x9769, 0x97cb, 0x97ed, 0x97f3, 0x9801, 0x98a8,
+ 0x98db, 0x98df, 0x9996, 0x9999, 0x4e58, 0x4eb3, 0x500c, 0x500d,
+ 0x5023, 0x4fef, 0x5026, 0x5025, 0x4ff8, 0x5029, 0x5016, 0x5006,
+ 0x503c, 0x501f, 0x501a, 0x5012, 0x5011, 0x4ffa, 0x5000, 0x5014,
+ 0x5028, 0x4ff1, 0x5021, 0x500b, 0x5019, 0x5018, 0x4ff3, 0x4fee,
+ 0x502d, 0x502a, 0x4ffe, 0x502b, 0x5009, 0x517c, 0x51a4, 0x51a5,
+ 0x51a2, 0x51cd, 0x51cc, 0x51c6, 0x51cb, 0x5256, 0x525c, 0x5254,
+ 0x525b, 0x525d, 0x532a, 0x537f, 0x539f, 0x539d, 0x53df, 0x54e8,
+ 0x5510, 0x5501, 0x5537, 0x54fc, 0x54e5, 0x54f2, 0x5506, 0x54fa,
+ 0x5514, 0x54e9, 0x54ed, 0x54e1, 0x5509, 0x54ee, 0x54ea, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x54e6, 0x5527, 0x5507, 0x54fd, 0x550f, 0x5703, 0x5704, 0x57c2,
+ 0x57d4, 0x57cb, 0x57c3, 0x5809, 0x590f, 0x5957, 0x5958, 0x595a,
+ 0x5a11, 0x5a18, 0x5a1c, 0x5a1f, 0x5a1b, 0x5a13, 0x59ec, 0x5a20,
+ 0x5a23, 0x5a29, 0x5a25, 0x5a0c, 0x5a09, 0x5b6b, 0x5c58, 0x5bb0,
+ 0x5bb3, 0x5bb6, 0x5bb4, 0x5bae, 0x5bb5, 0x5bb9, 0x5bb8, 0x5c04,
+ 0x5c51, 0x5c55, 0x5c50, 0x5ced, 0x5cfd, 0x5cfb, 0x5cea, 0x5ce8,
+ 0x5cf0, 0x5cf6, 0x5d01, 0x5cf4, 0x5dee, 0x5e2d, 0x5e2b, 0x5eab,
+ 0x5ead, 0x5ea7, 0x5f31, 0x5f92, 0x5f91, 0x5f90, 0x6059, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6063, 0x6065, 0x6050, 0x6055, 0x606d, 0x6069, 0x606f,
+ 0x6084, 0x609f, 0x609a, 0x608d, 0x6094, 0x608c, 0x6085, 0x6096,
+ 0x6247, 0x62f3, 0x6308, 0x62ff, 0x634e, 0x633e, 0x632f, 0x6355,
+ 0x6342, 0x6346, 0x634f, 0x6349, 0x633a, 0x6350, 0x633d, 0x632a,
+ 0x632b, 0x6328, 0x634d, 0x634c, 0x6548, 0x6549, 0x6599, 0x65c1,
+ 0x65c5, 0x6642, 0x6649, 0x664f, 0x6643, 0x6652, 0x664c, 0x6645,
+ 0x6641, 0x66f8, 0x6714, 0x6715, 0x6717, 0x6821, 0x6838, 0x6848,
+ 0x6846, 0x6853, 0x6839, 0x6842, 0x6854, 0x6829, 0x68b3, 0x6817,
+ 0x684c, 0x6851, 0x683d, 0x67f4, 0x6850, 0x6840, 0x683c, 0x6843,
+ 0x682a, 0x6845, 0x6813, 0x6818, 0x6841, 0x6b8a, 0x6b89, 0x6bb7,
+ 0x6c23, 0x6c27, 0x6c28, 0x6c26, 0x6c24, 0x6cf0, 0x6d6a, 0x6d95,
+ 0x6d88, 0x6d87, 0x6d66, 0x6d78, 0x6d77, 0x6d59, 0x6d93, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6d6c, 0x6d89, 0x6d6e, 0x6d5a, 0x6d74, 0x6d69, 0x6d8c, 0x6d8a,
+ 0x6d79, 0x6d85, 0x6d65, 0x6d94, 0x70ca, 0x70d8, 0x70e4, 0x70d9,
+ 0x70c8, 0x70cf, 0x7239, 0x7279, 0x72fc, 0x72f9, 0x72fd, 0x72f8,
+ 0x72f7, 0x7386, 0x73ed, 0x7409, 0x73ee, 0x73e0, 0x73ea, 0x73de,
+ 0x7554, 0x755d, 0x755c, 0x755a, 0x7559, 0x75be, 0x75c5, 0x75c7,
+ 0x75b2, 0x75b3, 0x75bd, 0x75bc, 0x75b9, 0x75c2, 0x75b8, 0x768b,
+ 0x76b0, 0x76ca, 0x76cd, 0x76ce, 0x7729, 0x771f, 0x7720, 0x7728,
+ 0x77e9, 0x7830, 0x7827, 0x7838, 0x781d, 0x7834, 0x7837, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7825, 0x782d, 0x7820, 0x781f, 0x7832, 0x7955, 0x7950,
+ 0x7960, 0x795f, 0x7956, 0x795e, 0x795d, 0x7957, 0x795a, 0x79e4,
+ 0x79e3, 0x79e7, 0x79df, 0x79e6, 0x79e9, 0x79d8, 0x7a84, 0x7a88,
+ 0x7ad9, 0x7b06, 0x7b11, 0x7c89, 0x7d21, 0x7d17, 0x7d0b, 0x7d0a,
+ 0x7d20, 0x7d22, 0x7d14, 0x7d10, 0x7d15, 0x7d1a, 0x7d1c, 0x7d0d,
+ 0x7d19, 0x7d1b, 0x7f3a, 0x7f5f, 0x7f94, 0x7fc5, 0x7fc1, 0x8006,
+ 0x8018, 0x8015, 0x8019, 0x8017, 0x803d, 0x803f, 0x80f1, 0x8102,
+ 0x80f0, 0x8105, 0x80ed, 0x80f4, 0x8106, 0x80f8, 0x80f3, 0x8108,
+ 0x80fd, 0x810a, 0x80fc, 0x80ef, 0x81ed, 0x81ec, 0x8200, 0x8210,
+ 0x822a, 0x822b, 0x8228, 0x822c, 0x82bb, 0x832b, 0x8352, 0x8354,
+ 0x834a, 0x8338, 0x8350, 0x8349, 0x8335, 0x8334, 0x834f, 0x8332,
+ 0x8339, 0x8336, 0x8317, 0x8340, 0x8331, 0x8328, 0x8343, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8654, 0x868a, 0x86aa, 0x8693, 0x86a4, 0x86a9, 0x868c, 0x86a3,
+ 0x869c, 0x8870, 0x8877, 0x8881, 0x8882, 0x887d, 0x8879, 0x8a18,
+ 0x8a10, 0x8a0e, 0x8a0c, 0x8a15, 0x8a0a, 0x8a17, 0x8a13, 0x8a16,
+ 0x8a0f, 0x8a11, 0x8c48, 0x8c7a, 0x8c79, 0x8ca1, 0x8ca2, 0x8d77,
+ 0x8eac, 0x8ed2, 0x8ed4, 0x8ecf, 0x8fb1, 0x9001, 0x9006, 0x8ff7,
+ 0x9000, 0x8ffa, 0x8ff4, 0x9003, 0x8ffd, 0x9005, 0x8ff8, 0x9095,
+ 0x90e1, 0x90dd, 0x90e2, 0x9152, 0x914d, 0x914c, 0x91d8, 0x91dd,
+ 0x91d7, 0x91dc, 0x91d9, 0x9583, 0x9662, 0x9663, 0x9661, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x965b, 0x965d, 0x9664, 0x9658, 0x965e, 0x96bb, 0x98e2,
+ 0x99ac, 0x9aa8, 0x9ad8, 0x9b25, 0x9b32, 0x9b3c, 0x4e7e, 0x507a,
+ 0x507d, 0x505c, 0x5047, 0x5043, 0x504c, 0x505a, 0x5049, 0x5065,
+ 0x5076, 0x504e, 0x5055, 0x5075, 0x5074, 0x5077, 0x504f, 0x500f,
+ 0x506f, 0x506d, 0x515c, 0x5195, 0x51f0, 0x526a, 0x526f, 0x52d2,
+ 0x52d9, 0x52d8, 0x52d5, 0x5310, 0x530f, 0x5319, 0x533f, 0x5340,
+ 0x533e, 0x53c3, 0x66fc, 0x5546, 0x556a, 0x5566, 0x5544, 0x555e,
+ 0x5561, 0x5543, 0x554a, 0x5531, 0x5556, 0x554f, 0x5555, 0x552f,
+ 0x5564, 0x5538, 0x552e, 0x555c, 0x552c, 0x5563, 0x5533, 0x5541,
+ 0x5557, 0x5708, 0x570b, 0x5709, 0x57df, 0x5805, 0x580a, 0x5806,
+ 0x57e0, 0x57e4, 0x57fa, 0x5802, 0x5835, 0x57f7, 0x57f9, 0x5920,
+ 0x5962, 0x5a36, 0x5a41, 0x5a49, 0x5a66, 0x5a6a, 0x5a40, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5a3c, 0x5a62, 0x5a5a, 0x5a46, 0x5a4a, 0x5b70, 0x5bc7, 0x5bc5,
+ 0x5bc4, 0x5bc2, 0x5bbf, 0x5bc6, 0x5c09, 0x5c08, 0x5c07, 0x5c60,
+ 0x5c5c, 0x5c5d, 0x5d07, 0x5d06, 0x5d0e, 0x5d1b, 0x5d16, 0x5d22,
+ 0x5d11, 0x5d29, 0x5d14, 0x5d19, 0x5d24, 0x5d27, 0x5d17, 0x5de2,
+ 0x5e38, 0x5e36, 0x5e33, 0x5e37, 0x5eb7, 0x5eb8, 0x5eb6, 0x5eb5,
+ 0x5ebe, 0x5f35, 0x5f37, 0x5f57, 0x5f6c, 0x5f69, 0x5f6b, 0x5f97,
+ 0x5f99, 0x5f9e, 0x5f98, 0x5fa1, 0x5fa0, 0x5f9c, 0x607f, 0x60a3,
+ 0x6089, 0x60a0, 0x60a8, 0x60cb, 0x60b4, 0x60e6, 0x60bd, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x60c5, 0x60bb, 0x60b5, 0x60dc, 0x60bc, 0x60d8, 0x60d5,
+ 0x60c6, 0x60df, 0x60b8, 0x60da, 0x60c7, 0x621a, 0x621b, 0x6248,
+ 0x63a0, 0x63a7, 0x6372, 0x6396, 0x63a2, 0x63a5, 0x6377, 0x6367,
+ 0x6398, 0x63aa, 0x6371, 0x63a9, 0x6389, 0x6383, 0x639b, 0x636b,
+ 0x63a8, 0x6384, 0x6388, 0x6399, 0x63a1, 0x63ac, 0x6392, 0x638f,
+ 0x6380, 0x637b, 0x6369, 0x6368, 0x637a, 0x655d, 0x6556, 0x6551,
+ 0x6559, 0x6557, 0x555f, 0x654f, 0x6558, 0x6555, 0x6554, 0x659c,
+ 0x659b, 0x65ac, 0x65cf, 0x65cb, 0x65cc, 0x65ce, 0x665d, 0x665a,
+ 0x6664, 0x6668, 0x6666, 0x665e, 0x66f9, 0x52d7, 0x671b, 0x6881,
+ 0x68af, 0x68a2, 0x6893, 0x68b5, 0x687f, 0x6876, 0x68b1, 0x68a7,
+ 0x6897, 0x68b0, 0x6883, 0x68c4, 0x68ad, 0x6886, 0x6885, 0x6894,
+ 0x689d, 0x68a8, 0x689f, 0x68a1, 0x6882, 0x6b32, 0x6bba, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6beb, 0x6bec, 0x6c2b, 0x6d8e, 0x6dbc, 0x6df3, 0x6dd9, 0x6db2,
+ 0x6de1, 0x6dcc, 0x6de4, 0x6dfb, 0x6dfa, 0x6e05, 0x6dc7, 0x6dcb,
+ 0x6daf, 0x6dd1, 0x6dae, 0x6dde, 0x6df9, 0x6db8, 0x6df7, 0x6df5,
+ 0x6dc5, 0x6dd2, 0x6e1a, 0x6db5, 0x6dda, 0x6deb, 0x6dd8, 0x6dea,
+ 0x6df1, 0x6dee, 0x6de8, 0x6dc6, 0x6dc4, 0x6daa, 0x6dec, 0x6dbf,
+ 0x6de6, 0x70f9, 0x7109, 0x710a, 0x70fd, 0x70ef, 0x723d, 0x727d,
+ 0x7281, 0x731c, 0x731b, 0x7316, 0x7313, 0x7319, 0x7387, 0x7405,
+ 0x740a, 0x7403, 0x7406, 0x73fe, 0x740d, 0x74e0, 0x74f6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x74f7, 0x751c, 0x7522, 0x7565, 0x7566, 0x7562, 0x7570,
+ 0x758f, 0x75d4, 0x75d5, 0x75b5, 0x75ca, 0x75cd, 0x768e, 0x76d4,
+ 0x76d2, 0x76db, 0x7737, 0x773e, 0x773c, 0x7736, 0x7738, 0x773a,
+ 0x786b, 0x7843, 0x784e, 0x7965, 0x7968, 0x796d, 0x79fb, 0x7a92,
+ 0x7a95, 0x7b20, 0x7b28, 0x7b1b, 0x7b2c, 0x7b26, 0x7b19, 0x7b1e,
+ 0x7b2e, 0x7c92, 0x7c97, 0x7c95, 0x7d46, 0x7d43, 0x7d71, 0x7d2e,
+ 0x7d39, 0x7d3c, 0x7d40, 0x7d30, 0x7d33, 0x7d44, 0x7d2f, 0x7d42,
+ 0x7d32, 0x7d31, 0x7f3d, 0x7f9e, 0x7f9a, 0x7fcc, 0x7fce, 0x7fd2,
+ 0x801c, 0x804a, 0x8046, 0x812f, 0x8116, 0x8123, 0x812b, 0x8129,
+ 0x8130, 0x8124, 0x8202, 0x8235, 0x8237, 0x8236, 0x8239, 0x838e,
+ 0x839e, 0x8398, 0x8378, 0x83a2, 0x8396, 0x83bd, 0x83ab, 0x8392,
+ 0x838a, 0x8393, 0x8389, 0x83a0, 0x8377, 0x837b, 0x837c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8386, 0x83a7, 0x8655, 0x5f6a, 0x86c7, 0x86c0, 0x86b6, 0x86c4,
+ 0x86b5, 0x86c6, 0x86cb, 0x86b1, 0x86af, 0x86c9, 0x8853, 0x889e,
+ 0x8888, 0x88ab, 0x8892, 0x8896, 0x888d, 0x888b, 0x8993, 0x898f,
+ 0x8a2a, 0x8a1d, 0x8a23, 0x8a25, 0x8a31, 0x8a2d, 0x8a1f, 0x8a1b,
+ 0x8a22, 0x8c49, 0x8c5a, 0x8ca9, 0x8cac, 0x8cab, 0x8ca8, 0x8caa,
+ 0x8ca7, 0x8d67, 0x8d66, 0x8dbe, 0x8dba, 0x8edb, 0x8edf, 0x9019,
+ 0x900d, 0x901a, 0x9017, 0x9023, 0x901f, 0x901d, 0x9010, 0x9015,
+ 0x901e, 0x9020, 0x900f, 0x9022, 0x9016, 0x901b, 0x9014, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x90e8, 0x90ed, 0x90fd, 0x9157, 0x91ce, 0x91f5, 0x91e6,
+ 0x91e3, 0x91e7, 0x91ed, 0x91e9, 0x9589, 0x966a, 0x9675, 0x9673,
+ 0x9678, 0x9670, 0x9674, 0x9676, 0x9677, 0x966c, 0x96c0, 0x96ea,
+ 0x96e9, 0x7ae0, 0x7adf, 0x9802, 0x9803, 0x9b5a, 0x9ce5, 0x9e75,
+ 0x9e7f, 0x9ea5, 0x9ebb, 0x50a2, 0x508d, 0x5085, 0x5099, 0x5091,
+ 0x5080, 0x5096, 0x5098, 0x509a, 0x6700, 0x51f1, 0x5272, 0x5274,
+ 0x5275, 0x5269, 0x52de, 0x52dd, 0x52db, 0x535a, 0x53a5, 0x557b,
+ 0x5580, 0x55a7, 0x557c, 0x558a, 0x559d, 0x5598, 0x5582, 0x559c,
+ 0x55aa, 0x5594, 0x5587, 0x558b, 0x5583, 0x55b3, 0x55ae, 0x559f,
+ 0x553e, 0x55b2, 0x559a, 0x55bb, 0x55ac, 0x55b1, 0x557e, 0x5589,
+ 0x55ab, 0x5599, 0x570d, 0x582f, 0x582a, 0x5834, 0x5824, 0x5830,
+ 0x5831, 0x5821, 0x581d, 0x5820, 0x58f9, 0x58fa, 0x5960, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5a77, 0x5a9a, 0x5a7f, 0x5a92, 0x5a9b, 0x5aa7, 0x5b73, 0x5b71,
+ 0x5bd2, 0x5bcc, 0x5bd3, 0x5bd0, 0x5c0a, 0x5c0b, 0x5c31, 0x5d4c,
+ 0x5d50, 0x5d34, 0x5d47, 0x5dfd, 0x5e45, 0x5e3d, 0x5e40, 0x5e43,
+ 0x5e7e, 0x5eca, 0x5ec1, 0x5ec2, 0x5ec4, 0x5f3c, 0x5f6d, 0x5fa9,
+ 0x5faa, 0x5fa8, 0x60d1, 0x60e1, 0x60b2, 0x60b6, 0x60e0, 0x611c,
+ 0x6123, 0x60fa, 0x6115, 0x60f0, 0x60fb, 0x60f4, 0x6168, 0x60f1,
+ 0x610e, 0x60f6, 0x6109, 0x6100, 0x6112, 0x621f, 0x6249, 0x63a3,
+ 0x638c, 0x63cf, 0x63c0, 0x63e9, 0x63c9, 0x63c6, 0x63cd, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x63d2, 0x63e3, 0x63d0, 0x63e1, 0x63d6, 0x63ed, 0x63ee,
+ 0x6376, 0x63f4, 0x63ea, 0x63db, 0x6452, 0x63da, 0x63f9, 0x655e,
+ 0x6566, 0x6562, 0x6563, 0x6591, 0x6590, 0x65af, 0x666e, 0x6670,
+ 0x6674, 0x6676, 0x666f, 0x6691, 0x667a, 0x667e, 0x6677, 0x66fe,
+ 0x66ff, 0x671f, 0x671d, 0x68fa, 0x68d5, 0x68e0, 0x68d8, 0x68d7,
+ 0x6905, 0x68df, 0x68f5, 0x68ee, 0x68e7, 0x68f9, 0x68d2, 0x68f2,
+ 0x68e3, 0x68cb, 0x68cd, 0x690d, 0x6912, 0x690e, 0x68c9, 0x68da,
+ 0x696e, 0x68fb, 0x6b3e, 0x6b3a, 0x6b3d, 0x6b98, 0x6b96, 0x6bbc,
+ 0x6bef, 0x6c2e, 0x6c2f, 0x6c2c, 0x6e2f, 0x6e38, 0x6e54, 0x6e21,
+ 0x6e32, 0x6e67, 0x6e4a, 0x6e20, 0x6e25, 0x6e23, 0x6e1b, 0x6e5b,
+ 0x6e58, 0x6e24, 0x6e56, 0x6e6e, 0x6e2d, 0x6e26, 0x6e6f, 0x6e34,
+ 0x6e4d, 0x6e3a, 0x6e2c, 0x6e43, 0x6e1d, 0x6e3e, 0x6ecb, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6e89, 0x6e19, 0x6e4e, 0x6e63, 0x6e44, 0x6e72, 0x6e69, 0x6e5f,
+ 0x7119, 0x711a, 0x7126, 0x7130, 0x7121, 0x7136, 0x716e, 0x711c,
+ 0x724c, 0x7284, 0x7280, 0x7336, 0x7325, 0x7334, 0x7329, 0x743a,
+ 0x742a, 0x7433, 0x7422, 0x7425, 0x7435, 0x7436, 0x7434, 0x742f,
+ 0x741b, 0x7426, 0x7428, 0x7525, 0x7526, 0x756b, 0x756a, 0x75e2,
+ 0x75db, 0x75e3, 0x75d9, 0x75d8, 0x75de, 0x75e0, 0x767b, 0x767c,
+ 0x7696, 0x7693, 0x76b4, 0x76dc, 0x774f, 0x77ed, 0x785d, 0x786c,
+ 0x786f, 0x7a0d, 0x7a08, 0x7a0b, 0x7a05, 0x7a00, 0x7a98, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7a97, 0x7a96, 0x7ae5, 0x7ae3, 0x7b49, 0x7b56, 0x7b46,
+ 0x7b50, 0x7b52, 0x7b54, 0x7b4d, 0x7b4b, 0x7b4f, 0x7b51, 0x7c9f,
+ 0x7ca5, 0x7d5e, 0x7d50, 0x7d68, 0x7d55, 0x7d2b, 0x7d6e, 0x7d72,
+ 0x7d61, 0x7d66, 0x7d62, 0x7d70, 0x7d73, 0x5584, 0x7fd4, 0x7fd5,
+ 0x800b, 0x8052, 0x8085, 0x8155, 0x8154, 0x814b, 0x8151, 0x814e,
+ 0x8139, 0x8146, 0x813e, 0x814c, 0x8153, 0x8174, 0x8212, 0x821c,
+ 0x83e9, 0x8403, 0x83f8, 0x840d, 0x83e0, 0x83c5, 0x840b, 0x83c1,
+ 0x83ef, 0x83f1, 0x83f4, 0x8457, 0x840a, 0x83f0, 0x840c, 0x83cc,
+ 0x83fd, 0x83f2, 0x83ca, 0x8438, 0x840e, 0x8404, 0x83dc, 0x8407,
+ 0x83d4, 0x83df, 0x865b, 0x86df, 0x86d9, 0x86ed, 0x86d4, 0x86db,
+ 0x86e4, 0x86d0, 0x86de, 0x8857, 0x88c1, 0x88c2, 0x88b1, 0x8983,
+ 0x8996, 0x8a3b, 0x8a60, 0x8a55, 0x8a5e, 0x8a3c, 0x8a41, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8a54, 0x8a5b, 0x8a50, 0x8a46, 0x8a34, 0x8a3a, 0x8a36, 0x8a56,
+ 0x8c61, 0x8c82, 0x8caf, 0x8cbc, 0x8cb3, 0x8cbd, 0x8cc1, 0x8cbb,
+ 0x8cc0, 0x8cb4, 0x8cb7, 0x8cb6, 0x8cbf, 0x8cb8, 0x8d8a, 0x8d85,
+ 0x8d81, 0x8dce, 0x8ddd, 0x8dcb, 0x8dda, 0x8dd1, 0x8dcc, 0x8ddb,
+ 0x8dc6, 0x8efb, 0x8ef8, 0x8efc, 0x8f9c, 0x902e, 0x9035, 0x9031,
+ 0x9038, 0x9032, 0x9036, 0x9102, 0x90f5, 0x9109, 0x90fe, 0x9163,
+ 0x9165, 0x91cf, 0x9214, 0x9215, 0x9223, 0x9209, 0x921e, 0x920d,
+ 0x9210, 0x9207, 0x9211, 0x9594, 0x958f, 0x958b, 0x9591, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9593, 0x9592, 0x958e, 0x968a, 0x968e, 0x968b, 0x967d,
+ 0x9685, 0x9686, 0x968d, 0x9672, 0x9684, 0x96c1, 0x96c5, 0x96c4,
+ 0x96c6, 0x96c7, 0x96ef, 0x96f2, 0x97cc, 0x9805, 0x9806, 0x9808,
+ 0x98e7, 0x98ea, 0x98ef, 0x98e9, 0x98f2, 0x98ed, 0x99ae, 0x99ad,
+ 0x9ec3, 0x9ecd, 0x9ed1, 0x4e82, 0x50ad, 0x50b5, 0x50b2, 0x50b3,
+ 0x50c5, 0x50be, 0x50ac, 0x50b7, 0x50bb, 0x50af, 0x50c7, 0x527f,
+ 0x5277, 0x527d, 0x52df, 0x52e6, 0x52e4, 0x52e2, 0x52e3, 0x532f,
+ 0x55df, 0x55e8, 0x55d3, 0x55e6, 0x55ce, 0x55dc, 0x55c7, 0x55d1,
+ 0x55e3, 0x55e4, 0x55ef, 0x55da, 0x55e1, 0x55c5, 0x55c6, 0x55e5,
+ 0x55c9, 0x5712, 0x5713, 0x585e, 0x5851, 0x5858, 0x5857, 0x585a,
+ 0x5854, 0x586b, 0x584c, 0x586d, 0x584a, 0x5862, 0x5852, 0x584b,
+ 0x5967, 0x5ac1, 0x5ac9, 0x5acc, 0x5abe, 0x5abd, 0x5abc, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5ab3, 0x5ac2, 0x5ab2, 0x5d69, 0x5d6f, 0x5e4c, 0x5e79, 0x5ec9,
+ 0x5ec8, 0x5f12, 0x5f59, 0x5fac, 0x5fae, 0x611a, 0x610f, 0x6148,
+ 0x611f, 0x60f3, 0x611b, 0x60f9, 0x6101, 0x6108, 0x614e, 0x614c,
+ 0x6144, 0x614d, 0x613e, 0x6134, 0x6127, 0x610d, 0x6106, 0x6137,
+ 0x6221, 0x6222, 0x6413, 0x643e, 0x641e, 0x642a, 0x642d, 0x643d,
+ 0x642c, 0x640f, 0x641c, 0x6414, 0x640d, 0x6436, 0x6416, 0x6417,
+ 0x6406, 0x656c, 0x659f, 0x65b0, 0x6697, 0x6689, 0x6687, 0x6688,
+ 0x6696, 0x6684, 0x6698, 0x668d, 0x6703, 0x6994, 0x696d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x695a, 0x6977, 0x6960, 0x6954, 0x6975, 0x6930, 0x6982,
+ 0x694a, 0x6968, 0x696b, 0x695e, 0x6953, 0x6979, 0x6986, 0x695d,
+ 0x6963, 0x695b, 0x6b47, 0x6b72, 0x6bc0, 0x6bbf, 0x6bd3, 0x6bfd,
+ 0x6ea2, 0x6eaf, 0x6ed3, 0x6eb6, 0x6ec2, 0x6e90, 0x6e9d, 0x6ec7,
+ 0x6ec5, 0x6ea5, 0x6e98, 0x6ebc, 0x6eba, 0x6eab, 0x6ed1, 0x6e96,
+ 0x6e9c, 0x6ec4, 0x6ed4, 0x6eaa, 0x6ea7, 0x6eb4, 0x714e, 0x7159,
+ 0x7169, 0x7164, 0x7149, 0x7167, 0x715c, 0x716c, 0x7166, 0x714c,
+ 0x7165, 0x715e, 0x7146, 0x7168, 0x7156, 0x723a, 0x7252, 0x7337,
+ 0x7345, 0x733f, 0x733e, 0x746f, 0x745a, 0x7455, 0x745f, 0x745e,
+ 0x7441, 0x743f, 0x7459, 0x745b, 0x745c, 0x7576, 0x7578, 0x7600,
+ 0x75f0, 0x7601, 0x75f2, 0x75f1, 0x75fa, 0x75ff, 0x75f4, 0x75f3,
+ 0x76de, 0x76df, 0x775b, 0x776b, 0x7766, 0x775e, 0x7763, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7779, 0x776a, 0x776c, 0x775c, 0x7765, 0x7768, 0x7762, 0x77ee,
+ 0x788e, 0x78b0, 0x7897, 0x7898, 0x788c, 0x7889, 0x787c, 0x7891,
+ 0x7893, 0x787f, 0x797a, 0x797f, 0x7981, 0x842c, 0x79bd, 0x7a1c,
+ 0x7a1a, 0x7a20, 0x7a14, 0x7a1f, 0x7a1e, 0x7a9f, 0x7aa0, 0x7b77,
+ 0x7bc0, 0x7b60, 0x7b6e, 0x7b67, 0x7cb1, 0x7cb3, 0x7cb5, 0x7d93,
+ 0x7d79, 0x7d91, 0x7d81, 0x7d8f, 0x7d5b, 0x7f6e, 0x7f69, 0x7f6a,
+ 0x7f72, 0x7fa9, 0x7fa8, 0x7fa4, 0x8056, 0x8058, 0x8086, 0x8084,
+ 0x8171, 0x8170, 0x8178, 0x8165, 0x816e, 0x8173, 0x816b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8179, 0x817a, 0x8166, 0x8205, 0x8247, 0x8482, 0x8477,
+ 0x843d, 0x8431, 0x8475, 0x8466, 0x846b, 0x8449, 0x846c, 0x845b,
+ 0x843c, 0x8435, 0x8461, 0x8463, 0x8469, 0x846d, 0x8446, 0x865e,
+ 0x865c, 0x865f, 0x86f9, 0x8713, 0x8708, 0x8707, 0x8700, 0x86fe,
+ 0x86fb, 0x8702, 0x8703, 0x8706, 0x870a, 0x8859, 0x88df, 0x88d4,
+ 0x88d9, 0x88dc, 0x88d8, 0x88dd, 0x88e1, 0x88ca, 0x88d5, 0x88d2,
+ 0x899c, 0x89e3, 0x8a6b, 0x8a72, 0x8a73, 0x8a66, 0x8a69, 0x8a70,
+ 0x8a87, 0x8a7c, 0x8a63, 0x8aa0, 0x8a71, 0x8a85, 0x8a6d, 0x8a62,
+ 0x8a6e, 0x8a6c, 0x8a79, 0x8a7b, 0x8a3e, 0x8a68, 0x8c62, 0x8c8a,
+ 0x8c89, 0x8cca, 0x8cc7, 0x8cc8, 0x8cc4, 0x8cb2, 0x8cc3, 0x8cc2,
+ 0x8cc5, 0x8de1, 0x8ddf, 0x8de8, 0x8def, 0x8df3, 0x8dfa, 0x8dea,
+ 0x8de4, 0x8de6, 0x8eb2, 0x8f03, 0x8f09, 0x8efe, 0x8f0a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8f9f, 0x8fb2, 0x904b, 0x904a, 0x9053, 0x9042, 0x9054, 0x903c,
+ 0x9055, 0x9050, 0x9047, 0x904f, 0x904e, 0x904d, 0x9051, 0x903e,
+ 0x9041, 0x9112, 0x9117, 0x916c, 0x916a, 0x9169, 0x91c9, 0x9237,
+ 0x9257, 0x9238, 0x923d, 0x9240, 0x923e, 0x925b, 0x924b, 0x9264,
+ 0x9251, 0x9234, 0x9249, 0x924d, 0x9245, 0x9239, 0x923f, 0x925a,
+ 0x9598, 0x9698, 0x9694, 0x9695, 0x96cd, 0x96cb, 0x96c9, 0x96ca,
+ 0x96f7, 0x96fb, 0x96f9, 0x96f6, 0x9756, 0x9774, 0x9776, 0x9810,
+ 0x9811, 0x9813, 0x980a, 0x9812, 0x980c, 0x98fc, 0x98f4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x98fd, 0x98fe, 0x99b3, 0x99b1, 0x99b4, 0x9ae1, 0x9ce9,
+ 0x9e82, 0x9f0e, 0x9f13, 0x9f20, 0x50e7, 0x50ee, 0x50e5, 0x50d6,
+ 0x50ed, 0x50da, 0x50d5, 0x50cf, 0x50d1, 0x50f1, 0x50ce, 0x50e9,
+ 0x5162, 0x51f3, 0x5283, 0x5282, 0x5331, 0x53ad, 0x55fe, 0x5600,
+ 0x561b, 0x5617, 0x55fd, 0x5614, 0x5606, 0x5609, 0x560d, 0x560e,
+ 0x55f7, 0x5616, 0x561f, 0x5608, 0x5610, 0x55f6, 0x5718, 0x5716,
+ 0x5875, 0x587e, 0x5883, 0x5893, 0x588a, 0x5879, 0x5885, 0x587d,
+ 0x58fd, 0x5925, 0x5922, 0x5924, 0x596a, 0x5969, 0x5ae1, 0x5ae6,
+ 0x5ae9, 0x5ad7, 0x5ad6, 0x5ad8, 0x5ae3, 0x5b75, 0x5bde, 0x5be7,
+ 0x5be1, 0x5be5, 0x5be6, 0x5be8, 0x5be2, 0x5be4, 0x5bdf, 0x5c0d,
+ 0x5c62, 0x5d84, 0x5d87, 0x5e5b, 0x5e63, 0x5e55, 0x5e57, 0x5e54,
+ 0x5ed3, 0x5ed6, 0x5f0a, 0x5f46, 0x5f70, 0x5fb9, 0x6147, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x613f, 0x614b, 0x6177, 0x6162, 0x6163, 0x615f, 0x615a, 0x6158,
+ 0x6175, 0x622a, 0x6487, 0x6458, 0x6454, 0x64a4, 0x6478, 0x645f,
+ 0x647a, 0x6451, 0x6467, 0x6434, 0x646d, 0x647b, 0x6572, 0x65a1,
+ 0x65d7, 0x65d6, 0x66a2, 0x66a8, 0x669d, 0x699c, 0x69a8, 0x6995,
+ 0x69c1, 0x69ae, 0x69d3, 0x69cb, 0x699b, 0x69b7, 0x69bb, 0x69ab,
+ 0x69b4, 0x69d0, 0x69cd, 0x69ad, 0x69cc, 0x69a6, 0x69c3, 0x69a3,
+ 0x6b49, 0x6b4c, 0x6c33, 0x6f33, 0x6f14, 0x6efe, 0x6f13, 0x6ef4,
+ 0x6f29, 0x6f3e, 0x6f20, 0x6f2c, 0x6f0f, 0x6f02, 0x6f22, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6eff, 0x6eef, 0x6f06, 0x6f31, 0x6f38, 0x6f32, 0x6f23,
+ 0x6f15, 0x6f2b, 0x6f2f, 0x6f88, 0x6f2a, 0x6eec, 0x6f01, 0x6ef2,
+ 0x6ecc, 0x6ef7, 0x7194, 0x7199, 0x717d, 0x718a, 0x7184, 0x7192,
+ 0x723e, 0x7292, 0x7296, 0x7344, 0x7350, 0x7464, 0x7463, 0x746a,
+ 0x7470, 0x746d, 0x7504, 0x7591, 0x7627, 0x760d, 0x760b, 0x7609,
+ 0x7613, 0x76e1, 0x76e3, 0x7784, 0x777d, 0x777f, 0x7761, 0x78c1,
+ 0x789f, 0x78a7, 0x78b3, 0x78a9, 0x78a3, 0x798e, 0x798f, 0x798d,
+ 0x7a2e, 0x7a31, 0x7aaa, 0x7aa9, 0x7aed, 0x7aef, 0x7ba1, 0x7b95,
+ 0x7b8b, 0x7b75, 0x7b97, 0x7b9d, 0x7b94, 0x7b8f, 0x7bb8, 0x7b87,
+ 0x7b84, 0x7cb9, 0x7cbd, 0x7cbe, 0x7dbb, 0x7db0, 0x7d9c, 0x7dbd,
+ 0x7dbe, 0x7da0, 0x7dca, 0x7db4, 0x7db2, 0x7db1, 0x7dba, 0x7da2,
+ 0x7dbf, 0x7db5, 0x7db8, 0x7dad, 0x7dd2, 0x7dc7, 0x7dac, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7f70, 0x7fe0, 0x7fe1, 0x7fdf, 0x805e, 0x805a, 0x8087, 0x8150,
+ 0x8180, 0x818f, 0x8188, 0x818a, 0x817f, 0x8182, 0x81e7, 0x81fa,
+ 0x8207, 0x8214, 0x821e, 0x824b, 0x84c9, 0x84bf, 0x84c6, 0x84c4,
+ 0x8499, 0x849e, 0x84b2, 0x849c, 0x84cb, 0x84b8, 0x84c0, 0x84d3,
+ 0x8490, 0x84bc, 0x84d1, 0x84ca, 0x873f, 0x871c, 0x873b, 0x8722,
+ 0x8725, 0x8734, 0x8718, 0x8755, 0x8737, 0x8729, 0x88f3, 0x8902,
+ 0x88f4, 0x88f9, 0x88f8, 0x88fd, 0x88e8, 0x891a, 0x88ef, 0x8aa6,
+ 0x8a8c, 0x8a9e, 0x8aa3, 0x8a8d, 0x8aa1, 0x8a93, 0x8aa4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8aaa, 0x8aa5, 0x8aa8, 0x8a98, 0x8a91, 0x8a9a, 0x8aa7,
+ 0x8c6a, 0x8c8d, 0x8c8c, 0x8cd3, 0x8cd1, 0x8cd2, 0x8d6b, 0x8d99,
+ 0x8d95, 0x8dfc, 0x8f14, 0x8f12, 0x8f15, 0x8f13, 0x8fa3, 0x9060,
+ 0x9058, 0x905c, 0x9063, 0x9059, 0x905e, 0x9062, 0x905d, 0x905b,
+ 0x9119, 0x9118, 0x911e, 0x9175, 0x9178, 0x9177, 0x9174, 0x9278,
+ 0x9280, 0x9285, 0x9298, 0x9296, 0x927b, 0x9293, 0x929c, 0x92a8,
+ 0x927c, 0x9291, 0x95a1, 0x95a8, 0x95a9, 0x95a3, 0x95a5, 0x95a4,
+ 0x9699, 0x969c, 0x969b, 0x96cc, 0x96d2, 0x9700, 0x977c, 0x9785,
+ 0x97f6, 0x9817, 0x9818, 0x98af, 0x98b1, 0x9903, 0x9905, 0x990c,
+ 0x9909, 0x99c1, 0x9aaf, 0x9ab0, 0x9ae6, 0x9b41, 0x9b42, 0x9cf4,
+ 0x9cf6, 0x9cf3, 0x9ebc, 0x9f3b, 0x9f4a, 0x5104, 0x5100, 0x50fb,
+ 0x50f5, 0x50f9, 0x5102, 0x5108, 0x5109, 0x5105, 0x51dc, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5287, 0x5288, 0x5289, 0x528d, 0x528a, 0x52f0, 0x53b2, 0x562e,
+ 0x563b, 0x5639, 0x5632, 0x563f, 0x5634, 0x5629, 0x5653, 0x564e,
+ 0x5657, 0x5674, 0x5636, 0x562f, 0x5630, 0x5880, 0x589f, 0x589e,
+ 0x58b3, 0x589c, 0x58ae, 0x58a9, 0x58a6, 0x596d, 0x5b09, 0x5afb,
+ 0x5b0b, 0x5af5, 0x5b0c, 0x5b08, 0x5bee, 0x5bec, 0x5be9, 0x5beb,
+ 0x5c64, 0x5c65, 0x5d9d, 0x5d94, 0x5e62, 0x5e5f, 0x5e61, 0x5ee2,
+ 0x5eda, 0x5edf, 0x5edd, 0x5ee3, 0x5ee0, 0x5f48, 0x5f71, 0x5fb7,
+ 0x5fb5, 0x6176, 0x6167, 0x616e, 0x615d, 0x6155, 0x6182, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x617c, 0x6170, 0x616b, 0x617e, 0x61a7, 0x6190, 0x61ab,
+ 0x618e, 0x61ac, 0x619a, 0x61a4, 0x6194, 0x61ae, 0x622e, 0x6469,
+ 0x646f, 0x6479, 0x649e, 0x64b2, 0x6488, 0x6490, 0x64b0, 0x64a5,
+ 0x6493, 0x6495, 0x64a9, 0x6492, 0x64ae, 0x64ad, 0x64ab, 0x649a,
+ 0x64ac, 0x6499, 0x64a2, 0x64b3, 0x6575, 0x6577, 0x6578, 0x66ae,
+ 0x66ab, 0x66b4, 0x66b1, 0x6a23, 0x6a1f, 0x69e8, 0x6a01, 0x6a1e,
+ 0x6a19, 0x69fd, 0x6a21, 0x6a13, 0x6a0a, 0x69f3, 0x6a02, 0x6a05,
+ 0x69ed, 0x6a11, 0x6b50, 0x6b4e, 0x6ba4, 0x6bc5, 0x6bc6, 0x6f3f,
+ 0x6f7c, 0x6f84, 0x6f51, 0x6f66, 0x6f54, 0x6f86, 0x6f6d, 0x6f5b,
+ 0x6f78, 0x6f6e, 0x6f8e, 0x6f7a, 0x6f70, 0x6f64, 0x6f97, 0x6f58,
+ 0x6ed5, 0x6f6f, 0x6f60, 0x6f5f, 0x719f, 0x71ac, 0x71b1, 0x71a8,
+ 0x7256, 0x729b, 0x734e, 0x7357, 0x7469, 0x748b, 0x7483, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x747e, 0x7480, 0x757f, 0x7620, 0x7629, 0x761f, 0x7624, 0x7626,
+ 0x7621, 0x7622, 0x769a, 0x76ba, 0x76e4, 0x778e, 0x7787, 0x778c,
+ 0x7791, 0x778b, 0x78cb, 0x78c5, 0x78ba, 0x78ca, 0x78be, 0x78d5,
+ 0x78bc, 0x78d0, 0x7a3f, 0x7a3c, 0x7a40, 0x7a3d, 0x7a37, 0x7a3b,
+ 0x7aaf, 0x7aae, 0x7bad, 0x7bb1, 0x7bc4, 0x7bb4, 0x7bc6, 0x7bc7,
+ 0x7bc1, 0x7ba0, 0x7bcc, 0x7cca, 0x7de0, 0x7df4, 0x7def, 0x7dfb,
+ 0x7dd8, 0x7dec, 0x7ddd, 0x7de8, 0x7de3, 0x7dda, 0x7dde, 0x7de9,
+ 0x7d9e, 0x7dd9, 0x7df2, 0x7df9, 0x7f75, 0x7f77, 0x7faf, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7fe9, 0x8026, 0x819b, 0x819c, 0x819d, 0x81a0, 0x819a,
+ 0x8198, 0x8517, 0x853d, 0x851a, 0x84ee, 0x852c, 0x852d, 0x8513,
+ 0x8511, 0x8523, 0x8521, 0x8514, 0x84ec, 0x8525, 0x84ff, 0x8506,
+ 0x8782, 0x8774, 0x8776, 0x8760, 0x8766, 0x8778, 0x8768, 0x8759,
+ 0x8757, 0x874c, 0x8753, 0x885b, 0x885d, 0x8910, 0x8907, 0x8912,
+ 0x8913, 0x8915, 0x890a, 0x8abc, 0x8ad2, 0x8ac7, 0x8ac4, 0x8a95,
+ 0x8acb, 0x8af8, 0x8ab2, 0x8ac9, 0x8ac2, 0x8abf, 0x8ab0, 0x8ad6,
+ 0x8acd, 0x8ab6, 0x8ab9, 0x8adb, 0x8c4c, 0x8c4e, 0x8c6c, 0x8ce0,
+ 0x8cde, 0x8ce6, 0x8ce4, 0x8cec, 0x8ced, 0x8ce2, 0x8ce3, 0x8cdc,
+ 0x8cea, 0x8ce1, 0x8d6d, 0x8d9f, 0x8da3, 0x8e2b, 0x8e10, 0x8e1d,
+ 0x8e22, 0x8e0f, 0x8e29, 0x8e1f, 0x8e21, 0x8e1e, 0x8eba, 0x8f1d,
+ 0x8f1b, 0x8f1f, 0x8f29, 0x8f26, 0x8f2a, 0x8f1c, 0x8f1e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8f25, 0x9069, 0x906e, 0x9068, 0x906d, 0x9077, 0x9130, 0x912d,
+ 0x9127, 0x9131, 0x9187, 0x9189, 0x918b, 0x9183, 0x92c5, 0x92bb,
+ 0x92b7, 0x92ea, 0x92ac, 0x92e4, 0x92c1, 0x92b3, 0x92bc, 0x92d2,
+ 0x92c7, 0x92f0, 0x92b2, 0x95ad, 0x95b1, 0x9704, 0x9706, 0x9707,
+ 0x9709, 0x9760, 0x978d, 0x978b, 0x978f, 0x9821, 0x982b, 0x981c,
+ 0x98b3, 0x990a, 0x9913, 0x9912, 0x9918, 0x99dd, 0x99d0, 0x99df,
+ 0x99db, 0x99d1, 0x99d5, 0x99d2, 0x99d9, 0x9ab7, 0x9aee, 0x9aef,
+ 0x9b27, 0x9b45, 0x9b44, 0x9b77, 0x9b6f, 0x9d06, 0x9d09, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9d03, 0x9ea9, 0x9ebe, 0x9ece, 0x58a8, 0x9f52, 0x5112,
+ 0x5118, 0x5114, 0x5110, 0x5115, 0x5180, 0x51aa, 0x51dd, 0x5291,
+ 0x5293, 0x52f3, 0x5659, 0x566b, 0x5679, 0x5669, 0x5664, 0x5678,
+ 0x566a, 0x5668, 0x5665, 0x5671, 0x566f, 0x566c, 0x5662, 0x5676,
+ 0x58c1, 0x58be, 0x58c7, 0x58c5, 0x596e, 0x5b1d, 0x5b34, 0x5b78,
+ 0x5bf0, 0x5c0e, 0x5f4a, 0x61b2, 0x6191, 0x61a9, 0x618a, 0x61cd,
+ 0x61b6, 0x61be, 0x61ca, 0x61c8, 0x6230, 0x64c5, 0x64c1, 0x64cb,
+ 0x64bb, 0x64bc, 0x64da, 0x64c4, 0x64c7, 0x64c2, 0x64cd, 0x64bf,
+ 0x64d2, 0x64d4, 0x64be, 0x6574, 0x66c6, 0x66c9, 0x66b9, 0x66c4,
+ 0x66c7, 0x66b8, 0x6a3d, 0x6a38, 0x6a3a, 0x6a59, 0x6a6b, 0x6a58,
+ 0x6a39, 0x6a44, 0x6a62, 0x6a61, 0x6a4b, 0x6a47, 0x6a35, 0x6a5f,
+ 0x6a48, 0x6b59, 0x6b77, 0x6c05, 0x6fc2, 0x6fb1, 0x6fa1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6fc3, 0x6fa4, 0x6fc1, 0x6fa7, 0x6fb3, 0x6fc0, 0x6fb9, 0x6fb6,
+ 0x6fa6, 0x6fa0, 0x6fb4, 0x71be, 0x71c9, 0x71d0, 0x71d2, 0x71c8,
+ 0x71d5, 0x71b9, 0x71ce, 0x71d9, 0x71dc, 0x71c3, 0x71c4, 0x7368,
+ 0x749c, 0x74a3, 0x7498, 0x749f, 0x749e, 0x74e2, 0x750c, 0x750d,
+ 0x7634, 0x7638, 0x763a, 0x76e7, 0x76e5, 0x77a0, 0x779e, 0x779f,
+ 0x77a5, 0x78e8, 0x78da, 0x78ec, 0x78e7, 0x79a6, 0x7a4d, 0x7a4e,
+ 0x7a46, 0x7a4c, 0x7a4b, 0x7aba, 0x7bd9, 0x7c11, 0x7bc9, 0x7be4,
+ 0x7bdb, 0x7be1, 0x7be9, 0x7be6, 0x7cd5, 0x7cd6, 0x7e0a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7e11, 0x7e08, 0x7e1b, 0x7e23, 0x7e1e, 0x7e1d, 0x7e09,
+ 0x7e10, 0x7f79, 0x7fb2, 0x7ff0, 0x7ff1, 0x7fee, 0x8028, 0x81b3,
+ 0x81a9, 0x81a8, 0x81fb, 0x8208, 0x8258, 0x8259, 0x854a, 0x8559,
+ 0x8548, 0x8568, 0x8569, 0x8543, 0x8549, 0x856d, 0x856a, 0x855e,
+ 0x8783, 0x879f, 0x879e, 0x87a2, 0x878d, 0x8861, 0x892a, 0x8932,
+ 0x8925, 0x892b, 0x8921, 0x89aa, 0x89a6, 0x8ae6, 0x8afa, 0x8aeb,
+ 0x8af1, 0x8b00, 0x8adc, 0x8ae7, 0x8aee, 0x8afe, 0x8b01, 0x8b02,
+ 0x8af7, 0x8aed, 0x8af3, 0x8af6, 0x8afc, 0x8c6b, 0x8c6d, 0x8c93,
+ 0x8cf4, 0x8e44, 0x8e31, 0x8e34, 0x8e42, 0x8e39, 0x8e35, 0x8f3b,
+ 0x8f2f, 0x8f38, 0x8f33, 0x8fa8, 0x8fa6, 0x9075, 0x9074, 0x9078,
+ 0x9072, 0x907c, 0x907a, 0x9134, 0x9192, 0x9320, 0x9336, 0x92f8,
+ 0x9333, 0x932f, 0x9322, 0x92fc, 0x932b, 0x9304, 0x931a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9310, 0x9326, 0x9321, 0x9315, 0x932e, 0x9319, 0x95bb, 0x96a7,
+ 0x96a8, 0x96aa, 0x96d5, 0x970e, 0x9711, 0x9716, 0x970d, 0x9713,
+ 0x970f, 0x975b, 0x975c, 0x9766, 0x9798, 0x9830, 0x9838, 0x983b,
+ 0x9837, 0x982d, 0x9839, 0x9824, 0x9910, 0x9928, 0x991e, 0x991b,
+ 0x9921, 0x991a, 0x99ed, 0x99e2, 0x99f1, 0x9ab8, 0x9abc, 0x9afb,
+ 0x9aed, 0x9b28, 0x9b91, 0x9d15, 0x9d23, 0x9d26, 0x9d28, 0x9d12,
+ 0x9d1b, 0x9ed8, 0x9ed4, 0x9f8d, 0x9f9c, 0x512a, 0x511f, 0x5121,
+ 0x5132, 0x52f5, 0x568e, 0x5680, 0x5690, 0x5685, 0x5687, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x568f, 0x58d5, 0x58d3, 0x58d1, 0x58ce, 0x5b30, 0x5b2a,
+ 0x5b24, 0x5b7a, 0x5c37, 0x5c68, 0x5dbc, 0x5dba, 0x5dbd, 0x5db8,
+ 0x5e6b, 0x5f4c, 0x5fbd, 0x61c9, 0x61c2, 0x61c7, 0x61e6, 0x61cb,
+ 0x6232, 0x6234, 0x64ce, 0x64ca, 0x64d8, 0x64e0, 0x64f0, 0x64e6,
+ 0x64ec, 0x64f1, 0x64e2, 0x64ed, 0x6582, 0x6583, 0x66d9, 0x66d6,
+ 0x6a80, 0x6a94, 0x6a84, 0x6aa2, 0x6a9c, 0x6adb, 0x6aa3, 0x6a7e,
+ 0x6a97, 0x6a90, 0x6aa0, 0x6b5c, 0x6bae, 0x6bda, 0x6c08, 0x6fd8,
+ 0x6ff1, 0x6fdf, 0x6fe0, 0x6fdb, 0x6fe4, 0x6feb, 0x6fef, 0x6f80,
+ 0x6fec, 0x6fe1, 0x6fe9, 0x6fd5, 0x6fee, 0x6ff0, 0x71e7, 0x71df,
+ 0x71ee, 0x71e6, 0x71e5, 0x71ed, 0x71ec, 0x71f4, 0x71e0, 0x7235,
+ 0x7246, 0x7370, 0x7372, 0x74a9, 0x74b0, 0x74a6, 0x74a8, 0x7646,
+ 0x7642, 0x764c, 0x76ea, 0x77b3, 0x77aa, 0x77b0, 0x77ac, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x77a7, 0x77ad, 0x77ef, 0x78f7, 0x78fa, 0x78f4, 0x78ef, 0x7901,
+ 0x79a7, 0x79aa, 0x7a57, 0x7abf, 0x7c07, 0x7c0d, 0x7bfe, 0x7bf7,
+ 0x7c0c, 0x7be0, 0x7ce0, 0x7cdc, 0x7cde, 0x7ce2, 0x7cdf, 0x7cd9,
+ 0x7cdd, 0x7e2e, 0x7e3e, 0x7e46, 0x7e37, 0x7e32, 0x7e43, 0x7e2b,
+ 0x7e3d, 0x7e31, 0x7e45, 0x7e41, 0x7e34, 0x7e39, 0x7e48, 0x7e35,
+ 0x7e3f, 0x7e2f, 0x7f44, 0x7ff3, 0x7ffc, 0x8071, 0x8072, 0x8070,
+ 0x806f, 0x8073, 0x81c6, 0x81c3, 0x81ba, 0x81c2, 0x81c0, 0x81bf,
+ 0x81bd, 0x81c9, 0x81be, 0x81e8, 0x8209, 0x8271, 0x85aa, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8584, 0x857e, 0x859c, 0x8591, 0x8594, 0x85af, 0x859b,
+ 0x8587, 0x85a8, 0x858a, 0x8667, 0x87c0, 0x87d1, 0x87b3, 0x87d2,
+ 0x87c6, 0x87ab, 0x87bb, 0x87ba, 0x87c8, 0x87cb, 0x893b, 0x8936,
+ 0x8944, 0x8938, 0x893d, 0x89ac, 0x8b0e, 0x8b17, 0x8b19, 0x8b1b,
+ 0x8b0a, 0x8b20, 0x8b1d, 0x8b04, 0x8b10, 0x8c41, 0x8c3f, 0x8c73,
+ 0x8cfa, 0x8cfd, 0x8cfc, 0x8cf8, 0x8cfb, 0x8da8, 0x8e49, 0x8e4b,
+ 0x8e48, 0x8e4a, 0x8f44, 0x8f3e, 0x8f42, 0x8f45, 0x8f3f, 0x907f,
+ 0x907d, 0x9084, 0x9081, 0x9082, 0x9080, 0x9139, 0x91a3, 0x919e,
+ 0x919c, 0x934d, 0x9382, 0x9328, 0x9375, 0x934a, 0x9365, 0x934b,
+ 0x9318, 0x937e, 0x936c, 0x935b, 0x9370, 0x935a, 0x9354, 0x95ca,
+ 0x95cb, 0x95cc, 0x95c8, 0x95c6, 0x96b1, 0x96b8, 0x96d6, 0x971c,
+ 0x971e, 0x97a0, 0x97d3, 0x9846, 0x98b6, 0x9935, 0x9a01, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x99ff, 0x9bae, 0x9bab, 0x9baa, 0x9bad, 0x9d3b, 0x9d3f, 0x9e8b,
+ 0x9ecf, 0x9ede, 0x9edc, 0x9edd, 0x9edb, 0x9f3e, 0x9f4b, 0x53e2,
+ 0x5695, 0x56ae, 0x58d9, 0x58d8, 0x5b38, 0x5f5d, 0x61e3, 0x6233,
+ 0x64f4, 0x64f2, 0x64fe, 0x6506, 0x64fa, 0x64fb, 0x64f7, 0x65b7,
+ 0x66dc, 0x6726, 0x6ab3, 0x6aac, 0x6ac3, 0x6abb, 0x6ab8, 0x6ac2,
+ 0x6aae, 0x6aaf, 0x6b5f, 0x6b78, 0x6baf, 0x7009, 0x700b, 0x6ffe,
+ 0x7006, 0x6ffa, 0x7011, 0x700f, 0x71fb, 0x71fc, 0x71fe, 0x71f8,
+ 0x7377, 0x7375, 0x74a7, 0x74bf, 0x7515, 0x7656, 0x7658, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7652, 0x77bd, 0x77bf, 0x77bb, 0x77bc, 0x790e, 0x79ae,
+ 0x7a61, 0x7a62, 0x7a60, 0x7ac4, 0x7ac5, 0x7c2b, 0x7c27, 0x7c2a,
+ 0x7c1e, 0x7c23, 0x7c21, 0x7ce7, 0x7e54, 0x7e55, 0x7e5e, 0x7e5a,
+ 0x7e61, 0x7e52, 0x7e59, 0x7f48, 0x7ff9, 0x7ffb, 0x8077, 0x8076,
+ 0x81cd, 0x81cf, 0x820a, 0x85cf, 0x85a9, 0x85cd, 0x85d0, 0x85c9,
+ 0x85b0, 0x85ba, 0x85b9, 0x85a6, 0x87ef, 0x87ec, 0x87f2, 0x87e0,
+ 0x8986, 0x89b2, 0x89f4, 0x8b28, 0x8b39, 0x8b2c, 0x8b2b, 0x8c50,
+ 0x8d05, 0x8e59, 0x8e63, 0x8e66, 0x8e64, 0x8e5f, 0x8e55, 0x8ec0,
+ 0x8f49, 0x8f4d, 0x9087, 0x9083, 0x9088, 0x91ab, 0x91ac, 0x91d0,
+ 0x9394, 0x938a, 0x9396, 0x93a2, 0x93b3, 0x93ae, 0x93ac, 0x93b0,
+ 0x9398, 0x939a, 0x9397, 0x95d4, 0x95d6, 0x95d0, 0x95d5, 0x96e2,
+ 0x96dc, 0x96d9, 0x96db, 0x96de, 0x9724, 0x97a3, 0x97a6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x97ad, 0x97f9, 0x984d, 0x984f, 0x984c, 0x984e, 0x9853, 0x98ba,
+ 0x993e, 0x993f, 0x993d, 0x992e, 0x99a5, 0x9a0e, 0x9ac1, 0x9b03,
+ 0x9b06, 0x9b4f, 0x9b4e, 0x9b4d, 0x9bca, 0x9bc9, 0x9bfd, 0x9bc8,
+ 0x9bc0, 0x9d51, 0x9d5d, 0x9d60, 0x9ee0, 0x9f15, 0x9f2c, 0x5133,
+ 0x56a5, 0x58de, 0x58df, 0x58e2, 0x5bf5, 0x9f90, 0x5eec, 0x61f2,
+ 0x61f7, 0x61f6, 0x61f5, 0x6500, 0x650f, 0x66e0, 0x66dd, 0x6ae5,
+ 0x6add, 0x6ada, 0x6ad3, 0x701b, 0x701f, 0x7028, 0x701a, 0x701d,
+ 0x7015, 0x7018, 0x7206, 0x720d, 0x7258, 0x72a2, 0x7378, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x737a, 0x74bd, 0x74ca, 0x74e3, 0x7587, 0x7586, 0x765f,
+ 0x7661, 0x77c7, 0x7919, 0x79b1, 0x7a6b, 0x7a69, 0x7c3e, 0x7c3f,
+ 0x7c38, 0x7c3d, 0x7c37, 0x7c40, 0x7e6b, 0x7e6d, 0x7e79, 0x7e69,
+ 0x7e6a, 0x7f85, 0x7e73, 0x7fb6, 0x7fb9, 0x7fb8, 0x81d8, 0x85e9,
+ 0x85dd, 0x85ea, 0x85d5, 0x85e4, 0x85e5, 0x85f7, 0x87fb, 0x8805,
+ 0x880d, 0x87f9, 0x87fe, 0x8960, 0x895f, 0x8956, 0x895e, 0x8b41,
+ 0x8b5c, 0x8b58, 0x8b49, 0x8b5a, 0x8b4e, 0x8b4f, 0x8b46, 0x8b59,
+ 0x8d08, 0x8d0a, 0x8e7c, 0x8e72, 0x8e87, 0x8e76, 0x8e6c, 0x8e7a,
+ 0x8e74, 0x8f54, 0x8f4e, 0x8fad, 0x908a, 0x908b, 0x91b1, 0x91ae,
+ 0x93e1, 0x93d1, 0x93df, 0x93c3, 0x93c8, 0x93dc, 0x93dd, 0x93d6,
+ 0x93e2, 0x93cd, 0x93d8, 0x93e4, 0x93d7, 0x93e8, 0x95dc, 0x96b4,
+ 0x96e3, 0x972a, 0x9727, 0x9761, 0x97dc, 0x97fb, 0x985e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9858, 0x985b, 0x98bc, 0x9945, 0x9949, 0x9a16, 0x9a19, 0x9b0d,
+ 0x9be8, 0x9be7, 0x9bd6, 0x9bdb, 0x9d89, 0x9d61, 0x9d72, 0x9d6a,
+ 0x9d6c, 0x9e92, 0x9e97, 0x9e93, 0x9eb4, 0x52f8, 0x56a8, 0x56b7,
+ 0x56b6, 0x56b4, 0x56bc, 0x58e4, 0x5b40, 0x5b43, 0x5b7d, 0x5bf6,
+ 0x5dc9, 0x61f8, 0x61fa, 0x6518, 0x6514, 0x6519, 0x66e6, 0x6727,
+ 0x6aec, 0x703e, 0x7030, 0x7032, 0x7210, 0x737b, 0x74cf, 0x7662,
+ 0x7665, 0x7926, 0x792a, 0x792c, 0x792b, 0x7ac7, 0x7af6, 0x7c4c,
+ 0x7c43, 0x7c4d, 0x7cef, 0x7cf0, 0x8fae, 0x7e7d, 0x7e7c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7e82, 0x7f4c, 0x8000, 0x81da, 0x8266, 0x85fb, 0x85f9,
+ 0x8611, 0x85fa, 0x8606, 0x860b, 0x8607, 0x860a, 0x8814, 0x8815,
+ 0x8964, 0x89ba, 0x89f8, 0x8b70, 0x8b6c, 0x8b66, 0x8b6f, 0x8b5f,
+ 0x8b6b, 0x8d0f, 0x8d0d, 0x8e89, 0x8e81, 0x8e85, 0x8e82, 0x91b4,
+ 0x91cb, 0x9418, 0x9403, 0x93fd, 0x95e1, 0x9730, 0x98c4, 0x9952,
+ 0x9951, 0x99a8, 0x9a2b, 0x9a30, 0x9a37, 0x9a35, 0x9c13, 0x9c0d,
+ 0x9e79, 0x9eb5, 0x9ee8, 0x9f2f, 0x9f5f, 0x9f63, 0x9f61, 0x5137,
+ 0x5138, 0x56c1, 0x56c0, 0x56c2, 0x5914, 0x5c6c, 0x5dcd, 0x61fc,
+ 0x61fe, 0x651d, 0x651c, 0x6595, 0x66e9, 0x6afb, 0x6b04, 0x6afa,
+ 0x6bb2, 0x704c, 0x721b, 0x72a7, 0x74d6, 0x74d4, 0x7669, 0x77d3,
+ 0x7c50, 0x7e8f, 0x7e8c, 0x7fbc, 0x8617, 0x862d, 0x861a, 0x8823,
+ 0x8822, 0x8821, 0x881f, 0x896a, 0x896c, 0x89bd, 0x8b74, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8b77, 0x8b7d, 0x8d13, 0x8e8a, 0x8e8d, 0x8e8b, 0x8f5f, 0x8faf,
+ 0x91ba, 0x942e, 0x9433, 0x9435, 0x943a, 0x9438, 0x9432, 0x942b,
+ 0x95e2, 0x9738, 0x9739, 0x9732, 0x97ff, 0x9867, 0x9865, 0x9957,
+ 0x9a45, 0x9a43, 0x9a40, 0x9a3e, 0x9acf, 0x9b54, 0x9b51, 0x9c2d,
+ 0x9c25, 0x9daf, 0x9db4, 0x9dc2, 0x9db8, 0x9e9d, 0x9eef, 0x9f19,
+ 0x9f5c, 0x9f66, 0x9f67, 0x513c, 0x513b, 0x56c8, 0x56ca, 0x56c9,
+ 0x5b7f, 0x5dd4, 0x5dd2, 0x5f4e, 0x61ff, 0x6524, 0x6b0a, 0x6b61,
+ 0x7051, 0x7058, 0x7380, 0x74e4, 0x758a, 0x766e, 0x766c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x79b3, 0x7c60, 0x7c5f, 0x807e, 0x807d, 0x81df, 0x8972,
+ 0x896f, 0x89fc, 0x8b80, 0x8d16, 0x8d17, 0x8e91, 0x8e93, 0x8f61,
+ 0x9148, 0x9444, 0x9451, 0x9452, 0x973d, 0x973e, 0x97c3, 0x97c1,
+ 0x986b, 0x9955, 0x9a55, 0x9a4d, 0x9ad2, 0x9b1a, 0x9c49, 0x9c31,
+ 0x9c3e, 0x9c3b, 0x9dd3, 0x9dd7, 0x9f34, 0x9f6c, 0x9f6a, 0x9f94,
+ 0x56cc, 0x5dd6, 0x6200, 0x6523, 0x652b, 0x652a, 0x66ec, 0x6b10,
+ 0x74da, 0x7aca, 0x7c64, 0x7c63, 0x7c65, 0x7e93, 0x7e96, 0x7e94,
+ 0x81e2, 0x8638, 0x863f, 0x8831, 0x8b8a, 0x9090, 0x908f, 0x9463,
+ 0x9460, 0x9464, 0x9768, 0x986f, 0x995c, 0x9a5a, 0x9a5b, 0x9a57,
+ 0x9ad3, 0x9ad4, 0x9ad1, 0x9c54, 0x9c57, 0x9c56, 0x9de5, 0x9e9f,
+ 0x9ef4, 0x56d1, 0x58e9, 0x652c, 0x705e, 0x7671, 0x7672, 0x77d7,
+ 0x7f50, 0x7f88, 0x8836, 0x8839, 0x8862, 0x8b93, 0x8b92, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8b96, 0x8277, 0x8d1b, 0x91c0, 0x946a, 0x9742, 0x9748, 0x9744,
+ 0x97c6, 0x9870, 0x9a5f, 0x9b22, 0x9b58, 0x9c5f, 0x9df9, 0x9dfa,
+ 0x9e7c, 0x9e7d, 0x9f07, 0x9f77, 0x9f72, 0x5ef3, 0x6b16, 0x7063,
+ 0x7c6c, 0x7c6e, 0x883b, 0x89c0, 0x8ea1, 0x91c1, 0x9472, 0x9470,
+ 0x9871, 0x995e, 0x9ad6, 0x9b23, 0x9ecc, 0x7064, 0x77da, 0x8b9a,
+ 0x9477, 0x97c9, 0x9a62, 0x9a65, 0x7e9c, 0x8b9c, 0x8eaa, 0x91c5,
+ 0x947d, 0x947e, 0x947c, 0x9c77, 0x9c78, 0x9ef7, 0x8c54, 0x947f,
+ 0x9e1a, 0x7228, 0x9a6a, 0x9b31, 0x9e1b, 0x9e1e, 0x7c72, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466,
+ 0x2467, 0x2468, 0x2469, 0x2474, 0x2475, 0x2476, 0x2477, 0x2478,
+ 0x2479, 0x247a, 0x247b, 0x247c, 0x247d, 0x2170, 0x2171, 0x2172,
+ 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x4e36,
+ 0x4e3f, 0x4e85, 0x4ea0, 0x5182, 0x5196, 0x51ab, 0x52f9, 0x5338,
+ 0x5369, 0x53b6, 0x590a, 0x5b80, 0x5ddb, 0x2f33, 0x5e7f, 0xf6df,
+ 0x5f50, 0x5f61, 0x6534, 0xf6e3, 0x7592, 0xf6e5, 0x8fb5, 0xf6e7,
+ 0x00a8, 0x02c6, 0x30fd, 0x30fe, 0x309d, 0x309e, 0xf6ee, 0xf6ef,
+ 0x3005, 0x3006, 0x3007, 0x30fc, 0xff3b, 0xff3d, 0x273d, 0x3041,
+ 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049,
+ 0x304a, 0x304b, 0x304c, 0x304d, 0x304e, 0x304f, 0x3050, 0x3051,
+ 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057, 0x3058, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3059, 0x305a, 0x305b, 0x305c, 0x305d, 0x305e, 0x305f, 0x3060,
+ 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067, 0x3068,
+ 0x3069, 0x306a, 0x306b, 0x306c, 0x306d, 0x306e, 0x306f, 0x3070,
+ 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077, 0x3078,
+ 0x3079, 0x307a, 0x307b, 0x307c, 0x307d, 0x307e, 0x307f, 0x3080,
+ 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086, 0x3087, 0x3088,
+ 0x3089, 0x308a, 0x308b, 0x308c, 0x308d, 0x308e, 0x308f, 0x3090,
+ 0x3091, 0x3092, 0x3093, 0x30a1, 0x30a2, 0x30a3, 0x30a4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x30a5, 0x30a6, 0x30a7, 0x30a8, 0x30a9, 0x30aa, 0x30ab,
+ 0x30ac, 0x30ad, 0x30ae, 0x30af, 0x30b0, 0x30b1, 0x30b2, 0x30b3,
+ 0x30b4, 0x30b5, 0x30b6, 0x30b7, 0x30b8, 0x30b9, 0x30ba, 0x30bb,
+ 0x30bc, 0x30bd, 0x30be, 0x30bf, 0x30c0, 0x30c1, 0x30c2, 0x30c3,
+ 0x30c4, 0x30c5, 0x30c6, 0x30c7, 0x30c8, 0x30c9, 0x30ca, 0x30cb,
+ 0x30cc, 0x30cd, 0x30ce, 0x30cf, 0x30d0, 0x30d1, 0x30d2, 0x30d3,
+ 0x30d4, 0x30d5, 0x30d6, 0x30d7, 0x30d8, 0x30d9, 0x30da, 0x30db,
+ 0x30dc, 0x30dd, 0x30de, 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e3,
+ 0x30e4, 0x30e5, 0x30e6, 0x30e7, 0x30e8, 0x30e9, 0x30ea, 0x30eb,
+ 0x30ec, 0x30ed, 0x30ee, 0x30ef, 0x30f0, 0x30f1, 0x30f2, 0x30f3,
+ 0x30f4, 0x30f5, 0x30f6, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414,
+ 0x0415, 0x0401, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, 0x0420, 0x0421, 0x0422,
+ 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a,
+ 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, 0x0430, 0x0431, 0x0432,
+ 0x0433, 0x0434, 0x0435, 0x0451, 0x0436, 0x0437, 0x0438, 0x0439,
+ 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, 0x0440, 0x0441,
+ 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449,
+ 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, 0x21e7, 0x21b8,
+ 0x21b9, 0xf7e5, 0xf7e6, 0x4e5a, 0xf7e8, 0x5202, 0xf7ea, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf7eb, 0x5188, 0xf7ed, 0xf7ee, 0xf7ef, 0xf7f0, 0xf7f1,
+ 0xf7f2, 0xf7f3, 0xf7f4, 0xf7f5, 0xf7f6, 0xf7f7, 0xf7f8, 0xf7f9,
+ 0xf7fa, 0xf7fb, 0xf7fc, 0xf7fd, 0xf7fe, 0xf7ff, 0xf800, 0xf801,
+ 0xf802, 0xf803, 0xf804, 0xf805, 0xf806, 0xf807, 0xf808, 0xf809,
+ 0xf80a, 0xf80b, 0xf80c, 0xf80d, 0xf80e, 0xf80f, 0xf810, 0xf811,
+ 0xf812, 0xf813, 0xf814, 0xf815, 0xf816, 0xffe2, 0xffe4, 0xff07,
+ 0xff02, 0x3231, 0x2116, 0x2121, 0x309b, 0x309c, 0x2e80, 0x2e84,
+ 0x2e86, 0x2e87, 0x2e88, 0x2e8a, 0x2e8c, 0x2e8d, 0x2e95, 0x2e9c,
+ 0x2e9d, 0x2ea5, 0x2ea7, 0x2eaa, 0x2eac, 0x2eae, 0x2eb6, 0x2ebc,
+ 0x2ebe, 0x2ec6, 0x2eca, 0x2ecc, 0x2ecd, 0x2ecf, 0x2ed6, 0x2ed7,
+ 0x2ede, 0x2ee3, 0xf83c, 0xf83d, 0xf83e, 0x0283, 0x0250, 0x025b,
+ 0x0254, 0x0275, 0x0153, 0x00f8, 0x014b, 0x028a, 0x026a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4e42, 0x4e5c, 0x51f5, 0x531a, 0x5382, 0x4e07, 0x4e0c, 0x4e47,
+ 0x4e8d, 0x56d7, 0xfa0c, 0x5c6e, 0x5f73, 0x4e0f, 0x5187, 0x4e0e,
+ 0x4e2e, 0x4e93, 0x4ec2, 0x4ec9, 0x4ec8, 0x5198, 0x52fc, 0x536c,
+ 0x53b9, 0x5720, 0x5903, 0x592c, 0x5c10, 0x5dff, 0x65e1, 0x6bb3,
+ 0x6bcc, 0x6c14, 0x723f, 0x4e31, 0x4e3c, 0x4ee8, 0x4edc, 0x4ee9,
+ 0x4ee1, 0x4edd, 0x4eda, 0x520c, 0x531c, 0x534c, 0x5722, 0x5723,
+ 0x5917, 0x592f, 0x5b81, 0x5b84, 0x5c12, 0x5c3b, 0x5c74, 0x5c73,
+ 0x5e04, 0x5e80, 0x5e82, 0x5fc9, 0x6209, 0x6250, 0x6c15, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6c36, 0x6c43, 0x6c3f, 0x6c3b, 0x72ae, 0x72b0, 0x738a,
+ 0x79b8, 0x808a, 0x961e, 0x4f0e, 0x4f18, 0x4f2c, 0x4ef5, 0x4f14,
+ 0x4ef1, 0x4f00, 0x4ef7, 0x4f08, 0x4f1d, 0x4f02, 0x4f05, 0x4f22,
+ 0x4f13, 0x4f04, 0x4ef4, 0x4f12, 0x51b1, 0x5213, 0x5209, 0x5210,
+ 0x52a6, 0x5322, 0x531f, 0x534d, 0x538a, 0x5407, 0x56e1, 0x56df,
+ 0x572e, 0x572a, 0x5734, 0x593c, 0x5980, 0x597c, 0x5985, 0x597b,
+ 0x597e, 0x5977, 0x597f, 0x5b56, 0x5c15, 0x5c25, 0x5c7c, 0x5c7a,
+ 0x5c7b, 0x5c7e, 0x5ddf, 0x5e75, 0x5e84, 0x5f02, 0x5f1a, 0x5f74,
+ 0x5fd5, 0x5fd4, 0x5fcf, 0x625c, 0x625e, 0x6264, 0x6261, 0x6266,
+ 0x6262, 0x6259, 0x6260, 0x625a, 0x6265, 0x65ef, 0x65ee, 0x673e,
+ 0x6739, 0x6738, 0x673b, 0x673a, 0x673f, 0x673c, 0x6733, 0x6c18,
+ 0x6c46, 0x6c52, 0x6c5c, 0x6c4f, 0x6c4a, 0x6c54, 0x6c4b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6c4c, 0x7071, 0x725e, 0x72b4, 0x72b5, 0x738e, 0x752a, 0x767f,
+ 0x7a75, 0x7f51, 0x8278, 0x827c, 0x8280, 0x827d, 0x827f, 0x864d,
+ 0x897e, 0x9099, 0x9097, 0x9098, 0x909b, 0x9094, 0x9622, 0x9624,
+ 0x9620, 0x9623, 0x4f56, 0x4f3b, 0x4f62, 0x4f49, 0x4f53, 0x4f64,
+ 0x4f3e, 0x4f67, 0x4f52, 0x4f5f, 0x4f41, 0x4f58, 0x4f2d, 0x4f33,
+ 0x4f3f, 0x4f61, 0x518f, 0x51b9, 0x521c, 0x521e, 0x5221, 0x52ad,
+ 0x52ae, 0x5309, 0x5363, 0x5372, 0x538e, 0x538f, 0x5430, 0x5437,
+ 0x542a, 0x5454, 0x5445, 0x5419, 0x541c, 0x5425, 0x5418, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x543d, 0x544f, 0x5441, 0x5428, 0x5424, 0x5447, 0x56ee,
+ 0x56e7, 0x56e5, 0x5741, 0x5745, 0x574c, 0x5749, 0x574b, 0x5752,
+ 0x5906, 0x5940, 0x59a6, 0x5998, 0x59a0, 0x5997, 0x598e, 0x59a2,
+ 0x5990, 0x598f, 0x59a7, 0x59a1, 0x5b8e, 0x5b92, 0x5c28, 0x5c2a,
+ 0x5c8d, 0x5c8f, 0x5c88, 0x5c8b, 0x5c89, 0x5c92, 0x5c8a, 0x5c86,
+ 0x5c93, 0x5c95, 0x5de0, 0x5e0a, 0x5e0e, 0x5e8b, 0x5e89, 0x5e8c,
+ 0x5e88, 0x5e8d, 0x5f05, 0x5f1d, 0x5f78, 0x5f76, 0x5fd2, 0x5fd1,
+ 0x5fd0, 0x5fed, 0x5fe8, 0x5fee, 0x5ff3, 0x5fe1, 0x5fe4, 0x5fe3,
+ 0x5ffa, 0x5fef, 0x5ff7, 0x5ffb, 0x6000, 0x5ff4, 0x623a, 0x6283,
+ 0x628c, 0x628e, 0x628f, 0x6294, 0x6287, 0x6271, 0x627b, 0x627a,
+ 0x6270, 0x6281, 0x6288, 0x6277, 0x627d, 0x6272, 0x6274, 0x6537,
+ 0x65f0, 0x65f4, 0x65f3, 0x65f2, 0x65f5, 0x6745, 0x6747, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6759, 0x6755, 0x674c, 0x6748, 0x675d, 0x674d, 0x675a, 0x674b,
+ 0x6bd0, 0x6c19, 0x6c1a, 0x6c78, 0x6c67, 0x6c6b, 0x6c84, 0x6c8b,
+ 0x6c8f, 0x6c71, 0x6c6f, 0x6c69, 0x6c9a, 0x6c6d, 0x6c87, 0x6c95,
+ 0x6c9c, 0x6c66, 0x6c73, 0x6c65, 0x6c7b, 0x6c8e, 0x7074, 0x707a,
+ 0x7263, 0x72bf, 0x72bd, 0x72c3, 0x72c6, 0x72c1, 0x72ba, 0x72c5,
+ 0x7395, 0x7397, 0x7393, 0x7394, 0x7392, 0x753a, 0x7539, 0x7594,
+ 0x7595, 0x7681, 0x793d, 0x8034, 0x8095, 0x8099, 0x8090, 0x8092,
+ 0x809c, 0x8290, 0x828f, 0x8285, 0x828e, 0x8291, 0x8293, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x828a, 0x8283, 0x8284, 0x8c78, 0x8fc9, 0x8fbf, 0x909f,
+ 0x90a1, 0x90a5, 0x909e, 0x90a7, 0x90a0, 0x9630, 0x9628, 0x962f,
+ 0x962d, 0x4e33, 0x4f98, 0x4f7c, 0x4f85, 0x4f7d, 0x4f80, 0x4f87,
+ 0x4f76, 0x4f74, 0x4f89, 0x4f84, 0x4f77, 0x4f4c, 0x4f97, 0x4f6a,
+ 0x4f9a, 0x4f79, 0x4f81, 0x4f78, 0x4f90, 0x4f9c, 0x4f94, 0x4f9e,
+ 0x4f92, 0x4f82, 0x4f95, 0x4f6b, 0x4f6e, 0x519e, 0x51bc, 0x51be,
+ 0x5235, 0x5232, 0x5233, 0x5246, 0x5231, 0x52bc, 0x530a, 0x530b,
+ 0x533c, 0x5392, 0x5394, 0x5487, 0x547f, 0x5481, 0x5491, 0x5482,
+ 0x5488, 0x546b, 0x547a, 0x547e, 0x5465, 0x546c, 0x5474, 0x5466,
+ 0x548d, 0x546f, 0x5461, 0x5460, 0x5498, 0x5463, 0x5467, 0x5464,
+ 0x56f7, 0x56f9, 0x576f, 0x5772, 0x576d, 0x576b, 0x5771, 0x5770,
+ 0x5776, 0x5780, 0x5775, 0x577b, 0x5773, 0x5774, 0x5762, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5768, 0x577d, 0x590c, 0x5945, 0x59b5, 0x59ba, 0x59cf, 0x59ce,
+ 0x59b2, 0x59cc, 0x59c1, 0x59b6, 0x59bc, 0x59c3, 0x59d6, 0x59b1,
+ 0x59bd, 0x59c0, 0x59c8, 0x59b4, 0x59c7, 0x5b62, 0x5b65, 0x5b93,
+ 0x5b95, 0x5c44, 0x5c47, 0x5cae, 0x5ca4, 0x5ca0, 0x5cb5, 0x5caf,
+ 0x5ca8, 0x5cac, 0x5c9f, 0x5ca3, 0x5cad, 0x5ca2, 0x5caa, 0x5ca7,
+ 0x5c9d, 0x5ca5, 0x5cb6, 0x5cb0, 0x5ca6, 0x5e17, 0x5e14, 0x5e19,
+ 0x5f28, 0x5f22, 0x5f23, 0x5f24, 0x5f54, 0x5f82, 0x5f7e, 0x5f7d,
+ 0x5fde, 0x5fe5, 0x602d, 0x6026, 0x6019, 0x6032, 0x600b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6034, 0x600a, 0x6017, 0x6033, 0x601a, 0x601e, 0x602c,
+ 0x6022, 0x600d, 0x6010, 0x602e, 0x6013, 0x6011, 0x600c, 0x6009,
+ 0x601c, 0x6214, 0x623d, 0x62ad, 0x62b4, 0x62d1, 0x62be, 0x62aa,
+ 0x62b6, 0x62ca, 0x62ae, 0x62b3, 0x62af, 0x62bb, 0x62a9, 0x62b0,
+ 0x62b8, 0x653d, 0x65a8, 0x65bb, 0x6609, 0x65fc, 0x6604, 0x6612,
+ 0x6608, 0x65fb, 0x6603, 0x660b, 0x660d, 0x6605, 0x65fd, 0x6611,
+ 0x6610, 0x66f6, 0x670a, 0x6785, 0x676c, 0x678e, 0x6792, 0x6776,
+ 0x677b, 0x6798, 0x6786, 0x6784, 0x6774, 0x678d, 0x678c, 0x677a,
+ 0x679f, 0x6791, 0x6799, 0x6783, 0x677d, 0x6781, 0x6778, 0x6779,
+ 0x6794, 0x6b25, 0x6b80, 0x6b7e, 0x6bde, 0x6c1d, 0x6c93, 0x6cec,
+ 0x6ceb, 0x6cee, 0x6cd9, 0x6cb6, 0x6cd4, 0x6cad, 0x6ce7, 0x6cb7,
+ 0x6cd0, 0x6cc2, 0x6cba, 0x6cc3, 0x6cc6, 0x6ced, 0x6cf2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6cd2, 0x6cdd, 0x6cb4, 0x6c8a, 0x6c9d, 0x6c80, 0x6cde, 0x6cc0,
+ 0x6d30, 0x6ccd, 0x6cc7, 0x6cb0, 0x6cf9, 0x6ccf, 0x6ce9, 0x6cd1,
+ 0x7094, 0x7098, 0x7085, 0x7093, 0x7086, 0x7084, 0x7091, 0x7096,
+ 0x7082, 0x709a, 0x7083, 0x726a, 0x72d6, 0x72cb, 0x72d8, 0x72c9,
+ 0x72dc, 0x72d2, 0x72d4, 0x72da, 0x72cc, 0x72d1, 0x73a4, 0x73a1,
+ 0x73ad, 0x73a6, 0x73a2, 0x73a0, 0x73ac, 0x739d, 0x74dd, 0x74e8,
+ 0x753f, 0x7540, 0x753e, 0x758c, 0x7598, 0x76af, 0x76f3, 0x76f1,
+ 0x76f0, 0x76f5, 0x77f8, 0x77fc, 0x77f9, 0x77fb, 0x77fa, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x77f7, 0x7942, 0x793f, 0x79c5, 0x7a78, 0x7a7b, 0x7afb,
+ 0x7c75, 0x7cfd, 0x8035, 0x808f, 0x80ae, 0x80a3, 0x80b8, 0x80b5,
+ 0x80ad, 0x8220, 0x82a0, 0x82c0, 0x82ab, 0x829a, 0x8298, 0x829b,
+ 0x82b5, 0x82a7, 0x82ae, 0x82bc, 0x829e, 0x82ba, 0x82b4, 0x82a8,
+ 0x82a1, 0x82a9, 0x82c2, 0x82a4, 0x82c3, 0x82b6, 0x82a2, 0x8670,
+ 0x866f, 0x866d, 0x866e, 0x8c56, 0x8fd2, 0x8fcb, 0x8fd3, 0x8fcd,
+ 0x8fd6, 0x8fd5, 0x8fd7, 0x90b2, 0x90b4, 0x90af, 0x90b3, 0x90b0,
+ 0x9639, 0x963d, 0x963c, 0x963a, 0x9643, 0x4fcd, 0x4fc5, 0x4fd3,
+ 0x4fb2, 0x4fc9, 0x4fcb, 0x4fc1, 0x4fd4, 0x4fdc, 0x4fd9, 0x4fbb,
+ 0x4fb3, 0x4fdb, 0x4fc7, 0x4fd6, 0x4fba, 0x4fc0, 0x4fb9, 0x4fec,
+ 0x5244, 0x5249, 0x52c0, 0x52c2, 0x533d, 0x537c, 0x5397, 0x5396,
+ 0x5399, 0x5398, 0x54ba, 0x54a1, 0x54ad, 0x54a5, 0x54cf, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x54c3, 0x830d, 0x54b7, 0x54ae, 0x54d6, 0x54b6, 0x54c5, 0x54c6,
+ 0x54a0, 0x5470, 0x54bc, 0x54a2, 0x54be, 0x5472, 0x54de, 0x54b0,
+ 0x57b5, 0x579e, 0x579f, 0x57a4, 0x578c, 0x5797, 0x579d, 0x579b,
+ 0x5794, 0x5798, 0x578f, 0x5799, 0x57a5, 0x579a, 0x5795, 0x58f4,
+ 0x590d, 0x5953, 0x59e1, 0x59de, 0x59ee, 0x5a00, 0x59f1, 0x59dd,
+ 0x59fa, 0x59fd, 0x59fc, 0x59f6, 0x59e4, 0x59f2, 0x59f7, 0x59db,
+ 0x59e9, 0x59f3, 0x59f5, 0x59e0, 0x59fe, 0x59f4, 0x59ed, 0x5ba8,
+ 0x5c4c, 0x5cd0, 0x5cd8, 0x5ccc, 0x5cd7, 0x5ccb, 0x5cdb, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5cde, 0x5cda, 0x5cc9, 0x5cc7, 0x5cca, 0x5cd6, 0x5cd3,
+ 0x5cd4, 0x5ccf, 0x5cc8, 0x5cc6, 0x5cce, 0x5cdf, 0x5cf8, 0x5df9,
+ 0x5e21, 0x5e22, 0x5e23, 0x5e20, 0x5e24, 0x5eb0, 0x5ea4, 0x5ea2,
+ 0x5e9b, 0x5ea3, 0x5ea5, 0x5f07, 0x5f2e, 0x5f56, 0x5f86, 0x6037,
+ 0x6039, 0x6054, 0x6072, 0x605e, 0x6045, 0x6053, 0x6047, 0x6049,
+ 0x605b, 0x604c, 0x6040, 0x6042, 0x605f, 0x6024, 0x6044, 0x6058,
+ 0x6066, 0x606e, 0x6242, 0x6243, 0x62cf, 0x630d, 0x630b, 0x62f5,
+ 0x630e, 0x6303, 0x62eb, 0x62f9, 0x630f, 0x630c, 0x62f8, 0x62f6,
+ 0x6300, 0x6313, 0x6314, 0x62fa, 0x6315, 0x62fb, 0x62f0, 0x6541,
+ 0x6543, 0x65aa, 0x65bf, 0x6636, 0x6621, 0x6632, 0x6635, 0x661c,
+ 0x6626, 0x6622, 0x6633, 0x662b, 0x663a, 0x661d, 0x6634, 0x6639,
+ 0x662e, 0x670f, 0x6710, 0x67c1, 0x67f2, 0x67c8, 0x67ba, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x67dc, 0x67bb, 0x67f8, 0x67d8, 0x67c0, 0x67b7, 0x67c5, 0x67eb,
+ 0x67e4, 0x67df, 0x67b5, 0x67cd, 0x67b3, 0x67f7, 0x67f6, 0x67ee,
+ 0x67e3, 0x67c2, 0x67b9, 0x67ce, 0x67e7, 0x67f0, 0x67b2, 0x67fc,
+ 0x67c6, 0x67ed, 0x67cc, 0x67ae, 0x67e6, 0x67db, 0x67fa, 0x67c9,
+ 0x67ca, 0x67c3, 0x67ea, 0x67cb, 0x6b28, 0x6b82, 0x6b84, 0x6bb6,
+ 0x6bd6, 0x6bd8, 0x6be0, 0x6c20, 0x6c21, 0x6d28, 0x6d34, 0x6d2d,
+ 0x6d1f, 0x6d3c, 0x6d3f, 0x6d12, 0x6d0a, 0x6cda, 0x6d33, 0x6d04,
+ 0x6d19, 0x6d3a, 0x6d1a, 0x6d11, 0x6d00, 0x6d1d, 0x6d42, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6d01, 0x6d18, 0x6d37, 0x6d03, 0x6d0f, 0x6d40, 0x6d07,
+ 0x6d20, 0x6d2c, 0x6d08, 0x6d22, 0x6d09, 0x6d10, 0x70b7, 0x709f,
+ 0x70be, 0x70b1, 0x70b0, 0x70a1, 0x70b4, 0x70b5, 0x70a9, 0x7241,
+ 0x7249, 0x724a, 0x726c, 0x7270, 0x7273, 0x726e, 0x72ca, 0x72e4,
+ 0x72e8, 0x72eb, 0x72df, 0x72ea, 0x72e6, 0x72e3, 0x7385, 0x73cc,
+ 0x73c2, 0x73c8, 0x73c5, 0x73b9, 0x73b6, 0x73b5, 0x73b4, 0x73eb,
+ 0x73bf, 0x73c7, 0x73be, 0x73c3, 0x73c6, 0x73b8, 0x73cb, 0x74ec,
+ 0x74ee, 0x752e, 0x7547, 0x7548, 0x75a7, 0x75aa, 0x7679, 0x76c4,
+ 0x7708, 0x7703, 0x7704, 0x7705, 0x770a, 0x76f7, 0x76fb, 0x76fa,
+ 0x77e7, 0x77e8, 0x7806, 0x7811, 0x7812, 0x7805, 0x7810, 0x780f,
+ 0x780e, 0x7809, 0x7803, 0x7813, 0x794a, 0x794c, 0x794b, 0x7945,
+ 0x7944, 0x79d5, 0x79cd, 0x79cf, 0x79d6, 0x79ce, 0x7a80, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7a7e, 0x7ad1, 0x7b00, 0x7b01, 0x7c7a, 0x7c78, 0x7c79, 0x7c7f,
+ 0x7c80, 0x7c81, 0x7d03, 0x7d08, 0x7d01, 0x7f58, 0x7f91, 0x7f8d,
+ 0x7fbe, 0x8007, 0x800e, 0x800f, 0x8014, 0x8037, 0x80d8, 0x80c7,
+ 0x80e0, 0x80d1, 0x80c8, 0x80c2, 0x80d0, 0x80c5, 0x80e3, 0x80d9,
+ 0x80dc, 0x80ca, 0x80d5, 0x80c9, 0x80cf, 0x80d7, 0x80e6, 0x80cd,
+ 0x81ff, 0x8221, 0x8294, 0x82d9, 0x82fe, 0x82f9, 0x8307, 0x82e8,
+ 0x8300, 0x82d5, 0x833a, 0x82eb, 0x82d6, 0x82f4, 0x82ec, 0x82e1,
+ 0x82f2, 0x82f5, 0x830c, 0x82fb, 0x82f6, 0x82f0, 0x82ea, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x82e4, 0x82e0, 0x82fa, 0x82f3, 0x82ed, 0x8677, 0x8674,
+ 0x867c, 0x8673, 0x8841, 0x884e, 0x8867, 0x886a, 0x8869, 0x89d3,
+ 0x8a04, 0x8a07, 0x8d72, 0x8fe3, 0x8fe1, 0x8fee, 0x8fe0, 0x90f1,
+ 0x90bd, 0x90bf, 0x90d5, 0x90c5, 0x90be, 0x90c7, 0x90cb, 0x90c8,
+ 0x91d4, 0x91d3, 0x9654, 0x964f, 0x9651, 0x9653, 0x964a, 0x964e,
+ 0x501e, 0x5005, 0x5007, 0x5013, 0x5022, 0x5030, 0x501b, 0x4ff5,
+ 0x4ff4, 0x5033, 0x5037, 0x502c, 0x4ff6, 0x4ff7, 0x5017, 0x501c,
+ 0x5020, 0x5027, 0x5035, 0x502f, 0x5031, 0x500e, 0x515a, 0x5194,
+ 0x5193, 0x51ca, 0x51c4, 0x51c5, 0x51c8, 0x51ce, 0x5261, 0x525a,
+ 0x5252, 0x525e, 0x525f, 0x5255, 0x5262, 0x52cd, 0x530e, 0x539e,
+ 0x5526, 0x54e2, 0x5517, 0x5512, 0x54e7, 0x54f3, 0x54e4, 0x551a,
+ 0x54ff, 0x5504, 0x5508, 0x54eb, 0x5511, 0x5505, 0x54f1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x550a, 0x54fb, 0x54f7, 0x54f8, 0x54e0, 0x550e, 0x5503, 0x550b,
+ 0x5701, 0x5702, 0x57cc, 0x5832, 0x57d5, 0x57d2, 0x57ba, 0x57c6,
+ 0x57bd, 0x57bc, 0x57b8, 0x57b6, 0x57bf, 0x57c7, 0x57d0, 0x57b9,
+ 0x57c1, 0x590e, 0x594a, 0x5a19, 0x5a16, 0x5a2d, 0x5a2e, 0x5a15,
+ 0x5a0f, 0x5a17, 0x5a0a, 0x5a1e, 0x5a33, 0x5b6c, 0x5ba7, 0x5bad,
+ 0x5bac, 0x5c03, 0x5c56, 0x5c54, 0x5cec, 0x5cff, 0x5cee, 0x5cf1,
+ 0x5cf7, 0x5d00, 0x5cf9, 0x5e29, 0x5e28, 0x5ea8, 0x5eae, 0x5eaa,
+ 0x5eac, 0x5f33, 0x5f30, 0x5f67, 0x605d, 0x605a, 0x6067, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6041, 0x60a2, 0x6088, 0x6080, 0x6092, 0x6081, 0x609d,
+ 0x6083, 0x6095, 0x609b, 0x6097, 0x6087, 0x609c, 0x608e, 0x6219,
+ 0x6246, 0x62f2, 0x6310, 0x6356, 0x632c, 0x6344, 0x6345, 0x6336,
+ 0x6343, 0x63e4, 0x6339, 0x634b, 0x634a, 0x633c, 0x6329, 0x6341,
+ 0x6334, 0x6358, 0x6354, 0x6359, 0x632d, 0x6347, 0x6333, 0x635a,
+ 0x6351, 0x6338, 0x6357, 0x6340, 0x6348, 0x654a, 0x6546, 0x65c6,
+ 0x65c3, 0x65c4, 0x65c2, 0x664a, 0x665f, 0x6647, 0x6651, 0x6712,
+ 0x6713, 0x681f, 0x681a, 0x6849, 0x6832, 0x6833, 0x683b, 0x684b,
+ 0x684f, 0x6816, 0x6831, 0x681c, 0x6835, 0x682b, 0x682d, 0x682f,
+ 0x684e, 0x6844, 0x6834, 0x681d, 0x6812, 0x6814, 0x6826, 0x6828,
+ 0x682e, 0x684d, 0x683a, 0x6825, 0x6820, 0x6b2c, 0x6b2f, 0x6b2d,
+ 0x6b31, 0x6b34, 0x6b6d, 0x8082, 0x6b88, 0x6be6, 0x6be4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6be8, 0x6be3, 0x6be2, 0x6be7, 0x6c25, 0x6d7a, 0x6d63, 0x6d64,
+ 0x6d76, 0x6d0d, 0x6d61, 0x6d92, 0x6d58, 0x6d62, 0x6d6d, 0x6d6f,
+ 0x6d91, 0x6d8d, 0x6def, 0x6d7f, 0x6d86, 0x6d5e, 0x6d67, 0x6d60,
+ 0x6d97, 0x6d70, 0x6d7c, 0x6d5f, 0x6d82, 0x6d98, 0x6d2f, 0x6d68,
+ 0x6d8b, 0x6d7e, 0x6d80, 0x6d84, 0x6d16, 0x6d83, 0x6d7b, 0x6d7d,
+ 0x6d75, 0x6d90, 0x70dc, 0x70d3, 0x70d1, 0x70dd, 0x70cb, 0x7f39,
+ 0x70e2, 0x70d7, 0x70d2, 0x70de, 0x70e0, 0x70d4, 0x70cd, 0x70c5,
+ 0x70c6, 0x70c7, 0x70da, 0x70ce, 0x70e1, 0x7242, 0x7278, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7277, 0x7276, 0x7300, 0x72fa, 0x72f4, 0x72fe, 0x72f6,
+ 0x72f3, 0x72fb, 0x7301, 0x73d3, 0x73d9, 0x73e5, 0x73d6, 0x73bc,
+ 0x73e7, 0x73e3, 0x73e9, 0x73dc, 0x73d2, 0x73db, 0x73d4, 0x73dd,
+ 0x73da, 0x73d7, 0x73d8, 0x73e8, 0x74de, 0x74df, 0x74f4, 0x74f5,
+ 0x7521, 0x755b, 0x755f, 0x75b0, 0x75c1, 0x75bb, 0x75c4, 0x75c0,
+ 0x75bf, 0x75b6, 0x75ba, 0x768a, 0x76c9, 0x771d, 0x771b, 0x7710,
+ 0x7713, 0x7712, 0x7723, 0x7711, 0x7715, 0x7719, 0x771a, 0x7722,
+ 0x7727, 0x7823, 0x782c, 0x7822, 0x7835, 0x782f, 0x7828, 0x782e,
+ 0x782b, 0x7821, 0x7829, 0x7833, 0x782a, 0x7831, 0x7954, 0x795b,
+ 0x794f, 0x795c, 0x7953, 0x7952, 0x7951, 0x79eb, 0x79ec, 0x79e0,
+ 0x79ee, 0x79ed, 0x79ea, 0x79dc, 0x79de, 0x79dd, 0x7a86, 0x7a89,
+ 0x7a85, 0x7a8b, 0x7a8c, 0x7a8a, 0x7a87, 0x7ad8, 0x7b10, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7b04, 0x7b13, 0x7b05, 0x7b0f, 0x7b08, 0x7b0a, 0x7b0e, 0x7b09,
+ 0x7b12, 0x7c84, 0x7c91, 0x7c8a, 0x7c8c, 0x7c88, 0x7c8d, 0x7c85,
+ 0x7d1e, 0x7d1d, 0x7d11, 0x7d0e, 0x7d18, 0x7d16, 0x7d13, 0x7d1f,
+ 0x7d12, 0x7d0f, 0x7d0c, 0x7f5c, 0x7f61, 0x7f5e, 0x7f60, 0x7f5d,
+ 0x7f5b, 0x7f96, 0x7f92, 0x7fc3, 0x7fc2, 0x7fc0, 0x8016, 0x803e,
+ 0x8039, 0x80fa, 0x80f2, 0x80f9, 0x80f5, 0x8101, 0x80fb, 0x8100,
+ 0x8201, 0x822f, 0x8225, 0x8333, 0x832d, 0x8344, 0x8319, 0x8351,
+ 0x8325, 0x8356, 0x833f, 0x8341, 0x8326, 0x831c, 0x8322, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8342, 0x834e, 0x831b, 0x832a, 0x8308, 0x833c, 0x834d,
+ 0x8316, 0x8324, 0x8320, 0x8337, 0x832f, 0x8329, 0x8347, 0x8345,
+ 0x834c, 0x8353, 0x831e, 0x832c, 0x834b, 0x8327, 0x8348, 0x8653,
+ 0x8652, 0x86a2, 0x86a8, 0x8696, 0x868d, 0x8691, 0x869e, 0x8687,
+ 0x8697, 0x8686, 0x868b, 0x869a, 0x8685, 0x86a5, 0x8699, 0x86a1,
+ 0x86a7, 0x8695, 0x8698, 0x868e, 0x869d, 0x8690, 0x8694, 0x8843,
+ 0x8844, 0x886d, 0x8875, 0x8876, 0x8872, 0x8880, 0x8871, 0x887f,
+ 0x886f, 0x8883, 0x887e, 0x8874, 0x887c, 0x8a12, 0x8c47, 0x8c57,
+ 0x8c7b, 0x8ca4, 0x8ca3, 0x8d76, 0x8d78, 0x8db5, 0x8db7, 0x8db6,
+ 0x8ed1, 0x8ed3, 0x8ffe, 0x8ff5, 0x9002, 0x8fff, 0x8ffb, 0x9004,
+ 0x8ffc, 0x8ff6, 0x90d6, 0x90e0, 0x90d9, 0x90da, 0x90e3, 0x90df,
+ 0x90e5, 0x90d8, 0x90db, 0x90d7, 0x90dc, 0x90e4, 0x9150, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x914e, 0x914f, 0x91d5, 0x91e2, 0x91da, 0x965c, 0x965f, 0x96bc,
+ 0x98e3, 0x9adf, 0x9b2f, 0x4e7f, 0x5070, 0x506a, 0x5061, 0x505e,
+ 0x5060, 0x5053, 0x504b, 0x505d, 0x5072, 0x5048, 0x504d, 0x5041,
+ 0x505b, 0x504a, 0x5062, 0x5015, 0x5045, 0x505f, 0x5069, 0x506b,
+ 0x5063, 0x5064, 0x5046, 0x5040, 0x506e, 0x5073, 0x5057, 0x5051,
+ 0x51d0, 0x526b, 0x526d, 0x526c, 0x526e, 0x52d6, 0x52d3, 0x532d,
+ 0x539c, 0x5575, 0x5576, 0x553c, 0x554d, 0x5550, 0x5534, 0x552a,
+ 0x5551, 0x5562, 0x5536, 0x5535, 0x5530, 0x5552, 0x5545, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x550c, 0x5532, 0x5565, 0x554e, 0x5539, 0x5548, 0x552d,
+ 0x553b, 0x5540, 0x554b, 0x570a, 0x5707, 0x57fb, 0x5814, 0x57e2,
+ 0x57f6, 0x57dc, 0x57f4, 0x5800, 0x57ed, 0x57fd, 0x5808, 0x57f8,
+ 0x580b, 0x57f3, 0x57cf, 0x5807, 0x57ee, 0x57e3, 0x57f2, 0x57e5,
+ 0x57ec, 0x57e1, 0x580e, 0x57fc, 0x5810, 0x57e7, 0x5801, 0x580c,
+ 0x57f1, 0x57e9, 0x57f0, 0x580d, 0x5804, 0x595c, 0x5a60, 0x5a58,
+ 0x5a55, 0x5a67, 0x5a5e, 0x5a38, 0x5a35, 0x5a6d, 0x5a50, 0x5a5f,
+ 0x5a65, 0x5a6c, 0x5a53, 0x5a64, 0x5a57, 0x5a43, 0x5a5d, 0x5a52,
+ 0x5a44, 0x5a5b, 0x5a48, 0x5a8e, 0x5a3e, 0x5a4d, 0x5a39, 0x5a4c,
+ 0x5a70, 0x5a69, 0x5a47, 0x5a51, 0x5a56, 0x5a42, 0x5a5c, 0x5b72,
+ 0x5b6e, 0x5bc1, 0x5bc0, 0x5c59, 0x5d1e, 0x5d0b, 0x5d1d, 0x5d1a,
+ 0x5d20, 0x5d0c, 0x5d28, 0x5d0d, 0x5d26, 0x5d25, 0x5d0f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5d30, 0x5d12, 0x5d23, 0x5d1f, 0x5d2e, 0x5e3e, 0x5e34, 0x5eb1,
+ 0x5eb4, 0x5eb9, 0x5eb2, 0x5eb3, 0x5f36, 0x5f38, 0x5f9b, 0x5f96,
+ 0x5f9f, 0x608a, 0x6090, 0x6086, 0x60be, 0x60b0, 0x60ba, 0x60d3,
+ 0x60d4, 0x60cf, 0x60e4, 0x60d9, 0x60dd, 0x60c8, 0x60b1, 0x60db,
+ 0x60b7, 0x60ca, 0x60bf, 0x60c3, 0x60cd, 0x60c0, 0x6332, 0x6365,
+ 0x638a, 0x6382, 0x637d, 0x63bd, 0x639e, 0x63ad, 0x639d, 0x6397,
+ 0x63ab, 0x638e, 0x636f, 0x6387, 0x6390, 0x636e, 0x63af, 0x6375,
+ 0x639c, 0x636d, 0x63ae, 0x637c, 0x63a4, 0x633b, 0x639f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6378, 0x6385, 0x6381, 0x6391, 0x638d, 0x6370, 0x6553,
+ 0x65cd, 0x6665, 0x6661, 0x665b, 0x6659, 0x665c, 0x6662, 0x6718,
+ 0x6879, 0x6887, 0x6890, 0x689c, 0x686d, 0x686e, 0x68ae, 0x68ab,
+ 0x6956, 0x686f, 0x68a3, 0x68ac, 0x68a9, 0x6875, 0x6874, 0x68b2,
+ 0x688f, 0x6877, 0x6892, 0x687c, 0x686b, 0x6872, 0x68aa, 0x6880,
+ 0x6871, 0x687e, 0x689b, 0x6896, 0x688b, 0x68a0, 0x6889, 0x68a4,
+ 0x6878, 0x687b, 0x6891, 0x688c, 0x688a, 0x687d, 0x6b36, 0x6b33,
+ 0x6b37, 0x6b38, 0x6b91, 0x6b8f, 0x6b8d, 0x6b8e, 0x6b8c, 0x6c2a,
+ 0x6dc0, 0x6dab, 0x6db4, 0x6db3, 0x6e74, 0x6dac, 0x6de9, 0x6de2,
+ 0x6db7, 0x6df6, 0x6dd4, 0x6e00, 0x6dc8, 0x6de0, 0x6ddf, 0x6dd6,
+ 0x6dbe, 0x6de5, 0x6ddc, 0x6ddd, 0x6ddb, 0x6df4, 0x6dca, 0x6dbd,
+ 0x6ded, 0x6df0, 0x6dba, 0x6dd5, 0x6dc2, 0x6dcf, 0x6dc9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6dd0, 0x6df2, 0x6dd3, 0x6dfd, 0x6dd7, 0x6dcd, 0x6de3, 0x6dbb,
+ 0x70fa, 0x710d, 0x70f7, 0x7117, 0x70f4, 0x710c, 0x70f0, 0x7104,
+ 0x70f3, 0x7110, 0x70fc, 0x70ff, 0x7106, 0x7113, 0x7100, 0x70f8,
+ 0x70f6, 0x710b, 0x7102, 0x710e, 0x727e, 0x727b, 0x727c, 0x727f,
+ 0x731d, 0x7317, 0x7307, 0x7311, 0x7318, 0x730a, 0x7308, 0x72ff,
+ 0x730f, 0x731e, 0x7388, 0x73f6, 0x73f8, 0x73f5, 0x7404, 0x7401,
+ 0x73fd, 0x7407, 0x7400, 0x73fa, 0x73fc, 0x73ff, 0x740c, 0x740b,
+ 0x73f4, 0x7408, 0x7564, 0x7563, 0x75ce, 0x75d2, 0x75cf, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x75cb, 0x75cc, 0x75d1, 0x75d0, 0x768f, 0x7689, 0x76d3,
+ 0x7739, 0x772f, 0x772d, 0x7731, 0x7732, 0x7734, 0x7733, 0x773d,
+ 0x7725, 0x773b, 0x7735, 0x7848, 0x7852, 0x7849, 0x784d, 0x784a,
+ 0x784c, 0x7826, 0x7845, 0x7850, 0x7964, 0x7967, 0x7969, 0x796a,
+ 0x7963, 0x796b, 0x7961, 0x79bb, 0x79fa, 0x79f8, 0x79f6, 0x79f7,
+ 0x7a8f, 0x7a94, 0x7a90, 0x7b35, 0x7b47, 0x7b34, 0x7b25, 0x7b30,
+ 0x7b22, 0x7b24, 0x7b33, 0x7b18, 0x7b2a, 0x7b1d, 0x7b31, 0x7b2b,
+ 0x7b2d, 0x7b2f, 0x7b32, 0x7b38, 0x7b1a, 0x7b23, 0x7c94, 0x7c98,
+ 0x7c96, 0x7ca3, 0x7d35, 0x7d3d, 0x7d38, 0x7d36, 0x7d3a, 0x7d45,
+ 0x7d2c, 0x7d29, 0x7d41, 0x7d47, 0x7d3e, 0x7d3f, 0x7d4a, 0x7d3b,
+ 0x7d28, 0x7f63, 0x7f95, 0x7f9c, 0x7f9d, 0x7f9b, 0x7fca, 0x7fcb,
+ 0x7fcd, 0x7fd0, 0x7fd1, 0x7fc7, 0x7fcf, 0x7fc9, 0x801f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x801e, 0x801b, 0x8047, 0x8043, 0x8048, 0x8118, 0x8125, 0x8119,
+ 0x811b, 0x812d, 0x811f, 0x812c, 0x811e, 0x8121, 0x8115, 0x8127,
+ 0x811d, 0x8122, 0x8211, 0x8238, 0x8233, 0x823a, 0x8234, 0x8232,
+ 0x8274, 0x8390, 0x83a3, 0x83a8, 0x838d, 0x837a, 0x8373, 0x83a4,
+ 0x8374, 0x838f, 0x8381, 0x8395, 0x8399, 0x8375, 0x8394, 0x83a9,
+ 0x837d, 0x8383, 0x838c, 0x839d, 0x839b, 0x83aa, 0x838b, 0x837e,
+ 0x83a5, 0x83af, 0x8388, 0x8397, 0x83b0, 0x837f, 0x83a6, 0x8387,
+ 0x83ae, 0x8376, 0x839a, 0x8659, 0x8656, 0x86bf, 0x86b7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x86c2, 0x86c1, 0x86c5, 0x86ba, 0x86b0, 0x86c8, 0x86b9,
+ 0x86b3, 0x86b8, 0x86cc, 0x86b4, 0x86bb, 0x86bc, 0x86c3, 0x86bd,
+ 0x86be, 0x8852, 0x8889, 0x8895, 0x88a8, 0x88a2, 0x88aa, 0x889a,
+ 0x8891, 0x88a1, 0x889f, 0x8898, 0x88a7, 0x8899, 0x889b, 0x8897,
+ 0x88a4, 0x88ac, 0x888c, 0x8893, 0x888e, 0x8982, 0x89d6, 0x89d9,
+ 0x89d5, 0x8a30, 0x8a27, 0x8a2c, 0x8a1e, 0x8c39, 0x8c3b, 0x8c5c,
+ 0x8c5d, 0x8c7d, 0x8ca5, 0x8d7d, 0x8d7b, 0x8d79, 0x8dbc, 0x8dc2,
+ 0x8db9, 0x8dbf, 0x8dc1, 0x8ed8, 0x8ede, 0x8edd, 0x8edc, 0x8ed7,
+ 0x8ee0, 0x8ee1, 0x9024, 0x900b, 0x9011, 0x901c, 0x900c, 0x9021,
+ 0x90ef, 0x90ea, 0x90f0, 0x90f4, 0x90f2, 0x90f3, 0x90d4, 0x90eb,
+ 0x90ec, 0x90e9, 0x9156, 0x9158, 0x915a, 0x9153, 0x9155, 0x91ec,
+ 0x91f4, 0x91f1, 0x91f3, 0x91f8, 0x91e4, 0x91f9, 0x91ea, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x91eb, 0x91f7, 0x91e8, 0x91ee, 0x957a, 0x9586, 0x9588, 0x967c,
+ 0x966d, 0x966b, 0x9671, 0x966f, 0x96bf, 0x976a, 0x9804, 0x98e5,
+ 0x9997, 0x509b, 0x5095, 0x5094, 0x509e, 0x508b, 0x50a3, 0x5083,
+ 0x508c, 0x508e, 0x509d, 0x5068, 0x509c, 0x5092, 0x5082, 0x5087,
+ 0x515f, 0x51d4, 0x5312, 0x5311, 0x53a4, 0x53a7, 0x5591, 0x55a8,
+ 0x55a5, 0x55ad, 0x5577, 0x5645, 0x55a2, 0x5593, 0x5588, 0x558f,
+ 0x55b5, 0x5581, 0x55a3, 0x5592, 0x55a4, 0x557d, 0x558c, 0x55a6,
+ 0x557f, 0x5595, 0x55a1, 0x558e, 0x570c, 0x5829, 0x5837, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5819, 0x581e, 0x5827, 0x5823, 0x5828, 0x57f5, 0x5848,
+ 0x5825, 0x581c, 0x581b, 0x5833, 0x583f, 0x5836, 0x582e, 0x5839,
+ 0x5838, 0x582d, 0x582c, 0x583b, 0x5961, 0x5aaf, 0x5a94, 0x5a9f,
+ 0x5a7a, 0x5aa2, 0x5a9e, 0x5a78, 0x5aa6, 0x5a7c, 0x5aa5, 0x5aac,
+ 0x5a95, 0x5aae, 0x5a37, 0x5a84, 0x5a8a, 0x5a97, 0x5a83, 0x5a8b,
+ 0x5aa9, 0x5a7b, 0x5a7d, 0x5a8c, 0x5a9c, 0x5a8f, 0x5a93, 0x5a9d,
+ 0x5bea, 0x5bcd, 0x5bcb, 0x5bd4, 0x5bd1, 0x5bca, 0x5bce, 0x5c0c,
+ 0x5c30, 0x5d37, 0x5d43, 0x5d6b, 0x5d41, 0x5d4b, 0x5d3f, 0x5d35,
+ 0x5d51, 0x5d4e, 0x5d55, 0x5d33, 0x5d3a, 0x5d52, 0x5d3d, 0x5d31,
+ 0x5d59, 0x5d42, 0x5d39, 0x5d49, 0x5d38, 0x5d3c, 0x5d32, 0x5d36,
+ 0x5d40, 0x5d45, 0x5e44, 0x5e41, 0x5f58, 0x5fa6, 0x5fa5, 0x5fab,
+ 0x60c9, 0x60b9, 0x60cc, 0x60e2, 0x60ce, 0x60c4, 0x6114, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x60f2, 0x610a, 0x6116, 0x6105, 0x60f5, 0x6113, 0x60f8, 0x60fc,
+ 0x60fe, 0x60c1, 0x6103, 0x6118, 0x611d, 0x6110, 0x60ff, 0x6104,
+ 0x610b, 0x624a, 0x6394, 0x63b1, 0x63b0, 0x63ce, 0x63e5, 0x63e8,
+ 0x63ef, 0x63c3, 0x649d, 0x63f3, 0x63ca, 0x63e0, 0x63f6, 0x63d5,
+ 0x63f2, 0x63f5, 0x6461, 0x63df, 0x63be, 0x63dd, 0x63dc, 0x63c4,
+ 0x63d8, 0x63d3, 0x63c2, 0x63c7, 0x63cc, 0x63cb, 0x63c8, 0x63f0,
+ 0x63d7, 0x63d9, 0x6532, 0x6567, 0x656a, 0x6564, 0x655c, 0x6568,
+ 0x6565, 0x658c, 0x659d, 0x659e, 0x65ae, 0x65d0, 0x65d2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x667c, 0x666c, 0x667b, 0x6680, 0x6671, 0x6679, 0x666a,
+ 0x6672, 0x6701, 0x690c, 0x68d3, 0x6904, 0x68dc, 0x692a, 0x68ec,
+ 0x68ea, 0x68f1, 0x690f, 0x68d6, 0x68f7, 0x68eb, 0x68e4, 0x68f6,
+ 0x6913, 0x6910, 0x68f3, 0x68e1, 0x6907, 0x68cc, 0x6908, 0x6970,
+ 0x68b4, 0x6911, 0x68ef, 0x68c6, 0x6914, 0x68f8, 0x68d0, 0x68fd,
+ 0x68fc, 0x68e8, 0x690b, 0x690a, 0x6917, 0x68ce, 0x68c8, 0x68dd,
+ 0x68de, 0x68e6, 0x68f4, 0x68d1, 0x6906, 0x68d4, 0x68e9, 0x6915,
+ 0x6925, 0x68c7, 0x6b39, 0x6b3b, 0x6b3f, 0x6b3c, 0x6b94, 0x6b97,
+ 0x6b99, 0x6b95, 0x6bbd, 0x6bf0, 0x6bf2, 0x6bf3, 0x6c30, 0x6dfc,
+ 0x6e46, 0x6e47, 0x6e1f, 0x6e49, 0x6e88, 0x6e3c, 0x6e3d, 0x6e45,
+ 0x6e62, 0x6e2b, 0x6e3f, 0x6e41, 0x6e5d, 0x6e73, 0x6e1c, 0x6e33,
+ 0x6e4b, 0x6e40, 0x6e51, 0x6e3b, 0x6e03, 0x6e2e, 0x6e5e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6e68, 0x6e5c, 0x6e61, 0x6e31, 0x6e28, 0x6e60, 0x6e71, 0x6e6b,
+ 0x6e39, 0x6e22, 0x6e30, 0x6e53, 0x6e65, 0x6e27, 0x6e78, 0x6e64,
+ 0x6e77, 0x6e55, 0x6e79, 0x6e52, 0x6e66, 0x6e35, 0x6e36, 0x6e5a,
+ 0x7120, 0x711e, 0x712f, 0x70fb, 0x712e, 0x7131, 0x7123, 0x7125,
+ 0x7122, 0x7132, 0x711f, 0x7128, 0x713a, 0x711b, 0x724b, 0x725a,
+ 0x7288, 0x7289, 0x7286, 0x7285, 0x728b, 0x7312, 0x730b, 0x7330,
+ 0x7322, 0x7331, 0x7333, 0x7327, 0x7332, 0x732d, 0x7326, 0x7323,
+ 0x7335, 0x730c, 0x742e, 0x742c, 0x7430, 0x742b, 0x7416, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x741a, 0x7421, 0x742d, 0x7431, 0x7424, 0x7423, 0x741d,
+ 0x7429, 0x7420, 0x7432, 0x74fb, 0x752f, 0x756f, 0x756c, 0x75e7,
+ 0x75da, 0x75e1, 0x75e6, 0x75dd, 0x75df, 0x75e4, 0x75d7, 0x7695,
+ 0x7692, 0x76da, 0x7746, 0x7747, 0x7744, 0x774d, 0x7745, 0x774a,
+ 0x774e, 0x774b, 0x774c, 0x77de, 0x77ec, 0x7860, 0x7864, 0x7865,
+ 0x785c, 0x786d, 0x7871, 0x786a, 0x786e, 0x7870, 0x7869, 0x7868,
+ 0x785e, 0x7862, 0x7974, 0x7973, 0x7972, 0x7970, 0x7a02, 0x7a0a,
+ 0x7a03, 0x7a0c, 0x7a04, 0x7a99, 0x7ae6, 0x7ae4, 0x7b4a, 0x7b3b,
+ 0x7b44, 0x7b48, 0x7b4c, 0x7b4e, 0x7b40, 0x7b58, 0x7b45, 0x7ca2,
+ 0x7c9e, 0x7ca8, 0x7ca1, 0x7d58, 0x7d6f, 0x7d63, 0x7d53, 0x7d56,
+ 0x7d67, 0x7d6a, 0x7d4f, 0x7d6d, 0x7d5c, 0x7d6b, 0x7d52, 0x7d54,
+ 0x7d69, 0x7d51, 0x7d5f, 0x7d4e, 0x7f3e, 0x7f3f, 0x7f65, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7f66, 0x7fa2, 0x7fa0, 0x7fa1, 0x7fd7, 0x8051, 0x804f, 0x8050,
+ 0x80fe, 0x80d4, 0x8143, 0x814a, 0x8152, 0x814f, 0x8147, 0x813d,
+ 0x814d, 0x813a, 0x81e6, 0x81ee, 0x81f7, 0x81f8, 0x81f9, 0x8204,
+ 0x823c, 0x823d, 0x823f, 0x8275, 0x833b, 0x83cf, 0x83f9, 0x8423,
+ 0x83c0, 0x83e8, 0x8412, 0x83e7, 0x83e4, 0x83fc, 0x83f6, 0x8410,
+ 0x83c6, 0x83c8, 0x83eb, 0x83e3, 0x83bf, 0x8401, 0x83dd, 0x83e5,
+ 0x83d8, 0x83ff, 0x83e1, 0x83cb, 0x83ce, 0x83d6, 0x83f5, 0x83c9,
+ 0x8409, 0x840f, 0x83de, 0x8411, 0x8406, 0x83c2, 0x83f3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x83d5, 0x83fa, 0x83c7, 0x83d1, 0x83ea, 0x8413, 0x83c3,
+ 0x83ec, 0x83ee, 0x83c4, 0x83fb, 0x83d7, 0x83e2, 0x841b, 0x83db,
+ 0x83fe, 0x86d8, 0x86e2, 0x86e6, 0x86d3, 0x86e3, 0x86da, 0x86ea,
+ 0x86dd, 0x86eb, 0x86dc, 0x86ec, 0x86e9, 0x86d7, 0x86e8, 0x86d1,
+ 0x8848, 0x8856, 0x8855, 0x88ba, 0x88d7, 0x88b9, 0x88b8, 0x88c0,
+ 0x88be, 0x88b6, 0x88bc, 0x88b7, 0x88bd, 0x88b2, 0x8901, 0x88c9,
+ 0x8995, 0x8998, 0x8997, 0x89dd, 0x89da, 0x89db, 0x8a4e, 0x8a4d,
+ 0x8a39, 0x8a59, 0x8a40, 0x8a57, 0x8a58, 0x8a44, 0x8a45, 0x8a52,
+ 0x8a48, 0x8a51, 0x8a4a, 0x8a4c, 0x8a4f, 0x8c5f, 0x8c81, 0x8c80,
+ 0x8cba, 0x8cbe, 0x8cb0, 0x8cb9, 0x8cb5, 0x8d84, 0x8d80, 0x8d89,
+ 0x8dd8, 0x8dd3, 0x8dcd, 0x8dc7, 0x8dd6, 0x8ddc, 0x8dcf, 0x8dd5,
+ 0x8dd9, 0x8dc8, 0x8dd7, 0x8dc5, 0x8eef, 0x8ef7, 0x8efa, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8ef9, 0x8ee6, 0x8eee, 0x8ee5, 0x8ef5, 0x8ee7, 0x8ee8, 0x8ef6,
+ 0x8eeb, 0x8ef1, 0x8eec, 0x8ef4, 0x8ee9, 0x902d, 0x9034, 0x902f,
+ 0x9106, 0x912c, 0x9104, 0x90ff, 0x90fc, 0x9108, 0x90f9, 0x90fb,
+ 0x9101, 0x9100, 0x9107, 0x9105, 0x9103, 0x9161, 0x9164, 0x915f,
+ 0x9162, 0x9160, 0x9201, 0x920a, 0x9225, 0x9203, 0x921a, 0x9226,
+ 0x920f, 0x920c, 0x9200, 0x9212, 0x91ff, 0x91fd, 0x9206, 0x9204,
+ 0x9227, 0x9202, 0x921c, 0x9224, 0x9219, 0x9217, 0x9205, 0x9216,
+ 0x957b, 0x958d, 0x958c, 0x9590, 0x9687, 0x967e, 0x9688, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9689, 0x9683, 0x9680, 0x96c2, 0x96c8, 0x96c3, 0x96f1,
+ 0x96f0, 0x976c, 0x9770, 0x976e, 0x9807, 0x98a9, 0x98eb, 0x9ce6,
+ 0x9ef9, 0x4e83, 0x4e84, 0x4eb6, 0x50bd, 0x50bf, 0x50c6, 0x50ae,
+ 0x50c4, 0x50ca, 0x50b4, 0x50c8, 0x50c2, 0x50b0, 0x50c1, 0x50ba,
+ 0x50b1, 0x50cb, 0x50c9, 0x50b6, 0x50b8, 0x51d7, 0x527a, 0x5278,
+ 0x527b, 0x527c, 0x55c3, 0x55db, 0x55cc, 0x55d0, 0x55cb, 0x55ca,
+ 0x55dd, 0x55c0, 0x55d4, 0x55c4, 0x55e9, 0x55bf, 0x55d2, 0x558d,
+ 0x55cf, 0x55d5, 0x55e2, 0x55d6, 0x55c8, 0x55f2, 0x55cd, 0x55d9,
+ 0x55c2, 0x5714, 0x5853, 0x5868, 0x5864, 0x584f, 0x584d, 0x5849,
+ 0x586f, 0x5855, 0x584e, 0x585d, 0x5859, 0x5865, 0x585b, 0x583d,
+ 0x5863, 0x5871, 0x58fc, 0x5ac7, 0x5ac4, 0x5acb, 0x5aba, 0x5ab8,
+ 0x5ab1, 0x5ab5, 0x5ab0, 0x5abf, 0x5ac8, 0x5abb, 0x5ac6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5ab7, 0x5ac0, 0x5aca, 0x5ab4, 0x5ab6, 0x5acd, 0x5ab9, 0x5a90,
+ 0x5bd6, 0x5bd8, 0x5bd9, 0x5c1f, 0x5c33, 0x5d71, 0x5d63, 0x5d4a,
+ 0x5d65, 0x5d72, 0x5d6c, 0x5d5e, 0x5d68, 0x5d67, 0x5d62, 0x5df0,
+ 0x5e4f, 0x5e4e, 0x5e4a, 0x5e4d, 0x5e4b, 0x5ec5, 0x5ecc, 0x5ec6,
+ 0x5ecb, 0x5ec7, 0x5f40, 0x5faf, 0x5fad, 0x60f7, 0x6149, 0x614a,
+ 0x612b, 0x6145, 0x6136, 0x6132, 0x612e, 0x6146, 0x612f, 0x614f,
+ 0x6129, 0x6140, 0x6220, 0x9168, 0x6223, 0x6225, 0x6224, 0x63c5,
+ 0x63f1, 0x63eb, 0x6410, 0x6412, 0x6409, 0x6420, 0x6424, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6433, 0x6443, 0x641f, 0x6415, 0x6418, 0x6439, 0x6437,
+ 0x6422, 0x6423, 0x640c, 0x6426, 0x6430, 0x6428, 0x6441, 0x6435,
+ 0x642f, 0x640a, 0x641a, 0x6440, 0x6425, 0x6427, 0x640b, 0x63e7,
+ 0x641b, 0x642e, 0x6421, 0x640e, 0x656f, 0x6592, 0x65d3, 0x6686,
+ 0x668c, 0x6695, 0x6690, 0x668b, 0x668a, 0x6699, 0x6694, 0x6678,
+ 0x6720, 0x6966, 0x695f, 0x6938, 0x694e, 0x6962, 0x6971, 0x693f,
+ 0x6945, 0x696a, 0x6939, 0x6942, 0x6957, 0x6959, 0x697a, 0x6948,
+ 0x6949, 0x6935, 0x696c, 0x6933, 0x693d, 0x6965, 0x68f0, 0x6978,
+ 0x6934, 0x6969, 0x6940, 0x696f, 0x6944, 0x6976, 0x6958, 0x6941,
+ 0x6974, 0x694c, 0x693b, 0x694b, 0x6937, 0x695c, 0x694f, 0x6951,
+ 0x6932, 0x6952, 0x692f, 0x697b, 0x693c, 0x6b46, 0x6b45, 0x6b43,
+ 0x6b42, 0x6b48, 0x6b41, 0x6b9b, 0xfa0d, 0x6bfb, 0x6bfc, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6bf9, 0x6bf7, 0x6bf8, 0x6e9b, 0x6ed6, 0x6ec8, 0x6e8f, 0x6ec0,
+ 0x6e9f, 0x6e93, 0x6e94, 0x6ea0, 0x6eb1, 0x6eb9, 0x6ec6, 0x6ed2,
+ 0x6ebd, 0x6ec1, 0x6e9e, 0x6ec9, 0x6eb7, 0x6eb0, 0x6ecd, 0x6ea6,
+ 0x6ecf, 0x6eb2, 0x6ebe, 0x6ec3, 0x6edc, 0x6ed8, 0x6e99, 0x6e92,
+ 0x6e8e, 0x6e8d, 0x6ea4, 0x6ea1, 0x6ebf, 0x6eb3, 0x6ed0, 0x6eca,
+ 0x6e97, 0x6eae, 0x6ea3, 0x7147, 0x7154, 0x7152, 0x7163, 0x7160,
+ 0x7141, 0x715d, 0x7162, 0x7172, 0x7178, 0x716a, 0x7161, 0x7142,
+ 0x7158, 0x7143, 0x714b, 0x7170, 0x715f, 0x7150, 0x7153, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7144, 0x714d, 0x715a, 0x724f, 0x728d, 0x728c, 0x7291,
+ 0x7290, 0x728e, 0x733c, 0x7342, 0x733b, 0x733a, 0x7340, 0x734a,
+ 0x7349, 0x7444, 0x744a, 0x744b, 0x7452, 0x7451, 0x7457, 0x7440,
+ 0x744f, 0x7450, 0x744e, 0x7442, 0x7446, 0x744d, 0x7454, 0x74e1,
+ 0x74ff, 0x74fe, 0x74fd, 0x751d, 0x7579, 0x7577, 0x6983, 0x75ef,
+ 0x760f, 0x7603, 0x75f7, 0x75fe, 0x75fc, 0x75f9, 0x75f8, 0x7610,
+ 0x75fb, 0x75f6, 0x75ed, 0x75f5, 0x75fd, 0x7699, 0x76b5, 0x76dd,
+ 0x7755, 0x775f, 0x7760, 0x7752, 0x7756, 0x775a, 0x7769, 0x7767,
+ 0x7754, 0x7759, 0x776d, 0x77e0, 0x7887, 0x789a, 0x7894, 0x788f,
+ 0x7884, 0x7895, 0x7885, 0x7886, 0x78a1, 0x7883, 0x7879, 0x7899,
+ 0x7880, 0x7896, 0x787b, 0x797c, 0x7982, 0x797d, 0x7979, 0x7a11,
+ 0x7a18, 0x7a19, 0x7a12, 0x7a17, 0x7a15, 0x7a22, 0x7a13, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7a1b, 0x7a10, 0x7aa3, 0x7aa2, 0x7a9e, 0x7aeb, 0x7b66, 0x7b64,
+ 0x7b6d, 0x7b74, 0x7b69, 0x7b72, 0x7b65, 0x7b73, 0x7b71, 0x7b70,
+ 0x7b61, 0x7b78, 0x7b76, 0x7b63, 0x7cb2, 0x7cb4, 0x7caf, 0x7d88,
+ 0x7d86, 0x7d80, 0x7d8d, 0x7d7f, 0x7d85, 0x7d7a, 0x7d8e, 0x7d7b,
+ 0x7d83, 0x7d7c, 0x7d8c, 0x7d94, 0x7d84, 0x7d7d, 0x7d92, 0x7f6d,
+ 0x7f6b, 0x7f67, 0x7f68, 0x7f6c, 0x7fa6, 0x7fa5, 0x7fa7, 0x7fdb,
+ 0x7fdc, 0x8021, 0x8164, 0x8160, 0x8177, 0x815c, 0x8169, 0x815b,
+ 0x8162, 0x8172, 0x6721, 0x815e, 0x8176, 0x8167, 0x816f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8144, 0x8161, 0x821d, 0x8249, 0x8244, 0x8240, 0x8242,
+ 0x8245, 0x84f1, 0x843f, 0x8456, 0x8476, 0x8479, 0x848f, 0x848d,
+ 0x8465, 0x8451, 0x8440, 0x8486, 0x8467, 0x8430, 0x844d, 0x847d,
+ 0x845a, 0x8459, 0x8474, 0x8473, 0x845d, 0x8507, 0x845e, 0x8437,
+ 0x843a, 0x8434, 0x847a, 0x8443, 0x8478, 0x8432, 0x8445, 0x8429,
+ 0x83d9, 0x844b, 0x842f, 0x8442, 0x842d, 0x845f, 0x8470, 0x8439,
+ 0x844e, 0x844c, 0x8452, 0x846f, 0x84c5, 0x848e, 0x843b, 0x8447,
+ 0x8436, 0x8433, 0x8468, 0x847e, 0x8444, 0x842b, 0x8460, 0x8454,
+ 0x846e, 0x8450, 0x870b, 0x8704, 0x86f7, 0x870c, 0x86fa, 0x86d6,
+ 0x86f5, 0x874d, 0x86f8, 0x870e, 0x8709, 0x8701, 0x86f6, 0x870d,
+ 0x8705, 0x88d6, 0x88cb, 0x88cd, 0x88ce, 0x88de, 0x88db, 0x88da,
+ 0x88cc, 0x88d0, 0x8985, 0x899b, 0x89df, 0x89e5, 0x89e4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x89e1, 0x89e0, 0x89e2, 0x89dc, 0x89e6, 0x8a76, 0x8a86, 0x8a7f,
+ 0x8a61, 0x8a3f, 0x8a77, 0x8a82, 0x8a84, 0x8a75, 0x8a83, 0x8a81,
+ 0x8a74, 0x8a7a, 0x8c3c, 0x8c4b, 0x8c4a, 0x8c65, 0x8c64, 0x8c66,
+ 0x8c86, 0x8c84, 0x8c85, 0x8ccc, 0x8d68, 0x8d69, 0x8d91, 0x8d8c,
+ 0x8d8e, 0x8d8f, 0x8d8d, 0x8d93, 0x8d94, 0x8d90, 0x8d92, 0x8df0,
+ 0x8de0, 0x8dec, 0x8df1, 0x8dee, 0x8dd0, 0x8de9, 0x8de3, 0x8de2,
+ 0x8de7, 0x8df2, 0x8deb, 0x8df4, 0x8f06, 0x8eff, 0x8f01, 0x8f00,
+ 0x8f05, 0x8f07, 0x8f08, 0x8f02, 0x8f0b, 0x9052, 0x903f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9044, 0x9049, 0x903d, 0x9110, 0x910d, 0x910f, 0x9111,
+ 0x9116, 0x9114, 0x910b, 0x910e, 0x916e, 0x916f, 0x9248, 0x9252,
+ 0x9230, 0x923a, 0x9266, 0x9233, 0x9265, 0x925e, 0x9283, 0x922e,
+ 0x924a, 0x9246, 0x926d, 0x926c, 0x924f, 0x9260, 0x9267, 0x926f,
+ 0x9236, 0x9261, 0x9270, 0x9231, 0x9254, 0x9263, 0x9250, 0x9272,
+ 0x924e, 0x9253, 0x924c, 0x9256, 0x9232, 0x959f, 0x959c, 0x959e,
+ 0x959b, 0x9692, 0x9693, 0x9691, 0x9697, 0x96ce, 0x96fa, 0x96fd,
+ 0x96f8, 0x96f5, 0x9773, 0x9777, 0x9778, 0x9772, 0x980f, 0x980d,
+ 0x980e, 0x98ac, 0x98f6, 0x98f9, 0x99af, 0x99b2, 0x99b0, 0x99b5,
+ 0x9aad, 0x9aab, 0x9b5b, 0x9cea, 0x9ced, 0x9ce7, 0x9e80, 0x9efd,
+ 0x50e6, 0x50d4, 0x50d7, 0x50e8, 0x50f3, 0x50db, 0x50ea, 0x50dd,
+ 0x50e4, 0x50d3, 0x50ec, 0x50f0, 0x50ef, 0x50e3, 0x50e0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x51d8, 0x5280, 0x5281, 0x52e9, 0x52eb, 0x5330, 0x53ac, 0x5627,
+ 0x5615, 0x560c, 0x5612, 0x55fc, 0x560f, 0x561c, 0x5601, 0x5613,
+ 0x5602, 0x55fa, 0x561d, 0x5604, 0x55ff, 0x55f9, 0x5889, 0x587c,
+ 0x5890, 0x5898, 0x5886, 0x5881, 0x587f, 0x5874, 0x588b, 0x587a,
+ 0x5887, 0x5891, 0x588e, 0x5876, 0x5882, 0x5888, 0x587b, 0x5894,
+ 0x588f, 0x58fe, 0x596b, 0x5adc, 0x5aee, 0x5ae5, 0x5ad5, 0x5aea,
+ 0x5ada, 0x5aed, 0x5aeb, 0x5af3, 0x5ae2, 0x5ae0, 0x5adb, 0x5aec,
+ 0x5ade, 0x5add, 0x5ad9, 0x5ae8, 0x5adf, 0x5b77, 0x5be0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5be3, 0x5c63, 0x5d82, 0x5d80, 0x5d7d, 0x5d86, 0x5d7a,
+ 0x5d81, 0x5d77, 0x5d8a, 0x5d89, 0x5d88, 0x5d7e, 0x5d7c, 0x5d8d,
+ 0x5d79, 0x5d7f, 0x5e58, 0x5e59, 0x5e53, 0x5ed8, 0x5ed1, 0x5ed7,
+ 0x5ece, 0x5edc, 0x5ed5, 0x5ed9, 0x5ed2, 0x5ed4, 0x5f44, 0x5f43,
+ 0x5f6f, 0x5fb6, 0x612c, 0x6128, 0x6141, 0x615e, 0x6171, 0x6173,
+ 0x6152, 0x6153, 0x6172, 0x616c, 0x6180, 0x6174, 0x6154, 0x617a,
+ 0x615b, 0x6165, 0x613b, 0x616a, 0x6161, 0x6156, 0x6229, 0x6227,
+ 0x622b, 0x642b, 0x644d, 0x645b, 0x645d, 0x6474, 0x6476, 0x6472,
+ 0x6473, 0x647d, 0x6475, 0x6466, 0x64a6, 0x644e, 0x6482, 0x645e,
+ 0x645c, 0x644b, 0x6453, 0x6460, 0x6450, 0x647f, 0x643f, 0x646c,
+ 0x646b, 0x6459, 0x6465, 0x6477, 0x6573, 0x65a0, 0x66a1, 0x66a0,
+ 0x669f, 0x6705, 0x6704, 0x6722, 0x69b1, 0x69b6, 0x69c9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x69a0, 0x69ce, 0x6996, 0x69b0, 0x69ac, 0x69bc, 0x6991, 0x6999,
+ 0x698e, 0x69a7, 0x698d, 0x69a9, 0x69be, 0x69af, 0x69bf, 0x69c4,
+ 0x69bd, 0x69a4, 0x69d4, 0x69b9, 0x69ca, 0x699a, 0x69cf, 0x69b3,
+ 0x6993, 0x69aa, 0x69a1, 0x699e, 0x69d9, 0x6997, 0x6990, 0x69c2,
+ 0x69b5, 0x69a5, 0x69c6, 0x6b4a, 0x6b4d, 0x6b4b, 0x6b9e, 0x6b9f,
+ 0x6ba0, 0x6bc3, 0x6bc4, 0x6bfe, 0x6ece, 0x6ef5, 0x6ef1, 0x6f03,
+ 0x6f25, 0x6ef8, 0x6f37, 0x6efb, 0x6f2e, 0x6f09, 0x6f4e, 0x6f19,
+ 0x6f1a, 0x6f27, 0x6f18, 0x6f3b, 0x6f12, 0x6eed, 0x6f0a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6f36, 0x6f73, 0x6ef9, 0x6eee, 0x6f2d, 0x6f40, 0x6f30,
+ 0x6f3c, 0x6f35, 0x6eeb, 0x6f07, 0x6f0e, 0x6f43, 0x6f05, 0x6efd,
+ 0x6ef6, 0x6f39, 0x6f1c, 0x6efc, 0x6f3a, 0x6f1f, 0x6f0d, 0x6f1e,
+ 0x6f08, 0x6f21, 0x7187, 0x7190, 0x7189, 0x7180, 0x7185, 0x7182,
+ 0x718f, 0x717b, 0x7186, 0x7181, 0x7197, 0x7244, 0x7253, 0x7297,
+ 0x7295, 0x7293, 0x7343, 0x734d, 0x7351, 0x734c, 0x7462, 0x7473,
+ 0x7471, 0x7475, 0x7472, 0x7467, 0x746e, 0x7500, 0x7502, 0x7503,
+ 0x757d, 0x7590, 0x7616, 0x7608, 0x760c, 0x7615, 0x7611, 0x760a,
+ 0x7614, 0x76b8, 0x7781, 0x777c, 0x7785, 0x7782, 0x776e, 0x7780,
+ 0x776f, 0x777e, 0x7783, 0x78b2, 0x78aa, 0x78b4, 0x78ad, 0x78a8,
+ 0x787e, 0x78ab, 0x789e, 0x78a5, 0x78a0, 0x78ac, 0x78a2, 0x78a4,
+ 0x7998, 0x798a, 0x798b, 0x7996, 0x7995, 0x7994, 0x7993, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7997, 0x7988, 0x7992, 0x7990, 0x7a2b, 0x7a4a, 0x7a30, 0x7a2f,
+ 0x7a28, 0x7a26, 0x7aa8, 0x7aab, 0x7aac, 0x7aee, 0x7b88, 0x7b9c,
+ 0x7b8a, 0x7b91, 0x7b90, 0x7b96, 0x7b8d, 0x7b8c, 0x7b9b, 0x7b8e,
+ 0x7b85, 0x7b98, 0x5284, 0x7b99, 0x7ba4, 0x7b82, 0x7cbb, 0x7cbf,
+ 0x7cbc, 0x7cba, 0x7da7, 0x7db7, 0x7dc2, 0x7da3, 0x7daa, 0x7dc1,
+ 0x7dc0, 0x7dc5, 0x7d9d, 0x7dce, 0x7dc4, 0x7dc6, 0x7dcb, 0x7dcc,
+ 0x7daf, 0x7db9, 0x7d96, 0x7dbc, 0x7d9f, 0x7da6, 0x7dae, 0x7da9,
+ 0x7da1, 0x7dc9, 0x7f73, 0x7fe2, 0x7fe3, 0x7fe5, 0x7fde, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8024, 0x805d, 0x805c, 0x8189, 0x8186, 0x8183, 0x8187,
+ 0x818d, 0x818c, 0x818b, 0x8215, 0x8497, 0x84a4, 0x84a1, 0x849f,
+ 0x84ba, 0x84ce, 0x84c2, 0x84ac, 0x84ae, 0x84ab, 0x84b9, 0x84b4,
+ 0x84c1, 0x84cd, 0x84aa, 0x849a, 0x84b1, 0x84d0, 0x849d, 0x84a7,
+ 0x84bb, 0x84a2, 0x8494, 0x84c7, 0x84cc, 0x849b, 0x84a9, 0x84af,
+ 0x84a8, 0x84d6, 0x8498, 0x84b6, 0x84cf, 0x84a0, 0x84d7, 0x84d4,
+ 0x84d2, 0x84db, 0x84b0, 0x8491, 0x8661, 0x8733, 0x8723, 0x8728,
+ 0x876b, 0x8740, 0x872e, 0x871e, 0x8721, 0x8719, 0x871b, 0x8743,
+ 0x872c, 0x8741, 0x873e, 0x8746, 0x8720, 0x8732, 0x872a, 0x872d,
+ 0x873c, 0x8712, 0x873a, 0x8731, 0x8735, 0x8742, 0x8726, 0x8727,
+ 0x8738, 0x8724, 0x871a, 0x8730, 0x8711, 0x88f7, 0x88e7, 0x88f1,
+ 0x88f2, 0x88fa, 0x88fe, 0x88ee, 0x88fc, 0x88f6, 0x88fb, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x88f0, 0x88ec, 0x88eb, 0x899d, 0x89a1, 0x899f, 0x899e, 0x89e9,
+ 0x89eb, 0x89e8, 0x8aab, 0x8a99, 0x8a8b, 0x8a92, 0x8a8f, 0x8a96,
+ 0x8c3d, 0x8c68, 0x8c69, 0x8cd5, 0x8ccf, 0x8cd7, 0x8d96, 0x8e09,
+ 0x8e02, 0x8dff, 0x8e0d, 0x8dfd, 0x8e0a, 0x8e03, 0x8e07, 0x8e06,
+ 0x8e05, 0x8dfe, 0x8e00, 0x8e04, 0x8f10, 0x8f11, 0x8f0e, 0x8f0d,
+ 0x9123, 0x911c, 0x9120, 0x9122, 0x911f, 0x911d, 0x911a, 0x9124,
+ 0x9121, 0x911b, 0x917a, 0x9172, 0x9179, 0x9173, 0x92a5, 0x92a4,
+ 0x9276, 0x929b, 0x927a, 0x92a0, 0x9294, 0x92aa, 0x928d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x92a6, 0x929a, 0x92ab, 0x9279, 0x9297, 0x927f, 0x92a3,
+ 0x92ee, 0x928e, 0x9282, 0x9295, 0x92a2, 0x927d, 0x9288, 0x92a1,
+ 0x928a, 0x9286, 0x928c, 0x9299, 0x92a7, 0x927e, 0x9287, 0x92a9,
+ 0x929d, 0x928b, 0x922d, 0x969e, 0x96a1, 0x96ff, 0x9758, 0x977d,
+ 0x977a, 0x977e, 0x9783, 0x9780, 0x9782, 0x977b, 0x9784, 0x9781,
+ 0x977f, 0x97ce, 0x97cd, 0x9816, 0x98ad, 0x98ae, 0x9902, 0x9900,
+ 0x9907, 0x999d, 0x999c, 0x99c3, 0x99b9, 0x99bb, 0x99ba, 0x99c2,
+ 0x99bd, 0x99c7, 0x9ab1, 0x9ae3, 0x9ae7, 0x9b3e, 0x9b3f, 0x9b60,
+ 0x9b61, 0x9b5f, 0x9cf1, 0x9cf2, 0x9cf5, 0x9ea7, 0x50ff, 0x5103,
+ 0x5130, 0x50f8, 0x5106, 0x5107, 0x50f6, 0x50fe, 0x510b, 0x510c,
+ 0x50fd, 0x510a, 0x528b, 0x528c, 0x52f1, 0x52ef, 0x5648, 0x5642,
+ 0x564c, 0x5635, 0x5641, 0x564a, 0x5649, 0x5646, 0x5658, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x565a, 0x5640, 0x5633, 0x563d, 0x562c, 0x563e, 0x5638, 0x562a,
+ 0x563a, 0x571a, 0x58ab, 0x589d, 0x58b1, 0x58a0, 0x58a3, 0x58af,
+ 0x58ac, 0x58a5, 0x58a1, 0x58ff, 0x5aff, 0x5af4, 0x5afd, 0x5af7,
+ 0x5af6, 0x5b03, 0x5af8, 0x5b02, 0x5af9, 0x5b01, 0x5b07, 0x5b05,
+ 0x5b0f, 0x5c67, 0x5d99, 0x5d97, 0x5d9f, 0x5d92, 0x5da2, 0x5d93,
+ 0x5d95, 0x5da0, 0x5d9c, 0x5da1, 0x5d9a, 0x5d9e, 0x5e69, 0x5e5d,
+ 0x5e60, 0x5e5c, 0x7df3, 0x5edb, 0x5ede, 0x5ee1, 0x5f49, 0x5fb2,
+ 0x618b, 0x6183, 0x6179, 0x61b1, 0x61b0, 0x61a2, 0x6189, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x619b, 0x6193, 0x61af, 0x61ad, 0x619f, 0x6192, 0x61aa,
+ 0x61a1, 0x618d, 0x6166, 0x61b3, 0x622d, 0x646e, 0x6470, 0x6496,
+ 0x64a0, 0x6485, 0x6497, 0x649c, 0x648f, 0x648b, 0x648a, 0x648c,
+ 0x64a3, 0x649f, 0x6468, 0x64b1, 0x6498, 0x6576, 0x657a, 0x6579,
+ 0x657b, 0x65b2, 0x65b3, 0x66b5, 0x66b0, 0x66a9, 0x66b2, 0x66b7,
+ 0x66aa, 0x66af, 0x6a00, 0x6a06, 0x6a17, 0x69e5, 0x69f8, 0x6a15,
+ 0x69f1, 0x69e4, 0x6a20, 0x69ff, 0x69ec, 0x69e2, 0x6a1b, 0x6a1d,
+ 0x69fe, 0x6a27, 0x69f2, 0x69ee, 0x6a14, 0x69f7, 0x69e7, 0x6a40,
+ 0x6a08, 0x69e6, 0x69fb, 0x6a0d, 0x69fc, 0x69eb, 0x6a09, 0x6a04,
+ 0x6a18, 0x6a25, 0x6a0f, 0x69f6, 0x6a26, 0x6a07, 0x69f4, 0x6a16,
+ 0x6b51, 0x6ba5, 0x6ba3, 0x6ba2, 0x6ba6, 0x6c01, 0x6c00, 0x6bff,
+ 0x6c02, 0x6f41, 0x6f26, 0x6f7e, 0x6f87, 0x6fc6, 0x6f92, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6f8d, 0x6f89, 0x6f8c, 0x6f62, 0x6f4f, 0x6f85, 0x6f5a, 0x6f96,
+ 0x6f76, 0x6f6c, 0x6f82, 0x6f55, 0x6f72, 0x6f52, 0x6f50, 0x6f57,
+ 0x6f94, 0x6f93, 0x6f5d, 0x6f00, 0x6f61, 0x6f6b, 0x6f7d, 0x6f67,
+ 0x6f90, 0x6f53, 0x6f8b, 0x6f69, 0x6f7f, 0x6f95, 0x6f63, 0x6f77,
+ 0x6f6a, 0x6f7b, 0x71b2, 0x71af, 0x719b, 0x71b0, 0x71a0, 0x719a,
+ 0x71a9, 0x71b5, 0x719d, 0x71a5, 0x719e, 0x71a4, 0x71a1, 0x71aa,
+ 0x719c, 0x71a7, 0x71b3, 0x7298, 0x729a, 0x7358, 0x7352, 0x735e,
+ 0x735f, 0x7360, 0x735d, 0x735b, 0x7361, 0x735a, 0x7359, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7362, 0x7487, 0x7489, 0x748a, 0x7486, 0x7481, 0x747d,
+ 0x7485, 0x7488, 0x747c, 0x7479, 0x7508, 0x7507, 0x757e, 0x7625,
+ 0x761e, 0x7619, 0x761d, 0x761c, 0x7623, 0x761a, 0x7628, 0x761b,
+ 0x769c, 0x769d, 0x769e, 0x769b, 0x778d, 0x778f, 0x7789, 0x7788,
+ 0x78cd, 0x78bb, 0x78cf, 0x78cc, 0x78d1, 0x78ce, 0x78d4, 0x78c8,
+ 0x78c3, 0x78c4, 0x78c9, 0x799a, 0x79a1, 0x79a0, 0x799c, 0x79a2,
+ 0x799b, 0x6b76, 0x7a39, 0x7ab2, 0x7ab4, 0x7ab3, 0x7bb7, 0x7bcb,
+ 0x7bbe, 0x7bac, 0x7bce, 0x7baf, 0x7bb9, 0x7bca, 0x7bb5, 0x7cc5,
+ 0x7cc8, 0x7ccc, 0x7ccb, 0x7df7, 0x7ddb, 0x7dea, 0x7de7, 0x7dd7,
+ 0x7de1, 0x7e03, 0x7dfa, 0x7de6, 0x7df6, 0x7df1, 0x7df0, 0x7dee,
+ 0x7ddf, 0x7f76, 0x7fac, 0x7fb0, 0x7fad, 0x7fed, 0x7feb, 0x7fea,
+ 0x7fec, 0x7fe6, 0x7fe8, 0x8064, 0x8067, 0x81a3, 0x819f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x819e, 0x8195, 0x81a2, 0x8199, 0x8197, 0x8216, 0x824f, 0x8253,
+ 0x8252, 0x8250, 0x824e, 0x8251, 0x8524, 0x853b, 0x850f, 0x8500,
+ 0x8529, 0x850e, 0x8509, 0x850d, 0x851f, 0x850a, 0x8527, 0x851c,
+ 0x84fb, 0x852b, 0x84fa, 0x8508, 0x850c, 0x84f4, 0x852a, 0x84f2,
+ 0x8515, 0x84f7, 0x84eb, 0x84f3, 0x84fc, 0x8512, 0x84ea, 0x84e9,
+ 0x8516, 0x84fe, 0x8528, 0x851d, 0x852e, 0x8502, 0x84fd, 0x851e,
+ 0x84f6, 0x8531, 0x8526, 0x84e7, 0x84e8, 0x84f0, 0x84ef, 0x84f9,
+ 0x8518, 0x8520, 0x8530, 0x850b, 0x8519, 0x852f, 0x8662, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8756, 0x8763, 0x8764, 0x8777, 0x87e1, 0x8773, 0x8758,
+ 0x8754, 0x875b, 0x8752, 0x8761, 0x875a, 0x8751, 0x875e, 0x876d,
+ 0x876a, 0x8750, 0x874e, 0x875f, 0x875d, 0x876f, 0x876c, 0x877a,
+ 0x876e, 0x875c, 0x8765, 0x874f, 0x877b, 0x8775, 0x8762, 0x8767,
+ 0x8769, 0x885a, 0x8905, 0x890c, 0x8914, 0x890b, 0x8917, 0x8918,
+ 0x8919, 0x8906, 0x8916, 0x8911, 0x890e, 0x8909, 0x89a2, 0x89a4,
+ 0x89a3, 0x89ed, 0x89f0, 0x89ec, 0x8acf, 0x8ac6, 0x8ab8, 0x8ad3,
+ 0x8ad1, 0x8ad4, 0x8ad5, 0x8abb, 0x8ad7, 0x8abe, 0x8ac0, 0x8ac5,
+ 0x8ad8, 0x8ac3, 0x8aba, 0x8abd, 0x8ad9, 0x8c3e, 0x8c4d, 0x8c8f,
+ 0x8ce5, 0x8cdf, 0x8cd9, 0x8ce8, 0x8cda, 0x8cdd, 0x8ce7, 0x8da0,
+ 0x8d9c, 0x8da1, 0x8d9b, 0x8e20, 0x8e23, 0x8e25, 0x8e24, 0x8e2e,
+ 0x8e15, 0x8e1b, 0x8e16, 0x8e11, 0x8e19, 0x8e26, 0x8e27, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8e14, 0x8e12, 0x8e18, 0x8e13, 0x8e1c, 0x8e17, 0x8e1a, 0x8f2c,
+ 0x8f24, 0x8f18, 0x8f1a, 0x8f20, 0x8f23, 0x8f16, 0x8f17, 0x9073,
+ 0x9070, 0x906f, 0x9067, 0x906b, 0x912f, 0x912b, 0x9129, 0x912a,
+ 0x9132, 0x9126, 0x912e, 0x9185, 0x9186, 0x918a, 0x9181, 0x9182,
+ 0x9184, 0x9180, 0x92d0, 0x92c3, 0x92c4, 0x92c0, 0x92d9, 0x92b6,
+ 0x92cf, 0x92f1, 0x92df, 0x92d8, 0x92e9, 0x92d7, 0x92dd, 0x92cc,
+ 0x92ef, 0x92c2, 0x92e8, 0x92ca, 0x92c8, 0x92ce, 0x92e6, 0x92cd,
+ 0x92d5, 0x92c9, 0x92e0, 0x92de, 0x92e7, 0x92d1, 0x92d3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x92b5, 0x92e1, 0x92c6, 0x92b4, 0x957c, 0x95ac, 0x95ab,
+ 0x95ae, 0x95b0, 0x96a4, 0x96a2, 0x96d3, 0x9705, 0x9708, 0x9702,
+ 0x975a, 0x978a, 0x978e, 0x9788, 0x97d0, 0x97cf, 0x981e, 0x981d,
+ 0x9826, 0x9829, 0x9828, 0x9820, 0x981b, 0x9827, 0x98b2, 0x9908,
+ 0x98fa, 0x9911, 0x9914, 0x9916, 0x9917, 0x9915, 0x99dc, 0x99cd,
+ 0x99cf, 0x99d3, 0x99d4, 0x99ce, 0x99c9, 0x99d6, 0x99d8, 0x99cb,
+ 0x99d7, 0x99cc, 0x9ab3, 0x9aec, 0x9aeb, 0x9af3, 0x9af2, 0x9af1,
+ 0x9b46, 0x9b43, 0x9b67, 0x9b74, 0x9b71, 0x9b66, 0x9b76, 0x9b75,
+ 0x9b70, 0x9b68, 0x9b64, 0x9b6c, 0x9cfc, 0x9cfa, 0x9cfd, 0x9cff,
+ 0x9cf7, 0x9d07, 0x9d00, 0x9cf9, 0x9cfb, 0x9d08, 0x9d05, 0x9d04,
+ 0x9e83, 0x9ed3, 0x9f0f, 0x9f10, 0x511c, 0x5113, 0x5117, 0x511a,
+ 0x5111, 0x51de, 0x5334, 0x53e1, 0x5670, 0x5660, 0x566e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5673, 0x5666, 0x5663, 0x566d, 0x5672, 0x565e, 0x5677, 0x571c,
+ 0x571b, 0x58c8, 0x58bd, 0x58c9, 0x58bf, 0x58ba, 0x58c2, 0x58bc,
+ 0x58c6, 0x5b17, 0x5b19, 0x5b1b, 0x5b21, 0x5b14, 0x5b13, 0x5b10,
+ 0x5b16, 0x5b28, 0x5b1a, 0x5b20, 0x5b1e, 0x5bef, 0x5dac, 0x5db1,
+ 0x5da9, 0x5da7, 0x5db5, 0x5db0, 0x5dae, 0x5daa, 0x5da8, 0x5db2,
+ 0x5dad, 0x5daf, 0x5db4, 0x5e67, 0x5e68, 0x5e66, 0x5e6f, 0x5ee9,
+ 0x5ee7, 0x5ee6, 0x5ee8, 0x5ee5, 0x5f4b, 0x5fbc, 0x619d, 0x61a8,
+ 0x6196, 0x61c5, 0x61b4, 0x61c6, 0x61c1, 0x61cc, 0x61ba, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x61bf, 0x61b8, 0x618c, 0x64d7, 0x64d6, 0x64d0, 0x64cf,
+ 0x64c9, 0x64bd, 0x6489, 0x64c3, 0x64db, 0x64f3, 0x64d9, 0x6533,
+ 0x657f, 0x657c, 0x65a2, 0x66c8, 0x66be, 0x66c0, 0x66ca, 0x66cb,
+ 0x66cf, 0x66bd, 0x66bb, 0x66ba, 0x66cc, 0x6723, 0x6a34, 0x6a66,
+ 0x6a49, 0x6a67, 0x6a32, 0x6a68, 0x6a3e, 0x6a5d, 0x6a6d, 0x6a76,
+ 0x6a5b, 0x6a51, 0x6a28, 0x6a5a, 0x6a3b, 0x6a3f, 0x6a41, 0x6a6a,
+ 0x6a64, 0x6a50, 0x6a4f, 0x6a54, 0x6a6f, 0x6a69, 0x6a60, 0x6a3c,
+ 0x6a5e, 0x6a56, 0x6a55, 0x6a4d, 0x6a4e, 0x6a46, 0x6b55, 0x6b54,
+ 0x6b56, 0x6ba7, 0x6baa, 0x6bab, 0x6bc8, 0x6bc7, 0x6c04, 0x6c03,
+ 0x6c06, 0x6fad, 0x6fcb, 0x6fa3, 0x6fc7, 0x6fbc, 0x6fce, 0x6fc8,
+ 0x6f5e, 0x6fc4, 0x6fbd, 0x6f9e, 0x6fca, 0x6fa8, 0x7004, 0x6fa5,
+ 0x6fae, 0x6fba, 0x6fac, 0x6faa, 0x6fcf, 0x6fbf, 0x6fb8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6fa2, 0x6fc9, 0x6fab, 0x6fcd, 0x6faf, 0x6fb2, 0x6fb0, 0x71c5,
+ 0x71c2, 0x71bf, 0x71b8, 0x71d6, 0x71c0, 0x71c1, 0x71cb, 0x71d4,
+ 0x71ca, 0x71c7, 0x71cf, 0x71bd, 0x71d8, 0x71bc, 0x71c6, 0x71da,
+ 0x71db, 0x729d, 0x729e, 0x7369, 0x7366, 0x7367, 0x736c, 0x7365,
+ 0x736b, 0x736a, 0x747f, 0x749a, 0x74a0, 0x7494, 0x7492, 0x7495,
+ 0x74a1, 0x750b, 0x7580, 0x762f, 0x762d, 0x7631, 0x763d, 0x7633,
+ 0x763c, 0x7635, 0x7632, 0x7630, 0x76bb, 0x76e6, 0x779a, 0x779d,
+ 0x77a1, 0x779c, 0x779b, 0x77a2, 0x77a3, 0x7795, 0x7799, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7797, 0x78dd, 0x78e9, 0x78e5, 0x78ea, 0x78de, 0x78e3,
+ 0x78db, 0x78e1, 0x78e2, 0x78ed, 0x78df, 0x78e0, 0x79a4, 0x7a44,
+ 0x7a48, 0x7a47, 0x7ab6, 0x7ab8, 0x7ab5, 0x7ab1, 0x7ab7, 0x7bde,
+ 0x7be3, 0x7be7, 0x7bdd, 0x7bd5, 0x7be5, 0x7bda, 0x7be8, 0x7bf9,
+ 0x7bd4, 0x7bea, 0x7be2, 0x7bdc, 0x7beb, 0x7bd8, 0x7bdf, 0x7cd2,
+ 0x7cd4, 0x7cd7, 0x7cd0, 0x7cd1, 0x7e12, 0x7e21, 0x7e17, 0x7e0c,
+ 0x7e1f, 0x7e20, 0x7e13, 0x7e0e, 0x7e1c, 0x7e15, 0x7e1a, 0x7e22,
+ 0x7e0b, 0x7e0f, 0x7e16, 0x7e0d, 0x7e14, 0x7e25, 0x7e24, 0x7f43,
+ 0x7f7b, 0x7f7c, 0x7f7a, 0x7fb1, 0x7fef, 0x802a, 0x8029, 0x806c,
+ 0x81b1, 0x81a6, 0x81ae, 0x81b9, 0x81b5, 0x81ab, 0x81b0, 0x81ac,
+ 0x81b4, 0x81b2, 0x81b7, 0x81a7, 0x81f2, 0x8255, 0x8256, 0x8257,
+ 0x8556, 0x8545, 0x856b, 0x854d, 0x8553, 0x8561, 0x8558, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8540, 0x8546, 0x8564, 0x8541, 0x8562, 0x8544, 0x8551, 0x8547,
+ 0x8563, 0x853e, 0x855b, 0x8571, 0x854e, 0x856e, 0x8575, 0x8555,
+ 0x8567, 0x8560, 0x858c, 0x8566, 0x855d, 0x8554, 0x8565, 0x856c,
+ 0x8663, 0x8665, 0x8664, 0x879b, 0x878f, 0x8797, 0x8793, 0x8792,
+ 0x8788, 0x8781, 0x8796, 0x8798, 0x8779, 0x8787, 0x87a3, 0x8785,
+ 0x8790, 0x8791, 0x879d, 0x8784, 0x8794, 0x879c, 0x879a, 0x8789,
+ 0x891e, 0x8926, 0x8930, 0x892d, 0x892e, 0x8927, 0x8931, 0x8922,
+ 0x8929, 0x8923, 0x892f, 0x892c, 0x891f, 0x89f1, 0x8ae0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8ae2, 0x8af2, 0x8af4, 0x8af5, 0x8add, 0x8b14, 0x8ae4,
+ 0x8adf, 0x8af0, 0x8ac8, 0x8ade, 0x8ae1, 0x8ae8, 0x8aff, 0x8aef,
+ 0x8afb, 0x8c91, 0x8c92, 0x8c90, 0x8cf5, 0x8cee, 0x8cf1, 0x8cf0,
+ 0x8cf3, 0x8d6c, 0x8d6e, 0x8da5, 0x8da7, 0x8e33, 0x8e3e, 0x8e38,
+ 0x8e40, 0x8e45, 0x8e36, 0x8e3c, 0x8e3d, 0x8e41, 0x8e30, 0x8e3f,
+ 0x8ebd, 0x8f36, 0x8f2e, 0x8f35, 0x8f32, 0x8f39, 0x8f37, 0x8f34,
+ 0x9076, 0x9079, 0x907b, 0x9086, 0x90fa, 0x9133, 0x9135, 0x9136,
+ 0x9193, 0x9190, 0x9191, 0x918d, 0x918f, 0x9327, 0x931e, 0x9308,
+ 0x931f, 0x9306, 0x930f, 0x937a, 0x9338, 0x933c, 0x931b, 0x9323,
+ 0x9312, 0x9301, 0x9346, 0x932d, 0x930e, 0x930d, 0x92cb, 0x931d,
+ 0x92fa, 0x9325, 0x9313, 0x92f9, 0x92f7, 0x9334, 0x9302, 0x9324,
+ 0x92ff, 0x9329, 0x9339, 0x9335, 0x932a, 0x9314, 0x930c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x930b, 0x92fe, 0x9309, 0x9300, 0x92fb, 0x9316, 0x95bc, 0x95cd,
+ 0x95be, 0x95b9, 0x95ba, 0x95b6, 0x95bf, 0x95b5, 0x95bd, 0x96a9,
+ 0x96d4, 0x970b, 0x9712, 0x9710, 0x9799, 0x9797, 0x9794, 0x97f0,
+ 0x97f8, 0x9835, 0x982f, 0x9832, 0x9924, 0x991f, 0x9927, 0x9929,
+ 0x999e, 0x99ee, 0x99ec, 0x99e5, 0x99e4, 0x99f0, 0x99e3, 0x99ea,
+ 0x99e9, 0x99e7, 0x9ab9, 0x9abf, 0x9ab4, 0x9abb, 0x9af6, 0x9afa,
+ 0x9af9, 0x9af7, 0x9b33, 0x9b80, 0x9b85, 0x9b87, 0x9b7c, 0x9b7e,
+ 0x9b7b, 0x9b82, 0x9b93, 0x9b92, 0x9b90, 0x9b7a, 0x9b95, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9b7d, 0x9b88, 0x9d25, 0x9d17, 0x9d20, 0x9d1e, 0x9d14,
+ 0x9d29, 0x9d1d, 0x9d18, 0x9d22, 0x9d10, 0x9d19, 0x9d1f, 0x9e88,
+ 0x9e86, 0x9e87, 0x9eae, 0x9ead, 0x9ed5, 0x9ed6, 0x9efa, 0x9f12,
+ 0x9f3d, 0x5126, 0x5125, 0x5122, 0x5124, 0x5120, 0x5129, 0x52f4,
+ 0x5693, 0x568c, 0x568d, 0x5686, 0x5684, 0x5683, 0x567e, 0x5682,
+ 0x567f, 0x5681, 0x58d6, 0x58d4, 0x58cf, 0x58d2, 0x5b2d, 0x5b25,
+ 0x5b32, 0x5b23, 0x5b2c, 0x5b27, 0x5b26, 0x5b2f, 0x5b2e, 0x5b7b,
+ 0x5bf1, 0x5bf2, 0x5db7, 0x5e6c, 0x5e6a, 0x5fbe, 0x5fbb, 0x61c3,
+ 0x61b5, 0x61bc, 0x61e7, 0x61e0, 0x61e5, 0x61e4, 0x61e8, 0x61de,
+ 0x64ef, 0x64e9, 0x64e3, 0x64eb, 0x64e4, 0x64e8, 0x6581, 0x6580,
+ 0x65b6, 0x65da, 0x66d2, 0x6a8d, 0x6a96, 0x6a81, 0x6aa5, 0x6a89,
+ 0x6a9f, 0x6a9b, 0x6aa1, 0x6a9e, 0x6a87, 0x6a93, 0x6a8e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6a95, 0x6a83, 0x6aa8, 0x6aa4, 0x6a91, 0x6a7f, 0x6aa6, 0x6a9a,
+ 0x6a85, 0x6a8c, 0x6a92, 0x6b5b, 0x6bad, 0x6c09, 0x6fcc, 0x6fa9,
+ 0x6ff4, 0x6fd4, 0x6fe3, 0x6fdc, 0x6fed, 0x6fe7, 0x6fe6, 0x6fde,
+ 0x6ff2, 0x6fdd, 0x6fe2, 0x6fe8, 0x71e1, 0x71f1, 0x71e8, 0x71f2,
+ 0x71e4, 0x71f0, 0x71e2, 0x7373, 0x736e, 0x736f, 0x7497, 0x74b2,
+ 0x74ab, 0x7490, 0x74aa, 0x74ad, 0x74b1, 0x74a5, 0x74af, 0x7510,
+ 0x7511, 0x7512, 0x750f, 0x7584, 0x7643, 0x7648, 0x7649, 0x7647,
+ 0x76a4, 0x76e9, 0x77b5, 0x77ab, 0x77b2, 0x77b7, 0x77b6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x77b4, 0x77b1, 0x77a8, 0x77f0, 0x78f3, 0x78fd, 0x7902,
+ 0x78fb, 0x78fc, 0x78f2, 0x7905, 0x78f9, 0x78fe, 0x7904, 0x79ab,
+ 0x79a8, 0x7a5c, 0x7a5b, 0x7a56, 0x7a58, 0x7a54, 0x7a5a, 0x7abe,
+ 0x7ac0, 0x7ac1, 0x7c05, 0x7c0f, 0x7bf2, 0x7c00, 0x7bff, 0x7bfb,
+ 0x7c0e, 0x7bf4, 0x7c0b, 0x7bf3, 0x7c02, 0x7c09, 0x7c03, 0x7c01,
+ 0x7bf8, 0x7bfd, 0x7c06, 0x7bf0, 0x7bf1, 0x7c10, 0x7c0a, 0x7ce8,
+ 0x7e2d, 0x7e3c, 0x7e42, 0x7e33, 0x9848, 0x7e38, 0x7e2a, 0x7e49,
+ 0x7e40, 0x7e47, 0x7e29, 0x7e4c, 0x7e30, 0x7e3b, 0x7e36, 0x7e44,
+ 0x7e3a, 0x7f45, 0x7f7f, 0x7f7e, 0x7f7d, 0x7ff4, 0x7ff2, 0x802c,
+ 0x81bb, 0x81c4, 0x81cc, 0x81ca, 0x81c5, 0x81c7, 0x81bc, 0x81e9,
+ 0x825b, 0x825a, 0x825c, 0x8583, 0x8580, 0x858f, 0x85a7, 0x8595,
+ 0x85a0, 0x858b, 0x85a3, 0x857b, 0x85a4, 0x859a, 0x859e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8577, 0x857c, 0x8589, 0x85a1, 0x857a, 0x8578, 0x8557, 0x858e,
+ 0x8596, 0x8586, 0x858d, 0x8599, 0x859d, 0x8581, 0x85a2, 0x8582,
+ 0x8588, 0x8585, 0x8579, 0x8576, 0x8598, 0x8590, 0x859f, 0x8668,
+ 0x87be, 0x87aa, 0x87ad, 0x87c5, 0x87b0, 0x87ac, 0x87b9, 0x87b5,
+ 0x87bc, 0x87ae, 0x87c9, 0x87c3, 0x87c2, 0x87cc, 0x87b7, 0x87af,
+ 0x87c4, 0x87ca, 0x87b4, 0x87b6, 0x87bf, 0x87b8, 0x87bd, 0x87de,
+ 0x87b2, 0x8935, 0x8933, 0x893c, 0x893e, 0x8941, 0x8952, 0x8937,
+ 0x8942, 0x89ad, 0x89af, 0x89ae, 0x89f2, 0x89f3, 0x8b1e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8b18, 0x8b16, 0x8b11, 0x8b05, 0x8b0b, 0x8b22, 0x8b0f,
+ 0x8b12, 0x8b15, 0x8b07, 0x8b0d, 0x8b08, 0x8b06, 0x8b1c, 0x8b13,
+ 0x8b1a, 0x8c4f, 0x8c70, 0x8c72, 0x8c71, 0x8c6f, 0x8c95, 0x8c94,
+ 0x8cf9, 0x8d6f, 0x8e4e, 0x8e4d, 0x8e53, 0x8e50, 0x8e4c, 0x8e47,
+ 0x8f43, 0x8f40, 0x9085, 0x907e, 0x9138, 0x919a, 0x91a2, 0x919b,
+ 0x9199, 0x919f, 0x91a1, 0x919d, 0x91a0, 0x93a1, 0x9383, 0x93af,
+ 0x9364, 0x9356, 0x9347, 0x937c, 0x9358, 0x935c, 0x9376, 0x9349,
+ 0x9350, 0x9351, 0x9360, 0x936d, 0x938f, 0x934c, 0x936a, 0x9379,
+ 0x9357, 0x9355, 0x9352, 0x934f, 0x9371, 0x9377, 0x937b, 0x9361,
+ 0x935e, 0x9363, 0x9367, 0x9380, 0x934e, 0x9359, 0x95c7, 0x95c0,
+ 0x95c9, 0x95c3, 0x95c5, 0x95b7, 0x96ae, 0x96b0, 0x96ac, 0x9720,
+ 0x971f, 0x9718, 0x971d, 0x9719, 0x979a, 0x97a1, 0x979c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x979e, 0x979d, 0x97d5, 0x97d4, 0x97f1, 0x9841, 0x9844, 0x984a,
+ 0x9849, 0x9845, 0x9843, 0x9925, 0x992b, 0x992c, 0x992a, 0x9933,
+ 0x9932, 0x992f, 0x992d, 0x9931, 0x9930, 0x9998, 0x99a3, 0x99a1,
+ 0x9a02, 0x99fa, 0x99f4, 0x99f7, 0x99f9, 0x99f8, 0x99f6, 0x99fb,
+ 0x99fd, 0x99fe, 0x99fc, 0x9a03, 0x9abe, 0x9afe, 0x9afd, 0x9b01,
+ 0x9afc, 0x9b48, 0x9b9a, 0x9ba8, 0x9b9e, 0x9b9b, 0x9ba6, 0x9ba1,
+ 0x9ba5, 0x9ba4, 0x9b86, 0x9ba2, 0x9ba0, 0x9baf, 0x9d33, 0x9d41,
+ 0x9d67, 0x9d36, 0x9d2e, 0x9d2f, 0x9d31, 0x9d38, 0x9d30, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9d45, 0x9d42, 0x9d43, 0x9d3e, 0x9d37, 0x9d40, 0x9d3d,
+ 0x7ff5, 0x9d2d, 0x9e8a, 0x9e89, 0x9e8d, 0x9eb0, 0x9ec8, 0x9eda,
+ 0x9efb, 0x9eff, 0x9f24, 0x9f23, 0x9f22, 0x9f54, 0x9fa0, 0x5131,
+ 0x512d, 0x512e, 0x5698, 0x569c, 0x5697, 0x569a, 0x569d, 0x5699,
+ 0x5970, 0x5b3c, 0x5c69, 0x5c6a, 0x5dc0, 0x5e6d, 0x5e6e, 0x61d8,
+ 0x61df, 0x61ed, 0x61ee, 0x61f1, 0x61ea, 0x61f0, 0x61eb, 0x61d6,
+ 0x61e9, 0x64ff, 0x6504, 0x64fd, 0x64f8, 0x6501, 0x6503, 0x64fc,
+ 0x6594, 0x65db, 0x66da, 0x66db, 0x66d8, 0x6ac5, 0x6ab9, 0x6abd,
+ 0x6ae1, 0x6ac6, 0x6aba, 0x6ab6, 0x6ab7, 0x6ac7, 0x6ab4, 0x6aad,
+ 0x6b5e, 0x6bc9, 0x6c0b, 0x7007, 0x700c, 0x700d, 0x7001, 0x7005,
+ 0x7014, 0x700e, 0x6fff, 0x7000, 0x6ffb, 0x7026, 0x6ffc, 0x6ff7,
+ 0x700a, 0x7201, 0x71ff, 0x71f9, 0x7203, 0x71fd, 0x7376, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x74b8, 0x74c0, 0x74b5, 0x74c1, 0x74be, 0x74b6, 0x74bb, 0x74c2,
+ 0x7514, 0x7513, 0x765c, 0x7664, 0x7659, 0x7650, 0x7653, 0x7657,
+ 0x765a, 0x76a6, 0x76bd, 0x76ec, 0x77c2, 0x77ba, 0x78ff, 0x790c,
+ 0x7913, 0x7914, 0x7909, 0x7910, 0x7912, 0x7911, 0x79ad, 0x79ac,
+ 0x7a5f, 0x7c1c, 0x7c29, 0x7c19, 0x7c20, 0x7c1f, 0x7c2d, 0x7c1d,
+ 0x7c26, 0x7c28, 0x7c22, 0x7c25, 0x7c30, 0x7e5c, 0x7e50, 0x7e56,
+ 0x7e63, 0x7e58, 0x7e62, 0x7e5f, 0x7e51, 0x7e60, 0x7e57, 0x7e53,
+ 0x7fb5, 0x7fb3, 0x7ff7, 0x7ff8, 0x8075, 0x81d1, 0x81d2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x81d0, 0x825f, 0x825e, 0x85b4, 0x85c6, 0x85c0, 0x85c3,
+ 0x85c2, 0x85b3, 0x85b5, 0x85bd, 0x85c7, 0x85c4, 0x85bf, 0x85cb,
+ 0x85ce, 0x85c8, 0x85c5, 0x85b1, 0x85b6, 0x85d2, 0x8624, 0x85b8,
+ 0x85b7, 0x85be, 0x8669, 0x87e7, 0x87e6, 0x87e2, 0x87db, 0x87eb,
+ 0x87ea, 0x87e5, 0x87df, 0x87f3, 0x87e4, 0x87d4, 0x87dc, 0x87d3,
+ 0x87ed, 0x87d8, 0x87e3, 0x87a4, 0x87d7, 0x87d9, 0x8801, 0x87f4,
+ 0x87e8, 0x87dd, 0x8953, 0x894b, 0x894f, 0x894c, 0x8946, 0x8950,
+ 0x8951, 0x8949, 0x8b2a, 0x8b27, 0x8b23, 0x8b33, 0x8b30, 0x8b35,
+ 0x8b47, 0x8b2f, 0x8b3c, 0x8b3e, 0x8b31, 0x8b25, 0x8b37, 0x8b26,
+ 0x8b36, 0x8b2e, 0x8b24, 0x8b3b, 0x8b3d, 0x8b3a, 0x8c42, 0x8c75,
+ 0x8c99, 0x8c98, 0x8c97, 0x8cfe, 0x8d04, 0x8d02, 0x8d00, 0x8e5c,
+ 0x8e62, 0x8e60, 0x8e57, 0x8e56, 0x8e5e, 0x8e65, 0x8e67, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8e5b, 0x8e5a, 0x8e61, 0x8e5d, 0x8e69, 0x8e54, 0x8f46, 0x8f47,
+ 0x8f48, 0x8f4b, 0x9128, 0x913a, 0x913b, 0x913e, 0x91a8, 0x91a5,
+ 0x91a7, 0x91af, 0x91aa, 0x93b5, 0x938c, 0x9392, 0x93b7, 0x939b,
+ 0x939d, 0x9389, 0x93a7, 0x938e, 0x93aa, 0x939e, 0x93a6, 0x9395,
+ 0x9388, 0x9399, 0x939f, 0x938d, 0x93b1, 0x9391, 0x93b2, 0x93a4,
+ 0x93a8, 0x93b4, 0x93a3, 0x93a5, 0x95d2, 0x95d3, 0x95d1, 0x96b3,
+ 0x96d7, 0x96da, 0x5dc2, 0x96df, 0x96d8, 0x96dd, 0x9723, 0x9722,
+ 0x9725, 0x97ac, 0x97ae, 0x97a8, 0x97ab, 0x97a4, 0x97aa, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x97a2, 0x97a5, 0x97d7, 0x97d9, 0x97d6, 0x97d8, 0x97fa,
+ 0x9850, 0x9851, 0x9852, 0x98b8, 0x9941, 0x993c, 0x993a, 0x9a0f,
+ 0x9a0b, 0x9a09, 0x9a0d, 0x9a04, 0x9a11, 0x9a0a, 0x9a05, 0x9a07,
+ 0x9a06, 0x9ac0, 0x9adc, 0x9b08, 0x9b04, 0x9b05, 0x9b29, 0x9b35,
+ 0x9b4a, 0x9b4c, 0x9b4b, 0x9bc7, 0x9bc6, 0x9bc3, 0x9bbf, 0x9bc1,
+ 0x9bb5, 0x9bb8, 0x9bd3, 0x9bb6, 0x9bc4, 0x9bb9, 0x9bbd, 0x9d5c,
+ 0x9d53, 0x9d4f, 0x9d4a, 0x9d5b, 0x9d4b, 0x9d59, 0x9d56, 0x9d4c,
+ 0x9d57, 0x9d52, 0x9d54, 0x9d5f, 0x9d58, 0x9d5a, 0x9e8e, 0x9e8c,
+ 0x9edf, 0x9f01, 0x9f00, 0x9f16, 0x9f25, 0x9f2b, 0x9f2a, 0x9f29,
+ 0x9f28, 0x9f4c, 0x9f55, 0x5134, 0x5135, 0x5296, 0x52f7, 0x53b4,
+ 0x56ab, 0x56ad, 0x56a6, 0x56a7, 0x56aa, 0x56ac, 0x58da, 0x58dd,
+ 0x58db, 0x5912, 0x5b3d, 0x5b3e, 0x5b3f, 0x5dc3, 0x5e70, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5fbf, 0x61fb, 0x6507, 0x6510, 0x650d, 0x6509, 0x650c, 0x650e,
+ 0x6584, 0x65de, 0x65dd, 0x66de, 0x6ae7, 0x6ae0, 0x6acc, 0x6ad1,
+ 0x6ad9, 0x6acb, 0x6adf, 0x6adc, 0x6ad0, 0x6aeb, 0x6acf, 0x6acd,
+ 0x6ade, 0x6b60, 0x6bb0, 0x6c0c, 0x7019, 0x7027, 0x7020, 0x7016,
+ 0x702b, 0x7021, 0x7022, 0x7023, 0x7029, 0x7017, 0x7024, 0x701c,
+ 0x702a, 0x720c, 0x720a, 0x7207, 0x7202, 0x7205, 0x72a5, 0x72a6,
+ 0x72a4, 0x72a3, 0x72a1, 0x74cb, 0x74c5, 0x74b7, 0x74c3, 0x7516,
+ 0x7660, 0x77c9, 0x77ca, 0x77c4, 0x77f1, 0x791d, 0x791b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7921, 0x791c, 0x7917, 0x791e, 0x79b0, 0x7a67, 0x7a68,
+ 0x7c33, 0x7c3c, 0x7c39, 0x7c2c, 0x7c3b, 0x7cec, 0x7cea, 0x7e76,
+ 0x7e75, 0x7e78, 0x7e70, 0x7e77, 0x7e6f, 0x7e7a, 0x7e72, 0x7e74,
+ 0x7e68, 0x7f4b, 0x7f4a, 0x7f83, 0x7f86, 0x7fb7, 0x7ffd, 0x7ffe,
+ 0x8078, 0x81d7, 0x81d5, 0x8264, 0x8261, 0x8263, 0x85eb, 0x85f1,
+ 0x85ed, 0x85d9, 0x85e1, 0x85e8, 0x85da, 0x85d7, 0x85ec, 0x85f2,
+ 0x85f8, 0x85d8, 0x85df, 0x85e3, 0x85dc, 0x85d1, 0x85f0, 0x85e6,
+ 0x85ef, 0x85de, 0x85e2, 0x8800, 0x87fa, 0x8803, 0x87f6, 0x87f7,
+ 0x8809, 0x880c, 0x880b, 0x8806, 0x87fc, 0x8808, 0x87ff, 0x880a,
+ 0x8802, 0x8962, 0x895a, 0x895b, 0x8957, 0x8961, 0x895c, 0x8958,
+ 0x895d, 0x8959, 0x8988, 0x89b7, 0x89b6, 0x89f6, 0x8b50, 0x8b48,
+ 0x8b4a, 0x8b40, 0x8b53, 0x8b56, 0x8b54, 0x8b4b, 0x8b55, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8b51, 0x8b42, 0x8b52, 0x8b57, 0x8c43, 0x8c77, 0x8c76, 0x8c9a,
+ 0x8d06, 0x8d07, 0x8d09, 0x8dac, 0x8daa, 0x8dad, 0x8dab, 0x8e6d,
+ 0x8e78, 0x8e73, 0x8e6a, 0x8e6f, 0x8e7b, 0x8ec2, 0x8f52, 0x8f51,
+ 0x8f4f, 0x8f50, 0x8f53, 0x8fb4, 0x9140, 0x913f, 0x91b0, 0x91ad,
+ 0x93de, 0x93c7, 0x93cf, 0x93c2, 0x93da, 0x93d0, 0x93f9, 0x93ec,
+ 0x93cc, 0x93d9, 0x93a9, 0x93e6, 0x93ca, 0x93d4, 0x93ee, 0x93e3,
+ 0x93d5, 0x93c4, 0x93ce, 0x93c0, 0x93d2, 0x93e7, 0x957d, 0x95da,
+ 0x95db, 0x96e1, 0x9729, 0x972b, 0x972c, 0x9728, 0x9726, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x97b3, 0x97b7, 0x97b6, 0x97dd, 0x97de, 0x97df, 0x985c,
+ 0x9859, 0x985d, 0x9857, 0x98bf, 0x98bd, 0x98bb, 0x98be, 0x9948,
+ 0x9947, 0x9943, 0x99a6, 0x99a7, 0x9a1a, 0x9a15, 0x9a25, 0x9a1d,
+ 0x9a24, 0x9a1b, 0x9a22, 0x9a20, 0x9a27, 0x9a23, 0x9a1e, 0x9a1c,
+ 0x9a14, 0x9ac2, 0x9b0b, 0x9b0a, 0x9b0e, 0x9b0c, 0x9b37, 0x9bea,
+ 0x9beb, 0x9be0, 0x9bde, 0x9be4, 0x9be6, 0x9be2, 0x9bf0, 0x9bd4,
+ 0x9bd7, 0x9bec, 0x9bdc, 0x9bd9, 0x9be5, 0x9bd5, 0x9be1, 0x9bda,
+ 0x9d77, 0x9d81, 0x9d8a, 0x9d84, 0x9d88, 0x9d71, 0x9d80, 0x9d78,
+ 0x9d86, 0x9d8b, 0x9d8c, 0x9d7d, 0x9d6b, 0x9d74, 0x9d75, 0x9d70,
+ 0x9d69, 0x9d85, 0x9d73, 0x9d7b, 0x9d82, 0x9d6f, 0x9d79, 0x9d7f,
+ 0x9d87, 0x9d68, 0x9e94, 0x9e91, 0x9ec0, 0x9efc, 0x9f2d, 0x9f40,
+ 0x9f41, 0x9f4d, 0x9f56, 0x9f57, 0x9f58, 0x5337, 0x56b2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x56b5, 0x56b3, 0x58e3, 0x5b45, 0x5dc6, 0x5dc7, 0x5eee, 0x5eef,
+ 0x5fc0, 0x5fc1, 0x61f9, 0x6517, 0x6516, 0x6515, 0x6513, 0x65df,
+ 0x66e8, 0x66e3, 0x66e4, 0x6af3, 0x6af0, 0x6aea, 0x6ae8, 0x6af9,
+ 0x6af1, 0x6aee, 0x6aef, 0x703c, 0x7035, 0x702f, 0x7037, 0x7034,
+ 0x7031, 0x7042, 0x7038, 0x703f, 0x703a, 0x7039, 0x7040, 0x703b,
+ 0x7033, 0x7041, 0x7213, 0x7214, 0x72a8, 0x737d, 0x737c, 0x74ba,
+ 0x76ab, 0x76aa, 0x76be, 0x76ed, 0x77cc, 0x77ce, 0x77cf, 0x77cd,
+ 0x77f2, 0x7925, 0x7923, 0x7927, 0x7928, 0x7924, 0x7929, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x79b2, 0x7a6e, 0x7a6c, 0x7a6d, 0x7af7, 0x7c49, 0x7c48,
+ 0x7c4a, 0x7c47, 0x7c45, 0x7cee, 0x7e7b, 0x7e7e, 0x7e81, 0x7e80,
+ 0x7fba, 0x7fff, 0x8079, 0x81db, 0x81d9, 0x820b, 0x8268, 0x8269,
+ 0x8622, 0x85ff, 0x8601, 0x85fe, 0x861b, 0x8600, 0x85f6, 0x8604,
+ 0x8609, 0x8605, 0x860c, 0x85fd, 0x8819, 0x8810, 0x8811, 0x8817,
+ 0x8813, 0x8816, 0x8963, 0x8966, 0x89b9, 0x89f7, 0x8b60, 0x8b6a,
+ 0x8b5d, 0x8b68, 0x8b63, 0x8b65, 0x8b67, 0x8b6d, 0x8dae, 0x8e86,
+ 0x8e88, 0x8e84, 0x8f59, 0x8f56, 0x8f57, 0x8f55, 0x8f58, 0x8f5a,
+ 0x908d, 0x9143, 0x9141, 0x91b7, 0x91b5, 0x91b2, 0x91b3, 0x940b,
+ 0x9413, 0x93fb, 0x9420, 0x940f, 0x9414, 0x93fe, 0x9415, 0x9410,
+ 0x9428, 0x9419, 0x940d, 0x93f5, 0x9400, 0x93f7, 0x9407, 0x940e,
+ 0x9416, 0x9412, 0x93fa, 0x9409, 0x93f8, 0x940a, 0x93ff, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x93fc, 0x940c, 0x93f6, 0x9411, 0x9406, 0x95de, 0x95e0, 0x95df,
+ 0x972e, 0x972f, 0x97b9, 0x97bb, 0x97fd, 0x97fe, 0x9860, 0x9862,
+ 0x9863, 0x985f, 0x98c1, 0x98c2, 0x9950, 0x994e, 0x9959, 0x994c,
+ 0x994b, 0x9953, 0x9a32, 0x9a34, 0x9a31, 0x9a2c, 0x9a2a, 0x9a36,
+ 0x9a29, 0x9a2e, 0x9a38, 0x9a2d, 0x9ac7, 0x9aca, 0x9ac6, 0x9b10,
+ 0x9b12, 0x9b11, 0x9c0b, 0x9c08, 0x9bf7, 0x9c05, 0x9c12, 0x9bf8,
+ 0x9c40, 0x9c07, 0x9c0e, 0x9c06, 0x9c17, 0x9c14, 0x9c09, 0x9d9f,
+ 0x9d99, 0x9da4, 0x9d9d, 0x9d92, 0x9d98, 0x9d90, 0x9d9b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9da0, 0x9d94, 0x9d9c, 0x9daa, 0x9d97, 0x9da1, 0x9d9a,
+ 0x9da2, 0x9da8, 0x9d9e, 0x9da3, 0x9dbf, 0x9da9, 0x9d96, 0x9da6,
+ 0x9da7, 0x9e99, 0x9e9b, 0x9e9a, 0x9ee5, 0x9ee4, 0x9ee7, 0x9ee6,
+ 0x9f30, 0x9f2e, 0x9f5b, 0x9f60, 0x9f5e, 0x9f5d, 0x9f59, 0x9f91,
+ 0x513a, 0x5139, 0x5298, 0x5297, 0x56c3, 0x56bd, 0x56be, 0x5b48,
+ 0x5b47, 0x5dcb, 0x5dcf, 0x5ef1, 0x61fd, 0x651b, 0x6b02, 0x6afc,
+ 0x6b03, 0x6af8, 0x6b00, 0x7043, 0x7044, 0x704a, 0x7048, 0x7049,
+ 0x7045, 0x7046, 0x721d, 0x721a, 0x7219, 0x737e, 0x7517, 0x766a,
+ 0x77d0, 0x792d, 0x7931, 0x792f, 0x7c54, 0x7c53, 0x7cf2, 0x7e8a,
+ 0x7e87, 0x7e88, 0x7e8b, 0x7e86, 0x7e8d, 0x7f4d, 0x7fbb, 0x8030,
+ 0x81dd, 0x8618, 0x862a, 0x8626, 0x861f, 0x8623, 0x861c, 0x8619,
+ 0x8627, 0x862e, 0x8621, 0x8620, 0x8629, 0x861e, 0x8625, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8829, 0x881d, 0x881b, 0x8820, 0x8824, 0x881c, 0x882b, 0x884a,
+ 0x896d, 0x8969, 0x896e, 0x896b, 0x89fa, 0x8b79, 0x8b78, 0x8b45,
+ 0x8b7a, 0x8b7b, 0x8d10, 0x8d14, 0x8daf, 0x8e8e, 0x8e8c, 0x8f5e,
+ 0x8f5b, 0x8f5d, 0x9146, 0x9144, 0x9145, 0x91b9, 0x943f, 0x943b,
+ 0x9436, 0x9429, 0x943d, 0x943c, 0x9430, 0x9439, 0x942a, 0x9437,
+ 0x942c, 0x9440, 0x9431, 0x95e5, 0x95e4, 0x95e3, 0x9735, 0x973a,
+ 0x97bf, 0x97e1, 0x9864, 0x98c9, 0x98c6, 0x98c0, 0x9958, 0x9956,
+ 0x9a39, 0x9a3d, 0x9a46, 0x9a44, 0x9a42, 0x9a41, 0x9a3a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9a3f, 0x9acd, 0x9b15, 0x9b17, 0x9b18, 0x9b16, 0x9b3a,
+ 0x9b52, 0x9c2b, 0x9c1d, 0x9c1c, 0x9c2c, 0x9c23, 0x9c28, 0x9c29,
+ 0x9c24, 0x9c21, 0x9db7, 0x9db6, 0x9dbc, 0x9dc1, 0x9dc7, 0x9dca,
+ 0x9dcf, 0x9dbe, 0x9dc5, 0x9dc3, 0x9dbb, 0x9db5, 0x9dce, 0x9db9,
+ 0x9dba, 0x9dac, 0x9dc8, 0x9db1, 0x9dad, 0x9dcc, 0x9db3, 0x9dcd,
+ 0x9db2, 0x9e7a, 0x9e9c, 0x9eeb, 0x9eee, 0x9eed, 0x9f1b, 0x9f18,
+ 0x9f1a, 0x9f31, 0x9f4e, 0x9f65, 0x9f64, 0x9f92, 0x4eb9, 0x56c6,
+ 0x56c5, 0x56cb, 0x5971, 0x5b4b, 0x5b4c, 0x5dd5, 0x5dd1, 0x5ef2,
+ 0x6521, 0x6520, 0x6526, 0x6522, 0x6b0b, 0x6b08, 0x6b09, 0x6c0d,
+ 0x7055, 0x7056, 0x7057, 0x7052, 0x721e, 0x721f, 0x72a9, 0x737f,
+ 0x74d8, 0x74d5, 0x74d9, 0x74d7, 0x766d, 0x76ad, 0x7935, 0x79b4,
+ 0x7a70, 0x7a71, 0x7c57, 0x7c5c, 0x7c59, 0x7c5b, 0x7c5a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7cf4, 0x7cf1, 0x7e91, 0x7f4f, 0x7f87, 0x81de, 0x826b, 0x8634,
+ 0x8635, 0x8633, 0x862c, 0x8632, 0x8636, 0x882c, 0x8828, 0x8826,
+ 0x882a, 0x8825, 0x8971, 0x89bf, 0x89be, 0x89fb, 0x8b7e, 0x8b84,
+ 0x8b82, 0x8b86, 0x8b85, 0x8b7f, 0x8d15, 0x8e95, 0x8e94, 0x8e9a,
+ 0x8e92, 0x8e90, 0x8e96, 0x8e97, 0x8f60, 0x8f62, 0x9147, 0x944c,
+ 0x9450, 0x944a, 0x944b, 0x944f, 0x9447, 0x9445, 0x9448, 0x9449,
+ 0x9446, 0x973f, 0x97e3, 0x986a, 0x9869, 0x98cb, 0x9954, 0x995b,
+ 0x9a4e, 0x9a53, 0x9a54, 0x9a4c, 0x9a4f, 0x9a48, 0x9a4a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9a49, 0x9a52, 0x9a50, 0x9ad0, 0x9b19, 0x9b2b, 0x9b3b,
+ 0x9b56, 0x9b55, 0x9c46, 0x9c48, 0x9c3f, 0x9c44, 0x9c39, 0x9c33,
+ 0x9c41, 0x9c3c, 0x9c37, 0x9c34, 0x9c32, 0x9c3d, 0x9c36, 0x9ddb,
+ 0x9dd2, 0x9dde, 0x9dda, 0x9dcb, 0x9dd0, 0x9ddc, 0x9dd1, 0x9ddf,
+ 0x9de9, 0x9dd9, 0x9dd8, 0x9dd6, 0x9df5, 0x9dd5, 0x9ddd, 0x9eb6,
+ 0x9ef0, 0x9f35, 0x9f33, 0x9f32, 0x9f42, 0x9f6b, 0x9f95, 0x9fa2,
+ 0x513d, 0x5299, 0x58e8, 0x58e7, 0x5972, 0x5b4d, 0x5dd8, 0x882f,
+ 0x5f4f, 0x6201, 0x6203, 0x6204, 0x6529, 0x6525, 0x6596, 0x66eb,
+ 0x6b11, 0x6b12, 0x6b0f, 0x6bca, 0x705b, 0x705a, 0x7222, 0x7382,
+ 0x7381, 0x7383, 0x7670, 0x77d4, 0x7c67, 0x7c66, 0x7e95, 0x826c,
+ 0x863a, 0x8640, 0x8639, 0x863c, 0x8631, 0x863b, 0x863e, 0x8830,
+ 0x8832, 0x882e, 0x8833, 0x8976, 0x8974, 0x8973, 0x89fe, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8b8c, 0x8b8e, 0x8b8b, 0x8b88, 0x8c45, 0x8d19, 0x8e98, 0x8f64,
+ 0x8f63, 0x91bc, 0x9462, 0x9455, 0x945d, 0x9457, 0x945e, 0x97c4,
+ 0x97c5, 0x9800, 0x9a56, 0x9a59, 0x9b1e, 0x9b1f, 0x9b20, 0x9c52,
+ 0x9c58, 0x9c50, 0x9c4a, 0x9c4d, 0x9c4b, 0x9c55, 0x9c59, 0x9c4c,
+ 0x9c4e, 0x9dfb, 0x9df7, 0x9def, 0x9de3, 0x9deb, 0x9df8, 0x9de4,
+ 0x9df6, 0x9de1, 0x9dee, 0x9de6, 0x9df2, 0x9df0, 0x9de2, 0x9dec,
+ 0x9df4, 0x9df3, 0x9de8, 0x9ded, 0x9ec2, 0x9ed0, 0x9ef2, 0x9ef3,
+ 0x9f06, 0x9f1c, 0x9f38, 0x9f37, 0x9f36, 0x9f43, 0x9f4f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9f71, 0x9f70, 0x9f6e, 0x9f6f, 0x56d3, 0x56cd, 0x5b4e,
+ 0x5c6d, 0x652d, 0x66ed, 0x66ee, 0x6b13, 0x705f, 0x7061, 0x705d,
+ 0x7060, 0x7223, 0x74db, 0x74e5, 0x77d5, 0x7938, 0x79b7, 0x79b6,
+ 0x7c6a, 0x7e97, 0x7f89, 0x826d, 0x8643, 0x8838, 0x8837, 0x8835,
+ 0x884b, 0x8b94, 0x8b95, 0x8e9e, 0x8e9f, 0x8ea0, 0x8e9d, 0x91be,
+ 0x91bd, 0x91c2, 0x946b, 0x9468, 0x9469, 0x96e5, 0x9746, 0x9743,
+ 0x9747, 0x97c7, 0x97e5, 0x9a5e, 0x9ad5, 0x9b59, 0x9c63, 0x9c67,
+ 0x9c66, 0x9c62, 0x9c5e, 0x9c60, 0x9e02, 0x9dfe, 0x9e07, 0x9e03,
+ 0x9e06, 0x9e05, 0x9e00, 0x9e01, 0x9e09, 0x9dff, 0x9dfd, 0x9e04,
+ 0x9ea0, 0x9f1e, 0x9f46, 0x9f74, 0x9f75, 0x9f76, 0x56d4, 0x652e,
+ 0x65b8, 0x6b18, 0x6b19, 0x6b17, 0x6b1a, 0x7062, 0x7226, 0x72aa,
+ 0x77d8, 0x77d9, 0x7939, 0x7c69, 0x7c6b, 0x7cf6, 0x7e9a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7e98, 0x7e9b, 0x7e99, 0x81e0, 0x81e1, 0x8646, 0x8647, 0x8648,
+ 0x8979, 0x897a, 0x897c, 0x897b, 0x89ff, 0x8b98, 0x8b99, 0x8ea5,
+ 0x8ea4, 0x8ea3, 0x946e, 0x946d, 0x946f, 0x9471, 0x9473, 0x9749,
+ 0x9872, 0x995f, 0x9c68, 0x9c6e, 0x9c6d, 0x9e0b, 0x9e0d, 0x9e10,
+ 0x9e0f, 0x9e12, 0x9e11, 0x9ea1, 0x9ef5, 0x9f09, 0x9f47, 0x9f78,
+ 0x9f7b, 0x9f7a, 0x9f79, 0x571e, 0x7066, 0x7c6f, 0x883c, 0x8db2,
+ 0x8ea6, 0x91c3, 0x9474, 0x9478, 0x9476, 0x9475, 0x9a60, 0x9c74,
+ 0x9c73, 0x9c71, 0x9c75, 0x9e14, 0x9e13, 0x9ef6, 0x9f0a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9fa4, 0x7068, 0x7065, 0x7cf7, 0x866a, 0x883e, 0x883d,
+ 0x883f, 0x8b9e, 0x8c9c, 0x8ea9, 0x8ec9, 0x974b, 0x9873, 0x9874,
+ 0x98cc, 0x9961, 0x99ab, 0x9a64, 0x9a66, 0x9a67, 0x9b24, 0x9e15,
+ 0x9e17, 0x9f48, 0x6207, 0x6b1e, 0x7227, 0x864c, 0x8ea8, 0x9482,
+ 0x9480, 0x9481, 0x9a69, 0x9a68, 0x9b2e, 0x9e19, 0x7229, 0x864b,
+ 0x8b9f, 0x9483, 0x9c79, 0x9eb7, 0x7675, 0x9a6b, 0x9c7a, 0x9e1d,
+ 0x7069, 0x706a, 0x9ea4, 0x9f7e, 0x9f49, 0x9f98, 0x7881, 0x92b9,
+ 0x88cf, 0x58bb, 0x6052, 0x7ca7, 0x5afa, 0x2554, 0x2566, 0x2557,
+ 0x2560, 0x256c, 0x2563, 0x255a, 0x2569, 0x255d, 0x2552, 0x2564,
+ 0x2555, 0x255e, 0x256a, 0x2561, 0x2558, 0x2567, 0x255b, 0x2553,
+ 0x2565, 0x2556, 0x255f, 0x256b, 0x2562, 0x2559, 0x2568, 0x255c,
+ 0x2551, 0x2550, 0x256d, 0x256e, 0x2570, 0x256f, 0xffed, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe000, 0x92db, 0xe002, 0xe003, 0x854c, 0x42b5, 0x73ef, 0x51b5,
+ 0x3649, 0xe009, 0xe00a, 0x9344, 0xe00c, 0x82ee, 0xe00e, 0x783c,
+ 0x6744, 0x62df, 0xe012, 0xe013, 0xe014, 0xe015, 0xe016, 0x4fab,
+ 0xe018, 0x5008, 0xe01a, 0xe01b, 0xe01c, 0xe01d, 0xe01e, 0x5029,
+ 0xe020, 0x5fa4, 0xe022, 0xe023, 0x6edb, 0xe025, 0x507d, 0x5101,
+ 0x347a, 0x510e, 0x986c, 0x3743, 0x8416, 0xe02d, 0xe02e, 0x5160,
+ 0xe030, 0x516a, 0xe032, 0xe033, 0xe034, 0xe035, 0xe036, 0xe037,
+ 0xe038, 0x5b82, 0x877d, 0xe03b, 0xe03c, 0x51b2, 0x51b8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9d34, 0x51c9, 0x51cf, 0x51d1, 0x3cdc, 0x51d3, 0xe045,
+ 0x51b3, 0x51e2, 0x5342, 0x51ed, 0x83cd, 0x693e, 0xe04c, 0x5f7b,
+ 0x520b, 0x5226, 0x523c, 0x52b5, 0x5257, 0x5294, 0x52b9, 0x52c5,
+ 0x7c15, 0x8542, 0x52e0, 0x860d, 0xe05a, 0x5305, 0xe05c, 0x5549,
+ 0x6ed9, 0xe05f, 0xe060, 0xe061, 0x5333, 0x5344, 0xe064, 0x6ccb,
+ 0xe066, 0x681b, 0x73d5, 0x604a, 0x3eaa, 0x38cc, 0xe06c, 0x71dd,
+ 0x44a2, 0x536d, 0x5374, 0xe071, 0x537e, 0x537f, 0xe074, 0xe075,
+ 0x77e6, 0x5393, 0xe078, 0x53a0, 0x53ab, 0x53ae, 0x73a7, 0xe07d,
+ 0x3f59, 0x739c, 0x53c1, 0x53c5, 0x6c49, 0x4e49, 0x57fe, 0x53d9,
+ 0x3aab, 0xe087, 0x53e0, 0xe089, 0xe08a, 0x53f6, 0xe08c, 0x5413,
+ 0x7079, 0x552b, 0x6657, 0x6d5b, 0x546d, 0xe093, 0xe094, 0x555d,
+ 0x548f, 0x54a4, 0x47a6, 0xe099, 0xe09a, 0x3db4, 0xe09c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe09d, 0xe09e, 0x5547, 0x4ced, 0x542f, 0x7417, 0x5586, 0x55a9,
+ 0x5605, 0xe0a6, 0xe0a7, 0x4552, 0xe0a9, 0x66b3, 0xe0ab, 0x5637,
+ 0x66cd, 0xe0ae, 0x66a4, 0x66ad, 0x564d, 0x564f, 0x78f1, 0x56f1,
+ 0x9787, 0x53fe, 0x5700, 0x56ef, 0x56ed, 0xe0ba, 0x3623, 0xe0bc,
+ 0x5746, 0xe0be, 0x6c6e, 0x708b, 0x5742, 0x36b1, 0xe0c3, 0x57e6,
+ 0xe0c5, 0x5803, 0xe0c7, 0xe0c8, 0x5826, 0xe0ca, 0x585c, 0x58aa,
+ 0x3561, 0x58e0, 0x58dc, 0xe0d0, 0x58fb, 0x5bff, 0x5743, 0xe0d4,
+ 0xe0d5, 0x93d3, 0x35a1, 0x591f, 0x68a6, 0x36c3, 0x6e59, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe0dc, 0x5a24, 0x5553, 0xe0df, 0x8505, 0x59c9, 0xe0e2,
+ 0xe0e3, 0xe0e4, 0xe0e5, 0x59d9, 0xe0e7, 0xe0e8, 0xe0e9, 0x6d71,
+ 0xe0eb, 0xe0ec, 0x59f9, 0xe0ee, 0x5aab, 0x5a63, 0x36e6, 0xe0f2,
+ 0x5a77, 0x3708, 0x5a96, 0x7465, 0x5ad3, 0xe0f8, 0xe0f9, 0x3d85,
+ 0xe0fb, 0x3732, 0xe0fd, 0x5e83, 0x52d0, 0x5b76, 0x6588, 0x5b7c,
+ 0xe103, 0x4004, 0x485d, 0xe106, 0x5bd5, 0x6160, 0xe109, 0xe10a,
+ 0xe10b, 0x5bf3, 0x5b9d, 0x4d10, 0x5c05, 0xe110, 0x5c13, 0x73ce,
+ 0x5c14, 0xe114, 0xe115, 0x5c49, 0x48dd, 0x5c85, 0x5ce9, 0x5cef,
+ 0x5d8b, 0xe11c, 0xe11d, 0x5d10, 0x5d18, 0x5d46, 0xe121, 0x5cba,
+ 0x5dd7, 0x82fc, 0x382d, 0xe126, 0xe127, 0xe128, 0x8287, 0x3836,
+ 0x3bc2, 0x5e2e, 0x6a8a, 0x5e75, 0x5e7a, 0xe130, 0xe131, 0x53a6,
+ 0x4eb7, 0x5ed0, 0x53a8, 0xe136, 0x5e09, 0x5ef4, 0xe139, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5ef9, 0x5efb, 0x38a0, 0x5efc, 0x683e, 0x941b, 0x5f0d, 0xe141,
+ 0xe142, 0x3ade, 0x48ae, 0xe145, 0x5f3a, 0xe147, 0xe148, 0x5f58,
+ 0xe14a, 0x5f63, 0x97bd, 0xe14d, 0x5f72, 0x9340, 0xe150, 0x5fa7,
+ 0x5db6, 0x3d5f, 0xe154, 0xe155, 0xe156, 0xe157, 0x91d6, 0xe159,
+ 0xe15a, 0x6031, 0x6685, 0xe15d, 0x3963, 0x3dc7, 0x3639, 0x5790,
+ 0xe162, 0x7971, 0x3e40, 0x609e, 0x60a4, 0x60b3, 0xe168, 0xe169,
+ 0xe16a, 0x74a4, 0x50e1, 0x5aa0, 0x6164, 0x8424, 0x6142, 0xe171,
+ 0xe172, 0x6181, 0x51f4, 0xe175, 0x6187, 0x5baa, 0xe178, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe179, 0x61d3, 0xe17b, 0xe17c, 0x61d0, 0x3932, 0xe17f,
+ 0xe180, 0x6023, 0x615c, 0x651e, 0x638b, 0xe185, 0x62c5, 0xe187,
+ 0x62d5, 0xe189, 0x636c, 0xe18b, 0x3a17, 0x6438, 0x63f8, 0xe18f,
+ 0xe190, 0x6490, 0x6f8a, 0xe193, 0x9814, 0xe195, 0xe196, 0x64e1,
+ 0x64e5, 0x947b, 0x3a66, 0x643a, 0x3a57, 0x654d, 0x6f16, 0xe19f,
+ 0xe1a0, 0x6585, 0x656d, 0x655f, 0xe1a4, 0x65b5, 0xe1a6, 0x4b37,
+ 0x65d1, 0x40d8, 0xe1aa, 0x65e0, 0x65e3, 0x5fdf, 0xe1ae, 0x6618,
+ 0xe1b0, 0xe1b1, 0x6644, 0xe1b3, 0xe1b4, 0x664b, 0xe1b6, 0x6667,
+ 0xe1b8, 0x6673, 0x6674, 0xe1bb, 0xe1bc, 0xe1bd, 0xe1be, 0xe1bf,
+ 0x77c5, 0xe1c1, 0x99a4, 0x6702, 0xe1c4, 0xe1c5, 0x3b2b, 0x69fa,
+ 0xe1c8, 0x675e, 0x6767, 0x6762, 0xe1cc, 0xe1cd, 0x67d7, 0x44e9,
+ 0x6822, 0x6e50, 0x923c, 0x6801, 0xe1d4, 0xe1d5, 0x685d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe1d7, 0x69e1, 0x6a0b, 0xe1da, 0x6973, 0x68c3, 0xe1dd, 0x6901,
+ 0x6900, 0x3d32, 0x3a01, 0xe1e2, 0x3b80, 0x67ac, 0x6961, 0xe1e6,
+ 0x42fc, 0x6936, 0x6998, 0x3ba1, 0xe1eb, 0x8363, 0x5090, 0x69f9,
+ 0xe1ef, 0xe1f0, 0x6a45, 0xe1f2, 0x6a9d, 0x3bf3, 0x67b1, 0x6ac8,
+ 0xe1f7, 0x3c0d, 0x6b1d, 0xe1fa, 0x60de, 0x6b35, 0x6b74, 0xe1fe,
+ 0x6eb5, 0xe200, 0xe201, 0xe202, 0x3740, 0x5421, 0xe205, 0x6be1,
+ 0xe207, 0x6bdc, 0x6c37, 0xe20a, 0xe20b, 0xe20c, 0x6c5a, 0x8226,
+ 0x6c79, 0xe210, 0x44c5, 0xe212, 0xe213, 0xe214, 0xe215, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe216, 0x36e5, 0x3ceb, 0xe219, 0x9b83, 0xe21b, 0xe21c,
+ 0x7f8f, 0x6837, 0xe21f, 0xe220, 0xe221, 0x6d96, 0x6d5c, 0x6e7c,
+ 0x6f04, 0xe226, 0xe227, 0xe228, 0x8533, 0xe22a, 0x51c7, 0x6c9c,
+ 0x6e1d, 0x842e, 0xe22f, 0x6e2f, 0xe231, 0x7453, 0xe233, 0x79cc,
+ 0x6e4f, 0x5a91, 0xe237, 0x6ff8, 0x370d, 0x6f9d, 0xe23b, 0x6efa,
+ 0xe23d, 0xe23e, 0x4555, 0x93f0, 0x6f44, 0x6f5c, 0x3d4e, 0x6f74,
+ 0xe245, 0x3d3b, 0x6f9f, 0xe248, 0x6fd3, 0xe24a, 0xe24b, 0xe24c,
+ 0xe24d, 0xe24e, 0xe24f, 0x51df, 0xe251, 0xe252, 0xe253, 0xe254,
+ 0x704b, 0x707e, 0x70a7, 0x7081, 0x70cc, 0x70d5, 0x70d6, 0x70df,
+ 0x4104, 0x3de8, 0x71b4, 0x7196, 0xe261, 0x712b, 0x7145, 0x5a88,
+ 0x714a, 0x716e, 0x5c9c, 0xe268, 0x714f, 0x9362, 0xe26b, 0x712c,
+ 0xe26d, 0xe26e, 0xe26f, 0x71ba, 0xe271, 0x70bd, 0x720e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9442, 0x7215, 0x5911, 0x9443, 0x7224, 0x9341, 0xe27a, 0x722e,
+ 0x7240, 0xe27d, 0x68bd, 0x7255, 0x7257, 0x3e55, 0xe282, 0x680d,
+ 0x6f3d, 0x7282, 0x732a, 0x732b, 0xe288, 0xe289, 0x48ed, 0xe28b,
+ 0x7328, 0x732e, 0x73cf, 0x73aa, 0xe290, 0xe291, 0x73c9, 0x7449,
+ 0xe294, 0xe295, 0xe296, 0x6623, 0x36c5, 0xe299, 0xe29a, 0xe29b,
+ 0x73f7, 0x7415, 0x6903, 0xe29f, 0x7439, 0xe2a1, 0x3ed7, 0x745c,
+ 0xe2a4, 0x7460, 0xe2a6, 0x7447, 0x73e4, 0x7476, 0x83b9, 0x746c,
+ 0x3730, 0x7474, 0x93f1, 0x6a2c, 0x7482, 0x4953, 0xe2b2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe2b3, 0xe2b4, 0xe2b5, 0x5b46, 0xe2b7, 0xe2b8, 0x74c8,
+ 0xe2ba, 0x750e, 0x74e9, 0x751e, 0xe2be, 0xe2bf, 0x5bd7, 0xe2c1,
+ 0x9385, 0x754d, 0x754a, 0x7567, 0x756e, 0xe2c7, 0x3f04, 0xe2c9,
+ 0x758e, 0x745d, 0x759e, 0x75b4, 0x7602, 0x762c, 0x7651, 0x764f,
+ 0x766f, 0x7676, 0xe2d4, 0x7690, 0x81ef, 0x37f8, 0xe2d8, 0xe2d9,
+ 0x76a1, 0x76a5, 0x76b7, 0x76cc, 0xe2de, 0x8462, 0xe2e0, 0xe2e1,
+ 0xe2e2, 0x771e, 0x7726, 0x7740, 0x64af, 0xe2e7, 0x7758, 0xe2e9,
+ 0x77af, 0xe2eb, 0xe2ec, 0xe2ed, 0x77f4, 0x7809, 0xe2f0, 0xe2f1,
+ 0x68ca, 0x78af, 0x78c7, 0x78d3, 0x96a5, 0x792e, 0xe2f8, 0x78d7,
+ 0x7934, 0x78b1, 0xe2fc, 0x8fb8, 0x8884, 0xe2ff, 0xe300, 0xe301,
+ 0x7986, 0x8900, 0x6902, 0x7980, 0xe306, 0x799d, 0xe308, 0x793c,
+ 0x79a9, 0x6e2a, 0xe30c, 0x3ea8, 0x79c6, 0xe30f, 0x79d4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x79d4, 0xfefe, 0x00ff, 0x0000, 0x0100, 0x0005, 0x8000, 0x804f240
+};
+
+#ifndef LUA_FF_LIB
+
+static const unsigned short big5hkscs_from_unicode_0[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1b1,
+ 0xc6d8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1c2,
+ 0xa258, 0xa1d3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa150,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8859, 0x8857, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x885d, 0x885b, 0x8866, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8861, 0x885f, 0x0000, 0x0000, 0x0000, 0xa1d1,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x886a, 0x8868, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x886f, 0x886d, 0x88a7, 0x0000, 0x8873, 0x8871, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8877, 0x8875, 0x0000, 0x0000, 0x0000, 0xa1d2,
+ 0xc8fb, 0x887b, 0x8879, 0x0000, 0x88a2, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_1[] = {
+ 0x8856, 0x8867, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x885a, 0x886c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x885c, 0x886e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8870, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xc8fc, 0x885e, 0x8874, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xc8fa, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8878, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8858, 0x8869, 0x0000,
+ 0x8872, 0x8860, 0x8876, 0x0000, 0x887a, 0x0000, 0x887c, 0x0000,
+ 0x887d, 0x0000, 0x887e, 0x0000, 0x88a1, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_2[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xc8f6, 0x886b, 0x0000, 0x0000, 0xc8f8, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xc8f7, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x88a8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xc8fe, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc8f9, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xc8f5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xc8fd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc6d9, 0xa3be,
+ 0x0000, 0xa3bc, 0xa3bd, 0xa3bf, 0x0000, 0xa1c5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa3bb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_3[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa344, 0xa345, 0xa346, 0xa347, 0xa348, 0xa349, 0xa34a,
+ 0xa34b, 0xa34c, 0xa34d, 0xa34e, 0xa34f, 0xa350, 0xa351, 0xa352,
+ 0xa353, 0xa354, 0x0000, 0xa355, 0xa356, 0xa357, 0xa358, 0xa359,
+ 0xa35a, 0xa35b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa35c, 0xa35d, 0xa35e, 0xa35f, 0xa360, 0xa361, 0xa362,
+ 0xa363, 0xa364, 0xa365, 0xa366, 0xa367, 0xa368, 0xa369, 0xa36a,
+ 0xa36b, 0xa36c, 0x0000, 0xa36d, 0xa36e, 0xa36f, 0xa370, 0xa371,
+ 0xa372, 0xa373, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_4[] = {
+ 0x0000, 0xc7f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xc7f3, 0xc7f4, 0xc7f5, 0xc7f6, 0xc7f7, 0xc7f8, 0xc7fa, 0xc7fb,
+ 0xc7fc, 0xc7fd, 0xc7fe, 0xc840, 0xc841, 0xc842, 0xc843, 0xc844,
+ 0xc845, 0xc846, 0xc847, 0xc848, 0xc849, 0xc84a, 0xc84b, 0xc84c,
+ 0xc84d, 0xc84e, 0xc84f, 0xc850, 0xc851, 0xc852, 0xc853, 0xc854,
+ 0xc855, 0xc856, 0xc857, 0xc858, 0xc859, 0xc85a, 0xc85c, 0xc85d,
+ 0xc85e, 0xc85f, 0xc860, 0xc861, 0xc862, 0xc863, 0xc864, 0xc865,
+ 0xc866, 0xc867, 0xc868, 0xc869, 0xc86a, 0xc86b, 0xc86c, 0xc86d,
+ 0xc86e, 0xc86f, 0xc870, 0xc871, 0xc872, 0xc873, 0xc874, 0xc875,
+ 0x0000, 0xc85b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_1e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8863, 0x88a4,
+ 0x8865, 0x88a6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_20[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa156, 0xa158, 0x0000, 0x0000, 0x0000,
+ 0xa1a5, 0xa1a6, 0x0000, 0x0000, 0xa1a7, 0xa1a8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa14c, 0xa14b, 0xa145,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa1ac, 0x0000, 0x0000, 0xa1ab, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa1b0, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_21[] = {
+ 0x0000, 0x0000, 0x0000, 0xa24a, 0x0000, 0xa1c1, 0x0000, 0x0000,
+ 0x0000, 0xa24b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc8d2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc8d3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa2b9, 0xa2ba, 0xa2bb, 0xa2bc, 0xa2bd, 0xa2be, 0xa2bf, 0xa2c0,
+ 0xa2c1, 0xa2c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xc6b5, 0xc6b6, 0xc6b7, 0xc6b8, 0xc6b9, 0xc6ba, 0xc6bb, 0xc6bc,
+ 0xc6bd, 0xc6be, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa1f6, 0xa1f4, 0xa1f7, 0xa1f5, 0x0000, 0x0000, 0xa1f8, 0xa1f9,
+ 0xa1fb, 0xa1fa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xc877, 0xc878, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc876,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_22[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa241, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa1d4, 0x0000, 0x0000, 0x0000, 0xa1db, 0xa1e8,
+ 0xa1e7, 0x0000, 0x0000, 0xa1fd, 0x0000, 0xa1fc, 0x0000, 0x0000,
+ 0x0000, 0xa1e4, 0xa1e5, 0xa1ec, 0x0000, 0x0000, 0xa1ed, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa1ef, 0xa1ee, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa1dc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa1da, 0xa1dd, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1d8, 0xa1d9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1f2, 0x0000, 0x0000,
+ 0x0000, 0xa1f3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1e6, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1e9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_24[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xc6a1, 0xc6a2, 0xc6a3, 0xc6a4, 0xc6a5, 0xc6a6, 0xc6a7, 0xc6a8,
+ 0xc6a9, 0xc6aa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xc6ab, 0xc6ac, 0xc6ad, 0xc6ae,
+ 0xc6af, 0xc6b0, 0xc6b1, 0xc6b2, 0xc6b3, 0xc6b4, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_25[] = {
+ 0xa277, 0x0000, 0xa278, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa27a, 0x0000, 0x0000, 0x0000,
+ 0xa27b, 0x0000, 0x0000, 0x0000, 0xa27c, 0x0000, 0x0000, 0x0000,
+ 0xa27d, 0x0000, 0x0000, 0x0000, 0xa275, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa274, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa273, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa272, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa271, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf9f9, 0xf9f8, 0xf9e6, 0xf9ef, 0xf9dd, 0xf9e8, 0xf9f1, 0xf9df,
+ 0xf9ec, 0xf9f5, 0xf9e3, 0xf9ee, 0xf9f7, 0xf9e5, 0xf9e9, 0xf9f2,
+ 0xf9e0, 0xf9eb, 0xf9f4, 0xf9e2, 0xf9e7, 0xf9f0, 0xf9de, 0xf9ed,
+ 0xf9f6, 0xf9e4, 0xf9ea, 0xf9f3, 0xf9e1, 0xf9fa, 0xf9fb, 0xf9fd,
+ 0xf9fc, 0xa2ac, 0xa2ad, 0xa2ae, 0xa15a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa262, 0xa263, 0xa264, 0xa265, 0xa266, 0xa267, 0xa268,
+ 0xa269, 0xa270, 0xa26f, 0xa26e, 0xa26d, 0xa26c, 0xa26b, 0xa26a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa276, 0xa279, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa1bd, 0xa1bc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa1b6, 0xa1b5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa1bf, 0xa1be, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1bb, 0xa1ba,
+ 0x0000, 0x0000, 0x0000, 0xa1b3, 0x0000, 0x0000, 0xa1b7, 0xa1b4,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa2a8, 0xa2a9, 0xa2ab, 0xa2aa, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_26[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1b9, 0xa1b8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa1f0, 0x0000, 0xa1f1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_27[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc6e6, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_2e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xc8d6, 0x0000, 0x0000, 0x0000, 0xc8d7, 0x0000, 0xc8d8, 0xc8d9,
+ 0xc8da, 0x0000, 0xc8db, 0x0000, 0xc8dc, 0xc8dd, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc8de, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xc8df, 0xc8e0, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc8e1, 0x0000, 0xc8e2,
+ 0x0000, 0x0000, 0xc8e3, 0x0000, 0xc8e4, 0x0000, 0xc8e5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc8e6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xc8e7, 0x0000, 0xc8e8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc8e9, 0x0000,
+ 0x0000, 0x0000, 0xc8ea, 0x0000, 0xc8eb, 0xc8ec, 0x0000, 0xc8ed,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc8ee, 0xc8ef,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc8f0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xc8f1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_2f[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xc6cd, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_30[] = {
+ 0xa140, 0xa142, 0xa143, 0xa1b2, 0x0000, 0xc6e0, 0xc6e1, 0xc6e2,
+ 0xa171, 0xa172, 0xa16d, 0xa16e, 0xa175, 0xa176, 0xa179, 0xa17a,
+ 0xa169, 0xa16a, 0xa245, 0x0000, 0xa165, 0xa166, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1a9, 0xa1aa, 0x0000,
+ 0x0000, 0xa2c3, 0xa2c4, 0xa2c5, 0xa2c6, 0xa2c7, 0xa2c8, 0xa2c9,
+ 0xa2ca, 0xa2cb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc6e7, 0xc6e8, 0xc6e9, 0xc6ea, 0xc6eb, 0xc6ec, 0xc6ed,
+ 0xc6ee, 0xc6ef, 0xc6f0, 0xc6f1, 0xc6f2, 0xc6f3, 0xc6f4, 0xc6f5,
+ 0xc6f6, 0xc6f7, 0xc6f8, 0xc6f9, 0xc6fa, 0xc6fb, 0xc6fc, 0xc6fd,
+ 0xc6fe, 0xc740, 0xc741, 0xc742, 0xc743, 0xc744, 0xc745, 0xc746,
+ 0xc747, 0xc748, 0xc749, 0xc74a, 0xc74b, 0xc74c, 0xc74d, 0xc74e,
+ 0xc74f, 0xc750, 0xc751, 0xc752, 0xc753, 0xc754, 0xc755, 0xc756,
+ 0xc757, 0xc758, 0xc759, 0xc75a, 0xc75b, 0xc75c, 0xc75d, 0xc75e,
+ 0xc75f, 0xc760, 0xc761, 0xc762, 0xc763, 0xc764, 0xc765, 0xc766,
+ 0xc767, 0xc768, 0xc769, 0xc76a, 0xc76b, 0xc76c, 0xc76d, 0xc76e,
+ 0xc76f, 0xc770, 0xc771, 0xc772, 0xc773, 0xc774, 0xc775, 0xc776,
+ 0xc777, 0xc778, 0xc779, 0xc77a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xc8d4, 0xc8d5, 0xc6dc, 0xc6dd, 0x0000,
+ 0x0000, 0xc77b, 0xc77c, 0xc77d, 0xc77e, 0xc7a1, 0xc7a2, 0xc7a3,
+ 0xc7a4, 0xc7a5, 0xc7a6, 0xc7a7, 0xc7a8, 0xc7a9, 0xc7aa, 0xc7ab,
+ 0xc7ac, 0xc7ad, 0xc7ae, 0xc7af, 0xc7b0, 0xc7b1, 0xc7b2, 0xc7b3,
+ 0xc7b4, 0xc7b5, 0xc7b6, 0xc7b7, 0xc7b8, 0xc7b9, 0xc7ba, 0xc7bb,
+ 0xc7bc, 0xc7bd, 0xc7be, 0xc7bf, 0xc7c0, 0xc7c1, 0xc7c2, 0xc7c3,
+ 0xc7c4, 0xc7c5, 0xc7c6, 0xc7c7, 0xc7c8, 0xc7c9, 0xc7ca, 0xc7cb,
+ 0xc7cc, 0xc7cd, 0xc7ce, 0xc7cf, 0xc7d0, 0xc7d1, 0xc7d2, 0xc7d3,
+ 0xc7d4, 0xc7d5, 0xc7d6, 0xc7d7, 0xc7d8, 0xc7d9, 0xc7da, 0xc7db,
+ 0xc7dc, 0xc7dd, 0xc7de, 0xc7df, 0xc7e0, 0xc7e1, 0xc7e2, 0xc7e3,
+ 0xc7e4, 0xc7e5, 0xc7e6, 0xc7e7, 0xc7e8, 0xc7e9, 0xc7ea, 0xc7eb,
+ 0xc7ec, 0xc7ed, 0xc7ee, 0xc7ef, 0xc7f0, 0xc7f1, 0xc7f2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xc6e3, 0xc6da, 0xc6db, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_31[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa374, 0xa375, 0xa376,
+ 0xa377, 0xa378, 0xa379, 0xa37a, 0xa37b, 0xa37c, 0xa37d, 0xa37e,
+ 0xa3a1, 0xa3a2, 0xa3a3, 0xa3a4, 0xa3a5, 0xa3a6, 0xa3a7, 0xa3a8,
+ 0xa3a9, 0xa3aa, 0xa3ab, 0xa3ac, 0xa3ad, 0xa3ae, 0xa3af, 0xa3b0,
+ 0xa3b1, 0xa3b2, 0xa3b3, 0xa3b4, 0xa3b5, 0xa3b6, 0xa3b7, 0xa3b8,
+ 0xa3b9, 0xa3ba, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_32[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc8d1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa1c0, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_33[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa255, 0xa256,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa250, 0xa251, 0xa252, 0x0000,
+ 0x0000, 0xa254, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa257, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa253, 0x0000,
+ 0x0000, 0xa1eb, 0xa1ea, 0x0000, 0x0000, 0xa24f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_34[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9277, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x96df, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x89d5, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x93cd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x9bdf, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xfa68, 0x0000, 0x0000, 0x89da, 0x8f59, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x89db, 0x0000, 0x0000, 0x8f5d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x89dc, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x96f7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8ada, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8bdc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x97db, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9e53,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9daa, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x9bea, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_35[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8a6e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8bc8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x89e8, 0x0000, 0x89ea, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8c4b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xfb70, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x89ed, 0x0000, 0x0000,
+ 0x94dd, 0x0000, 0x89ee, 0x0000, 0x0000, 0x0000, 0x0000, 0x9eb4,
+ 0x8ad3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x92db, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x94db,
+ 0x89f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xfb7a, 0x0000, 0x0000, 0x0000, 0x89fb, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9efc, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x89fc,
+ 0x0000, 0x89bf, 0x0000, 0x0000, 0x0000, 0x89fe, 0x0000, 0x89e6,
+ 0x0000, 0x0000, 0x9d46, 0x0000, 0x0000, 0x0000, 0x9dee, 0x0000,
+ 0x0000, 0x0000, 0xa07e, 0x0000, 0x0000, 0x0000, 0xa068, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x98e9, 0x0000, 0x8b68, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8dfd, 0x8bbe, 0x9fd9, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8aeb, 0x0000, 0x0000, 0x9fd7, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_36[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8b6a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9c5c, 0x0000, 0x8bb1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xfb5e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9df3, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa0d0, 0x0000, 0x0000,
+ 0x0000, 0xfc66, 0x0000, 0x0000, 0x0000, 0x0000, 0x92e9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9aec,
+ 0x8fab, 0xfa48, 0x0000, 0x0000, 0x0000, 0x0000, 0x8e45, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9c6f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9ede, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x89ef, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x96e9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9ebb, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x94de, 0x0000, 0x9eb8, 0x0000, 0x0000, 0x0000,
+ 0x97ba, 0xfb65, 0x0000, 0x0000, 0x0000, 0x95d6, 0x0000, 0x0000,
+ 0x0000, 0x9cbb, 0x0000, 0x0000, 0x97da, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8f45, 0x0000, 0xfb7d, 0x9158, 0xfe64, 0x0000, 0x9856,
+ 0x9b4d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x935b, 0x95c7, 0x0000, 0x97e7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9359, 0x0000, 0x0000,
+ 0x0000, 0x91f5, 0x97b8, 0x0000, 0x0000, 0xfda2, 0xfbb6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x92fa, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_37[] = {
+ 0x0000, 0x9357, 0x0000, 0x8ba6, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfbb9, 0x0000, 0x97b0, 0x0000, 0x0000, 0xfdc4, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9ca1, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x91f2, 0x91f9, 0x0000, 0x8ff1, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9745, 0x9853, 0x0000, 0x0000,
+ 0xfe78, 0x0000, 0xfbc1, 0x9251, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9dad, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfd6c, 0x0000, 0x0000, 0xfa6b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9bc2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9a7b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8b60,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x934b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9abd, 0x0000, 0x0000, 0x0000, 0x0000, 0x91b7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x95b4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfec5, 0x0000, 0x0000, 0x9ef0, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_38[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8d64,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9269, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8d67, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfbea, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfbef, 0x0000,
+ 0x8d68, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x93eb, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfc42, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x9166, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xfacd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x93dd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8bcc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_39[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8d6d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8d6e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x96a8,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xfca6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8d6f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8d70, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xfc64, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9060, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8d74, 0x97c3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8ad0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9274, 0x0000, 0x9bbe, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9cc8, 0x0000, 0x0000, 0x9cba, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8d78, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9eb9, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x955a, 0x0000, 0x0000, 0x91b4, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8a48, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8d7d, 0x0000, 0x0000, 0x8a7d, 0x0000, 0x0000, 0x8ac2, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_3a[] = {
+ 0x0000, 0xfd4a, 0x0000, 0x8da1, 0x0000, 0x0000, 0x8ad1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfcb4,
+ 0x8b47, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x93a4, 0x9eda, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8a51, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8da6, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9ec5, 0x0000, 0x0000, 0x0000, 0x0000, 0xfcc4,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa078, 0x0000, 0x94b5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfcc2, 0x8a6b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8dab,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xfae8, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8dad, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfc49, 0x0000,
+ 0x93c1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x906f, 0x0000, 0x8db0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x947e, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_3b[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x90fa, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9479, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8db2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xfcee, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x997b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8db4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8db7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x91b3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8dbb, 0x8dba, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8dbc, 0x9044, 0x0000, 0x0000, 0x0000,
+ 0xfd4c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x93e4, 0x0000,
+ 0x0000, 0x93e0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xfd53, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8dc3, 0x0000, 0x9bb8, 0x0000,
+ 0x0000, 0x0000, 0xfbf0, 0x0000, 0x93e9, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x93f6,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8dc5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8dca, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8dcc, 0xfd5d, 0x93b5, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_3c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfd61, 0x0000, 0x0000,
+ 0x0000, 0x9cf8, 0x0000, 0x0000, 0x0000, 0x9252, 0x0000, 0x0000,
+ 0xa0e8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9ca5, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8c56, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8dd6, 0x0000, 0x97c0, 0x0000, 0x0000,
+ 0x0000, 0xa0de, 0x0000, 0x0000, 0x0000, 0x0000, 0x97d2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xfaa5, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xfda3, 0x0000, 0x0000, 0x0000, 0x8ddb,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_3d[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8eaf, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x91b5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xfd49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xfdd1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8deb, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x97c6, 0x0000, 0xfdce, 0x0000,
+ 0x0000, 0x90fc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfc59,
+ 0x0000, 0x0000, 0x96d6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x97c5, 0x8def, 0x0000, 0x0000, 0x0000, 0x0000, 0x97d7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8df0, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x96a6, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfbbf, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8df3, 0x0000, 0x0000, 0x0000, 0x0000, 0x9449,
+ 0x0000, 0x8df5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9872, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8e6b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xfafd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8f50,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9dcc, 0xfc65,
+ 0x0000, 0x8c44, 0x0000, 0x0000, 0x996e, 0x94a1, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8f63, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa0da, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9253,
+ 0xfde9, 0x0000, 0x0000, 0x9db5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x9879, 0x0000, 0x0000, 0x0000, 0x9d5d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8d63, 0x9669, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_3e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9f70, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfc6a, 0x0000, 0x0000, 0x8ac7, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x89d7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfe4d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9edd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfefb, 0x98bc, 0xfacc, 0x0000, 0x0000, 0x95b0, 0x0000, 0x0000,
+ 0x0000, 0x9464, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x936f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x94b9,
+ 0x0000, 0x0000, 0x95ec, 0x0000, 0x0000, 0x0000, 0x0000, 0x91ee,
+ 0x0000, 0x0000, 0x98c3, 0x0000, 0x95f6, 0x0000, 0x0000, 0x0000,
+ 0x8ffd, 0x98c5, 0x0000, 0x0000, 0x0000, 0x0000, 0x9766, 0xfe6e,
+ 0x0000, 0x0000, 0x97dd, 0x8caa, 0x0000, 0x0000, 0x92d2, 0x0000,
+ 0x0000, 0x9761, 0x98cb, 0x0000, 0x0000, 0x0000, 0x0000, 0x95f0,
+ 0x0000, 0x975d, 0x0000, 0x91e3, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x98cc, 0x0000, 0x0000, 0x9469, 0x98cd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x98ce, 0x0000, 0x95fc, 0x0000, 0x0000, 0x94a3
+};
+
+static const unsigned short big5hkscs_from_unicode_3f[] = {
+ 0x9662, 0x0000, 0x0000, 0x0000, 0xfeb6, 0x0000, 0x9463, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x98d0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x98d1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9475, 0xfae0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x9472, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x98d6, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8af0, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x98d9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x98db,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x98dd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x98a8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8a6d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8afb, 0x8aae, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_40[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xfbc9, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8c5d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x98e4, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x98e6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x98e8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8a4d, 0x0000, 0x0000, 0x0000, 0x9257,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x95df, 0x0000, 0x0000, 0xa0ac, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x98eb, 0x0000, 0x0000, 0x0000, 0x0000, 0x98ec,
+ 0x0000, 0x8cc3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x98f4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8ab8, 0x0000, 0x0000, 0x0000, 0x9ee7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x94bc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfcd1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9cc6,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9e7e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_41[] = {
+ 0x0000, 0x0000, 0x0000, 0x98fe, 0xfde8, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9940, 0x0000, 0x0000, 0x0000, 0x0000, 0x94c9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x94d3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9946,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x90c0, 0x0000, 0x94d1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9573,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x93c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9948, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x994b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8e55, 0x0000, 0x0000, 0x0000, 0x0000, 0x994e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8efe, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8e59,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x94ec, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_42[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x94ef, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8c60, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8f74, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9955, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9544, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8ccb, 0x0000,
+ 0x0000, 0x0000, 0x9956, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9959, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x995b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8cc4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfa45, 0x0000, 0x0000,
+ 0x0000, 0x90b7, 0x0000, 0x0000, 0x9743, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x95cd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x97c9, 0xfd50, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_43[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8eb9, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x95c6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9967,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8ab9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8dfc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8a76, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9d51,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9973, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9d4f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_44[] = {
+ 0x0000, 0x997a, 0x9564, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x99a1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x99a5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x99a7, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8eed, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x99ad,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x946e,
+ 0x8f70, 0x0000, 0xfad0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x99b3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa053,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x965c, 0x0000, 0x0000, 0x0000, 0x0000, 0xfd7a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x97fe, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x92bd, 0x0000, 0x97fd,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8f64, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xfcf7, 0x9562, 0x97cd, 0x9e64, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x924c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_45[] = {
+ 0x0000, 0x0000, 0x0000, 0x8ec9, 0x99bc, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9da5, 0x0000, 0x8f54, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8f7c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8ea2, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8f7a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x97ae, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x96c8, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x99c3, 0x0000, 0x90d6, 0x0000, 0x9cbe,
+ 0x0000, 0x0000, 0x0000, 0x8f76, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9470, 0xfb4b, 0x0000, 0x0000, 0xfdca, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8ec7, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa0f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8fa9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x99c7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x90d7, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9edf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_46[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x99ce, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8fba,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8feb, 0x0000, 0x99cf,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8fc2, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x92c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x97dc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x95b3,
+ 0x9c79, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x95b2, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_47[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8fdb, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9be3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9e7a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9bee, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x99de, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfafa, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9ee5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8a52, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x99e1, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8a67, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_48[] = {
+ 0x8bb5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8aac, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x99e9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfbca, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x97de, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x95d1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x99f5, 0xfc4a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9ba9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfbdc, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfe56, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x9ea4, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9d49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_49[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x95db, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x89c5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x99f8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9664, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9055, 0x0000, 0x0000, 0x96d4, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x977c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x964d, 0x0000, 0x97e1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9a48, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9a49, 0x0000, 0xfe7d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x90aa, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9a50, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9347, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8ed8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x90c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9a55,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x90bc,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9a58, 0x0000, 0x8bb8,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_4a[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x90d5,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9641, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9a5a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9a5c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x97c2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8abb, 0x0000, 0x0000, 0x0000,
+ 0x9baa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x90f5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9a60, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9145
+};
+
+static const unsigned short big5hkscs_from_unicode_4b[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8c58, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9a63, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8c49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8bb6, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfccf,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x966b,
+ 0x9a6e, 0x0000, 0x914f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x9746, 0x0000, 0x0000, 0xa0e6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x92d7, 0x0000,
+ 0x9675, 0x0000, 0x0000, 0x93d4, 0x0000, 0x0000, 0x91bb, 0x9679,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9a70, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9678, 0x91cd, 0x0000,
+ 0x9c4a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_4c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa06f, 0x0000, 0x0000, 0xa06a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x915f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x9fa5, 0x0000, 0x0000, 0x89ba, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x9ecd, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9a79, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9dce, 0x0000, 0x0000,
+ 0x0000, 0x8cd2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9d73, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x96b9, 0x0000,
+ 0x96bc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9cd1,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x89b7, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9eee, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfb43, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_4d[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9ec9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfbd3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x91ae, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9d78, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9d7b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_4e[] = {
+ 0xa440, 0xa442, 0x0000, 0xa443, 0x9eb3, 0x0000, 0x0000, 0xc945,
+ 0xa456, 0xa454, 0xa457, 0xa455, 0xc946, 0xa4a3, 0xc94f, 0xc94d,
+ 0xa4a2, 0xa4a1, 0x0000, 0x0000, 0xa542, 0xa541, 0xa540, 0x0000,
+ 0xa543, 0xa4fe, 0x9eb2, 0x0000, 0x9dd6, 0x0000, 0xa5e0, 0xa5e1,
+ 0x0000, 0x994f, 0x0000, 0x0000, 0x89ce, 0x0000, 0xa8c3, 0x0000,
+ 0x8bc0, 0x0000, 0x9fc4, 0xa458, 0x8bd4, 0xa4a4, 0xc950, 0x8c72,
+ 0xa4a5, 0xc963, 0xa6ea, 0xcbb1, 0x0000, 0x0000, 0xc6bf, 0x8bf9,
+ 0xa459, 0xa4a6, 0x0000, 0xa544, 0xc964, 0x8946, 0x0000, 0xc6c0,
+ 0x0000, 0x0000, 0xc940, 0xa444, 0x0000, 0xa45b, 0x0000, 0xc947,
+ 0xa45c, 0xfae5, 0x0000, 0xa4a7, 0x0000, 0xa545, 0xa547, 0xa546,
+ 0x0000, 0x0000, 0xa5e2, 0xa5e3, 0x0000, 0x0000, 0xa8c4, 0x0000,
+ 0xadbc, 0xa441, 0xc87b, 0x8bc6, 0xc941, 0xa445, 0xa45e, 0xa45d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa5e4, 0x9c57, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa8c5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9afb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb0ae, 0xd44b,
+ 0x89d0, 0x89cf, 0xb6c3, 0xdcb1, 0xdcb2, 0xc6c1, 0xa446, 0x89d1,
+ 0xa4a9, 0x89e2, 0x0000, 0xa8c6, 0xa447, 0xc948, 0xa45f, 0x0000,
+ 0x0000, 0xa4aa, 0xa4ac, 0xc951, 0xa4ad, 0xa4ab, 0x0000, 0x0000,
+ 0x927e, 0xa5e5, 0x9dba, 0xa8c7, 0x0000, 0x0000, 0xa8c8, 0xab45,
+ 0xc6c2, 0xa460, 0xa4ae, 0x8c6f, 0xa5e6, 0xa5e8, 0xa5e7, 0x0000,
+ 0xa6eb, 0x0000, 0x0000, 0xa8c9, 0xa8ca, 0xab46, 0xab47, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xadbd, 0x0000, 0x0000, 0xdcb3, 0xfbf8,
+ 0x0000, 0xf6d6, 0xa448, 0x8bc7, 0x926b, 0x0000, 0x0000, 0x89d2,
+ 0xa4b0, 0xa4af, 0xc952, 0xa4b1, 0xa4b7, 0x0000, 0xa4b2, 0xa4b3,
+ 0xc954, 0xc953, 0xa4b5, 0xa4b6, 0x0000, 0xa4b4, 0x9fcf, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa54a, 0xa54b, 0xa54c, 0xa54d,
+ 0xa549, 0xa550, 0xc96a, 0x0000, 0xc966, 0xc969, 0xa551, 0xa561,
+ 0x0000, 0xc968, 0x0000, 0xa54e, 0xa54f, 0xa548, 0x0000, 0x0000,
+ 0xc965, 0xc967, 0x9da9, 0x89d3, 0x0000, 0x0000, 0x99e2, 0x0000,
+ 0xa5f5, 0xc9b0, 0xa5f2, 0xa5f6, 0xc9ba, 0xc9ae, 0xa5f3, 0xc9b2,
+ 0x9267, 0x0000, 0x0000, 0xa5f4, 0x0000, 0xa5f7, 0x0000, 0xa5e9
+};
+
+static const unsigned short big5hkscs_from_unicode_4f[] = {
+ 0xc9b1, 0xa5f8, 0xc9b5, 0x92a4, 0xc9b9, 0xc9b6, 0x0000, 0x0000,
+ 0xc9b3, 0xa5ea, 0xa5ec, 0xa5f9, 0x0000, 0xa5ee, 0xc9ab, 0xa5f1,
+ 0xa5ef, 0xa5f0, 0xc9bb, 0xc9b8, 0xc9af, 0xa5ed, 0x0000, 0x8c73,
+ 0xc9ac, 0xa5eb, 0x894e, 0x0000, 0x0000, 0xc9b4, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xc9b7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x894f, 0x9278, 0x0000, 0x0000, 0xc9ad, 0xca66, 0x0000, 0xa742,
+ 0xa6f4, 0x0000, 0x91b6, 0xca67, 0xa6f1, 0x0000, 0xa744, 0x89d4,
+ 0xa6f9, 0x9fd2, 0xa6f8, 0xca5b, 0xa6fc, 0xa6f7, 0xca60, 0xca68,
+ 0x0000, 0xca64, 0x92a7, 0xa6fa, 0x0000, 0x95a2, 0xa6fd, 0xa6ee,
+ 0xa747, 0xca5d, 0x0000, 0x926e, 0xcbbd, 0xa6ec, 0xa743, 0xa6ed,
+ 0xa6f5, 0xa6f6, 0xca62, 0xca5e, 0xa6fb, 0xa6f3, 0xca5a, 0xa6ef,
+ 0xca65, 0xa745, 0xa748, 0xa6f2, 0xa740, 0xa746, 0xa6f0, 0xca63,
+ 0xa741, 0xca69, 0xca5c, 0xa6fe, 0xca5f, 0x0000, 0x0000, 0xca61,
+ 0x0000, 0xa8d8, 0xcbbf, 0xcbcb, 0xa8d0, 0x0000, 0xcbcc, 0xa8cb,
+ 0xa8d5, 0x0000, 0x96ea, 0xa8ce, 0xcbb9, 0xa8d6, 0xcbb8, 0xcbbc,
+ 0xcbc3, 0xcbc1, 0xa8de, 0xa8d9, 0xcbb3, 0xcbb5, 0xa8db, 0xa8cf,
+ 0xcbb6, 0xcbc2, 0xcbc9, 0xa8d4, 0xcbbb, 0xcbb4, 0xa8d3, 0xcbb7,
+ 0xa8d7, 0xcbba, 0x926f, 0xa8d2, 0x0000, 0xa8cd, 0x0000, 0xa8dc,
+ 0xcbc4, 0xa8dd, 0xcbc8, 0x0000, 0xcbc6, 0xcbca, 0xa8da, 0xcbbe,
+ 0xcbb2, 0x0000, 0xcbc0, 0xa8d1, 0xcbc5, 0xa8cc, 0xcbc7, 0x0000,
+ 0x0000, 0x0000, 0x92a3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8950, 0x0000, 0x0000, 0xfa57, 0x0000, 0x0000, 0xab56, 0xab4a,
+ 0x9866, 0x0000, 0xcde0, 0xcde8, 0x0000, 0xab49, 0xab51, 0xab5d,
+ 0x0000, 0xcdee, 0xcdec, 0xcde7, 0x0000, 0x89d6, 0x0000, 0xab4b,
+ 0xcded, 0xcde3, 0xab59, 0xab50, 0xab58, 0xcdde, 0x0000, 0xcdea,
+ 0x98b2, 0xcde1, 0xab54, 0xcde2, 0x92ab, 0xcddd, 0xab5b, 0xab4e,
+ 0xab57, 0xab4d, 0x0000, 0xcddf, 0xcde4, 0x0000, 0xcdeb, 0xab55,
+ 0xab52, 0xcde6, 0xab5a, 0xcde9, 0xcde5, 0xab4f, 0xab5c, 0xab53,
+ 0xab4c, 0xab48, 0x0000, 0x0000, 0x96de, 0x92ac, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xcdef, 0x0000, 0xadd7, 0xadc1,
+ 0x8c70, 0xadd1, 0x9f6e, 0xadd6, 0xd0d0, 0xd0cf, 0xd0d4, 0xd0d5,
+ 0xadc4, 0x8ef2, 0xadcd, 0x0000, 0x0000, 0x9f6c, 0xadda, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_50[] = {
+ 0xadce, 0x0000, 0x0000, 0x89d8, 0x0000, 0xd0c9, 0xadc7, 0xd0ca,
+ 0xfa59, 0xaddc, 0x0000, 0xadd3, 0xadbe, 0xadbf, 0xd0dd, 0xb0bf,
+ 0x0000, 0xadcc, 0xadcb, 0xd0cb, 0xadcf, 0xd45b, 0xadc6, 0xd0d6,
+ 0xadd5, 0xadd4, 0xadca, 0xd0ce, 0xd0d7, 0x0000, 0xd0c8, 0xadc9,
+ 0xd0d8, 0xadd2, 0xd0cc, 0xadc0, 0x0000, 0xadc3, 0xadc2, 0xd0d9,
+ 0xadd0, 0xfa5f, 0xadd9, 0xaddb, 0xd0d3, 0xadd8, 0x92a8, 0xd0db,
+ 0xd0cd, 0xd0dc, 0x0000, 0xd0d1, 0x9163, 0xd0da, 0x0000, 0xd0d2,
+ 0x0000, 0x0000, 0x0000, 0x8c40, 0xadc8, 0x0000, 0x0000, 0x0000,
+ 0xd463, 0xd457, 0x0000, 0xb0b3, 0x0000, 0xd45c, 0xd462, 0xb0b2,
+ 0xd455, 0xb0b6, 0xd459, 0xd452, 0xb0b4, 0xd456, 0xb0b9, 0xb0be,
+ 0x0000, 0xd467, 0x0000, 0xd451, 0x0000, 0xb0ba, 0x9f73, 0xd466,
+ 0x92ad, 0x0000, 0xb0b5, 0xd458, 0xb0b1, 0xd453, 0xd44f, 0xd45d,
+ 0xd450, 0xd44e, 0xd45a, 0xd460, 0xd461, 0xb0b7, 0x9be9, 0x0000,
+ 0xd85b, 0xd45e, 0xd44d, 0xd45f, 0x92a9, 0xb0c1, 0xd464, 0xb0c0,
+ 0xd44c, 0x0000, 0xd454, 0xd465, 0xb0bc, 0xb0bb, 0xb0b8, 0xb0bd,
+ 0x0000, 0x0000, 0xb0af, 0x0000, 0x0000, 0xfa66, 0x0000, 0x0000,
+ 0xb3c8, 0x92aa, 0xd85e, 0xd857, 0x0000, 0xb3c5, 0x0000, 0xd85f,
+ 0x89d9, 0x0000, 0x0000, 0xd855, 0xd858, 0xb3c4, 0xd859, 0x0000,
+ 0xfd56, 0xb3c7, 0xd85d, 0x0000, 0xd853, 0xd852, 0xb3c9, 0x0000,
+ 0xb3ca, 0xb3c6, 0xb3cb, 0xd851, 0xd85c, 0xd85a, 0xd854, 0x0000,
+ 0x0000, 0x0000, 0xb3c3, 0xd856, 0x0000, 0x0000, 0x9fa8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xb6ca, 0xb6c4, 0xdcb7, 0xb6cd,
+ 0xdcbd, 0xdcc0, 0xb6c6, 0xb6c7, 0xdcba, 0xb6c5, 0xdcc3, 0xb6cb,
+ 0xdcc4, 0x0000, 0xdcbf, 0xb6cc, 0x8c71, 0xdcb4, 0xb6c9, 0xdcb5,
+ 0x0000, 0xdcbe, 0xdcbc, 0x0000, 0xdcb8, 0xb6c8, 0xdcb6, 0xb6ce,
+ 0xdcbb, 0xdcc2, 0xdcb9, 0xdcc1, 0x0000, 0x92a1, 0xb9b6, 0xb9b3,
+ 0x90e3, 0xb9b4, 0x0000, 0xe0f9, 0xe0f1, 0xb9b2, 0xb9af, 0xe0f2,
+ 0x0000, 0xa0a6, 0xb9b1, 0xe0f5, 0x0000, 0xe0f7, 0x0000, 0x94ab,
+ 0xe0fe, 0xfc72, 0x0000, 0xe0fd, 0xe0f8, 0xb9ae, 0xe0f0, 0xb9ac,
+ 0xe0f3, 0xb9b7, 0xe0f6, 0x0000, 0xe0fa, 0xb9b0, 0xb9ad, 0xe0fc,
+ 0xe0fb, 0xb9b5, 0x0000, 0xe0f4, 0x97c4, 0xbbf8, 0xe4ec, 0x0000,
+ 0xe4e9, 0xbbf9, 0x0000, 0xbbf7, 0x92ae, 0xe4f0, 0xe4ed, 0xe4e6
+};
+
+static const unsigned short big5hkscs_from_unicode_51[] = {
+ 0xbbf6, 0xfa67, 0xbbfa, 0xe4e7, 0xbbf5, 0xbbfd, 0xe4ea, 0xe4eb,
+ 0xbbfb, 0xbbfc, 0xe4f1, 0xe4ee, 0xe4ef, 0x92a2, 0xfa69, 0x0000,
+ 0xbeaa, 0xe8f8, 0xbea7, 0xe8f5, 0xbea9, 0xbeab, 0x0000, 0xe8f6,
+ 0xbea8, 0x0000, 0xe8f7, 0x0000, 0xe8f4, 0x0000, 0x0000, 0xc076,
+ 0xecbd, 0xc077, 0xecbb, 0x0000, 0xecbc, 0xecba, 0xecb9, 0x0000,
+ 0x0000, 0xecbe, 0xc075, 0x9268, 0x0000, 0xefb8, 0xefb9, 0x0000,
+ 0xe4e8, 0xefb7, 0xc078, 0xc35f, 0xf1eb, 0xf1ec, 0x0000, 0xc4d7,
+ 0xc4d8, 0xf5c1, 0xf5c0, 0xc56c, 0xc56b, 0xf7d0, 0x0000, 0xa449,
+ 0xa461, 0xa4b9, 0x0000, 0xa4b8, 0xa553, 0xa552, 0xa5fc, 0xa5fb,
+ 0xa5fd, 0xa5fa, 0x0000, 0xa74a, 0xa749, 0xa74b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa8e0, 0x0000, 0xa8df, 0xa8e1, 0x8951, 0xab5e,
+ 0x0000, 0xa259, 0xd0de, 0xa25a, 0xb0c2, 0xa25c, 0xa25b, 0xd860,
+ 0xfa6f, 0xa25d, 0xb9b8, 0xa25e, 0x0000, 0xa44a, 0x0000, 0xa4ba,
+ 0xa5fe, 0xa8e2, 0xfa71, 0xa44b, 0xa4bd, 0xa4bb, 0xa4bc, 0x0000,
+ 0x0000, 0xa640, 0x0000, 0x0000, 0x8952, 0xa74c, 0xa8e4, 0xa8e3,
+ 0xa8e5, 0x945a, 0x0000, 0x0000, 0xaddd, 0x0000, 0x0000, 0x0000,
+ 0xbeac, 0x0000, 0xc6c3, 0x0000, 0x0000, 0x0000, 0x89dd, 0xc94e,
+ 0xc8a2, 0xa554, 0xa555, 0x0000, 0x0000, 0xa641, 0x0000, 0xca6a,
+ 0x0000, 0xab60, 0xab5f, 0xd0e0, 0xd0df, 0xb0c3, 0xc6c4, 0xa4be,
+ 0xc955, 0x0000, 0x9e52, 0x0000, 0x8953, 0x0000, 0xcbcd, 0x0000,
+ 0xab61, 0x0000, 0xade0, 0x0000, 0xadde, 0xaddf, 0x0000, 0x9e55,
+ 0x92ba, 0x0000, 0xbead, 0xc6c5, 0xa556, 0x0000, 0x8c5b, 0x0000,
+ 0xa642, 0xc9bc, 0xfa7d, 0xfaa8, 0x9a68, 0xfa47, 0xa74d, 0xa74e,
+ 0xfa7e, 0xca6b, 0x0000, 0x0000, 0xcbce, 0xa8e6, 0xcbcf, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x92bb, 0xd0e2, 0xd0e3, 0xade3, 0xfdb6,
+ 0xd0e4, 0xfaa2, 0xd0e1, 0xade4, 0xade2, 0xade1, 0xd0e5, 0xfaa3,
+ 0xd468, 0xfaa4, 0x9bb4, 0xfaa6, 0xd861, 0x0000, 0x0000, 0xdcc5,
+ 0xe140, 0x0000, 0x0000, 0x89df, 0xbbfe, 0xbeae, 0xe8f9, 0xfddb,
+ 0xa44c, 0xa45a, 0xfaa9, 0x0000, 0x8954, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfaab, 0x0000, 0x0000,
+ 0xb0c4, 0xb3cd, 0x0000, 0xb9b9, 0xfc7a, 0xc942, 0xa4bf, 0x0000,
+ 0xa559, 0xa557, 0xa558, 0x0000, 0x89e0, 0xa8e7, 0x9f4f, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_52[] = {
+ 0xa44d, 0xa44e, 0xc87d, 0xa462, 0x0000, 0x89e1, 0xa4c0, 0xa4c1,
+ 0xa4c2, 0xc9be, 0xa55a, 0xfab0, 0xc96b, 0x0000, 0xa646, 0x0000,
+ 0xc9bf, 0xa644, 0xa645, 0xc9bd, 0x0000, 0x0000, 0xa647, 0xa643,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xca6c, 0xaaec, 0xca6d, 0x9fcd,
+ 0xa0e7, 0xca6e, 0x0000, 0x0000, 0xa750, 0xa74f, 0xfab1, 0x89a6,
+ 0xa753, 0xa751, 0xa752, 0x0000, 0x0000, 0x0000, 0xa8ed, 0x0000,
+ 0xa8ec, 0xcbd4, 0xcbd1, 0xcbd2, 0x9efa, 0xcbd0, 0xa8ee, 0xa8ea,
+ 0xa8e9, 0x0000, 0xa8eb, 0xa8e8, 0xfab2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa8ef, 0x0000, 0xab63, 0xcdf0, 0x0000, 0xcbd3, 0xab68,
+ 0x0000, 0xcdf1, 0xab64, 0xab67, 0xab66, 0xab65, 0xab62, 0x0000,
+ 0x0000, 0x0000, 0xd0e8, 0x0000, 0xade7, 0xd0eb, 0xade5, 0xfab4,
+ 0x0000, 0x92c4, 0xd0e7, 0xade8, 0xade6, 0xade9, 0xd0e9, 0xd0ea,
+ 0x9f6f, 0xd0e6, 0xd0ec, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8bb0, 0xb3d1, 0xb0c5, 0xd469, 0xd46b, 0xd46a, 0xd46c, 0xb0c6,
+ 0x0000, 0x0000, 0xb3ce, 0x9fac, 0xb3cf, 0xb3d0, 0x0000, 0xb6d0,
+ 0xdcc7, 0x89e3, 0xdcc6, 0xdcc8, 0xdcc9, 0xb6d1, 0x0000, 0xb6cf,
+ 0xe141, 0xe142, 0xb9bb, 0xb9ba, 0xe35a, 0x0000, 0x0000, 0xbc40,
+ 0xbc41, 0xbc42, 0xbc44, 0xe4f2, 0xe4f3, 0xbc43, 0x0000, 0x9bd3,
+ 0x89e4, 0xbeaf, 0x0000, 0xbeb0, 0xfab5, 0x0000, 0xf1ed, 0xf5c3,
+ 0xf5c2, 0xf7d1, 0x9fd5, 0xa44f, 0x0000, 0x0000, 0x0000, 0xa55c,
+ 0xa55b, 0x8955, 0x0000, 0xa648, 0x92c5, 0x0000, 0xc9c0, 0x0000,
+ 0x8956, 0xa755, 0xa756, 0xa754, 0xa757, 0xca6f, 0xca70, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfab3, 0x0000, 0x0000,
+ 0x0000, 0xfab6, 0x0000, 0xa8f1, 0xcbd5, 0x0000, 0xa8f0, 0x0000,
+ 0xcdf2, 0xab6c, 0xcdf3, 0xab6b, 0x0000, 0xfab7, 0x0000, 0xab69,
+ 0x0000, 0xab6a, 0x0000, 0x0000, 0x9edc, 0xd0ed, 0x0000, 0x0000,
+ 0xfbc4, 0x9f71, 0xb0c7, 0xd46e, 0x0000, 0xb0ca, 0xd46d, 0xb1e5,
+ 0xb0c9, 0xb0c8, 0x0000, 0xb3d4, 0x0000, 0xb3d3, 0xb3d2, 0xb6d2,
+ 0xfaba, 0x92c7, 0xb6d5, 0xb6d6, 0xb6d4, 0x0000, 0xb6d3, 0x0000,
+ 0x0000, 0xe143, 0x0000, 0xe144, 0x0000, 0x0000, 0x0000, 0xe4f5,
+ 0xbc45, 0xe4f4, 0x0000, 0xbeb1, 0xecbf, 0xc079, 0x0000, 0xf1ee,
+ 0xc455, 0xc6c6, 0xa463, 0xa4c3, 0xc956, 0x0000, 0xa4c4, 0xa4c5
+};
+
+static const unsigned short big5hkscs_from_unicode_53[] = {
+ 0x0000, 0x9a4c, 0x0000, 0x0000, 0x0000, 0xfabd, 0xa55e, 0x0000,
+ 0xa649, 0xca71, 0xcbd6, 0xcbd7, 0x0000, 0xab6d, 0xd0ee, 0xb0cc,
+ 0xb0cb, 0xd863, 0xd862, 0x0000, 0x0000, 0xa450, 0xa4c6, 0xa55f,
+ 0x0000, 0xb0cd, 0xc943, 0x0000, 0xc96c, 0xa560, 0x0000, 0xc9c2,
+ 0xa64b, 0xa64a, 0xc9c1, 0xa758, 0x8c68, 0x0000, 0x0000, 0x89e5,
+ 0x0000, 0x0000, 0xadea, 0x0000, 0x9f7d, 0xd46f, 0x0000, 0xb6d7,
+ 0xe145, 0xb9bc, 0xa0a9, 0xfac4, 0xe8fa, 0x0000, 0x0000, 0xf3fd,
+ 0xc6c7, 0xa4c7, 0x0000, 0x8957, 0xcbd8, 0xcdf4, 0xb0d0, 0xb0ce,
+ 0xb0cf, 0xa451, 0xfaaa, 0xa464, 0xfac5, 0xa4ca, 0x0000, 0xa4c9,
+ 0xa4c8, 0xa563, 0xa562, 0x0000, 0xc96d, 0xc9c3, 0x8958, 0x0000,
+ 0x0000, 0xa8f5, 0xa8f2, 0xa8f4, 0xa8f3, 0x0000, 0x0000, 0xab6e,
+ 0x0000, 0x0000, 0xb3d5, 0x0000, 0xa452, 0x8be3, 0xa4cb, 0x8b61,
+ 0xa565, 0xa564, 0x0000, 0xca72, 0x9af1, 0x0000, 0xa8f6, 0x9eb7,
+ 0x0000, 0xc6c8, 0x0000, 0x0000, 0xc957, 0xfad1, 0xa567, 0xa566,
+ 0xa64c, 0xa64d, 0xca73, 0xa759, 0xfad2, 0xa75a, 0x0000, 0xa8f7,
+ 0xa8f8, 0xa8f9, 0x0000, 0xab6f, 0xcdf5, 0x9eba, 0xfad4, 0xfad5,
+ 0x0000, 0x0000, 0xc944, 0x0000, 0xa4cc, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xc9c4, 0x0000, 0x0000, 0x0000, 0xca74, 0xca75,
+ 0x0000, 0x0000, 0xcbd9, 0xfad9, 0xcbda, 0x0000, 0xcdf7, 0xcdf6,
+ 0xcdf9, 0xcdf8, 0xab70, 0x0000, 0xd470, 0xaded, 0xd0ef, 0xadec,
+ 0xfadb, 0x0000, 0x9ce0, 0x0000, 0xd864, 0xb3d6, 0xfbf7, 0xd865,
+ 0xfbfa, 0x89e7, 0xa07a, 0xfadc, 0xe146, 0xb9bd, 0xfadd, 0x0000,
+ 0x89e9, 0x0000, 0xbc46, 0x0000, 0xf1ef, 0x0000, 0xc6c9, 0x0000,
+ 0x0000, 0xc958, 0x0000, 0xa568, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xfae2, 0x89eb, 0xb0d1, 0x0000, 0xfae3, 0x0000, 0x0000,
+ 0xa453, 0xa465, 0xa4ce, 0xa4cd, 0x90c8, 0xa4cf, 0x0000, 0x0000,
+ 0x92da, 0x8959, 0x9cf5, 0x0000, 0xa8fb, 0x0000, 0xa8fa, 0xa8fc,
+ 0x895a, 0xfae7, 0x9fa2, 0xab71, 0x0000, 0x0000, 0x0000, 0xadee,
+ 0xfaea, 0xe8fb, 0xc24f, 0xa466, 0xa56a, 0xa579, 0xa574, 0x0000,
+ 0xa56f, 0xa56e, 0xa575, 0xa573, 0xa56c, 0xa57a, 0xa56d, 0xa569,
+ 0xa578, 0xa577, 0xa576, 0xa56b, 0x0000, 0xa572, 0xfaed, 0x8fad,
+ 0xa571, 0x0000, 0x0000, 0xa57b, 0xa570, 0x0000, 0xfb59, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_54[] = {
+ 0x0000, 0xa653, 0x0000, 0xa659, 0xa655, 0x0000, 0xa65b, 0xc9c5,
+ 0xa658, 0xa64e, 0xa651, 0xa654, 0xa650, 0xa657, 0xa65a, 0xa64f,
+ 0xa652, 0xa656, 0xa65c, 0xfaef, 0x96ef, 0x0000, 0x9dec, 0x0000,
+ 0xca7e, 0xca7b, 0x9dca, 0xa767, 0xca7c, 0xa75b, 0xa75d, 0xa775,
+ 0xa770, 0xfd6d, 0x0000, 0x89ec, 0xcaa5, 0xca7d, 0xa75f, 0xa761,
+ 0xcaa4, 0xa768, 0xca78, 0xa774, 0xa776, 0xa75c, 0xa76d, 0xfb44,
+ 0xca76, 0xa773, 0x9de2, 0xa764, 0x8c75, 0xa76e, 0xa76f, 0xca77,
+ 0xa76c, 0xa76a, 0x0000, 0xa76b, 0xa771, 0xcaa1, 0xa75e, 0x0000,
+ 0xa772, 0xcaa3, 0xa766, 0xa763, 0x0000, 0xca7a, 0xa762, 0xcaa6,
+ 0xa765, 0x0000, 0xa769, 0x9ec0, 0x0000, 0x9e56, 0xa760, 0xcaa2,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xca79, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xcbeb, 0xcbea, 0xa94f, 0xcbed, 0xcbef, 0xcbe4, 0xcbe7, 0xcbee,
+ 0xa950, 0x9f79, 0x9ac7, 0xcbe1, 0xcbe5, 0xfaf4, 0x0000, 0xcbe9,
+ 0xce49, 0xa94b, 0xce4d, 0xa8fd, 0xcbe6, 0xa8fe, 0xa94c, 0xa945,
+ 0xa941, 0x0000, 0xcbe2, 0xa944, 0xa949, 0xa952, 0xcbe3, 0xcbdc,
+ 0xa943, 0xcbdd, 0xcbdf, 0x0000, 0xa946, 0x98a1, 0xa948, 0xcbdb,
+ 0xcbe0, 0x0000, 0x0000, 0xa951, 0xa94d, 0xcbe8, 0xa953, 0xfaf8,
+ 0xa94a, 0xcbde, 0xa947, 0x89f0, 0x9e47, 0xa942, 0xa940, 0x9df7,
+ 0xcbec, 0x0000, 0xa94e, 0x0000, 0x9fd3, 0x0000, 0x9aca, 0x0000,
+ 0xce48, 0xcdfb, 0xce4b, 0x89f1, 0xfaf9, 0xcdfd, 0xab78, 0xaba8,
+ 0xab74, 0xaba7, 0xab7d, 0xaba4, 0xab72, 0xcdfc, 0xce43, 0xaba3,
+ 0xce4f, 0xaba5, 0x8e5a, 0xab79, 0x89f2, 0x0000, 0xce45, 0xce42,
+ 0xab77, 0x89f3, 0xcdfa, 0xaba6, 0xce4a, 0xab7c, 0xce4c, 0xaba9,
+ 0xab73, 0xab7e, 0xab7b, 0xce40, 0xaba1, 0xce46, 0xce47, 0xab7a,
+ 0xaba2, 0xab76, 0x0000, 0x925d, 0x8b51, 0x92e0, 0xab75, 0xcdfe,
+ 0x89f4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xce44, 0x0000,
+ 0x0000, 0x0000, 0x9fd4, 0x0000, 0x0000, 0x0000, 0xce4e, 0x0000,
+ 0xd144, 0xadfb, 0xd0f1, 0x8a79, 0xd0f6, 0xadf4, 0xae40, 0xd0f4,
+ 0xadef, 0xadf9, 0xadfe, 0xd0fb, 0x0000, 0xadfa, 0xadfd, 0x89f5,
+ 0x0000, 0xd0fe, 0xadf5, 0xd0f5, 0x0000, 0x0000, 0x0000, 0xd142,
+ 0xd143, 0x0000, 0xadf7, 0xd141, 0xadf3, 0xae43, 0x0000, 0xd0f8
+};
+
+static const unsigned short big5hkscs_from_unicode_55[] = {
+ 0x0000, 0xadf1, 0x97a7, 0xd146, 0xd0f9, 0xd0fd, 0xadf6, 0xae42,
+ 0xd0fa, 0xadfc, 0xd140, 0xd147, 0xd4a1, 0x93ba, 0xd145, 0xae44,
+ 0xadf0, 0xd0fc, 0xd0f3, 0x9e58, 0xadf8, 0x0000, 0x0000, 0xd0f2,
+ 0x89f6, 0x0000, 0xd0f7, 0x0000, 0x0000, 0x0000, 0x9e57, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x89f7, 0x0000, 0x8a41, 0xd0f0, 0xae41,
+ 0x89f8, 0x0000, 0xd477, 0xfaf1, 0xb0e4, 0xd4a7, 0xb0e2, 0xb0df,
+ 0xd47c, 0xb0db, 0xd4a2, 0xb0e6, 0xd476, 0xd47b, 0xd47a, 0xadf2,
+ 0xb0e1, 0xd4a5, 0x0000, 0xd4a8, 0xd473, 0x0000, 0xb3e8, 0x89fa,
+ 0xd4a9, 0xb0e7, 0x0000, 0xb0d9, 0xb0d6, 0xd47e, 0xb0d3, 0xfb42,
+ 0xd4a6, 0xfabf, 0xb0da, 0xd4aa, 0x0000, 0xd474, 0xd4a4, 0xb0dd,
+ 0xd475, 0xd478, 0xd47d, 0xfba3, 0x0000, 0xb0de, 0xb0dc, 0xb0e8,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xb0e3, 0xfaf7, 0xb0d7, 0xb1d2,
+ 0x0000, 0xb0d8, 0xd479, 0xb0e5, 0xb0e0, 0xd4a3, 0xb0d5, 0x0000,
+ 0x0000, 0x9e4e, 0xb0d4, 0x94dc, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x95da, 0x9df8, 0x9f6a, 0x0000, 0xd471, 0xd472, 0xd86a,
+ 0x0000, 0x8ab7, 0x0000, 0xb3d7, 0xb3da, 0xd875, 0xb3ee, 0xd878,
+ 0xb3d8, 0xd871, 0xb3de, 0xb3e4, 0xb5bd, 0x0000, 0xfb46, 0xb3e2,
+ 0xd86e, 0xb3ef, 0xb3db, 0xb3e3, 0xd876, 0xdcd7, 0xd87b, 0xd86f,
+ 0x8a46, 0xd866, 0xd873, 0xd86d, 0xb3e1, 0xd879, 0x0000, 0x0000,
+ 0xb3dd, 0xb3f1, 0xb3ea, 0x0000, 0xb3df, 0xb3dc, 0x0000, 0xb3e7,
+ 0x0000, 0xd87a, 0xd86c, 0xd872, 0xd874, 0xd868, 0xd877, 0xb3d9,
+ 0xd867, 0xfb47, 0xb3e0, 0xb3f0, 0xb3ec, 0xd869, 0xb3e6, 0x0000,
+ 0x9148, 0xb3ed, 0xb3e9, 0xb3e5, 0x92de, 0xd870, 0x0000, 0x0000,
+ 0x0000, 0x8b53, 0x9df6, 0xb3eb, 0x9bda, 0x0000, 0x0000, 0xdcd5,
+ 0xdcd1, 0x9d7e, 0xdce0, 0xdcca, 0xdcd3, 0xb6e5, 0xb6e6, 0xb6de,
+ 0xdcdc, 0xb6e8, 0xdccf, 0xdcce, 0xdccc, 0xdcde, 0xb6dc, 0xdcd8,
+ 0xdccd, 0xb6df, 0xdcd6, 0xb6da, 0xdcd2, 0xdcd9, 0xdcdb, 0x89fd,
+ 0x99e4, 0xdcdf, 0xb6e3, 0xdccb, 0xb6dd, 0xdcd0, 0x9e43, 0xb6d8,
+ 0x0000, 0xb6e4, 0xdcda, 0xb6e0, 0xb6e1, 0xb6e7, 0xb6db, 0xa25f,
+ 0xb6d9, 0xdcd4, 0x9de9, 0x0000, 0x8f52, 0x0000, 0x0000, 0xb6e2,
+ 0x9df5, 0x9df0, 0xdcdd, 0x0000, 0x0000, 0x99e7, 0xb9cd, 0xb9c8,
+ 0x0000, 0xe155, 0xe151, 0x8bbd, 0xe14b, 0xb9c2, 0xb9be, 0xe154
+};
+
+static const unsigned short big5hkscs_from_unicode_56[] = {
+ 0xb9bf, 0xe14e, 0xe150, 0x0000, 0xe153, 0xfb48, 0xb9c4, 0x0000,
+ 0xb9cb, 0xb9c5, 0x0000, 0x0000, 0xe149, 0xb9c6, 0xb9c7, 0xe14c,
+ 0xb9cc, 0x9fb7, 0xe14a, 0xe14f, 0xb9c3, 0xe148, 0xb9c9, 0xb9c1,
+ 0x0000, 0x0000, 0x0000, 0xb9c0, 0xe14d, 0xe152, 0x9dd0, 0xb9ca,
+ 0x9feb, 0x8da9, 0x9dcf, 0x98e1, 0x0000, 0x9de5, 0x0000, 0xe147,
+ 0x0000, 0xbc4d, 0xe547, 0x0000, 0xe544, 0x9dc8, 0xbc47, 0xbc53,
+ 0xbc54, 0x0000, 0xbc4a, 0xe542, 0xbc4c, 0xe4f9, 0xbc52, 0xfb4f,
+ 0xe546, 0xbc49, 0xe548, 0xbc48, 0x0000, 0xe543, 0xe545, 0xbc4b,
+ 0xe541, 0xe4fa, 0xe4f7, 0x9deb, 0x0000, 0xd86b, 0xe4fd, 0x0000,
+ 0xe4f6, 0xe4fc, 0xe4fb, 0x0000, 0xe4f8, 0xfb54, 0xbc4f, 0xfb55,
+ 0x9aa2, 0x0000, 0x8ad6, 0xbc4e, 0x9a5f, 0x0000, 0x0000, 0xbc50,
+ 0xe4fe, 0xbeb2, 0xe540, 0x0000, 0x0000, 0x9ef5, 0xe945, 0x0000,
+ 0xe8fd, 0x8fb7, 0xbebe, 0xe942, 0xbeb6, 0xbeba, 0xe941, 0x0000,
+ 0xbeb9, 0xbeb5, 0xbeb8, 0xbeb3, 0xbebd, 0xe943, 0xe8fe, 0xbebc,
+ 0xe8fc, 0xbebb, 0xe944, 0xe940, 0xbc51, 0x0000, 0xbebf, 0xe946,
+ 0xbeb7, 0xbeb4, 0x9ad2, 0x9e6a, 0x9ee8, 0x0000, 0xecc6, 0xecc8,
+ 0xc07b, 0xecc9, 0xecc7, 0xecc5, 0xecc4, 0xc07d, 0xecc3, 0xc07e,
+ 0x0000, 0x8bbf, 0x91c2, 0x9d62, 0xecc1, 0xecc2, 0xc07a, 0xc0a1,
+ 0xc07c, 0x0000, 0x9260, 0xecc0, 0x0000, 0xc250, 0x0000, 0xefbc,
+ 0xefba, 0xefbf, 0xefbd, 0x0000, 0xefbb, 0xefbe, 0x925e, 0x91c1,
+ 0x0000, 0x8ac5, 0x0000, 0x0000, 0x97a3, 0xc360, 0xf1f2, 0xf1f3,
+ 0xc456, 0x0000, 0xf1f4, 0xf1f0, 0xf1f5, 0xf1f1, 0xc251, 0x8b6c,
+ 0x0000, 0x8d7e, 0xf3fe, 0xf441, 0xc459, 0xf440, 0xc458, 0xc457,
+ 0x0000, 0x9c54, 0x0000, 0x0000, 0xc45a, 0xf5c5, 0xf5c6, 0x9dbd,
+ 0xc4da, 0xc4d9, 0xc4db, 0xf5c4, 0x0000, 0xf6d8, 0xf6d7, 0x0000,
+ 0xc56d, 0xc56f, 0xc56e, 0xf6d9, 0xc5c8, 0xf8a6, 0x0000, 0x0000,
+ 0x0000, 0xc5f1, 0x0000, 0xf8a5, 0xf8ee, 0x0000, 0x9cc5, 0xc949,
+ 0x0000, 0x0000, 0xa57d, 0xa57c, 0x0000, 0xa65f, 0xa65e, 0xc9c7,
+ 0xa65d, 0xc9c6, 0x895b, 0x0000, 0xa779, 0xcaa9, 0x0000, 0xcaa8,
+ 0x0000, 0x0000, 0xa777, 0xa77a, 0x0000, 0xfb5c, 0xcaa7, 0xfb5b,
+ 0xa778, 0xfb57, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xcbf0,
+ 0x0000, 0xcbf1, 0xa954, 0x0000, 0x0000, 0x98c7, 0x0000, 0xabaa
+};
+
+static const unsigned short big5hkscs_from_unicode_57[] = {
+ 0xfb5a, 0xd148, 0xd149, 0xae45, 0xae46, 0x0000, 0x0000, 0xd4ac,
+ 0xb0e9, 0xb0eb, 0xd4ab, 0xb0ea, 0xd87c, 0xb3f2, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xb6e9, 0xb6ea, 0xdce1, 0x9cee, 0xb9cf, 0x0000,
+ 0xb9ce, 0x0000, 0xe549, 0xe948, 0xe947, 0x92e2, 0xf96b, 0xa467,
+ 0xc959, 0x0000, 0xc96e, 0xc96f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa662, 0xa666, 0xc9c9, 0x0000, 0xa664, 0xa663, 0xc9c8, 0xa665,
+ 0xa661, 0x0000, 0x94a7, 0xa660, 0xc9ca, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa7a6, 0x0000, 0x8ccc, 0xa7a3, 0x9bd4,
+ 0xa77d, 0xcaaa, 0xfb64, 0xfb76, 0x0000, 0xcaab, 0xfb60, 0xa7a1,
+ 0x0000, 0xcaad, 0xa77b, 0xcaae, 0xcaac, 0xa77e, 0xa7a2, 0xa7a5,
+ 0xa7a4, 0xa77c, 0xcaaf, 0x0000, 0x99e5, 0x0000, 0x0000, 0x9ac2,
+ 0x0000, 0x0000, 0x0000, 0x91fb, 0x0000, 0x0000, 0x0000, 0xa073,
+ 0x0000, 0xa959, 0xcbfe, 0x0000, 0xa95b, 0x0000, 0xa95a, 0x9f72,
+ 0xcc40, 0xa958, 0xa957, 0xcbf5, 0x0000, 0xcbf4, 0x0000, 0xcbf2,
+ 0xcbf7, 0xcbf6, 0xcbf3, 0xcbfc, 0xcbfd, 0xcbfa, 0xcbf8, 0xa956,
+ 0x0000, 0x0000, 0x9fcc, 0xcbfb, 0xa95c, 0xcc41, 0x98a5, 0x92e8,
+ 0xcbf9, 0x0000, 0xabab, 0xa955, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9bbc, 0x0000, 0x96f3, 0xabac, 0xce54, 0x92e7, 0x0000, 0xce5a,
+ 0xfc67, 0x0000, 0x0000, 0xabb2, 0xce58, 0xce5e, 0x0000, 0xce55,
+ 0xce59, 0xce5b, 0xce5d, 0xce57, 0x8b7d, 0xce56, 0xce51, 0xce52,
+ 0xabad, 0x9bf4, 0xabaf, 0xabae, 0xce53, 0xce5c, 0x0000, 0x9ef7,
+ 0x0000, 0x0000, 0x9ec1, 0x0000, 0x0000, 0x0000, 0xabb1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x996f, 0xce50, 0xd153, 0x0000,
+ 0xd152, 0xd157, 0xd14e, 0x96f1, 0xd151, 0xd150, 0x8e41, 0xd154,
+ 0x0000, 0xd158, 0xae47, 0xae4a, 0x954a, 0x0000, 0xd14f, 0xd155,
+ 0x97e6, 0x0000, 0x0000, 0xae49, 0xd14a, 0x0000, 0xabb0, 0xd4ba,
+ 0xd156, 0x0000, 0xd14d, 0x0000, 0xae48, 0xd14c, 0x0000, 0x96f5,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd4b1, 0x92e6, 0x9f42, 0xb0ec,
+ 0xb0f0, 0xd4c1, 0xd4af, 0xd4bd, 0xb0f1, 0xd4bf, 0xfb67, 0xd4c5,
+ 0x0000, 0xd4c9, 0x0000, 0x0000, 0xd4c0, 0xd4b4, 0xd4bc, 0x99a9,
+ 0xd4ca, 0xd4c8, 0xd4be, 0xd4b9, 0xd4b2, 0xd8a6, 0xd4b0, 0xb0f5,
+ 0xd4b7, 0xb0f6, 0xb0f2, 0xd4ad, 0xd4c3, 0xd4b5, 0xfae6, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_58[] = {
+ 0xd4b3, 0xd4c6, 0xb0f3, 0xfb69, 0xd4cc, 0xb0ed, 0xb0ef, 0xd4bb,
+ 0xd4b6, 0xae4b, 0xb0ee, 0xd4b8, 0xd4c7, 0xd4cb, 0xd4c2, 0x0000,
+ 0xd4c4, 0x0000, 0x97e5, 0x0000, 0xd4ae, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd8a1, 0x0000, 0xd8aa, 0xd8a9, 0xb3fa, 0xd8a2, 0x0000,
+ 0xb3fb, 0xb3f9, 0x967d, 0xd8a4, 0xb3f6, 0xd8a8, 0xfb6c, 0xd8a3,
+ 0xd8a5, 0xd87d, 0xb3f4, 0x0000, 0xd8b2, 0xd8b1, 0xd8ae, 0xb3f3,
+ 0xb3f7, 0xb3f8, 0xd14b, 0xd8ab, 0xb3f5, 0xb0f4, 0xd8ad, 0xd87e,
+ 0xd8b0, 0xd8af, 0x99a2, 0xd8b3, 0x0000, 0xdcef, 0x0000, 0xd8ac,
+ 0x9abb, 0x0000, 0x0000, 0x0000, 0x9a65, 0x0000, 0x0000, 0x944e,
+ 0xd8a7, 0xdce7, 0xb6f4, 0xb6f7, 0xb6f2, 0xdce6, 0xdcea, 0xdce5,
+ 0x0000, 0xb6ec, 0xb6f6, 0xdce2, 0xb6f0, 0xdce9, 0x0000, 0xb6ee,
+ 0xb6ed, 0xdcec, 0xb6ef, 0xdcee, 0xfb6e, 0xdceb, 0xb6eb, 0x99df,
+ 0x0000, 0x0000, 0xb6f5, 0xdcf0, 0xdce4, 0xdced, 0x0000, 0x0000,
+ 0xdce3, 0x98e3, 0x0000, 0xb6f1, 0x9254, 0xb6f3, 0x0000, 0xdce8,
+ 0x0000, 0xdcf1, 0x967b, 0x8aaf, 0xe15d, 0xb9d0, 0xe163, 0x0000,
+ 0x0000, 0xb9d5, 0xe15f, 0xe166, 0xe157, 0xb9d7, 0xb9d1, 0xe15c,
+ 0xbc55, 0xe15b, 0xe164, 0xb9d2, 0x0000, 0xb9d6, 0xe15a, 0xe160,
+ 0xe165, 0xe156, 0xb9d4, 0xe15e, 0x0000, 0x0000, 0xe162, 0xe168,
+ 0xe158, 0xe161, 0x8c77, 0xb9d3, 0xe167, 0x0000, 0x0000, 0x0000,
+ 0xe159, 0x8baf, 0x9ebd, 0x0000, 0xbc59, 0xe54b, 0xbc57, 0xbc56,
+ 0xe54d, 0xe552, 0x0000, 0xe54e, 0x0000, 0xe551, 0xbc5c, 0x9ee6,
+ 0xbea5, 0xbc5b, 0xfb6f, 0xe54a, 0xe550, 0x0000, 0xbc5a, 0xe54f,
+ 0x8ee1, 0xe54c, 0x0000, 0xbc58, 0x0000, 0x9b7d, 0x9c7e, 0x0000,
+ 0x0000, 0x0000, 0xe94d, 0xf9d9, 0xe94f, 0xe94a, 0xbec1, 0xe94c,
+ 0x0000, 0xbec0, 0xe94e, 0x0000, 0x0000, 0xbec3, 0xe950, 0xbec2,
+ 0xe949, 0xe94b, 0x0000, 0x92ea, 0x0000, 0x0000, 0xc0a5, 0xeccc,
+ 0x8c78, 0xc0a4, 0xeccd, 0xc0a3, 0xeccb, 0xc0a2, 0xecca, 0x0000,
+ 0xc253, 0xc252, 0xf1f6, 0xf1f8, 0xfb72, 0xf1f7, 0xc361, 0xc362,
+ 0xfb71, 0x0000, 0xc363, 0xf442, 0xc45b, 0x0000, 0x0000, 0xf7d3,
+ 0xf7d2, 0xc5f2, 0x0000, 0xa468, 0xa4d0, 0x0000, 0x0000, 0xa7a7,
+ 0x895c, 0x0000, 0x98f0, 0x96f2, 0xce5f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb3fc, 0xb3fd, 0xfb74, 0xdcf2, 0xb9d8, 0xe169, 0xe553
+};
+
+static const unsigned short big5hkscs_from_unicode_59[] = {
+ 0x0000, 0x0000, 0x8bc1, 0xc95a, 0x895d, 0x89de, 0xcab0, 0x895e,
+ 0x0000, 0x0000, 0xc6ca, 0x0000, 0xcc42, 0xce60, 0xd159, 0xae4c,
+ 0x0000, 0xfe42, 0xf1f9, 0x0000, 0xc4dc, 0xa469, 0xa57e, 0xc970,
+ 0x0000, 0xa667, 0xa668, 0x0000, 0xa95d, 0x0000, 0x0000, 0xfb7b,
+ 0xb0f7, 0x0000, 0xb9da, 0x0000, 0xb9db, 0xb9d9, 0x0000, 0xa46a,
+ 0x0000, 0xa4d1, 0xa4d3, 0xa4d2, 0xc95b, 0xa4d4, 0xa5a1, 0xc971,
+ 0x0000, 0xa5a2, 0x895f, 0x0000, 0x8960, 0x0000, 0x0000, 0xa669,
+ 0xa66a, 0x0000, 0x0000, 0x0000, 0xc9cb, 0x0000, 0xa7a8, 0x0000,
+ 0xcab1, 0x0000, 0x0000, 0x0000, 0xa961, 0xcc43, 0x0000, 0xa95f,
+ 0xa960, 0xa95e, 0xd15a, 0x0000, 0x0000, 0x0000, 0xabb6, 0xabb5,
+ 0xabb7, 0xabb4, 0x0000, 0xce61, 0xa962, 0xabb3, 0x0000, 0xae4d,
+ 0xae4e, 0x0000, 0xae4f, 0x0000, 0xd4cd, 0x0000, 0x0000, 0x0000,
+ 0xb3fe, 0xd8b4, 0xb0f8, 0x0000, 0x0000, 0x9bcd, 0x0000, 0xb6f8,
+ 0x0000, 0xb9dd, 0xb9dc, 0xe16a, 0x0000, 0xbc5d, 0xbec4, 0x0000,
+ 0xefc0, 0xf6da, 0xf7d4, 0xa46b, 0xa5a3, 0x9dd3, 0xa5a4, 0xc9d1,
+ 0xa66c, 0xa66f, 0x0000, 0xc9cf, 0xc9cd, 0xa66e, 0xc9d0, 0xc9d2,
+ 0xc9cc, 0xa671, 0xa670, 0xa66d, 0xa66b, 0xc9ce, 0x0000, 0x0000,
+ 0x0000, 0x984c, 0xa7b3, 0x0000, 0x0000, 0xa7b0, 0xcab6, 0xcab9,
+ 0xcab8, 0x0000, 0xa7aa, 0xa7b2, 0x9752, 0x0000, 0xa7af, 0xcab5,
+ 0xcab3, 0xa7ae, 0x95c3, 0x0000, 0x0000, 0xa7a9, 0xa7ac, 0x9bb6,
+ 0xcab4, 0xcabb, 0xcab7, 0xa7ad, 0xa7b1, 0xa7b4, 0xcab2, 0xcaba,
+ 0xa7ab, 0x0000, 0x0000, 0x0000, 0x9ab9, 0x0000, 0xa967, 0xa96f,
+ 0x97b3, 0xcc4f, 0xcc48, 0xa970, 0xcc53, 0xcc44, 0xcc4b, 0x9f74,
+ 0x92f1, 0xa966, 0xcc45, 0xa964, 0xcc4c, 0xcc50, 0xa963, 0x0000,
+ 0xcc51, 0xcc4a, 0x0000, 0xcc4d, 0x97df, 0xa972, 0xa969, 0xcc54,
+ 0xcc52, 0xfba6, 0xa96e, 0xa96c, 0xcc49, 0xa96b, 0xcc47, 0xcc46,
+ 0xa96a, 0xa968, 0xa971, 0xa96d, 0xa965, 0x0000, 0xcc4e, 0x0000,
+ 0xabb9, 0xfbab, 0xabc0, 0xce6f, 0xabb8, 0xce67, 0xce63, 0x0000,
+ 0xce73, 0xce62, 0x0000, 0xabbb, 0xce6c, 0xabbe, 0xabc1, 0x0000,
+ 0xabbc, 0xce70, 0xabbf, 0x9877, 0xae56, 0xce76, 0xce64, 0x9854,
+ 0x95c5, 0xce66, 0xce6d, 0xce71, 0xce75, 0xce72, 0xce6b, 0xce6e,
+ 0x9d55, 0xfbb2, 0xce68, 0xabc3, 0xce6a, 0xce69, 0xce74, 0xabba
+};
+
+static const unsigned short big5hkscs_from_unicode_5a[] = {
+ 0xce65, 0xabc2, 0x957e, 0xabbd, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xae5c, 0xd162, 0x9742, 0xae5b, 0x94e6, 0x0000, 0xd160,
+ 0x0000, 0xae50, 0x92f5, 0xae55, 0x0000, 0xd15f, 0xd15c, 0xd161,
+ 0xae51, 0xd15b, 0x8cc5, 0xae54, 0xae52, 0x0000, 0xd163, 0xae53,
+ 0xae57, 0x92fd, 0x0000, 0xae58, 0xfba2, 0xae5a, 0x0000, 0x9c51,
+ 0x0000, 0xae59, 0x94e9, 0x985c, 0x92f0, 0xd15d, 0xd15e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xd164, 0x0000, 0xd4d4, 0xb0f9, 0xd8c2,
+ 0xd4d3, 0xd4e6, 0x0000, 0x0000, 0xb140, 0x944c, 0xd4e4, 0x0000,
+ 0xb0fe, 0xb0fa, 0xd4ed, 0xd4dd, 0xd4e0, 0x916b, 0xb143, 0xd4ea,
+ 0xd4e2, 0xb0fb, 0xb144, 0x0000, 0xd4e7, 0xd4e5, 0x0000, 0x0000,
+ 0xd4d6, 0xd4eb, 0xd4df, 0xd4da, 0x8b78, 0xd4d0, 0xd4ec, 0xd4dc,
+ 0xd4cf, 0x94e2, 0xb142, 0xd4e1, 0xd4ee, 0xd4de, 0xd4d2, 0xd4d7,
+ 0xd4ce, 0x984f, 0xb141, 0xfbb5, 0xd4db, 0xd4d8, 0xb0fc, 0xd4d1,
+ 0x9271, 0xd4e9, 0xb0fd, 0x9365, 0xd4d9, 0xd4d5, 0x985b, 0x0000,
+ 0xd4e8, 0x9850, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfbb8,
+ 0xd8bb, 0x97bc, 0xd8b8, 0xd8c9, 0xd8bd, 0xd8ca, 0x92f3, 0xb442,
+ 0x0000, 0x9340, 0x984d, 0xd8c6, 0xd8c3, 0x0000, 0x9572, 0x0000,
+ 0xfdef, 0x0000, 0xd8c4, 0xd8c7, 0xd8cb, 0x0000, 0xd4e3, 0xd8cd,
+ 0xdd47, 0xfdc1, 0xb443, 0xd8ce, 0xd8b6, 0xd8c0, 0xfbba, 0xd8c5,
+ 0x0000, 0x92eb, 0xb441, 0xb444, 0xd8cc, 0xd8cf, 0xd8ba, 0xd8b7,
+ 0xfc73, 0x97b7, 0xd8b9, 0x0000, 0x0000, 0xd8be, 0xd8bc, 0xb445,
+ 0x0000, 0xd8c8, 0x0000, 0xfbb4, 0xd8bf, 0x0000, 0xd8c1, 0xd8b5,
+ 0xdcfa, 0xdcf8, 0xb742, 0xb740, 0xdd43, 0xdcf9, 0xdd44, 0xdd40,
+ 0xdcf7, 0xdd46, 0xdcf6, 0xdcfd, 0xb6fe, 0xb6fd, 0xb6fc, 0xdcfb,
+ 0xdd41, 0xb6f9, 0xb741, 0x90a7, 0xdcf4, 0x0000, 0xdcfe, 0xdcf3,
+ 0xdcfc, 0xb6fa, 0xdd42, 0xdcf5, 0xb6fb, 0xdd45, 0x9741, 0x92f4,
+ 0x0000, 0x0000, 0x0000, 0xfbbc, 0x0000, 0xe16e, 0xb9e2, 0xb9e1,
+ 0xb9e3, 0xe17a, 0xe170, 0xe176, 0xe16b, 0xe179, 0xe178, 0xe17c,
+ 0xe175, 0xb9de, 0xe174, 0xb9e4, 0x9577, 0xe16d, 0xb9df, 0x0000,
+ 0xe17b, 0xb9e0, 0xe16f, 0xe172, 0xe177, 0xe171, 0xe16c, 0x0000,
+ 0x9ee2, 0x0000, 0x8f78, 0xe173, 0xe555, 0xbc61, 0xe558, 0xe557,
+ 0xe55a, 0xe55c, 0xf9dc, 0xbc5f, 0x0000, 0xe556, 0x9672, 0xe554
+};
+
+static const unsigned short big5hkscs_from_unicode_5b[] = {
+ 0x0000, 0xe55d, 0xe55b, 0xe559, 0x0000, 0xe55f, 0x0000, 0xe55e,
+ 0xbc63, 0xbc5e, 0x0000, 0xbc60, 0xbc62, 0x9eb5, 0x0000, 0xe560,
+ 0xe957, 0x964b, 0x0000, 0xe956, 0xe955, 0x8cac, 0xe958, 0xe951,
+ 0x0000, 0xe952, 0xe95a, 0xe953, 0x0000, 0xbec5, 0xe95c, 0xa0fa,
+ 0xe95b, 0xe954, 0x0000, 0xecd1, 0xc0a8, 0xeccf, 0xecd4, 0xecd3,
+ 0xe959, 0x0000, 0xc0a7, 0x9575, 0xecd2, 0xecce, 0xecd6, 0xecd5,
+ 0xc0a6, 0x0000, 0xecd0, 0x0000, 0xbec6, 0x0000, 0x0000, 0x0000,
+ 0xc254, 0x0000, 0x0000, 0x0000, 0xefc1, 0xf1fa, 0xf1fb, 0xf1fc,
+ 0xc45c, 0x90da, 0x0000, 0xc45d, 0x9367, 0xf443, 0xfea4, 0xf5c8,
+ 0xf5c7, 0x0000, 0x90df, 0xf6db, 0xf6dc, 0xf7d5, 0xf8a7, 0x9354,
+ 0xa46c, 0xa46d, 0x0000, 0xa46e, 0xa4d5, 0xa5a5, 0xc9d3, 0xa672,
+ 0xa673, 0x0000, 0xa7b7, 0xa7b8, 0xa7b6, 0xa7b5, 0x0000, 0xa973,
+ 0x0000, 0x0000, 0xcc55, 0xa975, 0xa974, 0xcc56, 0x8961, 0x0000,
+ 0x8bb4, 0xabc4, 0x0000, 0xae5d, 0xd165, 0x9dc0, 0xd4f0, 0x0000,
+ 0xb145, 0xb447, 0xd4ef, 0xb446, 0x8e48, 0xb9e5, 0xfbc5, 0xe17d,
+ 0xbec7, 0x0000, 0xc0a9, 0xecd7, 0xfbc7, 0xc45e, 0x0000, 0xc570,
+ 0xc6cb, 0xc972, 0xfa79, 0xa5a6, 0xc973, 0xa676, 0x0000, 0xa674,
+ 0xa675, 0xa677, 0x0000, 0xa7ba, 0xa7b9, 0x0000, 0xcabc, 0xa7bb,
+ 0x9e67, 0x0000, 0xcabd, 0xcc57, 0x0000, 0xcc58, 0x8cd9, 0xa976,
+ 0xa978, 0xa97a, 0xa977, 0xa97b, 0xa979, 0xfbd2, 0x8962, 0x8963,
+ 0x0000, 0x0000, 0xabc8, 0xabc5, 0xabc7, 0xabc9, 0xabc6, 0xd166,
+ 0xce77, 0x0000, 0xfc7d, 0x0000, 0xd168, 0xd167, 0xae63, 0x0000,
+ 0xae5f, 0x0000, 0x0000, 0xae60, 0xae62, 0xae64, 0xae61, 0x0000,
+ 0xae66, 0xae65, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb14a,
+ 0xd4f2, 0xd4f1, 0xb149, 0x9f6b, 0xb148, 0xb147, 0xb14b, 0xb146,
+ 0x0000, 0x0000, 0xd8d5, 0xd8d2, 0xb449, 0xd8d1, 0xd8d6, 0x0000,
+ 0xb44b, 0xd8d4, 0xb448, 0xb44a, 0xd8d3, 0xfbcc, 0xdd48, 0xfeae,
+ 0xdd49, 0xdd4a, 0x0000, 0x0000, 0x0000, 0x0000, 0xb9e6, 0xb9ee,
+ 0xe17e, 0xb9e8, 0xb9ec, 0xe1a1, 0xb9ed, 0xb9e9, 0xb9ea, 0xb9e7,
+ 0xb9eb, 0xbc66, 0xd8d0, 0xbc67, 0xbc65, 0x0000, 0xbc64, 0xe95d,
+ 0xbec8, 0xecd8, 0xecd9, 0xfbd1, 0x0000, 0xc364, 0xc45f, 0x0000,
+ 0xa46f, 0x0000, 0xa678, 0x0000, 0x0000, 0x0000, 0x0000, 0xfb75
+};
+
+static const unsigned short big5hkscs_from_unicode_5c[] = {
+ 0x0000, 0xabca, 0x0000, 0xd169, 0xae67, 0xfbd4, 0x0000, 0xb14e,
+ 0xb14d, 0xb14c, 0xb44c, 0xb44d, 0xd8d7, 0xb9ef, 0xbec9, 0xa470,
+ 0xc95c, 0xa4d6, 0xc974, 0xfbd6, 0xfbd8, 0xc9d4, 0xa679, 0x0000,
+ 0x0000, 0x0000, 0xa97c, 0x0000, 0x8b5d, 0x0000, 0x934c, 0xdd4b,
+ 0x9ae2, 0x0000, 0xa471, 0x8bc9, 0xa4d7, 0xc9d5, 0x0000, 0x0000,
+ 0xcabe, 0x0000, 0xcabf, 0x0000, 0xa7bc, 0x0000, 0x0000, 0x0000,
+ 0xd8d8, 0xb44e, 0x0000, 0xdd4c, 0x0000, 0x0000, 0x0000, 0xc0aa,
+ 0xa472, 0xa4a8, 0xa4d8, 0xc975, 0xa5a7, 0x0000, 0xa7c0, 0xa7bf,
+ 0xa7bd, 0xa7be, 0x0000, 0x0000, 0xcc59, 0xa97e, 0xa9a1, 0xcc5a,
+ 0xa97d, 0xfbdb, 0x9fc9, 0xabce, 0xce78, 0xabcd, 0xabcb, 0xabcc,
+ 0xae6a, 0xae68, 0x0000, 0x9f44, 0xd16b, 0xae69, 0xd16a, 0x0000,
+ 0xae5e, 0xd4f3, 0x0000, 0x0000, 0xb150, 0xb151, 0x98ed, 0x0000,
+ 0xb14f, 0x0000, 0xb9f0, 0xe1a2, 0xbc68, 0xbc69, 0x0000, 0xe561,
+ 0xc0ab, 0xefc2, 0xefc3, 0x0000, 0xc4dd, 0xf8a8, 0xc94b, 0xa4d9,
+ 0x0000, 0xa473, 0x0000, 0xc977, 0xc976, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa67a, 0xc9d7, 0xc9d8, 0xc9d6, 0x0000, 0xc9d9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfbdd, 0xcac7, 0x0000,
+ 0xcac2, 0xcac4, 0xcac6, 0xcac3, 0xa7c4, 0xcac0, 0x0000, 0xcac1,
+ 0xa7c1, 0xa7c2, 0xcac5, 0xcac8, 0xa7c3, 0xcac9, 0x0000, 0x0000,
+ 0x0000, 0x8df2, 0x8964, 0x0000, 0xfdf2, 0xcc68, 0x934d, 0xcc62,
+ 0xcc5d, 0xa9a3, 0xcc65, 0xcc63, 0xcc5c, 0xcc69, 0xcc6c, 0xcc67,
+ 0xcc60, 0xa9a5, 0xcc66, 0xa9a6, 0xcc61, 0xcc64, 0xcc5b, 0xcc5f,
+ 0xcc6b, 0xa9a7, 0x0000, 0xa9a8, 0x0000, 0xcc5e, 0xcc6a, 0xa9a2,
+ 0xa9a4, 0x0000, 0xfbe7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa0f2, 0x9868, 0x0000, 0x0000, 0x0000, 0xceab, 0xcea4,
+ 0xceaa, 0xcea3, 0xcea5, 0xce7d, 0xce7b, 0x0000, 0xceac, 0xcea9,
+ 0xce79, 0x9f58, 0xabd0, 0xcea7, 0xcea8, 0x0000, 0xcea6, 0xce7c,
+ 0xce7a, 0xabcf, 0xcea2, 0xce7e, 0x0000, 0x0000, 0xcea1, 0xcead,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8d73, 0x0000, 0x0000,
+ 0xae6f, 0xfbde, 0xae6e, 0x0000, 0xd16c, 0xae6b, 0xd16e, 0xfbdf,
+ 0xae70, 0xd16f, 0x0000, 0x0000, 0xae73, 0x8c48, 0xae71, 0xd170,
+ 0xceae, 0xd172, 0x0000, 0xae6d, 0x0000, 0xae6c, 0x0000, 0xd16d
+};
+
+static const unsigned short big5hkscs_from_unicode_5d[] = {
+ 0xd171, 0xae72, 0x0000, 0x0000, 0x0000, 0x0000, 0xb153, 0xb152,
+ 0x0000, 0x0000, 0x0000, 0xd4f5, 0xd4f9, 0xd4fb, 0xb154, 0xd4fe,
+ 0xfbe3, 0xb158, 0xd541, 0x0000, 0xb15a, 0x8da8, 0xb156, 0xb15e,
+ 0xfbe4, 0xb15b, 0xd4f7, 0xb155, 0x0000, 0xd4f6, 0xd4f4, 0xd543,
+ 0xd4f8, 0x0000, 0xb157, 0xd542, 0xb15c, 0xd4fd, 0xd4fc, 0xb15d,
+ 0xd4fa, 0xb159, 0x0000, 0x0000, 0x9c75, 0x0000, 0xd544, 0x9878,
+ 0xd540, 0xd8e7, 0xd8ee, 0xd8e3, 0xb451, 0xd8df, 0xd8ef, 0xd8d9,
+ 0xd8ec, 0xd8ea, 0xd8e4, 0x0000, 0xd8ed, 0xd8e6, 0x8d60, 0xd8de,
+ 0xd8f0, 0xd8dc, 0xd8e9, 0xd8da, 0x0000, 0xd8f1, 0xfbe5, 0xb452,
+ 0x8d61, 0xd8eb, 0xdd4f, 0xd8dd, 0xb44f, 0x0000, 0xd8e1, 0x0000,
+ 0xb450, 0xd8e0, 0xd8e5, 0x0000, 0x0000, 0xd8e2, 0x8d62, 0xa0a1,
+ 0x0000, 0xd8e8, 0x0000, 0x9c40, 0x0000, 0x0000, 0xdd53, 0x0000,
+ 0x0000, 0x0000, 0xdd56, 0xdd4e, 0x0000, 0xdd50, 0x0000, 0xdd55,
+ 0xdd54, 0xb743, 0x0000, 0xd8db, 0xdd52, 0x0000, 0x0000, 0xb744,
+ 0x98ad, 0xdd4d, 0xdd51, 0x0000, 0x9eea, 0x0000, 0x0000, 0xe1a9,
+ 0x0000, 0xe1b0, 0xe1a7, 0x8cd4, 0xe1ae, 0xe1a5, 0xe1ad, 0xe1b1,
+ 0xe1a4, 0xe1a8, 0xe1a3, 0x0000, 0xb9f1, 0x9ceb, 0xe1a6, 0xb9f2,
+ 0xe1ac, 0xe1ab, 0xe1aa, 0xfbe0, 0x0000, 0xe1af, 0x9f51, 0x0000,
+ 0x0000, 0x0000, 0xe565, 0xe567, 0xbc6b, 0xe568, 0x0000, 0xe563,
+ 0x0000, 0xe562, 0xe56c, 0x0000, 0xe56a, 0xbc6a, 0xe56d, 0xe564,
+ 0xe569, 0xe56b, 0xe566, 0x0000, 0x8d65, 0x0000, 0x0000, 0xe961,
+ 0xe966, 0xe960, 0xe965, 0x9cf1, 0xe95e, 0xe968, 0xe964, 0xe969,
+ 0xe963, 0xe95f, 0xe967, 0x0000, 0xe96a, 0xe962, 0xfc58, 0xecda,
+ 0xc0af, 0x8d66, 0xc0ad, 0x0000, 0xc0ac, 0xc0ae, 0x0000, 0x0000,
+ 0xefc4, 0x9654, 0xf172, 0xf1fd, 0x0000, 0x0000, 0xf444, 0xf445,
+ 0x0000, 0xc460, 0x0000, 0xf5c9, 0x0000, 0xc4de, 0x0000, 0xf5ca,
+ 0x0000, 0xf6de, 0xc572, 0x0000, 0xc571, 0xf6dd, 0xc5c9, 0xfbe8,
+ 0xf7d6, 0x0000, 0x0000, 0xc6cc, 0x0000, 0xa474, 0xa67b, 0xc9da,
+ 0xcaca, 0xa8b5, 0xb15f, 0x0000, 0x0000, 0xa475, 0xa5aa, 0xa5a9,
+ 0xa5a8, 0x0000, 0x0000, 0xa7c5, 0x0000, 0x0000, 0xae74, 0x0000,
+ 0xdd57, 0xa476, 0xa477, 0xa478, 0xa4da, 0x9fce, 0x0000, 0xabd1,
+ 0x0000, 0xceaf, 0x0000, 0x0000, 0x0000, 0xb453, 0xa479, 0xc95d
+};
+
+static const unsigned short big5hkscs_from_unicode_5e[] = {
+ 0x0000, 0x0000, 0xa5ab, 0xa5ac, 0xc978, 0x0000, 0xa67c, 0x0000,
+ 0x0000, 0xfbfc, 0xcacb, 0x9ae4, 0xa7c6, 0x0000, 0xcacc, 0x0000,
+ 0x0000, 0xa9ae, 0x9f75, 0x0000, 0xcc6e, 0xa9ac, 0xa9ab, 0xcc6d,
+ 0xa9a9, 0xcc6f, 0xa9aa, 0xa9ad, 0x0000, 0xabd2, 0x0000, 0xabd4,
+ 0xceb3, 0xceb0, 0xceb1, 0xceb2, 0xceb4, 0xabd3, 0x0000, 0x0000,
+ 0xd174, 0xd173, 0x0000, 0xae76, 0x0000, 0xae75, 0xfbf1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xb162, 0xd546, 0x0000, 0xb161, 0xb163,
+ 0xb160, 0x0000, 0x0000, 0x0000, 0x0000, 0xb455, 0xd545, 0x0000,
+ 0xb456, 0xd8f3, 0x8d69, 0xb457, 0xd8f2, 0xb454, 0x0000, 0x0000,
+ 0x934f, 0x0000, 0xdd5a, 0xdd5c, 0xb745, 0xdd5b, 0xdd59, 0xdd58,
+ 0x0000, 0x0000, 0x0000, 0xe1b4, 0xb9f7, 0xb9f5, 0x0000, 0xb9f6,
+ 0xe1b2, 0xe1b3, 0x0000, 0xb9f3, 0xe571, 0xe56f, 0x934e, 0xbc6d,
+ 0xe570, 0xbc6e, 0xbc6c, 0xb9f4, 0x0000, 0x0000, 0xe96d, 0xe96b,
+ 0xe96c, 0xe56e, 0xecdc, 0xc0b0, 0xecdb, 0xefc5, 0xefc6, 0xe96e,
+ 0xf1fe, 0x0000, 0xa47a, 0xa5ad, 0xa67e, 0xfbf3, 0xa67d, 0x0000,
+ 0xa9af, 0xb746, 0xfbf4, 0xa4db, 0xa5ae, 0xabd5, 0xb458, 0xc6ce,
+ 0xc979, 0x0000, 0xc97a, 0xfbc3, 0xc9dc, 0x0000, 0x8965, 0xa7c8,
+ 0xcad0, 0xcace, 0xa7c9, 0xcacd, 0xcacf, 0xcad1, 0x0000, 0xa7c7,
+ 0x0000, 0x0000, 0x8c7a, 0x0000, 0x0000, 0xa9b3, 0xa9b4, 0xa9b1,
+ 0x0000, 0x8c7b, 0xa9b0, 0xceb8, 0xa9b2, 0x0000, 0x0000, 0x0000,
+ 0xabd6, 0x0000, 0xceb7, 0xceb9, 0xceb6, 0xceba, 0xabd7, 0xae79,
+ 0xd175, 0x0000, 0xd177, 0xae77, 0xd178, 0xae78, 0xd176, 0x0000,
+ 0xceb5, 0xd547, 0xd54a, 0xd54b, 0xd548, 0xb167, 0xb166, 0xb164,
+ 0xb165, 0xd549, 0x0000, 0x0000, 0x0000, 0x8d6a, 0xb168, 0x0000,
+ 0x0000, 0xb45a, 0xb45b, 0x0000, 0xb45c, 0xdd5d, 0xdd5f, 0xdd61,
+ 0xb748, 0xb747, 0xb459, 0xdd60, 0xdd5e, 0x9353, 0xe1b8, 0x0000,
+ 0xfbf9, 0xe1b6, 0xe1bc, 0xb9f8, 0xe1bd, 0xe1ba, 0xb9f9, 0xe1b7,
+ 0xe1b5, 0xe1bb, 0xbc70, 0xe573, 0xe1b9, 0xbc72, 0xe574, 0xbc71,
+ 0xbc74, 0xe575, 0xbc6f, 0xbc73, 0x0000, 0xe973, 0xe971, 0xe970,
+ 0xe972, 0xe96f, 0x0000, 0x0000, 0xc366, 0x0000, 0xf446, 0xf447,
+ 0x0000, 0xf5cb, 0xf6df, 0xc655, 0xfbfd, 0x0000, 0xa9b5, 0xa7ca,
+ 0x9059, 0xfc40, 0xabd8, 0xfc41, 0xfc43, 0x0000, 0xa47b, 0xa4dc
+};
+
+static const unsigned short big5hkscs_from_unicode_5f[] = {
+ 0x0000, 0xa5af, 0xc9dd, 0x0000, 0xa7cb, 0xcad2, 0x0000, 0xcebb,
+ 0xabd9, 0x0000, 0xb9fa, 0xa47c, 0x9fd8, 0xfc46, 0x9362, 0xa6a1,
+ 0x0000, 0x0000, 0xb749, 0xa47d, 0xa4dd, 0xa4de, 0x0000, 0xa5b1,
+ 0xa5b0, 0x0000, 0xc9de, 0xa6a2, 0x0000, 0xcad3, 0x0000, 0xa7cc,
+ 0x0000, 0x0000, 0xcc71, 0xcc72, 0xcc73, 0x8d6b, 0xa9b6, 0xa9b7,
+ 0xcc70, 0xa9b8, 0x0000, 0x0000, 0x0000, 0xabda, 0xcebc, 0x0000,
+ 0xd17a, 0xae7a, 0x0000, 0xd179, 0x0000, 0xb169, 0xd54c, 0xb16a,
+ 0xd54d, 0x0000, 0xfc4c, 0x0000, 0xb45d, 0x0000, 0x0000, 0x0000,
+ 0xdd62, 0x0000, 0x0000, 0xe1bf, 0xe1be, 0x0000, 0xb9fb, 0x0000,
+ 0xbc75, 0xe576, 0xbeca, 0xe974, 0xc0b1, 0x95b8, 0xc573, 0xf7d8,
+ 0xc6d0, 0x8bca, 0x0000, 0x0000, 0xcc74, 0x0000, 0xcebd, 0xb16b,
+ 0xfc4f, 0xb74a, 0x0000, 0x0000, 0x987a, 0xc255, 0x0000, 0x0000,
+ 0x0000, 0xc6d1, 0xa7ce, 0xfc51, 0xa7cd, 0xabdb, 0x0000, 0xd17b,
+ 0x0000, 0xb16d, 0xb343, 0xb16e, 0xb16c, 0xb45e, 0x0000, 0xe1c0,
+ 0xb9fc, 0xbc76, 0xfc54, 0xc94c, 0xc9df, 0x0000, 0xcad5, 0xa7cf,
+ 0xcad4, 0xa7d0, 0x0000, 0xfaaf, 0xa9bc, 0xcc77, 0xcc76, 0xa9bb,
+ 0xa9b9, 0xa9ba, 0xcc75, 0x8d6c, 0x0000, 0xabdd, 0xcebe, 0xabe0,
+ 0xabdc, 0xabe2, 0xabde, 0xabdf, 0xabe1, 0x0000, 0x0000, 0x0000,
+ 0xae7d, 0xae7c, 0xae7b, 0x0000, 0x0000, 0x0000, 0xd54f, 0xb16f,
+ 0xb172, 0xb170, 0x0000, 0xd54e, 0xb175, 0x0000, 0xb171, 0xd550,
+ 0xb174, 0xb173, 0x0000, 0x0000, 0xfa61, 0xd8f6, 0xd8f5, 0xfc57,
+ 0xb461, 0xb45f, 0xb460, 0xd8f7, 0xb74b, 0xdd64, 0xb74c, 0xdd63,
+ 0x0000, 0x9b70, 0xe577, 0x0000, 0x0000, 0xbc78, 0xe1c1, 0xbc77,
+ 0x0000, 0xb9fd, 0xa051, 0xecde, 0xe975, 0xc0b2, 0xecdd, 0xf240,
+ 0xf448, 0xf449, 0x8c7c, 0xa4df, 0x8bcb, 0xa5b2, 0x0000, 0x0000,
+ 0x0000, 0xc97b, 0x0000, 0x0000, 0xa7d2, 0xa7d4, 0x0000, 0xc9e2,
+ 0xcad8, 0xcad7, 0xcad6, 0x0000, 0xc9e1, 0xc9e0, 0xa6a4, 0xa7d3,
+ 0xa7d1, 0xa6a3, 0x0000, 0x936e, 0x0000, 0xa9bd, 0xcc78, 0xfcd5,
+ 0xa9be, 0xcadd, 0x0000, 0xcadf, 0xcade, 0xcc79, 0x0000, 0x0000,
+ 0xcada, 0x0000, 0xa7d8, 0xa7d6, 0x0000, 0xcad9, 0xcadb, 0xcae1,
+ 0x0000, 0xa7d5, 0x0000, 0xcadc, 0xcae5, 0xa9c0, 0x0000, 0xcae2,
+ 0xa7d7, 0x0000, 0xcae0, 0xcae3, 0x0000, 0xa9bf, 0x0000, 0xa9c1
+};
+
+static const unsigned short big5hkscs_from_unicode_60[] = {
+ 0xcae4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xccaf, 0xcca2, 0xcc7e, 0xccae, 0xcca9, 0xabe7, 0xa9c2,
+ 0xccaa, 0xccad, 0xabe3, 0xccac, 0xa9c3, 0xa9c8, 0xa9c6, 0xcca3,
+ 0x0000, 0xcc7c, 0xcca5, 0xa9cd, 0xccb0, 0xabe4, 0xcca6, 0x0000,
+ 0xabe5, 0xa9c9, 0xcca8, 0xfca9, 0xcecd, 0xabe6, 0xcc7b, 0xa9ca,
+ 0xabe8, 0xa9cb, 0xa9c7, 0xa9cc, 0xcca7, 0xcc7a, 0xccab, 0xa9c4,
+ 0x0000, 0xfc61, 0xcc7d, 0xcca4, 0xcca1, 0xa9c5, 0x0000, 0xcebf,
+ 0x0000, 0xcec0, 0x0000, 0x8966, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xceca, 0xd1a1, 0xcecb, 0xabee, 0xcece, 0xcec4, 0xabed, 0xcec6,
+ 0x0000, 0xcec7, 0xfacb, 0x0000, 0xcec9, 0xabe9, 0x0000, 0x0000,
+ 0xaea3, 0x0000, 0xf9da, 0xcec5, 0xcec1, 0xaea4, 0x0000, 0x0000,
+ 0xcecf, 0xae7e, 0xd17d, 0xcec8, 0x0000, 0xd17c, 0xcec3, 0xcecc,
+ 0x0000, 0x0000, 0xabec, 0xaea1, 0xabf2, 0xaea2, 0xced0, 0xd17e,
+ 0xabeb, 0xaea6, 0xabf1, 0xabf0, 0xabef, 0xaea5, 0xced1, 0xaea7,
+ 0xabea, 0x0000, 0xcec2, 0x0000, 0x0000, 0x937a, 0x0000, 0xa0e0,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x936b, 0xb176,
+ 0xd1a4, 0xd1a6, 0x0000, 0xd1a8, 0xaea8, 0xaeae, 0xd553, 0xd1ac,
+ 0xd1a3, 0xb178, 0xd551, 0x0000, 0xaead, 0xaeab, 0xd1ae, 0x0000,
+ 0xd552, 0x0000, 0xd1a5, 0x0000, 0xaeac, 0xd1a9, 0xaeaf, 0xd1ab,
+ 0x0000, 0x0000, 0xaeaa, 0xd1aa, 0xd1ad, 0xd1a7, 0xfc6b, 0xaea9,
+ 0xb179, 0x0000, 0xd1a2, 0xb177, 0xfc6c, 0x0000, 0x0000, 0x9468,
+ 0xb17a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd555, 0xd55e, 0xb464, 0xfc6d, 0xb17c, 0xb1a3, 0xb465, 0xd560,
+ 0xb1aa, 0xd8f9, 0xd556, 0xb1a2, 0xb1a5, 0xb17e, 0xd554, 0xd562,
+ 0xd565, 0xd949, 0x0000, 0xd563, 0xd8fd, 0xb1a1, 0xb1a8, 0xb1ac,
+ 0xd55d, 0xd8f8, 0xd561, 0xb17b, 0xd8fa, 0xd564, 0xd8fc, 0xd559,
+ 0x0000, 0xb462, 0x0000, 0xd557, 0xd558, 0xb1a7, 0x0000, 0x8d71,
+ 0xb1a6, 0xd55b, 0xb1ab, 0xd55f, 0xb1a4, 0xd55c, 0xfd64, 0xb1a9,
+ 0xb466, 0xb463, 0xd8fb, 0x99ba, 0xd55a, 0x0000, 0xb17d, 0x9ad0,
+ 0x9a61, 0xa0e5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xb46b, 0xb46f, 0xd940, 0xb751, 0xb46d, 0xd944, 0xb471, 0xdd65,
+ 0xd946, 0xb753, 0xb469, 0xb46c, 0xd947, 0xa05b, 0xd948, 0xd94e
+};
+
+static const unsigned short big5hkscs_from_unicode_61[] = {
+ 0xb473, 0xb754, 0x0000, 0xd94a, 0xd94f, 0xd943, 0xb75e, 0x96ac,
+ 0xb755, 0xb472, 0xd941, 0xd950, 0x9740, 0xb75d, 0xb470, 0xb74e,
+ 0xd94d, 0x0000, 0xb474, 0xd945, 0xd8fe, 0xb46a, 0xd942, 0x0000,
+ 0xd94b, 0x9ef1, 0xb74d, 0xb752, 0xb467, 0xd94c, 0x0000, 0xb750,
+ 0x0000, 0x0000, 0x8c4d, 0xb468, 0x0000, 0x0000, 0x0000, 0xb75c,
+ 0xe1c3, 0xdd70, 0x0000, 0xdd68, 0xe1c2, 0x0000, 0xdd6c, 0xdd6e,
+ 0x9f7e, 0x0000, 0xdd6b, 0x0000, 0xb75b, 0x0000, 0xdd6a, 0xb75f,
+ 0x0000, 0x0000, 0x0000, 0xe1d2, 0x0000, 0x8d72, 0xb75a, 0xba40,
+ 0xdd71, 0xe1c4, 0xfc76, 0x0000, 0xb758, 0xdd69, 0xdd6d, 0xb9fe,
+ 0xb74f, 0xdd66, 0xdd67, 0xba41, 0xb757, 0xb759, 0xb756, 0xdd6f,
+ 0x96a9, 0x0000, 0xe1c8, 0xe1c9, 0xe1ce, 0xbc7d, 0xe1d5, 0x0000,
+ 0xba47, 0xa06e, 0xba46, 0xe1d0, 0xfcaa, 0xbc7c, 0xe1c5, 0xba45,
+ 0xfbcd, 0xe1d4, 0xba43, 0xba44, 0xfc74, 0xe1d1, 0xe5aa, 0xbc7a,
+ 0xb46e, 0x0000, 0xe1d3, 0xbca3, 0xe1cb, 0x0000, 0xbc7b, 0xa074,
+ 0xbca2, 0xe1c6, 0xe1ca, 0xe1c7, 0xe1cd, 0xba48, 0xbc79, 0xba42,
+ 0x0000, 0xe57a, 0xe1cf, 0x0000, 0xbca1, 0xa071, 0xbca4, 0x0000,
+ 0xe1cc, 0xfc79, 0xbc7e, 0xe579, 0x0000, 0x0000, 0x0000, 0xfc7c,
+ 0x0000, 0xe57e, 0xbece, 0xe578, 0xe9a3, 0xe5a9, 0xbca8, 0x0000,
+ 0xbca6, 0xbecc, 0xe5a6, 0xe5a2, 0xbcac, 0x9c50, 0xe978, 0x0000,
+ 0x9379, 0x9378, 0xbcaa, 0xe5a1, 0xa0dd, 0xe976, 0x0000, 0xe5a5,
+ 0x0000, 0xe5a8, 0xe57d, 0x0000, 0xbcab, 0x0000, 0x0000, 0xbca5,
+ 0xe977, 0xbecd, 0xe5a7, 0xbca7, 0xbca9, 0xe5a4, 0xbcad, 0xe5a3,
+ 0xe57c, 0xe57b, 0xbecb, 0xe5ab, 0xe97a, 0xece0, 0xbed0, 0x8d75,
+ 0xe9a2, 0x8d76, 0xe97e, 0x0000, 0xece1, 0x0000, 0xbed1, 0xe9a1,
+ 0x9374, 0xe97c, 0xc0b4, 0xecdf, 0x0000, 0xe979, 0xe97b, 0xc0b5,
+ 0xbed3, 0xc0b3, 0xbed2, 0xc0b7, 0xe97d, 0xbecf, 0x0000, 0x8d77,
+ 0xfca5, 0x0000, 0x0000, 0xfca2, 0x0000, 0x0000, 0xefcf, 0x0000,
+ 0xefc7, 0x0000, 0x90c3, 0x0000, 0x0000, 0x0000, 0xece7, 0xefc8,
+ 0xece3, 0x0000, 0xa079, 0xc256, 0xece5, 0xece4, 0xc0b6, 0xece2,
+ 0xece6, 0xefd0, 0xefcc, 0xefce, 0x0000, 0xefc9, 0xefca, 0x0000,
+ 0xefcd, 0xefcb, 0xc367, 0x0000, 0x0000, 0xc36a, 0xc369, 0xc368,
+ 0xc461, 0xf44a, 0xc462, 0xf241, 0xc4df, 0xf5cc, 0xc4e0, 0xc574
+};
+
+static const unsigned short big5hkscs_from_unicode_62[] = {
+ 0xc5ca, 0xf7d9, 0x0000, 0xf7da, 0xf7db, 0x0000, 0x0000, 0xf9ba,
+ 0xa4e0, 0xc97c, 0xa5b3, 0x0000, 0xa6a6, 0xa6a7, 0xa6a5, 0x0000,
+ 0xa6a8, 0xa7da, 0xa7d9, 0x0000, 0xccb1, 0xa9cf, 0xa9ce, 0x0000,
+ 0x0000, 0xd1af, 0xb1ad, 0xb1ae, 0x0000, 0x0000, 0x0000, 0xb475,
+ 0xdd72, 0xb760, 0xb761, 0xdd74, 0xdd76, 0xdd75, 0x0000, 0xe1d7,
+ 0x0000, 0xe1d6, 0xba49, 0xe1d8, 0x8d79, 0xe5ac, 0xbcae, 0x0000,
+ 0xbed4, 0x0000, 0xc0b8, 0xc257, 0xc0b9, 0x0000, 0xa4e1, 0x8bfc,
+ 0x0000, 0xa076, 0xcae6, 0x0000, 0x0000, 0xccb2, 0xa9d1, 0xa9d0,
+ 0xa9d2, 0xabf3, 0xced2, 0xced3, 0x0000, 0x0000, 0xd1b0, 0xaeb0,
+ 0xb1af, 0xb476, 0xd951, 0xa4e2, 0x8bcd, 0xa47e, 0xa4e3, 0x0000,
+ 0xc97d, 0xa5b7, 0xa5b6, 0xa5b4, 0xa5b5, 0x0000, 0x0000, 0x0000,
+ 0xa6ab, 0xc9e9, 0xc9eb, 0xa6aa, 0xc9e3, 0x0000, 0xc9e4, 0x0000,
+ 0xc9ea, 0xc9e6, 0xc9e8, 0xa6a9, 0xc9e5, 0xc9ec, 0xc9e7, 0x0000,
+ 0x9f5a, 0x0000, 0x0000, 0x0000, 0x0000, 0xa7e1, 0xa7ea, 0xa7e8,
+ 0xcaf0, 0xcaed, 0xcaf5, 0xa7e6, 0xcaf6, 0x0000, 0xa7df, 0xcaf3,
+ 0x0000, 0xa7e5, 0xcaef, 0xcaee, 0xa7e3, 0xcaf4, 0xa7e4, 0xa9d3,
+ 0xa7de, 0xcaf1, 0x9ff4, 0xcae7, 0xa7db, 0x9fba, 0xa7ee, 0xcaec,
+ 0xcaf2, 0xa7e0, 0xa7e2, 0x0000, 0xcae8, 0x0000, 0xcae9, 0xcaea,
+ 0x8d7a, 0xa7ed, 0xa7e7, 0xa7ec, 0xcaeb, 0xa7eb, 0xa7dd, 0xa7dc,
+ 0xa7e9, 0x0000, 0x0000, 0x0000, 0x0000, 0x9e45, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x93b0, 0x0000, 0xa075, 0x0000,
+ 0xa9e1, 0xccbe, 0xccb7, 0xa9dc, 0xa9ef, 0xccb3, 0xccba, 0xccbc,
+ 0xccbf, 0xa9ea, 0x0000, 0xccbb, 0xccb4, 0xa9e8, 0xccb8, 0x0000,
+ 0xccc0, 0xa9d9, 0x0000, 0xccbd, 0xa9e3, 0xa9e2, 0xccb6, 0xa9d7,
+ 0x0000, 0x0000, 0xa9d8, 0x9b46, 0xa9d6, 0xfcae, 0xa9ee, 0xa9e6,
+ 0xa9e0, 0xa9d4, 0xccb9, 0xa9df, 0xa9d5, 0xa9e7, 0xa9f0, 0xced4,
+ 0xa9e4, 0xccb5, 0xa9da, 0xa9dd, 0xa9de, 0xfcb0, 0xa9ec, 0xa9ed,
+ 0xa9eb, 0xa9e5, 0xa9e9, 0xa9db, 0xabf4, 0x0000, 0x0000, 0xfa51,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8d7b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xceda, 0xac41, 0xabf8, 0xabfa, 0xac40,
+ 0xcee6, 0xabfd, 0xd1b1, 0xaeb1, 0xac43, 0xced7, 0xcedf, 0xabfe,
+ 0xcede, 0xcedb, 0xcee3, 0xcee5, 0xabf7, 0xabfb, 0xac42, 0xaeb3
+};
+
+static const unsigned short big5hkscs_from_unicode_63[] = {
+ 0xcee0, 0xabf9, 0xac45, 0xced9, 0x0000, 0x0000, 0x0000, 0xabfc,
+ 0xaeb2, 0xabf6, 0x0000, 0xced6, 0xcedd, 0xced5, 0xced8, 0xcedc,
+ 0xd1b2, 0xac44, 0x0000, 0xcee1, 0xcee2, 0xcee4, 0xabf5, 0x0000,
+ 0x8d7c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xaec1, 0xd1be, 0xaebf, 0xaec0, 0xd1b4, 0xd1c4, 0x9ed6, 0xaeb6,
+ 0x0000, 0x93ac, 0xd566, 0xd1c6, 0xd1c0, 0x9f5b, 0xd1b7, 0x93a9,
+ 0xd1c9, 0xd1ba, 0xaebc, 0xd57d, 0xd1bd, 0xaebe, 0xaeb5, 0x0000,
+ 0xd1cb, 0xd1bf, 0xaeb8, 0xd1b8, 0xd1b5, 0xd1b6, 0xaeb9, 0xd1c5,
+ 0xd1cc, 0xaebb, 0xd1bc, 0xd1bb, 0xaec3, 0xaec2, 0xaeb4, 0xaeba,
+ 0xaebd, 0xd1c8, 0x0000, 0x0000, 0xd1c2, 0xaeb7, 0xd1b3, 0xd1ca,
+ 0xd1c1, 0xd1c3, 0xd1c7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa07c, 0xd567, 0x0000, 0xb1b7,
+ 0xb1cb, 0xb1ca, 0x0000, 0xb1bf, 0xfcb2, 0xd579, 0xd575, 0xd572,
+ 0xd5a6, 0xb1ba, 0xb1b2, 0x0000, 0x0000, 0xd577, 0xb4a8, 0xb1b6,
+ 0xd5a1, 0x8ac1, 0xb1cc, 0xb1c9, 0xd57b, 0xd56a, 0x0000, 0x9fb4,
+ 0xb1c8, 0xd5a3, 0xd569, 0xb1bd, 0xb1c1, 0xd5a2, 0x0000, 0xd573,
+ 0xb1c2, 0xb1bc, 0xd568, 0xfcac, 0xb478, 0xd5a5, 0xd571, 0xb1c7,
+ 0xd574, 0xd5a4, 0xb1c6, 0x0000, 0xd952, 0x0000, 0xb1b3, 0xd56f,
+ 0xb1b8, 0xb1c3, 0x0000, 0xb1be, 0xd578, 0xd56e, 0xd56c, 0xd57e,
+ 0xb1b0, 0xb1c4, 0xb1b4, 0xb477, 0xd57c, 0xb1b5, 0x0000, 0xb1b1,
+ 0xb1c0, 0xb1bb, 0xb1b9, 0xd570, 0xb1c5, 0xd56d, 0xd57a, 0xd576,
+ 0xd954, 0xd953, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9e4c, 0x0000, 0x0000, 0x0000, 0xd56b, 0xd964, 0x0000,
+ 0xb47a, 0x8fc5, 0xd96a, 0xd959, 0xd967, 0xdd77, 0xb47d, 0xd96b,
+ 0xd96e, 0xb47c, 0xd95c, 0xd96d, 0xd96c, 0xb47e, 0xd955, 0xb479,
+ 0xb4a3, 0x93ad, 0xb4a1, 0xd969, 0x0000, 0xd95f, 0xb4a5, 0xd970,
+ 0xd968, 0xd971, 0xb4ad, 0xb4ab, 0xd966, 0xd965, 0x9dc3, 0xd963,
+ 0xd95d, 0xb4a4, 0x8da2, 0xb4a2, 0xd1b9, 0xd956, 0x9d4a, 0xddb7,
+ 0xd957, 0xb47b, 0xb4aa, 0xdd79, 0x0000, 0xb4a6, 0xb4a7, 0xd958,
+ 0xd96f, 0xdd78, 0xd960, 0xd95b, 0xb4a9, 0xd961, 0xd95e, 0x0000,
+ 0xfcb6, 0xb4ae, 0x0000, 0x8da3, 0x9e4b, 0x0000, 0x9e4d, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_64[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb770, 0x8da4,
+ 0x0000, 0xdd7c, 0xddb1, 0xddb6, 0xddaa, 0xb76c, 0xddbb, 0xb769,
+ 0xdd7a, 0x0000, 0xdd7b, 0xb762, 0xb76b, 0xdda4, 0xb76e, 0xb76f,
+ 0xdda5, 0x0000, 0xddb2, 0xddb8, 0xb76a, 0x0000, 0xb764, 0xdda3,
+ 0xdd7d, 0xddba, 0xdda8, 0xdda9, 0xdd7e, 0xddb4, 0xddab, 0xddb5,
+ 0xddad, 0x0000, 0xb765, 0xe1d9, 0xb768, 0xb766, 0xddb9, 0xddb0,
+ 0xddac, 0x0000, 0x8afd, 0xdda1, 0xba53, 0xddaf, 0xb76d, 0xdda7,
+ 0xfcb5, 0xdda6, 0xfcc3, 0x93b2, 0x0000, 0xb767, 0xb763, 0xe1ee,
+ 0xddb3, 0xddae, 0x0000, 0xdda2, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe1e9, 0x0000, 0xe1da, 0xe1e5, 0x0000,
+ 0xe1ec, 0xba51, 0xb4ac, 0xe1ea, 0xba4c, 0x0000, 0x0000, 0x0000,
+ 0xba4b, 0xe1f1, 0x8da5, 0xe1db, 0xe1e8, 0xe1dc, 0xe1e7, 0xba4f,
+ 0xe1eb, 0xd962, 0x0000, 0x0000, 0x0000, 0xe1f2, 0xe1e3, 0xba52,
+ 0xe5ba, 0xbcaf, 0x0000, 0xe1f0, 0xe1ef, 0xba54, 0xe5ad, 0xbcb0,
+ 0xe5ae, 0x93a1, 0xe1df, 0xe1e0, 0xe1dd, 0xe1e2, 0xe1de, 0xe1f3,
+ 0xba4e, 0xbcb1, 0xba50, 0xba55, 0x8ac6, 0xe1e1, 0x0000, 0xe1ed,
+ 0x0000, 0x0000, 0xe1e6, 0x0000, 0x0000, 0xe5b1, 0x0000, 0xba4a,
+ 0xbcb4, 0xe9aa, 0xe5b6, 0xe5b5, 0xe5b7, 0x8a5b, 0x0000, 0xe5b4,
+ 0xfcb9, 0x894d, 0xbcbb, 0xbcb8, 0x0000, 0xbcb9, 0xe5af, 0xe5b2,
+ 0xe5bc, 0xbcc1, 0xbcbf, 0x0000, 0xe5b3, 0xd95a, 0xbcb2, 0xe5b9,
+ 0xe5b0, 0x0000, 0xbcc2, 0xe5b8, 0xba4d, 0xbcb7, 0xe1e4, 0x0000,
+ 0x0000, 0xbcba, 0x0000, 0xbcbe, 0xbcc0, 0xbcbd, 0xbcbc, 0xfed4,
+ 0xbcb6, 0xe5bb, 0xbcb3, 0xbcc3, 0x8a78, 0x0000, 0x93ab, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xbed8, 0xbed9, 0xe9a9, 0xbee2, 0xbedf,
+ 0x8da7, 0xbed6, 0xbedd, 0xe9ab, 0xbedb, 0xbed5, 0x0000, 0xbedc,
+ 0x0000, 0xe9a8, 0xc0bb, 0xbed7, 0x0000, 0xbede, 0xc0ba, 0xe9a7,
+ 0xe9a6, 0x0000, 0xbee0, 0x9f45, 0xbee1, 0x0000, 0xe9a5, 0xe9a4,
+ 0xc0bc, 0xe9ae, 0xbeda, 0xe9ac, 0x0000, 0x8a56, 0x0000, 0x0000,
+ 0xc0bd, 0xfcbf, 0xc0c2, 0xecea, 0xecec, 0xfcc0, 0xc0bf, 0x8ee6,
+ 0xeced, 0xece9, 0x8aa4, 0xeceb, 0xc0c0, 0xc0c3, 0x0000, 0xece8,
+ 0xc0be, 0xc0c1, 0xc259, 0xe9ad, 0xc258, 0x0000, 0x0000, 0xc25e,
+ 0xefd4, 0x0000, 0xc25c, 0xc25d, 0xefd7, 0xefd3, 0xc25a, 0xefd1
+};
+
+static const unsigned short big5hkscs_from_unicode_65[] = {
+ 0xc36b, 0xefd5, 0x0000, 0xefd6, 0xefd2, 0x0000, 0xc25b, 0xf242,
+ 0x0000, 0xf245, 0x8943, 0x0000, 0xf246, 0xf244, 0xf247, 0xc36c,
+ 0xf243, 0x93f3, 0x0000, 0xf44e, 0xc464, 0xf44d, 0xf44c, 0xf44b,
+ 0xc463, 0xc465, 0x0000, 0xf5cd, 0xc4e2, 0xc4e1, 0xfcab, 0x9ea2,
+ 0xf6e1, 0xf6e0, 0xf6e3, 0xc5cb, 0xc575, 0xf7dd, 0xf6e2, 0x0000,
+ 0x0000, 0xf7dc, 0xc5cd, 0xc5cc, 0xc5f3, 0xf8a9, 0xf8ef, 0xa4e4,
+ 0x9dc7, 0x0000, 0xd972, 0xe9af, 0xc6d2, 0x8bce, 0xa6ac, 0xcaf7,
+ 0xa7f1, 0xa7ef, 0x0000, 0xa7f0, 0x0000, 0xccc1, 0xa9f1, 0xac46,
+ 0x0000, 0xcee7, 0x0000, 0xcee8, 0x0000, 0xac47, 0xd1ce, 0x0000,
+ 0xaec4, 0xaec5, 0xd1cd, 0x0000, 0x0000, 0xfcc5, 0x0000, 0xb1d3,
+ 0x0000, 0xb1cf, 0x0000, 0xd5a7, 0xb1d6, 0xb1d5, 0xb1ce, 0xb1d1,
+ 0xb1d4, 0xb1d0, 0x0000, 0x0000, 0xd976, 0xb1cd, 0xb4af, 0xfccb,
+ 0x0000, 0x0000, 0xb4b1, 0xb4b2, 0xd975, 0xd978, 0xb4b0, 0xd973,
+ 0xd977, 0x0000, 0xd974, 0x93b3, 0xb771, 0xfcca, 0x0000, 0xddbc,
+ 0x0000, 0x0000, 0xba56, 0xe1f4, 0xbee3, 0xbcc4, 0xe5bd, 0xbcc5,
+ 0xbcc6, 0xe5bf, 0xe5be, 0xe5c0, 0xe9b1, 0x0000, 0x0000, 0xe9b0,
+ 0xecef, 0xecee, 0xc0c4, 0xc0c5, 0xf248, 0xfcc9, 0x8dac, 0xa4e5,
+ 0xfbc6, 0x8967, 0x0000, 0x8c7e, 0xd979, 0x0000, 0x0000, 0x0000,
+ 0xb4b4, 0xb4b3, 0xddbd, 0x0000, 0xefd8, 0xc4e3, 0xf7de, 0xa4e6,
+ 0x0000, 0xaec6, 0x0000, 0xb1d8, 0xb1d7, 0xd97a, 0xd97b, 0xb772,
+ 0xe1f5, 0xba57, 0xe9b2, 0x0000, 0xa4e7, 0xa5b8, 0x0000, 0xa9f2,
+ 0xccc2, 0x0000, 0xcee9, 0xac48, 0xb1d9, 0x0000, 0xd97c, 0xb4b5,
+ 0xb773, 0x0000, 0xe5c1, 0xe5c2, 0x0000, 0xfccd, 0xecf0, 0xc25f,
+ 0xf8f0, 0xa4e8, 0x0000, 0xccc3, 0xa9f3, 0xac49, 0x9cf3, 0xceea,
+ 0x0000, 0xaec7, 0xd1d2, 0xd1d0, 0xd1d1, 0xaec8, 0xd1cf, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xb1db, 0xb1dc, 0xd5a8, 0xb1dd, 0xb1da,
+ 0xd97d, 0xfcd0, 0xd97e, 0xddbe, 0x95bb, 0x0000, 0xba59, 0xba58,
+ 0x0000, 0x0000, 0xecf1, 0xefd9, 0x0000, 0xf24a, 0xf249, 0xf44f,
+ 0xfcd3, 0xc95e, 0xac4a, 0xfcd4, 0x0000, 0xa4e9, 0xa5b9, 0x0000,
+ 0xa6ae, 0xa6ad, 0x0000, 0x0000, 0xa6af, 0xa6b0, 0xc9ee, 0xc9ed,
+ 0xcaf8, 0xa7f2, 0xcafb, 0xcafa, 0xcaf9, 0xcafc, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa9f4, 0xccc9, 0xccc5, 0xccce, 0x0000, 0x8dae
+};
+
+static const unsigned short big5hkscs_from_unicode_66[] = {
+ 0xa9fb, 0x0000, 0xa9f9, 0xccca, 0xccc6, 0xcccd, 0xa9f8, 0xaa40,
+ 0xccc8, 0xccc4, 0xa9fe, 0xcccb, 0xa9f7, 0xcccc, 0xa9fa, 0xa9fc,
+ 0xccd0, 0xcccf, 0xccc7, 0xa9f6, 0xa9f5, 0xa9fd, 0x0000, 0x0000,
+ 0xfcd7, 0x0000, 0x0000, 0x0000, 0xceef, 0xcef5, 0x93db, 0xac50,
+ 0xac4d, 0xceec, 0xcef1, 0xfe63, 0xac53, 0xac4b, 0xcef0, 0xac4e,
+ 0xac51, 0x0000, 0x0000, 0xcef3, 0x0000, 0xac4c, 0xcef8, 0xac4f,
+ 0x93d5, 0xac52, 0xceed, 0xcef2, 0xcef6, 0xceee, 0xceeb, 0x0000,
+ 0x0000, 0xcef7, 0xcef4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xaed0, 0xaec9, 0xaecc, 0xfcda, 0xaecf, 0x0000, 0xd1d5,
+ 0x9b71, 0xaeca, 0xd1d3, 0xfcdd, 0xaece, 0x0000, 0x0000, 0xaecb,
+ 0x0000, 0xd1d6, 0xaecd, 0x8daf, 0x0000, 0x0000, 0x0000, 0xfaf2,
+ 0x0000, 0xd5ac, 0xb1df, 0xd5ab, 0xd5ad, 0xb1de, 0xb1e3, 0xd1d4,
+ 0x0000, 0xd5aa, 0xd5ae, 0x93d8, 0xb1e0, 0xd5a9, 0xb1e2, 0xfcdf,
+ 0xb1e1, 0x0000, 0xd9a7, 0x93d3, 0xd9a2, 0x0000, 0xb4b6, 0xb4ba,
+ 0xb4b7, 0xd9a5, 0xd9a8, 0xfce1, 0xfce2, 0x0000, 0xb4b9, 0xb4be,
+ 0xddc7, 0xd9a6, 0xb4bc, 0xd9a3, 0xd9a1, 0x8e76, 0xb4bd, 0x0000,
+ 0xd9a4, 0x0000, 0x0000, 0x0000, 0xb779, 0xfc62, 0xddbf, 0xb776,
+ 0xb777, 0xb775, 0xddc4, 0xddc3, 0xddc0, 0xb77b, 0x93d1, 0x0000,
+ 0xddc2, 0xb4bb, 0x8db1, 0x0000, 0xddc6, 0xddc1, 0xb778, 0xb774,
+ 0xb77a, 0xddc5, 0x9859, 0x0000, 0x0000, 0xba5c, 0x0000, 0xe1f8,
+ 0xe1f7, 0xe1f6, 0xba5a, 0x0000, 0xfb52, 0x0000, 0x0000, 0x0000,
+ 0xba5b, 0xe5c5, 0xe5c8, 0xbcc8, 0x0000, 0xfb53, 0xbcc7, 0xe5c9,
+ 0xe5c4, 0xbcca, 0xe5c6, 0xfb4d, 0xbcc9, 0xe5c3, 0x9cbf, 0xe5c7,
+ 0xbee9, 0xbee6, 0xe9bb, 0xe9ba, 0x0000, 0xe9b9, 0xe9b4, 0x9b72,
+ 0xe9b5, 0x0000, 0x0000, 0x0000, 0xbee7, 0x0000, 0xbee4, 0xbee8,
+ 0xe9b3, 0xbee5, 0xe9b6, 0xe9b7, 0xe9bc, 0xfb50, 0x93be, 0xe9b8,
+ 0x0000, 0x0000, 0xecf2, 0x0000, 0x0000, 0x0000, 0xc0c7, 0x0000,
+ 0xefdc, 0xc0c6, 0xefda, 0xefdb, 0xc260, 0xc36e, 0xf24b, 0x0000,
+ 0xc36d, 0x0000, 0x0000, 0xf451, 0xf452, 0x0000, 0xc466, 0x0000,
+ 0xf450, 0xc4e4, 0x0000, 0xf7df, 0xc5ce, 0xf8aa, 0xf8ab, 0x0000,
+ 0xa4ea, 0x9df1, 0xa6b1, 0xa6b2, 0xa7f3, 0x0000, 0xccd1, 0xac54,
+ 0xaed1, 0xb1e4, 0x0000, 0x0000, 0xb0d2, 0x0000, 0xb4bf, 0xb4c0
+};
+
+static const unsigned short big5hkscs_from_unicode_67[] = {
+ 0xb3cc, 0xd9a9, 0xfceb, 0xb77c, 0xe1fa, 0xe1f9, 0x0000, 0x0000,
+ 0xa4eb, 0xa6b3, 0xccd2, 0xaa42, 0xa0bb, 0xaa41, 0x9b7e, 0xcef9,
+ 0xcefa, 0x0000, 0xd1d7, 0xd1d8, 0xaed2, 0xaed3, 0x8db3, 0xaed4,
+ 0xd5af, 0x8c52, 0x0000, 0xb1e6, 0x0000, 0xb4c2, 0x9ae8, 0xb4c1,
+ 0xddc8, 0xdf7a, 0xe1fb, 0xe9bd, 0x0000, 0x8edc, 0xc261, 0xc467,
+ 0xa4ec, 0x0000, 0xa5bc, 0xa5bd, 0xa5bb, 0xa5be, 0xa5ba, 0x0000,
+ 0x0000, 0xa6b6, 0x0000, 0xc9f6, 0xa6b5, 0xa6b7, 0x9cf9, 0x0000,
+ 0xc9f1, 0xc9f0, 0xc9f3, 0xc9f2, 0xc9f5, 0xa6b4, 0xc9ef, 0xc9f4,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xfa50, 0xcafd, 0xa7fd, 0xcafe,
+ 0xcb43, 0xa7fc, 0x0000, 0xcb47, 0xcb42, 0xcb45, 0xa7f5, 0xa7f6,
+ 0xa7f7, 0xa7f8, 0x0000, 0xa840, 0x0000, 0xcb41, 0xa7fa, 0xa841,
+ 0x0000, 0xcb40, 0xcb46, 0x0000, 0xa7f9, 0xcb44, 0xfcf1, 0xa7f4,
+ 0xa7fe, 0x98e7, 0xfcf3, 0x0000, 0x0000, 0x0000, 0x0000, 0xfcf2,
+ 0x0000, 0x0000, 0xaa57, 0x8cca, 0xccd4, 0xaa43, 0x0000, 0xaa4d,
+ 0xaa4e, 0xaa46, 0xaa58, 0xaa48, 0xccdc, 0xaa53, 0xccd7, 0xaa49,
+ 0xcce6, 0xcce7, 0xccdf, 0xccd8, 0xaa56, 0xcce4, 0xaa51, 0xaa4f,
+ 0x0000, 0xcce5, 0x0000, 0xcce3, 0xccdb, 0xccd3, 0xccda, 0xaa4a,
+ 0x0000, 0xaa50, 0x0000, 0xaa44, 0xccde, 0xccdd, 0xccd5, 0x93e5,
+ 0xaa52, 0xcce1, 0xccd6, 0xaa55, 0xcce8, 0xaa45, 0x0000, 0xaa4c,
+ 0xccd9, 0xcce2, 0xaa54, 0x0000, 0xaa47, 0xaa4b, 0x0000, 0xcce0,
+ 0x9a59, 0x0000, 0x0000, 0x0000, 0x8db5, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xfd4d, 0x0000, 0xcf5b, 0xac5c,
+ 0xac69, 0xfd5e, 0xcf56, 0xcf4c, 0xac62, 0xcf4a, 0xac5b, 0xcf45,
+ 0xac65, 0xcf52, 0xcefe, 0xcf41, 0x0000, 0x0000, 0x0000, 0x8f7d,
+ 0xcf44, 0xcefb, 0xcf51, 0xcf61, 0xac60, 0xcf46, 0xcf58, 0x0000,
+ 0xcefd, 0xcf5f, 0xcf60, 0xcf63, 0xcf5a, 0xcf4b, 0xcf53, 0xac66,
+ 0xac59, 0xac61, 0xac6d, 0xac56, 0xac58, 0x0000, 0x9547, 0xfcf6,
+ 0xcf43, 0xac6a, 0xac63, 0xcf5d, 0xcf40, 0xac6c, 0xac67, 0xcf49,
+ 0x0000, 0x0000, 0xac6b, 0xcf50, 0xcf48, 0xac64, 0xcf5c, 0xcf54,
+ 0x0000, 0xac5e, 0xcf62, 0xcf47, 0xac5a, 0xcf59, 0xcf4f, 0xac5f,
+ 0xcf55, 0xac57, 0xcefc, 0xac68, 0xaee3, 0xac5d, 0xcf4e, 0xcf4d,
+ 0xcf42, 0x9250, 0xcf5e, 0x0000, 0xcf57, 0x0000, 0x8968, 0xac55
+};
+
+static const unsigned short big5hkscs_from_unicode_68[] = {
+ 0x8db6, 0xfcfb, 0xa07d, 0x98fc, 0x8969, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfe4f, 0x0000, 0x0000,
+ 0x9256, 0x0000, 0xd1ec, 0xaeea, 0xd1ed, 0x0000, 0xd1e1, 0xaedf,
+ 0xaeeb, 0x0000, 0xd1da, 0xfac9, 0xd1e3, 0xd1eb, 0x93e8, 0xd1d9,
+ 0xd1f4, 0xaed5, 0xfcf8, 0x0000, 0x0000, 0xd1f3, 0xd1ee, 0x0000,
+ 0xd1ef, 0xaedd, 0xaee8, 0xd1e5, 0x0000, 0xd1e6, 0xd1f0, 0xd1e7,
+ 0x0000, 0xd1e2, 0xd1dc, 0xd1dd, 0xd1ea, 0xd1e4, 0x9ce3, 0xfda9,
+ 0xaed6, 0xaeda, 0xd1f2, 0xd1de, 0xaee6, 0xaee2, 0xfc44, 0x0000,
+ 0xaee5, 0xaeec, 0xaedb, 0xaee7, 0xd1e9, 0xaee9, 0xaed8, 0x9640,
+ 0xaed7, 0xd1db, 0x8db8, 0xd1df, 0xaee0, 0xd1f1, 0xd1e8, 0xd1e0,
+ 0xaee4, 0xaee1, 0x0000, 0xaed9, 0xaedc, 0x9b4a, 0x8fb9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfcfe, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x896a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xd5c4, 0x0000, 0xd5b4, 0xd5b5, 0xd5b9,
+ 0x0000, 0xd5c8, 0xd5c5, 0x0000, 0xd5be, 0xd5bd, 0xb1ed, 0xd5c1,
+ 0xd5d0, 0xd5b0, 0x0000, 0xd5d1, 0xd5c3, 0xd5d5, 0xd5c9, 0xb1ec,
+ 0xd5c7, 0xb1e7, 0xb1fc, 0xb1f2, 0x8db9, 0xb1f6, 0xb1f5, 0xd5b1,
+ 0x917e, 0xd5ce, 0xd5d4, 0xd5cc, 0xd5d3, 0x0000, 0x0000, 0xd5c0,
+ 0xd5b2, 0xd5d2, 0xd5c2, 0xb1ea, 0xb1f7, 0x0000, 0xd5cb, 0xb1f0,
+ 0x93f4, 0x0000, 0x0000, 0xd5ca, 0xd5b3, 0xb1f8, 0x0000, 0xb1fa,
+ 0xd5cd, 0xb1fb, 0xb1e9, 0xd5ba, 0xd5cf, 0x0000, 0xfb7c, 0xb1ef,
+ 0xb1f9, 0xd5bc, 0xd5c6, 0xd5b7, 0xd5bb, 0xb1f4, 0xd5b6, 0xb1e8,
+ 0xb1f1, 0xb1ee, 0xd5bf, 0xaede, 0xd9c0, 0xb1eb, 0x93e7, 0x0000,
+ 0x0000, 0x97ef, 0x0000, 0x0000, 0x0000, 0xfe4a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xfd45, 0xb1f3, 0x96a5, 0xd9c3, 0xd9d9,
+ 0xd9ce, 0xb4d6, 0xfee0, 0xb4d1, 0xd9bd, 0xb4d2, 0xd9cd, 0x0000,
+ 0xd9c6, 0xd9d3, 0xb4ce, 0xd9ab, 0xd9d5, 0xb4c4, 0xd9b3, 0xb4c7,
+ 0xb4c6, 0x0000, 0xb4d7, 0x0000, 0xd9ad, 0xd9cf, 0xd9d0, 0xb4c9,
+ 0xb4c5, 0xd9bb, 0x0000, 0xb4d0, 0xd9b6, 0x0000, 0xd9d1, 0xb4cc,
+ 0xd9c9, 0xd9d6, 0xd9b0, 0xd9b5, 0xd9af, 0x0000, 0xb4cb, 0xd9c2,
+ 0xddde, 0xd9b1, 0xb4cf, 0xd9ba, 0xd9d2, 0xb4ca, 0xd9b7, 0xd9b4,
+ 0xd9c5, 0xb4cd, 0xb4c3, 0xb4d9, 0xd9c8, 0xd9c7, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_69[] = {
+ 0xfd48, 0xfd47, 0xfef2, 0xfe6a, 0xd9ac, 0xb4c8, 0xd9d4, 0xd9bc,
+ 0xd9be, 0x8dbd, 0xd9cb, 0xd9ca, 0xd9aa, 0xb4d3, 0xb4d5, 0xd9b2,
+ 0xd9b9, 0xd9c1, 0xb4d4, 0xd9b8, 0xd9c4, 0xd9d7, 0x0000, 0xd9cc,
+ 0x9ba1, 0x8ca2, 0x9ab7, 0x8efc, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd9d8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd9ae, 0x0000, 0x9fa1, 0x0000, 0x0000, 0xddf2,
+ 0xb7a6, 0x0000, 0xddf0, 0xdddb, 0xdde0, 0xddd9, 0xfd51, 0xddec,
+ 0xddcb, 0xddd2, 0x0000, 0xddea, 0xddf4, 0xdddc, 0xfaad, 0xddcf,
+ 0xdde2, 0xdde7, 0xddd3, 0x8dbe, 0xdde4, 0xddd0, 0x89a4, 0x0000,
+ 0xddd7, 0xddd8, 0xb7a8, 0xddeb, 0xdde9, 0x0000, 0xddcc, 0xddee,
+ 0x0000, 0xddef, 0xddf1, 0xb7ac, 0xb7a4, 0x9ad9, 0xd5b8, 0xddd4,
+ 0xdde6, 0xddd5, 0xb7a1, 0xb7b1, 0xdded, 0xb7af, 0xb7ab, 0xddca,
+ 0xb7a3, 0xfd4e, 0xddcd, 0xb7b0, 0x8dc0, 0xdddd, 0xddc9, 0x97f0,
+ 0xb7a9, 0xdde1, 0xddd1, 0xb7aa, 0xddda, 0xb77e, 0xb4d8, 0xdde3,
+ 0xd9bf, 0xddce, 0x93b4, 0xfd44, 0xdde8, 0xb7a5, 0xdde5, 0xb7a2,
+ 0xdddf, 0xb7ad, 0xddd6, 0xddf3, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9fa7, 0x0000, 0xb7a7, 0xdec6, 0x0000, 0x8dc2, 0xb7ae, 0x0000,
+ 0x0000, 0x0000, 0x99b6, 0x0000, 0x0000, 0xe24a, 0xe248, 0x0000,
+ 0xe25e, 0xe246, 0x0000, 0xe258, 0xb77d, 0xba5f, 0xe242, 0xe25d,
+ 0xfd52, 0xe247, 0xe255, 0xba64, 0xba5d, 0x0000, 0xe25b, 0x8dc1,
+ 0xe240, 0xe25a, 0x8e46, 0xba6f, 0xe251, 0xe261, 0xba6d, 0xe249,
+ 0xba5e, 0xe24b, 0xe259, 0xba67, 0xe244, 0xba6b, 0xba61, 0xe24d,
+ 0xe243, 0xe1fc, 0xa0d1, 0xe257, 0xba68, 0xe260, 0xe1fd, 0xba65,
+ 0x0000, 0xe253, 0x0000, 0xba66, 0xe245, 0xe250, 0xe24c, 0xe24e,
+ 0x9fca, 0xba60, 0xe25f, 0xba6e, 0xe24f, 0x0000, 0xe262, 0x0000,
+ 0x0000, 0xe1fe, 0xe254, 0xba63, 0xba6c, 0xba6a, 0xe241, 0xe256,
+ 0xba69, 0x92cf, 0x0000, 0xba62, 0xe252, 0x9cf4, 0x8dc4, 0x0000,
+ 0x0000, 0xe25c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xfd41, 0xe5d5, 0x0000, 0xe5d1, 0xe5cd, 0xe5e1, 0xe5de,
+ 0xbccd, 0x9b4c, 0x0000, 0xe5e5, 0xe5d4, 0xbcd8, 0xe5db, 0x0000,
+ 0x0000, 0xe5d0, 0xe5da, 0xbcd5, 0xe5ee, 0x0000, 0xe5eb, 0xe5dd,
+ 0xe5ce, 0xfd57, 0xfcef, 0xe5e2, 0xe5e4, 0xbcd1, 0xe5d8, 0xe5d3
+};
+
+static const unsigned short big5hkscs_from_unicode_6a[] = {
+ 0xe5ca, 0xbcce, 0xbcd6, 0x9cde, 0xe5e7, 0xbcd7, 0xe5cb, 0xe5ed,
+ 0xe5e0, 0xe5e6, 0xbcd4, 0xfd42, 0x986c, 0xe5e3, 0x0000, 0xe5ea,
+ 0x0000, 0xbcd9, 0x0000, 0xbcd3, 0xe5dc, 0xe5cf, 0xe5ef, 0xe5cc,
+ 0xe5e8, 0xbcd0, 0x97f9, 0xe5d6, 0x9558, 0xe5d7, 0xbccf, 0xbccc,
+ 0xe5d2, 0xbcd2, 0x0000, 0xbccb, 0x0000, 0xe5e9, 0xe5ec, 0xe5d9,
+ 0xe9ca, 0x0000, 0x0000, 0x985e, 0xfe7b, 0x94cd, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe9c2, 0x93ee, 0xe9be, 0xbef6, 0x0000, 0x0000,
+ 0xbeeb, 0xbef0, 0xbeec, 0xe9cc, 0xe9d7, 0xbeea, 0xe9c4, 0xe9cd,
+ 0xe5df, 0xe9ce, 0x0000, 0x8ca3, 0xbef1, 0xfd5a, 0xe9dd, 0xbef5,
+ 0xbef8, 0xe9c0, 0x0000, 0xbef4, 0x93f5, 0xe9db, 0xe9dc, 0xe9d2,
+ 0xe9d1, 0xe9c9, 0x93ef, 0x8eea, 0xe9d3, 0xe9da, 0xe9d9, 0x8f5b,
+ 0xbeef, 0xbeed, 0xe9cb, 0xe9c8, 0x0000, 0xe9c5, 0xe9d8, 0xbef7,
+ 0xe9d6, 0xbef3, 0xbef2, 0x8c5e, 0xe9d0, 0x8dc6, 0xe9bf, 0xe9c1,
+ 0xe9c3, 0xe9d5, 0xe9cf, 0xbeee, 0x0000, 0xe9c6, 0x0000, 0xe9d4,
+ 0x0000, 0x8dc8, 0x0000, 0x0000, 0x8dc7, 0x0000, 0xe9c7, 0x0000,
+ 0x0000, 0x0000, 0x93f7, 0x0000, 0x0000, 0x0000, 0xc0cf, 0xed45,
+ 0xc0c8, 0xecf5, 0x8dc9, 0xed41, 0xc0ca, 0xed48, 0x0000, 0xecfc,
+ 0x0000, 0xecf7, 0xfbf2, 0x0000, 0xed49, 0xecf3, 0xecfe, 0x9670,
+ 0xc0d1, 0xed44, 0xed4a, 0xecfd, 0xc0c9, 0xed40, 0xecf4, 0xc0d0,
+ 0x0000, 0x8dcb, 0xed47, 0xecf9, 0xc0cc, 0xfd5c, 0xecfb, 0xecf8,
+ 0xc0d2, 0xecfa, 0xc0cb, 0xc0ce, 0xed43, 0xecf6, 0xed46, 0x8f65,
+ 0xed42, 0x0000, 0x0000, 0x8dcd, 0xc263, 0xefe7, 0xc268, 0xc269,
+ 0x0000, 0x9da8, 0x94f9, 0xc262, 0xefe6, 0x8dce, 0xefe3, 0xefe4,
+ 0xc266, 0xefde, 0xefe2, 0xc265, 0x0000, 0xefdf, 0x93ea, 0x0000,
+ 0x0000, 0x0000, 0xc267, 0xc264, 0x0000, 0xefdd, 0xefe1, 0xefe5,
+ 0xfd5f, 0x93f0, 0x9fb6, 0xf251, 0xf24e, 0xf257, 0x0000, 0xf256,
+ 0xf254, 0xf24f, 0x0000, 0xc372, 0x8dcf, 0x0000, 0x0000, 0x0000,
+ 0x9763, 0xf250, 0xc371, 0xc0cd, 0xf253, 0xc370, 0xf258, 0xf252,
+ 0xf24d, 0xefe0, 0x0000, 0x0000, 0x0000, 0xc36f, 0x0000, 0xf24c,
+ 0xf456, 0x0000, 0xf455, 0xf255, 0xc468, 0x0000, 0xf459, 0xf45a,
+ 0xf454, 0xf458, 0x0000, 0xf453, 0x0000, 0x0000, 0x8dd0, 0x0000,
+ 0xf5d1, 0xf457, 0xc4e7, 0xc4e5, 0xf5cf, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_6b[] = {
+ 0xf5d2, 0x0000, 0xf5ce, 0xf5d0, 0xc4e6, 0x93f1, 0x0000, 0x0000,
+ 0xf6e5, 0xf6e6, 0xc576, 0xf6e4, 0x0000, 0x0000, 0x0000, 0xf7e2,
+ 0xc5cf, 0xf7e0, 0xf7e1, 0xf8ac, 0x0000, 0x0000, 0xc656, 0xf8f3,
+ 0xf8f1, 0xf8f2, 0xf8f4, 0x0000, 0x0000, 0xfd62, 0xf9bb, 0x0000,
+ 0xa4ed, 0xa6b8, 0x0000, 0xaa59, 0x0000, 0xcce9, 0x0000, 0x0000,
+ 0xcf64, 0x0000, 0x0000, 0x0000, 0xd1f5, 0xd1f7, 0x0000, 0xd1f6,
+ 0x0000, 0xd1f8, 0xb1fd, 0xd5d7, 0xd1f9, 0xfd65, 0xd5d6, 0xd5d8,
+ 0xd5d9, 0xd9da, 0xb4db, 0xd9db, 0xd9dd, 0xb4dc, 0xb4da, 0xd9dc,
+ 0x0000, 0xddfa, 0xddf8, 0xddf7, 0x0000, 0xddf6, 0xddf5, 0xb7b2,
+ 0xddf9, 0xba70, 0xe263, 0xe265, 0xba71, 0xe264, 0xbcdb, 0x0000,
+ 0xbcda, 0xe5f0, 0x9fdb, 0x0000, 0xe9df, 0xe9de, 0xe9e0, 0x93f8,
+ 0x0000, 0xbef9, 0x0000, 0xed4b, 0xc0d3, 0x0000, 0xefe8, 0xc26a,
+ 0xf259, 0xc577, 0xa4ee, 0xa5bf, 0xa6b9, 0xa842, 0xaa5a, 0xaa5b,
+ 0x0000, 0x0000, 0xac6e, 0x0000, 0x0000, 0xd1fa, 0x0000, 0x8bf7,
+ 0x0000, 0x0000, 0xb7b3, 0x0000, 0xfd66, 0x0000, 0xe6d1, 0xbefa,
+ 0xc26b, 0xa4ef, 0x8bcf, 0xa6ba, 0x0000, 0x0000, 0xcceb, 0xaa5c,
+ 0xccea, 0x8dd1, 0xcf65, 0xac6f, 0xcf66, 0x0000, 0xac70, 0x0000,
+ 0xd1fc, 0xaeee, 0xaeed, 0x0000, 0xd5de, 0xd5dc, 0xd5dd, 0xd5db,
+ 0x0000, 0xd5da, 0x0000, 0x0000, 0xd9de, 0xd9e1, 0xb4de, 0xd9df,
+ 0xb4dd, 0xd9e0, 0x0000, 0xddfb, 0x0000, 0x0000, 0xe266, 0xe267,
+ 0xe268, 0x0000, 0xe5f3, 0xe5f2, 0xbcdc, 0xe5f1, 0xe5f4, 0xe9e1,
+ 0x0000, 0x0000, 0xe9e2, 0xe9e3, 0x0000, 0xed4c, 0xc0d4, 0xc26c,
+ 0xf25a, 0x0000, 0xc4e8, 0xc95f, 0x0000, 0xac71, 0xcf67, 0xaeef,
+ 0x0000, 0x0000, 0xb1fe, 0x0000, 0xb4df, 0xd9e2, 0x0000, 0xb7b5,
+ 0xb7b4, 0x8dd2, 0x0000, 0xe269, 0xe26a, 0xbcdd, 0xbcde, 0xe9e5,
+ 0xe9e4, 0xefe9, 0xf7e3, 0xa4f0, 0xc960, 0xa5c0, 0x0000, 0xa843,
+ 0xcb48, 0x0000, 0xac72, 0xb7b6, 0xa4f1, 0x0000, 0xcf68, 0xac73,
+ 0xcf69, 0x0000, 0xc0d5, 0xa4f2, 0xfd71, 0x0000, 0xccec, 0x0000,
+ 0xcf6a, 0xfd6f, 0xd242, 0xd241, 0xd1fe, 0x0000, 0xd1fd, 0xd243,
+ 0xd240, 0x0000, 0x8dd3, 0xb240, 0xb241, 0x0000, 0x0000, 0xb4e0,
+ 0xd9e3, 0x0000, 0xd9e4, 0xd9e5, 0x0000, 0x0000, 0x0000, 0xde41,
+ 0xde42, 0xde40, 0x9fe7, 0xddfd, 0xddfe, 0xb7b7, 0xe26b, 0xe5f7
+};
+
+static const unsigned short big5hkscs_from_unicode_6c[] = {
+ 0xe5f6, 0xe5f5, 0xe5f8, 0xe9e7, 0xe9e6, 0xbefb, 0xe9e8, 0x0000,
+ 0xc0d6, 0xed4d, 0x0000, 0xefea, 0xf25b, 0xf6e7, 0x0000, 0xa4f3,
+ 0xa5c2, 0xa5c1, 0x0000, 0xaa5d, 0xc961, 0xc97e, 0xa6bb, 0x0000,
+ 0xc9f7, 0xcb49, 0xcb4a, 0xaa5e, 0x90bd, 0xcced, 0x0000, 0xac74,
+ 0xcf6b, 0xcf6c, 0x0000, 0xaef0, 0xaef4, 0xd244, 0xaef3, 0xaef1,
+ 0xaef2, 0x0000, 0xd5df, 0xb242, 0xb4e3, 0x0000, 0xb4e1, 0xb4e2,
+ 0xd9e6, 0x9fd0, 0x0000, 0xba72, 0xa4f4, 0x8bd0, 0xc9a1, 0xfd72,
+ 0xa5c3, 0x9cae, 0x8bd1, 0xc9a4, 0x0000, 0x8adb, 0xa5c6, 0xc9a3,
+ 0xa5c5, 0xa5c4, 0xa844, 0xc9a2, 0x0000, 0x0000, 0xc9f8, 0x0000,
+ 0x0000, 0xfae4, 0xc9fc, 0xc9fe, 0xca40, 0xa6c5, 0xa6c6, 0xc9fb,
+ 0xa6c1, 0x0000, 0xc9f9, 0x0000, 0xc9fd, 0xa6c2, 0x0000, 0xa6bd,
+ 0x95ce, 0xa6be, 0xfd76, 0xa6c4, 0xc9fa, 0xa6bc, 0xa845, 0xa6bf,
+ 0xa6c0, 0xa6c3, 0x0000, 0x0000, 0x0000, 0xcb5b, 0xcb59, 0xcb4c,
+ 0xa851, 0xcb53, 0xa84c, 0xcb4d, 0x0000, 0xcb55, 0xfb62, 0xcb52,
+ 0xa84f, 0xcb51, 0xa856, 0xcb5a, 0xa858, 0x8dd4, 0xa85a, 0x0000,
+ 0xcb4b, 0xfd78, 0xa84d, 0xcb5c, 0x0000, 0xa854, 0xa857, 0x8ee3,
+ 0xcd45, 0xa847, 0xa85e, 0xa855, 0xcb4e, 0xa84a, 0xa859, 0xcb56,
+ 0xa848, 0xa849, 0xcd43, 0xcb4f, 0xa850, 0xa85b, 0xcb5d, 0xcb50,
+ 0xa84e, 0x0000, 0xa853, 0xccee, 0xa85c, 0xcb57, 0xa852, 0x0000,
+ 0xa85d, 0xa846, 0xcb54, 0xa84b, 0xfdb7, 0xcd44, 0x0000, 0x9076,
+ 0x0000, 0x0000, 0x98c6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8dd5, 0xaa6a, 0xaa7a, 0xccf5, 0xaa71, 0x97d1,
+ 0xcd4b, 0xaa62, 0x9eb6, 0xaa65, 0xcd42, 0x0000, 0xccf3, 0xccf7,
+ 0xaa6d, 0xaa6f, 0xccfa, 0xaa76, 0xaa68, 0xaa66, 0xaa67, 0xaa75,
+ 0xcd47, 0xaa70, 0xccf9, 0xccfb, 0xaa6e, 0xaa73, 0xccfc, 0xcd4a,
+ 0x0000, 0xac75, 0xaa79, 0xfac7, 0xaa63, 0xcd49, 0xa042, 0xcd4d,
+ 0xccf8, 0xcd4f, 0xcd40, 0xaa6c, 0xccf4, 0xaa6b, 0xaa7d, 0xaa72,
+ 0x0000, 0xccf2, 0xcf75, 0xaa78, 0xaa7c, 0xcd41, 0xcd46, 0x9873,
+ 0xaa7e, 0xaa77, 0xaa69, 0xaa5f, 0x0000, 0xaa64, 0x0000, 0xccf6,
+ 0xaa60, 0xcd4e, 0x9ffc, 0xccf0, 0xccef, 0xccfd, 0xccf1, 0xaa7b,
+ 0xaef5, 0xaa74, 0xccfe, 0xaa61, 0x0000, 0xaca6, 0x0000, 0x0000,
+ 0x0000, 0xcd4c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8ca5
+};
+
+static const unsigned short big5hkscs_from_unicode_6d[] = {
+ 0xcf7c, 0xcfa1, 0x8dd7, 0xcfa4, 0xcf77, 0x92fb, 0x8dd8, 0xcfa7,
+ 0xcfaa, 0xcfac, 0xcf74, 0xac76, 0xac7b, 0xd249, 0xacad, 0xcfa5,
+ 0xcfad, 0xcf7b, 0xcf73, 0x0000, 0x0000, 0x0000, 0xd264, 0xac7e,
+ 0xcfa2, 0xcf78, 0xcf7a, 0xaca5, 0x0000, 0xcf7d, 0xac7d, 0xcf70,
+ 0xcfa8, 0x0000, 0xcfab, 0x0000, 0x944f, 0xac7a, 0x8dd9, 0xaca8,
+ 0xcf6d, 0xacaa, 0xac78, 0xacae, 0xcfa9, 0xcf6f, 0xacab, 0xd25e,
+ 0xcd48, 0xac7c, 0xac77, 0xcf76, 0xcf6e, 0xacac, 0xaca4, 0xcfa3,
+ 0xaca9, 0xaca7, 0xcf79, 0xaca1, 0xcf71, 0xaca2, 0xaca3, 0xcf72,
+ 0xcfa6, 0xac79, 0xcf7e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x896b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x97ce,
+ 0xd24c, 0xaefd, 0xaf43, 0xfaf3, 0xfdae, 0x0000, 0xd255, 0xd25b,
+ 0xd257, 0xd24a, 0xd24d, 0xd246, 0xd247, 0xaf4a, 0xaefa, 0xd256,
+ 0xd25f, 0xaf45, 0xaef6, 0x0000, 0xaf40, 0xd24e, 0xaf42, 0xd24f,
+ 0xd259, 0xfbaf, 0x92b7, 0x0000, 0xaf44, 0xd268, 0xd248, 0xaefc,
+ 0xaefb, 0xaf48, 0xd245, 0xd266, 0xd25a, 0xd267, 0xd261, 0xd253,
+ 0xd262, 0x8dda, 0xd25c, 0xd265, 0xd263, 0xaf49, 0xd254, 0xaef9,
+ 0xaef8, 0xaf41, 0xaf47, 0xd260, 0xaf46, 0xd251, 0xb243, 0x9c5a,
+ 0xd269, 0xd250, 0xd24b, 0xaefe, 0xaf4b, 0xaef7, 0xfdad, 0xd258,
+ 0xd25d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8ddc, 0x9444, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xb265, 0xd5e1, 0xd5e5, 0x0000, 0xb252, 0xb250,
+ 0x0000, 0x8ddd, 0xb247, 0xd5e3, 0xd5e2, 0xb25b, 0x0000, 0xd5e8,
+ 0xb255, 0xa0d6, 0xd5fa, 0xd647, 0xb244, 0xd5f7, 0xd5f0, 0xb267,
+ 0xd5e0, 0x0000, 0xd5fc, 0x0000, 0xb264, 0xb258, 0xb263, 0xb24e,
+ 0xd5ec, 0xd5fe, 0xd5f6, 0xb24f, 0xb249, 0xd645, 0x0000, 0xd5fd,
+ 0xd640, 0xb251, 0xb259, 0xd642, 0xd5ea, 0xd5fb, 0xd5ef, 0xd644,
+ 0xb25e, 0xb246, 0xb25c, 0xd5f4, 0xd5f2, 0xd5f3, 0xb253, 0xd5ee,
+ 0xd5ed, 0xb248, 0xd5e7, 0xd646, 0xb24a, 0xd5f1, 0xb268, 0x0000,
+ 0xb262, 0xd5e6, 0xb25f, 0xb25d, 0xb266, 0xd5f8, 0xb261, 0xd252,
+ 0xd5f9, 0xb260, 0xd641, 0xb245, 0xd5f5, 0xb257, 0xd5e9, 0xb256,
+ 0x0000, 0xb254, 0xb24c, 0xb24b, 0xd9e7, 0xd643, 0x8c41, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_6e[] = {
+ 0xd5eb, 0x0000, 0x97d5, 0xd9fc, 0x944a, 0xb24d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x944d, 0x0000, 0x0000, 0x0000, 0x0000, 0x97cb,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8dde, 0x0000, 0x0000,
+ 0x8ddf, 0xb541, 0xb25a, 0xb4ee, 0xd9f6, 0xfdb8, 0x0000, 0xd9ea,
+ 0xb4eb, 0xb4e7, 0xda49, 0xb4ed, 0xb4f1, 0xb4ec, 0xb4f5, 0xda4d,
+ 0xda44, 0x8de0, 0xfef9, 0xd9f1, 0xb4fa, 0xb4f4, 0xd9fd, 0xfdbb,
+ 0xda4a, 0xda43, 0xb4e8, 0xd9f7, 0xb4f7, 0xda55, 0xda56, 0x0000,
+ 0xb4e5, 0xda48, 0xb4f9, 0xd9fb, 0xd9ed, 0xd9ee, 0xb4fd, 0xd9f2,
+ 0xd9f9, 0xd9f3, 0x0000, 0xb4fb, 0xb544, 0xd9ef, 0xd9e8, 0xd9e9,
+ 0x0000, 0xd9eb, 0xb4ea, 0xd9f8, 0x0000, 0xb4f8, 0xb542, 0xfdc0,
+ 0xfcf9, 0xd9fa, 0xda53, 0xda4b, 0xb4e6, 0xda51, 0xb4f2, 0x0000,
+ 0xb4f0, 0xfb7e, 0xda57, 0xb4ef, 0xda41, 0xd9f4, 0xd9fe, 0xb547,
+ 0xda45, 0xda42, 0xd9f0, 0xb543, 0xda4f, 0xda4c, 0xda54, 0xb4e9,
+ 0xda40, 0xb546, 0x0000, 0xda47, 0x0000, 0x0000, 0xb4f3, 0xb4f6,
+ 0x0000, 0xda46, 0xb545, 0xd9f5, 0xd5e4, 0x0000, 0x92b3, 0xda50,
+ 0xda4e, 0xda52, 0x0000, 0x0000, 0xfdaf, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8de1, 0x0000,
+ 0xd9ec, 0xb540, 0x0000, 0x95d3, 0x0000, 0xde61, 0xde60, 0xde46,
+ 0xb7bd, 0x0000, 0xde5f, 0xde49, 0xde4a, 0x0000, 0xb7c7, 0xde68,
+ 0xb7c2, 0xde5e, 0x89c1, 0xde43, 0xb7c8, 0xb7be, 0xde52, 0xde48,
+ 0xde4b, 0xde63, 0xb7b8, 0xde6a, 0xde62, 0xb7c1, 0xde57, 0xb7cc,
+ 0x0000, 0x0000, 0xb7cb, 0xb7c5, 0x0000, 0x0000, 0xde69, 0xb7b9,
+ 0xde55, 0xde4c, 0xde59, 0xde65, 0xb7cd, 0xfd68, 0xb7bb, 0xde54,
+ 0x9cb7, 0xde4d, 0xb7c4, 0x8de3, 0xb7c3, 0xde50, 0xde5a, 0xde64,
+ 0xde47, 0xde51, 0xb7bc, 0xde5b, 0xb7c9, 0xb7c0, 0xde4e, 0xb7bf,
+ 0xde45, 0xde53, 0xde67, 0xb4fe, 0xbab0, 0xde56, 0xe26c, 0xde58,
+ 0xde66, 0xb7c6, 0xde4f, 0xb7ba, 0xb7ca, 0xbcf0, 0xde44, 0x0000,
+ 0xde5d, 0xfac0, 0x8de5, 0xfa64, 0xde5c, 0x8947, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8de4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8de7, 0x8de8, 0x0000, 0xe2aa, 0xbaad, 0xe27d, 0xe2a4, 0xbaa2,
+ 0x0000, 0xe26e, 0xbaaf, 0x0000, 0xba77, 0xe26d, 0xe2b0, 0xbab1,
+ 0xe271, 0xe2a3, 0xfdc7, 0xe273, 0xe2b3, 0xe2af, 0xba75, 0xbaa1
+};
+
+static const unsigned short big5hkscs_from_unicode_6f[] = {
+ 0xe653, 0xbaae, 0xba7d, 0xe26f, 0xfdb0, 0xe2ae, 0xbaa3, 0xe2ab,
+ 0xe2b8, 0xe275, 0xe27e, 0x9445, 0x97d6, 0xe2b6, 0xe2ac, 0xba7c,
+ 0x0000, 0x0000, 0xe27c, 0xba76, 0xba74, 0xbaa8, 0xfcc6, 0x9844,
+ 0xe27a, 0xe277, 0xe278, 0x0000, 0xe2b2, 0x0000, 0xe2b7, 0xe2b5,
+ 0xba7a, 0xe2b9, 0xba7e, 0xbaa7, 0x8de9, 0xe270, 0xe5fa, 0xe279,
+ 0x0000, 0xba78, 0xbaac, 0xbaa9, 0xba7b, 0xe2a5, 0xe274, 0xbaaa,
+ 0xe2a7, 0xbaa4, 0xbaa6, 0xba73, 0x8dea, 0xe2a9, 0xe2a1, 0xe272,
+ 0xbaa5, 0xe2b1, 0xe2b4, 0xe27b, 0xe2a8, 0xfe50, 0xba79, 0xbcdf,
+ 0xe2a6, 0xe5f9, 0x0000, 0xe2ad, 0xfdcc, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe276, 0xe644,
+ 0xe64e, 0xbce2, 0xe64d, 0xe659, 0xbce4, 0xe64b, 0x9da7, 0xe64f,
+ 0xbcef, 0x0000, 0xe646, 0xbce7, 0xfdcd, 0xe652, 0xe9f0, 0xbcf3,
+ 0xbcf2, 0xe654, 0xe643, 0xe65e, 0xbced, 0x0000, 0xbce3, 0xe657,
+ 0x0000, 0xe65b, 0xe660, 0xe655, 0xe649, 0xbce6, 0xbce9, 0xbcf1,
+ 0xbcec, 0x0000, 0xe64c, 0xe2a2, 0xfdcf, 0x0000, 0xe648, 0xe65f,
+ 0xbce8, 0x95d2, 0xbceb, 0xe661, 0xbce0, 0xe656, 0xe5fb, 0xe65c,
+ 0xc0df, 0x8ded, 0xe64a, 0x0000, 0xbce1, 0xe645, 0xbce5, 0xe5fc,
+ 0xbaab, 0xe641, 0xfcba, 0xe65a, 0xe642, 0xe640, 0xbcea, 0x0000,
+ 0xe658, 0x0000, 0xe5fe, 0xe651, 0xe650, 0xe65d, 0xe647, 0xbcee,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfdc5, 0xe9f3, 0xfdd2,
+ 0xbf49, 0xbefe, 0xea40, 0xe9eb, 0xbf41, 0xe9f7, 0xbf48, 0xbf43,
+ 0xe9f5, 0xed4f, 0xe9fb, 0xea42, 0xe9fa, 0xe9e9, 0xe9f8, 0xea44,
+ 0xea46, 0xbefd, 0xea45, 0xbf44, 0xbf4a, 0x9cdc, 0xbf47, 0x0000,
+ 0xe9fe, 0xbf46, 0xe9f9, 0x95cf, 0xe9ed, 0xe9f2, 0x8dee, 0xe9fd,
+ 0xbf45, 0xbf42, 0xbefc, 0xbf40, 0xe9f1, 0x0000, 0xe5fd, 0xe9ec,
+ 0xe9ef, 0xea41, 0xe9f4, 0xe9ea, 0xed4e, 0xea43, 0xe9ee, 0xe9fc,
+ 0x0000, 0x0000, 0x0000, 0xfdd4, 0xed51, 0xc0e3, 0x0000, 0x0000,
+ 0xc0d7, 0x96ec, 0x96eb, 0xc0db, 0xed53, 0xed59, 0xed57, 0xc0d9,
+ 0xc0da, 0xc0e1, 0xed5a, 0xed52, 0xc0dc, 0x0000, 0xed56, 0xed55,
+ 0xed5b, 0xc0e2, 0x0000, 0xc0dd, 0xc0e0, 0xed54, 0xc0e4, 0xc0de,
+ 0xc0e5, 0xc0d8, 0xed58, 0x0000, 0xed50, 0x0000, 0x90b6, 0xeff7,
+ 0xfdc3, 0x0000, 0xc271, 0xeff4, 0xeff6, 0x0000, 0xc26f, 0xeff2
+};
+
+static const unsigned short big5hkscs_from_unicode_70[] = {
+ 0xeff3, 0xefee, 0x0000, 0x98ab, 0xe9f6, 0xefef, 0xc270, 0xefeb,
+ 0x0000, 0xc26d, 0xeff8, 0xc26e, 0xefec, 0xefed, 0xeff1, 0xc273,
+ 0x0000, 0xc272, 0x0000, 0x0000, 0xeff0, 0xc378, 0xf25f, 0xf265,
+ 0xc379, 0xf25c, 0xc376, 0xc373, 0xf267, 0xc377, 0x96ee, 0xc374,
+ 0xf25e, 0xf261, 0xf262, 0xf263, 0xf266, 0x0000, 0xeff5, 0xf25d,
+ 0xc375, 0xf264, 0xf268, 0xf260, 0x8df4, 0x0000, 0x0000, 0xf45d,
+ 0xc46a, 0xf460, 0xc46b, 0xf468, 0xf45f, 0xf45c, 0x0000, 0xf45e,
+ 0xf462, 0xf465, 0xf464, 0xf467, 0xf45b, 0x0000, 0xc469, 0xf463,
+ 0xf466, 0xf469, 0xf461, 0xf5d3, 0xf5d4, 0xf5d8, 0xf5d9, 0x0000,
+ 0xf5d6, 0xf5d7, 0xf5d5, 0xfde0, 0xc4e9, 0x8c67, 0x0000, 0x0000,
+ 0x8df6, 0xc578, 0xf6eb, 0x0000, 0x8df7, 0xf6e8, 0xf6e9, 0xf6ea,
+ 0xc579, 0x0000, 0xf7e5, 0xf7e4, 0x8ffa, 0xf8af, 0xc5f4, 0xf8ad,
+ 0xf8b0, 0xf8ae, 0xf8f5, 0xc657, 0xc665, 0xf9a3, 0xf96c, 0x97d0,
+ 0xf9a2, 0xf9d0, 0xf9d1, 0xa4f5, 0x8bd2, 0x0000, 0x0000, 0x8df8,
+ 0xa6c7, 0xca41, 0x0000, 0x0000, 0xcb5e, 0x90d9, 0xa85f, 0x8c47,
+ 0xa862, 0xfaf0, 0xcb5f, 0x0000, 0xa860, 0xa861, 0xfde1, 0x8df9,
+ 0x0000, 0xfde3, 0xcd58, 0xcd5a, 0xcd55, 0xcd52, 0xcd54, 0x0000,
+ 0x0000, 0x8dfa, 0xaaa4, 0xfb63, 0x0000, 0x0000, 0xaaa2, 0x90a6,
+ 0x0000, 0xcd56, 0xaaa3, 0xcd53, 0xcd50, 0xaaa1, 0xcd57, 0x0000,
+ 0xcd51, 0xaaa5, 0xcd59, 0x0000, 0x0000, 0x0000, 0x0000, 0xcfaf,
+ 0x9970, 0xcfb3, 0x0000, 0x91eb, 0xacb7, 0x9770, 0x986f, 0xfde2,
+ 0x0000, 0xcfb6, 0x0000, 0xacaf, 0xacb2, 0xacb4, 0xacb6, 0xacb3,
+ 0xcfb2, 0xcfb1, 0x0000, 0xacb1, 0xcfb4, 0xcfb5, 0x0000, 0xcfae,
+ 0xacb5, 0x98f2, 0xacb0, 0x9afc, 0x896c, 0xfdfd, 0xcfb0, 0x0000,
+ 0x995e, 0x0000, 0x0000, 0x0000, 0x95bd, 0xd277, 0xd278, 0xd279,
+ 0xaf50, 0x0000, 0xaf4c, 0xd26e, 0xfde4, 0xd276, 0xd27b, 0xaf51,
+ 0x91e6, 0xd26c, 0xd272, 0xd26b, 0xd275, 0xfde5, 0xfde6, 0xd271,
+ 0xaf4d, 0xaf4f, 0xd27a, 0x0000, 0xd26a, 0xd26d, 0xd273, 0xfde7,
+ 0xd274, 0xd27c, 0xd270, 0x0000, 0xaf4e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb26d,
+ 0xd64e, 0x9454, 0x0000, 0xd650, 0xd64c, 0x99b8, 0xd658, 0xd64a,
+ 0xd657, 0xb269, 0xd648, 0xda5b, 0xd652, 0xb26c, 0x97e9, 0xd653
+};
+
+static const unsigned short big5hkscs_from_unicode_71[] = {
+ 0xd656, 0x0000, 0xd65a, 0x0000, 0xd64f, 0x9346, 0xd654, 0x0000,
+ 0x0000, 0xb26a, 0xb26b, 0xd659, 0xd64d, 0xd649, 0xd65b, 0x0000,
+ 0xd651, 0x0000, 0x0000, 0xd655, 0x0000, 0x0000, 0x0000, 0xd64b,
+ 0x0000, 0xb548, 0xb549, 0xda65, 0xb54f, 0x9863, 0xda59, 0xda62,
+ 0xda58, 0xb54c, 0xda60, 0xda5e, 0x0000, 0xda5f, 0xb54a, 0x0000,
+ 0xda63, 0x95bc, 0x0000, 0xfded, 0xfdf7, 0x0000, 0xda5c, 0xda5a,
+ 0xb54b, 0xda5d, 0xda61, 0x9870, 0x96f6, 0x8ea9, 0xb54d, 0x0000,
+ 0x0000, 0x0000, 0xda64, 0x9451, 0x0000, 0x0000, 0x8e43, 0x0000,
+ 0x8b5a, 0xde70, 0xde77, 0xde79, 0xdea1, 0xfdee, 0xb7da, 0xde6b,
+ 0x0000, 0xb7d2, 0xfdf0, 0xde7a, 0xb7d7, 0xdea2, 0xb7ce, 0xfdf4,
+ 0xde7d, 0x9bf5, 0xde6d, 0xde7e, 0xde6c, 0x0000, 0xb7dc, 0x0000,
+ 0xde78, 0xb7cf, 0xdea3, 0x0000, 0xb7d4, 0xde71, 0xb7d9, 0xde7c,
+ 0xde6f, 0xde76, 0xde72, 0xde6e, 0xb7d1, 0xb7d8, 0xb7d6, 0xb7d3,
+ 0xb7db, 0xb7d0, 0xde75, 0x977e, 0xb7d5, 0x0000, 0xfdf1, 0x0000,
+ 0xde7b, 0x9bd5, 0xde73, 0x9ac3, 0x0000, 0x97c8, 0xa0db, 0x91d0,
+ 0xde74, 0x0000, 0x9fe4, 0xe2c1, 0x8fdd, 0xbab4, 0x91e9, 0x0000,
+ 0xe2bd, 0xe2c3, 0xe2bf, 0x0000, 0xbab6, 0xe2be, 0xe2c2, 0xe2ba,
+ 0x98e0, 0xe2bc, 0xbab5, 0x0000, 0x92ca, 0x0000, 0x9857, 0xe2c0,
+ 0xe2bb, 0x8c51, 0xbab7, 0x0000, 0xbab2, 0x0000, 0xfdeb, 0xe2c4,
+ 0x9b49, 0xbab3, 0xe667, 0xe664, 0xe670, 0xe66a, 0xe66c, 0xbcf4,
+ 0xe666, 0xe66e, 0x9d76, 0x9eaf, 0xe66d, 0xe66b, 0x0000, 0xe671,
+ 0xbcf7, 0xe668, 0xe66f, 0x0000, 0xbcf5, 0x9ccc, 0x0000, 0xe663,
+ 0xe665, 0xbcf6, 0xe662, 0xe672, 0xfdea, 0xe669, 0x0000, 0x8df1,
+ 0xea4a, 0xbf51, 0xfdfb, 0x0000, 0xea55, 0xea53, 0xbf4b, 0xea49,
+ 0xea4c, 0xea4d, 0xea48, 0xbf55, 0xbf56, 0xea47, 0xea56, 0xea51,
+ 0xbf4f, 0xbf4c, 0xea50, 0xea4e, 0x0000, 0x0000, 0xbf52, 0xea52,
+ 0xbf4d, 0x8e53, 0xbf4e, 0x0000, 0xea4f, 0xbf50, 0xea4b, 0x0000,
+ 0xea54, 0xbf53, 0xea57, 0xea58, 0xbf54, 0xfacf, 0x0000, 0xc0e7,
+ 0xc0ee, 0xed5c, 0xed62, 0x0000, 0xed60, 0xc0ea, 0xc0e9, 0xc0e6,
+ 0xed5e, 0x0000, 0x0000, 0x96f9, 0xc0ec, 0xc0eb, 0xc0e8, 0x0000,
+ 0xed61, 0xed5d, 0xed5f, 0x0000, 0xc0ed, 0x98bf, 0x9e49, 0x0000,
+ 0xc277, 0xeffb, 0x0000, 0xc274, 0xc275, 0xeffd, 0xc276, 0xeffa
+};
+
+static const unsigned short big5hkscs_from_unicode_72[] = {
+ 0x8ca7, 0xeff9, 0xf26c, 0xeffc, 0x0000, 0xf26d, 0xc37a, 0xf26b,
+ 0x0000, 0x9bca, 0xf26a, 0x0000, 0xf269, 0xc37b, 0xfdfe, 0x92dc,
+ 0xc46c, 0x0000, 0x0000, 0xf46a, 0xf46b, 0xfe41, 0x91cc, 0x91e2,
+ 0x0000, 0xf5dc, 0xf5db, 0xc4ea, 0x0000, 0xf5da, 0xf6ec, 0xf6ed,
+ 0x0000, 0x0000, 0xf7e6, 0xf8b1, 0xfe44, 0x0000, 0xf8f6, 0xf9bc,
+ 0xc679, 0xf9c6, 0xa4f6, 0x8bd3, 0xaaa6, 0xaaa7, 0xfe47, 0x0000,
+ 0xacb8, 0x0000, 0x0000, 0x0000, 0x0000, 0xc0ef, 0xa4f7, 0x0000,
+ 0xaaa8, 0xaf52, 0xb7dd, 0xa4f8, 0x0000, 0xb26e, 0xbab8, 0xc962,
+ 0xfe48, 0xcfb7, 0xd27d, 0x0000, 0xe2c5, 0x0000, 0xc0f0, 0xa4f9,
+ 0xaaa9, 0xcfb8, 0xcfb9, 0xda66, 0xb550, 0x0000, 0x0000, 0xdea4,
+ 0xa0e4, 0x0000, 0xb7de, 0xe2c6, 0x0000, 0xfe4b, 0xbcf8, 0xfe4c,
+ 0xc37c, 0xa4fa, 0xda67, 0xa4fb, 0x8dbf, 0xa6c9, 0xca42, 0xa6c8,
+ 0xa865, 0xa864, 0xa863, 0xcb60, 0x0000, 0x0000, 0x9e78, 0xaaaa,
+ 0x0000, 0xaaab, 0xcd5b, 0x0000, 0xcfba, 0x0000, 0xcfbd, 0xacba,
+ 0xcfbb, 0x0000, 0xacb9, 0xcfbc, 0xacbb, 0x0000, 0xd2a2, 0xd2a1,
+ 0xd27e, 0xaf53, 0x0000, 0xd65d, 0xd65e, 0xb26f, 0xd65c, 0xd65f,
+ 0xb552, 0xb270, 0xfe51, 0x0000, 0xb551, 0xda6b, 0xda6a, 0x9456,
+ 0xda68, 0xda69, 0x0000, 0xda6c, 0xdea6, 0xdea5, 0xdea9, 0x9d61,
+ 0xdea8, 0xdea7, 0xbab9, 0xe2c9, 0x9457, 0xe2c8, 0xbaba, 0xe2c7,
+ 0xe673, 0x0000, 0xe674, 0xbcf9, 0x0000, 0xea59, 0xea5a, 0x9966,
+ 0x0000, 0xf272, 0xc37d, 0xf271, 0xf270, 0xf26e, 0xf26f, 0xc4eb,
+ 0xf46c, 0xf6ee, 0xf8f7, 0x0000, 0xa4fc, 0x8bd5, 0xc9a5, 0xa5c7,
+ 0xc9a6, 0x0000, 0xa069, 0x0000, 0xca43, 0xca44, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xcb66, 0x0000, 0x0000, 0xcb62, 0x0000, 0xcb61,
+ 0xaaac, 0xcb65, 0xa867, 0xcb63, 0xa866, 0xcb67, 0xcb64, 0x0000,
+ 0x0000, 0xcd5f, 0xcfbe, 0xcd5d, 0xcd64, 0x98b4, 0xaaad, 0x0000,
+ 0xaab0, 0xcd65, 0xcd61, 0x0000, 0xcd62, 0x0000, 0xcd5c, 0xaaaf,
+ 0xcd5e, 0xaaae, 0xcd63, 0x0000, 0xcd60, 0x0000, 0x0000, 0xcfc2,
+ 0xacbd, 0xacbe, 0xa049, 0xcfc5, 0xcfbf, 0x0000, 0xcfc4, 0x0000,
+ 0xcfc0, 0xacbc, 0xcfc3, 0xcfc1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xd2a8, 0xd2a5, 0x0000, 0xd2a7, 0xaf58,
+ 0xaf57, 0xaf55, 0xd2a4, 0xd2a9, 0xaf54, 0xaf56, 0xd2a6, 0xd667
+};
+
+static const unsigned short big5hkscs_from_unicode_73[] = {
+ 0xd2a3, 0xd2aa, 0xa04c, 0x0000, 0x9e65, 0x0000, 0x0000, 0xd662,
+ 0xd666, 0x0000, 0xd665, 0xda6e, 0xda79, 0x0000, 0x0000, 0xd668,
+ 0x98b5, 0xd663, 0xda6d, 0xb274, 0x0000, 0x0000, 0xb273, 0xd661,
+ 0xd664, 0xb275, 0x0000, 0xb272, 0xb271, 0xd660, 0xd669, 0x0000,
+ 0x0000, 0x0000, 0xda70, 0xda77, 0x0000, 0xb554, 0xda76, 0xda73,
+ 0xfe58, 0xb556, 0xfe52, 0xfe53, 0xa065, 0xda75, 0xfe59, 0x0000,
+ 0xda6f, 0xda71, 0xda74, 0xda72, 0xb555, 0xda78, 0xb553, 0xb7df,
+ 0x98b7, 0x98b8, 0xdead, 0xdeac, 0xdeaa, 0x0000, 0xb7e2, 0xb7e1,
+ 0xdeae, 0x98ba, 0xdeab, 0xe2ca, 0xbabb, 0xb7e0, 0x0000, 0x0000,
+ 0x98bb, 0xdeb0, 0xdeaf, 0x0000, 0xe2cd, 0xe2cb, 0xbcfa, 0x9fbc,
+ 0xbabc, 0xe2cc, 0xe676, 0x0000, 0x0000, 0x0000, 0x0000, 0xbcfb,
+ 0xe675, 0xe67e, 0xe67d, 0xe67b, 0x0000, 0xe67a, 0xe677, 0xe678,
+ 0xe679, 0xe67c, 0xe6a1, 0x0000, 0x0000, 0xea5f, 0xea5c, 0xea5d,
+ 0xbf57, 0xea5b, 0xea61, 0xea60, 0xea5e, 0x0000, 0xed64, 0xed65,
+ 0xc0f1, 0xa04a, 0xc0f2, 0xed63, 0x9ec7, 0xc279, 0xeffe, 0xc278,
+ 0xc37e, 0x0000, 0xc3a1, 0xc46d, 0xf46e, 0xf46d, 0xf5dd, 0xf6ef,
+ 0xc57a, 0xf7e8, 0xf7e7, 0xf7e9, 0xa5c8, 0xcfc6, 0xaf59, 0xb276,
+ 0xd66a, 0xa5c9, 0xc9a7, 0xa4fd, 0x8ca9, 0x0000, 0xca45, 0x98ae,
+ 0x0000, 0x0000, 0xcb6c, 0xcb6a, 0xcb6b, 0xcb68, 0xa868, 0xcb69,
+ 0x92d6, 0x0000, 0x0000, 0x0000, 0xfae1, 0xcd6d, 0x91d4, 0xaab3,
+ 0xcd6b, 0xcd67, 0xcd6a, 0x0000, 0xcd66, 0xaab5, 0xcd69, 0xfade,
+ 0xaab2, 0xaab1, 0xfe5b, 0xaab4, 0xcd6c, 0xcd68, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xacc2, 0xacc5, 0xcfce, 0xcfcd, 0xcfcc, 0xacbf,
+ 0xcfd5, 0xcfcb, 0x8c53, 0xacc1, 0xd2af, 0x0000, 0xcfd2, 0xcfd0,
+ 0xacc4, 0x0000, 0xcfc8, 0xcfd3, 0x0000, 0xcfca, 0xcfd4, 0xcfd1,
+ 0xcfc9, 0xfe5e, 0xacc0, 0xcfd6, 0xcfc7, 0xacc3, 0xfbd7, 0xfe5a,
+ 0x94c5, 0x0000, 0xd2b4, 0xd2ab, 0xd2b6, 0xfaca, 0xd2ae, 0xd2b9,
+ 0xd2ba, 0xd2ac, 0xd2b8, 0xd2b5, 0xd2b3, 0xd2b7, 0xaf5f, 0x0000,
+ 0xaf5d, 0x98c1, 0x975c, 0xd2b1, 0xfe74, 0xd2ad, 0x9773, 0xd2b0,
+ 0xd2bb, 0xd2b2, 0xaf5e, 0xcfcf, 0x0000, 0xaf5a, 0xaf5c, 0xfa46,
+ 0x0000, 0x0000, 0x0000, 0x9764, 0xd678, 0xd66d, 0xd66b, 0xfe68,
+ 0xd66c, 0x964e, 0xd673, 0x9765, 0xd674, 0xd670, 0xb27b, 0xd675
+};
+
+static const unsigned short big5hkscs_from_unicode_74[] = {
+ 0xd672, 0xd66f, 0x8c5a, 0xb279, 0xd66e, 0xb277, 0xb27a, 0xd671,
+ 0xd679, 0xaf5b, 0xb278, 0xd677, 0xd676, 0xb27c, 0x0000, 0x0000,
+ 0x0000, 0x89a1, 0x95fa, 0x0000, 0x92d4, 0xfe69, 0xda7e, 0xfb45,
+ 0x0000, 0x98c8, 0xdaa1, 0xb560, 0x90ef, 0xdaa7, 0x98c9, 0x98ca,
+ 0xdaa9, 0xdaa2, 0xb55a, 0xdaa6, 0xdaa5, 0xb55b, 0xb561, 0x0000,
+ 0xb562, 0xdaa8, 0xb558, 0xda7d, 0xda7b, 0xdaa3, 0xda7a, 0xb55f,
+ 0xda7c, 0xdaa4, 0xdaaa, 0xb559, 0xb55e, 0xb55c, 0xb55d, 0x946d,
+ 0x94b7, 0xfe6c, 0xb557, 0x0000, 0x946b, 0x0000, 0x0000, 0xb7e9,
+ 0xdeb7, 0xb7e8, 0xdebb, 0x92fc, 0xdeb1, 0x95eb, 0xdebc, 0xfe73,
+ 0x976e, 0xfe5f, 0xdeb2, 0xdeb3, 0x0000, 0xdebd, 0xdeba, 0xdeb8,
+ 0xdeb9, 0xdeb5, 0xdeb4, 0xfdbd, 0xdebe, 0xb7e5, 0x92d5, 0xdeb6,
+ 0x0000, 0xb7ea, 0xb7e4, 0xb7eb, 0xfe6f, 0xfeb9, 0xb7e7, 0xb7e6,
+ 0xfe71, 0x0000, 0xe2ce, 0xbabe, 0xbabd, 0xfbbb, 0x0000, 0xe2d3,
+ 0xa0d5, 0xbcfc, 0xbabf, 0x95fb, 0xfe77, 0xbac1, 0xe2d4, 0xb7e3,
+ 0xbac0, 0xe2d0, 0xe2d2, 0xe2cf, 0xfe79, 0xe2d1, 0xfe75, 0x0000,
+ 0x0000, 0xe6ab, 0x945d, 0x0000, 0xe6aa, 0xe6a7, 0xbd40, 0xea62,
+ 0xbd41, 0xe6a6, 0xfe7c, 0xbcfe, 0x0000, 0xe6a8, 0xe6a5, 0xe6a2,
+ 0xe6a9, 0xe6a3, 0xe6a4, 0xbcfd, 0x9344, 0x8ea6, 0x0000, 0x0000,
+ 0xed69, 0x0000, 0xea66, 0x0000, 0xea65, 0xea67, 0x0000, 0xed66,
+ 0xbf5a, 0x92d3, 0xea63, 0x94b8, 0xbf58, 0x0000, 0xbf5c, 0xbf5b,
+ 0xea64, 0xea68, 0x0000, 0xbf59, 0xfc71, 0xed6d, 0xc0f5, 0xc27a,
+ 0xc0f6, 0xc0f3, 0xed6a, 0xed68, 0x0000, 0xed6b, 0x0000, 0xed6e,
+ 0xc0f4, 0xed6c, 0xed67, 0x0000, 0x975e, 0xf042, 0xf045, 0xf275,
+ 0xf040, 0x8cad, 0xf46f, 0xf046, 0x0000, 0xc3a2, 0xf044, 0xc27b,
+ 0xf041, 0xf043, 0xf047, 0xf276, 0x0000, 0xf274, 0x0000, 0x0000,
+ 0xfea7, 0x0000, 0xc3a3, 0xf273, 0x946a, 0x0000, 0x0000, 0xc46e,
+ 0x93e3, 0x0000, 0x0000, 0x98cf, 0xc4ed, 0xf6f1, 0xc4ec, 0xf6f3,
+ 0xf6f0, 0xf6f2, 0xc5d0, 0xf8b2, 0xa5ca, 0xcd6e, 0xd2bc, 0xd2bd,
+ 0xb27d, 0xdebf, 0xbf5d, 0xc3a4, 0xc57b, 0xf8b3, 0xa5cb, 0xa0d9,
+ 0xcd6f, 0xfeaa, 0x0000, 0x0000, 0xcfd7, 0x0000, 0xcfd8, 0x0000,
+ 0xa0bf, 0xa04d, 0xa0b8, 0x0000, 0xd2be, 0xd2bf, 0xb27e, 0xb2a1,
+ 0xa0ce, 0x0000, 0x0000, 0xdaab, 0x0000, 0xdec2, 0xdec1, 0xdec0
+};
+
+static const unsigned short big5hkscs_from_unicode_75[] = {
+ 0xe2d5, 0x0000, 0xe2d6, 0xe2d7, 0xbac2, 0xa0b7, 0x0000, 0xe6ad,
+ 0xe6ac, 0x0000, 0x0000, 0xea69, 0xbf5e, 0xbf5f, 0xfea9, 0xed72,
+ 0xed6f, 0xed70, 0xed71, 0xf049, 0xf048, 0xc27c, 0xf277, 0xf5de,
+ 0xa5cc, 0x89c3, 0xacc6, 0x0000, 0xb2a2, 0xdec3, 0xfeab, 0xa5cd,
+ 0x0000, 0xd2c0, 0xb2a3, 0x0000, 0x0000, 0xb563, 0xb564, 0x0000,
+ 0xa5ce, 0xa5cf, 0xca46, 0xa86a, 0xa869, 0xacc7, 0xcfd9, 0xdaac,
+ 0xa5d0, 0xa5d1, 0xa5d2, 0xa5d3, 0x9df4, 0x896d, 0x0000, 0xa86b,
+ 0xa86c, 0xcb6e, 0xcb6d, 0x9c7b, 0x0000, 0xaab6, 0xcd72, 0xcd70,
+ 0xcd71, 0x0000, 0x98d2, 0x0000, 0x0000, 0x0000, 0x9fa9, 0xcfda,
+ 0xcfdb, 0x0000, 0xfeb2, 0xaccb, 0xacc9, 0xfeb1, 0xacca, 0xacc8,
+ 0x0000, 0x97d9, 0x0000, 0xa0c4, 0xaf60, 0x9476, 0x0000, 0x0000,
+ 0x0000, 0xaf64, 0xaf63, 0xd2c1, 0xaf62, 0xaf61, 0x0000, 0xd2c2,
+ 0x9978, 0x0000, 0xb2a6, 0xd67b, 0xd67a, 0xb2a4, 0xb2a5, 0xfeb3,
+ 0x0000, 0x0000, 0xb566, 0xb565, 0xdaae, 0x98d3, 0xfeb4, 0xdaad,
+ 0xb2a7, 0x0000, 0x98d4, 0x0000, 0x0000, 0x0000, 0xb7ed, 0xdec5,
+ 0xb7ee, 0xdec4, 0x9fb9, 0x0000, 0x0000, 0xe2d8, 0xe6ae, 0xbd42,
+ 0xea6a, 0x0000, 0x0000, 0x9471, 0xed73, 0x0000, 0xc3a6, 0xc3a5,
+ 0x0000, 0x0000, 0xc57c, 0xa5d4, 0xcd73, 0x98d5, 0xfeb8, 0xb2a8,
+ 0xe2d9, 0xbac3, 0xc6d4, 0x0000, 0xcb6f, 0xcb70, 0x0000, 0x0000,
+ 0xcd74, 0xaab8, 0xaab9, 0x0000, 0x0000, 0xaab7, 0xfeba, 0x0000,
+ 0x0000, 0x0000, 0xaccf, 0xacd0, 0xaccd, 0xacce, 0x0000, 0xcfdc,
+ 0x0000, 0x0000, 0xcfdd, 0xaccc, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd2c3, 0x9e5c, 0xaf68, 0xaf69, 0xfebb, 0xb2ab, 0xd2c9, 0x0000,
+ 0xaf6e, 0xaf6c, 0xd2ca, 0xd2c5, 0xaf6b, 0xaf6a, 0xaf65, 0xd2c8,
+ 0xd2c7, 0xd2c4, 0xaf6d, 0xa044, 0xd2c6, 0xaf66, 0x0000, 0xaf67,
+ 0x98d7, 0x0000, 0xb2ac, 0xd6a1, 0xd6a2, 0xb2ad, 0xd67c, 0xd67e,
+ 0xd6a4, 0xd6a3, 0xd67d, 0x0000, 0xb2a9, 0xb2aa, 0x0000, 0xdab6,
+ 0xb56b, 0xb56a, 0xdab0, 0xb568, 0x98d8, 0xdab3, 0xb56c, 0xdab4,
+ 0xb56d, 0xdab1, 0xb567, 0xb569, 0xdab5, 0x0000, 0xdab2, 0xdaaf,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xded2, 0x0000, 0xdec7,
+ 0xb7f0, 0xb7f3, 0xb7f2, 0xb7f7, 0xb7f6, 0xded3, 0xded1, 0xdeca,
+ 0xdece, 0xdecd, 0xb7f4, 0xded0, 0xdecc, 0xded4, 0xdecb, 0xb7f5
+};
+
+static const unsigned short big5hkscs_from_unicode_76[] = {
+ 0xb7ef, 0xb7f1, 0xfebc, 0xdec9, 0x0000, 0x0000, 0x0000, 0x9ffe,
+ 0xe2db, 0xbac7, 0xe2df, 0xbac6, 0xe2dc, 0xbac5, 0x0000, 0xdec8,
+ 0xdecf, 0xe2de, 0x0000, 0xbac8, 0xe2e0, 0xe2dd, 0xe2da, 0x0000,
+ 0x0000, 0xe6b1, 0xe6b5, 0xe6b7, 0xe6b3, 0xe6b2, 0xe6b0, 0xbd45,
+ 0xbd43, 0xbd48, 0xbd49, 0xe6b4, 0xbd46, 0xe6af, 0xbd47, 0xbac4,
+ 0xe6b6, 0xbd44, 0x0000, 0x0000, 0xfebd, 0xea6c, 0x0000, 0xea6b,
+ 0xea73, 0xea6d, 0xea72, 0xea6f, 0xbf60, 0xea71, 0x0000, 0x0000,
+ 0xbf61, 0x0000, 0xbf62, 0x9ddd, 0xea70, 0xea6e, 0x0000, 0x0000,
+ 0x9ee1, 0x0000, 0xc0f8, 0xed74, 0x0000, 0x0000, 0xc0f7, 0xed77,
+ 0xed75, 0xed76, 0x0000, 0x0000, 0xc0f9, 0x98da, 0x9ddf, 0xfebf,
+ 0xf04d, 0xfebe, 0xc2a1, 0xf04e, 0x9eeb, 0x0000, 0xc27d, 0xf04f,
+ 0xc27e, 0xf04c, 0xf050, 0x0000, 0xf04a, 0x0000, 0x0000, 0xc3a7,
+ 0xf278, 0xc3a8, 0xc46f, 0x0000, 0xf04b, 0xc470, 0x9e59, 0xa05c,
+ 0x0000, 0xc4ee, 0xf5df, 0x0000, 0xc57e, 0xf6f4, 0xc57d, 0xfec0,
+ 0xf7ea, 0xc5f5, 0xc5f6, 0x9477, 0x98dc, 0xf9cc, 0xfec1, 0x0000,
+ 0xacd1, 0xcfde, 0x98de, 0xb56e, 0xb56f, 0xa5d5, 0xa6ca, 0xca47,
+ 0x0000, 0xcb71, 0xa86d, 0x0000, 0xaaba, 0x0000, 0xacd2, 0xacd3,
+ 0xacd4, 0xd6a6, 0xd2cb, 0xaf6f, 0x0000, 0x0000, 0xb2ae, 0xd6a5,
+ 0xfec3, 0x0000, 0xdab8, 0xb571, 0x0000, 0xdab7, 0xb570, 0x0000,
+ 0x0000, 0xded5, 0xbd4a, 0xe6bb, 0xe6b8, 0xe6b9, 0xe6ba, 0x0000,
+ 0x0000, 0xfec8, 0x0000, 0x0000, 0xed78, 0xfec9, 0xf051, 0x0000,
+ 0x0000, 0x0000, 0xf471, 0xf470, 0x0000, 0xf6f5, 0xa5d6, 0xcd75,
+ 0xaf70, 0x0000, 0x0000, 0x0000, 0xb572, 0xded6, 0x0000, 0xfeca,
+ 0xe2e1, 0x0000, 0xbd4b, 0xea74, 0x0000, 0xf052, 0xf472, 0xa5d7,
+ 0x0000, 0x0000, 0xaabb, 0xacd7, 0xcfdf, 0xacd8, 0xacd6, 0x0000,
+ 0xacd5, 0xd2cc, 0xaf71, 0x0000, 0xfecb, 0xaf72, 0xaf73, 0x0000,
+ 0x0000, 0x0000, 0xb2b0, 0xd6a7, 0xb2af, 0x0000, 0x9fc2, 0x0000,
+ 0x0000, 0x8c6b, 0xdab9, 0xb2b1, 0xb573, 0xded7, 0xb7f8, 0xb7f9,
+ 0x0000, 0xbac9, 0x0000, 0xbaca, 0xbd4c, 0xbf64, 0xea75, 0xbf63,
+ 0x0000, 0xed79, 0xc0fa, 0x0000, 0xf053, 0xf473, 0xa5d8, 0xa86e,
+ 0xcd78, 0xcd77, 0xaabc, 0xcd76, 0xaabd, 0xcd79, 0x0000, 0xcfe5,
+ 0xacdb, 0xacda, 0xcfe7, 0xcfe6, 0xacdf, 0x0000, 0xacde, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_77[] = {
+ 0x0000, 0xacd9, 0x0000, 0xcfe1, 0xcfe2, 0xcfe3, 0x0000, 0xace0,
+ 0xcfe0, 0xacdc, 0xcfe4, 0xacdd, 0x98c4, 0x0000, 0x94b0, 0x94b1,
+ 0xd2cf, 0xd2d3, 0xd2d1, 0xd2d0, 0x0000, 0xd2d4, 0x0000, 0x0000,
+ 0x0000, 0xd2d5, 0xd2d6, 0xd2ce, 0x0000, 0xd2cd, 0xfed1, 0xaf75,
+ 0xaf76, 0x0000, 0xd2d7, 0xd2d2, 0xa0c1, 0xd6b0, 0xfed2, 0xd2d8,
+ 0xaf77, 0xaf74, 0x0000, 0xa0cd, 0x0000, 0xd6aa, 0x0000, 0xd6a9,
+ 0x0000, 0xd6ab, 0xd6ac, 0xd6ae, 0xd6ad, 0xd6b2, 0xb2b5, 0xb2b2,
+ 0xb2b6, 0xd6a8, 0xb2b7, 0xd6b1, 0xb2b4, 0xd6af, 0xb2b3, 0x0000,
+ 0xfed3, 0x0000, 0x0000, 0x98e5, 0xdabc, 0xdabe, 0xdaba, 0xdabb,
+ 0x0000, 0x0000, 0xdabf, 0xdac1, 0xdac2, 0xdabd, 0xdac0, 0xb574,
+ 0x0000, 0x0000, 0xdedb, 0x0000, 0xdee0, 0xded8, 0xdedc, 0x0000,
+ 0xfed6, 0xdee1, 0xdedd, 0xb7fa, 0xb843, 0x0000, 0xb7fd, 0xded9,
+ 0xdeda, 0xbace, 0xb846, 0xb7fe, 0x0000, 0xb844, 0xb7fc, 0xdedf,
+ 0xb845, 0xdede, 0xb841, 0xb7fb, 0xb842, 0xdee2, 0xe2e6, 0xe2e8,
+ 0x0000, 0x0000, 0x91e4, 0x0000, 0x0000, 0x0000, 0x0000, 0x8fc7,
+ 0x94ae, 0xb840, 0x8a4f, 0x94b2, 0xe2e3, 0xbacc, 0xe2e9, 0xbacd,
+ 0xe2e7, 0xe2e2, 0xe2e5, 0xe2ea, 0xbacb, 0xe2e4, 0x0000, 0xbd4e,
+ 0xe6bf, 0xe6be, 0x0000, 0xbd51, 0xbd4f, 0xe6bc, 0xbd4d, 0xe6bd,
+ 0x0000, 0xbd50, 0x0000, 0x8fd4, 0x0000, 0xea7d, 0x0000, 0xeaa1,
+ 0x98ea, 0xea7e, 0xea76, 0xea7a, 0xea79, 0xea77, 0xbf66, 0xbf67,
+ 0xbf65, 0xea78, 0xea7b, 0xea7c, 0x0000, 0xbf68, 0x0000, 0xc140,
+ 0xeda3, 0x0000, 0xc0fc, 0xed7b, 0xc0fe, 0xc141, 0x0000, 0xfed8,
+ 0xc0fd, 0xeda2, 0xed7c, 0xc0fb, 0xeda1, 0xed7a, 0xed7e, 0xed7d,
+ 0x0000, 0x9de0, 0xf055, 0xc2a4, 0xc2a5, 0xc2a2, 0x98ee, 0xc2a3,
+ 0x0000, 0x0000, 0xf054, 0x95c4, 0xf27b, 0xfce8, 0x0000, 0xc3a9,
+ 0x0000, 0xf279, 0xf27a, 0x98ef, 0xf474, 0xf477, 0xf475, 0xf476,
+ 0xf5e0, 0x0000, 0x0000, 0xc4ef, 0xf7eb, 0xf8b4, 0x0000, 0xc5f7,
+ 0xf8f8, 0xf8f9, 0xc666, 0xa5d9, 0xace1, 0x8c6e, 0xdac3, 0x0000,
+ 0xdee3, 0x0000, 0xa5da, 0xa86f, 0x0000, 0xaabe, 0xfad8, 0xcfe8,
+ 0xcfe9, 0xaf78, 0x0000, 0x0000, 0xdac4, 0xb575, 0xb847, 0xc142,
+ 0xeda4, 0xf27c, 0xf478, 0xa5db, 0xfedc, 0x0000, 0x0000, 0xcda1,
+ 0xcd7a, 0xcd7c, 0xcd7e, 0xcd7d, 0xcd7b, 0xaabf, 0xa0ae, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_78[] = {
+ 0x0000, 0x0000, 0xace2, 0xcff2, 0x0000, 0xcfed, 0xcfea, 0x0000,
+ 0x9d4c, 0xfedd, 0x0000, 0x0000, 0xace4, 0xace5, 0xcff0, 0xcfef,
+ 0xcfee, 0xcfeb, 0xcfec, 0xcff3, 0xace3, 0x0000, 0x0000, 0x0000,
+ 0x98f1, 0x0000, 0x0000, 0x0000, 0x98f3, 0xaf7c, 0x94c1, 0xafa4,
+ 0xafa3, 0xd2e1, 0xd2db, 0xd2d9, 0x0000, 0xafa1, 0xd6b9, 0xaf7a,
+ 0xd2de, 0xd2e2, 0xd2e4, 0xd2e0, 0xd2da, 0xafa2, 0xd2df, 0xd2dd,
+ 0xaf79, 0xd2e5, 0xafa5, 0xd2e3, 0xaf7d, 0xd2dc, 0x0000, 0xaf7e,
+ 0xaf7b, 0x98f5, 0x0000, 0x0000, 0xfa4f, 0x96e2, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9450, 0xb2b9, 0x96a2, 0xd6ba, 0x0000, 0x98f6,
+ 0xd6b3, 0xd6b5, 0xd6b7, 0x96e5, 0xd6b8, 0xd6b6, 0xb2ba, 0x0000,
+ 0xd6bb, 0x98f7, 0xd6b4, 0xa046, 0x96e3, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xdac8, 0xb576, 0xdad0, 0x0000,
+ 0xdac5, 0x0000, 0xdad1, 0x0000, 0xdac6, 0xdac7, 0x98f8, 0x0000,
+ 0xdacf, 0xdace, 0xdacb, 0xb2b8, 0xb577, 0xdac9, 0xdacc, 0xb578,
+ 0xdacd, 0xdaca, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xdeee, 0x9ee4, 0xdef2, 0xb84e, 0x0000, 0xe2f0, 0xb851,
+ 0xdef0, 0xf9d6, 0x0000, 0xdeed, 0xdee8, 0xdeea, 0xdeeb, 0xdee4,
+ 0x94c3, 0xb84d, 0x0000, 0x0000, 0xb84c, 0x94c2, 0xb848, 0xdee7,
+ 0x0000, 0xb84f, 0x0000, 0xb850, 0xdee6, 0xdee9, 0xdef1, 0xb84a,
+ 0xb84b, 0xdeef, 0xdee5, 0x0000, 0x0000, 0x0000, 0xe2f2, 0xbad0,
+ 0xe2f4, 0xdeec, 0xe2f6, 0xbad4, 0xe2f7, 0xe2f3, 0x0000, 0xbad1,
+ 0xe2ef, 0xbad3, 0xe2ec, 0xe2f1, 0xe2f5, 0xe2ee, 0x0000, 0xfee1,
+ 0xb849, 0xfee9, 0xe2eb, 0xbad2, 0xe2ed, 0x0000, 0x96e4, 0x0000,
+ 0x89ac, 0x96db, 0xbd54, 0xe6c1, 0xbd58, 0x0000, 0xbd56, 0x0000,
+ 0x0000, 0xbacf, 0x0000, 0xe6c8, 0xe6c9, 0xbd53, 0x0000, 0xfee2,
+ 0xe6c7, 0xe6ca, 0xbd55, 0xbd52, 0xe6c3, 0xe6c0, 0xe6c5, 0xe6c2,
+ 0xbd59, 0xe6c4, 0x94c4, 0xfee3, 0xe6c6, 0xbd57, 0x0000, 0xfee7,
+ 0x9ffb, 0x0000, 0xbf6a, 0xeaa8, 0x0000, 0xeaa2, 0xeaa6, 0xeaac,
+ 0xeaad, 0xeaa9, 0xeaaa, 0xeaa7, 0x8c59, 0xeaa4, 0x0000, 0xbf6c,
+ 0xbf69, 0xeaa3, 0xeaa5, 0x0000, 0xbf6b, 0xeaab, 0x93c9, 0xc146,
+ 0x94e8, 0xfb56, 0xedaa, 0xeda5, 0xc145, 0x90c5, 0x0000, 0xc143,
+ 0x0000, 0xedac, 0xc144, 0xeda8, 0xeda9, 0xeda6, 0xedad, 0xf056
+};
+
+static const unsigned short big5hkscs_from_unicode_79[] = {
+ 0x0000, 0xc147, 0xeda7, 0x0000, 0xedae, 0xedab, 0xa0a8, 0x0000,
+ 0x0000, 0xf05a, 0x0000, 0x0000, 0xf057, 0x0000, 0xc2a6, 0x0000,
+ 0xf05b, 0xf05d, 0xf05c, 0xf058, 0xf059, 0x0000, 0x0000, 0xf2a3,
+ 0x0000, 0xc3aa, 0x0000, 0xf27e, 0xf2a2, 0xf27d, 0xf2a4, 0x0000,
+ 0x0000, 0xf2a1, 0x0000, 0xf47a, 0xf47d, 0xf479, 0xc471, 0xf47b,
+ 0xf47c, 0xf47e, 0xc472, 0xc474, 0xc473, 0xf5e1, 0xfee5, 0xf5e3,
+ 0x0000, 0xf5e2, 0x98fd, 0x98fb, 0xfee8, 0xf6f6, 0x8ebf, 0x0000,
+ 0xf8b5, 0xf8fa, 0xa5dc, 0x8bd8, 0xfef7, 0xcb72, 0xaac0, 0xcda3,
+ 0xaac1, 0xaac2, 0xcda2, 0x0000, 0xcff8, 0xcff7, 0xace6, 0xace9,
+ 0xace8, 0xace7, 0xcff4, 0xcff6, 0xcff5, 0x0000, 0x0000, 0xd2e8,
+ 0xafa7, 0xd2ec, 0xd2eb, 0xd2ea, 0xd2e6, 0xafa6, 0xafaa, 0xafad,
+ 0x8f68, 0x94c6, 0xafae, 0xd2e7, 0xd2e9, 0xafac, 0xafab, 0xafa9,
+ 0xafa8, 0xd6c2, 0x9dea, 0xd6c0, 0xd6bc, 0xb2bb, 0x0000, 0xd6bd,
+ 0xb2bc, 0xd6be, 0xd6bf, 0xd6c1, 0x0000, 0xb2bd, 0x0000, 0x0000,
+ 0xdad5, 0xfc69, 0xdad4, 0xdad3, 0xdad2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xdef6, 0xb852, 0x0000, 0xdef3, 0xdef5, 0x9cda, 0xb853,
+ 0xfef3, 0xb854, 0xdef4, 0x9c72, 0x0000, 0x0000, 0xfef0, 0x89c9,
+ 0xe341, 0x0000, 0xe2f9, 0xe2fa, 0x0000, 0xbad7, 0xbad5, 0xbad6,
+ 0xe343, 0x9941, 0xe342, 0xe2fe, 0xe2fd, 0xe2fc, 0xe2fb, 0xe340,
+ 0xe2f8, 0x9942, 0xe6cb, 0xe6d0, 0xe6ce, 0xfef5, 0x0000, 0x91d7,
+ 0xe6cd, 0xe6cc, 0xe6cf, 0x0000, 0xeaae, 0x94cc, 0xbf6d, 0xc148,
+ 0xedb0, 0xfef8, 0xc149, 0xedaf, 0xf05f, 0xf05e, 0xc2a7, 0x0000,
+ 0xf2a5, 0xc3ab, 0xf4a1, 0xc5a1, 0xf6f7, 0x0000, 0xf8b7, 0xf8b6,
+ 0xc9a8, 0xacea, 0xaceb, 0xd6c3, 0x0000, 0xb856, 0xa5dd, 0xa872,
+ 0xa871, 0xa870, 0x0000, 0x0000, 0x97a8, 0xcda4, 0xfefc, 0x0000,
+ 0xaac4, 0xaac3, 0x0000, 0xacee, 0xfdbf, 0xcffa, 0xcffd, 0xcffb,
+ 0x0000, 0xacec, 0xaced, 0x0000, 0xfefe, 0xcff9, 0xcffc, 0x0000,
+ 0xafb5, 0x0000, 0x0000, 0x0000, 0xd2f3, 0xd2f5, 0xd2f4, 0xafb2,
+ 0xd2ef, 0x0000, 0x96d1, 0xafb0, 0xafaf, 0x0000, 0xafb3, 0xafb1,
+ 0x0000, 0xafb4, 0xd2f2, 0xd2ed, 0xd2ee, 0xd2f1, 0xd2f0, 0x0000,
+ 0x0000, 0x94d5, 0x0000, 0x0000, 0x94d0, 0x0000, 0xd6c6, 0xd6c7,
+ 0xd6c5, 0x0000, 0xd6c4, 0xb2be, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_7a[] = {
+ 0xb57d, 0x0000, 0xdad6, 0xdad8, 0xdada, 0xb57c, 0x9944, 0x0000,
+ 0xb57a, 0x0000, 0xdad7, 0xb57b, 0xdad9, 0xb579, 0x0000, 0x0000,
+ 0xdf41, 0xdef7, 0xdefa, 0xdefe, 0xb85a, 0xdefc, 0x0000, 0xdefb,
+ 0xdef8, 0xdef9, 0xb858, 0xdf40, 0xb857, 0x0000, 0xb85c, 0xb85b,
+ 0xb859, 0x0000, 0xdefd, 0x0000, 0x0000, 0x0000, 0xe349, 0x0000,
+ 0xe348, 0x0000, 0x8c63, 0xe344, 0x0000, 0xa0b3, 0xbad8, 0xe347,
+ 0xe346, 0xbad9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbd5e,
+ 0x0000, 0xe6d2, 0x94cf, 0xbd5f, 0xbd5b, 0xbd5d, 0x9ffa, 0xbd5a,
+ 0xbd5c, 0x0000, 0x0000, 0x91e5, 0xeaaf, 0x9c6a, 0xbf70, 0xeab1,
+ 0xeab0, 0x8e49, 0xe345, 0xbf72, 0xbf71, 0xbf6e, 0xbf6f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xedb5, 0x0000, 0xedb3, 0xc14a,
+ 0xedb4, 0x0000, 0xedb6, 0xedb2, 0xedb1, 0x0000, 0x0000, 0xf060,
+ 0xc2aa, 0xc2a8, 0xc2a9, 0x0000, 0x0000, 0x8e4c, 0x0000, 0xf2a6,
+ 0xf2a7, 0xc3ad, 0x0000, 0xc3ac, 0xf4a3, 0xf4a4, 0xf4a2, 0x0000,
+ 0xf6f8, 0xf6f9, 0x0000, 0x0000, 0xa5de, 0xca48, 0xa873, 0x0000,
+ 0xcda5, 0xaac6, 0xaac5, 0xcda6, 0x0000, 0x8e4d, 0xd040, 0xacef,
+ 0xcffe, 0xacf0, 0x0000, 0x9a73, 0xafb6, 0xd2f8, 0xd2f6, 0xd2fc,
+ 0xafb7, 0xd2f7, 0xd2fb, 0xd2f9, 0xd2fa, 0x0000, 0x0000, 0xd6c8,
+ 0xd6ca, 0x9947, 0xb2bf, 0x8cb1, 0xd6c9, 0xb2c0, 0xb5a2, 0xb5a1,
+ 0xb57e, 0xdadb, 0x0000, 0x0000, 0x0000, 0x0000, 0xdf44, 0xb85d,
+ 0xb85e, 0x0000, 0xdf43, 0xdf42, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe34a, 0xbadb, 0xbada, 0xe34b, 0xe34c, 0x0000, 0xbd61, 0xbd60,
+ 0x8e50, 0xeab5, 0xe6d3, 0xe6d5, 0xe6d4, 0xeab4, 0xeab2, 0xeab6,
+ 0xeab3, 0x0000, 0xbf73, 0x8e4f, 0x9949, 0x0000, 0xedb7, 0xc14b,
+ 0xedb8, 0xedb9, 0x8e51, 0x8e52, 0xc2ab, 0xc2ac, 0x0000, 0xc475,
+ 0x9ab2, 0x89a5, 0xc5d1, 0xa5df, 0x0000, 0x0000, 0x0000, 0x994c,
+ 0x0000, 0xd041, 0x0000, 0x9ff8, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd2fd, 0xafb8, 0x8e56, 0x994d, 0x91ca, 0x8e57, 0x0000, 0xb3ba,
+ 0xb3b9, 0x0000, 0x94e1, 0xb5a4, 0xdadd, 0xb5a3, 0xdadc, 0x9047,
+ 0x0000, 0x8fd8, 0x8e58, 0xdf45, 0x0000, 0xbadc, 0xe34d, 0xbadd,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc476, 0xf4a5,
+ 0x0000, 0xa6cb, 0xaac7, 0xcda7, 0x0000, 0xacf2, 0x94eb, 0xacf1
+};
+
+static const unsigned short big5hkscs_from_unicode_7b[] = {
+ 0xd042, 0xd043, 0x0000, 0x0000, 0xd340, 0xd342, 0xafb9, 0x0000,
+ 0xd344, 0xd347, 0xd345, 0x8e5c, 0x9553, 0x0000, 0xd346, 0xd343,
+ 0xd2fe, 0xafba, 0xd348, 0xd341, 0x9fe5, 0x0000, 0x0000, 0x0000,
+ 0xd6d3, 0xb2c6, 0xd6dc, 0xb2c3, 0x0000, 0xd6d5, 0xb2c7, 0x9f56,
+ 0xb2c1, 0x0000, 0xd6d0, 0xd6dd, 0xd6d1, 0xd6ce, 0xb2c5, 0x954f,
+ 0xb2c2, 0x8e5e, 0xd6d4, 0xd6d7, 0xb2c4, 0xd6d8, 0xb2c8, 0xd6d9,
+ 0xd6cf, 0xd6d6, 0xd6da, 0xd6d2, 0xd6cd, 0xd6cb, 0x0000, 0x0000,
+ 0xd6db, 0x996a, 0x0000, 0xdadf, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xdae4, 0x0000, 0x9c64, 0x9cd9, 0xdae0, 0xdae6, 0xb5a7, 0xd6cc,
+ 0xdae1, 0xb5a5, 0xdade, 0xb5ac, 0xdae2, 0xb5ab, 0xdae3, 0xb5ad,
+ 0xb5a8, 0xb5ae, 0xb5a9, 0x0000, 0xb5aa, 0x8e5d, 0xb5a6, 0x0000,
+ 0xdae5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xb861, 0xdf50, 0x9950, 0xdf53, 0xdf47, 0xdf4c, 0xdf46, 0xb863,
+ 0x0000, 0xdf4a, 0x0000, 0x0000, 0x9951, 0xdf48, 0xb862, 0x8e62,
+ 0xdf4f, 0xdf4e, 0xdf4b, 0xdf4d, 0xdf49, 0xbae1, 0xdf52, 0xb85f,
+ 0xdf51, 0x0000, 0x0000, 0x9952, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe35d, 0x0000, 0xbae8, 0xe358, 0x0000, 0xbae7,
+ 0xe34e, 0x0000, 0xe350, 0xbae0, 0xe355, 0xe354, 0xe357, 0xbae5,
+ 0xe352, 0xe351, 0x8e68, 0x0000, 0xbae4, 0xbadf, 0xe353, 0xbae2,
+ 0xe359, 0xe35b, 0x0000, 0xe356, 0xe34f, 0xbae3, 0x0000, 0x0000,
+ 0xbd69, 0xbade, 0x8e61, 0x9f59, 0xe35c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe6d9, 0xbd62, 0x0000, 0xe6db,
+ 0x0000, 0xbd63, 0x8bb3, 0x0000, 0xbd65, 0xe6de, 0x0000, 0xe6d6,
+ 0xbae6, 0xe6dc, 0x0000, 0x0000, 0x0000, 0x0000, 0xe6d8, 0x0000,
+ 0xb860, 0xbd68, 0x0000, 0x0000, 0xbd64, 0x0000, 0xbd66, 0xbd67,
+ 0x0000, 0xbf76, 0xe6dd, 0xe6d7, 0xbd6a, 0x0000, 0xe6da, 0x9f5d,
+ 0x8e66, 0x0000, 0x0000, 0x0000, 0xeac0, 0xeabb, 0x0000, 0x0000,
+ 0xeac5, 0xbf74, 0xeabd, 0xbf78, 0xeac3, 0xeaba, 0xeab7, 0xeac6,
+ 0xc151, 0xbf79, 0xeac2, 0xeab8, 0xbf77, 0xeabc, 0xbf7b, 0xeab9,
+ 0xeabe, 0xbf7a, 0xeac1, 0xeac4, 0x8cb2, 0x0000, 0x0000, 0x0000,
+ 0xedcb, 0xedcc, 0xedbc, 0xedc3, 0xedc1, 0x0000, 0x0000, 0xc14f,
+ 0xedc8, 0xeabf, 0x8e6e, 0xedbf, 0x9f64, 0xedc9, 0xc14e, 0xedbe
+};
+
+static const unsigned short big5hkscs_from_unicode_7c[] = {
+ 0xedbd, 0xedc7, 0xedc4, 0xedc6, 0x0000, 0xedba, 0xedca, 0xc14c,
+ 0x0000, 0xedc5, 0xedce, 0xedc2, 0xc150, 0xc14d, 0xedc0, 0xedbb,
+ 0xedcd, 0xbf75, 0x9953, 0x0000, 0x0000, 0xfab8, 0x0000, 0x0000,
+ 0x0000, 0xf063, 0x0000, 0x9954, 0xf061, 0xf067, 0xc2b0, 0xf065,
+ 0xf064, 0xc2b2, 0xf06a, 0xc2b1, 0x0000, 0xf06b, 0xf068, 0xc2ae,
+ 0xf069, 0xf062, 0xc2af, 0xc2ad, 0xf2ab, 0xf066, 0x0000, 0x0000,
+ 0xf06c, 0x0000, 0x0000, 0xf2a8, 0x0000, 0x8e70, 0x0000, 0xc3b2,
+ 0xc3b0, 0xf2aa, 0x0000, 0xf2ac, 0xf2a9, 0xc3b1, 0xc3ae, 0xc3af,
+ 0xc3b3, 0x0000, 0x9f61, 0xc478, 0x8e72, 0xf4aa, 0x0000, 0xf4a9,
+ 0xf4a7, 0xf4a6, 0xf4a8, 0x0000, 0xc477, 0xc479, 0x0000, 0x0000,
+ 0xc4f0, 0xa06b, 0x0000, 0xf5e5, 0xf5e4, 0x0000, 0x9f40, 0xf6fa,
+ 0x0000, 0xf6fc, 0xf6fe, 0xf6fd, 0xf6fb, 0x94ed, 0x0000, 0xc5a3,
+ 0xc5a2, 0x0000, 0x0000, 0xc5d3, 0xc5d2, 0xc5d4, 0xf7ed, 0xf7ec,
+ 0x0000, 0xf8fb, 0xf8b8, 0xf8fc, 0xc658, 0x94ee, 0xc659, 0xf96d,
+ 0x9fbd, 0x0000, 0xc67e, 0xa6cc, 0x8e7b, 0xcda8, 0x0000, 0x0000,
+ 0xd045, 0xd046, 0xd044, 0x9957, 0x94f7, 0xacf3, 0x9f5f, 0xd047,
+ 0xd048, 0xd049, 0x0000, 0x8e73, 0xd349, 0xd34f, 0x9f62, 0x0000,
+ 0xd34d, 0xafbb, 0xd34b, 0x0000, 0xd34c, 0xd34e, 0x94f6, 0x0000,
+ 0x0000, 0xd34a, 0xb2c9, 0x0000, 0xd6de, 0xb2cb, 0xd6e0, 0xb2ca,
+ 0xd6df, 0x0000, 0x0000, 0x0000, 0x9958, 0x0000, 0xdae8, 0xb5af,
+ 0x0000, 0xdaea, 0xdae7, 0xd6e1, 0x0000, 0xb5b0, 0x8e75, 0xf9db,
+ 0xdae9, 0x0000, 0x0000, 0x0000, 0x9072, 0x0000, 0x94f8, 0xdf56,
+ 0x0000, 0xb864, 0xdf54, 0xb865, 0xdf55, 0xb866, 0x0000, 0x0000,
+ 0x995a, 0xbae9, 0xe361, 0xe35e, 0xe360, 0xbaea, 0xbaeb, 0xe35f,
+ 0x0000, 0x0000, 0xa0b0, 0x8cb3, 0x0000, 0xe6df, 0x0000, 0x8e79,
+ 0xe6e0, 0x8e78, 0xbd6b, 0xe6e2, 0xe6e1, 0x94f3, 0xa261, 0x0000,
+ 0xeaca, 0xeacb, 0xeac7, 0x98af, 0xeac8, 0xbf7c, 0xbf7d, 0xeac9,
+ 0x0000, 0xc157, 0xa0b2, 0x0000, 0xc153, 0xc158, 0xc154, 0xc156,
+ 0xc152, 0x0000, 0xc155, 0x0000, 0x0000, 0x0000, 0x8e7a, 0xc2b3,
+ 0xedcf, 0x0000, 0xf2ae, 0x0000, 0xf2ad, 0x995c, 0xf4ab, 0xc47a,
+ 0xc47b, 0xf741, 0xf5e6, 0x8e7c, 0xf740, 0x8e7d, 0xf8fd, 0xf9a4,
+ 0xa6cd, 0x8bd9, 0x0000, 0xa874, 0x89a2, 0xcda9, 0xaac8, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_7d[] = {
+ 0xacf6, 0xd04c, 0xacf4, 0xd04a, 0xacf9, 0xacf5, 0xacfa, 0xacf8,
+ 0xd04b, 0xacf7, 0xafbf, 0xafbe, 0xd35a, 0xafc7, 0xd353, 0xd359,
+ 0xafc3, 0xd352, 0xd358, 0xd356, 0xafc2, 0xafc4, 0xd355, 0xafbd,
+ 0xd354, 0xafc8, 0xafc5, 0xafc9, 0xafc6, 0xd351, 0xd350, 0xd357,
+ 0xafc0, 0xafbc, 0xafc1, 0x0000, 0x0000, 0x9ed7, 0x0000, 0x0000,
+ 0xd6f0, 0xd6e9, 0x0000, 0xb5b5, 0xd6e8, 0x0000, 0xb2cf, 0xb2d6,
+ 0xb2d3, 0xb2d9, 0xb2d8, 0xb2d4, 0x0000, 0xd6e2, 0xd6e5, 0x0000,
+ 0xd6e4, 0xb2d0, 0xd6e6, 0xd6ef, 0xb2d1, 0xd6e3, 0xd6ec, 0xd6ed,
+ 0xb2d2, 0xd6ea, 0xb2d7, 0xb2cd, 0xb2d5, 0xd6e7, 0xb2cc, 0xd6eb,
+ 0x0000, 0x0000, 0xd6ee, 0x0000, 0x0000, 0xa0b6, 0xdafb, 0xdaf2,
+ 0xb5b2, 0xdaf9, 0xdaf6, 0xdaee, 0xdaf7, 0xb5b4, 0xdaef, 0x0000,
+ 0xdaeb, 0x0000, 0x9e42, 0xb86c, 0xdaf4, 0x8ea4, 0xb5b1, 0xdafa,
+ 0x0000, 0xb5b8, 0xb5ba, 0xdaed, 0x0000, 0x0000, 0xb5b9, 0xdaf0,
+ 0xb5b3, 0xdaf8, 0xdaf1, 0xdaf5, 0x0000, 0xdaf3, 0xb5b6, 0xdaec,
+ 0xb5bb, 0xb2ce, 0xb5b7, 0xb5bc, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb868, 0xdf5d, 0xdf5f, 0xdf61, 0xdf65, 0x0000, 0xdf5b,
+ 0xdf59, 0xb86a, 0x0000, 0xdf60, 0xdf64, 0xdf5c, 0xdf58, 0x0000,
+ 0xdf57, 0x8ea7, 0x0000, 0x8c76, 0xdf62, 0xdf5a, 0xdf5e, 0xb86b,
+ 0x0000, 0xb869, 0xdf66, 0xb867, 0xdf63, 0x0000, 0xe372, 0x9542,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xbaee, 0xe36a, 0xbd78, 0xe374,
+ 0xbaf1, 0xe378, 0xbaf7, 0xe365, 0x987d, 0x0000, 0xe375, 0xe362,
+ 0x9755, 0xe377, 0xe366, 0x8ea8, 0xbafe, 0xbafb, 0xe376, 0xe370,
+ 0xbaed, 0xbaf5, 0xbaf4, 0x8eaa, 0xbaf3, 0xbaf9, 0x0000, 0xe363,
+ 0xbafa, 0xe371, 0xbaf6, 0xbaec, 0xe373, 0xbaef, 0xbaf0, 0xbaf8,
+ 0xe368, 0xe367, 0xe364, 0x0000, 0xe36c, 0xe369, 0xe36d, 0xbafd,
+ 0x0000, 0xe379, 0xbaf2, 0xe36e, 0xe36f, 0x89a3, 0xe36b, 0x9960,
+ 0x9962, 0x0000, 0xbafc, 0x94fc, 0x9961, 0x0000, 0x0000, 0xe6e7,
+ 0xbd70, 0xbd79, 0xbd75, 0xe6e4, 0x94fa, 0xbd72, 0xbd76, 0xe6f0,
+ 0xbd6c, 0xe6e8, 0x0000, 0xbd74, 0x8eae, 0x8eb2, 0xe6eb, 0xe6e6,
+ 0xbd73, 0xbd77, 0xe6e5, 0x0000, 0xbd71, 0x0000, 0xe6ef, 0xbd6e,
+ 0xe6ee, 0xe6ed, 0xbd7a, 0xe572, 0xbd6d, 0x8eb0, 0xe6ec, 0xe6e3,
+ 0x0000, 0xbd7b, 0xe6ea, 0xbd6f, 0x0000, 0x9963, 0x97aa, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_7e[] = {
+ 0x0000, 0x0000, 0x0000, 0xe6e9, 0x0000, 0x0000, 0x0000, 0x94fb,
+ 0xbfa2, 0xbfa7, 0xbf7e, 0xead8, 0xeacf, 0xeadb, 0xead3, 0xead9,
+ 0xbfa8, 0xbfa1, 0xeacc, 0xead2, 0xeadc, 0xead5, 0xeada, 0xeace,
+ 0x0000, 0x0000, 0xead6, 0xbfa3, 0xead4, 0xbfa6, 0xbfa5, 0xead0,
+ 0xead1, 0xeacd, 0xead7, 0xbfa4, 0xeade, 0xeadd, 0x0000, 0x8ebb,
+ 0x0000, 0xedda, 0xedd6, 0xc15f, 0x0000, 0xedd0, 0xc159, 0xc169,
+ 0xeddc, 0xc161, 0xc15d, 0xedd3, 0xc164, 0xc167, 0xedde, 0xc15c,
+ 0xedd5, 0xc165, 0xede0, 0xeddd, 0xedd1, 0xc160, 0xc15a, 0xc168,
+ 0xedd8, 0xc163, 0xedd2, 0xc15e, 0xeddf, 0xc162, 0xc15b, 0xedd9,
+ 0xc166, 0xedd7, 0x0000, 0x0000, 0xeddb, 0x0000, 0x0000, 0x0000,
+ 0xf06e, 0xf074, 0xc2b9, 0xf077, 0xc2b4, 0xc2b5, 0xf06f, 0xf076,
+ 0xf071, 0xc2ba, 0xc2b7, 0x8cdc, 0xf06d, 0x0000, 0xc2b6, 0xf073,
+ 0xf075, 0xc2b8, 0xf072, 0xf070, 0x0000, 0x9876, 0x0000, 0x8ea1,
+ 0xf2b8, 0xc3b7, 0xc3b8, 0xc3b4, 0x8cb4, 0xc3b5, 0x8eb7, 0xf2b4,
+ 0xf2b2, 0x0000, 0xf2b6, 0xc3ba, 0xf2b7, 0xf2b0, 0xf2af, 0xf2b3,
+ 0xf2b1, 0xc3b6, 0xf2b5, 0xf4ac, 0xc47e, 0xc47d, 0xf4ad, 0x9da6,
+ 0xf4af, 0xf4ae, 0xc4a1, 0x0000, 0x0000, 0x0000, 0xf5eb, 0xf5e8,
+ 0xf5e9, 0x0000, 0xf5e7, 0xf5ea, 0xc4f2, 0xf5ec, 0x9eb0, 0xc4f1,
+ 0x0000, 0xf742, 0x8eb8, 0xc5d5, 0xc5d7, 0xf7ee, 0xc5d6, 0xf8b9,
+ 0xf940, 0xf942, 0xf8fe, 0xf941, 0xc66c, 0x0000, 0x0000, 0x9d70,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x896e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x896f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8970, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8971,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8972,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8973,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_7f[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8974, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa6ce, 0x8975,
+ 0xacfb, 0xd26f, 0xafca, 0x0000, 0x0000, 0xb2da, 0xdafc, 0xdafd,
+ 0x8ebc, 0x8ebd, 0x0000, 0xeadf, 0xc16a, 0xede1, 0x0000, 0x8ebe,
+ 0xc2bb, 0x9dd1, 0xf2ba, 0xf2b9, 0xc4a2, 0xf5ed, 0x94fd, 0xf743,
+ 0xc5f8, 0xca49, 0x8bd7, 0x8bda, 0xaac9, 0xa875, 0x0000, 0x0000,
+ 0xd04d, 0x0000, 0x0000, 0xd360, 0xd35b, 0xd35f, 0xd35d, 0xafcb,
+ 0xd35e, 0xd35c, 0x0000, 0xd6f1, 0x0000, 0xdafe, 0xdb40, 0xdf69,
+ 0xdf6a, 0xb86e, 0xb86f, 0xdf68, 0xdf6b, 0xdf67, 0xb86d, 0x0000,
+ 0xbb40, 0xa0e2, 0xb870, 0xe37a, 0x0000, 0xbd7c, 0xe6f1, 0xbd7d,
+ 0x9fe9, 0xbfa9, 0xeae2, 0xeae0, 0xeae1, 0xede4, 0xede3, 0xede2,
+ 0x0000, 0x0000, 0x0000, 0xf2bb, 0x0000, 0xc3b9, 0xf2bc, 0xf744,
+ 0xc5f9, 0xf8ba, 0xa6cf, 0xaacb, 0xaaca, 0xd04f, 0xacfc, 0xfda8,
+ 0x0000, 0xd04e, 0xd362, 0x8ae7, 0xafcc, 0xd6f2, 0xd361, 0x8ec2,
+ 0x0000, 0x0000, 0xb2dc, 0xd6f5, 0xd6f3, 0xd6f4, 0xb2db, 0x0000,
+ 0xdb42, 0xdb43, 0xdb41, 0x8ec4, 0xb873, 0xdf6d, 0xdf6c, 0xdf6e,
+ 0xb872, 0xb871, 0x0000, 0x0000, 0xe6f2, 0xe6f4, 0x9964, 0xbd7e,
+ 0xe6f3, 0xeae3, 0xbfaa, 0xf079, 0x9965, 0xf078, 0xc3bb, 0xf2bd,
+ 0xc3bd, 0xc3bc, 0xf4b0, 0xf5ee, 0xc4f3, 0xa6d0, 0xd050, 0xacfd,
+ 0xd365, 0xafce, 0xd364, 0xd363, 0x0000, 0xafcd, 0x0000, 0xd6fb,
+ 0x0000, 0xd6fd, 0xd6f6, 0xd6f7, 0xb2dd, 0xd6f8, 0xb2de, 0xd6fc,
+ 0xd6f9, 0xd6fa, 0xb2df, 0x0000, 0xb5be, 0xb5bf, 0x0000, 0xdb44,
+ 0x0000, 0x0000, 0x0000, 0xdf6f, 0xdf70, 0x954e, 0xe37e, 0xbb43,
+ 0xbb41, 0xbb42, 0xe37b, 0xe37c, 0x0000, 0xe37d, 0xe6f9, 0x98b3,
+ 0xe6fa, 0xbda1, 0xe6f7, 0xe6f6, 0xe6f8, 0xe6f5, 0xbfad, 0xeae4,
+ 0xbfab, 0xbfac, 0xede6, 0xc16b, 0xede5, 0xefa8, 0x0000, 0xf07a,
+ 0xf07b, 0xc2bc, 0x8ecb, 0xc2bd, 0xc16c, 0xf2be, 0xf2bf, 0xf4b1
+};
+
+static const unsigned short big5hkscs_from_unicode_80[] = {
+ 0xc4a3, 0xa6d1, 0x8bdf, 0xa6d2, 0xacfe, 0xaacc, 0xafcf, 0xd051,
+ 0x8ece, 0x0000, 0x0000, 0xb5c0, 0xa6d3, 0xad41, 0xd052, 0xd053,
+ 0xad40, 0xad42, 0xa6d4, 0x0000, 0xd054, 0xafd1, 0xd366, 0xafd3,
+ 0xafd0, 0xafd2, 0x0000, 0xd741, 0xb2e0, 0x8ecf, 0xd740, 0xd6fe,
+ 0x9968, 0xdf71, 0x0000, 0x0000, 0xe3a1, 0x9969, 0xbda2, 0x0000,
+ 0xbfae, 0xeae6, 0xeae5, 0x0000, 0xede7, 0x0000, 0x996b, 0x8ed1,
+ 0xf5ef, 0x996c, 0x0000, 0xa6d5, 0xcb73, 0xcdaa, 0xad43, 0xd055,
+ 0x0000, 0xd368, 0x0000, 0x8ed4, 0x8ed5, 0xafd4, 0xd367, 0xafd5,
+ 0x0000, 0x0000, 0x0000, 0xd743, 0x0000, 0x0000, 0xb2e2, 0xd742,
+ 0xd744, 0x0000, 0xb2e1, 0x0000, 0x0000, 0x0000, 0x0000, 0xdb46,
+ 0xdb47, 0xdb45, 0xb5c1, 0x0000, 0x996d, 0x0000, 0xb874, 0x0000,
+ 0xb875, 0x0000, 0xbb45, 0xa0be, 0xe3a3, 0xe3a2, 0xbb44, 0x0000,
+ 0x0000, 0x8ed6, 0xa0bc, 0xa0b5, 0xe6fb, 0x0000, 0xa0b4, 0xe6fc,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xeae7, 0x0000, 0x0000, 0xc170,
+ 0xc16f, 0xc16d, 0xc16e, 0xc171, 0x0000, 0xf07c, 0xc2bf, 0xc2be,
+ 0xf2c0, 0xf4b2, 0x0000, 0x0000, 0x0000, 0xc5a5, 0xc5a4, 0xa6d6,
+ 0x8be0, 0x0000, 0xd1fb, 0x0000, 0xb877, 0xb5c2, 0xb876, 0xbb46,
+ 0x0000, 0xa6d7, 0xc9a9, 0xa6d8, 0xa6d9, 0x0000, 0x0000, 0xcdab,
+ 0xcb76, 0x0000, 0xcb77, 0xa877, 0x0000, 0xcb74, 0xa876, 0x0000,
+ 0xa879, 0xcb75, 0xa87b, 0xa87a, 0xcb78, 0xa878, 0x0000, 0x89b5,
+ 0x0000, 0xaad1, 0xaacf, 0xcdad, 0x0000, 0xaace, 0x0000, 0x8edd,
+ 0x0000, 0xaad3, 0xaad5, 0xaad2, 0x0000, 0xcdb0, 0xcdac, 0xaad6,
+ 0x0000, 0xaad0, 0xa87c, 0x0000, 0xaad4, 0xcdaf, 0x9e5d, 0x9971,
+ 0xcdae, 0x0000, 0xaacd, 0x0000, 0x89ae, 0x9de8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd05b, 0xad47, 0xad48, 0xd05d, 0x9565, 0xd057,
+ 0xd05a, 0xd063, 0xd061, 0x0000, 0xad49, 0xd067, 0xad4c, 0xd064,
+ 0xd05c, 0xd059, 0x0000, 0x0000, 0xdb49, 0xd062, 0xad44, 0xd065,
+ 0xd056, 0xd05f, 0xad46, 0xad4b, 0xd060, 0xad4f, 0xad4d, 0x0000,
+ 0xd058, 0xad4a, 0x0000, 0xd05e, 0xad4e, 0xad45, 0xd066, 0x0000,
+ 0x0000, 0x9972, 0x0000, 0x0000, 0x8b5c, 0xafda, 0x0000, 0xafe3,
+ 0xafd8, 0xafd6, 0xd36a, 0xafde, 0xafdb, 0xd36c, 0x89b1, 0x0000,
+ 0xafdd, 0xd36b, 0xd369, 0xd36e, 0xafe2, 0xafe0, 0xdb48, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_81[] = {
+ 0xd36f, 0xd36d, 0xafd7, 0xa0c0, 0x0000, 0xafd9, 0xafdc, 0x8edf,
+ 0xafdf, 0x9566, 0xafe1, 0x0000, 0x9974, 0x0000, 0x9976, 0x0000,
+ 0x0000, 0x0000, 0x9977, 0x0000, 0x9979, 0xd74e, 0xb2e4, 0x9dda,
+ 0xd745, 0xd747, 0x8ee0, 0xd748, 0x0000, 0xd750, 0xd74c, 0xd74a,
+ 0x0000, 0xd74d, 0xd751, 0xb2e5, 0xb2e9, 0xd746, 0x0000, 0xd74f,
+ 0x0000, 0xb2e7, 0x935c, 0xb2e6, 0xd74b, 0xd749, 0x0000, 0xb2e3,
+ 0xb2e8, 0x0000, 0x9de6, 0x0000, 0x8b5f, 0x0000, 0x0000, 0x9563,
+ 0x0000, 0xb5c8, 0xdb51, 0x0000, 0x0000, 0xdb4f, 0xb5ca, 0x0000,
+ 0x0000, 0x0000, 0x9567, 0xdb4a, 0xdfa1, 0x0000, 0xb5c9, 0xdb4e,
+ 0x9de3, 0x0000, 0xdb4b, 0xb5c5, 0xb5cb, 0xdb50, 0xb5c7, 0xdb4d,
+ 0xbb47, 0xb5c6, 0xdb4c, 0xb5cc, 0xb5c4, 0xb5c3, 0x997c, 0x0000,
+ 0x0000, 0x997d, 0x997e, 0xdf77, 0xdf75, 0x0000, 0xdf7b, 0x0000,
+ 0xdf73, 0xdfa2, 0xdf78, 0x0000, 0xdf72, 0xb87b, 0xb8a3, 0xdf7d,
+ 0x0000, 0xdf76, 0x0000, 0xb87e, 0x0000, 0x8b5b, 0xb87c, 0xdf7e,
+ 0xb879, 0xb878, 0xdf79, 0xb87d, 0xb5cd, 0x0000, 0xdf7c, 0xdf74,
+ 0xb87a, 0xb8a1, 0xb8a2, 0x0000, 0x99a3, 0x0000, 0x0000, 0xbb4c,
+ 0xbb48, 0x0000, 0xbb4d, 0xe3a6, 0x99a4, 0x0000, 0xe3a5, 0xe3a7,
+ 0xbb4a, 0xe3a4, 0xbb4b, 0xe3aa, 0xe3a9, 0xe3a8, 0x0000, 0xbb49,
+ 0x0000, 0x0000, 0x0000, 0x99a6, 0x0000, 0xe741, 0x0000, 0xe744,
+ 0xbda8, 0xe743, 0xbda7, 0xbda3, 0xbda4, 0xbda5, 0xe740, 0xe6fe,
+ 0xbda6, 0x0000, 0xe742, 0xe6fd, 0x0000, 0x99a8, 0xeae9, 0xeaf3,
+ 0xbfb1, 0xbfb0, 0x8abe, 0xeaed, 0xeaef, 0x0000, 0xeaea, 0x0000,
+ 0xeaee, 0xeae8, 0xeaf1, 0xbfaf, 0xeaf0, 0xeaec, 0x9e61, 0xeaf2,
+ 0x0000, 0xeaeb, 0xc174, 0xede8, 0xedee, 0xc178, 0xc17a, 0xc177,
+ 0xc176, 0x99aa, 0xc175, 0xc173, 0xede9, 0xedec, 0xc172, 0xeded,
+ 0xa0c8, 0xc179, 0xedeb, 0x0000, 0xedea, 0xc2c0, 0x0000, 0xc2c1,
+ 0xf0a1, 0xf07d, 0xf07e, 0x0000, 0x0000, 0xf2c2, 0x0000, 0xf2c1,
+ 0xc3be, 0xf4b4, 0xc4a4, 0xf4b3, 0x0000, 0xf5f0, 0xf745, 0xc5a6,
+ 0xf943, 0xf944, 0xc5d8, 0xa6da, 0x99ab, 0xaad7, 0xdb52, 0xbb4e,
+ 0xc17b, 0xedef, 0xa6db, 0x0000, 0xafe5, 0xafe4, 0xdb53, 0xfec4,
+ 0x0000, 0x0000, 0xeaf4, 0xa6dc, 0xad50, 0x0000, 0x98c2, 0xdb54,
+ 0xdb55, 0xdb56, 0xbb4f, 0xbfb2, 0xa6dd, 0x0000, 0xaad8, 0xd068
+};
+
+static const unsigned short big5hkscs_from_unicode_82[] = {
+ 0xafe6, 0xd370, 0xb2ea, 0x0000, 0xdb57, 0xb8a4, 0x0000, 0xbb50,
+ 0xbfb3, 0xc17c, 0xc2c2, 0xf4b5, 0xa6de, 0xaad9, 0x0000, 0x0000,
+ 0xafe7, 0xd752, 0xb5ce, 0x0000, 0xbb51, 0xe3ab, 0xe745, 0x0000,
+ 0x8ee8, 0x0000, 0xa0ba, 0xa6df, 0xb5cf, 0xdfa3, 0xbb52, 0xa6e0,
+ 0xcdb1, 0xd069, 0xad51, 0x0000, 0x0000, 0xd372, 0xfd77, 0x0000,
+ 0xafea, 0x8eee, 0xafe8, 0xafe9, 0xafeb, 0x9ebf, 0x0000, 0xd371,
+ 0x0000, 0x0000, 0xd757, 0xd754, 0xd756, 0xb2eb, 0xb2ed, 0xb2ec,
+ 0xd753, 0xb2ee, 0xd755, 0x0000, 0xdb58, 0xdb59, 0x89c2, 0xdb5a,
+ 0xdfa6, 0x0000, 0xdfa7, 0x0000, 0xdfa5, 0xdfa8, 0x0000, 0xb8a5,
+ 0x0000, 0xdfa4, 0x0000, 0xbb53, 0x0000, 0x0000, 0xe74a, 0xe746,
+ 0xe749, 0xe74b, 0xe748, 0xe747, 0x99ac, 0xeaf5, 0xeaf6, 0xeaf7,
+ 0xbfb4, 0xbfb5, 0xedf1, 0xedf0, 0xedf2, 0x0000, 0xf0a3, 0xf0a2,
+ 0x0000, 0xf2c4, 0x956b, 0xf2c5, 0xf2c3, 0x956c, 0xc4a5, 0x0000,
+ 0xf4b6, 0xf4b7, 0x0000, 0xf746, 0xf7ef, 0xf8bb, 0xa6e1, 0xa87d,
+ 0x0000, 0xc17d, 0xa6e2, 0x0000, 0xd758, 0xdb5b, 0x99af, 0xc641,
+ 0xca4a, 0x994a, 0x8976, 0x8f48, 0xca4b, 0xca4d, 0xa6e3, 0xca4e,
+ 0xca4c, 0x0000, 0x0000, 0xcba2, 0xcba3, 0xcb7b, 0x0000, 0xfbee,
+ 0x0000, 0x0000, 0xcba1, 0xa8a1, 0x0000, 0xa8a2, 0xcb7c, 0xcb7a,
+ 0xcb79, 0xcb7d, 0xa87e, 0xcb7e, 0xd06a, 0x0000, 0x0000, 0x0000,
+ 0xcdb6, 0xaadc, 0xcdb5, 0xcdb7, 0x0000, 0xaadb, 0xcdbc, 0xaadf,
+ 0xcdb2, 0xcdc0, 0xcdc6, 0xaae6, 0xcdc3, 0xaae3, 0x99ae, 0xcdb9,
+ 0xcdbf, 0xcdc1, 0x8efb, 0xcdb4, 0xaae2, 0xaadd, 0xcdba, 0xaae4,
+ 0xaae7, 0xaae1, 0x0000, 0xaada, 0xcdbe, 0xcdb8, 0xcdc5, 0xaae9,
+ 0xaae5, 0xaae0, 0xcdbd, 0xafec, 0xcdbb, 0xaade, 0xaae8, 0x8cd0,
+ 0xcdb3, 0x0000, 0xcdc2, 0xcdc4, 0x8b52, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x99b0, 0x0000, 0x0000, 0x0000, 0x0000, 0x8977,
+ 0x8f41, 0xad62, 0xad5c, 0xad64, 0xad61, 0xd071, 0xd074, 0xad5d,
+ 0x99b1, 0xd06b, 0x0000, 0xad56, 0xad60, 0x0000, 0xad63, 0xad65,
+ 0xd0a2, 0xd077, 0x8f49, 0xad55, 0xd0a1, 0xad59, 0xad57, 0xad52,
+ 0xd06f, 0x0000, 0xd07e, 0xd073, 0xd076, 0xd0a5, 0xfa4d, 0xad66,
+ 0xd07d, 0xad5e, 0xd078, 0xd0a4, 0xd075, 0xd079, 0xd07c, 0x9de4,
+ 0x8cb5, 0xd06d, 0xd0a3, 0xd07b, 0xfbe9, 0x9b54, 0xd06c, 0x99b2
+};
+
+static const unsigned short big5hkscs_from_unicode_83[] = {
+ 0xd070, 0xad5f, 0xad5a, 0xad53, 0xad58, 0xad54, 0xad67, 0xd06e,
+ 0xd3a5, 0xad5b, 0x0000, 0x9e68, 0xd07a, 0xce41, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd3a8, 0xaffa,
+ 0x8f4a, 0xd376, 0x8f42, 0xd3a3, 0xd37d, 0x8f51, 0xd3b2, 0x0000,
+ 0xd3aa, 0x0000, 0xd37e, 0x0000, 0xd3a9, 0xd378, 0xd37c, 0xd3b5,
+ 0xaffd, 0xd3ad, 0xd3a4, 0xafed, 0xd3b3, 0xd374, 0x0000, 0xd3ac,
+ 0x0000, 0xaffc, 0xaff7, 0xd373, 0xaff5, 0xaff4, 0xaff9, 0xd3ab,
+ 0xaff1, 0xaff8, 0xd072, 0xdb5c, 0xd3a6, 0x9846, 0x0000, 0xd37a,
+ 0xaffb, 0xd37b, 0xd3a1, 0xaffe, 0xd375, 0xd3af, 0x0000, 0xd3ae,
+ 0xd3b6, 0xaff3, 0xaff0, 0xd3b4, 0xd3b0, 0xd3a7, 0xd3a2, 0xaff6,
+ 0xaff2, 0xd377, 0xafee, 0xd3b1, 0xafef, 0x0000, 0xd379, 0x99b4,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8ef5, 0xfd55, 0x0000, 0x0000, 0x9ccd, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8978,
+ 0x0000, 0x0000, 0x0000, 0xd75e, 0xd760, 0xd765, 0xd779, 0xb2fc,
+ 0xb2f2, 0x0000, 0xd75d, 0xb2fd, 0xb2fe, 0xd768, 0xd76f, 0xd775,
+ 0x0000, 0xd762, 0x0000, 0xd769, 0x0000, 0x8f53, 0xb340, 0xd777,
+ 0xd772, 0xb2fa, 0xb2f8, 0xd76e, 0xd76a, 0xd75c, 0xb2ef, 0xd761,
+ 0xd759, 0x8f6f, 0xb2f7, 0xb2f9, 0xd766, 0xd763, 0xb2f4, 0xd773,
+ 0xb2f1, 0xd764, 0xd77a, 0xd76c, 0x8e63, 0xd76b, 0xb2f0, 0x0000,
+ 0xb2fb, 0x0000, 0xb2f3, 0xd75a, 0xd75f, 0xd770, 0xd776, 0xb341,
+ 0xd75b, 0xd767, 0xd76d, 0xb2f6, 0x8f56, 0x0000, 0xd778, 0xd771,
+ 0xd774, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xfe76, 0x0000, 0x0000, 0x0000, 0xb2f5, 0x9fc6, 0xdb6c,
+ 0xdb60, 0xb5d7, 0xdb7d, 0xdba7, 0xdbaa, 0xb5d5, 0xdb68, 0xdba3,
+ 0xdb69, 0xdb77, 0xb5e2, 0xdb73, 0xb5df, 0xfaac, 0xdb74, 0xdb5d,
+ 0x0000, 0xdba4, 0x0000, 0x8f58, 0xb5e8, 0xdba1, 0xdb75, 0xdbac,
+ 0xdb70, 0xdfc8, 0x0000, 0xdbaf, 0xb5e6, 0xdb6e, 0xdb7a, 0xb5e9,
+ 0xb5d4, 0xdb72, 0xdbad, 0xdb6b, 0xdb64, 0xdb6f, 0x0000, 0xdb63,
+ 0xdb61, 0xb5d0, 0xdba5, 0xdb6a, 0xdba8, 0x9848, 0xdba9, 0xb5d8,
+ 0xb5dd, 0xb5d9, 0xb5e1, 0xdb7e, 0xb5da, 0xdb76, 0xdb66, 0x0000,
+ 0xb5d2, 0xdb5e, 0xdba2, 0xdbab, 0xdb65, 0xb5e0, 0xdbb0, 0xdb71
+};
+
+static const unsigned short big5hkscs_from_unicode_84[] = {
+ 0x0000, 0xdb6d, 0x0000, 0xb5d1, 0xb5e5, 0x99b7, 0xdb7c, 0xb5e7,
+ 0x0000, 0xdb78, 0xb5dc, 0xb5d6, 0xb5de, 0xb5d3, 0xb5e4, 0xdb79,
+ 0xdb67, 0xdb7b, 0xdb62, 0xdba6, 0x9665, 0x0000, 0xfa6c, 0x0000,
+ 0x9de7, 0x0000, 0x0000, 0xdbae, 0x9e62, 0x0000, 0x0000, 0x0000,
+ 0x96cc, 0x8e67, 0x0000, 0xdb5f, 0xfc75, 0x0000, 0x987e, 0x0000,
+ 0x0000, 0xdfc7, 0x0000, 0xdfdd, 0xb855, 0xdfcc, 0xfdb9, 0xdfca,
+ 0xdfb5, 0xb8a9, 0xdfc5, 0xdfd9, 0xdfc1, 0xb8b1, 0xdfd8, 0xdfbf,
+ 0xb5e3, 0xdfcf, 0xdfc0, 0xdfd6, 0xb8b0, 0xb8a8, 0x97fc, 0xdfaa,
+ 0xdfb2, 0x0000, 0xdfcb, 0xdfc3, 0xdfdc, 0xdfc6, 0xb8b6, 0xdfd7,
+ 0x98f9, 0xb8ad, 0x8f66, 0xdfc9, 0xdfd1, 0xdfb6, 0xdfd0, 0x0000,
+ 0xdfe1, 0xdfb1, 0xdfd2, 0x956e, 0xdfdf, 0x9245, 0xdfab, 0xb5db,
+ 0x8f60, 0xdfb9, 0xdfb8, 0xb8af, 0x9ed1, 0xdfbc, 0xdfbe, 0xdfcd,
+ 0xdfde, 0xb8b2, 0xfecd, 0xb8b3, 0x99b9, 0xdfb0, 0xb8ab, 0xdfb4,
+ 0xdfda, 0xb8b4, 0x0000, 0xb8ac, 0xb8ae, 0xb8b5, 0xdfe0, 0xdfd3,
+ 0xdfce, 0x8f62, 0x974c, 0xdfbb, 0xdfba, 0xb8aa, 0xdfac, 0xb8a7,
+ 0xdfc4, 0xdfad, 0xdfc2, 0x0000, 0x0000, 0xdfb7, 0xdfdb, 0x91c7,
+ 0x955f, 0x0000, 0xb8a6, 0x0000, 0x0000, 0x0000, 0xdfb3, 0x0000,
+ 0x99bb, 0x0000, 0x0000, 0x0000, 0x0000, 0xdfaf, 0xdfd5, 0xdfae,
+ 0xbb60, 0xe3d3, 0x8e6d, 0x8f71, 0xe3c2, 0x0000, 0x94cb, 0xe3ac,
+ 0xe3ca, 0xbb58, 0xe3bb, 0xe3c5, 0xbb5b, 0xe3be, 0xbb59, 0xe3af,
+ 0xe3cd, 0xe3ae, 0xe3c1, 0x95b1, 0xe3ad, 0x0000, 0x0000, 0xe3bf,
+ 0xe3c8, 0xe3c6, 0xe3ba, 0xe3b5, 0xe3b3, 0x9af2, 0xe3b4, 0xe3c7,
+ 0xe3d2, 0xe3bc, 0xbb5a, 0x0000, 0xe3b7, 0x0000, 0xe3cb, 0x0000,
+ 0xbb5d, 0xe3b6, 0xe3b0, 0xe3c0, 0xbb61, 0x96c3, 0x99bd, 0xbb55,
+ 0xbb5e, 0xe3b8, 0xe3b2, 0x0000, 0xbb57, 0xdfd4, 0xbb56, 0xe3c3,
+ 0x0000, 0xbb54, 0xbb63, 0xbb5c, 0xe3c4, 0xe3b9, 0xe3b1, 0xe3cc,
+ 0xe3bd, 0xbb62, 0xe3d0, 0xbb5f, 0xe3cf, 0x0000, 0xe3c9, 0xe3ce,
+ 0x0000, 0x0000, 0xa0cf, 0xe3d1, 0x0000, 0x0000, 0x8f6d, 0x0000,
+ 0x0000, 0x99be, 0x8ef4, 0x0000, 0x8f72, 0x95e4, 0x0000, 0xe773,
+ 0xe774, 0xe767, 0xe766, 0xe762, 0xbdb4, 0x0000, 0xbdac, 0xe776,
+ 0xe775, 0xdfa9, 0xe75f, 0xe763, 0xe75d, 0x0000, 0xe770, 0xe761,
+ 0x99bf, 0xe777, 0xe75a, 0xe758, 0xe764, 0xe76e, 0xe769, 0xbdb6
+};
+
+static const unsigned short big5hkscs_from_unicode_85[] = {
+ 0xe74f, 0x0000, 0xe76d, 0x9244, 0x0000, 0xfba5, 0xbdb7, 0xdfbd,
+ 0xe75b, 0xe752, 0xe755, 0xe77b, 0xe75c, 0xe753, 0xe751, 0xe74e,
+ 0x99c0, 0xbdb0, 0xe765, 0xbdaf, 0xbdb3, 0xe760, 0xe768, 0xbda9,
+ 0xe778, 0xe77c, 0xbdab, 0x0000, 0xe757, 0xe76b, 0xe76f, 0xe754,
+ 0xe779, 0xbdb2, 0x0000, 0xbdb1, 0xe74c, 0xbdb5, 0xe772, 0xe756,
+ 0xe76a, 0xe750, 0xe75e, 0xe759, 0xbdad, 0xbdae, 0xe76c, 0xe77d,
+ 0xe77a, 0xe771, 0x0000, 0xfdb4, 0x8f77, 0x0000, 0x0000, 0x0000,
+ 0x99c1, 0x0000, 0x0000, 0xe74d, 0x0000, 0xbdaa, 0xeb49, 0x0000,
+ 0xeb40, 0xeb43, 0xfab9, 0xbfbb, 0xeb45, 0xeaf9, 0xeb41, 0xeb47,
+ 0xbfb8, 0xbfbc, 0xbfb6, 0x8f40, 0xfa44, 0xeafb, 0xeb4c, 0x0000,
+ 0x0000, 0xeb46, 0x99c2, 0xeafc, 0xeb55, 0xeb4f, 0xeaf8, 0xee46,
+ 0xeafe, 0xbfb7, 0x8f5c, 0xeb4a, 0x0000, 0xeb54, 0xbfbf, 0x8cbd,
+ 0xeb51, 0xeafd, 0xeb44, 0xeb48, 0xeb42, 0xeb56, 0xeb53, 0xeb50,
+ 0xbfb9, 0xbfba, 0xbfbe, 0xeafa, 0xeb57, 0xbfbd, 0xeb4d, 0x99c4,
+ 0x99c5, 0xeb4b, 0x0000, 0x8f7b, 0x0000, 0xeb4e, 0xee53, 0xee40,
+ 0xee45, 0xee52, 0xee44, 0xedfb, 0xee41, 0x0000, 0xc1a2, 0x0000,
+ 0xedf4, 0xee4d, 0xee4f, 0xedf3, 0xc1a1, 0xee51, 0xee49, 0xc1a8,
+ 0xee50, 0xee42, 0xc1aa, 0xedf9, 0xeb52, 0xee4a, 0xee47, 0xedf5,
+ 0xee55, 0xc1a4, 0x0000, 0x0000, 0xc1a5, 0xedf7, 0xee48, 0x8cb6,
+ 0xee54, 0xee4b, 0xedfd, 0xc1a7, 0xc1a3, 0xee4c, 0xedfe, 0xee56,
+ 0xedf8, 0xee43, 0xee4e, 0xedfa, 0xedfc, 0x0000, 0xc2cb, 0xedf6,
+ 0xc1a9, 0xc2c4, 0xc17e, 0x0000, 0x0000, 0x0000, 0x0000, 0xc1a6,
+ 0xc2c8, 0xf0b3, 0x0000, 0xf0a9, 0xf0a4, 0xf0aa, 0xf0b4, 0xf0b8,
+ 0xf0b7, 0xc2ca, 0xc2c9, 0x0000, 0x0000, 0xf0ab, 0xf0b9, 0xf0ae,
+ 0xf0a6, 0x8fa3, 0xf0a8, 0xf0a7, 0xf0ad, 0xf0b2, 0xf0a5, 0xf0ac,
+ 0xf0b1, 0xc2c7, 0x0000, 0xf0af, 0x0000, 0xc2c5, 0xf0b0, 0xc2c3,
+ 0xc2c6, 0xf2d5, 0xf0b5, 0x0000, 0x0000, 0xc3c2, 0x8cce, 0xf2cd,
+ 0xf2d1, 0xf2c9, 0xf2cc, 0x0000, 0xf2d4, 0xc3c0, 0xf2d9, 0xf2d2,
+ 0x99c6, 0xf2ca, 0xf2da, 0xf2d3, 0xc3c3, 0xc3c4, 0xf2d7, 0x0000,
+ 0xf2cb, 0xc3bf, 0xc3c1, 0xf2c6, 0xf2ce, 0xf2c8, 0x96cd, 0xf2d8,
+ 0xf2d6, 0xf2c7, 0xf2cf, 0x0000, 0x0000, 0x0000, 0xf4be, 0xc3c5,
+ 0xf2d0, 0xc4a7, 0xc4a9, 0xc4a6, 0x96c7, 0xf4c3, 0xf4bb, 0xf4b9
+};
+
+static const unsigned short big5hkscs_from_unicode_86[] = {
+ 0xf4bd, 0xf4ba, 0x8fa5, 0x0000, 0xf4bf, 0xf4c1, 0xc4aa, 0xc4ac,
+ 0x0000, 0xf4c0, 0xc4ad, 0xc4ab, 0xf4c2, 0xfabb, 0x0000, 0x8c61,
+ 0x9570, 0xc4a8, 0x0000, 0x0000, 0x9368, 0x0000, 0x8f7e, 0xc4f4,
+ 0xf5f1, 0xf5f7, 0xc4f6, 0xf4bc, 0xf5f6, 0x0000, 0xf5fd, 0xf5f4,
+ 0xf5fb, 0xf5fa, 0xf4b8, 0xf5f5, 0xf0b6, 0xf5fe, 0xf5f3, 0xf5f8,
+ 0x8faa, 0xf5fc, 0xf5f2, 0x0000, 0xf74a, 0xc4f5, 0xf5f9, 0xa050,
+ 0x0000, 0xf7f4, 0xf74b, 0xf749, 0xf747, 0xf748, 0xf74c, 0x0000,
+ 0xc5d9, 0xf7f2, 0xf7f0, 0xf7f5, 0xf7f3, 0x0000, 0xf7f6, 0xc5da,
+ 0xf7f1, 0x0000, 0x90d3, 0xf8bc, 0x0000, 0x9556, 0xf945, 0xf946,
+ 0xf947, 0x0000, 0x0000, 0xf9c7, 0xf9bd, 0xca4f, 0xaaea, 0x0000,
+ 0xad68, 0x0000, 0xd3b8, 0xd3b7, 0xb040, 0xb342, 0xd77c, 0x0000,
+ 0x0000, 0xd77b, 0x0000, 0xb5ea, 0xb8b8, 0x0000, 0xb8b7, 0xb8b9,
+ 0x0000, 0xe3d4, 0xe77e, 0xeb58, 0xeb5a, 0xeb59, 0x0000, 0xc1ab,
+ 0xee57, 0xf0ba, 0xf9a5, 0xa6e4, 0x8fb8, 0xcdc9, 0xcdca, 0xcdc8,
+ 0xcdc7, 0xaaeb, 0x99c8, 0xd0a9, 0xd0a7, 0x0000, 0x0000, 0xd0a6,
+ 0x0000, 0xad69, 0xad6b, 0xad6a, 0xd0a8, 0x0000, 0x8faf, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd3c4, 0xd3c1, 0xd3bf,
+ 0x0000, 0x0000, 0xb041, 0xd3c2, 0xb046, 0xd3bc, 0xd3cb, 0x0000,
+ 0xd3cd, 0xd3bd, 0x99c9, 0xb043, 0xd3ce, 0xd3c9, 0xd3bb, 0xd3c0,
+ 0xd3ca, 0xd3c6, 0xd3c3, 0x0000, 0xb048, 0xd3cc, 0xd3be, 0x0000,
+ 0x9579, 0xd3c7, 0xd3b9, 0xb047, 0xb044, 0xd3c5, 0x0000, 0xd3c8,
+ 0xd3ba, 0xb045, 0xb042, 0x0000, 0x0000, 0x9f49, 0x0000, 0xb34c,
+ 0xd7a5, 0xb34b, 0x99ca, 0xd7a8, 0xd7ab, 0xb348, 0xb346, 0xd77e,
+ 0xd7a9, 0xd7a7, 0xd7a4, 0xd7ac, 0xd7ad, 0xd7af, 0xd7b0, 0xd77d,
+ 0xb345, 0xd7a2, 0xd7a1, 0xd7ae, 0xb347, 0xd7a3, 0xb349, 0xb344,
+ 0xd7a6, 0xb34d, 0x0000, 0xb34a, 0xd7aa, 0x0000, 0x0000, 0x0000,
+ 0xb5f1, 0xdbbf, 0x0000, 0xdbb4, 0xb5ee, 0x0000, 0xdfe7, 0xdbbd,
+ 0xdbb1, 0xb5ec, 0xdbb6, 0xb5ef, 0xdbba, 0xdbb8, 0xb5f2, 0xb5eb,
+ 0x0000, 0x0000, 0xdbb2, 0xdbb5, 0xb5f0, 0x0000, 0xdbb3, 0x0000,
+ 0xdbbe, 0xdbbc, 0xdbb7, 0xdbb9, 0xdbbb, 0xb5ed, 0x0000, 0x99cb,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdfe8, 0xdfee, 0xdfe4,
+ 0xdfea, 0xb8ba, 0xdfe6, 0xb8c0, 0x0000, 0x0000, 0xb8bf, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_87[] = {
+ 0xb8be, 0xdfed, 0xb8c1, 0xb8c2, 0xdfe3, 0xdff0, 0xb8c3, 0xb8bd,
+ 0xb8bc, 0xdfec, 0xb8c4, 0xdfe2, 0xdfe5, 0xdfef, 0xdfeb, 0x0000,
+ 0x0000, 0xe3f4, 0xe3e9, 0xb8bb, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xbb6a, 0xe3dd, 0xe3f2, 0xe3de, 0xbb65, 0x0000, 0xe3db, 0x0000,
+ 0xe3e4, 0xe3dc, 0xbb67, 0xe3d6, 0xe3f1, 0xbb68, 0xe3ee, 0xe3ef,
+ 0xe3d7, 0xbb6d, 0xe3e6, 0x0000, 0xe3e0, 0xe3e7, 0xe3da, 0x0000,
+ 0xe3f3, 0xe3eb, 0xe3e5, 0xe3d5, 0xbb69, 0xe3ec, 0x0000, 0xbb6c,
+ 0xe3f0, 0x0000, 0xe3ea, 0xbb66, 0xe3e8, 0x0000, 0xe3e2, 0xbb64,
+ 0xe3d9, 0xe3e1, 0xe3ed, 0xe3df, 0x0000, 0x0000, 0xe3e3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xbdc1, 0xdfe9, 0xe7b2, 0xe7bb,
+ 0xe7b1, 0xe7ad, 0xe7aa, 0xbdc2, 0xe7a8, 0xbb6b, 0xe7a1, 0xbdc0,
+ 0xe7a7, 0xbdbf, 0xe7ac, 0xe7a9, 0xe7b9, 0xe7b4, 0xe7ae, 0xe7b3,
+ 0xbdbb, 0xe7ab, 0xe7be, 0xe7a2, 0xe7a3, 0xe7ba, 0xbdbc, 0xe7bf,
+ 0xbdbe, 0xe7c0, 0xe7b0, 0xe3d8, 0xe7b6, 0xe7af, 0xe7b8, 0xe7b5,
+ 0x9dd5, 0x8fb0, 0x0000, 0xe7a6, 0xbdb9, 0xe7bd, 0xbdba, 0xe7a4,
+ 0xbdbd, 0xeb64, 0xe7b7, 0xe7bc, 0x0000, 0xfa7a, 0x0000, 0x0000,
+ 0x0000, 0xeb61, 0xbdb8, 0xbfc0, 0xeb6b, 0xeb67, 0x9e5f, 0xeb65,
+ 0xeb60, 0xeb6f, 0x0000, 0x99cd, 0xa0c9, 0xbfc4, 0x0000, 0xeb5c,
+ 0xeb68, 0xeb69, 0xeb5f, 0xeb5e, 0xeb6c, 0x0000, 0xeb62, 0xeb5d,
+ 0xeb63, 0x0000, 0xeb6e, 0xeb5b, 0xeb6d, 0xeb6a, 0xbfc2, 0xbfc1,
+ 0x0000, 0x0000, 0xbfc3, 0xeb66, 0xf0cb, 0x9adb, 0x0000, 0x0000,
+ 0x0000, 0xa0c6, 0xee59, 0xc1b1, 0xee5d, 0xee5a, 0xee61, 0xee67,
+ 0xee5c, 0x8fb4, 0xee70, 0xc1ae, 0xee6a, 0xee5f, 0xee6b, 0xee66,
+ 0xee6d, 0xee5e, 0xc1b3, 0xc1b2, 0xee60, 0xee6e, 0xee58, 0xee6c,
+ 0xc1ac, 0xa0d7, 0xee64, 0xee63, 0xee68, 0xee5b, 0xc1b0, 0x0000,
+ 0xc1b4, 0xee62, 0xee69, 0xc1b5, 0xee65, 0x0000, 0xa0c7, 0x0000,
+ 0x0000, 0xc1ad, 0xc1af, 0xf0c7, 0xf0c5, 0x0000, 0xa043, 0xf0cc,
+ 0xf0c9, 0xf0cd, 0x8fb5, 0xf0be, 0xf0c6, 0xf0d1, 0xee6f, 0xf0c2,
+ 0xc2cf, 0xe7a5, 0xf0bd, 0xf0ca, 0xf0c4, 0xf0c1, 0xf0bc, 0xf0bb,
+ 0xf0d0, 0x0000, 0xf0c0, 0xf0bf, 0xc2cd, 0xf0c8, 0x8fb2, 0xc2cc,
+ 0x0000, 0x0000, 0xc2ce, 0xf0c3, 0xf0cf, 0xa061, 0xf2de, 0xf2df,
+ 0x0000, 0xc3c9, 0xf2dc, 0xc3c6, 0xf2e4, 0x0000, 0xc3ca, 0xf2e6
+};
+
+static const unsigned short big5hkscs_from_unicode_88[] = {
+ 0xf2db, 0xf0ce, 0xf2e8, 0xf2dd, 0x9e5e, 0xc3c7, 0xf2e3, 0x0000,
+ 0xf2e5, 0xf2e0, 0xf2e7, 0xf2e2, 0xf2e1, 0xc3c8, 0x0000, 0xa063,
+ 0xf4c5, 0xf4c6, 0x0000, 0xf4c8, 0xc4ae, 0xc4af, 0xf4c9, 0xf4c7,
+ 0x9fe8, 0xf4c4, 0x0000, 0xf642, 0xf645, 0xf641, 0x0000, 0xc4fa,
+ 0xf643, 0xc4f9, 0xc4f8, 0xc4f7, 0xf644, 0xf751, 0xf74f, 0x9cb2,
+ 0xf74e, 0xf640, 0xf750, 0xf646, 0xf74d, 0x957c, 0xf7f9, 0xf7d7,
+ 0xf7f7, 0xc5db, 0xf7f8, 0xf7fa, 0x0000, 0xf8bf, 0xc5fa, 0xf8be,
+ 0xf8bd, 0xc5fb, 0x0000, 0xc65a, 0xf96e, 0xf9a7, 0xf9a6, 0xf9a8,
+ 0xa6e5, 0xd0aa, 0x9fc7, 0xd3cf, 0xd3d0, 0x8fbb, 0x8fbc, 0x0000,
+ 0xdbc0, 0x0000, 0xf647, 0xf8c0, 0xa6e6, 0xad6c, 0xd0ab, 0x8fec,
+ 0x0000, 0x0000, 0xd7b1, 0xb34e, 0x0000, 0xdbc2, 0xdbc1, 0xb5f3,
+ 0x0000, 0xb8c5, 0xe7c1, 0xbdc3, 0x0000, 0xbdc4, 0x8fc0, 0x0000,
+ 0x936a, 0xbfc5, 0xc5fc, 0xa6e7, 0x8be4, 0x9c7c, 0x0000, 0xd0ac,
+ 0xaaed, 0xd0ae, 0xd0ad, 0xad6d, 0x0000, 0xd3d1, 0x95a1, 0xd3d8,
+ 0xb049, 0xd3d6, 0xd3d4, 0x0000, 0xd3db, 0xd3d2, 0xd3d3, 0xb04a,
+ 0x0000, 0xb04e, 0x0000, 0x0000, 0xd3dc, 0xb04d, 0xd3da, 0xd3d7,
+ 0xd3d5, 0xb04b, 0xb04c, 0xd3d9, 0xfeec, 0x0000, 0x0000, 0x95a3,
+ 0xb350, 0xd7b2, 0x0000, 0xb355, 0xd7c2, 0xb354, 0xd7c4, 0x8c45,
+ 0x8cb8, 0xd7b8, 0xb352, 0xd7c3, 0x0000, 0xd7b3, 0xb353, 0xd7bf,
+ 0xd7bb, 0xd7bd, 0xd7b7, 0xd7be, 0x8fc1, 0x0000, 0xb34f, 0xd7ba,
+ 0xa052, 0xd7b9, 0xd7b5, 0x0000, 0xd7c0, 0x0000, 0x0000, 0xd7bc,
+ 0xd7b4, 0x0000, 0xd7b6, 0xb351, 0xd7c1, 0x0000, 0x99d0, 0x0000,
+ 0x0000, 0xb5f6, 0xdbcd, 0x0000, 0x8fc3, 0x8fc4, 0xdbc9, 0xdbcb,
+ 0xdbc6, 0xdbc5, 0xdbc3, 0x0000, 0xdbca, 0xdbcc, 0xdbc8, 0x95a4,
+ 0xdbc7, 0xb5f4, 0xb5f5, 0x0000, 0x0000, 0x8fc6, 0x0000, 0x9e60,
+ 0x0000, 0xdbcf, 0xb8cd, 0xdff2, 0xdff8, 0xdff3, 0xdff4, 0xf9d8,
+ 0xdff9, 0x0000, 0xb8cf, 0x0000, 0xb8c7, 0xb8ce, 0xdff1, 0xdbc4,
+ 0xb8ca, 0xb8c8, 0xdff7, 0xdff6, 0xb8c9, 0xb8cb, 0xdff5, 0xb8c6,
+ 0x0000, 0xb8cc, 0x0000, 0x0000, 0x0000, 0x0000, 0x95a5, 0xe3f6,
+ 0xbb74, 0x0000, 0x0000, 0xe442, 0xe441, 0x0000, 0xe3fb, 0xbb76,
+ 0xe440, 0xe3f7, 0xe3f8, 0xbb6e, 0xbb70, 0x9cb3, 0xe3fd, 0xe3f5,
+ 0xbb72, 0xbb71, 0xe3f9, 0xe3fe, 0xe3fc, 0xbb73, 0xe3fa, 0x99d1
+};
+
+static const unsigned short big5hkscs_from_unicode_89[] = {
+ 0xfef1, 0xdbce, 0xbb6f, 0x0000, 0x0000, 0xe7c2, 0xe7c9, 0xbdc6,
+ 0x0000, 0xe7cd, 0xbdca, 0xe7c5, 0xe7c3, 0x0000, 0xe7cc, 0x0000,
+ 0xbdc5, 0xe7cb, 0xbdc7, 0xbdc8, 0xe7c4, 0xbdc9, 0xe7ca, 0xe7c6,
+ 0xe7c7, 0xe7c8, 0xbb75, 0x0000, 0x0000, 0x0000, 0xeb70, 0xeb7c,
+ 0x0000, 0xbfca, 0xeb77, 0xeb79, 0x99d2, 0xbfc8, 0xeb71, 0xeb75,
+ 0x0000, 0xeb78, 0xbfc6, 0xbfc9, 0xeb7b, 0xeb73, 0xeb74, 0xeb7a,
+ 0xeb72, 0xeb76, 0xbfc7, 0xee72, 0x0000, 0xee71, 0xc1b7, 0xee77,
+ 0xc1b9, 0x0000, 0x0000, 0xc1b6, 0xee73, 0xc1ba, 0xee74, 0x0000,
+ 0x0000, 0xee75, 0xee78, 0x9cc2, 0xc1b8, 0x0000, 0xf0d6, 0x99d3,
+ 0x0000, 0xf0d9, 0x0000, 0xf0d3, 0xf0d5, 0x95a7, 0x0000, 0xf0d4,
+ 0xf0d7, 0xf0d8, 0xee76, 0xf0d2, 0x95a9, 0x0000, 0xc3cd, 0xf2ec,
+ 0xf2ef, 0xf2f1, 0xf2ea, 0xf2eb, 0xf2ee, 0xf2f0, 0xc3ce, 0xc3cc,
+ 0xc3cb, 0xf2ed, 0xf2e9, 0xf4ca, 0xc4b0, 0x95a6, 0xf4cb, 0x0000,
+ 0x0000, 0xf649, 0xc4fb, 0xf64b, 0xc4fc, 0xf648, 0xf64a, 0xc5a8,
+ 0x0000, 0xf752, 0xc5a7, 0xf7fd, 0xf7fc, 0x0000, 0xf7fb, 0x9c5d,
+ 0x0000, 0xf948, 0xf949, 0xf94b, 0xf94a, 0x0000, 0xca50, 0xa6e8,
+ 0x98e2, 0xad6e, 0xd7c5, 0xb5f7, 0x0000, 0xdffa, 0xc2d0, 0x8fc9,
+ 0xf2f2, 0xa0c2, 0x8fca, 0xa8a3, 0x0000, 0x0000, 0x0000, 0xb357,
+ 0x0000, 0x99d4, 0x0000, 0xb356, 0xa0b9, 0xdbd0, 0xb5f8, 0xdbd2,
+ 0xdbd1, 0x0000, 0x0000, 0xdffb, 0xb8d0, 0xe443, 0xe446, 0xe445,
+ 0x0000, 0xe444, 0xe7ce, 0xe7d0, 0xe7cf, 0x9b58, 0xbfcc, 0x8fcd,
+ 0x0000, 0xa0d4, 0xbfcb, 0x0000, 0xc1bb, 0xee79, 0xee7b, 0xee7a,
+ 0x0000, 0x0000, 0xc2d1, 0x0000, 0x0000, 0x0000, 0xf2f4, 0xf2f3,
+ 0x0000, 0xf4cc, 0xc4b1, 0x0000, 0x8fce, 0xc4fd, 0xf754, 0xf753,
+ 0xc65b, 0x8be5, 0x0000, 0x0000, 0x0000, 0x0000, 0x8979, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa8a4, 0xd0af, 0xad6f, 0xd7c8, 0xd7c6, 0x0000,
+ 0x0000, 0xd7c7, 0xdbd4, 0xdbd5, 0xe043, 0xdbd3, 0x0000, 0xdffc,
+ 0xe041, 0xe040, 0xe042, 0xb8d1, 0xdffe, 0xdffd, 0xe044, 0x8fd0,
+ 0xe449, 0xe447, 0x0000, 0xe448, 0xe7d3, 0xe7d1, 0x0000, 0x0000,
+ 0xe7d2, 0xeb7d, 0xee7c, 0xee7d, 0xc2d2, 0x0000, 0xf2f5, 0xf4cd,
+ 0xc4b2, 0x0000, 0xf64c, 0xf755, 0xc5a9, 0x0000, 0xf7fe, 0xf94c
+};
+
+static const unsigned short big5hkscs_from_unicode_8a[] = {
+ 0xa8a5, 0x0000, 0xad71, 0xad72, 0xd0b0, 0x0000, 0x0000, 0xd0b1,
+ 0xad70, 0x0000, 0xb054, 0x0000, 0xb052, 0x0000, 0xb051, 0xb058,
+ 0xb050, 0xb059, 0xd3dd, 0xb056, 0x0000, 0xb053, 0xb057, 0xb055,
+ 0xb04f, 0x0000, 0x0000, 0xb35f, 0x95b6, 0xb359, 0xd7cc, 0xb35e,
+ 0x0000, 0x0000, 0xb360, 0xb35a, 0x0000, 0xb35b, 0x0000, 0xd7ca,
+ 0x0000, 0x99d6, 0xb358, 0x95e5, 0xd7cb, 0xb35d, 0x0000, 0x0000,
+ 0xd7c9, 0xb35c, 0x0000, 0x0000, 0xb644, 0x0000, 0xb646, 0x0000,
+ 0x99d7, 0xdbd8, 0xb645, 0xb5f9, 0xb5fd, 0x95b5, 0xb8e4, 0xe049,
+ 0xdbda, 0xb5fe, 0x0000, 0x0000, 0xdbdd, 0xdbde, 0xb643, 0x0000,
+ 0xdbe0, 0xa0ca, 0xdbe2, 0x0000, 0xdbe3, 0xdbd7, 0xdbd6, 0xdbe4,
+ 0xb642, 0xdbe1, 0xdbdf, 0x0000, 0xb640, 0xb5fb, 0xb647, 0xdbdb,
+ 0xdbdc, 0xdbd9, 0x0000, 0xb641, 0x0000, 0x0000, 0xb5fc, 0x0000,
+ 0xb5fa, 0xe048, 0xb8df, 0xb8da, 0x0000, 0x0000, 0xb8d5, 0x9ffd,
+ 0xb8e5, 0xb8d6, 0x0000, 0xb8d2, 0xb8e1, 0xb8de, 0xb8e0, 0x0000,
+ 0xb8d7, 0xb8dc, 0xb8d3, 0xb8d4, 0xe050, 0xe04d, 0xe045, 0xe04a,
+ 0x0000, 0xb8e2, 0xe051, 0xb8e3, 0xb8d9, 0x0000, 0xa058, 0xe047,
+ 0x0000, 0xe04f, 0xe04b, 0xe04e, 0xe04c, 0xb8dd, 0xe046, 0xb8d8,
+ 0x0000, 0x0000, 0x0000, 0xe44c, 0xbb78, 0xbb7b, 0x0000, 0xe44e,
+ 0x8fd6, 0xbba5, 0xe44d, 0xbb7d, 0x99d8, 0xbdcf, 0xe44f, 0x0000,
+ 0xbba4, 0xe44b, 0xbba6, 0x0000, 0x8fd3, 0x0000, 0xbb79, 0x0000,
+ 0xb8db, 0xbb7c, 0x0000, 0xbb7a, 0xbb7e, 0xbba2, 0xbb77, 0xbba7,
+ 0xbba3, 0x8fe5, 0xbba1, 0xe44a, 0x0000, 0x0000, 0x0000, 0x8fe9,
+ 0xbdd6, 0x0000, 0xbdd2, 0x0000, 0x99d9, 0x0000, 0xbdd9, 0x0000,
+ 0xe7d6, 0xbdda, 0xe7e2, 0xe7db, 0xbdcb, 0xe7e3, 0xe7dd, 0xbdd5,
+ 0xe7de, 0x0000, 0xbdd4, 0xe7e1, 0xbdce, 0xe7df, 0xe7d5, 0xbdcd,
+ 0xebaa, 0xbdd3, 0x0000, 0xbdd0, 0x0000, 0xbdd8, 0x0000, 0xe7d4,
+ 0x0000, 0xe7d8, 0xbdcc, 0xe7d7, 0xe7d9, 0xe7da, 0xbdd7, 0xe7dc,
+ 0xe7e0, 0xe7e4, 0x927c, 0xbddb, 0xbfd2, 0xeba5, 0xebab, 0xeba8,
+ 0xeb7e, 0xebac, 0xeba1, 0x0000, 0xeba7, 0x0000, 0xbfcd, 0xbfd3,
+ 0xebad, 0x0000, 0x9c45, 0xbfcf, 0x0000, 0xbfd9, 0xbfd4, 0xebaf,
+ 0xeba9, 0xbfd0, 0xeba2, 0xbfda, 0xeba3, 0xeba4, 0xbfdb, 0xbfd8,
+ 0xbdd1, 0x0000, 0xbfce, 0xebb0, 0xbfdc, 0x0000, 0xbfd5, 0xebae
+};
+
+static const unsigned short big5hkscs_from_unicode_8b[] = {
+ 0xbfd1, 0xbfd6, 0xbfd7, 0x0000, 0xc1c3, 0xeea4, 0xeead, 0xeeaa,
+ 0xeeac, 0x0000, 0xc1c0, 0xeea5, 0x8fde, 0xeeab, 0xc1bc, 0xeea7,
+ 0xc1c4, 0xeea3, 0xeea8, 0xeeaf, 0xeba6, 0xeea9, 0xeea2, 0xc1bd,
+ 0xeea1, 0xc1be, 0xeeb0, 0xc1bf, 0xeeae, 0xc1c2, 0xee7e, 0x8fdf,
+ 0xc1c1, 0x0000, 0xeea6, 0xf0dc, 0xf0ea, 0xf0e5, 0xf0e7, 0xf0db,
+ 0xc2d3, 0x0000, 0xf0da, 0xc2d6, 0xc2d5, 0xa04b, 0xf0e9, 0xf0e1,
+ 0xf0de, 0xf0e4, 0x0000, 0xf0dd, 0x0000, 0xf0df, 0xf0e8, 0xf0e6,
+ 0x0000, 0xc2d4, 0xf0ed, 0xf0eb, 0xf0e2, 0xf0ec, 0xf0e3, 0x8fe2,
+ 0xf2f9, 0xc3cf, 0xf341, 0xa0cc, 0x0000, 0xf64f, 0xc3d6, 0xf0e0,
+ 0xf2f7, 0xc3d2, 0xf2f8, 0xf2fd, 0x8fe3, 0x8fe4, 0xc3d4, 0xc3d5,
+ 0xf2f6, 0xf340, 0xf342, 0xf2fa, 0xf2fc, 0xf2fe, 0xf2fb, 0xf343,
+ 0xc3d1, 0xc3d7, 0xc3d3, 0x0000, 0xc3d0, 0xf4d0, 0x9bc4, 0xc4b7,
+ 0xf4ce, 0x0000, 0x9bfc, 0xf4d2, 0x0000, 0xf4d3, 0xc4b5, 0xf4d4,
+ 0xf4d1, 0x964c, 0xf4cf, 0xc4b8, 0xc4b4, 0xf4d5, 0x0000, 0xc4b6,
+ 0xc4b3, 0x0000, 0x0000, 0x0000, 0xc4fe, 0x0000, 0x0000, 0xc540,
+ 0xf64e, 0xf64d, 0xf650, 0xf651, 0x0000, 0xc541, 0xf756, 0xf75b,
+ 0xc5aa, 0x9af6, 0xf758, 0x8cae, 0xf757, 0xf75a, 0xf759, 0x0000,
+ 0xf843, 0x0000, 0xc5dc, 0xf842, 0xf840, 0x0000, 0xf841, 0x0000,
+ 0x8fe7, 0x0000, 0xc5fe, 0xc5fd, 0xf8c1, 0xf8c2, 0xc640, 0x0000,
+ 0xf94d, 0xf94e, 0xc667, 0x8fe8, 0xc66d, 0x0000, 0xf9a9, 0xf9c8,
+ 0x8be7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x897a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x897b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_8c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa8a6,
+ 0x0000, 0xd7cd, 0x0000, 0xd7ce, 0xe052, 0xe450, 0xe7e5, 0xc1c6,
+ 0x0000, 0xc1c5, 0xf0ee, 0xf344, 0x0000, 0xf844, 0xa8a7, 0xd3de,
+ 0xb05a, 0xb361, 0xe054, 0xe053, 0xbddc, 0xe7e6, 0xbddd, 0xeeb1,
+ 0xc2d7, 0x99da, 0x0000, 0x0000, 0xc676, 0xa8a8, 0xcdcb, 0xd3df,
+ 0x0000, 0x0000, 0xb362, 0x0000, 0xd7cf, 0xd7d0, 0x0000, 0xdbe5,
+ 0x0000, 0xb648, 0xb8e6, 0x0000, 0xe056, 0xe055, 0xe057, 0x0000,
+ 0xe451, 0xe452, 0xbba8, 0xbfdd, 0xbdde, 0xbfde, 0x0000, 0xeeb5,
+ 0xeeb2, 0xeeb4, 0xeeb3, 0xc1c7, 0x0000, 0xf0ef, 0xf346, 0xf345,
+ 0xcba4, 0xb05c, 0xb05b, 0xd3e0, 0x0000, 0xd7d1, 0x0000, 0x0000,
+ 0xdbe7, 0xdbe6, 0xb649, 0x0000, 0xe059, 0xe05a, 0xe058, 0x0000,
+ 0x0000, 0xb8e8, 0xb8e7, 0x0000, 0xbbaa, 0xbba9, 0x0000, 0xe7e7,
+ 0xebb3, 0xebb1, 0xebb2, 0xbfdf, 0xeeb7, 0xeeb6, 0x0000, 0xf0f2,
+ 0xf0f1, 0xf0f0, 0xf347, 0x8fed, 0xf9aa, 0xa8a9, 0xad73, 0x95c0,
+ 0xad74, 0xb05d, 0xb05e, 0xd3e2, 0xd3e1, 0xd7d2, 0x0000, 0xb368,
+ 0xb366, 0xb363, 0xb367, 0xb365, 0xb364, 0xa0cb, 0x0000, 0xb64a,
+ 0xdbea, 0x0000, 0xb8ed, 0xb64c, 0xb651, 0xdbec, 0xb653, 0xb652,
+ 0xb655, 0xdbeb, 0xdbe8, 0xb64f, 0xb64b, 0xb64d, 0xdbe9, 0xb654,
+ 0xb650, 0xb64e, 0xb8ef, 0xb8ee, 0xb8ec, 0xb8f0, 0x0000, 0xb8ea,
+ 0xb8eb, 0x0000, 0xb8e9, 0x0000, 0xe05b, 0x9e48, 0x0000, 0xe454,
+ 0x0000, 0xbbac, 0xbbad, 0xbbab, 0x99db, 0xe453, 0x8ff3, 0xe455,
+ 0x0000, 0xe7ea, 0xe7ec, 0x8ff9, 0xbde7, 0xe7ed, 0xbde0, 0xe7e9,
+ 0xbddf, 0xbde9, 0xbde5, 0xbde6, 0xbde2, 0xe7e8, 0xbde1, 0xe7ee,
+ 0xe7eb, 0x95c1, 0xbde8, 0xa04e, 0xbde3, 0xbde4, 0xebb5, 0x0000,
+ 0xebb7, 0xebb6, 0x99dc, 0xebb8, 0xbfe0, 0xebb4, 0x0000, 0xa064,
+ 0xc1cb, 0xeeb8, 0xc1c8, 0xc1cc, 0xc1ca, 0xc1c9, 0xf0f3, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_8d[] = {
+ 0xf0f6, 0x0000, 0xf0f5, 0x8ff7, 0xf0f4, 0xc2d8, 0xf348, 0xf349,
+ 0xc3d8, 0xf34a, 0xc3d9, 0x89b0, 0xa048, 0xc4ba, 0x0000, 0xc4b9,
+ 0xf652, 0x8ffb, 0x8ff6, 0xc542, 0xf653, 0xf75c, 0xc5ab, 0xc5ac,
+ 0x9ddc, 0xf845, 0x0000, 0xc642, 0x99dd, 0x8be8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa8aa, 0x0000, 0xb36a, 0xb369,
+ 0xe05c, 0xe05d, 0x0000, 0xbbae, 0xebb9, 0xbdea, 0xebba, 0xeeb9,
+ 0xa8ab, 0x0000, 0xd0b2, 0xad76, 0xad75, 0x0000, 0xd3e3, 0xb05f,
+ 0xd3e4, 0xd7d5, 0x92c1, 0xd7d4, 0x0000, 0xd7d3, 0x0000, 0x0000,
+ 0xdbee, 0xb658, 0x9fd6, 0x0000, 0xdbed, 0xb657, 0x0000, 0x0000,
+ 0x0000, 0xdbef, 0xb656, 0x0000, 0xe05f, 0xe062, 0xe060, 0xe061,
+ 0xe065, 0xe05e, 0xe066, 0xe063, 0xe064, 0xbbb0, 0xe456, 0x0000,
+ 0x0000, 0xbbaf, 0x0000, 0xe7f2, 0xe7f0, 0x0000, 0x0000, 0xbdeb,
+ 0xe7ef, 0xe7f1, 0x0000, 0xbdec, 0x0000, 0xebbb, 0xa0d2, 0xebbc,
+ 0xc1cd, 0x9040, 0xf34c, 0xf34e, 0xf34b, 0xf34d, 0xf4d6, 0xf654,
+ 0x0000, 0x0000, 0xf96f, 0xa8ac, 0xad77, 0xd3e5, 0xd3e7, 0xd3e6,
+ 0x0000, 0xd7d8, 0xb36c, 0x0000, 0xd7d6, 0x0000, 0xb36b, 0xd7d9,
+ 0x8ac4, 0xd7da, 0xd7d7, 0x99e0, 0x0000, 0xdbfb, 0xb660, 0xdbf3,
+ 0xdbf9, 0x0000, 0x0000, 0xb65b, 0xb65e, 0xdbf2, 0xb659, 0xdbf6,
+ 0xe06c, 0xb65d, 0x0000, 0xdbf1, 0x9ff0, 0xdbf7, 0xdbf4, 0xdbfa,
+ 0xdbf0, 0xdbf8, 0xb65c, 0xb65f, 0xdbf5, 0xb65a, 0x0000, 0xb8f2,
+ 0xe068, 0xb8f1, 0xe06f, 0xe06e, 0xb8f8, 0x0000, 0xb8f9, 0xe070,
+ 0xb8f3, 0xe06d, 0xb8f7, 0xe072, 0xe069, 0x0000, 0xe06b, 0xb8f4,
+ 0xe067, 0xe06a, 0xe071, 0xb8f5, 0xe073, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xb8f6, 0x0000, 0xbbb1, 0xe45b, 0xe461, 0xe459
+};
+
+static const unsigned short big5hkscs_from_unicode_8e[] = {
+ 0xe462, 0x9ff3, 0xe458, 0xe45d, 0xe463, 0xe460, 0xe45f, 0xe45e,
+ 0x0000, 0xe457, 0xe45c, 0x0000, 0x0000, 0xe45a, 0x9dbf, 0xbdf1,
+ 0xbdee, 0xe7fb, 0xe841, 0xe843, 0xe840, 0xe7f8, 0xe7fa, 0xe845,
+ 0xe842, 0xe7fc, 0xe846, 0xe7f9, 0xe844, 0xbdef, 0xbdf5, 0xbdf3,
+ 0xe7f3, 0xbdf4, 0xbdf0, 0xe7f4, 0xe7f6, 0xe7f5, 0xe7fd, 0xe7fe,
+ 0x9ff6, 0xbdf2, 0x95c8, 0xbded, 0x0000, 0x9e5a, 0xe7f7, 0x0000,
+ 0xebc6, 0xbfe2, 0x0000, 0xebbd, 0xbfe3, 0xbfe6, 0xebc2, 0x0000,
+ 0xebbf, 0xbfe5, 0x99e3, 0x0000, 0xebc3, 0xebc4, 0xebbe, 0xebc7,
+ 0xebc0, 0xebc5, 0xbfe4, 0x0000, 0xbfe1, 0xebc1, 0x8a4a, 0xeebf,
+ 0xc1d0, 0xc1ce, 0xc1d1, 0xc1cf, 0xeebe, 0xeebb, 0xeeba, 0x9ff1,
+ 0xeebd, 0x0000, 0x0000, 0xeebc, 0xf145, 0xc2de, 0xf0fb, 0xf0fa,
+ 0x0000, 0xc2d9, 0xf141, 0xf140, 0xf0f7, 0xf143, 0xf0fc, 0xc2dd,
+ 0xf0f9, 0xf142, 0xf0f8, 0xc2da, 0xc2dc, 0xf0fd, 0xc2db, 0xf0fe,
+ 0x8aa7, 0xf144, 0xf352, 0x0000, 0xc3de, 0xf34f, 0x0000, 0xf353,
+ 0x0000, 0x99e6, 0xc3db, 0xf351, 0xc3e0, 0x9ff7, 0xc3dd, 0x9fed,
+ 0xf350, 0x0000, 0xc3df, 0xf354, 0xc3da, 0x0000, 0x8a5c, 0x0000,
+ 0x9dae, 0xc4bc, 0xc4be, 0x0000, 0xf4d9, 0xc4bd, 0xf4d7, 0xc3dc,
+ 0xf4d8, 0xc4bb, 0xc543, 0xc545, 0xf656, 0xc544, 0xf655, 0x0000,
+ 0xf761, 0xc5ad, 0xf760, 0xc5ae, 0xf75e, 0xf75d, 0xf762, 0xf763,
+ 0xf846, 0x0000, 0xf75f, 0x0000, 0x0000, 0xf8c6, 0xf8c3, 0xf8c4,
+ 0xf8c5, 0xc65c, 0x0000, 0xf951, 0xf950, 0xf94f, 0xf970, 0x95c9,
+ 0xf9be, 0xf9ab, 0xc66e, 0xa8ad, 0xb060, 0x9048, 0x0000, 0x0000,
+ 0x99e8, 0x0000, 0xb8fa, 0x0000, 0x0000, 0x0000, 0x9049, 0x0000,
+ 0x0000, 0x8cba, 0xbdf6, 0x0000, 0x90b1, 0xebc8, 0x0000, 0x0000,
+ 0xc2df, 0x0000, 0xf355, 0x904a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf9ac, 0xa8ae, 0xaaee, 0xad79, 0xad78, 0x99ea, 0xb063,
+ 0x0000, 0xd3e8, 0xb061, 0xd3e9, 0xb062, 0x0000, 0x0000, 0xd7df,
+ 0xd7db, 0x0000, 0x9bd1, 0xb36d, 0xd7de, 0xd7dd, 0xd7dc, 0xb36e,
+ 0xd7e0, 0xd7e1, 0x99eb, 0x0000, 0x99ec, 0xdc43, 0xdc41, 0xdc45,
+ 0xdc46, 0xdc4c, 0x0000, 0xdc48, 0xdc4a, 0x99ed, 0xdc42, 0xdbfc,
+ 0x0000, 0xdc49, 0x99ee, 0x0000, 0xdc4b, 0xdc44, 0xdc47, 0xdbfd,
+ 0xb662, 0xdc40, 0xdbfe, 0xb661, 0xb663, 0x0000, 0xb8fd, 0xe075
+};
+
+static const unsigned short big5hkscs_from_unicode_8f[] = {
+ 0xe077, 0xe076, 0xe07b, 0xb8fb, 0x0000, 0xe078, 0xe074, 0xe079,
+ 0xe07a, 0xb8fc, 0xb8fe, 0xe07c, 0x0000, 0xe467, 0xe466, 0x0000,
+ 0xe464, 0xe465, 0xbbb3, 0xbbb5, 0xbbb2, 0xbbb4, 0xe84d, 0xe84e,
+ 0xe849, 0x904c, 0xe84a, 0xbdf8, 0xbdfd, 0xbdf7, 0xbdfe, 0xbdf9,
+ 0xe84b, 0x0000, 0x0000, 0xe84c, 0xe848, 0xbe40, 0xbdfb, 0x0000,
+ 0x0000, 0xbdfa, 0xbdfc, 0x0000, 0xe847, 0x904d, 0xebca, 0xbfe8,
+ 0x95cb, 0x0000, 0xebcc, 0xbfea, 0xebcf, 0xebcb, 0xebc9, 0xebce,
+ 0xbfe9, 0xebcd, 0x0000, 0xbfe7, 0x0000, 0x0000, 0xc1d3, 0xc1d6,
+ 0xeec1, 0x97e2, 0xc1d4, 0xeec0, 0xc1d2, 0xc1d5, 0xf146, 0xf147,
+ 0xf148, 0xc2e0, 0x95cc, 0xf149, 0x0000, 0xc2e1, 0xc3e2, 0xf358,
+ 0xf359, 0xf357, 0xf356, 0xf35a, 0xc3e1, 0xf4dd, 0xf4db, 0xf4dc,
+ 0xf4de, 0xf4da, 0xf4df, 0xf658, 0x9f78, 0xf659, 0xf657, 0xc546,
+ 0xf764, 0xc5af, 0xf765, 0xf848, 0xf847, 0x0000, 0x897c, 0x897d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x897e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x995d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa8af, 0xb664, 0x0000, 0x0000, 0xb940,
+ 0x9b5a, 0x0000, 0x0000, 0xbbb6, 0x0000, 0x9050, 0xbfec, 0x8c4f,
+ 0xbfeb, 0x0000, 0x0000, 0x0000, 0x0000, 0xc3e3, 0xc47c, 0xc547,
+ 0xa8b0, 0xb064, 0xb941, 0x9054, 0xf35b, 0xc6d6, 0x9aa8, 0x99ef,
+ 0xfeeb, 0x9da3, 0x9da1, 0x9943, 0x9945, 0x0000, 0x9d7d, 0xcba6,
+ 0x0000, 0x99f0, 0xa8b1, 0x0000, 0xa8b4, 0xa8b3, 0xa8b2, 0x0000,
+ 0x0000, 0xcba5, 0x99f1, 0xcdcd, 0x99f2, 0xcdcf, 0xaaef, 0x8cbc,
+ 0x9d60, 0xaaf1, 0xcdcc, 0xcdce, 0xaaf0, 0xcdd1, 0xcdd0, 0xcdd2,
+ 0x0000, 0x0000, 0xa0a3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd0b6, 0xd0b4, 0xad7c, 0xd0b3, 0xada3, 0xad7e, 0xad7b, 0x0000,
+ 0xada4, 0x0000, 0xad7d, 0xada2, 0x0000, 0xada1, 0xd0b5, 0x0000,
+ 0xad7a, 0x0000, 0x0000, 0x0000, 0xb06a, 0xd3eb, 0xd3f1, 0xb067,
+ 0xb06e, 0x905b, 0xb069, 0xd3ee, 0xd3f0, 0xb06c, 0xd3ea, 0xd3ed
+};
+
+static const unsigned short big5hkscs_from_unicode_90[] = {
+ 0xb068, 0xb065, 0xd3ec, 0xb06b, 0xd3ef, 0xb06d, 0xb066, 0x0000,
+ 0x9edb, 0x0000, 0x0000, 0xd7e3, 0xd7e6, 0xb370, 0x0000, 0xb37a,
+ 0xb376, 0xd7e4, 0x9d79, 0x0000, 0xb37e, 0xb377, 0xb37c, 0xb372,
+ 0x0000, 0xb36f, 0xb371, 0xb37d, 0xd7e5, 0xb375, 0xb378, 0xb374,
+ 0xb379, 0xd7e7, 0xb37b, 0xb373, 0xd7e2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdc4d, 0xb665, 0xdc4f,
+ 0x0000, 0xb667, 0xb669, 0x99f3, 0xdc4e, 0xb666, 0xb66a, 0x9062,
+ 0xb668, 0x0000, 0x0000, 0x0000, 0xb947, 0xe0a3, 0xb94f, 0xe07e,
+ 0x0000, 0xb950, 0xb945, 0x0000, 0xe0a1, 0x0000, 0x0000, 0xb94a,
+ 0x0000, 0xe0a2, 0xb943, 0xb942, 0x9f55, 0xb94d, 0xb94c, 0xb94b,
+ 0xb949, 0xb94e, 0xe07d, 0xb944, 0xb946, 0xb948, 0x9bf9, 0x0000,
+ 0xbbb8, 0xbbbb, 0x0000, 0xbbbf, 0xbbb9, 0xbbbe, 0xbbbc, 0x0000,
+ 0xbbb7, 0x9065, 0xbbbd, 0xbbba, 0x96e0, 0x0000, 0x0000, 0xe852,
+ 0xbe43, 0xbe41, 0x0000, 0xe853, 0x98be, 0xbe44, 0xbe42, 0xe851,
+ 0xe850, 0x0000, 0xbff0, 0xe84f, 0xbfee, 0xbfed, 0xebd0, 0xbe45,
+ 0xbfef, 0xebd1, 0xbff2, 0xebd2, 0xbff1, 0xc1d8, 0xeec3, 0xc1d7,
+ 0xc1dc, 0xc1da, 0xc1db, 0xc2e3, 0xc1d9, 0xeec2, 0xebd3, 0xc2e2,
+ 0xc2e4, 0x0000, 0xc3e4, 0xc3e5, 0x0000, 0xf4e0, 0x0000, 0xc5de,
+ 0xc5dd, 0xa8b6, 0x0000, 0x0000, 0xca55, 0xb06f, 0x0000, 0xca52,
+ 0xca53, 0xca51, 0x0000, 0xca54, 0x0000, 0x0000, 0xcbaa, 0xcba7,
+ 0xcbac, 0xcba8, 0xa8b7, 0xa8ba, 0x0000, 0xcba9, 0xa8b9, 0xcbab,
+ 0x9068, 0x0000, 0xa8b8, 0x0000, 0x0000, 0x0000, 0x906c, 0xcdd5,
+ 0xcdd7, 0xaaf4, 0xcdd3, 0xcdd6, 0xcdd4, 0xaaf2, 0xaaf5, 0x0000,
+ 0xaaf3, 0x0000, 0x0000, 0x95d8, 0x0000, 0xd0b8, 0xd0bc, 0xd0b9,
+ 0x0000, 0xada7, 0x0000, 0xada8, 0x906a, 0xd0bb, 0x0000, 0xd0bd,
+ 0xd0bf, 0x0000, 0xada5, 0xd0be, 0x0000, 0x0000, 0xada6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd7ee, 0xd0ba, 0xd3f2, 0xd3fb,
+ 0xd3f9, 0xd3f4, 0xd3f5, 0xd3fa, 0xd3fc, 0xb071, 0x0000, 0xd3f7,
+ 0xd3f3, 0xb070, 0xb072, 0xd3f6, 0xd3fd, 0xd3f8, 0x0000, 0x0000,
+ 0xb3a1, 0xd7f1, 0xd7e9, 0xd7ef, 0xd7f0, 0xb3a2, 0x0000, 0xd7e8,
+ 0xd7ea, 0xd0b7, 0xd7ec, 0xd7ed, 0xd7eb, 0xb66c, 0x0000, 0x0000,
+ 0x0000, 0xdc56, 0xebd4, 0xdc57, 0xdc54, 0xb3a3, 0xb66e, 0xdc53
+};
+
+static const unsigned short big5hkscs_from_unicode_91[] = {
+ 0xdc59, 0xdc58, 0xb66b, 0xdc5c, 0xdc52, 0xdc5b, 0xdc50, 0xdc5a,
+ 0xdc55, 0xb66d, 0x0000, 0xe0aa, 0x0000, 0xe0a5, 0xe0ab, 0xe0a6,
+ 0xe0a4, 0xe0a7, 0xb951, 0x0000, 0xe0a9, 0x0000, 0xe0a8, 0xb952,
+ 0xbbc1, 0xbbc0, 0xe46e, 0xe471, 0xe469, 0xe46d, 0xbbc2, 0xe46c,
+ 0xe46a, 0xe470, 0xe46b, 0xe468, 0xe46f, 0x0000, 0xe859, 0xbe48,
+ 0xf14a, 0xe856, 0xe857, 0xe855, 0xdc51, 0xbe47, 0xe85a, 0xe854,
+ 0xbe46, 0xbe49, 0xe858, 0xebd5, 0xbff3, 0xebd6, 0xebd7, 0x0000,
+ 0xeec4, 0xc1dd, 0xf14b, 0xf14c, 0x0000, 0x0000, 0xf14d, 0xf35d,
+ 0xf35c, 0xf4e2, 0x0000, 0xf4e1, 0xf65b, 0xf65c, 0xf65a, 0xf766,
+ 0xc5b0, 0xa8bb, 0xadaa, 0xada9, 0xb075, 0xb074, 0xd440, 0xd441,
+ 0xd3fe, 0x9fb2, 0xb073, 0xd7f5, 0x0000, 0xd7f6, 0xd7f2, 0xb3a4,
+ 0xd7f3, 0x9fae, 0xd7f4, 0x0000, 0x9fb0, 0x0000, 0x89ad, 0xdc5f,
+ 0xdc61, 0xdc5d, 0xdc60, 0xb66f, 0xdc5e, 0xb670, 0x0000, 0x906e,
+ 0xdd73, 0xb955, 0xb954, 0x0000, 0xb953, 0x0000, 0xe0ac, 0xe0ad,
+ 0x9e71, 0x0000, 0xe473, 0xe475, 0xbbc6, 0xbbc3, 0x9e4a, 0xbbc5,
+ 0xbbc4, 0xe474, 0xe472, 0x0000, 0x9fdc, 0x0000, 0x0000, 0x0000,
+ 0xe861, 0xe85e, 0xe85f, 0xbe4d, 0xe860, 0xe85b, 0xe85c, 0xbe4a,
+ 0x0000, 0xbe4b, 0xe85d, 0xbe4c, 0x89ab, 0xebdb, 0x9fb8, 0xebdc,
+ 0xebd9, 0xebda, 0xbff4, 0xebd8, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeec8, 0xeec5, 0xeec7, 0xc1e0, 0xeecb, 0xc1df, 0xeec9,
+ 0xeecc, 0xeeca, 0xeec6, 0xc1de, 0x0000, 0xf14f, 0x0000, 0xf150,
+ 0xf14e, 0x9070, 0xf152, 0xc2e5, 0xc2e6, 0xf35f, 0xc3e7, 0xf151,
+ 0xf35e, 0xc3e6, 0xf4e5, 0xf4e6, 0xc4bf, 0xf4e4, 0x8b63, 0xf4e3,
+ 0x0000, 0xf65d, 0xc548, 0x95dc, 0xf849, 0xf8c8, 0xf8c7, 0x0000,
+ 0xc643, 0xc65d, 0xf8c9, 0xf971, 0x9071, 0xc66f, 0xa8bc, 0xaaf6,
+ 0x0000, 0xb956, 0x0000, 0xc4c0, 0xa8bd, 0xadab, 0xb3a5, 0xb671,
+ 0xc2e7, 0xaaf7, 0x0000, 0xd0c1, 0xd0c0, 0xd442, 0xfc5e, 0xb078,
+ 0xb076, 0xb07a, 0xd444, 0x0000, 0xb079, 0xb077, 0x0000, 0x8949,
+ 0x0000, 0x0000, 0xd443, 0xb3a8, 0xd7fc, 0x965b, 0xb3a7, 0xb3a9,
+ 0xd842, 0xb3ab, 0xd7fe, 0xd840, 0xd7f7, 0xb3aa, 0xd843, 0x0000,
+ 0x0000, 0xd7f9, 0x0000, 0xd7fa, 0xd7f8, 0xb3a6, 0x8c50, 0xd841,
+ 0xd7fb, 0xd7fd, 0x94a6, 0x0000, 0x0000, 0xdc6d, 0x8fd5, 0xdc6c
+};
+
+static const unsigned short big5hkscs_from_unicode_92[] = {
+ 0xdc6a, 0xdc62, 0xdc71, 0xdc65, 0xdc6f, 0xdc76, 0xdc6e, 0xb679,
+ 0x9e73, 0xb675, 0xdc63, 0x0000, 0xdc69, 0xb677, 0x9075, 0xdc68,
+ 0xb678, 0xb67a, 0xdc6b, 0x99f7, 0xb672, 0xb673, 0xdc77, 0xdc75,
+ 0x0000, 0xdc74, 0xdc66, 0x0000, 0xdc72, 0x0000, 0xb676, 0x0000,
+ 0x0000, 0x8cbf, 0x0000, 0xb674, 0xdc73, 0xdc64, 0xdc67, 0xdc70,
+ 0x99f9, 0x0000, 0x9663, 0x95b9, 0x0000, 0xe4ba, 0xe0b7, 0x0000,
+ 0xe0b0, 0xe0c3, 0xe0cc, 0xe0b3, 0xb961, 0x94d4, 0xe0c0, 0xb957,
+ 0xb959, 0xb965, 0xe0b1, 0x0000, 0xfcfa, 0xb95a, 0xb95c, 0xb966,
+ 0xb95b, 0x9077, 0x0000, 0x0000, 0x90ab, 0xb964, 0xe0b9, 0x0000,
+ 0xe0ae, 0xb962, 0xe0b8, 0xb95e, 0xe0ca, 0xb963, 0xe0c8, 0xe0bc,
+ 0xe0c6, 0xb960, 0xe0af, 0xe0c9, 0xe0c4, 0x9d4d, 0xe0cb, 0xb958,
+ 0x99fa, 0x0000, 0xb967, 0xb95d, 0x0000, 0x92e3, 0xe0b5, 0x97bb,
+ 0xe0bd, 0xe0c1, 0x9078, 0xe0c5, 0xb95f, 0xe0b4, 0xe0b2, 0xe0be,
+ 0x0000, 0x0000, 0x0000, 0x99fb, 0xe0bb, 0xe0ba, 0x97e0, 0xe0bf,
+ 0xe0c2, 0x0000, 0xe0c7, 0x0000, 0x0000, 0x0000, 0xe478, 0x96dc,
+ 0xbbc7, 0xe4a4, 0xe47a, 0xbbcc, 0xbbd0, 0xe4ad, 0xe4b5, 0xe4a6,
+ 0xbbc8, 0x9ca8, 0xe4aa, 0xe0b6, 0x9772, 0xbbc9, 0xe4b1, 0xe4b6,
+ 0xe4ae, 0x9440, 0xe4b0, 0xe4b9, 0xe4b2, 0xe47e, 0xe4a9, 0x92f2,
+ 0x0000, 0xbbd1, 0x0000, 0xbbcd, 0xe47c, 0xe4ab, 0xbbcb, 0xe4a5,
+ 0xbbca, 0xe4b3, 0xe4a2, 0xe479, 0xbbce, 0xe4b8, 0x0000, 0x0000,
+ 0xe47b, 0xe4af, 0xe4ac, 0xe4a7, 0xe477, 0xe476, 0xe4a1, 0xe4b4,
+ 0xbbcf, 0xe4b7, 0xe47d, 0xe4a3, 0xbe52, 0x0000, 0x99fd, 0x0000,
+ 0x0000, 0x99fc, 0xbe5a, 0xbe55, 0xe8a4, 0xe8a1, 0xe867, 0xbe50,
+ 0x0000, 0xf9d7, 0x964a, 0xbe4f, 0xbe56, 0x0000, 0x96d8, 0x99fe,
+ 0xe865, 0xbe54, 0xe871, 0xe863, 0xe864, 0xbe4e, 0xe8a3, 0xbe58,
+ 0xe874, 0xe879, 0xe873, 0xebee, 0xe86f, 0xe877, 0xe875, 0xe868,
+ 0xe862, 0xe87d, 0xbe57, 0xe87e, 0x904b, 0xe878, 0x0000, 0xe86d,
+ 0xe86b, 0xe866, 0x0000, 0xfa41, 0x0000, 0xe86e, 0xe87b, 0xe86a,
+ 0xe87a, 0xe8a2, 0x0000, 0x9a40, 0xbe53, 0x975b, 0xe876, 0xe87c,
+ 0xe872, 0xe86c, 0xbe51, 0x9a41, 0x91dd, 0x0000, 0xe4a8, 0xe870,
+ 0xbe59, 0xe869, 0x93fc, 0x9a42, 0x9a43, 0x0000, 0x9659, 0xebf4,
+ 0xbff7, 0xebf3, 0xebf0, 0xec44, 0xbffb, 0x9a44, 0xec41, 0xebf8
+};
+
+static const unsigned short big5hkscs_from_unicode_93[] = {
+ 0xec43, 0xebe9, 0xebf6, 0x9051, 0xbffd, 0x0000, 0xebe1, 0x94bf,
+ 0xebdf, 0xec42, 0x0000, 0xec40, 0xebfe, 0xebed, 0xebec, 0xebe2,
+ 0xc040, 0x0000, 0xebe8, 0xebf2, 0xebfd, 0xc043, 0xec45, 0x0000,
+ 0xc1e8, 0xc045, 0xbffe, 0xebe6, 0x0000, 0xebef, 0xebde, 0xebe0,
+ 0xbff5, 0xc042, 0xbffa, 0xebe7, 0xebf7, 0xebf1, 0xc041, 0xebdd,
+ 0xc1e3, 0xebf9, 0xebfc, 0xbffc, 0x90a2, 0xebeb, 0xc044, 0xbff9,
+ 0x9cab, 0x9776, 0x0000, 0xbff8, 0xebf5, 0xebfb, 0xbff6, 0x0000,
+ 0xebe4, 0xebfa, 0x0000, 0x0000, 0xebe5, 0x0000, 0x0000, 0x0000,
+ 0xfc55, 0xfe45, 0x94a8, 0x9a45, 0xfa4b, 0x9de1, 0xebea, 0xeed2,
+ 0x96d9, 0xeed7, 0xc1e5, 0xc1e7, 0xeedd, 0xc1e1, 0xeeec, 0xeee3,
+ 0xeed8, 0xeed9, 0xeee2, 0x0000, 0xc1ee, 0xeee1, 0xeed1, 0xeee0,
+ 0xeed4, 0xeeed, 0xc1ed, 0xc1eb, 0xeed5, 0x0000, 0xeee8, 0x9774,
+ 0xeeda, 0xeee7, 0xfdf5, 0xeee9, 0xeed0, 0xc1e6, 0x92e5, 0xeeea,
+ 0x9645, 0x91da, 0xeede, 0x90a3, 0xc1ea, 0xeedb, 0xa05f, 0x0000,
+ 0xc1ec, 0xeee4, 0x0000, 0x90af, 0x97bf, 0xc1e4, 0xeed6, 0xeee5,
+ 0x914c, 0xeedf, 0xebe3, 0xeee6, 0xeed3, 0x967a, 0xc1e9, 0x0000,
+ 0xeeeb, 0x91de, 0xc1e2, 0xeece, 0x9a46, 0xfeb0, 0x9779, 0x946c,
+ 0xf160, 0xf159, 0xc2e9, 0x0000, 0xf154, 0xf163, 0xf15b, 0xeedc,
+ 0x9858, 0xf165, 0xf155, 0x0000, 0xc2e8, 0xf15f, 0xc2ea, 0xc2f2,
+ 0xc2f0, 0xf161, 0xc2f1, 0xf157, 0x9266, 0xf158, 0xf15d, 0xf162,
+ 0x93fb, 0xeecd, 0xc2eb, 0xf16a, 0xf167, 0xf16b, 0xf15e, 0xf15a,
+ 0xf168, 0xf36a, 0xf15c, 0x0000, 0xc2ee, 0x9a47, 0xc2ed, 0xeecf,
+ 0xc2ef, 0xf164, 0xf166, 0xc2ec, 0xf169, 0xf153, 0x0000, 0xf156,
+ 0x9749, 0x0000, 0x0000, 0x9748, 0x0000, 0x934a, 0x0000, 0x9ce2,
+ 0xf373, 0x0000, 0xf363, 0xc3eb, 0xf371, 0x0000, 0x9264, 0xf361,
+ 0xc3ec, 0x0000, 0xf36c, 0x91df, 0xf368, 0xc3f1, 0xf372, 0xf362,
+ 0xf365, 0xc3e9, 0xf374, 0xfb79, 0xf36d, 0xf370, 0xc3ef, 0xc3f4,
+ 0xc3f2, 0xf369, 0xf364, 0x96d7, 0xc3ed, 0xc3ee, 0xf360, 0xc3ea,
+ 0x9343, 0xc3e8, 0xc3f0, 0xf36f, 0xc3f3, 0x0000, 0xf36b, 0xf375,
+ 0xc3f5, 0x0000, 0x0000, 0x0000, 0xf367, 0x0000, 0xf36e, 0x0000,
+ 0xfdcb, 0xfe7a, 0x0000, 0x91db, 0x8c6a, 0xf4f3, 0xf542, 0xf4f5,
+ 0xf4fc, 0xf366, 0xf4fa, 0xf4e9, 0xf540, 0xc4c3, 0xf4ed, 0xf4fe
+};
+
+static const unsigned short big5hkscs_from_unicode_94[] = {
+ 0xf4f4, 0x97af, 0x0000, 0xc4c2, 0x95dd, 0x0000, 0xf544, 0xf4f6,
+ 0x9348, 0xf4fb, 0xf4fd, 0xf4e7, 0xf541, 0xf4f2, 0xf4f7, 0xf4eb,
+ 0xf4ef, 0xf543, 0xf4f9, 0xf4e8, 0xf4ec, 0xf4ee, 0xf4f8, 0x9a4b,
+ 0xc4c1, 0xf4f1, 0x0000, 0xfc45, 0x0000, 0x9a4d, 0x0000, 0x0000,
+ 0xf4ea, 0x0000, 0x0000, 0x0000, 0x91bc, 0x90e2, 0x90b4, 0x95e1,
+ 0xf4f0, 0xf661, 0xf666, 0xc54f, 0xf668, 0x9a4e, 0xc549, 0x0000,
+ 0xf664, 0xf66a, 0xc54e, 0xc54a, 0x0000, 0xc54b, 0xf660, 0xf667,
+ 0xc54d, 0xf665, 0xc54c, 0xf65f, 0xf663, 0xf662, 0x9a4f, 0xf65e,
+ 0xf669, 0x0000, 0xfe40, 0xfe43, 0xc5b1, 0xf76d, 0xf770, 0xf76c,
+ 0xf76e, 0xf76f, 0xf769, 0xf76a, 0xf767, 0x96dd, 0x0000, 0xf76b,
+ 0xf768, 0xc5b2, 0xc5b3, 0x0000, 0x9a51, 0xf84b, 0x0000, 0xf84d,
+ 0x96a7, 0x0000, 0x0000, 0x90b0, 0x0000, 0xf84c, 0xf84e, 0x0000,
+ 0xc5e0, 0x0000, 0xf84a, 0xc5df, 0xc5e1, 0x9c4e, 0x0000, 0x9443,
+ 0xf8cb, 0xf8cc, 0xc644, 0xf8ca, 0x8eba, 0xf953, 0xf952, 0xf954,
+ 0xc65f, 0xf955, 0xc65e, 0xf956, 0xf972, 0xf975, 0xf974, 0xc668,
+ 0xf973, 0x9a52, 0x0000, 0xfcc1, 0xc672, 0xc670, 0xc671, 0xc677,
+ 0xf9c0, 0xf9c1, 0xf9bf, 0xf9c9, 0x0000, 0x8be9, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9caf,
+ 0x0000, 0x0000, 0x8bfd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9abc, 0x0000, 0x9ab8, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9aae, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9aa7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_95[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9a53, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9d74,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xaaf8,
+ 0x8bea, 0x0000, 0xd844, 0xdc78, 0xe8a5, 0xf376, 0x0000, 0x8beb,
+ 0xaaf9, 0x0000, 0xadac, 0xb07b, 0x0000, 0x90b2, 0xd845, 0x0000,
+ 0xd846, 0xb3ac, 0x0000, 0xb67d, 0xdc7a, 0xdc79, 0xb6a3, 0xb67c,
+ 0xdc7b, 0xb67e, 0xb6a2, 0xb6a1, 0xb67b, 0x0000, 0x95e9, 0x95e8,
+ 0xb968, 0x95e6, 0x0000, 0xe0d0, 0xe0ce, 0x0000, 0xe0cf, 0xe0cd,
+ 0x90b5, 0xbbd2, 0x9a54, 0xbbd5, 0xbbd7, 0xbbd6, 0x90b3, 0x95e7,
+ 0xbbd3, 0xbbd4, 0x8b50, 0xe8a7, 0xe8a6, 0xbe5b, 0xe8a8, 0x0000,
+ 0xe8a9, 0xbe5c, 0x0000, 0x0000, 0x0000, 0xec4d, 0xec4b, 0xeef3,
+ 0x0000, 0xec49, 0xec4a, 0xc046, 0xec46, 0xec4e, 0xec48, 0xec4c,
+ 0xeeef, 0x0000, 0x0000, 0xeef1, 0x0000, 0xeef2, 0xc1f3, 0xeeee,
+ 0xc1f2, 0xeef0, 0xc1ef, 0xc1f0, 0xc1f1, 0xec47, 0x0000, 0x0000,
+ 0xc2f5, 0xf16e, 0xf16c, 0xf16d, 0xc2f3, 0xc2f6, 0xc2f4, 0x0000,
+ 0x0000, 0x0000, 0xf377, 0xf378, 0xc3f6, 0x0000, 0xf545, 0xf547,
+ 0xf546, 0xc4c4, 0xc550, 0xf66d, 0xf66c, 0xf66b, 0x0000, 0x0000,
+ 0x8bec, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9a56, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_96[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xaafa, 0x8bfb, 0xc9aa, 0x0000,
+ 0xca58, 0xa6e9, 0xca56, 0xca59, 0xca57, 0x0000, 0x0000, 0x0000,
+ 0xcbae, 0x0000, 0xa8c1, 0x0000, 0xa8c2, 0xcbb0, 0xa8bf, 0xcbaf,
+ 0xcbad, 0xa8c0, 0xa8be, 0x9a57, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa0aa, 0xcdd8, 0xcddb, 0xaafd, 0xcdda, 0xcdd9, 0x0000, 0xaafc,
+ 0xaafb, 0x9fa6, 0xab40, 0xcddc, 0xaafe, 0x99cc, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd0c6, 0xadae, 0xadaf, 0xadb0, 0xd0c7, 0xd0c3,
+ 0xadad, 0xd0c4, 0x0000, 0xd0c5, 0xd0c2, 0x0000, 0x9c59, 0x0000,
+ 0xb0a4, 0x0000, 0x0000, 0xb0a1, 0xd445, 0xb0a2, 0xb0a5, 0xd446,
+ 0x0000, 0xb07e, 0xb07c, 0xb07d, 0xb0a3, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x99b5, 0xb3ad, 0xd849, 0xb3b5, 0xd848, 0x0000, 0xd84b,
+ 0xb3b1, 0xd84a, 0xb6ab, 0xb3af, 0xb3b2, 0xb3ae, 0xb3b3, 0xb3b4,
+ 0xb3b0, 0x0000, 0x0000, 0x90be, 0xd847, 0xb6a7, 0xdc7d, 0x0000,
+ 0xdca3, 0x9faf, 0x0000, 0xdca2, 0xb6ac, 0xb6a8, 0xb6a9, 0xdc7c,
+ 0xdc7e, 0xdca1, 0xb6a4, 0xb6a6, 0x0000, 0xb6aa, 0xb6a5, 0x95f2,
+ 0x0000, 0xe0d3, 0xe0d1, 0xe0d2, 0xb96a, 0xb96b, 0x90bf, 0xe0d4,
+ 0xb969, 0xbbd8, 0x0000, 0xbbda, 0xbbd9, 0x0000, 0xe4bb, 0x0000,
+ 0x0000, 0xe4bc, 0xe8ab, 0x90c1, 0xe8aa, 0xfee4, 0x0000, 0xc047,
+ 0xc048, 0xec4f, 0xc049, 0x0000, 0xeef6, 0x0000, 0xeef4, 0x0000,
+ 0xeef5, 0xc1f4, 0x0000, 0xf16f, 0xc3f7, 0x0000, 0x90c4, 0x0000,
+ 0xc1f5, 0xab41, 0x0000, 0xb0a6, 0xd447, 0x90c7, 0x0000, 0xd84c,
+ 0xb3b6, 0xb6ad, 0xdca4, 0xdca6, 0xb6af, 0xb6ae, 0xb6b0, 0xb6b1,
+ 0xdca5, 0xb96e, 0xb96f, 0xb96d, 0xbbdb, 0xb96c, 0xe0d5, 0x0000,
+ 0x0000, 0x0000, 0xbbdc, 0xe8ac, 0xec50, 0xc04a, 0xc1f6, 0xf170,
+ 0xf174, 0xc2f9, 0xf171, 0xc2fa, 0xc2f8, 0xf175, 0xc2fb, 0xf173,
+ 0x0000, 0xf379, 0xc2f7, 0xc3f8, 0x0000, 0xf8cd, 0x0000, 0x0000,
+ 0xab42, 0xb3b8, 0xb3b7, 0x0000, 0x0000, 0x0000, 0x0000, 0xb6b2,
+ 0xdca8, 0xdca7, 0xb6b3, 0x0000, 0x92e4, 0xe0d9, 0xb973, 0xb970,
+ 0xe0d8, 0xb972, 0xe0d6, 0xb971, 0x0000, 0xe0d7, 0x0000, 0xe4bd
+};
+
+static const unsigned short big5hkscs_from_unicode_97[] = {
+ 0xbbdd, 0x0000, 0xe8af, 0x9f52, 0xbe5d, 0xe8ad, 0xbe5e, 0xbe5f,
+ 0xe8ae, 0xbe60, 0x0000, 0xec51, 0x0000, 0xc04e, 0xc04b, 0xc050,
+ 0xec53, 0xc04c, 0xec52, 0xc04f, 0x0000, 0x0000, 0xc04d, 0x0000,
+ 0xeef9, 0xeefb, 0x0000, 0x90db, 0xc1f7, 0xeefa, 0xc1f8, 0xeef8,
+ 0xeef7, 0xa066, 0xf177, 0xf176, 0xc2fc, 0xf178, 0xf37e, 0xc3fa,
+ 0xf37d, 0xf37a, 0xc3f9, 0xf37b, 0xf37c, 0x0000, 0xf548, 0xf549,
+ 0xc4c5, 0x90d2, 0xc553, 0x0000, 0x0000, 0xf66e, 0x90d4, 0x0000,
+ 0xc551, 0xc552, 0xf66f, 0x0000, 0x0000, 0xc5b4, 0xc5b5, 0xf771,
+ 0x9a5b, 0x95fd, 0xc645, 0xf8cf, 0xc647, 0x0000, 0xf8ce, 0xf8d0,
+ 0xc646, 0xf957, 0x0000, 0xf9ad, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8bc4, 0xab43, 0x0000, 0x0000, 0x8c66, 0xb974, 0x90de,
+ 0xe4be, 0x0000, 0xe8b0, 0xc051, 0xc052, 0x9ce4, 0xab44, 0x90e1,
+ 0xbe61, 0xc3fb, 0xadb1, 0x0000, 0x0000, 0x0000, 0xc053, 0x0000,
+ 0xc5e2, 0xadb2, 0xd84d, 0x0000, 0xdca9, 0x9e46, 0xdcab, 0x0000,
+ 0xdcaa, 0x9651, 0xe0dd, 0xe0da, 0xb975, 0x0000, 0xb976, 0xe0db,
+ 0xe0dc, 0x0000, 0xe4c0, 0xe4c5, 0xbbde, 0xe4bf, 0xe4c1, 0xe4c8,
+ 0xe4c3, 0xe4c7, 0xe4c4, 0xe4c2, 0xe4c6, 0xbbdf, 0x0000, 0xfb58,
+ 0xe8b3, 0x90e6, 0xe8b1, 0xbe63, 0x0000, 0xbe62, 0xe8b2, 0xbe64,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xec56, 0x0000, 0x0000, 0xec55,
+ 0xc054, 0xec54, 0xeefc, 0x9650, 0xeefe, 0xef41, 0xef40, 0x90e7,
+ 0xc1f9, 0xeefd, 0xf1a1, 0xc2fd, 0xf17d, 0xf1a2, 0xc2fe, 0x0000,
+ 0xf17b, 0x0000, 0xf17e, 0xf17c, 0xf179, 0xc340, 0xf17a, 0x0000,
+ 0x0000, 0x90e8, 0x9a5d, 0xf3a1, 0x9f7a, 0x0000, 0xf3a3, 0xf3a2,
+ 0x9b5c, 0xf54a, 0x9f7c, 0xf54b, 0x0000, 0xfc52, 0x90e9, 0xf670,
+ 0x90ea, 0xc5b7, 0x9a5e, 0xc5b6, 0xf84f, 0xf850, 0xc648, 0xf8d1,
+ 0x9f76, 0xc669, 0x0000, 0xadb3, 0xb6b4, 0xe4ca, 0xe4c9, 0xe8b5,
+ 0xe8b4, 0x0000, 0x90eb, 0xc1fa, 0xef43, 0xef42, 0xf1a5, 0xf1a3,
+ 0xf1a6, 0xf1a4, 0x0000, 0x0000, 0xc3fc, 0xf3a4, 0xf3a5, 0xf3a6,
+ 0x90ec, 0xf671, 0x0000, 0xf772, 0x0000, 0xf8d2, 0x8bee, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xadb4, 0x90ee, 0x0000,
+ 0xec57, 0xef44, 0x91c6, 0xadb5, 0x0000, 0x90f2, 0xbbe0, 0x0000,
+ 0xec58, 0xc341, 0xf1a7, 0xc3fd, 0x0000, 0xf54c, 0xf54d, 0xc554
+};
+
+static const unsigned short big5hkscs_from_unicode_98[] = {
+ 0xf851, 0xadb6, 0xb3bb, 0xb3bc, 0xd84e, 0xb6b5, 0xb6b6, 0xdcac,
+ 0xb6b7, 0x0000, 0xb97a, 0x0000, 0xb97c, 0xe0df, 0xe0e0, 0xe0de,
+ 0xb977, 0xb978, 0xb97b, 0xb979, 0xfcbc, 0x8a74, 0xe4cb, 0xbbe1,
+ 0xbbe2, 0x0000, 0x0000, 0xe8bc, 0xbe67, 0xe8b7, 0xe8b6, 0x9657,
+ 0xe8bb, 0xbe65, 0x0000, 0x9cef, 0xc05b, 0x0000, 0xe8b8, 0xe8bd,
+ 0xe8ba, 0xe8b9, 0x0000, 0xbe66, 0x0000, 0xc059, 0x9fdf, 0xec5a,
+ 0xc055, 0x0000, 0xec5b, 0x90f7, 0x90f6, 0xec59, 0x0000, 0xc058,
+ 0xc056, 0xc05a, 0x0000, 0xc057, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xef45, 0x0000, 0xef4a, 0xef46, 0xef49, 0xc1fb, 0x9b5e,
+ 0xedd4, 0xef48, 0xef47, 0x90f8, 0xc344, 0xc342, 0xc345, 0xc343,
+ 0xf1a8, 0xf1a9, 0xf1aa, 0xc346, 0x0000, 0x0000, 0x0000, 0xf3aa,
+ 0xc440, 0xf3a8, 0x0000, 0xc441, 0xf3a7, 0xf3a9, 0xc3fe, 0xf551,
+ 0xf54e, 0x0000, 0xf54f, 0xf550, 0xf672, 0xc556, 0x90f9, 0xc555,
+ 0x8cc9, 0xf774, 0xf773, 0xc5b8, 0xfa6a, 0x0000, 0x0000, 0xc5e3,
+ 0xc649, 0xc660, 0xf958, 0xf9ae, 0xf9af, 0x8bef, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xadb7, 0xdcad, 0x0000, 0x0000, 0xe0e1, 0xe4cc, 0xe4cd, 0xbbe3,
+ 0x0000, 0xbbe4, 0xe8be, 0xbe68, 0x9fe0, 0x0000, 0xc1fc, 0x9142,
+ 0xf1ab, 0x9a62, 0xc347, 0xf3ad, 0xc442, 0xf3ac, 0xf3ae, 0xf3ab,
+ 0xf675, 0xf552, 0xf553, 0x9569, 0xc4c6, 0x0000, 0xf674, 0x9144,
+ 0x9143, 0xf673, 0x9141, 0xf775, 0xf9b0, 0x0000, 0x8bf0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xadb8, 0x9660, 0x0000, 0x8bf1, 0xadb9,
+ 0x99f6, 0x9149, 0xb0a7, 0xd448, 0x0000, 0xd84f, 0x914a, 0xb6b8,
+ 0x0000, 0xb6bb, 0xb6b9, 0xdcae, 0x914b, 0xb6bd, 0x0000, 0xb6ba,
+ 0x0000, 0x9a64, 0xb6bc, 0x0000, 0xb97e, 0x8abf, 0xe0e2, 0x0000,
+ 0x0000, 0xe0e3, 0xe8c0, 0x0000, 0xb97d, 0xb9a1, 0xb9a2, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_99[] = {
+ 0xe4cf, 0x0000, 0xe4ce, 0xbbe5, 0x0000, 0xbbe6, 0x0000, 0xe4d0,
+ 0xe8bf, 0xbbe8, 0xbe69, 0x0000, 0xbbe7, 0x0000, 0x9a66, 0x0000,
+ 0xc05c, 0xe8c1, 0xbe6b, 0xbe6a, 0xe8c2, 0xe8c5, 0xe8c3, 0xe8c4,
+ 0xbe6c, 0x9a67, 0xc061, 0xc05f, 0x9a69, 0x0000, 0xc05e, 0xec5d,
+ 0x0000, 0xc060, 0x0000, 0x0000, 0xec5c, 0xef4b, 0x0000, 0xec5e,
+ 0xc05d, 0xec5f, 0xef4e, 0xef4c, 0xef4d, 0xef52, 0xc34b, 0xef51,
+ 0xef54, 0xef53, 0xef50, 0xef4f, 0x0000, 0xc1fd, 0x0000, 0x9a6a,
+ 0x9652, 0x914d, 0xf1ae, 0x9666, 0xf1ad, 0xc34a, 0xc348, 0xc349,
+ 0x9f7b, 0xf1ac, 0x9a6b, 0xf3b1, 0x0000, 0xc443, 0x0000, 0xf3b0,
+ 0xf3af, 0xc444, 0xa06c, 0xf558, 0xf557, 0x9667, 0xf555, 0x0000,
+ 0xf554, 0xc4c8, 0xc4c7, 0xf559, 0xf776, 0xc5b9, 0xf677, 0xc557,
+ 0xf676, 0xf556, 0x0000, 0xf777, 0xc5e4, 0x9a6c, 0xc661, 0xf959,
+ 0x0000, 0xf9b1, 0x9a6d, 0x8bf2, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xadba, 0xd850,
+ 0xef55, 0xadbb, 0x0000, 0x966a, 0xe4d2, 0xe4d1, 0xec60, 0x0000,
+ 0x0000, 0xef57, 0x0000, 0xef56, 0xfcea, 0xc34c, 0xf3b2, 0xf3b3,
+ 0xc4c9, 0x0000, 0x966c, 0xf9b2, 0xb0a8, 0xb6bf, 0xb6be, 0xe0e4,
+ 0xe0e6, 0xb9a4, 0xe0e5, 0xb9a3, 0xb9a5, 0xe0e7, 0x0000, 0x0000,
+ 0x91c4, 0xe4d4, 0xe4d6, 0xe4d5, 0x9677, 0xe4d8, 0x0000, 0x0000,
+ 0x0000, 0xbbe9, 0xe4d7, 0xe4d3, 0x99f4, 0x9a6f, 0x0000, 0xe4d9,
+ 0x0000, 0xe8cc, 0x0000, 0xe8cf, 0xe8d1, 0xe8c7, 0xe8cb, 0xe8c8,
+ 0xbe6e, 0xbe71, 0xbe73, 0xe8c9, 0xe8ca, 0xbe72, 0xe8cd, 0xe8d0,
+ 0xe8ce, 0xbe74, 0x9fab, 0xbe70, 0xe8c6, 0xbe6d, 0x0000, 0xbe6f,
+ 0x8cbe, 0x8ec1, 0xc063, 0xec66, 0xec64, 0xec63, 0x9555, 0xec69,
+ 0x0000, 0xec68, 0xec67, 0x0000, 0xec62, 0xc062, 0xec61, 0x0000,
+ 0xec65, 0xc064, 0x0000, 0x0000, 0xef5a, 0x9152, 0xef5e, 0xef5b,
+ 0xef5d, 0xef5c, 0xef59, 0xef5f, 0xef62, 0xef60, 0xef61, 0xc240
+};
+
+static const unsigned short big5hkscs_from_unicode_9a[] = {
+ 0x0000, 0xc1fe, 0xef58, 0xef63, 0xf1b3, 0xf1b6, 0xf1b8, 0xf1b7,
+ 0x0000, 0xf1b1, 0xf1b5, 0xf1b0, 0x9153, 0xf1b2, 0xc34d, 0xf1af,
+ 0x9155, 0xf1b4, 0x0000, 0x0000, 0xf3c0, 0xf3b5, 0xc445, 0x0000,
+ 0x0000, 0xc446, 0xf3b4, 0xf3b9, 0xf3bf, 0xf3b7, 0xf3be, 0x955d,
+ 0xf3bb, 0x9671, 0xf3ba, 0xf3bd, 0xf3b8, 0xf3b6, 0x9c6d, 0xf3bc,
+ 0x0000, 0xf560, 0xf55e, 0xc4ca, 0xf55d, 0xf563, 0xf561, 0x9673,
+ 0xc4cb, 0xf55c, 0xf55a, 0x0000, 0xf55b, 0xc4cd, 0xf55f, 0xc4cc,
+ 0xf562, 0xf678, 0xf67e, 0x9154, 0x9a71, 0xf679, 0xc55b, 0xf6a1,
+ 0xc55a, 0xf67d, 0xf67c, 0xc559, 0xf67b, 0xc558, 0xf67a, 0x0000,
+ 0xf77d, 0xf7a1, 0xf77e, 0x0000, 0xf77b, 0xc5bb, 0xf778, 0xf77c,
+ 0xf7a3, 0x0000, 0xf7a2, 0xf779, 0xf77a, 0xc5ba, 0xf852, 0xc5e7,
+ 0x9156, 0xf853, 0xc5e5, 0xc5e6, 0x966d, 0x0000, 0xf8d3, 0xc64a,
+ 0xf976, 0x0000, 0xc66a, 0x9557, 0xf9b3, 0xc66b, 0xf9b4, 0xf9b5,
+ 0xf9c3, 0xf9c2, 0xc67a, 0xf9cd, 0x89c6, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x89c7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xb0a9, 0x0000, 0x0000, 0xe0e9, 0x0000, 0xe0e8, 0x0000, 0xbbea,
+ 0xbbeb, 0xe4da, 0x8a6a, 0xe8d2, 0xec6c, 0x0000, 0x8b57, 0xbe75,
+ 0xc065, 0xec6a, 0x9fe1, 0xec6d, 0xc066, 0x9b5f, 0xef64, 0xec6b,
+ 0xf1b9, 0xc34e, 0xf3c1, 0x0000, 0x0000, 0x0000, 0xf566, 0xf564,
+ 0x0000, 0x0000, 0xf565, 0x0000, 0x0000, 0xf6a2, 0x0000, 0xc55c,
+ 0xf7a4, 0xc5ea, 0xc5bc, 0xc5e8, 0xc5e9, 0xf8d4, 0xc662, 0xa05d,
+ 0xb0aa, 0x0000, 0x0000, 0x0000, 0xf1ba, 0x0000, 0x0000, 0xd449,
+ 0x915b, 0xb9a6, 0x915c, 0xe4db, 0x0000, 0x0000, 0xbbec, 0xe4dc,
+ 0x0000, 0x0000, 0x0000, 0xe8d4, 0xe8d3, 0xc068, 0xbe76, 0xbe77,
+ 0x0000, 0xe8d7, 0xe8d6, 0xe8d5, 0x915e, 0x0000, 0xec6e, 0xec71,
+ 0x0000, 0xec70, 0xec6f, 0xc067, 0xef68, 0xef66, 0xef65, 0x9f5c
+};
+
+static const unsigned short big5hkscs_from_unicode_9b[] = {
+ 0x0000, 0xef67, 0x9f57, 0xc34f, 0xf1bc, 0xf1bd, 0xc350, 0x0000,
+ 0xf1bb, 0x9f65, 0xf3c3, 0xf3c2, 0xf3c5, 0xc447, 0xf3c4, 0x9a72,
+ 0xf567, 0xf569, 0xf568, 0x0000, 0x9160, 0xf6a3, 0xf6a6, 0xf6a4,
+ 0xf6a5, 0xf7a5, 0xc5bd, 0x0000, 0x0000, 0x0000, 0xf854, 0xf855,
+ 0xf856, 0x0000, 0xc64b, 0xc663, 0xf9b6, 0xb0ab, 0x0000, 0xbe78,
+ 0xc069, 0xf1be, 0x9f5e, 0xf7a6, 0x0000, 0x9161, 0xf9c4, 0xd44a,
+ 0x0000, 0xc67b, 0xb0ac, 0xec72, 0x9164, 0xf1bf, 0x0000, 0xf3c6,
+ 0x0000, 0x9f41, 0xf6a7, 0xf7a7, 0xb0ad, 0x0000, 0xe4dd, 0xe4de,
+ 0x9169, 0xbbed, 0xbbee, 0xe8d9, 0xbe7a, 0xbe79, 0xe8d8, 0x0000,
+ 0xef69, 0x0000, 0xf1c0, 0xf1c2, 0xf1c1, 0xc353, 0xc352, 0xc351,
+ 0x9168, 0xc55e, 0xf6a8, 0x0000, 0xc55d, 0xf7a9, 0xf7a8, 0x0000,
+ 0xc64c, 0xf8d5, 0xb3bd, 0xe0ea, 0x0000, 0x0000, 0x0000, 0xe4e1,
+ 0xe4df, 0xe4e0, 0x0000, 0x0000, 0xe8e2, 0x0000, 0xe8dd, 0xe8da,
+ 0xe8e1, 0x9a74, 0x0000, 0x0000, 0xe8e3, 0x0000, 0x0000, 0xbe7c,
+ 0xe8e0, 0xe8dc, 0x0000, 0x0000, 0xe8db, 0xe8df, 0xe8de, 0xbe7b,
+ 0x0000, 0x0000, 0xec7d, 0xec78, 0xec76, 0xeca1, 0xec77, 0x96b2,
+ 0xec73, 0x9a75, 0xec79, 0xfda5, 0x0000, 0xec74, 0xef72, 0xec75,
+ 0xeca2, 0x0000, 0x0000, 0x9ee9, 0x0000, 0x8bba, 0x916d, 0xa060,
+ 0xec7c, 0xc06a, 0xec7b, 0xec7a, 0x0000, 0xec7e, 0x0000, 0x9fde,
+ 0x0000, 0x0000, 0xef6a, 0xef6d, 0x0000, 0x9fc3, 0xef6c, 0x96b5,
+ 0xef74, 0xef6f, 0xef73, 0x0000, 0xef71, 0xef70, 0xef6e, 0x0000,
+ 0xef6b, 0x0000, 0xc243, 0xc242, 0x0000, 0xc244, 0xc241, 0xef75,
+ 0xa067, 0x0000, 0x0000, 0x0000, 0x0000, 0xf1c8, 0xf1cb, 0x0000,
+ 0xf1c9, 0xf1cd, 0x0000, 0x0000, 0x0000, 0xf1ce, 0x0000, 0xf1c6,
+ 0xc358, 0xf1c7, 0x0000, 0xf1c5, 0xf1cc, 0x0000, 0xf1c4, 0xf1c3,
+ 0xc357, 0xc355, 0xc354, 0x0000, 0x0000, 0x0000, 0x0000, 0x96b3,
+ 0x0000, 0x0000, 0x0000, 0xf1ca, 0xf3cf, 0xf3d5, 0xc44a, 0xf3d0,
+ 0x0000, 0xf3d3, 0xf3d7, 0xc44b, 0xf3d2, 0x9a76, 0xf3ca, 0x0000,
+ 0xf3c9, 0xf3d6, 0xf3cd, 0x0000, 0xf3cb, 0xf3d4, 0xf3cc, 0xc449,
+ 0xc448, 0x95d5, 0xf3c7, 0xf3c8, 0xf3d1, 0x9eca, 0x0000, 0x0000,
+ 0xf3ce, 0x9a77, 0x0000, 0x0000, 0x9a78, 0x0000, 0x0000, 0xf56c,
+ 0xf56f, 0x0000, 0x0000, 0x0000, 0x0000, 0xc356, 0x0000, 0x9170
+};
+
+static const unsigned short big5hkscs_from_unicode_9c[] = {
+ 0x0000, 0x0000, 0x916f, 0x0000, 0x0000, 0xf56d, 0xf573, 0xf571,
+ 0xf56b, 0xf576, 0x9fa3, 0xf56a, 0x9171, 0xc4cf, 0xf572, 0x0000,
+ 0x96b1, 0x0000, 0xf56e, 0xc4ce, 0xf575, 0x9f63, 0x0000, 0xf574,
+ 0x0000, 0x0000, 0x0000, 0x9f67, 0xf6ab, 0xf6aa, 0x0000, 0x8bb9,
+ 0x9a7a, 0xf6b1, 0x0000, 0xf6ad, 0xf6b0, 0xc560, 0x8b56, 0x0000,
+ 0xf6ae, 0xf6af, 0x0000, 0xf6a9, 0xf6ac, 0xc55f, 0x0000, 0x9ada,
+ 0x0000, 0xc5bf, 0xf7b4, 0xf7af, 0xf7b3, 0x96b0, 0xf7b6, 0xf7b2,
+ 0x0000, 0xf7ae, 0x9a7e, 0xc5c1, 0xf7b1, 0xf7b5, 0xc5c0, 0xf7ac,
+ 0xf570, 0xf7b0, 0x0000, 0x0000, 0xf7ad, 0x9dde, 0xf7aa, 0x0000,
+ 0xf7ab, 0xc5be, 0xf85a, 0xf85c, 0xf85f, 0xf85b, 0xf860, 0x96ad,
+ 0xf859, 0x0000, 0xf857, 0x96ae, 0xc5eb, 0xf85d, 0xc5ed, 0xc5ec,
+ 0xf858, 0xf85e, 0x0000, 0x0000, 0x0000, 0x9ea1, 0xf8da, 0xc64d,
+ 0xf8db, 0x0000, 0xf8d9, 0xf8d6, 0x0000, 0x0000, 0xf8d8, 0xf8d7,
+ 0xf95a, 0x0000, 0x0000, 0x0000, 0x0000, 0xf95c, 0xf95b, 0x0000,
+ 0x0000, 0xf979, 0x9e50, 0xf978, 0xf977, 0xf97a, 0x0000, 0xc673,
+ 0xc674, 0xf9ca, 0xf9ce, 0x96af, 0x8bf4, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb3be, 0xdcaf, 0xe0ed,
+ 0x0000, 0xb9a7, 0xe0eb, 0x0000, 0x0000, 0xe0ec, 0x0000, 0x0000,
+ 0x0000, 0xe4e2, 0xe4e3, 0xbbf1, 0xbbef, 0xe4e4, 0xbbf0, 0xe8e8,
+ 0x0000, 0xe8eb, 0xe8e5, 0xe8ec, 0xe8e4, 0xe8e6, 0x0000, 0xe8e7
+};
+
+static const unsigned short big5hkscs_from_unicode_9d[] = {
+ 0xe8ea, 0x0000, 0x9fa4, 0xbea1, 0xe8ef, 0xe8ee, 0xbe7d, 0xe8e9,
+ 0xe8ed, 0xbe7e, 0x0000, 0x0000, 0x96bd, 0x0000, 0x0000, 0x0000,
+ 0xecac, 0x0000, 0xc06f, 0x0000, 0xeca7, 0xc06b, 0x96f4, 0xeca4,
+ 0xecaa, 0xecad, 0x0000, 0xc070, 0x0000, 0xeca9, 0xeca6, 0xecae,
+ 0xeca5, 0x96b8, 0xecab, 0xc06c, 0x0000, 0xeca3, 0xc06d, 0x0000,
+ 0xc06e, 0xeca8, 0x0000, 0x0000, 0x0000, 0xefa9, 0xef7a, 0xef7b,
+ 0xef7e, 0xef7c, 0x0000, 0xef76, 0xfaa1, 0x0000, 0xef79, 0xefa5,
+ 0xef7d, 0x91a7, 0x0000, 0xc245, 0x0000, 0xefa7, 0xefa4, 0xc246,
+ 0xefa6, 0xef77, 0xefa2, 0xefa3, 0xa05e, 0xefa1, 0x0000, 0x0000,
+ 0x0000, 0x9a7d, 0xf1d2, 0xf1d4, 0xf1d7, 0x0000, 0x8948, 0xf1d1,
+ 0x9eb1, 0xc359, 0xf1d9, 0xf1d0, 0xf1da, 0x0000, 0xf1d6, 0xf1d8,
+ 0xf1dc, 0xf1d5, 0xf1dd, 0xf1d3, 0xf1cf, 0xc35a, 0x9ddb, 0xf1db,
+ 0xc35b, 0xc44d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xef78,
+ 0xf3f1, 0xf3e8, 0xc44f, 0xf3e4, 0xc450, 0x95bf, 0x8a73, 0xf3ed,
+ 0xf3e7, 0xf3dd, 0xc44e, 0xf3ea, 0xf3e5, 0xf3e6, 0x0000, 0xf3d8,
+ 0xf3df, 0xf3ee, 0x0000, 0xf3eb, 0x9efe, 0xf3e3, 0x917a, 0xf3ef,
+ 0xf3de, 0xf3d9, 0xf3ec, 0x917b, 0xf3db, 0xf3e9, 0xf3e0, 0xf3f0,
+ 0xf3dc, 0xc44c, 0xf3da, 0xf3e1, 0xf3e2, 0x0000, 0x0000, 0x0000,
+ 0xf57d, 0x0000, 0xf57b, 0x9aa3, 0xf5a2, 0x0000, 0xf5ae, 0xf5a5,
+ 0xf57c, 0xf578, 0xf5a7, 0xf57e, 0xf5a3, 0xf57a, 0xf5aa, 0xf577,
+ 0xf5a1, 0xf5a6, 0xf5a8, 0xf5ab, 0xf579, 0x96c2, 0xf5af, 0xf5b0,
+ 0xf5a9, 0xf5ad, 0xf5a4, 0x9f77, 0xf6c1, 0xf6c4, 0x0000, 0xc561,
+ 0x0000, 0xf6c3, 0xf6c8, 0xf6c6, 0xc562, 0xf6bd, 0xf6b3, 0xf6b2,
+ 0xc564, 0xf6bf, 0xf6c0, 0xf6bc, 0xf6b4, 0x9aa4, 0xf6b9, 0xf5ac,
+ 0x9aa5, 0xf6b5, 0xc563, 0xf6bb, 0x91a1, 0xf6ba, 0x0000, 0xf6b6,
+ 0xf6c2, 0x89b8, 0xf6b7, 0xf7bb, 0xf6c5, 0xf6c7, 0xf6be, 0xf6b8,
+ 0xf7bc, 0xf7be, 0xf7b8, 0xc5c2, 0x9173, 0xf7c5, 0xf7c3, 0xc5c3,
+ 0xf7c2, 0xf7c1, 0xf7ba, 0xf7b7, 0xf7bd, 0xf7c6, 0xf7b9, 0xf7bf,
+ 0x0000, 0xf869, 0xf86e, 0xf864, 0xf867, 0xc5ee, 0xf86b, 0x0000,
+ 0xf872, 0xf7c0, 0x0000, 0xf865, 0xf86f, 0xf873, 0xf86a, 0xf863,
+ 0xf86d, 0x0000, 0xf86c, 0xf871, 0xf870, 0xf7c4, 0xf868, 0xf862,
+ 0xf866, 0xc64e, 0xc64f, 0xf861, 0x9aa6, 0xf8e6, 0xf8dd, 0xf8e5
+};
+
+static const unsigned short big5hkscs_from_unicode_9e[] = {
+ 0xf8e2, 0xf8e3, 0xf8dc, 0xf8df, 0xf8e7, 0xf8e1, 0xf8e0, 0xf8de,
+ 0x0000, 0xf8e4, 0x89bd, 0xf95d, 0x89b9, 0xf95e, 0x917d, 0xf960,
+ 0xf95f, 0xf962, 0xf961, 0xf97c, 0xf97b, 0xf9b7, 0x0000, 0xf9b8,
+ 0x96bb, 0xf9c5, 0xc678, 0xc67c, 0x9ff2, 0xf9cf, 0xc67d, 0x8bf5,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb3bf, 0x0000, 0x0000,
+ 0x0000, 0xc4d0, 0xf6c9, 0x9aa9, 0xc650, 0xc651, 0x0000, 0xb3c0,
+ 0xe0ee, 0x9f54, 0xb9a8, 0xe8f0, 0x9fe3, 0x9eed, 0xecb0, 0xecb1,
+ 0xecaf, 0xefab, 0xefaa, 0xc247, 0xf1df, 0xefac, 0xf1de, 0x0000,
+ 0x91aa, 0xf3f3, 0xc451, 0xc453, 0xf3f2, 0x91ab, 0xa070, 0xc452,
+ 0x9f6d, 0xf5b1, 0xf5b3, 0xf5b2, 0xf6ca, 0xc565, 0x91ac, 0xc5ef,
+ 0xf8e8, 0xf963, 0x91ad, 0x0000, 0xf9d2, 0xb3c1, 0xa0fd, 0xe4e5,
+ 0x9fe2, 0xbea2, 0x91af, 0x9e41, 0x9aaa, 0xecb3, 0xecb2, 0x91b0,
+ 0xefad, 0x9aab, 0x0000, 0x0000, 0xc454, 0xc4d1, 0xf7c7, 0xf9cb,
+ 0x0000, 0x0000, 0x0000, 0xb3c2, 0xbbf2, 0x9aac, 0xbea3, 0x9a4a,
+ 0xf3f4, 0x91b2, 0xf874, 0xb6c0, 0x8bf6, 0x0000, 0x9aad, 0x89b6,
+ 0xefae, 0x0000, 0x0000, 0x0000, 0xc664, 0xb6c1, 0xbea4, 0xc248,
+ 0xf875, 0xb6c2, 0x0000, 0xe8f1, 0xc072, 0xecb4, 0xecb5, 0x0000,
+ 0xc071, 0x0000, 0xefaf, 0xc24c, 0xc24a, 0xc24b, 0xc249, 0xf1e0,
+ 0xc35c, 0x0000, 0x9aaf, 0x0000, 0xf5b5, 0xf5b4, 0xf5b7, 0xf5b6,
+ 0xc4d2, 0x0000, 0x0000, 0xf6cb, 0x0000, 0xf6cd, 0xf6cc, 0xc566,
+ 0xf7c8, 0x9ab0, 0xf876, 0xf877, 0xc5f0, 0xf964, 0xf97d, 0xc675,
+ 0x9ab1, 0xdcb0, 0xecb6, 0xefb0, 0xf3f5, 0xe0ef, 0x9aa1, 0xefb1
+};
+
+static const unsigned short big5hkscs_from_unicode_9f[] = {
+ 0xf1e2, 0xf1e1, 0x91b9, 0x0000, 0x0000, 0x0000, 0xf878, 0xc652,
+ 0x91ba, 0xf965, 0xf97e, 0x0000, 0x0000, 0x0000, 0xb9a9, 0xe8f2,
+ 0xe8f3, 0x0000, 0xecb7, 0xb9aa, 0x0000, 0xc35d, 0xf1e3, 0x9f66,
+ 0xf6cf, 0xc567, 0xf6d0, 0xf6ce, 0xf879, 0x0000, 0xf8e9, 0x0000,
+ 0xb9ab, 0x0000, 0xefb4, 0xefb3, 0xefb2, 0xf1e4, 0xa041, 0x8bb7,
+ 0xf1e8, 0xf1e7, 0xf1e6, 0xf1e5, 0xc35e, 0xf3f6, 0xf5b9, 0xc4d3,
+ 0xf5b8, 0xf6d1, 0xf7cb, 0xf7ca, 0xc5c4, 0xf7c9, 0xf87c, 0xf87b,
+ 0xf87a, 0x91c0, 0x0000, 0xbbf3, 0x0000, 0xecb8, 0xc24d, 0x0000,
+ 0xf3f7, 0xf3f8, 0xf7cc, 0xf87d, 0x9ab3, 0x91c3, 0xf8ea, 0xf966,
+ 0xf9b9, 0xf9d4, 0xbbf4, 0xc24e, 0xf1e9, 0xf3f9, 0xf6d2, 0xf87e,
+ 0xa0fc, 0x0000, 0xbea6, 0x9fee, 0xefb5, 0xf1ea, 0xf3fa, 0xf3fb,
+ 0xf3fc, 0xf5be, 0x9f69, 0xf5ba, 0xc568, 0xf5bd, 0xf5bc, 0xc4d4,
+ 0xf5bb, 0xc4d6, 0x91c8, 0xc4d5, 0xf6d4, 0xf6d3, 0xc569, 0xc56a,
+ 0x0000, 0x91c9, 0xc5c6, 0xf7cd, 0xc5c5, 0x0000, 0xf8a3, 0xf8a4,
+ 0xf8a2, 0xf8a1, 0xc654, 0x0000, 0xf8eb, 0xf8ec, 0xf8ed, 0xc653,
+ 0xf967, 0xf96a, 0xf969, 0xf968, 0x0000, 0x0000, 0xf9d3, 0x8de6,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc073, 0x91cb, 0x0000,
+ 0xc365, 0xf5bf, 0xf6d5, 0x0000, 0xc5c7, 0xf7ce, 0x0000, 0x0000,
+ 0xf9d5, 0x89c8, 0x0000, 0x0000, 0xc074, 0x0000, 0x0000, 0x8daa,
+ 0xefb6, 0x0000, 0xf7cf, 0x0000, 0xf9a1, 0x9fdd, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_e0[] = {
+ 0xfa40, 0x0000, 0xfa42, 0xfa43, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xfa49, 0xfa4a, 0x0000, 0xfa4c, 0x0000, 0xfa4e, 0x0000,
+ 0x0000, 0x0000, 0xfa52, 0xfa53, 0xfa54, 0xfa55, 0xfa56, 0x0000,
+ 0xfa58, 0x0000, 0xfa5a, 0xfa5b, 0xfa5c, 0xfa5d, 0xfa5e, 0x0000,
+ 0xfa60, 0x0000, 0xfa62, 0xfa63, 0x0000, 0xfa65, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfa6d, 0xfa6e, 0x0000,
+ 0xfa70, 0x0000, 0xfa72, 0xfa73, 0xfa74, 0xfa75, 0xfa76, 0xfa77,
+ 0xfa78, 0x0000, 0x0000, 0xfa7b, 0xfa7c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfaa7, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xfaae, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xfabc, 0x0000, 0xfabe, 0x0000, 0x0000, 0xfac1,
+ 0xfac2, 0xfac3, 0x0000, 0x0000, 0xfac6, 0x0000, 0xfac8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xface, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xfad3, 0x0000, 0x0000, 0xfad6, 0xfad7, 0x0000, 0x0000,
+ 0xfada, 0x0000, 0x0000, 0x0000, 0x0000, 0xfadf, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfae9,
+ 0x0000, 0xfaeb, 0xfaec, 0x0000, 0xfaee, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xfaf5, 0xfaf6, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xfafb, 0xfafc, 0x0000, 0xfafe, 0xfb40, 0xfb41, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfb49, 0xfb4a,
+ 0x0000, 0xfb4c, 0x0000, 0xfb4e, 0x0000, 0x0000, 0xfb51, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xfb5d, 0x0000, 0xfb5f, 0x0000, 0xfb61, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xfb66, 0x0000, 0xfb68, 0x0000, 0xfb6a,
+ 0xfb6b, 0x0000, 0xfb6d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfb73, 0x0000, 0x0000, 0x0000, 0xfb77, 0xfb78, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xfba1, 0x0000, 0x0000, 0xfba4,
+ 0x0000, 0x0000, 0xfba7, 0xfba8, 0xfba9, 0xfbaa, 0x0000, 0xfbac,
+ 0xfbad, 0xfbae, 0x0000, 0xfbb0, 0xfbb1, 0x0000, 0xfbb3, 0x0000,
+ 0x0000, 0x0000, 0xfbb7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfbbd, 0xfbbe, 0x0000, 0xfbc0, 0x0000, 0xfbc2, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_e1[] = {
+ 0x0000, 0x0000, 0x0000, 0xfbc8, 0x0000, 0x0000, 0xfbcb, 0x0000,
+ 0x0000, 0xfbce, 0xfbcf, 0xfbd0, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfbd5, 0x0000, 0x0000, 0x0000, 0xfbd9, 0xfbda, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xfbe1, 0xfbe2, 0x0000, 0x0000,
+ 0x0000, 0xfbe6, 0x0000, 0x0000, 0x0000, 0x0000, 0xfbeb, 0xfbec,
+ 0xfbed, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfbf5, 0xfbf6, 0x0000, 0x0000, 0x0000, 0x0000, 0xfbfb, 0x0000,
+ 0x0000, 0xfbfe, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xfc47, 0xfc48, 0x0000, 0x0000, 0xfc4b, 0x0000, 0xfc4d,
+ 0xfc4e, 0x0000, 0xfc50, 0x0000, 0x0000, 0xfc53, 0x0000, 0x0000,
+ 0xfc56, 0x0000, 0x0000, 0x0000, 0xfc5a, 0xfc5b, 0xfc5c, 0xfc5d,
+ 0x0000, 0xfc5f, 0xfc60, 0x0000, 0x0000, 0xfc63, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xfc68, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfc6e, 0xfc6f, 0xfc70, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xfc77, 0xfc78, 0x0000, 0x0000, 0xfc7b, 0x0000, 0x0000,
+ 0xfc7e, 0xfca1, 0x0000, 0xfca3, 0xfca4, 0x0000, 0x0000, 0xfca7,
+ 0xfca8, 0x0000, 0x0000, 0x0000, 0x0000, 0xfcad, 0x0000, 0xfcaf,
+ 0x0000, 0xfcb1, 0x0000, 0xfcb3, 0x0000, 0x0000, 0x0000, 0xfcb7,
+ 0xfcb8, 0x0000, 0x0000, 0xfcbb, 0x0000, 0xfcbd, 0xfcbe, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfcc7,
+ 0xfcc8, 0x0000, 0x0000, 0x0000, 0xfccc, 0x0000, 0xfcce, 0x0000,
+ 0x0000, 0x0000, 0xfcd2, 0x0000, 0x0000, 0x0000, 0xfcd6, 0x0000,
+ 0xfcd8, 0xfcd9, 0x0000, 0xfcdb, 0xfcdc, 0x0000, 0xfcde, 0x0000,
+ 0xfce0, 0x0000, 0x0000, 0xfce3, 0xfce4, 0xfce5, 0xfce6, 0xfce7,
+ 0x0000, 0xfce9, 0x0000, 0x0000, 0xfcec, 0xfced, 0x0000, 0x0000,
+ 0xfcf0, 0x0000, 0x0000, 0x0000, 0xfcf4, 0xfcf5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xfcfc, 0xfcfd, 0x0000, 0xfd40,
+ 0x0000, 0x0000, 0xfd43, 0x0000, 0x0000, 0xfd46, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xfd4b, 0x0000, 0x0000, 0x0000, 0xfd4f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xfd54, 0x0000, 0x0000, 0x0000, 0xfd58,
+ 0xfd59, 0x0000, 0xfd5b, 0x0000, 0x0000, 0x0000, 0x0000, 0xfd60,
+ 0x0000, 0x0000, 0xfd63, 0x0000, 0x0000, 0x0000, 0xfd67, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_e2[] = {
+ 0xfd69, 0xfd6a, 0xfd6b, 0x0000, 0x0000, 0xfd6e, 0x0000, 0xfd70,
+ 0x0000, 0x0000, 0xfd73, 0xfd74, 0xfd75, 0x0000, 0x0000, 0x0000,
+ 0xfd79, 0x0000, 0xfd7b, 0xfd7c, 0xfd7d, 0xfd7e, 0xfda1, 0x0000,
+ 0x0000, 0xfda4, 0x0000, 0xfda6, 0xfda7, 0x0000, 0x0000, 0xfdaa,
+ 0xfdab, 0xfdac, 0x0000, 0x0000, 0x0000, 0x0000, 0xfdb1, 0xfdb2,
+ 0xfdb3, 0x0000, 0xfdb5, 0x0000, 0x0000, 0x0000, 0x0000, 0xfdba,
+ 0x0000, 0xfdbc, 0x0000, 0xfdbe, 0x0000, 0x0000, 0x0000, 0xfdc2,
+ 0x0000, 0x0000, 0x0000, 0xfdc6, 0x0000, 0xfdc8, 0xfdc9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfdd0, 0x0000, 0x0000,
+ 0xfdd3, 0x0000, 0xfdd5, 0xfdd6, 0xfdd7, 0xfdd8, 0xfdd9, 0xfdda,
+ 0x0000, 0xfddc, 0xfddd, 0xfdde, 0xfddf, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xfdec, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfdf3, 0x0000, 0x0000, 0xfdf6, 0x0000, 0xfdf8, 0xfdf9, 0xfdfa,
+ 0x0000, 0xfdfc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xfe46, 0x0000, 0x0000, 0xfe49, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xfe4e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfe54, 0xfe55, 0x0000, 0xfe57, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfe5c, 0xfe5d, 0x0000, 0x0000, 0xfe60, 0xfe61, 0xfe62, 0x0000,
+ 0x0000, 0xfe65, 0xfe66, 0xfe67, 0x0000, 0x0000, 0x0000, 0xfe6b,
+ 0x0000, 0xfe6d, 0x0000, 0x0000, 0xfe70, 0x0000, 0xfe72, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xfe7e, 0xfea1, 0xfea2, 0xfea3, 0x0000, 0xfea5,
+ 0xfea6, 0x0000, 0xfea8, 0x0000, 0x0000, 0x0000, 0xfeac, 0xfead,
+ 0x0000, 0xfeaf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfeb5,
+ 0x0000, 0xfeb7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xfec2, 0x0000, 0x0000, 0x0000,
+ 0xfec6, 0xfec7, 0x0000, 0x0000, 0x0000, 0x0000, 0xfecc, 0x0000,
+ 0xfece, 0xfecf, 0xfed0, 0x0000, 0x0000, 0x0000, 0x0000, 0xfed5,
+ 0x0000, 0xfed7, 0x0000, 0xfed9, 0xfeda, 0xfedb, 0x0000, 0x0000,
+ 0xfede, 0xfedf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfee6, 0x0000, 0x0000, 0x0000, 0xfeea, 0x0000, 0x0000, 0xfeed
+};
+
+static const unsigned short big5hkscs_from_unicode_e3[] = {
+ 0xfeee, 0xfeef, 0x0000, 0x0000, 0x0000, 0x0000, 0xfef4, 0x0000,
+ 0xfef6, 0x0000, 0x0000, 0x0000, 0xfefa, 0x0000, 0x0000, 0xfefd,
+ 0x0000, 0x8e40, 0x0000, 0x8e42, 0x0000, 0x8e44, 0x0000, 0x0000,
+ 0x8e47, 0x0000, 0x0000, 0x8e4a, 0x8e4b, 0x0000, 0x0000, 0x8e4e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8e54, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8e5b, 0x0000, 0x0000, 0x0000,
+ 0x8e5f, 0x8e60, 0x0000, 0x0000, 0x0000, 0x8e64, 0x8e65, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8e6a, 0x0000, 0x8e6c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8e71, 0x0000, 0x0000, 0x8e74, 0x0000, 0x0000,
+ 0x8e77, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8ea3, 0x0000, 0x8ea5, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8eac, 0x8ead, 0x0000, 0x0000, 0x0000,
+ 0x8eb1, 0x0000, 0x8eb3, 0x0000, 0x8eb5, 0x8eb6, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8ec0,
+ 0x0000, 0x0000, 0x8ec3, 0x0000, 0x8ec5, 0x8ec6, 0x0000, 0x8ec8,
+ 0x0000, 0x8eca, 0x0000, 0x8ecc, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8ed2, 0x8ed3, 0x0000, 0x0000, 0x0000, 0x8ed7, 0x0000,
+ 0x8ed9, 0x8eda, 0x8edb, 0x0000, 0x0000, 0x8ede, 0x0000, 0x0000,
+ 0x0000, 0x8ee2, 0x0000, 0x8ee4, 0x8ee5, 0x0000, 0x8ee7, 0x0000,
+ 0x8ee9, 0x0000, 0x8eeb, 0x8eec, 0x0000, 0x0000, 0x8eef, 0x8ef0,
+ 0x8ef1, 0x0000, 0x8ef3, 0x0000, 0x0000, 0x8ef6, 0x8ef7, 0x8ef8,
+ 0x8ef9, 0x8efa, 0x0000, 0x0000, 0x8efd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8f43, 0x8f44, 0x0000, 0x8f46, 0x8f47, 0x0000, 0x0000,
+ 0x0000, 0x8f4b, 0x8f4c, 0x8f4d, 0x8f4e, 0x8f4f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8f55, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8f5a, 0x0000, 0x0000, 0x0000, 0x8f5e, 0x8f5f, 0x0000, 0x8f61,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8f67, 0x0000, 0x0000,
+ 0x8f6a, 0x8f6b, 0x8f6c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8f73, 0x0000, 0x8f75, 0x0000, 0x0000, 0x0000, 0x8f79,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8fa1, 0x8fa2, 0x0000,
+ 0x8fa4, 0x0000, 0x8fa6, 0x8fa7, 0x8fa8, 0x0000, 0x0000, 0x0000,
+ 0x8fac, 0x0000, 0x8fae, 0x0000, 0x0000, 0x8fb1, 0x0000, 0x8fb3
+};
+
+static const unsigned short big5hkscs_from_unicode_e4[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8fbd, 0x8fbe, 0x8fbf, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8fc8, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8fcf, 0x0000, 0x8fd1, 0x8fd2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8fd7, 0x0000, 0x8fd9, 0x8fda, 0x0000,
+ 0x8fdc, 0x0000, 0x0000, 0x0000, 0x8fe0, 0x8fe1, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8fe6, 0x0000, 0x0000, 0x0000, 0x8fea, 0x0000,
+ 0x0000, 0x0000, 0x8fee, 0x8fef, 0x8ff0, 0x0000, 0x8ff2, 0x0000,
+ 0x8ff4, 0x8ff5, 0x0000, 0x0000, 0x8ff8, 0x0000, 0x0000, 0x0000,
+ 0x8ffc, 0x0000, 0x0000, 0x0000, 0x9041, 0x9042, 0x9043, 0x0000,
+ 0x9045, 0x9046, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x904e, 0x904f, 0x0000, 0x0000, 0x9052, 0x9053, 0x0000,
+ 0x0000, 0x9056, 0x9057, 0x9058, 0x0000, 0x905a, 0x0000, 0x905c,
+ 0x905d, 0x905e, 0x905f, 0x0000, 0x9061, 0x0000, 0x9063, 0x9064,
+ 0x0000, 0x9066, 0x9067, 0x0000, 0x9069, 0x0000, 0x906b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9073, 0x9074,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9079, 0x0000, 0x907b, 0x907c,
+ 0x907d, 0x907e, 0x90a1, 0x0000, 0x0000, 0x90a4, 0x90a5, 0x0000,
+ 0x0000, 0x90a8, 0x90a9, 0x0000, 0x0000, 0x90ac, 0x90ad, 0x90ae,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x90b8, 0x90b9, 0x90ba, 0x90bb, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x90c2, 0x0000, 0x0000, 0x0000, 0x90c6,
+ 0x0000, 0x0000, 0x0000, 0x90ca, 0x90cb, 0x90cc, 0x90cd, 0x90ce,
+ 0x90cf, 0x90d0, 0x90d1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x90d8, 0x0000, 0x0000, 0x0000, 0x0000, 0x90dd, 0x0000,
+ 0x0000, 0x90e0, 0x0000, 0x0000, 0x0000, 0x90e4, 0x90e5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x90ed, 0x0000,
+ 0x0000, 0x90f0, 0x0000, 0x0000, 0x90f3, 0x90f4, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x90fb, 0x0000, 0x90fd, 0x90fe,
+ 0x9140, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9146, 0x9147,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x914e, 0x0000,
+ 0x9150, 0x9151, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9157
+};
+
+static const unsigned short big5hkscs_from_unicode_e5[] = {
+ 0x0000, 0x9159, 0x915a, 0x0000, 0x0000, 0x915d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9162, 0x0000, 0x0000, 0x9165, 0x0000, 0x9167,
+ 0x0000, 0x0000, 0x916a, 0x0000, 0x916c, 0x0000, 0x916e, 0x0000,
+ 0x0000, 0x0000, 0x9172, 0x0000, 0x9174, 0x9175, 0x9176, 0x9177,
+ 0x9178, 0x9179, 0x0000, 0x0000, 0x917c, 0x0000, 0x0000, 0x0000,
+ 0x91a2, 0x91a3, 0x91a4, 0x91a5, 0x91a6, 0x0000, 0x91a8, 0x91a9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x91b1,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x91b8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x91bd, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x91c5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x91ce, 0x91cf, 0x0000, 0x91d1,
+ 0x91d2, 0x91d3, 0x0000, 0x91d5, 0x91d6, 0x0000, 0x91d8, 0x91d9,
+ 0x0000, 0x0000, 0x91dc, 0x0000, 0x0000, 0x0000, 0x91e0, 0x91e1,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x91e7, 0x91e8, 0x0000,
+ 0x91ea, 0x0000, 0x91ec, 0x91ed, 0x0000, 0x91ef, 0x91f0, 0x91f1,
+ 0x0000, 0x91f3, 0x91f4, 0x0000, 0x91f6, 0x91f7, 0x91f8, 0x0000,
+ 0x91fa, 0x0000, 0x91fc, 0x91fd, 0x91fe, 0x9240, 0x9241, 0x0000,
+ 0x9243, 0x0000, 0x0000, 0x9246, 0x9247, 0x9248, 0x9249, 0x924a,
+ 0x924b, 0x0000, 0x924d, 0x924e, 0x924f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9255, 0x0000, 0x0000, 0x9258, 0x9259, 0x925a,
+ 0x925b, 0x925c, 0x0000, 0x0000, 0x925f, 0x0000, 0x9261, 0x9262,
+ 0x9263, 0x0000, 0x9265, 0x0000, 0x0000, 0x0000, 0x0000, 0x926a,
+ 0x0000, 0x926c, 0x926d, 0x0000, 0x0000, 0x9270, 0x0000, 0x9272,
+ 0x9273, 0x0000, 0x9275, 0x9276, 0x0000, 0x0000, 0x9279, 0x927a,
+ 0x927b, 0x0000, 0x927d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x92a5, 0x92a6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x92b4,
+ 0x92b5, 0x92b6, 0x0000, 0x92b8, 0x92b9, 0x0000, 0x0000, 0x92bc,
+ 0x0000, 0x92be, 0x92bf, 0x92c0, 0x0000, 0x92c2, 0x92c3, 0x0000,
+ 0x0000, 0x92c6, 0x0000, 0x0000, 0x0000, 0x0000, 0x92cb, 0x92cc,
+ 0x92cd, 0x92ce, 0x0000, 0x92d0, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x92d8, 0x92d9, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_e6[] = {
+ 0x92dd, 0x0000, 0x92df, 0x0000, 0x92e1, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x92ec,
+ 0x92ed, 0x92ee, 0x92ef, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x92f6, 0x92f7, 0x92f8, 0x92f9, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x92fe, 0x0000, 0x9341, 0x9342, 0x0000, 0x0000, 0x9345,
+ 0x0000, 0x0000, 0x0000, 0x9349, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9350, 0x9351, 0x9352, 0x0000, 0x0000, 0x9355,
+ 0x9356, 0x0000, 0x9358, 0x0000, 0x935a, 0x0000, 0x0000, 0x935d,
+ 0x935e, 0x935f, 0x9360, 0x0000, 0x0000, 0x9363, 0x9364, 0x0000,
+ 0x9366, 0x0000, 0x0000, 0x9369, 0x0000, 0x0000, 0x936c, 0x936d,
+ 0x0000, 0x0000, 0x9370, 0x9371, 0x9372, 0x9373, 0x0000, 0x9375,
+ 0x9376, 0x9377, 0x0000, 0x0000, 0x0000, 0x937b, 0x937c, 0x937d,
+ 0x937e, 0x0000, 0x93a2, 0x93a3, 0x0000, 0x93a5, 0x93a6, 0x93a7,
+ 0x93a8, 0x0000, 0x93aa, 0x0000, 0x0000, 0x0000, 0x93ae, 0x93af,
+ 0x0000, 0x93b1, 0x0000, 0x0000, 0x0000, 0x0000, 0x93b6, 0x93b7,
+ 0x93b8, 0x93b9, 0x0000, 0x93bb, 0x93bc, 0x93bd, 0x0000, 0x93bf,
+ 0x93c0, 0x0000, 0x0000, 0x93c3, 0x93c4, 0x93c5, 0x93c6, 0x93c7,
+ 0x93c8, 0x0000, 0x93ca, 0x93cb, 0x93cc, 0x0000, 0x93ce, 0x93cf,
+ 0x93d0, 0x0000, 0x93d2, 0x0000, 0x0000, 0x0000, 0x93d6, 0x93d7,
+ 0x0000, 0x93d9, 0x93da, 0x0000, 0x93dc, 0x0000, 0x93de, 0x93df,
+ 0x0000, 0x93e1, 0x93e2, 0x0000, 0x0000, 0x0000, 0x93e6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x93ec, 0x93ed, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x93f2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x93f9, 0x93fa, 0x0000, 0x0000, 0x93fd, 0x93fe, 0x0000,
+ 0x9441, 0x9442, 0x0000, 0x0000, 0x0000, 0x9446, 0x0000, 0x9448,
+ 0x0000, 0x0000, 0x944b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9452, 0x9453, 0x0000, 0x0000, 0x0000, 0x0000, 0x9458,
+ 0x9459, 0x0000, 0x945b, 0x945c, 0x0000, 0x945e, 0x945f, 0x9460,
+ 0x9461, 0x9462, 0x0000, 0x0000, 0x9465, 0x9466, 0x9467, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x946f, 0x0000,
+ 0x0000, 0x0000, 0x9473, 0x9474, 0x0000, 0x0000, 0x0000, 0x9478,
+ 0x0000, 0x0000, 0x947b, 0x947c, 0x947d, 0x0000, 0x0000, 0x94a2
+};
+
+static const unsigned short big5hkscs_from_unicode_e7[] = {
+ 0x0000, 0x94a4, 0x94a5, 0x0000, 0x0000, 0x0000, 0x94a9, 0x94aa,
+ 0x0000, 0x94ac, 0x94ad, 0x0000, 0x94af, 0x0000, 0x0000, 0x0000,
+ 0x94b3, 0x94b4, 0x0000, 0x94b6, 0x0000, 0x0000, 0x0000, 0x94ba,
+ 0x94bb, 0x0000, 0x94bd, 0x94be, 0x0000, 0x94c0, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x94c7, 0x94c8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x94ce, 0x0000, 0x0000, 0x0000, 0x94d2,
+ 0x0000, 0x0000, 0x0000, 0x94d6, 0x94d7, 0x94d8, 0x94d9, 0x94da,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x94df, 0x94e0, 0x0000, 0x0000,
+ 0x94e3, 0x94e4, 0x94e5, 0x0000, 0x94e7, 0x0000, 0x0000, 0x94ea,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x94f0, 0x94f1, 0x94f2,
+ 0x0000, 0x94f4, 0x94f5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x94fe, 0x9540, 0x9541, 0x0000, 0x9543,
+ 0x0000, 0x9545, 0x9546, 0x0000, 0x9548, 0x9549, 0x0000, 0x954b,
+ 0x954c, 0x954d, 0x0000, 0x0000, 0x9550, 0x9551, 0x9552, 0x0000,
+ 0x9554, 0x0000, 0x0000, 0x0000, 0x0000, 0x9559, 0x0000, 0x955b,
+ 0x955c, 0x0000, 0x955e, 0x0000, 0x9560, 0x9561, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9568, 0x0000, 0x956a, 0x0000,
+ 0x0000, 0x956d, 0x0000, 0x956f, 0x0000, 0x9571, 0x0000, 0x0000,
+ 0x9574, 0x0000, 0x9576, 0x0000, 0x9578, 0x0000, 0x957a, 0x957b,
+ 0x0000, 0x957d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x95a8, 0x0000, 0x95aa, 0x95ab, 0x95ac, 0x95ad,
+ 0x95ae, 0x95af, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x95b7, 0x0000, 0x0000, 0x95ba, 0x0000, 0x0000, 0x0000,
+ 0x95be, 0x0000, 0x0000, 0x0000, 0x95c2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x95ca, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x95d0, 0x0000, 0x0000, 0x0000, 0x95d4, 0x0000,
+ 0x0000, 0x95d7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x95de, 0x0000, 0x95e0, 0x0000, 0x95e2, 0x95e3, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x95ea, 0x0000, 0x0000, 0x95ed,
+ 0x95ee, 0x95ef, 0x0000, 0x95f1, 0x0000, 0x95f3, 0x95f4, 0x95f5,
+ 0x0000, 0x95f7, 0x95f8, 0x95f9, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x95fe, 0x0000, 0x0000, 0x9642, 0x9643, 0x0000, 0x0000, 0x9646
+};
+
+static const unsigned short big5hkscs_from_unicode_e8[] = {
+ 0x9647, 0x9648, 0x9649, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x964f, 0x0000, 0x0000, 0x0000, 0x9653, 0x0000, 0x9655, 0x9656,
+ 0x0000, 0x9658, 0x0000, 0x965a, 0x0000, 0x0000, 0x965d, 0x965e,
+ 0x965f, 0x0000, 0x9661, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9668, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x966e,
+ 0x966f, 0x0000, 0x0000, 0x0000, 0x0000, 0x9674, 0x0000, 0x9676,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x967c, 0x0000, 0x967e,
+ 0x96a1, 0x0000, 0x96a3, 0x96a4, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x96aa, 0x96ab, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x96b4, 0x0000, 0x96b6, 0x96b7, 0x0000,
+ 0x0000, 0x96ba, 0x0000, 0x0000, 0x0000, 0x96be, 0x96bf, 0x96c0,
+ 0x96c1, 0x0000, 0x0000, 0x96c4, 0x96c5, 0x96c6, 0x0000, 0x0000,
+ 0x96c9, 0x96ca, 0x96cb, 0x0000, 0x0000, 0x96ce, 0x96cf, 0x96d0,
+ 0x0000, 0x96d2, 0x96d3, 0x0000, 0x96d5, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x96da, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x96e1, 0x0000, 0x0000, 0x0000, 0x0000, 0x96e6, 0x96e7, 0x96e8,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x96f0,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x96f8,
+ 0x0000, 0x96fa, 0x96fb, 0x0000, 0x96fd, 0x96fe, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x9744, 0x0000, 0x0000, 0x9747, 0x0000, 0x0000,
+ 0x974a, 0x974b, 0x0000, 0x974d, 0x974e, 0x974f, 0x9750, 0x9751,
+ 0x0000, 0x9753, 0x9754, 0x0000, 0x9756, 0x9757, 0x9758, 0x9759,
+ 0x975a, 0x0000, 0x0000, 0x0000, 0x0000, 0x975f, 0x9760, 0x0000,
+ 0x9762, 0x0000, 0x0000, 0x0000, 0x0000, 0x9767, 0x9768, 0x9769,
+ 0x976a, 0x976b, 0x976c, 0x976d, 0x0000, 0x976f, 0x0000, 0x9771,
+ 0x0000, 0x0000, 0x0000, 0x9775, 0x0000, 0x9777, 0x9778, 0x0000,
+ 0x977a, 0x977b, 0x0000, 0x977d, 0x0000, 0x97a1, 0x97a2, 0x0000,
+ 0x97a4, 0x97a5, 0x97a6, 0x0000, 0x0000, 0x97a9, 0x0000, 0x97ab,
+ 0x97ac, 0x97ad, 0x0000, 0x0000, 0x0000, 0x97b1, 0x97b2, 0x0000,
+ 0x97b4, 0x97b5, 0x97b6, 0x0000, 0x0000, 0x97b9, 0x0000, 0x0000,
+ 0x0000, 0x97bd, 0x97be, 0x0000, 0x0000, 0x97c1, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x97c7, 0x0000, 0x0000, 0x97ca, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_e9[] = {
+ 0x97cc, 0x0000, 0x0000, 0x97cf, 0x0000, 0x0000, 0x0000, 0x97d3,
+ 0x97d4, 0x0000, 0x0000, 0x0000, 0x97d8, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x97e3,
+ 0x97e4, 0x0000, 0x0000, 0x0000, 0x97e8, 0x0000, 0x97ea, 0x97eb,
+ 0x97ec, 0x97ed, 0x97ee, 0x0000, 0x0000, 0x97f1, 0x97f2, 0x97f3,
+ 0x97f4, 0x97f5, 0x97f6, 0x97f7, 0x97f8, 0x0000, 0x97fa, 0x97fb,
+ 0x0000, 0x0000, 0x0000, 0x9840, 0x9841, 0x9842, 0x9843, 0x0000,
+ 0x9845, 0x0000, 0x9847, 0x0000, 0x9849, 0x984a, 0x984b, 0x0000,
+ 0x0000, 0x984e, 0x0000, 0x0000, 0x9851, 0x9852, 0x0000, 0x0000,
+ 0x9855, 0x0000, 0x0000, 0x0000, 0x0000, 0x985a, 0x0000, 0x0000,
+ 0x985d, 0x0000, 0x985f, 0x9860, 0x9861, 0x9862, 0x0000, 0x9864,
+ 0x9865, 0x0000, 0x9867, 0x0000, 0x9869, 0x986a, 0x986b, 0x0000,
+ 0x986d, 0x986e, 0x0000, 0x0000, 0x9871, 0x0000, 0x0000, 0x9874,
+ 0x9875, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x987b, 0x987c,
+ 0x0000, 0x0000, 0x0000, 0x98a2, 0x98a3, 0x98a4, 0x0000, 0x98a6,
+ 0x98a7, 0x0000, 0x98a9, 0x98aa, 0x0000, 0x98ac, 0x0000, 0x0000,
+ 0x0000, 0x98b0, 0x98b1, 0x0000, 0x0000, 0x0000, 0x0000, 0x98b6,
+ 0x0000, 0x0000, 0x98b9, 0x0000, 0x0000, 0x0000, 0x98bd, 0x0000,
+ 0x0000, 0x98c0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x98df, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x98fa, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x995f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_ea[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x99d5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9a7c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9ab4,
+ 0x9ab5, 0x9ab6, 0x0000, 0x0000, 0x0000, 0x9aba, 0x0000, 0x0000,
+ 0x0000, 0x9abe, 0x9abf, 0x9ac0, 0x9ac1, 0x0000, 0x0000, 0x9ac4,
+ 0x9ac5, 0x9ac6, 0x0000, 0x9ac8, 0x9ac9, 0x0000, 0x9acb, 0x9acc,
+ 0x9acd, 0x9ace, 0x9acf, 0x0000, 0x9ad1, 0x0000, 0x9ad3, 0x9ad4,
+ 0x9ad5, 0x9ad6, 0x9ad7, 0x9ad8, 0x0000, 0x0000, 0x0000, 0x9adc,
+ 0x9add, 0x9ade, 0x9adf, 0x9ae0, 0x9ae1, 0x0000, 0x9ae3, 0x0000,
+ 0x9ae5, 0x9ae6, 0x9ae7, 0x0000, 0x9ae9, 0x9aea, 0x9aeb, 0x0000,
+ 0x9aed, 0x9aee, 0x9aef, 0x9af0, 0x0000, 0x0000, 0x9af3, 0x9af4
+};
+
+static const unsigned short big5hkscs_from_unicode_eb[] = {
+ 0x9af5, 0x0000, 0x9af7, 0x9af8, 0x9af9, 0x9afa, 0x0000, 0x0000,
+ 0x9afd, 0x9afe, 0x9b40, 0x9b41, 0x9b42, 0x9b43, 0x9b44, 0x9b45,
+ 0x0000, 0x9b47, 0x9b48, 0x0000, 0x0000, 0x9b4b, 0x0000, 0x0000,
+ 0x9b4e, 0x9b4f, 0x9b50, 0x9b51, 0x9b52, 0x9b53, 0x0000, 0x9b55,
+ 0x9b56, 0x9b57, 0x0000, 0x9b59, 0x0000, 0x9b5b, 0x0000, 0x9b5d,
+ 0x0000, 0x0000, 0x9b60, 0x9b61, 0x9b62, 0x9b63, 0x9b64, 0x9b65,
+ 0x9b66, 0x9b67, 0x9b68, 0x9b69, 0x9b6a, 0x9b6b, 0x9b6c, 0x9b6d,
+ 0x9b6e, 0x9b6f, 0x0000, 0x0000, 0x0000, 0x9b73, 0x9b74, 0x9b75,
+ 0x0000, 0x9b77, 0x0000, 0x9b79, 0x9b7a, 0x0000, 0x9b7c, 0x0000,
+ 0x0000, 0x0000, 0x9ba2, 0x9ba3, 0x9ba4, 0x9ba5, 0x9ba6, 0x9ba7,
+ 0x9ba8, 0x0000, 0x0000, 0x9bab, 0x9bac, 0x9bad, 0x9bae, 0x9baf,
+ 0x9bb0, 0x9bb1, 0x9bb2, 0x9bb3, 0x0000, 0x9bb5, 0x0000, 0x9bb7,
+ 0x0000, 0x9bb9, 0x9bba, 0x9bbb, 0x0000, 0x9bbd, 0x0000, 0x9bbf,
+ 0x9bc0, 0x9bc1, 0x0000, 0x9bc3, 0x0000, 0x9bc5, 0x0000, 0x9bc7,
+ 0x9bc8, 0x9bc9, 0x0000, 0x9bcb, 0x9bcc, 0x0000, 0x9bce, 0x9bcf,
+ 0x9bd0, 0x0000, 0x9bd2, 0x0000, 0x0000, 0x0000, 0x9bd6, 0x9bd7,
+ 0x9bd8, 0x9bd9, 0x0000, 0x9bdb, 0x9bdc, 0x9bdd, 0x0000, 0x0000,
+ 0x9be0, 0x9be1, 0x9be2, 0x0000, 0x9be4, 0x9be5, 0x9be6, 0x9be7,
+ 0x9be8, 0x0000, 0x0000, 0x9beb, 0x0000, 0x9bed, 0x0000, 0x9bef,
+ 0x9bf0, 0x9bf1, 0x9bf2, 0x9bf3, 0x0000, 0x0000, 0x0000, 0x9bf7,
+ 0x9bf8, 0x0000, 0x9bfa, 0x9bfb, 0x0000, 0x9bfd, 0x9bfe, 0x0000,
+ 0x9c41, 0x0000, 0x9c43, 0x9c44, 0x0000, 0x9c46, 0x9c47, 0x9c48,
+ 0x9c49, 0x0000, 0x9c4b, 0x9c4c, 0x9c4d, 0x0000, 0x9c4f, 0x0000,
+ 0x0000, 0x9c52, 0x0000, 0x0000, 0x9c55, 0x9c56, 0x0000, 0x9c58,
+ 0x0000, 0x0000, 0x9c5b, 0x0000, 0x0000, 0x9c5e, 0x9c5f, 0x9c60,
+ 0x9c61, 0x0000, 0x9c63, 0x0000, 0x9c65, 0x9c66, 0x9c67, 0x0000,
+ 0x9c69, 0x0000, 0x0000, 0x9c6c, 0x0000, 0x9c6e, 0x0000, 0x9c70,
+ 0x9c71, 0x0000, 0x9c73, 0x9c74, 0x0000, 0x9c76, 0x0000, 0x9c78,
+ 0x0000, 0x9c7a, 0x0000, 0x0000, 0x9c7d, 0x0000, 0x0000, 0x9ca2,
+ 0x9ca3, 0x9ca4, 0x0000, 0x9ca6, 0x9ca7, 0x0000, 0x9ca9, 0x9caa,
+ 0x0000, 0x9cac, 0x9cad, 0x0000, 0x0000, 0x9cb0, 0x9cb1, 0x0000,
+ 0x0000, 0x9cb4, 0x9cb5, 0x9cb6, 0x0000, 0x9cb8, 0x9cb9, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_ec[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9cc0, 0x9cc1, 0x0000,
+ 0x9cc3, 0x9cc4, 0x0000, 0x0000, 0x9cc7, 0x0000, 0x9cc9, 0x9cca,
+ 0x9ccb, 0x0000, 0x0000, 0x9cce, 0x9ccf, 0x0000, 0x0000, 0x9cd2,
+ 0x9cd3, 0x9cd4, 0x9cd5, 0x9cd6, 0x9cd7, 0x9cd8, 0x0000, 0x0000,
+ 0x9cdb, 0x0000, 0x9cdd, 0x0000, 0x9cdf, 0x0000, 0x9ce1, 0x0000,
+ 0x0000, 0x0000, 0x9ce5, 0x9ce6, 0x9ce7, 0x9ce8, 0x9ce9, 0x9cea,
+ 0x0000, 0x9cec, 0x9ced, 0x0000, 0x0000, 0x9cf0, 0x0000, 0x9cf2,
+ 0x0000, 0x0000, 0x0000, 0x9cf6, 0x9cf7, 0x0000, 0x0000, 0x9cfa,
+ 0x9cfb, 0x9cfc, 0x9cfd, 0x9cfe, 0x9d40, 0x9d41, 0x9d42, 0x9d43,
+ 0x9d44, 0x9d45, 0x0000, 0x9d47, 0x9d48, 0x0000, 0x0000, 0x9d4b,
+ 0x0000, 0x0000, 0x9d4e, 0x0000, 0x9d50, 0x0000, 0x9d52, 0x9d53,
+ 0x9d54, 0x0000, 0x9d56, 0x0000, 0x9d58, 0x9d59, 0x0000, 0x9d5b,
+ 0x9d5c, 0x0000, 0x9d5e, 0x9d5f, 0x0000, 0x0000, 0x0000, 0x9d63,
+ 0x9d64, 0x9d65, 0x9d66, 0x9d67, 0x9d68, 0x9d69, 0x9d6a, 0x9d6b,
+ 0x9d6c, 0x9d6d, 0x9d6e, 0x9d6f, 0x0000, 0x9d71, 0x9d72, 0x0000,
+ 0x0000, 0x9d75, 0x0000, 0x9d77, 0x0000, 0x0000, 0x9d7a, 0x0000,
+ 0x9d7c, 0x0000, 0x0000, 0x0000, 0x9da2, 0x0000, 0x9da4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9dab, 0x9dac, 0x0000,
+ 0x0000, 0x9daf, 0x9db0, 0x9db1, 0x9db2, 0x9db3, 0x9db4, 0x0000,
+ 0x9db6, 0x9db7, 0x9db8, 0x9db9, 0x0000, 0x9dbb, 0x9dbc, 0x0000,
+ 0x9dbe, 0x0000, 0x0000, 0x9dc1, 0x9dc2, 0x0000, 0x0000, 0x9dc5,
+ 0x9dc6, 0x0000, 0x0000, 0x9dc9, 0x0000, 0x9dcb, 0x0000, 0x9dcd,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9dd2, 0x0000, 0x9dd4, 0x0000,
+ 0x0000, 0x9dd7, 0x9dd8, 0x9dd9, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9ded,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9df2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x9df9, 0x9dfa, 0x0000, 0x9dfc, 0x9dfd,
+ 0x9dfe, 0x9e40, 0x0000, 0x0000, 0x0000, 0x9e44, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x9e4f, 0x0000, 0x9e51, 0x0000, 0x0000, 0x9e54, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9e5b, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_ed[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9e63, 0x0000, 0x0000, 0x9e66,
+ 0x0000, 0x0000, 0x9e69, 0x0000, 0x9e6b, 0x9e6c, 0x9e6d, 0x9e6e,
+ 0x9e6f, 0x9e70, 0x0000, 0x9e72, 0x0000, 0x9e74, 0x9e75, 0x9e76,
+ 0x9e77, 0x0000, 0x9e79, 0x0000, 0x9e7b, 0x9e7c, 0x9e7d, 0x0000,
+ 0x0000, 0x0000, 0x9ea3, 0x0000, 0x9ea5, 0x9ea6, 0x9ea7, 0x9ea8,
+ 0x0000, 0x9eaa, 0x9eab, 0x9eac, 0x9ead, 0x9eae, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x9ebc, 0x0000, 0x9ebe, 0x0000, 0x0000,
+ 0x0000, 0x9ec2, 0x9ec3, 0x9ec4, 0x0000, 0x9ec6, 0x0000, 0x9ec8,
+ 0x0000, 0x0000, 0x9ecb, 0x9ecc, 0x0000, 0x9ece, 0x9ecf, 0x9ed0,
+ 0x0000, 0x9ed2, 0x9ed3, 0x9ed4, 0x9ed5, 0x0000, 0x0000, 0x9ed8,
+ 0x9ed9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9ee0,
+ 0x0000, 0x0000, 0x9ee3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x9eec, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9ef2, 0x9ef3, 0x9ef4, 0x0000, 0x9ef6, 0x0000, 0x9ef8,
+ 0x9ef9, 0x0000, 0x9efb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9f43, 0x0000, 0x0000, 0x9f46, 0x9f47, 0x9f48, 0x0000,
+ 0x9f4a, 0x9f4b, 0x9f4c, 0x9f4d, 0x9f4e, 0x0000, 0x9f50, 0x0000,
+ 0x0000, 0x9f53, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9f68, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9faa, 0x0000,
+ 0x0000, 0x9fad, 0x0000, 0x0000, 0x0000, 0x9fb1, 0x0000, 0x9fb3,
+ 0x0000, 0x9fb5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9fbb,
+ 0x0000, 0x0000, 0x9fbe, 0x9fbf, 0x9fc0, 0x9fc1, 0x0000, 0x0000,
+ 0x0000, 0x9fc5, 0x0000, 0x0000, 0x9fc8, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9fd1, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9fda, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_ee[] = {
+ 0x0000, 0x0000, 0x9fe6, 0x0000, 0x0000, 0x0000, 0x9fea, 0x0000,
+ 0x9fec, 0x0000, 0x0000, 0x9fef, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9ff5, 0x0000, 0x0000, 0x0000, 0x9ff9, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa040, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa045, 0x0000, 0xa047, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa04f, 0x0000, 0x0000, 0x0000, 0x0000, 0xa054,
+ 0xa055, 0xa056, 0xa057, 0x0000, 0xa059, 0xa05a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa062, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa06d, 0x0000, 0x0000, 0x0000, 0x0000, 0xa072, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa07b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa0a2, 0x0000, 0xa0a4, 0xa0a5, 0x0000,
+ 0xa0a7, 0x0000, 0x0000, 0x0000, 0xa0ab, 0x0000, 0xa0ad, 0x0000,
+ 0xa0af, 0x0000, 0xa0b1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa0bd, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa0c3, 0x0000, 0xa0c5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa0d3, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa0d8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa0e1, 0x0000, 0xa0e3, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa0e9, 0xa0ea, 0xa0eb, 0xa0ec, 0xa0ed, 0xa0ee,
+ 0xa0ef, 0xa0f0, 0xa0f1, 0x0000, 0xa0f3, 0xa0f4, 0xa0f5, 0xa0f6,
+ 0xa0f7, 0xa0f8, 0x0000, 0x0000, 0xa0fb, 0x0000, 0x0000, 0xa0fe,
+ 0x8140, 0x8141, 0x8142, 0x8143, 0x8144, 0x8145, 0x8146, 0x8147,
+ 0x8148, 0x8149, 0x814a, 0x814b, 0x814c, 0x814d, 0x814e, 0x814f,
+ 0x8150, 0x8151, 0x8152, 0x8153, 0x8154, 0x8155, 0x8156, 0x8157,
+ 0x8158, 0x8159, 0x815a, 0x815b, 0x815c, 0x815d, 0x815e, 0x815f,
+ 0x8160, 0x8161, 0x8162, 0x8163, 0x8164, 0x8165, 0x8166, 0x8167,
+ 0x8168, 0x8169, 0x816a, 0x816b, 0x816c, 0x816d, 0x816e, 0x816f,
+ 0x8170, 0x8171, 0x8172, 0x8173, 0x8174, 0x8175, 0x8176, 0x8177,
+ 0x8178, 0x8179, 0x817a, 0x817b, 0x817c, 0x817d, 0x817e, 0x81a1,
+ 0x81a2, 0x81a3, 0x81a4, 0x81a5, 0x81a6, 0x81a7, 0x81a8, 0x81a9
+};
+
+static const unsigned short big5hkscs_from_unicode_ef[] = {
+ 0x81aa, 0x81ab, 0x81ac, 0x81ad, 0x81ae, 0x81af, 0x81b0, 0x81b1,
+ 0x81b2, 0x81b3, 0x81b4, 0x81b5, 0x81b6, 0x81b7, 0x81b8, 0x81b9,
+ 0x81ba, 0x81bb, 0x81bc, 0x81bd, 0x81be, 0x81bf, 0x81c0, 0x81c1,
+ 0x81c2, 0x81c3, 0x81c4, 0x81c5, 0x81c6, 0x81c7, 0x81c8, 0x81c9,
+ 0x81ca, 0x81cb, 0x81cc, 0x81cd, 0x81ce, 0x81cf, 0x81d0, 0x81d1,
+ 0x81d2, 0x81d3, 0x81d4, 0x81d5, 0x81d6, 0x81d7, 0x81d8, 0x81d9,
+ 0x81da, 0x81db, 0x81dc, 0x81dd, 0x81de, 0x81df, 0x81e0, 0x81e1,
+ 0x81e2, 0x81e3, 0x81e4, 0x81e5, 0x81e6, 0x81e7, 0x81e8, 0x81e9,
+ 0x81ea, 0x81eb, 0x81ec, 0x81ed, 0x81ee, 0x81ef, 0x81f0, 0x81f1,
+ 0x81f2, 0x81f3, 0x81f4, 0x81f5, 0x81f6, 0x81f7, 0x81f8, 0x81f9,
+ 0x81fa, 0x81fb, 0x81fc, 0x81fd, 0x81fe, 0x8240, 0x8241, 0x8242,
+ 0x8243, 0x8244, 0x8245, 0x8246, 0x8247, 0x8248, 0x8249, 0x824a,
+ 0x824b, 0x824c, 0x824d, 0x824e, 0x824f, 0x8250, 0x8251, 0x8252,
+ 0x8253, 0x8254, 0x8255, 0x8256, 0x8257, 0x8258, 0x8259, 0x825a,
+ 0x825b, 0x825c, 0x825d, 0x825e, 0x825f, 0x8260, 0x8261, 0x8262,
+ 0x8263, 0x8264, 0x8265, 0x8266, 0x8267, 0x8268, 0x8269, 0x826a,
+ 0x826b, 0x826c, 0x826d, 0x826e, 0x826f, 0x8270, 0x8271, 0x8272,
+ 0x8273, 0x8274, 0x8275, 0x8276, 0x8277, 0x8278, 0x8279, 0x827a,
+ 0x827b, 0x827c, 0x827d, 0x827e, 0x82a1, 0x82a2, 0x82a3, 0x82a4,
+ 0x82a5, 0x82a6, 0x82a7, 0x82a8, 0x82a9, 0x82aa, 0x82ab, 0x82ac,
+ 0x82ad, 0x82ae, 0x82af, 0x82b0, 0x82b1, 0x82b2, 0x82b3, 0x82b4,
+ 0x82b5, 0x82b6, 0x82b7, 0x82b8, 0x82b9, 0x82ba, 0x82bb, 0x82bc,
+ 0x82bd, 0x82be, 0x82bf, 0x82c0, 0x82c1, 0x82c2, 0x82c3, 0x82c4,
+ 0x82c5, 0x82c6, 0x82c7, 0x82c8, 0x82c9, 0x82ca, 0x82cb, 0x82cc,
+ 0x82cd, 0x82ce, 0x82cf, 0x82d0, 0x82d1, 0x82d2, 0x82d3, 0x82d4,
+ 0x82d5, 0x82d6, 0x82d7, 0x82d8, 0x82d9, 0x82da, 0x82db, 0x82dc,
+ 0x82dd, 0x82de, 0x82df, 0x82e0, 0x82e1, 0x82e2, 0x82e3, 0x82e4,
+ 0x82e5, 0x82e6, 0x82e7, 0x82e8, 0x82e9, 0x82ea, 0x82eb, 0x82ec,
+ 0x82ed, 0x82ee, 0x82ef, 0x82f0, 0x82f1, 0x82f2, 0x82f3, 0x82f4,
+ 0x82f5, 0x82f6, 0x82f7, 0x82f8, 0x82f9, 0x82fa, 0x82fb, 0x82fc,
+ 0x82fd, 0x82fe, 0x8340, 0x8341, 0x8342, 0x8343, 0x8344, 0x8345,
+ 0x8346, 0x8347, 0x8348, 0x8349, 0x834a, 0x834b, 0x834c, 0x834d
+};
+
+static const unsigned short big5hkscs_from_unicode_f0[] = {
+ 0x834e, 0x834f, 0x8350, 0x8351, 0x8352, 0x8353, 0x8354, 0x8355,
+ 0x8356, 0x8357, 0x8358, 0x8359, 0x835a, 0x835b, 0x835c, 0x835d,
+ 0x835e, 0x835f, 0x8360, 0x8361, 0x8362, 0x8363, 0x8364, 0x8365,
+ 0x8366, 0x8367, 0x8368, 0x8369, 0x836a, 0x836b, 0x836c, 0x836d,
+ 0x836e, 0x836f, 0x8370, 0x8371, 0x8372, 0x8373, 0x8374, 0x8375,
+ 0x8376, 0x8377, 0x8378, 0x8379, 0x837a, 0x837b, 0x837c, 0x837d,
+ 0x837e, 0x83a1, 0x83a2, 0x83a3, 0x83a4, 0x83a5, 0x83a6, 0x83a7,
+ 0x83a8, 0x83a9, 0x83aa, 0x83ab, 0x83ac, 0x83ad, 0x83ae, 0x83af,
+ 0x83b0, 0x83b1, 0x83b2, 0x83b3, 0x83b4, 0x83b5, 0x83b6, 0x83b7,
+ 0x83b8, 0x83b9, 0x83ba, 0x83bb, 0x83bc, 0x83bd, 0x83be, 0x83bf,
+ 0x83c0, 0x83c1, 0x83c2, 0x83c3, 0x83c4, 0x83c5, 0x83c6, 0x83c7,
+ 0x83c8, 0x83c9, 0x83ca, 0x83cb, 0x83cc, 0x83cd, 0x83ce, 0x83cf,
+ 0x83d0, 0x83d1, 0x83d2, 0x83d3, 0x83d4, 0x83d5, 0x83d6, 0x83d7,
+ 0x83d8, 0x83d9, 0x83da, 0x83db, 0x83dc, 0x83dd, 0x83de, 0x83df,
+ 0x83e0, 0x83e1, 0x83e2, 0x83e3, 0x83e4, 0x83e5, 0x83e6, 0x83e7,
+ 0x83e8, 0x83e9, 0x83ea, 0x83eb, 0x83ec, 0x83ed, 0x83ee, 0x83ef,
+ 0x83f0, 0x83f1, 0x83f2, 0x83f3, 0x83f4, 0x83f5, 0x83f6, 0x83f7,
+ 0x83f8, 0x83f9, 0x83fa, 0x83fb, 0x83fc, 0x83fd, 0x83fe, 0x8440,
+ 0x8441, 0x8442, 0x8443, 0x8444, 0x8445, 0x8446, 0x8447, 0x8448,
+ 0x8449, 0x844a, 0x844b, 0x844c, 0x844d, 0x844e, 0x844f, 0x8450,
+ 0x8451, 0x8452, 0x8453, 0x8454, 0x8455, 0x8456, 0x8457, 0x8458,
+ 0x8459, 0x845a, 0x845b, 0x845c, 0x845d, 0x845e, 0x845f, 0x8460,
+ 0x8461, 0x8462, 0x8463, 0x8464, 0x8465, 0x8466, 0x8467, 0x8468,
+ 0x8469, 0x846a, 0x846b, 0x846c, 0x846d, 0x846e, 0x846f, 0x8470,
+ 0x8471, 0x8472, 0x8473, 0x8474, 0x8475, 0x8476, 0x8477, 0x8478,
+ 0x8479, 0x847a, 0x847b, 0x847c, 0x847d, 0x847e, 0x84a1, 0x84a2,
+ 0x84a3, 0x84a4, 0x84a5, 0x84a6, 0x84a7, 0x84a8, 0x84a9, 0x84aa,
+ 0x84ab, 0x84ac, 0x84ad, 0x84ae, 0x84af, 0x84b0, 0x84b1, 0x84b2,
+ 0x84b3, 0x84b4, 0x84b5, 0x84b6, 0x84b7, 0x84b8, 0x84b9, 0x84ba,
+ 0x84bb, 0x84bc, 0x84bd, 0x84be, 0x84bf, 0x84c0, 0x84c1, 0x84c2,
+ 0x84c3, 0x84c4, 0x84c5, 0x84c6, 0x84c7, 0x84c8, 0x84c9, 0x84ca,
+ 0x84cb, 0x84cc, 0x84cd, 0x84ce, 0x84cf, 0x84d0, 0x84d1, 0x84d2
+};
+
+static const unsigned short big5hkscs_from_unicode_f1[] = {
+ 0x84d3, 0x84d4, 0x84d5, 0x84d6, 0x84d7, 0x84d8, 0x84d9, 0x84da,
+ 0x84db, 0x84dc, 0x84dd, 0x84de, 0x84df, 0x84e0, 0x84e1, 0x84e2,
+ 0x84e3, 0x84e4, 0x84e5, 0x84e6, 0x84e7, 0x84e8, 0x84e9, 0x84ea,
+ 0x84eb, 0x84ec, 0x84ed, 0x84ee, 0x84ef, 0x84f0, 0x84f1, 0x84f2,
+ 0x84f3, 0x84f4, 0x84f5, 0x84f6, 0x84f7, 0x84f8, 0x84f9, 0x84fa,
+ 0x84fb, 0x84fc, 0x84fd, 0x84fe, 0x8540, 0x8541, 0x8542, 0x8543,
+ 0x8544, 0x8545, 0x8546, 0x8547, 0x8548, 0x8549, 0x854a, 0x854b,
+ 0x854c, 0x854d, 0x854e, 0x854f, 0x8550, 0x8551, 0x8552, 0x8553,
+ 0x8554, 0x8555, 0x8556, 0x8557, 0x8558, 0x8559, 0x855a, 0x855b,
+ 0x855c, 0x855d, 0x855e, 0x855f, 0x8560, 0x8561, 0x8562, 0x8563,
+ 0x8564, 0x8565, 0x8566, 0x8567, 0x8568, 0x8569, 0x856a, 0x856b,
+ 0x856c, 0x856d, 0x856e, 0x856f, 0x8570, 0x8571, 0x8572, 0x8573,
+ 0x8574, 0x8575, 0x8576, 0x8577, 0x8578, 0x8579, 0x857a, 0x857b,
+ 0x857c, 0x857d, 0x857e, 0x85a1, 0x85a2, 0x85a3, 0x85a4, 0x85a5,
+ 0x85a6, 0x85a7, 0x85a8, 0x85a9, 0x85aa, 0x85ab, 0x85ac, 0x85ad,
+ 0x85ae, 0x85af, 0x85b0, 0x85b1, 0x85b2, 0x85b3, 0x85b4, 0x85b5,
+ 0x85b6, 0x85b7, 0x85b8, 0x85b9, 0x85ba, 0x85bb, 0x85bc, 0x85bd,
+ 0x85be, 0x85bf, 0x85c0, 0x85c1, 0x85c2, 0x85c3, 0x85c4, 0x85c5,
+ 0x85c6, 0x85c7, 0x85c8, 0x85c9, 0x85ca, 0x85cb, 0x85cc, 0x85cd,
+ 0x85ce, 0x85cf, 0x85d0, 0x85d1, 0x85d2, 0x85d3, 0x85d4, 0x85d5,
+ 0x85d6, 0x85d7, 0x85d8, 0x85d9, 0x85da, 0x85db, 0x85dc, 0x85dd,
+ 0x85de, 0x85df, 0x85e0, 0x85e1, 0x85e2, 0x85e3, 0x85e4, 0x85e5,
+ 0x85e6, 0x85e7, 0x85e8, 0x85e9, 0x85ea, 0x85eb, 0x85ec, 0x85ed,
+ 0x85ee, 0x85ef, 0x85f0, 0x85f1, 0x85f2, 0x85f3, 0x85f4, 0x85f5,
+ 0x85f6, 0x85f7, 0x85f8, 0x85f9, 0x85fa, 0x85fb, 0x85fc, 0x85fd,
+ 0x85fe, 0x8640, 0x8641, 0x8642, 0x8643, 0x8644, 0x8645, 0x8646,
+ 0x8647, 0x8648, 0x8649, 0x864a, 0x864b, 0x864c, 0x864d, 0x864e,
+ 0x864f, 0x8650, 0x8651, 0x8652, 0x8653, 0x8654, 0x8655, 0x8656,
+ 0x8657, 0x8658, 0x8659, 0x865a, 0x865b, 0x865c, 0x865d, 0x865e,
+ 0x865f, 0x8660, 0x8661, 0x8662, 0x8663, 0x8664, 0x8665, 0x8666,
+ 0x8667, 0x8668, 0x8669, 0x866a, 0x866b, 0x866c, 0x866d, 0x866e,
+ 0x866f, 0x8670, 0x8671, 0x8672, 0x8673, 0x8674, 0x8675, 0x8676
+};
+
+static const unsigned short big5hkscs_from_unicode_f2[] = {
+ 0x8677, 0x8678, 0x8679, 0x867a, 0x867b, 0x867c, 0x867d, 0x867e,
+ 0x86a1, 0x86a2, 0x86a3, 0x86a4, 0x86a5, 0x86a6, 0x86a7, 0x86a8,
+ 0x86a9, 0x86aa, 0x86ab, 0x86ac, 0x86ad, 0x86ae, 0x86af, 0x86b0,
+ 0x86b1, 0x86b2, 0x86b3, 0x86b4, 0x86b5, 0x86b6, 0x86b7, 0x86b8,
+ 0x86b9, 0x86ba, 0x86bb, 0x86bc, 0x86bd, 0x86be, 0x86bf, 0x86c0,
+ 0x86c1, 0x86c2, 0x86c3, 0x86c4, 0x86c5, 0x86c6, 0x86c7, 0x86c8,
+ 0x86c9, 0x86ca, 0x86cb, 0x86cc, 0x86cd, 0x86ce, 0x86cf, 0x86d0,
+ 0x86d1, 0x86d2, 0x86d3, 0x86d4, 0x86d5, 0x86d6, 0x86d7, 0x86d8,
+ 0x86d9, 0x86da, 0x86db, 0x86dc, 0x86dd, 0x86de, 0x86df, 0x86e0,
+ 0x86e1, 0x86e2, 0x86e3, 0x86e4, 0x86e5, 0x86e6, 0x86e7, 0x86e8,
+ 0x86e9, 0x86ea, 0x86eb, 0x86ec, 0x86ed, 0x86ee, 0x86ef, 0x86f0,
+ 0x86f1, 0x86f2, 0x86f3, 0x86f4, 0x86f5, 0x86f6, 0x86f7, 0x86f8,
+ 0x86f9, 0x86fa, 0x86fb, 0x86fc, 0x86fd, 0x86fe, 0x8740, 0x8741,
+ 0x8742, 0x8743, 0x8744, 0x8745, 0x8746, 0x8747, 0x8748, 0x8749,
+ 0x874a, 0x874b, 0x874c, 0x874d, 0x874e, 0x874f, 0x8750, 0x8751,
+ 0x8752, 0x8753, 0x8754, 0x8755, 0x8756, 0x8757, 0x8758, 0x8759,
+ 0x875a, 0x875b, 0x875c, 0x875d, 0x875e, 0x875f, 0x8760, 0x8761,
+ 0x8762, 0x8763, 0x8764, 0x8765, 0x8766, 0x8767, 0x8768, 0x8769,
+ 0x876a, 0x876b, 0x876c, 0x876d, 0x876e, 0x876f, 0x8770, 0x8771,
+ 0x8772, 0x8773, 0x8774, 0x8775, 0x8776, 0x8777, 0x8778, 0x8779,
+ 0x877a, 0x877b, 0x877c, 0x877d, 0x877e, 0x87a1, 0x87a2, 0x87a3,
+ 0x87a4, 0x87a5, 0x87a6, 0x87a7, 0x87a8, 0x87a9, 0x87aa, 0x87ab,
+ 0x87ac, 0x87ad, 0x87ae, 0x87af, 0x87b0, 0x87b1, 0x87b2, 0x87b3,
+ 0x87b4, 0x87b5, 0x87b6, 0x87b7, 0x87b8, 0x87b9, 0x87ba, 0x87bb,
+ 0x87bc, 0x87bd, 0x87be, 0x87bf, 0x87c0, 0x87c1, 0x87c2, 0x87c3,
+ 0x87c4, 0x87c5, 0x87c6, 0x87c7, 0x87c8, 0x87c9, 0x87ca, 0x87cb,
+ 0x87cc, 0x87cd, 0x87ce, 0x87cf, 0x87d0, 0x87d1, 0x87d2, 0x87d3,
+ 0x87d4, 0x87d5, 0x87d6, 0x87d7, 0x87d8, 0x87d9, 0x87da, 0x87db,
+ 0x87dc, 0x87dd, 0x87de, 0x87df, 0x87e0, 0x87e1, 0x87e2, 0x87e3,
+ 0x87e4, 0x87e5, 0x87e6, 0x87e7, 0x87e8, 0x87e9, 0x87ea, 0x87eb,
+ 0x87ec, 0x87ed, 0x87ee, 0x87ef, 0x87f0, 0x87f1, 0x87f2, 0x87f3,
+ 0x87f4, 0x87f5, 0x87f6, 0x87f7, 0x87f8, 0x87f9, 0x87fa, 0x87fb
+};
+
+static const unsigned short big5hkscs_from_unicode_f3[] = {
+ 0x87fc, 0x87fd, 0x87fe, 0x8840, 0x8841, 0x8842, 0x8843, 0x8844,
+ 0x8845, 0x8846, 0x8847, 0x8848, 0x8849, 0x884a, 0x884b, 0x884c,
+ 0x884d, 0x884e, 0x884f, 0x8850, 0x8851, 0x8852, 0x8853, 0x8854,
+ 0x8855, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8862, 0x0000, 0x8864,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x88a3, 0x0000, 0x88a5, 0x0000,
+ 0x0000, 0x0000, 0x88a9, 0x88aa, 0x88ab, 0x88ac, 0x88ad, 0x88ae,
+ 0x88af, 0x88b0, 0x88b1, 0x88b2, 0x88b3, 0x88b4, 0x88b5, 0x88b6,
+ 0x88b7, 0x88b8, 0x88b9, 0x88ba, 0x88bb, 0x88bc, 0x88bd, 0x88be,
+ 0x88bf, 0x88c0, 0x88c1, 0x88c2, 0x88c3, 0x88c4, 0x88c5, 0x88c6,
+ 0x88c7, 0x88c8, 0x88c9, 0x88ca, 0x88cb, 0x88cc, 0x88cd, 0x88ce,
+ 0x88cf, 0x88d0, 0x88d1, 0x88d2, 0x88d3, 0x88d4, 0x88d5, 0x88d6,
+ 0x88d7, 0x88d8, 0x88d9, 0x88da, 0x88db, 0x88dc, 0x88dd, 0x88de,
+ 0x88df, 0x88e0, 0x88e1, 0x88e2, 0x88e3, 0x88e4, 0x88e5, 0x88e6,
+ 0x88e7, 0x88e8, 0x88e9, 0x88ea, 0x88eb, 0x88ec, 0x88ed, 0x88ee,
+ 0x88ef, 0x88f0, 0x88f1, 0x88f2, 0x88f3, 0x88f4, 0x88f5, 0x88f6,
+ 0x88f7, 0x88f8, 0x88f9, 0x88fa, 0x88fb, 0x88fc, 0x88fd, 0x88fe,
+ 0x8940, 0x8941, 0x8942, 0x0000, 0x8944, 0x8945, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x894a, 0x894b, 0x894c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x89a7, 0x89a8, 0x89a9,
+ 0x89aa, 0x0000, 0x0000, 0x0000, 0x0000, 0x89af, 0x0000, 0x0000,
+ 0x89b2, 0x89b3, 0x89b4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x89bb, 0x89bc, 0x0000, 0x89be, 0x0000, 0x89c0, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_f4[] = {
+ 0x0000, 0x0000, 0x89c4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x89ca, 0x89cb, 0x89cc, 0x89cd, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8a40, 0x0000, 0x8a42,
+ 0x8a43, 0x8a44, 0x8a45, 0x0000, 0x8a47, 0x0000, 0x8a49, 0x0000,
+ 0x8a4b, 0x8a4c, 0x0000, 0x8a4e, 0x0000, 0x8a50, 0x0000, 0x0000,
+ 0x8a53, 0x8a54, 0x8a55, 0x0000, 0x8a57, 0x8a58, 0x8a59, 0x8a5a,
+ 0x0000, 0x0000, 0x8a5d, 0x8a5e, 0x8a5f, 0x8a60, 0x8a61, 0x8a62,
+ 0x8a63, 0x8a64, 0x8a65, 0x8a66, 0x0000, 0x8a68, 0x8a69, 0x0000,
+ 0x0000, 0x8a6c, 0x0000, 0x0000, 0x8a6f, 0x8a70, 0x8a71, 0x8a72,
+ 0x0000, 0x0000, 0x8a75, 0x0000, 0x8a77, 0x0000, 0x0000, 0x8a7a,
+ 0x8a7b, 0x8a7c, 0x0000, 0x8a7e, 0x8aa1, 0x8aa2, 0x8aa3, 0x0000,
+ 0x8aa5, 0x8aa6, 0x0000, 0x8aa8, 0x8aa9, 0x8aaa, 0x8aab, 0x0000,
+ 0x8aad, 0x0000, 0x0000, 0x8ab0, 0x8ab1, 0x8ab2, 0x8ab3, 0x8ab4,
+ 0x8ab5, 0x8ab6, 0x0000, 0x0000, 0x0000, 0x8aba, 0x0000, 0x8abc,
+ 0x8abd, 0x0000, 0x0000, 0x8ac0, 0x0000, 0x0000, 0x8ac3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8ac8, 0x8ac9, 0x8aca, 0x8acb, 0x8acc,
+ 0x8acd, 0x8ace, 0x8acf, 0x0000, 0x0000, 0x8ad2, 0x0000, 0x8ad4,
+ 0x8ad5, 0x0000, 0x8ad7, 0x8ad8, 0x8ad9, 0x0000, 0x0000, 0x8adc,
+ 0x8add, 0x8ade, 0x8adf, 0x8ae0, 0x8ae1, 0x8ae2, 0x8ae3, 0x8ae4,
+ 0x8ae5, 0x8ae6, 0x0000, 0x8ae8, 0x8ae9, 0x8aea, 0x0000, 0x8aec,
+ 0x8aed, 0x8aee, 0x8aef, 0x0000, 0x8af1, 0x8af2, 0x8af3, 0x8af4,
+ 0x8af5, 0x8af6, 0x8af7, 0x8af8, 0x8af9, 0x8afa, 0x0000, 0x8afc,
+ 0x0000, 0x8afe, 0x8b40, 0x8b41, 0x8b42, 0x8b43, 0x8b44, 0x8b45,
+ 0x8b46, 0x0000, 0x8b48, 0x8b49, 0x8b4a, 0x8b4b, 0x8b4c, 0x8b4d,
+ 0x8b4e, 0x8b4f, 0x0000, 0x0000, 0x0000, 0x0000, 0x8b54, 0x8b55,
+ 0x0000, 0x0000, 0x8b58, 0x8b59, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8b5e, 0x0000, 0x0000, 0x0000, 0x8b62, 0x0000, 0x8b64, 0x8b65
+};
+
+static const unsigned short big5hkscs_from_unicode_f5[] = {
+ 0x8b66, 0x8b67, 0x0000, 0x8b69, 0x0000, 0x8b6b, 0x0000, 0x8b6d,
+ 0x8b6e, 0x8b6f, 0x8b70, 0x8b71, 0x8b72, 0x8b73, 0x8b74, 0x8b75,
+ 0x8b76, 0x8b77, 0x0000, 0x8b79, 0x8b7a, 0x8b7b, 0x8b7c, 0x0000,
+ 0x8b7e, 0x8ba1, 0x8ba2, 0x8ba3, 0x8ba4, 0x8ba5, 0x0000, 0x8ba7,
+ 0x8ba8, 0x8ba9, 0x8baa, 0x8bab, 0x8bac, 0x8bad, 0x8bae, 0x0000,
+ 0x0000, 0x0000, 0x8bb2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8bbb, 0x8bbc, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8bc2, 0x8bc3, 0x0000, 0x8bc5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8bd6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8bdb, 0x0000, 0x8bdd, 0x8bde, 0x0000,
+ 0x0000, 0x8be1, 0x8be2, 0x0000, 0x0000, 0x0000, 0x8be6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8bed, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8bf3, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8bfa, 0x0000, 0x0000, 0x0000, 0x8bfe, 0x0000,
+ 0x0000, 0x8c42, 0x8c43, 0x0000, 0x0000, 0x8c46, 0x0000, 0x0000,
+ 0x0000, 0x8c4a, 0x0000, 0x8c4c, 0x0000, 0x8c4e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8c54, 0x8c55, 0x0000, 0x8c57, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8c5c, 0x0000, 0x0000, 0x8c5f, 0x0000,
+ 0x0000, 0x8c62, 0x0000, 0x8c64, 0x8c65, 0x0000, 0x0000, 0x0000,
+ 0x8c69, 0x0000, 0x0000, 0x8c6c, 0x8c6d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x8c74, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x8c79, 0x0000, 0x0000, 0x0000, 0x8c7d, 0x0000, 0x8ca1, 0x0000,
+ 0x0000, 0x8ca4, 0x0000, 0x8ca6, 0x0000, 0x8ca8, 0x0000, 0x0000,
+ 0x8cab, 0x0000, 0x0000, 0x0000, 0x8caf, 0x8cb0, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8cb7, 0x0000, 0x8cb9, 0x0000,
+ 0x8cbb, 0x0000, 0x0000, 0x0000, 0x0000, 0x8cc0, 0x8cc1, 0x8cc2,
+ 0x0000, 0x0000, 0x0000, 0x8cc6, 0x8cc7, 0x8cc8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8ccd, 0x0000, 0x8ccf, 0x0000, 0x8cd1, 0x0000,
+ 0x8cd3, 0x0000, 0x8cd5, 0x8cd6, 0x8cd7, 0x8cd8, 0x0000, 0x8cda,
+ 0x8cdb, 0x0000, 0x8cdd, 0x8cde, 0x8cdf, 0x8ce0, 0x8ce1, 0x8ce2,
+ 0x8ce3, 0x8ce4, 0x8ce5, 0x8ce6, 0x8ce7, 0x8ce8, 0x8ce9, 0x8cea
+};
+
+static const unsigned short big5hkscs_from_unicode_f6[] = {
+ 0x8ceb, 0x8cec, 0x8ced, 0x8cee, 0x8cef, 0x8cf0, 0x8cf1, 0x8cf2,
+ 0x8cf3, 0x8cf4, 0x8cf5, 0x8cf6, 0x8cf7, 0x8cf8, 0x8cf9, 0x8cfa,
+ 0x8cfb, 0x8cfc, 0x8cfd, 0x8cfe, 0x8d40, 0x8d41, 0x8d42, 0x8d43,
+ 0x8d44, 0x8d45, 0x8d46, 0x8d47, 0x8d48, 0x8d49, 0x8d4a, 0x8d4b,
+ 0x8d4c, 0x8d4d, 0x8d4e, 0x8d4f, 0x8d50, 0x8d51, 0x8d52, 0x8d53,
+ 0x8d54, 0x8d55, 0x8d56, 0x8d57, 0x8d58, 0x8d59, 0x8d5a, 0x8d5b,
+ 0x8d5c, 0x8d5d, 0x8d5e, 0x8d5f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8de2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8dec, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8dfb, 0x0000, 0x0000,
+ 0x8dfe, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc6cf,
+ 0x0000, 0x0000, 0x0000, 0xc6d3, 0x0000, 0xc6d5, 0x0000, 0xc6d7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc6de, 0xc6df,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_f7[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc879, 0xc87a, 0x0000,
+ 0xc87c, 0x0000, 0xc87e, 0xc8a1, 0x0000, 0xc8a3, 0xc8a4, 0xc8a5,
+ 0xc8a6, 0xc8a7, 0xc8a8, 0xc8a9, 0xc8aa, 0xc8ab, 0xc8ac, 0xc8ad,
+ 0xc8ae, 0xc8af, 0xc8b0, 0xc8b1, 0xc8b2, 0xc8b3, 0xc8b4, 0xc8b5
+};
+
+static const unsigned short big5hkscs_from_unicode_f8[] = {
+ 0xc8b6, 0xc8b7, 0xc8b8, 0xc8b9, 0xc8ba, 0xc8bb, 0xc8bc, 0xc8bd,
+ 0xc8be, 0xc8bf, 0xc8c0, 0xc8c1, 0xc8c2, 0xc8c3, 0xc8c4, 0xc8c5,
+ 0xc8c6, 0xc8c7, 0xc8c8, 0xc8c9, 0xc8ca, 0xc8cb, 0xc8cc, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xc8f2, 0xc8f3, 0xc8f4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_f9[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8bf8,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_fa[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xc94a, 0xddfc, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_fe[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa14a, 0xa157, 0x0000, 0xa159, 0xa15b, 0xa15f, 0xa160, 0xa163,
+ 0xa164, 0xa167, 0xa168, 0xa16b, 0xa16c, 0xa16f, 0xa170, 0xa173,
+ 0xa174, 0xa177, 0xa178, 0xa17b, 0xa17c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa1c6, 0xa1c7, 0xa1ca, 0xa1cb, 0xa1c8, 0xa1c9, 0xa15c,
+ 0xa14d, 0xa14e, 0xa14f, 0x0000, 0xa151, 0xa152, 0xa153, 0xa154,
+ 0x0000, 0xa17d, 0xa17e, 0xa1a1, 0xa1a2, 0xa1a3, 0xa1a4, 0xa1cc,
+ 0xa1cd, 0xa1ce, 0xa1de, 0xa1df, 0xa1e0, 0xa1e1, 0xa1e2, 0x0000,
+ 0xa242, 0xa24c, 0xa24d, 0xa24e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short big5hkscs_from_unicode_ff[] = {
+ 0x0000, 0xa149, 0xc8d0, 0xa1ad, 0xa243, 0xa248, 0xa1ae, 0xc8cf,
+ 0xa15d, 0xa15e, 0xa1af, 0xa1cf, 0xa141, 0xa1d0, 0xa144, 0xa1fe,
+ 0xa2af, 0xa2b0, 0xa2b1, 0xa2b2, 0xa2b3, 0xa2b4, 0xa2b5, 0xa2b6,
+ 0xa2b7, 0xa2b8, 0xa147, 0xa146, 0xa1d5, 0xa1d7, 0xa1d6, 0xa148,
+ 0xa249, 0xa2cf, 0xa2d0, 0xa2d1, 0xa2d2, 0xa2d3, 0xa2d4, 0xa2d5,
+ 0xa2d6, 0xa2d7, 0xa2d8, 0xa2d9, 0xa2da, 0xa2db, 0xa2dc, 0xa2dd,
+ 0xa2de, 0xa2df, 0xa2e0, 0xa2e1, 0xa2e2, 0xa2e3, 0xa2e4, 0xa2e5,
+ 0xa2e6, 0xa2e7, 0xa2e8, 0xc6e4, 0xa240, 0xc6e5, 0x0000, 0xa1c4,
+ 0x0000, 0xa2e9, 0xa2ea, 0xa2eb, 0xa2ec, 0xa2ed, 0xa2ee, 0xa2ef,
+ 0xa2f0, 0xa2f1, 0xa2f2, 0xa2f3, 0xa2f4, 0xa2f5, 0xa2f6, 0xa2f7,
+ 0xa2f8, 0xa2f9, 0xa2fa, 0xa2fb, 0xa2fc, 0xa2fd, 0xa2fe, 0xa340,
+ 0xa341, 0xa342, 0xa343, 0xa161, 0xa155, 0xa162, 0xa1e3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xa246, 0xa247, 0xc8cd, 0xa1c3, 0xc8ce, 0xa244, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf9fe, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short * const big5hkscs_from_unicode_[] = {
+ big5hkscs_from_unicode_0,
+ big5hkscs_from_unicode_1,
+ big5hkscs_from_unicode_2,
+ big5hkscs_from_unicode_3,
+ big5hkscs_from_unicode_4,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ big5hkscs_from_unicode_1e,
+ u_allzeros,
+ big5hkscs_from_unicode_20,
+ big5hkscs_from_unicode_21,
+ big5hkscs_from_unicode_22,
+ u_allzeros,
+ big5hkscs_from_unicode_24,
+ big5hkscs_from_unicode_25,
+ big5hkscs_from_unicode_26,
+ big5hkscs_from_unicode_27,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ big5hkscs_from_unicode_2e,
+ big5hkscs_from_unicode_2f,
+ big5hkscs_from_unicode_30,
+ big5hkscs_from_unicode_31,
+ big5hkscs_from_unicode_32,
+ big5hkscs_from_unicode_33,
+ big5hkscs_from_unicode_34,
+ big5hkscs_from_unicode_35,
+ big5hkscs_from_unicode_36,
+ big5hkscs_from_unicode_37,
+ big5hkscs_from_unicode_38,
+ big5hkscs_from_unicode_39,
+ big5hkscs_from_unicode_3a,
+ big5hkscs_from_unicode_3b,
+ big5hkscs_from_unicode_3c,
+ big5hkscs_from_unicode_3d,
+ big5hkscs_from_unicode_3e,
+ big5hkscs_from_unicode_3f,
+ big5hkscs_from_unicode_40,
+ big5hkscs_from_unicode_41,
+ big5hkscs_from_unicode_42,
+ big5hkscs_from_unicode_43,
+ big5hkscs_from_unicode_44,
+ big5hkscs_from_unicode_45,
+ big5hkscs_from_unicode_46,
+ big5hkscs_from_unicode_47,
+ big5hkscs_from_unicode_48,
+ big5hkscs_from_unicode_49,
+ big5hkscs_from_unicode_4a,
+ big5hkscs_from_unicode_4b,
+ big5hkscs_from_unicode_4c,
+ big5hkscs_from_unicode_4d,
+ big5hkscs_from_unicode_4e,
+ big5hkscs_from_unicode_4f,
+ big5hkscs_from_unicode_50,
+ big5hkscs_from_unicode_51,
+ big5hkscs_from_unicode_52,
+ big5hkscs_from_unicode_53,
+ big5hkscs_from_unicode_54,
+ big5hkscs_from_unicode_55,
+ big5hkscs_from_unicode_56,
+ big5hkscs_from_unicode_57,
+ big5hkscs_from_unicode_58,
+ big5hkscs_from_unicode_59,
+ big5hkscs_from_unicode_5a,
+ big5hkscs_from_unicode_5b,
+ big5hkscs_from_unicode_5c,
+ big5hkscs_from_unicode_5d,
+ big5hkscs_from_unicode_5e,
+ big5hkscs_from_unicode_5f,
+ big5hkscs_from_unicode_60,
+ big5hkscs_from_unicode_61,
+ big5hkscs_from_unicode_62,
+ big5hkscs_from_unicode_63,
+ big5hkscs_from_unicode_64,
+ big5hkscs_from_unicode_65,
+ big5hkscs_from_unicode_66,
+ big5hkscs_from_unicode_67,
+ big5hkscs_from_unicode_68,
+ big5hkscs_from_unicode_69,
+ big5hkscs_from_unicode_6a,
+ big5hkscs_from_unicode_6b,
+ big5hkscs_from_unicode_6c,
+ big5hkscs_from_unicode_6d,
+ big5hkscs_from_unicode_6e,
+ big5hkscs_from_unicode_6f,
+ big5hkscs_from_unicode_70,
+ big5hkscs_from_unicode_71,
+ big5hkscs_from_unicode_72,
+ big5hkscs_from_unicode_73,
+ big5hkscs_from_unicode_74,
+ big5hkscs_from_unicode_75,
+ big5hkscs_from_unicode_76,
+ big5hkscs_from_unicode_77,
+ big5hkscs_from_unicode_78,
+ big5hkscs_from_unicode_79,
+ big5hkscs_from_unicode_7a,
+ big5hkscs_from_unicode_7b,
+ big5hkscs_from_unicode_7c,
+ big5hkscs_from_unicode_7d,
+ big5hkscs_from_unicode_7e,
+ big5hkscs_from_unicode_7f,
+ big5hkscs_from_unicode_80,
+ big5hkscs_from_unicode_81,
+ big5hkscs_from_unicode_82,
+ big5hkscs_from_unicode_83,
+ big5hkscs_from_unicode_84,
+ big5hkscs_from_unicode_85,
+ big5hkscs_from_unicode_86,
+ big5hkscs_from_unicode_87,
+ big5hkscs_from_unicode_88,
+ big5hkscs_from_unicode_89,
+ big5hkscs_from_unicode_8a,
+ big5hkscs_from_unicode_8b,
+ big5hkscs_from_unicode_8c,
+ big5hkscs_from_unicode_8d,
+ big5hkscs_from_unicode_8e,
+ big5hkscs_from_unicode_8f,
+ big5hkscs_from_unicode_90,
+ big5hkscs_from_unicode_91,
+ big5hkscs_from_unicode_92,
+ big5hkscs_from_unicode_93,
+ big5hkscs_from_unicode_94,
+ big5hkscs_from_unicode_95,
+ big5hkscs_from_unicode_96,
+ big5hkscs_from_unicode_97,
+ big5hkscs_from_unicode_98,
+ big5hkscs_from_unicode_99,
+ big5hkscs_from_unicode_9a,
+ big5hkscs_from_unicode_9b,
+ big5hkscs_from_unicode_9c,
+ big5hkscs_from_unicode_9d,
+ big5hkscs_from_unicode_9e,
+ big5hkscs_from_unicode_9f,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ big5hkscs_from_unicode_e0,
+ big5hkscs_from_unicode_e1,
+ big5hkscs_from_unicode_e2,
+ big5hkscs_from_unicode_e3,
+ big5hkscs_from_unicode_e4,
+ big5hkscs_from_unicode_e5,
+ big5hkscs_from_unicode_e6,
+ big5hkscs_from_unicode_e7,
+ big5hkscs_from_unicode_e8,
+ big5hkscs_from_unicode_e9,
+ big5hkscs_from_unicode_ea,
+ big5hkscs_from_unicode_eb,
+ big5hkscs_from_unicode_ec,
+ big5hkscs_from_unicode_ed,
+ big5hkscs_from_unicode_ee,
+ big5hkscs_from_unicode_ef,
+ big5hkscs_from_unicode_f0,
+ big5hkscs_from_unicode_f1,
+ big5hkscs_from_unicode_f2,
+ big5hkscs_from_unicode_f3,
+ big5hkscs_from_unicode_f4,
+ big5hkscs_from_unicode_f5,
+ big5hkscs_from_unicode_f6,
+ big5hkscs_from_unicode_f7,
+ big5hkscs_from_unicode_f8,
+ big5hkscs_from_unicode_f9,
+ big5hkscs_from_unicode_fa,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ big5hkscs_from_unicode_fe,
+ big5hkscs_from_unicode_ff
+};
+
+struct charmap2 big5hkscs_from_unicode = { 0, 255, (unsigned short **) big5hkscs_from_unicode_, (unichar_t *) unicode_from_big5hkscs };
+
+#endif
+
+const unichar_t unicode_from_ksc5601[] = {
+ 0x3164, 0x3001, 0x3002, 0x30fb, 0x2025, 0x22ef, 0x00a8, 0x3003,
+ 0x2013, 0x2014, 0x2016, 0xff3c, 0xff5e, 0x2018, 0x2019, 0x201c,
+ 0x201d, 0x3014, 0x3015, 0x3008, 0x3009, 0x300a, 0x300b, 0x300c,
+ 0x300d, 0x300e, 0x300f, 0x3010, 0x3011, 0x00b1, 0x00d7, 0x00f7,
+ 0x2260, 0x2264, 0x2265, 0x221e, 0x2234, 0x00b0, 0x2032, 0x2033,
+ 0x2103, 0x212b, 0xffe0, 0xffe1, 0xffe5, 0x2642, 0x2640, 0x2220,
+ 0x22a5, 0x2312, 0x2202, 0x2207, 0x2261, 0x2252, 0x00a7, 0x203b,
+ 0x2606, 0x2605, 0x25cb, 0x25cf, 0x25ce, 0x25c7, 0x25c6, 0x25a1,
+ 0x25a0, 0x25b3, 0x25b2, 0x25bd, 0x25bc, 0x2192, 0x2190, 0x2191,
+ 0x2193, 0x2194, 0x3013, 0x00ab, 0x00bb, 0x221a, 0x223d, 0x221d,
+ 0x2235, 0x222b, 0x222c, 0x2208, 0x220b, 0x2286, 0x2287, 0x2282,
+ 0x2283, 0x222a, 0x2229, 0x2227, 0x2228, 0xffe2, 0x21d2, 0x21d4,
+ 0x2200, 0x2203, 0x00b4, 0x02dc, 0x02c7, 0x02d8, 0x02dd, 0x02da,
+ 0x02d9, 0x00b8, 0x02db, 0x00a1, 0x00bf, 0x2236, 0x222e, 0x2211,
+ 0x220f, 0x00a4, 0x2109, 0x2030, 0x25c1, 0x25c0, 0x25b7, 0x25b6,
+ 0x2664, 0x2660, 0x2661, 0x2665, 0x2667, 0x2663, 0x25c9, 0x25c8,
+ 0x25a3, 0x25d0, 0x25d1, 0x2592, 0x25a4, 0x25a5, 0x25a8, 0x25a7,
+ 0x25a6, 0x25a9, 0x2668, 0x260f, 0x260e, 0x261c, 0x261e, 0x00b6,
+ 0x2020, 0x2021, 0x2195, 0x2197, 0x2199, 0x2196, 0x2198, 0x266d,
+ 0x2669, 0x266a, 0x266c, 0x327f, 0x321c, 0x2116, 0x33c7, 0x2122,
+ 0x33c2, 0x33d8, 0x2121, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xff01, 0xff02, 0xff03, 0xff04,
+ 0xff05, 0xff06, 0xff07, 0xff08, 0xff09, 0xff0a, 0xff0b, 0xff0c,
+ 0xff0d, 0xff0e, 0xff0f, 0xff10, 0xff11, 0xff12, 0xff13, 0xff14,
+ 0xff15, 0xff16, 0xff17, 0xff18, 0xff19, 0xff1a, 0xff1b, 0xff1c,
+ 0xff1d, 0xff1e, 0xff1f, 0xff20, 0xff21, 0xff22, 0xff23, 0xff24,
+ 0xff25, 0xff26, 0xff27, 0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c,
+ 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31, 0xff32, 0xff33, 0xff34,
+ 0xff35, 0xff36, 0xff37, 0xff38, 0xff39, 0xff3a, 0xff3b, 0xffe6,
+ 0xff3d, 0xff3e, 0xff3f, 0xff40, 0xff41, 0xff42, 0xff43, 0xff44,
+ 0xff45, 0xff46, 0xff47, 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c,
+ 0xff4d, 0xff4e, 0xff4f, 0xff50, 0xff51, 0xff52, 0xff53, 0xff54,
+ 0xff55, 0xff56, 0xff57, 0xff58, 0xff59, 0xff5a, 0xff5b, 0xff5c,
+ 0xff5d, 0xffe3, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136,
+ 0x3137, 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e,
+ 0x313f, 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146,
+ 0x3147, 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e,
+ 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156,
+ 0x3157, 0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e,
+ 0x315f, 0x3160, 0x3161, 0x3162, 0x3163, 0x0000, 0x3165, 0x3166,
+ 0x3167, 0x3168, 0x3169, 0x316a, 0x316b, 0x316c, 0x316d, 0x316e,
+ 0x316f, 0x3170, 0x3171, 0x3172, 0x3173, 0x3174, 0x3175, 0x3176,
+ 0x3177, 0x3178, 0x3179, 0x317a, 0x317b, 0x317c, 0x317d, 0x317e,
+ 0x317f, 0x3180, 0x3181, 0x3182, 0x3183, 0x3184, 0x3185, 0x3186,
+ 0x3187, 0x3188, 0x3189, 0x318a, 0x318b, 0x318c, 0x318d, 0x318e,
+ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
+ 0x2178, 0x2179, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2160,
+ 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168,
+ 0x2169, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398,
+ 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0,
+ 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8,
+ 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0,
+ 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2500, 0x2502,
+ 0x250c, 0x2510, 0x2518, 0x2514, 0x251c, 0x252c, 0x2524, 0x2534,
+ 0x253c, 0x2501, 0x2503, 0x250f, 0x2513, 0x251b, 0x2517, 0x2523,
+ 0x2533, 0x252b, 0x253b, 0x254b, 0x2520, 0x252f, 0x2528, 0x2537,
+ 0x253f, 0x251d, 0x2530, 0x2525, 0x2538, 0x2542, 0x2512, 0x2511,
+ 0x251a, 0x2519, 0x2516, 0x2515, 0x250e, 0x250d, 0x251e, 0x251f,
+ 0x2521, 0x2522, 0x2526, 0x2527, 0x2529, 0x252a, 0x252d, 0x252e,
+ 0x2531, 0x2532, 0x2535, 0x2536, 0x2539, 0x253a, 0x253d, 0x253e,
+ 0x2540, 0x2541, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547, 0x2548,
+ 0x2549, 0x254a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3395, 0x3396, 0x3397, 0x2113,
+ 0x3398, 0x33c4, 0x33a3, 0x33a4, 0x33a5, 0x33a6, 0x3399, 0x339a,
+ 0x339b, 0x339c, 0x339d, 0x339e, 0x339f, 0x33a0, 0x33a1, 0x33a2,
+ 0x33ca, 0x338d, 0x338e, 0x338f, 0x33cf, 0x3388, 0x3389, 0x33c8,
+ 0x33a7, 0x33a8, 0x33b0, 0x33b1, 0x33b2, 0x33b3, 0x33b4, 0x33b5,
+ 0x33b6, 0x33b7, 0x33b8, 0x33b9, 0x3380, 0x3381, 0x3382, 0x3383,
+ 0x3384, 0x33ba, 0x33bb, 0x33bc, 0x33bd, 0x33be, 0x33bf, 0x3390,
+ 0x3391, 0x3392, 0x3393, 0x3394, 0x2126, 0x33c0, 0x33c1, 0x338a,
+ 0x338b, 0x338c, 0x33d6, 0x33c5, 0x33ad, 0x33ae, 0x33af, 0x33db,
+ 0x33a9, 0x33aa, 0x33ab, 0x33ac, 0x33dd, 0x33d0, 0x33d3, 0x33c3,
+ 0x33c9, 0x33dc, 0x33c6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x00c6, 0x00d0, 0x00aa, 0x0126, 0x0000, 0x0132,
+ 0x0000, 0x013f, 0x0141, 0x00d8, 0x0152, 0x00ba, 0x00de, 0x0166,
+ 0x014a, 0x0000, 0x3260, 0x3261, 0x3262, 0x3263, 0x3264, 0x3265,
+ 0x3266, 0x3267, 0x3268, 0x3269, 0x326a, 0x326b, 0x326c, 0x326d,
+ 0x326e, 0x326f, 0x3270, 0x3271, 0x3272, 0x3273, 0x3274, 0x3275,
+ 0x3276, 0x3277, 0x3278, 0x3279, 0x327a, 0x327b, 0x24d0, 0x24d1,
+ 0x24d2, 0x24d3, 0x24d4, 0x24d5, 0x24d6, 0x24d7, 0x24d8, 0x24d9,
+ 0x24da, 0x24db, 0x24dc, 0x24dd, 0x24de, 0x24df, 0x24e0, 0x24e1,
+ 0x24e2, 0x24e3, 0x24e4, 0x24e5, 0x24e6, 0x24e7, 0x24e8, 0x24e9,
+ 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467,
+ 0x2468, 0x2469, 0x246a, 0x246b, 0x246c, 0x246d, 0x246e, 0x00bd,
+ 0x2153, 0x2154, 0x00bc, 0x00be, 0x215b, 0x215c, 0x215d, 0x215e,
+ 0x00e6, 0x0111, 0x00f0, 0x0127, 0x0131, 0x0133, 0x0138, 0x0140,
+ 0x0142, 0x00f8, 0x0153, 0x00df, 0x00fe, 0x0167, 0x014b, 0x0149,
+ 0x3200, 0x3201, 0x3202, 0x3203, 0x3204, 0x3205, 0x3206, 0x3207,
+ 0x3208, 0x3209, 0x320a, 0x320b, 0x320c, 0x320d, 0x320e, 0x320f,
+ 0x3210, 0x3211, 0x3212, 0x3213, 0x3214, 0x3215, 0x3216, 0x3217,
+ 0x3218, 0x3219, 0x321a, 0x321b, 0x249c, 0x249d, 0x249e, 0x249f,
+ 0x24a0, 0x24a1, 0x24a2, 0x24a3, 0x24a4, 0x24a5, 0x24a6, 0x24a7,
+ 0x24a8, 0x24a9, 0x24aa, 0x24ab, 0x24ac, 0x24ad, 0x24ae, 0x24af,
+ 0x24b0, 0x24b1, 0x24b2, 0x24b3, 0x24b4, 0x24b5, 0x2474, 0x2475,
+ 0x2476, 0x2477, 0x2478, 0x2479, 0x247a, 0x247b, 0x247c, 0x247d,
+ 0x247e, 0x247f, 0x2480, 0x2481, 0x2482, 0x00b9, 0x00b2, 0x00b3,
+ 0x2074, 0x207f, 0x2081, 0x2082, 0x2083, 0x2084, 0x3041, 0x3042,
+ 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049, 0x304a,
+ 0x304b, 0x304c, 0x304d, 0x304e, 0x304f, 0x3050, 0x3051, 0x3052,
+ 0x3053, 0x3054, 0x3055, 0x3056, 0x3057, 0x3058, 0x3059, 0x305a,
+ 0x305b, 0x305c, 0x305d, 0x305e, 0x305f, 0x3060, 0x3061, 0x3062,
+ 0x3063, 0x3064, 0x3065, 0x3066, 0x3067, 0x3068, 0x3069, 0x306a,
+ 0x306b, 0x306c, 0x306d, 0x306e, 0x306f, 0x3070, 0x3071, 0x3072,
+ 0x3073, 0x3074, 0x3075, 0x3076, 0x3077, 0x3078, 0x3079, 0x307a,
+ 0x307b, 0x307c, 0x307d, 0x307e, 0x307f, 0x3080, 0x3081, 0x3082,
+ 0x3083, 0x3084, 0x3085, 0x3086, 0x3087, 0x3088, 0x3089, 0x308a,
+ 0x308b, 0x308c, 0x308d, 0x308e, 0x308f, 0x3090, 0x3091, 0x3092,
+ 0x3093, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x30a1, 0x30a2, 0x30a3, 0x30a4,
+ 0x30a5, 0x30a6, 0x30a7, 0x30a8, 0x30a9, 0x30aa, 0x30ab, 0x30ac,
+ 0x30ad, 0x30ae, 0x30af, 0x30b0, 0x30b1, 0x30b2, 0x30b3, 0x30b4,
+ 0x30b5, 0x30b6, 0x30b7, 0x30b8, 0x30b9, 0x30ba, 0x30bb, 0x30bc,
+ 0x30bd, 0x30be, 0x30bf, 0x30c0, 0x30c1, 0x30c2, 0x30c3, 0x30c4,
+ 0x30c5, 0x30c6, 0x30c7, 0x30c8, 0x30c9, 0x30ca, 0x30cb, 0x30cc,
+ 0x30cd, 0x30ce, 0x30cf, 0x30d0, 0x30d1, 0x30d2, 0x30d3, 0x30d4,
+ 0x30d5, 0x30d6, 0x30d7, 0x30d8, 0x30d9, 0x30da, 0x30db, 0x30dc,
+ 0x30dd, 0x30de, 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e3, 0x30e4,
+ 0x30e5, 0x30e6, 0x30e7, 0x30e8, 0x30e9, 0x30ea, 0x30eb, 0x30ec,
+ 0x30ed, 0x30ee, 0x30ef, 0x30f0, 0x30f1, 0x30f2, 0x30f3, 0x30f4,
+ 0x30f5, 0x30f6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415,
+ 0x0401, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c,
+ 0x041d, 0x041e, 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424,
+ 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c,
+ 0x042d, 0x042e, 0x042f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435,
+ 0x0451, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c,
+ 0x043d, 0x043e, 0x043f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444,
+ 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c,
+ 0x044d, 0x044e, 0x044f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xac00, 0xac01, 0xac04, 0xac07, 0xac08, 0xac09,
+ 0xac0a, 0xac10, 0xac11, 0xac12, 0xac13, 0xac14, 0xac15, 0xac16,
+ 0xac17, 0xac19, 0xac1a, 0xac1b, 0xac1c, 0xac1d, 0xac20, 0xac24,
+ 0xac2c, 0xac2d, 0xac2f, 0xac30, 0xac31, 0xac38, 0xac39, 0xac3c,
+ 0xac40, 0xac4b, 0xac4d, 0xac54, 0xac58, 0xac5c, 0xac70, 0xac71,
+ 0xac74, 0xac77, 0xac78, 0xac7a, 0xac80, 0xac81, 0xac83, 0xac84,
+ 0xac85, 0xac86, 0xac89, 0xac8a, 0xac8b, 0xac8c, 0xac90, 0xac94,
+ 0xac9c, 0xac9d, 0xac9f, 0xaca0, 0xaca1, 0xaca8, 0xaca9, 0xacaa,
+ 0xacac, 0xacaf, 0xacb0, 0xacb8, 0xacb9, 0xacbb, 0xacbc, 0xacbd,
+ 0xacc1, 0xacc4, 0xacc8, 0xaccc, 0xacd5, 0xacd7, 0xace0, 0xace1,
+ 0xace4, 0xace7, 0xace8, 0xacea, 0xacec, 0xacef, 0xacf0, 0xacf1,
+ 0xacf3, 0xacf5, 0xacf6, 0xacfc, 0xacfd, 0xad00, 0xad04, 0xad06,
+ 0xad0c, 0xad0d, 0xad0f, 0xad11, 0xad18, 0xad1c, 0xad20, 0xad29,
+ 0xad2c, 0xad2d, 0xad34, 0xad35, 0xad38, 0xad3c, 0xad44, 0xad45,
+ 0xad47, 0xad49, 0xad50, 0xad54, 0xad58, 0xad61, 0xad63, 0xad6c,
+ 0xad6d, 0xad70, 0xad73, 0xad74, 0xad75, 0xad76, 0xad7b, 0xad7c,
+ 0xad7d, 0xad7f, 0xad81, 0xad82, 0xad88, 0xad89, 0xad8c, 0xad90,
+ 0xad9c, 0xad9d, 0xada4, 0xadb7, 0xadc0, 0xadc1, 0xadc4, 0xadc8,
+ 0xadd0, 0xadd1, 0xadd3, 0xaddc, 0xade0, 0xade4, 0xadf8, 0xadf9,
+ 0xadfc, 0xadff, 0xae00, 0xae01, 0xae08, 0xae09, 0xae0b, 0xae0d,
+ 0xae14, 0xae30, 0xae31, 0xae34, 0xae37, 0xae38, 0xae3a, 0xae40,
+ 0xae41, 0xae43, 0xae45, 0xae46, 0xae4a, 0xae4c, 0xae4d, 0xae4e,
+ 0xae50, 0xae54, 0xae56, 0xae5c, 0xae5d, 0xae5f, 0xae60, 0xae61,
+ 0xae65, 0xae68, 0xae69, 0xae6c, 0xae70, 0xae78, 0xae79, 0xae7b,
+ 0xae7c, 0xae7d, 0xae84, 0xae85, 0xae8c, 0xaebc, 0xaebd, 0xaebe,
+ 0xaec0, 0xaec4, 0xaecc, 0xaecd, 0xaecf, 0xaed0, 0xaed1, 0xaed8,
+ 0xaed9, 0xaedc, 0xaee8, 0xaeeb, 0xaeed, 0xaef4, 0xaef8, 0xaefc,
+ 0xaf07, 0xaf08, 0xaf0d, 0xaf10, 0xaf2c, 0xaf2d, 0xaf30, 0xaf32,
+ 0xaf34, 0xaf3c, 0xaf3d, 0xaf3f, 0xaf41, 0xaf42, 0xaf43, 0xaf48,
+ 0xaf49, 0xaf50, 0xaf5c, 0xaf5d, 0xaf64, 0xaf65, 0xaf79, 0xaf80,
+ 0xaf84, 0xaf88, 0xaf90, 0xaf91, 0xaf95, 0xaf9c, 0xafb8, 0xafb9,
+ 0xafbc, 0xafc0, 0xafc7, 0xafc8, 0xafc9, 0xafcb, 0xafcd, 0xafce,
+ 0xafd4, 0xafdc, 0xafe8, 0xafe9, 0xaff0, 0xaff1, 0xaff4, 0xaff8,
+ 0xb000, 0xb001, 0xb004, 0xb00c, 0xb010, 0xb014, 0xb01c, 0xb01d,
+ 0xb028, 0xb044, 0xb045, 0xb048, 0xb04a, 0xb04c, 0xb04e, 0xb053,
+ 0xb054, 0xb055, 0xb057, 0xb059, 0xb05d, 0xb07c, 0xb07d, 0xb080,
+ 0xb084, 0xb08c, 0xb08d, 0xb08f, 0xb091, 0xb098, 0xb099, 0xb09a,
+ 0xb09c, 0xb09f, 0xb0a0, 0xb0a1, 0xb0a2, 0xb0a8, 0xb0a9, 0xb0ab,
+ 0xb0ac, 0xb0ad, 0xb0ae, 0xb0af, 0xb0b1, 0xb0b3, 0xb0b4, 0xb0b5,
+ 0xb0b8, 0xb0bc, 0xb0c4, 0xb0c5, 0xb0c7, 0xb0c8, 0xb0c9, 0xb0d0,
+ 0xb0d1, 0xb0d4, 0xb0d8, 0xb0e0, 0xb0e5, 0xb108, 0xb109, 0xb10b,
+ 0xb10c, 0xb110, 0xb112, 0xb113, 0xb118, 0xb119, 0xb11b, 0xb11c,
+ 0xb11d, 0xb123, 0xb124, 0xb125, 0xb128, 0xb12c, 0xb134, 0xb135,
+ 0xb137, 0xb138, 0xb139, 0xb140, 0xb141, 0xb144, 0xb148, 0xb150,
+ 0xb151, 0xb154, 0xb155, 0xb158, 0xb15c, 0xb160, 0xb178, 0xb179,
+ 0xb17c, 0xb180, 0xb182, 0xb188, 0xb189, 0xb18b, 0xb18d, 0xb192,
+ 0xb193, 0xb194, 0xb198, 0xb19c, 0xb1a8, 0xb1cc, 0xb1d0, 0xb1d4,
+ 0xb1dc, 0xb1dd, 0xb1df, 0xb1e8, 0xb1e9, 0xb1ec, 0xb1f0, 0xb1f9,
+ 0xb1fb, 0xb1fd, 0xb204, 0xb205, 0xb208, 0xb20b, 0xb20c, 0xb214,
+ 0xb215, 0xb217, 0xb219, 0xb220, 0xb234, 0xb23c, 0xb258, 0xb25c,
+ 0xb260, 0xb268, 0xb269, 0xb274, 0xb275, 0xb27c, 0xb284, 0xb285,
+ 0xb289, 0xb290, 0xb291, 0xb294, 0xb298, 0xb299, 0xb29a, 0xb2a0,
+ 0xb2a1, 0xb2a3, 0xb2a5, 0xb2a6, 0xb2aa, 0xb2ac, 0xb2b0, 0xb2b4,
+ 0xb2c8, 0xb2c9, 0xb2cc, 0xb2d0, 0xb2d2, 0xb2d8, 0xb2d9, 0xb2db,
+ 0xb2dd, 0xb2e2, 0xb2e4, 0xb2e5, 0xb2e6, 0xb2e8, 0xb2eb, 0xb2ec,
+ 0xb2ed, 0xb2ee, 0xb2ef, 0xb2f3, 0xb2f4, 0xb2f5, 0xb2f7, 0xb2f8,
+ 0xb2f9, 0xb2fa, 0xb2fb, 0xb2ff, 0xb300, 0xb301, 0xb304, 0xb308,
+ 0xb310, 0xb311, 0xb313, 0xb314, 0xb315, 0xb31c, 0xb354, 0xb355,
+ 0xb356, 0xb358, 0xb35b, 0xb35c, 0xb35e, 0xb35f, 0xb364, 0xb365,
+ 0xb367, 0xb369, 0xb36b, 0xb36e, 0xb370, 0xb371, 0xb374, 0xb378,
+ 0xb380, 0xb381, 0xb383, 0xb384, 0xb385, 0xb38c, 0xb390, 0xb394,
+ 0xb3a0, 0xb3a1, 0xb3a8, 0xb3ac, 0xb3c4, 0xb3c5, 0xb3c8, 0xb3cb,
+ 0xb3cc, 0xb3ce, 0xb3d0, 0xb3d4, 0xb3d5, 0xb3d7, 0xb3d9, 0xb3db,
+ 0xb3dd, 0xb3e0, 0xb3e4, 0xb3e8, 0xb3fc, 0xb410, 0xb418, 0xb41c,
+ 0xb420, 0xb428, 0xb429, 0xb42b, 0xb434, 0xb450, 0xb451, 0xb454,
+ 0xb458, 0xb460, 0xb461, 0xb463, 0xb465, 0xb46c, 0xb480, 0xb488,
+ 0xb49d, 0xb4a4, 0xb4a8, 0xb4ac, 0xb4b5, 0xb4b7, 0xb4b9, 0xb4c0,
+ 0xb4c4, 0xb4c8, 0xb4d0, 0xb4d5, 0xb4dc, 0xb4dd, 0xb4e0, 0xb4e3,
+ 0xb4e4, 0xb4e6, 0xb4ec, 0xb4ed, 0xb4ef, 0xb4f1, 0xb4f8, 0xb514,
+ 0xb515, 0xb518, 0xb51b, 0xb51c, 0xb524, 0xb525, 0xb527, 0xb528,
+ 0xb529, 0xb52a, 0xb530, 0xb531, 0xb534, 0xb538, 0xb540, 0xb541,
+ 0xb543, 0xb544, 0xb545, 0xb54b, 0xb54c, 0xb54d, 0xb550, 0xb554,
+ 0xb55c, 0xb55d, 0xb55f, 0xb560, 0xb561, 0xb5a0, 0xb5a1, 0xb5a4,
+ 0xb5a8, 0xb5aa, 0xb5ab, 0xb5b0, 0xb5b1, 0xb5b3, 0xb5b4, 0xb5b5,
+ 0xb5bb, 0xb5bc, 0xb5bd, 0xb5c0, 0xb5c4, 0xb5cc, 0xb5cd, 0xb5cf,
+ 0xb5d0, 0xb5d1, 0xb5d8, 0xb5ec, 0xb610, 0xb611, 0xb614, 0xb618,
+ 0xb625, 0xb62c, 0xb634, 0xb648, 0xb664, 0xb668, 0xb69c, 0xb69d,
+ 0xb6a0, 0xb6a4, 0xb6ab, 0xb6ac, 0xb6b1, 0xb6d4, 0xb6f0, 0xb6f4,
+ 0xb6f8, 0xb700, 0xb701, 0xb705, 0xb728, 0xb729, 0xb72c, 0xb72f,
+ 0xb730, 0xb738, 0xb739, 0xb73b, 0xb744, 0xb748, 0xb74c, 0xb754,
+ 0xb755, 0xb760, 0xb764, 0xb768, 0xb770, 0xb771, 0xb773, 0xb775,
+ 0xb77c, 0xb77d, 0xb780, 0xb784, 0xb78c, 0xb78d, 0xb78f, 0xb790,
+ 0xb791, 0xb792, 0xb796, 0xb797, 0xb798, 0xb799, 0xb79c, 0xb7a0,
+ 0xb7a8, 0xb7a9, 0xb7ab, 0xb7ac, 0xb7ad, 0xb7b4, 0xb7b5, 0xb7b8,
+ 0xb7c7, 0xb7c9, 0xb7ec, 0xb7ed, 0xb7f0, 0xb7f4, 0xb7fc, 0xb7fd,
+ 0xb7ff, 0xb800, 0xb801, 0xb807, 0xb808, 0xb809, 0xb80c, 0xb810,
+ 0xb818, 0xb819, 0xb81b, 0xb81d, 0xb824, 0xb825, 0xb828, 0xb82c,
+ 0xb834, 0xb835, 0xb837, 0xb838, 0xb839, 0xb840, 0xb844, 0xb851,
+ 0xb853, 0xb85c, 0xb85d, 0xb860, 0xb864, 0xb86c, 0xb86d, 0xb86f,
+ 0xb871, 0xb878, 0xb87c, 0xb88d, 0xb8a8, 0xb8b0, 0xb8b4, 0xb8b8,
+ 0xb8c0, 0xb8c1, 0xb8c3, 0xb8c5, 0xb8cc, 0xb8d0, 0xb8d4, 0xb8dd,
+ 0xb8df, 0xb8e1, 0xb8e8, 0xb8e9, 0xb8ec, 0xb8f0, 0xb8f8, 0xb8f9,
+ 0xb8fb, 0xb8fd, 0xb904, 0xb918, 0xb920, 0xb93c, 0xb93d, 0xb940,
+ 0xb944, 0xb94c, 0xb94f, 0xb951, 0xb958, 0xb959, 0xb95c, 0xb960,
+ 0xb968, 0xb969, 0xb96b, 0xb96d, 0xb974, 0xb975, 0xb978, 0xb97c,
+ 0xb984, 0xb985, 0xb987, 0xb989, 0xb98a, 0xb98d, 0xb98e, 0xb9ac,
+ 0xb9ad, 0xb9b0, 0xb9b4, 0xb9bc, 0xb9bd, 0xb9bf, 0xb9c1, 0xb9c8,
+ 0xb9c9, 0xb9cc, 0xb9ce, 0xb9cf, 0xb9d0, 0xb9d1, 0xb9d2, 0xb9d8,
+ 0xb9d9, 0xb9db, 0xb9dd, 0xb9de, 0xb9e1, 0xb9e3, 0xb9e4, 0xb9e5,
+ 0xb9e8, 0xb9ec, 0xb9f4, 0xb9f5, 0xb9f7, 0xb9f8, 0xb9f9, 0xb9fa,
+ 0xba00, 0xba01, 0xba08, 0xba15, 0xba38, 0xba39, 0xba3c, 0xba40,
+ 0xba42, 0xba48, 0xba49, 0xba4b, 0xba4d, 0xba4e, 0xba53, 0xba54,
+ 0xba55, 0xba58, 0xba5c, 0xba64, 0xba65, 0xba67, 0xba68, 0xba69,
+ 0xba70, 0xba71, 0xba74, 0xba78, 0xba83, 0xba84, 0xba85, 0xba87,
+ 0xba8c, 0xbaa8, 0xbaa9, 0xbaab, 0xbaac, 0xbab0, 0xbab2, 0xbab8,
+ 0xbab9, 0xbabb, 0xbabd, 0xbac4, 0xbac8, 0xbad8, 0xbad9, 0xbafc,
+ 0xbb00, 0xbb04, 0xbb0d, 0xbb0f, 0xbb11, 0xbb18, 0xbb1c, 0xbb20,
+ 0xbb29, 0xbb2b, 0xbb34, 0xbb35, 0xbb36, 0xbb38, 0xbb3b, 0xbb3c,
+ 0xbb3d, 0xbb3e, 0xbb44, 0xbb45, 0xbb47, 0xbb49, 0xbb4d, 0xbb4f,
+ 0xbb50, 0xbb54, 0xbb58, 0xbb61, 0xbb63, 0xbb6c, 0xbb88, 0xbb8c,
+ 0xbb90, 0xbba4, 0xbba8, 0xbbac, 0xbbb4, 0xbbb7, 0xbbc0, 0xbbc4,
+ 0xbbc8, 0xbbd0, 0xbbd3, 0xbbf8, 0xbbf9, 0xbbfc, 0xbbff, 0xbc00,
+ 0xbc02, 0xbc08, 0xbc09, 0xbc0b, 0xbc0c, 0xbc0d, 0xbc0f, 0xbc11,
+ 0xbc14, 0xbc15, 0xbc16, 0xbc17, 0xbc18, 0xbc1b, 0xbc1c, 0xbc1d,
+ 0xbc1e, 0xbc1f, 0xbc24, 0xbc25, 0xbc27, 0xbc29, 0xbc2d, 0xbc30,
+ 0xbc31, 0xbc34, 0xbc38, 0xbc40, 0xbc41, 0xbc43, 0xbc44, 0xbc45,
+ 0xbc49, 0xbc4c, 0xbc4d, 0xbc50, 0xbc5d, 0xbc84, 0xbc85, 0xbc88,
+ 0xbc8b, 0xbc8c, 0xbc8e, 0xbc94, 0xbc95, 0xbc97, 0xbc99, 0xbc9a,
+ 0xbca0, 0xbca1, 0xbca4, 0xbca7, 0xbca8, 0xbcb0, 0xbcb1, 0xbcb3,
+ 0xbcb4, 0xbcb5, 0xbcbc, 0xbcbd, 0xbcc0, 0xbcc4, 0xbccd, 0xbccf,
+ 0xbcd0, 0xbcd1, 0xbcd5, 0xbcd8, 0xbcdc, 0xbcf4, 0xbcf5, 0xbcf6,
+ 0xbcf8, 0xbcfc, 0xbd04, 0xbd05, 0xbd07, 0xbd09, 0xbd10, 0xbd14,
+ 0xbd24, 0xbd2c, 0xbd40, 0xbd48, 0xbd49, 0xbd4c, 0xbd50, 0xbd58,
+ 0xbd59, 0xbd64, 0xbd68, 0xbd80, 0xbd81, 0xbd84, 0xbd87, 0xbd88,
+ 0xbd89, 0xbd8a, 0xbd90, 0xbd91, 0xbd93, 0xbd95, 0xbd99, 0xbd9a,
+ 0xbd9c, 0xbda4, 0xbdb0, 0xbdb8, 0xbdd4, 0xbdd5, 0xbdd8, 0xbddc,
+ 0xbde9, 0xbdf0, 0xbdf4, 0xbdf8, 0xbe00, 0xbe03, 0xbe05, 0xbe0c,
+ 0xbe0d, 0xbe10, 0xbe14, 0xbe1c, 0xbe1d, 0xbe1f, 0xbe44, 0xbe45,
+ 0xbe48, 0xbe4c, 0xbe4e, 0xbe54, 0xbe55, 0xbe57, 0xbe59, 0xbe5a,
+ 0xbe5b, 0xbe60, 0xbe61, 0xbe64, 0xbe68, 0xbe6a, 0xbe70, 0xbe71,
+ 0xbe73, 0xbe74, 0xbe75, 0xbe7b, 0xbe7c, 0xbe7d, 0xbe80, 0xbe84,
+ 0xbe8c, 0xbe8d, 0xbe8f, 0xbe90, 0xbe91, 0xbe98, 0xbe99, 0xbea8,
+ 0xbed0, 0xbed1, 0xbed4, 0xbed7, 0xbed8, 0xbee0, 0xbee3, 0xbee4,
+ 0xbee5, 0xbeec, 0xbf01, 0xbf08, 0xbf09, 0xbf18, 0xbf19, 0xbf1b,
+ 0xbf1c, 0xbf1d, 0xbf40, 0xbf41, 0xbf44, 0xbf48, 0xbf50, 0xbf51,
+ 0xbf55, 0xbf94, 0xbfb0, 0xbfc5, 0xbfcc, 0xbfcd, 0xbfd0, 0xbfd4,
+ 0xbfdc, 0xbfdf, 0xbfe1, 0xc03c, 0xc051, 0xc058, 0xc05c, 0xc060,
+ 0xc068, 0xc069, 0xc090, 0xc091, 0xc094, 0xc098, 0xc0a0, 0xc0a1,
+ 0xc0a3, 0xc0a5, 0xc0ac, 0xc0ad, 0xc0af, 0xc0b0, 0xc0b3, 0xc0b4,
+ 0xc0b5, 0xc0b6, 0xc0bc, 0xc0bd, 0xc0bf, 0xc0c0, 0xc0c1, 0xc0c5,
+ 0xc0c8, 0xc0c9, 0xc0cc, 0xc0d0, 0xc0d8, 0xc0d9, 0xc0db, 0xc0dc,
+ 0xc0dd, 0xc0e4, 0xc0e5, 0xc0e8, 0xc0ec, 0xc0f4, 0xc0f5, 0xc0f7,
+ 0xc0f9, 0xc100, 0xc104, 0xc108, 0xc110, 0xc115, 0xc11c, 0xc11d,
+ 0xc11e, 0xc11f, 0xc120, 0xc123, 0xc124, 0xc126, 0xc127, 0xc12c,
+ 0xc12d, 0xc12f, 0xc130, 0xc131, 0xc136, 0xc138, 0xc139, 0xc13c,
+ 0xc140, 0xc148, 0xc149, 0xc14b, 0xc14c, 0xc14d, 0xc154, 0xc155,
+ 0xc158, 0xc15c, 0xc164, 0xc165, 0xc167, 0xc168, 0xc169, 0xc170,
+ 0xc174, 0xc178, 0xc185, 0xc18c, 0xc18d, 0xc18e, 0xc190, 0xc194,
+ 0xc196, 0xc19c, 0xc19d, 0xc19f, 0xc1a1, 0xc1a5, 0xc1a8, 0xc1a9,
+ 0xc1ac, 0xc1b0, 0xc1bd, 0xc1c4, 0xc1c8, 0xc1cc, 0xc1d4, 0xc1d7,
+ 0xc1d8, 0xc1e0, 0xc1e4, 0xc1e8, 0xc1f0, 0xc1f1, 0xc1f3, 0xc1fc,
+ 0xc1fd, 0xc200, 0xc204, 0xc20c, 0xc20d, 0xc20f, 0xc211, 0xc218,
+ 0xc219, 0xc21c, 0xc21f, 0xc220, 0xc228, 0xc229, 0xc22b, 0xc22d,
+ 0xc22f, 0xc231, 0xc232, 0xc234, 0xc248, 0xc250, 0xc251, 0xc254,
+ 0xc258, 0xc260, 0xc265, 0xc26c, 0xc26d, 0xc270, 0xc274, 0xc27c,
+ 0xc27d, 0xc27f, 0xc281, 0xc288, 0xc289, 0xc290, 0xc298, 0xc29b,
+ 0xc29d, 0xc2a4, 0xc2a5, 0xc2a8, 0xc2ac, 0xc2ad, 0xc2b4, 0xc2b5,
+ 0xc2b7, 0xc2b9, 0xc2dc, 0xc2dd, 0xc2e0, 0xc2e3, 0xc2e4, 0xc2eb,
+ 0xc2ec, 0xc2ed, 0xc2ef, 0xc2f1, 0xc2f6, 0xc2f8, 0xc2f9, 0xc2fb,
+ 0xc2fc, 0xc300, 0xc308, 0xc309, 0xc30c, 0xc30d, 0xc313, 0xc314,
+ 0xc315, 0xc318, 0xc31c, 0xc324, 0xc325, 0xc328, 0xc329, 0xc345,
+ 0xc368, 0xc369, 0xc36c, 0xc370, 0xc372, 0xc378, 0xc379, 0xc37c,
+ 0xc37d, 0xc384, 0xc388, 0xc38c, 0xc3c0, 0xc3d8, 0xc3d9, 0xc3dc,
+ 0xc3df, 0xc3e0, 0xc3e2, 0xc3e8, 0xc3e9, 0xc3ed, 0xc3f4, 0xc3f5,
+ 0xc3f8, 0xc408, 0xc410, 0xc424, 0xc42c, 0xc430, 0xc434, 0xc43c,
+ 0xc43d, 0xc448, 0xc464, 0xc465, 0xc468, 0xc46c, 0xc474, 0xc475,
+ 0xc479, 0xc480, 0xc494, 0xc49c, 0xc4b8, 0xc4bc, 0xc4e9, 0xc4f0,
+ 0xc4f1, 0xc4f4, 0xc4f8, 0xc4fa, 0xc4ff, 0xc500, 0xc501, 0xc50c,
+ 0xc510, 0xc514, 0xc51c, 0xc528, 0xc529, 0xc52c, 0xc530, 0xc538,
+ 0xc539, 0xc53b, 0xc53d, 0xc544, 0xc545, 0xc548, 0xc549, 0xc54a,
+ 0xc54c, 0xc54d, 0xc54e, 0xc553, 0xc554, 0xc555, 0xc557, 0xc558,
+ 0xc559, 0xc55d, 0xc55e, 0xc560, 0xc561, 0xc564, 0xc568, 0xc570,
+ 0xc571, 0xc573, 0xc574, 0xc575, 0xc57c, 0xc57d, 0xc580, 0xc584,
+ 0xc587, 0xc58c, 0xc58d, 0xc58f, 0xc591, 0xc595, 0xc597, 0xc598,
+ 0xc59c, 0xc5a0, 0xc5a9, 0xc5b4, 0xc5b5, 0xc5b8, 0xc5b9, 0xc5bb,
+ 0xc5bc, 0xc5bd, 0xc5be, 0xc5c4, 0xc5c5, 0xc5c6, 0xc5c7, 0xc5c8,
+ 0xc5c9, 0xc5ca, 0xc5cc, 0xc5ce, 0xc5d0, 0xc5d1, 0xc5d4, 0xc5d8,
+ 0xc5e0, 0xc5e1, 0xc5e3, 0xc5e5, 0xc5ec, 0xc5ed, 0xc5ee, 0xc5f0,
+ 0xc5f4, 0xc5f6, 0xc5f7, 0xc5fc, 0xc5fd, 0xc5fe, 0xc5ff, 0xc600,
+ 0xc601, 0xc605, 0xc606, 0xc607, 0xc608, 0xc60c, 0xc610, 0xc618,
+ 0xc619, 0xc61b, 0xc61c, 0xc624, 0xc625, 0xc628, 0xc62c, 0xc62d,
+ 0xc62e, 0xc630, 0xc633, 0xc634, 0xc635, 0xc637, 0xc639, 0xc63b,
+ 0xc640, 0xc641, 0xc644, 0xc648, 0xc650, 0xc651, 0xc653, 0xc654,
+ 0xc655, 0xc65c, 0xc65d, 0xc660, 0xc66c, 0xc66f, 0xc671, 0xc678,
+ 0xc679, 0xc67c, 0xc680, 0xc688, 0xc689, 0xc68b, 0xc68d, 0xc694,
+ 0xc695, 0xc698, 0xc69c, 0xc6a4, 0xc6a5, 0xc6a7, 0xc6a9, 0xc6b0,
+ 0xc6b1, 0xc6b4, 0xc6b8, 0xc6b9, 0xc6ba, 0xc6c0, 0xc6c1, 0xc6c3,
+ 0xc6c5, 0xc6cc, 0xc6cd, 0xc6d0, 0xc6d4, 0xc6dc, 0xc6dd, 0xc6e0,
+ 0xc6e1, 0xc6e8, 0xc6e9, 0xc6ec, 0xc6f0, 0xc6f8, 0xc6f9, 0xc6fd,
+ 0xc704, 0xc705, 0xc708, 0xc70c, 0xc714, 0xc715, 0xc717, 0xc719,
+ 0xc720, 0xc721, 0xc724, 0xc728, 0xc730, 0xc731, 0xc733, 0xc735,
+ 0xc737, 0xc73c, 0xc73d, 0xc740, 0xc744, 0xc74a, 0xc74c, 0xc74d,
+ 0xc74f, 0xc751, 0xc752, 0xc753, 0xc754, 0xc755, 0xc756, 0xc757,
+ 0xc758, 0xc75c, 0xc760, 0xc768, 0xc76b, 0xc774, 0xc775, 0xc778,
+ 0xc77c, 0xc77d, 0xc77e, 0xc783, 0xc784, 0xc785, 0xc787, 0xc788,
+ 0xc789, 0xc78a, 0xc78e, 0xc790, 0xc791, 0xc794, 0xc796, 0xc797,
+ 0xc798, 0xc79a, 0xc7a0, 0xc7a1, 0xc7a3, 0xc7a4, 0xc7a5, 0xc7a6,
+ 0xc7ac, 0xc7ad, 0xc7b0, 0xc7b4, 0xc7bc, 0xc7bd, 0xc7bf, 0xc7c0,
+ 0xc7c1, 0xc7c8, 0xc7c9, 0xc7cc, 0xc7ce, 0xc7d0, 0xc7d8, 0xc7dd,
+ 0xc7e4, 0xc7e8, 0xc7ec, 0xc800, 0xc801, 0xc804, 0xc808, 0xc80a,
+ 0xc810, 0xc811, 0xc813, 0xc815, 0xc816, 0xc81c, 0xc81d, 0xc820,
+ 0xc824, 0xc82c, 0xc82d, 0xc82f, 0xc831, 0xc838, 0xc83c, 0xc840,
+ 0xc848, 0xc849, 0xc84c, 0xc84d, 0xc854, 0xc870, 0xc871, 0xc874,
+ 0xc878, 0xc87a, 0xc880, 0xc881, 0xc883, 0xc885, 0xc886, 0xc887,
+ 0xc88b, 0xc88c, 0xc88d, 0xc894, 0xc89d, 0xc89f, 0xc8a1, 0xc8a8,
+ 0xc8bc, 0xc8bd, 0xc8c4, 0xc8c8, 0xc8cc, 0xc8d4, 0xc8d5, 0xc8d7,
+ 0xc8d9, 0xc8e0, 0xc8e1, 0xc8e4, 0xc8f5, 0xc8fc, 0xc8fd, 0xc900,
+ 0xc904, 0xc905, 0xc906, 0xc90c, 0xc90d, 0xc90f, 0xc911, 0xc918,
+ 0xc92c, 0xc934, 0xc950, 0xc951, 0xc954, 0xc958, 0xc960, 0xc961,
+ 0xc963, 0xc96c, 0xc970, 0xc974, 0xc97c, 0xc988, 0xc989, 0xc98c,
+ 0xc990, 0xc998, 0xc999, 0xc99b, 0xc99d, 0xc9c0, 0xc9c1, 0xc9c4,
+ 0xc9c7, 0xc9c8, 0xc9ca, 0xc9d0, 0xc9d1, 0xc9d3, 0xc9d5, 0xc9d6,
+ 0xc9d9, 0xc9da, 0xc9dc, 0xc9dd, 0xc9e0, 0xc9e2, 0xc9e4, 0xc9e7,
+ 0xc9ec, 0xc9ed, 0xc9ef, 0xc9f0, 0xc9f1, 0xc9f8, 0xc9f9, 0xc9fc,
+ 0xca00, 0xca08, 0xca09, 0xca0b, 0xca0c, 0xca0d, 0xca14, 0xca18,
+ 0xca29, 0xca4c, 0xca4d, 0xca50, 0xca54, 0xca5c, 0xca5d, 0xca5f,
+ 0xca60, 0xca61, 0xca68, 0xca7d, 0xca84, 0xca98, 0xcabc, 0xcabd,
+ 0xcac0, 0xcac4, 0xcacc, 0xcacd, 0xcacf, 0xcad1, 0xcad3, 0xcad8,
+ 0xcad9, 0xcae0, 0xcaec, 0xcaf4, 0xcb08, 0xcb10, 0xcb14, 0xcb18,
+ 0xcb20, 0xcb21, 0xcb41, 0xcb48, 0xcb49, 0xcb4c, 0xcb50, 0xcb58,
+ 0xcb59, 0xcb5d, 0xcb64, 0xcb78, 0xcb79, 0xcb9c, 0xcbb8, 0xcbd4,
+ 0xcbe4, 0xcbe7, 0xcbe9, 0xcc0c, 0xcc0d, 0xcc10, 0xcc14, 0xcc1c,
+ 0xcc1d, 0xcc21, 0xcc22, 0xcc27, 0xcc28, 0xcc29, 0xcc2c, 0xcc2e,
+ 0xcc30, 0xcc38, 0xcc39, 0xcc3b, 0xcc3c, 0xcc3d, 0xcc3e, 0xcc44,
+ 0xcc45, 0xcc48, 0xcc4c, 0xcc54, 0xcc55, 0xcc57, 0xcc58, 0xcc59,
+ 0xcc60, 0xcc64, 0xcc66, 0xcc68, 0xcc70, 0xcc75, 0xcc98, 0xcc99,
+ 0xcc9c, 0xcca0, 0xcca8, 0xcca9, 0xccab, 0xccac, 0xccad, 0xccb4,
+ 0xccb5, 0xccb8, 0xccbc, 0xccc4, 0xccc5, 0xccc7, 0xccc9, 0xccd0,
+ 0xccd4, 0xcce4, 0xccec, 0xccf0, 0xcd01, 0xcd08, 0xcd09, 0xcd0c,
+ 0xcd10, 0xcd18, 0xcd19, 0xcd1b, 0xcd1d, 0xcd24, 0xcd28, 0xcd2c,
+ 0xcd39, 0xcd5c, 0xcd60, 0xcd64, 0xcd6c, 0xcd6d, 0xcd6f, 0xcd71,
+ 0xcd78, 0xcd88, 0xcd94, 0xcd95, 0xcd98, 0xcd9c, 0xcda4, 0xcda5,
+ 0xcda7, 0xcda9, 0xcdb0, 0xcdc4, 0xcdcc, 0xcdd0, 0xcde8, 0xcdec,
+ 0xcdf0, 0xcdf8, 0xcdf9, 0xcdfb, 0xcdfd, 0xce04, 0xce08, 0xce0c,
+ 0xce14, 0xce19, 0xce20, 0xce21, 0xce24, 0xce28, 0xce30, 0xce31,
+ 0xce33, 0xce35, 0xce58, 0xce59, 0xce5c, 0xce5f, 0xce60, 0xce61,
+ 0xce68, 0xce69, 0xce6b, 0xce6d, 0xce74, 0xce75, 0xce78, 0xce7c,
+ 0xce84, 0xce85, 0xce87, 0xce89, 0xce90, 0xce91, 0xce94, 0xce98,
+ 0xcea0, 0xcea1, 0xcea3, 0xcea4, 0xcea5, 0xceac, 0xcead, 0xcec1,
+ 0xcee4, 0xcee5, 0xcee8, 0xceeb, 0xceec, 0xcef4, 0xcef5, 0xcef7,
+ 0xcef8, 0xcef9, 0xcf00, 0xcf01, 0xcf04, 0xcf08, 0xcf10, 0xcf11,
+ 0xcf13, 0xcf15, 0xcf1c, 0xcf20, 0xcf24, 0xcf2c, 0xcf2d, 0xcf2f,
+ 0xcf30, 0xcf31, 0xcf38, 0xcf54, 0xcf55, 0xcf58, 0xcf5c, 0xcf64,
+ 0xcf65, 0xcf67, 0xcf69, 0xcf70, 0xcf71, 0xcf74, 0xcf78, 0xcf80,
+ 0xcf85, 0xcf8c, 0xcfa1, 0xcfa8, 0xcfb0, 0xcfc4, 0xcfe0, 0xcfe1,
+ 0xcfe4, 0xcfe8, 0xcff0, 0xcff1, 0xcff3, 0xcff5, 0xcffc, 0xd000,
+ 0xd004, 0xd011, 0xd018, 0xd02d, 0xd034, 0xd035, 0xd038, 0xd03c,
+ 0xd044, 0xd045, 0xd047, 0xd049, 0xd050, 0xd054, 0xd058, 0xd060,
+ 0xd06c, 0xd06d, 0xd070, 0xd074, 0xd07c, 0xd07d, 0xd081, 0xd0a4,
+ 0xd0a5, 0xd0a8, 0xd0ac, 0xd0b4, 0xd0b5, 0xd0b7, 0xd0b9, 0xd0c0,
+ 0xd0c1, 0xd0c4, 0xd0c8, 0xd0c9, 0xd0d0, 0xd0d1, 0xd0d3, 0xd0d4,
+ 0xd0d5, 0xd0dc, 0xd0dd, 0xd0e0, 0xd0e4, 0xd0ec, 0xd0ed, 0xd0ef,
+ 0xd0f0, 0xd0f1, 0xd0f8, 0xd10d, 0xd130, 0xd131, 0xd134, 0xd138,
+ 0xd13a, 0xd140, 0xd141, 0xd143, 0xd144, 0xd145, 0xd14c, 0xd14d,
+ 0xd150, 0xd154, 0xd15c, 0xd15d, 0xd15f, 0xd161, 0xd168, 0xd16c,
+ 0xd17c, 0xd184, 0xd188, 0xd1a0, 0xd1a1, 0xd1a4, 0xd1a8, 0xd1b0,
+ 0xd1b1, 0xd1b3, 0xd1b5, 0xd1ba, 0xd1bc, 0xd1c0, 0xd1d8, 0xd1f4,
+ 0xd1f8, 0xd207, 0xd209, 0xd210, 0xd22c, 0xd22d, 0xd230, 0xd234,
+ 0xd23c, 0xd23d, 0xd23f, 0xd241, 0xd248, 0xd25c, 0xd264, 0xd280,
+ 0xd281, 0xd284, 0xd288, 0xd290, 0xd291, 0xd295, 0xd29c, 0xd2a0,
+ 0xd2a4, 0xd2ac, 0xd2b1, 0xd2b8, 0xd2b9, 0xd2bc, 0xd2bf, 0xd2c0,
+ 0xd2c2, 0xd2c8, 0xd2c9, 0xd2cb, 0xd2d4, 0xd2d8, 0xd2dc, 0xd2e4,
+ 0xd2e5, 0xd2f0, 0xd2f1, 0xd2f4, 0xd2f8, 0xd300, 0xd301, 0xd303,
+ 0xd305, 0xd30c, 0xd30d, 0xd30e, 0xd310, 0xd314, 0xd316, 0xd31c,
+ 0xd31d, 0xd31f, 0xd320, 0xd321, 0xd325, 0xd328, 0xd329, 0xd32c,
+ 0xd330, 0xd338, 0xd339, 0xd33b, 0xd33c, 0xd33d, 0xd344, 0xd345,
+ 0xd37c, 0xd37d, 0xd380, 0xd384, 0xd38c, 0xd38d, 0xd38f, 0xd390,
+ 0xd391, 0xd398, 0xd399, 0xd39c, 0xd3a0, 0xd3a8, 0xd3a9, 0xd3ab,
+ 0xd3ad, 0xd3b4, 0xd3b8, 0xd3bc, 0xd3c4, 0xd3c5, 0xd3c8, 0xd3c9,
+ 0xd3d0, 0xd3d8, 0xd3e1, 0xd3e3, 0xd3ec, 0xd3ed, 0xd3f0, 0xd3f4,
+ 0xd3fc, 0xd3fd, 0xd3ff, 0xd401, 0xd408, 0xd41d, 0xd440, 0xd444,
+ 0xd45c, 0xd460, 0xd464, 0xd46d, 0xd46f, 0xd478, 0xd479, 0xd47c,
+ 0xd47f, 0xd480, 0xd482, 0xd488, 0xd489, 0xd48b, 0xd48d, 0xd494,
+ 0xd4a9, 0xd4cc, 0xd4d0, 0xd4d4, 0xd4dc, 0xd4df, 0xd4e8, 0xd4ec,
+ 0xd4f0, 0xd4f8, 0xd4fb, 0xd4fd, 0xd504, 0xd508, 0xd50c, 0xd514,
+ 0xd515, 0xd517, 0xd53c, 0xd53d, 0xd540, 0xd544, 0xd54c, 0xd54d,
+ 0xd54f, 0xd551, 0xd558, 0xd559, 0xd55c, 0xd560, 0xd565, 0xd568,
+ 0xd569, 0xd56b, 0xd56d, 0xd574, 0xd575, 0xd578, 0xd57c, 0xd584,
+ 0xd585, 0xd587, 0xd588, 0xd589, 0xd590, 0xd5a5, 0xd5c8, 0xd5c9,
+ 0xd5cc, 0xd5d0, 0xd5d2, 0xd5d8, 0xd5d9, 0xd5db, 0xd5dd, 0xd5e4,
+ 0xd5e5, 0xd5e8, 0xd5ec, 0xd5f4, 0xd5f5, 0xd5f7, 0xd5f9, 0xd600,
+ 0xd601, 0xd604, 0xd608, 0xd610, 0xd611, 0xd613, 0xd614, 0xd615,
+ 0xd61c, 0xd620, 0xd624, 0xd62d, 0xd638, 0xd639, 0xd63c, 0xd640,
+ 0xd645, 0xd648, 0xd649, 0xd64b, 0xd64d, 0xd651, 0xd654, 0xd655,
+ 0xd658, 0xd65c, 0xd667, 0xd669, 0xd670, 0xd671, 0xd674, 0xd683,
+ 0xd685, 0xd68c, 0xd68d, 0xd690, 0xd694, 0xd69d, 0xd69f, 0xd6a1,
+ 0xd6a8, 0xd6ac, 0xd6b0, 0xd6b9, 0xd6bb, 0xd6c4, 0xd6c5, 0xd6c8,
+ 0xd6cc, 0xd6d1, 0xd6d4, 0xd6d7, 0xd6d9, 0xd6e0, 0xd6e4, 0xd6e8,
+ 0xd6f0, 0xd6f5, 0xd6fc, 0xd6fd, 0xd700, 0xd704, 0xd711, 0xd718,
+ 0xd719, 0xd71c, 0xd720, 0xd728, 0xd729, 0xd72b, 0xd72d, 0xd734,
+ 0xd735, 0xd738, 0xd73c, 0xd744, 0xd747, 0xd749, 0xd750, 0xd751,
+ 0xd754, 0xd756, 0xd757, 0xd758, 0xd759, 0xd760, 0xd761, 0xd763,
+ 0xd765, 0xd769, 0xd76c, 0xd770, 0xd774, 0xd77c, 0xd77d, 0xd781,
+ 0xd788, 0xd789, 0xd78c, 0xd790, 0xd798, 0xd799, 0xd79b, 0xd79d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4f3d, 0x4f73,
+ 0x5047, 0x50f9, 0x52a0, 0x53ef, 0x5475, 0x54e5, 0x5609, 0x5ac1,
+ 0x5bb6, 0x6687, 0x67b6, 0x67b7, 0x67ef, 0x6b4c, 0x73c2, 0x75c2,
+ 0x7a3c, 0x82db, 0x8304, 0x8857, 0x8888, 0x8a36, 0x8cc8, 0x8dcf,
+ 0x8efb, 0x8fe6, 0x99d5, 0x523b, 0x5374, 0x5404, 0x606a, 0x6164,
+ 0x6bbc, 0x73cf, 0x811a, 0x89ba, 0x89d2, 0x95a3, 0x4f83, 0x520a,
+ 0x58be, 0x5978, 0x59e6, 0x5e72, 0x5e79, 0x61c7, 0x63c0, 0x6746,
+ 0x67ec, 0x687f, 0x6f97, 0x764e, 0x770b, 0x78f5, 0x7a08, 0x7aff,
+ 0x7c21, 0x809d, 0x826e, 0x8271, 0x8aeb, 0x9593, 0x4e6b, 0x559d,
+ 0x66f7, 0x6e34, 0x78a3, 0x7aed, 0x845b, 0x8910, 0x874e, 0x97a8,
+ 0x52d8, 0x574e, 0x582a, 0x5d4c, 0x611f, 0x61be, 0x6221, 0x6562,
+ 0x67d1, 0x6a44, 0x6e1b, 0x7518, 0x75b3, 0x76e3, 0x77b0, 0x7d3a,
+ 0x90af, 0x9451, 0x9452, 0x9f95, 0x5323, 0x5cac, 0x7532, 0x80db,
+ 0x9240, 0x9598, 0x525b, 0x5808, 0x59dc, 0x5ca1, 0x5d17, 0x5eb7,
+ 0x5f3a, 0x5f4a, 0x6177, 0x6c5f, 0x757a, 0x7586, 0x7ce0, 0x7d73,
+ 0x7db1, 0x7f8c, 0x8154, 0x8221, 0x8591, 0x8941, 0x8b1b, 0x92fc,
+ 0x0000, 0x9c47, 0x4ecb, 0x4ef7, 0x500b, 0x51f1, 0x584f, 0x6137,
+ 0x613e, 0x6168, 0x6539, 0x69ea, 0x6f11, 0x75a5, 0x7686, 0x76d6,
+ 0x7b87, 0x82a5, 0x84cb, 0x0000, 0x93a7, 0x958b, 0x5580, 0x5ba2,
+ 0x5751, 0x66f4, 0x7cb3, 0x7fb9, 0x91b5, 0x5028, 0x53bb, 0x5c45,
+ 0x5de8, 0x62d2, 0x636e, 0x64da, 0x64e7, 0x6e20, 0x70ac, 0x795b,
+ 0x8ddd, 0x8e1e, 0x0000, 0x907d, 0x9245, 0x92f8, 0x4e7e, 0x4ef6,
+ 0x5065, 0x5dfe, 0x5efa, 0x6106, 0x6957, 0x8171, 0x8654, 0x8e47,
+ 0x9375, 0x9a2b, 0x4e5e, 0x5091, 0x6770, 0x6840, 0x5109, 0x528d,
+ 0x5292, 0x6aa2, 0x77bc, 0x9210, 0x9ed4, 0x52ab, 0x602f, 0x8ff2,
+ 0x5048, 0x61a9, 0x63ed, 0x64ca, 0x683c, 0x6a84, 0x6fc0, 0x8188,
+ 0x89a1, 0x9694, 0x5805, 0x727d, 0x72ac, 0x7504, 0x7d79, 0x7e6d,
+ 0x80a9, 0x0000, 0x8b74, 0x9063, 0x9d51, 0x6289, 0x6c7a, 0x6f54,
+ 0x7d50, 0x7f3a, 0x8a23, 0x517c, 0x614a, 0x7b9d, 0x8b19, 0x9257,
+ 0x938c, 0x4eac, 0x4fd3, 0x501e, 0x50be, 0x5106, 0x52c1, 0x52cd,
+ 0x537f, 0x5770, 0x5883, 0x5e9a, 0x5f91, 0x6176, 0x61ac, 0x64ce,
+ 0x656c, 0x666f, 0x66bb, 0x0000, 0x6897, 0x6d87, 0x7085, 0x70f1,
+ 0x749f, 0x74a5, 0x74ca, 0x75d9, 0x786c, 0x78ec, 0x7adf, 0x7af6,
+ 0x7d45, 0x7d93, 0x8015, 0x803f, 0x811b, 0x8396, 0x8b66, 0x8f15,
+ 0x9015, 0x93e1, 0x9803, 0x9838, 0x9a5a, 0x9be8, 0x4fc2, 0x5553,
+ 0x583a, 0x0000, 0x5b63, 0x5c46, 0x60b8, 0x6212, 0x6842, 0x68b0,
+ 0x68e8, 0x6eaa, 0x754c, 0x7678, 0x78ce, 0x7a3d, 0x7cfb, 0x7e6b,
+ 0x7e7c, 0x8a08, 0x8aa1, 0x8c3f, 0x968e, 0x9dc4, 0x53e4, 0x53e9,
+ 0x544a, 0x5471, 0x56fa, 0x59d1, 0x5b64, 0x5c3b, 0x5eab, 0x62f7,
+ 0x6537, 0x6545, 0x6572, 0x66a0, 0x67af, 0x69c1, 0x6cbd, 0x75fc,
+ 0x7690, 0x777e, 0x7a3f, 0x7f94, 0x8003, 0x80a1, 0x818f, 0x82e6,
+ 0x82fd, 0x83f0, 0x85c1, 0x8831, 0x88b4, 0x8aa5, 0x0000, 0x8f9c,
+ 0x932e, 0x96c7, 0x9867, 0x9ad8, 0x9f13, 0x54ed, 0x659b, 0x66f2,
+ 0x688f, 0x7a40, 0x8c37, 0x9d60, 0x56f0, 0x5764, 0x5d11, 0x6606,
+ 0x68b1, 0x68cd, 0x6efe, 0x7428, 0x889e, 0x9be4, 0x6c68, 0x0000,
+ 0x9aa8, 0x4f9b, 0x516c, 0x5171, 0x529f, 0x5b54, 0x5de5, 0x6050,
+ 0x606d, 0x62f1, 0x63a7, 0x653b, 0x73d9, 0x7a7a, 0x86a3, 0x8ca2,
+ 0x978f, 0x0000, 0x5be1, 0x6208, 0x679c, 0x74dc, 0x79d1, 0x83d3,
+ 0x8a87, 0x8ab2, 0x8de8, 0x904e, 0x934b, 0x9846, 0x5ed3, 0x69e8,
+ 0x85ff, 0x90ed, 0x4e32, 0x51a0, 0x5b98, 0x5bec, 0x6163, 0x68fa,
+ 0x6b3e, 0x704c, 0x742f, 0x74d8, 0x7ba1, 0x7f50, 0x83c5, 0x89c0,
+ 0x8cab, 0x95dc, 0x9928, 0x522e, 0x605d, 0x62ec, 0x9002, 0x4f8a,
+ 0x5149, 0x5321, 0x58d9, 0x5ee3, 0x66e0, 0x6d38, 0x709a, 0x72c2,
+ 0x73d6, 0x7b50, 0x80f1, 0x945b, 0x5366, 0x639b, 0x7f6b, 0x4e56,
+ 0x5080, 0x584a, 0x58de, 0x602a, 0x6127, 0x62d0, 0x69d0, 0x9b41,
+ 0x5b8f, 0x7d18, 0x80b1, 0x8f5f, 0x4ea4, 0x50d1, 0x54ac, 0x55ac,
+ 0x5b0c, 0x5da0, 0x5de7, 0x652a, 0x654e, 0x6821, 0x6a4b, 0x72e1,
+ 0x768e, 0x77ef, 0x7d5e, 0x7ff9, 0x81a0, 0x854e, 0x86df, 0x8f03,
+ 0x8f4e, 0x90ca, 0x9903, 0x9a55, 0x9bab, 0x4e18, 0x4e45, 0x4e5d,
+ 0x4ec7, 0x4ff1, 0x5177, 0x52fe, 0x5340, 0x53e3, 0x53e5, 0x548e,
+ 0x5614, 0x5775, 0x57a2, 0x5bc7, 0x5d87, 0x5ed0, 0x61fc, 0x62d8,
+ 0x6551, 0x67b8, 0x67e9, 0x69cb, 0x6b50, 0x6bc6, 0x6bec, 0x6c42,
+ 0x6e9d, 0x7078, 0x72d7, 0x7396, 0x7403, 0x77bf, 0x77e9, 0x7a76,
+ 0x7d7f, 0x8009, 0x81fc, 0x8205, 0x820a, 0x82df, 0x8862, 0x8b33,
+ 0x8cfc, 0x8ec0, 0x9011, 0x90b1, 0x9264, 0x92b6, 0x99d2, 0x9a45,
+ 0x9ce9, 0x9dd7, 0x9f9c, 0x570b, 0x5c40, 0x83ca, 0x97a0, 0x97ab,
+ 0x9eb4, 0x541b, 0x7a98, 0x7fa4, 0x88d9, 0x8ecd, 0x90e1, 0x5800,
+ 0x5c48, 0x6398, 0x7a9f, 0x5bae, 0x5f13, 0x7a79, 0x7aae, 0x828e,
+ 0x8eac, 0x5026, 0x5238, 0x52f8, 0x5377, 0x5708, 0x62f3, 0x6372,
+ 0x6b0a, 0x6dc3, 0x7737, 0x53a5, 0x7357, 0x8568, 0x8e76, 0x95d5,
+ 0x673a, 0x6ac3, 0x6f70, 0x8a6d, 0x8ecc, 0x994b, 0x0000, 0x6677,
+ 0x6b78, 0x8cb4, 0x9b3c, 0x0000, 0x53eb, 0x572d, 0x594e, 0x63c6,
+ 0x69fb, 0x73ea, 0x7845, 0x7aba, 0x7ac5, 0x7cfe, 0x8475, 0x898f,
+ 0x8d73, 0x9035, 0x95a8, 0x52fb, 0x5747, 0x7547, 0x7b60, 0x83cc,
+ 0x921e, 0x0000, 0x6a58, 0x514b, 0x524b, 0x5287, 0x621f, 0x68d8,
+ 0x6975, 0x9699, 0x50c5, 0x52a4, 0x52e4, 0x61c3, 0x65a4, 0x6839,
+ 0x69ff, 0x747e, 0x7b4b, 0x82b9, 0x83eb, 0x89b2, 0x8b39, 0x8fd1,
+ 0x9949, 0x5951, 0x4eca, 0x5997, 0x64d2, 0x6611, 0x6a8e, 0x7434,
+ 0x7981, 0x79bd, 0x82a9, 0x887e, 0x887f, 0x895f, 0x91d1, 0x9326,
+ 0x4f0b, 0x53ca, 0x6025, 0x6271, 0x6c72, 0x7d1a, 0x7d66, 0x4e98,
+ 0x5162, 0x77dc, 0x80af, 0x4f01, 0x4f0e, 0x5176, 0x5180, 0x55dc,
+ 0x5668, 0x573b, 0x57fa, 0x57fc, 0x5914, 0x5947, 0x5993, 0x5bc4,
+ 0x5c90, 0x5d0e, 0x5df1, 0x5e7e, 0x5fcc, 0x6280, 0x65d7, 0x65e3,
+ 0x671e, 0x671f, 0x675e, 0x68cb, 0x68c4, 0x6a5f, 0x6b3a, 0x6c23,
+ 0x6c7d, 0x6c82, 0x6dc7, 0x7398, 0x7426, 0x742a, 0x7482, 0x74a3,
+ 0x7578, 0x757f, 0x7881, 0x78ef, 0x7941, 0x7947, 0x7948, 0x797a,
+ 0x7b95, 0x7d00, 0x7dba, 0x7f88, 0x8006, 0x802d, 0x808c, 0x8a18,
+ 0x8b4f, 0x8c48, 0x8d77, 0x9321, 0x9324, 0x98e2, 0x9951, 0x9a0e,
+ 0x9a0f, 0x9a65, 0x9e92, 0x7dca, 0x4f76, 0x5409, 0x62ee, 0x6854,
+ 0x0000, 0x55ab, 0x513a, 0x5587, 0x5948, 0x5a1c, 0x61e6, 0x61f6,
+ 0x62cf, 0x62ff, 0x7669, 0x7f85, 0x863f, 0x87ba, 0x88f8, 0x908f,
+ 0x90a3, 0x6a02, 0x6d1b, 0x70d9, 0x73de, 0x843d, 0x8afe, 0x916a,
+ 0x99f1, 0x4e82, 0x5375, 0x6696, 0x6b04, 0x7156, 0x721b, 0x862d,
+ 0x96e3, 0x9e1e, 0x634f, 0x637a, 0x5357, 0x5d50, 0x678f, 0x6960,
+ 0x6e73, 0x6feb, 0x7537, 0x85cd, 0x8964, 0x62c9, 0x7d0d, 0x81d8,
+ 0x881f, 0x8872, 0x56ca, 0x5a18, 0x5eca, 0x6717, 0x6d6a, 0x72fc,
+ 0x90de, 0x4e43, 0x4f86, 0x5167, 0x0000, 0x67f0, 0x8010, 0x51b7,
+ 0x5973, 0x5e74, 0x649a, 0x79ca, 0x5ff5, 0x606c, 0x62c8, 0x637b,
+ 0x5be7, 0x5bd7, 0x52aa, 0x52de, 0x5974, 0x5f29, 0x6012, 0x64c4,
+ 0x6ad3, 0x7210, 0x7459, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
+ 0x9732, 0x99d1, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9,
+ 0x9304, 0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x6fc3, 0x7c60, 0x807e,
+ 0x81bf, 0x8fb2, 0x60f1, 0x7262, 0x78ca, 0x8166, 0x8cc2, 0x96f7,
+ 0x5c3f, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f, 0x7e37,
+ 0x964b, 0x5ae9, 0x8a25, 0x677b, 0x7d10, 0x52d2, 0x808b, 0x51dc,
+ 0x51cc, 0x7a1c, 0x7dbe, 0x80fd, 0x83f1, 0x9675, 0x5c3c, 0x6ce5,
+ 0x533f, 0x6eba, 0x591a, 0x8336, 0x4e39, 0x4eb6, 0x4f46, 0x55ae,
+ 0x5718, 0x58c7, 0x5f56, 0x65b7, 0x65e6, 0x6a80, 0x6bb5, 0x6e4d,
+ 0x77ed, 0x7aef, 0x7c1e, 0x7dde, 0x86cb, 0x8892, 0x9132, 0x935b,
+ 0x64bb, 0x6fbe, 0x737a, 0x75b8, 0x9054, 0x5556, 0x574d, 0x61ba,
+ 0x64d4, 0x66c7, 0x6de1, 0x6e5b, 0x6f6d, 0x6fb9, 0x75f0, 0x8043,
+ 0x81bd, 0x8541, 0x8983, 0x8ac7, 0x8b5a, 0x931f, 0x6c93, 0x7553,
+ 0x7b54, 0x8e0f, 0x905d, 0x5510, 0x5802, 0x5858, 0x5e62, 0x6207,
+ 0x649e, 0x68e0, 0x7576, 0x7cd6, 0x87b3, 0x9ee8, 0x4ee3, 0x5788,
+ 0x576e, 0x5927, 0x5c0d, 0x5cb1, 0x5e36, 0x5f85, 0x6234, 0x64e1,
+ 0x73b3, 0x81fa, 0x888b, 0x8cb8, 0x968a, 0x9edb, 0x5b85, 0x5fb7,
+ 0x60b3, 0x5012, 0x5200, 0x5230, 0x5716, 0x5835, 0x5857, 0x5c0e,
+ 0x5c60, 0x5cf6, 0x5d8b, 0x5ea6, 0x5f92, 0x60bc, 0x6311, 0x6389,
+ 0x6417, 0x6843, 0x68f9, 0x6ac2, 0x6dd8, 0x6e21, 0x6ed4, 0x6fe4,
+ 0x71fe, 0x76dc, 0x7779, 0x79b1, 0x7a3b, 0x8404, 0x89a9, 0x8ced,
+ 0x8df3, 0x8e48, 0x9003, 0x9014, 0x9053, 0x90fd, 0x934d, 0x9676,
+ 0x97dc, 0x6bd2, 0x7006, 0x7258, 0x72a2, 0x7368, 0x7763, 0x79bf,
+ 0x7be4, 0x7e9b, 0x8b80, 0x58a9, 0x60c7, 0x6566, 0x65fd, 0x66be,
+ 0x6c8c, 0x711e, 0x71c9, 0x8c5a, 0x9813, 0x4e6d, 0x7a81, 0x4edd,
+ 0x51ac, 0x51cd, 0x52d5, 0x540c, 0x61a7, 0x6771, 0x6850, 0x68df,
+ 0x6d1e, 0x6f7c, 0x75bc, 0x77b3, 0x7ae5, 0x80f4, 0x8463, 0x9285,
+ 0x515c, 0x6597, 0x675c, 0x6793, 0x75d8, 0x7ac7, 0x8373, 0x0000,
+ 0x8c46, 0x9017, 0x982d, 0x5c6f, 0x81c0, 0x829a, 0x9041, 0x906f,
+ 0x920d, 0x5f97, 0x5d9d, 0x6a59, 0x71c8, 0x767b, 0x7b49, 0x85e4,
+ 0x8b04, 0x9127, 0x9a30, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7d61, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6b12, 0x703e, 0x0000, 0x0000, 0x0000, 0x524c, 0x8fa3,
+ 0x0000, 0x64e5, 0x652c, 0x6b16, 0x0000, 0x7c43, 0x7e9c, 0x0000,
+ 0x0000, 0x89bd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7405, 0x746f, 0x8782, 0x0000, 0x0000, 0x5d0d, 0x5fa0,
+ 0x840a, 0x0000, 0x63a0, 0x7565, 0x4eae, 0x5006, 0x5169, 0x51c9,
+ 0x6881, 0x6a11, 0x7cae, 0x7cb1, 0x7ce7, 0x826f, 0x8ad2, 0x8f1b,
+ 0x91cf, 0x4fb6, 0x5137, 0x52f5, 0x5442, 0x5eec, 0x616e, 0x623e,
+ 0x65c5, 0x6ada, 0x6ffe, 0x792a, 0x85dc, 0x8823, 0x95ad, 0x9a62,
+ 0x9a6a, 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x701d, 0x792b,
+ 0x8f62, 0x9742, 0x6190, 0x6200, 0x6523, 0x6f23, 0x7149, 0x7489,
+ 0x7df4, 0x806f, 0x84ee, 0x8f26, 0x9023, 0x934a, 0x51bd, 0x5217,
+ 0x52a3, 0x6d0c, 0x70c8, 0x88c2, 0x5ec9, 0x6582, 0x6bae, 0x6fc2,
+ 0x7c3e, 0x7375, 0x4ee4, 0x4f36, 0x56f9, 0x0000, 0x5cba, 0x5dba,
+ 0x601c, 0x73b2, 0x7b2d, 0x7f9a, 0x7fce, 0x8046, 0x901e, 0x9234,
+ 0x96f6, 0x9748, 0x9818, 0x9f61, 0x4f8b, 0x6fa7, 0x79ae, 0x91b4,
+ 0x96b7, 0x0000, 0x0000, 0x6488, 0x0000, 0x0000, 0x6f5e, 0x7018,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8f05, 0x0000,
+ 0x0000, 0x0000, 0x9e75, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9e93, 0x0000, 0x0000, 0x0000, 0x6727, 0x7027, 0x74cf,
+ 0x0000, 0x0000, 0x5121, 0x7028, 0x0000, 0x0000, 0x0000, 0x8cda,
+ 0x8cf4, 0x0000, 0x4e86, 0x50da, 0x5bee, 0x5ed6, 0x6599, 0x71ce,
+ 0x7642, 0x77ad, 0x804a, 0x84fc, 0x907c, 0x9b27, 0x9f8d, 0x0000,
+ 0x5a41, 0x0000, 0x0000, 0x0000, 0x0000, 0x763b, 0x0000, 0x0000,
+ 0x851e, 0x8938, 0x93e4, 0x0000, 0x5289, 0x65d2, 0x67f3, 0x69b4,
+ 0x6d41, 0x6e9c, 0x700f, 0x7409, 0x7460, 0x7559, 0x7624, 0x786b,
+ 0x8b2c, 0x985e, 0x516d, 0x622e, 0x9678, 0x4f96, 0x502b, 0x5d19,
+ 0x6dea, 0x7db8, 0x8f2a, 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x695e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4fda, 0x5229, 0x5398, 0x540f, 0x550e, 0x5c65, 0x60a7,
+ 0x674e, 0x68a8, 0x6d6c, 0x7281, 0x72f8, 0x7406, 0x7483, 0x7570,
+ 0x75e2, 0x7c6c, 0x7f79, 0x7fb8, 0x8389, 0x88cf, 0x88e1, 0x91cc,
+ 0x91d0, 0x96e2, 0x9bc9, 0x541d, 0x6f7e, 0x71d0, 0x7498, 0x85fa,
+ 0x8eaa, 0x96a3, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x7433, 0x81e8,
+ 0x9716, 0x782c, 0x7acb, 0x7b20, 0x7c92, 0x6469, 0x746a, 0x75f2,
+ 0x78bc, 0x78e8, 0x99ac, 0x9b54, 0x9ebb, 0x5bde, 0x5e55, 0x6f20,
+ 0x819c, 0x83ab, 0x9088, 0x4e07, 0x534d, 0x5a29, 0x5dd2, 0x5f4e,
+ 0x6162, 0x633d, 0x6669, 0x66fc, 0x6eff, 0x6f2b, 0x7063, 0x779e,
+ 0x842c, 0x8513, 0x883b, 0x8f13, 0x9945, 0x9c3b, 0x551c, 0x62b9,
+ 0x672b, 0x6cab, 0x8309, 0x896a, 0x977a, 0x4ea1, 0x5984, 0x5fd8,
+ 0x5fd9, 0x671b, 0x7db2, 0x7f54, 0x8292, 0x832b, 0x83bd, 0x8f1e,
+ 0x9099, 0x57cb, 0x59b9, 0x5a92, 0x5bd0, 0x6627, 0x679a, 0x6885,
+ 0x6bcf, 0x7164, 0x7f75, 0x8cb7, 0x8ce3, 0x9081, 0x9b45, 0x8108,
+ 0x8c8a, 0x964c, 0x9a40, 0x9ea5, 0x5b5f, 0x6c13, 0x731b, 0x76f2,
+ 0x76df, 0x840c, 0x51aa, 0x8993, 0x514d, 0x5195, 0x52c9, 0x68c9,
+ 0x6c94, 0x7704, 0x7720, 0x7dbf, 0x7dec, 0x9762, 0x9eb5, 0x6ec5,
+ 0x8511, 0x51a5, 0x540d, 0x547d, 0x660e, 0x669d, 0x6927, 0x6e9f,
+ 0x76bf, 0x7791, 0x8317, 0x84c2, 0x879f, 0x9169, 0x9298, 0x9cf4,
+ 0x8882, 0x4fae, 0x5192, 0x52df, 0x59c6, 0x5e3d, 0x6155, 0x6478,
+ 0x6479, 0x66ae, 0x67d0, 0x6a21, 0x6bcd, 0x6bdb, 0x725f, 0x7261,
+ 0x7441, 0x7738, 0x77db, 0x8017, 0x82bc, 0x8305, 0x8b00, 0x8b28,
+ 0x8c8c, 0x6728, 0x6c90, 0x7267, 0x76ee, 0x7766, 0x7a46, 0x9da9,
+ 0x6b7f, 0x6c92, 0x5922, 0x6726, 0x8499, 0x536f, 0x5893, 0x5999,
+ 0x5edf, 0x63cf, 0x6634, 0x6773, 0x6e3a, 0x732b, 0x7ad7, 0x82d7,
+ 0x9328, 0x52d9, 0x5deb, 0x61ae, 0x61cb, 0x620a, 0x62c7, 0x64ab,
+ 0x65e0, 0x6959, 0x6b66, 0x6bcb, 0x7121, 0x73f7, 0x755d, 0x7e46,
+ 0x821e, 0x8302, 0x856a, 0x8aa3, 0x8cbf, 0x9727, 0x9d61, 0x58a8,
+ 0x9ed8, 0x5011, 0x520e, 0x543b, 0x554f, 0x6587, 0x6c76, 0x7d0a,
+ 0x7d0b, 0x805e, 0x868a, 0x9580, 0x96ef, 0x52ff, 0x6c95, 0x7269,
+ 0x5473, 0x5a9a, 0x5c3e, 0x5d4b, 0x5f4c, 0x5fae, 0x672a, 0x68b6,
+ 0x6963, 0x6e3c, 0x6e44, 0x7709, 0x7c73, 0x7f8e, 0x8587, 0x8b0e,
+ 0x8ff7, 0x9761, 0x9ef4, 0x5cb7, 0x60b6, 0x610d, 0x61ab, 0x654f,
+ 0x65fb, 0x65fc, 0x6c11, 0x6cef, 0x739f, 0x73c9, 0x7de1, 0x9594,
+ 0x5bc6, 0x871c, 0x8b10, 0x525d, 0x535a, 0x62cd, 0x640f, 0x64b2,
+ 0x6734, 0x6a38, 0x6cca, 0x73c0, 0x749e, 0x7b94, 0x7c95, 0x7e1b,
+ 0x818a, 0x8236, 0x8584, 0x8feb, 0x96f9, 0x99c1, 0x4f34, 0x534a,
+ 0x53cd, 0x53db, 0x62cc, 0x642c, 0x6500, 0x6591, 0x69c3, 0x6cee,
+ 0x6f58, 0x73ed, 0x7554, 0x7622, 0x76e4, 0x76fc, 0x78d0, 0x78fb,
+ 0x792c, 0x7d46, 0x822c, 0x87e0, 0x8fd4, 0x9812, 0x98ef, 0x52c3,
+ 0x62d4, 0x64a5, 0x6e24, 0x6f51, 0x767c, 0x8dcb, 0x91b1, 0x9262,
+ 0x9aee, 0x9b43, 0x5023, 0x508d, 0x574a, 0x59a8, 0x5c28, 0x5e47,
+ 0x5f77, 0x623f, 0x653e, 0x65b9, 0x65c1, 0x6609, 0x678b, 0x699c,
+ 0x6ec2, 0x78c5, 0x7d21, 0x80aa, 0x8180, 0x822b, 0x82b3, 0x84a1,
+ 0x868c, 0x8a2a, 0x8b17, 0x90a6, 0x9632, 0x9f90, 0x500d, 0x4ff3,
+ 0x5317, 0x57f9, 0x5f98, 0x62dc, 0x6392, 0x676f, 0x6e43, 0x7119,
+ 0x76c3, 0x80cc, 0x80da, 0x88f4, 0x88f5, 0x8919, 0x8ce0, 0x8f29,
+ 0x914d, 0x966a, 0x4f2f, 0x4f70, 0x5e1b, 0x67cf, 0x6822, 0x767d,
+ 0x767e, 0x9b44, 0x5e61, 0x6a0a, 0x7169, 0x71d4, 0x756a, 0x0000,
+ 0x7e41, 0x8543, 0x85e9, 0x98dc, 0x4f10, 0x7b4f, 0x7f70, 0x95a5,
+ 0x51e1, 0x5e06, 0x68b5, 0x6c3e, 0x6c4e, 0x6cdb, 0x72af, 0x7bc4,
+ 0x8303, 0x6cd5, 0x743a, 0x50fb, 0x5288, 0x58c1, 0x64d8, 0x6a97,
+ 0x74a7, 0x7656, 0x78a7, 0x8617, 0x95e2, 0x9739, 0x4fbf, 0x535e,
+ 0x5f01, 0x8b8a, 0x8fa8, 0x8faf, 0x908a, 0x5225, 0x77a5, 0x9c49,
+ 0x9f08, 0x4e19, 0x5002, 0x5175, 0x5c5b, 0x5e77, 0x661e, 0x663a,
+ 0x67c4, 0x68c5, 0x70b3, 0x7501, 0x75c5, 0x79c9, 0x7add, 0x8f27,
+ 0x9920, 0x9a08, 0x4fdd, 0x5821, 0x5831, 0x5bf6, 0x666e, 0x6b65,
+ 0x6d11, 0x6e7a, 0x6f7d, 0x73e4, 0x752b, 0x83e9, 0x88dc, 0x8913,
+ 0x8b5c, 0x8f14, 0x4f0f, 0x50d5, 0x5310, 0x535c, 0x5b93, 0x5fa9,
+ 0x670d, 0x798f, 0x8179, 0x832f, 0x8514, 0x8907, 0x8986, 0x8f39,
+ 0x8f3b, 0x99a5, 0x9c12, 0x672c, 0x4e76, 0x4ff8, 0x5949, 0x5c01,
+ 0x5cef, 0x5cf0, 0x6367, 0x68d2, 0x70fd, 0x71a2, 0x742b, 0x7e2b,
+ 0x84ec, 0x8702, 0x9022, 0x92d2, 0x9cf3, 0x4e0d, 0x4ed8, 0x4fef,
+ 0x5085, 0x5256, 0x526f, 0x5426, 0x5490, 0x57e0, 0x592b, 0x5a66,
+ 0x5b5a, 0x5b75, 0x5bcc, 0x5e9c, 0x0000, 0x6276, 0x6577, 0x65a7,
+ 0x6d6e, 0x6ea5, 0x7236, 0x7b26, 0x7c3f, 0x7f36, 0x8150, 0x8151,
+ 0x819a, 0x8240, 0x8299, 0x83a9, 0x8a03, 0x8ca0, 0x8ce6, 0x8cfb,
+ 0x8d74, 0x8dba, 0x90e8, 0x91dc, 0x961c, 0x9644, 0x99d9, 0x9ce7,
+ 0x0000, 0x5206, 0x5429, 0x5674, 0x58b3, 0x5954, 0x596e, 0x5fff,
+ 0x61a4, 0x626e, 0x6610, 0x6c7e, 0x711a, 0x76c6, 0x7c89, 0x7cde,
+ 0x7d1b, 0x82ac, 0x8cc1, 0x96f0, 0x0000, 0x4f5b, 0x5f17, 0x5f7f,
+ 0x62c2, 0x5d29, 0x670b, 0x68da, 0x787c, 0x7e43, 0x9d6c, 0x4e15,
+ 0x5099, 0x5315, 0x532a, 0x5351, 0x5983, 0x5a62, 0x5e87, 0x60b2,
+ 0x618a, 0x6249, 0x6279, 0x6590, 0x6787, 0x69a7, 0x6bd4, 0x6bd6,
+ 0x6bd7, 0x6bd8, 0x6cb8, 0x6ccc, 0x7435, 0x75fa, 0x7812, 0x7891,
+ 0x79d5, 0x79d8, 0x7c83, 0x7dcb, 0x7fe1, 0x80a5, 0x813e, 0x81c2,
+ 0x83f2, 0x871a, 0x88e8, 0x8ab9, 0x8b6c, 0x8cbb, 0x9119, 0x975e,
+ 0x98db, 0x9f3b, 0x56ac, 0x5b2a, 0x5f6c, 0x658c, 0x6ab3, 0x6baf,
+ 0x6d5c, 0x6ff1, 0x7015, 0x725d, 0x73ad, 0x8ca7, 0x8cd3, 0x983b,
+ 0x6191, 0x6c37, 0x8058, 0x9a01, 0x4e4d, 0x4e8b, 0x4e9b, 0x4ed5,
+ 0x4f3a, 0x4f3c, 0x4f7f, 0x4fdf, 0x50ff, 0x53f2, 0x53f8, 0x5506,
+ 0x55e3, 0x56db, 0x58eb, 0x5962, 0x5a11, 0x5beb, 0x5bfa, 0x5c04,
+ 0x5df3, 0x5e2b, 0x5f99, 0x601d, 0x6368, 0x659c, 0x65af, 0x67f6,
+ 0x67fb, 0x68ad, 0x6b7b, 0x6c99, 0x6cd7, 0x6e23, 0x7009, 0x7345,
+ 0x7802, 0x793e, 0x7940, 0x7960, 0x79c1, 0x7be9, 0x7d17, 0x7d72,
+ 0x8086, 0x820d, 0x838e, 0x84d1, 0x86c7, 0x88df, 0x8a50, 0x8a5e,
+ 0x8b1d, 0x8cdc, 0x8d66, 0x8fad, 0x90aa, 0x98fc, 0x99df, 0x9e9d,
+ 0x524a, 0x6578, 0x6714, 0x7d22, 0x5098, 0x522a, 0x5c71, 0x6563,
+ 0x6c55, 0x73ca, 0x7523, 0x759d, 0x7b97, 0x849c, 0x9178, 0x9730,
+ 0x4e77, 0x6492, 0x6bba, 0x715e, 0x85a9, 0x4e09, 0x53c3, 0x6749,
+ 0x68ee, 0x6e17, 0x829f, 0x8518, 0x886b, 0x63f7, 0x6f81, 0x9212,
+ 0x98af, 0x4e0a, 0x50b7, 0x50cf, 0x511f, 0x5546, 0x55aa, 0x5617,
+ 0x5b40, 0x5c19, 0x5ce0, 0x5e38, 0x5e8a, 0x5ea0, 0x5ec2, 0x60f3,
+ 0x6851, 0x6a61, 0x6e58, 0x723d, 0x7240, 0x72c0, 0x76f8, 0x7965,
+ 0x7bb1, 0x7fd4, 0x88f3, 0x89f4, 0x8a73, 0x8c61, 0x8cde, 0x971c,
+ 0x585e, 0x74bd, 0x8cfd, 0x55c7, 0x0000, 0x7a61, 0x0000, 0x8272,
+ 0x7272, 0x751f, 0x7525, 0x7701, 0x7b19, 0x5885, 0x58fb, 0x5dbc,
+ 0x5e8f, 0x5eb6, 0x5f90, 0x6055, 0x6292, 0x637f, 0x654d, 0x6691,
+ 0x66d9, 0x66f8, 0x6816, 0x68f2, 0x7280, 0x745e, 0x7b6e, 0x7d6e,
+ 0x7dd6, 0x7f72, 0x80e5, 0x8212, 0x85af, 0x897f, 0x8a93, 0x901d,
+ 0x92e4, 0x9ecd, 0x9f20, 0x5915, 0x596d, 0x5e2d, 0x60dc, 0x6614,
+ 0x6673, 0x6790, 0x6c50, 0x6dc5, 0x6f5f, 0x77f3, 0x78a9, 0x84c6,
+ 0x91cb, 0x932b, 0x4ed9, 0x50ca, 0x5148, 0x5584, 0x5b0b, 0x5ba3,
+ 0x6247, 0x657e, 0x65cb, 0x6e32, 0x717d, 0x7401, 0x7444, 0x7487,
+ 0x74bf, 0x766c, 0x79aa, 0x7dda, 0x7e55, 0x7fa8, 0x817a, 0x81b3,
+ 0x8239, 0x861a, 0x87ec, 0x8a75, 0x8de3, 0x9078, 0x9291, 0x9425,
+ 0x994d, 0x9bae, 0x5368, 0x5c51, 0x6954, 0x6cc4, 0x6d29, 0x6e2b,
+ 0x820c, 0x859b, 0x893b, 0x8a2d, 0x8aaa, 0x96ea, 0x9f67, 0x5261,
+ 0x66b9, 0x6bb2, 0x7e96, 0x87fe, 0x8d0d, 0x9583, 0x965d, 0x651d,
+ 0x6d89, 0x71ee, 0x8449, 0x57ce, 0x59d3, 0x5bac, 0x6027, 0x60fa,
+ 0x6210, 0x661f, 0x665f, 0x7329, 0x73f9, 0x76db, 0x0000, 0x7b6c,
+ 0x8056, 0x8072, 0x8165, 0x8aa0, 0x9192, 0x4e16, 0x52e2, 0x6b72,
+ 0x6d17, 0x7a05, 0x7b39, 0x7d30, 0x0000, 0x8cb0, 0x53ec, 0x562f,
+ 0x5851, 0x5bb5, 0x5c0f, 0x5c11, 0x5de2, 0x6240, 0x6383, 0x6414,
+ 0x662d, 0x68b3, 0x6cbc, 0x6d88, 0x6eaf, 0x701f, 0x70a4, 0x71d2,
+ 0x7526, 0x758f, 0x758e, 0x7619, 0x7b11, 0x7be0, 0x7c2b, 0x7d20,
+ 0x7d39, 0x852c, 0x856d, 0x8607, 0x8a34, 0x900d, 0x9061, 0x90b5,
+ 0x92b7, 0x97f6, 0x9a37, 0x4fd7, 0x5c6c, 0x675f, 0x6d91, 0x7c9f,
+ 0x7e8c, 0x8b16, 0x8d16, 0x901f, 0x5b6b, 0x5dfd, 0x640d, 0x84c0,
+ 0x905c, 0x98e1, 0x0000, 0x5b8b, 0x609a, 0x677e, 0x6dde, 0x8a1f,
+ 0x8aa6, 0x9001, 0x980c, 0x5237, 0x0000, 0x7051, 0x788e, 0x9396,
+ 0x8870, 0x91d7, 0x4fee, 0x53d7, 0x55fd, 0x56da, 0x5782, 0x58fd,
+ 0x5ac2, 0x5b88, 0x5cab, 0x5cc0, 0x5e25, 0x6101, 0x620d, 0x624b,
+ 0x6388, 0x641c, 0x6536, 0x0000, 0x6a39, 0x6b8a, 0x6c34, 0x6d19,
+ 0x6f31, 0x71e7, 0x72e9, 0x7378, 0x7407, 0x74b2, 0x7626, 0x7761,
+ 0x79c0, 0x7a57, 0x7aea, 0x7cb9, 0x7d8f, 0x7dac, 0x7e61, 0x7f9e,
+ 0x8129, 0x8331, 0x8490, 0x84da, 0x85ea, 0x8896, 0x8ab0, 0x8b90,
+ 0x8f38, 0x9042, 0x9083, 0x916c, 0x9296, 0x92b9, 0x968b, 0x96a7,
+ 0x96a8, 0x96d6, 0x9700, 0x9808, 0x9996, 0x9ad3, 0x9b1a, 0x53d4,
+ 0x587e, 0x5919, 0x5b70, 0x5bbf, 0x6dd1, 0x6f5a, 0x719f, 0x7421,
+ 0x74b9, 0x8085, 0x83fd, 0x5de1, 0x5f87, 0x5faa, 0x6042, 0x65ec,
+ 0x6812, 0x696f, 0x6a53, 0x6b89, 0x6d35, 0x6df3, 0x73e3, 0x76fe,
+ 0x77ac, 0x7b4d, 0x7d14, 0x8123, 0x821c, 0x8340, 0x84f4, 0x8563,
+ 0x8a62, 0x8ac4, 0x9187, 0x931e, 0x9806, 0x99b4, 0x620c, 0x8853,
+ 0x8ff0, 0x9265, 0x5d07, 0x5d27, 0x5d69, 0x745f, 0x819d, 0x8768,
+ 0x6fd5, 0x62fe, 0x7fd2, 0x8936, 0x8972, 0x4e1e, 0x4e58, 0x50e7,
+ 0x52dd, 0x5347, 0x627f, 0x6607, 0x7e69, 0x8805, 0x965e, 0x4f8d,
+ 0x5319, 0x5636, 0x59cb, 0x5aa4, 0x5c38, 0x5c4e, 0x5c4d, 0x5e02,
+ 0x5f11, 0x6043, 0x65bd, 0x662f, 0x6642, 0x67be, 0x67f4, 0x731c,
+ 0x77e2, 0x793a, 0x7fc5, 0x8494, 0x84cd, 0x8996, 0x8a66, 0x8a69,
+ 0x8ae1, 0x8c55, 0x8c7a, 0x57f4, 0x5bd4, 0x5f0f, 0x606f, 0x62ed,
+ 0x690d, 0x6b96, 0x6e5c, 0x7184, 0x7bd2, 0x8755, 0x8b58, 0x8efe,
+ 0x98df, 0x98fe, 0x4f38, 0x4f81, 0x4fe1, 0x547b, 0x5a20, 0x5bb8,
+ 0x613c, 0x65b0, 0x6668, 0x71fc, 0x7533, 0x795e, 0x7d33, 0x814e,
+ 0x81e3, 0x8398, 0x85aa, 0x85ce, 0x8703, 0x8a0a, 0x8eab, 0x8f9b,
+ 0x8fb0, 0x8fc5, 0x5931, 0x5ba4, 0x5be6, 0x6089, 0x5be9, 0x5c0b,
+ 0x5fc3, 0x6c81, 0x6c88, 0x6df1, 0x700b, 0x751a, 0x82af, 0x8af6,
+ 0x4ec0, 0x5341, 0x0000, 0x96d9, 0x6c0f, 0x4e9e, 0x4fc4, 0x5152,
+ 0x555e, 0x5a25, 0x5ce8, 0x6211, 0x7259, 0x82bd, 0x83aa, 0x86fe,
+ 0x8859, 0x8a1d, 0x963f, 0x96c5, 0x9913, 0x9d09, 0x9d5d, 0x580a,
+ 0x5cb3, 0x5dbd, 0x5e44, 0x60e1, 0x6115, 0x63e1, 0x0000, 0x6e25,
+ 0x9102, 0x9354, 0x984e, 0x9c10, 0x9f77, 0x5b89, 0x5cb8, 0x6309,
+ 0x664f, 0x6848, 0x773c, 0x96c1, 0x978d, 0x9854, 0x9b9f, 0x65a1,
+ 0x8b01, 0x8ecb, 0x95bc, 0x5535, 0x5ca9, 0x5dd6, 0x5eb5, 0x6697,
+ 0x764c, 0x83f4, 0x95c7, 0x58d3, 0x62bc, 0x72ce, 0x9d28, 0x4ef0,
+ 0x592e, 0x600f, 0x663b, 0x6b83, 0x79e7, 0x9d26, 0x5393, 0x54c0,
+ 0x57c3, 0x5d16, 0x611b, 0x66d6, 0x6daf, 0x788d, 0x827e, 0x9698,
+ 0x9744, 0x5384, 0x627c, 0x6396, 0x6db2, 0x7e0a, 0x814b, 0x984d,
+ 0x6afb, 0x7f4c, 0x9daf, 0x9e1a, 0x4e5f, 0x503b, 0x51b6, 0x591c,
+ 0x60f9, 0x63f6, 0x6930, 0x723a, 0x8036, 0x82e5, 0x91ce, 0x5f31,
+ 0x0000, 0x0000, 0x7d04, 0x0000, 0x846f, 0x84bb, 0x85e5, 0x8e8d,
+ 0x0000, 0x4f6f, 0x0000, 0x0000, 0x58e4, 0x5b43, 0x6059, 0x63da,
+ 0x6518, 0x656d, 0x6698, 0x0000, 0x694a, 0x6a23, 0x6d0b, 0x7001,
+ 0x716c, 0x75d2, 0x760d, 0x79b3, 0x7a70, 0x0000, 0x7f8a, 0x0000,
+ 0x8944, 0x0000, 0x8b93, 0x91c0, 0x967d, 0x0000, 0x990a, 0x5704,
+ 0x5fa1, 0x65bc, 0x6f01, 0x7600, 0x79a6, 0x8a9e, 0x99ad, 0x9b5a,
+ 0x9f6c, 0x5104, 0x61b6, 0x6291, 0x6a8d, 0x81c6, 0x5043, 0x5830,
+ 0x5f66, 0x7109, 0x8a00, 0x8afa, 0x5b7c, 0x8616, 0x4ffa, 0x513c,
+ 0x56b4, 0x5944, 0x63a9, 0x6df9, 0x5daa, 0x696d, 0x5186, 0x4e88,
+ 0x4f59, 0x0000, 0x0000, 0x0000, 0x5982, 0x0000, 0x0000, 0x6b5f,
+ 0x6c5d, 0x0000, 0x74b5, 0x7916, 0x0000, 0x8207, 0x8245, 0x8339,
+ 0x8f3f, 0x8f5d, 0x0000, 0x9918, 0x0000, 0x0000, 0x0000, 0x4ea6,
+ 0x0000, 0x57df, 0x5f79, 0x6613, 0x0000, 0x0000, 0x75ab, 0x7e79,
+ 0x8b6f, 0x0000, 0x9006, 0x9a5b, 0x56a5, 0x5827, 0x59f8, 0x5a1f,
+ 0x5bb4, 0x0000, 0x5ef6, 0x0000, 0x0000, 0x6350, 0x633b, 0x0000,
+ 0x693d, 0x6c87, 0x6cbf, 0x6d8e, 0x6d93, 0x6df5, 0x6f14, 0x0000,
+ 0x70df, 0x7136, 0x7159, 0x0000, 0x71c3, 0x71d5, 0x0000, 0x784f,
+ 0x786f, 0x0000, 0x7b75, 0x7de3, 0x0000, 0x7e2f, 0x0000, 0x884d,
+ 0x8edf, 0x0000, 0x0000, 0x0000, 0x925b, 0x0000, 0x9cf6, 0x0000,
+ 0x0000, 0x54bd, 0x6085, 0x6d85, 0x0000, 0x71b1, 0x0000, 0x0000,
+ 0x95b1, 0x53ad, 0x0000, 0x0000, 0x0000, 0x67d3, 0x0000, 0x708e,
+ 0x7130, 0x7430, 0x8276, 0x82d2, 0x0000, 0x95bb, 0x9ae5, 0x9e7d,
+ 0x66c4, 0x0000, 0x71c1, 0x0000, 0x0000, 0x0000, 0x584b, 0x0000,
+ 0x0000, 0x5db8, 0x5f71, 0x0000, 0x6620, 0x668e, 0x6979, 0x69ae,
+ 0x6c38, 0x6cf3, 0x6e36, 0x6f41, 0x6fda, 0x701b, 0x702f, 0x7150,
+ 0x71df, 0x7370, 0x0000, 0x745b, 0x7469, 0x74d4, 0x76c8, 0x7a4e,
+ 0x7e93, 0x0000, 0x0000, 0x82f1, 0x8a60, 0x8fce, 0x0000, 0x9348,
+ 0x0000, 0x9719, 0x0000, 0x0000, 0x4e42, 0x502a, 0x0000, 0x5208,
+ 0x53e1, 0x66f3, 0x6c6d, 0x6fca, 0x730a, 0x777f, 0x7a62, 0x82ae,
+ 0x85dd, 0x8602, 0x0000, 0x88d4, 0x8a63, 0x8b7d, 0x8c6b, 0x0000,
+ 0x92b3, 0x0000, 0x9713, 0x9810, 0x4e94, 0x4f0d, 0x4fc9, 0x50b2,
+ 0x5348, 0x543e, 0x5433, 0x55da, 0x5862, 0x58ba, 0x5967, 0x5a1b,
+ 0x5be4, 0x609f, 0x0000, 0x61ca, 0x6556, 0x65ff, 0x6664, 0x68a7,
+ 0x6c5a, 0x6fb3, 0x70cf, 0x71ac, 0x7352, 0x7b7d, 0x8708, 0x8aa4,
+ 0x9c32, 0x9f07, 0x5c4b, 0x6c83, 0x7344, 0x7389, 0x923a, 0x6eab,
+ 0x7465, 0x761f, 0x7a69, 0x7e15, 0x860a, 0x5140, 0x58c5, 0x64c1,
+ 0x74ee, 0x7515, 0x7670, 0x7fc1, 0x9095, 0x96cd, 0x9954, 0x6e26,
+ 0x74e6, 0x7aa9, 0x7aaa, 0x81e5, 0x86d9, 0x8778, 0x8a1b, 0x5a49,
+ 0x5b8c, 0x5b9b, 0x68a1, 0x6900, 0x6d63, 0x73a9, 0x7413, 0x742c,
+ 0x7897, 0x7de9, 0x7feb, 0x8118, 0x8155, 0x839e, 0x8c4c, 0x962e,
+ 0x9811, 0x66f0, 0x5f80, 0x65fa, 0x6789, 0x6c6a, 0x738b, 0x502d,
+ 0x5a03, 0x6b6a, 0x77ee, 0x5916, 0x5d6c, 0x5dcd, 0x7325, 0x754f,
+ 0x0000, 0x0000, 0x50e5, 0x51f9, 0x582f, 0x592d, 0x5996, 0x59da,
+ 0x5be5, 0x0000, 0x0000, 0x5da2, 0x62d7, 0x6416, 0x6493, 0x64fe,
+ 0x0000, 0x66dc, 0x0000, 0x6a48, 0x0000, 0x71ff, 0x7464, 0x0000,
+ 0x7a88, 0x7aaf, 0x7e47, 0x7e5e, 0x8000, 0x8170, 0x0000, 0x87ef,
+ 0x8981, 0x8b20, 0x9059, 0x0000, 0x9080, 0x9952, 0x617e, 0x6b32,
+ 0x6d74, 0x7e1f, 0x8925, 0x8fb1, 0x4fd1, 0x50ad, 0x5197, 0x52c7,
+ 0x57c7, 0x5889, 0x5bb9, 0x5eb8, 0x6142, 0x6995, 0x6d8c, 0x6e67,
+ 0x6eb6, 0x7194, 0x7462, 0x7528, 0x752c, 0x8073, 0x8338, 0x84c9,
+ 0x8e0a, 0x9394, 0x93de, 0x0000, 0x4e8e, 0x4f51, 0x5076, 0x512a,
+ 0x53c8, 0x53cb, 0x53f3, 0x5b87, 0x5bd3, 0x5c24, 0x611a, 0x6182,
+ 0x65f4, 0x725b, 0x7397, 0x7440, 0x76c2, 0x7950, 0x7991, 0x79b9,
+ 0x7d06, 0x7fbd, 0x828b, 0x85d5, 0x865e, 0x8fc2, 0x9047, 0x90f5,
+ 0x91ea, 0x9685, 0x96e8, 0x96e9, 0x52d6, 0x5f67, 0x65ed, 0x6631,
+ 0x682f, 0x715c, 0x7a36, 0x90c1, 0x980a, 0x4e91, 0x6688, 0x6a52,
+ 0x6b9e, 0x6f90, 0x7189, 0x8018, 0x82b8, 0x8553, 0x904b, 0x9695,
+ 0x96f2, 0x97fb, 0x851a, 0x9b31, 0x4e90, 0x718a, 0x96c4, 0x5143,
+ 0x539f, 0x54e1, 0x5713, 0x5712, 0x57a3, 0x5a9b, 0x5ac4, 0x5bc3,
+ 0x6028, 0x613f, 0x63f4, 0x6c85, 0x6d39, 0x6e72, 0x6e90, 0x7230,
+ 0x733f, 0x7457, 0x82d1, 0x8881, 0x8f45, 0x9060, 0x0000, 0x9662,
+ 0x9858, 0x9d1b, 0x6708, 0x8d8a, 0x925e, 0x4f4d, 0x5049, 0x50de,
+ 0x5371, 0x570d, 0x59d4, 0x5a01, 0x5c09, 0x6170, 0x6690, 0x6e2d,
+ 0x7232, 0x744b, 0x7def, 0x80c3, 0x840e, 0x8466, 0x853f, 0x875f,
+ 0x885b, 0x8918, 0x8b02, 0x9055, 0x97cb, 0x9b4f, 0x4e73, 0x4f91,
+ 0x5112, 0x516a, 0x0000, 0x552f, 0x55a9, 0x5b7a, 0x5ba5, 0x5e7c,
+ 0x5e7d, 0x5ebe, 0x60a0, 0x60df, 0x6108, 0x6109, 0x63c4, 0x6538,
+ 0x6709, 0x0000, 0x67d4, 0x67da, 0x0000, 0x6961, 0x6962, 0x6cb9,
+ 0x6d27, 0x0000, 0x6e38, 0x0000, 0x6fe1, 0x7336, 0x7337, 0x0000,
+ 0x745c, 0x7531, 0x0000, 0x7652, 0x0000, 0x0000, 0x7dad, 0x81fe,
+ 0x8438, 0x88d5, 0x8a98, 0x8adb, 0x8aed, 0x8e30, 0x8e42, 0x904a,
+ 0x903e, 0x907a, 0x9149, 0x91c9, 0x936e, 0x0000, 0x0000, 0x5809,
+ 0x0000, 0x6bd3, 0x8089, 0x80b2, 0x0000, 0x0000, 0x5141, 0x596b,
+ 0x5c39, 0x0000, 0x0000, 0x6f64, 0x73a7, 0x80e4, 0x8d07, 0x0000,
+ 0x9217, 0x958f, 0x0000, 0x0000, 0x0000, 0x0000, 0x807f, 0x620e,
+ 0x701c, 0x7d68, 0x878d, 0x0000, 0x57a0, 0x6069, 0x6147, 0x6bb7,
+ 0x8abe, 0x9280, 0x96b1, 0x4e59, 0x541f, 0x6deb, 0x852d, 0x9670,
+ 0x97f3, 0x98ee, 0x63d6, 0x6ce3, 0x9091, 0x51dd, 0x61c9, 0x81ba,
+ 0x9df9, 0x4f9d, 0x501a, 0x5100, 0x5b9c, 0x610f, 0x61ff, 0x64ec,
+ 0x6905, 0x6bc5, 0x7591, 0x77e3, 0x7fa9, 0x8264, 0x858f, 0x87fb,
+ 0x8863, 0x8abc, 0x8b70, 0x91ab, 0x4e8c, 0x4ee5, 0x4f0a, 0x0000,
+ 0x0000, 0x5937, 0x59e8, 0x0000, 0x5df2, 0x5f1b, 0x5f5b, 0x6021,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x723e, 0x73e5, 0x0000, 0x0000,
+ 0x75cd, 0x0000, 0x79fb, 0x0000, 0x800c, 0x8033, 0x8084, 0x82e1,
+ 0x8351, 0x0000, 0x0000, 0x8cbd, 0x8cb3, 0x9087, 0x0000, 0x0000,
+ 0x98f4, 0x990c, 0x0000, 0x0000, 0x7037, 0x76ca, 0x7fca, 0x7fcc,
+ 0x7ffc, 0x8b1a, 0x4eba, 0x4ec1, 0x5203, 0x5370, 0x0000, 0x0000,
+ 0x56e0, 0x59fb, 0x5bc5, 0x5f15, 0x5fcd, 0x6e6e, 0x0000, 0x0000,
+ 0x7d6a, 0x8335, 0x0000, 0x8693, 0x8a8d, 0x0000, 0x976d, 0x9777,
+ 0x0000, 0x0000, 0x4e00, 0x4f5a, 0x4f7e, 0x58f9, 0x65e5, 0x6ea2,
+ 0x9038, 0x93b0, 0x99b9, 0x4efb, 0x58ec, 0x598a, 0x59d9, 0x6041,
+ 0x0000, 0x0000, 0x7a14, 0x0000, 0x834f, 0x8cc3, 0x5165, 0x5344,
+ 0x0000, 0x0000, 0x0000, 0x4ecd, 0x5269, 0x5b55, 0x82bf, 0x4ed4,
+ 0x523a, 0x54a8, 0x59c9, 0x59ff, 0x5b50, 0x5b57, 0x5b5c, 0x6063,
+ 0x6148, 0x6ecb, 0x7099, 0x716e, 0x7386, 0x74f7, 0x75b5, 0x78c1,
+ 0x7d2b, 0x8005, 0x81ea, 0x8328, 0x8517, 0x85c9, 0x8aee, 0x8cc7,
+ 0x96cc, 0x4f5c, 0x52fa, 0x56bc, 0x65ab, 0x6628, 0x707c, 0x70b8,
+ 0x7235, 0x7dbd, 0x828d, 0x914c, 0x96c0, 0x9d72, 0x5b71, 0x68e7,
+ 0x6b98, 0x6f7a, 0x76de, 0x5c91, 0x66ab, 0x6f5b, 0x7bb4, 0x7c2a,
+ 0x8836, 0x96dc, 0x4e08, 0x4ed7, 0x5320, 0x5834, 0x58bb, 0x58ef,
+ 0x596c, 0x5c07, 0x5e33, 0x5e84, 0x5f35, 0x638c, 0x66b2, 0x6756,
+ 0x6a1f, 0x6aa3, 0x6b0c, 0x6f3f, 0x7246, 0x0000, 0x7350, 0x748b,
+ 0x7ae0, 0x7ca7, 0x8178, 0x81df, 0x81e7, 0x838a, 0x846c, 0x8523,
+ 0x8594, 0x85cf, 0x88dd, 0x8d13, 0x91ac, 0x9577, 0x969c, 0x518d,
+ 0x54c9, 0x5728, 0x5bb0, 0x624d, 0x6750, 0x683d, 0x6893, 0x6e3d,
+ 0x6ed3, 0x707d, 0x7e21, 0x88c1, 0x8ca1, 0x8f09, 0x9f4b, 0x9f4e,
+ 0x722d, 0x7b8f, 0x8acd, 0x931a, 0x4f47, 0x4f4e, 0x5132, 0x5480,
+ 0x59d0, 0x5e95, 0x62b5, 0x6775, 0x696e, 0x6a17, 0x6cae, 0x6e1a,
+ 0x72d9, 0x732a, 0x75bd, 0x7bb8, 0x7d35, 0x82e7, 0x83f9, 0x8457,
+ 0x85f7, 0x8a5b, 0x8caf, 0x8e87, 0x9019, 0x90b8, 0x96ce, 0x9f5f,
+ 0x52e3, 0x540a, 0x5ae1, 0x5bc2, 0x6458, 0x6575, 0x6ef4, 0x72c4,
+ 0x0000, 0x7684, 0x7a4d, 0x7b1b, 0x7c4d, 0x7e3e, 0x7fdf, 0x837b,
+ 0x8b2b, 0x8cca, 0x8d64, 0x8de1, 0x8e5f, 0x8fea, 0x8ff9, 0x9069,
+ 0x93d1, 0x4f43, 0x4f7a, 0x50b3, 0x5168, 0x5178, 0x524d, 0x526a,
+ 0x5861, 0x587c, 0x5960, 0x5c08, 0x5c55, 0x5edb, 0x609b, 0x6230,
+ 0x6813, 0x6bbf, 0x6c08, 0x6fb1, 0x714e, 0x7420, 0x7530, 0x7538,
+ 0x7551, 0x7672, 0x7b4c, 0x7b8b, 0x7bad, 0x7bc6, 0x7e8f, 0x8a6e,
+ 0x8f3e, 0x8f49, 0x923f, 0x9293, 0x9322, 0x942b, 0x96fb, 0x985a,
+ 0x986b, 0x991e, 0x5207, 0x622a, 0x6298, 0x6d59, 0x7664, 0x7aca,
+ 0x7bc0, 0x7d76, 0x5360, 0x5cbe, 0x5e97, 0x6f38, 0x70b9, 0x7c98,
+ 0x9711, 0x9b8e, 0x9ede, 0x63a5, 0x647a, 0x8776, 0x4e01, 0x4e95,
+ 0x4ead, 0x505c, 0x5075, 0x5448, 0x59c3, 0x5b9a, 0x5e40, 0x5ead,
+ 0x5ef7, 0x5f81, 0x60c5, 0x633a, 0x653f, 0x6574, 0x65cc, 0x6676,
+ 0x6678, 0x67fe, 0x6968, 0x6a89, 0x6b63, 0x6c40, 0x6dc0, 0x6de8,
+ 0x6e1f, 0x6e5e, 0x701e, 0x70a1, 0x738e, 0x73fd, 0x753a, 0x775b,
+ 0x7887, 0x798e, 0x7a0b, 0x7a7d, 0x7cbe, 0x7d8e, 0x8247, 0x8a02,
+ 0x8aea, 0x8c9e, 0x912d, 0x914a, 0x91d8, 0x9266, 0x92cc, 0x9320,
+ 0x9706, 0x9756, 0x975c, 0x9802, 0x9f0e, 0x5236, 0x5291, 0x557c,
+ 0x5824, 0x5e1d, 0x5f1f, 0x608c, 0x63d0, 0x68af, 0x6fdf, 0x796d,
+ 0x7b2c, 0x81cd, 0x85ba, 0x88fd, 0x8af8, 0x8e44, 0x918d, 0x9664,
+ 0x969b, 0x973d, 0x984c, 0x9f4a, 0x4fce, 0x5146, 0x51cb, 0x52a9,
+ 0x5632, 0x5f14, 0x5f6b, 0x63aa, 0x64cd, 0x65e9, 0x6641, 0x66fa,
+ 0x66f9, 0x671d, 0x689d, 0x68d7, 0x69fd, 0x6f15, 0x6f6e, 0x7167,
+ 0x71e5, 0x722a, 0x74aa, 0x773a, 0x7956, 0x795a, 0x79df, 0x7a20,
+ 0x7a95, 0x7c97, 0x7cdf, 0x7d44, 0x7e70, 0x8087, 0x85fb, 0x86a4,
+ 0x8a54, 0x8abf, 0x8d99, 0x8e81, 0x9020, 0x906d, 0x91e3, 0x963b,
+ 0x96d5, 0x9ce5, 0x65cf, 0x7c07, 0x8db3, 0x93c3, 0x5b58, 0x5c0a,
+ 0x5352, 0x62d9, 0x731d, 0x5027, 0x5b97, 0x5f9e, 0x60b0, 0x616b,
+ 0x68d5, 0x6dd9, 0x742e, 0x7a2e, 0x7d42, 0x7d9c, 0x7e31, 0x816b,
+ 0x8e2a, 0x8e35, 0x937e, 0x9418, 0x4f50, 0x5750, 0x5de6, 0x5ea7,
+ 0x632b, 0x7f6a, 0x4e3b, 0x4f4f, 0x4f8f, 0x505a, 0x59dd, 0x80c4,
+ 0x546a, 0x5468, 0x55fe, 0x594f, 0x5b99, 0x5dde, 0x5eda, 0x665d,
+ 0x6731, 0x67f1, 0x682a, 0x6ce8, 0x6d32, 0x6e4a, 0x6f8d, 0x70b7,
+ 0x73e0, 0x7587, 0x7c4c, 0x7d02, 0x7d2c, 0x7da2, 0x821f, 0x86db,
+ 0x8a3b, 0x8a85, 0x8d70, 0x8e8a, 0x8f33, 0x9031, 0x914e, 0x9152,
+ 0x9444, 0x99d0, 0x7af9, 0x7ca5, 0x4fca, 0x5101, 0x51c6, 0x57c8,
+ 0x5bef, 0x5cfb, 0x6659, 0x6a3d, 0x6d5a, 0x6e96, 0x6fec, 0x710c,
+ 0x756f, 0x7ae3, 0x8822, 0x9021, 0x9075, 0x96cb, 0x99ff, 0x8301,
+ 0x4e2d, 0x4ef2, 0x8846, 0x91cd, 0x537d, 0x6adb, 0x696b, 0x6c41,
+ 0x847a, 0x589e, 0x618e, 0x66fe, 0x62ef, 0x70dd, 0x7511, 0x75c7,
+ 0x7e52, 0x84b8, 0x8b49, 0x8d08, 0x4e4b, 0x53ea, 0x54ab, 0x5730,
+ 0x5740, 0x5fd7, 0x6301, 0x6307, 0x646f, 0x652f, 0x65e8, 0x667a,
+ 0x679d, 0x67b3, 0x6b62, 0x6c60, 0x6c9a, 0x6f2c, 0x77e5, 0x7825,
+ 0x7949, 0x7957, 0x7d19, 0x80a2, 0x8102, 0x81f3, 0x829d, 0x82b7,
+ 0x8718, 0x8a8c, 0x0000, 0x8d04, 0x8dbe, 0x9072, 0x76f4, 0x7a19,
+ 0x7a37, 0x7e54, 0x8077, 0x5507, 0x55d4, 0x5875, 0x632f, 0x6422,
+ 0x6649, 0x664b, 0x686d, 0x699b, 0x6b84, 0x6d25, 0x6eb1, 0x73cd,
+ 0x7468, 0x74a1, 0x755b, 0x75b9, 0x76e1, 0x771e, 0x778b, 0x79e6,
+ 0x7e09, 0x7e1d, 0x81fb, 0x852f, 0x8897, 0x8a3a, 0x8cd1, 0x8eeb,
+ 0x0000, 0x9032, 0x93ad, 0x9663, 0x9673, 0x9707, 0x4f84, 0x53f1,
+ 0x59ea, 0x5ac9, 0x5e19, 0x684e, 0x74c6, 0x75be, 0x79e9, 0x7a92,
+ 0x81a3, 0x86ed, 0x8cea, 0x8dcc, 0x8fed, 0x659f, 0x6715, 0x0000,
+ 0x57f7, 0x6f57, 0x7ddd, 0x8f2f, 0x93f6, 0x96c6, 0x5fb5, 0x61f2,
+ 0x6f84, 0x4e14, 0x4f98, 0x501f, 0x53c9, 0x55df, 0x5d6f, 0x5dee,
+ 0x6b21, 0x6b64, 0x78cb, 0x7b9a, 0x0000, 0x8e49, 0x8eca, 0x906e,
+ 0x6349, 0x643e, 0x7740, 0x7a84, 0x932f, 0x947f, 0x9f6a, 0x64b0,
+ 0x6faf, 0x71e6, 0x74a8, 0x74da, 0x7ac4, 0x7c12, 0x7e82, 0x7cb2,
+ 0x7e98, 0x8b9a, 0x8d0a, 0x947d, 0x9910, 0x994c, 0x5239, 0x5bdf,
+ 0x64e6, 0x672d, 0x7d2e, 0x50ed, 0x0000, 0x5879, 0x6158, 0x6159,
+ 0x61fa, 0x65ac, 0x7ad9, 0x8b92, 0x8b96, 0x5009, 0x5021, 0x5275,
+ 0x5531, 0x5a3c, 0x5ee0, 0x5f70, 0x6134, 0x655e, 0x660c, 0x6636,
+ 0x66a2, 0x69cd, 0x6ec4, 0x6f32, 0x7316, 0x7621, 0x7a93, 0x8139,
+ 0x8259, 0x83d6, 0x84bc, 0x50b5, 0x57f0, 0x5bc0, 0x5be8, 0x5f69,
+ 0x63a1, 0x7826, 0x7db5, 0x83dc, 0x8521, 0x91c7, 0x91f5, 0x518a,
+ 0x67f5, 0x7b56, 0x8cac, 0x51c4, 0x59bb, 0x60bd, 0x8655, 0x501c,
+ 0x0000, 0x5254, 0x5c3a, 0x617d, 0x621a, 0x62d3, 0x64f2, 0x65a5,
+ 0x6ecc, 0x7620, 0x810a, 0x8e60, 0x965f, 0x96bb, 0x4edf, 0x5343,
+ 0x5598, 0x5929, 0x5ddd, 0x64c5, 0x6cc9, 0x6dfa, 0x7394, 0x7a7f,
+ 0x821b, 0x85a6, 0x8ce4, 0x8e10, 0x9077, 0x91e7, 0x95e1, 0x9621,
+ 0x97c6, 0x51f8, 0x54f2, 0x5586, 0x5fb9, 0x64a4, 0x6f88, 0x7db4,
+ 0x8f1f, 0x8f4d, 0x9435, 0x50c9, 0x5c16, 0x6cbe, 0x6dfb, 0x751b,
+ 0x77bb, 0x7c3d, 0x7c64, 0x8a79, 0x8ac2, 0x581e, 0x59be, 0x5e16,
+ 0x6377, 0x7252, 0x758a, 0x776b, 0x8adc, 0x8cbc, 0x8f12, 0x5ef3,
+ 0x6674, 0x6df8, 0x807d, 0x83c1, 0x8acb, 0x9751, 0x9bd6, 0x0000,
+ 0x5243, 0x66ff, 0x6d95, 0x6eef, 0x7de0, 0x8ae6, 0x902e, 0x905e,
+ 0x9ad4, 0x521d, 0x527f, 0x54e8, 0x6194, 0x6284, 0x62db, 0x68a2,
+ 0x6912, 0x695a, 0x6a35, 0x7092, 0x7126, 0x785d, 0x7901, 0x790e,
+ 0x79d2, 0x7a0d, 0x8096, 0x8278, 0x82d5, 0x8349, 0x8549, 0x8c82,
+ 0x8d85, 0x9162, 0x918b, 0x91ae, 0x4fc3, 0x56d1, 0x71ed, 0x77d7,
+ 0x8700, 0x89f8, 0x5bf8, 0x5fd6, 0x6751, 0x90a8, 0x53e2, 0x585a,
+ 0x5bf5, 0x60a4, 0x6181, 0x6460, 0x7e3d, 0x8070, 0x8525, 0x9283,
+ 0x64ae, 0x50ac, 0x5d14, 0x6700, 0x589c, 0x62bd, 0x63a8, 0x690e,
+ 0x6978, 0x6a1e, 0x6e6b, 0x76ba, 0x79cb, 0x82bb, 0x8429, 0x8acf,
+ 0x8da8, 0x8ffd, 0x9112, 0x914b, 0x919c, 0x9310, 0x9318, 0x939a,
+ 0x96db, 0x9a36, 0x9c0d, 0x4e11, 0x755c, 0x795d, 0x7afa, 0x7b51,
+ 0x7bc9, 0x7e2e, 0x84c4, 0x8e59, 0x8e74, 0x8ef8, 0x9010, 0x6625,
+ 0x693f, 0x7443, 0x51fa, 0x672e, 0x9edc, 0x5145, 0x5fe0, 0x6c96,
+ 0x87f2, 0x885d, 0x8877, 0x60b4, 0x81b5, 0x8403, 0x8d05, 0x53d6,
+ 0x5439, 0x5634, 0x5a36, 0x5c31, 0x708a, 0x7fe0, 0x805a, 0x8106,
+ 0x81ed, 0x8da3, 0x9189, 0x9a5f, 0x9df2, 0x5074, 0x4ec4, 0x53a0,
+ 0x60fb, 0x6e2c, 0x5c64, 0x4f88, 0x5024, 0x55e4, 0x5cd9, 0x5e5f,
+ 0x6065, 0x6894, 0x6cbb, 0x6dc4, 0x71be, 0x75d4, 0x75f4, 0x7661,
+ 0x7a1a, 0x7a49, 0x7dc7, 0x7dfb, 0x7f6e, 0x81f4, 0x86a9, 0x8f1c,
+ 0x96c9, 0x99b3, 0x9f52, 0x5247, 0x52c5, 0x98ed, 0x89aa, 0x4e03,
+ 0x67d2, 0x6f06, 0x4fb5, 0x5be2, 0x6795, 0x0000, 0x6d78, 0x741b,
+ 0x7827, 0x91dd, 0x937c, 0x87c4, 0x79e4, 0x7a31, 0x5feb, 0x4ed6,
+ 0x54a4, 0x553e, 0x58ae, 0x59a5, 0x60f0, 0x6253, 0x62d6, 0x6736,
+ 0x6955, 0x8235, 0x9640, 0x99b1, 0x99dd, 0x502c, 0x5353, 0x5544,
+ 0x577c, 0x0000, 0x6258, 0x0000, 0x64e2, 0x666b, 0x67dd, 0x6fc1,
+ 0x6fef, 0x7422, 0x7438, 0x8a17, 0x9438, 0x5451, 0x5606, 0x5766,
+ 0x5f48, 0x619a, 0x6b4e, 0x7058, 0x70ad, 0x7dbb, 0x8a95, 0x596a,
+ 0x812b, 0x63a2, 0x7708, 0x803d, 0x8caa, 0x5854, 0x642d, 0x69bb,
+ 0x5b95, 0x5e11, 0x6e6f, 0x0000, 0x8569, 0x514c, 0x53f0, 0x592a,
+ 0x6020, 0x614b, 0x6b86, 0x6c70, 0x6cf0, 0x7b1e, 0x80ce, 0x82d4,
+ 0x8dc6, 0x90b0, 0x98b1, 0x0000, 0x64c7, 0x6fa4, 0x6491, 0x6504,
+ 0x514e, 0x5410, 0x571f, 0x8a0e, 0x615f, 0x6876, 0x0000, 0x75db,
+ 0x7b52, 0x7d71, 0x901a, 0x5806, 0x69cc, 0x817f, 0x892a, 0x9000,
+ 0x9839, 0x5078, 0x5957, 0x59ac, 0x6295, 0x900f, 0x9b2a, 0x615d,
+ 0x7279, 0x95d6, 0x5761, 0x5a46, 0x5df4, 0x628a, 0x64ad, 0x64fa,
+ 0x6777, 0x6ce2, 0x6d3e, 0x722c, 0x7436, 0x7834, 0x7f77, 0x82ad,
+ 0x8ddb, 0x9817, 0x5224, 0x5742, 0x677f, 0x7248, 0x74e3, 0x8ca9,
+ 0x8fa6, 0x9211, 0x962a, 0x516b, 0x53ed, 0x634c, 0x4f69, 0x5504,
+ 0x6096, 0x6557, 0x6c9b, 0x6d7f, 0x724c, 0x72fd, 0x7a17, 0x8987,
+ 0x8c9d, 0x5f6d, 0x6f8e, 0x70f9, 0x81a8, 0x610e, 0x0000, 0x504f,
+ 0x6241, 0x7247, 0x7bc7, 0x7de8, 0x7fe9, 0x904d, 0x97ad, 0x9a19,
+ 0x8cb6, 0x576a, 0x5e73, 0x67b0, 0x840d, 0x8a55, 0x5420, 0x5b16,
+ 0x5e63, 0x5ee2, 0x5f0a, 0x6583, 0x80ba, 0x853d, 0x9589, 0x965b,
+ 0x4f48, 0x5305, 0x530d, 0x530f, 0x5486, 0x54fa, 0x5703, 0x5e03,
+ 0x6016, 0x629b, 0x62b1, 0x6355, 0x66b4, 0x6ce1, 0x6d66, 0x75b1,
+ 0x7832, 0x80de, 0x812f, 0x82de, 0x8461, 0x84b2, 0x888d, 0x8912,
+ 0x900b, 0x92ea, 0x98fd, 0x9b91, 0x5e45, 0x0000, 0x66dd, 0x7011,
+ 0x7206, 0x0000, 0x4ff5, 0x527d, 0x5f6a, 0x6153, 0x6753, 0x6a19,
+ 0x6f02, 0x74e2, 0x7968, 0x8868, 0x8c79, 0x98c7, 0x98c4, 0x9a43,
+ 0x54c1, 0x7a1f, 0x6953, 0x8af7, 0x8c4a, 0x98a8, 0x99ae, 0x5f7c,
+ 0x62ab, 0x75b2, 0x76ae, 0x88ab, 0x907f, 0x9642, 0x5339, 0x5f3c,
+ 0x5fc5, 0x0000, 0x73cc, 0x7562, 0x758b, 0x7b46, 0x82fe, 0x999d,
+ 0x4e4f, 0x903c, 0x4e0b, 0x4f55, 0x53a6, 0x590f, 0x5ec8, 0x6630,
+ 0x6cb3, 0x7455, 0x8377, 0x8766, 0x8cc0, 0x9050, 0x971e, 0x9c15,
+ 0x58d1, 0x5b78, 0x8650, 0x8b14, 0x9db4, 0x5bd2, 0x6068, 0x608d,
+ 0x65f1, 0x6c57, 0x6f22, 0x6fa3, 0x701a, 0x7f55, 0x7ff0, 0x9591,
+ 0x9592, 0x9650, 0x97d3, 0x5272, 0x8f44, 0x51fd, 0x542b, 0x54b8,
+ 0x5563, 0x558a, 0x6abb, 0x6db5, 0x7dd8, 0x8266, 0x929c, 0x9677,
+ 0x9e79, 0x5408, 0x54c8, 0x76d2, 0x86e4, 0x95a4, 0x95d4, 0x965c,
+ 0x4ea2, 0x4f09, 0x59ee, 0x5ae6, 0x5df7, 0x6052, 0x6297, 0x676d,
+ 0x6841, 0x6c86, 0x6e2f, 0x7f38, 0x809b, 0x822a, 0x884c, 0x964d,
+ 0x9805, 0x4ea5, 0x5055, 0x54b3, 0x5793, 0x595a, 0x5b69, 0x5bb3,
+ 0x61c8, 0x6977, 0x6d77, 0x7023, 0x87f9, 0x89e3, 0x8a72, 0x8ae7,
+ 0x9082, 0x99ed, 0x9ab8, 0x52be, 0x6838, 0x5016, 0x5e78, 0x674f,
+ 0x8347, 0x0000, 0x4eab, 0x5411, 0x56ae, 0x73e6, 0x9115, 0x97ff,
+ 0x9909, 0x9957, 0x9999, 0x5653, 0x589f, 0x865b, 0x8a31, 0x61b2,
+ 0x6af6, 0x737b, 0x8ed2, 0x6b47, 0x96aa, 0x9a57, 0x5955, 0x7200,
+ 0x8d6b, 0x9769, 0x4fd4, 0x5cf4, 0x5f26, 0x61f8, 0x665b, 0x6ceb,
+ 0x70ab, 0x7384, 0x73b9, 0x73fe, 0x7729, 0x774d, 0x7d43, 0x7d62,
+ 0x7e23, 0x8237, 0x8852, 0x898b, 0x8ce2, 0x9249, 0x986f, 0x5b51,
+ 0x7a74, 0x8840, 0x9801, 0x5acc, 0x4fe0, 0x5354, 0x593e, 0x5cfd,
+ 0x633e, 0x6d79, 0x72f9, 0x8105, 0x8107, 0x83a2, 0x92cf, 0x9830,
+ 0x4ea8, 0x5144, 0x5211, 0x578b, 0x5f62, 0x6cc2, 0x6ece, 0x7005,
+ 0x7050, 0x70af, 0x7192, 0x73e9, 0x0000, 0x834a, 0x87a2, 0x8861,
+ 0x9008, 0x90a2, 0x93a3, 0x99a8, 0x516e, 0x5f57, 0x60e0, 0x6167,
+ 0x66b3, 0x8559, 0x8e4a, 0x91af, 0x978b, 0x4e4e, 0x4e92, 0x547c,
+ 0x58d5, 0x58fa, 0x597d, 0x5cb5, 0x5f27, 0x6236, 0x6248, 0x660a,
+ 0x6667, 0x6beb, 0x6d69, 0x6dcf, 0x6e56, 0x6ef8, 0x6f94, 0x6fe0,
+ 0x6fe9, 0x705d, 0x72d0, 0x7425, 0x745a, 0x74e0, 0x7693, 0x795c,
+ 0x7cca, 0x7e1e, 0x80e1, 0x82a6, 0x846b, 0x84bf, 0x864e, 0x865f,
+ 0x8774, 0x8b77, 0x8c6a, 0x93ac, 0x9800, 0x9865, 0x60d1, 0x6216,
+ 0x9177, 0x5a5a, 0x660f, 0x6df7, 0x6e3e, 0x743f, 0x9b42, 0x5ffd,
+ 0x60da, 0x7b0f, 0x54c4, 0x5f18, 0x6c5e, 0x6cd3, 0x6d2a, 0x70d8,
+ 0x7d05, 0x8679, 0x8a0c, 0x9d3b, 0x5316, 0x548c, 0x5b05, 0x6a3a,
+ 0x706b, 0x7575, 0x798d, 0x79be, 0x82b1, 0x83ef, 0x8a71, 0x8b41,
+ 0x8ca8, 0x9774, 0x0000, 0x64f4, 0x652b, 0x78ba, 0x78bb, 0x7a6b,
+ 0x4e38, 0x559a, 0x5950, 0x5ba6, 0x5e7b, 0x60a3, 0x63db, 0x6b61,
+ 0x6665, 0x6853, 0x6e19, 0x7165, 0x74b0, 0x7d08, 0x9084, 0x9a69,
+ 0x9c25, 0x6d3b, 0x6ed1, 0x733e, 0x8c41, 0x95ca, 0x51f0, 0x5e4c,
+ 0x5fa8, 0x604d, 0x60f6, 0x6130, 0x614c, 0x6643, 0x6644, 0x69a5,
+ 0x6cc1, 0x6e5f, 0x6ec9, 0x6f62, 0x714c, 0x749c, 0x7687, 0x7bc1,
+ 0x7c27, 0x8352, 0x8757, 0x9051, 0x968d, 0x9ec3, 0x532f, 0x56de,
+ 0x5efb, 0x5f8a, 0x6062, 0x6094, 0x61f7, 0x6666, 0x6703, 0x6a9c,
+ 0x6dee, 0x6fae, 0x7070, 0x736a, 0x7e6a, 0x81be, 0x8334, 0x86d4,
+ 0x8aa8, 0x8cc4, 0x5283, 0x7372, 0x5b96, 0x6a6b, 0x9404, 0x54ee,
+ 0x5686, 0x5b5d, 0x6548, 0x6585, 0x66c9, 0x689f, 0x6d8d, 0x6dc6,
+ 0x723b, 0x80b4, 0x9175, 0x9a4d, 0x4faf, 0x5019, 0x539a, 0x540e,
+ 0x543c, 0x5589, 0x55c5, 0x5e3f, 0x5f8c, 0x673d, 0x7166, 0x73dd,
+ 0x9005, 0x52db, 0x52f3, 0x5864, 0x58ce, 0x7104, 0x718f, 0x71fb,
+ 0x85b0, 0x8a13, 0x0000, 0x85a8, 0x55a7, 0x6684, 0x714a, 0x8431,
+ 0x5349, 0x5599, 0x6bc1, 0x5f59, 0x5fbd, 0x63ee, 0x6689, 0x7147,
+ 0x8af1, 0x8f1d, 0x9ebe, 0x4f11, 0x643a, 0x70cb, 0x7566, 0x8667,
+ 0x6064, 0x8b4e, 0x9df8, 0x5147, 0x51f6, 0x5308, 0x6d36, 0x80f8,
+ 0x9ed1, 0x6615, 0x6b23, 0x7098, 0x75d5, 0x5403, 0x5c79, 0x7d07,
+ 0x8a16, 0x6b20, 0x6b3d, 0x6b46, 0x5438, 0x6070, 0x6d3d, 0x7fd5,
+ 0x8208, 0x50d6, 0x51de, 0x559c, 0x566b, 0x56cd, 0x59ec, 0x5b09,
+ 0x5e0c, 0x6199, 0x6198, 0x6231, 0x665e, 0x66e6, 0x7199, 0x71b9,
+ 0x71ba, 0x72a7, 0x79a7, 0x7a00, 0x7fb2, 0x8a70, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x0000, 0x0000, 0x79d4, 0x0004, 0x2288, 0x804f240
+};
+
+#ifndef LUA_FF_LIB
+
+static unsigned short ksc5601_from_unicode_0[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x222e, 0x0000, 0x0000, 0x2234, 0x0000, 0x0000, 0x2157,
+ 0x2127, 0x0000, 0x2823, 0x216c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2146, 0x213e, 0x2977, 0x2978, 0x2225, 0x0000, 0x2252, 0x0000,
+ 0x222c, 0x2976, 0x282c, 0x216d, 0x2879, 0x2876, 0x287a, 0x222f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2821, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2822, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x213f,
+ 0x282a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x282d, 0x292c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2921, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2923, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2140,
+ 0x292a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x292d, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_1[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2922, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2824, 0x2924,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2925, 0x2826, 0x2926, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2927, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2828,
+ 0x2928, 0x2829, 0x2929, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2930, 0x282f, 0x292f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x282b, 0x292b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x282e, 0x292e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_2[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2227,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2228, 0x222b, 0x222a, 0x222d, 0x2226, 0x2229, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_3[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547,
+ 0x2548, 0x2549, 0x254a, 0x254b, 0x254c, 0x254d, 0x254e, 0x254f,
+ 0x2550, 0x2551, 0x0000, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556,
+ 0x2557, 0x2558, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567,
+ 0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x256d, 0x256e, 0x256f,
+ 0x2570, 0x2571, 0x0000, 0x2572, 0x2573, 0x2574, 0x2575, 0x2576,
+ 0x2577, 0x2578, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_4[] = {
+ 0x0000, 0x2c27, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2c21, 0x2c22, 0x2c23, 0x2c24, 0x2c25, 0x2c26, 0x2c28, 0x2c29,
+ 0x2c2a, 0x2c2b, 0x2c2c, 0x2c2d, 0x2c2e, 0x2c2f, 0x2c30, 0x2c31,
+ 0x2c32, 0x2c33, 0x2c34, 0x2c35, 0x2c36, 0x2c37, 0x2c38, 0x2c39,
+ 0x2c3a, 0x2c3b, 0x2c3c, 0x2c3d, 0x2c3e, 0x2c3f, 0x2c40, 0x2c41,
+ 0x2c51, 0x2c52, 0x2c53, 0x2c54, 0x2c55, 0x2c56, 0x2c58, 0x2c59,
+ 0x2c5a, 0x2c5b, 0x2c5c, 0x2c5d, 0x2c5e, 0x2c5f, 0x2c60, 0x2c61,
+ 0x2c62, 0x2c63, 0x2c64, 0x2c65, 0x2c66, 0x2c67, 0x2c68, 0x2c69,
+ 0x2c6a, 0x2c6b, 0x2c6c, 0x2c6d, 0x2c6e, 0x2c6f, 0x2c70, 0x2c71,
+ 0x0000, 0x2c57, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_20[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2129, 0x212a, 0x0000, 0x212b, 0x0000,
+ 0x212e, 0x212f, 0x0000, 0x0000, 0x2130, 0x2131, 0x0000, 0x0000,
+ 0x2253, 0x2254, 0x0000, 0x0000, 0x0000, 0x2125, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2236, 0x0000, 0x2147, 0x2148, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2158, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2979, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x297a,
+ 0x0000, 0x297b, 0x297c, 0x297d, 0x297e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_21[] = {
+ 0x0000, 0x0000, 0x0000, 0x2149, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2235, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2724, 0x0000, 0x0000, 0x2260, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2265, 0x2262, 0x0000, 0x0000, 0x0000, 0x2759, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x214a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2877, 0x2878, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x287b, 0x287c, 0x287d, 0x287e, 0x0000,
+ 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537,
+ 0x2538, 0x2539, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527, 0x2528,
+ 0x2529, 0x252a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2167, 0x2168, 0x2166, 0x2169, 0x216a, 0x2255, 0x2258, 0x2256,
+ 0x2259, 0x2257, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2221, 0x0000, 0x2222, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_22[] = {
+ 0x2223, 0x0000, 0x2153, 0x2224, 0x0000, 0x0000, 0x0000, 0x2154,
+ 0x2174, 0x0000, 0x0000, 0x2175, 0x0000, 0x0000, 0x0000, 0x2233,
+ 0x0000, 0x2232, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x216e, 0x0000, 0x0000, 0x2170, 0x2144, 0x0000,
+ 0x2150, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x217c,
+ 0x217d, 0x217b, 0x217a, 0x2172, 0x2173, 0x0000, 0x2231, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2145, 0x2171, 0x2230, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x216f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2156, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2141, 0x2155, 0x0000, 0x0000, 0x2142, 0x2143, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2178, 0x2179, 0x0000, 0x0000, 0x2176, 0x2177,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2151, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2126,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_23[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2152, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_24[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2867, 0x2868, 0x2869, 0x286a, 0x286b, 0x286c, 0x286d, 0x286e,
+ 0x286f, 0x2870, 0x2871, 0x2872, 0x2873, 0x2874, 0x2875, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2967, 0x2968, 0x2969, 0x296a,
+ 0x296b, 0x296c, 0x296d, 0x296e, 0x296f, 0x2970, 0x2971, 0x2972,
+ 0x2973, 0x2974, 0x2975, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x294d, 0x294e, 0x294f, 0x2950,
+ 0x2951, 0x2952, 0x2953, 0x2954, 0x2955, 0x2956, 0x2957, 0x2958,
+ 0x2959, 0x295a, 0x295b, 0x295c, 0x295d, 0x295e, 0x295f, 0x2960,
+ 0x2961, 0x2962, 0x2963, 0x2964, 0x2965, 0x2966, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x284d, 0x284e, 0x284f, 0x2850, 0x2851, 0x2852, 0x2853, 0x2854,
+ 0x2855, 0x2856, 0x2857, 0x2858, 0x2859, 0x285a, 0x285b, 0x285c,
+ 0x285d, 0x285e, 0x285f, 0x2860, 0x2861, 0x2862, 0x2863, 0x2864,
+ 0x2865, 0x2866, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_25[] = {
+ 0x2621, 0x262c, 0x2622, 0x262d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2623, 0x2648, 0x2647, 0x262e,
+ 0x2624, 0x2642, 0x2641, 0x262f, 0x2626, 0x2646, 0x2645, 0x2631,
+ 0x2625, 0x2644, 0x2643, 0x2630, 0x2627, 0x263c, 0x2649, 0x264a,
+ 0x2637, 0x264b, 0x264c, 0x2632, 0x2629, 0x263e, 0x264d, 0x264e,
+ 0x2639, 0x264f, 0x2650, 0x2634, 0x2628, 0x2651, 0x2652, 0x2638,
+ 0x263d, 0x2653, 0x2654, 0x2633, 0x262a, 0x2655, 0x2656, 0x263a,
+ 0x263f, 0x2657, 0x2658, 0x2635, 0x262b, 0x2659, 0x265a, 0x263b,
+ 0x265b, 0x265c, 0x2640, 0x265d, 0x265e, 0x265f, 0x2660, 0x2661,
+ 0x2662, 0x2663, 0x2664, 0x2636, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2246, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2161, 0x2160, 0x0000, 0x2243, 0x2247, 0x2248, 0x224b, 0x224a,
+ 0x2249, 0x224c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2163, 0x2162, 0x0000, 0x0000, 0x223a, 0x2239,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2165, 0x2164, 0x0000, 0x0000,
+ 0x2238, 0x2237, 0x0000, 0x0000, 0x0000, 0x0000, 0x215f, 0x215e,
+ 0x2242, 0x2241, 0x0000, 0x215b, 0x0000, 0x0000, 0x215d, 0x215c,
+ 0x2244, 0x2245, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_26[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x215a, 0x2159, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x224f, 0x224e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2250, 0x0000, 0x2251, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x214f, 0x0000, 0x214e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x223c, 0x223d, 0x0000, 0x2240, 0x223b, 0x223e, 0x0000, 0x223f,
+ 0x224d, 0x225b, 0x225c, 0x0000, 0x225d, 0x225a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_30[] = {
+ 0x0000, 0x2122, 0x2123, 0x2128, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2134, 0x2135, 0x2136, 0x2137, 0x2138, 0x2139, 0x213a, 0x213b,
+ 0x213c, 0x213d, 0x0000, 0x216b, 0x2132, 0x2133, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2a21, 0x2a22, 0x2a23, 0x2a24, 0x2a25, 0x2a26, 0x2a27,
+ 0x2a28, 0x2a29, 0x2a2a, 0x2a2b, 0x2a2c, 0x2a2d, 0x2a2e, 0x2a2f,
+ 0x2a30, 0x2a31, 0x2a32, 0x2a33, 0x2a34, 0x2a35, 0x2a36, 0x2a37,
+ 0x2a38, 0x2a39, 0x2a3a, 0x2a3b, 0x2a3c, 0x2a3d, 0x2a3e, 0x2a3f,
+ 0x2a40, 0x2a41, 0x2a42, 0x2a43, 0x2a44, 0x2a45, 0x2a46, 0x2a47,
+ 0x2a48, 0x2a49, 0x2a4a, 0x2a4b, 0x2a4c, 0x2a4d, 0x2a4e, 0x2a4f,
+ 0x2a50, 0x2a51, 0x2a52, 0x2a53, 0x2a54, 0x2a55, 0x2a56, 0x2a57,
+ 0x2a58, 0x2a59, 0x2a5a, 0x2a5b, 0x2a5c, 0x2a5d, 0x2a5e, 0x2a5f,
+ 0x2a60, 0x2a61, 0x2a62, 0x2a63, 0x2a64, 0x2a65, 0x2a66, 0x2a67,
+ 0x2a68, 0x2a69, 0x2a6a, 0x2a6b, 0x2a6c, 0x2a6d, 0x2a6e, 0x2a6f,
+ 0x2a70, 0x2a71, 0x2a72, 0x2a73, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2b21, 0x2b22, 0x2b23, 0x2b24, 0x2b25, 0x2b26, 0x2b27,
+ 0x2b28, 0x2b29, 0x2b2a, 0x2b2b, 0x2b2c, 0x2b2d, 0x2b2e, 0x2b2f,
+ 0x2b30, 0x2b31, 0x2b32, 0x2b33, 0x2b34, 0x2b35, 0x2b36, 0x2b37,
+ 0x2b38, 0x2b39, 0x2b3a, 0x2b3b, 0x2b3c, 0x2b3d, 0x2b3e, 0x2b3f,
+ 0x2b40, 0x2b41, 0x2b42, 0x2b43, 0x2b44, 0x2b45, 0x2b46, 0x2b47,
+ 0x2b48, 0x2b49, 0x2b4a, 0x2b4b, 0x2b4c, 0x2b4d, 0x2b4e, 0x2b4f,
+ 0x2b50, 0x2b51, 0x2b52, 0x2b53, 0x2b54, 0x2b55, 0x2b56, 0x2b57,
+ 0x2b58, 0x2b59, 0x2b5a, 0x2b5b, 0x2b5c, 0x2b5d, 0x2b5e, 0x2b5f,
+ 0x2b60, 0x2b61, 0x2b62, 0x2b63, 0x2b64, 0x2b65, 0x2b66, 0x2b67,
+ 0x2b68, 0x2b69, 0x2b6a, 0x2b6b, 0x2b6c, 0x2b6d, 0x2b6e, 0x2b6f,
+ 0x2b70, 0x2b71, 0x2b72, 0x2b73, 0x2b74, 0x2b75, 0x2b76, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2124, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_31[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427,
+ 0x2428, 0x2429, 0x242a, 0x242b, 0x242c, 0x242d, 0x242e, 0x242f,
+ 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437,
+ 0x2438, 0x2439, 0x243a, 0x243b, 0x243c, 0x243d, 0x243e, 0x243f,
+ 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447,
+ 0x2448, 0x2449, 0x244a, 0x244b, 0x244c, 0x244d, 0x244e, 0x244f,
+ 0x2450, 0x2451, 0x2452, 0x2453, 0x2121, 0x2455, 0x2456, 0x2457,
+ 0x2458, 0x2459, 0x245a, 0x245b, 0x245c, 0x245d, 0x245e, 0x245f,
+ 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467,
+ 0x2468, 0x2469, 0x246a, 0x246b, 0x246c, 0x246d, 0x246e, 0x246f,
+ 0x2470, 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, 0x2477,
+ 0x2478, 0x2479, 0x247a, 0x247b, 0x247c, 0x247d, 0x247e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_32[] = {
+ 0x2931, 0x2932, 0x2933, 0x2934, 0x2935, 0x2936, 0x2937, 0x2938,
+ 0x2939, 0x293a, 0x293b, 0x293c, 0x293d, 0x293e, 0x293f, 0x2940,
+ 0x2941, 0x2942, 0x2943, 0x2944, 0x2945, 0x2946, 0x2947, 0x2948,
+ 0x2949, 0x294a, 0x294b, 0x294c, 0x225f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2831, 0x2832, 0x2833, 0x2834, 0x2835, 0x2836, 0x2837, 0x2838,
+ 0x2839, 0x283a, 0x283b, 0x283c, 0x283d, 0x283e, 0x283f, 0x2840,
+ 0x2841, 0x2842, 0x2843, 0x2844, 0x2845, 0x2846, 0x2847, 0x2848,
+ 0x2849, 0x284a, 0x284b, 0x284c, 0x0000, 0x0000, 0x0000, 0x225e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_33[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2749, 0x274a, 0x274b, 0x274c, 0x274d, 0x0000, 0x0000, 0x0000,
+ 0x273a, 0x273b, 0x275c, 0x275d, 0x275e, 0x2736, 0x2737, 0x2738,
+ 0x2754, 0x2755, 0x2756, 0x2757, 0x2758, 0x2721, 0x2722, 0x2723,
+ 0x2725, 0x272b, 0x272c, 0x272d, 0x272e, 0x272f, 0x2730, 0x2731,
+ 0x2732, 0x2733, 0x2734, 0x2727, 0x2728, 0x2729, 0x272a, 0x273d,
+ 0x273e, 0x2765, 0x2766, 0x2767, 0x2768, 0x2761, 0x2762, 0x2763,
+ 0x273f, 0x2740, 0x2741, 0x2742, 0x2743, 0x2744, 0x2745, 0x2746,
+ 0x2747, 0x2748, 0x274e, 0x274f, 0x2750, 0x2751, 0x2752, 0x2753,
+ 0x275a, 0x275b, 0x2263, 0x276c, 0x2726, 0x2760, 0x276f, 0x2261,
+ 0x273c, 0x276d, 0x2735, 0x0000, 0x0000, 0x0000, 0x0000, 0x2739,
+ 0x276a, 0x0000, 0x0000, 0x276b, 0x0000, 0x0000, 0x275f, 0x0000,
+ 0x2264, 0x0000, 0x0000, 0x2764, 0x276e, 0x2769, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_4e[] = {
+ 0x6c69, 0x6f4b, 0x0000, 0x7652, 0x0000, 0x0000, 0x0000, 0x5832,
+ 0x6d5b, 0x5f32, 0x5f3e, 0x793b, 0x0000, 0x5c74, 0x0000, 0x0000,
+ 0x0000, 0x7564, 0x0000, 0x0000, 0x7326, 0x5d60, 0x6126, 0x0000,
+ 0x4e78, 0x5c30, 0x0000, 0x0000, 0x0000, 0x0000, 0x632a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7169, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4e2d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7c2f, 0x5321, 0x0000, 0x712b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6751, 0x522c, 0x0000, 0x4e79, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x717d, 0x0000, 0x5e3f, 0x7b3a, 0x7939,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e52, 0x0000,
+ 0x632b, 0x6b60, 0x0000, 0x0000, 0x0000, 0x4e7a, 0x4b77, 0x6525,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4a61, 0x0000, 0x544c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6a61, 0x0000, 0x0000, 0x5c63, 0x5f2d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b6b, 0x0000,
+ 0x0000, 0x0000, 0x516a, 0x0000, 0x0000, 0x0000, 0x5675, 0x0000,
+ 0x6578, 0x0000, 0x0000, 0x5e40, 0x6c23, 0x0000, 0x694d, 0x0000,
+ 0x6a27, 0x6976, 0x7b3b, 0x0000, 0x6769, 0x6f4c, 0x0000, 0x0000,
+ 0x5066, 0x0000, 0x0000, 0x5e41, 0x0000, 0x0000, 0x642c, 0x0000,
+ 0x0000, 0x584c, 0x7971, 0x0000, 0x4e5f, 0x7a24, 0x6632, 0x0000,
+ 0x7a7b, 0x0000, 0x0000, 0x7a3d, 0x4c48, 0x6f4d, 0x5555, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5322, 0x0000,
+ 0x0000, 0x0000, 0x6c51, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6427, 0x6c52, 0x0000, 0x0000, 0x7631, 0x0000, 0x0000, 0x4e7b,
+ 0x0000, 0x0000, 0x5051, 0x4b3f, 0x0000, 0x6d24, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6d28, 0x5e42, 0x7662, 0x6d5c,
+ 0x5c75, 0x6039, 0x0000, 0x0000, 0x0000, 0x544e, 0x0000, 0x7435,
+ 0x0000, 0x0000, 0x0000, 0x535b, 0x5635, 0x6c24, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6466, 0x0000, 0x716a, 0x0000, 0x0000, 0x0000, 0x4b6c, 0x4b40,
+ 0x0000, 0x0000, 0x0000, 0x6c72, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_4f[] = {
+ 0x0000, 0x506a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7972, 0x6c25, 0x505f, 0x0000, 0x676a, 0x506b, 0x5c51,
+ 0x5b69, 0x7d4c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b57,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5a61, 0x0000, 0x5636, 0x0000,
+ 0x635f, 0x0000, 0x5e43, 0x0000, 0x5e44, 0x4a21, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6e6c, 0x0000, 0x0000, 0x5323, 0x6e37,
+ 0x784f, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a48, 0x6e38, 0x712c,
+ 0x7125, 0x694e, 0x0000, 0x0000, 0x0000, 0x793c, 0x0000, 0x0000,
+ 0x0000, 0x6579, 0x6c6a, 0x5d56, 0x6d42, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7825, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x653a,
+ 0x5b58, 0x0000, 0x0000, 0x4a22, 0x0000, 0x0000, 0x514d, 0x0000,
+ 0x0000, 0x0000, 0x6e6d, 0x0000, 0x0000, 0x0000, 0x6c6b, 0x5e45,
+ 0x0000, 0x6360, 0x0000, 0x4a49, 0x7269, 0x0000, 0x522d, 0x0000,
+ 0x7636, 0x0000, 0x4e42, 0x5647, 0x0000, 0x6334, 0x0000, 0x712d,
+ 0x0000, 0x6a62, 0x0000, 0x0000, 0x0000, 0x0000, 0x5742, 0x0000,
+ 0x7327, 0x0000, 0x0000, 0x4d6a, 0x0000, 0x6b6e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5932, 0x7d25,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7655, 0x5562, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c25,
+ 0x0000, 0x0000, 0x4c75, 0x7535, 0x642d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x676b, 0x7155, 0x0000, 0x0000, 0x0000, 0x703b, 0x0000,
+ 0x0000, 0x6935, 0x0000, 0x4c49, 0x7a55, 0x0000, 0x0000, 0x6154,
+ 0x0000, 0x0000, 0x5756, 0x0000, 0x0000, 0x5c41, 0x0000, 0x5e46,
+ 0x7a6f, 0x6361, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6173, 0x5c76,
+ 0x0000, 0x4e7c, 0x0000, 0x5b44, 0x0000, 0x7871, 0x0000, 0x0000,
+ 0x5c64, 0x0000, 0x656f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_50[] = {
+ 0x0000, 0x0000, 0x5c31, 0x0000, 0x0000, 0x0000, 0x5556, 0x0000,
+ 0x0000, 0x735a, 0x0000, 0x4b41, 0x0000, 0x5b43, 0x0000, 0x0000,
+ 0x0000, 0x597a, 0x536e, 0x0000, 0x0000, 0x0000, 0x7a38, 0x0000,
+ 0x0000, 0x7d26, 0x6b6f, 0x0000, 0x7426, 0x0000, 0x4c4a, 0x7328,
+ 0x0000, 0x735b, 0x0000, 0x5b27, 0x7637, 0x0000, 0x4f66, 0x7072,
+ 0x4b5a, 0x0000, 0x6752, 0x5743, 0x7670, 0x685e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6526, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6567, 0x0000, 0x0000, 0x0000, 0x4a23,
+ 0x4c27, 0x6a49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7836,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7a25, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x712e, 0x0000, 0x6f4e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b6d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7630, 0x6f4f, 0x694f, 0x0000,
+ 0x775e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4e53, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c77, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b28, 0x0000, 0x0000,
+ 0x0000, 0x4b78, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5f21, 0x5d61, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x754a, 0x6936, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x676c, 0x6e6e, 0x0000, 0x7370, 0x0000, 0x5f3f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c4b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5041, 0x0000, 0x0000,
+ 0x0000, 0x7452, 0x603a, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f40,
+ 0x0000, 0x4e60, 0x0000, 0x0000, 0x0000, 0x5c52, 0x7d6a, 0x0000,
+ 0x0000, 0x0000, 0x5676, 0x0000, 0x0000, 0x0000, 0x6a4a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6869, 0x0000, 0x632c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7350, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4a24, 0x0000, 0x5b78, 0x0000, 0x0000, 0x0000, 0x5e47
+};
+
+static unsigned short ksc5601_from_unicode_51[] = {
+ 0x6b70, 0x7156, 0x0000, 0x0000, 0x6562, 0x0000, 0x4c4c, 0x0000,
+ 0x0000, 0x4b7b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6a63, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f41,
+ 0x0000, 0x566d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6950, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6e39, 0x0000, 0x0000, 0x0000, 0x0000, 0x5563,
+ 0x0000, 0x0000, 0x5153, 0x0000, 0x6570, 0x0000, 0x0000, 0x0000,
+ 0x6834, 0x6b43, 0x0000, 0x6a2a, 0x7a7c, 0x7576, 0x703c, 0x7d54,
+ 0x603b, 0x4e43, 0x0000, 0x503a, 0x773a, 0x5873, 0x774d, 0x0000,
+ 0x0000, 0x0000, 0x642e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x545f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5067, 0x0000, 0x0000, 0x6c7d, 0x0000, 0x522e,
+ 0x6e6f, 0x5557, 0x6a64, 0x7822, 0x4d6b, 0x573f, 0x7b31, 0x0000,
+ 0x0000, 0x4d6c, 0x0000, 0x0000, 0x0000, 0x5c32, 0x506c, 0x4e7d,
+ 0x6e70, 0x0000, 0x0000, 0x0000, 0x4c42, 0x0000, 0x0000, 0x0000,
+ 0x506d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6577, 0x0000,
+ 0x0000, 0x0000, 0x737c, 0x0000, 0x0000, 0x6e22, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5933, 0x0000, 0x0000, 0x5874, 0x0000, 0x6937,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4e2e, 0x0000, 0x0000, 0x0000, 0x0000, 0x5922, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5871, 0x0000, 0x544f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6527, 0x5232,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5629, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7422, 0x0000, 0x7157, 0x0000,
+ 0x0000, 0x5558, 0x0000, 0x703d, 0x5273, 0x5450, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5272, 0x6b6a, 0x7d6b, 0x0000,
+ 0x0000, 0x5b6d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7c45, 0x4b42, 0x0000, 0x0000, 0x0000, 0x0000, 0x7d55, 0x0000,
+ 0x7448, 0x686a, 0x7573, 0x0000, 0x0000, 0x795e, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_52[] = {
+ 0x536f, 0x0000, 0x0000, 0x6c53, 0x0000, 0x0000, 0x5d42, 0x6f37,
+ 0x6754, 0x0000, 0x4a4a, 0x0000, 0x0000, 0x0000, 0x597b, 0x0000,
+ 0x0000, 0x7a7d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x562a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7478, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7777, 0x5c2c, 0x0000, 0x0000,
+ 0x0000, 0x5757, 0x5f22, 0x0000, 0x0000, 0x0000, 0x4e3e, 0x0000,
+ 0x5370, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7024, 0x616c,
+ 0x4f67, 0x734b, 0x6d29, 0x4a3e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x746f, 0x0000, 0x0000, 0x0000, 0x764e,
+ 0x0000, 0x0000, 0x5e7b, 0x503b, 0x5537, 0x6e71, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7428, 0x0000, 0x5c78, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4b27, 0x0000, 0x5a4e, 0x0000, 0x0000,
+ 0x0000, 0x6066, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6d25, 0x6e72, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c79,
+ 0x0000, 0x0000, 0x795c, 0x0000, 0x0000, 0x735c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7872, 0x0000, 0x7479,
+ 0x0000, 0x0000, 0x0000, 0x7c71, 0x0000, 0x0000, 0x0000, 0x503c,
+ 0x5b79, 0x5731, 0x0000, 0x0000, 0x0000, 0x4b7c, 0x0000, 0x0000,
+ 0x0000, 0x7025, 0x4b7d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5574, 0x0000, 0x0000, 0x0000, 0x4d6d,
+ 0x4a25, 0x0000, 0x0000, 0x562b, 0x5042, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x703e, 0x523d, 0x4c24, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7a36, 0x0000,
+ 0x0000, 0x4c4d, 0x0000, 0x5a7a, 0x0000, 0x764f, 0x0000, 0x6938,
+ 0x0000, 0x5875, 0x0000, 0x0000, 0x0000, 0x4c4e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5270, 0x0000, 0x0000, 0x5451, 0x696d, 0x0000,
+ 0x4a6b, 0x5962, 0x0000, 0x7d32, 0x0000, 0x632d, 0x523e, 0x5934,
+ 0x0000, 0x0000, 0x6127, 0x6e53, 0x5043, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7d33, 0x0000, 0x5564, 0x0000, 0x0000,
+ 0x4f68, 0x0000, 0x6d43, 0x5032, 0x0000, 0x0000, 0x4e7e, 0x5a28
+};
+
+static unsigned short ksc5601_from_unicode_53[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7850, 0x0000, 0x0000,
+ 0x7d56, 0x0000, 0x0000, 0x0000, 0x0000, 0x7851, 0x0000, 0x7852,
+ 0x5c53, 0x0000, 0x0000, 0x0000, 0x0000, 0x5d62, 0x7b79, 0x5b45,
+ 0x0000, 0x6335, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6d5d, 0x4e44, 0x0000, 0x4b21, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5d63, 0x0000, 0x0000, 0x0000, 0x0000, 0x7c5d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x792f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x527b,
+ 0x4f21, 0x6428, 0x0000, 0x7436, 0x6c7e, 0x0000, 0x0000, 0x632e,
+ 0x676d, 0x7d41, 0x5a62, 0x0000, 0x0000, 0x5833, 0x0000, 0x0000,
+ 0x0000, 0x5d64, 0x706f, 0x7671, 0x7a70, 0x0000, 0x0000, 0x5175,
+ 0x0000, 0x0000, 0x5a4f, 0x0000, 0x5c54, 0x0000, 0x5c26, 0x0000,
+ 0x6f3f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e4f, 0x0000,
+ 0x6059, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5956,
+ 0x6c54, 0x6a4b, 0x0000, 0x0000, 0x4a3f, 0x516b, 0x0000, 0x4f69,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x716d, 0x0000, 0x4c4f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6478, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x646d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5758, 0x0000, 0x7d27, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a2b,
+ 0x7632, 0x0000, 0x0000, 0x0000, 0x0000, 0x4f70, 0x793d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6674, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4b5b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5f33, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6951, 0x7329, 0x5060, 0x6952, 0x0000, 0x5a63, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6252, 0x0000, 0x7622, 0x6174,
+ 0x0000, 0x0000, 0x0000, 0x5a64, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6755, 0x753f, 0x4f22, 0x4d2f, 0x4f23, 0x0000, 0x0000,
+ 0x0000, 0x4d30, 0x717e, 0x5023, 0x612f, 0x7823, 0x0000, 0x4a26,
+ 0x773b, 0x726a, 0x5e48, 0x6953, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5e49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_54[] = {
+ 0x0000, 0x0000, 0x0000, 0x7d5e, 0x4a40, 0x0000, 0x0000, 0x0000,
+ 0x796a, 0x514e, 0x6e54, 0x0000, 0x5452, 0x5923, 0x7d28, 0x5759,
+ 0x774e, 0x7a3e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4f56, 0x0000, 0x5770, 0x0000, 0x6b61,
+ 0x7845, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c7a, 0x0000,
+ 0x0000, 0x5d43, 0x0000, 0x795f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x676f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7d65, 0x7623, 0x0000, 0x597c, 0x7d29, 0x0000, 0x676e, 0x0000,
+ 0x0000, 0x0000, 0x5565, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6f50, 0x0000, 0x4d31, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7722, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7132, 0x0000, 0x7131, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4d32, 0x0000, 0x5a2b, 0x0000, 0x4a27, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6362, 0x7b3c, 0x5924, 0x0000, 0x0000,
+ 0x6e3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7853, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7b7a, 0x0000, 0x4f24, 0x0000,
+ 0x5c7b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7663, 0x0000, 0x0000, 0x0000,
+ 0x6d2a, 0x0000, 0x0000, 0x7221, 0x4e61, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7a26, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7960, 0x0000, 0x0000, 0x0000, 0x0000, 0x666c, 0x0000, 0x0000,
+ 0x646e, 0x7921, 0x0000, 0x0000, 0x7b6f, 0x0000, 0x0000, 0x0000,
+ 0x796b, 0x6e23, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6a2c, 0x0000, 0x0000, 0x0000, 0x4a28, 0x0000, 0x0000,
+ 0x747a, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d56, 0x7c76, 0x0000,
+ 0x0000, 0x0000, 0x7449, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7854, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_55[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7826, 0x0000, 0x5e4a, 0x7246,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x575a, 0x0000,
+ 0x5350, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5845, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a66,
+ 0x0000, 0x735d, 0x0000, 0x0000, 0x0000, 0x645a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7664, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7672, 0x0000, 0x5f42, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x597d,
+ 0x0000, 0x0000, 0x0000, 0x4c76, 0x0000, 0x0000, 0x533a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x642f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7961, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7026, 0x0000, 0x0000, 0x0000,
+ 0x4b53, 0x0000, 0x0000, 0x0000, 0x603c, 0x0000, 0x744a, 0x5154,
+ 0x0000, 0x7d2a, 0x7962, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7437, 0x7d42, 0x7c30, 0x0000, 0x7d6c, 0x4a62, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7d3d,
+ 0x0000, 0x6a67, 0x5f43, 0x5152, 0x4e62, 0x0000, 0x5324, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7d2b, 0x0000, 0x5f60,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7247, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6770, 0x0000, 0x506e, 0x0000, 0x0000, 0x732a,
+ 0x0000, 0x0000, 0x0000, 0x5e4b, 0x7638, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6175, 0x7133, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_56[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7723, 0x0000,
+ 0x0000, 0x4a29, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4f25, 0x0000, 0x0000, 0x5f44,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6130,
+ 0x0000, 0x0000, 0x703f, 0x0000, 0x7624, 0x0000, 0x6336, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7a46, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x506f, 0x0000, 0x0000, 0x7d6d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5d44, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7c77, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x663f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5e2d, 0x0000, 0x7a3f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6571, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6d44, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5225, 0x0000, 0x0000, 0x7d6e, 0x0000, 0x0000,
+ 0x0000, 0x7536, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6176, 0x5e4c, 0x0000, 0x0000, 0x7c5e, 0x0000,
+ 0x6c57, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4d5d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5637, 0x4d33, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_57[] = {
+ 0x0000, 0x0000, 0x0000, 0x7855, 0x6558, 0x0000, 0x0000, 0x0000,
+ 0x4f6a, 0x0000, 0x0000, 0x4f50, 0x0000, 0x6a4c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6a2e, 0x6a2d, 0x0000, 0x0000, 0x5371, 0x0000,
+ 0x5325, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x774f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6e24, 0x0000, 0x0000, 0x0000, 0x0000, 0x5024, 0x0000, 0x0000,
+ 0x7222, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5070, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7223, 0x0000, 0x7778, 0x0000, 0x0000, 0x0000, 0x0000, 0x5033,
+ 0x0000, 0x0000, 0x5b29, 0x0000, 0x0000, 0x533b, 0x4a6c, 0x0000,
+ 0x7126, 0x4b55, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7767, 0x0000, 0x0000, 0x4d5e, 0x0000, 0x7724, 0x0000,
+ 0x0000, 0x0000, 0x7840, 0x0000, 0x0000, 0x0000, 0x535d, 0x0000,
+ 0x4c50, 0x0000, 0x0000, 0x0000, 0x0000, 0x4f26, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7673, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6177, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x535c, 0x0000, 0x0000, 0x7a7e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7a27, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6b59, 0x0000, 0x4f27, 0x6a2f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x646f, 0x0000, 0x0000, 0x0000, 0x6939,
+ 0x7158, 0x0000, 0x0000, 0x5858, 0x0000, 0x0000, 0x6072, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6634,
+ 0x5c7c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7371, 0x0000, 0x0000, 0x0000, 0x6350, 0x0000, 0x0000, 0x727b,
+ 0x0000, 0x5b46, 0x5071, 0x0000, 0x5072, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_58[] = {
+ 0x4f5c, 0x0000, 0x5351, 0x0000, 0x0000, 0x4c31, 0x7758, 0x0000,
+ 0x4b28, 0x6b3c, 0x643e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x745c, 0x0000,
+ 0x0000, 0x5c42, 0x0000, 0x0000, 0x7027, 0x0000, 0x0000, 0x6640,
+ 0x0000, 0x0000, 0x4a6d, 0x0000, 0x0000, 0x0000, 0x0000, 0x686b,
+ 0x6568, 0x5c43, 0x0000, 0x0000, 0x6d5e, 0x5372, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4c77, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4e54, 0x672b, 0x0000, 0x0000, 0x0000, 0x4b43,
+ 0x0000, 0x6131, 0x0000, 0x0000, 0x7732, 0x0000, 0x0000, 0x5373,
+ 0x5352, 0x0000, 0x7540, 0x0000, 0x0000, 0x0000, 0x5f5d, 0x0000,
+ 0x0000, 0x6e73, 0x6771, 0x0000, 0x7d34, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7248, 0x0000, 0x0000,
+ 0x0000, 0x7352, 0x0000, 0x0000, 0x6e74, 0x0000, 0x6253, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4c51, 0x0000, 0x5f6a, 0x0000, 0x0000,
+ 0x0000, 0x693a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5957, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x754d, 0x0000, 0x7172, 0x7a47,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5978, 0x5442, 0x0000, 0x0000, 0x0000, 0x0000, 0x7665, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5d45, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6772, 0x6d5f, 0x0000, 0x0000, 0x4a4b, 0x0000,
+ 0x0000, 0x5b7a, 0x0000, 0x0000, 0x0000, 0x6835, 0x0000, 0x5326,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7d35, 0x0000,
+ 0x0000, 0x7949, 0x0000, 0x6462, 0x0000, 0x7b3d, 0x0000, 0x0000,
+ 0x5264, 0x4e45, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e55, 0x5256,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x653d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5e4d, 0x6c73, 0x0000, 0x0000, 0x6d60,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6c6c, 0x7b3e, 0x5f6b, 0x0000, 0x6178, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_59[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x793e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5073, 0x602a, 0x6862, 0x0000,
+ 0x0000, 0x6254, 0x527d, 0x0000, 0x6528, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5953, 0x0000, 0x0000, 0x0000, 0x0000, 0x535e,
+ 0x0000, 0x7438, 0x773c, 0x5c7d, 0x0000, 0x686c, 0x6467, 0x0000,
+ 0x0000, 0x6377, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6c28,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7a71, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6572, 0x0000, 0x0000, 0x5074,
+ 0x5155, 0x5c65, 0x0000, 0x0000, 0x0000, 0x0000, 0x5025, 0x7134,
+ 0x7c31, 0x5050, 0x0000, 0x0000, 0x5d46, 0x7a51, 0x0000, 0x775f,
+ 0x0000, 0x0000, 0x7a28, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6e75, 0x0000, 0x5e4e, 0x0000, 0x0000, 0x0000, 0x0000, 0x6773,
+ 0x0000, 0x0000, 0x772c, 0x6b44, 0x6d61, 0x602b, 0x5d47, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5233, 0x523f, 0x0000, 0x0000, 0x0000,
+ 0x4a4c, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b3f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x657d, 0x5d65, 0x584d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6c74, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5075, 0x0000, 0x0000, 0x686d, 0x5052,
+ 0x0000, 0x5958, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7666, 0x0000, 0x0000,
+ 0x5b2a, 0x0000, 0x0000, 0x0000, 0x7760, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5859, 0x0000, 0x7423, 0x0000, 0x0000, 0x745d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6f51, 0x0000, 0x0000, 0x5935, 0x0000,
+ 0x0000, 0x6d2b, 0x0000, 0x6337, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6e3b, 0x4d34, 0x0000, 0x6073, 0x6a4d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6c75, 0x686e, 0x0000, 0x4b29, 0x712f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a4d, 0x0000,
+ 0x6c29, 0x0000, 0x726b, 0x0000, 0x7d6f, 0x0000, 0x7973, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6641, 0x0000, 0x0000, 0x6c58, 0x0000, 0x0000, 0x0000, 0x6d2c
+};
+
+static unsigned short ksc5601_from_unicode_5a[] = {
+ 0x0000, 0x6a4e, 0x0000, 0x685f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5e4f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5226, 0x0000, 0x0000, 0x6774, 0x5156, 0x0000, 0x0000, 0x6642,
+ 0x6363, 0x0000, 0x0000, 0x0000, 0x0000, 0x6430, 0x0000, 0x0000,
+ 0x0000, 0x5834, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7625, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x735e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5725, 0x0000, 0x0000, 0x0000, 0x0000, 0x7768, 0x0000,
+ 0x0000, 0x6846, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7b66, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5d66, 0x0000, 0x0000, 0x0000, 0x5c7e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x585a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5a2c, 0x6a30, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6338, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4a2a, 0x6179, 0x0000, 0x6a31, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x726c, 0x0000, 0x0000, 0x7a6e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6e55, 0x0000, 0x0000, 0x0000, 0x0000, 0x7974, 0x0000,
+ 0x0000, 0x526c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_5b[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b7b, 0x0000, 0x0000,
+ 0x0000, 0x7d70, 0x0000, 0x603d, 0x4e63, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7846, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5e2e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5f45, 0x0000, 0x0000, 0x653e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6d2d, 0x7a6a, 0x0000, 0x0000, 0x4d6e, 0x6d26, 0x0000, 0x6d2e,
+ 0x706d, 0x0000, 0x5d21, 0x0000, 0x6d2f, 0x7c78, 0x0000, 0x586b,
+ 0x0000, 0x0000, 0x0000, 0x4c79, 0x4d35, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7a29, 0x0000, 0x615d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6255, 0x6d4f, 0x0000, 0x0000, 0x0000, 0x5d22, 0x0000, 0x0000,
+ 0x794a, 0x0000, 0x6a68, 0x0000, 0x656d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x536b, 0x0000, 0x6954,
+ 0x617a, 0x644c, 0x0000, 0x6164, 0x6847, 0x0000, 0x0000, 0x4e5b,
+ 0x0000, 0x0000, 0x0000, 0x5c55, 0x0000, 0x7735, 0x7c73, 0x7073,
+ 0x4e2f, 0x7135, 0x6f52, 0x6848, 0x6b71, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4b54, 0x603e, 0x6378, 0x6a69, 0x7c32, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6074, 0x0000, 0x4f60, 0x0000,
+ 0x6e25, 0x0000, 0x0000, 0x7a2a, 0x6643, 0x6132, 0x4a2b, 0x0000,
+ 0x6364, 0x693b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6256,
+ 0x7372, 0x0000, 0x6e56, 0x6a32, 0x5076, 0x6c59, 0x5a4b, 0x4f28,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5d23, 0x0000, 0x0000, 0x0000,
+ 0x585b, 0x0000, 0x794e, 0x6955, 0x6351, 0x0000, 0x0000, 0x523c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x582c, 0x734c,
+ 0x0000, 0x4d7b, 0x7656, 0x0000, 0x6775, 0x686f, 0x6379, 0x523b,
+ 0x7373, 0x637b, 0x0000, 0x5e50, 0x4e30, 0x0000, 0x5677, 0x7159,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7541, 0x5c44, 0x0000,
+ 0x753b, 0x0000, 0x5e51, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_5c[] = {
+ 0x0000, 0x5c66, 0x0000, 0x0000, 0x5e52, 0x0000, 0x0000, 0x6d62,
+ 0x6e76, 0x6a4f, 0x706e, 0x637c, 0x0000, 0x535f, 0x5374, 0x6133,
+ 0x0000, 0x6134, 0x0000, 0x0000, 0x0000, 0x0000, 0x7453, 0x0000,
+ 0x0000, 0x5f46, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6956, 0x0000, 0x0000, 0x0000,
+ 0x5b2b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7626, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6339, 0x6b45, 0x7429, 0x4d36, 0x5279, 0x0000, 0x5a2d, 0x5263,
+ 0x4f51, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b5c, 0x4c7a, 0x0000,
+ 0x4f5d, 0x0000, 0x0000, 0x6829, 0x0000, 0x633b, 0x633a, 0x0000,
+ 0x0000, 0x605a, 0x0000, 0x0000, 0x0000, 0x6e77, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5c33, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5375, 0x0000, 0x5265, 0x0000, 0x7635, 0x575b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6155, 0x0000, 0x0000, 0x546a,
+ 0x0000, 0x5f23, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7d5f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5077, 0x6d54, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4b2a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x645b, 0x0000, 0x617b, 0x4b22, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5360, 0x0000, 0x643f, 0x0000, 0x7b40, 0x0000, 0x5a3e,
+ 0x644d, 0x0000, 0x5639, 0x0000, 0x0000, 0x0000, 0x6f40, 0x0000,
+ 0x617c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7639, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5f47, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6431, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c67,
+ 0x5c68, 0x0000, 0x0000, 0x0000, 0x7a56, 0x0000, 0x5376, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x715a, 0x0000, 0x7a72, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_5d[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x627d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x554f, 0x5078, 0x0000,
+ 0x0000, 0x4d5f, 0x0000, 0x0000, 0x754b, 0x0000, 0x6470, 0x4b2b,
+ 0x0000, 0x5744, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x627e,
+ 0x0000, 0x5d5a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5a2e, 0x4a6e, 0x0000, 0x0000, 0x0000,
+ 0x5176, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6321, 0x0000, 0x0000, 0x6863, 0x0000, 0x0000, 0x732b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4f29,
+ 0x0000, 0x0000, 0x0000, 0x5377, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5471, 0x0000, 0x0000,
+ 0x4e64, 0x0000, 0x6872, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6575, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x672e, 0x0000, 0x563a, 0x0000, 0x5f6c, 0x6440, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6864, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5835, 0x0000, 0x0000, 0x0000, 0x645c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7439, 0x7136, 0x0000,
+ 0x0000, 0x625e, 0x6135, 0x0000, 0x0000, 0x4d6f, 0x7127, 0x4e65,
+ 0x4b5d, 0x0000, 0x0000, 0x5963, 0x0000, 0x0000, 0x732c, 0x0000,
+ 0x0000, 0x5079, 0x6c2b, 0x5e53, 0x7769, 0x0000, 0x0000, 0x7975,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x615e, 0x4b6e, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_5e[] = {
+ 0x0000, 0x0000, 0x633c, 0x7856, 0x0000, 0x0000, 0x5b6e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7d71, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7736, 0x0000, 0x0000, 0x0000, 0x0000, 0x745e, 0x0000,
+ 0x0000, 0x726d, 0x0000, 0x5b59, 0x0000, 0x7028, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x617d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5e54, 0x0000, 0x602c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6d63, 0x0000, 0x0000, 0x5361, 0x0000,
+ 0x5f48, 0x0000, 0x0000, 0x0000, 0x0000, 0x5936, 0x0000, 0x7d2c,
+ 0x6f53, 0x0000, 0x0000, 0x0000, 0x6441, 0x786b, 0x0000, 0x5b2c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7c46, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x582d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x763a,
+ 0x0000, 0x5b5f, 0x5353, 0x7847, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4a4e, 0x7841, 0x5234, 0x0000, 0x0000, 0x5c34,
+ 0x7a39, 0x4a4f, 0x0000, 0x7c33, 0x6a6a, 0x6a6b, 0x507a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6d64, 0x0000, 0x0000, 0x5d67,
+ 0x0000, 0x0000, 0x5f49, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f6d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6e3c, 0x0000, 0x6f41,
+ 0x0000, 0x0000, 0x4c52, 0x0000, 0x5d24, 0x0000, 0x0000, 0x0000,
+ 0x5f4a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5378, 0x7128,
+ 0x0000, 0x0000, 0x0000, 0x4d37, 0x0000, 0x6f54, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x645d, 0x5f6e, 0x4b2c,
+ 0x693c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a6c, 0x0000,
+ 0x0000, 0x0000, 0x5f4b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x793f, 0x562f, 0x5227, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4f2a, 0x0000, 0x0000, 0x4e29, 0x0000, 0x0000, 0x5678, 0x0000,
+ 0x0000, 0x0000, 0x7137, 0x6e78, 0x0000, 0x0000, 0x0000, 0x5959,
+ 0x735f, 0x0000, 0x7848, 0x4e46, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5566, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7466, 0x0000, 0x0000, 0x6645, 0x6f55,
+ 0x0000, 0x0000, 0x4b6f, 0x7c5f, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_5f[] = {
+ 0x0000, 0x5c27, 0x0000, 0x0000, 0x5257, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7849, 0x0000, 0x0000, 0x0000, 0x0000, 0x6352,
+ 0x0000, 0x633d, 0x0000, 0x4f61, 0x7040, 0x6c5a, 0x0000, 0x5d57,
+ 0x7b70, 0x0000, 0x0000, 0x6c2c, 0x0000, 0x0000, 0x0000, 0x7029,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7a57, 0x7b41,
+ 0x0000, 0x5240, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6530, 0x0000, 0x0000, 0x0000, 0x6d65, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4b2d, 0x0000, 0x7930, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7725, 0x0000, 0x4b2e, 0x0000, 0x5a2f, 0x0000, 0x5836, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5327, 0x7b32,
+ 0x0000, 0x7d44, 0x0000, 0x6c2d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7b21, 0x0000, 0x0000, 0x0000, 0x6569, 0x696e,
+ 0x0000, 0x7374, 0x7873, 0x7041, 0x5e2f, 0x7830, 0x0000, 0x0000,
+ 0x7360, 0x672f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b2d,
+ 0x0000, 0x6635, 0x0000, 0x0000, 0x7928, 0x0000, 0x0000, 0x5d58,
+ 0x6859, 0x6f56, 0x0000, 0x0000, 0x0000, 0x5362, 0x0000, 0x625f,
+ 0x0000, 0x0000, 0x7c60, 0x5748, 0x7d2d, 0x0000, 0x0000, 0x0000,
+ 0x5f6f, 0x4c53, 0x5379, 0x0000, 0x0000, 0x0000, 0x0000, 0x5470,
+ 0x5b47, 0x5e55, 0x0000, 0x0000, 0x0000, 0x0000, 0x7074, 0x0000,
+ 0x5550, 0x6559, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7c47, 0x5c56, 0x6260, 0x0000, 0x0000, 0x0000, 0x5a30, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7323, 0x0000, 0x536c,
+ 0x0000, 0x744b, 0x0000, 0x0000, 0x0000, 0x7d45, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x637d, 0x0000, 0x7931, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x507b, 0x6c5b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x753c, 0x7224,
+ 0x584e, 0x584f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7577, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7661, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5237, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b6c, 0x0000, 0x5d48
+};
+
+static unsigned short ksc5601_from_unicode_60[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6468,
+ 0x0000, 0x0000, 0x5241, 0x0000, 0x0000, 0x0000, 0x7857, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x563b, 0x5e56, 0x0000, 0x0000,
+ 0x773d, 0x6c2e, 0x0000, 0x0000, 0x0000, 0x5061, 0x0000, 0x6075,
+ 0x6a33, 0x0000, 0x4e56, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c25,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6c76, 0x6261, 0x633e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7c48, 0x0000, 0x0000,
+ 0x4d70, 0x0000, 0x7976, 0x0000, 0x0000, 0x5f70, 0x0000, 0x0000,
+ 0x0000, 0x653f, 0x0000, 0x0000, 0x0000, 0x4e3f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7c61, 0x6d30, 0x7d51, 0x763b, 0x0000, 0x0000,
+ 0x794f, 0x6b5a, 0x4a41, 0x0000, 0x5238, 0x4d71, 0x0000, 0x6353,
+ 0x7d66, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x666d, 0x0000, 0x0000,
+ 0x0000, 0x637a, 0x0000, 0x0000, 0x702a, 0x7950, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7c62, 0x0000, 0x7827, 0x0000,
+ 0x0000, 0x0000, 0x6165, 0x6e79, 0x0000, 0x0000, 0x0000, 0x6776,
+ 0x6a6d, 0x0000, 0x0000, 0x7c34, 0x7542, 0x0000, 0x0000, 0x575c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7075, 0x0000, 0x5d68, 0x536d, 0x757c, 0x0000, 0x5a3f, 0x0000,
+ 0x4c7b, 0x0000, 0x0000, 0x0000, 0x537a, 0x7424, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6f57, 0x0000, 0x5443,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7b63, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7b6d, 0x0000, 0x602d, 0x0000, 0x0000, 0x6a6e,
+ 0x7b33, 0x6442, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7667, 0x525d, 0x0000, 0x5f4c, 0x0000, 0x0000, 0x7c49, 0x0000,
+ 0x0000, 0x6529, 0x6076, 0x7633, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_61[] = {
+ 0x0000, 0x617e, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b70, 0x0000,
+ 0x6a6f, 0x6a70, 0x0000, 0x0000, 0x0000, 0x5a40, 0x7834, 0x6b72,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6443, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6957, 0x6471, 0x0000, 0x0000, 0x0000, 0x4a6f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e57,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7c4a, 0x0000, 0x0000, 0x0000, 0x7361, 0x0000, 0x0000, 0x4b44,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6365, 0x0000, 0x4b45, 0x6a34,
+ 0x0000, 0x0000, 0x693d, 0x0000, 0x5749, 0x0000, 0x0000, 0x6b5b,
+ 0x6d31, 0x0000, 0x4c43, 0x773e, 0x7c4b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7874, 0x0000, 0x5937, 0x0000, 0x0000,
+ 0x7353, 0x7354, 0x0000, 0x0000, 0x0000, 0x7764, 0x0000, 0x7751,
+ 0x0000, 0x0000, 0x5837, 0x4e31, 0x4a42, 0x0000, 0x0000, 0x7b34,
+ 0x4b46, 0x0000, 0x0000, 0x7076, 0x0000, 0x0000, 0x5567, 0x0000,
+ 0x6a50, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c54, 0x4b2f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x742a, 0x692f, 0x0000,
+ 0x0000, 0x7543, 0x6958, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5d69, 0x0000, 0x0000, 0x0000, 0x7173, 0x0000,
+ 0x557b, 0x5e3b, 0x0000, 0x0000, 0x747b, 0x0000, 0x0000, 0x0000,
+ 0x7d73, 0x7d72, 0x7726, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5d49, 0x0000, 0x0000, 0x5453,
+ 0x0000, 0x4c28, 0x0000, 0x5a41, 0x4c55, 0x0000, 0x5964, 0x0000,
+ 0x0000, 0x0000, 0x7a4a, 0x0000, 0x0000, 0x0000, 0x6563, 0x0000,
+ 0x0000, 0x0000, 0x533c, 0x0000, 0x0000, 0x0000, 0x4a70, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5044, 0x0000, 0x0000, 0x0000, 0x4a50,
+ 0x7a2b, 0x6b6b, 0x6778, 0x5965, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5157, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7324, 0x0000, 0x0000, 0x0000, 0x5158, 0x7c63,
+ 0x7a58, 0x0000, 0x7355, 0x0000, 0x4f2b, 0x0000, 0x0000, 0x6b73
+};
+
+static unsigned short ksc5601_from_unicode_62[] = {
+ 0x557c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5354,
+ 0x4d7c, 0x0000, 0x5966, 0x0000, 0x6279, 0x6221, 0x6b54, 0x0000,
+ 0x6077, 0x6432, 0x4c7c, 0x0000, 0x0000, 0x0000, 0x7b64, 0x0000,
+ 0x0000, 0x0000, 0x742b, 0x0000, 0x0000, 0x0000, 0x0000, 0x503d,
+ 0x0000, 0x4a71, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6f38, 0x0000, 0x0000, 0x0000, 0x5740, 0x0000,
+ 0x6e7a, 0x7d74, 0x0000, 0x0000, 0x5363, 0x0000, 0x7b42, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5568, 0x5b2e,
+ 0x6136, 0x7837, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x603f,
+ 0x7b43, 0x5d6a, 0x0000, 0x6222, 0x0000, 0x6e26, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7668, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7675, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5d4a, 0x0000,
+ 0x0000, 0x5062, 0x0000, 0x0000, 0x0000, 0x0000, 0x5d26, 0x0000,
+ 0x0000, 0x5d6b, 0x0000, 0x0000, 0x6479, 0x0000, 0x0000, 0x632f,
+ 0x507c, 0x0000, 0x0000, 0x0000, 0x747c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4c3c, 0x776a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6564, 0x5f71, 0x0000, 0x0000, 0x7761, 0x0000, 0x7977,
+ 0x6f39, 0x0000, 0x0000, 0x7858, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7929, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7859, 0x0000, 0x0000, 0x0000, 0x6e3d, 0x0000, 0x0000,
+ 0x0000, 0x5846, 0x0000, 0x0000, 0x6463, 0x754e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5d59, 0x0000, 0x0000, 0x0000, 0x0000, 0x5967,
+ 0x5239, 0x517e, 0x0000, 0x0000, 0x5a65, 0x5a50, 0x0000, 0x5159,
+ 0x4e58, 0x0000, 0x4b5e, 0x742c, 0x5a7b, 0x0000, 0x7669, 0x6873,
+ 0x4f2c, 0x7070, 0x0000, 0x747d, 0x5b48, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4e40, 0x6354, 0x514f, 0x7175,
+ 0x0000, 0x4d72, 0x0000, 0x4f6b, 0x0000, 0x0000, 0x0000, 0x4d38,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6326, 0x515a
+};
+
+static unsigned short ksc5601_from_unicode_63[] = {
+ 0x0000, 0x7225, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7226,
+ 0x0000, 0x644e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x537b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7129, 0x0000, 0x0000, 0x0000, 0x7249,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6f58, 0x6649, 0x0000, 0x5838, 0x7a73, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7335, 0x0000, 0x0000, 0x7824, 0x0000, 0x0000, 0x5173,
+ 0x6648, 0x0000, 0x0000, 0x0000, 0x0000, 0x785a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c69,
+ 0x5e57, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b5f, 0x0000,
+ 0x0000, 0x0000, 0x4f6c, 0x0000, 0x0000, 0x0000, 0x0000, 0x745f,
+ 0x0000, 0x0000, 0x5174, 0x523a, 0x0000, 0x0000, 0x0000, 0x5f72,
+ 0x0000, 0x0000, 0x0000, 0x6137, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6223, 0x537c, 0x0000, 0x0000, 0x6d66, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5b49, 0x0000, 0x0000, 0x0000, 0x647a, 0x0000,
+ 0x4f5e, 0x0000, 0x0000, 0x4e50, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5553, 0x7375, 0x772e, 0x0000, 0x0000, 0x6f48, 0x0000, 0x4d73,
+ 0x754f, 0x6573, 0x7042, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4a51, 0x0000, 0x0000, 0x0000, 0x6a71, 0x0000, 0x5026, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x595a,
+ 0x702b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6b67, 0x0000,
+ 0x0000, 0x0000, 0x6540, 0x7c35, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6444, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c29, 0x7d46, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6a35, 0x0000, 0x652a, 0x5f3a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_64[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x615f, 0x0000, 0x5a51,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6138, 0x0000, 0x6874, 0x537d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6224, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x724a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5a66, 0x7733, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7d4d, 0x0000, 0x0000, 0x0000, 0x7336, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6e57, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7544, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5824, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7227,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5938, 0x5939, 0x6f49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x564e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x774b, 0x5f2e, 0x6875, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5235, 0x0000, 0x0000, 0x0000, 0x5355, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x744c, 0x5a7c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5968, 0x0000, 0x776b, 0x7549, 0x0000,
+ 0x733c, 0x0000, 0x5a52, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5335, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6836, 0x0000, 0x0000, 0x5242, 0x743a, 0x0000, 0x7749,
+ 0x0000, 0x0000, 0x4c2a, 0x0000, 0x0000, 0x7043, 0x4c56, 0x0000,
+ 0x0000, 0x0000, 0x5053, 0x0000, 0x533d, 0x0000, 0x0000, 0x0000,
+ 0x5b7b, 0x0000, 0x4b60, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5364, 0x7677, 0x0000, 0x0000, 0x553a, 0x734d, 0x4b61,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6b74, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x742d, 0x0000, 0x7c2a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x776c, 0x0000, 0x0000, 0x0000, 0x6876, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_65[] = {
+ 0x5a67, 0x0000, 0x0000, 0x0000, 0x774c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6541, 0x0000, 0x0000, 0x0000, 0x0000, 0x606e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x557d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4e66, 0x7c2b, 0x553b, 0x0000, 0x0000, 0x7228,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6225, 0x4d39,
+ 0x6a72, 0x4b47, 0x0000, 0x4d74, 0x0000, 0x0000, 0x5b2f, 0x6f59,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d3a, 0x0000, 0x0000,
+ 0x7c79, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f73, 0x4e67, 0x5a42,
+ 0x0000, 0x4f2d, 0x0000, 0x0000, 0x0000, 0x0000, 0x6779, 0x7828,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7362, 0x0000,
+ 0x0000, 0x0000, 0x4a72, 0x5f24, 0x0000, 0x0000, 0x5444, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4c57, 0x6542, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4d3b, 0x0000, 0x6f5a, 0x6e58, 0x0000, 0x5d27,
+ 0x5e7c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6040, 0x0000,
+ 0x0000, 0x0000, 0x5630, 0x784a, 0x0000, 0x7c7a, 0x0000, 0x597e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5e30, 0x0000, 0x0000, 0x0000,
+ 0x5d6c, 0x5a68, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5460,
+ 0x0000, 0x5679, 0x0000, 0x4d57, 0x5e58, 0x0000, 0x0000, 0x7278,
+ 0x0000, 0x6456, 0x0000, 0x0000, 0x5045, 0x742e, 0x0000, 0x5d28,
+ 0x0000, 0x0000, 0x0000, 0x6d45, 0x7356, 0x0000, 0x0000, 0x5e59,
+ 0x6366, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5328,
+ 0x0000, 0x5b30, 0x0000, 0x0000, 0x655a, 0x633f, 0x0000, 0x0000,
+ 0x0000, 0x5b31, 0x0000, 0x0000, 0x0000, 0x5569, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6041, 0x6f5b, 0x0000, 0x0000, 0x7069,
+ 0x0000, 0x0000, 0x5732, 0x0000, 0x0000, 0x0000, 0x0000, 0x507d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5969, 0x0000, 0x0000, 0x507e, 0x0000, 0x6c6d, 0x5329, 0x0000,
+ 0x7229, 0x7044, 0x0000, 0x0000, 0x6262, 0x696f, 0x0000, 0x0000,
+ 0x0000, 0x7951, 0x0000, 0x0000, 0x6959, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x685a, 0x5a43, 0x5a44, 0x5445, 0x0000, 0x677a
+};
+
+static unsigned short ksc5601_from_unicode_66[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d60, 0x6330,
+ 0x0000, 0x5b32, 0x7b44, 0x0000, 0x7363, 0x0000, 0x5925, 0x7b67,
+ 0x5d4b, 0x5054, 0x0000, 0x6636, 0x602e, 0x7d5a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c35, 0x6078,
+ 0x6731, 0x0000, 0x0000, 0x0000, 0x0000, 0x7570, 0x0000, 0x585c,
+ 0x6d46, 0x0000, 0x0000, 0x0000, 0x0000, 0x6139, 0x0000, 0x6340,
+ 0x7940, 0x6970, 0x0000, 0x0000, 0x595b, 0x0000, 0x7364, 0x0000,
+ 0x0000, 0x0000, 0x5c36, 0x6469, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7045, 0x6341, 0x7c4c, 0x7c4d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x724b, 0x0000, 0x724c, 0x0000, 0x0000, 0x0000, 0x644f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x715b, 0x0000, 0x7a59, 0x0000, 0x7138, 0x7d75, 0x6079,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x677b, 0x7c37, 0x7c64, 0x7b45,
+ 0x6367, 0x5839, 0x0000, 0x7678, 0x0000, 0x0000, 0x5c45, 0x4c58,
+ 0x0000, 0x0000, 0x0000, 0x602f, 0x7467, 0x0000, 0x6f5c, 0x4f7c,
+ 0x6f5d, 0x0000, 0x722a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7d3e, 0x0000, 0x0000, 0x4a2c,
+ 0x6977, 0x7d47, 0x0000, 0x0000, 0x0000, 0x0000, 0x6732, 0x0000,
+ 0x6a51, 0x5f74, 0x0000, 0x0000, 0x0000, 0x0000, 0x516c, 0x645e,
+ 0x6543, 0x0000, 0x0000, 0x0000, 0x0000, 0x5926, 0x0000, 0x0000,
+ 0x4d3c, 0x0000, 0x7365, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6d55, 0x0000, 0x0000, 0x593a, 0x0000,
+ 0x0000, 0x0000, 0x6d67, 0x7b35, 0x785b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6067, 0x0000, 0x4c59, 0x0000, 0x0000, 0x5446, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6725, 0x0000, 0x5575, 0x533e,
+ 0x0000, 0x7c7b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6472, 0x0000,
+ 0x0000, 0x5f75, 0x0000, 0x0000, 0x6878, 0x786d, 0x0000, 0x0000,
+ 0x4e47, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7d76, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6858, 0x0000, 0x4d58, 0x6756, 0x4b56, 0x0000, 0x0000, 0x4a63,
+ 0x5f76, 0x7047, 0x7046, 0x0000, 0x583a, 0x0000, 0x7174, 0x7470
+};
+
+static unsigned short ksc5601_from_unicode_67[] = {
+ 0x754c, 0x0000, 0x0000, 0x7c65, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6a45, 0x6a73, 0x0000, 0x5d5b, 0x0000, 0x5c57, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5e7d, 0x7279, 0x0000, 0x5228,
+ 0x0000, 0x0000, 0x0000, 0x5850, 0x0000, 0x7048, 0x5121, 0x5122,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5954, 0x5668,
+ 0x594a, 0x0000, 0x5a31, 0x5847, 0x5c62, 0x734e, 0x7574, 0x0000,
+ 0x0000, 0x7139, 0x0000, 0x0000, 0x5a53, 0x0000, 0x766a, 0x0000,
+ 0x0000, 0x0000, 0x4f75, 0x0000, 0x0000, 0x7d2e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a52, 0x0000,
+ 0x0000, 0x5f34, 0x0000, 0x0000, 0x0000, 0x0000, 0x575d, 0x7a3a,
+ 0x6e27, 0x753d, 0x0000, 0x7875, 0x0000, 0x0000, 0x6d68, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5461, 0x0000, 0x5123, 0x6156,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7978, 0x0000, 0x5b4a,
+ 0x4b79, 0x5454, 0x0000, 0x595c, 0x0000, 0x6e3e, 0x0000, 0x776d,
+ 0x0000, 0x0000, 0x0000, 0x526e, 0x0000, 0x0000, 0x6166, 0x7779,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5d6d,
+ 0x0000, 0x685b, 0x0000, 0x5b33, 0x0000, 0x0000, 0x0000, 0x5177,
+ 0x6030, 0x0000, 0x0000, 0x5462, 0x0000, 0x7657, 0x0000, 0x5779,
+ 0x0000, 0x0000, 0x585d, 0x0000, 0x4d7d, 0x722b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d3d,
+ 0x7842, 0x0000, 0x0000, 0x722c, 0x0000, 0x0000, 0x4a2d, 0x4a2e,
+ 0x4f2e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6342, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5c37, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b5a,
+ 0x593b, 0x4a73, 0x7653, 0x6678, 0x6a75, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6a76, 0x0000, 0x0000, 0x7679, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4f2f, 0x0000, 0x0000, 0x4a53, 0x0000, 0x0000, 0x4a2f,
+ 0x5230, 0x713a, 0x0000, 0x5733, 0x6343, 0x737d, 0x5e5a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5e5b, 0x0000, 0x0000, 0x6f5e, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_68[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6263, 0x6e7b, 0x0000, 0x0000, 0x5f77, 0x574a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4e68, 0x5b5b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x713b, 0x0000, 0x0000, 0x0000, 0x0000, 0x6971,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7a37, 0x5046, 0x0000, 0x0000, 0x4c2b, 0x6e28, 0x0000, 0x0000,
+ 0x4b7a, 0x7979, 0x4c7d, 0x537e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6450, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x726e, 0x0000,
+ 0x5455, 0x5f4d, 0x0000, 0x7c38, 0x5150, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x724d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7752, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a54,
+ 0x0000, 0x5559, 0x0000, 0x0000, 0x0000, 0x585e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d59,
+ 0x0000, 0x0000, 0x0000, 0x6e29, 0x763c, 0x0000, 0x0000, 0x4c5b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7049, 0x0000, 0x7c7c,
+ 0x0000, 0x6849, 0x747e, 0x0000, 0x0000, 0x0000, 0x0000, 0x677c,
+ 0x575e, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e5c, 0x0000, 0x702c,
+ 0x4c7e, 0x4d61, 0x0000, 0x613a, 0x0000, 0x5b6f, 0x5a32, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5125, 0x5c38, 0x0000, 0x0000,
+ 0x0000, 0x5876, 0x0000, 0x5124, 0x0000, 0x4d62, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5c6a, 0x0000, 0x0000, 0x7077, 0x0000, 0x704a,
+ 0x503e, 0x0000, 0x5d5c, 0x0000, 0x0000, 0x0000, 0x0000, 0x5456,
+ 0x5356, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d50,
+ 0x4d21, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f35, 0x0000,
+ 0x0000, 0x0000, 0x5f78, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5421, 0x4e32, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_69[] = {
+ 0x684a, 0x0000, 0x0000, 0x0000, 0x0000, 0x6b75, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6355, 0x7550, 0x0000,
+ 0x0000, 0x0000, 0x7521, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5927,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x652b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x664b, 0x0000, 0x7571,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6545, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7923, 0x605b, 0x766b, 0x0000, 0x4b71,
+ 0x0000, 0x596a, 0x7522, 0x0000, 0x0000, 0x0000, 0x5751, 0x0000,
+ 0x5178, 0x6a78, 0x6a79, 0x5a33, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6f5f, 0x0000, 0x0000, 0x716f, 0x0000, 0x6576, 0x6e3f, 0x6264,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x503f, 0x0000, 0x7a2c,
+ 0x7551, 0x6733, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x693e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x724e, 0x5b34, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7c4e, 0x0000, 0x5d6e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6734, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5734, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7734, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4d3e, 0x0000, 0x5a69, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4f30, 0x7759, 0x7366, 0x0000, 0x0000,
+ 0x4e59, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4e2a, 0x0000, 0x4b48, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5027, 0x0000, 0x704b, 0x0000, 0x5047
+};
+
+static unsigned short ksc5601_from_unicode_6a[] = {
+ 0x0000, 0x0000, 0x5162, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5b60, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x555a, 0x0000, 0x5266, 0x0000, 0x0000, 0x0000, 0x6e40,
+ 0x0000, 0x7876, 0x0000, 0x0000, 0x0000, 0x0000, 0x7552, 0x6d69,
+ 0x0000, 0x593c, 0x0000, 0x6546, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7523, 0x0000, 0x0000,
+ 0x5a54, 0x6227, 0x7b7c, 0x0000, 0x0000, 0x715c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4a74, 0x0000, 0x0000, 0x0000,
+ 0x687a, 0x0000, 0x0000, 0x4e69, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6978, 0x6265, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5039, 0x5472, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5126,
+ 0x0000, 0x5f4e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7c74, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x532a, 0x0000, 0x0000, 0x0000, 0x4c2c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6f60, 0x0000, 0x0000, 0x0000, 0x6565, 0x5055, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b7c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7c66, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4b7e, 0x6d6a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5e31, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7963, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5422, 0x4f76, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5243, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x556a, 0x716e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7a4b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6521, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_6b[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x516d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4f6d, 0x0000, 0x6d6b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5532, 0x0000, 0x0000, 0x0000, 0x553c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7d62, 0x732d, 0x0000, 0x7d5b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6930, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5127, 0x0000, 0x0000, 0x7d63, 0x4e33, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7d64, 0x7a4e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4a30, 0x0000, 0x7727, 0x0000,
+ 0x4f31, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6622,
+ 0x0000, 0x7c36, 0x722d, 0x6f61, 0x732e, 0x5c46, 0x596b, 0x0000,
+ 0x0000, 0x0000, 0x6860, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6128, 0x0000, 0x0000, 0x0000, 0x0000, 0x5576,
+ 0x4f7d, 0x0000, 0x0000, 0x5e5d, 0x0000, 0x0000, 0x0000, 0x5951,
+ 0x0000, 0x0000, 0x0000, 0x646a, 0x724f, 0x0000, 0x773f, 0x0000,
+ 0x0000, 0x6266, 0x6228, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6356, 0x0000,
+ 0x6d51, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6979, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5631, 0x5e32,
+ 0x0000, 0x0000, 0x6068, 0x0000, 0x0000, 0x532b, 0x0000, 0x6b5c,
+ 0x0000, 0x0000, 0x5f2f, 0x0000, 0x4a43, 0x0000, 0x0000, 0x6e7c,
+ 0x0000, 0x7d43, 0x0000, 0x0000, 0x0000, 0x6b76, 0x4f32, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x596c, 0x0000, 0x593d, 0x0000, 0x585f,
+ 0x0000, 0x0000, 0x5438, 0x6b3e, 0x5d6f, 0x0000, 0x5d70, 0x5d71,
+ 0x5d72, 0x0000, 0x0000, 0x593e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7b46, 0x4f33, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_6c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6e7d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x642b,
+ 0x0000, 0x5a45, 0x0000, 0x586c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5128, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6229, 0x0000, 0x0000, 0x5e3c,
+ 0x6735, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b70, 0x0000,
+ 0x6f62, 0x7170, 0x4f34, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b71, 0x0000,
+ 0x6031, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f25, 0x0000, 0x7952,
+ 0x0000, 0x0000, 0x677d, 0x0000, 0x0000, 0x6623, 0x7b71, 0x4b30,
+ 0x722e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4d67, 0x0000, 0x685c, 0x0000, 0x0000, 0x6757, 0x0000, 0x0000,
+ 0x7740, 0x0000, 0x5063, 0x0000, 0x0000, 0x0000, 0x5a21, 0x0000,
+ 0x0000, 0x0000, 0x4c3d, 0x0000, 0x0000, 0x5129, 0x5d4c, 0x0000,
+ 0x0000, 0x637e, 0x512a, 0x682a, 0x0000, 0x6a36, 0x797a, 0x664c,
+ 0x6421, 0x0000, 0x0000, 0x0000, 0x5447, 0x0000, 0x0000, 0x0000,
+ 0x594b, 0x0000, 0x5952, 0x534b, 0x5877, 0x5a29, 0x7578, 0x0000,
+ 0x0000, 0x5e5e, 0x722f, 0x7829, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5848, 0x0000, 0x0000, 0x6e41, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7941, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5d73, 0x6a7a, 0x0000, 0x763d, 0x613b, 0x4d3f, 0x7454, 0x664d,
+ 0x0000, 0x7c4f, 0x7b22, 0x0000, 0x605c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x743b, 0x5a55, 0x0000, 0x5d74, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7b72, 0x0000, 0x5b76, 0x0000, 0x5e5f,
+ 0x0000, 0x0000, 0x0000, 0x5b72, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x785c, 0x776e, 0x6b68, 0x0000, 0x527a, 0x0000, 0x0000,
+ 0x713c, 0x0000, 0x0000, 0x7a5a, 0x0000, 0x0000, 0x5a6a, 0x5a46,
+ 0x7741, 0x0000, 0x0000, 0x6736, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_6d[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6547, 0x562c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5c47, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6129,
+ 0x0000, 0x622a, 0x0000, 0x5163, 0x0000, 0x0000, 0x5457, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7250, 0x0000, 0x6a7b,
+ 0x0000, 0x605d, 0x7b73, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x713d, 0x0000, 0x0000, 0x6267, 0x7d57, 0x0000,
+ 0x4e48, 0x6a37, 0x0000, 0x7c40, 0x0000, 0x7d67, 0x776f, 0x0000,
+ 0x0000, 0x5735, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6f3a, 0x715d, 0x0000, 0x5e33, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x684b, 0x0000, 0x0000, 0x785d, 0x0000,
+ 0x0000, 0x7b47, 0x5229, 0x0000, 0x575f, 0x0000, 0x5d29, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6931, 0x0000, 0x0000, 0x7a2d,
+ 0x7659, 0x7a74, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x782a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x666e, 0x0000, 0x4c5c,
+ 0x613c, 0x606f, 0x0000, 0x0000, 0x693f, 0x7c7d, 0x664e, 0x0000,
+ 0x0000, 0x6157, 0x0000, 0x664f, 0x0000, 0x7471, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6473,
+ 0x0000, 0x0000, 0x647b, 0x0000, 0x0000, 0x7964, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6f63, 0x0000, 0x0000, 0x4f6e, 0x763e, 0x6032, 0x7c7e, 0x512b,
+ 0x0000, 0x0000, 0x0000, 0x577a, 0x0000, 0x0000, 0x0000, 0x7b48,
+ 0x0000, 0x6257, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5423, 0x7078, 0x5267, 0x0000, 0x0000, 0x0000, 0x6167, 0x0000,
+ 0x0000, 0x533f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6f64, 0x0000, 0x5745, 0x6b62, 0x0000, 0x0000, 0x7c67, 0x0000,
+ 0x0000, 0x6422, 0x0000, 0x6268, 0x0000, 0x6650, 0x0000, 0x7b68,
+ 0x7468, 0x6574, 0x743c, 0x7455, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_6e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f36,
+ 0x0000, 0x7c39, 0x6e42, 0x4a75, 0x0000, 0x0000, 0x0000, 0x6f65,
+ 0x4b62, 0x5424, 0x0000, 0x5e60, 0x5a7d, 0x6446, 0x683e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x605e, 0x7634, 0x6a52, 0x0000, 0x797b,
+ 0x0000, 0x0000, 0x6042, 0x0000, 0x4a64, 0x0000, 0x6737, 0x0000,
+ 0x6a7d, 0x0000, 0x595d, 0x0000, 0x5a34, 0x6e2a, 0x7b69, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5b4b, 0x5a35, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x713e, 0x0000, 0x0000, 0x532c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b49, 0x0000,
+ 0x5f4f, 0x0000, 0x0000, 0x5340, 0x6357, 0x0000, 0x6f66, 0x7c50,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6940,
+ 0x0000, 0x0000, 0x0000, 0x7553, 0x0000, 0x0000, 0x6c5c, 0x7737,
+ 0x0000, 0x0000, 0x6a38, 0x5179, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5c48, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6a39, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x715e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5736, 0x4f35, 0x0000, 0x5928,
+ 0x0000, 0x0000, 0x6c6e, 0x0000, 0x0000, 0x5d2a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4d22, 0x682e, 0x0000, 0x0000, 0x0000, 0x613d,
+ 0x0000, 0x7251, 0x0000, 0x0000, 0x0000, 0x0000, 0x6941, 0x0000,
+ 0x0000, 0x0000, 0x527c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5b35, 0x0000, 0x7367, 0x587e, 0x0000, 0x0000,
+ 0x0000, 0x7c51, 0x0000, 0x6d32, 0x742f, 0x0000, 0x7b23, 0x0000,
+ 0x0000, 0x7c41, 0x0000, 0x6e2b, 0x5425, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7472,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6e59, 0x0000, 0x0000, 0x0000,
+ 0x7b4a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d63, 0x583b
+};
+
+static unsigned short ksc5601_from_unicode_6f[] = {
+ 0x0000, 0x655b, 0x7877, 0x0000, 0x0000, 0x0000, 0x7654, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5268,
+ 0x0000, 0x4b49, 0x0000, 0x0000, 0x6651, 0x704c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x582e, 0x0000, 0x7953, 0x557e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x583c, 0x7230, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x622b, 0x7368, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6f42, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d6c,
+ 0x0000, 0x6738, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5a7e, 0x0000, 0x0000, 0x4c3e, 0x0000, 0x0000, 0x727c,
+ 0x5a6b, 0x0000, 0x6258, 0x6d56, 0x0000, 0x0000, 0x5651, 0x6033,
+ 0x0000, 0x0000, 0x7c52, 0x0000, 0x6b48, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5341, 0x704d, 0x0000,
+ 0x4f77, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6d52, 0x0000, 0x5458, 0x5c49, 0x5771, 0x0000,
+ 0x0000, 0x5f3b, 0x0000, 0x0000, 0x7325, 0x0000, 0x0000, 0x0000,
+ 0x744d, 0x0000, 0x0000, 0x0000, 0x0000, 0x713f, 0x7831, 0x0000,
+ 0x697a, 0x0000, 0x0000, 0x0000, 0x7b4b, 0x0000, 0x0000, 0x4a55,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7954, 0x774a, 0x0000, 0x0000, 0x5648,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7c68, 0x733d,
+ 0x0000, 0x6e7e, 0x0000, 0x677e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5342, 0x0000, 0x0000, 0x0000, 0x0000, 0x5336, 0x0000,
+ 0x4c2d, 0x767a, 0x5632, 0x5258, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6758, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6325, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6739, 0x0000, 0x0000, 0x0000, 0x0000, 0x702d,
+ 0x7b4c, 0x6b21, 0x0000, 0x0000, 0x5426, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7b4d, 0x0000, 0x517a, 0x715f, 0x0000, 0x0000, 0x767b,
+ 0x0000, 0x5e34, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x556b, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_70[] = {
+ 0x0000, 0x6548, 0x0000, 0x0000, 0x0000, 0x7b24, 0x5439, 0x0000,
+ 0x0000, 0x5e61, 0x0000, 0x6423, 0x0000, 0x0000, 0x0000, 0x5737,
+ 0x0000, 0x786e, 0x0000, 0x0000, 0x0000, 0x5e35, 0x0000, 0x0000,
+ 0x5652, 0x0000, 0x7955, 0x673a, 0x6b55, 0x5577, 0x6f67, 0x613e,
+ 0x0000, 0x0000, 0x0000, 0x7a2e, 0x0000, 0x0000, 0x0000, 0x5669,
+ 0x566e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x673b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6c4b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5533, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4e34, 0x0000, 0x0000, 0x0000,
+ 0x7b25, 0x616e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7728, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b4e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x583d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7b7d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7c69, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4f36, 0x0000, 0x0000, 0x0000, 0x6d47, 0x6e2c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c5d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7627, 0x0000, 0x0000, 0x0000, 0x667a, 0x0000,
+ 0x0000, 0x0000, 0x7524, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7d5c, 0x6d33, 0x4e49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6f68, 0x0000, 0x0000, 0x613f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7a5b, 0x4b63, 0x7729, 0x0000, 0x7b26,
+ 0x0000, 0x0000, 0x0000, 0x5c39, 0x0000, 0x0000, 0x0000, 0x7140,
+ 0x6d48, 0x6f43, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x562d, 0x0000, 0x0000, 0x7d4e, 0x0000, 0x0000, 0x0000, 0x6821,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7b74, 0x5164, 0x0000, 0x0000, 0x0000, 0x7176, 0x0000, 0x6653,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4c5e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7832, 0x0000, 0x0000, 0x0000, 0x5c6b, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_71[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7d36, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x656a, 0x0000, 0x0000, 0x7160, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5b4c, 0x5d4d, 0x0000, 0x0000, 0x0000, 0x5448, 0x0000,
+ 0x0000, 0x596d, 0x0000, 0x0000, 0x0000, 0x0000, 0x7525, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x667b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6654, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7d48,
+ 0x0000, 0x5621, 0x7d3f, 0x0000, 0x7c53, 0x0000, 0x6f21, 0x0000,
+ 0x673c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x516e, 0x0000,
+ 0x0000, 0x6655, 0x0000, 0x0000, 0x6972, 0x0000, 0x5f30, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5860, 0x7c3a, 0x7d2f, 0x704e,
+ 0x0000, 0x5b61, 0x0000, 0x0000, 0x6549, 0x0000, 0x6d34, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6043, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6358, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x697b, 0x6a28, 0x0000, 0x0000, 0x0000, 0x0000, 0x7d37,
+ 0x0000, 0x0000, 0x7b27, 0x0000, 0x6942, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7d77, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6259,
+ 0x0000, 0x0000, 0x5c6c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6822, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6670, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7d78, 0x7d79, 0x0000, 0x0000, 0x0000, 0x763f, 0x0000,
+ 0x0000, 0x6727, 0x0000, 0x6657, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5473, 0x5449, 0x0000, 0x0000, 0x0000, 0x0000, 0x567a, 0x0000,
+ 0x5772, 0x0000, 0x6140, 0x0000, 0x5b62, 0x6658, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x673d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x704f, 0x733e, 0x622c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7537, 0x6070, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7d38, 0x6368, 0x0000, 0x5427, 0x687c
+};
+
+static unsigned short ksc5601_from_unicode_72[] = {
+ 0x7a52, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x786f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5244, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x516f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7050, 0x0000, 0x7770, 0x6e33, 0x0000, 0x0000,
+ 0x6a3a, 0x0000, 0x6a53, 0x0000, 0x0000, 0x6d49, 0x5d2b, 0x0000,
+ 0x0000, 0x0000, 0x652c, 0x7d21, 0x0000, 0x5f50, 0x6c33, 0x0000,
+ 0x5f51, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d6d, 0x7838,
+ 0x777a, 0x0000, 0x0000, 0x0000, 0x782b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7460, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x543a, 0x6433, 0x0000, 0x695a, 0x0000, 0x5e36, 0x0000, 0x593f,
+ 0x0000, 0x5940, 0x525e, 0x0000, 0x0000, 0x0000, 0x0000, 0x594c,
+ 0x0000, 0x5a2a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5f65, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7765, 0x0000, 0x0000, 0x0000, 0x4c32, 0x0000, 0x0000,
+ 0x5f79, 0x5760, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x543b, 0x0000, 0x0000, 0x0000, 0x0000, 0x7d7a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4c33, 0x0000, 0x0000, 0x5b73,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5f52, 0x0000, 0x4e4a, 0x0000, 0x6e5a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6464, 0x0000,
+ 0x7b4f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4f37,
+ 0x0000, 0x6e43, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4e6a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x622d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5761, 0x7a75, 0x0000, 0x0000, 0x522a, 0x782c, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_73[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6759, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7369, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x586d, 0x6344, 0x7071, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6865, 0x0000, 0x0000,
+ 0x0000, 0x607a, 0x6e44, 0x595e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6b22, 0x6b23,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7c42, 0x6a3b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x682b, 0x5e62, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6d6f, 0x0000, 0x6823, 0x0000, 0x0000, 0x0000, 0x0000, 0x4f71,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x543c, 0x0000, 0x7c6a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x673e, 0x0000, 0x7c72, 0x0000, 0x0000, 0x5634, 0x0000, 0x0000,
+ 0x622e, 0x0000, 0x5337, 0x7a4c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7a5c, 0x0000, 0x6d35, 0x574b,
+ 0x0000, 0x682c, 0x0000, 0x685d, 0x0000, 0x0000, 0x6f69, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x743d, 0x0000, 0x4f38, 0x695b,
+ 0x512c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a47,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6b49,
+ 0x0000, 0x684c, 0x0000, 0x0000, 0x0000, 0x5e37, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x563c, 0x5365, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7a5d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5a56, 0x0000, 0x4a31, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5a48, 0x5f26, 0x0000, 0x7933, 0x7252, 0x0000, 0x4a44,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e4b, 0x0000,
+ 0x0000, 0x4d75, 0x0000, 0x0000, 0x0000, 0x7d30, 0x5165, 0x0000,
+ 0x7141, 0x0000, 0x0000, 0x6269, 0x5c4a, 0x6c34, 0x7a40, 0x0000,
+ 0x0000, 0x7b28, 0x5028, 0x0000, 0x0000, 0x5a6c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x596e,
+ 0x0000, 0x607b, 0x0000, 0x0000, 0x0000, 0x6f6a, 0x7a5e, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_74[] = {
+ 0x0000, 0x6044, 0x0000, 0x4f39, 0x0000, 0x554a, 0x5762, 0x622f,
+ 0x0000, 0x5738, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x684d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x765a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6f22, 0x625a, 0x767c, 0x0000, 0x0000, 0x7b50, 0x512d, 0x0000,
+ 0x4d64, 0x0000, 0x512e, 0x5c6d, 0x684e, 0x0000, 0x7079, 0x4e35,
+ 0x667c, 0x0000, 0x0000, 0x577b, 0x5056, 0x5d75, 0x7771, 0x0000,
+ 0x767d, 0x0000, 0x5b77, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b6a,
+ 0x695c, 0x5941, 0x0000, 0x7572, 0x6045, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6a54, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7942, 0x0000, 0x6a3c,
+ 0x0000, 0x5245, 0x7b51, 0x6740, 0x6b25, 0x0000, 0x5f7a, 0x6322,
+ 0x5739, 0x0000, 0x6943, 0x0000, 0x687d, 0x682f, 0x0000, 0x0000,
+ 0x7253, 0x6741, 0x5825, 0x0000, 0x0000, 0x0000, 0x0000, 0x554b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5048, 0x0000,
+ 0x0000, 0x0000, 0x512f, 0x5763, 0x0000, 0x0000, 0x0000, 0x6046,
+ 0x0000, 0x5622, 0x0000, 0x6d70, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5773, 0x0000, 0x0000, 0x0000, 0x7c54, 0x0000, 0x5a57, 0x4c5f,
+ 0x0000, 0x7254, 0x0000, 0x5130, 0x0000, 0x4c60, 0x0000, 0x5b7d,
+ 0x733f, 0x0000, 0x7051, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7c3b, 0x0000, 0x6230, 0x0000, 0x0000, 0x6625, 0x0000, 0x0000,
+ 0x0000, 0x625b, 0x0000, 0x0000, 0x0000, 0x5f5e, 0x0000, 0x6047,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x726f, 0x0000,
+ 0x0000, 0x0000, 0x4c61, 0x0000, 0x0000, 0x0000, 0x0000, 0x566a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6742, 0x0000, 0x0000, 0x0000,
+ 0x4e36, 0x0000, 0x7340, 0x0000, 0x4d7e, 0x0000, 0x0000, 0x0000,
+ 0x7b52, 0x0000, 0x7878, 0x777b, 0x0000, 0x0000, 0x683f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6837, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d36,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_75[] = {
+ 0x0000, 0x5c3a, 0x0000, 0x0000, 0x4c34, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7177, 0x0000, 0x0000, 0x0000, 0x6838, 0x0000, 0x0000,
+ 0x4a76, 0x0000, 0x6424, 0x7456, 0x0000, 0x0000, 0x0000, 0x5f66,
+ 0x0000, 0x0000, 0x0000, 0x5f27, 0x0000, 0x5f67, 0x6141, 0x0000,
+ 0x6944, 0x0000, 0x0000, 0x5c4b, 0x6945, 0x0000, 0x0000, 0x0000,
+ 0x6f23, 0x6b26, 0x4b23, 0x6369, 0x0000, 0x0000, 0x0000, 0x517b,
+ 0x6f24, 0x0000, 0x6f6b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5034,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4d23, 0x0000, 0x0000, 0x6866,
+ 0x0000, 0x6f25, 0x0000, 0x534c, 0x5a6d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x573a, 0x0000, 0x7255, 0x7565, 0x596f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7934, 0x0000, 0x0000, 0x5554, 0x7d4f, 0x0000,
+ 0x0000, 0x0000, 0x5b63, 0x0000, 0x0000, 0x0000, 0x0000, 0x7161,
+ 0x5764, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b7e, 0x5357, 0x0000,
+ 0x5131, 0x0000, 0x4b31, 0x0000, 0x0000, 0x0000, 0x0000, 0x5132,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b32, 0x7142,
+ 0x0000, 0x0000, 0x7461, 0x7935, 0x0000, 0x0000, 0x6143, 0x6142,
+ 0x0000, 0x6b77, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f28, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b4a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6639, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x785e, 0x792a, 0x4a77, 0x0000, 0x6d37, 0x0000, 0x0000,
+ 0x5338, 0x7256, 0x0000, 0x0000, 0x5459, 0x6e45, 0x7270, 0x0000,
+ 0x0000, 0x0000, 0x4a32, 0x0000, 0x0000, 0x5c3b, 0x0000, 0x7178,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6c37, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x654a, 0x0000, 0x7640, 0x7d5d, 0x0000, 0x0000,
+ 0x5463, 0x4c62, 0x0000, 0x7754, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5765, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5343, 0x0000, 0x5826, 0x0000, 0x7641, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5d76, 0x0000, 0x4d40, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_76[] = {
+ 0x655c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x654b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6144, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6830,
+ 0x7430, 0x736a, 0x5a6e, 0x0000, 0x573b, 0x0000, 0x6231, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x572a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x567b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x645f, 0x0000, 0x4a56, 0x0000,
+ 0x0000, 0x0000, 0x6b28, 0x0000, 0x0000, 0x0000, 0x5b7e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7642, 0x0000, 0x0000, 0x6f3b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x515b, 0x0000, 0x0000, 0x6048, 0x0000, 0x0000, 0x0000,
+ 0x6839, 0x0000, 0x6f26, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4d24, 0x0000, 0x0000, 0x5474, 0x5b21, 0x5b5c, 0x5b5d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6e5c, 0x0000, 0x4b4b, 0x7c55,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e6b, 0x0000,
+ 0x4d41, 0x0000, 0x0000, 0x7b53, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x792b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7554, 0x0000, 0x0000, 0x0000, 0x0000, 0x5929,
+ 0x0000, 0x0000, 0x695d, 0x5b4d, 0x0000, 0x0000, 0x5d4e, 0x0000,
+ 0x6743, 0x0000, 0x6c4c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x796c, 0x0000, 0x0000, 0x0000, 0x4b4c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x607c, 0x5428, 0x0000, 0x6d53, 0x586f,
+ 0x0000, 0x7257, 0x0000, 0x4a78, 0x5a6f, 0x0000, 0x0000, 0x5246,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x594d, 0x0000,
+ 0x0000, 0x0000, 0x586e, 0x0000, 0x7241, 0x0000, 0x0000, 0x0000,
+ 0x5f53, 0x0000, 0x0000, 0x0000, 0x5a70, 0x0000, 0x626a, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_77[] = {
+ 0x0000, 0x5f68, 0x0000, 0x0000, 0x5878, 0x0000, 0x0000, 0x0000,
+ 0x772f, 0x5a36, 0x0000, 0x4a57, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7258, 0x0000,
+ 0x5879, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7a5f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4f6f,
+ 0x5942, 0x0000, 0x7052, 0x0000, 0x6451, 0x0000, 0x0000, 0x0000,
+ 0x7337, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7a60, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6f6c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6232, 0x0000, 0x543d, 0x0000, 0x0000, 0x594e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7462, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5429, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d42, 0x675a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7259, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x592a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x583e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c2d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x626b, 0x567c, 0x0000, 0x0000,
+ 0x4a79, 0x0000, 0x0000, 0x545a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7457, 0x4c21, 0x0000, 0x0000, 0x4f3a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7538,
+ 0x0000, 0x0000, 0x0000, 0x5943, 0x5068, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6345, 0x6b78, 0x0000, 0x7231, 0x0000, 0x0000,
+ 0x0000, 0x4f3b, 0x0000, 0x0000, 0x0000, 0x532d, 0x6861, 0x4e6c,
+ 0x0000, 0x0000, 0x0000, 0x6034, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_78[] = {
+ 0x0000, 0x0000, 0x5e63, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5d77, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7232, 0x7376, 0x765b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x577e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x785f, 0x0000, 0x7772, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5029, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x665a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7526, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x573c, 0x4c63, 0x0000, 0x0000, 0x665b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5d5d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5133, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6f6d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x524f, 0x6474, 0x616f, 0x0000,
+ 0x0000, 0x5d78, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x684f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4a65, 0x0000, 0x0000, 0x0000, 0x5c21,
+ 0x0000, 0x6035, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7c2c, 0x7c2d, 0x5827, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6d38, 0x0000, 0x0000, 0x0000, 0x5b36, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x525f, 0x732f, 0x0000, 0x0000, 0x4d25, 0x0000,
+ 0x5a71, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5828, 0x0000, 0x0000, 0x0000, 0x4c64, 0x0000, 0x0000, 0x5134,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a58, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5a72, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_79[] = {
+ 0x0000, 0x7527, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7528, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6626, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x556c, 0x5578, 0x5a73, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6346, 0x0000, 0x0000, 0x0000, 0x5e64, 0x0000,
+ 0x5e65, 0x5135, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5136,
+ 0x5137, 0x7233, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x695e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7053, 0x7234,
+ 0x0000, 0x0000, 0x7054, 0x4b64, 0x7b54, 0x7566, 0x636a, 0x0000,
+ 0x5e66, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f54, 0x0000, 0x0000,
+ 0x7879, 0x0000, 0x0000, 0x0000, 0x0000, 0x702e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5138, 0x0000, 0x0000, 0x0000, 0x0000, 0x5250,
+ 0x0000, 0x5057, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7c21, 0x6f6e, 0x5c58,
+ 0x0000, 0x695f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x655d, 0x7d7b,
+ 0x0000, 0x0000, 0x6049, 0x0000, 0x0000, 0x0000, 0x5649, 0x0000,
+ 0x0000, 0x542a, 0x0000, 0x654c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6960, 0x0000, 0x0000, 0x0000, 0x5058, 0x7c22, 0x543e,
+ 0x6233, 0x5e67, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5c3c, 0x5236, 0x7555, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4e21, 0x7529, 0x0000, 0x0000, 0x5d79, 0x0000, 0x0000,
+ 0x5d7a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7055,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x765f, 0x0000, 0x725a, 0x646b,
+ 0x0000, 0x7271, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6c39, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_7a[] = {
+ 0x7d7c, 0x0000, 0x0000, 0x0000, 0x0000, 0x612a, 0x0000, 0x0000,
+ 0x4a59, 0x0000, 0x0000, 0x6f6f, 0x0000, 0x752a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6c79, 0x0000, 0x0000, 0x782d,
+ 0x0000, 0x7242, 0x7643, 0x0000, 0x5274, 0x0000, 0x0000, 0x7922,
+ 0x7056, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x707a, 0x0000,
+ 0x0000, 0x7660, 0x0000, 0x0000, 0x0000, 0x0000, 0x6973, 0x7243,
+ 0x0000, 0x0000, 0x0000, 0x542b, 0x4a33, 0x4d26, 0x0000, 0x4d43,
+ 0x4d5a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x594f, 0x0000,
+ 0x0000, 0x7644, 0x0000, 0x0000, 0x0000, 0x6e5d, 0x6744, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6234,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5f62, 0x675b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6831, 0x0000, 0x7c2e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x654d, 0x0000, 0x0000, 0x0000, 0x7a6b, 0x0000, 0x4f3c, 0x0000,
+ 0x0000, 0x4f62, 0x4d76, 0x0000, 0x0000, 0x6f70, 0x0000, 0x743e,
+ 0x0000, 0x544d, 0x0000, 0x0000, 0x7338, 0x0000, 0x0000, 0x0000,
+ 0x6921, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7272, 0x736b, 0x0000, 0x7057, 0x0000, 0x0000,
+ 0x4f57, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4f5f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6840, 0x6841, 0x0000, 0x0000, 0x0000, 0x4f63, 0x6922,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x502a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7341, 0x502b, 0x0000, 0x5464,
+ 0x0000, 0x0000, 0x6f3c, 0x5821, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x595f,
+ 0x0000, 0x7357, 0x0000, 0x0000, 0x0000, 0x5c3d, 0x0000, 0x4c65,
+ 0x6d71, 0x0000, 0x0000, 0x7162, 0x0000, 0x545b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6235, 0x0000, 0x0000, 0x4a66, 0x0000, 0x532e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c66, 0x0000,
+ 0x0000, 0x7153, 0x7567, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a5a
+};
+
+static unsigned short ksc5601_from_unicode_7b[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b6e,
+ 0x0000, 0x6145, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5f69, 0x0000, 0x6e5e, 0x0000, 0x0000, 0x7742, 0x0000,
+ 0x5822, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5d2c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x702f, 0x563d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x612b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7936, 0x0000,
+ 0x0000, 0x5475, 0x0000, 0x5049, 0x6f27, 0x626c, 0x0000, 0x5b6a,
+ 0x4e4c, 0x7568, 0x7755, 0x0000, 0x534d, 0x0000, 0x737e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5035, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x607e, 0x0000, 0x5f7b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x665d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6824, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b4d,
+ 0x0000, 0x0000, 0x0000, 0x6f28, 0x0000, 0x0000, 0x0000, 0x6e34,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5a58, 0x5139, 0x0000, 0x5f29,
+ 0x0000, 0x0000, 0x7330, 0x0000, 0x0000, 0x4c44, 0x0000, 0x0000,
+ 0x0000, 0x4e37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6f29, 0x0000, 0x0000,
+ 0x0000, 0x5f55, 0x0000, 0x0000, 0x6d57, 0x0000, 0x0000, 0x0000,
+ 0x6e46, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6f3d, 0x7c56, 0x0000, 0x0000, 0x5b74, 0x0000, 0x6f2a, 0x7839,
+ 0x0000, 0x7569, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6359, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6146, 0x0000, 0x0000, 0x0000, 0x543f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5e68, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_7c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x706a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7342, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x532f, 0x0000,
+ 0x0000, 0x4a5b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7c57,
+ 0x0000, 0x0000, 0x6d58, 0x6147, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7458, 0x5633, 0x5d2d,
+ 0x0000, 0x0000, 0x0000, 0x553e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7143, 0x6e5f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5259, 0x0000, 0x0000, 0x0000, 0x7459, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5766, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5a37, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5d7b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5d4f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5823, 0x0000, 0x0000, 0x5a59, 0x0000, 0x7058,
+ 0x6f44, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6158,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7154, 0x0000, 0x6d72,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x555b, 0x0000,
+ 0x0000, 0x555c, 0x7344, 0x4b57, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6236, 0x0000, 0x0000, 0x0000, 0x0000, 0x6f71, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7b55, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5358, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5d50, 0x7059,
+ 0x4b33, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x555d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4d27, 0x0000, 0x0000, 0x502c, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_7d[] = {
+ 0x513a, 0x0000, 0x7144, 0x0000, 0x6533, 0x7b75, 0x6961, 0x7d60,
+ 0x7c3c, 0x0000, 0x5a22, 0x5a23, 0x0000, 0x5221, 0x0000, 0x0000,
+ 0x526f, 0x0000, 0x0000, 0x0000, 0x626d, 0x0000, 0x0000, 0x5e69,
+ 0x4e5c, 0x7235, 0x5064, 0x5d51, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6148, 0x5b37, 0x5e7e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6d39, 0x7145, 0x0000, 0x734f, 0x5269,
+ 0x612c, 0x0000, 0x0000, 0x636b, 0x0000, 0x6e47, 0x0000, 0x0000,
+ 0x0000, 0x6149, 0x4a7a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x707b, 0x7a61, 0x705a, 0x4c67, 0x5a74, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4c3f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e6d, 0x0000,
+ 0x0000, 0x5529, 0x7a62, 0x0000, 0x0000, 0x0000, 0x5065, 0x0000,
+ 0x6b56, 0x0000, 0x6c5f, 0x0000, 0x0000, 0x0000, 0x5f7c, 0x0000,
+ 0x0000, 0x7756, 0x5e6a, 0x4b34, 0x0000, 0x0000, 0x6f3e, 0x0000,
+ 0x0000, 0x4c35, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4f3d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6f72, 0x6237,
+ 0x0000, 0x0000, 0x0000, 0x4c68, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x707c, 0x0000, 0x0000, 0x0000,
+ 0x5251, 0x0000, 0x7146, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6238, 0x6b2b, 0x0000, 0x0000,
+ 0x0000, 0x4b35, 0x5851, 0x0000, 0x744e, 0x7377, 0x0000, 0x0000,
+ 0x5746, 0x0000, 0x513b, 0x772a, 0x0000, 0x6d4a, 0x5275, 0x587a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7645,
+ 0x0000, 0x0000, 0x514c, 0x5d7c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f7d, 0x0000,
+ 0x7965, 0x0000, 0x604a, 0x0000, 0x0000, 0x727d, 0x5330, 0x0000,
+ 0x7473, 0x5a49, 0x0000, 0x665e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x783a, 0x6850, 0x0000, 0x0000, 0x587b, 0x0000, 0x0000, 0x6a55,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5623, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7646, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_7e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x725b, 0x647c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6832, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5a5a, 0x0000, 0x725c, 0x7b56, 0x6932,
+ 0x0000, 0x6e2d, 0x0000, 0x7a63, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5c6e, 0x0000, 0x0000, 0x756a, 0x6660,
+ 0x0000, 0x707d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x526a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7545, 0x6e60, 0x0000,
+ 0x0000, 0x5b65, 0x0000, 0x5d5e, 0x0000, 0x0000, 0x5970, 0x6923,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7179, 0x0000, 0x7244, 0x604b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6924, 0x0000,
+ 0x0000, 0x6239, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6331, 0x7c6b, 0x4d28, 0x0000, 0x4c36, 0x0000, 0x0000,
+ 0x705b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x663a, 0x0000, 0x0000, 0x4d29, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7343, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6159, 0x0000, 0x0000, 0x6f2b,
+ 0x0000, 0x0000, 0x0000, 0x6745, 0x0000, 0x0000, 0x6069, 0x0000,
+ 0x7345, 0x0000, 0x0000, 0x5440, 0x553f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_7f[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5d2e, 0x0000,
+ 0x797c, 0x0000, 0x4c40, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6522, 0x0000, 0x0000, 0x0000,
+ 0x4e38, 0x0000, 0x0000, 0x0000, 0x5852, 0x7956, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x712a, 0x4e51, 0x0000, 0x0000, 0x7647, 0x0000,
+ 0x5b6b, 0x0000, 0x5f7e, 0x0000, 0x0000, 0x5861, 0x0000, 0x7773,
+ 0x0000, 0x5767, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x515c, 0x0000, 0x0000,
+ 0x513c, 0x0000, 0x654f, 0x0000, 0x4b36, 0x0000, 0x5a38, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4d44, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x563e, 0x0000, 0x0000, 0x0000, 0x623a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4f58, 0x0000, 0x0000, 0x0000,
+ 0x604c, 0x6b79, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7d7d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5768, 0x4b58, 0x0000, 0x0000, 0x0000, 0x6962, 0x0000, 0x0000,
+ 0x0000, 0x683a, 0x0000, 0x0000, 0x0000, 0x6347, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6c4d, 0x0000, 0x6c4e, 0x0000, 0x563f, 0x0000,
+ 0x0000, 0x0000, 0x6327, 0x0000, 0x5f56, 0x7d68, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6e61,
+ 0x7628, 0x5d7d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x783b, 0x0000, 0x6851, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7957, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4e6e, 0x0000, 0x0000, 0x6c4f, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_80[] = {
+ 0x6925, 0x5247, 0x0000, 0x4d45, 0x0000, 0x6d3a, 0x513d, 0x0000,
+ 0x0000, 0x4f3e, 0x0000, 0x0000, 0x6c3b, 0x0000, 0x0000, 0x0000,
+ 0x5231, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c69, 0x0000, 0x5944,
+ 0x697c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x513e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6c3c, 0x0000, 0x0000, 0x652d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7730, 0x0000, 0x4c6a,
+ 0x0000, 0x0000, 0x0000, 0x5344, 0x0000, 0x0000, 0x5640, 0x0000,
+ 0x0000, 0x0000, 0x567d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6121, 0x0000,
+ 0x5e3d, 0x0000, 0x7629, 0x0000, 0x0000, 0x0000, 0x5a24, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5624,
+ 0x7546, 0x0000, 0x6122, 0x6946, 0x0000, 0x0000, 0x0000, 0x7245,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7469, 0x525a, 0x6b53,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6c3d, 0x625c, 0x5e6b, 0x705c,
+ 0x0000, 0x6b3f, 0x0000, 0x5271, 0x513f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x752b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x797d, 0x0000, 0x4a5c, 0x0000, 0x0000,
+ 0x0000, 0x4d46, 0x7236, 0x0000, 0x0000, 0x5d7e, 0x0000, 0x0000,
+ 0x0000, 0x4c37, 0x5b38, 0x0000, 0x0000, 0x0000, 0x0000, 0x5069,
+ 0x0000, 0x4e5d, 0x6b40, 0x0000, 0x7d22, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x784b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6a56, 0x7130, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5b4e, 0x0000, 0x7743, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5b4f, 0x4b24, 0x0000, 0x0000, 0x7860, 0x0000,
+ 0x0000, 0x7b57, 0x0000, 0x0000, 0x6b4a, 0x6021, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4e4d, 0x0000, 0x0000, 0x545c, 0x0000, 0x0000, 0x0000,
+ 0x7d58, 0x0000, 0x0000, 0x0000, 0x0000, 0x5276, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_81[] = {
+ 0x0000, 0x0000, 0x7237, 0x0000, 0x0000, 0x7a76, 0x762a, 0x7a77,
+ 0x5866, 0x0000, 0x7431, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6852, 0x0000, 0x4a45, 0x4c6b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x626e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x623b, 0x0000, 0x772d, 0x0000, 0x0000, 0x0000, 0x7861,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x736c, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e21, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x647d, 0x0000, 0x0000, 0x636c, 0x0000,
+ 0x5d2f, 0x5d30, 0x0000, 0x0000, 0x4b37, 0x6853, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6123, 0x5260, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x707e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6926, 0x4b72, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6d73, 0x5c59, 0x604d, 0x0000, 0x0000, 0x0000, 0x0000, 0x775a,
+ 0x5b39, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4c2e, 0x0000, 0x5a5b, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d47,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5d31, 0x0000, 0x582f, 0x6323, 0x0000, 0x0000,
+ 0x4e6f, 0x0000, 0x0000, 0x7273, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7833, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x604e, 0x0000, 0x757d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6b6c, 0x0000, 0x0000, 0x5345, 0x7c6c, 0x525b,
+ 0x546b, 0x0000, 0x5e22, 0x0000, 0x0000, 0x0000, 0x6566, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7030, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5222, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d74,
+ 0x0000, 0x0000, 0x0000, 0x636d, 0x0000, 0x6842, 0x0000, 0x6d75,
+ 0x577c, 0x0000, 0x6d3b, 0x0000, 0x0000, 0x762b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7238, 0x7648, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5366, 0x725d, 0x4f3f, 0x0000, 0x6b2c, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_82[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4f40, 0x0000, 0x6628,
+ 0x7d69, 0x0000, 0x4f41, 0x0000, 0x605f, 0x5e6c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6022, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x743f, 0x626f, 0x0000, 0x5971, 0x7147,
+ 0x0000, 0x4b38, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x797e, 0x5b3a, 0x5a75, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x766c, 0x5a5c, 0x7a64,
+ 0x0000, 0x604f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5d32, 0x0000, 0x0000, 0x0000, 0x0000, 0x6629, 0x0000, 0x6f73,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x736d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6b7a, 0x0000, 0x7966, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a5d, 0x555e,
+ 0x0000, 0x4a5e, 0x5f64, 0x0000, 0x0000, 0x0000, 0x667d, 0x0000,
+ 0x752c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6475, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6963, 0x0000, 0x6d4b, 0x4f64, 0x0000,
+ 0x0000, 0x0000, 0x5853, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5d33, 0x546c, 0x0000, 0x0000, 0x7239, 0x0000, 0x5f37,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b4e, 0x7b58, 0x0000,
+ 0x0000, 0x5059, 0x0000, 0x0000, 0x5d52, 0x7774, 0x675c, 0x6425,
+ 0x0000, 0x7c23, 0x0000, 0x5b3b, 0x0000, 0x0000, 0x0000, 0x723a,
+ 0x697d, 0x504a, 0x0000, 0x7556, 0x5945, 0x6434, 0x0000, 0x6d27,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6a3d, 0x667e, 0x0000, 0x7744, 0x752d, 0x0000, 0x5960,
+ 0x0000, 0x0000, 0x0000, 0x4a34, 0x0000, 0x0000, 0x7862, 0x4f42,
+ 0x0000, 0x6c3e, 0x0000, 0x0000, 0x0000, 0x652e, 0x4d48, 0x6e48,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6748, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d49, 0x7937, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_83[] = {
+ 0x0000, 0x7168, 0x5972, 0x5b75, 0x4a35, 0x5946, 0x0000, 0x0000,
+ 0x0000, 0x5849, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x592b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6d3c, 0x0000, 0x0000, 0x5854, 0x0000, 0x0000, 0x0000, 0x5c5a,
+ 0x0000, 0x623c, 0x0000, 0x0000, 0x7c6d, 0x6c60, 0x527e, 0x0000,
+ 0x6947, 0x662a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6270, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7a3b,
+ 0x0000, 0x752e, 0x7b2a, 0x0000, 0x0000, 0x0000, 0x0000, 0x6c7b,
+ 0x0000, 0x6c3f, 0x7c58, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5465, 0x0000, 0x0000, 0x0000, 0x7943,
+ 0x0000, 0x0000, 0x0000, 0x6e62, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5769, 0x6d76, 0x0000, 0x0000, 0x0000, 0x5e6d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c6c, 0x0000,
+ 0x636e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6854, 0x0000,
+ 0x0000, 0x0000, 0x7a78, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5d34, 0x6435, 0x5830, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5855, 0x0000, 0x0000,
+ 0x0000, 0x746a, 0x0000, 0x0000, 0x0000, 0x4e39, 0x0000, 0x0000,
+ 0x0000, 0x5252, 0x4f52, 0x0000, 0x5036, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4e22, 0x0000, 0x0000, 0x736e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7378, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5c4c, 0x0000, 0x504b, 0x0000, 0x0000, 0x0000, 0x7c24,
+ 0x4d4a, 0x5277, 0x5e23, 0x0000, 0x6460, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6e49, 0x0000, 0x0000, 0x0000, 0x625d, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_84[] = {
+ 0x0000, 0x0000, 0x0000, 0x757e, 0x542c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5551, 0x0000, 0x5870, 0x7843, 0x6a57, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7557, 0x0000, 0x0000, 0x583f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7d40, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6b2d, 0x0000, 0x0000, 0x0000, 0x0000, 0x5166, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6071, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6e4a,
+ 0x0000, 0x0000, 0x0000, 0x4a67, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7863, 0x0000, 0x545d, 0x0000, 0x0000, 0x6a58, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7b59, 0x6d77, 0x0000, 0x0000, 0x6535,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x502d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7171, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x623d, 0x0000, 0x0000, 0x0000, 0x6348, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5955, 0x0000, 0x0000, 0x5f2a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5b3c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7864, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x717a, 0x0000, 0x0000, 0x6536, 0x736f, 0x0000, 0x0000, 0x7b5a,
+ 0x6160, 0x0000, 0x592c, 0x0000, 0x756b, 0x0000, 0x6036, 0x0000,
+ 0x0000, 0x6948, 0x0000, 0x4b4f, 0x0000, 0x6349, 0x0000, 0x0000,
+ 0x0000, 0x5e6e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x623e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5c6f, 0x0000, 0x5625, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6271, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x567e, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_85[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5921, 0x0000, 0x5840, 0x5c5b, 0x0000, 0x0000, 0x6d3d,
+ 0x5f38, 0x0000, 0x6a25, 0x0000, 0x0000, 0x0000, 0x572d, 0x0000,
+ 0x0000, 0x7379, 0x0000, 0x6d78, 0x0000, 0x7547, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x614a, 0x6b63, 0x0000, 0x725e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x784c, 0x0000, 0x6a59,
+ 0x0000, 0x5346, 0x0000, 0x5b66, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x752f, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e70, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x697e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7b36, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6272, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4f72, 0x7739, 0x5973, 0x0000, 0x0000, 0x614b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5a5d, 0x0000, 0x0000, 0x5a39,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6b7b,
+ 0x0000, 0x4b39, 0x0000, 0x0000, 0x6d79, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6060, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7440, 0x0000,
+ 0x7d3c, 0x5f31, 0x636f, 0x0000, 0x0000, 0x0000, 0x0000, 0x6023,
+ 0x7d39, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7031, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4d4b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6d3e, 0x0000, 0x0000, 0x0000, 0x517c, 0x6370, 0x6d7a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6964, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x556d, 0x675d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5476, 0x6537, 0x0000, 0x0000,
+ 0x0000, 0x5b67, 0x623f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6e4b,
+ 0x0000, 0x0000, 0x5774, 0x705d, 0x0000, 0x0000, 0x0000, 0x4e2b
+};
+
+static unsigned short ksc5601_from_unicode_86[] = {
+ 0x0000, 0x0000, 0x675e, 0x0000, 0x0000, 0x0000, 0x5248, 0x614c,
+ 0x0000, 0x0000, 0x6833, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x656e, 0x5c22,
+ 0x0000, 0x0000, 0x6050, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5170, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x515d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b5b, 0x0000,
+ 0x794b, 0x0000, 0x0000, 0x0000, 0x4b73, 0x7425, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7a48, 0x5249, 0x0000, 0x6965, 0x7b5c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7d50,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7b76, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5a25, 0x0000, 0x5b3d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6c62, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4d77, 0x705e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7649, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e6f,
+ 0x0000, 0x0000, 0x0000, 0x5331, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7c6e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6843, 0x0000, 0x7148, 0x0000, 0x0000, 0x0000, 0x4e71,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x796d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7274, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6436, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_87[] = {
+ 0x7539, 0x0000, 0x5c70, 0x6371, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6825, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x723b, 0x0000, 0x5e24, 0x0000, 0x5a4c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a69, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x635a, 0x0000, 0x7c59,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a5a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7944, 0x0000,
+ 0x6324, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7b5d, 0x0000, 0x6f4a, 0x0000,
+ 0x6844, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x554c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6b57, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x592d,
+ 0x0000, 0x0000, 0x7b2b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5359, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x515e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x765e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5a76, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6051, 0x0000, 0x0000, 0x6928,
+ 0x0000, 0x0000, 0x7579, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7a2f, 0x0000, 0x6b7c, 0x0000, 0x0000, 0x606a, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_88[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6332, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5223,
+ 0x0000, 0x0000, 0x7163, 0x556e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4d4c, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d59, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5841, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7a6c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x716b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7a21, 0x6662, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7a65, 0x627a, 0x0000, 0x0000, 0x0000, 0x4a36,
+ 0x0000, 0x6437, 0x0000, 0x6a5b, 0x0000, 0x757a, 0x0000, 0x0000,
+ 0x0000, 0x7b2c, 0x4f43, 0x6b7d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x787a, 0x0000, 0x0000, 0x5f39, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6171, 0x0000, 0x5224, 0x0000, 0x0000, 0x0000, 0x0000, 0x757b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x505a, 0x505b,
+ 0x0000, 0x6a3e, 0x5931, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4a37, 0x0000, 0x0000, 0x5367, 0x0000, 0x7865, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5332, 0x0000, 0x0000, 0x0000, 0x6240, 0x725f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d65, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x792c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4d4d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6e2e, 0x562e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x576a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6760, 0x6b2e, 0x0000, 0x0000,
+ 0x0000, 0x4f59, 0x0000, 0x0000, 0x5c4d, 0x6d7b, 0x0000, 0x5e70,
+ 0x0000, 0x576b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5e25, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5f57, 0x5b50, 0x5b51, 0x0000, 0x0000,
+ 0x515f, 0x0000, 0x0000, 0x0000, 0x0000, 0x7032, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_89[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c5c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4a68, 0x0000, 0x7866, 0x5c4e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6a5c, 0x5b52, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6933, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x775b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6328, 0x0000,
+ 0x572e, 0x0000, 0x0000, 0x6061, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4b3a, 0x0000, 0x0000, 0x6551, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x505c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x517d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x584a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6329, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6024,
+ 0x0000, 0x6929, 0x0000, 0x5347, 0x0000, 0x0000, 0x5c5d, 0x782e,
+ 0x0000, 0x0000, 0x0000, 0x7a66, 0x0000, 0x0000, 0x0000, 0x502e,
+ 0x0000, 0x0000, 0x0000, 0x5872, 0x0000, 0x0000, 0x634a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4c2f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x542d, 0x7651, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x504c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4a46, 0x0000, 0x0000, 0x5542, 0x0000, 0x0000,
+ 0x4e3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4a47, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7a30, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5f58, 0x0000, 0x0000, 0x0000,
+ 0x753a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_8a[] = {
+ 0x656b, 0x0000, 0x6f74, 0x5d35, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4d2a, 0x0000, 0x6372, 0x0000, 0x7b77, 0x0000, 0x7750, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7d3a, 0x0000, 0x0000, 0x7d61, 0x767e,
+ 0x5140, 0x0000, 0x0000, 0x6845, 0x0000, 0x6438, 0x0000, 0x6168,
+ 0x0000, 0x0000, 0x0000, 0x4c41, 0x0000, 0x526d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5b3e, 0x0000, 0x0000, 0x6062, 0x0000, 0x0000,
+ 0x0000, 0x7a49, 0x0000, 0x0000, 0x614d, 0x0000, 0x4a38, 0x0000,
+ 0x0000, 0x0000, 0x7260, 0x7149, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5e71, 0x0000, 0x0000, 0x0000, 0x705f, 0x7844, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6e4c, 0x0000, 0x0000, 0x5e72, 0x0000,
+ 0x6749, 0x0000, 0x6273, 0x6761, 0x0000, 0x0000, 0x634b, 0x0000,
+ 0x0000, 0x634c, 0x0000, 0x0000, 0x0000, 0x4f78, 0x6f2c, 0x0000,
+ 0x7d7e, 0x7c25, 0x7a31, 0x5f59, 0x0000, 0x6052, 0x0000, 0x0000,
+ 0x0000, 0x745a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x714a, 0x0000, 0x4e23,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x723c, 0x6c63, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6025, 0x0000, 0x772b, 0x0000, 0x0000,
+ 0x6b2f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x655e, 0x0000,
+ 0x6124, 0x4d2b, 0x0000, 0x5974, 0x6826, 0x4d4e, 0x6169, 0x0000,
+ 0x7c6f, 0x0000, 0x6063, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6241, 0x0000, 0x4e24, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5e26, 0x0000, 0x0000, 0x6b7e, 0x0000, 0x6b5d, 0x7060,
+ 0x0000, 0x0000, 0x745b, 0x0000, 0x6274, 0x0000, 0x0000, 0x5348,
+ 0x0000, 0x0000, 0x0000, 0x746b, 0x0000, 0x6e35, 0x0000, 0x7558,
+ 0x0000, 0x0000, 0x555f, 0x0000, 0x0000, 0x0000, 0x5255, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6b30, 0x7463, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x634d, 0x0000, 0x0000, 0x0000, 0x0000, 0x7474, 0x7a32,
+ 0x0000, 0x0000, 0x6f75, 0x4a5f, 0x0000, 0x6b31, 0x6d3f, 0x0000,
+ 0x0000, 0x7d49, 0x0000, 0x0000, 0x0000, 0x0000, 0x6426, 0x7924,
+ 0x7033, 0x0000, 0x656c, 0x0000, 0x0000, 0x0000, 0x5167, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_8b[] = {
+ 0x5947, 0x6457, 0x6a5d, 0x0000, 0x5477, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a3a, 0x0000,
+ 0x5a4d, 0x0000, 0x0000, 0x0000, 0x794c, 0x0000, 0x615a, 0x5b3f,
+ 0x0000, 0x4c45, 0x6c50, 0x4b3b, 0x0000, 0x5e73, 0x0000, 0x0000,
+ 0x692a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5948, 0x0000, 0x0000, 0x6e63, 0x573d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4f44, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x504d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7c26, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x717b, 0x0000, 0x0000, 0x0000, 0x0000, 0x7d52, 0x5141,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x635b, 0x0000, 0x5349, 0x0000, 0x5c4f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c6d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5e27, 0x0000, 0x0000, 0x663b,
+ 0x6c21, 0x0000, 0x0000, 0x0000, 0x4c39, 0x0000, 0x0000, 0x7b5e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6762, 0x0000, 0x0000,
+ 0x5441, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5c28, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6242, 0x0000, 0x7358, 0x6553, 0x0000, 0x0000, 0x7359, 0x0000,
+ 0x0000, 0x0000, 0x7346, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_8c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d5b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d2c,
+ 0x0000, 0x7c43, 0x0000, 0x0000, 0x0000, 0x0000, 0x5467, 0x0000,
+ 0x5142, 0x0000, 0x7925, 0x0000, 0x6855, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x634e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x544a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5f5a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7b5f, 0x6763, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x787b, 0x634f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7530, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5867, 0x0000, 0x5949, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x782f, 0x6f76, 0x0000,
+ 0x5d36, 0x6e2f, 0x4d78, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e38,
+ 0x7c27, 0x777c, 0x7731, 0x4e3b, 0x7421, 0x0000, 0x0000, 0x6e4d,
+ 0x612e, 0x0000, 0x0000, 0x6c43, 0x4f7e, 0x0000, 0x783f, 0x5862,
+ 0x5368, 0x0000, 0x0000, 0x5e28, 0x7464, 0x6c42, 0x0000, 0x5975,
+ 0x7945, 0x5d53, 0x5261, 0x6c7c, 0x7c70, 0x0000, 0x0000, 0x6d40,
+ 0x4a39, 0x0000, 0x6e64, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7261, 0x0000, 0x5e39, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5672, 0x0000, 0x5e74, 0x0000, 0x5f5b, 0x0000,
+ 0x5b53, 0x0000, 0x7a67, 0x5863, 0x7441, 0x0000, 0x5d37, 0x0000,
+ 0x0000, 0x0000, 0x7275, 0x0000, 0x0000, 0x542e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5673, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5d38, 0x4f45, 0x5f5f, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_8d[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x723e, 0x7621, 0x0000, 0x6b4b,
+ 0x717c, 0x0000, 0x7347, 0x0000, 0x0000, 0x606b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6d7c, 0x0000, 0x0000, 0x615b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6e65, 0x0000, 0x5e75, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7a53, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x714b, 0x0000, 0x0000, 0x502f, 0x5d39, 0x0000, 0x0000, 0x5143,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7531, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6a46, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7061, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x762c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7559, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x706b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5d3a, 0x0000, 0x0000, 0x0000, 0x723f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7745, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5b22, 0x7276, 0x0000, 0x0000, 0x4a3a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7775, 0x0000, 0x4b65, 0x0000, 0x0000,
+ 0x0000, 0x6e66, 0x0000, 0x6053, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4e25, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x524a,
+ 0x0000, 0x0000, 0x0000, 0x542f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_8e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6949, 0x0000, 0x0000, 0x0000, 0x0000, 0x534e,
+ 0x7442, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b66, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7121, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6b32, 0x0000, 0x0000, 0x0000, 0x0000, 0x7122, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6b33, 0x0000, 0x7034, 0x0000, 0x0000, 0x4b74,
+ 0x5430, 0x7332, 0x7b37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x756c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6e67,
+ 0x7432, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x756d, 0x0000, 0x4f73, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7062, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6e4e,
+ 0x0000, 0x0000, 0x714c, 0x0000, 0x0000, 0x6538, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5775, 0x6373, 0x4f65, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4f46, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7333, 0x6458, 0x4f79, 0x4f5a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7a4d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6663,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7262, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x756e, 0x0000, 0x0000, 0x4a3b, 0x0000, 0x0000, 0x635c, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_8f[] = {
+ 0x0000, 0x0000, 0x0000, 0x4e72, 0x0000, 0x5659, 0x0000, 0x0000,
+ 0x0000, 0x6e30, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7465, 0x5842, 0x5c50, 0x4c6e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5560, 0x764a, 0x7d4a, 0x5856, 0x744f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5626, 0x5c3e,
+ 0x0000, 0x5b54, 0x5747, 0x0000, 0x0000, 0x0000, 0x0000, 0x727e,
+ 0x0000, 0x0000, 0x0000, 0x714d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6243, 0x5c5e, 0x0000, 0x5c5f, 0x0000, 0x0000, 0x6f2d, 0x662b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x795d, 0x6a3f, 0x0000, 0x0000,
+ 0x0000, 0x6f2e, 0x0000, 0x0000, 0x0000, 0x7450, 0x4e73, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x662c, 0x0000, 0x4e5e,
+ 0x0000, 0x0000, 0x5579, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6374, 0x4d50, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5538, 0x0000, 0x0000, 0x777d, 0x0000,
+ 0x5c29, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e76, 0x0000, 0x5c2a,
+ 0x6375, 0x6934, 0x525c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6966, 0x0000, 0x0000, 0x6376, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x674a, 0x0000,
+ 0x0000, 0x504e, 0x0000, 0x0000, 0x5a77, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a3c, 0x0000,
+ 0x0000, 0x0000, 0x6e68, 0x5a5e, 0x0000, 0x7277, 0x0000, 0x0000,
+ 0x627b, 0x0000, 0x4c26, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a3b,
+ 0x0000, 0x6e69, 0x0000, 0x0000, 0x0000, 0x755a, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_90[] = {
+ 0x775c, 0x616a, 0x4e41, 0x5431, 0x0000, 0x7d31, 0x663d, 0x0000,
+ 0x7b2d, 0x0000, 0x0000, 0x7867, 0x0000, 0x614e, 0x0000, 0x7762,
+ 0x756f, 0x4f47, 0x0000, 0x0000, 0x5432, 0x4c6f, 0x0000, 0x5468,
+ 0x0000, 0x6e4f, 0x7757, 0x0000, 0x0000, 0x6026, 0x5641, 0x615c,
+ 0x7063, 0x7164, 0x5c71, 0x5627, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7475, 0x0000,
+ 0x0000, 0x714e, 0x7264, 0x0000, 0x0000, 0x5030, 0x0000, 0x0000,
+ 0x6c6f, 0x0000, 0x0000, 0x0000, 0x793a, 0x0000, 0x6b35, 0x0000,
+ 0x0000, 0x546d, 0x6244, 0x0000, 0x0000, 0x0000, 0x0000, 0x6967,
+ 0x0000, 0x0000, 0x6b34, 0x6a21, 0x0000, 0x783c, 0x4e26, 0x0000,
+ 0x7946, 0x7c5a, 0x0000, 0x5433, 0x5339, 0x6a5e, 0x0000, 0x0000,
+ 0x0000, 0x692b, 0x0000, 0x0000, 0x6161, 0x534f, 0x7476, 0x0000,
+ 0x6a40, 0x614f, 0x0000, 0x4c3a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6e6a, 0x0000, 0x0000, 0x0000, 0x7064, 0x7334, 0x546e,
+ 0x0000, 0x0000, 0x7240, 0x0000, 0x0000, 0x7165, 0x0000, 0x7443,
+ 0x6054, 0x0000, 0x6b36, 0x0000, 0x5721, 0x4b68, 0x0000, 0x792d,
+ 0x692d, 0x5864, 0x7a33, 0x6245, 0x7c3d, 0x0000, 0x0000, 0x6c44,
+ 0x5831, 0x0000, 0x5c2b, 0x0000, 0x0000, 0x0000, 0x0000, 0x5160,
+ 0x0000, 0x6b69, 0x0000, 0x0000, 0x0000, 0x683b, 0x0000, 0x0000,
+ 0x0000, 0x5857, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7b2e, 0x5161, 0x0000, 0x0000, 0x5b40, 0x0000,
+ 0x753e, 0x0000, 0x5e77, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a7b,
+ 0x7746, 0x4f48, 0x0000, 0x0000, 0x0000, 0x6150, 0x0000, 0x0000,
+ 0x6e50, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6974, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4e74, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x522b, 0x0000,
+ 0x0000, 0x4f5b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5d3b, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e2c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6968, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5434, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_91[] = {
+ 0x0000, 0x0000, 0x6447, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x755b, 0x0000, 0x0000, 0x7a41, 0x0000, 0x0000,
+ 0x0000, 0x5e29, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5478,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6f77, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5333, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6b37, 0x6f78, 0x755c, 0x6d4c, 0x5b55, 0x714f, 0x0000,
+ 0x0000, 0x0000, 0x7150, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7532, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x592e, 0x5168, 0x0000, 0x6246, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7d23, 0x0000, 0x7b65,
+ 0x5f2b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6275,
+ 0x0000, 0x762d, 0x0000, 0x7533, 0x0000, 0x7035, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6125, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x755d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6c22, 0x6d7d, 0x0000, 0x7534, 0x7b38,
+ 0x0000, 0x5b23, 0x0000, 0x0000, 0x564a, 0x4b59, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6554, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x737a,
+ 0x0000, 0x6b38, 0x0000, 0x6037, 0x576c, 0x716c, 0x652f, 0x5561,
+ 0x576d, 0x505d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6172,
+ 0x6f79, 0x0000, 0x0000, 0x0000, 0x5d3c, 0x765c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7065, 0x0000, 0x0000, 0x0000, 0x7444,
+ 0x0000, 0x0000, 0x6969, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x737b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_92[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x546f, 0x0000, 0x0000,
+ 0x4c22, 0x777e, 0x5f3c, 0x0000, 0x0000, 0x0000, 0x0000, 0x6b4d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5037, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5642, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x682d, 0x0000, 0x0000, 0x0000, 0x0000, 0x6f2f,
+ 0x4b25, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b69, 0x0000, 0x0000,
+ 0x0000, 0x7a68, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c46,
+ 0x0000, 0x0000, 0x0000, 0x6667, 0x0000, 0x0000, 0x6a47, 0x0000,
+ 0x0000, 0x0000, 0x5b24, 0x0000, 0x4f49, 0x627c, 0x6f7a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6b5e, 0x0000, 0x0000, 0x7548, 0x0000, 0x545e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6055, 0x0000, 0x6f30, 0x0000, 0x0000, 0x6247, 0x0000,
+ 0x592f, 0x0000, 0x0000, 0x0000, 0x7967, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6765, 0x0000, 0x0000, 0x4f4a, 0x6151,
+ 0x0000, 0x6248, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6f7b, 0x0000, 0x0000, 0x7a79,
+ 0x0000, 0x0000, 0x5c72, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6027, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7868, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4b6a, 0x0000, 0x0000, 0x0000, 0x4b3c, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_93[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5253, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x755e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x755f, 0x0000, 0x6e36, 0x0000, 0x0000, 0x0000, 0x6276, 0x534a,
+ 0x6f7c, 0x5144, 0x6f31, 0x0000, 0x5145, 0x0000, 0x505e, 0x0000,
+ 0x5961, 0x0000, 0x0000, 0x6038, 0x0000, 0x0000, 0x4d51, 0x7339,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x674c, 0x0000, 0x5628, 0x4e27, 0x0000, 0x5435, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6448, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5334, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6b39, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b75, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x765d, 0x0000, 0x7123, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4c47, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x694a, 0x0000, 0x6170, 0x0000,
+ 0x0000, 0x0000, 0x7560, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7b2f, 0x0000, 0x0000, 0x0000, 0x4b51,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7b60, 0x7265, 0x0000, 0x0000,
+ 0x6c70, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x706c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6e6b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x694b, 0x0000,
+ 0x0000, 0x4c70, 0x0000, 0x0000, 0x572f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7321, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_94[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7c75, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7124, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6056, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6f32, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7451, 0x0000, 0x0000,
+ 0x7721, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7151, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4a7c, 0x4a7d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4e4e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7348, 0x0000, 0x733a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_95[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d7e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5a26, 0x0000, 0x0000, 0x606c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x784d, 0x0000, 0x4b52, 0x0000, 0x0000, 0x0000, 0x6b4e,
+ 0x0000, 0x7958, 0x7959, 0x4a60, 0x5a4a, 0x0000, 0x0000, 0x0000,
+ 0x4b26, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4a48, 0x796e, 0x5b6c, 0x0000, 0x0000,
+ 0x5031, 0x0000, 0x0000, 0x0000, 0x0000, 0x556f, 0x0000, 0x0000,
+ 0x0000, 0x6673, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6722, 0x6459, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6461,
+ 0x0000, 0x0000, 0x7c44, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x796f, 0x4f74, 0x7766, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4e3c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7445, 0x5c23, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_96[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5d3d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7446, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7821, 0x0000, 0x0000, 0x0000, 0x6856, 0x0000,
+ 0x0000, 0x0000, 0x5b41, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7066, 0x0000, 0x0000, 0x0000, 0x6439,
+ 0x766d, 0x0000, 0x792e, 0x0000, 0x5d3e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x526b, 0x5868, 0x7a22, 0x0000, 0x0000,
+ 0x795a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x784e, 0x7970, 0x606d, 0x6333, 0x7433,
+ 0x0000, 0x0000, 0x6a42, 0x7266, 0x7036, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5b56, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6b64, 0x0000, 0x0000, 0x7267, 0x0000, 0x5278, 0x5436, 0x7968,
+ 0x5741, 0x0000, 0x0000, 0x0000, 0x0000, 0x6555, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x696a, 0x574c, 0x0000,
+ 0x0000, 0x0000, 0x5369, 0x6249, 0x0000, 0x7c5b, 0x4d2d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4c30, 0x6a22, 0x0000, 0x0000,
+ 0x6476, 0x5040, 0x0000, 0x7037, 0x6e21, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5776, 0x0000, 0x0000, 0x0000, 0x624a,
+ 0x624b, 0x0000, 0x7a4f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6b5f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x564b,
+ 0x0000, 0x0000, 0x0000, 0x7434, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6d4d, 0x6452, 0x0000, 0x0000, 0x6a29, 0x643a, 0x7322, 0x4d52,
+ 0x0000, 0x764b, 0x0000, 0x7166, 0x6d41, 0x683c, 0x6e51, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7067, 0x624c, 0x0000,
+ 0x0000, 0x642a, 0x0000, 0x7561, 0x6d5a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x576e, 0x5171, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x696b, 0x696c, 0x6064, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a27,
+ 0x5d54, 0x0000, 0x6a23, 0x0000, 0x0000, 0x0000, 0x5643, 0x5262,
+ 0x0000, 0x5a5f, 0x0000, 0x6f33, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_97[] = {
+ 0x624d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6f7d, 0x7268,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6f45, 0x0000, 0x6767, 0x0000, 0x0000, 0x577d, 0x0000,
+ 0x0000, 0x674e, 0x0000, 0x0000, 0x5f5c, 0x0000, 0x7947, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5976,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5f2c, 0x0000, 0x524b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5c24, 0x0000, 0x0000, 0x0000, 0x7038, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x557a, 0x0000, 0x6477, 0x0000, 0x0000, 0x0000,
+ 0x5644, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x746c, 0x0000, 0x0000, 0x0000, 0x0000, 0x6f7e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7021, 0x0000, 0x5e2a, 0x0000,
+ 0x0000, 0x5a3c, 0x587c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7a54, 0x0000, 0x0000, 0x0000, 0x6c65, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7c28, 0x0000, 0x0000, 0x6c66,
+ 0x0000, 0x0000, 0x584b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7b39, 0x0000, 0x6453, 0x0000, 0x4d79,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4f53, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4a6a, 0x0000, 0x0000, 0x4f54, 0x0000, 0x783d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7447, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6a5f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x795b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5437, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6b65, 0x0000, 0x0000, 0x6152, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6a24, 0x0000, 0x0000, 0x0000, 0x7a42
+};
+
+static unsigned short ksc5601_from_unicode_98[] = {
+ 0x7b61, 0x7a6d, 0x7022, 0x4c71, 0x0000, 0x7a23, 0x6277, 0x0000,
+ 0x624e, 0x0000, 0x6975, 0x0000, 0x616b, 0x0000, 0x0000, 0x0000,
+ 0x6768, 0x6857, 0x5a78, 0x544b, 0x0000, 0x0000, 0x0000, 0x7776,
+ 0x5645, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5469, 0x0000, 0x0000,
+ 0x7a7a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4c72, 0x775d, 0x0000, 0x5e3a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e28, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7039, 0x647e, 0x6449, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6454, 0x0000, 0x0000, 0x0000,
+ 0x6a43, 0x0000, 0x6f34, 0x0000, 0x0000, 0x0000, 0x573e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b62, 0x0000, 0x4d53,
+ 0x0000, 0x0000, 0x0000, 0x6f35, 0x0000, 0x0000, 0x0000, 0x7a69,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7926, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f3d,
+ 0x0000, 0x7747, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x787d, 0x0000, 0x0000, 0x787c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5e2b, 0x5b68, 0x0000, 0x0000, 0x635d,
+ 0x0000, 0x6162, 0x5146, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7650, 0x6b66, 0x5a79,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6c47, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5e78, 0x7869, 0x635e, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_99[] = {
+ 0x0000, 0x0000, 0x0000, 0x4e75, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7a43, 0x6557, 0x0000, 0x6c48, 0x0000, 0x0000, 0x0000,
+ 0x7349, 0x0000, 0x0000, 0x643b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x662e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6f36, 0x0000,
+ 0x5c3f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4e3d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5843, 0x0000, 0x0000,
+ 0x0000, 0x504f, 0x0000, 0x4f7a, 0x734a, 0x6057, 0x0000, 0x0000,
+ 0x0000, 0x5147, 0x692e, 0x0000, 0x683d, 0x0000, 0x0000, 0x7a44,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x624f, 0x0000,
+ 0x0000, 0x7a45, 0x0000, 0x0000, 0x0000, 0x7938, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c60, 0x0000, 0x0000,
+ 0x7b30, 0x0000, 0x0000, 0x0000, 0x5829, 0x655f, 0x7927, 0x0000,
+ 0x0000, 0x766e, 0x0000, 0x764c, 0x6278, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6c71, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5a60, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7152, 0x524c, 0x4f4b, 0x0000, 0x0000, 0x4a3d, 0x0000, 0x0000,
+ 0x0000, 0x5d3f, 0x0000, 0x0000, 0x0000, 0x766f, 0x0000, 0x5e79,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7a34, 0x0000, 0x0000,
+ 0x0000, 0x5169, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7167
+};
+
+static unsigned short ksc5601_from_unicode_9a[] = {
+ 0x0000, 0x5e3e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5c40, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5148, 0x5149,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x783e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4b76, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5479, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7562, 0x6153,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5869, 0x0000, 0x0000, 0x787e, 0x0000, 0x4f4c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7d24, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e76, 0x0000, 0x7a50,
+ 0x0000, 0x0000, 0x4c73, 0x663e, 0x0000, 0x0000, 0x0000, 0x762e,
+ 0x0000, 0x0000, 0x5570, 0x0000, 0x0000, 0x514a, 0x0000, 0x0000,
+ 0x0000, 0x7c3e, 0x5571, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4d69, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7a35, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6250, 0x7477, 0x0000, 0x0000, 0x0000,
+ 0x4d54, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6723, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b25, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_9b[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6251, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5722,
+ 0x0000, 0x0000, 0x7763, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6a26, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5021, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4e5a, 0x7b6b, 0x5b26, 0x5b5e, 0x5865, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a60,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x582a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6560, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x524d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6f46, 0x0000,
+ 0x0000, 0x786a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6455,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4e77, 0x0000, 0x0000, 0x6058, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x576f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x746d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4d66, 0x0000, 0x0000, 0x0000,
+ 0x4c74, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_9c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7563, 0x0000, 0x0000,
+ 0x644a, 0x0000, 0x5c61, 0x0000, 0x0000, 0x7948, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7c3f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6827, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5844, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b3e,
+ 0x0000, 0x5c2e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5777,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7068, 0x0000, 0x5d40,
+ 0x0000, 0x4f4d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5c73, 0x5930, 0x0000, 0x6669, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_9d[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x643c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6a44, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x646c, 0x0000,
+ 0x6465, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7b78, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4c3b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x643d, 0x0000, 0x0000,
+ 0x4d5c, 0x5977, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5d5f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6d4e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5950, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6523,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x794d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4d2e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4f4e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x762f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7d53, 0x6b6d, 0x524e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_9e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6524, 0x0000, 0x0000, 0x0000, 0x5172, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x565d, 0x0000, 0x0000,
+ 0x0000, 0x7969, 0x0000, 0x0000, 0x0000, 0x6724, 0x0000, 0x5254,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x514b, 0x5664, 0x0000, 0x0000, 0x0000, 0x5572,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e7a, 0x0000, 0x5778,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x586a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4f55, 0x587d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x582b, 0x0000, 0x0000, 0x7d4b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7c5c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6028, 0x5573, 0x0000,
+ 0x0000, 0x7d59, 0x0000, 0x0000, 0x4c23, 0x0000, 0x0000, 0x0000,
+ 0x5979, 0x0000, 0x0000, 0x536a, 0x7575, 0x0000, 0x6f47, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x535a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5a3d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_9f[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6828,
+ 0x5c2f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7023, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4d55, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6029, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5e2c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x703a, 0x6e31, 0x0000, 0x0000, 0x6e32, 0x0000,
+ 0x0000, 0x0000, 0x764d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6e52,
+ 0x0000, 0x5646, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6065,
+ 0x0000, 0x0000, 0x733b, 0x0000, 0x6561, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x644b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5723, 0x0000, 0x0000,
+ 0x5b42, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a7e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4f4f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_ac[] = {
+ 0x3021, 0x3022, 0x0000, 0x0000, 0x3023, 0x0000, 0x0000, 0x3024,
+ 0x3025, 0x3026, 0x3027, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3028, 0x3029, 0x302a, 0x302b, 0x302c, 0x302d, 0x302e, 0x302f,
+ 0x0000, 0x3030, 0x3031, 0x3032, 0x3033, 0x3034, 0x0000, 0x0000,
+ 0x3035, 0x0000, 0x0000, 0x0000, 0x3036, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3037, 0x3038, 0x0000, 0x3039,
+ 0x303a, 0x303b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x303c, 0x303d, 0x0000, 0x0000, 0x303e, 0x0000, 0x0000, 0x0000,
+ 0x303f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3040, 0x0000, 0x3041, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3042, 0x0000, 0x0000, 0x0000,
+ 0x3043, 0x0000, 0x0000, 0x0000, 0x3044, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3045, 0x3046, 0x0000, 0x0000, 0x3047, 0x0000, 0x0000, 0x3048,
+ 0x3049, 0x0000, 0x304a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x304b, 0x304c, 0x0000, 0x304d, 0x304e, 0x304f, 0x3050, 0x0000,
+ 0x0000, 0x3051, 0x3052, 0x3053, 0x3054, 0x0000, 0x0000, 0x0000,
+ 0x3055, 0x0000, 0x0000, 0x0000, 0x3056, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3057, 0x3058, 0x0000, 0x3059,
+ 0x305a, 0x305b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x305c, 0x305d, 0x305e, 0x0000, 0x305f, 0x0000, 0x0000, 0x3060,
+ 0x3061, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3062, 0x3063, 0x0000, 0x3064, 0x3065, 0x3066, 0x0000, 0x0000,
+ 0x0000, 0x3067, 0x0000, 0x0000, 0x3068, 0x0000, 0x0000, 0x0000,
+ 0x3069, 0x0000, 0x0000, 0x0000, 0x306a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x306b, 0x0000, 0x306c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x306d, 0x306e, 0x0000, 0x0000, 0x306f, 0x0000, 0x0000, 0x3070,
+ 0x3071, 0x0000, 0x3072, 0x0000, 0x3073, 0x0000, 0x0000, 0x3074,
+ 0x3075, 0x3076, 0x0000, 0x3077, 0x0000, 0x3078, 0x3079, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x307a, 0x307b, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_ad[] = {
+ 0x307c, 0x0000, 0x0000, 0x0000, 0x307d, 0x0000, 0x307e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3121, 0x3122, 0x0000, 0x3123,
+ 0x0000, 0x3124, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3125, 0x0000, 0x0000, 0x0000, 0x3126, 0x0000, 0x0000, 0x0000,
+ 0x3127, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3128, 0x0000, 0x0000, 0x3129, 0x312a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x312b, 0x312c, 0x0000, 0x0000,
+ 0x312d, 0x0000, 0x0000, 0x0000, 0x312e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x312f, 0x3130, 0x0000, 0x3131,
+ 0x0000, 0x3132, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3133, 0x0000, 0x0000, 0x0000, 0x3134, 0x0000, 0x0000, 0x0000,
+ 0x3135, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3136, 0x0000, 0x3137, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3138, 0x3139, 0x0000, 0x0000,
+ 0x313a, 0x0000, 0x0000, 0x313b, 0x313c, 0x313d, 0x313e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x313f, 0x3140, 0x3141, 0x0000, 0x3142,
+ 0x0000, 0x3143, 0x3144, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3145, 0x3146, 0x0000, 0x0000, 0x3147, 0x0000, 0x0000, 0x0000,
+ 0x3148, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3149, 0x314a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x314b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x314c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x314d, 0x314e, 0x0000, 0x0000, 0x314f, 0x0000, 0x0000, 0x0000,
+ 0x3150, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3151, 0x3152, 0x0000, 0x3153, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3154, 0x0000, 0x0000, 0x0000,
+ 0x3155, 0x0000, 0x0000, 0x0000, 0x3156, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3157, 0x3158, 0x0000, 0x0000, 0x3159, 0x0000, 0x0000, 0x315a
+};
+
+static unsigned short ksc5601_from_unicode_ae[] = {
+ 0x315b, 0x315c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x315d, 0x315e, 0x0000, 0x315f, 0x0000, 0x3160, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3161, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3162, 0x3163, 0x0000, 0x0000, 0x3164, 0x0000, 0x0000, 0x3165,
+ 0x3166, 0x0000, 0x3167, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3168, 0x3169, 0x0000, 0x316a, 0x0000, 0x316b, 0x316c, 0x0000,
+ 0x0000, 0x0000, 0x316d, 0x0000, 0x316e, 0x316f, 0x3170, 0x0000,
+ 0x3171, 0x0000, 0x0000, 0x0000, 0x3172, 0x0000, 0x3173, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3174, 0x3175, 0x0000, 0x3176,
+ 0x3177, 0x3178, 0x0000, 0x0000, 0x0000, 0x3179, 0x0000, 0x0000,
+ 0x317a, 0x317b, 0x0000, 0x0000, 0x317c, 0x0000, 0x0000, 0x0000,
+ 0x317d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x317e, 0x3221, 0x0000, 0x3222, 0x3223, 0x3224, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3225, 0x3226, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3227, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3228, 0x3229, 0x322a, 0x0000,
+ 0x322b, 0x0000, 0x0000, 0x0000, 0x322c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x322d, 0x322e, 0x0000, 0x322f,
+ 0x3230, 0x3231, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3232, 0x3233, 0x0000, 0x0000, 0x3234, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3235, 0x0000, 0x0000, 0x3236, 0x0000, 0x3237, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3238, 0x0000, 0x0000, 0x0000,
+ 0x3239, 0x0000, 0x0000, 0x0000, 0x323a, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_af[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x323b,
+ 0x323c, 0x0000, 0x0000, 0x0000, 0x0000, 0x323d, 0x0000, 0x0000,
+ 0x323e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x323f, 0x3240, 0x0000, 0x0000,
+ 0x3241, 0x0000, 0x3242, 0x0000, 0x3243, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3244, 0x3245, 0x0000, 0x3246,
+ 0x0000, 0x3247, 0x3248, 0x3249, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x324a, 0x324b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x324c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x324d, 0x324e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x324f, 0x3250, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3251, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3252, 0x0000, 0x0000, 0x0000, 0x3253, 0x0000, 0x0000, 0x0000,
+ 0x3254, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3255, 0x3256, 0x0000, 0x0000, 0x0000, 0x3257, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3258, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3259, 0x325a, 0x0000, 0x0000, 0x325b, 0x0000, 0x0000, 0x0000,
+ 0x325c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x325d,
+ 0x325e, 0x325f, 0x0000, 0x3260, 0x0000, 0x3261, 0x3262, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3263, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3264, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3265, 0x3266, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3267, 0x3268, 0x0000, 0x0000, 0x3269, 0x0000, 0x0000, 0x0000,
+ 0x326a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_b0[] = {
+ 0x326b, 0x326c, 0x0000, 0x0000, 0x326d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x326e, 0x0000, 0x0000, 0x0000,
+ 0x326f, 0x0000, 0x0000, 0x0000, 0x3270, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3271, 0x3272, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3273, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3274, 0x3275, 0x0000, 0x0000,
+ 0x3276, 0x0000, 0x3277, 0x0000, 0x3278, 0x0000, 0x3279, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x327a, 0x327b, 0x327c, 0x0000, 0x327d,
+ 0x0000, 0x327e, 0x0000, 0x0000, 0x0000, 0x3321, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3322, 0x3323, 0x0000, 0x0000,
+ 0x3324, 0x0000, 0x0000, 0x0000, 0x3325, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3326, 0x3327, 0x0000, 0x3328,
+ 0x0000, 0x3329, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x332a, 0x332b, 0x332c, 0x0000, 0x332d, 0x0000, 0x0000, 0x332e,
+ 0x332f, 0x3330, 0x3331, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3332, 0x3333, 0x0000, 0x3334, 0x3335, 0x3336, 0x3337, 0x3338,
+ 0x0000, 0x3339, 0x0000, 0x333a, 0x333b, 0x333c, 0x0000, 0x0000,
+ 0x333d, 0x0000, 0x0000, 0x0000, 0x333e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x333f, 0x3340, 0x0000, 0x3341,
+ 0x3342, 0x3343, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3344, 0x3345, 0x0000, 0x0000, 0x3346, 0x0000, 0x0000, 0x0000,
+ 0x3347, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3348, 0x0000, 0x0000, 0x0000, 0x0000, 0x3349, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_b1[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x334a, 0x334b, 0x0000, 0x334c, 0x334d, 0x0000, 0x0000, 0x0000,
+ 0x334e, 0x0000, 0x334f, 0x3350, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3351, 0x3352, 0x0000, 0x3353, 0x3354, 0x3355, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3356, 0x3357, 0x3358, 0x0000, 0x0000,
+ 0x3359, 0x0000, 0x0000, 0x0000, 0x335a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x335b, 0x335c, 0x0000, 0x335d,
+ 0x335e, 0x335f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3360, 0x3361, 0x0000, 0x0000, 0x3362, 0x0000, 0x0000, 0x0000,
+ 0x3363, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3364, 0x3365, 0x0000, 0x0000, 0x3366, 0x3367, 0x0000, 0x0000,
+ 0x3368, 0x0000, 0x0000, 0x0000, 0x3369, 0x0000, 0x0000, 0x0000,
+ 0x336a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x336b, 0x336c, 0x0000, 0x0000, 0x336d, 0x0000, 0x0000, 0x0000,
+ 0x336e, 0x0000, 0x336f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3370, 0x3371, 0x0000, 0x3372, 0x0000, 0x3373, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3374, 0x3375, 0x3376, 0x0000, 0x0000, 0x0000,
+ 0x3377, 0x0000, 0x0000, 0x0000, 0x3378, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3379, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x337a, 0x0000, 0x0000, 0x0000,
+ 0x337b, 0x0000, 0x0000, 0x0000, 0x337c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x337d, 0x337e, 0x0000, 0x3421,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3422, 0x3423, 0x0000, 0x0000, 0x3424, 0x0000, 0x0000, 0x0000,
+ 0x3425, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3426, 0x0000, 0x3427, 0x0000, 0x3428, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_b2[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3429, 0x342a, 0x0000, 0x0000,
+ 0x342b, 0x0000, 0x0000, 0x342c, 0x342d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x342e, 0x342f, 0x0000, 0x3430,
+ 0x0000, 0x3431, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3432, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3433, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3434, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3435, 0x0000, 0x0000, 0x0000, 0x3436, 0x0000, 0x0000, 0x0000,
+ 0x3437, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3438, 0x3439, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x343a, 0x343b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x343c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x343d, 0x343e, 0x0000, 0x0000,
+ 0x0000, 0x343f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3440, 0x3441, 0x0000, 0x0000, 0x3442, 0x0000, 0x0000, 0x0000,
+ 0x3443, 0x3444, 0x3445, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3446, 0x3447, 0x0000, 0x3448, 0x0000, 0x3449, 0x344a, 0x0000,
+ 0x0000, 0x0000, 0x344b, 0x0000, 0x344c, 0x0000, 0x0000, 0x0000,
+ 0x344d, 0x0000, 0x0000, 0x0000, 0x344e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x344f, 0x3450, 0x0000, 0x0000, 0x3451, 0x0000, 0x0000, 0x0000,
+ 0x3452, 0x0000, 0x3453, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3454, 0x3455, 0x0000, 0x3456, 0x0000, 0x3457, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3458, 0x0000, 0x3459, 0x345a, 0x345b, 0x0000,
+ 0x345c, 0x0000, 0x0000, 0x345d, 0x345e, 0x345f, 0x3460, 0x3461,
+ 0x0000, 0x0000, 0x0000, 0x3462, 0x3463, 0x3464, 0x0000, 0x3465,
+ 0x3466, 0x3467, 0x3468, 0x3469, 0x0000, 0x0000, 0x0000, 0x346a
+};
+
+static unsigned short ksc5601_from_unicode_b3[] = {
+ 0x346b, 0x346c, 0x0000, 0x0000, 0x346d, 0x0000, 0x0000, 0x0000,
+ 0x346e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x346f, 0x3470, 0x0000, 0x3471, 0x3472, 0x3473, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3474, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3475, 0x3476, 0x3477, 0x0000,
+ 0x3478, 0x0000, 0x0000, 0x3479, 0x347a, 0x0000, 0x347b, 0x347c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x347d, 0x347e, 0x0000, 0x3521,
+ 0x0000, 0x3522, 0x0000, 0x3523, 0x0000, 0x0000, 0x3524, 0x0000,
+ 0x3525, 0x3526, 0x0000, 0x0000, 0x3527, 0x0000, 0x0000, 0x0000,
+ 0x3528, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3529, 0x352a, 0x0000, 0x352b, 0x352c, 0x352d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x352e, 0x0000, 0x0000, 0x0000,
+ 0x352f, 0x0000, 0x0000, 0x0000, 0x3530, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3531, 0x3532, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3533, 0x0000, 0x0000, 0x0000, 0x3534, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3535, 0x3536, 0x0000, 0x0000,
+ 0x3537, 0x0000, 0x0000, 0x3538, 0x3539, 0x0000, 0x353a, 0x0000,
+ 0x353b, 0x0000, 0x0000, 0x0000, 0x353c, 0x353d, 0x0000, 0x353e,
+ 0x0000, 0x353f, 0x0000, 0x3540, 0x0000, 0x3541, 0x0000, 0x0000,
+ 0x3542, 0x0000, 0x0000, 0x0000, 0x3543, 0x0000, 0x0000, 0x0000,
+ 0x3544, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3545, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_b4[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3546, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3547, 0x0000, 0x0000, 0x0000, 0x3548, 0x0000, 0x0000, 0x0000,
+ 0x3549, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x354a, 0x354b, 0x0000, 0x354c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x354d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x354e, 0x354f, 0x0000, 0x0000, 0x3550, 0x0000, 0x0000, 0x0000,
+ 0x3551, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3552, 0x3553, 0x0000, 0x3554, 0x0000, 0x3555, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3556, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3557, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3558, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3559, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x355a, 0x0000, 0x0000, 0x0000,
+ 0x355b, 0x0000, 0x0000, 0x0000, 0x355c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x355d, 0x0000, 0x355e,
+ 0x0000, 0x355f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3560, 0x0000, 0x0000, 0x0000, 0x3561, 0x0000, 0x0000, 0x0000,
+ 0x3562, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3563, 0x0000, 0x0000, 0x0000, 0x0000, 0x3564, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3565, 0x3566, 0x0000, 0x0000,
+ 0x3567, 0x0000, 0x0000, 0x3568, 0x3569, 0x0000, 0x356a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x356b, 0x356c, 0x0000, 0x356d,
+ 0x0000, 0x356e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x356f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_b5[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3570, 0x3571, 0x0000, 0x0000,
+ 0x3572, 0x0000, 0x0000, 0x3573, 0x3574, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3575, 0x3576, 0x0000, 0x3577,
+ 0x3578, 0x3579, 0x357a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x357b, 0x357c, 0x0000, 0x0000, 0x357d, 0x0000, 0x0000, 0x0000,
+ 0x357e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3621, 0x3622, 0x0000, 0x3623, 0x3624, 0x3625, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3626, 0x3627, 0x3628, 0x0000, 0x0000,
+ 0x3629, 0x0000, 0x0000, 0x0000, 0x362a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x362b, 0x362c, 0x0000, 0x362d,
+ 0x362e, 0x362f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3630, 0x3631, 0x0000, 0x0000, 0x3632, 0x0000, 0x0000, 0x0000,
+ 0x3633, 0x0000, 0x3634, 0x3635, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3636, 0x3637, 0x0000, 0x3638, 0x3639, 0x363a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x363b, 0x363c, 0x363d, 0x0000, 0x0000,
+ 0x363e, 0x0000, 0x0000, 0x0000, 0x363f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3640, 0x3641, 0x0000, 0x3642,
+ 0x3643, 0x3644, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3645, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3646, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_b6[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3647, 0x3648, 0x0000, 0x0000, 0x3649, 0x0000, 0x0000, 0x0000,
+ 0x364a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x364b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x364c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x364d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x364e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x364f, 0x0000, 0x0000, 0x0000,
+ 0x3650, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3651, 0x3652, 0x0000, 0x0000,
+ 0x3653, 0x0000, 0x0000, 0x0000, 0x3654, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3655, 0x3656, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3657, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3658, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3659, 0x0000, 0x0000, 0x0000, 0x365a, 0x0000, 0x0000, 0x0000,
+ 0x365b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_b7[] = {
+ 0x365c, 0x365d, 0x0000, 0x0000, 0x0000, 0x365e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x365f, 0x3660, 0x0000, 0x0000, 0x3661, 0x0000, 0x0000, 0x3662,
+ 0x3663, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3664, 0x3665, 0x0000, 0x3666, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3667, 0x0000, 0x0000, 0x0000,
+ 0x3668, 0x0000, 0x0000, 0x0000, 0x3669, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x366a, 0x366b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x366c, 0x0000, 0x0000, 0x0000, 0x366d, 0x0000, 0x0000, 0x0000,
+ 0x366e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x366f, 0x3670, 0x0000, 0x3671, 0x0000, 0x3672, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3673, 0x3674, 0x0000, 0x0000,
+ 0x3675, 0x0000, 0x0000, 0x0000, 0x3676, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3677, 0x3678, 0x0000, 0x3679,
+ 0x367a, 0x367b, 0x367c, 0x0000, 0x0000, 0x0000, 0x367d, 0x367e,
+ 0x3721, 0x3722, 0x0000, 0x0000, 0x3723, 0x0000, 0x0000, 0x0000,
+ 0x3724, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3725, 0x3726, 0x0000, 0x3727, 0x3728, 0x3729, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x372a, 0x372b, 0x0000, 0x0000,
+ 0x372c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x372d,
+ 0x0000, 0x372e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x372f, 0x3730, 0x0000, 0x0000,
+ 0x3731, 0x0000, 0x0000, 0x0000, 0x3732, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3733, 0x3734, 0x0000, 0x3735
+};
+
+static unsigned short ksc5601_from_unicode_b8[] = {
+ 0x3736, 0x3737, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3738,
+ 0x3739, 0x373a, 0x0000, 0x0000, 0x373b, 0x0000, 0x0000, 0x0000,
+ 0x373c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x373d, 0x373e, 0x0000, 0x373f, 0x0000, 0x3740, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3741, 0x3742, 0x0000, 0x0000,
+ 0x3743, 0x0000, 0x0000, 0x0000, 0x3744, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3745, 0x3746, 0x0000, 0x3747,
+ 0x3748, 0x3749, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x374a, 0x0000, 0x0000, 0x0000, 0x374b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x374c, 0x0000, 0x374d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x374e, 0x374f, 0x0000, 0x0000,
+ 0x3750, 0x0000, 0x0000, 0x0000, 0x3751, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3752, 0x3753, 0x0000, 0x3754,
+ 0x0000, 0x3755, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3756, 0x0000, 0x0000, 0x0000, 0x3757, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3758, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3759, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x375a, 0x0000, 0x0000, 0x0000, 0x375b, 0x0000, 0x0000, 0x0000,
+ 0x375c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x375d, 0x375e, 0x0000, 0x375f, 0x0000, 0x3760, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3761, 0x0000, 0x0000, 0x0000,
+ 0x3762, 0x0000, 0x0000, 0x0000, 0x3763, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3764, 0x0000, 0x3765,
+ 0x0000, 0x3766, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3767, 0x3768, 0x0000, 0x0000, 0x3769, 0x0000, 0x0000, 0x0000,
+ 0x376a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x376b, 0x376c, 0x0000, 0x376d, 0x0000, 0x376e, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_b9[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x376f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3770, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3771, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3772, 0x3773, 0x0000, 0x0000,
+ 0x3774, 0x0000, 0x0000, 0x0000, 0x3775, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3776, 0x0000, 0x0000, 0x3777,
+ 0x0000, 0x3778, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3779, 0x377a, 0x0000, 0x0000, 0x377b, 0x0000, 0x0000, 0x0000,
+ 0x377c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x377d, 0x377e, 0x0000, 0x3821, 0x0000, 0x3822, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3823, 0x3824, 0x0000, 0x0000,
+ 0x3825, 0x0000, 0x0000, 0x0000, 0x3826, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3827, 0x3828, 0x0000, 0x3829,
+ 0x0000, 0x382a, 0x382b, 0x0000, 0x0000, 0x382c, 0x382d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x382e, 0x382f, 0x0000, 0x0000,
+ 0x3830, 0x0000, 0x0000, 0x0000, 0x3831, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3832, 0x3833, 0x0000, 0x3834,
+ 0x0000, 0x3835, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3836, 0x3837, 0x0000, 0x0000, 0x3838, 0x0000, 0x3839, 0x383a,
+ 0x383b, 0x383c, 0x383d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x383e, 0x383f, 0x0000, 0x3840, 0x0000, 0x3841, 0x3842, 0x0000,
+ 0x0000, 0x3843, 0x0000, 0x3844, 0x3845, 0x3846, 0x0000, 0x0000,
+ 0x3847, 0x0000, 0x0000, 0x0000, 0x3848, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3849, 0x384a, 0x0000, 0x384b,
+ 0x384c, 0x384d, 0x384e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_ba[] = {
+ 0x384f, 0x3850, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3851, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3852, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3853, 0x3854, 0x0000, 0x0000, 0x3855, 0x0000, 0x0000, 0x0000,
+ 0x3856, 0x0000, 0x3857, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3858, 0x3859, 0x0000, 0x385a, 0x0000, 0x385b, 0x385c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x385d, 0x385e, 0x385f, 0x0000, 0x0000,
+ 0x3860, 0x0000, 0x0000, 0x0000, 0x3861, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3862, 0x3863, 0x0000, 0x3864,
+ 0x3865, 0x3866, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3867, 0x3868, 0x0000, 0x0000, 0x3869, 0x0000, 0x0000, 0x0000,
+ 0x386a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x386b, 0x386c, 0x386d, 0x0000, 0x386e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x386f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3870, 0x3871, 0x0000, 0x3872, 0x3873, 0x0000, 0x0000, 0x0000,
+ 0x3874, 0x0000, 0x3875, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3876, 0x3877, 0x0000, 0x3878, 0x0000, 0x3879, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x387a, 0x0000, 0x0000, 0x0000,
+ 0x387b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x387c, 0x387d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x387e, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_bb[] = {
+ 0x3921, 0x0000, 0x0000, 0x0000, 0x3922, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3923, 0x0000, 0x3924,
+ 0x0000, 0x3925, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3926, 0x0000, 0x0000, 0x0000, 0x3927, 0x0000, 0x0000, 0x0000,
+ 0x3928, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3929, 0x0000, 0x392a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x392b, 0x392c, 0x392d, 0x0000,
+ 0x392e, 0x0000, 0x0000, 0x392f, 0x3930, 0x3931, 0x3932, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3933, 0x3934, 0x0000, 0x3935,
+ 0x0000, 0x3936, 0x0000, 0x0000, 0x0000, 0x3937, 0x0000, 0x3938,
+ 0x3939, 0x0000, 0x0000, 0x0000, 0x393a, 0x0000, 0x0000, 0x0000,
+ 0x393b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x393c, 0x0000, 0x393d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x393e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x393f, 0x0000, 0x0000, 0x0000, 0x3940, 0x0000, 0x0000, 0x0000,
+ 0x3941, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3942, 0x0000, 0x0000, 0x0000,
+ 0x3943, 0x0000, 0x0000, 0x0000, 0x3944, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3945, 0x0000, 0x0000, 0x3946,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3947, 0x0000, 0x0000, 0x0000, 0x3948, 0x0000, 0x0000, 0x0000,
+ 0x3949, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x394a, 0x0000, 0x0000, 0x394b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x394c, 0x394d, 0x0000, 0x0000, 0x394e, 0x0000, 0x0000, 0x394f
+};
+
+static unsigned short ksc5601_from_unicode_bc[] = {
+ 0x3950, 0x0000, 0x3951, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3952, 0x3953, 0x0000, 0x3954, 0x3955, 0x3956, 0x0000, 0x3957,
+ 0x0000, 0x3958, 0x0000, 0x0000, 0x3959, 0x395a, 0x395b, 0x395c,
+ 0x395d, 0x0000, 0x0000, 0x395e, 0x395f, 0x3960, 0x3961, 0x3962,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3963, 0x3964, 0x0000, 0x3965,
+ 0x0000, 0x3966, 0x0000, 0x0000, 0x0000, 0x3967, 0x0000, 0x0000,
+ 0x3968, 0x3969, 0x0000, 0x0000, 0x396a, 0x0000, 0x0000, 0x0000,
+ 0x396b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x396c, 0x396d, 0x0000, 0x396e, 0x396f, 0x3970, 0x0000, 0x0000,
+ 0x0000, 0x3971, 0x0000, 0x0000, 0x3972, 0x3973, 0x0000, 0x0000,
+ 0x3974, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3975, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3976, 0x3977, 0x0000, 0x0000,
+ 0x3978, 0x0000, 0x0000, 0x3979, 0x397a, 0x0000, 0x397b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x397c, 0x397d, 0x0000, 0x397e,
+ 0x0000, 0x3a21, 0x3a22, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3a23, 0x3a24, 0x0000, 0x0000, 0x3a25, 0x0000, 0x0000, 0x3a26,
+ 0x3a27, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3a28, 0x3a29, 0x0000, 0x3a2a, 0x3a2b, 0x3a2c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3a2d, 0x3a2e, 0x0000, 0x0000,
+ 0x3a2f, 0x0000, 0x0000, 0x0000, 0x3a30, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3a31, 0x0000, 0x3a32,
+ 0x3a33, 0x3a34, 0x0000, 0x0000, 0x0000, 0x3a35, 0x0000, 0x0000,
+ 0x3a36, 0x0000, 0x0000, 0x0000, 0x3a37, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3a38, 0x3a39, 0x3a3a, 0x0000,
+ 0x3a3b, 0x0000, 0x0000, 0x0000, 0x3a3c, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_bd[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3a3d, 0x3a3e, 0x0000, 0x3a3f,
+ 0x0000, 0x3a40, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3a41, 0x0000, 0x0000, 0x0000, 0x3a42, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3a43, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3a44, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3a45, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3a46, 0x3a47, 0x0000, 0x0000, 0x3a48, 0x0000, 0x0000, 0x0000,
+ 0x3a49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3a4a, 0x3a4b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3a4c, 0x0000, 0x0000, 0x0000,
+ 0x3a4d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3a4e, 0x3a4f, 0x0000, 0x0000, 0x3a50, 0x0000, 0x0000, 0x3a51,
+ 0x3a52, 0x3a53, 0x3a54, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3a55, 0x3a56, 0x0000, 0x3a57, 0x0000, 0x3a58, 0x0000, 0x0000,
+ 0x0000, 0x3a59, 0x3a5a, 0x0000, 0x3a5b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3a5c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3a5d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3a5e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3a5f, 0x3a60, 0x0000, 0x0000,
+ 0x3a61, 0x0000, 0x0000, 0x0000, 0x3a62, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3a63, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3a64, 0x0000, 0x0000, 0x0000, 0x3a65, 0x0000, 0x0000, 0x0000,
+ 0x3a66, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_be[] = {
+ 0x3a67, 0x0000, 0x0000, 0x3a68, 0x0000, 0x3a69, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3a6a, 0x3a6b, 0x0000, 0x0000,
+ 0x3a6c, 0x0000, 0x0000, 0x0000, 0x3a6d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3a6e, 0x3a6f, 0x0000, 0x3a70,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3a71, 0x3a72, 0x0000, 0x0000,
+ 0x3a73, 0x0000, 0x0000, 0x0000, 0x3a74, 0x0000, 0x3a75, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3a76, 0x3a77, 0x0000, 0x3a78,
+ 0x0000, 0x3a79, 0x3a7a, 0x3a7b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3a7c, 0x3a7d, 0x0000, 0x0000, 0x3a7e, 0x0000, 0x0000, 0x0000,
+ 0x3b21, 0x0000, 0x3b22, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3b23, 0x3b24, 0x0000, 0x3b25, 0x3b26, 0x3b27, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3b28, 0x3b29, 0x3b2a, 0x0000, 0x0000,
+ 0x3b2b, 0x0000, 0x0000, 0x0000, 0x3b2c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3b2d, 0x3b2e, 0x0000, 0x3b2f,
+ 0x3b30, 0x3b31, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3b32, 0x3b33, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3b34, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3b35, 0x3b36, 0x0000, 0x0000, 0x3b37, 0x0000, 0x0000, 0x3b38,
+ 0x3b39, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3b3a, 0x0000, 0x0000, 0x3b3b, 0x3b3c, 0x3b3d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3b3e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_bf[] = {
+ 0x0000, 0x3b3f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3b40, 0x3b41, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3b42, 0x3b43, 0x0000, 0x3b44, 0x3b45, 0x3b46, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3b47, 0x3b48, 0x0000, 0x0000, 0x3b49, 0x0000, 0x0000, 0x0000,
+ 0x3b4a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3b4b, 0x3b4c, 0x0000, 0x0000, 0x0000, 0x3b4d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3b4e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3b4f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3b50, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3b51, 0x3b52, 0x0000, 0x0000,
+ 0x3b53, 0x0000, 0x0000, 0x0000, 0x3b54, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3b55, 0x0000, 0x0000, 0x3b56,
+ 0x0000, 0x3b57, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_c0[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3b58, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3b59, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3b5a, 0x0000, 0x0000, 0x0000, 0x3b5b, 0x0000, 0x0000, 0x0000,
+ 0x3b5c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3b5d, 0x3b5e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3b5f, 0x3b60, 0x0000, 0x0000, 0x3b61, 0x0000, 0x0000, 0x0000,
+ 0x3b62, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3b63, 0x3b64, 0x0000, 0x3b65, 0x0000, 0x3b66, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3b67, 0x3b68, 0x0000, 0x3b69,
+ 0x3b6a, 0x0000, 0x0000, 0x3b6b, 0x3b6c, 0x3b6d, 0x3b6e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3b6f, 0x3b70, 0x0000, 0x3b71,
+ 0x3b72, 0x3b73, 0x0000, 0x0000, 0x0000, 0x3b74, 0x0000, 0x0000,
+ 0x3b75, 0x3b76, 0x0000, 0x0000, 0x3b77, 0x0000, 0x0000, 0x0000,
+ 0x3b78, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3b79, 0x3b7a, 0x0000, 0x3b7b, 0x3b7c, 0x3b7d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3b7e, 0x3c21, 0x0000, 0x0000,
+ 0x3c22, 0x0000, 0x0000, 0x0000, 0x3c23, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3c24, 0x3c25, 0x0000, 0x3c26,
+ 0x0000, 0x3c27, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_c1[] = {
+ 0x3c28, 0x0000, 0x0000, 0x0000, 0x3c29, 0x0000, 0x0000, 0x0000,
+ 0x3c2a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3c2b, 0x0000, 0x0000, 0x0000, 0x0000, 0x3c2c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3c2d, 0x3c2e, 0x3c2f, 0x3c30,
+ 0x3c31, 0x0000, 0x0000, 0x3c32, 0x3c33, 0x0000, 0x3c34, 0x3c35,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3c36, 0x3c37, 0x0000, 0x3c38,
+ 0x3c39, 0x3c3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x3c3b, 0x0000,
+ 0x3c3c, 0x3c3d, 0x0000, 0x0000, 0x3c3e, 0x0000, 0x0000, 0x0000,
+ 0x3c3f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3c40, 0x3c41, 0x0000, 0x3c42, 0x3c43, 0x3c44, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3c45, 0x3c46, 0x0000, 0x0000,
+ 0x3c47, 0x0000, 0x0000, 0x0000, 0x3c48, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3c49, 0x3c4a, 0x0000, 0x3c4b,
+ 0x3c4c, 0x3c4d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3c4e, 0x0000, 0x0000, 0x0000, 0x3c4f, 0x0000, 0x0000, 0x0000,
+ 0x3c50, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3c51, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3c52, 0x3c53, 0x3c54, 0x0000,
+ 0x3c55, 0x0000, 0x0000, 0x0000, 0x3c56, 0x0000, 0x3c57, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3c58, 0x3c59, 0x0000, 0x3c5a,
+ 0x0000, 0x3c5b, 0x0000, 0x0000, 0x0000, 0x3c5c, 0x0000, 0x0000,
+ 0x3c5d, 0x3c5e, 0x0000, 0x0000, 0x3c5f, 0x0000, 0x0000, 0x0000,
+ 0x3c60, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3c61, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3c62, 0x0000, 0x0000, 0x0000,
+ 0x3c63, 0x0000, 0x0000, 0x0000, 0x3c64, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3c65, 0x0000, 0x0000, 0x3c66,
+ 0x3c67, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3c68, 0x0000, 0x0000, 0x0000, 0x3c69, 0x0000, 0x0000, 0x0000,
+ 0x3c6a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3c6b, 0x3c6c, 0x0000, 0x3c6d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3c6e, 0x3c6f, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_c2[] = {
+ 0x3c70, 0x0000, 0x0000, 0x0000, 0x3c71, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3c72, 0x3c73, 0x0000, 0x3c74,
+ 0x0000, 0x3c75, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3c76, 0x3c77, 0x0000, 0x0000, 0x3c78, 0x0000, 0x0000, 0x3c79,
+ 0x3c7a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3c7b, 0x3c7c, 0x0000, 0x3c7d, 0x0000, 0x3c7e, 0x0000, 0x3d21,
+ 0x0000, 0x3d22, 0x3d23, 0x0000, 0x3d24, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d25, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d26, 0x3d27, 0x0000, 0x0000, 0x3d28, 0x0000, 0x0000, 0x0000,
+ 0x3d29, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d2a, 0x0000, 0x0000, 0x0000, 0x0000, 0x3d2b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3d2c, 0x3d2d, 0x0000, 0x0000,
+ 0x3d2e, 0x0000, 0x0000, 0x0000, 0x3d2f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3d30, 0x3d31, 0x0000, 0x3d32,
+ 0x0000, 0x3d33, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d34, 0x3d35, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d36, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d37, 0x0000, 0x0000, 0x3d38, 0x0000, 0x3d39, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3d3a, 0x3d3b, 0x0000, 0x0000,
+ 0x3d3c, 0x0000, 0x0000, 0x0000, 0x3d3d, 0x3d3e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3d3f, 0x3d40, 0x0000, 0x3d41,
+ 0x0000, 0x3d42, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3d43, 0x3d44, 0x0000, 0x0000,
+ 0x3d45, 0x0000, 0x0000, 0x3d46, 0x3d47, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3d48, 0x3d49, 0x3d4a, 0x0000, 0x3d4b,
+ 0x0000, 0x3d4c, 0x0000, 0x0000, 0x0000, 0x0000, 0x3d4d, 0x0000,
+ 0x3d4e, 0x3d4f, 0x0000, 0x3d50, 0x3d51, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_c3[] = {
+ 0x3d52, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d53, 0x3d54, 0x0000, 0x0000, 0x3d55, 0x3d56, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3d57, 0x3d58, 0x3d59, 0x0000, 0x0000,
+ 0x3d5a, 0x0000, 0x0000, 0x0000, 0x3d5b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3d5c, 0x3d5d, 0x0000, 0x0000,
+ 0x3d5e, 0x3d5f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3d60, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d61, 0x3d62, 0x0000, 0x0000, 0x3d63, 0x0000, 0x0000, 0x0000,
+ 0x3d64, 0x0000, 0x3d65, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d66, 0x3d67, 0x0000, 0x0000, 0x3d68, 0x3d69, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3d6a, 0x0000, 0x0000, 0x0000,
+ 0x3d6b, 0x0000, 0x0000, 0x0000, 0x3d6c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d6d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d6e, 0x3d6f, 0x0000, 0x0000, 0x3d70, 0x0000, 0x0000, 0x3d71,
+ 0x3d72, 0x0000, 0x3d73, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d74, 0x3d75, 0x0000, 0x0000, 0x0000, 0x3d76, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3d77, 0x3d78, 0x0000, 0x0000,
+ 0x3d79, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_c4[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d7a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d7b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3d7c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3d7d, 0x0000, 0x0000, 0x0000,
+ 0x3d7e, 0x0000, 0x0000, 0x0000, 0x3e21, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3e22, 0x3e23, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3e24, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3e25, 0x3e26, 0x0000, 0x0000,
+ 0x3e27, 0x0000, 0x0000, 0x0000, 0x3e28, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3e29, 0x3e2a, 0x0000, 0x0000,
+ 0x0000, 0x3e2b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3e2c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3e2d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3e2e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3e2f, 0x0000, 0x0000, 0x0000, 0x3e30, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3e31, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3e32, 0x3e33, 0x0000, 0x0000, 0x3e34, 0x0000, 0x0000, 0x0000,
+ 0x3e35, 0x0000, 0x3e36, 0x0000, 0x0000, 0x0000, 0x0000, 0x3e37
+};
+
+static unsigned short ksc5601_from_unicode_c5[] = {
+ 0x3e38, 0x3e39, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3e3a, 0x0000, 0x0000, 0x0000,
+ 0x3e3b, 0x0000, 0x0000, 0x0000, 0x3e3c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3e3d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3e3e, 0x3e3f, 0x0000, 0x0000, 0x3e40, 0x0000, 0x0000, 0x0000,
+ 0x3e41, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3e42, 0x3e43, 0x0000, 0x3e44, 0x0000, 0x3e45, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3e46, 0x3e47, 0x0000, 0x0000,
+ 0x3e48, 0x3e49, 0x3e4a, 0x0000, 0x3e4b, 0x3e4c, 0x3e4d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3e4e, 0x3e4f, 0x3e50, 0x0000, 0x3e51,
+ 0x3e52, 0x3e53, 0x0000, 0x0000, 0x0000, 0x3e54, 0x3e55, 0x0000,
+ 0x3e56, 0x3e57, 0x0000, 0x0000, 0x3e58, 0x0000, 0x0000, 0x0000,
+ 0x3e59, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3e5a, 0x3e5b, 0x0000, 0x3e5c, 0x3e5d, 0x3e5e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3e5f, 0x3e60, 0x0000, 0x0000,
+ 0x3e61, 0x0000, 0x0000, 0x0000, 0x3e62, 0x0000, 0x0000, 0x3e63,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3e64, 0x3e65, 0x0000, 0x3e66,
+ 0x0000, 0x3e67, 0x0000, 0x0000, 0x0000, 0x3e68, 0x0000, 0x3e69,
+ 0x3e6a, 0x0000, 0x0000, 0x0000, 0x3e6b, 0x0000, 0x0000, 0x0000,
+ 0x3e6c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3e6d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3e6e, 0x3e6f, 0x0000, 0x0000,
+ 0x3e70, 0x3e71, 0x0000, 0x3e72, 0x3e73, 0x3e74, 0x3e75, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3e76, 0x3e77, 0x3e78, 0x3e79,
+ 0x3e7a, 0x3e7b, 0x3e7c, 0x0000, 0x3e7d, 0x0000, 0x3e7e, 0x0000,
+ 0x3f21, 0x3f22, 0x0000, 0x0000, 0x3f23, 0x0000, 0x0000, 0x0000,
+ 0x3f24, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3f25, 0x3f26, 0x0000, 0x3f27, 0x0000, 0x3f28, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3f29, 0x3f2a, 0x3f2b, 0x0000,
+ 0x3f2c, 0x0000, 0x0000, 0x0000, 0x3f2d, 0x0000, 0x3f2e, 0x3f2f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3f30, 0x3f31, 0x3f32, 0x3f33
+};
+
+static unsigned short ksc5601_from_unicode_c6[] = {
+ 0x3f34, 0x3f35, 0x0000, 0x0000, 0x0000, 0x3f36, 0x3f37, 0x3f38,
+ 0x3f39, 0x0000, 0x0000, 0x0000, 0x3f3a, 0x0000, 0x0000, 0x0000,
+ 0x3f3b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3f3c, 0x3f3d, 0x0000, 0x3f3e, 0x3f3f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3f40, 0x3f41, 0x0000, 0x0000,
+ 0x3f42, 0x0000, 0x0000, 0x0000, 0x3f43, 0x3f44, 0x3f45, 0x0000,
+ 0x3f46, 0x0000, 0x0000, 0x3f47, 0x3f48, 0x3f49, 0x0000, 0x3f4a,
+ 0x0000, 0x3f4b, 0x0000, 0x3f4c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3f4d, 0x3f4e, 0x0000, 0x0000, 0x3f4f, 0x0000, 0x0000, 0x0000,
+ 0x3f50, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3f51, 0x3f52, 0x0000, 0x3f53, 0x3f54, 0x3f55, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3f56, 0x3f57, 0x0000, 0x0000,
+ 0x3f58, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3f59, 0x0000, 0x0000, 0x3f5a,
+ 0x0000, 0x3f5b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3f5c, 0x3f5d, 0x0000, 0x0000, 0x3f5e, 0x0000, 0x0000, 0x0000,
+ 0x3f5f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3f60, 0x3f61, 0x0000, 0x3f62, 0x0000, 0x3f63, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3f64, 0x3f65, 0x0000, 0x0000,
+ 0x3f66, 0x0000, 0x0000, 0x0000, 0x3f67, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3f68, 0x3f69, 0x0000, 0x3f6a,
+ 0x0000, 0x3f6b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3f6c, 0x3f6d, 0x0000, 0x0000, 0x3f6e, 0x0000, 0x0000, 0x0000,
+ 0x3f6f, 0x3f70, 0x3f71, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3f72, 0x3f73, 0x0000, 0x3f74, 0x0000, 0x3f75, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3f76, 0x3f77, 0x0000, 0x0000,
+ 0x3f78, 0x0000, 0x0000, 0x0000, 0x3f79, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3f7a, 0x3f7b, 0x0000, 0x0000,
+ 0x3f7c, 0x3f7d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3f7e, 0x4021, 0x0000, 0x0000, 0x4022, 0x0000, 0x0000, 0x0000,
+ 0x4023, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4024, 0x4025, 0x0000, 0x0000, 0x0000, 0x4026, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_c7[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4027, 0x4028, 0x0000, 0x0000,
+ 0x4029, 0x0000, 0x0000, 0x0000, 0x402a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x402b, 0x402c, 0x0000, 0x402d,
+ 0x0000, 0x402e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x402f, 0x4030, 0x0000, 0x0000, 0x4031, 0x0000, 0x0000, 0x0000,
+ 0x4032, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4033, 0x4034, 0x0000, 0x4035, 0x0000, 0x4036, 0x0000, 0x4037,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4038, 0x4039, 0x0000, 0x0000,
+ 0x403a, 0x0000, 0x0000, 0x0000, 0x403b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x403c, 0x0000, 0x403d, 0x403e, 0x0000, 0x403f,
+ 0x0000, 0x4040, 0x4041, 0x4042, 0x4043, 0x4044, 0x4045, 0x4046,
+ 0x4047, 0x0000, 0x0000, 0x0000, 0x4048, 0x0000, 0x0000, 0x0000,
+ 0x4049, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x404a, 0x0000, 0x0000, 0x404b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x404c, 0x404d, 0x0000, 0x0000,
+ 0x404e, 0x0000, 0x0000, 0x0000, 0x404f, 0x4050, 0x4051, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4052, 0x4053, 0x4054, 0x0000, 0x4055,
+ 0x4056, 0x4057, 0x4058, 0x0000, 0x0000, 0x0000, 0x4059, 0x0000,
+ 0x405a, 0x405b, 0x0000, 0x0000, 0x405c, 0x0000, 0x405d, 0x405e,
+ 0x405f, 0x0000, 0x4060, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4061, 0x4062, 0x0000, 0x4063, 0x4064, 0x4065, 0x4066, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4067, 0x4068, 0x0000, 0x0000,
+ 0x4069, 0x0000, 0x0000, 0x0000, 0x406a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x406b, 0x406c, 0x0000, 0x406d,
+ 0x406e, 0x406f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4070, 0x4071, 0x0000, 0x0000, 0x4072, 0x0000, 0x4073, 0x0000,
+ 0x4074, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4075, 0x0000, 0x0000, 0x0000, 0x0000, 0x4076, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4077, 0x0000, 0x0000, 0x0000,
+ 0x4078, 0x0000, 0x0000, 0x0000, 0x4079, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_c8[] = {
+ 0x407a, 0x407b, 0x0000, 0x0000, 0x407c, 0x0000, 0x0000, 0x0000,
+ 0x407d, 0x0000, 0x407e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4121, 0x4122, 0x0000, 0x4123, 0x0000, 0x4124, 0x4125, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4126, 0x4127, 0x0000, 0x0000,
+ 0x4128, 0x0000, 0x0000, 0x0000, 0x4129, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x412a, 0x412b, 0x0000, 0x412c,
+ 0x0000, 0x412d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x412e, 0x0000, 0x0000, 0x0000, 0x412f, 0x0000, 0x0000, 0x0000,
+ 0x4130, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4131, 0x4132, 0x0000, 0x0000, 0x4133, 0x4134, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4135, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4136, 0x4137, 0x0000, 0x0000, 0x4138, 0x0000, 0x0000, 0x0000,
+ 0x4139, 0x0000, 0x413a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x413b, 0x413c, 0x0000, 0x413d, 0x0000, 0x413e, 0x413f, 0x4140,
+ 0x0000, 0x0000, 0x0000, 0x4141, 0x4142, 0x4143, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4144, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4145, 0x0000, 0x4146,
+ 0x0000, 0x4147, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4148, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4149, 0x414a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x414b, 0x0000, 0x0000, 0x0000,
+ 0x414c, 0x0000, 0x0000, 0x0000, 0x414d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x414e, 0x414f, 0x0000, 0x4150,
+ 0x0000, 0x4151, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4152, 0x4153, 0x0000, 0x0000, 0x4154, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4155, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4156, 0x4157, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_c9[] = {
+ 0x4158, 0x0000, 0x0000, 0x0000, 0x4159, 0x415a, 0x415b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x415c, 0x415d, 0x0000, 0x415e,
+ 0x0000, 0x415f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4160, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4161, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4162, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4163, 0x4164, 0x0000, 0x0000, 0x4165, 0x0000, 0x0000, 0x0000,
+ 0x4166, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4167, 0x4168, 0x0000, 0x4169, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x416a, 0x0000, 0x0000, 0x0000,
+ 0x416b, 0x0000, 0x0000, 0x0000, 0x416c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x416d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x416e, 0x416f, 0x0000, 0x0000, 0x4170, 0x0000, 0x0000, 0x0000,
+ 0x4171, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4172, 0x4173, 0x0000, 0x4174, 0x0000, 0x4175, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4176, 0x4177, 0x0000, 0x0000, 0x4178, 0x0000, 0x0000, 0x4179,
+ 0x417a, 0x0000, 0x417b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x417c, 0x417d, 0x0000, 0x417e, 0x0000, 0x4221, 0x4222, 0x0000,
+ 0x0000, 0x4223, 0x4224, 0x0000, 0x4225, 0x4226, 0x0000, 0x0000,
+ 0x4227, 0x0000, 0x4228, 0x0000, 0x4229, 0x0000, 0x0000, 0x422a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x422b, 0x422c, 0x0000, 0x422d,
+ 0x422e, 0x422f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4230, 0x4231, 0x0000, 0x0000, 0x4232, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_ca[] = {
+ 0x4233, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4234, 0x4235, 0x0000, 0x4236, 0x4237, 0x4238, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4239, 0x0000, 0x0000, 0x0000,
+ 0x423a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x423b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x423c, 0x423d, 0x0000, 0x0000,
+ 0x423e, 0x0000, 0x0000, 0x0000, 0x423f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4240, 0x4241, 0x0000, 0x4242,
+ 0x4243, 0x4244, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4245, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4246, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4247, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4248, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4249, 0x424a, 0x0000, 0x0000,
+ 0x424b, 0x0000, 0x0000, 0x0000, 0x424c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x424d, 0x424e, 0x0000, 0x424f,
+ 0x0000, 0x4250, 0x0000, 0x4251, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4252, 0x4253, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4254, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4255, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4256, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_cb[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4257, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4258, 0x0000, 0x0000, 0x0000, 0x4259, 0x0000, 0x0000, 0x0000,
+ 0x425a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x425b, 0x425c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x425d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x425e, 0x425f, 0x0000, 0x0000, 0x4260, 0x0000, 0x0000, 0x0000,
+ 0x4261, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4262, 0x4263, 0x0000, 0x0000, 0x0000, 0x4264, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4265, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4266, 0x4267, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4268, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4269, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x426a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x426b, 0x0000, 0x0000, 0x426c,
+ 0x0000, 0x426d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_cc[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x426e, 0x426f, 0x0000, 0x0000,
+ 0x4270, 0x0000, 0x0000, 0x0000, 0x4271, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4272, 0x4273, 0x0000, 0x0000,
+ 0x0000, 0x4274, 0x4275, 0x0000, 0x0000, 0x0000, 0x0000, 0x4276,
+ 0x4277, 0x4278, 0x0000, 0x0000, 0x4279, 0x0000, 0x427a, 0x0000,
+ 0x427b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x427c, 0x427d, 0x0000, 0x427e, 0x4321, 0x4322, 0x4323, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4324, 0x4325, 0x0000, 0x0000,
+ 0x4326, 0x0000, 0x0000, 0x0000, 0x4327, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4328, 0x4329, 0x0000, 0x432a,
+ 0x432b, 0x432c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x432d, 0x0000, 0x0000, 0x0000, 0x432e, 0x0000, 0x432f, 0x0000,
+ 0x4330, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4331, 0x0000, 0x0000, 0x0000, 0x0000, 0x4332, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4333, 0x4334, 0x0000, 0x0000, 0x4335, 0x0000, 0x0000, 0x0000,
+ 0x4336, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4337, 0x4338, 0x0000, 0x4339, 0x433a, 0x433b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x433c, 0x433d, 0x0000, 0x0000,
+ 0x433e, 0x0000, 0x0000, 0x0000, 0x433f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4340, 0x4341, 0x0000, 0x4342,
+ 0x0000, 0x4343, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4344, 0x0000, 0x0000, 0x0000, 0x4345, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4346, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4347, 0x0000, 0x0000, 0x0000,
+ 0x4348, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_cd[] = {
+ 0x0000, 0x4349, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x434a, 0x434b, 0x0000, 0x0000, 0x434c, 0x0000, 0x0000, 0x0000,
+ 0x434d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x434e, 0x434f, 0x0000, 0x4350, 0x0000, 0x4351, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4352, 0x0000, 0x0000, 0x0000,
+ 0x4353, 0x0000, 0x0000, 0x0000, 0x4354, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4355, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4356, 0x0000, 0x0000, 0x0000,
+ 0x4357, 0x0000, 0x0000, 0x0000, 0x4358, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4359, 0x435a, 0x0000, 0x435b,
+ 0x0000, 0x435c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x435d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x435e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x435f, 0x4360, 0x0000, 0x0000,
+ 0x4361, 0x0000, 0x0000, 0x0000, 0x4362, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4363, 0x4364, 0x0000, 0x4365,
+ 0x0000, 0x4366, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4367, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4368, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4369, 0x0000, 0x0000, 0x0000,
+ 0x436a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x436b, 0x0000, 0x0000, 0x0000, 0x436c, 0x0000, 0x0000, 0x0000,
+ 0x436d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x436e, 0x436f, 0x0000, 0x4370, 0x0000, 0x4371, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_ce[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4372, 0x0000, 0x0000, 0x0000,
+ 0x4373, 0x0000, 0x0000, 0x0000, 0x4374, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4375, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4376, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4377, 0x4378, 0x0000, 0x0000, 0x4379, 0x0000, 0x0000, 0x0000,
+ 0x437a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x437b, 0x437c, 0x0000, 0x437d, 0x0000, 0x437e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4421, 0x4422, 0x0000, 0x0000, 0x4423, 0x0000, 0x0000, 0x4424,
+ 0x4425, 0x4426, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4427, 0x4428, 0x0000, 0x4429, 0x0000, 0x442a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x442b, 0x442c, 0x0000, 0x0000,
+ 0x442d, 0x0000, 0x0000, 0x0000, 0x442e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x442f, 0x4430, 0x0000, 0x4431,
+ 0x0000, 0x4432, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4433, 0x4434, 0x0000, 0x0000, 0x4435, 0x0000, 0x0000, 0x0000,
+ 0x4436, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4437, 0x4438, 0x0000, 0x4439, 0x443a, 0x443b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x443c, 0x443d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x443e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x443f, 0x4440, 0x0000, 0x0000,
+ 0x4441, 0x0000, 0x0000, 0x4442, 0x4443, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4444, 0x4445, 0x0000, 0x4446,
+ 0x4447, 0x4448, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_cf[] = {
+ 0x4449, 0x444a, 0x0000, 0x0000, 0x444b, 0x0000, 0x0000, 0x0000,
+ 0x444c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x444d, 0x444e, 0x0000, 0x444f, 0x0000, 0x4450, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4451, 0x0000, 0x0000, 0x0000,
+ 0x4452, 0x0000, 0x0000, 0x0000, 0x4453, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4454, 0x4455, 0x0000, 0x4456,
+ 0x4457, 0x4458, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4459, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x445a, 0x445b, 0x0000, 0x0000,
+ 0x445c, 0x0000, 0x0000, 0x0000, 0x445d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x445e, 0x445f, 0x0000, 0x4460,
+ 0x0000, 0x4461, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4462, 0x4463, 0x0000, 0x0000, 0x4464, 0x0000, 0x0000, 0x0000,
+ 0x4465, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4466, 0x0000, 0x0000, 0x0000, 0x0000, 0x4467, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4468, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4469, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x446a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x446b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x446c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x446d, 0x446e, 0x0000, 0x0000, 0x446f, 0x0000, 0x0000, 0x0000,
+ 0x4470, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4471, 0x4472, 0x0000, 0x4473, 0x0000, 0x4474, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4475, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_d0[] = {
+ 0x4476, 0x0000, 0x0000, 0x0000, 0x4477, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4478, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4479, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x447a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x447b, 0x447c, 0x0000, 0x0000,
+ 0x447d, 0x0000, 0x0000, 0x0000, 0x447e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4521, 0x4522, 0x0000, 0x4523,
+ 0x0000, 0x4524, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4525, 0x0000, 0x0000, 0x0000, 0x4526, 0x0000, 0x0000, 0x0000,
+ 0x4527, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4528, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4529, 0x452a, 0x0000, 0x0000,
+ 0x452b, 0x0000, 0x0000, 0x0000, 0x452c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x452d, 0x452e, 0x0000, 0x0000,
+ 0x0000, 0x452f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4530, 0x4531, 0x0000, 0x0000,
+ 0x4532, 0x0000, 0x0000, 0x0000, 0x4533, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4534, 0x4535, 0x0000, 0x4536,
+ 0x0000, 0x4537, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4538, 0x4539, 0x0000, 0x0000, 0x453a, 0x0000, 0x0000, 0x0000,
+ 0x453b, 0x453c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x453d, 0x453e, 0x0000, 0x453f, 0x4540, 0x4541, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4542, 0x4543, 0x0000, 0x0000,
+ 0x4544, 0x0000, 0x0000, 0x0000, 0x4545, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4546, 0x4547, 0x0000, 0x4548,
+ 0x4549, 0x454a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x454b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_d1[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x454c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x454d, 0x454e, 0x0000, 0x0000, 0x454f, 0x0000, 0x0000, 0x0000,
+ 0x4550, 0x0000, 0x4551, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4552, 0x4553, 0x0000, 0x4554, 0x4555, 0x4556, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4557, 0x4558, 0x0000, 0x0000,
+ 0x4559, 0x0000, 0x0000, 0x0000, 0x455a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x455b, 0x455c, 0x0000, 0x455d,
+ 0x0000, 0x455e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x455f, 0x0000, 0x0000, 0x0000, 0x4560, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4561, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4562, 0x0000, 0x0000, 0x0000,
+ 0x4563, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4564, 0x4565, 0x0000, 0x0000, 0x4566, 0x0000, 0x0000, 0x0000,
+ 0x4567, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4568, 0x4569, 0x0000, 0x456a, 0x0000, 0x456b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x456c, 0x0000, 0x456d, 0x0000, 0x0000, 0x0000,
+ 0x456e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x456f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4570, 0x0000, 0x0000, 0x0000,
+ 0x4571, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_d2[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4572,
+ 0x0000, 0x4573, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4574, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4575, 0x4576, 0x0000, 0x0000,
+ 0x4577, 0x0000, 0x0000, 0x0000, 0x4578, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4579, 0x457a, 0x0000, 0x457b,
+ 0x0000, 0x457c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x457d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x457e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4621, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4622, 0x4623, 0x0000, 0x0000, 0x4624, 0x0000, 0x0000, 0x0000,
+ 0x4625, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4626, 0x4627, 0x0000, 0x0000, 0x0000, 0x4628, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4629, 0x0000, 0x0000, 0x0000,
+ 0x462a, 0x0000, 0x0000, 0x0000, 0x462b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x462c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x462d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x462e, 0x462f, 0x0000, 0x0000, 0x4630, 0x0000, 0x0000, 0x4631,
+ 0x4632, 0x0000, 0x4633, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4634, 0x4635, 0x0000, 0x4636, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4637, 0x0000, 0x0000, 0x0000,
+ 0x4638, 0x0000, 0x0000, 0x0000, 0x4639, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x463a, 0x463b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x463c, 0x463d, 0x0000, 0x0000, 0x463e, 0x0000, 0x0000, 0x0000,
+ 0x463f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_d3[] = {
+ 0x4640, 0x4641, 0x0000, 0x4642, 0x0000, 0x4643, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4644, 0x4645, 0x4646, 0x0000,
+ 0x4647, 0x0000, 0x0000, 0x0000, 0x4648, 0x0000, 0x4649, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x464a, 0x464b, 0x0000, 0x464c,
+ 0x464d, 0x464e, 0x0000, 0x0000, 0x0000, 0x464f, 0x0000, 0x0000,
+ 0x4650, 0x4651, 0x0000, 0x0000, 0x4652, 0x0000, 0x0000, 0x0000,
+ 0x4653, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4654, 0x4655, 0x0000, 0x4656, 0x4657, 0x4658, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4659, 0x465a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x465b, 0x465c, 0x0000, 0x0000,
+ 0x465d, 0x0000, 0x0000, 0x0000, 0x465e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x465f, 0x4660, 0x0000, 0x4661,
+ 0x4662, 0x4663, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4664, 0x4665, 0x0000, 0x0000, 0x4666, 0x0000, 0x0000, 0x0000,
+ 0x4667, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4668, 0x4669, 0x0000, 0x466a, 0x0000, 0x466b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x466c, 0x0000, 0x0000, 0x0000,
+ 0x466d, 0x0000, 0x0000, 0x0000, 0x466e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x466f, 0x4670, 0x0000, 0x0000,
+ 0x4671, 0x4672, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4673, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4674, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4675, 0x0000, 0x4676, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4677, 0x4678, 0x0000, 0x0000,
+ 0x4679, 0x0000, 0x0000, 0x0000, 0x467a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x467b, 0x467c, 0x0000, 0x467d
+};
+
+static unsigned short ksc5601_from_unicode_d4[] = {
+ 0x0000, 0x467e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4721, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4722, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4723, 0x0000, 0x0000, 0x0000, 0x4724, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4725, 0x0000, 0x0000, 0x0000,
+ 0x4726, 0x0000, 0x0000, 0x0000, 0x4727, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4728, 0x0000, 0x4729,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x472a, 0x472b, 0x0000, 0x0000, 0x472c, 0x0000, 0x0000, 0x472d,
+ 0x472e, 0x0000, 0x472f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4730, 0x4731, 0x0000, 0x4732, 0x0000, 0x4733, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4734, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4735, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4736, 0x0000, 0x0000, 0x0000,
+ 0x4737, 0x0000, 0x0000, 0x0000, 0x4738, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4739, 0x0000, 0x0000, 0x473a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x473b, 0x0000, 0x0000, 0x0000, 0x473c, 0x0000, 0x0000, 0x0000,
+ 0x473d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x473e, 0x0000, 0x0000, 0x473f, 0x0000, 0x4740, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_d5[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4741, 0x0000, 0x0000, 0x0000,
+ 0x4742, 0x0000, 0x0000, 0x0000, 0x4743, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4744, 0x4745, 0x0000, 0x4746,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4747, 0x4748, 0x0000, 0x0000,
+ 0x4749, 0x0000, 0x0000, 0x0000, 0x474a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x474b, 0x474c, 0x0000, 0x474d,
+ 0x0000, 0x474e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x474f, 0x4750, 0x0000, 0x0000, 0x4751, 0x0000, 0x0000, 0x0000,
+ 0x4752, 0x0000, 0x0000, 0x0000, 0x0000, 0x4753, 0x0000, 0x0000,
+ 0x4754, 0x4755, 0x0000, 0x4756, 0x0000, 0x4757, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4758, 0x4759, 0x0000, 0x0000,
+ 0x475a, 0x0000, 0x0000, 0x0000, 0x475b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x475c, 0x475d, 0x0000, 0x475e,
+ 0x475f, 0x4760, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4761, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4762, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4763, 0x4764, 0x0000, 0x0000, 0x4765, 0x0000, 0x0000, 0x0000,
+ 0x4766, 0x0000, 0x4767, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4768, 0x4769, 0x0000, 0x476a, 0x0000, 0x476b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x476c, 0x476d, 0x0000, 0x0000,
+ 0x476e, 0x0000, 0x0000, 0x0000, 0x476f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4770, 0x4771, 0x0000, 0x4772,
+ 0x0000, 0x4773, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_d6[] = {
+ 0x4774, 0x4775, 0x0000, 0x0000, 0x4776, 0x0000, 0x0000, 0x0000,
+ 0x4777, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4778, 0x4779, 0x0000, 0x477a, 0x477b, 0x477c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x477d, 0x0000, 0x0000, 0x0000,
+ 0x477e, 0x0000, 0x0000, 0x0000, 0x4821, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4822, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4823, 0x4824, 0x0000, 0x0000, 0x4825, 0x0000, 0x0000, 0x0000,
+ 0x4826, 0x0000, 0x0000, 0x0000, 0x0000, 0x4827, 0x0000, 0x0000,
+ 0x4828, 0x4829, 0x0000, 0x482a, 0x0000, 0x482b, 0x0000, 0x0000,
+ 0x0000, 0x482c, 0x0000, 0x0000, 0x482d, 0x482e, 0x0000, 0x0000,
+ 0x482f, 0x0000, 0x0000, 0x0000, 0x4830, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4831,
+ 0x0000, 0x4832, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4833, 0x4834, 0x0000, 0x0000, 0x4835, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4836, 0x0000, 0x4837, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4838, 0x4839, 0x0000, 0x0000,
+ 0x483a, 0x0000, 0x0000, 0x0000, 0x483b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x483c, 0x0000, 0x483d,
+ 0x0000, 0x483e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x483f, 0x0000, 0x0000, 0x0000, 0x4840, 0x0000, 0x0000, 0x0000,
+ 0x4841, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4842, 0x0000, 0x4843, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4844, 0x4845, 0x0000, 0x0000,
+ 0x4846, 0x0000, 0x0000, 0x0000, 0x4847, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4848, 0x0000, 0x0000, 0x4849, 0x0000, 0x0000, 0x484a,
+ 0x0000, 0x484b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x484c, 0x0000, 0x0000, 0x0000, 0x484d, 0x0000, 0x0000, 0x0000,
+ 0x484e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x484f, 0x0000, 0x0000, 0x0000, 0x0000, 0x4850, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4851, 0x4852, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_d7[] = {
+ 0x4853, 0x0000, 0x0000, 0x0000, 0x4854, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4855, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4856, 0x4857, 0x0000, 0x0000, 0x4858, 0x0000, 0x0000, 0x0000,
+ 0x4859, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x485a, 0x485b, 0x0000, 0x485c, 0x0000, 0x485d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x485e, 0x485f, 0x0000, 0x0000,
+ 0x4860, 0x0000, 0x0000, 0x0000, 0x4861, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4862, 0x0000, 0x0000, 0x4863,
+ 0x0000, 0x4864, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4865, 0x4866, 0x0000, 0x0000, 0x4867, 0x0000, 0x4868, 0x4869,
+ 0x486a, 0x486b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x486c, 0x486d, 0x0000, 0x486e, 0x0000, 0x486f, 0x0000, 0x0000,
+ 0x0000, 0x4870, 0x0000, 0x0000, 0x4871, 0x0000, 0x0000, 0x0000,
+ 0x4872, 0x0000, 0x0000, 0x0000, 0x4873, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4874, 0x4875, 0x0000, 0x0000,
+ 0x0000, 0x4876, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4877, 0x4878, 0x0000, 0x0000, 0x4879, 0x0000, 0x0000, 0x0000,
+ 0x487a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x487b, 0x487c, 0x0000, 0x487d, 0x0000, 0x487e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short ksc5601_from_unicode_ff[] = {
+ 0x0000, 0x2321, 0x2322, 0x2323, 0x2324, 0x2325, 0x2326, 0x2327,
+ 0x2328, 0x2329, 0x232a, 0x232b, 0x232c, 0x232d, 0x232e, 0x232f,
+ 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337,
+ 0x2338, 0x2339, 0x233a, 0x233b, 0x233c, 0x233d, 0x233e, 0x233f,
+ 0x2340, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347,
+ 0x2348, 0x2349, 0x234a, 0x234b, 0x234c, 0x234d, 0x234e, 0x234f,
+ 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357,
+ 0x2358, 0x2359, 0x235a, 0x235b, 0x212c, 0x235d, 0x235e, 0x235f,
+ 0x2360, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367,
+ 0x2368, 0x2369, 0x236a, 0x236b, 0x236c, 0x236d, 0x236e, 0x236f,
+ 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377,
+ 0x2378, 0x2379, 0x237a, 0x237b, 0x237c, 0x237d, 0x212d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x214b, 0x214c, 0x217e, 0x237e, 0x0000, 0x214d, 0x235c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short * const ksc5601_from_unicode_[] = {
+ ksc5601_from_unicode_0,
+ ksc5601_from_unicode_1,
+ ksc5601_from_unicode_2,
+ ksc5601_from_unicode_3,
+ ksc5601_from_unicode_4,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ ksc5601_from_unicode_20,
+ ksc5601_from_unicode_21,
+ ksc5601_from_unicode_22,
+ ksc5601_from_unicode_23,
+ ksc5601_from_unicode_24,
+ ksc5601_from_unicode_25,
+ ksc5601_from_unicode_26,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ ksc5601_from_unicode_30,
+ ksc5601_from_unicode_31,
+ ksc5601_from_unicode_32,
+ ksc5601_from_unicode_33,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ ksc5601_from_unicode_4e,
+ ksc5601_from_unicode_4f,
+ ksc5601_from_unicode_50,
+ ksc5601_from_unicode_51,
+ ksc5601_from_unicode_52,
+ ksc5601_from_unicode_53,
+ ksc5601_from_unicode_54,
+ ksc5601_from_unicode_55,
+ ksc5601_from_unicode_56,
+ ksc5601_from_unicode_57,
+ ksc5601_from_unicode_58,
+ ksc5601_from_unicode_59,
+ ksc5601_from_unicode_5a,
+ ksc5601_from_unicode_5b,
+ ksc5601_from_unicode_5c,
+ ksc5601_from_unicode_5d,
+ ksc5601_from_unicode_5e,
+ ksc5601_from_unicode_5f,
+ ksc5601_from_unicode_60,
+ ksc5601_from_unicode_61,
+ ksc5601_from_unicode_62,
+ ksc5601_from_unicode_63,
+ ksc5601_from_unicode_64,
+ ksc5601_from_unicode_65,
+ ksc5601_from_unicode_66,
+ ksc5601_from_unicode_67,
+ ksc5601_from_unicode_68,
+ ksc5601_from_unicode_69,
+ ksc5601_from_unicode_6a,
+ ksc5601_from_unicode_6b,
+ ksc5601_from_unicode_6c,
+ ksc5601_from_unicode_6d,
+ ksc5601_from_unicode_6e,
+ ksc5601_from_unicode_6f,
+ ksc5601_from_unicode_70,
+ ksc5601_from_unicode_71,
+ ksc5601_from_unicode_72,
+ ksc5601_from_unicode_73,
+ ksc5601_from_unicode_74,
+ ksc5601_from_unicode_75,
+ ksc5601_from_unicode_76,
+ ksc5601_from_unicode_77,
+ ksc5601_from_unicode_78,
+ ksc5601_from_unicode_79,
+ ksc5601_from_unicode_7a,
+ ksc5601_from_unicode_7b,
+ ksc5601_from_unicode_7c,
+ ksc5601_from_unicode_7d,
+ ksc5601_from_unicode_7e,
+ ksc5601_from_unicode_7f,
+ ksc5601_from_unicode_80,
+ ksc5601_from_unicode_81,
+ ksc5601_from_unicode_82,
+ ksc5601_from_unicode_83,
+ ksc5601_from_unicode_84,
+ ksc5601_from_unicode_85,
+ ksc5601_from_unicode_86,
+ ksc5601_from_unicode_87,
+ ksc5601_from_unicode_88,
+ ksc5601_from_unicode_89,
+ ksc5601_from_unicode_8a,
+ ksc5601_from_unicode_8b,
+ ksc5601_from_unicode_8c,
+ ksc5601_from_unicode_8d,
+ ksc5601_from_unicode_8e,
+ ksc5601_from_unicode_8f,
+ ksc5601_from_unicode_90,
+ ksc5601_from_unicode_91,
+ ksc5601_from_unicode_92,
+ ksc5601_from_unicode_93,
+ ksc5601_from_unicode_94,
+ ksc5601_from_unicode_95,
+ ksc5601_from_unicode_96,
+ ksc5601_from_unicode_97,
+ ksc5601_from_unicode_98,
+ ksc5601_from_unicode_99,
+ ksc5601_from_unicode_9a,
+ ksc5601_from_unicode_9b,
+ ksc5601_from_unicode_9c,
+ ksc5601_from_unicode_9d,
+ ksc5601_from_unicode_9e,
+ ksc5601_from_unicode_9f,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ ksc5601_from_unicode_ac,
+ ksc5601_from_unicode_ad,
+ ksc5601_from_unicode_ae,
+ ksc5601_from_unicode_af,
+ ksc5601_from_unicode_b0,
+ ksc5601_from_unicode_b1,
+ ksc5601_from_unicode_b2,
+ ksc5601_from_unicode_b3,
+ ksc5601_from_unicode_b4,
+ ksc5601_from_unicode_b5,
+ ksc5601_from_unicode_b6,
+ ksc5601_from_unicode_b7,
+ ksc5601_from_unicode_b8,
+ ksc5601_from_unicode_b9,
+ ksc5601_from_unicode_ba,
+ ksc5601_from_unicode_bb,
+ ksc5601_from_unicode_bc,
+ ksc5601_from_unicode_bd,
+ ksc5601_from_unicode_be,
+ ksc5601_from_unicode_bf,
+ ksc5601_from_unicode_c0,
+ ksc5601_from_unicode_c1,
+ ksc5601_from_unicode_c2,
+ ksc5601_from_unicode_c3,
+ ksc5601_from_unicode_c4,
+ ksc5601_from_unicode_c5,
+ ksc5601_from_unicode_c6,
+ ksc5601_from_unicode_c7,
+ ksc5601_from_unicode_c8,
+ ksc5601_from_unicode_c9,
+ ksc5601_from_unicode_ca,
+ ksc5601_from_unicode_cb,
+ ksc5601_from_unicode_cc,
+ ksc5601_from_unicode_cd,
+ ksc5601_from_unicode_ce,
+ ksc5601_from_unicode_cf,
+ ksc5601_from_unicode_d0,
+ ksc5601_from_unicode_d1,
+ ksc5601_from_unicode_d2,
+ ksc5601_from_unicode_d3,
+ ksc5601_from_unicode_d4,
+ ksc5601_from_unicode_d5,
+ ksc5601_from_unicode_d6,
+ ksc5601_from_unicode_d7,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ ksc5601_from_unicode_ff
+};
+
+struct charmap2 ksc5601_from_unicode = { 0, 255, (unsigned short **) ksc5601_from_unicode_, (unichar_t *) unicode_from_ksc5601 };
+
+#endif
+
+const unichar_t unicode_from_johab[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136,
+ 0x3137, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
+ 0x3140, 0x3141, 0x0000, 0x3142, 0x3144, 0x3145, 0x3146, 0x3147,
+ 0x3148, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000, 0x0000,
+ 0x0000, 0x314f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3150, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3151, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3152, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3153, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3154, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3155, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3156, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3157, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3158, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3159, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x315a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x315b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x315c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x315d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x315e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x315f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3160, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3161, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3162, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3163, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xac00, 0xac01, 0xac02, 0xac03, 0xac04, 0xac05, 0xac06,
+ 0xac07, 0xac08, 0xac09, 0xac0a, 0xac0b, 0xac0c, 0xac0d, 0xac0e,
+ 0xac0f, 0xac10, 0x0000, 0xac11, 0xac12, 0xac13, 0xac14, 0xac15,
+ 0xac16, 0xac17, 0xac18, 0xac19, 0xac1a, 0xac1b, 0x0000, 0x0000,
+ 0x0000, 0xac1c, 0xac1d, 0xac1e, 0xac1f, 0xac20, 0xac21, 0xac22,
+ 0xac23, 0xac24, 0xac25, 0xac26, 0xac27, 0xac28, 0xac29, 0xac2a,
+ 0xac2b, 0xac2c, 0x0000, 0xac2d, 0xac2e, 0xac2f, 0xac30, 0xac31,
+ 0xac32, 0xac33, 0xac34, 0xac35, 0xac36, 0xac37, 0x0000, 0x0000,
+ 0x0000, 0xac38, 0xac39, 0xac3a, 0xac3b, 0xac3c, 0xac3d, 0xac3e,
+ 0xac3f, 0xac40, 0xac41, 0xac42, 0xac43, 0xac44, 0xac45, 0xac46,
+ 0xac47, 0xac48, 0x0000, 0xac49, 0xac4a, 0xac4b, 0xac4c, 0xac4d,
+ 0xac4e, 0xac4f, 0xac50, 0xac51, 0xac52, 0xac53, 0x0000, 0x0000,
+ 0x0000, 0xac54, 0xac55, 0xac56, 0xac57, 0xac58, 0xac59, 0xac5a,
+ 0xac5b, 0xac5c, 0xac5d, 0xac5e, 0xac5f, 0xac60, 0xac61, 0xac62,
+ 0xac63, 0xac64, 0x0000, 0xac65, 0xac66, 0xac67, 0xac68, 0xac69,
+ 0xac6a, 0xac6b, 0xac6c, 0xac6d, 0xac6e, 0xac6f, 0x0000, 0x0000,
+ 0x0000, 0xac70, 0xac71, 0xac72, 0xac73, 0xac74, 0xac75, 0xac76,
+ 0xac77, 0xac78, 0xac79, 0xac7a, 0xac7b, 0xac7c, 0xac7d, 0xac7e,
+ 0xac7f, 0xac80, 0x0000, 0xac81, 0xac82, 0xac83, 0xac84, 0xac85,
+ 0xac86, 0xac87, 0xac88, 0xac89, 0xac8a, 0xac8b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xac8c, 0xac8d, 0xac8e, 0xac8f, 0xac90, 0xac91, 0xac92,
+ 0xac93, 0xac94, 0xac95, 0xac96, 0xac97, 0xac98, 0xac99, 0xac9a,
+ 0xac9b, 0xac9c, 0x0000, 0xac9d, 0xac9e, 0xac9f, 0xaca0, 0xaca1,
+ 0xaca2, 0xaca3, 0xaca4, 0xaca5, 0xaca6, 0xaca7, 0x0000, 0x0000,
+ 0x0000, 0xaca8, 0xaca9, 0xacaa, 0xacab, 0xacac, 0xacad, 0xacae,
+ 0xacaf, 0xacb0, 0xacb1, 0xacb2, 0xacb3, 0xacb4, 0xacb5, 0xacb6,
+ 0xacb7, 0xacb8, 0x0000, 0xacb9, 0xacba, 0xacbb, 0xacbc, 0xacbd,
+ 0xacbe, 0xacbf, 0xacc0, 0xacc1, 0xacc2, 0xacc3, 0x0000, 0x0000,
+ 0x0000, 0xacc4, 0xacc5, 0xacc6, 0xacc7, 0xacc8, 0xacc9, 0xacca,
+ 0xaccb, 0xaccc, 0xaccd, 0xacce, 0xaccf, 0xacd0, 0xacd1, 0xacd2,
+ 0xacd3, 0xacd4, 0x0000, 0xacd5, 0xacd6, 0xacd7, 0xacd8, 0xacd9,
+ 0xacda, 0xacdb, 0xacdc, 0xacdd, 0xacde, 0xacdf, 0x0000, 0x0000,
+ 0x0000, 0xace0, 0xace1, 0xace2, 0xace3, 0xace4, 0xace5, 0xace6,
+ 0xace7, 0xace8, 0xace9, 0xacea, 0xaceb, 0xacec, 0xaced, 0xacee,
+ 0xacef, 0xacf0, 0x0000, 0xacf1, 0xacf2, 0xacf3, 0xacf4, 0xacf5,
+ 0xacf6, 0xacf7, 0xacf8, 0xacf9, 0xacfa, 0xacfb, 0x0000, 0x0000,
+ 0x0000, 0xacfc, 0xacfd, 0xacfe, 0xacff, 0xad00, 0xad01, 0xad02,
+ 0xad03, 0xad04, 0xad05, 0xad06, 0xad07, 0xad08, 0xad09, 0xad0a,
+ 0xad0b, 0xad0c, 0x0000, 0xad0d, 0xad0e, 0xad0f, 0xad10, 0xad11,
+ 0xad12, 0xad13, 0xad14, 0xad15, 0xad16, 0xad17, 0x0000, 0x0000,
+ 0x0000, 0xad18, 0xad19, 0xad1a, 0xad1b, 0xad1c, 0xad1d, 0xad1e,
+ 0xad1f, 0xad20, 0xad21, 0xad22, 0xad23, 0xad24, 0xad25, 0xad26,
+ 0xad27, 0xad28, 0x0000, 0xad29, 0xad2a, 0xad2b, 0xad2c, 0xad2d,
+ 0xad2e, 0xad2f, 0xad30, 0xad31, 0xad32, 0xad33, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xad34, 0xad35, 0xad36, 0xad37, 0xad38, 0xad39, 0xad3a,
+ 0xad3b, 0xad3c, 0xad3d, 0xad3e, 0xad3f, 0xad40, 0xad41, 0xad42,
+ 0xad43, 0xad44, 0x0000, 0xad45, 0xad46, 0xad47, 0xad48, 0xad49,
+ 0xad4a, 0xad4b, 0xad4c, 0xad4d, 0xad4e, 0xad4f, 0x0000, 0x0000,
+ 0x0000, 0xad50, 0xad51, 0xad52, 0xad53, 0xad54, 0xad55, 0xad56,
+ 0xad57, 0xad58, 0xad59, 0xad5a, 0xad5b, 0xad5c, 0xad5d, 0xad5e,
+ 0xad5f, 0xad60, 0x0000, 0xad61, 0xad62, 0xad63, 0xad64, 0xad65,
+ 0xad66, 0xad67, 0xad68, 0xad69, 0xad6a, 0xad6b, 0x0000, 0x0000,
+ 0x0000, 0xad6c, 0xad6d, 0xad6e, 0xad6f, 0xad70, 0xad71, 0xad72,
+ 0xad73, 0xad74, 0xad75, 0xad76, 0xad77, 0xad78, 0xad79, 0xad7a,
+ 0xad7b, 0xad7c, 0x0000, 0xad7d, 0xad7e, 0xad7f, 0xad80, 0xad81,
+ 0xad82, 0xad83, 0xad84, 0xad85, 0xad86, 0xad87, 0x0000, 0x0000,
+ 0x0000, 0xad88, 0xad89, 0xad8a, 0xad8b, 0xad8c, 0xad8d, 0xad8e,
+ 0xad8f, 0xad90, 0xad91, 0xad92, 0xad93, 0xad94, 0xad95, 0xad96,
+ 0xad97, 0xad98, 0x0000, 0xad99, 0xad9a, 0xad9b, 0xad9c, 0xad9d,
+ 0xad9e, 0xad9f, 0xada0, 0xada1, 0xada2, 0xada3, 0x0000, 0x0000,
+ 0x0000, 0xada4, 0xada5, 0xada6, 0xada7, 0xada8, 0xada9, 0xadaa,
+ 0xadab, 0xadac, 0xadad, 0xadae, 0xadaf, 0xadb0, 0xadb1, 0xadb2,
+ 0xadb3, 0xadb4, 0x0000, 0xadb5, 0xadb6, 0xadb7, 0xadb8, 0xadb9,
+ 0xadba, 0xadbb, 0xadbc, 0xadbd, 0xadbe, 0xadbf, 0x0000, 0x0000,
+ 0x0000, 0xadc0, 0xadc1, 0xadc2, 0xadc3, 0xadc4, 0xadc5, 0xadc6,
+ 0xadc7, 0xadc8, 0xadc9, 0xadca, 0xadcb, 0xadcc, 0xadcd, 0xadce,
+ 0xadcf, 0xadd0, 0x0000, 0xadd1, 0xadd2, 0xadd3, 0xadd4, 0xadd5,
+ 0xadd6, 0xadd7, 0xadd8, 0xadd9, 0xadda, 0xaddb, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xaddc, 0xaddd, 0xadde, 0xaddf, 0xade0, 0xade1, 0xade2,
+ 0xade3, 0xade4, 0xade5, 0xade6, 0xade7, 0xade8, 0xade9, 0xadea,
+ 0xadeb, 0xadec, 0x0000, 0xaded, 0xadee, 0xadef, 0xadf0, 0xadf1,
+ 0xadf2, 0xadf3, 0xadf4, 0xadf5, 0xadf6, 0xadf7, 0x0000, 0x0000,
+ 0x0000, 0xadf8, 0xadf9, 0xadfa, 0xadfb, 0xadfc, 0xadfd, 0xadfe,
+ 0xadff, 0xae00, 0xae01, 0xae02, 0xae03, 0xae04, 0xae05, 0xae06,
+ 0xae07, 0xae08, 0x0000, 0xae09, 0xae0a, 0xae0b, 0xae0c, 0xae0d,
+ 0xae0e, 0xae0f, 0xae10, 0xae11, 0xae12, 0xae13, 0x0000, 0x0000,
+ 0x0000, 0xae14, 0xae15, 0xae16, 0xae17, 0xae18, 0xae19, 0xae1a,
+ 0xae1b, 0xae1c, 0xae1d, 0xae1e, 0xae1f, 0xae20, 0xae21, 0xae22,
+ 0xae23, 0xae24, 0x0000, 0xae25, 0xae26, 0xae27, 0xae28, 0xae29,
+ 0xae2a, 0xae2b, 0xae2c, 0xae2d, 0xae2e, 0xae2f, 0x0000, 0x0000,
+ 0x0000, 0xae30, 0xae31, 0xae32, 0xae33, 0xae34, 0xae35, 0xae36,
+ 0xae37, 0xae38, 0xae39, 0xae3a, 0xae3b, 0xae3c, 0xae3d, 0xae3e,
+ 0xae3f, 0xae40, 0x0000, 0xae41, 0xae42, 0xae43, 0xae44, 0xae45,
+ 0xae46, 0xae47, 0xae48, 0xae49, 0xae4a, 0xae4b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xae4c, 0xae4d, 0xae4e, 0xae4f, 0xae50, 0xae51, 0xae52,
+ 0xae53, 0xae54, 0xae55, 0xae56, 0xae57, 0xae58, 0xae59, 0xae5a,
+ 0xae5b, 0xae5c, 0x0000, 0xae5d, 0xae5e, 0xae5f, 0xae60, 0xae61,
+ 0xae62, 0xae63, 0xae64, 0xae65, 0xae66, 0xae67, 0x0000, 0x0000,
+ 0x0000, 0xae68, 0xae69, 0xae6a, 0xae6b, 0xae6c, 0xae6d, 0xae6e,
+ 0xae6f, 0xae70, 0xae71, 0xae72, 0xae73, 0xae74, 0xae75, 0xae76,
+ 0xae77, 0xae78, 0x0000, 0xae79, 0xae7a, 0xae7b, 0xae7c, 0xae7d,
+ 0xae7e, 0xae7f, 0xae80, 0xae81, 0xae82, 0xae83, 0x0000, 0x0000,
+ 0x0000, 0xae84, 0xae85, 0xae86, 0xae87, 0xae88, 0xae89, 0xae8a,
+ 0xae8b, 0xae8c, 0xae8d, 0xae8e, 0xae8f, 0xae90, 0xae91, 0xae92,
+ 0xae93, 0xae94, 0x0000, 0xae95, 0xae96, 0xae97, 0xae98, 0xae99,
+ 0xae9a, 0xae9b, 0xae9c, 0xae9d, 0xae9e, 0xae9f, 0x0000, 0x0000,
+ 0x0000, 0xaea0, 0xaea1, 0xaea2, 0xaea3, 0xaea4, 0xaea5, 0xaea6,
+ 0xaea7, 0xaea8, 0xaea9, 0xaeaa, 0xaeab, 0xaeac, 0xaead, 0xaeae,
+ 0xaeaf, 0xaeb0, 0x0000, 0xaeb1, 0xaeb2, 0xaeb3, 0xaeb4, 0xaeb5,
+ 0xaeb6, 0xaeb7, 0xaeb8, 0xaeb9, 0xaeba, 0xaebb, 0x0000, 0x0000,
+ 0x0000, 0xaebc, 0xaebd, 0xaebe, 0xaebf, 0xaec0, 0xaec1, 0xaec2,
+ 0xaec3, 0xaec4, 0xaec5, 0xaec6, 0xaec7, 0xaec8, 0xaec9, 0xaeca,
+ 0xaecb, 0xaecc, 0x0000, 0xaecd, 0xaece, 0xaecf, 0xaed0, 0xaed1,
+ 0xaed2, 0xaed3, 0xaed4, 0xaed5, 0xaed6, 0xaed7, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xaed8, 0xaed9, 0xaeda, 0xaedb, 0xaedc, 0xaedd, 0xaede,
+ 0xaedf, 0xaee0, 0xaee1, 0xaee2, 0xaee3, 0xaee4, 0xaee5, 0xaee6,
+ 0xaee7, 0xaee8, 0x0000, 0xaee9, 0xaeea, 0xaeeb, 0xaeec, 0xaeed,
+ 0xaeee, 0xaeef, 0xaef0, 0xaef1, 0xaef2, 0xaef3, 0x0000, 0x0000,
+ 0x0000, 0xaef4, 0xaef5, 0xaef6, 0xaef7, 0xaef8, 0xaef9, 0xaefa,
+ 0xaefb, 0xaefc, 0xaefd, 0xaefe, 0xaeff, 0xaf00, 0xaf01, 0xaf02,
+ 0xaf03, 0xaf04, 0x0000, 0xaf05, 0xaf06, 0xaf07, 0xaf08, 0xaf09,
+ 0xaf0a, 0xaf0b, 0xaf0c, 0xaf0d, 0xaf0e, 0xaf0f, 0x0000, 0x0000,
+ 0x0000, 0xaf10, 0xaf11, 0xaf12, 0xaf13, 0xaf14, 0xaf15, 0xaf16,
+ 0xaf17, 0xaf18, 0xaf19, 0xaf1a, 0xaf1b, 0xaf1c, 0xaf1d, 0xaf1e,
+ 0xaf1f, 0xaf20, 0x0000, 0xaf21, 0xaf22, 0xaf23, 0xaf24, 0xaf25,
+ 0xaf26, 0xaf27, 0xaf28, 0xaf29, 0xaf2a, 0xaf2b, 0x0000, 0x0000,
+ 0x0000, 0xaf2c, 0xaf2d, 0xaf2e, 0xaf2f, 0xaf30, 0xaf31, 0xaf32,
+ 0xaf33, 0xaf34, 0xaf35, 0xaf36, 0xaf37, 0xaf38, 0xaf39, 0xaf3a,
+ 0xaf3b, 0xaf3c, 0x0000, 0xaf3d, 0xaf3e, 0xaf3f, 0xaf40, 0xaf41,
+ 0xaf42, 0xaf43, 0xaf44, 0xaf45, 0xaf46, 0xaf47, 0x0000, 0x0000,
+ 0x0000, 0xaf48, 0xaf49, 0xaf4a, 0xaf4b, 0xaf4c, 0xaf4d, 0xaf4e,
+ 0xaf4f, 0xaf50, 0xaf51, 0xaf52, 0xaf53, 0xaf54, 0xaf55, 0xaf56,
+ 0xaf57, 0xaf58, 0x0000, 0xaf59, 0xaf5a, 0xaf5b, 0xaf5c, 0xaf5d,
+ 0xaf5e, 0xaf5f, 0xaf60, 0xaf61, 0xaf62, 0xaf63, 0x0000, 0x0000,
+ 0x0000, 0xaf64, 0xaf65, 0xaf66, 0xaf67, 0xaf68, 0xaf69, 0xaf6a,
+ 0xaf6b, 0xaf6c, 0xaf6d, 0xaf6e, 0xaf6f, 0xaf70, 0xaf71, 0xaf72,
+ 0xaf73, 0xaf74, 0x0000, 0xaf75, 0xaf76, 0xaf77, 0xaf78, 0xaf79,
+ 0xaf7a, 0xaf7b, 0xaf7c, 0xaf7d, 0xaf7e, 0xaf7f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xaf80, 0xaf81, 0xaf82, 0xaf83, 0xaf84, 0xaf85, 0xaf86,
+ 0xaf87, 0xaf88, 0xaf89, 0xaf8a, 0xaf8b, 0xaf8c, 0xaf8d, 0xaf8e,
+ 0xaf8f, 0xaf90, 0x0000, 0xaf91, 0xaf92, 0xaf93, 0xaf94, 0xaf95,
+ 0xaf96, 0xaf97, 0xaf98, 0xaf99, 0xaf9a, 0xaf9b, 0x0000, 0x0000,
+ 0x0000, 0xaf9c, 0xaf9d, 0xaf9e, 0xaf9f, 0xafa0, 0xafa1, 0xafa2,
+ 0xafa3, 0xafa4, 0xafa5, 0xafa6, 0xafa7, 0xafa8, 0xafa9, 0xafaa,
+ 0xafab, 0xafac, 0x0000, 0xafad, 0xafae, 0xafaf, 0xafb0, 0xafb1,
+ 0xafb2, 0xafb3, 0xafb4, 0xafb5, 0xafb6, 0xafb7, 0x0000, 0x0000,
+ 0x0000, 0xafb8, 0xafb9, 0xafba, 0xafbb, 0xafbc, 0xafbd, 0xafbe,
+ 0xafbf, 0xafc0, 0xafc1, 0xafc2, 0xafc3, 0xafc4, 0xafc5, 0xafc6,
+ 0xafc7, 0xafc8, 0x0000, 0xafc9, 0xafca, 0xafcb, 0xafcc, 0xafcd,
+ 0xafce, 0xafcf, 0xafd0, 0xafd1, 0xafd2, 0xafd3, 0x0000, 0x0000,
+ 0x0000, 0xafd4, 0xafd5, 0xafd6, 0xafd7, 0xafd8, 0xafd9, 0xafda,
+ 0xafdb, 0xafdc, 0xafdd, 0xafde, 0xafdf, 0xafe0, 0xafe1, 0xafe2,
+ 0xafe3, 0xafe4, 0x0000, 0xafe5, 0xafe6, 0xafe7, 0xafe8, 0xafe9,
+ 0xafea, 0xafeb, 0xafec, 0xafed, 0xafee, 0xafef, 0x0000, 0x0000,
+ 0x0000, 0xaff0, 0xaff1, 0xaff2, 0xaff3, 0xaff4, 0xaff5, 0xaff6,
+ 0xaff7, 0xaff8, 0xaff9, 0xaffa, 0xaffb, 0xaffc, 0xaffd, 0xaffe,
+ 0xafff, 0xb000, 0x0000, 0xb001, 0xb002, 0xb003, 0xb004, 0xb005,
+ 0xb006, 0xb007, 0xb008, 0xb009, 0xb00a, 0xb00b, 0x0000, 0x0000,
+ 0x0000, 0xb00c, 0xb00d, 0xb00e, 0xb00f, 0xb010, 0xb011, 0xb012,
+ 0xb013, 0xb014, 0xb015, 0xb016, 0xb017, 0xb018, 0xb019, 0xb01a,
+ 0xb01b, 0xb01c, 0x0000, 0xb01d, 0xb01e, 0xb01f, 0xb020, 0xb021,
+ 0xb022, 0xb023, 0xb024, 0xb025, 0xb026, 0xb027, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb028, 0xb029, 0xb02a, 0xb02b, 0xb02c, 0xb02d, 0xb02e,
+ 0xb02f, 0xb030, 0xb031, 0xb032, 0xb033, 0xb034, 0xb035, 0xb036,
+ 0xb037, 0xb038, 0x0000, 0xb039, 0xb03a, 0xb03b, 0xb03c, 0xb03d,
+ 0xb03e, 0xb03f, 0xb040, 0xb041, 0xb042, 0xb043, 0x0000, 0x0000,
+ 0x0000, 0xb044, 0xb045, 0xb046, 0xb047, 0xb048, 0xb049, 0xb04a,
+ 0xb04b, 0xb04c, 0xb04d, 0xb04e, 0xb04f, 0xb050, 0xb051, 0xb052,
+ 0xb053, 0xb054, 0x0000, 0xb055, 0xb056, 0xb057, 0xb058, 0xb059,
+ 0xb05a, 0xb05b, 0xb05c, 0xb05d, 0xb05e, 0xb05f, 0x0000, 0x0000,
+ 0x0000, 0xb060, 0xb061, 0xb062, 0xb063, 0xb064, 0xb065, 0xb066,
+ 0xb067, 0xb068, 0xb069, 0xb06a, 0xb06b, 0xb06c, 0xb06d, 0xb06e,
+ 0xb06f, 0xb070, 0x0000, 0xb071, 0xb072, 0xb073, 0xb074, 0xb075,
+ 0xb076, 0xb077, 0xb078, 0xb079, 0xb07a, 0xb07b, 0x0000, 0x0000,
+ 0x0000, 0xb07c, 0xb07d, 0xb07e, 0xb07f, 0xb080, 0xb081, 0xb082,
+ 0xb083, 0xb084, 0xb085, 0xb086, 0xb087, 0xb088, 0xb089, 0xb08a,
+ 0xb08b, 0xb08c, 0x0000, 0xb08d, 0xb08e, 0xb08f, 0xb090, 0xb091,
+ 0xb092, 0xb093, 0xb094, 0xb095, 0xb096, 0xb097, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb098, 0xb099, 0xb09a, 0xb09b, 0xb09c, 0xb09d, 0xb09e,
+ 0xb09f, 0xb0a0, 0xb0a1, 0xb0a2, 0xb0a3, 0xb0a4, 0xb0a5, 0xb0a6,
+ 0xb0a7, 0xb0a8, 0x0000, 0xb0a9, 0xb0aa, 0xb0ab, 0xb0ac, 0xb0ad,
+ 0xb0ae, 0xb0af, 0xb0b0, 0xb0b1, 0xb0b2, 0xb0b3, 0x0000, 0x0000,
+ 0x0000, 0xb0b4, 0xb0b5, 0xb0b6, 0xb0b7, 0xb0b8, 0xb0b9, 0xb0ba,
+ 0xb0bb, 0xb0bc, 0xb0bd, 0xb0be, 0xb0bf, 0xb0c0, 0xb0c1, 0xb0c2,
+ 0xb0c3, 0xb0c4, 0x0000, 0xb0c5, 0xb0c6, 0xb0c7, 0xb0c8, 0xb0c9,
+ 0xb0ca, 0xb0cb, 0xb0cc, 0xb0cd, 0xb0ce, 0xb0cf, 0x0000, 0x0000,
+ 0x0000, 0xb0d0, 0xb0d1, 0xb0d2, 0xb0d3, 0xb0d4, 0xb0d5, 0xb0d6,
+ 0xb0d7, 0xb0d8, 0xb0d9, 0xb0da, 0xb0db, 0xb0dc, 0xb0dd, 0xb0de,
+ 0xb0df, 0xb0e0, 0x0000, 0xb0e1, 0xb0e2, 0xb0e3, 0xb0e4, 0xb0e5,
+ 0xb0e6, 0xb0e7, 0xb0e8, 0xb0e9, 0xb0ea, 0xb0eb, 0x0000, 0x0000,
+ 0x0000, 0xb0ec, 0xb0ed, 0xb0ee, 0xb0ef, 0xb0f0, 0xb0f1, 0xb0f2,
+ 0xb0f3, 0xb0f4, 0xb0f5, 0xb0f6, 0xb0f7, 0xb0f8, 0xb0f9, 0xb0fa,
+ 0xb0fb, 0xb0fc, 0x0000, 0xb0fd, 0xb0fe, 0xb0ff, 0xb100, 0xb101,
+ 0xb102, 0xb103, 0xb104, 0xb105, 0xb106, 0xb107, 0x0000, 0x0000,
+ 0x0000, 0xb108, 0xb109, 0xb10a, 0xb10b, 0xb10c, 0xb10d, 0xb10e,
+ 0xb10f, 0xb110, 0xb111, 0xb112, 0xb113, 0xb114, 0xb115, 0xb116,
+ 0xb117, 0xb118, 0x0000, 0xb119, 0xb11a, 0xb11b, 0xb11c, 0xb11d,
+ 0xb11e, 0xb11f, 0xb120, 0xb121, 0xb122, 0xb123, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb124, 0xb125, 0xb126, 0xb127, 0xb128, 0xb129, 0xb12a,
+ 0xb12b, 0xb12c, 0xb12d, 0xb12e, 0xb12f, 0xb130, 0xb131, 0xb132,
+ 0xb133, 0xb134, 0x0000, 0xb135, 0xb136, 0xb137, 0xb138, 0xb139,
+ 0xb13a, 0xb13b, 0xb13c, 0xb13d, 0xb13e, 0xb13f, 0x0000, 0x0000,
+ 0x0000, 0xb140, 0xb141, 0xb142, 0xb143, 0xb144, 0xb145, 0xb146,
+ 0xb147, 0xb148, 0xb149, 0xb14a, 0xb14b, 0xb14c, 0xb14d, 0xb14e,
+ 0xb14f, 0xb150, 0x0000, 0xb151, 0xb152, 0xb153, 0xb154, 0xb155,
+ 0xb156, 0xb157, 0xb158, 0xb159, 0xb15a, 0xb15b, 0x0000, 0x0000,
+ 0x0000, 0xb15c, 0xb15d, 0xb15e, 0xb15f, 0xb160, 0xb161, 0xb162,
+ 0xb163, 0xb164, 0xb165, 0xb166, 0xb167, 0xb168, 0xb169, 0xb16a,
+ 0xb16b, 0xb16c, 0x0000, 0xb16d, 0xb16e, 0xb16f, 0xb170, 0xb171,
+ 0xb172, 0xb173, 0xb174, 0xb175, 0xb176, 0xb177, 0x0000, 0x0000,
+ 0x0000, 0xb178, 0xb179, 0xb17a, 0xb17b, 0xb17c, 0xb17d, 0xb17e,
+ 0xb17f, 0xb180, 0xb181, 0xb182, 0xb183, 0xb184, 0xb185, 0xb186,
+ 0xb187, 0xb188, 0x0000, 0xb189, 0xb18a, 0xb18b, 0xb18c, 0xb18d,
+ 0xb18e, 0xb18f, 0xb190, 0xb191, 0xb192, 0xb193, 0x0000, 0x0000,
+ 0x0000, 0xb194, 0xb195, 0xb196, 0xb197, 0xb198, 0xb199, 0xb19a,
+ 0xb19b, 0xb19c, 0xb19d, 0xb19e, 0xb19f, 0xb1a0, 0xb1a1, 0xb1a2,
+ 0xb1a3, 0xb1a4, 0x0000, 0xb1a5, 0xb1a6, 0xb1a7, 0xb1a8, 0xb1a9,
+ 0xb1aa, 0xb1ab, 0xb1ac, 0xb1ad, 0xb1ae, 0xb1af, 0x0000, 0x0000,
+ 0x0000, 0xb1b0, 0xb1b1, 0xb1b2, 0xb1b3, 0xb1b4, 0xb1b5, 0xb1b6,
+ 0xb1b7, 0xb1b8, 0xb1b9, 0xb1ba, 0xb1bb, 0xb1bc, 0xb1bd, 0xb1be,
+ 0xb1bf, 0xb1c0, 0x0000, 0xb1c1, 0xb1c2, 0xb1c3, 0xb1c4, 0xb1c5,
+ 0xb1c6, 0xb1c7, 0xb1c8, 0xb1c9, 0xb1ca, 0xb1cb, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb1cc, 0xb1cd, 0xb1ce, 0xb1cf, 0xb1d0, 0xb1d1, 0xb1d2,
+ 0xb1d3, 0xb1d4, 0xb1d5, 0xb1d6, 0xb1d7, 0xb1d8, 0xb1d9, 0xb1da,
+ 0xb1db, 0xb1dc, 0x0000, 0xb1dd, 0xb1de, 0xb1df, 0xb1e0, 0xb1e1,
+ 0xb1e2, 0xb1e3, 0xb1e4, 0xb1e5, 0xb1e6, 0xb1e7, 0x0000, 0x0000,
+ 0x0000, 0xb1e8, 0xb1e9, 0xb1ea, 0xb1eb, 0xb1ec, 0xb1ed, 0xb1ee,
+ 0xb1ef, 0xb1f0, 0xb1f1, 0xb1f2, 0xb1f3, 0xb1f4, 0xb1f5, 0xb1f6,
+ 0xb1f7, 0xb1f8, 0x0000, 0xb1f9, 0xb1fa, 0xb1fb, 0xb1fc, 0xb1fd,
+ 0xb1fe, 0xb1ff, 0xb200, 0xb201, 0xb202, 0xb203, 0x0000, 0x0000,
+ 0x0000, 0xb204, 0xb205, 0xb206, 0xb207, 0xb208, 0xb209, 0xb20a,
+ 0xb20b, 0xb20c, 0xb20d, 0xb20e, 0xb20f, 0xb210, 0xb211, 0xb212,
+ 0xb213, 0xb214, 0x0000, 0xb215, 0xb216, 0xb217, 0xb218, 0xb219,
+ 0xb21a, 0xb21b, 0xb21c, 0xb21d, 0xb21e, 0xb21f, 0x0000, 0x0000,
+ 0x0000, 0xb220, 0xb221, 0xb222, 0xb223, 0xb224, 0xb225, 0xb226,
+ 0xb227, 0xb228, 0xb229, 0xb22a, 0xb22b, 0xb22c, 0xb22d, 0xb22e,
+ 0xb22f, 0xb230, 0x0000, 0xb231, 0xb232, 0xb233, 0xb234, 0xb235,
+ 0xb236, 0xb237, 0xb238, 0xb239, 0xb23a, 0xb23b, 0x0000, 0x0000,
+ 0x0000, 0xb23c, 0xb23d, 0xb23e, 0xb23f, 0xb240, 0xb241, 0xb242,
+ 0xb243, 0xb244, 0xb245, 0xb246, 0xb247, 0xb248, 0xb249, 0xb24a,
+ 0xb24b, 0xb24c, 0x0000, 0xb24d, 0xb24e, 0xb24f, 0xb250, 0xb251,
+ 0xb252, 0xb253, 0xb254, 0xb255, 0xb256, 0xb257, 0x0000, 0x0000,
+ 0x0000, 0xb258, 0xb259, 0xb25a, 0xb25b, 0xb25c, 0xb25d, 0xb25e,
+ 0xb25f, 0xb260, 0xb261, 0xb262, 0xb263, 0xb264, 0xb265, 0xb266,
+ 0xb267, 0xb268, 0x0000, 0xb269, 0xb26a, 0xb26b, 0xb26c, 0xb26d,
+ 0xb26e, 0xb26f, 0xb270, 0xb271, 0xb272, 0xb273, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb274, 0xb275, 0xb276, 0xb277, 0xb278, 0xb279, 0xb27a,
+ 0xb27b, 0xb27c, 0xb27d, 0xb27e, 0xb27f, 0xb280, 0xb281, 0xb282,
+ 0xb283, 0xb284, 0x0000, 0xb285, 0xb286, 0xb287, 0xb288, 0xb289,
+ 0xb28a, 0xb28b, 0xb28c, 0xb28d, 0xb28e, 0xb28f, 0x0000, 0x0000,
+ 0x0000, 0xb290, 0xb291, 0xb292, 0xb293, 0xb294, 0xb295, 0xb296,
+ 0xb297, 0xb298, 0xb299, 0xb29a, 0xb29b, 0xb29c, 0xb29d, 0xb29e,
+ 0xb29f, 0xb2a0, 0x0000, 0xb2a1, 0xb2a2, 0xb2a3, 0xb2a4, 0xb2a5,
+ 0xb2a6, 0xb2a7, 0xb2a8, 0xb2a9, 0xb2aa, 0xb2ab, 0x0000, 0x0000,
+ 0x0000, 0xb2ac, 0xb2ad, 0xb2ae, 0xb2af, 0xb2b0, 0xb2b1, 0xb2b2,
+ 0xb2b3, 0xb2b4, 0xb2b5, 0xb2b6, 0xb2b7, 0xb2b8, 0xb2b9, 0xb2ba,
+ 0xb2bb, 0xb2bc, 0x0000, 0xb2bd, 0xb2be, 0xb2bf, 0xb2c0, 0xb2c1,
+ 0xb2c2, 0xb2c3, 0xb2c4, 0xb2c5, 0xb2c6, 0xb2c7, 0x0000, 0x0000,
+ 0x0000, 0xb2c8, 0xb2c9, 0xb2ca, 0xb2cb, 0xb2cc, 0xb2cd, 0xb2ce,
+ 0xb2cf, 0xb2d0, 0xb2d1, 0xb2d2, 0xb2d3, 0xb2d4, 0xb2d5, 0xb2d6,
+ 0xb2d7, 0xb2d8, 0x0000, 0xb2d9, 0xb2da, 0xb2db, 0xb2dc, 0xb2dd,
+ 0xb2de, 0xb2df, 0xb2e0, 0xb2e1, 0xb2e2, 0xb2e3, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb2e4, 0xb2e5, 0xb2e6, 0xb2e7, 0xb2e8, 0xb2e9, 0xb2ea,
+ 0xb2eb, 0xb2ec, 0xb2ed, 0xb2ee, 0xb2ef, 0xb2f0, 0xb2f1, 0xb2f2,
+ 0xb2f3, 0xb2f4, 0x0000, 0xb2f5, 0xb2f6, 0xb2f7, 0xb2f8, 0xb2f9,
+ 0xb2fa, 0xb2fb, 0xb2fc, 0xb2fd, 0xb2fe, 0xb2ff, 0x0000, 0x0000,
+ 0x0000, 0xb300, 0xb301, 0xb302, 0xb303, 0xb304, 0xb305, 0xb306,
+ 0xb307, 0xb308, 0xb309, 0xb30a, 0xb30b, 0xb30c, 0xb30d, 0xb30e,
+ 0xb30f, 0xb310, 0x0000, 0xb311, 0xb312, 0xb313, 0xb314, 0xb315,
+ 0xb316, 0xb317, 0xb318, 0xb319, 0xb31a, 0xb31b, 0x0000, 0x0000,
+ 0x0000, 0xb31c, 0xb31d, 0xb31e, 0xb31f, 0xb320, 0xb321, 0xb322,
+ 0xb323, 0xb324, 0xb325, 0xb326, 0xb327, 0xb328, 0xb329, 0xb32a,
+ 0xb32b, 0xb32c, 0x0000, 0xb32d, 0xb32e, 0xb32f, 0xb330, 0xb331,
+ 0xb332, 0xb333, 0xb334, 0xb335, 0xb336, 0xb337, 0x0000, 0x0000,
+ 0x0000, 0xb338, 0xb339, 0xb33a, 0xb33b, 0xb33c, 0xb33d, 0xb33e,
+ 0xb33f, 0xb340, 0xb341, 0xb342, 0xb343, 0xb344, 0xb345, 0xb346,
+ 0xb347, 0xb348, 0x0000, 0xb349, 0xb34a, 0xb34b, 0xb34c, 0xb34d,
+ 0xb34e, 0xb34f, 0xb350, 0xb351, 0xb352, 0xb353, 0x0000, 0x0000,
+ 0x0000, 0xb354, 0xb355, 0xb356, 0xb357, 0xb358, 0xb359, 0xb35a,
+ 0xb35b, 0xb35c, 0xb35d, 0xb35e, 0xb35f, 0xb360, 0xb361, 0xb362,
+ 0xb363, 0xb364, 0x0000, 0xb365, 0xb366, 0xb367, 0xb368, 0xb369,
+ 0xb36a, 0xb36b, 0xb36c, 0xb36d, 0xb36e, 0xb36f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb370, 0xb371, 0xb372, 0xb373, 0xb374, 0xb375, 0xb376,
+ 0xb377, 0xb378, 0xb379, 0xb37a, 0xb37b, 0xb37c, 0xb37d, 0xb37e,
+ 0xb37f, 0xb380, 0x0000, 0xb381, 0xb382, 0xb383, 0xb384, 0xb385,
+ 0xb386, 0xb387, 0xb388, 0xb389, 0xb38a, 0xb38b, 0x0000, 0x0000,
+ 0x0000, 0xb38c, 0xb38d, 0xb38e, 0xb38f, 0xb390, 0xb391, 0xb392,
+ 0xb393, 0xb394, 0xb395, 0xb396, 0xb397, 0xb398, 0xb399, 0xb39a,
+ 0xb39b, 0xb39c, 0x0000, 0xb39d, 0xb39e, 0xb39f, 0xb3a0, 0xb3a1,
+ 0xb3a2, 0xb3a3, 0xb3a4, 0xb3a5, 0xb3a6, 0xb3a7, 0x0000, 0x0000,
+ 0x0000, 0xb3a8, 0xb3a9, 0xb3aa, 0xb3ab, 0xb3ac, 0xb3ad, 0xb3ae,
+ 0xb3af, 0xb3b0, 0xb3b1, 0xb3b2, 0xb3b3, 0xb3b4, 0xb3b5, 0xb3b6,
+ 0xb3b7, 0xb3b8, 0x0000, 0xb3b9, 0xb3ba, 0xb3bb, 0xb3bc, 0xb3bd,
+ 0xb3be, 0xb3bf, 0xb3c0, 0xb3c1, 0xb3c2, 0xb3c3, 0x0000, 0x0000,
+ 0x0000, 0xb3c4, 0xb3c5, 0xb3c6, 0xb3c7, 0xb3c8, 0xb3c9, 0xb3ca,
+ 0xb3cb, 0xb3cc, 0xb3cd, 0xb3ce, 0xb3cf, 0xb3d0, 0xb3d1, 0xb3d2,
+ 0xb3d3, 0xb3d4, 0x0000, 0xb3d5, 0xb3d6, 0xb3d7, 0xb3d8, 0xb3d9,
+ 0xb3da, 0xb3db, 0xb3dc, 0xb3dd, 0xb3de, 0xb3df, 0x0000, 0x0000,
+ 0x0000, 0xb3e0, 0xb3e1, 0xb3e2, 0xb3e3, 0xb3e4, 0xb3e5, 0xb3e6,
+ 0xb3e7, 0xb3e8, 0xb3e9, 0xb3ea, 0xb3eb, 0xb3ec, 0xb3ed, 0xb3ee,
+ 0xb3ef, 0xb3f0, 0x0000, 0xb3f1, 0xb3f2, 0xb3f3, 0xb3f4, 0xb3f5,
+ 0xb3f6, 0xb3f7, 0xb3f8, 0xb3f9, 0xb3fa, 0xb3fb, 0x0000, 0x0000,
+ 0x0000, 0xb3fc, 0xb3fd, 0xb3fe, 0xb3ff, 0xb400, 0xb401, 0xb402,
+ 0xb403, 0xb404, 0xb405, 0xb406, 0xb407, 0xb408, 0xb409, 0xb40a,
+ 0xb40b, 0xb40c, 0x0000, 0xb40d, 0xb40e, 0xb40f, 0xb410, 0xb411,
+ 0xb412, 0xb413, 0xb414, 0xb415, 0xb416, 0xb417, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb418, 0xb419, 0xb41a, 0xb41b, 0xb41c, 0xb41d, 0xb41e,
+ 0xb41f, 0xb420, 0xb421, 0xb422, 0xb423, 0xb424, 0xb425, 0xb426,
+ 0xb427, 0xb428, 0x0000, 0xb429, 0xb42a, 0xb42b, 0xb42c, 0xb42d,
+ 0xb42e, 0xb42f, 0xb430, 0xb431, 0xb432, 0xb433, 0x0000, 0x0000,
+ 0x0000, 0xb434, 0xb435, 0xb436, 0xb437, 0xb438, 0xb439, 0xb43a,
+ 0xb43b, 0xb43c, 0xb43d, 0xb43e, 0xb43f, 0xb440, 0xb441, 0xb442,
+ 0xb443, 0xb444, 0x0000, 0xb445, 0xb446, 0xb447, 0xb448, 0xb449,
+ 0xb44a, 0xb44b, 0xb44c, 0xb44d, 0xb44e, 0xb44f, 0x0000, 0x0000,
+ 0x0000, 0xb450, 0xb451, 0xb452, 0xb453, 0xb454, 0xb455, 0xb456,
+ 0xb457, 0xb458, 0xb459, 0xb45a, 0xb45b, 0xb45c, 0xb45d, 0xb45e,
+ 0xb45f, 0xb460, 0x0000, 0xb461, 0xb462, 0xb463, 0xb464, 0xb465,
+ 0xb466, 0xb467, 0xb468, 0xb469, 0xb46a, 0xb46b, 0x0000, 0x0000,
+ 0x0000, 0xb46c, 0xb46d, 0xb46e, 0xb46f, 0xb470, 0xb471, 0xb472,
+ 0xb473, 0xb474, 0xb475, 0xb476, 0xb477, 0xb478, 0xb479, 0xb47a,
+ 0xb47b, 0xb47c, 0x0000, 0xb47d, 0xb47e, 0xb47f, 0xb480, 0xb481,
+ 0xb482, 0xb483, 0xb484, 0xb485, 0xb486, 0xb487, 0x0000, 0x0000,
+ 0x0000, 0xb488, 0xb489, 0xb48a, 0xb48b, 0xb48c, 0xb48d, 0xb48e,
+ 0xb48f, 0xb490, 0xb491, 0xb492, 0xb493, 0xb494, 0xb495, 0xb496,
+ 0xb497, 0xb498, 0x0000, 0xb499, 0xb49a, 0xb49b, 0xb49c, 0xb49d,
+ 0xb49e, 0xb49f, 0xb4a0, 0xb4a1, 0xb4a2, 0xb4a3, 0x0000, 0x0000,
+ 0x0000, 0xb4a4, 0xb4a5, 0xb4a6, 0xb4a7, 0xb4a8, 0xb4a9, 0xb4aa,
+ 0xb4ab, 0xb4ac, 0xb4ad, 0xb4ae, 0xb4af, 0xb4b0, 0xb4b1, 0xb4b2,
+ 0xb4b3, 0xb4b4, 0x0000, 0xb4b5, 0xb4b6, 0xb4b7, 0xb4b8, 0xb4b9,
+ 0xb4ba, 0xb4bb, 0xb4bc, 0xb4bd, 0xb4be, 0xb4bf, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb4c0, 0xb4c1, 0xb4c2, 0xb4c3, 0xb4c4, 0xb4c5, 0xb4c6,
+ 0xb4c7, 0xb4c8, 0xb4c9, 0xb4ca, 0xb4cb, 0xb4cc, 0xb4cd, 0xb4ce,
+ 0xb4cf, 0xb4d0, 0x0000, 0xb4d1, 0xb4d2, 0xb4d3, 0xb4d4, 0xb4d5,
+ 0xb4d6, 0xb4d7, 0xb4d8, 0xb4d9, 0xb4da, 0xb4db, 0x0000, 0x0000,
+ 0x0000, 0xb4dc, 0xb4dd, 0xb4de, 0xb4df, 0xb4e0, 0xb4e1, 0xb4e2,
+ 0xb4e3, 0xb4e4, 0xb4e5, 0xb4e6, 0xb4e7, 0xb4e8, 0xb4e9, 0xb4ea,
+ 0xb4eb, 0xb4ec, 0x0000, 0xb4ed, 0xb4ee, 0xb4ef, 0xb4f0, 0xb4f1,
+ 0xb4f2, 0xb4f3, 0xb4f4, 0xb4f5, 0xb4f6, 0xb4f7, 0x0000, 0x0000,
+ 0x0000, 0xb4f8, 0xb4f9, 0xb4fa, 0xb4fb, 0xb4fc, 0xb4fd, 0xb4fe,
+ 0xb4ff, 0xb500, 0xb501, 0xb502, 0xb503, 0xb504, 0xb505, 0xb506,
+ 0xb507, 0xb508, 0x0000, 0xb509, 0xb50a, 0xb50b, 0xb50c, 0xb50d,
+ 0xb50e, 0xb50f, 0xb510, 0xb511, 0xb512, 0xb513, 0x0000, 0x0000,
+ 0x0000, 0xb514, 0xb515, 0xb516, 0xb517, 0xb518, 0xb519, 0xb51a,
+ 0xb51b, 0xb51c, 0xb51d, 0xb51e, 0xb51f, 0xb520, 0xb521, 0xb522,
+ 0xb523, 0xb524, 0x0000, 0xb525, 0xb526, 0xb527, 0xb528, 0xb529,
+ 0xb52a, 0xb52b, 0xb52c, 0xb52d, 0xb52e, 0xb52f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3138, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb530, 0xb531, 0xb532, 0xb533, 0xb534, 0xb535, 0xb536,
+ 0xb537, 0xb538, 0xb539, 0xb53a, 0xb53b, 0xb53c, 0xb53d, 0xb53e,
+ 0xb53f, 0xb540, 0x0000, 0xb541, 0xb542, 0xb543, 0xb544, 0xb545,
+ 0xb546, 0xb547, 0xb548, 0xb549, 0xb54a, 0xb54b, 0x0000, 0x0000,
+ 0x0000, 0xb54c, 0xb54d, 0xb54e, 0xb54f, 0xb550, 0xb551, 0xb552,
+ 0xb553, 0xb554, 0xb555, 0xb556, 0xb557, 0xb558, 0xb559, 0xb55a,
+ 0xb55b, 0xb55c, 0x0000, 0xb55d, 0xb55e, 0xb55f, 0xb560, 0xb561,
+ 0xb562, 0xb563, 0xb564, 0xb565, 0xb566, 0xb567, 0x0000, 0x0000,
+ 0x0000, 0xb568, 0xb569, 0xb56a, 0xb56b, 0xb56c, 0xb56d, 0xb56e,
+ 0xb56f, 0xb570, 0xb571, 0xb572, 0xb573, 0xb574, 0xb575, 0xb576,
+ 0xb577, 0xb578, 0x0000, 0xb579, 0xb57a, 0xb57b, 0xb57c, 0xb57d,
+ 0xb57e, 0xb57f, 0xb580, 0xb581, 0xb582, 0xb583, 0x0000, 0x0000,
+ 0x0000, 0xb584, 0xb585, 0xb586, 0xb587, 0xb588, 0xb589, 0xb58a,
+ 0xb58b, 0xb58c, 0xb58d, 0xb58e, 0xb58f, 0xb590, 0xb591, 0xb592,
+ 0xb593, 0xb594, 0x0000, 0xb595, 0xb596, 0xb597, 0xb598, 0xb599,
+ 0xb59a, 0xb59b, 0xb59c, 0xb59d, 0xb59e, 0xb59f, 0x0000, 0x0000,
+ 0x0000, 0xb5a0, 0xb5a1, 0xb5a2, 0xb5a3, 0xb5a4, 0xb5a5, 0xb5a6,
+ 0xb5a7, 0xb5a8, 0xb5a9, 0xb5aa, 0xb5ab, 0xb5ac, 0xb5ad, 0xb5ae,
+ 0xb5af, 0xb5b0, 0x0000, 0xb5b1, 0xb5b2, 0xb5b3, 0xb5b4, 0xb5b5,
+ 0xb5b6, 0xb5b7, 0xb5b8, 0xb5b9, 0xb5ba, 0xb5bb, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb5bc, 0xb5bd, 0xb5be, 0xb5bf, 0xb5c0, 0xb5c1, 0xb5c2,
+ 0xb5c3, 0xb5c4, 0xb5c5, 0xb5c6, 0xb5c7, 0xb5c8, 0xb5c9, 0xb5ca,
+ 0xb5cb, 0xb5cc, 0x0000, 0xb5cd, 0xb5ce, 0xb5cf, 0xb5d0, 0xb5d1,
+ 0xb5d2, 0xb5d3, 0xb5d4, 0xb5d5, 0xb5d6, 0xb5d7, 0x0000, 0x0000,
+ 0x0000, 0xb5d8, 0xb5d9, 0xb5da, 0xb5db, 0xb5dc, 0xb5dd, 0xb5de,
+ 0xb5df, 0xb5e0, 0xb5e1, 0xb5e2, 0xb5e3, 0xb5e4, 0xb5e5, 0xb5e6,
+ 0xb5e7, 0xb5e8, 0x0000, 0xb5e9, 0xb5ea, 0xb5eb, 0xb5ec, 0xb5ed,
+ 0xb5ee, 0xb5ef, 0xb5f0, 0xb5f1, 0xb5f2, 0xb5f3, 0x0000, 0x0000,
+ 0x0000, 0xb5f4, 0xb5f5, 0xb5f6, 0xb5f7, 0xb5f8, 0xb5f9, 0xb5fa,
+ 0xb5fb, 0xb5fc, 0xb5fd, 0xb5fe, 0xb5ff, 0xb600, 0xb601, 0xb602,
+ 0xb603, 0xb604, 0x0000, 0xb605, 0xb606, 0xb607, 0xb608, 0xb609,
+ 0xb60a, 0xb60b, 0xb60c, 0xb60d, 0xb60e, 0xb60f, 0x0000, 0x0000,
+ 0x0000, 0xb610, 0xb611, 0xb612, 0xb613, 0xb614, 0xb615, 0xb616,
+ 0xb617, 0xb618, 0xb619, 0xb61a, 0xb61b, 0xb61c, 0xb61d, 0xb61e,
+ 0xb61f, 0xb620, 0x0000, 0xb621, 0xb622, 0xb623, 0xb624, 0xb625,
+ 0xb626, 0xb627, 0xb628, 0xb629, 0xb62a, 0xb62b, 0x0000, 0x0000,
+ 0x0000, 0xb62c, 0xb62d, 0xb62e, 0xb62f, 0xb630, 0xb631, 0xb632,
+ 0xb633, 0xb634, 0xb635, 0xb636, 0xb637, 0xb638, 0xb639, 0xb63a,
+ 0xb63b, 0xb63c, 0x0000, 0xb63d, 0xb63e, 0xb63f, 0xb640, 0xb641,
+ 0xb642, 0xb643, 0xb644, 0xb645, 0xb646, 0xb647, 0x0000, 0x0000,
+ 0x0000, 0xb648, 0xb649, 0xb64a, 0xb64b, 0xb64c, 0xb64d, 0xb64e,
+ 0xb64f, 0xb650, 0xb651, 0xb652, 0xb653, 0xb654, 0xb655, 0xb656,
+ 0xb657, 0xb658, 0x0000, 0xb659, 0xb65a, 0xb65b, 0xb65c, 0xb65d,
+ 0xb65e, 0xb65f, 0xb660, 0xb661, 0xb662, 0xb663, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb664, 0xb665, 0xb666, 0xb667, 0xb668, 0xb669, 0xb66a,
+ 0xb66b, 0xb66c, 0xb66d, 0xb66e, 0xb66f, 0xb670, 0xb671, 0xb672,
+ 0xb673, 0xb674, 0x0000, 0xb675, 0xb676, 0xb677, 0xb678, 0xb679,
+ 0xb67a, 0xb67b, 0xb67c, 0xb67d, 0xb67e, 0xb67f, 0x0000, 0x0000,
+ 0x0000, 0xb680, 0xb681, 0xb682, 0xb683, 0xb684, 0xb685, 0xb686,
+ 0xb687, 0xb688, 0xb689, 0xb68a, 0xb68b, 0xb68c, 0xb68d, 0xb68e,
+ 0xb68f, 0xb690, 0x0000, 0xb691, 0xb692, 0xb693, 0xb694, 0xb695,
+ 0xb696, 0xb697, 0xb698, 0xb699, 0xb69a, 0xb69b, 0x0000, 0x0000,
+ 0x0000, 0xb69c, 0xb69d, 0xb69e, 0xb69f, 0xb6a0, 0xb6a1, 0xb6a2,
+ 0xb6a3, 0xb6a4, 0xb6a5, 0xb6a6, 0xb6a7, 0xb6a8, 0xb6a9, 0xb6aa,
+ 0xb6ab, 0xb6ac, 0x0000, 0xb6ad, 0xb6ae, 0xb6af, 0xb6b0, 0xb6b1,
+ 0xb6b2, 0xb6b3, 0xb6b4, 0xb6b5, 0xb6b6, 0xb6b7, 0x0000, 0x0000,
+ 0x0000, 0xb6b8, 0xb6b9, 0xb6ba, 0xb6bb, 0xb6bc, 0xb6bd, 0xb6be,
+ 0xb6bf, 0xb6c0, 0xb6c1, 0xb6c2, 0xb6c3, 0xb6c4, 0xb6c5, 0xb6c6,
+ 0xb6c7, 0xb6c8, 0x0000, 0xb6c9, 0xb6ca, 0xb6cb, 0xb6cc, 0xb6cd,
+ 0xb6ce, 0xb6cf, 0xb6d0, 0xb6d1, 0xb6d2, 0xb6d3, 0x0000, 0x0000,
+ 0x0000, 0xb6d4, 0xb6d5, 0xb6d6, 0xb6d7, 0xb6d8, 0xb6d9, 0xb6da,
+ 0xb6db, 0xb6dc, 0xb6dd, 0xb6de, 0xb6df, 0xb6e0, 0xb6e1, 0xb6e2,
+ 0xb6e3, 0xb6e4, 0x0000, 0xb6e5, 0xb6e6, 0xb6e7, 0xb6e8, 0xb6e9,
+ 0xb6ea, 0xb6eb, 0xb6ec, 0xb6ed, 0xb6ee, 0xb6ef, 0x0000, 0x0000,
+ 0x0000, 0xb6f0, 0xb6f1, 0xb6f2, 0xb6f3, 0xb6f4, 0xb6f5, 0xb6f6,
+ 0xb6f7, 0xb6f8, 0xb6f9, 0xb6fa, 0xb6fb, 0xb6fc, 0xb6fd, 0xb6fe,
+ 0xb6ff, 0xb700, 0x0000, 0xb701, 0xb702, 0xb703, 0xb704, 0xb705,
+ 0xb706, 0xb707, 0xb708, 0xb709, 0xb70a, 0xb70b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb70c, 0xb70d, 0xb70e, 0xb70f, 0xb710, 0xb711, 0xb712,
+ 0xb713, 0xb714, 0xb715, 0xb716, 0xb717, 0xb718, 0xb719, 0xb71a,
+ 0xb71b, 0xb71c, 0x0000, 0xb71d, 0xb71e, 0xb71f, 0xb720, 0xb721,
+ 0xb722, 0xb723, 0xb724, 0xb725, 0xb726, 0xb727, 0x0000, 0x0000,
+ 0x0000, 0xb728, 0xb729, 0xb72a, 0xb72b, 0xb72c, 0xb72d, 0xb72e,
+ 0xb72f, 0xb730, 0xb731, 0xb732, 0xb733, 0xb734, 0xb735, 0xb736,
+ 0xb737, 0xb738, 0x0000, 0xb739, 0xb73a, 0xb73b, 0xb73c, 0xb73d,
+ 0xb73e, 0xb73f, 0xb740, 0xb741, 0xb742, 0xb743, 0x0000, 0x0000,
+ 0x0000, 0xb744, 0xb745, 0xb746, 0xb747, 0xb748, 0xb749, 0xb74a,
+ 0xb74b, 0xb74c, 0xb74d, 0xb74e, 0xb74f, 0xb750, 0xb751, 0xb752,
+ 0xb753, 0xb754, 0x0000, 0xb755, 0xb756, 0xb757, 0xb758, 0xb759,
+ 0xb75a, 0xb75b, 0xb75c, 0xb75d, 0xb75e, 0xb75f, 0x0000, 0x0000,
+ 0x0000, 0xb760, 0xb761, 0xb762, 0xb763, 0xb764, 0xb765, 0xb766,
+ 0xb767, 0xb768, 0xb769, 0xb76a, 0xb76b, 0xb76c, 0xb76d, 0xb76e,
+ 0xb76f, 0xb770, 0x0000, 0xb771, 0xb772, 0xb773, 0xb774, 0xb775,
+ 0xb776, 0xb777, 0xb778, 0xb779, 0xb77a, 0xb77b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb77c, 0xb77d, 0xb77e, 0xb77f, 0xb780, 0xb781, 0xb782,
+ 0xb783, 0xb784, 0xb785, 0xb786, 0xb787, 0xb788, 0xb789, 0xb78a,
+ 0xb78b, 0xb78c, 0x0000, 0xb78d, 0xb78e, 0xb78f, 0xb790, 0xb791,
+ 0xb792, 0xb793, 0xb794, 0xb795, 0xb796, 0xb797, 0x0000, 0x0000,
+ 0x0000, 0xb798, 0xb799, 0xb79a, 0xb79b, 0xb79c, 0xb79d, 0xb79e,
+ 0xb79f, 0xb7a0, 0xb7a1, 0xb7a2, 0xb7a3, 0xb7a4, 0xb7a5, 0xb7a6,
+ 0xb7a7, 0xb7a8, 0x0000, 0xb7a9, 0xb7aa, 0xb7ab, 0xb7ac, 0xb7ad,
+ 0xb7ae, 0xb7af, 0xb7b0, 0xb7b1, 0xb7b2, 0xb7b3, 0x0000, 0x0000,
+ 0x0000, 0xb7b4, 0xb7b5, 0xb7b6, 0xb7b7, 0xb7b8, 0xb7b9, 0xb7ba,
+ 0xb7bb, 0xb7bc, 0xb7bd, 0xb7be, 0xb7bf, 0xb7c0, 0xb7c1, 0xb7c2,
+ 0xb7c3, 0xb7c4, 0x0000, 0xb7c5, 0xb7c6, 0xb7c7, 0xb7c8, 0xb7c9,
+ 0xb7ca, 0xb7cb, 0xb7cc, 0xb7cd, 0xb7ce, 0xb7cf, 0x0000, 0x0000,
+ 0x0000, 0xb7d0, 0xb7d1, 0xb7d2, 0xb7d3, 0xb7d4, 0xb7d5, 0xb7d6,
+ 0xb7d7, 0xb7d8, 0xb7d9, 0xb7da, 0xb7db, 0xb7dc, 0xb7dd, 0xb7de,
+ 0xb7df, 0xb7e0, 0x0000, 0xb7e1, 0xb7e2, 0xb7e3, 0xb7e4, 0xb7e5,
+ 0xb7e6, 0xb7e7, 0xb7e8, 0xb7e9, 0xb7ea, 0xb7eb, 0x0000, 0x0000,
+ 0x0000, 0xb7ec, 0xb7ed, 0xb7ee, 0xb7ef, 0xb7f0, 0xb7f1, 0xb7f2,
+ 0xb7f3, 0xb7f4, 0xb7f5, 0xb7f6, 0xb7f7, 0xb7f8, 0xb7f9, 0xb7fa,
+ 0xb7fb, 0xb7fc, 0x0000, 0xb7fd, 0xb7fe, 0xb7ff, 0xb800, 0xb801,
+ 0xb802, 0xb803, 0xb804, 0xb805, 0xb806, 0xb807, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb808, 0xb809, 0xb80a, 0xb80b, 0xb80c, 0xb80d, 0xb80e,
+ 0xb80f, 0xb810, 0xb811, 0xb812, 0xb813, 0xb814, 0xb815, 0xb816,
+ 0xb817, 0xb818, 0x0000, 0xb819, 0xb81a, 0xb81b, 0xb81c, 0xb81d,
+ 0xb81e, 0xb81f, 0xb820, 0xb821, 0xb822, 0xb823, 0x0000, 0x0000,
+ 0x0000, 0xb824, 0xb825, 0xb826, 0xb827, 0xb828, 0xb829, 0xb82a,
+ 0xb82b, 0xb82c, 0xb82d, 0xb82e, 0xb82f, 0xb830, 0xb831, 0xb832,
+ 0xb833, 0xb834, 0x0000, 0xb835, 0xb836, 0xb837, 0xb838, 0xb839,
+ 0xb83a, 0xb83b, 0xb83c, 0xb83d, 0xb83e, 0xb83f, 0x0000, 0x0000,
+ 0x0000, 0xb840, 0xb841, 0xb842, 0xb843, 0xb844, 0xb845, 0xb846,
+ 0xb847, 0xb848, 0xb849, 0xb84a, 0xb84b, 0xb84c, 0xb84d, 0xb84e,
+ 0xb84f, 0xb850, 0x0000, 0xb851, 0xb852, 0xb853, 0xb854, 0xb855,
+ 0xb856, 0xb857, 0xb858, 0xb859, 0xb85a, 0xb85b, 0x0000, 0x0000,
+ 0x0000, 0xb85c, 0xb85d, 0xb85e, 0xb85f, 0xb860, 0xb861, 0xb862,
+ 0xb863, 0xb864, 0xb865, 0xb866, 0xb867, 0xb868, 0xb869, 0xb86a,
+ 0xb86b, 0xb86c, 0x0000, 0xb86d, 0xb86e, 0xb86f, 0xb870, 0xb871,
+ 0xb872, 0xb873, 0xb874, 0xb875, 0xb876, 0xb877, 0x0000, 0x0000,
+ 0x0000, 0xb878, 0xb879, 0xb87a, 0xb87b, 0xb87c, 0xb87d, 0xb87e,
+ 0xb87f, 0xb880, 0xb881, 0xb882, 0xb883, 0xb884, 0xb885, 0xb886,
+ 0xb887, 0xb888, 0x0000, 0xb889, 0xb88a, 0xb88b, 0xb88c, 0xb88d,
+ 0xb88e, 0xb88f, 0xb890, 0xb891, 0xb892, 0xb893, 0x0000, 0x0000,
+ 0x0000, 0xb894, 0xb895, 0xb896, 0xb897, 0xb898, 0xb899, 0xb89a,
+ 0xb89b, 0xb89c, 0xb89d, 0xb89e, 0xb89f, 0xb8a0, 0xb8a1, 0xb8a2,
+ 0xb8a3, 0xb8a4, 0x0000, 0xb8a5, 0xb8a6, 0xb8a7, 0xb8a8, 0xb8a9,
+ 0xb8aa, 0xb8ab, 0xb8ac, 0xb8ad, 0xb8ae, 0xb8af, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb8b0, 0xb8b1, 0xb8b2, 0xb8b3, 0xb8b4, 0xb8b5, 0xb8b6,
+ 0xb8b7, 0xb8b8, 0xb8b9, 0xb8ba, 0xb8bb, 0xb8bc, 0xb8bd, 0xb8be,
+ 0xb8bf, 0xb8c0, 0x0000, 0xb8c1, 0xb8c2, 0xb8c3, 0xb8c4, 0xb8c5,
+ 0xb8c6, 0xb8c7, 0xb8c8, 0xb8c9, 0xb8ca, 0xb8cb, 0x0000, 0x0000,
+ 0x0000, 0xb8cc, 0xb8cd, 0xb8ce, 0xb8cf, 0xb8d0, 0xb8d1, 0xb8d2,
+ 0xb8d3, 0xb8d4, 0xb8d5, 0xb8d6, 0xb8d7, 0xb8d8, 0xb8d9, 0xb8da,
+ 0xb8db, 0xb8dc, 0x0000, 0xb8dd, 0xb8de, 0xb8df, 0xb8e0, 0xb8e1,
+ 0xb8e2, 0xb8e3, 0xb8e4, 0xb8e5, 0xb8e6, 0xb8e7, 0x0000, 0x0000,
+ 0x0000, 0xb8e8, 0xb8e9, 0xb8ea, 0xb8eb, 0xb8ec, 0xb8ed, 0xb8ee,
+ 0xb8ef, 0xb8f0, 0xb8f1, 0xb8f2, 0xb8f3, 0xb8f4, 0xb8f5, 0xb8f6,
+ 0xb8f7, 0xb8f8, 0x0000, 0xb8f9, 0xb8fa, 0xb8fb, 0xb8fc, 0xb8fd,
+ 0xb8fe, 0xb8ff, 0xb900, 0xb901, 0xb902, 0xb903, 0x0000, 0x0000,
+ 0x0000, 0xb904, 0xb905, 0xb906, 0xb907, 0xb908, 0xb909, 0xb90a,
+ 0xb90b, 0xb90c, 0xb90d, 0xb90e, 0xb90f, 0xb910, 0xb911, 0xb912,
+ 0xb913, 0xb914, 0x0000, 0xb915, 0xb916, 0xb917, 0xb918, 0xb919,
+ 0xb91a, 0xb91b, 0xb91c, 0xb91d, 0xb91e, 0xb91f, 0x0000, 0x0000,
+ 0x0000, 0xb920, 0xb921, 0xb922, 0xb923, 0xb924, 0xb925, 0xb926,
+ 0xb927, 0xb928, 0xb929, 0xb92a, 0xb92b, 0xb92c, 0xb92d, 0xb92e,
+ 0xb92f, 0xb930, 0x0000, 0xb931, 0xb932, 0xb933, 0xb934, 0xb935,
+ 0xb936, 0xb937, 0xb938, 0xb939, 0xb93a, 0xb93b, 0x0000, 0x0000,
+ 0x0000, 0xb93c, 0xb93d, 0xb93e, 0xb93f, 0xb940, 0xb941, 0xb942,
+ 0xb943, 0xb944, 0xb945, 0xb946, 0xb947, 0xb948, 0xb949, 0xb94a,
+ 0xb94b, 0xb94c, 0x0000, 0xb94d, 0xb94e, 0xb94f, 0xb950, 0xb951,
+ 0xb952, 0xb953, 0xb954, 0xb955, 0xb956, 0xb957, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb958, 0xb959, 0xb95a, 0xb95b, 0xb95c, 0xb95d, 0xb95e,
+ 0xb95f, 0xb960, 0xb961, 0xb962, 0xb963, 0xb964, 0xb965, 0xb966,
+ 0xb967, 0xb968, 0x0000, 0xb969, 0xb96a, 0xb96b, 0xb96c, 0xb96d,
+ 0xb96e, 0xb96f, 0xb970, 0xb971, 0xb972, 0xb973, 0x0000, 0x0000,
+ 0x0000, 0xb974, 0xb975, 0xb976, 0xb977, 0xb978, 0xb979, 0xb97a,
+ 0xb97b, 0xb97c, 0xb97d, 0xb97e, 0xb97f, 0xb980, 0xb981, 0xb982,
+ 0xb983, 0xb984, 0x0000, 0xb985, 0xb986, 0xb987, 0xb988, 0xb989,
+ 0xb98a, 0xb98b, 0xb98c, 0xb98d, 0xb98e, 0xb98f, 0x0000, 0x0000,
+ 0x0000, 0xb990, 0xb991, 0xb992, 0xb993, 0xb994, 0xb995, 0xb996,
+ 0xb997, 0xb998, 0xb999, 0xb99a, 0xb99b, 0xb99c, 0xb99d, 0xb99e,
+ 0xb99f, 0xb9a0, 0x0000, 0xb9a1, 0xb9a2, 0xb9a3, 0xb9a4, 0xb9a5,
+ 0xb9a6, 0xb9a7, 0xb9a8, 0xb9a9, 0xb9aa, 0xb9ab, 0x0000, 0x0000,
+ 0x0000, 0xb9ac, 0xb9ad, 0xb9ae, 0xb9af, 0xb9b0, 0xb9b1, 0xb9b2,
+ 0xb9b3, 0xb9b4, 0xb9b5, 0xb9b6, 0xb9b7, 0xb9b8, 0xb9b9, 0xb9ba,
+ 0xb9bb, 0xb9bc, 0x0000, 0xb9bd, 0xb9be, 0xb9bf, 0xb9c0, 0xb9c1,
+ 0xb9c2, 0xb9c3, 0xb9c4, 0xb9c5, 0xb9c6, 0xb9c7, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xb9c8, 0xb9c9, 0xb9ca, 0xb9cb, 0xb9cc, 0xb9cd, 0xb9ce,
+ 0xb9cf, 0xb9d0, 0xb9d1, 0xb9d2, 0xb9d3, 0xb9d4, 0xb9d5, 0xb9d6,
+ 0xb9d7, 0xb9d8, 0x0000, 0xb9d9, 0xb9da, 0xb9db, 0xb9dc, 0xb9dd,
+ 0xb9de, 0xb9df, 0xb9e0, 0xb9e1, 0xb9e2, 0xb9e3, 0x0000, 0x0000,
+ 0x0000, 0xb9e4, 0xb9e5, 0xb9e6, 0xb9e7, 0xb9e8, 0xb9e9, 0xb9ea,
+ 0xb9eb, 0xb9ec, 0xb9ed, 0xb9ee, 0xb9ef, 0xb9f0, 0xb9f1, 0xb9f2,
+ 0xb9f3, 0xb9f4, 0x0000, 0xb9f5, 0xb9f6, 0xb9f7, 0xb9f8, 0xb9f9,
+ 0xb9fa, 0xb9fb, 0xb9fc, 0xb9fd, 0xb9fe, 0xb9ff, 0x0000, 0x0000,
+ 0x0000, 0xba00, 0xba01, 0xba02, 0xba03, 0xba04, 0xba05, 0xba06,
+ 0xba07, 0xba08, 0xba09, 0xba0a, 0xba0b, 0xba0c, 0xba0d, 0xba0e,
+ 0xba0f, 0xba10, 0x0000, 0xba11, 0xba12, 0xba13, 0xba14, 0xba15,
+ 0xba16, 0xba17, 0xba18, 0xba19, 0xba1a, 0xba1b, 0x0000, 0x0000,
+ 0x0000, 0xba1c, 0xba1d, 0xba1e, 0xba1f, 0xba20, 0xba21, 0xba22,
+ 0xba23, 0xba24, 0xba25, 0xba26, 0xba27, 0xba28, 0xba29, 0xba2a,
+ 0xba2b, 0xba2c, 0x0000, 0xba2d, 0xba2e, 0xba2f, 0xba30, 0xba31,
+ 0xba32, 0xba33, 0xba34, 0xba35, 0xba36, 0xba37, 0x0000, 0x0000,
+ 0x0000, 0xba38, 0xba39, 0xba3a, 0xba3b, 0xba3c, 0xba3d, 0xba3e,
+ 0xba3f, 0xba40, 0xba41, 0xba42, 0xba43, 0xba44, 0xba45, 0xba46,
+ 0xba47, 0xba48, 0x0000, 0xba49, 0xba4a, 0xba4b, 0xba4c, 0xba4d,
+ 0xba4e, 0xba4f, 0xba50, 0xba51, 0xba52, 0xba53, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xba54, 0xba55, 0xba56, 0xba57, 0xba58, 0xba59, 0xba5a,
+ 0xba5b, 0xba5c, 0xba5d, 0xba5e, 0xba5f, 0xba60, 0xba61, 0xba62,
+ 0xba63, 0xba64, 0x0000, 0xba65, 0xba66, 0xba67, 0xba68, 0xba69,
+ 0xba6a, 0xba6b, 0xba6c, 0xba6d, 0xba6e, 0xba6f, 0x0000, 0x0000,
+ 0x0000, 0xba70, 0xba71, 0xba72, 0xba73, 0xba74, 0xba75, 0xba76,
+ 0xba77, 0xba78, 0xba79, 0xba7a, 0xba7b, 0xba7c, 0xba7d, 0xba7e,
+ 0xba7f, 0xba80, 0x0000, 0xba81, 0xba82, 0xba83, 0xba84, 0xba85,
+ 0xba86, 0xba87, 0xba88, 0xba89, 0xba8a, 0xba8b, 0x0000, 0x0000,
+ 0x0000, 0xba8c, 0xba8d, 0xba8e, 0xba8f, 0xba90, 0xba91, 0xba92,
+ 0xba93, 0xba94, 0xba95, 0xba96, 0xba97, 0xba98, 0xba99, 0xba9a,
+ 0xba9b, 0xba9c, 0x0000, 0xba9d, 0xba9e, 0xba9f, 0xbaa0, 0xbaa1,
+ 0xbaa2, 0xbaa3, 0xbaa4, 0xbaa5, 0xbaa6, 0xbaa7, 0x0000, 0x0000,
+ 0x0000, 0xbaa8, 0xbaa9, 0xbaaa, 0xbaab, 0xbaac, 0xbaad, 0xbaae,
+ 0xbaaf, 0xbab0, 0xbab1, 0xbab2, 0xbab3, 0xbab4, 0xbab5, 0xbab6,
+ 0xbab7, 0xbab8, 0x0000, 0xbab9, 0xbaba, 0xbabb, 0xbabc, 0xbabd,
+ 0xbabe, 0xbabf, 0xbac0, 0xbac1, 0xbac2, 0xbac3, 0x0000, 0x0000,
+ 0x0000, 0xbac4, 0xbac5, 0xbac6, 0xbac7, 0xbac8, 0xbac9, 0xbaca,
+ 0xbacb, 0xbacc, 0xbacd, 0xbace, 0xbacf, 0xbad0, 0xbad1, 0xbad2,
+ 0xbad3, 0xbad4, 0x0000, 0xbad5, 0xbad6, 0xbad7, 0xbad8, 0xbad9,
+ 0xbada, 0xbadb, 0xbadc, 0xbadd, 0xbade, 0xbadf, 0x0000, 0x0000,
+ 0x0000, 0xbae0, 0xbae1, 0xbae2, 0xbae3, 0xbae4, 0xbae5, 0xbae6,
+ 0xbae7, 0xbae8, 0xbae9, 0xbaea, 0xbaeb, 0xbaec, 0xbaed, 0xbaee,
+ 0xbaef, 0xbaf0, 0x0000, 0xbaf1, 0xbaf2, 0xbaf3, 0xbaf4, 0xbaf5,
+ 0xbaf6, 0xbaf7, 0xbaf8, 0xbaf9, 0xbafa, 0xbafb, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xbafc, 0xbafd, 0xbafe, 0xbaff, 0xbb00, 0xbb01, 0xbb02,
+ 0xbb03, 0xbb04, 0xbb05, 0xbb06, 0xbb07, 0xbb08, 0xbb09, 0xbb0a,
+ 0xbb0b, 0xbb0c, 0x0000, 0xbb0d, 0xbb0e, 0xbb0f, 0xbb10, 0xbb11,
+ 0xbb12, 0xbb13, 0xbb14, 0xbb15, 0xbb16, 0xbb17, 0x0000, 0x0000,
+ 0x0000, 0xbb18, 0xbb19, 0xbb1a, 0xbb1b, 0xbb1c, 0xbb1d, 0xbb1e,
+ 0xbb1f, 0xbb20, 0xbb21, 0xbb22, 0xbb23, 0xbb24, 0xbb25, 0xbb26,
+ 0xbb27, 0xbb28, 0x0000, 0xbb29, 0xbb2a, 0xbb2b, 0xbb2c, 0xbb2d,
+ 0xbb2e, 0xbb2f, 0xbb30, 0xbb31, 0xbb32, 0xbb33, 0x0000, 0x0000,
+ 0x0000, 0xbb34, 0xbb35, 0xbb36, 0xbb37, 0xbb38, 0xbb39, 0xbb3a,
+ 0xbb3b, 0xbb3c, 0xbb3d, 0xbb3e, 0xbb3f, 0xbb40, 0xbb41, 0xbb42,
+ 0xbb43, 0xbb44, 0x0000, 0xbb45, 0xbb46, 0xbb47, 0xbb48, 0xbb49,
+ 0xbb4a, 0xbb4b, 0xbb4c, 0xbb4d, 0xbb4e, 0xbb4f, 0x0000, 0x0000,
+ 0x0000, 0xbb50, 0xbb51, 0xbb52, 0xbb53, 0xbb54, 0xbb55, 0xbb56,
+ 0xbb57, 0xbb58, 0xbb59, 0xbb5a, 0xbb5b, 0xbb5c, 0xbb5d, 0xbb5e,
+ 0xbb5f, 0xbb60, 0x0000, 0xbb61, 0xbb62, 0xbb63, 0xbb64, 0xbb65,
+ 0xbb66, 0xbb67, 0xbb68, 0xbb69, 0xbb6a, 0xbb6b, 0x0000, 0x0000,
+ 0x0000, 0xbb6c, 0xbb6d, 0xbb6e, 0xbb6f, 0xbb70, 0xbb71, 0xbb72,
+ 0xbb73, 0xbb74, 0xbb75, 0xbb76, 0xbb77, 0xbb78, 0xbb79, 0xbb7a,
+ 0xbb7b, 0xbb7c, 0x0000, 0xbb7d, 0xbb7e, 0xbb7f, 0xbb80, 0xbb81,
+ 0xbb82, 0xbb83, 0xbb84, 0xbb85, 0xbb86, 0xbb87, 0x0000, 0x0000,
+ 0x0000, 0xbb88, 0xbb89, 0xbb8a, 0xbb8b, 0xbb8c, 0xbb8d, 0xbb8e,
+ 0xbb8f, 0xbb90, 0xbb91, 0xbb92, 0xbb93, 0xbb94, 0xbb95, 0xbb96,
+ 0xbb97, 0xbb98, 0x0000, 0xbb99, 0xbb9a, 0xbb9b, 0xbb9c, 0xbb9d,
+ 0xbb9e, 0xbb9f, 0xbba0, 0xbba1, 0xbba2, 0xbba3, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xbba4, 0xbba5, 0xbba6, 0xbba7, 0xbba8, 0xbba9, 0xbbaa,
+ 0xbbab, 0xbbac, 0xbbad, 0xbbae, 0xbbaf, 0xbbb0, 0xbbb1, 0xbbb2,
+ 0xbbb3, 0xbbb4, 0x0000, 0xbbb5, 0xbbb6, 0xbbb7, 0xbbb8, 0xbbb9,
+ 0xbbba, 0xbbbb, 0xbbbc, 0xbbbd, 0xbbbe, 0xbbbf, 0x0000, 0x0000,
+ 0x0000, 0xbbc0, 0xbbc1, 0xbbc2, 0xbbc3, 0xbbc4, 0xbbc5, 0xbbc6,
+ 0xbbc7, 0xbbc8, 0xbbc9, 0xbbca, 0xbbcb, 0xbbcc, 0xbbcd, 0xbbce,
+ 0xbbcf, 0xbbd0, 0x0000, 0xbbd1, 0xbbd2, 0xbbd3, 0xbbd4, 0xbbd5,
+ 0xbbd6, 0xbbd7, 0xbbd8, 0xbbd9, 0xbbda, 0xbbdb, 0x0000, 0x0000,
+ 0x0000, 0xbbdc, 0xbbdd, 0xbbde, 0xbbdf, 0xbbe0, 0xbbe1, 0xbbe2,
+ 0xbbe3, 0xbbe4, 0xbbe5, 0xbbe6, 0xbbe7, 0xbbe8, 0xbbe9, 0xbbea,
+ 0xbbeb, 0xbbec, 0x0000, 0xbbed, 0xbbee, 0xbbef, 0xbbf0, 0xbbf1,
+ 0xbbf2, 0xbbf3, 0xbbf4, 0xbbf5, 0xbbf6, 0xbbf7, 0x0000, 0x0000,
+ 0x0000, 0xbbf8, 0xbbf9, 0xbbfa, 0xbbfb, 0xbbfc, 0xbbfd, 0xbbfe,
+ 0xbbff, 0xbc00, 0xbc01, 0xbc02, 0xbc03, 0xbc04, 0xbc05, 0xbc06,
+ 0xbc07, 0xbc08, 0x0000, 0xbc09, 0xbc0a, 0xbc0b, 0xbc0c, 0xbc0d,
+ 0xbc0e, 0xbc0f, 0xbc10, 0xbc11, 0xbc12, 0xbc13, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xbc14, 0xbc15, 0xbc16, 0xbc17, 0xbc18, 0xbc19, 0xbc1a,
+ 0xbc1b, 0xbc1c, 0xbc1d, 0xbc1e, 0xbc1f, 0xbc20, 0xbc21, 0xbc22,
+ 0xbc23, 0xbc24, 0x0000, 0xbc25, 0xbc26, 0xbc27, 0xbc28, 0xbc29,
+ 0xbc2a, 0xbc2b, 0xbc2c, 0xbc2d, 0xbc2e, 0xbc2f, 0x0000, 0x0000,
+ 0x0000, 0xbc30, 0xbc31, 0xbc32, 0xbc33, 0xbc34, 0xbc35, 0xbc36,
+ 0xbc37, 0xbc38, 0xbc39, 0xbc3a, 0xbc3b, 0xbc3c, 0xbc3d, 0xbc3e,
+ 0xbc3f, 0xbc40, 0x0000, 0xbc41, 0xbc42, 0xbc43, 0xbc44, 0xbc45,
+ 0xbc46, 0xbc47, 0xbc48, 0xbc49, 0xbc4a, 0xbc4b, 0x0000, 0x0000,
+ 0x0000, 0xbc4c, 0xbc4d, 0xbc4e, 0xbc4f, 0xbc50, 0xbc51, 0xbc52,
+ 0xbc53, 0xbc54, 0xbc55, 0xbc56, 0xbc57, 0xbc58, 0xbc59, 0xbc5a,
+ 0xbc5b, 0xbc5c, 0x0000, 0xbc5d, 0xbc5e, 0xbc5f, 0xbc60, 0xbc61,
+ 0xbc62, 0xbc63, 0xbc64, 0xbc65, 0xbc66, 0xbc67, 0x0000, 0x0000,
+ 0x0000, 0xbc68, 0xbc69, 0xbc6a, 0xbc6b, 0xbc6c, 0xbc6d, 0xbc6e,
+ 0xbc6f, 0xbc70, 0xbc71, 0xbc72, 0xbc73, 0xbc74, 0xbc75, 0xbc76,
+ 0xbc77, 0xbc78, 0x0000, 0xbc79, 0xbc7a, 0xbc7b, 0xbc7c, 0xbc7d,
+ 0xbc7e, 0xbc7f, 0xbc80, 0xbc81, 0xbc82, 0xbc83, 0x0000, 0x0000,
+ 0x0000, 0xbc84, 0xbc85, 0xbc86, 0xbc87, 0xbc88, 0xbc89, 0xbc8a,
+ 0xbc8b, 0xbc8c, 0xbc8d, 0xbc8e, 0xbc8f, 0xbc90, 0xbc91, 0xbc92,
+ 0xbc93, 0xbc94, 0x0000, 0xbc95, 0xbc96, 0xbc97, 0xbc98, 0xbc99,
+ 0xbc9a, 0xbc9b, 0xbc9c, 0xbc9d, 0xbc9e, 0xbc9f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xbca0, 0xbca1, 0xbca2, 0xbca3, 0xbca4, 0xbca5, 0xbca6,
+ 0xbca7, 0xbca8, 0xbca9, 0xbcaa, 0xbcab, 0xbcac, 0xbcad, 0xbcae,
+ 0xbcaf, 0xbcb0, 0x0000, 0xbcb1, 0xbcb2, 0xbcb3, 0xbcb4, 0xbcb5,
+ 0xbcb6, 0xbcb7, 0xbcb8, 0xbcb9, 0xbcba, 0xbcbb, 0x0000, 0x0000,
+ 0x0000, 0xbcbc, 0xbcbd, 0xbcbe, 0xbcbf, 0xbcc0, 0xbcc1, 0xbcc2,
+ 0xbcc3, 0xbcc4, 0xbcc5, 0xbcc6, 0xbcc7, 0xbcc8, 0xbcc9, 0xbcca,
+ 0xbccb, 0xbccc, 0x0000, 0xbccd, 0xbcce, 0xbccf, 0xbcd0, 0xbcd1,
+ 0xbcd2, 0xbcd3, 0xbcd4, 0xbcd5, 0xbcd6, 0xbcd7, 0x0000, 0x0000,
+ 0x0000, 0xbcd8, 0xbcd9, 0xbcda, 0xbcdb, 0xbcdc, 0xbcdd, 0xbcde,
+ 0xbcdf, 0xbce0, 0xbce1, 0xbce2, 0xbce3, 0xbce4, 0xbce5, 0xbce6,
+ 0xbce7, 0xbce8, 0x0000, 0xbce9, 0xbcea, 0xbceb, 0xbcec, 0xbced,
+ 0xbcee, 0xbcef, 0xbcf0, 0xbcf1, 0xbcf2, 0xbcf3, 0x0000, 0x0000,
+ 0x0000, 0xbcf4, 0xbcf5, 0xbcf6, 0xbcf7, 0xbcf8, 0xbcf9, 0xbcfa,
+ 0xbcfb, 0xbcfc, 0xbcfd, 0xbcfe, 0xbcff, 0xbd00, 0xbd01, 0xbd02,
+ 0xbd03, 0xbd04, 0x0000, 0xbd05, 0xbd06, 0xbd07, 0xbd08, 0xbd09,
+ 0xbd0a, 0xbd0b, 0xbd0c, 0xbd0d, 0xbd0e, 0xbd0f, 0x0000, 0x0000,
+ 0x0000, 0xbd10, 0xbd11, 0xbd12, 0xbd13, 0xbd14, 0xbd15, 0xbd16,
+ 0xbd17, 0xbd18, 0xbd19, 0xbd1a, 0xbd1b, 0xbd1c, 0xbd1d, 0xbd1e,
+ 0xbd1f, 0xbd20, 0x0000, 0xbd21, 0xbd22, 0xbd23, 0xbd24, 0xbd25,
+ 0xbd26, 0xbd27, 0xbd28, 0xbd29, 0xbd2a, 0xbd2b, 0x0000, 0x0000,
+ 0x0000, 0xbd2c, 0xbd2d, 0xbd2e, 0xbd2f, 0xbd30, 0xbd31, 0xbd32,
+ 0xbd33, 0xbd34, 0xbd35, 0xbd36, 0xbd37, 0xbd38, 0xbd39, 0xbd3a,
+ 0xbd3b, 0xbd3c, 0x0000, 0xbd3d, 0xbd3e, 0xbd3f, 0xbd40, 0xbd41,
+ 0xbd42, 0xbd43, 0xbd44, 0xbd45, 0xbd46, 0xbd47, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xbd48, 0xbd49, 0xbd4a, 0xbd4b, 0xbd4c, 0xbd4d, 0xbd4e,
+ 0xbd4f, 0xbd50, 0xbd51, 0xbd52, 0xbd53, 0xbd54, 0xbd55, 0xbd56,
+ 0xbd57, 0xbd58, 0x0000, 0xbd59, 0xbd5a, 0xbd5b, 0xbd5c, 0xbd5d,
+ 0xbd5e, 0xbd5f, 0xbd60, 0xbd61, 0xbd62, 0xbd63, 0x0000, 0x0000,
+ 0x0000, 0xbd64, 0xbd65, 0xbd66, 0xbd67, 0xbd68, 0xbd69, 0xbd6a,
+ 0xbd6b, 0xbd6c, 0xbd6d, 0xbd6e, 0xbd6f, 0xbd70, 0xbd71, 0xbd72,
+ 0xbd73, 0xbd74, 0x0000, 0xbd75, 0xbd76, 0xbd77, 0xbd78, 0xbd79,
+ 0xbd7a, 0xbd7b, 0xbd7c, 0xbd7d, 0xbd7e, 0xbd7f, 0x0000, 0x0000,
+ 0x0000, 0xbd80, 0xbd81, 0xbd82, 0xbd83, 0xbd84, 0xbd85, 0xbd86,
+ 0xbd87, 0xbd88, 0xbd89, 0xbd8a, 0xbd8b, 0xbd8c, 0xbd8d, 0xbd8e,
+ 0xbd8f, 0xbd90, 0x0000, 0xbd91, 0xbd92, 0xbd93, 0xbd94, 0xbd95,
+ 0xbd96, 0xbd97, 0xbd98, 0xbd99, 0xbd9a, 0xbd9b, 0x0000, 0x0000,
+ 0x0000, 0xbd9c, 0xbd9d, 0xbd9e, 0xbd9f, 0xbda0, 0xbda1, 0xbda2,
+ 0xbda3, 0xbda4, 0xbda5, 0xbda6, 0xbda7, 0xbda8, 0xbda9, 0xbdaa,
+ 0xbdab, 0xbdac, 0x0000, 0xbdad, 0xbdae, 0xbdaf, 0xbdb0, 0xbdb1,
+ 0xbdb2, 0xbdb3, 0xbdb4, 0xbdb5, 0xbdb6, 0xbdb7, 0x0000, 0x0000,
+ 0x0000, 0xbdb8, 0xbdb9, 0xbdba, 0xbdbb, 0xbdbc, 0xbdbd, 0xbdbe,
+ 0xbdbf, 0xbdc0, 0xbdc1, 0xbdc2, 0xbdc3, 0xbdc4, 0xbdc5, 0xbdc6,
+ 0xbdc7, 0xbdc8, 0x0000, 0xbdc9, 0xbdca, 0xbdcb, 0xbdcc, 0xbdcd,
+ 0xbdce, 0xbdcf, 0xbdd0, 0xbdd1, 0xbdd2, 0xbdd3, 0x0000, 0x0000,
+ 0x0000, 0xbdd4, 0xbdd5, 0xbdd6, 0xbdd7, 0xbdd8, 0xbdd9, 0xbdda,
+ 0xbddb, 0xbddc, 0xbddd, 0xbdde, 0xbddf, 0xbde0, 0xbde1, 0xbde2,
+ 0xbde3, 0xbde4, 0x0000, 0xbde5, 0xbde6, 0xbde7, 0xbde8, 0xbde9,
+ 0xbdea, 0xbdeb, 0xbdec, 0xbded, 0xbdee, 0xbdef, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xbdf0, 0xbdf1, 0xbdf2, 0xbdf3, 0xbdf4, 0xbdf5, 0xbdf6,
+ 0xbdf7, 0xbdf8, 0xbdf9, 0xbdfa, 0xbdfb, 0xbdfc, 0xbdfd, 0xbdfe,
+ 0xbdff, 0xbe00, 0x0000, 0xbe01, 0xbe02, 0xbe03, 0xbe04, 0xbe05,
+ 0xbe06, 0xbe07, 0xbe08, 0xbe09, 0xbe0a, 0xbe0b, 0x0000, 0x0000,
+ 0x0000, 0xbe0c, 0xbe0d, 0xbe0e, 0xbe0f, 0xbe10, 0xbe11, 0xbe12,
+ 0xbe13, 0xbe14, 0xbe15, 0xbe16, 0xbe17, 0xbe18, 0xbe19, 0xbe1a,
+ 0xbe1b, 0xbe1c, 0x0000, 0xbe1d, 0xbe1e, 0xbe1f, 0xbe20, 0xbe21,
+ 0xbe22, 0xbe23, 0xbe24, 0xbe25, 0xbe26, 0xbe27, 0x0000, 0x0000,
+ 0x0000, 0xbe28, 0xbe29, 0xbe2a, 0xbe2b, 0xbe2c, 0xbe2d, 0xbe2e,
+ 0xbe2f, 0xbe30, 0xbe31, 0xbe32, 0xbe33, 0xbe34, 0xbe35, 0xbe36,
+ 0xbe37, 0xbe38, 0x0000, 0xbe39, 0xbe3a, 0xbe3b, 0xbe3c, 0xbe3d,
+ 0xbe3e, 0xbe3f, 0xbe40, 0xbe41, 0xbe42, 0xbe43, 0x0000, 0x0000,
+ 0x0000, 0xbe44, 0xbe45, 0xbe46, 0xbe47, 0xbe48, 0xbe49, 0xbe4a,
+ 0xbe4b, 0xbe4c, 0xbe4d, 0xbe4e, 0xbe4f, 0xbe50, 0xbe51, 0xbe52,
+ 0xbe53, 0xbe54, 0x0000, 0xbe55, 0xbe56, 0xbe57, 0xbe58, 0xbe59,
+ 0xbe5a, 0xbe5b, 0xbe5c, 0xbe5d, 0xbe5e, 0xbe5f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3143, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xbe60, 0xbe61, 0xbe62, 0xbe63, 0xbe64, 0xbe65, 0xbe66,
+ 0xbe67, 0xbe68, 0xbe69, 0xbe6a, 0xbe6b, 0xbe6c, 0xbe6d, 0xbe6e,
+ 0xbe6f, 0xbe70, 0x0000, 0xbe71, 0xbe72, 0xbe73, 0xbe74, 0xbe75,
+ 0xbe76, 0xbe77, 0xbe78, 0xbe79, 0xbe7a, 0xbe7b, 0x0000, 0x0000,
+ 0x0000, 0xbe7c, 0xbe7d, 0xbe7e, 0xbe7f, 0xbe80, 0xbe81, 0xbe82,
+ 0xbe83, 0xbe84, 0xbe85, 0xbe86, 0xbe87, 0xbe88, 0xbe89, 0xbe8a,
+ 0xbe8b, 0xbe8c, 0x0000, 0xbe8d, 0xbe8e, 0xbe8f, 0xbe90, 0xbe91,
+ 0xbe92, 0xbe93, 0xbe94, 0xbe95, 0xbe96, 0xbe97, 0x0000, 0x0000,
+ 0x0000, 0xbe98, 0xbe99, 0xbe9a, 0xbe9b, 0xbe9c, 0xbe9d, 0xbe9e,
+ 0xbe9f, 0xbea0, 0xbea1, 0xbea2, 0xbea3, 0xbea4, 0xbea5, 0xbea6,
+ 0xbea7, 0xbea8, 0x0000, 0xbea9, 0xbeaa, 0xbeab, 0xbeac, 0xbead,
+ 0xbeae, 0xbeaf, 0xbeb0, 0xbeb1, 0xbeb2, 0xbeb3, 0x0000, 0x0000,
+ 0x0000, 0xbeb4, 0xbeb5, 0xbeb6, 0xbeb7, 0xbeb8, 0xbeb9, 0xbeba,
+ 0xbebb, 0xbebc, 0xbebd, 0xbebe, 0xbebf, 0xbec0, 0xbec1, 0xbec2,
+ 0xbec3, 0xbec4, 0x0000, 0xbec5, 0xbec6, 0xbec7, 0xbec8, 0xbec9,
+ 0xbeca, 0xbecb, 0xbecc, 0xbecd, 0xbece, 0xbecf, 0x0000, 0x0000,
+ 0x0000, 0xbed0, 0xbed1, 0xbed2, 0xbed3, 0xbed4, 0xbed5, 0xbed6,
+ 0xbed7, 0xbed8, 0xbed9, 0xbeda, 0xbedb, 0xbedc, 0xbedd, 0xbede,
+ 0xbedf, 0xbee0, 0x0000, 0xbee1, 0xbee2, 0xbee3, 0xbee4, 0xbee5,
+ 0xbee6, 0xbee7, 0xbee8, 0xbee9, 0xbeea, 0xbeeb, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xbeec, 0xbeed, 0xbeee, 0xbeef, 0xbef0, 0xbef1, 0xbef2,
+ 0xbef3, 0xbef4, 0xbef5, 0xbef6, 0xbef7, 0xbef8, 0xbef9, 0xbefa,
+ 0xbefb, 0xbefc, 0x0000, 0xbefd, 0xbefe, 0xbeff, 0xbf00, 0xbf01,
+ 0xbf02, 0xbf03, 0xbf04, 0xbf05, 0xbf06, 0xbf07, 0x0000, 0x0000,
+ 0x0000, 0xbf08, 0xbf09, 0xbf0a, 0xbf0b, 0xbf0c, 0xbf0d, 0xbf0e,
+ 0xbf0f, 0xbf10, 0xbf11, 0xbf12, 0xbf13, 0xbf14, 0xbf15, 0xbf16,
+ 0xbf17, 0xbf18, 0x0000, 0xbf19, 0xbf1a, 0xbf1b, 0xbf1c, 0xbf1d,
+ 0xbf1e, 0xbf1f, 0xbf20, 0xbf21, 0xbf22, 0xbf23, 0x0000, 0x0000,
+ 0x0000, 0xbf24, 0xbf25, 0xbf26, 0xbf27, 0xbf28, 0xbf29, 0xbf2a,
+ 0xbf2b, 0xbf2c, 0xbf2d, 0xbf2e, 0xbf2f, 0xbf30, 0xbf31, 0xbf32,
+ 0xbf33, 0xbf34, 0x0000, 0xbf35, 0xbf36, 0xbf37, 0xbf38, 0xbf39,
+ 0xbf3a, 0xbf3b, 0xbf3c, 0xbf3d, 0xbf3e, 0xbf3f, 0x0000, 0x0000,
+ 0x0000, 0xbf40, 0xbf41, 0xbf42, 0xbf43, 0xbf44, 0xbf45, 0xbf46,
+ 0xbf47, 0xbf48, 0xbf49, 0xbf4a, 0xbf4b, 0xbf4c, 0xbf4d, 0xbf4e,
+ 0xbf4f, 0xbf50, 0x0000, 0xbf51, 0xbf52, 0xbf53, 0xbf54, 0xbf55,
+ 0xbf56, 0xbf57, 0xbf58, 0xbf59, 0xbf5a, 0xbf5b, 0x0000, 0x0000,
+ 0x0000, 0xbf5c, 0xbf5d, 0xbf5e, 0xbf5f, 0xbf60, 0xbf61, 0xbf62,
+ 0xbf63, 0xbf64, 0xbf65, 0xbf66, 0xbf67, 0xbf68, 0xbf69, 0xbf6a,
+ 0xbf6b, 0xbf6c, 0x0000, 0xbf6d, 0xbf6e, 0xbf6f, 0xbf70, 0xbf71,
+ 0xbf72, 0xbf73, 0xbf74, 0xbf75, 0xbf76, 0xbf77, 0x0000, 0x0000,
+ 0x0000, 0xbf78, 0xbf79, 0xbf7a, 0xbf7b, 0xbf7c, 0xbf7d, 0xbf7e,
+ 0xbf7f, 0xbf80, 0xbf81, 0xbf82, 0xbf83, 0xbf84, 0xbf85, 0xbf86,
+ 0xbf87, 0xbf88, 0x0000, 0xbf89, 0xbf8a, 0xbf8b, 0xbf8c, 0xbf8d,
+ 0xbf8e, 0xbf8f, 0xbf90, 0xbf91, 0xbf92, 0xbf93, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xbf94, 0xbf95, 0xbf96, 0xbf97, 0xbf98, 0xbf99, 0xbf9a,
+ 0xbf9b, 0xbf9c, 0xbf9d, 0xbf9e, 0xbf9f, 0xbfa0, 0xbfa1, 0xbfa2,
+ 0xbfa3, 0xbfa4, 0x0000, 0xbfa5, 0xbfa6, 0xbfa7, 0xbfa8, 0xbfa9,
+ 0xbfaa, 0xbfab, 0xbfac, 0xbfad, 0xbfae, 0xbfaf, 0x0000, 0x0000,
+ 0x0000, 0xbfb0, 0xbfb1, 0xbfb2, 0xbfb3, 0xbfb4, 0xbfb5, 0xbfb6,
+ 0xbfb7, 0xbfb8, 0xbfb9, 0xbfba, 0xbfbb, 0xbfbc, 0xbfbd, 0xbfbe,
+ 0xbfbf, 0xbfc0, 0x0000, 0xbfc1, 0xbfc2, 0xbfc3, 0xbfc4, 0xbfc5,
+ 0xbfc6, 0xbfc7, 0xbfc8, 0xbfc9, 0xbfca, 0xbfcb, 0x0000, 0x0000,
+ 0x0000, 0xbfcc, 0xbfcd, 0xbfce, 0xbfcf, 0xbfd0, 0xbfd1, 0xbfd2,
+ 0xbfd3, 0xbfd4, 0xbfd5, 0xbfd6, 0xbfd7, 0xbfd8, 0xbfd9, 0xbfda,
+ 0xbfdb, 0xbfdc, 0x0000, 0xbfdd, 0xbfde, 0xbfdf, 0xbfe0, 0xbfe1,
+ 0xbfe2, 0xbfe3, 0xbfe4, 0xbfe5, 0xbfe6, 0xbfe7, 0x0000, 0x0000,
+ 0x0000, 0xbfe8, 0xbfe9, 0xbfea, 0xbfeb, 0xbfec, 0xbfed, 0xbfee,
+ 0xbfef, 0xbff0, 0xbff1, 0xbff2, 0xbff3, 0xbff4, 0xbff5, 0xbff6,
+ 0xbff7, 0xbff8, 0x0000, 0xbff9, 0xbffa, 0xbffb, 0xbffc, 0xbffd,
+ 0xbffe, 0xbfff, 0xc000, 0xc001, 0xc002, 0xc003, 0x0000, 0x0000,
+ 0x0000, 0xc004, 0xc005, 0xc006, 0xc007, 0xc008, 0xc009, 0xc00a,
+ 0xc00b, 0xc00c, 0xc00d, 0xc00e, 0xc00f, 0xc010, 0xc011, 0xc012,
+ 0xc013, 0xc014, 0x0000, 0xc015, 0xc016, 0xc017, 0xc018, 0xc019,
+ 0xc01a, 0xc01b, 0xc01c, 0xc01d, 0xc01e, 0xc01f, 0x0000, 0x0000,
+ 0x0000, 0xc020, 0xc021, 0xc022, 0xc023, 0xc024, 0xc025, 0xc026,
+ 0xc027, 0xc028, 0xc029, 0xc02a, 0xc02b, 0xc02c, 0xc02d, 0xc02e,
+ 0xc02f, 0xc030, 0x0000, 0xc031, 0xc032, 0xc033, 0xc034, 0xc035,
+ 0xc036, 0xc037, 0xc038, 0xc039, 0xc03a, 0xc03b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc03c, 0xc03d, 0xc03e, 0xc03f, 0xc040, 0xc041, 0xc042,
+ 0xc043, 0xc044, 0xc045, 0xc046, 0xc047, 0xc048, 0xc049, 0xc04a,
+ 0xc04b, 0xc04c, 0x0000, 0xc04d, 0xc04e, 0xc04f, 0xc050, 0xc051,
+ 0xc052, 0xc053, 0xc054, 0xc055, 0xc056, 0xc057, 0x0000, 0x0000,
+ 0x0000, 0xc058, 0xc059, 0xc05a, 0xc05b, 0xc05c, 0xc05d, 0xc05e,
+ 0xc05f, 0xc060, 0xc061, 0xc062, 0xc063, 0xc064, 0xc065, 0xc066,
+ 0xc067, 0xc068, 0x0000, 0xc069, 0xc06a, 0xc06b, 0xc06c, 0xc06d,
+ 0xc06e, 0xc06f, 0xc070, 0xc071, 0xc072, 0xc073, 0x0000, 0x0000,
+ 0x0000, 0xc074, 0xc075, 0xc076, 0xc077, 0xc078, 0xc079, 0xc07a,
+ 0xc07b, 0xc07c, 0xc07d, 0xc07e, 0xc07f, 0xc080, 0xc081, 0xc082,
+ 0xc083, 0xc084, 0x0000, 0xc085, 0xc086, 0xc087, 0xc088, 0xc089,
+ 0xc08a, 0xc08b, 0xc08c, 0xc08d, 0xc08e, 0xc08f, 0x0000, 0x0000,
+ 0x0000, 0xc090, 0xc091, 0xc092, 0xc093, 0xc094, 0xc095, 0xc096,
+ 0xc097, 0xc098, 0xc099, 0xc09a, 0xc09b, 0xc09c, 0xc09d, 0xc09e,
+ 0xc09f, 0xc0a0, 0x0000, 0xc0a1, 0xc0a2, 0xc0a3, 0xc0a4, 0xc0a5,
+ 0xc0a6, 0xc0a7, 0xc0a8, 0xc0a9, 0xc0aa, 0xc0ab, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc0ac, 0xc0ad, 0xc0ae, 0xc0af, 0xc0b0, 0xc0b1, 0xc0b2,
+ 0xc0b3, 0xc0b4, 0xc0b5, 0xc0b6, 0xc0b7, 0xc0b8, 0xc0b9, 0xc0ba,
+ 0xc0bb, 0xc0bc, 0x0000, 0xc0bd, 0xc0be, 0xc0bf, 0xc0c0, 0xc0c1,
+ 0xc0c2, 0xc0c3, 0xc0c4, 0xc0c5, 0xc0c6, 0xc0c7, 0x0000, 0x0000,
+ 0x0000, 0xc0c8, 0xc0c9, 0xc0ca, 0xc0cb, 0xc0cc, 0xc0cd, 0xc0ce,
+ 0xc0cf, 0xc0d0, 0xc0d1, 0xc0d2, 0xc0d3, 0xc0d4, 0xc0d5, 0xc0d6,
+ 0xc0d7, 0xc0d8, 0x0000, 0xc0d9, 0xc0da, 0xc0db, 0xc0dc, 0xc0dd,
+ 0xc0de, 0xc0df, 0xc0e0, 0xc0e1, 0xc0e2, 0xc0e3, 0x0000, 0x0000,
+ 0x0000, 0xc0e4, 0xc0e5, 0xc0e6, 0xc0e7, 0xc0e8, 0xc0e9, 0xc0ea,
+ 0xc0eb, 0xc0ec, 0xc0ed, 0xc0ee, 0xc0ef, 0xc0f0, 0xc0f1, 0xc0f2,
+ 0xc0f3, 0xc0f4, 0x0000, 0xc0f5, 0xc0f6, 0xc0f7, 0xc0f8, 0xc0f9,
+ 0xc0fa, 0xc0fb, 0xc0fc, 0xc0fd, 0xc0fe, 0xc0ff, 0x0000, 0x0000,
+ 0x0000, 0xc100, 0xc101, 0xc102, 0xc103, 0xc104, 0xc105, 0xc106,
+ 0xc107, 0xc108, 0xc109, 0xc10a, 0xc10b, 0xc10c, 0xc10d, 0xc10e,
+ 0xc10f, 0xc110, 0x0000, 0xc111, 0xc112, 0xc113, 0xc114, 0xc115,
+ 0xc116, 0xc117, 0xc118, 0xc119, 0xc11a, 0xc11b, 0x0000, 0x0000,
+ 0x0000, 0xc11c, 0xc11d, 0xc11e, 0xc11f, 0xc120, 0xc121, 0xc122,
+ 0xc123, 0xc124, 0xc125, 0xc126, 0xc127, 0xc128, 0xc129, 0xc12a,
+ 0xc12b, 0xc12c, 0x0000, 0xc12d, 0xc12e, 0xc12f, 0xc130, 0xc131,
+ 0xc132, 0xc133, 0xc134, 0xc135, 0xc136, 0xc137, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc138, 0xc139, 0xc13a, 0xc13b, 0xc13c, 0xc13d, 0xc13e,
+ 0xc13f, 0xc140, 0xc141, 0xc142, 0xc143, 0xc144, 0xc145, 0xc146,
+ 0xc147, 0xc148, 0x0000, 0xc149, 0xc14a, 0xc14b, 0xc14c, 0xc14d,
+ 0xc14e, 0xc14f, 0xc150, 0xc151, 0xc152, 0xc153, 0x0000, 0x0000,
+ 0x0000, 0xc154, 0xc155, 0xc156, 0xc157, 0xc158, 0xc159, 0xc15a,
+ 0xc15b, 0xc15c, 0xc15d, 0xc15e, 0xc15f, 0xc160, 0xc161, 0xc162,
+ 0xc163, 0xc164, 0x0000, 0xc165, 0xc166, 0xc167, 0xc168, 0xc169,
+ 0xc16a, 0xc16b, 0xc16c, 0xc16d, 0xc16e, 0xc16f, 0x0000, 0x0000,
+ 0x0000, 0xc170, 0xc171, 0xc172, 0xc173, 0xc174, 0xc175, 0xc176,
+ 0xc177, 0xc178, 0xc179, 0xc17a, 0xc17b, 0xc17c, 0xc17d, 0xc17e,
+ 0xc17f, 0xc180, 0x0000, 0xc181, 0xc182, 0xc183, 0xc184, 0xc185,
+ 0xc186, 0xc187, 0xc188, 0xc189, 0xc18a, 0xc18b, 0x0000, 0x0000,
+ 0x0000, 0xc18c, 0xc18d, 0xc18e, 0xc18f, 0xc190, 0xc191, 0xc192,
+ 0xc193, 0xc194, 0xc195, 0xc196, 0xc197, 0xc198, 0xc199, 0xc19a,
+ 0xc19b, 0xc19c, 0x0000, 0xc19d, 0xc19e, 0xc19f, 0xc1a0, 0xc1a1,
+ 0xc1a2, 0xc1a3, 0xc1a4, 0xc1a5, 0xc1a6, 0xc1a7, 0x0000, 0x0000,
+ 0x0000, 0xc1a8, 0xc1a9, 0xc1aa, 0xc1ab, 0xc1ac, 0xc1ad, 0xc1ae,
+ 0xc1af, 0xc1b0, 0xc1b1, 0xc1b2, 0xc1b3, 0xc1b4, 0xc1b5, 0xc1b6,
+ 0xc1b7, 0xc1b8, 0x0000, 0xc1b9, 0xc1ba, 0xc1bb, 0xc1bc, 0xc1bd,
+ 0xc1be, 0xc1bf, 0xc1c0, 0xc1c1, 0xc1c2, 0xc1c3, 0x0000, 0x0000,
+ 0x0000, 0xc1c4, 0xc1c5, 0xc1c6, 0xc1c7, 0xc1c8, 0xc1c9, 0xc1ca,
+ 0xc1cb, 0xc1cc, 0xc1cd, 0xc1ce, 0xc1cf, 0xc1d0, 0xc1d1, 0xc1d2,
+ 0xc1d3, 0xc1d4, 0x0000, 0xc1d5, 0xc1d6, 0xc1d7, 0xc1d8, 0xc1d9,
+ 0xc1da, 0xc1db, 0xc1dc, 0xc1dd, 0xc1de, 0xc1df, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc1e0, 0xc1e1, 0xc1e2, 0xc1e3, 0xc1e4, 0xc1e5, 0xc1e6,
+ 0xc1e7, 0xc1e8, 0xc1e9, 0xc1ea, 0xc1eb, 0xc1ec, 0xc1ed, 0xc1ee,
+ 0xc1ef, 0xc1f0, 0x0000, 0xc1f1, 0xc1f2, 0xc1f3, 0xc1f4, 0xc1f5,
+ 0xc1f6, 0xc1f7, 0xc1f8, 0xc1f9, 0xc1fa, 0xc1fb, 0x0000, 0x0000,
+ 0x0000, 0xc1fc, 0xc1fd, 0xc1fe, 0xc1ff, 0xc200, 0xc201, 0xc202,
+ 0xc203, 0xc204, 0xc205, 0xc206, 0xc207, 0xc208, 0xc209, 0xc20a,
+ 0xc20b, 0xc20c, 0x0000, 0xc20d, 0xc20e, 0xc20f, 0xc210, 0xc211,
+ 0xc212, 0xc213, 0xc214, 0xc215, 0xc216, 0xc217, 0x0000, 0x0000,
+ 0x0000, 0xc218, 0xc219, 0xc21a, 0xc21b, 0xc21c, 0xc21d, 0xc21e,
+ 0xc21f, 0xc220, 0xc221, 0xc222, 0xc223, 0xc224, 0xc225, 0xc226,
+ 0xc227, 0xc228, 0x0000, 0xc229, 0xc22a, 0xc22b, 0xc22c, 0xc22d,
+ 0xc22e, 0xc22f, 0xc230, 0xc231, 0xc232, 0xc233, 0x0000, 0x0000,
+ 0x0000, 0xc234, 0xc235, 0xc236, 0xc237, 0xc238, 0xc239, 0xc23a,
+ 0xc23b, 0xc23c, 0xc23d, 0xc23e, 0xc23f, 0xc240, 0xc241, 0xc242,
+ 0xc243, 0xc244, 0x0000, 0xc245, 0xc246, 0xc247, 0xc248, 0xc249,
+ 0xc24a, 0xc24b, 0xc24c, 0xc24d, 0xc24e, 0xc24f, 0x0000, 0x0000,
+ 0x0000, 0xc250, 0xc251, 0xc252, 0xc253, 0xc254, 0xc255, 0xc256,
+ 0xc257, 0xc258, 0xc259, 0xc25a, 0xc25b, 0xc25c, 0xc25d, 0xc25e,
+ 0xc25f, 0xc260, 0x0000, 0xc261, 0xc262, 0xc263, 0xc264, 0xc265,
+ 0xc266, 0xc267, 0xc268, 0xc269, 0xc26a, 0xc26b, 0x0000, 0x0000,
+ 0x0000, 0xc26c, 0xc26d, 0xc26e, 0xc26f, 0xc270, 0xc271, 0xc272,
+ 0xc273, 0xc274, 0xc275, 0xc276, 0xc277, 0xc278, 0xc279, 0xc27a,
+ 0xc27b, 0xc27c, 0x0000, 0xc27d, 0xc27e, 0xc27f, 0xc280, 0xc281,
+ 0xc282, 0xc283, 0xc284, 0xc285, 0xc286, 0xc287, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc288, 0xc289, 0xc28a, 0xc28b, 0xc28c, 0xc28d, 0xc28e,
+ 0xc28f, 0xc290, 0xc291, 0xc292, 0xc293, 0xc294, 0xc295, 0xc296,
+ 0xc297, 0xc298, 0x0000, 0xc299, 0xc29a, 0xc29b, 0xc29c, 0xc29d,
+ 0xc29e, 0xc29f, 0xc2a0, 0xc2a1, 0xc2a2, 0xc2a3, 0x0000, 0x0000,
+ 0x0000, 0xc2a4, 0xc2a5, 0xc2a6, 0xc2a7, 0xc2a8, 0xc2a9, 0xc2aa,
+ 0xc2ab, 0xc2ac, 0xc2ad, 0xc2ae, 0xc2af, 0xc2b0, 0xc2b1, 0xc2b2,
+ 0xc2b3, 0xc2b4, 0x0000, 0xc2b5, 0xc2b6, 0xc2b7, 0xc2b8, 0xc2b9,
+ 0xc2ba, 0xc2bb, 0xc2bc, 0xc2bd, 0xc2be, 0xc2bf, 0x0000, 0x0000,
+ 0x0000, 0xc2c0, 0xc2c1, 0xc2c2, 0xc2c3, 0xc2c4, 0xc2c5, 0xc2c6,
+ 0xc2c7, 0xc2c8, 0xc2c9, 0xc2ca, 0xc2cb, 0xc2cc, 0xc2cd, 0xc2ce,
+ 0xc2cf, 0xc2d0, 0x0000, 0xc2d1, 0xc2d2, 0xc2d3, 0xc2d4, 0xc2d5,
+ 0xc2d6, 0xc2d7, 0xc2d8, 0xc2d9, 0xc2da, 0xc2db, 0x0000, 0x0000,
+ 0x0000, 0xc2dc, 0xc2dd, 0xc2de, 0xc2df, 0xc2e0, 0xc2e1, 0xc2e2,
+ 0xc2e3, 0xc2e4, 0xc2e5, 0xc2e6, 0xc2e7, 0xc2e8, 0xc2e9, 0xc2ea,
+ 0xc2eb, 0xc2ec, 0x0000, 0xc2ed, 0xc2ee, 0xc2ef, 0xc2f0, 0xc2f1,
+ 0xc2f2, 0xc2f3, 0xc2f4, 0xc2f5, 0xc2f6, 0xc2f7, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc2f8, 0xc2f9, 0xc2fa, 0xc2fb, 0xc2fc, 0xc2fd, 0xc2fe,
+ 0xc2ff, 0xc300, 0xc301, 0xc302, 0xc303, 0xc304, 0xc305, 0xc306,
+ 0xc307, 0xc308, 0x0000, 0xc309, 0xc30a, 0xc30b, 0xc30c, 0xc30d,
+ 0xc30e, 0xc30f, 0xc310, 0xc311, 0xc312, 0xc313, 0x0000, 0x0000,
+ 0x0000, 0xc314, 0xc315, 0xc316, 0xc317, 0xc318, 0xc319, 0xc31a,
+ 0xc31b, 0xc31c, 0xc31d, 0xc31e, 0xc31f, 0xc320, 0xc321, 0xc322,
+ 0xc323, 0xc324, 0x0000, 0xc325, 0xc326, 0xc327, 0xc328, 0xc329,
+ 0xc32a, 0xc32b, 0xc32c, 0xc32d, 0xc32e, 0xc32f, 0x0000, 0x0000,
+ 0x0000, 0xc330, 0xc331, 0xc332, 0xc333, 0xc334, 0xc335, 0xc336,
+ 0xc337, 0xc338, 0xc339, 0xc33a, 0xc33b, 0xc33c, 0xc33d, 0xc33e,
+ 0xc33f, 0xc340, 0x0000, 0xc341, 0xc342, 0xc343, 0xc344, 0xc345,
+ 0xc346, 0xc347, 0xc348, 0xc349, 0xc34a, 0xc34b, 0x0000, 0x0000,
+ 0x0000, 0xc34c, 0xc34d, 0xc34e, 0xc34f, 0xc350, 0xc351, 0xc352,
+ 0xc353, 0xc354, 0xc355, 0xc356, 0xc357, 0xc358, 0xc359, 0xc35a,
+ 0xc35b, 0xc35c, 0x0000, 0xc35d, 0xc35e, 0xc35f, 0xc360, 0xc361,
+ 0xc362, 0xc363, 0xc364, 0xc365, 0xc366, 0xc367, 0x0000, 0x0000,
+ 0x0000, 0xc368, 0xc369, 0xc36a, 0xc36b, 0xc36c, 0xc36d, 0xc36e,
+ 0xc36f, 0xc370, 0xc371, 0xc372, 0xc373, 0xc374, 0xc375, 0xc376,
+ 0xc377, 0xc378, 0x0000, 0xc379, 0xc37a, 0xc37b, 0xc37c, 0xc37d,
+ 0xc37e, 0xc37f, 0xc380, 0xc381, 0xc382, 0xc383, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc384, 0xc385, 0xc386, 0xc387, 0xc388, 0xc389, 0xc38a,
+ 0xc38b, 0xc38c, 0xc38d, 0xc38e, 0xc38f, 0xc390, 0xc391, 0xc392,
+ 0xc393, 0xc394, 0x0000, 0xc395, 0xc396, 0xc397, 0xc398, 0xc399,
+ 0xc39a, 0xc39b, 0xc39c, 0xc39d, 0xc39e, 0xc39f, 0x0000, 0x0000,
+ 0x0000, 0xc3a0, 0xc3a1, 0xc3a2, 0xc3a3, 0xc3a4, 0xc3a5, 0xc3a6,
+ 0xc3a7, 0xc3a8, 0xc3a9, 0xc3aa, 0xc3ab, 0xc3ac, 0xc3ad, 0xc3ae,
+ 0xc3af, 0xc3b0, 0x0000, 0xc3b1, 0xc3b2, 0xc3b3, 0xc3b4, 0xc3b5,
+ 0xc3b6, 0xc3b7, 0xc3b8, 0xc3b9, 0xc3ba, 0xc3bb, 0x0000, 0x0000,
+ 0x0000, 0xc3bc, 0xc3bd, 0xc3be, 0xc3bf, 0xc3c0, 0xc3c1, 0xc3c2,
+ 0xc3c3, 0xc3c4, 0xc3c5, 0xc3c6, 0xc3c7, 0xc3c8, 0xc3c9, 0xc3ca,
+ 0xc3cb, 0xc3cc, 0x0000, 0xc3cd, 0xc3ce, 0xc3cf, 0xc3d0, 0xc3d1,
+ 0xc3d2, 0xc3d3, 0xc3d4, 0xc3d5, 0xc3d6, 0xc3d7, 0x0000, 0x0000,
+ 0x0000, 0xc3d8, 0xc3d9, 0xc3da, 0xc3db, 0xc3dc, 0xc3dd, 0xc3de,
+ 0xc3df, 0xc3e0, 0xc3e1, 0xc3e2, 0xc3e3, 0xc3e4, 0xc3e5, 0xc3e6,
+ 0xc3e7, 0xc3e8, 0x0000, 0xc3e9, 0xc3ea, 0xc3eb, 0xc3ec, 0xc3ed,
+ 0xc3ee, 0xc3ef, 0xc3f0, 0xc3f1, 0xc3f2, 0xc3f3, 0x0000, 0x0000,
+ 0x0000, 0xc3f4, 0xc3f5, 0xc3f6, 0xc3f7, 0xc3f8, 0xc3f9, 0xc3fa,
+ 0xc3fb, 0xc3fc, 0xc3fd, 0xc3fe, 0xc3ff, 0xc400, 0xc401, 0xc402,
+ 0xc403, 0xc404, 0x0000, 0xc405, 0xc406, 0xc407, 0xc408, 0xc409,
+ 0xc40a, 0xc40b, 0xc40c, 0xc40d, 0xc40e, 0xc40f, 0x0000, 0x0000,
+ 0x0000, 0xc410, 0xc411, 0xc412, 0xc413, 0xc414, 0xc415, 0xc416,
+ 0xc417, 0xc418, 0xc419, 0xc41a, 0xc41b, 0xc41c, 0xc41d, 0xc41e,
+ 0xc41f, 0xc420, 0x0000, 0xc421, 0xc422, 0xc423, 0xc424, 0xc425,
+ 0xc426, 0xc427, 0xc428, 0xc429, 0xc42a, 0xc42b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc42c, 0xc42d, 0xc42e, 0xc42f, 0xc430, 0xc431, 0xc432,
+ 0xc433, 0xc434, 0xc435, 0xc436, 0xc437, 0xc438, 0xc439, 0xc43a,
+ 0xc43b, 0xc43c, 0x0000, 0xc43d, 0xc43e, 0xc43f, 0xc440, 0xc441,
+ 0xc442, 0xc443, 0xc444, 0xc445, 0xc446, 0xc447, 0x0000, 0x0000,
+ 0x0000, 0xc448, 0xc449, 0xc44a, 0xc44b, 0xc44c, 0xc44d, 0xc44e,
+ 0xc44f, 0xc450, 0xc451, 0xc452, 0xc453, 0xc454, 0xc455, 0xc456,
+ 0xc457, 0xc458, 0x0000, 0xc459, 0xc45a, 0xc45b, 0xc45c, 0xc45d,
+ 0xc45e, 0xc45f, 0xc460, 0xc461, 0xc462, 0xc463, 0x0000, 0x0000,
+ 0x0000, 0xc464, 0xc465, 0xc466, 0xc467, 0xc468, 0xc469, 0xc46a,
+ 0xc46b, 0xc46c, 0xc46d, 0xc46e, 0xc46f, 0xc470, 0xc471, 0xc472,
+ 0xc473, 0xc474, 0x0000, 0xc475, 0xc476, 0xc477, 0xc478, 0xc479,
+ 0xc47a, 0xc47b, 0xc47c, 0xc47d, 0xc47e, 0xc47f, 0x0000, 0x0000,
+ 0x0000, 0xc480, 0xc481, 0xc482, 0xc483, 0xc484, 0xc485, 0xc486,
+ 0xc487, 0xc488, 0xc489, 0xc48a, 0xc48b, 0xc48c, 0xc48d, 0xc48e,
+ 0xc48f, 0xc490, 0x0000, 0xc491, 0xc492, 0xc493, 0xc494, 0xc495,
+ 0xc496, 0xc497, 0xc498, 0xc499, 0xc49a, 0xc49b, 0x0000, 0x0000,
+ 0x0000, 0xc49c, 0xc49d, 0xc49e, 0xc49f, 0xc4a0, 0xc4a1, 0xc4a2,
+ 0xc4a3, 0xc4a4, 0xc4a5, 0xc4a6, 0xc4a7, 0xc4a8, 0xc4a9, 0xc4aa,
+ 0xc4ab, 0xc4ac, 0x0000, 0xc4ad, 0xc4ae, 0xc4af, 0xc4b0, 0xc4b1,
+ 0xc4b2, 0xc4b3, 0xc4b4, 0xc4b5, 0xc4b6, 0xc4b7, 0x0000, 0x0000,
+ 0x0000, 0xc4b8, 0xc4b9, 0xc4ba, 0xc4bb, 0xc4bc, 0xc4bd, 0xc4be,
+ 0xc4bf, 0xc4c0, 0xc4c1, 0xc4c2, 0xc4c3, 0xc4c4, 0xc4c5, 0xc4c6,
+ 0xc4c7, 0xc4c8, 0x0000, 0xc4c9, 0xc4ca, 0xc4cb, 0xc4cc, 0xc4cd,
+ 0xc4ce, 0xc4cf, 0xc4d0, 0xc4d1, 0xc4d2, 0xc4d3, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc4d4, 0xc4d5, 0xc4d6, 0xc4d7, 0xc4d8, 0xc4d9, 0xc4da,
+ 0xc4db, 0xc4dc, 0xc4dd, 0xc4de, 0xc4df, 0xc4e0, 0xc4e1, 0xc4e2,
+ 0xc4e3, 0xc4e4, 0x0000, 0xc4e5, 0xc4e6, 0xc4e7, 0xc4e8, 0xc4e9,
+ 0xc4ea, 0xc4eb, 0xc4ec, 0xc4ed, 0xc4ee, 0xc4ef, 0x0000, 0x0000,
+ 0x0000, 0xc4f0, 0xc4f1, 0xc4f2, 0xc4f3, 0xc4f4, 0xc4f5, 0xc4f6,
+ 0xc4f7, 0xc4f8, 0xc4f9, 0xc4fa, 0xc4fb, 0xc4fc, 0xc4fd, 0xc4fe,
+ 0xc4ff, 0xc500, 0x0000, 0xc501, 0xc502, 0xc503, 0xc504, 0xc505,
+ 0xc506, 0xc507, 0xc508, 0xc509, 0xc50a, 0xc50b, 0x0000, 0x0000,
+ 0x0000, 0xc50c, 0xc50d, 0xc50e, 0xc50f, 0xc510, 0xc511, 0xc512,
+ 0xc513, 0xc514, 0xc515, 0xc516, 0xc517, 0xc518, 0xc519, 0xc51a,
+ 0xc51b, 0xc51c, 0x0000, 0xc51d, 0xc51e, 0xc51f, 0xc520, 0xc521,
+ 0xc522, 0xc523, 0xc524, 0xc525, 0xc526, 0xc527, 0x0000, 0x0000,
+ 0x0000, 0xc528, 0xc529, 0xc52a, 0xc52b, 0xc52c, 0xc52d, 0xc52e,
+ 0xc52f, 0xc530, 0xc531, 0xc532, 0xc533, 0xc534, 0xc535, 0xc536,
+ 0xc537, 0xc538, 0x0000, 0xc539, 0xc53a, 0xc53b, 0xc53c, 0xc53d,
+ 0xc53e, 0xc53f, 0xc540, 0xc541, 0xc542, 0xc543, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc544, 0xc545, 0xc546, 0xc547, 0xc548, 0xc549, 0xc54a,
+ 0xc54b, 0xc54c, 0xc54d, 0xc54e, 0xc54f, 0xc550, 0xc551, 0xc552,
+ 0xc553, 0xc554, 0x0000, 0xc555, 0xc556, 0xc557, 0xc558, 0xc559,
+ 0xc55a, 0xc55b, 0xc55c, 0xc55d, 0xc55e, 0xc55f, 0x0000, 0x0000,
+ 0x0000, 0xc560, 0xc561, 0xc562, 0xc563, 0xc564, 0xc565, 0xc566,
+ 0xc567, 0xc568, 0xc569, 0xc56a, 0xc56b, 0xc56c, 0xc56d, 0xc56e,
+ 0xc56f, 0xc570, 0x0000, 0xc571, 0xc572, 0xc573, 0xc574, 0xc575,
+ 0xc576, 0xc577, 0xc578, 0xc579, 0xc57a, 0xc57b, 0x0000, 0x0000,
+ 0x0000, 0xc57c, 0xc57d, 0xc57e, 0xc57f, 0xc580, 0xc581, 0xc582,
+ 0xc583, 0xc584, 0xc585, 0xc586, 0xc587, 0xc588, 0xc589, 0xc58a,
+ 0xc58b, 0xc58c, 0x0000, 0xc58d, 0xc58e, 0xc58f, 0xc590, 0xc591,
+ 0xc592, 0xc593, 0xc594, 0xc595, 0xc596, 0xc597, 0x0000, 0x0000,
+ 0x0000, 0xc598, 0xc599, 0xc59a, 0xc59b, 0xc59c, 0xc59d, 0xc59e,
+ 0xc59f, 0xc5a0, 0xc5a1, 0xc5a2, 0xc5a3, 0xc5a4, 0xc5a5, 0xc5a6,
+ 0xc5a7, 0xc5a8, 0x0000, 0xc5a9, 0xc5aa, 0xc5ab, 0xc5ac, 0xc5ad,
+ 0xc5ae, 0xc5af, 0xc5b0, 0xc5b1, 0xc5b2, 0xc5b3, 0x0000, 0x0000,
+ 0x0000, 0xc5b4, 0xc5b5, 0xc5b6, 0xc5b7, 0xc5b8, 0xc5b9, 0xc5ba,
+ 0xc5bb, 0xc5bc, 0xc5bd, 0xc5be, 0xc5bf, 0xc5c0, 0xc5c1, 0xc5c2,
+ 0xc5c3, 0xc5c4, 0x0000, 0xc5c5, 0xc5c6, 0xc5c7, 0xc5c8, 0xc5c9,
+ 0xc5ca, 0xc5cb, 0xc5cc, 0xc5cd, 0xc5ce, 0xc5cf, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc5d0, 0xc5d1, 0xc5d2, 0xc5d3, 0xc5d4, 0xc5d5, 0xc5d6,
+ 0xc5d7, 0xc5d8, 0xc5d9, 0xc5da, 0xc5db, 0xc5dc, 0xc5dd, 0xc5de,
+ 0xc5df, 0xc5e0, 0x0000, 0xc5e1, 0xc5e2, 0xc5e3, 0xc5e4, 0xc5e5,
+ 0xc5e6, 0xc5e7, 0xc5e8, 0xc5e9, 0xc5ea, 0xc5eb, 0x0000, 0x0000,
+ 0x0000, 0xc5ec, 0xc5ed, 0xc5ee, 0xc5ef, 0xc5f0, 0xc5f1, 0xc5f2,
+ 0xc5f3, 0xc5f4, 0xc5f5, 0xc5f6, 0xc5f7, 0xc5f8, 0xc5f9, 0xc5fa,
+ 0xc5fb, 0xc5fc, 0x0000, 0xc5fd, 0xc5fe, 0xc5ff, 0xc600, 0xc601,
+ 0xc602, 0xc603, 0xc604, 0xc605, 0xc606, 0xc607, 0x0000, 0x0000,
+ 0x0000, 0xc608, 0xc609, 0xc60a, 0xc60b, 0xc60c, 0xc60d, 0xc60e,
+ 0xc60f, 0xc610, 0xc611, 0xc612, 0xc613, 0xc614, 0xc615, 0xc616,
+ 0xc617, 0xc618, 0x0000, 0xc619, 0xc61a, 0xc61b, 0xc61c, 0xc61d,
+ 0xc61e, 0xc61f, 0xc620, 0xc621, 0xc622, 0xc623, 0x0000, 0x0000,
+ 0x0000, 0xc624, 0xc625, 0xc626, 0xc627, 0xc628, 0xc629, 0xc62a,
+ 0xc62b, 0xc62c, 0xc62d, 0xc62e, 0xc62f, 0xc630, 0xc631, 0xc632,
+ 0xc633, 0xc634, 0x0000, 0xc635, 0xc636, 0xc637, 0xc638, 0xc639,
+ 0xc63a, 0xc63b, 0xc63c, 0xc63d, 0xc63e, 0xc63f, 0x0000, 0x0000,
+ 0x0000, 0xc640, 0xc641, 0xc642, 0xc643, 0xc644, 0xc645, 0xc646,
+ 0xc647, 0xc648, 0xc649, 0xc64a, 0xc64b, 0xc64c, 0xc64d, 0xc64e,
+ 0xc64f, 0xc650, 0x0000, 0xc651, 0xc652, 0xc653, 0xc654, 0xc655,
+ 0xc656, 0xc657, 0xc658, 0xc659, 0xc65a, 0xc65b, 0x0000, 0x0000,
+ 0x0000, 0xc65c, 0xc65d, 0xc65e, 0xc65f, 0xc660, 0xc661, 0xc662,
+ 0xc663, 0xc664, 0xc665, 0xc666, 0xc667, 0xc668, 0xc669, 0xc66a,
+ 0xc66b, 0xc66c, 0x0000, 0xc66d, 0xc66e, 0xc66f, 0xc670, 0xc671,
+ 0xc672, 0xc673, 0xc674, 0xc675, 0xc676, 0xc677, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc678, 0xc679, 0xc67a, 0xc67b, 0xc67c, 0xc67d, 0xc67e,
+ 0xc67f, 0xc680, 0xc681, 0xc682, 0xc683, 0xc684, 0xc685, 0xc686,
+ 0xc687, 0xc688, 0x0000, 0xc689, 0xc68a, 0xc68b, 0xc68c, 0xc68d,
+ 0xc68e, 0xc68f, 0xc690, 0xc691, 0xc692, 0xc693, 0x0000, 0x0000,
+ 0x0000, 0xc694, 0xc695, 0xc696, 0xc697, 0xc698, 0xc699, 0xc69a,
+ 0xc69b, 0xc69c, 0xc69d, 0xc69e, 0xc69f, 0xc6a0, 0xc6a1, 0xc6a2,
+ 0xc6a3, 0xc6a4, 0x0000, 0xc6a5, 0xc6a6, 0xc6a7, 0xc6a8, 0xc6a9,
+ 0xc6aa, 0xc6ab, 0xc6ac, 0xc6ad, 0xc6ae, 0xc6af, 0x0000, 0x0000,
+ 0x0000, 0xc6b0, 0xc6b1, 0xc6b2, 0xc6b3, 0xc6b4, 0xc6b5, 0xc6b6,
+ 0xc6b7, 0xc6b8, 0xc6b9, 0xc6ba, 0xc6bb, 0xc6bc, 0xc6bd, 0xc6be,
+ 0xc6bf, 0xc6c0, 0x0000, 0xc6c1, 0xc6c2, 0xc6c3, 0xc6c4, 0xc6c5,
+ 0xc6c6, 0xc6c7, 0xc6c8, 0xc6c9, 0xc6ca, 0xc6cb, 0x0000, 0x0000,
+ 0x0000, 0xc6cc, 0xc6cd, 0xc6ce, 0xc6cf, 0xc6d0, 0xc6d1, 0xc6d2,
+ 0xc6d3, 0xc6d4, 0xc6d5, 0xc6d6, 0xc6d7, 0xc6d8, 0xc6d9, 0xc6da,
+ 0xc6db, 0xc6dc, 0x0000, 0xc6dd, 0xc6de, 0xc6df, 0xc6e0, 0xc6e1,
+ 0xc6e2, 0xc6e3, 0xc6e4, 0xc6e5, 0xc6e6, 0xc6e7, 0x0000, 0x0000,
+ 0x0000, 0xc6e8, 0xc6e9, 0xc6ea, 0xc6eb, 0xc6ec, 0xc6ed, 0xc6ee,
+ 0xc6ef, 0xc6f0, 0xc6f1, 0xc6f2, 0xc6f3, 0xc6f4, 0xc6f5, 0xc6f6,
+ 0xc6f7, 0xc6f8, 0x0000, 0xc6f9, 0xc6fa, 0xc6fb, 0xc6fc, 0xc6fd,
+ 0xc6fe, 0xc6ff, 0xc700, 0xc701, 0xc702, 0xc703, 0x0000, 0x0000,
+ 0x0000, 0xc704, 0xc705, 0xc706, 0xc707, 0xc708, 0xc709, 0xc70a,
+ 0xc70b, 0xc70c, 0xc70d, 0xc70e, 0xc70f, 0xc710, 0xc711, 0xc712,
+ 0xc713, 0xc714, 0x0000, 0xc715, 0xc716, 0xc717, 0xc718, 0xc719,
+ 0xc71a, 0xc71b, 0xc71c, 0xc71d, 0xc71e, 0xc71f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc720, 0xc721, 0xc722, 0xc723, 0xc724, 0xc725, 0xc726,
+ 0xc727, 0xc728, 0xc729, 0xc72a, 0xc72b, 0xc72c, 0xc72d, 0xc72e,
+ 0xc72f, 0xc730, 0x0000, 0xc731, 0xc732, 0xc733, 0xc734, 0xc735,
+ 0xc736, 0xc737, 0xc738, 0xc739, 0xc73a, 0xc73b, 0x0000, 0x0000,
+ 0x0000, 0xc73c, 0xc73d, 0xc73e, 0xc73f, 0xc740, 0xc741, 0xc742,
+ 0xc743, 0xc744, 0xc745, 0xc746, 0xc747, 0xc748, 0xc749, 0xc74a,
+ 0xc74b, 0xc74c, 0x0000, 0xc74d, 0xc74e, 0xc74f, 0xc750, 0xc751,
+ 0xc752, 0xc753, 0xc754, 0xc755, 0xc756, 0xc757, 0x0000, 0x0000,
+ 0x0000, 0xc758, 0xc759, 0xc75a, 0xc75b, 0xc75c, 0xc75d, 0xc75e,
+ 0xc75f, 0xc760, 0xc761, 0xc762, 0xc763, 0xc764, 0xc765, 0xc766,
+ 0xc767, 0xc768, 0x0000, 0xc769, 0xc76a, 0xc76b, 0xc76c, 0xc76d,
+ 0xc76e, 0xc76f, 0xc770, 0xc771, 0xc772, 0xc773, 0x0000, 0x0000,
+ 0x0000, 0xc774, 0xc775, 0xc776, 0xc777, 0xc778, 0xc779, 0xc77a,
+ 0xc77b, 0xc77c, 0xc77d, 0xc77e, 0xc77f, 0xc780, 0xc781, 0xc782,
+ 0xc783, 0xc784, 0x0000, 0xc785, 0xc786, 0xc787, 0xc788, 0xc789,
+ 0xc78a, 0xc78b, 0xc78c, 0xc78d, 0xc78e, 0xc78f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc790, 0xc791, 0xc792, 0xc793, 0xc794, 0xc795, 0xc796,
+ 0xc797, 0xc798, 0xc799, 0xc79a, 0xc79b, 0xc79c, 0xc79d, 0xc79e,
+ 0xc79f, 0xc7a0, 0x0000, 0xc7a1, 0xc7a2, 0xc7a3, 0xc7a4, 0xc7a5,
+ 0xc7a6, 0xc7a7, 0xc7a8, 0xc7a9, 0xc7aa, 0xc7ab, 0x0000, 0x0000,
+ 0x0000, 0xc7ac, 0xc7ad, 0xc7ae, 0xc7af, 0xc7b0, 0xc7b1, 0xc7b2,
+ 0xc7b3, 0xc7b4, 0xc7b5, 0xc7b6, 0xc7b7, 0xc7b8, 0xc7b9, 0xc7ba,
+ 0xc7bb, 0xc7bc, 0x0000, 0xc7bd, 0xc7be, 0xc7bf, 0xc7c0, 0xc7c1,
+ 0xc7c2, 0xc7c3, 0xc7c4, 0xc7c5, 0xc7c6, 0xc7c7, 0x0000, 0x0000,
+ 0x0000, 0xc7c8, 0xc7c9, 0xc7ca, 0xc7cb, 0xc7cc, 0xc7cd, 0xc7ce,
+ 0xc7cf, 0xc7d0, 0xc7d1, 0xc7d2, 0xc7d3, 0xc7d4, 0xc7d5, 0xc7d6,
+ 0xc7d7, 0xc7d8, 0x0000, 0xc7d9, 0xc7da, 0xc7db, 0xc7dc, 0xc7dd,
+ 0xc7de, 0xc7df, 0xc7e0, 0xc7e1, 0xc7e2, 0xc7e3, 0x0000, 0x0000,
+ 0x0000, 0xc7e4, 0xc7e5, 0xc7e6, 0xc7e7, 0xc7e8, 0xc7e9, 0xc7ea,
+ 0xc7eb, 0xc7ec, 0xc7ed, 0xc7ee, 0xc7ef, 0xc7f0, 0xc7f1, 0xc7f2,
+ 0xc7f3, 0xc7f4, 0x0000, 0xc7f5, 0xc7f6, 0xc7f7, 0xc7f8, 0xc7f9,
+ 0xc7fa, 0xc7fb, 0xc7fc, 0xc7fd, 0xc7fe, 0xc7ff, 0x0000, 0x0000,
+ 0x0000, 0xc800, 0xc801, 0xc802, 0xc803, 0xc804, 0xc805, 0xc806,
+ 0xc807, 0xc808, 0xc809, 0xc80a, 0xc80b, 0xc80c, 0xc80d, 0xc80e,
+ 0xc80f, 0xc810, 0x0000, 0xc811, 0xc812, 0xc813, 0xc814, 0xc815,
+ 0xc816, 0xc817, 0xc818, 0xc819, 0xc81a, 0xc81b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc81c, 0xc81d, 0xc81e, 0xc81f, 0xc820, 0xc821, 0xc822,
+ 0xc823, 0xc824, 0xc825, 0xc826, 0xc827, 0xc828, 0xc829, 0xc82a,
+ 0xc82b, 0xc82c, 0x0000, 0xc82d, 0xc82e, 0xc82f, 0xc830, 0xc831,
+ 0xc832, 0xc833, 0xc834, 0xc835, 0xc836, 0xc837, 0x0000, 0x0000,
+ 0x0000, 0xc838, 0xc839, 0xc83a, 0xc83b, 0xc83c, 0xc83d, 0xc83e,
+ 0xc83f, 0xc840, 0xc841, 0xc842, 0xc843, 0xc844, 0xc845, 0xc846,
+ 0xc847, 0xc848, 0x0000, 0xc849, 0xc84a, 0xc84b, 0xc84c, 0xc84d,
+ 0xc84e, 0xc84f, 0xc850, 0xc851, 0xc852, 0xc853, 0x0000, 0x0000,
+ 0x0000, 0xc854, 0xc855, 0xc856, 0xc857, 0xc858, 0xc859, 0xc85a,
+ 0xc85b, 0xc85c, 0xc85d, 0xc85e, 0xc85f, 0xc860, 0xc861, 0xc862,
+ 0xc863, 0xc864, 0x0000, 0xc865, 0xc866, 0xc867, 0xc868, 0xc869,
+ 0xc86a, 0xc86b, 0xc86c, 0xc86d, 0xc86e, 0xc86f, 0x0000, 0x0000,
+ 0x0000, 0xc870, 0xc871, 0xc872, 0xc873, 0xc874, 0xc875, 0xc876,
+ 0xc877, 0xc878, 0xc879, 0xc87a, 0xc87b, 0xc87c, 0xc87d, 0xc87e,
+ 0xc87f, 0xc880, 0x0000, 0xc881, 0xc882, 0xc883, 0xc884, 0xc885,
+ 0xc886, 0xc887, 0xc888, 0xc889, 0xc88a, 0xc88b, 0x0000, 0x0000,
+ 0x0000, 0xc88c, 0xc88d, 0xc88e, 0xc88f, 0xc890, 0xc891, 0xc892,
+ 0xc893, 0xc894, 0xc895, 0xc896, 0xc897, 0xc898, 0xc899, 0xc89a,
+ 0xc89b, 0xc89c, 0x0000, 0xc89d, 0xc89e, 0xc89f, 0xc8a0, 0xc8a1,
+ 0xc8a2, 0xc8a3, 0xc8a4, 0xc8a5, 0xc8a6, 0xc8a7, 0x0000, 0x0000,
+ 0x0000, 0xc8a8, 0xc8a9, 0xc8aa, 0xc8ab, 0xc8ac, 0xc8ad, 0xc8ae,
+ 0xc8af, 0xc8b0, 0xc8b1, 0xc8b2, 0xc8b3, 0xc8b4, 0xc8b5, 0xc8b6,
+ 0xc8b7, 0xc8b8, 0x0000, 0xc8b9, 0xc8ba, 0xc8bb, 0xc8bc, 0xc8bd,
+ 0xc8be, 0xc8bf, 0xc8c0, 0xc8c1, 0xc8c2, 0xc8c3, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc8c4, 0xc8c5, 0xc8c6, 0xc8c7, 0xc8c8, 0xc8c9, 0xc8ca,
+ 0xc8cb, 0xc8cc, 0xc8cd, 0xc8ce, 0xc8cf, 0xc8d0, 0xc8d1, 0xc8d2,
+ 0xc8d3, 0xc8d4, 0x0000, 0xc8d5, 0xc8d6, 0xc8d7, 0xc8d8, 0xc8d9,
+ 0xc8da, 0xc8db, 0xc8dc, 0xc8dd, 0xc8de, 0xc8df, 0x0000, 0x0000,
+ 0x0000, 0xc8e0, 0xc8e1, 0xc8e2, 0xc8e3, 0xc8e4, 0xc8e5, 0xc8e6,
+ 0xc8e7, 0xc8e8, 0xc8e9, 0xc8ea, 0xc8eb, 0xc8ec, 0xc8ed, 0xc8ee,
+ 0xc8ef, 0xc8f0, 0x0000, 0xc8f1, 0xc8f2, 0xc8f3, 0xc8f4, 0xc8f5,
+ 0xc8f6, 0xc8f7, 0xc8f8, 0xc8f9, 0xc8fa, 0xc8fb, 0x0000, 0x0000,
+ 0x0000, 0xc8fc, 0xc8fd, 0xc8fe, 0xc8ff, 0xc900, 0xc901, 0xc902,
+ 0xc903, 0xc904, 0xc905, 0xc906, 0xc907, 0xc908, 0xc909, 0xc90a,
+ 0xc90b, 0xc90c, 0x0000, 0xc90d, 0xc90e, 0xc90f, 0xc910, 0xc911,
+ 0xc912, 0xc913, 0xc914, 0xc915, 0xc916, 0xc917, 0x0000, 0x0000,
+ 0x0000, 0xc918, 0xc919, 0xc91a, 0xc91b, 0xc91c, 0xc91d, 0xc91e,
+ 0xc91f, 0xc920, 0xc921, 0xc922, 0xc923, 0xc924, 0xc925, 0xc926,
+ 0xc927, 0xc928, 0x0000, 0xc929, 0xc92a, 0xc92b, 0xc92c, 0xc92d,
+ 0xc92e, 0xc92f, 0xc930, 0xc931, 0xc932, 0xc933, 0x0000, 0x0000,
+ 0x0000, 0xc934, 0xc935, 0xc936, 0xc937, 0xc938, 0xc939, 0xc93a,
+ 0xc93b, 0xc93c, 0xc93d, 0xc93e, 0xc93f, 0xc940, 0xc941, 0xc942,
+ 0xc943, 0xc944, 0x0000, 0xc945, 0xc946, 0xc947, 0xc948, 0xc949,
+ 0xc94a, 0xc94b, 0xc94c, 0xc94d, 0xc94e, 0xc94f, 0x0000, 0x0000,
+ 0x0000, 0xc950, 0xc951, 0xc952, 0xc953, 0xc954, 0xc955, 0xc956,
+ 0xc957, 0xc958, 0xc959, 0xc95a, 0xc95b, 0xc95c, 0xc95d, 0xc95e,
+ 0xc95f, 0xc960, 0x0000, 0xc961, 0xc962, 0xc963, 0xc964, 0xc965,
+ 0xc966, 0xc967, 0xc968, 0xc969, 0xc96a, 0xc96b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc96c, 0xc96d, 0xc96e, 0xc96f, 0xc970, 0xc971, 0xc972,
+ 0xc973, 0xc974, 0xc975, 0xc976, 0xc977, 0xc978, 0xc979, 0xc97a,
+ 0xc97b, 0xc97c, 0x0000, 0xc97d, 0xc97e, 0xc97f, 0xc980, 0xc981,
+ 0xc982, 0xc983, 0xc984, 0xc985, 0xc986, 0xc987, 0x0000, 0x0000,
+ 0x0000, 0xc988, 0xc989, 0xc98a, 0xc98b, 0xc98c, 0xc98d, 0xc98e,
+ 0xc98f, 0xc990, 0xc991, 0xc992, 0xc993, 0xc994, 0xc995, 0xc996,
+ 0xc997, 0xc998, 0x0000, 0xc999, 0xc99a, 0xc99b, 0xc99c, 0xc99d,
+ 0xc99e, 0xc99f, 0xc9a0, 0xc9a1, 0xc9a2, 0xc9a3, 0x0000, 0x0000,
+ 0x0000, 0xc9a4, 0xc9a5, 0xc9a6, 0xc9a7, 0xc9a8, 0xc9a9, 0xc9aa,
+ 0xc9ab, 0xc9ac, 0xc9ad, 0xc9ae, 0xc9af, 0xc9b0, 0xc9b1, 0xc9b2,
+ 0xc9b3, 0xc9b4, 0x0000, 0xc9b5, 0xc9b6, 0xc9b7, 0xc9b8, 0xc9b9,
+ 0xc9ba, 0xc9bb, 0xc9bc, 0xc9bd, 0xc9be, 0xc9bf, 0x0000, 0x0000,
+ 0x0000, 0xc9c0, 0xc9c1, 0xc9c2, 0xc9c3, 0xc9c4, 0xc9c5, 0xc9c6,
+ 0xc9c7, 0xc9c8, 0xc9c9, 0xc9ca, 0xc9cb, 0xc9cc, 0xc9cd, 0xc9ce,
+ 0xc9cf, 0xc9d0, 0x0000, 0xc9d1, 0xc9d2, 0xc9d3, 0xc9d4, 0xc9d5,
+ 0xc9d6, 0xc9d7, 0xc9d8, 0xc9d9, 0xc9da, 0xc9db, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3149, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc9dc, 0xc9dd, 0xc9de, 0xc9df, 0xc9e0, 0xc9e1, 0xc9e2,
+ 0xc9e3, 0xc9e4, 0xc9e5, 0xc9e6, 0xc9e7, 0xc9e8, 0xc9e9, 0xc9ea,
+ 0xc9eb, 0xc9ec, 0x0000, 0xc9ed, 0xc9ee, 0xc9ef, 0xc9f0, 0xc9f1,
+ 0xc9f2, 0xc9f3, 0xc9f4, 0xc9f5, 0xc9f6, 0xc9f7, 0x0000, 0x0000,
+ 0x0000, 0xc9f8, 0xc9f9, 0xc9fa, 0xc9fb, 0xc9fc, 0xc9fd, 0xc9fe,
+ 0xc9ff, 0xca00, 0xca01, 0xca02, 0xca03, 0xca04, 0xca05, 0xca06,
+ 0xca07, 0xca08, 0x0000, 0xca09, 0xca0a, 0xca0b, 0xca0c, 0xca0d,
+ 0xca0e, 0xca0f, 0xca10, 0xca11, 0xca12, 0xca13, 0x0000, 0x0000,
+ 0x0000, 0xca14, 0xca15, 0xca16, 0xca17, 0xca18, 0xca19, 0xca1a,
+ 0xca1b, 0xca1c, 0xca1d, 0xca1e, 0xca1f, 0xca20, 0xca21, 0xca22,
+ 0xca23, 0xca24, 0x0000, 0xca25, 0xca26, 0xca27, 0xca28, 0xca29,
+ 0xca2a, 0xca2b, 0xca2c, 0xca2d, 0xca2e, 0xca2f, 0x0000, 0x0000,
+ 0x0000, 0xca30, 0xca31, 0xca32, 0xca33, 0xca34, 0xca35, 0xca36,
+ 0xca37, 0xca38, 0xca39, 0xca3a, 0xca3b, 0xca3c, 0xca3d, 0xca3e,
+ 0xca3f, 0xca40, 0x0000, 0xca41, 0xca42, 0xca43, 0xca44, 0xca45,
+ 0xca46, 0xca47, 0xca48, 0xca49, 0xca4a, 0xca4b, 0x0000, 0x0000,
+ 0x0000, 0xca4c, 0xca4d, 0xca4e, 0xca4f, 0xca50, 0xca51, 0xca52,
+ 0xca53, 0xca54, 0xca55, 0xca56, 0xca57, 0xca58, 0xca59, 0xca5a,
+ 0xca5b, 0xca5c, 0x0000, 0xca5d, 0xca5e, 0xca5f, 0xca60, 0xca61,
+ 0xca62, 0xca63, 0xca64, 0xca65, 0xca66, 0xca67, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xca68, 0xca69, 0xca6a, 0xca6b, 0xca6c, 0xca6d, 0xca6e,
+ 0xca6f, 0xca70, 0xca71, 0xca72, 0xca73, 0xca74, 0xca75, 0xca76,
+ 0xca77, 0xca78, 0x0000, 0xca79, 0xca7a, 0xca7b, 0xca7c, 0xca7d,
+ 0xca7e, 0xca7f, 0xca80, 0xca81, 0xca82, 0xca83, 0x0000, 0x0000,
+ 0x0000, 0xca84, 0xca85, 0xca86, 0xca87, 0xca88, 0xca89, 0xca8a,
+ 0xca8b, 0xca8c, 0xca8d, 0xca8e, 0xca8f, 0xca90, 0xca91, 0xca92,
+ 0xca93, 0xca94, 0x0000, 0xca95, 0xca96, 0xca97, 0xca98, 0xca99,
+ 0xca9a, 0xca9b, 0xca9c, 0xca9d, 0xca9e, 0xca9f, 0x0000, 0x0000,
+ 0x0000, 0xcaa0, 0xcaa1, 0xcaa2, 0xcaa3, 0xcaa4, 0xcaa5, 0xcaa6,
+ 0xcaa7, 0xcaa8, 0xcaa9, 0xcaaa, 0xcaab, 0xcaac, 0xcaad, 0xcaae,
+ 0xcaaf, 0xcab0, 0x0000, 0xcab1, 0xcab2, 0xcab3, 0xcab4, 0xcab5,
+ 0xcab6, 0xcab7, 0xcab8, 0xcab9, 0xcaba, 0xcabb, 0x0000, 0x0000,
+ 0x0000, 0xcabc, 0xcabd, 0xcabe, 0xcabf, 0xcac0, 0xcac1, 0xcac2,
+ 0xcac3, 0xcac4, 0xcac5, 0xcac6, 0xcac7, 0xcac8, 0xcac9, 0xcaca,
+ 0xcacb, 0xcacc, 0x0000, 0xcacd, 0xcace, 0xcacf, 0xcad0, 0xcad1,
+ 0xcad2, 0xcad3, 0xcad4, 0xcad5, 0xcad6, 0xcad7, 0x0000, 0x0000,
+ 0x0000, 0xcad8, 0xcad9, 0xcada, 0xcadb, 0xcadc, 0xcadd, 0xcade,
+ 0xcadf, 0xcae0, 0xcae1, 0xcae2, 0xcae3, 0xcae4, 0xcae5, 0xcae6,
+ 0xcae7, 0xcae8, 0x0000, 0xcae9, 0xcaea, 0xcaeb, 0xcaec, 0xcaed,
+ 0xcaee, 0xcaef, 0xcaf0, 0xcaf1, 0xcaf2, 0xcaf3, 0x0000, 0x0000,
+ 0x0000, 0xcaf4, 0xcaf5, 0xcaf6, 0xcaf7, 0xcaf8, 0xcaf9, 0xcafa,
+ 0xcafb, 0xcafc, 0xcafd, 0xcafe, 0xcaff, 0xcb00, 0xcb01, 0xcb02,
+ 0xcb03, 0xcb04, 0x0000, 0xcb05, 0xcb06, 0xcb07, 0xcb08, 0xcb09,
+ 0xcb0a, 0xcb0b, 0xcb0c, 0xcb0d, 0xcb0e, 0xcb0f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xcb10, 0xcb11, 0xcb12, 0xcb13, 0xcb14, 0xcb15, 0xcb16,
+ 0xcb17, 0xcb18, 0xcb19, 0xcb1a, 0xcb1b, 0xcb1c, 0xcb1d, 0xcb1e,
+ 0xcb1f, 0xcb20, 0x0000, 0xcb21, 0xcb22, 0xcb23, 0xcb24, 0xcb25,
+ 0xcb26, 0xcb27, 0xcb28, 0xcb29, 0xcb2a, 0xcb2b, 0x0000, 0x0000,
+ 0x0000, 0xcb2c, 0xcb2d, 0xcb2e, 0xcb2f, 0xcb30, 0xcb31, 0xcb32,
+ 0xcb33, 0xcb34, 0xcb35, 0xcb36, 0xcb37, 0xcb38, 0xcb39, 0xcb3a,
+ 0xcb3b, 0xcb3c, 0x0000, 0xcb3d, 0xcb3e, 0xcb3f, 0xcb40, 0xcb41,
+ 0xcb42, 0xcb43, 0xcb44, 0xcb45, 0xcb46, 0xcb47, 0x0000, 0x0000,
+ 0x0000, 0xcb48, 0xcb49, 0xcb4a, 0xcb4b, 0xcb4c, 0xcb4d, 0xcb4e,
+ 0xcb4f, 0xcb50, 0xcb51, 0xcb52, 0xcb53, 0xcb54, 0xcb55, 0xcb56,
+ 0xcb57, 0xcb58, 0x0000, 0xcb59, 0xcb5a, 0xcb5b, 0xcb5c, 0xcb5d,
+ 0xcb5e, 0xcb5f, 0xcb60, 0xcb61, 0xcb62, 0xcb63, 0x0000, 0x0000,
+ 0x0000, 0xcb64, 0xcb65, 0xcb66, 0xcb67, 0xcb68, 0xcb69, 0xcb6a,
+ 0xcb6b, 0xcb6c, 0xcb6d, 0xcb6e, 0xcb6f, 0xcb70, 0xcb71, 0xcb72,
+ 0xcb73, 0xcb74, 0x0000, 0xcb75, 0xcb76, 0xcb77, 0xcb78, 0xcb79,
+ 0xcb7a, 0xcb7b, 0xcb7c, 0xcb7d, 0xcb7e, 0xcb7f, 0x0000, 0x0000,
+ 0x0000, 0xcb80, 0xcb81, 0xcb82, 0xcb83, 0xcb84, 0xcb85, 0xcb86,
+ 0xcb87, 0xcb88, 0xcb89, 0xcb8a, 0xcb8b, 0xcb8c, 0xcb8d, 0xcb8e,
+ 0xcb8f, 0xcb90, 0x0000, 0xcb91, 0xcb92, 0xcb93, 0xcb94, 0xcb95,
+ 0xcb96, 0xcb97, 0xcb98, 0xcb99, 0xcb9a, 0xcb9b, 0x0000, 0x0000,
+ 0x0000, 0xcb9c, 0xcb9d, 0xcb9e, 0xcb9f, 0xcba0, 0xcba1, 0xcba2,
+ 0xcba3, 0xcba4, 0xcba5, 0xcba6, 0xcba7, 0xcba8, 0xcba9, 0xcbaa,
+ 0xcbab, 0xcbac, 0x0000, 0xcbad, 0xcbae, 0xcbaf, 0xcbb0, 0xcbb1,
+ 0xcbb2, 0xcbb3, 0xcbb4, 0xcbb5, 0xcbb6, 0xcbb7, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xcbb8, 0xcbb9, 0xcbba, 0xcbbb, 0xcbbc, 0xcbbd, 0xcbbe,
+ 0xcbbf, 0xcbc0, 0xcbc1, 0xcbc2, 0xcbc3, 0xcbc4, 0xcbc5, 0xcbc6,
+ 0xcbc7, 0xcbc8, 0x0000, 0xcbc9, 0xcbca, 0xcbcb, 0xcbcc, 0xcbcd,
+ 0xcbce, 0xcbcf, 0xcbd0, 0xcbd1, 0xcbd2, 0xcbd3, 0x0000, 0x0000,
+ 0x0000, 0xcbd4, 0xcbd5, 0xcbd6, 0xcbd7, 0xcbd8, 0xcbd9, 0xcbda,
+ 0xcbdb, 0xcbdc, 0xcbdd, 0xcbde, 0xcbdf, 0xcbe0, 0xcbe1, 0xcbe2,
+ 0xcbe3, 0xcbe4, 0x0000, 0xcbe5, 0xcbe6, 0xcbe7, 0xcbe8, 0xcbe9,
+ 0xcbea, 0xcbeb, 0xcbec, 0xcbed, 0xcbee, 0xcbef, 0x0000, 0x0000,
+ 0x0000, 0xcbf0, 0xcbf1, 0xcbf2, 0xcbf3, 0xcbf4, 0xcbf5, 0xcbf6,
+ 0xcbf7, 0xcbf8, 0xcbf9, 0xcbfa, 0xcbfb, 0xcbfc, 0xcbfd, 0xcbfe,
+ 0xcbff, 0xcc00, 0x0000, 0xcc01, 0xcc02, 0xcc03, 0xcc04, 0xcc05,
+ 0xcc06, 0xcc07, 0xcc08, 0xcc09, 0xcc0a, 0xcc0b, 0x0000, 0x0000,
+ 0x0000, 0xcc0c, 0xcc0d, 0xcc0e, 0xcc0f, 0xcc10, 0xcc11, 0xcc12,
+ 0xcc13, 0xcc14, 0xcc15, 0xcc16, 0xcc17, 0xcc18, 0xcc19, 0xcc1a,
+ 0xcc1b, 0xcc1c, 0x0000, 0xcc1d, 0xcc1e, 0xcc1f, 0xcc20, 0xcc21,
+ 0xcc22, 0xcc23, 0xcc24, 0xcc25, 0xcc26, 0xcc27, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xcc28, 0xcc29, 0xcc2a, 0xcc2b, 0xcc2c, 0xcc2d, 0xcc2e,
+ 0xcc2f, 0xcc30, 0xcc31, 0xcc32, 0xcc33, 0xcc34, 0xcc35, 0xcc36,
+ 0xcc37, 0xcc38, 0x0000, 0xcc39, 0xcc3a, 0xcc3b, 0xcc3c, 0xcc3d,
+ 0xcc3e, 0xcc3f, 0xcc40, 0xcc41, 0xcc42, 0xcc43, 0x0000, 0x0000,
+ 0x0000, 0xcc44, 0xcc45, 0xcc46, 0xcc47, 0xcc48, 0xcc49, 0xcc4a,
+ 0xcc4b, 0xcc4c, 0xcc4d, 0xcc4e, 0xcc4f, 0xcc50, 0xcc51, 0xcc52,
+ 0xcc53, 0xcc54, 0x0000, 0xcc55, 0xcc56, 0xcc57, 0xcc58, 0xcc59,
+ 0xcc5a, 0xcc5b, 0xcc5c, 0xcc5d, 0xcc5e, 0xcc5f, 0x0000, 0x0000,
+ 0x0000, 0xcc60, 0xcc61, 0xcc62, 0xcc63, 0xcc64, 0xcc65, 0xcc66,
+ 0xcc67, 0xcc68, 0xcc69, 0xcc6a, 0xcc6b, 0xcc6c, 0xcc6d, 0xcc6e,
+ 0xcc6f, 0xcc70, 0x0000, 0xcc71, 0xcc72, 0xcc73, 0xcc74, 0xcc75,
+ 0xcc76, 0xcc77, 0xcc78, 0xcc79, 0xcc7a, 0xcc7b, 0x0000, 0x0000,
+ 0x0000, 0xcc7c, 0xcc7d, 0xcc7e, 0xcc7f, 0xcc80, 0xcc81, 0xcc82,
+ 0xcc83, 0xcc84, 0xcc85, 0xcc86, 0xcc87, 0xcc88, 0xcc89, 0xcc8a,
+ 0xcc8b, 0xcc8c, 0x0000, 0xcc8d, 0xcc8e, 0xcc8f, 0xcc90, 0xcc91,
+ 0xcc92, 0xcc93, 0xcc94, 0xcc95, 0xcc96, 0xcc97, 0x0000, 0x0000,
+ 0x0000, 0xcc98, 0xcc99, 0xcc9a, 0xcc9b, 0xcc9c, 0xcc9d, 0xcc9e,
+ 0xcc9f, 0xcca0, 0xcca1, 0xcca2, 0xcca3, 0xcca4, 0xcca5, 0xcca6,
+ 0xcca7, 0xcca8, 0x0000, 0xcca9, 0xccaa, 0xccab, 0xccac, 0xccad,
+ 0xccae, 0xccaf, 0xccb0, 0xccb1, 0xccb2, 0xccb3, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xccb4, 0xccb5, 0xccb6, 0xccb7, 0xccb8, 0xccb9, 0xccba,
+ 0xccbb, 0xccbc, 0xccbd, 0xccbe, 0xccbf, 0xccc0, 0xccc1, 0xccc2,
+ 0xccc3, 0xccc4, 0x0000, 0xccc5, 0xccc6, 0xccc7, 0xccc8, 0xccc9,
+ 0xccca, 0xcccb, 0xcccc, 0xcccd, 0xccce, 0xcccf, 0x0000, 0x0000,
+ 0x0000, 0xccd0, 0xccd1, 0xccd2, 0xccd3, 0xccd4, 0xccd5, 0xccd6,
+ 0xccd7, 0xccd8, 0xccd9, 0xccda, 0xccdb, 0xccdc, 0xccdd, 0xccde,
+ 0xccdf, 0xcce0, 0x0000, 0xcce1, 0xcce2, 0xcce3, 0xcce4, 0xcce5,
+ 0xcce6, 0xcce7, 0xcce8, 0xcce9, 0xccea, 0xcceb, 0x0000, 0x0000,
+ 0x0000, 0xccec, 0xcced, 0xccee, 0xccef, 0xccf0, 0xccf1, 0xccf2,
+ 0xccf3, 0xccf4, 0xccf5, 0xccf6, 0xccf7, 0xccf8, 0xccf9, 0xccfa,
+ 0xccfb, 0xccfc, 0x0000, 0xccfd, 0xccfe, 0xccff, 0xcd00, 0xcd01,
+ 0xcd02, 0xcd03, 0xcd04, 0xcd05, 0xcd06, 0xcd07, 0x0000, 0x0000,
+ 0x0000, 0xcd08, 0xcd09, 0xcd0a, 0xcd0b, 0xcd0c, 0xcd0d, 0xcd0e,
+ 0xcd0f, 0xcd10, 0xcd11, 0xcd12, 0xcd13, 0xcd14, 0xcd15, 0xcd16,
+ 0xcd17, 0xcd18, 0x0000, 0xcd19, 0xcd1a, 0xcd1b, 0xcd1c, 0xcd1d,
+ 0xcd1e, 0xcd1f, 0xcd20, 0xcd21, 0xcd22, 0xcd23, 0x0000, 0x0000,
+ 0x0000, 0xcd24, 0xcd25, 0xcd26, 0xcd27, 0xcd28, 0xcd29, 0xcd2a,
+ 0xcd2b, 0xcd2c, 0xcd2d, 0xcd2e, 0xcd2f, 0xcd30, 0xcd31, 0xcd32,
+ 0xcd33, 0xcd34, 0x0000, 0xcd35, 0xcd36, 0xcd37, 0xcd38, 0xcd39,
+ 0xcd3a, 0xcd3b, 0xcd3c, 0xcd3d, 0xcd3e, 0xcd3f, 0x0000, 0x0000,
+ 0x0000, 0xcd40, 0xcd41, 0xcd42, 0xcd43, 0xcd44, 0xcd45, 0xcd46,
+ 0xcd47, 0xcd48, 0xcd49, 0xcd4a, 0xcd4b, 0xcd4c, 0xcd4d, 0xcd4e,
+ 0xcd4f, 0xcd50, 0x0000, 0xcd51, 0xcd52, 0xcd53, 0xcd54, 0xcd55,
+ 0xcd56, 0xcd57, 0xcd58, 0xcd59, 0xcd5a, 0xcd5b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xcd5c, 0xcd5d, 0xcd5e, 0xcd5f, 0xcd60, 0xcd61, 0xcd62,
+ 0xcd63, 0xcd64, 0xcd65, 0xcd66, 0xcd67, 0xcd68, 0xcd69, 0xcd6a,
+ 0xcd6b, 0xcd6c, 0x0000, 0xcd6d, 0xcd6e, 0xcd6f, 0xcd70, 0xcd71,
+ 0xcd72, 0xcd73, 0xcd74, 0xcd75, 0xcd76, 0xcd77, 0x0000, 0x0000,
+ 0x0000, 0xcd78, 0xcd79, 0xcd7a, 0xcd7b, 0xcd7c, 0xcd7d, 0xcd7e,
+ 0xcd7f, 0xcd80, 0xcd81, 0xcd82, 0xcd83, 0xcd84, 0xcd85, 0xcd86,
+ 0xcd87, 0xcd88, 0x0000, 0xcd89, 0xcd8a, 0xcd8b, 0xcd8c, 0xcd8d,
+ 0xcd8e, 0xcd8f, 0xcd90, 0xcd91, 0xcd92, 0xcd93, 0x0000, 0x0000,
+ 0x0000, 0xcd94, 0xcd95, 0xcd96, 0xcd97, 0xcd98, 0xcd99, 0xcd9a,
+ 0xcd9b, 0xcd9c, 0xcd9d, 0xcd9e, 0xcd9f, 0xcda0, 0xcda1, 0xcda2,
+ 0xcda3, 0xcda4, 0x0000, 0xcda5, 0xcda6, 0xcda7, 0xcda8, 0xcda9,
+ 0xcdaa, 0xcdab, 0xcdac, 0xcdad, 0xcdae, 0xcdaf, 0x0000, 0x0000,
+ 0x0000, 0xcdb0, 0xcdb1, 0xcdb2, 0xcdb3, 0xcdb4, 0xcdb5, 0xcdb6,
+ 0xcdb7, 0xcdb8, 0xcdb9, 0xcdba, 0xcdbb, 0xcdbc, 0xcdbd, 0xcdbe,
+ 0xcdbf, 0xcdc0, 0x0000, 0xcdc1, 0xcdc2, 0xcdc3, 0xcdc4, 0xcdc5,
+ 0xcdc6, 0xcdc7, 0xcdc8, 0xcdc9, 0xcdca, 0xcdcb, 0x0000, 0x0000,
+ 0x0000, 0xcdcc, 0xcdcd, 0xcdce, 0xcdcf, 0xcdd0, 0xcdd1, 0xcdd2,
+ 0xcdd3, 0xcdd4, 0xcdd5, 0xcdd6, 0xcdd7, 0xcdd8, 0xcdd9, 0xcdda,
+ 0xcddb, 0xcddc, 0x0000, 0xcddd, 0xcdde, 0xcddf, 0xcde0, 0xcde1,
+ 0xcde2, 0xcde3, 0xcde4, 0xcde5, 0xcde6, 0xcde7, 0x0000, 0x0000,
+ 0x0000, 0xcde8, 0xcde9, 0xcdea, 0xcdeb, 0xcdec, 0xcded, 0xcdee,
+ 0xcdef, 0xcdf0, 0xcdf1, 0xcdf2, 0xcdf3, 0xcdf4, 0xcdf5, 0xcdf6,
+ 0xcdf7, 0xcdf8, 0x0000, 0xcdf9, 0xcdfa, 0xcdfb, 0xcdfc, 0xcdfd,
+ 0xcdfe, 0xcdff, 0xce00, 0xce01, 0xce02, 0xce03, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xce04, 0xce05, 0xce06, 0xce07, 0xce08, 0xce09, 0xce0a,
+ 0xce0b, 0xce0c, 0xce0d, 0xce0e, 0xce0f, 0xce10, 0xce11, 0xce12,
+ 0xce13, 0xce14, 0x0000, 0xce15, 0xce16, 0xce17, 0xce18, 0xce19,
+ 0xce1a, 0xce1b, 0xce1c, 0xce1d, 0xce1e, 0xce1f, 0x0000, 0x0000,
+ 0x0000, 0xce20, 0xce21, 0xce22, 0xce23, 0xce24, 0xce25, 0xce26,
+ 0xce27, 0xce28, 0xce29, 0xce2a, 0xce2b, 0xce2c, 0xce2d, 0xce2e,
+ 0xce2f, 0xce30, 0x0000, 0xce31, 0xce32, 0xce33, 0xce34, 0xce35,
+ 0xce36, 0xce37, 0xce38, 0xce39, 0xce3a, 0xce3b, 0x0000, 0x0000,
+ 0x0000, 0xce3c, 0xce3d, 0xce3e, 0xce3f, 0xce40, 0xce41, 0xce42,
+ 0xce43, 0xce44, 0xce45, 0xce46, 0xce47, 0xce48, 0xce49, 0xce4a,
+ 0xce4b, 0xce4c, 0x0000, 0xce4d, 0xce4e, 0xce4f, 0xce50, 0xce51,
+ 0xce52, 0xce53, 0xce54, 0xce55, 0xce56, 0xce57, 0x0000, 0x0000,
+ 0x0000, 0xce58, 0xce59, 0xce5a, 0xce5b, 0xce5c, 0xce5d, 0xce5e,
+ 0xce5f, 0xce60, 0xce61, 0xce62, 0xce63, 0xce64, 0xce65, 0xce66,
+ 0xce67, 0xce68, 0x0000, 0xce69, 0xce6a, 0xce6b, 0xce6c, 0xce6d,
+ 0xce6e, 0xce6f, 0xce70, 0xce71, 0xce72, 0xce73, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xce74, 0xce75, 0xce76, 0xce77, 0xce78, 0xce79, 0xce7a,
+ 0xce7b, 0xce7c, 0xce7d, 0xce7e, 0xce7f, 0xce80, 0xce81, 0xce82,
+ 0xce83, 0xce84, 0x0000, 0xce85, 0xce86, 0xce87, 0xce88, 0xce89,
+ 0xce8a, 0xce8b, 0xce8c, 0xce8d, 0xce8e, 0xce8f, 0x0000, 0x0000,
+ 0x0000, 0xce90, 0xce91, 0xce92, 0xce93, 0xce94, 0xce95, 0xce96,
+ 0xce97, 0xce98, 0xce99, 0xce9a, 0xce9b, 0xce9c, 0xce9d, 0xce9e,
+ 0xce9f, 0xcea0, 0x0000, 0xcea1, 0xcea2, 0xcea3, 0xcea4, 0xcea5,
+ 0xcea6, 0xcea7, 0xcea8, 0xcea9, 0xceaa, 0xceab, 0x0000, 0x0000,
+ 0x0000, 0xceac, 0xcead, 0xceae, 0xceaf, 0xceb0, 0xceb1, 0xceb2,
+ 0xceb3, 0xceb4, 0xceb5, 0xceb6, 0xceb7, 0xceb8, 0xceb9, 0xceba,
+ 0xcebb, 0xcebc, 0x0000, 0xcebd, 0xcebe, 0xcebf, 0xcec0, 0xcec1,
+ 0xcec2, 0xcec3, 0xcec4, 0xcec5, 0xcec6, 0xcec7, 0x0000, 0x0000,
+ 0x0000, 0xcec8, 0xcec9, 0xceca, 0xcecb, 0xcecc, 0xcecd, 0xcece,
+ 0xcecf, 0xced0, 0xced1, 0xced2, 0xced3, 0xced4, 0xced5, 0xced6,
+ 0xced7, 0xced8, 0x0000, 0xced9, 0xceda, 0xcedb, 0xcedc, 0xcedd,
+ 0xcede, 0xcedf, 0xcee0, 0xcee1, 0xcee2, 0xcee3, 0x0000, 0x0000,
+ 0x0000, 0xcee4, 0xcee5, 0xcee6, 0xcee7, 0xcee8, 0xcee9, 0xceea,
+ 0xceeb, 0xceec, 0xceed, 0xceee, 0xceef, 0xcef0, 0xcef1, 0xcef2,
+ 0xcef3, 0xcef4, 0x0000, 0xcef5, 0xcef6, 0xcef7, 0xcef8, 0xcef9,
+ 0xcefa, 0xcefb, 0xcefc, 0xcefd, 0xcefe, 0xceff, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xcf00, 0xcf01, 0xcf02, 0xcf03, 0xcf04, 0xcf05, 0xcf06,
+ 0xcf07, 0xcf08, 0xcf09, 0xcf0a, 0xcf0b, 0xcf0c, 0xcf0d, 0xcf0e,
+ 0xcf0f, 0xcf10, 0x0000, 0xcf11, 0xcf12, 0xcf13, 0xcf14, 0xcf15,
+ 0xcf16, 0xcf17, 0xcf18, 0xcf19, 0xcf1a, 0xcf1b, 0x0000, 0x0000,
+ 0x0000, 0xcf1c, 0xcf1d, 0xcf1e, 0xcf1f, 0xcf20, 0xcf21, 0xcf22,
+ 0xcf23, 0xcf24, 0xcf25, 0xcf26, 0xcf27, 0xcf28, 0xcf29, 0xcf2a,
+ 0xcf2b, 0xcf2c, 0x0000, 0xcf2d, 0xcf2e, 0xcf2f, 0xcf30, 0xcf31,
+ 0xcf32, 0xcf33, 0xcf34, 0xcf35, 0xcf36, 0xcf37, 0x0000, 0x0000,
+ 0x0000, 0xcf38, 0xcf39, 0xcf3a, 0xcf3b, 0xcf3c, 0xcf3d, 0xcf3e,
+ 0xcf3f, 0xcf40, 0xcf41, 0xcf42, 0xcf43, 0xcf44, 0xcf45, 0xcf46,
+ 0xcf47, 0xcf48, 0x0000, 0xcf49, 0xcf4a, 0xcf4b, 0xcf4c, 0xcf4d,
+ 0xcf4e, 0xcf4f, 0xcf50, 0xcf51, 0xcf52, 0xcf53, 0x0000, 0x0000,
+ 0x0000, 0xcf54, 0xcf55, 0xcf56, 0xcf57, 0xcf58, 0xcf59, 0xcf5a,
+ 0xcf5b, 0xcf5c, 0xcf5d, 0xcf5e, 0xcf5f, 0xcf60, 0xcf61, 0xcf62,
+ 0xcf63, 0xcf64, 0x0000, 0xcf65, 0xcf66, 0xcf67, 0xcf68, 0xcf69,
+ 0xcf6a, 0xcf6b, 0xcf6c, 0xcf6d, 0xcf6e, 0xcf6f, 0x0000, 0x0000,
+ 0x0000, 0xcf70, 0xcf71, 0xcf72, 0xcf73, 0xcf74, 0xcf75, 0xcf76,
+ 0xcf77, 0xcf78, 0xcf79, 0xcf7a, 0xcf7b, 0xcf7c, 0xcf7d, 0xcf7e,
+ 0xcf7f, 0xcf80, 0x0000, 0xcf81, 0xcf82, 0xcf83, 0xcf84, 0xcf85,
+ 0xcf86, 0xcf87, 0xcf88, 0xcf89, 0xcf8a, 0xcf8b, 0x0000, 0x0000,
+ 0x0000, 0xcf8c, 0xcf8d, 0xcf8e, 0xcf8f, 0xcf90, 0xcf91, 0xcf92,
+ 0xcf93, 0xcf94, 0xcf95, 0xcf96, 0xcf97, 0xcf98, 0xcf99, 0xcf9a,
+ 0xcf9b, 0xcf9c, 0x0000, 0xcf9d, 0xcf9e, 0xcf9f, 0xcfa0, 0xcfa1,
+ 0xcfa2, 0xcfa3, 0xcfa4, 0xcfa5, 0xcfa6, 0xcfa7, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xcfa8, 0xcfa9, 0xcfaa, 0xcfab, 0xcfac, 0xcfad, 0xcfae,
+ 0xcfaf, 0xcfb0, 0xcfb1, 0xcfb2, 0xcfb3, 0xcfb4, 0xcfb5, 0xcfb6,
+ 0xcfb7, 0xcfb8, 0x0000, 0xcfb9, 0xcfba, 0xcfbb, 0xcfbc, 0xcfbd,
+ 0xcfbe, 0xcfbf, 0xcfc0, 0xcfc1, 0xcfc2, 0xcfc3, 0x0000, 0x0000,
+ 0x0000, 0xcfc4, 0xcfc5, 0xcfc6, 0xcfc7, 0xcfc8, 0xcfc9, 0xcfca,
+ 0xcfcb, 0xcfcc, 0xcfcd, 0xcfce, 0xcfcf, 0xcfd0, 0xcfd1, 0xcfd2,
+ 0xcfd3, 0xcfd4, 0x0000, 0xcfd5, 0xcfd6, 0xcfd7, 0xcfd8, 0xcfd9,
+ 0xcfda, 0xcfdb, 0xcfdc, 0xcfdd, 0xcfde, 0xcfdf, 0x0000, 0x0000,
+ 0x0000, 0xcfe0, 0xcfe1, 0xcfe2, 0xcfe3, 0xcfe4, 0xcfe5, 0xcfe6,
+ 0xcfe7, 0xcfe8, 0xcfe9, 0xcfea, 0xcfeb, 0xcfec, 0xcfed, 0xcfee,
+ 0xcfef, 0xcff0, 0x0000, 0xcff1, 0xcff2, 0xcff3, 0xcff4, 0xcff5,
+ 0xcff6, 0xcff7, 0xcff8, 0xcff9, 0xcffa, 0xcffb, 0x0000, 0x0000,
+ 0x0000, 0xcffc, 0xcffd, 0xcffe, 0xcfff, 0xd000, 0xd001, 0xd002,
+ 0xd003, 0xd004, 0xd005, 0xd006, 0xd007, 0xd008, 0xd009, 0xd00a,
+ 0xd00b, 0xd00c, 0x0000, 0xd00d, 0xd00e, 0xd00f, 0xd010, 0xd011,
+ 0xd012, 0xd013, 0xd014, 0xd015, 0xd016, 0xd017, 0x0000, 0x0000,
+ 0x0000, 0xd018, 0xd019, 0xd01a, 0xd01b, 0xd01c, 0xd01d, 0xd01e,
+ 0xd01f, 0xd020, 0xd021, 0xd022, 0xd023, 0xd024, 0xd025, 0xd026,
+ 0xd027, 0xd028, 0x0000, 0xd029, 0xd02a, 0xd02b, 0xd02c, 0xd02d,
+ 0xd02e, 0xd02f, 0xd030, 0xd031, 0xd032, 0xd033, 0x0000, 0x0000,
+ 0x0000, 0xd034, 0xd035, 0xd036, 0xd037, 0xd038, 0xd039, 0xd03a,
+ 0xd03b, 0xd03c, 0xd03d, 0xd03e, 0xd03f, 0xd040, 0xd041, 0xd042,
+ 0xd043, 0xd044, 0x0000, 0xd045, 0xd046, 0xd047, 0xd048, 0xd049,
+ 0xd04a, 0xd04b, 0xd04c, 0xd04d, 0xd04e, 0xd04f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd050, 0xd051, 0xd052, 0xd053, 0xd054, 0xd055, 0xd056,
+ 0xd057, 0xd058, 0xd059, 0xd05a, 0xd05b, 0xd05c, 0xd05d, 0xd05e,
+ 0xd05f, 0xd060, 0x0000, 0xd061, 0xd062, 0xd063, 0xd064, 0xd065,
+ 0xd066, 0xd067, 0xd068, 0xd069, 0xd06a, 0xd06b, 0x0000, 0x0000,
+ 0x0000, 0xd06c, 0xd06d, 0xd06e, 0xd06f, 0xd070, 0xd071, 0xd072,
+ 0xd073, 0xd074, 0xd075, 0xd076, 0xd077, 0xd078, 0xd079, 0xd07a,
+ 0xd07b, 0xd07c, 0x0000, 0xd07d, 0xd07e, 0xd07f, 0xd080, 0xd081,
+ 0xd082, 0xd083, 0xd084, 0xd085, 0xd086, 0xd087, 0x0000, 0x0000,
+ 0x0000, 0xd088, 0xd089, 0xd08a, 0xd08b, 0xd08c, 0xd08d, 0xd08e,
+ 0xd08f, 0xd090, 0xd091, 0xd092, 0xd093, 0xd094, 0xd095, 0xd096,
+ 0xd097, 0xd098, 0x0000, 0xd099, 0xd09a, 0xd09b, 0xd09c, 0xd09d,
+ 0xd09e, 0xd09f, 0xd0a0, 0xd0a1, 0xd0a2, 0xd0a3, 0x0000, 0x0000,
+ 0x0000, 0xd0a4, 0xd0a5, 0xd0a6, 0xd0a7, 0xd0a8, 0xd0a9, 0xd0aa,
+ 0xd0ab, 0xd0ac, 0xd0ad, 0xd0ae, 0xd0af, 0xd0b0, 0xd0b1, 0xd0b2,
+ 0xd0b3, 0xd0b4, 0x0000, 0xd0b5, 0xd0b6, 0xd0b7, 0xd0b8, 0xd0b9,
+ 0xd0ba, 0xd0bb, 0xd0bc, 0xd0bd, 0xd0be, 0xd0bf, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd0c0, 0xd0c1, 0xd0c2, 0xd0c3, 0xd0c4, 0xd0c5, 0xd0c6,
+ 0xd0c7, 0xd0c8, 0xd0c9, 0xd0ca, 0xd0cb, 0xd0cc, 0xd0cd, 0xd0ce,
+ 0xd0cf, 0xd0d0, 0x0000, 0xd0d1, 0xd0d2, 0xd0d3, 0xd0d4, 0xd0d5,
+ 0xd0d6, 0xd0d7, 0xd0d8, 0xd0d9, 0xd0da, 0xd0db, 0x0000, 0x0000,
+ 0x0000, 0xd0dc, 0xd0dd, 0xd0de, 0xd0df, 0xd0e0, 0xd0e1, 0xd0e2,
+ 0xd0e3, 0xd0e4, 0xd0e5, 0xd0e6, 0xd0e7, 0xd0e8, 0xd0e9, 0xd0ea,
+ 0xd0eb, 0xd0ec, 0x0000, 0xd0ed, 0xd0ee, 0xd0ef, 0xd0f0, 0xd0f1,
+ 0xd0f2, 0xd0f3, 0xd0f4, 0xd0f5, 0xd0f6, 0xd0f7, 0x0000, 0x0000,
+ 0x0000, 0xd0f8, 0xd0f9, 0xd0fa, 0xd0fb, 0xd0fc, 0xd0fd, 0xd0fe,
+ 0xd0ff, 0xd100, 0xd101, 0xd102, 0xd103, 0xd104, 0xd105, 0xd106,
+ 0xd107, 0xd108, 0x0000, 0xd109, 0xd10a, 0xd10b, 0xd10c, 0xd10d,
+ 0xd10e, 0xd10f, 0xd110, 0xd111, 0xd112, 0xd113, 0x0000, 0x0000,
+ 0x0000, 0xd114, 0xd115, 0xd116, 0xd117, 0xd118, 0xd119, 0xd11a,
+ 0xd11b, 0xd11c, 0xd11d, 0xd11e, 0xd11f, 0xd120, 0xd121, 0xd122,
+ 0xd123, 0xd124, 0x0000, 0xd125, 0xd126, 0xd127, 0xd128, 0xd129,
+ 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd12f, 0x0000, 0x0000,
+ 0x0000, 0xd130, 0xd131, 0xd132, 0xd133, 0xd134, 0xd135, 0xd136,
+ 0xd137, 0xd138, 0xd139, 0xd13a, 0xd13b, 0xd13c, 0xd13d, 0xd13e,
+ 0xd13f, 0xd140, 0x0000, 0xd141, 0xd142, 0xd143, 0xd144, 0xd145,
+ 0xd146, 0xd147, 0xd148, 0xd149, 0xd14a, 0xd14b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd14c, 0xd14d, 0xd14e, 0xd14f, 0xd150, 0xd151, 0xd152,
+ 0xd153, 0xd154, 0xd155, 0xd156, 0xd157, 0xd158, 0xd159, 0xd15a,
+ 0xd15b, 0xd15c, 0x0000, 0xd15d, 0xd15e, 0xd15f, 0xd160, 0xd161,
+ 0xd162, 0xd163, 0xd164, 0xd165, 0xd166, 0xd167, 0x0000, 0x0000,
+ 0x0000, 0xd168, 0xd169, 0xd16a, 0xd16b, 0xd16c, 0xd16d, 0xd16e,
+ 0xd16f, 0xd170, 0xd171, 0xd172, 0xd173, 0xd174, 0xd175, 0xd176,
+ 0xd177, 0xd178, 0x0000, 0xd179, 0xd17a, 0xd17b, 0xd17c, 0xd17d,
+ 0xd17e, 0xd17f, 0xd180, 0xd181, 0xd182, 0xd183, 0x0000, 0x0000,
+ 0x0000, 0xd184, 0xd185, 0xd186, 0xd187, 0xd188, 0xd189, 0xd18a,
+ 0xd18b, 0xd18c, 0xd18d, 0xd18e, 0xd18f, 0xd190, 0xd191, 0xd192,
+ 0xd193, 0xd194, 0x0000, 0xd195, 0xd196, 0xd197, 0xd198, 0xd199,
+ 0xd19a, 0xd19b, 0xd19c, 0xd19d, 0xd19e, 0xd19f, 0x0000, 0x0000,
+ 0x0000, 0xd1a0, 0xd1a1, 0xd1a2, 0xd1a3, 0xd1a4, 0xd1a5, 0xd1a6,
+ 0xd1a7, 0xd1a8, 0xd1a9, 0xd1aa, 0xd1ab, 0xd1ac, 0xd1ad, 0xd1ae,
+ 0xd1af, 0xd1b0, 0x0000, 0xd1b1, 0xd1b2, 0xd1b3, 0xd1b4, 0xd1b5,
+ 0xd1b6, 0xd1b7, 0xd1b8, 0xd1b9, 0xd1ba, 0xd1bb, 0x0000, 0x0000,
+ 0x0000, 0xd1bc, 0xd1bd, 0xd1be, 0xd1bf, 0xd1c0, 0xd1c1, 0xd1c2,
+ 0xd1c3, 0xd1c4, 0xd1c5, 0xd1c6, 0xd1c7, 0xd1c8, 0xd1c9, 0xd1ca,
+ 0xd1cb, 0xd1cc, 0x0000, 0xd1cd, 0xd1ce, 0xd1cf, 0xd1d0, 0xd1d1,
+ 0xd1d2, 0xd1d3, 0xd1d4, 0xd1d5, 0xd1d6, 0xd1d7, 0x0000, 0x0000,
+ 0x0000, 0xd1d8, 0xd1d9, 0xd1da, 0xd1db, 0xd1dc, 0xd1dd, 0xd1de,
+ 0xd1df, 0xd1e0, 0xd1e1, 0xd1e2, 0xd1e3, 0xd1e4, 0xd1e5, 0xd1e6,
+ 0xd1e7, 0xd1e8, 0x0000, 0xd1e9, 0xd1ea, 0xd1eb, 0xd1ec, 0xd1ed,
+ 0xd1ee, 0xd1ef, 0xd1f0, 0xd1f1, 0xd1f2, 0xd1f3, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd1f4, 0xd1f5, 0xd1f6, 0xd1f7, 0xd1f8, 0xd1f9, 0xd1fa,
+ 0xd1fb, 0xd1fc, 0xd1fd, 0xd1fe, 0xd1ff, 0xd200, 0xd201, 0xd202,
+ 0xd203, 0xd204, 0x0000, 0xd205, 0xd206, 0xd207, 0xd208, 0xd209,
+ 0xd20a, 0xd20b, 0xd20c, 0xd20d, 0xd20e, 0xd20f, 0x0000, 0x0000,
+ 0x0000, 0xd210, 0xd211, 0xd212, 0xd213, 0xd214, 0xd215, 0xd216,
+ 0xd217, 0xd218, 0xd219, 0xd21a, 0xd21b, 0xd21c, 0xd21d, 0xd21e,
+ 0xd21f, 0xd220, 0x0000, 0xd221, 0xd222, 0xd223, 0xd224, 0xd225,
+ 0xd226, 0xd227, 0xd228, 0xd229, 0xd22a, 0xd22b, 0x0000, 0x0000,
+ 0x0000, 0xd22c, 0xd22d, 0xd22e, 0xd22f, 0xd230, 0xd231, 0xd232,
+ 0xd233, 0xd234, 0xd235, 0xd236, 0xd237, 0xd238, 0xd239, 0xd23a,
+ 0xd23b, 0xd23c, 0x0000, 0xd23d, 0xd23e, 0xd23f, 0xd240, 0xd241,
+ 0xd242, 0xd243, 0xd244, 0xd245, 0xd246, 0xd247, 0x0000, 0x0000,
+ 0x0000, 0xd248, 0xd249, 0xd24a, 0xd24b, 0xd24c, 0xd24d, 0xd24e,
+ 0xd24f, 0xd250, 0xd251, 0xd252, 0xd253, 0xd254, 0xd255, 0xd256,
+ 0xd257, 0xd258, 0x0000, 0xd259, 0xd25a, 0xd25b, 0xd25c, 0xd25d,
+ 0xd25e, 0xd25f, 0xd260, 0xd261, 0xd262, 0xd263, 0x0000, 0x0000,
+ 0x0000, 0xd264, 0xd265, 0xd266, 0xd267, 0xd268, 0xd269, 0xd26a,
+ 0xd26b, 0xd26c, 0xd26d, 0xd26e, 0xd26f, 0xd270, 0xd271, 0xd272,
+ 0xd273, 0xd274, 0x0000, 0xd275, 0xd276, 0xd277, 0xd278, 0xd279,
+ 0xd27a, 0xd27b, 0xd27c, 0xd27d, 0xd27e, 0xd27f, 0x0000, 0x0000,
+ 0x0000, 0xd280, 0xd281, 0xd282, 0xd283, 0xd284, 0xd285, 0xd286,
+ 0xd287, 0xd288, 0xd289, 0xd28a, 0xd28b, 0xd28c, 0xd28d, 0xd28e,
+ 0xd28f, 0xd290, 0x0000, 0xd291, 0xd292, 0xd293, 0xd294, 0xd295,
+ 0xd296, 0xd297, 0xd298, 0xd299, 0xd29a, 0xd29b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd29c, 0xd29d, 0xd29e, 0xd29f, 0xd2a0, 0xd2a1, 0xd2a2,
+ 0xd2a3, 0xd2a4, 0xd2a5, 0xd2a6, 0xd2a7, 0xd2a8, 0xd2a9, 0xd2aa,
+ 0xd2ab, 0xd2ac, 0x0000, 0xd2ad, 0xd2ae, 0xd2af, 0xd2b0, 0xd2b1,
+ 0xd2b2, 0xd2b3, 0xd2b4, 0xd2b5, 0xd2b6, 0xd2b7, 0x0000, 0x0000,
+ 0x0000, 0xd2b8, 0xd2b9, 0xd2ba, 0xd2bb, 0xd2bc, 0xd2bd, 0xd2be,
+ 0xd2bf, 0xd2c0, 0xd2c1, 0xd2c2, 0xd2c3, 0xd2c4, 0xd2c5, 0xd2c6,
+ 0xd2c7, 0xd2c8, 0x0000, 0xd2c9, 0xd2ca, 0xd2cb, 0xd2cc, 0xd2cd,
+ 0xd2ce, 0xd2cf, 0xd2d0, 0xd2d1, 0xd2d2, 0xd2d3, 0x0000, 0x0000,
+ 0x0000, 0xd2d4, 0xd2d5, 0xd2d6, 0xd2d7, 0xd2d8, 0xd2d9, 0xd2da,
+ 0xd2db, 0xd2dc, 0xd2dd, 0xd2de, 0xd2df, 0xd2e0, 0xd2e1, 0xd2e2,
+ 0xd2e3, 0xd2e4, 0x0000, 0xd2e5, 0xd2e6, 0xd2e7, 0xd2e8, 0xd2e9,
+ 0xd2ea, 0xd2eb, 0xd2ec, 0xd2ed, 0xd2ee, 0xd2ef, 0x0000, 0x0000,
+ 0x0000, 0xd2f0, 0xd2f1, 0xd2f2, 0xd2f3, 0xd2f4, 0xd2f5, 0xd2f6,
+ 0xd2f7, 0xd2f8, 0xd2f9, 0xd2fa, 0xd2fb, 0xd2fc, 0xd2fd, 0xd2fe,
+ 0xd2ff, 0xd300, 0x0000, 0xd301, 0xd302, 0xd303, 0xd304, 0xd305,
+ 0xd306, 0xd307, 0xd308, 0xd309, 0xd30a, 0xd30b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd30c, 0xd30d, 0xd30e, 0xd30f, 0xd310, 0xd311, 0xd312,
+ 0xd313, 0xd314, 0xd315, 0xd316, 0xd317, 0xd318, 0xd319, 0xd31a,
+ 0xd31b, 0xd31c, 0x0000, 0xd31d, 0xd31e, 0xd31f, 0xd320, 0xd321,
+ 0xd322, 0xd323, 0xd324, 0xd325, 0xd326, 0xd327, 0x0000, 0x0000,
+ 0x0000, 0xd328, 0xd329, 0xd32a, 0xd32b, 0xd32c, 0xd32d, 0xd32e,
+ 0xd32f, 0xd330, 0xd331, 0xd332, 0xd333, 0xd334, 0xd335, 0xd336,
+ 0xd337, 0xd338, 0x0000, 0xd339, 0xd33a, 0xd33b, 0xd33c, 0xd33d,
+ 0xd33e, 0xd33f, 0xd340, 0xd341, 0xd342, 0xd343, 0x0000, 0x0000,
+ 0x0000, 0xd344, 0xd345, 0xd346, 0xd347, 0xd348, 0xd349, 0xd34a,
+ 0xd34b, 0xd34c, 0xd34d, 0xd34e, 0xd34f, 0xd350, 0xd351, 0xd352,
+ 0xd353, 0xd354, 0x0000, 0xd355, 0xd356, 0xd357, 0xd358, 0xd359,
+ 0xd35a, 0xd35b, 0xd35c, 0xd35d, 0xd35e, 0xd35f, 0x0000, 0x0000,
+ 0x0000, 0xd360, 0xd361, 0xd362, 0xd363, 0xd364, 0xd365, 0xd366,
+ 0xd367, 0xd368, 0xd369, 0xd36a, 0xd36b, 0xd36c, 0xd36d, 0xd36e,
+ 0xd36f, 0xd370, 0x0000, 0xd371, 0xd372, 0xd373, 0xd374, 0xd375,
+ 0xd376, 0xd377, 0xd378, 0xd379, 0xd37a, 0xd37b, 0x0000, 0x0000,
+ 0x0000, 0xd37c, 0xd37d, 0xd37e, 0xd37f, 0xd380, 0xd381, 0xd382,
+ 0xd383, 0xd384, 0xd385, 0xd386, 0xd387, 0xd388, 0xd389, 0xd38a,
+ 0xd38b, 0xd38c, 0x0000, 0xd38d, 0xd38e, 0xd38f, 0xd390, 0xd391,
+ 0xd392, 0xd393, 0xd394, 0xd395, 0xd396, 0xd397, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd398, 0xd399, 0xd39a, 0xd39b, 0xd39c, 0xd39d, 0xd39e,
+ 0xd39f, 0xd3a0, 0xd3a1, 0xd3a2, 0xd3a3, 0xd3a4, 0xd3a5, 0xd3a6,
+ 0xd3a7, 0xd3a8, 0x0000, 0xd3a9, 0xd3aa, 0xd3ab, 0xd3ac, 0xd3ad,
+ 0xd3ae, 0xd3af, 0xd3b0, 0xd3b1, 0xd3b2, 0xd3b3, 0x0000, 0x0000,
+ 0x0000, 0xd3b4, 0xd3b5, 0xd3b6, 0xd3b7, 0xd3b8, 0xd3b9, 0xd3ba,
+ 0xd3bb, 0xd3bc, 0xd3bd, 0xd3be, 0xd3bf, 0xd3c0, 0xd3c1, 0xd3c2,
+ 0xd3c3, 0xd3c4, 0x0000, 0xd3c5, 0xd3c6, 0xd3c7, 0xd3c8, 0xd3c9,
+ 0xd3ca, 0xd3cb, 0xd3cc, 0xd3cd, 0xd3ce, 0xd3cf, 0x0000, 0x0000,
+ 0x0000, 0xd3d0, 0xd3d1, 0xd3d2, 0xd3d3, 0xd3d4, 0xd3d5, 0xd3d6,
+ 0xd3d7, 0xd3d8, 0xd3d9, 0xd3da, 0xd3db, 0xd3dc, 0xd3dd, 0xd3de,
+ 0xd3df, 0xd3e0, 0x0000, 0xd3e1, 0xd3e2, 0xd3e3, 0xd3e4, 0xd3e5,
+ 0xd3e6, 0xd3e7, 0xd3e8, 0xd3e9, 0xd3ea, 0xd3eb, 0x0000, 0x0000,
+ 0x0000, 0xd3ec, 0xd3ed, 0xd3ee, 0xd3ef, 0xd3f0, 0xd3f1, 0xd3f2,
+ 0xd3f3, 0xd3f4, 0xd3f5, 0xd3f6, 0xd3f7, 0xd3f8, 0xd3f9, 0xd3fa,
+ 0xd3fb, 0xd3fc, 0x0000, 0xd3fd, 0xd3fe, 0xd3ff, 0xd400, 0xd401,
+ 0xd402, 0xd403, 0xd404, 0xd405, 0xd406, 0xd407, 0x0000, 0x0000,
+ 0x0000, 0xd408, 0xd409, 0xd40a, 0xd40b, 0xd40c, 0xd40d, 0xd40e,
+ 0xd40f, 0xd410, 0xd411, 0xd412, 0xd413, 0xd414, 0xd415, 0xd416,
+ 0xd417, 0xd418, 0x0000, 0xd419, 0xd41a, 0xd41b, 0xd41c, 0xd41d,
+ 0xd41e, 0xd41f, 0xd420, 0xd421, 0xd422, 0xd423, 0x0000, 0x0000,
+ 0x0000, 0xd424, 0xd425, 0xd426, 0xd427, 0xd428, 0xd429, 0xd42a,
+ 0xd42b, 0xd42c, 0xd42d, 0xd42e, 0xd42f, 0xd430, 0xd431, 0xd432,
+ 0xd433, 0xd434, 0x0000, 0xd435, 0xd436, 0xd437, 0xd438, 0xd439,
+ 0xd43a, 0xd43b, 0xd43c, 0xd43d, 0xd43e, 0xd43f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd440, 0xd441, 0xd442, 0xd443, 0xd444, 0xd445, 0xd446,
+ 0xd447, 0xd448, 0xd449, 0xd44a, 0xd44b, 0xd44c, 0xd44d, 0xd44e,
+ 0xd44f, 0xd450, 0x0000, 0xd451, 0xd452, 0xd453, 0xd454, 0xd455,
+ 0xd456, 0xd457, 0xd458, 0xd459, 0xd45a, 0xd45b, 0x0000, 0x0000,
+ 0x0000, 0xd45c, 0xd45d, 0xd45e, 0xd45f, 0xd460, 0xd461, 0xd462,
+ 0xd463, 0xd464, 0xd465, 0xd466, 0xd467, 0xd468, 0xd469, 0xd46a,
+ 0xd46b, 0xd46c, 0x0000, 0xd46d, 0xd46e, 0xd46f, 0xd470, 0xd471,
+ 0xd472, 0xd473, 0xd474, 0xd475, 0xd476, 0xd477, 0x0000, 0x0000,
+ 0x0000, 0xd478, 0xd479, 0xd47a, 0xd47b, 0xd47c, 0xd47d, 0xd47e,
+ 0xd47f, 0xd480, 0xd481, 0xd482, 0xd483, 0xd484, 0xd485, 0xd486,
+ 0xd487, 0xd488, 0x0000, 0xd489, 0xd48a, 0xd48b, 0xd48c, 0xd48d,
+ 0xd48e, 0xd48f, 0xd490, 0xd491, 0xd492, 0xd493, 0x0000, 0x0000,
+ 0x0000, 0xd494, 0xd495, 0xd496, 0xd497, 0xd498, 0xd499, 0xd49a,
+ 0xd49b, 0xd49c, 0xd49d, 0xd49e, 0xd49f, 0xd4a0, 0xd4a1, 0xd4a2,
+ 0xd4a3, 0xd4a4, 0x0000, 0xd4a5, 0xd4a6, 0xd4a7, 0xd4a8, 0xd4a9,
+ 0xd4aa, 0xd4ab, 0xd4ac, 0xd4ad, 0xd4ae, 0xd4af, 0x0000, 0x0000,
+ 0x0000, 0xd4b0, 0xd4b1, 0xd4b2, 0xd4b3, 0xd4b4, 0xd4b5, 0xd4b6,
+ 0xd4b7, 0xd4b8, 0xd4b9, 0xd4ba, 0xd4bb, 0xd4bc, 0xd4bd, 0xd4be,
+ 0xd4bf, 0xd4c0, 0x0000, 0xd4c1, 0xd4c2, 0xd4c3, 0xd4c4, 0xd4c5,
+ 0xd4c6, 0xd4c7, 0xd4c8, 0xd4c9, 0xd4ca, 0xd4cb, 0x0000, 0x0000,
+ 0x0000, 0xd4cc, 0xd4cd, 0xd4ce, 0xd4cf, 0xd4d0, 0xd4d1, 0xd4d2,
+ 0xd4d3, 0xd4d4, 0xd4d5, 0xd4d6, 0xd4d7, 0xd4d8, 0xd4d9, 0xd4da,
+ 0xd4db, 0xd4dc, 0x0000, 0xd4dd, 0xd4de, 0xd4df, 0xd4e0, 0xd4e1,
+ 0xd4e2, 0xd4e3, 0xd4e4, 0xd4e5, 0xd4e6, 0xd4e7, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd4e8, 0xd4e9, 0xd4ea, 0xd4eb, 0xd4ec, 0xd4ed, 0xd4ee,
+ 0xd4ef, 0xd4f0, 0xd4f1, 0xd4f2, 0xd4f3, 0xd4f4, 0xd4f5, 0xd4f6,
+ 0xd4f7, 0xd4f8, 0x0000, 0xd4f9, 0xd4fa, 0xd4fb, 0xd4fc, 0xd4fd,
+ 0xd4fe, 0xd4ff, 0xd500, 0xd501, 0xd502, 0xd503, 0x0000, 0x0000,
+ 0x0000, 0xd504, 0xd505, 0xd506, 0xd507, 0xd508, 0xd509, 0xd50a,
+ 0xd50b, 0xd50c, 0xd50d, 0xd50e, 0xd50f, 0xd510, 0xd511, 0xd512,
+ 0xd513, 0xd514, 0x0000, 0xd515, 0xd516, 0xd517, 0xd518, 0xd519,
+ 0xd51a, 0xd51b, 0xd51c, 0xd51d, 0xd51e, 0xd51f, 0x0000, 0x0000,
+ 0x0000, 0xd520, 0xd521, 0xd522, 0xd523, 0xd524, 0xd525, 0xd526,
+ 0xd527, 0xd528, 0xd529, 0xd52a, 0xd52b, 0xd52c, 0xd52d, 0xd52e,
+ 0xd52f, 0xd530, 0x0000, 0xd531, 0xd532, 0xd533, 0xd534, 0xd535,
+ 0xd536, 0xd537, 0xd538, 0xd539, 0xd53a, 0xd53b, 0x0000, 0x0000,
+ 0x0000, 0xd53c, 0xd53d, 0xd53e, 0xd53f, 0xd540, 0xd541, 0xd542,
+ 0xd543, 0xd544, 0xd545, 0xd546, 0xd547, 0xd548, 0xd549, 0xd54a,
+ 0xd54b, 0xd54c, 0x0000, 0xd54d, 0xd54e, 0xd54f, 0xd550, 0xd551,
+ 0xd552, 0xd553, 0xd554, 0xd555, 0xd556, 0xd557, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd558, 0xd559, 0xd55a, 0xd55b, 0xd55c, 0xd55d, 0xd55e,
+ 0xd55f, 0xd560, 0xd561, 0xd562, 0xd563, 0xd564, 0xd565, 0xd566,
+ 0xd567, 0xd568, 0x0000, 0xd569, 0xd56a, 0xd56b, 0xd56c, 0xd56d,
+ 0xd56e, 0xd56f, 0xd570, 0xd571, 0xd572, 0xd573, 0x0000, 0x0000,
+ 0x0000, 0xd574, 0xd575, 0xd576, 0xd577, 0xd578, 0xd579, 0xd57a,
+ 0xd57b, 0xd57c, 0xd57d, 0xd57e, 0xd57f, 0xd580, 0xd581, 0xd582,
+ 0xd583, 0xd584, 0x0000, 0xd585, 0xd586, 0xd587, 0xd588, 0xd589,
+ 0xd58a, 0xd58b, 0xd58c, 0xd58d, 0xd58e, 0xd58f, 0x0000, 0x0000,
+ 0x0000, 0xd590, 0xd591, 0xd592, 0xd593, 0xd594, 0xd595, 0xd596,
+ 0xd597, 0xd598, 0xd599, 0xd59a, 0xd59b, 0xd59c, 0xd59d, 0xd59e,
+ 0xd59f, 0xd5a0, 0x0000, 0xd5a1, 0xd5a2, 0xd5a3, 0xd5a4, 0xd5a5,
+ 0xd5a6, 0xd5a7, 0xd5a8, 0xd5a9, 0xd5aa, 0xd5ab, 0x0000, 0x0000,
+ 0x0000, 0xd5ac, 0xd5ad, 0xd5ae, 0xd5af, 0xd5b0, 0xd5b1, 0xd5b2,
+ 0xd5b3, 0xd5b4, 0xd5b5, 0xd5b6, 0xd5b7, 0xd5b8, 0xd5b9, 0xd5ba,
+ 0xd5bb, 0xd5bc, 0x0000, 0xd5bd, 0xd5be, 0xd5bf, 0xd5c0, 0xd5c1,
+ 0xd5c2, 0xd5c3, 0xd5c4, 0xd5c5, 0xd5c6, 0xd5c7, 0x0000, 0x0000,
+ 0x0000, 0xd5c8, 0xd5c9, 0xd5ca, 0xd5cb, 0xd5cc, 0xd5cd, 0xd5ce,
+ 0xd5cf, 0xd5d0, 0xd5d1, 0xd5d2, 0xd5d3, 0xd5d4, 0xd5d5, 0xd5d6,
+ 0xd5d7, 0xd5d8, 0x0000, 0xd5d9, 0xd5da, 0xd5db, 0xd5dc, 0xd5dd,
+ 0xd5de, 0xd5df, 0xd5e0, 0xd5e1, 0xd5e2, 0xd5e3, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd5e4, 0xd5e5, 0xd5e6, 0xd5e7, 0xd5e8, 0xd5e9, 0xd5ea,
+ 0xd5eb, 0xd5ec, 0xd5ed, 0xd5ee, 0xd5ef, 0xd5f0, 0xd5f1, 0xd5f2,
+ 0xd5f3, 0xd5f4, 0x0000, 0xd5f5, 0xd5f6, 0xd5f7, 0xd5f8, 0xd5f9,
+ 0xd5fa, 0xd5fb, 0xd5fc, 0xd5fd, 0xd5fe, 0xd5ff, 0x0000, 0x0000,
+ 0x0000, 0xd600, 0xd601, 0xd602, 0xd603, 0xd604, 0xd605, 0xd606,
+ 0xd607, 0xd608, 0xd609, 0xd60a, 0xd60b, 0xd60c, 0xd60d, 0xd60e,
+ 0xd60f, 0xd610, 0x0000, 0xd611, 0xd612, 0xd613, 0xd614, 0xd615,
+ 0xd616, 0xd617, 0xd618, 0xd619, 0xd61a, 0xd61b, 0x0000, 0x0000,
+ 0x0000, 0xd61c, 0xd61d, 0xd61e, 0xd61f, 0xd620, 0xd621, 0xd622,
+ 0xd623, 0xd624, 0xd625, 0xd626, 0xd627, 0xd628, 0xd629, 0xd62a,
+ 0xd62b, 0xd62c, 0x0000, 0xd62d, 0xd62e, 0xd62f, 0xd630, 0xd631,
+ 0xd632, 0xd633, 0xd634, 0xd635, 0xd636, 0xd637, 0x0000, 0x0000,
+ 0x0000, 0xd638, 0xd639, 0xd63a, 0xd63b, 0xd63c, 0xd63d, 0xd63e,
+ 0xd63f, 0xd640, 0xd641, 0xd642, 0xd643, 0xd644, 0xd645, 0xd646,
+ 0xd647, 0xd648, 0x0000, 0xd649, 0xd64a, 0xd64b, 0xd64c, 0xd64d,
+ 0xd64e, 0xd64f, 0xd650, 0xd651, 0xd652, 0xd653, 0x0000, 0x0000,
+ 0x0000, 0xd654, 0xd655, 0xd656, 0xd657, 0xd658, 0xd659, 0xd65a,
+ 0xd65b, 0xd65c, 0xd65d, 0xd65e, 0xd65f, 0xd660, 0xd661, 0xd662,
+ 0xd663, 0xd664, 0x0000, 0xd665, 0xd666, 0xd667, 0xd668, 0xd669,
+ 0xd66a, 0xd66b, 0xd66c, 0xd66d, 0xd66e, 0xd66f, 0x0000, 0x0000,
+ 0x0000, 0xd670, 0xd671, 0xd672, 0xd673, 0xd674, 0xd675, 0xd676,
+ 0xd677, 0xd678, 0xd679, 0xd67a, 0xd67b, 0xd67c, 0xd67d, 0xd67e,
+ 0xd67f, 0xd680, 0x0000, 0xd681, 0xd682, 0xd683, 0xd684, 0xd685,
+ 0xd686, 0xd687, 0xd688, 0xd689, 0xd68a, 0xd68b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd68c, 0xd68d, 0xd68e, 0xd68f, 0xd690, 0xd691, 0xd692,
+ 0xd693, 0xd694, 0xd695, 0xd696, 0xd697, 0xd698, 0xd699, 0xd69a,
+ 0xd69b, 0xd69c, 0x0000, 0xd69d, 0xd69e, 0xd69f, 0xd6a0, 0xd6a1,
+ 0xd6a2, 0xd6a3, 0xd6a4, 0xd6a5, 0xd6a6, 0xd6a7, 0x0000, 0x0000,
+ 0x0000, 0xd6a8, 0xd6a9, 0xd6aa, 0xd6ab, 0xd6ac, 0xd6ad, 0xd6ae,
+ 0xd6af, 0xd6b0, 0xd6b1, 0xd6b2, 0xd6b3, 0xd6b4, 0xd6b5, 0xd6b6,
+ 0xd6b7, 0xd6b8, 0x0000, 0xd6b9, 0xd6ba, 0xd6bb, 0xd6bc, 0xd6bd,
+ 0xd6be, 0xd6bf, 0xd6c0, 0xd6c1, 0xd6c2, 0xd6c3, 0x0000, 0x0000,
+ 0x0000, 0xd6c4, 0xd6c5, 0xd6c6, 0xd6c7, 0xd6c8, 0xd6c9, 0xd6ca,
+ 0xd6cb, 0xd6cc, 0xd6cd, 0xd6ce, 0xd6cf, 0xd6d0, 0xd6d1, 0xd6d2,
+ 0xd6d3, 0xd6d4, 0x0000, 0xd6d5, 0xd6d6, 0xd6d7, 0xd6d8, 0xd6d9,
+ 0xd6da, 0xd6db, 0xd6dc, 0xd6dd, 0xd6de, 0xd6df, 0x0000, 0x0000,
+ 0x0000, 0xd6e0, 0xd6e1, 0xd6e2, 0xd6e3, 0xd6e4, 0xd6e5, 0xd6e6,
+ 0xd6e7, 0xd6e8, 0xd6e9, 0xd6ea, 0xd6eb, 0xd6ec, 0xd6ed, 0xd6ee,
+ 0xd6ef, 0xd6f0, 0x0000, 0xd6f1, 0xd6f2, 0xd6f3, 0xd6f4, 0xd6f5,
+ 0xd6f6, 0xd6f7, 0xd6f8, 0xd6f9, 0xd6fa, 0xd6fb, 0x0000, 0x0000,
+ 0x0000, 0xd6fc, 0xd6fd, 0xd6fe, 0xd6ff, 0xd700, 0xd701, 0xd702,
+ 0xd703, 0xd704, 0xd705, 0xd706, 0xd707, 0xd708, 0xd709, 0xd70a,
+ 0xd70b, 0xd70c, 0x0000, 0xd70d, 0xd70e, 0xd70f, 0xd710, 0xd711,
+ 0xd712, 0xd713, 0xd714, 0xd715, 0xd716, 0xd717, 0x0000, 0x0000,
+ 0x0000, 0xd718, 0xd719, 0xd71a, 0xd71b, 0xd71c, 0xd71d, 0xd71e,
+ 0xd71f, 0xd720, 0xd721, 0xd722, 0xd723, 0xd724, 0xd725, 0xd726,
+ 0xd727, 0xd728, 0x0000, 0xd729, 0xd72a, 0xd72b, 0xd72c, 0xd72d,
+ 0xd72e, 0xd72f, 0xd730, 0xd731, 0xd732, 0xd733, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd734, 0xd735, 0xd736, 0xd737, 0xd738, 0xd739, 0xd73a,
+ 0xd73b, 0xd73c, 0xd73d, 0xd73e, 0xd73f, 0xd740, 0xd741, 0xd742,
+ 0xd743, 0xd744, 0x0000, 0xd745, 0xd746, 0xd747, 0xd748, 0xd749,
+ 0xd74a, 0xd74b, 0xd74c, 0xd74d, 0xd74e, 0xd74f, 0x0000, 0x0000,
+ 0x0000, 0xd750, 0xd751, 0xd752, 0xd753, 0xd754, 0xd755, 0xd756,
+ 0xd757, 0xd758, 0xd759, 0xd75a, 0xd75b, 0xd75c, 0xd75d, 0xd75e,
+ 0xd75f, 0xd760, 0x0000, 0xd761, 0xd762, 0xd763, 0xd764, 0xd765,
+ 0xd766, 0xd767, 0xd768, 0xd769, 0xd76a, 0xd76b, 0x0000, 0x0000,
+ 0x0000, 0xd76c, 0xd76d, 0xd76e, 0xd76f, 0xd770, 0xd771, 0xd772,
+ 0xd773, 0xd774, 0xd775, 0xd776, 0xd777, 0xd778, 0xd779, 0xd77a,
+ 0xd77b, 0xd77c, 0x0000, 0xd77d, 0xd77e, 0xd77f, 0xd780, 0xd781,
+ 0xd782, 0xd783, 0xd784, 0xd785, 0xd786, 0xd787, 0x0000, 0x0000,
+ 0x0000, 0xd788, 0xd789, 0xd78a, 0xd78b, 0xd78c, 0xd78d, 0xd78e,
+ 0xd78f, 0xd790, 0xd791, 0xd792, 0xd793, 0xd794, 0xd795, 0xd796,
+ 0xd797, 0xd798, 0x0000, 0xd799, 0xd79a, 0xd79b, 0xd79c, 0xd79d,
+ 0xd79e, 0xd79f, 0xd7a0, 0xd7a1, 0xd7a2, 0xd7a3, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3164, 0x3001, 0x3002, 0x30fb, 0x2025, 0x22ef, 0x00a8,
+ 0x3003, 0x2013, 0x2014, 0x2016, 0xff3c, 0xff5e, 0x2018, 0x2019,
+ 0x201c, 0x201d, 0x3014, 0x3015, 0x3008, 0x3009, 0x300a, 0x300b,
+ 0x300c, 0x300d, 0x300e, 0x300f, 0x3010, 0x3011, 0x00b1, 0x00d7,
+ 0x00f7, 0x2260, 0x2264, 0x2265, 0x221e, 0x2234, 0x00b0, 0x2032,
+ 0x2033, 0x2103, 0x212b, 0xffe0, 0xffe1, 0xffe5, 0x2642, 0x2640,
+ 0x2220, 0x22a5, 0x2312, 0x2202, 0x2207, 0x2261, 0x2252, 0x00a7,
+ 0x203b, 0x2606, 0x2605, 0x25cb, 0x25cf, 0x25ce, 0x25c7, 0x25c6,
+ 0x25a1, 0x25a0, 0x25b3, 0x25b2, 0x25bd, 0x25bc, 0x2192, 0x2190,
+ 0x2191, 0x2193, 0x2194, 0x3013, 0x00ab, 0x00bb, 0x221a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x223d, 0x221d, 0x2235, 0x222b, 0x222c, 0x2208, 0x220b,
+ 0x2286, 0x2287, 0x2282, 0x2283, 0x222a, 0x2229, 0x2227, 0x2228,
+ 0xffe2, 0x21d2, 0x21d4, 0x2200, 0x2203, 0x00b4, 0x02dc, 0x02c7,
+ 0x02d8, 0x02dd, 0x02da, 0x02d9, 0x00b8, 0x02db, 0x00a1, 0x00bf,
+ 0x2236, 0x222e, 0x2211, 0x220f, 0x00a4, 0x2109, 0x2030, 0x25c1,
+ 0x25c0, 0x25b7, 0x25b6, 0x2664, 0x2660, 0x2661, 0x2665, 0x2667,
+ 0x2663, 0x25c9, 0x25c8, 0x25a3, 0x25d0, 0x25d1, 0x2592, 0x25a4,
+ 0x25a5, 0x25a8, 0x25a7, 0x25a6, 0x25a9, 0x2668, 0x260f, 0x260e,
+ 0x261c, 0x261e, 0x00b6, 0x2020, 0x2021, 0x2195, 0x2197, 0x2199,
+ 0x2196, 0x2198, 0x266d, 0x2669, 0x266a, 0x266c, 0x327f, 0x321c,
+ 0x2116, 0x33c7, 0x2122, 0x33c2, 0x33d8, 0x2121, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xff01, 0xff02, 0xff03, 0xff04, 0xff05, 0xff06, 0xff07,
+ 0xff08, 0xff09, 0xff0a, 0xff0b, 0xff0c, 0xff0d, 0xff0e, 0xff0f,
+ 0xff10, 0xff11, 0xff12, 0xff13, 0xff14, 0xff15, 0xff16, 0xff17,
+ 0xff18, 0xff19, 0xff1a, 0xff1b, 0xff1c, 0xff1d, 0xff1e, 0xff1f,
+ 0xff20, 0xff21, 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27,
+ 0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f,
+ 0xff30, 0xff31, 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37,
+ 0xff38, 0xff39, 0xff3a, 0xff3b, 0xffe6, 0xff3d, 0xff3e, 0xff3f,
+ 0xff40, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47,
+ 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xff4f, 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55,
+ 0xff56, 0xff57, 0xff58, 0xff59, 0xff5a, 0xff5b, 0xff5c, 0xff5d,
+ 0xffe3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3165, 0x3166, 0x3167,
+ 0x3168, 0x3169, 0x316a, 0x316b, 0x316c, 0x316d, 0x316e, 0x316f,
+ 0x3170, 0x3171, 0x3172, 0x3173, 0x3174, 0x3175, 0x3176, 0x3177,
+ 0x3178, 0x3179, 0x317a, 0x317b, 0x317c, 0x317d, 0x317e, 0x317f,
+ 0x3180, 0x3181, 0x3182, 0x3183, 0x3184, 0x3185, 0x3186, 0x3187,
+ 0x3188, 0x3189, 0x318a, 0x318b, 0x318c, 0x318d, 0x318e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176,
+ 0x2177, 0x2178, 0x2179, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167,
+ 0x2168, 0x2169, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+ 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
+ 0x03a0, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8,
+ 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
+ 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x03bf, 0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03c6,
+ 0x03c7, 0x03c8, 0x03c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2500, 0x2502, 0x250c, 0x2510, 0x2518, 0x2514, 0x251c,
+ 0x252c, 0x2524, 0x2534, 0x253c, 0x2501, 0x2503, 0x250f, 0x2513,
+ 0x251b, 0x2517, 0x2523, 0x2533, 0x252b, 0x253b, 0x254b, 0x2520,
+ 0x252f, 0x2528, 0x2537, 0x253f, 0x251d, 0x2530, 0x2525, 0x2538,
+ 0x2542, 0x2512, 0x2511, 0x251a, 0x2519, 0x2516, 0x2515, 0x250e,
+ 0x250d, 0x251e, 0x251f, 0x2521, 0x2522, 0x2526, 0x2527, 0x2529,
+ 0x252a, 0x252d, 0x252e, 0x2531, 0x2532, 0x2535, 0x2536, 0x2539,
+ 0x253a, 0x253d, 0x253e, 0x2540, 0x2541, 0x2543, 0x2544, 0x2545,
+ 0x2546, 0x2547, 0x2548, 0x2549, 0x254a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3395, 0x3396, 0x3397, 0x2113, 0x3398, 0x33c4, 0x33a3,
+ 0x33a4, 0x33a5, 0x33a6, 0x3399, 0x339a, 0x339b, 0x339c, 0x339d,
+ 0x339e, 0x339f, 0x33a0, 0x33a1, 0x33a2, 0x33ca, 0x338d, 0x338e,
+ 0x338f, 0x33cf, 0x3388, 0x3389, 0x33c8, 0x33a7, 0x33a8, 0x33b0,
+ 0x33b1, 0x33b2, 0x33b3, 0x33b4, 0x33b5, 0x33b6, 0x33b7, 0x33b8,
+ 0x33b9, 0x3380, 0x3381, 0x3382, 0x3383, 0x3384, 0x33ba, 0x33bb,
+ 0x33bc, 0x33bd, 0x33be, 0x33bf, 0x3390, 0x3391, 0x3392, 0x3393,
+ 0x3394, 0x2126, 0x33c0, 0x33c1, 0x338a, 0x338b, 0x338c, 0x33d6,
+ 0x33c5, 0x33ad, 0x33ae, 0x33af, 0x33db, 0x33a9, 0x33aa, 0x33ab,
+ 0x33ac, 0x33dd, 0x33d0, 0x33d3, 0x33c3, 0x33c9, 0x33dc, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x33c6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x00c6, 0x00d0, 0x00aa, 0x0126, 0x0000, 0x0132, 0x0000,
+ 0x013f, 0x0141, 0x00d8, 0x0152, 0x00ba, 0x00de, 0x0166, 0x014a,
+ 0x0000, 0x3260, 0x3261, 0x3262, 0x3263, 0x3264, 0x3265, 0x3266,
+ 0x3267, 0x3268, 0x3269, 0x326a, 0x326b, 0x326c, 0x326d, 0x326e,
+ 0x326f, 0x3270, 0x3271, 0x3272, 0x3273, 0x3274, 0x3275, 0x3276,
+ 0x3277, 0x3278, 0x3279, 0x327a, 0x327b, 0x24d0, 0x24d1, 0x24d2,
+ 0x24d3, 0x24d4, 0x24d5, 0x24d6, 0x24d7, 0x24d8, 0x24d9, 0x24da,
+ 0x24db, 0x24dc, 0x24dd, 0x24de, 0x24df, 0x24e0, 0x24e1, 0x24e2,
+ 0x24e3, 0x24e4, 0x24e5, 0x24e6, 0x24e7, 0x24e8, 0x24e9, 0x2460,
+ 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468,
+ 0x2469, 0x246a, 0x246b, 0x246c, 0x246d, 0x246e, 0x00bd, 0x2153,
+ 0x2154, 0x00bc, 0x00be, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x00e6, 0x0111, 0x00f0, 0x0127, 0x0131, 0x0133, 0x0138,
+ 0x0140, 0x0142, 0x00f8, 0x0153, 0x00df, 0x00fe, 0x0167, 0x014b,
+ 0x0149, 0x3200, 0x3201, 0x3202, 0x3203, 0x3204, 0x3205, 0x3206,
+ 0x3207, 0x3208, 0x3209, 0x320a, 0x320b, 0x320c, 0x320d, 0x320e,
+ 0x320f, 0x3210, 0x3211, 0x3212, 0x3213, 0x3214, 0x3215, 0x3216,
+ 0x3217, 0x3218, 0x3219, 0x321a, 0x321b, 0x249c, 0x249d, 0x249e,
+ 0x249f, 0x24a0, 0x24a1, 0x24a2, 0x24a3, 0x24a4, 0x24a5, 0x24a6,
+ 0x24a7, 0x24a8, 0x24a9, 0x24aa, 0x24ab, 0x24ac, 0x24ad, 0x24ae,
+ 0x24af, 0x24b0, 0x24b1, 0x24b2, 0x24b3, 0x24b4, 0x24b5, 0x2474,
+ 0x2475, 0x2476, 0x2477, 0x2478, 0x2479, 0x247a, 0x247b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x247c, 0x247d, 0x247e, 0x247f, 0x2480, 0x2481, 0x2482,
+ 0x00b9, 0x00b2, 0x00b3, 0x2074, 0x207f, 0x2081, 0x2082, 0x2083,
+ 0x2084, 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047,
+ 0x3048, 0x3049, 0x304a, 0x304b, 0x304c, 0x304d, 0x304e, 0x304f,
+ 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057,
+ 0x3058, 0x3059, 0x305a, 0x305b, 0x305c, 0x305d, 0x305e, 0x305f,
+ 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067,
+ 0x3068, 0x3069, 0x306a, 0x306b, 0x306c, 0x306d, 0x306e, 0x306f,
+ 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077,
+ 0x3078, 0x3079, 0x307a, 0x307b, 0x307c, 0x307d, 0x307e, 0x307f,
+ 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086, 0x3087,
+ 0x3088, 0x3089, 0x308a, 0x308b, 0x308c, 0x308d, 0x308e, 0x308f,
+ 0x3090, 0x3091, 0x3092, 0x3093, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x30a1, 0x30a2, 0x30a3, 0x30a4, 0x30a5, 0x30a6, 0x30a7,
+ 0x30a8, 0x30a9, 0x30aa, 0x30ab, 0x30ac, 0x30ad, 0x30ae, 0x30af,
+ 0x30b0, 0x30b1, 0x30b2, 0x30b3, 0x30b4, 0x30b5, 0x30b6, 0x30b7,
+ 0x30b8, 0x30b9, 0x30ba, 0x30bb, 0x30bc, 0x30bd, 0x30be, 0x30bf,
+ 0x30c0, 0x30c1, 0x30c2, 0x30c3, 0x30c4, 0x30c5, 0x30c6, 0x30c7,
+ 0x30c8, 0x30c9, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf,
+ 0x30d0, 0x30d1, 0x30d2, 0x30d3, 0x30d4, 0x30d5, 0x30d6, 0x30d7,
+ 0x30d8, 0x30d9, 0x30da, 0x30db, 0x30dc, 0x30dd, 0x30de, 0x30df,
+ 0x30e0, 0x30e1, 0x30e2, 0x30e3, 0x30e4, 0x30e5, 0x30e6, 0x30e7,
+ 0x30e8, 0x30e9, 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ee, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x30ef, 0x30f0, 0x30f1, 0x30f2, 0x30f3, 0x30f4, 0x30f5,
+ 0x30f6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0401,
+ 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d,
+ 0x041e, 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425,
+ 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d,
+ 0x042e, 0x042f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0451,
+ 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d,
+ 0x043e, 0x043f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445,
+ 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d,
+ 0x044e, 0x044f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4f3d, 0x4f73, 0x5047, 0x50f9, 0x52a0, 0x53ef, 0x5475,
+ 0x54e5, 0x5609, 0x5ac1, 0x5bb6, 0x6687, 0x67b6, 0x67b7, 0x67ef,
+ 0x6b4c, 0x73c2, 0x75c2, 0x7a3c, 0x82db, 0x8304, 0x8857, 0x8888,
+ 0x8a36, 0x8cc8, 0x8dcf, 0x8efb, 0x8fe6, 0x99d5, 0x523b, 0x5374,
+ 0x5404, 0x606a, 0x6164, 0x6bbc, 0x73cf, 0x811a, 0x89ba, 0x89d2,
+ 0x95a3, 0x4f83, 0x520a, 0x58be, 0x5978, 0x59e6, 0x5e72, 0x5e79,
+ 0x61c7, 0x63c0, 0x6746, 0x67ec, 0x687f, 0x6f97, 0x764e, 0x770b,
+ 0x78f5, 0x7a08, 0x7aff, 0x7c21, 0x809d, 0x826e, 0x8271, 0x8aeb,
+ 0x9593, 0x4e6b, 0x559d, 0x66f7, 0x6e34, 0x78a3, 0x7aed, 0x845b,
+ 0x8910, 0x874e, 0x97a8, 0x52d8, 0x574e, 0x582a, 0x5d4c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x611f, 0x61be, 0x6221, 0x6562, 0x67d1, 0x6a44, 0x6e1b,
+ 0x7518, 0x75b3, 0x76e3, 0x77b0, 0x7d3a, 0x90af, 0x9451, 0x9452,
+ 0x9f95, 0x5323, 0x5cac, 0x7532, 0x80db, 0x9240, 0x9598, 0x525b,
+ 0x5808, 0x59dc, 0x5ca1, 0x5d17, 0x5eb7, 0x5f3a, 0x5f4a, 0x6177,
+ 0x6c5f, 0x757a, 0x7586, 0x7ce0, 0x7d73, 0x7db1, 0x7f8c, 0x8154,
+ 0x8221, 0x8591, 0x8941, 0x8b1b, 0x92fc, 0x964d, 0x9c47, 0x4ecb,
+ 0x4ef7, 0x500b, 0x51f1, 0x584f, 0x6137, 0x613e, 0x6168, 0x6539,
+ 0x69ea, 0x6f11, 0x75a5, 0x7686, 0x76d6, 0x7b87, 0x82a5, 0x84cb,
+ 0x8c48, 0x93a7, 0x958b, 0x5580, 0x5ba2, 0x5751, 0x66f4, 0x7cb3,
+ 0x7fb9, 0x91b5, 0x5028, 0x53bb, 0x5c45, 0x5de8, 0x62d2, 0x636e,
+ 0x64da, 0x64e7, 0x6e20, 0x70ac, 0x795b, 0x8ddd, 0x8e1e, 0x8eca,
+ 0x907d, 0x9245, 0x92f8, 0x4e7e, 0x4ef6, 0x5065, 0x5dfe, 0x5efa,
+ 0x6106, 0x6957, 0x8171, 0x8654, 0x8e47, 0x9375, 0x9a2b, 0x4e5e,
+ 0x5091, 0x6770, 0x6840, 0x5109, 0x528d, 0x5292, 0x6aa2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x77bc, 0x9210, 0x9ed4, 0x52ab, 0x602f, 0x8ff2, 0x5048,
+ 0x61a9, 0x63ed, 0x64ca, 0x683c, 0x6a84, 0x6fc0, 0x8188, 0x89a1,
+ 0x9694, 0x5805, 0x727d, 0x72ac, 0x7504, 0x7d79, 0x7e6d, 0x80a9,
+ 0x898b, 0x8b74, 0x9063, 0x9d51, 0x6289, 0x6c7a, 0x6f54, 0x7d50,
+ 0x7f3a, 0x8a23, 0x517c, 0x614a, 0x7b9d, 0x8b19, 0x9257, 0x938c,
+ 0x4eac, 0x4fd3, 0x501e, 0x50be, 0x5106, 0x52c1, 0x52cd, 0x537f,
+ 0x5770, 0x5883, 0x5e9a, 0x5f91, 0x6176, 0x61ac, 0x64ce, 0x656c,
+ 0x666f, 0x66bb, 0x0000, 0x6897, 0x6d87, 0x7085, 0x70f1, 0x749f,
+ 0x74a5, 0x74ca, 0x75d9, 0x786c, 0x78ec, 0x7adf, 0x7af6, 0x7d45,
+ 0x7d93, 0x8015, 0x803f, 0x811b, 0x8396, 0x8b66, 0x8f15, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9015, 0x93e1, 0x9803, 0x9838, 0x9a5a, 0x9be8, 0x4fc2,
+ 0x5553, 0x583a, 0x5951, 0x5b63, 0x5c46, 0x60b8, 0x6212, 0x6842,
+ 0x68b0, 0x68e8, 0x6eaa, 0x754c, 0x7678, 0x78ce, 0x7a3d, 0x7cfb,
+ 0x7e6b, 0x7e7c, 0x8a08, 0x8aa1, 0x8c3f, 0x968e, 0x9dc4, 0x53e4,
+ 0x53e9, 0x544a, 0x5471, 0x56fa, 0x59d1, 0x5b64, 0x5c3b, 0x5eab,
+ 0x62f7, 0x6537, 0x6545, 0x6572, 0x66a0, 0x67af, 0x69c1, 0x6cbd,
+ 0x75fc, 0x7690, 0x777e, 0x7a3f, 0x7f94, 0x8003, 0x80a1, 0x818f,
+ 0x82e6, 0x82fd, 0x83f0, 0x85c1, 0x8831, 0x88b4, 0x8aa5, 0x0000,
+ 0x8f9c, 0x932e, 0x96c7, 0x9867, 0x9ad8, 0x9f13, 0x54ed, 0x659b,
+ 0x66f2, 0x688f, 0x7a40, 0x8c37, 0x9d60, 0x56f0, 0x5764, 0x5d11,
+ 0x6606, 0x68b1, 0x68cd, 0x6efe, 0x7428, 0x889e, 0x9be4, 0x6c68,
+ 0x6ed1, 0x9aa8, 0x4f9b, 0x516c, 0x5171, 0x529f, 0x5b54, 0x5de5,
+ 0x6050, 0x606d, 0x62f1, 0x63a7, 0x653b, 0x73d9, 0x7a7a, 0x86a3,
+ 0x8ca2, 0x978f, 0x4e32, 0x5be1, 0x6208, 0x679c, 0x74dc, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x79d1, 0x83d3, 0x8a87, 0x8ab2, 0x8de8, 0x904e, 0x934b,
+ 0x9846, 0x5ed3, 0x69e8, 0x85ff, 0x90ed, 0x0000, 0x51a0, 0x5b98,
+ 0x5bec, 0x6163, 0x68fa, 0x6b3e, 0x704c, 0x742f, 0x74d8, 0x7ba1,
+ 0x7f50, 0x83c5, 0x89c0, 0x8cab, 0x95dc, 0x9928, 0x522e, 0x605d,
+ 0x62ec, 0x9002, 0x4f8a, 0x5149, 0x5321, 0x58d9, 0x5ee3, 0x66e0,
+ 0x6d38, 0x709a, 0x72c2, 0x73d6, 0x7b50, 0x80f1, 0x945b, 0x5366,
+ 0x639b, 0x7f6b, 0x4e56, 0x5080, 0x584a, 0x58de, 0x602a, 0x6127,
+ 0x62d0, 0x69d0, 0x9b41, 0x5b8f, 0x7d18, 0x80b1, 0x8f5f, 0x4ea4,
+ 0x50d1, 0x54ac, 0x55ac, 0x5b0c, 0x5da0, 0x5de7, 0x652a, 0x654e,
+ 0x6821, 0x6a4b, 0x72e1, 0x768e, 0x77ef, 0x7d5e, 0x7ff9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x81a0, 0x854e, 0x86df, 0x8f03, 0x8f4e, 0x90ca, 0x9903,
+ 0x9a55, 0x9bab, 0x4e18, 0x4e45, 0x4e5d, 0x4ec7, 0x4ff1, 0x5177,
+ 0x52fe, 0x5340, 0x53e3, 0x53e5, 0x548e, 0x5614, 0x5775, 0x57a2,
+ 0x5bc7, 0x5d87, 0x5ed0, 0x61fc, 0x62d8, 0x6551, 0x67b8, 0x67e9,
+ 0x69cb, 0x6b50, 0x6bc6, 0x6bec, 0x6c42, 0x6e9d, 0x7078, 0x72d7,
+ 0x7396, 0x7403, 0x77bf, 0x77e9, 0x7a76, 0x7d7f, 0x8009, 0x81fc,
+ 0x8205, 0x820a, 0x82df, 0x8862, 0x8b33, 0x8cfc, 0x8ec0, 0x9011,
+ 0x90b1, 0x9264, 0x92b6, 0x99d2, 0x9a45, 0x9ce9, 0x9dd7, 0x9f9c,
+ 0x570b, 0x5c40, 0x83ca, 0x97a0, 0x97ab, 0x9eb4, 0x541b, 0x7a98,
+ 0x7fa4, 0x88d9, 0x8ecd, 0x90e1, 0x5800, 0x5c48, 0x6398, 0x7a9f,
+ 0x5bae, 0x5f13, 0x7a79, 0x7aae, 0x828e, 0x8eac, 0x5026, 0x5238,
+ 0x52f8, 0x5377, 0x5708, 0x62f3, 0x6372, 0x6b0a, 0x6dc3, 0x7737,
+ 0x53a5, 0x7357, 0x8568, 0x8e76, 0x95d5, 0x673a, 0x6ac3, 0x6f70,
+ 0x8a6d, 0x8ecc, 0x994b, 0x0000, 0x6677, 0x6b78, 0x8cb4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9b3c, 0x0000, 0x53eb, 0x572d, 0x594e, 0x63c6, 0x69fb,
+ 0x73ea, 0x7845, 0x7aba, 0x7ac5, 0x7cfe, 0x8475, 0x898f, 0x8d73,
+ 0x9035, 0x95a8, 0x52fb, 0x5747, 0x7547, 0x7b60, 0x83cc, 0x921e,
+ 0x0000, 0x6a58, 0x514b, 0x524b, 0x5287, 0x621f, 0x68d8, 0x6975,
+ 0x9699, 0x50c5, 0x52a4, 0x52e4, 0x61c3, 0x65a4, 0x6839, 0x69ff,
+ 0x747e, 0x7b4b, 0x82b9, 0x83eb, 0x89b2, 0x8b39, 0x8fd1, 0x9949,
+ 0x0000, 0x4eca, 0x5997, 0x64d2, 0x6611, 0x6a8e, 0x7434, 0x7981,
+ 0x79bd, 0x82a9, 0x887e, 0x887f, 0x895f, 0x91d1, 0x9326, 0x4f0b,
+ 0x53ca, 0x6025, 0x6271, 0x6c72, 0x7d1a, 0x7d66, 0x4e98, 0x5162,
+ 0x77dc, 0x80af, 0x4f01, 0x4f0e, 0x5176, 0x5180, 0x55dc, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5668, 0x573b, 0x57fa, 0x57fc, 0x5914, 0x5947, 0x5993,
+ 0x5bc4, 0x5c90, 0x5d0e, 0x5df1, 0x5e7e, 0x5fcc, 0x6280, 0x65d7,
+ 0x65e3, 0x671e, 0x671f, 0x675e, 0x68cb, 0x68c4, 0x6a5f, 0x6b3a,
+ 0x6c23, 0x6c7d, 0x6c82, 0x6dc7, 0x7398, 0x7426, 0x742a, 0x7482,
+ 0x74a3, 0x7578, 0x757f, 0x7881, 0x78ef, 0x7941, 0x7947, 0x7948,
+ 0x797a, 0x7b95, 0x7d00, 0x7dba, 0x7f88, 0x8006, 0x802d, 0x808c,
+ 0x8a18, 0x8b4f, 0x0000, 0x8d77, 0x9321, 0x9324, 0x98e2, 0x9951,
+ 0x9a0e, 0x9a0f, 0x9a65, 0x9e92, 0x7dca, 0x4f76, 0x5409, 0x62ee,
+ 0x6854, 0x0000, 0x55ab, 0x513a, 0x5587, 0x5948, 0x5a1c, 0x61e6,
+ 0x61f6, 0x62cf, 0x62ff, 0x7669, 0x7f85, 0x863f, 0x87ba, 0x88f8,
+ 0x908f, 0x90a3, 0x6a02, 0x6d1b, 0x70d9, 0x73de, 0x843d, 0x8afe,
+ 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6696, 0x6b04, 0x7156, 0x721b,
+ 0x862d, 0x96e3, 0x9e1e, 0x634f, 0x637a, 0x5357, 0x5d50, 0x678f,
+ 0x6960, 0x6e73, 0x6feb, 0x7537, 0x85cd, 0x8964, 0x62c9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7d0d, 0x81d8, 0x881f, 0x8872, 0x56ca, 0x5a18, 0x5eca,
+ 0x6717, 0x6d6a, 0x72fc, 0x90de, 0x4e43, 0x4f86, 0x5167, 0x0000,
+ 0x67f0, 0x8010, 0x51b7, 0x5973, 0x5e74, 0x649a, 0x79ca, 0x5ff5,
+ 0x606c, 0x62c8, 0x637b, 0x5be7, 0x5bd7, 0x52aa, 0x52de, 0x5974,
+ 0x5f29, 0x6012, 0x64c4, 0x6ad3, 0x7210, 0x7459, 0x76e7, 0x8001,
+ 0x8606, 0x865c, 0x8def, 0x9732, 0x99d1, 0x9b6f, 0x9dfa, 0x788c,
+ 0x797f, 0x7da0, 0x83c9, 0x9304, 0x9e7f, 0x8ad6, 0x58df, 0x5f04,
+ 0x6fc3, 0x7c60, 0x807e, 0x81bf, 0x8fb2, 0x60f1, 0x7262, 0x78ca,
+ 0x8166, 0x8cc2, 0x96f7, 0x5c3f, 0x58d8, 0x5c62, 0x6a13, 0x6dda,
+ 0x6f0f, 0x7d2f, 0x7e37, 0x964b, 0x5ae9, 0x8a25, 0x677b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7d10, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
+ 0x80fd, 0x83f1, 0x9675, 0x5c3c, 0x6ce5, 0x533f, 0x6eba, 0x591a,
+ 0x8336, 0x4e39, 0x4eb6, 0x4f46, 0x55ae, 0x5718, 0x58c7, 0x5f56,
+ 0x65b7, 0x65e6, 0x6a80, 0x6bb5, 0x6e4d, 0x77ed, 0x7aef, 0x7c1e,
+ 0x7dde, 0x86cb, 0x8892, 0x9132, 0x935b, 0x64bb, 0x6fbe, 0x737a,
+ 0x75b8, 0x9054, 0x5556, 0x574d, 0x61ba, 0x64d4, 0x66c7, 0x6de1,
+ 0x6e5b, 0x6f6d, 0x6fb9, 0x75f0, 0x8043, 0x81bd, 0x8541, 0x8983,
+ 0x8ac7, 0x8b5a, 0x931f, 0x6c93, 0x7553, 0x7b54, 0x8e0f, 0x905d,
+ 0x5510, 0x5802, 0x5858, 0x5e62, 0x6207, 0x649e, 0x68e0, 0x7576,
+ 0x7cd6, 0x87b3, 0x9ee8, 0x4ee3, 0x5788, 0x576e, 0x5927, 0x5c0d,
+ 0x5cb1, 0x5e36, 0x5f85, 0x6234, 0x64e1, 0x73b3, 0x81fa, 0x888b,
+ 0x8cb8, 0x968a, 0x9edb, 0x5b85, 0x5fb7, 0x60b3, 0x5012, 0x5200,
+ 0x5230, 0x5716, 0x5835, 0x5857, 0x5c0e, 0x5c60, 0x5cf6, 0x5d8b,
+ 0x5ea6, 0x5f92, 0x60bc, 0x6311, 0x6389, 0x6417, 0x6843, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x68f9, 0x6ac2, 0x6dd8, 0x6e21, 0x6ed4, 0x6fe4, 0x71fe,
+ 0x76dc, 0x7779, 0x79b1, 0x7a3b, 0x8404, 0x89a9, 0x8ced, 0x8df3,
+ 0x8e48, 0x9003, 0x9014, 0x9053, 0x90fd, 0x934d, 0x9676, 0x97dc,
+ 0x6bd2, 0x7006, 0x7258, 0x72a2, 0x7368, 0x7763, 0x79bf, 0x7be4,
+ 0x7e9b, 0x8b80, 0x58a9, 0x60c7, 0x6566, 0x65fd, 0x66be, 0x6c8c,
+ 0x711e, 0x71c9, 0x8c5a, 0x9813, 0x4e6d, 0x7a81, 0x4edd, 0x51ac,
+ 0x51cd, 0x52d5, 0x540c, 0x61a7, 0x6771, 0x6850, 0x68df, 0x6d1e,
+ 0x6f7c, 0x75bc, 0x77b3, 0x7ae5, 0x80f4, 0x8463, 0x9285, 0x515c,
+ 0x6597, 0x675c, 0x6793, 0x75d8, 0x7ac7, 0x8373, 0x0000, 0x8c46,
+ 0x9017, 0x982d, 0x5c6f, 0x81c0, 0x829a, 0x9041, 0x906f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x920d, 0x5f97, 0x5d9d, 0x6a59, 0x71c8, 0x767b, 0x7b49,
+ 0x85e4, 0x8b04, 0x9127, 0x9a30, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7d61, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6b12, 0x703e, 0x0000, 0x0000, 0x0000, 0x524c,
+ 0x8fa3, 0x0000, 0x64e5, 0x652c, 0x6b16, 0x0000, 0x7c43, 0x7e9c,
+ 0x0000, 0x0000, 0x89bd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7405, 0x746f, 0x8782, 0x0000, 0x0000, 0x5d0d,
+ 0x5fa0, 0x840a, 0x0000, 0x63a0, 0x7565, 0x4eae, 0x5006, 0x5169,
+ 0x51c9, 0x6881, 0x6a11, 0x7cae, 0x7cb1, 0x7ce7, 0x826f, 0x8ad2,
+ 0x8f1b, 0x91cf, 0x4fb6, 0x5137, 0x52f5, 0x5442, 0x5eec, 0x616e,
+ 0x623e, 0x65c5, 0x6ada, 0x6ffe, 0x792a, 0x85dc, 0x8823, 0x95ad,
+ 0x9a62, 0x9a6a, 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x701d,
+ 0x792b, 0x8f62, 0x9742, 0x6190, 0x6200, 0x6523, 0x6f23, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7149, 0x7489, 0x7df4, 0x806f, 0x84ee, 0x8f26, 0x9023,
+ 0x934a, 0x51bd, 0x5217, 0x52a3, 0x6d0c, 0x70c8, 0x88c2, 0x5ec9,
+ 0x6582, 0x6bae, 0x6fc2, 0x7c3e, 0x7375, 0x4ee4, 0x4f36, 0x56f9,
+ 0x0000, 0x5cba, 0x5dba, 0x601c, 0x73b2, 0x7b2d, 0x7f9a, 0x7fce,
+ 0x8046, 0x901e, 0x9234, 0x96f6, 0x9748, 0x9818, 0x9f61, 0x4f8b,
+ 0x6fa7, 0x79ae, 0x91b4, 0x96b7, 0x0000, 0x0000, 0x6488, 0x0000,
+ 0x0000, 0x6f5e, 0x7018, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8f05, 0x0000, 0x0000, 0x0000, 0x9e75, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9e93, 0x0000, 0x0000, 0x0000,
+ 0x6727, 0x7027, 0x74cf, 0x0000, 0x0000, 0x5121, 0x7028, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8cda, 0x8cf4, 0x0000, 0x4e86,
+ 0x50da, 0x5bee, 0x5ed6, 0x6599, 0x71ce, 0x7642, 0x77ad, 0x804a,
+ 0x84fc, 0x907c, 0x9b27, 0x9f8d, 0x0000, 0x5a41, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x763b, 0x0000, 0x0000, 0x851e, 0x8938, 0x93e4,
+ 0x0000, 0x5289, 0x65d2, 0x67f3, 0x69b4, 0x6d41, 0x6e9c, 0x700f,
+ 0x7409, 0x7460, 0x7559, 0x7624, 0x786b, 0x8b2c, 0x985e, 0x516d,
+ 0x622e, 0x9678, 0x4f96, 0x502b, 0x5d19, 0x6dea, 0x7db8, 0x8f2a,
+ 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x695e, 0x0000, 0x0000, 0x0000, 0x0000, 0x4fda, 0x5229,
+ 0x5398, 0x540f, 0x550e, 0x5c65, 0x60a7, 0x674e, 0x68a8, 0x6d6c,
+ 0x7281, 0x72f8, 0x7406, 0x7483, 0x7570, 0x75e2, 0x7c6c, 0x7f79,
+ 0x7fb8, 0x8389, 0x88cf, 0x88e1, 0x91cc, 0x91d0, 0x96e2, 0x9bc9,
+ 0x541d, 0x6f7e, 0x71d0, 0x7498, 0x85fa, 0x8eaa, 0x96a3, 0x9c57,
+ 0x9e9f, 0x6797, 0x6dcb, 0x7433, 0x81e8, 0x9716, 0x782c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7acb, 0x7b20, 0x7c92, 0x6469, 0x746a, 0x75f2, 0x78bc,
+ 0x78e8, 0x99ac, 0x9b54, 0x9ebb, 0x5bde, 0x5e55, 0x6f20, 0x819c,
+ 0x83ab, 0x9088, 0x4e07, 0x534d, 0x5a29, 0x5dd2, 0x5f4e, 0x6162,
+ 0x633d, 0x6669, 0x66fc, 0x6eff, 0x6f2b, 0x7063, 0x779e, 0x842c,
+ 0x8513, 0x883b, 0x8f13, 0x9945, 0x9c3b, 0x551c, 0x62b9, 0x672b,
+ 0x6cab, 0x8309, 0x896a, 0x977a, 0x4ea1, 0x5984, 0x5fd8, 0x5fd9,
+ 0x671b, 0x7db2, 0x7f54, 0x8292, 0x832b, 0x83bd, 0x8f1e, 0x9099,
+ 0x57cb, 0x59b9, 0x5a92, 0x5bd0, 0x6627, 0x679a, 0x6885, 0x6bcf,
+ 0x7164, 0x7f75, 0x8cb7, 0x8ce3, 0x9081, 0x9b45, 0x8108, 0x8c8a,
+ 0x964c, 0x9a40, 0x9ea5, 0x5b5f, 0x6c13, 0x731b, 0x76f2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x76df, 0x840c, 0x51aa, 0x8993, 0x514d, 0x5195, 0x52c9,
+ 0x68c9, 0x6c94, 0x7704, 0x7720, 0x7dbf, 0x7dec, 0x9762, 0x9eb5,
+ 0x6ec5, 0x8511, 0x51a5, 0x540d, 0x547d, 0x660e, 0x669d, 0x6927,
+ 0x6e9f, 0x76bf, 0x7791, 0x8317, 0x84c2, 0x879f, 0x9169, 0x9298,
+ 0x9cf4, 0x8882, 0x4fae, 0x5192, 0x52df, 0x59c6, 0x5e3d, 0x6155,
+ 0x6478, 0x6479, 0x66ae, 0x67d0, 0x6a21, 0x6bcd, 0x6bdb, 0x725f,
+ 0x7261, 0x7441, 0x7738, 0x77db, 0x8017, 0x82bc, 0x8305, 0x8b00,
+ 0x8b28, 0x8c8c, 0x6728, 0x6c90, 0x7267, 0x76ee, 0x7766, 0x7a46,
+ 0x9da9, 0x6b7f, 0x6c92, 0x5922, 0x6726, 0x8499, 0x536f, 0x5893,
+ 0x5999, 0x5edf, 0x63cf, 0x6634, 0x6773, 0x6e3a, 0x732b, 0x7ad7,
+ 0x82d7, 0x9328, 0x52d9, 0x5deb, 0x61ae, 0x61cb, 0x620a, 0x62c7,
+ 0x64ab, 0x65e0, 0x6959, 0x6b66, 0x6bcb, 0x7121, 0x73f7, 0x755d,
+ 0x7e46, 0x821e, 0x8302, 0x856a, 0x8aa3, 0x8cbf, 0x9727, 0x9d61,
+ 0x58a8, 0x9ed8, 0x5011, 0x520e, 0x543b, 0x554f, 0x6587, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6c76, 0x7d0a, 0x7d0b, 0x805e, 0x868a, 0x9580, 0x96ef,
+ 0x52ff, 0x6c95, 0x7269, 0x5473, 0x5a9a, 0x5c3e, 0x5d4b, 0x5f4c,
+ 0x5fae, 0x672a, 0x68b6, 0x6963, 0x6e3c, 0x6e44, 0x7709, 0x7c73,
+ 0x7f8e, 0x8587, 0x8b0e, 0x8ff7, 0x9761, 0x9ef4, 0x5cb7, 0x60b6,
+ 0x610d, 0x61ab, 0x654f, 0x65fb, 0x65fc, 0x6c11, 0x6cef, 0x739f,
+ 0x73c9, 0x7de1, 0x9594, 0x5bc6, 0x871c, 0x8b10, 0x525d, 0x535a,
+ 0x62cd, 0x640f, 0x64b2, 0x6734, 0x6a38, 0x6cca, 0x73c0, 0x749e,
+ 0x7b94, 0x7c95, 0x7e1b, 0x818a, 0x8236, 0x8584, 0x8feb, 0x96f9,
+ 0x99c1, 0x4f34, 0x534a, 0x53cd, 0x53db, 0x62cc, 0x642c, 0x6500,
+ 0x6591, 0x69c3, 0x6cee, 0x6f58, 0x73ed, 0x7554, 0x7622, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x76e4, 0x76fc, 0x78d0, 0x78fb, 0x792c, 0x7d46, 0x822c,
+ 0x87e0, 0x8fd4, 0x9812, 0x98ef, 0x52c3, 0x62d4, 0x64a5, 0x6e24,
+ 0x6f51, 0x767c, 0x8dcb, 0x91b1, 0x9262, 0x9aee, 0x9b43, 0x5023,
+ 0x508d, 0x574a, 0x59a8, 0x5c28, 0x5e47, 0x5f77, 0x623f, 0x653e,
+ 0x65b9, 0x65c1, 0x6609, 0x678b, 0x699c, 0x6ec2, 0x78c5, 0x7d21,
+ 0x80aa, 0x8180, 0x822b, 0x82b3, 0x84a1, 0x868c, 0x8a2a, 0x8b17,
+ 0x90a6, 0x9632, 0x9f90, 0x500d, 0x4ff3, 0x5317, 0x57f9, 0x5f98,
+ 0x62dc, 0x6392, 0x676f, 0x6e43, 0x7119, 0x76c3, 0x80cc, 0x80da,
+ 0x88f4, 0x88f5, 0x8919, 0x8ce0, 0x8f29, 0x914d, 0x966a, 0x4f2f,
+ 0x4f70, 0x5e1b, 0x67cf, 0x6822, 0x767d, 0x767e, 0x9b44, 0x5e61,
+ 0x6a0a, 0x7169, 0x71d4, 0x756a, 0x0000, 0x7e41, 0x8543, 0x85e9,
+ 0x98dc, 0x4f10, 0x7b4f, 0x7f70, 0x95a5, 0x51e1, 0x5e06, 0x68b5,
+ 0x6c3e, 0x6c4e, 0x6cdb, 0x72af, 0x7bc4, 0x8303, 0x6cd5, 0x743a,
+ 0x50fb, 0x5288, 0x58c1, 0x64d8, 0x6a97, 0x74a7, 0x7656, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x78a7, 0x8617, 0x95e2, 0x9739, 0x4fbf, 0x535e, 0x5f01,
+ 0x8b8a, 0x8fa8, 0x8faf, 0x908a, 0x5225, 0x77a5, 0x9c49, 0x9f08,
+ 0x4e19, 0x5002, 0x5175, 0x5c5b, 0x5e77, 0x661e, 0x663a, 0x67c4,
+ 0x68c5, 0x70b3, 0x7501, 0x75c5, 0x79c9, 0x7add, 0x8f27, 0x9920,
+ 0x9a08, 0x4fdd, 0x5821, 0x5831, 0x5bf6, 0x666e, 0x6b65, 0x6d11,
+ 0x6e7a, 0x6f7d, 0x73e4, 0x752b, 0x83e9, 0x88dc, 0x8913, 0x8b5c,
+ 0x8f14, 0x4f0f, 0x50d5, 0x5310, 0x535c, 0x5b93, 0x5fa9, 0x670d,
+ 0x798f, 0x8179, 0x832f, 0x8514, 0x8907, 0x8986, 0x8f39, 0x8f3b,
+ 0x99a5, 0x9c12, 0x672c, 0x4e76, 0x4ff8, 0x5949, 0x5c01, 0x5cef,
+ 0x5cf0, 0x6367, 0x68d2, 0x70fd, 0x71a2, 0x742b, 0x7e2b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x84ec, 0x8702, 0x9022, 0x92d2, 0x9cf3, 0x4e0d, 0x4ed8,
+ 0x4fef, 0x5085, 0x5256, 0x526f, 0x5426, 0x5490, 0x57e0, 0x592b,
+ 0x5a66, 0x5b5a, 0x5b75, 0x5bcc, 0x5e9c, 0x0000, 0x6276, 0x6577,
+ 0x65a7, 0x6d6e, 0x6ea5, 0x7236, 0x7b26, 0x7c3f, 0x7f36, 0x8150,
+ 0x8151, 0x819a, 0x8240, 0x8299, 0x83a9, 0x8a03, 0x8ca0, 0x8ce6,
+ 0x8cfb, 0x8d74, 0x8dba, 0x90e8, 0x91dc, 0x961c, 0x9644, 0x99d9,
+ 0x9ce7, 0x0000, 0x5206, 0x5429, 0x5674, 0x58b3, 0x5954, 0x596e,
+ 0x5fff, 0x61a4, 0x626e, 0x6610, 0x6c7e, 0x711a, 0x76c6, 0x7c89,
+ 0x7cde, 0x7d1b, 0x82ac, 0x8cc1, 0x96f0, 0x0000, 0x4f5b, 0x5f17,
+ 0x5f7f, 0x62c2, 0x5d29, 0x670b, 0x68da, 0x787c, 0x7e43, 0x9d6c,
+ 0x4e15, 0x5099, 0x5315, 0x532a, 0x5351, 0x5983, 0x5a62, 0x5e87,
+ 0x60b2, 0x618a, 0x6249, 0x6279, 0x6590, 0x6787, 0x69a7, 0x6bd4,
+ 0x6bd6, 0x6bd7, 0x6bd8, 0x6cb8, 0x6ccc, 0x7435, 0x75fa, 0x7812,
+ 0x7891, 0x79d5, 0x79d8, 0x7c83, 0x7dcb, 0x7fe1, 0x80a5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x813e, 0x81c2, 0x83f2, 0x871a, 0x88e8, 0x8ab9, 0x8b6c,
+ 0x8cbb, 0x9119, 0x975e, 0x98db, 0x9f3b, 0x56ac, 0x5b2a, 0x5f6c,
+ 0x658c, 0x6ab3, 0x6baf, 0x6d5c, 0x6ff1, 0x7015, 0x725d, 0x73ad,
+ 0x8ca7, 0x8cd3, 0x983b, 0x6191, 0x6c37, 0x8058, 0x9a01, 0x4e4d,
+ 0x4e8b, 0x4e9b, 0x4ed5, 0x4f3a, 0x4f3c, 0x4f7f, 0x4fdf, 0x50ff,
+ 0x53f2, 0x53f8, 0x5506, 0x55e3, 0x56db, 0x58eb, 0x5962, 0x5a11,
+ 0x5beb, 0x5bfa, 0x5c04, 0x5df3, 0x5e2b, 0x5f99, 0x601d, 0x6368,
+ 0x659c, 0x65af, 0x67f6, 0x67fb, 0x68ad, 0x6b7b, 0x6c99, 0x6cd7,
+ 0x6e23, 0x7009, 0x7345, 0x7802, 0x793e, 0x7940, 0x7960, 0x79c1,
+ 0x7be9, 0x7d17, 0x7d72, 0x8086, 0x820d, 0x838e, 0x84d1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x86c7, 0x88df, 0x8a50, 0x8a5e, 0x8b1d, 0x8cdc, 0x8d66,
+ 0x8fad, 0x90aa, 0x98fc, 0x99df, 0x9e9d, 0x524a, 0x6578, 0x6714,
+ 0x7d22, 0x5098, 0x522a, 0x5c71, 0x6563, 0x6c55, 0x73ca, 0x7523,
+ 0x759d, 0x7b97, 0x849c, 0x9178, 0x9730, 0x4e77, 0x6492, 0x6bba,
+ 0x715e, 0x85a9, 0x4e09, 0x53c3, 0x6749, 0x68ee, 0x6e17, 0x829f,
+ 0x8518, 0x886b, 0x63f7, 0x6f81, 0x9212, 0x98af, 0x4e0a, 0x50b7,
+ 0x50cf, 0x511f, 0x5546, 0x55aa, 0x5617, 0x5b40, 0x5c19, 0x5ce0,
+ 0x5e38, 0x5e8a, 0x5ea0, 0x5ec2, 0x60f3, 0x6851, 0x6a61, 0x6e58,
+ 0x723d, 0x7240, 0x72c0, 0x76f8, 0x7965, 0x7bb1, 0x7fd4, 0x88f3,
+ 0x89f4, 0x8a73, 0x8c61, 0x8cde, 0x971c, 0x585e, 0x74bd, 0x8cfd,
+ 0x55c7, 0x0000, 0x7a61, 0x0000, 0x8272, 0x7272, 0x751f, 0x7525,
+ 0x7701, 0x7b19, 0x5885, 0x58fb, 0x5dbc, 0x5e8f, 0x5eb6, 0x5f90,
+ 0x6055, 0x6292, 0x637f, 0x654d, 0x6691, 0x66d9, 0x66f8, 0x6816,
+ 0x68f2, 0x7280, 0x745e, 0x7b6e, 0x7d6e, 0x7dd6, 0x7f72, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x80e5, 0x8212, 0x85af, 0x897f, 0x8a93, 0x901d, 0x92e4,
+ 0x9ecd, 0x9f20, 0x5915, 0x596d, 0x5e2d, 0x60dc, 0x6614, 0x6673,
+ 0x6790, 0x6c50, 0x6dc5, 0x6f5f, 0x77f3, 0x78a9, 0x84c6, 0x91cb,
+ 0x932b, 0x4ed9, 0x50ca, 0x5148, 0x5584, 0x5b0b, 0x5ba3, 0x6247,
+ 0x657e, 0x65cb, 0x6e32, 0x717d, 0x7401, 0x7444, 0x7487, 0x74bf,
+ 0x766c, 0x79aa, 0x7dda, 0x7e55, 0x7fa8, 0x817a, 0x81b3, 0x8239,
+ 0x861a, 0x87ec, 0x8a75, 0x8de3, 0x9078, 0x9291, 0x9425, 0x994d,
+ 0x9bae, 0x5368, 0x5c51, 0x6954, 0x6cc4, 0x6d29, 0x6e2b, 0x820c,
+ 0x859b, 0x893b, 0x8a2d, 0x8aaa, 0x96ea, 0x9f67, 0x5261, 0x66b9,
+ 0x6bb2, 0x7e96, 0x87fe, 0x8d0d, 0x9583, 0x965d, 0x651d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6d89, 0x71ee, 0x8449, 0x57ce, 0x59d3, 0x5bac, 0x6027,
+ 0x60fa, 0x6210, 0x661f, 0x665f, 0x7329, 0x73f9, 0x76db, 0x0000,
+ 0x7b6c, 0x8056, 0x8072, 0x8165, 0x8aa0, 0x9192, 0x4e16, 0x52e2,
+ 0x6b72, 0x6d17, 0x7a05, 0x7b39, 0x7d30, 0x0000, 0x8cb0, 0x53ec,
+ 0x562f, 0x5851, 0x5bb5, 0x5c0f, 0x5c11, 0x5de2, 0x6240, 0x6383,
+ 0x6414, 0x662d, 0x68b3, 0x6cbc, 0x6d88, 0x6eaf, 0x701f, 0x70a4,
+ 0x71d2, 0x7526, 0x758f, 0x758e, 0x7619, 0x7b11, 0x7be0, 0x7c2b,
+ 0x7d20, 0x7d39, 0x852c, 0x856d, 0x8607, 0x8a34, 0x900d, 0x9061,
+ 0x90b5, 0x92b7, 0x97f6, 0x9a37, 0x4fd7, 0x5c6c, 0x675f, 0x6d91,
+ 0x7c9f, 0x7e8c, 0x8b16, 0x8d16, 0x901f, 0x5b6b, 0x5dfd, 0x640d,
+ 0x84c0, 0x905c, 0x98e1, 0x0000, 0x5b8b, 0x609a, 0x677e, 0x6dde,
+ 0x8a1f, 0x8aa6, 0x9001, 0x980c, 0x5237, 0x0000, 0x7051, 0x788e,
+ 0x9396, 0x8870, 0x91d7, 0x4fee, 0x53d7, 0x55fd, 0x56da, 0x5782,
+ 0x58fd, 0x5ac2, 0x5b88, 0x5cab, 0x5cc0, 0x5e25, 0x6101, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x620d, 0x624b, 0x6388, 0x641c, 0x6536, 0x0000, 0x6a39,
+ 0x6b8a, 0x6c34, 0x6d19, 0x6f31, 0x71e7, 0x72e9, 0x7378, 0x7407,
+ 0x74b2, 0x7626, 0x7761, 0x79c0, 0x7a57, 0x7aea, 0x7cb9, 0x7d8f,
+ 0x7dac, 0x7e61, 0x7f9e, 0x8129, 0x8331, 0x8490, 0x84da, 0x85ea,
+ 0x8896, 0x8ab0, 0x8b90, 0x8f38, 0x9042, 0x9083, 0x916c, 0x9296,
+ 0x92b9, 0x968b, 0x96a7, 0x96a8, 0x96d6, 0x9700, 0x9808, 0x9996,
+ 0x9ad3, 0x9b1a, 0x53d4, 0x587e, 0x5919, 0x5b70, 0x5bbf, 0x6dd1,
+ 0x6f5a, 0x719f, 0x7421, 0x74b9, 0x8085, 0x83fd, 0x5de1, 0x5f87,
+ 0x5faa, 0x6042, 0x65ec, 0x6812, 0x696f, 0x6a53, 0x6b89, 0x6d35,
+ 0x6df3, 0x73e3, 0x76fe, 0x77ac, 0x7b4d, 0x7d14, 0x8123, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x821c, 0x8340, 0x84f4, 0x8563, 0x8a62, 0x8ac4, 0x9187,
+ 0x931e, 0x9806, 0x99b4, 0x620c, 0x8853, 0x8ff0, 0x9265, 0x5d07,
+ 0x5d27, 0x5d69, 0x745f, 0x819d, 0x8768, 0x6fd5, 0x62fe, 0x7fd2,
+ 0x8936, 0x8972, 0x4e1e, 0x4e58, 0x50e7, 0x52dd, 0x5347, 0x627f,
+ 0x6607, 0x7e69, 0x8805, 0x965e, 0x4f8d, 0x5319, 0x5636, 0x59cb,
+ 0x5aa4, 0x5c38, 0x5c4e, 0x5c4d, 0x5e02, 0x5f11, 0x6043, 0x65bd,
+ 0x662f, 0x6642, 0x67be, 0x67f4, 0x731c, 0x77e2, 0x793a, 0x7fc5,
+ 0x8494, 0x84cd, 0x8996, 0x8a66, 0x8a69, 0x8ae1, 0x8c55, 0x8c7a,
+ 0x57f4, 0x5bd4, 0x5f0f, 0x606f, 0x62ed, 0x690d, 0x6b96, 0x6e5c,
+ 0x7184, 0x7bd2, 0x8755, 0x8b58, 0x8efe, 0x98df, 0x98fe, 0x4f38,
+ 0x4f81, 0x4fe1, 0x547b, 0x5a20, 0x5bb8, 0x613c, 0x65b0, 0x6668,
+ 0x71fc, 0x7533, 0x795e, 0x7d33, 0x814e, 0x81e3, 0x8398, 0x85aa,
+ 0x85ce, 0x8703, 0x8a0a, 0x8eab, 0x8f9b, 0x8fb0, 0x8fc5, 0x5931,
+ 0x5ba4, 0x5be6, 0x6089, 0x5be9, 0x5c0b, 0x5fc3, 0x6c81, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6c88, 0x6df1, 0x700b, 0x751a, 0x82af, 0x8af6, 0x4ec0,
+ 0x5341, 0x0000, 0x96d9, 0x6c0f, 0x4e9e, 0x4fc4, 0x5152, 0x555e,
+ 0x5a25, 0x5ce8, 0x6211, 0x7259, 0x82bd, 0x83aa, 0x86fe, 0x8859,
+ 0x8a1d, 0x963f, 0x96c5, 0x9913, 0x9d09, 0x9d5d, 0x580a, 0x5cb3,
+ 0x5dbd, 0x5e44, 0x60e1, 0x6115, 0x63e1, 0x0000, 0x6e25, 0x9102,
+ 0x9354, 0x984e, 0x9c10, 0x9f77, 0x5b89, 0x5cb8, 0x6309, 0x664f,
+ 0x6848, 0x773c, 0x96c1, 0x978d, 0x9854, 0x9b9f, 0x65a1, 0x8b01,
+ 0x8ecb, 0x95bc, 0x5535, 0x5ca9, 0x5dd6, 0x5eb5, 0x6697, 0x764c,
+ 0x83f4, 0x95c7, 0x58d3, 0x62bc, 0x72ce, 0x9d28, 0x4ef0, 0x592e,
+ 0x600f, 0x663b, 0x6b83, 0x79e7, 0x9d26, 0x5393, 0x54c0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x57c3, 0x5d16, 0x611b, 0x66d6, 0x6daf, 0x788d, 0x827e,
+ 0x9698, 0x9744, 0x5384, 0x627c, 0x6396, 0x6db2, 0x7e0a, 0x814b,
+ 0x984d, 0x6afb, 0x7f4c, 0x9daf, 0x9e1a, 0x4e5f, 0x503b, 0x51b6,
+ 0x591c, 0x60f9, 0x63f6, 0x6930, 0x723a, 0x8036, 0x82e5, 0x91ce,
+ 0x5f31, 0x0000, 0x0000, 0x7d04, 0x0000, 0x846f, 0x84bb, 0x85e5,
+ 0x8e8d, 0x0000, 0x4f6f, 0x0000, 0x0000, 0x58e4, 0x5b43, 0x6059,
+ 0x63da, 0x6518, 0x656d, 0x6698, 0x0000, 0x694a, 0x6a23, 0x6d0b,
+ 0x7001, 0x716c, 0x75d2, 0x760d, 0x79b3, 0x7a70, 0x0000, 0x7f8a,
+ 0x0000, 0x8944, 0x0000, 0x8b93, 0x91c0, 0x967d, 0x0000, 0x990a,
+ 0x5704, 0x5fa1, 0x65bc, 0x6f01, 0x7600, 0x79a6, 0x8a9e, 0x99ad,
+ 0x9b5a, 0x9f6c, 0x5104, 0x61b6, 0x6291, 0x6a8d, 0x81c6, 0x5043,
+ 0x5830, 0x5f66, 0x7109, 0x8a00, 0x8afa, 0x5b7c, 0x8616, 0x4ffa,
+ 0x513c, 0x56b4, 0x5944, 0x63a9, 0x6df9, 0x5daa, 0x696d, 0x5186,
+ 0x4e88, 0x4f59, 0x0000, 0x0000, 0x0000, 0x5982, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6b5f, 0x6c5d, 0x0000, 0x74b5, 0x7916, 0x0000,
+ 0x8207, 0x8245, 0x8339, 0x8f3f, 0x8f5d, 0x0000, 0x9918, 0x0000,
+ 0x0000, 0x0000, 0x4ea6, 0x0000, 0x57df, 0x5f79, 0x6613, 0x0000,
+ 0x0000, 0x75ab, 0x7e79, 0x8b6f, 0x0000, 0x9006, 0x9a5b, 0x56a5,
+ 0x5827, 0x59f8, 0x5a1f, 0x5bb4, 0x0000, 0x5ef6, 0x0000, 0x0000,
+ 0x6350, 0x633b, 0x0000, 0x693d, 0x6c87, 0x6cbf, 0x6d8e, 0x6d93,
+ 0x6df5, 0x6f14, 0x0000, 0x70df, 0x7136, 0x7159, 0x0000, 0x71c3,
+ 0x71d5, 0x0000, 0x784f, 0x786f, 0x0000, 0x7b75, 0x7de3, 0x0000,
+ 0x7e2f, 0x0000, 0x884d, 0x8edf, 0x0000, 0x0000, 0x0000, 0x925b,
+ 0x0000, 0x9cf6, 0x0000, 0x0000, 0x54bd, 0x6085, 0x6d85, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x71b1, 0x0000, 0x0000, 0x95b1, 0x53ad, 0x0000,
+ 0x0000, 0x0000, 0x67d3, 0x0000, 0x708e, 0x7130, 0x7430, 0x8276,
+ 0x82d2, 0x0000, 0x95bb, 0x9ae5, 0x9e7d, 0x66c4, 0x0000, 0x71c1,
+ 0x0000, 0x0000, 0x0000, 0x584b, 0x0000, 0x0000, 0x5db8, 0x5f71,
+ 0x0000, 0x6620, 0x668e, 0x6979, 0x69ae, 0x6c38, 0x6cf3, 0x6e36,
+ 0x6f41, 0x6fda, 0x701b, 0x702f, 0x7150, 0x71df, 0x7370, 0x0000,
+ 0x745b, 0x7469, 0x74d4, 0x76c8, 0x7a4e, 0x7e93, 0x0000, 0x0000,
+ 0x82f1, 0x8a60, 0x8fce, 0x0000, 0x9348, 0x0000, 0x9719, 0x0000,
+ 0x0000, 0x4e42, 0x502a, 0x0000, 0x5208, 0x53e1, 0x66f3, 0x6c6d,
+ 0x6fca, 0x730a, 0x777f, 0x7a62, 0x82ae, 0x85dd, 0x8602, 0x0000,
+ 0x88d4, 0x8a63, 0x8b7d, 0x8c6b, 0x0000, 0x92b3, 0x0000, 0x9713,
+ 0x9810, 0x4e94, 0x4f0d, 0x4fc9, 0x50b2, 0x5348, 0x543e, 0x5433,
+ 0x55da, 0x5862, 0x58ba, 0x5967, 0x5a1b, 0x5be4, 0x609f, 0x0000,
+ 0x61ca, 0x6556, 0x65ff, 0x6664, 0x68a7, 0x6c5a, 0x6fb3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x70cf, 0x71ac, 0x7352, 0x7b7d, 0x8708, 0x8aa4, 0x9c32,
+ 0x9f07, 0x5c4b, 0x6c83, 0x7344, 0x7389, 0x923a, 0x6eab, 0x7465,
+ 0x761f, 0x7a69, 0x7e15, 0x860a, 0x5140, 0x58c5, 0x64c1, 0x74ee,
+ 0x7515, 0x7670, 0x7fc1, 0x9095, 0x96cd, 0x9954, 0x6e26, 0x74e6,
+ 0x7aa9, 0x7aaa, 0x81e5, 0x86d9, 0x8778, 0x8a1b, 0x5a49, 0x5b8c,
+ 0x5b9b, 0x68a1, 0x6900, 0x6d63, 0x73a9, 0x7413, 0x742c, 0x7897,
+ 0x7de9, 0x7feb, 0x8118, 0x8155, 0x839e, 0x8c4c, 0x962e, 0x9811,
+ 0x66f0, 0x5f80, 0x65fa, 0x6789, 0x6c6a, 0x738b, 0x502d, 0x5a03,
+ 0x6b6a, 0x77ee, 0x5916, 0x5d6c, 0x5dcd, 0x7325, 0x754f, 0x0000,
+ 0x0000, 0x50e5, 0x51f9, 0x582f, 0x592d, 0x5996, 0x59da, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5be5, 0x0000, 0x0000, 0x5da2, 0x62d7, 0x6416, 0x6493,
+ 0x64fe, 0x0000, 0x66dc, 0x0000, 0x6a48, 0x0000, 0x71ff, 0x7464,
+ 0x0000, 0x7a88, 0x7aaf, 0x7e47, 0x7e5e, 0x8000, 0x8170, 0x0000,
+ 0x87ef, 0x8981, 0x8b20, 0x9059, 0x0000, 0x9080, 0x9952, 0x617e,
+ 0x6b32, 0x6d74, 0x7e1f, 0x8925, 0x8fb1, 0x4fd1, 0x50ad, 0x5197,
+ 0x52c7, 0x57c7, 0x5889, 0x5bb9, 0x5eb8, 0x6142, 0x6995, 0x6d8c,
+ 0x6e67, 0x6eb6, 0x7194, 0x7462, 0x7528, 0x752c, 0x8073, 0x8338,
+ 0x84c9, 0x8e0a, 0x9394, 0x93de, 0x0000, 0x4e8e, 0x4f51, 0x5076,
+ 0x512a, 0x53c8, 0x53cb, 0x53f3, 0x5b87, 0x5bd3, 0x5c24, 0x611a,
+ 0x6182, 0x65f4, 0x725b, 0x7397, 0x7440, 0x76c2, 0x7950, 0x7991,
+ 0x79b9, 0x7d06, 0x7fbd, 0x828b, 0x85d5, 0x865e, 0x8fc2, 0x9047,
+ 0x90f5, 0x91ea, 0x9685, 0x96e8, 0x96e9, 0x52d6, 0x5f67, 0x65ed,
+ 0x6631, 0x682f, 0x715c, 0x7a36, 0x90c1, 0x980a, 0x4e91, 0x6688,
+ 0x6a52, 0x6b9e, 0x6f90, 0x7189, 0x8018, 0x82b8, 0x8553, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x904b, 0x9695, 0x96f2, 0x97fb, 0x851a, 0x9b31, 0x4e90,
+ 0x718a, 0x96c4, 0x5143, 0x539f, 0x54e1, 0x5713, 0x5712, 0x57a3,
+ 0x5a9b, 0x5ac4, 0x5bc3, 0x6028, 0x613f, 0x63f4, 0x6c85, 0x6d39,
+ 0x6e72, 0x6e90, 0x7230, 0x733f, 0x7457, 0x82d1, 0x8881, 0x8f45,
+ 0x9060, 0x0000, 0x9662, 0x9858, 0x9d1b, 0x6708, 0x8d8a, 0x925e,
+ 0x4f4d, 0x5049, 0x50de, 0x5371, 0x570d, 0x59d4, 0x5a01, 0x5c09,
+ 0x6170, 0x6690, 0x6e2d, 0x7232, 0x744b, 0x7def, 0x80c3, 0x840e,
+ 0x8466, 0x853f, 0x875f, 0x885b, 0x8918, 0x8b02, 0x9055, 0x97cb,
+ 0x9b4f, 0x4e73, 0x4f91, 0x5112, 0x516a, 0x0000, 0x552f, 0x55a9,
+ 0x5b7a, 0x5ba5, 0x5e7c, 0x5e7d, 0x5ebe, 0x60a0, 0x60df, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6108, 0x6109, 0x63c4, 0x6538, 0x6709, 0x0000, 0x67d4,
+ 0x67da, 0x0000, 0x6961, 0x6962, 0x6cb9, 0x6d27, 0x0000, 0x6e38,
+ 0x0000, 0x6fe1, 0x7336, 0x7337, 0x0000, 0x745c, 0x7531, 0x0000,
+ 0x7652, 0x0000, 0x0000, 0x7dad, 0x81fe, 0x8438, 0x88d5, 0x8a98,
+ 0x8adb, 0x8aed, 0x8e30, 0x8e42, 0x904a, 0x903e, 0x907a, 0x9149,
+ 0x91c9, 0x936e, 0x0000, 0x0000, 0x5809, 0x0000, 0x6bd3, 0x8089,
+ 0x80b2, 0x0000, 0x0000, 0x5141, 0x596b, 0x5c39, 0x0000, 0x0000,
+ 0x6f64, 0x73a7, 0x80e4, 0x8d07, 0x0000, 0x9217, 0x958f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x807f, 0x620e, 0x701c, 0x7d68, 0x878d,
+ 0x0000, 0x57a0, 0x6069, 0x6147, 0x6bb7, 0x8abe, 0x9280, 0x96b1,
+ 0x4e59, 0x541f, 0x6deb, 0x852d, 0x9670, 0x97f3, 0x98ee, 0x63d6,
+ 0x6ce3, 0x9091, 0x51dd, 0x61c9, 0x81ba, 0x9df9, 0x4f9d, 0x501a,
+ 0x5100, 0x5b9c, 0x610f, 0x61ff, 0x64ec, 0x6905, 0x6bc5, 0x7591,
+ 0x77e3, 0x7fa9, 0x8264, 0x858f, 0x87fb, 0x8863, 0x8abc, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8b70, 0x91ab, 0x4e8c, 0x4ee5, 0x4f0a, 0x0000, 0x0000,
+ 0x5937, 0x59e8, 0x0000, 0x5df2, 0x5f1b, 0x5f5b, 0x6021, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x723e, 0x73e5, 0x0000, 0x0000, 0x75cd,
+ 0x0000, 0x79fb, 0x0000, 0x800c, 0x8033, 0x8084, 0x82e1, 0x8351,
+ 0x0000, 0x0000, 0x8cbd, 0x8cb3, 0x9087, 0x0000, 0x0000, 0x98f4,
+ 0x990c, 0x0000, 0x0000, 0x7037, 0x76ca, 0x7fca, 0x7fcc, 0x7ffc,
+ 0x8b1a, 0x4eba, 0x4ec1, 0x5203, 0x5370, 0x0000, 0x0000, 0x56e0,
+ 0x59fb, 0x5bc5, 0x5f15, 0x5fcd, 0x6e6e, 0x0000, 0x0000, 0x7d6a,
+ 0x8335, 0x0000, 0x8693, 0x8a8d, 0x0000, 0x976d, 0x9777, 0x0000,
+ 0x0000, 0x4e00, 0x4f5a, 0x4f7e, 0x58f9, 0x65e5, 0x6ea2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9038, 0x93b0, 0x99b9, 0x4efb, 0x58ec, 0x598a, 0x59d9,
+ 0x6041, 0x0000, 0x0000, 0x7a14, 0x0000, 0x834f, 0x8cc3, 0x5165,
+ 0x5344, 0x0000, 0x0000, 0x0000, 0x4ecd, 0x5269, 0x5b55, 0x82bf,
+ 0x4ed4, 0x523a, 0x54a8, 0x59c9, 0x59ff, 0x5b50, 0x5b57, 0x5b5c,
+ 0x6063, 0x6148, 0x6ecb, 0x7099, 0x716e, 0x7386, 0x74f7, 0x75b5,
+ 0x78c1, 0x7d2b, 0x8005, 0x81ea, 0x8328, 0x8517, 0x85c9, 0x8aee,
+ 0x8cc7, 0x96cc, 0x4f5c, 0x52fa, 0x56bc, 0x65ab, 0x6628, 0x707c,
+ 0x70b8, 0x7235, 0x7dbd, 0x828d, 0x914c, 0x96c0, 0x9d72, 0x5b71,
+ 0x68e7, 0x6b98, 0x6f7a, 0x76de, 0x5c91, 0x66ab, 0x6f5b, 0x7bb4,
+ 0x7c2a, 0x8836, 0x96dc, 0x4e08, 0x4ed7, 0x5320, 0x5834, 0x58bb,
+ 0x58ef, 0x596c, 0x5c07, 0x5e33, 0x5e84, 0x5f35, 0x638c, 0x66b2,
+ 0x6756, 0x6a1f, 0x6aa3, 0x6b0c, 0x6f3f, 0x7246, 0x0000, 0x7350,
+ 0x748b, 0x7ae0, 0x7ca7, 0x8178, 0x81df, 0x81e7, 0x838a, 0x846c,
+ 0x8523, 0x8594, 0x85cf, 0x88dd, 0x8d13, 0x91ac, 0x9577, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x969c, 0x518d, 0x54c9, 0x5728, 0x5bb0, 0x624d, 0x6750,
+ 0x683d, 0x6893, 0x6e3d, 0x6ed3, 0x707d, 0x7e21, 0x88c1, 0x8ca1,
+ 0x8f09, 0x9f4b, 0x9f4e, 0x722d, 0x7b8f, 0x8acd, 0x931a, 0x4f47,
+ 0x4f4e, 0x5132, 0x5480, 0x59d0, 0x5e95, 0x62b5, 0x6775, 0x696e,
+ 0x6a17, 0x6cae, 0x6e1a, 0x72d9, 0x732a, 0x75bd, 0x7bb8, 0x7d35,
+ 0x82e7, 0x83f9, 0x8457, 0x85f7, 0x8a5b, 0x8caf, 0x8e87, 0x9019,
+ 0x90b8, 0x96ce, 0x9f5f, 0x52e3, 0x540a, 0x5ae1, 0x5bc2, 0x6458,
+ 0x6575, 0x6ef4, 0x72c4, 0x0000, 0x7684, 0x7a4d, 0x7b1b, 0x7c4d,
+ 0x7e3e, 0x7fdf, 0x837b, 0x8b2b, 0x8cca, 0x8d64, 0x8de1, 0x8e5f,
+ 0x8fea, 0x8ff9, 0x9069, 0x93d1, 0x4f43, 0x4f7a, 0x50b3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5168, 0x5178, 0x524d, 0x526a, 0x5861, 0x587c, 0x5960,
+ 0x5c08, 0x5c55, 0x5edb, 0x609b, 0x6230, 0x6813, 0x6bbf, 0x6c08,
+ 0x6fb1, 0x714e, 0x7420, 0x7530, 0x7538, 0x7551, 0x7672, 0x7b4c,
+ 0x7b8b, 0x7bad, 0x7bc6, 0x7e8f, 0x8a6e, 0x8f3e, 0x8f49, 0x923f,
+ 0x9293, 0x9322, 0x942b, 0x96fb, 0x985a, 0x986b, 0x991e, 0x5207,
+ 0x622a, 0x6298, 0x6d59, 0x7664, 0x7aca, 0x7bc0, 0x7d76, 0x5360,
+ 0x5cbe, 0x5e97, 0x6f38, 0x70b9, 0x7c98, 0x9711, 0x9b8e, 0x9ede,
+ 0x63a5, 0x647a, 0x8776, 0x4e01, 0x4e95, 0x4ead, 0x505c, 0x5075,
+ 0x5448, 0x59c3, 0x5b9a, 0x5e40, 0x5ead, 0x5ef7, 0x5f81, 0x60c5,
+ 0x633a, 0x653f, 0x6574, 0x65cc, 0x6676, 0x6678, 0x67fe, 0x6968,
+ 0x6a89, 0x6b63, 0x6c40, 0x6dc0, 0x6de8, 0x6e1f, 0x6e5e, 0x701e,
+ 0x70a1, 0x738e, 0x73fd, 0x753a, 0x775b, 0x7887, 0x798e, 0x7a0b,
+ 0x7a7d, 0x7cbe, 0x7d8e, 0x8247, 0x8a02, 0x8aea, 0x8c9e, 0x912d,
+ 0x914a, 0x91d8, 0x9266, 0x92cc, 0x9320, 0x9706, 0x9756, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x975c, 0x9802, 0x9f0e, 0x5236, 0x5291, 0x557c, 0x5824,
+ 0x5e1d, 0x5f1f, 0x608c, 0x63d0, 0x68af, 0x6fdf, 0x796d, 0x7b2c,
+ 0x81cd, 0x85ba, 0x88fd, 0x8af8, 0x8e44, 0x918d, 0x9664, 0x969b,
+ 0x973d, 0x984c, 0x9f4a, 0x4fce, 0x5146, 0x51cb, 0x52a9, 0x5632,
+ 0x5f14, 0x5f6b, 0x63aa, 0x64cd, 0x65e9, 0x6641, 0x66fa, 0x66f9,
+ 0x671d, 0x689d, 0x68d7, 0x69fd, 0x6f15, 0x6f6e, 0x7167, 0x71e5,
+ 0x722a, 0x74aa, 0x773a, 0x7956, 0x795a, 0x79df, 0x7a20, 0x7a95,
+ 0x7c97, 0x7cdf, 0x7d44, 0x7e70, 0x8087, 0x85fb, 0x86a4, 0x8a54,
+ 0x8abf, 0x8d99, 0x8e81, 0x9020, 0x906d, 0x91e3, 0x963b, 0x96d5,
+ 0x9ce5, 0x65cf, 0x7c07, 0x8db3, 0x93c3, 0x5b58, 0x5c0a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5352, 0x62d9, 0x731d, 0x5027, 0x5b97, 0x5f9e, 0x60b0,
+ 0x616b, 0x68d5, 0x6dd9, 0x742e, 0x7a2e, 0x7d42, 0x7d9c, 0x7e31,
+ 0x816b, 0x8e2a, 0x8e35, 0x937e, 0x9418, 0x4f50, 0x5750, 0x5de6,
+ 0x5ea7, 0x632b, 0x7f6a, 0x4e3b, 0x4f4f, 0x4f8f, 0x505a, 0x59dd,
+ 0x80c4, 0x546a, 0x5468, 0x55fe, 0x594f, 0x5b99, 0x5dde, 0x5eda,
+ 0x665d, 0x6731, 0x67f1, 0x682a, 0x6ce8, 0x6d32, 0x6e4a, 0x6f8d,
+ 0x70b7, 0x73e0, 0x7587, 0x7c4c, 0x7d02, 0x7d2c, 0x7da2, 0x821f,
+ 0x86db, 0x8a3b, 0x8a85, 0x8d70, 0x8e8a, 0x8f33, 0x9031, 0x914e,
+ 0x9152, 0x9444, 0x99d0, 0x7af9, 0x7ca5, 0x4fca, 0x5101, 0x51c6,
+ 0x57c8, 0x5bef, 0x5cfb, 0x6659, 0x6a3d, 0x6d5a, 0x6e96, 0x6fec,
+ 0x710c, 0x756f, 0x7ae3, 0x8822, 0x9021, 0x9075, 0x96cb, 0x99ff,
+ 0x8301, 0x4e2d, 0x4ef2, 0x8846, 0x91cd, 0x537d, 0x6adb, 0x696b,
+ 0x6c41, 0x847a, 0x589e, 0x618e, 0x66fe, 0x62ef, 0x70dd, 0x7511,
+ 0x75c7, 0x7e52, 0x84b8, 0x8b49, 0x8d08, 0x4e4b, 0x53ea, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x54ab, 0x5730, 0x5740, 0x5fd7, 0x6301, 0x6307, 0x646f,
+ 0x652f, 0x65e8, 0x667a, 0x679d, 0x67b3, 0x6b62, 0x6c60, 0x6c9a,
+ 0x6f2c, 0x77e5, 0x7825, 0x7949, 0x7957, 0x7d19, 0x80a2, 0x8102,
+ 0x81f3, 0x829d, 0x82b7, 0x8718, 0x8a8c, 0x0000, 0x8d04, 0x8dbe,
+ 0x9072, 0x76f4, 0x7a19, 0x7a37, 0x7e54, 0x8077, 0x5507, 0x55d4,
+ 0x5875, 0x632f, 0x6422, 0x6649, 0x664b, 0x686d, 0x699b, 0x6b84,
+ 0x6d25, 0x6eb1, 0x73cd, 0x7468, 0x74a1, 0x755b, 0x75b9, 0x76e1,
+ 0x771e, 0x778b, 0x79e6, 0x7e09, 0x7e1d, 0x81fb, 0x852f, 0x8897,
+ 0x8a3a, 0x8cd1, 0x8eeb, 0x0000, 0x9032, 0x93ad, 0x9663, 0x9673,
+ 0x9707, 0x4f84, 0x53f1, 0x59ea, 0x5ac9, 0x5e19, 0x684e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x74c6, 0x75be, 0x79e9, 0x7a92, 0x81a3, 0x86ed, 0x8cea,
+ 0x8dcc, 0x8fed, 0x659f, 0x6715, 0x0000, 0x57f7, 0x6f57, 0x7ddd,
+ 0x8f2f, 0x93f6, 0x96c6, 0x5fb5, 0x61f2, 0x6f84, 0x4e14, 0x4f98,
+ 0x501f, 0x53c9, 0x55df, 0x5d6f, 0x5dee, 0x6b21, 0x6b64, 0x78cb,
+ 0x7b9a, 0x0000, 0x8e49, 0x0000, 0x906e, 0x6349, 0x643e, 0x7740,
+ 0x7a84, 0x932f, 0x947f, 0x9f6a, 0x64b0, 0x6faf, 0x71e6, 0x74a8,
+ 0x74da, 0x7ac4, 0x7c12, 0x7e82, 0x7cb2, 0x7e98, 0x8b9a, 0x8d0a,
+ 0x947d, 0x9910, 0x994c, 0x5239, 0x5bdf, 0x64e6, 0x672d, 0x7d2e,
+ 0x50ed, 0x0000, 0x5879, 0x6158, 0x6159, 0x61fa, 0x65ac, 0x7ad9,
+ 0x8b92, 0x8b96, 0x5009, 0x5021, 0x5275, 0x5531, 0x5a3c, 0x5ee0,
+ 0x5f70, 0x6134, 0x655e, 0x660c, 0x6636, 0x66a2, 0x69cd, 0x6ec4,
+ 0x6f32, 0x7316, 0x7621, 0x7a93, 0x8139, 0x8259, 0x83d6, 0x84bc,
+ 0x50b5, 0x57f0, 0x5bc0, 0x5be8, 0x5f69, 0x63a1, 0x7826, 0x7db5,
+ 0x83dc, 0x8521, 0x91c7, 0x91f5, 0x518a, 0x67f5, 0x7b56, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8cac, 0x51c4, 0x59bb, 0x60bd, 0x8655, 0x501c, 0x0000,
+ 0x5254, 0x5c3a, 0x617d, 0x621a, 0x62d3, 0x64f2, 0x65a5, 0x6ecc,
+ 0x7620, 0x810a, 0x8e60, 0x965f, 0x96bb, 0x4edf, 0x5343, 0x5598,
+ 0x5929, 0x5ddd, 0x64c5, 0x6cc9, 0x6dfa, 0x7394, 0x7a7f, 0x821b,
+ 0x85a6, 0x8ce4, 0x8e10, 0x9077, 0x91e7, 0x95e1, 0x9621, 0x97c6,
+ 0x51f8, 0x54f2, 0x5586, 0x5fb9, 0x64a4, 0x6f88, 0x7db4, 0x8f1f,
+ 0x8f4d, 0x9435, 0x50c9, 0x5c16, 0x6cbe, 0x6dfb, 0x751b, 0x77bb,
+ 0x7c3d, 0x7c64, 0x8a79, 0x8ac2, 0x581e, 0x59be, 0x5e16, 0x6377,
+ 0x7252, 0x758a, 0x776b, 0x8adc, 0x8cbc, 0x8f12, 0x5ef3, 0x6674,
+ 0x6df8, 0x807d, 0x83c1, 0x8acb, 0x9751, 0x9bd6, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5243, 0x66ff, 0x6d95, 0x6eef, 0x7de0, 0x8ae6, 0x902e,
+ 0x905e, 0x9ad4, 0x521d, 0x527f, 0x54e8, 0x6194, 0x6284, 0x62db,
+ 0x68a2, 0x6912, 0x695a, 0x6a35, 0x7092, 0x7126, 0x785d, 0x7901,
+ 0x790e, 0x79d2, 0x7a0d, 0x8096, 0x8278, 0x82d5, 0x8349, 0x8549,
+ 0x8c82, 0x8d85, 0x9162, 0x918b, 0x91ae, 0x4fc3, 0x56d1, 0x71ed,
+ 0x77d7, 0x8700, 0x89f8, 0x5bf8, 0x5fd6, 0x6751, 0x90a8, 0x53e2,
+ 0x585a, 0x5bf5, 0x60a4, 0x6181, 0x6460, 0x7e3d, 0x8070, 0x8525,
+ 0x9283, 0x64ae, 0x50ac, 0x5d14, 0x6700, 0x589c, 0x62bd, 0x63a8,
+ 0x690e, 0x6978, 0x6a1e, 0x6e6b, 0x76ba, 0x79cb, 0x82bb, 0x8429,
+ 0x8acf, 0x8da8, 0x8ffd, 0x9112, 0x914b, 0x919c, 0x9310, 0x9318,
+ 0x939a, 0x96db, 0x9a36, 0x9c0d, 0x4e11, 0x755c, 0x795d, 0x7afa,
+ 0x7b51, 0x7bc9, 0x7e2e, 0x84c4, 0x8e59, 0x8e74, 0x8ef8, 0x9010,
+ 0x6625, 0x693f, 0x7443, 0x51fa, 0x672e, 0x9edc, 0x5145, 0x5fe0,
+ 0x6c96, 0x87f2, 0x885d, 0x8877, 0x60b4, 0x81b5, 0x8403, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8d05, 0x53d6, 0x5439, 0x5634, 0x5a36, 0x5c31, 0x708a,
+ 0x7fe0, 0x805a, 0x8106, 0x81ed, 0x8da3, 0x9189, 0x9a5f, 0x9df2,
+ 0x5074, 0x4ec4, 0x53a0, 0x60fb, 0x6e2c, 0x5c64, 0x4f88, 0x5024,
+ 0x55e4, 0x5cd9, 0x5e5f, 0x6065, 0x6894, 0x6cbb, 0x6dc4, 0x71be,
+ 0x75d4, 0x75f4, 0x7661, 0x7a1a, 0x7a49, 0x7dc7, 0x7dfb, 0x7f6e,
+ 0x81f4, 0x86a9, 0x8f1c, 0x96c9, 0x99b3, 0x9f52, 0x5247, 0x52c5,
+ 0x98ed, 0x89aa, 0x4e03, 0x67d2, 0x6f06, 0x4fb5, 0x5be2, 0x6795,
+ 0x0000, 0x6d78, 0x741b, 0x7827, 0x91dd, 0x937c, 0x87c4, 0x79e4,
+ 0x7a31, 0x5feb, 0x4ed6, 0x54a4, 0x553e, 0x58ae, 0x59a5, 0x60f0,
+ 0x6253, 0x62d6, 0x6736, 0x6955, 0x8235, 0x9640, 0x99b1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x99dd, 0x502c, 0x5353, 0x5544, 0x577c, 0x0000, 0x6258,
+ 0x0000, 0x64e2, 0x666b, 0x67dd, 0x6fc1, 0x6fef, 0x7422, 0x7438,
+ 0x8a17, 0x9438, 0x5451, 0x5606, 0x5766, 0x5f48, 0x619a, 0x6b4e,
+ 0x7058, 0x70ad, 0x7dbb, 0x8a95, 0x596a, 0x812b, 0x63a2, 0x7708,
+ 0x803d, 0x8caa, 0x5854, 0x642d, 0x69bb, 0x5b95, 0x5e11, 0x6e6f,
+ 0x0000, 0x8569, 0x514c, 0x53f0, 0x592a, 0x6020, 0x614b, 0x6b86,
+ 0x6c70, 0x6cf0, 0x7b1e, 0x80ce, 0x82d4, 0x8dc6, 0x90b0, 0x98b1,
+ 0x0000, 0x64c7, 0x6fa4, 0x6491, 0x6504, 0x514e, 0x5410, 0x571f,
+ 0x8a0e, 0x615f, 0x6876, 0x0000, 0x75db, 0x7b52, 0x7d71, 0x901a,
+ 0x5806, 0x69cc, 0x817f, 0x892a, 0x9000, 0x9839, 0x5078, 0x5957,
+ 0x59ac, 0x6295, 0x900f, 0x9b2a, 0x615d, 0x7279, 0x95d6, 0x5761,
+ 0x5a46, 0x5df4, 0x628a, 0x64ad, 0x64fa, 0x6777, 0x6ce2, 0x6d3e,
+ 0x722c, 0x7436, 0x7834, 0x7f77, 0x82ad, 0x8ddb, 0x9817, 0x5224,
+ 0x5742, 0x677f, 0x7248, 0x74e3, 0x8ca9, 0x8fa6, 0x9211, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x962a, 0x516b, 0x53ed, 0x634c, 0x4f69, 0x5504, 0x6096,
+ 0x6557, 0x6c9b, 0x6d7f, 0x724c, 0x72fd, 0x7a17, 0x8987, 0x8c9d,
+ 0x5f6d, 0x6f8e, 0x70f9, 0x81a8, 0x610e, 0x0000, 0x504f, 0x6241,
+ 0x7247, 0x7bc7, 0x7de8, 0x7fe9, 0x904d, 0x97ad, 0x9a19, 0x8cb6,
+ 0x576a, 0x5e73, 0x67b0, 0x840d, 0x8a55, 0x5420, 0x5b16, 0x5e63,
+ 0x5ee2, 0x5f0a, 0x6583, 0x80ba, 0x853d, 0x9589, 0x965b, 0x4f48,
+ 0x5305, 0x530d, 0x530f, 0x5486, 0x54fa, 0x5703, 0x5e03, 0x6016,
+ 0x629b, 0x62b1, 0x6355, 0x66b4, 0x6ce1, 0x6d66, 0x75b1, 0x7832,
+ 0x80de, 0x812f, 0x82de, 0x8461, 0x84b2, 0x888d, 0x8912, 0x900b,
+ 0x92ea, 0x98fd, 0x9b91, 0x5e45, 0x0000, 0x66dd, 0x7011, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7206, 0x0000, 0x4ff5, 0x527d, 0x5f6a, 0x6153, 0x6753,
+ 0x6a19, 0x6f02, 0x74e2, 0x7968, 0x8868, 0x8c79, 0x98c7, 0x98c4,
+ 0x9a43, 0x54c1, 0x7a1f, 0x6953, 0x8af7, 0x8c4a, 0x98a8, 0x99ae,
+ 0x5f7c, 0x62ab, 0x75b2, 0x76ae, 0x88ab, 0x907f, 0x9642, 0x5339,
+ 0x5f3c, 0x5fc5, 0x0000, 0x73cc, 0x7562, 0x758b, 0x7b46, 0x82fe,
+ 0x999d, 0x4e4f, 0x903c, 0x4e0b, 0x4f55, 0x53a6, 0x590f, 0x5ec8,
+ 0x6630, 0x6cb3, 0x7455, 0x8377, 0x8766, 0x8cc0, 0x9050, 0x971e,
+ 0x9c15, 0x58d1, 0x5b78, 0x8650, 0x8b14, 0x9db4, 0x5bd2, 0x6068,
+ 0x608d, 0x65f1, 0x6c57, 0x6f22, 0x6fa3, 0x701a, 0x7f55, 0x7ff0,
+ 0x9591, 0x9592, 0x9650, 0x97d3, 0x5272, 0x8f44, 0x51fd, 0x542b,
+ 0x54b8, 0x5563, 0x558a, 0x6abb, 0x6db5, 0x7dd8, 0x8266, 0x929c,
+ 0x9677, 0x9e79, 0x5408, 0x54c8, 0x76d2, 0x86e4, 0x95a4, 0x95d4,
+ 0x965c, 0x4ea2, 0x4f09, 0x59ee, 0x5ae6, 0x5df7, 0x6052, 0x6297,
+ 0x676d, 0x6841, 0x6c86, 0x6e2f, 0x7f38, 0x809b, 0x822a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x884c, 0x0000, 0x9805, 0x4ea5, 0x5055, 0x54b3, 0x5793,
+ 0x595a, 0x5b69, 0x5bb3, 0x61c8, 0x6977, 0x6d77, 0x7023, 0x87f9,
+ 0x89e3, 0x8a72, 0x8ae7, 0x9082, 0x99ed, 0x9ab8, 0x52be, 0x6838,
+ 0x5016, 0x5e78, 0x674f, 0x8347, 0x0000, 0x4eab, 0x5411, 0x56ae,
+ 0x73e6, 0x9115, 0x97ff, 0x9909, 0x9957, 0x9999, 0x5653, 0x589f,
+ 0x865b, 0x8a31, 0x61b2, 0x6af6, 0x737b, 0x8ed2, 0x6b47, 0x96aa,
+ 0x9a57, 0x5955, 0x7200, 0x8d6b, 0x9769, 0x4fd4, 0x5cf4, 0x5f26,
+ 0x61f8, 0x665b, 0x6ceb, 0x70ab, 0x7384, 0x73b9, 0x73fe, 0x7729,
+ 0x774d, 0x7d43, 0x7d62, 0x7e23, 0x8237, 0x8852, 0x0000, 0x8ce2,
+ 0x9249, 0x986f, 0x5b51, 0x7a74, 0x8840, 0x9801, 0x5acc, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4fe0, 0x5354, 0x593e, 0x5cfd, 0x633e, 0x6d79, 0x72f9,
+ 0x8105, 0x8107, 0x83a2, 0x92cf, 0x9830, 0x4ea8, 0x5144, 0x5211,
+ 0x578b, 0x5f62, 0x6cc2, 0x6ece, 0x7005, 0x7050, 0x70af, 0x7192,
+ 0x73e9, 0x0000, 0x834a, 0x87a2, 0x8861, 0x9008, 0x90a2, 0x93a3,
+ 0x99a8, 0x516e, 0x5f57, 0x60e0, 0x6167, 0x66b3, 0x8559, 0x8e4a,
+ 0x91af, 0x978b, 0x4e4e, 0x4e92, 0x547c, 0x58d5, 0x58fa, 0x597d,
+ 0x5cb5, 0x5f27, 0x6236, 0x6248, 0x660a, 0x6667, 0x6beb, 0x6d69,
+ 0x6dcf, 0x6e56, 0x6ef8, 0x6f94, 0x6fe0, 0x6fe9, 0x705d, 0x72d0,
+ 0x7425, 0x745a, 0x74e0, 0x7693, 0x795c, 0x7cca, 0x7e1e, 0x80e1,
+ 0x82a6, 0x846b, 0x84bf, 0x864e, 0x865f, 0x8774, 0x8b77, 0x8c6a,
+ 0x93ac, 0x9800, 0x9865, 0x60d1, 0x6216, 0x9177, 0x5a5a, 0x660f,
+ 0x6df7, 0x6e3e, 0x743f, 0x9b42, 0x5ffd, 0x60da, 0x7b0f, 0x54c4,
+ 0x5f18, 0x6c5e, 0x6cd3, 0x6d2a, 0x70d8, 0x7d05, 0x8679, 0x8a0c,
+ 0x9d3b, 0x5316, 0x548c, 0x5b05, 0x6a3a, 0x706b, 0x7575, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x798d, 0x79be, 0x82b1, 0x83ef, 0x8a71, 0x8b41, 0x8ca8,
+ 0x9774, 0x0000, 0x64f4, 0x652b, 0x78ba, 0x78bb, 0x7a6b, 0x4e38,
+ 0x559a, 0x5950, 0x5ba6, 0x5e7b, 0x60a3, 0x63db, 0x6b61, 0x6665,
+ 0x6853, 0x6e19, 0x7165, 0x74b0, 0x7d08, 0x9084, 0x9a69, 0x9c25,
+ 0x6d3b, 0x0000, 0x733e, 0x8c41, 0x95ca, 0x51f0, 0x5e4c, 0x5fa8,
+ 0x604d, 0x60f6, 0x6130, 0x614c, 0x6643, 0x6644, 0x69a5, 0x6cc1,
+ 0x6e5f, 0x6ec9, 0x6f62, 0x714c, 0x749c, 0x7687, 0x7bc1, 0x7c27,
+ 0x8352, 0x8757, 0x9051, 0x968d, 0x9ec3, 0x532f, 0x56de, 0x5efb,
+ 0x5f8a, 0x6062, 0x6094, 0x61f7, 0x6666, 0x6703, 0x6a9c, 0x6dee,
+ 0x6fae, 0x7070, 0x736a, 0x7e6a, 0x81be, 0x8334, 0x86d4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8aa8, 0x8cc4, 0x5283, 0x7372, 0x5b96, 0x6a6b, 0x9404,
+ 0x54ee, 0x5686, 0x5b5d, 0x6548, 0x6585, 0x66c9, 0x689f, 0x6d8d,
+ 0x6dc6, 0x723b, 0x80b4, 0x9175, 0x9a4d, 0x4faf, 0x5019, 0x539a,
+ 0x540e, 0x543c, 0x5589, 0x55c5, 0x5e3f, 0x5f8c, 0x673d, 0x7166,
+ 0x73dd, 0x9005, 0x52db, 0x52f3, 0x5864, 0x58ce, 0x7104, 0x718f,
+ 0x71fb, 0x85b0, 0x8a13, 0x0000, 0x85a8, 0x55a7, 0x6684, 0x714a,
+ 0x8431, 0x5349, 0x5599, 0x6bc1, 0x5f59, 0x5fbd, 0x63ee, 0x6689,
+ 0x7147, 0x8af1, 0x8f1d, 0x9ebe, 0x4f11, 0x643a, 0x70cb, 0x7566,
+ 0x8667, 0x6064, 0x8b4e, 0x9df8, 0x5147, 0x51f6, 0x5308, 0x6d36,
+ 0x80f8, 0x9ed1, 0x6615, 0x6b23, 0x7098, 0x75d5, 0x5403, 0x5c79,
+ 0x7d07, 0x8a16, 0x6b20, 0x6b3d, 0x6b46, 0x5438, 0x6070, 0x6d3d,
+ 0x7fd5, 0x8208, 0x50d6, 0x51de, 0x559c, 0x566b, 0x56cd, 0x59ec,
+ 0x5b09, 0x5e0c, 0x6199, 0x6198, 0x6231, 0x665e, 0x66e6, 0x7199,
+ 0x71b9, 0x71ba, 0x72a7, 0x79a7, 0x7a00, 0x7fb2, 0x8a70, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3164, 0x3001, 0x3002, 0x30fb, 0x2025, 0x22ef, 0x00a8, 0x3003
+};
+
+#ifndef LUA_FF_LIB
+
+static unsigned short johab_from_unicode_0[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd9ae, 0x0000, 0x0000, 0xd9b4, 0x0000, 0x0000, 0xd967,
+ 0xd937, 0x0000, 0xdca3, 0xd97c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd956, 0xd94e, 0xdd99, 0xdd9a, 0xd9a5, 0x0000, 0xd9d2, 0x0000,
+ 0xd9ac, 0xdd98, 0xdcac, 0xd97d, 0xdcf9, 0xdcf6, 0xdcfa, 0xd9af,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdca1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xdca2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd94f,
+ 0xdcaa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdcad, 0xdd3c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdd31, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xdd33, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd950,
+ 0xdd3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdd3d, 0x0000
+};
+
+static unsigned short johab_from_unicode_1[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xdd32, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdca4, 0xdd34,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xdd35, 0xdca6, 0xdd36, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xdd37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdca8,
+ 0xdd38, 0xdca9, 0xdd39, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xdd40, 0xdcaf, 0xdd3f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xdcab, 0xdd3b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdcae, 0xdd3e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_2[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd9a7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd9a8, 0xd9ab, 0xd9aa, 0xd9ad, 0xd9a6, 0xd9a9, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_3[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xdb51, 0xdb52, 0xdb53, 0xdb54, 0xdb55, 0xdb56, 0xdb57,
+ 0xdb58, 0xdb59, 0xdb5a, 0xdb5b, 0xdb5c, 0xdb5d, 0xdb5e, 0xdb5f,
+ 0xdb60, 0xdb61, 0x0000, 0xdb62, 0xdb63, 0xdb64, 0xdb65, 0xdb66,
+ 0xdb67, 0xdb68, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xdb71, 0xdb72, 0xdb73, 0xdb74, 0xdb75, 0xdb76, 0xdb77,
+ 0xdb78, 0xdb79, 0xdb7a, 0xdb7b, 0xdb7c, 0xdb7d, 0xdb7e, 0xdb91,
+ 0xdb92, 0xdb93, 0x0000, 0xdb94, 0xdb95, 0xdb96, 0xdb97, 0xdb98,
+ 0xdb99, 0xdb9a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_4[] = {
+ 0x0000, 0xdea7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xdea1, 0xdea2, 0xdea3, 0xdea4, 0xdea5, 0xdea6, 0xdea8, 0xdea9,
+ 0xdeaa, 0xdeab, 0xdeac, 0xdead, 0xdeae, 0xdeaf, 0xdeb0, 0xdeb1,
+ 0xdeb2, 0xdeb3, 0xdeb4, 0xdeb5, 0xdeb6, 0xdeb7, 0xdeb8, 0xdeb9,
+ 0xdeba, 0xdebb, 0xdebc, 0xdebd, 0xdebe, 0xdebf, 0xdec0, 0xdec1,
+ 0xded1, 0xded2, 0xded3, 0xded4, 0xded5, 0xded6, 0xded8, 0xded9,
+ 0xdeda, 0xdedb, 0xdedc, 0xdedd, 0xdede, 0xdedf, 0xdee0, 0xdee1,
+ 0xdee2, 0xdee3, 0xdee4, 0xdee5, 0xdee6, 0xdee7, 0xdee8, 0xdee9,
+ 0xdeea, 0xdeeb, 0xdeec, 0xdeed, 0xdeee, 0xdeef, 0xdef0, 0xdef1,
+ 0x0000, 0xded7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_20[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xd939, 0xd93a, 0x0000, 0xd93b, 0x0000,
+ 0xd93e, 0xd93f, 0x0000, 0x0000, 0xd940, 0xd941, 0x0000, 0x0000,
+ 0xd9d3, 0xd9d4, 0x0000, 0x0000, 0x0000, 0xd935, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd9b6, 0x0000, 0xd957, 0xd958, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xd968, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xdd9b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdd9c,
+ 0x0000, 0xdd9d, 0xdd9e, 0xdd9f, 0xdda0, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_21[] = {
+ 0x0000, 0x0000, 0x0000, 0xd959, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd9b5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xdc34, 0x0000, 0x0000, 0xd9e0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd9e5, 0xd9e2, 0x0000, 0x0000, 0x0000, 0xdc69, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xd95a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xdcf7, 0xdcf8, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xdcfb, 0xdcfc, 0xdcfd, 0xdcfe, 0x0000,
+ 0xdb40, 0xdb41, 0xdb42, 0xdb43, 0xdb44, 0xdb45, 0xdb46, 0xdb47,
+ 0xdb48, 0xdb49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xdb31, 0xdb32, 0xdb33, 0xdb34, 0xdb35, 0xdb36, 0xdb37, 0xdb38,
+ 0xdb39, 0xdb3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd977, 0xd978, 0xd976, 0xd979, 0xd97a, 0xd9d5, 0xd9d8, 0xd9d6,
+ 0xd9d9, 0xd9d7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd9a1, 0x0000, 0xd9a2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_22[] = {
+ 0xd9a3, 0x0000, 0xd963, 0xd9a4, 0x0000, 0x0000, 0x0000, 0xd964,
+ 0xd996, 0x0000, 0x0000, 0xd997, 0x0000, 0x0000, 0x0000, 0xd9b3,
+ 0x0000, 0xd9b2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd97e, 0x0000, 0x0000, 0xd992, 0xd954, 0x0000,
+ 0xd960, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd99e,
+ 0xd99f, 0xd99d, 0xd99c, 0xd994, 0xd995, 0x0000, 0xd9b1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd955, 0xd993, 0xd9b0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd991, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd966, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd951, 0xd965, 0x0000, 0x0000, 0xd952, 0xd953, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd99a, 0xd99b, 0x0000, 0x0000, 0xd998, 0xd999,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd961, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd936,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_23[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd962, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_24[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xdce7, 0xdce8, 0xdce9, 0xdcea, 0xdceb, 0xdcec, 0xdced, 0xdcee,
+ 0xdcef, 0xdcf0, 0xdcf1, 0xdcf2, 0xdcf3, 0xdcf4, 0xdcf5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xdd77, 0xdd78, 0xdd79, 0xdd7a,
+ 0xdd7b, 0xdd7c, 0xdd7d, 0xdd7e, 0xdd91, 0xdd92, 0xdd93, 0xdd94,
+ 0xdd95, 0xdd96, 0xdd97, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xdd5d, 0xdd5e, 0xdd5f, 0xdd60,
+ 0xdd61, 0xdd62, 0xdd63, 0xdd64, 0xdd65, 0xdd66, 0xdd67, 0xdd68,
+ 0xdd69, 0xdd6a, 0xdd6b, 0xdd6c, 0xdd6d, 0xdd6e, 0xdd6f, 0xdd70,
+ 0xdd71, 0xdd72, 0xdd73, 0xdd74, 0xdd75, 0xdd76, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xdccd, 0xdcce, 0xdccf, 0xdcd0, 0xdcd1, 0xdcd2, 0xdcd3, 0xdcd4,
+ 0xdcd5, 0xdcd6, 0xdcd7, 0xdcd8, 0xdcd9, 0xdcda, 0xdcdb, 0xdcdc,
+ 0xdcdd, 0xdcde, 0xdcdf, 0xdce0, 0xdce1, 0xdce2, 0xdce3, 0xdce4,
+ 0xdce5, 0xdce6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_25[] = {
+ 0xdba1, 0xdbac, 0xdba2, 0xdbad, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xdba3, 0xdbc8, 0xdbc7, 0xdbae,
+ 0xdba4, 0xdbc2, 0xdbc1, 0xdbaf, 0xdba6, 0xdbc6, 0xdbc5, 0xdbb1,
+ 0xdba5, 0xdbc4, 0xdbc3, 0xdbb0, 0xdba7, 0xdbbc, 0xdbc9, 0xdbca,
+ 0xdbb7, 0xdbcb, 0xdbcc, 0xdbb2, 0xdba9, 0xdbbe, 0xdbcd, 0xdbce,
+ 0xdbb9, 0xdbcf, 0xdbd0, 0xdbb4, 0xdba8, 0xdbd1, 0xdbd2, 0xdbb8,
+ 0xdbbd, 0xdbd3, 0xdbd4, 0xdbb3, 0xdbaa, 0xdbd5, 0xdbd6, 0xdbba,
+ 0xdbbf, 0xdbd7, 0xdbd8, 0xdbb5, 0xdbab, 0xdbd9, 0xdbda, 0xdbbb,
+ 0xdbdb, 0xdbdc, 0xdbc0, 0xdbdd, 0xdbde, 0xdbdf, 0xdbe0, 0xdbe1,
+ 0xdbe2, 0xdbe3, 0xdbe4, 0xdbb6, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd9c6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd971, 0xd970, 0x0000, 0xd9c3, 0xd9c7, 0xd9c8, 0xd9cb, 0xd9ca,
+ 0xd9c9, 0xd9cc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xd973, 0xd972, 0x0000, 0x0000, 0xd9ba, 0xd9b9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd975, 0xd974, 0x0000, 0x0000,
+ 0xd9b8, 0xd9b7, 0x0000, 0x0000, 0x0000, 0x0000, 0xd96f, 0xd96e,
+ 0xd9c2, 0xd9c1, 0x0000, 0xd96b, 0x0000, 0x0000, 0xd96d, 0xd96c,
+ 0xd9c4, 0xd9c5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_26[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd96a, 0xd969, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd9cf, 0xd9ce,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xd9d0, 0x0000, 0xd9d1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd95f, 0x0000, 0xd95e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd9bc, 0xd9bd, 0x0000, 0xd9c0, 0xd9bb, 0xd9be, 0x0000, 0xd9bf,
+ 0xd9cd, 0xd9db, 0xd9dc, 0x0000, 0xd9dd, 0xd9da, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_30[] = {
+ 0x0000, 0xd932, 0xd933, 0xd938, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd944, 0xd945, 0xd946, 0xd947, 0xd948, 0xd949, 0xd94a, 0xd94b,
+ 0xd94c, 0xd94d, 0x0000, 0xd97b, 0xd942, 0xd943, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xdda1, 0xdda2, 0xdda3, 0xdda4, 0xdda5, 0xdda6, 0xdda7,
+ 0xdda8, 0xdda9, 0xddaa, 0xddab, 0xddac, 0xddad, 0xddae, 0xddaf,
+ 0xddb0, 0xddb1, 0xddb2, 0xddb3, 0xddb4, 0xddb5, 0xddb6, 0xddb7,
+ 0xddb8, 0xddb9, 0xddba, 0xddbb, 0xddbc, 0xddbd, 0xddbe, 0xddbf,
+ 0xddc0, 0xddc1, 0xddc2, 0xddc3, 0xddc4, 0xddc5, 0xddc6, 0xddc7,
+ 0xddc8, 0xddc9, 0xddca, 0xddcb, 0xddcc, 0xddcd, 0xddce, 0xddcf,
+ 0xddd0, 0xddd1, 0xddd2, 0xddd3, 0xddd4, 0xddd5, 0xddd6, 0xddd7,
+ 0xddd8, 0xddd9, 0xddda, 0xdddb, 0xdddc, 0xdddd, 0xddde, 0xdddf,
+ 0xdde0, 0xdde1, 0xdde2, 0xdde3, 0xdde4, 0xdde5, 0xdde6, 0xdde7,
+ 0xdde8, 0xdde9, 0xddea, 0xddeb, 0xddec, 0xdded, 0xddee, 0xddef,
+ 0xddf0, 0xddf1, 0xddf2, 0xddf3, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xde31, 0xde32, 0xde33, 0xde34, 0xde35, 0xde36, 0xde37,
+ 0xde38, 0xde39, 0xde3a, 0xde3b, 0xde3c, 0xde3d, 0xde3e, 0xde3f,
+ 0xde40, 0xde41, 0xde42, 0xde43, 0xde44, 0xde45, 0xde46, 0xde47,
+ 0xde48, 0xde49, 0xde4a, 0xde4b, 0xde4c, 0xde4d, 0xde4e, 0xde4f,
+ 0xde50, 0xde51, 0xde52, 0xde53, 0xde54, 0xde55, 0xde56, 0xde57,
+ 0xde58, 0xde59, 0xde5a, 0xde5b, 0xde5c, 0xde5d, 0xde5e, 0xde5f,
+ 0xde60, 0xde61, 0xde62, 0xde63, 0xde64, 0xde65, 0xde66, 0xde67,
+ 0xde68, 0xde69, 0xde6a, 0xde6b, 0xde6c, 0xde6d, 0xde6e, 0xde6f,
+ 0xde70, 0xde71, 0xde72, 0xde73, 0xde74, 0xde75, 0xde76, 0xde77,
+ 0xde78, 0xde79, 0xde7a, 0xde7b, 0xde7c, 0xde7d, 0xde7e, 0xde91,
+ 0xde92, 0xde93, 0xde94, 0xde95, 0xde96, 0xde97, 0xde98, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xd934, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_31[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x8442, 0x8443, 0x8444, 0x8445, 0x8446, 0x8447, 0x8448,
+ 0x9841, 0x8449, 0x844a, 0x844b, 0x844c, 0x844d, 0x844e, 0x844f,
+ 0x8450, 0x8451, 0x8453, 0xa841, 0x8454, 0x8455, 0x8456, 0x8457,
+ 0x8458, 0xbc41, 0x8459, 0x845a, 0x845b, 0x845c, 0x845d, 0x8461,
+ 0x8481, 0x84a1, 0x84c1, 0x84e1, 0x8541, 0x8561, 0x8581, 0x85a1,
+ 0x85c1, 0x85e1, 0x8641, 0x8661, 0x8681, 0x86a1, 0x86c1, 0x86e1,
+ 0x8741, 0x8761, 0x8781, 0x87a1, 0xd931, 0xdad5, 0xdad6, 0xdad7,
+ 0xdad8, 0xdad9, 0xdada, 0xdadb, 0xdadc, 0xdadd, 0xdade, 0xdadf,
+ 0xdae0, 0xdae1, 0xdae2, 0xdae3, 0xdae4, 0xdae5, 0xdae6, 0xdae7,
+ 0xdae8, 0xdae9, 0xdaea, 0xdaeb, 0xdaec, 0xdaed, 0xdaee, 0xdaef,
+ 0xdaf0, 0xdaf1, 0xdaf2, 0xdaf3, 0xdaf4, 0xdaf5, 0xdaf6, 0xdaf7,
+ 0xdaf8, 0xdaf9, 0xdafa, 0xdafb, 0xdafc, 0xdafd, 0xdafe, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_32[] = {
+ 0xdd41, 0xdd42, 0xdd43, 0xdd44, 0xdd45, 0xdd46, 0xdd47, 0xdd48,
+ 0xdd49, 0xdd4a, 0xdd4b, 0xdd4c, 0xdd4d, 0xdd4e, 0xdd4f, 0xdd50,
+ 0xdd51, 0xdd52, 0xdd53, 0xdd54, 0xdd55, 0xdd56, 0xdd57, 0xdd58,
+ 0xdd59, 0xdd5a, 0xdd5b, 0xdd5c, 0xd9df, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xdcb1, 0xdcb2, 0xdcb3, 0xdcb4, 0xdcb5, 0xdcb6, 0xdcb7, 0xdcb8,
+ 0xdcb9, 0xdcba, 0xdcbb, 0xdcbc, 0xdcbd, 0xdcbe, 0xdcbf, 0xdcc0,
+ 0xdcc1, 0xdcc2, 0xdcc3, 0xdcc4, 0xdcc5, 0xdcc6, 0xdcc7, 0xdcc8,
+ 0xdcc9, 0xdcca, 0xdccb, 0xdccc, 0x0000, 0x0000, 0x0000, 0xd9de,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_33[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xdc59, 0xdc5a, 0xdc5b, 0xdc5c, 0xdc5d, 0x0000, 0x0000, 0x0000,
+ 0xdc4a, 0xdc4b, 0xdc6c, 0xdc6d, 0xdc6e, 0xdc46, 0xdc47, 0xdc48,
+ 0xdc64, 0xdc65, 0xdc66, 0xdc67, 0xdc68, 0xdc31, 0xdc32, 0xdc33,
+ 0xdc35, 0xdc3b, 0xdc3c, 0xdc3d, 0xdc3e, 0xdc3f, 0xdc40, 0xdc41,
+ 0xdc42, 0xdc43, 0xdc44, 0xdc37, 0xdc38, 0xdc39, 0xdc3a, 0xdc4d,
+ 0xdc4e, 0xdc75, 0xdc76, 0xdc77, 0xdc78, 0xdc71, 0xdc72, 0xdc73,
+ 0xdc4f, 0xdc50, 0xdc51, 0xdc52, 0xdc53, 0xdc54, 0xdc55, 0xdc56,
+ 0xdc57, 0xdc58, 0xdc5e, 0xdc5f, 0xdc60, 0xdc61, 0xdc62, 0xdc63,
+ 0xdc6a, 0xdc6b, 0xd9e3, 0xdc7c, 0xdc36, 0xdc70, 0xdc91, 0xd9e1,
+ 0xdc4c, 0xdc7d, 0xdc45, 0x0000, 0x0000, 0x0000, 0x0000, 0xdc49,
+ 0xdc7a, 0x0000, 0x0000, 0xdc7b, 0x0000, 0x0000, 0xdc6f, 0x0000,
+ 0xd9e4, 0x0000, 0x0000, 0xdc74, 0xdc7e, 0xdc79, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_4e[] = {
+ 0xf179, 0xf2cb, 0x0000, 0xf662, 0x0000, 0x0000, 0x0000, 0xe742,
+ 0xf1db, 0xeab2, 0xeabe, 0xf7bb, 0x0000, 0xe996, 0x0000, 0x0000,
+ 0x0000, 0xf5e4, 0x0000, 0x0000, 0xf4a6, 0xe9e0, 0xeba6, 0x0000,
+ 0xe29a, 0xe940, 0x0000, 0x0000, 0x0000, 0x0000, 0xecaa, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf3e9, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe1fa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf93f, 0xe4a1, 0x0000, 0xf3ab, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xeed1, 0xe43c, 0x0000, 0xe29b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf3fd, 0x0000, 0xea4f, 0xf8ba, 0xf7b9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe262, 0x0000,
+ 0xecab, 0xf0e0, 0x0000, 0x0000, 0x0000, 0xe29c, 0xe0f7, 0xeda5,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe071, 0x0000, 0xe55c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf071, 0x0000, 0x0000, 0xe973, 0xeaad,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe0eb, 0x0000,
+ 0x0000, 0x0000, 0xe3ea, 0x0000, 0x0000, 0x0000, 0xe697, 0x0000,
+ 0xedf8, 0x0000, 0x0000, 0xea50, 0xf133, 0x0000, 0xefcd, 0x0000,
+ 0xf037, 0xeff6, 0xf8bb, 0x0000, 0xeee9, 0xf2cc, 0x0000, 0x0000,
+ 0xe376, 0x0000, 0x0000, 0xea51, 0x0000, 0x0000, 0xed3c, 0x0000,
+ 0x0000, 0xe75c, 0xf7f1, 0x0000, 0xe26f, 0xf834, 0xee42, 0x0000,
+ 0xf89d, 0x0000, 0x0000, 0xf84d, 0xe158, 0xf2cd, 0xe5d5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe4a2, 0x0000,
+ 0x0000, 0x0000, 0xf161, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xed37, 0xf162, 0x0000, 0x0000, 0xf641, 0x0000, 0x0000, 0xe29d,
+ 0x0000, 0x0000, 0xe361, 0xe0bf, 0x0000, 0xf1a4, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf1a8, 0xea52, 0xf672, 0xf1dc,
+ 0xe997, 0xeb49, 0x0000, 0x0000, 0x0000, 0xe55e, 0x0000, 0xf545,
+ 0x0000, 0x0000, 0x0000, 0xe4db, 0xe645, 0xf134, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xed76, 0x0000, 0xf3ea, 0x0000, 0x0000, 0x0000, 0xe0ec, 0xe0c0,
+ 0x0000, 0x0000, 0x0000, 0xf194, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_4f[] = {
+ 0x0000, 0xe37a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf7f2, 0xf135, 0xe36f, 0x0000, 0xeeea, 0xe37b, 0xe961,
+ 0xe8e9, 0xf9cc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe8d7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe871, 0x0000, 0xe646, 0x0000,
+ 0xecdf, 0x0000, 0xea53, 0x0000, 0xea54, 0xe031, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf27c, 0x0000, 0x0000, 0xe4a3, 0xf247,
+ 0xf75f, 0x0000, 0x0000, 0x0000, 0x0000, 0xf058, 0xf248, 0xf3ac,
+ 0xf3a5, 0xefce, 0x0000, 0x0000, 0x0000, 0xf7bc, 0x0000, 0x0000,
+ 0x0000, 0xedf9, 0xf17a, 0xe9d6, 0xf1c2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf735, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xedba,
+ 0xe8d8, 0x0000, 0x0000, 0xe032, 0x0000, 0x0000, 0xe3cd, 0x0000,
+ 0x0000, 0x0000, 0xf27d, 0x0000, 0x0000, 0x0000, 0xf17b, 0xea55,
+ 0x0000, 0xece0, 0x0000, 0xe059, 0xf479, 0x0000, 0xe43d, 0x0000,
+ 0xf646, 0x0000, 0xe252, 0xe657, 0x0000, 0xecb4, 0x0000, 0xf3ad,
+ 0x0000, 0xf072, 0x0000, 0x0000, 0x0000, 0x0000, 0xe6c2, 0x0000,
+ 0xf4a7, 0x0000, 0x0000, 0xe1ea, 0x0000, 0xf0ee, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7b2, 0xf9a5,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf665, 0xe5e2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe935,
+ 0x0000, 0x0000, 0xe197, 0xf5b5, 0xed3d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeeeb, 0xf3d5, 0x0000, 0x0000, 0x0000, 0xf34b, 0x0000,
+ 0x0000, 0xefb5, 0x0000, 0xe159, 0xf865, 0x0000, 0x0000, 0xebd4,
+ 0x0000, 0x0000, 0xe6d6, 0x0000, 0x0000, 0xe951, 0x0000, 0xea56,
+ 0xf891, 0xece1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xebf3, 0xe998,
+ 0x0000, 0xe29e, 0x0000, 0xe8c4, 0x0000, 0xf793, 0x0000, 0x0000,
+ 0xe974, 0x0000, 0xedef, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_50[] = {
+ 0x0000, 0x0000, 0xe941, 0x0000, 0x0000, 0x0000, 0xe5d6, 0x0000,
+ 0x0000, 0xf4da, 0x0000, 0xe0c1, 0x0000, 0xe8c3, 0x0000, 0x0000,
+ 0x0000, 0xe7fa, 0xe4ee, 0x0000, 0x0000, 0x0000, 0xf848, 0x0000,
+ 0x0000, 0xf9a6, 0xf0ef, 0x0000, 0xf536, 0x0000, 0xe15a, 0xf4a8,
+ 0x0000, 0xf4db, 0x0000, 0xe8a7, 0xf647, 0x0000, 0xe2e6, 0xf394,
+ 0xe0da, 0x0000, 0xeed2, 0xe6c3, 0xf692, 0xef6e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xeda6, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xede7, 0x0000, 0x0000, 0x0000, 0xe033,
+ 0xe137, 0xf059, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf746,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf835, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf3ae, 0x0000, 0xf2ce, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe0ed, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf640, 0xf2cf, 0xefcf, 0x0000,
+ 0xf6de, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe263, 0x0000, 0x0000, 0x0000, 0x0000, 0xe999, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe8a8, 0x0000, 0x0000,
+ 0x0000, 0xe0f8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xeaa1, 0xe9e1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf5ca, 0xefb6, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xeeec, 0xf27e, 0x0000, 0xf4f0, 0x0000, 0xeabf,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe15b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe351, 0x0000, 0x0000,
+ 0x0000, 0xf562, 0xeb4a, 0x0000, 0x0000, 0x0000, 0x0000, 0xeac0,
+ 0x0000, 0xe270, 0x0000, 0x0000, 0x0000, 0xe962, 0xf9ea, 0x0000,
+ 0x0000, 0x0000, 0xe698, 0x0000, 0x0000, 0x0000, 0xf05a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xef79, 0x0000, 0xecac,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf4d0, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe034, 0x0000, 0xe8f8, 0x0000, 0x0000, 0x0000, 0xea57
+};
+
+static unsigned short johab_from_unicode_51[] = {
+ 0xf0f0, 0xf3d6, 0x0000, 0x0000, 0xede2, 0x0000, 0xe15c, 0x0000,
+ 0x0000, 0xe0fb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf073, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeac1,
+ 0x0000, 0xe67d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xefd0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf249, 0x0000, 0x0000, 0x0000, 0x0000, 0xe5e3,
+ 0x0000, 0x0000, 0xe3d3, 0x0000, 0xedf0, 0x0000, 0x0000, 0x0000,
+ 0xef44, 0xf0c3, 0x0000, 0xf03a, 0xf89e, 0xf5f6, 0xf34c, 0xf9d4,
+ 0xeb4b, 0xe253, 0x0000, 0xe34a, 0xf6ba, 0xe795, 0xf6cd, 0x0000,
+ 0x0000, 0x0000, 0xed3e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe56f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe377, 0x0000, 0x0000, 0xf19f, 0x0000, 0xe43e,
+ 0xf291, 0xe5d7, 0xf074, 0xf732, 0xe1eb, 0xe6bf, 0xf8b1, 0x0000,
+ 0x0000, 0xe1ec, 0x0000, 0x0000, 0x0000, 0xe942, 0xe37c, 0xe29f,
+ 0xf292, 0x0000, 0x0000, 0x0000, 0xe152, 0x0000, 0x0000, 0x0000,
+ 0xe37d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xedf7, 0x0000,
+ 0x0000, 0x0000, 0xf4fc, 0x0000, 0x0000, 0xf232, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe7b3, 0x0000, 0x0000, 0xe796, 0x0000, 0xefb7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe23e, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7a2, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe793, 0x0000, 0xe55f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeda7, 0xe442,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe639, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf532, 0x0000, 0xf3d7, 0x0000,
+ 0x0000, 0xe5d8, 0x0000, 0xf34d, 0xe495, 0xe560, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe494, 0xf0ea, 0xf9eb, 0x0000,
+ 0x0000, 0xe8ed, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf955, 0xe0c2, 0x0000, 0x0000, 0x0000, 0x0000, 0xf9d5, 0x0000,
+ 0xf558, 0xef7a, 0xf5f3, 0x0000, 0x0000, 0xf7de, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_52[] = {
+ 0xe4ef, 0x0000, 0x0000, 0xf163, 0x0000, 0x0000, 0xe9c2, 0xf2b7,
+ 0xeed4, 0x0000, 0xe05a, 0x0000, 0x0000, 0x0000, 0xe7fb, 0x0000,
+ 0x0000, 0xf89f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe63a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf59a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf6f7, 0xe93c, 0x0000, 0x0000,
+ 0x0000, 0xe6d7, 0xeaa2, 0x0000, 0x0000, 0x0000, 0xe24e, 0x0000,
+ 0xe4f0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf334, 0xebec,
+ 0xe2e7, 0xf4cb, 0xf1a9, 0xe04e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf591, 0x0000, 0x0000, 0x0000, 0xf65e,
+ 0x0000, 0x0000, 0xea9d, 0xe34b, 0xe5b7, 0xf293, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf538, 0x0000, 0xe99a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe0a7, 0x0000, 0xe85e, 0x0000, 0x0000,
+ 0x0000, 0xeb76, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf1a5, 0xf294, 0x0000, 0x0000, 0x0000, 0x0000, 0xe99b,
+ 0x0000, 0x0000, 0xf7dc, 0x0000, 0x0000, 0xf4dc, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf794, 0x0000, 0xf59b,
+ 0x0000, 0x0000, 0x0000, 0xf993, 0x0000, 0x0000, 0x0000, 0xe34c,
+ 0xe8f9, 0xe6b1, 0x0000, 0x0000, 0x0000, 0xe0fc, 0x0000, 0x0000,
+ 0x0000, 0xf335, 0xe0fd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe5f4, 0x0000, 0x0000, 0x0000, 0xe1ed,
+ 0xe035, 0x0000, 0x0000, 0xe63b, 0xe352, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf34e, 0xe44d, 0xe134, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf846, 0x0000,
+ 0x0000, 0xe15d, 0x0000, 0xe89c, 0x0000, 0xf65f, 0x0000, 0xefb8,
+ 0x0000, 0xe797, 0x0000, 0x0000, 0x0000, 0xe15e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe492, 0x0000, 0x0000, 0xe561, 0xefed, 0x0000,
+ 0xe07b, 0xe7e2, 0x0000, 0xf9b2, 0x0000, 0xecad, 0xe44e, 0xe7b4,
+ 0x0000, 0x0000, 0xeba7, 0xf263, 0xe353, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf9b3, 0x0000, 0xe5e4, 0x0000, 0x0000,
+ 0xe2e8, 0x0000, 0xf1c3, 0xe342, 0x0000, 0x0000, 0xe2a0, 0xe838
+};
+
+static unsigned short johab_from_unicode_53[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf760, 0x0000, 0x0000,
+ 0xf9d6, 0x0000, 0x0000, 0x0000, 0x0000, 0xf761, 0x0000, 0xf762,
+ 0xe963, 0x0000, 0x0000, 0x0000, 0x0000, 0xe9e2, 0xf8f9, 0xe8c5,
+ 0x0000, 0xecb5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf1dd, 0xe254, 0x0000, 0xe0a1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe9e3, 0x0000, 0x0000, 0x0000, 0x0000, 0xf96d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf7af, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe49d,
+ 0xe2a1, 0xed38, 0x0000, 0xf546, 0xf1a0, 0x0000, 0x0000, 0xecae,
+ 0xeeed, 0xf9c1, 0xe872, 0x0000, 0x0000, 0xe743, 0x0000, 0x0000,
+ 0x0000, 0xe9e4, 0xf391, 0xf693, 0xf892, 0x0000, 0x0000, 0xe3f5,
+ 0x0000, 0x0000, 0xe85f, 0x0000, 0xe964, 0x0000, 0xe936, 0x0000,
+ 0xf2bf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe25f, 0x0000,
+ 0xeb69, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7d6,
+ 0xf164, 0xf05b, 0x0000, 0x0000, 0xe04f, 0xe3eb, 0x0000, 0xe2e9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf3ed, 0x0000, 0xe15f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xed9a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xed7d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe6d8, 0x0000, 0xf9a7, 0x0000, 0x0000, 0x0000, 0x0000, 0xf03b,
+ 0xf642, 0x0000, 0x0000, 0x0000, 0x0000, 0xe2f0, 0xf7bd, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xee96, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe0db, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xeab3, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xefd1, 0xf4a9, 0xe370, 0xefd2, 0x0000, 0xe873, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xec62, 0x0000, 0xf632, 0xebf4,
+ 0x0000, 0x0000, 0x0000, 0xe874, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeed5, 0xf5bf, 0xe2a2, 0xe1af, 0xe2a3, 0x0000, 0x0000,
+ 0x0000, 0xe1b0, 0xf3fe, 0xe333, 0xebaf, 0xf733, 0x0000, 0xe036,
+ 0xf6bb, 0xf47a, 0xea58, 0xefd3, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xea59, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_54[] = {
+ 0x0000, 0x0000, 0x0000, 0xf9de, 0xe050, 0x0000, 0x0000, 0x0000,
+ 0xf7ea, 0xe3ce, 0xf264, 0x0000, 0xe562, 0xe7a3, 0xf9a8, 0xe6d9,
+ 0xf6ce, 0xf84e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe2d6, 0x0000, 0xe6f0, 0x0000, 0xf0e1,
+ 0xf755, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe99c, 0x0000,
+ 0x0000, 0xe9c3, 0x0000, 0xf7df, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xeeef, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf9e5, 0xf633, 0x0000, 0xe7fc, 0xf9a9, 0x0000, 0xeeee, 0x0000,
+ 0x0000, 0x0000, 0xe5e5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf2d0, 0x0000, 0xe1b1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf6a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf3b2, 0x0000, 0xf3b1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe1b2, 0x0000, 0xe83b, 0x0000, 0xe037, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xece2, 0xf8bc, 0xe7a4, 0x0000, 0x0000,
+ 0xf24a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf763, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf8fa, 0x0000, 0xe2a4, 0x0000,
+ 0xe99d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf673, 0x0000, 0x0000, 0x0000,
+ 0xf1aa, 0x0000, 0x0000, 0xf431, 0xe271, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf836, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf7e0, 0x0000, 0x0000, 0x0000, 0x0000, 0xee7c, 0x0000, 0x0000,
+ 0xed7e, 0xf7a1, 0x0000, 0x0000, 0xf8ef, 0x0000, 0x0000, 0x0000,
+ 0xf7eb, 0xf233, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf03c, 0x0000, 0x0000, 0x0000, 0xe038, 0x0000, 0x0000,
+ 0xf59c, 0x0000, 0x0000, 0x0000, 0x0000, 0xe1d6, 0xf998, 0x0000,
+ 0x0000, 0x0000, 0xf559, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf764, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_55[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf736, 0x0000, 0xea5a, 0xf456,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe6da, 0x0000,
+ 0xe4d0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe755, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf076,
+ 0x0000, 0xf4dd, 0x0000, 0x0000, 0x0000, 0xed6a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf674, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf694, 0x0000, 0xeac2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7fd,
+ 0x0000, 0x0000, 0x0000, 0xe198, 0x0000, 0x0000, 0xe4ba, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xed3f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf7e1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf336, 0x0000, 0x0000, 0x0000,
+ 0xe0d3, 0x0000, 0x0000, 0x0000, 0xeb4c, 0x0000, 0xf55a, 0xe3d4,
+ 0x0000, 0xf9aa, 0xf7e2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf547, 0xf9c2, 0xf940, 0x0000, 0xf9ec, 0xe072, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf9bd,
+ 0x0000, 0xf077, 0xeac3, 0xe3d2, 0xe272, 0x0000, 0xe4a4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf9ab, 0x0000, 0xeae0,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf457, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xeef0, 0x0000, 0xe37e, 0x0000, 0x0000, 0xf4aa,
+ 0x0000, 0x0000, 0x0000, 0xea5b, 0xf648, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xebf5, 0xf3b3, 0x0000
+};
+
+static unsigned short johab_from_unicode_56[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf6a3, 0x0000,
+ 0x0000, 0xe039, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe2a5, 0x0000, 0x0000, 0xeac4,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xebb0,
+ 0x0000, 0x0000, 0xf34f, 0x0000, 0xf634, 0x0000, 0xecb6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf856, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe391, 0x0000, 0x0000, 0xf9ed, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe9c4, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf999, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xee4f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xea3d, 0x0000, 0xf84f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xedf1, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf1c4, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe435, 0x0000, 0x0000, 0xf9ee, 0x0000, 0x0000,
+ 0x0000, 0xf5b6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xebf6, 0xea5c, 0x0000, 0x0000, 0xf96e, 0x0000,
+ 0xf167, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe1dd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe647, 0xe1b3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_57[] = {
+ 0x0000, 0x0000, 0x0000, 0xf765, 0xedd8, 0x0000, 0x0000, 0x0000,
+ 0xe2ea, 0x0000, 0x0000, 0xe2d0, 0x0000, 0xf05c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf03e, 0xf03d, 0x0000, 0x0000, 0xe4f1, 0x0000,
+ 0xe4a5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf6cf,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf234, 0x0000, 0x0000, 0x0000, 0x0000, 0xe334, 0x0000, 0x0000,
+ 0xf432, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe392, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf433, 0x0000, 0xf6f8, 0x0000, 0x0000, 0x0000, 0x0000, 0xe343,
+ 0x0000, 0x0000, 0xe8a9, 0x0000, 0x0000, 0xe4bb, 0xe07c, 0x0000,
+ 0xf3a6, 0xe0d5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf6e7, 0x0000, 0x0000, 0xe1de, 0x0000, 0xf6a4, 0x0000,
+ 0x0000, 0x0000, 0xf750, 0x0000, 0x0000, 0x0000, 0xe4dd, 0x0000,
+ 0xe160, 0x0000, 0x0000, 0x0000, 0x0000, 0xe2a6, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf695, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xebf7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe4dc, 0x0000, 0x0000, 0xf8a0, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf837, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf0d9, 0x0000, 0xe2a7, 0xf03f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xed91, 0x0000, 0x0000, 0x0000, 0xefb9,
+ 0xf3d8, 0x0000, 0x0000, 0xe768, 0x0000, 0x0000, 0xeb94, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xee44,
+ 0xe99e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf4f1, 0x0000, 0x0000, 0x0000, 0xecd0, 0x0000, 0x0000, 0xf49d,
+ 0x0000, 0xe8c6, 0xe393, 0x0000, 0xe394, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_58[] = {
+ 0xe2dc, 0x0000, 0xe4d1, 0x0000, 0x0000, 0xe141, 0xf6d8, 0x0000,
+ 0xe0a8, 0xf0bc, 0xed4e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf56c, 0x0000,
+ 0x0000, 0xe952, 0x0000, 0x0000, 0xf337, 0x0000, 0x0000, 0xee50,
+ 0x0000, 0x0000, 0xe07d, 0x0000, 0x0000, 0x0000, 0x0000, 0xef7b,
+ 0xede8, 0xe953, 0x0000, 0x0000, 0xf1de, 0xe4f2, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe199, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe264, 0xeeab, 0x0000, 0x0000, 0x0000, 0xe0c3,
+ 0x0000, 0xebb1, 0x0000, 0x0000, 0xf6b2, 0x0000, 0x0000, 0xe4f3,
+ 0xe4d2, 0x0000, 0xf5c0, 0x0000, 0x0000, 0x0000, 0xeadd, 0x0000,
+ 0x0000, 0xf295, 0xeef1, 0x0000, 0xf9b4, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf458, 0x0000, 0x0000,
+ 0x0000, 0xf4d2, 0x0000, 0x0000, 0xf296, 0x0000, 0xec63, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe161, 0x0000, 0xeaea, 0x0000, 0x0000,
+ 0x0000, 0xefba, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe7d7, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf5cd, 0x0000, 0xf3f2, 0xf857,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe7f8, 0xe552, 0x0000, 0x0000, 0x0000, 0x0000, 0xf675, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe9c5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xeef2, 0xf1df, 0x0000, 0x0000, 0xe05b, 0x0000,
+ 0x0000, 0xe8fa, 0x0000, 0x0000, 0x0000, 0xef45, 0x0000, 0xe4a6,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf9b5, 0x0000,
+ 0x0000, 0xf7c9, 0x0000, 0xed72, 0x0000, 0xf8bd, 0x0000, 0x0000,
+ 0xe474, 0xe255, 0x0000, 0x0000, 0x0000, 0x0000, 0xe265, 0xe466,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xedbd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xea5d, 0xf195, 0x0000, 0x0000, 0xf1e0,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf17c, 0xf8be, 0xeaeb, 0x0000, 0xebf8, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_59[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf7be,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe395, 0xeb3a, 0xef72, 0x0000,
+ 0x0000, 0xec64, 0xe49f, 0x0000, 0xeda8, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe7d3, 0x0000, 0x0000, 0x0000, 0x0000, 0xe4de,
+ 0x0000, 0xf548, 0xf6bc, 0xe99f, 0x0000, 0xef7c, 0xed77, 0x0000,
+ 0x0000, 0xecf7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf138,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf893, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xedf2, 0x0000, 0x0000, 0xe396,
+ 0xe3d5, 0xe975, 0x0000, 0x0000, 0x0000, 0x0000, 0xe335, 0xf3b4,
+ 0xf941, 0xe19a, 0x0000, 0x0000, 0xe9c6, 0xf861, 0x0000, 0xf6df,
+ 0x0000, 0x0000, 0xf838, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf297, 0x0000, 0xea5e, 0x0000, 0x0000, 0x0000, 0x0000, 0xeef3,
+ 0x0000, 0x0000, 0xf6ac, 0xf0c4, 0xf1e1, 0xeb3b, 0xe9c7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe443, 0xe44f, 0x0000, 0x0000, 0x0000,
+ 0xe05c, 0x0000, 0x0000, 0x0000, 0x0000, 0xf8bf, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xedfd, 0xe9e5, 0xe75d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf196, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe397, 0x0000, 0x0000, 0xef7d, 0xe362,
+ 0x0000, 0xe7d8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf676, 0x0000, 0x0000,
+ 0xe8aa, 0x0000, 0x0000, 0x0000, 0xf6e0, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe769, 0x0000, 0xf533, 0x0000, 0x0000, 0xf56d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf2d1, 0x0000, 0x0000, 0xe7b5, 0x0000,
+ 0x0000, 0xf1ab, 0x0000, 0xecb7, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf24b, 0xe1b4, 0x0000, 0xeb95, 0xf05d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf197, 0xef7e, 0x0000, 0xe0a9, 0xf3af, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe05d, 0x0000,
+ 0xf139, 0x0000, 0xf47b, 0x0000, 0xf9ef, 0x0000, 0xf7f3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xee51, 0x0000, 0x0000, 0xf168, 0x0000, 0x0000, 0x0000, 0xf1ac
+};
+
+static unsigned short johab_from_unicode_5a[] = {
+ 0x0000, 0xf05e, 0x0000, 0xef6f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xea5f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe436, 0x0000, 0x0000, 0xeef4, 0xe3d6, 0x0000, 0x0000, 0xee52,
+ 0xece3, 0x0000, 0x0000, 0x0000, 0x0000, 0xed40, 0x0000, 0x0000,
+ 0x0000, 0xe744, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf635, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf4de, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe6a5, 0x0000, 0x0000, 0x0000, 0x0000, 0xf6e8, 0x0000,
+ 0x0000, 0xef56, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf8e6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe9e6, 0x0000, 0x0000, 0x0000, 0xe9a0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe76a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe83c, 0xf040, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xecb8, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe03a, 0xebf9, 0x0000, 0xf041, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf47c, 0x0000, 0x0000, 0xf87e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf265, 0x0000, 0x0000, 0x0000, 0x0000, 0xf7f4, 0x0000,
+ 0x0000, 0xe47c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_5b[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf8fb, 0x0000, 0x0000,
+ 0x0000, 0xf9f0, 0x0000, 0xeb4d, 0xe273, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf756, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xea3e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xeac5, 0x0000, 0x0000, 0xedbe, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf1ad, 0xf87a, 0x0000, 0x0000, 0xe1ee, 0xf1a6, 0x0000, 0xf1ae,
+ 0xf37d, 0x0000, 0xe9a1, 0x0000, 0xf1af, 0xf99a, 0x0000, 0xe77b,
+ 0x0000, 0x0000, 0x0000, 0xe19b, 0xe1b5, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf839, 0x0000, 0xebdd, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xec65, 0xf1cf, 0x0000, 0x0000, 0x0000, 0xe9a2, 0x0000, 0x0000,
+ 0xf7ca, 0x0000, 0xf078, 0x0000, 0xeded, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe4eb, 0x0000, 0xefd4,
+ 0xebfa, 0xed5c, 0x0000, 0xebe4, 0xef57, 0x0000, 0x0000, 0xe26b,
+ 0x0000, 0x0000, 0x0000, 0xe965, 0x0000, 0xf6b5, 0xf995, 0xf395,
+ 0xe23f, 0xf3b5, 0xf2d2, 0xef58, 0xf0f1, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe0d4, 0xeb4e, 0xecf8, 0xf079, 0xf942, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xeb96, 0x0000, 0xe2e0, 0x0000,
+ 0xf235, 0x0000, 0x0000, 0xf83a, 0xee53, 0xebb2, 0xe03b, 0x0000,
+ 0xece4, 0xefbb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xec66,
+ 0xf4f2, 0x0000, 0xf266, 0xf042, 0xe398, 0xf169, 0xe85b, 0xe2a8,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe9a3, 0x0000, 0x0000, 0x0000,
+ 0xe76b, 0x0000, 0xf7ce, 0xefd5, 0xecd1, 0x0000, 0x0000, 0xe44c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe73c, 0xf4cc,
+ 0x0000, 0xe1fb, 0xf666, 0x0000, 0xeef5, 0xef91, 0xecf9, 0xe44b,
+ 0xf4f3, 0xecfb, 0x0000, 0xea60, 0xe240, 0x0000, 0xe699, 0xf3d9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5c1, 0xe954, 0x0000,
+ 0xf5bb, 0x0000, 0xea61, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_5c[] = {
+ 0x0000, 0xe976, 0x0000, 0x0000, 0xea62, 0x0000, 0x0000, 0xf1e2,
+ 0xf298, 0xf05f, 0xf37e, 0xecfc, 0x0000, 0xe4df, 0xe4f4, 0xebb3,
+ 0x0000, 0xebb4, 0x0000, 0x0000, 0x0000, 0x0000, 0xf563, 0x0000,
+ 0x0000, 0xeac6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xefd6, 0x0000, 0x0000, 0x0000,
+ 0xe8ab, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf636, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xecb9, 0xf0c5, 0xf539, 0xe1b6, 0xe49b, 0x0000, 0xe83d, 0xe473,
+ 0xe2d1, 0x0000, 0x0000, 0x0000, 0x0000, 0xe0dc, 0xe19c, 0x0000,
+ 0xe2dd, 0x0000, 0x0000, 0xef39, 0x0000, 0xecbb, 0xecba, 0x0000,
+ 0x0000, 0xeb6a, 0x0000, 0x0000, 0x0000, 0xf299, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe943, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe4f5, 0x0000, 0xe475, 0x0000, 0xf645, 0xe6db, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xebd5, 0x0000, 0x0000, 0xe57a,
+ 0x0000, 0xeaa3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf9df, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe399, 0xf1d4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe0aa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xed6b, 0x0000, 0xebfb, 0xe0a2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe4e0, 0x0000, 0xed4f, 0x0000, 0xf8c0, 0x0000, 0xe84e,
+ 0xed5d, 0x0000, 0xe649, 0x0000, 0x0000, 0x0000, 0xf2c0, 0x0000,
+ 0xebfc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf649, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xeac7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xed41, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe977,
+ 0xe978, 0x0000, 0x0000, 0x0000, 0xf866, 0x0000, 0xe4f6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf3da, 0x0000, 0xf894, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_5d[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xec9f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe5cf, 0xe39a, 0x0000,
+ 0x0000, 0xe1df, 0x0000, 0x0000, 0xf5cb, 0x0000, 0xed92, 0xe0ab,
+ 0x0000, 0xe6c4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeca0,
+ 0x0000, 0xe9da, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe83e, 0xe07e, 0x0000, 0x0000, 0x0000,
+ 0xe3f6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeca1, 0x0000, 0x0000, 0xef73, 0x0000, 0x0000, 0xf4ab,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe2a9,
+ 0x0000, 0x0000, 0x0000, 0xe4f7, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe593, 0x0000, 0x0000,
+ 0xe274, 0x0000, 0xef94, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xedf5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xeeae, 0x0000, 0xe64a, 0x0000, 0xeaec, 0xed50, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xef74, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe745, 0x0000, 0x0000, 0x0000, 0xed6c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf549, 0xf3b6, 0x0000,
+ 0x0000, 0xec6e, 0xebb5, 0x0000, 0x0000, 0xe1ef, 0xf3a7, 0xe275,
+ 0xe0dd, 0x0000, 0x0000, 0xe7e3, 0x0000, 0x0000, 0xf4ac, 0x0000,
+ 0x0000, 0xe39b, 0xf13b, 0xea63, 0xf6e9, 0x0000, 0x0000, 0xf7f5,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xebde, 0xe0ee, 0x0000
+};
+
+static unsigned short johab_from_unicode_5e[] = {
+ 0x0000, 0x0000, 0xecbc, 0xf766, 0x0000, 0x0000, 0xe8ee, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf9f1, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf6b6, 0x0000, 0x0000, 0x0000, 0x0000, 0xf56e, 0x0000,
+ 0x0000, 0xf47d, 0x0000, 0xe8d9, 0x0000, 0xf338, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xebfd, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xea64, 0x0000, 0xeb3c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf1e3, 0x0000, 0x0000, 0xe4e1, 0x0000,
+ 0xeac8, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7b6, 0x0000, 0xf9ac,
+ 0xf2d3, 0x0000, 0x0000, 0x0000, 0xed51, 0xf77b, 0x0000, 0xe8ac,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf956, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe73d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf64a,
+ 0x0000, 0xe8df, 0xe4d3, 0xf757, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe05e, 0xf751, 0xe444, 0x0000, 0x0000, 0xe944,
+ 0xf849, 0xe05f, 0x0000, 0xf943, 0xf07a, 0xf07b, 0xe39c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf1e4, 0x0000, 0x0000, 0xe9e7,
+ 0x0000, 0x0000, 0xeac9, 0x0000, 0x0000, 0x0000, 0x0000, 0xeaed,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf24c, 0x0000, 0xf2c1,
+ 0x0000, 0x0000, 0xe162, 0x0000, 0xe9a4, 0x0000, 0x0000, 0x0000,
+ 0xeaca, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe4f8, 0xf3a8,
+ 0x0000, 0x0000, 0x0000, 0xe1b7, 0x0000, 0xf2d4, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xed6d, 0xeaee, 0xe0ac,
+ 0xefbc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf07c, 0x0000,
+ 0x0000, 0x0000, 0xeacb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf7bf, 0xe63f, 0xe437, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe2aa, 0x0000, 0x0000, 0xe239, 0x0000, 0x0000, 0xe69a, 0x0000,
+ 0x0000, 0x0000, 0xf3b7, 0xf29a, 0x0000, 0x0000, 0x0000, 0xe7d9,
+ 0xf4df, 0x0000, 0xf758, 0xe256, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe5e6, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf576, 0x0000, 0x0000, 0xee55, 0xf2d5,
+ 0x0000, 0x0000, 0xe0ef, 0xf96f, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_5f[] = {
+ 0x0000, 0xe937, 0x0000, 0x0000, 0xe467, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf759, 0x0000, 0x0000, 0x0000, 0x0000, 0xecd2,
+ 0x0000, 0xecbd, 0x0000, 0xe2e1, 0xf350, 0xf16a, 0x0000, 0xe9d7,
+ 0xf8f0, 0x0000, 0x0000, 0xf13c, 0x0000, 0x0000, 0x0000, 0xf339,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf867, 0xf8c1,
+ 0x0000, 0xe450, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xedb0, 0x0000, 0x0000, 0x0000, 0xf1e5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe0ad, 0x0000, 0xf7b0, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf6a5, 0x0000, 0xe0ae, 0x0000, 0xe83f, 0x0000, 0xe746, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe4a7, 0xf8b2,
+ 0x0000, 0xf9c4, 0x0000, 0xf13d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf8a1, 0x0000, 0x0000, 0x0000, 0xede9, 0xefee,
+ 0x0000, 0xf4f4, 0xf795, 0xf351, 0xea3f, 0xf740, 0x0000, 0x0000,
+ 0xf4e0, 0xeeaf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe8ad,
+ 0x0000, 0xee45, 0x0000, 0x0000, 0xf7a8, 0x0000, 0x0000, 0xe9d8,
+ 0xef69, 0xf2d6, 0x0000, 0x0000, 0x0000, 0xe4e2, 0x0000, 0xec6f,
+ 0x0000, 0x0000, 0xf970, 0xe6c8, 0xf9ad, 0x0000, 0x0000, 0x0000,
+ 0xeaef, 0xe163, 0xe4f9, 0x0000, 0x0000, 0x0000, 0x0000, 0xe592,
+ 0xe8c7, 0xea65, 0x0000, 0x0000, 0x0000, 0x0000, 0xf396, 0x0000,
+ 0xe5d0, 0xedd9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf957, 0xe966, 0xec70, 0x0000, 0x0000, 0x0000, 0xe840, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf4a3, 0x0000, 0xe4ec,
+ 0x0000, 0xf55b, 0x0000, 0x0000, 0x0000, 0xf9c5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xecfd, 0x0000, 0xf7b1, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe39d, 0xf16b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5bc, 0xf434,
+ 0xe75e, 0xe75f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf5f7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf671, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe447, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf8ec, 0x0000, 0xe9c8
+};
+
+static unsigned short johab_from_unicode_60[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xed78,
+ 0x0000, 0x0000, 0xe451, 0x0000, 0x0000, 0x0000, 0xf767, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe64b, 0xea66, 0x0000, 0x0000,
+ 0xf6bd, 0xf13e, 0x0000, 0x0000, 0x0000, 0xe371, 0x0000, 0xeb97,
+ 0xf043, 0x0000, 0xe266, 0x0000, 0x0000, 0x0000, 0x0000, 0xe135,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf198, 0xec71, 0xecbe, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf958, 0x0000, 0x0000,
+ 0xe1f0, 0x0000, 0xf7f6, 0x0000, 0x0000, 0xeaf0, 0x0000, 0x0000,
+ 0x0000, 0xedbf, 0x0000, 0x0000, 0x0000, 0xe24f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf971, 0xf1b0, 0xf9d1, 0xf64b, 0x0000, 0x0000,
+ 0xf7cf, 0xf0da, 0xe051, 0x0000, 0xe448, 0xe1f1, 0x0000, 0xecd3,
+ 0xf9e6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xee7d, 0x0000, 0x0000,
+ 0x0000, 0xecfa, 0x0000, 0x0000, 0xf33a, 0xf7d0, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf972, 0x0000, 0xf737, 0x0000,
+ 0x0000, 0x0000, 0xebe5, 0xf29b, 0x0000, 0x0000, 0x0000, 0xeef6,
+ 0xf07d, 0x0000, 0x0000, 0xf944, 0xf5c2, 0x0000, 0x0000, 0xe6dc,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf397, 0x0000, 0xe9e8, 0xe4ed, 0xf5fc, 0x0000, 0xe84f, 0x0000,
+ 0xe19d, 0x0000, 0x0000, 0x0000, 0xe4fa, 0xf534, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf2d7, 0x0000, 0xe553,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf8e3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf8ed, 0x0000, 0xeb3d, 0x0000, 0x0000, 0xf07e,
+ 0xf8b3, 0xed52, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf677, 0xe46d, 0x0000, 0xeacc, 0x0000, 0x0000, 0xf959, 0x0000,
+ 0x0000, 0xeda9, 0xeb98, 0xf643, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_61[] = {
+ 0x0000, 0xebfe, 0x0000, 0x0000, 0x0000, 0x0000, 0xe0f0, 0x0000,
+ 0xf091, 0xf092, 0x0000, 0x0000, 0x0000, 0xe850, 0xf744, 0xf0f2,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xed53, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xefd7, 0xed93, 0x0000, 0x0000, 0x0000, 0xe091,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe267,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf95a, 0x0000, 0x0000, 0x0000, 0xf4e1, 0x0000, 0x0000, 0xe0c4,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xece5, 0x0000, 0xe0c5, 0xf044,
+ 0x0000, 0x0000, 0xefbd, 0x0000, 0xe6c9, 0x0000, 0x0000, 0xf0db,
+ 0xf1b1, 0x0000, 0xe153, 0xf6be, 0xf95b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf796, 0x0000, 0xe7b7, 0x0000, 0x0000,
+ 0xf4d3, 0xf4d4, 0x0000, 0x0000, 0x0000, 0xf6e4, 0x0000, 0xf6d1,
+ 0x0000, 0x0000, 0xe747, 0xe241, 0xe052, 0x0000, 0x0000, 0xf8b4,
+ 0xe0c6, 0x0000, 0x0000, 0xf398, 0x0000, 0x0000, 0xe5e7, 0x0000,
+ 0xf060, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe164, 0xe0af,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf53a, 0xefaf, 0x0000,
+ 0x0000, 0xf5c3, 0xefd8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe9e9, 0x0000, 0x0000, 0x0000, 0xf3f3, 0x0000,
+ 0xe5fb, 0xea4b, 0x0000, 0x0000, 0xf59d, 0x0000, 0x0000, 0x0000,
+ 0xf9f3, 0xf9f2, 0xf6a6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe9c9, 0x0000, 0x0000, 0xe563,
+ 0x0000, 0xe138, 0x0000, 0xe851, 0xe165, 0x0000, 0xe7e4, 0x0000,
+ 0x0000, 0x0000, 0xf85a, 0x0000, 0x0000, 0x0000, 0xede3, 0x0000,
+ 0x0000, 0x0000, 0xe4bc, 0x0000, 0x0000, 0x0000, 0xe092, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe354, 0x0000, 0x0000, 0x0000, 0xe060,
+ 0xf83b, 0xf0eb, 0xeef8, 0xe7e5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3d7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf4a4, 0x0000, 0x0000, 0x0000, 0xe3d8, 0xf973,
+ 0xf868, 0x0000, 0xf4d5, 0x0000, 0xe2ab, 0x0000, 0x0000, 0xf0f3
+};
+
+static unsigned short johab_from_unicode_62[] = {
+ 0xe5fc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe4d4,
+ 0xe1fc, 0x0000, 0xe7e6, 0x0000, 0xec9b, 0xec31, 0xf0d4, 0x0000,
+ 0xeb99, 0xed42, 0xe19e, 0x0000, 0x0000, 0x0000, 0xf8e4, 0x0000,
+ 0x0000, 0x0000, 0xf53b, 0x0000, 0x0000, 0x0000, 0x0000, 0xe34d,
+ 0x0000, 0xe093, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf2b8, 0x0000, 0x0000, 0x0000, 0xe6c0, 0x0000,
+ 0xf29c, 0xf9f4, 0x0000, 0x0000, 0xe4e3, 0x0000, 0xf8c2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe5e8, 0xe8ae,
+ 0xebb6, 0xf747, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeb4f,
+ 0xf8c3, 0xe9ea, 0x0000, 0xec32, 0x0000, 0xf236, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf678, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf697, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe9ca, 0x0000,
+ 0x0000, 0xe372, 0x0000, 0x0000, 0x0000, 0x0000, 0xe9a6, 0x0000,
+ 0x0000, 0xe9eb, 0x0000, 0x0000, 0xed9b, 0x0000, 0x0000, 0xecaf,
+ 0xe39e, 0x0000, 0x0000, 0x0000, 0xf59e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe14c, 0xf6ea, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xede4, 0xeaf1, 0x0000, 0x0000, 0xf6e1, 0x0000, 0xf7f7,
+ 0xf2b9, 0x0000, 0x0000, 0xf768, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf7a9, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf769, 0x0000, 0x0000, 0x0000, 0xf24d, 0x0000, 0x0000,
+ 0x0000, 0xe756, 0x0000, 0x0000, 0xed73, 0xf5ce, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe9d9, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7e7,
+ 0xe449, 0xe3fe, 0x0000, 0x0000, 0xe875, 0xe860, 0x0000, 0xe3d9,
+ 0xe268, 0x0000, 0xe0de, 0xf53c, 0xe89d, 0x0000, 0xf679, 0xef95,
+ 0xe2ac, 0xf392, 0x0000, 0xf59f, 0xe8c8, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe250, 0xecd4, 0xe3cf, 0xf3f5,
+ 0x0000, 0xe1f2, 0x0000, 0xe2eb, 0x0000, 0x0000, 0x0000, 0xe1b8,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeca6, 0xe3da
+};
+
+static unsigned short johab_from_unicode_63[] = {
+ 0x0000, 0xf435, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf436,
+ 0x0000, 0xed5e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe4fb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf3a9, 0x0000, 0x0000, 0x0000, 0xf459,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf2d8, 0xee59, 0x0000, 0xe748, 0xf895, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf4b5, 0x0000, 0x0000, 0xf734, 0x0000, 0x0000, 0xe3f3,
+ 0xee58, 0x0000, 0x0000, 0x0000, 0x0000, 0xf76a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe979,
+ 0xea67, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe0df, 0x0000,
+ 0x0000, 0x0000, 0xe2ec, 0x0000, 0x0000, 0x0000, 0x0000, 0xf56f,
+ 0x0000, 0x0000, 0xe3f4, 0xe44a, 0x0000, 0x0000, 0x0000, 0xeaf2,
+ 0x0000, 0x0000, 0x0000, 0xebb7, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xec33, 0xe4fc, 0x0000, 0x0000, 0xf1e6, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe8c9, 0x0000, 0x0000, 0x0000, 0xed9c, 0x0000,
+ 0xe2de, 0x0000, 0x0000, 0xe260, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe5d3, 0xf4f5, 0xf6ae, 0x0000, 0x0000, 0xf2c8, 0x0000, 0xe1f3,
+ 0xf5cf, 0xedf3, 0xf352, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe061, 0x0000, 0x0000, 0x0000, 0xf093, 0x0000, 0xe336, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7da,
+ 0xf33b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf0e7, 0x0000,
+ 0x0000, 0x0000, 0xedc0, 0xf945, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xed54, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe139, 0xf9c6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf045, 0x0000, 0xedaa, 0xeaba,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_64[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xebdf, 0x0000, 0xe861,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xebb8, 0x0000, 0xef96, 0xe4fd,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xec34, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf45a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe876, 0xf6b3, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf9cd, 0x0000, 0x0000, 0x0000, 0xf4b6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf267, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf5c4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe734, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf437,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe7b8, 0xe7b9, 0xf2c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe65e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf6cb, 0xeaae, 0xef97, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe445, 0x0000, 0x0000, 0x0000, 0xe4d5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf55c, 0xe89e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe7e8, 0x0000, 0xf6eb, 0xf5c9, 0x0000,
+ 0xf4bc, 0x0000, 0xe862, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe4b5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xef46, 0x0000, 0x0000, 0xe452, 0xf54a, 0x0000, 0xf6c9,
+ 0x0000, 0x0000, 0xe13a, 0x0000, 0x0000, 0xf353, 0xe166, 0x0000,
+ 0x0000, 0x0000, 0xe363, 0x0000, 0xe4bd, 0x0000, 0x0000, 0x0000,
+ 0xe8fb, 0x0000, 0xe0e0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe4e4, 0xf699, 0x0000, 0x0000, 0xe5ba, 0xf4cd, 0xe0e1,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf0f4, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf53d, 0x0000, 0xf93a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf6ec, 0x0000, 0x0000, 0x0000, 0xef98, 0x0000
+};
+
+static unsigned short johab_from_unicode_65[] = {
+ 0xe877, 0x0000, 0x0000, 0x0000, 0xf6cc, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xedc1, 0x0000, 0x0000, 0x0000, 0x0000, 0xeb7e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe5fd, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe276, 0xf93b, 0xe5bb, 0x0000, 0x0000, 0xf438,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xec35, 0xe1b9,
+ 0xf094, 0xe0c7, 0x0000, 0xe1f4, 0x0000, 0x0000, 0xe8af, 0xf2d9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe1ba, 0x0000, 0x0000,
+ 0xf99b, 0x0000, 0x0000, 0x0000, 0x0000, 0xeaf3, 0xe277, 0xe852,
+ 0x0000, 0xe2ad, 0x0000, 0x0000, 0x0000, 0x0000, 0xeef9, 0xf738,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf4e2, 0x0000,
+ 0x0000, 0x0000, 0xe094, 0xeaa4, 0x0000, 0x0000, 0xe554, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe167, 0xedc2, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe1bb, 0x0000, 0xf2da, 0xf268, 0x0000, 0xe9a7,
+ 0xea9e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeb50, 0x0000,
+ 0x0000, 0x0000, 0xe640, 0xf75a, 0x0000, 0xf99c, 0x0000, 0xe7fe,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xea40, 0x0000, 0x0000, 0x0000,
+ 0xe9ec, 0xe878, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe570,
+ 0x0000, 0xe69b, 0x0000, 0xe1d7, 0xea68, 0x0000, 0x0000, 0xf49a,
+ 0x0000, 0xed66, 0x0000, 0x0000, 0xe355, 0xf53e, 0x0000, 0xe9a8,
+ 0x0000, 0x0000, 0x0000, 0xf1c5, 0xf4d6, 0x0000, 0x0000, 0xea69,
+ 0xece6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe4a8,
+ 0x0000, 0xe8b0, 0x0000, 0x0000, 0xedda, 0xecbf, 0x0000, 0x0000,
+ 0x0000, 0xe8b1, 0x0000, 0x0000, 0x0000, 0xe5e9, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xeb51, 0xf2db, 0x0000, 0x0000, 0xf379,
+ 0x0000, 0x0000, 0xe6b2, 0x0000, 0x0000, 0x0000, 0x0000, 0xe39f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe7e9, 0x0000, 0x0000, 0xe3a0, 0x0000, 0xf17d, 0xe4a9, 0x0000,
+ 0xf439, 0xf354, 0x0000, 0x0000, 0xec72, 0xefef, 0x0000, 0x0000,
+ 0x0000, 0xf7d1, 0x0000, 0x0000, 0xefd9, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xef6a, 0xe853, 0xe854, 0xe555, 0x0000, 0xeefa
+};
+
+static unsigned short johab_from_unicode_66[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe1e0, 0xecb0,
+ 0x0000, 0xe8b2, 0xf8c4, 0x0000, 0xf4e3, 0x0000, 0xe7a5, 0xf8e7,
+ 0xe9cb, 0xe364, 0x0000, 0xee46, 0xeb3e, 0xf9da, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe945, 0xeb9a,
+ 0xeeb1, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5f0, 0x0000, 0xe76c,
+ 0xf1c6, 0x0000, 0x0000, 0x0000, 0x0000, 0xebb9, 0x0000, 0xecc0,
+ 0xf7c0, 0xeff0, 0x0000, 0x0000, 0xe7db, 0x0000, 0xf4e4, 0x0000,
+ 0x0000, 0x0000, 0xe946, 0xed79, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf355, 0xecc1, 0xf95c, 0xf95d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf45b, 0x0000, 0xf45c, 0x0000, 0x0000, 0x0000, 0xed5f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf3db, 0x0000, 0xf869, 0x0000, 0xf3b8, 0xf9f5, 0xeb9b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xeefb, 0xf947, 0xf974, 0xf8c5,
+ 0xece7, 0xe749, 0x0000, 0xf69a, 0x0000, 0x0000, 0xe955, 0xe168,
+ 0x0000, 0x0000, 0x0000, 0xeb3f, 0xf577, 0x0000, 0xf2dc, 0xe2fc,
+ 0xf2dd, 0x0000, 0xf43a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf9be, 0x0000, 0x0000, 0xe03c,
+ 0xeff7, 0xf9c7, 0x0000, 0x0000, 0x0000, 0x0000, 0xeeb2, 0x0000,
+ 0xf061, 0xeaf4, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3ec, 0xed6e,
+ 0xedc3, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7a6, 0x0000, 0x0000,
+ 0xe1bc, 0x0000, 0xf4e5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf1d5, 0x0000, 0x0000, 0xe7ba, 0x0000,
+ 0x0000, 0x0000, 0xf1e7, 0xf8b5, 0xf76b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeb77, 0x0000, 0xe169, 0x0000, 0x0000, 0xe556, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xeea5, 0x0000, 0xe5f5, 0xe4be,
+ 0x0000, 0xf99d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xed94, 0x0000,
+ 0x0000, 0xeaf5, 0x0000, 0x0000, 0xef9a, 0xf77d, 0x0000, 0x0000,
+ 0xe257, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf9f6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xef68, 0x0000, 0xe1d8, 0xeed6, 0xe0d6, 0x0000, 0x0000, 0xe073,
+ 0xeaf6, 0xf357, 0xf356, 0x0000, 0xe74a, 0x0000, 0xf3f4, 0xf592
+};
+
+static unsigned short johab_from_unicode_67[] = {
+ 0xf5cc, 0x0000, 0x0000, 0xf975, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf055, 0xf095, 0x0000, 0xe9db, 0x0000, 0xe967, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xea9f, 0xf49b, 0x0000, 0xe438,
+ 0x0000, 0x0000, 0x0000, 0xe760, 0x0000, 0xf358, 0xe3a1, 0xe3a2,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7d4, 0xe678,
+ 0xe7ca, 0x0000, 0xe841, 0xe757, 0xe972, 0xf4ce, 0xf5f4, 0x0000,
+ 0x0000, 0xf3b9, 0x0000, 0x0000, 0xe863, 0x0000, 0xf67a, 0x0000,
+ 0x0000, 0x0000, 0xe2f5, 0x0000, 0x0000, 0xf9ae, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe062, 0x0000,
+ 0x0000, 0xeab4, 0x0000, 0x0000, 0x0000, 0x0000, 0xe6dd, 0xf84a,
+ 0xf237, 0xf5bd, 0x0000, 0xf797, 0x0000, 0x0000, 0xf1e8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe571, 0x0000, 0xe3a3, 0xebd6,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf7f8, 0x0000, 0xe8ca,
+ 0xe0f9, 0xe564, 0x0000, 0xe7dc, 0x0000, 0xf24e, 0x0000, 0xf6ed,
+ 0x0000, 0x0000, 0x0000, 0xe47e, 0x0000, 0x0000, 0xebe6, 0xf6f9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe9ed,
+ 0x0000, 0xef6b, 0x0000, 0xe8b3, 0x0000, 0x0000, 0x0000, 0xe3f7,
+ 0xeb40, 0x0000, 0x0000, 0xe572, 0x0000, 0xf667, 0x0000, 0xe6f9,
+ 0x0000, 0x0000, 0xe76d, 0x0000, 0xe1fd, 0xf43b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe1bd,
+ 0xf752, 0x0000, 0x0000, 0xf43c, 0x0000, 0x0000, 0xe03d, 0xe03e,
+ 0xe2ae, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xecc2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe947, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe8da,
+ 0xe7bb, 0xe095, 0xf663, 0xee9a, 0xf097, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf098, 0x0000, 0x0000, 0xf69b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe2af, 0x0000, 0x0000, 0xe063, 0x0000, 0x0000, 0xe03f,
+ 0xe440, 0xf3ba, 0x0000, 0xe6b3, 0xecc3, 0xf4fd, 0xea6a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xea6b, 0x0000, 0x0000, 0xf2de, 0x0000
+};
+
+static unsigned short johab_from_unicode_68[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xec73, 0xf29d, 0x0000, 0x0000, 0xeaf7, 0xe6ca,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe278, 0xe8db, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf3bb, 0x0000, 0x0000, 0x0000, 0x0000, 0xeff1,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf847, 0xe356, 0x0000, 0x0000, 0xe13b, 0xf238, 0x0000, 0x0000,
+ 0xe0fa, 0xf7f9, 0xe19f, 0xe4fe, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xed60, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf47e, 0x0000,
+ 0xe565, 0xeacd, 0x0000, 0xf948, 0xe3d0, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf45d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf6d2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe064,
+ 0x0000, 0xe5d9, 0x0000, 0x0000, 0x0000, 0xe76e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe1d9,
+ 0x0000, 0x0000, 0x0000, 0xf239, 0xf64c, 0x0000, 0x0000, 0xe16b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf359, 0x0000, 0xf99e,
+ 0x0000, 0xef59, 0xf5a0, 0x0000, 0x0000, 0x0000, 0x0000, 0xeefc,
+ 0xe6de, 0x0000, 0x0000, 0x0000, 0x0000, 0xea6c, 0x0000, 0xf33c,
+ 0xe1a0, 0xe1e1, 0x0000, 0xebba, 0x0000, 0xe8ef, 0xe842, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe3a5, 0xe948, 0x0000, 0x0000,
+ 0x0000, 0xe798, 0x0000, 0xe3a4, 0x0000, 0xe1e2, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe97a, 0x0000, 0x0000, 0xf399, 0x0000, 0xf35a,
+ 0xe34e, 0x0000, 0xe9dc, 0x0000, 0x0000, 0x0000, 0x0000, 0xe566,
+ 0xe4d6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf1d0,
+ 0xe1a1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeab5, 0x0000,
+ 0x0000, 0x0000, 0xeaf8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe531, 0xe242, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_69[] = {
+ 0xef5a, 0x0000, 0x0000, 0x0000, 0x0000, 0xf0f5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xecd5, 0xf5d0, 0x0000,
+ 0x0000, 0x0000, 0xf5a1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7a7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xedab, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xee5b, 0x0000, 0xf5f1,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xedc5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf7a3, 0xeb6b, 0xf67b, 0x0000, 0xe0f1,
+ 0x0000, 0xe7ea, 0xf5a2, 0x0000, 0x0000, 0x0000, 0xe6d1, 0x0000,
+ 0xe3f8, 0xf09a, 0xf09b, 0xe843, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf2df, 0x0000, 0x0000, 0xf3ef, 0x0000, 0xedf6, 0xf24f, 0xec74,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe34f, 0x0000, 0xf83c,
+ 0xf5d1, 0xeeb3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xefbe, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf45e, 0xe8b4, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf95e, 0x0000, 0xe9ee,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeeb4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe6b4, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf6b4, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe1be, 0x0000, 0xe879, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe2b0, 0xf6d9, 0xf4e6, 0x0000, 0x0000,
+ 0xe269, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe23a, 0x0000, 0xe0c8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe337, 0x0000, 0xf35b, 0x0000, 0xe357
+};
+
+static unsigned short johab_from_unicode_6a[] = {
+ 0x0000, 0x0000, 0xe3e2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe8e0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe5da, 0x0000, 0xe476, 0x0000, 0x0000, 0x0000, 0xf250,
+ 0x0000, 0xf798, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5d2, 0xf1e9,
+ 0x0000, 0xe7bc, 0x0000, 0xedc6, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5a3, 0x0000, 0x0000,
+ 0xe864, 0xec37, 0xf8fc, 0x0000, 0x0000, 0xf3dc, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe096, 0x0000, 0x0000, 0x0000,
+ 0xef9c, 0x0000, 0x0000, 0xe279, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xeff8, 0xec75, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe349, 0xe594, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3a6,
+ 0x0000, 0xeace, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf996, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe4aa, 0x0000, 0x0000, 0x0000, 0xe13c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf2e0, 0x0000, 0x0000, 0x0000, 0xede5, 0xe365, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe8fc,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf976, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe0fe, 0xf1ea, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xea41, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf7e3, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe532, 0xe2f6, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe453, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe5ea, 0xf3ee, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf85b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xeda1, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_6b[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe3ed, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe2ed, 0x0000, 0xf1eb, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe5b2, 0x0000, 0x0000, 0x0000, 0xe5bc, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf9e2, 0xf4ad, 0x0000, 0xf9db, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xefb0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe3a7, 0x0000, 0x0000, 0xf9e3, 0xe243, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf9e4, 0xf85e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe040, 0x0000, 0xf6a7, 0x0000,
+ 0xe2b1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xee32,
+ 0x0000, 0xf946, 0xf43d, 0xf2e1, 0xf4ae, 0xe956, 0xe7eb, 0x0000,
+ 0x0000, 0x0000, 0xef70, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xeba8, 0x0000, 0x0000, 0x0000, 0x0000, 0xe5f6,
+ 0xe2fd, 0x0000, 0x0000, 0xea6d, 0x0000, 0x0000, 0x0000, 0xe7d1,
+ 0x0000, 0x0000, 0x0000, 0xed7a, 0xf45f, 0x0000, 0xf6bf, 0x0000,
+ 0x0000, 0xec76, 0xec38, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xecd6, 0x0000,
+ 0xf1d1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeff9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe641, 0xea42,
+ 0x0000, 0x0000, 0xeb78, 0x0000, 0x0000, 0xe4ab, 0x0000, 0xf0dc,
+ 0x0000, 0x0000, 0xeaaf, 0x0000, 0xe053, 0x0000, 0x0000, 0xf29e,
+ 0x0000, 0xf9c3, 0x0000, 0x0000, 0x0000, 0xf0f6, 0xe2b2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe7ec, 0x0000, 0xe7bd, 0x0000, 0xe76f,
+ 0x0000, 0x0000, 0xe548, 0xf0be, 0xe9ef, 0x0000, 0xe9f0, 0xe9f1,
+ 0xe9f2, 0x0000, 0x0000, 0xe7be, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf8c6, 0xe2b3, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_6c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf29f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xed3b,
+ 0x0000, 0xe855, 0x0000, 0xe77c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe3a8, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xec39, 0x0000, 0x0000, 0xea4c,
+ 0xeeb5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe8f0, 0x0000,
+ 0xf2e2, 0xf3f0, 0xe2b4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe8f1, 0x0000,
+ 0xeb41, 0x0000, 0x0000, 0x0000, 0x0000, 0xeaa5, 0x0000, 0xf7d2,
+ 0x0000, 0x0000, 0xeefd, 0x0000, 0x0000, 0xee33, 0xf8f1, 0xe0b0,
+ 0xf43e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe1e7, 0x0000, 0xef6c, 0x0000, 0x0000, 0xeed7, 0x0000, 0x0000,
+ 0xf6c0, 0x0000, 0xe373, 0x0000, 0x0000, 0x0000, 0xe831, 0x0000,
+ 0x0000, 0x0000, 0xe14d, 0x0000, 0x0000, 0xe3a9, 0xe9cc, 0x0000,
+ 0x0000, 0xecfe, 0xe3aa, 0xef3a, 0x0000, 0xf046, 0xf7fa, 0xee5c,
+ 0xed31, 0x0000, 0x0000, 0x0000, 0xe557, 0x0000, 0x0000, 0x0000,
+ 0xe7cb, 0x0000, 0xe7d2, 0xe4cb, 0xe799, 0xe839, 0xf5f8, 0x0000,
+ 0x0000, 0xea6e, 0xf43f, 0xf739, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe758, 0x0000, 0x0000, 0xf251, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf7c1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe9f3, 0xf09c, 0x0000, 0xf64d, 0xebbb, 0xe1bf, 0xf564, 0xee5d,
+ 0x0000, 0xf95f, 0xf8a2, 0x0000, 0xeb6c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf54b, 0xe865, 0x0000, 0xe9f4, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf8f2, 0x0000, 0xe8f6, 0x0000, 0xea6f,
+ 0x0000, 0x0000, 0x0000, 0xe8f2, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf76c, 0xf6ee, 0xf0e8, 0x0000, 0xe49c, 0x0000, 0x0000,
+ 0xf3bc, 0x0000, 0x0000, 0xf86a, 0x0000, 0x0000, 0xe87a, 0xe856,
+ 0xf6c1, 0x0000, 0x0000, 0xeeb6, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_6d[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xedc7, 0xe63c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe957, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeba9,
+ 0x0000, 0xec3a, 0x0000, 0xe3e3, 0x0000, 0x0000, 0xe567, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf460, 0x0000, 0xf09d,
+ 0x0000, 0xeb6d, 0xf8f3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf3bd, 0x0000, 0x0000, 0xec77, 0xf9d7, 0x0000,
+ 0xe258, 0xf047, 0x0000, 0xf950, 0x0000, 0xf9e7, 0xf6ef, 0x0000,
+ 0x0000, 0xe6b5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf2ba, 0xf3dd, 0x0000, 0xea43, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xef5b, 0x0000, 0x0000, 0xf76d, 0x0000,
+ 0x0000, 0xf8c7, 0xe439, 0x0000, 0xe6df, 0x0000, 0xe9a9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xefb1, 0x0000, 0x0000, 0xf83d,
+ 0xf669, 0xf896, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf73a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xee7e, 0x0000, 0xe16c,
+ 0xebbc, 0xeb91, 0x0000, 0x0000, 0xefbf, 0xf99f, 0xee5e, 0x0000,
+ 0x0000, 0xebd7, 0x0000, 0xee5f, 0x0000, 0xf593, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xed95,
+ 0x0000, 0x0000, 0xed9d, 0x0000, 0x0000, 0xf7e4, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf2e3, 0x0000, 0x0000, 0xe2ee, 0xf64e, 0xeb42, 0xf9a0, 0xe3ab,
+ 0x0000, 0x0000, 0x0000, 0xe6fa, 0x0000, 0x0000, 0x0000, 0xf8c8,
+ 0x0000, 0xec67, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe533, 0xf39a, 0xe477, 0x0000, 0x0000, 0x0000, 0xebe7, 0x0000,
+ 0x0000, 0xe4bf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf2e4, 0x0000, 0xe6c5, 0xf0e2, 0x0000, 0x0000, 0xf977, 0x0000,
+ 0x0000, 0xed32, 0x0000, 0xec78, 0x0000, 0xee60, 0x0000, 0xf8e8,
+ 0xf578, 0xedf4, 0xf54c, 0xf565, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_6e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeab6,
+ 0x0000, 0xf949, 0xf252, 0xe097, 0x0000, 0x0000, 0x0000, 0xf2e5,
+ 0xe0e2, 0xe534, 0x0000, 0xea70, 0xe89f, 0xed56, 0xef4e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xeb6e, 0xf644, 0xf062, 0x0000, 0xf7fb,
+ 0x0000, 0x0000, 0xeb52, 0x0000, 0xe074, 0x0000, 0xeeb7, 0x0000,
+ 0xf09f, 0x0000, 0xe7dd, 0x0000, 0xe844, 0xf23a, 0xf8e9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe8cb, 0xe845, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf3be, 0x0000, 0x0000, 0xe4ac, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf8c9, 0x0000,
+ 0xeacf, 0x0000, 0x0000, 0xe4c0, 0xecd7, 0x0000, 0xf2e6, 0xf960,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xefc0,
+ 0x0000, 0x0000, 0x0000, 0xf5d3, 0x0000, 0x0000, 0xf16c, 0xf6b7,
+ 0x0000, 0x0000, 0xf048, 0xe3f9, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe958, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf049, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf3de, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe6b6, 0xe2b5, 0x0000, 0xe7a8,
+ 0x0000, 0x0000, 0xf17e, 0x0000, 0x0000, 0xe9aa, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe1a2, 0xef3e, 0x0000, 0x0000, 0x0000, 0xebbd,
+ 0x0000, 0xf461, 0x0000, 0x0000, 0x0000, 0x0000, 0xefc1, 0x0000,
+ 0x0000, 0x0000, 0xe49e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe8b5, 0x0000, 0xf4e7, 0xe7a0, 0x0000, 0x0000,
+ 0x0000, 0xf961, 0x0000, 0xf1b2, 0xf53f, 0x0000, 0xf8a3, 0x0000,
+ 0x0000, 0xe1e8, 0x0000, 0xf23b, 0xe535, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf594,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf269, 0x0000, 0x0000, 0x0000,
+ 0xf8ca, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe1e3, 0xe74b
+};
+
+static unsigned short johab_from_unicode_6f[] = {
+ 0x0000, 0xeddb, 0xf799, 0x0000, 0x0000, 0x0000, 0xf664, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe478,
+ 0x0000, 0xe0c9, 0x0000, 0x0000, 0xee61, 0xf35c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe73e, 0x0000, 0xf7d3, 0xe5fe, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe74c, 0xf440, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xec3b, 0xf4e8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf2c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf1ec,
+ 0x0000, 0xeeb8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe8a0, 0x0000, 0x0000, 0xe14e, 0x0000, 0x0000, 0xf49e,
+ 0xe87b, 0x0000, 0xec68, 0xf1d6, 0x0000, 0x0000, 0xe661, 0xeb43,
+ 0x0000, 0x0000, 0xf962, 0x0000, 0xf0c8, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe4c1, 0xf35d, 0x0000,
+ 0xe2f7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf1d2, 0x0000, 0xe568, 0xe959, 0xe6f1, 0x0000,
+ 0x0000, 0xeabb, 0x0000, 0x0000, 0xf4a5, 0x0000, 0x0000, 0x0000,
+ 0xf55d, 0x0000, 0x0000, 0x0000, 0x0000, 0xf3bf, 0xf741, 0x0000,
+ 0xeffa, 0x0000, 0x0000, 0x0000, 0xf8cb, 0x0000, 0x0000, 0xe065,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf7d4, 0xf6ca, 0x0000, 0x0000, 0xe658,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf978, 0xf4bd,
+ 0x0000, 0xf2a0, 0x0000, 0xeefe, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe4c2, 0x0000, 0x0000, 0x0000, 0x0000, 0xe4b6, 0x0000,
+ 0xe13d, 0xf69c, 0xe642, 0xe468, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xeed8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeca5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xeeb9, 0x0000, 0x0000, 0x0000, 0x0000, 0xf33d,
+ 0xf8cc, 0xf0a1, 0x0000, 0x0000, 0xe536, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf8cd, 0x0000, 0xe3fa, 0xf3df, 0x0000, 0x0000, 0xf69d,
+ 0x0000, 0xea44, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe5eb, 0x0000
+};
+
+static unsigned short johab_from_unicode_70[] = {
+ 0x0000, 0xedc8, 0x0000, 0x0000, 0x0000, 0xf8a4, 0xe549, 0x0000,
+ 0x0000, 0xea71, 0x0000, 0xed33, 0x0000, 0x0000, 0x0000, 0xe6b7,
+ 0x0000, 0xf77e, 0x0000, 0x0000, 0x0000, 0xea45, 0x0000, 0x0000,
+ 0xe662, 0x0000, 0xf7d5, 0xeeba, 0xf0d5, 0xe5f7, 0xf2e7, 0xebbe,
+ 0x0000, 0x0000, 0x0000, 0xf83e, 0x0000, 0x0000, 0x0000, 0xe679,
+ 0xe67e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeebb,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf15b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe5b3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe244, 0x0000, 0x0000, 0x0000,
+ 0xf8a5, 0xebee, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf6a8, 0x0000, 0x0000, 0x0000, 0x0000, 0xf8ce, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe74d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf8fd, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf979, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe2b6, 0x0000, 0x0000, 0x0000, 0xf1c7, 0xf23c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe16d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf637, 0x0000, 0x0000, 0x0000, 0xee9c, 0x0000,
+ 0x0000, 0x0000, 0xf5a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf9dc, 0xf1b3, 0xe259, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf2e8, 0x0000, 0x0000, 0xebbf, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf86b, 0xe0e3, 0xf6a9, 0x0000, 0xf8a6,
+ 0x0000, 0x0000, 0x0000, 0xe949, 0x0000, 0x0000, 0x0000, 0xf3c0,
+ 0xf1c8, 0xf2c3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe63d, 0x0000, 0x0000, 0xf9ce, 0x0000, 0x0000, 0x0000, 0xef31,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf8f4, 0xe3e4, 0x0000, 0x0000, 0x0000, 0xf3f6, 0x0000, 0xee63,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe16e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf742, 0x0000, 0x0000, 0x0000, 0xe97b, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_71[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf9b6, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xedea, 0x0000, 0x0000, 0xf3e0, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe8cc, 0xe9cd, 0x0000, 0x0000, 0x0000, 0xe558, 0x0000,
+ 0x0000, 0xe7ed, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5a5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xee9d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xee64, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf9c8,
+ 0x0000, 0xe631, 0xf9bf, 0x0000, 0xf963, 0x0000, 0xf2a1, 0x0000,
+ 0xeebc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3ee, 0x0000,
+ 0x0000, 0xee65, 0x0000, 0x0000, 0xeff2, 0x0000, 0xeab0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe770, 0xf94a, 0xf9af, 0xf35e,
+ 0x0000, 0xe8e1, 0x0000, 0x0000, 0xedc9, 0x0000, 0xf1b4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeb53, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xecd8, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeffb, 0xf038, 0x0000, 0x0000, 0x0000, 0x0000, 0xf9b7,
+ 0x0000, 0x0000, 0xf8a7, 0x0000, 0xefc2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf9f7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xec69,
+ 0x0000, 0x0000, 0xe97c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xef32, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xee92, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf9f8, 0xf9f9, 0x0000, 0x0000, 0x0000, 0xf64f, 0x0000,
+ 0x0000, 0xeea7, 0x0000, 0xee67, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe595, 0xe559, 0x0000, 0x0000, 0x0000, 0x0000, 0xe69c, 0x0000,
+ 0xe6f2, 0x0000, 0xebc0, 0x0000, 0xe8e2, 0xee68, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeebd,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf35f, 0xf4be, 0xec3c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5b7, 0xeb92, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf9b8, 0xece8, 0x0000, 0xe537, 0xef9e
+};
+
+static unsigned short johab_from_unicode_72[] = {
+ 0xf862, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf791, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe454, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe3ef, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf360, 0x0000, 0xf6f0, 0xf243, 0x0000, 0x0000,
+ 0xf04a, 0x0000, 0xf063, 0x0000, 0x0000, 0xf1c9, 0xe9ab, 0x0000,
+ 0x0000, 0x0000, 0xedac, 0xf9a1, 0x0000, 0xead0, 0xf143, 0x0000,
+ 0xead1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf1ed, 0xf748,
+ 0xf6fa, 0x0000, 0x0000, 0x0000, 0xf73b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf570, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe54a, 0xed43, 0x0000, 0xefda, 0x0000, 0xea46, 0x0000, 0xe7bf,
+ 0x0000, 0xe7c0, 0xe46e, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7cc,
+ 0x0000, 0xe83a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xeae5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf6e5, 0x0000, 0x0000, 0x0000, 0xe142, 0x0000, 0x0000,
+ 0xeaf9, 0xe6e0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe54b, 0x0000, 0x0000, 0x0000, 0x0000, 0xf9fa,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe143, 0x0000, 0x0000, 0xe8f3,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xead2, 0x0000, 0xe25a, 0x0000, 0xf26a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xed74, 0x0000,
+ 0xf8cf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe2b7,
+ 0x0000, 0xf253, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe27a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xec3d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe6e1, 0xf897, 0x0000, 0x0000, 0xe43a, 0xf73c, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_73[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xeed9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf4e9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe77d, 0xecc4, 0xf393, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xef75, 0x0000, 0x0000,
+ 0x0000, 0xeb9c, 0xf254, 0xe7de, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf0a2, 0xf0a3,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf952, 0xf04b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xef3b, 0xea72, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf1ef, 0x0000, 0xef33, 0x0000, 0x0000, 0x0000, 0x0000, 0xe2f1,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe54c, 0x0000, 0xf97a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xeebe, 0x0000, 0xf994, 0x0000, 0x0000, 0xe644, 0x0000, 0x0000,
+ 0xec3e, 0x0000, 0xe4b7, 0xf85c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf86c, 0x0000, 0xf1b5, 0xe6cb,
+ 0x0000, 0xef3c, 0x0000, 0xef6d, 0x0000, 0x0000, 0xf2e9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf54d, 0x0000, 0xe2b8, 0xefdb,
+ 0xe3ac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe857,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf0c9,
+ 0x0000, 0xef5c, 0x0000, 0x0000, 0x0000, 0xea47, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe64c, 0xe4e5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf86d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe866, 0x0000, 0xe041, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe858, 0xeaa6, 0x0000, 0xf7b3, 0xf462, 0x0000, 0xe054,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe25b, 0x0000,
+ 0x0000, 0xe1f5, 0x0000, 0x0000, 0x0000, 0xf9b0, 0xe3e5, 0x0000,
+ 0xf3c1, 0x0000, 0x0000, 0xec79, 0xe95a, 0xf144, 0xf850, 0x0000,
+ 0x0000, 0xf8a8, 0xe338, 0x0000, 0x0000, 0xe87c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7ee,
+ 0x0000, 0xeb9d, 0x0000, 0x0000, 0x0000, 0xf2ea, 0xf86e, 0x0000
+};
+
+static unsigned short johab_from_unicode_74[] = {
+ 0x0000, 0xeb54, 0x0000, 0xe2b9, 0x0000, 0xe5ca, 0xe6e2, 0xec3f,
+ 0x0000, 0xe6b8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xef5d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf66a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf2a2, 0xec6a, 0xf69e, 0x0000, 0x0000, 0xf8d0, 0xe3ad, 0x0000,
+ 0xe1e4, 0x0000, 0xe3ae, 0xe97d, 0xef5e, 0x0000, 0xf39b, 0xe245,
+ 0xee9e, 0x0000, 0x0000, 0xe6fb, 0xe366, 0xe9f5, 0xf6f1, 0x0000,
+ 0xf69f, 0x0000, 0xe8f7, 0x0000, 0x0000, 0x0000, 0x0000, 0xf8ea,
+ 0xefdc, 0xe7c1, 0x0000, 0xf5f2, 0xeb55, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf064, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf7c2, 0x0000, 0xf04c,
+ 0x0000, 0xe455, 0xf8d1, 0xeec0, 0xf0a5, 0x0000, 0xeafa, 0xeca2,
+ 0xe6b9, 0x0000, 0xefc3, 0x0000, 0xef9f, 0xef3f, 0x0000, 0x0000,
+ 0xf463, 0xeec1, 0xe735, 0x0000, 0x0000, 0x0000, 0x0000, 0xe5cb,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe358, 0x0000,
+ 0x0000, 0x0000, 0xe3af, 0xe6e3, 0x0000, 0x0000, 0x0000, 0xeb56,
+ 0x0000, 0xe632, 0x0000, 0xf1f0, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe6f3, 0x0000, 0x0000, 0x0000, 0xf964, 0x0000, 0xe867, 0xe16f,
+ 0x0000, 0xf464, 0x0000, 0xe3b0, 0x0000, 0xe170, 0x0000, 0xe8fd,
+ 0xf4bf, 0x0000, 0xf361, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf94b, 0x0000, 0xec40, 0x0000, 0x0000, 0xee35, 0x0000, 0x0000,
+ 0x0000, 0xec6b, 0x0000, 0x0000, 0x0000, 0xeade, 0x0000, 0xeb57,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf491, 0x0000,
+ 0x0000, 0x0000, 0xe171, 0x0000, 0x0000, 0x0000, 0x0000, 0xe67a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xeec2, 0x0000, 0x0000, 0x0000,
+ 0xe246, 0x0000, 0xf4c0, 0x0000, 0xe1fe, 0x0000, 0x0000, 0x0000,
+ 0xf8d2, 0x0000, 0xf79a, 0xf6fb, 0x0000, 0x0000, 0xef4f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xef47, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf1b6,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_75[] = {
+ 0x0000, 0xe94a, 0x0000, 0x0000, 0xe144, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf3f7, 0x0000, 0x0000, 0x0000, 0xef48, 0x0000, 0x0000,
+ 0xe098, 0x0000, 0xed34, 0xf566, 0x0000, 0x0000, 0x0000, 0xeae6,
+ 0x0000, 0x0000, 0x0000, 0xeaa7, 0x0000, 0xeae7, 0xebc1, 0x0000,
+ 0xefc4, 0x0000, 0x0000, 0xe95b, 0xefc5, 0x0000, 0x0000, 0x0000,
+ 0xf2a3, 0xf0a6, 0xe0a3, 0xece9, 0x0000, 0x0000, 0x0000, 0xe3fb,
+ 0xf2a4, 0x0000, 0xf2eb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe344,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe1a3, 0x0000, 0x0000, 0xef76,
+ 0x0000, 0xf2a5, 0x0000, 0xe4cc, 0xe87d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe6ba, 0x0000, 0xf465, 0xf5e5, 0xe7ef, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf7b4, 0x0000, 0x0000, 0xe5d4, 0xf9cf, 0x0000,
+ 0x0000, 0x0000, 0xe8e3, 0x0000, 0x0000, 0x0000, 0x0000, 0xf3e1,
+ 0xe6e4, 0x0000, 0x0000, 0x0000, 0x0000, 0xf8fe, 0xe4d7, 0x0000,
+ 0xe3b1, 0x0000, 0xe0b1, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3b2,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe0b2, 0xf3c2,
+ 0x0000, 0x0000, 0xf571, 0xf7b5, 0x0000, 0x0000, 0xebc3, 0xebc2,
+ 0x0000, 0xf0f7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeaa8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe0ca, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xee49, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf76e, 0xf7aa, 0xe099, 0x0000, 0xf1b7, 0x0000, 0x0000,
+ 0xe4b8, 0xf466, 0x0000, 0x0000, 0xe569, 0xf255, 0xf492, 0x0000,
+ 0x0000, 0x0000, 0xe042, 0x0000, 0x0000, 0xe94b, 0x0000, 0xf3f8,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf147, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xedca, 0x0000, 0xf650, 0xf9dd, 0x0000, 0x0000,
+ 0xe573, 0xe172, 0x0000, 0xf6d4, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe6e5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe4c3, 0x0000, 0xe736, 0x0000, 0xf651, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe9f6, 0x0000, 0xe1c0, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_76[] = {
+ 0xeddc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xedcb, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xebc4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xef40,
+ 0xf540, 0xf4ea, 0xe87e, 0x0000, 0xe6bb, 0x0000, 0xec41, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe6aa, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe69d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xed6f, 0x0000, 0xe066, 0x0000,
+ 0x0000, 0x0000, 0xf0a8, 0x0000, 0x0000, 0x0000, 0xe8fe, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf652, 0x0000, 0x0000, 0xf2bb, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe3db, 0x0000, 0x0000, 0xeb58, 0x0000, 0x0000, 0x0000,
+ 0xef49, 0x0000, 0xf2a6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe1a4, 0x0000, 0x0000, 0xe596, 0xe8a1, 0xe8dc, 0xe8dd, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf26c, 0x0000, 0xe0cb, 0xf965,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe27b, 0x0000,
+ 0xe1c1, 0x0000, 0x0000, 0xf8d3, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf7ab, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf5d4, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7a9,
+ 0x0000, 0x0000, 0xefdd, 0xe8cd, 0x0000, 0x0000, 0xe9ce, 0x0000,
+ 0xeec3, 0x0000, 0xf15c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf7ec, 0x0000, 0x0000, 0x0000, 0xe0cc, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xeb9e, 0xe538, 0x0000, 0xf1d3, 0xe791,
+ 0x0000, 0xf467, 0x0000, 0xe09a, 0xe891, 0x0000, 0x0000, 0xe456,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7cd, 0x0000,
+ 0x0000, 0x0000, 0xe77e, 0x0000, 0xf451, 0x0000, 0x0000, 0x0000,
+ 0xead3, 0x0000, 0x0000, 0x0000, 0xe892, 0x0000, 0xec7a, 0x0000
+};
+
+static unsigned short johab_from_unicode_77[] = {
+ 0x0000, 0xeae8, 0x0000, 0x0000, 0xe79a, 0x0000, 0x0000, 0x0000,
+ 0xf6af, 0xe846, 0x0000, 0xe067, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf468, 0x0000,
+ 0xe79b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf86f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe2ef,
+ 0xe7c2, 0x0000, 0xf362, 0x0000, 0xed61, 0x0000, 0x0000, 0x0000,
+ 0xf4b7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf870, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf2ec, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xec42, 0x0000, 0xe54d, 0x0000, 0x0000, 0xe7ce, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf572, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe539, 0x0000, 0x0000, 0x0000, 0x0000, 0xe1c2, 0xeeda,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf469, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe7aa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe74e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe93d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xec7b, 0xe69e, 0x0000, 0x0000,
+ 0xe09b, 0x0000, 0x0000, 0xe56a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf567, 0xe131, 0x0000, 0x0000, 0xe2ba,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5b8,
+ 0x0000, 0x0000, 0x0000, 0xe7c3, 0xe378, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xecc5, 0xf0f8, 0x0000, 0xf441, 0x0000, 0x0000,
+ 0x0000, 0xe2bb, 0x0000, 0x0000, 0x0000, 0xe4ad, 0xef71, 0xe27c,
+ 0x0000, 0x0000, 0x0000, 0xeb44, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_78[] = {
+ 0x0000, 0x0000, 0xea73, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe9f7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf442, 0xf4f6, 0xf66b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe6fe, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf76f, 0x0000, 0xf6f2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe339, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xee6a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5a6, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe6bc, 0xe173, 0x0000, 0x0000, 0xee6b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe9dd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe3b3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf2ed,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe45f, 0xed96, 0xebef, 0x0000,
+ 0x0000, 0xe9f8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xef5f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe075, 0x0000, 0x0000, 0x0000, 0xe931,
+ 0x0000, 0xeb45, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf93c, 0xf93d, 0xe737, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf1b8, 0x0000, 0x0000, 0x0000, 0xe8b6, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe46f, 0xf4af, 0x0000, 0x0000, 0xe1a5, 0x0000,
+ 0xe893, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe738, 0x0000, 0x0000, 0x0000, 0xe174, 0x0000, 0x0000, 0xe3b4,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe068, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe894, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_79[] = {
+ 0x0000, 0xf5a7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5a8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xee36, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe5ec, 0xe5f8, 0xe895, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xecc6, 0x0000, 0x0000, 0x0000, 0xea74, 0x0000,
+ 0xea75, 0xe3b5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3b6,
+ 0xe3b7, 0xf443, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xefde, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf363, 0xf444,
+ 0x0000, 0x0000, 0xf364, 0xe0e4, 0xf8d4, 0xf5e6, 0xecea, 0x0000,
+ 0xea76, 0x0000, 0x0000, 0x0000, 0x0000, 0xead4, 0x0000, 0x0000,
+ 0xf79b, 0x0000, 0x0000, 0x0000, 0x0000, 0xf33e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe3b8, 0x0000, 0x0000, 0x0000, 0x0000, 0xe460,
+ 0x0000, 0xe367, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf931, 0xf2ee, 0xe968,
+ 0x0000, 0xefdf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeddd, 0xf9fb,
+ 0x0000, 0x0000, 0xeb59, 0x0000, 0x0000, 0x0000, 0xe659, 0x0000,
+ 0x0000, 0xe53a, 0x0000, 0xedcc, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xefe0, 0x0000, 0x0000, 0x0000, 0xe368, 0xf932, 0xe54e,
+ 0xec43, 0xea77, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe94c, 0xe446, 0xf5d5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe231, 0xf5a9, 0x0000, 0x0000, 0xe9f9, 0x0000, 0x0000,
+ 0xe9fa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf365,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf66f, 0x0000, 0xf46a, 0xed7b,
+ 0x0000, 0xf493, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf149, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_7a[] = {
+ 0xf9fc, 0x0000, 0x0000, 0x0000, 0x0000, 0xebaa, 0x0000, 0x0000,
+ 0xe069, 0x0000, 0x0000, 0xf2ef, 0x0000, 0xf5aa, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf19b, 0x0000, 0x0000, 0xf73d,
+ 0x0000, 0xf452, 0xf653, 0x0000, 0xe496, 0x0000, 0x0000, 0xf7a2,
+ 0xf366, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf39c, 0x0000,
+ 0x0000, 0xf670, 0x0000, 0x0000, 0x0000, 0x0000, 0xeff3, 0xf453,
+ 0x0000, 0x0000, 0x0000, 0xe53b, 0xe043, 0xe1a6, 0x0000, 0xe1c3,
+ 0xe1da, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7cf, 0x0000,
+ 0x0000, 0xf654, 0x0000, 0x0000, 0x0000, 0xf26d, 0xeec4, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xec44,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeae2, 0xeedb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xef41, 0x0000, 0xf93e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xedcd, 0x0000, 0x0000, 0x0000, 0xf87b, 0x0000, 0xe2bc, 0x0000,
+ 0x0000, 0xe2e2, 0xe1f6, 0x0000, 0x0000, 0xf2f0, 0x0000, 0xf54e,
+ 0x0000, 0xe55d, 0x0000, 0x0000, 0xf4b8, 0x0000, 0x0000, 0x0000,
+ 0xefa1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf494, 0xf4eb, 0x0000, 0xf367, 0x0000, 0x0000,
+ 0xe2d7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe2df,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xef50, 0xef51, 0x0000, 0x0000, 0x0000, 0xe2e3, 0xefa2,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe33a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf4c1, 0xe33b, 0x0000, 0xe574,
+ 0x0000, 0x0000, 0xf2bc, 0xe731, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7df,
+ 0x0000, 0xf4d7, 0x0000, 0x0000, 0x0000, 0xe94d, 0x0000, 0xe175,
+ 0xf1f1, 0x0000, 0x0000, 0xf3e2, 0x0000, 0xe56b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xec45, 0x0000, 0x0000, 0xe076, 0x0000, 0xe4ae,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe176, 0x0000,
+ 0x0000, 0xf3d3, 0xf5e7, 0x0000, 0x0000, 0x0000, 0x0000, 0xe06a
+};
+
+static unsigned short johab_from_unicode_7b[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf8ee,
+ 0x0000, 0xebc5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeae9, 0x0000, 0xf26e, 0x0000, 0x0000, 0xf6c2, 0x0000,
+ 0xe732, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe9ac, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf33f, 0xe64d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xebab, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf7b6, 0x0000,
+ 0x0000, 0xe597, 0x0000, 0xe359, 0xf2a7, 0xec7c, 0x0000, 0xe8ea,
+ 0xe25c, 0xf5e8, 0xf6d5, 0x0000, 0xe4cd, 0x0000, 0xf4fe, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe345, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xeba0, 0x0000, 0xeafb, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xee6d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xef34, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe0cd,
+ 0x0000, 0x0000, 0x0000, 0xf2a8, 0x0000, 0x0000, 0x0000, 0xf244,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe868, 0xe3b9, 0x0000, 0xeaa9,
+ 0x0000, 0x0000, 0xf4b0, 0x0000, 0x0000, 0xe154, 0x0000, 0x0000,
+ 0x0000, 0xe247, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf2a9, 0x0000, 0x0000,
+ 0x0000, 0xead5, 0x0000, 0x0000, 0xf1d7, 0x0000, 0x0000, 0x0000,
+ 0xf256, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf2bd, 0xf966, 0x0000, 0x0000, 0xe8f4, 0x0000, 0xf2aa, 0xf749,
+ 0x0000, 0xf5e9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xecd9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xebc6, 0x0000, 0x0000, 0x0000, 0xe54f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xea78, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_7c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf37a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf4c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe4af, 0x0000,
+ 0x0000, 0xe06b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf967,
+ 0x0000, 0x0000, 0xf1d8, 0xebc7, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf568, 0xe643, 0xe9ad,
+ 0x0000, 0x0000, 0x0000, 0xe5be, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf3c3, 0xf26f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe469, 0x0000, 0x0000, 0x0000, 0xf569, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe6e6, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe847, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe9fb, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe9cf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe733, 0x0000, 0x0000, 0xe869, 0x0000, 0xf368,
+ 0xf2c4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xebd8,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf3d4, 0x0000, 0xf1f2,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe5db, 0x0000,
+ 0x0000, 0xe5dc, 0xf4c4, 0xe0d7, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xec46, 0x0000, 0x0000, 0x0000, 0x0000, 0xf2f1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf8d5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe4d8, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe9d0, 0xf369,
+ 0xe0b3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe5dd,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe1a7, 0x0000, 0x0000, 0xe33c, 0x0000
+};
+
+static unsigned short johab_from_unicode_7d[] = {
+ 0xe3ba, 0x0000, 0xf3c4, 0x0000, 0xedb3, 0xf8f5, 0xefe1, 0xf9e0,
+ 0xf94c, 0x0000, 0xe832, 0xe833, 0x0000, 0xe431, 0x0000, 0x0000,
+ 0xe491, 0x0000, 0x0000, 0x0000, 0xec7d, 0x0000, 0x0000, 0xea79,
+ 0xe26c, 0xf445, 0xe374, 0xe9d1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xebc8, 0xe8b7, 0xeaa0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf1b9, 0xf3c5, 0x0000, 0xf4cf, 0xe479,
+ 0xebac, 0x0000, 0x0000, 0xeceb, 0x0000, 0xf257, 0x0000, 0x0000,
+ 0x0000, 0xebc9, 0xe09c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf39d, 0xf871, 0xf36a, 0xe177, 0xe896, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe14f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe27d, 0x0000,
+ 0x0000, 0xe5a9, 0xf872, 0x0000, 0x0000, 0x0000, 0xe375, 0x0000,
+ 0xf0d6, 0x0000, 0xf16f, 0x0000, 0x0000, 0x0000, 0xeafc, 0x0000,
+ 0x0000, 0xf6d6, 0xea7a, 0xe0b4, 0x0000, 0x0000, 0xf2be, 0x0000,
+ 0x0000, 0xe145, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe2bd,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf2f2, 0xec47,
+ 0x0000, 0x0000, 0x0000, 0xe178, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf39e, 0x0000, 0x0000, 0x0000,
+ 0xe461, 0x0000, 0xf3c6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xec48, 0xf0ab, 0x0000, 0x0000,
+ 0x0000, 0xe0b5, 0xe761, 0x0000, 0xf55e, 0xf4f7, 0x0000, 0x0000,
+ 0xe6c6, 0x0000, 0xe3bb, 0xf6aa, 0x0000, 0xf1ca, 0xe497, 0xe79c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf655,
+ 0x0000, 0x0000, 0xe3cc, 0xe9fc, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeafd, 0x0000,
+ 0xf7e5, 0x0000, 0xeb5a, 0x0000, 0x0000, 0xf49f, 0xe4b0, 0x0000,
+ 0xf595, 0xe859, 0x0000, 0xee6e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf74a, 0xef60, 0x0000, 0x0000, 0xe79d, 0x0000, 0x0000, 0xf065,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe633, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf656, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_7e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf46b, 0xed9e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xef42, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe86a, 0x0000, 0xf46c, 0xf8d6, 0xefb2,
+ 0x0000, 0xf23d, 0x0000, 0xf873, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe97e, 0x0000, 0x0000, 0xf5ea, 0xee70,
+ 0x0000, 0xf39f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe47a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5c5, 0xf270, 0x0000,
+ 0x0000, 0xe8e5, 0x0000, 0xe9de, 0x0000, 0x0000, 0xe7f0, 0xefa3,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf3f9, 0x0000, 0xf454, 0xeb5b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xefa4, 0x0000,
+ 0x0000, 0xec49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xecb1, 0xf97b, 0xe1a8, 0x0000, 0xe146, 0x0000, 0x0000,
+ 0xf36b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xee4a, 0x0000, 0x0000, 0xe1a9, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf4c3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xebd9, 0x0000, 0x0000, 0xf2ab,
+ 0x0000, 0x0000, 0x0000, 0xeec5, 0x0000, 0x0000, 0xeb79, 0x0000,
+ 0xf4c5, 0x0000, 0x0000, 0xe550, 0xe5bf, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_7f[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe9ae, 0x0000,
+ 0xf7fc, 0x0000, 0xe150, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xeda2, 0x0000, 0x0000, 0x0000,
+ 0xe248, 0x0000, 0x0000, 0x0000, 0xe762, 0xf7d6, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf3aa, 0xe261, 0x0000, 0x0000, 0xf657, 0x0000,
+ 0xe8eb, 0x0000, 0xeafe, 0x0000, 0x0000, 0xe771, 0x0000, 0xf6f3,
+ 0x0000, 0xe6e7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3dc, 0x0000, 0x0000,
+ 0xe3bc, 0x0000, 0xedcf, 0x0000, 0xe0b6, 0x0000, 0xe848, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe1c4, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe64e, 0x0000, 0x0000, 0x0000, 0xec4a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe2d8, 0x0000, 0x0000, 0x0000,
+ 0xeb5c, 0xf0f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf9fd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe6e8, 0xe0d8, 0x0000, 0x0000, 0x0000, 0xefe2, 0x0000, 0x0000,
+ 0x0000, 0xef4a, 0x0000, 0x0000, 0x0000, 0xecc7, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf15d, 0x0000, 0xf15e, 0x0000, 0xe64f, 0x0000,
+ 0x0000, 0x0000, 0xeca7, 0x0000, 0xead6, 0xf9e8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf271,
+ 0xf638, 0xe9fd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf74b, 0x0000, 0xef61, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf7d7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe27e, 0x0000, 0x0000, 0xf15f, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_80[] = {
+ 0xefa5, 0xe457, 0x0000, 0xe1c5, 0x0000, 0xf1ba, 0xe3bd, 0x0000,
+ 0x0000, 0xe2be, 0x0000, 0x0000, 0xf14b, 0x0000, 0x0000, 0x0000,
+ 0xe441, 0x0000, 0x0000, 0x0000, 0x0000, 0xe179, 0x0000, 0xe7c4,
+ 0xeffc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3be, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf14c, 0x0000, 0x0000, 0xedad, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf6b0, 0x0000, 0xe17a,
+ 0x0000, 0x0000, 0x0000, 0xe4c4, 0x0000, 0x0000, 0xe650, 0x0000,
+ 0x0000, 0x0000, 0xe69f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeba1, 0x0000,
+ 0xea4d, 0x0000, 0xf639, 0x0000, 0x0000, 0x0000, 0xe834, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe634,
+ 0xf5c6, 0x0000, 0xeba2, 0xefc6, 0x0000, 0x0000, 0x0000, 0xf455,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf579, 0xe46a, 0xf0d3,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf14d, 0xec6c, 0xea7b, 0xf36c,
+ 0x0000, 0xf0bf, 0x0000, 0xe493, 0xe3bf, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5ab, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf7fd, 0x0000, 0xe06c, 0x0000, 0x0000,
+ 0x0000, 0xe1c6, 0xf446, 0x0000, 0x0000, 0xe9fe, 0x0000, 0x0000,
+ 0x0000, 0xe147, 0xe8b8, 0x0000, 0x0000, 0x0000, 0x0000, 0xe379,
+ 0x0000, 0xe26d, 0xf0c0, 0x0000, 0xf9a2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf75b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf066, 0xf3b0, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe8ce, 0x0000, 0xf6c3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe8cf, 0xe0a4, 0x0000, 0x0000, 0xf770, 0x0000,
+ 0x0000, 0xf8d7, 0x0000, 0x0000, 0xf0ca, 0xeb31, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe25d, 0x0000, 0x0000, 0xe56c, 0x0000, 0x0000, 0x0000,
+ 0xf9d8, 0x0000, 0x0000, 0x0000, 0x0000, 0xe498, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_81[] = {
+ 0x0000, 0x0000, 0xf447, 0x0000, 0x0000, 0xf898, 0xf63a, 0xf899,
+ 0xe776, 0x0000, 0xf541, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xef62, 0x0000, 0xe055, 0xe17b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xec7e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xec4b, 0x0000, 0xf6ad, 0x0000, 0x0000, 0x0000, 0xf771,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf4ec, 0x0000, 0x0000, 0x0000, 0x0000, 0xea31, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xed9f, 0x0000, 0x0000, 0xecec, 0x0000,
+ 0xe9af, 0xe9b0, 0x0000, 0x0000, 0xe0b7, 0xef63, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeba3, 0xe470, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf3a0, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xefa6, 0xe0f2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf1f3, 0xe969, 0xeb5d, 0x0000, 0x0000, 0x0000, 0x0000, 0xf6da,
+ 0xe8b9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe13e, 0x0000, 0xe86b, 0x0000, 0x0000, 0x0000, 0x0000, 0xe1c7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe9b1, 0x0000, 0xe73f, 0xeca3, 0x0000, 0x0000,
+ 0xe291, 0x0000, 0x0000, 0xf495, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf743, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xeb5e, 0x0000, 0xf5fd, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf0ec, 0x0000, 0x0000, 0xe4c5, 0xf97c, 0xe46b,
+ 0xe57b, 0x0000, 0xea32, 0x0000, 0x0000, 0x0000, 0xede6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf340, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe432, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf1f4,
+ 0x0000, 0x0000, 0x0000, 0xeced, 0x0000, 0xef52, 0x0000, 0xf1f5,
+ 0xe6fc, 0x0000, 0xf1bb, 0x0000, 0x0000, 0xf63b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf448, 0xf658, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe4e6, 0xf46d, 0xe2bf, 0x0000, 0xf0ac, 0x0000
+};
+
+static unsigned short johab_from_unicode_82[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe2c0, 0x0000, 0xee38,
+ 0xf9e9, 0x0000, 0xe2c1, 0x0000, 0xeb6f, 0xea7c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xeb32, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf54f, 0xec91, 0x0000, 0xe7f1, 0xf3c7,
+ 0x0000, 0xe0b8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf7fe, 0xe8ba, 0xe897, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf67c, 0xe86c, 0xf874,
+ 0x0000, 0xeb5f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe9b2, 0x0000, 0x0000, 0x0000, 0x0000, 0xee39, 0x0000, 0xf2f3,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf4ed, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf0fa, 0x0000, 0xf7e6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe06d, 0xe5de,
+ 0x0000, 0xe06e, 0xeae4, 0x0000, 0x0000, 0x0000, 0xee9f, 0x0000,
+ 0xf5ac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xed97, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xefe3, 0x0000, 0xf1cb, 0xe2e4, 0x0000,
+ 0x0000, 0x0000, 0xe763, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe9b3, 0xe57c, 0x0000, 0x0000, 0xf449, 0x0000, 0xeab7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe0ce, 0xf8d8, 0x0000,
+ 0x0000, 0xe369, 0x0000, 0x0000, 0xe9d2, 0xf6f4, 0xeedc, 0xed35,
+ 0x0000, 0xf933, 0x0000, 0xe8bb, 0x0000, 0x0000, 0x0000, 0xf44a,
+ 0xeffd, 0xe35a, 0x0000, 0xf5d6, 0xe7c5, 0xed44, 0x0000, 0xf1a7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf04d, 0xeea0, 0x0000, 0xf6c4, 0xf5ad, 0x0000, 0xe7e0,
+ 0x0000, 0x0000, 0x0000, 0xe044, 0x0000, 0x0000, 0xf772, 0xe2c2,
+ 0x0000, 0xf14e, 0x0000, 0x0000, 0x0000, 0xedae, 0xe1c8, 0xf258,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeec8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe1c9, 0xf7b7, 0x0000
+};
+
+static unsigned short johab_from_unicode_83[] = {
+ 0x0000, 0xf3e8, 0xe7f2, 0xe8f5, 0xe045, 0xe7c6, 0x0000, 0x0000,
+ 0x0000, 0xe759, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7ab,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf1bc, 0x0000, 0x0000, 0xe764, 0x0000, 0x0000, 0x0000, 0xe96a,
+ 0x0000, 0xec4c, 0x0000, 0x0000, 0xf97d, 0xf170, 0xe4a0, 0x0000,
+ 0xefc7, 0xee3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xec92, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf84b,
+ 0x0000, 0xf5ae, 0xf8aa, 0x0000, 0x0000, 0x0000, 0x0000, 0xf19d,
+ 0x0000, 0xf14f, 0xf968, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe575, 0x0000, 0x0000, 0x0000, 0xf7c3,
+ 0x0000, 0x0000, 0x0000, 0xf272, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe6e9, 0xf1f6, 0x0000, 0x0000, 0x0000, 0xea7d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe17c, 0x0000,
+ 0xecee, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xef64, 0x0000,
+ 0x0000, 0x0000, 0xf89a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe9b4, 0xed45, 0xe740, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe765, 0x0000, 0x0000,
+ 0x0000, 0xf57a, 0x0000, 0x0000, 0x0000, 0xe249, 0x0000, 0x0000,
+ 0x0000, 0xe462, 0xe2d2, 0x0000, 0xe346, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe232, 0x0000, 0x0000, 0xf4ee, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf4f8, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe95c, 0x0000, 0xe35b, 0x0000, 0x0000, 0x0000, 0xf934,
+ 0xe1ca, 0xe499, 0xea33, 0x0000, 0xed70, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf259, 0x0000, 0x0000, 0x0000, 0xec6d, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_84[] = {
+ 0x0000, 0x0000, 0x0000, 0xf5fe, 0xe53c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe5d1, 0x0000, 0xe792, 0xf753, 0xf067, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf5d7, 0x0000, 0x0000, 0xe74f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf9c0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf0ad, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3e6, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeb93, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf25a,
+ 0x0000, 0x0000, 0x0000, 0xe077, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf773, 0x0000, 0xe56d, 0x0000, 0x0000, 0xf068, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf8d9, 0xf1f7, 0x0000, 0x0000, 0xedb5,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe33d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf3f1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xec4d, 0x0000, 0x0000, 0x0000, 0xecc8, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe7d5, 0x0000, 0x0000, 0xeaaa, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe8bc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf774, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf3fa, 0x0000, 0x0000, 0xedb6, 0xf4ef, 0x0000, 0x0000, 0xf8da,
+ 0xebe0, 0x0000, 0xe7ac, 0x0000, 0xf5eb, 0x0000, 0xeb46, 0x0000,
+ 0x0000, 0xefc8, 0x0000, 0xe0cf, 0x0000, 0xecc9, 0x0000, 0x0000,
+ 0x0000, 0xea7e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xec4e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe991, 0x0000, 0xe635, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xec93, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe6a0, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_85[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe7a1, 0x0000, 0xe750, 0xe96b, 0x0000, 0x0000, 0xf1bd,
+ 0xeab8, 0x0000, 0xf035, 0x0000, 0x0000, 0x0000, 0xe6ad, 0x0000,
+ 0x0000, 0xf4f9, 0x0000, 0xf1f8, 0x0000, 0xf5c7, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xebca, 0xf0e3, 0x0000, 0xf46e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf75c, 0x0000, 0xf069,
+ 0x0000, 0xe4c6, 0x0000, 0xe8e6, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf5af, 0x0000, 0x0000, 0x0000, 0x0000, 0xe292, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xeffe, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf8b6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xec94, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe2f2, 0xf6b9, 0xe7f3, 0x0000, 0x0000, 0xebcb, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe86d, 0x0000, 0x0000, 0xe849,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf0fb,
+ 0x0000, 0xe0b9, 0x0000, 0x0000, 0xf1f9, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xeb70, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf550, 0x0000,
+ 0xf9bc, 0xeab1, 0xecef, 0x0000, 0x0000, 0x0000, 0x0000, 0xeb33,
+ 0xf9b9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf341, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe1cb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf1be, 0x0000, 0x0000, 0x0000, 0xe3fc, 0xecf0, 0xf1fa,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xefe4, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe5ed, 0xeedd, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe598, 0xedb7, 0x0000, 0x0000,
+ 0x0000, 0xe8e7, 0xec4f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf25b,
+ 0x0000, 0x0000, 0xe6f4, 0xf36d, 0x0000, 0x0000, 0x0000, 0xe23b
+};
+
+static unsigned short johab_from_unicode_86[] = {
+ 0x0000, 0x0000, 0xeede, 0x0000, 0x0000, 0x0000, 0xe458, 0xebcc,
+ 0x0000, 0x0000, 0xef43, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xedee, 0xe932,
+ 0x0000, 0x0000, 0xeb60, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3f0, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3dd,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf8db, 0x0000,
+ 0xf7cb, 0x0000, 0x0000, 0x0000, 0xe0f3, 0xf535, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf858, 0xe459, 0x0000, 0xefe5, 0xf8dc,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf9d0,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf8f6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe835, 0x0000, 0xe8bd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf172, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe1f7, 0xf36e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf659, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xea91,
+ 0x0000, 0x0000, 0x0000, 0xe4b1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf97e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xef53, 0x0000, 0xf3c8, 0x0000, 0x0000, 0x0000, 0xe293,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf7ed, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf496, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xed46, 0x0000
+};
+
+static unsigned short johab_from_unicode_87[] = {
+ 0xf5b9, 0x0000, 0xe992, 0xecf1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xef35, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf44b, 0x0000, 0xea34, 0x0000, 0xe85c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe079, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xecda, 0x0000, 0xf969,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf06a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf7c4, 0x0000,
+ 0xeca4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf8dd, 0x0000, 0xf2ca, 0x0000,
+ 0xef54, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe5cc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf0d7, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7ad,
+ 0x0000, 0x0000, 0xf8ab, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe4d9, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe3de, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf66e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe898, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xeb61, 0x0000, 0x0000, 0xefa8,
+ 0x0000, 0x0000, 0xf5f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf83f, 0x0000, 0xf0fc, 0x0000, 0x0000, 0xeb7a, 0x0000
+};
+
+static unsigned short johab_from_unicode_88[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xecb2, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe433,
+ 0x0000, 0x0000, 0xf3e3, 0xe5ee, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe1cc, 0x0000, 0x0000, 0x0000, 0x0000, 0xf1d9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe751, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf87c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf3eb, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf831, 0xee72, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf875, 0xec9c, 0x0000, 0x0000, 0x0000, 0xe046,
+ 0x0000, 0xed47, 0x0000, 0xf06b, 0x0000, 0xf5fa, 0x0000, 0x0000,
+ 0x0000, 0xf8ac, 0xe2c3, 0xf0fd, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf79c, 0x0000, 0x0000, 0xeab9, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xebf1, 0x0000, 0xe434, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5fb,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe36a, 0xe36b,
+ 0x0000, 0xf04e, 0xe7b1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe047, 0x0000, 0x0000, 0xe4e7, 0x0000, 0xf775, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe4b2, 0x0000, 0x0000, 0x0000, 0xec50, 0xf46f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe1e5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf7ac, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe1cd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf23e, 0xe63e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe6ea,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xeee0, 0xf0ae, 0x0000, 0x0000,
+ 0x0000, 0xe2d9, 0x0000, 0x0000, 0xe95d, 0xf1fb, 0x0000, 0xea92,
+ 0x0000, 0xe6eb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xea35, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xead7, 0xe8d0, 0xe8d1, 0x0000, 0x0000,
+ 0xe3df, 0x0000, 0x0000, 0x0000, 0x0000, 0xf342, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_89[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe96c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe078, 0x0000, 0xf776, 0xe95e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf06c, 0xe8d2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xefb3, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf6db, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeca8, 0x0000,
+ 0xe6ae, 0x0000, 0x0000, 0xeb71, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe0ba, 0x0000, 0x0000, 0xedd1, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe36c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe3fd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe75a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xeca9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeb34,
+ 0x0000, 0xefa9, 0x0000, 0xe4c7, 0x0000, 0x0000, 0xe96d, 0xf73e,
+ 0x0000, 0x0000, 0x0000, 0xe148, 0x0000, 0x0000, 0x0000, 0xe33e,
+ 0x0000, 0x0000, 0x0000, 0xe794, 0x0000, 0x0000, 0xecca, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe13f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe53d, 0xf661, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe35c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe056, 0x0000, 0x0000, 0xe5c2, 0x0000, 0x0000,
+ 0xe24a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe057, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf840, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xead8, 0x0000, 0x0000, 0x0000,
+ 0xf5ba, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_8a[] = {
+ 0xedeb, 0x0000, 0xf2f4, 0xe9b5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe1aa, 0x0000, 0xecf2, 0x0000, 0xf8f7, 0x0000, 0xf6d0, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf9ba, 0x0000, 0x0000, 0xf9e1, 0xf6a0,
+ 0xe3c0, 0x0000, 0x0000, 0xef55, 0x0000, 0xed48, 0x0000, 0xebe8,
+ 0x0000, 0x0000, 0x0000, 0xe151, 0x0000, 0xe47d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe8be, 0x0000, 0x0000, 0xeb72, 0x0000, 0x0000,
+ 0x0000, 0xf859, 0x0000, 0x0000, 0xebcd, 0x0000, 0xe048, 0x0000,
+ 0x0000, 0x0000, 0xf470, 0xf3c9, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xea93, 0x0000, 0x0000, 0x0000, 0xf36f, 0xf754, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf25c, 0x0000, 0x0000, 0xea94, 0x0000,
+ 0xeec9, 0x0000, 0xec95, 0xeee1, 0x0000, 0x0000, 0xeccb, 0x0000,
+ 0x0000, 0xeccc, 0x0000, 0x0000, 0x0000, 0xe2f8, 0xf2ac, 0x0000,
+ 0xf9fe, 0xf935, 0xf841, 0xead9, 0x0000, 0xeb62, 0x0000, 0x0000,
+ 0x0000, 0xf56a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf3ca, 0x0000, 0xe233,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf44c, 0xf173, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xeb35, 0x0000, 0xf6ab, 0x0000, 0x0000,
+ 0xf0af, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xedde, 0x0000,
+ 0xeba4, 0xe1ab, 0x0000, 0xe7f4, 0xef36, 0xe1ce, 0xebe9, 0x0000,
+ 0xf991, 0x0000, 0xeb73, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xec51, 0x0000, 0xe234, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xea36, 0x0000, 0x0000, 0xf0fe, 0x0000, 0xf0dd, 0xf370,
+ 0x0000, 0x0000, 0xf56b, 0x0000, 0xec96, 0x0000, 0x0000, 0xe4c8,
+ 0x0000, 0x0000, 0x0000, 0xf57b, 0x0000, 0xf245, 0x0000, 0xf5d8,
+ 0x0000, 0x0000, 0xe5df, 0x0000, 0x0000, 0x0000, 0xe465, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf0b0, 0xf573, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeccd, 0x0000, 0x0000, 0x0000, 0x0000, 0xf596, 0xf842,
+ 0x0000, 0x0000, 0xf2f5, 0xe06f, 0x0000, 0xf0b1, 0xf1bf, 0x0000,
+ 0x0000, 0xf9c9, 0x0000, 0x0000, 0x0000, 0x0000, 0xed36, 0xf7a4,
+ 0xf343, 0x0000, 0xedec, 0x0000, 0x0000, 0x0000, 0xe3e7, 0x0000
+};
+
+static unsigned short johab_from_unicode_8b[] = {
+ 0xe7c7, 0xed67, 0xf06d, 0x0000, 0xe599, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe84a, 0x0000,
+ 0xe85d, 0x0000, 0x0000, 0x0000, 0xf7cc, 0x0000, 0xebda, 0xe8bf,
+ 0x0000, 0xe155, 0xf160, 0xe0bb, 0x0000, 0xea95, 0x0000, 0x0000,
+ 0xefaa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe7c8, 0x0000, 0x0000, 0xf273, 0xe6bd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe2c4, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe35d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf936, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf3fb, 0x0000, 0x0000, 0x0000, 0x0000, 0xf9d2, 0xe3c1,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xecdb, 0x0000, 0xe4c9, 0x0000, 0xe95f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe17d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xea37, 0x0000, 0x0000, 0xee4b,
+ 0xf131, 0x0000, 0x0000, 0x0000, 0xe149, 0x0000, 0x0000, 0xf8de,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeee2, 0x0000, 0x0000,
+ 0xe551, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe938, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xec52, 0x0000, 0xf4d8, 0xedd3, 0x0000, 0x0000, 0xf4d9, 0x0000,
+ 0x0000, 0x0000, 0xf4c6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_8c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe1db,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe1ac,
+ 0x0000, 0xf953, 0x0000, 0x0000, 0x0000, 0x0000, 0xe577, 0x0000,
+ 0xe0d0, 0x0000, 0xf7a5, 0x0000, 0xef65, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xecce, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe55a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeada, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf8df, 0xeee3, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf79d, 0xeccf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf5b0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe777, 0x0000, 0xe7c9, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf73f, 0xf2f6, 0x0000,
+ 0xe9b6, 0xf23f, 0xe1f8, 0x0000, 0x0000, 0x0000, 0x0000, 0xea48,
+ 0xf937, 0xf6fc, 0xf6b1, 0xe24b, 0xf531, 0x0000, 0x0000, 0xf25d,
+ 0xebae, 0x0000, 0x0000, 0xf153, 0xe2fe, 0x0000, 0xf74f, 0xe772,
+ 0xe4e8, 0x0000, 0x0000, 0xea38, 0xf574, 0xf152, 0x0000, 0xe7f5,
+ 0xf7c5, 0xe9d3, 0xe471, 0xf19e, 0xf992, 0x0000, 0x0000, 0xf1c0,
+ 0xe049, 0x0000, 0xf274, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf471, 0x0000, 0xea49, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe694, 0x0000, 0xea96, 0x0000, 0xeadb, 0x0000,
+ 0xe8d3, 0x0000, 0xf877, 0xe773, 0xf551, 0x0000, 0xe9b7, 0x0000,
+ 0x0000, 0x0000, 0xf497, 0x0000, 0x0000, 0xe53e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe695, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe9b8, 0xe2c5, 0xeadf, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_8d[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf44e, 0xf631, 0x0000, 0xf0cb,
+ 0xf3fc, 0x0000, 0xf4c7, 0x0000, 0x0000, 0xeb7b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf1fc, 0x0000, 0x0000, 0xebdb, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf275, 0x0000, 0xea97, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf863, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf3cb, 0x0000, 0x0000, 0xe33f, 0xe9b9, 0x0000, 0x0000, 0xe3c3,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5b1, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf056, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf371, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf63c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf5d9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf37b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe9ba, 0x0000, 0x0000, 0x0000, 0xf44f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf6c5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe8a2, 0xf498, 0x0000, 0x0000, 0xe04a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf6f5, 0x0000, 0xe0e5, 0x0000, 0x0000,
+ 0x0000, 0xf276, 0x0000, 0xeb63, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe235, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe45a,
+ 0x0000, 0x0000, 0x0000, 0xe53f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_8e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xefc9, 0x0000, 0x0000, 0x0000, 0x0000, 0xe4ce,
+ 0xf552, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe0e6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf3a1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf0b2, 0x0000, 0x0000, 0x0000, 0x0000, 0xf3a2, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf0b3, 0x0000, 0xf344, 0x0000, 0x0000, 0xe0f4,
+ 0xe540, 0xf4b2, 0xf8b7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf5ec, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf277,
+ 0xf542, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf5ed, 0x0000, 0xe2f3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf372, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf25e,
+ 0x0000, 0x0000, 0xf3cc, 0x0000, 0x0000, 0xedb8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe6f5, 0xecf3, 0xe2e5, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe2c6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe0e7, 0xed68, 0xe2f9, 0xe2da, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf85d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xee73,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf472, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf5ee, 0x0000, 0x0000, 0xe04b, 0x0000, 0x0000, 0xecdc, 0x0000
+};
+
+static unsigned short johab_from_unicode_8f[] = {
+ 0x0000, 0x0000, 0x0000, 0xe294, 0x0000, 0xe669, 0x0000, 0x0000,
+ 0x0000, 0xf240, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf575, 0xe752, 0xe960, 0xe17e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe5e0, 0xf65a, 0xf9ca, 0xe766, 0xf55f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe636, 0xe94e,
+ 0x0000, 0xe8d4, 0xe6c7, 0x0000, 0x0000, 0x0000, 0x0000, 0xf4a0,
+ 0x0000, 0x0000, 0x0000, 0xf3cd, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xec53, 0xe96e, 0x0000, 0xe96f, 0x0000, 0x0000, 0xf2ad, 0xee3b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf7dd, 0xf04f, 0x0000, 0x0000,
+ 0x0000, 0xf2ae, 0x0000, 0x0000, 0x0000, 0xf560, 0xe295, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xee3c, 0x0000, 0xe26e,
+ 0x0000, 0x0000, 0xe5f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xecf4, 0xe1d0, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe5b8, 0x0000, 0x0000, 0xf6fd, 0x0000,
+ 0xe939, 0x0000, 0x0000, 0x0000, 0x0000, 0xea98, 0x0000, 0xe93a,
+ 0xecf5, 0xefb4, 0xe46c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xefe6, 0x0000, 0x0000, 0xecf6, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeeca, 0x0000,
+ 0x0000, 0xe35e, 0x0000, 0x0000, 0xe899, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe04c, 0x0000,
+ 0x0000, 0x0000, 0xf278, 0xe86e, 0x0000, 0xf499, 0x0000, 0x0000,
+ 0xec9d, 0x0000, 0xe136, 0x0000, 0x0000, 0x0000, 0x0000, 0xe84b,
+ 0x0000, 0xf279, 0x0000, 0x0000, 0x0000, 0xf5da, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_90[] = {
+ 0xf6dc, 0xebea, 0xe251, 0xe541, 0x0000, 0xf9b1, 0xee4d, 0x0000,
+ 0xf8ad, 0x0000, 0x0000, 0xf777, 0x0000, 0xebce, 0x0000, 0xf6e2,
+ 0xf5ef, 0xe2c7, 0x0000, 0x0000, 0xe542, 0xe191, 0x0000, 0xe578,
+ 0x0000, 0xf25f, 0xf6d7, 0x0000, 0x0000, 0xeb36, 0xe651, 0xebdc,
+ 0xf373, 0xf3e4, 0xe993, 0xe637, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf597, 0x0000,
+ 0x0000, 0xf3ce, 0xf474, 0x0000, 0x0000, 0xe340, 0x0000, 0x0000,
+ 0xf191, 0x0000, 0x0000, 0x0000, 0xf7ba, 0x0000, 0xf0b5, 0x0000,
+ 0x0000, 0xe57d, 0xec54, 0x0000, 0x0000, 0x0000, 0x0000, 0xefe7,
+ 0x0000, 0x0000, 0xf0b4, 0xf031, 0x0000, 0xf74c, 0xe236, 0x0000,
+ 0xf7c6, 0xf96a, 0x0000, 0xe543, 0xe4b9, 0xf06e, 0x0000, 0x0000,
+ 0x0000, 0xefab, 0x0000, 0x0000, 0xebe1, 0xe4cf, 0xf598, 0x0000,
+ 0xf050, 0xebcf, 0x0000, 0xe14a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf27a, 0x0000, 0x0000, 0x0000, 0xf374, 0xf4b4, 0xe57e,
+ 0x0000, 0x0000, 0xf450, 0x0000, 0x0000, 0xf3e5, 0x0000, 0xf553,
+ 0xeb64, 0x0000, 0xf0b6, 0x0000, 0xe6a1, 0xe0e8, 0x0000, 0xf7ad,
+ 0xefad, 0xe774, 0xf843, 0xec55, 0xf94d, 0x0000, 0x0000, 0xf154,
+ 0xe741, 0x0000, 0xe93b, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3e0,
+ 0x0000, 0xf0e9, 0x0000, 0x0000, 0x0000, 0xef4b, 0x0000, 0x0000,
+ 0x0000, 0xe767, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf8ae, 0xe3e1, 0x0000, 0x0000, 0xe8c0, 0x0000,
+ 0xf5be, 0x0000, 0xea99, 0x0000, 0x0000, 0x0000, 0x0000, 0xe09d,
+ 0xf6c6, 0xe2c8, 0x0000, 0x0000, 0x0000, 0xebd0, 0x0000, 0x0000,
+ 0xf260, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeff4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe296, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe43b, 0x0000,
+ 0x0000, 0xe2db, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe9bb, 0x0000, 0x0000, 0x0000, 0x0000, 0xe23c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xefe8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe544, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_91[] = {
+ 0x0000, 0x0000, 0xed57, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf5db, 0x0000, 0x0000, 0xf851, 0x0000, 0x0000,
+ 0x0000, 0xea39, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe59a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf2f7, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe4b3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf0b7, 0xf2f8, 0xf5dc, 0xf1cc, 0xe8d5, 0xf3cf, 0x0000,
+ 0x0000, 0x0000, 0xf3d0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf5b2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe7ae, 0xe3e8, 0x0000, 0xec56, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf9a3, 0x0000, 0xf8e5,
+ 0xeaab, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xec97,
+ 0x0000, 0xf63d, 0x0000, 0xf5b3, 0x0000, 0xf345, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xeba5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf5dd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf132, 0xf1fd, 0x0000, 0xf5b4, 0xf8b8,
+ 0x0000, 0xe8a3, 0x0000, 0x0000, 0xe65a, 0xe0d9, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xedd4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf4fa,
+ 0x0000, 0xf0b8, 0x0000, 0xeb47, 0xe6ec, 0xf3ec, 0xedaf, 0xe5e1,
+ 0xe6ed, 0xe36d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xebf2,
+ 0xf2f9, 0x0000, 0x0000, 0x0000, 0xe9bc, 0xf66c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf375, 0x0000, 0x0000, 0x0000, 0xf554,
+ 0x0000, 0x0000, 0xefe9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf4fb, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_92[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe591, 0x0000, 0x0000,
+ 0xe132, 0xf6fe, 0xeabc, 0x0000, 0x0000, 0x0000, 0x0000, 0xf0cd,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe347, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe652, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xef3d, 0x0000, 0x0000, 0x0000, 0x0000, 0xf2af,
+ 0xe0a5, 0x0000, 0x0000, 0x0000, 0x0000, 0xe0e9, 0x0000, 0x0000,
+ 0x0000, 0xf878, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe156,
+ 0x0000, 0x0000, 0x0000, 0xee77, 0x0000, 0x0000, 0xf057, 0x0000,
+ 0x0000, 0x0000, 0xe8a4, 0x0000, 0xe2c9, 0xec9e, 0xf2fa, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf0de, 0x0000, 0x0000, 0xf5c8, 0x0000, 0xe56e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xeb65, 0x0000, 0xf2b0, 0x0000, 0x0000, 0xec57, 0x0000,
+ 0xe7af, 0x0000, 0x0000, 0x0000, 0xf7e7, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xeee5, 0x0000, 0x0000, 0xe2ca, 0xebd1,
+ 0x0000, 0xec58, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf2fb, 0x0000, 0x0000, 0xf89b,
+ 0x0000, 0x0000, 0xe994, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xeb37, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf778, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe0ea, 0x0000, 0x0000, 0x0000, 0xe0bc, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_93[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe463, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf5de, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf5df, 0x0000, 0xf246, 0x0000, 0x0000, 0x0000, 0xec98, 0xe4ca,
+ 0xf2fc, 0xe3c4, 0xf2b1, 0x0000, 0xe3c5, 0x0000, 0xe36e, 0x0000,
+ 0xe7e1, 0x0000, 0x0000, 0xeb48, 0x0000, 0x0000, 0xe1d1, 0xf4b9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xeecc, 0x0000, 0xe638, 0xe237, 0x0000, 0xe545, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xed58, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe4b4, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf0b9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe0f5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf66d, 0x0000, 0xf3a3, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe157, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xefca, 0x0000, 0xebf0, 0x0000,
+ 0x0000, 0x0000, 0xf5e0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf8af, 0x0000, 0x0000, 0x0000, 0xe0d1,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf8e0, 0xf475, 0x0000, 0x0000,
+ 0xf192, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf37c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf27b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xefcb, 0x0000,
+ 0x0000, 0xe192, 0x0000, 0x0000, 0xe6af, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf4a1, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_94[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf997, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf3a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeb66, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf2b2, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf561, 0x0000, 0x0000,
+ 0xf6a1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf3d1, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe09e, 0xe09f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe25e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf4c8, 0x0000, 0xf4ba,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_95[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf1fe,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe836, 0x0000, 0x0000, 0xeb7c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf75d, 0x0000, 0xe0d2, 0x0000, 0x0000, 0x0000, 0xf0ce,
+ 0x0000, 0xf7d8, 0xf7d9, 0xe070, 0xe85a, 0x0000, 0x0000, 0x0000,
+ 0xe0a6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe058, 0xf7ee, 0xe8ec, 0x0000, 0x0000,
+ 0xe341, 0x0000, 0x0000, 0x0000, 0x0000, 0xe5ef, 0x0000, 0x0000,
+ 0x0000, 0xee95, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xeea2, 0xed69, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xed71,
+ 0x0000, 0x0000, 0xf954, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf7ef, 0xe2f4, 0xf6e6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe24c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf555, 0xe933, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_96[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe9bd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf556, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf731, 0x0000, 0x0000, 0x0000, 0xef66, 0x0000,
+ 0x0000, 0x0000, 0xe8c1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf376, 0x0000, 0x0000, 0x0000, 0xed49,
+ 0xf67d, 0x0000, 0xf7ae, 0x0000, 0xe9be, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe47b, 0xe778, 0xe0bd, 0x0000, 0x0000,
+ 0xf7da, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf75e, 0xf7f0, 0xeb7d, 0xecb3, 0xf543,
+ 0x0000, 0x0000, 0xf052, 0xf476, 0xf346, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe8d6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf0e4, 0x0000, 0x0000, 0xf477, 0x0000, 0xe49a, 0xe546, 0xf7e8,
+ 0xe6c1, 0x0000, 0x0000, 0x0000, 0x0000, 0xedd5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xefea, 0xe6cc, 0x0000,
+ 0x0000, 0x0000, 0xe4e9, 0xec59, 0x0000, 0xf96b, 0xe1ad, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe140, 0xf032, 0x0000, 0x0000,
+ 0xed98, 0xe350, 0x0000, 0xf347, 0xf231, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe6f6, 0x0000, 0x0000, 0x0000, 0xec5a,
+ 0xec5b, 0x0000, 0xf85f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf0df, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe65b,
+ 0x0000, 0x0000, 0x0000, 0xf544, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf1cd, 0xed62, 0x0000, 0x0000, 0xf039, 0xed4a, 0xf4a2, 0xe1d2,
+ 0x0000, 0xf65b, 0x0000, 0xf3e6, 0xf1c1, 0xef4c, 0xf261, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf377, 0xec5c, 0x0000,
+ 0x0000, 0xed3a, 0x0000, 0xf5e1, 0xf1da, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe6ee, 0xe3f1, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xefeb, 0xefec, 0xeb74, 0x0000, 0x0000, 0x0000, 0x0000, 0xe837,
+ 0xe9d4, 0x0000, 0xf033, 0x0000, 0x0000, 0x0000, 0xe653, 0xe472,
+ 0x0000, 0xe86f, 0x0000, 0xf2b3, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_97[] = {
+ 0xec5d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf2fd, 0xf478,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf2c5, 0x0000, 0xeee7, 0x0000, 0x0000, 0xe6fd, 0x0000,
+ 0x0000, 0xeece, 0x0000, 0x0000, 0xeadc, 0x0000, 0xf7c7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe7f6,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xeaac, 0x0000, 0xe45b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe934, 0x0000, 0x0000, 0x0000, 0xf348, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe5fa, 0x0000, 0xed99, 0x0000, 0x0000, 0x0000,
+ 0xe654, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf57c, 0x0000, 0x0000, 0x0000, 0x0000, 0xf2fe, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf331, 0x0000, 0xea3a, 0x0000,
+ 0x0000, 0xe84c, 0xe79e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf864, 0x0000, 0x0000, 0x0000, 0xf175, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf938, 0x0000, 0x0000, 0xf176,
+ 0x0000, 0x0000, 0xe75b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf8b9, 0x0000, 0xed63, 0x0000, 0xe1f9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe2d3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe07a, 0x0000, 0x0000, 0xe2d4, 0x0000, 0xf74d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf557, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf06f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf7db, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe547, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf0e5, 0x0000, 0x0000, 0xebd2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf034, 0x0000, 0x0000, 0x0000, 0xf852
+};
+
+static unsigned short johab_from_unicode_98[] = {
+ 0xf8e1, 0xf87d, 0xf332, 0xe193, 0x0000, 0xf833, 0xec99, 0x0000,
+ 0xec5e, 0x0000, 0xeff5, 0x0000, 0xebeb, 0x0000, 0x0000, 0x0000,
+ 0xeee8, 0xef67, 0xe89a, 0xe55b, 0x0000, 0x0000, 0x0000, 0xf6f6,
+ 0xe655, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe579, 0x0000, 0x0000,
+ 0xf89c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe194, 0xf6dd, 0x0000, 0xea4a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe238, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf349, 0xeda0, 0xed59, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xed64, 0x0000, 0x0000, 0x0000,
+ 0xf053, 0x0000, 0xf2b4, 0x0000, 0x0000, 0x0000, 0xe6be, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf8e2, 0x0000, 0xe1d3,
+ 0x0000, 0x0000, 0x0000, 0xf2b5, 0x0000, 0x0000, 0x0000, 0xf879,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf7a6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeabd,
+ 0x0000, 0xf6c7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf79f, 0x0000, 0x0000, 0xf79e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xea3b, 0xe8e8, 0x0000, 0x0000, 0xecdd,
+ 0x0000, 0xebe2, 0xe3c6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf660, 0xf0e6, 0xe89b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf157, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xea9a, 0xf779, 0xecde, 0x0000
+};
+
+static unsigned short johab_from_unicode_99[] = {
+ 0x0000, 0x0000, 0x0000, 0xe297, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf853, 0xedd7, 0x0000, 0xf158, 0x0000, 0x0000, 0x0000,
+ 0xf4c9, 0x0000, 0x0000, 0xed4b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xee3e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf2b6, 0x0000,
+ 0xe94f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe24d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe753, 0x0000, 0x0000,
+ 0x0000, 0xe35f, 0x0000, 0xe2fa, 0xf4ca, 0xeb67, 0x0000, 0x0000,
+ 0x0000, 0xe3c7, 0xefae, 0x0000, 0xef4d, 0x0000, 0x0000, 0xf854,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xec5f, 0x0000,
+ 0x0000, 0xf855, 0x0000, 0x0000, 0x0000, 0xf7b8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe970, 0x0000, 0x0000,
+ 0xf8b0, 0x0000, 0x0000, 0x0000, 0xe739, 0xeddf, 0xf7a7, 0x0000,
+ 0x0000, 0xf67e, 0x0000, 0xf65c, 0xec9a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf193, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe870, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf3d2, 0xe45c, 0xe2cb, 0x0000, 0x0000, 0xe04d, 0x0000, 0x0000,
+ 0x0000, 0xe9bf, 0x0000, 0x0000, 0x0000, 0xf691, 0x0000, 0xea9b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf844, 0x0000, 0x0000,
+ 0x0000, 0xe3e9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf3e7
+};
+
+static unsigned short johab_from_unicode_9a[] = {
+ 0x0000, 0xea4e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe950, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3c8, 0xe3c9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf74e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe0f6, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe59b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5e2, 0xebd3,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe779, 0x0000, 0x0000, 0xf7a0, 0x0000, 0xe2cc, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf9a4, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe298, 0x0000, 0xf860,
+ 0x0000, 0x0000, 0xe195, 0xee4e, 0x0000, 0x0000, 0x0000, 0xf63e,
+ 0x0000, 0x0000, 0xe5f0, 0x0000, 0x0000, 0xe3ca, 0x0000, 0x0000,
+ 0x0000, 0xf94e, 0xe5f1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe1e9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf845, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xec60, 0xf599, 0x0000, 0x0000, 0x0000,
+ 0xe1d4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeea3, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe8a5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_9b[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xec61, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe6a2,
+ 0x0000, 0x0000, 0xf6e3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xf036, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe331, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe26a, 0xf8eb, 0xe8a6, 0xe8de, 0xe775, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf070,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe73a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xede0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe45d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf2c6, 0x0000,
+ 0x0000, 0xf77a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xed65,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe299, 0x0000, 0x0000, 0xeb68, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe6ef, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf57d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe1e6, 0x0000, 0x0000, 0x0000,
+ 0xe196, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_9c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5e3, 0x0000, 0x0000,
+ 0xed5a, 0x0000, 0xe971, 0x0000, 0x0000, 0xf7c8, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf94f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xef37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe754, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe0be,
+ 0x0000, 0xe93e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe6f7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf378, 0x0000, 0xe9c0,
+ 0x0000, 0xe2cd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe995, 0xe7b0, 0x0000, 0xee79, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_9d[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xed4c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf054, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xed7c, 0x0000,
+ 0xed75, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf8f8, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe14b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xed4d, 0x0000, 0x0000,
+ 0xe1dc, 0xe7f7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe9df, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf1ce, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xe7d0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeda3,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xf7cd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe1ae, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe2ce,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf63f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xf9d3, 0xf0ed, 0xe45e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_9e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xeda4, 0x0000, 0x0000, 0x0000, 0xe3f2, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe66d, 0x0000, 0x0000,
+ 0x0000, 0xf7e9, 0x0000, 0x0000, 0x0000, 0xeea4, 0x0000, 0xe464,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xe3cb, 0xe674, 0x0000, 0x0000, 0x0000, 0xe5f2,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xea9c, 0x0000, 0xe6f8,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe77a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe2d5, 0xe79f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe73b, 0x0000, 0x0000, 0xf9cb, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf96c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeb38, 0xe5f3, 0x0000,
+ 0x0000, 0xf9d9, 0x0000, 0x0000, 0xe133, 0x0000, 0x0000, 0x0000,
+ 0xe7f9, 0x0000, 0x0000, 0xe4ea, 0xf5f5, 0x0000, 0xf2c7, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xe4da, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe84d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_9f[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xef38,
+ 0xe93f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf333, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xe1d5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xeb39, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xea3c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xf34a, 0xf241, 0x0000, 0x0000, 0xf242, 0x0000,
+ 0x0000, 0x0000, 0xf65d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf262,
+ 0x0000, 0xe656, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeb75,
+ 0x0000, 0x0000, 0xf4bb, 0x0000, 0xede1, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xed5b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe6a3, 0x0000, 0x0000,
+ 0xe8c2, 0x0000, 0x0000, 0x0000, 0x0000, 0xe0a0, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xe2cf, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_ac[] = {
+ 0x8861, 0x8862, 0x8863, 0x8864, 0x8865, 0x8866, 0x8867, 0x8868,
+ 0x8869, 0x886a, 0x886b, 0x886c, 0x886d, 0x886e, 0x886f, 0x8870,
+ 0x8871, 0x8873, 0x8874, 0x8875, 0x8876, 0x8877, 0x8878, 0x8879,
+ 0x887a, 0x887b, 0x887c, 0x887d, 0x8881, 0x8882, 0x8883, 0x8884,
+ 0x8885, 0x8886, 0x8887, 0x8888, 0x8889, 0x888a, 0x888b, 0x888c,
+ 0x888d, 0x888e, 0x888f, 0x8890, 0x8891, 0x8893, 0x8894, 0x8895,
+ 0x8896, 0x8897, 0x8898, 0x8899, 0x889a, 0x889b, 0x889c, 0x889d,
+ 0x88a1, 0x88a2, 0x88a3, 0x88a4, 0x88a5, 0x88a6, 0x88a7, 0x88a8,
+ 0x88a9, 0x88aa, 0x88ab, 0x88ac, 0x88ad, 0x88ae, 0x88af, 0x88b0,
+ 0x88b1, 0x88b3, 0x88b4, 0x88b5, 0x88b6, 0x88b7, 0x88b8, 0x88b9,
+ 0x88ba, 0x88bb, 0x88bc, 0x88bd, 0x88c1, 0x88c2, 0x88c3, 0x88c4,
+ 0x88c5, 0x88c6, 0x88c7, 0x88c8, 0x88c9, 0x88ca, 0x88cb, 0x88cc,
+ 0x88cd, 0x88ce, 0x88cf, 0x88d0, 0x88d1, 0x88d3, 0x88d4, 0x88d5,
+ 0x88d6, 0x88d7, 0x88d8, 0x88d9, 0x88da, 0x88db, 0x88dc, 0x88dd,
+ 0x88e1, 0x88e2, 0x88e3, 0x88e4, 0x88e5, 0x88e6, 0x88e7, 0x88e8,
+ 0x88e9, 0x88ea, 0x88eb, 0x88ec, 0x88ed, 0x88ee, 0x88ef, 0x88f0,
+ 0x88f1, 0x88f3, 0x88f4, 0x88f5, 0x88f6, 0x88f7, 0x88f8, 0x88f9,
+ 0x88fa, 0x88fb, 0x88fc, 0x88fd, 0x8941, 0x8942, 0x8943, 0x8944,
+ 0x8945, 0x8946, 0x8947, 0x8948, 0x8949, 0x894a, 0x894b, 0x894c,
+ 0x894d, 0x894e, 0x894f, 0x8950, 0x8951, 0x8953, 0x8954, 0x8955,
+ 0x8956, 0x8957, 0x8958, 0x8959, 0x895a, 0x895b, 0x895c, 0x895d,
+ 0x8961, 0x8962, 0x8963, 0x8964, 0x8965, 0x8966, 0x8967, 0x8968,
+ 0x8969, 0x896a, 0x896b, 0x896c, 0x896d, 0x896e, 0x896f, 0x8970,
+ 0x8971, 0x8973, 0x8974, 0x8975, 0x8976, 0x8977, 0x8978, 0x8979,
+ 0x897a, 0x897b, 0x897c, 0x897d, 0x8981, 0x8982, 0x8983, 0x8984,
+ 0x8985, 0x8986, 0x8987, 0x8988, 0x8989, 0x898a, 0x898b, 0x898c,
+ 0x898d, 0x898e, 0x898f, 0x8990, 0x8991, 0x8993, 0x8994, 0x8995,
+ 0x8996, 0x8997, 0x8998, 0x8999, 0x899a, 0x899b, 0x899c, 0x899d,
+ 0x89a1, 0x89a2, 0x89a3, 0x89a4, 0x89a5, 0x89a6, 0x89a7, 0x89a8,
+ 0x89a9, 0x89aa, 0x89ab, 0x89ac, 0x89ad, 0x89ae, 0x89af, 0x89b0,
+ 0x89b1, 0x89b3, 0x89b4, 0x89b5, 0x89b6, 0x89b7, 0x89b8, 0x89b9,
+ 0x89ba, 0x89bb, 0x89bc, 0x89bd, 0x89c1, 0x89c2, 0x89c3, 0x89c4
+};
+
+static unsigned short johab_from_unicode_ad[] = {
+ 0x89c5, 0x89c6, 0x89c7, 0x89c8, 0x89c9, 0x89ca, 0x89cb, 0x89cc,
+ 0x89cd, 0x89ce, 0x89cf, 0x89d0, 0x89d1, 0x89d3, 0x89d4, 0x89d5,
+ 0x89d6, 0x89d7, 0x89d8, 0x89d9, 0x89da, 0x89db, 0x89dc, 0x89dd,
+ 0x89e1, 0x89e2, 0x89e3, 0x89e4, 0x89e5, 0x89e6, 0x89e7, 0x89e8,
+ 0x89e9, 0x89ea, 0x89eb, 0x89ec, 0x89ed, 0x89ee, 0x89ef, 0x89f0,
+ 0x89f1, 0x89f3, 0x89f4, 0x89f5, 0x89f6, 0x89f7, 0x89f8, 0x89f9,
+ 0x89fa, 0x89fb, 0x89fc, 0x89fd, 0x8a41, 0x8a42, 0x8a43, 0x8a44,
+ 0x8a45, 0x8a46, 0x8a47, 0x8a48, 0x8a49, 0x8a4a, 0x8a4b, 0x8a4c,
+ 0x8a4d, 0x8a4e, 0x8a4f, 0x8a50, 0x8a51, 0x8a53, 0x8a54, 0x8a55,
+ 0x8a56, 0x8a57, 0x8a58, 0x8a59, 0x8a5a, 0x8a5b, 0x8a5c, 0x8a5d,
+ 0x8a61, 0x8a62, 0x8a63, 0x8a64, 0x8a65, 0x8a66, 0x8a67, 0x8a68,
+ 0x8a69, 0x8a6a, 0x8a6b, 0x8a6c, 0x8a6d, 0x8a6e, 0x8a6f, 0x8a70,
+ 0x8a71, 0x8a73, 0x8a74, 0x8a75, 0x8a76, 0x8a77, 0x8a78, 0x8a79,
+ 0x8a7a, 0x8a7b, 0x8a7c, 0x8a7d, 0x8a81, 0x8a82, 0x8a83, 0x8a84,
+ 0x8a85, 0x8a86, 0x8a87, 0x8a88, 0x8a89, 0x8a8a, 0x8a8b, 0x8a8c,
+ 0x8a8d, 0x8a8e, 0x8a8f, 0x8a90, 0x8a91, 0x8a93, 0x8a94, 0x8a95,
+ 0x8a96, 0x8a97, 0x8a98, 0x8a99, 0x8a9a, 0x8a9b, 0x8a9c, 0x8a9d,
+ 0x8aa1, 0x8aa2, 0x8aa3, 0x8aa4, 0x8aa5, 0x8aa6, 0x8aa7, 0x8aa8,
+ 0x8aa9, 0x8aaa, 0x8aab, 0x8aac, 0x8aad, 0x8aae, 0x8aaf, 0x8ab0,
+ 0x8ab1, 0x8ab3, 0x8ab4, 0x8ab5, 0x8ab6, 0x8ab7, 0x8ab8, 0x8ab9,
+ 0x8aba, 0x8abb, 0x8abc, 0x8abd, 0x8ac1, 0x8ac2, 0x8ac3, 0x8ac4,
+ 0x8ac5, 0x8ac6, 0x8ac7, 0x8ac8, 0x8ac9, 0x8aca, 0x8acb, 0x8acc,
+ 0x8acd, 0x8ace, 0x8acf, 0x8ad0, 0x8ad1, 0x8ad3, 0x8ad4, 0x8ad5,
+ 0x8ad6, 0x8ad7, 0x8ad8, 0x8ad9, 0x8ada, 0x8adb, 0x8adc, 0x8add,
+ 0x8ae1, 0x8ae2, 0x8ae3, 0x8ae4, 0x8ae5, 0x8ae6, 0x8ae7, 0x8ae8,
+ 0x8ae9, 0x8aea, 0x8aeb, 0x8aec, 0x8aed, 0x8aee, 0x8aef, 0x8af0,
+ 0x8af1, 0x8af3, 0x8af4, 0x8af5, 0x8af6, 0x8af7, 0x8af8, 0x8af9,
+ 0x8afa, 0x8afb, 0x8afc, 0x8afd, 0x8b41, 0x8b42, 0x8b43, 0x8b44,
+ 0x8b45, 0x8b46, 0x8b47, 0x8b48, 0x8b49, 0x8b4a, 0x8b4b, 0x8b4c,
+ 0x8b4d, 0x8b4e, 0x8b4f, 0x8b50, 0x8b51, 0x8b53, 0x8b54, 0x8b55,
+ 0x8b56, 0x8b57, 0x8b58, 0x8b59, 0x8b5a, 0x8b5b, 0x8b5c, 0x8b5d,
+ 0x8b61, 0x8b62, 0x8b63, 0x8b64, 0x8b65, 0x8b66, 0x8b67, 0x8b68
+};
+
+static unsigned short johab_from_unicode_ae[] = {
+ 0x8b69, 0x8b6a, 0x8b6b, 0x8b6c, 0x8b6d, 0x8b6e, 0x8b6f, 0x8b70,
+ 0x8b71, 0x8b73, 0x8b74, 0x8b75, 0x8b76, 0x8b77, 0x8b78, 0x8b79,
+ 0x8b7a, 0x8b7b, 0x8b7c, 0x8b7d, 0x8b81, 0x8b82, 0x8b83, 0x8b84,
+ 0x8b85, 0x8b86, 0x8b87, 0x8b88, 0x8b89, 0x8b8a, 0x8b8b, 0x8b8c,
+ 0x8b8d, 0x8b8e, 0x8b8f, 0x8b90, 0x8b91, 0x8b93, 0x8b94, 0x8b95,
+ 0x8b96, 0x8b97, 0x8b98, 0x8b99, 0x8b9a, 0x8b9b, 0x8b9c, 0x8b9d,
+ 0x8ba1, 0x8ba2, 0x8ba3, 0x8ba4, 0x8ba5, 0x8ba6, 0x8ba7, 0x8ba8,
+ 0x8ba9, 0x8baa, 0x8bab, 0x8bac, 0x8bad, 0x8bae, 0x8baf, 0x8bb0,
+ 0x8bb1, 0x8bb3, 0x8bb4, 0x8bb5, 0x8bb6, 0x8bb7, 0x8bb8, 0x8bb9,
+ 0x8bba, 0x8bbb, 0x8bbc, 0x8bbd, 0x8c61, 0x8c62, 0x8c63, 0x8c64,
+ 0x8c65, 0x8c66, 0x8c67, 0x8c68, 0x8c69, 0x8c6a, 0x8c6b, 0x8c6c,
+ 0x8c6d, 0x8c6e, 0x8c6f, 0x8c70, 0x8c71, 0x8c73, 0x8c74, 0x8c75,
+ 0x8c76, 0x8c77, 0x8c78, 0x8c79, 0x8c7a, 0x8c7b, 0x8c7c, 0x8c7d,
+ 0x8c81, 0x8c82, 0x8c83, 0x8c84, 0x8c85, 0x8c86, 0x8c87, 0x8c88,
+ 0x8c89, 0x8c8a, 0x8c8b, 0x8c8c, 0x8c8d, 0x8c8e, 0x8c8f, 0x8c90,
+ 0x8c91, 0x8c93, 0x8c94, 0x8c95, 0x8c96, 0x8c97, 0x8c98, 0x8c99,
+ 0x8c9a, 0x8c9b, 0x8c9c, 0x8c9d, 0x8ca1, 0x8ca2, 0x8ca3, 0x8ca4,
+ 0x8ca5, 0x8ca6, 0x8ca7, 0x8ca8, 0x8ca9, 0x8caa, 0x8cab, 0x8cac,
+ 0x8cad, 0x8cae, 0x8caf, 0x8cb0, 0x8cb1, 0x8cb3, 0x8cb4, 0x8cb5,
+ 0x8cb6, 0x8cb7, 0x8cb8, 0x8cb9, 0x8cba, 0x8cbb, 0x8cbc, 0x8cbd,
+ 0x8cc1, 0x8cc2, 0x8cc3, 0x8cc4, 0x8cc5, 0x8cc6, 0x8cc7, 0x8cc8,
+ 0x8cc9, 0x8cca, 0x8ccb, 0x8ccc, 0x8ccd, 0x8cce, 0x8ccf, 0x8cd0,
+ 0x8cd1, 0x8cd3, 0x8cd4, 0x8cd5, 0x8cd6, 0x8cd7, 0x8cd8, 0x8cd9,
+ 0x8cda, 0x8cdb, 0x8cdc, 0x8cdd, 0x8ce1, 0x8ce2, 0x8ce3, 0x8ce4,
+ 0x8ce5, 0x8ce6, 0x8ce7, 0x8ce8, 0x8ce9, 0x8cea, 0x8ceb, 0x8cec,
+ 0x8ced, 0x8cee, 0x8cef, 0x8cf0, 0x8cf1, 0x8cf3, 0x8cf4, 0x8cf5,
+ 0x8cf6, 0x8cf7, 0x8cf8, 0x8cf9, 0x8cfa, 0x8cfb, 0x8cfc, 0x8cfd,
+ 0x8d41, 0x8d42, 0x8d43, 0x8d44, 0x8d45, 0x8d46, 0x8d47, 0x8d48,
+ 0x8d49, 0x8d4a, 0x8d4b, 0x8d4c, 0x8d4d, 0x8d4e, 0x8d4f, 0x8d50,
+ 0x8d51, 0x8d53, 0x8d54, 0x8d55, 0x8d56, 0x8d57, 0x8d58, 0x8d59,
+ 0x8d5a, 0x8d5b, 0x8d5c, 0x8d5d, 0x8d61, 0x8d62, 0x8d63, 0x8d64,
+ 0x8d65, 0x8d66, 0x8d67, 0x8d68, 0x8d69, 0x8d6a, 0x8d6b, 0x8d6c
+};
+
+static unsigned short johab_from_unicode_af[] = {
+ 0x8d6d, 0x8d6e, 0x8d6f, 0x8d70, 0x8d71, 0x8d73, 0x8d74, 0x8d75,
+ 0x8d76, 0x8d77, 0x8d78, 0x8d79, 0x8d7a, 0x8d7b, 0x8d7c, 0x8d7d,
+ 0x8d81, 0x8d82, 0x8d83, 0x8d84, 0x8d85, 0x8d86, 0x8d87, 0x8d88,
+ 0x8d89, 0x8d8a, 0x8d8b, 0x8d8c, 0x8d8d, 0x8d8e, 0x8d8f, 0x8d90,
+ 0x8d91, 0x8d93, 0x8d94, 0x8d95, 0x8d96, 0x8d97, 0x8d98, 0x8d99,
+ 0x8d9a, 0x8d9b, 0x8d9c, 0x8d9d, 0x8da1, 0x8da2, 0x8da3, 0x8da4,
+ 0x8da5, 0x8da6, 0x8da7, 0x8da8, 0x8da9, 0x8daa, 0x8dab, 0x8dac,
+ 0x8dad, 0x8dae, 0x8daf, 0x8db0, 0x8db1, 0x8db3, 0x8db4, 0x8db5,
+ 0x8db6, 0x8db7, 0x8db8, 0x8db9, 0x8dba, 0x8dbb, 0x8dbc, 0x8dbd,
+ 0x8dc1, 0x8dc2, 0x8dc3, 0x8dc4, 0x8dc5, 0x8dc6, 0x8dc7, 0x8dc8,
+ 0x8dc9, 0x8dca, 0x8dcb, 0x8dcc, 0x8dcd, 0x8dce, 0x8dcf, 0x8dd0,
+ 0x8dd1, 0x8dd3, 0x8dd4, 0x8dd5, 0x8dd6, 0x8dd7, 0x8dd8, 0x8dd9,
+ 0x8dda, 0x8ddb, 0x8ddc, 0x8ddd, 0x8de1, 0x8de2, 0x8de3, 0x8de4,
+ 0x8de5, 0x8de6, 0x8de7, 0x8de8, 0x8de9, 0x8dea, 0x8deb, 0x8dec,
+ 0x8ded, 0x8dee, 0x8def, 0x8df0, 0x8df1, 0x8df3, 0x8df4, 0x8df5,
+ 0x8df6, 0x8df7, 0x8df8, 0x8df9, 0x8dfa, 0x8dfb, 0x8dfc, 0x8dfd,
+ 0x8e41, 0x8e42, 0x8e43, 0x8e44, 0x8e45, 0x8e46, 0x8e47, 0x8e48,
+ 0x8e49, 0x8e4a, 0x8e4b, 0x8e4c, 0x8e4d, 0x8e4e, 0x8e4f, 0x8e50,
+ 0x8e51, 0x8e53, 0x8e54, 0x8e55, 0x8e56, 0x8e57, 0x8e58, 0x8e59,
+ 0x8e5a, 0x8e5b, 0x8e5c, 0x8e5d, 0x8e61, 0x8e62, 0x8e63, 0x8e64,
+ 0x8e65, 0x8e66, 0x8e67, 0x8e68, 0x8e69, 0x8e6a, 0x8e6b, 0x8e6c,
+ 0x8e6d, 0x8e6e, 0x8e6f, 0x8e70, 0x8e71, 0x8e73, 0x8e74, 0x8e75,
+ 0x8e76, 0x8e77, 0x8e78, 0x8e79, 0x8e7a, 0x8e7b, 0x8e7c, 0x8e7d,
+ 0x8e81, 0x8e82, 0x8e83, 0x8e84, 0x8e85, 0x8e86, 0x8e87, 0x8e88,
+ 0x8e89, 0x8e8a, 0x8e8b, 0x8e8c, 0x8e8d, 0x8e8e, 0x8e8f, 0x8e90,
+ 0x8e91, 0x8e93, 0x8e94, 0x8e95, 0x8e96, 0x8e97, 0x8e98, 0x8e99,
+ 0x8e9a, 0x8e9b, 0x8e9c, 0x8e9d, 0x8ea1, 0x8ea2, 0x8ea3, 0x8ea4,
+ 0x8ea5, 0x8ea6, 0x8ea7, 0x8ea8, 0x8ea9, 0x8eaa, 0x8eab, 0x8eac,
+ 0x8ead, 0x8eae, 0x8eaf, 0x8eb0, 0x8eb1, 0x8eb3, 0x8eb4, 0x8eb5,
+ 0x8eb6, 0x8eb7, 0x8eb8, 0x8eb9, 0x8eba, 0x8ebb, 0x8ebc, 0x8ebd,
+ 0x8ec1, 0x8ec2, 0x8ec3, 0x8ec4, 0x8ec5, 0x8ec6, 0x8ec7, 0x8ec8,
+ 0x8ec9, 0x8eca, 0x8ecb, 0x8ecc, 0x8ecd, 0x8ece, 0x8ecf, 0x8ed0
+};
+
+static unsigned short johab_from_unicode_b0[] = {
+ 0x8ed1, 0x8ed3, 0x8ed4, 0x8ed5, 0x8ed6, 0x8ed7, 0x8ed8, 0x8ed9,
+ 0x8eda, 0x8edb, 0x8edc, 0x8edd, 0x8ee1, 0x8ee2, 0x8ee3, 0x8ee4,
+ 0x8ee5, 0x8ee6, 0x8ee7, 0x8ee8, 0x8ee9, 0x8eea, 0x8eeb, 0x8eec,
+ 0x8eed, 0x8eee, 0x8eef, 0x8ef0, 0x8ef1, 0x8ef3, 0x8ef4, 0x8ef5,
+ 0x8ef6, 0x8ef7, 0x8ef8, 0x8ef9, 0x8efa, 0x8efb, 0x8efc, 0x8efd,
+ 0x8f41, 0x8f42, 0x8f43, 0x8f44, 0x8f45, 0x8f46, 0x8f47, 0x8f48,
+ 0x8f49, 0x8f4a, 0x8f4b, 0x8f4c, 0x8f4d, 0x8f4e, 0x8f4f, 0x8f50,
+ 0x8f51, 0x8f53, 0x8f54, 0x8f55, 0x8f56, 0x8f57, 0x8f58, 0x8f59,
+ 0x8f5a, 0x8f5b, 0x8f5c, 0x8f5d, 0x8f61, 0x8f62, 0x8f63, 0x8f64,
+ 0x8f65, 0x8f66, 0x8f67, 0x8f68, 0x8f69, 0x8f6a, 0x8f6b, 0x8f6c,
+ 0x8f6d, 0x8f6e, 0x8f6f, 0x8f70, 0x8f71, 0x8f73, 0x8f74, 0x8f75,
+ 0x8f76, 0x8f77, 0x8f78, 0x8f79, 0x8f7a, 0x8f7b, 0x8f7c, 0x8f7d,
+ 0x8f81, 0x8f82, 0x8f83, 0x8f84, 0x8f85, 0x8f86, 0x8f87, 0x8f88,
+ 0x8f89, 0x8f8a, 0x8f8b, 0x8f8c, 0x8f8d, 0x8f8e, 0x8f8f, 0x8f90,
+ 0x8f91, 0x8f93, 0x8f94, 0x8f95, 0x8f96, 0x8f97, 0x8f98, 0x8f99,
+ 0x8f9a, 0x8f9b, 0x8f9c, 0x8f9d, 0x8fa1, 0x8fa2, 0x8fa3, 0x8fa4,
+ 0x8fa5, 0x8fa6, 0x8fa7, 0x8fa8, 0x8fa9, 0x8faa, 0x8fab, 0x8fac,
+ 0x8fad, 0x8fae, 0x8faf, 0x8fb0, 0x8fb1, 0x8fb3, 0x8fb4, 0x8fb5,
+ 0x8fb6, 0x8fb7, 0x8fb8, 0x8fb9, 0x8fba, 0x8fbb, 0x8fbc, 0x8fbd,
+ 0x9061, 0x9062, 0x9063, 0x9064, 0x9065, 0x9066, 0x9067, 0x9068,
+ 0x9069, 0x906a, 0x906b, 0x906c, 0x906d, 0x906e, 0x906f, 0x9070,
+ 0x9071, 0x9073, 0x9074, 0x9075, 0x9076, 0x9077, 0x9078, 0x9079,
+ 0x907a, 0x907b, 0x907c, 0x907d, 0x9081, 0x9082, 0x9083, 0x9084,
+ 0x9085, 0x9086, 0x9087, 0x9088, 0x9089, 0x908a, 0x908b, 0x908c,
+ 0x908d, 0x908e, 0x908f, 0x9090, 0x9091, 0x9093, 0x9094, 0x9095,
+ 0x9096, 0x9097, 0x9098, 0x9099, 0x909a, 0x909b, 0x909c, 0x909d,
+ 0x90a1, 0x90a2, 0x90a3, 0x90a4, 0x90a5, 0x90a6, 0x90a7, 0x90a8,
+ 0x90a9, 0x90aa, 0x90ab, 0x90ac, 0x90ad, 0x90ae, 0x90af, 0x90b0,
+ 0x90b1, 0x90b3, 0x90b4, 0x90b5, 0x90b6, 0x90b7, 0x90b8, 0x90b9,
+ 0x90ba, 0x90bb, 0x90bc, 0x90bd, 0x90c1, 0x90c2, 0x90c3, 0x90c4,
+ 0x90c5, 0x90c6, 0x90c7, 0x90c8, 0x90c9, 0x90ca, 0x90cb, 0x90cc,
+ 0x90cd, 0x90ce, 0x90cf, 0x90d0, 0x90d1, 0x90d3, 0x90d4, 0x90d5
+};
+
+static unsigned short johab_from_unicode_b1[] = {
+ 0x90d6, 0x90d7, 0x90d8, 0x90d9, 0x90da, 0x90db, 0x90dc, 0x90dd,
+ 0x90e1, 0x90e2, 0x90e3, 0x90e4, 0x90e5, 0x90e6, 0x90e7, 0x90e8,
+ 0x90e9, 0x90ea, 0x90eb, 0x90ec, 0x90ed, 0x90ee, 0x90ef, 0x90f0,
+ 0x90f1, 0x90f3, 0x90f4, 0x90f5, 0x90f6, 0x90f7, 0x90f8, 0x90f9,
+ 0x90fa, 0x90fb, 0x90fc, 0x90fd, 0x9141, 0x9142, 0x9143, 0x9144,
+ 0x9145, 0x9146, 0x9147, 0x9148, 0x9149, 0x914a, 0x914b, 0x914c,
+ 0x914d, 0x914e, 0x914f, 0x9150, 0x9151, 0x9153, 0x9154, 0x9155,
+ 0x9156, 0x9157, 0x9158, 0x9159, 0x915a, 0x915b, 0x915c, 0x915d,
+ 0x9161, 0x9162, 0x9163, 0x9164, 0x9165, 0x9166, 0x9167, 0x9168,
+ 0x9169, 0x916a, 0x916b, 0x916c, 0x916d, 0x916e, 0x916f, 0x9170,
+ 0x9171, 0x9173, 0x9174, 0x9175, 0x9176, 0x9177, 0x9178, 0x9179,
+ 0x917a, 0x917b, 0x917c, 0x917d, 0x9181, 0x9182, 0x9183, 0x9184,
+ 0x9185, 0x9186, 0x9187, 0x9188, 0x9189, 0x918a, 0x918b, 0x918c,
+ 0x918d, 0x918e, 0x918f, 0x9190, 0x9191, 0x9193, 0x9194, 0x9195,
+ 0x9196, 0x9197, 0x9198, 0x9199, 0x919a, 0x919b, 0x919c, 0x919d,
+ 0x91a1, 0x91a2, 0x91a3, 0x91a4, 0x91a5, 0x91a6, 0x91a7, 0x91a8,
+ 0x91a9, 0x91aa, 0x91ab, 0x91ac, 0x91ad, 0x91ae, 0x91af, 0x91b0,
+ 0x91b1, 0x91b3, 0x91b4, 0x91b5, 0x91b6, 0x91b7, 0x91b8, 0x91b9,
+ 0x91ba, 0x91bb, 0x91bc, 0x91bd, 0x91c1, 0x91c2, 0x91c3, 0x91c4,
+ 0x91c5, 0x91c6, 0x91c7, 0x91c8, 0x91c9, 0x91ca, 0x91cb, 0x91cc,
+ 0x91cd, 0x91ce, 0x91cf, 0x91d0, 0x91d1, 0x91d3, 0x91d4, 0x91d5,
+ 0x91d6, 0x91d7, 0x91d8, 0x91d9, 0x91da, 0x91db, 0x91dc, 0x91dd,
+ 0x91e1, 0x91e2, 0x91e3, 0x91e4, 0x91e5, 0x91e6, 0x91e7, 0x91e8,
+ 0x91e9, 0x91ea, 0x91eb, 0x91ec, 0x91ed, 0x91ee, 0x91ef, 0x91f0,
+ 0x91f1, 0x91f3, 0x91f4, 0x91f5, 0x91f6, 0x91f7, 0x91f8, 0x91f9,
+ 0x91fa, 0x91fb, 0x91fc, 0x91fd, 0x9241, 0x9242, 0x9243, 0x9244,
+ 0x9245, 0x9246, 0x9247, 0x9248, 0x9249, 0x924a, 0x924b, 0x924c,
+ 0x924d, 0x924e, 0x924f, 0x9250, 0x9251, 0x9253, 0x9254, 0x9255,
+ 0x9256, 0x9257, 0x9258, 0x9259, 0x925a, 0x925b, 0x925c, 0x925d,
+ 0x9261, 0x9262, 0x9263, 0x9264, 0x9265, 0x9266, 0x9267, 0x9268,
+ 0x9269, 0x926a, 0x926b, 0x926c, 0x926d, 0x926e, 0x926f, 0x9270,
+ 0x9271, 0x9273, 0x9274, 0x9275, 0x9276, 0x9277, 0x9278, 0x9279
+};
+
+static unsigned short johab_from_unicode_b2[] = {
+ 0x927a, 0x927b, 0x927c, 0x927d, 0x9281, 0x9282, 0x9283, 0x9284,
+ 0x9285, 0x9286, 0x9287, 0x9288, 0x9289, 0x928a, 0x928b, 0x928c,
+ 0x928d, 0x928e, 0x928f, 0x9290, 0x9291, 0x9293, 0x9294, 0x9295,
+ 0x9296, 0x9297, 0x9298, 0x9299, 0x929a, 0x929b, 0x929c, 0x929d,
+ 0x92a1, 0x92a2, 0x92a3, 0x92a4, 0x92a5, 0x92a6, 0x92a7, 0x92a8,
+ 0x92a9, 0x92aa, 0x92ab, 0x92ac, 0x92ad, 0x92ae, 0x92af, 0x92b0,
+ 0x92b1, 0x92b3, 0x92b4, 0x92b5, 0x92b6, 0x92b7, 0x92b8, 0x92b9,
+ 0x92ba, 0x92bb, 0x92bc, 0x92bd, 0x92c1, 0x92c2, 0x92c3, 0x92c4,
+ 0x92c5, 0x92c6, 0x92c7, 0x92c8, 0x92c9, 0x92ca, 0x92cb, 0x92cc,
+ 0x92cd, 0x92ce, 0x92cf, 0x92d0, 0x92d1, 0x92d3, 0x92d4, 0x92d5,
+ 0x92d6, 0x92d7, 0x92d8, 0x92d9, 0x92da, 0x92db, 0x92dc, 0x92dd,
+ 0x92e1, 0x92e2, 0x92e3, 0x92e4, 0x92e5, 0x92e6, 0x92e7, 0x92e8,
+ 0x92e9, 0x92ea, 0x92eb, 0x92ec, 0x92ed, 0x92ee, 0x92ef, 0x92f0,
+ 0x92f1, 0x92f3, 0x92f4, 0x92f5, 0x92f6, 0x92f7, 0x92f8, 0x92f9,
+ 0x92fa, 0x92fb, 0x92fc, 0x92fd, 0x9341, 0x9342, 0x9343, 0x9344,
+ 0x9345, 0x9346, 0x9347, 0x9348, 0x9349, 0x934a, 0x934b, 0x934c,
+ 0x934d, 0x934e, 0x934f, 0x9350, 0x9351, 0x9353, 0x9354, 0x9355,
+ 0x9356, 0x9357, 0x9358, 0x9359, 0x935a, 0x935b, 0x935c, 0x935d,
+ 0x9361, 0x9362, 0x9363, 0x9364, 0x9365, 0x9366, 0x9367, 0x9368,
+ 0x9369, 0x936a, 0x936b, 0x936c, 0x936d, 0x936e, 0x936f, 0x9370,
+ 0x9371, 0x9373, 0x9374, 0x9375, 0x9376, 0x9377, 0x9378, 0x9379,
+ 0x937a, 0x937b, 0x937c, 0x937d, 0x9381, 0x9382, 0x9383, 0x9384,
+ 0x9385, 0x9386, 0x9387, 0x9388, 0x9389, 0x938a, 0x938b, 0x938c,
+ 0x938d, 0x938e, 0x938f, 0x9390, 0x9391, 0x9393, 0x9394, 0x9395,
+ 0x9396, 0x9397, 0x9398, 0x9399, 0x939a, 0x939b, 0x939c, 0x939d,
+ 0x93a1, 0x93a2, 0x93a3, 0x93a4, 0x93a5, 0x93a6, 0x93a7, 0x93a8,
+ 0x93a9, 0x93aa, 0x93ab, 0x93ac, 0x93ad, 0x93ae, 0x93af, 0x93b0,
+ 0x93b1, 0x93b3, 0x93b4, 0x93b5, 0x93b6, 0x93b7, 0x93b8, 0x93b9,
+ 0x93ba, 0x93bb, 0x93bc, 0x93bd, 0x9461, 0x9462, 0x9463, 0x9464,
+ 0x9465, 0x9466, 0x9467, 0x9468, 0x9469, 0x946a, 0x946b, 0x946c,
+ 0x946d, 0x946e, 0x946f, 0x9470, 0x9471, 0x9473, 0x9474, 0x9475,
+ 0x9476, 0x9477, 0x9478, 0x9479, 0x947a, 0x947b, 0x947c, 0x947d
+};
+
+static unsigned short johab_from_unicode_b3[] = {
+ 0x9481, 0x9482, 0x9483, 0x9484, 0x9485, 0x9486, 0x9487, 0x9488,
+ 0x9489, 0x948a, 0x948b, 0x948c, 0x948d, 0x948e, 0x948f, 0x9490,
+ 0x9491, 0x9493, 0x9494, 0x9495, 0x9496, 0x9497, 0x9498, 0x9499,
+ 0x949a, 0x949b, 0x949c, 0x949d, 0x94a1, 0x94a2, 0x94a3, 0x94a4,
+ 0x94a5, 0x94a6, 0x94a7, 0x94a8, 0x94a9, 0x94aa, 0x94ab, 0x94ac,
+ 0x94ad, 0x94ae, 0x94af, 0x94b0, 0x94b1, 0x94b3, 0x94b4, 0x94b5,
+ 0x94b6, 0x94b7, 0x94b8, 0x94b9, 0x94ba, 0x94bb, 0x94bc, 0x94bd,
+ 0x94c1, 0x94c2, 0x94c3, 0x94c4, 0x94c5, 0x94c6, 0x94c7, 0x94c8,
+ 0x94c9, 0x94ca, 0x94cb, 0x94cc, 0x94cd, 0x94ce, 0x94cf, 0x94d0,
+ 0x94d1, 0x94d3, 0x94d4, 0x94d5, 0x94d6, 0x94d7, 0x94d8, 0x94d9,
+ 0x94da, 0x94db, 0x94dc, 0x94dd, 0x94e1, 0x94e2, 0x94e3, 0x94e4,
+ 0x94e5, 0x94e6, 0x94e7, 0x94e8, 0x94e9, 0x94ea, 0x94eb, 0x94ec,
+ 0x94ed, 0x94ee, 0x94ef, 0x94f0, 0x94f1, 0x94f3, 0x94f4, 0x94f5,
+ 0x94f6, 0x94f7, 0x94f8, 0x94f9, 0x94fa, 0x94fb, 0x94fc, 0x94fd,
+ 0x9541, 0x9542, 0x9543, 0x9544, 0x9545, 0x9546, 0x9547, 0x9548,
+ 0x9549, 0x954a, 0x954b, 0x954c, 0x954d, 0x954e, 0x954f, 0x9550,
+ 0x9551, 0x9553, 0x9554, 0x9555, 0x9556, 0x9557, 0x9558, 0x9559,
+ 0x955a, 0x955b, 0x955c, 0x955d, 0x9561, 0x9562, 0x9563, 0x9564,
+ 0x9565, 0x9566, 0x9567, 0x9568, 0x9569, 0x956a, 0x956b, 0x956c,
+ 0x956d, 0x956e, 0x956f, 0x9570, 0x9571, 0x9573, 0x9574, 0x9575,
+ 0x9576, 0x9577, 0x9578, 0x9579, 0x957a, 0x957b, 0x957c, 0x957d,
+ 0x9581, 0x9582, 0x9583, 0x9584, 0x9585, 0x9586, 0x9587, 0x9588,
+ 0x9589, 0x958a, 0x958b, 0x958c, 0x958d, 0x958e, 0x958f, 0x9590,
+ 0x9591, 0x9593, 0x9594, 0x9595, 0x9596, 0x9597, 0x9598, 0x9599,
+ 0x959a, 0x959b, 0x959c, 0x959d, 0x95a1, 0x95a2, 0x95a3, 0x95a4,
+ 0x95a5, 0x95a6, 0x95a7, 0x95a8, 0x95a9, 0x95aa, 0x95ab, 0x95ac,
+ 0x95ad, 0x95ae, 0x95af, 0x95b0, 0x95b1, 0x95b3, 0x95b4, 0x95b5,
+ 0x95b6, 0x95b7, 0x95b8, 0x95b9, 0x95ba, 0x95bb, 0x95bc, 0x95bd,
+ 0x95c1, 0x95c2, 0x95c3, 0x95c4, 0x95c5, 0x95c6, 0x95c7, 0x95c8,
+ 0x95c9, 0x95ca, 0x95cb, 0x95cc, 0x95cd, 0x95ce, 0x95cf, 0x95d0,
+ 0x95d1, 0x95d3, 0x95d4, 0x95d5, 0x95d6, 0x95d7, 0x95d8, 0x95d9,
+ 0x95da, 0x95db, 0x95dc, 0x95dd, 0x95e1, 0x95e2, 0x95e3, 0x95e4
+};
+
+static unsigned short johab_from_unicode_b4[] = {
+ 0x95e5, 0x95e6, 0x95e7, 0x95e8, 0x95e9, 0x95ea, 0x95eb, 0x95ec,
+ 0x95ed, 0x95ee, 0x95ef, 0x95f0, 0x95f1, 0x95f3, 0x95f4, 0x95f5,
+ 0x95f6, 0x95f7, 0x95f8, 0x95f9, 0x95fa, 0x95fb, 0x95fc, 0x95fd,
+ 0x9641, 0x9642, 0x9643, 0x9644, 0x9645, 0x9646, 0x9647, 0x9648,
+ 0x9649, 0x964a, 0x964b, 0x964c, 0x964d, 0x964e, 0x964f, 0x9650,
+ 0x9651, 0x9653, 0x9654, 0x9655, 0x9656, 0x9657, 0x9658, 0x9659,
+ 0x965a, 0x965b, 0x965c, 0x965d, 0x9661, 0x9662, 0x9663, 0x9664,
+ 0x9665, 0x9666, 0x9667, 0x9668, 0x9669, 0x966a, 0x966b, 0x966c,
+ 0x966d, 0x966e, 0x966f, 0x9670, 0x9671, 0x9673, 0x9674, 0x9675,
+ 0x9676, 0x9677, 0x9678, 0x9679, 0x967a, 0x967b, 0x967c, 0x967d,
+ 0x9681, 0x9682, 0x9683, 0x9684, 0x9685, 0x9686, 0x9687, 0x9688,
+ 0x9689, 0x968a, 0x968b, 0x968c, 0x968d, 0x968e, 0x968f, 0x9690,
+ 0x9691, 0x9693, 0x9694, 0x9695, 0x9696, 0x9697, 0x9698, 0x9699,
+ 0x969a, 0x969b, 0x969c, 0x969d, 0x96a1, 0x96a2, 0x96a3, 0x96a4,
+ 0x96a5, 0x96a6, 0x96a7, 0x96a8, 0x96a9, 0x96aa, 0x96ab, 0x96ac,
+ 0x96ad, 0x96ae, 0x96af, 0x96b0, 0x96b1, 0x96b3, 0x96b4, 0x96b5,
+ 0x96b6, 0x96b7, 0x96b8, 0x96b9, 0x96ba, 0x96bb, 0x96bc, 0x96bd,
+ 0x96c1, 0x96c2, 0x96c3, 0x96c4, 0x96c5, 0x96c6, 0x96c7, 0x96c8,
+ 0x96c9, 0x96ca, 0x96cb, 0x96cc, 0x96cd, 0x96ce, 0x96cf, 0x96d0,
+ 0x96d1, 0x96d3, 0x96d4, 0x96d5, 0x96d6, 0x96d7, 0x96d8, 0x96d9,
+ 0x96da, 0x96db, 0x96dc, 0x96dd, 0x96e1, 0x96e2, 0x96e3, 0x96e4,
+ 0x96e5, 0x96e6, 0x96e7, 0x96e8, 0x96e9, 0x96ea, 0x96eb, 0x96ec,
+ 0x96ed, 0x96ee, 0x96ef, 0x96f0, 0x96f1, 0x96f3, 0x96f4, 0x96f5,
+ 0x96f6, 0x96f7, 0x96f8, 0x96f9, 0x96fa, 0x96fb, 0x96fc, 0x96fd,
+ 0x9741, 0x9742, 0x9743, 0x9744, 0x9745, 0x9746, 0x9747, 0x9748,
+ 0x9749, 0x974a, 0x974b, 0x974c, 0x974d, 0x974e, 0x974f, 0x9750,
+ 0x9751, 0x9753, 0x9754, 0x9755, 0x9756, 0x9757, 0x9758, 0x9759,
+ 0x975a, 0x975b, 0x975c, 0x975d, 0x9761, 0x9762, 0x9763, 0x9764,
+ 0x9765, 0x9766, 0x9767, 0x9768, 0x9769, 0x976a, 0x976b, 0x976c,
+ 0x976d, 0x976e, 0x976f, 0x9770, 0x9771, 0x9773, 0x9774, 0x9775,
+ 0x9776, 0x9777, 0x9778, 0x9779, 0x977a, 0x977b, 0x977c, 0x977d,
+ 0x9781, 0x9782, 0x9783, 0x9784, 0x9785, 0x9786, 0x9787, 0x9788
+};
+
+static unsigned short johab_from_unicode_b5[] = {
+ 0x9789, 0x978a, 0x978b, 0x978c, 0x978d, 0x978e, 0x978f, 0x9790,
+ 0x9791, 0x9793, 0x9794, 0x9795, 0x9796, 0x9797, 0x9798, 0x9799,
+ 0x979a, 0x979b, 0x979c, 0x979d, 0x97a1, 0x97a2, 0x97a3, 0x97a4,
+ 0x97a5, 0x97a6, 0x97a7, 0x97a8, 0x97a9, 0x97aa, 0x97ab, 0x97ac,
+ 0x97ad, 0x97ae, 0x97af, 0x97b0, 0x97b1, 0x97b3, 0x97b4, 0x97b5,
+ 0x97b6, 0x97b7, 0x97b8, 0x97b9, 0x97ba, 0x97bb, 0x97bc, 0x97bd,
+ 0x9861, 0x9862, 0x9863, 0x9864, 0x9865, 0x9866, 0x9867, 0x9868,
+ 0x9869, 0x986a, 0x986b, 0x986c, 0x986d, 0x986e, 0x986f, 0x9870,
+ 0x9871, 0x9873, 0x9874, 0x9875, 0x9876, 0x9877, 0x9878, 0x9879,
+ 0x987a, 0x987b, 0x987c, 0x987d, 0x9881, 0x9882, 0x9883, 0x9884,
+ 0x9885, 0x9886, 0x9887, 0x9888, 0x9889, 0x988a, 0x988b, 0x988c,
+ 0x988d, 0x988e, 0x988f, 0x9890, 0x9891, 0x9893, 0x9894, 0x9895,
+ 0x9896, 0x9897, 0x9898, 0x9899, 0x989a, 0x989b, 0x989c, 0x989d,
+ 0x98a1, 0x98a2, 0x98a3, 0x98a4, 0x98a5, 0x98a6, 0x98a7, 0x98a8,
+ 0x98a9, 0x98aa, 0x98ab, 0x98ac, 0x98ad, 0x98ae, 0x98af, 0x98b0,
+ 0x98b1, 0x98b3, 0x98b4, 0x98b5, 0x98b6, 0x98b7, 0x98b8, 0x98b9,
+ 0x98ba, 0x98bb, 0x98bc, 0x98bd, 0x98c1, 0x98c2, 0x98c3, 0x98c4,
+ 0x98c5, 0x98c6, 0x98c7, 0x98c8, 0x98c9, 0x98ca, 0x98cb, 0x98cc,
+ 0x98cd, 0x98ce, 0x98cf, 0x98d0, 0x98d1, 0x98d3, 0x98d4, 0x98d5,
+ 0x98d6, 0x98d7, 0x98d8, 0x98d9, 0x98da, 0x98db, 0x98dc, 0x98dd,
+ 0x98e1, 0x98e2, 0x98e3, 0x98e4, 0x98e5, 0x98e6, 0x98e7, 0x98e8,
+ 0x98e9, 0x98ea, 0x98eb, 0x98ec, 0x98ed, 0x98ee, 0x98ef, 0x98f0,
+ 0x98f1, 0x98f3, 0x98f4, 0x98f5, 0x98f6, 0x98f7, 0x98f8, 0x98f9,
+ 0x98fa, 0x98fb, 0x98fc, 0x98fd, 0x9941, 0x9942, 0x9943, 0x9944,
+ 0x9945, 0x9946, 0x9947, 0x9948, 0x9949, 0x994a, 0x994b, 0x994c,
+ 0x994d, 0x994e, 0x994f, 0x9950, 0x9951, 0x9953, 0x9954, 0x9955,
+ 0x9956, 0x9957, 0x9958, 0x9959, 0x995a, 0x995b, 0x995c, 0x995d,
+ 0x9961, 0x9962, 0x9963, 0x9964, 0x9965, 0x9966, 0x9967, 0x9968,
+ 0x9969, 0x996a, 0x996b, 0x996c, 0x996d, 0x996e, 0x996f, 0x9970,
+ 0x9971, 0x9973, 0x9974, 0x9975, 0x9976, 0x9977, 0x9978, 0x9979,
+ 0x997a, 0x997b, 0x997c, 0x997d, 0x9981, 0x9982, 0x9983, 0x9984,
+ 0x9985, 0x9986, 0x9987, 0x9988, 0x9989, 0x998a, 0x998b, 0x998c
+};
+
+static unsigned short johab_from_unicode_b6[] = {
+ 0x998d, 0x998e, 0x998f, 0x9990, 0x9991, 0x9993, 0x9994, 0x9995,
+ 0x9996, 0x9997, 0x9998, 0x9999, 0x999a, 0x999b, 0x999c, 0x999d,
+ 0x99a1, 0x99a2, 0x99a3, 0x99a4, 0x99a5, 0x99a6, 0x99a7, 0x99a8,
+ 0x99a9, 0x99aa, 0x99ab, 0x99ac, 0x99ad, 0x99ae, 0x99af, 0x99b0,
+ 0x99b1, 0x99b3, 0x99b4, 0x99b5, 0x99b6, 0x99b7, 0x99b8, 0x99b9,
+ 0x99ba, 0x99bb, 0x99bc, 0x99bd, 0x99c1, 0x99c2, 0x99c3, 0x99c4,
+ 0x99c5, 0x99c6, 0x99c7, 0x99c8, 0x99c9, 0x99ca, 0x99cb, 0x99cc,
+ 0x99cd, 0x99ce, 0x99cf, 0x99d0, 0x99d1, 0x99d3, 0x99d4, 0x99d5,
+ 0x99d6, 0x99d7, 0x99d8, 0x99d9, 0x99da, 0x99db, 0x99dc, 0x99dd,
+ 0x99e1, 0x99e2, 0x99e3, 0x99e4, 0x99e5, 0x99e6, 0x99e7, 0x99e8,
+ 0x99e9, 0x99ea, 0x99eb, 0x99ec, 0x99ed, 0x99ee, 0x99ef, 0x99f0,
+ 0x99f1, 0x99f3, 0x99f4, 0x99f5, 0x99f6, 0x99f7, 0x99f8, 0x99f9,
+ 0x99fa, 0x99fb, 0x99fc, 0x99fd, 0x9a41, 0x9a42, 0x9a43, 0x9a44,
+ 0x9a45, 0x9a46, 0x9a47, 0x9a48, 0x9a49, 0x9a4a, 0x9a4b, 0x9a4c,
+ 0x9a4d, 0x9a4e, 0x9a4f, 0x9a50, 0x9a51, 0x9a53, 0x9a54, 0x9a55,
+ 0x9a56, 0x9a57, 0x9a58, 0x9a59, 0x9a5a, 0x9a5b, 0x9a5c, 0x9a5d,
+ 0x9a61, 0x9a62, 0x9a63, 0x9a64, 0x9a65, 0x9a66, 0x9a67, 0x9a68,
+ 0x9a69, 0x9a6a, 0x9a6b, 0x9a6c, 0x9a6d, 0x9a6e, 0x9a6f, 0x9a70,
+ 0x9a71, 0x9a73, 0x9a74, 0x9a75, 0x9a76, 0x9a77, 0x9a78, 0x9a79,
+ 0x9a7a, 0x9a7b, 0x9a7c, 0x9a7d, 0x9a81, 0x9a82, 0x9a83, 0x9a84,
+ 0x9a85, 0x9a86, 0x9a87, 0x9a88, 0x9a89, 0x9a8a, 0x9a8b, 0x9a8c,
+ 0x9a8d, 0x9a8e, 0x9a8f, 0x9a90, 0x9a91, 0x9a93, 0x9a94, 0x9a95,
+ 0x9a96, 0x9a97, 0x9a98, 0x9a99, 0x9a9a, 0x9a9b, 0x9a9c, 0x9a9d,
+ 0x9aa1, 0x9aa2, 0x9aa3, 0x9aa4, 0x9aa5, 0x9aa6, 0x9aa7, 0x9aa8,
+ 0x9aa9, 0x9aaa, 0x9aab, 0x9aac, 0x9aad, 0x9aae, 0x9aaf, 0x9ab0,
+ 0x9ab1, 0x9ab3, 0x9ab4, 0x9ab5, 0x9ab6, 0x9ab7, 0x9ab8, 0x9ab9,
+ 0x9aba, 0x9abb, 0x9abc, 0x9abd, 0x9ac1, 0x9ac2, 0x9ac3, 0x9ac4,
+ 0x9ac5, 0x9ac6, 0x9ac7, 0x9ac8, 0x9ac9, 0x9aca, 0x9acb, 0x9acc,
+ 0x9acd, 0x9ace, 0x9acf, 0x9ad0, 0x9ad1, 0x9ad3, 0x9ad4, 0x9ad5,
+ 0x9ad6, 0x9ad7, 0x9ad8, 0x9ad9, 0x9ada, 0x9adb, 0x9adc, 0x9add,
+ 0x9ae1, 0x9ae2, 0x9ae3, 0x9ae4, 0x9ae5, 0x9ae6, 0x9ae7, 0x9ae8,
+ 0x9ae9, 0x9aea, 0x9aeb, 0x9aec, 0x9aed, 0x9aee, 0x9aef, 0x9af0
+};
+
+static unsigned short johab_from_unicode_b7[] = {
+ 0x9af1, 0x9af3, 0x9af4, 0x9af5, 0x9af6, 0x9af7, 0x9af8, 0x9af9,
+ 0x9afa, 0x9afb, 0x9afc, 0x9afd, 0x9b41, 0x9b42, 0x9b43, 0x9b44,
+ 0x9b45, 0x9b46, 0x9b47, 0x9b48, 0x9b49, 0x9b4a, 0x9b4b, 0x9b4c,
+ 0x9b4d, 0x9b4e, 0x9b4f, 0x9b50, 0x9b51, 0x9b53, 0x9b54, 0x9b55,
+ 0x9b56, 0x9b57, 0x9b58, 0x9b59, 0x9b5a, 0x9b5b, 0x9b5c, 0x9b5d,
+ 0x9b61, 0x9b62, 0x9b63, 0x9b64, 0x9b65, 0x9b66, 0x9b67, 0x9b68,
+ 0x9b69, 0x9b6a, 0x9b6b, 0x9b6c, 0x9b6d, 0x9b6e, 0x9b6f, 0x9b70,
+ 0x9b71, 0x9b73, 0x9b74, 0x9b75, 0x9b76, 0x9b77, 0x9b78, 0x9b79,
+ 0x9b7a, 0x9b7b, 0x9b7c, 0x9b7d, 0x9b81, 0x9b82, 0x9b83, 0x9b84,
+ 0x9b85, 0x9b86, 0x9b87, 0x9b88, 0x9b89, 0x9b8a, 0x9b8b, 0x9b8c,
+ 0x9b8d, 0x9b8e, 0x9b8f, 0x9b90, 0x9b91, 0x9b93, 0x9b94, 0x9b95,
+ 0x9b96, 0x9b97, 0x9b98, 0x9b99, 0x9b9a, 0x9b9b, 0x9b9c, 0x9b9d,
+ 0x9ba1, 0x9ba2, 0x9ba3, 0x9ba4, 0x9ba5, 0x9ba6, 0x9ba7, 0x9ba8,
+ 0x9ba9, 0x9baa, 0x9bab, 0x9bac, 0x9bad, 0x9bae, 0x9baf, 0x9bb0,
+ 0x9bb1, 0x9bb3, 0x9bb4, 0x9bb5, 0x9bb6, 0x9bb7, 0x9bb8, 0x9bb9,
+ 0x9bba, 0x9bbb, 0x9bbc, 0x9bbd, 0x9c61, 0x9c62, 0x9c63, 0x9c64,
+ 0x9c65, 0x9c66, 0x9c67, 0x9c68, 0x9c69, 0x9c6a, 0x9c6b, 0x9c6c,
+ 0x9c6d, 0x9c6e, 0x9c6f, 0x9c70, 0x9c71, 0x9c73, 0x9c74, 0x9c75,
+ 0x9c76, 0x9c77, 0x9c78, 0x9c79, 0x9c7a, 0x9c7b, 0x9c7c, 0x9c7d,
+ 0x9c81, 0x9c82, 0x9c83, 0x9c84, 0x9c85, 0x9c86, 0x9c87, 0x9c88,
+ 0x9c89, 0x9c8a, 0x9c8b, 0x9c8c, 0x9c8d, 0x9c8e, 0x9c8f, 0x9c90,
+ 0x9c91, 0x9c93, 0x9c94, 0x9c95, 0x9c96, 0x9c97, 0x9c98, 0x9c99,
+ 0x9c9a, 0x9c9b, 0x9c9c, 0x9c9d, 0x9ca1, 0x9ca2, 0x9ca3, 0x9ca4,
+ 0x9ca5, 0x9ca6, 0x9ca7, 0x9ca8, 0x9ca9, 0x9caa, 0x9cab, 0x9cac,
+ 0x9cad, 0x9cae, 0x9caf, 0x9cb0, 0x9cb1, 0x9cb3, 0x9cb4, 0x9cb5,
+ 0x9cb6, 0x9cb7, 0x9cb8, 0x9cb9, 0x9cba, 0x9cbb, 0x9cbc, 0x9cbd,
+ 0x9cc1, 0x9cc2, 0x9cc3, 0x9cc4, 0x9cc5, 0x9cc6, 0x9cc7, 0x9cc8,
+ 0x9cc9, 0x9cca, 0x9ccb, 0x9ccc, 0x9ccd, 0x9cce, 0x9ccf, 0x9cd0,
+ 0x9cd1, 0x9cd3, 0x9cd4, 0x9cd5, 0x9cd6, 0x9cd7, 0x9cd8, 0x9cd9,
+ 0x9cda, 0x9cdb, 0x9cdc, 0x9cdd, 0x9ce1, 0x9ce2, 0x9ce3, 0x9ce4,
+ 0x9ce5, 0x9ce6, 0x9ce7, 0x9ce8, 0x9ce9, 0x9cea, 0x9ceb, 0x9cec,
+ 0x9ced, 0x9cee, 0x9cef, 0x9cf0, 0x9cf1, 0x9cf3, 0x9cf4, 0x9cf5
+};
+
+static unsigned short johab_from_unicode_b8[] = {
+ 0x9cf6, 0x9cf7, 0x9cf8, 0x9cf9, 0x9cfa, 0x9cfb, 0x9cfc, 0x9cfd,
+ 0x9d41, 0x9d42, 0x9d43, 0x9d44, 0x9d45, 0x9d46, 0x9d47, 0x9d48,
+ 0x9d49, 0x9d4a, 0x9d4b, 0x9d4c, 0x9d4d, 0x9d4e, 0x9d4f, 0x9d50,
+ 0x9d51, 0x9d53, 0x9d54, 0x9d55, 0x9d56, 0x9d57, 0x9d58, 0x9d59,
+ 0x9d5a, 0x9d5b, 0x9d5c, 0x9d5d, 0x9d61, 0x9d62, 0x9d63, 0x9d64,
+ 0x9d65, 0x9d66, 0x9d67, 0x9d68, 0x9d69, 0x9d6a, 0x9d6b, 0x9d6c,
+ 0x9d6d, 0x9d6e, 0x9d6f, 0x9d70, 0x9d71, 0x9d73, 0x9d74, 0x9d75,
+ 0x9d76, 0x9d77, 0x9d78, 0x9d79, 0x9d7a, 0x9d7b, 0x9d7c, 0x9d7d,
+ 0x9d81, 0x9d82, 0x9d83, 0x9d84, 0x9d85, 0x9d86, 0x9d87, 0x9d88,
+ 0x9d89, 0x9d8a, 0x9d8b, 0x9d8c, 0x9d8d, 0x9d8e, 0x9d8f, 0x9d90,
+ 0x9d91, 0x9d93, 0x9d94, 0x9d95, 0x9d96, 0x9d97, 0x9d98, 0x9d99,
+ 0x9d9a, 0x9d9b, 0x9d9c, 0x9d9d, 0x9da1, 0x9da2, 0x9da3, 0x9da4,
+ 0x9da5, 0x9da6, 0x9da7, 0x9da8, 0x9da9, 0x9daa, 0x9dab, 0x9dac,
+ 0x9dad, 0x9dae, 0x9daf, 0x9db0, 0x9db1, 0x9db3, 0x9db4, 0x9db5,
+ 0x9db6, 0x9db7, 0x9db8, 0x9db9, 0x9dba, 0x9dbb, 0x9dbc, 0x9dbd,
+ 0x9dc1, 0x9dc2, 0x9dc3, 0x9dc4, 0x9dc5, 0x9dc6, 0x9dc7, 0x9dc8,
+ 0x9dc9, 0x9dca, 0x9dcb, 0x9dcc, 0x9dcd, 0x9dce, 0x9dcf, 0x9dd0,
+ 0x9dd1, 0x9dd3, 0x9dd4, 0x9dd5, 0x9dd6, 0x9dd7, 0x9dd8, 0x9dd9,
+ 0x9dda, 0x9ddb, 0x9ddc, 0x9ddd, 0x9de1, 0x9de2, 0x9de3, 0x9de4,
+ 0x9de5, 0x9de6, 0x9de7, 0x9de8, 0x9de9, 0x9dea, 0x9deb, 0x9dec,
+ 0x9ded, 0x9dee, 0x9def, 0x9df0, 0x9df1, 0x9df3, 0x9df4, 0x9df5,
+ 0x9df6, 0x9df7, 0x9df8, 0x9df9, 0x9dfa, 0x9dfb, 0x9dfc, 0x9dfd,
+ 0x9e41, 0x9e42, 0x9e43, 0x9e44, 0x9e45, 0x9e46, 0x9e47, 0x9e48,
+ 0x9e49, 0x9e4a, 0x9e4b, 0x9e4c, 0x9e4d, 0x9e4e, 0x9e4f, 0x9e50,
+ 0x9e51, 0x9e53, 0x9e54, 0x9e55, 0x9e56, 0x9e57, 0x9e58, 0x9e59,
+ 0x9e5a, 0x9e5b, 0x9e5c, 0x9e5d, 0x9e61, 0x9e62, 0x9e63, 0x9e64,
+ 0x9e65, 0x9e66, 0x9e67, 0x9e68, 0x9e69, 0x9e6a, 0x9e6b, 0x9e6c,
+ 0x9e6d, 0x9e6e, 0x9e6f, 0x9e70, 0x9e71, 0x9e73, 0x9e74, 0x9e75,
+ 0x9e76, 0x9e77, 0x9e78, 0x9e79, 0x9e7a, 0x9e7b, 0x9e7c, 0x9e7d,
+ 0x9e81, 0x9e82, 0x9e83, 0x9e84, 0x9e85, 0x9e86, 0x9e87, 0x9e88,
+ 0x9e89, 0x9e8a, 0x9e8b, 0x9e8c, 0x9e8d, 0x9e8e, 0x9e8f, 0x9e90,
+ 0x9e91, 0x9e93, 0x9e94, 0x9e95, 0x9e96, 0x9e97, 0x9e98, 0x9e99
+};
+
+static unsigned short johab_from_unicode_b9[] = {
+ 0x9e9a, 0x9e9b, 0x9e9c, 0x9e9d, 0x9ea1, 0x9ea2, 0x9ea3, 0x9ea4,
+ 0x9ea5, 0x9ea6, 0x9ea7, 0x9ea8, 0x9ea9, 0x9eaa, 0x9eab, 0x9eac,
+ 0x9ead, 0x9eae, 0x9eaf, 0x9eb0, 0x9eb1, 0x9eb3, 0x9eb4, 0x9eb5,
+ 0x9eb6, 0x9eb7, 0x9eb8, 0x9eb9, 0x9eba, 0x9ebb, 0x9ebc, 0x9ebd,
+ 0x9ec1, 0x9ec2, 0x9ec3, 0x9ec4, 0x9ec5, 0x9ec6, 0x9ec7, 0x9ec8,
+ 0x9ec9, 0x9eca, 0x9ecb, 0x9ecc, 0x9ecd, 0x9ece, 0x9ecf, 0x9ed0,
+ 0x9ed1, 0x9ed3, 0x9ed4, 0x9ed5, 0x9ed6, 0x9ed7, 0x9ed8, 0x9ed9,
+ 0x9eda, 0x9edb, 0x9edc, 0x9edd, 0x9ee1, 0x9ee2, 0x9ee3, 0x9ee4,
+ 0x9ee5, 0x9ee6, 0x9ee7, 0x9ee8, 0x9ee9, 0x9eea, 0x9eeb, 0x9eec,
+ 0x9eed, 0x9eee, 0x9eef, 0x9ef0, 0x9ef1, 0x9ef3, 0x9ef4, 0x9ef5,
+ 0x9ef6, 0x9ef7, 0x9ef8, 0x9ef9, 0x9efa, 0x9efb, 0x9efc, 0x9efd,
+ 0x9f41, 0x9f42, 0x9f43, 0x9f44, 0x9f45, 0x9f46, 0x9f47, 0x9f48,
+ 0x9f49, 0x9f4a, 0x9f4b, 0x9f4c, 0x9f4d, 0x9f4e, 0x9f4f, 0x9f50,
+ 0x9f51, 0x9f53, 0x9f54, 0x9f55, 0x9f56, 0x9f57, 0x9f58, 0x9f59,
+ 0x9f5a, 0x9f5b, 0x9f5c, 0x9f5d, 0x9f61, 0x9f62, 0x9f63, 0x9f64,
+ 0x9f65, 0x9f66, 0x9f67, 0x9f68, 0x9f69, 0x9f6a, 0x9f6b, 0x9f6c,
+ 0x9f6d, 0x9f6e, 0x9f6f, 0x9f70, 0x9f71, 0x9f73, 0x9f74, 0x9f75,
+ 0x9f76, 0x9f77, 0x9f78, 0x9f79, 0x9f7a, 0x9f7b, 0x9f7c, 0x9f7d,
+ 0x9f81, 0x9f82, 0x9f83, 0x9f84, 0x9f85, 0x9f86, 0x9f87, 0x9f88,
+ 0x9f89, 0x9f8a, 0x9f8b, 0x9f8c, 0x9f8d, 0x9f8e, 0x9f8f, 0x9f90,
+ 0x9f91, 0x9f93, 0x9f94, 0x9f95, 0x9f96, 0x9f97, 0x9f98, 0x9f99,
+ 0x9f9a, 0x9f9b, 0x9f9c, 0x9f9d, 0x9fa1, 0x9fa2, 0x9fa3, 0x9fa4,
+ 0x9fa5, 0x9fa6, 0x9fa7, 0x9fa8, 0x9fa9, 0x9faa, 0x9fab, 0x9fac,
+ 0x9fad, 0x9fae, 0x9faf, 0x9fb0, 0x9fb1, 0x9fb3, 0x9fb4, 0x9fb5,
+ 0x9fb6, 0x9fb7, 0x9fb8, 0x9fb9, 0x9fba, 0x9fbb, 0x9fbc, 0x9fbd,
+ 0xa061, 0xa062, 0xa063, 0xa064, 0xa065, 0xa066, 0xa067, 0xa068,
+ 0xa069, 0xa06a, 0xa06b, 0xa06c, 0xa06d, 0xa06e, 0xa06f, 0xa070,
+ 0xa071, 0xa073, 0xa074, 0xa075, 0xa076, 0xa077, 0xa078, 0xa079,
+ 0xa07a, 0xa07b, 0xa07c, 0xa07d, 0xa081, 0xa082, 0xa083, 0xa084,
+ 0xa085, 0xa086, 0xa087, 0xa088, 0xa089, 0xa08a, 0xa08b, 0xa08c,
+ 0xa08d, 0xa08e, 0xa08f, 0xa090, 0xa091, 0xa093, 0xa094, 0xa095,
+ 0xa096, 0xa097, 0xa098, 0xa099, 0xa09a, 0xa09b, 0xa09c, 0xa09d
+};
+
+static unsigned short johab_from_unicode_ba[] = {
+ 0xa0a1, 0xa0a2, 0xa0a3, 0xa0a4, 0xa0a5, 0xa0a6, 0xa0a7, 0xa0a8,
+ 0xa0a9, 0xa0aa, 0xa0ab, 0xa0ac, 0xa0ad, 0xa0ae, 0xa0af, 0xa0b0,
+ 0xa0b1, 0xa0b3, 0xa0b4, 0xa0b5, 0xa0b6, 0xa0b7, 0xa0b8, 0xa0b9,
+ 0xa0ba, 0xa0bb, 0xa0bc, 0xa0bd, 0xa0c1, 0xa0c2, 0xa0c3, 0xa0c4,
+ 0xa0c5, 0xa0c6, 0xa0c7, 0xa0c8, 0xa0c9, 0xa0ca, 0xa0cb, 0xa0cc,
+ 0xa0cd, 0xa0ce, 0xa0cf, 0xa0d0, 0xa0d1, 0xa0d3, 0xa0d4, 0xa0d5,
+ 0xa0d6, 0xa0d7, 0xa0d8, 0xa0d9, 0xa0da, 0xa0db, 0xa0dc, 0xa0dd,
+ 0xa0e1, 0xa0e2, 0xa0e3, 0xa0e4, 0xa0e5, 0xa0e6, 0xa0e7, 0xa0e8,
+ 0xa0e9, 0xa0ea, 0xa0eb, 0xa0ec, 0xa0ed, 0xa0ee, 0xa0ef, 0xa0f0,
+ 0xa0f1, 0xa0f3, 0xa0f4, 0xa0f5, 0xa0f6, 0xa0f7, 0xa0f8, 0xa0f9,
+ 0xa0fa, 0xa0fb, 0xa0fc, 0xa0fd, 0xa141, 0xa142, 0xa143, 0xa144,
+ 0xa145, 0xa146, 0xa147, 0xa148, 0xa149, 0xa14a, 0xa14b, 0xa14c,
+ 0xa14d, 0xa14e, 0xa14f, 0xa150, 0xa151, 0xa153, 0xa154, 0xa155,
+ 0xa156, 0xa157, 0xa158, 0xa159, 0xa15a, 0xa15b, 0xa15c, 0xa15d,
+ 0xa161, 0xa162, 0xa163, 0xa164, 0xa165, 0xa166, 0xa167, 0xa168,
+ 0xa169, 0xa16a, 0xa16b, 0xa16c, 0xa16d, 0xa16e, 0xa16f, 0xa170,
+ 0xa171, 0xa173, 0xa174, 0xa175, 0xa176, 0xa177, 0xa178, 0xa179,
+ 0xa17a, 0xa17b, 0xa17c, 0xa17d, 0xa181, 0xa182, 0xa183, 0xa184,
+ 0xa185, 0xa186, 0xa187, 0xa188, 0xa189, 0xa18a, 0xa18b, 0xa18c,
+ 0xa18d, 0xa18e, 0xa18f, 0xa190, 0xa191, 0xa193, 0xa194, 0xa195,
+ 0xa196, 0xa197, 0xa198, 0xa199, 0xa19a, 0xa19b, 0xa19c, 0xa19d,
+ 0xa1a1, 0xa1a2, 0xa1a3, 0xa1a4, 0xa1a5, 0xa1a6, 0xa1a7, 0xa1a8,
+ 0xa1a9, 0xa1aa, 0xa1ab, 0xa1ac, 0xa1ad, 0xa1ae, 0xa1af, 0xa1b0,
+ 0xa1b1, 0xa1b3, 0xa1b4, 0xa1b5, 0xa1b6, 0xa1b7, 0xa1b8, 0xa1b9,
+ 0xa1ba, 0xa1bb, 0xa1bc, 0xa1bd, 0xa1c1, 0xa1c2, 0xa1c3, 0xa1c4,
+ 0xa1c5, 0xa1c6, 0xa1c7, 0xa1c8, 0xa1c9, 0xa1ca, 0xa1cb, 0xa1cc,
+ 0xa1cd, 0xa1ce, 0xa1cf, 0xa1d0, 0xa1d1, 0xa1d3, 0xa1d4, 0xa1d5,
+ 0xa1d6, 0xa1d7, 0xa1d8, 0xa1d9, 0xa1da, 0xa1db, 0xa1dc, 0xa1dd,
+ 0xa1e1, 0xa1e2, 0xa1e3, 0xa1e4, 0xa1e5, 0xa1e6, 0xa1e7, 0xa1e8,
+ 0xa1e9, 0xa1ea, 0xa1eb, 0xa1ec, 0xa1ed, 0xa1ee, 0xa1ef, 0xa1f0,
+ 0xa1f1, 0xa1f3, 0xa1f4, 0xa1f5, 0xa1f6, 0xa1f7, 0xa1f8, 0xa1f9,
+ 0xa1fa, 0xa1fb, 0xa1fc, 0xa1fd, 0xa241, 0xa242, 0xa243, 0xa244
+};
+
+static unsigned short johab_from_unicode_bb[] = {
+ 0xa245, 0xa246, 0xa247, 0xa248, 0xa249, 0xa24a, 0xa24b, 0xa24c,
+ 0xa24d, 0xa24e, 0xa24f, 0xa250, 0xa251, 0xa253, 0xa254, 0xa255,
+ 0xa256, 0xa257, 0xa258, 0xa259, 0xa25a, 0xa25b, 0xa25c, 0xa25d,
+ 0xa261, 0xa262, 0xa263, 0xa264, 0xa265, 0xa266, 0xa267, 0xa268,
+ 0xa269, 0xa26a, 0xa26b, 0xa26c, 0xa26d, 0xa26e, 0xa26f, 0xa270,
+ 0xa271, 0xa273, 0xa274, 0xa275, 0xa276, 0xa277, 0xa278, 0xa279,
+ 0xa27a, 0xa27b, 0xa27c, 0xa27d, 0xa281, 0xa282, 0xa283, 0xa284,
+ 0xa285, 0xa286, 0xa287, 0xa288, 0xa289, 0xa28a, 0xa28b, 0xa28c,
+ 0xa28d, 0xa28e, 0xa28f, 0xa290, 0xa291, 0xa293, 0xa294, 0xa295,
+ 0xa296, 0xa297, 0xa298, 0xa299, 0xa29a, 0xa29b, 0xa29c, 0xa29d,
+ 0xa2a1, 0xa2a2, 0xa2a3, 0xa2a4, 0xa2a5, 0xa2a6, 0xa2a7, 0xa2a8,
+ 0xa2a9, 0xa2aa, 0xa2ab, 0xa2ac, 0xa2ad, 0xa2ae, 0xa2af, 0xa2b0,
+ 0xa2b1, 0xa2b3, 0xa2b4, 0xa2b5, 0xa2b6, 0xa2b7, 0xa2b8, 0xa2b9,
+ 0xa2ba, 0xa2bb, 0xa2bc, 0xa2bd, 0xa2c1, 0xa2c2, 0xa2c3, 0xa2c4,
+ 0xa2c5, 0xa2c6, 0xa2c7, 0xa2c8, 0xa2c9, 0xa2ca, 0xa2cb, 0xa2cc,
+ 0xa2cd, 0xa2ce, 0xa2cf, 0xa2d0, 0xa2d1, 0xa2d3, 0xa2d4, 0xa2d5,
+ 0xa2d6, 0xa2d7, 0xa2d8, 0xa2d9, 0xa2da, 0xa2db, 0xa2dc, 0xa2dd,
+ 0xa2e1, 0xa2e2, 0xa2e3, 0xa2e4, 0xa2e5, 0xa2e6, 0xa2e7, 0xa2e8,
+ 0xa2e9, 0xa2ea, 0xa2eb, 0xa2ec, 0xa2ed, 0xa2ee, 0xa2ef, 0xa2f0,
+ 0xa2f1, 0xa2f3, 0xa2f4, 0xa2f5, 0xa2f6, 0xa2f7, 0xa2f8, 0xa2f9,
+ 0xa2fa, 0xa2fb, 0xa2fc, 0xa2fd, 0xa341, 0xa342, 0xa343, 0xa344,
+ 0xa345, 0xa346, 0xa347, 0xa348, 0xa349, 0xa34a, 0xa34b, 0xa34c,
+ 0xa34d, 0xa34e, 0xa34f, 0xa350, 0xa351, 0xa353, 0xa354, 0xa355,
+ 0xa356, 0xa357, 0xa358, 0xa359, 0xa35a, 0xa35b, 0xa35c, 0xa35d,
+ 0xa361, 0xa362, 0xa363, 0xa364, 0xa365, 0xa366, 0xa367, 0xa368,
+ 0xa369, 0xa36a, 0xa36b, 0xa36c, 0xa36d, 0xa36e, 0xa36f, 0xa370,
+ 0xa371, 0xa373, 0xa374, 0xa375, 0xa376, 0xa377, 0xa378, 0xa379,
+ 0xa37a, 0xa37b, 0xa37c, 0xa37d, 0xa381, 0xa382, 0xa383, 0xa384,
+ 0xa385, 0xa386, 0xa387, 0xa388, 0xa389, 0xa38a, 0xa38b, 0xa38c,
+ 0xa38d, 0xa38e, 0xa38f, 0xa390, 0xa391, 0xa393, 0xa394, 0xa395,
+ 0xa396, 0xa397, 0xa398, 0xa399, 0xa39a, 0xa39b, 0xa39c, 0xa39d,
+ 0xa3a1, 0xa3a2, 0xa3a3, 0xa3a4, 0xa3a5, 0xa3a6, 0xa3a7, 0xa3a8
+};
+
+static unsigned short johab_from_unicode_bc[] = {
+ 0xa3a9, 0xa3aa, 0xa3ab, 0xa3ac, 0xa3ad, 0xa3ae, 0xa3af, 0xa3b0,
+ 0xa3b1, 0xa3b3, 0xa3b4, 0xa3b5, 0xa3b6, 0xa3b7, 0xa3b8, 0xa3b9,
+ 0xa3ba, 0xa3bb, 0xa3bc, 0xa3bd, 0xa461, 0xa462, 0xa463, 0xa464,
+ 0xa465, 0xa466, 0xa467, 0xa468, 0xa469, 0xa46a, 0xa46b, 0xa46c,
+ 0xa46d, 0xa46e, 0xa46f, 0xa470, 0xa471, 0xa473, 0xa474, 0xa475,
+ 0xa476, 0xa477, 0xa478, 0xa479, 0xa47a, 0xa47b, 0xa47c, 0xa47d,
+ 0xa481, 0xa482, 0xa483, 0xa484, 0xa485, 0xa486, 0xa487, 0xa488,
+ 0xa489, 0xa48a, 0xa48b, 0xa48c, 0xa48d, 0xa48e, 0xa48f, 0xa490,
+ 0xa491, 0xa493, 0xa494, 0xa495, 0xa496, 0xa497, 0xa498, 0xa499,
+ 0xa49a, 0xa49b, 0xa49c, 0xa49d, 0xa4a1, 0xa4a2, 0xa4a3, 0xa4a4,
+ 0xa4a5, 0xa4a6, 0xa4a7, 0xa4a8, 0xa4a9, 0xa4aa, 0xa4ab, 0xa4ac,
+ 0xa4ad, 0xa4ae, 0xa4af, 0xa4b0, 0xa4b1, 0xa4b3, 0xa4b4, 0xa4b5,
+ 0xa4b6, 0xa4b7, 0xa4b8, 0xa4b9, 0xa4ba, 0xa4bb, 0xa4bc, 0xa4bd,
+ 0xa4c1, 0xa4c2, 0xa4c3, 0xa4c4, 0xa4c5, 0xa4c6, 0xa4c7, 0xa4c8,
+ 0xa4c9, 0xa4ca, 0xa4cb, 0xa4cc, 0xa4cd, 0xa4ce, 0xa4cf, 0xa4d0,
+ 0xa4d1, 0xa4d3, 0xa4d4, 0xa4d5, 0xa4d6, 0xa4d7, 0xa4d8, 0xa4d9,
+ 0xa4da, 0xa4db, 0xa4dc, 0xa4dd, 0xa4e1, 0xa4e2, 0xa4e3, 0xa4e4,
+ 0xa4e5, 0xa4e6, 0xa4e7, 0xa4e8, 0xa4e9, 0xa4ea, 0xa4eb, 0xa4ec,
+ 0xa4ed, 0xa4ee, 0xa4ef, 0xa4f0, 0xa4f1, 0xa4f3, 0xa4f4, 0xa4f5,
+ 0xa4f6, 0xa4f7, 0xa4f8, 0xa4f9, 0xa4fa, 0xa4fb, 0xa4fc, 0xa4fd,
+ 0xa541, 0xa542, 0xa543, 0xa544, 0xa545, 0xa546, 0xa547, 0xa548,
+ 0xa549, 0xa54a, 0xa54b, 0xa54c, 0xa54d, 0xa54e, 0xa54f, 0xa550,
+ 0xa551, 0xa553, 0xa554, 0xa555, 0xa556, 0xa557, 0xa558, 0xa559,
+ 0xa55a, 0xa55b, 0xa55c, 0xa55d, 0xa561, 0xa562, 0xa563, 0xa564,
+ 0xa565, 0xa566, 0xa567, 0xa568, 0xa569, 0xa56a, 0xa56b, 0xa56c,
+ 0xa56d, 0xa56e, 0xa56f, 0xa570, 0xa571, 0xa573, 0xa574, 0xa575,
+ 0xa576, 0xa577, 0xa578, 0xa579, 0xa57a, 0xa57b, 0xa57c, 0xa57d,
+ 0xa581, 0xa582, 0xa583, 0xa584, 0xa585, 0xa586, 0xa587, 0xa588,
+ 0xa589, 0xa58a, 0xa58b, 0xa58c, 0xa58d, 0xa58e, 0xa58f, 0xa590,
+ 0xa591, 0xa593, 0xa594, 0xa595, 0xa596, 0xa597, 0xa598, 0xa599,
+ 0xa59a, 0xa59b, 0xa59c, 0xa59d, 0xa5a1, 0xa5a2, 0xa5a3, 0xa5a4,
+ 0xa5a5, 0xa5a6, 0xa5a7, 0xa5a8, 0xa5a9, 0xa5aa, 0xa5ab, 0xa5ac
+};
+
+static unsigned short johab_from_unicode_bd[] = {
+ 0xa5ad, 0xa5ae, 0xa5af, 0xa5b0, 0xa5b1, 0xa5b3, 0xa5b4, 0xa5b5,
+ 0xa5b6, 0xa5b7, 0xa5b8, 0xa5b9, 0xa5ba, 0xa5bb, 0xa5bc, 0xa5bd,
+ 0xa5c1, 0xa5c2, 0xa5c3, 0xa5c4, 0xa5c5, 0xa5c6, 0xa5c7, 0xa5c8,
+ 0xa5c9, 0xa5ca, 0xa5cb, 0xa5cc, 0xa5cd, 0xa5ce, 0xa5cf, 0xa5d0,
+ 0xa5d1, 0xa5d3, 0xa5d4, 0xa5d5, 0xa5d6, 0xa5d7, 0xa5d8, 0xa5d9,
+ 0xa5da, 0xa5db, 0xa5dc, 0xa5dd, 0xa5e1, 0xa5e2, 0xa5e3, 0xa5e4,
+ 0xa5e5, 0xa5e6, 0xa5e7, 0xa5e8, 0xa5e9, 0xa5ea, 0xa5eb, 0xa5ec,
+ 0xa5ed, 0xa5ee, 0xa5ef, 0xa5f0, 0xa5f1, 0xa5f3, 0xa5f4, 0xa5f5,
+ 0xa5f6, 0xa5f7, 0xa5f8, 0xa5f9, 0xa5fa, 0xa5fb, 0xa5fc, 0xa5fd,
+ 0xa641, 0xa642, 0xa643, 0xa644, 0xa645, 0xa646, 0xa647, 0xa648,
+ 0xa649, 0xa64a, 0xa64b, 0xa64c, 0xa64d, 0xa64e, 0xa64f, 0xa650,
+ 0xa651, 0xa653, 0xa654, 0xa655, 0xa656, 0xa657, 0xa658, 0xa659,
+ 0xa65a, 0xa65b, 0xa65c, 0xa65d, 0xa661, 0xa662, 0xa663, 0xa664,
+ 0xa665, 0xa666, 0xa667, 0xa668, 0xa669, 0xa66a, 0xa66b, 0xa66c,
+ 0xa66d, 0xa66e, 0xa66f, 0xa670, 0xa671, 0xa673, 0xa674, 0xa675,
+ 0xa676, 0xa677, 0xa678, 0xa679, 0xa67a, 0xa67b, 0xa67c, 0xa67d,
+ 0xa681, 0xa682, 0xa683, 0xa684, 0xa685, 0xa686, 0xa687, 0xa688,
+ 0xa689, 0xa68a, 0xa68b, 0xa68c, 0xa68d, 0xa68e, 0xa68f, 0xa690,
+ 0xa691, 0xa693, 0xa694, 0xa695, 0xa696, 0xa697, 0xa698, 0xa699,
+ 0xa69a, 0xa69b, 0xa69c, 0xa69d, 0xa6a1, 0xa6a2, 0xa6a3, 0xa6a4,
+ 0xa6a5, 0xa6a6, 0xa6a7, 0xa6a8, 0xa6a9, 0xa6aa, 0xa6ab, 0xa6ac,
+ 0xa6ad, 0xa6ae, 0xa6af, 0xa6b0, 0xa6b1, 0xa6b3, 0xa6b4, 0xa6b5,
+ 0xa6b6, 0xa6b7, 0xa6b8, 0xa6b9, 0xa6ba, 0xa6bb, 0xa6bc, 0xa6bd,
+ 0xa6c1, 0xa6c2, 0xa6c3, 0xa6c4, 0xa6c5, 0xa6c6, 0xa6c7, 0xa6c8,
+ 0xa6c9, 0xa6ca, 0xa6cb, 0xa6cc, 0xa6cd, 0xa6ce, 0xa6cf, 0xa6d0,
+ 0xa6d1, 0xa6d3, 0xa6d4, 0xa6d5, 0xa6d6, 0xa6d7, 0xa6d8, 0xa6d9,
+ 0xa6da, 0xa6db, 0xa6dc, 0xa6dd, 0xa6e1, 0xa6e2, 0xa6e3, 0xa6e4,
+ 0xa6e5, 0xa6e6, 0xa6e7, 0xa6e8, 0xa6e9, 0xa6ea, 0xa6eb, 0xa6ec,
+ 0xa6ed, 0xa6ee, 0xa6ef, 0xa6f0, 0xa6f1, 0xa6f3, 0xa6f4, 0xa6f5,
+ 0xa6f6, 0xa6f7, 0xa6f8, 0xa6f9, 0xa6fa, 0xa6fb, 0xa6fc, 0xa6fd,
+ 0xa741, 0xa742, 0xa743, 0xa744, 0xa745, 0xa746, 0xa747, 0xa748,
+ 0xa749, 0xa74a, 0xa74b, 0xa74c, 0xa74d, 0xa74e, 0xa74f, 0xa750
+};
+
+static unsigned short johab_from_unicode_be[] = {
+ 0xa751, 0xa753, 0xa754, 0xa755, 0xa756, 0xa757, 0xa758, 0xa759,
+ 0xa75a, 0xa75b, 0xa75c, 0xa75d, 0xa761, 0xa762, 0xa763, 0xa764,
+ 0xa765, 0xa766, 0xa767, 0xa768, 0xa769, 0xa76a, 0xa76b, 0xa76c,
+ 0xa76d, 0xa76e, 0xa76f, 0xa770, 0xa771, 0xa773, 0xa774, 0xa775,
+ 0xa776, 0xa777, 0xa778, 0xa779, 0xa77a, 0xa77b, 0xa77c, 0xa77d,
+ 0xa781, 0xa782, 0xa783, 0xa784, 0xa785, 0xa786, 0xa787, 0xa788,
+ 0xa789, 0xa78a, 0xa78b, 0xa78c, 0xa78d, 0xa78e, 0xa78f, 0xa790,
+ 0xa791, 0xa793, 0xa794, 0xa795, 0xa796, 0xa797, 0xa798, 0xa799,
+ 0xa79a, 0xa79b, 0xa79c, 0xa79d, 0xa7a1, 0xa7a2, 0xa7a3, 0xa7a4,
+ 0xa7a5, 0xa7a6, 0xa7a7, 0xa7a8, 0xa7a9, 0xa7aa, 0xa7ab, 0xa7ac,
+ 0xa7ad, 0xa7ae, 0xa7af, 0xa7b0, 0xa7b1, 0xa7b3, 0xa7b4, 0xa7b5,
+ 0xa7b6, 0xa7b7, 0xa7b8, 0xa7b9, 0xa7ba, 0xa7bb, 0xa7bc, 0xa7bd,
+ 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866, 0xa867, 0xa868,
+ 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f, 0xa870,
+ 0xa871, 0xa873, 0xa874, 0xa875, 0xa876, 0xa877, 0xa878, 0xa879,
+ 0xa87a, 0xa87b, 0xa87c, 0xa87d, 0xa881, 0xa882, 0xa883, 0xa884,
+ 0xa885, 0xa886, 0xa887, 0xa888, 0xa889, 0xa88a, 0xa88b, 0xa88c,
+ 0xa88d, 0xa88e, 0xa88f, 0xa890, 0xa891, 0xa893, 0xa894, 0xa895,
+ 0xa896, 0xa897, 0xa898, 0xa899, 0xa89a, 0xa89b, 0xa89c, 0xa89d,
+ 0xa8a1, 0xa8a2, 0xa8a3, 0xa8a4, 0xa8a5, 0xa8a6, 0xa8a7, 0xa8a8,
+ 0xa8a9, 0xa8aa, 0xa8ab, 0xa8ac, 0xa8ad, 0xa8ae, 0xa8af, 0xa8b0,
+ 0xa8b1, 0xa8b3, 0xa8b4, 0xa8b5, 0xa8b6, 0xa8b7, 0xa8b8, 0xa8b9,
+ 0xa8ba, 0xa8bb, 0xa8bc, 0xa8bd, 0xa8c1, 0xa8c2, 0xa8c3, 0xa8c4,
+ 0xa8c5, 0xa8c6, 0xa8c7, 0xa8c8, 0xa8c9, 0xa8ca, 0xa8cb, 0xa8cc,
+ 0xa8cd, 0xa8ce, 0xa8cf, 0xa8d0, 0xa8d1, 0xa8d3, 0xa8d4, 0xa8d5,
+ 0xa8d6, 0xa8d7, 0xa8d8, 0xa8d9, 0xa8da, 0xa8db, 0xa8dc, 0xa8dd,
+ 0xa8e1, 0xa8e2, 0xa8e3, 0xa8e4, 0xa8e5, 0xa8e6, 0xa8e7, 0xa8e8,
+ 0xa8e9, 0xa8ea, 0xa8eb, 0xa8ec, 0xa8ed, 0xa8ee, 0xa8ef, 0xa8f0,
+ 0xa8f1, 0xa8f3, 0xa8f4, 0xa8f5, 0xa8f6, 0xa8f7, 0xa8f8, 0xa8f9,
+ 0xa8fa, 0xa8fb, 0xa8fc, 0xa8fd, 0xa941, 0xa942, 0xa943, 0xa944,
+ 0xa945, 0xa946, 0xa947, 0xa948, 0xa949, 0xa94a, 0xa94b, 0xa94c,
+ 0xa94d, 0xa94e, 0xa94f, 0xa950, 0xa951, 0xa953, 0xa954, 0xa955
+};
+
+static unsigned short johab_from_unicode_bf[] = {
+ 0xa956, 0xa957, 0xa958, 0xa959, 0xa95a, 0xa95b, 0xa95c, 0xa95d,
+ 0xa961, 0xa962, 0xa963, 0xa964, 0xa965, 0xa966, 0xa967, 0xa968,
+ 0xa969, 0xa96a, 0xa96b, 0xa96c, 0xa96d, 0xa96e, 0xa96f, 0xa970,
+ 0xa971, 0xa973, 0xa974, 0xa975, 0xa976, 0xa977, 0xa978, 0xa979,
+ 0xa97a, 0xa97b, 0xa97c, 0xa97d, 0xa981, 0xa982, 0xa983, 0xa984,
+ 0xa985, 0xa986, 0xa987, 0xa988, 0xa989, 0xa98a, 0xa98b, 0xa98c,
+ 0xa98d, 0xa98e, 0xa98f, 0xa990, 0xa991, 0xa993, 0xa994, 0xa995,
+ 0xa996, 0xa997, 0xa998, 0xa999, 0xa99a, 0xa99b, 0xa99c, 0xa99d,
+ 0xa9a1, 0xa9a2, 0xa9a3, 0xa9a4, 0xa9a5, 0xa9a6, 0xa9a7, 0xa9a8,
+ 0xa9a9, 0xa9aa, 0xa9ab, 0xa9ac, 0xa9ad, 0xa9ae, 0xa9af, 0xa9b0,
+ 0xa9b1, 0xa9b3, 0xa9b4, 0xa9b5, 0xa9b6, 0xa9b7, 0xa9b8, 0xa9b9,
+ 0xa9ba, 0xa9bb, 0xa9bc, 0xa9bd, 0xa9c1, 0xa9c2, 0xa9c3, 0xa9c4,
+ 0xa9c5, 0xa9c6, 0xa9c7, 0xa9c8, 0xa9c9, 0xa9ca, 0xa9cb, 0xa9cc,
+ 0xa9cd, 0xa9ce, 0xa9cf, 0xa9d0, 0xa9d1, 0xa9d3, 0xa9d4, 0xa9d5,
+ 0xa9d6, 0xa9d7, 0xa9d8, 0xa9d9, 0xa9da, 0xa9db, 0xa9dc, 0xa9dd,
+ 0xa9e1, 0xa9e2, 0xa9e3, 0xa9e4, 0xa9e5, 0xa9e6, 0xa9e7, 0xa9e8,
+ 0xa9e9, 0xa9ea, 0xa9eb, 0xa9ec, 0xa9ed, 0xa9ee, 0xa9ef, 0xa9f0,
+ 0xa9f1, 0xa9f3, 0xa9f4, 0xa9f5, 0xa9f6, 0xa9f7, 0xa9f8, 0xa9f9,
+ 0xa9fa, 0xa9fb, 0xa9fc, 0xa9fd, 0xaa41, 0xaa42, 0xaa43, 0xaa44,
+ 0xaa45, 0xaa46, 0xaa47, 0xaa48, 0xaa49, 0xaa4a, 0xaa4b, 0xaa4c,
+ 0xaa4d, 0xaa4e, 0xaa4f, 0xaa50, 0xaa51, 0xaa53, 0xaa54, 0xaa55,
+ 0xaa56, 0xaa57, 0xaa58, 0xaa59, 0xaa5a, 0xaa5b, 0xaa5c, 0xaa5d,
+ 0xaa61, 0xaa62, 0xaa63, 0xaa64, 0xaa65, 0xaa66, 0xaa67, 0xaa68,
+ 0xaa69, 0xaa6a, 0xaa6b, 0xaa6c, 0xaa6d, 0xaa6e, 0xaa6f, 0xaa70,
+ 0xaa71, 0xaa73, 0xaa74, 0xaa75, 0xaa76, 0xaa77, 0xaa78, 0xaa79,
+ 0xaa7a, 0xaa7b, 0xaa7c, 0xaa7d, 0xaa81, 0xaa82, 0xaa83, 0xaa84,
+ 0xaa85, 0xaa86, 0xaa87, 0xaa88, 0xaa89, 0xaa8a, 0xaa8b, 0xaa8c,
+ 0xaa8d, 0xaa8e, 0xaa8f, 0xaa90, 0xaa91, 0xaa93, 0xaa94, 0xaa95,
+ 0xaa96, 0xaa97, 0xaa98, 0xaa99, 0xaa9a, 0xaa9b, 0xaa9c, 0xaa9d,
+ 0xaaa1, 0xaaa2, 0xaaa3, 0xaaa4, 0xaaa5, 0xaaa6, 0xaaa7, 0xaaa8,
+ 0xaaa9, 0xaaaa, 0xaaab, 0xaaac, 0xaaad, 0xaaae, 0xaaaf, 0xaab0,
+ 0xaab1, 0xaab3, 0xaab4, 0xaab5, 0xaab6, 0xaab7, 0xaab8, 0xaab9
+};
+
+static unsigned short johab_from_unicode_c0[] = {
+ 0xaaba, 0xaabb, 0xaabc, 0xaabd, 0xaac1, 0xaac2, 0xaac3, 0xaac4,
+ 0xaac5, 0xaac6, 0xaac7, 0xaac8, 0xaac9, 0xaaca, 0xaacb, 0xaacc,
+ 0xaacd, 0xaace, 0xaacf, 0xaad0, 0xaad1, 0xaad3, 0xaad4, 0xaad5,
+ 0xaad6, 0xaad7, 0xaad8, 0xaad9, 0xaada, 0xaadb, 0xaadc, 0xaadd,
+ 0xaae1, 0xaae2, 0xaae3, 0xaae4, 0xaae5, 0xaae6, 0xaae7, 0xaae8,
+ 0xaae9, 0xaaea, 0xaaeb, 0xaaec, 0xaaed, 0xaaee, 0xaaef, 0xaaf0,
+ 0xaaf1, 0xaaf3, 0xaaf4, 0xaaf5, 0xaaf6, 0xaaf7, 0xaaf8, 0xaaf9,
+ 0xaafa, 0xaafb, 0xaafc, 0xaafd, 0xab41, 0xab42, 0xab43, 0xab44,
+ 0xab45, 0xab46, 0xab47, 0xab48, 0xab49, 0xab4a, 0xab4b, 0xab4c,
+ 0xab4d, 0xab4e, 0xab4f, 0xab50, 0xab51, 0xab53, 0xab54, 0xab55,
+ 0xab56, 0xab57, 0xab58, 0xab59, 0xab5a, 0xab5b, 0xab5c, 0xab5d,
+ 0xab61, 0xab62, 0xab63, 0xab64, 0xab65, 0xab66, 0xab67, 0xab68,
+ 0xab69, 0xab6a, 0xab6b, 0xab6c, 0xab6d, 0xab6e, 0xab6f, 0xab70,
+ 0xab71, 0xab73, 0xab74, 0xab75, 0xab76, 0xab77, 0xab78, 0xab79,
+ 0xab7a, 0xab7b, 0xab7c, 0xab7d, 0xab81, 0xab82, 0xab83, 0xab84,
+ 0xab85, 0xab86, 0xab87, 0xab88, 0xab89, 0xab8a, 0xab8b, 0xab8c,
+ 0xab8d, 0xab8e, 0xab8f, 0xab90, 0xab91, 0xab93, 0xab94, 0xab95,
+ 0xab96, 0xab97, 0xab98, 0xab99, 0xab9a, 0xab9b, 0xab9c, 0xab9d,
+ 0xaba1, 0xaba2, 0xaba3, 0xaba4, 0xaba5, 0xaba6, 0xaba7, 0xaba8,
+ 0xaba9, 0xabaa, 0xabab, 0xabac, 0xabad, 0xabae, 0xabaf, 0xabb0,
+ 0xabb1, 0xabb3, 0xabb4, 0xabb5, 0xabb6, 0xabb7, 0xabb8, 0xabb9,
+ 0xabba, 0xabbb, 0xabbc, 0xabbd, 0xac61, 0xac62, 0xac63, 0xac64,
+ 0xac65, 0xac66, 0xac67, 0xac68, 0xac69, 0xac6a, 0xac6b, 0xac6c,
+ 0xac6d, 0xac6e, 0xac6f, 0xac70, 0xac71, 0xac73, 0xac74, 0xac75,
+ 0xac76, 0xac77, 0xac78, 0xac79, 0xac7a, 0xac7b, 0xac7c, 0xac7d,
+ 0xac81, 0xac82, 0xac83, 0xac84, 0xac85, 0xac86, 0xac87, 0xac88,
+ 0xac89, 0xac8a, 0xac8b, 0xac8c, 0xac8d, 0xac8e, 0xac8f, 0xac90,
+ 0xac91, 0xac93, 0xac94, 0xac95, 0xac96, 0xac97, 0xac98, 0xac99,
+ 0xac9a, 0xac9b, 0xac9c, 0xac9d, 0xaca1, 0xaca2, 0xaca3, 0xaca4,
+ 0xaca5, 0xaca6, 0xaca7, 0xaca8, 0xaca9, 0xacaa, 0xacab, 0xacac,
+ 0xacad, 0xacae, 0xacaf, 0xacb0, 0xacb1, 0xacb3, 0xacb4, 0xacb5,
+ 0xacb6, 0xacb7, 0xacb8, 0xacb9, 0xacba, 0xacbb, 0xacbc, 0xacbd
+};
+
+static unsigned short johab_from_unicode_c1[] = {
+ 0xacc1, 0xacc2, 0xacc3, 0xacc4, 0xacc5, 0xacc6, 0xacc7, 0xacc8,
+ 0xacc9, 0xacca, 0xaccb, 0xaccc, 0xaccd, 0xacce, 0xaccf, 0xacd0,
+ 0xacd1, 0xacd3, 0xacd4, 0xacd5, 0xacd6, 0xacd7, 0xacd8, 0xacd9,
+ 0xacda, 0xacdb, 0xacdc, 0xacdd, 0xace1, 0xace2, 0xace3, 0xace4,
+ 0xace5, 0xace6, 0xace7, 0xace8, 0xace9, 0xacea, 0xaceb, 0xacec,
+ 0xaced, 0xacee, 0xacef, 0xacf0, 0xacf1, 0xacf3, 0xacf4, 0xacf5,
+ 0xacf6, 0xacf7, 0xacf8, 0xacf9, 0xacfa, 0xacfb, 0xacfc, 0xacfd,
+ 0xad41, 0xad42, 0xad43, 0xad44, 0xad45, 0xad46, 0xad47, 0xad48,
+ 0xad49, 0xad4a, 0xad4b, 0xad4c, 0xad4d, 0xad4e, 0xad4f, 0xad50,
+ 0xad51, 0xad53, 0xad54, 0xad55, 0xad56, 0xad57, 0xad58, 0xad59,
+ 0xad5a, 0xad5b, 0xad5c, 0xad5d, 0xad61, 0xad62, 0xad63, 0xad64,
+ 0xad65, 0xad66, 0xad67, 0xad68, 0xad69, 0xad6a, 0xad6b, 0xad6c,
+ 0xad6d, 0xad6e, 0xad6f, 0xad70, 0xad71, 0xad73, 0xad74, 0xad75,
+ 0xad76, 0xad77, 0xad78, 0xad79, 0xad7a, 0xad7b, 0xad7c, 0xad7d,
+ 0xad81, 0xad82, 0xad83, 0xad84, 0xad85, 0xad86, 0xad87, 0xad88,
+ 0xad89, 0xad8a, 0xad8b, 0xad8c, 0xad8d, 0xad8e, 0xad8f, 0xad90,
+ 0xad91, 0xad93, 0xad94, 0xad95, 0xad96, 0xad97, 0xad98, 0xad99,
+ 0xad9a, 0xad9b, 0xad9c, 0xad9d, 0xada1, 0xada2, 0xada3, 0xada4,
+ 0xada5, 0xada6, 0xada7, 0xada8, 0xada9, 0xadaa, 0xadab, 0xadac,
+ 0xadad, 0xadae, 0xadaf, 0xadb0, 0xadb1, 0xadb3, 0xadb4, 0xadb5,
+ 0xadb6, 0xadb7, 0xadb8, 0xadb9, 0xadba, 0xadbb, 0xadbc, 0xadbd,
+ 0xadc1, 0xadc2, 0xadc3, 0xadc4, 0xadc5, 0xadc6, 0xadc7, 0xadc8,
+ 0xadc9, 0xadca, 0xadcb, 0xadcc, 0xadcd, 0xadce, 0xadcf, 0xadd0,
+ 0xadd1, 0xadd3, 0xadd4, 0xadd5, 0xadd6, 0xadd7, 0xadd8, 0xadd9,
+ 0xadda, 0xaddb, 0xaddc, 0xaddd, 0xade1, 0xade2, 0xade3, 0xade4,
+ 0xade5, 0xade6, 0xade7, 0xade8, 0xade9, 0xadea, 0xadeb, 0xadec,
+ 0xaded, 0xadee, 0xadef, 0xadf0, 0xadf1, 0xadf3, 0xadf4, 0xadf5,
+ 0xadf6, 0xadf7, 0xadf8, 0xadf9, 0xadfa, 0xadfb, 0xadfc, 0xadfd,
+ 0xae41, 0xae42, 0xae43, 0xae44, 0xae45, 0xae46, 0xae47, 0xae48,
+ 0xae49, 0xae4a, 0xae4b, 0xae4c, 0xae4d, 0xae4e, 0xae4f, 0xae50,
+ 0xae51, 0xae53, 0xae54, 0xae55, 0xae56, 0xae57, 0xae58, 0xae59,
+ 0xae5a, 0xae5b, 0xae5c, 0xae5d, 0xae61, 0xae62, 0xae63, 0xae64
+};
+
+static unsigned short johab_from_unicode_c2[] = {
+ 0xae65, 0xae66, 0xae67, 0xae68, 0xae69, 0xae6a, 0xae6b, 0xae6c,
+ 0xae6d, 0xae6e, 0xae6f, 0xae70, 0xae71, 0xae73, 0xae74, 0xae75,
+ 0xae76, 0xae77, 0xae78, 0xae79, 0xae7a, 0xae7b, 0xae7c, 0xae7d,
+ 0xae81, 0xae82, 0xae83, 0xae84, 0xae85, 0xae86, 0xae87, 0xae88,
+ 0xae89, 0xae8a, 0xae8b, 0xae8c, 0xae8d, 0xae8e, 0xae8f, 0xae90,
+ 0xae91, 0xae93, 0xae94, 0xae95, 0xae96, 0xae97, 0xae98, 0xae99,
+ 0xae9a, 0xae9b, 0xae9c, 0xae9d, 0xaea1, 0xaea2, 0xaea3, 0xaea4,
+ 0xaea5, 0xaea6, 0xaea7, 0xaea8, 0xaea9, 0xaeaa, 0xaeab, 0xaeac,
+ 0xaead, 0xaeae, 0xaeaf, 0xaeb0, 0xaeb1, 0xaeb3, 0xaeb4, 0xaeb5,
+ 0xaeb6, 0xaeb7, 0xaeb8, 0xaeb9, 0xaeba, 0xaebb, 0xaebc, 0xaebd,
+ 0xaec1, 0xaec2, 0xaec3, 0xaec4, 0xaec5, 0xaec6, 0xaec7, 0xaec8,
+ 0xaec9, 0xaeca, 0xaecb, 0xaecc, 0xaecd, 0xaece, 0xaecf, 0xaed0,
+ 0xaed1, 0xaed3, 0xaed4, 0xaed5, 0xaed6, 0xaed7, 0xaed8, 0xaed9,
+ 0xaeda, 0xaedb, 0xaedc, 0xaedd, 0xaee1, 0xaee2, 0xaee3, 0xaee4,
+ 0xaee5, 0xaee6, 0xaee7, 0xaee8, 0xaee9, 0xaeea, 0xaeeb, 0xaeec,
+ 0xaeed, 0xaeee, 0xaeef, 0xaef0, 0xaef1, 0xaef3, 0xaef4, 0xaef5,
+ 0xaef6, 0xaef7, 0xaef8, 0xaef9, 0xaefa, 0xaefb, 0xaefc, 0xaefd,
+ 0xaf41, 0xaf42, 0xaf43, 0xaf44, 0xaf45, 0xaf46, 0xaf47, 0xaf48,
+ 0xaf49, 0xaf4a, 0xaf4b, 0xaf4c, 0xaf4d, 0xaf4e, 0xaf4f, 0xaf50,
+ 0xaf51, 0xaf53, 0xaf54, 0xaf55, 0xaf56, 0xaf57, 0xaf58, 0xaf59,
+ 0xaf5a, 0xaf5b, 0xaf5c, 0xaf5d, 0xaf61, 0xaf62, 0xaf63, 0xaf64,
+ 0xaf65, 0xaf66, 0xaf67, 0xaf68, 0xaf69, 0xaf6a, 0xaf6b, 0xaf6c,
+ 0xaf6d, 0xaf6e, 0xaf6f, 0xaf70, 0xaf71, 0xaf73, 0xaf74, 0xaf75,
+ 0xaf76, 0xaf77, 0xaf78, 0xaf79, 0xaf7a, 0xaf7b, 0xaf7c, 0xaf7d,
+ 0xaf81, 0xaf82, 0xaf83, 0xaf84, 0xaf85, 0xaf86, 0xaf87, 0xaf88,
+ 0xaf89, 0xaf8a, 0xaf8b, 0xaf8c, 0xaf8d, 0xaf8e, 0xaf8f, 0xaf90,
+ 0xaf91, 0xaf93, 0xaf94, 0xaf95, 0xaf96, 0xaf97, 0xaf98, 0xaf99,
+ 0xaf9a, 0xaf9b, 0xaf9c, 0xaf9d, 0xafa1, 0xafa2, 0xafa3, 0xafa4,
+ 0xafa5, 0xafa6, 0xafa7, 0xafa8, 0xafa9, 0xafaa, 0xafab, 0xafac,
+ 0xafad, 0xafae, 0xafaf, 0xafb0, 0xafb1, 0xafb3, 0xafb4, 0xafb5,
+ 0xafb6, 0xafb7, 0xafb8, 0xafb9, 0xafba, 0xafbb, 0xafbc, 0xafbd,
+ 0xb061, 0xb062, 0xb063, 0xb064, 0xb065, 0xb066, 0xb067, 0xb068
+};
+
+static unsigned short johab_from_unicode_c3[] = {
+ 0xb069, 0xb06a, 0xb06b, 0xb06c, 0xb06d, 0xb06e, 0xb06f, 0xb070,
+ 0xb071, 0xb073, 0xb074, 0xb075, 0xb076, 0xb077, 0xb078, 0xb079,
+ 0xb07a, 0xb07b, 0xb07c, 0xb07d, 0xb081, 0xb082, 0xb083, 0xb084,
+ 0xb085, 0xb086, 0xb087, 0xb088, 0xb089, 0xb08a, 0xb08b, 0xb08c,
+ 0xb08d, 0xb08e, 0xb08f, 0xb090, 0xb091, 0xb093, 0xb094, 0xb095,
+ 0xb096, 0xb097, 0xb098, 0xb099, 0xb09a, 0xb09b, 0xb09c, 0xb09d,
+ 0xb0a1, 0xb0a2, 0xb0a3, 0xb0a4, 0xb0a5, 0xb0a6, 0xb0a7, 0xb0a8,
+ 0xb0a9, 0xb0aa, 0xb0ab, 0xb0ac, 0xb0ad, 0xb0ae, 0xb0af, 0xb0b0,
+ 0xb0b1, 0xb0b3, 0xb0b4, 0xb0b5, 0xb0b6, 0xb0b7, 0xb0b8, 0xb0b9,
+ 0xb0ba, 0xb0bb, 0xb0bc, 0xb0bd, 0xb0c1, 0xb0c2, 0xb0c3, 0xb0c4,
+ 0xb0c5, 0xb0c6, 0xb0c7, 0xb0c8, 0xb0c9, 0xb0ca, 0xb0cb, 0xb0cc,
+ 0xb0cd, 0xb0ce, 0xb0cf, 0xb0d0, 0xb0d1, 0xb0d3, 0xb0d4, 0xb0d5,
+ 0xb0d6, 0xb0d7, 0xb0d8, 0xb0d9, 0xb0da, 0xb0db, 0xb0dc, 0xb0dd,
+ 0xb0e1, 0xb0e2, 0xb0e3, 0xb0e4, 0xb0e5, 0xb0e6, 0xb0e7, 0xb0e8,
+ 0xb0e9, 0xb0ea, 0xb0eb, 0xb0ec, 0xb0ed, 0xb0ee, 0xb0ef, 0xb0f0,
+ 0xb0f1, 0xb0f3, 0xb0f4, 0xb0f5, 0xb0f6, 0xb0f7, 0xb0f8, 0xb0f9,
+ 0xb0fa, 0xb0fb, 0xb0fc, 0xb0fd, 0xb141, 0xb142, 0xb143, 0xb144,
+ 0xb145, 0xb146, 0xb147, 0xb148, 0xb149, 0xb14a, 0xb14b, 0xb14c,
+ 0xb14d, 0xb14e, 0xb14f, 0xb150, 0xb151, 0xb153, 0xb154, 0xb155,
+ 0xb156, 0xb157, 0xb158, 0xb159, 0xb15a, 0xb15b, 0xb15c, 0xb15d,
+ 0xb161, 0xb162, 0xb163, 0xb164, 0xb165, 0xb166, 0xb167, 0xb168,
+ 0xb169, 0xb16a, 0xb16b, 0xb16c, 0xb16d, 0xb16e, 0xb16f, 0xb170,
+ 0xb171, 0xb173, 0xb174, 0xb175, 0xb176, 0xb177, 0xb178, 0xb179,
+ 0xb17a, 0xb17b, 0xb17c, 0xb17d, 0xb181, 0xb182, 0xb183, 0xb184,
+ 0xb185, 0xb186, 0xb187, 0xb188, 0xb189, 0xb18a, 0xb18b, 0xb18c,
+ 0xb18d, 0xb18e, 0xb18f, 0xb190, 0xb191, 0xb193, 0xb194, 0xb195,
+ 0xb196, 0xb197, 0xb198, 0xb199, 0xb19a, 0xb19b, 0xb19c, 0xb19d,
+ 0xb1a1, 0xb1a2, 0xb1a3, 0xb1a4, 0xb1a5, 0xb1a6, 0xb1a7, 0xb1a8,
+ 0xb1a9, 0xb1aa, 0xb1ab, 0xb1ac, 0xb1ad, 0xb1ae, 0xb1af, 0xb1b0,
+ 0xb1b1, 0xb1b3, 0xb1b4, 0xb1b5, 0xb1b6, 0xb1b7, 0xb1b8, 0xb1b9,
+ 0xb1ba, 0xb1bb, 0xb1bc, 0xb1bd, 0xb1c1, 0xb1c2, 0xb1c3, 0xb1c4,
+ 0xb1c5, 0xb1c6, 0xb1c7, 0xb1c8, 0xb1c9, 0xb1ca, 0xb1cb, 0xb1cc
+};
+
+static unsigned short johab_from_unicode_c4[] = {
+ 0xb1cd, 0xb1ce, 0xb1cf, 0xb1d0, 0xb1d1, 0xb1d3, 0xb1d4, 0xb1d5,
+ 0xb1d6, 0xb1d7, 0xb1d8, 0xb1d9, 0xb1da, 0xb1db, 0xb1dc, 0xb1dd,
+ 0xb1e1, 0xb1e2, 0xb1e3, 0xb1e4, 0xb1e5, 0xb1e6, 0xb1e7, 0xb1e8,
+ 0xb1e9, 0xb1ea, 0xb1eb, 0xb1ec, 0xb1ed, 0xb1ee, 0xb1ef, 0xb1f0,
+ 0xb1f1, 0xb1f3, 0xb1f4, 0xb1f5, 0xb1f6, 0xb1f7, 0xb1f8, 0xb1f9,
+ 0xb1fa, 0xb1fb, 0xb1fc, 0xb1fd, 0xb241, 0xb242, 0xb243, 0xb244,
+ 0xb245, 0xb246, 0xb247, 0xb248, 0xb249, 0xb24a, 0xb24b, 0xb24c,
+ 0xb24d, 0xb24e, 0xb24f, 0xb250, 0xb251, 0xb253, 0xb254, 0xb255,
+ 0xb256, 0xb257, 0xb258, 0xb259, 0xb25a, 0xb25b, 0xb25c, 0xb25d,
+ 0xb261, 0xb262, 0xb263, 0xb264, 0xb265, 0xb266, 0xb267, 0xb268,
+ 0xb269, 0xb26a, 0xb26b, 0xb26c, 0xb26d, 0xb26e, 0xb26f, 0xb270,
+ 0xb271, 0xb273, 0xb274, 0xb275, 0xb276, 0xb277, 0xb278, 0xb279,
+ 0xb27a, 0xb27b, 0xb27c, 0xb27d, 0xb281, 0xb282, 0xb283, 0xb284,
+ 0xb285, 0xb286, 0xb287, 0xb288, 0xb289, 0xb28a, 0xb28b, 0xb28c,
+ 0xb28d, 0xb28e, 0xb28f, 0xb290, 0xb291, 0xb293, 0xb294, 0xb295,
+ 0xb296, 0xb297, 0xb298, 0xb299, 0xb29a, 0xb29b, 0xb29c, 0xb29d,
+ 0xb2a1, 0xb2a2, 0xb2a3, 0xb2a4, 0xb2a5, 0xb2a6, 0xb2a7, 0xb2a8,
+ 0xb2a9, 0xb2aa, 0xb2ab, 0xb2ac, 0xb2ad, 0xb2ae, 0xb2af, 0xb2b0,
+ 0xb2b1, 0xb2b3, 0xb2b4, 0xb2b5, 0xb2b6, 0xb2b7, 0xb2b8, 0xb2b9,
+ 0xb2ba, 0xb2bb, 0xb2bc, 0xb2bd, 0xb2c1, 0xb2c2, 0xb2c3, 0xb2c4,
+ 0xb2c5, 0xb2c6, 0xb2c7, 0xb2c8, 0xb2c9, 0xb2ca, 0xb2cb, 0xb2cc,
+ 0xb2cd, 0xb2ce, 0xb2cf, 0xb2d0, 0xb2d1, 0xb2d3, 0xb2d4, 0xb2d5,
+ 0xb2d6, 0xb2d7, 0xb2d8, 0xb2d9, 0xb2da, 0xb2db, 0xb2dc, 0xb2dd,
+ 0xb2e1, 0xb2e2, 0xb2e3, 0xb2e4, 0xb2e5, 0xb2e6, 0xb2e7, 0xb2e8,
+ 0xb2e9, 0xb2ea, 0xb2eb, 0xb2ec, 0xb2ed, 0xb2ee, 0xb2ef, 0xb2f0,
+ 0xb2f1, 0xb2f3, 0xb2f4, 0xb2f5, 0xb2f6, 0xb2f7, 0xb2f8, 0xb2f9,
+ 0xb2fa, 0xb2fb, 0xb2fc, 0xb2fd, 0xb341, 0xb342, 0xb343, 0xb344,
+ 0xb345, 0xb346, 0xb347, 0xb348, 0xb349, 0xb34a, 0xb34b, 0xb34c,
+ 0xb34d, 0xb34e, 0xb34f, 0xb350, 0xb351, 0xb353, 0xb354, 0xb355,
+ 0xb356, 0xb357, 0xb358, 0xb359, 0xb35a, 0xb35b, 0xb35c, 0xb35d,
+ 0xb361, 0xb362, 0xb363, 0xb364, 0xb365, 0xb366, 0xb367, 0xb368,
+ 0xb369, 0xb36a, 0xb36b, 0xb36c, 0xb36d, 0xb36e, 0xb36f, 0xb370
+};
+
+static unsigned short johab_from_unicode_c5[] = {
+ 0xb371, 0xb373, 0xb374, 0xb375, 0xb376, 0xb377, 0xb378, 0xb379,
+ 0xb37a, 0xb37b, 0xb37c, 0xb37d, 0xb381, 0xb382, 0xb383, 0xb384,
+ 0xb385, 0xb386, 0xb387, 0xb388, 0xb389, 0xb38a, 0xb38b, 0xb38c,
+ 0xb38d, 0xb38e, 0xb38f, 0xb390, 0xb391, 0xb393, 0xb394, 0xb395,
+ 0xb396, 0xb397, 0xb398, 0xb399, 0xb39a, 0xb39b, 0xb39c, 0xb39d,
+ 0xb3a1, 0xb3a2, 0xb3a3, 0xb3a4, 0xb3a5, 0xb3a6, 0xb3a7, 0xb3a8,
+ 0xb3a9, 0xb3aa, 0xb3ab, 0xb3ac, 0xb3ad, 0xb3ae, 0xb3af, 0xb3b0,
+ 0xb3b1, 0xb3b3, 0xb3b4, 0xb3b5, 0xb3b6, 0xb3b7, 0xb3b8, 0xb3b9,
+ 0xb3ba, 0xb3bb, 0xb3bc, 0xb3bd, 0xb461, 0xb462, 0xb463, 0xb464,
+ 0xb465, 0xb466, 0xb467, 0xb468, 0xb469, 0xb46a, 0xb46b, 0xb46c,
+ 0xb46d, 0xb46e, 0xb46f, 0xb470, 0xb471, 0xb473, 0xb474, 0xb475,
+ 0xb476, 0xb477, 0xb478, 0xb479, 0xb47a, 0xb47b, 0xb47c, 0xb47d,
+ 0xb481, 0xb482, 0xb483, 0xb484, 0xb485, 0xb486, 0xb487, 0xb488,
+ 0xb489, 0xb48a, 0xb48b, 0xb48c, 0xb48d, 0xb48e, 0xb48f, 0xb490,
+ 0xb491, 0xb493, 0xb494, 0xb495, 0xb496, 0xb497, 0xb498, 0xb499,
+ 0xb49a, 0xb49b, 0xb49c, 0xb49d, 0xb4a1, 0xb4a2, 0xb4a3, 0xb4a4,
+ 0xb4a5, 0xb4a6, 0xb4a7, 0xb4a8, 0xb4a9, 0xb4aa, 0xb4ab, 0xb4ac,
+ 0xb4ad, 0xb4ae, 0xb4af, 0xb4b0, 0xb4b1, 0xb4b3, 0xb4b4, 0xb4b5,
+ 0xb4b6, 0xb4b7, 0xb4b8, 0xb4b9, 0xb4ba, 0xb4bb, 0xb4bc, 0xb4bd,
+ 0xb4c1, 0xb4c2, 0xb4c3, 0xb4c4, 0xb4c5, 0xb4c6, 0xb4c7, 0xb4c8,
+ 0xb4c9, 0xb4ca, 0xb4cb, 0xb4cc, 0xb4cd, 0xb4ce, 0xb4cf, 0xb4d0,
+ 0xb4d1, 0xb4d3, 0xb4d4, 0xb4d5, 0xb4d6, 0xb4d7, 0xb4d8, 0xb4d9,
+ 0xb4da, 0xb4db, 0xb4dc, 0xb4dd, 0xb4e1, 0xb4e2, 0xb4e3, 0xb4e4,
+ 0xb4e5, 0xb4e6, 0xb4e7, 0xb4e8, 0xb4e9, 0xb4ea, 0xb4eb, 0xb4ec,
+ 0xb4ed, 0xb4ee, 0xb4ef, 0xb4f0, 0xb4f1, 0xb4f3, 0xb4f4, 0xb4f5,
+ 0xb4f6, 0xb4f7, 0xb4f8, 0xb4f9, 0xb4fa, 0xb4fb, 0xb4fc, 0xb4fd,
+ 0xb541, 0xb542, 0xb543, 0xb544, 0xb545, 0xb546, 0xb547, 0xb548,
+ 0xb549, 0xb54a, 0xb54b, 0xb54c, 0xb54d, 0xb54e, 0xb54f, 0xb550,
+ 0xb551, 0xb553, 0xb554, 0xb555, 0xb556, 0xb557, 0xb558, 0xb559,
+ 0xb55a, 0xb55b, 0xb55c, 0xb55d, 0xb561, 0xb562, 0xb563, 0xb564,
+ 0xb565, 0xb566, 0xb567, 0xb568, 0xb569, 0xb56a, 0xb56b, 0xb56c,
+ 0xb56d, 0xb56e, 0xb56f, 0xb570, 0xb571, 0xb573, 0xb574, 0xb575
+};
+
+static unsigned short johab_from_unicode_c6[] = {
+ 0xb576, 0xb577, 0xb578, 0xb579, 0xb57a, 0xb57b, 0xb57c, 0xb57d,
+ 0xb581, 0xb582, 0xb583, 0xb584, 0xb585, 0xb586, 0xb587, 0xb588,
+ 0xb589, 0xb58a, 0xb58b, 0xb58c, 0xb58d, 0xb58e, 0xb58f, 0xb590,
+ 0xb591, 0xb593, 0xb594, 0xb595, 0xb596, 0xb597, 0xb598, 0xb599,
+ 0xb59a, 0xb59b, 0xb59c, 0xb59d, 0xb5a1, 0xb5a2, 0xb5a3, 0xb5a4,
+ 0xb5a5, 0xb5a6, 0xb5a7, 0xb5a8, 0xb5a9, 0xb5aa, 0xb5ab, 0xb5ac,
+ 0xb5ad, 0xb5ae, 0xb5af, 0xb5b0, 0xb5b1, 0xb5b3, 0xb5b4, 0xb5b5,
+ 0xb5b6, 0xb5b7, 0xb5b8, 0xb5b9, 0xb5ba, 0xb5bb, 0xb5bc, 0xb5bd,
+ 0xb5c1, 0xb5c2, 0xb5c3, 0xb5c4, 0xb5c5, 0xb5c6, 0xb5c7, 0xb5c8,
+ 0xb5c9, 0xb5ca, 0xb5cb, 0xb5cc, 0xb5cd, 0xb5ce, 0xb5cf, 0xb5d0,
+ 0xb5d1, 0xb5d3, 0xb5d4, 0xb5d5, 0xb5d6, 0xb5d7, 0xb5d8, 0xb5d9,
+ 0xb5da, 0xb5db, 0xb5dc, 0xb5dd, 0xb5e1, 0xb5e2, 0xb5e3, 0xb5e4,
+ 0xb5e5, 0xb5e6, 0xb5e7, 0xb5e8, 0xb5e9, 0xb5ea, 0xb5eb, 0xb5ec,
+ 0xb5ed, 0xb5ee, 0xb5ef, 0xb5f0, 0xb5f1, 0xb5f3, 0xb5f4, 0xb5f5,
+ 0xb5f6, 0xb5f7, 0xb5f8, 0xb5f9, 0xb5fa, 0xb5fb, 0xb5fc, 0xb5fd,
+ 0xb641, 0xb642, 0xb643, 0xb644, 0xb645, 0xb646, 0xb647, 0xb648,
+ 0xb649, 0xb64a, 0xb64b, 0xb64c, 0xb64d, 0xb64e, 0xb64f, 0xb650,
+ 0xb651, 0xb653, 0xb654, 0xb655, 0xb656, 0xb657, 0xb658, 0xb659,
+ 0xb65a, 0xb65b, 0xb65c, 0xb65d, 0xb661, 0xb662, 0xb663, 0xb664,
+ 0xb665, 0xb666, 0xb667, 0xb668, 0xb669, 0xb66a, 0xb66b, 0xb66c,
+ 0xb66d, 0xb66e, 0xb66f, 0xb670, 0xb671, 0xb673, 0xb674, 0xb675,
+ 0xb676, 0xb677, 0xb678, 0xb679, 0xb67a, 0xb67b, 0xb67c, 0xb67d,
+ 0xb681, 0xb682, 0xb683, 0xb684, 0xb685, 0xb686, 0xb687, 0xb688,
+ 0xb689, 0xb68a, 0xb68b, 0xb68c, 0xb68d, 0xb68e, 0xb68f, 0xb690,
+ 0xb691, 0xb693, 0xb694, 0xb695, 0xb696, 0xb697, 0xb698, 0xb699,
+ 0xb69a, 0xb69b, 0xb69c, 0xb69d, 0xb6a1, 0xb6a2, 0xb6a3, 0xb6a4,
+ 0xb6a5, 0xb6a6, 0xb6a7, 0xb6a8, 0xb6a9, 0xb6aa, 0xb6ab, 0xb6ac,
+ 0xb6ad, 0xb6ae, 0xb6af, 0xb6b0, 0xb6b1, 0xb6b3, 0xb6b4, 0xb6b5,
+ 0xb6b6, 0xb6b7, 0xb6b8, 0xb6b9, 0xb6ba, 0xb6bb, 0xb6bc, 0xb6bd,
+ 0xb6c1, 0xb6c2, 0xb6c3, 0xb6c4, 0xb6c5, 0xb6c6, 0xb6c7, 0xb6c8,
+ 0xb6c9, 0xb6ca, 0xb6cb, 0xb6cc, 0xb6cd, 0xb6ce, 0xb6cf, 0xb6d0,
+ 0xb6d1, 0xb6d3, 0xb6d4, 0xb6d5, 0xb6d6, 0xb6d7, 0xb6d8, 0xb6d9
+};
+
+static unsigned short johab_from_unicode_c7[] = {
+ 0xb6da, 0xb6db, 0xb6dc, 0xb6dd, 0xb6e1, 0xb6e2, 0xb6e3, 0xb6e4,
+ 0xb6e5, 0xb6e6, 0xb6e7, 0xb6e8, 0xb6e9, 0xb6ea, 0xb6eb, 0xb6ec,
+ 0xb6ed, 0xb6ee, 0xb6ef, 0xb6f0, 0xb6f1, 0xb6f3, 0xb6f4, 0xb6f5,
+ 0xb6f6, 0xb6f7, 0xb6f8, 0xb6f9, 0xb6fa, 0xb6fb, 0xb6fc, 0xb6fd,
+ 0xb741, 0xb742, 0xb743, 0xb744, 0xb745, 0xb746, 0xb747, 0xb748,
+ 0xb749, 0xb74a, 0xb74b, 0xb74c, 0xb74d, 0xb74e, 0xb74f, 0xb750,
+ 0xb751, 0xb753, 0xb754, 0xb755, 0xb756, 0xb757, 0xb758, 0xb759,
+ 0xb75a, 0xb75b, 0xb75c, 0xb75d, 0xb761, 0xb762, 0xb763, 0xb764,
+ 0xb765, 0xb766, 0xb767, 0xb768, 0xb769, 0xb76a, 0xb76b, 0xb76c,
+ 0xb76d, 0xb76e, 0xb76f, 0xb770, 0xb771, 0xb773, 0xb774, 0xb775,
+ 0xb776, 0xb777, 0xb778, 0xb779, 0xb77a, 0xb77b, 0xb77c, 0xb77d,
+ 0xb781, 0xb782, 0xb783, 0xb784, 0xb785, 0xb786, 0xb787, 0xb788,
+ 0xb789, 0xb78a, 0xb78b, 0xb78c, 0xb78d, 0xb78e, 0xb78f, 0xb790,
+ 0xb791, 0xb793, 0xb794, 0xb795, 0xb796, 0xb797, 0xb798, 0xb799,
+ 0xb79a, 0xb79b, 0xb79c, 0xb79d, 0xb7a1, 0xb7a2, 0xb7a3, 0xb7a4,
+ 0xb7a5, 0xb7a6, 0xb7a7, 0xb7a8, 0xb7a9, 0xb7aa, 0xb7ab, 0xb7ac,
+ 0xb7ad, 0xb7ae, 0xb7af, 0xb7b0, 0xb7b1, 0xb7b3, 0xb7b4, 0xb7b5,
+ 0xb7b6, 0xb7b7, 0xb7b8, 0xb7b9, 0xb7ba, 0xb7bb, 0xb7bc, 0xb7bd,
+ 0xb861, 0xb862, 0xb863, 0xb864, 0xb865, 0xb866, 0xb867, 0xb868,
+ 0xb869, 0xb86a, 0xb86b, 0xb86c, 0xb86d, 0xb86e, 0xb86f, 0xb870,
+ 0xb871, 0xb873, 0xb874, 0xb875, 0xb876, 0xb877, 0xb878, 0xb879,
+ 0xb87a, 0xb87b, 0xb87c, 0xb87d, 0xb881, 0xb882, 0xb883, 0xb884,
+ 0xb885, 0xb886, 0xb887, 0xb888, 0xb889, 0xb88a, 0xb88b, 0xb88c,
+ 0xb88d, 0xb88e, 0xb88f, 0xb890, 0xb891, 0xb893, 0xb894, 0xb895,
+ 0xb896, 0xb897, 0xb898, 0xb899, 0xb89a, 0xb89b, 0xb89c, 0xb89d,
+ 0xb8a1, 0xb8a2, 0xb8a3, 0xb8a4, 0xb8a5, 0xb8a6, 0xb8a7, 0xb8a8,
+ 0xb8a9, 0xb8aa, 0xb8ab, 0xb8ac, 0xb8ad, 0xb8ae, 0xb8af, 0xb8b0,
+ 0xb8b1, 0xb8b3, 0xb8b4, 0xb8b5, 0xb8b6, 0xb8b7, 0xb8b8, 0xb8b9,
+ 0xb8ba, 0xb8bb, 0xb8bc, 0xb8bd, 0xb8c1, 0xb8c2, 0xb8c3, 0xb8c4,
+ 0xb8c5, 0xb8c6, 0xb8c7, 0xb8c8, 0xb8c9, 0xb8ca, 0xb8cb, 0xb8cc,
+ 0xb8cd, 0xb8ce, 0xb8cf, 0xb8d0, 0xb8d1, 0xb8d3, 0xb8d4, 0xb8d5,
+ 0xb8d6, 0xb8d7, 0xb8d8, 0xb8d9, 0xb8da, 0xb8db, 0xb8dc, 0xb8dd
+};
+
+static unsigned short johab_from_unicode_c8[] = {
+ 0xb8e1, 0xb8e2, 0xb8e3, 0xb8e4, 0xb8e5, 0xb8e6, 0xb8e7, 0xb8e8,
+ 0xb8e9, 0xb8ea, 0xb8eb, 0xb8ec, 0xb8ed, 0xb8ee, 0xb8ef, 0xb8f0,
+ 0xb8f1, 0xb8f3, 0xb8f4, 0xb8f5, 0xb8f6, 0xb8f7, 0xb8f8, 0xb8f9,
+ 0xb8fa, 0xb8fb, 0xb8fc, 0xb8fd, 0xb941, 0xb942, 0xb943, 0xb944,
+ 0xb945, 0xb946, 0xb947, 0xb948, 0xb949, 0xb94a, 0xb94b, 0xb94c,
+ 0xb94d, 0xb94e, 0xb94f, 0xb950, 0xb951, 0xb953, 0xb954, 0xb955,
+ 0xb956, 0xb957, 0xb958, 0xb959, 0xb95a, 0xb95b, 0xb95c, 0xb95d,
+ 0xb961, 0xb962, 0xb963, 0xb964, 0xb965, 0xb966, 0xb967, 0xb968,
+ 0xb969, 0xb96a, 0xb96b, 0xb96c, 0xb96d, 0xb96e, 0xb96f, 0xb970,
+ 0xb971, 0xb973, 0xb974, 0xb975, 0xb976, 0xb977, 0xb978, 0xb979,
+ 0xb97a, 0xb97b, 0xb97c, 0xb97d, 0xb981, 0xb982, 0xb983, 0xb984,
+ 0xb985, 0xb986, 0xb987, 0xb988, 0xb989, 0xb98a, 0xb98b, 0xb98c,
+ 0xb98d, 0xb98e, 0xb98f, 0xb990, 0xb991, 0xb993, 0xb994, 0xb995,
+ 0xb996, 0xb997, 0xb998, 0xb999, 0xb99a, 0xb99b, 0xb99c, 0xb99d,
+ 0xb9a1, 0xb9a2, 0xb9a3, 0xb9a4, 0xb9a5, 0xb9a6, 0xb9a7, 0xb9a8,
+ 0xb9a9, 0xb9aa, 0xb9ab, 0xb9ac, 0xb9ad, 0xb9ae, 0xb9af, 0xb9b0,
+ 0xb9b1, 0xb9b3, 0xb9b4, 0xb9b5, 0xb9b6, 0xb9b7, 0xb9b8, 0xb9b9,
+ 0xb9ba, 0xb9bb, 0xb9bc, 0xb9bd, 0xb9c1, 0xb9c2, 0xb9c3, 0xb9c4,
+ 0xb9c5, 0xb9c6, 0xb9c7, 0xb9c8, 0xb9c9, 0xb9ca, 0xb9cb, 0xb9cc,
+ 0xb9cd, 0xb9ce, 0xb9cf, 0xb9d0, 0xb9d1, 0xb9d3, 0xb9d4, 0xb9d5,
+ 0xb9d6, 0xb9d7, 0xb9d8, 0xb9d9, 0xb9da, 0xb9db, 0xb9dc, 0xb9dd,
+ 0xb9e1, 0xb9e2, 0xb9e3, 0xb9e4, 0xb9e5, 0xb9e6, 0xb9e7, 0xb9e8,
+ 0xb9e9, 0xb9ea, 0xb9eb, 0xb9ec, 0xb9ed, 0xb9ee, 0xb9ef, 0xb9f0,
+ 0xb9f1, 0xb9f3, 0xb9f4, 0xb9f5, 0xb9f6, 0xb9f7, 0xb9f8, 0xb9f9,
+ 0xb9fa, 0xb9fb, 0xb9fc, 0xb9fd, 0xba41, 0xba42, 0xba43, 0xba44,
+ 0xba45, 0xba46, 0xba47, 0xba48, 0xba49, 0xba4a, 0xba4b, 0xba4c,
+ 0xba4d, 0xba4e, 0xba4f, 0xba50, 0xba51, 0xba53, 0xba54, 0xba55,
+ 0xba56, 0xba57, 0xba58, 0xba59, 0xba5a, 0xba5b, 0xba5c, 0xba5d,
+ 0xba61, 0xba62, 0xba63, 0xba64, 0xba65, 0xba66, 0xba67, 0xba68,
+ 0xba69, 0xba6a, 0xba6b, 0xba6c, 0xba6d, 0xba6e, 0xba6f, 0xba70,
+ 0xba71, 0xba73, 0xba74, 0xba75, 0xba76, 0xba77, 0xba78, 0xba79,
+ 0xba7a, 0xba7b, 0xba7c, 0xba7d, 0xba81, 0xba82, 0xba83, 0xba84
+};
+
+static unsigned short johab_from_unicode_c9[] = {
+ 0xba85, 0xba86, 0xba87, 0xba88, 0xba89, 0xba8a, 0xba8b, 0xba8c,
+ 0xba8d, 0xba8e, 0xba8f, 0xba90, 0xba91, 0xba93, 0xba94, 0xba95,
+ 0xba96, 0xba97, 0xba98, 0xba99, 0xba9a, 0xba9b, 0xba9c, 0xba9d,
+ 0xbaa1, 0xbaa2, 0xbaa3, 0xbaa4, 0xbaa5, 0xbaa6, 0xbaa7, 0xbaa8,
+ 0xbaa9, 0xbaaa, 0xbaab, 0xbaac, 0xbaad, 0xbaae, 0xbaaf, 0xbab0,
+ 0xbab1, 0xbab3, 0xbab4, 0xbab5, 0xbab6, 0xbab7, 0xbab8, 0xbab9,
+ 0xbaba, 0xbabb, 0xbabc, 0xbabd, 0xbac1, 0xbac2, 0xbac3, 0xbac4,
+ 0xbac5, 0xbac6, 0xbac7, 0xbac8, 0xbac9, 0xbaca, 0xbacb, 0xbacc,
+ 0xbacd, 0xbace, 0xbacf, 0xbad0, 0xbad1, 0xbad3, 0xbad4, 0xbad5,
+ 0xbad6, 0xbad7, 0xbad8, 0xbad9, 0xbada, 0xbadb, 0xbadc, 0xbadd,
+ 0xbae1, 0xbae2, 0xbae3, 0xbae4, 0xbae5, 0xbae6, 0xbae7, 0xbae8,
+ 0xbae9, 0xbaea, 0xbaeb, 0xbaec, 0xbaed, 0xbaee, 0xbaef, 0xbaf0,
+ 0xbaf1, 0xbaf3, 0xbaf4, 0xbaf5, 0xbaf6, 0xbaf7, 0xbaf8, 0xbaf9,
+ 0xbafa, 0xbafb, 0xbafc, 0xbafd, 0xbb41, 0xbb42, 0xbb43, 0xbb44,
+ 0xbb45, 0xbb46, 0xbb47, 0xbb48, 0xbb49, 0xbb4a, 0xbb4b, 0xbb4c,
+ 0xbb4d, 0xbb4e, 0xbb4f, 0xbb50, 0xbb51, 0xbb53, 0xbb54, 0xbb55,
+ 0xbb56, 0xbb57, 0xbb58, 0xbb59, 0xbb5a, 0xbb5b, 0xbb5c, 0xbb5d,
+ 0xbb61, 0xbb62, 0xbb63, 0xbb64, 0xbb65, 0xbb66, 0xbb67, 0xbb68,
+ 0xbb69, 0xbb6a, 0xbb6b, 0xbb6c, 0xbb6d, 0xbb6e, 0xbb6f, 0xbb70,
+ 0xbb71, 0xbb73, 0xbb74, 0xbb75, 0xbb76, 0xbb77, 0xbb78, 0xbb79,
+ 0xbb7a, 0xbb7b, 0xbb7c, 0xbb7d, 0xbb81, 0xbb82, 0xbb83, 0xbb84,
+ 0xbb85, 0xbb86, 0xbb87, 0xbb88, 0xbb89, 0xbb8a, 0xbb8b, 0xbb8c,
+ 0xbb8d, 0xbb8e, 0xbb8f, 0xbb90, 0xbb91, 0xbb93, 0xbb94, 0xbb95,
+ 0xbb96, 0xbb97, 0xbb98, 0xbb99, 0xbb9a, 0xbb9b, 0xbb9c, 0xbb9d,
+ 0xbba1, 0xbba2, 0xbba3, 0xbba4, 0xbba5, 0xbba6, 0xbba7, 0xbba8,
+ 0xbba9, 0xbbaa, 0xbbab, 0xbbac, 0xbbad, 0xbbae, 0xbbaf, 0xbbb0,
+ 0xbbb1, 0xbbb3, 0xbbb4, 0xbbb5, 0xbbb6, 0xbbb7, 0xbbb8, 0xbbb9,
+ 0xbbba, 0xbbbb, 0xbbbc, 0xbbbd, 0xbc61, 0xbc62, 0xbc63, 0xbc64,
+ 0xbc65, 0xbc66, 0xbc67, 0xbc68, 0xbc69, 0xbc6a, 0xbc6b, 0xbc6c,
+ 0xbc6d, 0xbc6e, 0xbc6f, 0xbc70, 0xbc71, 0xbc73, 0xbc74, 0xbc75,
+ 0xbc76, 0xbc77, 0xbc78, 0xbc79, 0xbc7a, 0xbc7b, 0xbc7c, 0xbc7d,
+ 0xbc81, 0xbc82, 0xbc83, 0xbc84, 0xbc85, 0xbc86, 0xbc87, 0xbc88
+};
+
+static unsigned short johab_from_unicode_ca[] = {
+ 0xbc89, 0xbc8a, 0xbc8b, 0xbc8c, 0xbc8d, 0xbc8e, 0xbc8f, 0xbc90,
+ 0xbc91, 0xbc93, 0xbc94, 0xbc95, 0xbc96, 0xbc97, 0xbc98, 0xbc99,
+ 0xbc9a, 0xbc9b, 0xbc9c, 0xbc9d, 0xbca1, 0xbca2, 0xbca3, 0xbca4,
+ 0xbca5, 0xbca6, 0xbca7, 0xbca8, 0xbca9, 0xbcaa, 0xbcab, 0xbcac,
+ 0xbcad, 0xbcae, 0xbcaf, 0xbcb0, 0xbcb1, 0xbcb3, 0xbcb4, 0xbcb5,
+ 0xbcb6, 0xbcb7, 0xbcb8, 0xbcb9, 0xbcba, 0xbcbb, 0xbcbc, 0xbcbd,
+ 0xbcc1, 0xbcc2, 0xbcc3, 0xbcc4, 0xbcc5, 0xbcc6, 0xbcc7, 0xbcc8,
+ 0xbcc9, 0xbcca, 0xbccb, 0xbccc, 0xbccd, 0xbcce, 0xbccf, 0xbcd0,
+ 0xbcd1, 0xbcd3, 0xbcd4, 0xbcd5, 0xbcd6, 0xbcd7, 0xbcd8, 0xbcd9,
+ 0xbcda, 0xbcdb, 0xbcdc, 0xbcdd, 0xbce1, 0xbce2, 0xbce3, 0xbce4,
+ 0xbce5, 0xbce6, 0xbce7, 0xbce8, 0xbce9, 0xbcea, 0xbceb, 0xbcec,
+ 0xbced, 0xbcee, 0xbcef, 0xbcf0, 0xbcf1, 0xbcf3, 0xbcf4, 0xbcf5,
+ 0xbcf6, 0xbcf7, 0xbcf8, 0xbcf9, 0xbcfa, 0xbcfb, 0xbcfc, 0xbcfd,
+ 0xbd41, 0xbd42, 0xbd43, 0xbd44, 0xbd45, 0xbd46, 0xbd47, 0xbd48,
+ 0xbd49, 0xbd4a, 0xbd4b, 0xbd4c, 0xbd4d, 0xbd4e, 0xbd4f, 0xbd50,
+ 0xbd51, 0xbd53, 0xbd54, 0xbd55, 0xbd56, 0xbd57, 0xbd58, 0xbd59,
+ 0xbd5a, 0xbd5b, 0xbd5c, 0xbd5d, 0xbd61, 0xbd62, 0xbd63, 0xbd64,
+ 0xbd65, 0xbd66, 0xbd67, 0xbd68, 0xbd69, 0xbd6a, 0xbd6b, 0xbd6c,
+ 0xbd6d, 0xbd6e, 0xbd6f, 0xbd70, 0xbd71, 0xbd73, 0xbd74, 0xbd75,
+ 0xbd76, 0xbd77, 0xbd78, 0xbd79, 0xbd7a, 0xbd7b, 0xbd7c, 0xbd7d,
+ 0xbd81, 0xbd82, 0xbd83, 0xbd84, 0xbd85, 0xbd86, 0xbd87, 0xbd88,
+ 0xbd89, 0xbd8a, 0xbd8b, 0xbd8c, 0xbd8d, 0xbd8e, 0xbd8f, 0xbd90,
+ 0xbd91, 0xbd93, 0xbd94, 0xbd95, 0xbd96, 0xbd97, 0xbd98, 0xbd99,
+ 0xbd9a, 0xbd9b, 0xbd9c, 0xbd9d, 0xbda1, 0xbda2, 0xbda3, 0xbda4,
+ 0xbda5, 0xbda6, 0xbda7, 0xbda8, 0xbda9, 0xbdaa, 0xbdab, 0xbdac,
+ 0xbdad, 0xbdae, 0xbdaf, 0xbdb0, 0xbdb1, 0xbdb3, 0xbdb4, 0xbdb5,
+ 0xbdb6, 0xbdb7, 0xbdb8, 0xbdb9, 0xbdba, 0xbdbb, 0xbdbc, 0xbdbd,
+ 0xbdc1, 0xbdc2, 0xbdc3, 0xbdc4, 0xbdc5, 0xbdc6, 0xbdc7, 0xbdc8,
+ 0xbdc9, 0xbdca, 0xbdcb, 0xbdcc, 0xbdcd, 0xbdce, 0xbdcf, 0xbdd0,
+ 0xbdd1, 0xbdd3, 0xbdd4, 0xbdd5, 0xbdd6, 0xbdd7, 0xbdd8, 0xbdd9,
+ 0xbdda, 0xbddb, 0xbddc, 0xbddd, 0xbde1, 0xbde2, 0xbde3, 0xbde4,
+ 0xbde5, 0xbde6, 0xbde7, 0xbde8, 0xbde9, 0xbdea, 0xbdeb, 0xbdec
+};
+
+static unsigned short johab_from_unicode_cb[] = {
+ 0xbded, 0xbdee, 0xbdef, 0xbdf0, 0xbdf1, 0xbdf3, 0xbdf4, 0xbdf5,
+ 0xbdf6, 0xbdf7, 0xbdf8, 0xbdf9, 0xbdfa, 0xbdfb, 0xbdfc, 0xbdfd,
+ 0xbe41, 0xbe42, 0xbe43, 0xbe44, 0xbe45, 0xbe46, 0xbe47, 0xbe48,
+ 0xbe49, 0xbe4a, 0xbe4b, 0xbe4c, 0xbe4d, 0xbe4e, 0xbe4f, 0xbe50,
+ 0xbe51, 0xbe53, 0xbe54, 0xbe55, 0xbe56, 0xbe57, 0xbe58, 0xbe59,
+ 0xbe5a, 0xbe5b, 0xbe5c, 0xbe5d, 0xbe61, 0xbe62, 0xbe63, 0xbe64,
+ 0xbe65, 0xbe66, 0xbe67, 0xbe68, 0xbe69, 0xbe6a, 0xbe6b, 0xbe6c,
+ 0xbe6d, 0xbe6e, 0xbe6f, 0xbe70, 0xbe71, 0xbe73, 0xbe74, 0xbe75,
+ 0xbe76, 0xbe77, 0xbe78, 0xbe79, 0xbe7a, 0xbe7b, 0xbe7c, 0xbe7d,
+ 0xbe81, 0xbe82, 0xbe83, 0xbe84, 0xbe85, 0xbe86, 0xbe87, 0xbe88,
+ 0xbe89, 0xbe8a, 0xbe8b, 0xbe8c, 0xbe8d, 0xbe8e, 0xbe8f, 0xbe90,
+ 0xbe91, 0xbe93, 0xbe94, 0xbe95, 0xbe96, 0xbe97, 0xbe98, 0xbe99,
+ 0xbe9a, 0xbe9b, 0xbe9c, 0xbe9d, 0xbea1, 0xbea2, 0xbea3, 0xbea4,
+ 0xbea5, 0xbea6, 0xbea7, 0xbea8, 0xbea9, 0xbeaa, 0xbeab, 0xbeac,
+ 0xbead, 0xbeae, 0xbeaf, 0xbeb0, 0xbeb1, 0xbeb3, 0xbeb4, 0xbeb5,
+ 0xbeb6, 0xbeb7, 0xbeb8, 0xbeb9, 0xbeba, 0xbebb, 0xbebc, 0xbebd,
+ 0xbec1, 0xbec2, 0xbec3, 0xbec4, 0xbec5, 0xbec6, 0xbec7, 0xbec8,
+ 0xbec9, 0xbeca, 0xbecb, 0xbecc, 0xbecd, 0xbece, 0xbecf, 0xbed0,
+ 0xbed1, 0xbed3, 0xbed4, 0xbed5, 0xbed6, 0xbed7, 0xbed8, 0xbed9,
+ 0xbeda, 0xbedb, 0xbedc, 0xbedd, 0xbee1, 0xbee2, 0xbee3, 0xbee4,
+ 0xbee5, 0xbee6, 0xbee7, 0xbee8, 0xbee9, 0xbeea, 0xbeeb, 0xbeec,
+ 0xbeed, 0xbeee, 0xbeef, 0xbef0, 0xbef1, 0xbef3, 0xbef4, 0xbef5,
+ 0xbef6, 0xbef7, 0xbef8, 0xbef9, 0xbefa, 0xbefb, 0xbefc, 0xbefd,
+ 0xbf41, 0xbf42, 0xbf43, 0xbf44, 0xbf45, 0xbf46, 0xbf47, 0xbf48,
+ 0xbf49, 0xbf4a, 0xbf4b, 0xbf4c, 0xbf4d, 0xbf4e, 0xbf4f, 0xbf50,
+ 0xbf51, 0xbf53, 0xbf54, 0xbf55, 0xbf56, 0xbf57, 0xbf58, 0xbf59,
+ 0xbf5a, 0xbf5b, 0xbf5c, 0xbf5d, 0xbf61, 0xbf62, 0xbf63, 0xbf64,
+ 0xbf65, 0xbf66, 0xbf67, 0xbf68, 0xbf69, 0xbf6a, 0xbf6b, 0xbf6c,
+ 0xbf6d, 0xbf6e, 0xbf6f, 0xbf70, 0xbf71, 0xbf73, 0xbf74, 0xbf75,
+ 0xbf76, 0xbf77, 0xbf78, 0xbf79, 0xbf7a, 0xbf7b, 0xbf7c, 0xbf7d,
+ 0xbf81, 0xbf82, 0xbf83, 0xbf84, 0xbf85, 0xbf86, 0xbf87, 0xbf88,
+ 0xbf89, 0xbf8a, 0xbf8b, 0xbf8c, 0xbf8d, 0xbf8e, 0xbf8f, 0xbf90
+};
+
+static unsigned short johab_from_unicode_cc[] = {
+ 0xbf91, 0xbf93, 0xbf94, 0xbf95, 0xbf96, 0xbf97, 0xbf98, 0xbf99,
+ 0xbf9a, 0xbf9b, 0xbf9c, 0xbf9d, 0xbfa1, 0xbfa2, 0xbfa3, 0xbfa4,
+ 0xbfa5, 0xbfa6, 0xbfa7, 0xbfa8, 0xbfa9, 0xbfaa, 0xbfab, 0xbfac,
+ 0xbfad, 0xbfae, 0xbfaf, 0xbfb0, 0xbfb1, 0xbfb3, 0xbfb4, 0xbfb5,
+ 0xbfb6, 0xbfb7, 0xbfb8, 0xbfb9, 0xbfba, 0xbfbb, 0xbfbc, 0xbfbd,
+ 0xc061, 0xc062, 0xc063, 0xc064, 0xc065, 0xc066, 0xc067, 0xc068,
+ 0xc069, 0xc06a, 0xc06b, 0xc06c, 0xc06d, 0xc06e, 0xc06f, 0xc070,
+ 0xc071, 0xc073, 0xc074, 0xc075, 0xc076, 0xc077, 0xc078, 0xc079,
+ 0xc07a, 0xc07b, 0xc07c, 0xc07d, 0xc081, 0xc082, 0xc083, 0xc084,
+ 0xc085, 0xc086, 0xc087, 0xc088, 0xc089, 0xc08a, 0xc08b, 0xc08c,
+ 0xc08d, 0xc08e, 0xc08f, 0xc090, 0xc091, 0xc093, 0xc094, 0xc095,
+ 0xc096, 0xc097, 0xc098, 0xc099, 0xc09a, 0xc09b, 0xc09c, 0xc09d,
+ 0xc0a1, 0xc0a2, 0xc0a3, 0xc0a4, 0xc0a5, 0xc0a6, 0xc0a7, 0xc0a8,
+ 0xc0a9, 0xc0aa, 0xc0ab, 0xc0ac, 0xc0ad, 0xc0ae, 0xc0af, 0xc0b0,
+ 0xc0b1, 0xc0b3, 0xc0b4, 0xc0b5, 0xc0b6, 0xc0b7, 0xc0b8, 0xc0b9,
+ 0xc0ba, 0xc0bb, 0xc0bc, 0xc0bd, 0xc0c1, 0xc0c2, 0xc0c3, 0xc0c4,
+ 0xc0c5, 0xc0c6, 0xc0c7, 0xc0c8, 0xc0c9, 0xc0ca, 0xc0cb, 0xc0cc,
+ 0xc0cd, 0xc0ce, 0xc0cf, 0xc0d0, 0xc0d1, 0xc0d3, 0xc0d4, 0xc0d5,
+ 0xc0d6, 0xc0d7, 0xc0d8, 0xc0d9, 0xc0da, 0xc0db, 0xc0dc, 0xc0dd,
+ 0xc0e1, 0xc0e2, 0xc0e3, 0xc0e4, 0xc0e5, 0xc0e6, 0xc0e7, 0xc0e8,
+ 0xc0e9, 0xc0ea, 0xc0eb, 0xc0ec, 0xc0ed, 0xc0ee, 0xc0ef, 0xc0f0,
+ 0xc0f1, 0xc0f3, 0xc0f4, 0xc0f5, 0xc0f6, 0xc0f7, 0xc0f8, 0xc0f9,
+ 0xc0fa, 0xc0fb, 0xc0fc, 0xc0fd, 0xc141, 0xc142, 0xc143, 0xc144,
+ 0xc145, 0xc146, 0xc147, 0xc148, 0xc149, 0xc14a, 0xc14b, 0xc14c,
+ 0xc14d, 0xc14e, 0xc14f, 0xc150, 0xc151, 0xc153, 0xc154, 0xc155,
+ 0xc156, 0xc157, 0xc158, 0xc159, 0xc15a, 0xc15b, 0xc15c, 0xc15d,
+ 0xc161, 0xc162, 0xc163, 0xc164, 0xc165, 0xc166, 0xc167, 0xc168,
+ 0xc169, 0xc16a, 0xc16b, 0xc16c, 0xc16d, 0xc16e, 0xc16f, 0xc170,
+ 0xc171, 0xc173, 0xc174, 0xc175, 0xc176, 0xc177, 0xc178, 0xc179,
+ 0xc17a, 0xc17b, 0xc17c, 0xc17d, 0xc181, 0xc182, 0xc183, 0xc184,
+ 0xc185, 0xc186, 0xc187, 0xc188, 0xc189, 0xc18a, 0xc18b, 0xc18c,
+ 0xc18d, 0xc18e, 0xc18f, 0xc190, 0xc191, 0xc193, 0xc194, 0xc195
+};
+
+static unsigned short johab_from_unicode_cd[] = {
+ 0xc196, 0xc197, 0xc198, 0xc199, 0xc19a, 0xc19b, 0xc19c, 0xc19d,
+ 0xc1a1, 0xc1a2, 0xc1a3, 0xc1a4, 0xc1a5, 0xc1a6, 0xc1a7, 0xc1a8,
+ 0xc1a9, 0xc1aa, 0xc1ab, 0xc1ac, 0xc1ad, 0xc1ae, 0xc1af, 0xc1b0,
+ 0xc1b1, 0xc1b3, 0xc1b4, 0xc1b5, 0xc1b6, 0xc1b7, 0xc1b8, 0xc1b9,
+ 0xc1ba, 0xc1bb, 0xc1bc, 0xc1bd, 0xc1c1, 0xc1c2, 0xc1c3, 0xc1c4,
+ 0xc1c5, 0xc1c6, 0xc1c7, 0xc1c8, 0xc1c9, 0xc1ca, 0xc1cb, 0xc1cc,
+ 0xc1cd, 0xc1ce, 0xc1cf, 0xc1d0, 0xc1d1, 0xc1d3, 0xc1d4, 0xc1d5,
+ 0xc1d6, 0xc1d7, 0xc1d8, 0xc1d9, 0xc1da, 0xc1db, 0xc1dc, 0xc1dd,
+ 0xc1e1, 0xc1e2, 0xc1e3, 0xc1e4, 0xc1e5, 0xc1e6, 0xc1e7, 0xc1e8,
+ 0xc1e9, 0xc1ea, 0xc1eb, 0xc1ec, 0xc1ed, 0xc1ee, 0xc1ef, 0xc1f0,
+ 0xc1f1, 0xc1f3, 0xc1f4, 0xc1f5, 0xc1f6, 0xc1f7, 0xc1f8, 0xc1f9,
+ 0xc1fa, 0xc1fb, 0xc1fc, 0xc1fd, 0xc241, 0xc242, 0xc243, 0xc244,
+ 0xc245, 0xc246, 0xc247, 0xc248, 0xc249, 0xc24a, 0xc24b, 0xc24c,
+ 0xc24d, 0xc24e, 0xc24f, 0xc250, 0xc251, 0xc253, 0xc254, 0xc255,
+ 0xc256, 0xc257, 0xc258, 0xc259, 0xc25a, 0xc25b, 0xc25c, 0xc25d,
+ 0xc261, 0xc262, 0xc263, 0xc264, 0xc265, 0xc266, 0xc267, 0xc268,
+ 0xc269, 0xc26a, 0xc26b, 0xc26c, 0xc26d, 0xc26e, 0xc26f, 0xc270,
+ 0xc271, 0xc273, 0xc274, 0xc275, 0xc276, 0xc277, 0xc278, 0xc279,
+ 0xc27a, 0xc27b, 0xc27c, 0xc27d, 0xc281, 0xc282, 0xc283, 0xc284,
+ 0xc285, 0xc286, 0xc287, 0xc288, 0xc289, 0xc28a, 0xc28b, 0xc28c,
+ 0xc28d, 0xc28e, 0xc28f, 0xc290, 0xc291, 0xc293, 0xc294, 0xc295,
+ 0xc296, 0xc297, 0xc298, 0xc299, 0xc29a, 0xc29b, 0xc29c, 0xc29d,
+ 0xc2a1, 0xc2a2, 0xc2a3, 0xc2a4, 0xc2a5, 0xc2a6, 0xc2a7, 0xc2a8,
+ 0xc2a9, 0xc2aa, 0xc2ab, 0xc2ac, 0xc2ad, 0xc2ae, 0xc2af, 0xc2b0,
+ 0xc2b1, 0xc2b3, 0xc2b4, 0xc2b5, 0xc2b6, 0xc2b7, 0xc2b8, 0xc2b9,
+ 0xc2ba, 0xc2bb, 0xc2bc, 0xc2bd, 0xc2c1, 0xc2c2, 0xc2c3, 0xc2c4,
+ 0xc2c5, 0xc2c6, 0xc2c7, 0xc2c8, 0xc2c9, 0xc2ca, 0xc2cb, 0xc2cc,
+ 0xc2cd, 0xc2ce, 0xc2cf, 0xc2d0, 0xc2d1, 0xc2d3, 0xc2d4, 0xc2d5,
+ 0xc2d6, 0xc2d7, 0xc2d8, 0xc2d9, 0xc2da, 0xc2db, 0xc2dc, 0xc2dd,
+ 0xc2e1, 0xc2e2, 0xc2e3, 0xc2e4, 0xc2e5, 0xc2e6, 0xc2e7, 0xc2e8,
+ 0xc2e9, 0xc2ea, 0xc2eb, 0xc2ec, 0xc2ed, 0xc2ee, 0xc2ef, 0xc2f0,
+ 0xc2f1, 0xc2f3, 0xc2f4, 0xc2f5, 0xc2f6, 0xc2f7, 0xc2f8, 0xc2f9
+};
+
+static unsigned short johab_from_unicode_ce[] = {
+ 0xc2fa, 0xc2fb, 0xc2fc, 0xc2fd, 0xc341, 0xc342, 0xc343, 0xc344,
+ 0xc345, 0xc346, 0xc347, 0xc348, 0xc349, 0xc34a, 0xc34b, 0xc34c,
+ 0xc34d, 0xc34e, 0xc34f, 0xc350, 0xc351, 0xc353, 0xc354, 0xc355,
+ 0xc356, 0xc357, 0xc358, 0xc359, 0xc35a, 0xc35b, 0xc35c, 0xc35d,
+ 0xc361, 0xc362, 0xc363, 0xc364, 0xc365, 0xc366, 0xc367, 0xc368,
+ 0xc369, 0xc36a, 0xc36b, 0xc36c, 0xc36d, 0xc36e, 0xc36f, 0xc370,
+ 0xc371, 0xc373, 0xc374, 0xc375, 0xc376, 0xc377, 0xc378, 0xc379,
+ 0xc37a, 0xc37b, 0xc37c, 0xc37d, 0xc381, 0xc382, 0xc383, 0xc384,
+ 0xc385, 0xc386, 0xc387, 0xc388, 0xc389, 0xc38a, 0xc38b, 0xc38c,
+ 0xc38d, 0xc38e, 0xc38f, 0xc390, 0xc391, 0xc393, 0xc394, 0xc395,
+ 0xc396, 0xc397, 0xc398, 0xc399, 0xc39a, 0xc39b, 0xc39c, 0xc39d,
+ 0xc3a1, 0xc3a2, 0xc3a3, 0xc3a4, 0xc3a5, 0xc3a6, 0xc3a7, 0xc3a8,
+ 0xc3a9, 0xc3aa, 0xc3ab, 0xc3ac, 0xc3ad, 0xc3ae, 0xc3af, 0xc3b0,
+ 0xc3b1, 0xc3b3, 0xc3b4, 0xc3b5, 0xc3b6, 0xc3b7, 0xc3b8, 0xc3b9,
+ 0xc3ba, 0xc3bb, 0xc3bc, 0xc3bd, 0xc461, 0xc462, 0xc463, 0xc464,
+ 0xc465, 0xc466, 0xc467, 0xc468, 0xc469, 0xc46a, 0xc46b, 0xc46c,
+ 0xc46d, 0xc46e, 0xc46f, 0xc470, 0xc471, 0xc473, 0xc474, 0xc475,
+ 0xc476, 0xc477, 0xc478, 0xc479, 0xc47a, 0xc47b, 0xc47c, 0xc47d,
+ 0xc481, 0xc482, 0xc483, 0xc484, 0xc485, 0xc486, 0xc487, 0xc488,
+ 0xc489, 0xc48a, 0xc48b, 0xc48c, 0xc48d, 0xc48e, 0xc48f, 0xc490,
+ 0xc491, 0xc493, 0xc494, 0xc495, 0xc496, 0xc497, 0xc498, 0xc499,
+ 0xc49a, 0xc49b, 0xc49c, 0xc49d, 0xc4a1, 0xc4a2, 0xc4a3, 0xc4a4,
+ 0xc4a5, 0xc4a6, 0xc4a7, 0xc4a8, 0xc4a9, 0xc4aa, 0xc4ab, 0xc4ac,
+ 0xc4ad, 0xc4ae, 0xc4af, 0xc4b0, 0xc4b1, 0xc4b3, 0xc4b4, 0xc4b5,
+ 0xc4b6, 0xc4b7, 0xc4b8, 0xc4b9, 0xc4ba, 0xc4bb, 0xc4bc, 0xc4bd,
+ 0xc4c1, 0xc4c2, 0xc4c3, 0xc4c4, 0xc4c5, 0xc4c6, 0xc4c7, 0xc4c8,
+ 0xc4c9, 0xc4ca, 0xc4cb, 0xc4cc, 0xc4cd, 0xc4ce, 0xc4cf, 0xc4d0,
+ 0xc4d1, 0xc4d3, 0xc4d4, 0xc4d5, 0xc4d6, 0xc4d7, 0xc4d8, 0xc4d9,
+ 0xc4da, 0xc4db, 0xc4dc, 0xc4dd, 0xc4e1, 0xc4e2, 0xc4e3, 0xc4e4,
+ 0xc4e5, 0xc4e6, 0xc4e7, 0xc4e8, 0xc4e9, 0xc4ea, 0xc4eb, 0xc4ec,
+ 0xc4ed, 0xc4ee, 0xc4ef, 0xc4f0, 0xc4f1, 0xc4f3, 0xc4f4, 0xc4f5,
+ 0xc4f6, 0xc4f7, 0xc4f8, 0xc4f9, 0xc4fa, 0xc4fb, 0xc4fc, 0xc4fd
+};
+
+static unsigned short johab_from_unicode_cf[] = {
+ 0xc541, 0xc542, 0xc543, 0xc544, 0xc545, 0xc546, 0xc547, 0xc548,
+ 0xc549, 0xc54a, 0xc54b, 0xc54c, 0xc54d, 0xc54e, 0xc54f, 0xc550,
+ 0xc551, 0xc553, 0xc554, 0xc555, 0xc556, 0xc557, 0xc558, 0xc559,
+ 0xc55a, 0xc55b, 0xc55c, 0xc55d, 0xc561, 0xc562, 0xc563, 0xc564,
+ 0xc565, 0xc566, 0xc567, 0xc568, 0xc569, 0xc56a, 0xc56b, 0xc56c,
+ 0xc56d, 0xc56e, 0xc56f, 0xc570, 0xc571, 0xc573, 0xc574, 0xc575,
+ 0xc576, 0xc577, 0xc578, 0xc579, 0xc57a, 0xc57b, 0xc57c, 0xc57d,
+ 0xc581, 0xc582, 0xc583, 0xc584, 0xc585, 0xc586, 0xc587, 0xc588,
+ 0xc589, 0xc58a, 0xc58b, 0xc58c, 0xc58d, 0xc58e, 0xc58f, 0xc590,
+ 0xc591, 0xc593, 0xc594, 0xc595, 0xc596, 0xc597, 0xc598, 0xc599,
+ 0xc59a, 0xc59b, 0xc59c, 0xc59d, 0xc5a1, 0xc5a2, 0xc5a3, 0xc5a4,
+ 0xc5a5, 0xc5a6, 0xc5a7, 0xc5a8, 0xc5a9, 0xc5aa, 0xc5ab, 0xc5ac,
+ 0xc5ad, 0xc5ae, 0xc5af, 0xc5b0, 0xc5b1, 0xc5b3, 0xc5b4, 0xc5b5,
+ 0xc5b6, 0xc5b7, 0xc5b8, 0xc5b9, 0xc5ba, 0xc5bb, 0xc5bc, 0xc5bd,
+ 0xc5c1, 0xc5c2, 0xc5c3, 0xc5c4, 0xc5c5, 0xc5c6, 0xc5c7, 0xc5c8,
+ 0xc5c9, 0xc5ca, 0xc5cb, 0xc5cc, 0xc5cd, 0xc5ce, 0xc5cf, 0xc5d0,
+ 0xc5d1, 0xc5d3, 0xc5d4, 0xc5d5, 0xc5d6, 0xc5d7, 0xc5d8, 0xc5d9,
+ 0xc5da, 0xc5db, 0xc5dc, 0xc5dd, 0xc5e1, 0xc5e2, 0xc5e3, 0xc5e4,
+ 0xc5e5, 0xc5e6, 0xc5e7, 0xc5e8, 0xc5e9, 0xc5ea, 0xc5eb, 0xc5ec,
+ 0xc5ed, 0xc5ee, 0xc5ef, 0xc5f0, 0xc5f1, 0xc5f3, 0xc5f4, 0xc5f5,
+ 0xc5f6, 0xc5f7, 0xc5f8, 0xc5f9, 0xc5fa, 0xc5fb, 0xc5fc, 0xc5fd,
+ 0xc641, 0xc642, 0xc643, 0xc644, 0xc645, 0xc646, 0xc647, 0xc648,
+ 0xc649, 0xc64a, 0xc64b, 0xc64c, 0xc64d, 0xc64e, 0xc64f, 0xc650,
+ 0xc651, 0xc653, 0xc654, 0xc655, 0xc656, 0xc657, 0xc658, 0xc659,
+ 0xc65a, 0xc65b, 0xc65c, 0xc65d, 0xc661, 0xc662, 0xc663, 0xc664,
+ 0xc665, 0xc666, 0xc667, 0xc668, 0xc669, 0xc66a, 0xc66b, 0xc66c,
+ 0xc66d, 0xc66e, 0xc66f, 0xc670, 0xc671, 0xc673, 0xc674, 0xc675,
+ 0xc676, 0xc677, 0xc678, 0xc679, 0xc67a, 0xc67b, 0xc67c, 0xc67d,
+ 0xc681, 0xc682, 0xc683, 0xc684, 0xc685, 0xc686, 0xc687, 0xc688,
+ 0xc689, 0xc68a, 0xc68b, 0xc68c, 0xc68d, 0xc68e, 0xc68f, 0xc690,
+ 0xc691, 0xc693, 0xc694, 0xc695, 0xc696, 0xc697, 0xc698, 0xc699,
+ 0xc69a, 0xc69b, 0xc69c, 0xc69d, 0xc6a1, 0xc6a2, 0xc6a3, 0xc6a4
+};
+
+static unsigned short johab_from_unicode_d0[] = {
+ 0xc6a5, 0xc6a6, 0xc6a7, 0xc6a8, 0xc6a9, 0xc6aa, 0xc6ab, 0xc6ac,
+ 0xc6ad, 0xc6ae, 0xc6af, 0xc6b0, 0xc6b1, 0xc6b3, 0xc6b4, 0xc6b5,
+ 0xc6b6, 0xc6b7, 0xc6b8, 0xc6b9, 0xc6ba, 0xc6bb, 0xc6bc, 0xc6bd,
+ 0xc6c1, 0xc6c2, 0xc6c3, 0xc6c4, 0xc6c5, 0xc6c6, 0xc6c7, 0xc6c8,
+ 0xc6c9, 0xc6ca, 0xc6cb, 0xc6cc, 0xc6cd, 0xc6ce, 0xc6cf, 0xc6d0,
+ 0xc6d1, 0xc6d3, 0xc6d4, 0xc6d5, 0xc6d6, 0xc6d7, 0xc6d8, 0xc6d9,
+ 0xc6da, 0xc6db, 0xc6dc, 0xc6dd, 0xc6e1, 0xc6e2, 0xc6e3, 0xc6e4,
+ 0xc6e5, 0xc6e6, 0xc6e7, 0xc6e8, 0xc6e9, 0xc6ea, 0xc6eb, 0xc6ec,
+ 0xc6ed, 0xc6ee, 0xc6ef, 0xc6f0, 0xc6f1, 0xc6f3, 0xc6f4, 0xc6f5,
+ 0xc6f6, 0xc6f7, 0xc6f8, 0xc6f9, 0xc6fa, 0xc6fb, 0xc6fc, 0xc6fd,
+ 0xc741, 0xc742, 0xc743, 0xc744, 0xc745, 0xc746, 0xc747, 0xc748,
+ 0xc749, 0xc74a, 0xc74b, 0xc74c, 0xc74d, 0xc74e, 0xc74f, 0xc750,
+ 0xc751, 0xc753, 0xc754, 0xc755, 0xc756, 0xc757, 0xc758, 0xc759,
+ 0xc75a, 0xc75b, 0xc75c, 0xc75d, 0xc761, 0xc762, 0xc763, 0xc764,
+ 0xc765, 0xc766, 0xc767, 0xc768, 0xc769, 0xc76a, 0xc76b, 0xc76c,
+ 0xc76d, 0xc76e, 0xc76f, 0xc770, 0xc771, 0xc773, 0xc774, 0xc775,
+ 0xc776, 0xc777, 0xc778, 0xc779, 0xc77a, 0xc77b, 0xc77c, 0xc77d,
+ 0xc781, 0xc782, 0xc783, 0xc784, 0xc785, 0xc786, 0xc787, 0xc788,
+ 0xc789, 0xc78a, 0xc78b, 0xc78c, 0xc78d, 0xc78e, 0xc78f, 0xc790,
+ 0xc791, 0xc793, 0xc794, 0xc795, 0xc796, 0xc797, 0xc798, 0xc799,
+ 0xc79a, 0xc79b, 0xc79c, 0xc79d, 0xc7a1, 0xc7a2, 0xc7a3, 0xc7a4,
+ 0xc7a5, 0xc7a6, 0xc7a7, 0xc7a8, 0xc7a9, 0xc7aa, 0xc7ab, 0xc7ac,
+ 0xc7ad, 0xc7ae, 0xc7af, 0xc7b0, 0xc7b1, 0xc7b3, 0xc7b4, 0xc7b5,
+ 0xc7b6, 0xc7b7, 0xc7b8, 0xc7b9, 0xc7ba, 0xc7bb, 0xc7bc, 0xc7bd,
+ 0xc861, 0xc862, 0xc863, 0xc864, 0xc865, 0xc866, 0xc867, 0xc868,
+ 0xc869, 0xc86a, 0xc86b, 0xc86c, 0xc86d, 0xc86e, 0xc86f, 0xc870,
+ 0xc871, 0xc873, 0xc874, 0xc875, 0xc876, 0xc877, 0xc878, 0xc879,
+ 0xc87a, 0xc87b, 0xc87c, 0xc87d, 0xc881, 0xc882, 0xc883, 0xc884,
+ 0xc885, 0xc886, 0xc887, 0xc888, 0xc889, 0xc88a, 0xc88b, 0xc88c,
+ 0xc88d, 0xc88e, 0xc88f, 0xc890, 0xc891, 0xc893, 0xc894, 0xc895,
+ 0xc896, 0xc897, 0xc898, 0xc899, 0xc89a, 0xc89b, 0xc89c, 0xc89d,
+ 0xc8a1, 0xc8a2, 0xc8a3, 0xc8a4, 0xc8a5, 0xc8a6, 0xc8a7, 0xc8a8
+};
+
+static unsigned short johab_from_unicode_d1[] = {
+ 0xc8a9, 0xc8aa, 0xc8ab, 0xc8ac, 0xc8ad, 0xc8ae, 0xc8af, 0xc8b0,
+ 0xc8b1, 0xc8b3, 0xc8b4, 0xc8b5, 0xc8b6, 0xc8b7, 0xc8b8, 0xc8b9,
+ 0xc8ba, 0xc8bb, 0xc8bc, 0xc8bd, 0xc8c1, 0xc8c2, 0xc8c3, 0xc8c4,
+ 0xc8c5, 0xc8c6, 0xc8c7, 0xc8c8, 0xc8c9, 0xc8ca, 0xc8cb, 0xc8cc,
+ 0xc8cd, 0xc8ce, 0xc8cf, 0xc8d0, 0xc8d1, 0xc8d3, 0xc8d4, 0xc8d5,
+ 0xc8d6, 0xc8d7, 0xc8d8, 0xc8d9, 0xc8da, 0xc8db, 0xc8dc, 0xc8dd,
+ 0xc8e1, 0xc8e2, 0xc8e3, 0xc8e4, 0xc8e5, 0xc8e6, 0xc8e7, 0xc8e8,
+ 0xc8e9, 0xc8ea, 0xc8eb, 0xc8ec, 0xc8ed, 0xc8ee, 0xc8ef, 0xc8f0,
+ 0xc8f1, 0xc8f3, 0xc8f4, 0xc8f5, 0xc8f6, 0xc8f7, 0xc8f8, 0xc8f9,
+ 0xc8fa, 0xc8fb, 0xc8fc, 0xc8fd, 0xc941, 0xc942, 0xc943, 0xc944,
+ 0xc945, 0xc946, 0xc947, 0xc948, 0xc949, 0xc94a, 0xc94b, 0xc94c,
+ 0xc94d, 0xc94e, 0xc94f, 0xc950, 0xc951, 0xc953, 0xc954, 0xc955,
+ 0xc956, 0xc957, 0xc958, 0xc959, 0xc95a, 0xc95b, 0xc95c, 0xc95d,
+ 0xc961, 0xc962, 0xc963, 0xc964, 0xc965, 0xc966, 0xc967, 0xc968,
+ 0xc969, 0xc96a, 0xc96b, 0xc96c, 0xc96d, 0xc96e, 0xc96f, 0xc970,
+ 0xc971, 0xc973, 0xc974, 0xc975, 0xc976, 0xc977, 0xc978, 0xc979,
+ 0xc97a, 0xc97b, 0xc97c, 0xc97d, 0xc981, 0xc982, 0xc983, 0xc984,
+ 0xc985, 0xc986, 0xc987, 0xc988, 0xc989, 0xc98a, 0xc98b, 0xc98c,
+ 0xc98d, 0xc98e, 0xc98f, 0xc990, 0xc991, 0xc993, 0xc994, 0xc995,
+ 0xc996, 0xc997, 0xc998, 0xc999, 0xc99a, 0xc99b, 0xc99c, 0xc99d,
+ 0xc9a1, 0xc9a2, 0xc9a3, 0xc9a4, 0xc9a5, 0xc9a6, 0xc9a7, 0xc9a8,
+ 0xc9a9, 0xc9aa, 0xc9ab, 0xc9ac, 0xc9ad, 0xc9ae, 0xc9af, 0xc9b0,
+ 0xc9b1, 0xc9b3, 0xc9b4, 0xc9b5, 0xc9b6, 0xc9b7, 0xc9b8, 0xc9b9,
+ 0xc9ba, 0xc9bb, 0xc9bc, 0xc9bd, 0xc9c1, 0xc9c2, 0xc9c3, 0xc9c4,
+ 0xc9c5, 0xc9c6, 0xc9c7, 0xc9c8, 0xc9c9, 0xc9ca, 0xc9cb, 0xc9cc,
+ 0xc9cd, 0xc9ce, 0xc9cf, 0xc9d0, 0xc9d1, 0xc9d3, 0xc9d4, 0xc9d5,
+ 0xc9d6, 0xc9d7, 0xc9d8, 0xc9d9, 0xc9da, 0xc9db, 0xc9dc, 0xc9dd,
+ 0xc9e1, 0xc9e2, 0xc9e3, 0xc9e4, 0xc9e5, 0xc9e6, 0xc9e7, 0xc9e8,
+ 0xc9e9, 0xc9ea, 0xc9eb, 0xc9ec, 0xc9ed, 0xc9ee, 0xc9ef, 0xc9f0,
+ 0xc9f1, 0xc9f3, 0xc9f4, 0xc9f5, 0xc9f6, 0xc9f7, 0xc9f8, 0xc9f9,
+ 0xc9fa, 0xc9fb, 0xc9fc, 0xc9fd, 0xca41, 0xca42, 0xca43, 0xca44,
+ 0xca45, 0xca46, 0xca47, 0xca48, 0xca49, 0xca4a, 0xca4b, 0xca4c
+};
+
+static unsigned short johab_from_unicode_d2[] = {
+ 0xca4d, 0xca4e, 0xca4f, 0xca50, 0xca51, 0xca53, 0xca54, 0xca55,
+ 0xca56, 0xca57, 0xca58, 0xca59, 0xca5a, 0xca5b, 0xca5c, 0xca5d,
+ 0xca61, 0xca62, 0xca63, 0xca64, 0xca65, 0xca66, 0xca67, 0xca68,
+ 0xca69, 0xca6a, 0xca6b, 0xca6c, 0xca6d, 0xca6e, 0xca6f, 0xca70,
+ 0xca71, 0xca73, 0xca74, 0xca75, 0xca76, 0xca77, 0xca78, 0xca79,
+ 0xca7a, 0xca7b, 0xca7c, 0xca7d, 0xca81, 0xca82, 0xca83, 0xca84,
+ 0xca85, 0xca86, 0xca87, 0xca88, 0xca89, 0xca8a, 0xca8b, 0xca8c,
+ 0xca8d, 0xca8e, 0xca8f, 0xca90, 0xca91, 0xca93, 0xca94, 0xca95,
+ 0xca96, 0xca97, 0xca98, 0xca99, 0xca9a, 0xca9b, 0xca9c, 0xca9d,
+ 0xcaa1, 0xcaa2, 0xcaa3, 0xcaa4, 0xcaa5, 0xcaa6, 0xcaa7, 0xcaa8,
+ 0xcaa9, 0xcaaa, 0xcaab, 0xcaac, 0xcaad, 0xcaae, 0xcaaf, 0xcab0,
+ 0xcab1, 0xcab3, 0xcab4, 0xcab5, 0xcab6, 0xcab7, 0xcab8, 0xcab9,
+ 0xcaba, 0xcabb, 0xcabc, 0xcabd, 0xcac1, 0xcac2, 0xcac3, 0xcac4,
+ 0xcac5, 0xcac6, 0xcac7, 0xcac8, 0xcac9, 0xcaca, 0xcacb, 0xcacc,
+ 0xcacd, 0xcace, 0xcacf, 0xcad0, 0xcad1, 0xcad3, 0xcad4, 0xcad5,
+ 0xcad6, 0xcad7, 0xcad8, 0xcad9, 0xcada, 0xcadb, 0xcadc, 0xcadd,
+ 0xcae1, 0xcae2, 0xcae3, 0xcae4, 0xcae5, 0xcae6, 0xcae7, 0xcae8,
+ 0xcae9, 0xcaea, 0xcaeb, 0xcaec, 0xcaed, 0xcaee, 0xcaef, 0xcaf0,
+ 0xcaf1, 0xcaf3, 0xcaf4, 0xcaf5, 0xcaf6, 0xcaf7, 0xcaf8, 0xcaf9,
+ 0xcafa, 0xcafb, 0xcafc, 0xcafd, 0xcb41, 0xcb42, 0xcb43, 0xcb44,
+ 0xcb45, 0xcb46, 0xcb47, 0xcb48, 0xcb49, 0xcb4a, 0xcb4b, 0xcb4c,
+ 0xcb4d, 0xcb4e, 0xcb4f, 0xcb50, 0xcb51, 0xcb53, 0xcb54, 0xcb55,
+ 0xcb56, 0xcb57, 0xcb58, 0xcb59, 0xcb5a, 0xcb5b, 0xcb5c, 0xcb5d,
+ 0xcb61, 0xcb62, 0xcb63, 0xcb64, 0xcb65, 0xcb66, 0xcb67, 0xcb68,
+ 0xcb69, 0xcb6a, 0xcb6b, 0xcb6c, 0xcb6d, 0xcb6e, 0xcb6f, 0xcb70,
+ 0xcb71, 0xcb73, 0xcb74, 0xcb75, 0xcb76, 0xcb77, 0xcb78, 0xcb79,
+ 0xcb7a, 0xcb7b, 0xcb7c, 0xcb7d, 0xcb81, 0xcb82, 0xcb83, 0xcb84,
+ 0xcb85, 0xcb86, 0xcb87, 0xcb88, 0xcb89, 0xcb8a, 0xcb8b, 0xcb8c,
+ 0xcb8d, 0xcb8e, 0xcb8f, 0xcb90, 0xcb91, 0xcb93, 0xcb94, 0xcb95,
+ 0xcb96, 0xcb97, 0xcb98, 0xcb99, 0xcb9a, 0xcb9b, 0xcb9c, 0xcb9d,
+ 0xcba1, 0xcba2, 0xcba3, 0xcba4, 0xcba5, 0xcba6, 0xcba7, 0xcba8,
+ 0xcba9, 0xcbaa, 0xcbab, 0xcbac, 0xcbad, 0xcbae, 0xcbaf, 0xcbb0
+};
+
+static unsigned short johab_from_unicode_d3[] = {
+ 0xcbb1, 0xcbb3, 0xcbb4, 0xcbb5, 0xcbb6, 0xcbb7, 0xcbb8, 0xcbb9,
+ 0xcbba, 0xcbbb, 0xcbbc, 0xcbbd, 0xcc61, 0xcc62, 0xcc63, 0xcc64,
+ 0xcc65, 0xcc66, 0xcc67, 0xcc68, 0xcc69, 0xcc6a, 0xcc6b, 0xcc6c,
+ 0xcc6d, 0xcc6e, 0xcc6f, 0xcc70, 0xcc71, 0xcc73, 0xcc74, 0xcc75,
+ 0xcc76, 0xcc77, 0xcc78, 0xcc79, 0xcc7a, 0xcc7b, 0xcc7c, 0xcc7d,
+ 0xcc81, 0xcc82, 0xcc83, 0xcc84, 0xcc85, 0xcc86, 0xcc87, 0xcc88,
+ 0xcc89, 0xcc8a, 0xcc8b, 0xcc8c, 0xcc8d, 0xcc8e, 0xcc8f, 0xcc90,
+ 0xcc91, 0xcc93, 0xcc94, 0xcc95, 0xcc96, 0xcc97, 0xcc98, 0xcc99,
+ 0xcc9a, 0xcc9b, 0xcc9c, 0xcc9d, 0xcca1, 0xcca2, 0xcca3, 0xcca4,
+ 0xcca5, 0xcca6, 0xcca7, 0xcca8, 0xcca9, 0xccaa, 0xccab, 0xccac,
+ 0xccad, 0xccae, 0xccaf, 0xccb0, 0xccb1, 0xccb3, 0xccb4, 0xccb5,
+ 0xccb6, 0xccb7, 0xccb8, 0xccb9, 0xccba, 0xccbb, 0xccbc, 0xccbd,
+ 0xccc1, 0xccc2, 0xccc3, 0xccc4, 0xccc5, 0xccc6, 0xccc7, 0xccc8,
+ 0xccc9, 0xccca, 0xcccb, 0xcccc, 0xcccd, 0xccce, 0xcccf, 0xccd0,
+ 0xccd1, 0xccd3, 0xccd4, 0xccd5, 0xccd6, 0xccd7, 0xccd8, 0xccd9,
+ 0xccda, 0xccdb, 0xccdc, 0xccdd, 0xcce1, 0xcce2, 0xcce3, 0xcce4,
+ 0xcce5, 0xcce6, 0xcce7, 0xcce8, 0xcce9, 0xccea, 0xcceb, 0xccec,
+ 0xcced, 0xccee, 0xccef, 0xccf0, 0xccf1, 0xccf3, 0xccf4, 0xccf5,
+ 0xccf6, 0xccf7, 0xccf8, 0xccf9, 0xccfa, 0xccfb, 0xccfc, 0xccfd,
+ 0xcd41, 0xcd42, 0xcd43, 0xcd44, 0xcd45, 0xcd46, 0xcd47, 0xcd48,
+ 0xcd49, 0xcd4a, 0xcd4b, 0xcd4c, 0xcd4d, 0xcd4e, 0xcd4f, 0xcd50,
+ 0xcd51, 0xcd53, 0xcd54, 0xcd55, 0xcd56, 0xcd57, 0xcd58, 0xcd59,
+ 0xcd5a, 0xcd5b, 0xcd5c, 0xcd5d, 0xcd61, 0xcd62, 0xcd63, 0xcd64,
+ 0xcd65, 0xcd66, 0xcd67, 0xcd68, 0xcd69, 0xcd6a, 0xcd6b, 0xcd6c,
+ 0xcd6d, 0xcd6e, 0xcd6f, 0xcd70, 0xcd71, 0xcd73, 0xcd74, 0xcd75,
+ 0xcd76, 0xcd77, 0xcd78, 0xcd79, 0xcd7a, 0xcd7b, 0xcd7c, 0xcd7d,
+ 0xcd81, 0xcd82, 0xcd83, 0xcd84, 0xcd85, 0xcd86, 0xcd87, 0xcd88,
+ 0xcd89, 0xcd8a, 0xcd8b, 0xcd8c, 0xcd8d, 0xcd8e, 0xcd8f, 0xcd90,
+ 0xcd91, 0xcd93, 0xcd94, 0xcd95, 0xcd96, 0xcd97, 0xcd98, 0xcd99,
+ 0xcd9a, 0xcd9b, 0xcd9c, 0xcd9d, 0xcda1, 0xcda2, 0xcda3, 0xcda4,
+ 0xcda5, 0xcda6, 0xcda7, 0xcda8, 0xcda9, 0xcdaa, 0xcdab, 0xcdac,
+ 0xcdad, 0xcdae, 0xcdaf, 0xcdb0, 0xcdb1, 0xcdb3, 0xcdb4, 0xcdb5
+};
+
+static unsigned short johab_from_unicode_d4[] = {
+ 0xcdb6, 0xcdb7, 0xcdb8, 0xcdb9, 0xcdba, 0xcdbb, 0xcdbc, 0xcdbd,
+ 0xcdc1, 0xcdc2, 0xcdc3, 0xcdc4, 0xcdc5, 0xcdc6, 0xcdc7, 0xcdc8,
+ 0xcdc9, 0xcdca, 0xcdcb, 0xcdcc, 0xcdcd, 0xcdce, 0xcdcf, 0xcdd0,
+ 0xcdd1, 0xcdd3, 0xcdd4, 0xcdd5, 0xcdd6, 0xcdd7, 0xcdd8, 0xcdd9,
+ 0xcdda, 0xcddb, 0xcddc, 0xcddd, 0xcde1, 0xcde2, 0xcde3, 0xcde4,
+ 0xcde5, 0xcde6, 0xcde7, 0xcde8, 0xcde9, 0xcdea, 0xcdeb, 0xcdec,
+ 0xcded, 0xcdee, 0xcdef, 0xcdf0, 0xcdf1, 0xcdf3, 0xcdf4, 0xcdf5,
+ 0xcdf6, 0xcdf7, 0xcdf8, 0xcdf9, 0xcdfa, 0xcdfb, 0xcdfc, 0xcdfd,
+ 0xce41, 0xce42, 0xce43, 0xce44, 0xce45, 0xce46, 0xce47, 0xce48,
+ 0xce49, 0xce4a, 0xce4b, 0xce4c, 0xce4d, 0xce4e, 0xce4f, 0xce50,
+ 0xce51, 0xce53, 0xce54, 0xce55, 0xce56, 0xce57, 0xce58, 0xce59,
+ 0xce5a, 0xce5b, 0xce5c, 0xce5d, 0xce61, 0xce62, 0xce63, 0xce64,
+ 0xce65, 0xce66, 0xce67, 0xce68, 0xce69, 0xce6a, 0xce6b, 0xce6c,
+ 0xce6d, 0xce6e, 0xce6f, 0xce70, 0xce71, 0xce73, 0xce74, 0xce75,
+ 0xce76, 0xce77, 0xce78, 0xce79, 0xce7a, 0xce7b, 0xce7c, 0xce7d,
+ 0xce81, 0xce82, 0xce83, 0xce84, 0xce85, 0xce86, 0xce87, 0xce88,
+ 0xce89, 0xce8a, 0xce8b, 0xce8c, 0xce8d, 0xce8e, 0xce8f, 0xce90,
+ 0xce91, 0xce93, 0xce94, 0xce95, 0xce96, 0xce97, 0xce98, 0xce99,
+ 0xce9a, 0xce9b, 0xce9c, 0xce9d, 0xcea1, 0xcea2, 0xcea3, 0xcea4,
+ 0xcea5, 0xcea6, 0xcea7, 0xcea8, 0xcea9, 0xceaa, 0xceab, 0xceac,
+ 0xcead, 0xceae, 0xceaf, 0xceb0, 0xceb1, 0xceb3, 0xceb4, 0xceb5,
+ 0xceb6, 0xceb7, 0xceb8, 0xceb9, 0xceba, 0xcebb, 0xcebc, 0xcebd,
+ 0xcec1, 0xcec2, 0xcec3, 0xcec4, 0xcec5, 0xcec6, 0xcec7, 0xcec8,
+ 0xcec9, 0xceca, 0xcecb, 0xcecc, 0xcecd, 0xcece, 0xcecf, 0xced0,
+ 0xced1, 0xced3, 0xced4, 0xced5, 0xced6, 0xced7, 0xced8, 0xced9,
+ 0xceda, 0xcedb, 0xcedc, 0xcedd, 0xcee1, 0xcee2, 0xcee3, 0xcee4,
+ 0xcee5, 0xcee6, 0xcee7, 0xcee8, 0xcee9, 0xceea, 0xceeb, 0xceec,
+ 0xceed, 0xceee, 0xceef, 0xcef0, 0xcef1, 0xcef3, 0xcef4, 0xcef5,
+ 0xcef6, 0xcef7, 0xcef8, 0xcef9, 0xcefa, 0xcefb, 0xcefc, 0xcefd,
+ 0xcf41, 0xcf42, 0xcf43, 0xcf44, 0xcf45, 0xcf46, 0xcf47, 0xcf48,
+ 0xcf49, 0xcf4a, 0xcf4b, 0xcf4c, 0xcf4d, 0xcf4e, 0xcf4f, 0xcf50,
+ 0xcf51, 0xcf53, 0xcf54, 0xcf55, 0xcf56, 0xcf57, 0xcf58, 0xcf59
+};
+
+static unsigned short johab_from_unicode_d5[] = {
+ 0xcf5a, 0xcf5b, 0xcf5c, 0xcf5d, 0xcf61, 0xcf62, 0xcf63, 0xcf64,
+ 0xcf65, 0xcf66, 0xcf67, 0xcf68, 0xcf69, 0xcf6a, 0xcf6b, 0xcf6c,
+ 0xcf6d, 0xcf6e, 0xcf6f, 0xcf70, 0xcf71, 0xcf73, 0xcf74, 0xcf75,
+ 0xcf76, 0xcf77, 0xcf78, 0xcf79, 0xcf7a, 0xcf7b, 0xcf7c, 0xcf7d,
+ 0xcf81, 0xcf82, 0xcf83, 0xcf84, 0xcf85, 0xcf86, 0xcf87, 0xcf88,
+ 0xcf89, 0xcf8a, 0xcf8b, 0xcf8c, 0xcf8d, 0xcf8e, 0xcf8f, 0xcf90,
+ 0xcf91, 0xcf93, 0xcf94, 0xcf95, 0xcf96, 0xcf97, 0xcf98, 0xcf99,
+ 0xcf9a, 0xcf9b, 0xcf9c, 0xcf9d, 0xcfa1, 0xcfa2, 0xcfa3, 0xcfa4,
+ 0xcfa5, 0xcfa6, 0xcfa7, 0xcfa8, 0xcfa9, 0xcfaa, 0xcfab, 0xcfac,
+ 0xcfad, 0xcfae, 0xcfaf, 0xcfb0, 0xcfb1, 0xcfb3, 0xcfb4, 0xcfb5,
+ 0xcfb6, 0xcfb7, 0xcfb8, 0xcfb9, 0xcfba, 0xcfbb, 0xcfbc, 0xcfbd,
+ 0xd061, 0xd062, 0xd063, 0xd064, 0xd065, 0xd066, 0xd067, 0xd068,
+ 0xd069, 0xd06a, 0xd06b, 0xd06c, 0xd06d, 0xd06e, 0xd06f, 0xd070,
+ 0xd071, 0xd073, 0xd074, 0xd075, 0xd076, 0xd077, 0xd078, 0xd079,
+ 0xd07a, 0xd07b, 0xd07c, 0xd07d, 0xd081, 0xd082, 0xd083, 0xd084,
+ 0xd085, 0xd086, 0xd087, 0xd088, 0xd089, 0xd08a, 0xd08b, 0xd08c,
+ 0xd08d, 0xd08e, 0xd08f, 0xd090, 0xd091, 0xd093, 0xd094, 0xd095,
+ 0xd096, 0xd097, 0xd098, 0xd099, 0xd09a, 0xd09b, 0xd09c, 0xd09d,
+ 0xd0a1, 0xd0a2, 0xd0a3, 0xd0a4, 0xd0a5, 0xd0a6, 0xd0a7, 0xd0a8,
+ 0xd0a9, 0xd0aa, 0xd0ab, 0xd0ac, 0xd0ad, 0xd0ae, 0xd0af, 0xd0b0,
+ 0xd0b1, 0xd0b3, 0xd0b4, 0xd0b5, 0xd0b6, 0xd0b7, 0xd0b8, 0xd0b9,
+ 0xd0ba, 0xd0bb, 0xd0bc, 0xd0bd, 0xd0c1, 0xd0c2, 0xd0c3, 0xd0c4,
+ 0xd0c5, 0xd0c6, 0xd0c7, 0xd0c8, 0xd0c9, 0xd0ca, 0xd0cb, 0xd0cc,
+ 0xd0cd, 0xd0ce, 0xd0cf, 0xd0d0, 0xd0d1, 0xd0d3, 0xd0d4, 0xd0d5,
+ 0xd0d6, 0xd0d7, 0xd0d8, 0xd0d9, 0xd0da, 0xd0db, 0xd0dc, 0xd0dd,
+ 0xd0e1, 0xd0e2, 0xd0e3, 0xd0e4, 0xd0e5, 0xd0e6, 0xd0e7, 0xd0e8,
+ 0xd0e9, 0xd0ea, 0xd0eb, 0xd0ec, 0xd0ed, 0xd0ee, 0xd0ef, 0xd0f0,
+ 0xd0f1, 0xd0f3, 0xd0f4, 0xd0f5, 0xd0f6, 0xd0f7, 0xd0f8, 0xd0f9,
+ 0xd0fa, 0xd0fb, 0xd0fc, 0xd0fd, 0xd141, 0xd142, 0xd143, 0xd144,
+ 0xd145, 0xd146, 0xd147, 0xd148, 0xd149, 0xd14a, 0xd14b, 0xd14c,
+ 0xd14d, 0xd14e, 0xd14f, 0xd150, 0xd151, 0xd153, 0xd154, 0xd155,
+ 0xd156, 0xd157, 0xd158, 0xd159, 0xd15a, 0xd15b, 0xd15c, 0xd15d
+};
+
+static unsigned short johab_from_unicode_d6[] = {
+ 0xd161, 0xd162, 0xd163, 0xd164, 0xd165, 0xd166, 0xd167, 0xd168,
+ 0xd169, 0xd16a, 0xd16b, 0xd16c, 0xd16d, 0xd16e, 0xd16f, 0xd170,
+ 0xd171, 0xd173, 0xd174, 0xd175, 0xd176, 0xd177, 0xd178, 0xd179,
+ 0xd17a, 0xd17b, 0xd17c, 0xd17d, 0xd181, 0xd182, 0xd183, 0xd184,
+ 0xd185, 0xd186, 0xd187, 0xd188, 0xd189, 0xd18a, 0xd18b, 0xd18c,
+ 0xd18d, 0xd18e, 0xd18f, 0xd190, 0xd191, 0xd193, 0xd194, 0xd195,
+ 0xd196, 0xd197, 0xd198, 0xd199, 0xd19a, 0xd19b, 0xd19c, 0xd19d,
+ 0xd1a1, 0xd1a2, 0xd1a3, 0xd1a4, 0xd1a5, 0xd1a6, 0xd1a7, 0xd1a8,
+ 0xd1a9, 0xd1aa, 0xd1ab, 0xd1ac, 0xd1ad, 0xd1ae, 0xd1af, 0xd1b0,
+ 0xd1b1, 0xd1b3, 0xd1b4, 0xd1b5, 0xd1b6, 0xd1b7, 0xd1b8, 0xd1b9,
+ 0xd1ba, 0xd1bb, 0xd1bc, 0xd1bd, 0xd1c1, 0xd1c2, 0xd1c3, 0xd1c4,
+ 0xd1c5, 0xd1c6, 0xd1c7, 0xd1c8, 0xd1c9, 0xd1ca, 0xd1cb, 0xd1cc,
+ 0xd1cd, 0xd1ce, 0xd1cf, 0xd1d0, 0xd1d1, 0xd1d3, 0xd1d4, 0xd1d5,
+ 0xd1d6, 0xd1d7, 0xd1d8, 0xd1d9, 0xd1da, 0xd1db, 0xd1dc, 0xd1dd,
+ 0xd1e1, 0xd1e2, 0xd1e3, 0xd1e4, 0xd1e5, 0xd1e6, 0xd1e7, 0xd1e8,
+ 0xd1e9, 0xd1ea, 0xd1eb, 0xd1ec, 0xd1ed, 0xd1ee, 0xd1ef, 0xd1f0,
+ 0xd1f1, 0xd1f3, 0xd1f4, 0xd1f5, 0xd1f6, 0xd1f7, 0xd1f8, 0xd1f9,
+ 0xd1fa, 0xd1fb, 0xd1fc, 0xd1fd, 0xd241, 0xd242, 0xd243, 0xd244,
+ 0xd245, 0xd246, 0xd247, 0xd248, 0xd249, 0xd24a, 0xd24b, 0xd24c,
+ 0xd24d, 0xd24e, 0xd24f, 0xd250, 0xd251, 0xd253, 0xd254, 0xd255,
+ 0xd256, 0xd257, 0xd258, 0xd259, 0xd25a, 0xd25b, 0xd25c, 0xd25d,
+ 0xd261, 0xd262, 0xd263, 0xd264, 0xd265, 0xd266, 0xd267, 0xd268,
+ 0xd269, 0xd26a, 0xd26b, 0xd26c, 0xd26d, 0xd26e, 0xd26f, 0xd270,
+ 0xd271, 0xd273, 0xd274, 0xd275, 0xd276, 0xd277, 0xd278, 0xd279,
+ 0xd27a, 0xd27b, 0xd27c, 0xd27d, 0xd281, 0xd282, 0xd283, 0xd284,
+ 0xd285, 0xd286, 0xd287, 0xd288, 0xd289, 0xd28a, 0xd28b, 0xd28c,
+ 0xd28d, 0xd28e, 0xd28f, 0xd290, 0xd291, 0xd293, 0xd294, 0xd295,
+ 0xd296, 0xd297, 0xd298, 0xd299, 0xd29a, 0xd29b, 0xd29c, 0xd29d,
+ 0xd2a1, 0xd2a2, 0xd2a3, 0xd2a4, 0xd2a5, 0xd2a6, 0xd2a7, 0xd2a8,
+ 0xd2a9, 0xd2aa, 0xd2ab, 0xd2ac, 0xd2ad, 0xd2ae, 0xd2af, 0xd2b0,
+ 0xd2b1, 0xd2b3, 0xd2b4, 0xd2b5, 0xd2b6, 0xd2b7, 0xd2b8, 0xd2b9,
+ 0xd2ba, 0xd2bb, 0xd2bc, 0xd2bd, 0xd2c1, 0xd2c2, 0xd2c3, 0xd2c4
+};
+
+static unsigned short johab_from_unicode_d7[] = {
+ 0xd2c5, 0xd2c6, 0xd2c7, 0xd2c8, 0xd2c9, 0xd2ca, 0xd2cb, 0xd2cc,
+ 0xd2cd, 0xd2ce, 0xd2cf, 0xd2d0, 0xd2d1, 0xd2d3, 0xd2d4, 0xd2d5,
+ 0xd2d6, 0xd2d7, 0xd2d8, 0xd2d9, 0xd2da, 0xd2db, 0xd2dc, 0xd2dd,
+ 0xd2e1, 0xd2e2, 0xd2e3, 0xd2e4, 0xd2e5, 0xd2e6, 0xd2e7, 0xd2e8,
+ 0xd2e9, 0xd2ea, 0xd2eb, 0xd2ec, 0xd2ed, 0xd2ee, 0xd2ef, 0xd2f0,
+ 0xd2f1, 0xd2f3, 0xd2f4, 0xd2f5, 0xd2f6, 0xd2f7, 0xd2f8, 0xd2f9,
+ 0xd2fa, 0xd2fb, 0xd2fc, 0xd2fd, 0xd341, 0xd342, 0xd343, 0xd344,
+ 0xd345, 0xd346, 0xd347, 0xd348, 0xd349, 0xd34a, 0xd34b, 0xd34c,
+ 0xd34d, 0xd34e, 0xd34f, 0xd350, 0xd351, 0xd353, 0xd354, 0xd355,
+ 0xd356, 0xd357, 0xd358, 0xd359, 0xd35a, 0xd35b, 0xd35c, 0xd35d,
+ 0xd361, 0xd362, 0xd363, 0xd364, 0xd365, 0xd366, 0xd367, 0xd368,
+ 0xd369, 0xd36a, 0xd36b, 0xd36c, 0xd36d, 0xd36e, 0xd36f, 0xd370,
+ 0xd371, 0xd373, 0xd374, 0xd375, 0xd376, 0xd377, 0xd378, 0xd379,
+ 0xd37a, 0xd37b, 0xd37c, 0xd37d, 0xd381, 0xd382, 0xd383, 0xd384,
+ 0xd385, 0xd386, 0xd387, 0xd388, 0xd389, 0xd38a, 0xd38b, 0xd38c,
+ 0xd38d, 0xd38e, 0xd38f, 0xd390, 0xd391, 0xd393, 0xd394, 0xd395,
+ 0xd396, 0xd397, 0xd398, 0xd399, 0xd39a, 0xd39b, 0xd39c, 0xd39d,
+ 0xd3a1, 0xd3a2, 0xd3a3, 0xd3a4, 0xd3a5, 0xd3a6, 0xd3a7, 0xd3a8,
+ 0xd3a9, 0xd3aa, 0xd3ab, 0xd3ac, 0xd3ad, 0xd3ae, 0xd3af, 0xd3b0,
+ 0xd3b1, 0xd3b3, 0xd3b4, 0xd3b5, 0xd3b6, 0xd3b7, 0xd3b8, 0xd3b9,
+ 0xd3ba, 0xd3bb, 0xd3bc, 0xd3bd, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short johab_from_unicode_ff[] = {
+ 0x0000, 0xda31, 0xda32, 0xda33, 0xda34, 0xda35, 0xda36, 0xda37,
+ 0xda38, 0xda39, 0xda3a, 0xda3b, 0xda3c, 0xda3d, 0xda3e, 0xda3f,
+ 0xda40, 0xda41, 0xda42, 0xda43, 0xda44, 0xda45, 0xda46, 0xda47,
+ 0xda48, 0xda49, 0xda4a, 0xda4b, 0xda4c, 0xda4d, 0xda4e, 0xda4f,
+ 0xda50, 0xda51, 0xda52, 0xda53, 0xda54, 0xda55, 0xda56, 0xda57,
+ 0xda58, 0xda59, 0xda5a, 0xda5b, 0xda5c, 0xda5d, 0xda5e, 0xda5f,
+ 0xda60, 0xda61, 0xda62, 0xda63, 0xda64, 0xda65, 0xda66, 0xda67,
+ 0xda68, 0xda69, 0xda6a, 0xda6b, 0xd93c, 0xda6d, 0xda6e, 0xda6f,
+ 0xda70, 0xda71, 0xda72, 0xda73, 0xda74, 0xda75, 0xda76, 0xda77,
+ 0xda78, 0xda79, 0xda7a, 0xda7b, 0xda7c, 0xda7d, 0xda7e, 0xda91,
+ 0xda92, 0xda93, 0xda94, 0xda95, 0xda96, 0xda97, 0xda98, 0xda99,
+ 0xda9a, 0xda9b, 0xda9c, 0xda9d, 0xda9e, 0xda9f, 0xd93d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xd95b, 0xd95c, 0xd9a0, 0xdaa0, 0x0000, 0xd95d, 0xda6c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short * const johab_from_unicode_[] = {
+ johab_from_unicode_0,
+ johab_from_unicode_1,
+ johab_from_unicode_2,
+ johab_from_unicode_3,
+ johab_from_unicode_4,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ johab_from_unicode_20,
+ johab_from_unicode_21,
+ johab_from_unicode_22,
+ johab_from_unicode_23,
+ johab_from_unicode_24,
+ johab_from_unicode_25,
+ johab_from_unicode_26,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ johab_from_unicode_30,
+ johab_from_unicode_31,
+ johab_from_unicode_32,
+ johab_from_unicode_33,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ johab_from_unicode_4e,
+ johab_from_unicode_4f,
+ johab_from_unicode_50,
+ johab_from_unicode_51,
+ johab_from_unicode_52,
+ johab_from_unicode_53,
+ johab_from_unicode_54,
+ johab_from_unicode_55,
+ johab_from_unicode_56,
+ johab_from_unicode_57,
+ johab_from_unicode_58,
+ johab_from_unicode_59,
+ johab_from_unicode_5a,
+ johab_from_unicode_5b,
+ johab_from_unicode_5c,
+ johab_from_unicode_5d,
+ johab_from_unicode_5e,
+ johab_from_unicode_5f,
+ johab_from_unicode_60,
+ johab_from_unicode_61,
+ johab_from_unicode_62,
+ johab_from_unicode_63,
+ johab_from_unicode_64,
+ johab_from_unicode_65,
+ johab_from_unicode_66,
+ johab_from_unicode_67,
+ johab_from_unicode_68,
+ johab_from_unicode_69,
+ johab_from_unicode_6a,
+ johab_from_unicode_6b,
+ johab_from_unicode_6c,
+ johab_from_unicode_6d,
+ johab_from_unicode_6e,
+ johab_from_unicode_6f,
+ johab_from_unicode_70,
+ johab_from_unicode_71,
+ johab_from_unicode_72,
+ johab_from_unicode_73,
+ johab_from_unicode_74,
+ johab_from_unicode_75,
+ johab_from_unicode_76,
+ johab_from_unicode_77,
+ johab_from_unicode_78,
+ johab_from_unicode_79,
+ johab_from_unicode_7a,
+ johab_from_unicode_7b,
+ johab_from_unicode_7c,
+ johab_from_unicode_7d,
+ johab_from_unicode_7e,
+ johab_from_unicode_7f,
+ johab_from_unicode_80,
+ johab_from_unicode_81,
+ johab_from_unicode_82,
+ johab_from_unicode_83,
+ johab_from_unicode_84,
+ johab_from_unicode_85,
+ johab_from_unicode_86,
+ johab_from_unicode_87,
+ johab_from_unicode_88,
+ johab_from_unicode_89,
+ johab_from_unicode_8a,
+ johab_from_unicode_8b,
+ johab_from_unicode_8c,
+ johab_from_unicode_8d,
+ johab_from_unicode_8e,
+ johab_from_unicode_8f,
+ johab_from_unicode_90,
+ johab_from_unicode_91,
+ johab_from_unicode_92,
+ johab_from_unicode_93,
+ johab_from_unicode_94,
+ johab_from_unicode_95,
+ johab_from_unicode_96,
+ johab_from_unicode_97,
+ johab_from_unicode_98,
+ johab_from_unicode_99,
+ johab_from_unicode_9a,
+ johab_from_unicode_9b,
+ johab_from_unicode_9c,
+ johab_from_unicode_9d,
+ johab_from_unicode_9e,
+ johab_from_unicode_9f,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ johab_from_unicode_ac,
+ johab_from_unicode_ad,
+ johab_from_unicode_ae,
+ johab_from_unicode_af,
+ johab_from_unicode_b0,
+ johab_from_unicode_b1,
+ johab_from_unicode_b2,
+ johab_from_unicode_b3,
+ johab_from_unicode_b4,
+ johab_from_unicode_b5,
+ johab_from_unicode_b6,
+ johab_from_unicode_b7,
+ johab_from_unicode_b8,
+ johab_from_unicode_b9,
+ johab_from_unicode_ba,
+ johab_from_unicode_bb,
+ johab_from_unicode_bc,
+ johab_from_unicode_bd,
+ johab_from_unicode_be,
+ johab_from_unicode_bf,
+ johab_from_unicode_c0,
+ johab_from_unicode_c1,
+ johab_from_unicode_c2,
+ johab_from_unicode_c3,
+ johab_from_unicode_c4,
+ johab_from_unicode_c5,
+ johab_from_unicode_c6,
+ johab_from_unicode_c7,
+ johab_from_unicode_c8,
+ johab_from_unicode_c9,
+ johab_from_unicode_ca,
+ johab_from_unicode_cb,
+ johab_from_unicode_cc,
+ johab_from_unicode_cd,
+ johab_from_unicode_ce,
+ johab_from_unicode_cf,
+ johab_from_unicode_d0,
+ johab_from_unicode_d1,
+ johab_from_unicode_d2,
+ johab_from_unicode_d3,
+ johab_from_unicode_d4,
+ johab_from_unicode_d5,
+ johab_from_unicode_d6,
+ johab_from_unicode_d7,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ johab_from_unicode_ff
+};
+
+struct charmap2 johab_from_unicode = { 0, 255, (unsigned short **) johab_from_unicode_, (unichar_t *) unicode_from_johab };
+
+#endif
+
+const unichar_t unicode_from_gb2312[] = {
+ 0x3000, 0x3001, 0x3002, 0x30fb, 0x02c9, 0x02c7, 0x00a8, 0x3003,
+ 0x3005, 0x2014, 0xff5e, 0x2016, 0x2026, 0x2018, 0x2019, 0x201c,
+ 0x201d, 0x3014, 0x3015, 0x3008, 0x3009, 0x300a, 0x300b, 0x300c,
+ 0x300d, 0x300e, 0x300f, 0x3016, 0x3017, 0x3010, 0x3011, 0x00b1,
+ 0x00d7, 0x00f7, 0x2236, 0x2227, 0x2228, 0x2211, 0x220f, 0x222a,
+ 0x2229, 0x2208, 0x2237, 0x221a, 0x22a5, 0x2225, 0x2220, 0x2312,
+ 0x2299, 0x222b, 0x222e, 0x2261, 0x224c, 0x2248, 0x223d, 0x221d,
+ 0x2260, 0x226e, 0x226f, 0x2264, 0x2265, 0x221e, 0x2235, 0x2234,
+ 0x2642, 0x2640, 0x00b0, 0x2032, 0x2033, 0x2103, 0xff04, 0x00a4,
+ 0xffe0, 0xffe1, 0x2030, 0x00a7, 0x2116, 0x2606, 0x2605, 0x25cb,
+ 0x25cf, 0x25ce, 0x25c7, 0x25c6, 0x25a1, 0x25a0, 0x25b3, 0x25b2,
+ 0x203b, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2488, 0x2489,
+ 0x248a, 0x248b, 0x248c, 0x248d, 0x248e, 0x248f, 0x2490, 0x2491,
+ 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, 0x2497, 0x2498, 0x2499,
+ 0x249a, 0x249b, 0x2474, 0x2475, 0x2476, 0x2477, 0x2478, 0x2479,
+ 0x247a, 0x247b, 0x247c, 0x247d, 0x247e, 0x247f, 0x2480, 0x2481,
+ 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487, 0x2460, 0x2461,
+ 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468, 0x2469,
+ 0x0000, 0x0000, 0x3220, 0x3221, 0x3222, 0x3223, 0x3224, 0x3225,
+ 0x3226, 0x3227, 0x3228, 0x3229, 0x0000, 0x0000, 0x2160, 0x2161,
+ 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169,
+ 0x216a, 0x216b, 0x0000, 0x0000, 0xff01, 0xff02, 0xff03, 0xffe5,
+ 0xff05, 0xff06, 0xff07, 0xff08, 0xff09, 0xff0a, 0xff0b, 0xff0c,
+ 0xff0d, 0xff0e, 0xff0f, 0xff10, 0xff11, 0xff12, 0xff13, 0xff14,
+ 0xff15, 0xff16, 0xff17, 0xff18, 0xff19, 0xff1a, 0xff1b, 0xff1c,
+ 0xff1d, 0xff1e, 0xff1f, 0xff20, 0xff21, 0xff22, 0xff23, 0xff24,
+ 0xff25, 0xff26, 0xff27, 0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c,
+ 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31, 0xff32, 0xff33, 0xff34,
+ 0xff35, 0xff36, 0xff37, 0xff38, 0xff39, 0xff3a, 0xff3b, 0xff3c,
+ 0xff3d, 0xff3e, 0xff3f, 0xff40, 0xff41, 0xff42, 0xff43, 0xff44,
+ 0xff45, 0xff46, 0xff47, 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c,
+ 0xff4d, 0xff4e, 0xff4f, 0xff50, 0xff51, 0xff52, 0xff53, 0xff54,
+ 0xff55, 0xff56, 0xff57, 0xff58, 0xff59, 0xff5a, 0xff5b, 0xff5c,
+ 0xff5d, 0xffe3, 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046,
+ 0x3047, 0x3048, 0x3049, 0x304a, 0x304b, 0x304c, 0x304d, 0x304e,
+ 0x304f, 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056,
+ 0x3057, 0x3058, 0x3059, 0x305a, 0x305b, 0x305c, 0x305d, 0x305e,
+ 0x305f, 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066,
+ 0x3067, 0x3068, 0x3069, 0x306a, 0x306b, 0x306c, 0x306d, 0x306e,
+ 0x306f, 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076,
+ 0x3077, 0x3078, 0x3079, 0x307a, 0x307b, 0x307c, 0x307d, 0x307e,
+ 0x307f, 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086,
+ 0x3087, 0x3088, 0x3089, 0x308a, 0x308b, 0x308c, 0x308d, 0x308e,
+ 0x308f, 0x3090, 0x3091, 0x3092, 0x3093, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x30a1, 0x30a2, 0x30a3, 0x30a4, 0x30a5, 0x30a6, 0x30a7, 0x30a8,
+ 0x30a9, 0x30aa, 0x30ab, 0x30ac, 0x30ad, 0x30ae, 0x30af, 0x30b0,
+ 0x30b1, 0x30b2, 0x30b3, 0x30b4, 0x30b5, 0x30b6, 0x30b7, 0x30b8,
+ 0x30b9, 0x30ba, 0x30bb, 0x30bc, 0x30bd, 0x30be, 0x30bf, 0x30c0,
+ 0x30c1, 0x30c2, 0x30c3, 0x30c4, 0x30c5, 0x30c6, 0x30c7, 0x30c8,
+ 0x30c9, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, 0x30d0,
+ 0x30d1, 0x30d2, 0x30d3, 0x30d4, 0x30d5, 0x30d6, 0x30d7, 0x30d8,
+ 0x30d9, 0x30da, 0x30db, 0x30dc, 0x30dd, 0x30de, 0x30df, 0x30e0,
+ 0x30e1, 0x30e2, 0x30e3, 0x30e4, 0x30e5, 0x30e6, 0x30e7, 0x30e8,
+ 0x30e9, 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ee, 0x30ef, 0x30f0,
+ 0x30f1, 0x30f2, 0x30f3, 0x30f4, 0x30f5, 0x30f6, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0391, 0x0392,
+ 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a,
+ 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1, 0x03a3,
+ 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03b1, 0x03b2,
+ 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba,
+ 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c3,
+ 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0xe78d, 0xe78e,
+ 0xe78f, 0xe790, 0xe791, 0xe792, 0xe793, 0xfe35, 0xfe36, 0xfe39,
+ 0xfe3a, 0xfe3f, 0xfe40, 0xfe3d, 0xfe3e, 0xfe41, 0xfe42, 0xfe43,
+ 0xfe44, 0xe794, 0xe795, 0xfe3b, 0xfe3c, 0xfe37, 0xfe38, 0xfe31,
+ 0xe796, 0xfe33, 0xfe34, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0410, 0x0411, 0x0412, 0x0413,
+ 0x0414, 0x0415, 0x0401, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a,
+ 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, 0x0420, 0x0421, 0x0422,
+ 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a,
+ 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0430, 0x0431, 0x0432, 0x0433,
+ 0x0434, 0x0435, 0x0451, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a,
+ 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, 0x0440, 0x0441, 0x0442,
+ 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a,
+ 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0101, 0x00e1, 0x01ce, 0x00e0, 0x0113, 0x00e9,
+ 0x011b, 0x00e8, 0x012b, 0x00ed, 0x01d0, 0x00ec, 0x014d, 0x00f3,
+ 0x01d2, 0x00f2, 0x016b, 0x00fa, 0x01d4, 0x00f9, 0x01d6, 0x01d8,
+ 0x01da, 0x01dc, 0x00fc, 0x00ea, 0x0251, 0x1e3f, 0x0144, 0x0148,
+ 0x01f9, 0x0261, 0x0000, 0x0000, 0x0000, 0x0000, 0x3105, 0x3106,
+ 0x3107, 0x3108, 0x3109, 0x310a, 0x310b, 0x310c, 0x310d, 0x310e,
+ 0x310f, 0x3110, 0x3111, 0x3112, 0x3113, 0x3114, 0x3115, 0x3116,
+ 0x3117, 0x3118, 0x3119, 0x311a, 0x311b, 0x311c, 0x311d, 0x311e,
+ 0x311f, 0x3120, 0x3121, 0x3122, 0x3123, 0x3124, 0x3125, 0x3126,
+ 0x3127, 0x3128, 0x3129, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2500, 0x2501, 0x2502, 0x2503, 0x2504,
+ 0x2505, 0x2506, 0x2507, 0x2508, 0x2509, 0x250a, 0x250b, 0x250c,
+ 0x250d, 0x250e, 0x250f, 0x2510, 0x2511, 0x2512, 0x2513, 0x2514,
+ 0x2515, 0x2516, 0x2517, 0x2518, 0x2519, 0x251a, 0x251b, 0x251c,
+ 0x251d, 0x251e, 0x251f, 0x2520, 0x2521, 0x2522, 0x2523, 0x2524,
+ 0x2525, 0x2526, 0x2527, 0x2528, 0x2529, 0x252a, 0x252b, 0x252c,
+ 0x252d, 0x252e, 0x252f, 0x2530, 0x2531, 0x2532, 0x2533, 0x2534,
+ 0x2535, 0x2536, 0x2537, 0x2538, 0x2539, 0x253a, 0x253b, 0x253c,
+ 0x253d, 0x253e, 0x253f, 0x2540, 0x2541, 0x2542, 0x2543, 0x2544,
+ 0x2545, 0x2546, 0x2547, 0x2548, 0x2549, 0x254a, 0x254b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x554a, 0x963f, 0x57c3, 0x6328, 0x54ce, 0x5509,
+ 0x54c0, 0x7691, 0x764c, 0x853c, 0x77ee, 0x827e, 0x788d, 0x7231,
+ 0x9698, 0x978d, 0x6c28, 0x5b89, 0x4ffa, 0x6309, 0x6697, 0x5cb8,
+ 0x80fa, 0x6848, 0x80ae, 0x6602, 0x76ce, 0x51f9, 0x6556, 0x71ac,
+ 0x7ff1, 0x8884, 0x50b2, 0x5965, 0x61ca, 0x6fb3, 0x82ad, 0x634c,
+ 0x6252, 0x53ed, 0x5427, 0x7b06, 0x516b, 0x75a4, 0x5df4, 0x62d4,
+ 0x8dcb, 0x9776, 0x628a, 0x8019, 0x575d, 0x9738, 0x7f62, 0x7238,
+ 0x767d, 0x67cf, 0x767e, 0x6446, 0x4f70, 0x8d25, 0x62dc, 0x7a17,
+ 0x6591, 0x73ed, 0x642c, 0x6273, 0x822c, 0x9881, 0x677f, 0x7248,
+ 0x626e, 0x62cc, 0x4f34, 0x74e3, 0x534a, 0x529e, 0x7eca, 0x90a6,
+ 0x5e2e, 0x6886, 0x699c, 0x8180, 0x7ed1, 0x68d2, 0x78c5, 0x868c,
+ 0x9551, 0x508d, 0x8c24, 0x82de, 0x80de, 0x5305, 0x8912, 0x5265,
+ 0x8584, 0x96f9, 0x4fdd, 0x5821, 0x9971, 0x5b9d, 0x62b1, 0x62a5,
+ 0x66b4, 0x8c79, 0x9c8d, 0x7206, 0x676f, 0x7891, 0x60b2, 0x5351,
+ 0x5317, 0x8f88, 0x80cc, 0x8d1d, 0x94a1, 0x500d, 0x72c8, 0x5907,
+ 0x60eb, 0x7119, 0x88ab, 0x5954, 0x82ef, 0x672c, 0x7b28, 0x5d29,
+ 0x7ef7, 0x752d, 0x6cf5, 0x8e66, 0x8ff8, 0x903c, 0x9f3b, 0x6bd4,
+ 0x9119, 0x7b14, 0x5f7c, 0x78a7, 0x84d6, 0x853d, 0x6bd5, 0x6bd9,
+ 0x6bd6, 0x5e01, 0x5e87, 0x75f9, 0x95ed, 0x655d, 0x5f0a, 0x5fc5,
+ 0x8f9f, 0x58c1, 0x81c2, 0x907f, 0x965b, 0x97ad, 0x8fb9, 0x7f16,
+ 0x8d2c, 0x6241, 0x4fbf, 0x53d8, 0x535e, 0x8fa8, 0x8fa9, 0x8fab,
+ 0x904d, 0x6807, 0x5f6a, 0x8198, 0x8868, 0x9cd6, 0x618b, 0x522b,
+ 0x762a, 0x5f6c, 0x658c, 0x6fd2, 0x6ee8, 0x5bbe, 0x6448, 0x5175,
+ 0x51b0, 0x67c4, 0x4e19, 0x79c9, 0x997c, 0x70b3, 0x75c5, 0x5e76,
+ 0x73bb, 0x83e0, 0x64ad, 0x62e8, 0x94b5, 0x6ce2, 0x535a, 0x52c3,
+ 0x640f, 0x94c2, 0x7b94, 0x4f2f, 0x5e1b, 0x8236, 0x8116, 0x818a,
+ 0x6e24, 0x6cca, 0x9a73, 0x6355, 0x535c, 0x54fa, 0x8865, 0x57e0,
+ 0x4e0d, 0x5e03, 0x6b65, 0x7c3f, 0x90e8, 0x6016, 0x64e6, 0x731c,
+ 0x88c1, 0x6750, 0x624d, 0x8d22, 0x776c, 0x8e29, 0x91c7, 0x5f69,
+ 0x83dc, 0x8521, 0x9910, 0x53c2, 0x8695, 0x6b8b, 0x60ed, 0x60e8,
+ 0x707f, 0x82cd, 0x8231, 0x4ed3, 0x6ca7, 0x85cf, 0x64cd, 0x7cd9,
+ 0x69fd, 0x66f9, 0x8349, 0x5395, 0x7b56, 0x4fa7, 0x518c, 0x6d4b,
+ 0x5c42, 0x8e6d, 0x63d2, 0x53c9, 0x832c, 0x8336, 0x67e5, 0x78b4,
+ 0x643d, 0x5bdf, 0x5c94, 0x5dee, 0x8be7, 0x62c6, 0x67f4, 0x8c7a,
+ 0x6400, 0x63ba, 0x8749, 0x998b, 0x8c17, 0x7f20, 0x94f2, 0x4ea7,
+ 0x9610, 0x98a4, 0x660c, 0x7316, 0x573a, 0x5c1d, 0x5e38, 0x957f,
+ 0x507f, 0x80a0, 0x5382, 0x655e, 0x7545, 0x5531, 0x5021, 0x8d85,
+ 0x6284, 0x949e, 0x671d, 0x5632, 0x6f6e, 0x5de2, 0x5435, 0x7092,
+ 0x8f66, 0x626f, 0x64a4, 0x63a3, 0x5f7b, 0x6f88, 0x90f4, 0x81e3,
+ 0x8fb0, 0x5c18, 0x6668, 0x5ff1, 0x6c89, 0x9648, 0x8d81, 0x886c,
+ 0x6491, 0x79f0, 0x57ce, 0x6a59, 0x6210, 0x5448, 0x4e58, 0x7a0b,
+ 0x60e9, 0x6f84, 0x8bda, 0x627f, 0x901e, 0x9a8b, 0x79e4, 0x5403,
+ 0x75f4, 0x6301, 0x5319, 0x6c60, 0x8fdf, 0x5f1b, 0x9a70, 0x803b,
+ 0x9f7f, 0x4f88, 0x5c3a, 0x8d64, 0x7fc5, 0x65a5, 0x70bd, 0x5145,
+ 0x51b2, 0x866b, 0x5d07, 0x5ba0, 0x62bd, 0x916c, 0x7574, 0x8e0c,
+ 0x7a20, 0x6101, 0x7b79, 0x4ec7, 0x7ef8, 0x7785, 0x4e11, 0x81ed,
+ 0x521d, 0x51fa, 0x6a71, 0x53a8, 0x8e87, 0x9504, 0x96cf, 0x6ec1,
+ 0x9664, 0x695a, 0x7840, 0x50a8, 0x77d7, 0x6410, 0x89e6, 0x5904,
+ 0x63e3, 0x5ddd, 0x7a7f, 0x693d, 0x4f20, 0x8239, 0x5598, 0x4e32,
+ 0x75ae, 0x7a97, 0x5e62, 0x5e8a, 0x95ef, 0x521b, 0x5439, 0x708a,
+ 0x6376, 0x9524, 0x5782, 0x6625, 0x693f, 0x9187, 0x5507, 0x6df3,
+ 0x7eaf, 0x8822, 0x6233, 0x7ef0, 0x75b5, 0x8328, 0x78c1, 0x96cc,
+ 0x8f9e, 0x6148, 0x74f7, 0x8bcd, 0x6b64, 0x523a, 0x8d50, 0x6b21,
+ 0x806a, 0x8471, 0x56f1, 0x5306, 0x4ece, 0x4e1b, 0x51d1, 0x7c97,
+ 0x918b, 0x7c07, 0x4fc3, 0x8e7f, 0x7be1, 0x7a9c, 0x6467, 0x5d14,
+ 0x50ac, 0x8106, 0x7601, 0x7cb9, 0x6dec, 0x7fe0, 0x6751, 0x5b58,
+ 0x5bf8, 0x78cb, 0x64ae, 0x6413, 0x63aa, 0x632b, 0x9519, 0x642d,
+ 0x8fbe, 0x7b54, 0x7629, 0x6253, 0x5927, 0x5446, 0x6b79, 0x50a3,
+ 0x6234, 0x5e26, 0x6b86, 0x4ee3, 0x8d37, 0x888b, 0x5f85, 0x902e,
+ 0x6020, 0x803d, 0x62c5, 0x4e39, 0x5355, 0x90f8, 0x63b8, 0x80c6,
+ 0x65e6, 0x6c2e, 0x4f46, 0x60ee, 0x6de1, 0x8bde, 0x5f39, 0x86cb,
+ 0x5f53, 0x6321, 0x515a, 0x8361, 0x6863, 0x5200, 0x6363, 0x8e48,
+ 0x5012, 0x5c9b, 0x7977, 0x5bfc, 0x5230, 0x7a3b, 0x60bc, 0x9053,
+ 0x76d7, 0x5fb7, 0x5f97, 0x7684, 0x8e6c, 0x706f, 0x767b, 0x7b49,
+ 0x77aa, 0x51f3, 0x9093, 0x5824, 0x4f4e, 0x6ef4, 0x8fea, 0x654c,
+ 0x7b1b, 0x72c4, 0x6da4, 0x7fdf, 0x5ae1, 0x62b5, 0x5e95, 0x5730,
+ 0x8482, 0x7b2c, 0x5e1d, 0x5f1f, 0x9012, 0x7f14, 0x98a0, 0x6382,
+ 0x6ec7, 0x7898, 0x70b9, 0x5178, 0x975b, 0x57ab, 0x7535, 0x4f43,
+ 0x7538, 0x5e97, 0x60e6, 0x5960, 0x6dc0, 0x6bbf, 0x7889, 0x53fc,
+ 0x96d5, 0x51cb, 0x5201, 0x6389, 0x540a, 0x9493, 0x8c03, 0x8dcc,
+ 0x7239, 0x789f, 0x8776, 0x8fed, 0x8c0d, 0x53e0, 0x4e01, 0x76ef,
+ 0x53ee, 0x9489, 0x9876, 0x9f0e, 0x952d, 0x5b9a, 0x8ba2, 0x4e22,
+ 0x4e1c, 0x51ac, 0x8463, 0x61c2, 0x52a8, 0x680b, 0x4f97, 0x606b,
+ 0x51bb, 0x6d1e, 0x515c, 0x6296, 0x6597, 0x9661, 0x8c46, 0x9017,
+ 0x75d8, 0x90fd, 0x7763, 0x6bd2, 0x728a, 0x72ec, 0x8bfb, 0x5835,
+ 0x7779, 0x8d4c, 0x675c, 0x9540, 0x809a, 0x5ea6, 0x6e21, 0x5992,
+ 0x7aef, 0x77ed, 0x953b, 0x6bb5, 0x65ad, 0x7f0e, 0x5806, 0x5151,
+ 0x961f, 0x5bf9, 0x58a9, 0x5428, 0x8e72, 0x6566, 0x987f, 0x56e4,
+ 0x949d, 0x76fe, 0x9041, 0x6387, 0x54c6, 0x591a, 0x593a, 0x579b,
+ 0x8eb2, 0x6735, 0x8dfa, 0x8235, 0x5241, 0x60f0, 0x5815, 0x86fe,
+ 0x5ce8, 0x9e45, 0x4fc4, 0x989d, 0x8bb9, 0x5a25, 0x6076, 0x5384,
+ 0x627c, 0x904f, 0x9102, 0x997f, 0x6069, 0x800c, 0x513f, 0x8033,
+ 0x5c14, 0x9975, 0x6d31, 0x4e8c, 0x8d30, 0x53d1, 0x7f5a, 0x7b4f,
+ 0x4f10, 0x4e4f, 0x9600, 0x6cd5, 0x73d0, 0x85e9, 0x5e06, 0x756a,
+ 0x7ffb, 0x6a0a, 0x77fe, 0x9492, 0x7e41, 0x51e1, 0x70e6, 0x53cd,
+ 0x8fd4, 0x8303, 0x8d29, 0x72af, 0x996d, 0x6cdb, 0x574a, 0x82b3,
+ 0x65b9, 0x80aa, 0x623f, 0x9632, 0x59a8, 0x4eff, 0x8bbf, 0x7eba,
+ 0x653e, 0x83f2, 0x975e, 0x5561, 0x98de, 0x80a5, 0x532a, 0x8bfd,
+ 0x5420, 0x80ba, 0x5e9f, 0x6cb8, 0x8d39, 0x82ac, 0x915a, 0x5429,
+ 0x6c1b, 0x5206, 0x7eb7, 0x575f, 0x711a, 0x6c7e, 0x7c89, 0x594b,
+ 0x4efd, 0x5fff, 0x6124, 0x7caa, 0x4e30, 0x5c01, 0x67ab, 0x8702,
+ 0x5cf0, 0x950b, 0x98ce, 0x75af, 0x70fd, 0x9022, 0x51af, 0x7f1d,
+ 0x8bbd, 0x5949, 0x51e4, 0x4f5b, 0x5426, 0x592b, 0x6577, 0x80a4,
+ 0x5b75, 0x6276, 0x62c2, 0x8f90, 0x5e45, 0x6c1f, 0x7b26, 0x4f0f,
+ 0x4fd8, 0x670d, 0x6d6e, 0x6daa, 0x798f, 0x88b1, 0x5f17, 0x752b,
+ 0x629a, 0x8f85, 0x4fef, 0x91dc, 0x65a7, 0x812f, 0x8151, 0x5e9c,
+ 0x8150, 0x8d74, 0x526f, 0x8986, 0x8d4b, 0x590d, 0x5085, 0x4ed8,
+ 0x961c, 0x7236, 0x8179, 0x8d1f, 0x5bcc, 0x8ba3, 0x9644, 0x5987,
+ 0x7f1a, 0x5490, 0x5676, 0x560e, 0x8be5, 0x6539, 0x6982, 0x9499,
+ 0x76d6, 0x6e89, 0x5e72, 0x7518, 0x6746, 0x67d1, 0x7aff, 0x809d,
+ 0x8d76, 0x611f, 0x79c6, 0x6562, 0x8d63, 0x5188, 0x521a, 0x94a2,
+ 0x7f38, 0x809b, 0x7eb2, 0x5c97, 0x6e2f, 0x6760, 0x7bd9, 0x768b,
+ 0x9ad8, 0x818f, 0x7f94, 0x7cd5, 0x641e, 0x9550, 0x7a3f, 0x544a,
+ 0x54e5, 0x6b4c, 0x6401, 0x6208, 0x9e3d, 0x80f3, 0x7599, 0x5272,
+ 0x9769, 0x845b, 0x683c, 0x86e4, 0x9601, 0x9694, 0x94ec, 0x4e2a,
+ 0x5404, 0x7ed9, 0x6839, 0x8ddf, 0x8015, 0x66f4, 0x5e9a, 0x7fb9,
+ 0x57c2, 0x803f, 0x6897, 0x5de5, 0x653b, 0x529f, 0x606d, 0x9f9a,
+ 0x4f9b, 0x8eac, 0x516c, 0x5bab, 0x5f13, 0x5de9, 0x6c5e, 0x62f1,
+ 0x8d21, 0x5171, 0x94a9, 0x52fe, 0x6c9f, 0x82df, 0x72d7, 0x57a2,
+ 0x6784, 0x8d2d, 0x591f, 0x8f9c, 0x83c7, 0x5495, 0x7b8d, 0x4f30,
+ 0x6cbd, 0x5b64, 0x59d1, 0x9f13, 0x53e4, 0x86ca, 0x9aa8, 0x8c37,
+ 0x80a1, 0x6545, 0x987e, 0x56fa, 0x96c7, 0x522e, 0x74dc, 0x5250,
+ 0x5be1, 0x6302, 0x8902, 0x4e56, 0x62d0, 0x602a, 0x68fa, 0x5173,
+ 0x5b98, 0x51a0, 0x89c2, 0x7ba1, 0x9986, 0x7f50, 0x60ef, 0x704c,
+ 0x8d2f, 0x5149, 0x5e7f, 0x901b, 0x7470, 0x89c4, 0x572d, 0x7845,
+ 0x5f52, 0x9f9f, 0x95fa, 0x8f68, 0x9b3c, 0x8be1, 0x7678, 0x6842,
+ 0x67dc, 0x8dea, 0x8d35, 0x523d, 0x8f8a, 0x6eda, 0x68cd, 0x9505,
+ 0x90ed, 0x56fd, 0x679c, 0x88f9, 0x8fc7, 0x54c8, 0x9ab8, 0x5b69,
+ 0x6d77, 0x6c26, 0x4ea5, 0x5bb3, 0x9a87, 0x9163, 0x61a8, 0x90af,
+ 0x97e9, 0x542b, 0x6db5, 0x5bd2, 0x51fd, 0x558a, 0x7f55, 0x7ff0,
+ 0x64bc, 0x634d, 0x65f1, 0x61be, 0x608d, 0x710a, 0x6c57, 0x6c49,
+ 0x592f, 0x676d, 0x822a, 0x58d5, 0x568e, 0x8c6a, 0x6beb, 0x90dd,
+ 0x597d, 0x8017, 0x53f7, 0x6d69, 0x5475, 0x559d, 0x8377, 0x83cf,
+ 0x6838, 0x79be, 0x548c, 0x4f55, 0x5408, 0x76d2, 0x8c89, 0x9602,
+ 0x6cb3, 0x6db8, 0x8d6b, 0x8910, 0x9e64, 0x8d3a, 0x563f, 0x9ed1,
+ 0x75d5, 0x5f88, 0x72e0, 0x6068, 0x54fc, 0x4ea8, 0x6a2a, 0x8861,
+ 0x6052, 0x8f70, 0x54c4, 0x70d8, 0x8679, 0x9e3f, 0x6d2a, 0x5b8f,
+ 0x5f18, 0x7ea2, 0x5589, 0x4faf, 0x7334, 0x543c, 0x539a, 0x5019,
+ 0x540e, 0x547c, 0x4e4e, 0x5ffd, 0x745a, 0x58f6, 0x846b, 0x80e1,
+ 0x8774, 0x72d0, 0x7cca, 0x6e56, 0x5f27, 0x864e, 0x552c, 0x62a4,
+ 0x4e92, 0x6caa, 0x6237, 0x82b1, 0x54d7, 0x534e, 0x733e, 0x6ed1,
+ 0x753b, 0x5212, 0x5316, 0x8bdd, 0x69d0, 0x5f8a, 0x6000, 0x6dee,
+ 0x574f, 0x6b22, 0x73af, 0x6853, 0x8fd8, 0x7f13, 0x6362, 0x60a3,
+ 0x5524, 0x75ea, 0x8c62, 0x7115, 0x6da3, 0x5ba6, 0x5e7b, 0x8352,
+ 0x614c, 0x9ec4, 0x78fa, 0x8757, 0x7c27, 0x7687, 0x51f0, 0x60f6,
+ 0x714c, 0x6643, 0x5e4c, 0x604d, 0x8c0e, 0x7070, 0x6325, 0x8f89,
+ 0x5fbd, 0x6062, 0x86d4, 0x56de, 0x6bc1, 0x6094, 0x6167, 0x5349,
+ 0x60e0, 0x6666, 0x8d3f, 0x79fd, 0x4f1a, 0x70e9, 0x6c47, 0x8bb3,
+ 0x8bf2, 0x7ed8, 0x8364, 0x660f, 0x5a5a, 0x9b42, 0x6d51, 0x6df7,
+ 0x8c41, 0x6d3b, 0x4f19, 0x706b, 0x83b7, 0x6216, 0x60d1, 0x970d,
+ 0x8d27, 0x7978, 0x51fb, 0x573e, 0x57fa, 0x673a, 0x7578, 0x7a3d,
+ 0x79ef, 0x7b95, 0x808c, 0x9965, 0x8ff9, 0x6fc0, 0x8ba5, 0x9e21,
+ 0x59ec, 0x7ee9, 0x7f09, 0x5409, 0x6781, 0x68d8, 0x8f91, 0x7c4d,
+ 0x96c6, 0x53ca, 0x6025, 0x75be, 0x6c72, 0x5373, 0x5ac9, 0x7ea7,
+ 0x6324, 0x51e0, 0x810a, 0x5df1, 0x84df, 0x6280, 0x5180, 0x5b63,
+ 0x4f0e, 0x796d, 0x5242, 0x60b8, 0x6d4e, 0x5bc4, 0x5bc2, 0x8ba1,
+ 0x8bb0, 0x65e2, 0x5fcc, 0x9645, 0x5993, 0x7ee7, 0x7eaa, 0x5609,
+ 0x67b7, 0x5939, 0x4f73, 0x5bb6, 0x52a0, 0x835a, 0x988a, 0x8d3e,
+ 0x7532, 0x94be, 0x5047, 0x7a3c, 0x4ef7, 0x67b6, 0x9a7e, 0x5ac1,
+ 0x6b7c, 0x76d1, 0x575a, 0x5c16, 0x7b3a, 0x95f4, 0x714e, 0x517c,
+ 0x80a9, 0x8270, 0x5978, 0x7f04, 0x8327, 0x68c0, 0x67ec, 0x78b1,
+ 0x7877, 0x62e3, 0x6361, 0x7b80, 0x4fed, 0x526a, 0x51cf, 0x8350,
+ 0x69db, 0x9274, 0x8df5, 0x8d31, 0x89c1, 0x952e, 0x7bad, 0x4ef6,
+ 0x5065, 0x8230, 0x5251, 0x996f, 0x6e10, 0x6e85, 0x6da7, 0x5efa,
+ 0x50f5, 0x59dc, 0x5c06, 0x6d46, 0x6c5f, 0x7586, 0x848b, 0x6868,
+ 0x5956, 0x8bb2, 0x5320, 0x9171, 0x964d, 0x8549, 0x6912, 0x7901,
+ 0x7126, 0x80f6, 0x4ea4, 0x90ca, 0x6d47, 0x9a84, 0x5a07, 0x56bc,
+ 0x6405, 0x94f0, 0x77eb, 0x4fa5, 0x811a, 0x72e1, 0x89d2, 0x997a,
+ 0x7f34, 0x7ede, 0x527f, 0x6559, 0x9175, 0x8f7f, 0x8f83, 0x53eb,
+ 0x7a96, 0x63ed, 0x63a5, 0x7686, 0x79f8, 0x8857, 0x9636, 0x622a,
+ 0x52ab, 0x8282, 0x6854, 0x6770, 0x6377, 0x776b, 0x7aed, 0x6d01,
+ 0x7ed3, 0x89e3, 0x59d0, 0x6212, 0x85c9, 0x82a5, 0x754c, 0x501f,
+ 0x4ecb, 0x75a5, 0x8beb, 0x5c4a, 0x5dfe, 0x7b4b, 0x65a4, 0x91d1,
+ 0x4eca, 0x6d25, 0x895f, 0x7d27, 0x9526, 0x4ec5, 0x8c28, 0x8fdb,
+ 0x9773, 0x664b, 0x7981, 0x8fd1, 0x70ec, 0x6d78, 0x5c3d, 0x52b2,
+ 0x8346, 0x5162, 0x830e, 0x775b, 0x6676, 0x9cb8, 0x4eac, 0x60ca,
+ 0x7cbe, 0x7cb3, 0x7ecf, 0x4e95, 0x8b66, 0x666f, 0x9888, 0x9759,
+ 0x5883, 0x656c, 0x955c, 0x5f84, 0x75c9, 0x9756, 0x7adf, 0x7ade,
+ 0x51c0, 0x70af, 0x7a98, 0x63ea, 0x7a76, 0x7ea0, 0x7396, 0x97ed,
+ 0x4e45, 0x7078, 0x4e5d, 0x9152, 0x53a9, 0x6551, 0x65e7, 0x81fc,
+ 0x8205, 0x548e, 0x5c31, 0x759a, 0x97a0, 0x62d8, 0x72d9, 0x75bd,
+ 0x5c45, 0x9a79, 0x83ca, 0x5c40, 0x5480, 0x77e9, 0x4e3e, 0x6cae,
+ 0x805a, 0x62d2, 0x636e, 0x5de8, 0x5177, 0x8ddd, 0x8e1e, 0x952f,
+ 0x4ff1, 0x53e5, 0x60e7, 0x70ac, 0x5267, 0x6350, 0x9e43, 0x5a1f,
+ 0x5026, 0x7737, 0x5377, 0x7ee2, 0x6485, 0x652b, 0x6289, 0x6398,
+ 0x5014, 0x7235, 0x89c9, 0x51b3, 0x8bc0, 0x7edd, 0x5747, 0x83cc,
+ 0x94a7, 0x519b, 0x541b, 0x5cfb, 0x4fca, 0x7ae3, 0x6d5a, 0x90e1,
+ 0x9a8f, 0x5580, 0x5496, 0x5361, 0x54af, 0x5f00, 0x63e9, 0x6977,
+ 0x51ef, 0x6168, 0x520a, 0x582a, 0x52d8, 0x574e, 0x780d, 0x770b,
+ 0x5eb7, 0x6177, 0x7ce0, 0x625b, 0x6297, 0x4ea2, 0x7095, 0x8003,
+ 0x62f7, 0x70e4, 0x9760, 0x5777, 0x82db, 0x67ef, 0x68f5, 0x78d5,
+ 0x9897, 0x79d1, 0x58f3, 0x54b3, 0x53ef, 0x6e34, 0x514b, 0x523b,
+ 0x5ba2, 0x8bfe, 0x80af, 0x5543, 0x57a6, 0x6073, 0x5751, 0x542d,
+ 0x7a7a, 0x6050, 0x5b54, 0x63a7, 0x62a0, 0x53e3, 0x6263, 0x5bc7,
+ 0x67af, 0x54ed, 0x7a9f, 0x82e6, 0x9177, 0x5e93, 0x88e4, 0x5938,
+ 0x57ae, 0x630e, 0x8de8, 0x80ef, 0x5757, 0x7b77, 0x4fa9, 0x5feb,
+ 0x5bbd, 0x6b3e, 0x5321, 0x7b50, 0x72c2, 0x6846, 0x77ff, 0x7736,
+ 0x65f7, 0x51b5, 0x4e8f, 0x76d4, 0x5cbf, 0x7aa5, 0x8475, 0x594e,
+ 0x9b41, 0x5080, 0x9988, 0x6127, 0x6e83, 0x5764, 0x6606, 0x6346,
+ 0x56f0, 0x62ec, 0x6269, 0x5ed3, 0x9614, 0x5783, 0x62c9, 0x5587,
+ 0x8721, 0x814a, 0x8fa3, 0x5566, 0x83b1, 0x6765, 0x8d56, 0x84dd,
+ 0x5a6a, 0x680f, 0x62e6, 0x7bee, 0x9611, 0x5170, 0x6f9c, 0x8c30,
+ 0x63fd, 0x89c8, 0x61d2, 0x7f06, 0x70c2, 0x6ee5, 0x7405, 0x6994,
+ 0x72fc, 0x5eca, 0x90ce, 0x6717, 0x6d6a, 0x635e, 0x52b3, 0x7262,
+ 0x8001, 0x4f6c, 0x59e5, 0x916a, 0x70d9, 0x6d9d, 0x52d2, 0x4e50,
+ 0x96f7, 0x956d, 0x857e, 0x78ca, 0x7d2f, 0x5121, 0x5792, 0x64c2,
+ 0x808b, 0x7c7b, 0x6cea, 0x68f1, 0x695e, 0x51b7, 0x5398, 0x68a8,
+ 0x7281, 0x9ece, 0x7bf1, 0x72f8, 0x79bb, 0x6f13, 0x7406, 0x674e,
+ 0x91cc, 0x9ca4, 0x793c, 0x8389, 0x8354, 0x540f, 0x6817, 0x4e3d,
+ 0x5389, 0x52b1, 0x783e, 0x5386, 0x5229, 0x5088, 0x4f8b, 0x4fd0,
+ 0x75e2, 0x7acb, 0x7c92, 0x6ca5, 0x96b6, 0x529b, 0x7483, 0x54e9,
+ 0x4fe9, 0x8054, 0x83b2, 0x8fde, 0x9570, 0x5ec9, 0x601c, 0x6d9f,
+ 0x5e18, 0x655b, 0x8138, 0x94fe, 0x604b, 0x70bc, 0x7ec3, 0x7cae,
+ 0x51c9, 0x6881, 0x7cb1, 0x826f, 0x4e24, 0x8f86, 0x91cf, 0x667e,
+ 0x4eae, 0x8c05, 0x64a9, 0x804a, 0x50da, 0x7597, 0x71ce, 0x5be5,
+ 0x8fbd, 0x6f66, 0x4e86, 0x6482, 0x9563, 0x5ed6, 0x6599, 0x5217,
+ 0x88c2, 0x70c8, 0x52a3, 0x730e, 0x7433, 0x6797, 0x78f7, 0x9716,
+ 0x4e34, 0x90bb, 0x9cde, 0x6dcb, 0x51db, 0x8d41, 0x541d, 0x62ce,
+ 0x73b2, 0x83f1, 0x96f6, 0x9f84, 0x94c3, 0x4f36, 0x7f9a, 0x51cc,
+ 0x7075, 0x9675, 0x5cad, 0x9886, 0x53e6, 0x4ee4, 0x6e9c, 0x7409,
+ 0x69b4, 0x786b, 0x998f, 0x7559, 0x5218, 0x7624, 0x6d41, 0x67f3,
+ 0x516d, 0x9f99, 0x804b, 0x5499, 0x7b3c, 0x7abf, 0x9686, 0x5784,
+ 0x62e2, 0x9647, 0x697c, 0x5a04, 0x6402, 0x7bd3, 0x6f0f, 0x964b,
+ 0x82a6, 0x5362, 0x9885, 0x5e90, 0x7089, 0x63b3, 0x5364, 0x864f,
+ 0x9c81, 0x9e93, 0x788c, 0x9732, 0x8def, 0x8d42, 0x9e7f, 0x6f5e,
+ 0x7984, 0x5f55, 0x9646, 0x622e, 0x9a74, 0x5415, 0x94dd, 0x4fa3,
+ 0x65c5, 0x5c65, 0x5c61, 0x7f15, 0x8651, 0x6c2f, 0x5f8b, 0x7387,
+ 0x6ee4, 0x7eff, 0x5ce6, 0x631b, 0x5b6a, 0x6ee6, 0x5375, 0x4e71,
+ 0x63a0, 0x7565, 0x62a1, 0x8f6e, 0x4f26, 0x4ed1, 0x6ca6, 0x7eb6,
+ 0x8bba, 0x841d, 0x87ba, 0x7f57, 0x903b, 0x9523, 0x7ba9, 0x9aa1,
+ 0x88f8, 0x843d, 0x6d1b, 0x9a86, 0x7edc, 0x5988, 0x9ebb, 0x739b,
+ 0x7801, 0x8682, 0x9a6c, 0x9a82, 0x561b, 0x5417, 0x57cb, 0x4e70,
+ 0x9ea6, 0x5356, 0x8fc8, 0x8109, 0x7792, 0x9992, 0x86ee, 0x6ee1,
+ 0x8513, 0x66fc, 0x6162, 0x6f2b, 0x8c29, 0x8292, 0x832b, 0x76f2,
+ 0x6c13, 0x5fd9, 0x83bd, 0x732b, 0x8305, 0x951a, 0x6bdb, 0x77db,
+ 0x94c6, 0x536f, 0x8302, 0x5192, 0x5e3d, 0x8c8c, 0x8d38, 0x4e48,
+ 0x73ab, 0x679a, 0x6885, 0x9176, 0x9709, 0x7164, 0x6ca1, 0x7709,
+ 0x5a92, 0x9541, 0x6bcf, 0x7f8e, 0x6627, 0x5bd0, 0x59b9, 0x5a9a,
+ 0x95e8, 0x95f7, 0x4eec, 0x840c, 0x8499, 0x6aac, 0x76df, 0x9530,
+ 0x731b, 0x68a6, 0x5b5f, 0x772f, 0x919a, 0x9761, 0x7cdc, 0x8ff7,
+ 0x8c1c, 0x5f25, 0x7c73, 0x79d8, 0x89c5, 0x6ccc, 0x871c, 0x5bc6,
+ 0x5e42, 0x68c9, 0x7720, 0x7ef5, 0x5195, 0x514d, 0x52c9, 0x5a29,
+ 0x7f05, 0x9762, 0x82d7, 0x63cf, 0x7784, 0x85d0, 0x79d2, 0x6e3a,
+ 0x5e99, 0x5999, 0x8511, 0x706d, 0x6c11, 0x62bf, 0x76bf, 0x654f,
+ 0x60af, 0x95fd, 0x660e, 0x879f, 0x9e23, 0x94ed, 0x540d, 0x547d,
+ 0x8c2c, 0x6478, 0x6479, 0x8611, 0x6a21, 0x819c, 0x78e8, 0x6469,
+ 0x9b54, 0x62b9, 0x672b, 0x83ab, 0x58a8, 0x9ed8, 0x6cab, 0x6f20,
+ 0x5bde, 0x964c, 0x8c0b, 0x725f, 0x67d0, 0x62c7, 0x7261, 0x4ea9,
+ 0x59c6, 0x6bcd, 0x5893, 0x66ae, 0x5e55, 0x52df, 0x6155, 0x6728,
+ 0x76ee, 0x7766, 0x7267, 0x7a46, 0x62ff, 0x54ea, 0x5450, 0x94a0,
+ 0x90a3, 0x5a1c, 0x7eb3, 0x6c16, 0x4e43, 0x5976, 0x8010, 0x5948,
+ 0x5357, 0x7537, 0x96be, 0x56ca, 0x6320, 0x8111, 0x607c, 0x95f9,
+ 0x6dd6, 0x5462, 0x9981, 0x5185, 0x5ae9, 0x80fd, 0x59ae, 0x9713,
+ 0x502a, 0x6ce5, 0x5c3c, 0x62df, 0x4f60, 0x533f, 0x817b, 0x9006,
+ 0x6eba, 0x852b, 0x62c8, 0x5e74, 0x78be, 0x64b5, 0x637b, 0x5ff5,
+ 0x5a18, 0x917f, 0x9e1f, 0x5c3f, 0x634f, 0x8042, 0x5b7d, 0x556e,
+ 0x954a, 0x954d, 0x6d85, 0x60a8, 0x67e0, 0x72de, 0x51dd, 0x5b81,
+ 0x62e7, 0x6cde, 0x725b, 0x626d, 0x94ae, 0x7ebd, 0x8113, 0x6d53,
+ 0x519c, 0x5f04, 0x5974, 0x52aa, 0x6012, 0x5973, 0x6696, 0x8650,
+ 0x759f, 0x632a, 0x61e6, 0x7cef, 0x8bfa, 0x54e6, 0x6b27, 0x9e25,
+ 0x6bb4, 0x85d5, 0x5455, 0x5076, 0x6ca4, 0x556a, 0x8db4, 0x722c,
+ 0x5e15, 0x6015, 0x7436, 0x62cd, 0x6392, 0x724c, 0x5f98, 0x6e43,
+ 0x6d3e, 0x6500, 0x6f58, 0x76d8, 0x78d0, 0x76fc, 0x7554, 0x5224,
+ 0x53db, 0x4e53, 0x5e9e, 0x65c1, 0x802a, 0x80d6, 0x629b, 0x5486,
+ 0x5228, 0x70ae, 0x888d, 0x8dd1, 0x6ce1, 0x5478, 0x80da, 0x57f9,
+ 0x88f4, 0x8d54, 0x966a, 0x914d, 0x4f69, 0x6c9b, 0x55b7, 0x76c6,
+ 0x7830, 0x62a8, 0x70f9, 0x6f8e, 0x5f6d, 0x84ec, 0x68da, 0x787c,
+ 0x7bf7, 0x81a8, 0x670b, 0x9e4f, 0x6367, 0x78b0, 0x576f, 0x7812,
+ 0x9739, 0x6279, 0x62ab, 0x5288, 0x7435, 0x6bd7, 0x5564, 0x813e,
+ 0x75b2, 0x76ae, 0x5339, 0x75de, 0x50fb, 0x5c41, 0x8b6c, 0x7bc7,
+ 0x504f, 0x7247, 0x9a97, 0x98d8, 0x6f02, 0x74e2, 0x7968, 0x6487,
+ 0x77a5, 0x62fc, 0x9891, 0x8d2b, 0x54c1, 0x8058, 0x4e52, 0x576a,
+ 0x82f9, 0x840d, 0x5e73, 0x51ed, 0x74f6, 0x8bc4, 0x5c4f, 0x5761,
+ 0x6cfc, 0x9887, 0x5a46, 0x7834, 0x9b44, 0x8feb, 0x7c95, 0x5256,
+ 0x6251, 0x94fa, 0x4ec6, 0x8386, 0x8461, 0x83e9, 0x84b2, 0x57d4,
+ 0x6734, 0x5703, 0x666e, 0x6d66, 0x8c31, 0x66dd, 0x7011, 0x671f,
+ 0x6b3a, 0x6816, 0x621a, 0x59bb, 0x4e03, 0x51c4, 0x6f06, 0x67d2,
+ 0x6c8f, 0x5176, 0x68cb, 0x5947, 0x6b67, 0x7566, 0x5d0e, 0x8110,
+ 0x9f50, 0x65d7, 0x7948, 0x7941, 0x9a91, 0x8d77, 0x5c82, 0x4e5e,
+ 0x4f01, 0x542f, 0x5951, 0x780c, 0x5668, 0x6c14, 0x8fc4, 0x5f03,
+ 0x6c7d, 0x6ce3, 0x8bab, 0x6390, 0x6070, 0x6d3d, 0x7275, 0x6266,
+ 0x948e, 0x94c5, 0x5343, 0x8fc1, 0x7b7e, 0x4edf, 0x8c26, 0x4e7e,
+ 0x9ed4, 0x94b1, 0x94b3, 0x524d, 0x6f5c, 0x9063, 0x6d45, 0x8c34,
+ 0x5811, 0x5d4c, 0x6b20, 0x6b49, 0x67aa, 0x545b, 0x8154, 0x7f8c,
+ 0x5899, 0x8537, 0x5f3a, 0x62a2, 0x6a47, 0x9539, 0x6572, 0x6084,
+ 0x6865, 0x77a7, 0x4e54, 0x4fa8, 0x5de7, 0x9798, 0x64ac, 0x7fd8,
+ 0x5ced, 0x4fcf, 0x7a8d, 0x5207, 0x8304, 0x4e14, 0x602f, 0x7a83,
+ 0x94a6, 0x4fb5, 0x4eb2, 0x79e6, 0x7434, 0x52e4, 0x82b9, 0x64d2,
+ 0x79bd, 0x5bdd, 0x6c81, 0x9752, 0x8f7b, 0x6c22, 0x503e, 0x537f,
+ 0x6e05, 0x64ce, 0x6674, 0x6c30, 0x60c5, 0x9877, 0x8bf7, 0x5e86,
+ 0x743c, 0x7a77, 0x79cb, 0x4e18, 0x90b1, 0x7403, 0x6c42, 0x56da,
+ 0x914b, 0x6cc5, 0x8d8b, 0x533a, 0x86c6, 0x66f2, 0x8eaf, 0x5c48,
+ 0x9a71, 0x6e20, 0x53d6, 0x5a36, 0x9f8b, 0x8da3, 0x53bb, 0x5708,
+ 0x98a7, 0x6743, 0x919b, 0x6cc9, 0x5168, 0x75ca, 0x62f3, 0x72ac,
+ 0x5238, 0x529d, 0x7f3a, 0x7094, 0x7638, 0x5374, 0x9e4a, 0x69b7,
+ 0x786e, 0x96c0, 0x88d9, 0x7fa4, 0x7136, 0x71c3, 0x5189, 0x67d3,
+ 0x74e4, 0x58e4, 0x6518, 0x56b7, 0x8ba9, 0x9976, 0x6270, 0x7ed5,
+ 0x60f9, 0x70ed, 0x58ec, 0x4ec1, 0x4eba, 0x5fcd, 0x97e7, 0x4efb,
+ 0x8ba4, 0x5203, 0x598a, 0x7eab, 0x6254, 0x4ecd, 0x65e5, 0x620e,
+ 0x8338, 0x84c9, 0x8363, 0x878d, 0x7194, 0x6eb6, 0x5bb9, 0x7ed2,
+ 0x5197, 0x63c9, 0x67d4, 0x8089, 0x8339, 0x8815, 0x5112, 0x5b7a,
+ 0x5982, 0x8fb1, 0x4e73, 0x6c5d, 0x5165, 0x8925, 0x8f6f, 0x962e,
+ 0x854a, 0x745e, 0x9510, 0x95f0, 0x6da6, 0x82e5, 0x5f31, 0x6492,
+ 0x6d12, 0x8428, 0x816e, 0x9cc3, 0x585e, 0x8d5b, 0x4e09, 0x53c1,
+ 0x4f1e, 0x6563, 0x6851, 0x55d3, 0x4e27, 0x6414, 0x9a9a, 0x626b,
+ 0x5ac2, 0x745f, 0x8272, 0x6da9, 0x68ee, 0x50e7, 0x838e, 0x7802,
+ 0x6740, 0x5239, 0x6c99, 0x7eb1, 0x50bb, 0x5565, 0x715e, 0x7b5b,
+ 0x6652, 0x73ca, 0x82eb, 0x6749, 0x5c71, 0x5220, 0x717d, 0x886b,
+ 0x95ea, 0x9655, 0x64c5, 0x8d61, 0x81b3, 0x5584, 0x6c55, 0x6247,
+ 0x7f2e, 0x5892, 0x4f24, 0x5546, 0x8d4f, 0x664c, 0x4e0a, 0x5c1a,
+ 0x88f3, 0x68a2, 0x634e, 0x7a0d, 0x70e7, 0x828d, 0x52fa, 0x97f6,
+ 0x5c11, 0x54e8, 0x90b5, 0x7ecd, 0x5962, 0x8d4a, 0x86c7, 0x820c,
+ 0x820d, 0x8d66, 0x6444, 0x5c04, 0x6151, 0x6d89, 0x793e, 0x8bbe,
+ 0x7837, 0x7533, 0x547b, 0x4f38, 0x8eab, 0x6df1, 0x5a20, 0x7ec5,
+ 0x795e, 0x6c88, 0x5ba1, 0x5a76, 0x751a, 0x80be, 0x614e, 0x6e17,
+ 0x58f0, 0x751f, 0x7525, 0x7272, 0x5347, 0x7ef3, 0x7701, 0x76db,
+ 0x5269, 0x80dc, 0x5723, 0x5e08, 0x5931, 0x72ee, 0x65bd, 0x6e7f,
+ 0x8bd7, 0x5c38, 0x8671, 0x5341, 0x77f3, 0x62fe, 0x65f6, 0x4ec0,
+ 0x98df, 0x8680, 0x5b9e, 0x8bc6, 0x53f2, 0x77e2, 0x4f7f, 0x5c4e,
+ 0x9a76, 0x59cb, 0x5f0f, 0x793a, 0x58eb, 0x4e16, 0x67ff, 0x4e8b,
+ 0x62ed, 0x8a93, 0x901d, 0x52bf, 0x662f, 0x55dc, 0x566c, 0x9002,
+ 0x4ed5, 0x4f8d, 0x91ca, 0x9970, 0x6c0f, 0x5e02, 0x6043, 0x5ba4,
+ 0x89c6, 0x8bd5, 0x6536, 0x624b, 0x9996, 0x5b88, 0x5bff, 0x6388,
+ 0x552e, 0x53d7, 0x7626, 0x517d, 0x852c, 0x67a2, 0x68b3, 0x6b8a,
+ 0x6292, 0x8f93, 0x53d4, 0x8212, 0x6dd1, 0x758f, 0x4e66, 0x8d4e,
+ 0x5b70, 0x719f, 0x85af, 0x6691, 0x66d9, 0x7f72, 0x8700, 0x9ecd,
+ 0x9f20, 0x5c5e, 0x672f, 0x8ff0, 0x6811, 0x675f, 0x620d, 0x7ad6,
+ 0x5885, 0x5eb6, 0x6570, 0x6f31, 0x6055, 0x5237, 0x800d, 0x6454,
+ 0x8870, 0x7529, 0x5e05, 0x6813, 0x62f4, 0x971c, 0x53cc, 0x723d,
+ 0x8c01, 0x6c34, 0x7761, 0x7a0e, 0x542e, 0x77ac, 0x987a, 0x821c,
+ 0x8bf4, 0x7855, 0x6714, 0x70c1, 0x65af, 0x6495, 0x5636, 0x601d,
+ 0x79c1, 0x53f8, 0x4e1d, 0x6b7b, 0x8086, 0x5bfa, 0x55e3, 0x56db,
+ 0x4f3a, 0x4f3c, 0x9972, 0x5df3, 0x677e, 0x8038, 0x6002, 0x9882,
+ 0x9001, 0x5b8b, 0x8bbc, 0x8bf5, 0x641c, 0x8258, 0x64de, 0x55fd,
+ 0x82cf, 0x9165, 0x4fd7, 0x7d20, 0x901f, 0x7c9f, 0x50f3, 0x5851,
+ 0x6eaf, 0x5bbf, 0x8bc9, 0x8083, 0x9178, 0x849c, 0x7b97, 0x867d,
+ 0x968b, 0x968f, 0x7ee5, 0x9ad3, 0x788e, 0x5c81, 0x7a57, 0x9042,
+ 0x96a7, 0x795f, 0x5b59, 0x635f, 0x7b0b, 0x84d1, 0x68ad, 0x5506,
+ 0x7f29, 0x7410, 0x7d22, 0x9501, 0x6240, 0x584c, 0x4ed6, 0x5b83,
+ 0x5979, 0x5854, 0x736d, 0x631e, 0x8e4b, 0x8e0f, 0x80ce, 0x82d4,
+ 0x62ac, 0x53f0, 0x6cf0, 0x915e, 0x592a, 0x6001, 0x6c70, 0x574d,
+ 0x644a, 0x8d2a, 0x762b, 0x6ee9, 0x575b, 0x6a80, 0x75f0, 0x6f6d,
+ 0x8c2d, 0x8c08, 0x5766, 0x6bef, 0x8892, 0x78b3, 0x63a2, 0x53f9,
+ 0x70ad, 0x6c64, 0x5858, 0x642a, 0x5802, 0x68e0, 0x819b, 0x5510,
+ 0x7cd6, 0x5018, 0x8eba, 0x6dcc, 0x8d9f, 0x70eb, 0x638f, 0x6d9b,
+ 0x6ed4, 0x7ee6, 0x8404, 0x6843, 0x9003, 0x6dd8, 0x9676, 0x8ba8,
+ 0x5957, 0x7279, 0x85e4, 0x817e, 0x75bc, 0x8a8a, 0x68af, 0x5254,
+ 0x8e22, 0x9511, 0x63d0, 0x9898, 0x8e44, 0x557c, 0x4f53, 0x66ff,
+ 0x568f, 0x60d5, 0x6d95, 0x5243, 0x5c49, 0x5929, 0x6dfb, 0x586b,
+ 0x7530, 0x751c, 0x606c, 0x8214, 0x8146, 0x6311, 0x6761, 0x8fe2,
+ 0x773a, 0x8df3, 0x8d34, 0x94c1, 0x5e16, 0x5385, 0x542c, 0x70c3,
+ 0x6c40, 0x5ef7, 0x505c, 0x4ead, 0x5ead, 0x633a, 0x8247, 0x901a,
+ 0x6850, 0x916e, 0x77b3, 0x540c, 0x94dc, 0x5f64, 0x7ae5, 0x6876,
+ 0x6345, 0x7b52, 0x7edf, 0x75db, 0x5077, 0x6295, 0x5934, 0x900f,
+ 0x51f8, 0x79c3, 0x7a81, 0x56fe, 0x5f92, 0x9014, 0x6d82, 0x5c60,
+ 0x571f, 0x5410, 0x5154, 0x6e4d, 0x56e2, 0x63a8, 0x9893, 0x817f,
+ 0x8715, 0x892a, 0x9000, 0x541e, 0x5c6f, 0x81c0, 0x62d6, 0x6258,
+ 0x8131, 0x9e35, 0x9640, 0x9a6e, 0x9a7c, 0x692d, 0x59a5, 0x62d3,
+ 0x553e, 0x6316, 0x54c7, 0x86d9, 0x6d3c, 0x5a03, 0x74e6, 0x889c,
+ 0x6b6a, 0x5916, 0x8c4c, 0x5f2f, 0x6e7e, 0x73a9, 0x987d, 0x4e38,
+ 0x70f7, 0x5b8c, 0x7897, 0x633d, 0x665a, 0x7696, 0x60cb, 0x5b9b,
+ 0x5a49, 0x4e07, 0x8155, 0x6c6a, 0x738b, 0x4ea1, 0x6789, 0x7f51,
+ 0x5f80, 0x65fa, 0x671b, 0x5fd8, 0x5984, 0x5a01, 0x5dcd, 0x5fae,
+ 0x5371, 0x97e6, 0x8fdd, 0x6845, 0x56f4, 0x552f, 0x60df, 0x4e3a,
+ 0x6f4d, 0x7ef4, 0x82c7, 0x840e, 0x59d4, 0x4f1f, 0x4f2a, 0x5c3e,
+ 0x7eac, 0x672a, 0x851a, 0x5473, 0x754f, 0x80c3, 0x5582, 0x9b4f,
+ 0x4f4d, 0x6e2d, 0x8c13, 0x5c09, 0x6170, 0x536b, 0x761f, 0x6e29,
+ 0x868a, 0x6587, 0x95fb, 0x7eb9, 0x543b, 0x7a33, 0x7d0a, 0x95ee,
+ 0x55e1, 0x7fc1, 0x74ee, 0x631d, 0x8717, 0x6da1, 0x7a9d, 0x6211,
+ 0x65a1, 0x5367, 0x63e1, 0x6c83, 0x5deb, 0x545c, 0x94a8, 0x4e4c,
+ 0x6c61, 0x8bec, 0x5c4b, 0x65e0, 0x829c, 0x68a7, 0x543e, 0x5434,
+ 0x6bcb, 0x6b66, 0x4e94, 0x6342, 0x5348, 0x821e, 0x4f0d, 0x4fae,
+ 0x575e, 0x620a, 0x96fe, 0x6664, 0x7269, 0x52ff, 0x52a1, 0x609f,
+ 0x8bef, 0x6614, 0x7199, 0x6790, 0x897f, 0x7852, 0x77fd, 0x6670,
+ 0x563b, 0x5438, 0x9521, 0x727a, 0x7a00, 0x606f, 0x5e0c, 0x6089,
+ 0x819d, 0x5915, 0x60dc, 0x7184, 0x70ef, 0x6eaa, 0x6c50, 0x7280,
+ 0x6a84, 0x88ad, 0x5e2d, 0x4e60, 0x5ab3, 0x559c, 0x94e3, 0x6d17,
+ 0x7cfb, 0x9699, 0x620f, 0x7ec6, 0x778e, 0x867e, 0x5323, 0x971e,
+ 0x8f96, 0x6687, 0x5ce1, 0x4fa0, 0x72ed, 0x4e0b, 0x53a6, 0x590f,
+ 0x5413, 0x6380, 0x9528, 0x5148, 0x4ed9, 0x9c9c, 0x7ea4, 0x54b8,
+ 0x8d24, 0x8854, 0x8237, 0x95f2, 0x6d8e, 0x5f26, 0x5acc, 0x663e,
+ 0x9669, 0x73b0, 0x732e, 0x53bf, 0x817a, 0x9985, 0x7fa1, 0x5baa,
+ 0x9677, 0x9650, 0x7ebf, 0x76f8, 0x53a2, 0x9576, 0x9999, 0x7bb1,
+ 0x8944, 0x6e58, 0x4e61, 0x7fd4, 0x7965, 0x8be6, 0x60f3, 0x54cd,
+ 0x4eab, 0x9879, 0x5df7, 0x6a61, 0x50cf, 0x5411, 0x8c61, 0x8427,
+ 0x785d, 0x9704, 0x524a, 0x54ee, 0x56a3, 0x9500, 0x6d88, 0x5bb5,
+ 0x6dc6, 0x6653, 0x5c0f, 0x5b5d, 0x6821, 0x8096, 0x5578, 0x7b11,
+ 0x6548, 0x6954, 0x4e9b, 0x6b47, 0x874e, 0x978b, 0x534f, 0x631f,
+ 0x643a, 0x90aa, 0x659c, 0x80c1, 0x8c10, 0x5199, 0x68b0, 0x5378,
+ 0x87f9, 0x61c8, 0x6cc4, 0x6cfb, 0x8c22, 0x5c51, 0x85aa, 0x82af,
+ 0x950c, 0x6b23, 0x8f9b, 0x65b0, 0x5ffb, 0x5fc3, 0x4fe1, 0x8845,
+ 0x661f, 0x8165, 0x7329, 0x60fa, 0x5174, 0x5211, 0x578b, 0x5f62,
+ 0x90a2, 0x884c, 0x9192, 0x5e78, 0x674f, 0x6027, 0x59d3, 0x5144,
+ 0x51f6, 0x80f8, 0x5308, 0x6c79, 0x96c4, 0x718a, 0x4f11, 0x4fee,
+ 0x7f9e, 0x673d, 0x55c5, 0x9508, 0x79c0, 0x8896, 0x7ee3, 0x589f,
+ 0x620c, 0x9700, 0x865a, 0x5618, 0x987b, 0x5f90, 0x8bb8, 0x84c4,
+ 0x9157, 0x53d9, 0x65ed, 0x5e8f, 0x755c, 0x6064, 0x7d6e, 0x5a7f,
+ 0x7eea, 0x7eed, 0x8f69, 0x55a7, 0x5ba3, 0x60ac, 0x65cb, 0x7384,
+ 0x9009, 0x7663, 0x7729, 0x7eda, 0x9774, 0x859b, 0x5b66, 0x7a74,
+ 0x96ea, 0x8840, 0x52cb, 0x718f, 0x5faa, 0x65ec, 0x8be2, 0x5bfb,
+ 0x9a6f, 0x5de1, 0x6b89, 0x6c5b, 0x8bad, 0x8baf, 0x900a, 0x8fc5,
+ 0x538b, 0x62bc, 0x9e26, 0x9e2d, 0x5440, 0x4e2b, 0x82bd, 0x7259,
+ 0x869c, 0x5d16, 0x8859, 0x6daf, 0x96c5, 0x54d1, 0x4e9a, 0x8bb6,
+ 0x7109, 0x54bd, 0x9609, 0x70df, 0x6df9, 0x76d0, 0x4e25, 0x7814,
+ 0x8712, 0x5ca9, 0x5ef6, 0x8a00, 0x989c, 0x960e, 0x708e, 0x6cbf,
+ 0x5944, 0x63a9, 0x773c, 0x884d, 0x6f14, 0x8273, 0x5830, 0x71d5,
+ 0x538c, 0x781a, 0x96c1, 0x5501, 0x5f66, 0x7130, 0x5bb4, 0x8c1a,
+ 0x9a8c, 0x6b83, 0x592e, 0x9e2f, 0x79e7, 0x6768, 0x626c, 0x4f6f,
+ 0x75a1, 0x7f8a, 0x6d0b, 0x9633, 0x6c27, 0x4ef0, 0x75d2, 0x517b,
+ 0x6837, 0x6f3e, 0x9080, 0x8170, 0x5996, 0x7476, 0x6447, 0x5c27,
+ 0x9065, 0x7a91, 0x8c23, 0x59da, 0x54ac, 0x8200, 0x836f, 0x8981,
+ 0x8000, 0x6930, 0x564e, 0x8036, 0x7237, 0x91ce, 0x51b6, 0x4e5f,
+ 0x9875, 0x6396, 0x4e1a, 0x53f6, 0x66f3, 0x814b, 0x591c, 0x6db2,
+ 0x4e00, 0x58f9, 0x533b, 0x63d6, 0x94f1, 0x4f9d, 0x4f0a, 0x8863,
+ 0x9890, 0x5937, 0x9057, 0x79fb, 0x4eea, 0x80f0, 0x7591, 0x6c82,
+ 0x5b9c, 0x59e8, 0x5f5d, 0x6905, 0x8681, 0x501a, 0x5df2, 0x4e59,
+ 0x77e3, 0x4ee5, 0x827a, 0x6291, 0x6613, 0x9091, 0x5c79, 0x4ebf,
+ 0x5f79, 0x81c6, 0x9038, 0x8084, 0x75ab, 0x4ea6, 0x88d4, 0x610f,
+ 0x6bc5, 0x5fc6, 0x4e49, 0x76ca, 0x6ea2, 0x8be3, 0x8bae, 0x8c0a,
+ 0x8bd1, 0x5f02, 0x7ffc, 0x7fcc, 0x7ece, 0x8335, 0x836b, 0x56e0,
+ 0x6bb7, 0x97f3, 0x9634, 0x59fb, 0x541f, 0x94f6, 0x6deb, 0x5bc5,
+ 0x996e, 0x5c39, 0x5f15, 0x9690, 0x5370, 0x82f1, 0x6a31, 0x5a74,
+ 0x9e70, 0x5e94, 0x7f28, 0x83b9, 0x8424, 0x8425, 0x8367, 0x8747,
+ 0x8fce, 0x8d62, 0x76c8, 0x5f71, 0x9896, 0x786c, 0x6620, 0x54df,
+ 0x62e5, 0x4f63, 0x81c3, 0x75c8, 0x5eb8, 0x96cd, 0x8e0a, 0x86f9,
+ 0x548f, 0x6cf3, 0x6d8c, 0x6c38, 0x607f, 0x52c7, 0x7528, 0x5e7d,
+ 0x4f18, 0x60a0, 0x5fe7, 0x5c24, 0x7531, 0x90ae, 0x94c0, 0x72b9,
+ 0x6cb9, 0x6e38, 0x9149, 0x6709, 0x53cb, 0x53f3, 0x4f51, 0x91c9,
+ 0x8bf1, 0x53c8, 0x5e7c, 0x8fc2, 0x6de4, 0x4e8e, 0x76c2, 0x6986,
+ 0x865e, 0x611a, 0x8206, 0x4f59, 0x4fde, 0x903e, 0x9c7c, 0x6109,
+ 0x6e1d, 0x6e14, 0x9685, 0x4e88, 0x5a31, 0x96e8, 0x4e0e, 0x5c7f,
+ 0x79b9, 0x5b87, 0x8bed, 0x7fbd, 0x7389, 0x57df, 0x828b, 0x90c1,
+ 0x5401, 0x9047, 0x55bb, 0x5cea, 0x5fa1, 0x6108, 0x6b32, 0x72f1,
+ 0x80b2, 0x8a89, 0x6d74, 0x5bd3, 0x88d5, 0x9884, 0x8c6b, 0x9a6d,
+ 0x9e33, 0x6e0a, 0x51a4, 0x5143, 0x57a3, 0x8881, 0x539f, 0x63f4,
+ 0x8f95, 0x56ed, 0x5458, 0x5706, 0x733f, 0x6e90, 0x7f18, 0x8fdc,
+ 0x82d1, 0x613f, 0x6028, 0x9662, 0x66f0, 0x7ea6, 0x8d8a, 0x8dc3,
+ 0x94a5, 0x5cb3, 0x7ca4, 0x6708, 0x60a6, 0x9605, 0x8018, 0x4e91,
+ 0x90e7, 0x5300, 0x9668, 0x5141, 0x8fd0, 0x8574, 0x915d, 0x6655,
+ 0x97f5, 0x5b55, 0x531d, 0x7838, 0x6742, 0x683d, 0x54c9, 0x707e,
+ 0x5bb0, 0x8f7d, 0x518d, 0x5728, 0x54b1, 0x6512, 0x6682, 0x8d5e,
+ 0x8d43, 0x810f, 0x846c, 0x906d, 0x7cdf, 0x51ff, 0x85fb, 0x67a3,
+ 0x65e9, 0x6fa1, 0x86a4, 0x8e81, 0x566a, 0x9020, 0x7682, 0x7076,
+ 0x71e5, 0x8d23, 0x62e9, 0x5219, 0x6cfd, 0x8d3c, 0x600e, 0x589e,
+ 0x618e, 0x66fe, 0x8d60, 0x624e, 0x55b3, 0x6e23, 0x672d, 0x8f67,
+ 0x94e1, 0x95f8, 0x7728, 0x6805, 0x69a8, 0x548b, 0x4e4d, 0x70b8,
+ 0x8bc8, 0x6458, 0x658b, 0x5b85, 0x7a84, 0x503a, 0x5be8, 0x77bb,
+ 0x6be1, 0x8a79, 0x7c98, 0x6cbe, 0x76cf, 0x65a9, 0x8f97, 0x5d2d,
+ 0x5c55, 0x8638, 0x6808, 0x5360, 0x6218, 0x7ad9, 0x6e5b, 0x7efd,
+ 0x6a1f, 0x7ae0, 0x5f70, 0x6f33, 0x5f20, 0x638c, 0x6da8, 0x6756,
+ 0x4e08, 0x5e10, 0x8d26, 0x4ed7, 0x80c0, 0x7634, 0x969c, 0x62db,
+ 0x662d, 0x627e, 0x6cbc, 0x8d75, 0x7167, 0x7f69, 0x5146, 0x8087,
+ 0x53ec, 0x906e, 0x6298, 0x54f2, 0x86f0, 0x8f99, 0x8005, 0x9517,
+ 0x8517, 0x8fd9, 0x6d59, 0x73cd, 0x659f, 0x771f, 0x7504, 0x7827,
+ 0x81fb, 0x8d1e, 0x9488, 0x4fa6, 0x6795, 0x75b9, 0x8bca, 0x9707,
+ 0x632f, 0x9547, 0x9635, 0x84b8, 0x6323, 0x7741, 0x5f81, 0x72f0,
+ 0x4e89, 0x6014, 0x6574, 0x62ef, 0x6b63, 0x653f, 0x5e27, 0x75c7,
+ 0x90d1, 0x8bc1, 0x829d, 0x679d, 0x652f, 0x5431, 0x8718, 0x77e5,
+ 0x80a2, 0x8102, 0x6c41, 0x4e4b, 0x7ec7, 0x804c, 0x76f4, 0x690d,
+ 0x6b96, 0x6267, 0x503c, 0x4f84, 0x5740, 0x6307, 0x6b62, 0x8dbe,
+ 0x53ea, 0x65e8, 0x7eb8, 0x5fd7, 0x631a, 0x63b7, 0x81f3, 0x81f4,
+ 0x7f6e, 0x5e1c, 0x5cd9, 0x5236, 0x667a, 0x79e9, 0x7a1a, 0x8d28,
+ 0x7099, 0x75d4, 0x6ede, 0x6cbb, 0x7a92, 0x4e2d, 0x76c5, 0x5fe0,
+ 0x949f, 0x8877, 0x7ec8, 0x79cd, 0x80bf, 0x91cd, 0x4ef2, 0x4f17,
+ 0x821f, 0x5468, 0x5dde, 0x6d32, 0x8bcc, 0x7ca5, 0x8f74, 0x8098,
+ 0x5e1a, 0x5492, 0x76b1, 0x5b99, 0x663c, 0x9aa4, 0x73e0, 0x682a,
+ 0x86db, 0x6731, 0x732a, 0x8bf8, 0x8bdb, 0x9010, 0x7af9, 0x70db,
+ 0x716e, 0x62c4, 0x77a9, 0x5631, 0x4e3b, 0x8457, 0x67f1, 0x52a9,
+ 0x86c0, 0x8d2e, 0x94f8, 0x7b51, 0x4f4f, 0x6ce8, 0x795d, 0x9a7b,
+ 0x6293, 0x722a, 0x62fd, 0x4e13, 0x7816, 0x8f6c, 0x64b0, 0x8d5a,
+ 0x7bc6, 0x6869, 0x5e84, 0x88c5, 0x5986, 0x649e, 0x58ee, 0x72b6,
+ 0x690e, 0x9525, 0x8ffd, 0x8d58, 0x5760, 0x7f00, 0x8c06, 0x51c6,
+ 0x6349, 0x62d9, 0x5353, 0x684c, 0x7422, 0x8301, 0x914c, 0x5544,
+ 0x7740, 0x707c, 0x6d4a, 0x5179, 0x54a8, 0x8d44, 0x59ff, 0x6ecb,
+ 0x6dc4, 0x5b5c, 0x7d2b, 0x4ed4, 0x7c7d, 0x6ed3, 0x5b50, 0x81ea,
+ 0x6e0d, 0x5b57, 0x9b03, 0x68d5, 0x8e2a, 0x5b97, 0x7efc, 0x603b,
+ 0x7eb5, 0x90b9, 0x8d70, 0x594f, 0x63cd, 0x79df, 0x8db3, 0x5352,
+ 0x65cf, 0x7956, 0x8bc5, 0x963b, 0x7ec4, 0x94bb, 0x7e82, 0x5634,
+ 0x9189, 0x6700, 0x7f6a, 0x5c0a, 0x9075, 0x6628, 0x5de6, 0x4f50,
+ 0x67de, 0x505a, 0x4f5c, 0x5750, 0x5ea7, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4e8d, 0x4e0c, 0x5140, 0x4e10, 0x5eff, 0x5345,
+ 0x4e15, 0x4e98, 0x4e1e, 0x9b32, 0x5b6c, 0x5669, 0x4e28, 0x79ba,
+ 0x4e3f, 0x5315, 0x4e47, 0x592d, 0x723b, 0x536e, 0x6c10, 0x56df,
+ 0x80e4, 0x9997, 0x6bd3, 0x777e, 0x9f17, 0x4e36, 0x4e9f, 0x9f10,
+ 0x4e5c, 0x4e69, 0x4e93, 0x8288, 0x5b5b, 0x556c, 0x560f, 0x4ec4,
+ 0x538d, 0x539d, 0x53a3, 0x53a5, 0x53ae, 0x9765, 0x8d5d, 0x531a,
+ 0x53f5, 0x5326, 0x532e, 0x533e, 0x8d5c, 0x5366, 0x5363, 0x5202,
+ 0x5208, 0x520e, 0x522d, 0x5233, 0x523f, 0x5240, 0x524c, 0x525e,
+ 0x5261, 0x525c, 0x84af, 0x527d, 0x5282, 0x5281, 0x5290, 0x5293,
+ 0x5182, 0x7f54, 0x4ebb, 0x4ec3, 0x4ec9, 0x4ec2, 0x4ee8, 0x4ee1,
+ 0x4eeb, 0x4ede, 0x4f1b, 0x4ef3, 0x4f22, 0x4f64, 0x4ef5, 0x4f25,
+ 0x4f27, 0x4f09, 0x4f2b, 0x4f5e, 0x4f67, 0x6538, 0x4f5a, 0x4f5d,
+ 0x4f5f, 0x4f57, 0x4f32, 0x4f3d, 0x4f76, 0x4f74, 0x4f91, 0x4f89,
+ 0x4f83, 0x4f8f, 0x4f7e, 0x4f7b, 0x4faa, 0x4f7c, 0x4fac, 0x4f94,
+ 0x4fe6, 0x4fe8, 0x4fea, 0x4fc5, 0x4fda, 0x4fe3, 0x4fdc, 0x4fd1,
+ 0x4fdf, 0x4ff8, 0x5029, 0x504c, 0x4ff3, 0x502c, 0x500f, 0x502e,
+ 0x502d, 0x4ffe, 0x501c, 0x500c, 0x5025, 0x5028, 0x507e, 0x5043,
+ 0x5055, 0x5048, 0x504e, 0x506c, 0x507b, 0x50a5, 0x50a7, 0x50a9,
+ 0x50ba, 0x50d6, 0x5106, 0x50ed, 0x50ec, 0x50e6, 0x50ee, 0x5107,
+ 0x510b, 0x4edd, 0x6c3d, 0x4f58, 0x4f65, 0x4fce, 0x9fa0, 0x6c46,
+ 0x7c74, 0x516e, 0x5dfd, 0x9ec9, 0x9998, 0x5181, 0x5914, 0x52f9,
+ 0x530d, 0x8a07, 0x5310, 0x51eb, 0x5919, 0x5155, 0x4ea0, 0x5156,
+ 0x4eb3, 0x886e, 0x88a4, 0x4eb5, 0x8114, 0x88d2, 0x7980, 0x5b34,
+ 0x8803, 0x7fb8, 0x51ab, 0x51b1, 0x51bd, 0x51bc, 0x51c7, 0x5196,
+ 0x51a2, 0x51a5, 0x8ba0, 0x8ba6, 0x8ba7, 0x8baa, 0x8bb4, 0x8bb5,
+ 0x8bb7, 0x8bc2, 0x8bc3, 0x8bcb, 0x8bcf, 0x8bce, 0x8bd2, 0x8bd3,
+ 0x8bd4, 0x8bd6, 0x8bd8, 0x8bd9, 0x8bdc, 0x8bdf, 0x8be0, 0x8be4,
+ 0x8be8, 0x8be9, 0x8bee, 0x8bf0, 0x8bf3, 0x8bf6, 0x8bf9, 0x8bfc,
+ 0x8bff, 0x8c00, 0x8c02, 0x8c04, 0x8c07, 0x8c0c, 0x8c0f, 0x8c11,
+ 0x8c12, 0x8c14, 0x8c15, 0x8c16, 0x8c19, 0x8c1b, 0x8c18, 0x8c1d,
+ 0x8c1f, 0x8c20, 0x8c21, 0x8c25, 0x8c27, 0x8c2a, 0x8c2b, 0x8c2e,
+ 0x8c2f, 0x8c32, 0x8c33, 0x8c35, 0x8c36, 0x5369, 0x537a, 0x961d,
+ 0x9622, 0x9621, 0x9631, 0x962a, 0x963d, 0x963c, 0x9642, 0x9649,
+ 0x9654, 0x965f, 0x9667, 0x966c, 0x9672, 0x9674, 0x9688, 0x968d,
+ 0x9697, 0x96b0, 0x9097, 0x909b, 0x909d, 0x9099, 0x90ac, 0x90a1,
+ 0x90b4, 0x90b3, 0x90b6, 0x90ba, 0x90b8, 0x90b0, 0x90cf, 0x90c5,
+ 0x90be, 0x90d0, 0x90c4, 0x90c7, 0x90d3, 0x90e6, 0x90e2, 0x90dc,
+ 0x90d7, 0x90db, 0x90eb, 0x90ef, 0x90fe, 0x9104, 0x9122, 0x911e,
+ 0x9123, 0x9131, 0x912f, 0x9139, 0x9143, 0x9146, 0x520d, 0x5942,
+ 0x52a2, 0x52ac, 0x52ad, 0x52be, 0x54ff, 0x52d0, 0x52d6, 0x52f0,
+ 0x53df, 0x71ee, 0x77cd, 0x5ef4, 0x51f5, 0x51fc, 0x9b2f, 0x53b6,
+ 0x5f01, 0x755a, 0x5def, 0x574c, 0x57a9, 0x57a1, 0x587e, 0x58bc,
+ 0x58c5, 0x58d1, 0x5729, 0x572c, 0x572a, 0x5733, 0x5739, 0x572e,
+ 0x572f, 0x575c, 0x573b, 0x5742, 0x5769, 0x5785, 0x576b, 0x5786,
+ 0x577c, 0x577b, 0x5768, 0x576d, 0x5776, 0x5773, 0x57ad, 0x57a4,
+ 0x578c, 0x57b2, 0x57cf, 0x57a7, 0x57b4, 0x5793, 0x57a0, 0x57d5,
+ 0x57d8, 0x57da, 0x57d9, 0x57d2, 0x57b8, 0x57f4, 0x57ef, 0x57f8,
+ 0x57e4, 0x57dd, 0x580b, 0x580d, 0x57fd, 0x57ed, 0x5800, 0x581e,
+ 0x5819, 0x5844, 0x5820, 0x5865, 0x586c, 0x5881, 0x5889, 0x589a,
+ 0x5880, 0x99a8, 0x9f19, 0x61ff, 0x8279, 0x827d, 0x827f, 0x828f,
+ 0x828a, 0x82a8, 0x8284, 0x828e, 0x8291, 0x8297, 0x8299, 0x82ab,
+ 0x82b8, 0x82be, 0x82b0, 0x82c8, 0x82ca, 0x82e3, 0x8298, 0x82b7,
+ 0x82ae, 0x82cb, 0x82cc, 0x82c1, 0x82a9, 0x82b4, 0x82a1, 0x82aa,
+ 0x829f, 0x82c4, 0x82ce, 0x82a4, 0x82e1, 0x8309, 0x82f7, 0x82e4,
+ 0x830f, 0x8307, 0x82dc, 0x82f4, 0x82d2, 0x82d8, 0x830c, 0x82fb,
+ 0x82d3, 0x8311, 0x831a, 0x8306, 0x8314, 0x8315, 0x82e0, 0x82d5,
+ 0x831c, 0x8351, 0x835b, 0x835c, 0x8308, 0x8392, 0x833c, 0x8334,
+ 0x8331, 0x839b, 0x835e, 0x832f, 0x834f, 0x8347, 0x8343, 0x835f,
+ 0x8340, 0x8317, 0x8360, 0x832d, 0x833a, 0x8333, 0x8366, 0x8365,
+ 0x8368, 0x831b, 0x8369, 0x836c, 0x836a, 0x836d, 0x836e, 0x83b0,
+ 0x8378, 0x83b3, 0x83b4, 0x83a0, 0x83aa, 0x8393, 0x839c, 0x8385,
+ 0x837c, 0x83b6, 0x83a9, 0x837d, 0x83b8, 0x837b, 0x8398, 0x839e,
+ 0x83a8, 0x83ba, 0x83bc, 0x83c1, 0x8401, 0x83e5, 0x83d8, 0x5807,
+ 0x8418, 0x840b, 0x83dd, 0x83fd, 0x83d6, 0x841c, 0x8438, 0x8411,
+ 0x8406, 0x83d4, 0x83df, 0x840f, 0x8403, 0x83f8, 0x83f9, 0x83ea,
+ 0x83c5, 0x83c0, 0x8426, 0x83f0, 0x83e1, 0x845c, 0x8451, 0x845a,
+ 0x8459, 0x8473, 0x8487, 0x8488, 0x847a, 0x8489, 0x8478, 0x843c,
+ 0x8446, 0x8469, 0x8476, 0x848c, 0x848e, 0x8431, 0x846d, 0x84c1,
+ 0x84cd, 0x84d0, 0x84e6, 0x84bd, 0x84d3, 0x84ca, 0x84bf, 0x84ba,
+ 0x84e0, 0x84a1, 0x84b9, 0x84b4, 0x8497, 0x84e5, 0x84e3, 0x850c,
+ 0x750d, 0x8538, 0x84f0, 0x8539, 0x851f, 0x853a, 0x8556, 0x853b,
+ 0x84ff, 0x84fc, 0x8559, 0x8548, 0x8568, 0x8564, 0x855e, 0x857a,
+ 0x77a2, 0x8543, 0x8572, 0x857b, 0x85a4, 0x85a8, 0x8587, 0x858f,
+ 0x8579, 0x85ae, 0x859c, 0x8585, 0x85b9, 0x85b7, 0x85b0, 0x85d3,
+ 0x85c1, 0x85dc, 0x85ff, 0x8627, 0x8605, 0x8629, 0x8616, 0x863c,
+ 0x5efe, 0x5f08, 0x593c, 0x5941, 0x8037, 0x5955, 0x595a, 0x5958,
+ 0x530f, 0x5c22, 0x5c25, 0x5c2c, 0x5c34, 0x624c, 0x626a, 0x629f,
+ 0x62bb, 0x62ca, 0x62da, 0x62d7, 0x62ee, 0x6322, 0x62f6, 0x6339,
+ 0x634b, 0x6343, 0x63ad, 0x63f6, 0x6371, 0x637a, 0x638e, 0x63b4,
+ 0x636d, 0x63ac, 0x638a, 0x6369, 0x63ae, 0x63bc, 0x63f2, 0x63f8,
+ 0x63e0, 0x63ff, 0x63c4, 0x63de, 0x63ce, 0x6452, 0x63c6, 0x63be,
+ 0x6445, 0x6441, 0x640b, 0x641b, 0x6420, 0x640c, 0x6426, 0x6421,
+ 0x645e, 0x6484, 0x646d, 0x6496, 0x647a, 0x64b7, 0x64b8, 0x6499,
+ 0x64ba, 0x64c0, 0x64d0, 0x64d7, 0x64e4, 0x64e2, 0x6509, 0x6525,
+ 0x652e, 0x5f0b, 0x5fd2, 0x7519, 0x5f11, 0x535f, 0x53f1, 0x53fd,
+ 0x53e9, 0x53e8, 0x53fb, 0x5412, 0x5416, 0x5406, 0x544b, 0x5452,
+ 0x5453, 0x5454, 0x5456, 0x5443, 0x5421, 0x5457, 0x5459, 0x5423,
+ 0x5432, 0x5482, 0x5494, 0x5477, 0x5471, 0x5464, 0x549a, 0x549b,
+ 0x5484, 0x5476, 0x5466, 0x549d, 0x54d0, 0x54ad, 0x54c2, 0x54b4,
+ 0x54d2, 0x54a7, 0x54a6, 0x54d3, 0x54d4, 0x5472, 0x54a3, 0x54d5,
+ 0x54bb, 0x54bf, 0x54cc, 0x54d9, 0x54da, 0x54dc, 0x54a9, 0x54aa,
+ 0x54a4, 0x54dd, 0x54cf, 0x54de, 0x551b, 0x54e7, 0x5520, 0x54fd,
+ 0x5514, 0x54f3, 0x5522, 0x5523, 0x550f, 0x5511, 0x5527, 0x552a,
+ 0x5567, 0x558f, 0x55b5, 0x5549, 0x556d, 0x5541, 0x5555, 0x553f,
+ 0x5550, 0x553c, 0x5537, 0x5556, 0x5575, 0x5576, 0x5577, 0x5533,
+ 0x5530, 0x555c, 0x558b, 0x55d2, 0x5583, 0x55b1, 0x55b9, 0x5588,
+ 0x5581, 0x559f, 0x557e, 0x55d6, 0x5591, 0x557b, 0x55df, 0x55bd,
+ 0x55be, 0x5594, 0x5599, 0x55ea, 0x55f7, 0x55c9, 0x561f, 0x55d1,
+ 0x55eb, 0x55ec, 0x55d4, 0x55e6, 0x55dd, 0x55c4, 0x55ef, 0x55e5,
+ 0x55f2, 0x55f3, 0x55cc, 0x55cd, 0x55e8, 0x55f5, 0x55e4, 0x8f94,
+ 0x561e, 0x5608, 0x560c, 0x5601, 0x5624, 0x5623, 0x55fe, 0x5600,
+ 0x5627, 0x562d, 0x5658, 0x5639, 0x5657, 0x562c, 0x564d, 0x5662,
+ 0x5659, 0x565c, 0x564c, 0x5654, 0x5686, 0x5664, 0x5671, 0x566b,
+ 0x567b, 0x567c, 0x5685, 0x5693, 0x56af, 0x56d4, 0x56d7, 0x56dd,
+ 0x56e1, 0x56f5, 0x56eb, 0x56f9, 0x56ff, 0x5704, 0x570a, 0x5709,
+ 0x571c, 0x5e0f, 0x5e19, 0x5e14, 0x5e11, 0x5e31, 0x5e3b, 0x5e3c,
+ 0x5e37, 0x5e44, 0x5e54, 0x5e5b, 0x5e5e, 0x5e61, 0x5c8c, 0x5c7a,
+ 0x5c8d, 0x5c90, 0x5c96, 0x5c88, 0x5c98, 0x5c99, 0x5c91, 0x5c9a,
+ 0x5c9c, 0x5cb5, 0x5ca2, 0x5cbd, 0x5cac, 0x5cab, 0x5cb1, 0x5ca3,
+ 0x5cc1, 0x5cb7, 0x5cc4, 0x5cd2, 0x5ce4, 0x5ccb, 0x5ce5, 0x5d02,
+ 0x5d03, 0x5d27, 0x5d26, 0x5d2e, 0x5d24, 0x5d1e, 0x5d06, 0x5d1b,
+ 0x5d58, 0x5d3e, 0x5d34, 0x5d3d, 0x5d6c, 0x5d5b, 0x5d6f, 0x5d5d,
+ 0x5d6b, 0x5d4b, 0x5d4a, 0x5d69, 0x5d74, 0x5d82, 0x5d99, 0x5d9d,
+ 0x8c73, 0x5db7, 0x5dc5, 0x5f73, 0x5f77, 0x5f82, 0x5f87, 0x5f89,
+ 0x5f8c, 0x5f95, 0x5f99, 0x5f9c, 0x5fa8, 0x5fad, 0x5fb5, 0x5fbc,
+ 0x8862, 0x5f61, 0x72ad, 0x72b0, 0x72b4, 0x72b7, 0x72b8, 0x72c3,
+ 0x72c1, 0x72ce, 0x72cd, 0x72d2, 0x72e8, 0x72ef, 0x72e9, 0x72f2,
+ 0x72f4, 0x72f7, 0x7301, 0x72f3, 0x7303, 0x72fa, 0x72fb, 0x7317,
+ 0x7313, 0x7321, 0x730a, 0x731e, 0x731d, 0x7315, 0x7322, 0x7339,
+ 0x7325, 0x732c, 0x7338, 0x7331, 0x7350, 0x734d, 0x7357, 0x7360,
+ 0x736c, 0x736f, 0x737e, 0x821b, 0x5925, 0x98e7, 0x5924, 0x5902,
+ 0x9963, 0x9967, 0x9968, 0x9969, 0x996a, 0x996b, 0x996c, 0x9974,
+ 0x9977, 0x997d, 0x9980, 0x9984, 0x9987, 0x998a, 0x998d, 0x9990,
+ 0x9991, 0x9993, 0x9994, 0x9995, 0x5e80, 0x5e91, 0x5e8b, 0x5e96,
+ 0x5ea5, 0x5ea0, 0x5eb9, 0x5eb5, 0x5ebe, 0x5eb3, 0x8d53, 0x5ed2,
+ 0x5ed1, 0x5edb, 0x5ee8, 0x5eea, 0x81ba, 0x5fc4, 0x5fc9, 0x5fd6,
+ 0x5fcf, 0x6003, 0x5fee, 0x6004, 0x5fe1, 0x5fe4, 0x5ffe, 0x6005,
+ 0x6006, 0x5fea, 0x5fed, 0x5ff8, 0x6019, 0x6035, 0x6026, 0x601b,
+ 0x600f, 0x600d, 0x6029, 0x602b, 0x600a, 0x603f, 0x6021, 0x6078,
+ 0x6079, 0x607b, 0x607a, 0x6042, 0x606a, 0x607d, 0x6096, 0x609a,
+ 0x60ad, 0x609d, 0x6083, 0x6092, 0x608c, 0x609b, 0x60ec, 0x60bb,
+ 0x60b1, 0x60dd, 0x60d8, 0x60c6, 0x60da, 0x60b4, 0x6120, 0x6126,
+ 0x6115, 0x6123, 0x60f4, 0x6100, 0x610e, 0x612b, 0x614a, 0x6175,
+ 0x61ac, 0x6194, 0x61a7, 0x61b7, 0x61d4, 0x61f5, 0x5fdd, 0x96b3,
+ 0x95e9, 0x95eb, 0x95f1, 0x95f3, 0x95f5, 0x95f6, 0x95fc, 0x95fe,
+ 0x9603, 0x9604, 0x9606, 0x9608, 0x960a, 0x960b, 0x960c, 0x960d,
+ 0x960f, 0x9612, 0x9615, 0x9616, 0x9617, 0x9619, 0x961a, 0x4e2c,
+ 0x723f, 0x6215, 0x6c35, 0x6c54, 0x6c5c, 0x6c4a, 0x6ca3, 0x6c85,
+ 0x6c90, 0x6c94, 0x6c8c, 0x6c68, 0x6c69, 0x6c74, 0x6c76, 0x6c86,
+ 0x6ca9, 0x6cd0, 0x6cd4, 0x6cad, 0x6cf7, 0x6cf8, 0x6cf1, 0x6cd7,
+ 0x6cb2, 0x6ce0, 0x6cd6, 0x6cfa, 0x6ceb, 0x6cee, 0x6cb1, 0x6cd3,
+ 0x6cef, 0x6cfe, 0x6d39, 0x6d27, 0x6d0c, 0x6d43, 0x6d48, 0x6d07,
+ 0x6d04, 0x6d19, 0x6d0e, 0x6d2b, 0x6d4d, 0x6d2e, 0x6d35, 0x6d1a,
+ 0x6d4f, 0x6d52, 0x6d54, 0x6d33, 0x6d91, 0x6d6f, 0x6d9e, 0x6da0,
+ 0x6d5e, 0x6d93, 0x6d94, 0x6d5c, 0x6d60, 0x6d7c, 0x6d63, 0x6e1a,
+ 0x6dc7, 0x6dc5, 0x6dde, 0x6e0e, 0x6dbf, 0x6de0, 0x6e11, 0x6de6,
+ 0x6ddd, 0x6dd9, 0x6e16, 0x6dab, 0x6e0c, 0x6dae, 0x6e2b, 0x6e6e,
+ 0x6e4e, 0x6e6b, 0x6eb2, 0x6e5f, 0x6e86, 0x6e53, 0x6e54, 0x6e32,
+ 0x6e25, 0x6e44, 0x6edf, 0x6eb1, 0x6e98, 0x6ee0, 0x6f2d, 0x6ee2,
+ 0x6ea5, 0x6ea7, 0x6ebd, 0x6ebb, 0x6eb7, 0x6ed7, 0x6eb4, 0x6ecf,
+ 0x6e8f, 0x6ec2, 0x6e9f, 0x6f62, 0x6f46, 0x6f47, 0x6f24, 0x6f15,
+ 0x6ef9, 0x6f2f, 0x6f36, 0x6f4b, 0x6f74, 0x6f2a, 0x6f09, 0x6f29,
+ 0x6f89, 0x6f8d, 0x6f8c, 0x6f78, 0x6f72, 0x6f7c, 0x6f7a, 0x6fd1,
+ 0x6fc9, 0x6fa7, 0x6fb9, 0x6fb6, 0x6fc2, 0x6fe1, 0x6fee, 0x6fde,
+ 0x6fe0, 0x6fef, 0x701a, 0x7023, 0x701b, 0x7039, 0x7035, 0x704f,
+ 0x705e, 0x5b80, 0x5b84, 0x5b95, 0x5b93, 0x5ba5, 0x5bb8, 0x752f,
+ 0x9a9e, 0x6434, 0x5be4, 0x5bee, 0x8930, 0x5bf0, 0x8e47, 0x8b07,
+ 0x8fb6, 0x8fd3, 0x8fd5, 0x8fe5, 0x8fee, 0x8fe4, 0x8fe9, 0x8fe6,
+ 0x8ff3, 0x8fe8, 0x9005, 0x9004, 0x900b, 0x9026, 0x9011, 0x900d,
+ 0x9016, 0x9021, 0x9035, 0x9036, 0x902d, 0x902f, 0x9044, 0x9051,
+ 0x9052, 0x9050, 0x9068, 0x9058, 0x9062, 0x905b, 0x66b9, 0x9074,
+ 0x907d, 0x9082, 0x9088, 0x9083, 0x908b, 0x5f50, 0x5f57, 0x5f56,
+ 0x5f58, 0x5c3b, 0x54ab, 0x5c50, 0x5c59, 0x5b71, 0x5c63, 0x5c66,
+ 0x7fbc, 0x5f2a, 0x5f29, 0x5f2d, 0x8274, 0x5f3c, 0x9b3b, 0x5c6e,
+ 0x5981, 0x5983, 0x598d, 0x59a9, 0x59aa, 0x59a3, 0x5997, 0x59ca,
+ 0x59ab, 0x599e, 0x59a4, 0x59d2, 0x59b2, 0x59af, 0x59d7, 0x59be,
+ 0x5a05, 0x5a06, 0x59dd, 0x5a08, 0x59e3, 0x59d8, 0x59f9, 0x5a0c,
+ 0x5a09, 0x5a32, 0x5a34, 0x5a11, 0x5a23, 0x5a13, 0x5a40, 0x5a67,
+ 0x5a4a, 0x5a55, 0x5a3c, 0x5a62, 0x5a75, 0x80ec, 0x5aaa, 0x5a9b,
+ 0x5a77, 0x5a7a, 0x5abe, 0x5aeb, 0x5ab2, 0x5ad2, 0x5ad4, 0x5ab8,
+ 0x5ae0, 0x5ae3, 0x5af1, 0x5ad6, 0x5ae6, 0x5ad8, 0x5adc, 0x5b09,
+ 0x5b17, 0x5b16, 0x5b32, 0x5b37, 0x5b40, 0x5c15, 0x5c1c, 0x5b5a,
+ 0x5b65, 0x5b73, 0x5b51, 0x5b53, 0x5b62, 0x9a75, 0x9a77, 0x9a78,
+ 0x9a7a, 0x9a7f, 0x9a7d, 0x9a80, 0x9a81, 0x9a85, 0x9a88, 0x9a8a,
+ 0x9a90, 0x9a92, 0x9a93, 0x9a96, 0x9a98, 0x9a9b, 0x9a9c, 0x9a9d,
+ 0x9a9f, 0x9aa0, 0x9aa2, 0x9aa3, 0x9aa5, 0x9aa7, 0x7e9f, 0x7ea1,
+ 0x7ea3, 0x7ea5, 0x7ea8, 0x7ea9, 0x7ead, 0x7eb0, 0x7ebe, 0x7ec0,
+ 0x7ec1, 0x7ec2, 0x7ec9, 0x7ecb, 0x7ecc, 0x7ed0, 0x7ed4, 0x7ed7,
+ 0x7edb, 0x7ee0, 0x7ee1, 0x7ee8, 0x7eeb, 0x7eee, 0x7eef, 0x7ef1,
+ 0x7ef2, 0x7f0d, 0x7ef6, 0x7efa, 0x7efb, 0x7efe, 0x7f01, 0x7f02,
+ 0x7f03, 0x7f07, 0x7f08, 0x7f0b, 0x7f0c, 0x7f0f, 0x7f11, 0x7f12,
+ 0x7f17, 0x7f19, 0x7f1c, 0x7f1b, 0x7f1f, 0x7f21, 0x7f22, 0x7f23,
+ 0x7f24, 0x7f25, 0x7f26, 0x7f27, 0x7f2a, 0x7f2b, 0x7f2c, 0x7f2d,
+ 0x7f2f, 0x7f30, 0x7f31, 0x7f32, 0x7f33, 0x7f35, 0x5e7a, 0x757f,
+ 0x5ddb, 0x753e, 0x9095, 0x738e, 0x7391, 0x73ae, 0x73a2, 0x739f,
+ 0x73cf, 0x73c2, 0x73d1, 0x73b7, 0x73b3, 0x73c0, 0x73c9, 0x73c8,
+ 0x73e5, 0x73d9, 0x987c, 0x740a, 0x73e9, 0x73e7, 0x73de, 0x73ba,
+ 0x73f2, 0x740f, 0x742a, 0x745b, 0x7426, 0x7425, 0x7428, 0x7430,
+ 0x742e, 0x742c, 0x741b, 0x741a, 0x7441, 0x745c, 0x7457, 0x7455,
+ 0x7459, 0x7477, 0x746d, 0x747e, 0x749c, 0x748e, 0x7480, 0x7481,
+ 0x7487, 0x748b, 0x749e, 0x74a8, 0x74a9, 0x7490, 0x74a7, 0x74d2,
+ 0x74ba, 0x97ea, 0x97eb, 0x97ec, 0x674c, 0x6753, 0x675e, 0x6748,
+ 0x6769, 0x67a5, 0x6787, 0x676a, 0x6773, 0x6798, 0x67a7, 0x6775,
+ 0x67a8, 0x679e, 0x67ad, 0x678b, 0x6777, 0x677c, 0x67f0, 0x6809,
+ 0x67d8, 0x680a, 0x67e9, 0x67b0, 0x680c, 0x67d9, 0x67b5, 0x67da,
+ 0x67b3, 0x67dd, 0x6800, 0x67c3, 0x67b8, 0x67e2, 0x680e, 0x67c1,
+ 0x67fd, 0x6832, 0x6833, 0x6860, 0x6861, 0x684e, 0x6862, 0x6844,
+ 0x6864, 0x6883, 0x681d, 0x6855, 0x6866, 0x6841, 0x6867, 0x6840,
+ 0x683e, 0x684a, 0x6849, 0x6829, 0x68b5, 0x688f, 0x6874, 0x6877,
+ 0x6893, 0x686b, 0x68c2, 0x696e, 0x68fc, 0x691f, 0x6920, 0x68f9,
+ 0x6924, 0x68f0, 0x690b, 0x6901, 0x6957, 0x68e3, 0x6910, 0x6971,
+ 0x6939, 0x6960, 0x6942, 0x695d, 0x6984, 0x696b, 0x6980, 0x6998,
+ 0x6978, 0x6934, 0x69cc, 0x6987, 0x6988, 0x69ce, 0x6989, 0x6966,
+ 0x6963, 0x6979, 0x699b, 0x69a7, 0x69bb, 0x69ab, 0x69ad, 0x69d4,
+ 0x69b1, 0x69c1, 0x69ca, 0x69df, 0x6995, 0x69e0, 0x698d, 0x69ff,
+ 0x6a2f, 0x69ed, 0x6a17, 0x6a18, 0x6a65, 0x69f2, 0x6a44, 0x6a3e,
+ 0x6aa0, 0x6a50, 0x6a5b, 0x6a35, 0x6a8e, 0x6a79, 0x6a3d, 0x6a28,
+ 0x6a58, 0x6a7c, 0x6a91, 0x6a90, 0x6aa9, 0x6a97, 0x6aab, 0x7337,
+ 0x7352, 0x6b81, 0x6b82, 0x6b87, 0x6b84, 0x6b92, 0x6b93, 0x6b8d,
+ 0x6b9a, 0x6b9b, 0x6ba1, 0x6baa, 0x8f6b, 0x8f6d, 0x8f71, 0x8f72,
+ 0x8f73, 0x8f75, 0x8f76, 0x8f78, 0x8f77, 0x8f79, 0x8f7a, 0x8f7c,
+ 0x8f7e, 0x8f81, 0x8f82, 0x8f84, 0x8f87, 0x8f8b, 0x8f8d, 0x8f8e,
+ 0x8f8f, 0x8f98, 0x8f9a, 0x8ece, 0x620b, 0x6217, 0x621b, 0x621f,
+ 0x6222, 0x6221, 0x6225, 0x6224, 0x622c, 0x81e7, 0x74ef, 0x74f4,
+ 0x74ff, 0x750f, 0x7511, 0x7513, 0x6534, 0x65ee, 0x65ef, 0x65f0,
+ 0x660a, 0x6619, 0x6772, 0x6603, 0x6615, 0x6600, 0x7085, 0x66f7,
+ 0x661d, 0x6634, 0x6631, 0x6636, 0x6635, 0x8006, 0x665f, 0x6654,
+ 0x6641, 0x664f, 0x6656, 0x6661, 0x6657, 0x6677, 0x6684, 0x668c,
+ 0x66a7, 0x669d, 0x66be, 0x66db, 0x66dc, 0x66e6, 0x66e9, 0x8d32,
+ 0x8d33, 0x8d36, 0x8d3b, 0x8d3d, 0x8d40, 0x8d45, 0x8d46, 0x8d48,
+ 0x8d49, 0x8d47, 0x8d4d, 0x8d55, 0x8d59, 0x89c7, 0x89ca, 0x89cb,
+ 0x89cc, 0x89ce, 0x89cf, 0x89d0, 0x89d1, 0x726e, 0x729f, 0x725d,
+ 0x7266, 0x726f, 0x727e, 0x727f, 0x7284, 0x728b, 0x728d, 0x728f,
+ 0x7292, 0x6308, 0x6332, 0x63b0, 0x643f, 0x64d8, 0x8004, 0x6bea,
+ 0x6bf3, 0x6bfd, 0x6bf5, 0x6bf9, 0x6c05, 0x6c07, 0x6c06, 0x6c0d,
+ 0x6c15, 0x6c18, 0x6c19, 0x6c1a, 0x6c21, 0x6c29, 0x6c24, 0x6c2a,
+ 0x6c32, 0x6535, 0x6555, 0x656b, 0x724d, 0x7252, 0x7256, 0x7230,
+ 0x8662, 0x5216, 0x809f, 0x809c, 0x8093, 0x80bc, 0x670a, 0x80bd,
+ 0x80b1, 0x80ab, 0x80ad, 0x80b4, 0x80b7, 0x80e7, 0x80e8, 0x80e9,
+ 0x80ea, 0x80db, 0x80c2, 0x80c4, 0x80d9, 0x80cd, 0x80d7, 0x6710,
+ 0x80dd, 0x80eb, 0x80f1, 0x80f4, 0x80ed, 0x810d, 0x810e, 0x80f2,
+ 0x80fc, 0x6715, 0x8112, 0x8c5a, 0x8136, 0x811e, 0x812c, 0x8118,
+ 0x8132, 0x8148, 0x814c, 0x8153, 0x8174, 0x8159, 0x815a, 0x8171,
+ 0x8160, 0x8169, 0x817c, 0x817d, 0x816d, 0x8167, 0x584d, 0x5ab5,
+ 0x8188, 0x8182, 0x8191, 0x6ed5, 0x81a3, 0x81aa, 0x81cc, 0x6726,
+ 0x81ca, 0x81bb, 0x81c1, 0x81a6, 0x6b24, 0x6b37, 0x6b39, 0x6b43,
+ 0x6b46, 0x6b59, 0x98d1, 0x98d2, 0x98d3, 0x98d5, 0x98d9, 0x98da,
+ 0x6bb3, 0x5f40, 0x6bc2, 0x89f3, 0x6590, 0x9f51, 0x6593, 0x65bc,
+ 0x65c6, 0x65c4, 0x65c3, 0x65cc, 0x65ce, 0x65d2, 0x65d6, 0x7080,
+ 0x709c, 0x7096, 0x709d, 0x70bb, 0x70c0, 0x70b7, 0x70ab, 0x70b1,
+ 0x70e8, 0x70ca, 0x7110, 0x7113, 0x7116, 0x712f, 0x7131, 0x7173,
+ 0x715c, 0x7168, 0x7145, 0x7172, 0x714a, 0x7178, 0x717a, 0x7198,
+ 0x71b3, 0x71b5, 0x71a8, 0x71a0, 0x71e0, 0x71d4, 0x71e7, 0x71f9,
+ 0x721d, 0x7228, 0x706c, 0x7118, 0x7166, 0x71b9, 0x623e, 0x623d,
+ 0x6243, 0x6248, 0x6249, 0x793b, 0x7940, 0x7946, 0x7949, 0x795b,
+ 0x795c, 0x7953, 0x795a, 0x7962, 0x7957, 0x7960, 0x796f, 0x7967,
+ 0x797a, 0x7985, 0x798a, 0x799a, 0x79a7, 0x79b3, 0x5fd1, 0x5fd0,
+ 0x603c, 0x605d, 0x605a, 0x6067, 0x6041, 0x6059, 0x6063, 0x60ab,
+ 0x6106, 0x610d, 0x615d, 0x61a9, 0x619d, 0x61cb, 0x61d1, 0x6206,
+ 0x8080, 0x807f, 0x6c93, 0x6cf6, 0x6dfc, 0x77f6, 0x77f8, 0x7800,
+ 0x7809, 0x7817, 0x7818, 0x7811, 0x65ab, 0x782d, 0x781c, 0x781d,
+ 0x7839, 0x783a, 0x783b, 0x781f, 0x783c, 0x7825, 0x782c, 0x7823,
+ 0x7829, 0x784e, 0x786d, 0x7856, 0x7857, 0x7826, 0x7850, 0x7847,
+ 0x784c, 0x786a, 0x789b, 0x7893, 0x789a, 0x7887, 0x789c, 0x78a1,
+ 0x78a3, 0x78b2, 0x78b9, 0x78a5, 0x78d4, 0x78d9, 0x78c9, 0x78ec,
+ 0x78f2, 0x7905, 0x78f4, 0x7913, 0x7924, 0x791e, 0x7934, 0x9f9b,
+ 0x9ef9, 0x9efb, 0x9efc, 0x76f1, 0x7704, 0x770d, 0x76f9, 0x7707,
+ 0x7708, 0x771a, 0x7722, 0x7719, 0x772d, 0x7726, 0x7735, 0x7738,
+ 0x7750, 0x7751, 0x7747, 0x7743, 0x775a, 0x7768, 0x7762, 0x7765,
+ 0x777f, 0x778d, 0x777d, 0x7780, 0x778c, 0x7791, 0x779f, 0x77a0,
+ 0x77b0, 0x77b5, 0x77bd, 0x753a, 0x7540, 0x754e, 0x754b, 0x7548,
+ 0x755b, 0x7572, 0x7579, 0x7583, 0x7f58, 0x7f61, 0x7f5f, 0x8a48,
+ 0x7f68, 0x7f74, 0x7f71, 0x7f79, 0x7f81, 0x7f7e, 0x76cd, 0x76e5,
+ 0x8832, 0x9485, 0x9486, 0x9487, 0x948b, 0x948a, 0x948c, 0x948d,
+ 0x948f, 0x9490, 0x9494, 0x9497, 0x9495, 0x949a, 0x949b, 0x949c,
+ 0x94a3, 0x94a4, 0x94ab, 0x94aa, 0x94ad, 0x94ac, 0x94af, 0x94b0,
+ 0x94b2, 0x94b4, 0x94b6, 0x94b7, 0x94b8, 0x94b9, 0x94ba, 0x94bc,
+ 0x94bd, 0x94bf, 0x94c4, 0x94c8, 0x94c9, 0x94ca, 0x94cb, 0x94cc,
+ 0x94cd, 0x94ce, 0x94d0, 0x94d1, 0x94d2, 0x94d5, 0x94d6, 0x94d7,
+ 0x94d9, 0x94d8, 0x94db, 0x94de, 0x94df, 0x94e0, 0x94e2, 0x94e4,
+ 0x94e5, 0x94e7, 0x94e8, 0x94ea, 0x94e9, 0x94eb, 0x94ee, 0x94ef,
+ 0x94f3, 0x94f4, 0x94f5, 0x94f7, 0x94f9, 0x94fc, 0x94fd, 0x94ff,
+ 0x9503, 0x9502, 0x9506, 0x9507, 0x9509, 0x950a, 0x950d, 0x950e,
+ 0x950f, 0x9512, 0x9513, 0x9514, 0x9515, 0x9516, 0x9518, 0x951b,
+ 0x951d, 0x951e, 0x951f, 0x9522, 0x952a, 0x952b, 0x9529, 0x952c,
+ 0x9531, 0x9532, 0x9534, 0x9536, 0x9537, 0x9538, 0x953c, 0x953e,
+ 0x953f, 0x9542, 0x9535, 0x9544, 0x9545, 0x9546, 0x9549, 0x954c,
+ 0x954e, 0x954f, 0x9552, 0x9553, 0x9554, 0x9556, 0x9557, 0x9558,
+ 0x9559, 0x955b, 0x955e, 0x955f, 0x955d, 0x9561, 0x9562, 0x9564,
+ 0x9565, 0x9566, 0x9567, 0x9568, 0x9569, 0x956a, 0x956b, 0x956c,
+ 0x956f, 0x9571, 0x9572, 0x9573, 0x953a, 0x77e7, 0x77ec, 0x96c9,
+ 0x79d5, 0x79ed, 0x79e3, 0x79eb, 0x7a06, 0x5d47, 0x7a03, 0x7a02,
+ 0x7a1e, 0x7a14, 0x7a39, 0x7a37, 0x7a51, 0x9ecf, 0x99a5, 0x7a70,
+ 0x7688, 0x768e, 0x7693, 0x7699, 0x76a4, 0x74de, 0x74e0, 0x752c,
+ 0x9e20, 0x9e22, 0x9e28, 0x9e29, 0x9e2a, 0x9e2b, 0x9e2c, 0x9e32,
+ 0x9e31, 0x9e36, 0x9e38, 0x9e37, 0x9e39, 0x9e3a, 0x9e3e, 0x9e41,
+ 0x9e42, 0x9e44, 0x9e46, 0x9e47, 0x9e48, 0x9e49, 0x9e4b, 0x9e4c,
+ 0x9e4e, 0x9e51, 0x9e55, 0x9e57, 0x9e5a, 0x9e5b, 0x9e5c, 0x9e5e,
+ 0x9e63, 0x9e66, 0x9e67, 0x9e68, 0x9e69, 0x9e6a, 0x9e6b, 0x9e6c,
+ 0x9e71, 0x9e6d, 0x9e73, 0x7592, 0x7594, 0x7596, 0x75a0, 0x759d,
+ 0x75ac, 0x75a3, 0x75b3, 0x75b4, 0x75b8, 0x75c4, 0x75b1, 0x75b0,
+ 0x75c3, 0x75c2, 0x75d6, 0x75cd, 0x75e3, 0x75e8, 0x75e6, 0x75e4,
+ 0x75eb, 0x75e7, 0x7603, 0x75f1, 0x75fc, 0x75ff, 0x7610, 0x7600,
+ 0x7605, 0x760c, 0x7617, 0x760a, 0x7625, 0x7618, 0x7615, 0x7619,
+ 0x761b, 0x763c, 0x7622, 0x7620, 0x7640, 0x762d, 0x7630, 0x763f,
+ 0x7635, 0x7643, 0x763e, 0x7633, 0x764d, 0x765e, 0x7654, 0x765c,
+ 0x7656, 0x766b, 0x766f, 0x7fca, 0x7ae6, 0x7a78, 0x7a79, 0x7a80,
+ 0x7a86, 0x7a88, 0x7a95, 0x7aa6, 0x7aa0, 0x7aac, 0x7aa8, 0x7aad,
+ 0x7ab3, 0x8864, 0x8869, 0x8872, 0x887d, 0x887f, 0x8882, 0x88a2,
+ 0x88c6, 0x88b7, 0x88bc, 0x88c9, 0x88e2, 0x88ce, 0x88e3, 0x88e5,
+ 0x88f1, 0x891a, 0x88fc, 0x88e8, 0x88fe, 0x88f0, 0x8921, 0x8919,
+ 0x8913, 0x891b, 0x890a, 0x8934, 0x892b, 0x8936, 0x8941, 0x8966,
+ 0x897b, 0x758b, 0x80e5, 0x76b2, 0x76b4, 0x77dc, 0x8012, 0x8014,
+ 0x8016, 0x801c, 0x8020, 0x8022, 0x8025, 0x8026, 0x8027, 0x8029,
+ 0x8028, 0x8031, 0x800b, 0x8035, 0x8043, 0x8046, 0x804d, 0x8052,
+ 0x8069, 0x8071, 0x8983, 0x9878, 0x9880, 0x9883, 0x9889, 0x988c,
+ 0x988d, 0x988f, 0x9894, 0x989a, 0x989b, 0x989e, 0x989f, 0x98a1,
+ 0x98a2, 0x98a5, 0x98a6, 0x864d, 0x8654, 0x866c, 0x866e, 0x867f,
+ 0x867a, 0x867c, 0x867b, 0x86a8, 0x868d, 0x868b, 0x86ac, 0x869d,
+ 0x86a7, 0x86a3, 0x86aa, 0x8693, 0x86a9, 0x86b6, 0x86c4, 0x86b5,
+ 0x86ce, 0x86b0, 0x86ba, 0x86b1, 0x86af, 0x86c9, 0x86cf, 0x86b4,
+ 0x86e9, 0x86f1, 0x86f2, 0x86ed, 0x86f3, 0x86d0, 0x8713, 0x86de,
+ 0x86f4, 0x86df, 0x86d8, 0x86d1, 0x8703, 0x8707, 0x86f8, 0x8708,
+ 0x870a, 0x870d, 0x8709, 0x8723, 0x873b, 0x871e, 0x8725, 0x872e,
+ 0x871a, 0x873e, 0x8748, 0x8734, 0x8731, 0x8729, 0x8737, 0x873f,
+ 0x8782, 0x8722, 0x877d, 0x877e, 0x877b, 0x8760, 0x8770, 0x874c,
+ 0x876e, 0x878b, 0x8753, 0x8763, 0x877c, 0x8764, 0x8759, 0x8765,
+ 0x8793, 0x87af, 0x87a8, 0x87d2, 0x87c6, 0x8788, 0x8785, 0x87ad,
+ 0x8797, 0x8783, 0x87ab, 0x87e5, 0x87ac, 0x87b5, 0x87b3, 0x87cb,
+ 0x87d3, 0x87bd, 0x87d1, 0x87c0, 0x87ca, 0x87db, 0x87ea, 0x87e0,
+ 0x87ee, 0x8816, 0x8813, 0x87fe, 0x880a, 0x881b, 0x8821, 0x8839,
+ 0x883c, 0x7f36, 0x7f42, 0x7f44, 0x7f45, 0x8210, 0x7afa, 0x7afd,
+ 0x7b08, 0x7b03, 0x7b04, 0x7b15, 0x7b0a, 0x7b2b, 0x7b0f, 0x7b47,
+ 0x7b38, 0x7b2a, 0x7b19, 0x7b2e, 0x7b31, 0x7b20, 0x7b25, 0x7b24,
+ 0x7b33, 0x7b3e, 0x7b1e, 0x7b58, 0x7b5a, 0x7b45, 0x7b75, 0x7b4c,
+ 0x7b5d, 0x7b60, 0x7b6e, 0x7b7b, 0x7b62, 0x7b72, 0x7b71, 0x7b90,
+ 0x7ba6, 0x7ba7, 0x7bb8, 0x7bac, 0x7b9d, 0x7ba8, 0x7b85, 0x7baa,
+ 0x7b9c, 0x7ba2, 0x7bab, 0x7bb4, 0x7bd1, 0x7bc1, 0x7bcc, 0x7bdd,
+ 0x7bda, 0x7be5, 0x7be6, 0x7bea, 0x7c0c, 0x7bfe, 0x7bfc, 0x7c0f,
+ 0x7c16, 0x7c0b, 0x7c1f, 0x7c2a, 0x7c26, 0x7c38, 0x7c41, 0x7c40,
+ 0x81fe, 0x8201, 0x8202, 0x8204, 0x81ec, 0x8844, 0x8221, 0x8222,
+ 0x8223, 0x822d, 0x822f, 0x8228, 0x822b, 0x8238, 0x823b, 0x8233,
+ 0x8234, 0x823e, 0x8244, 0x8249, 0x824b, 0x824f, 0x825a, 0x825f,
+ 0x8268, 0x887e, 0x8885, 0x8888, 0x88d8, 0x88df, 0x895e, 0x7f9d,
+ 0x7f9f, 0x7fa7, 0x7faf, 0x7fb0, 0x7fb2, 0x7c7c, 0x6549, 0x7c91,
+ 0x7c9d, 0x7c9c, 0x7c9e, 0x7ca2, 0x7cb2, 0x7cbc, 0x7cbd, 0x7cc1,
+ 0x7cc7, 0x7ccc, 0x7ccd, 0x7cc8, 0x7cc5, 0x7cd7, 0x7ce8, 0x826e,
+ 0x66a8, 0x7fbf, 0x7fce, 0x7fd5, 0x7fe5, 0x7fe1, 0x7fe6, 0x7fe9,
+ 0x7fee, 0x7ff3, 0x7cf8, 0x7d77, 0x7da6, 0x7dae, 0x7e47, 0x7e9b,
+ 0x9eb8, 0x9eb4, 0x8d73, 0x8d84, 0x8d94, 0x8d91, 0x8db1, 0x8d67,
+ 0x8d6d, 0x8c47, 0x8c49, 0x914a, 0x9150, 0x914e, 0x914f, 0x9164,
+ 0x9162, 0x9161, 0x9170, 0x9169, 0x916f, 0x917d, 0x917e, 0x9172,
+ 0x9174, 0x9179, 0x918c, 0x9185, 0x9190, 0x918d, 0x9191, 0x91a2,
+ 0x91a3, 0x91aa, 0x91ad, 0x91ae, 0x91af, 0x91b5, 0x91b4, 0x91ba,
+ 0x8c55, 0x9e7e, 0x8db8, 0x8deb, 0x8e05, 0x8e59, 0x8e69, 0x8db5,
+ 0x8dbf, 0x8dbc, 0x8dba, 0x8dc4, 0x8dd6, 0x8dd7, 0x8dda, 0x8dde,
+ 0x8dce, 0x8dcf, 0x8ddb, 0x8dc6, 0x8dec, 0x8df7, 0x8df8, 0x8de3,
+ 0x8df9, 0x8dfb, 0x8de4, 0x8e09, 0x8dfd, 0x8e14, 0x8e1d, 0x8e1f,
+ 0x8e2c, 0x8e2e, 0x8e23, 0x8e2f, 0x8e3a, 0x8e40, 0x8e39, 0x8e35,
+ 0x8e3d, 0x8e31, 0x8e49, 0x8e41, 0x8e42, 0x8e51, 0x8e52, 0x8e4a,
+ 0x8e70, 0x8e76, 0x8e7c, 0x8e6f, 0x8e74, 0x8e85, 0x8e8f, 0x8e94,
+ 0x8e90, 0x8e9c, 0x8e9e, 0x8c78, 0x8c82, 0x8c8a, 0x8c85, 0x8c98,
+ 0x8c94, 0x659b, 0x89d6, 0x89de, 0x89da, 0x89dc, 0x89e5, 0x89eb,
+ 0x89ef, 0x8a3e, 0x8b26, 0x9753, 0x96e9, 0x96f3, 0x96ef, 0x9706,
+ 0x9701, 0x9708, 0x970f, 0x970e, 0x972a, 0x972d, 0x9730, 0x973e,
+ 0x9f80, 0x9f83, 0x9f85, 0x9f86, 0x9f87, 0x9f88, 0x9f89, 0x9f8a,
+ 0x9f8c, 0x9efe, 0x9f0b, 0x9f0d, 0x96b9, 0x96bc, 0x96bd, 0x96ce,
+ 0x96d2, 0x77bf, 0x96e0, 0x928e, 0x92ae, 0x92c8, 0x933e, 0x936a,
+ 0x93ca, 0x938f, 0x943e, 0x946b, 0x9c7f, 0x9c82, 0x9c85, 0x9c86,
+ 0x9c87, 0x9c88, 0x7a23, 0x9c8b, 0x9c8e, 0x9c90, 0x9c91, 0x9c92,
+ 0x9c94, 0x9c95, 0x9c9a, 0x9c9b, 0x9c9e, 0x9c9f, 0x9ca0, 0x9ca1,
+ 0x9ca2, 0x9ca3, 0x9ca5, 0x9ca6, 0x9ca7, 0x9ca8, 0x9ca9, 0x9cab,
+ 0x9cad, 0x9cae, 0x9cb0, 0x9cb1, 0x9cb2, 0x9cb3, 0x9cb4, 0x9cb5,
+ 0x9cb6, 0x9cb7, 0x9cba, 0x9cbb, 0x9cbc, 0x9cbd, 0x9cc4, 0x9cc5,
+ 0x9cc6, 0x9cc7, 0x9cca, 0x9ccb, 0x9ccc, 0x9ccd, 0x9cce, 0x9ccf,
+ 0x9cd0, 0x9cd3, 0x9cd4, 0x9cd5, 0x9cd7, 0x9cd8, 0x9cd9, 0x9cdc,
+ 0x9cdd, 0x9cdf, 0x9ce2, 0x977c, 0x9785, 0x9791, 0x9792, 0x9794,
+ 0x97af, 0x97ab, 0x97a3, 0x97b2, 0x97b4, 0x9ab1, 0x9ab0, 0x9ab7,
+ 0x9e58, 0x9ab6, 0x9aba, 0x9abc, 0x9ac1, 0x9ac0, 0x9ac5, 0x9ac2,
+ 0x9acb, 0x9acc, 0x9ad1, 0x9b45, 0x9b43, 0x9b47, 0x9b49, 0x9b48,
+ 0x9b4d, 0x9b51, 0x98e8, 0x990d, 0x992e, 0x9955, 0x9954, 0x9adf,
+ 0x9ae1, 0x9ae6, 0x9aef, 0x9aeb, 0x9afb, 0x9aed, 0x9af9, 0x9b08,
+ 0x9b0f, 0x9b13, 0x9b1f, 0x9b23, 0x9ebd, 0x9ebe, 0x7e3b, 0x9e82,
+ 0x9e87, 0x9e88, 0x9e8b, 0x9e92, 0x93d6, 0x9e9d, 0x9e9f, 0x9edb,
+ 0x9edc, 0x9edd, 0x9ee0, 0x9edf, 0x9ee2, 0x9ee9, 0x9ee7, 0x9ee5,
+ 0x9eea, 0x9eef, 0x9f22, 0x9f2c, 0x9f2f, 0x9f39, 0x9f37, 0x9f3d,
+ 0x9f3e, 0x9f44, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x9f44, 0xffffffff, 0x00ff, 0x0000,
+ 0x0100, 0x0003, 0x2288, 0x804f240, 0x0100, 0x0005, 0x00f8, 0x42130a14
+};
+
+#ifndef LUA_FF_LIB
+
+static unsigned short gb2312_from_unicode_0[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2168, 0x0000, 0x0000, 0x216c,
+ 0x2127, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2163, 0x2140, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2141,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2824, 0x2822, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2828, 0x2826, 0x283a, 0x0000, 0x282c, 0x282a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2830, 0x282e, 0x0000, 0x0000, 0x0000, 0x2142,
+ 0x0000, 0x2834, 0x2832, 0x0000, 0x2839, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_1[] = {
+ 0x0000, 0x2821, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2825, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2827, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2829, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x283d, 0x0000, 0x0000, 0x0000,
+ 0x283e, 0x0000, 0x0000, 0x0000, 0x0000, 0x282d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2831, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2823, 0x0000,
+ 0x282b, 0x0000, 0x282f, 0x0000, 0x2833, 0x0000, 0x2835, 0x0000,
+ 0x2836, 0x0000, 0x2837, 0x0000, 0x2838, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x283f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_2[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x283b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2840, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2126,
+ 0x0000, 0x2125, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_3[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2621, 0x2622, 0x2623, 0x2624, 0x2625, 0x2626, 0x2627,
+ 0x2628, 0x2629, 0x262a, 0x262b, 0x262c, 0x262d, 0x262e, 0x262f,
+ 0x2630, 0x2631, 0x0000, 0x2632, 0x2633, 0x2634, 0x2635, 0x2636,
+ 0x2637, 0x2638, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2641, 0x2642, 0x2643, 0x2644, 0x2645, 0x2646, 0x2647,
+ 0x2648, 0x2649, 0x264a, 0x264b, 0x264c, 0x264d, 0x264e, 0x264f,
+ 0x2650, 0x2651, 0x0000, 0x2652, 0x2653, 0x2654, 0x2655, 0x2656,
+ 0x2657, 0x2658, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_4[] = {
+ 0x0000, 0x2727, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2721, 0x2722, 0x2723, 0x2724, 0x2725, 0x2726, 0x2728, 0x2729,
+ 0x272a, 0x272b, 0x272c, 0x272d, 0x272e, 0x272f, 0x2730, 0x2731,
+ 0x2732, 0x2733, 0x2734, 0x2735, 0x2736, 0x2737, 0x2738, 0x2739,
+ 0x273a, 0x273b, 0x273c, 0x273d, 0x273e, 0x273f, 0x2740, 0x2741,
+ 0x2751, 0x2752, 0x2753, 0x2754, 0x2755, 0x2756, 0x2758, 0x2759,
+ 0x275a, 0x275b, 0x275c, 0x275d, 0x275e, 0x275f, 0x2760, 0x2761,
+ 0x2762, 0x2763, 0x2764, 0x2765, 0x2766, 0x2767, 0x2768, 0x2769,
+ 0x276a, 0x276b, 0x276c, 0x276d, 0x276e, 0x276f, 0x2770, 0x2771,
+ 0x0000, 0x2757, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_1e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x283c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_20[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x212a, 0x0000, 0x212c, 0x0000,
+ 0x212e, 0x212f, 0x0000, 0x0000, 0x2130, 0x2131, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x212d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x216b, 0x0000, 0x2164, 0x2165, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2179, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_21[] = {
+ 0x0000, 0x0000, 0x0000, 0x2166, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x216d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2271, 0x2272, 0x2273, 0x2274, 0x2275, 0x2276, 0x2277, 0x2278,
+ 0x2279, 0x227a, 0x227b, 0x227c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x217b, 0x217c, 0x217a, 0x217d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_22[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x214a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2147,
+ 0x0000, 0x2146, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x214c, 0x0000, 0x0000, 0x2158, 0x215e, 0x0000,
+ 0x214f, 0x0000, 0x0000, 0x0000, 0x0000, 0x214e, 0x0000, 0x2144,
+ 0x2145, 0x2149, 0x2148, 0x2152, 0x0000, 0x0000, 0x2153, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2160, 0x215f, 0x2143, 0x214b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2157, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2156, 0x0000, 0x0000, 0x0000, 0x2155, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2159, 0x2154, 0x0000, 0x0000, 0x215c, 0x215d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x215a, 0x215b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2151, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x214d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_23[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2150, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_24[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2259, 0x225a, 0x225b, 0x225c, 0x225d, 0x225e, 0x225f, 0x2260,
+ 0x2261, 0x2262, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2245, 0x2246, 0x2247, 0x2248,
+ 0x2249, 0x224a, 0x224b, 0x224c, 0x224d, 0x224e, 0x224f, 0x2250,
+ 0x2251, 0x2252, 0x2253, 0x2254, 0x2255, 0x2256, 0x2257, 0x2258,
+ 0x2231, 0x2232, 0x2233, 0x2234, 0x2235, 0x2236, 0x2237, 0x2238,
+ 0x2239, 0x223a, 0x223b, 0x223c, 0x223d, 0x223e, 0x223f, 0x2240,
+ 0x2241, 0x2242, 0x2243, 0x2244, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_25[] = {
+ 0x2924, 0x2925, 0x2926, 0x2927, 0x2928, 0x2929, 0x292a, 0x292b,
+ 0x292c, 0x292d, 0x292e, 0x292f, 0x2930, 0x2931, 0x2932, 0x2933,
+ 0x2934, 0x2935, 0x2936, 0x2937, 0x2938, 0x2939, 0x293a, 0x293b,
+ 0x293c, 0x293d, 0x293e, 0x293f, 0x2940, 0x2941, 0x2942, 0x2943,
+ 0x2944, 0x2945, 0x2946, 0x2947, 0x2948, 0x2949, 0x294a, 0x294b,
+ 0x294c, 0x294d, 0x294e, 0x294f, 0x2950, 0x2951, 0x2952, 0x2953,
+ 0x2954, 0x2955, 0x2956, 0x2957, 0x2958, 0x2959, 0x295a, 0x295b,
+ 0x295c, 0x295d, 0x295e, 0x295f, 0x2960, 0x2961, 0x2962, 0x2963,
+ 0x2964, 0x2965, 0x2966, 0x2967, 0x2968, 0x2969, 0x296a, 0x296b,
+ 0x296c, 0x296d, 0x296e, 0x296f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2176, 0x2175, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2178, 0x2177, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2174, 0x2173,
+ 0x0000, 0x0000, 0x0000, 0x2170, 0x0000, 0x0000, 0x2172, 0x2171,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_26[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x216f, 0x216e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2162, 0x0000, 0x2161, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_30[] = {
+ 0x2121, 0x2122, 0x2123, 0x2128, 0x0000, 0x2129, 0x0000, 0x0000,
+ 0x2134, 0x2135, 0x2136, 0x2137, 0x2138, 0x2139, 0x213a, 0x213b,
+ 0x213e, 0x213f, 0x0000, 0x217e, 0x2132, 0x2133, 0x213c, 0x213d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427,
+ 0x2428, 0x2429, 0x242a, 0x242b, 0x242c, 0x242d, 0x242e, 0x242f,
+ 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437,
+ 0x2438, 0x2439, 0x243a, 0x243b, 0x243c, 0x243d, 0x243e, 0x243f,
+ 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447,
+ 0x2448, 0x2449, 0x244a, 0x244b, 0x244c, 0x244d, 0x244e, 0x244f,
+ 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457,
+ 0x2458, 0x2459, 0x245a, 0x245b, 0x245c, 0x245d, 0x245e, 0x245f,
+ 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467,
+ 0x2468, 0x2469, 0x246a, 0x246b, 0x246c, 0x246d, 0x246e, 0x246f,
+ 0x2470, 0x2471, 0x2472, 0x2473, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527,
+ 0x2528, 0x2529, 0x252a, 0x252b, 0x252c, 0x252d, 0x252e, 0x252f,
+ 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537,
+ 0x2538, 0x2539, 0x253a, 0x253b, 0x253c, 0x253d, 0x253e, 0x253f,
+ 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547,
+ 0x2548, 0x2549, 0x254a, 0x254b, 0x254c, 0x254d, 0x254e, 0x254f,
+ 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557,
+ 0x2558, 0x2559, 0x255a, 0x255b, 0x255c, 0x255d, 0x255e, 0x255f,
+ 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567,
+ 0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x256d, 0x256e, 0x256f,
+ 0x2570, 0x2571, 0x2572, 0x2573, 0x2574, 0x2575, 0x2576, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2124, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_31[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2845, 0x2846, 0x2847,
+ 0x2848, 0x2849, 0x284a, 0x284b, 0x284c, 0x284d, 0x284e, 0x284f,
+ 0x2850, 0x2851, 0x2852, 0x2853, 0x2854, 0x2855, 0x2856, 0x2857,
+ 0x2858, 0x2859, 0x285a, 0x285b, 0x285c, 0x285d, 0x285e, 0x285f,
+ 0x2860, 0x2861, 0x2862, 0x2863, 0x2864, 0x2865, 0x2866, 0x2867,
+ 0x2868, 0x2869, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_32[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2265, 0x2266, 0x2267, 0x2268, 0x2269, 0x226a, 0x226b, 0x226c,
+ 0x226d, 0x226e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_4e[] = {
+ 0x523b, 0x3621, 0x0000, 0x465f, 0x0000, 0x0000, 0x0000, 0x4d72,
+ 0x5549, 0x487d, 0x494f, 0x4f42, 0x5822, 0x323b, 0x536b, 0x0000,
+ 0x5824, 0x3373, 0x0000, 0x5728, 0x4752, 0x5827, 0x4a40, 0x0000,
+ 0x4770, 0x317b, 0x5235, 0x3454, 0x362b, 0x4b3f, 0x5829, 0x0000,
+ 0x0000, 0x0000, 0x362a, 0x0000, 0x413d, 0x514f, 0x0000, 0x4925,
+ 0x582d, 0x0000, 0x3876, 0x513e, 0x635c, 0x5650, 0x0000, 0x0000,
+ 0x3761, 0x0000, 0x342e, 0x0000, 0x4159, 0x0000, 0x583c, 0x0000,
+ 0x4d68, 0x3524, 0x4e2a, 0x5677, 0x0000, 0x4076, 0x3e59, 0x582f,
+ 0x0000, 0x0000, 0x0000, 0x444b, 0x0000, 0x3e43, 0x0000, 0x5831,
+ 0x4334, 0x5265, 0x0000, 0x562e, 0x4e5a, 0x5527, 0x3a75, 0x3726,
+ 0x4056, 0x0000, 0x4639, 0x4552, 0x4747, 0x0000, 0x3954, 0x0000,
+ 0x334b, 0x5252, 0x0000, 0x0000, 0x583f, 0x3e45, 0x4672, 0x5232,
+ 0x4f30, 0x4f67, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a69, 0x0000,
+ 0x0000, 0x5840, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4272, 0x4252, 0x0000, 0x4869, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x472c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x414b, 0x0000,
+ 0x5368, 0x5579, 0x0000, 0x4a42, 0x367e, 0x5821, 0x535a, 0x3f77,
+ 0x0000, 0x5446, 0x3b25, 0x5841, 0x4e65, 0x3e2e, 0x0000, 0x0000,
+ 0x5828, 0x0000, 0x5147, 0x5029, 0x0000, 0x0000, 0x0000, 0x583d,
+ 0x596f, 0x4d76, 0x3f3a, 0x0000, 0x3d3b, 0x3a25, 0x5260, 0x327a,
+ 0x3a60, 0x4436, 0x0000, 0x4f6d, 0x3e29, 0x4d24, 0x4141, 0x0000,
+ 0x0000, 0x0000, 0x4757, 0x5971, 0x0000, 0x5974, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x484b, 0x5869, 0x0000, 0x0000, 0x0000, 0x525a,
+ 0x4a32, 0x484a, 0x586c, 0x586a, 0x5846, 0x3d76, 0x464d, 0x3370,
+ 0x0000, 0x586b, 0x3d71, 0x3d69, 0x0000, 0x4854, 0x3453, 0x0000,
+ 0x0000, 0x4258, 0x0000, 0x3256, 0x5750, 0x4a4b, 0x4b7b, 0x554c,
+ 0x3836, 0x4f49, 0x0000, 0x0000, 0x0000, 0x595a, 0x5870, 0x472a,
+ 0x0000, 0x586e, 0x0000, 0x347a, 0x416e, 0x5254, 0x0000, 0x0000,
+ 0x586d, 0x0000, 0x5247, 0x586f, 0x4347, 0x0000, 0x0000, 0x0000,
+ 0x5176, 0x0000, 0x5659, 0x5872, 0x0000, 0x5875, 0x3c7e, 0x3c5b,
+ 0x0000, 0x0000, 0x0000, 0x484e, 0x0000, 0x375d, 0x0000, 0x3742
+};
+
+static unsigned short gb2312_from_unicode_4f[] = {
+ 0x0000, 0x4673, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5878, 0x5241, 0x0000, 0x0000, 0x4e69, 0x3c3f, 0x377c,
+ 0x3725, 0x505d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x565a,
+ 0x5345, 0x3b6f, 0x3b61, 0x5871, 0x0000, 0x0000, 0x4921, 0x4e30,
+ 0x342b, 0x0000, 0x5873, 0x0000, 0x494b, 0x5876, 0x4257, 0x5877,
+ 0x0000, 0x0000, 0x4e31, 0x5879, 0x0000, 0x0000, 0x0000, 0x322e,
+ 0x3940, 0x0000, 0x5923, 0x0000, 0x3069, 0x0000, 0x4166, 0x0000,
+ 0x496c, 0x0000, 0x4b45, 0x0000, 0x4b46, 0x5924, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3568, 0x0000, 0x0000, 0x352b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e3b, 0x354d, 0x5721,
+ 0x5774, 0x5353, 0x0000, 0x4c65, 0x0000, 0x3a4e, 0x0000, 0x5922,
+ 0x595c, 0x5360, 0x587d, 0x3770, 0x5777, 0x587e, 0x587a, 0x5921,
+ 0x4463, 0x0000, 0x0000, 0x5336, 0x5874, 0x595d, 0x0000, 0x587b,
+ 0x0000, 0x4565, 0x0000, 0x0000, 0x4050, 0x0000, 0x0000, 0x5170,
+ 0x305b, 0x0000, 0x0000, 0x3c51, 0x5926, 0x0000, 0x5925, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x592c, 0x592e, 0x0000, 0x592b, 0x4a39,
+ 0x0000, 0x0000, 0x0000, 0x5929, 0x5636, 0x0000, 0x0000, 0x0000,
+ 0x335e, 0x5928, 0x0000, 0x407d, 0x0000, 0x4a4c, 0x0000, 0x592a,
+ 0x0000, 0x5927, 0x0000, 0x0000, 0x5930, 0x0000, 0x0000, 0x3631,
+ 0x0000, 0x0000, 0x0000, 0x3929, 0x0000, 0x5240, 0x0000, 0x0000,
+ 0x4f40, 0x0000, 0x0000, 0x4242, 0x0000, 0x3d44, 0x556c, 0x3260,
+ 0x4748, 0x3f6b, 0x592d, 0x0000, 0x592f, 0x0000, 0x4e6a, 0x3a6e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4756, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3163,
+ 0x0000, 0x0000, 0x0000, 0x3459, 0x366d, 0x5934, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3f21, 0x0000, 0x0000, 0x0000, 0x595e, 0x474e,
+ 0x407e, 0x5938, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b57,
+ 0x377d, 0x0000, 0x5935, 0x0000, 0x5937, 0x3123, 0x5361, 0x5939,
+ 0x0000, 0x5045, 0x0000, 0x5936, 0x0000, 0x0000, 0x5931, 0x0000,
+ 0x5932, 0x4129, 0x5933, 0x0000, 0x0000, 0x3c73, 0x505e, 0x3829,
+ 0x0000, 0x3e63, 0x0000, 0x593d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x593a, 0x0000, 0x3033, 0x0000, 0x0000, 0x0000, 0x5942, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_50[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5944, 0x3136, 0x0000, 0x593f,
+ 0x0000, 0x0000, 0x3539, 0x0000, 0x3e73, 0x0000, 0x0000, 0x0000,
+ 0x4c48, 0x3a72, 0x5250, 0x0000, 0x5943, 0x0000, 0x0000, 0x3d68,
+ 0x0000, 0x332b, 0x0000, 0x0000, 0x0000, 0x5945, 0x3e6b, 0x0000,
+ 0x5946, 0x593b, 0x445f, 0x0000, 0x593e, 0x5941, 0x5940, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x552e, 0x0000, 0x5635, 0x0000, 0x4763, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5948, 0x0000, 0x0000, 0x0000, 0x3c59,
+ 0x594a, 0x0000, 0x0000, 0x0000, 0x593c, 0x0000, 0x594b, 0x462b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5949, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5776, 0x0000, 0x4d23, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3d21, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x594c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x453c, 0x4d35,
+ 0x0000, 0x0000, 0x0000, 0x594d, 0x0000, 0x0000, 0x5947, 0x3325,
+ 0x3f7e, 0x0000, 0x0000, 0x0000, 0x0000, 0x3835, 0x0000, 0x0000,
+ 0x407c, 0x0000, 0x0000, 0x0000, 0x0000, 0x3078, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3476, 0x0000, 0x594e, 0x0000, 0x594f,
+ 0x3422, 0x5950, 0x0000, 0x0000, 0x345f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3041, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5951, 0x4935, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4f71,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5952, 0x0000,
+ 0x0000, 0x0000, 0x4145, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5956, 0x492e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5955, 0x5954, 0x5957, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4b5b, 0x0000, 0x3d29, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4627, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_51[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5953, 0x5958,
+ 0x0000, 0x0000, 0x0000, 0x5959, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4865, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x405c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3679,
+ 0x5823, 0x544a, 0x0000, 0x542a, 0x5056, 0x3364, 0x5557, 0x0000,
+ 0x4f48, 0x3962, 0x0000, 0x3f4b, 0x0000, 0x4362, 0x0000, 0x0000,
+ 0x0000, 0x3652, 0x0000, 0x0000, 0x4d43, 0x596e, 0x5970, 0x0000,
+ 0x0000, 0x0000, 0x3533, 0x0000, 0x3635, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3e24, 0x0000, 0x0000, 0x486b, 0x0000, 0x0000,
+ 0x482b, 0x0000, 0x0000, 0x304b, 0x392b, 0x4179, 0x5962, 0x0000,
+ 0x403c, 0x3932, 0x0000, 0x3958, 0x504b, 0x3178, 0x4664, 0x3e5f,
+ 0x3564, 0x5748, 0x0000, 0x5178, 0x3c66, 0x4a5e, 0x0000, 0x0000,
+ 0x3c3d, 0x5966, 0x5867, 0x0000, 0x0000, 0x445a, 0x0000, 0x0000,
+ 0x3854, 0x483d, 0x0000, 0x0000, 0x3261, 0x5459, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4330, 0x0000, 0x0000, 0x4361, 0x5a22, 0x485f,
+ 0x0000, 0x5034, 0x0000, 0x3e7c, 0x4529, 0x0000, 0x0000, 0x0000,
+ 0x395a, 0x0000, 0x5a23, 0x0000, 0x5429, 0x5a24, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x597b, 0x362c, 0x0000, 0x0000, 0x376b,
+ 0x3179, 0x597c, 0x3365, 0x3e76, 0x0000, 0x3f76, 0x5231, 0x4064,
+ 0x0000, 0x0000, 0x0000, 0x3633, 0x597e, 0x597d, 0x0000, 0x0000,
+ 0x3e3b, 0x0000, 0x0000, 0x0000, 0x4660, 0x0000, 0x573c, 0x5a21,
+ 0x0000, 0x4139, 0x0000, 0x3572, 0x4168, 0x0000, 0x0000, 0x3c75,
+ 0x0000, 0x3455, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x415d, 0x0000, 0x447d, 0x0000, 0x0000,
+ 0x3c38, 0x3732, 0x0000, 0x0000, 0x376f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x596c, 0x0000, 0x463e, 0x0000, 0x3f2d,
+ 0x3b4b, 0x0000, 0x0000, 0x354a, 0x0000, 0x5b49, 0x5057, 0x0000,
+ 0x4d39, 0x303c, 0x3376, 0x3b77, 0x5b4a, 0x3a2f, 0x0000, 0x5464
+};
+
+static unsigned short gb2312_from_unicode_52[] = {
+ 0x3536, 0x3573, 0x5856, 0x4850, 0x0000, 0x0000, 0x3756, 0x4750,
+ 0x5857, 0x0000, 0x3f2f, 0x0000, 0x0000, 0x5b3b, 0x5858, 0x0000,
+ 0x0000, 0x504c, 0x3b2e, 0x0000, 0x0000, 0x0000, 0x6b3e, 0x4150,
+ 0x4175, 0x5472, 0x3855, 0x3434, 0x0000, 0x3375, 0x0000, 0x0000,
+ 0x493e, 0x0000, 0x0000, 0x0000, 0x4550, 0x0000, 0x0000, 0x0000,
+ 0x4559, 0x407b, 0x0000, 0x3170, 0x0000, 0x5859, 0x394e, 0x0000,
+ 0x353d, 0x0000, 0x0000, 0x585a, 0x0000, 0x0000, 0x5646, 0x4b22,
+ 0x482f, 0x4932, 0x344c, 0x3f4c, 0x0000, 0x3974, 0x0000, 0x585b,
+ 0x585c, 0x3667, 0x3c41, 0x4c6a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4f77, 0x0000, 0x585d, 0x4730, 0x0000, 0x0000,
+ 0x3950, 0x3d23, 0x0000, 0x0000, 0x4c5e, 0x0000, 0x464a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5860, 0x0000, 0x585e, 0x0000,
+ 0x0000, 0x585f, 0x0000, 0x0000, 0x0000, 0x307e, 0x0000, 0x3e67,
+ 0x0000, 0x4a23, 0x3c74, 0x0000, 0x0000, 0x0000, 0x0000, 0x3831,
+ 0x0000, 0x0000, 0x386e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5862, 0x0000, 0x3d4b,
+ 0x0000, 0x5864, 0x5863, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x457c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5865, 0x0000, 0x0000, 0x5866, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4126, 0x0000, 0x4830, 0x306c, 0x3926,
+ 0x3c53, 0x4e71, 0x5b3d, 0x4153, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x362f, 0x567a, 0x452c, 0x3d59, 0x5b3e, 0x5b3f, 0x0000, 0x0000,
+ 0x0000, 0x4078, 0x3e22, 0x404d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b40, 0x4a46,
+ 0x0000, 0x0000, 0x0000, 0x322a, 0x0000, 0x0000, 0x0000, 0x5342,
+ 0x0000, 0x4363, 0x0000, 0x512b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5b42, 0x0000, 0x4055, 0x0000, 0x0000, 0x0000, 0x5b43, 0x0000,
+ 0x3f31, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x443c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x475a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5b44, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5968, 0x4957, 0x0000, 0x0000, 0x0000, 0x3934, 0x4e70
+};
+
+static unsigned short gb2312_from_unicode_53[] = {
+ 0x5448, 0x0000, 0x0000, 0x0000, 0x0000, 0x307c, 0x3452, 0x0000,
+ 0x5059, 0x0000, 0x0000, 0x0000, 0x0000, 0x5969, 0x0000, 0x5e4b,
+ 0x596b, 0x0000, 0x0000, 0x0000, 0x0000, 0x5830, 0x3b2f, 0x3131,
+ 0x0000, 0x3357, 0x584e, 0x0000, 0x0000, 0x5451, 0x0000, 0x0000,
+ 0x3d33, 0x3f6f, 0x0000, 0x4f3b, 0x0000, 0x0000, 0x5850, 0x0000,
+ 0x0000, 0x0000, 0x374b, 0x0000, 0x0000, 0x0000, 0x5851, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4625, 0x4778, 0x523d, 0x0000, 0x0000, 0x5852, 0x4464,
+ 0x0000, 0x4a2e, 0x0000, 0x4727, 0x0000, 0x5826, 0x0000, 0x497d,
+ 0x4e67, 0x3b5c, 0x306b, 0x0000, 0x0000, 0x0000, 0x3b2a, 0x502d,
+ 0x0000, 0x3130, 0x5764, 0x573f, 0x0000, 0x3525, 0x4274, 0x444f,
+ 0x0000, 0x0000, 0x3229, 0x0000, 0x3237, 0x0000, 0x3165, 0x5f32,
+ 0x553c, 0x3f28, 0x422c, 0x5855, 0x4231, 0x0000, 0x5854, 0x4e54,
+ 0x0000, 0x5a60, 0x0000, 0x4e40, 0x0000, 0x0000, 0x5834, 0x432e,
+ 0x5321, 0x4e23, 0x0000, 0x3c34, 0x4834, 0x4251, 0x0000, 0x3e6d,
+ 0x5036, 0x0000, 0x5a61, 0x0000, 0x0000, 0x0000, 0x0000, 0x4764,
+ 0x0000, 0x0000, 0x3327, 0x0000, 0x3672, 0x4c7c, 0x407a, 0x0000,
+ 0x0000, 0x4077, 0x0000, 0x5139, 0x5161, 0x5847, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x325e, 0x0000, 0x0000,
+ 0x4065, 0x0000, 0x3a71, 0x0000, 0x0000, 0x5848, 0x0000, 0x542d,
+ 0x0000, 0x0000, 0x4f61, 0x5849, 0x0000, 0x584a, 0x4f43, 0x0000,
+ 0x3378, 0x3e47, 0x0000, 0x0000, 0x0000, 0x0000, 0x584b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b4c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4825, 0x0000, 0x0000, 0x0000, 0x4f58,
+ 0x0000, 0x487e, 0x324e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5356, 0x3266, 0x3c30, 0x5351, 0x4b2b, 0x3734, 0x0000, 0x0000,
+ 0x0000, 0x3722, 0x0000, 0x0000, 0x4a65, 0x0000, 0x4821, 0x4a5c,
+ 0x3164, 0x5070, 0x0000, 0x4551, 0x0000, 0x0000, 0x0000, 0x5b45,
+ 0x357e, 0x0000, 0x0000, 0x3f5a, 0x3945, 0x3e64, 0x416d, 0x0000,
+ 0x5f36, 0x5f35, 0x563b, 0x3d50, 0x5559, 0x3048, 0x3623, 0x3f49,
+ 0x4c28, 0x5f33, 0x4a37, 0x5352, 0x0000, 0x584f, 0x5236, 0x3a45,
+ 0x4b3e, 0x4c3e, 0x0000, 0x5f37, 0x3570, 0x5f34, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_54[] = {
+ 0x0000, 0x5375, 0x0000, 0x3354, 0x3877, 0x0000, 0x5f3a, 0x0000,
+ 0x3a4f, 0x3c2a, 0x3575, 0x0000, 0x4d2c, 0x437b, 0x3a73, 0x4074,
+ 0x4d42, 0x4f72, 0x5f38, 0x4f45, 0x0000, 0x4240, 0x5f39, 0x4270,
+ 0x0000, 0x0000, 0x0000, 0x3e7d, 0x0000, 0x415f, 0x4d4c, 0x5277,
+ 0x374d, 0x5f41, 0x0000, 0x5f44, 0x0000, 0x0000, 0x3771, 0x3049,
+ 0x3656, 0x3754, 0x0000, 0x3a2c, 0x4c7d, 0x3f54, 0x4b31, 0x4674,
+ 0x0000, 0x5628, 0x5f45, 0x0000, 0x4e62, 0x3333, 0x0000, 0x0000,
+ 0x4e7c, 0x3435, 0x0000, 0x4e47, 0x3a70, 0x0000, 0x4e61, 0x0000,
+ 0x513d, 0x0000, 0x0000, 0x5f40, 0x0000, 0x0000, 0x3474, 0x0000,
+ 0x334a, 0x0000, 0x3866, 0x5f3b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4445, 0x0000, 0x5f3c, 0x5f3d, 0x5f3e, 0x453b, 0x5f3f, 0x5f42,
+ 0x5431, 0x5f43, 0x0000, 0x473a, 0x4e58, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4458, 0x0000, 0x5f4a, 0x0000, 0x5f4f, 0x0000,
+ 0x565c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5f49, 0x5f5a, 0x4e36, 0x0000, 0x3a47, 0x5f4e, 0x5f48,
+ 0x455e, 0x0000, 0x0000, 0x496b, 0x3a74, 0x437c, 0x0000, 0x0000,
+ 0x3e57, 0x0000, 0x5f46, 0x0000, 0x5f4d, 0x0000, 0x4558, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5526, 0x3a4d, 0x0000, 0x3e4c, 0x533d,
+ 0x3840, 0x0000, 0x5664, 0x0000, 0x5f47, 0x393e, 0x3f27, 0x0000,
+ 0x0000, 0x417c, 0x5f4b, 0x5f4c, 0x0000, 0x5f50, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5f5b, 0x5f65, 0x0000, 0x5f57, 0x5f56,
+ 0x5749, 0x5f63, 0x5f64, 0x656b, 0x5227, 0x5f52, 0x0000, 0x3f29,
+ 0x0000, 0x545b, 0x0000, 0x3f48, 0x5f54, 0x0000, 0x0000, 0x0000,
+ 0x4f4c, 0x0000, 0x0000, 0x5f5d, 0x0000, 0x514a, 0x0000, 0x5f5e,
+ 0x3027, 0x4637, 0x5f53, 0x0000, 0x3a65, 0x0000, 0x365f, 0x4d5b,
+ 0x397e, 0x5455, 0x0000, 0x0000, 0x5f5f, 0x4f6c, 0x3025, 0x5f67,
+ 0x5f51, 0x5146, 0x5f55, 0x5f58, 0x5f59, 0x5f5c, 0x0000, 0x3b29,
+ 0x0000, 0x5f60, 0x5f61, 0x0000, 0x5f62, 0x5f66, 0x5f68, 0x5334,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3867, 0x4536, 0x5f6a,
+ 0x495a, 0x4128, 0x4444, 0x0000, 0x0000, 0x3f5e, 0x4f78, 0x0000,
+ 0x0000, 0x0000, 0x555c, 0x5f6e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3238, 0x0000, 0x3a5f, 0x5f6c, 0x0000, 0x5b41
+};
+
+static unsigned short gb2312_from_unicode_55[] = {
+ 0x0000, 0x5164, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b74, 0x343d,
+ 0x0000, 0x3026, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f71,
+ 0x4c46, 0x5f72, 0x0000, 0x0000, 0x5f6d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5f69, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5f6b, 0x0000, 0x5f6f, 0x5f70, 0x3b3d, 0x0000, 0x0000, 0x5f73,
+ 0x0000, 0x0000, 0x5f74, 0x0000, 0x3b23, 0x0000, 0x4a5b, 0x4e28,
+ 0x6027, 0x332a, 0x0000, 0x6026, 0x0000, 0x0000, 0x0000, 0x6021,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5f7e, 0x0000, 0x4d59, 0x5f7c,
+ 0x0000, 0x5f7a, 0x0000, 0x3f50, 0x5744, 0x0000, 0x494c, 0x0000,
+ 0x0000, 0x5f78, 0x3021, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5f7d, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f7b, 0x6022, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6028, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3748, 0x0000, 0x0000, 0x4621, 0x4936, 0x4032, 0x5f75,
+ 0x0000, 0x0000, 0x453e, 0x0000, 0x5844, 0x5f79, 0x4476, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6023, 0x6024, 0x6025,
+ 0x5025, 0x0000, 0x0000, 0x6034, 0x4c64, 0x0000, 0x6031, 0x0000,
+ 0x3f26, 0x602f, 0x4e39, 0x602b, 0x4946, 0x0000, 0x0000, 0x402e,
+ 0x602e, 0x3a6d, 0x3a30, 0x6029, 0x0000, 0x0000, 0x0000, 0x5f76,
+ 0x0000, 0x6033, 0x0000, 0x0000, 0x6038, 0x0000, 0x0000, 0x0000,
+ 0x342d, 0x6039, 0x0000, 0x0000, 0x4f32, 0x3a48, 0x0000, 0x6030,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x507a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x602c, 0x0000, 0x547b, 0x0000, 0x5f77, 0x0000, 0x4567,
+ 0x0000, 0x602d, 0x0000, 0x5377, 0x0000, 0x6036, 0x6037, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6044, 0x5061, 0x0000, 0x0000,
+ 0x0000, 0x603c, 0x0000, 0x0000, 0x6049, 0x604a, 0x0000, 0x0000,
+ 0x0000, 0x603e, 0x602a, 0x4924, 0x6041, 0x0000, 0x6032, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4a48, 0x6043, 0x0000, 0x6035,
+ 0x0000, 0x4e4b, 0x0000, 0x4b43, 0x604d, 0x6046, 0x6042, 0x0000,
+ 0x604b, 0x0000, 0x603a, 0x603f, 0x6040, 0x0000, 0x0000, 0x6045,
+ 0x0000, 0x0000, 0x6047, 0x6048, 0x0000, 0x604c, 0x0000, 0x603b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b54, 0x6055, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_56[] = {
+ 0x6056, 0x6052, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6050, 0x3c4e, 0x0000, 0x0000, 0x6051, 0x0000, 0x3842, 0x5845,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x506a, 0x0000, 0x0000, 0x426f, 0x0000, 0x0000, 0x604f, 0x603d,
+ 0x0000, 0x0000, 0x0000, 0x6054, 0x6053, 0x0000, 0x0000, 0x6057,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x605c, 0x6058, 0x0000, 0x0000,
+ 0x0000, 0x5676, 0x3330, 0x0000, 0x576c, 0x0000, 0x4b3b, 0x0000,
+ 0x0000, 0x605a, 0x0000, 0x4e7b, 0x0000, 0x0000, 0x0000, 0x3a59,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6061, 0x605d, 0x522d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6062, 0x0000, 0x0000, 0x605b,
+ 0x6059, 0x605f, 0x0000, 0x0000, 0x6060, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x605e, 0x0000, 0x6064, 0x0000, 0x0000, 0x0000,
+ 0x4677, 0x582c, 0x546b, 0x6066, 0x4a49, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6065, 0x0000, 0x0000, 0x0000, 0x0000, 0x3841, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6067, 0x6068, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6069, 0x6063, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3a3f, 0x4c67,
+ 0x0000, 0x0000, 0x0000, 0x606a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4f79, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x606b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4842,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3d40, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4452, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x606c, 0x0000, 0x0000, 0x606d,
+ 0x0000, 0x0000, 0x4774, 0x4b44, 0x0000, 0x606e, 0x3b58, 0x5836,
+ 0x5272, 0x606f, 0x4d45, 0x0000, 0x365a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6071, 0x0000, 0x5430, 0x0000, 0x0000,
+ 0x4027, 0x3451, 0x0000, 0x0000, 0x4e27, 0x6070, 0x0000, 0x0000,
+ 0x0000, 0x6072, 0x394c, 0x0000, 0x0000, 0x397a, 0x4d3c, 0x6073
+};
+
+static unsigned short gb2312_from_unicode_57[] = {
+ 0x0000, 0x0000, 0x0000, 0x4654, 0x6074, 0x0000, 0x5432, 0x0000,
+ 0x4826, 0x6076, 0x6075, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6077, 0x0000, 0x0000, 0x4d41,
+ 0x0000, 0x0000, 0x0000, 0x4a25, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x545a, 0x5b57, 0x5b59, 0x0000, 0x5b58, 0x3967, 0x5b5c, 0x5b5d,
+ 0x3558, 0x0000, 0x0000, 0x5b5a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5b5b, 0x3321, 0x5b5f, 0x0000, 0x0000, 0x3b78, 0x0000,
+ 0x5637, 0x0000, 0x5b60, 0x0000, 0x0000, 0x0000, 0x0000, 0x3e79,
+ 0x0000, 0x0000, 0x373b, 0x0000, 0x5b50, 0x4c2e, 0x3f32, 0x3b35,
+ 0x5778, 0x3f53, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3f69,
+ 0x0000, 0x0000, 0x3c61, 0x4c33, 0x5b5e, 0x3053, 0x4e6b, 0x3758,
+ 0x5739, 0x4642, 0x0000, 0x0000, 0x4024, 0x0000, 0x4c39, 0x0000,
+ 0x5b67, 0x5b61, 0x463a, 0x5b63, 0x0000, 0x5b68, 0x0000, 0x4577,
+ 0x0000, 0x0000, 0x0000, 0x5b6a, 0x0000, 0x0000, 0x5b69, 0x3f40,
+ 0x0000, 0x0000, 0x0000, 0x5b66, 0x5b65, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3439, 0x402c, 0x4222, 0x5b62, 0x5b64, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x504d, 0x5b6d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x405d, 0x5b72, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3662, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5b73, 0x5b52, 0x3938, 0x542b, 0x5b6c, 0x0000, 0x3f51, 0x5b70,
+ 0x0000, 0x5b51, 0x0000, 0x3566, 0x0000, 0x5b6b, 0x3f65, 0x0000,
+ 0x0000, 0x0000, 0x5b6e, 0x0000, 0x5b71, 0x0000, 0x0000, 0x0000,
+ 0x5b79, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3921, 0x3023, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4271, 0x0000, 0x0000, 0x3347, 0x5b6f,
+ 0x0000, 0x0000, 0x5b78, 0x0000, 0x4652, 0x5b74, 0x0000, 0x0000,
+ 0x5b75, 0x5b77, 0x5b76, 0x0000, 0x0000, 0x5b7e, 0x0000, 0x5372,
+ 0x323a, 0x0000, 0x0000, 0x0000, 0x5b7d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c24, 0x0000, 0x5b7b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5b7a, 0x0000, 0x0000, 0x0000,
+ 0x5b7c, 0x4560, 0x3b79, 0x0000, 0x0000, 0x5c23, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_58[] = {
+ 0x5c25, 0x0000, 0x4c43, 0x0000, 0x0000, 0x0000, 0x3651, 0x5d40,
+ 0x0000, 0x0000, 0x0000, 0x5c21, 0x0000, 0x5c22, 0x0000, 0x0000,
+ 0x0000, 0x4735, 0x0000, 0x0000, 0x0000, 0x3669, 0x0000, 0x0000,
+ 0x0000, 0x5c27, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c26, 0x0000,
+ 0x5c29, 0x3124, 0x0000, 0x0000, 0x354c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3f30, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x515f, 0x0000, 0x0000, 0x0000, 0x0000, 0x3642, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5c28, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4b7a, 0x6b73, 0x0000, 0x0000,
+ 0x0000, 0x4b5c, 0x0000, 0x0000, 0x4b7e, 0x0000, 0x0000, 0x0000,
+ 0x4c41, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x487b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c2a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4c6e, 0x5c2b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b53, 0x0000,
+ 0x5c2f, 0x5c2c, 0x0000, 0x3e33, 0x0000, 0x4a7b, 0x0000, 0x0000,
+ 0x0000, 0x5c2d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x494a, 0x4439, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x473d, 0x5c2e, 0x0000, 0x0000, 0x0000, 0x5476, 0x5066,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x442b, 0x3655, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5b54, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x315a, 0x0000, 0x0000, 0x0000, 0x5b55, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5b56, 0x0000, 0x0000, 0x0000, 0x3a3e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4840, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4a3f, 0x4849, 0x0000, 0x5733, 0x0000,
+ 0x4979, 0x0000, 0x0000, 0x3f47, 0x0000, 0x0000, 0x3a78, 0x0000,
+ 0x0000, 0x523c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_59[] = {
+ 0x0000, 0x0000, 0x623a, 0x0000, 0x3426, 0x0000, 0x0000, 0x3138,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3834, 0x0000, 0x4f44,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5967, 0x4f26, 0x4d62, 0x0000,
+ 0x0000, 0x596d, 0x3660, 0x0000, 0x5239, 0x0000, 0x0000, 0x393b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6239, 0x6237, 0x0000, 0x3473,
+ 0x0000, 0x4c6c, 0x4c2b, 0x3772, 0x0000, 0x5832, 0x516b, 0x3a3b,
+ 0x0000, 0x4a27, 0x0000, 0x0000, 0x4d37, 0x0000, 0x0000, 0x5244,
+ 0x3f64, 0x3c50, 0x3661, 0x0000, 0x5e45, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5e46, 0x5b3c, 0x0000, 0x5159, 0x0000, 0x0000, 0x4666,
+ 0x444e, 0x376e, 0x0000, 0x375c, 0x0000, 0x0000, 0x3f7c, 0x5760,
+ 0x0000, 0x4675, 0x0000, 0x0000, 0x313c, 0x5e48, 0x3d31, 0x4c57,
+ 0x5e4a, 0x0000, 0x5e49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x356c, 0x0000, 0x495d, 0x0000, 0x0000, 0x3042, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x452e, 0x452b, 0x0000, 0x444c, 0x0000,
+ 0x3c69, 0x4b7d, 0x0000, 0x0000, 0x0000, 0x3a43, 0x0000, 0x0000,
+ 0x0000, 0x6579, 0x4867, 0x657a, 0x4d7d, 0x0000, 0x5731, 0x383e,
+ 0x4268, 0x0000, 0x4851, 0x0000, 0x0000, 0x657b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x364a, 0x3c4b, 0x0000, 0x0000, 0x517d, 0x6621,
+ 0x0000, 0x436e, 0x0000, 0x0000, 0x0000, 0x0000, 0x6624, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x657e, 0x6625, 0x4d57, 0x0000, 0x0000,
+ 0x3741, 0x657c, 0x657d, 0x6623, 0x0000, 0x0000, 0x445d, 0x6628,
+ 0x0000, 0x0000, 0x6627, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4343, 0x0000, 0x465e, 0x0000, 0x0000, 0x662a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4437, 0x0000,
+ 0x0000, 0x0000, 0x6622, 0x4a3c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d63, 0x3943, 0x6626, 0x5055, 0x4e2f, 0x0000, 0x0000, 0x6629,
+ 0x6630, 0x0000, 0x5226, 0x0000, 0x3d2a, 0x662d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x662f, 0x0000, 0x4051, 0x0000, 0x0000,
+ 0x524c, 0x0000, 0x0000, 0x0000, 0x3c27, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6631, 0x0000, 0x5276, 0x0000, 0x0000, 0x0000, 0x574b
+};
+
+static unsigned short gb2312_from_unicode_5a[] = {
+ 0x0000, 0x4d7e, 0x0000, 0x4d5e, 0x4226, 0x662b, 0x662c, 0x3d3f,
+ 0x662e, 0x6633, 0x0000, 0x0000, 0x6632, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6636, 0x0000, 0x6638, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x446f, 0x0000, 0x0000, 0x0000, 0x4448, 0x0000, 0x0000, 0x3e6a,
+ 0x496f, 0x0000, 0x0000, 0x6637, 0x0000, 0x3670, 0x0000, 0x0000,
+ 0x0000, 0x4364, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5369, 0x6634, 0x0000, 0x6635, 0x0000, 0x4822, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x663d, 0x0000, 0x0000, 0x0000,
+ 0x6639, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4645, 0x0000,
+ 0x0000, 0x4d71, 0x663b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x663c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3b69, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x663e, 0x0000, 0x0000, 0x0000, 0x0000, 0x663a,
+ 0x0000, 0x0000, 0x4037, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5324, 0x663f, 0x4974, 0x6643,
+ 0x0000, 0x0000, 0x6644, 0x0000, 0x0000, 0x0000, 0x0000, 0x5076,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x433d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4344, 0x6642, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6641, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6647, 0x4f31, 0x0000, 0x6b74, 0x0000, 0x0000,
+ 0x664a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6645, 0x0000,
+ 0x0000, 0x3c5e, 0x4929, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3c35, 0x0000, 0x0000, 0x4f53, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6648, 0x0000, 0x6649, 0x0000, 0x664e, 0x0000,
+ 0x6650, 0x0000, 0x0000, 0x0000, 0x6651, 0x0000, 0x0000, 0x0000,
+ 0x664b, 0x3555, 0x0000, 0x664c, 0x0000, 0x0000, 0x664f, 0x0000,
+ 0x0000, 0x445b, 0x0000, 0x6646, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x664d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_5b[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6652, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6654, 0x6653,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6655, 0x0000, 0x5978, 0x0000, 0x0000, 0x6656,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6657, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5753, 0x665d, 0x0000, 0x665e, 0x3f57, 0x5450, 0x0000, 0x5756,
+ 0x3466, 0x4b6f, 0x665a, 0x5843, 0x574e, 0x5022, 0x0000, 0x434f,
+ 0x0000, 0x0000, 0x665f, 0x3c3e, 0x3942, 0x665b, 0x5127, 0x0000,
+ 0x0000, 0x3a22, 0x424f, 0x0000, 0x582b, 0x0000, 0x0000, 0x0000,
+ 0x4a6b, 0x656e, 0x0000, 0x665c, 0x0000, 0x3775, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4866, 0x0000, 0x0000, 0x4475, 0x0000, 0x0000,
+ 0x6532, 0x447e, 0x0000, 0x4b7c, 0x6533, 0x552c, 0x0000, 0x536e,
+ 0x4a58, 0x3032, 0x0000, 0x4b4e, 0x4d6a, 0x0000, 0x0000, 0x3a6a,
+ 0x0000, 0x0000, 0x0000, 0x6535, 0x0000, 0x6534, 0x0000, 0x575a,
+ 0x3959, 0x5666, 0x3628, 0x4d70, 0x524b, 0x3126, 0x4a35, 0x0000,
+ 0x3368, 0x4973, 0x3f4d, 0x507b, 0x4a52, 0x6536, 0x3b42, 0x0000,
+ 0x0000, 0x0000, 0x4f5c, 0x392c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5457, 0x0000, 0x0000, 0x3a26, 0x5167, 0x4f7c, 0x3c52, 0x0000,
+ 0x6537, 0x485d, 0x0000, 0x0000, 0x0000, 0x3f6d, 0x3176, 0x4b5e,
+ 0x0000, 0x0000, 0x3c45, 0x0000, 0x3c44, 0x527a, 0x435c, 0x3f5c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x383b, 0x0000, 0x0000, 0x0000,
+ 0x4342, 0x0000, 0x3a2e, 0x5422, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x475e, 0x442f, 0x326c,
+ 0x0000, 0x3951, 0x0000, 0x0000, 0x653b, 0x4148, 0x0000, 0x0000,
+ 0x552f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x653c, 0x0000,
+ 0x653e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3467, 0x3654, 0x4b42, 0x5130, 0x353c, 0x0000, 0x0000, 0x4a59
+};
+
+static unsigned short gb2312_from_unicode_5c[] = {
+ 0x0000, 0x3762, 0x0000, 0x0000, 0x4964, 0x0000, 0x3d2b, 0x0000,
+ 0x0000, 0x4e3e, 0x5770, 0x0000, 0x0000, 0x0000, 0x0000, 0x5021,
+ 0x0000, 0x4959, 0x0000, 0x0000, 0x367b, 0x6658, 0x3c62, 0x0000,
+ 0x333e, 0x0000, 0x4950, 0x0000, 0x6659, 0x3322, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5e4c, 0x0000, 0x5348, 0x5e4d, 0x0000, 0x5222,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5e4e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3e4d, 0x0000, 0x0000, 0x5e4f, 0x0000, 0x0000, 0x0000,
+ 0x4a2c, 0x527c, 0x335f, 0x656a, 0x4461, 0x3e21, 0x4e32, 0x4472,
+ 0x3e56, 0x4628, 0x3263, 0x0000, 0x0000, 0x3e53, 0x0000, 0x0000,
+ 0x477c, 0x4c6b, 0x3d6c, 0x4e5d, 0x0000, 0x0000, 0x4a3a, 0x4641,
+ 0x656c, 0x503c, 0x0000, 0x0000, 0x0000, 0x5539, 0x0000, 0x0000,
+ 0x0000, 0x656d, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a74, 0x0000,
+ 0x4d40, 0x4245, 0x0000, 0x656f, 0x0000, 0x4244, 0x6570, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6578, 0x4d4d,
+ 0x0000, 0x493d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5259, 0x6128, 0x0000, 0x0000, 0x0000, 0x0000, 0x536c,
+ 0x0000, 0x4b6a, 0x4671, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x612c, 0x0000, 0x0000, 0x0000, 0x6127, 0x6129, 0x0000, 0x0000,
+ 0x612a, 0x612f, 0x0000, 0x0000, 0x326d, 0x0000, 0x612b, 0x385a,
+ 0x612d, 0x612e, 0x6130, 0x353a, 0x6131, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6133, 0x6138, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5152, 0x0000, 0x6136, 0x6135, 0x416b, 0x0000, 0x0000,
+ 0x0000, 0x6137, 0x0000, 0x5440, 0x0000, 0x6132, 0x0000, 0x613a,
+ 0x3036, 0x0000, 0x0000, 0x0000, 0x0000, 0x6134, 0x0000, 0x3f79,
+ 0x0000, 0x6139, 0x0000, 0x0000, 0x613b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x613e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x613c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5645, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4f3f, 0x0000, 0x0000, 0x613d, 0x613f, 0x424d, 0x0000,
+ 0x366b, 0x0000, 0x5378, 0x0000, 0x0000, 0x474d, 0x0000, 0x0000,
+ 0x3765, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3e7e, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_5d[] = {
+ 0x0000, 0x0000, 0x6140, 0x6141, 0x0000, 0x0000, 0x6147, 0x3367,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4669, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x345e, 0x0000, 0x5142, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6148, 0x0000, 0x0000, 0x6146, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6145, 0x0000, 0x6143, 0x6142,
+ 0x0000, 0x3140, 0x0000, 0x0000, 0x0000, 0x5538, 0x6144, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x614b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x614c, 0x614a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6f7a,
+ 0x0000, 0x0000, 0x6153, 0x6152, 0x4736, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6149, 0x0000, 0x0000, 0x614e, 0x0000, 0x6150, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6154, 0x0000, 0x6151, 0x614d, 0x0000, 0x0000, 0x614f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6155, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6156, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6157, 0x0000, 0x0000, 0x0000, 0x6158, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x615a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x615b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e21, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x675d, 0x0000, 0x3428, 0x565d, 0x0000,
+ 0x0000, 0x5132, 0x3332, 0x0000, 0x0000, 0x3924, 0x5773, 0x4749,
+ 0x3e5e, 0x392e, 0x0000, 0x4e57, 0x0000, 0x0000, 0x326e, 0x5b4f,
+ 0x0000, 0x3c3a, 0x5251, 0x4b48, 0x304d, 0x0000, 0x0000, 0x4f6f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5963, 0x3d6d, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_5e[] = {
+ 0x0000, 0x3152, 0x4a50, 0x323c, 0x0000, 0x4b27, 0x372b, 0x0000,
+ 0x4a26, 0x0000, 0x0000, 0x0000, 0x4f23, 0x0000, 0x0000, 0x6078,
+ 0x554a, 0x607b, 0x0000, 0x0000, 0x607a, 0x4541, 0x4c7b, 0x0000,
+ 0x4131, 0x6079, 0x5663, 0x322f, 0x5644, 0x355b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3478, 0x5621,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4f2f, 0x306f, 0x0000,
+ 0x0000, 0x607c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6121,
+ 0x3323, 0x0000, 0x0000, 0x607d, 0x607e, 0x4331, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x435d, 0x0000, 0x6122, 0x3779, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3b4f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6123, 0x443b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6124, 0x0000, 0x0000, 0x6125, 0x0000,
+ 0x0000, 0x6126, 0x3431, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3849, 0x463d, 0x446a, 0x0000, 0x3222, 0x0000,
+ 0x5052, 0x0000, 0x675b, 0x3b43, 0x5357, 0x5344, 0x0000, 0x3963,
+ 0x624f, 0x0000, 0x0000, 0x0000, 0x572f, 0x0000, 0x476c, 0x3153,
+ 0x0000, 0x0000, 0x3432, 0x6251, 0x0000, 0x0000, 0x0000, 0x5072,
+ 0x422e, 0x6250, 0x0000, 0x3f62, 0x5326, 0x3557, 0x6252, 0x356a,
+ 0x0000, 0x436d, 0x387d, 0x0000, 0x382e, 0x0000, 0x4553, 0x374f,
+ 0x6254, 0x0000, 0x0000, 0x0000, 0x0000, 0x6253, 0x3648, 0x5779,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d25, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6258, 0x0000, 0x6256, 0x4a7c, 0x3f35,
+ 0x5339, 0x6255, 0x0000, 0x0000, 0x0000, 0x0000, 0x6257, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x412e, 0x4048, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x625b, 0x625a, 0x402a, 0x0000, 0x0000, 0x414e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x625c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x625d, 0x0000, 0x625e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5b48, 0x0000, 0x5153, 0x4d22,
+ 0x0000, 0x0000, 0x3d28, 0x0000, 0x0000, 0x0000, 0x5e43, 0x5825
+};
+
+static unsigned short gb2312_from_unicode_5f[] = {
+ 0x3f2a, 0x5b4d, 0x526c, 0x467a, 0x452a, 0x0000, 0x0000, 0x0000,
+ 0x5e44, 0x0000, 0x3157, 0x5f2e, 0x0000, 0x0000, 0x0000, 0x4a3d,
+ 0x0000, 0x5f31, 0x0000, 0x392d, 0x0000, 0x527d, 0x0000, 0x3825,
+ 0x3a6b, 0x0000, 0x0000, 0x335a, 0x0000, 0x0000, 0x0000, 0x355c,
+ 0x5545, 0x0000, 0x0000, 0x0000, 0x0000, 0x4356, 0x4f52, 0x3b21,
+ 0x0000, 0x6573, 0x6572, 0x0000, 0x0000, 0x6574, 0x0000, 0x4d64,
+ 0x0000, 0x4875, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x352f, 0x473f, 0x0000, 0x6576, 0x0000, 0x0000, 0x0000,
+ 0x6c30, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6566, 0x0000, 0x3969, 0x3531, 0x0000, 0x423c, 0x6568, 0x6567,
+ 0x6569, 0x0000, 0x0000, 0x0000, 0x0000, 0x524d, 0x0000, 0x0000,
+ 0x0000, 0x616a, 0x504e, 0x0000, 0x4d2e, 0x0000, 0x5165, 0x0000,
+ 0x0000, 0x324a, 0x316b, 0x0000, 0x3172, 0x456d, 0x0000, 0x0000,
+ 0x5543, 0x5330, 0x0000, 0x615c, 0x0000, 0x0000, 0x0000, 0x615d,
+ 0x0000, 0x525b, 0x0000, 0x3339, 0x314b, 0x0000, 0x0000, 0x0000,
+ 0x4d79, 0x5577, 0x615e, 0x0000, 0x3e36, 0x347d, 0x0000, 0x615f,
+ 0x3a5c, 0x6160, 0x3b32, 0x4249, 0x6161, 0x0000, 0x0000, 0x0000,
+ 0x506c, 0x0000, 0x4d3d, 0x0000, 0x0000, 0x6162, 0x0000, 0x3543,
+ 0x4547, 0x6163, 0x0000, 0x0000, 0x6164, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5379, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6165, 0x0000, 0x512d, 0x0000, 0x0000, 0x6166, 0x4e22, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6167, 0x0000, 0x3542,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6168, 0x3b55, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5044, 0x6260, 0x3158, 0x5264, 0x0000,
+ 0x0000, 0x6261, 0x0000, 0x0000, 0x3c49, 0x484c, 0x0000, 0x6263,
+ 0x6c7e, 0x6c7d, 0x5f2f, 0x0000, 0x0000, 0x0000, 0x6262, 0x563e,
+ 0x4d7c, 0x4326, 0x0000, 0x0000, 0x0000, 0x6343, 0x0000, 0x0000,
+ 0x5652, 0x6267, 0x0000, 0x0000, 0x6268, 0x0000, 0x0000, 0x5347,
+ 0x0000, 0x0000, 0x626c, 0x3f6c, 0x0000, 0x626d, 0x6265, 0x0000,
+ 0x0000, 0x3340, 0x0000, 0x0000, 0x0000, 0x446e, 0x0000, 0x0000,
+ 0x626e, 0x0000, 0x0000, 0x5043, 0x0000, 0x3a76, 0x6269, 0x375e
+};
+
+static unsigned short gb2312_from_unicode_60[] = {
+ 0x3b33, 0x4c2c, 0x4b4b, 0x6264, 0x6266, 0x626a, 0x626b, 0x0000,
+ 0x0000, 0x0000, 0x6277, 0x0000, 0x0000, 0x6274, 0x5475, 0x6273,
+ 0x0000, 0x0000, 0x452d, 0x0000, 0x557a, 0x4542, 0x3240, 0x0000,
+ 0x0000, 0x626f, 0x0000, 0x6272, 0x412f, 0x4b3c, 0x0000, 0x0000,
+ 0x3521, 0x6279, 0x0000, 0x0000, 0x0000, 0x3c31, 0x6271, 0x5054,
+ 0x5439, 0x6275, 0x3956, 0x6276, 0x0000, 0x0000, 0x0000, 0x4753,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6270, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x575c, 0x6d21, 0x0000, 0x0000, 0x6278,
+ 0x0000, 0x6d25, 0x627e, 0x4a51, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4135, 0x0000, 0x3b50, 0x0000, 0x0000,
+ 0x3f56, 0x0000, 0x3a63, 0x0000, 0x0000, 0x4b21, 0x0000, 0x0000,
+ 0x0000, 0x6d26, 0x6d23, 0x0000, 0x0000, 0x6d22, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3b56, 0x6d27, 0x5074, 0x0000, 0x0000, 0x6d24,
+ 0x3a5e, 0x3677, 0x6321, 0x3632, 0x4c71, 0x3927, 0x0000, 0x4f22,
+ 0x4721, 0x0000, 0x0000, 0x3f52, 0x0000, 0x0000, 0x3671, 0x0000,
+ 0x627a, 0x627b, 0x627d, 0x627c, 0x4455, 0x6322, 0x0000, 0x5341,
+ 0x0000, 0x0000, 0x0000, 0x6327, 0x4744, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4f24, 0x0000, 0x0000, 0x6329, 0x3a37, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6328, 0x0000, 0x3b5a, 0x0000, 0x6323, 0x0000,
+ 0x0000, 0x0000, 0x6324, 0x632a, 0x0000, 0x6326, 0x0000, 0x4e72,
+ 0x5346, 0x0000, 0x0000, 0x3b3c, 0x0000, 0x0000, 0x5443, 0x0000,
+ 0x447a, 0x0000, 0x0000, 0x6d28, 0x507c, 0x6325, 0x0000, 0x4375,
+ 0x0000, 0x632d, 0x312f, 0x0000, 0x6332, 0x0000, 0x0000, 0x0000,
+ 0x3c42, 0x0000, 0x0000, 0x632c, 0x353f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4769, 0x6330, 0x0000,
+ 0x0000, 0x0000, 0x3e2a, 0x4d6f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3b73, 0x0000, 0x0000, 0x0000, 0x4c68, 0x0000, 0x0000,
+ 0x632f, 0x0000, 0x6331, 0x0000, 0x4f27, 0x632e, 0x0000, 0x4e29,
+ 0x3b5d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x356b, 0x3e65,
+ 0x3252, 0x334d, 0x0000, 0x3139, 0x632b, 0x3251, 0x352c, 0x395f,
+ 0x3668, 0x0000, 0x0000, 0x4f6b, 0x6337, 0x0000, 0x3b4c, 0x0000,
+ 0x0000, 0x4847, 0x504a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_61[] = {
+ 0x6338, 0x336e, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d29, 0x0000,
+ 0x537a, 0x5364, 0x0000, 0x0000, 0x0000, 0x6d2a, 0x6339, 0x5262,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6335, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x535e, 0x0000, 0x0000, 0x0000, 0x0000, 0x3850,
+ 0x6333, 0x0000, 0x0000, 0x6336, 0x375f, 0x0000, 0x6334, 0x4022,
+ 0x0000, 0x0000, 0x0000, 0x633a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5438,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3448, 0x0000, 0x633b, 0x0000, 0x3b45, 0x0000, 0x4977, 0x0000,
+ 0x0000, 0x4965, 0x0000, 0x0000, 0x0000, 0x443d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d2b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x427d, 0x0000, 0x0000, 0x0000, 0x0000, 0x3b5b,
+ 0x3f2e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4e3f, 0x0000, 0x0000, 0x0000, 0x0000, 0x633c, 0x0000, 0x3f36,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x316f, 0x0000, 0x0000, 0x5477, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x633e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d2d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x633f,
+ 0x3a29, 0x6d2c, 0x0000, 0x0000, 0x633d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6340,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3a36, 0x0000,
+ 0x0000, 0x0000, 0x362e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5038, 0x0000, 0x3043, 0x6d2e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6d2f, 0x4041, 0x0000, 0x6341, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4533, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6342, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c32
+};
+
+static unsigned short gb2312_from_unicode_62[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d30, 0x0000,
+ 0x386a, 0x0000, 0x4e6c, 0x6a27, 0x5067, 0x4a79, 0x4856, 0x4f37,
+ 0x3349, 0x4e52, 0x3d64, 0x0000, 0x0000, 0x635e, 0x3b72, 0x6a28,
+ 0x553d, 0x0000, 0x465d, 0x6a29, 0x0000, 0x0000, 0x0000, 0x6a2a,
+ 0x0000, 0x6a2c, 0x6a2b, 0x0000, 0x6a2e, 0x6a2d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3d58, 0x0000, 0x6a2f, 0x0000, 0x423e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3441, 0x3477, 0x0000, 0x0000, 0x3b27,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6c66, 0x6c65, 0x373f,
+ 0x4b79, 0x3162, 0x0000, 0x6c67, 0x0000, 0x0000, 0x0000, 0x4948,
+ 0x6c68, 0x6c69, 0x0000, 0x4a56, 0x5e50, 0x3245, 0x547a, 0x0000,
+ 0x0000, 0x464b, 0x3047, 0x3472, 0x4853, 0x0000, 0x0000, 0x0000,
+ 0x4d50, 0x0000, 0x0000, 0x3f38, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3f5b, 0x0000, 0x0000, 0x4724, 0x5634,
+ 0x0000, 0x4029, 0x5e51, 0x4928, 0x516f, 0x4524, 0x3067, 0x3336,
+ 0x4845, 0x0000, 0x0000, 0x3062, 0x0000, 0x0000, 0x3776, 0x0000,
+ 0x0000, 0x457a, 0x0000, 0x0000, 0x3673, 0x0000, 0x5552, 0x3350,
+ 0x3c3c, 0x0000, 0x0000, 0x0000, 0x332d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3e71, 0x3051, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5256, 0x4a63, 0x5725, 0x0000, 0x4d36, 0x3636, 0x3f39,
+ 0x555b, 0x0000, 0x3827, 0x4557, 0x0000, 0x0000, 0x0000, 0x5e52,
+ 0x3f59, 0x4255, 0x4740, 0x0000, 0x3b24, 0x3128, 0x0000, 0x0000,
+ 0x456a, 0x0000, 0x0000, 0x457b, 0x4c27, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3127, 0x0000, 0x0000, 0x0000, 0x3556, 0x0000, 0x0000,
+ 0x0000, 0x4428, 0x0000, 0x5e53, 0x513a, 0x3369, 0x0000, 0x4372,
+ 0x0000, 0x0000, 0x3777, 0x0000, 0x5674, 0x3523, 0x3270, 0x4434,
+ 0x4469, 0x402d, 0x5e54, 0x0000, 0x3068, 0x4544, 0x4160, 0x0000,
+ 0x3955, 0x0000, 0x3e5c, 0x4d58, 0x304e, 0x0000, 0x4d4f, 0x5e56,
+ 0x3e50, 0x573e, 0x5e55, 0x5550, 0x305d, 0x0000, 0x0000, 0x4462,
+ 0x0000, 0x0000, 0x4223, 0x3c70, 0x0000, 0x5335, 0x4039, 0x4521,
+ 0x3226, 0x5471, 0x0000, 0x0000, 0x4028, 0x4a43, 0x5e57, 0x557c,
+ 0x0000, 0x3930, 0x0000, 0x482d, 0x4b29, 0x0000, 0x5e59, 0x3f3d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4634, 0x5727, 0x4a30, 0x4443
+};
+
+static unsigned short gb2312_from_unicode_63[] = {
+ 0x0000, 0x3356, 0x3952, 0x0000, 0x0000, 0x0000, 0x0000, 0x5638,
+ 0x6a7c, 0x3034, 0x0000, 0x0000, 0x0000, 0x0000, 0x3f66, 0x0000,
+ 0x0000, 0x4c74, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d5a, 0x0000,
+ 0x0000, 0x0000, 0x563f, 0x424e, 0x0000, 0x4e4e, 0x4c22, 0x502e,
+ 0x4453, 0x3532, 0x5e58, 0x5575, 0x3c37, 0x3b53, 0x0000, 0x0000,
+ 0x3024, 0x0000, 0x4532, 0x346c, 0x0000, 0x0000, 0x0000, 0x5571,
+ 0x0000, 0x0000, 0x6a7d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5e5a, 0x4d26, 0x0000, 0x0000, 0x4d6c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4e66, 0x5e5c, 0x0000, 0x4d31, 0x4026, 0x0000,
+ 0x0000, 0x573d, 0x0000, 0x5e5b, 0x3046, 0x3a34, 0x4953, 0x4473,
+ 0x3e68, 0x0000, 0x0000, 0x0000, 0x0000, 0x3236, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x404c, 0x4b70,
+ 0x0000, 0x3c71, 0x3b3b, 0x3537, 0x0000, 0x0000, 0x0000, 0x4575,
+ 0x0000, 0x5e66, 0x0000, 0x0000, 0x0000, 0x5e63, 0x3e5d, 0x0000,
+ 0x0000, 0x5e5f, 0x0000, 0x0000, 0x0000, 0x0000, 0x3437, 0x3d5d,
+ 0x0000, 0x0000, 0x5e60, 0x446d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4f46, 0x0000, 0x3560, 0x0000, 0x0000, 0x0000, 0x0000, 0x365e,
+ 0x4a5a, 0x3574, 0x5e65, 0x0000, 0x5546, 0x0000, 0x5e61, 0x4c4d,
+ 0x467e, 0x0000, 0x4545, 0x0000, 0x0000, 0x0000, 0x5234, 0x0000,
+ 0x3e72, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4253, 0x0000, 0x4c3d, 0x3338, 0x0000, 0x3d53, 0x0000, 0x3f58,
+ 0x4d46, 0x515a, 0x346b, 0x0000, 0x5e64, 0x5e5d, 0x5e67, 0x0000,
+ 0x6a7e, 0x0000, 0x0000, 0x4230, 0x5e62, 0x0000, 0x0000, 0x5640,
+ 0x3527, 0x0000, 0x3274, 0x0000, 0x5e68, 0x0000, 0x5e72, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5e6d, 0x0000, 0x5e71, 0x0000,
+ 0x0000, 0x4860, 0x0000, 0x0000, 0x0000, 0x5761, 0x5e6f, 0x4368,
+ 0x4c61, 0x0000, 0x3265, 0x0000, 0x0000, 0x0000, 0x523e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e6e, 0x0000,
+ 0x5e6b, 0x4e55, 0x0000, 0x3427, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3f2b, 0x3e3e, 0x0000, 0x0000, 0x3d52, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5e69, 0x0000, 0x542e, 0x0000, 0x5e5e, 0x0000,
+ 0x5e6a, 0x0000, 0x0000, 0x0000, 0x0000, 0x403f, 0x0000, 0x5e6c
+};
+
+static unsigned short gb2312_from_unicode_64[] = {
+ 0x3273, 0x3869, 0x4227, 0x0000, 0x0000, 0x3d41, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5e75, 0x5e78, 0x0000, 0x0000, 0x322b,
+ 0x3424, 0x0000, 0x0000, 0x346a, 0x4926, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5e76, 0x4b51, 0x0000, 0x3863, 0x0000,
+ 0x5e77, 0x5e7a, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e79, 0x0000,
+ 0x0000, 0x0000, 0x4c42, 0x0000, 0x3061, 0x346e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x653a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x502f, 0x0000, 0x0000, 0x326b, 0x0000, 0x6b21,
+ 0x0000, 0x5e74, 0x0000, 0x0000, 0x4963, 0x5e73, 0x305a, 0x5221,
+ 0x3177, 0x0000, 0x4c2f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5e70, 0x0000, 0x4b24, 0x0000, 0x0000, 0x0000,
+ 0x552a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e7b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x345d,
+ 0x0000, 0x4426, 0x0000, 0x0000, 0x0000, 0x5e7d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x437e, 0x4421, 0x5f21, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x414c, 0x0000, 0x5e7c, 0x3e6f, 0x0000, 0x4632,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3345, 0x4876, 0x0000, 0x0000, 0x4b3a, 0x5e7e, 0x0000,
+ 0x0000, 0x5f24, 0x0000, 0x0000, 0x0000, 0x0000, 0x5732, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3337, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4143, 0x0000, 0x0000, 0x474b, 0x3225, 0x3469, 0x0000,
+ 0x572b, 0x0000, 0x0000, 0x0000, 0x0000, 0x446c, 0x0000, 0x5f22,
+ 0x5f23, 0x0000, 0x5f25, 0x0000, 0x3a33, 0x0000, 0x0000, 0x0000,
+ 0x5f26, 0x0000, 0x405e, 0x0000, 0x0000, 0x4943, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3259, 0x4766, 0x0000,
+ 0x5f27, 0x0000, 0x475c, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f28,
+ 0x6b22, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b53, 0x0000,
+ 0x0000, 0x0000, 0x5f2a, 0x0000, 0x5f29, 0x0000, 0x3241, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_65[] = {
+ 0x454a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5f2b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x545c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4841, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5f2c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3e70, 0x0000, 0x0000, 0x5f2d, 0x5627,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6a37, 0x6b36, 0x4a55, 0x0000,
+ 0x587c, 0x3844, 0x0000, 0x3925, 0x0000, 0x0000, 0x3745, 0x557e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x394a, 0x0000, 0x0000,
+ 0x5027, 0x744d, 0x0000, 0x0000, 0x3550, 0x0000, 0x0000, 0x4374,
+ 0x0000, 0x3e48, 0x0000, 0x0000, 0x0000, 0x6b37, 0x303d, 0x0000,
+ 0x0000, 0x3d4c, 0x0000, 0x4132, 0x0000, 0x3156, 0x3328, 0x0000,
+ 0x0000, 0x0000, 0x3852, 0x4922, 0x0000, 0x0000, 0x3658, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6b38, 0x3e34, 0x0000, 0x0000, 0x0000,
+ 0x4a7d, 0x0000, 0x4743, 0x0000, 0x557b, 0x0000, 0x0000, 0x3773,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e44,
+ 0x0000, 0x0000, 0x0000, 0x552b, 0x3173, 0x0000, 0x0000, 0x0000,
+ 0x6c33, 0x305f, 0x0000, 0x6c35, 0x0000, 0x0000, 0x0000, 0x3637,
+ 0x0000, 0x414f, 0x0000, 0x757a, 0x5031, 0x0000, 0x0000, 0x5565,
+ 0x0000, 0x4e53, 0x0000, 0x0000, 0x3d6f, 0x3362, 0x0000, 0x382b,
+ 0x0000, 0x5536, 0x0000, 0x6d3d, 0x0000, 0x364f, 0x0000, 0x4b39,
+ 0x5042, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x373d, 0x0000, 0x0000, 0x6c36, 0x4a29, 0x0000, 0x0000,
+ 0x0000, 0x4554, 0x0000, 0x6c39, 0x6c38, 0x4243, 0x6c37, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x507d, 0x6c3a, 0x0000, 0x6c3b, 0x5765,
+ 0x0000, 0x0000, 0x6c3c, 0x0000, 0x0000, 0x0000, 0x6c3d, 0x466c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4e5e, 0x0000, 0x3c48, 0x0000, 0x0000, 0x4855, 0x3529, 0x3e49,
+ 0x563c, 0x5467, 0x0000, 0x0000, 0x512e, 0x5071, 0x6a38, 0x6a39,
+ 0x6a3a, 0x3a35, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a31, 0x3f75,
+ 0x0000, 0x0000, 0x4d7a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_66[] = {
+ 0x6a40, 0x0000, 0x303a, 0x6a3e, 0x0000, 0x0000, 0x4025, 0x0000,
+ 0x0000, 0x0000, 0x6a3b, 0x0000, 0x327d, 0x0000, 0x4377, 0x3b68,
+ 0x0000, 0x0000, 0x0000, 0x5257, 0x4e74, 0x6a3f, 0x0000, 0x0000,
+ 0x0000, 0x6a3c, 0x0000, 0x0000, 0x0000, 0x6a43, 0x0000, 0x5047,
+ 0x5333, 0x0000, 0x0000, 0x0000, 0x0000, 0x343a, 0x0000, 0x4341,
+ 0x5772, 0x0000, 0x0000, 0x0000, 0x0000, 0x5551, 0x0000, 0x4a47,
+ 0x0000, 0x6a45, 0x0000, 0x0000, 0x6a44, 0x6a47, 0x6a46, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5667, 0x0000, 0x4f54, 0x0000,
+ 0x0000, 0x6a4b, 0x0000, 0x3b4e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3d7a, 0x494e, 0x0000, 0x0000, 0x6a4c,
+ 0x0000, 0x0000, 0x4939, 0x4f7e, 0x6a4a, 0x544e, 0x6a4d, 0x6a4f,
+ 0x0000, 0x0000, 0x4d6d, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a49,
+ 0x0000, 0x6a4e, 0x0000, 0x0000, 0x4e6e, 0x0000, 0x3b5e, 0x0000,
+ 0x333f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4655, 0x3e30,
+ 0x4e7a, 0x0000, 0x0000, 0x0000, 0x4767, 0x0000, 0x3e27, 0x6a50,
+ 0x0000, 0x0000, 0x5647, 0x0000, 0x0000, 0x0000, 0x4140, 0x0000,
+ 0x0000, 0x0000, 0x545d, 0x0000, 0x6a51, 0x0000, 0x0000, 0x4f3e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6a52, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4a6e, 0x0000, 0x0000, 0x0000, 0x0000, 0x452f, 0x3035,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a54, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a53,
+ 0x745f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x443a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3129, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x655f, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a55, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4a6f, 0x0000, 0x6a56, 0x6a57, 0x4658, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a58, 0x0000,
+ 0x0000, 0x6a59, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x543b, 0x0000, 0x477a, 0x5237, 0x387c, 0x0000, 0x0000, 0x6a42,
+ 0x0000, 0x325c, 0x0000, 0x0000, 0x427c, 0x0000, 0x5478, 0x4c66
+};
+
+static unsigned short gb2312_from_unicode_67[] = {
+ 0x576e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5442, 0x5350, 0x6b43, 0x4573, 0x0000, 0x377e, 0x0000, 0x0000,
+ 0x6b54, 0x0000, 0x0000, 0x0000, 0x4b37, 0x6b5e, 0x0000, 0x404a,
+ 0x0000, 0x0000, 0x0000, 0x4d7b, 0x0000, 0x332f, 0x0000, 0x465a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6b7c, 0x0000,
+ 0x443e, 0x0000, 0x4e34, 0x4429, 0x313e, 0x547d, 0x0000, 0x4a75,
+ 0x0000, 0x566c, 0x0000, 0x0000, 0x4653, 0x3664, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3b7a, 0x0000, 0x0000, 0x5060, 0x0000, 0x0000,
+ 0x4931, 0x0000, 0x5453, 0x4828, 0x0000, 0x0000, 0x384b, 0x0000,
+ 0x683e, 0x493c, 0x0000, 0x0000, 0x683b, 0x0000, 0x406e, 0x5053,
+ 0x3244, 0x3465, 0x0000, 0x683c, 0x0000, 0x0000, 0x5548, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3645, 0x0000, 0x683d, 0x4a78,
+ 0x385c, 0x4c75, 0x0000, 0x0000, 0x0000, 0x4034, 0x0000, 0x0000,
+ 0x516e, 0x683f, 0x6842, 0x0000, 0x0000, 0x3a3c, 0x0000, 0x312d,
+ 0x3d5c, 0x0000, 0x6a3d, 0x6843, 0x0000, 0x6846, 0x0000, 0x684b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x684c, 0x0000, 0x4b49, 0x3065,
+ 0x0000, 0x3c2b, 0x0000, 0x0000, 0x3939, 0x0000, 0x0000, 0x6841,
+ 0x0000, 0x4d77, 0x0000, 0x684a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4e76, 0x0000, 0x0000, 0x0000, 0x0000, 0x556d, 0x0000, 0x4156,
+ 0x6844, 0x0000, 0x4336, 0x0000, 0x397b, 0x5626, 0x6848, 0x0000,
+ 0x0000, 0x0000, 0x4a60, 0x5466, 0x0000, 0x6840, 0x0000, 0x6845,
+ 0x6847, 0x0000, 0x4739, 0x3763, 0x0000, 0x6849, 0x0000, 0x3f5d,
+ 0x6852, 0x0000, 0x0000, 0x6857, 0x0000, 0x6855, 0x3c5c, 0x3c4f,
+ 0x685b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x685e, 0x0000, 0x685a, 0x317a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3058,
+ 0x4433, 0x384c, 0x4662, 0x483e, 0x4861, 0x0000, 0x0000, 0x0000,
+ 0x684f, 0x6854, 0x6856, 0x0000, 0x3971, 0x6858, 0x5775, 0x0000,
+ 0x447b, 0x0000, 0x685c, 0x0000, 0x0000, 0x3269, 0x0000, 0x0000,
+ 0x0000, 0x6851, 0x0000, 0x0000, 0x3c6d, 0x0000, 0x0000, 0x3f42,
+ 0x684d, 0x5679, 0x0000, 0x4178, 0x3271, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x685f, 0x0000, 0x4a41
+};
+
+static unsigned short gb2312_from_unicode_68[] = {
+ 0x6859, 0x0000, 0x0000, 0x0000, 0x0000, 0x5524, 0x0000, 0x316a,
+ 0x553b, 0x684e, 0x6850, 0x3630, 0x6853, 0x0000, 0x685d, 0x4038,
+ 0x0000, 0x4a77, 0x0000, 0x4b28, 0x0000, 0x0000, 0x465c, 0x4075,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6869, 0x0000, 0x0000,
+ 0x0000, 0x5023, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6872, 0x566a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6860, 0x6861, 0x0000, 0x0000, 0x0000, 0x5179,
+ 0x3a4b, 0x3879, 0x0000, 0x0000, 0x3871, 0x5454, 0x686f, 0x0000,
+ 0x686e, 0x686c, 0x3970, 0x4c52, 0x6866, 0x4e26, 0x3f72, 0x0000,
+ 0x3038, 0x6871, 0x6870, 0x0000, 0x5740, 0x0000, 0x6864, 0x0000,
+ 0x4d29, 0x4923, 0x0000, 0x3b38, 0x3d5b, 0x686a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6862, 0x6863, 0x6865, 0x3535, 0x6867, 0x4745, 0x686b, 0x686d,
+ 0x3d30, 0x572e, 0x0000, 0x6878, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6875, 0x0000, 0x4d30, 0x6876,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x413a, 0x0000, 0x6868, 0x0000, 0x4337, 0x3070, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6874,
+ 0x0000, 0x0000, 0x0000, 0x6877, 0x0000, 0x0000, 0x0000, 0x3923,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4952, 0x0000, 0x0000, 0x0000, 0x434e, 0x4e60,
+ 0x4066, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b73, 0x0000, 0x4c5d,
+ 0x5035, 0x0000, 0x0000, 0x4a61, 0x0000, 0x6873, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3c6c, 0x0000, 0x6879, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x435e, 0x0000, 0x4665, 0x0000, 0x3977, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3074, 0x0000, 0x0000, 0x5758, 0x0000, 0x0000,
+ 0x3c2c, 0x0000, 0x456f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4c44, 0x0000, 0x0000, 0x6926, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x492d, 0x0000,
+ 0x6922, 0x4062, 0x0000, 0x0000, 0x0000, 0x3f43, 0x0000, 0x0000,
+ 0x0000, 0x687e, 0x3957, 0x0000, 0x687b, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_69[] = {
+ 0x0000, 0x6924, 0x0000, 0x0000, 0x0000, 0x524e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6923, 0x0000, 0x5632, 0x5735, 0x0000,
+ 0x6927, 0x0000, 0x3d37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x687c,
+ 0x687d, 0x0000, 0x0000, 0x0000, 0x6921, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d56, 0x0000, 0x0000,
+ 0x522c, 0x0000, 0x0000, 0x0000, 0x6932, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6929, 0x0000, 0x0000, 0x0000, 0x342a, 0x0000, 0x343b,
+ 0x0000, 0x0000, 0x692b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5028, 0x0000, 0x0000, 0x6925,
+ 0x0000, 0x0000, 0x337e, 0x0000, 0x0000, 0x692c, 0x4063, 0x0000,
+ 0x692a, 0x0000, 0x0000, 0x6939, 0x0000, 0x0000, 0x6938, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x692e, 0x0000, 0x0000, 0x687a, 0x0000,
+ 0x0000, 0x6928, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3f2c,
+ 0x6931, 0x693a, 0x0000, 0x0000, 0x4225, 0x0000, 0x0000, 0x0000,
+ 0x692f, 0x0000, 0x3845, 0x0000, 0x692d, 0x0000, 0x535c, 0x6934,
+ 0x6935, 0x6937, 0x0000, 0x0000, 0x0000, 0x6947, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4046, 0x6945, 0x0000, 0x0000,
+ 0x6930, 0x0000, 0x0000, 0x693b, 0x3071, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x693c,
+ 0x5525, 0x0000, 0x0000, 0x693e, 0x0000, 0x693f, 0x0000, 0x0000,
+ 0x0000, 0x6941, 0x0000, 0x0000, 0x4171, 0x0000, 0x0000, 0x4836,
+ 0x0000, 0x0000, 0x0000, 0x693d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6942, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6943, 0x0000, 0x6933, 0x0000, 0x6936, 0x0000,
+ 0x3b31, 0x0000, 0x0000, 0x0000, 0x6940, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3c77, 0x0000, 0x0000, 0x0000, 0x6944,
+ 0x6946, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x694a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x694e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x325b, 0x0000, 0x6948
+};
+
+static unsigned short gb2312_from_unicode_6a[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x372e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x694b,
+ 0x694c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5541,
+ 0x0000, 0x4423, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6958, 0x0000, 0x3a61, 0x0000, 0x0000, 0x0000, 0x0000, 0x6949,
+ 0x0000, 0x5323, 0x0000, 0x0000, 0x0000, 0x6954, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6957, 0x6950, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x694f, 0x0000, 0x0000, 0x4741,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6952, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6959, 0x3348, 0x0000, 0x6953, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4f70, 0x0000, 0x0000, 0x0000, 0x694d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3377, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6956, 0x0000, 0x0000, 0x695a, 0x0000, 0x0000, 0x0000,
+ 0x4c34, 0x0000, 0x0000, 0x0000, 0x4f2d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6955, 0x0000,
+ 0x695c, 0x695b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x695e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6951, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x695d, 0x0000, 0x695f, 0x434a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_6b[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4737, 0x344e, 0x3b36, 0x5040, 0x6c23, 0x0000, 0x0000, 0x4537,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x537b, 0x0000, 0x0000, 0x0000, 0x0000, 0x6c24,
+ 0x0000, 0x6c25, 0x465b, 0x0000, 0x0000, 0x0000, 0x3f6e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6c26, 0x0000, 0x0000, 0x6c27, 0x502a,
+ 0x0000, 0x4738, 0x0000, 0x0000, 0x3868, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6c28, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5639, 0x557d, 0x344b, 0x323d, 0x4e64, 0x4667,
+ 0x0000, 0x0000, 0x4d61, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3475, 0x0000, 0x4b40, 0x3c5f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6962, 0x6963, 0x516a, 0x6965, 0x0000, 0x3479, 0x6964,
+ 0x0000, 0x5133, 0x4a62, 0x3250, 0x0000, 0x6968, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6966, 0x6967, 0x0000, 0x0000, 0x5633, 0x0000,
+ 0x0000, 0x0000, 0x6969, 0x696a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x696b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x696c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6c2f, 0x4539, 0x364e, 0x0000, 0x5273,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x356e,
+ 0x0000, 0x3b59, 0x6c31, 0x0000, 0x0000, 0x5263, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4e63, 0x0000, 0x4438, 0x0000, 0x433f,
+ 0x0000, 0x0000, 0x363e, 0x5839, 0x3148, 0x314f, 0x3151, 0x457e,
+ 0x0000, 0x3150, 0x0000, 0x432b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5531, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6b24, 0x3a41, 0x0000, 0x0000, 0x0000, 0x4c3a,
+ 0x0000, 0x0000, 0x0000, 0x6b25, 0x0000, 0x6b27, 0x0000, 0x0000,
+ 0x0000, 0x6b28, 0x0000, 0x0000, 0x0000, 0x6b26, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_6c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6b29, 0x6b2b, 0x6b2a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6b2c, 0x0000, 0x4a4f,
+ 0x5835, 0x4371, 0x0000, 0x4325, 0x4678, 0x6b2d, 0x444a, 0x0000,
+ 0x6b2e, 0x6b2f, 0x6b30, 0x3755, 0x0000, 0x0000, 0x0000, 0x377a,
+ 0x0000, 0x6b31, 0x4762, 0x0000, 0x6b33, 0x0000, 0x3a24, 0x5175,
+ 0x3031, 0x6b32, 0x6b34, 0x0000, 0x0000, 0x0000, 0x352a, 0x4248,
+ 0x4768, 0x0000, 0x6b35, 0x0000, 0x4b2e, 0x635f, 0x0000, 0x0000,
+ 0x5340, 0x0000, 0x0000, 0x0000, 0x0000, 0x595b, 0x0000, 0x0000,
+ 0x4d21, 0x562d, 0x4773, 0x0000, 0x0000, 0x0000, 0x5960, 0x3b63,
+ 0x0000, 0x3a3a, 0x6362, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4f2b, 0x0000, 0x0000, 0x0000, 0x6360, 0x4947, 0x0000, 0x3a39,
+ 0x0000, 0x0000, 0x0000, 0x5134, 0x6361, 0x486a, 0x392f, 0x3d2d,
+ 0x3358, 0x4e5b, 0x0000, 0x0000, 0x4c40, 0x0000, 0x0000, 0x0000,
+ 0x6368, 0x6369, 0x4d74, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4c2d, 0x0000, 0x3c33, 0x0000, 0x636a, 0x0000, 0x636b, 0x0000,
+ 0x0000, 0x505a, 0x0000, 0x0000, 0x0000, 0x467b, 0x375a, 0x0000,
+ 0x0000, 0x475f, 0x524a, 0x4e56, 0x0000, 0x6364, 0x636c, 0x0000,
+ 0x4972, 0x3341, 0x0000, 0x0000, 0x6367, 0x0000, 0x0000, 0x4663,
+ 0x6365, 0x0000, 0x0000, 0x6d33, 0x6366, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4933, 0x0000, 0x4566, 0x0000, 0x0000, 0x0000, 0x3935,
+ 0x0000, 0x433b, 0x0000, 0x6363, 0x453d, 0x4124, 0x4259, 0x3257,
+ 0x0000, 0x636d, 0x3b26, 0x442d, 0x0000, 0x6370, 0x3e5a, 0x0000,
+ 0x0000, 0x637b, 0x6375, 0x3a53, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3750, 0x534d, 0x0000, 0x564e, 0x5553, 0x3941, 0x5534, 0x5158,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5039, 0x4776, 0x0000, 0x0000,
+ 0x0000, 0x482a, 0x3234, 0x0000, 0x435a, 0x0000, 0x0000, 0x0000,
+ 0x636e, 0x0000, 0x0000, 0x637c, 0x636f, 0x3728, 0x6377, 0x6374,
+ 0x0000, 0x0000, 0x0000, 0x373a, 0x0000, 0x0000, 0x4522, 0x0000,
+ 0x6376, 0x455d, 0x3228, 0x467c, 0x0000, 0x4460, 0x0000, 0x0000,
+ 0x5722, 0x0000, 0x4061, 0x6379, 0x0000, 0x0000, 0x637a, 0x637d,
+ 0x4c29, 0x6373, 0x0000, 0x533e, 0x0000, 0x3143, 0x6d34, 0x6371,
+ 0x6372, 0x0000, 0x6378, 0x503a, 0x4643, 0x5473, 0x637e, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_6d[] = {
+ 0x0000, 0x3d60, 0x0000, 0x0000, 0x6427, 0x0000, 0x0000, 0x6426,
+ 0x0000, 0x0000, 0x0000, 0x5173, 0x6423, 0x0000, 0x6429, 0x0000,
+ 0x0000, 0x0000, 0x4877, 0x0000, 0x0000, 0x0000, 0x0000, 0x4f34,
+ 0x0000, 0x6428, 0x642e, 0x4265, 0x0000, 0x0000, 0x3634, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3d72, 0x0000, 0x6422,
+ 0x0000, 0x0000, 0x3a69, 0x642a, 0x0000, 0x0000, 0x642c, 0x0000,
+ 0x0000, 0x367d, 0x565e, 0x6432, 0x0000, 0x642d, 0x0000, 0x0000,
+ 0x0000, 0x6421, 0x0000, 0x3b6e, 0x4d5d, 0x4722, 0x4549, 0x0000,
+ 0x0000, 0x4177, 0x0000, 0x6424, 0x0000, 0x4733, 0x3d2c, 0x3d3d,
+ 0x6425, 0x0000, 0x5747, 0x3262, 0x0000, 0x642b, 0x3c43, 0x642f,
+ 0x0000, 0x3b6b, 0x6430, 0x4528, 0x6431, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5563, 0x3f23, 0x0000, 0x643a, 0x0000, 0x6437, 0x0000,
+ 0x643b, 0x0000, 0x0000, 0x643d, 0x0000, 0x0000, 0x4656, 0x0000,
+ 0x0000, 0x3a46, 0x404b, 0x0000, 0x0000, 0x0000, 0x3821, 0x6434,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5421, 0x0000, 0x0000, 0x3a23,
+ 0x3d7e, 0x0000, 0x0000, 0x0000, 0x643c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4d3f, 0x0000, 0x0000, 0x4479, 0x0000, 0x0000,
+ 0x4f7b, 0x4966, 0x0000, 0x0000, 0x533f, 0x0000, 0x4f51, 0x0000,
+ 0x0000, 0x6433, 0x0000, 0x6438, 0x6439, 0x4c69, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4c4e, 0x0000, 0x4054, 0x6435, 0x4130,
+ 0x6436, 0x4e50, 0x0000, 0x3b41, 0x3553, 0x0000, 0x4873, 0x3d27,
+ 0x5547, 0x492c, 0x3822, 0x644a, 0x0000, 0x0000, 0x644c, 0x5144,
+ 0x0000, 0x0000, 0x523a, 0x0000, 0x0000, 0x3a2d, 0x0000, 0x0000,
+ 0x3a54, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6443,
+ 0x356d, 0x0000, 0x0000, 0x0000, 0x574d, 0x6440, 0x4f7d, 0x643f,
+ 0x0000, 0x0000, 0x0000, 0x415c, 0x4c4a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4a67, 0x0000, 0x0000, 0x0000, 0x0000, 0x4457, 0x0000,
+ 0x4c54, 0x6448, 0x0000, 0x0000, 0x0000, 0x6447, 0x6441, 0x0000,
+ 0x6444, 0x352d, 0x0000, 0x0000, 0x5359, 0x0000, 0x6446, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5279, 0x3463, 0x0000, 0x3b34, 0x0000,
+ 0x0000, 0x496e, 0x0000, 0x343e, 0x0000, 0x0000, 0x0000, 0x3b6c,
+ 0x0000, 0x514d, 0x0000, 0x4c6d, 0x6d35, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_6e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4765, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5428, 0x0000, 0x644b, 0x5755, 0x6442, 0x0000,
+ 0x3d25, 0x6445, 0x0000, 0x0000, 0x5366, 0x0000, 0x6449, 0x4978,
+ 0x0000, 0x0000, 0x643e, 0x0000, 0x0000, 0x5365, 0x0000, 0x0000,
+ 0x477e, 0x3649, 0x0000, 0x547c, 0x3233, 0x6457, 0x0000, 0x0000,
+ 0x0000, 0x4e42, 0x0000, 0x644d, 0x0000, 0x4e3c, 0x0000, 0x385b,
+ 0x0000, 0x0000, 0x6456, 0x0000, 0x3f4a, 0x0000, 0x0000, 0x0000,
+ 0x534e, 0x0000, 0x436c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4548, 0x6458, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d44, 0x644f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6454, 0x6455, 0x0000, 0x3a7e, 0x0000,
+ 0x4f66, 0x0000, 0x0000, 0x553f, 0x0000, 0x0000, 0x0000, 0x6452,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6450, 0x0000, 0x0000, 0x644e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d65, 0x4a2a,
+ 0x0000, 0x0000, 0x0000, 0x4023, 0x0000, 0x3d26, 0x6453, 0x0000,
+ 0x0000, 0x3848, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6467,
+ 0x5434, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x645b, 0x0000, 0x0000, 0x0000, 0x416f, 0x0000, 0x0000, 0x6469,
+ 0x0000, 0x0000, 0x5267, 0x0000, 0x0000, 0x645f, 0x0000, 0x6460,
+ 0x0000, 0x0000, 0x4f2a, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b5d,
+ 0x0000, 0x645a, 0x6451, 0x0000, 0x6465, 0x0000, 0x485c, 0x6463,
+ 0x0000, 0x0000, 0x4467, 0x6462, 0x0000, 0x6461, 0x0000, 0x0000,
+ 0x0000, 0x337c, 0x6468, 0x0000, 0x0000, 0x0000, 0x0000, 0x3561,
+ 0x0000, 0x0000, 0x0000, 0x574c, 0x0000, 0x0000, 0x0000, 0x6466,
+ 0x0000, 0x3b2c, 0x0000, 0x5752, 0x4c4f, 0x6b78, 0x0000, 0x6464,
+ 0x0000, 0x0000, 0x3976, 0x0000, 0x0000, 0x0000, 0x564d, 0x6459,
+ 0x645c, 0x427a, 0x645e, 0x0000, 0x424b, 0x4044, 0x4250, 0x0000,
+ 0x3175, 0x4c32, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x354e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x646f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_6f[] = {
+ 0x0000, 0x0000, 0x462f, 0x0000, 0x0000, 0x0000, 0x4661, 0x0000,
+ 0x0000, 0x6475, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4229,
+ 0x0000, 0x0000, 0x0000, 0x406c, 0x515d, 0x646e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x442e, 0x0000, 0x0000, 0x0000, 0x646d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6476, 0x6474, 0x427e, 0x0000, 0x645d, 0x0000, 0x6470,
+ 0x0000, 0x4a7e, 0x0000, 0x5544, 0x0000, 0x0000, 0x6471, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x517a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x646b, 0x646c,
+ 0x0000, 0x0000, 0x0000, 0x6472, 0x0000, 0x4e2b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x454b, 0x0000, 0x0000, 0x0000, 0x4731, 0x0000, 0x423a, 0x0000,
+ 0x0000, 0x0000, 0x646a, 0x0000, 0x0000, 0x0000, 0x414a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c36, 0x3331, 0x0000,
+ 0x0000, 0x0000, 0x647b, 0x0000, 0x6473, 0x0000, 0x0000, 0x0000,
+ 0x647a, 0x0000, 0x647d, 0x0000, 0x647c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x334e, 0x0000, 0x0000, 0x0000,
+ 0x333a, 0x6477, 0x0000, 0x0000, 0x6479, 0x6478, 0x456c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x403d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5468, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6522,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3044, 0x0000, 0x0000, 0x6524, 0x0000,
+ 0x0000, 0x6523, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3c24, 0x0000, 0x6525, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6521, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x647e, 0x3174, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6528, 0x0000,
+ 0x6529, 0x6526, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6527, 0x652a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_70[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4659, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x652b, 0x652d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x652c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x652f, 0x0000, 0x0000,
+ 0x0000, 0x652e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3960, 0x0000, 0x0000, 0x6530,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6531, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3b70, 0x6c61, 0x4370, 0x0000, 0x3546,
+ 0x3b52, 0x0000, 0x0000, 0x0000, 0x0000, 0x4169, 0x546e, 0x0000,
+ 0x3e44, 0x0000, 0x0000, 0x0000, 0x5746, 0x0000, 0x5456, 0x3253,
+ 0x6c3e, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a41, 0x0000, 0x0000,
+ 0x0000, 0x422f, 0x3436, 0x0000, 0x0000, 0x0000, 0x5157, 0x0000,
+ 0x0000, 0x0000, 0x3334, 0x0000, 0x4832, 0x3f3b, 0x6c40, 0x0000,
+ 0x0000, 0x564b, 0x0000, 0x0000, 0x6c3f, 0x6c41, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6c45, 0x3e66, 0x4c3f, 0x455a, 0x3e3c,
+ 0x0000, 0x6c46, 0x0000, 0x317e, 0x0000, 0x0000, 0x0000, 0x6c44,
+ 0x5528, 0x3563, 0x0000, 0x6c42, 0x4136, 0x3363, 0x0000, 0x0000,
+ 0x6c43, 0x4b38, 0x4043, 0x4c7e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4152, 0x0000, 0x6c48, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3a66, 0x4053, 0x0000, 0x5672, 0x0000, 0x0000, 0x0000, 0x514c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3f3e, 0x0000, 0x3733, 0x4955,
+ 0x6c47, 0x3b62, 0x0000, 0x4c4c, 0x3d7d, 0x4848, 0x0000, 0x4f29,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4d69,
+ 0x0000, 0x456b, 0x0000, 0x0000, 0x0000, 0x3769, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_71[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5149, 0x3a38, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6c49, 0x0000, 0x0000, 0x6c4a, 0x0000, 0x3b40, 0x6c4b, 0x0000,
+ 0x6c62, 0x313a, 0x3759, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3d39, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6c4c,
+ 0x5166, 0x6c4d, 0x0000, 0x0000, 0x0000, 0x0000, 0x483b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6c51, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6c53, 0x0000, 0x3b4d, 0x0000, 0x3c65, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6c4f, 0x0000, 0x4937, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x433a, 0x0000, 0x6c63, 0x5555,
+ 0x6c50, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5673, 0x0000,
+ 0x0000, 0x0000, 0x6c52, 0x6c4e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6c54, 0x0000, 0x6c55, 0x0000, 0x0000, 0x493f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4f28, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x505c, 0x0000, 0x0000, 0x0000, 0x0000, 0x512c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x485b, 0x0000, 0x0000, 0x0000,
+ 0x6c56, 0x4e75, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a6c,
+ 0x6c5a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6c59, 0x0000, 0x0000, 0x0000, 0x303e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6c57, 0x0000, 0x6c58, 0x0000, 0x0000,
+ 0x0000, 0x6c64, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x483c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4147, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6c5c, 0x5160, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6c5b, 0x0000, 0x0000, 0x0000, 0x0000, 0x546f, 0x0000, 0x6c5d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b46, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6c5e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_72[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x312c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6c5f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6c60, 0x0000, 0x5726, 0x0000, 0x4540, 0x0000, 0x0000, 0x0000,
+ 0x6b3c, 0x302e, 0x0000, 0x0000, 0x0000, 0x3e74, 0x3838, 0x522f,
+ 0x3056, 0x3579, 0x0000, 0x5833, 0x0000, 0x4b2c, 0x0000, 0x635d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x462c,
+ 0x3066, 0x0000, 0x0000, 0x0000, 0x4546, 0x6b39, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6b3a, 0x0000, 0x0000, 0x0000, 0x6b3b, 0x0000,
+ 0x0000, 0x5140, 0x0000, 0x4523, 0x0000, 0x6a72, 0x0000, 0x4432,
+ 0x0000, 0x4435, 0x404e, 0x0000, 0x0000, 0x0000, 0x6a73, 0x4441,
+ 0x0000, 0x4e6f, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a70, 0x6a74,
+ 0x0000, 0x0000, 0x497c, 0x0000, 0x0000, 0x4723, 0x0000, 0x0000,
+ 0x0000, 0x4c58, 0x4e7e, 0x0000, 0x0000, 0x0000, 0x6a75, 0x6a76,
+ 0x4f2c, 0x4067, 0x0000, 0x0000, 0x6a77, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x363f, 0x6a78, 0x0000, 0x6a79, 0x0000, 0x6a7a,
+ 0x0000, 0x0000, 0x6a7b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a71,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x482e, 0x616b, 0x0000, 0x3738,
+ 0x616c, 0x0000, 0x0000, 0x0000, 0x616d, 0x0000, 0x5734, 0x616e,
+ 0x616f, 0x534c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6171, 0x3f71, 0x6170, 0x3552, 0x0000, 0x0000, 0x0000,
+ 0x3137, 0x0000, 0x0000, 0x0000, 0x0000, 0x6173, 0x6172, 0x0000,
+ 0x3a7c, 0x0000, 0x6174, 0x0000, 0x0000, 0x0000, 0x0000, 0x3937,
+ 0x0000, 0x3e51, 0x0000, 0x0000, 0x0000, 0x0000, 0x447c, 0x0000,
+ 0x3a5d, 0x3d46, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6175, 0x6177, 0x0000, 0x0000, 0x3640, 0x4f41, 0x4a28, 0x6176,
+ 0x5578, 0x537c, 0x6178, 0x617c, 0x6179, 0x0000, 0x0000, 0x617a,
+ 0x406a, 0x0000, 0x617e, 0x6221, 0x4047, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_73[] = {
+ 0x0000, 0x617b, 0x0000, 0x617d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6225, 0x0000, 0x0000, 0x0000, 0x4154, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6223, 0x0000, 0x6228, 0x327e, 0x6222,
+ 0x0000, 0x0000, 0x0000, 0x434d, 0x3242, 0x6227, 0x6226, 0x0000,
+ 0x0000, 0x6224, 0x6229, 0x0000, 0x0000, 0x622b, 0x0000, 0x0000,
+ 0x0000, 0x5049, 0x566d, 0x4328, 0x622c, 0x0000, 0x4f57, 0x0000,
+ 0x0000, 0x622e, 0x0000, 0x0000, 0x3a6f, 0x0000, 0x0000, 0x6960,
+ 0x622d, 0x622a, 0x0000, 0x0000, 0x0000, 0x0000, 0x3b2b, 0x5433,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6230, 0x0000, 0x0000,
+ 0x622f, 0x0000, 0x6961, 0x0000, 0x0000, 0x0000, 0x0000, 0x6231,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6232, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6233, 0x4c21, 0x0000, 0x6234,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6235, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x507e, 0x0000, 0x0000, 0x424a,
+ 0x0000, 0x5371, 0x0000, 0x4d75, 0x0000, 0x0000, 0x6760, 0x0000,
+ 0x0000, 0x6761, 0x0000, 0x0000, 0x0000, 0x0000, 0x3e41, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x426a, 0x0000, 0x0000, 0x0000, 0x6764,
+ 0x0000, 0x0000, 0x6763, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4d66, 0x0000, 0x4335, 0x0000, 0x0000, 0x6762, 0x3b37,
+ 0x4f56, 0x0000, 0x4161, 0x6769, 0x0000, 0x0000, 0x0000, 0x6768,
+ 0x0000, 0x0000, 0x6774, 0x3223, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x676a, 0x0000, 0x6766, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x676c, 0x676b, 0x493a, 0x0000, 0x0000, 0x5564, 0x0000, 0x6765,
+ 0x3729, 0x6767, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x676e, 0x0000, 0x0000, 0x0000, 0x0000, 0x6773, 0x0000,
+ 0x5669, 0x0000, 0x0000, 0x0000, 0x0000, 0x676d, 0x0000, 0x6772,
+ 0x0000, 0x6771, 0x0000, 0x0000, 0x0000, 0x3060, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6775, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_74[] = {
+ 0x0000, 0x0000, 0x0000, 0x4772, 0x0000, 0x4045, 0x406d, 0x0000,
+ 0x0000, 0x4170, 0x6770, 0x0000, 0x0000, 0x0000, 0x0000, 0x6776,
+ 0x4b76, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6822, 0x6821, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5741, 0x0000, 0x0000, 0x677a, 0x6779, 0x0000,
+ 0x677b, 0x0000, 0x6777, 0x0000, 0x677e, 0x0000, 0x677d, 0x0000,
+ 0x677c, 0x0000, 0x0000, 0x4155, 0x4759, 0x457d, 0x4543, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x476d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6823, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6826, 0x0000, 0x6825,
+ 0x0000, 0x6827, 0x3a77, 0x6778, 0x6824, 0x0000, 0x4870, 0x492a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6829, 0x0000, 0x0000,
+ 0x3965, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x517e, 0x6828,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x682a, 0x0000,
+ 0x682d, 0x682e, 0x0000, 0x4127, 0x0000, 0x0000, 0x0000, 0x682f,
+ 0x0000, 0x0000, 0x0000, 0x6830, 0x0000, 0x0000, 0x682c, 0x0000,
+ 0x6834, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x682b, 0x0000, 0x6831, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6835,
+ 0x6832, 0x6833, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6837, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6836, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x394f, 0x0000, 0x702c, 0x0000,
+ 0x702d, 0x0000, 0x4630, 0x306a, 0x483f, 0x0000, 0x4d5f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e4d, 0x6a31,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6a32, 0x0000, 0x463f, 0x3449,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a33
+};
+
+static unsigned short gb2312_from_unicode_75[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5567, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5d79, 0x0000, 0x6a34,
+ 0x0000, 0x6a35, 0x0000, 0x6a36, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x384a, 0x5f30, 0x4975, 0x0000, 0x4c70, 0x0000, 0x0000, 0x497a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x497b, 0x0000, 0x0000,
+ 0x5343, 0x4b26, 0x0000, 0x3826, 0x702e, 0x3142, 0x0000, 0x6538,
+ 0x4c6f, 0x5349, 0x3c57, 0x496a, 0x0000, 0x3567, 0x0000, 0x4450,
+ 0x3569, 0x0000, 0x6e2e, 0x3b2d, 0x0000, 0x0000, 0x675e, 0x0000,
+ 0x6e2f, 0x0000, 0x0000, 0x0000, 0x0000, 0x3329, 0x0000, 0x0000,
+ 0x6e32, 0x0000, 0x0000, 0x6e31, 0x3d67, 0x0000, 0x6e30, 0x4e37,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x454f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4174, 0x5b4e, 0x6e33, 0x5073, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4254, 0x4668, 0x0000,
+ 0x0000, 0x0000, 0x372c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6e34, 0x0000, 0x336b, 0x0000, 0x0000, 0x0000,
+ 0x3b7b, 0x6e35, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x675c,
+ 0x0000, 0x0000, 0x0000, 0x6e36, 0x0000, 0x0000, 0x3d2e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7162, 0x0000, 0x0000, 0x0000, 0x4a68,
+ 0x0000, 0x5249, 0x705a, 0x0000, 0x705b, 0x0000, 0x705c, 0x4146,
+ 0x0000, 0x386d, 0x3e4e, 0x0000, 0x0000, 0x705e, 0x0000, 0x4531,
+ 0x705d, 0x5171, 0x0000, 0x7060, 0x304c, 0x3d6a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x525f, 0x705f, 0x0000, 0x342f, 0x3768,
+ 0x7066, 0x7065, 0x4623, 0x7061, 0x7062, 0x3443, 0x0000, 0x0000,
+ 0x7063, 0x556e, 0x0000, 0x0000, 0x4c5b, 0x3e52, 0x3c32, 0x0000,
+ 0x0000, 0x0000, 0x7068, 0x7067, 0x7064, 0x3221, 0x0000, 0x5622,
+ 0x5338, 0x3e37, 0x482c, 0x0000, 0x0000, 0x706a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5177, 0x0000, 0x564c, 0x3a5b, 0x7069, 0x0000,
+ 0x363b, 0x0000, 0x0000, 0x4d34, 0x0000, 0x0000, 0x4626, 0x0000,
+ 0x0000, 0x0000, 0x4121, 0x706b, 0x706e, 0x0000, 0x706d, 0x7070,
+ 0x706c, 0x0000, 0x3b3e, 0x706f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4c35, 0x7072, 0x0000, 0x0000, 0x3355, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3154, 0x0000, 0x0000, 0x7073, 0x0000, 0x0000, 0x7074
+};
+
+static unsigned short gb2312_from_unicode_76[] = {
+ 0x7076, 0x3461, 0x0000, 0x7071, 0x0000, 0x7077, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x707a, 0x0000, 0x7078, 0x0000, 0x0000, 0x0000,
+ 0x7075, 0x0000, 0x0000, 0x0000, 0x0000, 0x707d, 0x0000, 0x7079,
+ 0x707c, 0x707e, 0x0000, 0x7121, 0x0000, 0x0000, 0x0000, 0x4e41,
+ 0x7124, 0x0000, 0x7123, 0x0000, 0x4176, 0x707b, 0x4a5d, 0x0000,
+ 0x0000, 0x3471, 0x3171, 0x4c31, 0x0000, 0x7126, 0x0000, 0x0000,
+ 0x7127, 0x0000, 0x0000, 0x712c, 0x554e, 0x7129, 0x0000, 0x0000,
+ 0x4833, 0x0000, 0x0000, 0x0000, 0x7122, 0x0000, 0x712b, 0x7128,
+ 0x7125, 0x0000, 0x0000, 0x712a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3029, 0x712d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x712f, 0x0000, 0x7131, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7130, 0x0000, 0x712e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5122, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7132, 0x0000, 0x0000, 0x0000, 0x7133,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x396f, 0x0000, 0x0000, 0x3547, 0x0000, 0x3057, 0x3059, 0x0000,
+ 0x0000, 0x0000, 0x546d, 0x0000, 0x3544, 0x0000, 0x3d54, 0x3b4a,
+ 0x7027, 0x0000, 0x0000, 0x385e, 0x0000, 0x0000, 0x7028, 0x0000,
+ 0x0000, 0x3028, 0x0000, 0x7029, 0x0000, 0x0000, 0x4d6e, 0x0000,
+ 0x0000, 0x702a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x702b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4624, 0x0000,
+ 0x0000, 0x5665, 0x7164, 0x0000, 0x7165, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4373,
+ 0x0000, 0x0000, 0x535b, 0x0000, 0x0000, 0x5651, 0x4568, 0x0000,
+ 0x532f, 0x0000, 0x5266, 0x0000, 0x0000, 0x6e41, 0x303b, 0x5535,
+ 0x514e, 0x3c60, 0x3a50, 0x0000, 0x3f78, 0x0000, 0x3847, 0x3541,
+ 0x454c, 0x0000, 0x0000, 0x4a22, 0x0000, 0x0000, 0x0000, 0x434b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6e42, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x443f, 0x3622,
+ 0x0000, 0x6d6c, 0x4324, 0x0000, 0x5631, 0x0000, 0x0000, 0x0000,
+ 0x4f60, 0x6d6f, 0x0000, 0x0000, 0x454e, 0x0000, 0x365c, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_77[] = {
+ 0x0000, 0x4a21, 0x0000, 0x0000, 0x6d6d, 0x0000, 0x0000, 0x6d70,
+ 0x6d71, 0x433c, 0x0000, 0x3f34, 0x0000, 0x6d6e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6d74, 0x6d72, 0x0000, 0x0000, 0x0000, 0x0000, 0x5566,
+ 0x435f, 0x0000, 0x6d73, 0x0000, 0x0000, 0x0000, 0x6d76, 0x0000,
+ 0x5523, 0x5123, 0x0000, 0x0000, 0x0000, 0x6d75, 0x0000, 0x4350,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d77, 0x3f74, 0x3e6c,
+ 0x6d78, 0x0000, 0x4c77, 0x0000, 0x515b, 0x0000, 0x0000, 0x0000,
+ 0x5745, 0x5576, 0x0000, 0x6d7c, 0x0000, 0x0000, 0x0000, 0x6d7b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6d79, 0x6d7a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6d7d, 0x3e26, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4b2f, 0x6e21, 0x363d, 0x0000, 0x6e22, 0x4440, 0x0000,
+ 0x6d7e, 0x0000, 0x0000, 0x3d5e, 0x3247, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3643, 0x0000, 0x0000, 0x0000, 0x6e25, 0x583a, 0x6e23,
+ 0x6e26, 0x0000, 0x0000, 0x0000, 0x4369, 0x3372, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6e27, 0x6e24, 0x4f39, 0x0000,
+ 0x0000, 0x6e28, 0x4277, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6e29,
+ 0x6e2a, 0x0000, 0x5e2b, 0x0000, 0x0000, 0x4633, 0x0000, 0x4746,
+ 0x0000, 0x5675, 0x3549, 0x0000, 0x4b32, 0x0000, 0x0000, 0x0000,
+ 0x6e2b, 0x0000, 0x0000, 0x4d2b, 0x0000, 0x6e2c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5530, 0x0000, 0x6e2d, 0x0000, 0x7644,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b47, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3423,
+ 0x0000, 0x0000, 0x0000, 0x432c, 0x7166, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4a38, 0x5253, 0x0000, 0x562a, 0x0000, 0x6f72,
+ 0x0000, 0x3e58, 0x0000, 0x3d43, 0x6f73, 0x364c, 0x302b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4a2f, 0x0000, 0x0000, 0x6d36, 0x0000,
+ 0x6d37, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e79, 0x372f, 0x3f73
+};
+
+static unsigned short gb2312_from_unicode_78[] = {
+ 0x6d38, 0x426b, 0x4930, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6d39, 0x0000, 0x0000, 0x4676, 0x3f33, 0x0000, 0x0000,
+ 0x0000, 0x6d3c, 0x4578, 0x0000, 0x5150, 0x0000, 0x5729, 0x6d3a,
+ 0x6d3b, 0x0000, 0x5162, 0x0000, 0x6d3f, 0x6d40, 0x0000, 0x6d44,
+ 0x0000, 0x0000, 0x0000, 0x6d48, 0x0000, 0x6d46, 0x6d4e, 0x5568,
+ 0x0000, 0x6d49, 0x0000, 0x0000, 0x6d47, 0x6d3e, 0x0000, 0x0000,
+ 0x4569, 0x0000, 0x0000, 0x0000, 0x4646, 0x0000, 0x0000, 0x4969,
+ 0x5452, 0x6d41, 0x6d42, 0x6d43, 0x6d45, 0x0000, 0x4079, 0x0000,
+ 0x3421, 0x0000, 0x0000, 0x0000, 0x0000, 0x3968, 0x0000, 0x6d50,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6d51, 0x0000, 0x6d4a, 0x0000,
+ 0x6d4f, 0x0000, 0x4e78, 0x0000, 0x0000, 0x4b36, 0x6d4c, 0x6d4d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4f75, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6d52, 0x4172, 0x5332, 0x6d4b, 0x4837, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3c6f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4570, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d56,
+ 0x0000, 0x356f, 0x0000, 0x0000, 0x4235, 0x302d, 0x4b69, 0x0000,
+ 0x0000, 0x312e, 0x0000, 0x6d54, 0x0000, 0x0000, 0x0000, 0x4d6b,
+ 0x3562, 0x0000, 0x6d55, 0x6d53, 0x6d57, 0x0000, 0x0000, 0x357a,
+ 0x0000, 0x6d58, 0x0000, 0x6d59, 0x0000, 0x6d5c, 0x0000, 0x314c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4576, 0x3c6e, 0x6d5a, 0x4c3c, 0x326a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6d5b, 0x0000, 0x0000, 0x0000, 0x0000, 0x446b, 0x0000,
+ 0x0000, 0x3445, 0x0000, 0x0000, 0x0000, 0x3075, 0x0000, 0x0000,
+ 0x0000, 0x6d5f, 0x405a, 0x3468, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x454d, 0x0000, 0x0000, 0x0000, 0x6d5d, 0x3f44, 0x0000, 0x0000,
+ 0x0000, 0x6d5e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4425, 0x0000, 0x0000, 0x0000, 0x6d60, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6d61, 0x0000, 0x6d63, 0x0000, 0x0000, 0x4157,
+ 0x0000, 0x0000, 0x3b47, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_79[] = {
+ 0x0000, 0x3d38, 0x0000, 0x0000, 0x0000, 0x6d62, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6d64, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d66, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6d65, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6d67, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4a3e, 0x6c6a, 0x4071, 0x0000, 0x4967, 0x0000,
+ 0x6c6b, 0x466e, 0x0000, 0x0000, 0x0000, 0x0000, 0x6c6c, 0x0000,
+ 0x466d, 0x6c6d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6c70, 0x0000, 0x0000, 0x5766, 0x6c73,
+ 0x0000, 0x0000, 0x6c71, 0x6c6e, 0x6c6f, 0x5723, 0x4971, 0x4b6e,
+ 0x6c74, 0x0000, 0x6c72, 0x0000, 0x0000, 0x4f69, 0x0000, 0x6c76,
+ 0x4631, 0x0000, 0x0000, 0x0000, 0x0000, 0x3c40, 0x0000, 0x6c75,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x353b,
+ 0x3b76, 0x0000, 0x6c77, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5977, 0x3d7b, 0x0000, 0x0000, 0x423b, 0x6c78, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6c79, 0x0000, 0x0000, 0x0000, 0x0000, 0x3823,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6c7a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6c7b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6c7c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x536d, 0x582e, 0x406b, 0x0000, 0x475d, 0x3a4c, 0x0000,
+ 0x5063, 0x4b3d, 0x0000, 0x4d3a, 0x0000, 0x0000, 0x3851, 0x0000,
+ 0x0000, 0x317c, 0x0000, 0x476f, 0x0000, 0x5656, 0x0000, 0x0000,
+ 0x0000, 0x3f46, 0x436b, 0x0000, 0x0000, 0x6f75, 0x0000, 0x0000,
+ 0x4358, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5762,
+ 0x0000, 0x0000, 0x0000, 0x6f77, 0x3353, 0x0000, 0x4758, 0x516d,
+ 0x0000, 0x5648, 0x0000, 0x6f78, 0x0000, 0x6f76, 0x0000, 0x3b7d,
+ 0x3346, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3d55, 0x0000, 0x0000, 0x5246, 0x0000, 0x3b60, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_7a[] = {
+ 0x4f21, 0x0000, 0x6f7c, 0x6f7b, 0x0000, 0x0000, 0x6f79, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x334c, 0x0000, 0x4954, 0x4b30, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6f7e, 0x0000, 0x0000, 0x305e,
+ 0x0000, 0x0000, 0x5649, 0x0000, 0x0000, 0x0000, 0x6f7d, 0x0000,
+ 0x336d, 0x0000, 0x0000, 0x7655, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4e48, 0x0000, 0x0000, 0x0000, 0x7022,
+ 0x0000, 0x7021, 0x0000, 0x353e, 0x3c5a, 0x3b7c, 0x0000, 0x3865,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4442, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7023, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b6b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7026, 0x0000, 0x0000, 0x0000, 0x5128, 0x0000, 0x3e3f, 0x476e,
+ 0x7136, 0x7137, 0x3f55, 0x0000, 0x0000, 0x0000, 0x0000, 0x3429,
+ 0x7138, 0x4d3b, 0x0000, 0x4754, 0x552d, 0x0000, 0x7139, 0x0000,
+ 0x713a, 0x0000, 0x0000, 0x0000, 0x0000, 0x474f, 0x0000, 0x0000,
+ 0x0000, 0x5224, 0x564f, 0x0000, 0x0000, 0x713b, 0x3d51, 0x3430,
+ 0x3e3d, 0x0000, 0x0000, 0x0000, 0x345c, 0x4e51, 0x0000, 0x3f5f,
+ 0x713d, 0x0000, 0x0000, 0x0000, 0x0000, 0x3f7a, 0x713c, 0x0000,
+ 0x713f, 0x0000, 0x0000, 0x0000, 0x713e, 0x7140, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7141, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x417e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4122, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a7a, 0x0000,
+ 0x0000, 0x553e, 0x0000, 0x0000, 0x0000, 0x0000, 0x3e3a, 0x3e39,
+ 0x5542, 0x0000, 0x0000, 0x3f22, 0x0000, 0x4d2f, 0x7135, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3d5f, 0x0000, 0x364b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5671, 0x7343, 0x0000, 0x0000, 0x7344, 0x0000, 0x384d
+};
+
+static unsigned short gb2312_from_unicode_7b[] = {
+ 0x0000, 0x0000, 0x0000, 0x7346, 0x7347, 0x0000, 0x304a, 0x0000,
+ 0x7345, 0x0000, 0x7349, 0x4b71, 0x0000, 0x0000, 0x0000, 0x734b,
+ 0x0000, 0x5026, 0x0000, 0x0000, 0x314a, 0x7348, 0x0000, 0x0000,
+ 0x0000, 0x734f, 0x0000, 0x3551, 0x0000, 0x0000, 0x7357, 0x0000,
+ 0x7352, 0x0000, 0x0000, 0x0000, 0x7354, 0x7353, 0x377b, 0x0000,
+ 0x313f, 0x0000, 0x734e, 0x734a, 0x355a, 0x0000, 0x7350, 0x0000,
+ 0x0000, 0x7351, 0x0000, 0x7355, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x734d, 0x0000, 0x3c63, 0x0000, 0x417d, 0x0000, 0x7356, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x735a, 0x0000, 0x734c,
+ 0x0000, 0x3548, 0x0000, 0x3d6e, 0x735c, 0x0000, 0x0000, 0x3724,
+ 0x3f70, 0x567e, 0x4d32, 0x0000, 0x3470, 0x0000, 0x325f, 0x0000,
+ 0x7358, 0x0000, 0x7359, 0x4938, 0x0000, 0x735d, 0x0000, 0x0000,
+ 0x735e, 0x0000, 0x7361, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x735f, 0x0000,
+ 0x0000, 0x7363, 0x7362, 0x0000, 0x0000, 0x735b, 0x0000, 0x3f6a,
+ 0x0000, 0x336f, 0x0000, 0x7360, 0x0000, 0x0000, 0x4729, 0x0000,
+ 0x3c72, 0x0000, 0x0000, 0x0000, 0x0000, 0x736b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x393f, 0x0000, 0x0000,
+ 0x7364, 0x0000, 0x0000, 0x0000, 0x322d, 0x3b7e, 0x0000, 0x4b63,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x736d, 0x7369, 0x0000, 0x0000,
+ 0x0000, 0x395c, 0x736e, 0x0000, 0x0000, 0x0000, 0x7365, 0x7366,
+ 0x736a, 0x4261, 0x736c, 0x736f, 0x7368, 0x3c7d, 0x0000, 0x0000,
+ 0x0000, 0x4f64, 0x0000, 0x0000, 0x7370, 0x0000, 0x0000, 0x0000,
+ 0x7367, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7372, 0x0000, 0x0000, 0x0000, 0x0000, 0x572d, 0x462a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7373, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7371, 0x0000, 0x4228, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x385d, 0x7375, 0x0000, 0x0000, 0x7374, 0x0000, 0x0000,
+ 0x0000, 0x345b, 0x0000, 0x0000, 0x0000, 0x7376, 0x7377, 0x0000,
+ 0x0000, 0x0000, 0x7378, 0x0000, 0x0000, 0x0000, 0x403a, 0x0000,
+ 0x0000, 0x4069, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4571,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x737b, 0x0000, 0x737a, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_7c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3458,
+ 0x0000, 0x0000, 0x0000, 0x737e, 0x7379, 0x0000, 0x0000, 0x737c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x737d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7421,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7423, 0x3b49,
+ 0x0000, 0x0000, 0x7422, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7424, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x323e,
+ 0x7426, 0x7425, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3c2e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4357, 0x5961, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4060, 0x744c, 0x5751, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x375b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x744e, 0x4123, 0x0000, 0x0000, 0x4649, 0x0000, 0x3456,
+ 0x5533, 0x0000, 0x0000, 0x0000, 0x7450, 0x744f, 0x7451, 0x4b5a,
+ 0x0000, 0x0000, 0x7452, 0x0000, 0x5441, 0x5660, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3760, 0x0000, 0x0000, 0x0000, 0x4138, 0x0000,
+ 0x0000, 0x413b, 0x7453, 0x3e2c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3462, 0x0000, 0x0000, 0x7454, 0x7455, 0x3e2b, 0x0000,
+ 0x0000, 0x7456, 0x0000, 0x0000, 0x0000, 0x745b, 0x0000, 0x7457,
+ 0x745a, 0x0000, 0x3a7d, 0x0000, 0x7458, 0x7459, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3862, 0x4c47, 0x745c,
+ 0x0000, 0x325a, 0x0000, 0x0000, 0x4353, 0x0000, 0x0000, 0x5463,
+ 0x3f37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x745d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4534,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7469, 0x0000, 0x0000, 0x4f35, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_7d[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4e49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4b58, 0x0000, 0x4b77, 0x0000, 0x0000, 0x0000, 0x0000, 0x3d74,
+ 0x0000, 0x0000, 0x0000, 0x574f, 0x0000, 0x0000, 0x0000, 0x405b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5075, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x746a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x746b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x746c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_7e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7763, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3731, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x746d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x576b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x746e, 0x0000, 0x0000, 0x0000, 0x6679,
+ 0x3e40, 0x667a, 0x3a6c, 0x667b, 0x4f4b, 0x667c, 0x543c, 0x3c36,
+ 0x667d, 0x667e, 0x3c4d, 0x4852, 0x4e33, 0x6721, 0x0000, 0x343f,
+ 0x6722, 0x4934, 0x3859, 0x4449, 0x0000, 0x575d, 0x425a, 0x3757,
+ 0x563d, 0x4e46, 0x3744, 0x0000, 0x0000, 0x4526, 0x6723, 0x4f5f,
+ 0x6724, 0x6725, 0x6726, 0x4137, 0x5769, 0x4970, 0x4f38, 0x562f,
+ 0x5655, 0x6727, 0x306d, 0x6728, 0x6729, 0x495c, 0x526f, 0x3e2d,
+ 0x672a, 0x3073, 0x485e, 0x3d61, 0x672b, 0x4846, 0x0000, 0x672c,
+ 0x3b66, 0x3878, 0x5124, 0x672d, 0x4267, 0x3e78, 0x3d4a, 0x4d33,
+ 0x672e, 0x672f, 0x3e6e, 0x5065, 0x0000, 0x4b67, 0x4c50, 0x3c4c,
+ 0x6730, 0x3c28, 0x5077, 0x6731, 0x0000, 0x5078, 0x6732, 0x6733,
+ 0x3442, 0x6734, 0x6735, 0x497e, 0x4e2c, 0x4360, 0x6737, 0x3141,
+ 0x3371, 0x0000, 0x6738, 0x6739, 0x575b, 0x5540, 0x673a, 0x424c
+};
+
+static unsigned short gb2312_from_unicode_7f[] = {
+ 0x573a, 0x673b, 0x673c, 0x673d, 0x3c6a, 0x4365, 0x4042, 0x673e,
+ 0x673f, 0x3c29, 0x0000, 0x6740, 0x6741, 0x6736, 0x3650, 0x6742,
+ 0x0000, 0x6743, 0x6744, 0x3b3a, 0x355e, 0x4246, 0x3160, 0x6745,
+ 0x5435, 0x6746, 0x383f, 0x6748, 0x6747, 0x376c, 0x0000, 0x6749,
+ 0x3278, 0x674a, 0x674b, 0x674c, 0x674d, 0x674e, 0x674f, 0x6750,
+ 0x5327, 0x4b75, 0x6751, 0x6752, 0x6753, 0x6754, 0x4949, 0x6755,
+ 0x6756, 0x6757, 0x6758, 0x6759, 0x3d49, 0x675a, 0x733e, 0x0000,
+ 0x3857, 0x0000, 0x4831, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x733f, 0x0000, 0x7340, 0x7341, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x395e, 0x4d78, 0x0000, 0x0000, 0x5868, 0x3a31, 0x0000, 0x425e,
+ 0x6e37, 0x0000, 0x3723, 0x0000, 0x0000, 0x0000, 0x0000, 0x6e39,
+ 0x0000, 0x6e38, 0x3055, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6e3b, 0x5556, 0x576f, 0x0000, 0x0000, 0x0000, 0x5643, 0x0000,
+ 0x0000, 0x6e3d, 0x4a70, 0x0000, 0x6e3c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6e3e, 0x0000, 0x0000, 0x0000, 0x0000, 0x6e40, 0x0000,
+ 0x0000, 0x6e3f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5172, 0x0000, 0x473c, 0x0000, 0x4340, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3861, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4167, 0x0000, 0x0000, 0x7446, 0x505f, 0x7447,
+ 0x0000, 0x4f5b, 0x0000, 0x0000, 0x483a, 0x0000, 0x0000, 0x7448,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7449,
+ 0x744a, 0x0000, 0x744b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x597a, 0x387e, 0x0000, 0x0000, 0x6571, 0x5370, 0x0000, 0x7460,
+ 0x0000, 0x4e4c, 0x0000, 0x0000, 0x0000, 0x3361, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7134, 0x0000, 0x526e, 0x0000, 0x7461, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4f68, 0x7462, 0x0000, 0x0000,
+ 0x474c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3554,
+ 0x3464, 0x7464, 0x0000, 0x0000, 0x0000, 0x7463, 0x7465, 0x0000,
+ 0x0000, 0x7466, 0x0000, 0x0000, 0x0000, 0x0000, 0x7467, 0x0000,
+ 0x3a32, 0x303f, 0x0000, 0x7468, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x372d, 0x526d, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_80[] = {
+ 0x522b, 0x404f, 0x0000, 0x3f3c, 0x6b23, 0x555f, 0x6a48, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7173, 0x3678, 0x4b23, 0x0000, 0x0000,
+ 0x444d, 0x0000, 0x7167, 0x0000, 0x7168, 0x387b, 0x7169, 0x3a44,
+ 0x5445, 0x3052, 0x0000, 0x0000, 0x716a, 0x0000, 0x0000, 0x0000,
+ 0x716b, 0x0000, 0x716c, 0x0000, 0x0000, 0x716d, 0x716e, 0x716f,
+ 0x7171, 0x7170, 0x4555, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7172, 0x0000, 0x367a, 0x0000, 0x7174, 0x522e, 0x5e47,
+ 0x4b4a, 0x0000, 0x0000, 0x335c, 0x0000, 0x3522, 0x0000, 0x3922,
+ 0x0000, 0x0000, 0x4474, 0x7175, 0x0000, 0x0000, 0x7176, 0x0000,
+ 0x0000, 0x0000, 0x4144, 0x417b, 0x5630, 0x7177, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7178, 0x0000, 0x412a, 0x0000, 0x0000, 0x0000,
+ 0x4638, 0x0000, 0x3e5b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7179, 0x344f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x717a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6d32,
+ 0x6d31, 0x0000, 0x0000, 0x4b60, 0x525e, 0x0000, 0x4b41, 0x5558,
+ 0x0000, 0x4862, 0x0000, 0x405f, 0x3c21, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6b41, 0x0000, 0x0000, 0x5024, 0x0000,
+ 0x5662, 0x0000, 0x3647, 0x3858, 0x6b40, 0x384e, 0x0000, 0x6b3f,
+ 0x3326, 0x3949, 0x562b, 0x0000, 0x3774, 0x374a, 0x0000, 0x0000,
+ 0x0000, 0x3c67, 0x373e, 0x6b46, 0x0000, 0x6b47, 0x3039, 0x3f4f,
+ 0x0000, 0x6b45, 0x537d, 0x0000, 0x6b48, 0x0000, 0x0000, 0x6b49,
+ 0x0000, 0x0000, 0x374e, 0x0000, 0x6b42, 0x6b44, 0x4976, 0x5657,
+ 0x554d, 0x5032, 0x6b4f, 0x4e38, 0x6b50, 0x0000, 0x3528, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3133, 0x6b52, 0x4c25, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4556, 0x6b53,
+ 0x0000, 0x6b51, 0x455f, 0x6b4e, 0x4a24, 0x6b55, 0x307b, 0x0000,
+ 0x0000, 0x3a7a, 0x0000, 0x0000, 0x5837, 0x7163, 0x0000, 0x6b4a,
+ 0x6b4b, 0x6b4c, 0x6b4d, 0x6b56, 0x6640, 0x6b59, 0x0000, 0x3f68,
+ 0x5248, 0x6b57, 0x6b5c, 0x386c, 0x6b58, 0x0000, 0x3d3a, 0x0000,
+ 0x5058, 0x0000, 0x3037, 0x0000, 0x6b5d, 0x445c, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_81[] = {
+ 0x0000, 0x0000, 0x562c, 0x0000, 0x0000, 0x0000, 0x3460, 0x0000,
+ 0x0000, 0x4276, 0x3c39, 0x0000, 0x0000, 0x6b5a, 0x6b5b, 0x5460,
+ 0x466a, 0x4454, 0x6b5f, 0x4527, 0x5975, 0x0000, 0x3231, 0x0000,
+ 0x6b64, 0x0000, 0x3d45, 0x0000, 0x0000, 0x0000, 0x6b62, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6b63, 0x0000, 0x0000, 0x382c,
+ 0x0000, 0x4d51, 0x6b65, 0x0000, 0x0000, 0x0000, 0x6b61, 0x0000,
+ 0x4133, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4622, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c73, 0x0000,
+ 0x6b66, 0x0000, 0x4030, 0x5238, 0x6b67, 0x0000, 0x0000, 0x0000,
+ 0x382f, 0x382d, 0x0000, 0x6b68, 0x473b, 0x4d73, 0x0000, 0x0000,
+ 0x0000, 0x6b6a, 0x6b6b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6b6d, 0x0000, 0x0000, 0x0000, 0x0000, 0x5048, 0x0000, 0x6b72,
+ 0x0000, 0x6b6e, 0x0000, 0x0000, 0x0000, 0x6b71, 0x4879, 0x0000,
+ 0x517c, 0x6b6c, 0x0000, 0x0000, 0x6b69, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3839, 0x4f59, 0x4465, 0x6b6f, 0x6b70, 0x4c5a, 0x4d48,
+ 0x3072, 0x0000, 0x6b76, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6b75, 0x0000, 0x3232, 0x0000, 0x0000, 0x0000, 0x0000, 0x3860,
+ 0x0000, 0x6b77, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x316c, 0x0000, 0x0000, 0x4c45, 0x4424, 0x4f25, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6b79, 0x0000, 0x0000, 0x6c22, 0x0000,
+ 0x4572, 0x0000, 0x6b7a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4945, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x625f, 0x6b7e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4d4e, 0x6c21, 0x315b, 0x5337, 0x0000, 0x0000, 0x525c, 0x0000,
+ 0x0000, 0x0000, 0x6b7d, 0x0000, 0x6b7b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x333c, 0x0000, 0x0000, 0x0000, 0x6a30,
+ 0x0000, 0x0000, 0x5754, 0x0000, 0x742b, 0x3374, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5641, 0x5642, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5569, 0x3e4a, 0x0000, 0x7427, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_82[] = {
+ 0x5228, 0x7428, 0x7429, 0x0000, 0x742a, 0x3e4b, 0x535f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4960, 0x4961, 0x0000, 0x0000,
+ 0x7342, 0x0000, 0x4a66, 0x0000, 0x4c72, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6236, 0x4b34, 0x0000, 0x4e68, 0x565b,
+ 0x0000, 0x742d, 0x742e, 0x742f, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7432, 0x0000, 0x3a3d, 0x7433, 0x3063, 0x7430, 0x0000, 0x7431,
+ 0x3d22, 0x3255, 0x0000, 0x7436, 0x7437, 0x3666, 0x3230, 0x4f4f,
+ 0x7434, 0x342c, 0x0000, 0x7435, 0x0000, 0x0000, 0x7438, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7439, 0x0000, 0x0000, 0x4d27,
+ 0x0000, 0x743a, 0x0000, 0x743b, 0x0000, 0x0000, 0x0000, 0x743c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4b52, 0x0000, 0x743d, 0x0000, 0x0000, 0x0000, 0x0000, 0x743e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x743f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x745e, 0x413c,
+ 0x3c68, 0x0000, 0x492b, 0x515e, 0x6575, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5c33, 0x5255, 0x0000, 0x0000, 0x5c34, 0x302c, 0x5c35,
+ 0x0000, 0x0000, 0x3d5a, 0x0000, 0x5c39, 0x0000, 0x0000, 0x0000,
+ 0x5842, 0x0000, 0x5c37, 0x5373, 0x0000, 0x4956, 0x5c3a, 0x5c36,
+ 0x0000, 0x5c3b, 0x4322, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c3c,
+ 0x5c45, 0x5c3d, 0x0000, 0x0000, 0x4e5f, 0x5625, 0x0000, 0x5c4f,
+ 0x0000, 0x5c4d, 0x0000, 0x0000, 0x5c52, 0x3d66, 0x422b, 0x0000,
+ 0x5c38, 0x5c4b, 0x5c4e, 0x5c3e, 0x3752, 0x3045, 0x5c47, 0x503e,
+ 0x5c41, 0x3b28, 0x0000, 0x373c, 0x5c4c, 0x0000, 0x0000, 0x5c46,
+ 0x5c3f, 0x475b, 0x0000, 0x0000, 0x0000, 0x513f, 0x5c40, 0x0000,
+ 0x0000, 0x5c4a, 0x0000, 0x0000, 0x5c50, 0x0000, 0x0000, 0x4e2d,
+ 0x5c42, 0x0000, 0x5c43, 0x5c48, 0x5c49, 0x3254, 0x5c51, 0x4b55,
+ 0x0000, 0x5437, 0x5c5b, 0x5c5f, 0x4c26, 0x5c66, 0x0000, 0x4367,
+ 0x5c5c, 0x0000, 0x0000, 0x3f41, 0x5c59, 0x0000, 0x307a, 0x3936,
+ 0x5c65, 0x5c53, 0x0000, 0x5c44, 0x5c56, 0x4874, 0x3f60, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x493b, 0x0000, 0x0000, 0x0000, 0x313d,
+ 0x0000, 0x5322, 0x0000, 0x0000, 0x5c5a, 0x0000, 0x0000, 0x5c55,
+ 0x0000, 0x463b, 0x0000, 0x5c5e, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_83[] = {
+ 0x0000, 0x5742, 0x432f, 0x3736, 0x4751, 0x4329, 0x5c62, 0x5c58,
+ 0x5c6b, 0x5c54, 0x0000, 0x0000, 0x5c5d, 0x0000, 0x3e25, 0x5c57,
+ 0x0000, 0x5c60, 0x0000, 0x0000, 0x5c63, 0x5c64, 0x0000, 0x5c78,
+ 0x0000, 0x0000, 0x5c61, 0x5d22, 0x5c67, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3c6b,
+ 0x3444, 0x0000, 0x0000, 0x4323, 0x3267, 0x5c7a, 0x0000, 0x5c72,
+ 0x0000, 0x5c6f, 0x0000, 0x5c7c, 0x5c6e, 0x5270, 0x3268, 0x0000,
+ 0x4857, 0x4863, 0x5c7b, 0x0000, 0x5c6d, 0x0000, 0x0000, 0x0000,
+ 0x5c77, 0x0000, 0x0000, 0x5c75, 0x0000, 0x0000, 0x3e23, 0x5c74,
+ 0x0000, 0x325d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5c73,
+ 0x3c76, 0x5c68, 0x3b44, 0x0000, 0x4073, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3c54, 0x5c69, 0x5c6a, 0x0000, 0x5c71, 0x5c76,
+ 0x5c79, 0x3534, 0x0000, 0x4859, 0x3b67, 0x5c7e, 0x5c7d, 0x532b,
+ 0x5d21, 0x5d23, 0x5d25, 0x5271, 0x5d24, 0x5d26, 0x5d27, 0x5229,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3a49,
+ 0x5d29, 0x0000, 0x0000, 0x5d36, 0x5d31, 0x5d34, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5d30, 0x464e, 0x0000,
+ 0x0000, 0x4072, 0x0000, 0x0000, 0x0000, 0x0000, 0x492f, 0x0000,
+ 0x0000, 0x0000, 0x5c6c, 0x5d2e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5d37, 0x0000, 0x0000, 0x5c70, 0x5d2f, 0x0000, 0x5d38, 0x0000,
+ 0x5d2c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5d39, 0x5d33, 0x5d2d, 0x442a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5d28, 0x4033, 0x412b, 0x5d2a, 0x5d2b, 0x0000, 0x5d32, 0x3b71,
+ 0x5d35, 0x5328, 0x5d3a, 0x0000, 0x5d3b, 0x4327, 0x0000, 0x0000,
+ 0x5d52, 0x5d3c, 0x0000, 0x0000, 0x0000, 0x5d51, 0x0000, 0x393d,
+ 0x0000, 0x0000, 0x3e55, 0x0000, 0x3e7a, 0x0000, 0x0000, 0x3a4a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5d4a, 0x0000, 0x5d45, 0x0000,
+ 0x5d3f, 0x0000, 0x0000, 0x0000, 0x324b, 0x5d43, 0x0000, 0x5d4b,
+ 0x3224, 0x5d55, 0x0000, 0x0000, 0x0000, 0x5d3e, 0x0000, 0x0000,
+ 0x0000, 0x4650, 0x5d50, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5d54, 0x4162, 0x3746, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5d4e, 0x5d4f, 0x0000, 0x0000, 0x0000, 0x5d44, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_84[] = {
+ 0x0000, 0x5d3d, 0x0000, 0x5d4d, 0x4c51, 0x0000, 0x5d49, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5d42, 0x4348, 0x463c, 0x4e2e, 0x5d4c,
+ 0x0000, 0x5d48, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5d41, 0x0000, 0x0000, 0x0000, 0x5d46, 0x425c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5329, 0x532a, 0x5d53, 0x4f74,
+ 0x4878, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5d66, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5d47, 0x0000, 0x0000, 0x0000, 0x5d60, 0x4264, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5d61, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5d57, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5678,
+ 0x0000, 0x5d59, 0x5d58, 0x3870, 0x5d56, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x464f, 0x0000, 0x362d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5d62, 0x0000, 0x3a79, 0x5461, 0x5d67, 0x0000, 0x0000,
+ 0x0000, 0x3450, 0x0000, 0x5d5a, 0x0000, 0x3f7b, 0x5d63, 0x0000,
+ 0x5d5f, 0x0000, 0x5d5d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3559, 0x0000, 0x0000, 0x0000, 0x0000, 0x5d5b,
+ 0x5d5c, 0x5d5e, 0x0000, 0x3d2f, 0x5d64, 0x0000, 0x5d65, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5d75,
+ 0x0000, 0x4349, 0x0000, 0x0000, 0x4b62, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5d72, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5861,
+ 0x0000, 0x0000, 0x4651, 0x0000, 0x5d74, 0x0000, 0x0000, 0x0000,
+ 0x5574, 0x5d73, 0x5d70, 0x0000, 0x0000, 0x5d6c, 0x0000, 0x5d6f,
+ 0x0000, 0x5d68, 0x0000, 0x0000, 0x506e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4858, 0x5d6e, 0x0000, 0x0000, 0x5d69, 0x0000, 0x0000,
+ 0x5d6a, 0x4b72, 0x0000, 0x5d6d, 0x0000, 0x0000, 0x314d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4036, 0x0000, 0x3c3b,
+ 0x5d71, 0x0000, 0x0000, 0x5d77, 0x0000, 0x5d76, 0x5d6b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x456e, 0x0000, 0x0000, 0x0000,
+ 0x5d7b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5e24, 0x0000, 0x0000, 0x5e23
+};
+
+static unsigned short gb2312_from_unicode_85[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5d78, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x436f, 0x0000, 0x427b, 0x0000, 0x0000, 0x0000, 0x5561,
+ 0x0000, 0x0000, 0x4e35, 0x0000, 0x0000, 0x0000, 0x0000, 0x5d7d,
+ 0x0000, 0x324c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4468, 0x4a5f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x473e,
+ 0x5d7a, 0x5d7c, 0x5d7e, 0x5e22, 0x302a, 0x314e, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5e2c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5e26, 0x3d36, 0x486f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e21, 0x0000,
+ 0x0000, 0x5e25, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e29, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5e28, 0x0000, 0x0000, 0x0000,
+ 0x5e27, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5e2d, 0x0000, 0x544c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5e33, 0x5e2a, 0x5e2e, 0x0000, 0x0000, 0x4059, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3121, 0x5e36, 0x0000, 0x5e31,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e32,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5126, 0x5e35, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5e2f, 0x0000, 0x0000, 0x0000,
+ 0x5e30, 0x0000, 0x503d, 0x0000, 0x0000, 0x0000, 0x5e34, 0x4a6d,
+ 0x5e39, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e38,
+ 0x0000, 0x5e37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5e3b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3d65, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3258,
+ 0x436a, 0x0000, 0x0000, 0x5e3a, 0x0000, 0x453a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5e3c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4c59, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x372a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5465, 0x0000, 0x0000, 0x0000, 0x5e3d
+};
+
+static unsigned short gb2312_from_unicode_86[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e3f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4422, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e41, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5e3e,
+ 0x0000, 0x5e40, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x553a, 0x0000, 0x0000, 0x0000, 0x5e42, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x722e, 0x3b22, 0x4232,
+ 0x4530, 0x4247, 0x0000, 0x0000, 0x722f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5069, 0x0000, 0x0000, 0x0000, 0x535d, 0x0000,
+ 0x0000, 0x0000, 0x6b3d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3366, 0x7230, 0x0000, 0x7231, 0x0000,
+ 0x0000, 0x4a2d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3a67, 0x7233, 0x7235, 0x7234, 0x4b64, 0x4f3a, 0x7232,
+ 0x4a34, 0x524f, 0x426c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4e43, 0x7238, 0x3076, 0x7237, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x723e, 0x0000, 0x324f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5141, 0x723a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x723c, 0x5469, 0x0000, 0x0000, 0x723b,
+ 0x7236, 0x723f, 0x723d, 0x0000, 0x7239, 0x0000, 0x0000, 0x7247,
+ 0x7244, 0x7246, 0x0000, 0x0000, 0x724a, 0x7242, 0x7240, 0x0000,
+ 0x0000, 0x0000, 0x7245, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x567b, 0x0000, 0x0000, 0x0000, 0x7241, 0x0000, 0x4779, 0x495f,
+ 0x0000, 0x7248, 0x3946, 0x3530, 0x0000, 0x0000, 0x7243, 0x7249,
+ 0x7250, 0x7256, 0x0000, 0x0000, 0x3b57, 0x0000, 0x0000, 0x0000,
+ 0x7255, 0x4d5c, 0x0000, 0x566b, 0x0000, 0x0000, 0x7252, 0x7254,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3872, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x724b, 0x0000, 0x0000, 0x0000, 0x724e, 0x4279, 0x0000,
+ 0x555d, 0x724c, 0x724d, 0x724f, 0x7253, 0x0000, 0x0000, 0x0000,
+ 0x7259, 0x533c, 0x0000, 0x0000, 0x0000, 0x0000, 0x366a, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_87[] = {
+ 0x4a71, 0x0000, 0x3764, 0x7257, 0x0000, 0x0000, 0x0000, 0x7258,
+ 0x725a, 0x725d, 0x725b, 0x0000, 0x0000, 0x725c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5151, 0x7251, 0x0000, 0x4d49, 0x0000, 0x4e4f,
+ 0x5629, 0x0000, 0x7263, 0x0000, 0x435b, 0x0000, 0x7260, 0x0000,
+ 0x0000, 0x402f, 0x726c, 0x725e, 0x0000, 0x7261, 0x0000, 0x0000,
+ 0x0000, 0x7268, 0x0000, 0x0000, 0x0000, 0x0000, 0x7262, 0x0000,
+ 0x0000, 0x7267, 0x0000, 0x0000, 0x7266, 0x0000, 0x0000, 0x7269,
+ 0x0000, 0x0000, 0x0000, 0x725f, 0x0000, 0x0000, 0x7264, 0x726a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x532c,
+ 0x7265, 0x3275, 0x0000, 0x0000, 0x7272, 0x0000, 0x502b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7275, 0x0000, 0x0000, 0x0000, 0x3b48,
+ 0x0000, 0x7279, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7270, 0x0000, 0x0000, 0x7276, 0x7278, 0x727a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7273, 0x0000,
+ 0x7271, 0x0000, 0x0000, 0x0000, 0x3a7b, 0x0000, 0x357b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x726f, 0x7277, 0x726d, 0x726e, 0x0000,
+ 0x0000, 0x0000, 0x726b, 0x7326, 0x0000, 0x7323, 0x0000, 0x0000,
+ 0x7322, 0x0000, 0x0000, 0x7274, 0x0000, 0x485a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x727b, 0x0000, 0x0000, 0x0000, 0x7325,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4378,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x727d, 0x0000, 0x0000, 0x7327, 0x7329, 0x7324, 0x0000, 0x727c,
+ 0x0000, 0x0000, 0x0000, 0x732b, 0x0000, 0x732a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x425d, 0x0000, 0x0000, 0x732e, 0x0000, 0x0000,
+ 0x7330, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7321, 0x0000,
+ 0x0000, 0x0000, 0x7331, 0x732c, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x732f, 0x727e, 0x732d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7332, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7334, 0x0000, 0x0000, 0x0000, 0x0000, 0x7328, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7333, 0x0000, 0x0000, 0x0000, 0x7335, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5037, 0x0000, 0x0000, 0x0000, 0x0000, 0x7338, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_88[] = {
+ 0x0000, 0x0000, 0x0000, 0x5979, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7339, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7337, 0x0000, 0x4864, 0x7336, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x733a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x733b, 0x3440, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6e43, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x733c, 0x0000, 0x0000, 0x733d, 0x0000, 0x0000, 0x0000,
+ 0x512a, 0x0000, 0x0000, 0x0000, 0x742c, 0x5046, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5050, 0x515c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4f4e, 0x0000, 0x0000, 0x3d56,
+ 0x0000, 0x5143, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3a62, 0x6169, 0x5242, 0x7142, 0x3239, 0x0000, 0x0000,
+ 0x316d, 0x7143, 0x0000, 0x4940, 0x3344, 0x0000, 0x5972, 0x0000,
+ 0x4b25, 0x0000, 0x7144, 0x0000, 0x0000, 0x0000, 0x0000, 0x5654,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7145, 0x7440, 0x7146,
+ 0x0000, 0x542c, 0x7147, 0x0000, 0x3040, 0x7441, 0x0000, 0x0000,
+ 0x7442, 0x0000, 0x0000, 0x347c, 0x0000, 0x455b, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4c3b, 0x0000, 0x0000, 0x0000, 0x5064, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4d60, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7148, 0x0000, 0x5973, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x313b, 0x0000, 0x4f2e, 0x0000, 0x0000,
+ 0x0000, 0x3824, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x714a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x714b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3243, 0x4151, 0x0000, 0x0000, 0x5730, 0x7149, 0x0000,
+ 0x0000, 0x714c, 0x0000, 0x0000, 0x0000, 0x0000, 0x714e, 0x0000,
+ 0x0000, 0x0000, 0x5976, 0x0000, 0x5261, 0x5423, 0x0000, 0x0000,
+ 0x7443, 0x4839, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7444,
+ 0x0000, 0x0000, 0x714d, 0x714f, 0x3f63, 0x7150, 0x0000, 0x0000,
+ 0x7154, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7156, 0x7151, 0x0000, 0x4951, 0x4561, 0x0000, 0x0000, 0x0000,
+ 0x4263, 0x397c, 0x0000, 0x0000, 0x7153, 0x0000, 0x7155, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_89[] = {
+ 0x0000, 0x0000, 0x3953, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x715b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3a56, 0x0000, 0x307d, 0x7159, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7158, 0x7152, 0x715a, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7157, 0x0000, 0x0000, 0x0000, 0x486c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4d4a, 0x715d, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x653d, 0x0000, 0x0000, 0x0000, 0x715c, 0x0000, 0x715e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x715f, 0x0000, 0x0000, 0x4f65, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7445, 0x3d73,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7160, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7161, 0x0000, 0x0000, 0x0000, 0x4e77,
+ 0x0000, 0x522a, 0x0000, 0x717b, 0x0000, 0x0000, 0x3832, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3c7b, 0x395b, 0x0000, 0x3966, 0x4359, 0x4a53, 0x6a68,
+ 0x4040, 0x3e75, 0x6a69, 0x6a6a, 0x6a6b, 0x0000, 0x6a6c, 0x6a6d,
+ 0x6a6e, 0x6a6f, 0x3d47, 0x0000, 0x0000, 0x0000, 0x757b, 0x0000,
+ 0x0000, 0x0000, 0x757d, 0x0000, 0x757e, 0x0000, 0x757c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3d62, 0x0000, 0x7621, 0x3425, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7622, 0x0000, 0x0000, 0x0000, 0x7623,
+ 0x0000, 0x0000, 0x0000, 0x6c32, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_8a[] = {
+ 0x5154, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x596a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7624, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6e3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5532, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x537e, 0x4c5c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4a44, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_8b[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6540,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7625, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3e2f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4629, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5a25, 0x3c46, 0x3629, 0x383c, 0x484f, 0x3c25, 0x5a26, 0x5a27,
+ 0x4c56, 0x4843, 0x5a28, 0x467d, 0x0000, 0x5135, 0x5269, 0x5136,
+ 0x3c47, 0x0000, 0x3d32, 0x3b64, 0x5a29, 0x5a2a, 0x5148, 0x5a2b,
+ 0x506d, 0x366f, 0x425b, 0x0000, 0x4b4f, 0x376d, 0x4968, 0x3743,
+ 0x3e77, 0x5624, 0x5a2c, 0x5a2d, 0x4640, 0x5767, 0x4a36, 0x0000,
+ 0x5529, 0x4b5f, 0x556f, 0x5a2e, 0x565f, 0x344a, 0x5a30, 0x5a2f,
+ 0x0000, 0x526b, 0x5a31, 0x5a32, 0x5a33, 0x4a54, 0x5a34, 0x4a2b,
+ 0x5a35, 0x5a36, 0x334f, 0x566f, 0x5a37, 0x3b30, 0x352e, 0x5a38,
+ 0x5a39, 0x396e, 0x512f, 0x5268, 0x5a3a, 0x3843, 0x4f6a, 0x326f,
+ 0x5a3b, 0x5a3c, 0x0000, 0x3d6b, 0x4e5c, 0x536f, 0x5a3d, 0x4e73,
+ 0x5a3e, 0x5355, 0x3b65, 0x5a3f, 0x4b35, 0x4b50, 0x5a40, 0x476b,
+ 0x566e, 0x5a41, 0x4535, 0x3641, 0x5a42, 0x374c, 0x3f4e, 0x5a43
+};
+
+static unsigned short gb2312_from_unicode_8c[] = {
+ 0x5a44, 0x4b2d, 0x5a45, 0x3577, 0x5a46, 0x4142, 0x573b, 0x5a47,
+ 0x4c38, 0x0000, 0x526a, 0x4431, 0x5a48, 0x357d, 0x3b51, 0x5a49,
+ 0x5033, 0x5a4a, 0x5a4b, 0x4e3d, 0x5a4c, 0x5a4d, 0x5a4e, 0x3277,
+ 0x5a51, 0x5a4f, 0x5168, 0x5a50, 0x4355, 0x5a52, 0x0000, 0x5a53,
+ 0x5a54, 0x5a55, 0x503b, 0x5225, 0x3079, 0x5a56, 0x472b, 0x5a57,
+ 0x3d77, 0x4321, 0x5a58, 0x5a59, 0x437d, 0x4c37, 0x5a5a, 0x5a5b,
+ 0x403e, 0x4657, 0x5a5c, 0x5a5d, 0x4734, 0x5a5e, 0x5a5f, 0x3948,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3b6d, 0x0000, 0x0000, 0x0000, 0x0000, 0x3639, 0x7478,
+ 0x0000, 0x7479, 0x0000, 0x0000, 0x4d63, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7539, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x6b60, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4f73, 0x3b3f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x3a40, 0x5425, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6159, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7574, 0x312a, 0x3272, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7575, 0x0000, 0x0000, 0x7577, 0x0000, 0x0000,
+ 0x0000, 0x3a51, 0x7576, 0x0000, 0x4332, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7579, 0x0000, 0x0000, 0x0000,
+ 0x7578, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_8d[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3134, 0x556a, 0x383a,
+ 0x0000, 0x3931, 0x3246, 0x5470, 0x4f4d, 0x305c, 0x554b, 0x3b75,
+ 0x564a, 0x3737, 0x4c30, 0x4636, 0x3161, 0x393a, 0x567c, 0x3961,
+ 0x3721, 0x3c7a, 0x6a5a, 0x6a5b, 0x4c79, 0x3973, 0x6a5c, 0x347b,
+ 0x4333, 0x3751, 0x3a58, 0x6a5d, 0x5474, 0x6a5e, 0x3c56, 0x3b5f,
+ 0x6a5f, 0x415e, 0x4238, 0x545f, 0x574a, 0x6a60, 0x6a61, 0x6a64,
+ 0x6a62, 0x6a63, 0x495e, 0x3833, 0x3644, 0x6a65, 0x4a6a, 0x494d,
+ 0x344d, 0x0000, 0x0000, 0x6259, 0x4562, 0x6a66, 0x4035, 0x0000,
+ 0x5738, 0x6a67, 0x572c, 0x487c, 0x5853, 0x584d, 0x545e, 0x0000,
+ 0x5479, 0x4944, 0x532e, 0x3853, 0x3360, 0x0000, 0x4962, 0x7476,
+ 0x0000, 0x0000, 0x0000, 0x3a55, 0x0000, 0x7477, 0x0000, 0x0000,
+ 0x575f, 0x0000, 0x0000, 0x7471, 0x3830, 0x5554, 0x384f, 0x4670,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3343, 0x0000, 0x0000, 0x7472, 0x332c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x543d, 0x4777, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7474, 0x0000, 0x0000, 0x7473, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c4b,
+ 0x0000, 0x0000, 0x0000, 0x4824, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7475, 0x0000, 0x5763, 0x453f, 0x7540, 0x0000, 0x0000,
+ 0x753b, 0x0000, 0x7543, 0x0000, 0x7542, 0x0000, 0x563a, 0x7541,
+ 0x0000, 0x0000, 0x0000, 0x543e, 0x7544, 0x0000, 0x754c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x304f, 0x3578, 0x0000, 0x7549, 0x754a,
+ 0x0000, 0x455c, 0x0000, 0x0000, 0x0000, 0x0000, 0x7545, 0x7546,
+ 0x0000, 0x0000, 0x7547, 0x754b, 0x0000, 0x3e60, 0x7548, 0x387a,
+ 0x0000, 0x0000, 0x0000, 0x7550, 0x7553, 0x0000, 0x0000, 0x0000,
+ 0x3f67, 0x0000, 0x3972, 0x753c, 0x754d, 0x0000, 0x0000, 0x4237,
+ 0x0000, 0x0000, 0x0000, 0x4c78, 0x0000, 0x3c79, 0x0000, 0x754e,
+ 0x754f, 0x7551, 0x3665, 0x7552, 0x0000, 0x7555, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_8e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x753d, 0x0000, 0x0000,
+ 0x0000, 0x7554, 0x533b, 0x0000, 0x336c, 0x0000, 0x0000, 0x4c24,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7556, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7557, 0x3e61, 0x7558,
+ 0x0000, 0x0000, 0x4c5f, 0x755b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3248, 0x5759, 0x0000, 0x7559, 0x0000, 0x755a, 0x755c,
+ 0x0000, 0x7562, 0x0000, 0x0000, 0x0000, 0x7560, 0x0000, 0x0000,
+ 0x0000, 0x755f, 0x755d, 0x0000, 0x0000, 0x7561, 0x0000, 0x0000,
+ 0x755e, 0x7564, 0x7565, 0x0000, 0x4c63, 0x0000, 0x0000, 0x653f,
+ 0x3538, 0x7563, 0x7568, 0x4c23, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7566, 0x7567, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x753e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3144, 0x0000,
+ 0x0000, 0x753f, 0x0000, 0x0000, 0x3545, 0x3264, 0x0000, 0x756c,
+ 0x7569, 0x0000, 0x3657, 0x0000, 0x756d, 0x0000, 0x756a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x756b, 0x0000, 0x0000, 0x345a,
+ 0x0000, 0x546a, 0x0000, 0x0000, 0x0000, 0x756e, 0x0000, 0x3379,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x756f,
+ 0x7571, 0x0000, 0x0000, 0x0000, 0x7570, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7572, 0x0000, 0x7573, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x496d, 0x392a, 0x0000, 0x0000, 0x477b,
+ 0x0000, 0x0000, 0x3663, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4c49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a26, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_8f[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3335, 0x547e,
+ 0x396c, 0x5079, 0x0000, 0x696d, 0x572a, 0x696e, 0x4256, 0x486d,
+ 0x3a64, 0x696f, 0x6970, 0x6971, 0x5661, 0x6972, 0x6973, 0x6975,
+ 0x6974, 0x6976, 0x6977, 0x4761, 0x6978, 0x5458, 0x6979, 0x3d4e,
+ 0x0000, 0x697a, 0x697b, 0x3d4f, 0x697c, 0x3828, 0x413e, 0x697d,
+ 0x3132, 0x3b54, 0x3975, 0x697e, 0x0000, 0x6a21, 0x6a22, 0x6a23,
+ 0x3778, 0x3c2d, 0x0000, 0x4a64, 0x604e, 0x542f, 0x4f3d, 0x5537,
+ 0x6a24, 0x555e, 0x6a25, 0x5041, 0x393c, 0x0000, 0x3447, 0x3159,
+ 0x0000, 0x0000, 0x0000, 0x4031, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3166, 0x3167, 0x0000, 0x3168, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x333d, 0x4868, 0x0000, 0x0000, 0x0000, 0x0000, 0x6541, 0x0000,
+ 0x0000, 0x315f, 0x0000, 0x0000, 0x0000, 0x4149, 0x346f, 0x0000,
+ 0x0000, 0x4728, 0x5358, 0x0000, 0x4679, 0x5138, 0x0000, 0x397d,
+ 0x4275, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x532d, 0x0000,
+ 0x544b, 0x3d7c, 0x0000, 0x6542, 0x3735, 0x6543, 0x0000, 0x0000,
+ 0x3b39, 0x5562, 0x0000, 0x3d78, 0x5436, 0x4e25, 0x412c, 0x3359,
+ 0x0000, 0x0000, 0x4c76, 0x0000, 0x6546, 0x6544, 0x6548, 0x0000,
+ 0x654a, 0x6547, 0x354f, 0x4648, 0x0000, 0x357c, 0x6545, 0x0000,
+ 0x4a76, 0x0000, 0x0000, 0x6549, 0x0000, 0x0000, 0x0000, 0x4354,
+ 0x3145, 0x3c23, 0x0000, 0x0000, 0x0000, 0x5737, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_90[] = {
+ 0x4d4b, 0x4b4d, 0x4a4a, 0x4c53, 0x654c, 0x654b, 0x4466, 0x0000,
+ 0x0000, 0x5121, 0x5137, 0x654d, 0x0000, 0x6550, 0x0000, 0x4d38,
+ 0x5670, 0x654f, 0x355d, 0x0000, 0x4d3e, 0x0000, 0x6551, 0x363a,
+ 0x0000, 0x0000, 0x4d28, 0x3964, 0x0000, 0x4a45, 0x3351, 0x4b59,
+ 0x546c, 0x6552, 0x376a, 0x0000, 0x0000, 0x0000, 0x654e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6555, 0x347e, 0x6556,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6553, 0x6554, 0x0000,
+ 0x525d, 0x0000, 0x0000, 0x425f, 0x3146, 0x0000, 0x5362, 0x0000,
+ 0x0000, 0x365d, 0x4b6c, 0x0000, 0x6557, 0x0000, 0x0000, 0x5376,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3169, 0x0000, 0x3674,
+ 0x655a, 0x6558, 0x6559, 0x3540, 0x0000, 0x0000, 0x0000, 0x5245,
+ 0x655c, 0x0000, 0x0000, 0x655e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x655d, 0x4732, 0x0000, 0x5223, 0x0000, 0x0000,
+ 0x655b, 0x0000, 0x0000, 0x0000, 0x0000, 0x5462, 0x555a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x6560, 0x5771, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6561, 0x0000, 0x315c,
+ 0x517b, 0x0000, 0x6562, 0x6564, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x6563, 0x0000, 0x0000, 0x6565, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5258, 0x0000, 0x354b, 0x0000, 0x675f, 0x0000, 0x5a75,
+ 0x0000, 0x5a78, 0x0000, 0x5a76, 0x0000, 0x5a77, 0x0000, 0x0000,
+ 0x0000, 0x5a7a, 0x504f, 0x4447, 0x0000, 0x0000, 0x306e, 0x0000,
+ 0x0000, 0x0000, 0x5030, 0x0000, 0x5a79, 0x0000, 0x534a, 0x3a2a,
+ 0x5b22, 0x4771, 0x0000, 0x5a7c, 0x5a7b, 0x495b, 0x5a7d, 0x0000,
+ 0x5b21, 0x575e, 0x5a7e, 0x415a, 0x0000, 0x0000, 0x5b25, 0x0000,
+ 0x0000, 0x5374, 0x0000, 0x0000, 0x5b27, 0x5b24, 0x0000, 0x5b28,
+ 0x0000, 0x0000, 0x3d3c, 0x0000, 0x0000, 0x0000, 0x4049, 0x5b23,
+ 0x5b26, 0x5623, 0x0000, 0x5b29, 0x0000, 0x0000, 0x0000, 0x5b2d,
+ 0x0000, 0x0000, 0x0000, 0x5b2e, 0x5b2c, 0x3a42, 0x0000, 0x0000,
+ 0x0000, 0x3f24, 0x5b2b, 0x0000, 0x0000, 0x0000, 0x5b2a, 0x5447,
+ 0x323f, 0x0000, 0x0000, 0x5b2f, 0x0000, 0x3979, 0x0000, 0x5b30,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x333b, 0x0000, 0x0000, 0x0000,
+ 0x3526, 0x0000, 0x0000, 0x0000, 0x0000, 0x363c, 0x5b31, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_91[] = {
+ 0x0000, 0x0000, 0x3675, 0x0000, 0x5b32, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3149, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b34, 0x0000,
+ 0x0000, 0x0000, 0x5b33, 0x5b35, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b37,
+ 0x0000, 0x5b36, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5b38, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5b39, 0x0000, 0x0000, 0x5b3a, 0x0000,
+ 0x0000, 0x534f, 0x747a, 0x4775, 0x5743, 0x4564, 0x747c, 0x747d,
+ 0x747b, 0x0000, 0x3e46, 0x0000, 0x0000, 0x0000, 0x0000, 0x506f,
+ 0x0000, 0x0000, 0x3753, 0x0000, 0x0000, 0x544d, 0x4c2a, 0x0000,
+ 0x0000, 0x7522, 0x7521, 0x3a28, 0x747e, 0x4b56, 0x0000, 0x0000,
+ 0x0000, 0x7524, 0x4052, 0x0000, 0x336a, 0x0000, 0x4d2a, 0x7525,
+ 0x7523, 0x3d34, 0x7528, 0x0000, 0x7529, 0x3d4d, 0x4338, 0x3f61,
+ 0x4b61, 0x752a, 0x0000, 0x0000, 0x0000, 0x7526, 0x7527, 0x4470,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x752c, 0x0000, 0x343c,
+ 0x0000, 0x576d, 0x0000, 0x3457, 0x752b, 0x752e, 0x0000, 0x0000,
+ 0x752d, 0x752f, 0x5051, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4351, 0x4829, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7530, 0x7531, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7532, 0x0000, 0x0000, 0x7533, 0x7534, 0x7535,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7537, 0x7536, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7538, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3249,
+ 0x0000, 0x5354, 0x4a4d, 0x0000, 0x406f, 0x5658, 0x5230, 0x413f,
+ 0x0000, 0x3d70, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x382a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_92[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3c78, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7646, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7647, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7648, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_93[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7649, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x764a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x764c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x764b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7769, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_94[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x764d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x764e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6e44, 0x6e45, 0x6e46,
+ 0x556b, 0x3624, 0x6e48, 0x6e47, 0x6e49, 0x6e4a, 0x4725, 0x6e4b,
+ 0x6e4c, 0x0000, 0x3730, 0x3576, 0x6e4d, 0x6e4f, 0x0000, 0x6e4e,
+ 0x0000, 0x3846, 0x6e50, 0x6e51, 0x6e52, 0x365b, 0x332e, 0x5653,
+ 0x4446, 0x3135, 0x3856, 0x6e53, 0x6e54, 0x543f, 0x4755, 0x3e7b,
+ 0x4e59, 0x3933, 0x6e56, 0x6e55, 0x6e58, 0x6e57, 0x4525, 0x6e59,
+ 0x6e5a, 0x472e, 0x6e5b, 0x472f, 0x6e5c, 0x3227, 0x6e5d, 0x6e5e,
+ 0x6e5f, 0x6e60, 0x6e61, 0x576a, 0x6e62, 0x6e63, 0x3c58, 0x6e64,
+ 0x534b, 0x4c7a, 0x322c, 0x4165, 0x6e65, 0x4726, 0x432d, 0x0000,
+ 0x6e66, 0x6e67, 0x6e68, 0x6e69, 0x6e6a, 0x6e6b, 0x6e6c, 0x0000,
+ 0x6e6d, 0x6e6e, 0x6e6f, 0x0000, 0x0000, 0x6e70, 0x6e71, 0x6e72,
+ 0x6e74, 0x6e73, 0x0000, 0x6e75, 0x4d2d, 0x4241, 0x6e76, 0x6e77,
+ 0x6e78, 0x5521, 0x6e79, 0x4f33, 0x6e7a, 0x6e7b, 0x0000, 0x6e7c,
+ 0x6e7d, 0x6f21, 0x6e7e, 0x6f22, 0x3875, 0x437a, 0x6f23, 0x6f24,
+ 0x3d42, 0x523f, 0x3279, 0x6f25, 0x6f26, 0x6f27, 0x5278, 0x6f28,
+ 0x567d, 0x6f29, 0x464c, 0x0000, 0x6f2a, 0x6f2b, 0x4134, 0x6f2c
+};
+
+static unsigned short gb2312_from_unicode_95[] = {
+ 0x4f7a, 0x4b78, 0x6f2e, 0x6f2d, 0x337a, 0x3978, 0x6f2f, 0x6f30,
+ 0x5062, 0x6f31, 0x6f32, 0x3766, 0x503f, 0x6f33, 0x6f34, 0x6f35,
+ 0x4871, 0x4c60, 0x6f36, 0x6f37, 0x6f38, 0x6f39, 0x6f3a, 0x5560,
+ 0x6f3b, 0x346d, 0x432a, 0x6f3c, 0x0000, 0x6f3d, 0x6f3e, 0x6f3f,
+ 0x0000, 0x4e7d, 0x6f40, 0x4260, 0x3438, 0x5736, 0x3d75, 0x0000,
+ 0x4f47, 0x6f43, 0x6f41, 0x6f42, 0x6f44, 0x3627, 0x3c7c, 0x3e62,
+ 0x434c, 0x6f45, 0x6f46, 0x0000, 0x6f47, 0x6f4f, 0x6f48, 0x6f49,
+ 0x6f4a, 0x4742, 0x6f71, 0x364d, 0x6f4b, 0x0000, 0x6f4c, 0x6f4d,
+ 0x3646, 0x433e, 0x6f4e, 0x0000, 0x6f50, 0x6f51, 0x6f52, 0x5572,
+ 0x0000, 0x6f53, 0x4477, 0x0000, 0x6f54, 0x4478, 0x6f55, 0x6f56,
+ 0x3864, 0x3077, 0x6f57, 0x6f58, 0x6f59, 0x0000, 0x6f5a, 0x6f5b,
+ 0x6f5c, 0x6f5d, 0x0000, 0x6f5e, 0x3e35, 0x6f61, 0x6f5f, 0x6f60,
+ 0x0000, 0x6f62, 0x6f63, 0x414d, 0x6f64, 0x6f65, 0x6f66, 0x6f67,
+ 0x6f68, 0x6f69, 0x6f6a, 0x6f6b, 0x6f6c, 0x4058, 0x0000, 0x6f6d,
+ 0x412d, 0x6f6e, 0x6f6f, 0x6f70, 0x0000, 0x0000, 0x4f62, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3324,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4345, 0x6345, 0x4941, 0x6346, 0x0000, 0x3155, 0x4e4a, 0x3433,
+ 0x4872, 0x6347, 0x4f50, 0x6348, 0x3c64, 0x6349, 0x634a, 0x4346,
+ 0x5522, 0x4456, 0x396b, 0x4e45, 0x634b, 0x4376, 0x634c, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_96[] = {
+ 0x3727, 0x3873, 0x3a52, 0x634d, 0x634e, 0x5444, 0x634f, 0x0000,
+ 0x6350, 0x514b, 0x6351, 0x6352, 0x6353, 0x6354, 0x5156, 0x6355,
+ 0x327b, 0x403b, 0x6356, 0x0000, 0x402b, 0x6357, 0x6358, 0x6359,
+ 0x0000, 0x635a, 0x635b, 0x0000, 0x3837, 0x5a62, 0x0000, 0x3653,
+ 0x0000, 0x5a64, 0x5a63, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5a66, 0x0000, 0x0000, 0x0000, 0x486e, 0x0000,
+ 0x0000, 0x5a65, 0x3740, 0x5174, 0x5275, 0x5573, 0x3d57, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5768, 0x5a68, 0x5a67, 0x0000, 0x3022,
+ 0x4d53, 0x0000, 0x5a69, 0x0000, 0x383d, 0x3c4a, 0x423d, 0x4224,
+ 0x3342, 0x5a6a, 0x0000, 0x422a, 0x4430, 0x3d35, 0x0000, 0x0000,
+ 0x4f5e, 0x0000, 0x0000, 0x0000, 0x5a6b, 0x4942, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x315d, 0x0000, 0x0000, 0x0000, 0x5a6c,
+ 0x0000, 0x3638, 0x543a, 0x0000, 0x337d, 0x0000, 0x0000, 0x5a6d,
+ 0x5449, 0x4f55, 0x4563, 0x0000, 0x5a6e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x5a6f, 0x0000, 0x5a70, 0x416a, 0x4c55, 0x4f5d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5367, 0x4221, 0x0000,
+ 0x5a71, 0x0000, 0x0000, 0x4b65, 0x0000, 0x5a72, 0x0000, 0x4b66,
+ 0x527e, 0x0000, 0x0000, 0x0000, 0x3874, 0x0000, 0x0000, 0x5a73,
+ 0x302f, 0x4f36, 0x0000, 0x0000, 0x554f, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4b6d,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5a74, 0x0000, 0x0000, 0x6344, 0x0000, 0x0000, 0x4125, 0x0000,
+ 0x0000, 0x763f, 0x0000, 0x0000, 0x7640, 0x7641, 0x4451, 0x0000,
+ 0x4838, 0x5163, 0x0000, 0x0000, 0x505b, 0x5145, 0x3c2f, 0x394d,
+ 0x0000, 0x6f74, 0x0000, 0x0000, 0x3446, 0x533a, 0x7642, 0x337b,
+ 0x0000, 0x0000, 0x7643, 0x0000, 0x0000, 0x3571, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x7645, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x536a, 0x7627, 0x5129, 0x0000, 0x0000, 0x0000, 0x0000, 0x7629,
+ 0x0000, 0x0000, 0x0000, 0x7628, 0x0000, 0x0000, 0x4163, 0x4057,
+ 0x0000, 0x3122, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e6d, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_97[] = {
+ 0x5068, 0x762b, 0x0000, 0x0000, 0x4f76, 0x0000, 0x762a, 0x5570,
+ 0x762c, 0x4339, 0x0000, 0x0000, 0x0000, 0x3b74, 0x762e, 0x762d,
+ 0x0000, 0x0000, 0x0000, 0x445e, 0x0000, 0x0000, 0x4158, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4b2a, 0x0000, 0x4f3c, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x762f, 0x0000, 0x0000, 0x7630, 0x0000, 0x0000,
+ 0x7631, 0x0000, 0x4236, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3054, 0x4579, 0x0000, 0x0000, 0x0000, 0x0000, 0x7632, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4760, 0x7626, 0x0000, 0x0000, 0x3e38, 0x0000,
+ 0x0000, 0x3e32, 0x0000, 0x3565, 0x0000, 0x0000, 0x3747, 0x0000,
+ 0x3f3f, 0x4352, 0x4366, 0x0000, 0x0000, 0x584c, 0x0000, 0x0000,
+ 0x0000, 0x386f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x3d79, 0x5125, 0x0000, 0x3050, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7730, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7731, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x502c, 0x0000, 0x3030, 0x0000, 0x0000,
+ 0x0000, 0x7732, 0x7733, 0x0000, 0x7734, 0x0000, 0x0000, 0x0000,
+ 0x474a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3e4f, 0x0000, 0x0000, 0x7737, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7736, 0x0000, 0x315e, 0x0000, 0x7735,
+ 0x0000, 0x0000, 0x7738, 0x0000, 0x7739, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4e24, 0x484d,
+ 0x0000, 0x3a2b, 0x6838, 0x6839, 0x683a, 0x3e42, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x5274, 0x0000, 0x544f, 0x4958, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_98[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5233, 0x3625, 0x476a,
+ 0x717c, 0x4f6e, 0x4b33, 0x506b, 0x676f, 0x4d67, 0x394b, 0x3659,
+ 0x717d, 0x3064, 0x4b4c, 0x717e, 0x5424, 0x422d, 0x416c, 0x4644,
+ 0x3e31, 0x7221, 0x3c55, 0x0000, 0x7222, 0x7223, 0x0000, 0x7224,
+ 0x5243, 0x4635, 0x0000, 0x4d47, 0x7225, 0x0000, 0x5331, 0x3f45,
+ 0x4c62, 0x0000, 0x7226, 0x7227, 0x5155, 0x366e, 0x7228, 0x7229,
+ 0x355f, 0x722a, 0x722b, 0x0000, 0x327c, 0x722c, 0x722d, 0x4827,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3767, 0x0000,
+ 0x0000, 0x6c29, 0x6c2a, 0x6c2b, 0x0000, 0x6c2c, 0x0000, 0x0000,
+ 0x462e, 0x6c2d, 0x6c2e, 0x0000, 0x0000, 0x0000, 0x3749, 0x4a33,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6238,
+ 0x774f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_99[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7750, 0x0000, 0x0000,
+ 0x324d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7751, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7753, 0x7752, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x623b, 0x0000, 0x3c22, 0x0000, 0x623c,
+ 0x623d, 0x623e, 0x623f, 0x6240, 0x6241, 0x3739, 0x527b, 0x3d24,
+ 0x4a4e, 0x3125, 0x4b47, 0x0000, 0x6242, 0x367c, 0x4844, 0x6243,
+ 0x0000, 0x0000, 0x3d48, 0x0000, 0x317d, 0x6244, 0x0000, 0x3676,
+ 0x6245, 0x4459, 0x0000, 0x0000, 0x6246, 0x4f5a, 0x395d, 0x6247,
+ 0x4021, 0x0000, 0x6248, 0x3276, 0x0000, 0x6249, 0x0000, 0x4173,
+ 0x624a, 0x624b, 0x4278, 0x624c, 0x624d, 0x624e, 0x4a57, 0x5838,
+ 0x5965, 0x4f63, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7025, 0x0000, 0x0000,
+ 0x5c30, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_9a[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x426d, 0x5426, 0x4d54, 0x5131,
+ 0x335b, 0x477d, 0x0000, 0x3235, 0x423f, 0x6660, 0x4a3b, 0x6661,
+ 0x6662, 0x3e54, 0x6663, 0x5724, 0x4d55, 0x6665, 0x3c5d, 0x6664,
+ 0x6666, 0x6667, 0x426e, 0x0000, 0x3d3e, 0x6668, 0x4266, 0x3a27,
+ 0x6669, 0x0000, 0x666a, 0x3352, 0x5169, 0x0000, 0x0000, 0x3f25,
+ 0x666b, 0x466f, 0x666c, 0x666d, 0x0000, 0x0000, 0x666e, 0x462d,
+ 0x666f, 0x0000, 0x4927, 0x6670, 0x6671, 0x6672, 0x6539, 0x6673,
+ 0x6674, 0x4262, 0x6675, 0x6676, 0x5668, 0x6677, 0x0000, 0x6678,
+ 0x3947, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x773b, 0x773a, 0x0000, 0x0000, 0x0000, 0x0000, 0x773e, 0x773c,
+ 0x3a21, 0x0000, 0x773f, 0x0000, 0x7740, 0x0000, 0x0000, 0x0000,
+ 0x7742, 0x7741, 0x7744, 0x0000, 0x0000, 0x7743, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7745, 0x7746, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x7747, 0x0000, 0x4b68, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x385f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7754,
+ 0x0000, 0x7755, 0x0000, 0x0000, 0x0000, 0x0000, 0x7756, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x7758, 0x0000, 0x775a, 0x0000, 0x7757,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x775b, 0x0000, 0x7759, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_9b[] = {
+ 0x0000, 0x0000, 0x0000, 0x5757, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x775c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x775d,
+ 0x0000, 0x0000, 0x0000, 0x775e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x775f,
+ 0x0000, 0x0000, 0x0000, 0x7760, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5b4b,
+ 0x0000, 0x0000, 0x582a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x6577, 0x396d, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x3f7d, 0x3b6a, 0x7749, 0x4647, 0x7748, 0x0000, 0x774a,
+ 0x774c, 0x774b, 0x0000, 0x0000, 0x0000, 0x774d, 0x0000, 0x4e3a,
+ 0x0000, 0x774e, 0x0000, 0x0000, 0x4427, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_9c[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x5363, 0x0000, 0x0000, 0x764f,
+ 0x0000, 0x4233, 0x7650, 0x0000, 0x0000, 0x7651, 0x7652, 0x7653,
+ 0x7654, 0x0000, 0x0000, 0x7656, 0x0000, 0x312b, 0x7657, 0x0000,
+ 0x7658, 0x7659, 0x765a, 0x0000, 0x765b, 0x765c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x765d, 0x765e, 0x4f4a, 0x0000, 0x765f, 0x7660,
+ 0x7661, 0x7662, 0x7663, 0x7664, 0x4070, 0x7665, 0x7666, 0x7667,
+ 0x7668, 0x7669, 0x0000, 0x766a, 0x0000, 0x766b, 0x766c, 0x0000,
+ 0x766d, 0x766e, 0x766f, 0x7670, 0x7671, 0x7672, 0x7673, 0x7674,
+ 0x3e28, 0x0000, 0x7675, 0x7676, 0x7677, 0x7678, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x487a, 0x7679, 0x767a, 0x767b, 0x767c,
+ 0x0000, 0x0000, 0x767d, 0x767e, 0x7721, 0x7722, 0x7723, 0x7724,
+ 0x7725, 0x0000, 0x0000, 0x7726, 0x7727, 0x7728, 0x316e, 0x7729,
+ 0x772a, 0x772b, 0x0000, 0x0000, 0x772c, 0x772d, 0x415b, 0x772e,
+ 0x0000, 0x0000, 0x772f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_9e[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4471,
+ 0x702f, 0x3c26, 0x7030, 0x4379, 0x0000, 0x4538, 0x513b, 0x0000,
+ 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x513c, 0x0000, 0x516c,
+ 0x0000, 0x7037, 0x7036, 0x5427, 0x0000, 0x4d52, 0x7038, 0x703a,
+ 0x7039, 0x703b, 0x703c, 0x0000, 0x0000, 0x386b, 0x703d, 0x3a68,
+ 0x0000, 0x703e, 0x703f, 0x3e69, 0x7040, 0x366c, 0x7041, 0x7042,
+ 0x7043, 0x7044, 0x4835, 0x7045, 0x7046, 0x0000, 0x7047, 0x4574,
+ 0x0000, 0x7048, 0x0000, 0x0000, 0x0000, 0x7049, 0x0000, 0x704a,
+ 0x773d, 0x0000, 0x704b, 0x704c, 0x704d, 0x0000, 0x704e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x704f, 0x3a57, 0x0000, 0x7050, 0x7051,
+ 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x7058, 0x0000, 0x0000,
+ 0x5325, 0x7057, 0x0000, 0x7059, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x753a, 0x4239,
+ 0x0000, 0x0000, 0x7764, 0x0000, 0x0000, 0x0000, 0x0000, 0x7765,
+ 0x7766, 0x0000, 0x0000, 0x7767, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x7768, 0x4234, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x776a, 0x0000, 0x776b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4273, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7470, 0x0000, 0x0000, 0x0000,
+ 0x746f, 0x0000, 0x0000, 0x4269, 0x0000, 0x7761, 0x7762, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3b46, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x5964, 0x0000, 0x0000, 0x0000, 0x4a72, 0x4068, 0x7024,
+ 0x0000, 0x3a5a, 0x0000, 0x0000, 0x472d, 0x0000, 0x0000, 0x0000,
+ 0x442c, 0x0000, 0x0000, 0x776c, 0x776d, 0x776e, 0x0000, 0x7770,
+ 0x776f, 0x0000, 0x7771, 0x0000, 0x0000, 0x7774, 0x0000, 0x7773,
+ 0x0000, 0x7772, 0x7775, 0x0000, 0x0000, 0x0000, 0x0000, 0x7776,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x6d69, 0x0000, 0x6d6a, 0x6d6b, 0x0000, 0x763c, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_9f[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x763d, 0x0000, 0x763e, 0x3626, 0x0000,
+ 0x583e, 0x0000, 0x0000, 0x3944, 0x0000, 0x0000, 0x0000, 0x583b,
+ 0x0000, 0x5c31, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x4a73, 0x0000, 0x7777, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x7778, 0x0000, 0x0000, 0x7779,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x777b,
+ 0x0000, 0x777a, 0x0000, 0x3147, 0x0000, 0x777c, 0x777d, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x777e, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x466b, 0x6c34, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x335d,
+ 0x7633, 0x0000, 0x0000, 0x7634, 0x4164, 0x7635, 0x7636, 0x7637,
+ 0x7638, 0x7639, 0x763a, 0x4823, 0x763b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x417a, 0x3928, 0x6d68, 0x0000, 0x0000, 0x0000, 0x396a,
+ 0x595f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_e7[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2659, 0x265a, 0x265b,
+ 0x265c, 0x265d, 0x265e, 0x265f, 0x266c, 0x266d, 0x2673, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_fe[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2672, 0x0000, 0x2674, 0x2675, 0x2660, 0x2661, 0x2670,
+ 0x2671, 0x2662, 0x2663, 0x266e, 0x266f, 0x2666, 0x2667, 0x2664,
+ 0x2665, 0x2668, 0x2669, 0x266a, 0x266b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static unsigned short gb2312_from_unicode_ff[] = {
+ 0x0000, 0x2321, 0x2322, 0x2323, 0x2167, 0x2325, 0x2326, 0x2327,
+ 0x2328, 0x2329, 0x232a, 0x232b, 0x232c, 0x232d, 0x232e, 0x232f,
+ 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337,
+ 0x2338, 0x2339, 0x233a, 0x233b, 0x233c, 0x233d, 0x233e, 0x233f,
+ 0x2340, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347,
+ 0x2348, 0x2349, 0x234a, 0x234b, 0x234c, 0x234d, 0x234e, 0x234f,
+ 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357,
+ 0x2358, 0x2359, 0x235a, 0x235b, 0x235c, 0x235d, 0x235e, 0x235f,
+ 0x2360, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367,
+ 0x2368, 0x2369, 0x236a, 0x236b, 0x236c, 0x236d, 0x236e, 0x236f,
+ 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377,
+ 0x2378, 0x2379, 0x237a, 0x237b, 0x237c, 0x237d, 0x212b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2169, 0x216a, 0x0000, 0x237e, 0x0000, 0x2324, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short * const gb2312_from_unicode_[] = {
+ gb2312_from_unicode_0,
+ gb2312_from_unicode_1,
+ gb2312_from_unicode_2,
+ gb2312_from_unicode_3,
+ gb2312_from_unicode_4,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ gb2312_from_unicode_1e,
+ u_allzeros,
+ gb2312_from_unicode_20,
+ gb2312_from_unicode_21,
+ gb2312_from_unicode_22,
+ gb2312_from_unicode_23,
+ gb2312_from_unicode_24,
+ gb2312_from_unicode_25,
+ gb2312_from_unicode_26,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ gb2312_from_unicode_30,
+ gb2312_from_unicode_31,
+ gb2312_from_unicode_32,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ gb2312_from_unicode_4e,
+ gb2312_from_unicode_4f,
+ gb2312_from_unicode_50,
+ gb2312_from_unicode_51,
+ gb2312_from_unicode_52,
+ gb2312_from_unicode_53,
+ gb2312_from_unicode_54,
+ gb2312_from_unicode_55,
+ gb2312_from_unicode_56,
+ gb2312_from_unicode_57,
+ gb2312_from_unicode_58,
+ gb2312_from_unicode_59,
+ gb2312_from_unicode_5a,
+ gb2312_from_unicode_5b,
+ gb2312_from_unicode_5c,
+ gb2312_from_unicode_5d,
+ gb2312_from_unicode_5e,
+ gb2312_from_unicode_5f,
+ gb2312_from_unicode_60,
+ gb2312_from_unicode_61,
+ gb2312_from_unicode_62,
+ gb2312_from_unicode_63,
+ gb2312_from_unicode_64,
+ gb2312_from_unicode_65,
+ gb2312_from_unicode_66,
+ gb2312_from_unicode_67,
+ gb2312_from_unicode_68,
+ gb2312_from_unicode_69,
+ gb2312_from_unicode_6a,
+ gb2312_from_unicode_6b,
+ gb2312_from_unicode_6c,
+ gb2312_from_unicode_6d,
+ gb2312_from_unicode_6e,
+ gb2312_from_unicode_6f,
+ gb2312_from_unicode_70,
+ gb2312_from_unicode_71,
+ gb2312_from_unicode_72,
+ gb2312_from_unicode_73,
+ gb2312_from_unicode_74,
+ gb2312_from_unicode_75,
+ gb2312_from_unicode_76,
+ gb2312_from_unicode_77,
+ gb2312_from_unicode_78,
+ gb2312_from_unicode_79,
+ gb2312_from_unicode_7a,
+ gb2312_from_unicode_7b,
+ gb2312_from_unicode_7c,
+ gb2312_from_unicode_7d,
+ gb2312_from_unicode_7e,
+ gb2312_from_unicode_7f,
+ gb2312_from_unicode_80,
+ gb2312_from_unicode_81,
+ gb2312_from_unicode_82,
+ gb2312_from_unicode_83,
+ gb2312_from_unicode_84,
+ gb2312_from_unicode_85,
+ gb2312_from_unicode_86,
+ gb2312_from_unicode_87,
+ gb2312_from_unicode_88,
+ gb2312_from_unicode_89,
+ gb2312_from_unicode_8a,
+ gb2312_from_unicode_8b,
+ gb2312_from_unicode_8c,
+ gb2312_from_unicode_8d,
+ gb2312_from_unicode_8e,
+ gb2312_from_unicode_8f,
+ gb2312_from_unicode_90,
+ gb2312_from_unicode_91,
+ gb2312_from_unicode_92,
+ gb2312_from_unicode_93,
+ gb2312_from_unicode_94,
+ gb2312_from_unicode_95,
+ gb2312_from_unicode_96,
+ gb2312_from_unicode_97,
+ gb2312_from_unicode_98,
+ gb2312_from_unicode_99,
+ gb2312_from_unicode_9a,
+ gb2312_from_unicode_9b,
+ gb2312_from_unicode_9c,
+ u_allzeros,
+ gb2312_from_unicode_9e,
+ gb2312_from_unicode_9f,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ gb2312_from_unicode_e7,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ u_allzeros,
+ gb2312_from_unicode_fe,
+ gb2312_from_unicode_ff
+};
+
+struct charmap2 gb2312_from_unicode = { 0, 255, (unsigned short **) gb2312_from_unicode_, (unichar_t *) unicode_from_gb2312 };
+
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/Unicode/descrip.mms b/Build/source/libs/luafontforge/fontforge/Unicode/descrip.mms
new file mode 100644
index 00000000000..10fccc109c2
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/Unicode/descrip.mms
@@ -0,0 +1,27 @@
+libgunicode_OBJECTS = ArabicForms.obj,alphabet.obj,backtrns.obj,char.obj,\
+ cjk.obj,memory.obj,ucharmap.obj,unialt.obj,ustring.obj,\
+ utype.obj,usprintf.obj,gwwiconv.obj
+
+CFLAGS=/incl=([-.inc])/name=(as_is,short)/nowarn/define=(\
+ "_STATIC_LIBFREETYPE=1","_STATIC_LIBPNG=1","HAVE_LIBINTL_H=1",\
+ "_STATIC_LIBUNINAMESLIST=1","_STATIC_LIBXML=1","_NO_XINPUT=1",\
+ "_STATIC_LIBUNGIF=1","_STATIC_LIBJPEG=1","_STATIC_LIBTIFF=1")
+
+all : [-.libs]libgunicode.olb
+ write sys$output "unicode finished"
+
+[-.libs]libgunicode.olb : $(libgunicode_OBJECTS)
+ library/create [-.libs]libgunicode.olb $(libgunicode_OBJECTS)
+
+ArabicForms.obj : ArabicForms.c
+alphabet.obj : alphabet.c
+backtrns.obj : backtrns.c
+char.obj : char.c
+cjk.obj : cjk.c
+memory.obj : memory.c
+ucharmap.obj : ucharmap.c
+unialt.obj : unialt.c
+ustring.obj : ustring.c
+utype.obj : utype.c
+usprintf.obj : usprintf.c
+gwwiconv.obj : gwwiconv.c
diff --git a/Build/source/libs/luafontforge/fontforge/Unicode/gwwiconv.c b/Build/source/libs/luafontforge/fontforge/Unicode/gwwiconv.c
new file mode 100644
index 00000000000..a2033e499f6
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/Unicode/gwwiconv.c
@@ -0,0 +1,1074 @@
+/* Copyright (C) 2004-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <basics.h>
+#include <gwwiconv.h>
+#include <charset.h>
+#include <chardata.h>
+#include <string.h>
+#include <ustring.h>
+#include <stdio.h>
+
+#ifdef LUA_FF_LIB
+extern void LogError(const char *fmt,...);
+#endif
+
+#ifndef HAVE_ICONV_H
+
+/* I have written an limited iconv which will convert either to or from unichar_t */
+/* (either UCS2 or UCS4) */
+/* it will not convert latin1 to latin2, but latin1->UCS2, UCS2->latin2 */
+/* it uses the encodings built into libgunicode for systems with no iconv */
+/* (ie. macs before 10.3, perhaps others) */
+
+struct gww_iconv_t {
+ enum encoding from;
+ enum encoding to;
+};
+
+enum extended_encoding { e_jisgbpk = e_encodingmax };
+
+static enum endian { end_big, end_little, end_unknown } endian = end_unknown;
+
+static void endian_detector(void) {
+ union { short s; char c[2]; } u;
+
+ u.s = 0x0102;
+ if ( u.c[0]==0x1 )
+ endian = end_big;
+ else
+ endian = end_little;
+}
+
+static enum encoding name_to_enc(const char *encname) {
+ struct { const char *name; enum encoding enc; } map[] = {
+ { "UCS2", e_unicode },
+ { "UCS-2", e_unicode },
+ { "UCS-2-INTERNAL", e_unicode },
+ { "ISO-10646/UCS2", e_unicode },
+ { "ISO-10646/USC2", e_unicode }, /* Old typo */
+ { "UCS4", e_ucs4 },
+ { "UCS-4", e_ucs4 },
+ { "UCS-4-INTERNAL", e_ucs4 },
+ { "ISO-10646/UCS4", e_ucs4 },
+ { "iso8859-1", e_iso8859_1 },
+ { "iso8859-2", e_iso8859_2 },
+ { "iso8859-3", e_iso8859_3 },
+ { "iso8859-4", e_iso8859_4 },
+ { "iso8859-5", e_iso8859_5 },
+ { "iso8859-6", e_iso8859_6 },
+ { "iso8859-7", e_iso8859_7 },
+ { "iso8859-8", e_iso8859_8 },
+ { "iso8859-9", e_iso8859_9 },
+ { "iso8859-10", e_iso8859_10 },
+ { "iso8859-11", e_iso8859_11 },
+ { "iso8859-13", e_iso8859_13 },
+ { "iso8859-14", e_iso8859_14 },
+ { "iso8859-15", e_iso8859_15 },
+ { "iso-8859-1", e_iso8859_1 },
+ { "iso-8859-2", e_iso8859_2 },
+ { "iso-8859-3", e_iso8859_3 },
+ { "iso-8859-4", e_iso8859_4 },
+ { "iso-8859-5", e_iso8859_5 },
+ { "iso-8859-6", e_iso8859_6 },
+ { "iso-8859-7", e_iso8859_7 },
+ { "iso-8859-8", e_iso8859_8 },
+ { "iso-8859-9", e_iso8859_9 },
+ { "iso-8859-10", e_iso8859_10 },
+ { "iso-8859-11", e_iso8859_11 },
+ { "iso-8859-13", e_iso8859_13 },
+ { "iso-8859-14", e_iso8859_14 },
+ { "iso-8859-15", e_iso8859_15 },
+ { "koi8-r", e_koi8_r },
+ { "jis201", e_jis201 },
+ { "mac", e_mac },
+ { "Macintosh", e_mac },
+ { "MS-ANSI", e_win },
+ { "EUC-KR", e_wansung },
+ { "johab", e_johab },
+ { "ISO-2022-KR", e_jiskorean },
+ { "ISO-2022-CN", e_jisgb },
+ { "EUC-CN", e_jisgbpk },
+ { "big5", e_big5 },
+ { "big5hkscs", e_big5hkscs },
+ { "ISO-2022-JP", e_jis },
+ { "ISO-2022-JP-2", e_jis2 },
+ { "Sjis", e_sjis },
+ { "UTF-8", e_utf8 },
+ { "UTF8", e_utf8 },
+ { NULL }};
+ int i;
+
+ for ( i=0; map[i].name!=NULL; ++i )
+ if ( strmatch(map[i].name,encname)==0 )
+return( map[i].enc );
+
+return( -1 );
+}
+
+gww_iconv_t gww_iconv_open(const char *toenc,const char *fromenc) {
+ struct gww_iconv_t stuff, *ret;
+
+ if ( endian==end_unknown )
+ endian_detector();
+
+ stuff.from = name_to_enc(fromenc);
+ stuff.to = name_to_enc(toenc);
+ if ( stuff.from==(enum encoding) -1 || stuff.to==(enum encoding) -1 ) {
+ /*fprintf( stderr, "Unknown encoding\n" );*/
+return( (iconv_t)(-1) );
+#ifdef UNICHAR_16
+ } else if ( stuff.from!=e_unicode && stuff.to!=e_unicode ) {
+ fprintf( stderr, "Bad call to gww_iconv_open, neither arg is UCS2\n" );
+return( (iconv_t)(-1) );
+#else
+ } else if ( stuff.from!=e_ucs4 && stuff.to!=e_ucs4 ) {
+#ifdef LUA_FF_LIB
+ LogError("Bad call to gww_iconv_open, neither arg is UCS4 (%s->%s)", fromenc, toenc);
+#else
+ fprintf( stderr, "Bad call to gww_iconv_open, neither arg is UCS4 (%s->%s)\n" , fromenc, toenc);
+#endif
+return( (iconv_t)(-1) );
+#endif
+ }
+
+ ret = galloc(sizeof(struct gww_iconv_t));
+ *ret = stuff;
+return( ret );
+}
+
+void gww_iconv_close( gww_iconv_t cd) {
+ free(cd);
+}
+
+size_t gww_iconv( gww_iconv_t _cd,
+ char **inbuf, size_t *inlen,
+ char **outbuf, size_t *outlen) {
+ struct gww_iconv_t *cd = _cd;
+ int char_cnt = 0;
+ unsigned char *plane;
+ int ch;
+
+ if ( inbuf==NULL || outbuf==NULL || inlen==NULL || outlen==NULL ||
+ *inbuf==NULL || *outbuf==NULL )
+return( 0 ); /* Legal, used to reset the state. As we don't do states, irrelevant */
+
+ if ( cd->from<0 || cd->from>e_encodingmax || cd->to<0 || cd->to>e_encodingmax ) {
+ fprintf( stderr, "Garbage encoding passed to gww_iconv()\n" );
+return( (size_t) -1 );
+ }
+
+ if ( cd->from==e_unicode ) {
+ if ( cd->to==e_unicode ) {
+ int min = *inlen < *outlen ? *inlen : *outlen;
+ min &= ~1;
+ memcpy(*inbuf,*outbuf,min);
+ char_cnt = min/sizeof(short);
+ *inbuf += min; *outbuf += min;
+ *inlen -= min; *outlen -= min;
+ if ( *inlen==1 && *outlen>0 )
+return( (size_t) -1 ); /* Incomplete multi-byte sequence */
+ } else if ( cd->to==e_ucs4 ) {
+ int min = *inlen/sizeof(short) < *outlen/sizeof(int32) ? *inlen/sizeof(short) : *outlen/sizeof(int32);
+ int highch, lowch;
+ if ( endian == end_little ) {
+ while ( *inlen>=sizeof(short) && *outlen>=sizeof(int32) ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ ((uint8 *) outbuf)[3] = 0; ((uint8 *) outbuf)[2] = 0;
+ ((uint8 *) outbuf)[1] = highch; ((uint8 *) outbuf)[0] = lowch;
+ outbuf += sizeof(int32); inbuf += sizeof(short);
+ *outlen -= sizeof(int32); *inlen -= sizeof(short);
+ }
+ } else {
+ while ( *inlen>=sizeof(short) && *outlen>=sizeof(int32) ) {
+ highch = ((unsigned char *) *inbuf)[0], lowch = ((unsigned char *) *inbuf)[1];
+ ((uint8 *) outbuf)[0] = 0; ((uint8 *) outbuf)[1] = 0;
+ ((uint8 *) outbuf)[2] = highch; ((uint8 *) outbuf)[3] = lowch;
+ outbuf += sizeof(int32); inbuf += sizeof(short);
+ *outlen -= sizeof(int32); *inlen -= sizeof(short);
+ }
+ }
+ char_cnt = min;
+ if ( *inlen==1 && *outlen>0 )
+return( (size_t) -1 ); /* Incomplete multi-byte sequence */
+ } else if ( cd->to<e_first2byte ) {
+ struct charmap *table = NULL;
+ table = alphabets_from_unicode[cd->to];
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = *(unsigned char *) *inbuf, lowch = ((unsigned char *) *inbuf)[1];
+ }
+ if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ *((*outbuf)++) = ch;
+ -- *outlen;
+ *inlen -= 2;
+ *inbuf += 2;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+#ifndef LUA_FF_LIB
+ } else if ( cd->to==e_johab || cd->to==e_big5 || cd->to==e_big5hkscs ) {
+ struct charmap2 *table = cd->to==e_johab ? &johab_from_unicode :
+ cd->to==e_big5 ? &big5_from_unicode :
+ &big5hkscs_from_unicode;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = *(unsigned char *) *inbuf, lowch = ((unsigned char *) *inbuf)[1];
+ }
+ if ( highch==0 && lowch<=0x80 ) {
+ *((*outbuf)++) = highch;
+ --*outlen;
+ *inlen-=2;
+ *inbuf+=2;
+ ++char_cnt;
+ } else if ( *outlen==1 )
+return( (size_t) -1 );
+ else if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ *((*outbuf)++) = (ch>>8);
+ *((*outbuf)++) = (ch&0xff);
+ *outlen -= 2;
+ *inlen -= 2;
+ *inbuf += 2;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_wansung || cd->to==e_jisgbpk ) {
+ struct charmap2 *table = cd->to==e_wansung ? &ksc5601_from_unicode :
+ &gb2312_from_unicode;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = *(unsigned char *) *inbuf, lowch = ((unsigned char *) *inbuf)[1];
+ }
+ if ( highch==0 && lowch<=0x80 ) {
+ *((*outbuf)++) = lowch;
+ --*outlen;
+ *inlen-=2;
+ *inbuf+=2;
+ ++char_cnt;
+ } else if ( *outlen==1 )
+return( (size_t) -1 );
+ else if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ *((*outbuf)++) = (ch>>8)+0x80;
+ *((*outbuf)++) = (ch&0xff)+0x80;
+ *outlen -= 2;
+ *inlen -= 2;
+ *inbuf += 2;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_sjis ) {
+ unsigned char *plane1;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = *(unsigned char *) *inbuf, lowch = ((unsigned char *) *inbuf)[1];
+ }
+ if (( highch>=jis201_from_unicode.first && highch<=jis201_from_unicode.last &&
+ (plane1 = jis201_from_unicode.table[highch-jis201_from_unicode.first])!=NULL &&
+ (ch=plane1[lowch])!=0 ) ||
+ ( highch==0 && (ch=lowch)<' ' )) { /* control chars not mapped in jis201 */
+ *((*outbuf)++) = ch;
+ --*outlen;
+ *inlen-=2;
+ *inbuf+=2;
+ ++char_cnt;
+ } else if ( *outlen==1 )
+return( (size_t) -1 );
+ else if ( highch>=jis_from_unicode.first && highch<=jis_from_unicode.last &&
+ (plane = jis_from_unicode.table[highch-jis_from_unicode.first])!=NULL &&
+ (ch=plane[lowch])!=0 && ch<0x8000 ) { /* no jis212 */
+ int j1 = ch>>8, j2 = ch&0xff;
+ int ro = j1<95 ? 112 : 176;
+ int co = (j1&1) ? (j2>95?32:31) : 126;
+ *((*outbuf)++) = ((j1+1)>>1)+ro;
+ *((*outbuf)++) = j2+co;
+ *outlen -= 2;
+ *inlen -= 2;
+ *inbuf += 2;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_jis || cd->to==e_jis2 ||
+ cd->to==e_jiskorean || cd->to==e_jisgb ) {
+ struct charmap2 *table = cd->to==e_jisgb ? &gb2312_from_unicode :
+ cd->to==e_jiskorean ? &ksc5601_from_unicode :
+ &jis_from_unicode;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>1 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = *(unsigned char *) *inbuf, lowch = ((unsigned char *) *inbuf)[1];
+ }
+ if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ if ( ch>=0x8000 ) {
+ if ( cd->to!=e_jis2 )
+return( (size_t) -1 );
+ ch -= 0x8000;
+ } else {
+ if ( cd->to==e_jis2 )
+return( (size_t) -1 );
+ }
+ *((*outbuf)++) = (ch>>8);
+ *((*outbuf)++) = (ch&0xff);
+ *outlen -= 2;
+ *inlen -= 2;
+ *inbuf += 2;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+#endif
+ } else if ( cd->to==e_utf8 ) {
+ while ( *inlen>1 && *outlen>0 ) {
+ unichar_t uch;
+ if ( endian == end_little ) {
+ uch = (((unsigned char *) *inbuf)[1]<<8) | (*((unsigned char *) *inbuf));
+ } else {
+ uch = (*((unsigned char *) *inbuf)<<8) | (((unsigned char *) *inbuf)[1]);
+ }
+ if ( uch < 0x80 ) {
+ *((*outbuf)++) = uch;
+ --*outlen;
+ } else if ( uch<0x800 ) {
+ if ( *outlen==1 )
+return( (size_t) -1 );
+ *((*outbuf)++) = 0xc0 | (uch>>6);
+ *((*outbuf)++) = 0x80 | (uch&0x3f);
+ *outlen-=2;
+ } else { /* I'm not dealing with */
+ if ( *outlen<=2 )
+return( (size_t) -1 );
+ *((*outbuf)++) = 0xe0 | (uch>>12);
+ *((*outbuf)++) = 0x80 | ((uch>>6)&0x3f);
+ *((*outbuf)++) = 0x80 | (uch&0x3f);
+ *outlen-=3;
+ }
+ *inbuf += 2;
+ *inlen -= 2;
+ ++char_cnt;
+ }
+ } else {
+ fprintf( stderr, "Unexpected encoding\n" );
+return( (size_t) -1 );
+ }
+ } else if ( cd->from==e_ucs4 ) {
+ if ( cd->to==e_unicode ) {
+ int min = *inlen/sizeof(int32) < *outlen/sizeof(int16) ? *inlen/sizeof(int32) : *outlen/sizeof(int16);
+ int highch, lowch;
+ if ( endian == end_little ) {
+ while ( *inlen>=sizeof(short) && *outlen>=sizeof(int32) ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ ((uint8 *) outbuf)[1] = highch; ((uint8 *) outbuf)[0] = lowch;
+ outbuf += sizeof(int16); inbuf += sizeof(int32);
+ *outlen -= sizeof(int16); *inlen -= sizeof(int32);
+ }
+ } else {
+ while ( *inlen>=sizeof(short) && *outlen>=sizeof(int32) ) {
+ highch = ((unsigned char *) *inbuf)[2], lowch = ((unsigned char *) *inbuf)[3];
+ ((uint8 *) outbuf)[0] = highch; ((uint8 *) outbuf)[1] = lowch;
+ outbuf += sizeof(int16); inbuf += sizeof(int32);
+ *outlen -= sizeof(int16); *inlen -= sizeof(int32);
+ }
+ }
+ char_cnt = min;
+ if ( *inlen>0 && *outlen>0 )
+return( (size_t) -1 ); /* Incomplete multi-byte sequence */
+ } else if ( cd->to<e_first2byte ) {
+ struct charmap *table = NULL;
+ table = alphabets_from_unicode[cd->to];
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = ((unsigned char *) *inbuf)[2], lowch = ((unsigned char *) *inbuf)[3];
+ }
+ if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ *((*outbuf)++) = ch;
+ -- *outlen;
+ *inlen -= 4;
+ *inbuf += 4;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+#ifndef LUA_FF_LIB
+ } else if ( cd->to==e_johab || cd->to==e_big5 || cd->to==e_big5hkscs ) {
+ struct charmap2 *table = cd->to==e_johab ? &johab_from_unicode :
+ cd->to==e_big5 ? &big5_from_unicode :
+ &big5hkscs_from_unicode;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = ((unsigned char *) *inbuf)[2], lowch = ((unsigned char *) *inbuf)[3];
+ }
+ if ( highch==0 && lowch<=0x80 ) {
+ *((*outbuf)++) = highch;
+ --*outlen;
+ *inlen-=4;
+ *inbuf+=4;
+ ++char_cnt;
+ } else if ( *outlen==1 )
+return( (size_t) -1 );
+ else if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ *((*outbuf)++) = (ch>>8);
+ *((*outbuf)++) = (ch&0xff);
+ *outlen -= 2;
+ *inlen -= 4;
+ *inbuf += 4;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_wansung || cd->to==e_jisgbpk ) {
+ struct charmap2 *table = cd->to==e_wansung ? &ksc5601_from_unicode :
+ &gb2312_from_unicode;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = ((unsigned char *) *inbuf)[2], lowch = ((unsigned char *) *inbuf)[3];
+ }
+ if ( highch==0 && lowch<=0x80 ) {
+ *((*outbuf)++) = lowch;
+ --*outlen;
+ *inlen-=4;
+ *inbuf+=4;
+ ++char_cnt;
+ } else if ( *outlen==1 )
+return( (size_t) -1 );
+ else if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ *((*outbuf)++) = (ch>>8)+0x80;
+ *((*outbuf)++) = (ch&0xff)+0x80;
+ *outlen -= 2;
+ *inlen -= 4;
+ *inbuf += 4;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_sjis ) {
+ unsigned char *plane1;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = ((unsigned char *) *inbuf)[2], lowch = ((unsigned char *) *inbuf)[3];
+ }
+ if (( highch>=jis201_from_unicode.first && highch<=jis201_from_unicode.last &&
+ (plane1 = jis201_from_unicode.table[highch-jis201_from_unicode.first])!=NULL &&
+ (ch=plane1[lowch])!=0 ) ||
+ ( highch==0 && (ch=lowch)<' ' )) { /* control chars not mapped in jis201 */
+ *((*outbuf)++) = ch;
+ --*outlen;
+ *inlen-=4;
+ *inbuf+=4;
+ ++char_cnt;
+ } else if ( *outlen==1 )
+return( (size_t) -1 );
+ else if ( highch>=jis_from_unicode.first && highch<=jis_from_unicode.last &&
+ (plane = jis_from_unicode.table[highch-jis_from_unicode.first])!=NULL &&
+ (ch=plane[lowch])!=0 && ch<0x8000 ) { /* no jis212 */
+ int j1 = ch>>8, j2 = ch&0xff;
+ int ro = j1<95 ? 112 : 176;
+ int co = (j1&1) ? (j2>95?32:31) : 126;
+ *((*outbuf)++) = ((j1+1)>>1)+ro;
+ *((*outbuf)++) = j2+co;
+ *outlen -= 2;
+ *inlen -= 4;
+ *inbuf += 4;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_jis || cd->to==e_jis2 ||
+ cd->to==e_jiskorean || cd->to==e_jisgb ) {
+ struct charmap2 *table = cd->to==e_jisgb ? &gb2312_from_unicode :
+ cd->to==e_jiskorean ? &ksc5601_from_unicode :
+ &jis_from_unicode;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>1 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = ((unsigned char *) *inbuf)[2], lowch = ((unsigned char *) *inbuf)[3];
+ }
+ if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ if ( ch>=0x8000 ) {
+ if ( cd->to!=e_jis2 )
+return( (size_t) -1 );
+ ch -= 0x8000;
+ } else {
+ if ( cd->to==e_jis2 )
+return( (size_t) -1 );
+ }
+ *((*outbuf)++) = (ch>>8);
+ *((*outbuf)++) = (ch&0xff);
+ *outlen -= 2;
+ *inlen -= 4;
+ *inbuf += 4;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+#endif
+ } else if ( cd->to==e_utf8 ) {
+ while ( *inlen>1 && *outlen>0 ) {
+ int uch;
+ if ( endian == end_little ) {
+ uch = (((unsigned char *) *inbuf)[3]<<24) |
+ (((unsigned char *) *inbuf)[2]<<16) |
+ (((unsigned char *) *inbuf)[1]<<8) |
+ (*((unsigned char *) *inbuf));
+ } else {
+ uch = (*((unsigned char *) *inbuf)<<24) |
+ (((unsigned char *) *inbuf)[1]<<16) |
+ (((unsigned char *) *inbuf)[2]<<8) |
+ (((unsigned char *) *inbuf)[3]);
+ }
+ if ( uch < 0x80 ) {
+ *((*outbuf)++) = uch;
+ --*outlen;
+ } else if ( uch<0x800 ) {
+ if ( *outlen==1 )
+return( (size_t) -1 );
+ *((*outbuf)++) = 0xc0 | (uch>>6);
+ *((*outbuf)++) = 0x80 | (uch&0x3f);
+ *outlen-=2;
+ } else if ( uch < 0x10000 ) {
+ if ( *outlen<=2 )
+return( (size_t) -1 );
+ *((*outbuf)++) = 0xe0 | (uch>>12);
+ *((*outbuf)++) = 0x80 | ((uch>>6)&0x3f);
+ *((*outbuf)++) = 0x80 | (uch&0x3f);
+ *outlen-=3;
+ } else {
+ uint32 val = uch-0x10000;
+ int u = ((val&0xf0000)>>16)+1, z=(val&0x0f000)>>12, y=(val&0x00fc0)>>6, x=val&0x0003f;
+ if ( *outlen<=3 )
+return( (size_t) -1 );
+ *(*outbuf)++ = 0xf0 | (u>>2);
+ *(*outbuf)++ = 0x80 | ((u&3)<<4) | z;
+ *(*outbuf)++ = 0x80 | y;
+ *(*outbuf)++ = 0x80 | x;
+ *outlen-=4;
+ }
+ *inbuf += 4;
+ *inlen -= 4;
+ ++char_cnt;
+ }
+ } else {
+ fprintf( stderr, "Unexpected encoding\n" );
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_unicode ) {
+ const unichar_t *table;
+ if ( cd->from<e_first2byte ) {
+ table = unicode_from_alphabets[cd->from];
+ while ( *inlen>0 && *outlen>1 ) {
+ unichar_t ch = table[ *(unsigned char *) ((*inbuf)++)];
+ --*inlen;
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_jis || cd->from==e_jis2 ||
+ cd->from==e_jiskorean || cd->from==e_jisgb ) {
+ table = cd->from==e_jisgb ? unicode_from_gb2312 :
+ cd->from==e_jiskorean ? unicode_from_ksc5601 :
+ cd->from==e_jis ? unicode_from_jis208 :
+ unicode_from_jis212;
+ while ( *inlen>1 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch;
+ if ( *ipt<0x21 || *ipt>0x7e || ipt[1]<0x21 || ipt[1]>0x7e )
+return( (size_t) -1 );
+ ch = (*ipt-0x21)*94 + (ipt[1]-0x21);
+ ch = table[ch];
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ if ( *inlen==1 && *outlen>0 )
+return( (size_t) -1 ); /* Incomplete multi-byte sequence */
+ } else if ( cd->from==e_wansung || cd->from==e_jisgbpk ) {
+ table = cd->from==e_jisgbpk ? unicode_from_gb2312 :
+ unicode_from_ksc5601 ;
+ while ( *inlen>0 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch;
+ if ( *ipt<0x7f ) {
+ ch = *ipt;
+ --*inlen;
+ *inbuf = (char *) ipt+1;
+ } else {
+ if ( *ipt<0xa1 || *ipt>0xfe || ipt[1]<0xa1 || ipt[1]>0xfe ||
+ *inlen==1 )
+return( (size_t) -1 );
+ ch = (*ipt-0xa1)*94 + (ipt[1]-0xa1);
+ ch = table[ch];
+ *inlen -= 2;;
+ *inbuf = (char *) ipt+2;
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_johab || cd->from==e_big5 || cd->from==e_big5hkscs ) {
+ int offset;
+ if ( cd->from==e_big5 ) {
+ offset = 0xa100;
+ table = unicode_from_big5;
+ } else if ( cd->from==e_big5hkscs ) {
+ offset = 0x8100;
+ table = unicode_from_big5hkscs;
+ } else {
+ offset = 0x8400;
+ table = unicode_from_johab;
+ }
+ while ( *inlen>0 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch;
+ if ( *ipt<0x7f ) {
+ ch = *ipt;
+ --*inlen;
+ *inbuf = (char *) ipt+1;
+ } else {
+ if ( *inlen==1 )
+return( (size_t) -1 );
+ ch = (*ipt<<8) | ipt[1];
+ if ( ch<offset )
+return( (size_t) -1 );
+ ch -= offset;
+ ch = table[ch];
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_sjis ) {
+ while ( *inlen>0 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch1 = *ipt;
+ if ( ch1<127 || ( ch1>=161 && ch1<=223 )) {
+ ch = unicode_from_jis201[ch1];
+ *inbuf = (char *) ipt+1;
+ --*inlen;
+ } else if ( *inlen==1 )
+return( (size_t) -1 );
+ else {
+ int ch2 = ipt[1];
+ if ( ch1 >= 129 && ch1<= 159 )
+ ch1 -= 112;
+ else
+ ch1 -= 176;
+ ch1 <<= 1;
+ if ( ch2>=159 )
+ ch2-= 126;
+ else if ( ch2>127 ) {
+ --ch1;
+ ch2 -= 32;
+ } else {
+ --ch1;
+ ch2 -= 31;
+ }
+ if ( ch1-0x21>=94 || ch2-0x21>=94 )
+return( (size_t) -1 );
+ ch = unicode_from_jis208[(ch1-0x21)*94+(ch2-0x21)];
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_utf8 ) {
+ while ( *inlen>0 && *outlen>sizeof(unichar_t) ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch = *ipt;
+ if ( ch <= 127 ) {
+ *inbuf = (char *) ipt+1;
+ --*inlen;
+ } else if ( ch<=0xdf ) {
+ if ( *inlen<2 || ipt[1]<0x80 )
+return( (size_t) -1 );
+ ch = ((ch&0x1f)<<6) | (ipt[1] &0x3f);
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ } else if ( ch<=0xef ) {
+ if ( *inlen<3 || ipt[1]<0x80 || ipt[2]<0x80 )
+return( (size_t) -1 );
+ ch = ((ch&0x1f)<<12) | ((ipt[1] &0x3f)<<6) | (ipt[2]&0x3f);
+ *inlen -= 3;
+ *inbuf = (char *) ipt+3;
+ } else {
+ int w;
+ if ( *inlen<4 || *outlen<4 || ipt[1]<0x80 || ipt[2]<0x80 || ipt[3]<0x80 )
+return( (size_t) -1 );
+ w = ( ((ch&0x7)<<2) | ((ipt[1]&0x30)>>4) )-1;
+ ch = 0xd800 | (w<<6) | ((ipt[1]&0xf)<<2) | ((ipt[2]&0x30)>>4);
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= 2;
+ ch = 0xdc00 | ((ipt[2]&0xf)<<6) | (ipt[3]&0x3f);
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else {
+ fprintf( stderr, "Unexpected encoding\n" );
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_ucs4 ) {
+ const unichar_t *table;
+ if ( cd->from<e_first2byte ) {
+ table = unicode_from_alphabets[cd->from];
+ while ( *inlen>0 && *outlen>1 ) {
+ unichar_t ch = table[ *(unsigned char *) ((*inbuf)++)];
+ --*inlen;
+ if ( endian==end_little ) {
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_jis || cd->from==e_jis2 ||
+ cd->from==e_jiskorean || cd->from==e_jisgb ) {
+ table = cd->from==e_jisgb ? unicode_from_gb2312 :
+ cd->from==e_jiskorean ? unicode_from_ksc5601 :
+ cd->from==e_jis ? unicode_from_jis208 :
+ unicode_from_jis212;
+ while ( *inlen>1 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch;
+ if ( *ipt<0x21 || *ipt>0x7e || ipt[1]<0x21 || ipt[1]>0x7e )
+return( (size_t) -1 );
+ ch = (*ipt-0x21)*94 + (ipt[1]-0x21);
+ ch = table[ch];
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ if ( endian==end_little ) {
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ if ( *inlen==1 && *outlen>0 )
+return( (size_t) -1 ); /* Incomplete multi-byte sequence */
+ } else if ( cd->from==e_wansung || cd->from==e_jisgbpk ) {
+ table = cd->from==e_jisgbpk ? unicode_from_gb2312 :
+ unicode_from_ksc5601 ;
+ while ( *inlen>0 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch;
+ if ( *ipt<0x7f ) {
+ ch = *ipt;
+ --*inlen;
+ *inbuf = (char *) ipt+1;
+ } else {
+ if ( *ipt<0xa1 || *ipt>0xfe || ipt[1]<0xa1 || ipt[1]>0xfe ||
+ *inlen==1 )
+return( (size_t) -1 );
+ ch = (*ipt-0xa1)*94 + (ipt[1]-0xa1);
+ ch = table[ch];
+ *inlen -= 2;;
+ *inbuf = (char *) ipt+2;
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_johab || cd->from==e_big5 || cd->from==e_big5hkscs ) {
+ int offset;
+ if ( cd->from==e_big5 ) {
+ offset = 0xa100;
+ table = unicode_from_big5;
+ } else if ( cd->from==e_big5hkscs ) {
+ offset = 0x8100;
+ table = unicode_from_big5hkscs;
+ } else {
+ offset = 0x8400;
+ table = unicode_from_johab;
+ }
+ while ( *inlen>0 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch;
+ if ( *ipt<0x7f ) {
+ ch = *ipt;
+ --*inlen;
+ *inbuf = (char *) ipt+1;
+ } else {
+ if ( *inlen==1 )
+return( (size_t) -1 );
+ ch = (*ipt<<8) | ipt[1];
+ if ( ch<offset )
+return( (size_t) -1 );
+ ch -= offset;
+ ch = table[ch];
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_sjis ) {
+ while ( *inlen>0 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch1 = *ipt;
+ if ( ch1<127 || ( ch1>=161 && ch1<=223 )) {
+ ch = unicode_from_jis201[ch1];
+ *inbuf = (char *) ipt+1;
+ --*inlen;
+ } else if ( *inlen==1 )
+return( (size_t) -1 );
+ else {
+ int ch2 = ipt[1];
+ if ( ch1 >= 129 && ch1<= 159 )
+ ch1 -= 112;
+ else
+ ch1 -= 176;
+ ch1 <<= 1;
+ if ( ch2>=159 )
+ ch2-= 126;
+ else if ( ch2>127 ) {
+ --ch1;
+ ch2 -= 32;
+ } else {
+ --ch1;
+ ch2 -= 31;
+ }
+ if ( ch1-0x21>=94 || ch2-0x21>=94 )
+return( (size_t) -1 );
+ ch = unicode_from_jis208[(ch1-0x21)*94+(ch2-0x21)];
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_utf8 ) {
+ while ( *inlen>0 && *outlen>sizeof(unichar_t) ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch = *ipt;
+ if ( ch <= 127 ) {
+ *inbuf = (char *) ipt+1;
+ --*inlen;
+ } else if ( ch<=0xdf ) {
+ if ( *inlen<2 || ipt[1]<0x80 )
+return( (size_t) -1 );
+ ch = ((ch&0x1f)<<6) | (ipt[1] &0x3f);
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ } else if ( ch<=0xef ) {
+ if ( *inlen<3 || ipt[1]<0x80 || ipt[2]<0x80 )
+return( (size_t) -1 );
+ ch = ((ch&0x1f)<<12) | ((ipt[1] &0x3f)<<6) | (ipt[2]&0x3f);
+ *inlen -= 3;
+ *inbuf = (char *) ipt+3;
+ } else {
+ int w,w2;
+ w = ( ((*ipt&0x7)<<2) | ((ipt[1]&0x30)>>4) )-1;
+ w = (w<<6) | ((ipt[1]&0xf)<<2) | ((ipt[2]&0x30)>>4);
+ w2 = ((ipt[2]&0xf)<<6) | (ipt[3]&0x3f);
+ ch = w*0x400 + w2 + 0x10000;
+ *inbuf = (char *) ipt+4;
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch>>16;
+ *((*outbuf)++) = ch>>24;
+ } else {
+ *((*outbuf)++) = ch>>24;
+ *((*outbuf)++) = ch>>16;
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else {
+ fprintf( stderr, "Unexpected encoding\n" );
+return( (size_t) -1 );
+ }
+ } else {
+ fprintf( stderr, "One of the two encodings must be UCS2 in gww_iconv()\n" );
+return( (size_t) -1 );
+ }
+
+ if ( *outlen>=1 ) {
+ **outbuf = '\0';
+ if ( *outlen>1 )
+ (*outbuf)[1] = '\0';
+ if ( cd->to==e_ucs4 && *outlen>3 ) {
+ (*outbuf)[2] = '\0';
+ (*outbuf)[3] = '\0';
+ }
+ }
+return( char_cnt );
+}
+#else
+static const int a_file_must_define_something=1;
+#endif /* HAVE_ICONV_H */
diff --git a/Build/source/libs/luafontforge/fontforge/Unicode/memory.c b/Build/source/libs/luafontforge/fontforge/Unicode/memory.c
new file mode 100644
index 00000000000..a8458c4c6bd
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/Unicode/memory.c
@@ -0,0 +1,90 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ustring.h"
+
+/* wrappers around standard memory routines so we can trap errors. */
+static void default_trap(void) {
+ fprintf(stderr, "Attempt to allocate memory failed.\n" );
+ abort();
+}
+
+static void (*trap)(void) = default_trap;
+
+void galloc_set_trap(void (*newtrap)(void)) {
+ if ( newtrap==NULL ) newtrap = default_trap;
+ trap = newtrap;
+}
+
+void *galloc(long size) {
+ void *ret;
+ while (( ret = malloc(size))==NULL )
+ trap();
+ memset(ret,0x3c,size); /* fill with random junk for debugging */
+return( ret );
+}
+
+void *gcalloc(int cnt,long size) {
+ void *ret;
+ while (( ret = calloc(cnt,size))==NULL )
+ trap();
+return( ret );
+}
+
+void *grealloc(void *old,long size) {
+ void *ret;
+ while (( ret = realloc(old,size))==NULL )
+ trap();
+return( ret );
+}
+
+void gfree(void *old) {
+ free(old);
+}
+
+char *copy(const char *str) {
+ char *ret;
+
+ if ( str==NULL )
+return( NULL );
+ ret = galloc(strlen(str)+1);
+ strcpy(ret,str);
+return( ret );
+}
+
+char *copyn(const char *str,long n) {
+ char *ret;
+
+ if ( str==NULL )
+return( NULL );
+ ret = galloc(n+1);
+ memcpy(ret,str,n);
+ ret[n]='\0';
+return( ret );
+}
diff --git a/Build/source/libs/luafontforge/fontforge/Unicode/ustring.c b/Build/source/libs/luafontforge/fontforge/Unicode/ustring.c
new file mode 100644
index 00000000000..be4f2d46018
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/Unicode/ustring.c
@@ -0,0 +1,885 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stddef.h>
+#include "ustring.h"
+#include "utype.h"
+
+#ifdef LUA_FF_LIB
+extern int unic_tolower(int);
+#define Tolower unic_tolower
+#else
+#define Tolower tolower
+#endif
+
+
+long uc_strcmp(const unichar_t *str1,const char *str2) {
+ long ch1, ch2;
+ for (;;) {
+ ch1 = *str1++; ch2 = *(unsigned char *) str2++ ;
+ if ( ch1!=ch2 || ch1=='\0' )
+return(ch1-ch2);
+ }
+}
+
+long uc_strncmp(const unichar_t *str1,const char *str2,int n) {
+ long ch1, ch2;
+ while ( --n>=0 ) {
+ ch1 = *str1++; ch2 = *(unsigned char *) str2++ ;
+ if ( ch1!=ch2 || ch1=='\0' )
+return(ch1-ch2);
+ }
+return( 0 );
+}
+
+long uc_strmatch(const unichar_t *str1, const char *str2) {
+ long ch1, ch2;
+ for (;;) {
+ ch1 = *str1++; ch2 = *(unsigned char *) str2++ ;
+ ch1 = Tolower(ch1);
+ ch2 = Tolower(ch2);
+ if ( ch1!=ch2 || ch1=='\0' )
+return(ch1-ch2);
+ }
+}
+
+long uc_strnmatch(const unichar_t *str1, const char *str2, int len) {
+ long ch1, ch2;
+ for (;--len>=0;) {
+ ch1 = *str1++; ch2 = *(unsigned char *) str2++ ;
+ ch1 = Tolower(ch1);
+ ch2 = Tolower(ch2);
+ if ( ch1!=ch2 || ch1=='\0' || len<=0 )
+return(ch1-ch2);
+ }
+return( 0 );
+}
+
+long u_strnmatch(const unichar_t *str1, const unichar_t *str2, int len) {
+ long ch1, ch2;
+ for (;--len>=0;) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ ch1 = Tolower(ch1);
+ ch2 = Tolower(ch2);
+ if ( ch1!=ch2 || ch1=='\0' || len<=0 )
+return(ch1-ch2);
+ }
+return( 0 );
+}
+
+long u_strcmp(const unichar_t *str1,const unichar_t *str2) {
+ long ch1, ch2;
+ for (;;) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ if ( ch1!=ch2 || ch1=='\0' )
+return(ch1-ch2);
+ }
+}
+
+long u_strncmp(const unichar_t *str1,const unichar_t *str2,int n) {
+ long ch1, ch2;
+ while ( --n>=0 ) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ if ( ch1!=ch2 || ch1=='\0' )
+return(ch1-ch2);
+ }
+return( 0 );
+}
+
+long u_strmatch(const unichar_t *str1, const unichar_t *str2) {
+ long ch1, ch2;
+ for (;;) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ ch1 = Tolower(ch1);
+ ch2 = Tolower(ch2);
+ if ( ch1!=ch2 || ch1=='\0' )
+return(ch1-ch2);
+ }
+}
+
+void cu_strcpy(char *to, const unichar_t *from) {
+ register unichar_t ch;
+ while ( (ch = *from++) != '\0' )
+ *(to++) = ch;
+ *to = 0;
+}
+
+void uc_strcpy(unichar_t *to, const char *from) {
+ register unichar_t ch;
+ while ( (ch = *(unsigned char *) from++) != '\0' )
+ *(to++) = ch;
+ *to = 0;
+}
+
+void u_strcpy(unichar_t *to, const unichar_t *from) {
+ register unichar_t ch;
+ while ( (ch = *from++) != '\0' )
+ *(to++) = ch;
+ *to = 0;
+}
+
+void u_strncpy(register unichar_t *to, const unichar_t *from, int len) {
+ register unichar_t ch;
+ while ( (ch = *from++) != '\0' && --len>=0 )
+ *(to++) = ch;
+ *to = 0;
+}
+
+void cu_strncpy(register char *to, const unichar_t *from, int len) {
+ register unichar_t ch;
+ while ( (ch = *from++) != '\0' && --len>=0 )
+ *(to++) = ch;
+ *to = 0;
+}
+
+void uc_strncpy(register unichar_t *to, const char *from, int len) {
+ register unichar_t ch;
+ while ( (ch = *(unsigned char *) from++) != '\0' && --len>=0 )
+ *(to++) = ch;
+ *to = 0;
+}
+
+void uc_strcat(unichar_t *to, const char *from) {
+ uc_strcpy(to+u_strlen(to),from);
+}
+
+void uc_strncat(unichar_t *to, const char *from,int len) {
+ uc_strncpy(to+u_strlen(to),from,len);
+}
+
+void cu_strcat(char *to, const unichar_t *from) {
+ cu_strcpy(to+strlen(to),from);
+}
+
+void cu_strncat(char *to, const unichar_t *from, int len) {
+ cu_strncpy(to+strlen(to),from,len);
+}
+
+void u_strcat(unichar_t *to, const unichar_t *from) {
+ u_strcpy(to+u_strlen(to),from);
+}
+
+void u_strncat(unichar_t *to, const unichar_t *from, int len) {
+ u_strncpy(to+u_strlen(to),from,len);
+}
+
+int u_strlen(register const unichar_t *str) {
+ register int len = 0;
+
+ while ( *str++!='\0' )
+ ++len;
+return( len );
+}
+
+unichar_t *u_strchr(const unichar_t *str ,unichar_t ch) {
+ register unichar_t test;
+
+ while ( (test=*(str++))!='\0' )
+ if ( test==ch )
+return( (unichar_t *) str-1 );
+
+return( NULL );
+}
+
+unichar_t *u_strrchr(const unichar_t *str ,unichar_t ch) {
+ register unichar_t test, *last = NULL;
+
+ while ( (test=*(str++))!='\0' )
+ if ( test==ch )
+ last = (unichar_t *) str-1;
+
+return( last );
+}
+
+unichar_t *uc_strstr(const unichar_t *longer, const char *substr) {
+ long ch1, ch2;
+ const unichar_t *lpt, *str1; const char *str2;
+
+ for ( lpt=longer; *lpt!='\0'; ++lpt ) {
+ str1 = lpt; str2 = substr;
+ for (;;) {
+ ch1 = *str1++; ch2 = *(unsigned char *) str2++ ;
+ if ( ch2=='\0' )
+return((unichar_t *) lpt);
+ if ( ch1!=ch2 )
+ break;
+ }
+ }
+return( NULL );
+}
+
+unichar_t *u_strstr(const unichar_t *longer, const unichar_t *substr) {
+ long ch1, ch2;
+ const unichar_t *lpt, *str1, *str2;
+
+ for ( lpt=longer; *lpt!='\0'; ++lpt ) {
+ str1 = lpt; str2 = substr;
+ for (;;) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ if ( ch2=='\0' )
+return((unichar_t *) lpt);
+ if ( ch1!=ch2 )
+ break;
+ }
+ }
+return( NULL );
+}
+
+unichar_t *uc_strstrmatch(const unichar_t *longer, const char *substr) {
+ long ch1, ch2;
+ const unichar_t *lpt, *str1; const unsigned char *str2;
+
+ for ( lpt=longer; *lpt!='\0'; ++lpt ) {
+ str1 = lpt; str2 = (unsigned char *) substr;
+ for (;;) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ ch1 = Tolower(ch1);
+ ch2 = Tolower(ch2);
+ if ( ch2=='\0' )
+return((unichar_t *) lpt);
+ if ( ch1!=ch2 )
+ break;
+ }
+ }
+return( NULL );
+}
+
+unichar_t *u_strstrmatch(const unichar_t *longer, const unichar_t *substr) {
+ long ch1, ch2;
+ const unichar_t *lpt, *str1, *str2;
+
+ for ( lpt=longer; *lpt!='\0'; ++lpt ) {
+ str1 = lpt; str2 = substr;
+ for (;;) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ ch1 = Tolower(ch1);
+ ch2 = Tolower(ch2);
+ if ( ch2=='\0' )
+return((unichar_t *) lpt);
+ if ( ch1!=ch2 )
+ break;
+ }
+ }
+return( NULL );
+}
+
+unichar_t *u_copyn(const unichar_t *pt, long n) {
+ unichar_t *res;
+#ifdef MEMORY_MASK
+ if ( n*sizeof(unichar_t)>=MEMORY_MASK )
+ n = MEMORY_MASK/sizeof(unichar_t)-1;
+#endif
+ res = galloc((n+1)*sizeof(unichar_t));
+ memcpy(res,pt,n*sizeof(unichar_t));
+ res[n]='\0';
+return(res);
+}
+
+unichar_t *u_copy(const unichar_t *pt) {
+ if(pt)
+return u_copyn(pt,u_strlen(pt));
+
+return((unichar_t *)0);
+}
+
+unichar_t *u_concat(const unichar_t *s1, const unichar_t *s2) {
+ long len1, len2;
+ unichar_t *pt;
+
+ if ( s1==NULL )
+return( u_copy( s2 ));
+ else if ( s2==NULL )
+return( u_copy( s1 ));
+ len1 = u_strlen(s1); len2 = u_strlen(s2);
+ pt = galloc((len1+len2+1)*sizeof(unichar_t));
+ u_strcpy(pt,s1);
+ u_strcpy(pt+len1,s2);
+return( pt );
+}
+
+unichar_t *uc_copyn(const char *pt,int len) {
+ unichar_t *res, *rpt;
+
+ if(!pt)
+return((unichar_t *)0);
+
+#ifdef MEMORY_MASK
+ if ( (len+1)*sizeof(unichar_t)>=MEMORY_MASK )
+ len = MEMORY_MASK/sizeof(unichar_t)-1;
+#endif
+ res = galloc((len+1)*sizeof(unichar_t));
+ for ( rpt=res; --len>=0 ; *rpt++ = *(unsigned char *) pt++ );
+ *rpt = '\0';
+return(res);
+}
+
+unichar_t *uc_copy(const char *pt) {
+ unichar_t *res, *rpt;
+ int n;
+
+ if(!pt)
+return((unichar_t *)0);
+
+ n = strlen(pt);
+#ifdef MEMORY_MASK
+ if ( (n+1)*sizeof(unichar_t)>=MEMORY_MASK )
+ n = MEMORY_MASK/sizeof(unichar_t)-1;
+#endif
+ res = galloc((n+1)*sizeof(unichar_t));
+ for ( rpt=res; --n>=0 ; *rpt++ = *(unsigned char *) pt++ );
+ *rpt = '\0';
+return(res);
+}
+
+char *cu_copyn(const unichar_t *pt,int len) {
+ char *res, *rpt;
+
+ if(!pt)
+return(NULL);
+
+#ifdef MEMORY_MASK
+ if ( (len+1)>=MEMORY_MASK )
+ len = MEMORY_MASK-1;
+#endif
+ res = galloc(len+1);
+ for ( rpt=res; --len>=0 ; *rpt++ = *pt++ );
+ *rpt = '\0';
+return(res);
+}
+
+char *cu_copy(const unichar_t *pt) {
+ char *res, *rpt;
+ int n;
+
+ if(!pt)
+return((char *)0);
+
+ n = u_strlen(pt);
+#ifdef MEMORY_MASK
+ if ( (n+1)>=MEMORY_MASK )
+ n = MEMORY_MASK/sizeof(unichar_t)-1;
+#endif
+ res = galloc(n+1);
+ for ( rpt=res; --n>=0 ; *rpt++ = *pt++ );
+ *rpt = '\0';
+return(res);
+}
+
+double u_strtod(const unichar_t *str, unichar_t **ptr) {
+ char buf[60], *pt, *ret;
+ const unichar_t *upt;
+ double val;
+ extern double strtod(); /* Please don't delete this, not all of us have good ansi headers */
+
+ for ( upt=str, pt=buf; *upt<128 && *upt!='\0'; )
+ *pt++ = *upt++;
+ *pt = '\0';
+ val = strtod(buf,&ret);
+ if ( ptr!=NULL ) {
+ if ( pt==ret )
+ *ptr = (unichar_t *) upt;
+ else
+ *ptr = (unichar_t *) (str + (ret-buf));
+ }
+return( val );
+}
+
+long u_strtol(const unichar_t *str, unichar_t **ptr, int base) {
+ char buf[60], *pt, *ret;
+ const unichar_t *upt;
+ long val;
+ extern long strtol(); /* Please don't delete this, not all of us have good ansi headers */
+
+ for ( upt=str, pt=buf; *upt<128 && *upt!='\0' && pt<buf+sizeof(buf)-1; )
+ *pt++ = *upt++;
+ *pt = '\0';
+ val = strtol(buf,&ret,base);
+ if ( ptr!=NULL ) {
+ if ( pt==ret )
+ *ptr = (unichar_t *) upt;
+ else
+ *ptr = (unichar_t *) (str + (ret-buf));
+ }
+return( val );
+}
+
+unsigned long u_strtoul(const unichar_t *str, unichar_t **ptr, int base) {
+ char buf[60], *pt, *ret;
+ const unichar_t *upt;
+ unsigned long val;
+
+ for ( upt=str, pt=buf; *upt<128 && *upt!='\0' && pt<buf+sizeof(buf)-1; )
+ *pt++ = *upt++;
+ *pt = '\0';
+ val = strtoul(buf,&ret,base);
+ if ( ptr!=NULL ) {
+ if ( pt==ret )
+ *ptr = (unichar_t *) upt;
+ else
+ *ptr = (unichar_t *) (str + (ret-buf));
+ }
+return( val );
+}
+
+unichar_t *cu_strstartmatch(const char *key,const unichar_t *str) {
+ if ( key && str ) {
+ while( *key ) {
+ if(Tolower(*key) != Tolower(*str))
+return 0;
+ key++;
+ str++;
+ }
+ }
+return (unichar_t *)str;
+}
+
+unichar_t *u_strstartmatch(const unichar_t *initial, const unichar_t *full) {
+ int ch1, ch2;
+ for (;;) {
+ ch1 = *initial++; ch2 = *full++ ;
+ if ( ch1=='\0' )
+return( (unichar_t *) full );
+ ch1 = Tolower(ch1);
+ ch2 = Tolower(ch2);
+ if ( ch1!=ch2 || ch1=='\0' )
+return(NULL);
+ }
+}
+
+char *u_to_c(const unichar_t *ubuf) {
+ static char buf[400];
+ cu_strncpy(buf,ubuf,sizeof(buf));
+return( buf );
+}
+
+unichar_t *c_to_u(const char *buf) {
+ static unichar_t ubuf[400];
+ uc_strncpy(ubuf,buf,sizeof(ubuf));
+return( ubuf );
+}
+
+unichar_t *utf82u_strncpy(unichar_t *ubuf,const char *utf8buf,int len) {
+ unichar_t *upt=ubuf, *uend=ubuf+len-1;
+ const uint8 *pt = (const uint8 *) utf8buf, *end = pt+strlen(utf8buf);
+ int w, w2;
+
+ while ( pt<end && *pt!='\0' && upt<uend ) {
+ if ( *pt<=127 )
+ *upt = *pt++;
+ else if ( *pt<=0xdf ) {
+ *upt = ((*pt&0x1f)<<6) | (pt[1]&0x3f);
+ pt += 2;
+ } else if ( *pt<=0xef ) {
+ *upt = ((*pt&0xf)<<12) | ((pt[1]&0x3f)<<6) | (pt[2]&0x3f);
+ pt += 3;
+#ifdef UNICHAR_16
+ } else if ( upt+1<uend ) {
+ /* Um... I don't support surrogates */
+ w = ( ((*pt&0x7)<<2) | ((pt[1]&0x30)>>4) )-1;
+ *upt++ = 0xd800 | (w<<6) | ((pt[1]&0xf)<<2) | ((pt[2]&0x30)>>4);
+ *upt = 0xdc00 | ((pt[2]&0xf)<<6) | (pt[3]&0x3f);
+ pt += 4;
+ } else {
+ /* no space for surrogate */
+ pt += 4;
+#else
+ } else {
+ w = ( ((*pt&0x7)<<2) | ((pt[1]&0x30)>>4) )-1;
+ w = (w<<6) | ((pt[1]&0xf)<<2) | ((pt[2]&0x30)>>4);
+ w2 = ((pt[2]&0xf)<<6) | (pt[3]&0x3f);
+ *upt = w*0x400 + w2 + 0x10000;
+#endif
+ }
+ ++upt;
+ }
+ *upt = '\0';
+return( ubuf );
+}
+
+unichar_t *utf82u_strcpy(unichar_t *ubuf,const char *utf8buf) {
+return( utf82u_strncpy(ubuf,utf8buf,strlen(utf8buf)+1));
+}
+
+# ifdef UNICHAR_16
+uint32 *utf82u32_strncpy(uint32 *ubuf,const char *utf8buf,int len) {
+ uint32 *upt=ubuf, *uend=ubuf+len-1;
+ const uint8 *pt = (const uint8 *) utf8buf;
+ int w, w2;
+
+ while ( *pt!='\0' && upt<uend ) {
+ if ( *pt<=127 )
+ *upt = *pt++;
+ else if ( *pt<=0xdf ) {
+ *upt = ((*pt&0x1f)<<6) | (pt[1]&0x3f);
+ pt += 2;
+ } else if ( *pt<=0xef ) {
+ *upt = ((*pt&0xf)<<12) | ((pt[1]&0x3f)<<6) | (pt[2]&0x3f);
+ pt += 3;
+ } else {
+ w = ( ((*pt&0x7)<<2) | ((pt[1]&0x30)>>4) )-1;
+ w = (w<<6) | ((pt[1]&0xf)<<2) | ((pt[2]&0x30)>>4);
+ w2 = ((pt[2]&0xf)<<6) | (pt[3]&0x3f);
+ *upt = w*0x400 + w2 + 0x10000;
+ pt += 4;
+ }
+ ++upt;
+ }
+ *upt = '\0';
+return( ubuf );
+}
+
+char *u322utf8_strncpy(char *utf8buf, const uint32 *ubuf,int len) {
+ uint8 *pt=(uint8 *) utf8buf, *end=(uint8 *) utf8buf+len-1;
+ const uint32 *upt = ubuf;
+
+ while ( *upt!='\0' && pt<end ) {
+ if ( *upt<=127 )
+ *pt++ = *upt;
+ else if ( *upt<=0x7ff ) {
+ if ( pt+1>=end )
+ break;
+ *pt++ = 0xc0 | (*upt>>6);
+ *pt++ = 0x80 | (*upt&0x3f);
+ } else if ( *upt<=0xffff ) {
+ if ( pt+2>=end )
+ break;
+ *pt++ = 0xe0 | (*upt>>12);
+ *pt++ = 0x80 | ((*upt>>6)&0x3f);
+ *pt++ = 0x80 | (*upt&0x3f);
+ } else {
+ uint32 val = *upt-0x10000;
+ int u = ((val&0xf0000)>>16)+1, z=(val&0x0f000)>>12, y=(val&0x00fc0)>>6, x=val&0x0003f;
+ if ( pt+3>=end )
+ break;
+ *pt++ = 0xf0 | (u>>2);
+ *pt++ = 0x80 | ((u&3)<<4) | z;
+ *pt++ = 0x80 | y;
+ *pt++ = 0x80 | x;
+ }
+ ++upt;
+ }
+ *pt = '\0';
+return( utf8buf );
+}
+
+char *u322utf8_copy(const uint32 *ubuf) {
+ int i, len;
+ char *buf;
+
+ for ( i=len=0; ubuf[i]!=0; ++i )
+ if ( ubuf[i]<0x80 )
+ ++len;
+ else if ( ubuf[i]<0x800 )
+ len += 2;
+ else if ( ubuf[i]<0x10000 )
+ len += 3;
+ else
+ len += 4;
+ buf = galloc(len+1);
+return( u322utf8_strncpy(buf,ubuf,len+1));
+}
+#endif
+
+unichar_t *utf82u_copyn(const char *utf8buf,int len) {
+ unichar_t *ubuf = galloc((len+1)*sizeof(unichar_t));
+return( utf82u_strncpy(ubuf,utf8buf,len+1));
+}
+
+unichar_t *utf82u_copy(const char *utf8buf) {
+ int len;
+ unichar_t *ubuf;
+
+ if ( utf8buf==NULL )
+return( NULL );
+
+ len = strlen(utf8buf);
+ ubuf = galloc((len+1)*sizeof(unichar_t));
+return( utf82u_strncpy(ubuf,utf8buf,len+1));
+}
+
+void utf82u_strcat(unichar_t *to,const char *from) {
+ utf82u_strcpy(to+u_strlen(to),from);
+}
+
+#ifdef UNICHAR_16
+uint32 *utf82u32_copy(const char *utf8buf) {
+ int len;
+ uint32 *ubuf;
+
+ if ( utf8buf==NULL )
+return( NULL );
+
+ len = strlen(utf8buf);
+ ubuf = galloc((len+1)*sizeof(uint32));
+return( utf82u32_strncpy(ubuf,utf8buf,len+1));
+}
+#endif
+
+char *u2utf8_strcpy(char *utf8buf,const unichar_t *ubuf) {
+ char *pt = utf8buf;
+
+ while ( *ubuf ) {
+ if ( *ubuf<0x80 )
+ *pt++ = *ubuf;
+ else if ( *ubuf<0x800 ) {
+ *pt++ = 0xc0 | (*ubuf>>6);
+ *pt++ = 0x80 | (*ubuf&0x3f);
+#ifdef UNICHAR_16
+ } else if ( *ubuf>=0xd800 && *ubuf<0xdc00 && ubuf[1]>=0xdc00 && ubuf[1]<0xe000 ) {
+ int u = ((*ubuf>>6)&0xf)+1, y = ((*ubuf&3)<<4) | ((ubuf[1]>>6)&0xf);
+ *pt++ = 0xf0 | (u>>2);
+ *pt++ = 0x80 | ((u&3)<<4) | ((*ubuf>>2)&0xf);
+ *pt++ = 0x80 | y;
+ *pt++ = 0x80 | (ubuf[1]&0x3f);
+ } else {
+ *pt++ = 0xe0 | (*ubuf>>12);
+ *pt++ = 0x80 | ((*ubuf>>6)&0x3f);
+ *pt++ = 0x80 | (*ubuf&0x3f);
+#else
+ } else if ( *ubuf < 0x10000 ) {
+ *pt++ = 0xe0 | (*ubuf>>12);
+ *pt++ = 0x80 | ((*ubuf>>6)&0x3f);
+ *pt++ = 0x80 | (*ubuf&0x3f);
+ } else {
+ uint32 val = *ubuf-0x10000;
+ int u = ((val&0xf0000)>>16)+1, z=(val&0x0f000)>>12, y=(val&0x00fc0)>>6, x=val&0x0003f;
+ *pt++ = 0xf0 | (u>>2);
+ *pt++ = 0x80 | ((u&3)<<4) | z;
+ *pt++ = 0x80 | y;
+ *pt++ = 0x80 | x;
+#endif
+ }
+ ++ubuf;
+ }
+ *pt = '\0';
+return( utf8buf );
+}
+
+char *latin1_2_utf8_strcpy(char *utf8buf,const char *lbuf) {
+ char *pt = utf8buf;
+ const unsigned char *lpt = (const unsigned char *) lbuf;
+
+ while ( *lpt ) {
+ if ( *lpt<0x80 )
+ *pt++ = *lpt;
+ else {
+ *pt++ = 0xc0 | (*lpt>>6);
+ *pt++ = 0x80 | (*lpt&0x3f);
+ }
+ ++lpt;
+ }
+ *pt = '\0';
+return( utf8buf );
+}
+
+char *latin1_2_utf8_copy(const char *lbuf) {
+ int len;
+ char *utf8buf;
+
+ if ( lbuf==NULL )
+return( NULL );
+
+ len = strlen(lbuf);
+ utf8buf = galloc(2*len+1);
+return( latin1_2_utf8_strcpy(utf8buf,lbuf));
+}
+
+char *utf8_2_latin1_copy(const char *utf8buf) {
+ int len;
+ int ch;
+ char *lbuf, *pt; const char *upt;
+
+ if ( utf8buf==NULL )
+return( NULL );
+
+ len = strlen(utf8buf);
+ pt = lbuf = galloc(len+1);
+ for ( upt=utf8buf; (ch=utf8_ildb(&upt))!='\0'; )
+ if ( ch>=0xff )
+ *pt++ = '?';
+ else
+ *pt++ = ch;
+ *pt = '\0';
+return( lbuf );
+}
+
+char *u2utf8_copy(const unichar_t *ubuf) {
+ int len;
+ char *utf8buf;
+
+ if ( ubuf==NULL )
+return( NULL );
+
+ len = u_strlen(ubuf);
+ utf8buf = galloc((len+1)*3);
+return( u2utf8_strcpy(utf8buf,ubuf));
+}
+
+char *u2utf8_copyn(const unichar_t *ubuf,int len) {
+ int i;
+ char *utf8buf, *pt;
+
+ if ( ubuf==NULL )
+return( NULL );
+
+ utf8buf = pt = galloc((len+1)*3);
+ for ( i=0; i<len && *ubuf!='\0'; ++i )
+ pt = utf8_idpb(pt, *ubuf++);
+ *pt = '\0';
+return( utf8buf );
+}
+
+int32 utf8_ildb(const char **_text) {
+ int32 val= -1;
+ int ch;
+ const uint8 *text = (const uint8 *) *_text;
+ /* Increment and load character */
+
+ if ( (ch = *text++)<0x80 ) {
+ val = ch;
+ } else if ( ch<=0xbf ) {
+ /* error */
+ } else if ( ch<=0xdf ) {
+ if ( *text>=0x80 && *text<0xc0 )
+ val = ((ch&0x1f)<<6) | (*text++&0x3f);
+ } else if ( ch<=0xef ) {
+ if ( *text>=0x80 && *text<0xc0 && text[1]>=0x80 && text[1]<0xc0 ) {
+ val = ((ch&0xf)<<12) | ((text[0]&0x3f)<<6) | (text[1]&0x3f);
+ text += 2;
+ }
+ } else {
+ int w = ( ((ch&0x7)<<2) | ((text[0]&0x30)>>4) )-1, w2;
+ w = (w<<6) | ((text[0]&0xf)<<2) | ((text[1]&0x30)>>4);
+ w2 = ((text[1]&0xf)<<6) | (text[2]&0x3f);
+ val = w*0x400 + w2 + 0x10000;
+ if ( *text<0x80 || text[1]<0x80 || text[2]<0x80 ||
+ *text>=0xc0 || text[1]>=0xc0 || text[2]>=0xc0 )
+ val = -1;
+ else
+ text += 3;
+ }
+ *_text = (const char *) text;
+return( val );
+}
+
+char *utf8_idpb(char *utf8_text,uint32 ch) {
+ /* Increment and deposit character */
+ if ( ch<0 || ch>=17*65536 )
+return( utf8_text );
+
+ if ( ch<=127 )
+ *utf8_text++ = ch;
+ else if ( ch<=0x7ff ) {
+ *utf8_text++ = 0xc0 | (ch>>6);
+ *utf8_text++ = 0x80 | (ch&0x3f);
+ } else if ( ch<=0xffff ) {
+ *utf8_text++ = 0xe0 | (ch>>12);
+ *utf8_text++ = 0x80 | ((ch>>6)&0x3f);
+ *utf8_text++ = 0x80 | (ch&0x3f);
+ } else {
+ uint32 val = ch-0x10000;
+ int u = ((val&0xf0000)>>16)+1, z=(val&0x0f000)>>12, y=(val&0x00fc0)>>6, x=val&0x0003f;
+ *utf8_text++ = 0xf0 | (u>>2);
+ *utf8_text++ = 0x80 | ((u&3)<<4) | z;
+ *utf8_text++ = 0x80 | y;
+ *utf8_text++ = 0x80 | x;
+ }
+return( utf8_text );
+}
+
+
+char *utf8_ib(char *utf8_text) {
+ int ch;
+
+ /* Increment character */
+ if ( (ch = *utf8_text)=='\0' )
+return( utf8_text );
+ else if ( ch<=127 )
+return( utf8_text+1 );
+ else if ( ch<0xe0 )
+return( utf8_text+2 );
+ else if ( ch<0xf0 )
+return( utf8_text+3 );
+ else
+return( utf8_text+4 );
+}
+
+int utf8_valid(const char *str) {
+ /* Is this a valid utf8 string? */
+ int ch;
+
+ while ( (ch=utf8_ildb(&str))!='\0' )
+ if ( ch==-1 )
+return( false );
+
+return( true );
+}
+
+char *utf8_db(char *utf8_text) {
+ /* Decrement utf8 pointer */
+ unsigned char *pt = (unsigned char *) utf8_text;
+
+ --pt;
+ if ( *pt>=0xc0 )
+ /* This should never happen. The pointer was looking at an intermediate */
+ /* character. However, if it does happen then we are now properly */
+ /* positioned at the start of a new char */;
+ else if ( *pt>=0x80 ) {
+ --pt;
+ if ( *pt>=0xc0 )
+ /* Done */;
+ else if ( *pt>=0x80 ) {
+ --pt;
+ if ( *pt>=0xc0 )
+ /* Done */;
+ else if ( *pt>=0x80 )
+ --pt;
+ }
+ }
+return( (char *) pt );
+}
+
+int utf8_strlen(const char *utf8_str) {
+ /* how many characters in the string NOT bytes */
+ int len = 0;
+
+ while ( utf8_ildb(&utf8_str)!=0 )
+ ++len;
+return( len );
+}
+
+int utf82u_strlen(const char *utf8_str) {
+ /* how many shorts needed to represent it in UCS2 */
+ int ch;
+ int len = 0;
+
+ while ( (ch = utf8_ildb(&utf8_str))!=0 )
+ if ( ch>0x10000 )
+ len += 2;
+ else
+ ++len;
+return( len );
+}
diff --git a/Build/source/libs/luafontforge/fontforge/VERSION b/Build/source/libs/luafontforge/fontforge/VERSION
new file mode 100644
index 00000000000..86747f5830b
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/VERSION
@@ -0,0 +1 @@
+20070607
diff --git a/Build/source/libs/luafontforge/fontforge/descrip.mms b/Build/source/libs/luafontforge/fontforge/descrip.mms
new file mode 100644
index 00000000000..3629c307bf6
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/descrip.mms
@@ -0,0 +1,9 @@
+all :
+ set def [.unicode]
+ mms
+ set def [-.gdraw]
+ mms
+ set def [-.fontforge]
+ mms
+ set def [-.plugins]
+ mms
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/Makefile b/Build/source/libs/luafontforge/fontforge/fontforge/Makefile
new file mode 100644
index 00000000000..945cd1f5471
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/Makefile
@@ -0,0 +1,36 @@
+
+top_srcdir = ../../../../src/libs/luafontforge/fontforge
+srcdir = $(top_srcdir)/fontforge
+
+CC = gcc
+AR = ar cru
+RANLIB = ranlib
+
+OBJECTS =autohint.o charview.o fontinfo.o \
+ fontview.o fvfonts.o parsepfa.o parsettf.o prefs.o psread.o namelist.o \
+ splinefill.o splineoverlap.o splinestroke.o splineutil.o splineutil2.o stamp.o \
+ start.o encoding.o macbinary.o splineorder2.o kernclass.o ttfspecial.o \
+ parsettfatt.o contextchain.o macenc.o splinerefigure.o parsettfvar.o pua.o \
+ stemdb.o lookups.o featurefile.o \
+ tottf.o tottfgpos.o tottfvar.o splinesave.o
+
+_CFLAGS = -I$(top_srcdir)/inc -I$(srcdir) -I. -Wall $(XCFLAGS) \
+ -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 \
+ -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 \
+ -DHAVE_INTTYPES_H=1 -DHAVE_UNISTD_H=1 -D_NO_PYTHON=1 -DHAVE_LANGINFO_H=1 \
+ -DX_DISPLAY_MISSING=1 -DHAVE_LONG_DOUBLE=1 -D_HAS_LONGLONG=1 \
+ -DNODYNAMIC=1 -D_NO_FREETYPE=1 -D_NO_LIBUNINAMESLIST=1 \
+ -DFONTFORGE_CONFIG_NO_WINDOWING_UI=1 -DLUA_FF_LIB=1 -UHAVE_LIBINTL_H
+
+CFLAGS = -g -O2 $(_CFLAGS)
+
+all: $(OBJECTS)
+
+# The slight error introduced occasionally by optimization turns out to have
+# disasterous effects. This file may not be compiled with the optimizer.
+# On the other hand we do need CPPFLAGS to get the right includes...
+splinerefigure.o: $(srcdir)/splinerefigure.c $(srcdir)/splinefont.h
+ $(CC) -g -c -o splinerefigure.o $(_CFLAGS) $(srcdir)/splinerefigure.c
+
+%.o: $(srcdir)/%.c $(srcdir)/splinefont.h $(srcdir)/views.h $(srcdir)/stemdb.h $(srcdir)/ttf.h $(srcdir)/unicoderange.h $(srcdir)/psfont.h $(srcdir)/groups.h $(srcdir)/edgelist.h $(srcdir)/edgelist2.h
+ $(CC) $(CFLAGS) -c $< -o $@
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/autohint.c b/Build/source/libs/luafontforge/fontforge/fontforge/autohint.c
new file mode 100644
index 00000000000..a954c42481f
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/autohint.c
@@ -0,0 +1,3528 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include <stdio.h>
+#include <math.h>
+#include "splinefont.h"
+#include "views.h"
+#include "stemdb.h"
+#include <utype.h>
+#include <chardata.h>
+#include "edgelist.h"
+
+#ifdef LUA_FF_LIB
+/* no need for iconv here, since PS is 8-bit legacy */
+#define Isspace(a) ((a)==' '|| ((a) >= '\t' && (a) <= '\r'))
+#define Isdigit(a) ((a)>='0' && (a)<='9')
+#define Isalpha(a) (((a)>='a' && (a)<='z') || ((a)>='A' && (a)<='Z'))
+#define Isupper(a) ((a)>='A' && (a)<='Z')
+#define Isalnum(a) (Isalpha(a)||Isdigit(a))
+#define Ishexdigit(a) (((a)>='0' && (a)<='9')||((a)>='a' && (a)<='f')||((a)>='A' && (a)<='F'))
+#else
+#define Isspace isspace
+#define Isdigit isdigit
+#define Isalpha isalpha
+#define Isupper isupper
+#define Isalnum isalnum
+#define Ishexdigit ishexdigit
+#endif
+
+/* to create a type 1 font we must come up with the following entries for the
+ private dictionary:
+ BlueValues -- an array of 2n entries where Blue[2i]<Blue[2i+1] max n=7, Blue[i]>0
+ OtherBlues -- (optional) OtherBlue[i]<0
+ (blue zones should be at least 3 units appart)
+ StdHW -- (o) array with one entry, standard hstem height
+ StdVW -- (o) ditto vstem width
+ StemSnapH -- (o) up to 12 numbers containing various hstem heights (includes StdHW), small widths first
+ StemSnapV -- (o) ditto, vstem
+This file has routines to figure out at least some of these
+
+Also other routines to guess at good per-character hints
+*/
+
+#ifndef LUA_FF_LIB
+static void AddBlue(real val, real array[5], int force) {
+ val = rint(val);
+ if ( !force && (val<array[0]-array[1] || val >array[0]+array[1] ))
+return; /* Outside of one sd */
+ if ( array[3]==0 && array[4]==0 )
+ array[3] = array[4] = val;
+ else if ( val>array[4] )
+ array[4] = val;
+ else if ( val<array[3] )
+ array[3] = val;
+}
+
+static void MergeZones(real zone1[5], real zone2[5]) {
+ if ( zone1[2]!=0 && zone2[2]!=0 &&
+ ((zone1[4]+3>zone2[3] && zone1[3]<=zone2[3]) ||
+ (zone2[4]+3>zone1[3] && zone2[3]<=zone1[3]) )) {
+ if (( zone2[0]<zone1[0]-zone1[1] || zone2[0] >zone1[0]+zone1[1] ) &&
+ ( zone1[0]<zone2[0]-zone2[1] || zone1[0] >zone2[0]+zone2[1] ))
+ /* the means of the zones are too far appart, don't merge em */;
+ else {
+ if ( zone1[0]<zone2[0] ) zone2[0] = zone1[0];
+ if ( zone1[1]>zone2[1] ) zone2[1] = zone1[1];
+ }
+ zone1[2] = 0;
+ }
+}
+
+/* I can deal with latin, greek and cyrillic because the they all come from */
+/* the same set of letter shapes and have all evolved together and have */
+/* various common features (ascenders, descenders, lower case, etc.). Other */
+/* scripts don't fit */
+
+void FindBlues( SplineFont *sf, real blues[14], real otherblues[10]) {
+ real caph[5], xh[5], ascenth[5], digith[5], descenth[5], base[5];
+ real otherdigits[5];
+ int i, j, k;
+ DBounds b;
+
+ /* Go through once to get some idea of the average value so we can weed */
+ /* out undesireables */
+ caph[0] = caph[1] = caph[2] = xh[0] = xh[1] = xh[2] = 0;
+ ascenth[0] = ascenth[1] = ascenth[2] = digith[0] = digith[1] = digith[2] = 0;
+ descenth[0] = descenth[1] = descenth[2] = base[0] = base[1] = base[2] = 0;
+ otherdigits[0] = otherdigits[1] = otherdigits[2] = 0;
+ for ( i=0; i<sf->glyphcnt; ++i ) {
+ if ( sf->glyphs[i]!=NULL && sf->glyphs[i]->layers[ly_fore].splines!=NULL ) {
+ int enc = sf->glyphs[i]->unicodeenc;
+ const unichar_t *upt;
+ if ( enc<0x10000 && isalnum(enc) &&
+ ((enc>=32 && enc<128 ) || enc == 0xfe || enc==0xf0 || enc==0xdf ||
+ enc==0x131 ||
+ (enc>=0x391 && enc<=0x3f3 ) ||
+ (enc>=0x400 && enc<=0x4e9 ) )) {
+ /* no accented characters (or ligatures) */
+ if ( unicode_alternates[enc>>8]!=NULL &&
+ (upt =unicode_alternates[enc>>8][enc&0xff])!=NULL &&
+ upt[1]!='\0' )
+ continue;
+ SplineCharFindBounds(sf->glyphs[i],&b);
+ if ( b.miny==0 && b.maxy==0 )
+ continue;
+ if ( enc=='g' || enc=='j' || enc=='p' || enc=='q' || enc=='y' ||
+ enc==0xfe ||
+ enc==0x3c1 /* rho */ ||
+ enc==0x3c6 /* phi */ ||
+ enc==0x3c7 /* chi */ ||
+ enc==0x3c8 /* psi */ ||
+ enc==0x440 /* cyr er */ ||
+ enc==0x443 /* cyr u */ ||
+ enc==0x444 /* cyr ef */) {
+ descenth[0] += b.miny;
+ descenth[1] += b.miny*b.miny;
+ ++descenth[2];
+ } else if ( enc=='x' || enc=='r' || enc=='o' || enc=='e' ||
+ enc=='s' || enc=='c' || enc=='h' || enc=='k' ||
+ enc=='l' || enc=='m' || enc=='n' ||
+ enc==0x3b5 /* epsilon */ ||
+ enc==0x3b9 /* iota */ ||
+ enc==0x3ba /* kappa */ ||
+ enc==0x3bf /* omicron */ ||
+ enc==0x3c3 /* sigma */ ||
+ enc==0x3c5 /* upsilon */ ||
+ enc==0x430 /* cyr a */ ||
+ enc==0x432 /* cyr ve */ ||
+ enc==0x433 /* cyr ge */ ||
+ enc==0x435 /* cyr e */ ||
+ enc==0x436 /* cyr zhe */ ||
+ enc==0x438 /* cyr i */ ||
+ enc==0x43a /* cyr ka */ ||
+ enc==0x43d /* cyr en */ ||
+ enc==0x43e /* cyr o */ ||
+ enc==0x441 /* cyr es */ ||
+ enc==0x445 /* cyr ha */ ||
+ enc==0x447 /* cyr che */ ||
+ enc==0x448 /* cyr sha */ ||
+ enc==0x44f /* cyr ya */ ){
+ base[0] += b.miny;
+ base[1] += b.miny*b.miny;
+ ++base[2];
+ }
+ /* careful of lowercase digits, 6 and 8 should be ascenders */
+ if ( enc=='6' || enc=='8' ) {
+ digith[0] += b.maxy;
+ digith[1] += b.maxy*b.maxy;
+ ++digith[2];
+ } else if ( enc<0x10000 && isdigit(enc) ) {
+ otherdigits[0] += b.maxy;
+ otherdigits[1] += b.maxy*b.maxy;
+ ++otherdigits[2];
+ } else if ( enc<0x10000 && isupper(enc) && enc!=0x462 && enc!=0x490 ) {
+ caph[0] += b.maxy;
+ caph[1] += b.maxy*b.maxy;
+ ++caph[2];
+ } else if ( enc=='b' || enc=='d' || enc=='f' || enc=='h' || enc=='k' ||
+ enc == 'l' || enc==0xf0 || enc==0xfe || enc == 0xdf ||
+ enc == 0x3b2 || enc==0x3b6 || enc==0x3b8 || enc==0x3bb ||
+ enc == 0x3be ||
+ enc == 0x431 /* cyr be */ /* || enc == 0x444 - ef may have varible height */) {
+ ascenth[0] += b.maxy;
+ ascenth[1] += b.maxy*b.maxy;
+ ++ascenth[2];
+ } else if ( enc=='c' || enc=='e' || enc=='o' || enc=='s' || enc=='u' ||
+ enc=='u' || enc=='v' || enc=='w' || enc=='x' || enc=='y' ||
+ enc=='z' ||
+ enc==0x3b5 /* epsilon */ ||
+ enc==0x3b9 /* iota */ ||
+ enc==0x3ba /* kappa */ ||
+ enc==0x3bc /* mu */ ||
+ enc==0x3bd /* nu */ ||
+ enc==0x3bf /* omicron */ ||
+ enc==0x3c0 /* pi */ ||
+ enc==0x3c1 /* rho */ ||
+ enc==0x3c5 /* upsilon */ ||
+ enc==0x433 /* cyr ge */ ||
+ enc==0x435 /* cyr e */ ||
+ enc==0x436 /* cyr zhe */ ||
+ enc==0x438 /* cyr i */ ||
+ enc==0x43b /* cyr el */ ||
+ enc==0x43d /* cyr en */ ||
+ enc==0x43e /* cyr o */ ||
+ enc==0x43f /* cyr pe */ ||
+ enc==0x440 /* cyr er */ ||
+ enc==0x441 /* cyr es */ ||
+ enc==0x442 /* cyr te */ ||
+ enc==0x443 /* cyr u */ ||
+ enc==0x445 /* cyr ha */ ||
+ enc==0x446 /* cyr tse */ ||
+ enc==0x447 /* cyr che */ ||
+ enc==0x448 /* cyr sha */ ||
+ enc==0x449 /* cyr shcha */ ||
+ enc==0x44a /* cyr hard sign */ ||
+ enc==0x44b /* cyr yery */ ||
+ enc==0x44c /* cyr soft sign */ ||
+ enc==0x44d /* cyr reversed e */ ||
+ enc==0x44f /* cyr ya */ ) {
+ xh[0] += b.maxy;
+ xh[1] += b.maxy*b.maxy;
+ ++xh[2];
+ }
+ }
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ if ( !gwwv_progress_next())
+#elif defined(FONTFORGE_CONFIG_GTK)
+ if ( !gwwv_progress_next())
+#endif
+ break;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+ if ( otherdigits[2]>0 && digith[2]>0 ) {
+ if ( otherdigits[0]/otherdigits[2] >= .95*digith[0]/digith[2] ) {
+ /* all digits are about the same height, not lowercase */
+ digith[0] += otherdigits[0];
+ digith[1] += otherdigits[1];
+ digith[2] += otherdigits[2];
+ }
+ }
+
+ if ( xh[2]>1 ) {
+ xh[1] = sqrt((xh[1]-xh[0]*xh[0]/xh[2])/(xh[2]-1));
+ xh[0] /= xh[2];
+ }
+ if ( ascenth[2]>1 ) {
+ ascenth[1] = sqrt((ascenth[1]-ascenth[0]*ascenth[0]/ascenth[2])/(ascenth[2]-1));
+ ascenth[0] /= ascenth[2];
+ }
+ if ( caph[2]>1 ) {
+ caph[1] = sqrt((caph[1]-caph[0]*caph[0]/caph[2])/(caph[2]-1));
+ caph[0] /= caph[2];
+ }
+ if ( digith[2]>1 ) {
+ digith[1] = sqrt((digith[1]-digith[0]*digith[0]/digith[2])/(digith[2]-1));
+ digith[0] /= digith[2];
+ }
+ if ( base[2]>1 ) {
+ base[1] = sqrt((base[1]-base[0]*base[0]/base[2])/(base[2]-1));
+ base[0] /= base[2];
+ }
+ if ( descenth[2]>1 ) {
+ descenth[1] = sqrt((descenth[1]-descenth[0]*descenth[0]/descenth[2])/(descenth[2]-1));
+ descenth[0] /= descenth[2];
+ }
+
+ /* we'll accept values between +/- 1sd of the mean */
+ /* array[0] == mean, array[1] == sd, array[2] == cnt, array[3]=min, array[4]==max */
+ if ( base[0]+base[1]<0 ) base[1] = -base[0]; /* Make sure 0 is within the base bluezone */
+ caph[3] = caph[4] = 0;
+ xh[3] = xh[4] = 0;
+ ascenth[3] = ascenth[4] = 0;
+ digith[3] = digith[4] = 0;
+ descenth[3] = descenth[4] = 0;
+ base[3] = base[4] = 0;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ int enc = sf->glyphs[i]->unicodeenc;
+ const unichar_t *upt;
+ if ( enc<0x10000 && isalnum(enc) &&
+ ((enc>=32 && enc<128 ) || enc == 0xfe || enc==0xf0 || enc==0xdf ||
+ (enc>=0x391 && enc<=0x3f3 ) ||
+ (enc>=0x400 && enc<=0x4e9 ) )) {
+ /* no accented characters (or ligatures) */
+ if ( unicode_alternates[enc>>8]!=NULL &&
+ (upt =unicode_alternates[enc>>8][enc&0xff])!=NULL &&
+ upt[1]!='\0' )
+ continue;
+ SplineCharFindBounds(sf->glyphs[i],&b);
+ if ( b.miny==0 && b.maxy==0 )
+ continue;
+ if ( enc=='g' || enc=='j' || enc=='p' || enc=='q' || enc=='y' ||
+ enc==0xfe || enc == 0x3c6 || enc==0x3c8 ||
+ enc==0x440 || enc==0x443 || enc==0x444) {
+ AddBlue(b.miny,descenth,false);
+ } else {
+ /* O and o get forced into the baseline blue value even if they*/
+ /* are beyond 1 sd */
+ AddBlue(b.miny,base,enc=='O' || enc=='o');
+ }
+ if ( enc<0x10000 && isdigit(enc)) {
+ AddBlue(b.maxy,digith,false);
+ } else if ( enc<0x10000 && isupper(enc)) {
+ AddBlue(b.maxy,caph,enc=='O');
+ } else if ( enc=='b' || enc=='d' || enc=='f' || enc=='h' || enc=='k' ||
+ enc == 'l' || enc=='t' || enc==0xf0 || enc==0xfe || enc == 0xdf ||
+ enc == 0x3b2 || enc==0x3b6 || enc==0x3b8 || enc==0x3bb ||
+ enc == 0x3be ||
+ enc == 0x431 ) {
+ AddBlue(b.maxy,ascenth,false);
+ } else if ( enc=='c' || enc=='e' || enc=='o' || enc=='s' || enc=='u' ||
+ enc=='u' || enc=='v' || enc=='w' || enc=='x' || enc=='y' ||
+ enc=='z' ||
+ enc==0x3b5 /* epsilon */ ||
+ enc==0x3b9 /* iota */ ||
+ enc==0x3ba /* kappa */ ||
+ enc==0x3bc /* mu */ ||
+ enc==0x3bd /* nu */ ||
+ enc==0x3bf /* omicron */ ||
+ enc==0x3c0 /* pi */ ||
+ enc==0x3c1 /* rho */ ||
+ enc==0x3c5 /* upsilon */ ||
+ enc==0x433 /* cyr ge */ ||
+ enc==0x435 /* cyr e */ ||
+ enc==0x436 /* cyr zhe */ ||
+ enc==0x438 /* cyr i */ ||
+ enc==0x43b /* cyr el */ ||
+ enc==0x43d /* cyr en */ ||
+ enc==0x43e /* cyr o */ ||
+ enc==0x43f /* cyr pe */ ||
+ enc==0x440 /* cyr er */ ||
+ enc==0x441 /* cyr es */ ||
+ enc==0x442 /* cyr te */ ||
+ enc==0x443 /* cyr u */ ||
+ enc==0x445 /* cyr ha */ ||
+ enc==0x446 /* cyr tse */ ||
+ enc==0x447 /* cyr che */ ||
+ enc==0x448 /* cyr sha */ ||
+ enc==0x449 /* cyr shcha */ ||
+ enc==0x44a /* cyr hard sign */ ||
+ enc==0x44b /* cyr yery */ ||
+ enc==0x44c /* cyr soft sign */ ||
+ enc==0x44d /* cyr reversed e */ ||
+ enc==0x44f /* cyr ya */ ) {
+ AddBlue(b.maxy,xh,enc=='o' || enc=='x');
+ }
+ }
+ }
+
+ /* the descent blue zone merges into the base zone */
+ MergeZones(descenth,base);
+ MergeZones(xh,base);
+ MergeZones(ascenth,caph);
+ MergeZones(digith,caph);
+ MergeZones(xh,caph);
+ MergeZones(ascenth,digith);
+ MergeZones(xh,digith);
+
+ if ( otherblues!=NULL )
+ for ( i=0; i<10; ++i )
+ otherblues[i] = 0;
+ for ( i=0; i<14; ++i )
+ blues[i] = 0;
+
+ if ( otherblues!=NULL && descenth[2]!=0 ) {
+ otherblues[0] = descenth[3];
+ otherblues[1] = descenth[4];
+ }
+ i = 0;
+ if ( base[2]==0 && (xh[2]!=0 || ascenth[2]!=0 || caph[2]!=0 || digith[2]!=0 )) {
+ /* base line blue value must be present if any other value is */
+ /* make one up if we don't have one */
+ blues[0] = -20;
+ blues[1] = 0;
+ i = 2;
+ } else if ( base[2]!=0 ) {
+ blues[0] = base[3];
+ blues[1] = base[4];
+ i = 2;
+ }
+ if ( xh[2]!=0 ) {
+ blues[i++] = xh[3];
+ blues[i++] = xh[4];
+ }
+ if ( caph[2]!=0 ) {
+ blues[i++] = caph[3];
+ blues[i++] = caph[4];
+ }
+ if ( digith[2]!=0 ) {
+ blues[i++] = digith[3];
+ blues[i++] = digith[4];
+ }
+ if ( ascenth[2]!=0 ) {
+ blues[i++] = ascenth[3];
+ blues[i++] = ascenth[4];
+ }
+
+ for ( j=0; j<i; j+=2 ) for ( k=j+2; k<i; k+=2 ) {
+ if ( blues[j]>blues[k] ) {
+ real temp = blues[j];
+ blues[j]=blues[k];
+ blues[k] = temp;
+ temp = blues[j+1];
+ blues[j+1] = blues[k+1];
+ blues[k+1] = temp;
+ }
+ }
+}
+
+static int PVAddBlues(BlueData *bd,int bcnt,char *pt) {
+ char *end;
+ real val1, val2;
+ int i,j;
+
+ if ( pt==NULL )
+return( bcnt );
+
+ while ( Isspace(*pt) || *pt=='[' ) ++pt;
+ while ( *pt!=']' && *pt!='\0' ) {
+ val1 = strtod(pt,&end);
+ if ( *end=='\0' || end==pt )
+ break;
+ for ( pt=end; Isspace(*pt) ; ++pt );
+ val2 = strtod(pt,&end);
+ if ( end==pt )
+ break;
+ if ( bcnt==0 || val1>bd->blues[bcnt-1][0] )
+ i = bcnt;
+ else {
+ for ( i=0; i<bcnt && val1>bd->blues[i][0]; ++i );
+ for ( j=bcnt; j>i; --j ) {
+ bd->blues[j][0] = bd->blues[j-1][0];
+ bd->blues[j][1] = bd->blues[j-1][1];
+ }
+ }
+ bd->blues[i][0] = val1;
+ bd->blues[i][1] = val2;
+ ++bcnt;
+ if ( bcnt>=sizeof(bd->blues)/sizeof(bd->blues[0]))
+ break;
+ for ( pt=end; Isspace(*pt) ; ++pt );
+ }
+return( bcnt );
+}
+
+/* Quick and dirty (and sometimes wrong) approach to figure out the common */
+/* alignment zones in latin (greek, cyrillic) alphabets */
+
+void QuickBlues(SplineFont *_sf, BlueData *bd) {
+ real xheight = -1e10, caph = -1e10, ascent = -1e10, descent = 1e10, max, min;
+ real xheighttop = -1e10, caphtop = -1e10;
+ real numh = -1e10, numhtop = -1e10;
+ real base = -1e10, basebelow = 1e10;
+ SplineFont *sf;
+ SplinePoint *sp;
+ SplineSet *spl;
+ int i,j, bcnt;
+ SplineChar *t;
+ char *pt;
+
+ /* Get the alignment zones we care most about */
+
+ /* be careful of cid fonts */
+ if ( _sf->cidmaster!=NULL )
+ _sf = _sf->cidmaster;
+
+ j=0;
+ do {
+ sf = ( _sf->subfontcnt==0 )? _sf : _sf->subfonts[j];
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ int enc = sf->glyphs[i]->unicodeenc;
+ if ( enc=='I' || enc=='O' || enc=='x' || enc=='o' || enc=='p' || enc=='l' ||
+/* Jean-Christophe Dubacq points out that x-height should be calculated from */
+/* various characters and not just x and o. Italic "x"s often have strange */
+/* shapes */
+ enc=='A' || enc==0x391 || enc==0x410 ||
+ enc=='V' ||
+ enc=='u' || enc=='v' || enc=='w' || enc=='y' || enc=='z' ||
+ enc=='7' || enc=='8' || /* numbers with ascenders */
+ enc==0x399 || enc==0x39f || enc==0x3ba || enc==0x3bf || enc==0x3c1 || enc==0x3be || enc==0x3c7 ||
+ enc==0x41f || enc==0x41e || enc==0x43e || enc==0x43f || enc==0x440 || enc==0x452 || enc==0x445 ) {
+ t = sf->glyphs[i];
+ while ( t->layers[ly_fore].splines==NULL && t->layers[ly_fore].refs!=NULL )
+ t = t->layers[ly_fore].refs->sc;
+ max = -1e10; min = 1e10;
+ if ( t->layers[ly_fore].splines!=NULL ) {
+ for ( spl=t->layers[ly_fore].splines; spl!=NULL; spl=spl->next ) {
+ for ( sp=spl->first; ; ) {
+ if ( sp->me.y > max ) max = sp->me.y;
+ if ( sp->me.y < min ) min = sp->me.y;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ }
+ if ( enc>0x400 ) {
+ /* Only use ascent and descent here if we don't have anything better */
+ if ( enc==0x41f ) { caph = max; base = min; }
+ else if ( enc==0x41e ) { if ( max>caphtop ) caphtop = max; basebelow = min; }
+ else if ( enc==0x410 ) { if ( max>caphtop ) caphtop = max; }
+ else if ( enc==0x43f && xheight<0 ) xheight = max;
+ else if ( enc==0x445 && xheight<0 ) xheight = max;
+ else if ( enc==0x43e ) xheighttop = max;
+ else if ( enc==0x452 && ascent<0 ) ascent = max;
+ else if ( enc==0x440 && descent>0 ) descent = min;
+ } else if ( enc>0x300 ) {
+ if ( enc==0x399 ) { caph = max; base = min; }
+ else if ( enc==0x391 ) { if ( max>caphtop ) caphtop = max; }
+ else if ( enc==0x39f ) { if ( max>caphtop ) caphtop = max; basebelow = min; }
+ else if ( enc==0x3ba && xheight<0 ) xheight = max;
+ else if ( enc==0x3c7 && xheight<0 ) xheight = max;
+ else if ( enc==0x3bf ) xheighttop = max;
+ else if ( enc==0x3be && ascent<0 ) ascent = max;
+ else if ( enc==0x3c1 && descent>0 ) descent = min;
+ } else {
+ if ( enc=='I' ) { caph = max; base = min; }
+ else if ( enc=='O' ) { if ( max>caphtop ) caphtop = max; if ( basebelow<min ) basebelow = min; }
+ else if ( enc=='V' ) { if ( basebelow<min ) basebelow = min; }
+ else if ( enc=='A' ) { if ( max>caphtop ) caphtop = max; }
+ else if ( enc=='7' ) numh = max;
+ else if ( enc=='0' ) numhtop = max;
+ else if ( enc=='x' || enc=='o' || enc=='u' || enc=='v' ||
+ enc =='w' || enc=='y' || enc=='z' ) {
+ if ( xheighttop==-1e10 ) xheighttop = max;
+ if ( xheight==-1e10 ) xheight = max;
+ if ( max > xheighttop ) xheighttop = max;
+ else if ( max<xheight && max>20 ) xheight = max;
+ if ( enc=='y' && descent==1e10 ) descent = min;
+ } else if ( enc=='l' ) ascent = max;
+ else descent = min;
+ }
+ }
+ }
+ }
+ ++j;
+ } while ( j<_sf->subfontcnt );
+
+ if ( basebelow==1e10 ) basebelow=-1e10;
+
+ if ( caphtop<caph ) caphtop = caph; else if ( caph==-1e10 ) caph=caphtop;
+ if ( basebelow>base ) basebelow = base; else if ( base==-1e10 ) base=basebelow;
+ if ( base==-1e10 ) { base=basebelow = 0; }
+ if ( xheighttop<xheight ) xheighttop = xheight; else if ( xheight==-1e10 ) xheight=xheighttop;
+ bd->xheight = xheight; bd->xheighttop = xheighttop;
+ bd->caph = caph; bd->caphtop = caphtop;
+ bd->numh = numh; bd->numhtop = numhtop;
+ bd->ascent = ascent; bd->descent = descent;
+ bd->base = base; bd->basebelow = basebelow;
+
+ bcnt = 0;
+ if ( (pt=PSDictHasEntry(sf->private,"BlueValues"))!=NULL )
+ bcnt = PVAddBlues(bd,bcnt,pt);
+ if ( (pt=PSDictHasEntry(sf->private,"OtherBlues"))!=NULL )
+ bcnt = PVAddBlues(bd,bcnt,pt);
+ if ( bcnt==0 ) {
+ if ( basebelow==-1e10 ) basebelow = base;
+ if ( base==-1e10 ) base = basebelow;
+ if ( xheight==-1e10 ) xheight = xheighttop;
+ if ( xheighttop==-1e10 ) xheighttop = xheight;
+ if ( caph==-1e10 ) caph = caphtop;
+ if ( caphtop==-1e10 ) caphtop = caph;
+ if ( numh==-1e10 ) numh = numhtop;
+ if ( numhtop==-1e10 ) numhtop = numh;
+ if ( numh!=-1e10 && (numhtop>caph-2 && numh<caphtop+2)) {
+ if ( numh<caph ) caph=numh;
+ if ( numhtop>caphtop ) caphtop = numhtop;
+ numh = numhtop = -1e10;
+ }
+ if ( ascent!=-1e10 && (ascent>caph-2 && ascent<caphtop+2)) {
+ if ( ascent<caph ) caph=ascent;
+ if ( ascent>caphtop ) caphtop = ascent;
+ ascent = -1e10;
+ }
+ if ( ascent!=-1e10 && (ascent>numh-2 && ascent<numhtop+2)) {
+ if ( ascent<numh ) numh=ascent;
+ if ( ascent>numhtop ) numhtop = ascent;
+ ascent = -1e10;
+ if ( numhtop>caph-2 && numh<caphtop+2 ) {
+ if ( numh<caph ) caph=numh;
+ if ( numhtop>caphtop ) caphtop = numhtop;
+ numh = numhtop = -1e10;
+ }
+ }
+
+ if ( descent!=1e10 ) {
+ bd->blues[0][0] = bd->blues[0][1] = descent;
+ ++bcnt;
+ }
+ if ( basebelow!=-1e10 ) {
+ bd->blues[bcnt][0] = basebelow;
+ bd->blues[bcnt][1] = base;
+ ++bcnt;
+ }
+ if ( xheight!=-1e10 ) {
+ bd->blues[bcnt][0] = xheight;
+ bd->blues[bcnt][1] = xheighttop;
+ ++bcnt;
+ }
+ if ( numh!=-1e10 ) {
+ bd->blues[bcnt][0] = numh;
+ bd->blues[bcnt][1] = numhtop;
+ ++bcnt;
+ }
+ if ( caph!=-1e10 ) {
+ bd->blues[bcnt][0] = caph;
+ bd->blues[bcnt][1] = caphtop;
+ ++bcnt;
+ }
+ if ( ascent!=-1e10 ) {
+ bd->blues[bcnt][0] = bd->blues[bcnt][1] = ascent;
+ ++bcnt;
+ }
+ }
+ bd->bluecnt = bcnt;
+}
+#endif /* LUA_FF_LIB*/
+
+void ElFreeEI(EIList *el) {
+ EI *e, *next;
+
+ for ( e = el->edges; e!=NULL; e = next ) {
+ next = e->next;
+ free(e);
+ }
+}
+
+static int EIAddEdge(Spline *spline, real tmin, real tmax, EIList *el) {
+ EI *new = gcalloc(1,sizeof(EI));
+ real min, max, temp;
+ Spline1D *s;
+ real dxdtmin, dxdtmax, dydtmin, dydtmax;
+
+ new->spline = spline;
+ new->tmin = tmin;
+ new->tmax = tmax;
+
+ s = &spline->splines[1];
+ if (( dydtmin = (3*s->a*tmin + 2*s->b)*tmin + s->c )<0 ) dydtmin = -dydtmin;
+ if (( dydtmax = (3*s->a*tmax + 2*s->b)*tmax + s->c )<0 ) dydtmax = -dydtmax;
+ s = &spline->splines[0];
+ if (( dxdtmin = (3*s->a*tmin + 2*s->b)*tmin + s->c )<0 ) dxdtmin = -dxdtmin;
+ if (( dxdtmax = (3*s->a*tmax + 2*s->b)*tmax + s->c )<0 ) dxdtmax = -dxdtmax;
+
+ /*s = &spline->splines[0];*/
+ min = ((s->a * tmin + s->b)* tmin + s->c)* tmin + s->d;
+ max = ((s->a * tmax + s->b)* tmax + s->c)* tmax + s->d;
+ if ( tmax==1 ) max = spline->to->me.x; /* beware rounding errors */
+ if ( !el->leavetiny && floor(min)==floor(max) ) { /* If it doesn't cross a pixel boundary then it might as well be vertical */
+ if ( tmin==0 ) max = min;
+ else if ( tmax==1 ) min = max;
+ else max = min;
+ }
+ if ( min==max )
+ new->vert = true;
+ else if ( min<max )
+ new->hup = true;
+ else {
+ temp = min; min = max; max=temp;
+ }
+ if ( !el->leavetiny && min+1>max ) new->almostvert = true;
+ if ( 40*dxdtmin<dydtmin ) new->vertattmin = true;
+ if ( 40*dxdtmax<dydtmax ) new->vertattmax = true;
+ /*if ( new->vertattmin && new->vertattmax && s->a==0 && s->b==0 ) new->almostvert = true;*/
+ new->coordmin[0] = min; new->coordmax[0] = max;
+ if ( el->coordmin[0]>min )
+ el->coordmin[0] = min;
+ if ( el->coordmax[0]<max )
+ el->coordmax[0] = max;
+
+ s = &spline->splines[1];
+ min = ((s->a * tmin + s->b)* tmin + s->c)* tmin + s->d;
+ max = ((s->a * tmax + s->b)* tmax + s->c)* tmax + s->d;
+ if ( tmax==1 ) max = spline->to->me.y;
+ if ( !el->leavetiny && floor(min)==floor(max) ) { /* If it doesn't cross a pixel boundary then it might as well be horizontal */
+ if ( tmin==0 ) max = min;
+ else if ( tmax==1 ) min = max;
+ else max = min;
+ }
+ if ( min==max )
+ new->hor = true;
+ else if ( min<max )
+ new->vup = true;
+ else {
+ temp = min; min = max; max=temp;
+ }
+ if ( !el->leavetiny && min+1>max ) new->almosthor = true;
+ if ( 40*dydtmin<dxdtmin ) new->horattmin = true;
+ if ( 40*dydtmax<dxdtmax ) new->horattmax = true;
+ /*if ( new->horattmin && new->horattmax && s->a==0 && s->b==0 ) new->almosthor = true;*/
+ new->coordmin[1] = min; new->coordmax[1] = max;
+ if ( el->coordmin[1]>min )
+ el->coordmin[1] = min;
+ if ( el->coordmax[1]<max )
+ el->coordmax[1] = max;
+
+ if ( new->hor && new->vert ) {
+ /* This spline is too small for us to notice */
+ free(new);
+return( false );
+ } else {
+ new->next = el->edges;
+ el->edges = new;
+
+ if ( el->splinelast!=NULL )
+ el->splinelast->splinenext = new;
+ el->splinelast = new;
+ if ( el->splinefirst==NULL )
+ el->splinefirst = new;
+
+return( true );
+ }
+}
+
+static void EIAddSpline(Spline *spline, EIList *el) {
+ extended ts[6], temp;
+ int i, j, base, last;
+
+ ts[0] = 0; ts[5] = 1.0;
+ SplineFindExtrema(&spline->splines[0],&ts[1],&ts[2]);
+ SplineFindExtrema(&spline->splines[1],&ts[3],&ts[4]);
+ /* avoid teeny tiny segments, they just confuse us */
+ SplineRemoveExtremaTooClose(&spline->splines[0],&ts[1],&ts[2]);
+ SplineRemoveExtremaTooClose(&spline->splines[1],&ts[3],&ts[4]);
+ for ( i=0; i<4; ++i ) for ( j=i+1; j<5; ++j ) {
+ if ( ts[i]>ts[j] ) {
+ temp = ts[i];
+ ts[i] = ts[j];
+ ts[j] = temp;
+ }
+ }
+ for ( base=0; ts[base]==-1; ++base);
+ for ( i=5; i>base ; --i ) {
+ if ( ts[i]==ts[i-1] ) {
+ for ( j=i-1; j>base; --j )
+ ts[j] = ts[j-1];
+ ts[j] = -1;
+ ++base;
+ }
+ }
+ last = base;
+ for ( i=base; i<5 ; ++i )
+ if ( EIAddEdge(spline,ts[last],ts[i+1],el) )
+ last = i+1;
+}
+
+void ELFindEdges(SplineChar *sc, EIList *el) {
+ Spline *spline, *first;
+ SplineSet *spl;
+
+ el->sc = sc;
+ if ( sc->layers[ly_fore].splines==NULL )
+return;
+
+ el->coordmin[0] = el->coordmax[0] = sc->layers[ly_fore].splines->first->me.x;
+ el->coordmin[1] = el->coordmax[1] = sc->layers[ly_fore].splines->first->me.y;
+
+ for ( spl = sc->layers[ly_fore].splines; spl!=NULL; spl = spl->next ) if ( spl->first->prev!=NULL && spl->first->prev->from!=spl->first ) {
+ first = NULL;
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) {
+ EIAddSpline(spline,el);
+ if ( first==NULL ) first = spline;
+ }
+ if ( el->splinefirst!=NULL && spl->first->prev!=NULL )
+ el->splinelast->splinenext = el->splinefirst;
+ el->splinelast = NULL; el->splinefirst = NULL;
+ }
+}
+
+static int IsBiggerSlope(EI *test, EI *base, int major) {
+ int other = !major;
+ real tdo, tdm, bdo, bdm, t;
+
+ if (( major && test->vup ) || (!major && test->hup))
+ t = test->tmin;
+ else
+ t = test->tmax;
+ tdm = (3*test->spline->splines[major].a*t + 2*test->spline->splines[major].b)*t + test->spline->splines[major].c;
+ tdo = (3*test->spline->splines[other].a*t + 2*test->spline->splines[other].b)*t + test->spline->splines[other].c;
+
+ if (( major && base->vup ) || (!major && base->hup))
+ t = base->tmin;
+ else
+ t = base->tmax;
+ bdm = (3*base->spline->splines[major].a*t + 2*base->spline->splines[major].b)*t + base->spline->splines[major].c;
+ bdo = (3*base->spline->splines[other].a*t + 2*base->spline->splines[other].b)*t + base->spline->splines[other].c;
+
+ if ( tdm==0 && bdm==0 )
+return( tdo > bdo );
+ if ( tdo==0 )
+return( tdo>0 );
+ else if ( bdo==0 )
+return( bdo>0 );
+
+return( tdo/tdm > bdo/bdm );
+}
+
+void ELOrder(EIList *el, int major ) {
+ int other = !major;
+ int pos;
+ EI *ei, *prev, *test;
+
+ el->low = floor(el->coordmin[major]); el->high = ceil(el->coordmax[major]);
+ el->cnt = el->high-el->low+1;
+ el->ordered = gcalloc(el->cnt,sizeof(EI *));
+ el->ends = gcalloc(el->cnt,1);
+
+ for ( ei = el->edges; ei!=NULL ; ei=ei->next ) {
+ pos = ceil(ei->coordmax[major])-el->low;
+ el->ends[pos] = true;
+ pos = floor(ei->coordmin[major])-el->low;
+ ei->ocur = (ei->hup == ei->vup)?ei->coordmin[other]:ei->coordmax[other];
+ ei->tcur = ((major && ei->vup) || (!major && ei->hup)) ?
+ ei->tmin: ei->tmax;
+ if ( major ) {
+ ei->up = ei->vup;
+ ei->hv = (ei->vert || ei->almostvert);
+ ei->hvbottom = ei->vup ? ei->vertattmin : ei->vertattmax;
+ ei->hvtop =!ei->vup ? ei->vertattmin : ei->vertattmax;
+ if ( ei->hor || ei->almosthor)
+ continue;
+ } else {
+ ei->up = ei->hup;
+ ei->hv = (ei->hor || ei->almosthor);
+ ei->hvbottom = ei->hup ? ei->horattmin : ei->horattmax;
+ ei->hvtop =!ei->hup ? ei->horattmin : ei->horattmax;
+ if ( ei->vert || ei->almostvert)
+ continue;
+ }
+ if ( el->ordered[pos]==NULL || ei->ocur<el->ordered[pos]->ocur ) {
+ ei->ordered = el->ordered[pos];
+ el->ordered[pos] = ei;
+ } else {
+ for ( prev=el->ordered[pos], test = prev->ordered; test!=NULL;
+ prev = test, test = test->ordered ) {
+ if ( test->ocur>ei->ocur ||
+ (test->ocur==ei->ocur && IsBiggerSlope(test,ei,major)))
+ break;
+ }
+ ei->ordered = test;
+ prev->ordered = ei;
+ }
+ }
+}
+
+static HintInstance *HIMerge(HintInstance *into, HintInstance *hi) {
+ HintInstance *n, *first = NULL, *last = NULL;
+
+ while ( into!=NULL && hi!=NULL ) {
+ if ( into->begin<hi->begin ) {
+ n = into;
+ into = into->next;
+ } else {
+ n = hi;
+ hi = hi->next;
+ }
+ if ( first==NULL )
+ first = n;
+ else
+ last->next = n;
+ last = n;
+ }
+ if ( into!=NULL ) {
+ if ( first==NULL )
+ first = into;
+ else
+ last->next = into;
+ } else if ( hi!=NULL ) {
+ if ( first==NULL )
+ first = hi;
+ else
+ last->next = hi;
+ }
+return( first );
+}
+
+StemInfo *HintCleanup(StemInfo *stem,int dosort,int instance_count) {
+ StemInfo *s, *p=NULL, *t, *pt, *sn;
+ int swap;
+
+ for ( s=stem; s!=NULL; p=s, s=s->next ) {
+ if ( s->width<0 ) {
+ s->start += s->width;
+ s->width = -s->width;
+ s->ghost = true;
+ }
+ s->reordered = false;
+ if ( p!=NULL && p->start> s->start )
+ dosort = true;
+ }
+ if ( dosort ) {
+ for ( p=NULL, s=stem; s!=NULL; p=s, s = sn ) {
+ sn = s->next;
+ for ( pt=s, t=sn; t!=NULL; pt=t, t=t->next ) {
+ if ( instance_count>1 &&
+ t->u.unblended!=NULL && s->u.unblended!=NULL ) {
+ int temp = UnblendedCompare((*t->u.unblended)[0],(*s->u.unblended)[0],instance_count);
+ if ( temp==0 )
+ swap = UnblendedCompare((*t->u.unblended)[1],(*s->u.unblended)[1],instance_count);
+ else
+ swap = temp<0;
+ } else if ( t->start<s->start )
+ swap=true;
+ else if ( t->start>s->start )
+ swap = false;
+ else
+ swap = (t->width<s->width);
+ if ( swap ) {
+ s->next = t->next;
+ if ( pt==s ) {
+ t->next = s;
+ sn = s;
+ } else {
+ t->next = sn;
+ pt->next = s;
+ }
+ if ( p==NULL )
+ stem = t;
+ else
+ p->next = t;
+ pt = s; /* swap s and t */
+ s = t;
+ t = pt;
+ }
+ }
+ }
+ /* Remove duplicates */
+ if ( stem!=NULL ) for ( p=stem, s=stem->next; s!=NULL; s = sn ) {
+ sn = s->next;
+ if ( p->start==s->start && p->width==s->width && p->hintnumber==s->hintnumber ) {
+ p->where = HIMerge(p->where,s->where);
+ s->where = NULL;
+ p->next = sn;
+ StemInfoFree(s);
+ } else
+ p = s;
+ }
+ }
+return( stem );
+}
+
+real EITOfNextMajor(EI *e, EIList *el, real sought_m ) {
+ /* We want to find t so that Mspline(t) = sought_m */
+ /* the curve is monotonic */
+ Spline1D *msp = &e->spline->splines[el->major];
+ real new_t;
+ real found_m;
+ real t_mmax, t_mmin;
+
+ if ( msp->a==0 && msp->b==0 ) {
+ if ( msp->c == 0 ) {
+ IError("Hor/Vert line when not expected");
+return( 0 );
+ }
+ new_t = (sought_m-msp->d)/(msp->c);
+return( new_t );
+ }
+
+ t_mmax = e->up?e->tmax:e->tmin;
+ t_mmin = e->up?e->tmin:e->tmax;
+ /* sought_m += el->low; */
+
+ while ( 1 ) {
+ new_t = (t_mmin+t_mmax)/2;
+ found_m = ( ((msp->a*new_t+msp->b)*new_t+msp->c)*new_t + msp->d );
+ if ( found_m>sought_m-.001 && found_m<sought_m+.001 )
+return( new_t );
+ if ( found_m > sought_m ) {
+ t_mmax = new_t;
+ } else {
+ t_mmin = new_t;
+ }
+ if ( t_mmax==t_mmin ) {
+ IError("EITOfNextMajor failed! on %s", el->sc!=NULL?el->sc->name:"Unknown" );
+return( new_t );
+ }
+ }
+}
+
+EI *EIActiveListReorder(EI *active,int *change) {
+ int any;
+ EI *pr, *apt;
+
+ *change = false;
+ if ( active!=NULL ) {
+ any = true;
+ while ( any ) {
+ any = false;
+ for ( pr=NULL, apt=active; apt->aenext!=NULL; ) {
+ if ( apt->ocur <= apt->aenext->ocur ) {
+ /* still ordered */;
+ pr = apt;
+ apt = apt->aenext;
+ } else if ( pr==NULL ) {
+ active = apt->aenext;
+ apt->aenext = apt->aenext->aenext;
+ active->aenext = apt;
+ *change = true;
+ /* don't need to set any, since this reorder can't disorder the list */
+ pr = active;
+ } else {
+ pr->aenext = apt->aenext;
+ apt->aenext = apt->aenext->aenext;
+ pr->aenext->aenext = apt;
+ any = *change = true;
+ pr = pr->aenext;
+ }
+ }
+ }
+ }
+return( active );
+}
+
+EI *EIActiveEdgesRefigure(EIList *el, EI *active,real i,int major, int *_change) {
+ EI *apt, *pr, *npt;
+ int change = false, subchange;
+ int other = !major;
+
+ /* first remove any entry which doesn't intersect the new scan line */
+ /* (ie. stopped on last line) */
+ for ( pr=NULL, apt=active; apt!=NULL; apt = apt->aenext ) {
+ if ( apt->coordmax[major]<i+el->low ) {
+ if ( pr==NULL )
+ active = apt->aenext;
+ else
+ pr->aenext = apt->aenext;
+ change = true;
+ } else
+ pr = apt;
+ }
+ /* then move the active list to the next line */
+ for ( apt=active; apt!=NULL; apt = apt->aenext ) {
+ Spline1D *osp = &apt->spline->splines[other];
+ apt->tcur = EITOfNextMajor(apt,el,i+el->low);
+ apt->ocur = ( ((osp->a*apt->tcur+osp->b)*apt->tcur+osp->c)*apt->tcur + osp->d );
+ }
+ /* reorder list */
+ active = EIActiveListReorder(active,&subchange);
+ if ( subchange ) change = true;
+
+ /* Insert new nodes */
+ if ( el->ordered[(int) i]!=NULL ) change = true;
+ for ( pr=NULL, apt=active, npt=el->ordered[(int) i]; apt!=NULL && npt!=NULL; ) {
+ if ( npt->ocur<apt->ocur ) {
+ npt->aenext = apt;
+ if ( pr==NULL )
+ active = npt;
+ else
+ pr->aenext = npt;
+ pr = npt;
+ npt = npt->ordered;
+ } else {
+ pr = apt;
+ apt = apt->aenext;
+ }
+ }
+ while ( npt!=NULL ) {
+ npt->aenext = NULL;
+ if ( pr==NULL )
+ active = npt;
+ else
+ pr->aenext = npt;
+ pr = npt;
+ npt = npt->ordered;
+ }
+ *_change = change;
+return( active );
+}
+
+/* Should I consider e and n to be a continuation of the same spline? */
+/* If we are at an intersection (and it's the same intersection on both) */
+/* and they go in vaguely the same direction then we should */
+/* Ah, but also if they are at different intersections and are connected */
+/* by a series of horizontal/vertical lines (whichever are invisible to major)*/
+/* then we still should. */
+int EISameLine(EI *e, EI *n, real i, int major) {
+ EI *t;
+
+ if ( n!=NULL && /*n->up==e->up &&*/
+ (ceil(e->coordmin[major])==i || floor(e->coordmin[major])==i || floor(e->coordmax[major])==i || ceil(e->coordmax[major])==i) &&
+ (ceil(n->coordmin[major])==i || floor(n->coordmin[major])==i || floor(n->coordmax[major])==i || ceil(n->coordmax[major])==i) ) {
+ if (
+ (n==e->splinenext && n->tmin==e->tmax &&
+ n->tcur<n->tmin+.2 && e->tcur>e->tmax-.2 ) ||
+ (n->splinenext==e && n->tmax==e->tmin &&
+ n->tcur>n->tmax-.2 && e->tcur<e->tmin+.2 ) )
+return( true );
+ /* can be seperated by a horizontal/vertical line in the other direction */
+ if ( n->tmax==1 && e->tmin==0 && n->tcur>.8 && e->tcur<.2) {
+ t = n;
+ while ( (t = t->splinenext)!=e ) {
+ if ( t==NULL || t==n ||
+ (major && !t->hor) || ( !major && !t->vert ))
+return( false );
+ }
+return( n->up==e->up );
+ } else if ( n->tmin==0 && e->tmax==1 && n->tcur<.2 && e->tcur>.8) {
+ t = e;
+ while ( (t = t->splinenext)!=n ) {
+ if ( t==NULL || t==e ||
+ (major && !t->hor) || ( !major && !t->vert ))
+return( false );
+ }
+return( n->up==e->up );
+ }
+ }
+return( false );
+}
+
+#if 1
+int EISkipExtremum(EI *e, real i, int major) {
+ EI *n = e->aenext, *t;
+
+ if ( n==NULL )
+return( false );
+ if (
+ (ceil(e->coordmin[major])==i || floor(e->coordmin[major])==i || floor(e->coordmax[major])==i || ceil(e->coordmax[major])==i) &&
+ (ceil(n->coordmin[major])==i || floor(n->coordmin[major])==i || floor(n->coordmax[major])==i || ceil(n->coordmax[major])==i) ) {
+ if (
+ (n==e->splinenext && n->tmin==e->tmax &&
+ n->tcur<n->tmin+.2 && e->tcur>e->tmax-.2 ) ||
+ (n->splinenext==e && n->tmax==e->tmin &&
+ n->tcur>n->tmax-.2 && e->tcur<e->tmin+.2 ) )
+return( n->up!=e->up );
+ /* can be seperated by a horizontal/vertical line in the other direction */
+ if ( n->tmax==1 && e->tmin==0 && n->tcur>.8 && e->tcur<.2) {
+ t = n;
+ while ( (t = t->splinenext)!=e ) {
+ if ( t==NULL || t==n ||
+ (major && !t->hor) || ( !major && !t->vert ))
+return( false );
+ }
+return( n->up!=e->up );
+ } else if ( n->tmin==0 && e->tmax==1 && n->tcur<.2 && e->tcur>.8) {
+ t = e;
+ while ( (t = t->splinenext)!=n ) {
+ if ( t==NULL || t==e ||
+ (major && !t->hor) || ( !major && !t->vert ))
+return( false );
+ }
+return( n->up!=e->up );
+ }
+ }
+return( false );
+}
+#else
+int EISkipExtremum(EI *e, real pos, int major) {
+ Spline1D *s;
+ real slopem, slopeo;
+
+ s = &e->spline->splines[major];
+ slopem = (3*s->a*e->tcur+2*s->b)*e->tcur+s->c;
+ s = &e->spline->splines[!major];
+ slopeo = (3*s->a*e->tcur+2*s->b)*e->tcur+s->c;
+ if ( !RealNear(slopeo,0)) {
+ slopem/=slopeo;
+ if ( slopem>-.15 && slopem<.15 )
+return( true );
+ }
+return( false );
+}
+#endif
+
+#ifndef LUA_FF_LIB
+EI *EIActiveEdgesFindStem(EI *apt, real i, int major) {
+ int cnt=apt->up?1:-1;
+ EI *e, *p;
+
+ p = NULL;
+ /* If we're at an intersection point and the next spline continues */
+ /* in about the same direction then this doesn't count as two lines */
+ /* but as one */
+ if ( EISameLine(apt,apt->aenext,i,major))
+ apt = apt->aenext;
+
+ e=apt->aenext;
+ if ( e==NULL )
+return( NULL );
+
+ for ( ; e!=NULL && cnt!=0; e=e->aenext ) {
+ p = e;
+ if ( EISkipExtremum(e,i,major)) {
+ e = e->aenext;
+ if ( e==NULL )
+ break;
+ continue;
+ }
+ if ( EISameLine(e,e->aenext,i,major))
+ e = e->aenext;
+ cnt += (e->up?1:-1);
+ }
+return( p );
+}
+
+static StemInfo *StemRemoveFlexCandidates(StemInfo *stems) {
+ StemInfo *s, *t, *sn;
+ const real BlueShift = 7;
+ /* Suppose we have something that is a flex candidate */
+ /* We might get two hints from it... one from the two end points */
+ /* and one from the internal point */
+
+ if ( stems==NULL )
+return( NULL );
+
+ for ( s=stems; (sn = s->next)!=NULL; s = sn ) {
+ if ( s->start+BlueShift > sn->start && s->width>0 && sn->width>0 &&
+ s->start+s->width-BlueShift < sn->start+sn->width &&
+ s->start+s->width+BlueShift > sn->start+sn->width &&
+ s->where->next!=NULL && sn->where->next==NULL ) {
+ t = sn->next;
+ sn->next = NULL;
+ StemInfoFree(sn);
+ s->next = t;
+ sn = t;
+ if ( t==NULL )
+ break;
+ }
+ }
+return( stems );
+}
+#endif
+
+real HIlen( StemInfo *stems) {
+ HintInstance *hi;
+ real len = 0;
+
+ for ( hi=stems->where; hi!=NULL; hi = hi->next )
+ len += hi->end-hi->begin;
+return( len );
+}
+
+real HIoverlap( HintInstance *mhi, HintInstance *thi) {
+ HintInstance *hi;
+ real len = 0;
+ real s, e;
+
+ for ( ; mhi!=NULL; mhi = mhi->next ) {
+ for ( hi = thi; hi!=NULL && hi->begin<=mhi->end; hi = hi->next ) {
+ if ( hi->end<mhi->begin ) {
+ thi = hi;
+ continue;
+ }
+ s = hi->begin<mhi->begin?mhi->begin:hi->begin;
+ e = hi->end>mhi->end?mhi->end:hi->end;
+ if ( e<s )
+ continue; /* Shouldn't happen */
+ len += e-s;
+ }
+ }
+return( len );
+}
+
+int StemInfoAnyOverlaps(StemInfo *stems) {
+ while ( stems!=NULL ) {
+ if ( stems->hasconflicts )
+return( true );
+ stems = stems->next;
+ }
+return( false );
+}
+
+
+#ifndef LUA_FF_LIB
+static int StemWouldConflict(StemInfo *stems,double base, double width) {
+ int found;
+
+ if ( width<0 ) {
+ base += width;
+ width = -width;
+ }
+ while ( stems!=NULL && stems->start<base && stems->start+stems->width<base )
+ stems = stems->next;
+
+ found = false;
+ while ( stems!=NULL && ((stems->width>0 && stems->start<base+width) ||
+ (stems->width<0 && stems->start+stems->width<base+width )) ) {
+ if (( stems->start==base && stems->width==width ) ||
+ (stems->start+stems->width==base && stems->width==-width ))
+return( false ); /* If it has already been added, then too late to worry about conflicts */
+ if ( stems->width>0 ) {
+ if ( stems->start+stems->width>=base && stems->start<=base+width )
+ found = true;
+ } else {
+ if ( stems->start>=base && stems->start+stems->width<=base+width )
+ found = true;
+ }
+ stems = stems->next;
+ }
+return( found );
+}
+#endif
+
+int StemListAnyConflicts(StemInfo *stems) {
+ StemInfo *s;
+ int any= false;
+ double end;
+
+ for ( s=stems; s!=NULL ; s=s->next )
+ s->hasconflicts = false;
+ while ( stems!=NULL ) {
+ end = stems->width<0 ? stems->start : stems->start+stems->width;
+ for ( s=stems->next; s!=NULL && (s->width>0 ? s->start : s->start+s->width)<end; s=s->next ) {
+ stems->hasconflicts = true;
+ s->hasconflicts = true;
+ any = true;
+ }
+ stems = stems->next;
+ }
+return( any );
+}
+
+HintInstance *HICopyTrans(HintInstance *hi, real mul, real offset) {
+ HintInstance *first=NULL, *last = NULL, *cur, *p;
+
+ while ( hi!=NULL ) {
+ cur = chunkalloc(sizeof(HintInstance));
+ if ( mul>0 ) {
+ cur->begin = hi->begin*mul+offset;
+ cur->end = hi->end*mul+offset;
+ if ( first==NULL )
+ first = cur;
+ else
+ last->next = cur;
+ last = cur;
+ } else {
+ cur->begin = hi->end*mul+offset;
+ cur->end = hi->begin*mul+offset;
+ if ( first==NULL || cur->begin<first->begin ) {
+ cur->next = first;
+ first = cur;
+ } else {
+ for ( p=first, last=p->next; last!=NULL && cur->begin>last->begin; last=last->next );
+ p->next = cur;
+ cur->next = last;
+ }
+ }
+ hi = hi->next;
+ }
+return( first );
+}
+
+#ifndef LUA_FF_LIB
+
+static int inhints(StemInfo *stems,real base, real width) {
+
+ while ( stems!=NULL ) {
+ if ( stems->start==base || stems->start+stems->width==base+width ||
+ stems->start+stems->width==base || stems->start==base+width )
+return( true );
+ stems = stems->next;
+ }
+return( false );
+}
+
+static StemInfo *GhostAdd(StemInfo *ghosts, StemInfo *stems, real base,
+ real width, real xstart, real xend ) {
+ StemInfo *s, *prev, *test;
+ HintInstance *hi;
+
+ if ( base!=rint(base))
+return( ghosts );
+
+ if ( xstart>xend ) {
+ real temp = xstart;
+ xstart = xend;
+ xend = temp;
+ }
+ if ( width==20 ) base -= 20;
+
+ if ( inhints(stems,base,width))
+return(ghosts); /* already recorded */
+ if ( StemWouldConflict(stems,base,width))
+return(ghosts); /* Let's not add a conflicting ghost hint */
+ if ( StemWouldConflict(ghosts,base,width))
+return(ghosts);
+
+ for ( s=ghosts; s!=NULL; s=s->next )
+ if ( s->start==base && s->width==width )
+ break;
+ if ( s==NULL ) {
+ s = chunkalloc(sizeof(StemInfo));
+ s->start = base;
+ s->width = width;
+ s->ghost = true;
+ if ( ghosts==NULL || base<ghosts->start ) {
+ s->next = ghosts;
+ ghosts = s;
+ } else {
+ for ( prev=ghosts, test=ghosts->next; test!=NULL && base<test->start;
+ prev = test, test = test->next);
+ prev->next = s;
+ s->next = test;
+ }
+ }
+ hi = chunkalloc(sizeof(HintInstance));
+ hi->begin = xstart;
+ hi->end = xend;
+ s->where = HIMerge(s->where,hi);
+return( ghosts );
+}
+
+static StemInfo *CheckForGhostHints(StemInfo *stems,SplineChar *sc, BlueData *bd) {
+ /* PostScript doesn't allow a hint to stretch from one alignment zone to */
+ /* another. (Alignment zones are the things in bluevalues). */
+ /* Oops, I got this wrong. PS doesn't allow a hint to start in a bottom */
+ /* zone and stretch to a top zone. Everything in OtherBlues is a bottom */
+ /* zone. The baseline entry in BlueValues is also a bottom zone. Every- */
+ /* thing else in BlueValues is a top-zone. */
+ /* This means */
+ /* that we can't define a horizontal stem hint which stretches from */
+ /* the baseline to the top of a capital I, or the x-height of lower i */
+ /* If we find any such hints we must remove them, and replace them with */
+ /* ghost hints. The bottom hint has height -21, and the top -20 */
+ BlueData _bd;
+ SplineFont *sf = sc->parent;
+ StemInfo *prev, *s, *n, *snext, *ghosts = NULL;
+ SplineSet *spl, *spl_next;
+ Spline *spline, *first;
+ SplinePoint *sp, *sp2;
+ real base, width/*, toobig = (sc->parent->ascent+sc->parent->descent)/2*/;
+ int i,startfound, widthfound;
+ DBounds b;
+
+ /* Get the alignment zones */
+ if ( bd==NULL ) {
+ QuickBlues(sf,&_bd);
+ bd = &_bd;
+ }
+
+ /* look for any stems stretching from one zone to another and remove them */
+ /* (I used to turn them into ghost hints here, but that didn't work (for */
+ /* example on "E" where we don't need any ghosts from the big stem because*/
+ /* the narrow stems provide the hints that PS needs */
+ /* However, there are counter-examples. in Garamond-Pro the "T" character */
+ /* has a horizontal stem at the top which stretches between two adjacent */
+ /* bluezones. Removing it is wrong. Um... Thanks Adobe */
+ /* I misunderstood. Both of these were top-zones */
+ for ( prev=NULL, s=stems; s!=NULL; s=snext ) {
+ snext = s->next;
+ startfound = widthfound = -1;
+ for ( i=0; i<bd->bluecnt; ++i ) {
+ if ( s->start>=bd->blues[i][0]-1 && s->start<=bd->blues[i][1]+1 )
+ startfound = i;
+ else if ( s->start+s->width>=bd->blues[i][0]-1 && s->start+s->width<=bd->blues[i][1]+1 )
+ widthfound = i;
+ }
+ if ( startfound!=-1 && widthfound!=-1 &&
+ ( s->start>0 || s->start+s->width<=0 ))
+ startfound = widthfound = -1;
+ if ( startfound!=-1 && widthfound!=-1 ) {
+ if ( prev==NULL )
+ stems = snext;
+ else
+ prev->next = snext;
+ s->next = NULL;
+ StemInfoFree(s);
+ } else
+ prev = s;
+ }
+
+ /* Now look and see if we can find any edges which lie in */
+ /* these zones. Edges which are not currently in hints */
+ /* Use the current contour to determine top or bottom */
+ for ( spl = sc->layers[ly_fore].splines; spl!=NULL; spl = spl->next ) if ( spl->first->prev!=NULL ) {
+ first = NULL;
+ spl_next = spl->next; spl->next = NULL;
+ SplineSetQuickBounds(spl,&b);
+ spl->next = spl_next;
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; spline = spline->to->next ) {
+ base = spline->from->me.y;
+ if ( spline->knownlinear && base == spline->to->me.y ) {
+ for ( i=0; i<bd->bluecnt; ++i ) {
+ if ( base>=bd->blues[i][0]-1 && base<=bd->blues[i][1]+1 )
+ break;
+ }
+ if ( i!=bd->bluecnt ) {
+ if ( spline->from->me.y+21 > b.maxy )
+ width = 20;
+ else if ( spline->from->me.y-20 < b.miny )
+ width = 21;
+ else {
+ for ( sp2= spline->from->prev->from; sp2!=spline->from && sp2->me.y==spline->from->me.y; sp2=sp2->prev->from );
+ width = (sp2->me.y > spline->from->me.y)?21:20;
+ }
+ ghosts = GhostAdd(ghosts,stems, base,width,spline->from->me.x,spline->to->me.x);
+ }
+ }
+ if ( first==NULL ) first = spline;
+ }
+ /* And check for the horizontal top of a curved surface */
+ for ( sp = spl->first; ; ) {
+ base = sp->me.y;
+ if ( !sp->nonextcp && !sp->noprevcp && sp->nextcp.y==base &&
+ sp->prevcp.y==base ) {
+ for ( i=0; i<bd->bluecnt; ++i ) {
+ if ( base>=bd->blues[i][0]-1 && base<=bd->blues[i][1]+1 )
+ break;
+ }
+ if ( i!=bd->bluecnt ) {
+ if ( sp->me.y+21 > b.maxy )
+ width = 20;
+ else if ( sp->me.y-20 < b.miny )
+ width = 21;
+ else {
+ for ( sp2= sp->prev->from; sp2!=sp && sp2->me.y==spline->from->me.y; sp2=sp2->prev->from );
+ width = (sp2->me.y > sp->me.y)?21:20;
+ }
+ ghosts = GhostAdd(ghosts,stems, base,width,(sp->me.x+sp->prevcp.x)/2,(sp->me.x+sp->nextcp.x)/2);
+ }
+ }
+ sp = sp->next->to;
+ if ( sp == spl->first )
+ break;
+ }
+ }
+
+ /* Finally add any ghosts we've got back into the stem list */
+ for ( s=ghosts; s!=NULL; s=snext ) {
+ snext = s->next;
+ for ( prev=NULL, n=stems; n!=NULL && s->start>n->start; prev=n, n=n->next );
+ if ( prev==NULL ) {
+ s->next = stems;
+ stems = s;
+ } else {
+ prev->next = s;
+ s->next = n;
+ }
+ }
+return( stems );
+}
+#endif
+
+static HintInstance *SCGuessHintPoints(SplineChar *sc, StemInfo *stem,int major, int off) {
+ SplinePoint *starts[20], *ends[20];
+ int spt=0, ept=0;
+ SplinePointList *spl;
+ SplinePoint *sp, *np;
+ int sm, wm, i, j, val;
+ real coord;
+ HintInstance *head, *test, *cur, *prev;
+
+ for ( spl=sc->layers[ly_fore].splines; spl!=NULL; spl=spl->next ) {
+ for ( sp=spl->first; ; sp = np ) {
+ coord = (major?sp->me.x:sp->me.y);
+ sm = coord>=stem->start-off && coord<=stem->start+off;
+ wm = coord>=stem->start+stem->width-off && coord<=stem->start+stem->width+off;
+ if ( sm && spt<20 )
+ starts[spt++] = sp;
+ if ( wm && ept<20 )
+ ends[ept++] = sp;
+ if ( sp->next==NULL )
+ break;
+ np = sp->next->to;
+ if ( np==spl->first )
+ break;
+ }
+ }
+
+ head = NULL;
+ for ( i=0; i<spt; ++i ) {
+ val = 0x80000000;
+ for ( j=0; j<ept; ++j ) {
+ if ( major && starts[i]->me.y>=ends[j]->me.y-1 && starts[i]->me.y<=ends[j]->me.y+1 ) {
+ val = starts[i]->me.y;
+ break;
+ } else if ( !major && starts[i]->me.x>=ends[j]->me.x-1 && starts[i]->me.x<=ends[j]->me.x+1 ) {
+ val = starts[i]->me.x;
+ break;
+ }
+ }
+ if ( val!=0x80000000 ) {
+ for ( prev=NULL, test=head; test!=NULL && val>test->begin; prev=test, test=test->next );
+ if ( test==NULL || val!=test->begin ) {
+ cur = chunkalloc(sizeof(HintInstance));
+ cur->begin = cur->end = val;
+ cur->next = test;
+ if ( prev==NULL ) head = cur;
+ else prev->next = cur;
+ }
+ }
+ }
+return( head );
+}
+
+static void SCGuessHintInstances(SplineChar *sc, StemInfo *stem,int major) {
+ SplinePointList *spl;
+ SplinePoint *sp, *np;
+ int sm, wm, off;
+ real ob, oe;
+ HintInstance *s=NULL, *w=NULL, *cur, *p, *t, *n, *w2;
+ ob = 0; oe = 0;
+ /* We've got a hint (from somewhere, old data, reading in a font, user specified etc.) */
+ /* but we don't have HintInstance info. So see if we can find those data */
+ /* Will get confused by stems with holes in them (for example if you make */
+ /* a hint from one side of an H to the other, it will get the whole thing */
+ /* not just the cross stem) */
+
+ for ( spl=sc->layers[ly_fore].splines; spl!=NULL; spl=spl->next ) {
+ for ( sp=spl->first; ; sp = np ) {
+ sm = (major?sp->me.x:sp->me.y)==stem->start;
+ wm = (major?sp->me.x:sp->me.y)==stem->start+stem->width;
+ if ( sp->next==NULL )
+ break;
+ np = sp->next->to;
+ if ( sm || wm ) {
+ if ( !major ) {
+ if ( np->me.y==sp->me.y ) {
+ ob = sp->me.x; oe = np->me.x;
+ } else if ( sp->nextcp.y==sp->me.y ) {
+ ob = sp->me.x; oe = (sp->me.x+sp->nextcp.x)/2;
+ if ( sp->prevcp.y==sp->me.y )
+ ob = (sp->prevcp.x+sp->me.x)/2;
+ } else if ( sp->prevcp.y==sp->me.y ) {
+ ob = sp->me.x; oe = (sp->prevcp.x+sp->me.x)/2;
+ } else
+ sm = wm = false;
+ } else {
+ if ( np->me.x==sp->me.x ) {
+ ob = sp->me.y; oe = np->me.y;
+ } else if ( sp->nextcp.x==sp->me.x ) {
+ ob = sp->me.y; oe = (sp->nextcp.y+sp->me.y)/2;
+ if ( sp->prevcp.x==sp->me.x )
+ ob = (sp->prevcp.y+sp->me.y)/2;
+ } else if ( sp->prevcp.x==sp->me.x ) {
+ ob = sp->me.y; oe = (sp->prevcp.y+sp->me.y)/2;
+ } else
+ sm = wm = false;
+ }
+ }
+ if ( sm || wm ) {
+ cur = chunkalloc(sizeof(HintInstance));
+ if ( ob>oe ) { real temp=ob; ob=oe; oe=temp;}
+ cur->begin = ob;
+ cur->end = oe;
+ if ( sm ) {
+ if ( s==NULL || s->begin>cur->begin ) {
+ cur->next = s;
+ s = cur;
+ } else {
+ p = s;
+ for ( t=s->next; t!=NULL && t->begin<cur->begin; p=t, t=t->next );
+ p->next = cur; cur->next = t;
+ }
+ } else {
+ if ( w==NULL || w->begin>cur->begin ) {
+ cur->next = w;
+ w = cur;
+ } else {
+ p = w;
+ for ( t=w->next; t!=NULL && t->begin<cur->begin; p=t, t=t->next );
+ p->next = cur; cur->next = t;
+ }
+ }
+ }
+ if ( np==spl->first )
+ break;
+ }
+ }
+
+ /* Now we know what the right side of the stem looks like, and we know */
+ /* what the left side looks like. They may not look the same (H for example) */
+ /* Figure out the set where both are active */
+ /* Unless it's a ghost hint */
+ if ( stem->width==20 && s==NULL && w!=NULL ) {
+ s = w;
+ w = NULL;
+ } else if ( stem->width==21 && s!=NULL && w==NULL) {
+ /* Just use s */;
+ } else for ( p=NULL, t=s; t!=NULL; t=n ) {
+ n = t->next;
+ for ( w2=w; w2!=NULL && w2->begin<t->end ; w2=w2->next ) {
+ if ( w2->end<=t->begin )
+ continue;
+ if ( w2->begin<=t->begin && w2->end>=t->end ) {
+ /* Perfect match */
+ break;
+ }
+ if ( w2->begin>=t->begin )
+ t->begin = w2->begin;
+ if ( w2->end<=t->end ) {
+ cur = chunkalloc(sizeof(HintInstance));
+ cur->begin = w2->end;
+ cur->end = t->end;
+ cur->next = n;
+ t->next = cur;
+ n = cur;
+ t->end = w2->end;
+ }
+ break;
+ }
+ if ( w2!=NULL && w2->begin>=t->end )
+ w2 = NULL;
+ if ( w2==NULL && w!=NULL ) {
+ HintInstance *best = NULL;
+ double best_off=1e10, off;
+ for ( w2=w; w2!=NULL ; w2=w2->next ) {
+ if ( w2->end<=t->begin )
+ off = t->begin - w2->end;
+ else
+ off = w2->begin - t->end;
+ if ( best==NULL && off<best_off ) {
+ best = w2;
+ best_off = off;
+ }
+ }
+ if ( best!=NULL && best_off<stem->width ) {
+ w2 = best;
+ if( w2->begin<t->begin )
+ t->begin = w2->begin;
+ if ( w2->end>t->end )
+ t->end = w2->end;
+ }
+ }
+ if ( w2==NULL ) {
+ /* No match for t (or if there were it wasn't complete) get rid */
+ /* of what's left of t */
+ chunkfree(t,sizeof(*t));
+ if ( p==NULL )
+ s = n;
+ else
+ p->next = n;
+ } else
+ p = t;
+ }
+ while ( w!=NULL ) {
+ n = w->next;
+ chunkfree(w,sizeof(*w));
+ w=n;
+ }
+
+ /* If we couldn't find anything, then see if there are two points which */
+ /* have the same x or y value and whose other coordinates match those of */
+ /* the hint */
+ /* Surprisingly many fonts have hints which don't accurately match the */
+ /* points. Perhaps BlueFuzz (default 1) applies here too */
+ for ( off=0; off<1 && s==NULL; ++off )
+ s = SCGuessHintPoints(sc,stem,major,off);
+
+ stem->where = s;
+}
+
+static StemInfo *StemInfoAdd(StemInfo *list, StemInfo *new) {
+ StemInfo *prev, *test;
+
+ for ( prev=NULL, test=list; test!=NULL && new->start>test->start; prev=test, test=test->next );
+ if ( test!=NULL && test->start==new->start && test->width==new->width ) {
+ /* Replace the old with the new */
+ /* can't just free the new, because the Guess routines depend on it */
+ /* being around */
+ new->next = test->next;
+ StemInfoFree(test);
+ } else
+ new->next = test;
+ if ( prev==NULL )
+ list = new;
+ else
+ prev->next = new;
+return( list );
+}
+
+void SCGuessHHintInstancesAndAdd(SplineChar *sc, StemInfo *stem, real guess1, real guess2) {
+ SCGuessHintInstances(sc, stem, 0);
+ sc->hstem = StemInfoAdd(sc->hstem,stem);
+ if ( stem->where==NULL && guess1!=0x80000000 ) {
+ if ( guess1>guess2 ) { real temp = guess1; guess1 = guess2; guess2 = temp; }
+ stem->where = chunkalloc(sizeof(HintInstance));
+ stem->where->begin = guess1;
+ stem->where->end = guess2;
+ }
+ sc->hconflicts = StemListAnyConflicts(sc->hstem);
+ if ( stem->hasconflicts ) {
+ /*StemInfoReduceOverlap(sc->hstem,stem);*/ /* User asked for it, assume s/he knows what s/he's doing */
+ if ( stem->where==NULL )
+ IError("Couldn't figure out where this hint is active");
+ }
+}
+
+void SCGuessVHintInstancesAndAdd(SplineChar *sc, StemInfo *stem, real guess1, real guess2) {
+ SCGuessHintInstances(sc, stem, 1);
+ sc->vstem = StemInfoAdd(sc->vstem,stem);
+ if ( stem->where==NULL && guess1!=0x80000000 ) {
+ if ( guess1>guess2 ) { real temp = guess1; guess1 = guess2; guess2 = temp; }
+ stem->where = chunkalloc(sizeof(HintInstance));
+ stem->where->begin = guess1;
+ stem->where->end = guess2;
+ }
+ sc->vconflicts = StemListAnyConflicts(sc->vstem);
+ if ( stem->hasconflicts ) {
+ /*StemInfoReduceOverlap(sc->vstem,stem);*/ /* User asked for it, assume s/he knows what s/he's doing */
+ if ( stem->where==NULL )
+ IError("Couldn't figure out where this hint is active");
+ }
+}
+
+void SCGuessHHintInstancesList(SplineChar *sc) {
+ StemInfo *h;
+ int any = false;
+
+ for ( h= sc->hstem; h!=NULL; h=h->next )
+ if ( h->where==NULL ) {
+ SCGuessHintInstances(sc,h,0);
+ any |= h->where!=NULL;
+ }
+/*
+ if ( any )
+ for ( h= sc->hstem; h!=NULL; h=h->next )
+ StemInfoReduceOverlap(h->next,h);
+*/
+}
+
+void SCGuessVHintInstancesList(SplineChar *sc) {
+ StemInfo *h;
+ int any = false;
+
+ for ( h= sc->vstem; h!=NULL; h=h->next )
+ if ( h->where==NULL ) {
+ SCGuessHintInstances(sc,h,1);
+ any |= h->where!=NULL;
+ }
+/*
+ if ( any )
+ for ( h= sc->vstem; h!=NULL; h=h->next )
+ StemInfoReduceOverlap(h->next,h);
+*/
+}
+
+#ifndef LUA_FF_LIB
+static StemInfo *RefHintsMerge(StemInfo *into, StemInfo *rh, real mul, real offset,
+ real omul, real oofset) {
+ StemInfo *prev, *h, *n;
+ real start, width;
+
+ for ( ; rh!=NULL; rh=rh->next ) {
+ start = rh->start*mul + offset;
+ width = rh->width *mul;
+ if ( width<0 ) {
+ start += width; width = -width;
+ }
+ for ( h=into, prev=NULL; h!=NULL && (start>h->start || (start==h->start && width>h->width)); prev=h, h=h->next );
+ if ( h==NULL || start!=h->start || width!=h->width ) {
+ n = chunkalloc(sizeof(StemInfo));
+ n->start = start; n->width = width;
+ n->next = h;
+ if ( prev==NULL )
+ into = n;
+ else
+ prev->next = n;
+ n->where = HICopyTrans(rh->where,omul,oofset);
+ } else
+ h->where = HIMerge(h->where,HICopyTrans(rh->where,omul,oofset));
+ }
+return( into );
+}
+
+static DStemInfo *RefDHintsMerge(DStemInfo *into, DStemInfo *rh, real xmul, real xoffset,
+ real ymul, real yoffset) {
+ DStemInfo *new;
+ BasePoint temp;
+ DStemInfo *prev, *n;
+
+ for ( ; rh!=NULL; rh=rh->next ) {
+ new = chunkalloc(sizeof(DStemInfo));
+ *new = *rh;
+ new->leftedgetop.x = xmul*new->leftedgetop.x + xoffset;
+ new->rightedgetop.x = xmul*new->rightedgetop.x + xoffset;
+ new->leftedgebottom.x = xmul*new->leftedgebottom.x + xoffset;
+ new->rightedgebottom.x = xmul*new->rightedgebottom.x + xoffset;
+ new->leftedgetop.y = ymul*new->leftedgetop.y + yoffset;
+ new->rightedgetop.y = ymul*new->rightedgetop.y + yoffset;
+ new->leftedgebottom.y = ymul*new->leftedgebottom.y + yoffset;
+ new->rightedgebottom.y = ymul*new->rightedgebottom.y + yoffset;
+ if ( xmul<0 ) {
+ temp = new->leftedgetop;
+ new->leftedgetop = new->rightedgetop;
+ new->rightedgetop = temp;
+ temp = new->leftedgebottom;
+ new->leftedgebottom = new->rightedgebottom;
+ new->rightedgebottom = temp;
+ }
+ if ( ymul<0 ) {
+ temp = new->leftedgetop;
+ new->leftedgetop = new->leftedgebottom;
+ new->leftedgebottom = temp;
+ temp = new->rightedgetop;
+ new->rightedgetop = new->rightedgebottom;
+ new->rightedgebottom = temp;
+ }
+ if ( into==NULL || new->leftedgetop.x<into->leftedgetop.x ) {
+ new->next = into;
+ into = new;
+ } else {
+ for ( prev=into, n=prev->next; n!=NULL && new->leftedgetop.x>n->leftedgetop.x;
+ prev = n, n = n->next );
+ new->next = n;
+ prev->next = new;
+ }
+ }
+return( into );
+}
+
+static void AutoHintRefs(SplineChar *sc,BlueData *bd, int picky) {
+ RefChar *ref;
+
+ /* Add hints for base characters before accent hints => if there are any */
+ /* conflicts, the base characters win */
+ for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
+ if ( ref->transform[1]==0 && ref->transform[2]==0 ) {
+ if ( picky ) {
+ if ( !ref->sc->manualhints && ref->sc->changedsincelasthinted &&
+ (ref->sc->layers[ly_fore].refs!=NULL &&
+ ref->sc->layers[ly_fore].splines==NULL))
+ AutoHintRefs(ref->sc,bd,true);
+ } else if ( !ref->sc->manualhints && ref->sc->changedsincelasthinted )
+ SplineCharAutoHint(ref->sc,bd);
+ if ( ref->sc->unicodeenc!=-1 && ref->sc->unicodeenc<0x10000 &&
+ isalnum(ref->sc->unicodeenc) ) {
+ sc->hstem = RefHintsMerge(sc->hstem,ref->sc->hstem,ref->transform[3], ref->transform[5], ref->transform[0], ref->transform[4]);
+ sc->vstem = RefHintsMerge(sc->vstem,ref->sc->vstem,ref->transform[0], ref->transform[4], ref->transform[3], ref->transform[5]);
+ sc->dstem = RefDHintsMerge(sc->dstem,ref->sc->dstem,ref->transform[0], ref->transform[4], ref->transform[3], ref->transform[5]);
+ }
+ }
+ }
+
+ for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
+ if ( ref->transform[1]==0 && ref->transform[2]==0 &&
+ (ref->sc->unicodeenc==-1 || ref->sc->unicodeenc>=0x10000 ||
+ !isalnum(ref->sc->unicodeenc)) ) {
+ sc->hstem = RefHintsMerge(sc->hstem,ref->sc->hstem,ref->transform[3], ref->transform[5], ref->transform[0], ref->transform[4]);
+ sc->vstem = RefHintsMerge(sc->vstem,ref->sc->vstem,ref->transform[0], ref->transform[4], ref->transform[3], ref->transform[5]);
+ sc->dstem = RefDHintsMerge(sc->dstem,ref->sc->dstem,ref->transform[0], ref->transform[4], ref->transform[3], ref->transform[5]);
+ }
+ }
+
+ sc->vconflicts = StemListAnyConflicts(sc->vstem);
+ sc->hconflicts = StemListAnyConflicts(sc->hstem);
+
+ SCOutOfDateBackground(sc);
+ SCHintsChanged(sc);
+}
+#endif
+
+void SCClearHints(SplineChar *sc) {
+ SCClearHintMasks(sc,true);
+ StemInfosFree(sc->hstem);
+ StemInfosFree(sc->vstem);
+ sc->hstem = sc->vstem = NULL;
+ sc->hconflicts = sc->vconflicts = false;
+ DStemInfosFree(sc->dstem);
+ sc->dstem = NULL;
+ MinimumDistancesFree(sc->md);
+ sc->md = NULL;
+ SCClearRounds(sc);
+ SCOutOfDateBackground(sc);
+}
+
+static void _SCClearHintMasks(SplineChar *sc,int counterstoo) {
+ SplineSet *spl;
+ SplinePoint *sp;
+ RefChar *ref;
+
+ if ( counterstoo ) {
+ free(sc->countermasks);
+ sc->countermasks = NULL; sc->countermask_cnt = 0;
+ }
+
+ for ( spl = sc->layers[ly_fore].splines; spl!=NULL; spl=spl->next ) {
+ for ( sp = spl->first ; ; ) {
+ chunkfree(sp->hintmask,sizeof(HintMask));
+ sp->hintmask = NULL;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ }
+
+ for ( ref = sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
+ for ( spl = ref->layers[0].splines; spl!=NULL; spl=spl->next ) {
+ for ( sp = spl->first ; ; ) {
+ chunkfree(sp->hintmask,sizeof(HintMask));
+ sp->hintmask = NULL;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ }
+ }
+}
+
+static void ModifyHintMaskAdd(HintMask *hm,int index) {
+ int i;
+
+ if ( hm==NULL )
+return;
+
+ for ( i=94; i>=index ; --i ) {
+ if ( (*hm)[i>>3]&(0x80>>(i&7)) )
+ (*hm)[(i+1)>>3] |= (0x80>>((i+1)&7));
+ else
+ (*hm)[(i+1)>>3] &= ~(0x80>>((i+1)&7));
+ }
+ (*hm)[index>>3] &= ~(0x80>>(index&7));
+}
+
+void SCModifyHintMasksAdd(SplineChar *sc,StemInfo *new) {
+ SplineSet *spl;
+ SplinePoint *sp;
+ RefChar *ref;
+ int index;
+ StemInfo *h;
+ int i;
+ /* We've added a new stem. Figure out where it goes and modify the */
+ /* hintmasks accordingly */
+
+ for ( index=0, h=sc->hstem; h!=NULL && h!=new; ++index, h=h->next );
+ if ( h==NULL )
+ for ( h=sc->vstem; h!=NULL && h!=new; ++index, h=h->next );
+ if ( h==NULL )
+return;
+
+ for ( i=0; i<sc->countermask_cnt; ++i )
+ ModifyHintMaskAdd(&sc->countermasks[i],index);
+
+ for ( spl = sc->layers[ly_fore].splines; spl!=NULL; spl=spl->next ) {
+ for ( sp = spl->first ; ; ) {
+ ModifyHintMaskAdd(sp->hintmask,index);
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ }
+
+ for ( ref = sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
+ for ( spl = ref->layers[0].splines; spl!=NULL; spl=spl->next ) {
+ for ( sp = spl->first ; ; ) {
+ ModifyHintMaskAdd(sp->hintmask,index);
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ }
+ }
+}
+
+static void SCFigureSimpleCounterMasks(SplineChar *sc) {
+ SplineChar *scs[MmMax];
+#ifndef LUA_FF_LIB
+ int hadh3, hadv3, i;
+ HintMask mask;
+#endif
+
+ if ( sc->countermask_cnt!=0 )
+return;
+
+ scs[0] = sc;
+#ifndef LUA_FF_LIB
+ hadh3 = CvtPsStem3(NULL,scs,1,true,false);
+ hadv3 = CvtPsStem3(NULL,scs,1,false,false);
+ if ( hadh3 || hadv3 ) {
+ memset(mask,0,sizeof(mask));
+ if ( hadh3 ) mask[0] = 0x80|0x40|0x20;
+ if ( hadv3 ) {
+ for ( i=0; i<3 ; ++i ) {
+ int j = i+sc->vstem->hintnumber;
+ mask[j>>3] |= (0x80>>(j&7));
+ }
+ }
+ sc->countermask_cnt = 1;
+ sc->countermasks = galloc(sizeof(HintMask));
+ memcpy(sc->countermasks[0],mask,sizeof(HintMask));
+return;
+ }
+#endif
+}
+
+/* find all the other stems (after main) which seem to form a counter group */
+/* with main. That is their stems have a considerable overlap (in the other */
+/* coordinate) with main */
+static int stemmatches(StemInfo *main) {
+ StemInfo *last=main, *test;
+ real mlen, olen;
+ int cnt;
+
+ cnt = 1; /* for the main stem */
+ main->tobeused = true;
+ mlen = HIlen(main);
+ for ( test=main->next; test!=NULL; test=test->next )
+ test->tobeused = false;
+ for ( test=main->next; test!=NULL; test=test->next ) {
+ if ( test->used || last->start+last->width>test->start || test->hintnumber==-1 )
+ continue;
+ olen = HIoverlap(main->where,test->where);
+ if ( olen>mlen/3 && olen>HIlen(test)/3 ) {
+ test->tobeused = true;
+ ++cnt;
+ }
+ }
+return( cnt );
+}
+
+static int FigureCounters(StemInfo *stems,HintMask mask ) {
+ StemInfo *h, *first;
+
+ while ( stems!=NULL ) {
+ for ( first=stems; first!=NULL && first->used; first = first->next );
+ if ( first==NULL )
+ break;
+ if ( first->where==NULL || first->hintnumber==-1 || stemmatches(first)<=2 ) {
+ first->used = true;
+ stems = first->next;
+ continue;
+ }
+ for ( h = first; h!=NULL; h = h->next ) {
+ if ( h->tobeused ) {
+ mask[h->hintnumber>>3] |= (0x80>>(h->hintnumber&7));
+ h->used = true;
+ }
+ }
+return( true );
+ }
+return( false );
+}
+
+/* Only used for metafont routine */
+void SCFigureVerticalCounterMasks(SplineChar *sc) {
+ HintMask masks[30];
+ StemInfo *h;
+ int mc=0, i;
+
+ /* I'm not supporting counter hints for mm fonts */
+
+ if ( sc==NULL )
+return;
+
+ free(sc->countermasks);
+ sc->countermask_cnt = 0;
+ sc->countermasks = NULL;
+
+ for ( h=sc->vstem; h!=NULL ; h=h->next )
+ h->used = false;
+
+ mc = 0;
+
+ while ( mc<sizeof(masks)/sizeof(masks[0]) ) {
+ memset(masks[mc],'\0',sizeof(HintMask));
+ if ( !FigureCounters(sc->vstem,masks[mc]))
+ break;
+ ++mc;
+ }
+ if ( mc!=0 ) {
+ sc->countermask_cnt = mc;
+ sc->countermasks = galloc(mc*sizeof(HintMask));
+ for ( i=0; i<mc ; ++i )
+ memcpy(sc->countermasks[i],masks[i],sizeof(HintMask));
+ }
+}
+
+void SCFigureCounterMasks(SplineChar *sc) {
+ HintMask masks[30];
+ uint32 script;
+ StemInfo *h;
+ int mc=0, i;
+
+ /* I'm not supporting counter hints for mm fonts */
+
+ if ( sc==NULL )
+return;
+
+ free(sc->countermasks);
+ sc->countermask_cnt = 0;
+ sc->countermasks = NULL;
+
+ /* Check for h/vstem3 case */
+ /* Which is allowed even for non-CJK letters */
+ script = SCScriptFromUnicode(sc);
+ if ( script==CHR('l','a','t','n') || script==CHR('c','y','r','l') ||
+ script==CHR('g','r','e','k') ) {
+ SCFigureSimpleCounterMasks(sc);
+return;
+ }
+
+ for ( h=sc->hstem; h!=NULL ; h=h->next )
+ h->used = false;
+ for ( h=sc->vstem; h!=NULL ; h=h->next )
+ h->used = false;
+
+ mc = 0;
+
+ while ( mc<sizeof(masks)/sizeof(masks[0]) ) {
+ memset(masks[mc],'\0',sizeof(HintMask));
+ if ( !FigureCounters(sc->hstem,masks[mc]) && !FigureCounters(sc->vstem,masks[mc]))
+ break;
+ ++mc;
+ }
+ if ( mc!=0 ) {
+ sc->countermask_cnt = mc;
+ sc->countermasks = galloc(mc*sizeof(HintMask));
+ for ( i=0; i<mc ; ++i )
+ memcpy(sc->countermasks[i],masks[i],sizeof(HintMask));
+ }
+}
+
+void SCClearHintMasks(SplineChar *sc,int counterstoo) {
+ MMSet *mm = sc->parent->mm;
+ int i;
+
+ if ( mm==NULL )
+ _SCClearHintMasks(sc,counterstoo);
+ else {
+ for ( i=0; i<mm->instance_count; ++i ) {
+ if ( sc->orig_pos<mm->instances[i]->glyphcnt )
+ _SCClearHintMasks(mm->instances[i]->glyphs[sc->orig_pos],counterstoo);
+ }
+ if ( sc->orig_pos<mm->normal->glyphcnt )
+ _SCClearHintMasks(mm->normal->glyphs[sc->orig_pos],counterstoo);
+ }
+}
+
+static StemInfo *OnHHint(SplinePoint *sp, StemInfo *s) {
+ StemInfo *possible=NULL;
+ HintInstance *hi;
+
+ if ( sp==NULL )
+return( NULL );
+
+ for ( ; s!=NULL; s=s->next ) {
+ if ( sp->me.y<s->start )
+return( possible );
+ if ( s->start==sp->me.y || s->start+s->width==sp->me.y ) {
+ if ( !s->hasconflicts )
+return( s );
+ for ( hi=s->where; hi!=NULL; hi=hi->next ) {
+ if ( hi->begin<=sp->me.x && hi->end>=sp->me.x )
+return( s );
+ }
+ if ( !s->used )
+ possible = s;
+ }
+ }
+return( possible );
+}
+
+static StemInfo *OnVHint(SplinePoint *sp, StemInfo *s) {
+ StemInfo *possible=NULL;
+ HintInstance *hi;
+
+ if ( sp==NULL )
+return( NULL );
+
+ for ( ; s!=NULL; s=s->next ) {
+ if ( sp->me.x<s->start )
+return( possible );
+ if ( s->start==sp->me.x || s->start+s->width==sp->me.x ) {
+ if ( !s->hasconflicts )
+return( s );
+ for ( hi=s->where; hi!=NULL; hi=hi->next ) {
+ if ( hi->begin<=sp->me.y && hi->end>=sp->me.y )
+return( s );
+ }
+ if ( !s->used )
+ possible = s;
+ }
+ }
+return( possible );
+}
+
+/* Does h have a conflict with any of the stems in the list which have bits */
+/* set in the mask */
+static int ConflictsWithMask(StemInfo *stems, HintMask mask,StemInfo *h) {
+ while ( stems!=NULL && stems->start<h->start+h->width ) {
+ if ( stems->start+stems->width>=h->start && stems!=h ) {
+ if ( stems->hintnumber!=-1 &&
+ (mask[stems->hintnumber>>3]&(0x80>>(stems->hintnumber&7))) )
+return( true );
+ }
+ stems = stems->next;
+ }
+return( false );
+}
+
+/* All instances of a MM set must have the same hint mask at all points */
+static void FigureHintMask(SplineChar *scs[MmMax], SplinePoint *to[MmMax], int instance_count,
+ HintMask mask) {
+ StemInfo *s;
+ int i;
+ SplinePoint *sp;
+
+ memset(mask,'\0',sizeof(HintMask));
+
+ /* Install all hints that are always active */
+ i=0; {
+ SplineChar *sc = scs[i];
+
+ if ( sc==NULL )
+return;
+
+ for ( s=sc->hstem; s!=NULL; s=s->next )
+ if ( s->hintnumber!=-1 && !s->hasconflicts )
+ mask[s->hintnumber>>3] |= (0x80>>(s->hintnumber&7));
+ for ( s=sc->vstem; s!=NULL; s=s->next )
+ if ( s->hintnumber!=-1 && !s->hasconflicts )
+ mask[s->hintnumber>>3] |= (0x80>>(s->hintnumber&7));
+
+ if ( sc->hconflicts ) {
+ for ( sp=to[i]; sp!=NULL; ) {
+ s = OnHHint(sp,sc->hstem);
+ if ( s!=NULL && s->hintnumber!=-1 ) {
+ if ( ConflictsWithMask(scs[i]->hstem,mask,s))
+ break;
+ mask[s->hintnumber>>3] |= (0x80>>(s->hintnumber&7));
+ }
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( to[i]==sp )
+ break;
+ }
+ }
+ if ( sc->vconflicts ) {
+ for ( sp=to[i]; sp!=NULL; ) {
+ s = OnVHint(sp,sc->vstem);
+ if ( s!=NULL && s->hintnumber!=-1 ) {
+ if ( ConflictsWithMask(scs[i]->vstem,mask,s))
+ break;
+ mask[s->hintnumber>>3] |= (0x80>>(s->hintnumber&7));
+ }
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( to[i]==sp )
+ break;
+ }
+ }
+ }
+ for ( i=0; i<instance_count; ++i ) if ( to[i]!=NULL ) {
+ chunkfree(to[i]->hintmask,sizeof(HintMask));
+ to[i]->hintmask = chunkalloc(sizeof(HintMask));
+ memcpy(to[i]->hintmask,mask,sizeof(HintMask));
+ }
+}
+
+static int TestHintMask(SplineChar *scs[MmMax], SplinePoint *to[MmMax], int instance_count,
+ HintMask mask) {
+ StemInfo *h=NULL, *v=NULL;
+ int i;
+
+ for ( i=0; i<instance_count; ++i ) {
+ SplineChar *sc = scs[i];
+
+ if ( sc==NULL || (!sc->hconflicts && !sc->vconflicts ))
+ continue;
+
+ /* Does this point lie on any hints? */
+ if ( scs[i]->hconflicts )
+ h = OnHHint(to[i],sc->hstem);
+ if ( scs[i]->vconflicts )
+ v = OnVHint(to[i],sc->vstem);
+
+ /* Need to set this hint */
+ if ( (h!=NULL && h->hintnumber!=-1 && (mask[h->hintnumber>>3]&(0x80>>(h->hintnumber&7)))==0 ) ||
+ (v!=NULL && v->hintnumber!=-1 && (mask[v->hintnumber>>3]&(0x80>>(v->hintnumber&7)))==0 ))
+ break;
+ }
+ if ( i==instance_count ) /* All hint masks were ok */
+return( false );
+
+ FigureHintMask(scs,to,instance_count,mask);
+return( true );
+}
+
+static void UnnumberHints(SplineChar *sc) {
+ StemInfo *h;
+
+ for ( h=sc->hstem; h!=NULL; h=h->next )
+ h->hintnumber = -1;
+ for ( h=sc->vstem; h!=NULL; h=h->next )
+ h->hintnumber = -1;
+}
+
+static int NumberHints(SplineChar *sc) {
+ StemInfo *h;
+ int hcnt=0;
+
+ for ( h=sc->hstem; h!=NULL; h=h->next )
+ h->hintnumber = hcnt>=HntMax ? -1 : hcnt++;
+ for ( h=sc->vstem; h!=NULL; h=h->next )
+ h->hintnumber = hcnt>=HntMax ? -1 : hcnt++;
+return( hcnt );
+}
+
+static void UntickHints(SplineChar *sc) {
+ StemInfo *h;
+
+ for ( h=sc->hstem; h!=NULL; h=h->next )
+ h->used = false;
+ for ( h=sc->vstem; h!=NULL; h=h->next )
+ h->used = false;
+}
+
+struct coords {
+ real coords[MmMax];
+ struct coords *next;
+};
+
+typedef struct mmh {
+ StemInfo *hints[MmMax], *map[MmMax];
+ struct coords *where;
+ struct mmh *next;
+} MMH;
+
+static void AddCoord(MMH *mmh,SplinePoint *sps[MmMax],int instance_count, int ish) {
+ struct coords *coords;
+ int i;
+
+ coords = chunkalloc(sizeof(struct coords));
+ coords->next = mmh->where;
+ mmh->where = coords;
+ if ( ish )
+ for ( i=0; i<instance_count; ++i )
+ coords->coords[i] = sps[i]->me.x;
+ else
+ for ( i=0; i<instance_count; ++i )
+ coords->coords[i] = sps[i]->me.y;
+}
+
+static MMH *AddHintSet(MMH *hints,StemInfo *h[MmMax], int instance_count,
+ SplinePoint *sps[MmMax], int ish) {
+ int i, cnt, bestc;
+ MMH *test, *best;
+
+ for ( i=0; i<instance_count; ++i )
+ if ( h[i]==NULL )
+return( hints );
+
+ best = NULL; bestc = 0;
+ for ( test=hints; test!=NULL; test=test->next ) {
+ cnt = 0;
+ for ( i=0; i<instance_count; ++i )
+ if ( test->hints[i]==h[i] )
+ ++cnt;
+ if ( cnt==instance_count ) {
+ AddCoord(test,sps,instance_count,ish);
+return( hints );
+ }
+ if ( cnt>bestc ) {
+ bestc = cnt;
+ best = test;
+ }
+ }
+ test = chunkalloc(sizeof(MMH));
+ test->next = hints;
+ AddCoord(test,sps,instance_count,ish);
+ for ( i=0; i<instance_count; ++i )
+ test->hints[i]=h[i];
+ if ( bestc!=0 ) {
+ for ( i=0; i<instance_count; ++i ) {
+ if ( best->hints[i]==h[i] ) {
+ h[i]->hasconflicts = true;
+ test->map[i] = chunkalloc(sizeof(StemInfo));
+ *test->map[i] = *h[i];
+ test->map[i]->where = NULL;
+ test->map[i]->used = true;
+ h[i]->next = test->map[i];
+ } else
+ test->map[i] = h[i];
+ }
+ } else {
+ for ( i=0; i<instance_count; ++i )
+ test->map[i]=h[i];
+ }
+return( test );
+}
+
+static int CompareMMH(MMH *mmh1,MMH *mmh2, int instance_count) {
+ int i;
+
+ if ( mmh1->map[0]==NULL )
+return( 1 );
+ if ( mmh2->map[0]==NULL )
+return( -1 );
+
+ for ( i=0; i<instance_count; ++i ) {
+ if ( mmh1->map[i]->start!=mmh2->map[i]->start ) {
+ if ( mmh1->map[i]->start > mmh2->map[i]->start )
+return( 1 );
+ else
+return( -1 );
+ }
+ }
+ for ( i=0; i<instance_count; ++i ) {
+ if ( mmh1->map[i]->width!=mmh2->map[i]->width ) {
+ if ( mmh1->map[i]->width > mmh2->map[i]->width )
+return( 1 );
+ else
+return( -1 );
+ }
+ }
+return( 0 );
+}
+
+static MMH *SortMMH(MMH *head,int instance_count) {
+ MMH *mmh, *p, *smallest, *psmallest, *test, *ptest;
+
+ for ( mmh = head, p=NULL; mmh!=NULL ; ) {
+ smallest = mmh; psmallest = p;
+ ptest = mmh; test = mmh->next;
+ while ( test!=NULL ) {
+ if ( CompareMMH(test,smallest,instance_count)<0 ) {
+ smallest = test;
+ psmallest = ptest;
+ }
+ ptest = test;
+ test = test->next;
+ }
+ if ( smallest!=mmh ) {
+ if ( p==NULL )
+ head = smallest;
+ else
+ p->next = smallest;
+ if ( mmh->next==smallest ) {
+ mmh->next = smallest->next;
+ smallest->next = mmh;
+ } else {
+ test = mmh->next;
+ mmh->next = smallest->next;
+ smallest->next = test;
+ psmallest->next = mmh;
+ }
+ }
+ p = smallest;
+ mmh = smallest->next;
+ }
+return( head );
+}
+
+static int NumberMMH(MMH *mmh,int hstart,int instance_count) {
+ int i;
+ HintInstance *hi, *n;
+ struct coords *coords;
+
+ while ( mmh!=NULL ) {
+ for ( i=0; i<instance_count; ++i ) {
+ StemInfo *h = mmh->map[i];
+ if ( h==NULL )
+ continue;
+
+ h->hintnumber = hstart;
+
+ for ( hi=h->where; hi!=NULL; hi=n ) {
+ n = hi->next;
+ chunkfree(hi,sizeof(HintInstance));
+ }
+ h->where = NULL;
+ for ( coords=mmh->where; coords!=NULL; coords = coords->next ) {
+ hi = chunkalloc(sizeof(HintInstance));
+ hi->next = h->where;
+ h->where = hi;
+ hi->begin = coords->coords[i]-1;
+ hi->end = coords->coords[i]+1;
+ }
+ }
+ if ( mmh->map[0]!=NULL ) ++hstart;
+ mmh = mmh->next;
+ }
+return( hstart );
+}
+
+static void SortMMH2(SplineChar *scs[MmMax],MMH *mmh,int instance_count,int ish) {
+ int i;
+ StemInfo *h, *n;
+ MMH *m;
+
+ for ( i=0; i<instance_count; ++i ) {
+ for ( h= ish ? scs[i]->hstem : scs[i]->vstem; h!=NULL; h=n ) {
+ n = h->next;
+ if ( h->hintnumber==-1 )
+ StemInfoFree(h);
+ }
+ n = NULL;
+ for ( m = mmh ; m!=NULL; m=m->next ) {
+ h = m->map[i];
+ if ( n!=NULL )
+ n->next = h;
+ else if ( ish )
+ scs[i]->hstem = h;
+ else
+ scs[i]->vstem = h;
+ n = h;
+ }
+ if ( n!=NULL )
+ n->next = NULL;
+ else if ( ish )
+ scs[i]->hstem = NULL;
+ else
+ scs[i]->vstem = NULL;
+ }
+}
+
+static void MMHFreeList(MMH *mmh) {
+ MMH *mn;
+ struct coords *c, *n;
+
+ for ( ; mmh!=NULL; mmh = mn ) {
+ mn = mmh->next;
+ for ( c=mmh->where; c!=NULL; c=n ) {
+ n = c->next;
+ chunkfree(c,sizeof(struct coords));
+ }
+ chunkfree(mmh,sizeof(struct coords));
+ }
+}
+
+static void SplResolveSplitHints(SplineChar *scs[MmMax], SplineSet *spl[MmMax],
+ int instance_count, MMH **hs, MMH **vs) {
+ SplinePoint *to[MmMax];
+ StemInfo *h[MmMax], *v[MmMax];
+ int i, anymore;
+
+ forever {
+ for ( i=0; i<instance_count; ++i ) {
+ if ( spl[i]!=NULL )
+ to[i] = spl[i]->first;
+ else
+ to[i] = NULL;
+ }
+ forever {
+ for ( i=0; i<instance_count; ++i ) {
+ h[i] = OnHHint(to[i],scs[i]->hstem);
+ v[i] = OnVHint(to[i],scs[i]->vstem);
+ }
+ *hs = AddHintSet(*hs,h,instance_count,to,true);
+ *vs = AddHintSet(*vs,v,instance_count,to,false);
+ anymore = false;
+ for ( i=0; i<instance_count; ++i ) if ( to[i]!=NULL ) {
+ if ( to[i]->next==NULL ) to[i] = NULL;
+ else {
+ to[i] = to[i]->next->to;
+ if ( to[i]==spl[i]->first ) to[i] = NULL;
+ }
+ if ( to[i]!=NULL ) anymore = true;
+ }
+ if ( !anymore )
+ break;
+ }
+ anymore = false;
+ for ( i=0; i<instance_count; ++i ) {
+ if ( spl[i]!=NULL )
+ spl[i] = spl[i]->next;
+ if ( spl[i]!=NULL ) anymore = true;
+ }
+ if ( !anymore )
+ break;
+ }
+}
+
+static void ResolveSplitHints(SplineChar *scs[16],int instance_count) {
+ /* It is possible for a single hint in one mm instance to split into two */
+ /* in a different MM set. For example, we have two stems which happen */
+ /* to line up in one instance but which do not in another instance. */
+ /* It is even possible that there could be no instance with any conflicts */
+ /* but some of the intermediate forms might conflict. */
+ /* We can't deal (nor can postscript) with the case where hints change order*/
+ SplinePointList *spl[MmMax];
+ RefChar *ref[MmMax];
+ int i, hcnt, hmax=0, anymore;
+ MMH *hs=NULL, *vs=NULL;
+
+ for ( i=0; i<instance_count; ++i ) {
+ hcnt = NumberHints(scs[i]);
+ UntickHints(scs[i]);
+ if ( hcnt>hmax ) hmax = hcnt;
+ spl[i] = scs[i]->layers[ly_fore].splines;
+ }
+ if ( hmax==0 )
+return;
+
+ SplResolveSplitHints(scs,spl,instance_count,&hs,&vs);
+ anymore = false;
+ for ( i=0; i<instance_count; ++i ) {
+ ref[i] = scs[i]->layers[ly_fore].refs;
+ if ( ref[i]!=NULL ) anymore = true;
+ }
+ while ( anymore ) {
+ for ( i=0; i<instance_count; ++i )
+ spl[i] = ( ref[i]!=NULL ) ? ref[i]->layers[0].splines : NULL;
+ SplResolveSplitHints(scs,spl,instance_count,&hs,&vs);
+ anymore = false;
+ for ( i=0; i<instance_count; ++i ) {
+ if ( ref[i]!=NULL ) {
+ ref[i] = ref[i]->next;
+ if ( ref[i]!=NULL ) anymore = true;
+ }
+ }
+ }
+
+ for ( i=0; i<instance_count; ++i )
+ UnnumberHints(scs[i]);
+ hs = SortMMH(hs,instance_count);
+ vs = SortMMH(vs,instance_count);
+ hcnt = NumberMMH(hs,0,instance_count);
+ hcnt = NumberMMH(vs,hcnt,instance_count);
+ SortMMH2(scs,hs,instance_count,true);
+ SortMMH2(scs,vs,instance_count,false);
+ MMHFreeList(hs);
+ MMHFreeList(vs);
+}
+
+static int SplFigureHintMasks(SplineChar *scs[MmMax], SplineSet *spl[MmMax],
+ int instance_count, HintMask mask, int inited) {
+ SplinePoint *to[MmMax];
+ int i, anymore;
+
+ anymore = false;
+ for ( i=0; i<instance_count; ++i ) {
+ if ( spl[i]!=NULL ) {
+ SplineSetReverse(spl[i]);
+ to[i] = spl[i]->first;
+ anymore = true;
+ } else
+ to[i] = NULL;
+ }
+
+ /* Assign the initial hint mask */
+ if ( anymore && !inited ) {
+ FigureHintMask(scs,to,instance_count,mask);
+ inited = true;
+ }
+
+ forever {
+ for ( i=0; i<instance_count; ++i ) {
+ if ( spl[i]!=NULL )
+ to[i] = spl[i]->first;
+ else
+ to[i] = NULL;
+ }
+ forever {
+ TestHintMask(scs,to,instance_count,mask);
+ anymore = false;
+ for ( i=0; i<instance_count; ++i ) if ( to[i]!=NULL ) {
+ if ( to[i]->next==NULL ) to[i] = NULL;
+ else {
+ to[i] = to[i]->next->to;
+ if ( to[i]==spl[i]->first ) to[i] = NULL;
+ }
+ if ( to[i]!=NULL ) anymore = true;
+ }
+ if ( !anymore )
+ break;
+ }
+ anymore = false;
+ for ( i=0; i<instance_count; ++i ) {
+ if ( spl[i]!=NULL ) {
+ SplineSetReverse(spl[i]);
+ spl[i] = spl[i]->next;
+ }
+ if ( spl[i]!=NULL ) {
+ anymore = true;
+ SplineSetReverse(spl[i]);
+ }
+ }
+ if ( !anymore )
+ break;
+ }
+return( inited );
+}
+
+void SCFigureHintMasks(SplineChar *sc) {
+ SplineChar *scs[MmMax];
+ SplinePointList *spl[MmMax];
+ RefChar *ref[MmMax];
+ MMSet *mm = sc->parent->mm;
+ int i, instance_count, conflicts, anymore, inited;
+ HintMask mask;
+
+ if ( mm==NULL ) {
+ scs[0] = sc;
+ instance_count = 1;
+ SCClearHintMasks(sc,false);
+ } else {
+ if ( mm->apple )
+return;
+ instance_count = mm->instance_count;
+ for ( i=0; i<instance_count; ++i )
+ if ( sc->orig_pos < mm->instances[i]->glyphcnt ) {
+ scs[i] = mm->instances[i]->glyphs[sc->orig_pos];
+ SCClearHintMasks(scs[i],false);
+ }
+ ResolveSplitHints(scs,instance_count);
+ }
+ conflicts = false;
+ for ( i=0; i<instance_count; ++i ) {
+ NumberHints(scs[i]);
+ if ( scs[i]->hconflicts || scs[i]->vconflicts )
+ conflicts = true;
+ }
+ if ( !conflicts && instance_count==1 ) { /* All hints always active */
+ SCFigureSimpleCounterMasks(sc);
+return; /* In an MM font we may still need to resolve things like different numbers of hints */
+ }
+
+ for ( i=0; i<instance_count; ++i ) {
+ spl[i] = scs[i]->layers[ly_fore].splines;
+ ref[i] = scs[i]->layers[ly_fore].refs;
+ }
+ inited = SplFigureHintMasks(scs,spl,instance_count,mask,false);
+ forever {
+ for ( i=0; i<instance_count; ++i ) {
+ if ( ref[i]!=NULL )
+ spl[i] = ref[i]->layers[0].splines;
+ }
+ inited = SplFigureHintMasks(scs,spl,instance_count,mask,inited);
+ anymore = false;
+ for ( i=0; i<instance_count; ++i ) {
+ if ( ref[i]!=NULL ) {
+ ref[i] = ref[i]->next;
+ if ( ref[i]!=NULL ) anymore = true;
+ }
+ }
+ if ( !anymore )
+ break;
+ }
+ if ( instance_count==1 )
+ SCFigureSimpleCounterMasks(sc);
+}
+#ifndef LUA_FF_LIB
+
+static HintInstance *StemAddHIFromActive(struct stemdata *stem,int major) {
+ int i;
+ HintInstance *head = NULL, *cur, *t;
+ double mino, maxo;
+ double dir = ((real *) &stem->unit.x)[major]<0 ? -1 : 1;
+
+ for ( i=0; i<stem->activecnt; ++i ) {
+ mino = dir*stem->active[i].start + ((real *) &stem->left.x)[major];
+ maxo = dir*stem->active[i].end + ((real *) &stem->left.x)[major];
+ cur = chunkalloc(sizeof(HintInstance));
+ if ( dir>0 ) {
+ cur->begin = mino;
+ cur->end = maxo;
+ if ( head==NULL )
+ head = cur;
+ else
+ t->next = cur;
+ t = cur;
+ } else {
+ cur->begin = maxo;
+ cur->end = mino;
+ cur->next = head;
+ head = cur;
+ }
+ }
+return( head );
+}
+
+static void GDReassignPoint(struct glyphdata *gd,struct stemdata *stem,struct pointdata **_pd) {
+ struct pointdata *pd = *_pd;
+ BasePoint *dir;
+ int i,j;
+ struct stemdata *potential;
+ int chunk, is_r;
+
+ if ( pd==NULL )
+return;
+ if ( pd->nextstem==stem )
+ dir = &pd->nextunit;
+ else if ( pd->prevstem==stem )
+ dir = &pd->prevunit;
+ else {
+ *_pd = NULL;
+return;
+ }
+
+ potential = NULL; chunk = is_r = -1;
+ for ( i=0; i<gd->stemcnt; ++i ) {
+ struct stemdata *stem = &gd->stems[i];
+ if ( !stem->toobig && UnitsParallel(dir,&stem->unit)) {
+ for ( j=0; j<stem->chunk_cnt; ++j ) {
+ if ( stem->chunks[j].lpotential==pd ) {
+ if ( potential==stem )
+ /* Do Nothing */;
+ else if ( potential!=NULL )
+return;
+ else {
+ potential = stem; chunk = j; is_r = false;
+ }
+ } else if ( stem->chunks[j].rpotential==pd ) {
+ if ( potential==stem )
+ /* Do Nothing */;
+ else if ( potential!=NULL )
+return;
+ else {
+ potential = stem; chunk = j; is_r = true;
+ }
+ }
+ }
+ }
+ }
+
+ if ( potential!=NULL ) {
+ if ( is_r && potential->chunks[chunk].r==NULL ) {
+ potential->chunks[chunk].r = pd;
+ *_pd = NULL;
+ } else if ( !is_r && potential->chunks[chunk].l==NULL ) {
+ potential->chunks[chunk].l = pd;
+ *_pd = NULL;
+ }
+ }
+}
+
+
+static void GDPreprocess(struct glyphdata *gd) {
+ int i,j;
+
+ /* Remove points from unusable stem and see if we can use 'em elsewhere */
+ for ( i=0; i<gd->stemcnt; ++i ) {
+ struct stemdata *stem = &gd->stems[i];
+ if ( stem->toobig ) {
+ for ( j=0; j<stem->chunk_cnt; ++j ) {
+ GDReassignPoint(gd,stem,&stem->chunks[j].l);
+ GDReassignPoint(gd,stem,&stem->chunks[j].r);
+ }
+ }
+ }
+
+ for ( i=0; i<gd->pcnt; ++i ) {
+ struct pointdata *pd = &gd->points[i];
+ if ( pd->colinear ) {
+ if ( pd->nextstem==NULL )
+ pd->nextstem = pd->prevstem;
+ else if ( pd->prevstem==NULL )
+ pd->prevstem = pd->nextstem;
+ }
+ if ( pd->colinear && pd->nextstem!=NULL && pd->nextstem!=pd->prevstem ) {
+ double width1, width2;
+ if ( pd->nextunit.x==0 ) {
+ if ( (width1 = pd->nextstem->left.x-pd->nextstem->right.x )<0 )
+ width1 = -width1;
+ if ( (width2 = pd->prevstem->left.x-pd->prevstem->right.x )<0 )
+ width2 = -width2;
+ } else {
+ if ( (width1 = pd->nextstem->left.y-pd->nextstem->right.y )<0 )
+ width1 = -width1;
+ if ( (width2 = pd->prevstem->left.y-pd->prevstem->right.y )<0 )
+ width2 = -width2;
+ }
+ if ( width1>width2 && pd->nextstem->chunk_cnt<=1 ) {
+ if ( pd->nextstem->chunk_cnt==1 )
+ pd->nextstem->chunks[0].l = pd->nextstem->chunks[0].r = NULL;
+ } else if ( width1<width2 && pd->prevstem->chunk_cnt<=1 ) {
+ if ( pd->prevstem->chunk_cnt==1 )
+ pd->prevstem->chunks[0].l = pd->prevstem->chunks[0].r = NULL;
+ }
+ }
+ }
+}
+
+static StemInfo *GDFindStems(struct glyphdata *gd, int major) {
+ int i;
+ StemInfo *head = NULL, *cur, *p, *t;
+ struct stemdata *stem;
+ int other = !major;
+
+ for ( i=0; i<gd->stemcnt; ++i ) {
+ stem = &gd->stems[i];
+ if ( stem->toobig )
+ continue;
+ if ((( stem->unit.y>.99 || stem->unit.y<-.99) && major==1 ) ||
+ (( stem->unit.x>.99 || stem->unit.x<-.99) && major==0 )) {
+ double l = (&stem->left.x)[other], r = (&stem->right.x)[other];
+ int j, hasl=false, hasr=false;
+ for ( j=0; j<stem->chunk_cnt; ++j ) {
+ if ( stem->chunks[j].l!=NULL ) hasl = true;
+ if ( stem->chunks[j].r!=NULL ) hasr = true;
+ }
+ if ( !hasl || !hasr )
+ continue;
+ cur = chunkalloc(sizeof(StemInfo));
+ if ( l<r ) {
+ cur->start = l;
+ cur->width = r - l;
+ cur->haspointleft = hasl;
+ cur->haspointright = hasr;
+ } else {
+ cur->start = r;
+ cur->width = l - r;
+ cur->haspointleft = hasr;
+ cur->haspointright = hasl;
+ }
+ for ( p=NULL, t=head; t!=NULL ; p=t, t=t->next ) {
+ if ( cur->start<=t->start )
+ break;
+ }
+ cur->next = t;
+ if ( p==NULL )
+ head = cur;
+ else
+ p->next = cur;
+ cur->where = StemAddHIFromActive(stem,major);
+ }
+ }
+ head = StemRemoveFlexCandidates(head);
+return( head );
+}
+
+void _SplineCharAutoHint( SplineChar *sc, BlueData *bd, struct glyphdata *gd2 ) {
+ struct glyphdata *gd;
+
+ SCPreserveHints(sc);
+ StemInfosFree(sc->vstem); sc->vstem=NULL;
+ StemInfosFree(sc->hstem); sc->hstem=NULL;
+ DStemInfosFree(sc->dstem); sc->dstem=NULL;
+ MinimumDistancesFree(sc->md); sc->md=NULL;
+
+ free(sc->countermasks);
+ sc->countermasks = NULL; sc->countermask_cnt = 0;
+ /* We'll free the hintmasks when we call SCFigureHintMasks */
+
+ sc->changedsincelasthinted = false;
+ sc->manualhints = false;
+
+ if ( (gd=gd2)==NULL )
+ gd = GlyphDataBuild(sc,true);
+ if ( gd!=NULL ) {
+ GDPreprocess(gd);
+ sc->vstem = GDFindStems(gd,1);
+ sc->hstem = GDFindStems(gd,0);
+ if ( gd2==NULL ) GlyphDataFree(gd);
+ sc->hstem = CheckForGhostHints(sc->hstem,sc,bd);
+ }
+
+ AutoHintRefs(sc,bd,false);
+}
+
+void SplineCharAutoHint( SplineChar *sc, BlueData *bd ) {
+ MMSet *mm = sc->parent->mm;
+ int i;
+
+ if ( mm==NULL )
+ _SplineCharAutoHint(sc,bd,NULL);
+ else {
+ for ( i=0; i<mm->instance_count; ++i )
+ if ( sc->orig_pos < mm->instances[i]->glyphcnt )
+ _SplineCharAutoHint(mm->instances[i]->glyphs[sc->orig_pos],NULL,NULL);
+ if ( sc->orig_pos < mm->normal->glyphcnt )
+ _SplineCharAutoHint(mm->normal->glyphs[sc->orig_pos],NULL,NULL);
+ }
+ SCFigureHintMasks(sc);
+ SCUpdateAll(sc);
+}
+
+void SFSCAutoHint( SplineChar *sc, BlueData *bd ) {
+ RefChar *ref;
+
+ if ( sc->ticked )
+return;
+ for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
+ if ( !ref->sc->ticked )
+ SFSCAutoHint(ref->sc,bd);
+ }
+ sc->ticked = true;
+ SplineCharAutoHint(sc,bd);
+}
+
+int SFNeedsAutoHint( SplineFont *_sf) {
+ int i,k;
+ SplineFont *sf;
+
+ k=0;
+ do {
+ sf = _sf->subfontcnt==0 ? _sf : _sf->subfonts[k];
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ if ( sf->glyphs[i]->changedsincelasthinted &&
+ !sf->glyphs[i]->manualhints )
+return( true );
+ }
+ ++k;
+ } while ( k<_sf->subfontcnt );
+return( false );
+}
+
+void SplineFontAutoHint( SplineFont *_sf) {
+ int i,k;
+ SplineFont *sf;
+ BlueData *bd = NULL, _bd;
+ SplineChar *sc;
+
+ if ( _sf->mm==NULL ) {
+ QuickBlues(_sf,&_bd);
+ bd = &_bd;
+ }
+
+ /* Tick the ones we don't want to AH, untick the ones that need AH */
+ k=0;
+ do {
+ sf = _sf->subfontcnt==0 ? _sf : _sf->subfonts[k];
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( (sc = sf->glyphs[i])!=NULL )
+ sc->ticked = ( !sc->changedsincelasthinted || sc->manualhints );
+ ++k;
+ } while ( k<_sf->subfontcnt );
+
+ k=0;
+ do {
+ sf = _sf->subfontcnt==0 ? _sf : _sf->subfonts[k];
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ if ( sf->glyphs[i]->changedsincelasthinted &&
+ !sf->glyphs[i]->manualhints )
+ SFSCAutoHint(sf->glyphs[i],bd);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next()) {
+ k = _sf->subfontcnt+1;
+ break;
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+ ++k;
+ } while ( k<_sf->subfontcnt );
+}
+
+void SplineFontAutoHintRefs( SplineFont *_sf) {
+ int i,k;
+ SplineFont *sf;
+ BlueData *bd = NULL, _bd;
+ SplineChar *sc;
+
+ if ( _sf->mm==NULL ) {
+ QuickBlues(_sf,&_bd);
+ bd = &_bd;
+ }
+
+ k=0;
+ do {
+ sf = _sf->subfontcnt==0 ? _sf : _sf->subfonts[k];
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( (sc = sf->glyphs[i])!=NULL ) {
+ if ( sc->changedsincelasthinted &&
+ !sc->manualhints &&
+ (sc->layers[ly_fore].refs!=NULL && sc->layers[ly_fore].splines==NULL)) {
+ SCPreserveHints(sc);
+ StemInfosFree(sc->vstem); sc->vstem=NULL;
+ StemInfosFree(sc->hstem); sc->hstem=NULL;
+ AutoHintRefs(sc,bd,true);
+ }
+ }
+ ++k;
+ } while ( k<_sf->subfontcnt );
+}
+#endif
+
+static void FigureStems( SplineFont *sf, real snaps[12], real cnts[12],
+ int which ) {
+ int i, j, k, cnt, smax=0, smin=2000;
+ real stemwidths[2000];
+ StemInfo *stems, *test;
+ int len;
+ HintInstance *hi;
+
+ memset(stemwidths,'\0',sizeof(stemwidths));
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ stems = which?sf->glyphs[i]->hstem:sf->glyphs[i]->vstem;
+ for ( test=stems; test!=NULL; test = test->next ) if ( !test->ghost ) {
+ if ( (j=test->width)<0 ) j= -j;
+ if ( j<2000 ) {
+ len = 0;
+ for ( hi=test->where; hi!=NULL; hi=hi->next )
+ len += hi->end-hi->begin;
+ if ( len==0 ) len = 100;
+ stemwidths[j] += len;
+ if ( smax<j ) smax=j;
+ if ( smin>j ) smin=j;
+ }
+ }
+ }
+
+ for ( i=smin, cnt=0; i<=smax; ++i ) {
+ if ( stemwidths[i]!=0 )
+ ++cnt;
+ }
+
+ if ( cnt>12 ) {
+ /* Merge width windows */
+ int windsize=3, j;
+ for ( i=smin; i<=smax; ++i ) if ( stemwidths[i]!=0 ) {
+ if ( (j = i-windsize)<0 ) j=0;
+ for ( ; j<smax && j<=i+windsize; ++j )
+ if ( stemwidths[i]<stemwidths[j] )
+ break;
+ if ( j==smax || j>i+windsize ) {
+ if ( (j = i-windsize)<0 ) j=0;
+ for ( ; j<smax && j<=i+windsize; ++j ) if ( j!=i ) {
+ stemwidths[i] += stemwidths[j];
+ stemwidths[j] = 0;
+ }
+ }
+ }
+ /* Merge adjacent widths */
+ for ( i=smin; i<=smax; ++i ) {
+ if ( stemwidths[i]!=0 && i<=smax-1 && stemwidths[i+1]!=0 ) {
+ if ( stemwidths[i]>stemwidths[i+1] ) {
+ stemwidths[i] += stemwidths[i+1];
+ stemwidths[i+1] = 0;
+ } else {
+ if ( i<=smax-2 && stemwidths[i+2] && stemwidths[i+2]<stemwidths[i+1] ) {
+ stemwidths[i+1] += stemwidths[i+2];
+ stemwidths[i+2] = 0;
+ }
+ stemwidths[i+1] += stemwidths[i];
+ stemwidths[i] = 0;
+ ++i;
+ }
+ }
+ }
+ for ( i=smin, cnt=0; i<=smax; ++i ) {
+ if ( stemwidths[i]!=0 )
+ ++cnt;
+ }
+ }
+ if ( cnt<=12 ) {
+ for ( i=smin, cnt=0; i<=smax; ++i ) {
+ if ( stemwidths[i]!=0 ) {
+ snaps[cnt] = i;
+ cnts[cnt++] = stemwidths[i];
+ }
+ }
+ } else { real firstbiggest=0;
+ for ( cnt = 0; cnt<12; ++cnt ) {
+ int biggesti=0;
+ real biggest=0;
+ for ( i=smin; i<=smax; ++i ) {
+ if ( stemwidths[i]>biggest ) { biggest = stemwidths[i]; biggesti=i; }
+ }
+ /* array must be sorted */
+ if ( biggest<firstbiggest/6 )
+ break;
+ for ( j=0; j<cnt; ++j )
+ if ( snaps[j]>biggesti )
+ break;
+ for ( k=cnt-1; k>=j; --k ) {
+ snaps[k+1] = snaps[k];
+ cnts[k+1]=cnts[k];
+ }
+ snaps[j] = biggesti;
+ cnts[j] = biggest;
+ stemwidths[biggesti] = 0;
+ if ( firstbiggest==0 ) firstbiggest = biggest;
+ }
+ }
+ for ( ; cnt<12; ++cnt ) {
+ snaps[cnt] = 0;
+ cnts[cnt] = 0;
+ }
+}
+
+void FindHStems( SplineFont *sf, real snaps[12], real cnt[12]) {
+ FigureStems(sf,snaps,cnt,1);
+}
+
+void FindVStems( SplineFont *sf, real snaps[12], real cnt[12]) {
+ FigureStems(sf,snaps,cnt,0);
+}
+
+static int IsFlexSmooth(SplinePoint *sp) {
+ BasePoint nvec, pvec;
+ double proj_same, proj_normal;
+
+ if ( sp->nonextcp || sp->noprevcp )
+return( false ); /* No continuity of slopes */
+
+ nvec.x = sp->nextcp.x - sp->me.x; nvec.y = sp->nextcp.y - sp->me.y;
+ pvec.x = sp->me.x - sp->prevcp.x; pvec.y = sp->me.y - sp->prevcp.y;
+
+ /* Avoid cases where the slopes are 180 out of phase */
+ if ( (proj_same = nvec.x*pvec.x + nvec.y*pvec.y)<=0 )
+return( false );
+ if ( (proj_normal = nvec.x*pvec.y - nvec.y*pvec.x)<0 )
+ proj_normal = -proj_normal;
+
+ /* Something is smooth if the normal projection is 0. Let's allow for */
+ /* some rounding errors */
+ if ( proj_same >= 16*proj_normal )
+return( true );
+
+return( false );
+}
+
+static int _SplineCharIsFlexible(SplineChar *sc, int blueshift) {
+ /* Need two splines
+ outer endpoints have same x (or y) values
+ inner point must be less than 20 horizontal (v) units from the outer points
+ inner point must also be less than BlueShift units (defaults to 7=>6)
+ (can increase BlueShift up to 21)
+ the inner point must be a local extremum
+ the inner point's cps must be at the x (or y) value as the extremum
+ (I think)
+ */
+ /* We want long, nearly straight stems. If the end-points should not have
+ continuous slopes, or if they do, they must be horizontal/vertical.
+ This is an heuristic requirement, not part of Adobe's spec.
+ */
+ SplineSet *spl;
+ SplinePoint *sp, *np, *pp;
+ int max=0, val;
+ RefChar *r;
+
+ if ( sc==NULL )
+return(false);
+
+ for ( spl = sc->layers[ly_fore].splines; spl!=NULL; spl=spl->next ) {
+ if ( spl->first->prev==NULL ) {
+ /* Mark everything on the open path as inflexible */
+ sp=spl->first;
+ while ( 1 ) {
+ sp->flexx = sp->flexy = false;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ }
+ continue; /* Ignore open paths */
+ }
+ sp=spl->first;
+ do {
+ if ( sp->next==NULL || sp->prev==NULL )
+ break;
+ np = sp->next->to;
+ pp = sp->prev->from;
+ if ( !pp->flexx && !pp->flexy ) {
+ sp->flexy = sp->flexx = 0;
+ val = 0;
+ if ( RealNear(sp->nextcp.x,sp->me.x) &&
+ RealNear(sp->prevcp.x,sp->me.x) &&
+ RealNear(np->me.x,pp->me.x) &&
+ !RealNear(np->me.x,sp->me.x) &&
+ (!IsFlexSmooth(pp) || RealNear(pp->nextcp.x,pp->me.x)) &&
+ (!IsFlexSmooth(np) || RealNear(np->prevcp.x,np->me.x)) &&
+ np->me.x-sp->me.x < blueshift &&
+ np->me.x-sp->me.x > -blueshift ) {
+ if ( (np->me.x>sp->me.x &&
+ np->prevcp.x<=np->me.x && np->prevcp.x>=sp->me.x &&
+ pp->nextcp.x<=pp->me.x && pp->prevcp.x>=sp->me.x ) ||
+ (np->me.x<sp->me.x &&
+ np->prevcp.x>=np->me.x && np->prevcp.x<=sp->me.x &&
+ pp->nextcp.x>=pp->me.x && pp->prevcp.x<=sp->me.x )) {
+ sp->flexx = true;
+ val = np->me.x-sp->me.x;
+ }
+ }
+ if ( RealNear(sp->nextcp.y,sp->me.y) &&
+ RealNear(sp->prevcp.y,sp->me.y) &&
+ RealNear(np->me.y,pp->me.y) &&
+ !RealNear(np->me.y,sp->me.y) &&
+ (!IsFlexSmooth(pp) || RealNear(pp->nextcp.y,pp->me.y)) &&
+ (!IsFlexSmooth(np) || RealNear(np->prevcp.y,np->me.y)) &&
+ np->me.y-sp->me.y < blueshift &&
+ np->me.y-sp->me.y > -blueshift ) {
+ if ( (np->me.y>sp->me.y &&
+ np->prevcp.y<=np->me.y && np->prevcp.y>=sp->me.y &&
+ pp->nextcp.y<=pp->me.y && pp->nextcp.y>=sp->me.y ) ||
+ (np->me.y<sp->me.y &&
+ np->prevcp.y>=np->me.y && np->prevcp.y<=sp->me.y &&
+ pp->nextcp.y>=pp->me.y && pp->nextcp.y<=sp->me.y )) {
+ sp->flexy = true;
+ val = np->me.y-sp->me.y;
+ }
+ }
+ if ( val<0 ) val = -val;
+ if ( val>max ) max = val;
+ }
+ sp = np;
+ } while ( sp!=spl->first );
+ }
+ sc->anyflexes = max>0;
+ if ( max==0 )
+ for ( r = sc->layers[ly_fore].refs; r!=NULL ; r=r->next )
+ if ( r->sc->anyflexes ) {
+ sc->anyflexes = true;
+ break;
+ }
+return( max );
+}
+
+static int MatchFlexes(MMSet *mm,int opos) {
+ int any=false, i;
+ SplineSet *spl[16];
+ SplinePoint *sp[16];
+ int mismatchx, mismatchy;
+
+ for ( i=0; i<mm->instance_count; ++i )
+ if ( opos<mm->instances[i]->glyphcnt && mm->instances[i]->glyphs[opos]!=NULL )
+ spl[i] = mm->instances[i]->glyphs[opos]->layers[ly_fore].splines;
+ else
+ spl[i] = NULL;
+ while ( spl[0]!=NULL ) {
+ for ( i=0; i<mm->instance_count; ++i )
+ if ( spl[i]!=NULL )
+ sp[i] = spl[i]->first;
+ else
+ sp[i] = NULL;
+ while ( sp[0]!=NULL ) {
+ mismatchx = mismatchy = false;
+ for ( i=1 ; i<mm->instance_count; ++i ) {
+ if ( sp[i]==NULL )
+ mismatchx = mismatchy = true;
+ else {
+ if ( sp[i]->flexx != sp[0]->flexx )
+ mismatchx = true;
+ if ( sp[i]->flexy != sp[0]->flexy )
+ mismatchy = true;
+ }
+ }
+ if ( mismatchx || mismatchy ) {
+ for ( i=0 ; i<mm->instance_count; ++i ) if ( sp[i]!=NULL ) {
+ if ( mismatchx ) sp[i]->flexx = false;
+ if ( mismatchy ) sp[i]->flexy = false;
+ }
+ }
+ if ( sp[0]->flexx || sp[0]->flexy )
+ any = true;
+ for ( i=0 ; i<mm->instance_count; ++i ) if ( sp[i]!=NULL ) {
+ if ( sp[i]->next==NULL ) sp[i] = NULL;
+ else sp[i] = sp[i]->next->to;
+ }
+ if ( sp[0] == spl[0]->first )
+ break;
+ }
+ for ( i=0; i<mm->instance_count; ++i )
+ if ( spl[i]!=NULL )
+ spl[i] = spl[i]->next;
+ }
+return( any );
+}
+
+int SplineCharIsFlexible(SplineChar *sc) {
+ char *pt;
+ int blueshift;
+ int i;
+ MMSet *mm;
+
+ pt = PSDictHasEntry(sc->parent->private,"BlueShift");
+ blueshift = 7; /* use default value here */
+ if ( pt!=NULL ) {
+ blueshift = strtol(pt,NULL,10);
+ if ( blueshift>21 ) blueshift = 21;
+ } else if ( PSDictHasEntry(sc->parent->private,"BlueValues")!=NULL )
+ blueshift = 7;
+ if ( sc->parent->mm==NULL )
+return( _SplineCharIsFlexible(sc,blueshift));
+
+ mm = sc->parent->mm;
+ for ( i = 0; i<mm->instance_count; ++i )
+ if ( sc->orig_pos<mm->instances[i]->glyphcnt && mm->instances[i]->glyphs[sc->orig_pos]!=NULL )
+ _SplineCharIsFlexible(mm->instances[i]->glyphs[sc->orig_pos],blueshift);
+return( MatchFlexes(mm,sc->orig_pos));
+}
+
+static void SCUnflex(SplineChar *sc) {
+ SplineSet *spl;
+ SplinePoint *sp;
+
+ for ( spl = sc->layers[ly_fore].splines; spl!=NULL; spl=spl->next ) {
+ /* Mark everything on the path as inflexible */
+ sp=spl->first;
+ while ( 1 ) {
+ sp->flexx = sp->flexy = false;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ }
+ sc->anyflexes = false;
+}
+
+static void FlexDependents(SplineChar *sc) {
+ struct splinecharlist *scl;
+
+ sc->anyflexes = true;
+ for ( scl = sc->dependents; scl!=NULL; scl=scl->next )
+ FlexDependents(scl->sc);
+}
+
+int SplineFontIsFlexible(SplineFont *sf,int flags) {
+ int i;
+ int max=0, val;
+ char *pt;
+ int blueshift;
+ /* if the return value is bigger than 6 and we don't have a BlueShift */
+ /* then we must set BlueShift to ret+1 before saving private dictionary */
+ /* If the first point in a spline set is flexible, then we must rotate */
+ /* the splineset */
+
+ if ( flags&(ps_flag_nohints|ps_flag_noflex)) {
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ SCUnflex(sf->glyphs[i]);
+return( 0 );
+ }
+
+ pt = PSDictHasEntry(sf->private,"BlueShift");
+ blueshift = 21; /* maximum posible flex, not default */
+ if ( pt!=NULL ) {
+ blueshift = strtol(pt,NULL,10);
+ if ( blueshift>21 ) blueshift = 21;
+ } else if ( PSDictHasEntry(sf->private,"BlueValues")!=NULL )
+ blueshift = 7; /* The BlueValues array may depend on BlueShift having its default value */
+
+ for ( i=0; i<sf->glyphcnt; ++i )
+ if ( sf->glyphs[i]!=NULL ) if ( sf->glyphs[i]!=NULL ) {
+ val = _SplineCharIsFlexible(sf->glyphs[i],blueshift);
+ if ( val>max ) max = val;
+ if ( sf->glyphs[i]->anyflexes )
+ FlexDependents(sf->glyphs[i]);
+ }
+return( max );
+}
+
+
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/charview.c b/Build/source/libs/luafontforge/fontforge/fontforge/charview.c
new file mode 100644
index 00000000000..82434d8dbf9
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/charview.c
@@ -0,0 +1,9513 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* #define TEST_O2 */
+
+#include "pfaeditui.h"
+#include <math.h>
+#include <locale.h>
+#ifndef FONTFORGE_CONFIG_GTK
+# include <ustring.h>
+# include <utype.h>
+# include <gresource.h>
+# ifdef FONTFORGE_CONFIG_GDRAW
+extern int _GScrollBar_Width;
+# include <gkeysym.h>
+# endif
+#endif
+#ifdef HAVE_IEEEFP_H
+# include <ieeefp.h> /* Solaris defines isnan in ieeefp rather than math.h */
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+extern struct lconv localeinfo;
+extern char *coord_sep;
+struct cvshows CVShows = {
+ 1, /* show foreground */
+ 1, /* show background */
+ 1, /* show grid plane */
+ 1, /* show horizontal hints */
+ 1, /* show vertical hints */
+ 1, /* show diagonal hints */
+ 1, /* show points */
+ 0, /* show filled */
+ 1, /* show rulers */
+ 1, /* show points which are to be rounded to the ttf grid and aren't on hints */
+ 1, /* show x minimum distances */
+ 1, /* show y minimum distances */
+ 1, /* show horizontal metrics */
+ 0, /* show vertical metrics */
+ 0, /* mark extrema */
+ 0, /* show points of inflection */
+ 1, /* show blue values */
+ 1, /* show family blues too */
+ 1, /* show anchor points */
+ 1, /* show control point info when moving them */
+ 1, /* show tabs containing names of former glyphs */
+ 1 /* show side bearings */
+};
+static Color pointcol = 0xff0000;
+static Color firstpointcol = 0x707000;
+static Color selectedpointcol = 0xc8c800;
+static int selectedpointwidth = 2;
+static Color extremepointcol = 0xc00080;
+static Color pointofinflectioncol = 0x008080;
+Color nextcpcol = 0x007090;
+Color prevcpcol = 0xcc00cc;
+static Color selectedcpcol = 0xffffff;
+static Color coordcol = 0x808080;
+Color widthcol = 0x000000;
+static Color widthselcol = 0x00ff00;
+static Color widthgridfitcol = 0x009800;
+static Color lcaretcol = 0x909040;
+static Color rastercol = 0xa0a0a0;
+static Color rasternewcol = 0x909090;
+static Color rasteroldcol = 0xc0c0c0;
+static Color rastergridcol = 0xb0b0ff;
+static Color rasterdarkcol = 0x606060;
+static Color italiccoordcol = 0x909090;
+static Color metricslabelcol = 0x00000;
+static Color hintlabelcol = 0x00ffff;
+static Color bluevalstipplecol = 0x8080ff;
+static Color fambluestipplecol = 0xff7070;
+static Color mdhintcol = 0xe04040;
+static Color dhintcol = 0xd0a0a0;
+static Color hhintcol = 0xa0d0a0;
+static Color vhintcol = 0xc0c0ff;
+static Color hflexhintcol = 0x00ff00;
+static Color vflexhintcol = 0x00ff00;
+static Color conflicthintcol = 0x00ffff;
+static Color hhintactivecol = 0x00a000;
+static Color vhintactivecol = 0x0000ff;
+static Color anchorcol = 0x0040ff;
+static Color anchoredoutlinecol = 0x0040ff;
+static Color templateoutlinecol = 0x009800;
+static Color oldoutlinecol = 0x008000;
+static Color transformorigincol = 0x000000;
+static Color guideoutlinecol = 0x808080;
+static Color gridfitoutlinecol = 0x009800;
+static Color backoutlinecol = 0x009800;
+static Color foreoutlinecol = 0x000000;
+static Color backimagecol = 0x707070;
+static Color fillcol = 0x707070;
+static Color tracecol = 0x008000;
+
+static int cvcolsinited = false;
+
+static void CVColInit( void ) {
+ GResStruct cvcolors[] = {
+ { "PointColor", rt_color, &pointcol },
+ { "FirstPointColor", rt_color, &firstpointcol },
+ { "SelectedPointColor", rt_color, &selectedpointcol },
+ { "SelectedPointWidth", rt_int, &selectedpointwidth },
+ { "ExtremePointColor", rt_color, &extremepointcol },
+ { "PointOfInflectionColor", rt_color, &pointofinflectioncol },
+ { "NextCPColor", rt_color, &nextcpcol },
+ { "PrevCPColor", rt_color, &prevcpcol },
+ { "SelectedCPColor", rt_color, &selectedcpcol },
+ { "CoordinateLineColor", rt_color, &coordcol },
+ { "WidthColor", rt_color, &widthcol },
+ { "WidthSelColor", rt_color, &widthselcol },
+ { "GridFitWidthColor", rt_color, &widthgridfitcol },
+ { "LigatureCaretColor", rt_color, &lcaretcol },
+ { "RasterColor", rt_color, &rastercol },
+ { "RasterNewColor", rt_color, &rasternewcol },
+ { "RasterOldColor", rt_color, &rasteroldcol },
+ { "RasterGridColor", rt_color, &rastergridcol },
+ { "RasterDarkColor", rt_color, &rasterdarkcol },
+ { "ItalicCoordColor", rt_color, &italiccoordcol },
+ { "MetricsLabelColor", rt_color, &metricslabelcol },
+ { "HintLabelColor", rt_color, &hintlabelcol },
+ { "BlueValuesStippledColor", rt_color, &bluevalstipplecol },
+ { "FamilyBlueStippledColor", rt_color, &fambluestipplecol },
+ { "MDHintColor", rt_color, &mdhintcol },
+ { "DHintColor", rt_color, &dhintcol },
+ { "HHintColor", rt_color, &hhintcol },
+ { "VHintColor", rt_color, &vhintcol },
+ { "HFlexHintColor", rt_color, &hflexhintcol },
+ { "VFlexHintColor", rt_color, &vflexhintcol },
+ { "ConflictHintColor", rt_color, &conflicthintcol },
+ { "HHintActiveColor", rt_color, &hhintactivecol },
+ { "VHintActiveColor", rt_color, &vhintactivecol },
+ { "AnchorColor", rt_color, &anchorcol },
+ { "AnchoredOutlineColor", rt_color, &anchoredoutlinecol },
+ { "TemplateOutlineColor", rt_color, &templateoutlinecol },
+ { "OldOutlineColor", rt_color, &oldoutlinecol },
+ { "TransformOriginColor", rt_color, &transformorigincol },
+ { "GuideOutlineColor", rt_color, &guideoutlinecol },
+ { "GridFitOutlineColor", rt_color, &gridfitoutlinecol },
+ { "BackgroundOutlineColor", rt_color, &backoutlinecol },
+ { "ForegroundOutlineColor", rt_color, &foreoutlinecol },
+ { "BackgroundImageColor", rt_color, &backimagecol },
+ { "FillColor", rt_color, &fillcol },
+ { "TraceColor", rt_color, &tracecol },
+ { NULL }
+ };
+ GResourceFind( cvcolors, "CharView.");
+}
+
+
+GDevEventMask input_em[] = {
+ /* Event masks for wacom devices */
+ /* negative utility in opening Mouse1 */
+ /* No point in distinguishing cursor from core mouse */
+ { (1<<et_mousemove)|(1<<et_mousedown)|(1<<et_mouseup)|(1<<et_char), "stylus" },
+ { (1<<et_mousemove)|(1<<et_mousedown)|(1<<et_mouseup), "eraser" },
+ { 0, NULL }
+};
+const int input_em_cnt = sizeof(input_em)/sizeof(input_em[0])-1;
+
+/* Positions on the info line */
+#define RPT_BASE 5 /* Place to draw the pointer icon */
+#define RPT_DATA 13 /* x,y text after above */
+#define SPT_BASE 73 /* Place to draw selected pt icon */
+#define SPT_DATA 87 /* Any text for it */
+#define SOF_BASE 147 /* Place to draw selection to pointer icon */
+#define SOF_DATA 169 /* Any text for it */
+#define SDS_BASE 229 /* Place to draw distance icon */
+#define SDS_DATA 251 /* Any text for it */
+#define SAN_BASE 281 /* Place to draw angle icon */
+#define SAN_DATA 303 /* Any text for it */
+#define MAG_BASE 333 /* Place to draw magnification icon */
+#define MAG_DATA 344 /* Any text for it */
+#define LAYER_DATA 404 /* Text to show the current layer */
+#define CODERANGE_DATA 474 /* Text to show the current code range (if the debugger be active) */
+
+void CVDrawRubberRect(GWindow pixmap, CharView *cv) {
+ GRect r;
+ if ( !cv->p.rubberbanding )
+return;
+ r.x = cv->xoff + rint(cv->p.cx*cv->scale);
+ r.y = -cv->yoff + cv->height - rint(cv->p.cy*cv->scale);
+ r.width = rint( (cv->p.ex-cv->p.cx)*cv->scale );
+ r.height = -rint( (cv->p.ey-cv->p.cy)*cv->scale );
+ if ( r.width<0 ) {
+ r.x += r.width;
+ r.width = -r.width;
+ }
+ if ( r.height<0 ) {
+ r.y += r.height;
+ r.height = -r.height;
+ }
+ GDrawSetDashedLine(pixmap,2,2,0);
+ GDrawSetLineWidth(pixmap,0);
+ GDrawSetXORMode(pixmap);
+ GDrawSetXORBase(pixmap,GDrawGetDefaultBackground(NULL));
+ GDrawDrawRect(pixmap,&r,0x000000);
+ GDrawSetCopyMode(pixmap);
+ GDrawSetDashedLine(pixmap,0,0,0);
+}
+
+static void CVDrawRubberLine(GWindow pixmap, CharView *cv) {
+ int x,y, xend,yend;
+ if ( !cv->p.rubberlining )
+return;
+ x = cv->xoff + rint(cv->p.cx*cv->scale);
+ y = -cv->yoff + cv->height - rint(cv->p.cy*cv->scale);
+ xend = cv->xoff + rint(cv->info.x*cv->scale);
+ yend = -cv->yoff + cv->height - rint(cv->info.y*cv->scale);
+ GDrawSetXORMode(pixmap);
+ GDrawSetLineWidth(pixmap,0);
+ GDrawSetXORBase(pixmap,GDrawGetDefaultBackground(NULL));
+ GDrawDrawLine(pixmap,x,y,xend,yend,0x000000);
+ GDrawSetCopyMode(pixmap);
+}
+
+static void CVDrawBB(CharView *cv, GWindow pixmap, DBounds *bb) {
+ GRect r;
+ int off = cv->xoff+cv->height-cv->yoff;
+
+ r.x = cv->xoff + rint(bb->minx*cv->scale);
+ r.y = -cv->yoff + cv->height - rint(bb->maxy*cv->scale);
+ r.width = rint((bb->maxx-bb->minx)*cv->scale);
+ r.height = rint((bb->maxy-bb->miny)*cv->scale);
+ GDrawSetDashedLine(pixmap,1,1,off);
+ GDrawDrawRect(pixmap,&r,GDrawGetDefaultForeground(NULL));
+ GDrawSetDashedLine(pixmap,0,0,0);
+}
+
+/* Sigh. I have to do my own clipping because at large magnifications */
+/* things can easily exceed 16 bits */
+static int CVSplineOutside(CharView *cv, Spline *spline) {
+ int x[4], y[4];
+
+ x[0] = cv->xoff + rint(spline->from->me.x*cv->scale);
+ y[0] = -cv->yoff + cv->height - rint(spline->from->me.y*cv->scale);
+
+ x[1] = cv->xoff + rint(spline->to->me.x*cv->scale);
+ y[1] = -cv->yoff + cv->height - rint(spline->to->me.y*cv->scale);
+
+ if ( spline->from->nonextcp && spline->to->noprevcp ) {
+ if ( (x[0]<0 && x[1]<0) || (x[0]>=cv->width && x[1]>=cv->width) ||
+ (y[0]<0 && y[1]<0) || (y[0]>=cv->height && y[1]>=cv->height) )
+return( true );
+ } else {
+ x[2] = cv->xoff + rint(spline->from->nextcp.x*cv->scale);
+ y[2] = -cv->yoff + cv->height - rint(spline->from->nextcp.y*cv->scale);
+ x[3] = cv->xoff + rint(spline->to->prevcp.x*cv->scale);
+ y[3] = -cv->yoff + cv->height - rint(spline->to->prevcp.y*cv->scale);
+ if ( (x[0]<0 && x[1]<0 && x[2]<0 && x[3]<0) ||
+ (x[0]>=cv->width && x[1]>=cv->width && x[2]>=cv->width && x[3]>=cv->width ) ||
+ (y[0]<0 && y[1]<0 && y[2]<0 && y[3]<0 ) ||
+ (y[0]>=cv->height && y[1]>=cv->height && y[2]>=cv->height && y[3]>=cv->height) )
+return( true );
+ }
+
+return( false );
+}
+
+static int CVLinesIntersectScreen(CharView *cv, LinearApprox *lap) {
+ LineList *l;
+ int any = false;
+ int x,y;
+ int bothout;
+
+ for ( l=lap->lines; l!=NULL; l=l->next ) {
+ l->asend.x = l->asstart.x = cv->xoff + l->here.x;
+ l->asend.y = l->asstart.y = -cv->yoff + cv->height-l->here.y;
+ l->flags = 0;
+ if ( l->asend.x<0 || l->asend.x>=cv->width || l->asend.y<0 || l->asend.y>=cv->height ) {
+ l->flags = cvli_clipped;
+ any = true;
+ }
+ }
+ if ( !any ) {
+ for ( l=lap->lines; l!=NULL; l=l->next )
+ l->flags = cvli_onscreen;
+ lap->any = true;
+return( true );
+ }
+
+ any = false;
+ for ( l=lap->lines; l->next!=NULL; l=l->next ) {
+ if ( !(l->flags&cvli_clipped) && !(l->next->flags&cvli_clipped) )
+ l->flags = cvli_onscreen;
+ else {
+ bothout = (l->flags&cvli_clipped) && (l->next->flags&cvli_clipped);
+ if (( l->asstart.x<0 && l->next->asend.x>0 ) ||
+ ( l->asstart.x>0 && l->next->asend.x<0 )) {
+ y = -(l->next->asend.y-l->asstart.y)*(double)l->asstart.x/(l->next->asend.x-l->asstart.x) +
+ l->asstart.y;
+ if ( l->asstart.x<0 ) {
+ l->asstart.x = 0;
+ l->asstart.y = y;
+ } else {
+ l->next->asend.x = 0;
+ l->next->asend.y = y;
+ }
+ } else if ( l->asstart.x<0 && l->next->asend.x<0 )
+ continue;
+ if (( l->asstart.x<cv->width && l->next->asend.x>cv->width ) ||
+ ( l->asstart.x>cv->width && l->next->asend.x<cv->width )) {
+ y = (l->next->asend.y-l->asstart.y)*(double)(cv->width-l->asstart.x)/(l->next->asend.x-l->asstart.x) +
+ l->asstart.y;
+ if ( l->asstart.x>cv->width ) {
+ l->asstart.x = cv->width;
+ l->asstart.y = y;
+ } else {
+ l->next->asend.x = cv->width;
+ l->next->asend.y = y;
+ }
+ } else if ( l->asstart.x>cv->width && l->next->asend.x>cv->width )
+ continue;
+ if (( l->asstart.y<0 && l->next->asend.y>0 ) ||
+ ( l->asstart.y>0 && l->next->asend.y<0 )) {
+ x = -(l->next->asend.x-l->asstart.x)*(double)l->asstart.y/(l->next->asend.y-l->asstart.y) +
+ l->asstart.x;
+ if (( x<0 || x>=cv->width ) && bothout )
+ continue; /* Not on screen */;
+ if ( l->asstart.y<0 ) {
+ l->asstart.y = 0;
+ l->asstart.x = x;
+ } else {
+ l->next->asend.y = 0;
+ l->next->asend.x = x;
+ }
+ } else if ( l->asstart.y<0 && l->next->asend.y< 0 )
+ continue;
+ if (( l->asstart.y<cv->height && l->next->asend.y>cv->height ) ||
+ ( l->asstart.y>cv->height && l->next->asend.y<cv->height )) {
+ x = (l->next->asend.x-l->asstart.x)*(double)(cv->height-l->asstart.y)/(l->next->asend.y-l->asstart.y) +
+ l->asstart.x;
+ if (( x<0 || x>=cv->width ) && bothout )
+ continue; /* Not on screen */;
+ if ( l->asstart.y>cv->height ) {
+ l->asstart.y = cv->height;
+ l->asstart.x = x;
+ } else {
+ l->next->asend.y = cv->height;
+ l->next->asend.x = x;
+ }
+ } else if ( l->asstart.y>cv->height && l->next->asend.y>cv->height )
+ continue;
+ l->flags |= cvli_onscreen;
+ any = true;
+ }
+ }
+ lap->any = any;
+return( any );
+}
+
+typedef struct gpl { struct gpl *next; GPoint *gp; int cnt; } GPointList;
+
+static void GPLFree(GPointList *gpl) {
+ GPointList *next;
+
+ while ( gpl!=NULL ) {
+ next = gpl->next;
+ free( gpl->gp );
+ free( gpl );
+ gpl = next;
+ }
+}
+
+/* Before we did clipping this was a single polygon. Now it is a set of */
+/* sets of line segments. If no clipping is done, then we end up with */
+/* one set which is the original polygon, otherwise we get the segments */
+/* which are inside the screen. Each set of segments is contiguous */
+static GPointList *MakePoly(CharView *cv, SplinePointList *spl) {
+ int i, len;
+ LinearApprox *lap;
+ LineList *line, *prev;
+ Spline *spline, *first;
+ GPointList *head=NULL, *last=NULL, *cur;
+ int closed;
+
+ for ( i=0; i<2; ++i ) {
+ len = 0; first = NULL;
+ closed = true;
+ cur = NULL;
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) {
+ if ( !CVSplineOutside(cv,spline) && !isnan(spline->splines[0].a) && !isnan(spline->splines[1].a)) {
+ lap = SplineApproximate(spline,cv->scale);
+ if ( i==0 )
+ CVLinesIntersectScreen(cv,lap);
+ if ( lap->any ) {
+ for ( prev = lap->lines, line=prev->next; line!=NULL; prev=line, line=line->next ) {
+ if ( !(prev->flags&cvli_onscreen) ) {
+ closed = true;
+ continue;
+ }
+ if ( closed || (prev->flags&cvli_clipped) ) {
+ if ( i==0 ) {
+ cur = gcalloc(1,sizeof(GPointList));
+ if ( head==NULL )
+ head = cur;
+ else {
+ last->cnt = len;
+ last->next = cur;
+ }
+ last = cur;
+ } else {
+ if ( cur==NULL )
+ cur = head;
+ else
+ cur = cur->next;
+ cur->gp = galloc(cur->cnt*sizeof(GPoint));
+ cur->gp[0].x = prev->asstart.x;
+ cur->gp[0].y = prev->asstart.y;
+ }
+ len=1;
+ closed = false;
+ }
+ if ( i!=0 ) {
+ if ( len>=cur->cnt )
+ fprintf( stderr, "Clipping is screwed up, about to die %d (should be less than %d)\n", len, cur->cnt );
+ cur->gp[len].x = line->asend.x;
+ cur->gp[len].y = line->asend.y;
+ }
+ ++len;
+ if ( line->flags&cvli_clipped )
+ closed = true;
+ }
+ } else
+ closed = true;
+ } else
+ closed = true;
+ if ( first==NULL ) first = spline;
+ }
+ if ( i==0 && cur!=NULL )
+ cur->cnt = len;
+ }
+return( head );
+}
+
+static void DrawPoint(CharView *cv, GWindow pixmap, SplinePoint *sp,
+ SplineSet *spl, int onlynumber) {
+ GRect r;
+ int x, y, cx, cy;
+ Color col = sp==spl->first ? firstpointcol : pointcol, subcol;
+ int pnum;
+ char buf[12]; unichar_t ubuf[12];
+ int isfake;
+
+ if ( cv->markextrema && !sp->nonextcp && !sp->noprevcp &&
+ ((sp->nextcp.x==sp->me.x && sp->prevcp.x==sp->me.x) ||
+ (sp->nextcp.y==sp->me.y && sp->prevcp.y==sp->me.y)) )
+ col = extremepointcol;
+ if ( sp->selected )
+ col = selectedpointcol;
+
+ x = cv->xoff + rint(sp->me.x*cv->scale);
+ y = -cv->yoff + cv->height - rint(sp->me.y*cv->scale);
+ if ( x<-4000 || y<-4000 || x>cv->width+4000 || y>=cv->height+4000 )
+return;
+
+ /* draw the control points if it's selected */
+ if ( sp->selected || cv->showpointnumbers || cv->show_ft_results || cv->dv ) {
+ int iscurrent = sp==(cv->p.sp!=NULL?cv->p.sp:cv->lastselpt);
+ if ( !sp->nonextcp ) {
+ cx = cv->xoff + rint(sp->nextcp.x*cv->scale);
+ cy = -cv->yoff + cv->height - rint(sp->nextcp.y*cv->scale);
+ if ( cx<-100 ) { /* Clip */
+ cy = cx==x ? x : (cy-y) * (double)(-100-x)/(cx-x) + y;
+ cx = -100;
+ } else if ( cx>cv->width+100 ) {
+ cy = cx==x ? x : (cy-y) * (double)(cv->width+100-x)/(cx-x) + y;
+ cx = cv->width+100;
+ }
+ if ( cy<-100 ) {
+ cx = cy==y ? y : (cx-x) * (double)(-100-y)/(cy-y) + x;
+ cy = -100;
+ } else if ( cy>cv->height+100 ) {
+ cx = cy==y ? y : (cx-x) * (double)(cv->height+100-y)/(cy-y) + x;
+ cy = cv->height+100;
+ }
+ subcol = nextcpcol;
+ if ( iscurrent && cv->p.nextcp && !onlynumber ) {
+ r.x = cx-3; r.y = cy-3; r.width = r.height = 7;
+ GDrawFillRect(pixmap,&r, nextcpcol);
+ subcol = selectedcpcol;
+ }
+ if ( !onlynumber ) {
+ GDrawDrawLine(pixmap,x,y,cx,cy, nextcpcol);
+ GDrawDrawLine(pixmap,cx-3,cy-3,cx+3,cy+3,subcol);
+ GDrawDrawLine(pixmap,cx+3,cy-3,cx-3,cy+3,subcol);
+ }
+ if ( cv->showpointnumbers || cv->show_ft_results || cv->dv ) {
+ pnum = sp->nextcpindex;
+ if ( pnum!=0xffff && pnum!=0xfffe ) {
+ sprintf( buf,"%d", pnum );
+ uc_strcpy(ubuf,buf);
+ GDrawDrawText(pixmap,cx,cy-6,ubuf,-1,NULL,nextcpcol);
+ }
+ }
+ }
+ if ( !sp->noprevcp ) {
+ cx = cv->xoff + rint(sp->prevcp.x*cv->scale);
+ cy = -cv->yoff + cv->height - rint(sp->prevcp.y*cv->scale);
+ if ( cx<-100 ) { /* Clip */
+ cy = cx==x ? x : (cy-y) * (double)(-100-x)/(cx-x) + y;
+ cx = -100;
+ } else if ( cx>cv->width+100 ) {
+ cy = cx==x ? x : (cy-y) * (double)(cv->width+100-x)/(cx-x) + y;
+ cx = cv->width+100;
+ }
+ if ( cy<-100 ) {
+ cx = cy==y ? y : (cx-x) * (double)(-100-y)/(cy-y) + x;
+ cy = -100;
+ } else if ( cy>cv->height+100 ) {
+ cx = cy==y ? y : (cx-x) * (double)(cv->height+100-y)/(cy-y) + x;
+ cy = cv->height+100;
+ }
+ subcol = prevcpcol;
+ if ( iscurrent && cv->p.prevcp && !onlynumber ) {
+ r.x = cx-3; r.y = cy-3; r.width = r.height = 7;
+ GDrawFillRect(pixmap,&r, prevcpcol);
+ subcol = selectedcpcol;
+ }
+ if ( !onlynumber ) {
+ GDrawDrawLine(pixmap,x,y,cx,cy, prevcpcol);
+ GDrawDrawLine(pixmap,cx-3,cy-3,cx+3,cy+3,subcol);
+ GDrawDrawLine(pixmap,cx+3,cy-3,cx-3,cy+3,subcol);
+ }
+ }
+ }
+
+ if ( x<-4 || y<-4 || x>cv->width+4 || y>=cv->height+4 )
+return;
+ r.x = x-2;
+ r.y = y-2;
+ r.width = r.height = 5;
+ if ( sp->selected )
+ GDrawSetLineWidth(pixmap,selectedpointwidth);
+ isfake = false;
+ if ( cv->fv->sf->order2 && cv->drawmode==dm_fore &&
+ cv->sc->layers[ly_fore].refs==NULL ) {
+ int mightbe_fake = SPInterpolate(sp);
+ if ( !mightbe_fake && sp->ttfindex==0xffff )
+ sp->ttfindex = 0xfffe; /* if we have no instructions we won't call instrcheck and won't notice when a point stops being fake */
+ else if ( mightbe_fake )
+ sp->ttfindex = 0xffff;
+ isfake = sp->ttfindex==0xffff;
+ }
+ if ( onlynumber )
+ /* Draw Nothing */;
+ else if ( sp->pointtype==pt_curve ) {
+ --r.x; --r.y; r.width +=2; r.height += 2;
+ if ( sp->selected || isfake )
+ GDrawDrawElipse(pixmap,&r,col);
+ else
+ GDrawFillElipse(pixmap,&r,col);
+ } else if ( sp->pointtype==pt_corner ) {
+ if ( sp->selected || isfake )
+ GDrawDrawRect(pixmap,&r,col);
+ else
+ GDrawFillRect(pixmap,&r,col);
+ } else {
+ GPoint gp[5];
+ int dir;
+ BasePoint *cp=NULL;
+ if ( !sp->nonextcp )
+ cp = &sp->nextcp;
+ else if ( !sp->noprevcp )
+ cp = &sp->prevcp;
+ dir = 0;
+ if ( cp!=NULL ) {
+ float dx = cp->x-sp->me.x, dy = cp->y-sp->me.y;
+ if ( dx<0 ) dx= -dx;
+ if ( dy<0 ) dy= -dy;
+ if ( dx>2*dy ) {
+ if ( cp->x>sp->me.x ) dir = 0 /* right */;
+ else dir = 1 /* left */;
+ } else if ( dy>2*dx ) {
+ if ( cp->y>sp->me.y ) dir = 2 /* up */;
+ else dir = 3 /* down */;
+ } else {
+ if ( cp->y>sp->me.y && cp->x>sp->me.x ) dir=4;
+ else if ( cp->x>sp->me.x ) dir=5;
+ else if ( cp->y>sp->me.y ) dir=7;
+ else dir = 6;
+ }
+ }
+ if ( dir==1 /* left */ || dir==0 /* right */) {
+ gp[0].y = y; gp[0].x = (dir==0)?x+4:x-4;
+ gp[1].y = y-4; gp[1].x = x;
+ gp[2].y = y+4; gp[2].x = x;
+ } else if ( dir==2 /* up */ || dir==3 /* down */ ) {
+ gp[0].x = x; gp[0].y = dir==2?y-4:y+4; /* remember screen coordinates are backwards in y from character coords */
+ gp[1].x = x-4; gp[1].y = y;
+ gp[2].x = x+4; gp[2].y = y;
+ } else {
+ /* at a 45 angle, a value of 4 looks too small. I probably want 4*1.414 */
+ int xdiff= cp->x>sp->me.x?5:-5, ydiff = cp->y>sp->me.y?-5:5;
+ gp[0].x = x+xdiff/2; gp[0].y = y+ydiff/2;
+ gp[1].x = gp[0].x-xdiff; gp[1].y = gp[0].y;
+ gp[2].x = gp[0].x; gp[2].y = gp[0].y-ydiff;
+ }
+ gp[3] = gp[0];
+ if ( sp->selected || isfake )
+ GDrawDrawPoly(pixmap,gp,4,col);
+ else
+ GDrawFillPoly(pixmap,gp,4,col);
+ }
+ GDrawSetLineWidth(pixmap,0);
+ if ( (cv->showpointnumbers || cv->show_ft_results|| cv->dv ) && sp->ttfindex!=0xffff ) {
+ if ( sp->ttfindex==0xfffe )
+ strcpy(buf,"?");
+ else
+ sprintf( buf,"%d", sp->ttfindex );
+ GDrawDrawText8(pixmap,x,y-6,buf,-1,NULL,col);
+ }
+ if ( !onlynumber ) {
+ if ((( sp->roundx || sp->roundy ) &&
+ (((cv->showrounds&1) && cv->scale>=.3) || (cv->showrounds&2))) ||
+ (sp->watched && cv->dv!=NULL) ||
+ sp->hintmask!=NULL ) {
+ r.x = x-5; r.y = y-5;
+ r.width = r.height = 11;
+ GDrawDrawElipse(pixmap,&r,col);
+ }
+ if (( sp->flexx && cv->showhhints ) || (sp->flexy && cv->showvhints)) {
+ r.x = x-5; r.y = y-5;
+ r.width = r.height = 11;
+ GDrawDrawElipse(pixmap,&r,sp->flexx ? hflexhintcol : vflexhintcol );
+ }
+ }
+}
+
+static void DrawLine(CharView *cv, GWindow pixmap,
+ real x1, real y1, real x2, real y2, Color fg) {
+ int ix1 = cv->xoff + rint(x1*cv->scale);
+ int iy1 = -cv->yoff + cv->height - rint(y1*cv->scale);
+ int ix2 = cv->xoff + rint(x2*cv->scale);
+ int iy2 = -cv->yoff + cv->height - rint(y2*cv->scale);
+ if ( iy1==iy2 ) {
+ if ( iy1<0 || iy1>cv->height )
+return;
+ if ( ix1<0 ) ix1 = 0;
+ if ( ix2>cv->width ) ix2 = cv->width;
+ } else if ( ix1==ix2 ) {
+ if ( ix1<0 || ix1>cv->width )
+return;
+ if ( iy1<0 ) iy1 = 0;
+ if ( iy2<0 ) iy2 = 0;
+ if ( iy1>cv->height ) iy1 = cv->height;
+ if ( iy2>cv->height ) iy2 = cv->height;
+ }
+ GDrawDrawLine(pixmap, ix1,iy1, ix2,iy2, fg );
+}
+
+static void DrawDirection(CharView *cv,GWindow pixmap, SplinePoint *sp) {
+ BasePoint dir, *other;
+ double len;
+ int x,y,xe,ye;
+ SplinePoint *test;
+
+ if ( sp->next==NULL )
+return;
+
+ x = cv->xoff + rint(sp->me.x*cv->scale);
+ y = -cv->yoff + cv->height - rint(sp->me.y*cv->scale);
+ if ( x<0 || y<0 || x>cv->width || y>cv->width )
+return;
+
+ /* Werner complained when the first point and the second point were at */
+ /* the same location... */ /* Damn. They weren't at the same location */
+ /* the were off by a rounding error. I'm not going to fix for that */
+ for ( test=sp; ; ) {
+ if ( test->me.x!=sp->me.x || test->me.y!=sp->me.y ) {
+ other = &test->me;
+ break;
+ } else if ( !test->nonextcp ) {
+ other = &test->nextcp;
+ break;
+ }
+ if ( test->next==NULL )
+return;
+ test = test->next->to;
+ if ( test==sp )
+return;
+ }
+
+ dir.x = other->x-sp->me.x;
+ dir.y = sp->me.y-other->y; /* screen coordinates are the mirror of user coords */
+ len = sqrt(dir.x*dir.x + dir.y*dir.y);
+ dir.x /= len; dir.y /= len;
+
+ x += rint(5*dir.y);
+ y -= rint(5*dir.x);
+ xe = x + rint(7*dir.x);
+ ye = y + rint(7*dir.y);
+ GDrawDrawLine(pixmap,x,y,xe,ye,firstpointcol);
+ GDrawDrawLine(pixmap,xe,ye,xe+rint(2*(dir.y-dir.x)),ye+rint(2*(-dir.y-dir.x)), firstpointcol);
+ GDrawDrawLine(pixmap,xe,ye,xe+rint(2*(-dir.y-dir.x)),ye+rint(2*(dir.x-dir.y)), firstpointcol);
+}
+
+static void CVMarkInterestingLocations(CharView *cv, GWindow pixmap,
+ SplinePointList *spl) {
+ Spline *s, *first;
+ extended interesting[6];
+ int i, ecnt, cnt;
+ GRect r;
+
+ for ( s=spl->first->next, first=NULL; s!=NULL && s!=first; s=s->to->next ) {
+ if ( first==NULL ) first = s;
+ cnt = ecnt = 0;
+ if ( cv->markextrema )
+ ecnt = cnt = Spline2DFindExtrema(s,interesting);
+
+ if ( cv->markpoi ) {
+ cnt += Spline2DFindPointsOfInflection(s,interesting+cnt);
+ }
+ r.width = r.height = 9;
+ for ( i=0; i<cnt; ++i ) if ( interesting[i]>0 && interesting[i]<1.0 ) {
+ Color col = i<ecnt ? extremepointcol : pointofinflectioncol;
+ double x = ((s->splines[0].a*interesting[i]+s->splines[0].b)*interesting[i]+s->splines[0].c)*interesting[i]+s->splines[0].d;
+ double y = ((s->splines[1].a*interesting[i]+s->splines[1].b)*interesting[i]+s->splines[1].c)*interesting[i]+s->splines[1].d;
+ double sx = cv->xoff + rint(x*cv->scale);
+ double sy = -cv->yoff + cv->height - rint(y*cv->scale);
+ if ( sx<-5 || sy<-5 || sx>10000 || sy>10000 )
+ continue;
+ GDrawDrawLine(pixmap,sx-4,sy,sx+4,sy, col);
+ GDrawDrawLine(pixmap,sx,sy-4,sx,sy+4, col);
+ r.x = sx-4; r.y = sy-4;
+ GDrawDrawElipse(pixmap,&r,col);
+ }
+ }
+}
+
+void CVDrawSplineSet(CharView *cv, GWindow pixmap, SplinePointList *set,
+ Color fg, int dopoints, DRect *clip ) {
+ Spline *spline, *first;
+ SplinePointList *spl;
+
+ if ( cv->inactive )
+ dopoints = false;
+
+ GDrawSetFont(pixmap,cv->small); /* For point numbers */
+ for ( spl = set; spl!=NULL; spl = spl->next ) {
+ GPointList *gpl = MakePoly(cv,spl), *cur;
+ if ( dopoints>0 || (dopoints==-1 && cv->showpointnumbers) ) {
+ first = NULL;
+ if ( dopoints>0 )
+ DrawDirection(cv,pixmap,spl->first);
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) {
+ DrawPoint(cv,pixmap,spline->from,spl,dopoints<0);
+ if ( first==NULL ) first = spline;
+ }
+ if ( spline==NULL )
+ DrawPoint(cv,pixmap,spl->last,spl,dopoints<0);
+ }
+ for ( cur=gpl; cur!=NULL; cur=cur->next )
+ GDrawDrawPoly(pixmap,cur->gp,cur->cnt,fg);
+ GPLFree(gpl);
+ if (( cv->markextrema || cv->markpoi ) && dopoints )
+ CVMarkInterestingLocations(cv,pixmap,spl);
+ }
+}
+
+static void CVDrawLayerSplineSet(CharView *cv, GWindow pixmap, Layer *layer,
+ Color fg, int dopoints, DRect *clip ) {
+#ifdef FONTFORGE_CONFIG_TYPE3
+ int active = cv->layerheads[cv->drawmode]==layer;
+
+ if ( layer->dostroke ) {
+ if ( layer->stroke_pen.brush.col!=COLOR_INHERITED &&
+ layer->stroke_pen.brush.col!=GDrawGetDefaultBackground(NULL))
+ fg = layer->stroke_pen.brush.col;
+#if 0
+ if ( layer->stroke_pen.width!=WIDTH_INHERITED )
+ GDrawSetLineWidth(pixmap,rint(layer->stroke_pen.width*layer->stroke_pen.trans[0]*cv->scale));
+#endif
+ }
+ if ( layer->dofill ) {
+ if ( layer->fill_brush.col!=COLOR_INHERITED &&
+ layer->fill_brush.col!=GDrawGetDefaultBackground(NULL))
+ fg = layer->fill_brush.col;
+ }
+ if ( !active && layer!=&cv->sc->layers[ly_back] )
+ GDrawSetDashedLine(pixmap,5,5,cv->xoff+cv->height-cv->yoff);
+ CVDrawSplineSet(cv,pixmap,layer->splines,fg,dopoints && active,clip);
+ if ( !active && layer!=&cv->sc->layers[ly_back] )
+ GDrawSetDashedLine(pixmap,0,0,0);
+#if 0
+ if ( layer->dostroke && layer->stroke_pen.width!=WIDTH_INHERITED )
+ GDrawSetLineWidth(pixmap,0);
+#endif
+#else
+ CVDrawSplineSet(cv,pixmap,layer->splines,fg,dopoints,clip);
+#endif
+}
+
+static void CVDrawTemplates(CharView *cv,GWindow pixmap,SplineChar *template,DRect *clip) {
+ RefChar *r;
+
+ CVDrawSplineSet(cv,pixmap,template->layers[ly_fore].splines,templateoutlinecol,false,clip);
+ for ( r=template->layers[ly_fore].refs; r!=NULL; r=r->next )
+ CVDrawSplineSet(cv,pixmap,r->layers[0].splines,templateoutlinecol,false,clip);
+}
+
+static void CVShowDHint(CharView *cv, GWindow pixmap, DStemInfo *dstem) {
+ IPoint ip[40], ip2[40];
+ GPoint clipped[13];
+ int i,j, tot,last;
+
+ ip[0].x = cv->xoff + rint(dstem->leftedgetop.x*cv->scale);
+ ip[0].y = -cv->yoff + cv->height - rint(dstem->leftedgetop.y*cv->scale);
+ ip[1].x = cv->xoff + rint(dstem->rightedgetop.x*cv->scale);
+ ip[1].y = -cv->yoff + cv->height - rint(dstem->rightedgetop.y*cv->scale);
+ ip[2].x = cv->xoff + rint(dstem->rightedgebottom.x*cv->scale);
+ ip[2].y = -cv->yoff + cv->height - rint(dstem->rightedgebottom.y*cv->scale);
+ ip[3].x = cv->xoff + rint(dstem->leftedgebottom.x*cv->scale);
+ ip[3].y = -cv->yoff + cv->height - rint(dstem->leftedgebottom.y*cv->scale);
+
+ if (( ip[0].x<0 && ip[1].x<0 && ip[2].x<0 && ip[3].x<0 ) ||
+ ( ip[0].x>=cv->width && ip[1].x>=cv->width && ip[2].x>=cv->width && ip[3].x>=cv->width ) ||
+ ( ip[0].y<0 && ip[1].y<0 && ip[2].y<0 && ip[3].y<0 ) ||
+ ( ip[0].y>=cv->height && ip[1].y>=cv->height && ip[2].y>=cv->height && ip[3].y>=cv->height ))
+return; /* Offscreen */
+
+ /* clip to left edge */
+ tot = 4;
+ for ( i=j=0; i<tot; ++i ) {
+ last = i==0?tot-1:i-1;
+ if ( ip[i].x>=0 && ip[last].x>=0) {
+ ip2[j++] = ip[i];
+ } else if ( ip[i].x<0 && ip[last].x<0 ) {
+ if ( j==0 || ip2[j-1].x!=0 || ip2[j-1].y!=ip[i].y ) {
+ ip2[j].x = 0;
+ ip2[j++].y = ip[i].y;
+ }
+ } else {
+ ip2[j].x = 0;
+ ip2[j++].y = ip[last].y - ip[last].x * ((real) (ip[i].y-ip[last].y))/(ip[i].x-ip[last].x);
+ if ( ip[i].x>0 )
+ ip2[j++] = ip[i];
+ else {
+ ip2[j].x = 0;
+ ip2[j++].y = ip[i].y;
+ }
+ }
+ }
+ /* clip to right edge */
+ tot = j;
+ for ( i=j=0; i<tot; ++i ) {
+ last = i==0?tot-1:i-1;
+ if ( ip2[i].x<cv->width && ip2[last].x<cv->width ) {
+ ip[j++] = ip2[i];
+ } else if ( ip2[i].x>=cv->width && ip2[last].x>=cv->width ) {
+ if ( j==0 || ip[j-1].x!=cv->width-1 || ip[j-1].y!=ip2[i].y ) {
+ ip[j].x = cv->width-1;
+ ip[j++].y = ip2[i].y;
+ }
+ } else {
+ ip[j].x = cv->width-1;
+ ip[j++].y = ip2[last].y + (cv->width-1- ip2[last].x) * ((real) (ip2[i].y-ip2[last].y))/(ip2[i].x-ip2[last].x);
+ if ( ip2[i].x<cv->width )
+ ip[j++] = ip2[i];
+ else {
+ ip[j].x = cv->width-1;
+ ip[j++].y = ip2[i].y;
+ }
+ }
+ }
+ /* clip to bottom edge */
+ tot = j;
+ for ( i=j=0; i<tot; ++i ) {
+ last = i==0?tot-1:i-1;
+ if ( ip[i].y>=0 && ip[last].y>=0) {
+ ip2[j++] = ip[i];
+ } else if ( ip[i].y<0 && ip[last].y<0 ) {
+ ip2[j].y = 0;
+ ip2[j++].x = ip[i].x;
+ } else {
+ ip2[j].y = 0;
+ ip2[j++].x = ip[last].x - ip[last].y * ((real) (ip[i].x-ip[last].x))/(ip[i].y-ip[last].y);
+ if ( ip[i].y>0 )
+ ip2[j++] = ip[i];
+ else {
+ ip2[j].y = 0;
+ ip2[j++].x = ip[i].x;
+ }
+ }
+ }
+ /* clip to top edge */
+ tot = j;
+ for ( i=j=0; i<tot; ++i ) {
+ last = i==0?tot-1:i-1;
+ if ( ip2[i].y<cv->height && ip2[last].y<cv->height ) {
+ ip[j++] = ip2[i];
+ } else if ( ip2[i].y>=cv->height && ip2[last].y>=cv->height ) {
+ ip[j].y = cv->height-1;
+ ip[j++].x = ip2[i].x;
+ } else {
+ ip[j].y = cv->height-1;
+ ip[j++].x = ip2[last].x + (cv->height-1- ip2[last].y) * ((real) (ip2[i].x-ip2[last].x))/(ip2[i].y-ip2[last].y);
+ if ( ip2[i].y<cv->width )
+ ip[j++] = ip2[i];
+ else {
+ ip[j].y = cv->height-1;
+ ip[j++].x = ip2[i].x;
+ }
+ }
+ }
+
+ tot=j;
+ clipped[0].x = ip[0].x; clipped[0].y = ip[0].y;
+ for ( i=j=1; i<tot; ++i ) {
+ if ( ip[i].x!=ip[i-1].x || ip[i].y!=ip[i-1].y ) {
+ clipped[j].x = ip[i].x; clipped[j++].y = ip[i].y;
+ }
+ }
+ clipped[j++] = clipped[0];
+ GDrawFillPoly(pixmap,clipped,j,dhintcol);
+}
+
+static void CVShowMinimumDistance(CharView *cv, GWindow pixmap,MinimumDistance *md) {
+ int x1,y1, x2,y2;
+ int xa, ya;
+ int off = cv->xoff+cv->height-cv->yoff;
+
+ if (( md->x && !cv->showmdx ) || (!md->x && !cv->showmdy))
+return;
+ if ( md->sp1==NULL && md->sp2==NULL )
+return;
+ if ( md->sp1!=NULL ) {
+ x1 = cv->xoff + rint( md->sp1->me.x*cv->scale );
+ y1 = -cv->yoff + cv->height - rint(md->sp1->me.y*cv->scale);
+ } else {
+ x1 = cv->xoff + rint( cv->sc->width*cv->scale );
+ y1 = 0x80000000;
+ }
+ if ( md->sp2!=NULL ) {
+ x2 = cv->xoff + rint( md->sp2->me.x*cv->scale );
+ y2 = -cv->yoff + cv->height - rint(md->sp2->me.y*cv->scale);
+ } else {
+ x2 = cv->xoff + rint( cv->sc->width*cv->scale );
+ y2 = y1-8;
+ }
+ if ( y1==0x80000000 )
+ y1 = y2-8;
+ if ( md->x ) {
+ ya = (y1+y2)/2;
+ GDrawDrawArrow(pixmap, x1,ya, x2,ya, 2, mdhintcol);
+ GDrawSetDashedLine(pixmap,5,5,off);
+ GDrawDrawLine(pixmap, x1,ya, x1,y1, mdhintcol);
+ GDrawDrawLine(pixmap, x2,ya, x2,y2, mdhintcol);
+ } else {
+ xa = (x1+x2)/2;
+ GDrawDrawArrow(pixmap, xa,y1, xa,y2, 2, mdhintcol);
+ GDrawSetDashedLine(pixmap,5,5,off);
+ GDrawDrawLine(pixmap, xa,y1, x1,y1, mdhintcol);
+ GDrawDrawLine(pixmap, xa,y2, x2,y2, mdhintcol);
+ }
+ GDrawSetDashedLine(pixmap,0,0,0);
+}
+
+static void dtos(char *buf,real val) {
+ char *pt;
+
+ sprintf( buf,"%.1f", (double) val);
+ pt = buf+strlen(buf);
+ if ( pt[-1]=='0' && pt[-2]=='.' ) pt[-2] = '\0';
+}
+
+static void CVDrawBlues(CharView *cv,GWindow pixmap,char *bluevals,char *others,
+ Color col) {
+ double blues[24];
+ char *pt, *end;
+ int i=0, bcnt=0;
+ GRect r;
+ char buf[20];
+ int len,len2;
+
+ if ( bluevals!=NULL ) {
+ for ( pt = bluevals; isspace( *pt ) || *pt=='['; ++pt);
+ while ( i<14 && *pt!='\0' && *pt!=']' ) {
+ blues[i] = strtod(pt,&end);
+ if ( pt==end )
+ break;
+ ++i;
+ pt = end;
+ while ( isspace( *pt )) ++pt;
+ }
+ if ( i&1 ) --i;
+ }
+ if ( others!=NULL ) {
+ for ( pt = others; isspace( *pt ) || *pt=='['; ++pt);
+ while ( i<24 && *pt!='\0' && *pt!=']' ) {
+ blues[i] = strtod(pt,&end);
+ if ( pt==end )
+ break;
+ ++i;
+ pt = end;
+ while ( isspace( *pt )) ++pt;
+ }
+ if ( i&1 ) --i;
+ }
+ bcnt = i;
+ if ( i==0 )
+return;
+
+ r.x = 0; r.width = cv->width;
+ for ( i=0; i<bcnt; i += 2 ) {
+ int first, other;
+ first = -cv->yoff + cv->height - rint(blues[i]*cv->scale);
+ other = -cv->yoff + cv->height - rint(blues[i+1]*cv->scale);
+ r.y = first;
+ if ( ( r.y<0 && other<0 ) || (r.y>cv->height && other>cv->height))
+ continue;
+ if ( r.y<0 ) r.y = 0;
+ else if ( r.y>cv->height ) r.y = cv->height;
+ if ( other<0 ) other = 0;
+ else if ( other>cv->height ) other = cv->height;
+ if ( other<r.y ) {
+ r.height = r.y-other;
+ r.y = other;
+ } else
+ r.height = other-r.y;
+ if ( r.height==0 ) r.height = 1; /* show something */
+ GDrawSetStippled(pixmap,2, 0,0);
+ GDrawFillRect(pixmap,&r,col);
+ GDrawSetStippled(pixmap,0, 0,0);
+
+ if ( first>-20 && first<cv->height+20 ) {
+ dtos( buf, blues[i]);
+ len = GDrawGetText8Width(pixmap,buf,-1,NULL);
+ GDrawDrawText8(pixmap,cv->width-len-5,first-3,buf,-1,NULL,hintlabelcol);
+ } else
+ len = 0;
+ if ( other>-20 && other<cv->height+20 ) {
+ dtos( buf, blues[i+1]-blues[i]);
+ len2 = GDrawGetText8Width(pixmap,buf,-1,NULL);
+ GDrawDrawText8(pixmap,cv->width-len-5-len2-5,other+cv->sas-3,buf,-1,NULL,hintlabelcol);
+ }
+ }
+}
+
+static void CVShowHints(CharView *cv, GWindow pixmap) {
+ StemInfo *hint;
+ GRect r;
+ HintInstance *hi;
+ int end;
+ Color col;
+ DStemInfo *dstem;
+ MinimumDistance *md;
+ char *blues, *others;
+ struct psdict *private = cv->sc->parent->private;
+ char buf[20];
+ int len, len2;
+ SplinePoint *sp;
+ SplineSet *spl;
+
+ GDrawSetFont(pixmap,cv->small);
+ blues = PSDictHasEntry(private,"BlueValues"); others = PSDictHasEntry(private,"OtherBlues");
+ if ( cv->showblues && (blues!=NULL || others!=NULL))
+ CVDrawBlues(cv,pixmap,blues,others,bluevalstipplecol);
+ blues = PSDictHasEntry(private,"FamilyBlues"); others = PSDictHasEntry(private,"FamilyOtherBlues");
+ if ( cv->showfamilyblues && (blues!=NULL || others!=NULL))
+ CVDrawBlues(cv,pixmap,blues,others,fambluestipplecol);
+
+ if ( cv->showdhints ) for ( dstem = cv->sc->dstem; dstem!=NULL; dstem = dstem->next ) {
+ CVShowDHint(cv,pixmap,dstem);
+ }
+
+ if ( cv->showhhints && cv->sc->hstem!=NULL ) {
+ GDrawSetDashedLine(pixmap,5,5,cv->xoff);
+ for ( hint = cv->sc->hstem; hint!=NULL; hint = hint->next ) {
+ if ( hint->width<0 ) {
+ r.y = -cv->yoff + cv->height - rint(hint->start*cv->scale);
+ r.height = rint(-hint->width*cv->scale)+1;
+ } else {
+ r.y = -cv->yoff + cv->height - rint((hint->start+hint->width)*cv->scale);
+ r.height = rint(hint->width*cv->scale)+1;
+ }
+ col = hint->active ? hhintactivecol : hhintcol;
+ /* XRectangles are shorts! */
+ if ( r.y<32767 && r.y+r.height>-32768 ) {
+ if ( r.y<-32768 ) {
+ r.height -= (-32768-r.y);
+ r.y = -32768;
+ }
+ if ( r.y+r.height>32767 )
+ r.height = 32767-r.y;
+ for ( hi=hint->where; hi!=NULL; hi=hi->next ) {
+ r.x = cv->xoff + rint(hi->begin*cv->scale);
+ end = cv->xoff + rint(hi->end*cv->scale);
+ if ( end>=0 && r.x<=cv->width ) {
+ r.width = end-r.x+1;
+ GDrawFillRect(pixmap,&r,col);
+ }
+ }
+ }
+ col = (!hint->active && hint->hasconflicts) ? conflicthintcol : col;
+ if ( r.y>=0 && r.y<=cv->height )
+ GDrawDrawLine(pixmap,0,r.y,cv->width,r.y,col);
+ if ( r.y+r.height>=0 && r.y+r.height<=cv->width )
+ GDrawDrawLine(pixmap,0,r.y+r.height-1,cv->width,r.y+r.height-1,col);
+
+ r.y = -cv->yoff + cv->height - rint(hint->start*cv->scale);
+ r.y += ( hint->width>0 ) ? -3 : cv->sas+3;
+ if ( r.y>-20 && r.y<cv->height+20 ) {
+ dtos( buf, hint->start);
+ len = GDrawGetText8Width(pixmap,buf,-1,NULL);
+ GDrawDrawText8(pixmap,cv->width-len-5,r.y,buf,-1,NULL,hintlabelcol);
+ } else
+ len = 0;
+ r.y = -cv->yoff + cv->height - rint((hint->start+hint->width)*cv->scale);
+ r.y += ( hint->width>0 ) ? cv->sas+3 : -3;
+ if ( r.y>-20 && r.y<cv->height+20 ) {
+ if ( hint->ghost ) {
+ buf[0] = 'G';
+ buf[1] = ' ';
+ dtos(buf+2, hint->width);
+ } else
+ dtos( buf, hint->width);
+ len2 = GDrawGetText8Width(pixmap,buf,-1,NULL);
+ GDrawDrawText8(pixmap,cv->width-len-5-len2-5,r.y,buf,-1,NULL,hintlabelcol);
+ }
+ }
+ }
+ if ( cv->showvhints && cv->sc->vstem!=NULL ) {
+ GDrawSetDashedLine(pixmap,5,5,cv->height-cv->yoff);
+ for ( hint = cv->sc->vstem; hint!=NULL; hint = hint->next ) {
+ if ( hint->width<0 ) {
+ r.x = cv->xoff + rint( (hint->start+hint->width)*cv->scale );
+ r.width = rint(-hint->width*cv->scale)+1;
+ } else {
+ r.x = cv->xoff + rint(hint->start*cv->scale);
+ r.width = rint(hint->width*cv->scale)+1;
+ }
+ col = hint->active ? vhintactivecol : vhintcol;
+ if ( r.x<32767 && r.x+r.width>-32768 ) {
+ if ( r.x<-32768 ) {
+ r.width -= (-32768-r.x);
+ r.x = -32768;
+ }
+ if ( r.x+r.width>32767 )
+ r.width = 32767-r.x;
+ for ( hi=hint->where; hi!=NULL; hi=hi->next ) {
+ r.y = -cv->yoff + cv->height - rint(hi->end*cv->scale);
+ end = -cv->yoff + cv->height - rint(hi->begin*cv->scale);
+ if ( end>=0 && r.y<=cv->height ) {
+ r.height = end-r.y+1;
+ GDrawFillRect(pixmap,&r,col);
+ }
+ }
+ }
+ col = (!hint->active && hint->hasconflicts) ? conflicthintcol : col;
+ if ( r.x>=0 && r.x<=cv->width )
+ GDrawDrawLine(pixmap,r.x,0,r.x,cv->height,col);
+ if ( r.x+r.width>=0 && r.x+r.width<=cv->width )
+ GDrawDrawLine(pixmap,r.x+r.width-1,0,r.x+r.width-1,cv->height,col);
+
+ r.x = cv->xoff + rint(hint->start*cv->scale);
+ if ( r.x>-60 && r.x<cv->width+20 ) {
+ dtos( buf, hint->start);
+ len = GDrawGetText8Width(pixmap,buf,-1,NULL);
+ r.x += ( hint->width>0 ) ? 3 : -len-3;
+ GDrawDrawText8(pixmap,r.x,cv->sas+3,buf,-1,NULL,hintlabelcol);
+ }
+ r.x = cv->xoff + rint((hint->start+hint->width)*cv->scale);
+ if ( r.x>-60 && r.x<cv->width+20 ) {
+ if ( hint->ghost ) {
+ buf[0] = 'G';
+ buf[1] = ' ';
+ dtos(buf+2, hint->width);
+ } else
+ dtos( buf, hint->width);
+ len = GDrawGetText8Width(pixmap,buf,-1,NULL);
+ r.x += ( hint->width>0 ) ? -len-3 : 3;
+ GDrawDrawText8(pixmap,r.x,cv->sas+cv->sfh+3,buf,-1,NULL,hintlabelcol);
+ }
+ }
+ }
+ GDrawSetDashedLine(pixmap,0,0,0);
+
+ for ( md=cv->sc->md; md!=NULL; md=md->next )
+ CVShowMinimumDistance(cv, pixmap,md);
+
+ if ( cv->showvhints || cv->showhhints ) {
+ for ( spl=cv->sc->layers[ly_fore].splines; spl!=NULL; spl=spl->next ) {
+ if ( spl->first->prev!=NULL ) for ( sp=spl->first ; ; ) {
+ if ( cv->showhhints && sp->flexx ) {
+ double x,y,end;
+ x = cv->xoff + rint(sp->me.x*cv->scale);
+ y = -cv->yoff + cv->height - rint(sp->me.y*cv->scale);
+ end = cv->xoff + rint(sp->next->to->me.x*cv->scale);
+ if ( x>-4096 && x<32767 && y>-4096 && y<32767 ) {
+ GDrawDrawLine(pixmap,x,y,end,y,hflexhintcol);
+ }
+ }
+ if ( cv->showvhints && sp->flexy ) {
+ double x,y,end;
+ x = cv->xoff + rint(sp->me.x*cv->scale);
+ y = -cv->yoff + cv->height - rint(sp->me.y*cv->scale);
+ end = -cv->yoff + cv->height - rint(sp->next->to->me.y*cv->scale);
+ if ( x>-4096 && x<32767 && y>-4096 && y<32767 ) {
+ GDrawDrawLine(pixmap,x,y,x,end,vflexhintcol);
+ }
+ }
+ if ( sp->next==NULL ) /* This can happen if we get an internal error inside of RemoveOverlap when the pointlist is not in good shape */
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ }
+ }
+}
+
+static void CVDrawRefName(CharView *cv,GWindow pixmap,RefChar *ref,int fg) {
+ unichar_t namebuf[100];
+ int x,y, len;
+
+ x = cv->xoff + rint(ref->top.x*cv->scale);
+ y = -cv->yoff + cv->height - rint(ref->top.y*cv->scale);
+ y -= 5;
+ if ( x<-400 || y<-40 || x>cv->width+400 || y>cv->height )
+return;
+
+ uc_strncpy(namebuf,ref->sc->name,sizeof(namebuf)/sizeof(namebuf[0]));
+ GDrawSetFont(pixmap,cv->small);
+ len = GDrawGetTextWidth(pixmap,namebuf,-1,NULL);
+ GDrawDrawText(pixmap,x-len/2,y,namebuf,-1,NULL,fg);
+}
+
+void DrawAnchorPoint(GWindow pixmap,int x, int y,int selected) {
+ GPoint gp[9];
+ Color col = anchorcol;
+
+ gp[0].x = x-1; gp[0].y = y-1;
+ gp[1].x = x; gp[1].y = y-6;
+ gp[2].x = x+1; gp[2].y = y-1;
+ gp[3].x = x+6; gp[3].y = y;
+ gp[4].x = x+1; gp[4].y = y+1;
+ gp[5].x = x; gp[5].y = y+6;
+ gp[6].x = x-1; gp[6].y = y+1;
+ gp[7].x = x-6; gp[7].y = y;
+ gp[8] = gp[0];
+ if ( selected )
+ GDrawDrawPoly(pixmap,gp,9,col);
+ else
+ GDrawFillPoly(pixmap,gp,9,col);
+}
+
+static void CVDrawAnchorPoints(CharView *cv,GWindow pixmap) {
+ int x,y, len, sel;
+ Color col = anchorcol;
+ AnchorPoint *ap;
+ char *name, ubuf[40];
+ GRect r;
+
+ if ( cv->drawmode!=dm_fore || cv->sc->anchor==NULL || !cv->showanchor )
+return;
+ GDrawSetFont(pixmap,cv->normal);
+
+ for ( sel=0; sel<2; ++sel ) {
+ for ( ap = cv->sc->anchor; ap!=NULL; ap=ap->next ) if ( ap->selected==sel ) {
+ x = cv->xoff + rint(ap->me.x*cv->scale);
+ y = -cv->yoff + cv->height - rint(ap->me.y*cv->scale);
+ if ( x<-400 || y<-40 || x>cv->width+400 || y>cv->height )
+ continue;
+
+ DrawAnchorPoint(pixmap,x,y,ap->selected);
+ if ( ap->anchor->type==act_mkmk ) {
+ strncpy(ubuf,ap->anchor->name,20);
+ strcat(ubuf," ");
+ strcat(ubuf,ap->type==at_basemark ? _("Base") : _("Mark") );
+ name = ubuf;
+ } else if ( ap->type==at_basechar || ap->type==at_mark || ap->type==at_basemark ) {
+ name = ap->anchor->name;
+ } else if ( ap->type==at_centry || ap->type==at_cexit ) {
+ strncpy(ubuf,ap->anchor->name,20);
+ strcat(ubuf,ap->type==at_centry ? _("Entry") : _("Exit") );
+ name = ubuf;
+ } else if ( ap->type==at_baselig ) {
+ strncpy(ubuf,ap->anchor->name,20);
+ sprintf(ubuf+strlen(ubuf),"#%d", ap->lig_index);
+ name = ubuf;
+ } else
+ name = NULL; /* Should never happen */
+ len = GDrawGetText8Width(pixmap,name,-1,NULL);
+ r.x = x-len/2; r.width = len;
+ r.y = y+7; r.height = cv->nfh;
+ GDrawFillRect(pixmap,&r,GDrawGetDefaultBackground(NULL));
+ GDrawDrawText8(pixmap,x-len/2,y+7+cv->nas,name,-1,NULL,col);
+ }
+ }
+}
+
+static void DrawImageList(CharView *cv,GWindow pixmap,ImageList *backimages) {
+ GRect size, temp;
+ int x,y;
+
+ GDrawGetSize(pixmap,&size);
+
+ while ( backimages!=NULL ) {
+ struct _GImage *base = backimages->image->list_len==0?
+ backimages->image->u.image:backimages->image->u.images[0];
+
+ temp = size;
+ x = (int) (cv->xoff + rint(backimages->xoff * cv->scale));
+ y = (int) (-cv->yoff + cv->height - rint(backimages->yoff*cv->scale));
+ temp.x -= x; temp.y -= y;
+
+ GDrawDrawImageMagnified(pixmap, backimages->image, &temp,
+ x,y,
+ (int) rint((base->width*backimages->xscale*cv->scale)),
+ (int) rint((base->height*backimages->yscale*cv->scale)));
+ backimages = backimages->next;
+ }
+}
+
+static void DrawSelImageList(CharView *cv,GWindow pixmap,ImageList *images) {
+ while ( images!=NULL ) {
+ if ( images->selected )
+ CVDrawBB(cv,pixmap,&images->bb);
+ images = images->next;
+ }
+}
+
+static void DrawOldState(CharView *cv, GWindow pixmap, Undoes *undo, DRect *clip) {
+ RefChar *refs;
+
+ if ( undo==NULL )
+return;
+
+ CVDrawSplineSet(cv,pixmap,undo->u.state.splines,oldoutlinecol,false,clip);
+ for ( refs=undo->u.state.refs; refs!=NULL; refs=refs->next )
+ if ( refs->layers[0].splines!=NULL )
+ CVDrawSplineSet(cv,pixmap,refs->layers[0].splines,oldoutlinecol,false,clip);
+ /* Don't do images... */
+}
+
+static void DrawTransOrigin(CharView *cv, GWindow pixmap) {
+ int x = rint(cv->p.cx*cv->scale) + cv->xoff, y = cv->height-cv->yoff-rint(cv->p.cy*cv->scale);
+
+ GDrawDrawLine(pixmap,x-4,y,x+4,y,transformorigincol);
+ GDrawDrawLine(pixmap,x,y-4,x,y+4,transformorigincol);
+}
+
+static void DrawVLine(CharView *cv,GWindow pixmap,real pos,Color fg, int flags, GImage *lock) {
+ char buf[20];
+ int x = cv->xoff + rint(pos*cv->scale);
+ DrawLine(cv,pixmap,pos,-32768,pos,32767,fg);
+ if ( flags&1 ) {
+ if ( x>-400 && x<cv->width+400 ) {
+ dtos( buf, pos);
+ GDrawSetFont(pixmap,cv->small);
+ GDrawDrawText8(pixmap,x+5,cv->sas+3,buf,-1,NULL,metricslabelcol);
+ if ( lock!=NULL )
+ GDrawDrawImage(pixmap,lock,NULL,x+5,3+cv->sfh);
+ }
+ }
+ if ( ItalicConstrained && cv->sc->parent->italicangle!=0 ) {
+ double s = sin(-cv->sc->parent->italicangle*3.1415926535897932/180.);
+ int xoff = rint(8096*s);
+ DrawLine(cv,pixmap,pos-xoff,-8096,pos+xoff,8096,italiccoordcol);
+ }
+}
+
+static void DrawMMGhosts(CharView *cv,GWindow pixmap,DRect *clip) {
+ /* In an MM font, draw any selected alternate versions of the current char */
+ MMSet *mm = cv->sc->parent->mm;
+ int j;
+ SplineFont *sub;
+ SplineChar *sc;
+ RefChar *rf;
+
+ if ( mm==NULL )
+return;
+ for ( j = 0; j<mm->instance_count+1; ++j ) {
+ if ( j==0 )
+ sub = mm->normal;
+ else
+ sub = mm->instances[j-1];
+ sc = NULL;
+ if ( cv->sc->parent!=sub && (cv->mmvisible & (1<<j)) &&
+ cv->sc->orig_pos<sub->glyphcnt )
+ sc = sub->glyphs[cv->sc->orig_pos];
+ if ( sc!=NULL ) {
+ for ( rf=sc->layers[ly_fore].refs; rf!=NULL; rf = rf->next )
+ CVDrawSplineSet(cv,pixmap,rf->layers[0].splines,backoutlinecol,false,clip);
+ CVDrawSplineSet(cv,pixmap,sc->layers[ly_fore].splines,backoutlinecol,false,clip);
+ }
+ }
+}
+
+static void CVDrawGridRaster(CharView *cv, GWindow pixmap, DRect *clip ) {
+ if ( cv->showgrids ) {
+ /* Draw ppem grid, and the raster for truetype debugging, grid fit */
+ GRect pixel;
+ real grid_spacing = (cv->sc->parent->ascent+cv->sc->parent->descent) / (real) cv->ft_ppem;
+ int max,jmax,ii,i,jj,j;
+ int minx, maxx, miny, maxy, r,or;
+ Color clut[256];
+
+ pixel.width = pixel.height = grid_spacing*cv->scale+1;
+ if ( cv->raster!=NULL ) {
+ if ( cv->raster->num_greys>2 ) {
+ int rb, gb, bb, rd, gd, bd;
+ clut[0] = GDrawGetDefaultBackground(NULL);
+ rb = COLOR_RED(clut[0]); gb = COLOR_GREEN(clut[0]); bb = COLOR_BLUE(clut[0]);
+ rd = COLOR_RED(rasterdarkcol)-rb;
+ gd = COLOR_GREEN(rasterdarkcol)-gb;
+ bd = COLOR_BLUE(rasterdarkcol)-bb;
+ for ( i=1; i<256; ++i ) {
+ clut[i] = ( (rb +rd*(i)/0xff)<<16 ) |
+ ( (gb+gd*(i)/0xff)<<8 ) |
+ ( (bb+bd*(i)/0xff) );
+ }
+ }
+ minx = cv->raster->lb; maxx = minx+cv->raster->cols;
+ maxy = cv->raster->as; miny = maxy-cv->raster->rows;
+ if ( cv->oldraster!=NULL ) {
+ if ( cv->oldraster->lb<minx ) minx = cv->oldraster->lb;
+ if ( cv->oldraster->lb+cv->oldraster->cols>maxx ) maxx = cv->oldraster->lb+cv->oldraster->cols;
+ if ( cv->oldraster->as>maxy ) maxy = cv->oldraster->as;
+ if ( cv->oldraster->as-cv->oldraster->rows<miny ) miny = cv->oldraster->as-cv->oldraster->rows;
+ }
+ for ( ii=maxy; ii>miny; --ii ) {
+ for ( jj=minx; jj<maxx; ++jj ) {
+ i = cv->raster->as-ii; j = jj-cv->raster->lb;
+ if ( i<0 || i>=cv->raster->rows || j<0 || j>=cv->raster->cols )
+ r = 0;
+ else if ( cv->raster->num_greys<=2 )
+ r = cv->raster->bitmap[i*cv->raster->bytes_per_row+(j>>3)] & (1<<(7-(j&7)));
+ else
+ r = cv->raster->bitmap[i*cv->raster->bytes_per_row+j];
+ if ( cv->oldraster==NULL || cv->oldraster->num_greys!=cv->raster->num_greys)
+ or = r;
+ else {
+ i = cv->oldraster->as-ii; j = jj-cv->oldraster->lb;
+ if ( i<0 || i>=cv->oldraster->rows || j<0 || j>=cv->oldraster->cols )
+ or = 0;
+ else if ( cv->raster->num_greys<=2 )
+ or = cv->oldraster->bitmap[i*cv->oldraster->bytes_per_row+(j>>3)] & (1<<(7-(j&7)));
+ else
+ or = cv->oldraster->bitmap[i*cv->oldraster->bytes_per_row+j];
+ }
+ if ( r || or ) {
+ pixel.x = jj*grid_spacing*cv->scale + cv->xoff;
+ pixel.y = cv->height-cv->yoff - rint(ii*grid_spacing*cv->scale);
+ if ( cv->raster->num_greys<=2 )
+ GDrawFillRect(pixmap,&pixel,(r && or) ? rastercol : r ? rasternewcol : rasteroldcol );
+ else
+ GDrawFillRect(pixmap,&pixel,(r-or>-16 && r-or<16) ? clut[r] : (clut[r]&0x00ff00) );
+ }
+ }
+ }
+ }
+
+ for ( i = floor( clip->x/grid_spacing ), max = ceil((clip->x+clip->width)/grid_spacing);
+ i<=max; ++i )
+ DrawLine(cv,pixmap,i*grid_spacing,-32768,i*grid_spacing,32767,i==0?coordcol:rastergridcol);
+ for ( i = floor( clip->y/grid_spacing ), max = ceil((clip->y+clip->height)/grid_spacing);
+ i<=max; ++i )
+ DrawLine(cv,pixmap,-32768,i*grid_spacing,32767,i*grid_spacing,i==0?coordcol:rastergridcol);
+ if ( grid_spacing*cv->scale>=7 ) {
+ for ( i = floor( clip->x/grid_spacing ), max = ceil((clip->x+clip->width)/grid_spacing);
+ i<=max; ++i )
+ for ( j = floor( clip->y/grid_spacing ), jmax = ceil((clip->y+clip->height)/grid_spacing);
+ j<=jmax; ++j ) {
+ int x = (i+.5)*grid_spacing*cv->scale + cv->xoff;
+ int y = cv->height-cv->yoff - rint((j+.5)*grid_spacing*cv->scale);
+ GDrawDrawLine(pixmap,x-2,y,x+2,y,rastergridcol);
+ GDrawDrawLine(pixmap,x,y-2,x,y+2,rastergridcol);
+ }
+ }
+ }
+ if ( cv->showback ) {
+ CVDrawSplineSet(cv,pixmap,cv->gridfit,gridfitoutlinecol,
+ cv->showpoints,clip);
+ }
+}
+
+static int APinSC(AnchorPoint *ap,SplineChar *sc) {
+ /* Anchor points can be deleted ... */
+ AnchorPoint *test;
+
+ for ( test=sc->anchor; test!=NULL && test!=ap; test = test->next );
+return( test==ap );
+}
+
+static void DrawAPMatch(CharView *cv,GWindow pixmap,DRect *clip) {
+ SplineChar *sc = cv->sc, *apsc = cv->apsc;
+ SplineFont *sf = sc->parent;
+ real trans[6];
+ SplineSet *head, *tail, *temp;
+ RefChar *ref;
+
+ /* The other glyph might have been removed from the font */
+ /* Either anchor might have been deleted. Be prepared for that to happen */
+ if ( (apsc->orig_pos>=sf->glyphcnt || apsc->orig_pos<0) ||
+ sf->glyphs[apsc->orig_pos]!=apsc ||
+ !APinSC(cv->apmine,sc) || !APinSC(cv->apmatch,apsc)) {
+ cv->apmine = cv->apmatch = NULL;
+ cv->apsc =NULL;
+return;
+ }
+
+ /* Ok this isn't very accurate, but we are going to use the current glyph's*/
+ /* coordinate system (because we're showing the current glyph), we should */
+ /* always use the base character's coordinates, but that would screw up */
+ /* editing of the current glyph if it happened to be the mark */
+ trans[0] = trans[3] = 1;
+ trans[1] = trans[2] = 0;
+ trans[4] = cv->apmine->me.x - cv->apmatch->me.x;
+ trans[5] = cv->apmine->me.y - cv->apmatch->me.y;
+
+ head = tail = SplinePointListCopy(apsc->layers[ly_fore].splines);
+ for ( ref = apsc->layers[ly_fore].refs; ref!=NULL; ref = ref->next ) {
+ temp = SplinePointListCopy(ref->layers[0].splines);
+ if ( head!=NULL ) {
+ for ( ; tail->next!=NULL; tail = tail->next );
+ tail->next = temp;
+ } else
+ head = tail = temp;
+ }
+ head = SplinePointListTransform(head,trans,true);
+ CVDrawSplineSet(cv,pixmap,head,anchoredoutlinecol,
+ false,clip);
+ SplinePointListsFree(head);
+ if ( cv->apmine->type==at_mark || cv->apmine->type==at_centry ) {
+ DrawVLine(cv,pixmap,trans[4],anchoredoutlinecol,false,NULL);
+ DrawLine(cv,pixmap,-8096,trans[5],8096,trans[5],anchoredoutlinecol);
+ }
+}
+
+static void DrawPLine(CharView *cv,GWindow pixmap,int x1, int y1, int x2, int y2,Color col) {
+
+ if ( x1==x2 || y1==y2 ) {
+ if ( x1<0 ) x1=0;
+ else if ( x1>cv->width ) x1 = cv->width;
+ if ( x2<0 ) x2=0;
+ else if ( x2>cv->width ) x2 = cv->width;
+ if ( y1<0 ) y1=0;
+ else if ( y1>cv->height ) y1 = cv->height;
+ if ( y2<0 ) y2=0;
+ else if ( y2>cv->height ) y2 = cv->height;
+ } else if ( y1<-1000 || y2<-1000 || x1<-1000 || x2<-1000 ||
+ y1>cv->height+1000 || y2>cv->height+1000 ||
+ x1>cv->width+1000 || x2>cv->width+1000 )
+return;
+ GDrawDrawLine(pixmap,x1,y1,x2,y2,col);
+}
+
+static void FindQuickBounds(SplineSet *ss,BasePoint **bounds) {
+ SplinePoint *sp;
+
+ for ( ; ss!=NULL; ss=ss->next ) {
+ sp = ss->first;
+ if ( sp->next==NULL || sp->next->to==sp ) /* Ignore contours with one point. Often tt points for moving references or anchors */
+ continue;
+ forever {
+ if ( bounds[0]==NULL )
+ bounds[0] = bounds[1] = bounds[2] = bounds[3] = &sp->me;
+ else {
+ if ( sp->me.x<bounds[0]->x ) bounds[0] = &sp->me;
+ if ( sp->me.x>bounds[1]->x ) bounds[1] = &sp->me;
+ if ( sp->me.y<bounds[2]->y ) bounds[2] = &sp->me;
+ if ( sp->me.y>bounds[3]->y ) bounds[3] = &sp->me;
+ }
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ }
+}
+
+static void CVSideBearings(GWindow pixmap, CharView *cv) {
+ SplineChar *sc = cv->sc;
+ RefChar *ref;
+ BasePoint *bounds[4];
+ int layer,l;
+ int x,y, x2, y2;
+ char buf[20];
+
+ memset(bounds,0,sizeof(bounds));
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ FindQuickBounds(sc->layers[layer].splines,bounds);
+ for ( ref=sc->layers[layer].refs; ref!=NULL; ref=ref->next )
+ for ( l=0; l<ref->layer_cnt; ++l )
+ FindQuickBounds(ref->layers[l].splines,bounds);
+ }
+
+ if ( bounds[0]==NULL )
+return; /* no points. no side bearings */
+
+ GDrawSetFont(pixmap,cv->small);
+ if ( cv->showhmetrics ) {
+ if ( bounds[0]->x!=0 ) {
+ x = rint(bounds[0]->x*cv->scale) + cv->xoff;
+ y = cv->height-cv->yoff-rint(bounds[0]->y*cv->scale);
+ DrawPLine(cv,pixmap,cv->xoff,y,x,y,metricslabelcol);
+ /* arrow heads */
+ DrawPLine(cv,pixmap,cv->xoff,y,cv->xoff+4,y+4,metricslabelcol);
+ DrawPLine(cv,pixmap,cv->xoff,y,cv->xoff+4,y-4,metricslabelcol);
+ DrawPLine(cv,pixmap,x,y,x-4,y-4,metricslabelcol);
+ DrawPLine(cv,pixmap,x,y,x-4,y+4,metricslabelcol);
+ dtos( buf, bounds[0]->x);
+ x = cv->xoff + (x-cv->xoff-GDrawGetText8Width(pixmap,buf,-1,NULL))/2;
+ GDrawDrawText8(pixmap,x,y-4,buf,-1,NULL,metricslabelcol);
+ }
+
+ if ( sc->width != bounds[1]->x ) {
+ x = rint(bounds[1]->x*cv->scale) + cv->xoff;
+ y = cv->height-cv->yoff-rint(bounds[1]->y*cv->scale);
+ x2 = rint(sc->width*cv->scale) + cv->xoff;
+ DrawPLine(cv,pixmap,x,y,x2,y,metricslabelcol);
+ /* arrow heads */
+ DrawPLine(cv,pixmap,x,y,x+4,y+4,metricslabelcol);
+ DrawPLine(cv,pixmap,x,y,x+4,y-4,metricslabelcol);
+ DrawPLine(cv,pixmap,x2,y,x2-4,y-4,metricslabelcol);
+ DrawPLine(cv,pixmap,x2,y,x2-4,y+4,metricslabelcol);
+ dtos( buf, sc->width-bounds[1]->x);
+ x = x + (x2-x-GDrawGetText8Width(pixmap,buf,-1,NULL))/2;
+ GDrawDrawText8(pixmap,x,y-4,buf,-1,NULL,metricslabelcol);
+ }
+ }
+
+ if ( cv->showvmetrics ) {
+ x = rint(bounds[2]->x*cv->scale) + cv->xoff;
+ y = cv->height-cv->yoff-rint(bounds[2]->y*cv->scale);
+ y2 = cv->height-cv->yoff-rint(-sc->parent->descent*cv->scale);
+ DrawPLine(cv,pixmap,x,y,x,y2,metricslabelcol);
+ /* arrow heads */
+ DrawPLine(cv,pixmap,x,y,x-4,y-4,metricslabelcol);
+ DrawPLine(cv,pixmap,x,y,x+4,y-4,metricslabelcol);
+ DrawPLine(cv,pixmap,x,y2,x+4,y2+4,metricslabelcol);
+ DrawPLine(cv,pixmap,x,y2,x-4,y2+4,metricslabelcol);
+ dtos( buf, bounds[2]->y-sc->parent->descent);
+ y = y + (y-y2-cv->sfh)/2;
+ GDrawDrawText8(pixmap,x+4,y,buf,-1,NULL,metricslabelcol);
+
+ x = rint(bounds[3]->x*cv->scale) + cv->xoff;
+ y = cv->height-cv->yoff-rint(bounds[3]->y*cv->scale);
+ y2 = cv->height-cv->yoff-rint(sc->parent->ascent*cv->scale);
+ DrawPLine(cv,pixmap,x,y,x,y2,metricslabelcol);
+ /* arrow heads */
+ DrawPLine(cv,pixmap,x,y,x-4,y-4,metricslabelcol);
+ DrawPLine(cv,pixmap,x,y,x+4,y-4,metricslabelcol);
+ DrawPLine(cv,pixmap,x,y2,x+4,y2+4,metricslabelcol);
+ DrawPLine(cv,pixmap,x,y2,x-4,y2+4,metricslabelcol);
+ dtos( buf, sc->vwidth-bounds[3]->y);
+ x = x + (x2-x-GDrawGetText8Width(pixmap,buf,-1,NULL))/2;
+ GDrawDrawText8(pixmap,x,y-4,buf,-1,NULL,metricslabelcol);
+ }
+}
+
+static void CVExpose(CharView *cv, GWindow pixmap, GEvent *event ) {
+ SplineFont *sf = cv->sc->parent;
+ RefChar *rf;
+ GRect old;
+ DRect clip;
+ char buf[20];
+ PST *pst; int i, layer, rlayer;
+
+ GDrawPushClip(pixmap,&event->u.expose.rect,&old);
+
+ clip.width = event->u.expose.rect.width/cv->scale;
+ clip.height = event->u.expose.rect.height/cv->scale;
+ clip.x = (event->u.expose.rect.x-cv->xoff)/cv->scale;
+ clip.y = (cv->height-event->u.expose.rect.y-event->u.expose.rect.height-cv->yoff)/cv->scale;
+
+ GDrawSetFont(pixmap,cv->small);
+ GDrawSetLineWidth(pixmap,0);
+
+ if ( !cv->show_ft_results && cv->dv==NULL ) {
+ /* if we've got bg images (and we're showing them) then the hints live in */
+ /* the bg image pixmap (else they get overwritten by the pixmap) */
+ if ( (cv->showhhints || cv->showvhints || cv->showdhints) && ( cv->sc->layers[ly_back].images==NULL || !cv->showback) )
+ CVShowHints(cv,pixmap);
+
+ for ( layer = ly_back; layer<cv->sc->layer_cnt; ++layer ) if ( cv->sc->layers[layer].images!=NULL ) {
+ if ( (( cv->showback || cv->drawmode==dm_back ) && layer==ly_back ) ||
+ (( cv->showfore || cv->drawmode==dm_fore ) && layer>ly_back )) {
+ /* This really should be after the grids, but then it would completely*/
+ /* hide them. */
+ GRect r;
+ if ( cv->backimgs==NULL )
+ cv->backimgs = GDrawCreatePixmap(GDrawGetDisplayOfWindow(cv->v),cv->width,cv->height);
+ if ( cv->back_img_out_of_date ) {
+ GDrawFillRect(cv->backimgs,NULL,GDrawGetDefaultBackground(GDrawGetDisplayOfWindow(cv->v)));
+ if ( cv->showhhints || cv->showvhints || cv->showdhints)
+ CVShowHints(cv,cv->backimgs);
+ DrawImageList(cv,cv->backimgs,cv->sc->layers[layer].images);
+ cv->back_img_out_of_date = false;
+ }
+ r.x = r.y = 0; r.width = cv->width; r.height = cv->height;
+ GDrawDrawPixmap(pixmap,cv->backimgs,&r,0,0);
+ }
+ }
+ if ( cv->showgrids || cv->drawmode==dm_grid ) {
+ CVDrawSplineSet(cv,pixmap,cv->fv->sf->grid.splines,guideoutlinecol,
+ cv->showpoints && cv->drawmode==dm_grid,&clip);
+ }
+ if ( cv->showhmetrics ) {
+ DrawVLine(cv,pixmap,0,coordcol,false,NULL);
+ DrawLine(cv,pixmap,-8096,0,8096,0,coordcol);
+ DrawLine(cv,pixmap,-8096,sf->ascent,8096,sf->ascent,coordcol);
+ DrawLine(cv,pixmap,-8096,-sf->descent,8096,-sf->descent,coordcol);
+ }
+ if ( cv->showvmetrics ) {
+ DrawLine(cv,pixmap,(sf->ascent+sf->descent)/2,-8096,(sf->ascent+sf->descent)/2,8096,coordcol);
+ DrawLine(cv,pixmap,-8096,sf->vertical_origin,8096,sf->vertical_origin,coordcol);
+ }
+
+ DrawSelImageList(cv,pixmap,cv->layerheads[cv->drawmode]->images);
+
+ if (( cv->showfore || cv->drawmode==dm_fore ) && cv->showfilled ) {
+ /* Wrong order, I know. But it is useful to have the background */
+ /* visible on top of the fill... */
+ cv->gi.u.image->clut->clut[1] = fillcol;
+ GDrawDrawImage(pixmap, &cv->gi, NULL, cv->xoff + cv->filled->xmin,
+ -cv->yoff + cv->height-cv->filled->ymax);
+ cv->gi.u.image->clut->clut[1] = backimagecol;
+ }
+ } else {
+ /* Draw FreeType Results */
+ CVDrawGridRaster(cv,pixmap,&clip);
+ }
+
+ if ( cv->layerheads[cv->drawmode]->undoes!=NULL && cv->layerheads[cv->drawmode]->undoes->undotype==ut_tstate )
+ DrawOldState(cv,pixmap,cv->layerheads[cv->drawmode]->undoes, &clip);
+
+ if ( !cv->show_ft_results && cv->dv==NULL ) {
+ if ( cv->showback || cv->drawmode==dm_back ) {
+ /* Used to draw the image list here, but that's too slow. Optimization*/
+ /* is to draw to pixmap, dump pixmap a bit earlier */
+ /* Then when we moved the fill image around, we had to deal with the */
+ /* images before the fill... */
+ CVDrawLayerSplineSet(cv,pixmap,&cv->sc->layers[ly_back],backoutlinecol,
+ cv->showpoints && cv->drawmode==dm_back,&clip);
+ if ( cv->template1!=NULL )
+ CVDrawTemplates(cv,pixmap,cv->template1,&clip);
+ if ( cv->template2!=NULL )
+ CVDrawTemplates(cv,pixmap,cv->template2,&clip);
+ }
+ if ( cv->mmvisible!=0 )
+ DrawMMGhosts(cv,pixmap,&clip);
+ }
+
+ if ( cv->showfore || (cv->drawmode==dm_fore && !cv->show_ft_results && cv->dv==NULL)) {
+ CVDrawAnchorPoints(cv,pixmap);
+ for ( layer=ly_fore ; layer<cv->sc->layer_cnt; ++layer ) {
+ for ( rf=cv->sc->layers[layer].refs; rf!=NULL; rf = rf->next ) {
+ CVDrawRefName(cv,pixmap,rf,0);
+ for ( rlayer=0; rlayer<rf->layer_cnt; ++rlayer )
+ CVDrawSplineSet(cv,pixmap,rf->layers[rlayer].splines,foreoutlinecol,-1,&clip);
+ if ( rf->selected && cv->layerheads[cv->drawmode]==&cv->sc->layers[layer])
+ CVDrawBB(cv,pixmap,&rf->bb);
+ }
+
+ CVDrawLayerSplineSet(cv,pixmap,&cv->sc->layers[layer],foreoutlinecol,
+ cv->showpoints && cv->drawmode==dm_fore,&clip);
+ }
+ }
+
+ if ( cv->freehand.current_trace!=NULL )
+ CVDrawSplineSet(cv,pixmap,cv->freehand.current_trace,tracecol,
+ false,&clip);
+
+ if ( cv->showhmetrics && cv->searcher==NULL ) {
+ RefChar *lock = HasUseMyMetrics(cv->sc);
+ if ( lock!=NULL ) cv->sc->width = lock->sc->width;
+ DrawVLine(cv,pixmap,cv->sc->width,(!cv->inactive && cv->widthsel)?widthselcol:widthcol,true,
+ lock!=NULL ? &GIcon_lock : NULL);
+ for ( pst=cv->sc->possub; pst!=NULL && pst->type!=pst_lcaret; pst=pst->next );
+ if ( pst!=NULL ) {
+ for ( i=0; i<pst->u.lcaret.cnt; ++i )
+ DrawVLine(cv,pixmap,pst->u.lcaret.carets[i],lcaretcol,true,NULL);
+ }
+ if ( cv->show_ft_results || cv->dv!=NULL )
+ DrawVLine(cv,pixmap,cv->ft_gridfitwidth,widthgridfitcol,true,NULL);
+ }
+ if ( cv->showvmetrics ) {
+ int len, y = -cv->yoff + cv->height - rint((sf->vertical_origin-cv->sc->vwidth)*cv->scale);
+ DrawLine(cv,pixmap,-32768,sf->vertical_origin-cv->sc->vwidth,
+ 32767,sf->vertical_origin-cv->sc->vwidth,
+ (!cv->inactive && cv->vwidthsel)?widthselcol:widthcol);
+ if ( y>-40 && y<cv->height+40 ) {
+ dtos( buf, cv->sc->vwidth);
+ GDrawSetFont(pixmap,cv->small);
+ len = GDrawGetText8Width(pixmap,buf,-1,NULL);
+ GDrawDrawText8(pixmap,cv->width-len-5,y,buf,-1,NULL,metricslabelcol);
+ }
+ }
+ if ( cv->showsidebearings && cv->showfore &&
+ (cv->showvmetrics || cv->showhmetrics))
+ CVSideBearings(pixmap,cv);
+
+ if ( cv->p.rubberbanding )
+ CVDrawRubberRect(pixmap,cv);
+ if ( cv->p.rubberlining )
+ CVDrawRubberLine(pixmap,cv);
+ if ((( cv->active_tool >= cvt_scale && cv->active_tool <= cvt_perspective ) ||
+ cv->active_shape!=NULL ) &&
+ cv->p.pressed )
+ DrawTransOrigin(cv,pixmap);
+ if ( cv->apmine!=NULL )
+ DrawAPMatch(cv,pixmap,&clip);
+
+ GDrawPopClip(pixmap,&old);
+}
+#endif
+
+void SCUpdateAll(SplineChar *sc) {
+#if defined(FONTFORGE_CONFIG_GTK)
+ CharView *cv;
+ struct splinecharlist *dlist;
+
+ for ( cv=sc->views; cv!=NULL; cv=cv->next )
+ gtk_widget_queue_draw(cv->v);
+ for ( dlist=sc->dependents; dlist!=NULL; dlist=dlist->next )
+ SCUpdateAll(dlist->sc);
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+ CharView *cv;
+ struct splinecharlist *dlist;
+ MetricsView *mv;
+ FontView *fv;
+
+ for ( cv=sc->views; cv!=NULL; cv=cv->next )
+ GDrawRequestExpose(cv->v,NULL,false);
+ for ( dlist=sc->dependents; dlist!=NULL; dlist=dlist->next )
+ SCUpdateAll(dlist->sc);
+ if ( sc->parent!=NULL ) {
+ for ( fv = sc->parent->fv; fv!=NULL; fv=fv->nextsame )
+ FVRegenChar(fv,sc);
+ for ( mv = sc->parent->metrics; mv!=NULL; mv=mv->next )
+ MVRegenChar(mv,sc);
+ }
+#endif
+}
+
+void SCOutOfDateBackground(SplineChar *sc) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ CharView *cv;
+
+ for ( cv=sc->views; cv!=NULL; cv=cv->next )
+ cv->back_img_out_of_date = true;
+#endif
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static void CVRegenFill(CharView *cv) {
+ if ( cv->showfilled ) {
+ BDFCharFree(cv->filled);
+ cv->filled = SplineCharRasterize(cv->sc,cv->scale*(cv->fv->sf->ascent+cv->fv->sf->descent)+.1);
+ cv->gi.u.image->data = cv->filled->bitmap;
+ cv->gi.u.image->bytes_per_line = cv->filled->bytes_per_line;
+ cv->gi.u.image->width = cv->filled->xmax-cv->filled->xmin+1;
+ cv->gi.u.image->height = cv->filled->ymax-cv->filled->ymin+1;
+ GDrawRequestExpose(cv->v,NULL,false);
+ }
+}
+
+static void FVRedrawAllCharViews(FontView *fv) {
+ int i;
+ CharView *cv;
+
+ for ( i=0; i<fv->sf->glyphcnt; ++i ) if ( fv->sf->glyphs[i]!=NULL )
+ for ( cv = fv->sf->glyphs[i]->views; cv!=NULL; cv=cv->next )
+ GDrawRequestExpose(cv->v,NULL,false);
+}
+
+static void SCRegenFills(SplineChar *sc) {
+ struct splinecharlist *dlist;
+ CharView *cv;
+
+ for ( cv = sc->views; cv!=NULL; cv=cv->next )
+ CVRegenFill(cv);
+ for ( dlist=sc->dependents; dlist!=NULL; dlist=dlist->next )
+ SCRegenFills(dlist->sc);
+}
+
+static void SCRegenDependents(SplineChar *sc) {
+ struct splinecharlist *dlist;
+ FontView *fv;
+
+ for ( fv = sc->parent->fv; fv!=NULL; fv=fv->nextsame ) {
+ if ( fv->sv!=NULL ) {
+ SCReinstanciateRef(&fv->sv->sc_srch,sc);
+ SCReinstanciateRef(&fv->sv->sc_rpl,sc);
+ }
+ }
+
+ for ( dlist=sc->dependents; dlist!=NULL; dlist=dlist->next ) {
+ SCReinstanciateRef(dlist->sc,sc);
+ SCRegenDependents(dlist->sc);
+ }
+}
+
+static void CVUpdateInfo(CharView *cv, GEvent *event) {
+
+ cv->info_within = true;
+ cv->e.x = event->u.mouse.x; cv->e.y = event->u.mouse.y;
+ cv->info.x = (event->u.mouse.x-cv->xoff)/cv->scale;
+ cv->info.y = (cv->height-event->u.mouse.y-cv->yoff)/cv->scale;
+ CVInfoDraw(cv,cv->gw);
+}
+
+static void CVNewScale(CharView *cv) {
+ GEvent e;
+
+ CVRegenFill(cv);
+ cv->back_img_out_of_date = true;
+
+ GScrollBarSetBounds(cv->vsb,-20000*cv->scale,8000*cv->scale,cv->height);
+ GScrollBarSetBounds(cv->hsb,-8000*cv->scale,32000*cv->scale,cv->width);
+ GScrollBarSetPos(cv->vsb,cv->yoff-cv->height);
+ GScrollBarSetPos(cv->hsb,-cv->xoff);
+
+ GDrawRequestExpose(cv->v,NULL,false);
+ if ( cv->showrulers )
+ GDrawRequestExpose(cv->gw,NULL,false);
+ GDrawGetPointerPosition(cv->v,&e);
+ CVUpdateInfo(cv,&e);
+}
+
+static void _CVFit(CharView *cv,DBounds *b) {
+ real left, right, top, bottom, hsc, wsc;
+ extern int palettes_docked;
+ int offset = palettes_docked ? 90 : 0;
+ int em = cv->sc->parent->ascent + cv->sc->parent->descent;
+ int hsmall = true;
+
+ if ( offset>cv->width ) offset = 0;
+
+ bottom = b->miny;
+ top = b->maxy;
+ left = b->minx;
+ right = b->maxx;
+
+ if ( top<bottom ) IError("Bottom bigger than top!");
+ if ( right<left ) IError("Left bigger than right!");
+ top -= bottom;
+ right -= left;
+ if ( top==0 ) top = em;
+ if ( right==0 ) right = em;
+ wsc = (cv->width-offset) / right;
+ hsc = cv->height / top;
+ if ( wsc<hsc ) { hsc = wsc; hsmall = false ; }
+
+ cv->scale = hsc;
+ if ( cv->scale > 1.0 ) {
+ cv->scale = floor(2*cv->scale)/2;
+ } else {
+ cv->scale = 2/ceil(2/cv->scale);
+ }
+
+ cv->xoff = -left *cv->scale + offset;
+ if ( hsmall )
+ cv->yoff = -bottom*cv->scale;
+ else
+ cv->yoff = -(bottom+top/2)*cv->scale + cv->height/2;
+
+ CVNewScale(cv);
+}
+
+static void CVFit(CharView *cv) {
+ DBounds b;
+ double center;
+
+ SplineCharFindBounds(cv->sc,&b);
+ if ( b.miny==0 && b.maxy==0 ) {
+ b.maxy =cv->sc->parent->ascent;
+ b.miny = -cv->sc->parent->descent;
+ }
+ if ( b.miny>=0 ) b.miny = -cv->sc->parent->descent;
+ if ( b.minx>0 ) b.minx = 0;
+ if ( b.maxx<0 ) b.maxx = 0;
+ if ( b.maxy<0 ) b.maxy = 0;
+ if ( b.maxx<cv->sc->width ) b.maxx = cv->sc->width;
+ /* Now give some extra space around the interesting stuff */
+ center = (b.maxx+b.minx)/2;
+ b.minx = center - (center - b.minx)*1.2;
+ b.maxx = center + (b.maxx - center)*1.2;
+ center = (b.maxy+b.miny)/2;
+ b.miny = center - (center - b.miny)*1.2;
+ b.maxy = center + (b.maxy - center)*1.2;
+
+ _CVFit(cv,&b);
+}
+
+static void CVUnlinkView(CharView *cv ) {
+ CharView *test;
+
+ if ( cv->sc->views == cv ) {
+ cv->sc->views = cv->next;
+ } else {
+ for ( test=cv->sc->views; test->next!=cv && test->next!=NULL; test=test->next );
+ if ( test->next==cv )
+ test->next = cv->next;
+ }
+}
+
+static GWindow CharIcon(CharView *cv, FontView *fv) {
+ SplineChar *sc = cv->sc;
+ BDFFont *bdf, *bdf2;
+ BDFChar *bdfc;
+ GWindow icon = cv->icon;
+ GRect r;
+
+ r.x = r.y = 0; r.width = r.height = fv->cbw-1;
+ if ( icon == NULL )
+ cv->icon = icon = GDrawCreateBitmap(NULL,r.width,r.width,NULL);
+ GDrawFillRect(icon,&r,0x0); /* for some reason icons seem to be color reversed by my defn */
+
+ bdf = NULL; bdfc = NULL;
+ if ( sc->layers[ly_fore].refs!=NULL || sc->layers[ly_fore].splines!=NULL ) {
+ bdf = fv->show;
+ if ( sc->orig_pos>=bdf->glyphcnt || bdf->glyphs[sc->orig_pos]==NULL )
+ bdf = fv->filled;
+ if ( sc->orig_pos>=bdf->glyphcnt || bdf->glyphs[sc->orig_pos]==NULL ) {
+ bdf2 = NULL; bdfc = NULL;
+ for ( bdf=fv->sf->bitmaps; bdf!=NULL && bdf->pixelsize<24 ; bdf=bdf->next )
+ bdf2 = bdf;
+ if ( bdf2!=NULL && bdf!=NULL ) {
+ if ( 24-bdf2->pixelsize < bdf->pixelsize-24 )
+ bdf = bdf2;
+ } else if ( bdf==NULL )
+ bdf = bdf2;
+ }
+ if ( bdf!=NULL && sc->orig_pos<bdf->glyphcnt )
+ bdfc = bdf->glyphs[sc->orig_pos];
+ }
+
+ if ( bdfc!=NULL ) {
+ GClut clut;
+ struct _GImage base;
+ GImage gi;
+ /* if not empty, use the font's own shape, otherwise use a standard */
+ /* font */
+ memset(&gi,'\0',sizeof(gi));
+ memset(&base,'\0',sizeof(base));
+ memset(&clut,'\0',sizeof(clut));
+ gi.u.image = &base;
+ base.trans = -1;
+ base.clut = &clut;
+ if ( bdfc->byte_data ) { int i;
+ base.image_type = it_index;
+ clut.clut_len = bdf->clut->clut_len;
+ for ( i=0; i<clut.clut_len; ++i ) {
+ int v = 255-i*255/(clut.clut_len-1);
+ clut.clut[i] = COLOR_CREATE(v,v,v);
+ }
+ clut.trans_index = -1;
+ } else {
+ base.image_type = it_mono;
+ clut.clut_len = 2;
+ clut.clut[1] = 0xffffff;
+ }
+ base.data = bdfc->bitmap;
+ base.bytes_per_line = bdfc->bytes_per_line;
+ base.width = bdfc->xmax-bdfc->xmin+1;
+ base.height = bdfc->ymax-bdfc->ymin+1;
+ GDrawDrawImage(icon,&gi,NULL,(r.width-base.width)/2,(r.height-base.height)/2);
+ } else if ( sc->unicodeenc!=-1 ) {
+ FontRequest rq;
+ GFont *font;
+ static unichar_t times[] = { 't', 'i', 'm', 'e', 's',',','c','l','e','a','r','l','y','u',',','u','n','i','f','o','n','t', '\0' };
+ unichar_t text[2];
+ int as, ds, ld, width;
+
+ memset(&rq,0,sizeof(rq));
+ rq.family_name = times;
+ rq.point_size = 24;
+ rq.weight = 400;
+ font = GDrawInstanciateFont(NULL,&rq);
+ GDrawSetFont(icon,font);
+ text[0] = sc->unicodeenc; text[1] = 0;
+ GDrawFontMetrics(font,&as,&ds,&ld);
+ width = GDrawGetTextWidth(icon,text,1,NULL);
+ GDrawDrawText(icon,(r.width-width)/2,(r.height-as-ds)/2+as,text,1,NULL,0xffffff);
+ }
+return( icon );
+}
+
+static int CVCurEnc(CharView *cv) {
+ if ( cv->map_of_enc == cv->fv->map && cv->enc!=-1 )
+return( cv->enc );
+
+return( cv->fv->map->backmap[cv->sc->orig_pos] );
+}
+
+static char *CVMakeTitles(CharView *cv,char *buf) {
+ char *title;
+ SplineChar *sc = cv->sc;
+
+/* GT: This is the title for a window showing an outline character */
+/* GT: It will look something like: */
+/* GT: exclam at 33 from Arial */
+/* GT: $1 is the name of the glyph */
+/* GT: $2 is the glyph's encoding */
+/* GT: $3 is the font name */
+ sprintf(buf,_("%1$.80s at %2$d from %3$.90s"),
+ sc->name, CVCurEnc(cv), sc->parent->fontname);
+ if ( sc->changed )
+ strcat(buf," *");
+ title = copy(buf);
+ if ( sc->unicodeenc!=-1 && sc->unicodeenc<0x110000 && _UnicodeNameAnnot!=NULL &&
+ _UnicodeNameAnnot[sc->unicodeenc>>16][(sc->unicodeenc>>8)&0xff][sc->unicodeenc&0xff].name!=NULL ) {
+ strcat(buf, " ");
+ latin1_2_utf8_strcpy(buf+strlen(buf), _UnicodeNameAnnot[sc->unicodeenc>>16][(sc->unicodeenc>>8)&0xff][sc->unicodeenc&0xff].name);
+ }
+ if ( cv->show_ft_results || cv->dv )
+ sprintf(buf+strlen(buf), " (%gpt, %ddpi)", (double) cv->ft_pointsize, cv->ft_dpi );
+return( title );
+}
+
+void SCRefreshTitles(SplineChar *sc) {
+ /* Called if the user changes the unicode encoding or the character name */
+ CharView *cv;
+ char buf[300], *title;
+
+ if ( sc->views==NULL )
+return;
+ for ( cv = sc->views; cv!=NULL; cv=cv->next ) {
+ title = CVMakeTitles(cv,buf);
+ /* Could be different if one window is debugging and one is not */
+ GDrawSetWindowTitles8(cv->gw,buf,title);
+ free(title);
+ }
+}
+
+static void CVChangeTabsVisibility(CharView *cv,int makevisible) {
+ GRect gsize, pos, sbsize;
+
+ if ( cv->tabs==NULL || GGadgetIsVisible(cv->tabs)==makevisible )
+return;
+ GGadgetGetSize(cv->tabs,&gsize);
+ GGadgetGetSize(cv->vsb,&sbsize);
+ if ( makevisible ) {
+ cv->mbh += gsize.height;
+ cv->height -= gsize.height;
+ GGadgetMove(cv->vsb,sbsize.x,sbsize.y+gsize.height);
+ GGadgetResize(cv->vsb,sbsize.width,sbsize.height-gsize.height);
+ } else {
+ cv->mbh -= gsize.height;
+ cv->height += gsize.height;
+ GGadgetMove(cv->vsb,sbsize.x,sbsize.y-gsize.height);
+ GGadgetResize(cv->vsb,sbsize.width,sbsize.height+gsize.height);
+ }
+ GGadgetSetVisible(cv->tabs,makevisible);
+ cv->back_img_out_of_date = true;
+ pos.x = 0; pos.y = cv->mbh+cv->infoh;
+ pos.width = cv->width; pos.height = cv->height;
+ if ( cv->showrulers ) {
+ pos.x += cv->rulerh;
+ pos.y += cv->rulerh;
+ }
+ GDrawMoveResize(cv->v,pos.x,pos.y,pos.width,pos.height);
+ GDrawSync(NULL);
+ GDrawRequestExpose(cv->v,NULL,false);
+ GDrawRequestExpose(cv->gw,NULL,false);
+}
+
+void CVChangeSC(CharView *cv, SplineChar *sc ) {
+ char *title;
+ char buf[300];
+ extern int updateflex;
+ int i;
+
+ CVDebugFree(cv->dv);
+
+ if ( cv->expandedge != ee_none ) {
+ GDrawSetCursor(cv->v,ct_mypointer);
+ cv->expandedge = ee_none;
+ }
+
+ SplinePointListsFree(cv->gridfit); cv->gridfit = NULL;
+ FreeType_FreeRaster(cv->oldraster); cv->oldraster = NULL;
+ FreeType_FreeRaster(cv->raster); cv->raster = NULL;
+
+ SCLigCaretCheck(sc,false);
+
+ CVUnlinkView(cv);
+ cv->p.nextcp = cv->p.prevcp = cv->widthsel = cv->vwidthsel = false;
+ if ( sc->views==NULL && updateflex )
+ SplineCharIsFlexible(sc);
+ cv->sc = sc;
+ cv->next = sc->views;
+ sc->views = cv;
+ cv->layerheads[dm_fore] = &sc->layers[ly_fore];
+ cv->layerheads[dm_back] = &sc->layers[ly_back];
+ cv->layerheads[dm_grid] = &sc->parent->grid;
+ cv->p.sp = cv->lastselpt = NULL;
+ cv->apmine = cv->apmatch = NULL; cv->apsc = NULL;
+ cv->template1 = cv->template2 = NULL;
+#if HANYANG
+ if ( cv->sc->parent->rules!=NULL && cv->sc->compositionunit )
+ Disp_DefaultTemplate(cv);
+#endif
+ if ( cv->showpointnumbers || cv->show_ft_results )
+ SCNumberPoints(sc);
+ if ( cv->show_ft_results )
+ CVGridFitChar(cv);
+
+ CVNewScale(cv);
+
+ CharIcon(cv,cv->fv);
+ title = CVMakeTitles(cv,buf);
+ GDrawSetWindowTitles8(cv->gw,buf,title);
+ cv->lastselpt = NULL; cv->p.sp = NULL;
+ CVInfoDraw(cv,cv->gw);
+ free(title);
+ _CVPaletteActivate(cv,true);
+
+ if ( cv->tabs!=NULL ) {
+ for ( i=0; i<cv->former_cnt; ++i )
+ if ( strcmp(cv->former_names[i],sc->name)==0 )
+ break;
+ if ( i!=cv->former_cnt && cv->showtabs )
+ GTabSetSetSel(cv->tabs,i);
+ else {
+ if ( cv->former_cnt==FORMER_MAX )
+ free(cv->former_names[FORMER_MAX-1]);
+ for ( i=cv->former_cnt<FORMER_MAX?cv->former_cnt-1:FORMER_MAX-2; i>=0; --i )
+ cv->former_names[i+1] = cv->former_names[i];
+ cv->former_names[0] = copy(sc->name);
+ if ( cv->former_cnt<FORMER_MAX )
+ ++cv->former_cnt;
+ for ( i=0; i<cv->former_cnt; ++i )
+ GTabSetChangeTabName(cv->tabs,cv->former_names[i],i);
+ GTabSetRemetric(cv->tabs);
+ GTabSetSetSel(cv->tabs,0); /* This does a redraw */
+ if ( !GGadgetIsVisible(cv->tabs) && cv->showtabs )
+ CVChangeTabsVisibility(cv,true);
+ }
+ }
+}
+
+static void CVChangeChar(CharView *cv, int i ) {
+ SplineChar *sc;
+ SplineFont *sf = cv->sc->parent;
+ EncMap *map = cv->fv->map;
+ int gid = i<0 || i>= map->enccount ? -2 : map->map[i];
+
+ if ( gid == -2 )
+return;
+ if ( gid==-1 || (sc = sf->glyphs[gid])==NULL )
+ sc = SFMakeChar(sf,map,i);
+
+ if ( sc==NULL || (cv->sc == sc && cv->enc==i ))
+return;
+ cv->map_of_enc = map;
+ cv->enc = i;
+ CVChangeSC(cv,sc);
+}
+
+static int CVChangeToFormer( GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
+ CharView *cv = GDrawGetUserData(GGadgetGetWindow(g));
+ int new_aspect = GTabSetGetSel(g);
+ SplineFont *sf = cv->sc->parent;
+ int gid;
+
+ for ( gid=sf->glyphcnt-1; gid>=0; --gid )
+ if ( sf->glyphs[gid]!=NULL &&
+ strcmp(sf->glyphs[gid]->name,cv->former_names[new_aspect])==0 )
+ break;
+ if ( gid<0 ) {
+ /* They changed the name? See if we can get a unicode value from it */
+ int unienc = UniFromName(cv->former_names[new_aspect],sf->uni_interp,cv->fv->map->enc);
+ if ( unienc>=0 ) {
+ gid = SFFindGID(sf,unienc,cv->former_names[new_aspect]);
+ if ( gid>=0 ) {
+ free(cv->former_names[new_aspect]);
+ cv->former_names[new_aspect] = copy(sf->glyphs[gid]->name);
+ }
+ }
+ }
+ if ( gid<0 )
+return( true );
+ CVChangeSC(cv,sf->glyphs[gid]);
+ }
+return( true );
+}
+
+static void CVClear(GWindow,GMenuItem *mi, GEvent *);
+static void CVMouseMove(CharView *cv, GEvent *event );
+static void CVMouseUp(CharView *cv, GEvent *event );
+static void CVHScroll(CharView *cv,struct sbevent *sb);
+static void CVVScroll(CharView *cv,struct sbevent *sb);
+static void CVElide(GWindow gw,struct gmenuitem *mi,GEvent *e);
+static void CVMerge(GWindow gw,struct gmenuitem *mi,GEvent *e);
+static void SVElide(GWindow gw,struct gmenuitem *mi,GEvent *e);
+static void SVMerge(GWindow gw,struct gmenuitem *mi,GEvent *e);
+static void CVMenuSimplify(GWindow gw,struct gmenuitem *mi,GEvent *e);
+static void CVMenuSimplifyMore(GWindow gw,struct gmenuitem *mi,GEvent *e);
+static void SVMenuSimplify(GWindow gw,struct gmenuitem *mi,GEvent *e);
+#if 0
+static void SVMenuSimplifyMore(GWindow gw,struct gmenuitem *mi,GEvent *e);
+#endif
+
+
+static void CVFakeMove(CharView *cv, GEvent *event) {
+ GEvent e;
+
+ memset(&e,0,sizeof(e));
+ e.type = et_mousemove;
+ e.w = cv->v;
+ if ( event->w!=cv->v ) {
+ GPoint p;
+ p.x = event->u.chr.x; p.y = event->u.chr.y;
+ GDrawTranslateCoordinates(event->w,cv->v,&p);
+ event->u.chr.x = p.x; event->u.chr.y = p.y;
+ }
+ e.u.mouse.state = TrueCharState(event);
+ e.u.mouse.x = event->u.chr.x;
+ e.u.mouse.y = event->u.chr.y;
+ e.u.mouse.device = NULL;
+ CVMouseMove(cv,&e);
+}
+
+static void CVDoFindInFontView(CharView *cv) {
+ FVChangeChar(cv->fv,CVCurEnc(cv));
+ GDrawSetVisible(cv->fv->gw,true);
+ GDrawRaise(cv->fv->gw);
+}
+
+static void CVCharUp(CharView *cv, GEvent *event ) {
+#if _ModKeysAutoRepeat
+ /* Under cygwin these keys auto repeat, they don't under normal X */
+ if ( event->u.chr.keysym == GK_Shift_L || event->u.chr.keysym == GK_Shift_R ||
+ event->u.chr.keysym == GK_Control_L || event->u.chr.keysym == GK_Control_R ||
+ event->u.chr.keysym == GK_Meta_L || event->u.chr.keysym == GK_Meta_R ||
+ event->u.chr.keysym == GK_Alt_L || event->u.chr.keysym == GK_Alt_R ||
+ event->u.chr.keysym == GK_Super_L || event->u.chr.keysym == GK_Super_R ||
+ event->u.chr.keysym == GK_Hyper_L || event->u.chr.keysym == GK_Hyper_R ) {
+ if ( cv->autorpt!=NULL ) {
+ GDrawCancelTimer(cv->autorpt);
+ CVToolsSetCursor(cv,cv->oldstate,NULL);
+ }
+ cv->keysym = event->u.chr.keysym;
+ cv->oldkeyx = event->u.chr.x;
+ cv->oldkeyy = event->u.chr.y;
+ cv->oldkeyw = event->w;
+ cv->oldstate = TrueCharState(event);
+ cv->autorpt = GDrawRequestTimer(cv->v,100,0,NULL);
+ } else {
+ if ( cv->autorpt!=NULL ) {
+ GDrawCancelTimer(cv->autorpt); cv->autorpt=NULL;
+ CVToolsSetCursor(cv,cv->oldstate,NULL);
+ }
+ CVToolsSetCursor(cv,TrueCharState(event),NULL);
+ }
+#else
+ CVToolsSetCursor(cv,TrueCharState(event),NULL);
+ if ( event->u.chr.keysym == GK_Shift_L || event->u.chr.keysym == GK_Shift_R ||
+ event->u.chr.keysym == GK_Alt_L || event->u.chr.keysym == GK_Alt_R ||
+ event->u.chr.keysym == GK_Meta_L || event->u.chr.keysym == GK_Meta_R )
+ CVFakeMove(cv, event);
+#endif
+}
+
+static void CVInfoDrawText(CharView *cv, GWindow pixmap ) {
+ GRect r;
+ Color bg = GDrawGetDefaultBackground(GDrawGetDisplayOfWindow(pixmap));
+ Color fg = GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(pixmap));
+ char buffer[50];
+ unichar_t ubuffer[50];
+ int ybase = cv->mbh+(cv->infoh-cv->sfh)/2+cv->sas;
+ real xdiff, ydiff;
+ SplinePoint *sp, dummy;
+
+ GDrawSetFont(pixmap,cv->small);
+ r.x = RPT_DATA; r.width = 60;
+ r.y = cv->mbh; r.height = cv->infoh-1;
+ GDrawFillRect(pixmap,&r,bg);
+ r.x = SPT_DATA; r.width = 60;
+ GDrawFillRect(pixmap,&r,bg);
+ r.x = SOF_DATA; r.width = 60;
+ GDrawFillRect(pixmap,&r,bg);
+ r.x = SDS_DATA; r.width = 30;
+ GDrawFillRect(pixmap,&r,bg);
+ r.x = SAN_DATA; r.width = 30;
+ GDrawFillRect(pixmap,&r,bg);
+ r.x = MAG_DATA; r.width = 60;
+ GDrawFillRect(pixmap,&r,bg);
+ r.x = LAYER_DATA; r.width = 60;
+ GDrawFillRect(pixmap,&r,bg);
+ r.x = CODERANGE_DATA; r.width = 60;
+ GDrawFillRect(pixmap,&r,bg);
+
+ if ( cv->info_within ) {
+ if ( cv->info.x>=1000 || cv->info.x<=-1000 || cv->info.y>=1000 || cv->info.y<=-1000 )
+ sprintf(buffer,"%d%s%d", (int) cv->info.x, coord_sep, (int) cv->info.y );
+ else
+ sprintf(buffer,"%.4g%s%.4g", (double) cv->info.x, coord_sep, (double) cv->info.y );
+ buffer[11] = '\0';
+ uc_strcpy(ubuffer,buffer);
+ GDrawDrawText(pixmap,RPT_DATA,ybase,ubuffer,-1,NULL,fg);
+ }
+ if ( cv->scale>=.25 )
+ sprintf( buffer, "%d%%", (int) (100*cv->scale));
+ else
+ sprintf( buffer, "%.3g%%", (double) (100*cv->scale));
+ uc_strcpy(ubuffer,buffer);
+ GDrawDrawText(pixmap,MAG_DATA,ybase,ubuffer,-1,NULL,fg);
+ GDrawDrawText8(pixmap,LAYER_DATA,ybase,
+/* GT: Foreground, make it short */
+ cv->drawmode==dm_fore ? _("Fore") :
+/* GT: Background, make it short */
+ cv->drawmode==dm_back ? _("Back") :
+/* GT: Guide layer, make it short */
+ _("Guide"),
+ -1,NULL,fg);
+ if ( cv->coderange!=cr_none )
+ GDrawDrawText8(pixmap,CODERANGE_DATA,ybase,
+ cv->coderange==cr_fpgm ? _("'fpgm'") :
+ cv->coderange==cr_prep ? _("'prep'") : _("Glyph"),
+ -1,NULL,fg);
+ sp = cv->p.sp!=NULL ? cv->p.sp : cv->lastselpt;
+ if ( sp==NULL ) if ( cv->active_tool==cvt_rect || cv->active_tool==cvt_elipse ||
+ cv->active_tool==cvt_poly || cv->active_tool==cvt_star ) {
+ dummy.me.x = cv->p.cx; dummy.me.y = cv->p.cy;
+ sp = &dummy;
+ }
+ if ( sp ) {
+ real selx, sely;
+ if ( cv->pressed && sp==cv->p.sp ) {
+ selx = cv->p.constrain.x;
+ sely = cv->p.constrain.y;
+ } else {
+ selx = sp->me.x;
+ sely = sp->me.y;
+ }
+ xdiff=cv->info.x-selx;
+ ydiff = cv->info.y-sely;
+
+ if ( selx>=1000 || selx<=-1000 || sely>=1000 || sely<=-1000 )
+ sprintf(buffer,"%d%s%d", (int) selx, coord_sep, (int) sely );
+ else
+ sprintf(buffer,"%.4g%s%.4g", (double) selx, coord_sep, (double) sely );
+ buffer[11] = '\0';
+ uc_strcpy(ubuffer,buffer);
+ GDrawDrawText(pixmap,SPT_DATA,ybase,ubuffer,-1,NULL,fg);
+ } else if ( cv->widthsel && cv->info_within ) {
+ xdiff = cv->info.x-cv->p.cx;
+ ydiff = 0;
+ } else if ( cv->p.rubberbanding && cv->info_within ) {
+ xdiff=cv->info.x-cv->p.cx;
+ ydiff = cv->info.y-cv->p.cy;
+ } else
+return;
+ if ( !cv->info_within )
+return;
+
+ if ( xdiff>=1000 || xdiff<=-1000 || ydiff>=1000 || ydiff<=-1000 )
+ sprintf(buffer,"%d%s%d", (int) xdiff, coord_sep, (int) ydiff );
+ else
+ sprintf(buffer,"%.4g%s%.4g", (double) xdiff, coord_sep, (double) ydiff );
+ buffer[11] = '\0';
+ uc_strcpy(ubuffer,buffer);
+ GDrawDrawText(pixmap,SOF_DATA,ybase,ubuffer,-1,NULL,fg);
+
+ sprintf( buffer, "%.1f", sqrt(xdiff*xdiff+ydiff*ydiff));
+ uc_strcpy(ubuffer,buffer);
+ GDrawDrawText(pixmap,SDS_DATA,ybase,ubuffer,-1,NULL,fg);
+
+ sprintf( buffer, "%d\260", (int) rint(180*atan2(ydiff,xdiff)/3.1415926535897932));
+ uc_strcpy(ubuffer,buffer);
+ GDrawDrawText(pixmap,SAN_DATA,ybase,ubuffer,-1,NULL,fg);
+}
+
+static void CVInfoDrawRulers(CharView *cv, GWindow pixmap ) {
+ int rstart = cv->mbh+cv->infoh;
+ GDrawSetXORMode(pixmap);
+ GDrawSetXORBase(pixmap,GDrawGetDefaultBackground(NULL));
+ GDrawSetLineWidth(pixmap,0);
+ if ( cv->olde.x!=-1 ) {
+ GDrawDrawLine(pixmap,cv->olde.x+cv->rulerh,rstart,cv->olde.x+cv->rulerh,rstart+cv->rulerh,0xff0000);
+ GDrawDrawLine(pixmap,0,cv->olde.y+rstart+cv->rulerh,cv->rulerh,cv->olde.y+rstart+cv->rulerh,0xff0000);
+ }
+ GDrawDrawLine(pixmap,cv->e.x+cv->rulerh,rstart,cv->e.x+cv->rulerh,rstart+cv->rulerh,0xff0000);
+ GDrawDrawLine(pixmap,0,cv->e.y+rstart+cv->rulerh,cv->rulerh,cv->e.y+rstart+cv->rulerh,0xff0000);
+ cv->olde = cv->e;
+ GDrawSetCopyMode(pixmap);
+}
+
+void CVInfoDraw(CharView *cv, GWindow pixmap ) {
+ CVInfoDrawText(cv,pixmap);
+ if ( cv->showrulers )
+ CVInfoDrawRulers(cv,pixmap);
+}
+
+static void CVCrossing(CharView *cv, GEvent *event ) {
+ CVToolsSetCursor(cv,event->u.mouse.state,event->u.mouse.device);
+ cv->info_within = event->u.crossing.entered;
+ cv->info.x = (event->u.crossing.x-cv->xoff)/cv->scale;
+ cv->info.y = (cv->height-event->u.crossing.y-cv->yoff)/cv->scale;
+ CVInfoDraw(cv,cv->gw);
+ CPEndInfo(cv);
+}
+
+static int CheckPoint(FindSel *fs, SplinePoint *sp, SplineSet *spl) {
+
+ if ( fs->xl<=sp->me.x && fs->xh>=sp->me.x &&
+ fs->yl<=sp->me.y && fs->yh >= sp->me.y ) {
+ fs->p->sp = sp;
+ fs->p->spline = NULL;
+ fs->p->anysel = true;
+ fs->p->spl = spl;
+ if ( !fs->seek_controls )
+return( true );
+ }
+ if ( (sp->selected && fs->select_controls) || fs->all_controls ) {
+ if ( fs->xl<=sp->nextcp.x && fs->xh>=sp->nextcp.x &&
+ fs->yl<=sp->nextcp.y && fs->yh >= sp->nextcp.y ) {
+ fs->p->sp = sp;
+ fs->p->spline = NULL;
+ fs->p->spl = spl;
+ fs->p->nextcp = true;
+ fs->p->anysel = true;
+ fs->p->cp = sp->nextcp;
+ if ( sp->nonextcp && sp->pointtype==pt_curve ) {
+ fs->p->cp.x = sp->me.x + (sp->me.x-sp->prevcp.x);
+ fs->p->cp.y = sp->me.y + (sp->me.y-sp->prevcp.y);
+ }
+ sp->selected = true;
+return( true );
+ } else if ( fs->xl<=sp->prevcp.x && fs->xh>=sp->prevcp.x &&
+ fs->yl<=sp->prevcp.y && fs->yh >= sp->prevcp.y ) {
+ fs->p->sp = sp;
+ fs->p->spline = NULL;
+ fs->p->spl = spl;
+ fs->p->prevcp = true;
+ fs->p->anysel = true;
+ fs->p->cp = sp->prevcp;
+ if ( sp->noprevcp && sp->pointtype==pt_curve ) {
+ fs->p->cp.x = sp->me.x + (sp->me.x-sp->nextcp.x);
+ fs->p->cp.y = sp->me.y + (sp->me.y-sp->nextcp.y);
+ }
+ sp->selected = true;
+return( true );
+ }
+ }
+return( false );
+}
+
+static int CheckSpline(FindSel *fs, Spline *spline, SplineSet *spl) {
+
+ /* Anything else is better than a spline */
+ if ( fs->p->anysel )
+return( false );
+
+ if ( NearSpline(fs,spline)) {
+ fs->p->spline = spline;
+ fs->p->spl = spl;
+ fs->p->anysel = true;
+return( false /*true*/ ); /* Check if there's a point where we are first */
+ /* if there is use it, if not (because anysel is true) we'll fall back */
+ /* here */
+ }
+return( false );
+}
+
+static int InImage( FindSel *fs, ImageList *img) {
+ int x,y;
+
+ x = floor((fs->p->cx-img->xoff)/img->xscale);
+ y = floor((img->yoff-fs->p->cy)/img->yscale);
+ if ( x<0 || y<0 || x>=GImageGetWidth(img->image) || y>=GImageGetHeight(img->image))
+return ( false );
+ if ( GImageGetPixelColor(img->image,x,y)&0x80000000 ) /* Transparent */
+return( false );
+
+return( true );
+}
+
+static int InSplineSet( FindSel *fs, SplinePointList *set) {
+ SplinePointList *spl;
+ Spline *spline, *first;
+
+ for ( spl = set; spl!=NULL; spl = spl->next ) {
+ if ( CheckPoint(fs,spl->first,spl) && ( !fs->seek_controls || fs->p->nextcp || fs->p->prevcp )) {
+return( true );
+ }
+ first = NULL;
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) {
+ if ( (CheckPoint(fs,spline->to,spl) && ( !fs->seek_controls || fs->p->nextcp || fs->p->prevcp )) ||
+ ( CheckSpline(fs,spline,spl) && !fs->seek_controls )) {
+return( true );
+ }
+ if ( first==NULL ) first = spline;
+ }
+ }
+return( fs->p->anysel );
+}
+
+static int NearSplineSetPoints( FindSel *fs, SplinePointList *set) {
+ SplinePointList *spl;
+ Spline *spline, *first;
+
+ for ( spl = set; spl!=NULL; spl = spl->next ) {
+ if ( CheckPoint(fs,spl->first,spl)) {
+return( true );
+ }
+ first = NULL;
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) {
+ if ( CheckPoint(fs,spline->to,spl) ) {
+return( true );
+ }
+ if ( first==NULL ) first = spline;
+ }
+ }
+return( fs->p->anysel );
+}
+
+static void SetFS( FindSel *fs, PressedOn *p, CharView *cv, GEvent *event) {
+ extern float snapdistance;
+
+ memset(p,'\0',sizeof(PressedOn));
+ p->pressed = true;
+
+ memset(fs,'\0',sizeof(*fs));
+ fs->p = p;
+ fs->e = event;
+ p->x = event->u.mouse.x;
+ p->y = event->u.mouse.y;
+ p->cx = (event->u.mouse.x-cv->xoff)/cv->scale;
+ p->cy = (cv->height-event->u.mouse.y-cv->yoff)/cv->scale;
+
+ fs->fudge = snapdistance/cv->scale; /* 3.5 pixel fudge */
+ fs->xl = p->cx - fs->fudge;
+ fs->xh = p->cx + fs->fudge;
+ fs->yl = p->cy - fs->fudge;
+ fs->yh = p->cy + fs->fudge;
+}
+
+int CVMouseAtSpline(CharView *cv,GEvent *event) {
+ FindSel fs;
+ int pressed = cv->p.pressed;
+
+ SetFS(&fs,&cv->p,cv,event);
+ cv->p.pressed = pressed;
+return( InSplineSet(&fs,cv->layerheads[cv->drawmode]->splines));
+}
+
+static GEvent *CVConstrainedMouseDown(CharView *cv,GEvent *event, GEvent *fake) {
+ SplinePoint *base;
+ int basex, basey, dx, dy;
+ int sign;
+
+ base = CVAnySelPoint(cv);
+ if ( base==NULL )
+return( event );
+
+ basex = cv->xoff + rint(base->me.x*cv->scale);
+ basey = -cv->yoff + cv->height - rint(base->me.y*cv->scale);
+
+ dx= event->u.mouse.x-basex, dy = event->u.mouse.y-basey;
+ sign = dx*dy<0?-1:1;
+
+ fake->u.mouse = event->u.mouse;
+ if ( dx<0 ) dx = -dx; if ( dy<0 ) dy = -dy;
+ if ( dy >= 2*dx ) {
+ cv->p.x = fake->u.mouse.x = basex;
+ cv->p.cx = base->me.x;
+ if ( !(event->u.mouse.state&ksm_alt) &&
+ ItalicConstrained && cv->sc->parent->italicangle!=0 ) {
+ double off = tan(cv->sc->parent->italicangle*3.1415926535897932/180)*
+ (cv->p.cy-base->me.y);
+ double aoff = off<0 ? -off : off;
+ if ( dx>=aoff*cv->scale/2 && (event->u.mouse.x-basex<0)!=(off<0) ) {
+ cv->p.cx -= off;
+ cv->p.x = fake->u.mouse.x = cv->xoff + rint(cv->p.cx*cv->scale);
+ }
+ }
+ } else if ( dx >= 2*dy ) {
+ fake->u.mouse.y = basey;
+ cv->p.cy = base->me.y;
+ } else if ( dx > dy ) {
+ fake->u.mouse.x = basex + sign * (event->u.mouse.y-cv->p.y);
+ cv->p.cx = base->me.x - sign * (cv->p.cy-base->me.y);
+ } else {
+ fake->u.mouse.y = basey + sign * (event->u.mouse.x-cv->p.x);
+ cv->p.cy = base->me.y - sign * (cv->p.cx-base->me.x);
+ }
+
+return( fake );
+}
+
+static void CVSetConstrainPoint(CharView *cv, GEvent *event) {
+ SplineSet *sel;
+
+ if ( (sel = CVAnySelPointList(cv))!=NULL ) {
+ if ( sel->first->selected ) cv->p.constrain = sel->first->me;
+ else cv->p.constrain = sel->last->me;
+ } else if ( cv->p.sp!=NULL ) {
+ cv->p.constrain = cv->p.sp->me;
+ } else {
+ cv->p.constrain.x = cv->info.x;
+ cv->p.constrain.y = cv->info.y;
+ }
+}
+
+static void CVDoSnaps(CharView *cv, FindSel *fs) {
+ PressedOn *p = fs->p;
+
+#if 1
+ if ( cv->drawmode!=dm_grid && cv->layerheads[dm_grid]->splines!=NULL ) {
+ PressedOn temp;
+ int oldseek = fs->seek_controls;
+ temp = *p;
+ fs->p = &temp;
+ fs->seek_controls = false;
+ if ( InSplineSet( fs, cv->layerheads[dm_grid]->splines)) {
+ if ( temp.spline!=NULL ) {
+ p->cx = ((temp.spline->splines[0].a*temp.t+
+ temp.spline->splines[0].b)*temp.t+
+ temp.spline->splines[0].c)*temp.t+
+ temp.spline->splines[0].d;
+ p->cy = ((temp.spline->splines[1].a*temp.t+
+ temp.spline->splines[1].b)*temp.t+
+ temp.spline->splines[1].c)*temp.t+
+ temp.spline->splines[1].d;
+ } else if ( temp.sp!=NULL ) {
+ p->cx = temp.sp->me.x;
+ p->cy = temp.sp->me.y;
+ }
+ }
+ fs->p = p;
+ fs->seek_controls = oldseek;
+ }
+#endif
+ if ( p->cx>-fs->fudge && p->cx<fs->fudge )
+ p->cx = 0;
+ else if ( p->cx>cv->sc->width-fs->fudge && p->cx<cv->sc->width+fs->fudge &&
+ !cv->widthsel)
+ p->cx = cv->sc->width;
+ else if ( cv->widthsel && p!=&cv->p &&
+ p->cx>cv->oldwidth-fs->fudge && p->cx<cv->oldwidth+fs->fudge )
+ p->cx = cv->oldwidth;
+#if 0
+ else if ( cv->sc->parent->hsnaps!=NULL && cv->drawmode!=dm_grid ) {
+ int i, *hsnaps = cv->sc->parent->hsnaps;
+ for ( i=0; hsnaps[i]!=0x80000000; ++i ) {
+ if ( p->cx>hsnaps[i]-fs->fudge && p->cx<hsnaps[i]+fs->fudge ) {
+ p->cx = hsnaps[i];
+ break;
+ }
+ }
+ }
+#endif
+ if ( p->cy>-fs->fudge && p->cy<fs->fudge )
+ p->cy = 0;
+#if 0
+ else if ( cv->sc->parent->vsnaps!=NULL && cv->drawmode!=dm_grid ) {
+ int i, *vsnaps = cv->sc->parent->vsnaps;
+ for ( i=0; vsnaps[i]!=0x80000000; ++i ) {
+ if ( p->cy>vsnaps[i]-fs->fudge && p->cy<vsnaps[i]+fs->fudge ) {
+ p->cy = vsnaps[i];
+ break;
+ }
+ }
+ }
+#endif
+}
+
+static int _CVTestSelectFromEvent(CharView *cv,FindSel *fs) {
+ PressedOn temp;
+ ImageList *img;
+
+ if ( !InSplineSet(fs,cv->layerheads[cv->drawmode]->splines)) {
+ if ( cv->drawmode==dm_fore) {
+ RefChar *rf;
+ temp = cv->p;
+ fs->p = &temp;
+ fs->seek_controls = false;
+ for ( rf=cv->sc->layers[ly_fore].refs; rf!=NULL; rf = rf->next ) {
+ if ( InSplineSet(fs,rf->layers[0].splines)) {
+ cv->p.ref = rf;
+ cv->p.anysel = true;
+ break;
+ }
+ }
+ if ( cv->showanchor && !cv->p.anysel ) {
+ AnchorPoint *ap, *found=NULL;
+ /* I do this pecular search because: */
+ /* 1) I expect there to be lots of times we get multiple */
+ /* anchors at the same location */
+ /* 2) The anchor points are drawn so that the bottommost */
+ /* is displayed */
+ for ( ap=cv->sc->anchor; ap!=NULL; ap=ap->next )
+ if ( fs->xl<=ap->me.x && fs->xh>=ap->me.x &&
+ fs->yl<=ap->me.y && fs->yh >= ap->me.y )
+ found = ap;
+ if ( found!=NULL ) {
+ cv->p.ap = found;
+ cv->p.anysel = true;
+ }
+ }
+ }
+ for ( img = cv->layerheads[cv->drawmode]->images; img!=NULL; img=img->next ) {
+ if ( InImage(fs,img)) {
+ cv->p.img = img;
+ cv->p.anysel = true;
+ break;
+ }
+ }
+ }
+return( cv->p.anysel );
+}
+
+int CVTestSelectFromEvent(CharView *cv,GEvent *event) {
+ FindSel fs;
+
+ SetFS(&fs,&cv->p,cv,event);
+return( _CVTestSelectFromEvent(cv,&fs));
+}
+
+static void CVMouseDown(CharView *cv, GEvent *event ) {
+ FindSel fs;
+ GEvent fake;
+
+ if ( event->u.mouse.button==2 && event->u.mouse.device!=NULL &&
+ strcmp(event->u.mouse.device,"stylus")==0 )
+return; /* I treat this more like a modifier key change than a button press */
+
+ if ( cv->expandedge != ee_none )
+ GDrawSetCursor(cv->v,ct_mypointer);
+ if ( event->u.mouse.button==3 ) {
+ CVToolsPopup(cv,event);
+return;
+ }
+ CVToolsSetCursor(cv,event->u.mouse.state|(1<<(7+event->u.mouse.button)), event->u.mouse.device );
+ cv->active_tool = cv->showing_tool;
+ cv->needsrasterize = false;
+ cv->recentchange = false;
+
+ SetFS(&fs,&cv->p,cv,event);
+ if ( event->u.mouse.state&ksm_shift )
+ event = CVConstrainedMouseDown(cv,event,&fake);
+
+ if ( cv->active_tool == cvt_pointer ) {
+ fs.select_controls = true;
+ if ( event->u.mouse.state&ksm_alt ) fs.seek_controls = true;
+ if ( cv->showpointnumbers && cv->fv->sf->order2 ) fs.all_controls = true;
+ cv->lastselpt = NULL;
+ _CVTestSelectFromEvent(cv,&fs);
+ fs.p = &cv->p;
+ } else if ( cv->active_tool == cvt_curve || cv->active_tool == cvt_corner ||
+ cv->active_tool == cvt_tangent || cv->active_tool == cvt_pen ) {
+ InSplineSet(&fs,cv->layerheads[cv->drawmode]->splines);
+ if ( fs.p->sp==NULL && fs.p->spline==NULL )
+ CVDoSnaps(cv,&fs);
+ } else {
+ NearSplineSetPoints(&fs,cv->layerheads[cv->drawmode]->splines);
+ if ( fs.p->sp==NULL && fs.p->spline==NULL )
+ CVDoSnaps(cv,&fs);
+ }
+
+ cv->e.x = event->u.mouse.x; cv->e.y = event->u.mouse.y;
+ if ( cv->p.sp!=NULL ) {
+ BasePoint *p;
+ if ( cv->p.nextcp )
+ p = &cv->p.sp->nextcp;
+ else if ( cv->p.prevcp )
+ p = &cv->p.sp->prevcp;
+ else
+ p = &cv->p.sp->me;
+ cv->info.x = p->x;
+ cv->info.y = p->y;
+ cv->p.cx = p->x; cv->p.cy = p->y;
+ } else {
+ cv->info.x = cv->p.cx;
+ cv->info.y = cv->p.cy;
+ }
+ cv->info_within = true;
+ CVInfoDraw(cv,cv->gw);
+ CVSetConstrainPoint(cv,event);
+
+ switch ( cv->active_tool ) {
+ case cvt_pointer:
+ CVMouseDownPointer(cv, &fs, event);
+ cv->lastselpt = fs.p->sp;
+ break;
+ case cvt_magnify: case cvt_minify:
+ break;
+ case cvt_hand:
+ CVMouseDownHand(cv);
+ break;
+ case cvt_freehand:
+ CVMouseDownFreeHand(cv,event);
+ break;
+ case cvt_curve: case cvt_corner: case cvt_tangent: case cvt_pen:
+ CVMouseDownPoint(cv,event);
+ break;
+ case cvt_ruler:
+ CVMouseDownRuler(cv,event);
+ break;
+ case cvt_rotate: case cvt_flip: case cvt_scale: case cvt_skew:
+ case cvt_3d_rotate: case cvt_perspective:
+ CVMouseDownTransform(cv);
+ break;
+ case cvt_knife:
+ CVMouseDownKnife(cv);
+ break;
+ case cvt_rect: case cvt_elipse: case cvt_poly: case cvt_star:
+ CVMouseDownShape(cv,event);
+ break;
+ }
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+static int _SCRefNumberPoints2(SplineSet **_rss,SplineChar *sc,int pnum) {
+ SplineSet *ss, *rss = *_rss;
+ SplinePoint *sp, *rsp;
+ RefChar *r;
+ int starts_with_cp, startcnt;
+
+ for ( ss=sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next, rss=rss->next ) {
+ if ( rss==NULL ) /* Can't happen */
+ break;
+ starts_with_cp = !ss->first->noprevcp &&
+ ((ss->first->ttfindex == pnum+1 && ss->first->prev!=NULL &&
+ ss->first->prev->from->nextcpindex==pnum ) ||
+ ((ss->first->ttfindex==0xffff || SPInterpolate( ss->first ))));
+ startcnt = pnum;
+ if ( starts_with_cp ) ++pnum;
+ for ( sp = ss->first, rsp=rss->first; ; ) {
+ if ( sp->ttfindex==0xffff || SPInterpolate( sp ))
+ rsp->ttfindex = 0xffff;
+ else
+ rsp->ttfindex = pnum++;
+ if ( sp->next==NULL )
+ break;
+ if ( sp->next->to == ss->first ) {
+ if ( sp->nonextcp )
+ rsp->nextcpindex = 0xffff;
+ else if ( starts_with_cp )
+ rsp->nextcpindex = startcnt;
+ else
+ rsp->nextcpindex = pnum++;
+ break;
+ }
+ if ( sp->nonextcp )
+ rsp->nextcpindex = 0xffff;
+ else
+ rsp->nextcpindex = pnum++;
+ sp = sp->next->to;
+ rsp = rsp->next->to;
+ }
+ }
+
+ *_rss = rss;
+ for ( r = sc->layers[ly_fore].refs; r!=NULL; r=r->next )
+ pnum = _SCRefNumberPoints2(_rss,r->sc,pnum);
+return( pnum );
+}
+
+static int SCRefNumberPoints2(RefChar *ref,int pnum) {
+ SplineSet *rss;
+
+ rss = ref->layers[0].splines;
+return( _SCRefNumberPoints2(&rss,ref->sc,pnum));
+}
+
+int SSTtfNumberPoints(SplineSet *ss) {
+ int pnum=0;
+ SplinePoint *sp;
+ int starts_with_cp;
+
+ for ( ; ss!=NULL; ss=ss->next ) {
+ starts_with_cp = !ss->first->noprevcp &&
+ ((ss->first->ttfindex == pnum+1 && ss->first->prev!=NULL &&
+ ss->first->prev->from->nextcpindex==pnum ) ||
+ SPInterpolate( ss->first ));
+ if ( starts_with_cp && ss->first->prev!=NULL )
+ ss->first->prev->from->nextcpindex = pnum++;
+ for ( sp=ss->first; ; ) {
+ if ( SPInterpolate(sp) )
+ sp->ttfindex = 0xffff;
+ else
+ sp->ttfindex = pnum++;
+ if ( sp->nonextcp )
+ sp->nextcpindex = 0xffff;
+ else if ( !starts_with_cp || (sp->next!=NULL && sp->next->to!=ss->first) )
+ sp->nextcpindex = pnum++;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ }
+return( pnum );
+}
+
+int SCNumberPoints(SplineChar *sc) {
+ int pnum=0;
+ SplineSet *ss;
+ SplinePoint *sp;
+ RefChar *ref;
+
+ if ( sc->parent->order2 ) { /* TrueType and its complexities. I ignore svg here */
+ if ( sc->layers[ly_fore].refs!=NULL ) {
+ /* if there are references there can't be splines. So if we've got*/
+ /* splines mark all point numbers on them as meaningless */
+ for ( ss = sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) {
+ for ( sp=ss->first; ; ) {
+ sp->ttfindex = 0xfffe;
+ if ( !sp->nonextcp )
+ sp->nextcpindex = 0xfffe;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ }
+ for ( ref = sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next )
+ pnum = SCRefNumberPoints2(ref,pnum);
+ } else {
+ pnum = SSTtfNumberPoints(sc->layers[ly_fore].splines);
+ }
+ } else { /* cubic (PostScript/SVG) splines */
+ int layer;
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ for ( ss = sc->layers[layer].splines; ss!=NULL; ss=ss->next ) {
+ for ( sp=ss->first; ; ) {
+ sp->ttfindex = pnum++;
+ sp->nextcpindex = 0xffff;
+ if ( sc->numberpointsbackards ) {
+ if ( sp->prev==NULL )
+ break;
+ if ( !sp->noprevcp || !sp->prev->from->nonextcp )
+ pnum += 2;
+ sp = sp->prev->from;
+ } else {
+ if ( sp->next==NULL )
+ break;
+ if ( !sp->nonextcp || !sp->next->to->noprevcp )
+ pnum += 2;
+ sp = sp->next->to;
+ }
+ if ( sp==ss->first )
+ break;
+ }
+ }
+ }
+ }
+return( pnum );
+}
+
+int SCPointsNumberedProperly(SplineChar *sc) {
+ int pnum=0, skipit;
+ SplineSet *ss;
+ SplinePoint *sp;
+ int starts_with_cp;
+ int start_pnum;
+
+ if ( sc->layers[ly_fore].splines!=NULL &&
+ sc->layers[ly_fore].refs!=NULL )
+return( false ); /* TrueType can't represent this, so always remove instructions. They can't be meaningful */
+
+ for ( ss = sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) {
+ starts_with_cp = (ss->first->ttfindex == pnum+1 || ss->first->ttfindex==0xffff) &&
+ !ss->first->noprevcp;
+ start_pnum = pnum;
+ if ( starts_with_cp ) ++pnum;
+ for ( sp=ss->first; ; ) {
+ skipit = SPInterpolate(sp);
+ if ( sp->nonextcp || sp->noprevcp ) skipit = false;
+ if ( sp->ttfindex==0xffff && skipit )
+ /* Doesn't count */;
+ else if ( sp->ttfindex!=pnum )
+return( false );
+ else
+ ++pnum;
+ if ( sp->nonextcp && sp->nextcpindex==0xffff )
+ /* Doesn't count */;
+ else if ( sp->nextcpindex==pnum )
+ ++pnum;
+ else if ( sp->nextcpindex==start_pnum && starts_with_cp &&
+ (sp->next!=NULL && sp->next->to==ss->first) )
+ /* Ok */;
+ else
+return( false );
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ if ( starts_with_cp ) --pnum;
+ }
+return( true );
+}
+
+static void instrcheck(SplineChar *sc) {
+ uint8 *instrs = sc->ttf_instrs==NULL && sc->parent->mm!=NULL && sc->parent->mm->apple ?
+ sc->parent->mm->normal->glyphs[sc->orig_pos]->ttf_instrs : sc->ttf_instrs;
+ struct splinecharlist *dep;
+ int any_ptnumbers_shown = false;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ CharView *cv;
+#endif
+ extern int clear_tt_instructions_when_needed;
+ SplineSet *ss;
+ SplinePoint *sp;
+ AnchorPoint *ap;
+ int had_ap, had_dep, had_instrs;
+
+ if ( !sc->parent->order2 )
+return;
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ for ( cv=sc->views; cv!=NULL; cv=cv->next )
+ if ( cv->showpointnumbers ) {
+ any_ptnumbers_shown = true;
+ break;
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+ if ( sc->instructions_out_of_date && !any_ptnumbers_shown && sc->anchor==NULL )
+return;
+ if ( instrs==NULL && sc->dependents==NULL && !any_ptnumbers_shown && sc->anchor==NULL )
+return;
+ /* If the points are no longer in order then the instructions are not valid */
+ /* (because they'll refer to the wrong points) and should be removed */
+ /* Except that annoys users who don't expect it */
+ had_ap = had_dep = had_instrs = 0;
+ if ( !SCPointsNumberedProperly(sc)) {
+ if ( instrs!=NULL ) {
+ if ( clear_tt_instructions_when_needed ) {
+ free(sc->ttf_instrs); sc->ttf_instrs = NULL;
+ sc->ttf_instrs_len = 0;
+# ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ SCMarkInstrDlgAsChanged(sc);
+# endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ had_instrs = 1;
+ } else {
+ sc->instructions_out_of_date = true;
+ had_instrs = 2;
+ }
+ }
+ for ( dep=sc->dependents; dep!=NULL; dep=dep->next ) {
+ RefChar *ref;
+ if ( dep->sc->ttf_instrs_len!=0 ) {
+ if ( clear_tt_instructions_when_needed ) {
+ free(dep->sc->ttf_instrs); dep->sc->ttf_instrs = NULL;
+ dep->sc->ttf_instrs_len = 0;
+# ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ SCMarkInstrDlgAsChanged(dep->sc);
+# endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ had_instrs = 1;
+ } else {
+ dep->sc->instructions_out_of_date = true;
+ had_instrs = 2;
+ }
+ }
+ for ( ref=dep->sc->layers[ly_fore].refs; ref!=NULL && ref->sc!=sc; ref=ref->next );
+ for ( ; ref!=NULL ; ref=ref->next ) {
+#if 0
+ ref->point_match = false;
+#endif
+ if ( ref->point_match )
+ ref->point_match_out_of_date = true;
+ had_dep = true;
+ }
+ }
+ SCNumberPoints(sc);
+ for ( ap=sc->anchor ; ap!=NULL; ap=ap->next ) {
+ if ( ap->has_ttf_pt ) {
+ had_ap = true;
+ ap->has_ttf_pt = false;
+ for ( ss = sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) {
+ for ( sp=ss->first; ; ) {
+ if ( sp->me.x==ap->me.x && sp->me.y==ap->me.y && sp->ttfindex!=0xffff ) {
+ ap->has_ttf_pt = true;
+ ap->ttf_pt_index = sp->ttfindex;
+ goto found;
+ } else if ( sp->nextcp.x==ap->me.x && sp->nextcp.y==ap->me.y && sp->nextcpindex!=0xffff ) {
+ ap->has_ttf_pt = true;
+ ap->ttf_pt_index = sp->nextcpindex;
+ goto found;
+ }
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ }
+ found: ;
+ }
+ }
+ }
+ if ( no_windowing_ui )
+ /* If we're in a script it's annoying (and pointless) to get this message */;
+ else if ( sc->complained_about_ptnums )
+ /* It's annoying to get the same message over and over again as you edit a glyph */;
+ else if ( had_ap || had_dep || had_instrs ) {
+ ff_post_notice(_("You changed the point numbering"),
+ _("You have just changed the point numbering of glyph %s.%s%s%s"),
+ sc->name,
+ had_instrs==0 ? "" :
+ had_instrs==1 ? _(" Instructions in this glyph (or one that refers to it) have been lost.") :
+ _(" Instructions in this glyph (or one that refers to it) are now out of date."),
+ had_dep ? _(" At least one reference to this glyph used point matching. That match is now out of date.")
+ : "",
+ had_ap ? _(" At least one anchor point used point matching. It may be out of date now.")
+ : "" );
+ sc->complained_about_ptnums = true;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( had_instrs==2 )
+ GDrawRequestExpose(sc->parent->fv->v,NULL,false);
+#endif
+ }
+}
+
+static void _SCHintsChanged(SplineChar *sc) {
+ struct splinecharlist *dlist;
+
+ if ( !sc->changedsincelasthinted ) {
+ sc->changedsincelasthinted = true;
+ FVMarkHintsOutOfDate(sc);
+ }
+
+ for ( dlist=sc->dependents; dlist!=NULL; dlist=dlist->next )
+ _SCHintsChanged(dlist->sc);
+}
+
+void SCHintsChanged(SplineChar *sc) {
+ struct splinecharlist *dlist;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ int was = sc->changedsincelasthinted;
+#endif
+
+ if ( sc->parent->onlybitmaps || sc->parent->multilayer || sc->parent->strokedfont || sc->parent->order2 )
+return;
+ sc->changedsincelasthinted = false; /* We just applied a hinting change */
+ if ( !sc->changed ) {
+ sc->changed = true;
+ FVToggleCharChanged(sc);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ SCRefreshTitles(sc);
+#endif
+ if ( !sc->parent->changed ) {
+ sc->parent->changed = true;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FVSetTitle(sc->parent->fv);
+#endif
+ }
+ }
+ for ( dlist=sc->dependents; dlist!=NULL; dlist=dlist->next )
+ _SCHintsChanged(dlist->sc);
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( was ) {
+ FontView *fvs;
+ for ( fvs = sc->parent->fv; fvs!=NULL; fvs=fvs->nextsame )
+ GDrawRequestExpose(fvs->v,NULL,false);
+ }
+#endif
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+
+void CVSetCharChanged(CharView *cv,int changed) {
+ FontView *fv = cv->fv;
+ SplineFont *sf = fv->sf;
+ SplineChar *sc = cv->sc;
+ int oldchanged = sf->changed;
+ /* A changed argument of 2 means the outline didn't change, but something */
+ /* else (width, anchorpoint) did */
+
+ if ( changed )
+ SFSetModTime(sf);
+ if ( cv->drawmode==dm_grid ) {
+ if ( changed ) {
+ sf->changed = true;
+ if ( fv->cidmaster!=NULL )
+ fv->cidmaster->changed = true;
+ }
+ } else {
+ if ( cv->drawmode==dm_fore && changed!=2 )
+ sf->onlybitmaps = false;
+ if ( (sc->changed==0) != (changed==0) ) {
+ sc->changed = (changed!=0);
+ FVToggleCharChanged(sc);
+ SCRefreshTitles(sc);
+ if ( changed ) {
+ sf->changed = true;
+ if ( fv->cidmaster!=NULL )
+ fv->cidmaster->changed = true;
+ }
+ }
+ if ( changed==1 ) {
+ instrcheck(sc);
+ SCDeGridFit(sc);
+ if ( sc->parent->onlybitmaps )
+ /* Do nothing */;
+ else if ( sc->parent->multilayer || sc->parent->strokedfont || sc->parent->order2 )
+ sc->changed_since_search = true;
+ else if ( cv->drawmode==dm_fore )
+ sc->changed_since_search = sc->changedsincelasthinted = true;
+ sc->changed_since_autosave = true;
+ sf->changed_since_autosave = true;
+ sf->changed_since_xuidchanged = true;
+ if ( fv->cidmaster!=NULL ) {
+ fv->cidmaster->changed_since_autosave = true;
+ fv->cidmaster->changed_since_xuidchanged = true;
+ }
+ _SCHintsChanged(cv->sc);
+ }
+ if ( cv->drawmode==dm_fore ) {
+ cv->needsrasterize = true;
+ }
+ }
+ cv->recentchange = true;
+ if ( !oldchanged )
+ FVSetTitle(fv);
+}
+
+void SCClearSelPt(SplineChar *sc) {
+ CharView *cv;
+
+ for ( cv=sc->views; cv!=NULL; cv=cv->next ) {
+ cv->lastselpt = cv->p.sp = NULL;
+ }
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+static void TTFPointMatches(SplineChar *sc,int top) {
+ AnchorPoint *ap;
+ BasePoint here, there;
+ struct splinecharlist *deps;
+ RefChar *ref;
+
+ if ( !sc->parent->order2 )
+return;
+ for ( ap=sc->anchor ; ap!=NULL; ap=ap->next ) {
+ if ( ap->has_ttf_pt )
+ if ( ttfFindPointInSC(sc,ap->ttf_pt_index,&ap->me,NULL)!=-1 )
+ ap->has_ttf_pt = false;
+ }
+ for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
+ if ( ref->point_match ) {
+ if ( ttfFindPointInSC(sc,ref->match_pt_base,&there,ref)==-1 &&
+ ttfFindPointInSC(ref->sc,ref->match_pt_ref,&here,NULL)==-1 ) {
+ if ( ref->transform[4]!=there.x-here.x ||
+ ref->transform[5]!=there.y-here.y ) {
+ ref->transform[4] = there.x-here.x;
+ ref->transform[5] = there.y-here.y;
+ SCReinstanciateRefChar(sc,ref);
+ if ( !top )
+ _SCCharChangedUpdate(sc,true);
+ }
+ } else
+ ref->point_match = false; /* one of the points no longer exists */
+ }
+ }
+ for ( deps = sc->dependents; deps!=NULL; deps = deps->next )
+ TTFPointMatches(deps->sc,false);
+}
+
+void _SCCharChangedUpdate(SplineChar *sc,int changed) {
+ SplineFont *sf = sc->parent;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ extern int updateflex;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+ TTFPointMatches(sc,true);
+ if ( changed != -1 ) {
+ sc->changed_since_autosave = true;
+ SFSetModTime(sf);
+ if ( (sc->changed==0) != (changed==0) ) {
+ sc->changed = (changed!=0);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FVToggleCharChanged(sc);
+ SCRefreshTitles(sc);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !sf->changed && sf->fv!=NULL )
+ FVSetTitle(sf->fv);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ if ( changed ) {
+ instrcheck(sc);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ SCDeGridFit(sc);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+ if ( !sc->parent->onlybitmaps && !sc->parent->multilayer &&
+ changed==1 && !sc->parent->strokedfont && !sc->parent->order2 )
+ sc->changedsincelasthinted = true;
+ sc->changed_since_search = true;
+ sf->changed = true;
+ sf->changed_since_autosave = true;
+ sf->changed_since_xuidchanged = true;
+ _SCHintsChanged(sc);
+ }
+ if ( sf->cidmaster!=NULL )
+ sf->cidmaster->changed = sf->cidmaster->changed_since_autosave =
+ sf->cidmaster->changed_since_xuidchanged = true;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ SCRegenDependents(sc); /* All chars linked to this one need to get the new splines */
+ if ( updateflex && sc->views!=NULL )
+ SplineCharIsFlexible(sc);
+ SCUpdateAll(sc);
+# ifdef FONTFORGE_CONFIG_TYPE3
+ SCLayersChange(sc);
+# endif
+ SCRegenFills(sc);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+}
+
+void SCCharChangedUpdate(SplineChar *sc) {
+ _SCCharChangedUpdate(sc,true);
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+void _CVCharChangedUpdate(CharView *cv,int changed) {
+ extern int updateflex;
+ FontView *fv;
+
+ CVSetCharChanged(cv,changed);
+#ifdef FONTFORGE_CONFIG_TYPE3
+ CVLayerChange(cv);
+#endif
+ if ( cv->needsrasterize ) {
+ TTFPointMatches(cv->sc,true); /* Must precede regen dependents, as this can change references */
+ SCRegenDependents(cv->sc); /* All chars linked to this one need to get the new splines */
+ if ( updateflex )
+ SplineCharIsFlexible(cv->sc);
+ SCUpdateAll(cv->sc);
+ SCRegenFills(cv->sc);
+ for ( fv = cv->sc->parent->fv; fv!=NULL; fv=fv->nextsame )
+ FVRegenChar(fv,cv->sc);
+ cv->needsrasterize = false;
+ } else if ( cv->drawmode==dm_back ) {
+ /* If we changed the background then only views of this character */
+ /* need to know about it. No dependents needed, but why write */
+ /* another routine for a rare case... */
+ SCUpdateAll(cv->sc);
+ } else if ( cv->drawmode==dm_grid ) {
+ /* If we changed the grid then any character needs to know it */
+ FVRedrawAllCharViews(cv->fv);
+ }
+ cv->recentchange = false;
+ cv->p.sp = NULL; /* Might have been deleted */
+}
+
+void CVCharChangedUpdate(CharView *cv) {
+ _CVCharChangedUpdate(cv,true);
+}
+
+static void CVMouseMove(CharView *cv, GEvent *event ) {
+ real cx, cy;
+ PressedOn p;
+ FindSel fs;
+ GEvent fake;
+ int stop_motion = false;
+
+#if 0 /* Debug wacom !!!! */
+ printf( "dev=%s (%d,%d) 0x%x\n", event->u.mouse.device!=NULL?event->u.mouse.device:"<None>",
+ event->u.mouse.x, event->u.mouse.y, event->u.mouse.state);
+#endif
+
+ if ( event->u.mouse.device!=NULL )
+ CVToolsSetCursor(cv,event->u.mouse.state,event->u.mouse.device);
+
+ if ( !cv->p.pressed ) {
+ CVUpdateInfo(cv, event);
+ if ( cv->showing_tool == cvt_pointer ) {
+ CVCheckResizeCursors(cv);
+ if ( cv->dv!=NULL )
+ CVDebugPointPopup(cv);
+ } else if ( cv->showing_tool == cvt_ruler )
+ CVMouseMoveRuler(cv,event);
+return;
+ }
+
+ SetFS(&fs,&p,cv,event);
+ if ( cv->active_tool == cvt_freehand )
+ /* freehand does it's own kind of constraining */;
+ else if ( (event->u.mouse.state&ksm_shift) && !cv->p.rubberbanding ) {
+ /* Constrained */
+
+ fake.u.mouse = event->u.mouse;
+ if ( ((event->u.mouse.state&ksm_alt) ||
+ (!cv->cntrldown && (event->u.mouse.state&ksm_control))) &&
+ (cv->p.nextcp || cv->p.prevcp)) {
+ real dot = (cv->p.cp.x-cv->p.constrain.x)*(p.cx-cv->p.constrain.x) +
+ (cv->p.cp.y-cv->p.constrain.y)*(p.cy-cv->p.constrain.y);
+ real len = (cv->p.cp.x-cv->p.constrain.x)*(cv->p.cp.x-cv->p.constrain.x)+
+ (cv->p.cp.y-cv->p.constrain.y)*(cv->p.cp.y-cv->p.constrain.y);
+ if ( len!=0 ) {
+ dot /= len;
+ /* constrain control point to same angle with respect to base point*/
+ if ( dot<0 ) dot = 0;
+ p.cx = cv->p.constrain.x + dot*(cv->p.cp.x-cv->p.constrain.x);
+ p.cy = cv->p.constrain.y + dot*(cv->p.cp.y-cv->p.constrain.y);
+ p.x = fake.u.mouse.x = cv->xoff + rint(p.cx*cv->scale);
+ p.y = fake.u.mouse.y = -cv->yoff + cv->height - rint(p.cy*cv->scale);
+ }
+ } else {
+ /* Constrain mouse to hor/vert/45 from base point */
+ int basex = cv->active_tool!=cvt_hand ? cv->xoff + rint(cv->p.constrain.x*cv->scale) : cv->p.x;
+ int basey = cv->active_tool!=cvt_hand ?-cv->yoff + cv->height - rint(cv->p.constrain.y*cv->scale) : cv->p.y;
+ int dx= event->u.mouse.x-basex, dy = event->u.mouse.y-basey;
+ int sign = dx*dy<0?-1:1;
+ double aspect = 1.0;
+
+ if ( dx<0 ) dx = -dx; if ( dy<0 ) dy = -dy;
+ if ( cv->p.img!=NULL && cv->p.img->bb.minx!=cv->p.img->bb.maxx )
+ aspect = (cv->p.img->bb.maxy - cv->p.img->bb.miny) / (cv->p.img->bb.maxx - cv->p.img->bb.minx);
+ else if ( cv->p.ref!=NULL && cv->p.ref->bb.minx!=cv->p.ref->bb.maxx )
+ aspect = (cv->p.ref->bb.maxy - cv->p.ref->bb.miny) / (cv->p.ref->bb.maxx - cv->p.ref->bb.minx);
+ if ( dy >= 2*dx ) {
+ p.x = fake.u.mouse.x = basex;
+ p.cx = cv->p.constrain.x;
+ if ( ItalicConstrained && cv->sc->parent->italicangle!=0 ) {
+ double off = tan(cv->sc->parent->italicangle*3.1415926535897932/180)*
+ (p.cy-cv->p.constrain.y);
+ double aoff = off<0 ? -off : off;
+ if ( dx>=aoff*cv->scale/2 && (event->u.mouse.x-basex<0)!=(off<0) ) {
+ p.cx -= off;
+ p.x = fake.u.mouse.x = cv->xoff + rint(p.cx*cv->scale);
+ }
+ }
+ } else if ( dx >= 2*dy ) {
+ p.y = fake.u.mouse.y = basey;
+ p.cy = cv->p.constrain.y;
+ } else if ( dx > dy ) {
+ p.x = fake.u.mouse.x = basex + sign * (event->u.mouse.y-basey)/aspect;
+ p.cx = cv->p.constrain.x - sign * (p.cy-cv->p.constrain.y)/aspect;
+ } else {
+ p.y = fake.u.mouse.y = basey + sign * (event->u.mouse.x-basex)*aspect;
+ p.cy = cv->p.constrain.y - sign * (p.cx-cv->p.constrain.x)*aspect;
+ }
+ }
+ event = &fake;
+ }
+
+ /* If we've changed the character (recentchange is true) we want to */
+ /* snap to the original location, otherwise we'll keep snapping to the */
+ /* current point as it moves across the screen (jerkily) */
+ if ( cv->active_tool == cvt_hand || cv->active_tool == cvt_freehand )
+ /* Don't snap to points */;
+ else if ( cv->active_tool == cvt_pointer &&
+ ( cv->p.nextcp || cv->p.prevcp))
+ /* Don't snap to points when moving control points */;
+ else if ( !cv->joinvalid || !CheckPoint(&fs,&cv->joinpos,NULL)) {
+ SplinePointList *spl;
+ spl = cv->layerheads[cv->drawmode]->splines;
+ if ( cv->recentchange && cv->active_tool==cvt_pointer &&
+ cv->layerheads[cv->drawmode]->undoes!=NULL &&
+ (cv->layerheads[cv->drawmode]->undoes->undotype==ut_state ||
+ cv->layerheads[cv->drawmode]->undoes->undotype==ut_tstate ))
+ spl = cv->layerheads[cv->drawmode]->undoes->u.state.splines;
+ if ( cv->active_tool != cvt_knife )
+ NearSplineSetPoints(&fs,spl);
+ else
+ InSplineSet(&fs,spl);
+ }
+ if ( p.sp!=NULL && p.sp!=cv->active_sp ) { /* Snap to points */
+ p.cx = p.sp->me.x;
+ p.cy = p.sp->me.y;
+ } else {
+ CVDoSnaps(cv,&fs);
+ }
+ cx = (p.cx -cv->p.cx) / cv->scale;
+ cy = (p.cy - cv->p.cy) / cv->scale;
+ if ( cx<0 ) cx = -cx;
+ if ( cy<0 ) cy = -cy;
+
+ /* If they haven't moved far from the start point, then snap to it */
+ if ( cx+cy < 4 ) {
+ p.x = cv->p.x; p.y = cv->p.y;
+ }
+
+ cv->info.x = p.cx; cv->info.y = p.cy;
+ cv->info_sp = p.sp;
+ cv->e.x = event->u.mouse.x; cv->e.y = event->u.mouse.y;
+ CVInfoDraw(cv,cv->gw);
+
+ switch ( cv->active_tool ) {
+ case cvt_pointer:
+ stop_motion = CVMouseMovePointer(cv,event);
+ break;
+ case cvt_magnify: case cvt_minify:
+ if ( !cv->p.rubberbanding ) {
+ cv->p.ex = cv->p.cx;
+ cv->p.ey = cv->p.cy;
+ }
+ if ( cv->p.rubberbanding )
+ CVDrawRubberRect(cv->v,cv);
+ cv->p.ex = cv->info.x;
+ cv->p.ey = cv->info.y;
+ cv->p.rubberbanding = true;
+ CVDrawRubberRect(cv->v,cv);
+ break;
+ case cvt_hand:
+ CVMouseMoveHand(cv,event);
+ break;
+ case cvt_freehand:
+ CVMouseMoveFreeHand(cv,event);
+ break;
+ case cvt_curve: case cvt_corner: case cvt_tangent:
+ CVMouseMovePoint(cv,&p);
+ break;
+ case cvt_pen:
+ CVMouseMovePen(cv,&p,event);
+ break;
+ case cvt_ruler:
+ CVMouseMoveRuler(cv,event);
+ break;
+ case cvt_rotate: case cvt_flip: case cvt_scale: case cvt_skew:
+ case cvt_3d_rotate: case cvt_perspective:
+ CVMouseMoveTransform(cv);
+ break;
+ case cvt_knife:
+ CVMouseMoveKnife(cv,&p);
+ break;
+ case cvt_rect: case cvt_elipse: case cvt_poly: case cvt_star:
+ CVMouseMoveShape(cv);
+ break;
+ }
+ if ( stop_motion ) {
+ event->type = et_mouseup;
+ CVMouseUp(cv,event);
+ }
+}
+
+static void CVMagnify(CharView *cv, real midx, real midy, int bigger) {
+ static float scales[] = { 1, 2, 3, 4, 6, 8, 11, 16, 23, 32, 45, 64, 90, 128, 181, 256, 512, 1024, 0 };
+ int i, j;
+
+ if ( bigger!=0 ) {
+ if ( cv->scale>=1 ) {
+ for ( i=0; scales[i]!=0 && cv->scale>scales[i]; ++i );
+ if ( scales[i]==0 ) i=j= i-1;
+ else if ( RealNear(scales[i],cv->scale) ) j=i;
+ else if ( i!=0 && RealNear(scales[i-1],cv->scale) ) j= --i; /* Round errors! */
+ else j = i-1;
+ } else { real sinv = 1/cv->scale; int t;
+ for ( i=0; scales[i]!=0 && sinv>scales[i]; ++i );
+ if ( scales[i]==0 ) i=j= i-1;
+ else if ( RealNear(scales[i],sinv) ) j=i;
+ else if ( i!=0 && RealNear(scales[i-1],sinv) ) j= --i; /* Round errors! */
+ else j = i-1;
+ t = j;
+ j = -i; i = -t;
+ }
+ if ( bigger==1 ) {
+ if ( i==j ) ++i;
+ if ( i>0 && scales[i]==0 ) --i;
+ if ( i>=0 )
+ cv->scale = scales[i];
+ else
+ cv->scale = 1/scales[-i];
+ } else {
+ if ( i==j ) --j;
+ if ( j<0 && scales[-j]==0 ) ++j;
+ if ( j>=0 )
+ cv->scale = scales[j];
+ else
+ cv->scale = 1/scales[-j];
+ }
+ }
+ cv->xoff = -(rint(midx*cv->scale) - cv->width/2);
+ cv->yoff = -(rint(midy*cv->scale) - cv->height/2);
+ CVNewScale(cv);
+}
+
+static void CVMouseUp(CharView *cv, GEvent *event ) {
+
+ CVMouseMove(cv,event);
+ if ( cv->pressed!=NULL ) {
+ GDrawCancelTimer(cv->pressed);
+ cv->pressed = NULL;
+ }
+ cv->p.pressed = false;
+
+ if ( cv->p.rubberbanding ) {
+ CVDrawRubberRect(cv->v,cv);
+ cv->p.rubberbanding = false;
+ } else if ( cv->p.rubberlining ) {
+ CVDrawRubberLine(cv->v,cv);
+ cv->p.rubberlining = false;
+ }
+ switch ( cv->active_tool ) {
+ case cvt_pointer:
+ CVMouseUpPointer(cv);
+ break;
+ case cvt_ruler:
+ CVMouseUpRuler(cv,event);
+ break;
+ case cvt_hand:
+ CVMouseUpHand(cv);
+ break;
+ case cvt_freehand:
+ CVMouseUpFreeHand(cv,event);
+ break;
+ case cvt_curve: case cvt_corner: case cvt_tangent: case cvt_pen:
+ CVMouseUpPoint(cv,event);
+ break;
+ case cvt_magnify: case cvt_minify:
+ if ( cv->p.x>=event->u.mouse.x-6 && cv->p.x<=event->u.mouse.x+6 &&
+ cv->p.y>=event->u.mouse.y-6 && cv->p.y<=event->u.mouse.y+6 ) {
+ real cx, cy;
+ cx = (event->u.mouse.x-cv->xoff)/cv->scale ;
+ cy = (cv->height-event->u.mouse.y-cv->yoff)/cv->scale ;
+ CVMagnify(cv,cx,cy,cv->active_tool==cvt_minify?-1:1);
+ } else {
+ DBounds b;
+ double oldscale = cv->scale;
+ if ( cv->p.cx>cv->info.x ) {
+ b.minx = cv->info.x;
+ b.maxx = cv->p.cx;
+ } else {
+ b.minx = cv->p.cx;
+ b.maxx = cv->info.x;
+ }
+ if ( cv->p.cy>cv->info.y ) {
+ b.miny = cv->info.y;
+ b.maxy = cv->p.cy;
+ } else {
+ b.miny = cv->p.cy;
+ b.maxy = cv->info.y;
+ }
+ _CVFit(cv,&b);
+ if ( oldscale==cv->scale ) {
+ cv->scale += .5;
+ CVNewScale(cv);
+ }
+ }
+ break;
+ case cvt_rotate: case cvt_flip: case cvt_scale: case cvt_skew:
+ case cvt_3d_rotate: case cvt_perspective:
+ CVMouseUpTransform(cv);
+ break;
+ case cvt_knife:
+ CVMouseUpKnife(cv,event);
+ break;
+ case cvt_rect: case cvt_elipse: case cvt_poly: case cvt_star:
+ CVMouseUpShape(cv);
+ break;
+ }
+ cv->active_tool = cvt_none;
+ CVToolsSetCursor(cv,event->u.mouse.state&~(1<<(7+event->u.mouse.button)),event->u.mouse.device); /* X still has the buttons set in the state, even though we just released them. I don't want em */
+ /* CharChangedUpdate is a rather blunt tool. When moving anchor points with */
+ /* the mouse we need finer control than it provides */
+ /* If recentchange is set then change should also be set, don't think we */
+ /* need the full form of this call */
+ if ( cv->needsrasterize || cv->recentchange )
+ _CVCharChangedUpdate(cv,2);
+}
+
+static void CVTimer(CharView *cv,GEvent *event) {
+
+ if ( event->u.timer.timer==cv->pressed ) {
+ GEvent e;
+ GDrawGetPointerPosition(cv->v,&e);
+ if ( e.u.mouse.x<0 || e.u.mouse.y<0 ||
+ e.u.mouse.x>=cv->width || e.u.mouse.y >= cv->height ) {
+ real dx = 0, dy = 0;
+ if ( e.u.mouse.x<0 )
+ dx = cv->width/8;
+ else if ( e.u.mouse.x>=cv->width )
+ dx = -cv->width/8;
+ if ( e.u.mouse.y<0 )
+ dy = -cv->height/8;
+ else if ( e.u.mouse.y>=cv->height )
+ dy = cv->height/8;
+ cv->xoff += dx; cv->yoff += dy;
+ cv->back_img_out_of_date = true;
+ if ( dy!=0 )
+ GScrollBarSetPos(cv->vsb,cv->yoff-cv->height);
+ if ( dx!=0 )
+ GScrollBarSetPos(cv->hsb,-cv->xoff);
+ GDrawRequestExpose(cv->v,NULL,false);
+ }
+#if _ModKeysAutoRepeat
+ /* Under cygwin the modifier keys auto repeat, they don't under normal X */
+ } else if ( cv->autorpt==event->u.timer.timer ) {
+ cv->autorpt = NULL;
+ CVToolsSetCursor(cv,cv->oldstate,NULL);
+ if ( cv->keysym == GK_Shift_L || cv->keysym == GK_Shift_R ||
+ cv->keysym == GK_Alt_L || cv->keysym == GK_Alt_R ||
+ cv->keysym == GK_Meta_L || cv->keysym == GK_Meta_R ) {
+ GEvent e;
+ e.w = cv->oldkeyw;
+ e.u.chr.keysym = cv->keysym;
+ e.u.chr.x = cv->oldkeyx;
+ e.u.chr.y = cv->oldkeyy;
+ CVFakeMove(cv,&e);
+ }
+#endif
+ }
+}
+
+static void CVDrop(CharView *cv,GEvent *event) {
+ /* We should get a list of character names. Add each as a RefChar */
+ int32 len;
+ int ch, first = true;
+ char *start, *pt, *cnames;
+ SplineChar *rsc;
+ RefChar *new;
+
+ if ( cv->drawmode!=dm_fore ) {
+ gwwv_post_error(_("Not Foreground"),_("References may be dragged only to the foreground layer"));
+return;
+ }
+ if ( !GDrawSelectionHasType(cv->gw,sn_drag_and_drop,"STRING"))
+return;
+ cnames = GDrawRequestSelection(cv->gw,sn_drag_and_drop,"STRING",&len);
+ if ( cnames==NULL )
+return;
+
+ start = cnames;
+ while ( *start ) {
+ while ( *start==' ' ) ++start;
+ if ( *start=='\0' )
+ break;
+ for ( pt=start; *pt && *pt!=' '; ++pt );
+ ch = *pt; *pt = '\0';
+ if ( (rsc=SFGetChar(cv->sc->parent,-1,start))!=NULL && rsc!=cv->sc ) {
+ if ( first ) {
+ CVPreserveState(cv);
+ first =false;
+ }
+ new = RefCharCreate();
+ new->transform[0] = new->transform[3] = 1.0;
+ new->layers[0].splines = NULL;
+ new->sc = rsc;
+ new->next = cv->sc->layers[ly_fore].refs;
+ cv->sc->layers[ly_fore].refs = new;
+ SCReinstanciateRefChar(cv->sc,new);
+ SCMakeDependent(cv->sc,rsc);
+ }
+ *pt = ch;
+ start = pt;
+ }
+
+ free(cnames);
+ CVCharChangedUpdate(cv);
+}
+
+#ifdef TEST_O2
+static int o2_cp_fixup( SplineSet *spl) {
+ SplinePoint *sp, *n;
+ int ret = false, spi, ni;
+
+ while ( spl!=NULL ) {
+ for ( sp=spl->first ; ; ) {
+ if ( sp->next==NULL )
+ break;
+ n = sp->next->to;
+ if ( !sp->next->order2 )
+ /* No constraints on cubics */;
+ else if ( sp->nonextcp && n->noprevcp )
+ /* A line is ok */;
+ else if ( RealNear(sp->nextcp.x,n->prevcp.x) &&
+ RealNear(sp->nextcp.y,n->prevcp.y))
+ /* That's ok as well */;
+ else {
+ ret = true;
+ fprintf( stderr, "Control point between (%g,%g) and (%g,%g) is wrong.\n",
+ sp->me.x, sp->me.y, n->me.x, n->me.y );
+ spi = SPInterpolate(sp);
+ ni = SPInterpolate(n);
+ sp->nextcp.x = (sp->nextcp.x+n->prevcp.x)/2;
+ sp->nextcp.y = (sp->nextcp.y+n->prevcp.y)/2;
+ n->prevcp = sp->nextcp;
+ if ( spi ) {
+ sp->me.x = (sp->prevcp.x + sp->nextcp.x)/2;
+ sp->me.y = (sp->prevcp.y + sp->nextcp.y)/2;
+ }
+ if ( ni ) {
+ n->me.x = (n->prevcp.x + n->nextcp.x)/2;
+ n->me.y = (n->prevcp.y + n->nextcp.y)/2;
+ }
+ }
+ sp = n;
+ if ( sp==spl->first )
+ break;
+ }
+ spl = spl->next;
+ }
+return( ret );
+}
+#endif
+
+static int v_e_h(GWindow gw, GEvent *event) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ GGadgetPopupExternalEvent(event);
+ if (( event->type==et_mouseup || event->type==et_mousedown ) &&
+ (event->u.mouse.button==4 || event->u.mouse.button==5) ) {
+ if ( !(event->u.mouse.state&(ksm_shift|ksm_control)) ) /* bind shift to magnify/minify */
+return( GGadgetDispatchEvent(cv->vsb,event));
+ }
+
+ switch ( event->type ) {
+ case et_expose:
+ GDrawSetLineWidth(gw,0);
+ CVExpose(cv,gw,event);
+#ifdef TEST_O2
+ if ( o2_cp_fixup(cv->layerheads[cv->drawmode]->splines) )
+ IError("Mismatch control points" );
+#endif
+ break;
+ case et_crossing:
+ CVCrossing(cv,event);
+ break;
+ case et_mousedown:
+ CVPaletteActivate(cv);
+ if ( cv->gic!=NULL )
+ GDrawSetGIC(gw,cv->gic,0,20);
+ if ( cv->inactive )
+ SVMakeActive(cv->searcher,cv);
+ CVMouseDown(cv,event);
+ break;
+ case et_mousemove:
+ if ( cv->p.pressed )
+ GDrawSkipMouseMoveEvents(cv->v,event);
+ CVMouseMove(cv,event);
+ break;
+ case et_mouseup:
+ CVMouseUp(cv,event);
+ break;
+ case et_char:
+ if ( cv->searcher!=NULL )
+ SVChar(cv->searcher,event);
+ else
+ CVChar(cv,event);
+ break;
+ case et_charup:
+ CVCharUp(cv,event);
+ break;
+ case et_timer:
+ CVTimer(cv,event);
+ break;
+ case et_drop:
+ CVDrop(cv,event);
+ break;
+ case et_focus:
+ if ( event->u.focus.gained_focus ) {
+ if ( cv->gic!=NULL )
+ GDrawSetGIC(gw,cv->gic,0,20);
+#if 0
+ CVPaletteActivate(cv);
+#endif
+ }
+ break;
+ }
+return( true );
+}
+
+static void CVDrawNum(CharView *cv,GWindow pixmap,int x, int y, char *format,real val, int align) {
+ char buffer[40];
+ unichar_t ubuf[40];
+ int len;
+
+ if ( val==0 ) val=0; /* avoid -0 */
+ sprintf(buffer,format,val);
+ uc_strcpy(ubuf,buffer);
+ if ( align!=0 ) {
+ len = GDrawGetTextWidth(pixmap,ubuf,-1,NULL);
+ if ( align==1 )
+ x-=len/2;
+ else
+ x-=len;
+ }
+ GDrawDrawText(pixmap,x,y,ubuf,-1,NULL,GDrawGetDefaultForeground(NULL));
+}
+
+static void CVDrawVNum(CharView *cv,GWindow pixmap,int x, int y, char *format,real val, int align) {
+ char buffer[40];
+ unichar_t ubuf[40], *upt;
+ int len;
+
+ if ( val==0 ) val=0; /* avoid -0 */
+ sprintf(buffer,format,val);
+ uc_strcpy(ubuf,buffer);
+ if ( align!=0 ) {
+ len = strlen(buffer)*cv->sfh;
+ if ( align==1 )
+ y-=len/2;
+ else
+ y-=len;
+ }
+ for ( upt=ubuf; *upt; ++upt ) {
+ GDrawDrawText(pixmap,x,y,upt,1,NULL,GDrawGetDefaultForeground(NULL));
+ y += cv->sfh;
+ }
+}
+
+
+static void CVExposeRulers(CharView *cv, GWindow pixmap ) {
+ real xmin, xmax, ymin, ymax;
+ real onehundred, pos;
+ real units, littleunits;
+ int ybase = cv->mbh+cv->infoh;
+ int x,y;
+ GRect rect;
+ Color def_fg = GDrawGetDefaultForeground(NULL);
+
+ xmin = -cv->xoff/cv->scale;
+ xmax = (cv->width-cv->xoff)/cv->scale;
+ ymin = -cv->yoff/cv->scale;
+ ymax = (cv->height-cv->yoff)/cv->scale;
+ onehundred = 100/cv->scale;
+
+ if ( onehundred<5 ) {
+ units = 1; littleunits=0;
+ } else if ( onehundred<10 ) {
+ units = 5; littleunits=1;
+ } else if ( onehundred<50 ) {
+ units = 10; littleunits=2;
+ } else if ( onehundred<100 ) {
+ units = 25; littleunits=5;
+ } else if ( onehundred<500 ) {
+ units = 100; littleunits=20;
+ } else if ( onehundred<1000 ) {
+ units = 250; littleunits=50;
+ } else if ( onehundred<5000 ) {
+ units = 1000; littleunits=200;
+ } else if ( onehundred<10000 ) {
+ units = 2500; littleunits=500;
+ } else if ( onehundred<10000 ) {
+ units = 10000; littleunits=2000;
+ } else {
+ for ( units=1 ; units<onehundred; units *= 10 );
+ units/=10; littleunits = units/2;
+ }
+
+ rect.x = 0; rect.width = cv->width+cv->rulerh; rect.y = ybase; rect.height = cv->rulerh;
+ GDrawFillRect(pixmap,&rect,GDrawGetDefaultBackground(NULL));
+ rect.y = ybase; rect.height = cv->height+cv->rulerh; rect.x = 0; rect.width = cv->rulerh;
+ GDrawFillRect(pixmap,&rect,GDrawGetDefaultBackground(NULL));
+ GDrawSetLineWidth(pixmap,0);
+ GDrawDrawLine(pixmap,cv->rulerh,cv->mbh+cv->infoh+cv->rulerh-1,8096,cv->mbh+cv->infoh+cv->rulerh-1,def_fg);
+ GDrawDrawLine(pixmap,cv->rulerh-1,cv->mbh+cv->infoh+cv->rulerh,cv->rulerh-1,8096,def_fg);
+
+ GDrawSetFont(pixmap,cv->small);
+ if ( xmax-xmin<1 && cv->width>100 ) {
+ CVDrawNum(cv,pixmap,cv->rulerh,ybase+cv->sas,"%.3f",xmin,0);
+ CVDrawNum(cv,pixmap,cv->rulerh+cv->width,ybase+cv->sas,"%.3f",xmax,2);
+ }
+ if ( ymax-ymin<1 && cv->height>100 ) {
+ CVDrawVNum(cv,pixmap,1,ybase+cv->rulerh+cv->height+cv->sas,"%.3f",ymin,0);
+ CVDrawVNum(cv,pixmap,1,ybase+cv->rulerh+cv->sas,"%.3f",ymax,2);
+ }
+ if ( fabs(xmin/units) < 1e5 && fabs(ymin/units)<1e5 && fabs(xmax/units)<1e5 && fabs(ymax/units)<1e5 ) {
+ if ( littleunits!=0 ) {
+ for ( pos=littleunits*ceil(xmin/littleunits); pos<xmax; pos += littleunits ) {
+ x = cv->xoff + rint(pos*cv->scale);
+ GDrawDrawLine(pixmap,x+cv->rulerh,ybase+cv->rulerh-4,x+cv->rulerh,ybase+cv->rulerh, def_fg);
+ }
+ for ( pos=littleunits*ceil(ymin/littleunits); pos<ymax; pos += littleunits ) {
+ y = -cv->yoff + cv->height - rint(pos*cv->scale);
+ GDrawDrawLine(pixmap,cv->rulerh-4,ybase+cv->rulerh+y,cv->rulerh,ybase+cv->rulerh+y, def_fg);
+ }
+ }
+ for ( pos=units*ceil(xmin/units); pos<xmax; pos += units ) {
+ x = cv->xoff + rint(pos*cv->scale);
+ GDrawDrawLine(pixmap,x+cv->rulerh,ybase+cv->rulerh-6,x+cv->rulerh,ybase+cv->rulerh, def_fg);
+ CVDrawNum(cv,pixmap,x+cv->rulerh,ybase+cv->sas,"%g",pos,1);
+ }
+ for ( pos=units*ceil(ymin/units); pos<ymax; pos += units ) {
+ y = -cv->yoff + cv->height - rint(pos*cv->scale);
+ GDrawDrawLine(pixmap,cv->rulerh-6,ybase+cv->rulerh+y,cv->rulerh,ybase+cv->rulerh+y, def_fg);
+ CVDrawVNum(cv,pixmap,1,y+ybase+cv->rulerh+cv->sas,"%g",pos,1);
+ }
+ }
+}
+
+static void InfoExpose(CharView *cv, GWindow pixmap, GEvent *expose) {
+ GRect old1, old2;
+ Color def_fg = GDrawGetDefaultForeground(NULL);
+
+ if ( expose->u.expose.rect.y + expose->u.expose.rect.height < cv->mbh ||
+ (!cv->showrulers && expose->u.expose.rect.y >= cv->mbh+cv->infoh ))
+return;
+
+ GDrawPushClip(pixmap,&expose->u.expose.rect,&old1);
+ GDrawSetLineWidth(pixmap,0);
+ if ( expose->u.expose.rect.y< cv->mbh+cv->infoh ) {
+#if 0
+ r.x = 0; r.width = 8096;
+ r.y = cv->mbh; r.height = cv->infoh;
+#endif
+ GDrawPushClip(pixmap,&expose->u.expose.rect,&old2);
+
+ GDrawDrawLine(pixmap,0,cv->mbh+cv->infoh-1,8096,cv->mbh+cv->infoh-1,def_fg);
+ GDrawDrawImage(pixmap,&GIcon_rightpointer,NULL,RPT_BASE,cv->mbh+2);
+ GDrawDrawImage(pixmap,&GIcon_selectedpoint,NULL,SPT_BASE,cv->mbh+2);
+ GDrawDrawImage(pixmap,&GIcon_sel2ptr,NULL,SOF_BASE,cv->mbh+2);
+ GDrawDrawImage(pixmap,&GIcon_distance,NULL,SDS_BASE,cv->mbh+2);
+ GDrawDrawImage(pixmap,&GIcon_angle,NULL,SAN_BASE,cv->mbh+2);
+ GDrawDrawImage(pixmap,&GIcon_mag,NULL,MAG_BASE,cv->mbh+2);
+ CVInfoDrawText(cv,pixmap);
+ GDrawPopClip(pixmap,&old2);
+ }
+ if ( cv->showrulers ) {
+ CVExposeRulers(cv,pixmap);
+ cv->olde.x = -1;
+ CVInfoDrawRulers(cv,pixmap);
+ }
+ GDrawPopClip(pixmap,&old1);
+}
+
+void CVResize(CharView *cv ) {
+ int sbsize = GDrawPointsToPixels(cv->gw,_GScrollBar_Width);
+ GRect size;
+ GDrawGetSize(cv->gw,&size);
+ {
+ int newwidth = size.width-sbsize,
+ newheight = size.height-sbsize - cv->mbh-cv->infoh;
+ int sbwidth = newwidth, sbheight = newheight;
+
+ if ( cv->dv!=NULL ) {
+ newwidth -= cv->dv->dwidth;
+ sbwidth -= cv->dv->dwidth;
+ }
+ if ( newwidth<30 || newheight<50 ) {
+ if ( newwidth<30 )
+ newwidth = 30+sbsize+(cv->dv!=NULL ? cv->dv->dwidth : 0);
+ if ( newheight<50 )
+ newheight = 50+sbsize+cv->mbh+cv->infoh;
+ GDrawResize(cv->gw,newwidth,newheight);
+return;
+ }
+
+ if ( cv->dv!=NULL ) {
+ int dvheight = size.height-(cv->mbh+cv->infoh);
+ GDrawMove(cv->dv->dv,size.width-cv->dv->dwidth,cv->mbh+cv->infoh);
+ GDrawResize(cv->dv->dv,cv->dv->dwidth,dvheight);
+ GDrawResize(cv->dv->ii.v,cv->dv->dwidth-sbsize,dvheight-cv->dv->toph);
+ GGadgetResize(cv->dv->ii.vsb,sbsize,dvheight-cv->dv->toph);
+ cv->dv->ii.vheight = dvheight-cv->dv->toph;
+ GDrawRequestExpose(cv->dv->dv,NULL,false);
+ GDrawRequestExpose(cv->dv->ii.v,NULL,false);
+ GScrollBarSetBounds(cv->dv->ii.vsb,0,cv->dv->ii.lheight+1,
+ cv->dv->ii.vheight/cv->dv->ii.fh);
+ }
+ if ( cv->showrulers ) {
+ newheight -= cv->rulerh;
+ newwidth -= cv->rulerh;
+ }
+
+ if ( newwidth == cv->width && newheight == cv->height )
+return;
+ if ( cv->backimgs!=NULL )
+ GDrawDestroyWindow(cv->backimgs);
+ cv->backimgs = NULL;
+
+ /* MenuBar takes care of itself */
+ GDrawResize(cv->v,newwidth,newheight);
+ GGadgetMove(cv->vsb,sbwidth, cv->mbh+cv->infoh);
+ GGadgetResize(cv->vsb,sbsize,sbheight);
+ GGadgetMove(cv->hsb,0,size.height-sbsize);
+ GGadgetResize(cv->hsb,sbwidth,sbsize);
+ cv->width = newwidth; cv->height = newheight;
+ CVFit(cv);
+ CVPalettesRaise(cv);
+ }
+}
+
+static void CVHScroll(CharView *cv,struct sbevent *sb) {
+ int newpos = cv->xoff;
+
+ switch( sb->type ) {
+ case et_sb_top:
+ newpos = 0;
+ break;
+ case et_sb_uppage:
+ newpos += 9*cv->width/10;
+ break;
+ case et_sb_up:
+ newpos += cv->width/15;
+ break;
+ case et_sb_down:
+ newpos -= cv->width/15;
+ break;
+ case et_sb_downpage:
+ newpos -= 9*cv->width/10;
+ break;
+ case et_sb_bottom:
+ newpos = 0;
+ break;
+ case et_sb_thumb:
+ case et_sb_thumbrelease:
+ newpos = -sb->pos;
+ break;
+ case et_sb_halfup:
+ newpos += cv->width/30;
+ break;
+ case et_sb_halfdown:
+ newpos -= cv->width/30;
+ break;
+ }
+ if ( newpos<-(32000*cv->scale-cv->width) )
+ newpos = -(32000*cv->scale-cv->width);
+ if ( newpos>8000*cv->scale ) newpos = 8000*cv->scale;
+ if ( newpos!=cv->xoff ) {
+ int diff = newpos-cv->xoff;
+ cv->xoff = newpos;
+ cv->back_img_out_of_date = true;
+ GScrollBarSetPos(cv->hsb,-newpos);
+ GDrawScroll(cv->v,NULL,diff,0);
+ if (( cv->showhhints && cv->sc->hstem!=NULL ) || cv->showblues || cv->showvmetrics ) {
+ GRect r;
+ r.y = 0; r.height = cv->height;
+ r.width = 6*cv->sfh+10;
+ if ( diff>0 )
+ r.x = cv->width-r.width;
+ else
+ r.x = cv->width+diff-r.width;
+ GDrawRequestExpose(cv->v,&r,false);
+ }
+ if ( cv->showrulers ) {
+ GRect r;
+ r.y = cv->infoh+cv->mbh; r.height = cv->rulerh; r.x = 0; r.width = cv->rulerh+cv->width;
+ GDrawRequestExpose(cv->gw,&r,false);
+ }
+ }
+}
+
+static void CVVScroll(CharView *cv,struct sbevent *sb) {
+ int newpos = cv->yoff;
+
+ switch( sb->type ) {
+ case et_sb_top:
+ newpos = 0;
+ break;
+ case et_sb_uppage:
+ newpos -= 9*cv->height/10;
+ break;
+ case et_sb_up:
+ newpos -= cv->height/15;
+ break;
+ case et_sb_down:
+ newpos += cv->height/15;
+ break;
+ case et_sb_downpage:
+ newpos += 9*cv->height/10;
+ break;
+ case et_sb_bottom:
+ newpos = 0;
+ break;
+ case et_sb_thumb:
+ case et_sb_thumbrelease:
+ newpos = sb->pos+cv->height;
+ break;
+ case et_sb_halfup:
+ newpos -= cv->height/30;
+ break;
+ case et_sb_halfdown:
+ newpos += cv->height/30;
+ break;
+ }
+ if ( newpos<-(20000*cv->scale-cv->height) )
+ newpos = -(20000*cv->scale-cv->height);
+ if ( newpos>8000*cv->scale ) newpos = 8000*cv->scale;
+ if ( newpos!=cv->yoff ) {
+ int diff = newpos-cv->yoff;
+ cv->yoff = newpos;
+ cv->back_img_out_of_date = true;
+ GScrollBarSetPos(cv->vsb,newpos-cv->height);
+ GDrawScroll(cv->v,NULL,0,diff);
+ if (( cv->showvhints && cv->sc->vstem!=NULL) || cv->showhmetrics ) {
+ GRect r;
+ r.x = 0; r.width = cv->width;
+ r.height = 2*cv->sfh+6;
+ if ( diff>0 )
+ r.y = 0;
+ else
+ r.y = -diff;
+ GDrawRequestExpose(cv->v,&r,false);
+ }
+ if ( cv->showrulers ) {
+ GRect r;
+ r.x = 0; r.width = cv->rulerh; r.y = cv->infoh+cv->mbh; r.height = cv->rulerh+cv->height;
+ GDrawRequestExpose(cv->gw,&r,false);
+ }
+ }
+}
+
+void LogoExpose(GWindow pixmap,GEvent *event, GRect *r,enum drawmode dm) {
+ int sbsize = GDrawPointsToPixels(pixmap,_GScrollBar_Width);
+ GRect old;
+
+ r->width = r->height = sbsize;
+ if ( event->u.expose.rect.x+event->u.expose.rect.width >= r->x &&
+ event->u.expose.rect.y+event->u.expose.rect.height >= r->y ) {
+ /* Put something into the little box where the two scroll bars meet */
+ int xoff, yoff;
+ GImage *which = (dm==dm_fore) ? &GIcon_FontForgeLogo :
+ (dm==dm_back) ? &GIcon_FontForgeBack :
+ &GIcon_FontForgeGuide;
+ struct _GImage *base = which->u.image;
+ xoff = (sbsize-base->width);
+ yoff = (sbsize-base->height);
+ GDrawPushClip(pixmap,r,&old);
+ GDrawDrawImage(pixmap,which,NULL,
+ r->x+(xoff-xoff/2),r->y+(yoff-yoff/2));
+ GDrawPopClip(pixmap,&old);
+ /*GDrawDrawLine(pixmap,r->x+sbsize-1,r->y,r->x+sbsize-1,r->y+sbsize,0x000000);*/
+ }
+}
+
+static void CVLogoExpose(CharView *cv,GWindow pixmap,GEvent *event) {
+ int rh = cv->showrulers ? cv->rulerh : 0;
+ GRect r;
+
+ r.x = cv->width+rh;
+ r.y = cv->height+cv->mbh+cv->infoh+rh;
+ LogoExpose(pixmap,event,&r,cv->drawmode);
+}
+
+static int cv_e_h(GWindow gw, GEvent *event) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ if (( event->type==et_mouseup || event->type==et_mousedown ) &&
+ (event->u.mouse.button==4 || event->u.mouse.button==5) ) {
+return( GGadgetDispatchEvent(cv->vsb,event));
+ }
+
+ switch ( event->type ) {
+ case et_selclear:
+ ClipboardClear();
+ break;
+ case et_expose:
+ GDrawSetLineWidth(gw,0);
+ InfoExpose(cv,gw,event);
+ CVLogoExpose(cv,gw,event);
+ break;
+ case et_char:
+ if ( cv->searcher!=NULL )
+ SVChar(cv->searcher,event);
+ else
+ CVChar(cv,event);
+ break;
+ case et_charup:
+ CVCharUp(cv,event);
+ break;
+ case et_resize:
+ if ( event->u.resize.sized )
+ CVResize(cv);
+ break;
+ case et_controlevent:
+ switch ( event->u.control.subtype ) {
+ case et_scrollbarchange:
+ if ( event->u.control.g == cv->hsb )
+ CVHScroll(cv,&event->u.control.u.sb);
+ else
+ CVVScroll(cv,&event->u.control.u.sb);
+ break;
+ }
+ break;
+ case et_map:
+ if ( event->u.map.is_visible )
+ CVPaletteActivate(cv);
+ else
+ CVPalettesHideIfMine(cv);
+ break;
+ case et_destroy:
+ CVUnlinkView(cv);
+ CVPalettesHideIfMine(cv);
+ if ( cv->backimgs!=NULL ) {
+ GDrawDestroyWindow(cv->backimgs);
+ cv->backimgs = NULL;
+ }
+ if ( cv->icon!=NULL ) {
+ GDrawDestroyWindow(cv->icon);
+ cv->icon = NULL;
+ }
+ CharViewFree(cv);
+ break;
+ case et_close:
+ GDrawDestroyWindow(gw);
+ break;
+ case et_mouseup: case et_mousedown:
+ GGadgetEndPopup();
+ CVPaletteActivate(cv);
+ if ( cv->inactive )
+ SVMakeActive(cv->searcher,cv);
+ break;
+ case et_mousemove:
+ if ( event->u.mouse.y>cv->mbh ) {
+ int enc = CVCurEnc(cv);
+ SCPreparePopup(cv->gw,cv->sc,cv->fv->map->remap,enc,
+ UniFromEnc(enc,cv->fv->map->enc));
+ }
+ break;
+ case et_drop:
+ CVDrop(cv,event);
+ break;
+ case et_focus:
+ if ( event->u.focus.gained_focus ) {
+ if ( cv->gic!=NULL )
+ GDrawSetGIC(gw,cv->gic,0,20);
+#if 0
+ CVPaletteActivate(cv);
+#endif
+ }
+ break;
+ }
+return( true );
+}
+
+#define MID_Fit 2001
+#define MID_ZoomIn 2002
+#define MID_ZoomOut 2003
+#define MID_HidePoints 2004
+#define MID_Fill 2006
+#define MID_Next 2007
+#define MID_Prev 2008
+#define MID_HideRulers 2009
+#define MID_NextDef 2012
+#define MID_PrevDef 2013
+#define MID_DisplayCompositions 2014
+#define MID_MarkExtrema 2015
+#define MID_Goto 2016
+#define MID_FindInFontView 2017
+#define MID_KernPairs 2018
+#define MID_AnchorPairs 2019
+#define MID_ShowGridFit 2020
+#define MID_PtsNone 2021
+#define MID_PtsTrue 2022
+#define MID_PtsPost 2023
+#define MID_PtsSVG 2024
+#define MID_Ligatures 2025
+#define MID_Former 2026
+#define MID_MarkPointsOfInflection 2027
+#define MID_ShowCPInfo 2028
+#define MID_ShowTabs 2029
+#define MID_AnchorGlyph 2030
+#define MID_AnchorControl 2031
+#define MID_ShowSideBearings 2032
+#define MID_Cut 2101
+#define MID_Copy 2102
+#define MID_Paste 2103
+#define MID_Clear 2104
+#define MID_Merge 2105
+#define MID_SelAll 2106
+#define MID_CopyRef 2107
+#define MID_UnlinkRef 2108
+#define MID_Undo 2109
+#define MID_Redo 2110
+#define MID_CopyWidth 2111
+#define MID_RemoveUndoes 2112
+#define MID_CopyFgToBg 2115
+#define MID_NextPt 2116
+#define MID_PrevPt 2117
+#define MID_FirstPt 2118
+#define MID_NextCP 2119
+#define MID_PrevCP 2120
+#define MID_SelNone 2121
+#define MID_SelectWidth 2122
+#define MID_SelectVWidth 2123
+#define MID_CopyLBearing 2124
+#define MID_CopyRBearing 2125
+#define MID_CopyVWidth 2126
+#define MID_Join 2127
+#define MID_CopyGridFit 2128
+#define MID_Elide 2129
+#define MID_SelectAllPoints 2130
+#define MID_SelectAnchors 2131
+#define MID_FirstPtNextCont 2132
+#define MID_Contours 2133
+#define MID_SelectHM 2134
+#define MID_SelInvert 2136
+#define MID_CopyBgToFg 2137
+#define MID_SelPointAt 2138
+#define MID_CopyLookupData 2139
+#define MID_Clockwise 2201
+#define MID_Counter 2202
+#define MID_GetInfo 2203
+#define MID_Correct 2204
+#define MID_AvailBitmaps 2210
+#define MID_RegenBitmaps 2211
+#define MID_Stroke 2205
+#define MID_RmOverlap 2206
+#define MID_Simplify 2207
+#define MID_BuildAccent 2208
+#define MID_Autotrace 2212
+#define MID_Round 2213
+#define MID_MetaFont 2217
+#define MID_Average 2219
+#define MID_SpacePts 2220
+#define MID_SpaceRegion 2221
+#define MID_MakeParallel 2222
+#define MID_ShowDependentRefs 2223
+#define MID_AddExtrema 2224
+#define MID_CleanupGlyph 2225
+#define MID_TilePath 2226
+#define MID_BuildComposite 2227
+#define MID_Exclude 2228
+#define MID_Intersection 2229
+#define MID_FindInter 2230
+#define MID_Effects 2231
+#define MID_SimplifyMore 2232
+#define MID_First 2233
+#define MID_Earlier 2234
+#define MID_Later 2235
+#define MID_Last 2236
+#define MID_CharInfo 2240
+#define MID_ShowDependentSubs 2241
+#define MID_CanonicalStart 2242
+#define MID_CanonicalContours 2243
+#define MID_RemoveBitmaps 2244
+#define MID_Corner 2301
+#define MID_Tangent 2302
+#define MID_Curve 2303
+#define MID_MakeFirst 2304
+#define MID_MakeLine 2305
+#define MID_CenterCP 2306
+#define MID_ImplicitPt 2307
+#define MID_NoImplicitPt 2308
+#define MID_InsertPtOnSplineAt 2309
+#define MID_AddAnchor 2310
+#define MID_AutoHint 2400
+#define MID_ClearHStem 2401
+#define MID_ClearVStem 2402
+#define MID_AddHHint 2404
+#define MID_AddVHint 2405
+#define MID_AddDHint 2406
+#define MID_ReviewHints 2407
+#define MID_CreateHHint 2408
+#define MID_CreateVHint 2409
+#define MID_MinimumDistance 2410
+#define MID_AutoInstr 2411
+#define MID_ClearInstr 2412
+#define MID_EditInstructions 2413
+#define MID_Debug 2414
+#define MID_HintSubsPt 2415
+#define MID_AutoCounter 2416
+#define MID_DontAutoHint 2417
+#define MID_Tools 2501
+#define MID_Layers 2502
+#define MID_DockPalettes 2503
+#define MID_Center 2600
+#define MID_SetWidth 2601
+#define MID_SetLBearing 2602
+#define MID_SetRBearing 2603
+#define MID_Thirds 2604
+#define MID_RemoveKerns 2605
+#define MID_SetVWidth 2606
+#define MID_RemoveVKerns 2607
+#define MID_KPCloseup 2608
+#define MID_AnchorsAway 2609
+#define MID_OpenBitmap 2700
+#define MID_Revert 2702
+#define MID_Recent 2703
+#define MID_Display 2706
+#define MID_RevertGlyph 2707
+
+#define MID_MMReblend 2800
+#define MID_MMAll 2821
+#define MID_MMNone 2822
+
+#define MID_Warnings 3000
+
+static void CVMenuClose(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ GDrawDestroyWindow(gw);
+}
+
+static void CVMenuOpenBitmap(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ if ( cv->fv->sf->bitmaps==NULL )
+return;
+ BitmapViewCreatePick(CVCurEnc(cv),cv->fv);
+}
+
+static void CVMenuOpenMetrics(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ MetricsViewCreate(cv->fv,cv->sc,NULL);
+}
+
+static void CVMenuSave(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _FVMenuSave(cv->fv);
+}
+
+static void CVMenuSaveAs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _FVMenuSaveAs(cv->fv);
+}
+
+static void CVMenuGenerate(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _FVMenuGenerate(cv->fv,false);
+}
+
+static void CVMenuGenerateFamily(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _FVMenuGenerate(cv->fv,true);
+}
+
+static void CVMenuExport(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVExport(cv);
+}
+
+static void CVMenuImport(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVImport(cv);
+}
+
+static void CVMenuRevert(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ FVDelay(cv->fv,FVRevert); /* The revert command can potentially */
+ /* destroy our window (if the char weren't in the */
+ /* old font). If that happens before the menu finishes */
+ /* we get a crash. So delay till after the menu completes */
+}
+
+void RevertedGlyphReferenceFixup(SplineChar *sc, SplineFont *sf) {
+ RefChar *refs, *prev, *next;
+
+ for ( prev=NULL, refs = sc->layers[ly_fore].refs ; refs!=NULL; refs = next ) {
+ next = refs->next;
+ if ( refs->orig_pos<sf->glyphcnt && sf->glyphs[refs->orig_pos]!=NULL ) {
+ prev = refs;
+ refs->sc = sf->glyphs[refs->orig_pos];
+ refs->unicode_enc = refs->sc->unicodeenc;
+ SCReinstanciateRefChar(sc,refs);
+ SCMakeDependent(sc,refs->sc);
+ } else {
+ if ( prev==NULL )
+ sc->layers[ly_fore].refs = next;
+ else
+ prev->next = next;
+ RefCharFree(refs);
+ }
+ }
+}
+
+static void CVMenuRevertGlyph(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SplineChar *sc, temp;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ Undoes **undoes;
+ int layer, lc;
+#endif
+ CharView *cvs;
+
+ if ( cv->sc->parent->filename==NULL || cv->sc->namechanged || cv->sc->parent->mm!=NULL )
+return;
+ if ( cv->sc->parent->sfd_version<2 )
+ gwwv_post_error(_("Old sfd file"),_("This font comes from an old format sfd file. Not all aspects of it can be reverted successfully."));
+
+ sc = SFDReadOneChar(cv->sc->parent,cv->sc->name);
+ if ( sc==NULL ) {
+ gwwv_post_error(_("Can't Find Glyph"),_("The glyph, %.80s, can't be found in the sfd file"),cv->sc->name);
+ cv->sc->namechanged = true;
+ } else {
+ SCPreserveState(cv->sc,true);
+ SCPreserveBackground(cv->sc);
+ temp = *cv->sc;
+ cv->sc->dependents = NULL;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ lc = cv->sc->layer_cnt;
+ undoes = galloc(lc*sizeof(Undoes *));
+ for ( layer=0; layer<lc; ++layer ) {
+ undoes[layer] = cv->sc->layers[layer].undoes;
+ cv->sc->layers[layer].undoes = NULL;
+ }
+#else
+ cv->sc->layers[ly_fore].undoes = cv->sc->layers[ly_back].undoes = NULL;
+#endif
+ SplineCharFreeContents(cv->sc);
+ *cv->sc = *sc;
+ chunkfree(sc,sizeof(SplineChar));
+ cv->sc->parent = temp.parent;
+ cv->sc->dependents = temp.dependents;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ for ( layer = 0; layer<lc && layer<cv->sc->layer_cnt; ++layer )
+ cv->sc->layers[layer].undoes = undoes[layer];
+ for ( ; layer<lc; ++layer )
+ UndoesFree(undoes[layer]);
+ free(undoes);
+#else
+ cv->sc->layers[ly_fore].undoes = temp.layers[ly_fore].undoes;
+ cv->sc->layers[ly_back].undoes = temp.layers[ly_back].undoes;
+#endif
+ cv->sc->views = temp.views;
+ /* cv->sc->changed = temp.changed; */
+ for ( cvs=cv->sc->views; cvs!=NULL; cvs=cvs->next ) {
+ cvs->layerheads[dm_back] = &cv->sc->layers[ly_back];
+ cvs->layerheads[dm_fore] = &cv->sc->layers[ly_fore];
+ }
+ RevertedGlyphReferenceFixup(cv->sc, temp.parent);
+ _CVCharChangedUpdate(cv,false);
+ }
+}
+
+static void CVMenuPrint(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ PrintDlg(NULL,cv->sc,NULL);
+}
+
+static void CVMenuDisplay(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ DisplayDlg(cv->sc->parent);
+}
+
+static void fllistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_Revert:
+ mi->ti.disabled = cv->fv->sf->origname==NULL || cv->fv->sf->new;
+ break;
+ case MID_RevertGlyph:
+ mi->ti.disabled = cv->fv->sf->filename==NULL ||
+ cv->fv->sf->sfd_version<2 ||
+ cv->sc->namechanged ||
+ cv->fv->sf->mm!=NULL;
+ break;
+ case MID_Recent:
+ mi->ti.disabled = !RecentFilesAny();
+ break;
+ case MID_Display:
+ mi->ti.disabled = (cv->fv->sf->onlybitmaps && cv->fv->sf->bitmaps==NULL) ||
+ cv->fv->sf->multilayer;
+ break;
+ }
+ }
+}
+
+static void CVMenuFontInfo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ DelayEvent(FontMenuFontInfo,cv->fv);
+}
+
+static void CVMenuFindProblems(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ FindProblems(NULL,cv,NULL);
+}
+
+static void CVMenuMetaFont(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+#ifdef GWW_TEST
+ extern int ChangeWeight(SplineChar *sc,double factor,double add);
+ ChangeWeight(cv->sc,2.0,25);
+#else
+ MetaFont(NULL,cv,NULL);
+#endif
+}
+
+static void CVMenuInline(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ OutlineDlg(NULL,cv,NULL,true);
+}
+
+static void CVMenuOutline(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ OutlineDlg(NULL,cv,NULL,false);
+}
+
+static void CVMenuShadow(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ ShadowDlg(NULL,cv,NULL,false);
+}
+
+static void CVMenuWireframe(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ ShadowDlg(NULL,cv,NULL,true);
+}
+
+static void _CVMenuScale(CharView *cv,struct gmenuitem *mi) {
+
+ if ( mi->mid == MID_Fit ) {
+ CVFit(cv);
+ } else {
+ BasePoint c;
+ c.x = (cv->width/2-cv->xoff)/cv->scale;
+ c.y = (cv->height/2-cv->yoff)/cv->scale;
+ if ( CVAnySel(cv,NULL,NULL,NULL,NULL))
+ CVFindCenter(cv,&c,false);
+ CVMagnify(cv,c.x,c.y,mi->mid==MID_ZoomOut?-1:1);
+ }
+}
+
+static void CVMenuScale(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVMenuScale(cv,mi);
+}
+
+static void CVMenuShowHide(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ CVShows.showpoints = cv->showpoints = !cv->showpoints;
+ GDrawRequestExpose(cv->v,NULL,false);
+}
+
+static void CVMenuNumberPoints(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ switch ( mi->mid ) {
+ case MID_PtsNone:
+ cv->showpointnumbers = false;
+ break;
+ case MID_PtsTrue:
+ cv->showpointnumbers = true;
+ break;
+ case MID_PtsPost:
+ cv->showpointnumbers = true;
+ cv->sc->numberpointsbackards = true;
+ break;
+ case MID_PtsSVG:
+ cv->showpointnumbers = true;
+ cv->sc->numberpointsbackards = false;
+ break;
+ }
+ SCNumberPoints(cv->sc);
+ SCUpdateAll(cv->sc);
+}
+
+static void CVMenuMarkExtrema(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ CVShows.markextrema = cv->markextrema = !cv->markextrema;
+ SavePrefs();
+ GDrawRequestExpose(cv->v,NULL,false);
+}
+
+static void CVMenuMarkPointsOfInflection(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ CVShows.markpoi = cv->markpoi = !cv->markpoi;
+ SavePrefs();
+ GDrawRequestExpose(cv->v,NULL,false);
+}
+
+static void CVMenuShowCPInfo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ CVShows.showcpinfo = cv->showcpinfo = !cv->showcpinfo;
+ SavePrefs();
+ /* Nothing to update, only show this stuff in the user is moving a cp */
+ /* which s/he is currently not, s/he is manipulating the menu */
+}
+
+static void CVMenuShowTabs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ CVShows.showtabs = cv->showtabs = !cv->showtabs;
+ CVChangeTabsVisibility(cv,cv->showtabs);
+ SavePrefs();
+}
+
+static void CVMenuShowSideBearings(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ CVShows.showsidebearings = cv->showsidebearings = !cv->showsidebearings;
+ SavePrefs();
+ GDrawRequestExpose(cv->v,NULL,false);
+}
+
+static void _CVMenuShowHideRulers(CharView *cv) {
+ GRect pos;
+
+ CVShows.showrulers = cv->showrulers = !cv->showrulers;
+ pos.y = cv->mbh+cv->infoh;
+ pos.x = 0;
+ if ( cv->showrulers ) {
+ cv->height -= cv->rulerh;
+ cv->width -= cv->rulerh;
+ pos.y += cv->rulerh;
+ pos.x += cv->rulerh;
+ } else {
+ cv->height += cv->rulerh;
+ cv->width += cv->rulerh;
+ }
+ cv->back_img_out_of_date = true;
+ pos.width = cv->width; pos.height = cv->height;
+ GDrawMoveResize(cv->v,pos.x,pos.y,pos.width,pos.height);
+ GDrawSync(NULL);
+ GDrawRequestExpose(cv->v,NULL,false);
+ SavePrefs();
+}
+
+static void CVMenuShowHideRulers(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVMenuShowHideRulers(cv);
+}
+
+static void CVMenuFill(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ CVShows.showfilled = cv->showfilled = !cv->showfilled;
+ CVRegenFill(cv);
+ GDrawRequestExpose(cv->v,NULL,false);
+}
+
+static void CVMenuShowGridFit(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ if ( !hasFreeType() || cv->drawmode!=dm_fore || cv->dv!=NULL )
+return;
+ CVFtPpemDlg(cv,false);
+}
+
+static void CVMenuEditInstrs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ SCEditInstructions(cv->sc);
+}
+
+static void CVMenuDebug(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ if ( !hasFreeTypeDebugger())
+return;
+ CVFtPpemDlg(cv,true);
+}
+
+static void CVMenuClearInstrs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ if ( cv->sc->ttf_instrs_len!=0 ) {
+ free(cv->sc->ttf_instrs);
+ cv->sc->ttf_instrs = NULL;
+ cv->sc->ttf_instrs_len = 0;
+ cv->sc->instructions_out_of_date = false;
+ SCCharChangedUpdate(cv->sc);
+ SCMarkInstrDlgAsChanged(cv->sc);
+ cv->sc->complained_about_ptnums = false; /* Should be after CharChanged */
+ }
+}
+
+static void CVMenuKernPairs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SFShowKernPairs(cv->sc->parent,cv->sc,NULL);
+}
+
+static void CVMenuLigatures(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SFShowLigatures(cv->fv->sf,cv->sc);
+}
+
+static void CVMenuAnchorPairs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SFShowKernPairs(cv->sc->parent,cv->sc,(AnchorClass *) (-1));
+}
+
+static void CVMenuAPDetach(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ cv->apmine = cv->apmatch = NULL;
+ cv->apsc = NULL;
+ GDrawRequestExpose(cv->v,NULL,false);
+}
+
+static void CVMenuAPAttachSC(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ enum anchor_type type;
+ AnchorPoint *ap;
+ AnchorClass *ac;
+
+ ap = mi->ti.userdata;
+ if ( ap==NULL )
+ for ( ap = cv->sc->anchor; ap!=NULL && !ap->selected; ap=ap->next );
+ if ( ap==NULL )
+ ap = cv->sc->anchor;
+ if ( ap==NULL )
+return;
+ type = ap->type;
+ cv->apmine = ap;
+ ac = ap->anchor;
+ cv->apsc = mi->ti.userdata;
+ for ( ap = cv->apsc->anchor; ap!=NULL ; ap=ap->next ) {
+ if ( ap->anchor==ac &&
+ ((type==at_centry && ap->type==at_cexit) ||
+ (type==at_cexit && ap->type==at_centry) ||
+ (type==at_mark && ap->type!=at_mark) ||
+ ((type==at_basechar || type==at_baselig || type==at_basemark) && ap->type==at_mark)) )
+ break;
+ }
+ cv->apmatch = ap;
+ GDrawRequestExpose(cv->v,NULL,false);
+}
+
+static SplineChar **GlyphsMatchingAP(SplineFont *sf, AnchorPoint *ap) {
+ SplineChar *sc;
+ AnchorClass *ac = ap->anchor;
+ enum anchor_type type = ap->type;
+ int i, k, gcnt;
+ SplineChar **glyphs;
+
+ glyphs = NULL;
+ for ( k=0; k<2; ++k ) {
+ gcnt = 0;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL ) {
+ for ( ap = sc->anchor; ap!=NULL; ap=ap->next ) {
+ if ( ap->anchor == ac &&
+ ((type==at_centry && ap->type==at_cexit) ||
+ (type==at_cexit && ap->type==at_centry) ||
+ (type==at_mark && ap->type!=at_mark) ||
+ ((type==at_basechar || type==at_baselig || type==at_basemark) && ap->type==at_mark)) )
+ break;
+ }
+ if ( ap!=NULL ) {
+ if ( k )
+ glyphs[gcnt] = sc;
+ ++gcnt;
+ }
+ }
+ if ( !k ) {
+ if ( gcnt==0 )
+return( NULL );
+ glyphs = galloc((gcnt+1)*sizeof(SplineChar *));
+ } else
+ glyphs[gcnt] = NULL;
+ }
+return( glyphs );
+}
+
+static void _CVMenuChangeChar(CharView *cv,int mid ) {
+ SplineFont *sf = cv->sc->parent;
+ int pos = -1;
+ int gid;
+ EncMap *map = cv->fv->map;
+ Encoding *enc = map->enc;
+
+ if ( cv->searcher!=NULL )
+return;
+ if ( mid == MID_Next ) {
+ pos = CVCurEnc(cv)+1;
+ } else if ( mid == MID_Prev ) {
+ pos = CVCurEnc(cv)-1;
+ } else if ( mid == MID_NextDef ) {
+ for ( pos = CVCurEnc(cv)+1; pos<map->enccount &&
+ ((gid=map->map[pos])==-1 || !SCWorthOutputting(sf->glyphs[gid])); ++pos );
+ if ( pos>=map->enccount ) {
+ if ( enc->is_tradchinese ) {
+ if ( strstrmatch(enc->enc_name,"hkscs")!=NULL ) {
+ if ( CVCurEnc(cv)<0x8140 )
+ pos = 0x8140;
+ } else {
+ if ( CVCurEnc(cv)<0xa140 )
+ pos = 0xa140;
+ }
+ } else if ( CVCurEnc(cv)<0x8431 && strstrmatch(enc->enc_name,"johab")!=NULL )
+ pos = 0x8431;
+ else if ( CVCurEnc(cv)<0xa1a1 && strstrmatch(enc->iconv_name?enc->iconv_name:enc->enc_name,"EUC")!=NULL )
+ pos = 0xa1a1;
+ else if ( CVCurEnc(cv)<0x8140 && strstrmatch(enc->enc_name,"sjis")!=NULL )
+ pos = 0x8140;
+ else if ( CVCurEnc(cv)<0xe040 && strstrmatch(enc->enc_name,"sjis")!=NULL )
+ pos = 0xe040;
+ if ( pos>=map->enccount )
+return;
+ }
+ } else if ( mid == MID_PrevDef ) {
+ for ( pos = CVCurEnc(cv)-1; pos>=0 &&
+ ((gid=map->map[pos])==-1 || !SCWorthOutputting(sf->glyphs[gid])); --pos );
+ if ( pos<0 )
+return;
+ } else if ( mid == MID_Former ) {
+ if ( cv->former_cnt<=1 )
+return;
+ for ( gid=sf->glyphcnt-1; gid>=0; --gid )
+ if ( sf->glyphs[gid]!=NULL &&
+ strcmp(sf->glyphs[gid]->name,cv->former_names[1])==0 )
+ break;
+ if ( gid<0 )
+return;
+ pos = map->backmap[gid];
+ }
+ /* Werner doesn't think it should wrap */
+ if ( pos<0 ) /* pos = map->enccount-1; */
+return;
+ else if ( pos>= map->enccount ) /* pos = 0; */
+return;
+ if ( pos>=0 && pos<map->enccount )
+ CVChangeChar(cv,pos);
+}
+
+
+static void CVMenuChangeChar(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ _CVMenuChangeChar(cv,mi->mid);
+}
+
+void CVChar(CharView *cv, GEvent *event ) {
+ extern float arrowAmount;
+
+#if _ModKeysAutoRepeat
+ /* Under cygwin these keys auto repeat, they don't under normal X */
+ if ( cv->autorpt!=NULL ) {
+ GDrawCancelTimer(cv->autorpt); cv->autorpt = NULL;
+ if ( cv->keysym == event->u.chr.keysym ) /* It's an autorepeat, ignore it */
+return;
+ CVToolsSetCursor(cv,cv->oldstate,NULL);
+ }
+#endif
+
+#if MyMemory
+ if ( event->u.chr.keysym == GK_F2 ) {
+ fprintf( stderr, "Malloc debug on\n" );
+ __malloc_debug(5);
+ } else if ( event->u.chr.keysym == GK_F3 ) {
+ fprintf( stderr, "Malloc debug off\n" );
+ __malloc_debug(0);
+ }
+#endif
+#if 0
+ if ( event->u.chr.keysym == GK_F4 ) {
+ RepeatFromFile(cv);
+ }
+#endif
+
+ CVPaletteActivate(cv);
+ CVToolsSetCursor(cv,TrueCharState(event),NULL);
+ /* The isalpha check is to prevent infinite loops since DVChar can */
+ /* call CVChar too */
+ if ( cv->dv!=NULL && isalpha(event->u.chr.chars[0]) && DVChar(cv->dv,event))
+ /* All Done */;
+ else if ( event->u.chr.keysym=='s' &&
+ (event->u.chr.state&ksm_control) &&
+ (event->u.chr.state&ksm_meta) )
+ MenuSaveAll(NULL,NULL,NULL);
+ else if ( event->u.chr.keysym=='q' &&
+ (event->u.chr.state&ksm_control) &&
+ (event->u.chr.state&ksm_meta) )
+ MenuExit(NULL,NULL,NULL);
+ else if ( event->u.chr.keysym == GK_Shift_L || event->u.chr.keysym == GK_Shift_R ||
+ event->u.chr.keysym == GK_Alt_L || event->u.chr.keysym == GK_Alt_R ||
+ event->u.chr.keysym == GK_Meta_L || event->u.chr.keysym == GK_Meta_R ) {
+ CVFakeMove(cv, event);
+ } else if ( (event->u.chr.state&ksm_meta) &&
+ !(event->u.chr.state&(ksm_control|ksm_shift)) &&
+ event->u.chr.chars[0]!='\0' ) {
+ CVPaletteMnemonicCheck(event);
+ } else if ( !(event->u.chr.state&(ksm_control|ksm_meta)) &&
+ event->u.chr.keysym == GK_BackSpace ) {
+ /* Menu does delete */
+ CVClear(cv->gw,NULL,NULL);
+ } else if ( event->u.chr.keysym == GK_Help ) {
+ MenuHelp(NULL,NULL,NULL); /* Menu does F1 */
+ } else if ( event->u.chr.keysym=='<' && (event->u.chr.state&ksm_control) ) {
+ /* European keyboards do not need shift to get < */
+ CVDoFindInFontView(cv);
+ } else if ( (event->u.chr.keysym=='[' || event->u.chr.keysym==']') &&
+ (event->u.chr.state&ksm_control) ) {
+ /* European keyboards need a funky modifier to get [] */
+ _CVMenuChangeChar(cv,event->u.chr.keysym=='[' ? MID_Prev : MID_Next );
+ } else if ( (event->u.chr.keysym=='{' || event->u.chr.keysym=='}') &&
+ (event->u.chr.state&ksm_control) ) {
+ /* European keyboards need a funky modifier to get {} */
+ _CVMenuChangeChar(cv,event->u.chr.keysym=='{' ? MID_PrevDef : MID_NextDef );
+ } else if ( event->u.chr.keysym=='\\' && (event->u.chr.state&ksm_control) ) {
+ /* European keyboards need a funky modifier to get \ */
+ CVDoTransform(cv,cvt_none);
+ } else if ( event->u.chr.keysym == GK_Left ||
+ event->u.chr.keysym == GK_Up ||
+ event->u.chr.keysym == GK_Right ||
+ event->u.chr.keysym == GK_Down ||
+ event->u.chr.keysym == GK_KP_Left ||
+ event->u.chr.keysym == GK_KP_Up ||
+ event->u.chr.keysym == GK_KP_Right ||
+ event->u.chr.keysym == GK_KP_Down ) {
+ real dx=0, dy=0; int anya;
+ switch ( event->u.chr.keysym ) {
+ case GK_Left: case GK_KP_Left:
+ dx = -1;
+ break;
+ case GK_Right: case GK_KP_Right:
+ dx = 1;
+ break;
+ case GK_Up: case GK_KP_Up:
+ dy = 1;
+ break;
+ case GK_Down: case GK_KP_Down:
+ dy = -1;
+ break;
+ }
+ if ( event->u.chr.state & (ksm_control|ksm_capslock) ) {
+ struct sbevent sb;
+ sb.type = dy>0 || dx<0 ? et_sb_halfup : et_sb_halfdown;
+ if ( dx==0 )
+ CVVScroll(cv,&sb);
+ else
+ CVHScroll(cv,&sb);
+ } else {
+ if ( event->u.chr.state & ksm_meta ) {
+ dx *= 10; dy *= 10;
+ }
+ if ( event->u.chr.state & (ksm_shift) )
+ dx -= dy*tan((cv->sc->parent->italicangle)*(3.1415926535897932/180) );
+ if (( cv->p.sp!=NULL || cv->lastselpt!=NULL ) &&
+ (cv->p.nextcp || cv->p.prevcp) ) {
+ SplinePoint *sp = cv->p.sp ? cv->p.sp : cv->lastselpt;
+ SplinePoint *old = cv->p.sp;
+ BasePoint *which = cv->p.nextcp ? &sp->nextcp : &sp->prevcp;
+ BasePoint to;
+ to.x = which->x + dx*arrowAmount;
+ to.y = which->y + dy*arrowAmount;
+ cv->p.sp = sp;
+ CVPreserveState(cv);
+ CVAdjustControl(cv,which,&to);
+ cv->p.sp = old;
+ SCUpdateAll(cv->sc);
+ } else if ( CVAnySel(cv,NULL,NULL,NULL,&anya) || cv->widthsel || cv->vwidthsel ) {
+ CVPreserveState(cv);
+ CVMoveSelection(cv,dx*arrowAmount,dy*arrowAmount, event->u.chr.state);
+ if ( cv->widthsel )
+ SCSynchronizeWidth(cv->sc,cv->sc->width,cv->sc->width-dx,NULL);
+ _CVCharChangedUpdate(cv,2);
+ CVInfoDraw(cv,cv->gw);
+ }
+ }
+ } else if ( event->u.chr.keysym == GK_Page_Up ||
+ event->u.chr.keysym == GK_KP_Page_Up ||
+ event->u.chr.keysym == GK_Prior ||
+ event->u.chr.keysym == GK_Page_Down ||
+ event->u.chr.keysym == GK_KP_Page_Down ||
+ event->u.chr.keysym == GK_Next ) {
+ /* Um... how do we scroll horizontally??? */
+ struct sbevent sb;
+ sb.type = et_sb_uppage;
+ if ( event->u.chr.keysym == GK_Page_Down ||
+ event->u.chr.keysym == GK_KP_Page_Down ||
+ event->u.chr.keysym == GK_Next )
+ sb.type = et_sb_downpage;
+ CVVScroll(cv,&sb);
+ } else if ( event->u.chr.keysym == GK_Home ) {
+ CVFit(cv);
+ } else if ( !(event->u.chr.state&(ksm_control|ksm_meta)) &&
+ event->type == et_char &&
+ cv->searcher==NULL &&
+ cv->dv==NULL &&
+ event->u.chr.chars[0]>=' ' && event->u.chr.chars[1]=='\0' ) {
+ SplineFont *sf = cv->sc->parent;
+ int i;
+ EncMap *map = cv->fv->map;
+ extern int cv_auto_goto;
+ if ( cv_auto_goto ) {
+ i = SFFindSlot(sf,map,event->u.chr.chars[0],NULL);
+ if ( i!=-1 )
+ CVChangeChar(cv,i);
+ }
+ }
+}
+
+void CVShowPoint(CharView *cv, BasePoint *me) {
+ int x, y;
+ int fudge = 30;
+
+ if ( cv->width<60 )
+ fudge = cv->width/3;
+ if ( cv->height<60 && fudge>cv->height/3 )
+ fudge = cv->height/3;
+
+ /* Make sure the point is visible and has some context around it */
+ x = cv->xoff + rint(me->x*cv->scale);
+ y = -cv->yoff + cv->height - rint(me->y*cv->scale);
+ if ( x<fudge || y<fudge || x>cv->width-fudge || y>cv->height-fudge )
+ CVMagnify(cv,me->x,me->y,0);
+}
+
+static void CVSelectContours(CharView *cv,struct gmenuitem *mi) {
+ SplineSet *spl;
+ SplinePoint *sp;
+ int sel;
+
+ for ( spl=cv->layerheads[cv->drawmode]->splines; spl!=NULL; spl=spl->next ) {
+ sel = false;
+ for ( sp=spl->first ; ; ) {
+ if ( sp->selected ) {
+ sel = true;
+ break;
+ }
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ if ( sel ) {
+ for ( sp=spl->first ; ; ) {
+ sp->selected = true;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ }
+ }
+ SCUpdateAll(cv->sc);
+}
+
+static void CVMenuSelectContours(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVSelectContours(cv,mi);
+}
+
+static void CVMenuSelectPointAt(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVSelectPointAt(cv);
+}
+
+static void CVNextPrevPt(CharView *cv,struct gmenuitem *mi) {
+ SplinePoint *selpt=NULL, *other;
+ RefChar *r; ImageList *il;
+ SplineSet *spl, *ss;
+ int x, y;
+
+ if ( mi->mid != MID_FirstPt ) {
+ if ( cv->layerheads[cv->drawmode]->splines==NULL )
+return;
+ other = (cv->layerheads[cv->drawmode]->splines)->first;
+ CVClearSel(cv);
+ } else {
+ if ( !CVOneThingSel(cv,&selpt,&spl,&r,&il,NULL) || spl==NULL )
+return;
+ other = selpt;
+ if ( spl==NULL )
+return;
+ else if ( mi->mid == MID_NextPt ) {
+ if ( other->next!=NULL && other->next->to!=spl->first )
+ other = other->next->to;
+ else {
+ if ( spl->next == NULL )
+ spl = cv->layerheads[cv->drawmode]->splines;
+ else
+ spl = spl->next;
+ other = spl->first;
+ }
+ } else if ( mi->mid == MID_PrevPt ) {
+ if ( other!=spl->first ) {
+ other = other->prev->from;
+ } else {
+ if ( spl==cv->layerheads[cv->drawmode]->splines ) {
+ for ( ss = cv->layerheads[cv->drawmode]->splines; ss->next!=NULL; ss=ss->next );
+ } else {
+ for ( ss = cv->layerheads[cv->drawmode]->splines; ss->next!=spl; ss=ss->next );
+ }
+ spl = ss;
+ other = ss->last;
+ if ( spl->last==spl->first && spl->last->prev!=NULL )
+ other = other->prev->from;
+ }
+ } else if ( mi->mid == MID_FirstPtNextCont ) {
+ if ( spl->next!=NULL )
+ other = spl->next->first;
+ else
+ other = NULL;
+ }
+ }
+ if ( selpt!=NULL )
+ selpt->selected = false;
+ if ( other!=NULL )
+ other->selected = true;
+ cv->p.sp = NULL;
+ cv->lastselpt = other;
+
+ /* Make sure the point is visible and has some context around it */
+ if ( other!=NULL ) {
+ x = cv->xoff + rint(other->me.x*cv->scale);
+ y = -cv->yoff + cv->height - rint(other->me.y*cv->scale);
+ if ( x<40 || y<40 || x>cv->width-40 || y>cv->height-40 )
+ CVMagnify(cv,other->me.x,other->me.y,0);
+ }
+
+ CVInfoDraw(cv,cv->gw);
+ SCUpdateAll(cv->sc);
+}
+
+static void CVMenuNextPrevPt(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVNextPrevPt(cv,mi);
+}
+
+static void CVNextPrevCPt(CharView *cv,struct gmenuitem *mi) {
+ SplinePoint *selpt=NULL;
+ RefChar *r; ImageList *il;
+ SplineSet *spl;
+
+ if ( !CVOneThingSel(cv,&selpt,&spl,&r,&il,NULL))
+return;
+ if ( selpt==NULL )
+return;
+ cv->p.nextcp = mi->mid==MID_NextCP;
+ cv->p.prevcp = mi->mid==MID_PrevCP;
+ SCUpdateAll(cv->sc);
+}
+
+static void CVMenuNextPrevCPt(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVNextPrevCPt(cv,mi);
+}
+
+static void CVMenuGotoChar(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ int pos = GotoChar(cv->fv->sf,cv->fv->map);
+
+ if ( pos!=-1 )
+ CVChangeChar(cv,pos);
+}
+
+static void CVMenuFindInFontView(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ CVDoFindInFontView(cv);
+}
+
+static void CVMenuPalettesDock(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ PalettesChangeDocking();
+}
+
+static void CVMenuPaletteShow(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ CVPaletteSetVisible(cv, mi->mid==MID_Tools, !CVPaletteIsVisible(cv, mi->mid==MID_Tools));
+}
+
+static void cv_pllistcheck(CharView *cv,struct gmenuitem *mi,GEvent *e) {
+ extern int palettes_docked;
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_Tools:
+ mi->ti.checked = CVPaletteIsVisible(cv,1);
+ break;
+ case MID_Layers:
+ mi->ti.checked = CVPaletteIsVisible(cv,0);
+ break;
+ case MID_DockPalettes:
+ mi->ti.checked = palettes_docked;
+ break;
+ }
+ }
+}
+
+static void pllistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ cv_pllistcheck(cv,mi,e);
+}
+
+static void CVUndo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVDoUndo(cv);
+}
+
+static void CVRedo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVDoRedo(cv);
+}
+
+static void _CVCopy(CharView *cv) {
+ int desel = false, anya;
+
+ if ( !CVAnySel(cv,NULL,NULL,NULL,&anya))
+ if ( !(desel = CVSetSel(cv,-1)))
+return;
+ CopySelected(cv);
+ if ( desel )
+ CVClearSel(cv);
+}
+
+static void CVCopy(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVCopy(cv);
+}
+
+static void CVCopyLookupData(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SCCopyLookupData(cv->sc);
+}
+
+static void CVCopyRef(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CopyReference(cv->sc);
+}
+
+static void CVMenuCopyGridFit(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVCopyGridFit(cv);
+}
+
+static void CVCopyWidth(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ if ( mi->mid==MID_CopyVWidth && !cv->sc->parent->hasvmetrics )
+return;
+ CopyWidth(cv,mi->mid==MID_CopyWidth?ut_width:
+ mi->mid==MID_CopyVWidth?ut_vwidth:
+ mi->mid==MID_CopyLBearing?ut_lbearing:
+ ut_rbearing);
+}
+
+static void CVDoClear(CharView *cv) {
+ ImageList *prev, *imgs, *next;
+
+ CVPreserveState(cv);
+ if ( cv->drawmode==dm_fore )
+ SCRemoveSelectedMinimumDistances(cv->sc,2);
+ cv->layerheads[cv->drawmode]->splines = SplinePointListRemoveSelected(cv->sc,
+ cv->layerheads[cv->drawmode]->splines);
+ if ( cv->drawmode==dm_fore ) {
+ RefChar *refs, *next;
+ AnchorPoint *ap, *aprev=NULL, *anext;
+ for ( refs=cv->sc->layers[ly_fore].refs; refs!=NULL; refs = next ) {
+ next = refs->next;
+ if ( refs->selected )
+ SCRemoveDependent(cv->sc,refs);
+ }
+ if ( cv->showanchor ) for ( ap=cv->sc->anchor; ap!=NULL; ap=anext ) {
+ anext = ap->next;
+ if ( ap->selected ) {
+ if ( aprev!=NULL )
+ aprev->next = anext;
+ else
+ cv->sc->anchor = anext;
+ ap->next = NULL;
+ AnchorPointsFree(ap);
+ } else
+ aprev = ap;
+ }
+ }
+ for ( prev = NULL, imgs=cv->layerheads[cv->drawmode]->images; imgs!=NULL; imgs = next ) {
+ next = imgs->next;
+ if ( !imgs->selected )
+ prev = imgs;
+ else {
+ if ( prev==NULL )
+ cv->layerheads[cv->drawmode]->images = next;
+ else
+ prev->next = next;
+ chunkfree(imgs,sizeof(ImageList));
+ /* garbage collection of images????!!!! */
+ }
+ }
+ if ( cv->lastselpt!=NULL || cv->p.sp!=NULL ) {
+ cv->lastselpt = NULL; cv->p.sp = NULL;
+ CVInfoDraw(cv,cv->gw);
+ }
+}
+
+static void CVClear(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ int anyanchor;
+
+ if ( !CVAnySel(cv,NULL,NULL,NULL,&anyanchor))
+return;
+ CVDoClear(cv);
+ CVCharChangedUpdate(cv);
+}
+
+static void CVClearBackground(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ SCClearBackground(cv->sc);
+}
+
+static void _CVPaste(CharView *cv) {
+ enum undotype ut = CopyUndoType();
+ int was_empty = cv->drawmode==dm_fore && cv->sc->hstem==NULL && cv->sc->vstem==NULL && cv->sc->layers[ly_fore].splines==NULL && cv->sc->layers[ly_fore].refs==NULL;
+ if ( ut!=ut_lbearing ) /* The lbearing code does this itself */
+ CVPreserveStateHints(cv);
+ if ( ut!=ut_width && ut!=ut_vwidth && ut!=ut_lbearing && ut!=ut_rbearing && ut!=ut_possub )
+ CVClearSel(cv);
+ PasteToCV(cv);
+ CVCharChangedUpdate(cv);
+ if ( was_empty && (cv->sc->hstem != NULL || cv->sc->vstem!=NULL ))
+ cv->sc->changedsincelasthinted = false;
+}
+
+static void CVPaste(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVPaste(cv);
+}
+
+static void _CVMerge(CharView *cv,int elide) {
+ int anyp = 0;
+
+ if ( !CVAnySel(cv,&anyp,NULL,NULL,NULL) || !anyp)
+return;
+ CVPreserveState(cv);
+ SplineCharMerge(cv->sc,&cv->layerheads[cv->drawmode]->splines,!elide);
+ SCClearSelPt(cv->sc);
+ CVCharChangedUpdate(cv);
+}
+
+static void CVMerge(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVMerge(cv,false);
+}
+
+static void CVElide(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVMerge(cv,true);
+}
+
+static void _CVJoin(CharView *cv) {
+ int anyp = 0, changed;
+ extern float joinsnap;
+
+ CVAnySel(cv,&anyp,NULL,NULL,NULL);
+ CVPreserveState(cv);
+ cv->layerheads[cv->drawmode]->splines = SplineSetJoin(cv->layerheads[cv->drawmode]->splines,!anyp,joinsnap/cv->scale,&changed);
+ if ( changed )
+ CVCharChangedUpdate(cv);
+}
+
+static void CVJoin(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVJoin(cv);
+}
+
+static void _CVCut(CharView *cv) {
+ int anya;
+
+ if ( !CVAnySel(cv,NULL,NULL,NULL,&anya))
+return;
+ _CVCopy(cv);
+ CVDoClear(cv);
+ CVCharChangedUpdate(cv);
+}
+
+static void CVCut(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVCut(cv);
+}
+
+static void CVCopyFgBg(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ if ( cv->sc->layers[ly_fore].splines==NULL )
+return;
+ SCCopyFgToBg(cv->sc,true);
+}
+
+#ifdef FONTFORGE_CONFIG_COPY_BG_TO_FG
+static void CVCopyBgFg(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ if ( cv->sc->layers[ly_back].splines==NULL )
+return;
+ SCCopyBgToFg(cv->sc,true);
+}
+#endif
+
+static void CVSelectAll(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ int mask = -1;
+
+ if ( mi->mid==MID_SelectAllPoints )
+ mask = 1;
+ else if ( mi->mid==MID_SelectAnchors )
+ mask = 2;
+ if ( CVSetSel(cv,mask))
+ SCUpdateAll(cv->sc);
+}
+
+static void CVSelectNone(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ if ( CVClearSel(cv))
+ SCUpdateAll(cv->sc);
+}
+
+static void CVSelectInvert(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVInvertSel(cv);
+ SCUpdateAll(cv->sc);
+}
+
+static void CVSelectWidth(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ if ( HasUseMyMetrics(cv->sc)!=NULL )
+return;
+ cv->widthsel = !cv->widthsel;
+ cv->oldwidth = cv->sc->width;
+ SCUpdateAll(cv->sc);
+}
+
+static void CVSelectVWidth(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ if ( !cv->showvmetrics || !cv->sc->parent->hasvmetrics )
+return;
+ if ( HasUseMyMetrics(cv->sc)!=NULL )
+return;
+ cv->vwidthsel = !cv->widthsel;
+ cv->oldvwidth = cv->sc->vwidth;
+ SCUpdateAll(cv->sc);
+}
+
+static void CVSelectHM(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SplinePoint *sp; SplineSet *spl; RefChar *r; ImageList *im;
+ int exactlyone = CVOneThingSel(cv,&sp,&spl,&r,&im,NULL);
+
+ if ( !exactlyone || sp==NULL || sp->hintmask == NULL || spl==NULL )
+return;
+ while ( sp!=NULL ) {
+ if ( sp->prev==NULL )
+ break;
+ sp = sp->prev->from;
+ if ( sp == spl->first )
+ break;
+ if ( sp->hintmask!=NULL )
+ goto done;
+ sp->selected = true;
+ }
+ for ( spl = spl->next; spl!=NULL; spl = spl->next ) {
+ for ( sp=spl->first; sp!=NULL; ) {
+ if ( sp->hintmask!=NULL )
+ goto done;
+ sp->selected = true;
+ if ( sp->prev==NULL )
+ break;
+ sp = sp->prev->from;
+ if ( sp == spl->first )
+ break;
+ }
+ }
+ done:
+ SCUpdateAll(cv->sc);
+}
+
+static void _CVUnlinkRef(CharView *cv) {
+ int anyrefs=0;
+ RefChar *rf, *next;
+
+ if ( cv->drawmode==dm_fore && cv->layerheads[dm_fore]->refs!=NULL ) {
+ CVPreserveState(cv);
+ for ( rf=cv->layerheads[dm_fore]->refs; rf!=NULL && !anyrefs; rf=rf->next )
+ if ( rf->selected ) anyrefs = true;
+ for ( rf=cv->layerheads[dm_fore]->refs; rf!=NULL ; rf=next ) {
+ next = rf->next;
+ if ( rf->selected || !anyrefs) {
+ SCRefToSplines(cv->sc,rf);
+ }
+ }
+ CVSetCharChanged(cv,true);
+ SCUpdateAll(cv->sc);
+ /* Don't need to update dependancies, their splines won't have changed*/
+ }
+}
+
+static void CVUnlinkRef(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVUnlinkRef(cv);
+}
+
+static void CVRemoveUndoes(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ UndoesFree(cv->layerheads[cv->drawmode]->undoes);
+ UndoesFree(cv->layerheads[cv->drawmode]->redoes);
+ cv->layerheads[cv->drawmode]->undoes = cv->layerheads[cv->drawmode]->redoes = NULL;
+}
+
+/* We can only paste if there's something in the copy buffer */
+/* we can only copy if there's something selected to copy */
+/* figure out what things are possible from the edit menu before the user */
+/* pulls it down */
+static void cv_edlistcheck(CharView *cv,struct gmenuitem *mi,GEvent *e,int is_cv) {
+ int anypoints, anyrefs, anyimages, anyanchor;
+
+ CVAnySel(cv,&anypoints,&anyrefs,&anyimages,&anyanchor);
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_Join:
+ mi->ti.disabled = !anypoints;
+ break;
+ case MID_Merge:
+ mi->ti.disabled = !anypoints;
+ break;
+ case MID_Elide:
+ mi->ti.disabled = !anypoints;
+ break;
+ case MID_Clear: case MID_Cut: /*case MID_Copy:*/
+ /* If nothing is selected, copy copies everything */
+ mi->ti.disabled = !anypoints && !anyrefs && !anyimages && !anyanchor;
+ break;
+ case MID_CopyLBearing: case MID_CopyRBearing:
+ mi->ti.disabled = cv->drawmode!=dm_fore ||
+ (cv->sc->layers[ly_fore].splines==NULL && cv->sc->layers[ly_fore].refs==NULL);
+ break;
+#ifdef FONTFORGE_CONFIG_COPY_BG_TO_FG
+ case MID_CopyBgToFg:
+ mi->ti.disabled = cv->sc->layers[ly_back].splines==NULL;
+ break;
+#endif
+ case MID_CopyFgToBg:
+ mi->ti.disabled = cv->sc->layers[ly_fore].splines==NULL;
+ break;
+ case MID_CopyGridFit:
+ mi->ti.disabled = cv->gridfit==NULL;
+ break;
+ case MID_Paste:
+ mi->ti.disabled = !CopyContainsSomething() &&
+#ifndef _NO_LIBPNG
+ !GDrawSelectionHasType(cv->gw,sn_clipboard,"image/png") &&
+#endif
+#ifndef _NO_LIBXML
+ !GDrawSelectionHasType(cv->gw,sn_clipboard,"image/svg") &&
+#endif
+ !GDrawSelectionHasType(cv->gw,sn_clipboard,"image/bmp") &&
+ !GDrawSelectionHasType(cv->gw,sn_clipboard,"image/eps") &&
+ !GDrawSelectionHasType(cv->gw,sn_clipboard,"image/ps");
+ break;
+ case MID_Undo:
+ mi->ti.disabled = cv->layerheads[cv->drawmode]->undoes==NULL;
+ break;
+ case MID_Redo:
+ mi->ti.disabled = cv->layerheads[cv->drawmode]->redoes==NULL;
+ break;
+ case MID_RemoveUndoes:
+ mi->ti.disabled = cv->layerheads[cv->drawmode]->undoes==NULL && cv->layerheads[cv->drawmode]->redoes==NULL;
+ break;
+ case MID_CopyRef:
+ mi->ti.disabled = cv->drawmode!=dm_fore || cv->searcher!=NULL;
+ break;
+ case MID_CopyLookupData:
+ mi->ti.disabled = (cv->sc->possub==NULL && cv->sc->kerns==NULL && cv->sc->vkerns==NULL) ||
+ cv->searcher!=NULL;
+ break;
+ case MID_UnlinkRef:
+ mi->ti.disabled = cv->drawmode!=dm_fore || cv->sc->layers[ly_fore].refs==NULL;
+ break;
+ }
+ }
+}
+
+static void edlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ cv_edlistcheck(cv,mi,e,true);
+}
+
+int BpColinear(BasePoint *first, BasePoint *mid, BasePoint *last) {
+ BasePoint dist_f, unit_f, dist_l, unit_l;
+ double len, off_l, off_f;
+
+ dist_f.x = first->x - mid->x; dist_f.y = first->y - mid->y;
+ len = sqrt( dist_f.x*dist_f.x + dist_f.y*dist_f.y );
+ if ( len==0 )
+return( false );
+ unit_f.x = dist_f.x/len; unit_f.y = dist_f.y/len;
+
+ dist_l.x = last->x - mid->x; dist_l.y = last->y - mid->y;
+ len = sqrt( dist_l.x*dist_l.x + dist_l.y*dist_l.y );
+ if ( len==0 )
+return( false );
+ unit_l.x = dist_l.x/len; unit_l.y = dist_l.y/len;
+
+ off_f = dist_l.x*unit_f.y - dist_l.y*unit_f.x;
+ off_l = dist_f.x*unit_l.y - dist_f.y*unit_l.x;
+ if ( ( off_f<-1.5 || off_f>1.5 ) && ( off_l<-1.5 || off_l>1.5 ))
+return( false );
+
+return( true );
+}
+
+void SPChangePointType(SplinePoint *sp, int pointtype) {
+ BasePoint unitnext, unitprev;
+ double nextlen, prevlen;
+ int makedflt;
+ /*int oldpointtype = sp->pointtype;*/
+
+ if ( sp->pointtype==pointtype ) {
+ if ( pointtype==pt_curve ) {
+ if ( !sp->nextcpdef && sp->next!=NULL && !sp->next->order2 )
+ SplineCharDefaultNextCP(sp);
+ if ( !sp->prevcpdef && sp->prev!=NULL && !sp->prev->order2 )
+ SplineCharDefaultPrevCP(sp);
+ }
+return;
+ }
+ sp->pointtype = pointtype;
+
+ if ( pointtype==pt_corner ) {
+ /* Leave control points as they are */;
+ sp->nextcpdef = sp->nonextcp;
+ sp->prevcpdef = sp->noprevcp;
+ } else if ( pointtype==pt_tangent ) {
+ if ( sp->next!=NULL && !sp->nonextcp && sp->next->knownlinear ) {
+ sp->nonextcp = true;
+ sp->nextcp = sp->me;
+ } else if ( sp->prev!=NULL && !sp->nonextcp &&
+ BpColinear(&sp->prev->from->me,&sp->me,&sp->nextcp) ) {
+ /* The current control point is reasonable */
+ } else {
+ SplineCharTangentNextCP(sp);
+ if ( sp->next ) SplineRefigure(sp->next);
+ }
+ if ( sp->prev!=NULL && !sp->noprevcp && sp->prev->knownlinear ) {
+ sp->noprevcp = true;
+ sp->prevcp = sp->me;
+ } else if ( sp->next!=NULL && !sp->noprevcp &&
+ BpColinear(&sp->next->to->me,&sp->me,&sp->prevcp) ) {
+ /* The current control point is reasonable */
+ } else {
+ SplineCharTangentPrevCP(sp);
+ if ( sp->prev ) SplineRefigure(sp->prev);
+ }
+ } else if ( BpColinear(&sp->prevcp,&sp->me,&sp->nextcp) ||
+ ( sp->nonextcp ^ sp->noprevcp )) {
+ /* Retain the old control points */
+ } else {
+ unitnext.x = sp->nextcp.x-sp->me.x; unitnext.y = sp->nextcp.y-sp->me.y;
+ nextlen = sqrt(unitnext.x*unitnext.x + unitnext.y*unitnext.y);
+ unitprev.x = sp->me.x-sp->prevcp.x; unitprev.y = sp->me.y-sp->prevcp.y;
+ prevlen = sqrt(unitprev.x*unitprev.x + unitprev.y*unitprev.y);
+ makedflt=true;
+ if ( nextlen!=0 && prevlen!=0 ) {
+ unitnext.x /= nextlen; unitnext.y /= nextlen;
+ unitprev.x /= prevlen; unitprev.y /= prevlen;
+ if ( unitnext.x*unitprev.x + unitnext.y*unitprev.y>=.95 ) {
+ /* If the control points are essentially in the same direction*/
+ /* (so valid for a curve) then leave them as is */
+ makedflt = false;
+ }
+ }
+ if ( makedflt ) {
+ sp->nextcpdef = sp->prevcpdef = true;
+ if (( sp->prev!=NULL && sp->prev->order2 ) ||
+ (sp->next!=NULL && sp->next->order2)) {
+ if ( sp->prev!=NULL )
+ SplineRefigureFixup(sp->prev);
+ if ( sp->next!=NULL )
+ SplineRefigureFixup(sp->next);
+ } else {
+ SplineCharDefaultPrevCP(sp);
+ SplineCharDefaultNextCP(sp);
+ }
+ }
+ }
+}
+
+static void _CVMenuPointType(CharView *cv,struct gmenuitem *mi) {
+ int pointtype = mi->mid==MID_Corner?pt_corner:mi->mid==MID_Tangent?pt_tangent:pt_curve;
+ SplinePointList *spl;
+ Spline *spline, *first;
+
+ CVPreserveState(cv); /* We should only get here if there's a selection */
+ for ( spl = cv->layerheads[cv->drawmode]->splines; spl!=NULL ; spl = spl->next ) {
+ first = NULL;
+ if ( spl->first->selected ) {
+ if ( spl->first->pointtype!=pointtype )
+ SPChangePointType(spl->first,pointtype);
+ }
+ for ( spline=spl->first->next; spline!=NULL && spline!=first ; spline = spline->to->next ) {
+ if ( spline->to->selected ) {
+ if ( spline->to->pointtype!=pointtype )
+ SPChangePointType(spline->to,pointtype);
+ }
+ if ( first == NULL ) first = spline;
+ }
+ }
+ CVCharChangedUpdate(cv);
+}
+
+static void CVMenuPointType(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVMenuPointType(cv,mi);
+}
+
+static void _CVMenuImplicit(CharView *cv,struct gmenuitem *mi) {
+ SplinePointList *spl;
+ Spline *spline, *first;
+ int dontinterpolate = mi->mid==MID_NoImplicitPt;
+
+ if ( !cv->sc->parent->order2 )
+return;
+ CVPreserveState(cv); /* We should only get here if there's a selection */
+ for ( spl = cv->layerheads[cv->drawmode]->splines; spl!=NULL ; spl = spl->next ) {
+ first = NULL;
+ if ( spl->first->selected ) {
+ spl->first->dontinterpolate = dontinterpolate;
+ }
+ for ( spline=spl->first->next; spline!=NULL && spline!=first ; spline = spline->to->next ) {
+ if ( spline->to->selected ) {
+ spline->to->dontinterpolate = dontinterpolate;
+ }
+ if ( first == NULL ) first = spline;
+ }
+ }
+ SCNumberPoints(cv->sc);
+ CVCharChangedUpdate(cv);
+}
+
+static void CVMenuImplicit(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVMenuImplicit(cv,mi);
+}
+
+static void cv_ptlistcheck(CharView *cv,struct gmenuitem *mi,GEvent *e) {
+ int type = -2, cnt=0, ccp_cnt=0, spline_selected=0;
+ SplinePointList *spl, *sel=NULL;
+ Spline *spline, *first;
+ SplinePoint *selpt=NULL;
+ int notimplicit = -1;
+
+ for ( spl = cv->layerheads[cv->drawmode]->splines; spl!=NULL; spl = spl->next ) {
+ first = NULL;
+ if ( spl->first->selected ) {
+ sel = spl;
+ selpt = spl->first; ++cnt;
+ if ( type==-2 ) type = spl->first->pointtype;
+ else if ( type!=spl->first->pointtype ) type = -1;
+ if ( !spl->first->nonextcp && !spl->first->noprevcp && spl->first->prev!=NULL )
+ ++ccp_cnt;
+ if ( notimplicit==-1 ) notimplicit = spl->first->dontinterpolate;
+ else if ( notimplicit!=spl->first->dontinterpolate ) notimplicit = -2;
+ }
+ for ( spline=spl->first->next; spline!=NULL && spline!=first; spline = spline->to->next ) {
+ if ( spline->to->selected ) {
+ if ( type==-2 ) type = spline->to->pointtype;
+ else if ( type!=spline->to->pointtype ) type = -1;
+ selpt = spline->to;
+ sel = spl; ++cnt;
+ if ( !spline->to->nonextcp && !spline->to->noprevcp && spline->to->next!=NULL )
+ ++ccp_cnt;
+ if ( notimplicit==-1 ) notimplicit = spline->to->dontinterpolate;
+ else if ( notimplicit!=spline->to->dontinterpolate ) notimplicit = -2;
+ if ( spline->from->selected )
+ ++spline_selected;
+ }
+ if ( first == NULL ) first = spline;
+ }
+ }
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_Corner:
+ mi->ti.disabled = type==-2;
+ mi->ti.checked = type==pt_corner;
+ break;
+ case MID_Tangent:
+ mi->ti.disabled = type==-2;
+ mi->ti.checked = type==pt_tangent;
+ break;
+ case MID_Curve:
+ mi->ti.disabled = type==-2;
+ mi->ti.checked = type==pt_curve;
+ break;
+ case MID_MakeFirst:
+ mi->ti.disabled = cnt!=1 || sel->first->prev==NULL || sel->first==selpt;
+ break;
+ case MID_MakeLine:
+ mi->ti.disabled = cnt==0;
+ break;
+ case MID_InsertPtOnSplineAt:
+ mi->ti.disabled = spline_selected!=1;
+ break;
+ case MID_CenterCP:
+ mi->ti.disabled = ccp_cnt==0;
+ break;
+ case MID_ImplicitPt:
+ mi->ti.disabled = !cv->sc->parent->order2;
+ mi->ti.checked = notimplicit==0;
+ break;
+ case MID_NoImplicitPt:
+ mi->ti.disabled = !cv->sc->parent->order2;
+ mi->ti.checked = notimplicit==1;
+ break;
+#if 0
+ case MID_AddAnchor:
+ mi->ti.disabled = AnchorClassUnused(cv->sc,&waslig)==NULL;
+ break;
+#endif
+ }
+ }
+}
+
+static void ptlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ cv_ptlistcheck(cv,mi,e);
+}
+
+static void _CVMenuDir(CharView *cv,struct gmenuitem *mi) {
+ int splinepoints, dir;
+ SplinePointList *spl;
+ Spline *spline, *first;
+ int needsrefresh = false;
+
+ for ( spl = cv->layerheads[cv->drawmode]->splines; spl!=NULL; spl = spl->next ) {
+ first = NULL;
+ splinepoints = 0;
+ if ( spl->first->selected ) splinepoints = true;
+ for ( spline=spl->first->next; spline!=NULL && spline!=first && !splinepoints; spline = spline->to->next ) {
+ if ( spline->to->selected ) splinepoints = true;
+ if ( first == NULL ) first = spline;
+ }
+ if ( splinepoints && spl->first==spl->last && spl->first->next!=NULL ) {
+ dir = SplinePointListIsClockwise(spl);
+ if ( (mi->mid==MID_Clockwise && !dir) || (mi->mid==MID_Counter && dir)) {
+ if ( !needsrefresh )
+ CVPreserveState(cv);
+ SplineSetReverse(spl);
+ needsrefresh = true;
+ }
+ }
+ }
+ if ( needsrefresh )
+ CVCharChangedUpdate(cv);
+}
+
+static void CVMenuDir(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVMenuDir(cv,mi);
+}
+
+static int getorigin(void *d,BasePoint *base,int index) {
+ CharView *cv = (CharView *) d;
+
+ base->x = base->y = 0;
+ switch ( index ) {
+ case 0: /* Character origin */
+ /* all done */
+ break;
+ case 1: /* Center of selection */
+ CVFindCenter(cv,base,!CVAnySel(cv,NULL,NULL,NULL,NULL));
+ break;
+ case 2: /* last press */
+ base->x = cv->p.cx;
+ base->y = cv->p.cy;
+ /* I don't have any way of telling if a press has happened. if one */
+ /* hasn't they'll just get a 0,0 origin. oh well */
+ break;
+ default:
+return( false );
+ }
+return( true );
+}
+
+void BackgroundImageTransform(SplineChar *sc, ImageList *img,real transform[6]) {
+ if ( transform[1]==0 && transform[2]==0 && transform[0]>0 && transform[3]>0 ) {
+ img->xoff = transform[0]*img->xoff + transform[4];
+ img->yoff = transform[3]*img->yoff + transform[5];
+ if (( img->xscale *= transform[0])<0 ) img->xscale = -img->xscale;
+ if (( img->yscale *= transform[3])<0 ) img->yscale = -img->yscale;
+ img->bb.minx = img->xoff; img->bb.maxy = img->yoff;
+ img->bb.maxx = img->xoff + GImageGetWidth(img->image)*img->xscale;
+ img->bb.miny = img->yoff - GImageGetHeight(img->image)*img->yscale;
+ } else
+ /* Don't support rotating, flipping or skewing images */;
+ SCOutOfDateBackground(sc);
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+void CVTransFunc(CharView *cv,real transform[6], enum fvtrans_flags flags) {
+ int anysel = cv->p.transany;
+ RefChar *refs;
+ ImageList *img;
+ real t[6];
+ AnchorPoint *ap;
+ KernPair *kp;
+ PST *pst;
+ int j;
+
+ SplinePointListTransform(cv->layerheads[cv->drawmode]->splines,transform,!anysel);
+ if ( flags&fvt_round_to_int )
+ SplineSetsRound2Int(cv->layerheads[cv->drawmode]->splines,1.0);
+ if ( cv->layerheads[cv->drawmode]->images!=NULL ) {
+ ImageListTransform(cv->layerheads[cv->drawmode]->images,transform);
+ SCOutOfDateBackground(cv->sc);
+ }
+ if ( cv->drawmode==dm_fore ) {
+ for ( refs = cv->layerheads[cv->drawmode]->refs; refs!=NULL; refs=refs->next )
+ if ( refs->selected || !anysel ) {
+ for ( j=0; j<refs->layer_cnt; ++j )
+ SplinePointListTransform(refs->layers[j].splines,transform,true);
+ t[0] = refs->transform[0]*transform[0] +
+ refs->transform[1]*transform[2];
+ t[1] = refs->transform[0]*transform[1] +
+ refs->transform[1]*transform[3];
+ t[2] = refs->transform[2]*transform[0] +
+ refs->transform[3]*transform[2];
+ t[3] = refs->transform[2]*transform[1] +
+ refs->transform[3]*transform[3];
+ t[4] = refs->transform[4]*transform[0] +
+ refs->transform[5]*transform[2] +
+ transform[4];
+ t[5] = refs->transform[4]*transform[1] +
+ refs->transform[5]*transform[3] +
+ transform[5];
+ if ( flags&fvt_round_to_int ) {
+ t[4] = rint( t[4] );
+ t[5] = rint( t[5] );
+ }
+ memcpy(refs->transform,t,sizeof(t));
+ RefCharFindBounds(refs);
+ }
+ if ( cv->showanchor ) {
+ for ( ap=cv->sc->anchor; ap!=NULL; ap=ap->next ) if ( ap->selected || !anysel )
+ ApTransform(ap,transform);
+ }
+ if ( flags & fvt_scalepstpos ) {
+ for ( kp=cv->sc->kerns; kp!=NULL; kp=kp->next )
+ kp->off = rint(kp->off*transform[0]);
+ for ( kp=cv->sc->vkerns; kp!=NULL; kp=kp->next )
+ kp->off = rint(kp->off*transform[3]);
+ for ( pst = cv->sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->type == pst_position )
+ VrTrans(&pst->u.pos,transform);
+ else if ( pst->type==pst_pair ) {
+ VrTrans(&pst->u.pair.vr[0],transform);
+ VrTrans(&pst->u.pair.vr[1],transform);
+ }
+ }
+ }
+ if ( transform[1]==0 && transform[2]==0 ) {
+ TransHints(cv->sc->hstem,transform[3],transform[5],transform[0],transform[4],flags&fvt_round_to_int);
+ TransHints(cv->sc->vstem,transform[0],transform[4],transform[3],transform[5],flags&fvt_round_to_int);
+ }
+ if ( transform[0]==1 && transform[3]==1 && transform[1]==0 &&
+ transform[2]==0 && transform[5]==0 &&
+ transform[4]!=0 && CVAllSelected(cv) &&
+ cv->sc->unicodeenc!=-1 && isalpha(cv->sc->unicodeenc)) {
+ SCUndoSetLBearingChange(cv->sc,(int) rint(transform[4]));
+ SCSynchronizeLBearing(cv->sc,transform[4]);
+ }
+ if ( !(flags&fvt_dontmovewidth) && (cv->widthsel || !anysel))
+ if ( transform[0]>0 && transform[3]>0 && transform[1]==0 &&
+ transform[2]==0 && transform[4]!=0 )
+ SCSynchronizeWidth(cv->sc,cv->sc->width*transform[0]+transform[4],cv->sc->width,NULL);
+ if ( !(flags&fvt_dontmovewidth) && (cv->vwidthsel || !anysel))
+ if ( transform[0]==1 && transform[3]==1 && transform[1]==0 &&
+ transform[2]==0 && transform[5]!=0 )
+ cv->sc->vwidth+=transform[5];
+ if ( (flags&fvt_dobackground) && !anysel ) {
+ SCPreserveBackground(cv->sc);
+ for ( img = cv->sc->layers[ly_back].images; img!=NULL; img=img->next )
+ BackgroundImageTransform(cv->sc, img, transform);
+ SplinePointListTransform(cv->layerheads[cv->drawmode]->splines,
+ transform,true);
+ }
+ }
+}
+
+static void transfunc(void *d,real transform[6],int otype,BVTFunc *bvts,
+ enum fvtrans_flags flags) {
+ CharView *cv = (CharView *) d;
+ int anya;
+
+ cv->p.transany = CVAnySel(cv,NULL,NULL,NULL,&anya);
+ CVPreserveStateHints(cv);
+ if ( cv->drawmode==dm_fore && (flags&fvt_dobackground) )
+ SCPreserveBackground(cv->sc);
+ CVTransFunc(cv,transform,flags);
+ CVCharChangedUpdate(cv);
+}
+
+void CVDoTransform(CharView *cv, enum cvtools cvt ) {
+ int anysel = CVAnySel(cv,NULL,NULL,NULL,NULL);
+ TransformDlgCreate(cv,transfunc,getorigin,!anysel && cv->drawmode==dm_fore,
+ cvt);
+}
+
+static void CVMenuTransform(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVDoTransform(cv,cvt_none);
+}
+
+static void CVMenuPOV(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ struct pov_data pov_data;
+ if ( PointOfViewDlg(&pov_data,cv->sc->parent,true)==-1 )
+return;
+ CVPointOfView(cv,&pov_data);
+}
+
+static void CVMenuNLTransform(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ NonLinearDlg(NULL,cv);
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+static void SplinePointRound(SplinePoint *sp,real factor) {
+
+ sp->nextcp.x = rint(sp->nextcp.x*factor)/factor;
+ sp->nextcp.y = rint(sp->nextcp.y*factor)/factor;
+ if ( sp->next!=NULL && sp->next->order2 )
+ sp->next->to->prevcp = sp->nextcp;
+ sp->prevcp.x = rint(sp->prevcp.x*factor)/factor;
+ sp->prevcp.y = rint(sp->prevcp.y*factor)/factor;
+ if ( sp->prev!=NULL && sp->prev->order2 )
+ sp->prev->from->nextcp = sp->prevcp;
+ if ( sp->prev!=NULL && sp->next!=NULL && sp->next->order2 &&
+ sp->ttfindex == 0xffff ) {
+ sp->me.x = (sp->nextcp.x + sp->prevcp.x)/2;
+ sp->me.y = (sp->nextcp.y + sp->prevcp.y)/2;
+ } else {
+ sp->me.x = rint(sp->me.x*factor)/factor;
+ sp->me.y = rint(sp->me.y*factor)/factor;
+ }
+}
+
+void SplineSetsRound2Int(SplineSet *spl,real factor) {
+ SplinePoint *sp;
+
+ for ( ; spl!=NULL; spl=spl->next ) {
+ for ( sp=spl->first; ; ) {
+ SplinePointRound(sp,factor);
+ if ( sp->prev!=NULL )
+ SplineRefigure(sp->prev);
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ if ( spl->first->prev!=NULL )
+ SplineRefigure(spl->first->prev);
+ }
+}
+
+static void SplineSetsChangeCoord(SplineSet *spl,real old, real new,int isy) {
+ SplinePoint *sp;
+
+ for ( ; spl!=NULL; spl=spl->next ) {
+ for ( sp=spl->first; ; ) {
+ if ( isy ) {
+ if ( RealNear(sp->me.y,old) ) {
+ if ( RealNear(sp->nextcp.y,old))
+ sp->nextcp.y = new;
+ else
+ sp->nextcp.y += new-sp->me.y;
+ if ( RealNear(sp->prevcp.y,old))
+ sp->prevcp.y = new;
+ else
+ sp->prevcp.y += new-sp->me.y;
+ sp->me.y = new;
+ /* we expect to be called before SplineSetRound2Int and will */
+ /* allow it to do any SplineRefigures */
+ }
+ } else {
+ if ( RealNear(sp->me.x,old) ) {
+ if ( RealNear(sp->nextcp.x,old))
+ sp->nextcp.x = new;
+ else
+ sp->nextcp.x += new-sp->me.x;
+ if ( RealNear(sp->prevcp.x,old))
+ sp->prevcp.x = new;
+ else
+ sp->prevcp.x += new-sp->me.x;
+ sp->me.x = new;
+ }
+ }
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ if ( spl->first->prev!=NULL )
+ SplineRefigure(spl->first->prev);
+ }
+}
+
+void SCRound2Int(SplineChar *sc,real factor) {
+ RefChar *r;
+ StemInfo *stems;
+ real old, new;
+ int layer;
+
+ for ( stems = sc->hstem; stems!=NULL; stems=stems->next ) {
+ old = stems->start+stems->width;
+ stems->start = rint(stems->start*factor)/factor;
+ stems->width = rint(stems->width*factor)/factor;
+ new = stems->start+stems->width;
+ if ( old!=new )
+ SplineSetsChangeCoord(sc->layers[ly_fore].splines,old,new,true);
+ }
+ for ( stems = sc->vstem; stems!=NULL; stems=stems->next ) {
+ old = stems->start+stems->width;
+ stems->start = rint(stems->start*factor)/factor;
+ stems->width = rint(stems->width*factor)/factor;
+ new = stems->start+stems->width;
+ if ( old!=new )
+ SplineSetsChangeCoord(sc->layers[ly_fore].splines,old,new,false);
+ }
+
+ for ( layer = ly_fore; layer<sc->layer_cnt; ++layer ) {
+ SplineSetsRound2Int(sc->layers[layer].splines,factor);
+ for ( r=sc->layers[layer].refs; r!=NULL; r=r->next ) {
+ r->transform[4] = rint(r->transform[4]*factor)/factor;
+ r->transform[5] = rint(r->transform[5]*factor)/factor;
+ RefCharFindBounds(r);
+ }
+ }
+ SCCharChangedUpdate(sc);
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static void CVMenuConstrain(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVConstrainSelection(cv,mi->mid==MID_Average?0:
+ mi->mid==MID_SpacePts?1:
+ 2);
+}
+
+static void CVMenuMakeParallel(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVMakeParallel(cv);
+}
+
+static void _CVMenuRound2Int(CharView *cv, double factor) {
+ int anysel = CVAnySel(cv,NULL,NULL,NULL,NULL);
+ SplinePointList *spl;
+ SplinePoint *sp;
+ RefChar *r;
+
+ CVPreserveState(cv);
+ for ( spl= cv->layerheads[cv->drawmode]->splines; spl!=NULL; spl=spl->next ) {
+ for ( sp=spl->first; ; ) {
+ if ( sp->selected || !anysel )
+ SplinePointRound(sp,factor);
+ if ( sp->prev!=NULL )
+ SplineRefigure(sp->prev);
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ if ( spl->first->prev!=NULL )
+ SplineRefigure(spl->first->prev);
+ }
+ if ( cv->drawmode==dm_fore ) {
+ for ( r=cv->sc->layers[ly_fore].refs; r!=NULL; r=r->next ) {
+ if ( r->selected || !anysel ) {
+ r->transform[4] = rint(r->transform[4]*factor)/factor;
+ r->transform[5] = rint(r->transform[5]*factor)/factor;
+ }
+ }
+ }
+ CVCharChangedUpdate(cv);
+}
+
+static void CVMenuRound2Int(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVMenuRound2Int(cv,1.0);
+}
+
+static void CVMenuRound2Hundredths(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVMenuRound2Int(cv,100.0);
+}
+
+static void CVMenuCluster(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ int layer = cv->drawmode == dm_grid ? -1 :
+ cv->drawmode == dm_back ? 0
+ : cv->layerheads[dm_fore] - cv->sc->layers;
+ SCRoundToCluster(cv->sc,layer,true,.1,.5);
+}
+
+static void CVMenuStroke(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVStroke(cv);
+}
+
+#ifdef FONTFORGE_CONFIG_TILEPATH
+static void CVMenuTilePath(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVTile(cv);
+}
+#endif
+
+static void _CVMenuOverlap(CharView *cv,enum overlap_type ot) {
+ /* We know it's more likely that we'll find a problem in the overlap code */
+ /* than anywhere else, so let's save the current state against a crash */
+ int layer = cv->drawmode == dm_grid ? -1 :
+ cv->drawmode == dm_back ? 0
+ : cv->layerheads[dm_fore] - cv->sc->layers;
+
+ DoAutoSaves();
+ if ( !SCRoundToCluster(cv->sc,layer,false,.03,.12))
+ CVPreserveState(cv); /* SCRound2Cluster does this when it makes a change, not otherwise */
+ if ( cv->drawmode==dm_fore ) {
+ MinimumDistancesFree(cv->sc->md);
+ cv->sc->md = NULL;
+ }
+ cv->layerheads[cv->drawmode]->splines = SplineSetRemoveOverlap(cv->sc,cv->layerheads[cv->drawmode]->splines,ot);
+ CVCharChangedUpdate(cv);
+}
+
+static void CVMenuOverlap(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ int anysel;
+
+ (void) CVAnySel(cv,&anysel,NULL,NULL,NULL);
+ _CVMenuOverlap(cv,mi->mid==MID_RmOverlap ? (anysel ? over_rmselected: over_remove) :
+ mi->mid==MID_Intersection ? (anysel ? over_intersel : over_intersect ) :
+ mi->mid==MID_Exclude ? over_exclude :
+ (anysel ? over_fisel : over_findinter));
+}
+
+static void CVMenuOrder(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SplinePointList *spl;
+ RefChar *r;
+ ImageList *im;
+ int exactlyone = CVOneContourSel(cv,&spl,&r,&im);
+
+ if ( !exactlyone )
+return;
+
+ CVPreserveState(cv);
+ if ( spl!=NULL ) {
+ SplinePointList *p, *pp, *t;
+ p = pp = NULL;
+ for ( t=cv->layerheads[cv->drawmode]->splines; t!=NULL && t!=spl; t=t->next ) {
+ pp = p; p = t;
+ }
+ switch ( mi->mid ) {
+ case MID_First:
+ if ( p!=NULL ) {
+ p->next = spl->next;
+ spl->next = cv->layerheads[cv->drawmode]->splines;
+ cv->layerheads[cv->drawmode]->splines = spl;
+ }
+ break;
+ case MID_Earlier:
+ if ( p!=NULL ) {
+ p->next = spl->next;
+ spl->next = p;
+ if ( pp==NULL ) {
+ cv->layerheads[cv->drawmode]->splines = spl;
+ } else {
+ pp->next = spl;
+ }
+ }
+ break;
+ case MID_Last:
+ if ( spl->next!=NULL ) {
+ for ( t=cv->layerheads[cv->drawmode]->splines; t->next!=NULL; t=t->next );
+ t->next = spl;
+ if ( p==NULL )
+ cv->layerheads[cv->drawmode]->splines = spl->next;
+ else
+ p->next = spl->next;
+ spl->next = NULL;
+ }
+ break;
+ case MID_Later:
+ if ( spl->next!=NULL ) {
+ t = spl->next;
+ spl->next = t->next;
+ t->next = spl;
+ if ( p==NULL )
+ cv->layerheads[cv->drawmode]->splines = t;
+ else
+ p->next = t;
+ }
+ break;
+ }
+ } else if ( r!=NULL ) {
+ RefChar *p, *pp, *t;
+ p = pp = NULL;
+ for ( t=cv->sc->layers[ly_fore].refs; t!=NULL && t!=r; t=t->next ) {
+ pp = p; p = t;
+ }
+ switch ( mi->mid ) {
+ case MID_First:
+ if ( p!=NULL ) {
+ p->next = r->next;
+ r->next = cv->sc->layers[ly_fore].refs;
+ cv->sc->layers[ly_fore].refs = r;
+ }
+ break;
+ case MID_Earlier:
+ if ( p!=NULL ) {
+ p->next = r->next;
+ r->next = p;
+ if ( pp==NULL ) {
+ cv->sc->layers[ly_fore].refs = r;
+ } else {
+ pp->next = r;
+ }
+ }
+ break;
+ case MID_Last:
+ if ( r->next!=NULL ) {
+ for ( t=cv->sc->layers[ly_fore].refs; t->next!=NULL; t=t->next );
+ t->next = r;
+ if ( p==NULL )
+ cv->sc->layers[ly_fore].refs = r->next;
+ else
+ p->next = r->next;
+ r->next = NULL;
+ }
+ break;
+ case MID_Later:
+ if ( r->next!=NULL ) {
+ t = r->next;
+ r->next = t->next;
+ t->next = r;
+ if ( p==NULL )
+ cv->sc->layers[ly_fore].refs = t;
+ else
+ p->next = t;
+ }
+ break;
+ }
+ } else if ( im!=NULL ) {
+ ImageList *p, *pp, *t;
+ p = pp = NULL;
+ for ( t=cv->layerheads[cv->drawmode]->images; t!=NULL && t!=im; t=t->next ) {
+ pp = p; p = t;
+ }
+ switch ( mi->mid ) {
+ case MID_First:
+ if ( p!=NULL ) {
+ p->next = im->next;
+ im->next = cv->layerheads[cv->drawmode]->images;
+ cv->layerheads[cv->drawmode]->images = im;
+ }
+ break;
+ case MID_Earlier:
+ if ( p!=NULL ) {
+ p->next = im->next;
+ im->next = p;
+ if ( pp==NULL ) {
+ cv->layerheads[cv->drawmode]->images = im;
+ } else {
+ pp->next = im;
+ }
+ }
+ break;
+ case MID_Last:
+ if ( im->next!=NULL ) {
+ for ( t=cv->layerheads[cv->drawmode]->images; t->next!=NULL; t=t->next );
+ t->next = im;
+ if ( p==NULL )
+ cv->layerheads[cv->drawmode]->images = im->next;
+ else
+ p->next = im->next;
+ im->next = NULL;
+ }
+ break;
+ case MID_Later:
+ if ( im->next!=NULL ) {
+ t = im->next;
+ im->next = t->next;
+ t->next = im;
+ if ( p==NULL )
+ cv->layerheads[cv->drawmode]->images = t;
+ else
+ p->next = t;
+ }
+ break;
+ }
+ }
+ CVCharChangedUpdate(cv);
+}
+
+static void _CVMenuAddExtrema(CharView *cv) {
+ int anysel;
+ SplineFont *sf = cv->sc->parent;
+
+ (void) CVAnySel(cv,&anysel,NULL,NULL,NULL);
+ CVPreserveState(cv);
+ SplineCharAddExtrema(cv->sc,cv->layerheads[cv->drawmode]->splines,
+ anysel?ae_between_selected:ae_only_good,sf->ascent+sf->descent);
+ CVCharChangedUpdate(cv);
+}
+
+static void CVMenuAddExtrema(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVMenuAddExtrema(cv);
+}
+
+static void CVSimplify(CharView *cv,int type) {
+ static struct simplifyinfo smpls[] = {
+ { sf_normal },
+ { sf_normal,.75,.05,0,-1 },
+ { sf_normal,.75,.05,0,-1 }};
+ struct simplifyinfo *smpl = &smpls[type+1];
+
+ if ( smpl->linelenmax==-1 || (type==0 && !smpl->set_as_default)) {
+ smpl->err = (cv->sc->parent->ascent+cv->sc->parent->descent)/1000.;
+ smpl->linelenmax = (cv->sc->parent->ascent+cv->sc->parent->descent)/100.;
+ }
+
+ if ( type==1 ) {
+ if ( !SimplifyDlg(cv->sc->parent,smpl))
+return;
+ if ( smpl->set_as_default )
+ smpls[1] = *smpl;
+ }
+
+ CVPreserveState(cv);
+ smpl->check_selected_contours = true;
+ cv->layerheads[cv->drawmode]->splines = SplineCharSimplify(cv->sc,cv->layerheads[cv->drawmode]->splines,
+ smpl);
+ CVCharChangedUpdate(cv);
+}
+
+static void CVMenuSimplify(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVSimplify(cv,0);
+}
+
+static void CVMenuSimplifyMore(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVSimplify(cv,1);
+}
+
+static void CVMenuCleanupGlyph(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVSimplify(cv,-1);
+}
+
+static int SPLSelected(SplineSet *ss) {
+ SplinePoint *sp;
+
+ for ( sp=ss->first ;; ) {
+ if ( sp->selected )
+return( true );
+ if ( sp->next==NULL )
+return( false );
+ sp = sp->next->to;
+ if ( sp==ss->first )
+return( false );
+ }
+}
+
+static void CVCanonicalStart(CharView *cv) {
+ SplineSet *ss;
+ int changed = 0;
+
+ for ( ss = cv->layerheads[cv->drawmode]->splines; ss!=NULL; ss=ss->next )
+ if ( ss->first==ss->last && SPLSelected(ss))
+ SPLStartToLeftmost(cv->sc,ss,&changed);
+}
+
+static void CVMenuCanonicalStart(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVCanonicalStart(cv);
+}
+
+static void CVCanonicalContour(CharView *cv) {
+ if ( cv->drawmode==dm_fore )
+ CanonicalContours(cv->sc);
+}
+
+static void CVMenuCanonicalContours(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVCanonicalContour(cv);
+}
+
+static void _CVMenuMakeFirst(CharView *cv) {
+ SplinePoint *selpt = NULL;
+ int anypoints = 0, splinepoints;
+ SplinePointList *spl, *sel;
+ Spline *spline, *first;
+
+ sel = NULL;
+ for ( spl = cv->layerheads[cv->drawmode]->splines; spl!=NULL; spl = spl->next ) {
+ first = NULL;
+ splinepoints = 0;
+ if ( spl->first->selected ) { splinepoints = 1; sel = spl; selpt=spl->first; }
+ for ( spline=spl->first->next; spline!=NULL && spline!=first && !splinepoints; spline = spline->to->next ) {
+ if ( spline->to->selected ) { ++splinepoints; sel = spl; selpt=spline->to; }
+ if ( first == NULL ) first = spline;
+ }
+ anypoints += splinepoints;
+ }
+
+ if ( anypoints!=1 || sel->first->prev==NULL || sel->first==selpt )
+return;
+
+ CVPreserveState(cv);
+ sel->first = sel->last = selpt;
+ CVCharChangedUpdate(cv);
+}
+
+static void CVMenuMakeFirst(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVMenuMakeFirst(cv);
+}
+
+static void _CVMenuMakeLine(CharView *cv) {
+ SplinePointList *spl;
+ SplinePoint *sp;
+ int changed = false;
+
+ for ( spl = cv->layerheads[cv->drawmode]->splines; spl!=NULL; spl = spl->next ) {
+ for ( sp=spl->first; ; ) {
+ if ( sp->selected ) {
+ int any = false;
+ if ( !changed ) {
+ CVPreserveState(cv);
+ changed = true;
+ }
+ if ( sp->prev!=NULL && sp->prev->from->selected ) {
+ any = true;
+ sp->prevcp = sp->me;
+ sp->noprevcp = true;
+ sp->prev->from->nextcp = sp->prev->from->me;
+ sp->prev->from->nonextcp = true;
+ SplineRefigure(sp->prev);
+ }
+ if ( sp->next!=NULL && sp->next->to->selected ) {
+ any = true;
+ sp->nextcp = sp->me;
+ sp->nonextcp = true;
+ sp->next->to->prevcp = sp->next->to->me;
+ sp->next->to->noprevcp = true;
+ SplineRefigure(sp->next);
+ }
+ if ( !any ) {
+ sp->nextcp = sp->me;
+ sp->prevcp = sp->me;
+ sp->nonextcp = sp->noprevcp = true;
+ if ( sp->prev!=NULL ) SplineRefigure(sp->prev);
+ if ( sp->next!=NULL ) SplineRefigure(sp->next);
+ }
+ changed = true;
+ }
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ }
+
+ if ( changed )
+ CVCharChangedUpdate(cv);
+}
+
+static void CVMenuMakeLine(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVMenuMakeLine(cv);
+}
+
+struct insertonsplineat {
+ int done;
+ GWindow gw;
+ Spline *s;
+ CharView *cv;
+};
+
+#define CID_X 1001
+#define CID_Y 1002
+#define CID_XR 1003
+#define CID_YR 1004
+
+static int IOSA_OK(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ int err = false;
+ struct insertonsplineat *iosa = GDrawGetUserData(GGadgetGetWindow(g));
+ double val;
+ extended ts[3];
+ int which;
+ SplinePoint *sp;
+
+ if ( GGadgetIsChecked(GWidgetGetControl(iosa->gw,CID_XR)) ) {
+ val = GetReal8(iosa->gw,CID_X,"X",&err);
+ which = 0;
+ } else {
+ val = GetReal8(iosa->gw,CID_Y,"Y",&err);
+ which = 1;
+ }
+ if ( err )
+return(true);
+ if ( SplineSolveFull(&iosa->s->splines[which],val,ts)==0 ) {
+ gwwv_post_error(_("Out of Range"),_("The spline does not reach %g"), (double) val );
+return( true );
+ }
+ iosa->done = true;
+ CVPreserveState(iosa->cv);
+ forever {
+ sp = SplineBisect(iosa->s,ts[0]);
+ SplinePointCatagorize(sp);
+ if ( which==0 ) {
+ double off = val-sp->me.x;
+ sp->me.x = val; sp->nextcp.x += off; sp->prevcp.x += off;
+ } else {
+ double off = val-sp->me.y;
+ sp->me.y = val; sp->nextcp.y += off; sp->prevcp.y += off;
+ }
+ SplineRefigure(sp->prev); SplineRefigure(sp->next);
+ if ( ts[1]==-1 ) {
+ CVCharChangedUpdate(iosa->cv);
+return( true );
+ }
+ iosa->s = sp->next;
+ if ( SplineSolveFull(&iosa->s->splines[which],val,ts)==0 ) {
+ /* Odd. We found one earlier */
+ CVCharChangedUpdate(iosa->cv);
+return( true );
+ }
+ }
+ }
+return( true );
+}
+
+static int IOSA_Cancel(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct insertonsplineat *iosa = GDrawGetUserData(GGadgetGetWindow(g));
+ iosa->done = true;
+ }
+return( true );
+}
+
+static int IOSA_FocusChange(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_textfocuschanged ) {
+ struct insertonsplineat *iosa = GDrawGetUserData(GGadgetGetWindow(g));
+ int cid = (intpt) GGadgetGetUserData(g);
+ GGadgetSetChecked(GWidgetGetControl(iosa->gw,cid),true);
+ }
+return( true );
+}
+
+static int IOSA_RadioChange(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
+ struct insertonsplineat *iosa = GDrawGetUserData(GGadgetGetWindow(g));
+ int cid = (intpt) GGadgetGetUserData(g);
+ GWidgetIndicateFocusGadget(GWidgetGetControl(iosa->gw,cid));
+ GTextFieldSelect(GWidgetGetControl(iosa->gw,cid),0,-1);
+ }
+return( true );
+}
+
+static int iosa_e_h(GWindow gw, GEvent *event) {
+ if ( event->type==et_close ) {
+ struct insertonsplineat *iosa = GDrawGetUserData(gw);
+ iosa->done = true;
+ } else if ( event->type == et_char ) {
+return( false );
+ } else if ( event->type == et_map ) {
+ /* Above palettes */
+ GDrawRaise(gw);
+ }
+return( true );
+}
+
+static void _CVMenuInsertPt(CharView *cv) {
+ SplineSet *spl;
+ Spline *s, *found=NULL, *first;
+ struct insertonsplineat iosa;
+ GRect pos;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[11], boxes[2], topbox[2], *hvs[13], *varray[8], *buttons[6];
+ GTextInfo label[11];
+
+ for ( spl = cv->layerheads[cv->drawmode]->splines; spl!=NULL; spl = spl->next ) {
+ first = NULL;
+ for ( s=spl->first->next; s!=NULL && s!=first ; s = s->to->next ) {
+ if ( first==NULL ) first=s;
+ if ( s->from->selected && s->to->selected ) {
+ if ( found!=NULL )
+return; /* Can only work with one spline */
+ found = s;
+ }
+ }
+ }
+ if ( found==NULL )
+return; /* Need a spline */
+
+ memset(&iosa,0,sizeof(iosa));
+ iosa.s = found;
+ iosa.cv = cv;
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Insert a point on the given spline at either...");
+ wattrs.is_dlg = true;
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,210));
+ pos.height = GDrawPointsToPixels(NULL,120);
+ iosa.gw = GDrawCreateTopWindow(NULL,&pos,iosa_e_h,&iosa,&wattrs);
+
+ memset(&label,0,sizeof(label));
+ memset(&gcd,0,sizeof(gcd));
+
+ label[0].text = (unichar_t *) _("_X:");
+ label[0].text_is_1byte = true;
+ label[0].text_in_resource = true;
+ gcd[0].gd.label = &label[0];
+ gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 5;
+ gcd[0].gd.flags = gg_enabled|gg_visible|gg_cb_on;
+ gcd[0].gd.cid = CID_XR;
+ gcd[0].gd.handle_controlevent = IOSA_RadioChange;
+ gcd[0].data = (void *) CID_X;
+ gcd[0].creator = GRadioCreate;
+
+ label[1].text = (unichar_t *) _("_Y:");
+ label[1].text_is_1byte = true;
+ label[1].text_in_resource = true;
+ gcd[1].gd.label = &label[1];
+ gcd[1].gd.pos.x = 5; gcd[1].gd.pos.y = 32;
+ gcd[1].gd.flags = gg_enabled|gg_visible|gg_rad_continueold ;
+ gcd[1].gd.cid = CID_YR;
+ gcd[1].gd.handle_controlevent = IOSA_RadioChange;
+ gcd[1].data = (void *) CID_Y;
+ gcd[1].creator = GRadioCreate;
+
+ gcd[2].gd.pos.x = 131; gcd[2].gd.pos.y = 5; gcd[2].gd.pos.width = 60;
+ gcd[2].gd.flags = gg_enabled|gg_visible;
+ gcd[2].gd.cid = CID_X;
+ gcd[2].gd.handle_controlevent = IOSA_FocusChange;
+ gcd[2].data = (void *) CID_XR;
+ gcd[2].creator = GTextFieldCreate;
+
+ gcd[3].gd.pos.x = 131; gcd[3].gd.pos.y = 32; gcd[3].gd.pos.width = 60;
+ gcd[3].gd.flags = gg_enabled|gg_visible;
+ gcd[3].gd.cid = CID_Y;
+ gcd[3].gd.handle_controlevent = IOSA_FocusChange;
+ gcd[3].data = (void *) CID_YR;
+ gcd[3].creator = GTextFieldCreate;
+
+ gcd[4].gd.pos.x = 20-3; gcd[4].gd.pos.y = 120-32-3;
+ gcd[4].gd.pos.width = -1; gcd[4].gd.pos.height = 0;
+ gcd[4].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[4].text = (unichar_t *) _("_OK");
+ label[4].text_is_1byte = true;
+ label[4].text_in_resource = true;
+ gcd[4].gd.mnemonic = 'O';
+ gcd[4].gd.label = &label[4];
+ gcd[4].gd.handle_controlevent = IOSA_OK;
+ gcd[4].creator = GButtonCreate;
+
+ gcd[5].gd.pos.x = -20; gcd[5].gd.pos.y = 120-32;
+ gcd[5].gd.pos.width = -1; gcd[5].gd.pos.height = 0;
+ gcd[5].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[5].text = (unichar_t *) _("_Cancel");
+ label[5].text_is_1byte = true;
+ label[5].text_in_resource = true;
+ gcd[5].gd.label = &label[5];
+ gcd[5].gd.mnemonic = 'C';
+ gcd[5].gd.handle_controlevent = IOSA_Cancel;
+ gcd[5].creator = GButtonCreate;
+
+ hvs[0] = &gcd[0]; hvs[1] = &gcd[2]; hvs[2] = NULL;
+ hvs[3] = &gcd[1]; hvs[4] = &gcd[3]; hvs[5] = NULL;
+ hvs[6] = NULL;
+
+ buttons[0] = buttons[2] = buttons[4] = GCD_Glue; buttons[5] = NULL;
+ buttons[1] = &gcd[4]; buttons[3] = &gcd[5];
+
+ varray[0] = &boxes[1]; varray[1] = NULL;
+ varray[2] = GCD_Glue; varray[3] = NULL;
+ varray[4] = &boxes[0]; varray[5] = NULL;
+ varray[6] = NULL;
+
+ memset(boxes,0,sizeof(boxes));
+ boxes[0].gd.flags = gg_enabled|gg_visible;
+ boxes[0].gd.u.boxelements = buttons;
+ boxes[0].creator = GHBoxCreate;
+
+ boxes[1].gd.flags = gg_enabled|gg_visible;
+ boxes[1].gd.u.boxelements = hvs;
+ boxes[1].creator = GHVBoxCreate;
+
+ memset(topbox,0,sizeof(topbox));
+ topbox[0].gd.pos.x = topbox[0].gd.pos.y = 2;
+ topbox[0].gd.pos.width = pos.width-4; topbox[0].gd.pos.height = pos.height-4;
+ topbox[0].gd.flags = gg_enabled|gg_visible;
+ topbox[0].gd.u.boxelements = varray;
+ topbox[0].creator = GHVGroupCreate;
+
+
+ GGadgetsCreate(iosa.gw,topbox);
+ GHVBoxSetExpandableRow(topbox[0].ret,1);
+ GHVBoxSetExpandableCol(boxes[0].ret,gb_expandgluesame);
+ GHVBoxSetExpandableCol(boxes[1].ret,1);
+ GWidgetIndicateFocusGadget(GWidgetGetControl(iosa.gw,CID_X));
+ GTextFieldSelect(GWidgetGetControl(iosa.gw,CID_X),0,-1);
+ GHVBoxFitWindow(topbox[0].ret);
+
+ GDrawSetVisible(iosa.gw,true);
+ while ( !iosa.done )
+ GDrawProcessOneEvent(NULL);
+ GDrawDestroyWindow(iosa.gw);
+}
+
+static void CVMenuInsertPt(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVMenuInsertPt(cv);
+}
+
+static void _CVCenterCP(CharView *cv) {
+ SplinePointList *spl;
+ SplinePoint *sp;
+ int changed = false;
+ enum movething { mt_pt, mt_ncp, mt_pcp } movething = mt_pt;
+
+ for ( spl = cv->layerheads[cv->drawmode]->splines; spl!=NULL; spl = spl->next ) {
+ for ( sp=spl->first; ; ) {
+ if ( sp->selected && sp->prev!=NULL && sp->next!=NULL &&
+ !sp->noprevcp && !sp->nonextcp ) {
+ if ( sp->me.x != (sp->nextcp.x+sp->prevcp.x)/2 ||
+ sp->me.y != (sp->nextcp.y+sp->prevcp.y)/2 ) {
+ if ( !changed ) {
+ CVPreserveState(cv);
+ changed = true;
+ }
+ switch ( movething ) {
+ case mt_pt:
+ sp->me.x = (sp->nextcp.x+sp->prevcp.x)/2;
+ sp->me.y = (sp->nextcp.y+sp->prevcp.y)/2;
+ SplineRefigure(sp->prev);
+ SplineRefigure(sp->next);
+ break;
+ case mt_ncp:
+ sp->nextcp.x = sp->me.x - (sp->prevcp.x-sp->me.x);
+ sp->nextcp.y = sp->me.y - (sp->prevcp.y-sp->me.y);
+ if ( sp->next->order2 ) {
+ sp->next->to->prevcp = sp->nextcp;
+ sp->next->to->noprevcp = false;
+ }
+ SplineRefigure(sp->prev);
+ SplineRefigureFixup(sp->next);
+ break;
+ case mt_pcp:
+ sp->prevcp.x = sp->me.x - (sp->nextcp.x-sp->me.x);
+ sp->prevcp.y = sp->me.y - (sp->nextcp.y-sp->me.y);
+ if ( sp->prev->order2 ) {
+ sp->prev->from->nextcp = sp->prevcp;
+ sp->prev->from->nonextcp = false;
+ }
+ SplineRefigureFixup(sp->prev);
+ SplineRefigure(sp->next);
+ break;
+ }
+ }
+ }
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ }
+
+ if ( changed )
+ CVCharChangedUpdate(cv);
+}
+
+static void CVMenuCenterCP(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ _CVCenterCP(cv);
+}
+
+void CVAddAnchor(CharView *cv) {
+ int waslig;
+
+ if ( AnchorClassUnused(cv->sc,&waslig)==NULL ) {
+ ff_post_notice(_("Make a new anchor class"),_("I cannot find an unused anchor class\nto assign a new point to. If you\nwish a new anchor point you must\ndefine a new anchor class with\nElement->Font Info"));
+ FontInfo(cv->sc->parent,11,true); /* Lookups */
+ if ( AnchorClassUnused(cv->sc,&waslig)==NULL )
+return;
+ }
+ ApGetInfo(cv,NULL);
+}
+
+static void CVMenuAddAnchor(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ CVAddAnchor(cv);
+}
+
+static void CVMenuAutotrace(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SCAutoTrace(cv->sc,cv->v,e!=NULL && (e->u.mouse.state&ksm_shift));
+}
+
+static void CVMenuBuildAccent(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ extern int onlycopydisplayed;
+
+ if ( SFIsRotatable(cv->fv->sf,cv->sc))
+ /* It's ok */;
+ else if ( !SFIsSomethingBuildable(cv->fv->sf,cv->sc,true) )
+return;
+ SCBuildComposit(cv->fv->sf,cv->sc,!onlycopydisplayed,cv->fv);
+}
+
+static void CVMenuBuildComposite(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ extern int onlycopydisplayed;
+
+ if ( SFIsRotatable(cv->fv->sf,cv->sc))
+ /* It's ok */;
+ else if ( !SFIsCompositBuildable(cv->fv->sf,cv->sc->unicodeenc,cv->sc) )
+return;
+ SCBuildComposit(cv->fv->sf,cv->sc,!onlycopydisplayed,cv->fv);
+}
+
+static void CVMenuCorrectDir(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ int changed=false, refchanged=false;
+ RefChar *ref;
+ int asked=-1;
+
+ if ( cv->drawmode==dm_fore ) for ( ref=cv->sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
+ if ( ref->transform[0]*ref->transform[3]<0 ||
+ (ref->transform[0]==0 && ref->transform[1]*ref->transform[2]>0)) {
+ if ( asked==-1 ) {
+ char *buts[4];
+ buts[0] = _("_Unlink");
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ buts[1] = _("_No");
+ buts[2] = _("_Cancel");
+#elif defined(FONTFORGE_CONFIG_GTK)
+ buts[1] = GTK_STOCK_NO;
+ buts[2] = GTK_STOCK_CANCEL;
+#endif
+ buts[3] = NULL;
+ asked = gwwv_ask(_("Flipped Reference"),(const char **) buts,0,2,_("%.50s contains a flipped reference. This cannot be corrected as is. Would you like me to unlink it and then correct it?"), cv->sc->name );
+ if ( asked==2 )
+return;
+ else if ( asked==1 )
+ break;
+ }
+ if ( asked==0 ) {
+ if ( !refchanged ) {
+ refchanged = true;
+ CVPreserveState(cv);
+ }
+ SCRefToSplines(cv->sc,ref);
+ }
+ }
+ }
+
+ if ( !refchanged )
+ CVPreserveState(cv);
+
+ cv->layerheads[cv->drawmode]->splines = SplineSetsCorrect(cv->layerheads[cv->drawmode]->splines,&changed);
+ if ( changed || refchanged )
+ CVCharChangedUpdate(cv);
+}
+
+static void CVMenuGetInfo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ CVGetInfo(cv);
+}
+
+static void CVMenuCharInfo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SCCharInfo(cv->sc,cv->fv->map,CVCurEnc(cv));
+}
+
+static void CVMenuShowDependentRefs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SCRefBy(cv->sc);
+}
+
+static void CVMenuShowDependentSubs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SCSubBy(cv->sc);
+}
+
+static void CVMenuBitmaps(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ BitmapDlg(cv->fv,cv->sc,mi->mid==MID_RemoveBitmaps?-1: (mi->mid==MID_AvailBitmaps) );
+}
+
+static void cv_allistcheck(CharView *cv,struct gmenuitem *mi,GEvent *e) {
+ int selpoints = 0;
+ SplinePointList *spl;
+ SplinePoint *sp=NULL;
+
+ for ( spl = cv->layerheads[cv->drawmode]->splines; spl!=NULL; spl = spl->next ) {
+ sp=spl->first;
+ while ( 1 ) {
+ if ( sp->selected )
+ ++selpoints;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ }
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_Average:
+ mi->ti.disabled = selpoints<2;
+ break;
+ case MID_SpacePts:
+ mi->ti.disabled = ((selpoints<3) && (selpoints!=1));
+ break;
+ case MID_SpaceRegion:
+ mi->ti.disabled = selpoints<3;
+ break;
+ case MID_MakeParallel:
+ mi->ti.disabled = selpoints!=4;
+ break;
+ }
+ }
+}
+
+static void allistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ cv_allistcheck(cv,mi,e);
+}
+
+static void cv_balistcheck(CharView *cv,struct gmenuitem *mi,GEvent *e) {
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_BuildAccent:
+ mi->ti.disabled = !SFIsSomethingBuildable(cv->fv->sf,cv->sc,true);
+ break;
+ case MID_BuildComposite:
+ mi->ti.disabled = !SFIsSomethingBuildable(cv->fv->sf,cv->sc,false);
+ break;
+ }
+ }
+}
+
+static void balistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ cv_balistcheck(cv,mi,e);
+}
+
+static void delistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_ShowDependentRefs:
+ mi->ti.disabled = cv->sc->dependents==NULL;
+ break;
+ case MID_ShowDependentSubs:
+ mi->ti.disabled = !SCUsedBySubs(cv->sc);
+ break;
+ }
+ }
+}
+
+static void cv_ellistcheck(CharView *cv,struct gmenuitem *mi,GEvent *e,int is_cv) {
+ int anypoints = 0, splinepoints, dir = -2;
+ SplinePointList *spl;
+ Spline *spline, *first;
+ AnchorPoint *ap;
+ int order2 = cv->sc->parent->order2;
+
+#ifdef FONTFORGE_CONFIG_TILEPATH
+ int badsel = false;
+ RefChar *ref;
+ ImageList *il;
+
+ for ( ref=cv->layerheads[cv->drawmode]->refs; ref!=NULL; ref=ref->next )
+ if ( ref->selected )
+ badsel = true;
+
+ for ( il=cv->layerheads[cv->drawmode]->images; il!=NULL; il=il->next )
+ if ( il->selected )
+ badsel = true;
+#endif
+
+ for ( spl = cv->layerheads[cv->drawmode]->splines; spl!=NULL; spl = spl->next ) {
+ first = NULL;
+ splinepoints = 0;
+ if ( spl->first->selected ) { splinepoints = 1; }
+ for ( spline=spl->first->next; spline!=NULL && spline!=first && !splinepoints; spline = spline->to->next ) {
+ if ( spline->to->selected ) { ++splinepoints; }
+ if ( first == NULL ) first = spline;
+ }
+ if ( splinepoints ) {
+ anypoints += splinepoints;
+ if ( dir==-1 )
+ /* Do nothing */;
+ else if ( spl->first!=spl->last || spl->first->next==NULL ) {
+ if ( dir==-2 || dir==2 )
+ dir = 2; /* Not a closed path, no direction */
+ else
+ dir = -1;
+ } else if ( dir==-2 )
+ dir = SplinePointListIsClockwise(spl);
+ else {
+ int subdir = SplinePointListIsClockwise(spl);
+ if ( subdir!=dir )
+ dir = -1;
+ }
+ }
+ }
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_GetInfo:
+ {
+ SplinePoint *sp; SplineSet *spl; RefChar *ref; ImageList *img;
+ mi->ti.disabled = !CVOneThingSel(cv,&sp,&spl,&ref,&img,&ap);
+ }
+ break;
+ case MID_Clockwise:
+ mi->ti.disabled = !anypoints || dir==2;
+ mi->ti.checked = dir==1;
+ break;
+ case MID_Counter:
+ mi->ti.disabled = !anypoints || dir==2;
+ mi->ti.checked = dir==0;
+ break;
+ case MID_Correct:
+ mi->ti.disabled = !anypoints || dir==2;
+ break;
+ case MID_MetaFont:
+ mi->ti.disabled = cv->drawmode!=dm_fore || cv->sc->layers[ly_fore].refs!=NULL || order2;
+ break;
+ case MID_Stroke:
+ case MID_RmOverlap:
+ mi->ti.disabled = cv->layerheads[cv->drawmode]->splines==NULL;
+ break;
+ case MID_Effects:
+ mi->ti.disabled = ( cv->layerheads[cv->drawmode]->splines==NULL || order2 );
+ break;
+#ifdef FONTFORGE_CONFIG_TILEPATH
+ case MID_TilePath:
+ mi->ti.disabled = badsel || ClipBoardToSplineSet()==NULL || order2;
+ break;
+#endif
+ case MID_RegenBitmaps: case MID_RemoveBitmaps:
+ mi->ti.disabled = cv->fv->sf->bitmaps==NULL;
+ break;
+ case MID_AddExtrema:
+ mi->ti.disabled = cv->layerheads[cv->drawmode]->splines==NULL;
+ /* Like Simplify, always available, but may not do anything if */
+ /* all extrema have points. I'm not going to check for that, too hard */
+ break;
+ case MID_Simplify:
+ mi->ti.disabled = cv->layerheads[cv->drawmode]->splines==NULL;
+ /* Simplify is always available (it may not do anything though) */
+ /* well, ok. Disable it if there is absolutely nothing to work on */
+ break;
+ case MID_BuildAccent:
+ mi->ti.disabled = !SFIsSomethingBuildable(cv->fv->sf,cv->sc,false);
+ break;
+ case MID_Autotrace:
+ mi->ti.disabled = FindAutoTraceName()==NULL || cv->sc->layers[ly_back].images==NULL;
+ break;
+ }
+ }
+}
+
+static void ellistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ cv_ellistcheck(cv,mi,e,true);
+}
+
+static void CVMenuAutoHint(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ /*int removeOverlap = e==NULL || !(e->u.mouse.state&ksm_shift);*/
+ int was = cv->sc->changedsincelasthinted;
+
+ /* Hint undoes are done in _SplineCharAutoHint */
+ cv->sc->manualhints = false;
+ SplineCharAutoHint(cv->sc,NULL);
+ SCUpdateAll(cv->sc);
+ if ( was ) {
+ FontView *fvs;
+ for ( fvs=cv->fv; fvs!=NULL; fvs=fvs->nextsame )
+ GDrawRequestExpose(fvs->v,NULL,false); /* Clear any changedsincelasthinted marks */
+ }
+}
+
+static void CVMenuAutoHintSubs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ SCFigureHintMasks(cv->sc);
+ SCUpdateAll(cv->sc);
+}
+
+static void CVMenuAutoCounter(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ SCFigureCounterMasks(cv->sc);
+}
+
+static void CVMenuDontAutoHint(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ cv->sc->manualhints = !cv->sc->manualhints;
+}
+
+static void CVMenuAutoInstr(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ SCAutoInstr(cv->sc,NULL);
+}
+
+static void CVMenuClearHints(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ SCPreserveHints(cv->sc);
+ SCHintsChanged(cv->sc);
+ if ( mi->mid==MID_ClearHStem ) {
+ StemInfosFree(cv->sc->hstem);
+ cv->sc->hstem = NULL;
+ cv->sc->hconflicts = false;
+ } else if ( mi->mid==MID_ClearVStem ) {
+ StemInfosFree(cv->sc->vstem);
+ cv->sc->vstem = NULL;
+ cv->sc->vconflicts = false;
+ }
+ cv->sc->manualhints = true;
+ SCClearHintMasks(cv->sc,true);
+ SCOutOfDateBackground(cv->sc);
+ SCUpdateAll(cv->sc);
+}
+
+static void CVMenuAddHint(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SplinePoint *sp1, *sp2, *sp3, *sp4;
+ StemInfo *h=NULL;
+ DStemInfo *d;
+
+ if ( !CVTwoForePointsSelected(cv,&sp1,&sp2))
+return;
+
+ SCPreserveHints(cv->sc);
+ SCHintsChanged(cv->sc);
+ if ( mi->mid==MID_AddHHint ) {
+ if ( sp1->me.y==sp2->me.y )
+return;
+ h = chunkalloc(sizeof(StemInfo));
+ if ( sp2->me.y>sp1->me.y ) {
+ h->start = sp1->me.y;
+ h->width = sp2->me.y-sp1->me.y;
+ } else {
+ h->start = sp2->me.y;
+ h->width = sp1->me.y-sp2->me.y;
+ }
+ SCGuessHHintInstancesAndAdd(cv->sc,h,sp1->me.x,sp2->me.x);
+ cv->sc->hconflicts = StemListAnyConflicts(cv->sc->hstem);
+ } else if ( mi->mid==MID_AddVHint ) {
+ if ( sp1->me.x==sp2->me.x )
+return;
+ h = chunkalloc(sizeof(StemInfo));
+ if ( sp2->me.x>sp1->me.x ) {
+ h->start = sp1->me.x;
+ h->width = sp2->me.x-sp1->me.x;
+ } else {
+ h->start = sp2->me.x;
+ h->width = sp1->me.x-sp2->me.x;
+ }
+ SCGuessVHintInstancesAndAdd(cv->sc,h,sp1->me.y,sp2->me.y);
+ cv->sc->vconflicts = StemListAnyConflicts(cv->sc->vstem);
+ } else {
+ if ( !CVIsDiagonalable(sp1,sp2,&sp3,&sp4))
+return;
+ /* Make sure sp1<->sp3 is further left than sp2<->sp4 */
+ if ( sp1->me.x > sp2->me.x + (sp1->me.y-sp2->me.y) * (sp4->me.x-sp2->me.x)/(sp4->me.y-sp2->me.y) ) {
+ SplinePoint *temp;
+ temp = sp1; sp1 = sp2; sp2 = temp;
+ temp = sp3; sp3=sp4; sp4=temp;
+ }
+ /* Make sure sp1,sp2 are at the top */
+ if ( sp1->me.y<sp3->me.y ) {
+ SplinePoint *temp;
+ temp = sp1; sp1=sp3; sp3=temp;
+ temp = sp2; sp2=sp4; sp4=temp;
+ }
+ d = chunkalloc(sizeof(DStemInfo));
+ d->next = cv->sc->dstem;
+ cv->sc->dstem = d;
+ d->leftedgetop = sp1->me;
+ d->rightedgetop = sp2->me;
+ d->leftedgebottom = sp3->me;
+ d->rightedgebottom = sp4->me;
+ }
+ cv->sc->manualhints = true;
+ if ( h!=NULL && cv->sc->parent->mm==NULL )
+ SCModifyHintMasksAdd(cv->sc,h);
+ else
+ SCClearHintMasks(cv->sc,true);
+ SCOutOfDateBackground(cv->sc);
+ SCUpdateAll(cv->sc);
+}
+
+static void CVMenuCreateHint(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ CVCreateHint(cv,mi->mid==MID_CreateHHint,true);
+}
+
+static void CVMenuReviewHints(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ if ( cv->sc->hstem==NULL && cv->sc->vstem==NULL )
+return;
+ CVReviewHints(cv);
+}
+
+static void htlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SplinePoint *sp1, *sp2, *sp3, *sp4;
+ int multilayer = cv->sc->parent->multilayer;
+
+ sp1 = sp2 = NULL;
+ CVTwoForePointsSelected(cv,&sp1,&sp2);
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_AutoHint:
+ mi->ti.disabled = multilayer;
+ break;
+ case MID_HintSubsPt: case MID_AutoCounter:
+ mi->ti.disabled = cv->sc->parent->order2 || multilayer;
+ break;
+ case MID_DontAutoHint:
+ mi->ti.disabled = cv->sc->parent->order2 || multilayer;
+ mi->ti.checked = cv->sc->manualhints;
+ break;
+ case MID_AutoInstr:
+ case MID_EditInstructions:
+ mi->ti.disabled = !cv->fv->sf->order2 || multilayer;
+ break;
+ case MID_Debug:
+ mi->ti.disabled = !cv->fv->sf->order2 || multilayer || !hasFreeTypeDebugger();
+ break;
+ case MID_ClearInstr:
+ mi->ti.disabled = cv->sc->ttf_instrs_len==0;
+ break;
+ case MID_AddHHint:
+ mi->ti.disabled = sp2==NULL || sp2->me.y==sp1->me.y || multilayer;
+ break;
+ case MID_AddVHint:
+ mi->ti.disabled = sp2==NULL || sp2->me.x==sp1->me.x || multilayer;
+ break;
+ case MID_AddDHint:
+ mi->ti.disabled = !CVIsDiagonalable(sp1,sp2,&sp3,&sp4) || multilayer;
+ break;
+ case MID_ReviewHints:
+ mi->ti.disabled = (cv->sc->hstem==NULL && cv->sc->vstem==NULL ) || multilayer;
+ break;
+ }
+ }
+}
+
+static void mtlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ RefChar *r = HasUseMyMetrics(cv->sc);
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_RemoveKerns:
+ mi->ti.disabled = cv->sc->kerns==NULL;
+ break;
+ case MID_RemoveVKerns:
+ mi->ti.disabled = cv->sc->vkerns==NULL;
+ break;
+ case MID_SetVWidth:
+ mi->ti.disabled = !cv->sc->parent->hasvmetrics || r!=NULL;
+ break;
+ case MID_AnchorsAway:
+ mi->ti.disabled = cv->sc->anchor==NULL;
+ break;
+ case MID_SetWidth: case MID_SetLBearing: case MID_SetRBearing:
+ mi->ti.disabled = r!=NULL;
+ break;
+ }
+ }
+}
+
+static void cv_sllistcheck(CharView *cv,struct gmenuitem *mi,GEvent *e) {
+ SplinePoint *sp; SplineSet *spl; RefChar *r; ImageList *im;
+ int exactlyone = CVOneThingSel(cv,&sp,&spl,&r,&im,NULL);
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_NextPt: case MID_PrevPt:
+ case MID_NextCP: case MID_PrevCP:
+ case MID_FirstPtNextCont:
+ mi->ti.disabled = !exactlyone || sp==NULL;
+ break;
+ case MID_FirstPt: case MID_SelPointAt:
+ mi->ti.disabled = cv->layerheads[cv->drawmode]->splines==NULL;
+ break;
+ case MID_Contours:
+ mi->ti.disabled = CVAnySelPoints(cv)==NULL;
+ break;
+ case MID_SelectWidth:
+ mi->ti.disabled = !cv->showhmetrics;
+ if ( HasUseMyMetrics(cv->sc)!=NULL )
+ mi->ti.disabled = true;
+ if ( !mi->ti.disabled ) {
+ free(mi->ti.text);
+ mi->ti.text = utf82u_copy(cv->widthsel?_("Deselect Width"):_("Width"));
+ }
+ break;
+ case MID_SelectVWidth:
+ mi->ti.disabled = !cv->showvmetrics || !cv->sc->parent->hasvmetrics;
+ if ( HasUseMyMetrics(cv->sc)!=NULL )
+ mi->ti.disabled = true;
+ if ( !mi->ti.disabled ) {
+ free(mi->ti.text);
+ mi->ti.text = utf82u_copy(cv->vwidthsel?_("Deselect VWidth"):_("VWidth"));
+ }
+ break;
+ case MID_SelectHM:
+ mi->ti.disabled = !exactlyone || sp==NULL || sp->hintmask==NULL;
+ break;
+ }
+ }
+}
+
+static void sllistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ cv_sllistcheck(cv,mi,e);
+}
+
+static void cv_cblistcheck(CharView *cv,struct gmenuitem *mi,GEvent *e) {
+ int i;
+ KernPair *kp;
+ SplineChar *sc = cv->sc;
+ SplineFont *sf = sc->parent;
+ PST *pst;
+ char *name;
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_AnchorPairs:
+ mi->ti.disabled = sc->anchor==NULL;
+ break;
+ case MID_AnchorControl:
+ mi->ti.disabled = sc->anchor==NULL;
+ break;
+ case MID_AnchorGlyph:
+ if ( cv->apmine!=NULL )
+ mi->ti.disabled = false;
+ else
+ mi->ti.disabled = sc->anchor==NULL;
+ break;
+ case MID_KernPairs:
+ mi->ti.disabled = sc->kerns==NULL;
+ if ( sc->kerns==NULL ) {
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ for ( kp = sf->glyphs[i]->kerns; kp!=NULL; kp=kp->next ) {
+ if ( kp->sc == sc ) {
+ mi->ti.disabled = false;
+ goto out;
+ }
+ }
+ }
+ out:;
+ }
+ break;
+ case MID_Ligatures:
+ name = sc->name;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ for ( pst=sf->glyphs[i]->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->type==pst_ligature &&
+ PSTContains(pst->u.lig.components,name)) {
+ mi->ti.disabled = false;
+ goto break_out_2;
+ }
+ }
+ }
+ mi->ti.disabled = true;
+ break_out_2:;
+ break;
+ }
+ }
+}
+
+static void cv_nplistcheck(CharView *cv,struct gmenuitem *mi,GEvent *e) {
+ SplineChar *sc = cv->sc;
+ int order2 = sc->parent->order2;
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_PtsNone:
+ mi->ti.checked = !cv->showpointnumbers;
+ break;
+ case MID_PtsTrue:
+ mi->ti.disabled = !order2;
+ mi->ti.checked = cv->showpointnumbers && order2;
+ break;
+ case MID_PtsPost:
+ mi->ti.disabled = order2;
+ mi->ti.checked = cv->showpointnumbers && !order2 && sc->numberpointsbackards;
+ break;
+ case MID_PtsSVG:
+ mi->ti.disabled = order2;
+ mi->ti.checked = cv->showpointnumbers && !order2 && !sc->numberpointsbackards;
+ break;
+ }
+ }
+}
+
+static void cv_vwlistcheck(CharView *cv,struct gmenuitem *mi,GEvent *e) {
+ int pos, gid;
+ SplineFont *sf = cv->sc->parent;
+ EncMap *map = cv->fv->map;
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_NextDef:
+ for ( pos = CVCurEnc(cv)+1; pos<map->enccount && ((gid=map->map[pos])==-1 || !SCWorthOutputting(sf->glyphs[gid])); ++pos );
+ mi->ti.disabled = pos==map->enccount || cv->searcher!=NULL;
+ break;
+ case MID_PrevDef:
+ for ( pos = CVCurEnc(cv)-1; pos>=0 && ((gid=map->map[pos])==-1 || !SCWorthOutputting(sf->glyphs[gid])); --pos );
+ mi->ti.disabled = pos<0 || cv->searcher!=NULL;
+ break;
+ case MID_Next:
+ mi->ti.disabled = cv->searcher!=NULL || CVCurEnc(cv)==map->enccount-1;
+ break;
+ case MID_Prev:
+ mi->ti.disabled = cv->searcher!=NULL || CVCurEnc(cv)==0;
+ break;
+ case MID_Former:
+ if ( cv->former_cnt<=1 )
+ pos = -1;
+ else for ( pos = sf->glyphcnt-1; pos>=0 ; --pos )
+ if ( sf->glyphs[pos]!=NULL && strcmp(sf->glyphs[pos]->name,cv->former_names[1])==0 )
+ break;
+ mi->ti.disabled = pos==-1 || cv->searcher!=NULL;
+ break;
+ case MID_Goto: case MID_FindInFontView:
+ mi->ti.disabled = cv->searcher!=NULL;
+ break;
+ case MID_MarkExtrema:
+ mi->ti.checked = cv->markextrema;
+ break;
+ case MID_MarkPointsOfInflection:
+ mi->ti.checked = cv->markpoi;
+ break;
+ case MID_ShowCPInfo:
+ mi->ti.checked = cv->showcpinfo;
+ break;
+ case MID_ShowSideBearings:
+ mi->ti.checked = cv->showsidebearings;
+ break;
+ case MID_ShowTabs:
+ mi->ti.checked = cv->showtabs;
+ mi->ti.disabled = cv->former_cnt<=1;
+ break;
+ case MID_HidePoints:
+ free(mi->ti.text);
+ mi->ti.text = utf82u_copy(cv->showpoints?_("Hide Points"):_("Show Points"));
+ break;
+ case MID_HideRulers:
+ free(mi->ti.text);
+ mi->ti.text = utf82u_copy(cv->showrulers?_("Hide Rulers"):_("Show Rulers"));
+ break;
+ case MID_ShowGridFit:
+ mi->ti.disabled = !hasFreeType() || cv->drawmode!=dm_fore || cv->dv!=NULL;
+ mi->ti.checked = cv->show_ft_results;
+ break;
+ case MID_Fill:
+ mi->ti.checked = cv->showfilled;
+ break;
+#if HANYANG
+ case MID_DisplayCompositions:
+ mi->ti.disabled = !cv->sc->compositionunit || cv->sc->parent->rules==NULL;
+ break;
+#endif
+ }
+ }
+}
+
+static void cblistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ cv_cblistcheck(cv,mi,e);
+}
+
+static void nplistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ cv_nplistcheck(cv,mi,e);
+}
+
+static void vwlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ cv_vwlistcheck(cv,mi,e);
+}
+
+static void CVMenuCenter(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ DBounds bb;
+ real transform[6];
+ int drawmode = cv->drawmode;
+
+ cv->drawmode = dm_fore;
+
+ transform[0] = transform[3] = 1.0;
+ transform[1] = transform[2] = transform[5] = 0.0;
+ SplineCharFindBounds(cv->sc,&bb);
+ if ( mi->mid==MID_Center )
+ transform[4] = (cv->sc->width-(bb.maxx-bb.minx))/2 - bb.minx;
+ else
+ transform[4] = (cv->sc->width-(bb.maxx-bb.minx))/3 - bb.minx;
+ if ( transform[4]!=0 ) {
+ cv->p.transany = false;
+ CVPreserveState(cv);
+ CVTransFunc(cv,transform,fvt_dontmovewidth);
+ CVCharChangedUpdate(cv);
+ }
+ cv->drawmode = drawmode;
+}
+
+static void CVMenuSetWidth(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ if ( mi->mid == MID_SetVWidth && !cv->sc->parent->hasvmetrics )
+return;
+ CVSetWidth(cv,mi->mid==MID_SetWidth?wt_width:
+ mi->mid==MID_SetLBearing?wt_lbearing:
+ mi->mid==MID_SetRBearing?wt_rbearing:
+ wt_vwidth);
+}
+
+static void CVMenuRemoveKern(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ if ( cv->sc->kerns!=NULL ) {
+ KernPairsFree(cv->sc->kerns);
+ cv->sc->kerns = NULL;
+ cv->sc->parent->changed = true;
+ if ( cv->fv->cidmaster!=NULL )
+ cv->fv->cidmaster->changed = true;
+ }
+}
+
+static void CVMenuRemoveVKern(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ if ( cv->sc->vkerns!=NULL ) {
+ KernPairsFree(cv->sc->vkerns);
+ cv->sc->vkerns = NULL;
+ cv->sc->parent->changed = true;
+ if ( cv->fv->cidmaster!=NULL )
+ cv->fv->cidmaster->changed = true;
+ }
+}
+
+static void CVMenuKPCloseup(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ KernPairD(cv->sc->parent,cv->sc,NULL,false);
+}
+
+static void CVMenuAnchorsAway(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ AnchorPoint *ap;
+
+ ap = mi->ti.userdata;
+ if ( ap==NULL )
+ for ( ap = cv->sc->anchor; ap!=NULL && !ap->selected; ap = ap->next );
+ if ( ap==NULL ) ap= cv->sc->anchor;
+ if ( ap==NULL )
+return;
+
+ GDrawSetCursor(cv->v,ct_watch);
+ GDrawSync(NULL);
+ GDrawProcessPendingEvents(NULL);
+ AnchorControl(cv->sc,ap);
+ GDrawSetCursor(cv->v,ct_pointer);
+}
+
+static GMenuItem2 wnmenu[] = {
+ { { (unichar_t *) N_("New O_utline Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 1, 0, 'u' }, H_("New Outline Window|Ctl+H"), NULL, NULL, /* No function, never avail */NULL },
+ { { (unichar_t *) N_("New _Bitmap Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("New Bitmap Window|Ctl+J"), NULL, NULL, CVMenuOpenBitmap, MID_OpenBitmap },
+ { { (unichar_t *) N_("New _Metrics Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("New Metrics Window|Ctl+K"), NULL, NULL, CVMenuOpenMetrics },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Warnings"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Warnings|No Shortcut"), NULL, NULL, _MenuWarnings, MID_Warnings },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { NULL }
+};
+
+static void CVWindowMenuBuild(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ struct gmenuitem *wmi;
+
+ WindowMenuBuild(gw,mi,e);
+ for ( wmi = mi->sub; wmi->ti.text!=NULL || wmi->ti.line ; ++wmi ) {
+ switch ( wmi->mid ) {
+ case MID_OpenBitmap:
+ wmi->ti.disabled = cv->sc->parent->bitmaps==NULL;
+ break;
+ case MID_Warnings:
+ wmi->ti.disabled = ErrorWindowExists();
+ break;
+ }
+ }
+}
+
+static void SVWindowMenuBuild(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ struct gmenuitem *wmi;
+
+ WindowMenuBuild(gw,mi,e);
+ for ( wmi = mi->sub; wmi->ti.text!=NULL || wmi->ti.line ; ++wmi ) {
+ switch ( wmi->mid ) {
+ case MID_OpenBitmap:
+ wmi->ti.disabled = true;
+ break;
+ }
+ }
+}
+
+static GMenuItem2 dummyitem[] = { { (unichar_t *) N_("Font|_New"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'N' }, NULL };
+static GMenuItem2 fllist[] = {
+ { { (unichar_t *) N_("Font|_New"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'N' }, H_("New|Ctl+N"), NULL, NULL, MenuNew },
+ { { (unichar_t *) N_("_Open"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'O' }, H_("Open|Ctl+O"), NULL, NULL, MenuOpen },
+ { { (unichar_t *) N_("Recen_t"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 't' }, NULL, dummyitem, MenuRecentBuild, NULL, MID_Recent },
+ { { (unichar_t *) N_("_Close"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Close|Ctl+Shft+Q"), NULL, NULL, CVMenuClose },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Save"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Save|Ctl+S"), NULL, NULL, CVMenuSave },
+ { { (unichar_t *) N_("S_ave as..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'a' }, H_("Save as...|Ctl+Shft+S"), NULL, NULL, CVMenuSaveAs },
+ { { (unichar_t *) N_("_Generate Fonts..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'G' }, H_("Generate Fonts...|Ctl+Shft+G"), NULL, NULL, CVMenuGenerate },
+ { { (unichar_t *) N_("Generate Mac _Family..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Generate Mac Family...|Alt+Ctl+G"), NULL, NULL, CVMenuGenerateFamily },
+ { { (unichar_t *) N_("Expor_t..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 't' }, H_("Export...|No Shortcut"), NULL, NULL, CVMenuExport },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Import..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Import...|Ctl+Shft+I"), NULL, NULL, CVMenuImport },
+ { { (unichar_t *) N_("_Revert File"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Revert File|Ctl+Shft+R"), NULL, NULL, CVMenuRevert, MID_Revert },
+ { { (unichar_t *) N_("Revert Gl_yph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Revert Glyph|Alt+Ctl+R"), NULL, NULL, CVMenuRevertGlyph, MID_RevertGlyph },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Print..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Print...|Ctl+P"), NULL, NULL, CVMenuPrint },
+ { { (unichar_t *) N_("_Display..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'D' }, H_("Display...|Alt+Ctl+P"), NULL, NULL, CVMenuDisplay, MID_Display },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Pr_eferences..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'e' }, H_("Preferences...|No Shortcut"), NULL, NULL, MenuPrefs },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Quit"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'Q' }, H_("Quit|Ctl+Q"), NULL, NULL, MenuExit },
+ { NULL }
+};
+
+static GMenuItem2 sllist[] = {
+ { { (unichar_t *) N_("Select _All"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Select All|Ctl+A"), NULL, NULL, CVSelectAll, MID_SelAll },
+ { { (unichar_t *) N_("_Invert Selection"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Invert Selection|Ctl+Escape"), NULL, NULL, CVSelectInvert, MID_SelInvert },
+ { { (unichar_t *) N_("_Deselect All"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Deselect All|Escape"), NULL, NULL, CVSelectNone, MID_SelNone },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_First Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("First Point|Ctl+."), NULL, NULL, CVMenuNextPrevPt, MID_FirstPt },
+ { { (unichar_t *) N_("First P_oint, Next Contour"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("First Point, Next Contour|Alt+Ctl+."), NULL, NULL, CVMenuNextPrevPt, MID_FirstPtNextCont },
+ { { (unichar_t *) N_("_Next Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'N' }, H_("Next Point|Ctl+Shft+}"), NULL, NULL, CVMenuNextPrevPt, MID_NextPt },
+ { { (unichar_t *) N_("_Prev Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Prev Point|Ctl+Shft+{"), NULL, NULL, CVMenuNextPrevPt, MID_PrevPt },
+ { { (unichar_t *) N_("Ne_xt Control Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'x' }, H_("Next Control Point|Ctl+;"), NULL, NULL, CVMenuNextPrevCPt, MID_NextCP },
+ { { (unichar_t *) N_("P_rev Control Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'r' }, H_("Prev Control Point|Ctl+Shft+:"), NULL, NULL, CVMenuNextPrevCPt, MID_PrevCP },
+ { { (unichar_t *) N_("Points on Selected _Contours"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'r' }, H_("Points on Selected Contours|Alt+Ctl+,"), NULL, NULL, CVMenuSelectContours, MID_Contours },
+ { { (unichar_t *) N_("Point A_t"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'r' }, H_("Point At|Ctl+,"), NULL, NULL, CVMenuSelectPointAt, MID_SelPointAt },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Select All _Points & Refs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Select All Points & Refs|Alt+Ctl+A"), NULL, NULL, CVSelectAll, MID_SelectAllPoints },
+ { { (unichar_t *) N_("Sele_ct Anchors"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'c' }, H_("Select Anchors|No Shortcut"), NULL, NULL, CVSelectAll, MID_SelectAnchors },
+ { { (unichar_t *) N_("_Width"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Width|No Shortcut"), NULL, NULL, CVSelectWidth, MID_SelectWidth },
+ { { (unichar_t *) N_("_VWidth"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("VWidth|No Shortcut"), NULL, NULL, CVSelectVWidth, MID_SelectVWidth },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Select Points Affected by HM"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("Select Points Affected by HM|No Shortcut"), NULL, NULL, CVSelectHM, MID_SelectHM },
+ { NULL }
+};
+
+static GMenuItem2 edlist[] = {
+ { { (unichar_t *) N_("_Undo"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'U' }, H_("Undo|Ctl+Z"), NULL, NULL, CVUndo, MID_Undo },
+ { { (unichar_t *) N_("_Redo"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Redo|Ctl+Y"), NULL, NULL, CVRedo, MID_Redo },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Cu_t"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 't' }, H_("Cut|Ctl+X"), NULL, NULL, CVCut, MID_Cut },
+ { { (unichar_t *) N_("_Copy"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Copy|Ctl+C"), NULL, NULL, CVCopy, MID_Copy },
+ { { (unichar_t *) N_("C_opy Reference"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Copy Reference|Ctl+G"), NULL, NULL, CVCopyRef, MID_CopyRef },
+ { { (unichar_t *) N_("Copy _Lookup Data"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Copy Lookup Data|Alt+Ctl+C"), NULL, NULL, CVCopyLookupData, MID_CopyLookupData },
+ { { (unichar_t *) N_("Copy _Width"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'W' }, H_("Copy Width|Ctl+W"), NULL, NULL, CVCopyWidth, MID_CopyWidth },
+ { { (unichar_t *) N_("Co_py LBearing"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'p' }, H_("Copy LBearing|No Shortcut"), NULL, NULL, CVCopyWidth, MID_CopyLBearing },
+ { { (unichar_t *) N_("Copy RBearin_g"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'g' }, H_("Copy RBearing|No Shortcut"), NULL, NULL, CVCopyWidth, MID_CopyRBearing },
+ { { (unichar_t *) N_("_Paste"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Paste|Ctl+V"), NULL, NULL, CVPaste, MID_Paste },
+ { { (unichar_t *) N_("C_lear"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Clear|Delete"), NULL, NULL, CVClear, MID_Clear },
+ { { (unichar_t *) N_("Clear _Background"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Clear Background|No Shortcut"), NULL, NULL, CVClearBackground },
+ { { (unichar_t *) N_("_Merge"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Merge|Ctl+M"), NULL, NULL, CVMerge, MID_Merge },
+ { { (unichar_t *) N_("_Elide"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Elide|Alt+Ctl+M"), NULL, NULL, CVElide, MID_Elide },
+ { { (unichar_t *) N_("_Join"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'J' }, H_("Join|Ctl+Shft+J"), NULL, NULL, CVJoin, MID_Join },
+ { { (unichar_t *) N_("Copy _Fg To Bg"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Copy Fg To Bg|Ctl+Shft+C"), NULL, NULL, CVCopyFgBg, MID_CopyFgToBg },
+#ifdef FONTFORGE_CONFIG_COPY_BG_TO_FG
+ { { (unichar_t *) N_("Cop_y Bg To Fg"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Copy Bg To Fg|No Shortcut"), NULL, NULL, CVCopyBgFg, MID_CopyBgToFg },
+#endif
+ { { (unichar_t *) N_("Copy Gri_d Fit"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Copy Grid Fit|No Shortcut"), NULL, NULL, CVMenuCopyGridFit, MID_CopyGridFit },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Select"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, NULL, sllist, sllistcheck },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("U_nlink Reference"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'U' }, H_("Unlink Reference|Ctl+U"), NULL, NULL, CVUnlinkRef, MID_UnlinkRef },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Remo_ve Undoes"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'e' }, H_("Remove Undoes|No Shortcut"), NULL, NULL, CVRemoveUndoes, MID_RemoveUndoes },
+ { NULL }
+};
+
+static GMenuItem2 ptlist[] = {
+ { { (unichar_t *) N_("_Curve"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'C' }, H_("Curve|Ctl+2"), NULL, NULL, CVMenuPointType, MID_Curve },
+ { { (unichar_t *) N_("C_orner"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'o' }, H_("Corner|Ctl+3"), NULL, NULL, CVMenuPointType, MID_Corner },
+ { { (unichar_t *) N_("_Tangent"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Tangent|Ctl+4"), NULL, NULL, CVMenuPointType, MID_Tangent },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+/* GT: Make this (selected) point the first point in the glyph */
+ { { (unichar_t *) N_("_Make First"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Make First|Ctl+1"), NULL, NULL, CVMenuMakeFirst, MID_MakeFirst },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Can Be _Interpolated"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Can Be Interpolated|No Shortcut"), NULL, NULL, CVMenuImplicit, MID_ImplicitPt },
+ { { (unichar_t *) N_("Can't Be _Interpolated"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Can't Be Interpolated|No Shortcut"), NULL, NULL, CVMenuImplicit, MID_NoImplicitPt },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Add Anchor"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Add Anchor|Ctl+0"), NULL, NULL, CVMenuAddAnchor, MID_AddAnchor },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Make _Line"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Make Line|No Shortcut"), NULL, NULL, CVMenuMakeLine, MID_MakeLine },
+ { { (unichar_t *) N_("Insert Point On _Spline At..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Insert Point On Spline At...|No Shortcut"), NULL, NULL, CVMenuInsertPt, MID_InsertPtOnSplineAt },
+ { { (unichar_t *) N_("Center _Between Control Points"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Center Between Control Points|No Shortcut"), NULL, NULL, CVMenuCenterCP, MID_CenterCP },
+ { NULL }
+};
+
+static GMenuItem2 allist[] = {
+/* GT: Align these points to their average position */
+ { { (unichar_t *) N_("_Average Points"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Average Points|Ctl+Shft+@"), NULL, NULL, CVMenuConstrain, MID_Average },
+ { { (unichar_t *) N_("_Space Points"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Space Points|Ctl+Shft+#"), NULL, NULL, CVMenuConstrain, MID_SpacePts },
+ { { (unichar_t *) N_("Space _Regions..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Space Regions...|No Shortcut"), NULL, NULL, CVMenuConstrain, MID_SpaceRegion },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Make _Parallel..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Make Parallel...|No Shortcut"), NULL, NULL, CVMenuMakeParallel, MID_MakeParallel },
+ { NULL }
+};
+
+static GMenuItem2 smlist[] = {
+ { { (unichar_t *) N_("_Simplify"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Simplify|Ctl+Shft+M"), NULL, NULL, CVMenuSimplify, MID_Simplify },
+ { { (unichar_t *) N_("Simplify More..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Simplify More...|Alt+Ctl+Shft+M"), NULL, NULL, CVMenuSimplifyMore, MID_SimplifyMore },
+ { { (unichar_t *) N_("Clea_nup Glyph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'n' }, H_("Cleanup Glyph|No Shortcut"), NULL, NULL, CVMenuCleanupGlyph, MID_CleanupGlyph },
+ { { (unichar_t *) N_("Canonical Start _Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'n' }, H_("Canonical Start Point|No Shortcut"), NULL, NULL, CVMenuCanonicalStart, MID_CanonicalStart },
+ { { (unichar_t *) N_("Canonical _Contours"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'n' }, H_("Canonical Contours|No Shortcut"), NULL, NULL, CVMenuCanonicalContours, MID_CanonicalContours },
+ { NULL }
+};
+
+static void smlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_Simplify:
+ case MID_CleanupGlyph:
+ case MID_SimplifyMore:
+ case MID_CanonicalStart:
+ mi->ti.disabled = cv->layerheads[cv->drawmode]->splines==NULL;
+ break;
+ case MID_CanonicalContours:
+ mi->ti.disabled = cv->layerheads[cv->drawmode]->splines==NULL ||
+ cv->layerheads[cv->drawmode]->splines->next==NULL ||
+ cv->drawmode!=dm_fore;
+ break;
+ }
+ }
+}
+
+static GMenuItem2 orlist[] = {
+ { { (unichar_t *) N_("_First"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("First|No Shortcut"), NULL, NULL, CVMenuOrder, MID_First },
+ { { (unichar_t *) N_("_Earlier"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Earlier|No Shortcut"), NULL, NULL, CVMenuOrder, MID_Earlier },
+ { { (unichar_t *) N_("L_ater"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'n' }, H_("Later|No Shortcut"), NULL, NULL, CVMenuOrder, MID_Later },
+ { { (unichar_t *) N_("_Last"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'n' }, H_("Last|No Shortcut"), NULL, NULL, CVMenuOrder, MID_Last },
+ { NULL }
+};
+
+static void orlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SplinePointList *spl;
+ RefChar *r;
+ ImageList *im;
+ int exactlyone = CVOneContourSel(cv,&spl,&r,&im);
+ int isfirst, islast;
+
+ isfirst = islast = false;
+ if ( spl!=NULL ) {
+ isfirst = cv->layerheads[cv->drawmode]->splines==spl;
+ islast = spl->next==NULL;
+ } else if ( r!=NULL ) {
+ isfirst = cv->layerheads[cv->drawmode]->refs==r;
+ islast = r->next==NULL;
+ } else if ( im!=NULL ) {
+ isfirst = cv->layerheads[cv->drawmode]->images==im;
+ islast = im->next!=NULL;
+ }
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_First:
+ case MID_Earlier:
+ mi->ti.disabled = !exactlyone || isfirst;
+ break;
+ case MID_Last:
+ case MID_Later:
+ mi->ti.disabled = !exactlyone || islast;
+ break;
+ }
+ }
+}
+
+static GMenuItem2 rmlist[] = {
+ { { (unichar_t *) N_("_Remove Overlap"), &GIcon_rmoverlap, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Remove Overlap|Ctl+Shft+O"), NULL, NULL, CVMenuOverlap, MID_RmOverlap },
+ { { (unichar_t *) N_("_Intersect"), &GIcon_intersection, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Intersect|No Shortcut"), NULL, NULL, CVMenuOverlap, MID_Intersection },
+ { { (unichar_t *) N_("_Exclude"), &GIcon_exclude, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'E' }, H_("Exclude|No Shortcut"), NULL, NULL, CVMenuOverlap, MID_Exclude },
+ { { (unichar_t *) N_("_Find Intersections"), &GIcon_findinter, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Find Intersections|No Shortcut"), NULL, NULL, CVMenuOverlap, MID_FindInter },
+ { NULL }
+};
+
+static GMenuItem2 eflist[] = {
+ { { (unichar_t *) N_("_Inline"), &GIcon_inline, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'O' }, H_("Inline|No Shortcut"), NULL, NULL, CVMenuInline },
+ { { (unichar_t *) N_("_Outline"), &GIcon_outline, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Outline|No Shortcut"), NULL, NULL, CVMenuOutline },
+ { { (unichar_t *) N_("_Shadow"), &GIcon_shadow, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Shadow|No Shortcut"), NULL, NULL, CVMenuShadow },
+ { { (unichar_t *) N_("_Wireframe"), &GIcon_wireframe, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'W' }, H_("Wireframe|No Shortcut"), NULL, NULL, CVMenuWireframe },
+ { NULL }
+};
+
+static GMenuItem2 balist[] = {
+ { { (unichar_t *) N_("_Build Accented Glyph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'u' }, H_("Build Accented Glyph|Ctl+Shft+A"), NULL, NULL, CVMenuBuildAccent, MID_BuildAccent },
+ { { (unichar_t *) N_("Build _Composite Glyph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Build Composite Glyph|No Shortcut"), NULL, NULL, CVMenuBuildComposite, MID_BuildComposite },
+ { NULL }
+};
+
+static GMenuItem2 delist[] = {
+ { { (unichar_t *) N_("_References..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'u' }, H_("References...|Alt+Ctl+I"), NULL, NULL, CVMenuShowDependentRefs, MID_ShowDependentRefs },
+ { { (unichar_t *) N_("_Substitutions..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Substitutions...|No Shortcut"), NULL, NULL, CVMenuShowDependentSubs, MID_ShowDependentSubs },
+ { NULL }
+};
+
+static GMenuItem2 trlist[] = {
+ { { (unichar_t *) N_("_Transform..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Transform...|No Shortcut"), NULL, NULL, CVMenuTransform },
+ { { (unichar_t *) N_("_Point of View Projection..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Point of View Projection...|Ctl+Shft+<"), NULL, NULL, CVMenuPOV },
+ { { (unichar_t *) N_("_Non Linear Transform..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Non Linear Transform...|Ctl+Shft+|"), NULL, NULL, CVMenuNLTransform },
+ { NULL }
+};
+
+static GMenuItem2 rndlist[] = {
+ { { (unichar_t *) N_("To _Int"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("To Int|Ctl+Shft+_"), NULL, NULL, CVMenuRound2Int, MID_Round },
+ { { (unichar_t *) N_("To _Hundredths"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("To Hundredths|No Shortcut"), NULL, NULL, CVMenuRound2Hundredths, 0 },
+ { { (unichar_t *) N_("_Cluster"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Cluster|No Shortcut"), NULL, NULL, CVMenuCluster },
+ { NULL }
+};
+
+static GMenuItem2 ellist[] = {
+ { { (unichar_t *) N_("_Font Info..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Font Info...|Ctl+Shft+F"), NULL, NULL, CVMenuFontInfo },
+ { { (unichar_t *) N_("Glyph _Info..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Glyph Info...|Alt+Ctl+Shft+I"), NULL, NULL, CVMenuCharInfo, MID_CharInfo },
+ { { (unichar_t *) N_("Get _Info..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Get Info...|Ctl+I"), NULL, NULL, CVMenuGetInfo, MID_GetInfo },
+ { { (unichar_t *) N_("S_how Dependent"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'D' }, NULL, delist, delistcheck },
+ { { (unichar_t *) N_("Find Pr_oblems..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Find Problems...|Ctl+E"), NULL, NULL, CVMenuFindProblems },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Bitm_ap strikes Available..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Bitmap strikes Available...|Ctl+Shft+B"), NULL, NULL, CVMenuBitmaps, MID_AvailBitmaps },
+ { { (unichar_t *) N_("Regenerate _Bitmap Glyphs..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Regenerate Bitmap Glyphs...|Ctl+B"), NULL, NULL, CVMenuBitmaps, MID_RegenBitmaps },
+ { { (unichar_t *) N_("Remove Bitmap Glyphs..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Remove Bitmap Glyphs...|No Shortcut"), NULL, NULL, CVMenuBitmaps, MID_RemoveBitmaps },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Transformations"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Transformations|No Shortcut"), trlist },
+ { { (unichar_t *) N_("_Expand Stroke..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'E' }, H_("Expand Stroke...|Ctl+Shft+E"), NULL, NULL, CVMenuStroke, MID_Stroke },
+#ifdef FONTFORGE_CONFIG_TILEPATH
+ { { (unichar_t *) N_("Tile _Path..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Tile Path...|No Shortcut"), NULL, NULL, CVMenuTilePath, MID_TilePath },
+#endif
+ { { (unichar_t *) N_("O_verlap"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'v' }, NULL, rmlist, NULL, NULL, MID_RmOverlap },
+ { { (unichar_t *) N_("_Simplify"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, NULL, smlist, smlistcheck, NULL, MID_Simplify },
+ { { (unichar_t *) N_("Add E_xtrema"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'x' }, H_("Add Extrema|Ctl+Shft+X"), NULL, NULL, CVMenuAddExtrema, MID_AddExtrema },
+ { { (unichar_t *) N_("Effects"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, NULL, eflist, NULL, NULL, MID_Effects },
+ { { (unichar_t *) N_("_Meta Font..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Meta Font...|Ctl+Shft+!"), NULL, NULL, CVMenuMetaFont, MID_MetaFont },
+ { { (unichar_t *) N_("Autot_race"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'r' }, H_("Autotrace|Ctl+Shft+T"), NULL, NULL, CVMenuAutotrace, MID_Autotrace },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("A_lign"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'l' }, NULL, allist, allistcheck },
+ { { (unichar_t *) N_("Roun_d"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, NULL, rndlist, NULL, NULL, MID_Round },
+ { { (unichar_t *) N_("Order"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, NULL, orlist, orlistcheck },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Cl_ockwise"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'o' }, H_("Clockwise|No Shortcut"), NULL, NULL, CVMenuDir, MID_Clockwise },
+ { { (unichar_t *) N_("Cou_nter Clockwise"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'n' }, H_("Counter Clockwise|No Shortcut"), NULL, NULL, CVMenuDir, MID_Counter },
+ { { (unichar_t *) N_("_Correct Direction"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'D' }, H_("Correct Direction|Ctl+Shft+D"), NULL, NULL, CVMenuCorrectDir, MID_Correct },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("B_uild"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'u' }, NULL, balist, balistcheck, NULL, MID_BuildAccent },
+ { NULL }
+};
+
+static GMenuItem2 htlist[] = {
+ { { (unichar_t *) N_("Auto_Hint"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("AutoHint|Ctl+Shft+H"), NULL, NULL, CVMenuAutoHint, MID_AutoHint },
+ { { (unichar_t *) N_("Hint _Substitution Pts"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("Hint Substitution Pts|No Shortcut"), NULL, NULL, CVMenuAutoHintSubs, MID_HintSubsPt },
+ { { (unichar_t *) N_("Auto _Counter Hint"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("Auto Counter Hint|No Shortcut"), NULL, NULL, CVMenuAutoCounter, MID_AutoCounter },
+ { { (unichar_t *) N_("_Don't AutoHint"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'H' }, H_("Don't AutoHint|No Shortcut"), NULL, NULL, CVMenuDontAutoHint, MID_DontAutoHint },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Auto_Instr"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("AutoInstr|Ctl+T"), NULL, NULL, CVMenuAutoInstr, MID_AutoInstr },
+ { { (unichar_t *) N_("_Edit Instructions..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Edit Instructions...|No Shortcut"), NULL, NULL, CVMenuEditInstrs, MID_EditInstructions },
+ { { (unichar_t *) N_("_Debug..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Debug...|No Shortcut"), NULL, NULL, CVMenuDebug, MID_Debug },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Clear HStem"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Clear HStem|No Shortcut"), NULL, NULL, CVMenuClearHints, MID_ClearHStem },
+ { { (unichar_t *) N_("Clear _VStem"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("Clear VStem|No Shortcut"), NULL, NULL, CVMenuClearHints, MID_ClearVStem },
+ { { (unichar_t *) N_("Clear Instructions"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Clear Instructions|No Shortcut"), NULL, NULL, CVMenuClearInstrs, MID_ClearInstr },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Add HHint"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Add HHint|No Shortcut"), NULL, NULL, CVMenuAddHint, MID_AddHHint },
+ { { (unichar_t *) N_("Add VHi_nt"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 's' }, H_("Add VHint|No Shortcut"), NULL, NULL, CVMenuAddHint, MID_AddVHint },
+ { { (unichar_t *) N_("Add DHint"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 't' }, H_("Add DHint|No Shortcut"), NULL, NULL, CVMenuAddHint, MID_AddDHint },
+ { { (unichar_t *) N_("Crea_te HHint..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'r' }, H_("Create HHint...|No Shortcut"), NULL, NULL, CVMenuCreateHint, MID_CreateHHint },
+ { { (unichar_t *) N_("Cr_eate VHint..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'e' }, H_("Create VHint...|No Shortcut"), NULL, NULL, CVMenuCreateHint, MID_CreateVHint },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Review Hints..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Review Hints...|Alt+Ctl+H"), NULL, NULL, CVMenuReviewHints, MID_ReviewHints },
+ { NULL }
+};
+
+static GMenuItem2 ap2list[] = {
+ { NULL }
+};
+
+static void ap2listbuild(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ char buf[300];
+ GMenuItem *sub;
+ int k, cnt;
+ AnchorPoint *ap;
+ extern void GMenuItemArrayFree(GMenuItem *mi);
+
+ if ( mi->sub!=NULL ) {
+ GMenuItemArrayFree(mi->sub);
+ mi->sub = NULL;
+ }
+
+ for ( k=0; k<2; ++k ) {
+ cnt = 0;
+ for ( ap=cv->sc->anchor; ap!=NULL; ap=ap->next ) {
+ if ( k ) {
+ if ( ap->type==at_baselig )
+/* GT: In the next few lines the "%s" is the name of an anchor class, and the */
+/* GT: rest of the string identifies the type of the anchor */
+ snprintf(buf,sizeof(buf), _("%s at ligature pos %d"), ap->anchor->name, ap->lig_index );
+ else
+ snprintf(buf,sizeof(buf),
+ ap->type==at_cexit ? _("%s exit"):
+ ap->type==at_centry ? _("%s entry"):
+ ap->type==at_mark ? _("%s mark"):
+ _("%s base"),ap->anchor->name );
+ sub[cnt].ti.text = utf82u_copy(buf);
+ sub[cnt].ti.userdata = ap;
+ sub[cnt].ti.bg = sub[cnt].ti.fg = COLOR_DEFAULT;
+ sub[cnt].invoke = CVMenuAnchorsAway;
+ }
+ ++cnt;
+ }
+ if ( !k )
+ sub = gcalloc(cnt+1,sizeof(GMenuItem));
+ }
+ mi->sub = sub;
+}
+
+static GMenuItem2 mtlist[] = {
+ { { (unichar_t *) N_("_Center in Width"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Center in Width|No Shortcut"), NULL, NULL, CVMenuCenter, MID_Center },
+ { { (unichar_t *) N_("_Thirds in Width"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Thirds in Width|No Shortcut"), NULL, NULL, CVMenuCenter, MID_Thirds },
+ { { (unichar_t *) N_("Set _Width..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'W' }, H_("Set Width...|Ctl+Shft+L"), NULL, NULL, CVMenuSetWidth, MID_SetWidth },
+ { { (unichar_t *) N_("Set _LBearing..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'L' }, H_("Set LBearing...|Ctl+L"), NULL, NULL, CVMenuSetWidth, MID_SetLBearing },
+ { { (unichar_t *) N_("Set _RBearing..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Set RBearing...|Ctl+R"), NULL, NULL, CVMenuSetWidth, MID_SetRBearing },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Remove Kern _Pairs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Remove Kern Pairs|No Shortcut"), NULL, NULL, CVMenuRemoveKern, MID_RemoveKerns },
+ { { (unichar_t *) N_("Remove VKern Pairs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Remove VKern Pairs|No Shortcut"), NULL, NULL, CVMenuRemoveVKern, MID_RemoveVKerns },
+ { { (unichar_t *) N_("Kern Pair Closeup..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Kern Pair Closeup...|No Shortcut"), NULL, NULL, CVMenuKPCloseup, MID_KPCloseup },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Set _Vertical Advance..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("Set Vertical Advance...|No Shortcut"), NULL, NULL, CVMenuSetWidth, MID_SetVWidth },
+ { NULL }
+};
+
+static GMenuItem2 pllist[] = {
+ { { (unichar_t *) N_("_Tools"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Tools|No Shortcut"), NULL, NULL, CVMenuPaletteShow, MID_Tools },
+ { { (unichar_t *) N_("_Layers"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'L' }, H_("Layers|No Shortcut"), NULL, NULL, CVMenuPaletteShow, MID_Layers },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Docked Palettes"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'D' }, H_("Docked Palettes|No Shortcut"), NULL, NULL, CVMenuPalettesDock, MID_DockPalettes },
+ { NULL }
+};
+
+static GMenuItem2 aplist[] = {
+ { { (unichar_t *) N_("_Detach"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'K' }, H_("Detach|No Shortcut"), NULL, NULL, CVMenuAPDetach },
+ { NULL }
+};
+
+static void aplistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SplineChar *sc = cv->sc, **glyphs;
+ SplineFont *sf = sc->parent;
+ AnchorPoint *ap, *found;
+ extern void GMenuItemArrayFree(GMenuItem *mi);
+ extern void GMenuItem2ArrayFree(GMenuItem2 *mi);
+ extern GMenuItem *GMenuItem2ArrayCopy(GMenuItem2 *mi, uint16 *cnt);
+ GMenuItem2 *mit;
+ int cnt;
+
+ found = NULL;
+ for ( ap=sc->anchor; ap!=NULL; ap=ap->next ) {
+ if ( ap->selected ) {
+ if ( found==NULL )
+ found = ap;
+ else {
+ /* Can't deal with two selected anchors */
+ found = NULL;
+ break;
+ }
+ }
+ }
+
+ GMenuItemArrayFree(mi->sub);
+ if ( found==NULL )
+ glyphs = NULL;
+ else
+ glyphs = GlyphsMatchingAP(sf,found);
+ if ( glyphs==NULL ) {
+ mi->sub = GMenuItem2ArrayCopy(aplist,NULL);
+ mi->sub->ti.disabled = (cv->apmine==NULL);
+return;
+ }
+
+ for ( cnt = 0; glyphs[cnt]!=NULL; ++cnt );
+ mit = gcalloc(cnt+2,sizeof(GMenuItem2));
+ mit[0] = aplist[0];
+ mit[0].ti.text = (unichar_t *) copy( (char *) mit[0].ti.text );
+ mit[0].ti.disabled = (cv->apmine==NULL);
+ for ( cnt = 0; glyphs[cnt]!=NULL; ++cnt ) {
+ mit[cnt+1].ti.text = (unichar_t *) copy(glyphs[cnt]->name);
+ mit[cnt+1].ti.text_is_1byte = true;
+ mit[cnt+1].ti.fg = mit[cnt+1].ti.bg = COLOR_DEFAULT;
+ mit[cnt+1].ti.userdata = glyphs[cnt];
+ mit[cnt+1].invoke = CVMenuAPAttachSC;
+ if ( glyphs[cnt]==cv->apsc )
+ mit[cnt+1].ti.checked = mit[cnt+1].ti.checkable = true;
+ }
+ free(glyphs);
+ mi->sub = GMenuItem2ArrayCopy(mit,NULL);
+ GMenuItem2ArrayFree(mit);
+}
+
+static GMenuItem2 cblist[] = {
+ { { (unichar_t *) N_("_Kern Pairs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'K' }, H_("Kern Pairs|No Shortcut"), NULL, NULL, CVMenuKernPairs, MID_KernPairs },
+ { { (unichar_t *) N_("_Anchored Pairs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Anchored Pairs|No Shortcut"), NULL, NULL, CVMenuAnchorPairs, MID_AnchorPairs },
+ { { (unichar_t *) N_("_Anchor Control..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'V' }, NULL, ap2list, ap2listbuild, NULL, MID_AnchorControl },
+ { { (unichar_t *) N_("Anchor _Glyph at Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'A' }, NULL, aplist, aplistcheck, NULL, MID_AnchorGlyph },
+ { { (unichar_t *) N_("_Ligatures"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'L' }, H_("Ligatures|No Shortcut"), NULL, NULL, CVMenuLigatures, MID_Ligatures },
+ NULL
+};
+
+static GMenuItem2 nplist[] = {
+ { { (unichar_t *) N_("PointNumbers|_None"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'K' }, H_("None|No Shortcut"), NULL, NULL, CVMenuNumberPoints, MID_PtsNone },
+ { { (unichar_t *) N_("TrueType"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'A' }, H_("TrueType|No Shortcut"), NULL, NULL, CVMenuNumberPoints, MID_PtsTrue },
+ { { (unichar_t *) NU_("PostScript®"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'L' }, H_("PostScript|No Shortcut"), NULL, NULL, CVMenuNumberPoints, MID_PtsPost },
+ { { (unichar_t *) N_("SVG"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'L' }, H_("SVG|No Shortcut"), NULL, NULL, CVMenuNumberPoints, MID_PtsSVG },
+ NULL
+};
+
+static GMenuItem2 vwlist[] = {
+ { { (unichar_t *) N_("_Fit"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Fit|Ctl+F"), NULL, NULL, CVMenuScale, MID_Fit },
+ { { (unichar_t *) N_("Z_oom out"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Zoom out|Alt+Ctl+-"), NULL, NULL, CVMenuScale, MID_ZoomOut },
+ { { (unichar_t *) N_("Zoom _in"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'i' }, H_("Zoom in|Alt+Ctl+Shft++"), NULL, NULL, CVMenuScale, MID_ZoomIn },
+#if HANYANG
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Display Compositions..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'i' }, H_("Display Compositions...|No Shortcut"), NULL, NULL, CVDisplayCompositions, MID_DisplayCompositions },
+#endif
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Next Glyph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'N' }, H_("Next Glyph|Ctl+]"), NULL, NULL, CVMenuChangeChar, MID_Next },
+ { { (unichar_t *) N_("_Prev Glyph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Prev Glyph|Ctl+["), NULL, NULL, CVMenuChangeChar, MID_Prev },
+ { { (unichar_t *) N_("Next _Defined Glyph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'D' }, H_("Next Defined Glyph|Alt+Ctl+]"), NULL, NULL, CVMenuChangeChar, MID_NextDef },
+ { { (unichar_t *) N_("Prev Defined Gl_yph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'a' }, H_("Prev Defined Glyph|Alt+Ctl+["), NULL, NULL, CVMenuChangeChar, MID_PrevDef },
+ { { (unichar_t *) N_("Form_er Glyph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'a' }, H_("Former Glyph|Ctl+Shft+<"), NULL, NULL, CVMenuChangeChar, MID_Former },
+ { { (unichar_t *) N_("_Goto"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'G' }, H_("Goto|Ctl+Shft+>"), NULL, NULL, CVMenuGotoChar, MID_Goto },
+ { { (unichar_t *) N_("Find In Font _View"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("Find In Font View|Ctl+Shft+<"), NULL, NULL, CVMenuFindInFontView, MID_FindInFontView },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Hide Poin_ts"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Hide Points|Ctl+D"), NULL, NULL, CVMenuShowHide, MID_HidePoints },
+ { { (unichar_t *) N_("_Number Points"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, NULL, nplist, nplistcheck },
+ { { (unichar_t *) N_("_Mark Extrema"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'M' }, H_("Mark Extrema|No Shortcut"), NULL, NULL, CVMenuMarkExtrema, MID_MarkExtrema },
+ { { (unichar_t *) N_("M_ark Points of Inflection"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'M' }, H_("Mark Points of Inflection|No Shortcut"), NULL, NULL, CVMenuMarkPointsOfInflection, MID_MarkPointsOfInflection },
+ { { (unichar_t *) N_("Show _Control Point Info"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'M' }, H_("Show Control Point Info|No Shortcut"), NULL, NULL, CVMenuShowCPInfo, MID_ShowCPInfo },
+ { { (unichar_t *) N_("Show Side B_earings"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'M' }, H_("Show Side Bearings|No Shortcut"), NULL, NULL, CVMenuShowSideBearings, MID_ShowSideBearings },
+ { { (unichar_t *) N_("Fi_ll"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'l' }, H_("Fill|No Shortcut"), NULL, NULL, CVMenuFill, MID_Fill },
+ { { (unichar_t *) N_("Sho_w Grid Fit..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'l' }, H_("Show Grid Fit...|No Shortcut"), NULL, NULL, CVMenuShowGridFit, MID_ShowGridFit },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, }},
+ { { (unichar_t *) N_("Com_binations"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'b' }, NULL, cblist, cblistcheck },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, }},
+ { { (unichar_t *) N_("Palette_s"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, NULL, pllist, pllistcheck },
+ { { (unichar_t *) N_("S_how Glyph Tabs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'R' }, H_("Show Glyph Tabs|No Shortcut"), NULL, NULL, CVMenuShowTabs, MID_ShowTabs },
+ { { (unichar_t *) N_("Hide _Rulers"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Hide Rulers|No Shortcut"), NULL, NULL, CVMenuShowHideRulers, MID_HideRulers },
+ { NULL }
+};
+
+static void CVMenuShowMMMask(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ uint32 changemask = (uint32) (intpt) mi->ti.userdata;
+ /* Change which mms get displayed in the "background" */
+
+ if ( mi->mid==MID_MMAll ) {
+ if ( (cv->mmvisible&changemask)==changemask ) cv->mmvisible = 0;
+ else cv->mmvisible = changemask;
+ } else if ( mi->mid == MID_MMNone ) {
+ if ( cv->mmvisible==0 ) cv->mmvisible = (1<<(cv->sc->parent->mm->instance_count+1))-1;
+ else cv->mmvisible = 0;
+ } else
+ cv->mmvisible ^= changemask;
+ GDrawRequestExpose(cv->v,NULL,false);
+}
+
+static GMenuItem2 mvlist[] = {
+ { { (unichar_t *) N_("SubFonts|_All"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0xffffffff, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, '\0' }, H_("All|No Shortcut"), NULL, NULL, CVMenuShowMMMask, MID_MMAll },
+ { { (unichar_t *) N_("SubFonts|_None"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, '\0' }, H_("None|No Shortcut"), NULL, NULL, CVMenuShowMMMask, MID_MMNone },
+ { NULL }
+};
+
+static void mvlistcheck(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ int i, base, j;
+ extern void GMenuItemArrayFree(GMenuItem *mi);
+ extern GMenuItem *GMenuItem2ArrayCopy(GMenuItem2 *mi, uint16 *cnt);
+ MMSet *mm = cv->sc->parent->mm;
+ uint32 submask;
+ SplineFont *sub;
+ GMenuItem2 *mml;
+
+ base = 3;
+ if ( mm==NULL )
+ mml = mvlist;
+ else {
+ mml = gcalloc(base+mm->instance_count+2,sizeof(GMenuItem2));
+ memcpy(mml,mvlist,sizeof(mvlist));
+ mml[base-1].ti.fg = mml[base-1].ti.bg = COLOR_DEFAULT;
+ mml[base-1].ti.line = true;
+ submask = 0;
+ for ( j = 0, i=base; j<mm->instance_count+1; ++i, ++j ) {
+ if ( j==0 )
+ sub = mm->normal;
+ else
+ sub = mm->instances[j-1];
+ mml[i].ti.text = uc_copy(sub->fontname);
+ mml[i].ti.checkable = true;
+ mml[i].ti.checked = (cv->mmvisible & (1<<j))?1:0;
+ mml[i].ti.userdata = (void *) (intpt) (1<<j);
+ mml[i].invoke = CVMenuShowMMMask;
+ mml[i].ti.fg = mml[i].ti.bg = COLOR_DEFAULT;
+ if ( sub==cv->sc->parent )
+ submask = (1<<j);
+ }
+ /* All */
+ mml[0].ti.userdata = (void *) (intpt) ((1<<j)-1);
+ mml[0].ti.checked = (cv->mmvisible == (uint32) (intpt) mml[0].ti.userdata);
+ /* None */
+ mml[1].ti.checked = (cv->mmvisible == 0 || cv->mmvisible == submask);
+ }
+ GMenuItemArrayFree(mi->sub);
+ mi->sub = GMenuItem2ArrayCopy(mml,NULL);
+ if ( mml!=mvlist ) {
+ for ( i=base; mml[i].ti.text!=NULL; ++i )
+ free( mml[i].ti.text);
+ free(mml);
+ }
+}
+
+static void CVMenuReblend(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ char *err;
+ MMSet *mm = cv->sc->parent->mm;
+
+ if ( mm==NULL || mm->apple || cv->sc->parent!=mm->normal )
+return;
+ err = MMBlendChar(mm,cv->sc->orig_pos);
+ if ( mm->normal->glyphs[cv->sc->orig_pos]!=NULL )
+ _SCCharChangedUpdate(mm->normal->glyphs[cv->sc->orig_pos],-1);
+ if ( err!=0 )
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_post_error(_("Bad Multiple Master Font"),err);
+#endif
+}
+
+static GMenuItem2 mmlist[] = {
+/* GT: Here (and following) MM means "MultiMaster" */
+ { { (unichar_t *) N_("MM _Reblend"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("MM Reblend|No Shortcut"), NULL, NULL, CVMenuReblend, MID_MMReblend },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, }},
+ { { (unichar_t *) N_("_View"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, NULL, mvlist, mvlistcheck },
+ { NULL }
+};
+
+static void CVMenuShowSubChar(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ SplineFont *new = mi->ti.userdata;
+ /* Change to the same char in a different instance font of the mm */
+
+ CVChangeSC(cv,SFMakeChar(new,cv->fv->map,CVCurEnc(cv)));
+ cv->layerheads[dm_grid] = &new->grid;
+}
+
+static void mmlistcheck(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+ int i, base, j;
+ extern void GMenuItemArrayFree(GMenuItem *mi);
+ extern GMenuItem *GMenuItem2ArrayCopy(GMenuItem2 *mi, uint16 *cnt);
+ MMSet *mm = cv->sc->parent->mm;
+ SplineFont *sub;
+ GMenuItem2 *mml;
+
+ base = sizeof(mmlist)/sizeof(mmlist[0]);
+ if ( mm==NULL )
+ mml = mmlist;
+ else {
+ mml = gcalloc(base+mm->instance_count+2,sizeof(GMenuItem2));
+ memcpy(mml,mmlist,sizeof(mmlist));
+ mml[base-1].ti.fg = mml[base-1].ti.bg = COLOR_DEFAULT;
+ mml[base-1].ti.line = true;
+ for ( j = 0, i=base; j<mm->instance_count+1; ++i, ++j ) {
+ if ( j==0 )
+ sub = mm->normal;
+ else
+ sub = mm->instances[j-1];
+ mml[i].ti.text = uc_copy(sub->fontname);
+ mml[i].ti.checkable = true;
+ mml[i].ti.checked = sub==cv->sc->parent;
+ mml[i].ti.userdata = sub;
+ mml[i].invoke = CVMenuShowSubChar;
+ mml[i].ti.fg = mml[i].ti.bg = COLOR_DEFAULT;
+ }
+ }
+ mml[0].ti.disabled = (mm==NULL || cv->sc->parent!=mm->normal || mm->apple);
+ GMenuItemArrayFree(mi->sub);
+ mi->sub = GMenuItem2ArrayCopy(mml,NULL);
+ if ( mml!=mmlist ) {
+ for ( i=base; mml[i].ti.text!=NULL; ++i )
+ free( mml[i].ti.text);
+ free(mml);
+ }
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void CVMenuContextualHelp(GWindow base,struct gmenuitem *mi,GEvent *e) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void CharViewMenu_ContextualHelp(GtkMenuItem *menuitem, gpointer user_data) {
+# endif
+ help("charview.html");
+}
+
+static GMenuItem2 mblist[] = {
+ { { (unichar_t *) N_("_File"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, NULL, fllist, fllistcheck },
+ { { (unichar_t *) N_("_Edit"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'E' }, NULL, edlist, edlistcheck },
+ { { (unichar_t *) N_("_Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, NULL, ptlist, ptlistcheck },
+ { { (unichar_t *) N_("E_lement"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'l' }, NULL, ellist, ellistcheck },
+ { { (unichar_t *) N_("H_ints"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, NULL, htlist, htlistcheck },
+ { { (unichar_t *) N_("_View"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'V' }, NULL, vwlist, vwlistcheck },
+ { { (unichar_t *) N_("_Metrics"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, NULL, mtlist, mtlistcheck },
+/* GT: Here (and following) MM means "MultiMaster" */
+ { { (unichar_t *) N_("MM"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, NULL, mmlist, mmlistcheck },
+ { { (unichar_t *) N_("_Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'W' }, NULL, wnmenu, CVWindowMenuBuild },
+ { { (unichar_t *) N_("_Help"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, NULL, helplist, NULL },
+ { NULL }
+};
+
+static GMenuItem2 mblist_nomm[] = {
+ { { (unichar_t *) N_("_File"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, NULL, fllist, fllistcheck },
+ { { (unichar_t *) N_("_Edit"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'E' }, NULL, edlist, edlistcheck },
+ { { (unichar_t *) N_("_Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, NULL, ptlist, ptlistcheck },
+ { { (unichar_t *) N_("E_lement"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'l' }, NULL, ellist, ellistcheck },
+ { { (unichar_t *) N_("H_ints"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, NULL, htlist, htlistcheck },
+ { { (unichar_t *) N_("_View"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'V' }, NULL, vwlist, vwlistcheck },
+ { { (unichar_t *) N_("_Metrics"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, NULL, mtlist, mtlistcheck },
+ { { (unichar_t *) N_("_Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'W' }, NULL, wnmenu, CVWindowMenuBuild },
+ { { (unichar_t *) N_("_Help"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, NULL, helplist, NULL },
+ { NULL }
+};
+
+static void _CharViewCreate(CharView *cv, SplineChar *sc, FontView *fv,int enc) {
+ GRect pos;
+ GWindowAttrs wattrs;
+ GGadgetData gd;
+ int sbsize;
+ FontRequest rq;
+ int as, ds, ld;
+ extern int updateflex;
+ static unichar_t fixed[] = { 'f','i','x','e','d',',','c','l','e','a','r','l','y','u',',','u','n','i','f','o','n','t', '\0' };
+ static unichar_t *infofamily=NULL;
+ extern int cv_auto_goto;
+
+ if ( !cvcolsinited )
+ CVColInit();
+
+ if ( sc->views==NULL && updateflex )
+ SplineCharIsFlexible(sc);
+
+ cv->sc = sc;
+ cv->scale = .5;
+ cv->xoff = cv->yoff = 20;
+ cv->next = sc->views;
+ sc->views = cv;
+ cv->fv = fv;
+ cv->map_of_enc = fv->map;
+ cv->enc = enc;
+
+ cv->drawmode = dm_fore;
+
+ cv->showback = CVShows.showback;
+ cv->showfore = CVShows.showfore;
+ cv->showgrids = CVShows.showgrids;
+ cv->showhhints = CVShows.showhhints;
+ cv->showvhints = CVShows.showvhints;
+ cv->showdhints = CVShows.showdhints;
+ cv->showpoints = CVShows.showpoints;
+ cv->showrulers = CVShows.showrulers;
+ cv->showfilled = CVShows.showfilled;
+ cv->showrounds = CVShows.showrounds;
+ cv->showmdx = CVShows.showmdx;
+ cv->showmdy = CVShows.showmdy;
+ cv->showhmetrics = CVShows.showhmetrics;
+ cv->showvmetrics = CVShows.showvmetrics;
+ cv->markextrema = CVShows.markextrema;
+ cv->showsidebearings = CVShows.showsidebearings;
+ cv->markpoi = CVShows.markpoi;
+ cv->showblues = CVShows.showblues;
+ cv->showfamilyblues = CVShows.showfamilyblues;
+ cv->showanchor = CVShows.showanchor;
+ cv->showcpinfo = CVShows.showcpinfo;
+ cv->showtabs = CVShows.showtabs;
+
+ cv->infoh = 13;
+ cv->rulerh = 13;
+
+ GDrawGetSize(cv->gw,&pos);
+ memset(&gd,0,sizeof(gd));
+ gd.pos.y = cv->mbh+cv->infoh;
+ gd.pos.width = sbsize = GDrawPointsToPixels(cv->gw,_GScrollBar_Width);
+ gd.pos.height = pos.height-cv->mbh-cv->infoh - sbsize;
+ gd.pos.x = pos.width-sbsize;
+ gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
+ cv->vsb = GScrollBarCreate(cv->gw,&gd,cv);
+
+ gd.pos.y = pos.height-sbsize; gd.pos.height = sbsize;
+ gd.pos.width = pos.width - sbsize;
+ gd.pos.x = 0;
+ gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels;
+ cv->hsb = GScrollBarCreate(cv->gw,&gd,cv);
+
+ GDrawGetSize(cv->gw,&pos);
+ pos.y = cv->mbh+cv->infoh; pos.height -= cv->mbh + sbsize + cv->infoh;
+ pos.x = 0; pos.width -= sbsize;
+ if ( cv->showrulers ) {
+ pos.y += cv->rulerh; pos.height -= cv->rulerh;
+ pos.x += cv->rulerh; pos.width -= cv->rulerh;
+ }
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor;
+ wattrs.event_masks = -1;
+ wattrs.cursor = ct_mypointer;
+ cv->v = GWidgetCreateSubWindow(cv->gw,&pos,v_e_h,cv,&wattrs);
+
+ if ( GDrawRequestDeviceEvents(cv->v,input_em_cnt,input_em)>0 ) {
+ /* Success! They've got a wacom tablet */
+ }
+
+ if ( infofamily==NULL ) {
+ infofamily = uc_copy(GResourceFindString("CharView.InfoFamily"));
+ if ( infofamily==NULL )
+ infofamily = fixed;
+ }
+
+ memset(&rq,0,sizeof(rq));
+ rq.family_name = infofamily;
+ rq.point_size = -7;
+ rq.weight = 400;
+ cv->small = GDrawInstanciateFont(GDrawGetDisplayOfWindow(cv->gw),&rq);
+ GDrawFontMetrics(cv->small,&as,&ds,&ld);
+ cv->sfh = as+ds; cv->sas = as;
+ rq.point_size = 10;
+ cv->normal = GDrawInstanciateFont(GDrawGetDisplayOfWindow(cv->gw),&rq);
+ GDrawFontMetrics(cv->normal,&as,&ds,&ld);
+ cv->nfh = as+ds; cv->nas = as;
+
+ cv->height = pos.height; cv->width = pos.width;
+ cv->gi.u.image = gcalloc(1,sizeof(struct _GImage));
+ cv->gi.u.image->image_type = it_mono;
+ cv->gi.u.image->clut = gcalloc(1,sizeof(GClut));
+ cv->gi.u.image->clut->trans_index = cv->gi.u.image->trans = 0;
+ cv->gi.u.image->clut->clut_len = 2;
+ cv->gi.u.image->clut->clut[0] = 0xffffff;
+ cv->gi.u.image->clut->clut[1] = backimagecol;
+ cv->b1_tool = cvt_pointer; cv->cb1_tool = cvt_pointer;
+ cv->b2_tool = cvt_magnify; cv->cb2_tool = cvt_ruler;
+ cv->s1_tool = cvt_freehand; cv->s2_tool = cvt_pen;
+ cv->er_tool = cvt_knife;
+ cv->showing_tool = cvt_pointer;
+ cv->pressed_tool = cv->pressed_display = cv->active_tool = cvt_none;
+ cv->layerheads[dm_fore] = &sc->layers[ly_fore];
+ cv->layerheads[dm_back] = &sc->layers[ly_back];
+ cv->layerheads[dm_grid] = &fv->sf->grid;
+
+#if HANYANG
+ if ( sc->parent->rules!=NULL && sc->compositionunit )
+ Disp_DefaultTemplate(cv);
+#endif
+
+ cv->olde.x = -1;
+
+ cv->ft_dpi = 72; cv->ft_pointsize = 12.0; cv->ft_ppem = 12;
+
+ /*GWidgetHidePalettes();*/
+ /*cv->tools = CVMakeTools(cv);*/
+ /*cv->layers = CVMakeLayers(cv);*/
+
+ CVFit(cv);
+ GDrawSetVisible(cv->v,true);
+ if ( cv_auto_goto ) /* Chinese input method steals hot key key-strokes */
+ cv->gic = GDrawCreateInputContext(cv->v,gic_root|gic_orlesser);
+ GDrawSetVisible(cv->gw,true);
+}
+
+void DefaultY(GRect *pos) {
+ static int nexty=0;
+ GRect size;
+
+ GDrawGetSize(GDrawGetRoot(NULL),&size);
+ if ( nexty!=0 ) {
+ FontView *fv;
+ int any=0, i;
+ BDFFont *bdf;
+ /* are there any open cv/bv windows? */
+ for ( fv = fv_list; fv!=NULL && !any; fv = fv->next ) {
+ for ( i=0; i<fv->sf->glyphcnt; ++i ) if ( fv->sf->glyphs[i]!=NULL ) {
+ if ( fv->sf->glyphs[i]->views!=NULL ) {
+ any = true;
+ break;
+ }
+ }
+ for ( bdf = fv->sf->bitmaps; bdf!=NULL && !any; bdf=bdf->next ) {
+ for ( i=0; i<bdf->glyphcnt; ++i ) if ( bdf->glyphs[i]!=NULL ) {
+ if ( bdf->glyphs[i]->views!=NULL ) {
+ any = true;
+ break;
+ }
+ }
+ }
+ }
+ if ( !any ) nexty = 0;
+ }
+ pos->y = nexty;
+ nexty += 200;
+ if ( nexty+pos->height > size.height )
+ nexty = 0;
+}
+
+static void CharViewInit(void);
+
+CharView *CharViewCreate(SplineChar *sc, FontView *fv,int enc) {
+ CharView *cv = gcalloc(1,sizeof(CharView));
+ GWindowAttrs wattrs;
+ GRect pos, zoom;
+ GWindow gw;
+ GGadgetData gd;
+ GTabInfo aspects[2];
+ GRect gsize;
+ char buf[300];
+
+ CharViewInit();
+
+ cv->sc = sc;
+ cv->fv = fv;
+ cv->enc = enc;
+ cv->map_of_enc = fv->map; /* I know this is done again in _CharViewCreate, but it needs to be done before creating the title */
+
+ SCLigCaretCheck(sc,false);
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_utf8_ititle;
+ wattrs.event_masks = -1;
+ wattrs.cursor = ct_mypointer;
+ wattrs.utf8_icon_title = CVMakeTitles(cv,buf);
+ wattrs.utf8_window_title = buf;
+ wattrs.icon = CharIcon(cv, fv);
+ if ( wattrs.icon )
+ wattrs.mask |= wam_icon;
+ pos.x = GGadgetScale(104)+6; pos.width=pos.height = 540;
+ DefaultY(&pos);
+
+ cv->gw = gw = GDrawCreateTopWindow(NULL,&pos,cv_e_h,cv,&wattrs);
+ free( (unichar_t *) wattrs.icon_title );
+
+ GDrawGetSize(GDrawGetRoot(screen_display),&zoom);
+ zoom.x = CVPalettesWidth(); zoom.width -= zoom.x-10;
+ zoom.height -= 30; /* Room for title bar & such */
+ GDrawSetZoom(gw,&zoom,-1);
+
+ memset(&gd,0,sizeof(gd));
+ gd.flags = gg_visible | gg_enabled;
+ helplist[0].invoke = CVMenuContextualHelp;
+ gd.u.menu2 = sc->parent->mm==NULL ? mblist_nomm : mblist;
+ cv->mb = GMenu2BarCreate( gw, &gd, NULL);
+ GGadgetGetSize(cv->mb,&gsize);
+ cv->mbh = gsize.height;
+
+ memset(aspects,0,sizeof(aspects));
+ aspects[0].text = (unichar_t *) sc->name;
+ aspects[0].text_is_1byte = true;
+ /* NOT visible until we add a second glyph to the stack */
+ gd.flags = gg_enabled|gg_tabset_nowindow|gg_tabset_scroll|gg_pos_in_pixels;
+ gd.u.menu = NULL;
+ gd.u.tabs = aspects;
+ gd.pos.x = 0;
+ gd.pos.y = cv->mbh;
+ gd.handle_controlevent = CVChangeToFormer;
+ cv->tabs = GTabSetCreate( gw, &gd, NULL );
+ cv->former_cnt = 1;
+ cv->former_names[0] = copy(sc->name);
+ GGadgetTakesKeyboard(cv->tabs,false);
+
+ _CharViewCreate(cv,sc,fv,enc);
+return( cv );
+}
+
+void CharViewFree(CharView *cv) {
+ int i;
+
+ BDFCharFree(cv->filled);
+ if ( cv->ruler_w ) {
+ GDrawDestroyWindow(cv->ruler_w);
+ cv->ruler_w = NULL;
+ }
+ free(cv->gi.u.image->clut);
+ free(cv->gi.u.image);
+#if HANYANG
+ if ( cv->jamodisplay!=NULL )
+ Disp_DoFinish(cv->jamodisplay,true);
+#endif
+
+ CVDebugFree(cv->dv);
+
+ SplinePointListsFree(cv->gridfit);
+ FreeType_FreeRaster(cv->oldraster);
+ FreeType_FreeRaster(cv->raster);
+
+ CVDebugFree(cv->dv);
+
+ for ( i=0; i<cv->former_cnt; ++i )
+ free(cv->former_names[i]);
+
+ free(cv);
+}
+
+int CVValid(SplineFont *sf, SplineChar *sc, CharView *cv) {
+ /* A charview may have been closed. A splinechar may have been removed */
+ /* from a font */
+ CharView *test;
+
+ if ( cv->sc!=sc || sc->parent!=sf )
+return( false );
+ if ( sc->orig_pos<0 || sc->orig_pos>sf->glyphcnt )
+return( false );
+ if ( sf->glyphs[sc->orig_pos]!=sc )
+return( false );
+ for ( test=sc->views; test!=NULL; test=test->next )
+ if ( test==cv )
+return( true );
+
+return( false );
+}
+
+static void sv_fllistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_Recent:
+ mi->ti.disabled = !RecentFilesAny();
+ break;
+ }
+ }
+}
+
+static void sv_pllistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ cv_pllistcheck(cv,mi,e);
+}
+
+static void sv_edlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ cv_edlistcheck(cv,mi,e,false);
+}
+
+static void sv_ptlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ cv_ptlistcheck(cv,mi,e);
+}
+
+static void sv_allistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ cv_allistcheck(cv,mi,e);
+}
+
+static void sv_ellistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ cv_ellistcheck(cv,mi,e,false);
+}
+
+static void sv_sllistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ cv_sllistcheck(cv,mi,e);
+}
+
+static void sv_vwlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ cv_vwlistcheck(cv,mi,e);
+}
+
+static void SVMenuSave(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ _FVMenuSave(sv->fv);
+}
+
+static void SVMenuSaveAs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ _FVMenuSaveAs(sv->fv);
+}
+
+static void SVMenuGenerate(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ _FVMenuGenerate(sv->fv,false);
+}
+
+static void SVSelectAll(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ if ( CVSetSel(cv,-1))
+ SCUpdateAll(cv->sc);
+}
+
+static void SVSelectNone(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ if ( CVClearSel(cv))
+ SCUpdateAll(cv->sc);
+}
+
+static void SVMenuNextPrevPt(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ CVNextPrevPt(cv,mi);
+}
+
+static void SVMenuNextPrevCPt(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ CVNextPrevCPt(cv,mi);
+}
+
+static void SVUndo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ CVDoUndo(cv);
+}
+
+static void SVRedo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ CVDoRedo(cv);
+}
+
+static void SVCut(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ _CVCut(cv);
+}
+
+static void SVCopy(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ _CVCopy(cv);
+}
+
+static void SVPaste(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ _CVPaste(cv);
+}
+
+static void SVClear(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+
+ if ( !CVAnySel(cv,NULL,NULL,NULL,NULL))
+return;
+ CVDoClear(cv);
+ CVCharChangedUpdate(cv);
+}
+
+static void SVMerge(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ _CVMerge(cv,false);
+}
+
+static void SVElide(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ _CVMerge(cv,true);
+}
+
+static void SVJoin(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ _CVJoin(cv);
+}
+
+static void SVUnlinkRef(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ _CVUnlinkRef(cv);
+}
+
+static void SVRemoveUndoes(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+
+ UndoesFree(sv->cv_srch.layerheads[sv->cv_srch.drawmode]->undoes);
+ UndoesFree(sv->cv_srch.layerheads[sv->cv_srch.drawmode]->redoes);
+ sv->cv_srch.layerheads[sv->cv_srch.drawmode]->undoes = sv->cv_srch.layerheads[sv->cv_srch.drawmode]->redoes = NULL;
+
+ UndoesFree(sv->cv_rpl.layerheads[sv->cv_rpl.drawmode]->undoes);
+ UndoesFree(sv->cv_rpl.layerheads[sv->cv_rpl.drawmode]->redoes);
+ sv->cv_rpl.layerheads[sv->cv_rpl.drawmode]->undoes = sv->cv_rpl.layerheads[sv->cv_rpl.drawmode]->redoes = NULL;
+}
+
+static void SVMenuPointType(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ _CVMenuPointType(cv,mi);
+}
+
+static void SVMenuMakeFirst(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ _CVMenuMakeFirst(cv);
+}
+
+static void SVMenuConstrain(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ CVConstrainSelection(cv,mi->mid==MID_Average?0:
+ mi->mid==MID_SpacePts?1:
+ 2);
+}
+
+static void SVMenuMakeParallel(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ CVMakeParallel(cv);
+}
+
+static void SVMenuFontInfo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ DelayEvent(FontMenuFontInfo,sv->fv);
+}
+
+static void SVMenuGetInfo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ SplinePoint *sp; SplineSet *spl; RefChar *r; ImageList *im;
+
+ if( !CVOneThingSel(cv,&sp,&spl,&r,&im,NULL))
+return;
+ CVGetInfo(cv);
+}
+
+static void SVMenuTransform(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ int anysel = CVAnySel(cv,NULL,NULL,NULL,NULL);
+ TransformDlgCreate(cv,transfunc,getorigin,!anysel && cv->drawmode==dm_fore,
+ cvt_none);
+}
+
+static void SVMenuStroke(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ CVStroke(cv);
+}
+
+static void SVMenuOverlap(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ int anysel;
+
+ (void) CVAnySel(cv,&anysel,NULL,NULL,NULL);
+ _CVMenuOverlap(cv,anysel ? over_rmselected: over_remove);
+}
+
+static void SVMenuSimplify(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ static struct simplifyinfo smpl = { sf_normal,.75,.05,0 };
+ smpl.err = (cv->sc->parent->ascent+cv->sc->parent->descent)/1000.;
+ smpl.linelenmax = (cv->sc->parent->ascent+cv->sc->parent->descent)/100.;
+ CVPreserveState(cv);
+ cv->layerheads[cv->drawmode]->splines = SplineCharSimplify(cv->sc,cv->layerheads[cv->drawmode]->splines,&smpl);
+ CVCharChangedUpdate(cv);
+}
+
+static void SVMenuCleanupGlyph(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ static struct simplifyinfo smpl = { sf_cleanup };
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ CVPreserveState(cv);
+ cv->layerheads[cv->drawmode]->splines = SplineCharSimplify(cv->sc,cv->layerheads[cv->drawmode]->splines,&smpl);
+ CVCharChangedUpdate(cv);
+}
+
+static void SVMenuAddExtrema(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ _CVMenuAddExtrema(cv);
+}
+
+static void SVMenuRound2Int(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ _CVMenuRound2Int(cv,1.0);
+}
+
+static void SVMenuDir(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ _CVMenuDir(cv,mi);
+}
+
+static void SVMenuCorrectDir(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ int changed=false;
+ CVPreserveState(cv);
+ cv->layerheads[cv->drawmode]->splines = SplineSetsCorrect(cv->layerheads[cv->drawmode]->splines,&changed);
+ if ( changed )
+ CVCharChangedUpdate(cv);
+}
+
+static void SVMenuPaletteShow(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+
+ CVPaletteSetVisible(cv, mi->mid==MID_Tools, !CVPaletteIsVisible(cv, mi->mid==MID_Tools));
+}
+
+static void SVMenuScale(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+ _CVMenuScale(cv,mi);
+}
+
+static void SVMenuShowHide(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+
+ cv->showpoints = !cv->showpoints;
+ GDrawRequestExpose(cv->v,NULL,false);
+}
+
+static void SVMenuMarkExtrema(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+
+ cv->markextrema = !cv->markextrema;
+ GDrawRequestExpose(cv->v,NULL,false);
+}
+
+static void SVMenuShowHideRulers(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ SearchView *sv = (SearchView *) GDrawGetUserData(gw);
+ CharView *cv = sv->cv_srch.inactive ? &sv->cv_rpl : &sv->cv_srch;
+
+ if ( cv->showrulers == sv->cv_srch.showrulers )
+ _CVMenuShowHideRulers(&sv->cv_srch);
+ if ( cv->showrulers == sv->cv_rpl.showrulers )
+ _CVMenuShowHideRulers(&sv->cv_rpl);
+}
+
+static GMenuItem2 sv_fllist[] = {
+ { { (unichar_t *) N_("Font|_New"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'N' }, H_("New|Ctl+N"), NULL, NULL, MenuNew },
+ { { (unichar_t *) N_("_Open"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'O' }, H_("Open|Ctl+O"), NULL, NULL, MenuOpen },
+ { { (unichar_t *) N_("Recen_t"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 't' }, NULL, dummyitem, MenuRecentBuild, NULL, MID_Recent },
+ { { (unichar_t *) N_("_Close"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Close|Ctl+Shft+Q"), NULL, NULL, SVMenuClose },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Save"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Save|Ctl+S"), NULL, NULL, SVMenuSave },
+ { { (unichar_t *) N_("S_ave as..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'a' }, H_("Save as...|Ctl+Shft+S"), NULL, NULL, SVMenuSaveAs },
+ { { (unichar_t *) N_("_Generate Fonts..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'G' }, H_("Generate Fonts...|Ctl+Shft+G"), NULL, NULL, SVMenuGenerate },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Quit"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'Q' }, H_("Quit|Ctl+Q"), NULL, NULL, MenuExit },
+ { NULL }
+};
+
+static GMenuItem2 sv_sllist[] = {
+ { { (unichar_t *) N_("Select _All"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Select All|Ctl+A"), NULL, NULL, SVSelectAll, MID_SelAll },
+ { { (unichar_t *) N_("_Deselect All"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Deselect All|Escape"), NULL, NULL, SVSelectNone, MID_SelNone },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_First Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("First Point|Ctl+."), NULL, NULL, SVMenuNextPrevPt, MID_FirstPt },
+ { { (unichar_t *) N_("First P_oint, Next Contour"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("First Point, Next Contour|Alt+Ctl+."), NULL, NULL, SVMenuNextPrevPt, MID_FirstPtNextCont },
+ { { (unichar_t *) N_("_Next Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'N' }, H_("Next Point|Ctl+Shft+}"), NULL, NULL, SVMenuNextPrevPt, MID_NextPt },
+ { { (unichar_t *) N_("_Prev Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Prev Point|Ctl+Shft+{"), NULL, NULL, SVMenuNextPrevPt, MID_PrevPt },
+ { { (unichar_t *) N_("Ne_xt Control Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'x' }, H_("Next Control Point|Ctl+;"), NULL, NULL, SVMenuNextPrevCPt, MID_NextCP },
+ { { (unichar_t *) N_("P_rev Control Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'r' }, H_("Prev Control Point|Ctl+Shft+:"), NULL, NULL, SVMenuNextPrevCPt, MID_PrevCP },
+ { NULL }
+};
+
+static GMenuItem2 sv_edlist[] = {
+ { { (unichar_t *) N_("_Undo"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'U' }, H_("Undo|Ctl+Z"), NULL, NULL, SVUndo, MID_Undo },
+ { { (unichar_t *) N_("_Redo"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Redo|Ctl+Y"), NULL, NULL, SVRedo, MID_Redo },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Cu_t"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 't' }, H_("Cut|Ctl+X"), NULL, NULL, SVCut, MID_Cut },
+ { { (unichar_t *) N_("_Copy"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Copy|Ctl+C"), NULL, NULL, SVCopy, MID_Copy },
+ { { (unichar_t *) N_("_Paste"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Paste|Ctl+V"), NULL, NULL, SVPaste, MID_Paste },
+ { { (unichar_t *) N_("C_lear"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Clear|Delete"), NULL, NULL, SVClear, MID_Clear },
+ { { (unichar_t *) N_("_Merge"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Merge|Ctl+M"), NULL, NULL, SVMerge, MID_Merge },
+ { { (unichar_t *) N_("_Elide"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'E' }, H_("Elide|Alt+Ctl+M"), NULL, NULL, SVElide, MID_Elide },
+ { { (unichar_t *) N_("_Join"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'J' }, H_("Join|Ctl+Shft+J"), NULL, NULL, SVJoin, MID_Join },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Select"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, NULL, sv_sllist, sv_sllistcheck },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("U_nlink Reference"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'U' }, H_("Unlink Reference|Ctl+U"), NULL, NULL, SVUnlinkRef, MID_UnlinkRef },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Remo_ve Undoes"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'e' }, H_("Remove Undoes|No Shortcut"), NULL, NULL, SVRemoveUndoes, MID_RemoveUndoes },
+ { NULL }
+};
+
+static GMenuItem2 sv_ptlist[] = {
+ { { (unichar_t *) N_("_Curve"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'C' }, H_("Curve|Ctl+2"), NULL, NULL, SVMenuPointType, MID_Curve },
+ { { (unichar_t *) N_("C_orner"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'o' }, H_("Corner|Ctl+3"), NULL, NULL, SVMenuPointType, MID_Corner },
+ { { (unichar_t *) N_("_Tangent"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Tangent|Ctl+4"), NULL, NULL, SVMenuPointType, MID_Tangent },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Make First"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'r' }, H_("Make First|Ctl+1"), NULL, NULL, SVMenuMakeFirst, MID_MakeFirst },
+ { NULL }
+};
+
+static GMenuItem2 sv_allist[] = {
+/* GT: Align these points to their average position */
+ { { (unichar_t *) N_("_Average Points"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Average Points|Ctl+Shft+@"), NULL, NULL, SVMenuConstrain, MID_Average },
+ { { (unichar_t *) N_("_Space Points"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Space Points|Ctl+Shft+#"), NULL, NULL, SVMenuConstrain, MID_SpacePts },
+ { { (unichar_t *) N_("Space _Regions..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Space Regions...|No Shortcut"), NULL, NULL, SVMenuConstrain, MID_SpaceRegion },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Make _Parallel..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Make Parallel...|No Shortcut"), NULL, NULL, SVMenuMakeParallel, MID_MakeParallel },
+ { NULL }
+};
+
+static GMenuItem2 sv_ellist[] = {
+ { { (unichar_t *) N_("_Font Info..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Font Info...|Ctl+Shft+F"), NULL, NULL, SVMenuFontInfo },
+ { { (unichar_t *) N_("Get _Info..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Get Info...|Ctl+I"), NULL, NULL, SVMenuGetInfo, MID_GetInfo },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Transform..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Transform...|No Shortcut"), NULL, NULL, SVMenuTransform },
+ { { (unichar_t *) N_("_Expand Stroke..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'E' }, H_("Expand Stroke...|Ctl+Shft+E"), NULL, NULL, SVMenuStroke, MID_Stroke },
+ { { (unichar_t *) N_("_Remove Overlap"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'v' }, H_("Remove Overlap|Ctl+Shft+O"), NULL, NULL, SVMenuOverlap, MID_RmOverlap },
+ { { (unichar_t *) N_("_Simplify"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Simplify|Ctl+Shft+M"), NULL, NULL, SVMenuSimplify, MID_Simplify },
+ { { (unichar_t *) N_("Clea_nup Glyph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'n' }, H_("Cleanup Glyph|No Shortcut"), NULL, NULL, SVMenuCleanupGlyph, MID_CleanupGlyph },
+ { { (unichar_t *) N_("Add E_xtrema"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'x' }, H_("Add Extrema|Ctl+Shft+X"), NULL, NULL, SVMenuAddExtrema, MID_AddExtrema },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("A_lign"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'l' }, NULL, sv_allist, sv_allistcheck },
+ { { (unichar_t *) N_("To _Int"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("To Int|Ctl+Shft+_"), NULL, NULL, SVMenuRound2Int, MID_Round },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Cl_ockwise"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'o' }, H_("Clockwise|No Shortcut"), NULL, NULL, SVMenuDir, MID_Clockwise },
+ { { (unichar_t *) N_("Cou_nter Clockwise"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'n' }, H_("Counter Clockwise|No Shortcut"), NULL, NULL, SVMenuDir, MID_Counter },
+ { { (unichar_t *) N_("_Correct Direction"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'D' }, H_("Correct Direction|Ctl+Shft+D"), NULL, NULL, SVMenuCorrectDir, MID_Correct },
+ { NULL }
+};
+
+static GMenuItem2 sv_pllist[] = {
+ { { (unichar_t *) N_("_Tools"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Tools|No Shortcut"), NULL, NULL, SVMenuPaletteShow, MID_Tools },
+ { { (unichar_t *) N_("_Layers"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'L' }, H_("Layers|No Shortcut"), NULL, NULL, SVMenuPaletteShow, MID_Layers },
+ { { (unichar_t *) N_("_Docked Palettes"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'D' }, H_("Docked Palettes|No Shortcut"), NULL, NULL, CVMenuPalettesDock, MID_DockPalettes },
+ { NULL }
+};
+
+static GMenuItem2 sv_vwlist[] = {
+ { { (unichar_t *) N_("_Fit"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Fit|Ctl+F"), NULL, NULL, SVMenuScale, MID_Fit },
+ { { (unichar_t *) N_("Z_oom out"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Zoom out|Alt+Ctl+-"), NULL, NULL, SVMenuScale, MID_ZoomOut },
+ { { (unichar_t *) N_("Zoom _in"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'i' }, H_("Zoom in|Alt+Ctl+Shft++"), NULL, NULL, SVMenuScale, MID_ZoomIn },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Hide Poin_ts"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Hide Points|Ctl+D"), NULL, NULL, SVMenuShowHide, MID_HidePoints },
+ { { (unichar_t *) N_("_Mark Extrema"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'M' }, H_("Mark Extrema|No Shortcut"), NULL, NULL, SVMenuMarkExtrema, MID_MarkExtrema },
+ /*{ { (unichar_t *) N_("Fi_ll"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'l' }, '\0', 0, NULL, NULL, SVMenuFill, MID_Fill },*/
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, }},
+ { { (unichar_t *) N_("_Palettes"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, NULL, sv_pllist, sv_pllistcheck },
+ { { (unichar_t *) N_("Hide _Rulers"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Hide Rulers|No Shortcut"), NULL, NULL, SVMenuShowHideRulers, MID_HideRulers },
+ { NULL }
+};
+
+static GMenuItem2 sv_mblist[] = {
+ { { (unichar_t *) N_("_File"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, NULL, sv_fllist, sv_fllistcheck },
+ { { (unichar_t *) N_("_Edit"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'E' }, NULL, sv_edlist, sv_edlistcheck },
+ { { (unichar_t *) N_("_Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, NULL, sv_ptlist, sv_ptlistcheck },
+ { { (unichar_t *) N_("E_lement"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'l' }, NULL, sv_ellist, sv_ellistcheck },
+ { { (unichar_t *) N_("_View"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'V' }, NULL, sv_vwlist, sv_vwlistcheck },
+ { { (unichar_t *) N_("_Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'W' }, NULL, wnmenu, SVWindowMenuBuild },
+ { { (unichar_t *) N_("_Help"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, NULL, helplist, NULL },
+ { NULL }
+};
+
+static void CharViewInit(void) {
+ int i;
+ static int done = false;
+
+ if ( done )
+return;
+ done = true;
+
+ mb2DoGetText(sv_mblist);
+ mb2DoGetText(mblist);
+ for ( i=0; mblist_nomm[i].ti.text!=NULL; ++i )
+ mblist_nomm[i].ti.text = (unichar_t *) _((char *) mblist_nomm[i].ti.text);
+}
+
+static int sv_cv_e_h(GWindow gw, GEvent *event) {
+ CharView *cv = (CharView *) GDrawGetUserData(gw);
+
+ switch ( event->type ) {
+ case et_expose:
+ InfoExpose(cv,gw,event);
+ CVLogoExpose(cv,gw,event);
+ break;
+ case et_char:
+ SVChar(cv->searcher,event);
+ break;
+ case et_charup:
+ CVCharUp(cv,event);
+ break;
+ case et_controlevent:
+ switch ( event->u.control.subtype ) {
+ case et_scrollbarchange:
+ if ( event->u.control.g == cv->hsb )
+ CVHScroll(cv,&event->u.control.u.sb);
+ else
+ CVVScroll(cv,&event->u.control.u.sb);
+ break;
+ }
+ break;
+ case et_map:
+ if ( event->u.map.is_visible )
+ CVPaletteActivate(cv);
+ else
+ CVPalettesHideIfMine(cv);
+ break;
+ case et_resize:
+ if ( event->u.resize.sized )
+ CVResize(cv);
+ break;
+ case et_destroy:
+ if ( cv->backimgs!=NULL ) {
+ GDrawDestroyWindow(cv->backimgs);
+ cv->backimgs = NULL;
+ }
+ break;
+ case et_mouseup: case et_mousedown:
+ GGadgetEndPopup();
+ CVPaletteActivate(cv);
+ break;
+ case et_mousemove:
+ if ( event->u.mouse.y>cv->mbh ) {
+ int enc = CVCurEnc(cv);
+ SCPreparePopup(cv->gw,cv->sc,cv->fv->map->remap,enc,
+ UniFromEnc(enc,cv->fv->map->enc));
+ }
+ break;
+ }
+return( true );
+}
+
+void SVCharViewInits(SearchView *sv) {
+ GGadgetData gd;
+ GWindowAttrs wattrs;
+ GRect pos, gsize;
+
+ CharViewInit();
+
+ sv->cv_srch.searcher = sv;
+ sv->cv_rpl.inactive = true;
+ sv->cv_rpl.searcher = sv;
+
+ memset(&gd,0,sizeof(gd));
+ gd.flags = gg_visible | gg_enabled;
+ helplist[0].invoke = CVMenuContextualHelp;
+ gd.u.menu2 = sv_mblist;
+ sv->mb = GMenu2BarCreate( sv->gw, &gd, NULL);
+ GGadgetGetSize(sv->mb,&gsize);
+ sv->mbh = gsize.height;
+
+ sv->dummy_fv.map = &sv->dummy_map;
+ sv->dummy_map.map = sv->map;
+ sv->dummy_map.backmap = sv->backmap;
+ sv->dummy_map.enccount = sv->dummy_map.encmax = sv->dummy_map.backmax = 2;
+ sv->dummy_map.enc = &custom;
+
+ pos.y = sv->mbh+sv->fh+10; pos.height = 220;
+ pos.width = pos.height; pos.x = 10+pos.width+20; /* Do replace first so palettes appear propperly */
+ sv->rpl_x = pos.x; sv->cv_y = pos.y;
+ sv->cv_height = pos.height; sv->cv_width = pos.width;
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor;
+ wattrs.event_masks = -1;
+ wattrs.cursor = ct_mypointer;
+ sv->cv_rpl.gw = GWidgetCreateSubWindow(sv->gw,&pos,sv_cv_e_h,&sv->cv_rpl,&wattrs);
+ _CharViewCreate(&sv->cv_rpl, &sv->sc_rpl, &sv->dummy_fv, 1);
+
+ pos.x = 10;
+ sv->cv_srch.gw = GWidgetCreateSubWindow(sv->gw,&pos,sv_cv_e_h,&sv->cv_srch,&wattrs);
+ _CharViewCreate(&sv->cv_srch, &sv->sc_srch, &sv->dummy_fv, 0);
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/configure-pfaedit.h b/Build/source/libs/luafontforge/fontforge/fontforge/configure-pfaedit.h
new file mode 100644
index 00000000000..b84bd4fdb78
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/configure-pfaedit.h
@@ -0,0 +1,290 @@
+/* Copyright (C) 2002-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _CONFIG_FONTFORGE_H_
+#define _CONFIG_FONTFORGE_H_
+
+/* !!!!!!!!!!!!!!!!! Experimental. Don't try to use it yet !!!!!!!!!!!!!!!!! */
+/* FontForge can be configured with a windowing UI based on my widgets (gdraw)*/
+/* the gtk widget set, or finally with no windowing UI. */
+/* It is probably best to used gtk if it is available */
+/* */
+/* #define FONTFORGE_CONFIG_GTK */
+/* #define FONTFORGE_CONFIG_GDRAW */
+/* #define FONTFORGE_CONFIG_NO_WINDOWING_UI */
+/* */
+/* Can be set from configure --with-gtk, --with-gdraw, --with-noui */
+#ifdef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# undef FONTFORGE_CONFIG_GDRAW
+# undef FONTFORGE_CONFIG_GTK
+#elif defined(FONTFORGE_CONFIG_GTK)
+# undef FONTFORGE_CONFIG_GDRAW
+#elif !defined(FONTFORGE_CONFIG_GDRAW)
+/* If nothing defined, default to traditional setting. At least for now */
+# define FONTFORGE_CONFIG_GDRAW
+#endif
+
+
+/* Making FontForge handle more of the capabilities of type3 & svg fonts is not*/
+/* something most people will want. It wastes space too. So I thought I'd */
+/* make it conditional. */
+/* */
+/* #define FONTFORGE_CONFIG_TYPE3 */
+/* */
+/* It allows people to have images in a font, multiple layers, strokes, fills */
+/* transparencies, etc. (type3 doesn't support transparency, svg doesn't do */
+/* images) */
+/* Can be set from configure --with-multilayer */
+
+
+/* Making FontForge handle device tables uses up more space, so I want */
+/* people to be able to turn it off if space is an issue and device tables */
+/* (ability to correct rounding errors in spacing, ie. kerning, at small */
+/* point sizes) aren't important. */
+/* */
+/* #define FONTFORGE_CONFIG_DEVICETABLES */
+/* */
+/* Can be set from configure --with-devicetables */
+
+
+/* Apple suggests using a sfnt version of 'true' for fonts designed for use */
+/* only on a mac (windows refuses such fonts). I generally prefer to have a */
+/* font work everywhere, so normally ff produces fonts with version 1.0 */
+/* Set this if you want Apple only fonts (produced when Apple mode is set and*/
+/* Opentype mode is unset in the Generate Fonts-Options dialog). */
+/* */
+/* #define FONTFORGE_CONFIG_APPLE_ONLY_TTF */
+/* */
+
+
+/* Nobody else puts apple unicode encodings into the name table. So I probably*/
+/* shouldn't either. But if someone wants them... */
+/* */
+/* #define FONTFORGE_CONFIG_APPLE_UNICODE_NAMES */
+/* */
+
+
+/* Sometimes I want to create a glyph which is a word, and this command */
+/* makes that easy */
+/* */
+/* #define FONTFORGE_CONFIG_PASTEAFTER */
+/* */
+/* The paste after command pastes the contents of the clipboard into the */
+/* current glyph, translates that by the advance width of the current glyph */
+/* and increments the advance width by the advance width of the clipboard */
+
+
+/* Someone asked for encoding GB12345. Neither libiconv nor iconv supports it.*/
+/* */
+/* #define FONTFORGE_CONFIG_GB12345 */
+/* */
+/* Can be set from configure --with-gb12345 */
+
+
+/* I doubt anyone but me will be interested in the tile path command, so I */
+/* don't include code for it by default, but if you do want it simply define */
+/* the following macro */
+/* */
+/* #define FONTFORGE_CONFIG_TILEPATH */
+/* */
+/* The tile path command uses the contents of the clipboard as a tile which is*/
+/* applied to any selected paths, replacing them. It could be used to make a */
+/* font whose stems were filled with celtic knotwork, for example */
+/* It's sort of an extension to the Expand Stroke command, only it strokes */
+/* with a pattern */
+
+
+/* There used to be a property _XFREE86_GLYPH_RANGES (in bdf/pcf) fonts which */
+/* gave a quick view about what glyphs were in a bdf font. From what I gather*/
+/* this property has been dropped because it was redundant. If you would */
+/* like FontForge to generate it */
+/* */
+/* #define FONTFORGE_CONFIG_BDF_GLYPH_RANGES */
+/* */
+
+
+/* I used to use an approximation method when converting cubic to quadratic */
+/* splines which was non-symmetric. In some cases it produced better results */
+/* than the current approach. This flag restores the old algorithm. */
+/* */
+/* #define FONTFORGE_CONFIG_NON_SYMMETRIC_QUADRATIC_CONVERSION */
+/* */
+
+
+/* Yoshiki Hayashi wants a copy background to foreground command in the */
+/* outline view. Setting this flag will enable his patch */
+/* */
+/* #define FONTFORGE_CONFIG_COPY_BG_TO_FG */
+/* */
+
+
+/* Harald Harders would like to be able to generate a PFM file without */
+/* creating a font along with it. I don't see the need for this, but he pro- */
+/* vided a patch. Setting this flag will enable his patch */
+/* */
+/* #define FONTFORGE_CONFIG_WRITE_PFM */
+/* */
+
+
+/* Prior to late Sept of 2003 FontForge converted certain mac feature/settings*/
+/* into opentype-like tags. Some features could be converted directly but for*/
+/* a few I made up tags. Now FontForge is capable of using the mac feature */
+/* settings directly. If you set this flag then when FontForge loads in an sfd*/
+/* file with these non-standard opentype tags, it will convert them into the */
+/* appropriate mac feature/setting combinations. */
+/* */
+/* #define FONTFORGE_CONFIG_CVT_OLD_MAC_FEATURES */
+/* */
+
+
+/* Normally fontforge uses float (32 bit real data type) to store position */
+/* and transformation data. If you prefer you may use double (64 bit real) */
+/* instead. The extra precision is usually not needed, but the extra space */
+/* can be a problem with large (CJK, UNICODE) fonts. */
+/* */
+/* #define FONTFORGE_CONFIG_USE_DOUBLE */
+/* #define FONTFORGE_CONFIG_USE_LONGDOUBLE */
+/* */
+
+
+/* In addition to placing snippets of charstrings into subrs, I tried adding */
+/* whole glyphs (when that was possible). To my surprise, it made things */
+/* in one of my test cases, and barely registered an improvement in another */
+/* So I think we're better off without it. But I don't understand why things */
+/* are worse so I'm leaving the code in to play with */
+/* */
+/* #define FONTFORGE_CONFIG_PS_REFS_GET_SUBRS */
+/* */
+
+
+/* Werner wants to be able to see the raw (unscaled) data for the location of */
+/* points (in the points window of the debugger). I'm not sure that is */
+/* generally a good idea (I think it makes the dlg look unsymetric). */
+/* */
+/* #define FONTFORGE_CONFIG_SHOW_RAW_POINTS */
+/* */
+
+/* On most systems fontforge uses the alt or meta key as a mouse press modifier*/
+/* on the mac that would mean the option key. But the mac usually uses option*/
+/* keypress to mean mouse button 2, and so option isn't available. Let's use */
+/* capslock instead. */
+/* */
+/* #define FONTFORGE_CONFIG_CAPSLOCK_FOR_ALT */
+/* */
+/* This has three states: */
+/* Undefined (or 0) => use meta/alt key */
+/* 2 => Use either meta/alt or capslock */
+/* otherwise => use capslock */
+/* */
+/* Can be set from configure --with-capslock-for-alt */
+
+
+/* Use horizontal, rather than vertical, tabsets for the Font and glyph Info */
+/* dialogs. This is what things used to look like. */
+/* */
+/* #define FONTFORGE_CONFIG_INFO_HORIZONTAL */
+/* */
+
+/* ************************************************************************** */
+/* *********************** Set by configure script ************************** */
+/* ************************************************************************** */
+
+/* The following are expected to be set by the configure script, but I suppose*/
+/* you could set them here too */
+
+/* If your system does not have a working ldopen (to do dynamic binding of */
+/* shared libaries) then set NODYNAMIC */
+
+/* If you are on a Mac then set __Mac */
+/* If you are on a windows box with cygwin set __CygWin */
+
+/* If you are on a Mac where cursors are restricted to 16x16 pixel boxes then */
+/* set _CursorsMustBe16x16 */
+
+/* If you are on cygwin where even the modifier keys autorepeat then set */
+/* _ModKeysAutoRepeat */
+
+/* If you are on cygwin where some of the drawmode funtions (like AND) don't */
+/* work then set _BrokenBitmapImages */
+
+/* FontForge knows about 4 different keyboard settings, a windows keyboard, a */
+/* mac keyboard, a mac keyboard under SUSE linux, and a sun keyboard */
+/* When it starts up FontForge assumes that the keyboard is some default type*/
+/* You can override the type by setting _Keyboard to */
+/* 0 -- windows */
+/* 1 -- mac running mac osx */
+/* 3 -- mac running SUSE linux (7.1) */
+/* 2 -- sparc */
+/* Basically this affects the text that appears in menus. The sun keyboard */
+/* uses meta where the windows one uses alt, and the mac use command and */
+/* option. */
+
+/* If there are no freetype header files then define _NO_FREETYPE */
+/* If the freetype library has the bytecode debugger then define FREETYPE_HAS_DEBUGGER */
+/* If there is no mmap system call then define _NO_MMAP */
+#ifdef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# undef FREETYPE_HAS_DEBUGGER
+/* Debugger is meaningless if we have no UI (and doesn't compile) */
+#endif
+
+/* If there is no ungif library (or if it is out of date) define _NO_LIBUNGIF */
+/* If there is no png (or z) library define _NO_LIBPNG */
+/* If there libpng is version 1.2 define _LIBPNG12 */
+/* If there is no jpeg library define _NO_LIBJPEG */
+/* If there is no tiff library define _NO_LIBTIFF */
+/* If there is no xml2 library define _NO_LIBXML */
+/* If there is no uninameslist library define _NO_LIBUNINAMESLIST */
+
+/* If any of the above libraries exists, but only in static form (on a system */
+/* with a dynamic loader) then define _STATIC_LIBUNGIF, etc. */
+
+/* If there is no snprintf define _NO_SNPRINTF */
+
+/* If the XInput extension is not available define _NO_XINPUT */
+/* If the Xkb extension is not available define _NO_XKB */
+
+/* If the compiler supports long long define _HAS_LONGLONG */
+
+
+/* ************************************************************************** */
+/* ******************************** Obsolete ******************************** */
+/* ************************************************************************** */
+
+/******* I decided to turn this on and remove all uses of the flag ************/
+/* I thought it would be fun to write a generalized non linear transformation */
+/* routine. I'm not sure that it's very useful though. It can be used to do */
+/* perspective transformations and such */
+/* */
+/* #define FONTFORGE_CONFIG_NONLINEAR */
+/* */
+/* This command takes two strings which specify general expressions in x and y*/
+/* and applies the specified transformations to the splines. Note: Each */
+/* spline is transformed into a new spline, but some transformations require */
+/* that a spline be broken into components and each of those transformed eg: */
+/* "x' = x, y' = y+sin(x)" would not produce anything useful when applied to */
+/* a long line segment like [0,100]...[100,100], but if that were broken up */
+/* into sub-segments each pi long the results would be much better */
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/contextchain.c b/Build/source/libs/luafontforge/fontforge/fontforge/contextchain.c
new file mode 100644
index 00000000000..3425b883a09
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/contextchain.c
@@ -0,0 +1,3032 @@
+/* Copyright (C) 2003-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaeditui.h"
+#include <chardata.h>
+#include <utype.h>
+#include <ustring.h>
+#include <gkeysym.h>
+
+static void FPSTRuleContentsFree(struct fpst_rule *r, enum fpossub_format format) {
+ int j;
+
+ switch ( format ) {
+ case pst_glyphs:
+ free(r->u.glyph.names);
+ free(r->u.glyph.back);
+ free(r->u.glyph.fore);
+ break;
+ case pst_class:
+ free(r->u.class.nclasses);
+ free(r->u.class.bclasses);
+ free(r->u.class.fclasses);
+ break;
+ case pst_reversecoverage:
+ free(r->u.rcoverage.replacements);
+ case pst_coverage:
+ for ( j=0 ; j<r->u.coverage.ncnt ; ++j )
+ free(r->u.coverage.ncovers[j]);
+ free(r->u.coverage.ncovers);
+ for ( j=0 ; j<r->u.coverage.bcnt ; ++j )
+ free(r->u.coverage.bcovers[j]);
+ free(r->u.coverage.bcovers);
+ for ( j=0 ; j<r->u.coverage.fcnt ; ++j )
+ free(r->u.coverage.fcovers[j]);
+ free(r->u.coverage.fcovers);
+ break;
+ case pst_formatmax:
+ break;
+ }
+ free(r->lookups);
+}
+
+#ifndef LUA_FF_LIB
+static void FPSTRulesFree(struct fpst_rule *r, enum fpossub_format format, int rcnt) {
+ int i;
+ for ( i=0; i<rcnt; ++i )
+ FPSTRuleContentsFree(&r[i],format);
+ free(r);
+}
+#endif
+
+static struct fpst_rule *RulesCopy(struct fpst_rule *from, int cnt,
+ enum fpossub_format format ) {
+ int i, j;
+ struct fpst_rule *to, *f, *t;
+ if ( cnt==0 )
+return( NULL );
+
+ t = NULL;
+ to = gcalloc(cnt,sizeof(struct fpst_rule));
+ for ( i=0; i<cnt; ++i ) {
+ f = from+i; t = to+i;
+ switch ( format ) {
+ case pst_glyphs:
+ t->u.glyph.names = copy(f->u.glyph.names);
+ t->u.glyph.back = copy(f->u.glyph.back);
+ t->u.glyph.fore = copy(f->u.glyph.fore);
+ break;
+ case pst_class:
+ t->u.class.ncnt = f->u.class.ncnt;
+ t->u.class.bcnt = f->u.class.bcnt;
+ t->u.class.fcnt = f->u.class.fcnt;
+ t->u.class.nclasses = galloc( f->u.class.ncnt*sizeof(uint16));
+ memcpy(t->u.class.nclasses,f->u.class.nclasses,
+ f->u.class.ncnt*sizeof(uint16));
+ if ( t->u.class.bcnt!=0 ) {
+ t->u.class.bclasses = galloc( f->u.class.bcnt*sizeof(uint16));
+ memcpy(t->u.class.bclasses,f->u.class.bclasses,
+ f->u.class.bcnt*sizeof(uint16));
+ }
+ if ( t->u.class.fcnt!=0 ) {
+ t->u.class.fclasses = galloc( f->u.class.fcnt*sizeof(uint16));
+ memcpy(t->u.class.fclasses,f->u.class.fclasses,
+ f->u.class.fcnt*sizeof(uint16));
+ }
+ break;
+ case pst_reversecoverage:
+ t->u.rcoverage.replacements = copy(f->u.rcoverage.replacements);
+ case pst_coverage:
+ t->u.coverage.ncnt = f->u.coverage.ncnt;
+ t->u.coverage.bcnt = f->u.coverage.bcnt;
+ t->u.coverage.fcnt = f->u.coverage.fcnt;
+ t->u.coverage.ncovers = galloc( f->u.coverage.ncnt*sizeof(char *));
+ for ( j=0; j<t->u.coverage.ncnt; ++j )
+ t->u.coverage.ncovers[j] = copy(f->u.coverage.ncovers[j]);
+ if ( t->u.coverage.bcnt!=0 ) {
+ t->u.coverage.bcovers = galloc( f->u.coverage.bcnt*sizeof(char *));
+ for ( j=0; j<t->u.coverage.bcnt; ++j )
+ t->u.coverage.bcovers[j] = copy(f->u.coverage.bcovers[j]);
+ }
+ if ( t->u.coverage.fcnt!=0 ) {
+ t->u.coverage.fcovers = galloc( f->u.coverage.fcnt*sizeof(char *));
+ for ( j=0; j<t->u.coverage.fcnt; ++j )
+ t->u.coverage.fcovers[j] = copy(f->u.coverage.fcovers[j]);
+ }
+ break;
+ case pst_formatmax:
+ break;
+ }
+ if ( f->lookup_cnt!=0 ) {
+ t->lookup_cnt = f->lookup_cnt;
+ t->lookups = galloc(t->lookup_cnt*sizeof(struct seqlookup));
+ memcpy(t->lookups,f->lookups,t->lookup_cnt*sizeof(struct seqlookup));
+ }
+ }
+return( t );
+}
+
+FPST *FPSTCopy(FPST *fpst) {
+ FPST *nfpst;
+ int i;
+
+ nfpst = chunkalloc(sizeof(FPST));
+ *nfpst = *fpst;
+ nfpst->next = NULL;
+ if ( nfpst->nccnt!=0 ) {
+ nfpst->nclass = galloc(nfpst->nccnt*sizeof(char *));
+ for ( i=0; i<nfpst->nccnt; ++i )
+ nfpst->nclass[i] = copy(fpst->nclass[i]);
+ }
+ if ( nfpst->bccnt!=0 ) {
+ nfpst->bclass = galloc(nfpst->bccnt*sizeof(char *));
+ for ( i=0; i<nfpst->bccnt; ++i )
+ nfpst->bclass[i] = copy(fpst->bclass[i]);
+ }
+ if ( nfpst->fccnt!=0 ) {
+ nfpst->fclass = galloc(nfpst->fccnt*sizeof(char *));
+ for ( i=0; i<nfpst->fccnt; ++i )
+ nfpst->fclass[i] = copy(fpst->fclass[i]);
+ }
+ nfpst->rules = RulesCopy(fpst->rules,fpst->rule_cnt,fpst->format);
+return( nfpst );
+}
+
+void FPSTFree(FPST *fpst) {
+ FPST *next;
+ int i;
+
+ while ( fpst!=NULL ) {
+ next = fpst->next;
+ for ( i=0; i<fpst->nccnt; ++i )
+ free(fpst->nclass[i]);
+ for ( i=0; i<fpst->bccnt; ++i )
+ free(fpst->bclass[i]);
+ for ( i=0; i<fpst->fccnt; ++i )
+ free(fpst->fclass[i]);
+ free(fpst->nclass); free(fpst->bclass); free(fpst->fclass);
+ for ( i=0; i<fpst->rule_cnt; ++i ) {
+ FPSTRuleContentsFree( &fpst->rules[i],fpst->format );
+ }
+ free(fpst->rules);
+ chunkfree(fpst,sizeof(FPST));
+ fpst = next;
+ }
+}
+
+int ClassesMatch(int cnt1,char **classes1,int cnt2,char **classes2) {
+ int i;
+
+ if ( cnt1!=cnt2 )
+return( false );
+ for ( i=1; i<cnt2; ++i )
+ if ( strcmp(classes1[i],classes2[i])!=0 )
+return( false );
+
+return( true );
+}
+
+static char **classcopy(char **names,int nextclass) {
+ char **ret;
+ int i;
+
+ if ( nextclass <= 1 )
+return( NULL );
+
+ ret = galloc(nextclass*sizeof(char *));
+ ret[0] = NULL;
+ for ( i=1; i<nextclass; ++i )
+ ret[i] = copy(names[i]);
+return( ret );
+}
+
+FPST *FPSTGlyphToClass(FPST *fpst) {
+ FPST *new;
+ int nextclass=0, i,j,k, max, cnt, ch;
+ char *pt, *end;
+ char **names;
+
+ if ( fpst->format!=pst_glyphs )
+return( NULL );
+
+ new = chunkalloc(sizeof(FPST));
+ new->type = fpst->type;
+ new->format = pst_class;
+ new->subtable = fpst->subtable;
+ new->rule_cnt = fpst->rule_cnt;
+ new->rules = gcalloc(fpst->rule_cnt,sizeof(struct fpst_rule));
+
+ max = 100; nextclass=1;
+ names = galloc(max*sizeof(char *));
+ names[0] = NULL;
+ for ( i=0; i<fpst->rule_cnt; ++i ) {
+ for ( j=0; j<3; ++j ) {
+ cnt = 0;
+ if ( (&fpst->rules[i].u.glyph.names)[j]!=NULL && *(&fpst->rules[i].u.glyph.names)[j]!='\0' ) {
+ cnt = 1;
+ for ( pt=(&fpst->rules[i].u.glyph.names)[j]; *pt; ++pt ) {
+ if ( *pt==' ' ) {
+ ++cnt;
+ while ( *pt==' ' ) ++pt;
+ --pt;
+ }
+ }
+ }
+ (&new->rules[i].u.class.ncnt)[j] = cnt;
+ if ( cnt!=0 ) {
+ (&new->rules[i].u.class.nclasses)[j] = galloc(cnt*sizeof(uint16));
+ cnt = 0;
+ for ( pt=(&fpst->rules[i].u.glyph.names)[j]; *pt; pt=end ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ for ( end=pt ; *end!=' ' && *end!='\0'; ++end );
+ ch = *end; *end='\0';
+ for ( k=1; k<nextclass; ++k )
+ if ( strcmp(pt,names[k])==0 )
+ break;
+ if ( k==nextclass ) {
+ if ( nextclass>=max )
+ names = grealloc(names,(max+=100)*sizeof(char *));
+ names[nextclass++] = copy(pt);
+ }
+ *end = ch;
+ (&new->rules[i].u.class.nclasses)[j][cnt++] = k;
+ }
+ }
+ }
+ new->rules[i].lookup_cnt = fpst->rules[i].lookup_cnt;
+ new->rules[i].lookups = galloc(fpst->rules[i].lookup_cnt*sizeof(struct seqlookup));
+ memcpy(new->rules[i].lookups,fpst->rules[i].lookups,
+ fpst->rules[i].lookup_cnt*sizeof(struct seqlookup));
+ }
+ new->nccnt = nextclass;
+ new->nclass = names;
+ if ( fpst->type==pst_chainpos || fpst->type==pst_chainsub ) {
+ /* our class set has one "class" for each glyph used anywhere */
+ /* all three class sets are the same */
+ new->bccnt = new->fccnt = nextclass;
+ new->bclass = classcopy(names,nextclass);
+ new->fclass = classcopy(names,nextclass);
+ }
+return( new );
+}
+
+/* ************************************************************************** */
+/* ************************ Context/Chaining Dialog ************************* */
+/* ************************************************************************** */
+struct contextchaindlg {
+ struct gfi_data *gfi;
+ SplineFont *sf;
+ FPST *fpst;
+ unichar_t *newname;
+ int isnew;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ GWindow gw;
+ GWindow formats, coverage, glist, glyphs, cselect, class, classbuild, classnumber;
+ enum activewindow { aw_formats, aw_coverage, aw_glist, aw_glyphs, aw_cselect,
+ aw_class, aw_classbuild, aw_classnumber } aw;
+#endif
+ uint16 wasedit;
+ uint16 wasoffset;
+ uint8 foredefault;
+ int subheightdiff, canceldrop;
+};
+
+#define CID_OK 100
+#define CID_Cancel 101
+#define CID_Next 102
+#define CID_Prev 103
+#define CID_Group 104
+
+#define CID_ByGlyph 200
+#define CID_ByClass 201
+#define CID_ByCoverage 202
+
+/* There are more CIDs used in this file than those listed here */
+/* The CIDs given here are for glyph lists (aw_glyphs & aw_glist) */
+/* similar controls refering to coverage tables have 100 added to them */
+/* The CIDs here are also for the "match" aspect of the tabsets */
+/* those in backtrack get 20 added, those in lookahead get 40 */
+#define CID_New 300
+#define CID_Edit 301
+#define CID_Delete 302
+#define CID_Up 303
+#define CID_Down 304
+#define CID_GList 305
+
+#define CID_MatchType 1003
+#define CID_Set 1004
+#define CID_Select 1005
+#define CID_GlyphList 1006
+#define CID_Set2 1007
+#define CID_Select2 1008
+#define CID_RplList 1009
+#define CID_LookupList 1010
+#define CID_LNew 1011
+#define CID_LEdit 1012
+#define CID_LDelete 1013
+#define CID_LUp 1014
+#define CID_LDown 1015
+
+#define CID_StdClasses 1016
+
+#define CID_ClassNumbers 2000
+#define CID_ClassList 2001
+#define CID_ClassType 2002
+#define CID_SameAsClasses 2003
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+
+GTextInfo stdclasses[] = {
+ { (unichar_t *) N_("None"), NULL, 0, 0, "None", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("0-9"), NULL, 0, 0, "0-9", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Letters in Script(s)"), NULL, 0, 0, "Letters", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lower Case"), NULL, 0, 0, "LC", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Upper Case"), NULL, 0, 0, "UC", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Glyphs in Script(s)"), NULL, 0, 0, "Glyphs", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Added"), NULL, 0, 0, "None", NULL, 1, 0, 0, 0, 0, 0, 1},
+ { NULL }
+};
+
+#endif
+
+char *cu_copybetween(const unichar_t *start, const unichar_t *end) {
+ char *ret = galloc(end-start+1);
+ cu_strncpy(ret,start,end-start);
+ ret[end-start] = '\0';
+return( ret );
+}
+
+#ifndef LUA_FF_LIB
+static char *ccd_cu_copy(const unichar_t *start) {
+ char *ret, *pt;
+
+ while ( isspace(*start)) ++start;
+ if ( *start=='\0' )
+return( NULL );
+ ret = pt = galloc(u_strlen(start)+1);
+ while ( *start ) {
+ while ( !isspace(*start) && *start!='\0' )
+ *pt++ = *start++;
+ while ( isspace(*start)) ++start;
+ if ( *start!='\0' ) *pt++ = ' ';
+ }
+ *pt = '\0';
+return( ret );
+}
+
+static char *reversenames(char *str) {
+ char *ret;
+ char *rpt, *pt, *start, *spt;
+
+ if ( str==NULL )
+return( NULL );
+
+ rpt = ret = galloc(strlen(str)+1);
+ *ret = '\0';
+ for ( pt=str+strlen(str); pt>str; pt=start ) {
+ for ( start = pt-1; start>=str && *start!=' '; --start );
+ for ( spt=start+1; spt<pt; )
+ *rpt++ = *spt++;
+ *rpt++ = ' ';
+ }
+ if ( rpt>ret )
+ rpt[-1] = '\0';
+return( ret );
+}
+
+static unichar_t *classnumbers(int cnt,uint16 *classes) {
+ char buf[20];
+ int i, len;
+ unichar_t *pt, *ret;
+
+ len = 0;
+ for ( i=0; i<cnt; ++i ) {
+ sprintf( buf, "%d ", classes[i]);
+ len += strlen(buf);
+ }
+ ret = pt = galloc((len+3)*sizeof(unichar_t));
+ *pt = '\0'; /* In case it is empty */
+
+ for ( i=0; i<cnt; ++i ) {
+ sprintf( buf, "%d ", classes[i]);
+ uc_strcpy(pt,buf);
+ pt += strlen(buf);
+ }
+return( ret );
+}
+
+static unichar_t *rclassnumbers(int cnt,uint16 *classes) {
+ char buf[20];
+ int i, len;
+ unichar_t *pt, *ret;
+
+ len = 0;
+ for ( i=0; i<cnt; ++i ) {
+ sprintf( buf, "%d ", classes[i]);
+ len += strlen(buf);
+ }
+ ret = pt = galloc((len+3)*sizeof(unichar_t));
+ *pt = '\0';
+ for ( i=cnt-1; i>=0; --i ) {
+ sprintf( buf, "%d ", classes[i]);
+ uc_strcpy(pt,buf);
+ pt += strlen(buf);
+ }
+return( ret );
+}
+
+static int CCD_GlyphNameCnt(const unichar_t *pt) {
+ int cnt = 0;
+
+ while ( *pt ) {
+ while ( isspace( *pt )) ++pt;
+ if ( *pt=='\0' )
+return( cnt );
+ ++cnt;
+ while ( !isspace(*pt) && *pt!='\0' ) ++pt;
+ }
+return( cnt );
+}
+
+static int seqlookuplen(struct fpst_rule *r) {
+ int i, len=0;
+ char buf[20];
+
+ for ( i=0; i<r->lookup_cnt; ++i ) {
+ sprintf( buf," %d \"\",", r->lookups[i].seq );
+ len += strlen(buf) + utf8_strlen( r->lookups[i].lookup->lookup_name );
+ }
+return( len );
+}
+
+static unichar_t *addseqlookups(unichar_t *pt, struct fpst_rule *r) {
+ int i;
+ char buf[20];
+
+ *pt++ = 0x21d2;
+ for ( i=0; i<r->lookup_cnt; ++i ) {
+ unichar_t *temp;
+ sprintf( buf," %d \"", r->lookups[i].seq );
+ uc_strcpy(pt, buf);
+ pt += u_strlen(pt);
+ temp = utf82u_copy(r->lookups[i].lookup->lookup_name );
+ u_strcpy(pt,temp);
+ pt += u_strlen(pt);
+ *pt++ = '"';
+ *pt++ = ',';
+ }
+ if ( pt[-1]==',' ) pt[-1] = '\0';
+ *pt = '\0';
+return( pt );
+}
+
+static void parseseqlookups(SplineFont *sf, const unichar_t *solooks, struct fpst_rule *r) {
+ int cnt;
+ const unichar_t *pt;
+
+ for ( pt = solooks, cnt=0; *pt!='\0'; ) {
+ ++cnt;
+ while ( *pt!='"' && *pt!='\0' ) ++pt;
+ if ( *pt=='"' ) {
+ ++pt;
+ while ( *pt!='"' && *pt!='\0' ) ++pt;
+ if ( *pt=='"' ) ++pt;
+ }
+ if ( *pt==',' ) ++pt;
+ }
+ r->lookup_cnt = cnt;
+ r->lookups = gcalloc(cnt,sizeof(struct seqlookup));
+ cnt = 0;
+ pt = solooks;
+ forever {
+ unichar_t *end;
+ r->lookups[cnt].seq = u_strtol(pt,&end,10);
+ pt = end+1;
+ if ( *pt=='"' ) {
+ const unichar_t *eoname; char *temp;
+ ++pt;
+ for ( eoname = pt; *eoname!='\0' && *eoname!='"'; ++eoname );
+ temp = u2utf8_copyn(pt,eoname-pt);
+ r->lookups[cnt].lookup = SFFindLookup(sf,temp);
+ if ( r->lookups[cnt].lookup==NULL )
+ IError("No lookup in parseseqlookups");
+ free(temp);
+ pt = eoname;
+ if ( *pt=='"' ) ++pt;
+ }
+ ++cnt;
+ if ( *pt!=',' )
+ break;
+ ++pt;
+ }
+}
+
+static unichar_t *glistitem(struct fpst_rule *r) {
+ unichar_t *ret, *pt;
+ int len;
+
+ len = (r->u.glyph.back==NULL ? 0 : strlen(r->u.glyph.back)) +
+ strlen(r->u.glyph.names) +
+ (r->u.glyph.fore==0 ? 0 : strlen(r->u.glyph.fore)) +
+ seqlookuplen(r);
+
+ ret = pt = galloc((len+8) * sizeof(unichar_t));
+ if ( r->u.glyph.back!=NULL && *r->u.glyph.back!='\0' ) {
+ char *temp = reversenames(r->u.glyph.back);
+ uc_strcpy(pt,temp);
+ pt += strlen(temp);
+ free(temp);
+ *pt++ = ' ';
+ }
+ *pt++ = '[';
+ *pt++ = ' ';
+ uc_strcpy(pt,r->u.glyph.names);
+ pt += strlen(r->u.glyph.names);
+ *pt++ = ' ';
+ *pt++ = ']';
+ *pt++ = ' ';
+ if ( r->u.glyph.fore!=NULL && *r->u.glyph.fore!='\0' ) {
+ uc_strcpy(pt,r->u.glyph.fore);
+ pt += strlen(r->u.glyph.fore);
+ *pt++ = ' ';
+ }
+ pt = addseqlookups(pt, r);
+return( ret );
+}
+
+static void glistitem2rule(SplineFont *sf, const unichar_t *ret,struct fpst_rule *r) {
+ const unichar_t *pt;
+ char *temp;
+
+ for ( pt=ret; *pt!='\0' && *pt!='['; ++pt );
+ if ( *pt=='\0' )
+return;
+ if ( pt>ret ) {
+ temp = cu_copybetween(ret,pt-1);
+ r->u.glyph.back = reversenames(temp);
+ free(temp);
+ }
+ ret = pt+2;
+ for ( pt=ret; *pt!='\0' && *pt!=']'; ++pt );
+ if ( *pt=='\0' )
+return;
+ r->u.glyph.names = cu_copybetween(ret,pt-1);
+ ret = pt+2;
+ for ( pt=ret; *pt!='\0' && *pt!=0x21d2; ++pt );
+ if ( *pt=='\0' )
+return;
+ if ( pt!=ret )
+ r->u.glyph.fore = cu_copybetween(ret,pt-1);
+ parseseqlookups(sf,pt+2,r);
+}
+
+
+static GTextInfo **glistlist(FPST *fpst) {
+ GTextInfo **ti;
+ int i;
+
+ if ( fpst->format!=pst_glyphs || fpst->rule_cnt==0 )
+return(NULL);
+ ti = galloc((fpst->rule_cnt+1)*sizeof(GTextInfo *));
+ ti[fpst->rule_cnt] = gcalloc(1,sizeof(GTextInfo));
+ for ( i=0; i<fpst->rule_cnt; ++i ) {
+ ti[i] = gcalloc(1,sizeof(GTextInfo));
+ ti[i]->text = glistitem(&fpst->rules[i]);
+ ti[i]->fg = ti[i]->bg = COLOR_DEFAULT;
+ }
+return( ti );
+}
+
+
+static unichar_t *clslistitem(struct fpst_rule *r) {
+ unichar_t *ret, *pt;
+ int len, i, k;
+ char buf[20];
+
+ len = 0;
+ for ( i=0; i<3; ++i ) {
+ for ( k=0; k<(&r->u.class.ncnt)[i]; ++k ) {
+ sprintf( buf, "%d ", (&r->u.class.nclasses)[i][k]);
+ len += strlen(buf);
+ }
+ }
+
+ ret = pt = galloc((len+8+seqlookuplen(r)) * sizeof(unichar_t));
+ for ( k=r->u.class.bcnt-1; k>=0; --k ) {
+ sprintf( buf, "%d ", r->u.class.bclasses[k]);
+ uc_strcpy(pt,buf);
+ pt += strlen(buf);
+ }
+ *pt++ = '[';
+ for ( k=0; k<r->u.class.ncnt; ++k ) {
+ sprintf( buf, "%d ", r->u.class.nclasses[k]);
+ uc_strcpy(pt,buf);
+ pt += strlen(buf);
+ }
+ if ( pt[-1]==' ' ) --pt;
+ *pt++ = ']';
+ for ( k=0; k<r->u.class.fcnt; ++k ) {
+ sprintf( buf, " %d", r->u.class.fclasses[k]);
+ uc_strcpy(pt,buf);
+ pt += strlen(buf);
+ }
+
+ *pt++ = ' ';
+ pt = addseqlookups(pt, r);
+return( ret );
+}
+
+static void clslistitem2rule(SplineFont *sf,const unichar_t *ret,struct fpst_rule *r) {
+ const unichar_t *pt; unichar_t *end;
+ int len, i;
+
+ memset(r,0,sizeof(*r));
+
+ len = 0; i=1;
+ for ( pt=ret; *pt; ++pt ) {
+ while ( *pt!='[' && *pt!=']' && *pt!=0x21d2 && *pt!='\0' ) {
+ if ( isdigit( *pt )) {
+ ++len;
+ while ( isdigit(*pt)) ++pt;
+ } else if ( *pt!=' ' && *pt!='[' && *pt!=']' && *pt!=0x21d2 && *pt!='\0' )
+ ++pt;
+ while ( *pt==' ' ) ++pt;
+ }
+ (&r->u.class.ncnt)[i] = len;
+ (&r->u.class.nclasses)[i] = galloc(len*sizeof(uint16));
+ len = 0;
+ if ( *pt=='\0' || *pt==0x21d2 )
+ break;
+ if ( *pt=='[' ) i=0;
+ else i=2;
+ }
+ len = 0; i=1;
+ for ( pt=ret; *pt; ++pt ) {
+ while ( *pt!='[' && *pt!=']' && *pt!=0x21d2 && *pt!='\0' ) {
+ if ( isdigit( *pt )) {
+ if ( len>=(&r->u.class.ncnt)[i] )
+ IError( "clslistitem2rule bad memory");
+ (&r->u.class.nclasses)[i][len++] = u_strtol(pt,&end,10);
+ pt = end;
+ } else if ( *pt!=' ' && *pt!='[' && *pt!=']' && *pt!=0x21d2 && *pt!='\0' )
+ ++pt;
+ while ( *pt==' ' ) ++pt;
+ }
+ len = 0;
+ if ( *pt=='[' ) i=0;
+ else i=2;
+ if ( *pt=='\0' || *pt==0x21d2 )
+ break;
+ }
+ /* reverse the backtrack */
+ for ( i=0; i<r->u.class.bcnt/2; ++i ) {
+ int temp = r->u.class.bclasses[i];
+ r->u.class.bclasses[i] = r->u.class.bclasses[r->u.class.bcnt-1-i];
+ r->u.class.bclasses[r->u.class.bcnt-1-i] = temp;
+ }
+
+ if ( *pt=='\0' || pt[1]=='\0' )
+return;
+ parseseqlookups(sf,pt+2,r);
+}
+
+static GTextInfo **clslistlist(FPST *fpst) {
+ GTextInfo **ti;
+ int i;
+
+ if ( fpst->format!=pst_class || fpst->rule_cnt==0 )
+return(NULL);
+ ti = galloc((fpst->rule_cnt+1)*sizeof(GTextInfo *));
+ ti[fpst->rule_cnt] = gcalloc(1,sizeof(GTextInfo));
+ for ( i=0; i<fpst->rule_cnt; ++i ) {
+ ti[i] = gcalloc(1,sizeof(GTextInfo));
+ ti[i]->text = clslistitem(&fpst->rules[i]);
+ ti[i]->fg = ti[i]->bg = COLOR_DEFAULT;
+ }
+return( ti );
+}
+
+static GTextInfo **clistlist(FPST *fpst,int which) {
+ GTextInfo **ti;
+ int cnt, i;
+
+ if ( (fpst->format!=pst_coverage && fpst->format!=pst_reversecoverage) ||
+ fpst->rule_cnt!=1 )
+return(NULL);
+ cnt = (&fpst->rules[0].u.coverage.ncnt)[which];
+ if ( cnt == 0 )
+return( NULL );
+ ti = galloc((cnt+1)*sizeof(GTextInfo *));
+ ti[cnt] = gcalloc(1,sizeof(GTextInfo));
+ if ( which != 1 ) {
+ for ( i=0; i<cnt; ++i ) {
+ ti[i] = gcalloc(1,sizeof(GTextInfo));
+ ti[i]->text = uc_copy((&fpst->rules[0].u.coverage.ncovers)[which][i]);
+ ti[i]->fg = ti[i]->bg = COLOR_DEFAULT;
+ }
+ } else {
+ for ( i=0; i<cnt; ++i ) {
+ ti[i] = gcalloc(1,sizeof(GTextInfo));
+ ti[i]->text = uc_copy(fpst->rules[0].u.coverage.bcovers[cnt-i-1]);
+ ti[i]->fg = ti[i]->bg = COLOR_DEFAULT;
+ }
+ }
+return( ti );
+}
+
+static GTextInfo **slistlist(struct fpst_rule *r) {
+ GTextInfo **ti;
+ char buf[20];
+ int i;
+
+ if ( r->lookup_cnt==0 )
+return(NULL);
+ ti = galloc((r->lookup_cnt+1)*sizeof(GTextInfo *));
+ ti[r->lookup_cnt] = gcalloc(1,sizeof(GTextInfo));
+ for ( i=0; i<r->lookup_cnt; ++i ) {
+ unichar_t *space;
+ ti[i] = gcalloc(1,sizeof(GTextInfo));
+ sprintf( buf,"%d ", r->lookups[i].seq );
+ ti[i]->text = space = galloc((strlen(buf)+utf8_strlen(r->lookups[i].lookup->lookup_name)+2)*sizeof(unichar_t));
+ uc_strcpy(space,buf);
+ utf82u_strcat(space,r->lookups[i].lookup->lookup_name);
+ ti[i]->fg = ti[i]->bg = COLOR_DEFAULT;
+ }
+return( ti );
+}
+
+
+static void CCD_ParseLookupList(SplineFont *sf, struct fpst_rule *r,GGadget *list) {
+ int32 len, i;
+ GTextInfo **ti = GGadgetGetList(list,&len);
+ unichar_t *end;
+ char *name;
+
+ r->lookup_cnt = len;
+ r->lookups = galloc(len*sizeof(struct seqlookup));
+ for ( i=0; i<len; ++i ) {
+ r->lookups[i].seq = u_strtol(ti[i]->text,&end,10);
+ while ( *end==' ') ++end;
+ if ( *end=='"' ) ++end;
+ name = u2utf8_copy(end);
+ if ( name[strlen(name)-1] == '"' )
+ name[strlen(name)-1] = '\0';
+ r->lookups[i].lookup = SFFindLookup(sf,name);
+ if ( r->lookups[i].lookup==NULL )
+ IError("Failed to find lookup in CCD_ParseLookupList");
+ free(name);
+ }
+}
+
+
+static void CCD_EnableNextPrev(struct contextchaindlg *ccd) {
+ /* Cancel is always enabled */
+ switch ( ccd->aw ) {
+ case aw_formats:
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_Prev),false);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_Next),true);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_OK),false);
+ break;
+ case aw_glyphs:
+ case aw_classbuild:
+ case aw_classnumber:
+ case aw_cselect:
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_Prev),true);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_Next),true);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_OK),false);
+ break;
+ case aw_coverage:
+ case aw_glist:
+ case aw_class:
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_Prev),ccd->fpst->format!=pst_reversecoverage);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_Next),false);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_OK),true);
+ break;
+ default:
+ IError("Can't get here");
+ break;
+ }
+}
+
+static int CCD_ValidNameList(const char *ret,int empty_bad) {
+ int first;
+ extern int allow_utf8_glyphnames;
+
+ while ( isspace(*ret)) ++ret;
+ if ( *ret=='\0' )
+return( !empty_bad );
+
+ first = true;
+ while ( *ret ) {
+ if ( (*(unsigned char *) ret>=0x7f && !allow_utf8_glyphnames) || *ret<' ' )
+return( false );
+ if ( first && isdigit(*ret) )
+return( false );
+ first = isspace(*ret);
+ if ( *ret=='(' || *ret=='[' || *ret=='{' || *ret=='<' ||
+ *ret==')' || *ret==']' || *ret=='}' || *ret=='>' ||
+ *ret=='%' || *ret=='/' )
+return( false );
+ ++ret;
+ }
+return( true );
+}
+
+static char *CCD_NonExistantName(SplineFont *sf,const char *ret) {
+ const char *pt, *end; char *name;
+
+ for ( pt = ret; *pt; pt = end ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ end = strchr(pt,' ');
+ if ( end==NULL ) end = pt+strlen(pt);
+ name = copyn(pt,end-pt);
+ if ( SFGetChar(sf,-1,name)==NULL )
+return( name );
+ free(name);
+ }
+return( NULL );
+}
+
+int CCD_NameListCheck(SplineFont *sf,const char *ret,int empty_bad,char *title) {
+ char *missingname;
+ int ans;
+
+ if ( !CCD_ValidNameList(ret,empty_bad) ) {
+ gwwv_post_error(title,
+ strcmp(title,_("Bad Class"))==0? _("A class must contain at least one glyph name, glyph names must be valid postscript names, and no glyphs may appear in any other class") :
+ strcmp(title,_("Bad Coverage"))==0? _("A coverage table must contain at least one glyph name, and glyph names must be valid postscript names") :
+ _("A glyph list must contain at least one glyph name, and glyph names must be valid postscript names") );
+return(false);
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( (missingname=CCD_NonExistantName(sf,ret))!=NULL ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buts[3];
+ buts[0] = _("_Yes"); buts[1] = _("_No"); buts[2] = NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buts[] = { GTK_STOCK_YES, GTK_STOCK_NO, NULL };
+#endif
+ ans = gwwv_ask(title,(const char **) buts,0,1,
+ strcmp(title,_("Bad Class"))==0? _("The class member \"%.20s\" is not in this font.\nIs that what you want?") :
+ strcmp(title,_("Bad Coverage"))==0? _("The coverage table member \"%.20s\" is not in this font.\nIs that what you want?") :
+ _("There is no glyph named \"%.20hs\" in this font.\nIs that what you want?"), missingname );
+ free(missingname);
+return(!ans);
+ }
+#endif
+return( true );
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+
+int CCD_InvalidClassList(char *ret,GGadget *list,int wasedit) {
+ int32 len;
+ GTextInfo **ti = GGadgetGetList(list,&len);
+ char *pt, *end; unichar_t *tpt, *tend;
+ int i;
+
+ for ( pt = ret; *pt; pt = end ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ end = strchr(pt,' ');
+ if ( end==NULL ) end = pt+strlen(pt);
+ for ( i=0; i<len; ++i ) {
+ if ( wasedit && ti[i]->selected )
+ continue;
+ for ( tpt=ti[i]->text; *tpt; tpt = tend ) {
+ while ( *tpt==' ' ) ++tpt;
+ tend = u_strchr(tpt,' ');
+ if ( tend==NULL ) tend = tpt+u_strlen(tpt);
+ /* We've already checked for ASCII, so ucs2 & utf8 should */
+ /* have the same length for an ASCII string */
+ if ( tend-tpt==end-pt && uc_strncmp(tpt,pt,end-pt)==0 ) {
+ char *dupname = copyn(pt,end-pt);
+ gwwv_post_error(_("Bad Class"),_("No glyphs from another class may appear here, but %.30s does"), dupname);
+ free(dupname);
+return( true );
+ }
+ }
+ }
+ }
+return( false );
+}
+
+static int CCD_ReasonableClassNum(const unichar_t *match,GGadget *mlist,
+ const unichar_t *back, GGadget *blist,
+ const unichar_t *fore, GGadget *flist,
+ struct fpst_rule *r ) {
+ int32 mlen, blen, flen;
+ GTextInfo **ti;
+ const unichar_t *pt; unichar_t *end;
+ int any;
+ int val;
+
+ ti = GGadgetGetList(mlist,&mlen);
+ ti = GGadgetGetList(blist,&blen);
+ ti = GGadgetGetList(flist,&flen);
+
+ any = 0;
+ for ( pt=match;; pt = end) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ if ( isdigit( *pt )) ++any;
+ val = u_strtol(pt,&end,10);
+ if ( *end!=' ' && *end!='\0' ) {
+ gwwv_post_error(_("Bad Match Class Number"),_("The list of class numbers should only contain digits and spaces"));
+return( false );
+ }
+ if ( val>=mlen || val<0) {
+ gwwv_post_error(_("Bad Match Class Number"),_("There are only %d classes in this class set, yet you are trying to use %d."),mlen,val);
+return( false );
+ }
+ }
+ r->u.class.ncnt = any;
+ if ( any==0 ) {
+ gwwv_post_error(_("Bad Match Class Number"),_("There are no class numbers listed to be matched. There must be at least one."));
+return( false );
+ }
+
+ any = 0;
+ for ( pt=back;; pt = end) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ if ( isdigit( *pt )) ++any;
+ val = u_strtol(pt,&end,10);
+ if ( *end!=' ' && *end!='\0' ) {
+ gwwv_post_error(_("Bad Backtrack Class Number"),_("The list of class numbers should only contain digits and spaces"));
+return( false );
+ }
+ if ( val>=blen || val<0) {
+ gwwv_post_error(_("Bad Backtrack Class Number"),_("There are only %d classes in this class set, yet you are trying to use %d."),blen,val);
+return( false );
+ }
+ }
+ r->u.class.bcnt = any;
+
+ any = 0;
+ for ( pt=fore;; pt = end) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ if ( isdigit( *pt )) ++any;
+ val = u_strtol(pt,&end,10);
+ if ( *end!=' ' && *end!='\0' ) {
+ gwwv_post_error(_("Bad Lookahead Class Number"),_("The list of class numbers should only contain digits and spaces"));
+return( false );
+ }
+ if ( val>=flen || val<0) {
+ gwwv_post_error(_("Bad Lookahead Class Number"),_("There are only %d classes in this class set, yet you are trying to use %d."),flen,val);
+return( false );
+ }
+ }
+ r->u.class.fcnt = any;
+
+ r->u.class.nclasses = galloc(r->u.class.ncnt*sizeof(uint16));
+ r->u.class.bclasses = galloc(r->u.class.bcnt*sizeof(uint16));
+ r->u.class.fclasses = galloc(r->u.class.fcnt*sizeof(uint16));
+
+ any = 0;
+ for ( pt=match;; pt = end) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ if ( any>=r->u.class.ncnt ) IError("ReasonableClassNumber unreasonable");
+ r->u.class.nclasses[any++] = u_strtol(pt,&end,10);
+ }
+
+ any = 0;
+ for ( pt=back;; pt = end) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ if (r->u.class.bcnt-1-any<0 || r->u.class.bcnt-1-any>=r->u.class.bcnt ) IError("ReasonableClassNumber unreasonable");
+ r->u.class.bclasses[r->u.class.bcnt-1-any++] = u_strtol(pt,&end,10);
+ }
+
+ any = 0;
+ for ( pt=fore;; pt = end) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ if ( any>=r->u.class.fcnt ) IError("ReasonableClassNumber unreasonable");
+ r->u.class.fclasses[any++] = u_strtol(pt,&end,10);
+ }
+return( true );
+}
+
+static void CCD_FinishEditNew(struct contextchaindlg *ccd) {
+ char *temp;
+ struct fpst_rule dummy;
+ GGadget *list = GWidgetGetControl(ccd->gw,CID_GList+ccd->wasoffset);
+ int i,tot;
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buts[3];
+ buts[0] = _("_Yes"); buts[1] = _("_No"); buts[2] = NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buts[] = { GTK_STOCK_YES, GTK_STOCK_NO, NULL };
+#endif
+
+ if ( ccd->wasoffset>=300 ) { /* It's a class */
+ char *ret = GGadgetGetTitle8(GWidgetGetControl(ccd->gw,CID_GlyphList+300));
+ if ( !CCD_NameListCheck(ccd->sf,ret,true,_("Bad Class")) ||
+ CCD_InvalidClassList(ret,list,ccd->wasedit) ) {
+ free(ret);
+return;
+ }
+ if ( ccd->wasedit ) {
+ GListChangeLine8(list,GGadgetGetFirstListSelectedItem(list),ret);
+ } else {
+ GListAppendLine8(list,ret,false);
+ }
+ ccd->aw = aw_class;
+ GDrawSetVisible(ccd->classbuild,false);
+ GDrawSetVisible(ccd->class,true);
+ free(ret);
+ } else if ( ccd->wasoffset>=200 ) { /* It's class numbers */
+ unichar_t *ret;
+ memset(&dummy,0,sizeof(dummy));
+ CCD_ParseLookupList(ccd->sf,&dummy,GWidgetGetControl(ccd->gw,CID_LookupList+500));
+ if ( dummy.lookup_cnt==0 ) {
+ int ans = gwwv_ask(_("No Sequence/Lookups"),
+ (const char **) buts,0,1,
+ _("There are no entries in the Sequence/Lookup List, was this intentional?"));
+ if ( ans==1 )
+return;
+ }
+ if ( !CCD_ReasonableClassNum(
+ _GGadgetGetTitle(GWidgetGetControl(ccd->gw,CID_ClassNumbers)),
+ GWidgetGetControl(ccd->gw,CID_ClassList),
+ _GGadgetGetTitle(GWidgetGetControl(ccd->gw,CID_ClassNumbers+20)),
+ GWidgetGetControl(ccd->gw,CID_ClassList+20),
+ _GGadgetGetTitle(GWidgetGetControl(ccd->gw,CID_ClassNumbers+40)),
+ GWidgetGetControl(ccd->gw,CID_ClassList+40), &dummy )) {
+ FPSTRuleContentsFree(&dummy,pst_class);
+return;
+ }
+ for ( i=0; i<dummy.lookup_cnt; ++i ) {
+ if ( dummy.lookups[i].seq >= dummy.u.class.ncnt ) {
+ gwwv_post_error(_("Bad Sequence/Lookup List"),_("Sequence number out of bounds, must be less than %d (number of classes in list above)"), dummy.u.class.ncnt );
+return;
+ }
+ }
+ ret = clslistitem(&dummy);
+ FPSTRuleContentsFree(&dummy,pst_class);
+ if ( ccd->wasedit ) {
+ GListChangeLine(list,GGadgetGetFirstListSelectedItem(list),ret);
+ } else {
+ GListAppendLine(list,ret,false);
+ }
+ ccd->aw = aw_class;
+ GDrawSetVisible(ccd->classnumber,false);
+ GDrawSetVisible(ccd->class,true);
+ } else if ( ccd->wasoffset>=100 ) { /* It's from coverage */
+ char *ret = GGadgetGetTitle8(GWidgetGetControl(ccd->gw,CID_GlyphList+100));
+ if ( !CCD_NameListCheck(ccd->sf,ret,true,_("Bad Coverage")) ) {
+ free(ret);
+return;
+ }
+ if ( ccd->wasedit ) {
+ GListChangeLine8(list,GGadgetGetFirstListSelectedItem(list),ret);
+ } else {
+ GListAppendLine8(list,ret,false);
+ }
+ ccd->aw = aw_coverage;
+ GDrawSetVisible(ccd->cselect,false);
+ GDrawSetVisible(ccd->coverage,true);
+ free(ret);
+ } else { /* It's from glyph list */
+ unichar_t *ret; char *val;
+
+ memset(&dummy,0,sizeof(dummy));
+ val = GGadgetGetTitle8(GWidgetGetControl(ccd->gw,CID_GlyphList));
+ if ( !CCD_NameListCheck(ccd->sf,val,true,_("Bad Match Glyph List")) ) {
+ free(val);
+return;
+ }
+ free(val);
+ val = GGadgetGetTitle8(GWidgetGetControl(ccd->gw,CID_GlyphList+20));
+ if ( !CCD_NameListCheck(ccd->sf,val,false,_("Bad Backtrack Glyph List")) ) {
+ free(val);
+return;
+ }
+ free(val);
+ val = GGadgetGetTitle8(GWidgetGetControl(ccd->gw,CID_GlyphList+40));
+ if ( !CCD_NameListCheck(ccd->sf,val,false,_("Bad Lookahead Glyph List")) ) {
+ free(val);
+return;
+ }
+ free(val);
+ CCD_ParseLookupList(ccd->sf,&dummy,GWidgetGetControl(ccd->gw,CID_LookupList));
+ if ( dummy.lookup_cnt==0 ) {
+ int ans = gwwv_ask(_("No Sequence/Lookups"),
+ (const char **) buts,0,1,
+ _("There are no entries in the Sequence/Lookup List, was this intentional?"));
+ if ( ans==1 )
+return;
+ }
+ dummy.u.glyph.names = ccd_cu_copy(_GGadgetGetTitle(GWidgetGetControl(ccd->gw,CID_GlyphList)));
+ tot = CCD_GlyphNameCnt(_GGadgetGetTitle(GWidgetGetControl(ccd->gw,CID_GlyphList)));
+ for ( i=0; i<dummy.lookup_cnt; ++i ) {
+ if ( dummy.lookups[i].seq >= tot ) {
+ gwwv_post_error(_("Bad Sequence/Lookup List"),_("Sequence number out of bounds, must be less than %d (number of glyphs, classes or coverage tables)"), tot );
+return;
+ }
+ }
+ temp = ccd_cu_copy(_GGadgetGetTitle(GWidgetGetControl(ccd->gw,CID_GlyphList+20)));
+ dummy.u.glyph.back = reversenames(temp);
+ free(temp);
+ dummy.u.glyph.fore = ccd_cu_copy(_GGadgetGetTitle(GWidgetGetControl(ccd->gw,CID_GlyphList+40)));
+ ret = glistitem(&dummy);
+ FPSTRuleContentsFree(&dummy,pst_glyphs);
+ if ( ccd->wasedit ) {
+ GListChangeLine(list,GGadgetGetFirstListSelectedItem(list),ret);
+ } else {
+ GListAppendLine(list,ret,false);
+ }
+ ccd->aw = aw_glist;
+ GDrawSetVisible(ccd->glyphs,false);
+ GDrawSetVisible(ccd->glist,true);
+ }
+}
+
+static void _CCD_DoEditNew(struct contextchaindlg *ccd,int off,int isedit) {
+ static unichar_t nulstr[] = { 0 };
+ int i;
+
+ if ( off>=200 && off<300) { /* It's a list of class numbers from the class window */
+ int32 i, len;
+ GTextInfo **ti;
+ if ( isedit ) {
+ GGadget *list = GWidgetGetControl(ccd->gw,CID_GList+off);
+ struct fpst_rule dummy;
+ unichar_t *temp;
+ int32 len;
+ GTextInfo **old = GGadgetGetList(list,&len);
+ i = GGadgetGetFirstListSelectedItem(list);
+ if ( i==-1 )
+return;
+ memset(&dummy,0,sizeof(dummy));
+ clslistitem2rule(ccd->sf,old[i]->text,&dummy);
+ GGadgetSetTitle(GWidgetGetControl(ccd->gw,CID_ClassNumbers),
+ (temp=classnumbers(dummy.u.class.ncnt,dummy.u.class.nclasses)));
+ free(temp);
+ GGadgetSetTitle(GWidgetGetControl(ccd->gw,CID_ClassNumbers+20),
+ (temp=rclassnumbers(dummy.u.class.bcnt,dummy.u.class.bclasses)));
+ free(temp);
+ GGadgetSetTitle(GWidgetGetControl(ccd->gw,CID_ClassNumbers+40),
+ (temp=classnumbers(dummy.u.class.fcnt,dummy.u.class.fclasses)));
+ free(temp);
+ ti = slistlist(&dummy);
+ GGadgetSetList(GWidgetGetControl(ccd->gw,CID_LookupList+500),ti,false);
+ FPSTRuleContentsFree(&dummy,pst_class);
+ } else {
+ for ( i=0; i<3; ++i )
+ GGadgetSetTitle(GWidgetGetControl(ccd->gw,CID_ClassNumbers+i*20),nulstr);
+ GGadgetClearList(GWidgetGetControl(ccd->gw,CID_LookupList+500));
+ }
+ GWidgetIndicateFocusGadget(GWidgetGetControl(ccd->gw,CID_ClassNumbers));
+ for ( i=0; i<3; ++i ) {
+ if ( i!=0 && GGadgetIsChecked(GWidgetGetControl(ccd->gw,CID_SameAsClasses+i*20)) )
+ ti = GGadgetGetList(GWidgetGetControl(ccd->gw,CID_GList+300),&len);
+ else
+ ti = GGadgetGetList(GWidgetGetControl(ccd->gw,CID_GList+300+i*20),&len);
+ GGadgetSetList(GWidgetGetControl(ccd->gw,CID_ClassList+i*20),ti,true);
+ }
+ ccd->aw = aw_classnumber;
+ GDrawSetVisible(ccd->class,false);
+ GDrawSetVisible(ccd->classnumber,true);
+ } else if ( off>=100 ) { /* It's from coverage or class */
+ int to_off = off>=300 ? 300 : 100;
+ if ( isedit ) {
+ GGadget *list = GWidgetGetControl(ccd->gw,CID_GList+off);
+ int32 len;
+ GTextInfo **old = GGadgetGetList(list,&len);
+ i = GGadgetGetFirstListSelectedItem(list);
+ if ( i==-1 )
+return;
+ GGadgetSetTitle(GWidgetGetControl(ccd->gw,CID_GlyphList+to_off),old[i]->text);
+ } else {
+ GGadgetSetTitle(GWidgetGetControl(ccd->gw,CID_GlyphList+to_off),nulstr);
+ }
+ GWidgetIndicateFocusGadget(GWidgetGetControl(ccd->gw,CID_GlyphList+to_off));
+ if ( off>=300 ) { /* It's a class from the class window */
+ ccd->aw = aw_classbuild;
+ GDrawSetVisible(ccd->class,false);
+ GDrawSetVisible(ccd->classbuild,true);
+ } else {
+ ccd->aw = aw_cselect;
+ GDrawSetVisible(ccd->coverage,false);
+ GDrawSetVisible(ccd->cselect,true);
+ }
+ } else { /* It's from glyph list */
+ unichar_t *temp; char *temp2;
+ if ( isedit ) {
+ struct fpst_rule dummy;
+ GGadget *list = GWidgetGetControl(ccd->gw,CID_GList+off);
+ int32 len; int i;
+ GTextInfo **old = GGadgetGetList(list,&len), **ti;
+ i = GGadgetGetFirstListSelectedItem(list);
+ if ( i==-1 )
+return;
+ memset(&dummy,0,sizeof(dummy));
+ glistitem2rule(ccd->sf,old[i]->text,&dummy);
+ GGadgetSetTitle(GWidgetGetControl(ccd->gw,CID_GlyphList),(temp=uc_copy(dummy.u.glyph.names)));
+ free(temp);
+ GGadgetSetTitle(GWidgetGetControl(ccd->gw,CID_GlyphList+20),(temp=uc_copy((temp2 = reversenames(dummy.u.glyph.back))==NULL ? "" : temp2)));
+ free(temp); free(temp2);
+ GGadgetSetTitle(GWidgetGetControl(ccd->gw,CID_GlyphList+40),(temp=uc_copy(dummy.u.glyph.fore?dummy.u.glyph.fore:"")));
+ free(temp);
+ ti = slistlist(&dummy);
+ GGadgetSetList(GWidgetGetControl(ccd->gw,CID_LookupList),ti,false);
+ FPSTRuleContentsFree(&dummy,pst_glyphs);
+ } else {
+ for ( i=0; i<3; ++i )
+ GGadgetSetTitle(GWidgetGetControl(ccd->gw,CID_GlyphList+i*20),nulstr);
+ GGadgetClearList(GWidgetGetControl(ccd->gw,CID_LookupList));
+ }
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_LEdit),false);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_LDelete),false);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_LUp),false);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_LDown),false);
+ ccd->aw = aw_glyphs;
+ GDrawSetVisible(ccd->glist,false);
+ GDrawSetVisible(ccd->glyphs,true);
+ }
+ CCD_EnableNextPrev(ccd);
+ ccd->wasedit = isedit;
+ ccd->wasoffset = off;
+}
+
+static void _CCD_ToSelection(struct contextchaindlg *ccd,int cid,int order_matters ) {
+ const unichar_t *ret = _GGadgetGetTitle(GWidgetGetControl(ccd->gw,cid));
+ SplineFont *sf = ccd->sf;
+ FontView *fv = sf->fv;
+ const unichar_t *end;
+ int i,pos, found=-1;
+ char *nm;
+
+ GDrawRaise(fv->gw);
+ GDrawSetVisible(fv->gw,true);
+ memset(fv->selected,0,fv->map->enccount);
+ i=1;
+ while ( *ret ) {
+ end = u_strchr(ret,' ');
+ if ( end==NULL ) end = ret+u_strlen(ret);
+ nm = cu_copybetween(ret,end);
+ for ( ret = end; isspace(*ret); ++ret);
+ if (( pos = SFFindSlot(sf,fv->map,-1,nm))!=-1 ) {
+ if ( found==-1 ) found = pos;
+ fv->selected[pos] = i;
+ if ( order_matters && i<255 ) ++i;
+ }
+ free(nm);
+ }
+
+ if ( found!=-1 )
+ FVScrollToChar(fv,found);
+ GDrawRequestExpose(fv->v,NULL,false);
+}
+
+static int CCD_ToSelection(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_Select;
+ int isglyph = ccd->aw==aw_glyphs;
+
+ _CCD_ToSelection(ccd,CID_GlyphList+off,isglyph);
+ }
+return( true );
+}
+
+static int CCD_ToSelection2(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_Select2;
+
+ _CCD_ToSelection(ccd,CID_RplList+off,true);
+ }
+return( true );
+}
+#endif
+
+#ifndef LUA_FF_LIB
+
+static int BaseEnc(SplineChar *sc) {
+ int uni = sc->unicodeenc;
+
+ if ( uni==-1 || (uni>=0xe000 && uni<=0xf8ff)) { /* Private use or undefined */
+ char *pt = strchr(sc->name,'.');
+ if ( pt!=NULL ) {
+ *pt = '\0';
+ uni = UniFromName(sc->name,ui_none,NULL);
+ *pt = '.';
+ }
+ }
+return( uni );
+}
+
+static int GlyphInClass(char *name,char *glyphs) {
+ char *start, *pt;
+ int len = strlen(name);
+
+ for ( start = glyphs; *start ; ) {
+ pt = strchr(start,' ');
+ if ( pt==NULL ) {
+return( strcmp(name,start)==0 );
+ }
+ if ( pt-start==len && strncmp(name,start,len)==0 )
+return( true );
+ start = pt;
+ while ( *start==' ' ) ++start;
+ }
+return( false );
+}
+
+static char *addglyph(char *results,char *name) {
+ int len = strlen( results );
+ results = grealloc(results,len+strlen(name)+2);
+ if ( len!=0 ) {
+ results[len] = ' ';
+ strcpy( results+len+1,name );
+ } else
+ strcpy(results,name);
+return( results );
+}
+
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static int CCD_StdClass(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_StdClasses;
+ GTextInfo *ti = GGadgetGetListItemSelected(g);
+ char *glyphs, *results;
+ int any, gid, check_script, baseenc;
+ FeatureScriptLangList *fl = ccd->fpst->subtable->lookup->features;
+ SplineChar *sc;
+
+ if ( ti==NULL )
+return( true );
+ if ( strcmp((char *) ti->userdata,"None")==0 )
+return( true );
+
+ check_script= strcmp((char *) ti->userdata,"0-9")!=0;
+ if ( check_script && fl==NULL ) {
+ GGadgetSelectOneListItem(g,0);
+return( true );
+ }
+ glyphs = GGadgetGetTitle8(GWidgetGetControl(ccd->gw,CID_GlyphList+off));
+ results = copy(glyphs);
+ any = 0;
+
+ for ( gid=0; gid<ccd->sf->glyphcnt; ++gid ) if ( (sc=ccd->sf->glyphs[gid])!=NULL ) {
+ if ( check_script && !ScriptInFeatureScriptList(SCScriptFromUnicode(sc),fl))
+ continue;
+ baseenc = BaseEnc(sc);
+ if ( strcmp(ti->userdata,"Glyphs")==0 ) {
+ /* ok, we've checked the script, nothing else to do, it matches*/
+ } else if ( baseenc>=0x10000 || baseenc==-1 ) {
+ /* I don't have any tables outside bmp */
+ continue;
+ } else if ( strcmp(ti->userdata,"0-9")==0 ) {
+ if ( baseenc<'0' || baseenc>'9' )
+ continue;
+ } else if ( strcmp(ti->userdata,"Letters")==0 ) {
+ if ( !isalpha(baseenc))
+ continue;
+ } else if ( strcmp(ti->userdata,"LC")==0 ) {
+ if ( !islower(baseenc))
+ continue;
+ } else if ( strcmp(ti->userdata,"UC")==0 ) {
+ if ( !isupper(baseenc))
+ continue;
+ }
+ /* If we get here the glyph should be in the class */
+ if ( GlyphInClass(sc->name,glyphs))
+ continue; /* It's already there nothing for us to do */
+ results = addglyph(results,sc->name);
+ any = true;
+ }
+ if ( any ) {
+ GGadgetSelectOneListItem(g,sizeof(stdclasses)/sizeof(stdclasses[0])-2);
+ GGadgetSetTitle8(GWidgetGetControl(ccd->gw,CID_GlyphList+off),results);
+ } else
+ GGadgetSelectOneListItem(g,0);
+ free(glyphs); free(results);
+ }
+return( true );
+}
+#endif
+
+#ifndef LUA_FF_LIB
+static void _CCD_FromSelection(struct contextchaindlg *ccd,int cid,int order_matters ) {
+ SplineFont *sf = ccd->sf;
+ FontView *fv = sf->fv;
+ unichar_t *vals, *pt;
+ int i, j, len, max;
+ SplineChar *sc;
+
+ for ( i=len=max=0; i<fv->map->enccount; ++i ) if ( fv->selected[i]) {
+ sc = SFMakeChar(sf,fv->map,i);
+ len += strlen(sc->name)+1;
+ if ( fv->selected[i]>max ) max = fv->selected[i];
+ }
+ pt = vals = galloc((len+1)*sizeof(unichar_t));
+ *pt = '\0';
+ if ( order_matters ) {
+ /* in a glyph string the order of selection is important */
+ /* also in replacement list */
+ for ( j=1; j<=max; ++j ) {
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i]==j ) {
+ int gid = fv->map->map[i];
+ if ( gid!=-1 && sf->glyphs[gid]!=NULL ) {
+ uc_strcpy(pt,sf->glyphs[gid]->name);
+ pt += u_strlen(pt);
+ *pt++ = ' ';
+ }
+ }
+ }
+ } else {
+ /* in a coverage table (or class) the order of selection is irrelevant */
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] ) {
+ int gid = fv->map->map[i];
+ if ( gid!=-1 && sf->glyphs[gid]!=NULL ) {
+ uc_strcpy(pt,sf->glyphs[gid]->name);
+ pt += u_strlen(pt);
+ *pt++ = ' ';
+ }
+ }
+ }
+ if ( pt>vals ) pt[-1]='\0';
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ GGadgetSetTitle(GWidgetGetControl(ccd->gw,cid),vals);
+#endif
+ free(vals);
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static int CCD_FromSelection(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_Set;
+ int isglyph = ccd->aw==aw_glyphs;
+
+ _CCD_FromSelection(ccd,CID_GlyphList+off,isglyph);
+ }
+return( true );
+}
+
+static int CCD_FromSelection2(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_Set2;
+
+ _CCD_FromSelection(ccd,CID_RplList+off,true);
+ }
+return( true );
+}
+
+static int CCD_Delete(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_Delete;
+ GListDelSelected(GWidgetGetControl(ccd->gw,CID_GList+off));
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_Delete+off),false);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_Edit+off),false);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_Up+off),false);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_Down+off),false);
+ }
+return( true );
+}
+
+static int CCD_Up(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_Up;
+ GGadget *list = GWidgetGetControl(ccd->gw,CID_GList+off);
+ int32 len; int i;
+
+ (void) GGadgetGetList(list,&len);
+ GListMoveSelected(list,-1);
+ i = GGadgetGetFirstListSelectedItem(list);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_Up+off),i!=0);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_Down+off),i!=len-1);
+ }
+return( true );
+}
+
+static int CCD_Down(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_Down;
+ GGadget *list = GWidgetGetControl(ccd->gw,CID_GList+off);
+ int32 len; int i;
+
+ (void) GGadgetGetList(list,&len);
+ GListMoveSelected(list,1);
+ i = GGadgetGetFirstListSelectedItem(list);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_Up+off),i!=0);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_Down+off),i!=len-1);
+ }
+return( true );
+}
+
+static int CCD_Edit(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_Edit;
+ _CCD_DoEditNew(ccd,off,true);
+ }
+return( true );
+}
+
+static int CCD_New(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_New;
+ _CCD_DoEditNew(ccd,off,false);
+ }
+return( true );
+}
+
+static int CCD_GlyphSelected(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_GList;
+ int32 len; int i;
+
+ (void) GGadgetGetList(g,&len);
+ i = GGadgetGetFirstListSelectedItem(g);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_Up+off),i>0 &&
+ (i>1 || off<300));
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_Down+off),i!=len-1 &&
+ i!=-1 && (i!=0 || off<300));
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_Delete+off),i!=-1 &&
+ (i!=0 || off<300));
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_Edit+off),i!=-1 &&
+ (i!=0 || off<300));
+ } else if ( e->type==et_controlevent && e->u.control.subtype == et_listdoubleclick ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_GList;
+ int i = GGadgetGetFirstListSelectedItem(g);
+ if ( i!=0 || off<300 )
+ _CCD_DoEditNew(ccd,off,true);
+ }
+return( true );
+}
+
+static int CCD_SameAsClasses(GGadget *g, GEvent *e) {
+ int ison = GGadgetIsChecked(g);
+ int off = GGadgetGetCid(g)-CID_SameAsClasses;
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_GList+300+off),!ison);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_New+300+off),!ison);
+ if ( ison ) {
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_Edit+300+off),false);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_Delete+300+off),false);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_Up+300+off),false);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_Down+300+off),false);
+ } else {
+ GEvent ev;
+ memset(&ev,0,sizeof(ev));
+ ev.type =et_controlevent;
+ ev.u.control.subtype = et_listselected;
+ ev.u.control.g = GWidgetGetControl(ccd->gw,CID_GList+300+off);
+ CCD_GlyphSelected(ev.u.control.g,&ev);
+ }
+return( true );
+}
+
+static int CCD_ClassSelected(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_ClassList;
+ int i;
+ GGadget *tf = GWidgetGetControl(ccd->gw,CID_ClassNumbers+off);
+ char buf[20];
+ unichar_t ubuf[20];
+
+ i = GGadgetGetFirstListSelectedItem(g);
+ if ( i==-1 )
+return( true );
+ sprintf( buf, " %d ", i );
+ uc_strcpy(ubuf,buf);
+ GTextFieldReplace(tf,ubuf);
+ } else if ( e->type==et_controlevent && e->u.control.subtype == et_listdoubleclick ) {
+ }
+return( true );
+}
+
+static int CCD_LDelete(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_LDelete;
+ GListDelSelected(GWidgetGetControl(ccd->gw,CID_LookupList+off));
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_LDelete+off),false);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_LEdit+off),false);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_LUp+off),false);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_LDown+off),false);
+ }
+return( true );
+}
+
+static int CCD_LUp(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_LUp;
+ GGadget *list = GWidgetGetControl(ccd->gw,CID_LookupList+off);
+ int32 len; int i;
+
+ (void) GGadgetGetList(list,&len);
+ GListMoveSelected(list,-1);
+ i = GGadgetGetFirstListSelectedItem(list);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_LUp+off),i!=0);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_LDown+off),i!=len-1);
+ }
+return( true );
+}
+
+static int CCD_LDown(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_LDown;
+ GGadget *list = GWidgetGetControl(ccd->gw,CID_LookupList+off);
+ int32 len; int i;
+
+ (void) GGadgetGetList(list,&len);
+ GListMoveSelected(list,1);
+ i = GGadgetGetFirstListSelectedItem(list);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_LUp+off),i!=0);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_LDown+off),i!=len-1);
+ }
+return( true );
+}
+
+struct seqlook_data {
+ int done;
+ int ok;
+};
+
+static int seqlook_e_h(GWindow gw, GEvent *e) {
+ if ( e->type==et_close ) {
+ struct seqlook_data *d = GDrawGetUserData(gw);
+ d->done = true;
+ } else if ( e->type == et_char ) {
+return( false );
+ } else if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct seqlook_data *d = GDrawGetUserData(gw);
+ d->done = true;
+ d->ok = GGadgetGetCid(e->u.control.g);
+ }
+return( true );
+}
+
+static void _CCD_DoLEditNew(struct contextchaindlg *ccd,int off,int isedit) {
+ int seq, i;
+ char cbuf[20];
+ unichar_t nullstr[1], *end, *lstr = nullstr;
+ GGadget *list = GWidgetGetControl(ccd->gw,CID_LookupList+off);
+ struct seqlook_data d;
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[8];
+ GTextInfo label[8], **ti;
+ const unichar_t *pt;
+ unichar_t *line;
+ int selpos= -1;
+ int isgpos;
+
+ nullstr[0] = 0; seq = 0;
+ if ( isedit ) {
+ int32 len;
+ GTextInfo **ti = GGadgetGetList(list,&len);
+ selpos = GGadgetGetFirstListSelectedItem(list);
+ seq = u_strtol(ti[selpos]->text,&end,10);
+ if ( *end==' ' ) ++end;
+ lstr = end;
+ }
+
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Sequence/Lookup");
+ pos.x = pos.y = 0;
+ pos.width = GDrawPointsToPixels(NULL,180);
+ pos.height = GDrawPointsToPixels(NULL,130);
+ gw = GDrawCreateTopWindow(NULL,&pos,seqlook_e_h,&d,&wattrs);
+
+ memset(&label,0,sizeof(label));
+ memset(&gcd,0,sizeof(gcd));
+
+ label[0].text = (unichar_t *) _("Sequence Number:");
+ label[0].text_is_1byte = true;
+ gcd[0].gd.label = &label[0];
+ gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 6;
+ gcd[0].gd.flags = gg_visible | gg_enabled;
+ gcd[0].creator = GLabelCreate;
+
+ sprintf(cbuf,"%d",seq);
+ label[1].text = (unichar_t *) cbuf;
+ label[1].text_is_1byte = true;
+ gcd[1].gd.label = &label[1];
+ gcd[1].gd.pos.x = 10; gcd[1].gd.pos.y = 18;
+ gcd[1].gd.flags = gg_visible | gg_enabled;
+ gcd[1].gd.cid = 1000;
+ gcd[1].creator = GTextFieldCreate;
+
+ label[2].text = (unichar_t *) _("Lookup:");
+ label[2].text_is_1byte = true;
+ label[2].text_in_resource = true;
+ gcd[2].gd.label = &label[2];
+ gcd[2].gd.pos.x = 5; gcd[2].gd.pos.y = gcd[1].gd.pos.y+25;
+ gcd[2].gd.flags = gg_visible | gg_enabled;
+ gcd[2].creator = GLabelCreate;
+
+ gcd[3].gd.pos.x = 10; gcd[3].gd.pos.y = gcd[2].gd.pos.y+13;
+ gcd[3].gd.pos.width = 140;
+ gcd[3].gd.flags = gg_visible | gg_enabled;
+ gcd[3].creator = GListButtonCreate;
+
+ gcd[4].gd.pos.x = 20-3; gcd[4].gd.pos.y = 130-35-3;
+ gcd[4].gd.pos.width = -1; gcd[4].gd.pos.height = 0;
+ gcd[4].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[4].text = (unichar_t *) _("_OK");
+ label[4].text_is_1byte = true;
+ label[4].text_in_resource = true;
+ gcd[4].gd.label = &label[4];
+ gcd[4].gd.cid = true;
+ gcd[4].creator = GButtonCreate;
+
+ gcd[5].gd.pos.x = -20; gcd[5].gd.pos.y = 130-35;
+ gcd[5].gd.pos.width = -1; gcd[5].gd.pos.height = 0;
+ gcd[5].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[5].text = (unichar_t *) _("_Cancel");
+ label[5].text_is_1byte = true;
+ label[5].text_in_resource = true;
+ gcd[5].gd.label = &label[5];
+ gcd[5].creator = GButtonCreate;
+
+ gcd[6].gd.pos.x = 2; gcd[6].gd.pos.y = 2;
+ gcd[6].gd.pos.width = pos.width-4; gcd[6].gd.pos.height = pos.height-2;
+ gcd[6].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
+ gcd[6].creator = GGroupCreate;
+
+ GGadgetsCreate(gw,gcd);
+ isgpos = ( ccd->fpst->type==pst_contextpos || ccd->fpst->type==pst_chainpos );
+ GGadgetSetList(gcd[3].ret, ti = SFLookupListFromType(ccd->sf,ot_undef),false);
+ for ( i=0; ti[i]->text!=NULL; ++i )
+ if ( u_strcmp(lstr,ti[i]->text)==0 ) {
+ GGadgetSelectOneListItem(gcd[3].ret,i);
+ break;
+ }
+ GDrawSetVisible(gw,true);
+
+ retry:
+ memset(&d,'\0',sizeof(d));
+ while ( !d.done )
+ GDrawProcessOneEvent(NULL);
+
+ if ( d.ok ) {
+ int err = false;
+ seq = GetInt8(gw,1000,_("Sequence Position:"),&err);
+ if ( err )
+ goto retry;
+ pt = _GGadgetGetTitle(gcd[3].ret);
+ if ( *pt=='\0' ) {
+ gwwv_post_error("Please select a lookup", "Please select a lookup");
+ goto retry;
+ }
+ sprintf(cbuf,"%d ",seq);
+ line = galloc((strlen(cbuf)+u_strlen(pt)+4)*sizeof(unichar_t));
+ uc_strcpy(line,cbuf);
+ u_strcat(line,pt);
+ if ( isedit )
+ GListChangeLine(list,selpos,line);
+ else
+ GListAppendLine(list,line,false);
+ free(line);
+ }
+ GDrawDestroyWindow(gw);
+}
+
+static int CCD_LEdit(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_LEdit;
+ _CCD_DoLEditNew(ccd,off,true);
+ }
+return( true );
+}
+
+static int CCD_LNew(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_LNew;
+ _CCD_DoLEditNew(ccd,off,false);
+ }
+return( true );
+}
+
+static int CCD_LookupSelected(GGadget *g, GEvent *e) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_LookupList;
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ int32 len; int i;
+
+ (void) GGadgetGetList(g,&len);
+ i = GGadgetGetFirstListSelectedItem(g);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_LUp+off),i>0);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_LDown+off),i!=len-1 && i!=-1);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_LDelete+off),i!=-1);
+ GGadgetSetEnabled(GWidgetGetControl(ccd->gw,CID_LEdit+off),i!=-1);
+ } else if ( e->type==et_controlevent && e->u.control.subtype == et_listdoubleclick ) {
+ _CCD_DoLEditNew(ccd,off,true);
+ }
+return( true );
+}
+
+void CCD_Close(struct contextchaindlg *ccd) {
+ if ( ccd->isnew )
+ GFI_FinishContextNew(ccd->gfi,ccd->fpst,false);
+ GFI_CCDEnd(ccd->gfi);
+ GDrawDestroyWindow(ccd->gw);
+}
+
+static char **CCD_ParseCoverageList(struct contextchaindlg *ccd,int cid,int *cnt) {
+ int i;
+ int32 _cnt;
+ GTextInfo **ti = GGadgetGetList(GWidgetGetControl(ccd->gw,cid),&_cnt);
+ char **ret;
+
+ *cnt = _cnt;
+ if ( _cnt==0 )
+return( NULL );
+ ret = galloc(*cnt*sizeof(char *));
+ for ( i=0; i<_cnt; ++i )
+ ret[i] = ccd_cu_copy(ti[i]->text);
+return( ret );
+}
+
+static void CoverageReverse(char **bcovers,int bcnt) {
+ int i;
+ char *temp;
+
+ for ( i=0; i<bcnt/2; ++i ) {
+ temp = bcovers[i];
+ bcovers[i] = bcovers[bcnt-i-1];
+ bcovers[bcnt-i-1] = temp;
+ }
+}
+
+static void _CCD_Ok(struct contextchaindlg *ccd) {
+ FPST *fpst = ccd->fpst;
+ int32 len, i, k;
+ GTextInfo **old, **classes;
+ struct fpst_rule dummy;
+ int has[3];
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buts[3];
+ buts[0] = _("_Yes"); buts[1] = _("_No"); buts[2] = NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buts[] = { GTK_STOCK_YES, GTK_STOCK_NO, NULL };
+#endif
+
+ switch ( ccd->aw ) {
+ case aw_glist: {
+ old = GGadgetGetList(GWidgetGetControl(ccd->gw,CID_GList),&len);
+ if ( len==0 ) {
+ gwwv_post_error(_("Missing rules"),_(" There must be at least one contextual rule"));
+return;
+ }
+ FPSTRulesFree(fpst->rules,fpst->format,fpst->rule_cnt);
+ fpst->format = pst_glyphs;
+ fpst->rule_cnt = len;
+ fpst->rules = gcalloc(len,sizeof(struct fpst_rule));
+ for ( i=0; i<len; ++i )
+ glistitem2rule(ccd->sf,old[i]->text,&fpst->rules[i]);
+ } break;
+ case aw_class: {
+ old = GGadgetGetList(GWidgetGetControl(ccd->gw,CID_GList+200),&len);
+ if ( len==0 ) {
+ gwwv_post_error(_("Missing rules"),_(" There must be at least one contextual rule"));
+return;
+ }
+ FPSTRulesFree(fpst->rules,fpst->format,fpst->rule_cnt);
+ fpst->format = pst_class;
+ fpst->rule_cnt = len;
+ fpst->rules = gcalloc(len,sizeof(struct fpst_rule));
+ fpst->nccnt = fpst->bccnt = fpst->fccnt = 0;
+ fpst->nclass = fpst->bclass = fpst->fclass = NULL;
+ has[1] = has[2] = false; has[0] = true;
+ for ( i=0; i<len; ++i ) {
+ clslistitem2rule(ccd->sf,old[i]->text,&fpst->rules[i]);
+ if ( fpst->rules[i].u.class.bcnt!=0 ) has[1] = true;
+ if ( fpst->rules[i].u.class.fcnt!=0 ) has[2] = true;
+ }
+ for ( i=0; i<3; ++i ) {
+ if ( i==0 || !GGadgetIsChecked(GWidgetGetControl(ccd->gw,CID_SameAsClasses+i*20)) )
+ classes = GGadgetGetList(GWidgetGetControl(ccd->gw,CID_GList+300+i*20),&len);
+ else if ( has[i] )
+ classes = GGadgetGetList(GWidgetGetControl(ccd->gw,CID_GList+300),&len);
+ else
+ continue;
+ (&fpst->nccnt)[i] = len;
+ (&fpst->nclass)[i] = galloc(len*sizeof(char*));
+ (&fpst->nclass)[i][0] = NULL;
+ for ( k=1; k<len; ++k )
+ (&fpst->nclass)[i][k] = cu_copy(classes[k]->text);
+ }
+ } break;
+ case aw_coverage:
+ old = GGadgetGetList(GWidgetGetControl(ccd->gw,CID_GList+100),&len);
+ if ( len==0 ) {
+ gwwv_post_error(_("Bad Coverage Table"),_("There must be at least one match coverage table"));
+return;
+ }
+ if ( fpst->format==pst_reversecoverage ) {
+ if ( len!=1 ) {
+ gwwv_post_error(_("Bad Coverage Table"),_("In a Reverse Chaining Substitution there must be exactly one coverage table to match"));
+return;
+ }
+ if ( CCD_GlyphNameCnt(old[0]->text)!=CCD_GlyphNameCnt(
+ _GGadgetGetTitle(GWidgetGetControl(ccd->gw,CID_RplList+100))) ) {
+ gwwv_post_error(_("Replacement mismatch"),_("In a Reverse Chaining Substitution there must be exactly as many replacements as there are glyph names in the match coverage table"));
+return;
+ }
+ dummy.u.rcoverage.replacements = ccd_cu_copy(
+ _GGadgetGetTitle(GWidgetGetControl(ccd->gw,CID_RplList+100)));
+ } else {
+ CCD_ParseLookupList(ccd->sf,&dummy,GWidgetGetControl(ccd->gw,CID_LookupList+100));
+ if ( dummy.lookup_cnt==0 ) {
+ int ans = gwwv_ask(_("No Sequence/Lookups"),
+ (const char **) buts,0,1,
+ _("There are no entries in the Sequence/Lookup List, was this intentional?"));
+ if ( ans==1 )
+return;
+ }
+ }
+ FPSTRulesFree(fpst->rules,fpst->format,fpst->rule_cnt);
+ fpst->format = fpst->type==pst_reversesub ? pst_reversecoverage : pst_coverage;
+ fpst->rule_cnt = 1;
+ fpst->rules = gcalloc(1,sizeof(struct fpst_rule));
+ fpst->rules[0].u.coverage.ncovers = CCD_ParseCoverageList(ccd,CID_GList+100,&fpst->rules[0].u.coverage.ncnt);
+ fpst->rules[0].u.coverage.bcovers = CCD_ParseCoverageList(ccd,CID_GList+100+20,&fpst->rules[0].u.coverage.bcnt);
+ CoverageReverse(fpst->rules[0].u.coverage.bcovers,fpst->rules[0].u.coverage.bcnt);
+ fpst->rules[0].u.coverage.fcovers = CCD_ParseCoverageList(ccd,CID_GList+100+40,&fpst->rules[0].u.coverage.fcnt);
+ if ( fpst->format==pst_reversecoverage )
+ fpst->rules[0].u.rcoverage.replacements = dummy.u.rcoverage.replacements;
+ else {
+ fpst->rules[0].lookup_cnt = dummy.lookup_cnt;
+ fpst->rules[0].lookups = dummy.lookups;
+ for ( i=0; i<dummy.lookup_cnt; ++i ) {
+ if ( dummy.lookups[i].seq >= fpst->rules[0].u.coverage.ncnt ) {
+ gwwv_post_error(_("Bad Sequence/Lookup List"),
+ _("Sequence number out of bounds, must be less than %d (number of classes in list above)"),
+ fpst->rules[0].u.coverage.ncnt );
+return;
+ }
+ }
+ }
+ break;
+ default:
+ IError("The OK button should not be enabled here");
+return;
+ }
+ if ( ccd->isnew )
+ GFI_FinishContextNew(ccd->gfi,ccd->fpst,true);
+ GFI_CCDEnd(ccd->gfi);
+ GDrawDestroyWindow(ccd->gw);
+}
+
+static int CCD_OK(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ _CCD_Ok(ccd);
+ }
+return( true );
+}
+
+static int CCD_Cancel(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ CCD_Close(ccd);
+ }
+return( true );
+}
+
+static int CCD_Next(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ switch ( ccd->aw ) {
+ case aw_formats:
+ GDrawSetVisible(ccd->formats,false);
+ if ( GGadgetIsChecked(GWidgetGetControl(ccd->gw,CID_ByGlyph)) ) {
+ ccd->aw = aw_glist;
+ GDrawSetVisible(ccd->glist,true);
+ } else if ( GGadgetIsChecked(GWidgetGetControl(ccd->gw,CID_ByClass)) ) {
+ ccd->aw = aw_class;
+ GDrawSetVisible(ccd->class,true);
+ } else {
+ ccd->aw = aw_coverage;
+ GDrawSetVisible(ccd->coverage,true);
+ }
+ break;
+ case aw_glyphs:
+ case aw_classnumber:
+ case aw_classbuild:
+ case aw_cselect:
+ CCD_FinishEditNew(ccd);
+ break;
+ default:
+ IError("The next button should not be enabled here");
+ break;
+ }
+ CCD_EnableNextPrev(ccd);
+ }
+return( true );
+}
+
+static int CCD_Prev(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(GGadgetGetWindow(g));
+ switch ( ccd->aw ) {
+ case aw_formats:
+ CCD_Cancel(g,e);
+ break;
+ case aw_glyphs:
+ ccd->aw = aw_glist;
+ GDrawSetVisible(ccd->glyphs,false);
+ GDrawSetVisible(ccd->glist,true);
+ break;
+ case aw_cselect:
+ ccd->aw = aw_coverage;
+ GDrawSetVisible(ccd->cselect,false);
+ GDrawSetVisible(ccd->coverage,true);
+ break;
+ case aw_classnumber:
+ case aw_classbuild:
+ ccd->aw = aw_class;
+ GDrawSetVisible(ccd->classbuild,false);
+ GDrawSetVisible(ccd->classnumber,false);
+ GDrawSetVisible(ccd->class,true);
+ break;
+ case aw_coverage:
+ case aw_class:
+ case aw_glist:
+ ccd->aw = aw_formats;
+ GDrawSetVisible(ccd->coverage,false);
+ GDrawSetVisible(ccd->class,false);
+ GDrawSetVisible(ccd->glist,false);
+ GDrawSetVisible(ccd->formats,true);
+ break;
+ default:
+ IError("Can't get here");
+ break;
+ }
+ CCD_EnableNextPrev(ccd);
+ }
+return( true );
+}
+
+static void CCD_SimulateDefaultButton( struct contextchaindlg *ccd ) {
+ GEvent ev;
+ int i,j;
+
+ /* figure out what the default action should be */
+ memset(&ev,0,sizeof(ev));
+ ev.type = et_controlevent;
+ ev.u.control.subtype = et_buttonactivate;
+ if ( ccd->aw==aw_formats || ccd->aw == aw_glyphs || ccd->aw == aw_cselect ) {
+ ev.u.control.g = GWidgetGetControl(ccd->gw,CID_Next);
+ CCD_Next(ev.u.control.g,&ev);
+/* For the glyph list and the coverage list, the [Next] button is disabled */
+/* I think [OK] is probably inappropriate, so let's do either [New] or [Edit] */
+/* (which are what [Next] would logically do) depending on which of the two */
+/* is more appropriate */
+/* ev.u.control.g = GWidgetGetControl(ccd->gw,CID_OK); */
+/* CCD_OK(ev.u.control.g,&ev); */
+ } else if ( ccd->aw==aw_glist ) {
+ i = GGadgetGetFirstListSelectedItem( GWidgetGetControl(ccd->gw,CID_GList));
+ if ( i==-1 ) {
+ ev.u.control.g = GWidgetGetControl(ccd->gw,CID_New);
+ CCD_New(ev.u.control.g,&ev);
+ } else {
+ ev.u.control.g = GWidgetGetControl(ccd->gw,CID_Edit);
+ CCD_Edit(ev.u.control.g,&ev);
+ }
+ } else {
+ i = GTabSetGetSel( GWidgetGetControl(ccd->gw,CID_MatchType+100));
+ j = GGadgetGetFirstListSelectedItem( GWidgetGetControl(ccd->gw,CID_GList+100+i*20));
+ if ( j==-1 ) {
+ ev.u.control.g = GWidgetGetControl(ccd->gw,CID_New+100+i*20);
+ CCD_New(ev.u.control.g,&ev);
+ } else {
+ ev.u.control.g = GWidgetGetControl(ccd->gw,CID_Edit+100+i*20);
+ CCD_Edit(ev.u.control.g,&ev);
+ }
+ }
+}
+
+static void CCD_Drop(struct contextchaindlg *ccd,GEvent *event) {
+ char *cnames;
+ unichar_t *unames, *pt;
+ const unichar_t *ret;
+ GGadget *g;
+ int32 len;
+
+ if ( ccd->aw != aw_glyphs && ccd->aw != aw_cselect &&
+ (ccd->aw != aw_coverage || ccd->fpst->format!=pst_reversecoverage)) {
+ GDrawBeep(NULL);
+return;
+ }
+
+ if ( ccd->aw==aw_cselect )
+ g = GWidgetGetControl(ccd->gw,CID_GlyphList+100);
+ else if ( ccd->aw==aw_glyphs ) {
+ int which = GTabSetGetSel(GWidgetGetControl(ccd->glyphs,CID_MatchType));
+ g = GWidgetGetControl(ccd->gw,CID_GlyphList+20*which);
+ } else {
+ int which = GTabSetGetSel(GWidgetGetControl(ccd->coverage,CID_MatchType+100));
+ if ( which!=0 ) {
+ GDrawBeep(NULL);
+return;
+ }
+ g = GWidgetGetControl(ccd->gw,CID_RplList+100);
+ }
+
+ if ( !GDrawSelectionHasType(ccd->gw,sn_drag_and_drop,"STRING"))
+return;
+ cnames = GDrawRequestSelection(ccd->gw,sn_drag_and_drop,"STRING",&len);
+ if ( cnames==NULL )
+return;
+
+ ret = _GGadgetGetTitle(g);
+ unames = galloc((strlen(cnames)+u_strlen(ret)+8)*sizeof(unichar_t));
+ u_strcpy(unames,ret);
+ pt = unames+u_strlen(unames);
+ if ( pt>unames && pt[-1]!=' ' )
+ uc_strcpy(pt," ");
+ uc_strcat(pt,cnames);
+ free(cnames);
+
+ GGadgetSetTitle(g,unames);
+}
+
+static int subccd_e_h(GWindow gw, GEvent *event) {
+ if ( event->type==et_char ) {
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("contextchain.html");
+return( true );
+ } else if ( event->u.chr.keysym=='q' && (event->u.chr.state&ksm_control)) {
+ if ( event->u.chr.state&ksm_shift )
+ CCD_Close(GDrawGetUserData(gw));
+ else
+ MenuExit(NULL,NULL,NULL);
+return( true );
+ } else if ( event->u.chr.chars[0]=='\r' ) {
+ CCD_SimulateDefaultButton( (struct contextchaindlg *) GDrawGetUserData(gw));
+return( true );
+ }
+return( false );
+ } else if ( event->type == et_drop ) {
+ CCD_Drop(GDrawGetUserData(gw),event);
+ }
+return( true );
+}
+
+static int ccd_e_h(GWindow gw, GEvent *event) {
+ if ( event->type==et_close ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(gw);
+ CCD_Close(ccd);
+ } else if ( event->type==et_destroy ) {
+ struct contextchaindlg *ccd = GDrawGetUserData(gw);
+ chunkfree(ccd,sizeof(struct contextchaindlg));
+ } else if ( event->type==et_char ) {
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("contextchain.html");
+return( true );
+ } else if ( event->u.chr.keysym=='q' && (event->u.chr.state&ksm_control)) {
+ if ( event->u.chr.state&ksm_shift )
+ CCD_Close(GDrawGetUserData(gw));
+ else
+ MenuExit(NULL,NULL,NULL);
+return( true );
+ } else if ( event->u.chr.chars[0]=='\r' ) {
+ CCD_SimulateDefaultButton( (struct contextchaindlg *) GDrawGetUserData(gw));
+return( true );
+ }
+return( false );
+ } else if ( event->type==et_resize ) {
+ int blen = GDrawPointsToPixels(NULL,GIntGetResource(_NUM_Buttonsize)), i;
+ GRect wsize, csize;
+ struct contextchaindlg *ccd = GDrawGetUserData(gw);
+ GGadget *g;
+
+ GDrawGetSize(ccd->gw,&wsize);
+ GGadgetResize(GWidgetGetControl(ccd->gw,CID_Group),wsize.width-4,wsize.height-4);
+ GGadgetGetSize(GWidgetGetControl(ccd->gw,CID_OK),&csize);
+ GGadgetMove(GWidgetGetControl(ccd->gw,CID_OK),csize.x,wsize.height-ccd->canceldrop);
+ GGadgetGetSize(GWidgetGetControl(ccd->gw,CID_Next),&csize);
+ GGadgetMove(GWidgetGetControl(ccd->gw,CID_Next),csize.x,wsize.height-ccd->canceldrop);
+ GGadgetGetSize(GWidgetGetControl(ccd->gw,CID_Prev),&csize);
+ GGadgetMove(GWidgetGetControl(ccd->gw,CID_Prev),csize.x,wsize.height-ccd->canceldrop);
+ GGadgetGetSize(GWidgetGetControl(ccd->gw,CID_Cancel),&csize);
+ GGadgetMove(GWidgetGetControl(ccd->gw,CID_Cancel),wsize.width-blen-20,wsize.height-ccd->canceldrop);
+
+ GGadgetGetSize(GWidgetGetControl(ccd->gw,CID_MatchType),&csize);
+ GGadgetResize(GWidgetGetControl(ccd->gw,CID_MatchType),wsize.width-GDrawPointsToPixels(NULL,10),csize.height);
+ GGadgetGetSize(GWidgetGetControl(ccd->gw,CID_MatchType+100),&csize);
+ GGadgetResize(GWidgetGetControl(ccd->gw,CID_MatchType+100),wsize.width-GDrawPointsToPixels(NULL,10),csize.height);
+ GGadgetGetSize(GWidgetGetControl(ccd->gw,CID_LookupList),&csize);
+ GGadgetResize(GWidgetGetControl(ccd->gw,CID_LookupList),wsize.width-GDrawPointsToPixels(NULL,20),csize.height);
+ GGadgetGetSize(GWidgetGetControl(ccd->gw,CID_GList),&csize);
+ GGadgetResize(GWidgetGetControl(ccd->gw,CID_GList),wsize.width-GDrawPointsToPixels(NULL,20),csize.height);
+ if ( (g = GWidgetGetControl(ccd->gw,CID_LookupList+100))!=NULL ) {
+ GGadgetGetSize(g,&csize);
+ GGadgetResize(g,wsize.width-GDrawPointsToPixels(NULL,20),csize.height);
+ } else {
+ GGadgetGetSize(GWidgetGetControl(ccd->gw,CID_RplList+100),&csize);
+ GGadgetResize(GWidgetGetControl(ccd->gw,CID_RplList+100),wsize.width-GDrawPointsToPixels(NULL,25),csize.height);
+ }
+ for ( i=0; i<3; ++i ) {
+ if ( (g=GWidgetGetControl(ccd->gw,CID_GlyphList+i*20))!=NULL ) {
+ GGadgetGetSize(g,&csize);
+ GGadgetResize(g,wsize.width-GDrawPointsToPixels(NULL,25),csize.height);
+ }
+ if ( (g=GWidgetGetControl(ccd->gw,CID_GList+100+i*20))!=NULL ) {
+ GGadgetGetSize(g,&csize);
+ GGadgetResize(g,wsize.width-GDrawPointsToPixels(NULL,20),csize.height);
+ }
+ }
+ if ( (g=GWidgetGetControl(ccd->gw,CID_GlyphList+100))!=NULL ) {
+ GGadgetGetSize(g,&csize);
+ GGadgetResize(g,wsize.width-GDrawPointsToPixels(NULL,25),csize.height);
+ }
+
+ GDrawResize(ccd->formats,wsize.width-8,wsize.height-ccd->subheightdiff);
+ GDrawResize(ccd->coverage,wsize.width-8,wsize.height-ccd->subheightdiff);
+ GDrawResize(ccd->glist,wsize.width-8,wsize.height-ccd->subheightdiff);
+ GDrawResize(ccd->glyphs,wsize.width-8,wsize.height-ccd->subheightdiff);
+ GDrawResize(ccd->cselect,wsize.width-8,wsize.height-ccd->subheightdiff);
+ GDrawResize(ccd->class,wsize.width-8,wsize.height-ccd->subheightdiff);
+
+ GDrawRequestExpose(ccd->gw,NULL,false);
+ GDrawRequestExpose(ccd->aw==aw_formats ? ccd->formats :
+ ccd->aw==aw_coverage ? ccd->coverage :
+ ccd->aw==aw_glist ? ccd->glist :
+ ccd->aw==aw_glyphs ? ccd->glyphs :
+ ccd->cselect, NULL,false);
+ } else if ( event->type == et_drop ) {
+ CCD_Drop(GDrawGetUserData(gw),event);
+ }
+return( true );
+}
+
+#define CCD_WIDTH 340
+#define CCD_HEIGHT 340
+
+static int CCD_AddGList(GGadgetCreateData *gcd, GTextInfo *label,int off,
+ int y, int width,int height) {
+ int k = 0, space;
+ int blen = GIntGetResource(_NUM_Buttonsize);
+
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = y;
+ gcd[k].gd.pos.width = width;
+ gcd[k].gd.pos.height = height;
+ gcd[k].gd.flags = gg_visible | gg_enabled;
+ gcd[k].gd.handle_controlevent = CCD_GlyphSelected;
+ gcd[k].gd.cid = CID_GList+off;
+ gcd[k++].creator = GListCreate;
+
+ space = width==CCD_WIDTH-30 ? 7 : 10;
+ label[k].text = (unichar_t *) S_("Class|_New");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+gcd[k-1].gd.pos.height+10;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible | gg_enabled;
+ gcd[k].gd.handle_controlevent = CCD_New;
+ gcd[k].gd.cid = CID_New+off;
+ gcd[k++].creator = GButtonCreate;
+
+ label[k].text = (unichar_t *) _("_Edit");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 5+blen+space; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible;
+ gcd[k].gd.handle_controlevent = CCD_Edit;
+ gcd[k].gd.cid = CID_Edit+off;
+ gcd[k++].creator = GButtonCreate;
+
+ label[k].text = (unichar_t *) _("_Delete");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = gcd[k-1].gd.pos.x+blen+space; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible;
+ gcd[k].gd.handle_controlevent = CCD_Delete;
+ gcd[k].gd.cid = CID_Delete+off;
+ gcd[k++].creator = GButtonCreate;
+
+ label[k].text = (unichar_t *) _("_Up");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = gcd[k-1].gd.pos.x+blen+space+5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible;
+ gcd[k].gd.handle_controlevent = CCD_Up;
+ gcd[k].gd.cid = CID_Up+off;
+ gcd[k++].creator = GButtonCreate;
+
+ label[k].text = (unichar_t *) _("_Down");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = gcd[k-1].gd.pos.x+blen+space; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible;
+ gcd[k].gd.handle_controlevent = CCD_Down;
+ gcd[k].gd.cid = CID_Down+off;
+ gcd[k++].creator = GButtonCreate;
+
+return( k );
+}
+
+static int CCD_AddGlyphList(GGadgetCreateData *gcd, GTextInfo *label,int off,
+ int y, int height) {
+ int k;
+ static int inited = 0;
+
+ if ( !inited ) {
+ for ( k=0; stdclasses[k].text!=NULL; ++k )
+ stdclasses[k].text = (unichar_t *) _((char *) stdclasses[k].text);
+ inited = true;
+ }
+
+ k=0;
+ label[k].text = (unichar_t *) _("Set From Font");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = y;
+ gcd[k].gd.popup_msg = (unichar_t *) _("Set this glyph list to be the characters selected in the fontview");
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ gcd[k].gd.handle_controlevent = CCD_FromSelection;
+ gcd[k].gd.cid = CID_Set+off;
+ gcd[k++].creator = GButtonCreate;
+
+ label[k].text = (unichar_t *) _("Select In Font");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 110; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
+ gcd[k].gd.popup_msg = (unichar_t *) _("Set the fontview's selection to be the characters named here");
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ gcd[k].gd.handle_controlevent = CCD_ToSelection;
+ gcd[k].gd.cid = CID_Select+off;
+ gcd[k++].creator = GButtonCreate;
+
+ if ( off>100 ) { /* Don't add for glyph lists */
+ label[k].text = (unichar_t *) _("Add Standard Class:");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = y+24+6;
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ gcd[k++].creator = GLabelCreate;
+
+ gcd[k].gd.pos.x = 110; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-6;
+ gcd[k].gd.popup_msg = (unichar_t *) _("Add one of these standard classes of glyphs to the current class");
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ gcd[k].gd.u.list = stdclasses;
+ gcd[k].gd.handle_controlevent = CCD_StdClass;
+ gcd[k].gd.cid = CID_StdClasses+off;
+ gcd[k++].creator = GListButtonCreate;
+
+ y+=24;
+ }
+
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = y+24;
+ gcd[k].gd.pos.width = CCD_WIDTH-25; gcd[k].gd.pos.height = 8*13+4;
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_textarea_wrap;
+ gcd[k].gd.cid = CID_GlyphList+off;
+ gcd[k++].creator = GTextAreaCreate;
+return( k );
+}
+
+static void CCD_AddSeqLookup(GGadgetCreateData *gcd, GTextInfo *label,int off,
+ int y, int width, int height) {
+ int k, space;
+ int blen = GIntGetResource(_NUM_Buttonsize);
+
+ k = 0;
+ space = width==CCD_WIDTH-30 ? 7 : 10;
+ label[k].text = (unichar_t *) _("An ordered list of sequence positions and lookup tags");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = y;
+ gcd[k].gd.flags = gg_visible | gg_enabled;
+ gcd[k++].creator = GLabelCreate;
+
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+13;
+ gcd[k].gd.pos.width = width;
+ gcd[k].gd.pos.height = height;
+ gcd[k].gd.flags = gg_visible | gg_enabled;
+ gcd[k].gd.handle_controlevent = CCD_LookupSelected;
+ gcd[k].gd.cid = CID_LookupList+off;
+ gcd[k++].creator = GListCreate;
+
+ label[k].text = (unichar_t *) S_("Lookup|_New");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+gcd[k-1].gd.pos.height+10;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible | gg_enabled;
+ gcd[k].gd.handle_controlevent = CCD_LNew;
+ gcd[k].gd.cid = CID_LNew+off;
+ gcd[k++].creator = GButtonCreate;
+
+ label[k].text = (unichar_t *) _("_Edit");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = gcd[k-1].gd.pos.x+blen+space; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible;
+ gcd[k].gd.handle_controlevent = CCD_LEdit;
+ gcd[k].gd.cid = CID_LEdit+off;
+ gcd[k++].creator = GButtonCreate;
+
+ label[k].text = (unichar_t *) _("_Delete");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = gcd[k-1].gd.pos.x+blen+space; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible;
+ gcd[k].gd.handle_controlevent = CCD_LDelete;
+ gcd[k].gd.cid = CID_LDelete+off;
+ gcd[k++].creator = GButtonCreate;
+
+ label[k].text = (unichar_t *) _("_Up");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = gcd[k-1].gd.pos.x+blen+space+5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible;
+ gcd[k].gd.handle_controlevent = CCD_LUp;
+ gcd[k].gd.cid = CID_LUp+off;
+ gcd[k++].creator = GButtonCreate;
+
+ label[k].text = (unichar_t *) _("_Down");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = gcd[k-1].gd.pos.x+blen+space; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible;
+ gcd[k].gd.handle_controlevent = CCD_LDown;
+ gcd[k].gd.cid = CID_LDown+off;
+ gcd[k++].creator = GButtonCreate;
+}
+
+static void CCD_AddReplacements(GGadgetCreateData *gcd, GTextInfo *label,
+ struct fpst_rule *r,int off, int y) {
+ int k;
+
+ k=0;
+ label[k].text = (unichar_t *) _("Replacements");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = y;
+ gcd[k].gd.flags = gg_visible | gg_enabled;
+ gcd[k++].creator = GLabelCreate;
+
+ label[k].text = (unichar_t *) _("Set From Font");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+13;
+ gcd[k].gd.popup_msg = (unichar_t *) _("Set this glyph list to be the characters selected in the fontview");
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ gcd[k].gd.handle_controlevent = CCD_FromSelection2;
+ gcd[k].gd.cid = CID_Set2+off;
+ gcd[k++].creator = GButtonCreate;
+
+ label[k].text = (unichar_t *) _("Select In Font");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 110; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
+ gcd[k].gd.popup_msg = (unichar_t *) _("Set the fontview's selection to be the characters named here");
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ gcd[k].gd.handle_controlevent = CCD_ToSelection2;
+ gcd[k].gd.cid = CID_Select2+off;
+ gcd[k++].creator = GButtonCreate;
+
+ if ( r!=NULL && r->u.rcoverage.replacements!=NULL ) {
+ label[k].text = (unichar_t *) r->u.rcoverage.replacements;
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ }
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+25;
+ gcd[k].gd.pos.width = CCD_WIDTH-25; gcd[k].gd.pos.height = 4*13+4;
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_textarea_wrap;
+ gcd[k].gd.cid = CID_RplList+off;
+ gcd[k++].creator = GTextAreaCreate;
+}
+#endif
+
+struct contextchaindlg *ContextChainEdit(SplineFont *sf,FPST *fpst,
+ struct gfi_data *gfi, unichar_t *newname) {
+ struct contextchaindlg *ccd;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ int i,j,k, space;
+ static char *titles[2][5] = {
+ { N_("Edit Contextual Position"), N_("Edit Contextual Substitution"),
+ N_("Edit Chaining Position"), N_("Edit Chaining Substitution"),
+ N_("Edit Reverse Chaining Substitution"),
+ },
+ { N_("New Contextual Position"), N_("New Contextual Substitution"),
+ N_("New Chaining Position"), N_("New Chaining Substitution"),
+ N_("New Reverse Chaining Substitution")
+ }};
+ GRect pos, subpos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GTabInfo faspects[5];
+ GGadgetCreateData glgcd[8], fgcd[3], ggcd[3][14], cgcd[3][18], csgcd[6],
+ clgcd[10];
+ GTextInfo gllabel[8], flabel[3], glabel[3][14], clabel[3][18], cslabel[6],
+ cllabel[10];
+ GGadgetCreateData bgcd[6], rgcd[15];
+ GTextInfo blabel[4], rlabel[15];
+ int blen = GIntGetResource(_NUM_Buttonsize)*100/GGadgetScale(100);
+ struct fpst_rule *r=NULL;
+ char *text[] = {
+/* GT: The following strings should be concatenated together, the result */
+/* GT: translated, and then broken into lines by hand. I'm sure it would */
+/* GT: be better to specify this all as one string, but my widgets won't support */
+/* GT: that */
+ N_("OpenType Contextual or Chaining subtables may be in one"),
+ N_(" of three formats. The context may be specified either"),
+ N_(" as a string of specific glyphs, a string of glyph classes,"), N_(" or a string of coverage tables."),
+ N_("In the first format you must specify a string of glyph-names."), N_(" In the second format you must specify a string of class numbers."),
+ N_(" In the third format you must specify a string each element"), N_(" of which may contain several glyph-names."),
+ N_("For chaining subtables you may also specify backtrack and"),
+ N_(" lookahead lists."), 0 };
+ FPST *tempfpst;
+#endif
+
+ ccd = chunkalloc(sizeof(struct contextchaindlg));
+ ccd->gfi = gfi;
+ ccd->sf = sf;
+ ccd->fpst = fpst;
+ ccd->newname = newname;
+ ccd->isnew = newname!=NULL;
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.is_dlg = true;
+ wattrs.restrict_input_to_me = false;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _(titles[ccd->isnew][fpst->type-pst_contextpos]);
+ pos.x = pos.y = 0;
+ pos.width =GDrawPointsToPixels(NULL,GGadgetScale(CCD_WIDTH));
+ pos.height = GDrawPointsToPixels(NULL,CCD_HEIGHT);
+ ccd->gw = gw = GDrawCreateTopWindow(NULL,&pos,ccd_e_h,ccd,&wattrs);
+
+ subpos = pos;
+ subpos.y = subpos.x = 4;
+ subpos.width -= 8;
+ ccd->subheightdiff = GDrawPointsToPixels(NULL,44)-8;
+ subpos.height -= ccd->subheightdiff;
+
+
+ memset(&blabel,0,sizeof(blabel));
+ memset(&bgcd,0,sizeof(bgcd));
+
+ ccd->canceldrop = GDrawPointsToPixels(NULL,30);
+ bgcd[0].gd.pos.x = 20; bgcd[0].gd.pos.y = GDrawPixelsToPoints(NULL,pos.height)-33;
+ bgcd[0].gd.pos.width = -1; bgcd[0].gd.pos.height = 0;
+ bgcd[0].gd.flags = gg_visible | gg_enabled;
+ blabel[0].text = (unichar_t *) _("_OK");
+ blabel[0].text_is_1byte = true;
+ blabel[0].text_in_resource = true;
+ bgcd[0].gd.label = &blabel[0];
+ bgcd[0].gd.cid = CID_OK;
+ bgcd[0].gd.handle_controlevent = CCD_OK;
+ bgcd[0].creator = GButtonCreate;
+
+ space = (CCD_WIDTH-4*blen-40)/3;
+ bgcd[1].gd.pos.x = bgcd[0].gd.pos.x+blen+space; bgcd[1].gd.pos.y = bgcd[0].gd.pos.y;
+ bgcd[1].gd.pos.width = -1; bgcd[1].gd.pos.height = 0;
+ bgcd[1].gd.flags = gg_visible;
+ blabel[1].text = (unichar_t *) _("< _Prev");
+ blabel[1].text_is_1byte = true;
+ blabel[1].text_in_resource = true;
+ bgcd[1].gd.label = &blabel[1];
+ bgcd[1].gd.handle_controlevent = CCD_Prev;
+ bgcd[1].gd.cid = CID_Prev;
+ bgcd[1].creator = GButtonCreate;
+
+ bgcd[2].gd.pos.x = bgcd[1].gd.pos.x+blen+space; bgcd[2].gd.pos.y = bgcd[1].gd.pos.y;
+ bgcd[2].gd.pos.width = -1; bgcd[2].gd.pos.height = 0;
+ bgcd[2].gd.flags = gg_visible;
+ blabel[2].text = (unichar_t *) _("_Next >");
+ blabel[2].text_is_1byte = true;
+ blabel[2].text_in_resource = true;
+ bgcd[2].gd.label = &blabel[2];
+ bgcd[2].gd.handle_controlevent = CCD_Next;
+ bgcd[2].gd.cid = CID_Next;
+ bgcd[2].creator = GButtonCreate;
+
+ bgcd[3].gd.pos.x = -20; bgcd[3].gd.pos.y = bgcd[1].gd.pos.y;
+ bgcd[3].gd.pos.width = -1; bgcd[3].gd.pos.height = 0;
+ bgcd[3].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ blabel[3].text = (unichar_t *) _("_Cancel");
+ blabel[3].text_is_1byte = true;
+ blabel[3].text_in_resource = true;
+ bgcd[3].gd.label = &blabel[3];
+ bgcd[3].gd.handle_controlevent = CCD_Cancel;
+ bgcd[3].gd.cid = CID_Cancel;
+ bgcd[3].creator = GButtonCreate;
+
+ bgcd[4].gd.pos.x = 2; bgcd[4].gd.pos.y = 2;
+ bgcd[4].gd.pos.width = pos.width-4; bgcd[4].gd.pos.height = pos.height-4;
+ bgcd[4].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
+ bgcd[4].gd.cid = CID_Group;
+ bgcd[4].creator = GGroupCreate;
+
+ if ( fpst->type == pst_reversesub ) {
+ bgcd[1].gd.flags = bgcd[2].gd.flags = gg_visible;
+ ccd->aw = aw_coverage;
+ } else if ( ccd->isnew || fpst->rule_cnt==0) {
+ fpst->format = pst_class;
+ bgcd[0].gd.flags = gg_visible;
+ bgcd[2].gd.flags = gg_visible | gg_enabled;
+ ccd->aw = aw_formats;
+ } else if ( fpst->format==pst_coverage ) {
+ bgcd[1].gd.flags = gg_visible | gg_enabled; bgcd[2].gd.flags = gg_visible;
+ ccd->aw = aw_coverage; /* flags are different from those of reversesub above */
+ } else if ( fpst->format==pst_class ) {
+ bgcd[1].gd.flags = gg_visible | gg_enabled; bgcd[2].gd.flags = gg_visible;
+ ccd->aw = aw_class;
+ } else {
+ bgcd[1].gd.flags = gg_visible | gg_enabled; bgcd[2].gd.flags = gg_visible;
+ ccd->aw = aw_glist;
+ }
+
+ GGadgetsCreate(gw,bgcd);
+
+ wattrs.mask = wam_events;
+ ccd->formats = GWidgetCreateSubWindow(ccd->gw,&subpos,subccd_e_h,ccd,&wattrs);
+ memset(&rlabel,0,sizeof(rlabel));
+ memset(&rgcd,0,sizeof(rgcd));
+
+ for ( i=0; text[i]!=0; ++i ) {
+ rgcd[i].gd.pos.x = 5; rgcd[i].gd.pos.y = 5+i*13;
+ rgcd[i].gd.flags = gg_visible | gg_enabled;
+ rlabel[i].text = (unichar_t *) _(text[i]);
+ rlabel[i].text_is_1byte = true;
+ rgcd[i].gd.label = &rlabel[i];
+ rgcd[i].creator = GLabelCreate;
+ }
+
+ rgcd[i].gd.pos.x = 50; rgcd[i].gd.pos.y = rgcd[i-1].gd.pos.y+20;
+ rgcd[i].gd.flags = gg_visible | gg_enabled | (fpst->format==pst_glyphs ? gg_cb_on : 0 );
+ rlabel[i].text = (unichar_t *) _("By Glyphs");
+ rlabel[i].text_is_1byte = true;
+ rgcd[i].gd.label = &rlabel[i];
+ rgcd[i].gd.cid = CID_ByGlyph;
+ rgcd[i++].creator = GRadioCreate;
+
+ rgcd[i].gd.pos.x = rgcd[i-1].gd.pos.x; rgcd[i].gd.pos.y = rgcd[i-1].gd.pos.y+16;
+ rgcd[i].gd.flags = gg_visible | gg_enabled | (fpst->format==pst_class ? gg_cb_on : 0 );
+ rlabel[i].text = (unichar_t *) _("By Classes");
+ rlabel[i].text_is_1byte = true;
+ rgcd[i].gd.label = &rlabel[i];
+ rgcd[i].gd.cid = CID_ByClass;
+ rgcd[i++].creator = GRadioCreate;
+
+ rgcd[i].gd.pos.x = rgcd[i-1].gd.pos.x; rgcd[i].gd.pos.y = rgcd[i-1].gd.pos.y+16;
+ rgcd[i].gd.flags = gg_visible | gg_enabled | (fpst->format!=pst_glyphs && fpst->format!=pst_class ? gg_cb_on : 0 );
+ rlabel[i].text = (unichar_t *) _("By Coverage");
+ rlabel[i].text_is_1byte = true;
+ rgcd[i].gd.label = &rlabel[i];
+ rgcd[i].gd.cid = CID_ByCoverage;
+ rgcd[i].creator = GRadioCreate;
+ GGadgetsCreate(ccd->formats,rgcd);
+
+
+ ccd->glyphs = GWidgetCreateSubWindow(ccd->gw,&subpos,subccd_e_h,ccd,&wattrs);
+ memset(&ggcd,0,sizeof(ggcd));
+ memset(&fgcd,0,sizeof(fgcd));
+ memset(&glabel,0,sizeof(glabel));
+ memset(&flabel,0,sizeof(flabel));
+ memset(&faspects,0,sizeof(faspects));
+ for ( i=0; i<3; ++i ) {
+ k = CCD_AddGlyphList(&ggcd[i][0],&glabel[i][0],(0*100+i*20), 5, 8*13+4 );
+
+ if ( i==0 )
+ CCD_AddSeqLookup(&ggcd[i][k],&glabel[i][k],(i*20),ggcd[0][k-1].gd.pos.y+ggcd[0][k-1].gd.pos.height+10,
+ CCD_WIDTH-20,4*13+10);
+ }
+
+ j = 0;
+
+ faspects[j].text = (unichar_t *) _("Match");
+ faspects[j].text_is_1byte = true;
+ faspects[j].selected = true;
+ faspects[j].gcd = ggcd[j]; ++j;
+
+ faspects[j].text = (unichar_t *) _("Backtrack");
+ faspects[j].text_is_1byte = true;
+ faspects[j].disabled = fpst->type==pst_contextpos || fpst->type==pst_contextsub;
+ faspects[j].gcd = ggcd[j]; ++j;
+
+ faspects[j].text = (unichar_t *) _("Lookahead");
+ faspects[j].text_is_1byte = true;
+ faspects[j].disabled = fpst->type==pst_contextpos || fpst->type==pst_contextsub;
+ faspects[j].gcd = ggcd[j]; ++j;
+
+ flabel[0].text = (unichar_t *) _("A list of glyphs:");
+ flabel[0].text_is_1byte = true;
+ fgcd[0].gd.label = &flabel[0];
+ fgcd[0].gd.pos.x = 5; fgcd[0].gd.pos.y = 5;
+ fgcd[0].gd.flags = gg_visible | gg_enabled;
+ fgcd[0].creator = GLabelCreate;
+
+ fgcd[1].gd.pos.x = 3; fgcd[1].gd.pos.y = 18;
+ fgcd[1].gd.pos.width = CCD_WIDTH-10;
+ fgcd[1].gd.pos.height = CCD_HEIGHT-60;
+ fgcd[1].gd.u.tabs = faspects;
+ fgcd[1].gd.flags = gg_visible | gg_enabled;
+ fgcd[1].gd.cid = CID_MatchType;
+ fgcd[1].creator = GTabSetCreate;
+ GGadgetsCreate(ccd->glyphs,fgcd);
+
+
+ ccd->coverage = GWidgetCreateSubWindow(ccd->gw,&subpos,subccd_e_h,ccd,&wattrs);
+ memset(&clabel,0,sizeof(clabel));
+ memset(&cgcd,0,sizeof(cgcd));
+
+ for ( i=0; i<3; ++i ) {
+ k = CCD_AddGList(&cgcd[i][0],&clabel[i][0],100+i*20,5,
+ CCD_WIDTH-20,i==0 ? CCD_HEIGHT-250 : CCD_HEIGHT-150);
+
+ if ( i==0 ) {
+ if ( ccd->fpst->format!=pst_reversecoverage )
+ CCD_AddSeqLookup(&cgcd[i][k],&clabel[i][k],100,cgcd[0][k-1].gd.pos.y+40,
+ CCD_WIDTH-20,4*13+10);
+ else {
+ r = NULL;
+ if ( fpst->rule_cnt==1 ) r = &fpst->rules[0];
+ CCD_AddReplacements(&cgcd[i][k],&clabel[i][k],r,100,cgcd[0][k-1].gd.pos.y+40);
+ }
+ }
+ faspects[i].gcd = cgcd[i];
+ }
+ flabel[0].text = (unichar_t *) _("A coverage table:");
+ fgcd[1].gd.cid = CID_MatchType+100;
+ GGadgetsCreate(ccd->coverage,fgcd);
+ if (( fpst->format==pst_coverage || fpst->format==pst_reversecoverage ) &&
+ fpst->rule_cnt==1 ) {
+ for ( i=0; i<3; ++i ) {
+ if ( (&fpst->rules[0].u.coverage.ncnt)[i]!=0 )
+ GGadgetSetList(cgcd[i][0].ret,clistlist(fpst,i),false);
+ }
+ if ( fpst->format==pst_coverage ) {
+ GTextInfo **ti = slistlist(&fpst->rules[0]);
+ GGadgetSetList(GWidgetGetControl(ccd->gw,CID_LookupList+100),ti,false);
+ }
+ }
+
+ ccd->glist = GWidgetCreateSubWindow(ccd->gw,&subpos,subccd_e_h,ccd,&wattrs);
+ memset(&gllabel,0,sizeof(gllabel));
+ memset(&glgcd,0,sizeof(glgcd));
+
+ k = 0;
+ gllabel[k].text = (unichar_t *) _("A list of glyph lists:");
+ gllabel[k].text_is_1byte = true;
+ glgcd[k].gd.label = &gllabel[k];
+ glgcd[k].gd.pos.x = 5; glgcd[k].gd.pos.y = 5;
+ glgcd[k].gd.flags = gg_visible | gg_enabled;
+ glgcd[k++].creator = GLabelCreate;
+
+ k += CCD_AddGList(&glgcd[k],&gllabel[k],0,19,
+ CCD_WIDTH-20,CCD_HEIGHT-100);
+
+ GGadgetsCreate(ccd->glist,glgcd);
+ if ( fpst->format==pst_glyphs && fpst->rule_cnt>0 )
+ GGadgetSetList(glgcd[1].ret,glistlist(fpst),false);
+
+
+ ccd->cselect = GWidgetCreateSubWindow(ccd->gw,&subpos,subccd_e_h,ccd,&wattrs);
+ memset(&cslabel,0,sizeof(cslabel));
+ memset(&csgcd,0,sizeof(csgcd));
+
+ CCD_AddGlyphList(csgcd,cslabel,100,5,8*13+4);
+ GGadgetsCreate(ccd->cselect,csgcd);
+
+ ccd->class = GWidgetCreateSubWindow(ccd->gw,&subpos,subccd_e_h,ccd,&wattrs);
+ memset(&cllabel,0,sizeof(cllabel));
+ memset(&clgcd,0,sizeof(clgcd));
+ memset(&clabel,0,sizeof(clabel));
+ memset(&cgcd,0,sizeof(cgcd));
+
+ k=0;
+ cllabel[k].text = (unichar_t *) _("List of lists of class numbers");
+ cllabel[k].text_is_1byte = true;
+ clgcd[k].gd.label = &cllabel[k];
+ clgcd[k].gd.pos.x = 5; clgcd[k].gd.pos.y = 5;
+ clgcd[k].gd.flags = gg_visible | gg_enabled;
+ clgcd[k++].creator = GLabelCreate;
+
+ k += CCD_AddGList(&clgcd[k],&cllabel[k],200,19,
+ CCD_WIDTH-20,CCD_HEIGHT-270);
+
+ clgcd[k].gd.pos.x = 2; clgcd[k].gd.pos.y = clgcd[k-1].gd.pos.y+30;
+ clgcd[k].gd.pos.width = CCD_WIDTH-23;
+ clgcd[k].gd.flags = gg_visible | gg_enabled;
+ clgcd[k++].creator = GLineCreate;
+
+ for ( i=0; i<3; ++i ) {
+ int l=0;
+ clabel[i][l].text = (unichar_t *) _("Classes (Lists of lists of glyph names)");
+ clabel[i][l].text_is_1byte = true;
+ cgcd[i][l].gd.label = &clabel[i][l];
+ cgcd[i][l].gd.pos.x = 5; cgcd[i][l].gd.pos.y = 5;
+ cgcd[i][l].gd.flags = gg_visible | gg_enabled;
+ cgcd[i][l++].creator = GLabelCreate;
+
+ if ( i!=0 ) {
+ clabel[i][l].text = (unichar_t *) _("Same as Match Classes");
+ clabel[i][l].text_is_1byte = true;
+ cgcd[i][l].gd.label = &clabel[i][l];
+ cgcd[i][l].gd.pos.x = 190; cgcd[i][l].gd.pos.y = 7;
+ cgcd[i][l].gd.handle_controlevent = CCD_SameAsClasses;
+ cgcd[i][l].gd.flags = gg_visible | gg_enabled;
+ cgcd[i][l].gd.cid = CID_SameAsClasses + i*20;
+ cgcd[i][l++].creator = GCheckBoxCreate;
+ }
+
+ CCD_AddGList(&cgcd[i][l],&clabel[i][l],300+i*20,cgcd[i][0].gd.pos.y+15,
+ CCD_WIDTH-20,CCD_HEIGHT-270);
+ faspects[i].gcd = cgcd[i];
+ }
+ j=0;
+ faspects[j++].text = (unichar_t *) _("Match Classes");
+ faspects[j++].text = (unichar_t *) _("Back Classes");
+ faspects[j++].text = (unichar_t *) _("Ahead Classes");
+
+ clgcd[k].gd.pos.x = 3; clgcd[k].gd.pos.y = clgcd[k-1].gd.pos.y+5;
+ clgcd[k].gd.pos.width = CCD_WIDTH-10;
+ clgcd[k].gd.pos.height = CCD_HEIGHT-185;
+ clgcd[k].gd.u.tabs = faspects;
+ clgcd[k].gd.flags = gg_visible | gg_enabled;
+ clgcd[k].gd.cid = CID_MatchType+300;
+ clgcd[k].creator = GTabSetCreate;
+ GGadgetsCreate(ccd->class,clgcd);
+
+ tempfpst = fpst;
+ if ( fpst->format==pst_glyphs && fpst->rule_cnt>0 )
+ tempfpst = FPSTGlyphToClass(fpst);
+ if ( tempfpst->format==pst_class && tempfpst->rule_cnt>0 ) {
+ GGadgetSetList(GWidgetGetControl(ccd->class,CID_GList+200),clslistlist(tempfpst),false);
+ for ( i=0; i<3; ++i ) {
+ GGadget *list = GWidgetGetControl(ccd->class,CID_GList+300+i*20);
+ GListAppendLine8(list,_("{Everything Else}"),false);
+ for ( k=1; k<(&tempfpst->nccnt)[i]; ++k ) {
+ GListAppendLine8(list,(&tempfpst->nclass)[i][k],false);
+ }
+ if ( i!=0 && ClassesMatch((&tempfpst->nccnt)[i],(&tempfpst->nclass)[i],tempfpst->nccnt,tempfpst->nclass)) {
+ GGadgetSetChecked(GWidgetGetControl(ccd->class,CID_SameAsClasses+i*20),true);
+ CCD_SameAsClasses(GWidgetGetControl(ccd->class,CID_SameAsClasses+i*20),NULL);
+ }
+ }
+ if ( tempfpst!=fpst )
+ FPSTFree(tempfpst);
+ } else {
+ for ( i=0; i<3; ++i )
+ GListAppendLine8(GWidgetGetControl(ccd->class,CID_GList+300+i*20),
+ _("{Everything Else}"),false);
+ for ( i=1; i<3; ++i ) {
+ GGadgetSetChecked(GWidgetGetControl(ccd->class,CID_SameAsClasses+i*20),true);
+ CCD_SameAsClasses(GWidgetGetControl(ccd->class,CID_SameAsClasses+i*20),NULL);
+ }
+ }
+
+ ccd->classbuild = GWidgetCreateSubWindow(ccd->gw,&subpos,subccd_e_h,ccd,&wattrs);
+ memset(&cslabel,0,sizeof(cslabel));
+ memset(&csgcd,0,sizeof(csgcd));
+
+ CCD_AddGlyphList(csgcd,cslabel,300,5,8*13+4);
+ GGadgetsCreate(ccd->classbuild,csgcd);
+
+ ccd->classnumber = GWidgetCreateSubWindow(ccd->gw,&subpos,subccd_e_h,ccd,&wattrs);
+ memset(&clabel,0,sizeof(clabel));
+ memset(&cgcd,0,sizeof(cgcd));
+ memset(&cllabel,0,sizeof(cllabel));
+ memset(&clgcd,0,sizeof(clgcd));
+
+ for ( i=0; i<3; ++i ) {
+ k=0;
+
+ clabel[i][k].text = (unichar_t *) _("List of class numbers");
+ clabel[i][k].text_is_1byte = true;
+ cgcd[i][k].gd.label = &clabel[i][k];
+ cgcd[i][k].gd.pos.x = 5; cgcd[i][k].gd.pos.y = 5;
+ cgcd[i][k].gd.flags = gg_visible | gg_enabled;
+ cgcd[i][k++].creator = GLabelCreate;
+
+ cgcd[i][k].gd.pos.x = 5; cgcd[i][k].gd.pos.y = cgcd[i][k-1].gd.pos.y+14;
+ cgcd[i][k].gd.pos.width = CCD_WIDTH-25; cgcd[i][k].gd.pos.height = 4*13+4;
+ cgcd[i][k].gd.flags = gg_visible | gg_enabled | gg_textarea_wrap;
+ cgcd[i][k].gd.cid = CID_ClassNumbers+i*20;
+ cgcd[i][k++].creator = GTextAreaCreate;
+
+ clabel[i][k].text = (unichar_t *) _("Classes");
+ clabel[i][k].text_is_1byte = true;
+ cgcd[i][k].gd.label = &clabel[i][k];
+ cgcd[i][k].gd.pos.x = 5; cgcd[i][k].gd.pos.y = cgcd[i][k-1].gd.pos.y+cgcd[i][k-1].gd.pos.height+5;
+ cgcd[i][k].gd.flags = gg_visible | gg_enabled;
+ cgcd[i][k++].creator = GLabelCreate;
+
+ cgcd[i][k].gd.pos.x = 5; cgcd[i][k].gd.pos.y = cgcd[i][k-1].gd.pos.y+14;
+ cgcd[i][k].gd.pos.width = CCD_WIDTH-25; cgcd[i][k].gd.pos.height = 4*13+10;
+ cgcd[i][k].gd.flags = gg_visible | gg_enabled | gg_textarea_wrap;
+ cgcd[i][k].gd.handle_controlevent = CCD_ClassSelected;
+ cgcd[i][k].gd.cid = CID_ClassList+i*20;
+ cgcd[i][k++].creator = GListCreate;
+
+ if ( i==0 )
+ CCD_AddSeqLookup(&cgcd[i][k],&clabel[i][k],500,cgcd[0][k-1].gd.pos.y+cgcd[0][k-1].gd.pos.height+5,
+ CCD_WIDTH-20,4*13+10);
+ faspects[i].gcd = cgcd[i];
+ }
+
+ j=0;
+ faspects[j++].text = (unichar_t *) _("Match");
+ faspects[j++].text = (unichar_t *) _("Backtrack");
+ faspects[j++].text = (unichar_t *) _("Lookahead");
+
+ k=0;
+ clgcd[k].gd.pos.x = 3; clgcd[k].gd.pos.y = 5;
+ clgcd[k].gd.pos.width = CCD_WIDTH-10;
+ clgcd[k].gd.pos.height = CCD_HEIGHT-45;
+ clgcd[k].gd.u.tabs = faspects;
+ clgcd[k].gd.flags = gg_visible | gg_enabled;
+ clgcd[k].gd.cid = CID_ClassType;
+ clgcd[k].creator = GTabSetCreate;
+ GGadgetsCreate(ccd->classnumber,clgcd);
+
+
+ if ( ccd->aw == aw_formats )
+ GDrawSetVisible(ccd->formats,true);
+ else if ( ccd->aw == aw_glist )
+ GDrawSetVisible(ccd->glist,true);
+ else if ( ccd->aw == aw_class )
+ GDrawSetVisible(ccd->class,true);
+ else
+ GDrawSetVisible(ccd->coverage,true);
+
+ GDrawSetVisible(gw,true);
+#endif
+return( ccd );
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/descrip.mms b/Build/source/libs/luafontforge/fontforge/fontforge/descrip.mms
new file mode 100644
index 00000000000..78a390c14f9
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/descrip.mms
@@ -0,0 +1,197 @@
+CFLAGS=/nowarn/incl=([-.inc])/name=(as_is,short)/define=(\
+ "_STATIC_LIBFREETYPE=1","_STATIC_LIBPNG=1","HAVE_LIBINTL_H=1",\
+ "_STATIC_LIBUNINAMESLIST=1","_STATIC_LIBXML=1","_NO_XINPUT=1",\
+ "_STATIC_LIBUNGIF=1","_STATIC_LIBJPEG=1","_STATIC_LIBTIFF=1",\
+ "_NO_PYTHON=1",\
+ "FONTFORGE_CONFIG_DEVICETABLES=1","PLUGINDIR=""/FONTFORGE$PLUGINS""")
+
+fontforge_OBJECTS = alignment.obj,autohint.obj,autosave.obj,autowidth.obj,\
+ bitmapdlg.obj,metafont.obj,parsettfbmf.obj,\
+ bitmapview.obj,bvedit.obj,charview.obj,cursors.obj
+
+fontforge_OBJECTS1=cvaddpoints.obj,cvexport.obj,cvgetinfo.obj,cvhints.obj,cvimages.obj,cvknife.obj,\
+cvpalettes.obj,cvpointer.obj,cvruler.obj,cvshapes.obj,cvstroke.obj,cvtranstools.obj
+
+fontforge_OBJECTS2=cvundoes.obj,dumpbdf.obj,dumppfa.obj,fontinfo.obj,fontview.obj,fvcomposit.obj,\
+ fvfonts.obj,fvimportbdf.obj,fvmetrics.obj,images.obj,metricsview.obj,\
+ parsepfa.obj,parsettf.obj,prefs.obj,psread.obj,namelist.obj,savefontdlg.obj
+
+fontforge_OBJECTS3=sfd.obj,splashimage.obj,splinefill.obj,splineoverlap.obj,splinesave.obj,\
+ splinesaveafm.obj,splinestroke.obj,splineutil.obj,splineutil2.obj,stamp.obj,\
+ start.obj,tottf.obj,transform.obj,uiutil.obj,utils.obj,windowmenu.obj
+
+fontforge_OBJECTS4=zapfnomen.obj,othersubrs.obj,autotrace.obj,openfontdlg.obj,encoding.obj,print.obj,\
+ problems.obj,crctab.obj,macbinary.obj,scripting.obj
+
+fontforge_OBJECTS5=displayfonts.obj,combinations.obj,sftextfield.obj,ikarus.obj,\
+ cvfreehand.obj,cvhand.obj,simplifydlg.obj,winfonts.obj,freetype.obj,\
+ gotodlg.obj,search.obj,tottfgpos.obj,charinfo.obj,tottfaat.obj
+
+fontforge_OBJECTS6=splineorder2.obj,genttfinstrs.obj,ttfinstrs.obj,cvgridfit.obj,\
+ cvdebug.obj,showatt.obj,kernclass.obj,nonlineartrans.obj,effects.obj,\
+ histograms.obj,ttfspecial.obj,svg.obj,parsettfatt.obj,contextchain.obj
+
+fontforge_OBJECTS7=macenc.obj,statemachine.obj,splinerefigure.obj,mm.obj,\
+ parsettfvar.obj,tottfvar.obj,pua.obj,stemdb.obj,anchorsaway.obj,\
+ palmfonts.obj,cvdgloss.obj,groups.obj,parsepdf.obj,plugins.obj
+
+fontforge_OBJECTS8=bdfinfo.obj,glyphcomp.obj,unicoderange.obj,ufo.obj,\
+ ofl.obj,lookups.obj,sfd1.obj,python.obj,featurefile.obj
+
+fontforge.exe : main.obj lff.opt xlib.opt [-.libs]libfontforge.exe
+ link/exec=fontforge.exe main,lff/opt,[-.libs]LIBGDRAW/lib,\
+ LIBGUNICODE/lib,[]xlib.opt/opt
+
+[-.libs]libfontforge.exe : $(fontforge_OBJECTS) $(fontforge_OBJECTS1)\
+ $(fontforge_OBJECTS2) $(fontforge_OBJECTS3) $(fontforge_OBJECTS4)\
+ $(fontforge_OBJECTS5) $(fontforge_OBJECTS6) $(fontforge_OBJECTS7)\
+ $(fontforge_OBJECTS8) [-.libs]LIBGDRAW.olb [-.libs]LIBGUNICODE.olb
+ @ WRITE_ SYS$OUTPUT " generating lff1.opt"
+ @ OPEN_/WRITE FILE lff1.opt
+ @ WRITE_ FILE "!"
+ @ WRITE_ FILE "! lff1.opt generated by DESCRIP.$(MMS_EXT)"
+ @ WRITE_ FILE "!"
+ @ WRITE_ FILE "IDENTIFICATION=""lff"""
+ @ WRITE_ FILE "GSMATCH=LEQUAL,1,0
+ @ WRITE_ FILE "$(fontforge_OBJECTS)"
+ @ WRITE_ FILE "$(fontforge_OBJECTS1)"
+ @ WRITE_ FILE "$(fontforge_OBJECTS2)"
+ @ WRITE_ FILE "$(fontforge_OBJECTS3)"
+ @ WRITE_ FILE "$(fontforge_OBJECTS4)"
+ @ WRITE_ FILE "$(fontforge_OBJECTS5)"
+ @ WRITE_ FILE "$(fontforge_OBJECTS6)"
+ @ WRITE_ FILE "$(fontforge_OBJECTS7)"
+ @ WRITE_ FILE "$(fontforge_OBJECTS8)"
+ @ CLOSE_ FILE
+ @ $(MMS)$(MMSQUALIFIERS)/ignore=warning lff_vms
+ @ WRITE_ SYS$OUTPUT " linking libfontforge.exe ..."
+ @ LINK_/NODEB/SHARE=[-.libs]libfontforge.exe/MAP=lff.map/FULL lff1.opt/opt,\
+ lff_vms.opt/opt,[-.libs]LIBGDRAW/lib,LIBGUNICODE/lib,\
+ [-.fontforge]xlib.opt/opt
+
+lff_vms :
+ @ WRITE_ SYS$OUTPUT " generating lff.map ..."
+ @ LINK_/NODEB/NOSHARE/NOEXE/MAP=lff.map/FULL lff1.opt/OPT
+ @ WRITE_ SYS$OUTPUT " analyzing lff.map ..."
+ @ @[-.plugins]ANALYZE_MAP.COM lff.map lff_vms.opt
+
+alignment.obj : alignment.c
+autohint.obj : autohint.c
+autosave.obj : autosave.c
+autowidth.obj : autowidth.c
+bitmapdlg.obj : bitmapdlg.c
+metafont.obj : metafont.c
+parsettfbmf.obj : parsettfbmf.c
+bitmapview.obj : bitmapview.c
+bvedit.obj : bvedit.c
+charview.obj : charview.c
+cursors.obj : cursors.c
+cvaddpoints.obj : cvaddpoints.c
+cvexport.obj : cvexport.c
+cvgetinfo.obj : cvgetinfo.c
+cvhints.obj : cvhints.c
+cvimages.obj : cvimages.c
+cvknife.obj : cvknife.c
+cvpalettes.obj : cvpalettes.c
+cvpointer.obj : cvpointer.c
+cvruler.obj : cvruler.c
+cvshapes.obj : cvshapes.c
+cvstroke.obj : cvstroke.c
+cvtranstools. : cvtranstools.c
+cvundoes.obj : cvundoes.c
+dumpbdf.obj : dumpbdf.c
+dumppfa.obj : dumppfa.c
+fontinfo.obj : fontinfo.c
+fontview.obj : fontview.c
+fvcomposit.obj : fvcomposit.c
+fvfonts.obj : fvfonts.c
+fvimportbdf.obj : fvimportbdf.c
+fvmetrics.obj : fvmetrics.c
+images.obj : images.c
+metricsview.obj : metricsview.c
+parsepfa.obj : parsepfa.c
+parsettf.obj : parsettf.c
+prefs.obj : prefs.c
+psread.obj : psread.c
+namelist.obj : namelist.c
+savefontdlg.ob : savefontdlg.c
+sfd.obj : sfd.c
+splashimage.obj : splashimage.c
+splinefill.obj : splinefill.c
+splineoverlap.obj : splineoverlap.c
+splinesave.obj : splinesave.c
+splinesaveafm.obj : splinesaveafm.c
+splinestroke.obj : splinestroke.c
+splineutil.obj : splineutil.c
+splineutil2.obj : splineutil2.c
+stamp.obj : stamp.c
+start.obj : start.c
+tottf.obj : tottf.c
+ $(CC) $(CFLAGS)/noop tottf
+transform.obj : transform.c
+uiutil.obj : uiutil.c
+utils.obj : utils.c
+windowmenu.obj : windowmenu.c
+zapfnomen.obj : zapfnomen.c
+othersubrs.obj : othersubrs.c
+autotrace.obj : autotrace.c
+openfontdlg.obj : openfontdlg.c
+encoding.obj : encoding.c
+print.ob : print.c
+problems.obj : problems.c
+crctab.obj : crctab.c
+macbinary.obj : macbinary.c
+scripting.obj : scripting.c
+displayfonts.obj : displayfonts.c
+combinations.obj : combinations.c
+sftextfield.obj : sftextfield.c
+ikarus.obj : ikarus.c
+cvfreehand.obj : cvfreehand.c
+cvhand.obj : cvhand.c
+simplifydlg.obj : simplifydlg.c
+winfonts.obj : winfonts.c
+freetype.obj : freetype.c
+gotodlg.obj : gotodlg.c
+search.obj : search.c
+tottfgpos.obj : tottfgpos.c
+charinfo.obj : charinfo.c
+tottfaat.obj : tottfaat.c
+ $(CC) $(CFLAGS)/noop tottfaat
+splineorder2.obj : splineorder2.c
+genttfinstrs.obj : genttfinstrs.c
+ttfinstrs.obj : ttfinstrs.c
+cvgridfit.obj : cvgridfit.c
+cvdebug.obj : cvdebug.c
+showatt.obj : showatt.c
+kernclass.obj : kernclass.c
+nonlineartrans.obj : nonlineartrans.c
+effects.obj : effects.c
+histograms.obj : histograms.c
+ttfspecial.obj : ttfspecial.c
+svg.obj : svg.c
+parsettfatt.obj : parsettfatt.c
+contextchain.obj : contextchain.c
+macenc.obj : macenc.c
+statemachine.obj : statemachine.c
+splinerefigure.obj : splinerefigure.c
+mm.obj : mm.c
+parsettfvar.obj : parsettfvar.c
+tottfvar.obj : tottfvar.c
+pua.obj : pua.c
+stemdb.obj : stemdb.c
+anchorsaway.obj : anchorsaway.c
+palmfonts.obj : palmfonts.c
+cvdgloss.obj : cvdgloss.c
+groups.obj : groups.c
+parsepdf.obj : parsepdf.c
+plugins.obj : plugins.c
+main.obj : main.c
+bdfinfo.obj : bdfinfo.c
+glyphcomp.obj : glyphcomp.c
+unicoderange.obj : unicoderange.c
+ufo.obj : ufo.c
+ofl.obj : ofl.c
+lookups.obj : lookups.c
+sfd1.obj : sfd1.c
+python.obj : python.c
+featurefile.obj : featurefile.c
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/edgelist.h b/Build/source/libs/luafontforge/fontforge/fontforge/edgelist.h
new file mode 100644
index 00000000000..8a606c4c8c3
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/edgelist.h
@@ -0,0 +1,146 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _EDGELIST_H
+#define _EDGELIST_H
+#include "splinefont.h"
+
+typedef struct hints {
+ real base, width;
+ real b1, b2, e1, e2;
+ real ab, ae;
+ unsigned int adjustb: 1;
+ unsigned int adjuste: 1;
+ struct hints *next;
+} Hints;
+
+/* Instead of y and x coordinates these are based on major and other */
+/* major maybe either x or y depending on what we're interested in */
+/* at the moment, and other will be the other one. Of course it's */
+/* consistant accross the datastructure at any given time */
+typedef struct edge {
+ real mmin, mmax; /* relative to es->mmin */
+ real t_mmin, t_mmax;
+ real tmin, tmax;
+ real o_mmin, o_mmax;
+ real t_cur, o_cur, m_cur;
+ unsigned int up: 1; /* line is directed up in the spline list */
+ unsigned int max_adjusted: 1; /* by hstem hints */
+ unsigned int min_adjusted: 1;
+ Spline *spline; /* spline which generated this segment */
+ struct edge *esnext, *aenext;
+ struct edge *before, *after;
+ int last_opos, last_mpos;
+ real oldt; /* only used for FindIntersections of RemoveOverlap */
+} Edge;
+
+typedef struct edgelist {
+ Edge **edges;
+ int cnt;
+ real mmin, mmax;
+ real omin, omax;
+ real scale;
+ int bytes_per_line;
+ uint8 *bitmap;
+ Edge *last, *splinesetfirst;
+ SplineChar *sc;
+ char *interesting;
+ int major, other;
+ unsigned int genmajoredges: 1; /* generate a list of edges parrallel to the major axis */
+ Edge *majors; /* ordered so that lowest edge is first */
+ Edge *majorhold; /* to hold major edges as we pass them and they become useless */
+ Hints *hhints, *vhints;
+ int is_overlap;
+} EdgeList;
+
+extern void FreeEdges(EdgeList *es);
+extern double TOfNextMajor(Edge *e, EdgeList *es, double sought_y );
+extern void FindEdgesSplineSet(SplinePointList *spl, EdgeList *es);
+extern Edge *ActiveEdgesInsertNew(EdgeList *es, Edge *active,int i);
+extern Edge *ActiveEdgesRefigure(EdgeList *es, Edge *active,real i);
+extern Edge *ActiveEdgesFindStem(Edge *apt, Edge **prev, real i);
+
+/* Version which is better for everything other than rasterization */
+/* (I think) */
+typedef struct edgeinfo {
+ /* The spline is broken up at all extrema. So... */
+ /* The spline between tmin and tmax is monotonic in both coordinates */
+ /* If the spline becomes vert/horizontal that will be at one of the */
+ /* end points too */
+ Spline *spline;
+ real tmin, tmax;
+ real coordmin[2];
+ real coordmax[2];
+ unsigned int up: 1;
+ unsigned int hv: 1;
+ unsigned int hvbottom: 1;
+ unsigned int hvtop: 1;
+ unsigned int hor: 1;
+ unsigned int vert: 1;
+ unsigned int almosthor: 1;
+ unsigned int almostvert: 1;
+ unsigned int horattmin: 1;
+ unsigned int horattmax: 1;
+ unsigned int vertattmin: 1;
+ unsigned int vertattmax: 1;
+ unsigned hup: 1;
+ unsigned vup: 1;
+ real tcur; /* Value of t for current major coord */
+ real ocur; /* Value of the other coord for current major coord */
+ struct edgeinfo *next;
+ struct edgeinfo *ordered;
+ struct edgeinfo *aenext;
+ struct edgeinfo *splinenext;
+ SplineChar *sc;
+ int major;
+} EI;
+
+typedef struct eilist {
+ EI *edges;
+ real coordmin[2];
+ real coordmax[2];
+ int low, high, cnt;
+ EI **ordered;
+ char *ends; /* flag to say an edge ends on this line */
+ SplineChar *sc;
+ int major;
+ EI *splinelast, *splinefirst;
+ EI **bottoms, **tops; /* Used only be FindNeeded in RemoveOverlap */
+ unsigned leavetiny: 1;
+ enum overlap_type ot;
+} EIList;
+
+extern void ElFreeEI(EIList *el);
+extern void ELFindEdges(SplineChar *sc, EIList *el);
+extern void ELOrder(EIList *el, int major );
+extern real EITOfNextMajor(EI *e, EIList *el, real sought_m );
+extern int EISameLine(EI *e, EI *n, real i, int major);
+extern int EISkipExtremum(EI *e, real i, int major);
+extern EI *EIActiveEdgesFindStem(EI *apt, real i, int major);
+extern EI *EIActiveListReorder(EI *active,int *change);
+extern EI *EIActiveEdgesRefigure(EIList *el, EI *active,real i,int major,
+ int *_change);
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/edgelist2.h b/Build/source/libs/luafontforge/fontforge/fontforge/edgelist2.h
new file mode 100644
index 00000000000..c2cccac0c3b
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/edgelist2.h
@@ -0,0 +1,54 @@
+/* Copyright (C) 2004-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _EDGELIST2_H
+#define _EDGELIST2_H
+#include "splinefont.h"
+
+typedef struct monotonic {
+ Spline *s;
+ extended tstart, tend;
+ struct monotonic *next, *prev; /* along original contour */
+ uint8 xup; /* increasing t => increasing x */
+ uint8 yup;
+ unsigned int isneeded : 1;
+ unsigned int isunneeded : 1;
+ unsigned int exclude : 1;
+ struct intersection *start;
+ struct intersection *end;
+ DBounds b;
+ extended other, t;
+ struct monotonic *linked; /* singly linked list of all monotonic*/
+ /* segments, no contour indication */
+ double when_set; /* Debugging */
+} Monotonic;
+
+extern void FreeMonotonics(Monotonic *m);
+extern Monotonic *SSsToMContours(SplineSet *spl, enum overlap_type ot);
+ /* overlap_type controls whether we look at selected splinesets or all splinesets */
+extern int MonotonicFindAt(Monotonic *ms,int which, extended test, Monotonic **space );
+
+#endif /* _EDGELIST2_H */
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/encoding.c b/Build/source/libs/luafontforge/fontforge/fontforge/encoding.c
new file mode 100644
index 00000000000..439382bbd1d
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/encoding.c
@@ -0,0 +1,3093 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pfaeditui.h"
+#include <ustring.h>
+#include <utype.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <gfile.h>
+#include <gio.h>
+#include <gresource.h>
+#include "plugins.h"
+
+#ifdef LUA_FF_LIB
+/* no need for iconv here, since PS is 8-bit legacy */
+#define Isspace(a) ((a)==' '|| ((a) >= '\t' && (a) <= '\r'))
+#define Isdigit(a) ((a)>='0' && (a)<='9')
+#define Isalpha(a) (((a)>='a' && (a)<='z') || ((a)>='A' && (a)<='Z'))
+#define Isupper(a) ((a)>='A' && (a)<='Z')
+#define Isalnum(a) (Isalpha(a)||Isdigit(a))
+#define Ishexdigit(a) (((a)>='0' && (a)<='9')||((a)>='a' && (a)<='f')||((a)>='A' && (a)<='F'))
+extern void gwwv_post_error(char *a, ...);
+#else
+#define Isspace isspace
+#define Isdigit isdigit
+#define Isalpha isalpha
+#define Isupper isupper
+#define Isalnum isalnum
+#define Ishexdigit ishexdigit
+#endif
+
+
+
+static int32 tex_base_encoding[] = {
+ 0x0000, 0x02d9, 0xfb01, 0xfb02, 0x2044, 0x02dd, 0x0141, 0x0142,
+ 0x02db, 0x02da, 0x000a, 0x02d8, 0x2212, 0x000d, 0x017d, 0x017e,
+ 0x02c7, 0x0131, 0xf6be, 0xfb00, 0xfb03, 0xfb04, 0x2260, 0x221e,
+ 0x2264, 0x2265, 0x2202, 0x2211, 0x220f, 0x03c0, 0x0060, 0x0027,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2019,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x2018, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x20ac, 0x222b, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
+ 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x2126, 0x221a, 0x2248,
+ 0x0090, 0x0091, 0x0092, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
+ 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x2206, 0x25ca, 0x0178,
+ 0x0000, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
+ 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x002d, 0x00ae, 0x00af,
+ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
+ 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
+ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
+ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
+ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
+ 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
+};
+
+static int32 unicode_from_MacSymbol[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x2200, 0x0023, 0x2203, 0x0025, 0x0026, 0x220d,
+ 0x0028, 0x0029, 0x2217, 0x002b, 0x002c, 0x2212, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x2245, 0x0391, 0x0392, 0x03a7, 0x0394, 0x0395, 0x03a6, 0x0393,
+ 0x0397, 0x0399, 0x03d1, 0x039a, 0x039b, 0x039c, 0x039d, 0x039f,
+ 0x03a0, 0x0398, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03c2, 0x03a9,
+ 0x039e, 0x03a8, 0x0396, 0x005b, 0x2234, 0x005d, 0x22a5, 0x005f,
+ 0xf8e5, 0x03b1, 0x03b2, 0x03c7, 0x03b4, 0x03b5, 0x03c6, 0x03b3,
+ 0x03b7, 0x03b9, 0x03d5, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03bf,
+ 0x03c0, 0x03b8, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03d6, 0x03c9,
+ 0x03be, 0x03c8, 0x03b6, 0x007b, 0x007c, 0x007d, 0x223c, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x0000, 0x03d2, 0x2032, 0x2264, 0x2044, 0x221e, 0x0192, 0x2663,
+ 0x2666, 0x2665, 0x2660, 0x2194, 0x2190, 0x2191, 0x2192, 0x2193,
+ 0x00b0, 0x00b1, 0x2033, 0x2265, 0x00d7, 0x221d, 0x2202, 0x2022,
+ 0x00f7, 0x2260, 0x2261, 0x2248, 0x2026, 0xf8e6, 0xf8e7, 0x21b5,
+ 0x2135, 0x2111, 0x211c, 0x2118, 0x2297, 0x2295, 0x2205, 0x2229,
+ 0x222a, 0x2283, 0x2287, 0x2284, 0x2282, 0x2286, 0x2208, 0x2209,
+ 0x2220, 0x2207, 0x00ae, 0x00a9, 0x2122, 0x220f, 0x221a, 0x22c5,
+ 0x00ac, 0x2227, 0x2228, 0x21d4, 0x21d0, 0x21d1, 0x21d2, 0x21d3,
+ 0x22c4, 0x2329, 0xf8e8, 0xf8e9, 0xf8ea, 0x2211, 0xf8eb, 0xf8ec,
+ 0xf8ed, 0xf8ee, 0xf8ef, 0xf8f0, 0xf8f1, 0xf8f2, 0xf8f3, 0xf8f4,
+ 0xf8ff, 0x232a, 0x222b, 0x2320, 0xf8f5, 0x2321, 0xf8f6, 0xf8f7,
+ 0xf8f8, 0xf8f9, 0xf8fa, 0xf8fb, 0xf8fc, 0xf8fd, 0xf8fe, 0x02c7
+};
+
+/* I don't think iconv provides encodings for zapfdingbats nor jis201 */
+/* Perhaps I should list them here for compatability, but I think I'll just */
+/* leave them out. I doubt they get used. */
+static Encoding texbase = { "TeX-Base-Encoding", 256, tex_base_encoding, NULL, NULL, 1, 1, 1, 1 };
+ Encoding custom = { "Custom", 0, NULL, NULL, &texbase, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0 };
+static Encoding original = { "Original", 0, NULL, NULL, &custom, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0 };
+static Encoding unicodebmp = { "UnicodeBmp", 65536, NULL, NULL, &original, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0 };
+static Encoding unicodefull = { "UnicodeFull", 17*65536, NULL, NULL, &unicodebmp, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0 };
+static Encoding adobestd = { "AdobeStandard", 256, unicode_from_adobestd, AdobeStandardEncoding, &unicodefull,
+ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 };
+static Encoding symbol = { "Symbol", 256, unicode_from_MacSymbol, NULL, &adobestd,1, 1, 1, 1, 0, 0, 0, 0, 0, 0 };
+
+Encoding *enclist = &symbol;
+
+const char *FindUnicharName(void) {
+ /* Iconv and libiconv use different names for UCS2. Just great. Perhaps */
+ /* different versions of each use still different names? */
+ /* Even worse, both accept UCS-2, but under iconv it means native byte */
+ /* ordering and under libiconv it means big-endian */
+ iconv_t test;
+ static char *goodname = NULL;
+#ifdef UNICHAR_16
+ static char *names[] = { "UCS-2", "UCS-2-INTERNAL", "UCS2", "ISO-10646/UCS2", "UNICODE", NULL };
+ static char *namesle[] = { "UCS-2LE", "UNICODELITTLE", NULL };
+ static char *namesbe[] = { "UCS-2BE", "UNICODEBIG", NULL };
+#else
+ static char *names[] = { "UCS-4", "UCS-4-INTERNAL", "UCS4", "ISO-10646-UCS-4", "UTF-32", NULL };
+ static char *namesle[] = { "UCS-4LE", "UTF-32LE", NULL };
+ static char *namesbe[] = { "UCS-4BE", "UTF-32BE", NULL };
+#endif
+ char **testnames;
+ int i;
+ union {
+ short s;
+ char c[2];
+ } u;
+
+ if ( goodname!=NULL )
+return( goodname );
+
+ u.c[0] = 0x1; u.c[1] = 0x2;
+ if ( u.s==0x201 ) { /* Little endian */
+ testnames = namesle;
+ } else {
+ testnames = namesbe;
+ }
+ for ( i=0; testnames[i]!=NULL; ++i ) {
+ test = iconv_open(testnames[i],"ISO-8859-1");
+ if ( test!=(iconv_t) -1 && test!=NULL ) {
+ iconv_close(test);
+ goodname = testnames[i];
+ break;
+ }
+ }
+
+ if ( goodname==NULL ) {
+ for ( i=0; names[i]!=NULL; ++i ) {
+ test = iconv_open(names[i],"ISO-8859-1");
+ if ( test!=(iconv_t) -1 && test!=NULL ) {
+ iconv_close(test);
+ goodname = names[i];
+ break;
+ }
+ }
+ }
+
+ if ( goodname==NULL ) {
+#ifdef UNICHAR_16
+ IError( "I can't figure out your version of iconv(). I need a name for the UCS-2 encoding and I can't find one. Reconfigure --without-iconv. Bye.");
+#else
+ IError( "I can't figure out your version of iconv(). I need a name for the UCS-4 encoding and I can't find one. Reconfigure --without-iconv. Bye.");
+#endif
+ exit( 1 );
+ }
+
+ test = iconv_open(names[i],"Mac");
+ if ( test==(iconv_t) -1 || test==NULL ) {
+ IError( "Your version of iconv does not support the \"Mac Roman\" encoding.\nIf this causes problems, reconfigure --without-iconv." );
+ } else
+ iconv_close(test);
+
+ /* I really should check for ISO-2022-JP, KR, CN, and all the other encodings */
+ /* I might find in a ttf 'name' table. But those tables take too long to build */
+return( goodname );
+}
+
+static int TryEscape( Encoding *enc,char *escape_sequence ) {
+ char from[20], ucs[20];
+ size_t fromlen, tolen;
+ ICONV_CONST char *fpt;
+ char *upt;
+ int i, j, low;
+ int esc_len = strlen(escape_sequence);
+
+ strcpy(from,escape_sequence);
+
+ enc->has_2byte = false;
+ low = -1;
+ for ( i=0; i<256; ++i ) if ( i!=escape_sequence[0] ) {
+ for ( j=0; j<256; ++j ) {
+ from[esc_len] = i; from[esc_len+1] = j; from[esc_len+2] = 0;
+ fromlen = esc_len+2;
+ fpt = from;
+ upt = ucs;
+ tolen = sizeof(ucs);
+ if ( iconv( enc->tounicode , &fpt, &fromlen, &upt, &tolen )!= (size_t) (-1) &&
+ upt-ucs==sizeof(unichar_t) /* Exactly one character */ ) {
+ if ( low==-1 ) {
+ enc->low_page = low = i;
+ enc->has_2byte = true;
+ }
+ enc->high_page = i;
+ break;
+ }
+ }
+ }
+ if ( enc->low_page==enc->high_page )
+ enc->has_2byte = false;
+ if ( enc->has_2byte ) {
+ strcpy(enc->iso_2022_escape, escape_sequence);
+ enc->iso_2022_escape_len = esc_len;
+ }
+return( enc->has_2byte );
+}
+
+Encoding *_FindOrMakeEncoding(const char *name,int make_it) {
+ Encoding *enc;
+ char buffer[20];
+ const char *iconv_name;
+ Encoding temp;
+ uint8 good[256];
+ int i, j, any, all;
+ char from[8], ucs[20];
+ size_t fromlen, tolen;
+ ICONV_CONST char *fpt;
+ char *upt;
+ /* iconv is not case sensitive */
+
+ if ( strncasecmp(name,"iso8859_",8)==0 || strncasecmp(name,"koi8_",5)==0 ) {
+ /* Fixup for old naming conventions */
+ strncpy(buffer,name,sizeof(buffer));
+ *strchr(buffer,'_') = '-';
+ name = buffer;
+ } else if ( strcasecmp(name,"iso-8859")==0 ) {
+ /* Fixup for old naming conventions */
+ strncpy(buffer,name,3);
+ strncpy(buffer+3,name+4,sizeof(buffer)-3);
+ name = buffer;
+ } else if ( strcasecmp(name,"isolatin1")==0 ) {
+ name = "iso8859-1";
+ } else if ( strcasecmp(name,"isocyrillic")==0 ) {
+ name = "iso8859-5";
+ } else if ( strcasecmp(name,"isoarabic")==0 ) {
+ name = "iso8859-6";
+ } else if ( strcasecmp(name,"isogreek")==0 ) {
+ name = "iso8859-7";
+ } else if ( strcasecmp(name,"isohebrew")==0 ) {
+ name = "iso8859-8";
+ } else if ( strcasecmp(name,"isothai")==0 ) {
+ name = "tis-620"; /* TIS doesn't define non-breaking space in 0xA0 */
+ } else if ( strcasecmp(name,"latin0")==0 || strcasecmp(name,"latin9")==0 ) {
+ name = "iso8859-15"; /* "latin-9" is supported (libiconv bug?) */
+ } else if ( strcasecmp(name,"koi8r")==0 ) {
+ name = "koi8-r";
+ } else if ( strncasecmp(name,"jis201",6)==0 || strncasecmp(name,"jisx0201",8)==0 ) {
+ name = "jis_x0201";
+ } else if ( strcasecmp(name,"AdobeStandardEncoding")==0 || strcasecmp(name,"Adobe")==0 )
+ name = "AdobeStandard";
+ for ( enc=enclist; enc!=NULL; enc=enc->next )
+ if ( strmatch(name,enc->enc_name)==0 ||
+ (enc->iconv_name!=NULL && strmatch(name,enc->iconv_name)==0))
+return( enc );
+ if ( strmatch(name,"unicode")==0 || strmatch(name,"iso10646")==0 || strmatch(name,"iso10646-1")==0 )
+return( &unicodebmp );
+ if ( strmatch(name,"unicode4")==0 || strmatch(name,"ucs4")==0 )
+return( &unicodefull );
+
+ iconv_name = name;
+ /* Mac seems to work ok */
+ if ( strcasecmp(name,"win")==0 || strcasecmp(name,"ansi")==0 )
+ iconv_name = "MS-ANSI"; /* "WINDOWS-1252";*/
+ else if ( strncasecmp(name,"jis208",6)==0 || strncasecmp(name,"jisx0208",8)==0 )
+ iconv_name = "ISO-2022-JP";
+ else if ( strncasecmp(name,"jis212",6)==0 || strncasecmp(name,"jisx0212",8)==0 )
+ iconv_name = "ISO-2022-JP-2";
+ else if ( strncasecmp(name,"ksc5601",7)==0 )
+ iconv_name = "ISO-2022-KR";
+ else if ( strcasecmp(name,"gb2312pk")==0 || strcasecmp(name,"gb2312packed")==0 )
+ iconv_name = "EUC-CN";
+ else if ( strncasecmp(name,"gb2312",6)==0 )
+ iconv_name = "ISO-2022-CN";
+ else if ( strcasecmp(name,"wansung")==0 )
+ iconv_name = "EUC-KR";
+ else if ( strcasecmp(name,"EUC-CN")==0 ) {
+ iconv_name = name;
+ name = "gb2312pk";
+ } else if ( strcasecmp(name,"EUC-KR")==0 ) {
+ iconv_name = name;
+ name = "wansung";
+ }
+
+/* Escape sequences: */
+/* ISO-2022-CN: \e $ ) A ^N */
+/* ISO-2022-KR: \e $ ) C ^N */
+/* ISO-2022-JP: \e $ B */
+/* ISO-2022-JP-2: \e $ ( D */
+/* ISO-2022-JP-3: \e $ ( O */ /* Capital "O", not zero */
+/* ISO-2022-CN-EXT: \e $ ) E ^N */ /* Not sure about this, also uses CN escape */
+
+ memset(&temp,0,sizeof(temp));
+ temp.builtin = true;
+ temp.tounicode = iconv_open(FindUnicharName(),iconv_name);
+ if ( temp.tounicode==(iconv_t) -1 || temp.tounicode==NULL )
+return( NULL ); /* Iconv doesn't recognize this name */
+ temp.fromunicode = iconv_open(iconv_name,FindUnicharName());
+ if ( temp.fromunicode==(iconv_t) -1 || temp.fromunicode==NULL ) {
+ /* This should never happen, but if it does... */
+ iconv_close(temp.tounicode);
+return( NULL );
+ }
+
+ memset(good,0,sizeof(good));
+ any = false; all = true;
+ for ( i=1; i<256; ++i ) {
+ from[0] = i; from[1] = 0;
+ fromlen = 1;
+ fpt = from;
+ upt = ucs;
+ tolen = sizeof(ucs);
+ if ( iconv( temp.tounicode , &fpt, &fromlen, &upt, &tolen )!= (size_t) (-1)) {
+ good[i] = true;
+ any = true;
+ } else
+ all = false;
+ }
+ if ( any )
+ temp.has_1byte = true;
+ if ( all )
+ temp.only_1byte = true;
+
+ if ( !all ) {
+ if ( strstr(iconv_name,"2022")==NULL ) {
+ for ( i=temp.has_1byte; i<256; ++i ) if ( !good[i] ) {
+ for ( j=0; j<256; ++j ) {
+ from[0] = i; from[1] = j; from[2] = 0;
+ fromlen = 2;
+ fpt = from;
+ upt = ucs;
+ tolen = sizeof(ucs);
+ if ( iconv( temp.tounicode , &fpt, &fromlen, &upt, &tolen )!= (size_t) (-1) &&
+ upt-ucs==sizeof(unichar_t) /* Exactly one character */ ) {
+ if ( temp.low_page==-1 )
+ temp.low_page = i;
+ temp.high_page = i;
+ temp.has_2byte = true;
+ break;
+ }
+ }
+ }
+ if ( temp.low_page==temp.high_page ) {
+ temp.has_2byte = false;
+ temp.low_page = temp.high_page = -1;
+ }
+ }
+ if ( !temp.has_2byte && !good[033]/* escape */ ) {
+ if ( strstr(iconv_name,"2022")!=NULL &&
+ strstr(iconv_name,"JP3")!=NULL &&
+ TryEscape( &temp,"\33$(O" ))
+ ;
+ else if ( strstr(iconv_name,"2022")!=NULL &&
+ strstr(iconv_name,"JP2")!=NULL &&
+ TryEscape( &temp,"\33$(D" ))
+ ;
+ else if ( strstr(iconv_name,"2022")!=NULL &&
+ strstr(iconv_name,"JP")!=NULL &&
+ TryEscape( &temp,"\33$B" ))
+ ;
+ else if ( strstr(iconv_name,"2022")!=NULL &&
+ strstr(iconv_name,"KR")!=NULL &&
+ TryEscape( &temp,"\33$)C\16" ))
+ ;
+ else if ( strstr(iconv_name,"2022")!=NULL &&
+ strstr(iconv_name,"CN")!=NULL &&
+ TryEscape( &temp,"\33$)A\16" ))
+ ;
+ }
+ }
+ if ( !temp.has_1byte && !temp.has_2byte )
+return( NULL );
+ if ( !make_it )
+return( NULL );
+
+ enc = chunkalloc(sizeof(Encoding));
+ *enc = temp;
+ enc->enc_name = copy(name);
+ if ( iconv_name!=name )
+ enc->iconv_name = copy(iconv_name);
+ enc->next = enclist;
+ enc->builtin = true;
+ enclist = enc;
+ if ( enc->has_2byte )
+ enc->char_cnt = (enc->high_page<<8) + 256;
+ else {
+ enc->char_cnt = 256;
+ enc->only_1byte = true;
+ }
+ if ( strstrmatch(iconv_name,"JP")!=NULL ||
+ strstrmatch(iconv_name,"sjis")!=NULL ||
+ strstrmatch(iconv_name,"cp932")!=NULL )
+ enc->is_japanese = true;
+ else if ( strstrmatch(iconv_name,"KR")!=NULL )
+ enc->is_korean = true;
+ else if ( strstrmatch(iconv_name,"CN")!=NULL )
+ enc->is_simplechinese = true;
+ else if ( strstrmatch(iconv_name,"BIG")!=NULL && strstrmatch(iconv_name,"5")!=NULL )
+ enc->is_tradchinese = true;
+
+ if ( strstrmatch(name,"ISO8859")!=NULL &&
+ strtol(name+strlen(name)-2,NULL,10)>=16 )
+ /* Not in our menu, don't hide */;
+ else if ( iconv_name!=name || strmatch(name,"mac")==0 || strstrmatch(name,"ISO8859")!=NULL ||
+ strmatch(name,"koi8-r")==0 || strmatch(name,"sjis")==0 ||
+ strmatch(name,"big5")==0 || strmatch(name,"big5hkscs")==0 )
+ enc->hidden = true;
+
+return( enc );
+}
+
+Encoding *FindOrMakeEncoding(const char *name) {
+return( _FindOrMakeEncoding(name,true));
+}
+
+/* Plugin API */
+int AddEncoding(char *name,EncFunc enc_to_uni,EncFunc uni_to_enc,int max) {
+ Encoding *enc;
+ int i;
+
+ for ( enc=enclist; enc!=NULL; enc=enc->next ) {
+ if ( strmatch(name,enc->enc_name)==0 ||
+ (enc->iconv_name!=NULL && strmatch(name,enc->iconv_name)==0)) {
+ if ( enc->tounicode_func==NULL )
+return( 0 ); /* Failure */
+ else {
+ enc->tounicode_func = enc_to_uni;
+ enc->fromunicode_func = uni_to_enc;
+ enc->char_cnt = max;
+return( 2 );
+ }
+ }
+ }
+
+ if ( strmatch(name,"unicode")==0 || strmatch(name,"iso10646")==0 || strmatch(name,"iso10646-1")==0 )
+return( 0 ); /* Failure */
+ if ( strmatch(name,"unicode4")==0 || strmatch(name,"ucs4")==0 )
+return( 0 ); /* Failure */
+
+ enc = chunkalloc(sizeof(Encoding));
+ enc->enc_name = copy(name);
+ enc->next = enclist;
+ enclist = enc;
+ enc->tounicode_func = enc_to_uni;
+ enc->fromunicode_func = uni_to_enc;
+ enc->char_cnt = max;
+ for ( i=0; i<256 && i<max; ++i )
+ if ( enc_to_uni(i)!=-1 )
+ break;
+
+ if ( i<256 && i<max )
+ enc->has_1byte = true;
+ if ( max<256 )
+ enc->only_1byte = true;
+ else
+ enc->has_2byte = true;
+return( 1 );
+}
+
+static char *getPfaEditEncodings(void) {
+ static char *encfile=NULL;
+ char buffer[1025];
+
+ if ( encfile!=NULL )
+return( encfile );
+ if ( getPfaEditDir(buffer)==NULL )
+return( NULL );
+ sprintf(buffer,"%s/Encodings.ps", getPfaEditDir(buffer));
+ encfile = copy(buffer);
+return( encfile );
+}
+
+static void EncodingFree(Encoding *item) {
+ int i;
+
+ free(item->enc_name);
+ if ( item->psnames!=NULL ) for ( i=0; i<item->char_cnt; ++i )
+ free(item->psnames[i]);
+ free(item->psnames);
+ free(item->unicode);
+ free(item);
+}
+
+/* Parse a TXT file from the unicode consortium */
+ /* Unicode Consortium Format A */
+ /* List of lines with several fields, */
+ /* first is the encoding value (in hex), second the Unicode value (in hex) */
+ /* # is a comment character (to eol) */
+static Encoding *ParseConsortiumEncodingFile(FILE *file) {
+ char buffer[200];
+ int32 encs[1024];
+ int enc, unienc, max, i;
+ Encoding *item;
+
+ for ( i=0; i<1024; ++i )
+ encs[i] = 0;
+ for ( i=0; i<32; ++i )
+ encs[i] = i;
+ for ( i=127; i<0xa0; ++i )
+ encs[i] = i;
+ max = -1;
+
+ while ( fgets(buffer,sizeof(buffer),file)!=NULL ) {
+ if ( Ishexdigit(buffer[0]) ) {
+ if ( sscanf(buffer, "%x %x", (unsigned *) &enc, (unsigned *) &unienc)==2 &&
+ enc<1024 && enc>=0 ) {
+ encs[enc] = unienc;
+ if ( enc>max ) max = enc;
+ }
+ }
+ }
+
+ if ( max==-1 )
+return( NULL );
+
+ ++max;
+ if ( max<256 ) max = 256;
+ item = gcalloc(1,sizeof(Encoding));
+ item->only_1byte = item->has_1byte = true;
+ item->char_cnt = max;
+ item->unicode = galloc(max*sizeof(int32));
+ memcpy(item->unicode,encs,max*sizeof(int32));
+return( item );
+}
+
+static void DeleteEncoding(Encoding *me);
+
+static void RemoveMultiples(Encoding *item) {
+ Encoding *test;
+
+ for ( test=enclist; test!=NULL; test = test->next ) {
+ if ( strcmp(test->enc_name,item->enc_name)==0 )
+ break;
+ }
+ if ( test!=NULL )
+ DeleteEncoding(test);
+}
+
+void ParseEncodingFile(char *filename) {
+ FILE *file;
+ char *orig = filename;
+ Encoding *head, *item, *prev, *next;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ char buf[300];
+ char *name;
+#endif
+ int i,ch;
+ file = NULL;
+ if ( filename==NULL ) filename = getPfaEditEncodings();
+ if ( filename!=NULL ) file = fopen(filename,"r");
+ if ( file==NULL ) {
+ if ( orig!=NULL )
+ gwwv_post_error(_("Couldn't open file"), _("Couldn't open file %.200s"), orig);
+return;
+ }
+ ch = getc(file);
+ if ( ch==EOF ) {
+ fclose(file);
+return;
+ }
+ ungetc(ch,file);
+ if ( ch=='#' || ch=='0' )
+ head = ParseConsortiumEncodingFile(file);
+ else
+ head = PSSlurpEncodings(file);
+ fclose(file);
+ if ( head==NULL ) {
+ gwwv_post_error(_("Bad encoding file format"),_("Bad encoding file format") );
+return;
+ }
+
+ for ( i=0, prev=NULL, item=head; item!=NULL; prev = item, item=next, ++i ) {
+ next = item->next;
+ if ( item->enc_name==NULL ) {
+ if ( no_windowing_ui ) {
+ gwwv_post_error(_("Bad encoding file format"),_("This file contains an unnamed encoding, which cannot be named in a script"));
+return;
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( item==head && item->next==NULL )
+ strcpy(buf,_("Please name this encoding"));
+ else {
+# if defined( _NO_SNPRINTF ) || defined( __VMS )
+ if ( i<=3 )
+ sprintf(buf,
+ _("Please name the %s encoding in this file"),
+ i==1 ? _("First") :
+ i==2 ? _("Second") :
+ _("Third") );
+ else
+ sprintf(buf, _("Please name the %dth encoding in this file"),
+ i );
+# else
+ if ( i<=3 )
+ snprintf(buf,sizeof(buf),
+ _("Please name the %s encoding in this file"),
+ i==1 ? _("_First") : i==2 ? _("Second") : _("Third") );
+ else
+ snprintf(buf,sizeof(buf),
+ _("Please name the %dth encoding in this file"),
+ i );
+# endif
+ }
+ name = gwwv_ask_string(buf,NULL,buf);
+ if ( name!=NULL ) {
+ item->enc_name = copy(name);
+ free(name);
+ } else {
+ if ( prev==NULL )
+ head = item->next;
+ else
+ prev->next = item->next;
+ EncodingFree(item);
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+ }
+ for ( item=head; item!=NULL; item=item->next )
+ RemoveMultiples(item);
+
+ if ( enclist == NULL )
+ enclist = head;
+ else {
+ for ( item=enclist; item->next!=NULL; item=item->next );
+ item->next = head;
+ }
+}
+
+void LoadPfaEditEncodings(void) {
+ ParseEncodingFile(NULL);
+}
+
+void DumpPfaEditEncodings(void) {
+ FILE *file;
+ Encoding *item;
+ int i;
+ char buffer[80];
+
+ for ( item=enclist; item!=NULL && item->builtin; item=item->next );
+ if ( item==NULL ) {
+ unlink(getPfaEditEncodings());
+return;
+ }
+
+ file = fopen( getPfaEditEncodings(), "w");
+ if ( file==NULL ) {
+ LogError( _("couldn't write encodings file\n") );
+return;
+ }
+
+ for ( item=enclist; item!=NULL; item = item->next ) if ( !item->builtin && item->tounicode_func==NULL ) {
+ fprintf( file, "/%s [\n", item->enc_name );
+ if ( item->psnames==NULL )
+ fprintf( file, "%% Use codepoints.\n" );
+ for ( i=0; i<item->char_cnt; ++i ) {
+ if ( item->psnames!=NULL && item->psnames[i]!=NULL )
+ fprintf( file, " /%s", item->psnames[i]);
+ else if ( item->unicode[i]<' ' || (item->unicode[i]>=0x7f && item->unicode[i]<0xa0))
+ fprintf( file, " /.notdef" );
+ else
+ fprintf( file, " /%s", StdGlyphName(buffer,item->unicode[i],ui_none,(NameList *) -1));
+ if ( (i&0xf)==0 )
+ fprintf( file, "\t\t%% 0x%02x\n", i );
+ else
+ putc('\n',file);
+ }
+ fprintf( file, "] def\n\n" );
+ }
+ fclose(file);
+}
+
+static void DeleteEncoding(Encoding *me) {
+ FontView *fv;
+ Encoding *prev;
+
+ if ( me->builtin )
+return;
+
+ for ( fv = fv_list; fv!=NULL; fv = fv->next ) {
+ if ( fv->map->enc==me )
+ fv->map->enc = &custom;
+ }
+ if ( me==enclist )
+ enclist = me->next;
+ else {
+ for ( prev = enclist; prev!=NULL && prev->next!=me; prev=prev->next );
+ if ( prev!=NULL ) prev->next = me->next;
+ }
+ EncodingFree(me);
+ if ( default_encoding == me )
+ default_encoding = FindOrMakeEncoding("ISO8859-1");
+ if ( default_encoding == NULL )
+ default_encoding = &custom;
+ DumpPfaEditEncodings();
+}
+
+#ifndef LUA_FF_LIB
+static GTextInfo *EncodingList(void) {
+ GTextInfo *ti;
+ int i;
+ Encoding *item;
+
+ i = 0;
+ for ( item=enclist; item!=NULL ; item=item->next )
+ if ( !item->builtin )
+ ++i;
+ ti = gcalloc(i+1,sizeof(GTextInfo));
+ i = 0;
+ for ( item=enclist; item!=NULL ; item=item->next )
+ if ( !item->builtin )
+ ti[i++].text = uc_copy(item->enc_name);
+ if ( i!=0 )
+ ti[0].selected = true;
+return( ti );
+}
+#endif
+
+#define CID_Encodings 1001
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+
+static int DE_Delete(GGadget *g, GEvent *e) {
+ GWindow gw;
+ int *done;
+ GGadget *list;
+ int sel,i;
+ Encoding *item;
+
+ if ( e->type==et_controlevent &&
+ (e->u.control.subtype == et_buttonactivate ||
+ e->u.control.subtype == et_listdoubleclick )) {
+ gw = GGadgetGetWindow(g);
+ done = GDrawGetUserData(gw);
+ list = GWidgetGetControl(gw,CID_Encodings);
+ sel = GGadgetGetFirstListSelectedItem(list);
+ i=0;
+ for ( item=enclist; item!=NULL; item=item->next ) {
+ if ( item->builtin )
+ /* Do Nothing */;
+ else if ( i==sel )
+ break;
+ else
+ ++i;
+ }
+ if ( item!=NULL )
+ DeleteEncoding(item);
+ *done = true;
+ }
+return( true );
+}
+
+static int DE_Cancel(GGadget *g, GEvent *e) {
+ GWindow gw;
+ int *done;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ gw = GGadgetGetWindow(g);
+ done = GDrawGetUserData(gw);
+ *done = true;
+ }
+return( true );
+}
+
+static int de_e_h(GWindow gw, GEvent *event) {
+ if ( event->type==et_close ) {
+ int *done = GDrawGetUserData(gw);
+ *done = true;
+ } else if ( event->type == et_char ) {
+return( false );
+ }
+return( true );
+}
+
+void RemoveEncoding(void) {
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[5];
+ GTextInfo label[5];
+ Encoding *item;
+ int done = 0;
+
+ for ( item=enclist; item!=NULL && item->builtin; item=item->next );
+ if ( item==NULL )
+return;
+
+ memset(&gcd,0,sizeof(gcd));
+ memset(&label,0,sizeof(label));
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Remove Encoding");
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,150));
+ pos.height = GDrawPointsToPixels(NULL,110);
+ gw = GDrawCreateTopWindow(NULL,&pos,de_e_h,&done,&wattrs);
+
+ gcd[0].gd.pos.x = 10; gcd[0].gd.pos.y = 6;
+ gcd[0].gd.pos.width = 130; gcd[0].gd.pos.height = 5*12+10;
+ gcd[0].gd.flags = gg_visible | gg_enabled;
+ gcd[0].gd.cid = CID_Encodings;
+ gcd[0].gd.u.list = EncodingList();
+ gcd[0].gd.handle_controlevent = DE_Delete;
+ gcd[0].creator = GListCreate;
+
+ gcd[2].gd.pos.x = -10; gcd[2].gd.pos.y = gcd[0].gd.pos.y+gcd[0].gd.pos.height+5;
+ gcd[2].gd.pos.width = -1; gcd[2].gd.pos.height = 0;
+ gcd[2].gd.flags = gg_visible | gg_enabled | gg_but_cancel ;
+ label[2].text = (unichar_t *) _("_Cancel");
+ label[2].text_is_1byte = true;
+ label[2].text_in_resource = true;
+ gcd[2].gd.label = &label[2];
+ gcd[2].gd.mnemonic = 'C';
+ gcd[2].gd.handle_controlevent = DE_Cancel;
+ gcd[2].creator = GButtonCreate;
+
+ gcd[1].gd.pos.x = 10-3; gcd[1].gd.pos.y = gcd[2].gd.pos.y-3;
+ gcd[1].gd.pos.width = -1; gcd[1].gd.pos.height = 0;
+ gcd[1].gd.flags = gg_visible | gg_enabled | gg_but_default ;
+ label[1].text = (unichar_t *) _("_Delete");
+ label[1].text_is_1byte = true;
+ label[1].text_in_resource = true;
+ gcd[1].gd.mnemonic = 'D';
+ gcd[1].gd.label = &label[1];
+ gcd[1].gd.handle_controlevent = DE_Delete;
+ gcd[1].creator = GButtonCreate;
+
+ gcd[3].gd.pos.x = 2; gcd[3].gd.pos.y = 2;
+ gcd[3].gd.pos.width = pos.width-4; gcd[3].gd.pos.height = pos.height-2;
+ gcd[3].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
+ gcd[3].creator = GGroupCreate;
+
+ GGadgetsCreate(gw,gcd);
+ GTextInfoListFree(gcd[0].gd.u.list);
+
+ GWidgetHidePalettes();
+ GDrawSetVisible(gw,true);
+ while ( !done )
+ GDrawProcessOneEvent(NULL);
+ GDrawDestroyWindow(gw);
+}
+#endif
+
+Encoding *MakeEncoding(SplineFont *sf,EncMap *map) {
+ char *name;
+ int i, gid;
+ Encoding *item, *temp;
+ SplineChar *sc;
+
+ if ( map->enc!=&custom )
+return(NULL);
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ name = gwwv_ask_string(_("Please name this encoding"),NULL,_("Please name this encoding"));
+#else
+ name = NULL;
+#endif
+ if ( name==NULL )
+return(NULL);
+ item = gcalloc(1,sizeof(Encoding));
+ item->enc_name = name;
+ item->only_1byte = item->has_1byte = true;
+ item->char_cnt = map->enccount;
+ item->unicode = gcalloc(map->enccount,sizeof(int32));
+ for ( i=0; i<map->enccount; ++i ) if ( (gid = map->map[i])!=-1 && (sc=sf->glyphs[gid])!=NULL ) {
+ if ( sc->unicodeenc!=-1 )
+ item->unicode[i] = sc->unicodeenc;
+ else if ( strcmp(sc->name,".notdef")!=0 ) {
+ if ( item->psnames==NULL )
+ item->psnames = gcalloc(map->enccount,sizeof(unichar_t *));
+ item->psnames[i] = copy(sc->name);
+ }
+ }
+ RemoveMultiples(item);
+
+ if ( enclist == NULL )
+ enclist = item;
+ else {
+ for ( temp=enclist; temp->next!=NULL; temp=temp->next );
+ temp->next = item;
+ }
+ DumpPfaEditEncodings();
+return( item );
+}
+
+#ifndef LUA_FF_LIB
+void LoadEncodingFile(void) {
+ char *filename;
+ char *fn = NULL;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ static char filter[] = "*.{ps,PS,txt,TXT,enc,ENC}";
+ fn = gwwv_open_filename(_("Load Encoding"), NULL, filter, NULL);
+#endif
+ if ( fn==NULL )
+return;
+ filename = utf82def_copy(fn);
+ ParseEncodingFile(filename);
+ free(fn); free(filename);
+ DumpPfaEditEncodings();
+}
+#endif
+
+void SFFindNearTop(SplineFont *sf) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FontView *fv;
+ EncMap *map;
+ int i,k,gid;
+
+ if ( sf->cidmaster!=NULL )
+ sf = sf->cidmaster;
+ if ( sf->subfontcnt==0 ) {
+ for ( fv=sf->fv; fv!=NULL; fv=fv->nextsame ) {
+ map = fv->map;
+ fv->sc_near_top = NULL;
+ for ( i=fv->rowoff*fv->colcnt; i<map->enccount && i<(fv->rowoff+fv->rowcnt)*fv->colcnt; ++i )
+ if ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL ) {
+ fv->sc_near_top = sf->glyphs[gid];
+ break;
+ }
+ }
+ } else {
+ for ( fv=sf->fv; fv!=NULL; fv=fv->nextsame ) {
+ map = fv->map;
+ fv->sc_near_top = NULL;
+ for ( i=fv->rowoff*fv->colcnt; i<map->enccount && i<(fv->rowoff+fv->rowcnt)*fv->colcnt; ++i ) {
+ for ( k=0; k<sf->subfontcnt; ++k )
+ if ( (gid=map->map[i])!=-1 &&
+ gid<sf->subfonts[k]->glyphcnt &&
+ sf->subfonts[k]->glyphs[gid]!=NULL )
+ fv->sc_near_top = sf->subfonts[k]->glyphs[gid];
+ }
+ }
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+}
+
+void SFRestoreNearTop(SplineFont *sf) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FontView *fv;
+
+ for ( fv=sf->fv; fv!=NULL; fv=fv->nextsame ) if ( fv->sc_near_top!=NULL ) {
+ /* Note: For CID keyed fonts, we don't care if sc is in the currenly */
+ /* displayed font, all we care about is the CID */
+ int enc = fv->map->backmap[fv->sc_near_top->orig_pos];
+ if ( enc!=-1 ) {
+ fv->rowoff = enc/fv->colcnt;
+ GScrollBarSetPos(fv->vsb,fv->rowoff);
+ /* Don't ask for an expose event yet. We'll get one soon enough */
+ }
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+}
+
+/* ************************************************************************** */
+/* ****************************** CID Encodings ***************************** */
+/* ************************************************************************** */
+struct cidmap {
+ char *registry, *ordering;
+ int supplement, maxsupple;
+ int cidmax; /* Max cid found in the charset */
+ int namemax; /* Max cid with useful info */
+ uint32 *unicode;
+ char **name;
+ struct cidmap *next;
+};
+
+static struct cidmap *cidmaps = NULL;
+
+int CIDFromName(char *name,SplineFont *cidmaster) {
+ /* We've had various conventions for encoding a cid inside a name */
+ /* I'm primarily interested in this when the name is something like */
+ /* Japan1.504.vert */
+ /* which tells me that the current glyph is the rotated version of */
+ /* cid 504 */
+ /* Other convention "cid-504.vert" */
+ int len = strlen( cidmaster->ordering );
+ int cid;
+ char *end;
+
+ if ( strncmp(name,cidmaster->ordering,len)==0 ) {
+ if ( name[len]=='.' ) ++len;
+ } else if ( strncmp(name,"cid-",4)==0 ) {
+ len = 4;
+ }
+ cid = strtol(name+len,&end,10);
+ if ( end==name+len )
+return( -1 );
+ if ( *end!='.' && *end!='\0' )
+return( -1 );
+
+return ( cid );
+}
+
+int CID2Uni(struct cidmap *map,int cid) {
+ unsigned int uni;
+
+ if ( map==NULL )
+return( -1 );
+ else if ( cid==0 )
+return( 0 );
+ else if ( cid<map->namemax && map->unicode[cid]!=0 )
+return( map->unicode[cid] );
+ else if ( cid<map->namemax && map->name[cid]!=NULL ) {
+ if ( sscanf(map->name[cid],"uni%x", &uni )==1 )
+return( uni );
+ }
+
+return( -1 );
+}
+
+int CID2NameUni(struct cidmap *map,int cid, char *buffer, int len) {
+ int enc = -1;
+ const char *temp;
+
+#if defined( _NO_SNPRINTF ) || defined( __VMS )
+ if ( map==NULL )
+ sprintf(buffer,"cid-%d", cid);
+ else if ( cid<map->namemax && map->name[cid]!=NULL )
+ strncpy(buffer,map->name[cid],len);
+ else if ( cid==0 || (cid<map->namemax && map->unicode[cid]!=0 )) {
+ if ( map->unicode==NULL || map->namemax==0 )
+ enc = 0;
+ else
+ enc = map->unicode[cid];
+ temp = StdGlyphName(buffer,enc,ui_none,(NameList *) -1);
+ if ( temp!=buffer )
+ strcpy(buffer,temp);
+ } else
+ sprintf(buffer,"%s.%d", map->ordering, cid);
+#else
+ if ( map==NULL )
+ snprintf(buffer,len,"cid-%d", cid);
+ else if ( cid<map->namemax && map->name[cid]!=NULL )
+ strncpy(buffer,map->name[cid],len);
+ else if ( cid==0 )
+ strcpy(buffer,".notdef");
+ else if ( cid<map->namemax && map->unicode[cid]!=0 ) {
+ if ( map->unicode==NULL || map->namemax==0 )
+ enc = 0;
+ else
+ enc = map->unicode[cid];
+ temp = StdGlyphName(buffer,enc,ui_none,(NameList *) -1);
+ if ( temp!=buffer )
+ strcpy(buffer,temp);
+ } else
+ snprintf(buffer,len,"%s.%d", map->ordering, cid);
+#endif
+return( enc );
+}
+
+int NameUni2CID(struct cidmap *map,int uni, const char *name) {
+ int i;
+
+ if ( map==NULL )
+return( -1 );
+ if ( uni!=-1 ) {
+ for ( i=0; i<map->namemax; ++i )
+ if ( map->unicode[i]==uni )
+return( i );
+ } else {
+ for ( i=0; i<map->namemax; ++i )
+ if ( map->name[i]!=NULL && strcmp(map->name[i],name)==0 )
+return( i );
+ }
+return( -1 );
+}
+
+int MaxCID(struct cidmap *map) {
+return( map->cidmax );
+}
+
+static char *SearchDirForCidMap(char *dir,char *registry,char *ordering,
+ int supplement,char **maybefile) {
+ char maybe[FILENAME_MAX+1];
+ struct dirent *ent;
+ DIR *d;
+ int len, rlen = strlen(registry), olen=strlen(ordering);
+ char *pt, *end, *ret;
+ int test, best = -1;
+
+ if ( dir==NULL )
+return( NULL );
+
+ if ( *maybefile!=NULL ) {
+ char *pt = strrchr(*maybefile,'.');
+ while ( pt>*maybefile && Isdigit(pt[-1]))
+ --pt;
+ best = strtol(pt,NULL,10);
+ }
+
+ d = opendir(dir);
+ if ( d==NULL )
+return( NULL );
+ while ( (ent = readdir(d))!=NULL ) {
+ if ( (len = strlen(ent->d_name))<8 )
+ continue;
+ if ( strcmp(ent->d_name+len-7,".cidmap")!=0 )
+ continue;
+ if ( strncmp(ent->d_name,registry,rlen)!=0 || ent->d_name[rlen]!='-' )
+ continue;
+ pt = ent->d_name+rlen+1;
+ if ( strncmp(pt,ordering,olen)!=0 || pt[olen]!='-' )
+ continue;
+ pt += olen+1;
+ if ( !Isdigit(*pt))
+ continue;
+ test = strtol(pt,&end,10);
+ if ( *end!='.' )
+ continue;
+ if ( test>=supplement ) {
+ ret = galloc(strlen(dir)+1+len+1);
+ strcpy(ret,dir);
+ strcat(ret,"/");
+ strcat(ret,ent->d_name);
+ closedir(d);
+return( ret );
+ } else if ( test>best ) {
+ best = test;
+ strcpy(maybe,ent->d_name);
+ }
+ }
+ closedir(d);
+ if ( best>-1 ) {
+ ret = galloc(strlen(dir)+1+strlen(maybe)+1);
+ strcpy(ret,dir);
+ strcat(ret,"/");
+ strcat(ret,maybe);
+ *maybefile = ret;
+ }
+return( NULL );
+}
+
+#ifndef LUA_FF_LIB
+static char *SearchNoLibsDirForCidMap(char *dir,char *registry,char *ordering,
+ int supplement,char **maybefile) {
+ char *ret;
+
+ if ( dir==NULL || strstr(dir,"/.libs")==NULL )
+return( NULL );
+
+ dir = copy(dir);
+ *strstr(dir,"/.libs") = '\0';
+
+ ret = SearchDirForCidMap(dir,registry,ordering,supplement,maybefile);
+ free(dir);
+return( ret );
+}
+#endif
+
+static struct cidmap *MakeDummyMap(char *registry,char *ordering,int supplement) {
+ struct cidmap *ret = galloc(sizeof(struct cidmap));
+
+ ret->registry = copy(registry);
+ ret->ordering = copy(ordering);
+ ret->supplement = ret->maxsupple = supplement;
+ ret->cidmax = ret->namemax = 0;
+ ret->unicode = NULL; ret->name = NULL;
+ ret->next = cidmaps;
+ cidmaps = ret;
+return( ret );
+}
+
+struct cidmap *LoadMapFromFile(char *file,char *registry,char *ordering,
+ int supplement) {
+ struct cidmap *ret = galloc(sizeof(struct cidmap));
+ char *pt = strrchr(file,'.');
+ FILE *f;
+ int cid1, cid2, uni, cnt, i;
+ char name[100];
+
+ while ( pt>file && Isdigit(pt[-1]))
+ --pt;
+ ret->supplement = ret->maxsupple = strtol(pt,NULL,10);
+ if ( supplement>ret->maxsupple )
+ ret->maxsupple = supplement;
+ ret->registry = copy(registry);
+ ret->ordering = copy(ordering);
+ ret->next = cidmaps;
+ cidmaps = ret;
+
+ f = fopen( file,"r" );
+ if ( f==NULL ) {
+#if defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("Missing cidmap file"),_("Couldn't open cidmap file: %s"), file );
+#else
+ gwwv_post_error(_("Couldn't open file"), _("Couldn't open file %.200s"), file);
+#endif
+ ret->cidmax = ret->namemax = 0;
+ ret->unicode = NULL; ret->name = NULL;
+ } else if ( fscanf( f, "%d %d", &ret->cidmax, &ret->namemax )!=2 ) {
+#if defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("Bad cidmap file"),_("%s is not a cidmap file, please download\nhttp://fontforge.sourceforge.net/cidmaps.tgz"), file );
+ fprintf( stderr, _("%s is not a cidmap file, please download\nhttp://fontforge.sourceforge.net/cidmaps.tgz"), file );
+#else
+ gwwv_post_error(_("Bad Cidmap File"), _("%s is not a cidmap file, please download\nhttp://fontforge.sourceforge.net/cidmaps.tgz"), file);
+ fprintf( stderr, "%s is not a cidmap file, please download\nhttp://fontforge.sourceforge.net/cidmaps.tgz", file );
+#endif
+ ret->cidmax = ret->namemax = 0;
+ ret->unicode = NULL; ret->name = NULL;
+ } else {
+ ret->unicode = gcalloc(ret->namemax+1,sizeof(uint32));
+ ret->name = gcalloc(ret->namemax+1,sizeof(char *));
+ while ( 1 ) {
+ cnt=fscanf( f, "%d..%d %x", &cid1, &cid2, (unsigned *) &uni );
+ if ( cnt<=0 )
+ break;
+ if ( cid1>ret->namemax )
+ continue;
+ if ( cnt==3 ) {
+ if ( cid2>ret->namemax ) cid2 = ret->namemax;
+ for ( i=cid1; i<=cid2; ++i )
+ ret->unicode[i] = uni++;
+ } else if ( cnt==1 ) {
+ if ( fscanf(f,"%x", (unsigned *) &uni )==1 )
+ ret->unicode[cid1] = uni;
+ else if ( fscanf(f," /%s", name )==1 )
+ ret->name[cid1] = copy(name);
+ }
+ }
+ fclose(f);
+ }
+ free(file);
+return( ret );
+}
+
+struct cidmap *FindCidMap(char *registry,char *ordering,int supplement,SplineFont *sf) {
+ struct cidmap *map, *maybe=NULL;
+ char *file, *maybefile=NULL;
+ int maybe_sup = -1;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ char *buts[3], *buts2[3], *buts3[3];
+ char buf[100];
+#endif
+ int ret;
+
+ if ( sf!=NULL && sf->loading_cid_map )
+return( NULL );
+
+ for ( map = cidmaps; map!=NULL; map = map->next ) {
+ if ( strcmp(map->registry,registry)==0 && strcmp(map->ordering,ordering)==0 ) {
+ if ( supplement<=map->supplement )
+return( map );
+ else if ( maybe==NULL || maybe->supplement<map->supplement )
+ maybe = map;
+ }
+ }
+ if ( maybe!=NULL && supplement<=maybe->maxsupple )
+return( maybe ); /* User has said it's ok to use maybe at this supplement level */
+
+ file = SearchDirForCidMap(".",registry,ordering,supplement,&maybefile);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( file==NULL )
+ file = SearchDirForCidMap(GResourceProgramDir,registry,ordering,supplement,&maybefile);
+ if ( file==NULL )
+ file = SearchNoLibsDirForCidMap(GResourceProgramDir,registry,ordering,supplement,&maybefile);
+#endif
+#ifdef SHAREDIR
+ if ( file==NULL )
+ file = SearchDirForCidMap(SHAREDIR,registry,ordering,supplement,&maybefile);
+#endif
+ if ( file==NULL )
+ file = SearchDirForCidMap(getPfaEditShareDir(),registry,ordering,supplement,&maybefile);
+ if ( file==NULL )
+ file = SearchDirForCidMap("/usr/share/fontforge",registry,ordering,supplement,&maybefile);
+
+ if ( file==NULL && (maybe!=NULL || maybefile!=NULL)) {
+ if ( maybefile!=NULL ) {
+ char *pt = strrchr(maybefile,'.');
+ while ( pt>maybefile && Isdigit(pt[-1]))
+ --pt;
+ maybe_sup = strtol(pt,NULL,10);
+ if ( maybe!=NULL && maybe->supplement >= maybe_sup ) {
+ free(maybefile); maybefile = NULL;
+ maybe_sup = maybe->supplement;
+ } else
+ maybe = NULL;
+ }
+ if ( maybe!=NULL )
+ maybe_sup = maybe->supplement;
+ if ( sf!=NULL ) sf->loading_cid_map = true;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ buts[0] = _("_Use It"); buts[1] = _("_Search"); buts[2] = NULL;
+ ret = gwwv_ask(_("Use CID Map"),(const char **) buts,0,1,_("This font is based on the charset %1$.20s-%2$.20s-%3$d, but the best I've been able to find is %1$.20s-%2$.20s-%4$d.\nShall I use that or let you search?"),
+ registry,ordering,supplement,maybe_sup);
+#else
+ ret = 0; /* In a script, default to using an old version of the file */
+ /* We'll get most cids that way */
+#endif
+ if ( sf!=NULL ) sf->loading_cid_map = false;
+ if ( ret==0 ) {
+ if ( maybe!=NULL ) {
+ maybe->maxsupple = supplement;
+return( maybe );
+ } else {
+ file = maybefile;
+ maybefile = NULL;
+ }
+ }
+ }
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( file==NULL ) {
+ char *uret;
+#if defined( _NO_SNPRINTF ) || defined( __VMS )
+ sprintf(buf,"%s-%s-*.cidmap", registry, ordering );
+#else
+ snprintf(buf,sizeof(buf),"%s-%s-*.cidmap", registry, ordering );
+#endif
+ if ( maybe==NULL && maybefile==NULL ) {
+ buts3[0] = _("_Browse"); buts3[1] = _("_Give Up"); buts3[2] = NULL;
+ ret = gwwv_ask(_("No cidmap file..."),(const char **)buts3,0,1,_("FontForge was unable to find a cidmap file for this font. It is not essential to have one, but some things will work better if you do. If you have not done so you might want to download the cidmaps from:\n http://FontForge.sourceforge.net/cidmaps.tgz\nand then gunzip and untar them and move them to:\n %.80s\n\nWould you like to search your local disk for an appropriate file?"),
+#ifdef SHAREDIR
+ SHAREDIR
+#else
+ getPfaEditShareDir()==NULL?"/usr/share/fontforge":getPfaEditShareDir()
+#endif
+ );
+ if ( ret==1 || no_windowing_ui )
+ buf[0] = '\0';
+ }
+ uret = NULL;
+ if ( buf[0]!='\0' && !no_windowing_ui ) {
+ if ( sf!=NULL ) sf->loading_cid_map = true;
+ uret = gwwv_open_filename(_("Find a cidmap file..."),NULL,buf,NULL);
+ if ( sf!=NULL ) sf->loading_cid_map = false;
+ }
+ if ( uret==NULL ) {
+ buts2[0] = "_Use It"; buts2[1] = "_Search"; buts2[2] = NULL;
+ if ( maybe==NULL && maybefile==NULL )
+ /* No luck */;
+ else if ( no_windowing_ui && maybe!=NULL ) {
+ maybe->maxsupple = supplement;
+return( maybe );
+ } else if ( no_windowing_ui ) {
+ file = maybefile;
+ maybefile = NULL;
+ } else if ( gwwv_ask(_("Use CID Map"),(const char **)buts2,0,1,_("Are you sure you don't want to use the cidmap I found?"))==0 ) {
+ if ( maybe!=NULL ) {
+ maybe->maxsupple = supplement;
+return( maybe );
+ } else {
+ file = maybefile;
+ maybefile = NULL;
+ }
+ }
+ } else {
+ file = utf82def_copy(uret);
+ free(uret);
+ }
+ }
+#else /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ if ( maybe==NULL && maybefile==NULL )
+ /* No luck */;
+ else if ( maybe!=NULL ) {
+ maybe->maxsupple = supplement;
+return( maybe );
+ } else {
+ file = maybefile;
+ maybefile = NULL;
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+ free(maybefile);
+ if ( file!=NULL )
+return( LoadMapFromFile(file,registry,ordering,supplement));
+
+return( MakeDummyMap(registry,ordering,supplement));
+}
+
+static void SFApplyOrdering(SplineFont *sf, int glyphcnt) {
+ SplineChar **glyphs, *sc;
+ int i;
+ RefChar *refs, *rnext, *rprev;
+ SplineSet *new, *spl;
+
+ /* Remove references to characters which aren't in the new map (if any) */
+ /* Don't need to fix up dependencies, because we throw the char away */
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( (sc = sf->glyphs[i])!=NULL ) {
+ for ( rprev = NULL, refs=sc->layers[ly_fore].refs; refs!=NULL; refs=rnext ) {
+ rnext = refs->next;
+ if ( refs->sc->orig_pos==-1 ) {
+ new = refs->layers[0].splines;
+ if ( new!=NULL ) {
+ for ( spl = new; spl->next!=NULL; spl = spl->next );
+ spl->next = sc->layers[ly_fore].splines;
+ sc->layers[ly_fore].splines = new;
+ }
+ refs->layers[0].splines=NULL;
+ RefCharFree(refs);
+ if ( rprev==NULL )
+ sc->layers[ly_fore].refs = rnext;
+ else
+ rprev->next = rnext;
+ } else
+ rprev = refs;
+ }
+ }
+
+ glyphs = gcalloc(glyphcnt+1,sizeof(SplineChar *));
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( (sc = sf->glyphs[i])!=NULL ) {
+ if ( sc->orig_pos==-1 )
+ SplineCharFree(sc);
+ else
+ glyphs[sc->orig_pos] = sc;
+ }
+
+ free(sf->glyphs);
+ sf->glyphcnt = sf->glyphmax = glyphcnt;
+ sf->glyphs = glyphs;
+}
+
+/* Convert a normal font to a cid font, rearranging glyphs into cid order */
+void SFEncodeToMap(SplineFont *sf,struct cidmap *map) {
+ SplineChar *sc;
+ int i,max=0, anyextras=0;
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sc = sf->glyphs[i]) ) {
+ sc->orig_pos = NameUni2CID(map,sc->unicodeenc,sc->name);
+ if ( sc->orig_pos>max ) max = sc->orig_pos;
+ else if ( sc->orig_pos==-1 ) ++anyextras;
+ } else if ( sc!=NULL )
+ sc->orig_pos = -1;
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( anyextras ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buttons[3];
+ buttons[0] = _("_Delete");
+ buttons[1] = _("_Add");
+ buttons[2] = NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buttons[] = { GTK_STOCK_DELETE, GTK_STOCK_ADD, NULL };
+#endif
+ if ( gwwv_ask(_("Extraneous glyphs"),(const char **) buttons,0,1,_("The current encoding contains glyphs which I cannot map to CIDs.\nShould I delete them or add them to the end (where they may conflict with future ros definitions)?"))==1 ) {
+ if ( map!=NULL && max<map->cidmax ) max = map->cidmax;
+ anyextras = 0;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sc = sf->glyphs[i]) ) {
+ if ( sc->orig_pos == -1 ) sc->orig_pos = max + anyextras++;
+ }
+ max += anyextras;
+ }
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ SFApplyOrdering(sf, max+1);
+}
+
+#ifndef LUA_FF_LIB
+struct block {
+ int cur, tot;
+ char **maps;
+ char **dirs;
+};
+
+static void AddToBlock(struct block *block,char *mapname, char *dir) {
+ int i, val, j;
+ int len = strlen(mapname);
+
+ if ( mapname[len-7]=='.' ) len -= 7;
+ for ( i=0; i<block->cur; ++i ) {
+ if ( (val=strncmp(block->maps[i],mapname,len))==0 )
+return; /* Duplicate */
+ else if ( val>0 )
+ break;
+ }
+ if ( block->tot==0 ) {
+ block->tot = 10;
+ block->maps = galloc(10*sizeof(char *));
+ block->dirs = galloc(10*sizeof(char *));
+ } else if ( block->cur>=block->tot ) {
+ block->tot += 10;
+ block->maps = grealloc(block->maps,block->tot*sizeof(char *));
+ block->dirs = grealloc(block->dirs,block->tot*sizeof(char *));
+ }
+ for ( j=block->cur; j>=i; --j ) {
+ block->maps[j+1] = block->maps[j];
+ block->dirs[j+1] = block->dirs[j];
+ }
+ block->maps[i] = copyn(mapname,len);
+ block->dirs[i] = dir;
+ ++block->cur;
+}
+
+static void FindMapsInDir(struct block *block,char *dir) {
+ struct dirent *ent;
+ DIR *d;
+ int len;
+ char *pt, *pt2;
+
+ if ( dir==NULL )
+return;
+ /* format of cidmap filename "?*-?*-[0-9]*.cidmap" */
+ d = opendir(dir);
+ if ( d==NULL )
+return;
+ while ( (ent = readdir(d))!=NULL ) {
+ if ( (len = strlen(ent->d_name))<8 )
+ continue;
+ if ( strcmp(ent->d_name+len-7,".cidmap")!=0 )
+ continue;
+ pt = strchr(ent->d_name, '-');
+ if ( pt==NULL || pt==ent->d_name )
+ continue;
+ pt2 = strchr(pt+1, '-' );
+ if ( pt2==NULL || pt2==pt+1 || !isdigit(pt2[1]))
+ continue;
+ AddToBlock(block,ent->d_name,dir);
+ }
+}
+
+static void FindMapsInNoLibsDir(struct block *block,char *dir) {
+
+ if ( dir==NULL || strstr(dir,"/.libs")==NULL )
+return;
+
+ dir = copy(dir);
+ *strstr(dir,"/.libs") = '\0';
+
+ FindMapsInDir(block,dir);
+ free(dir);
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+struct cidmap *AskUserForCIDMap(SplineFont *sf) {
+ struct block block;
+ struct cidmap *map = NULL;
+ char buffer[200];
+ char **choices;
+ int i,ret;
+ char *filename=NULL;
+ char *reg, *ord, *pt;
+ int supplement;
+
+ memset(&block,'\0',sizeof(block));
+ for ( map = cidmaps; map!=NULL; map = map->next ) {
+ sprintf(buffer,"%s-%s-%d", map->registry, map->ordering, map->supplement);
+ AddToBlock(&block,buffer,NULL);
+ }
+ FindMapsInDir(&block,".");
+ FindMapsInDir(&block,GResourceProgramDir);
+ FindMapsInNoLibsDir(&block,GResourceProgramDir);
+#ifdef SHAREDIR
+ FindMapsInDir(&block,SHAREDIR);
+#endif
+ FindMapsInDir(&block,getPfaEditShareDir());
+ FindMapsInDir(&block,"/usr/share/fontforge");
+
+ choices = gcalloc(block.cur+2,sizeof(unichar_t *));
+ choices[0] = copy(_("Browse..."));
+ for ( i=0; i<block.cur; ++i )
+ choices[i+1] = copy(block.maps[i]);
+ ret = gwwv_choose(_("Find a cidmap file..."),(const char **) choices,i+1,0,_("Please select a CID ordering"));
+ for ( i=0; i<=block.cur; ++i )
+ free( choices[i] );
+ free(choices);
+ if ( ret==0 ) {
+ filename = gwwv_open_filename(_("Find a cidmap file..."),NULL,
+ "?*-?*-[0-9]*.cidmap",NULL);
+ if ( filename==NULL )
+ ret = -1;
+ }
+ if ( ret!=-1 ) {
+ if ( filename!=NULL )
+ /* Do nothing for now */;
+ else if ( block.dirs[ret-1]!=NULL ) {
+ filename = galloc(strlen(block.dirs[ret-1])+strlen(block.maps[ret-1])+3+8);
+ strcpy(filename,block.dirs[ret-1]);
+ strcat(filename,"/");
+ strcat(filename,block.maps[ret-1]);
+ strcat(filename,".cidmap");
+ }
+ if ( ret!=0 )
+ reg = block.maps[ret-1];
+ else {
+ reg = strrchr(filename,'/');
+ if ( reg==NULL ) reg = filename;
+ else ++reg;
+ reg = copy(reg);
+ }
+ pt = strchr(reg,'-');
+ if ( pt==NULL )
+ ret = -1;
+ else {
+ *pt = '\0';
+ ord = pt+1;
+ pt = strchr(ord,'-');
+ if ( pt==NULL )
+ ret = -1;
+ else {
+ *pt = '\0';
+ supplement = strtol(pt+1,NULL,10);
+ }
+ }
+ if ( ret == -1 )
+ /* No map */;
+ else if ( filename==NULL )
+ map = FindCidMap(reg,ord,supplement,sf);
+ else
+ map = LoadMapFromFile(filename,reg,ord,supplement);
+ if ( ret!=0 && reg!=block.maps[ret-1] )
+ free(reg);
+ /*free(filename);*/ /* Freed by loadmap */
+ }
+ for ( i=0; i<block.cur; ++i )
+ free( block.maps[i]);
+ free(block.maps);
+ free(block.dirs);
+ if ( map!=NULL ) {
+ sf->cidregistry = copy(map->registry);
+ sf->ordering = copy(map->ordering);
+ sf->supplement = map->supplement;
+ }
+return( map );
+}
+
+static enum fchooserret CMapFilter(GGadget *g,GDirEntry *ent,
+ const unichar_t *dir) {
+ enum fchooserret ret = GFileChooserDefFilter(g,ent,dir);
+ char buf2[256];
+ FILE *file;
+ static char *cmapflag = "%!PS-Adobe-3.0 Resource-CMap";
+
+ if ( ret==fc_show && !ent->isdir ) {
+ int len = 3*(u_strlen(dir)+u_strlen(ent->name)+5);
+ char *filename = galloc(len);
+ u2def_strncpy(filename,dir,len);
+ strcat(filename,"/");
+ u2def_strncpy(buf2,ent->name,sizeof(buf2));
+ strcat(filename,buf2);
+ file = fopen(filename,"r");
+ if ( file==NULL )
+ ret = fc_hide;
+ else {
+ if ( fgets(buf2,sizeof(buf2),file)==NULL ||
+ strncmp(buf2,cmapflag,strlen(cmapflag))!=0 )
+ ret = fc_hide;
+ fclose(file);
+ }
+ free(filename);
+ }
+return( ret );
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+enum cmaptype { cmt_out=-1, cmt_coderange, cmt_notdefs, cmt_cid, cmt_max };
+struct cmap {
+ struct {
+ int n;
+ struct coderange { uint32 first, last, cid; } *ranges;
+ } groups[cmt_max];
+ char *registry;
+ char *ordering;
+ int supplement;
+ struct remap *remap;
+ int total;
+};
+
+static void cmapfree(struct cmap *cmap) {
+ free(cmap->registry);
+ free(cmap->ordering);
+ free(cmap->groups[cmt_coderange].ranges);
+ free(cmap->groups[cmt_notdefs].ranges);
+ free(cmap->groups[cmt_cid].ranges);
+ free(cmap->remap);
+ free(cmap);
+}
+
+static struct coderange *ExtendArray(struct coderange *ranges,int *n, int val) {
+ if ( *n == 0 )
+ ranges = gcalloc(val,sizeof(struct coderange));
+ else {
+ ranges = grealloc(ranges,(*n+val)*sizeof(struct coderange));
+ memset(ranges+*n,0,val*sizeof(struct coderange));
+ }
+ *n += val;
+return( ranges );
+}
+
+static char *readpsstr(char *str) {
+ char *eos;
+
+ while ( Isspace(*str)) ++str;
+ if ( *str=='(' ) ++str;
+ /* Postscript strings can be more complicated than this (hex, nested parens, Enc85...) */
+ /* but none of those should show up here */
+ for ( eos = str; *eos!=')' && *eos!='\0'; ++eos );
+return( copyn(str,eos-str));
+}
+
+static struct cmap *ParseCMap(char *filename) {
+ char buf2[200];
+ FILE *file;
+ struct cmap *cmap;
+ char *end, *pt;
+ int val, pos;
+ enum cmaptype in;
+ static const char *bcsr = "begincodespacerange", *bndr = "beginnotdefrange", *bcr = "begincidrange";
+ static const char *reg = "/Registry", *ord = "/Ordering", *sup="/Supplement";
+
+ pos = 0;
+ file = fopen(filename,"r");
+ if ( file==NULL )
+return( NULL );
+
+ cmap = gcalloc(1,sizeof(struct cmap));
+ in = cmt_out;
+ while ( fgets(buf2,sizeof(buf2),file)!=NULL ) {
+ for ( pt=buf2; Isspace(*pt); ++pt);
+ if ( in==cmt_out ) {
+ if ( *pt=='/' ) {
+ if ( strncmp(pt,reg,strlen(reg))==0 )
+ cmap->registry = readpsstr(pt+strlen(reg));
+ else if ( strncmp(pt,ord,strlen(ord))==0 )
+ cmap->ordering = readpsstr(pt+strlen(ord));
+ else if ( strncmp(pt,ord,strlen(ord))==0 ) {
+ for ( pt += strlen(sup); Isspace(*pt); ++pt );
+ cmap->supplement = strtol(pt,NULL,10);
+ }
+ continue;
+ } else if ( !Isdigit(*pt) )
+ continue;
+ val = strtol(pt,&end,10);
+ while ( Isspace(*end)) ++end;
+ if ( strncmp(end,bcsr,strlen(bcsr))==0 )
+ in = cmt_coderange;
+ else if ( strncmp(end,bndr,strlen(bndr))==0 )
+ in = cmt_notdefs;
+ else if ( strncmp(end,bcr,strlen(bcr))==0 )
+ in = cmt_cid;
+ if ( in!=cmt_out ) {
+ pos = cmap->groups[in].n;
+ cmap->groups[in].ranges = ExtendArray(cmap->groups[in].ranges,&cmap->groups[in].n,val);
+ }
+ } else if ( strncmp(pt,"end",3)== 0 )
+ in = cmt_out;
+ else {
+ if ( *pt!='<' )
+ continue;
+ cmap->groups[in].ranges[pos].first = strtoul(pt+1,&end,16);
+ if ( *end=='>' ) ++end;
+ while ( Isspace(*end)) ++end;
+ if ( *end=='<' ) ++end;
+ cmap->groups[in].ranges[pos].last = strtoul(end,&end,16);
+ if ( in!=cmt_coderange ) {
+ if ( *end=='>' ) ++end;
+ while ( Isspace(*end)) ++end;
+ cmap->groups[in].ranges[pos].cid = strtol(end,&end,10);
+ }
+ ++pos;
+ }
+ }
+ fclose(file);
+return( cmap );
+}
+
+static void CompressCMap(struct cmap *cmap) {
+ int32 i,j,k, pos, base;
+ uint32 min, oldmax;
+ /* we can't really deal with three and four byte encodings */
+ /* so if we get one arrange for the sf itself to do a remap */
+
+ cmap->total = 0x10000;
+ for ( i=0; i<cmap->groups[cmt_coderange].n; ++i )
+ if ( cmap->groups[cmt_coderange].ranges[i].last>0xfffff )
+ break;
+ if ( i==cmap->groups[cmt_coderange].n ) /* No need to remap */
+return;
+
+ cmap->remap = gcalloc(cmap->groups[cmt_coderange].n+1,sizeof(struct remap));
+ base = 0;
+ for ( i=0; i<cmap->groups[cmt_coderange].n; ++i )
+ if ( cmap->groups[cmt_coderange].ranges[i].last<0xffff ) {
+ base = 0x10000;
+ break;
+ }
+
+ pos=0;
+ oldmax = base==0?0:0xffff;
+ for ( i=0; i<cmap->groups[cmt_coderange].n; ++i ) {
+ min = 0xffffffff; k=-1;
+ for ( j=0; j<cmap->groups[cmt_coderange].n; ++j )
+ if ( cmap->groups[cmt_coderange].ranges[j].first>oldmax &&
+ cmap->groups[cmt_coderange].ranges[j].first<min ) {
+ min = cmap->groups[cmt_coderange].ranges[j].first;
+ k = j;
+ }
+ if ( k==-1 )
+ break;
+ cmap->remap[pos].firstenc = cmap->groups[cmt_coderange].ranges[k].first&~0xff;
+ cmap->remap[pos].lastenc = cmap->groups[cmt_coderange].ranges[k].last|0xff;
+ cmap->remap[pos].infont = base;
+ base += cmap->remap[pos].lastenc-cmap->remap[pos].firstenc+1;
+ oldmax = cmap->remap[pos].lastenc;
+ ++pos;
+ }
+ cmap->remap[pos].infont = -1; /* Marks end */
+ cmap->total = base;
+ /* so cmap->remap will map sf indeces into the encoding in the cmap */
+
+ /* And now we want to change the groups[cmt_cid].ranges so that they will */
+ /* map into sf indeces rather than into the encoding of the cmap */
+ for ( i=0; i<cmap->groups[cmt_cid].n; ++i ) {
+ for ( k=0; cmap->remap[k].infont!=-1; ++k )
+ if ( cmap->groups[cmt_cid].ranges[i].first>=cmap->remap[k].firstenc &&
+ cmap->groups[cmt_cid].ranges[i].first<=cmap->remap[k].lastenc )
+ break;
+ if ( cmap->remap[k].infont==-1 )
+ continue;
+ cmap->groups[cmt_cid].ranges[i].first += cmap->remap[k].infont-cmap->remap[k].firstenc;
+ cmap->groups[cmt_cid].ranges[i].last += cmap->remap[k].infont-cmap->remap[k].firstenc;
+ }
+}
+
+SplineFont *CIDFlatten(SplineFont *cidmaster,SplineChar **glyphs,int charcnt) {
+ FontView *fvs;
+ SplineFont *new;
+ char buffer[20];
+ BDFFont *bdf;
+ int j;
+
+ if ( cidmaster==NULL )
+return(NULL);
+ new = SplineFontEmpty();
+ new->fontname = copy(cidmaster->fontname);
+ new->fullname = copy(cidmaster->fullname);
+ new->familyname = copy(cidmaster->familyname);
+ new->weight = copy(cidmaster->weight);
+ new->copyright = copy(cidmaster->copyright);
+ sprintf(buffer,"%g", cidmaster->cidversion);
+ new->version = copy(buffer);
+ new->italicangle = cidmaster->italicangle;
+ new->upos = cidmaster->upos;
+ new->uwidth = cidmaster->uwidth;
+ new->ascent = cidmaster->ascent;
+ new->descent = cidmaster->descent;
+ new->changed = new->changed_since_autosave = true;
+ new->display_antialias = cidmaster->display_antialias;
+ new->hasvmetrics = cidmaster->hasvmetrics;
+ new->fv = cidmaster->fv;
+ /* Don't copy the grid splines, there won't be anything meaningfull at top level */
+ /* and won't know which font to copy from below */
+ new->bitmaps = cidmaster->bitmaps; /* should already be flattened */
+ cidmaster->bitmaps = NULL; /* don't free 'em */
+ for ( bdf=new->bitmaps; bdf!=NULL; bdf=bdf->next )
+ bdf->sf = new;
+ new->gpos_lookups = cidmaster->gpos_lookups;
+ cidmaster->gpos_lookups = NULL;
+ new->gsub_lookups = cidmaster->gsub_lookups;
+ cidmaster->gsub_lookups = NULL;
+ new->kerns = cidmaster->kerns; new->vkerns = cidmaster->vkerns;
+ cidmaster->kerns = cidmaster->vkerns = NULL;
+ new->names = cidmaster->names; cidmaster->names = NULL;
+ new->pfminfo = cidmaster->pfminfo;
+ new->texdata = cidmaster->texdata;
+ new->possub = cidmaster->possub; cidmaster->possub = NULL;
+ new->sm = cidmaster->sm; cidmaster->sm = NULL;
+ new->features = cidmaster->features; cidmaster->features = NULL;
+ new->macstyle = cidmaster->macstyle;
+ new->origname = copy( cidmaster->origname );
+ new->display_size = cidmaster->display_size;
+ /* Don't copy private */
+ new->xuid = copy(cidmaster->xuid);
+ new->glyphs = glyphs;
+ new->glyphcnt = new->glyphmax = charcnt;
+ for ( j=0; j<charcnt; ++j ) if ( glyphs[j]!=NULL ) {
+ glyphs[j]->parent = new;
+ glyphs[j]->orig_pos = j;
+ }
+ for ( fvs=new->fv; fvs!=NULL; fvs=fvs->nextsame ) {
+ fvs->cidmaster = NULL;
+ if ( fvs->sf->glyphcnt!=new->glyphcnt ) {
+ free(fvs->selected);
+ fvs->selected = gcalloc(new->glyphcnt,sizeof(char));
+ if ( fvs->map->encmax < new->glyphcnt )
+ fvs->map->map = grealloc(fvs->map->map,(fvs->map->encmax = new->glyphcnt)*sizeof(int));
+ fvs->map->enccount = new->glyphcnt;
+ if ( fvs->map->backmax < new->glyphcnt )
+ fvs->map->backmap = grealloc(fvs->map->backmap,(fvs->map->backmax = new->glyphcnt)*sizeof(int));
+ for ( j=0; j<new->glyphcnt; ++j )
+ fvs->map->map[j] = fvs->map->backmap[j] = j;
+ }
+ fvs->sf = new;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FVSetTitle(fvs);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FontViewReformatAll(new);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ SplineFontFree(cidmaster);
+return( new );
+}
+
+void SFFlatten(SplineFont *cidmaster) {
+ SplineChar **glyphs;
+ int i,j,max;
+
+ if ( cidmaster==NULL )
+return;
+ if ( cidmaster->cidmaster!=NULL )
+ cidmaster = cidmaster->cidmaster;
+ /* This doesn't change the ordering, so no need for special tricks to */
+ /* preserve scrolling location. */
+ for ( i=max=0; i<cidmaster->subfontcnt; ++i ) {
+ if ( max<cidmaster->subfonts[i]->glyphcnt )
+ max = cidmaster->subfonts[i]->glyphcnt;
+ }
+ glyphs = gcalloc(max,sizeof(SplineChar *));
+ for ( j=0; j<max; ++j ) {
+ for ( i=0; i<cidmaster->subfontcnt; ++i ) {
+ if ( j<cidmaster->subfonts[i]->glyphcnt && cidmaster->subfonts[i]->glyphs[j]!=NULL ) {
+ glyphs[j] = cidmaster->subfonts[i]->glyphs[j];
+ cidmaster->subfonts[i]->glyphs[j] = NULL;
+ break;
+ }
+ }
+ }
+ CIDFlatten(cidmaster,glyphs,max);
+}
+
+int SFFlattenByCMap(SplineFont *sf,char *cmapname) {
+ struct cmap *cmap;
+ int i,j,k,l,m, extras, max, curmax, warned;
+ int found[4];
+ SplineChar **glyphs = NULL, *sc;
+ FontView *fvs;
+
+ if ( sf->cidmaster!=NULL )
+ sf = sf->cidmaster;
+ if ( sf->subfontcnt==0 ) {
+ gwwv_post_error(_("Not a CID-keyed font"),_("Not a CID-keyed font"));
+return( false );
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( cmapname==NULL ) {
+ cmapname = gwwv_open_filename(_("Find an adobe CMap file..."),NULL,NULL,CMapFilter);
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ if ( cmapname==NULL )
+return( false );
+ cmap = ParseCMap(cmapname);
+ if ( cmap==NULL )
+return( false );
+ CompressCMap(cmap);
+ max = 0;
+ for ( i=0; i<cmap->groups[cmt_cid].n; ++i ) {
+ if ( max<cmap->groups[cmt_cid].ranges[i].last )
+ max = cmap->groups[cmt_cid].ranges[i].last;
+ if ( cmap->groups[cmt_cid].ranges[i].last>0x100000 ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ gwwv_post_error(_("Encoding Too Large"),_("Encoding Too Large"));
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("Encoding Too Large"),_("Encoding Too Large"));
+#endif
+ cmapfree(cmap);
+return( false );
+ }
+ }
+
+ SFFindNearTop(sf);
+ curmax = 0;
+ for ( k=0; k<sf->subfontcnt; ++k ) {
+ if ( curmax < sf->subfonts[k]->glyphcnt )
+ curmax = sf->subfonts[k]->glyphcnt;
+ }
+
+ glyphs = gcalloc(curmax,sizeof(SplineChar *));
+ for ( i=0; i<curmax; ++i ) {
+ for ( k=0; k<sf->subfontcnt; ++k )
+ if ( i<sf->subfonts[k]->glyphcnt && sf->subfonts[k]->glyphs[i]!=NULL ) {
+ glyphs[i] = sf->subfonts[k]->glyphs[i];
+ sf->subfonts[k]->glyphs[i] = NULL;
+ break;
+ }
+ }
+ sf = CIDFlatten(sf,glyphs,curmax);
+
+ warned = true;
+ for ( fvs=sf->fv; fvs!=NULL; fvs=fvs->nextsame ) {
+ EncMap *map = fvs->map;
+ for ( j=0; j<2; ++j ) {
+ extras = 0;
+ for ( i=0; i<curmax; ++i ) {
+ sc = glyphs[i];
+ if ( sc!=NULL ) {
+ m = 0;
+ for ( l=0; l<cmap->groups[cmt_cid].n; ++l ) {
+ if ( i>=cmap->groups[cmt_cid].ranges[l].cid &&
+ i<=cmap->groups[cmt_cid].ranges[l].cid +
+ cmap->groups[cmt_cid].ranges[l].last -
+ cmap->groups[cmt_cid].ranges[l].first ) {
+ if ( m<sizeof(found)/sizeof(found[0]) )
+ found[m++] = l;
+ else if ( !warned ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ ff_post_notice(_("MultipleEncodingIgnored"),
+ _("The glyph at CID %d is mapped to more than %d encodings. Only the first %d are handled."), i,
+ sizeof(found)/sizeof(found[0]),
+ sizeof(found)/sizeof(found[0]));
+#elif defined(FONTFORGE_CONFIG_GTK)
+ ff_post_notice(_("MultipleEncodingIgnored"),
+ _("The glyph at CID %d is mapped to more than %d encodings. Only the first %d are handled."), i,
+ sizeof(found)/sizeof(found[0]),
+ sizeof(found)/sizeof(found[0]));
+#endif
+ warned = true;
+ }
+ }
+ }
+ if ( m==0 ) {
+ if ( j ) {
+ map->map[max+extras] = sc->orig_pos;
+ map->backmap[sc->orig_pos] = max+extras;
+ }
+ ++extras;
+ } else {
+ if ( j ) {
+ int p = cmap->groups[cmt_cid].ranges[found[0]].first +
+ i-cmap->groups[cmt_cid].ranges[found[0]].cid;
+ map->map[p] = sc->orig_pos;
+ map->backmap[sc->orig_pos] = p;
+ for ( l=1; l<m; ++l ) {
+ int pos = cmap->groups[cmt_cid].ranges[found[l]].first +
+ i-cmap->groups[cmt_cid].ranges[found[l]].cid;
+ map->map[pos] = sc->orig_pos;
+ }
+ }
+ }
+ }
+ }
+ if ( !j ) {
+ map->map = grealloc(map->map,(map->encmax = map->enccount = max+extras)*sizeof(int));
+ memset(map->map,-1,map->enccount*sizeof(int));
+ memset(map->backmap,-1,sf->glyphcnt*sizeof(int));
+ map->remap = cmap->remap; cmap->remap = NULL;
+ }
+ warned = true;
+ }
+ }
+ cmapfree(cmap);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FontViewReformatAll(sf);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ SFRestoreNearTop(sf);
+return( true );
+}
+
+static int Enc2CMap(struct cmap *cmap,int enc) {
+ int i;
+
+ for ( i=0; i<cmap->groups[cmt_cid].n; ++i )
+ if ( enc>=cmap->groups[cmt_cid].ranges[i].first &&
+ enc<=cmap->groups[cmt_cid].ranges[i].last )
+return( enc-cmap->groups[cmt_cid].ranges[i].first+
+ cmap->groups[cmt_cid].ranges[i].cid );
+
+return( -1 );
+}
+
+static void SFEncodeToCMap(SplineFont *cidmaster,SplineFont *sf,EncMap *oldmap, struct cmap *cmap) {
+ SplineChar *sc;
+ int i,max=0, anyextras=0;
+
+ cidmaster->cidregistry = cmap->registry; cmap->registry = NULL;
+ cidmaster->ordering = cmap->ordering; cmap->ordering = NULL;
+ cidmaster->supplement = cmap->supplement;
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( (sc = sf->glyphs[i])!=NULL ) {
+ if ( strcmp(sc->name,".notdef")==0 )
+ sc->orig_pos = 0;
+ else if ( oldmap->backmap[i]==-1 )
+ sc->orig_pos = -1;
+ else {
+ sc->orig_pos = Enc2CMap(cmap,oldmap->backmap[i]);
+ if ( sc->orig_pos==0 ) sc->orig_pos = -1;
+ }
+ if ( sc->orig_pos>max ) max = sc->orig_pos;
+ else if ( sc->orig_pos==-1 ) ++anyextras;
+ }
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( anyextras ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buttons[3];
+ buttons[0] = _("_Delete");
+ buttons[1] = _("_Add");
+ buttons[2] = NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buttons[] = { GTK_STOCK_DELETE, GTK_STOCK_ADD, NULL };
+#endif
+ if ( gwwv_ask(_("Extraneous glyphs"),(const char **) buttons,0,1,_("The current encoding contains glyphs which I cannot map to CIDs.\nShould I delete them or add them to the end (where they may conflict with future ros definitions)?"))==1 ) {
+ if ( cmap!=NULL && max<cmap->total ) max = cmap->total;
+ anyextras = 0;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( (sc = sf->glyphs[i])!=NULL ) {
+ if ( sc->orig_pos == -1 ) sc->orig_pos = max + anyextras++;
+ }
+ max += anyextras;
+ }
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ SFApplyOrdering(sf, max);
+}
+
+SplineFont *MakeCIDMaster(SplineFont *sf,EncMap *oldmap,int bycmap,char *cmapfilename, struct cidmap *cidmap) {
+ SplineFont *cidmaster;
+ struct cidmap *map;
+ struct cmap *cmap;
+ FontView *fvs;
+ int freeme;
+
+ cidmaster = SplineFontEmpty();
+ SFFindNearTop(sf);
+ if ( bycmap ) {
+ freeme = false;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( cmapfilename==NULL ) {
+ cmapfilename = gwwv_open_filename(_("Find an adobe CMap file..."),NULL,NULL,CMapFilter);
+ freeme = true;
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ if ( cmapfilename==NULL ) {
+ SplineFontFree(cidmaster);
+return(NULL);
+ }
+ cmap = ParseCMap(cmapfilename);
+ if ( freeme )
+ free(cmapfilename);
+ if ( cmap==NULL ) {
+ SplineFontFree(cidmaster);
+return(NULL);
+ }
+ CompressCMap(cmap);
+ SFEncodeToCMap(cidmaster,sf,oldmap,cmap);
+ cmapfree(cmap);
+ } else {
+ map = cidmap;
+ if (map == NULL) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ map = AskUserForCIDMap(cidmaster); /* Sets the ROS fields */
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ } else {
+ cidmaster->cidregistry = copy(map->registry);
+ cidmaster->ordering = copy(map->ordering);
+ cidmaster->supplement = map->supplement;
+ }
+ if ( map==NULL ) {
+ SplineFontFree(cidmaster);
+return(NULL);
+ }
+ SFEncodeToMap(sf,map);
+ }
+ if ( sf->uni_interp!=ui_none && sf->uni_interp!=ui_unset )
+ cidmaster->uni_interp = sf->uni_interp;
+ else if ( strstrmatch(cidmaster->ordering,"japan")!=NULL )
+ cidmaster->uni_interp = ui_japanese;
+ else if ( strstrmatch(cidmaster->ordering,"CNS")!=NULL )
+ cidmaster->uni_interp = ui_trad_chinese;
+ else if ( strstrmatch(cidmaster->ordering,"GB")!=NULL )
+ cidmaster->uni_interp = ui_simp_chinese;
+ else if ( strstrmatch(cidmaster->ordering,"Korea")!=NULL )
+ cidmaster->uni_interp = ui_korean;
+ sf->uni_interp = cidmaster->uni_interp;
+ cidmaster->fontname = copy(sf->fontname);
+ cidmaster->fullname = copy(sf->fullname);
+ cidmaster->familyname = copy(sf->familyname);
+ cidmaster->weight = copy(sf->weight);
+ cidmaster->copyright = copy(sf->copyright);
+ cidmaster->cidversion = 1.0;
+ cidmaster->display_antialias = sf->display_antialias;
+ cidmaster->display_size = sf->display_size;
+ cidmaster->ascent = sf->ascent /*880*/;
+ cidmaster->descent = sf->descent /*120*/;
+ cidmaster->changed = cidmaster->changed_since_autosave = true;
+ for ( fvs=sf->fv; fvs!=NULL; fvs=fvs->nextsame )
+ fvs->cidmaster = cidmaster;
+ cidmaster->fv = sf->fv;
+ sf->cidmaster = cidmaster;
+ cidmaster->subfontcnt = 1;
+ cidmaster->subfonts = gcalloc(2,sizeof(SplineFont *));
+ cidmaster->subfonts[0] = sf;
+ cidmaster->gpos_lookups = sf->gpos_lookups; sf->gpos_lookups = NULL;
+ cidmaster->gsub_lookups = sf->gsub_lookups; sf->gsub_lookups = NULL;
+ cidmaster->possub = sf->possub; sf->possub = NULL;
+ cidmaster->kerns = sf->kerns; sf->kerns = NULL;
+ cidmaster->vkerns = sf->vkerns; sf->vkerns = NULL;
+ if ( sf->private==NULL )
+ sf->private = gcalloc(1,sizeof(struct psdict));
+ if ( !PSDictHasEntry(sf->private,"lenIV"))
+ PSDictChangeEntry(sf->private,"lenIV","1"); /* It's 4 by default, in CIDs the convention seems to be 1 */
+ for ( fvs=sf->fv; fvs!=NULL; fvs=fvs->nextsame ) {
+ free(fvs->selected);
+ fvs->selected = gcalloc(fvs->sf->glyphcnt,sizeof(char));
+ EncMapFree(fvs->map);
+ fvs->map = EncMap1to1(fvs->sf->glyphcnt);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FVSetTitle(fvs);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+ SFRestoreNearTop(sf);
+ CIDMasterAsDes(sf);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FontViewReformatAll(sf);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+return( cidmaster );
+}
+
+int CountOfEncoding(Encoding *encoding_name) {
+return( encoding_name->char_cnt );
+}
+
+char *SFEncodingName(SplineFont *sf,EncMap *map) {
+ char buffer[130];
+
+ if ( sf->cidmaster!=NULL )
+ sf = sf->cidmaster;
+ if ( sf->subfontcnt!=0 ) {
+ sprintf( buffer, "%.50s-%.50s-%d", sf->cidregistry, sf->ordering, sf->supplement );
+return( copy( buffer ));
+ }
+return( copy( map->enc->enc_name ));
+}
+
+/* ************************** Reencoding routines ************************** */
+
+static void BDFOrigFixup(BDFFont *bdf,int orig_cnt,SplineFont *sf) {
+ BDFChar **glyphs = gcalloc(orig_cnt,sizeof(BDFChar *));
+ int i;
+
+ for ( i=0; i<bdf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ glyphs[sf->glyphs[i]->orig_pos] = bdf->glyphs[i];
+ if ( bdf->glyphs[i]!=NULL ) /* Not all glyphs exist in a piecemeal font */
+ bdf->glyphs[i]->orig_pos = sf->glyphs[i]->orig_pos;
+ }
+ free(bdf->glyphs);
+ bdf->glyphs = glyphs;
+ bdf->glyphcnt = bdf->glyphmax = orig_cnt;
+ bdf->ticked = true;
+}
+
+static int _SFForceEncoding(SplineFont *sf,EncMap *old, Encoding *new_enc) {
+ int enc_cnt,i;
+ BDFFont *bdf;
+ FontView *fvs;
+
+ /* Normally we base our encoding process on unicode code points. */
+ /* but encodings like AdobeStandard are more interested in names than */
+ /* code points. It is perfectly possible to have a font properly */
+ /* encoded by code point which is not properly encoded by name */
+ /* (might have f_i where it should have fi). So even if it's got */
+ /* the right encoding, we still may want to force the names */
+ if ( new_enc->is_custom )
+return(false); /* Custom, it's whatever's there */
+
+ if ( new_enc->is_original ) {
+ SplineChar **glyphs;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ sf->glyphs[i]->orig_pos = -1;
+ for ( i=enc_cnt=0; i<old->enccount; ++i )
+ if ( old->map[i]!=-1 && sf->glyphs[old->map[i]]!=NULL &&
+ sf->glyphs[old->map[i]]->orig_pos == -1 )
+ sf->glyphs[old->map[i]]->orig_pos = enc_cnt++;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ if ( sf->glyphs[i]->orig_pos==-1 )
+ sf->glyphs[i]->orig_pos = enc_cnt++;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ struct splinecharlist *scl;
+ int layer;
+ RefChar *ref;
+
+ for ( scl=sf->glyphs[i]->dependents; scl!=NULL; scl=scl->next ) {
+ for ( layer=ly_fore; layer<scl->sc->layer_cnt; ++layer )
+ for ( ref = scl->sc->layers[layer].refs; ref!=NULL; ref=ref->next )
+ ref->orig_pos = ref->sc->orig_pos;
+ }
+ }
+ for ( fvs=sf->fv; fvs!=NULL; fvs=fvs->nextsame ) {
+ fvs->map->ticked = false;
+ if ( fvs->filled!=NULL ) fvs->filled->ticked = false;
+ }
+ for ( fvs=sf->fv; fvs!=NULL; fvs=fvs->nextsame ) if ( !fvs->map->ticked ) {
+ EncMap *map = fvs->map;
+ for ( i=0; i<map->enccount; ++i ) if ( map->map[i]!=-1 )
+ map->map[i] = sf->glyphs[map->map[i]]->orig_pos;
+ if ( enc_cnt>map->backmax ) {
+ free(map->backmap);
+ map->backmax = enc_cnt;
+ map->backmap = galloc(enc_cnt*sizeof(int));
+ }
+ memset(map->backmap,-1,enc_cnt*sizeof(int));
+ for ( i=0; i<map->enccount; ++i ) if ( map->map[i]!=-1 )
+ if ( map->backmap[map->map[i]]==-1 )
+ map->backmap[map->map[i]] = i;
+ map->ticked = true;
+ }
+ if ( !old->ticked )
+ IError( "Unticked encmap" );
+ for ( bdf=sf->bitmaps; bdf!=NULL; bdf=bdf->next )
+ BDFOrigFixup(bdf,enc_cnt,sf);
+ for ( fvs=sf->fv; fvs!=NULL ; fvs=fvs->nextsame ) {
+ if ( fvs->filled!=NULL && !fvs->filled->ticked )
+ BDFOrigFixup(sf->fv->filled,enc_cnt,sf);
+ }
+ glyphs = gcalloc(enc_cnt,sizeof(SplineChar *));
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ glyphs[sf->glyphs[i]->orig_pos] = sf->glyphs[i];
+ free(sf->glyphs);
+ sf->glyphs = glyphs;
+ sf->glyphcnt = sf->glyphmax = enc_cnt;
+return( true );
+ }
+
+ enc_cnt = new_enc->char_cnt;
+
+ if ( old->enccount<enc_cnt ) {
+ if ( old->encmax<enc_cnt ) {
+ old->map = grealloc(old->map,enc_cnt*sizeof(int));
+ old->encmax = enc_cnt;
+ }
+ memset(old->map+old->enccount,-1,(enc_cnt-old->enccount)*sizeof(int));
+ old->enccount = enc_cnt;
+ }
+ old->enc = new_enc;
+ for ( i=0; i<old->enccount && i<enc_cnt; ++i ) if ( old->map[i]!=-1 && sf->glyphs[old->map[i]]!=NULL ) {
+ SplineChar dummy;
+ int j = old->map[i];
+ SCBuildDummy(&dummy,sf,old,i);
+ sf->glyphs[j]->unicodeenc = dummy.unicodeenc;
+ free(sf->glyphs[j]->name);
+ sf->glyphs[j]->name = copy(dummy.name);
+ }
+ /* We just changed the unicode values for most glyphs */
+ /* but any references to them will have the old values, and that's bad, so fix 'em up */
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ struct splinecharlist *scl;
+ int layer;
+ RefChar *ref;
+
+ for ( scl=sf->glyphs[i]->dependents; scl!=NULL; scl=scl->next ) {
+ for ( layer=ly_fore; layer<scl->sc->layer_cnt; ++layer )
+ for ( ref = scl->sc->layers[layer].refs; ref!=NULL; ref=ref->next )
+ ref->unicode_enc = ref->sc->unicodeenc;
+ }
+ }
+return( true );
+}
+
+int SFForceEncoding(SplineFont *sf,EncMap *old, Encoding *new_enc) {
+ if ( sf->mm!=NULL ) {
+ MMSet *mm = sf->mm;
+ int i;
+ for ( i=0; i<mm->instance_count; ++i )
+ _SFForceEncoding(mm->instances[i],old,new_enc);
+ _SFForceEncoding(mm->normal,old,new_enc);
+ } else
+return( _SFForceEncoding(sf,old,new_enc));
+
+return( true );
+}
+
+EncMap *EncMapFromEncoding(SplineFont *sf,Encoding *enc) {
+ int i,j, extras, found, base, unmax;
+ int *encoded, *unencoded;
+ EncMap *map;
+ struct altuni *altuni;
+ SplineChar *sc;
+
+ if ( enc==NULL )
+return( NULL );
+
+ base = enc->char_cnt;
+ if ( enc->is_original )
+ base = 0;
+ else if ( enc->char_cnt<=256 )
+ base = 256;
+ else if ( enc->char_cnt<=0x10000 )
+ base = 0x10000;
+ encoded = galloc(base*sizeof(int));
+ memset(encoded,-1,base*sizeof(int));
+ unencoded = galloc(sf->glyphcnt*sizeof(int));
+ unmax = sf->glyphcnt;
+
+ for ( i=extras=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL ) {
+ found = false;
+ if ( enc->psnames!=NULL ) {
+ for ( j=enc->char_cnt-1; j>=0; --j ) {
+ if ( enc->psnames[j]!=NULL &&
+ strcmp(enc->psnames[j],sc->name)==0 ) {
+ found = true;
+ encoded[j] = i;
+ }
+ }
+ }
+ if ( !found ) {
+ if ( sc->unicodeenc!=-1 &&
+ sc->unicodeenc<unicode4_size &&
+ (j = EncFromUni(sc->unicodeenc,enc))!= -1 )
+ encoded[j] = i;
+ else {
+ /* I don't think extras can surpass unmax now, but it doesn't */
+ /* hurt to leave the code (it's from when we encoded duplicates see below) */
+ if ( extras>=unmax ) unencoded = grealloc(unencoded,(unmax+=300)*sizeof(int));
+ unencoded[extras++] = i;
+ }
+ for ( altuni=sc->altuni; altuni!=NULL; altuni=altuni->next ) {
+ if ( altuni->unienc!=-1 &&
+ altuni->unienc<unicode4_size &&
+ (j = EncFromUni(altuni->unienc,enc))!= -1 )
+ encoded[j] = i;
+ /* I used to have code here to add these unencoded duplicates */
+ /* but I don't really see any reason to do so. The main unicode */
+ /* will occur, and any encoded duplicates so the glyph won't */
+ /* vanish */
+ }
+ }
+ }
+
+ /* Some glyphs have both a pua encoding and an encoding in a non-bmp */
+ /* plane. Big5HK does and the AMS glyphs do */
+ if ( enc->is_unicodefull && (sf->uni_interp == ui_trad_chinese ||
+ sf->uni_interp == ui_ams )) {
+ extern const int cns14pua[], amspua[];
+ const int *pua = sf->uni_interp == ui_ams? amspua : cns14pua;
+ for ( i=0xe000; i<0xf8ff; ++i ) {
+ if ( pua[i-0xe000]!=0 )
+ encoded[pua[i-0xe000]] = encoded[i];
+ }
+ }
+
+ if ( enc->psnames != NULL ) {
+ /* Names are more important than unicode code points for some encodings */
+ /* AdobeStandard for instance which won't work if you have a glyph */
+ /* named "f_i" (must be "fi") even though the code point is correct */
+ /* The code above would match f_i where AS requires fi, so force the */
+ /* names to be correct. */
+ for ( j=0; j<enc->char_cnt; ++j ) {
+ if ( encoded[j]!=-1 && enc->psnames[j]!=NULL &&
+ strcmp(sf->glyphs[encoded[j]]->name,enc->psnames[j])!=0 ) {
+ free(sf->glyphs[encoded[j]]->name);
+ sf->glyphs[encoded[j]]->name = copy(enc->psnames[j]);
+ }
+ }
+ }
+
+ map = chunkalloc(sizeof(EncMap));
+ map->enccount = map->encmax = base + extras;
+ map->map = galloc(map->enccount*sizeof(int));
+ memcpy(map->map,encoded,base*sizeof(int));
+ memcpy(map->map+base,unencoded,extras*sizeof(int));
+ map->backmax = sf->glyphcnt;
+ map->backmap = galloc(sf->glyphcnt*sizeof(int));
+ memset(map->backmap,-1,sf->glyphcnt*sizeof(int)); /* Just in case there are some unencoded glyphs (duplicates perhaps) */
+ for ( i = map->enccount-1; i>=0; --i ) if ( map->map[i]!=-1 )
+ map->backmap[map->map[i]] = i;
+ map->enc = enc;
+
+ free(encoded);
+ free(unencoded);
+
+return( map );
+}
+
+EncMap *CompactEncMap(EncMap *map, SplineFont *sf) {
+ int i, inuse, gid;
+ int32 *newmap;
+
+ for ( i=inuse=0; i<map->enccount ; ++i )
+ if ( (gid = map->map[i])!=-1 && SCWorthOutputting(sf->glyphs[gid]))
+ ++inuse;
+ newmap = galloc(inuse*sizeof(int32));
+ for ( i=inuse=0; i<map->enccount ; ++i )
+ if ( (gid = map->map[i])!=-1 && SCWorthOutputting(sf->glyphs[gid]))
+ newmap[inuse++] = gid;
+ free(map->map);
+ map->map = newmap;
+ map->enccount = inuse;
+ map->encmax = inuse;
+ map->enc = &custom;
+ memset(map->backmap,-1,sf->glyphcnt*sizeof(int));
+ for ( i=inuse-1; i>=0; --i )
+ if ( (gid=map->map[i])!=-1 )
+ map->backmap[gid] = i;
+return( map );
+}
+
+void SFRemoveGlyph(SplineFont *sf,SplineChar *sc, int *flags) {
+ struct splinecharlist *dep, *dnext;
+ BDFFont *bdf;
+ BDFChar *bfc;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ CharView *cv, *next;
+ BitmapView *bv, *bvnext;
+ FontView *fvs;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ RefChar *refs, *rnext;
+ KernPair *kp, *kprev;
+ int i;
+
+ if ( sc==NULL )
+return;
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ /* Close any open windows */
+ if ( sc->views ) {
+ for ( cv = sc->views; cv!=NULL; cv=next ) {
+ next = cv->next;
+ GDrawDestroyWindow(cv->gw);
+ }
+ GDrawSync(NULL);
+ GDrawProcessPendingEvents(NULL);
+ GDrawSync(NULL);
+ GDrawProcessPendingEvents(NULL);
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+ for ( bdf=sf->bitmaps; bdf!=NULL; bdf = bdf->next ) {
+ if ( sc->orig_pos<bdf->glyphcnt && (bfc = bdf->glyphs[sc->orig_pos])!= NULL ) {
+ bdf->glyphs[sc->orig_pos] = NULL;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( bfc->views!=NULL ) {
+ for ( bv= bfc->views; bv!=NULL; bv=bvnext ) {
+ bvnext = bv->next;
+ GDrawDestroyWindow(bv->gw);
+ }
+ GDrawSync(NULL);
+ GDrawProcessPendingEvents(NULL);
+ GDrawSync(NULL);
+ GDrawProcessPendingEvents(NULL);
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ BDFCharFree(bfc);
+ }
+ }
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ /* Turn any searcher references to this glyph into inline copies of it */
+ for ( fvs=sc->parent->fv; fvs!=NULL; fvs=fvs->nextsame ) {
+ if ( fvs->sv!=NULL ) {
+ RefChar *rf, *rnext;
+ for ( rf = fvs->sv->sc_srch.layers[ly_fore].refs; rf!=NULL; rf=rnext ) {
+ rnext = rf->next;
+ if ( rf->sc==sc )
+ SCRefToSplines(&fvs->sv->sc_srch,rf);
+ }
+ for ( rf = fvs->sv->sc_rpl.layers[ly_fore].refs; rf!=NULL; rf=rnext ) {
+ rnext = rf->next;
+ if ( rf->sc==sc )
+ SCRefToSplines(&fvs->sv->sc_rpl,rf);
+ }
+ }
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+ /* Turn any references to this glyph into inline copies of it */
+ for ( dep=sc->dependents; dep!=NULL; dep=dnext ) {
+ SplineChar *dsc = dep->sc;
+ RefChar *rf, *rnext;
+ dnext = dep->next;
+ /* May be more than one reference to us, colon has two refs to period */
+ /* but only one dlist entry */
+ for ( rf = dsc->layers[ly_fore].refs; rf!=NULL; rf=rnext ) {
+ rnext = rf->next;
+ if ( rf->sc==sc )
+ SCRefToSplines(dsc,rf);
+ }
+ }
+
+ for ( refs=sc->layers[ly_fore].refs; refs!=NULL; refs = rnext ) {
+ rnext = refs->next;
+ SCRemoveDependent(sc,refs);
+ }
+
+ /* Remove any kerning pairs that look at this character */
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ for ( kprev=NULL, kp=sf->glyphs[i]->kerns; kp!=NULL; kprev = kp, kp=kp->next ) {
+ if ( kp->sc==sc ) {
+ if ( kprev==NULL )
+ sf->glyphs[i]->kerns = kp->next;
+ else
+ kprev->next = kp->next;
+ kp->next = NULL;
+ KernPairsFree(kp);
+ break;
+ }
+ }
+ }
+
+ sf->glyphs[sc->orig_pos] = NULL;
+ SplineCharFree(sc);
+}
+
+void FVAddEncodingSlot(FontView *fv,int gid) {
+ EncMap *map = fv->map;
+ int enc;
+
+ if ( map->enccount>=map->encmax )
+ map->map = grealloc(map->map,(map->encmax+=10)*sizeof(int));
+ enc = map->enccount++;
+ map->map[enc] = gid;
+ map->backmap[gid] = enc;
+
+ fv->selected = grealloc(fv->selected,map->enccount);
+ fv->selected[enc] = 0;
+ if ( fv->colcnt!=0 ) { /* Ie. scripting vs. UI */
+ fv->rowltot = (enc+1+fv->colcnt-1)/fv->colcnt;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ GScrollBarSetBounds(fv->vsb,0,fv->rowltot,fv->rowcnt);
+#endif
+ }
+}
+
+void SFAddEncodingSlot(SplineFont *sf,int gid) {
+ FontView *fv;
+ for ( fv=sf->fv; fv!=NULL; fv = fv->nextsame )
+ FVAddEncodingSlot(fv,gid);
+}
+
+static int MapAddEnc(SplineFont *sf,SplineChar *sc,EncMap *basemap, EncMap *map,int baseenc, int gid, FontView *fv) {
+ int any = false, enc;
+
+ if ( gid>=map->backmax ) {
+ map->backmap = grealloc(map->backmap,(map->backmax+=10)*sizeof(int));
+ memset(map->backmap+map->backmax-10,-1,10*sizeof(int));
+ }
+ if ( map->enc->psnames!=NULL ) {
+ /* Check for multiple encodings */
+ for ( enc = map->enc->char_cnt-1; enc>=0; --enc ) {
+ if ( map->enc->psnames[enc]!=NULL && strcmp(sc->name,map->enc->psnames[enc])==0 ) {
+ if ( !any ) {
+ map->backmap[gid] = enc;
+ any = true;
+ }
+ map->map[enc] = gid;
+ }
+ }
+ } else {
+ enc = SFFindSlot(sf,map,sc->unicodeenc,sc->name);
+ if ( enc!=-1 ) {
+ map->map[enc] = gid;
+ map->backmap[gid] = enc;
+ any = true;
+ }
+ }
+ if ( basemap!=NULL && map->enc==basemap->enc && baseenc!=-1 ) {
+ if ( baseenc>=map->enccount )
+ FVAddEncodingSlot(fv,gid);
+ else {
+ map->map[baseenc] = gid;
+ if ( map->backmap[gid]==-1 )
+ map->backmap[gid] = baseenc;
+ }
+ any = true;
+ }
+return( any );
+}
+
+void SFAddGlyphAndEncode(SplineFont *sf,SplineChar *sc,EncMap *basemap, int baseenc) {
+ int gid, mapfound = false;
+ FontView *fv;
+ BDFFont *bdf;
+
+ if ( sf->cidmaster==NULL ) {
+ if ( sf->glyphcnt+1>=sf->glyphmax )
+ sf->glyphs = grealloc(sf->glyphs,(sf->glyphmax+=10)*sizeof(SplineChar *));
+ gid = sf->glyphcnt++;
+ for ( bdf = sf->bitmaps; bdf!=NULL; bdf=bdf->next ) {
+ if ( sf->glyphcnt+1>=bdf->glyphmax )
+ bdf->glyphs = grealloc(bdf->glyphs,(bdf->glyphmax=sf->glyphmax)*sizeof(BDFChar *));
+ if ( sf->glyphcnt>bdf->glyphcnt ) {
+ memset(bdf->glyphs+bdf->glyphcnt,0,(sf->glyphcnt-bdf->glyphcnt)*sizeof(BDFChar *));
+ bdf->glyphcnt = sf->glyphcnt;
+ }
+ }
+ for ( fv=sf->fv; fv!=NULL; fv = fv->nextsame ) {
+ EncMap *map = fv->map;
+ if ( gid>=map->backmax )
+ map->backmap = grealloc(map->backmap,(map->backmax=gid+10)*sizeof(int));
+ map->backmap[gid] = -1;
+ }
+ } else {
+ gid = baseenc;
+ if ( baseenc+1>=sf->glyphmax )
+ sf->glyphs = grealloc(sf->glyphs,(sf->glyphmax = baseenc+10)*sizeof(SplineChar *));
+ if ( baseenc>=sf->glyphcnt ) {
+ memset(sf->glyphs+sf->glyphcnt,0,(baseenc+1-sf->glyphcnt)*sizeof(SplineChar *));
+ sf->glyphcnt = baseenc+1;
+ for ( bdf = sf->cidmaster->bitmaps; bdf!=NULL; bdf=bdf->next ) {
+ if ( baseenc+1>=bdf->glyphmax )
+ bdf->glyphs = grealloc(bdf->glyphs,(bdf->glyphmax=baseenc+10)*sizeof(BDFChar *));
+ if ( baseenc+1>bdf->glyphcnt ) {
+ memset(bdf->glyphs+bdf->glyphcnt,0,(baseenc+1-bdf->glyphcnt)*sizeof(BDFChar *));
+ bdf->glyphcnt = baseenc+1;
+ }
+ }
+ for ( fv=sf->fv; fv!=NULL; fv = fv->nextsame ) if ( fv->sf==sf ) {
+ EncMap *map = fv->map;
+ if ( gid>=map->backmax )
+ map->backmap = grealloc(map->backmap,(map->backmax=gid+10)*sizeof(int));
+ map->backmap[gid] = -1;
+ }
+ }
+ }
+ sf->glyphs[gid] = NULL;
+ for ( fv=sf->fv; fv!=NULL; fv = fv->nextsame ) {
+ EncMap *map = fv->map;
+ BDFFont *bdf = fv->filled;
+
+ if ( bdf!=NULL ) {
+ if ( gid>=bdf->glyphmax )
+ bdf->glyphs = grealloc(bdf->glyphs,sf->glyphmax*sizeof(BDFChar *));
+ if ( gid>=bdf->glyphcnt ) {
+ memset(bdf->glyphs+bdf->glyphcnt,0,(gid+1-bdf->glyphcnt)*sizeof(BDFChar *));
+ bdf->glyphcnt = gid+1;
+ }
+ }
+ if ( !MapAddEnc(sf,sc,basemap,map,baseenc,gid,fv) )
+ FVAddEncodingSlot(fv,gid);
+ if ( map==basemap ) mapfound = true;
+ }
+ if ( !mapfound && basemap!=NULL )
+ MapAddEnc(sf,sc,basemap,basemap,baseenc,gid,fv);
+ sf->glyphs[gid] = sc;
+ sc->orig_pos = gid;
+ sc->parent = sf;
+ SFHashGlyph(sf,sc);
+}
+
+static SplineChar *SplineCharMatch(SplineFont *parent,SplineChar *sc) {
+ SplineChar *scnew = SplineCharCreate();
+
+ scnew->parent = parent;
+ scnew->orig_pos = sc->orig_pos;
+ scnew->name = copy(sc->name);
+ scnew->unicodeenc = sc->unicodeenc;
+ scnew->width = sc->width;
+ scnew->vwidth = sc->vwidth;
+ scnew->widthset = true;
+return( scnew );
+}
+
+void SFMatchGlyphs(SplineFont *sf,SplineFont *target,int addempties) {
+ /* reorder sf so that its glyphs array is the same as that in target */
+ int i, j, cnt, cnt2;
+ SplineChar **glyphs;
+ BDFFont *bdf;
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ sf->glyphs[i]->ticked = false;
+ if (( cnt = target->glyphcnt )<sf->glyphcnt ) cnt = sf->glyphcnt;
+ glyphs = gcalloc(cnt,sizeof(SplineChar *));
+ for ( i=0; i<target->glyphcnt; ++i ) if ( target->glyphs[i]!=NULL ) {
+ SplineChar *sc = SFGetChar(sf,target->glyphs[i]->unicodeenc,target->glyphs[i]->name );
+ if ( sc==NULL && addempties )
+ sc = SplineCharMatch(sf,target->glyphs[i]);
+ if ( sc!=NULL ) {
+ glyphs[i] = sc;
+ sc->ticked = true;
+ }
+ }
+ for ( i=cnt2=0; i<sf->glyphcnt; ++i )
+ if ( sf->glyphs[i]!=NULL && !sf->glyphs[i]->ticked )
+ ++cnt2;
+ if ( target->glyphcnt+cnt2>cnt ) {
+ glyphs = grealloc(glyphs,(target->glyphcnt+cnt2)*sizeof(SplineChar *));
+ memset(glyphs+cnt,0,(target->glyphcnt+cnt2-cnt)*sizeof(SplineChar *));
+ cnt = target->glyphcnt+cnt2;
+ }
+ j = target->glyphcnt;
+ for ( i=0; i<sf->glyphcnt; ++i )
+ if ( sf->glyphs[i]!=NULL && !sf->glyphs[i]->ticked )
+ glyphs[j++] = sf->glyphs[i];
+ free(sf->glyphs);
+ sf->glyphs = glyphs;
+ sf->glyphcnt = sf->glyphmax = cnt;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ sf->glyphs[i]->orig_pos = i;
+ for ( bdf = sf->bitmaps; bdf!=NULL; bdf = bdf->next ) {
+ BDFChar **glyphs;
+ glyphs = gcalloc(sf->glyphcnt,sizeof(BDFChar *));
+ for ( i=0; i<bdf->glyphcnt; ++i ) if ( bdf->glyphs[i]!=NULL )
+ glyphs[bdf->glyphs[i]->sc->orig_pos] = bdf->glyphs[i];
+ free(bdf->glyphs);
+ bdf->glyphs = glyphs;
+ bdf->glyphcnt = bdf->glyphmax = sf->glyphcnt;
+ }
+}
+
+void MMMatchGlyphs(MMSet *mm) {
+ /* reorder all instances so that they have the same orig_pos */
+ int i, j, index, lasthole;
+ SplineFont *sf, *base = NULL;
+ SplineChar *sc, *scnew, *sc2;
+
+ for ( i = 0; i<mm->instance_count; ++i ) if ( mm->instances[i]!=NULL ) {
+ base = mm->instances[i];
+ break;
+ }
+ if ( base==NULL )
+return;
+
+ /* First build up an ordering that uses all glyphs found in any of the */
+ /* sub-fonts, "base" will be the start of it. We will add glyphs to */
+ /* "base" as needed */
+ lasthole = -1;
+ for ( i = 0; i<mm->instance_count; ++i ) if ( (sf=mm->instances[i])!=NULL && sf!=NULL ) {
+ for ( j=0; j<sf->glyphcnt; ++j ) if ( (sc=sf->glyphs[j])!=NULL ) {
+ if ( j<base->glyphcnt && base->glyphs[j]!=NULL &&
+ base->glyphs[j]->unicodeenc==sc->unicodeenc &&
+ strcmp(base->glyphs[j]->name,sc->name)==0 )
+ continue; /* It's good, and in the same place */
+ else if ( (sc2=SFGetChar(base,sc->unicodeenc,sc->name))!=NULL &&
+ sc2->unicodeenc==sc->unicodeenc &&
+ strcmp(sc2->name,sc->name)==0 )
+ continue; /* Well, it's in there somewhere */
+ else {
+ /* We need to add it */
+ if ( j<base->glyphcnt && base->glyphs[j]==NULL )
+ index = j;
+ else {
+ for ( ++lasthole ; lasthole<base->glyphcnt && base->glyphs[lasthole]!=NULL; ++lasthole );
+ index = lasthole;
+ if ( lasthole>=base->glyphmax )
+ base->glyphs = grealloc(base->glyphs,(base->glyphmax+=20)*sizeof(SplineChar *));
+ if ( lasthole>=base->glyphcnt )
+ base->glyphcnt = lasthole+1;
+ }
+ base->glyphs[index] = scnew = SplineCharMatch(base,sc);
+ scnew->orig_pos = index;
+ }
+ }
+ }
+
+ /* Now force all other instances to match */
+ for ( i = 0; i<mm->instance_count; ++i ) if ( (sf=mm->instances[i])!=NULL && sf!=NULL )
+ SFMatchGlyphs(sf,base,true);
+ if ( mm->normal!=NULL )
+ SFMatchGlyphs(mm->normal,base,true);
+}
+
+GTextInfo encodingtypes[] = {
+ { (unichar_t *) N_("Custom"), NULL, 0, 0, (void *) "Custom", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Encoding|Glyph Order"), NULL, 0, 0, (void *) "Original", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL, NULL, 0, 0, NULL, NULL, 1, 0, 0, 0, 0, 1, 0 },
+ { (unichar_t *) N_("ISO 8859-1 (Latin1)"), NULL, 0, 0, (void *) "iso8859-1", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("ISO 8859-15 (Latin0)"), NULL, 0, 0, (void *) "iso8859-15", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("ISO 8859-2 (Latin2)"), NULL, 0, 0, (void *) "iso8859-2", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("ISO 8859-3 (Latin3)"), NULL, 0, 0, (void *) "iso8859-3", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("ISO 8859-4 (Latin4)"), NULL, 0, 0, (void *) "iso8859-4", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("ISO 8859-9 (Latin5)"), NULL, 0, 0, (void *) "iso8859-9", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("ISO 8859-10 (Latin6)"), NULL, 0, 0, (void *) "iso8859-10", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("ISO 8859-13 (Latin7)"), NULL, 0, 0, (void *) "iso8859-13", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("ISO 8859-14 (Latin8)"), NULL, 0, 0, (void *) "iso8859-14", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL, NULL, 0, 0, NULL, NULL, 1, 0, 0, 0, 0, 1, 0 },
+ { (unichar_t *) N_("ISO 8859-5 (Cyrillic)"), NULL, 0, 0, (void *) "iso8859-5", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("KOI8-R (Cyrillic)"), NULL, 0, 0, (void *) "koi8-r", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("ISO 8859-6 (Arabic)"), NULL, 0, 0, (void *) "iso8859-6", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("ISO 8859-7 (Greek)"), NULL, 0, 0, (void *) "iso8859-7", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("ISO 8859-8 (Hebrew)"), NULL, 0, 0, (void *) "iso8859-8", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("ISO 8859-11 (Thai)"), NULL, 0, 0, (void *) "iso8859-11", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL, NULL, 0, 0, NULL, NULL, 1, 0, 0, 0, 0, 1, 0 },
+ { (unichar_t *) N_("Macintosh Latin"), NULL, 0, 0, (void *) "mac", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Windows Latin (\"ANSI\")"), NULL, 0, 0, (void *) "win", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Adobe Standard"), NULL, 0, 0, (void *) "AdobeStandard", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Symbol"), NULL, 0, 0, (void *) "Symbol", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) NU_("ΤεΧ Base (8r)"), NULL, 0, 0, (void *) "TeX-Base-Encoding", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL, NULL, 0, 0, NULL, NULL, 1, 0, 0, 0, 0, 1, 0 },
+ { (unichar_t *) N_("ISO 10646-1 (Unicode, BMP)"), NULL, 0, 0, (void *) "UnicodeBmp", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("ISO 10646-1 (Unicode, Full)"), NULL, 0, 0, (void *) "UnicodeFull", NULL, 0, 0, 0, 0, 0, 0, 1},
+ /*{ (unichar_t *) N_("ISO 10646-? (by plane) ..."), NULL, 0, 0, (void *) em_unicodeplanes, NULL, 0, 0, 0, 0, 0, 0, 1}*/
+ { NULL, NULL, 0, 0, NULL, NULL, 1, 0, 0, 0, 0, 1, 0 },
+ { (unichar_t *) N_("SJIS (Kanji)"), NULL, 0, 0, (void *) "sjis", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("JIS 208 (Kanji)"), NULL, 0, 0, (void *) "jis208", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("JIS 212 (Kanji)"), NULL, 0, 0, (void *) "jis212", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Wansung (Korean)"), NULL, 0, 0, (void *) "wansung", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("KSC 5601-1987 (Korean)"), NULL, 0, 0, (void *) "ksc5601", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Johab (Korean)"), NULL, 0, 0, (void *) "johab", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("GB 2312 (Simp. Chinese)"), NULL, 0, 0, (void *) "gb2312", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("EUC GB 2312 (Chinese)"), NULL, 0, 0, (void *) "gb2312pk", NULL, 0, 0, 0, 0, 0, 0, 1},
+#ifdef FONTFORGE_CONFIG_GB12345
+ { (unichar_t *) N_("EUC-GB12345"), NULL, 0, 0, (void *) "GB12345-EUC", NULL, 0, 0, 0, 0, 0, 0, 1, 0},
+#endif
+ { (unichar_t *) N_("Big5 (Trad. Chinese)"), NULL, 0, 0, (void *) "big5", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Big5 HKSCS (Trad. Chinese)"), NULL, 0, 0, (void *) "big5hkscs", NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+
+static void EncodingInit(void) {
+ int i;
+ static int done = false;
+
+ if ( done )
+return;
+ done = true;
+ for ( i=0; i<sizeof(encodingtypes)/sizeof(encodingtypes[0])-1; ++i ) {
+ if ( !encodingtypes[i].line )
+ encodingtypes[i].text = (unichar_t *) S_((char *) encodingtypes[i].text);
+ }
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+GMenuItem *GetEncodingMenu(void (*func)(GWindow,GMenuItem *,GEvent *),
+ Encoding *current) {
+ GMenuItem *mi;
+ int i, cnt;
+ Encoding *item;
+
+ EncodingInit();
+
+ cnt = 0;
+ for ( item=enclist; item!=NULL ; item=item->next )
+ if ( !item->hidden )
+ ++cnt;
+ i = cnt+1;
+ i += sizeof(encodingtypes)/sizeof(encodingtypes[0]);
+ mi = gcalloc(i+1,sizeof(GMenuItem));
+ for ( i=0; i<sizeof(encodingtypes)/sizeof(encodingtypes[0])-1; ++i ) {
+ mi[i].ti = encodingtypes[i];
+ if ( !mi[i].ti.line ) {
+ mi[i].ti.text = utf82u_copy((char *) (mi[i].ti.text));
+ mi[i].ti.checkable = true;
+ if ( strmatch(mi[i].ti.userdata,current->enc_name)==0 ||
+ (current->iconv_name!=NULL && strmatch(mi[i].ti.userdata,current->iconv_name)==0))
+ mi[i].ti.checked = true;
+ }
+ mi[i].ti.text_is_1byte = false;
+ mi[i].ti.fg = mi[i].ti.bg = COLOR_DEFAULT;
+ mi[i].invoke = func;
+ }
+ if ( cnt!=0 ) {
+ mi[i].ti.fg = mi[i].ti.bg = COLOR_DEFAULT;
+ mi[i++].ti.line = true;
+ for ( item=enclist; item!=NULL ; item=item->next )
+ if ( !item->hidden ) {
+ mi[i].ti.text = utf82u_copy(item->enc_name);
+ mi[i].ti.userdata = (void *) item->enc_name;
+ mi[i].ti.fg = mi[i].ti.bg = COLOR_DEFAULT;
+ mi[i].ti.checkable = true;
+ if ( item==current )
+ mi[i].ti.checked = true;
+ mi[i++].invoke = func;
+ }
+ }
+return( mi );
+}
+#endif
+
+GTextInfo *GetEncodingTypes(void) {
+ GTextInfo *ti;
+ int i, cnt;
+ Encoding *item;
+
+ EncodingInit();
+
+ cnt = 0;
+ for ( item=enclist; item!=NULL ; item=item->next )
+ if ( !item->hidden )
+ ++cnt;
+ i = cnt + sizeof(encodingtypes)/sizeof(encodingtypes[0]);
+ ti = gcalloc(i+1,sizeof(GTextInfo));
+ memcpy(ti,encodingtypes,sizeof(encodingtypes)-sizeof(encodingtypes[0]));
+ for ( i=0; i<sizeof(encodingtypes)/sizeof(encodingtypes[0])-1; ++i ) {
+ ti[i].text = (unichar_t *) copy((char *) ti[i].text);
+ }
+ if ( cnt!=0 ) {
+ ti[i++].line = true;
+ for ( item=enclist; item!=NULL ; item=item->next )
+ if ( !item->hidden ) {
+ ti[i].text = uc_copy(item->enc_name);
+ ti[i++].userdata = (void *) item->enc_name;
+ }
+ }
+return( ti );
+}
+
+GTextInfo *EncodingTypesFindEnc(GTextInfo *encodingtypes, Encoding *enc) {
+ int i;
+ char *name;
+ Encoding *new_enc;
+
+ for ( i=0; encodingtypes[i].text!=NULL || encodingtypes[i].line; ++i ) {
+ if ( encodingtypes[i].text==NULL )
+ continue;
+ name = encodingtypes[i].userdata;
+ new_enc = FindOrMakeEncoding(name);
+ if ( new_enc==NULL )
+ continue;
+ if ( enc==new_enc )
+return( &encodingtypes[i] );
+ }
+return( NULL );
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+Encoding *ParseEncodingNameFromList(GGadget *listfield) {
+ const unichar_t *name = _GGadgetGetTitle(listfield);
+ int32 len;
+ GTextInfo **ti = GGadgetGetList(listfield,&len);
+ int i;
+ Encoding *enc = NULL;
+
+ for ( i=0; i<len; ++i ) if ( ti[i]->text!=NULL ) {
+ if ( u_strcmp(name,ti[i]->text)==0 ) {
+ enc = FindOrMakeEncoding(ti[i]->userdata);
+ break;
+ }
+ }
+
+ if ( enc == NULL ) {
+ char *temp = u2utf8_copy(name);
+ enc = FindOrMakeEncoding(temp);
+ free(temp);
+ }
+ if ( enc==NULL )
+ gwwv_post_error(_("Bad Encoding"),_("Bad Encoding"));
+return( enc );
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+void SFExpandGlyphCount(SplineFont *sf, int newcnt) {
+ int old = sf->glyphcnt;
+ FontView *fv;
+
+ if ( old>=newcnt )
+return;
+ if ( sf->glyphmax<newcnt ) {
+ sf->glyphs = grealloc(sf->glyphs,newcnt*sizeof(SplineChar *));
+ sf->glyphmax = newcnt;
+ }
+ memset(sf->glyphs+sf->glyphcnt,0,(newcnt-sf->glyphcnt)*sizeof(SplineChar *));
+ sf->glyphcnt = newcnt;
+
+ for ( fv=sf->fv; fv!=NULL; fv=fv->nextsame ) {
+ if ( fv->sf==sf ) { /* Beware of cid keyed fonts which might look at a different subfont */
+ if ( fv->normal!=NULL )
+ continue; /* If compacted then we haven't added any glyphs so haven't changed anything */
+ /* Don't display any of these guys, so not mapped. */
+ /* No change to selection, or to map->map, but change to backmap */
+ if ( newcnt>fv->map->backmax )
+ fv->map->backmap = grealloc(fv->map->backmap,(fv->map->backmax = newcnt+5)*sizeof(int32));
+ memset(fv->map->backmap+old,-1,(newcnt-old)*sizeof(int32));
+ }
+ }
+}
+
+
+
+
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/featurefile.c b/Build/source/libs/luafontforge/fontforge/fontforge/featurefile.c
new file mode 100644
index 00000000000..b90b9b6a625
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/featurefile.c
@@ -0,0 +1,5539 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaeditui.h"
+#include "ttf.h"
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <utype.h>
+#include <ustring.h>
+
+#include <stddef.h> /* for offsetof() */
+
+#ifdef LUA_FF_LIB
+extern void gwwv_post_error(char *a, ...);
+extern void gwwv_post_notice (char *a, ...) ;
+
+#define Isspace(a) ((a)==' '|| ((a) >= '\t' && (a) <= '\r'))
+#define Isdigit(a) ((a)>='0' && (a)<='9')
+#define Isalpha(a) (((a)>='A' && (a)<='Z')||((a)>='a' && (a)<='z'))
+#define Ishexdigit(a) (((a)>='0' && (a)<='9')||((a)>='A' && (a)<='F')||((a)>='a' && (a)<='f'))
+#define Isalnum(a) (((a)>='0' && (a)<='9')||((a)>='A' && (a)<='Z')||((a)>='a' && (a)<='z'))
+#endif
+
+/* Adobe's opentype feature file */
+
+/* ************************************************************************** */
+/* ******************************* Output feat ****************************** */
+/* ************************************************************************** */
+
+/* Do GPOS and GSUB features have to share the same feature statement? */
+
+static void dump_glyphname(FILE *out, SplineChar *sc) {
+ if ( sc->parent->cidmaster!=NULL )
+ fprintf( out, "\\%d", sc->orig_pos /* That's the CID */ );
+ else
+ fprintf( out, "\\%s", sc->name );
+}
+
+static void dump_glyphbyname(FILE *out, SplineFont *sf, char *name) {
+ SplineChar *sc = SFGetChar(sf,-1,name);
+
+ if ( sc==NULL )
+ LogError( "No glyph named %s.", name );
+ if ( sc->parent->cidmaster==NULL || sc==NULL )
+ fprintf( out, "\\%s", name );
+ else
+ fprintf( out, "\\%s", sc->name );
+}
+
+static void dump_glyphnamelist(FILE *out, SplineFont *sf, char *names) {
+ char *pt, *start;
+ int ch;
+ SplineChar *sc2;
+ int len=0;
+ char cidbuf[20], *nm;
+
+ if ( sf->subfontcnt==0 ) {
+ for ( pt=names; ; ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ for ( start=pt; *pt!=' ' && *pt!='\0'; ++pt );
+ ch = *pt; *pt = '\0';
+ if ( pt-start+len+1 >72 ) {
+ fprintf( out, "\n\t" );
+ len = 8;
+ }
+ fprintf( out, "%s ", start );
+ len += strlen(start)+1;
+ *pt = ch;
+ }
+ } else {
+ for ( pt=names; ; ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ for ( start=pt; *pt!=' ' && *pt!='\0'; ++pt );
+ ch = *pt; *pt = '\0';
+ sc2 = SFGetChar(sf,-1,start);
+ if ( sc2==NULL ) {
+ LogError( "No CID named %s", start);
+ nm = start;
+ } else {
+ sprintf( cidbuf, "\\%d", sc2->orig_pos );
+ nm = cidbuf;
+ }
+ if ( strlen(nm)+len+1 >72 ) {
+ fprintf( out, "\n\t" );
+ len = 8;
+ }
+ fprintf( out, "%s ", nm );
+ len += strlen(nm)+1;
+ *pt = ch;
+ }
+ }
+}
+
+static char *lookupname(OTLookup *otl) {
+ char *pt1, *pt2;
+ static char space[32];
+
+ if ( otl->tempname != NULL )
+return( otl->tempname );
+
+ for ( pt1=otl->lookup_name,pt2=space; *pt1 && pt2<space+31; ++pt1 ) {
+ if ( !(*pt1&0x80) && (Isalpha(*pt1) || *pt1=='_' || *pt1=='.' ||
+ (pt1!=otl->lookup_name && Isdigit(*pt1))))
+ *pt2++ = *pt1;
+ }
+ *pt2 = '\0';
+return( space );
+}
+
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+static void dumpdevice(FILE *out,DeviceTable *devtab) {
+ int i, any = false;
+
+ fprintf( out, "<device " );
+ if ( devtab!=NULL && devtab->corrections!=NULL ) {
+ for ( i=devtab->first_pixel_size; i<=devtab->last_pixel_size; ++i ) if ( devtab->corrections[i-devtab->first_pixel_size]!=0 ) {
+ if ( any )
+ putc(',',out);
+ else
+ any = true;
+ fprintf( out, "%d %d", i, devtab->corrections[i-devtab->first_pixel_size]);
+ }
+ }
+ if ( any )
+ fprintf( out, ">" );
+ else
+ fprintf( out, "NULL>" );
+}
+#endif
+
+static void dump_valuerecord(FILE *out, struct vr *vr) {
+ fprintf( out, "<%d %d %d %d", vr->xoff, vr->yoff, vr->h_adv_off, vr->v_adv_off );
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( vr->adjust!=NULL ) {
+ putc( ' ', out);
+ dumpdevice(out,&vr->adjust->xadjust);
+ putc( ' ', out);
+ dumpdevice(out,&vr->adjust->yadjust);
+ putc( ' ', out);
+ dumpdevice(out,&vr->adjust->xadv);
+ putc( ' ', out);
+ dumpdevice(out,&vr->adjust->yadv);
+ }
+#endif
+ putc('>',out);
+}
+
+static void dump_anchorpoint(FILE *out,AnchorPoint *ap) {
+
+ if ( ap==NULL ) {
+ fprintf( out, "<anchor NULL>" );
+return;
+ }
+
+ fprintf( out, "<anchor %g %g", rint(ap->me.x), rint(ap->me.y) );
+ if ( ap->has_ttf_pt )
+ fprintf( out, " %d", ap->ttf_pt_index );
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ else if ( ap->xadjust.corrections!=NULL || ap->yadjust.corrections!=NULL ) {
+ putc(' ',out);
+ dumpdevice(out,&ap->xadjust);
+ putc(' ',out);
+ dumpdevice(out,&ap->yadjust);
+ }
+#endif
+ putc('>',out);
+}
+
+static void dump_kernclass(FILE *out,SplineFont *sf,struct lookup_subtable *sub) {
+ int i,j;
+ KernClass *kc = sub->kc;
+
+ for ( i=0; i<kc->first_cnt; ++i ) if ( kc->firsts[i]!=NULL ) {
+ fprintf( out, " @kc%d_first_%d = [", sub->subtable_offset, i );
+ dump_glyphnamelist(out,sf,kc->firsts[i] );
+ fprintf( out, "];\n" );
+ }
+ for ( i=0; i<kc->second_cnt; ++i ) if ( kc->seconds[i]!=NULL ) {
+ fprintf( out, " @kc%d_second_%d = [", sub->subtable_offset, i );
+ dump_glyphnamelist(out,sf,kc->seconds[i] );
+ fprintf( out, "];\n" );
+ }
+ for ( i=0; i<kc->first_cnt; ++i ) if ( kc->firsts[i]!=NULL ) {
+ for ( j=0; j<kc->second_cnt; ++j ) if ( kc->seconds[j]!=NULL ) {
+ if ( kc->offsets[i*kc->second_cnt+j]!=0 )
+ fprintf( out, " pos @kc%d_first_%d @kc%d_second_%d %d;\n",
+ sub->subtable_offset, i,
+ sub->subtable_offset, j,
+ kc->offsets[i*kc->second_cnt+j]);
+ }
+ }
+}
+
+static char *nameend_from_class(char *glyphclass) {
+ char *pt = glyphclass;
+
+ while ( *pt==' ' ) ++pt;
+ while ( *pt!=' ' && *pt!='\0' ) ++pt;
+return( pt );
+}
+
+static OTLookup *lookup_in_rule(struct fpst_rule *r,int seq,int *index, int *pos) {
+ int i;
+ OTLookup *otl;
+ /* Suppose there are two lookups which affect the same sequence pos? */
+ /* That's legal in otf, but I don't think it can be specified in the */
+ /* feature file. It doesn't seem likely to be used so I ignore it */
+
+ for ( i=0; i<r->lookup_cnt && seq<r->lookups[i].seq; ++i );
+ if ( i>=r->lookup_cnt )
+return( NULL );
+ *index = i;
+ *pos = seq-r->lookups[i].seq;
+ otl = r->lookups[i].lookup;
+ if ( seq==r->lookups[i].seq )
+return( otl );
+ if ( otl->lookup_type == gsub_ligature )
+return( otl );
+ else if ( otl->lookup_type == gpos_pair && *pos==1 )
+return( otl );
+
+return( NULL );
+}
+
+static PST *pst_from_single_lookup(SplineFont *sf, OTLookup *otl, char *name ) {
+ SplineChar *sc = SFGetChar(sf,-1,name);
+ PST *pst;
+
+ if ( sc==NULL )
+return( NULL );
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable!=NULL && pst->subtable->lookup == otl )
+return( pst );
+ }
+return( NULL );
+}
+
+static PST *pst_from_pos_pair_lookup(SplineFont *sf, OTLookup *otl, char *name1, char *name2, PST *space ) {
+ SplineChar *sc = SFGetChar(sf,-1,name1), *sc2;
+ PST *pst;
+ int isv;
+ KernPair *kp;
+
+ if ( sc==NULL )
+return( NULL );
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable!=NULL && pst->subtable->lookup == otl &&
+ strcmp(pst->u.pair.paired,name2)==0 )
+return( pst );
+ }
+
+ sc2 = SFGetChar(sf,-1,name2);
+ if ( sc2==NULL )
+return( NULL );
+ /* Ok. not saved as a pst. If a kp then build a pst of it */
+ for ( isv=0; isv<2; ++isv ) {
+ for ( kp= isv ? sc->vkerns : sc->kerns; kp!=NULL; kp=kp->next ) {
+ if ( kp->subtable->lookup==otl && kp->sc == sc2 ) {
+ memset(space->u.pair.vr,0,2*sizeof(struct vr));
+ /* !!! Bug. Lose device tables here */
+ if ( isv )
+ space->u.pair.vr[0].v_adv_off = kp->off;
+ else if ( otl->lookup_flags&pst_r2l )
+ space->u.pair.vr[1].h_adv_off = kp->off;
+ else
+ space->u.pair.vr[0].h_adv_off = kp->off;
+return( space );
+ }
+ }
+ }
+return( NULL );
+}
+
+static PST *pst_from_ligature(SplineFont *sf, OTLookup *otl, char *components ) {
+ PST *pst;
+ SplineFont *_sf;
+ int k,gid;
+ SplineChar *sc;
+
+ k=0;
+ do {
+ _sf = sf->subfontcnt==0 ? sf : sf->subfonts[k];
+ for ( gid=0; gid<_sf->glyphcnt; ++gid ) if ( (sc = _sf->glyphs[gid])!=NULL ) {
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable!=NULL && pst->subtable->lookup == otl &&
+ strcmp(pst->u.lig.components,components)==0 ) {
+ pst->u.lig.lig = sc;
+return( pst );
+ }
+ }
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+return( NULL );
+}
+
+static PST *pst_any_from_otl(SplineFont *sf, OTLookup *otl ) {
+ PST *pst;
+ SplineFont *_sf;
+ int k,gid;
+ SplineChar *sc;
+
+ k=0;
+ do {
+ _sf = sf->subfontcnt==0 ? sf : sf->subfonts[k];
+ for ( gid=0; gid<_sf->glyphcnt; ++gid ) if ( (sc = _sf->glyphs[gid])!=NULL ) {
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable!=NULL && pst->subtable->lookup == otl ) {
+ if ( otl->lookup_type == gsub_ligature )
+ pst->u.lig.lig = sc;
+return( pst );
+ }
+ }
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+return( NULL );
+}
+
+static AnchorPoint *apfind_entry_exit(SplineFont *sf,OTLookup *otl, char *name,
+ AnchorPoint **_exit) {
+ AnchorPoint *entry = NULL, *exit = NULL;
+ AnchorPoint *ap;
+ SplineChar *sc = SFGetChar(sf,-1,name);
+
+ if ( sc==NULL )
+return( NULL );
+ for ( ap = sc->anchor ; ap!=NULL; ap=ap->next ) {
+ if ( ap->anchor->subtable->lookup == otl ) {
+ if ( ap->type == at_centry )
+ entry = ap;
+ else if ( ap->type == at_cexit )
+ exit = ap;
+ }
+ }
+ *_exit = exit;
+return( entry );
+}
+
+static void dump_contextpstglyphs(FILE *out,SplineFont *sf,
+ struct lookup_subtable *sub, struct fpst_rule *r, int in_ignore) {
+ int i, j, pos, index;
+ OTLookup *otl;
+ struct vr pairvr[2];
+ PST *pst, space;
+ char *start, *pt, *last_start, *last_end;
+ int ch, ch2;
+
+ space.u.pair.vr = pairvr;
+
+ if ( r->u.glyph.back!=NULL ) {
+ dump_glyphnamelist(out,sf,r->u.glyph.back );
+ putc(' ',out);
+ }
+ last_start = last_end = NULL;
+ for ( pt=r->u.glyph.names; ; ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ for ( start=pt; *pt!=' ' && *pt!='\0'; ++pt );
+ ch = *pt; *pt = '\0';
+ otl = lookup_in_rule(r,i,&index, &pos);
+ if ( otl!=NULL ) {
+ if ( otl->lookup_type == gpos_cursive )
+ fprintf( out, "cursive " );
+ else if ( otl->lookup_type == gpos_mark2mark )
+ fprintf( out, "mark " );
+ }
+ dump_glyphbyname(out,sf,start);
+ if ( in_ignore )
+ putc('\'',out);
+ else if ( otl!=NULL ) {
+ putc( index&1 ? '"' : '\'', out );
+ if ( otl->lookup_type==gpos_single ) {
+ pst = pst_from_single_lookup(sf, otl, start);
+ if ( pst!=NULL )
+ dump_valuerecord(out,&pst->u.pos);
+ } else if ( otl->lookup_type==gpos_pair ) {
+ if ( pos==1 ) {
+ ch2 = *last_end; *last_end = '\0';
+ pst = pst_from_pos_pair_lookup(sf,otl,last_start,start,&space);
+ *last_end = ch2;
+ } else {
+ char *next_start, *next_end;
+ next_start = pt;
+ while ( *next_start==' ' ) ++next_start;
+ if ( *next_start!='\0' ) {
+ for ( next_end=next_start; *next_end!=' ' && *next_end!='\0'; ++next_end );
+ ch2 = *next_end; *next_end = '\0';
+ pst = pst_from_pos_pair_lookup(sf,otl,start,next_start,&space);
+ *next_end = ch2;
+ } else
+ pst = NULL;
+ }
+ if ( pst!=NULL )
+ dump_valuerecord(out,&pst->u.pair.vr[pos]);
+ } else if ( otl->lookup_type==gpos_cursive ) {
+ AnchorPoint *entry, *exit;
+ entry = apfind_entry_exit(sf,otl,start,&exit);
+ dump_anchorpoint(out,entry);
+ putc(' ',out);
+ dump_anchorpoint(out,exit);
+ putc(' ',out);
+ } else if ( otl->lookup_type>gpos_start && otl->ticked )
+ fprintf(out, "<lookup %s> ", lookupname(otl) );
+ }
+ last_start = start; last_end = pt;
+ *pt = ch;
+ putc(' ',out);
+ }
+ if ( r->u.glyph.fore!=NULL ) {
+ dump_glyphnamelist(out,sf,r->u.glyph.fore );
+ putc(' ',out);
+ }
+ if ( r->lookup_cnt!=0 && sub->lookup->lookup_type<gpos_start ) {
+ fprintf( out, " by " );
+ for ( i=0; i<r->lookup_cnt; ++i ) {
+ otl = r->lookups[i].lookup;
+ for ( pt=r->u.glyph.names, j=0; ; ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' || j>=r->lookups[i].seq )
+ break;
+ while ( *pt!=' ' && *pt!='\0' ) ++pt;
+ }
+ if ( otl->lookup_type == gsub_single ) {
+ pst = pst_from_single_lookup(sf,otl,pt);
+ if ( pst!=NULL )
+ dump_glyphbyname(out,sf,pst->u.subs.variant );
+ } else if ( otl->lookup_type==gsub_ligature ) {
+ pst = pst_from_ligature(sf,otl,pt);
+ if ( pst!=NULL )
+ dump_glyphname(out,pst->u.lig.lig);
+ putc( ' ',out );
+ } else if ( otl->lookup_type<gpos_start && otl->ticked )
+ fprintf(out, "<lookup %s> ", lookupname(otl) );
+ }
+ }
+}
+
+static void dump_contextpstcoverage(FILE *out,SplineFont *sf,
+ struct lookup_subtable *sub, struct fpst_rule *r, int in_ignore) {
+ int i, pos, index;
+ OTLookup *otl;
+ PST *pst, space;
+ char *start, *pt, *last_end;
+ int ch, ch2;
+
+ for ( i=0; i<r->u.coverage.bcnt; ++i ) {
+ putc('[',out);
+ dump_glyphnamelist(out,sf,r->u.coverage.bcovers[i] );
+ fprintf( out, "] ");
+ }
+ for ( i=0; i<r->u.coverage.ncnt; ++i ) {
+ putc('[',out);
+ dump_glyphnamelist(out,sf,r->u.coverage.ncovers[i] );
+ putc(']',out);
+ if ( in_ignore )
+ putc('\'',out);
+ else {
+ otl = lookup_in_rule(r,i,&index, &pos);
+ if ( otl!=NULL ) {
+ putc( index&1 ? '"' : '\'', out );
+ /* Ok, I don't see any way to specify a class of value records */
+ /* so just assume all vr will be the same for the class */
+ pt = nameend_from_class(r->u.coverage.ncovers[i]);
+ ch = *pt; *pt = '\0';
+ if ( otl->ticked && otl->lookup_type>=gpos_start )
+ fprintf(out, "<lookup %s> ", lookupname(otl) );
+ else if ( otl->lookup_type==gpos_single ) {
+ pst = pst_from_single_lookup(sf,otl,r->u.coverage.ncovers[i]);
+ if ( pst!=NULL )
+ dump_valuerecord(out,&pst->u.pos);
+ } else if ( otl->lookup_type==gpos_pair ) {
+ if ( pos==1 ) {
+ last_end = nameend_from_class(r->u.coverage.ncovers[i-1]);
+ ch2 = *last_end; *last_end = '\0';
+ pst = pst_from_pos_pair_lookup(sf,otl,r->u.coverage.ncovers[i-1],r->u.coverage.ncovers[i],&space);
+ *last_end = ch2;
+ } else if ( i+1<r->u.coverage.ncnt ) {
+ char *next_end;
+ next_end = nameend_from_class(r->u.coverage.ncovers[i+1]);
+ ch2 = *next_end; *next_end = '\0';
+ pst = pst_from_pos_pair_lookup(sf,otl,r->u.coverage.ncovers[i],r->u.coverage.ncovers[i+1],&space);
+ *next_end = ch2;
+ } else
+ pst = NULL;
+ if ( pst!=NULL )
+ dump_valuerecord(out,&pst->u.pair.vr[pos]);
+ }
+ *pt = ch;
+ }
+ }
+ putc(' ',out);
+ }
+ for ( i=0; i<r->u.coverage.fcnt; ++i ) {
+ putc('[',out);
+ dump_glyphnamelist(out,sf,r->u.coverage.fcovers[i] );
+ fprintf( out, "] ");
+ }
+ if ( r->lookup_cnt!=0 && sub->lookup->lookup_type<gpos_start ) {
+ fprintf( out, " by " );
+ for ( i=0; i<r->lookup_cnt; ++i ) {
+ int len;
+ otl = r->lookups[i].lookup;
+ if ( otl->ticked )
+ fprintf(out, "<lookup %s> ", lookupname(otl) );
+ else if ( otl->lookup_type==gsub_single ) {
+ len = 40;
+ putc('[',out);
+ for ( pt=r->u.coverage.ncovers[r->lookups[i].seq]; ; ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ for ( start=pt; *pt!=' ' && *pt!='\0'; ++pt );
+ ch = *pt; *pt = '\0';
+ pst = pst_from_single_lookup(sf,otl,start);
+ if ( len+(pst==NULL?4:strlen(pst->u.subs.variant))>80 ) {
+ fprintf(out,"\n\t" );
+ len = 8;
+ }
+ if ( pst!=NULL ) {
+ dump_glyphbyname(out,sf,pst->u.subs.variant);
+ len += strlen(pst->u.subs.variant);
+ } else {
+ fprintf( out, "NULL" );
+ len += 4;
+ }
+ *pt = ch;
+ putc(' ',out);
+ ++len;
+ }
+ putc(']',out);
+ } else if ( otl->lookup_type==gsub_ligature ) {
+ /* If we get here assume there is only one ligature */
+ /* or there is only one combination of input glyphs (all coverage tables contain one glyph) */
+ if ( sub->fpst->effectively_by_glyphs ) {
+ /* Build up THE combination of input glyphs */
+ int len, n;
+ char *start;
+ for ( n=len=0; n<r->u.coverage.ncnt; ++n )
+ len += strlen(r->u.coverage.ncovers[n])+1;
+ start = galloc(len+1);
+ for ( n=len=0; n<r->u.coverage.ncnt; ++n ) {
+ strcpy(start+len,r->u.coverage.ncovers[n]);
+ len += strlen(r->u.coverage.ncovers[n]);
+ if ( start[len-1]!=' ' )
+ start[len++] = ' ';
+ }
+ if ( len!=0 )
+ start[len-1] = '\0';
+ pst = pst_from_ligature(sf,otl,start);
+ free( start );
+ } else
+ pst = pst_any_from_otl(sf,otl);
+ if ( pst!=NULL )
+ dump_glyphname(out,pst->u.lig.lig);
+ }
+ }
+ }
+ putc(';',out); putc('\n',out);
+}
+
+static void dump_contextpstclass(FILE *out,SplineFont *sf,
+ struct lookup_subtable *sub, struct fpst_rule *r, int in_ignore) {
+ FPST *fpst = sub->fpst;
+ int i, pos, index;
+ OTLookup *otl;
+ PST *pst, space;
+ char *start, *pt, *last_start, *last_end;
+ int ch, ch2;
+
+ for ( i=0; i<r->u.class.bcnt; ++i )
+ fprintf( out, "@cc%d_back_%d ", sub->subtable_offset, r->u.class.bclasses[i] );
+ for ( i=0; i<r->u.class.ncnt; ++i ) {
+ fprintf( out, "@cc%d_match_%d", sub->subtable_offset, r->u.class.nclasses[i] );
+ if ( in_ignore )
+ putc( '\'',out );
+ else {
+ otl = lookup_in_rule(r,i,&index, &pos);
+ if ( otl!=NULL ) {
+ putc( index&1 ? '"' : '\'', out );
+ /* Ok, I don't see any way to specify a class of value records */
+ /* so just assume all vr will be the same for the class */
+ start = fpst->nclass[r->u.class.nclasses[i]];
+ pt = nameend_from_class(start);
+ ch = *pt; *pt = '\0';
+ if ( otl->ticked && otl->lookup_type>=gpos_start )
+ fprintf(out, "<lookup %s> ", lookupname(otl) );
+ else if ( otl->lookup_type==gpos_single ) {
+ pst = pst_from_single_lookup(sf,otl,start);
+ if ( pst!=NULL )
+ dump_valuerecord(out,&pst->u.pos);
+ } else if ( otl->lookup_type==gpos_pair ) {
+ if ( pos==1 ) {
+ last_start = fpst->nclass[r->u.class.nclasses[i-1]];
+ last_end = nameend_from_class(last_start);
+ ch2 = *last_end; *last_end = '\0';
+ pst = pst_from_pos_pair_lookup(sf,otl,last_start,start,&space);
+ *last_end = ch2;
+ } else if ( i+1<r->u.coverage.ncnt ) {
+ char *next_start, *next_end;
+ next_start = fpst->nclass[r->u.class.nclasses[i+1]];
+ next_end = nameend_from_class(next_start);
+ ch2 = *next_end; *next_end = '\0';
+ pst = pst_from_pos_pair_lookup(sf,otl,start,next_start,&space);
+ *next_end = ch2;
+ } else
+ pst = NULL;
+ if ( pst!=NULL )
+ dump_valuerecord(out,&pst->u.pair.vr[pos]);
+ }
+ *pt = ch;
+ }
+ }
+ putc(' ',out);
+ }
+ for ( i=0; i<r->u.class.fcnt; ++i )
+ fprintf( out, "@cc%d_ahead_%d ", sub->subtable_offset, r->u.class.fclasses[i] );
+ if ( r->lookup_cnt!=0 && sub->lookup->lookup_type<gpos_start ) {
+ fprintf( out, " by " );
+ for ( i=0; i<r->lookup_cnt; ++i ) {
+ otl = r->lookups[i].lookup;
+ if ( otl->ticked )
+ fprintf(out, "<lookup %s> ", lookupname(otl) );
+ else if ( otl->lookup_type==gsub_single ) {
+ putc('[',out);
+ for ( pt=fpst->nclass[r->u.class.nclasses[r->lookups[i].seq]]; ; ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ for ( start=pt; *pt!=' ' && *pt!='\0'; ++pt );
+ ch = *pt; *pt = '\0';
+ pst = pst_from_single_lookup(sf,otl,start);
+ if ( pst!=NULL )
+ dump_glyphbyname(out,sf,pst->u.subs.variant);
+ else
+ fprintf( out, "NULL" );
+ *pt = ch;
+ putc(' ',out);
+ }
+ putc(']',out);
+ } else if ( otl->lookup_type==gsub_ligature ) {
+ /* I don't think it is possible to do this correctly */
+ /* adobe doesn't say how to order glyphs for [f longs]' [i l]' */
+ /* so just assume there is only one ligature */
+ pst = pst_any_from_otl(sf,otl);
+ if ( pst!=NULL )
+ dump_glyphname(out,pst->u.lig.lig);
+ }
+ putc( ' ',out );
+ }
+ }
+}
+
+static void dump_contextpst(FILE *out,SplineFont *sf,struct lookup_subtable *sub) {
+ FPST *fpst = sub->fpst;
+ int i,j,k;
+
+ if ( fpst->format==pst_reversecoverage ) {
+ IError( "I can find no documentation on how to describe reverse context chaining lookups. Lookup %s will be skipped.",
+ sub->lookup->lookup_name );
+return;
+ }
+ if ( fpst->format==pst_class ) {
+ if ( fpst->nclass!=NULL ) {
+ for ( i=0; i<fpst->nccnt; ++i ) if ( fpst->nclass[i]!=NULL ) {
+ fprintf( out, " @cc%d_match_%d = [", sub->subtable_offset, i );
+ dump_glyphnamelist(out,sf,fpst->nclass[i] );
+ fprintf( out, "];\n" );
+ }
+ }
+ if ( fpst->bclass!=NULL ) {
+ for ( i=0; i<fpst->bccnt; ++i ) if ( fpst->bclass[i]!=NULL ) {
+ fprintf( out, " @cc%d_back_%d = [", sub->subtable_offset, i );
+ dump_glyphnamelist(out,sf,fpst->bclass[i] );
+ fprintf( out, "];\n" );
+ }
+ }
+ if ( fpst->fclass!=NULL ) {
+ for ( i=0; i<fpst->fccnt; ++i ) if ( fpst->fclass[i]!=NULL ) {
+ fprintf( out, " @cc%d_ahead_%d = [", sub->subtable_offset, i );
+ dump_glyphnamelist(out,sf,fpst->fclass[i] );
+ fprintf( out, "];\n" );
+ }
+ }
+ }
+ for ( j=0; j<fpst->rule_cnt; ++j ) {
+ struct fpst_rule *r = &fpst->rules[j];
+ for ( i=0; i<r->lookup_cnt; ++i ) for ( k=i+1; k<r->lookup_cnt; ++k ) {
+ if ( r->lookups[i].seq > r->lookups[k].seq ) {
+ int s = r->lookups[i].seq;
+ OTLookup *otl = r->lookups[i].lookup;
+ r->lookups[i].seq = r->lookups[k].seq;
+ r->lookups[k].seq = s;
+ r->lookups[i].lookup = r->lookups[k].lookup;
+ r->lookups[k].lookup = otl;
+ }
+ }
+ fprintf( out, r->lookup_cnt==0 ? " ignore sub " : " sub " );
+ if ( fpst->format==pst_class ) {
+ dump_contextpstclass(out,sf,sub,r,true);
+ } else if ( fpst->format==pst_glyphs ) {
+ dump_contextpstglyphs(out,sf,sub,r,true);
+ } else {
+ dump_contextpstcoverage(out,sf,sub,r,true);
+ }
+ }
+}
+
+static void dump_anchors(FILE *out,SplineFont *sf,struct lookup_subtable *sub) {
+ int i, j, k, l;
+ SplineFont *_sf;
+ SplineChar *sc;
+ AnchorClass *ac;
+ AnchorPoint *ap, *ap_entry, *ap_exit;
+
+ for ( ac = sf->anchor; ac!=NULL; ac=ac->next ) if ( ac->subtable==sub ) {
+ if ( sub->lookup->lookup_type==gpos_cursive ) {
+ k=0;
+ do {
+ _sf = k<sf->subfontcnt ? sf->subfonts[k] : sf;
+ for ( i=0; i<_sf->glyphcnt; ++i ) if ( (sc=_sf->glyphs[i])!=NULL ) {
+ ap_entry = ap_exit = NULL;
+ for ( ap=sc->anchor; ap!=NULL; ap=ap->next ) if ( ap->anchor==ac ) {
+ if ( ap->type == at_centry )
+ ap_entry = ap;
+ else if ( ap->type == at_cexit )
+ ap_exit = ap;
+ }
+ if ( ap_entry!=NULL || ap_exit!=NULL ) {
+ fprintf( out, " pos cursive " );
+ dump_glyphname(out,sc);
+ putc(' ',out);
+ dump_anchorpoint(out,ap_entry);
+ putc(' ',out);
+ dump_anchorpoint(out,ap_exit);
+ putc(';',out);
+ putc('\n',out);
+ }
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+ } else {
+ struct amarks { SplineChar *sc; AnchorPoint *ap; } *marks = NULL;
+ int cnt, max;
+ cnt = max = 0;
+ k=0;
+ do {
+ _sf = k<sf->subfontcnt ? sf->subfonts[k] : sf;
+ for ( i=0; i<_sf->glyphcnt; ++i ) if ( (sc=_sf->glyphs[i])!=NULL ) {
+ for ( ap=sc->anchor; ap!=NULL; ap=ap->next ) {
+ if ( ap->anchor==ac && ap->type==at_mark ) {
+ if ( cnt>=max )
+ marks = grealloc(marks,(max+=20)*sizeof(struct amarks));
+ marks[cnt].sc = sc;
+ marks[cnt].ap = ap;
+ fprintf( out, " mark ");
+ dump_glyphname(out,sc);
+ putc(' ',out);
+ dump_anchorpoint(out,ap);
+ fprintf( out, ";\n");
+ ++cnt;
+ break;
+ }
+ }
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+ if ( cnt==0 )
+ continue; /* No marks? Nothing to be done */
+ if ( sub->lookup->lookup_type!=gpos_mark2ligature ) {
+ do {
+ _sf = k<sf->subfontcnt ? sf->subfonts[k] : sf;
+ for ( i=0; i<_sf->glyphcnt; ++i ) if ( (sc=_sf->glyphs[i])!=NULL ) {
+ for ( ap=sc->anchor; ap!=NULL; ap=ap->next ) {
+ if ( ap->anchor==ac && ap->type!=at_mark ) {
+ fprintf( out, " pos ");
+ if ( sub->lookup->lookup_type == gpos_mark2mark )
+ fprintf( out, "mark " );
+ dump_glyphname(out,sc);
+ putc(' ',out);
+ dump_anchorpoint(out,ap);
+ fprintf( out, " mark [" );
+ for ( j=0; j<cnt; ++j ) {
+ dump_glyphname(out,marks[j].sc);
+ putc(' ',out);
+ }
+ fprintf(out,"];\n" );
+ }
+ }
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+ } else {
+ struct amarks *lig=NULL;
+ int lcnt, lmax=0, ligmax;
+ do {
+ _sf = k<sf->subfontcnt ? sf->subfonts[k] : sf;
+ for ( i=0; i<_sf->glyphcnt; ++i ) if ( (sc=_sf->glyphs[i])!=NULL ) {
+ lcnt = 0; ligmax=1;
+ for ( ap=sc->anchor; ap!=NULL; ap=ap->next ) {
+ if ( ap->anchor==ac && ap->type!=at_mark ) {
+ if ( lcnt>=lmax )
+ lig = grealloc(lig,(lmax+=20)*sizeof(struct amarks));
+ lig[lcnt].sc = sc;
+ lig[lcnt].ap = ap;
+ if ( ap->lig_index>ligmax )
+ ligmax = ap->lig_index;
+ ++lcnt;
+ }
+ }
+ if ( lcnt>0 ) {
+ fprintf( out, " pos " );
+ dump_glyphname(out,sc);
+ for ( j=0; j<=ligmax; ++j ) {
+ putc(' ',out );
+ for ( l=0; l<lcnt; ++l ) {
+ if ( lig[l].ap->lig_index==ligmax ) {
+ dump_anchorpoint(out,lig[l].ap);
+ break;
+ }
+ }
+ if ( l==lcnt )
+ dump_anchorpoint(out,NULL);
+ }
+ fprintf( out, " mark [" );
+ for ( j=0; j<cnt; ++j ) {
+ dump_glyphname(out,marks[j].sc);
+ putc(' ',out);
+ }
+ fprintf(out,"];\n" );
+ }
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+ free(lig);
+ }
+ free(marks);
+ }
+ }
+}
+
+static void number_subtables(SplineFont *sf) {
+ OTLookup *otl;
+ struct lookup_subtable *sub;
+ int isgpos, cnt;
+
+ cnt = 0;
+ for ( isgpos=0; isgpos<2; ++isgpos ) {
+ for ( otl = isgpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl = otl->next ) {
+ for ( sub = otl->subtables; sub!=NULL; sub=sub->next )
+ sub->subtable_offset = cnt++;
+ }
+ }
+}
+
+static int fea_bad_contextual_nestedlookup(SplineFont *sf,FPST *fpst, OTLookup *nested) {
+ int gid, k;
+ SplineFont *_sf;
+ SplineChar *sc;
+ PST *pst, *found;
+ /* non-cursive anchors can't currently be expressed in contextuals */
+ /* Nor can other contextuals */
+ /* Nor can alternate/multiple substitutions */
+ /* If we are class based or coverage table based (and interesting classes */
+ /* contain more than one glyph name) then we can't express single_pos, */
+ /* kerning, ligatures, cursive anchors (unless everything in the lookup */
+ /* results in the same transformation) */
+
+ switch ( nested->lookup_type ) {
+ case gsub_single:
+return( false ); /* This is the one thing that can always be expressed */
+ case gsub_multiple:
+ case gsub_alternate:
+ case gsub_context:
+ case gsub_contextchain:
+ case gsub_reversecchain:
+ case gpos_mark2base:
+ case gpos_mark2ligature:
+ case gpos_mark2mark:
+ case gpos_contextchain:
+ case gpos_context:
+return( true ); /* These can never be expressed */
+ case gpos_cursive:
+ case gpos_pair:
+return( fpst->format!=pst_glyphs /* && !fpst->effectively_by_glyphs*/ );
+ case gsub_ligature:
+ case gpos_single:
+ if ( fpst->format==pst_glyphs || fpst->effectively_by_glyphs )
+return( false );
+ /* One can conceive of a fraction lookup */
+ /* [one one.proportion] [slash fraction] [two two.lining] => onehalf */
+ /* where all inputs go to one output. That can be expressed */
+ /* One can also conceive of a positioning lookup (subscript->superscript) */
+ /* where all value records are the same */
+ found = NULL;
+ k=0;
+ do {
+ _sf = sf->subfontcnt==0 ? sf : sf->subfonts[k];
+ for ( gid=0; gid<_sf->glyphcnt; ++gid ) if ( (sc = _sf->glyphs[gid])!=NULL ) {
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable!=NULL && pst->subtable->lookup==nested ) {
+ if ( found==NULL ) {
+ found = pst;
+ break;
+ } else if ( nested->lookup_type==gsub_ligature )
+return( true ); /* Different glyphs */
+ else if ( found->u.pos.xoff!=pst->u.pos.xoff ||
+ found->u.pos.yoff!=pst->u.pos.yoff ||
+ found->u.pos.h_adv_off!=pst->u.pos.h_adv_off ||
+ found->u.pos.v_adv_off!=pst->u.pos.v_adv_off )
+return( true );
+ else
+ break;
+ }
+ }
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+ if ( found==NULL )
+return( true );
+return( false );
+ default:
+return( true );
+ }
+}
+
+static void dump_lookup(FILE *out, SplineFont *sf, OTLookup *otl);
+
+static void dump_needednestedlookups(FILE *out, SplineFont *sf, OTLookup *otl) {
+ struct lookup_subtable *sub;
+ int r, s, n;
+ /* So we cheat, and extend the fea format to allow us to specify a lookup */
+ /* in contextuals */
+
+ for ( sub = otl->subtables; sub!=NULL; sub=sub->next ) {
+ FPST *fpst = sub->fpst;
+ fpst->effectively_by_glyphs = false;
+ if ( fpst->format==pst_coverage ) {
+ fpst->effectively_by_glyphs = true;
+ for ( r=0; r<fpst->rule_cnt; ++r ) {
+ for ( n=0; n<fpst->rules[r].u.coverage.ncnt; ++n ) {
+ if ( strchr(fpst->rules[r].u.coverage.ncovers[n],' ')!=NULL )
+ fpst->effectively_by_glyphs = false;
+ break;
+ }
+ }
+ }
+ for ( r=0; r<fpst->rule_cnt; ++r ) {
+ for ( s=0; s<fpst->rules[r].lookup_cnt; ++s ) {
+ OTLookup *nested = fpst->rules[r].lookups[s].lookup;
+ if ( nested!=NULL && nested->features==NULL && !nested->ticked &&
+ fea_bad_contextual_nestedlookup(sf,fpst,nested))
+ dump_lookup(out,sf,nested);
+ }
+ }
+ }
+}
+
+static void dump_lookup(FILE *out, SplineFont *sf, OTLookup *otl) {
+ struct lookup_subtable *sub;
+ static char *flagnames[] = { "RightToLeft", "IgnoreBaseGlyphs", "IgnoreLigatures", "IgnoreMarks", NULL };
+ int i, k, first;
+ SplineFont *_sf;
+ SplineChar *sc;
+ PST *pst;
+ int isv;
+ KernPair *kp;
+
+ if ( otl->lookup_type == morx_indic || otl->lookup_type==morx_context ||
+ otl->lookup_type==morx_insert || otl->lookup_type==kern_statemachine )
+return; /* No support for apple "lookups" */
+
+ otl->ticked = true;
+
+ if ( otl->lookup_type==gsub_context || otl->lookup_type==gsub_contextchain ||
+ otl->lookup_type==gpos_context || otl->lookup_type==gpos_contextchain )
+ dump_needednestedlookups(out,sf,otl);
+
+ if ( sf->cidmaster ) sf = sf->cidmaster;
+ number_subtables(sf);
+
+ fprintf( out, "\nlookup %s {\n", lookupname(otl) );
+ if ( otl->lookup_flags==0 || otl->lookup_flags>15 )
+ fprintf( out, " lookupflag %d;\n", otl->lookup_flags );
+ else {
+ fprintf( out, " lookupflag" );
+ first = true;
+ for ( i=0; i<4; ++i ) if ( otl->lookup_flags&(1<<i)) {
+ if ( !first )
+ putc(',',out);
+ else
+ first = false;
+ fprintf( out, " %s", flagnames[i] );
+ }
+ putc(';',out);
+ putc('\n',out);
+ }
+ for ( sub=otl->subtables; sub!=NULL; sub=sub->next ) {
+ if ( sub!=otl->subtables )
+ fprintf( out, " subtable;\n" );
+ if ( sub->kc!=NULL )
+ dump_kernclass(out,sf,sub);
+ else if ( sub->fpst!=NULL )
+ dump_contextpst(out,sf,sub);
+ else if ( sub->anchor_classes )
+ dump_anchors(out,sf,sub);
+ else {
+ k=0;
+ do {
+ _sf = k<sf->subfontcnt ? sf->subfonts[k] : sf;
+ for ( i=0; i<_sf->glyphcnt; ++i ) if ( (sc=_sf->glyphs[i])!=NULL ) {
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) if ( pst->subtable==sub ) {
+ switch ( otl->lookup_type ) {
+ case gsub_single:
+ case gsub_multiple:
+ fprintf( out, " sub " );
+ dump_glyphname(out,sc);
+ fprintf( out, " by " );
+ dump_glyphnamelist(out,sf,pst->u.subs.variant );
+ fprintf( out,";\n" );
+ break;
+ case gsub_alternate:
+ fprintf( out, " sub " );
+ dump_glyphname(out,sc);
+ fprintf( out, " from [" );
+ dump_glyphnamelist(out,sf,pst->u.alt.components );
+ fprintf( out,"];\n" );
+ break;
+ case gsub_ligature:
+ fprintf( out, " sub " );
+ dump_glyphnamelist(out,sf,pst->u.lig.components );
+ fprintf( out, " by " );
+ dump_glyphname(out,sc);
+ fprintf( out,";\n" );
+ break;
+ case gpos_single:
+ fprintf( out, " pos " );
+ dump_glyphname(out,sc);
+ putc(' ',out);
+ dump_valuerecord(out,&pst->u.pos);
+ fprintf( out,";\n" );
+ break;
+ case gpos_pair:
+ fprintf( out, " pos " );
+ dump_glyphname(out,sc);
+ putc(' ',out);
+ dump_valuerecord(out,&pst->u.pair.vr[0]);
+ putc(' ',out);
+ dump_glyphnamelist(out,sf,pst->u.pair.paired );
+ putc(' ',out);
+ dump_valuerecord(out,&pst->u.pair.vr[0]);
+ fprintf( out,";\n" );
+ break;
+ default:
+ /* Eh? How'd we get here? An anchor class with */
+ /* no anchors perhaps? */
+ break;
+ }
+ }
+ for ( isv=0; isv<2; ++isv ) {
+ for ( kp=isv ? sc->vkerns : sc->kerns; kp!=NULL; kp=kp->next ) if ( kp->subtable==sub ) {
+ fprintf( out, " pos " );
+ dump_glyphname(out,sc);
+ putc(' ',out);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( kp->adjust!=NULL ) {
+ /* If we have a device table then we must use the long */
+ /* format */
+ if ( isv ) {
+ fprintf( out," < 0 0 0 %d <device NULL> <device NULL> <device NULL> ",
+ kp->off );
+ dumpdevice(out,kp->adjust);
+ fprintf( out, " > " );
+ dump_glyphname(out,kp->sc);
+ fprintf( out, " < 0 0 0 0 >;\n" );
+ } else if ( otl->lookup_flags&pst_r2l ) {
+ fprintf( out, " < 0 0 0 0 > " );
+ dump_glyphname(out,kp->sc);
+ fprintf( out," < 0 0 %d 0 <device NULL> <device NULL> ",
+ kp->off );
+ dumpdevice(out,kp->adjust);
+ fprintf( out, " <device NULL>>;\n" );
+ } else {
+ fprintf( out," < 0 0 %d 0 <device NULL> <device NULL> ",
+ kp->off );
+ dumpdevice(out,kp->adjust);
+ fprintf( out, " <device NULL>> " );
+ dump_glyphname(out,kp->sc);
+ fprintf( out, " < 0 0 0 0 >;\n" );
+ }
+ } else
+#endif
+ if ( otl->lookup_flags&pst_r2l ) {
+ fprintf( out, " < 0 0 0 0 > " );
+ dump_glyphname(out,kp->sc);
+ fprintf( out," < 0 0 %d 0 >;\n", kp->off );
+ } else {
+ dump_glyphname(out,kp->sc);
+ putc(' ',out);
+ fprintf( out, "%d;\n", kp->off );
+ }
+ }
+ } /* End isv/kp loops */
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+ }
+ } /* End subtables */
+ fprintf( out, "} %s;\n", lookupname(otl) );
+}
+
+#ifndef LUA_FF_LIB
+static void untick_lookups(SplineFont *sf) {
+ OTLookup *otl;
+ int isgpos;
+
+ for ( isgpos=0; isgpos<2; ++isgpos )
+ for ( otl= isgpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl=otl->next )
+ otl->ticked = false;
+}
+#endif
+
+void FeatDumpOneLookup(FILE *out,SplineFont *sf, OTLookup *otl) {
+#ifndef LUA_FF_LIB
+ FeatureScriptLangList *fl;
+ struct scriptlanglist *sl;
+ int l;
+
+ untick_lookups(sf);
+
+ dump_lookup(out,sf,otl);
+
+ for ( fl = otl->features; fl!=NULL; fl=fl->next ) {
+ fprintf( out, "\nfeature %s%c%c%c%c {\n",
+ fl->featuretag==CHR('m','a','r','k') ? "\\" : "",
+ fl->featuretag>>24, fl->featuretag>16, fl->featuretag>>8, fl->featuretag );
+ for ( sl = fl->scripts; sl!=NULL; sl=sl->next ) {
+ fprintf( out, " script %c%c%c%c;\n",
+ sl->script>>24, sl->script>16, sl->script>>8, sl->script );
+ for ( l=0; l<sl->lang_cnt; ++l ) {
+ uint32 lang = l<MAX_LANG ? sl->langs[l] : sl->morelangs[l-MAX_LANG];
+ fprintf( out, " language %c%c%c%c %s;\n",
+ lang>>24, lang>16, lang>>8, lang,
+ lang!=DEFAULT_LANG ? "exclude_dflt" : "" );
+ fprintf( out, " lookup %s;\n", lookupname(otl));
+ }
+ }
+ fprintf( out, "\n} %s%c%c%c%c;\n",
+ fl->featuretag==CHR('m','a','r','k') ? "\\" : "",
+ fl->featuretag>>24, fl->featuretag>16, fl->featuretag>>8, fl->featuretag );
+ }
+#endif
+}
+
+#ifndef LUA_FF_LIB
+static void dump_gdef(FILE *out,SplineFont *sf) {
+ PST *pst;
+ int i,gid,j,k,l, lcnt, needsclass;
+ SplineChar *sc;
+ SplineFont *_sf;
+ struct lglyphs { SplineChar *sc; PST *pst; } *glyphs;
+ static char *clsnames[] = { "@GDEF_Simple", "@GDEF_Ligature", "@GDEF_Mark", "@GDEF_Component" };
+ _sf = NULL;
+ glyphs = NULL;
+ for ( l=0; l<2; ++l ) {
+ lcnt = 0;
+ needsclass = false;
+ k=0;
+ do {
+ _sf = sf->subfontcnt==0 ? sf : _sf;
+ for ( gid=0; gid<_sf->glyphcnt; ++gid ) if ( (sc=_sf->glyphs[gid])!=NULL ) {
+ if ( sc->glyph_class!=0 || gdefclass(sc)!=1 )
+ needsclass = true;
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->type == pst_lcaret ) {
+ for ( j=pst->u.lcaret.cnt-1; j>=0; --j )
+ if ( pst->u.lcaret.carets[j]!=0 )
+ break;
+ if ( j!=-1 )
+ break;
+ }
+ }
+ if ( pst!=NULL ) {
+ if ( glyphs!=NULL ) { glyphs[lcnt].sc = sc; glyphs[lcnt].pst = pst; }
+ ++lcnt;
+ }
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+ if ( lcnt==0 )
+ break;
+ if ( glyphs!=NULL )
+ break;
+ glyphs = galloc((lcnt+1)*sizeof(struct lglyphs));
+ glyphs[lcnt].sc = NULL;
+ }
+
+ if ( !needsclass && lcnt==0 /* && sf->mark_class_cnt==0*/ )
+return; /* No anchor positioning, no ligature carets */
+
+ if ( needsclass ) {
+ int len;
+ putc('\n',out);
+ /* Class definitions must go outside the table itself. Stupid */
+ for ( i=0; i<4; ++i ) {
+ fprintf( out, "%s = [", clsnames[i] );
+ len = strlen(clsnames[i])+8;
+ k=0;
+ do {
+ _sf = sf->subfontcnt==0 ? sf : _sf;
+ for ( gid=0; gid<_sf->glyphcnt; ++gid ) if ( (sc=_sf->glyphs[gid])!=NULL ) {
+ if ( sc->glyph_class==i+1 || (sc->glyph_class==0 && gdefclass(sc)==i+1 )) {
+ if ( len+strlen(sc->name)+1 >80 ) {
+ putc('\n',out); putc('\t',out);
+ len = 8;
+ }
+ dump_glyphname(out,sc);
+ putc(' ',out);
+ len += strlen(sc->name)+1;
+ }
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+ fprintf( out, "];\n");
+ }
+ }
+ fprintf( out, "\ntable GDEF {\n" );
+ if ( needsclass ) {
+ fprintf( out, " GlyphClassDef %s %s %s %s;\n\n",
+ clsnames[0], clsnames[1], clsnames[2], clsnames[3]);
+ }
+
+ for ( i=0; i<lcnt; ++i ) {
+ PST *pst = glyphs[i].pst;
+ fprintf( out, " LigatureCaret " );
+ dump_glyphname(out,glyphs[i].sc);
+ for ( k=0; k<pst->u.lcaret.cnt; ++k ) {
+ fprintf( out, " <caret %d>", pst->u.lcaret.carets[k]);
+ }
+ fprintf( out, ";\n" );
+ }
+ free( glyphs );
+
+ /* no way to specify mark classes */
+
+ fprintf( out, "} GDEF;\n\n" );
+}
+
+static void dump_gsubgpos(FILE *out, SplineFont *sf) {
+ int isgpos;
+ int i,l,s, subl;
+ OTLookup *otl;
+ FeatureScriptLangList *fl;
+ struct scriptlanglist *sl;
+
+ for ( isgpos=0; isgpos<2; ++isgpos ) {
+ uint32 *feats = SFFeaturesInScriptLang(sf,isgpos,0xffffffff,0xffffffff);
+ if ( feats[0]!=0 ) {
+ uint32 *scripts = SFScriptsInLookups(sf,isgpos);
+ fprintf( out, "\n# %s \n\n", isgpos ? "GPOS" : "GSUB" );
+ for ( otl= isgpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl=otl->next )
+ if ( otl->features!=NULL ) /* Nested lookups will be output with the lookups which invoke them */
+ dump_lookup( out, sf, otl );
+ for ( i=0; feats[i]!=0; ++i ) {
+ fprintf( out, "\nfeature %s%c%c%c%c {\n",
+ feats[i]==CHR('m','a','r','k') ? "\\" : "",
+ feats[i]>>24, feats[i]>>16, feats[i]>>8, feats[i] );
+ if ( feats[i]==CHR('s','i','z','e') ) {
+ struct otfname *nm;
+ fprintf( out, " parameters %.1f", sf->design_size/10.0 );
+ if ( sf->fontstyle_id!=0 ) {
+ fprintf( out, " %d %.1f %.1f;\n",
+ sf->fontstyle_id,
+ sf->design_range_bottom/10.0, sf->design_range_top/10.0 );
+ for ( nm = sf->fontstyle_name; nm!=NULL; nm=nm->next ) {
+ char *pt;
+ fprintf( out, " sizemenuname 3 1 0x%x \"", nm->lang );
+ for ( pt = nm->name; ; ) {
+ int ch = utf8_ildb((const char **) &pt);
+ if ( ch=='\0' )
+ break;
+ if ( ch>=' ' && ch<=0x7f && ch!='"' && ch!='\\' )
+ putc(ch,out);
+ else
+ fprintf( out, "\\%04x", ch );
+ }
+ fprintf( out, "\";\n" );
+ }
+ } else
+ fprintf( out, " 0 0 0;\n" );
+ } else for ( s=0; scripts[s]!=0; ++s ) {
+ uint32 *langs = SFLangsInScript(sf,isgpos,scripts[s]);
+ int firsts = true;
+ for ( l=0; langs[l]!=0; ++l ) {
+ int first = true;
+ for ( otl = isgpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl=otl->next ) {
+ for ( fl=otl->features; fl!=NULL; fl=fl->next ) if ( fl->featuretag==feats[i] ) {
+ for ( sl=fl->scripts; sl!=NULL; sl=sl->next ) if ( sl->script==scripts[s] ) {
+ for ( subl=0; subl<sl->lang_cnt; ++subl ) {
+ uint32 lang = subl<MAX_LANG ? sl->langs[subl] : sl->morelangs[subl-MAX_LANG];
+ if ( lang==langs[l] )
+ goto found;
+ }
+ }
+ }
+ found:
+ if ( fl!=NULL ) {
+ if ( firsts ) {
+ fprintf( out, "\n script %c%c%c%c;\n",
+ scripts[s]>>24, scripts[s]>>16, scripts[s]>>8, scripts[s] );
+ firsts = false;
+ }
+ if ( first ) {
+ fprintf( out, " language %c%c%c%c %s;\n",
+ langs[l]>>24, langs[l]>>16, langs[l]>>8, langs[l],
+ langs[l]!=DEFAULT_LANG ? "exclude_dflt" : "" );
+ first = false;
+ }
+ fprintf( out, " lookup %s;\n", lookupname(otl));
+ }
+ }
+ }
+ free(langs);
+ }
+ fprintf( out, "} %s%c%c%c%c;\n",
+ feats[i]==CHR('m','a','r','k') ? "\\" : "",
+ feats[i]>>24, feats[i]>>16, feats[i]>>8, feats[i] );
+ }
+ free(scripts);
+ }
+ free(feats);
+ }
+}
+
+/* Sadly the lookup names I generate are often not distinguishable in the */
+/* first 31 characters. So provide a fall back mechanism if we get a name */
+/* collision */
+static void preparenames(SplineFont *sf) {
+ int isgpos, cnt, try, i;
+ OTLookup *otl;
+ char **names, *name;
+ char namebuf[32], featbuf[8], scriptbuf[8], *feat, *script;
+ struct scriptlanglist *sl;
+
+ cnt = 0;
+ for ( isgpos=0; isgpos<2; ++isgpos )
+ for ( otl=isgpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl=otl->next )
+ ++cnt;
+ if ( cnt==0 )
+return;
+ names = galloc(cnt*sizeof(char *));
+ featbuf[4] = scriptbuf[4] = 0;
+ cnt = 0;
+ for ( isgpos=0; isgpos<2; ++isgpos ) {
+ for ( otl=isgpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl=otl->next ) {
+ name = lookupname(otl);
+ for ( try=0; ; ++try ) {
+ for ( i=0; i<cnt; ++i )
+ if ( strcmp(name,names[i])==0 )
+ break;
+ if ( i==cnt ) {
+ /* It's a unique name, use it */
+ otl->tempname = names[cnt++] = copy(name);
+ break;
+ }
+
+ feat = ""; script = "";
+ if ( otl->features!=NULL ) {
+ featbuf[0] = otl->features->featuretag>>24;
+ featbuf[1] = otl->features->featuretag>>16;
+ featbuf[2] = otl->features->featuretag>>8;
+ featbuf[3] = otl->features->featuretag&0xff;
+ feat = featbuf;
+ for ( sl=otl->features->scripts; sl!=NULL; sl=sl->next ) {
+ if ( sl->script!=DEFAULT_SCRIPT ) {
+ scriptbuf[0] = sl->script>>24;
+ scriptbuf[1] = sl->script>>16;
+ scriptbuf[2] = sl->script>>8;
+ scriptbuf[3] = sl->script&0xff;
+ script = scriptbuf;
+ break;
+ }
+ }
+ }
+ sprintf( namebuf, "%s_%s_%s%s_%d", isgpos ? "pos" : "sub",
+ otl->lookup_type== gsub_single ? "single" :
+ otl->lookup_type== gsub_multiple ? "mult" :
+ otl->lookup_type== gsub_alternate ? "alt" :
+ otl->lookup_type== gsub_ligature ? "ligature" :
+ otl->lookup_type== gsub_context ? "context" :
+ otl->lookup_type== gsub_contextchain ? "chain" :
+ otl->lookup_type== gsub_reversecchain ? "reversecc" :
+ otl->lookup_type== gpos_single ? "single" :
+ otl->lookup_type== gpos_pair ? "pair" :
+ otl->lookup_type== gpos_cursive ? "cursive" :
+ otl->lookup_type== gpos_mark2base ? "mark2base" :
+ otl->lookup_type== gpos_mark2ligature ? "mark2liga" :
+ otl->lookup_type== gpos_mark2mark ? "mark2mark" :
+ otl->lookup_type== gpos_context ? "context" :
+ otl->lookup_type== gpos_contextchain ? "chain" :
+ "unknown",
+ feat, script, try++ );
+ name = namebuf;
+ }
+ }
+ }
+ free(names);
+}
+
+static void cleanupnames(SplineFont *sf) {
+ int isgpos;
+ OTLookup *otl;
+
+ for ( isgpos=0; isgpos<2; ++isgpos )
+ for ( otl=isgpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl=otl->next ) {
+ free( otl->tempname );
+ otl->tempname = NULL;
+ }
+}
+#endif
+
+void FeatDumpFontLookups(FILE *out,SplineFont *sf) {
+#ifndef LUA_FF_LIB
+ if ( sf->cidmaster!=NULL ) sf=sf->cidmaster;
+
+ untick_lookups(sf);
+ preparenames(sf);
+ dump_gsubgpos(out,sf);
+ dump_gdef(out,sf);
+ cleanupnames(sf);
+#endif
+}
+
+
+/* ************************************************************************** */
+/* ******************************* Parse feat ******************************* */
+/* ************************************************************************** */
+
+#include <gfile.h>
+
+struct nameid {
+ uint16 strid;
+ uint16 platform, specific, language;
+ char *utf8_str;
+ struct nameid *next;
+};
+
+struct tablekeywords {
+ char *name;
+ int size; /* 1=>byte, 2=>short, 4=>int32 */
+ int cnt; /* normally 1, but 10 for panose, -1 for infinite */
+ int offset; /* -1 => parse but don't store */
+};
+
+struct tablevalues {
+ int index; /* in the table key structure above */
+ int value;
+ uint8 panose_vals[10];
+ struct tablevalues *next;
+};
+
+enum feat_type { ft_lookup_start, ft_lookup_end, ft_feat_start, ft_feat_end,
+ ft_table, ft_names, ft_gdefclasses, ft_lcaret, ft_tablekeys,
+ ft_sizeparams,
+ ft_subtable, ft_script, ft_lang, ft_lookupflags, ft_langsys,
+ ft_pst, ft_pstclass, ft_fpst, ft_ap, ft_lookup_ref };
+struct feat_item {
+ uint16 /* enum feat_type */ type;
+ uint8 ticked;
+ union {
+ SplineChar *sc; /* For psts, aps */
+ char *class; /* List of glyph names for kerning by class, lcarets */
+ char *lookup_name; /* for lookup_start/ lookup_ref */
+ uint32 tag; /* for feature/script/lang tag */
+ int *params; /* size params */
+ struct tablekeywords *offsets;
+ char **gdef_classes;
+ } u1;
+ union {
+ PST *pst;
+ /* For kerning by class we'll generate an invalid pst with the class as the "paired" field */
+ FPST *fpst;
+ AnchorPoint *ap;
+ int lookupflags;
+ struct scriptlanglist *sl; /* Default langsyses for features/langsys */
+ int exclude_dflt; /* for lang tags */
+ struct nameid *names; /* size params */
+ struct tablevalues *tvals;
+ int16 *lcaret;
+ } u2;
+ char *mark_class; /* For mark to base-ligature-mark, names of all marks which attach to this anchor */
+ struct feat_item *next, *lookup_next;
+};
+
+static int strcmpD(const void *_str1, const void *_str2) {
+ const char *str1 = *(const char **)_str1, *str2 = *(const char **) _str2;
+return( strcmp(str1,str2));
+}
+
+/* Ok, somes strings overlap so can't use normal strcpy */
+static char *mystrcpy(char *str1, const char *str2) {
+ int ch;
+ char *dest = str1;
+
+ while ( (ch = *str2++)!='\0' )
+ *str1++ = ch;
+ *str1 = '\0';
+return( dest );
+}
+
+/* Order glyph classes just so we can do a simple string compare to check for */
+/* class match. So the order doesn't really matter, just so it is consistent */
+static char *fea_canonicalClassOrder(char *class) {
+ int name_cnt, i;
+ char *pt, **names, *cpt;
+ char *temp = copy(class);
+
+ name_cnt = 0;
+ for ( pt = class; ; ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ for ( ; *pt!=' ' && *pt!='\0'; ++pt );
+ ++name_cnt;
+ }
+
+ names = galloc(name_cnt*sizeof(char *));
+ name_cnt = 0;
+ for ( pt = temp; ; ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ for ( names[name_cnt++]=pt ; *pt!=' ' && *pt!='\0'; ++pt );
+ if ( *pt==' ' )
+ *pt++ = '\0';
+ }
+
+ qsort(names,name_cnt,sizeof(char *),strcmpD);
+ cpt = class;
+ for ( i=0; i<name_cnt; ++i ) {
+ strcpy(cpt,names[i]);
+ cpt += strlen(cpt);
+ *cpt++ = ' ';
+ }
+ if ( name_cnt!=0 )
+ cpt[-1] = '\0';
+ free(names);
+ free(temp);
+
+return( class );
+}
+
+static int fea_classesIntersect(char *class1, char *class2) {
+ char *pt1, *start1, *pt2, *start2;
+ int ch1, ch2;
+
+ for ( pt1=class1 ; ; ) {
+ while ( *pt1==' ' ) ++pt1;
+ if ( *pt1=='\0' )
+return( 0 );
+ for ( start1 = pt1; *pt1!=' ' && *pt1!='\0'; ++pt1 );
+ ch1 = *pt1; *pt1 = '\0';
+ for ( pt2=class2 ; ; ) {
+ while ( *pt2==' ' ) ++pt2;
+ if ( *pt2=='\0' )
+ break;
+ for ( start2 = pt2; *pt2!=' ' && *pt2!='\0'; ++pt2 );
+ ch2 = *pt2; *pt2 = '\0';
+ if ( strcmp(start1,start2)==0 ) {
+ *pt2 = ch2; *pt1 = ch1;
+return( 1 );
+ }
+ *pt2 = ch2;
+ }
+ *pt1 = ch1;
+ }
+}
+
+static char *fea_classesSplit(char *class1, char *class2) {
+ char *pt1, *start1, *pt2, *start2;
+ int ch1, ch2;
+ int len = strlen(class1), len2 = strlen(class2);
+ char *intersection, *ipt;
+
+ if ( len2>len ) len = len2;
+ intersection = ipt = galloc(len2+1);
+
+ for ( pt1=class1 ; ; ) {
+ while ( *pt1==' ' ) ++pt1;
+ if ( *pt1=='\0' )
+ break;
+ for ( start1 = pt1; *pt1!=' ' && *pt1!='\0'; ++pt1 );
+ ch1 = *pt1; *pt1 = '\0';
+ for ( pt2=class2 ; ; ) {
+ while ( *pt2==' ' ) ++pt2;
+ if ( *pt2=='\0' )
+ break;
+ for ( start2 = pt2; *pt2!=' ' && *pt2!='\0'; ++pt2 );
+ ch2 = *pt2; *pt2 = '\0';
+ if ( strcmp(start1,start2)==0 ) {
+ /* Here's a glyph name in both classes. Remove it from each */
+ /* and add to the new intersection class */
+ strcpy(ipt,start1);
+ ipt += strlen(ipt);
+ *ipt++ = ' ';
+ *pt2 = ch2; *pt1 = ch1;
+ while ( *pt2==' ' ) ++pt2;
+ while ( *pt1==' ' ) ++pt1;
+ mystrcpy(start1,pt1); ch1 = *pt1;
+ mystrcpy(start2,pt2);
+ break;
+ }
+ *pt2 = ch2;
+ }
+ *pt1 = ch1;
+ }
+ if ( ipt!=intersection )
+ ipt[-1] = '\0';
+ else
+ *intersection = '\0'; /* Should never happen (we only call this if there is one) */
+return( intersection );
+}
+
+#define MAXT 40
+#define MAXI 5
+struct parseState {
+ char tokbuf[MAXT+1];
+ long value;
+ enum toktype { tk_name, tk_class, tk_int, tk_char, tk_cid, tk_eof,
+/* keywords */
+ tk_firstkey,
+ tk_anchor=tk_firstkey, tk_anonymous, tk_by, tk_caret, tk_cursive, tk_device,
+ tk_enumerate, tk_excludeDFLT, tk_exclude_dflt, tk_feature, tk_from,
+ tk_ignore, tk_ignoreDFLT, tk_ignoredflt, tk_IgnoreBaseGlyphs,
+ tk_IgnoreLigatures, tk_IgnoreMarks, tk_include, tk_includeDFLT,
+ tk_include_dflt, tk_language, tk_languagesystem, tk_lookup,
+ tk_lookupflag, tk_mark, tk_nameid, tk_NULL, tk_parameters, tk_position,
+ tk_required, tk_RightToLeft, tk_script, tk_substitute, tk_subtable,
+ tk_table, tk_useExtension
+ } type;
+ uint32 tag;
+ int could_be_tag;
+ FILE *inlist[MAXI];
+ int inc_depth;
+ int line[MAXI];
+ char *filename[MAXI];
+ int err_count;
+ unsigned int warned_about_not_cid: 1;
+ unsigned int lookup_in_sf_warned: 1;
+ unsigned int in_vkrn: 1;
+ unsigned int backedup: 1;
+ unsigned int skipping: 1;
+ SplineFont *sf;
+ struct scriptlanglist *def_langsyses;
+ struct glyphclasses { char *classname, *glyphs; struct glyphclasses *next; } *classes;
+ struct feat_item *sofar;
+ int base; /* normally numbers are base 10, but in the case of languages in stringids, they can be octal or hex */
+ OTLookup *created, *last; /* Ordered, but not sorted into GSUB, GPOS yet */
+ AnchorClass *accreated;
+};
+
+static struct keywords {
+ char *name;
+ enum toktype tok;
+} fea_keywords[] = {
+/* list must be in toktype order */
+ { "name", tk_name }, { "glyphclass", tk_class }, { "integer", tk_int },
+ { "random character", tk_char}, { "cid", tk_cid }, { "EOF", tk_eof },
+/* keywords now */
+ { "anchor", tk_anchor },
+ { "anonymous", tk_anonymous },
+ { "by", tk_by },
+ { "caret", tk_caret },
+ { "cursive", tk_cursive },
+ { "device", tk_device },
+ { "enumerate", tk_enumerate },
+ { "excludeDFLT", tk_excludeDFLT },
+ { "exclude_dflt", tk_exclude_dflt },
+ { "feature", tk_feature },
+ { "from", tk_from },
+ { "ignore", tk_ignore },
+ { "IgnoreBaseGlyphs", tk_IgnoreBaseGlyphs },
+ { "IgnoreLigatures", tk_IgnoreLigatures },
+ { "IgnoreMarks", tk_IgnoreMarks },
+ { "include", tk_include },
+ { "includeDFLT", tk_includeDFLT },
+ { "include_dflt", tk_include_dflt },
+ { "language", tk_language },
+ { "languagesystem", tk_languagesystem },
+ { "lookup", tk_lookup },
+ { "lookupflag", tk_lookupflag },
+ { "mark", tk_mark },
+ { "nameid", tk_nameid },
+ { "NULL", tk_NULL },
+ { "parameters", tk_parameters },
+ { "position", tk_position },
+ { "required", tk_required },
+ { "RightToLeft", tk_RightToLeft },
+ { "script", tk_script },
+ { "substitute", tk_substitute },
+ { "subtable", tk_subtable },
+ { "table", tk_table },
+ { "useExtension", tk_useExtension },
+/* synonyms */
+ { "sub", tk_substitute },
+ { "pos", tk_position },
+ { "enum", tk_enumerate },
+ { "anon", tk_anonymous },
+ {NULL}
+};
+
+static struct tablekeywords hhead_keys[] = {
+ { "CaretOffset", sizeof(short), 1, -1 }, /* Don't even know what this is! */
+ { "Ascender", sizeof(short), 1, offsetof(struct pfminfo,hhead_ascent)+offsetof(SplineFont,pfminfo) },
+ { "Descender", sizeof(short), 1, offsetof(struct pfminfo,hhead_descent)+offsetof(SplineFont,pfminfo) },
+ { "LineGap", sizeof(short), 1, offsetof(struct pfminfo,linegap)+offsetof(SplineFont,pfminfo) },
+ {NULL}
+};
+
+static struct tablekeywords vhead_keys[] = {
+ { "VertTypoAscender", sizeof(short), 1, -1 },
+ { "VertTypoDescender", sizeof(short), 1, -1 },
+ { "VertTypoLineGap", sizeof(short), 1, offsetof(struct pfminfo,vlinegap)+offsetof(SplineFont,pfminfo) },
+ {NULL}
+};
+
+static struct tablekeywords os2_keys[] = {
+ { "FSType", sizeof(short), 1, offsetof(struct pfminfo,fstype)+offsetof(SplineFont,pfminfo) },
+ { "Panose", sizeof(uint8), 10, offsetof(struct pfminfo,panose)+offsetof(SplineFont,pfminfo) },
+ { "UnicodeRange", sizeof(short), -1, -1 },
+ { "CodePageRange", sizeof(short), -1, -1 },
+ { "TypoAscender", sizeof(short), 1, offsetof(struct pfminfo,os2_typoascent)+offsetof(SplineFont,pfminfo) },
+ { "TypoDescender", sizeof(short), 1, offsetof(struct pfminfo,os2_typodescent)+offsetof(SplineFont,pfminfo) },
+ { "TypoLineGap", sizeof(short), 1, offsetof(struct pfminfo,os2_typolinegap)+offsetof(SplineFont,pfminfo) },
+ { "winAscent", sizeof(short), 1, offsetof(struct pfminfo,os2_winascent)+offsetof(SplineFont,pfminfo) },
+ { "winDescent", sizeof(short), 1, offsetof(struct pfminfo,os2_windescent)+offsetof(SplineFont,pfminfo) },
+ { "XHeight", sizeof(short), 1, -1 },
+ { "CapHeight", sizeof(short), 1, -1 },
+ { "WeightClass", sizeof(short), 1, offsetof(struct pfminfo,weight)+offsetof(SplineFont,pfminfo) },
+ { "WidthClass", sizeof(short), 1, offsetof(struct pfminfo,width)+offsetof(SplineFont,pfminfo) },
+ { "Vendor", sizeof(short), 1, offsetof(struct pfminfo,os2_vendor)+offsetof(SplineFont,pfminfo) },
+ {NULL}
+};
+
+
+static void fea_ParseTok(struct parseState *tok);
+
+static void fea_handle_include(struct parseState *tok) {
+ FILE *in;
+ char namebuf[1025], *pt, *filename;
+ int ch;
+
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_char || tok->tokbuf[0]!='(' ) {
+ LogError(_("Unparseable include on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+return;
+ }
+
+ in = tok->inlist[tok->inc_depth];
+ ch = getc(in);
+ while ( Isspace(ch))
+ ch = getc(in);
+ pt = namebuf;
+ while ( ch!=EOF && ch!=')' && pt<namebuf+sizeof(namebuf)-1 ) {
+ *pt++ = ch;
+ ch = getc(in);
+ }
+ if ( ch!=EOF && ch!=')' ) {
+ while ( ch!=EOF && ch!=')' )
+ ch = getc(in);
+ LogError(_("Include filename too long on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ while ( pt>=namebuf+1 && Isspace(pt[-1]) )
+ --pt;
+ *pt = '\0';
+ if ( ch!=')' ) {
+ if ( ch==EOF )
+ LogError(_("End of file in include on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ else
+ LogError(_("Missing close parenthesis in include on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+return;
+ }
+
+ if ( pt==namebuf ) {
+ LogError(_("No filename specified in include on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+return;
+ }
+
+ if ( tok->inc_depth>=MAXI-1 ) {
+ LogError(_("Includes nested too deeply on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+return;
+ }
+
+ if ( *namebuf=='/' ||
+ ( pt = strrchr(tok->filename[tok->inc_depth],'/') )==NULL )
+ filename=copy(namebuf);
+ else {
+ *pt = '\0';
+ filename = GFileAppendFile(tok->filename[tok->inc_depth],namebuf,false);
+ *pt = '/';
+ }
+ in = fopen(filename,"r");
+ if ( in==NULL ) {
+ LogError(_("Could not open include file (%s) on line %d of %s"),
+ filename, tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ free(filename);
+return;
+ }
+
+ ++tok->inc_depth;
+ tok->filename[tok->inc_depth] = filename;
+ tok->inlist[tok->inc_depth] = in;
+ tok->line[tok->inc_depth] = 1;
+}
+
+static void fea_ParseTok(struct parseState *tok) {
+ FILE *in = tok->inlist[tok->inc_depth];
+ int ch, peekch;
+ char *pt, *start;
+
+ if ( tok->backedup ) {
+ tok->backedup = false;
+return;
+ }
+
+ peekch = 0;
+ skip_whitespace:
+ ch = getc(in);
+ while ( Isspace(ch) || ch=='#' ) {
+ if ( ch=='#' )
+ while ( (ch=getc(in))!=EOF && ch!='\n' && ch!='\r' );
+ if ( ch=='\n' || ch=='\r' ) {
+ if ( ch=='\r' ) {
+ ch = getc(in);
+ if ( ch!='\n' )
+ ungetc(ch,in);
+ }
+ ++tok->line[tok->inc_depth];
+ }
+ ch = getc(in);
+ }
+
+ tok->could_be_tag = 0;
+ if ( ch==EOF ) {
+ if ( tok->inc_depth>0 ) {
+ fclose(tok->inlist[tok->inc_depth]);
+ free(tok->filename[tok->inc_depth]);
+ in = tok->inlist[--tok->inc_depth];
+ goto skip_whitespace;
+ }
+ tok->type = tk_eof;
+ strcpy(tok->tokbuf,"EOF");
+return;
+ }
+
+ start = pt = tok->tokbuf;
+ if ( ch=='\\' ) {
+ peekch=getc(in);
+ ungetc(peekch,in);
+ }
+
+ if ( Isdigit(ch) || ch=='-' || ch=='+' || (ch=='\\' && Isdigit(peekch)) ) {
+ tok->type = tk_int;
+ if ( ch=='-' || ch=='+' ) {
+ if ( ch=='-' ) {
+ *pt++ = ch;
+ start = pt;
+ }
+ ch = getc(in);
+ } else if ( ch=='\\' ) {
+ ch = getc(in);
+ tok->type = tk_cid;
+ }
+ while ( (Isdigit( ch ) ||
+ (tok->base==0 && (ch=='x' || ch=='X' || (ch>='a' && ch<='f') || (ch>='A' && ch<='F'))))
+ && pt<tok->tokbuf+15 ) {
+ *pt++ = ch;
+ ch = getc(in);
+ }
+ if ( Isdigit(ch)) {
+ LogError(_("Number too long on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else if ( pt==start ) {
+ LogError(_("Missing number on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ ungetc(ch,in);
+ *pt = '\0';
+ tok->value = strtol(tok->tokbuf,NULL,tok->base);
+return;
+ } else if ( ch=='@' || ch=='_' || ch=='\\' || Isalnum(ch)) { /* Names can't start with dot */
+ int check_keywords = true;
+ tok->type = tk_name;
+ if ( ch=='@' ) {
+ tok->type = tk_class;
+ *pt++ = ch;
+ start = pt;
+ ch = getc(in);
+ check_keywords = false;
+ } else if ( ch=='\\' ) {
+ ch = getc(in);
+ check_keywords = false;
+ }
+ while (( Isalnum(ch) || ch=='_' || ch=='.' ) && pt<start+31 ) {
+ *pt++ = ch;
+ ch = getc(in);
+ }
+ *pt = '\0';
+ ungetc(ch,in);
+ if ( Isalnum(ch) || ch=='_' || ch=='.' ) {
+ LogError(_("Name too long on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else if ( pt==start ) {
+ LogError(_("Missing name on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+
+ if ( check_keywords ) {
+ int i;
+ for ( i=tk_firstkey; fea_keywords[i].name!=NULL; ++i ) {
+ if ( strcmp(fea_keywords[i].name,tok->tokbuf)==0 ) {
+ tok->type = fea_keywords[i].tok;
+ break;
+ }
+ }
+ if ( tok->type==tk_include )
+ fea_handle_include(tok);
+ }
+ if ( tok->type==tk_name && pt-tok->tokbuf<=4 && pt!=tok->tokbuf ) {
+ unsigned char tag[4];
+ tok->could_be_tag = true;
+ memset(tag,' ',4);
+ tag[0] = tok->tokbuf[0];
+ if ( tok->tokbuf[1]!='\0' ) {
+ tag[1] = tok->tokbuf[1];
+ if ( tok->tokbuf[2]!='\0' ) {
+ tag[2] = tok->tokbuf[2];
+ if ( tok->tokbuf[3]!='\0' )
+ tag[3] = tok->tokbuf[3];
+ }
+ }
+ tok->tag = (tag[0]<<24) | (tag[1]<<16) | (tag[2]<<8) | tag[3];
+ }
+ } else {
+ /* I've already handled the special characters # @ and \ */
+ /* so don't treat them as errors here, if they occur they will be out of context */
+ if ( ch==';' || ch==',' || ch=='-' || ch=='=' || ch=='\'' || ch=='"' ||
+ ch=='{' || ch=='}' ||
+ ch=='[' || ch==']' ||
+ ch=='<' || ch=='>' ||
+ ch=='(' || ch==')' ) {
+ tok->type = tk_char;
+ tok->tokbuf[0] = ch;
+ tok->tokbuf[1] = '\0';
+ } else {
+ if ( !tok->skipping ) {
+ LogError(_("Unexpected character (0x%02X) on line %d of %s"), ch, tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ goto skip_whitespace;
+ }
+ }
+}
+
+static void fea_ParseTag(struct parseState *tok) {
+ /* The tag used for OS/2 doesn't get parsed properly */
+ /* So if we know we are looking for a tag do some fixups */
+
+ fea_ParseTok(tok);
+ if ( tok->type==tk_name && tok->could_be_tag &&
+ tok->tag==CHR('O','S',' ',' ') ) {
+ FILE *in = tok->inlist[tok->inc_depth];
+ int ch;
+ ch = getc(in);
+ if ( ch=='/' ) {
+ ch = getc(in);
+ if ( ch=='2' ) {
+ tok->tag = CHR('O','S','/','2');
+ } else {
+ tok->tag = CHR('O','S','/',' ');
+ ungetc(ch,in);
+ }
+ } else
+ ungetc(ch,in);
+ }
+}
+
+static void fea_UnParseTok(struct parseState *tok) {
+ tok->backedup = true;
+}
+
+static int fea_ParseDeciPoints(struct parseState *tok) {
+ /* When parsing size features floating point numbers are allowed */
+ /* but they should be converted to ints by multiplying by 10 */
+ /* (not my convention) */
+
+ fea_ParseTok(tok);
+ if ( tok->type==tk_int ) {
+ FILE *in = tok->inlist[tok->inc_depth];
+ char *pt = tok->tokbuf + strlen(tok->tokbuf);
+ int ch;
+ ch = getc(in);
+ if ( ch=='.' ) {
+ *pt++ = ch;
+ while ( (ch = getc(in))!=EOF && Isdigit(ch)) {
+ if ( pt<tok->tokbuf+sizeof(tok->tokbuf)-1 )
+ *pt++ = ch;
+ }
+ *pt = '\0';
+ tok->value = rint(strtod(tok->tokbuf,NULL)*10.0);
+ }
+ if ( ch!=EOF )
+ ungetc(ch,in);
+ } else {
+ LogError(_("Expected '%s' on line %d of %s"), fea_keywords[tk_int],
+ tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ tok->value = -1;
+ }
+return( tok->value );
+}
+
+static void fea_TokenMustBe(struct parseState *tok, enum toktype type, int ch) {
+ fea_ParseTok(tok);
+ if ( type==tk_char && (tok->type!=type || tok->tokbuf[0]!=ch) ) {
+ LogError(_("Expected '%c' on line %d of %s"), ch, tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else if ( type!=tk_char && tok->type!=type ) {
+ LogError(_("Expected '%s' on line %d of %s"), fea_keywords[type],
+ tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+}
+
+static void fea_skip_to_semi(struct parseState *tok) {
+ int nest=0;
+
+ while ( tok->type!=tk_char || tok->tokbuf[0]!=';' || nest>0 ) {
+ fea_ParseTok(tok);
+ if ( tok->type==tk_char ) {
+ if ( tok->tokbuf[0]=='{' ) ++nest;
+ else if ( tok->tokbuf[0]=='}' ) --nest;
+ if ( nest<0 )
+ break;
+ }
+ if ( tok->type==tk_eof )
+ break;
+ }
+}
+
+static void fea_skip_to_close_curly(struct parseState *tok) {
+ int nest=0;
+
+ tok->skipping = true;
+ /* The table blocks have slightly different syntaxes and can take strings */
+ /* and floating point numbers. So don't complain about unknown chars when */
+ /* in a table (that's skipping) */
+ while ( tok->type!=tk_char || tok->tokbuf[0]!='}' || nest>0 ) {
+ fea_ParseTok(tok);
+ if ( tok->type==tk_char ) {
+ if ( tok->tokbuf[0]=='{' ) ++nest;
+ else if ( tok->tokbuf[0]=='}' ) --nest;
+ }
+ if ( tok->type==tk_eof )
+ break;
+ }
+ tok->skipping = false;
+}
+
+static void fea_now_semi(struct parseState *tok) {
+ if ( tok->type!=tk_char || tok->tokbuf[0]!=';' ) {
+ LogError(_("Expected ';' at statement end on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ fea_skip_to_semi(tok);
+ ++tok->err_count;
+return;
+ }
+}
+
+static void fea_end_statement(struct parseState *tok) {
+ fea_ParseTok(tok);
+ fea_now_semi(tok);
+}
+
+static struct glyphclasses *fea_lookup_class(struct parseState *tok,char *classname) {
+ struct glyphclasses *test;
+
+ for ( test=tok->classes; test!=NULL; test=test->next ) {
+ if ( strcmp(classname,test->classname)==0 )
+return( test );
+ }
+return( NULL );
+}
+
+static char *fea_lookup_class_complain(struct parseState *tok,char *classname) {
+ struct glyphclasses *test;
+
+ for ( test=tok->classes; test!=NULL; test=test->next ) {
+ if ( strcmp(classname,test->classname)==0 )
+return( copy( test->glyphs) );
+ }
+ LogError(_("Use of undefined glyph class, %s, on line %d of %s"), classname, tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+return( NULL );
+}
+
+static void fea_AddClassDef(struct parseState *tok,char *classname,char *contents) {
+ struct glyphclasses *test;
+
+ test = fea_lookup_class(tok,classname);
+ if ( test==NULL ) {
+ test=chunkalloc(sizeof(struct glyphclasses));
+ test->classname = classname;
+ test->next = tok->classes;
+ tok->classes = test;
+ } else {
+ free(classname);
+ free(test->glyphs);
+ }
+ test->glyphs = contents;
+}
+
+static int fea_AddGlyphs(char **_glyphs, int *_max, int cnt, char *contents ) {
+ int len = strlen(contents);
+ char *glyphs = *_glyphs;
+ /* Append a glyph name, etc. to a glyph class */
+
+ if ( glyphs==NULL ) {
+ glyphs = copy(contents);
+ cnt = *_max = len;
+ } else {
+ if ( *_max-cnt <= len+1 )
+ glyphs = grealloc(glyphs,(*_max+=200+len+1)+1);
+ glyphs[cnt++] = ' ';
+ strcpy(glyphs+cnt,contents);
+ cnt += strlen(contents);
+ }
+ free(contents);
+ *_glyphs = glyphs;
+return( cnt );
+}
+
+static char *fea_cid_validate(struct parseState *tok,int cid) {
+ int i, max;
+ SplineFont *maxsf;
+ SplineChar *sc;
+ EncMap *map;
+
+ if ( tok->sf->subfontcnt==0 ) {
+ if ( !tok->warned_about_not_cid ) {
+ LogError(_("Reference to a CID in a non-CID-keyed font on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ tok->warned_about_not_cid = true;
+ }
+ ++tok->err_count;
+return(NULL);
+ }
+ max = 0; maxsf = NULL;
+ for ( i=0; i<tok->sf->subfontcnt; ++i ) {
+ SplineFont *sub = tok->sf->subfonts[i];
+ if ( cid<sub->glyphcnt && sub->glyphs[cid]!=NULL )
+return( sub->glyphs[cid]->name );
+ if ( sub->glyphcnt>max ) {
+ max = sub->glyphcnt;
+ maxsf = sub;
+ }
+ }
+ /* Not defined, try to create it */
+ if ( maxsf==NULL ) /* No subfonts */
+return( NULL );
+ if ( cid>=maxsf->glyphcnt ) {
+ struct cidmap *cidmap = FindCidMap(tok->sf->cidregistry,tok->sf->ordering,tok->sf->supplement,tok->sf);
+ if ( cidmap==NULL || cid>=MaxCID(cidmap) )
+return( NULL );
+ SFExpandGlyphCount(maxsf,MaxCID(cidmap));
+ }
+ if ( cid>=maxsf->glyphcnt )
+return( NULL );
+ map = EncMap1to1(maxsf->glyphcnt);
+ sc = SFMakeChar(maxsf,map,cid);
+ EncMapFree(map);
+ if ( sc==NULL )
+return( NULL );
+return( copy( sc->name ));
+}
+
+static SplineChar *fea_glyphname_get(struct parseState *tok,char *name) {
+ SplineFont *sf = tok->sf;
+ SplineChar *sc = SFGetChar(sf,-1,name);
+ int gid;
+#ifndef LUA_FF_LIB
+ int enc;
+#endif
+
+ if ( sf->subfontcnt!=0 ) {
+ LogError(_("Reference to a glyph name in a CID-keyed font on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+return(sc);
+ }
+
+ if ( sc!=NULL )
+return( sc );
+#ifndef LUA_FF_LIB
+ enc = SFFindSlot(sf,sf->fv->map,-1,name);
+ if ( enc!=-1 ) {
+ sc = SFMakeChar(sf,sf->fv->map,enc);
+ if ( sc!=NULL ) {
+ sc->widthset = true;
+ free(sc->name);
+ sc->name = copy(name);
+ }
+return( sc );
+ }
+#endif
+
+ for ( gid=sf->glyphcnt-1; gid>=0; --gid ) if ( (sc=sf->glyphs[gid])!=NULL ) {
+ if ( strcmp(sc->name,name)==0 )
+return( sc );
+ }
+
+/* Don't encode it (not in current encoding), just add it, so we needn't */
+/* mess with maps or selections */
+ SFExpandGlyphCount(sf,sf->glyphcnt+1);
+ sc = SplineCharCreate();
+ sc->name = copy(name);
+ sc->unicodeenc = UniFromName(name,ui_none,&custom);
+ sc->parent = sf;
+ sc->vwidth = (sf->ascent+sf->descent);
+ sc->width = 6*sc->vwidth/10;
+ sc->widthset = true; /* So we don't lose the glyph */
+ sc->orig_pos = sf->glyphcnt-1;
+ sf->glyphs[sc->orig_pos] = sc;
+return( sc );
+}
+
+static char *fea_glyphname_validate(struct parseState *tok,char *name) {
+ SplineChar *sc = fea_glyphname_get(tok,name);
+
+ if ( sc==NULL )
+return( NULL );
+
+return( copy( sc->name ));
+}
+
+static char *fea_ParseGlyphClass(struct parseState *tok) {
+ char *glyphs = NULL;
+
+ if ( tok->type==tk_class ) {
+ glyphs = fea_lookup_class_complain(tok,tok->tokbuf);
+ } else if ( tok->type!=tk_char || tok->tokbuf[0]!='[' ) {
+ LogError(_("Expected '[' in glyph class definition on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+return(NULL);
+ } else {
+ char *contents;
+ int cnt=0, max=0;
+ int last_val, range_type, range_len;
+ char last_glyph[MAXT+1];
+ char *pt1, *start1, *pt2, *start2;
+ int v1, v2;
+
+ start2 = NULL; range_len = 0; last_val =0 ; contents = NULL;
+ forever {
+ fea_ParseTok(tok);
+ if ( tok->type==tk_char && tok->tokbuf[0]==']' )
+ break;
+ if ( tok->type==tk_class ) {
+ contents = fea_lookup_class_complain(tok,tok->tokbuf);
+ last_val=-1; last_glyph[0] = '\0';
+ } else if ( tok->type==tk_cid ) {
+ last_val = tok->value; last_glyph[0] = '\0';
+ contents = fea_cid_validate(tok,tok->value);
+ } else if ( tok->type==tk_name ) {
+ strcpy(last_glyph,tok->tokbuf); last_val = -1;
+ contents = fea_glyphname_validate(tok,tok->tokbuf);
+ } else if ( tok->type==tk_char && tok->tokbuf[0]=='-' ) {
+ fea_ParseTok(tok);
+ if ( last_val!=-1 && tok->type==tk_cid ) {
+ if ( last_val>=tok->value ) {
+ LogError(_("Invalid CID range in glyph class on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ /* Last val has already been added to the class */
+ /* and we'll add the current value later */
+ for ( ++last_val; last_val<tok->value; ++last_val ) {
+ contents = fea_cid_validate(tok,last_val);
+ if ( contents!=NULL )
+ cnt = fea_AddGlyphs(&glyphs,&max,cnt,contents);
+ }
+ contents = fea_cid_validate(tok,tok->value);
+ } else if ( last_glyph[0]!='\0' && tok->type==tk_name ) {
+ range_type=0;
+ if ( strlen(last_glyph)==strlen(tok->tokbuf) &&
+ strcmp(last_glyph,tok->tokbuf)<0 ) {
+ start1=NULL;
+ for ( pt1=last_glyph, pt2=tok->tokbuf;
+ *pt1!='\0'; ++pt1, ++pt2 ) {
+ if ( *pt1!=*pt2 ) {
+ if ( start1!=NULL ) {
+ range_type=0;
+ break;
+ }
+ start1 = pt1; start2 = pt2;
+ if ( !Isdigit(*pt1) || !Isdigit(*pt2))
+ range_type = 1;
+ else {
+ for ( range_len=0; range_len<3 && Isdigit(*pt1) && Isdigit(*pt2);
+ ++range_len, ++pt1, ++pt2 );
+ range_type = 2;
+ --pt1; --pt2;
+ }
+ }
+ }
+ }
+ if ( range_type==0 ) {
+ LogError(_("Invalid glyph name range in glyph class on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else if ( range_type==1 || range_len==1 ) {
+ /* Single letter changes */
+ v1 = *start1; v2 = *start2;
+ for ( ++v1; v1<=v2; ++v1 ) {
+ *start1 = v1;
+ contents = fea_glyphname_validate(tok,tok->tokbuf);
+ if ( v1==v2 )
+ break;
+ if ( contents!=NULL )
+ cnt = fea_AddGlyphs(&glyphs,&max,cnt,contents);
+ }
+ } else {
+ v1 = strtol(start1,NULL,10);
+ v2 = strtol(start2,NULL,10);
+ for ( ++v1; v1<=v2; ++v1 ) {
+ if ( range_len==2 )
+ sprintf( last_glyph, "%.*s%02d%s", start2-tok->tokbuf,
+ tok->tokbuf, v1, start2+2 );
+ else
+ sprintf( last_glyph, "%.*s%03d%s", start2-tok->tokbuf,
+ tok->tokbuf, v1, start2+3 );
+ contents = fea_glyphname_validate(tok,last_glyph);
+ if ( v1==v2 )
+ break;
+ if ( contents!=NULL )
+ cnt = fea_AddGlyphs(&glyphs,&max,cnt,contents);
+ }
+ }
+ } else {
+ LogError(_("Unexpected token in glyph class range on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ if ( tok->type==tk_char && tok->tokbuf[0]==']' )
+ break;
+ }
+ last_val=-1; last_glyph[0] = '\0';
+ } else {
+ LogError(_("Expected glyph name, cid, or class in glyph class definition on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+return(NULL);
+ }
+ if ( contents!=NULL )
+ cnt = fea_AddGlyphs(&glyphs,&max,cnt,contents);
+ }
+ if ( glyphs==NULL )
+ glyphs = copy(""); /* Is it legal to have an empty class? I can't think of any use for one */
+ }
+return( glyphs );
+}
+
+static void fea_ParseLookupFlags(struct parseState *tok) {
+ int val = 0;
+ struct feat_item *item;
+
+ fea_ParseTok(tok);
+ if ( tok->type==tk_int ) {
+ val = tok->value;
+ fea_end_statement(tok);
+ } else {
+ while ( tok->type==tk_RightToLeft || tok->type==tk_IgnoreBaseGlyphs ||
+ tok->type==tk_IgnoreMarks || tok->type==tk_IgnoreLigatures ) {
+ if ( tok->type == tk_RightToLeft )
+ val |= pst_r2l;
+ else if ( tok->type == tk_IgnoreBaseGlyphs )
+ val |= pst_ignorebaseglyphs;
+ else if ( tok->type == tk_IgnoreMarks )
+ val |= pst_ignorecombiningmarks;
+ else if ( tok->type == tk_IgnoreLigatures )
+ val |= pst_ignoreligatures;
+ fea_ParseTok(tok);
+ if ( tok->type == tk_char && tok->tokbuf[0]==';' )
+ break;
+ else if ( tok->type==tk_char && tok->tokbuf[0]!=',' ) {
+ LogError(_("Expected ';' in lookupflags on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+ break;
+ }
+ fea_ParseTok(tok);
+ }
+ if ( tok->type != tk_char || tok->tokbuf[0]!=';' ) {
+ LogError(_("Unexpected token in lookupflags on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+ } else if ( val==0 ) {
+ LogError(_("No flags specified in lookupflags on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ }
+
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_lookupflags;
+ item->u2.lookupflags = val;
+ item->next = tok->sofar;
+ tok->sofar = item;
+}
+
+static void fea_ParseGlyphClassDef(struct parseState *tok) {
+ char *classname = copy(tok->tokbuf );
+ char *contents;
+
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_char || tok->tokbuf[0]!='=' ) {
+ LogError(_("Expected '=' in glyph class definition on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+return;
+ }
+ fea_ParseTok(tok);
+ contents = fea_ParseGlyphClass(tok);
+ if ( contents==NULL ) {
+ fea_skip_to_semi(tok);
+return;
+ }
+ fea_AddClassDef(tok,classname,copy(contents));
+ fea_end_statement(tok);
+}
+
+static void fea_ParseLangSys(struct parseState *tok, int inside_feat) {
+ uint32 script, lang;
+ struct scriptlanglist *sl;
+ int l;
+
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_name || !tok->could_be_tag ) {
+ LogError(_("Expected tag in languagesystem on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+return;
+ }
+ script = tok->tag;
+
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_name || !tok->could_be_tag ) {
+ LogError(_("Expected tag in languagesystem on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+return;
+ }
+ lang = tok->tag;
+
+ for ( sl=tok->def_langsyses; sl!=NULL && sl->script!=script; sl=sl->next );
+ if ( sl==NULL ) {
+ sl = chunkalloc(sizeof(struct scriptlanglist));
+ sl->script = script;
+ sl->next = tok->def_langsyses;
+ tok->def_langsyses = sl;
+ }
+ for ( l=0; l<sl->lang_cnt; ++l ) {
+ uint32 language = l<MAX_LANG ? sl->langs[l] : sl->morelangs[l-MAX_LANG];
+ if ( language==lang )
+ break;
+ }
+ if ( l<sl->lang_cnt )
+ /* Er... this combination is already in the list. I guess that's ok */;
+ else if ( sl->lang_cnt<MAX_LANG )
+ sl->langs[sl->lang_cnt++] = lang;
+ else {
+ sl->morelangs = grealloc(sl->morelangs,(sl->lang_cnt+1)*sizeof(uint32));
+ sl->morelangs[sl->lang_cnt++ - MAX_LANG] = lang;
+ }
+ fea_end_statement(tok);
+
+ if ( inside_feat ) {
+ struct feat_item *item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_langsys;
+ item->u2.sl = SLCopy(tok->def_langsyses);
+ item->next = tok->sofar;
+ tok->sofar = item;
+ }
+}
+
+struct markedglyphs {
+ unsigned int has_marks: 1; /* Are there any marked glyphs in the entire sequence? */
+ unsigned int is_cursive: 1; /* Only in a position sequence */
+ unsigned int is_mark: 1; /* Only in a position sequence/mark keyword=>mark2mark */
+ unsigned int is_name: 1; /* Otherwise a class */
+ unsigned int is_lookup: 1; /* Or a lookup when parsing a subs replacement list */
+ uint16 mark_count; /* 0=>unmarked, 1=>first mark, etc. */
+ char *name_or_class; /* Glyph name / class contents */
+ struct vr *vr; /* A value record. Only in position sequences */
+ int ap_cnt; /* Number of anchor points */
+ AnchorPoint **anchors;
+ char *lookupname;
+ struct markedglyphs *next;
+};
+
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+static void fea_ParseDeviceTable(struct parseState *tok,DeviceTable *adjust)
+#else
+static void fea_ParseDeviceTable(struct parseState *tok)
+#endif
+ {
+ int first = true;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ int min=0, max= -1;
+ int8 values[512];
+
+ memset(values,0,sizeof(values));
+#endif
+
+ fea_TokenMustBe(tok,tk_device,'\0');
+ if ( tok->type!=tk_device )
+return;
+
+ forever {
+ fea_ParseTok(tok);
+ if ( first && tok->type==tk_NULL ) {
+ fea_TokenMustBe(tok,tk_char,'>');
+ break;
+ } else if ( tok->type==tk_char && tok->tokbuf[0]=='>' ) {
+ break;
+ } else if ( tok->type!=tk_int ) {
+ LogError(_("Expected integer in device table on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else {
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ int pixel = tok->value;
+#endif
+ fea_TokenMustBe(tok,tk_int,'\0');
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( pixel>=sizeof(values) || pixel<0 )
+ LogError(_("Pixel size too big in device table on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ else {
+ values[pixel] = tok->value;
+ if ( max==-1 )
+ min=max=pixel;
+ else if ( pixel<min ) min = pixel;
+ else if ( pixel>max ) max = pixel;
+ }
+#endif
+ }
+ first = false;
+ }
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( max!=-1 ) {
+ int i;
+ adjust->first_pixel_size = min;
+ adjust->last_pixel_size = max;
+ adjust->corrections = galloc(max-min+1);
+ for ( i=min; i<=max; ++i )
+ adjust->corrections[i-min] = values[i];
+ }
+#endif
+}
+
+static void fea_ParseCaret(struct parseState *tok) {
+ int val=0;
+
+ fea_TokenMustBe(tok,tk_caret,'\0');
+ if ( tok->type!=tk_caret )
+return;
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_int ) {
+ LogError(_("Expected integer in caret on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else
+ val = tok->value;
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_char || tok->tokbuf[0]!='>' ) {
+ LogError(_("Expected '>' in caret on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ tok->value = val;
+}
+
+static AnchorPoint *fea_ParseAnchor(struct parseState *tok) {
+ AnchorPoint *ap = NULL;
+
+ if ( tok->type==tk_anchor ) {
+ fea_ParseTok(tok);
+ if ( tok->type==tk_NULL )
+ ap = NULL;
+ else if ( tok->type==tk_int ) {
+ ap = chunkalloc(sizeof(AnchorPoint));
+ ap->me.x = tok->value;
+ fea_TokenMustBe(tok,tk_int,'\0');
+ ap->me.y = tok->value;
+ fea_ParseTok(tok);
+ if ( tok->type==tk_int ) {
+ ap->ttf_pt_index = tok->value;
+ ap->has_ttf_pt = true;
+ fea_TokenMustBe(tok,tk_char,'>');
+ } else if ( tok->type==tk_char && tok->tokbuf[0]=='<' ) {
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ fea_ParseDeviceTable(tok,&ap->xadjust);
+ fea_TokenMustBe(tok,tk_char,'<');
+ fea_ParseDeviceTable(tok,&ap->yadjust);
+#else
+ fea_ParseDeviceTable(tok);
+ fea_TokenMustBe(tok,tk_char,'<');
+ fea_ParseDeviceTable(tok);
+#endif
+ fea_TokenMustBe(tok,tk_char,'>');
+ } else if ( tok->type!=tk_char || tok->tokbuf[0]!='>' ) {
+ LogError(_("Expected '>' in anchor on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ } else {
+ LogError(_("Expected integer in anchor on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ } else {
+ LogError(_("Expected 'anchor' keyword in anchor on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+return( ap );
+}
+
+static int fea_findLookup(struct parseState *tok,char *name ) {
+ struct feat_item *feat;
+
+ for ( feat=tok->sofar; feat!=NULL; feat=feat->next ) {
+ if ( feat->type==ft_lookup_start && strcmp(name,feat->u1.lookup_name)==0 )
+return( true );
+ }
+
+ if ( SFFindLookup(tok->sf,name)!=NULL ) {
+ if ( !tok->lookup_in_sf_warned ) {
+ gwwv_post_notice(_("Refers to Font"),_("Reference to a lookup which is not in the feature file but which is in the font, %.50s"), name );
+ tok->lookup_in_sf_warned = true;
+ }
+return( true );
+ }
+
+return( false );
+}
+
+static void fea_ParseBroket(struct parseState *tok,struct markedglyphs *last) {
+ /* We've read the open broket. Might find: value record, anchor, lookup */
+ /* (lookups are my extension) */
+ struct vr *vr;
+
+ fea_ParseTok(tok);
+ if ( tok->type==tk_lookup ) {
+ fea_TokenMustBe(tok,tk_name,'\0');
+ if ( last->mark_count==0 ) {
+ LogError(_("Lookups may only be specified after marked glyphs on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ if ( !fea_findLookup(tok,tok->tokbuf) ) {
+ LogError(_("Lookups must be defined before being used on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else
+ last->lookupname = copy(tok->tokbuf);
+ fea_TokenMustBe(tok,tk_char,'>');
+ } else if ( tok->type==tk_anchor ) {
+ last->anchors = grealloc(last->anchors,(++last->ap_cnt)*sizeof(AnchorPoint *));
+ last->anchors[last->ap_cnt-1] = fea_ParseAnchor(tok);
+ } else if ( tok->type==tk_NULL ) {
+ /* NULL value record. Adobe documents it and doesn't implement it */
+ /* Not sure what it's good for */
+ fea_TokenMustBe(tok,tk_char,'>');
+ } else if ( tok->type==tk_int ) {
+ last->vr = vr = chunkalloc(sizeof( struct vr ));
+ vr->xoff = tok->value;
+ fea_ParseTok(tok);
+ if ( tok->type==tk_char && tok->tokbuf[0]=='>' ) {
+ if ( tok->in_vkrn )
+ vr->v_adv_off = vr->xoff;
+ else
+ vr->h_adv_off = vr->xoff;
+ vr->xoff = 0;
+ } else if ( tok->type!=tk_int ) {
+ LogError(_("Expected integer in value record on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else {
+ vr->yoff = tok->value;
+ fea_TokenMustBe(tok,tk_int,'\0');
+ vr->h_adv_off = tok->value;
+ fea_TokenMustBe(tok,tk_int,'\0');
+ vr->v_adv_off = tok->value;
+ fea_ParseTok(tok);
+ if ( tok->type==tk_char && tok->tokbuf[0]=='<' ) {
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ vr->adjust = chunkalloc(sizeof(struct valdev));
+ fea_ParseDeviceTable(tok,&vr->adjust->xadjust);
+ fea_TokenMustBe(tok,tk_char,'<');
+ fea_ParseDeviceTable(tok,&vr->adjust->yadjust);
+ fea_TokenMustBe(tok,tk_char,'<');
+ fea_ParseDeviceTable(tok,&vr->adjust->xadv);
+ fea_TokenMustBe(tok,tk_char,'<');
+ fea_ParseDeviceTable(tok,&vr->adjust->yadv);
+#else
+ fea_ParseDeviceTable(tok);
+ fea_TokenMustBe(tok,tk_char,'<');
+ fea_ParseDeviceTable(tok);
+ fea_TokenMustBe(tok,tk_char,'<');
+ fea_ParseDeviceTable(tok);
+ fea_TokenMustBe(tok,tk_char,'<');
+ fea_ParseDeviceTable(tok);
+#endif
+ fea_TokenMustBe(tok,tk_char,'>');
+ } else if ( tok->type!=tk_char || tok->tokbuf[0]!='>' ) {
+ LogError(_("Expected '>' in value record on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ }
+ }
+}
+
+static struct markedglyphs *fea_ParseMarkedGlyphs(struct parseState *tok,
+ int is_pos, int allow_marks, int allow_lookups) {
+ int mark_cnt = 0, last_mark=0, is_cursive = false, is_mark=false;
+ struct markedglyphs *head=NULL, *last=NULL, *prev=NULL, *cur;
+ int first = true;
+ char *contents;
+
+ forever {
+ fea_ParseTok(tok);
+ cur = NULL;
+ if ( first && is_pos && tok->type == tk_cursive )
+ is_cursive = true;
+ else if ( first && is_pos && tok->type == tk_mark )
+ is_mark = true;
+ else if ( tok->type==tk_name || tok->type == tk_cid ) {
+ if ( tok->type == tk_name )
+ contents = fea_glyphname_validate(tok,tok->tokbuf);
+ else
+ contents = fea_cid_validate(tok,tok->value);
+ if ( contents!=NULL ) {
+ cur = chunkalloc(sizeof(struct markedglyphs));
+ cur->is_cursive = is_cursive;
+ cur->is_mark = is_mark;
+ cur->is_name = true;
+ cur->name_or_class = contents;
+ }
+ } else if ( tok->type == tk_class || (tok->type==tk_char && tok->tokbuf[0]=='[')) {
+ cur = chunkalloc(sizeof(struct markedglyphs));
+ cur->is_cursive = is_cursive;
+ cur->is_mark = is_mark;
+ cur->is_name = false;
+ cur->name_or_class = fea_ParseGlyphClass(tok);
+ } else if ( allow_marks && tok->type==tk_char &&
+ (tok->tokbuf[0]=='\'' || tok->tokbuf[0]=='"') && last!=NULL ) {
+ if ( last_mark!=tok->tokbuf[0] || (prev!=NULL && prev->mark_count==0)) {
+ ++mark_cnt;
+ last_mark = tok->tokbuf[0];
+ }
+ last->mark_count = mark_cnt;
+ } else if ( is_pos && last!=NULL && last->vr==NULL && tok->type == tk_int ) {
+ last->vr = chunkalloc(sizeof(struct vr));
+ if ( tok->in_vkrn )
+ last->vr->v_adv_off = tok->value;
+ else
+ last->vr->h_adv_off = tok->value;
+ } else if ( is_pos && last!=NULL && tok->type == tk_char && tok->tokbuf[0]=='<' ) {
+ fea_ParseBroket(tok,last);
+ } else if ( !is_pos && allow_lookups && tok->type == tk_char && tok->tokbuf[0]=='<' ) {
+ fea_TokenMustBe(tok,tk_lookup,'\0');
+ fea_TokenMustBe(tok,tk_name,'\0');
+ cur = chunkalloc(sizeof(struct markedglyphs));
+ cur->is_name = false;
+ cur->is_lookup = true;
+ cur->lookupname = copy(tok->tokbuf);
+ fea_TokenMustBe(tok,tk_char,'>');
+ } else
+ break;
+ if ( cur!=NULL ) {
+ prev = last;
+ if ( last==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ }
+ first = false;
+ }
+ if ( head!=NULL && mark_cnt!=0 )
+ head->has_marks = true;
+ fea_UnParseTok(tok);
+return( head );
+}
+
+static void fea_markedglyphsFree(struct markedglyphs *gl) {
+ struct markedglyphs *next;
+ int i;
+
+ while ( gl!=NULL ) {
+ next = gl->next;
+ free(gl->name_or_class);
+ free(gl->lookupname);
+ for ( i=0; i<gl->ap_cnt; ++i )
+ AnchorPointsFree(gl->anchors[i]);
+ free(gl->anchors);
+ if ( gl->vr!=NULL ) {
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ ValDevFree(gl->vr->adjust);
+#endif
+ chunkfree(gl->vr,sizeof(struct vr));
+ }
+ gl = next;
+ }
+}
+
+static struct feat_item *fea_AddAllLigPosibilities(struct parseState *tok,struct markedglyphs *glyphs,
+ SplineChar *sc,char *sequence_start,char *next, struct feat_item *sofar) {
+ char *start, *pt, ch;
+ SplineChar *temp;
+ char *after;
+ struct feat_item *item;
+
+ start = glyphs->name_or_class;
+ forever {
+ while ( *start==' ' ) ++start;
+ if ( *start=='\0' )
+ break;
+ for ( pt=start; *pt!='\0' && *pt!=' '; ++pt );
+ ch = *pt; *pt = '\0';
+ temp = fea_glyphname_get(tok,start);
+ *pt = ch; start = pt;
+ if ( temp==NULL )
+ continue;
+ strcpy(next,temp->name);
+ after = next+strlen(next);
+ if ( glyphs->next!=NULL ) {
+ *after++ = ' ';
+ sofar = fea_AddAllLigPosibilities(tok,glyphs->next,sc,sequence_start,after,sofar);
+ } else {
+ *after = '\0';
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_pst;
+ item->next = sofar;
+ sofar = item;
+ item->u1.sc = sc;
+ item->u2.pst = chunkalloc(sizeof(PST));
+ item->u2.pst->type = pst_ligature;
+ item->u2.pst->u.lig.components = copy(sequence_start);
+ item->u2.pst->u.lig.lig = sc;
+ }
+ }
+return( sofar );
+}
+
+static struct markedglyphs *fea_glyphs_to_names(struct markedglyphs *glyphs,
+ int cnt,char **to) {
+ struct markedglyphs *g;
+ int len, i;
+ char *names, *pt;
+
+ len = 0;
+ for ( g=glyphs, i=0; i<cnt; ++i, g=g->next )
+ len += strlen( g->name_or_class ) +1;
+ names = pt = galloc(len+1);
+ for ( g=glyphs, i=0; i<cnt; ++i, g=g->next ) {
+ strcpy(pt,g->name_or_class);
+ pt += strlen( pt );
+ *pt++ = ' ';
+ }
+ if ( pt!=names )
+ pt[-1] = '\0';
+ else
+ *pt = '\0';
+ *to = names;
+return( g );
+}
+
+static struct feat_item *fea_process_pos_single(struct parseState *tok,
+ struct markedglyphs *glyphs, struct feat_item *sofar) {
+ char *start, *pt, ch;
+ struct feat_item *item;
+ SplineChar *sc;
+
+ start = glyphs->name_or_class;
+ forever {
+ while ( *start==' ' ) ++start;
+ if ( *start=='\0' )
+ break;
+ for ( pt=start; *pt!='\0' && *pt!=' '; ++pt );
+ ch = *pt; *pt = '\0';
+ sc = fea_glyphname_get(tok,start);
+ *pt = ch; start = pt;
+ if ( sc!=NULL ) {
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_pst;
+ item->next = sofar;
+ sofar = item;
+ item->u1.sc = sc;
+ item->u2.pst = chunkalloc(sizeof(PST));
+ item->u2.pst->type = pst_position;
+ item->u2.pst->u.pos = glyphs->vr[0];
+ }
+ }
+return( sofar );
+}
+
+static struct feat_item *fea_process_pos_pair(struct parseState *tok,
+ struct markedglyphs *glyphs, struct feat_item *sofar, int enumer) {
+ char *start, *pt, ch, *start2, *pt2, ch2;
+ struct feat_item *item;
+ struct vr vr[2];
+ SplineChar *sc, *sc2;
+
+ memset(vr,0,sizeof(vr));
+ if ( glyphs->vr==NULL )
+ vr[0] = *glyphs->next->vr;
+ else {
+ vr[0] = *glyphs->vr;
+ if ( glyphs->next->vr!=NULL )
+ vr[1] = *glyphs->next->vr;
+ }
+ if ( enumer || (glyphs->is_name && glyphs->next->is_name)) {
+ start = glyphs->name_or_class;
+ forever {
+ while ( *start==' ' ) ++start;
+ if ( *start=='\0' )
+ break;
+ for ( pt=start; *pt!='\0' && *pt!=' '; ++pt );
+ ch = *pt; *pt = '\0';
+ sc = fea_glyphname_get(tok,start);
+ *pt = ch; start = pt;
+ if ( sc!=NULL ) {
+ start2 = glyphs->next->name_or_class;
+ forever {
+ while ( *start2==' ' ) ++start2;
+ if ( *start2=='\0' )
+ break;
+ for ( pt2=start2; *pt2!='\0' && *pt2!=' '; ++pt2 );
+ ch2 = *pt2; *pt2 = '\0';
+ sc2 = fea_glyphname_get(tok,start2);
+ *pt2 = ch2; start2 = pt2;
+ if ( sc2!=NULL ) {
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_pst;
+ item->next = sofar;
+ sofar = item;
+ item->u1.sc = sc;
+ item->u2.pst = chunkalloc(sizeof(PST));
+ item->u2.pst->type = pst_pair;
+ item->u2.pst->u.pair.paired = copy(sc2->name);
+ item->u2.pst->u.pair.vr = chunkalloc(sizeof( struct vr[2]));
+ memcpy(item->u2.pst->u.pair.vr,vr,sizeof(vr));
+ }
+ }
+ }
+ }
+ } else {
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_pstclass;
+ item->next = sofar;
+ sofar = item;
+ item->u1.class = copy(glyphs->name_or_class);
+ item->u2.pst = chunkalloc(sizeof(PST));
+ item->u2.pst->type = pst_pair;
+ item->u2.pst->u.pair.paired = copy(glyphs->next->name_or_class);
+ item->u2.pst->u.pair.vr = chunkalloc(sizeof( struct vr[2]));
+ memcpy(item->u2.pst->u.pair.vr,vr,sizeof(vr));
+ }
+return( sofar );
+}
+
+static struct feat_item *fea_process_sub_single(struct parseState *tok,
+ struct markedglyphs *glyphs, struct markedglyphs *rpl,
+ struct feat_item *sofar ) {
+ char *start, *pt, ch, *start2, *pt2, ch2;
+ struct feat_item *item;
+ SplineChar *sc, *temp;
+
+ if ( rpl->is_name ) {
+ temp = fea_glyphname_get(tok,rpl->name_or_class);
+ if ( temp!=NULL ) {
+ start = glyphs->name_or_class;
+ forever {
+ while ( *start==' ' ) ++start;
+ if ( *start=='\0' )
+ break;
+ for ( pt=start; *pt!='\0' && *pt!=' '; ++pt );
+ ch = *pt; *pt = '\0';
+ sc = fea_glyphname_get(tok,start);
+ *pt = ch; start = pt;
+ if ( sc!=NULL ) {
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_pst;
+ item->next = sofar;
+ sofar = item;
+ item->u1.sc = sc;
+ item->u2.pst = chunkalloc(sizeof(PST));
+ item->u2.pst->type = pst_substitution;
+ item->u2.pst->u.subs.variant = copy(temp->name);
+ }
+ }
+ }
+ } else if ( !glyphs->is_name ) {
+ start = glyphs->name_or_class;
+ start2 = rpl->name_or_class;
+ forever {
+ while ( *start==' ' ) ++start;
+ while ( *start2==' ' ) ++start2;
+ if ( *start=='\0' && *start2=='\0' )
+ break;
+ else if ( *start=='\0' || *start2=='\0' ) {
+ LogError(_("When a single substitution is specified by glyph classes, those classes must be of the same length on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ break;
+ }
+ for ( pt=start; *pt!='\0' && *pt!=' '; ++pt );
+ ch = *pt; *pt = '\0';
+ for ( pt2=start2; *pt2!='\0' && *pt2!=' '; ++pt2 );
+ ch2 = *pt2; *pt2 = '\0';
+ sc = fea_glyphname_get(tok,start);
+ temp = fea_glyphname_get(tok,start2);
+ *pt = ch; start = pt;
+ *pt2 = ch2; start2 = pt2;
+ if ( sc==NULL || temp==NULL )
+ continue;
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_pst;
+ item->next = sofar;
+ sofar = item;
+ item->u1.sc = sc;
+ item->u2.pst = chunkalloc(sizeof(PST));
+ item->u2.pst->type = pst_substitution;
+ item->u2.pst->u.subs.variant = copy(temp->name);
+ }
+ } else {
+ LogError(_("When a single substitution's replacement is specified by a glyph class, the thing being replaced must also be a class on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+return( sofar );
+}
+
+static struct feat_item *fea_process_sub_ligature(struct parseState *tok,
+ struct markedglyphs *glyphs, struct markedglyphs *rpl,
+ struct feat_item *sofar ) {
+ SplineChar *sc;
+ struct markedglyphs *g;
+
+ /* I store ligatures backwards, in the ligature glyph not the glyphs being substituted */
+ sc = fea_glyphname_get(tok,rpl->name_or_class);
+ if ( sc!=NULL ) {
+ int len=0;
+ char *space;
+ for ( g=glyphs; g!=NULL && g->mark_count==glyphs->mark_count; g=g->next )
+ len += strlen(g->name_or_class)+1;
+ space = galloc(len+1);
+ sofar = fea_AddAllLigPosibilities(tok,glyphs,sc,space,space,sofar);
+ free(space);
+ }
+return( sofar );
+}
+
+static FPST *fea_markedglyphs_to_fpst(struct parseState *tok,struct markedglyphs *glyphs,
+ int is_pos,int is_ignore) {
+ struct markedglyphs *g;
+ int bcnt=0, ncnt=0, fcnt=0, cnt;
+ int all_single=true;
+ int mmax = 0;
+ int i;
+ FPST *fpst;
+ struct fpst_rule *r;
+ struct feat_item *item, *head;
+ head = NULL;
+ for ( g=glyphs; g!=NULL && g->mark_count==0; g=g->next ) {
+ ++bcnt;
+ if ( !g->is_name ) all_single = false;
+ }
+ for ( ; g!=NULL ; g=g->next ) {
+ if ( !g->is_name ) all_single = false;
+ if ( g->mark_count==0 )
+ ++fcnt;
+ else {
+ /* if we found some unmarked glyphs between two runs of marked */
+ /* they don't count as lookaheads */
+ ncnt += fcnt + 1;
+ fcnt = 0;
+ if ( g->mark_count>mmax ) mmax = g->mark_count;
+ }
+ }
+
+ fpst = chunkalloc(sizeof(FPST));
+ fpst->type = is_pos ? pst_chainpos : pst_chainsub;
+ fpst->format = all_single ? pst_glyphs : pst_coverage;
+ fpst->rule_cnt = 1;
+ fpst->rules = r = gcalloc(1,sizeof(struct fpst_rule));
+ if ( is_ignore )
+ mmax = 0;
+ r->lookup_cnt = mmax;
+ r->lookups = gcalloc(mmax,sizeof(struct seqlookup));
+ for ( i=0; i<mmax; ++i )
+ r->lookups[i].seq = i;
+
+ if ( all_single ) {
+ g = fea_glyphs_to_names(glyphs,bcnt,&r->u.glyph.back);
+ g = fea_glyphs_to_names(g,ncnt,&r->u.glyph.names);
+ g = fea_glyphs_to_names(g,fcnt,&r->u.glyph.fore);
+ } else {
+ r->u.coverage.ncnt = ncnt;
+ r->u.coverage.bcnt = bcnt;
+ r->u.coverage.fcnt = fcnt;
+ r->u.coverage.ncovers = galloc(ncnt*sizeof(char*));
+ r->u.coverage.bcovers = galloc(bcnt*sizeof(char*));
+ r->u.coverage.fcovers = galloc(fcnt*sizeof(char*));
+ for ( i=0, g=glyphs; i<bcnt; ++i, g=g->next )
+ r->u.coverage.bcovers[i] = copy(g->name_or_class);
+ for ( i=0; i<ncnt; ++i, g=g->next )
+ r->u.coverage.ncovers[i] = copy(g->name_or_class);
+ for ( i=0; i<fcnt; ++i, g=g->next )
+ r->u.coverage.fcovers[i] = copy(g->name_or_class);
+ }
+
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_fpst;
+ item->next = tok->sofar;
+ tok->sofar = item;
+ item->u2.fpst = fpst;
+
+ if ( is_pos ) {
+ for ( g=glyphs; g!=NULL && g->mark_count!=0; g=g->next );
+ for ( i=0; g!=NULL; ++i ) {
+ if ( g->lookupname!=NULL ) {
+ head = chunkalloc(sizeof(struct feat_item));
+ head->type = ft_lookup_ref;
+ head->u1.lookup_name = copy(g->lookupname);
+ } else if ( (g->next==NULL || g->next->mark_count!=g->mark_count) &&
+ g->vr!=NULL ) {
+ head = fea_process_pos_single(tok,g,NULL);
+ } else if ( g->next!=NULL && g->mark_count==g->next->mark_count &&
+ (g->vr!=NULL || g->next->vr!=NULL ) &&
+ ( g->next->next==NULL || g->next->next->mark_count!=g->mark_count)) {
+ head = fea_process_pos_pair(tok,g,NULL,false);
+ } else {
+ LogError(_("Unparseable contetual sequence on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ r->lookups[i].lookup = (OTLookup *) head;
+ cnt = g->mark_count;
+ while ( g!=NULL && g->mark_count == cnt ) /* skip everything involved here */
+ g=g->next;
+ for ( ; g!=NULL && g->mark_count!=0; g=g->next ); /* skip any uninvolved glyphs */
+ }
+ }
+
+return( fpst );
+}
+
+static void fea_ParseIgnore(struct parseState *tok) {
+ struct markedglyphs *glyphs;
+ int is_pos;
+ FPST *fpst;
+ /* ignore [pos|sub] <marked glyph sequence> (, <marked g sequence>)* */
+
+ fea_ParseTok(tok);
+ if ( tok->type==tk_position )
+ is_pos = true;
+ else if ( tok->type == tk_substitute )
+ is_pos = false;
+ else {
+ LogError(_("The ignore keyword must be followed by either position or substitute on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ is_pos = true;
+ }
+ forever {
+ glyphs = fea_ParseMarkedGlyphs(tok,false/* don't parse value records, etc*/,
+ true/*allow marks*/,false/* no lookups */);
+ fpst = fea_markedglyphs_to_fpst(tok,glyphs,false,true);
+ if ( is_pos )
+ fpst->type = pst_chainpos;
+ fea_markedglyphsFree(glyphs);
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_char || tok->tokbuf[0]!=',' )
+ break;
+ }
+
+ fea_now_semi(tok);
+}
+
+static void fea_ParseSubstitute(struct parseState *tok) {
+ /* name by name => single subs */
+ /* class by name => single subs */
+ /* class by class => single subs */
+ /* name by <glyph sequence> => multiple subs */
+ /* name from <class> => alternate subs */
+ /* <glyph sequence> by name => ligature */
+ /* <marked glyph sequence> by <name> => context chaining */
+ /* <marked glyph sequence> by <lookup name>* => context chaining */
+ /* [ignore sub] <marked glyph sequence> (, <marked g sequence>)* */
+ struct markedglyphs *glyphs = fea_ParseMarkedGlyphs(tok,false,true,false),
+ *g, *rpl, *rp;
+ int cnt, i;
+ SplineChar *sc;
+ struct feat_item *item, *head;
+
+ fea_ParseTok(tok);
+ for ( cnt=0, g=glyphs; g!=NULL; g=g->next, ++cnt );
+ if ( glyphs==NULL ) {
+ LogError(_("Empty subsitute on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else if ( !glyphs->has_marks ) {
+ /* Non-contextual */
+ if ( cnt==1 && glyphs->is_name && tok->type==tk_from ) {
+ /* Alternate subs */
+ char *alts;
+ fea_ParseTok(tok);
+ alts = fea_ParseGlyphClass(tok);
+ sc = fea_glyphname_get(tok,glyphs->name_or_class);
+ if ( sc!=NULL ) {
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_pst;
+ item->next = tok->sofar;
+ tok->sofar = item;
+ item->u1.sc = sc;
+ item->u2.pst = chunkalloc(sizeof(PST));
+ item->u2.pst->type = pst_alternate;
+ item->u2.pst->u.alt.components = alts;
+ }
+ } else if ( cnt>=1 && tok->type==tk_by ) {
+ rpl = fea_ParseMarkedGlyphs(tok,false,false,false);
+ if ( rpl==NULL ) {
+ LogError(_("No substitution specified on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else if ( rpl->has_marks ) {
+ LogError(_("No marked glyphs allowed in replacement on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else {
+ if ( cnt==1 && rpl->next==NULL ) {
+ tok->sofar = fea_process_sub_single(tok,glyphs,rpl,tok->sofar);
+ } else if ( cnt==1 && glyphs->is_name && rpl->next!=NULL && rpl->is_name ) {
+ /* Multiple substitution */
+ int len=0;
+ char *mult;
+ for ( g=rpl; g!=NULL; g=g->next )
+ len += strlen(g->name_or_class)+1;
+ mult = galloc(len+1);
+ len = 0;
+ for ( g=rpl; g!=NULL; g=g->next ) {
+ strcpy(mult+len,g->name_or_class);
+ len += strlen(g->name_or_class);
+ mult[len++] = ' ';
+ }
+ mult[len-1] = '\0';
+ sc = fea_glyphname_get(tok,glyphs->name_or_class);
+ if ( sc!=NULL ) {
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_pst;
+ item->next = tok->sofar;
+ tok->sofar = item;
+ item->u1.sc = sc;
+ item->u2.pst = chunkalloc(sizeof(PST));
+ item->u2.pst->type = pst_multiple;
+ item->u2.pst->u.mult.components = mult;
+ }
+ } else if ( cnt>1 && rpl->is_name && rpl->next==NULL ) {
+ tok->sofar = fea_process_sub_ligature(tok,glyphs,rpl,tok->sofar);
+ /* Ligature */
+ } else {
+ LogError(_("Unparseable glyph sequence in substitution on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ }
+ fea_markedglyphsFree(rpl);
+ } else {
+ LogError(_("Expected 'by' or 'from' keywords in substitution on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ } else {
+ /* Contextual */
+ FPST *fpst = fea_markedglyphs_to_fpst(tok,glyphs,false,false);
+ struct fpst_rule *r = fpst->rules;
+ if ( tok->type!=tk_by ) {
+ LogError(_("Expected 'by' keyword in substitution on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ rpl = fea_ParseMarkedGlyphs(tok,false,false,true);
+ for ( g=glyphs; g!=NULL && g->mark_count==0; g=g->next );
+ for ( i=0, rp=rpl; g!=NULL && rp!=NULL; ++i, rp=rp->next ) {
+ if ( rp->lookupname!=NULL ) {
+ head = chunkalloc(sizeof(struct feat_item));
+ head->type = ft_lookup_ref;
+ head->u1.lookup_name = copy(rp->lookupname);
+ } else if ( g->next==NULL || g->next->mark_count!=g->mark_count ) {
+ head = fea_process_sub_single(tok,g,rp,NULL);
+ } else if ( g->next!=NULL && g->mark_count==g->next->mark_count ) {
+ head = fea_process_sub_ligature(tok,g,rpl,NULL);
+ } else {
+ LogError(_("Unparseable contetual sequence on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ r->lookups[i].lookup = (OTLookup *) head;
+ cnt = g->mark_count;
+ while ( g!=NULL && g->mark_count == cnt ) /* skip everything involved here */
+ g=g->next;
+ for ( ; g!=NULL && g->mark_count!=0; g=g->next ); /* skip any uninvolved glyphs */
+ }
+
+ fea_markedglyphsFree(rpl);
+ }
+
+ fea_end_statement(tok);
+ fea_markedglyphsFree(glyphs);
+}
+
+static void fea_ParseMarks(struct parseState *tok) {
+ /* mark name|class <anchor> */
+ char *contents = NULL;
+ SplineChar *sc = NULL;
+ AnchorPoint *ap;
+ char *start, *pt;
+ int ch;
+
+ fea_ParseTok(tok);
+ if ( tok->type==tk_name )
+ sc = fea_glyphname_get(tok,tok->tokbuf);
+ else if ( tok->type==tk_class )
+ contents = fea_lookup_class_complain(tok,tok->tokbuf);
+ else if ( tok->type==tk_char && tok->tokbuf[0]=='[' )
+ contents = fea_ParseGlyphClass(tok);
+ else {
+ LogError(_("Expected glyph name or class in mark statement on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+return;
+ }
+ if ( sc==NULL && contents==NULL ) {
+ fea_skip_to_semi(tok);
+return;
+ }
+
+ fea_TokenMustBe(tok,tk_char,'<');
+ fea_TokenMustBe(tok,tk_anchor,'\0');
+ ap = fea_ParseAnchor(tok);
+ ap->type = at_mark;
+ fea_end_statement(tok);
+
+ if ( ap!=NULL ) {
+ pt = contents;
+ forever {
+ struct feat_item *item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_ap;
+ item->u2.ap = ap;
+ item->next = tok->sofar;
+ tok->sofar = item;
+ start = pt;
+ if ( contents==NULL ) {
+ item->u1.sc = sc;
+ break;
+ }
+ while ( *pt!='\0' && *pt!=' ' )
+ ++pt;
+ ch = *pt; *pt = '\0';
+ sc = fea_glyphname_get(tok,start);
+ *pt = ch;
+ while ( Isspace(*pt)) ++pt;
+ if ( sc==NULL ) {
+ tok->sofar = item->next; /* Oops, remove it */
+ chunkfree(item,sizeof(*item));
+ if ( *pt=='\0' ) {
+ AnchorPointsFree(ap);
+ break;
+ }
+ } else {
+ item->u1.sc = sc;
+ if ( *pt=='\0' )
+ break;
+ ap = AnchorPointsCopy(ap);
+ }
+ }
+ }
+ free(contents);
+}
+
+static void fea_ParsePosition(struct parseState *tok, int enumer) {
+ /* name <vr> => single pos */
+ /* class <vr> => single pos */
+ /* name|class <vr> name|class <vr> => pair pos */
+ /* name|class name|class <vr> => pair pos */
+ /* cursive name|class <anchor> <anchor> => cursive positioning */
+ /* name|class <anchor> mark name|class => mark to base pos */
+ /* Must be preceded by a mark statement */
+ /* name|class <anchor> <anchor>+ mark name|class => mark to ligature pos */
+ /* Must be preceded by a mark statement */
+ /* mark name|class <anchor> mark name|class => mark to base pos */
+ /* Must be preceded by a mark statement */
+ /* <marked glyph pos sequence> => context chaining */
+ /* [ignore pos] <marked glyph sequence> (, <marked g sequence>)* */
+ struct markedglyphs *glyphs = fea_ParseMarkedGlyphs(tok,true,true,false), *g;
+ int cnt, i;
+ struct feat_item *item;
+ char *start, *pt, ch;
+ SplineChar *sc;
+
+ fea_ParseTok(tok);
+ for ( cnt=0, g=glyphs; g!=NULL; g=g->next, ++cnt );
+ if ( glyphs==NULL ) {
+ LogError(_("Empty position on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else if ( !glyphs->has_marks ) {
+ /* Non-contextual */
+ if ( glyphs->is_cursive ) {
+ if ( cnt!=1 || glyphs->ap_cnt!=2 ) {
+ LogError(_("Invalid cursive position on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else {
+ start = glyphs->name_or_class;
+ if ( glyphs->anchors[1]!=NULL )
+ glyphs->anchors[1]->type = at_cexit;
+ forever {
+ while ( *start==' ' ) ++start;
+ if ( *start=='\0' )
+ break;
+ for ( pt=start; *pt!='\0' && *pt!=' '; ++pt );
+ ch = *pt; *pt = '\0';
+ sc = fea_glyphname_get(tok,start);
+ *pt = ch; start = pt;
+ if ( sc!=NULL ) {
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_ap;
+ item->next = tok->sofar;
+ tok->sofar = item;
+ item->u1.sc = sc;
+ if ( glyphs->anchors[0]!=NULL ) {
+ glyphs->anchors[0]->type = at_centry;
+ glyphs->anchors[0]->next = glyphs->anchors[1];
+ item->u2.ap = AnchorPointsCopy(glyphs->anchors[0]);
+ } else
+ item->u2.ap = AnchorPointsCopy(glyphs->anchors[1]);
+ }
+ }
+ }
+ } else if ( cnt==1 && glyphs->vr!=NULL ) {
+ tok->sofar = fea_process_pos_single(tok,glyphs,tok->sofar);
+ } else if ( cnt==2 && (glyphs->vr!=NULL || glyphs->next->vr!=NULL) ) {
+ tok->sofar = fea_process_pos_pair(tok,glyphs,tok->sofar, enumer);
+ } else if ( cnt==1 && glyphs->ap_cnt>=1 && tok->type == tk_mark ) {
+ /* Mark to base, mark to mark, mark to ligature */
+ char *mark_class;
+ AnchorPoint *head=NULL, *last=NULL;
+ if ( tok->type!=tk_mark ) {
+ LogError(_("A mark glyph (or class of marks) must be specified here on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ fea_ParseTok(tok);
+ if ( tok->type==tk_name )
+ mark_class = copy(tok->tokbuf);
+ else
+ mark_class = fea_canonicalClassOrder(fea_ParseGlyphClass(tok));
+ if ( glyphs->is_mark && glyphs->ap_cnt>1 ) {
+ LogError(_("Mark to base anchor statements may only have one anchor on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ if ( mark_class!=NULL ) {
+ for ( i=0; i<glyphs->ap_cnt; ++i ) {
+ if ( glyphs->anchors[i]==NULL )
+ /* Nothing to be done */;
+ else {
+ if ( glyphs->ap_cnt>1 ) {
+ glyphs->anchors[i]->type = at_baselig;
+ glyphs->anchors[i]->lig_index = i;
+ } else if ( glyphs->is_mark )
+ glyphs->anchors[i]->type = at_basemark;
+ else
+ glyphs->anchors[i]->type = at_basechar;
+ if ( head==NULL )
+ head = glyphs->anchors[i];
+ else
+ last->next = glyphs->anchors[i];
+ last = glyphs->anchors[i];
+ }
+ }
+
+ start = glyphs->name_or_class;
+ forever {
+ while ( *start==' ' ) ++start;
+ if ( *start=='\0' )
+ break;
+ for ( pt=start; *pt!='\0' && *pt!=' '; ++pt );
+ ch = *pt; *pt = '\0';
+ sc = fea_glyphname_get(tok,start);
+ *pt = ch; start = pt;
+ if ( sc!=NULL ) {
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_ap;
+ item->next = tok->sofar;
+ tok->sofar = item;
+ item->u1.sc = sc;
+ item->u2.ap = AnchorPointsCopy(head);
+ item->mark_class = copy(mark_class);
+ }
+ }
+
+ /* So we can free them properly */
+ for ( ; head!=NULL; head = last ) {
+ last = head->next;
+ head->next = NULL;
+ }
+ }
+ } else {
+ LogError(_("Unparseable glyph sequence in position on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ } else {
+ /* Contextual */
+ (void) fea_markedglyphs_to_fpst(tok,glyphs,true,false);
+ }
+ fea_now_semi(tok);
+ fea_markedglyphsFree(glyphs);
+}
+
+static enum otlookup_type fea_LookupTypeFromItem(struct feat_item *item) {
+ switch ( item->type ) {
+ case ft_pst: case ft_pstclass:
+ switch ( item->u2.pst->type ) {
+ case pst_position:
+return( gpos_single );
+ case pst_pair:
+return( gpos_pair );
+ case pst_substitution:
+return( gsub_single );
+ case pst_alternate:
+return( gsub_alternate );
+ case pst_multiple:
+return( gsub_multiple );
+ case pst_ligature:
+return( gsub_ligature );
+ default:
+return( ot_undef ); /* Can't happen */
+ }
+ break;
+ case ft_ap:
+ switch( item->u2.ap->type ) {
+ case at_centry: case at_cexit:
+return( gpos_cursive );
+ case at_mark:
+return( ot_undef ); /* Can be used in three different lookups. Not enough info */
+ case at_basechar:
+return( gpos_mark2base );
+ case at_baselig:
+return( gpos_mark2ligature );
+ case at_basemark:
+return( gpos_mark2mark );
+ default:
+return( ot_undef ); /* Can't happen */
+ }
+ break;
+ case ft_fpst:
+ switch( item->u2.fpst->type ) {
+ case pst_chainpos:
+return( gpos_contextchain );
+ case pst_chainsub:
+return( gsub_contextchain );
+ default:
+return( ot_undef ); /* Can't happen */
+ }
+ break;
+ default:
+return( ot_undef ); /* Can happen */
+ }
+}
+
+static struct feat_item *fea_AddFeatItem(struct parseState *tok,enum feat_type type,uint32 tag) {
+ struct feat_item *item;
+
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = type;
+ item->u1.tag = tag;
+ item->next = tok->sofar;
+ tok->sofar = item;
+return( item );
+}
+
+static int fea_LookupSwitch(struct parseState *tok) {
+ int enumer = false;
+
+ switch ( tok->type ) {
+ case tk_class:
+ fea_ParseGlyphClassDef(tok);
+ break;
+ case tk_lookupflag:
+ fea_ParseLookupFlags(tok);
+ break;
+ case tk_mark:
+ fea_ParseMarks(tok);
+ break;
+ case tk_ignore:
+ fea_ParseIgnore(tok);
+ break;
+ case tk_enumerate:
+ fea_TokenMustBe(tok,tk_position,'\0');
+ enumer = true;
+ /* Fall through */;
+ case tk_position:
+ fea_ParsePosition(tok,enumer);
+ break;
+ case tk_substitute:
+ fea_ParseSubstitute(tok);
+ enumer = false;
+ break;
+ case tk_subtable:
+ fea_AddFeatItem(tok,ft_subtable,0);
+ fea_TokenMustBe(tok,tk_char,';');
+ break;
+ case tk_char:
+ if ( tok->tokbuf[0]=='}' )
+return( 2 );
+ /* Fall through */
+ default:
+return( 0 );
+ }
+return( 1 );
+}
+
+static void fea_ParseLookupDef(struct parseState *tok, int could_be_stat ) {
+ char *lookup_name;
+ struct feat_item *item, *first_after_mark;
+ enum otlookup_type lookuptype;
+ int has_marks;
+ int ret;
+
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_name ) {
+ LogError(_("Expected name in lookup on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+return;
+ }
+ lookup_name = copy(tok->tokbuf);
+ fea_ParseTok(tok);
+ if ( could_be_stat && tok->type==tk_char && tok->tokbuf[0]==';' ) {
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_lookup_ref;
+ item->u1.lookup_name = lookup_name;
+ item->next = tok->sofar;
+ tok->sofar = item;
+return;
+ } else if ( tok->type==tk_useExtension ) /* I just ignore this */
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_char || tok->tokbuf[0]!='{' ) {
+ LogError(_("Expected '{' in feature definition on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+return;
+ }
+
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_lookup_start;
+ item->u1.lookup_name = lookup_name;
+ item->next = tok->sofar;
+ tok->sofar = item;
+
+ first_after_mark = NULL;
+ forever {
+ fea_ParseTok(tok);
+ if ( tok->err_count>100 )
+ break;
+ if ( tok->type==tk_eof ) {
+ LogError(_("Unexpected end of file in lookup definition on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+return;
+ } else if ( (ret = fea_LookupSwitch(tok))==0 ) {
+ LogError(_("Unexpected token, %s, in lookup definition on line %d of %s"), tok->tokbuf, tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ if ( tok->type==tk_name && strcmp(tok->tokbuf,"subs")==0 )
+ LogError(_(" Perhaps you meant to use the keyword 'sub' rather than 'subs'?") );
+ ++tok->err_count;
+return;
+ } else if ( ret==2 )
+ break;
+ /* Ok, mark classes must either contain exactly the same glyphs, or */
+ /* they may not intersect at all */
+ /* Mark2* lookups are not well documented (because adobe FDK doesn't */
+ /* support them) but I'm going to assume that if I have some mark */
+ /* statements, then some pos statement, then another mark statement */
+ /* that I begin a new subtable with the second set of marks (and a */
+ /* different set of mark classes) */
+ if ( tok->sofar!=NULL && tok->sofar->type==ft_subtable )
+ first_after_mark = NULL;
+ else if ( tok->sofar!=NULL && tok->sofar->type==ft_ap ) {
+ if ( tok->sofar->u2.ap->type == at_mark )
+ first_after_mark = NULL;
+ else if ( tok->sofar->mark_class==NULL )
+ /* we don't have to worry about Cursive connections */;
+ else if ( first_after_mark == NULL )
+ first_after_mark = tok->sofar;
+ else {
+ struct feat_item *f;
+ for ( f = tok->sofar->next; f!=NULL; f=f->next ) {
+ if ( f->type!=ft_ap || f->mark_class==NULL )
+ continue;
+ if ( strcmp(tok->sofar->mark_class,f->mark_class)==0 )
+ continue; /* same glyphs, that's ok */
+ else if ( fea_classesIntersect(tok->sofar->mark_class,f->mark_class)) {
+ LogError(_("Mark classes must either be exactly the same or contain no common glyphs\n But the class on line %d of %s contains a match."),
+ tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ if ( f==first_after_mark )
+ break;
+ }
+ }
+ }
+ }
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_name || strcmp(tok->tokbuf,lookup_name)!=0 ) {
+ LogError(_("Expected %s in lookup definition on line %d of %s"),
+ lookup_name, tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ fea_end_statement(tok);
+
+ /* Make sure all entries in this lookup of the same lookup type */
+ lookuptype = ot_undef;
+ has_marks = false;
+ for ( item=tok->sofar ; item!=NULL && item->type!=ft_lookup_start; item=item->next ) {
+ enum otlookup_type cur = fea_LookupTypeFromItem(item);
+ if ( item->type==ft_ap && item->u2.ap->type == at_mark )
+ has_marks = true;
+ if ( cur==ot_undef ) /* Some entries in the list (lookupflags) have no type */
+ /* Tum, ty, tum tum */;
+ else if ( lookuptype==ot_undef )
+ lookuptype = cur;
+ else if ( lookuptype!=cur ) {
+ LogError(_("All entries in a lookup must have the same type on line %d of %s"),
+ tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ break;
+ }
+ }
+ if ( lookuptype==ot_undef ) {
+ LogError(_("This lookup has no effect, I can't figure out its type on line %d of %s"),
+ tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else if ( has_marks && lookuptype!=gpos_mark2base &&
+ lookuptype!=gpos_mark2mark &&
+ lookuptype!=gpos_mark2ligature ) {
+ LogError(_("Mark glyphs may not be specified with this type of lookup on line %d of %s"),
+ tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_lookup_end;
+ /* item->u1.lookup_name = lookup_name; */
+ item->next = tok->sofar;
+ tok->sofar = item;
+}
+
+static struct nameid *fea_ParseNameId(struct parseState *tok,int strid) {
+ int platform = 3, specific = 1, language = 0x409;
+ struct nameid *nm;
+ char *start, *pt;
+ int max, ch, value;
+ FILE *in = tok->inlist[tok->inc_depth];
+ /* nameid <id> [<string attibute>] string; */
+ /* "nameid" and <id> will already have been parsed when we get here */
+ /* <string attribute> := <platform> | <platform> <specific> <language> */
+ /* <patform>==3 => <specific>=1 <language>=0x409 */
+ /* <platform>==1 => <specific>=0 <lang>=0 */
+ /* string in double quotes \XXXX escapes to UCS2 (for 3) */
+ /* string in double quotes \XX escapes to MacLatin (for 1) */
+ /* I only store 3,1 strings */
+
+ fea_ParseTok(tok);
+ if ( tok->type == tk_int ) {
+ if ( tok->value!=3 && tok->value!=1 ) {
+ LogError(_("Invalid platform for string on line %d of %s"),
+ tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else if ( tok->value==1 ) {
+ specific = language = 0;
+ }
+ fea_ParseTok(tok);
+ if ( tok->type == tk_int ) {
+ specific = tok->value;
+ tok->base = 0;
+ fea_TokenMustBe(tok,tk_int,'\0');
+ language = tok->value;
+ tok->base = 10;
+ fea_ParseTok(tok);
+ }
+ }
+ if ( tok->type!=tk_char || tok->tokbuf[0]!='"' ) {
+ LogError(_("Expected string on line %d of %s"),
+ tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+ nm = NULL;
+ } else {
+ if ( platform==3 && specific==1 ) {
+ nm = chunkalloc(sizeof(struct nameid));
+ nm->strid = strid;
+ nm->platform = platform;
+ nm->specific = specific;
+ nm->language = language;
+ } else
+ nm = NULL;
+ max = 0;
+ pt = start = NULL;
+ while ( (ch=getc(in))!=EOF && ch!='"' ) {
+ if ( ch=='\n' || ch=='\r' )
+ continue; /* Newline characters are ignored here */
+ /* may be specified with backslashes */
+ if ( ch=='\\' ) {
+ int i, dmax = platform==3 ? 4 : 2;
+ value = 0;
+ for ( i=0; i<dmax; ++i ) {
+ ch = getc(in);
+ if ( !Ishexdigit(ch)) {
+ ungetc(ch,in);
+ break;
+ }
+ if ( ch>='a' && ch<='f' )
+ ch -= ('a'-10);
+ else if ( ch>='A' && ch<='F' )
+ ch -= ('A'-10);
+ else
+ ch -= '0';
+ value <<= 4;
+ value |= ch;
+ }
+ } else
+ value = ch;
+ if ( nm!=NULL ) {
+ if ( pt-start+3>=max ) {
+ int off = pt-start;
+ start = grealloc(start,(max+=100)+1);
+ pt = start+off;
+ }
+ pt = utf8_idpb(pt,value);
+ }
+ }
+ if ( nm!=NULL ) {
+ if ( pt==NULL )
+ nm->utf8_str = copy("");
+ else {
+ *pt = '\0';
+ nm->utf8_str = copy(start);
+ free(start);
+ }
+ }
+ if ( tok->type!=tk_char || tok->tokbuf[0]!='"' ) {
+ LogError(_("End of file found in string on line %d of %s"),
+ tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else
+ fea_end_statement(tok);
+ }
+return( nm );
+}
+
+static struct feat_item *fea_ParseParameters(struct parseState *tok, struct feat_item *feat) {
+ /* Ok. The only time a parameter keyword may be used is inside a 'size' */
+ /* feature and then it takes 4 numbers */
+ /* The first, third and fourth are in decipoints and may be either */
+ /* integers or floats (in which case we must multiply them by 10) */
+ int params[4];
+ int i;
+
+ memset(params,0,sizeof(params));
+ for ( i=0; i<4; ++i ) {
+ params[i] = fea_ParseDeciPoints(tok);
+ if ( tok->type==tk_char && tok->tokbuf[0]==';' )
+ break;
+ }
+ fea_end_statement(tok);
+
+ if ( feat==NULL ) {
+ feat = chunkalloc(sizeof(struct feat_item));
+ feat->type = ft_sizeparams;
+ feat->next = tok->sofar;
+ tok->sofar = feat;
+ }
+ feat->u1.params = galloc(sizeof(params));
+ memcpy(feat->u1.params,params,sizeof(params));
+return( feat );
+}
+
+static struct feat_item *fea_ParseSizeMenuName(struct parseState *tok, struct feat_item *feat) {
+ /* Sizemenuname takes either 0, 1 or 3 numbers and a string */
+ /* if no numbers are given (or the first number is 3) then the string is */
+ /* unicode. Otherwise a mac encoding, treated as single byte */
+ /* Since fontforge only supports windows strings here I shall parse and */
+ /* ignore mac strings */
+ struct nameid *string;
+
+ string = fea_ParseNameId(tok,-1);
+
+ if ( string!=NULL ) {
+ if ( feat==NULL ) {
+ feat = chunkalloc(sizeof(struct feat_item));
+ feat->type = ft_sizeparams;
+ feat->next = tok->sofar;
+ tok->sofar = feat;
+ }
+ string->next = feat->u2.names;
+ feat->u2.names = string;
+ }
+return( feat );
+}
+
+static void fea_ParseFeatureDef(struct parseState *tok) {
+ uint32 feat_tag;
+ struct feat_item *item, *size_item = NULL;
+ int type, ret;
+
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_name || !tok->could_be_tag ) {
+ LogError(_("Expected tag in feature on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+return;
+ }
+ feat_tag = tok->tag;
+ tok->in_vkrn = feat_tag == CHR('v','k','r','n');
+
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_feat_start;
+ item->u1.tag = feat_tag;
+ if ( tok->def_langsyses!=NULL )
+ item->u2.sl = SLCopy(tok->def_langsyses);
+ else {
+ item->u2.sl = chunkalloc(sizeof(struct scriptlanglist));
+ item->u2.sl->script = DEFAULT_SCRIPT;
+ item->u2.sl->lang_cnt = 1;
+ item->u2.sl->langs[0] = DEFAULT_LANG;
+ }
+ item->next = tok->sofar;
+ tok->sofar = item;
+
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_char || tok->tokbuf[0]!='{' ) {
+ LogError(_("Expected '{' in feature definition on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+return;
+ }
+
+ forever {
+ fea_ParseTok(tok);
+ if ( tok->err_count>100 )
+ break;
+ if ( tok->type==tk_eof ) {
+ LogError(_("Unexpected end of file in feature definition on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+return;
+ } else if ( (ret = fea_LookupSwitch(tok))==0 ) {
+ switch ( tok->type ) {
+ case tk_lookup:
+ fea_ParseLookupDef(tok,true);
+ break;
+ case tk_languagesystem:
+ fea_ParseLangSys(tok,true);
+ break;
+ case tk_feature:
+ /* can appear inside an 'aalt' feature. I don't support it, but */
+ /* just parse and ignore it */
+ if ( feat_tag!=CHR('a','a','l','t')) {
+ LogError(_("Features inside of other features are only permitted for 'aalt' features on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_name || !tok->could_be_tag ) {
+ LogError(_("Expected tag on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ fea_end_statement(tok);
+ break;
+ case tk_script:
+ case tk_language:
+ /* If no lang specified after script use 'dflt', if no script specified before a language use 'latn' */
+ type = tok->type==tk_script ? ft_script : ft_lang;
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_name || !tok->could_be_tag ) {
+ LogError(_("Expected tag on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ } else {
+ item = fea_AddFeatItem(tok,type,tok->tag);
+ if ( type==ft_lang ) {
+ forever {
+ fea_ParseTok(tok);
+ if ( tok->type==tk_include_dflt )
+ /* Unneeded */;
+ else if ( tok->type==tk_exclude_dflt )
+ item->u2.exclude_dflt = true;
+ else if ( tok->type==tk_required )
+ /* Not supported by adobe (or me) */;
+ else if ( tok->type==tk_char && tok->tokbuf[0]==';' )
+ break;
+ else {
+ LogError(_("Expected ';' on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ break;
+ }
+ }
+ } else
+ fea_end_statement(tok);
+ }
+ break;
+ case tk_parameters:
+ if ( feat_tag==CHR('s','i','z','e') ) {
+ size_item = fea_ParseParameters(tok, size_item);
+ break;
+ }
+ /* Fall on through */
+ case tk_name:
+ if ( feat_tag==CHR('s','i','z','e') && strcmp(tok->tokbuf,"sizemenuname")==0 ) {
+ size_item = fea_ParseSizeMenuName(tok, size_item);
+ break;
+ }
+ /* Fall on through */
+ default:
+ LogError(_("Unexpected token, %s, in feature definition on line %d of %s"), tok->tokbuf, tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+return;
+ }
+ } else if ( ret==2 )
+ break;
+ }
+
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_name || !tok->could_be_tag || tok->tag!=feat_tag ) {
+ LogError(_("Expected '%c%c%c%c' in lookup definition on line %d of %s"),
+ feat_tag>>24, feat_tag>>16, feat_tag>>8, feat_tag,
+ tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+ fea_end_statement(tok);
+
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_feat_end;
+ item->u1.tag = feat_tag;
+ item->next = tok->sofar;
+ tok->sofar = item;
+
+ tok->in_vkrn = false;
+}
+
+static void fea_ParseNameTable(struct parseState *tok) {
+ struct nameid *head=NULL, *string;
+ struct feat_item *item;
+ /* nameid <id> [<string attibute>] string; */
+
+ forever {
+ fea_ParseTok(tok);
+ if ( tok->type != tk_nameid )
+ break;
+ fea_TokenMustBe(tok,tk_int,'\0');
+ string = fea_ParseNameId(tok,tok->value);
+ if ( string!=NULL ) {
+ string->next = head;
+ head = string;
+ }
+ }
+
+ if ( head!=NULL ) {
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_names;
+ item->next = tok->sofar;
+ tok->sofar = item;
+ item->u2.names = head;
+ }
+ if ( tok->type!=tk_char || tok->tokbuf[0]!='}' ) {
+ LogError(_("Expected closing curly brace on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ }
+}
+
+static void fea_ParseTableKeywords(struct parseState *tok, struct tablekeywords *keys) {
+ int index;
+ struct tablevalues *tv, *head = NULL;
+ int i;
+ struct feat_item *item;
+
+ forever {
+ fea_ParseTok(tok);
+ if ( tok->type != tk_name )
+ break;
+ for ( index=0; keys[index].name!=NULL; ++index ) {
+ if ( strcmp(keys[index].name,tok->tokbuf)==0 )
+ break;
+ }
+ if ( keys[index].name==NULL ) {
+ LogError(_("Unknown field %s on line %d of %s"), tok->tokbuf, tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ index = -1;
+ }
+ if ( index!=-1 && keys[index].offset!=-1 ) {
+ tv = chunkalloc(sizeof(struct tablevalues));
+ tv->index = index;
+ } else
+ tv = NULL;
+ fea_ParseTok(tok);
+ if ( strcmp(tok->tokbuf,"Vendor")==0 && tv!=NULL) {
+ /* This takes a 4 character string */
+ /* of course strings aren't part of the syntax, but it takes one anyway */
+ if ( tok->type==tk_name && tok->could_be_tag )
+ /* Accept a normal tag, since that's what it really is */
+ tv->value = tok->tag;
+ else if ( tok->type==tk_char && tok->tokbuf[0]=='"' ) {
+ uint8 foo[4]; int ch;
+ FILE *in = tok->inlist[tok->inc_depth];
+ memset(foo,' ',sizeof(foo));
+ for ( i=0; i<4; ++i ) {
+ ch = getc(in);
+ if ( ch==EOF )
+ break;
+ else if ( ch=='"' ) {
+ ungetc(ch,in);
+ break;
+ }
+ foo[i] = ch;
+ }
+ while ( (ch=getc(in))!=EOF && ch!='"' );
+ tok->value=(foo[0]<<24) | (foo[1]<<16) | (foo[2]<<8) | foo[3];
+ } else {
+ LogError(_("Expected string on line %d of %s"),
+ tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ chunkfree(tv,sizeof(*tv));
+ tv = NULL;
+ }
+ fea_ParseTok(tok);
+ } else {
+ if ( tok->type!=tk_int ) {
+ LogError(_("Expected integer on line %d of %s"),
+ tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ chunkfree(tv,sizeof(*tv));
+ tv = NULL;
+ fea_ParseTok(tok);
+ } else {
+ if ( tv!=NULL )
+ tv->value = tok->value;
+ if ( strcmp(keys[index].name,"FontRevision")==0 ) {
+ /* Can take a float */
+ FILE *in = tok->inlist[tok->inc_depth];
+ int ch = getc(in);
+ if ( ch=='.' )
+ for ( ch=getc(in); Isdigit(ch); ch=getc(in));
+ ungetc(ch,in);
+ }
+ if ( index!=-1 && keys[index].cnt!=1 ) {
+ int is_panose = strcmp(keys[index].name,"Panose")==0 && tv!=NULL;
+ if ( is_panose )
+ tv->panose_vals[0] = tv->value;
+ for ( i=1; ; ++i ) {
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_int )
+ break;
+ if ( is_panose && i<10 && tv!=NULL )
+ tv->panose_vals[i] = tok->value;
+ }
+ } else
+ fea_ParseTok(tok);
+ }
+ }
+ if ( tok->type!=tk_char || tok->tokbuf[0]!=';' ) {
+ LogError(_("Expected semicolon on line %d of %s"),
+ tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_close_curly(tok);
+ chunkfree(tv,sizeof(*tv));
+ break;
+ }
+ if ( tv!=NULL ) {
+ tv->next = head;
+ head = tv;
+ }
+ }
+ if ( tok->type!=tk_char || tok->tokbuf[0]!='}' ) {
+ LogError(_("Expected '}' on line %d of %s"),
+ tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_close_curly(tok);
+ }
+ if ( head!=NULL ) {
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_tablekeys;
+ item->u1.offsets = keys;
+ item->u2.tvals = head;
+ item->next = tok->sofar;
+ tok->sofar = item;
+ }
+}
+
+static void fea_ParseGDEFTable(struct parseState *tok) {
+ /* GlyphClassDef <base> <lig> <mark> <component>; */
+ /* Attach <glyph>|<glyph class> <number>+; */ /* parse & ignore */
+ /* LigatureCaret <glyph>|<glyph class> <caret value>+ */
+ int i;
+ struct feat_item *item;
+ int16 *carets=NULL; int len=0, max=0;
+
+ forever {
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_name )
+ break;
+ if ( strcmp(tok->tokbuf,"Attach")==0 ) {
+ fea_ParseTok(tok);
+ /* Bug. Not parsing inline classes */
+ if ( tok->type!=tk_class && tok->type!=tk_name ) {
+ LogError(_("Expected name or class on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+ } else {
+ forever {
+ fea_ParseTok(tok);
+ if ( tok->type!=tk_int )
+ break;
+ }
+ }
+ } else if ( strcmp(tok->tokbuf,"LigatureCaret")==0 ) {
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_lcaret;
+ item->next = tok->sofar;
+ tok->sofar = item;
+
+ fea_ParseTok(tok);
+ if ( tok->type==tk_name )
+ item->u1.class = fea_glyphname_validate(tok,tok->tokbuf);
+ else if ( tok->type==tk_cid )
+ item->u1.class = fea_cid_validate(tok,tok->value);
+ else if ( tok->type == tk_class || (tok->type==tk_char && tok->tokbuf[0]=='['))
+ item->u1.class = fea_ParseGlyphClass(tok);
+ else {
+ LogError(_("Expected name or class on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+ continue;
+ }
+ forever {
+ fea_ParseTok(tok);
+ if ( tok->type==tk_int )
+ /* Not strictly cricket, but I'll accept it */;
+ else if ( tok->type==tk_char && tok->tokbuf[0]=='<' )
+ fea_ParseCaret(tok);
+ else
+ break;
+ if ( len>=max )
+ carets = grealloc(carets,(max+=10)*sizeof(int16));
+ carets[len++] = tok->value;
+ }
+ if ( tok->type!=tk_char || tok->tokbuf[0]!=';' ) {
+ LogError(_("Expected semicolon on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+ }
+ item->u2.lcaret = galloc((len+1)*sizeof(int16));
+ memcpy(item->u2.lcaret,carets,len*sizeof(int16));
+ item->u2.lcaret[len] = 0;
+ } else if ( strcmp(tok->tokbuf,"GlyphClassDef")==0 ) {
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_gdefclasses;
+ item->u1.gdef_classes = chunkalloc(sizeof(char *[4]));
+ item->next = tok->sofar;
+ tok->sofar = item;
+ for ( i=0; i<4; ++i ) {
+ fea_ParseTok(tok);
+ item->u1.gdef_classes[i] = fea_ParseGlyphClass(tok);
+ }
+ fea_ParseTok(tok);
+ } else {
+ LogError(_("Expected Attach or LigatureCaret or GlyphClassDef on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ break;
+ }
+ }
+ if ( tok->type!=tk_char || tok->tokbuf[0]!='}' ) {
+ LogError(_("Unexpected token in GDEF on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_close_curly(tok);
+ }
+ free(carets);
+}
+
+static void fea_ParseTableDef(struct parseState *tok) {
+ uint32 table_tag;
+ struct feat_item *item;
+
+ fea_ParseTag(tok);
+ if ( tok->type!=tk_name || !tok->could_be_tag ) {
+ LogError(_("Expected tag in table on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+return;
+ }
+ table_tag = tok->tag;
+
+ item = chunkalloc(sizeof(struct feat_item));
+ item->type = ft_table;
+ item->u1.tag = table_tag;
+ item->next = tok->sofar;
+ tok->sofar = item;
+ fea_TokenMustBe(tok,tk_char,'{');
+ switch ( table_tag ) {
+ case CHR('G','D','E','F'):
+ fea_ParseGDEFTable(tok);
+ break;
+ case CHR('n','a','m','e'):
+ fea_ParseNameTable(tok);
+ break;
+
+ case CHR('h','h','e','a'):
+ fea_ParseTableKeywords(tok,hhead_keys);
+ break;
+ case CHR('v','h','e','a'):
+ fea_ParseTableKeywords(tok,vhead_keys);
+ break;
+ case CHR('O','S','/','2'):
+ fea_ParseTableKeywords(tok,os2_keys);
+ break;
+
+ case CHR('h','e','a','d'):
+ /* FontRevision <number>.<number>; */
+ /* Only one field here, and I don't really support it */
+ case CHR('v','m','t','x'):
+ /* I don't support 'vmtx' tables */
+ case CHR('B','A','S','E'):
+ /* I don't support 'BASE' tables */
+ default:
+ fea_skip_to_close_curly(tok);
+ break;
+ }
+
+ fea_ParseTag(tok);
+ if ( tok->type!=tk_name || !tok->could_be_tag || tok->tag!=table_tag ) {
+ LogError(_("Expected matching tag in table on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ fea_skip_to_semi(tok);
+return;
+ }
+ fea_end_statement(tok);
+}
+
+/* ************************************************************************** */
+/* ******************************* Free feat ******************************** */
+/* ************************************************************************** */
+
+static void NameIdFree(struct nameid *nm) {
+ struct nameid *nmnext;
+
+ while ( nm!=NULL ) {
+ nmnext = nm->next;
+ free( nm->utf8_str );
+ chunkfree(nm,sizeof(*nm));
+ nm = nmnext;
+ }
+}
+
+static void TableValsFree(struct tablevalues *tb) {
+ struct tablevalues *tbnext;
+
+ while ( tb!=NULL ) {
+ tbnext = tb->next;
+ chunkfree(tb,sizeof(*tb));
+ tb = tbnext;
+ }
+}
+
+static void fea_featitemFree(struct feat_item *item) {
+ struct feat_item *next;
+ int i,j;
+
+ while ( item!=NULL ) {
+ next = item->next;
+ switch ( item->type ) {
+ case ft_lookup_end:
+ case ft_feat_end:
+ case ft_table:
+ case ft_subtable:
+ case ft_script:
+ case ft_lang:
+ case ft_lookupflags:
+ /* Nothing needs freeing */;
+ break;
+ case ft_feat_start:
+ case ft_langsys:
+ ScriptLangListFree( item->u2.sl);
+ break;
+ case ft_lookup_start:
+ case ft_lookup_ref:
+ free( item->u1.lookup_name );
+ break;
+ case ft_sizeparams:
+ free( item->u1.params );
+ NameIdFree( item->u2.names );
+ break;
+ case ft_names:
+ NameIdFree( item->u2.names );
+ break;
+ case ft_gdefclasses:
+ for ( i=0; i<4; ++i )
+ free(item->u1.gdef_classes[i]);
+ chunkfree(item->u1.gdef_classes,sizeof(char *[4]));
+ break;
+ case ft_lcaret:
+ free( item->u2.lcaret );
+ break;
+ case ft_tablekeys:
+ TableValsFree( item->u2.tvals );
+ break;
+ case ft_pst:
+ PSTFree( item->u2.pst );
+ break;
+ case ft_pstclass:
+ free( item->u1.class );
+ PSTFree( item->u2.pst );
+ break;
+ case ft_ap:
+ AnchorPointsFree( item->u2.ap );
+ free( item->mark_class );
+ break;
+ case ft_fpst:
+ if ( item->u2.fpst!=NULL ) {
+ for ( i=0; i<item->u2.fpst->rule_cnt; ++i ) {
+ struct fpst_rule *r = &item->u2.fpst->rules[i];
+ for ( j=0; j<r->lookup_cnt; ++j ) {
+ if ( r->lookups[j].lookup!=NULL ) {
+ struct feat_item *nested = (struct feat_item *) (r->lookups[j].lookup);
+ fea_featitemFree(nested);
+ r->lookups[j].lookup = NULL;
+ }
+ }
+ }
+ FPSTFree(item->u2.fpst);
+ }
+ break;
+ default:
+ IError("Don't know how to free a feat_item of type %d", item->type );
+ break;
+ }
+ chunkfree(item,sizeof(*item));
+ item = next;
+ }
+}
+
+static void fea_ParseFeatureFile(struct parseState *tok) {
+
+ forever {
+ fea_ParseTok(tok);
+ if ( tok->err_count>100 )
+ break;
+ switch ( tok->type ) {
+ case tk_class:
+ fea_ParseGlyphClassDef(tok);
+ break;
+ case tk_lookup:
+ fea_ParseLookupDef(tok,false);
+ break;
+ case tk_languagesystem:
+ fea_ParseLangSys(tok,false);
+ break;
+ case tk_feature:
+ fea_ParseFeatureDef(tok);
+ break;
+ case tk_table:
+ fea_ParseTableDef(tok);
+ break;
+ case tk_anonymous:
+ LogError(_("FontForge does not support anonymous tables on line %d of %s"), tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ fea_skip_to_close_curly(tok);
+ break;
+ case tk_eof:
+ goto end_loop;
+ default:
+ LogError(_("Unexpected token, %s, on line %d of %s"), tok->tokbuf, tok->line[tok->inc_depth], tok->filename[tok->inc_depth] );
+ ++tok->err_count;
+ goto end_loop;
+ }
+ }
+ end_loop:;
+}
+
+/* ************************************************************************** */
+/* ******************************* Apply feat ******************************* */
+/* ************************************************************************** */
+static int fea_FeatItemEndsLookup(enum feat_type type) {
+return( type==ft_lookup_end || type == ft_feat_end ||
+ type == ft_table || type == ft_script ||
+ type == ft_lang || type == ft_langsys ||
+ type == ft_lookup_ref );
+}
+
+static struct feat_item *fea_SetLookupLink(struct feat_item *nested,
+ enum otlookup_type type) {
+ struct feat_item *prev = NULL;
+ enum otlookup_type found_type;
+
+ while ( nested!=NULL ) {
+ /* Stop when we find something which forces a new lookup */
+ if ( fea_FeatItemEndsLookup(nested->type) )
+ break;
+ if ( nested->ticked ) {
+ nested = nested->next;
+ continue;
+ }
+ found_type = fea_LookupTypeFromItem(nested);
+ if ( type==ot_undef || found_type == ot_undef || found_type == type ) {
+ if ( nested->type!=ft_ap || nested->u2.ap->type!=at_mark )
+ nested->ticked = true; /* Marks might get used in more than one lookup */
+ if ( prev!=NULL )
+ prev->lookup_next = nested;
+ prev = nested;
+ }
+ nested = nested->next;
+ }
+return( nested );
+}
+
+static void fea_ApplyLookupListPST(struct parseState *tok,
+ struct feat_item *lookup_data,OTLookup *otl) {
+ struct lookup_subtable *sub = NULL, *last=NULL;
+ struct feat_item *l;
+ /* Simple pst's are easy. We just attach them to their proper glyphs */
+ /* and then clear the feat_item pst slot (so we don't free them later) */
+ /* There might be a subtable break */
+ /* There might be a lookupflags */
+
+ for ( l = lookup_data; l!=NULL; l=l->lookup_next ) {
+ switch ( l->type ) {
+ case ft_lookup_start:
+ case ft_lookupflags:
+ /* Ignore these, already handled them */;
+ break;
+ case ft_subtable:
+ sub = NULL;
+ break;
+ case ft_pst:
+ if ( sub==NULL ) {
+ sub = chunkalloc(sizeof(struct lookup_subtable));
+ sub->lookup = otl;
+ sub->per_glyph_pst_or_kern = true;
+ if ( last==NULL )
+ otl->subtables = sub;
+ else
+ last->next = sub;
+ last = sub;
+ }
+ l->u2.pst->subtable = sub;
+ l->u2.pst->next = l->u1.sc->possub;
+ l->u1.sc->possub = l->u2.pst;
+ l->u2.pst = NULL; /* So we don't free it later */
+ break;
+ default:
+ IError("Unexpected feature type %d in a PST feature", l->type );
+ break;
+ }
+ }
+}
+
+static OTLookup *fea_ApplyLookupList(struct parseState *tok,
+ struct feat_item *lookup_data,int lookup_flag);
+
+static void fea_ApplyLookupListContextual(struct parseState *tok,
+ struct feat_item *lookup_data,OTLookup *otl) {
+ struct lookup_subtable *sub = NULL, *last=NULL;
+ struct feat_item *l;
+ int i,j;
+ /* Fpst's are almost as easy as psts. We don't worry about subtables */
+ /* (every fpst gets a new subtable, so the statement is irrelevant) */
+ /* the only complication is that we must recursively handle a lookup list */
+ /* There might be a lookupflags */
+
+ for ( l = lookup_data; l!=NULL; l=l->lookup_next ) {
+ switch ( l->type ) {
+ case ft_lookup_start:
+ case ft_lookupflags:
+ case ft_subtable:
+ /* Ignore these, already handled them */;
+ break;
+ case ft_fpst:
+ sub = chunkalloc(sizeof(struct lookup_subtable));
+ sub->lookup = otl;
+ if ( last==NULL )
+ otl->subtables = sub;
+ else
+ last->next = sub;
+ last = sub;
+ sub->fpst = l->u2.fpst;
+ l->u2.fpst = NULL;
+ sub->fpst->subtable = sub;
+ for ( i=0; i<sub->fpst->rule_cnt; ++i ) {
+ struct fpst_rule *r = &sub->fpst->rules[i];
+ for ( j=0; j<r->lookup_cnt; ++j ) {
+ if ( r->lookups[j].lookup!=NULL ) {
+ struct feat_item *nested = (struct feat_item *) (r->lookups[j].lookup);
+ fea_SetLookupLink(nested,ot_undef);
+ r->lookups[j].lookup = fea_ApplyLookupList(tok,nested,otl->lookup_flags); /* Not really sure what the lookup flag should be here. */
+ fea_featitemFree(nested);
+ }
+ }
+ }
+ break;
+ default:
+ IError("Unexpected feature type %d in a FPST feature", l->type );
+ break;
+ }
+ }
+}
+
+static void fea_ApplyLookupListCursive(struct parseState *tok,
+ struct feat_item *lookup_data,OTLookup *otl) {
+ struct lookup_subtable *sub = NULL, *last=NULL;
+ struct feat_item *l;
+ AnchorPoint *aplast, *ap;
+ AnchorClass *ac = NULL;
+ /* Cursive's are also easy. There might be two ap's in the list so slight */
+ /* care needed when adding them to a glyph, and we must create an anchorclass */
+ /* There might be a subtable break */
+ /* There might be a lookupflags */
+
+ for ( l = lookup_data; l!=NULL; l=l->lookup_next ) {
+ switch ( l->type ) {
+ case ft_lookup_start:
+ case ft_lookupflags:
+ /* Ignore these, already handled them */;
+ break;
+ case ft_subtable:
+ sub = NULL;
+ break;
+ case ft_ap:
+ if ( sub==NULL ) {
+ sub = chunkalloc(sizeof(struct lookup_subtable));
+ sub->lookup = otl;
+ sub->anchor_classes = true;
+ if ( last==NULL )
+ otl->subtables = sub;
+ else
+ last->next = sub;
+ last = sub;
+ ac = chunkalloc(sizeof(AnchorClass));
+ ac->subtable = sub;
+ ac->type = act_curs;
+ ac->next = tok->accreated;
+ tok->accreated = ac;
+ }
+ aplast = NULL;
+ for ( ap=l->u2.ap; ap!=NULL; ap=ap->next ) {
+ aplast = ap;
+ ap->anchor = ac;
+ }
+ aplast->next = l->u1.sc->anchor;
+ l->u1.sc->anchor = l->u2.ap;
+ l->u2.ap = NULL; /* So we don't free them later */
+ break;
+ default:
+ IError("Unexpected feature type %d in a cursive feature", l->type );
+ break;
+ }
+ }
+}
+
+static void fea_ApplyLookupListMark2(struct parseState *tok,
+ struct feat_item *lookup_data,int mcnt,OTLookup *otl) {
+ /* Mark2* lookups are not well documented (because adobe FDK doesn't */
+ /* support them) but I'm going to assume that if I have some mark */
+ /* statements, then some pos statement, then another mark statement */
+ /* that I begin a new subtable with the second set of marks (and a */
+ /* different set of mark classes) */
+ char **classes;
+ AnchorClass **acs;
+ int ac_cnt, i;
+ struct lookup_subtable *sub = NULL, *last=NULL;
+ struct feat_item *mark_start, *l;
+ AnchorPoint *ap, *aplast;
+
+ classes = galloc(mcnt*sizeof(char *));
+ acs = galloc(mcnt*sizeof(AnchorClass *));
+ ac_cnt = 0;
+ while ( lookup_data != NULL ) {
+ sub = NULL;
+ /* Skip any subtable marks */
+ while ( lookup_data!=NULL &&
+ (lookup_data->type==ft_subtable ||
+ lookup_data->type==ft_lookup_start ||
+ lookup_data->type==ft_lookupflags ) )
+ lookup_data = lookup_data->lookup_next;
+
+ /* Skip over the marks, we'll deal with them after we know the mark classes */
+ mark_start = lookup_data;
+ while ( lookup_data!=NULL &&
+ ((lookup_data->type==ft_ap && lookup_data->u2.ap->type==at_mark) ||
+ lookup_data->type==ft_lookup_start ||
+ lookup_data->type==ft_lookupflags ) )
+ lookup_data = lookup_data->lookup_next;
+
+ /* Now process the base glyphs and figure out the mark classes */
+ while ( lookup_data!=NULL &&
+ ((lookup_data->type==ft_ap && lookup_data->mark_class!=NULL) ||
+ lookup_data->type==ft_lookup_start ||
+ lookup_data->type==ft_lookupflags ) ) {
+ if ( lookup_data->type == ft_ap ) {
+ for ( i=0; i<ac_cnt; ++i ) {
+ if ( strcmp(lookup_data->mark_class,classes[i])==0 )
+ break;
+ }
+ if ( i==ac_cnt ) {
+ ++ac_cnt;
+ classes[i] = lookup_data->mark_class;
+ acs[i] = chunkalloc(sizeof(AnchorClass));
+ if ( sub==NULL ) {
+ sub = chunkalloc(sizeof(struct lookup_subtable));
+ sub->lookup = otl;
+ sub->anchor_classes = true;
+ if ( last==NULL )
+ otl->subtables = sub;
+ else
+ last->next = sub;
+ last = sub;
+ }
+ acs[i]->subtable = sub;
+ acs[i]->type = otl->lookup_type==gpos_mark2mark ? act_mkmk :
+ otl->lookup_type==gpos_mark2base ? act_mark :
+ act_mklg;
+ acs[i]->next = tok->accreated;
+ tok->accreated = acs[i];
+ }
+ aplast = NULL;
+ for ( ap=lookup_data->u2.ap; ap!=NULL; ap=ap->next ) {
+ aplast = ap;
+ ap->anchor = acs[i];
+ }
+ aplast->next = lookup_data->u1.sc->anchor;
+ lookup_data->u1.sc->anchor = lookup_data->u2.ap;
+ lookup_data->u2.ap = NULL; /* So we don't free them later */
+ }
+ lookup_data = lookup_data->next;
+ }
+
+ /* Now go back and assign the marks to the correct anchor classes */
+ for ( l=mark_start; l!=NULL &&
+ ((l->type==ft_ap && l->u2.ap->type==at_mark) ||
+ l->type==ft_lookup_start ||
+ l->type==ft_lookupflags ) ;
+ l = l->lookup_next ) {
+ if ( l->type==ft_ap ) {
+ for ( i=0; i<ac_cnt; ++i ) {
+ if ( fea_classesIntersect(l->u1.sc->name,classes[i])) {
+ AnchorPoint *ap = AnchorPointsCopy(l->u2.ap);
+ /* We make a copy of this anchor point because marks */
+ /* might be used in more than one lookup. It makes */
+ /* sense for a user to define a set of marks to be */
+ /* used with both a m2base and a m2lig lookup within */
+ /* a feature */
+ ap->anchor = acs[i];
+ ap->next = l->u1.sc->anchor;
+ l->u1.sc->anchor = ap;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+struct class_set {
+ char **classes;
+ int cnt, max;
+};
+
+/* We've got a set of glyph classes -- but they are the classes that make sense */
+/* to the user and so there's no guarantee that there aren't two classes with */
+/* the same glyph(s) */
+/* Simplify the list so that: There are no duplicates classes and each name */
+/* appears in at most one class. This is what we need */
+static void fea_canonicalClassSet(struct class_set *set) {
+ int i,j,k;
+
+ /* Remove any duplicate classes */
+ qsort(set->classes,set->cnt,sizeof(char *), strcmpD);
+ for ( i=0; i<set->cnt; ++i ) {
+ for ( j=i+1; j<set->cnt; ++j )
+ if ( strcmp(set->classes[i],set->classes[j])!=0 )
+ break;
+ if ( j>i+1 ) {
+ int off = j-(i+1);
+ for ( k=i+1; k<j; ++k )
+ free(set->classes[k]);
+ for ( k=j ; k<set->cnt; ++k )
+ set->classes[k-off] = set->classes[k];
+ set->cnt -= off;
+ }
+ }
+ for ( i=1; i<set->cnt; ++i ) {
+ if ( fea_classesIntersect(set->classes[i-1],set->classes[i]) ) {
+ if ( set->cnt>=set->max )
+ set->classes = grealloc(set->classes,(set->max+=20)*sizeof(char *));
+ set->classes[set->cnt++] = fea_classesSplit(set->classes[i-1],set->classes[i]);
+ }
+ }
+}
+
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+static void KCFillDevTab(KernClass *kc,int index,DeviceTable *dt) {
+ if ( dt==NULL || dt->corrections == NULL )
+return;
+ if ( kc->adjusts == NULL )
+ kc->adjusts = gcalloc(kc->first_cnt*kc->second_cnt,sizeof(DeviceTable));
+ kc->adjusts[index] = *dt;
+ kc->adjusts[index].corrections = galloc(dt->last_pixel_size-dt->first_pixel_size+1);
+ memcpy(kc->adjusts[index].corrections,dt->corrections,dt->last_pixel_size-dt->first_pixel_size+1);
+
+}
+
+static void KPFillDevTab(KernPair *kp,DeviceTable *dt) {
+ if ( dt==NULL || dt->corrections == NULL )
+return;
+ kp->adjust = chunkalloc(sizeof(DeviceTable));
+ *kp->adjust = *dt;
+ kp->adjust->corrections = galloc(dt->last_pixel_size-dt->first_pixel_size+1);
+ memcpy(kp->adjust->corrections,dt->corrections,dt->last_pixel_size-dt->first_pixel_size+1);
+}
+#endif
+
+static void fea_fillKernClass(KernClass *kc,struct feat_item *l) {
+ int i,j;
+ PST *pst;
+
+ while ( l!=NULL && l->type!=ft_subtable ) {
+ if ( l->type==ft_pstclass ) {
+ pst = l->u2.pst;
+ for ( i=1; i<kc->first_cnt; ++i ) {
+ if ( fea_classesIntersect(kc->firsts[i],l->u1.class) ) {
+ for ( j=1; j<kc->first_cnt; ++j ) {
+ if ( fea_classesIntersect(kc->seconds[j],pst->u.pair.paired) ) {
+ /* FontForge only supports kerning classes in one direction at a time, not full value records */
+ if ( pst->u.pair.vr[0].h_adv_off != 0 ) {
+ kc->offsets[i*kc->second_cnt+j] = pst->u.pair.vr[0].h_adv_off;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( pst->u.pair.vr[0].adjust!=NULL )
+ KCFillDevTab(kc,i*kc->second_cnt+j,&pst->u.pair.vr[0].adjust->xadv);
+#endif
+ } else if ( pst->u.pair.vr[0].v_adv_off != 0 ) {
+ kc->offsets[i*kc->second_cnt+j] = pst->u.pair.vr[0].v_adv_off;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( pst->u.pair.vr[0].adjust!=NULL )
+ KCFillDevTab(kc,i*kc->second_cnt+j,&pst->u.pair.vr[0].adjust->yadv);
+#endif
+ } else if ( pst->u.pair.vr[1].h_adv_off != 0 ) {
+ kc->offsets[i*kc->second_cnt+j] = pst->u.pair.vr[1].h_adv_off;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( pst->u.pair.vr[1].adjust!=NULL )
+ KCFillDevTab(kc,i*kc->second_cnt+j,&pst->u.pair.vr[1].adjust->xadv);
+#endif
+ }
+ if ( strcmp(kc->seconds[j],pst->u.pair.paired)==0 )
+ break;
+ }
+ }
+ if ( strcmp(kc->firsts[i],l->u1.class)==0 )
+ break;
+ }
+ }
+ }
+ l = l->lookup_next;
+ }
+}
+
+static void fea_ApplyLookupListPair(struct parseState *tok,
+ struct feat_item *lookup_data,int kmax,OTLookup *otl) {
+ /* kcnt is the number of left/right glyph-name-lists we must sort into classes */
+ struct feat_item *l, *first;
+ struct class_set lefts, rights;
+ struct lookup_subtable *sub = NULL, *lastsub=NULL;
+ SplineChar *sc, *other;
+ PST *pst;
+ KernPair *kp;
+ KernClass *kc;
+ int vkern, kcnt, i;
+
+ memset(&lefts,0,sizeof(lefts));
+ memset(&rights,0,sizeof(rights));
+ if ( kmax!=0 ) {
+ lefts.classes = galloc(kmax*sizeof(char *));
+ rights.classes = galloc(kmax*sizeof(char *));
+ lefts.max = rights.max = kmax;
+ }
+ vkern = false;
+ for ( l = lookup_data; l!=NULL; ) {
+ first = l;
+ kcnt = 0;
+ while ( l!=NULL && l->type!=ft_subtable ) {
+ if ( l->type == ft_pst ) {
+ if ( sub==NULL ) {
+ sub = chunkalloc(sizeof(struct lookup_subtable));
+ sub->lookup = otl;
+ sub->per_glyph_pst_or_kern = true;
+ if ( lastsub==NULL )
+ otl->subtables = sub;
+ else
+ lastsub->next = sub;
+ lastsub = sub;
+ }
+ pst = l->u2.pst;
+ sc = l->u1.sc;
+ l->u2.pst = NULL;
+ kp = NULL;
+ other = SFGetChar(sc->parent,-1,pst->u.pair.paired);
+ if ( pst->u.pair.vr[0].xoff==0 && pst->u.pair.vr[0].yoff==0 &&
+ pst->u.pair.vr[1].xoff==0 && pst->u.pair.vr[1].yoff==0 &&
+ pst->u.pair.vr[1].v_adv_off==0 &&
+ other!=NULL ) {
+ if ( (otl->lookup_flags&pst_r2l) &&
+ (pst->u.pair.vr[0].h_adv_off==0 && pst->u.pair.vr[0].v_adv_off==0 )) {
+ kp = chunkalloc(sizeof(KernPair));
+ kp->off = pst->u.pair.vr[1].h_adv_off;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( pst->u.pair.vr[1].adjust!=NULL )
+ KPFillDevTab(kp,&pst->u.pair.vr[1].adjust->xadv);
+#endif
+ } else if ( !(otl->lookup_flags&pst_r2l) &&
+ (pst->u.pair.vr[1].h_adv_off==0 && pst->u.pair.vr[0].v_adv_off==0 )) {
+ kp = chunkalloc(sizeof(KernPair));
+ kp->off = pst->u.pair.vr[0].h_adv_off;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( pst->u.pair.vr[0].adjust!=NULL )
+ KPFillDevTab(kp,&pst->u.pair.vr[0].adjust->xadv);
+#endif
+ } else if ( (pst->u.pair.vr[0].h_adv_off==0 && pst->u.pair.vr[1].h_adv_off==0 )) {
+ vkern = sub->vertical_kerning = true;
+ kp = chunkalloc(sizeof(KernPair));
+ kp->off = pst->u.pair.vr[0].v_adv_off;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( pst->u.pair.vr[0].adjust!=NULL )
+ KPFillDevTab(kp,&pst->u.pair.vr[0].adjust->yadv);
+#endif
+ }
+ }
+ if ( kp!=NULL ) {
+ kp->sc = other;
+ kp->subtable = sub;
+ if ( vkern ) {
+ kp->next = sc->vkerns;
+ sc->vkerns = kp;
+ } else {
+ kp->next = sc->kerns;
+ sc->kerns = kp;
+ }
+ PSTFree(pst);
+ } else {
+ pst->subtable = sub;
+ pst->next = sc->possub;
+ sc->possub = pst;
+ }
+ } else if ( l->type == ft_pstclass ) {
+ lefts.classes[kcnt] = copy(fea_canonicalClassOrder(l->u1.class));
+ rights.classes[kcnt++] = copy(fea_canonicalClassOrder(l->u2.pst->u.pair.paired));
+ }
+ l = l->lookup_next;
+ }
+ if ( kcnt!=0 ) {
+ lefts.cnt = rights.cnt = kcnt;
+ fea_canonicalClassSet(&lefts);
+ fea_canonicalClassSet(&rights);
+
+ sub = chunkalloc(sizeof(struct lookup_subtable));
+ sub->lookup = otl;
+ if ( lastsub==NULL )
+ otl->subtables = sub;
+ else
+ lastsub->next = sub;
+ lastsub = sub;
+
+ sub->kc = kc = chunkalloc(sizeof(KernClass));
+ kc->first_cnt = lefts.cnt+1; kc->second_cnt = rights.cnt+1;
+ kc->firsts = galloc(kc->first_cnt*sizeof(char *));
+ kc->seconds = galloc(kc->second_cnt*sizeof(char *));
+ kc->firsts[0] = kc->seconds[0] = NULL;
+ for ( i=0; i<lefts.cnt; ++i )
+ kc->firsts[i+1] = lefts.classes[i];
+ for ( i=0; i<rights.cnt; ++i )
+ kc->seconds[i+1] = rights.classes[i];
+ kc->subtable = sub;
+ kc->offsets = gcalloc(kc->first_cnt*kc->second_cnt,sizeof(int16));
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ kc->adjusts = gcalloc(kc->first_cnt*kc->second_cnt,sizeof(DeviceTable));
+#endif
+ fea_fillKernClass(kc,first);
+ if ( sub->vertical_kerning ) {
+ kc->next = tok->sf->vkerns;
+ tok->sf->vkerns = kc;
+ } else {
+ kc->next = tok->sf->kerns;
+ tok->sf->kerns = kc;
+ }
+ }
+ sub = NULL;
+ while ( l!=NULL && l->type==ft_subtable )
+ l = l->lookup_next;
+ }
+ if ( kmax!=0 ) {
+ free(lefts.classes);
+ free(rights.classes);
+ }
+}
+
+static OTLookup *fea_ApplyLookupList(struct parseState *tok,
+ struct feat_item *lookup_data,int lookup_flag) {
+ /* A lookup list might consist just of a lookup_ref so find the lookup named u1.lookup_name */
+ /* A lookup_start is optional and provides the lookup name */
+ /* A lookupflags is optional and may occur anywhere u2.lookupflags */
+ /* An ap is for mark2 types for the mark u1.sc and u2.ap (not grouped in anchor classes yet) */
+ /* A fpst is for contextuals u2.fpst (rule.lookups[i].lookup are lookup lists in their own rights that need to become lookups) */
+ /* A subtable means a subtable break, make up a new name, ignore multiple subtable entries */
+ /* A pst is for simple things u1.sc, u2.pst */
+ /* A pstclass is for kerning classes u1.class, u2.pst (paired may be a class list too) */
+ /* An ap is for cursive types for the u1.sc and u2.ap (an entry and an exit ap) */
+ /* An ap is for mark2 types for the base u1.sc and u2.ap and mark_class */
+ OTLookup *otl;
+ int kcnt, mcnt;
+ struct feat_item *l;
+ enum otlookup_type temp;
+
+ if ( lookup_data->type == ft_lookup_ref ) {
+ for ( otl=tok->created; otl!=NULL; otl=otl->next )
+ if ( otl->lookup_name!=NULL &&
+ strcmp(otl->lookup_name,lookup_data->u1.lookup_name)==0)
+return( otl );
+return( SFFindLookup(tok->sf,lookup_data->u1.lookup_name));
+ }
+
+ otl = chunkalloc(sizeof(OTLookup));
+ otl->lookup_flags = lookup_flag;
+ otl->lookup_type = ot_undef;
+ if ( tok->last==NULL )
+ tok->created = otl;
+ else
+ tok->last->next = otl;
+ tok->last = otl;
+
+ /* Search first for class counts */
+ kcnt = mcnt = 0;
+ for ( l = lookup_data; l!=NULL; l=l->lookup_next ) {
+ if ( l->type == ft_ap && l->mark_class!=NULL )
+ ++mcnt;
+ else if ( l->type == ft_pstclass )
+ ++kcnt;
+ else if ( l->type == ft_lookupflags )
+ otl->lookup_flags = l->u2.lookupflags;
+ else if ( l->type == ft_lookup_start ) {
+ otl->lookup_name = l->u1.lookup_name;
+ l->u1.lookup_name = NULL; /* So we don't free it later */
+ }
+ temp = fea_LookupTypeFromItem(l);
+ if ( temp==ot_undef )
+ /* Tum ty tum tum. No information */;
+ else if ( otl->lookup_type == ot_undef )
+ otl->lookup_type = temp;
+ else if ( otl->lookup_type != temp )
+ IError(_("Mismatch lookup types inside a parsed lookup"));
+ }
+ if ( otl->lookup_type==gpos_mark2base ||
+ otl->lookup_type==gpos_mark2ligature ||
+ otl->lookup_type==gpos_mark2mark )
+ fea_ApplyLookupListMark2(tok,lookup_data,mcnt,otl);
+ else if ( mcnt!=0 )
+ IError(_("Mark anchors provided when nothing can use them"));
+ else if ( otl->lookup_type==gpos_cursive )
+ fea_ApplyLookupListCursive(tok,lookup_data,otl);
+ else if ( otl->lookup_type==gpos_pair )
+ fea_ApplyLookupListPair(tok,lookup_data,kcnt,otl);
+ else if ( otl->lookup_type==gpos_contextchain ||
+ otl->lookup_type==gsub_contextchain )
+ fea_ApplyLookupListContextual(tok,lookup_data,otl);
+ else
+ fea_ApplyLookupListPST(tok,lookup_data,otl);
+return( otl );
+}
+
+static struct otfname *fea_NameID2OTFName(struct nameid *names) {
+ struct otfname *head=NULL, *cur;
+
+ while ( names!=NULL ) {
+ cur = chunkalloc(sizeof(struct otfname));
+ cur->lang = names->language;
+ cur->name = names->utf8_str;
+ names->utf8_str = NULL;
+ cur->next = head;
+ head = cur;
+ names = names->next;
+ }
+return( head );
+}
+
+static void fea_AttachFeatureToLookup(OTLookup *otl,uint32 feat_tag,
+ struct scriptlanglist *sl) {
+ FeatureScriptLangList *fl;
+
+ for ( fl = otl->features; fl!=NULL && fl->featuretag!=feat_tag; fl=fl->next );
+ if ( fl==NULL ) {
+ fl = chunkalloc(sizeof(FeatureScriptLangList));
+ fl->next = otl->features;
+ otl->features = fl;
+ fl->featuretag = feat_tag;
+ fl->scripts = SLCopy(sl);
+ } else
+ SLMerge(fl,sl);
+}
+
+static void fea_NameID2NameTable(SplineFont *sf, struct nameid *names) {
+ struct ttflangname *cur;
+
+ while ( names!=NULL ) {
+ for ( cur = sf->names; cur!=NULL && cur->lang!=names->language; cur=cur->next );
+ if ( cur==NULL ) {
+ cur = chunkalloc(sizeof(struct ttflangname));
+ cur->lang = names->language;
+ cur->next = sf->names;
+ sf->names = cur;
+ }
+ free(cur->names[names->strid]);
+ cur->names[names->strid] = names->utf8_str;
+ names->utf8_str = NULL;
+ names = names->next;
+ }
+}
+
+static void fea_TableByKeywords(SplineFont *sf, struct feat_item *f) {
+ struct tablevalues *tv;
+ struct tablekeywords *offsets = f->u1.offsets, *cur;
+ int i;
+
+ if ( !sf->pfminfo.pfmset ) {
+ SFDefaultOS2Info(&sf->pfminfo,sf,sf->fontname);
+ sf->pfminfo.pfmset = sf->pfminfo.subsuper_set = sf->pfminfo.panose_set =
+ sf->pfminfo.hheadset = sf->pfminfo.vheadset = true;
+ }
+ for ( tv = f->u2.tvals; tv!=NULL; tv=tv->next ) {
+ cur = &offsets[tv->index];
+ if ( cur->offset==-1 )
+ /* We don't support this guy, whatever he may be, but we did parse it */;
+ else if ( cur->cnt==1 ) {
+ if ( cur->size==4 )
+ *((uint32 *) (((uint8 *) sf) + cur->offset)) = tv->value;
+ else if ( cur->size==2 )
+ *((uint16 *) (((uint8 *) sf) + cur->offset)) = tv->value;
+ else
+ *((uint8 *) (((uint8 *) sf) + cur->offset)) = tv->value;
+ if ( strcmp(cur->name,"Ascender")==0 )
+ sf->pfminfo.hheadascent_add = false;
+ else if ( strcmp(cur->name,"Descender")==0 )
+ sf->pfminfo.hheaddescent_add = false;
+ else if ( strcmp(cur->name,"winAscent")==0 )
+ sf->pfminfo.winascent_add = false;
+ else if ( strcmp(cur->name,"winDescent")==0 )
+ sf->pfminfo.windescent_add = false;
+ else if ( strcmp(cur->name,"TypoAscender")==0 )
+ sf->pfminfo.typoascent_add = false;
+ else if ( strcmp(cur->name,"TypoDescender")==0 )
+ sf->pfminfo.typodescent_add = false;
+ } else if ( cur->cnt==10 && cur->size==1 ) {
+ for ( i=0; i<10; ++i )
+ (((uint8 *) sf) + cur->offset)[i] = tv->panose_vals[i];
+ }
+ }
+}
+
+static void fea_GDefGlyphClasses(SplineFont *sf, struct feat_item *f) {
+ int i, ch;
+ char *pt, *start;
+ SplineChar *sc;
+
+ for ( i=0; i<4; ++i ) if ( f->u1.gdef_classes[i]!=NULL ) {
+ for ( pt=f->u1.gdef_classes[i]; ; ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ for ( start = pt; *pt!=' ' && *pt!='\0'; ++pt );
+ ch = *pt; *pt = '\0';
+ sc = SFGetChar(sf,-1,start);
+ *pt = ch;
+ if ( sc!=NULL )
+ sc->glyph_class = i+1;
+ }
+ }
+}
+
+static void fea_GDefLigCarets(SplineFont *sf, struct feat_item *f) {
+ int i, ch;
+ char *pt, *start;
+ SplineChar *sc;
+ PST *pst, *prev, *next;
+
+ for ( pt=f->u1.class; ; ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ for ( start = pt; *pt!=' ' && *pt!='\0'; ++pt );
+ ch = *pt; *pt = '\0';
+ sc = SFGetChar(sf,-1,start);
+ *pt = ch;
+ if ( sc!=NULL ) {
+ for ( prev=NULL, pst=sc->possub; pst!=NULL; pst=next ) {
+ next = pst->next;
+ if ( pst->type!=pst_lcaret )
+ prev = pst;
+ else {
+ if ( prev==NULL )
+ sc->possub = next;
+ else
+ prev->next = next;
+ pst->next = NULL;
+ PSTFree(pst);
+ }
+ }
+ for ( i=0; f->u2.lcaret[i]!=0; ++i );
+ pst = chunkalloc(sizeof(PST));
+ pst->next = sc->possub;
+ sc->possub = pst;
+ pst->type = pst_lcaret;
+ pst->u.lcaret.cnt = i;
+ pst->u.lcaret.carets = f->u2.lcaret;
+ f->u2.lcaret = NULL;
+ }
+ }
+}
+
+static struct feat_item *fea_ApplyFeatureList(struct parseState *tok,
+ struct feat_item *feat_data) {
+ int lookup_flags = 0;
+ uint32 feature_tag = feat_data->u1.tag;
+ struct scriptlanglist *sl = feat_data->u2.sl;
+ struct feat_item *f, *start;
+ OTLookup *otl;
+ int saw_script = false;
+ enum otlookup_type ltype;
+
+ feat_data->u2.sl = NULL;
+
+ for ( f=feat_data->next; f!=NULL && f->type!=ft_feat_end ; ) {
+ if ( f->ticked ) {
+ f = f->next;
+ continue;
+ }
+ switch ( f->type ) {
+ case ft_lookupflags:
+ lookup_flags = f->u2.lookupflags;
+ f = f->next;
+ continue;
+ case ft_lookup_ref:
+ otl = fea_ApplyLookupList(tok,f,lookup_flags);
+ fea_AttachFeatureToLookup(otl,feature_tag,sl);
+ f = f->next;
+ continue;
+ case ft_lookup_start:
+ start = f;
+ start->lookup_next = f->next;
+ f = fea_SetLookupLink(start->next,ot_undef);
+ if ( f!=NULL && f->type == ft_lookup_end )
+ f = f->next;
+ otl = fea_ApplyLookupList(tok,start,lookup_flags);
+ fea_AttachFeatureToLookup(otl,feature_tag,sl);
+ continue;
+ case ft_script:
+ ScriptLangListFree(sl);
+ sl = chunkalloc(sizeof(struct scriptlanglist));
+ sl->script = f->u1.tag;
+ sl->lang_cnt = 1;
+ sl->langs[0] = DEFAULT_LANG;
+ saw_script = true;
+ f = f->next;
+ continue;
+ case ft_lang:
+ if ( !saw_script ) {
+ ScriptLangListFree(sl);
+ sl = chunkalloc(sizeof(struct scriptlanglist));
+ sl->script = CHR('l','a','t','n');
+ }
+ sl->langs[0] = f->u1.tag;
+ sl->lang_cnt = 1;
+ if ( !f->u2.exclude_dflt ) {
+ if ( sl->langs[0]!=DEFAULT_LANG ) {
+ sl->langs[1] = DEFAULT_LANG;
+ sl->lang_cnt = 2;
+ }
+ }
+ f = f->next;
+ continue;
+ case ft_langsys:
+ ScriptLangListFree(sl);
+ saw_script = false;
+ sl = f->u2.sl;
+ f->u2.sl = NULL;
+ f = f->next;
+ continue;
+ case ft_sizeparams:
+ if ( f->u1.params!=NULL ) {
+ tok->sf->design_size = f->u1.params[0];
+ tok->sf->fontstyle_id = f->u1.params[1];
+ tok->sf->design_range_bottom = f->u1.params[2];
+ tok->sf->design_range_top = f->u1.params[3];
+ }
+ OtfNameListFree(tok->sf->fontstyle_name);
+ tok->sf->fontstyle_name = fea_NameID2OTFName(f->u2.names);
+ f = f->next;
+ continue;
+ case ft_subtable:
+ f = f->next;
+ continue;
+ case ft_pst:
+ case ft_pstclass:
+ case ft_ap:
+ case ft_fpst:
+ if ( f->type==ft_ap && f->u2.ap->type==at_mark ) {
+ struct feat_item *n, *a;
+ /* skip over the marks */
+ for ( n=f; n!=NULL && n->type == ft_ap && n->u2.ap->type==at_mark; n=n->next );
+ /* find the next thing which can use those marks (might not be anything) */
+ for ( a=n; a!=NULL; a=a->next ) {
+ if ( a->ticked )
+ continue;
+ if ( fea_FeatItemEndsLookup(a->type) ||
+ a->type==ft_subtable || a->type==ft_ap )
+ break;
+ }
+ if ( a==NULL || fea_FeatItemEndsLookup(a->type) || a->type==ft_subtable ||
+ (a->type==ft_ap && a->u2.ap->type == at_mark )) {
+ /* There's nothing else that can use these marks so we are */
+ /* done with them. Skip over all of them */
+ f = n;
+ continue;
+ }
+ ltype = fea_LookupTypeFromItem(a);
+ } else
+ ltype = fea_LookupTypeFromItem(f);
+ start = f;
+ f = fea_SetLookupLink(start,ltype);
+ otl = fea_ApplyLookupList(tok,start,lookup_flags);
+ fea_AttachFeatureToLookup(otl,feature_tag,sl);
+ continue;
+ default:
+ IError("Unexpected feature item in feature definition %d", f->type );
+ f = f->next;
+ }
+ }
+ if ( f!=NULL && f->type == ft_feat_end )
+ f = f->next;
+return( f );
+}
+
+static void fea_ApplyFile(struct parseState *tok, struct feat_item *item) {
+ struct feat_item *f, *start;
+
+ for ( f=item; f!=NULL ; ) {
+ switch ( f->type ) {
+ case ft_lookup_start:
+ start = f;
+ start->lookup_next = f->next;
+ f = fea_SetLookupLink(start->next,ot_undef);
+ if ( f!=NULL && f->type == ft_lookup_end )
+ f = f->next;
+ fea_ApplyLookupList(tok,start,0);
+ continue;
+ case ft_feat_start:
+ f = fea_ApplyFeatureList(tok,f);
+ continue;
+ case ft_table:
+ /* I store things all mushed together, so this tag is useless to me*/
+ /* ignore it. The stuff inside the table matters though... */
+ f = f->next;
+ continue;
+ case ft_names:
+ fea_NameID2NameTable(tok->sf,f->u2.names);
+ f = f->next;
+ continue;
+ case ft_tablekeys:
+ fea_TableByKeywords(tok->sf,f);
+ f = f->next;
+ continue;
+ case ft_gdefclasses:
+ fea_GDefGlyphClasses(tok->sf,f);
+ f = f->next;
+ continue;
+ case ft_lcaret:
+ fea_GDefLigCarets(tok->sf,f);
+ f = f->next;
+ continue;
+ default:
+ IError("Unexpected feature item in feature file %d", f->type );
+ f = f->next;
+ }
+ }
+}
+
+static struct feat_item *fea_reverseList(struct feat_item *f) {
+ struct feat_item *n = NULL, *p = NULL;
+
+ p = NULL;
+ while ( f!=NULL ) {
+ n = f->next;
+ f->next = p;
+ p = f;
+ f = n;
+ }
+return( p );
+}
+
+static void fea_NameLookups(struct parseState *tok) {
+ SplineFont *sf = tok->sf;
+ OTLookup *gpos_last, *gsub_last, *otl, *otlnext;
+ int gp_cnt=0, gs_cnt=0, acnt;
+ AnchorClass *ac, *acnext, *an;
+
+ for ( gpos_last = sf->gpos_lookups; gpos_last!=NULL; gpos_last=gpos_last->next )
+ gpos_last->lookup_index = gp_cnt++;
+ for ( gsub_last = sf->gsub_lookups; gsub_last!=NULL; gsub_last=gsub_last->next )
+ gsub_last->lookup_index = gs_cnt++;
+
+ for ( otl = tok->created; otl!=NULL; otl=otlnext ) {
+ otlnext = otl->next;
+ otl->next = NULL;
+ if ( otl->lookup_name!=NULL && SFFindLookup(sf,otl->lookup_name)!=NULL ) {
+ int cnt=0;
+ char *namebuf = galloc(strlen( otl->lookup_name )+8 );
+ /* Name already in use, modify it */
+ do {
+ sprintf(namebuf,"%s-%d", otl->lookup_name, cnt++ );
+ } while ( SFFindLookup(sf,namebuf)!=NULL );
+ free(otl->lookup_name);
+ otl->lookup_name = namebuf;
+ }
+ if ( otl->lookup_type < gpos_start ) {
+ if ( gsub_last==NULL )
+ sf->gsub_lookups = otl;
+ else
+ gsub_last->next = otl;
+ gsub_last = otl;
+ otl->lookup_index = gs_cnt++;
+ } else {
+ if ( gpos_last==NULL )
+ sf->gpos_lookups = otl;
+ else
+ gpos_last->next = otl;
+ gpos_last = otl;
+ otl->lookup_index = gp_cnt++;
+ }
+ NameOTLookup(otl,sf); /* But only if it has no name */
+ }
+
+ /* Now name and attach any unnamed anchor classes (order here doesn't matter) */
+ acnt = 0;
+ for ( ac=tok->accreated; ac!=NULL; ac=acnext ) {
+ acnext = ac->next;
+ if ( ac->name==NULL ) {
+ char buf[50];
+ do {
+ snprintf(buf,sizeof(buf),_("Anchor-%d"), acnt++ );
+ for ( an=sf->anchor; an!=NULL && strcmp(an->name,buf)!=0; an=an->next );
+ } while ( an!=NULL );
+ ac->name = copy(buf);
+ }
+ ac->next = sf->anchor;
+ sf->anchor = ac;
+ }
+
+ sf->changed = true;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FVSetTitle(sf->fv);
+ if ( sf->fv->v!=NULL )
+ GDrawRequestExpose(sf->fv->v,NULL,false);
+#endif
+}
+
+void SFApplyFeatureFile(SplineFont *sf,FILE *file,char *filename) {
+ struct parseState tok;
+ struct glyphclasses *gc, *gcnext;
+
+ memset(&tok,0,sizeof(tok));
+ tok.line[0] = 1;
+ tok.filename[0] = filename;
+ tok.inlist[0] = file;
+ tok.base = 10;
+ if ( sf->cidmaster ) sf = sf->cidmaster;
+ tok.sf = sf;
+
+ fea_ParseFeatureFile(&tok);
+ if ( tok.err_count==0 ) {
+ tok.sofar = fea_reverseList(tok.sofar);
+ fea_ApplyFile(&tok, tok.sofar);
+ fea_NameLookups(&tok);
+ } else
+ gwwv_post_error("Not applied","There were errors when parsing the feature file and the features have not been applied");
+ fea_featitemFree(tok.sofar);
+ ScriptLangListFree(tok.def_langsyses);
+ for ( gc = tok.classes; gc!=NULL; gc=gcnext ) {
+ gcnext = gc->next;
+ free(gc->classname); free(gc->glyphs);
+ chunkfree(gc,sizeof(struct glyphclasses));
+ }
+}
+
+void SFApplyFeatureFilename(SplineFont *sf,char *filename) {
+ FILE *in = fopen(filename,"r");
+
+ if ( in==NULL ) {
+ gwwv_post_error(_("Cannot open file"),_("Cannot open feature file %.120s"), filename );
+return;
+ }
+ SFApplyFeatureFile(sf,in,filename);
+ fclose(in);
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/fontinfo.c b/Build/source/libs/luafontforge/fontforge/fontforge/fontinfo.c
new file mode 100644
index 00000000000..da8f2441c1f
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/fontinfo.c
@@ -0,0 +1,10184 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaeditui.h"
+#include "ofl.h"
+#include <ustring.h>
+#include <chardata.h>
+#include <utype.h>
+#include "unicoderange.h"
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+extern int _GScrollBar_Width;
+#endif
+#include <gkeysym.h>
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+
+#ifdef LUA_FF_LIB
+#define Isspace(a) (a==' ')
+#else
+#define Isspace isspace
+#endif
+
+#ifndef LUA_FF_LIB
+static int last_aspect=0;
+#endif
+
+GTextInfo emsizes[] = {
+ { (unichar_t *) "1000", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "1024", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "2048", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "4096", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }
+};
+
+GTextInfo interpretations[] = {
+/* GT: See the long comment at "Property|New" */
+/* GT: The msgstr should contain a translation of "None", ignore "Interpretation|" */
+/* GT: In french this could be "Aucun" or "Aucune" depending on the gender */
+/* GT: of "Interpretation" */
+ { (unichar_t *) N_("Interpretation|None"), NULL, 0, 0, (void *) ui_none, NULL, 0, 0, 0, 0, 0, 0, 1},
+/* { (unichar_t *) N_("Adobe Public Use Defs."), NULL, 0, 0, (void *) ui_adobe, NULL, 0, 0, 0, 0, 0, 0, 1}, */
+/* { (unichar_t *) N_("Greek"), NULL, 0, 0, (void *) ui_greek, NULL, 0, 0, 0, 0, 0, 0, 1}, */
+ { (unichar_t *) N_("Japanese"), NULL, 0, 0, (void *) ui_japanese, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Traditional Chinese"), NULL, 0, 0, (void *) ui_trad_chinese, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Simplified Chinese"), NULL, 0, 0, (void *) ui_simp_chinese, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Korean"), NULL, 0, 0, (void *) ui_korean, NULL, 0, 0, 0, 0, 0, 0, 1},
+/* { (unichar_t *) N_("AMS Public Use"), NULL, 0, 0, (void *) ui_ams, NULL, 0, 0, 0, 0, 0, 0, 1}, */
+ { NULL }};
+GTextInfo macstyles[] = {
+ { (unichar_t *) N_("MacStyles|Bold"), NULL, 0, 0, (void *) sf_bold, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("MacStyles|Italic"), NULL, 0, 0, (void *) sf_italic, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("MacStyles|Condense"), NULL, 0, 0, (void *) sf_condense, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("MacStyles|Expand"), NULL, 0, 0, (void *) sf_extend, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("MacStyles|Underline"), NULL, 0, 0, (void *) sf_underline, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("MacStyles|Outline"), NULL, 0, 0, (void *) sf_outline, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("MacStyles|Shadow"), NULL, 0, 0, (void *) sf_shadow, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo widthclass[] = {
+ { (unichar_t *) N_("Ultra-Condensed (50%)"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Extra-Condensed (62.5%)"), NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Condensed (75%)"), NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Semi-Condensed (87.5%)"), NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Medium (100%)"), NULL, 0, 0, (void *) 5, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Semi-Expanded (112.5%)"), NULL, 0, 0, (void *) 6, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Expanded (125%)"), NULL, 0, 0, (void *) 7, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Extra-Expanded (150%)"), NULL, 0, 0, (void *) 8, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Ultra-Expanded (200%)"), NULL, 0, 0, (void *) 9, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo weightclass[] = {
+ { (unichar_t *) N_("100 Thin"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("200 Extra-Light"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("300 Light"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("400 Book"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("500 Medium"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("600 Demi-Bold"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("700 Bold"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("800 Heavy"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("900 Black"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo fstype[] = {
+ { (unichar_t *) N_("Never Embed/No Editing"), NULL, 0, 0, (void *) 0x02, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Printable Document"), NULL, 0, 0, (void *) 0x04, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Editable Document"), NULL, 0, 0, (void *) 0x08, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Installable Font"), NULL, 0, 0, (void *) 0x00, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo pfmfamily[] = {
+ { (unichar_t *) N_("Serif"), NULL, 0, 0, (void *) 0x11, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sans-Serif"), NULL, 0, 0, (void *) 0x21, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Monospace"), NULL, 0, 0, (void *) 0x31, NULL, 0, 0, 0, 0, 0, 0, 1},
+/* GT: See the long comment at "Property|New" */
+/* GT: The msgstr should contain a translation of "Script", ignore "cursive|" */
+/* GT: English uses "script" to me a general writing style (latin, greek, kanji) */
+/* GT: and the cursive handwriting style. Here we mean cursive handwriting. */
+ { (unichar_t *) N_("cursive|Script"), NULL, 0, 0, (void *) 0x41, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Decorative"), NULL, 0, 0, (void *) 0x51, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo ibmfamily[] = {
+ { (unichar_t *) N_("No Classification"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Old Style Serifs"), NULL, 0, 0, (void *) 0x100, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("OSS Rounded Legibility"), NULL, 0, 0, (void *) 0x101, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("OSS Geralde"), NULL, 0, 0, (void *) 0x102, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("OSS Venetian"), NULL, 0, 0, (void *) 0x103, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("OSS Modified Venetian"), NULL, 0, 0, (void *) 0x104, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("OSS Dutch Modern"), NULL, 0, 0, (void *) 0x105, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("OSS Dutch Trad"), NULL, 0, 0, (void *) 0x106, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("OSS Contemporary"), NULL, 0, 0, (void *) 0x107, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("OSS Calligraphic"), NULL, 0, 0, (void *) 0x108, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("OSS Miscellaneous"), NULL, 0, 0, (void *) 0x10f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Transitional Serifs"), NULL, 0, 0, (void *) 0x200, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("TS Direct Line"), NULL, 0, 0, (void *) 0x201, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("TS Script"), NULL, 0, 0, (void *) 0x202, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("TS Miscellaneous"), NULL, 0, 0, (void *) 0x20f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Modern Serifs"), NULL, 0, 0, (void *) 0x300, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("MS Italian"), NULL, 0, 0, (void *) 0x301, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("MS Script"), NULL, 0, 0, (void *) 0x302, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("MS Miscellaneous"), NULL, 0, 0, (void *) 0x30f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Clarendon Serifs"), NULL, 0, 0, (void *) 0x400, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("CS Clarendon"), NULL, 0, 0, (void *) 0x401, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("CS Modern"), NULL, 0, 0, (void *) 0x402, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("CS Traditional"), NULL, 0, 0, (void *) 0x403, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("CS Newspaper"), NULL, 0, 0, (void *) 0x404, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("CS Stub Serif"), NULL, 0, 0, (void *) 0x405, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("CS Monotone"), NULL, 0, 0, (void *) 0x406, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("CS Typewriter"), NULL, 0, 0, (void *) 0x407, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("CS Miscellaneous"), NULL, 0, 0, (void *) 0x40f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Slab Serifs"), NULL, 0, 0, (void *) 0x500, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Slab Serifs|SS Monotone"), NULL, 0, 0, (void *) 0x501, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Slab Serifs|SS Humanist"), NULL, 0, 0, (void *) 0x502, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Slab Serifs|SS Geometric"), NULL, 0, 0, (void *) 0x503, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Slab Serifs|SS Swiss"), NULL, 0, 0, (void *) 0x504, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Slab Serifs|SS Typewriter"), NULL, 0, 0, (void *) 0x505, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Slab Serifs|SS Miscellaneous"), NULL, 0, 0, (void *) 0x50f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Freeform Serifs"), NULL, 0, 0, (void *) 0x700, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("FS Modern"), NULL, 0, 0, (void *) 0x701, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("FS Miscellaneous"), NULL, 0, 0, (void *) 0x70f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sans-Serif"), NULL, 0, 0, (void *) 0x800, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sans-Serif|SS IBM NeoGrotesque Gothic"), NULL, 0, 0, (void *) 0x801, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sans-Serif|SS Humanist"), NULL, 0, 0, (void *) 0x802, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sans-Serif|SS Low-x Round Geometric"), NULL, 0, 0, (void *) 0x803, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sans-Serif|SS High-x Round Geometric"), NULL, 0, 0, (void *) 0x804, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sans-Serif|SS NeoGrotesque Gothic"), NULL, 0, 0, (void *) 0x805, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sans-Serif|SS Modified Grotesque Gothic"), NULL, 0, 0, (void *) 0x806, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sans-Serif|SS Typewriter Gothic"), NULL, 0, 0, (void *) 0x809, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sans-Serif|SS Matrix"), NULL, 0, 0, (void *) 0x80a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sans-Serif|SS Miscellaneous"), NULL, 0, 0, (void *) 0x80f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Ornamentals"), NULL, 0, 0, (void *) 0x900, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("O Engraver"), NULL, 0, 0, (void *) 0x901, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("O Black Letter"), NULL, 0, 0, (void *) 0x902, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("O Decorative"), NULL, 0, 0, (void *) 0x903, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("O Three Dimensional"), NULL, 0, 0, (void *) 0x904, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("O Miscellaneous"), NULL, 0, 0, (void *) 0x90f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Scripts"), NULL, 0, 0, (void *) 0xa00, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("S Uncial"), NULL, 0, 0, (void *) 0xa01, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("S Brush Joined"), NULL, 0, 0, (void *) 0xa02, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("S Formal Joined"), NULL, 0, 0, (void *) 0xa03, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("S Monotone Joined"), NULL, 0, 0, (void *) 0xa04, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("S Calligraphic"), NULL, 0, 0, (void *) 0xa05, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("S Brush Unjoined"), NULL, 0, 0, (void *) 0xa06, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("S Formal Unjoined"), NULL, 0, 0, (void *) 0xa07, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("S Monotone Unjoined"), NULL, 0, 0, (void *) 0xa08, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("S Miscellaneous"), NULL, 0, 0, (void *) 0xa0f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Symbolic"), NULL, 0, 0, (void *) 0xc00, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sy Mixed Serif"), NULL, 0, 0, (void *) 0xc03, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sy Old Style Serif"), NULL, 0, 0, (void *) 0xc06, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sy Neo-grotesque Sans Serif"), NULL, 0, 0, (void *) 0xc07, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sy Miscellaneous"), NULL, 0, 0, (void *) 0xc0f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo os2versions[] = {
+ { (unichar_t *) N_("OS2Version|Automatic"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("1"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("2"), NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("3"), NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("4"), NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+#ifndef LUA_FF_LIB
+static GTextInfo gaspversions[] = {
+ { (unichar_t *) N_("0"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("1"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+#endif
+static GTextInfo panfamily[] = {
+ { (unichar_t *) N_("PanoseFamily|Any"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseFamily|No Fit"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Text & Display"), NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 0, 0, 1},
+/* GT: See the long comment at "Property|New" */
+/* GT: The msgstr should contain a translation of "Script", ignore "cursive|" */
+/* GT: English uses "script" to me a general writing style (latin, greek, kanji) */
+/* GT: and the cursive handwriting style. Here we mean cursive handwriting. */
+ { (unichar_t *) N_("cursive|Script"), NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Decorative"), NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Pictorial"), NULL, 0, 0, (void *) 5, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "6", NULL, 0, 0, (void *) 6, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "7", NULL, 0, 0, (void *) 7, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "8", NULL, 0, 0, (void *) 8, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "9", NULL, 0, 0, (void *) 9, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "10", NULL, 0, 0, (void *) 10, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "11", NULL, 0, 0, (void *) 11, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "12", NULL, 0, 0, (void *) 12, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "13", NULL, 0, 0, (void *) 13, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "14", NULL, 0, 0, (void *) 14, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "15", NULL, 0, 0, (void *) 15, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo panserifs[] = {
+ { (unichar_t *) N_("PanoseSerifs|Any"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseSerifs|No Fit"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Cove"), NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Obtuse Cove"), NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Square Cove"), NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Obtuse Square Cove"), NULL, 0, 0, (void *) 5, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseSerivfs|Square"), NULL, 0, 0, (void *) 6, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseSerifs|Thin"), NULL, 0, 0, (void *) 7, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Bone"), NULL, 0, 0, (void *) 8, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Exaggerated"), NULL, 0, 0, (void *) 9, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Triangle"), NULL, 0, 0, (void *) 10, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Normal Sans"), NULL, 0, 0, (void *) 11, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Obtuse Sans"), NULL, 0, 0, (void *) 12, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Perp Sans"), NULL, 0, 0, (void *) 13, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Flared"), NULL, 0, 0, (void *) 14, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseSerivfs|Rounded"), NULL, 0, 0, (void *) 15, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo panweight[] = {
+ { (unichar_t *) N_("PanoseWeight|Any"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseWeight|No Fit"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Very Light"), NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Light"), NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseWeight|Thin"), NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Book"), NULL, 0, 0, (void *) 5, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Medium"), NULL, 0, 0, (void *) 6, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Demi"), NULL, 0, 0, (void *) 7, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Bold"), NULL, 0, 0, (void *) 8, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Heavy"), NULL, 0, 0, (void *) 9, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Black"), NULL, 0, 0, (void *) 10, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Nord"), NULL, 0, 0, (void *) 11, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "12", NULL, 0, 0, (void *) 12, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "13", NULL, 0, 0, (void *) 13, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "14", NULL, 0, 0, (void *) 14, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "15", NULL, 0, 0, (void *) 15, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo panprop[] = {
+ { (unichar_t *) N_("PanoseProportion|Any"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseProportion|No Fit"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Old Style"), NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Modern"), NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Even Width"), NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Expanded"), NULL, 0, 0, (void *) 5, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Condensed"), NULL, 0, 0, (void *) 6, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Very Expanded"), NULL, 0, 0, (void *) 7, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Very Condensed"), NULL, 0, 0, (void *) 8, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Monospaced"), NULL, 0, 0, (void *) 9, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "10", NULL, 0, 0, (void *) 10, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "11", NULL, 0, 0, (void *) 11, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "12", NULL, 0, 0, (void *) 12, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "13", NULL, 0, 0, (void *) 13, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "14", NULL, 0, 0, (void *) 14, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "15", NULL, 0, 0, (void *) 15, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo pancontrast[] = {
+ { (unichar_t *) N_("PanoseContrast|Any"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseContrast|No Fit"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseContrast|None"), NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseContrast|Very Low"), NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseContrast|Low"), NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseContrast|Medium Low"), NULL, 0, 0, (void *) 5, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseContrast|Medium"), NULL, 0, 0, (void *) 6, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseContrast|Medium High"), NULL, 0, 0, (void *) 7, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseContrast|High"), NULL, 0, 0, (void *) 8, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseContrast|Very High"), NULL, 0, 0, (void *) 9, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "10", NULL, 0, 0, (void *) 10, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "11", NULL, 0, 0, (void *) 11, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "12", NULL, 0, 0, (void *) 12, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "13", NULL, 0, 0, (void *) 13, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "14", NULL, 0, 0, (void *) 14, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "15", NULL, 0, 0, (void *) 15, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo panstrokevar[] = {
+ { (unichar_t *) N_("PanoseStrokeVariation|Any"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseStrokeVariation|No Fit"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Gradual/Diagonal"), NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Gradual/Transitional"), NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Gradual/Vertical"), NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Gradual/Horizontal"), NULL, 0, 0, (void *) 5, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Rapid/Vertical"), NULL, 0, 0, (void *) 6, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Rapid/Horizontal"), NULL, 0, 0, (void *) 7, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Instant/Vertical"), NULL, 0, 0, (void *) 8, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "9", NULL, 0, 0, (void *) 9, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "10", NULL, 0, 0, (void *) 10, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "11", NULL, 0, 0, (void *) 11, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "12", NULL, 0, 0, (void *) 12, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "13", NULL, 0, 0, (void *) 13, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "14", NULL, 0, 0, (void *) 14, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "15", NULL, 0, 0, (void *) 15, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo panarmstyle[] = {
+ { (unichar_t *) N_("PanoseArmStyle|Any"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseArmStyle|No Fit"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Straight Arms/Horizontal"), NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Straight Arms/Wedge"), NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Straight Arms/Vertical"), NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Straight Arms/Single Serif"), NULL, 0, 0, (void *) 5, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Straight Arms/Double Serif"), NULL, 0, 0, (void *) 6, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Non-Straight Arms/Horizontal"), NULL, 0, 0, (void *) 7, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Non-Straight Arms/Wedge"), NULL, 0, 0, (void *) 8, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Non-Straight Arms/Vertical"), NULL, 0, 0, (void *) 9, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Non-Straight Arms/Single Serif"), NULL, 0, 0, (void *) 10, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Non-Straight Arms/Double Serif"), NULL, 0, 0, (void *) 11, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "12", NULL, 0, 0, (void *) 12, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "13", NULL, 0, 0, (void *) 13, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "14", NULL, 0, 0, (void *) 14, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "15", NULL, 0, 0, (void *) 15, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo panletterform[] = {
+ { (unichar_t *) N_("PanoseLetterform|Any"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseLetterform|No Fit"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Normal/Contact"), NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Normal/Weighted"), NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Normal/Boxed"), NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Normal/Flattened"), NULL, 0, 0, (void *) 5, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Normal/Rounded"), NULL, 0, 0, (void *) 6, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Normal/Off-Center"), NULL, 0, 0, (void *) 7, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Normal/Square"), NULL, 0, 0, (void *) 8, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Oblique/Contact"), NULL, 0, 0, (void *) 9, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Oblique/Weighted"), NULL, 0, 0, (void *) 10, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Oblique/Boxed"), NULL, 0, 0, (void *) 11, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Oblique/Rounded"), NULL, 0, 0, (void *) 12, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Oblique/Off-Center"), NULL, 0, 0, (void *) 13, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Oblique/Square"), NULL, 0, 0, (void *) 14, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "15", NULL, 0, 0, (void *) 15, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo panmidline[] = {
+ { (unichar_t *) N_("PanoseMidline|Any"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseMidline|No Fit"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseMidline|Standard/Trimmed"), NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseMidline|Standard/Pointed"), NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseMidline|Standard/Serifed"), NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseMidline|High/Trimmed"), NULL, 0, 0, (void *) 5, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseMidline|High/Pointed"), NULL, 0, 0, (void *) 6, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseMidline|High/Serifed"), NULL, 0, 0, (void *) 7, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseMidline|Constant/Trimmed"), NULL, 0, 0, (void *) 8, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseMidline|Constant/Pointed"), NULL, 0, 0, (void *) 9, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseMidline|Constant/Serifed"), NULL, 0, 0, (void *) 10, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseMidline|Low/Trimmed"), NULL, 0, 0, (void *) 11, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseMidline|Low/Pointed"), NULL, 0, 0, (void *) 12, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseMidline|Low/Serifed"), NULL, 0, 0, (void *) 13, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "14", NULL, 0, 0, (void *) 14, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "15", NULL, 0, 0, (void *) 15, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo panxheight[] = {
+ { (unichar_t *) N_("PanoseXHeight|Any"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseXHeight|No Fit"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseXHeight|Constant/Small"), NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseXHeight|Constant/Standard"), NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseXHeight|Constant/Large"), NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseXHeight|Ducking/Small"), NULL, 0, 0, (void *) 5, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseXHeight|Ducking/Standard"), NULL, 0, 0, (void *) 6, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("PanoseXHeight|Ducking/Large"), NULL, 0, 0, (void *) 7, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "8", NULL, 0, 0, (void *) 8, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "9", NULL, 0, 0, (void *) 9, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "10", NULL, 0, 0, (void *) 10, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "11", NULL, 0, 0, (void *) 11, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "12", NULL, 0, 0, (void *) 12, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "13", NULL, 0, 0, (void *) 13, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "14", NULL, 0, 0, (void *) 14, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "15", NULL, 0, 0, (void *) 15, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+
+#ifndef LUA_FF_LIB
+static struct ms_2_locales { char *loc_name; int local_id; } ms_2_locals[] = {
+ { "af", 0x436 },
+ { "sq_AL", 0x41c },
+ { "am", 0x45e },
+ { "ar_SA", 0x401 },
+ { "ar_IQ", 0x801 },
+ { "ar_EG", 0xc01 },
+ { "ar_LY", 0x1001 },
+ { "ar_DZ", 0x1401 },
+ { "ar_MA", 0x1801 },
+ { "ar_TN", 0x1C01 },
+ { "ar_OM", 0x2001 },
+ { "ar_YE", 0x2401 },
+ { "ar_SY", 0x2801 },
+ { "ar_JO", 0x2c01 },
+ { "ar_LB", 0x3001 },
+ { "ar_KW", 0x3401 },
+ { "ar_AE", 0x3801 },
+ { "ar_BH", 0x3c01 },
+ { "ar_QA", 0x4001 },
+ { "hy", 0x42b },
+ { "as", 0x44d },
+ { "az", 0x42c },
+ { "az", 0x82c },
+ { "eu", 0x42d },
+ { "be_BY", 0x423 },
+ { "bn_IN", 0x445 },
+ { "bn_BD", 0x845 },
+ { "bg_BG", 0x402 },
+ { "my", 0x455 },
+ { "ca", 0x403 },
+ { "km", 0x453 },
+ { "zh_TW", 0x404 }, /* Trad */
+ { "zh_CN", 0x804 }, /* Simp */
+ { "zh_HK", 0xc04 }, /* Trad */
+ { "zh_SG", 0x1004 }, /* Simp */
+ { "zh_MO", 0x1404 }, /* Trad */
+ { "hr", 0x41a },
+ { "hr_BA", 0x101a },
+ { "cs_CZ", 0x405 },
+ { "da_DK", 0x406 },
+ { "div", 0x465 },
+ { "nl_NL", 0x413 },
+ { "nl_BE", 0x813 },
+ { "en_UK", 0x809 },
+ { "en_US", 0x409 },
+ { "en_CA", 0x1009 },
+ { "en_AU", 0xc09 },
+ { "en_NZ", 0x1409 },
+ { "en_IE", 0x1809 },
+ { "en_ZA", 0x1c09 },
+ { "en_JM", 0x2009 },
+ { "en", 0x2409 },
+ { "en_BZ", 0x2809 },
+ { "en_TT", 0x2c09 },
+ { "en_ZW", 0x3009 },
+ { "en_PH", 0x3409 },
+ { "en_ID", 0x3809 },
+ { "en_HK", 0x3c09 },
+ { "en_IN", 0x4009 },
+ { "en_MY", 0x4409 },
+ { "et_EE", 0x425 },
+ { "fo", 0x438 },
+/* No language code for filipino */
+ { "fa", 0x429 },
+ { "fi_FI", 0x40b },
+ { "fr_FR", 0x40c },
+ { "fr_BE", 0x80c },
+ { "fr_CA", 0xc0c },
+ { "fr_CH", 0x100c },
+ { "fr_LU", 0x140c },
+ { "fr_MC", 0x180c },
+ { "fr", 0x1c0c }, /* West Indes */
+ { "fr_RE", 0x200c },
+ { "fr_CD", 0x240c },
+ { "fr_SN", 0x280c },
+ { "fr_CM", 0x2c0c },
+ { "fr_CI", 0x300c },
+ { "fr_ML", 0x340c },
+ { "fr_MA", 0x380c },
+ { "fr_HT", 0x3c0c },
+ { "fr_DZ", 0xe40c }, /* North African is most likely to be Algeria, possibly Tunisia */
+ { "fy", 0x462 },
+ { "gl", 0x456 },
+ { "ka", 0x437 },
+ { "de_DE", 0x407 },
+ { "de_CH", 0x807 },
+ { "de_AT", 0xc07 },
+ { "de_LU", 0x1007 },
+ { "de_LI", 0x1407 },
+ { "el_GR", 0x408 },
+ { "ga", 0x83c },
+ { "gd", 0x43c },
+ { "gn", 0x474 },
+ { "gu", 0x447 },
+ { "ha", 0x468 },
+ { "he_IL", 0x40d },
+ { "iw", 0x40d }, /* Obsolete name for Hebrew */
+ { "hi", 0x439 },
+ { "hu_HU", 0x40e },
+ { "is_IS", 0x40f },
+ { "id", 0x421 },
+ { "in", 0x421 }, /* Obsolete name for Indonesean */
+ { "iu", 0x45d },
+ { "it_IT", 0x410 },
+ { "it_CH", 0x810 },
+ { "ja_JP", 0x411 },
+ { "kn", 0x44b },
+ { "ks_IN", 0x860 },
+ { "kk", 0x43f },
+ { "ky", 0x440 },
+ { "km", 0x453 },
+ { "kok", 0x457 },
+ { "ko", 0x412 },
+ { "ko", 0x812 }, /*Johab */
+ { "lo", 0x454 },
+ { "la", 0x476 },
+ { "lv_LV", 0x426 },
+ { "lt_LT", 0x427 },
+ { "lt", 0x827 }, /* Classic */
+ { "mk", 0x42f },
+ { "ms", 0x43e },
+ { "ms", 0x83e },
+ { "ml", 0x44c },
+ { "mt", 0x43a },
+ { "mr", 0x44e },
+ { "mn", 0x450 },
+ { "ne_NP", 0x461 },
+ { "ne_IN", 0x861 },
+ { "no_NO", 0x414 }, /* Bokmal */
+ { "no_NO", 0x814 }, /* Nynorsk */
+ { "or", 0x448 },
+ { "om", 0x472 },
+ { "ps", 0x463 },
+ { "pl_PL", 0x415 },
+ { "pt_PT", 0x416 },
+ { "pt_BR", 0x816 },
+ { "pa_IN", 0x446 },
+ { "pa_PK", 0x846 },
+ { "qu_BO", 0x46b },
+ { "qu_EC", 0x86b },
+ { "qu_PE", 0xc6b },
+ { "rm", 0x417 },
+ { "ro_RO", 0x418 },
+ { "ro_MD", 0x818 },
+ { "ru_RU", 0x419 },
+ { "ru_MD", 0x819 },
+ { "smi", 0x43b },
+ { "sa", 0x43b },
+/* No language code for Sepedi */
+ { "sr", 0xc1a }, /* Cyrillic */
+ { "sr", 0x81a }, /* Latin */
+ { "sd_IN", 0x459 },
+ { "sd_PK", 0x859 },
+ { "si", 0x45b },
+ { "sk_SK", 0x41b },
+ { "sl_SI", 0x424 },
+ { "wen", 0x42e },
+ { "es_ES", 0x40a }, /* traditional spanish */
+ { "es_MX", 0x80a },
+ { "es_ES", 0xc0a }, /* Modern spanish */
+ { "es_GT", 0x100a },
+ { "es_CR", 0x140a },
+ { "es_PA", 0x180a },
+ { "es_DO", 0x1c0a },
+ { "es_VE", 0x200a },
+ { "es_CO", 0x240a },
+ { "es_PE", 0x280a },
+ { "es_AR", 0x2c0a },
+ { "es_EC", 0x300a },
+ { "es_CL", 0x340a },
+ { "es_UY", 0x380a },
+ { "es_PY", 0x3c0a },
+ { "es_BO", 0x400a },
+ { "es_SV", 0x440a },
+ { "es_HN", 0x480a },
+ { "es_NI", 0x4c0a },
+ { "es_PR", 0x500a },
+ { "es_US", 0x540a },
+ { "sutu", 0x430 },
+ { "sw_KE", 0x441 },
+ { "sv_SE", 0x41d },
+ { "sv_FI", 0x81d },
+ { "tl", 0x464 },
+ { "tg", 0x464 },
+ { "ta", 0x449 },
+ { "tt", 0x444 },
+ { "te", 0x44a },
+ { "th", 0x41e },
+ { "bo_CN", 0x451 },
+ { "bo_BT", 0x451 },
+ { "ti_ET", 0x473 },
+ { "ti_ER", 0x873 },
+ { "ts", 0x431 },
+ { "tn", 0x432 },
+ { "tr_TR", 0x41f },
+ { "tk", 0x442 },
+ { "uk_UA", 0x422 },
+ { "ug", 0x480 },
+ { "ur_PK", 0x420 },
+ { "ur_IN", 0x820 },
+ { "uz", 0x443 }, /* Latin */
+ { "uz", 0x843 }, /* Cyrillic */
+ { "ven", 0x433 },
+ { "vi", 0x42a },
+ { "cy", 0x452 },
+ { "xh", 0x434 },
+ { "yi", 0x43d },
+ { "ji", 0x43d }, /* Obsolete Yiddish */
+ { "yo", 0x46a },
+ { "zu", 0x435 },
+ { NULL }};
+#endif
+
+static GTextInfo mslanguages[] = {
+ { (unichar_t *) N_("Afrikaans"), NULL, 0, 0, (void *) 0x436, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Albanian"), NULL, 0, 0, (void *) 0x41c, NULL, 0, 0, 0, 0, 0, 0, 1},
+/* GT: See the long comment at "Property|New" */
+/* GT: The msgstr should contain a translation of "Malayalam", ignore "Lang|" */
+ { (unichar_t *) N_("Lang|Amharic"), NULL, 0, 0, (void *) 0x45e, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (Saudi Arabia)"), NULL, 0, 0, (void *) 0x401, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (Iraq)"), NULL, 0, 0, (void *) 0x801, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (Egypt)"), NULL, 0, 0, (void *) 0xc01, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (Libya)"), NULL, 0, 0, (void *) 0x1001, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (Algeria)"), NULL, 0, 0, (void *) 0x1401, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (Morocco)"), NULL, 0, 0, (void *) 0x1801, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (Tunisia)"), NULL, 0, 0, (void *) 0x1C01, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (Oman)"), NULL, 0, 0, (void *) 0x2001, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (Yemen)"), NULL, 0, 0, (void *) 0x2401, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (Syria)"), NULL, 0, 0, (void *) 0x2801, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (Jordan)"), NULL, 0, 0, (void *) 0x2c01, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (Lebanon)"), NULL, 0, 0, (void *) 0x3001, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (Kuwait)"), NULL, 0, 0, (void *) 0x3401, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (U.A.E.)"), NULL, 0, 0, (void *) 0x3801, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (Bahrain)"), NULL, 0, 0, (void *) 0x3c01, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Arabic (Qatar)"), NULL, 0, 0, (void *) 0x4001, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Armenian"), NULL, 0, 0, (void *) 0x42b, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Assamese"), NULL, 0, 0, (void *) 0x44d, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Azeri (Latin)"), NULL, 0, 0, (void *) 0x42c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Azeri (Cyrillic)"), NULL, 0, 0, (void *) 0x82c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Basque"), NULL, 0, 0, (void *) 0x42d, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Byelorussian"), NULL, 0, 0, (void *) 0x423, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Bengali"), NULL, 0, 0, (void *) 0x445, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Bengali Bangladesh"), NULL, 0, 0, (void *) 0x845, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Bulgarian"), NULL, 0, 0, (void *) 0x402, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Burmese"), NULL, 0, 0, (void *) 0x455, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Catalan"), NULL, 0, 0, (void *) 0x403, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Cambodian"), NULL, 0, 0, (void *) 0x453, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Cherokee"), NULL, 0, 0, (void *) 0x45c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Chinese (Taiwan)"), NULL, 0, 0, (void *) 0x404, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Chinese (PRC)"), NULL, 0, 0, (void *) 0x804, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Chinese (Hong Kong)"), NULL, 0, 0, (void *) 0xc04, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Chinese (Singapore)"), NULL, 0, 0, (void *) 0x1004, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Chinese (Macau)"), NULL, 0, 0, (void *) 0x1404, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Croatian"), NULL, 0, 0, (void *) 0x41a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Croatian Bosnia/Herzegovina"), NULL, 0, 0, (void *) 0x101a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Czech"), NULL, 0, 0, (void *) 0x405, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Danish"), NULL, 0, 0, (void *) 0x406, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Divehi"), NULL, 0, 0, (void *) 0x465, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Dutch"), NULL, 0, 0, (void *) 0x413, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Flemish (Belgian Dutch)"), NULL, 0, 0, (void *) 0x813, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Edo"), NULL, 0, 0, (void *) 0x466, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (British)"), NULL, 0, 0, (void *) 0x809, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (US)"), NULL, 0, 0, (void *) 0x409, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (Canada)"), NULL, 0, 0, (void *) 0x1009, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (Australian)"), NULL, 0, 0, (void *) 0xc09, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (New Zealand)"), NULL, 0, 0, (void *) 0x1409, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (Irish)"), NULL, 0, 0, (void *) 0x1809, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (South Africa)"), NULL, 0, 0, (void *) 0x1c09, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (Jamaica)"), NULL, 0, 0, (void *) 0x2009, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (Caribbean)"), NULL, 0, 0, (void *) 0x2409, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (Belize)"), NULL, 0, 0, (void *) 0x2809, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (Trinidad)"), NULL, 0, 0, (void *) 0x2c09, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (Zimbabwe)"), NULL, 0, 0, (void *) 0x3009, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (Philippines)"), NULL, 0, 0, (void *) 0x3409, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (Indonesia)"), NULL, 0, 0, (void *) 0x3809, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (Hong Kong)"), NULL, 0, 0, (void *) 0x3c09, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (India)"), NULL, 0, 0, (void *) 0x4009, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("English (Malaysia)"), NULL, 0, 0, (void *) 0x4409, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Estonian"), NULL, 0, 0, (void *) 0x425, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Faeroese"), NULL, 0, 0, (void *) 0x438, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Farsi"), NULL, 0, 0, (void *) 0x429, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Filipino"), NULL, 0, 0, (void *) 0x464, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Finnish"), NULL, 0, 0, (void *) 0x40b, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("French French"), NULL, 0, 0, (void *) 0x40c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("French Belgium"), NULL, 0, 0, (void *) 0x80c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("French Canadian"), NULL, 0, 0, (void *) 0xc0c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("French Swiss"), NULL, 0, 0, (void *) 0x100c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("French Luxembourg"), NULL, 0, 0, (void *) 0x140c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("French Monaco"), NULL, 0, 0, (void *) 0x180c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("French West Indies"), NULL, 0, 0, (void *) 0x1c0c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) NU_("French R\303\251union"), NULL, 0, 0, (void *) 0x200c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("French D.R. Congo"), NULL, 0, 0, (void *) 0x240c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("French Senegal"), NULL, 0, 0, (void *) 0x280c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("French Camaroon"), NULL, 0, 0, (void *) 0x2c0c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) NU_("French C\303\264te d'Ivoire"), NULL, 0, 0, (void *) 0x300c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("French Mali"), NULL, 0, 0, (void *) 0x340c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("French Morocco"), NULL, 0, 0, (void *) 0x380c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("French Haiti"), NULL, 0, 0, (void *) 0x3c0c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("French North Africa"), NULL, 0, 0, (void *) 0xe40c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Frisian"), NULL, 0, 0, (void *) 0x462, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Fulfulde"), NULL, 0, 0, (void *) 0x467, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Gaelic (Scottish)"), NULL, 0, 0, (void *) 0x43c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Gaelic (Irish)"), NULL, 0, 0, (void *) 0x83c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Galician"), NULL, 0, 0, (void *) 0x467, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Georgian"), NULL, 0, 0, (void *) 0x437, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("German German"), NULL, 0, 0, (void *) 0x407, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("German Swiss"), NULL, 0, 0, (void *) 0x807, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("German Austrian"), NULL, 0, 0, (void *) 0xc07, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("German Luxembourg"), NULL, 0, 0, (void *) 0x1007, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("German Liechtenstein"), NULL, 0, 0, (void *) 0x1407, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Greek"), NULL, 0, 0, (void *) 0x408, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Guarani"), NULL, 0, 0, (void *) 0x474, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Gujarati"), NULL, 0, 0, (void *) 0x447, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Hausa"), NULL, 0, 0, (void *) 0x468, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Hawaiian"), NULL, 0, 0, (void *) 0x475, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Hebrew"), NULL, 0, 0, (void *) 0x40d, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Hindi"), NULL, 0, 0, (void *) 0x439, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Hungarian"), NULL, 0, 0, (void *) 0x40e, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Ibibio"), NULL, 0, 0, (void *) 0x469, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Icelandic"), NULL, 0, 0, (void *) 0x40f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Igbo"), NULL, 0, 0, (void *) 0x470, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Indonesian"), NULL, 0, 0, (void *) 0x421, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Inuktitut"), NULL, 0, 0, (void *) 0x45d, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Italian"), NULL, 0, 0, (void *) 0x410, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Italian Swiss"), NULL, 0, 0, (void *) 0x810, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Japanese"), NULL, 0, 0, (void *) 0x411, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Kannada"), NULL, 0, 0, (void *) 0x44b, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Kanuri"), NULL, 0, 0, (void *) 0x471, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Kashmiri (India)"), NULL, 0, 0, (void *) 0x860, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Kazakh"), NULL, 0, 0, (void *) 0x43f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Khmer"), NULL, 0, 0, (void *) 0x453, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Kirghiz"), NULL, 0, 0, (void *) 0x440, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Konkani"), NULL, 0, 0, (void *) 0x457, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Korean"), NULL, 0, 0, (void *) 0x412, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Korean (Johab)"), NULL, 0, 0, (void *) 0x812, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lao"), NULL, 0, 0, (void *) 0x454, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Latvian"), NULL, 0, 0, (void *) 0x426, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Latin"), NULL, 0, 0, (void *) 0x476, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lithuanian"), NULL, 0, 0, (void *) 0x427, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lithuanian (Classic)"), NULL, 0, 0, (void *) 0x827, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Macedonian"), NULL, 0, 0, (void *) 0x42f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Malay"), NULL, 0, 0, (void *) 0x43e, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Malay (Brunei)"), NULL, 0, 0, (void *) 0x83e, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Malayalam"), NULL, 0, 0, (void *) 0x44c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Maltese"), NULL, 0, 0, (void *) 0x43a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Manipuri"), NULL, 0, 0, (void *) 0x458, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Maori"), NULL, 0, 0, (void *) 0x481, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Marathi"), NULL, 0, 0, (void *) 0x44e, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Mongolian (Cyrillic)"), NULL, 0, 0, (void *) 0x450, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Mongolian (Mongolian)"), NULL, 0, 0, (void *) 0x850, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Nepali"), NULL, 0, 0, (void *) 0x461, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Nepali (India)"), NULL, 0, 0, (void *) 0x861, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Norwegian (Bokmal)"), NULL, 0, 0, (void *) 0x414, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Norwegian (Nynorsk)"), NULL, 0, 0, (void *) 0x814, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Oriya"), NULL, 0, 0, (void *) 0x448, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Oromo"), NULL, 0, 0, (void *) 0x472, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Papiamentu"), NULL, 0, 0, (void *) 0x479, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Pashto"), NULL, 0, 0, (void *) 0x463, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Polish"), NULL, 0, 0, (void *) 0x415, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Portugese (Portugal)"), NULL, 0, 0, (void *) 0x416, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Portuguese (Brasil)"), NULL, 0, 0, (void *) 0x816, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Punjabi (India)"), NULL, 0, 0, (void *) 0x446, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Punjabi (Pakistan)"), NULL, 0, 0, (void *) 0x846, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Quecha (Bolivia)"), NULL, 0, 0, (void *) 0x46b, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Quecha (Ecuador)"), NULL, 0, 0, (void *) 0x86b, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Quecha (Peru)"), NULL, 0, 0, (void *) 0xc6b, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Rhaeto-Romanic"), NULL, 0, 0, (void *) 0x417, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Romanian"), NULL, 0, 0, (void *) 0x418, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Romanian (Moldova)"), NULL, 0, 0, (void *) 0x818, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Russian"), NULL, 0, 0, (void *) 0x419, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Russian (Moldova)"), NULL, 0, 0, (void *) 0x819, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sami (Lappish)"), NULL, 0, 0, (void *) 0x43b, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sanskrit"), NULL, 0, 0, (void *) 0x43b, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sepedi"), NULL, 0, 0, (void *) 0x46c, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Serbian (Cyrillic)"), NULL, 0, 0, (void *) 0xc1a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Serbian (Latin)"), NULL, 0, 0, (void *) 0x81a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sindhi India"), NULL, 0, 0, (void *) 0x459, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sindhi Pakistan"), NULL, 0, 0, (void *) 0x859, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Sinhalese"), NULL, 0, 0, (void *) 0x45b, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Slovak"), NULL, 0, 0, (void *) 0x41b, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Slovenian"), NULL, 0, 0, (void *) 0x424, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sorbian"), NULL, 0, 0, (void *) 0x42e, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Traditional)"), NULL, 0, 0, (void *) 0x40a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish Mexico"), NULL, 0, 0, (void *) 0x80a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Modern)"), NULL, 0, 0, (void *) 0xc0a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Guatemala)"), NULL, 0, 0, (void *) 0x100a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Costa Rica)"), NULL, 0, 0, (void *) 0x140a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Panama)"), NULL, 0, 0, (void *) 0x180a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Dominican Republic)"), NULL, 0, 0, (void *) 0x1c0a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Venezuela)"), NULL, 0, 0, (void *) 0x200a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Colombia)"), NULL, 0, 0, (void *) 0x240a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Peru)"), NULL, 0, 0, (void *) 0x280a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Argentina)"), NULL, 0, 0, (void *) 0x2c0a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Ecuador)"), NULL, 0, 0, (void *) 0x300a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Chile)"), NULL, 0, 0, (void *) 0x340a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Uruguay)"), NULL, 0, 0, (void *) 0x380a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Paraguay)"), NULL, 0, 0, (void *) 0x3c0a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Bolivia)"), NULL, 0, 0, (void *) 0x400a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (El Salvador)"), NULL, 0, 0, (void *) 0x440a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Honduras)"), NULL, 0, 0, (void *) 0x480a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Nicaragua)"), NULL, 0, 0, (void *) 0x4c0a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Puerto Rico)"), NULL, 0, 0, (void *) 0x500a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (United States)"), NULL, 0, 0, (void *) 0x540a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish (Latin America)"), NULL, 0, 0, (void *) 0xe40a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sutu"), NULL, 0, 0, (void *) 0x430, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Swahili (Kenyan)"), NULL, 0, 0, (void *) 0x441, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Swedish (Sweden)"), NULL, 0, 0, (void *) 0x41d, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Swedish (Finland)"), NULL, 0, 0, (void *) 0x81d, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Syriac"), NULL, 0, 0, (void *) 0x45a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Tagalog"), NULL, 0, 0, (void *) 0x464, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Tajik"), NULL, 0, 0, (void *) 0x428, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Tamazight (Arabic)"), NULL, 0, 0, (void *) 0x45f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Tamazight (Latin)"), NULL, 0, 0, (void *) 0x85f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Tamil"), NULL, 0, 0, (void *) 0x449, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Tatar (Tatarstan)"), NULL, 0, 0, (void *) 0x444, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Telugu"), NULL, 0, 0, (void *) 0x44a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Thai"), NULL, 0, 0, (void *) 0x41e, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Tibetan (PRC)"), NULL, 0, 0, (void *) 0x451, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Tibetan Bhutan"), NULL, 0, 0, (void *) 0x851, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Tigrinya Ethiopia"), NULL, 0, 0, (void *) 0x473, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Tigrinyan Eritrea"), NULL, 0, 0, (void *) 0x873, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Tsonga"), NULL, 0, 0, (void *) 0x431, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Tswana"), NULL, 0, 0, (void *) 0x432, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Turkish"), NULL, 0, 0, (void *) 0x41f, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Turkmen"), NULL, 0, 0, (void *) 0x442, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Uighur"), NULL, 0, 0, (void *) 0x480, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Ukrainian"), NULL, 0, 0, (void *) 0x422, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Urdu (Pakistan)"), NULL, 0, 0, (void *) 0x420, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Urdu (India)"), NULL, 0, 0, (void *) 0x820, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Uzbek (Latin)"), NULL, 0, 0, (void *) 0x443, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Uzbek (Cyrillic)"), NULL, 0, 0, (void *) 0x843, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Venda"), NULL, 0, 0, (void *) 0x433, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Vietnamese"), NULL, 0, 0, (void *) 0x42a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Welsh"), NULL, 0, 0, (void *) 0x452, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Xhosa"), NULL, 0, 0, (void *) 0x434, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Yi"), NULL, 0, 0, (void *) 0x478, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Yiddish"), NULL, 0, 0, (void *) 0x43d, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Yoruba"), NULL, 0, 0, (void *) 0x46a, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Zulu"), NULL, 0, 0, (void *) 0x435, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo ttfnameids[] = {
+/* Put styles (docs call it subfamily) first because it is most likely to change */
+ { (unichar_t *) N_("Styles (SubFamily)"), NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 1, 0, 1},
+ { (unichar_t *) N_("Copyright"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Family"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Fullname"), NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("UniqueID"), NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Version"), NULL, 0, 0, (void *) 5, NULL, 0, 0, 0, 0, 0, 0, 1},
+/* Don't give user access to PostscriptName, we set that elsewhere */
+ { (unichar_t *) N_("Trademark"), NULL, 0, 0, (void *) 7, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Manufacturer"), NULL, 0, 0, (void *) 8, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Designer"), NULL, 0, 0, (void *) 9, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Descriptor"), NULL, 0, 0, (void *) 10, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Vendor URL"), NULL, 0, 0, (void *) 11, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Designer URL"), NULL, 0, 0, (void *) 12, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("License"), NULL, 0, 0, (void *) 13, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("License URL"), NULL, 0, 0, (void *) 14, NULL, 0, 0, 0, 0, 0, 0, 1},
+/* slot 15 is reserved */
+ { (unichar_t *) N_("Preferred Family"), NULL, 0, 0, (void *) 16, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Preferred Styles"), NULL, 0, 0, (void *) 17, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Compatible Full"), NULL, 0, 0, (void *) 18, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sample Text"), NULL, 0, 0, (void *) 19, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("CID findfont Name"), NULL, 0, 0, (void *) 20, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static char *TN_DefaultName(GGadget *g, int r, int c);
+static void TN_StrIDEnable(GGadget *g,GMenuItem *mi, int r, int c);
+static void TN_LangEnable(GGadget *g,GMenuItem *mi, int r, int c);
+static struct col_init ci[3] = {
+ { me_enum, NULL, mslanguages, TN_LangEnable, N_("Language") },
+ { me_enum, NULL, ttfnameids, TN_StrIDEnable, N_("String ID") },
+ { me_func, TN_DefaultName, NULL, NULL, N_("String") }
+ };
+#endif
+static GTextInfo gridfit[] = {
+ { (unichar_t *) N_("No Grid Fit"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 1, 0, 1},
+ { (unichar_t *) N_("Grid Fit"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo antialias[] = {
+ { (unichar_t *) N_("No Anti-Alias"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 1, 0, 1},
+ { (unichar_t *) N_("Anti-Alias"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static GTextInfo symsmooth[] = {
+ { (unichar_t *) N_("No Symmetric-Smooth"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 1, 0, 1},
+ { (unichar_t *) N_("Symmetric-Smoothing"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo gfsymsmooth[] = {
+ { (unichar_t *) N_("No Grid Fit w/ Sym-Smooth"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 1, 0, 1},
+ { (unichar_t *) N_("Grid Fit w/ Sym-Smooth"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static struct col_init gaspci[5] = {
+ { me_int , NULL, NULL, NULL, N_("Gasp|Pixels Per EM") },
+ { me_enum, NULL, gridfit, NULL, N_("Gasp|Grid Fit") },
+ { me_enum, NULL, antialias, NULL, N_("Gasp|Anti-Alias") },
+ { me_enum, NULL, symsmooth, NULL, N_("Gasp|Symmetric Smoothing") },
+ { me_enum, NULL, gfsymsmooth, NULL, N_("Gasp|Grid Fit w/ Sym Smooth") }
+ };
+#endif
+
+struct langstyle { int lang; const char *str; };
+static const char regulareng[] = "Regular";
+static const char demiboldeng[] = "DemiBold";
+static const char demiboldeng3[] = "Demi";
+static const char demiboldeng5[] = "SemiBold";
+static const char boldeng[] = "Bold";
+static const char thineng[] = "Thin";
+static const char lighteng[] = "Light";
+static const char extralighteng[] = "ExtraLight";
+static const char extralighteng2[] = "VeryLight";
+static const char mediumeng[] = "Medium";
+static const char bookeng[] = "Book";
+static const char heavyeng[] = "Heavy";
+static const char blackeng[] = "Black";
+static const char italiceng[] = "Italic";
+static const char obliqueeng[] = "Oblique";
+static const char condensedeng[] = "Condensed";
+static const char expandedeng[] = "Expanded";
+static const char outlineeng[] = "Outline";
+
+static const char regularfren[] = "Normal";
+static const char boldfren[] = "Gras";
+static const char demiboldfren[] = "DemiGras";
+static const char demiboldfren2[] = "Demi";
+static const char mediumfren[] = "Normal";
+static const char lightfren[] = "Maigre";
+static const char blackfren[] = "ExtraGras";
+static const char italicfren[] = "Italique";
+static const char obliquefren[] = "Oblique";
+static const char condensedfren[] = "Etroite";
+static const char expandedfren[] = "Elargi";
+static const char outlinefren[] = "Contour";
+
+static const char regulargerm[] = "Standard";
+static const char demiboldgerm[] = "Halbfett";
+static const char demiboldgerm2[] = "Schmallfett";
+static const char boldgerm[] = "Fett";
+static const char boldgerm2[] = "Dick";
+static const char blackgerm[] = "Schwarz";
+static const char lightgerm[] = "Mager";
+static const char mediumgerm[] = "Mittel";
+static const char bookgerm[] = "Buchschrift";
+static const char italicgerm[] = "Kursiv";
+static const char obliquegerm[] = "Schr\303\244g";
+static const char condensedgerm[] = "Schmal";
+static const char expandedgerm[] = "Breit";
+static const char outlinegerm[] = "Konturert";
+
+static const char regularspan[] = "Normal";
+static const char boldspan[] = "Negrita";
+static const char lightspan[] = "Fina";
+static const char blackspan[] = "Supernegra";
+static const char italicspan[] = "Cursiva";
+static const char condensedspan[] = "Condensada";
+static const char expandedspan[] = "Amplida";
+
+static const char regulardutch[] = "Normaal";
+static const char mediumdutch[] = "Normaal";
+static const char bookdutch[] = "Normaal";
+static const char bolddutch[] = "Vet";
+static const char demibolddutch[] = "Halfvet";
+static const char lightdutch[] = "Licht mager";
+static const char blackdutch[] = "Extra vet";
+static const char italicdutch[] = "Cursief";
+static const char italicdutch2[] = "italiek";
+static const char obliquedutch[] = "oblique";
+static const char obliquedutch2[] = "schuin";
+static const char condenseddutch[] = "Smal";
+static const char expandeddutch[] = "Breed";
+static const char outlinedutch[] = "Contour";
+
+static const char regularswed[] = "Mager";
+static const char boldswed[] = "Fet";
+static const char lightswed[] = "Extrafin";
+static const char blackswed[] = "Extrafet";
+static const char italicswed[] = "Kursiv";
+static const char condensedswed[] = "Smal";
+static const char expandedswed[] = "Bred";
+
+static const char regulardanish[] = "Normal";
+static const char bolddanish[] = "Fed";
+static const char demibolddanish[] = "Halvfed";
+static const char lightdanish[] = "Fin";
+static const char mediumdanish[] = "Medium";
+static const char blackdanish[] = "Extrafed";
+static const char italicdanish[] = "Kursiv";
+static const char condenseddanish[] = "Smal";
+static const char expandeddanish[] = "Bred";
+static const char outlinedanish[] = "Kontour";
+
+static const char regularnor[] = "Vanlig";
+static const char boldnor[] = "Halvfet";
+static const char lightnor[] = "Mager";
+static const char blacknor[] = "Fet";
+static const char italicnor[] = "Kursiv";
+static const char condensednor[] = "Smal";
+static const char expandednor[] = "Sperret";
+
+static const char regularital[] = "Normale";
+static const char demiboldital[] = "Nerretto";
+static const char boldital[] = "Nero";
+static const char thinital[] = "Fine";
+static const char lightital[] = "Chiaro";
+static const char mediumital[] = "Medio";
+static const char bookital[] = "Libro";
+static const char heavyital[] = "Nerissimo";
+static const char blackital[] = "ExtraNero";
+static const char italicital[] = "Cursivo";
+static const char obliqueital[] = "Obliquo";
+static const char condensedital[] = "Condensato";
+static const char expandedital[] = "Allargato";
+
+static const char regularru[] = "\320\236\320\261\321\213\321\207\320\275\321\213\320\271";
+static const char demiboldru[] = "\320\237\320\276\320\273\321\203\320\266\320\270\321\200\320\275\321\213\320\271";
+static const char boldru[] = "\320\236\320\261\321\213\321\207\320\275\321\213\320\271";
+static const char heavyru[] = "\320\241\320\262\320\265\321\200\321\205\320\266\320\270\321\200\320\275\321\213\320\271";
+static const char blackru[] = "\320\247\321\221\321\200\320\275\321\213\320\271";
+static const char thinru[] = "\320\242\320\276\320\275\320\272\320\270\320\271";
+static const char lightru[] = "\320\241\320\262\320\265\321\202\320\273\321\213\320\271";
+static const char italicru[] = "\320\232\321\203\321\200\321\201\320\270\320\262";
+static const char obliqueru[] = "\320\235\320\260\320\272\320\273\320\276\320\275";
+static const char condensedru[] = "\320\243\320\267\320\272\320\270\320\271";
+static const char expandedru[] = "\320\250\320\270\321\200\320\276\320\272\320\270\320\271";
+
+static const char regularhu[] = "Norm\303\241l";
+static const char demiboldhu[] = "Negyedk\303\266v\303\251r";
+static const char demiboldhu2[] = "F\303\251lk\303\266v\303\251r";
+static const char boldhu[] = "F\303\251lk\303\266v\303\251r";
+static const char boldhu2[] = "H\303\241romnegyedk\303\266v\303\251r";
+static const char thinhu[] = "Sov\303\241ny";
+static const char lighthu[] = "Vil\303\241gos";
+static const char mediumhu[] = "K\303\266zepes";
+static const char bookhu[] = "Halv\303\241ny";
+static const char bookhu2[] = "K\303\266nyv";
+static const char heavyhu[] = "K\303\266v\303\251r";
+static const char heavyhu2[] = "Extrak\303\266v\303\251r";
+static const char blackhu[] = "Fekete";
+static const char blackhu2[] = "S\303\266t\303\251t";
+static const char italichu[] = "D\305\221lt";
+static const char obliquehu[] = "D\303\266nt\303\266tt";
+static const char obliquehu2[] = "Ferde";
+static const char condensedhu[] = "Keskeny";
+static const char expandedhu[] = "Sz\303\251les";
+static const char outlinehu[] = "Kont\303\272ros";
+
+static const char regularpl[] = "podstawowa";
+static const char demiboldpl[] = "p\303\263\305\202gruba";
+static const char boldpl[] = "pogrubiona";
+static const char thinpl[] = "cienka";
+static const char lightpl[] = "bardzo cienka";
+static const char heavypl[] = "bardzo gruba";
+static const char italicpl[] = "pochy\305\202a";
+static const char obliquepl[] = "pochy\305\202a";
+static const char condensedpl[] = "w\304\205ska";
+static const char expandedpl[] = "szeroka";
+static const char outlinepl[] = "konturowa";
+static const char mediumpl[] = "zwyk\305\202a";
+static const char bookpl[] = "zwyk\305\202a";
+
+
+#ifndef LUA_FF_LIB
+
+static struct langstyle regs[] = { {0x409, regulareng}, { 0x40c, regularfren }, { 0x410, regularital }, { 0x407, regulargerm }, { 0x40a, regularspan }, { 0x419, regularru }, { 0x40e, regularhu },
+ { 0x413, regulardutch}, { 0x41d, regularswed }, { 0x414, regularnor },
+ { 0x406, regulardanish}, {0x415, regularpl }, { 0x804, "\346\255\243\345\270\270"},
+ { 0x408, "\316\272\316\261\316\275\316\277\316\275\316\271\316\272\316\256"}, { 0x42a, "Chu\341\272\251n"}, { 0 }};
+static struct langstyle meds[] = { {0x409, mediumeng}, { 0x410, mediumital },
+ { 0x40c, mediumfren }, { 0x407, mediumgerm }, { 0x40e, mediumhu },
+ { 0x406, mediumdanish}, {0x415, mediumpl }, { 0x804, "\344\270\255\347\255\211"},
+ { 0x408, "\302\265\316\265\317\203\316\261\316\257\316\261"}, { 0x42a, "V\341\273\253a"}, { 0x413, mediumdutch}, { 0 }};
+static struct langstyle books[] = { {0x409, bookeng}, { 0x410, bookital },
+ { 0x407, bookgerm }, { 0x40e, bookhu }, { 0x40e, bookhu2 },
+ { 0x415, bookpl}, { 0x804, "\344\271\246\344\275\223"}, { 0x408, "\303\237\316\271\303\237\316\273\316\257\316\277\317\205"},
+ { 0x42a, "S\303\241ch"}, { 0x413, bookdutch}, { 0 }};
+static struct langstyle bolds[] = { {0x409, boldeng}, { 0x410, boldital }, { 0x40c, boldfren }, { 0x407, boldgerm }, { 0x407, boldgerm2 }, { 0x40a, boldspan}, { 0x419, boldru }, { 0x40e, boldhu }, { 0x40e, boldhu2 },
+ { 0x413, bolddutch}, { 0x41d, boldswed }, { 0x414, boldnor },
+ { 0x406, bolddanish}, { 0x415, boldpl}, { 0x804, "\347\262\227\344\275\223"},
+ { 0x408, "\316\255\316\275\317\204\316\277\316\275\316\267"}, { 0x42a, "\304\220\341\272\255m"}, { 0 }};
+static struct langstyle italics[] = { {0x409, italiceng}, { 0x410, italicital }, { 0x40c, italicfren }, { 0x407, italicgerm }, { 0x40a, italicspan}, { 0x419, italicru }, { 0x40e, italichu },
+ { 0x413, italicdutch}, { 0x413, italicdutch2}, { 0x41d, italicswed }, { 0x414, italicnor },
+ { 0x406, italicdanish}, { 0x415, italicpl}, { 0x804, "\346\226\234\344\275\223"},
+ { 0x408, "\316\233\316\265\316\271\317\210\316\257\316\261\317\202"}, { 0x42a, "Nghi\303\252ng" }, { 0 }};
+static struct langstyle obliques[] = { {0x409, obliqueeng}, { 0x410, obliqueital },
+ { 0x40c, obliquefren }, { 0x407, obliquegerm }, { 0x419, obliqueru },
+ { 0x40e, obliquehu }, { 0x40e, obliquehu2 }, {0x415, obliquepl},
+ { 0x804, "\346\226\234\344\275\223"}, { 0x408, "\317\200\316\273\316\254\316\263\316\271\316\261"},
+ { 0x42a, "Xi\303\252n" }, { 0x413, obliquedutch}, { 0x413, obliquedutch2}, { 0 }};
+static struct langstyle demibolds[] = { {0x409, demiboldeng}, {0x409, demiboldeng3}, {0x409, demiboldeng5},
+ { 0x410, demiboldital }, { 0x40c, demiboldfren }, { 0x40c, demiboldfren2 }, { 0x407, demiboldgerm }, { 0x407, demiboldgerm2 },
+ { 0x419, demiboldru }, { 0x40e, demiboldhu }, { 0x40e, demiboldhu2 },
+ { 0x406, demibolddanish}, { 0x415, demiboldpl },
+ { 0x804, "\347\225\245\347\262\227"}, { 0x408, "\316\267\302\265\316\271\316\255\316\275\317\204\316\277\316\275\316\267"},
+ { 0x42a, "N\341\273\255a \304\221\341\272\255m"}, { 0x413, demibolddutch}, { 0 }};
+static struct langstyle heavys[] = { {0x409, heavyeng}, { 0x410, heavyital },
+ { 0x419, heavyru }, { 0x40e, heavyhu }, { 0x40e, heavyhu2 },
+ { 0x415, heavypl }, { 0x804, "\347\262\227"}, { 0 }};
+static struct langstyle blacks[] = { {0x409, blackeng}, { 0x410, blackital }, { 0x40c, blackfren }, { 0x407, blackgerm }, { 0x419, blackru }, { 0x40e, blackhu }, { 0x40e, blackhu2 }, { 0x40a, blackspan },
+ { 0x413, blackdutch}, { 0x41d, blackswed }, { 0x414, blacknor }, { 0x406, blackdanish},
+ { 0x415, heavypl }, { 0x804, "\351\273\221"}, { 0x408, "\302\265\316\261\317\215\317\201\316\261"},
+ { 0x42a, "\304\220en"}, {0} };
+static struct langstyle thins[] = { {0x409, thineng}, { 0x410, thinital },
+ { 0x419, thinru }, { 0x40e, thinhu }, { 0x415, thinpl},
+ { 0x804, "\347\273\206"}, { 0 }};
+static struct langstyle extralights[] = { {0x409, extralighteng}, {0x409, extralighteng2},
+ { 0x804, "\346\236\201\347\273\206"}, {0}};
+static struct langstyle lights[] = { {0x409, lighteng}, {0x410, lightital}, {0x40c, lightfren}, {0x407, lightgerm}, { 0x419, lightru }, { 0x40e, lighthu }, { 0x40a, lightspan },
+ { 0x413, lightdutch}, { 0x41d, lightswed }, { 0x414, lightnor },
+ { 0x406, lightdanish}, { 0x415, lightpl}, { 0x804, "\347\273\206"},
+ { 0x408, "\316\273\316\265\317\200\317\204\316\256"}, { 0x42a, "Nh\341\272\271" }, { 0 }};
+static struct langstyle condenseds[] = { {0x409, condensedeng}, {0x410, condensedital}, {0x40c, condensedfren}, {0x407, condensedgerm}, { 0x419, condensedru }, { 0x40e, condensedhu }, { 0x40a, condensedspan },
+ { 0x413, condenseddutch}, { 0x41d, condensedswed },
+ { 0x414, condensednor }, { 0x406, condenseddanish},
+ { 0x415, condensedpl }, { 0x804, "\345\216\213\347\274\251"},
+ { 0x408, "\317\200\317\205\316\272\316\275\316\256"}, { 0x42a, "H\341\272\271p" }, { 0 }};
+static struct langstyle expandeds[] = { {0x409, expandedeng}, {0x410, expandedital}, {0x40c, expandedfren}, {0x407, expandedgerm}, { 0x419, expandedru }, { 0x40e, expandedhu }, { 0x40a, expandedspan },
+ { 0x413, expandeddutch}, { 0x41d, expandedswed }, { 0x414, expandednor },
+ { 0x406, expandeddanish}, { 0x415, expandedpl }, { 0x804, "\345\212\240\345\256\275"},
+ { 0x408, "\316\261\317\201\316\261\316\271\316\256"}, { 0x42a, "R\341\273\231ng" }, { 0 }};
+static struct langstyle outlines[] = { {0x409, outlineeng}, {0x40c, outlinefren},
+ {0x407, outlinegerm}, {0x40e, outlinehu}, { 0x406, outlinedanish},
+ {0x415, outlinepl}, { 0x804, "\350\275\256\345\273\223"}, { 0x408, "\317\200\316\265\317\201\316\271\316\263\317\201\316\254\316\274\316\274\316\261\317\204\316\277\317\202"},
+ {0x42a, "N\303\251t ngo\303\240i" }, { 0x413, outlinedutch}, { 0 }};
+static struct langstyle *stylelist[] = {regs, meds, books, demibolds, bolds, heavys, blacks,
+ extralights, lights, thins, italics, obliques, condenseds, expandeds, outlines, NULL };
+#endif
+
+#define CID_Features 101 /* Mac stuff */
+#define CID_FeatureDel 103
+#define CID_FeatureEdit 105
+
+#define CID_Family 1002
+#define CID_Weight 1003
+#define CID_ItalicAngle 1004
+#define CID_UPos 1005
+#define CID_UWidth 1006
+#define CID_Ascent 1007
+#define CID_Descent 1008
+#define CID_Notice 1010
+#define CID_Version 1011
+#define CID_UniqueID 1012
+#define CID_HasVerticalMetrics 1013
+#define CID_VOriginLab 1014
+#define CID_VOrigin 1015
+#define CID_Fontname 1016
+#define CID_Em 1017
+#define CID_Scale 1018
+#define CID_IsOrder2 1019
+#define CID_IsMultiLayer 1020
+#define CID_Interpretation 1021
+#define CID_IsStrokedFont 1022
+#define CID_StrokeWidth 1023
+#define CID_Namelist 1024
+#define CID_XUID 1113
+#define CID_Human 1114
+#define CID_SameAsFontname 1115
+#define CID_HasDefBase 1116
+#define CID_DefBaseName 1117
+
+#define CID_PrivateEntries 2001
+#define CID_PrivateValues 2002
+#define CID_Add 2003
+#define CID_Guess 2004
+#define CID_Remove 2005
+#define CID_Hist 2006
+
+#define CID_TTFTabs 3000
+#define CID_WeightClass 3001
+#define CID_WidthClass 3002
+#define CID_PFMFamily 3003
+#define CID_FSType 3004
+#define CID_NoSubsetting 3005
+#define CID_OnlyBitmaps 3006
+#define CID_LineGap 3007
+#define CID_VLineGap 3008
+#define CID_VLineGapLab 3009
+#define CID_WinAscent 3010
+#define CID_WinAscentLab 3011
+#define CID_WinAscentIsOff 3012
+#define CID_WinDescent 3013
+#define CID_WinDescentLab 3014
+#define CID_WinDescentIsOff 3015
+#define CID_TypoAscent 3016
+#define CID_TypoAscentLab 3017
+#define CID_TypoAscentIsOff 3018
+#define CID_TypoDescent 3019
+#define CID_TypoDescentLab 3020
+#define CID_TypoDescentIsOff 3021
+#define CID_TypoLineGap 3022
+#define CID_HHeadAscent 3023
+#define CID_HHeadAscentLab 3024
+#define CID_HHeadAscentIsOff 3025
+#define CID_HHeadDescent 3026
+#define CID_HHeadDescentLab 3027
+#define CID_HHeadDescentIsOff 3028
+#define CID_Vendor 3029
+#define CID_IBMFamily 3030
+#define CID_OS2Version 3031
+#define CID_UseTypoMetrics 3032
+#define CID_WeightWidthSlopeOnly 3033
+
+#define CID_SubSuperDefault 3100
+#define CID_SubXSize 3101
+#define CID_SubYSize 3102
+#define CID_SubXOffset 3103
+#define CID_SubYOffset 3104
+#define CID_SuperXSize 3105
+#define CID_SuperYSize 3106
+#define CID_SuperXOffset 3107
+#define CID_SuperYOffset 3108
+#define CID_StrikeoutSize 3109
+#define CID_StrikeoutPos 3110
+
+#define CID_PanFamily 4001
+#define CID_PanSerifs 4002
+#define CID_PanWeight 4003
+#define CID_PanProp 4004
+#define CID_PanContrast 4005
+#define CID_PanStrokeVar 4006
+#define CID_PanArmStyle 4007
+#define CID_PanLetterform 4008
+#define CID_PanMidLine 4009
+#define CID_PanXHeight 4010
+#define CID_PanDefault 4011
+#define CID_PanFamilyLab 4021
+#define CID_PanSerifsLab 4022
+#define CID_PanWeightLab 4023
+#define CID_PanPropLab 4024
+#define CID_PanContrastLab 4025
+#define CID_PanStrokeVarLab 4026
+#define CID_PanArmStyleLab 4027
+#define CID_PanLetterformLab 4028
+#define CID_PanMidLineLab 4029
+#define CID_PanXHeightLab 4030
+
+#define CID_TNLangSort 5001
+#define CID_TNStringSort 5002
+#define CID_TNVScroll 5003
+#define CID_TNHScroll 5004
+#define CID_TNames 5005
+
+#define CID_Language 5006 /* Used by AskForLangNames */
+
+#define CID_Gasp 5100
+#define CID_GaspVersion 5101
+#define CID_HeadClearType 5102
+
+#define CID_Comment 6001
+
+#define CID_MarkClasses 7101
+#define CID_MarkNew 7102
+#define CID_MarkEdit 7103
+
+#define CID_TeXText 8001
+#define CID_TeXMathSym 8002
+#define CID_TeXMathExt 8003
+#define CID_MoreParams 8005
+#define CID_TeXExtraSpLabel 8006
+#define CID_TeX 8007 /* through 8014 */
+
+#define CID_DesignSize 8301
+#define CID_DesignBottom 8302
+#define CID_DesignTop 8303
+#define CID_StyleID 8304
+#define CID_StyleName 8305
+#define CID_StyleNameNew 8306
+#define CID_StyleNameDel 8307
+#define CID_StyleNameRename 8308
+
+#define CID_Tabs 10001
+#define CID_OK 10002
+#define CID_Cancel 10003
+#define CID_MainGroup 10004
+
+#define CID_Lookups 11000
+#define CID_LookupTop 11001
+#define CID_LookupUp 11002
+#define CID_LookupDown 11003
+#define CID_LookupBottom 11004
+#define CID_AddLookup 11005
+#define CID_AddSubtable 11006
+#define CID_EditMetadata 11007
+#define CID_EditSubtable 11008
+#define CID_DeleteLookup 11009
+#define CID_MergeLookup 11010
+#define CID_RevertLookups 11011
+#define CID_LookupSort 11012
+#define CID_ImportLookups 11013
+#define CID_LookupWin 11020 /* (GSUB, add 1 for GPOS) */
+#define CID_LookupVSB 11022 /* (GSUB, add 1 for GPOS) */
+#define CID_LookupHSB 11024 /* (GSUB, add 1 for GPOS) */
+#define CID_SaveLookup 11026
+#define CID_SaveFeat 11027
+#define CID_AddAllAlternates 11028
+#define CID_AddDFLT 11029
+
+#define CID_MacAutomatic 16000
+#define CID_MacStyles 16001
+#define CID_MacFOND 16002
+
+#define CID_Unicode 16100
+#define CID_UnicodeEmpties 16101
+
+const char *TTFNameIds(int id) {
+ int i;
+
+ FontInfoInit();
+ for ( i=0; ttfnameids[i].text!=NULL; ++i )
+ if ( ttfnameids[i].userdata == (void *) (intpt) id )
+return( (char *) ttfnameids[i].text );
+
+ if ( id==6 )
+return( "Postscript" );
+
+return( _("Unknown") );
+}
+
+const char *MSLangString(int language) {
+ int i;
+
+ FontInfoInit();
+ for ( i=0; mslanguages[i].text!=NULL; ++i )
+ if ( mslanguages[i].userdata == (void *) (intpt) language )
+return( (char *) mslanguages[i].text );
+
+ language &= 0xff;
+ for ( i=0; mslanguages[i].text!=NULL; ++i )
+ if ( ((intpt) mslanguages[i].userdata & 0xff) == language )
+return( (char *) mslanguages[i].text );
+
+return( _("Unknown") );
+}
+
+
+struct psdict *PSDictCopy(struct psdict *dict) {
+ struct psdict *ret;
+ int i;
+
+ if ( dict==NULL )
+return( NULL );
+
+ ret = gcalloc(1,sizeof(struct psdict));
+ ret->cnt = dict->cnt; ret->next = dict->next;
+ ret->keys = gcalloc(ret->cnt,sizeof(char *));
+ ret->values = gcalloc(ret->cnt,sizeof(char *));
+ for ( i=0; i<dict->next; ++i ) {
+ ret->keys[i] = copy(dict->keys[i]);
+ ret->values[i] = copy(dict->values[i]);
+ }
+
+return( ret );
+}
+
+int PSDictFindEntry(struct psdict *dict, char *key) {
+ int i;
+
+ if ( dict==NULL )
+return( -1 );
+
+ for ( i=0; i<dict->next; ++i )
+ if ( strcmp(dict->keys[i],key)==0 )
+return( i );
+
+return( -1 );
+}
+
+char *PSDictHasEntry(struct psdict *dict, char *key) {
+ int i;
+
+ if ( dict==NULL )
+return( NULL );
+
+ for ( i=0; i<dict->next; ++i )
+ if ( strcmp(dict->keys[i],key)==0 )
+return( dict->values[i] );
+
+return( NULL );
+}
+
+int PSDictRemoveEntry(struct psdict *dict, char *key) {
+ int i;
+
+ if ( dict==NULL )
+return( false );
+
+ for ( i=0; i<dict->next; ++i )
+ if ( strcmp(dict->keys[i],key)==0 )
+ break;
+ if ( i==dict->next )
+return( false );
+ free( dict->keys[i]);
+ free( dict->values[i] );
+ --dict->next;
+ while ( i<dict->next ) {
+ dict->keys[i] = dict->keys[i+1];
+ dict->values[i] = dict->values[i+1];
+ ++i;
+ }
+
+return( true );
+}
+
+int PSDictChangeEntry(struct psdict *dict, char *key, char *newval) {
+ int i;
+
+ if ( dict==NULL )
+return( -1 );
+
+ for ( i=0; i<dict->next; ++i )
+ if ( strcmp(dict->keys[i],key)==0 )
+ break;
+ if ( i==dict->next ) {
+ if ( dict->next>=dict->cnt ) {
+ dict->cnt += 10;
+ dict->keys = grealloc(dict->keys,dict->cnt*sizeof(char *));
+ dict->values = grealloc(dict->values,dict->cnt*sizeof(char *));
+ }
+ dict->keys[dict->next] = copy(key);
+ dict->values[dict->next] = NULL;
+ ++dict->next;
+ }
+ free(dict->values[i]);
+ dict->values[i] = copy(newval);
+return( i );
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+/* These are Postscript names, and as such should not be translated */
+enum { pt_number, pt_boolean, pt_array, pt_code };
+static struct { const char *name; short type, arr_size, present; } KnownPrivates[] = {
+ { "BlueValues", pt_array, 14 },
+ { "OtherBlues", pt_array, 10 },
+ { "BlueFuzz", pt_number },
+ { "FamilyBlues", pt_array, 14 },
+ { "FamilyOtherBlues", pt_array, 10 },
+ { "BlueScale", pt_number },
+ { "BlueShift", pt_number },
+ { "StdHW", pt_array, 1 },
+ { "StdVW", pt_array, 1 },
+ { "StemSnapH", pt_array, 12 },
+ { "StemSnapV", pt_array, 12 },
+ { "ForceBold", pt_boolean },
+ { "LanguageGroup", pt_number },
+ { "RndStemUp", pt_number },
+ { "lenIV", pt_number },
+ { "ExpansionFactor", pt_number },
+ { "Erode", pt_code },
+/* I am deliberately not including Subrs and OtherSubrs */
+/* The first could not be entered (because it's a set of binary strings) */
+/* And the second has special meaning to us and must be handled with care */
+ { NULL }
+};
+
+struct ask_data {
+ int ret;
+ int done;
+};
+
+static int Ask_Cancel(GGadget *g, GEvent *e) {
+ GWindow gw;
+ struct ask_data *d;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ gw = GGadgetGetWindow(g);
+ d = GDrawGetUserData(gw);
+ d->done = true;
+ }
+return( true );
+}
+
+static int Ask_OK(GGadget *g, GEvent *e) {
+ GWindow gw;
+ struct ask_data *d;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ gw = GGadgetGetWindow(g);
+ d = GDrawGetUserData(gw);
+ d->done = d->ret = true;
+ }
+return( true );
+}
+
+static int ask_e_h(GWindow gw, GEvent *event) {
+ if ( event->type==et_close ) {
+ struct ask_data *d = GDrawGetUserData(gw);
+ d->done = true;
+ } else if ( event->type == et_char ) {
+return( false );
+ }
+return( true );
+}
+
+static char *AskKey(SplineFont *sf) {
+ int i,j, cnt=0;
+ GTextInfo *ti;
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[8], boxes[3], *varray[9], *harray[7];
+ GTextInfo label[8];
+ struct ask_data d;
+ char *ret;
+ int ptwidth;
+
+ if ( sf->private==NULL )
+ for ( i=0; KnownPrivates[i].name!=NULL; ++i ) {
+ KnownPrivates[i].present = 0;
+ ++cnt;
+ }
+ else {
+ for ( i=0; KnownPrivates[i].name!=NULL; ++i ) {
+ for ( j=0; j<sf->private->next; ++j )
+ if ( strcmp(KnownPrivates[i].name,sf->private->keys[j])==0 )
+ break;
+ if ( !(KnownPrivates[i].present = (j<sf->private->next)) )
+ ++cnt;
+ }
+ }
+ if ( cnt==0 )
+ ti = NULL;
+ else {
+ ti = gcalloc(cnt+1,sizeof(GTextInfo));
+ for ( i=cnt=0; KnownPrivates[i].name!=NULL; ++i )
+ if ( !KnownPrivates[i].present )
+ ti[cnt++].text = uc_copy(KnownPrivates[i].name);
+ }
+
+ memset(&d,'\0',sizeof(d));
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Private Key");
+ pos.x = pos.y = 0;
+ ptwidth = 2*GIntGetResource(_NUM_Buttonsize)+GGadgetScale(60);
+ pos.width =GDrawPointsToPixels(NULL,ptwidth);
+ pos.height = GDrawPointsToPixels(NULL,90);
+ gw = GDrawCreateTopWindow(NULL,&pos,ask_e_h,&d,&wattrs);
+
+ memset(&label,0,sizeof(label));
+ memset(&gcd,0,sizeof(gcd));
+
+ label[0].text = (unichar_t *) _("Key (in Private dictionary)");
+ label[0].text_is_1byte = true;
+ gcd[0].gd.label = &label[0];
+ gcd[0].gd.pos.x = 10; gcd[0].gd.pos.y = 6;
+ gcd[0].gd.flags = gg_visible | gg_enabled;
+ gcd[0].creator = GLabelCreate;
+ varray[0] = &gcd[0]; varray[1] = NULL;
+
+ gcd[1].gd.pos.x = 10; gcd[1].gd.pos.y = 18; gcd[1].gd.pos.width = ptwidth-20;
+ gcd[1].gd.flags = gg_visible | gg_enabled;
+ gcd[1].creator = GTextFieldCreate;
+ if ( ti!=NULL ) {
+ gcd[1].gd.u.list = ti;
+ gcd[1].creator = GListFieldCreate;
+ }
+ varray[2] = &gcd[1]; varray[3] = NULL;
+ varray[4] = GCD_Glue; varray[5] = NULL;
+
+ gcd[2].gd.pos.x = 20-3; gcd[2].gd.pos.y = 90-35-3;
+ gcd[2].gd.pos.width = -1; gcd[2].gd.pos.height = 0;
+ gcd[2].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[2].text = (unichar_t *) _("_OK");
+ label[2].text_is_1byte = true;
+ label[2].text_in_resource = true;
+ gcd[2].gd.label = &label[2];
+ gcd[2].gd.handle_controlevent = Ask_OK;
+ gcd[2].creator = GButtonCreate;
+ harray[0] = GCD_Glue; harray[1] = &gcd[2]; harray[2] = GCD_Glue;
+
+ gcd[3].gd.pos.x = -20; gcd[3].gd.pos.y = 90-35;
+ gcd[3].gd.pos.width = -1; gcd[3].gd.pos.height = 0;
+ gcd[3].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[3].text = (unichar_t *) _("_Cancel");
+ label[3].text_is_1byte = true;
+ label[3].text_in_resource = true;
+ gcd[3].gd.label = &label[3];
+ gcd[3].gd.handle_controlevent = Ask_Cancel;
+ gcd[3].creator = GButtonCreate;
+ harray[3] = GCD_Glue; harray[4] = &gcd[3]; harray[5] = GCD_Glue;
+ harray[6] = NULL;
+ varray[6] = &boxes[2]; varray[7] = NULL;
+ varray[8] = NULL;
+
+ gcd[4].gd.pos.x = 2; gcd[4].gd.pos.y = 2;
+ gcd[4].gd.pos.width = pos.width-4; gcd[4].gd.pos.height = pos.height-2;
+ gcd[4].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
+ gcd[4].creator = GGroupCreate;
+
+ memset(boxes,0,sizeof(boxes));
+ boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
+ boxes[0].gd.flags = gg_enabled|gg_visible;
+ boxes[0].gd.u.boxelements = varray;
+ boxes[0].creator = GHVGroupCreate;
+
+ boxes[2].gd.flags = gg_enabled|gg_visible;
+ boxes[2].gd.u.boxelements = harray;
+ boxes[2].creator = GHBoxCreate;
+
+ GGadgetsCreate(gw,boxes);
+ GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
+ GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
+ GHVBoxFitWindow(boxes[0].ret);
+ GWidgetHidePalettes();
+ GDrawSetVisible(gw,true);
+ while ( !d.done )
+ GDrawProcessOneEvent(NULL);
+ ret = NULL;
+ if ( d.ret )
+ ret = cu_copy(_GGadgetGetTitle(gcd[1].ret));
+ GTextInfoListFree(ti);
+ GDrawDestroyWindow(gw);
+return( ret );
+}
+
+static GTextInfo *PI_ListSet(SplineFont *sf) {
+ GTextInfo *ti = gcalloc((sf->private==NULL?0:sf->private->next)+1,sizeof( GTextInfo ));
+ int i=0;
+
+ if ( sf->private!=NULL ) {
+ for ( i=0; i<sf->private->next; ++i ) {
+ ti[i].text = uc_copy(sf->private->keys[i]);
+ }
+ }
+ if ( i!=0 )
+ ti[0].selected = true;
+return( ti );
+}
+
+static GTextInfo **PI_ListArray(struct psdict *private) {
+ GTextInfo **ti = gcalloc((private==NULL?0:private->next)+1,sizeof( GTextInfo *));
+ int i=0;
+
+ if ( private!=NULL ) {
+ for ( i=0; i<private->next; ++i ) {
+ ti[i] = gcalloc(1,sizeof(GTextInfo));
+ ti[i]->fg = ti[i]->bg = COLOR_DEFAULT;
+ ti[i]->text = uc_copy(private->keys[i]);
+ }
+ }
+ ti[i] = gcalloc(1,sizeof(GTextInfo));
+ if ( i!=0 )
+ ti[0]->selected = true;
+return( ti );
+}
+
+static void PIPrivateCheck(struct gfi_data *d) {
+ if ( d->private==NULL ) {
+ if ( d->sf->private==NULL ) {
+ d->private = gcalloc(1,sizeof(struct psdict));
+ d->private->cnt = 10;
+ d->private->keys = gcalloc(10,sizeof(char *));
+ d->private->values = gcalloc(10,sizeof(char *));
+ } else
+ d->private = PSDictCopy(d->sf->private);
+ }
+}
+
+static int PIFinishFormer(struct gfi_data *d) {
+ unichar_t *end;
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buts[3];
+ buts[0] = _("_OK"); buts[1] = _("_Cancel"); buts[2]=NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buts[] = { GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL };
+#endif
+
+ if ( d->old_sel < 0 )
+return( true );
+ if ( d->private==NULL && d->sf->private!=NULL ) {
+ const unichar_t *val = _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_PrivateValues));
+ if ( uc_strcmp(val,d->sf->private->values[d->old_sel])==0 )
+return( true ); /* Didn't change */
+ PIPrivateCheck(d);
+ }
+ if ( d->private!=NULL && d->old_sel>=0 && d->old_sel!=d->private->next ) {
+ const unichar_t *val = _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_PrivateValues));
+ const unichar_t *pt = val;
+ int i;
+
+ /* does the type appear reasonable? */
+ while ( isspace(*pt)) ++pt;
+ for ( i=0; KnownPrivates[i].name!=NULL; ++i )
+ if ( strcmp(KnownPrivates[i].name,d->private->keys[d->old_sel])==0 )
+ break;
+ if ( KnownPrivates[i].name!=NULL ) {
+ if ( KnownPrivates[i].type==pt_array ) {
+ if ( *pt!='[' && gwwv_ask(_("Bad type"),(const char **) buts,0,1,_("Expected array.\nProceed anyway?"))==1 )
+return( false );
+ } else if ( KnownPrivates[i].type==pt_boolean ) {
+ if ( uc_strcmp(pt,"true")!=0 && uc_strcmp(pt,"false")!=0 &&
+ gwwv_ask(_("Bad type"),(const char **) buts,0,1,_("Expected boolean.\nProceed anyway?"))==1 )
+return( false );
+ } else if ( KnownPrivates[i].type==pt_code ) {
+ if ( *pt!='{' && gwwv_ask(_("Bad type"),(const char **) buts,0,1,_("Expected code.\nProceed anyway?"))==1 )
+return( false );
+ } else if ( KnownPrivates[i].type==pt_number ) {
+ u_strtod(pt,&end);
+ while ( isspace(*end)) ++end;
+ if ( *end!='\0' && gwwv_ask(_("Bad type"),(const char **) buts,0,1,_("Expected number.\nProceed anyway?"))==1 )
+return( false );
+ }
+ }
+
+ /* Ok then set it */
+ free(d->private->values[d->old_sel]);
+ d->private->values[d->old_sel] = cu_copy(val);
+ d->old_sel = -1;
+ }
+return( true );
+}
+
+static void ProcessListSel(struct gfi_data *d) {
+ GGadget *list = GWidgetGetControl(d->gw,CID_PrivateEntries);
+ int sel = GGadgetGetFirstListSelectedItem(list);
+ unichar_t *temp;
+ static const unichar_t nullstr[] = { 0 };
+ SplineFont *sf = d->sf;
+ struct psdict *private;
+
+ if ( d->old_sel==sel )
+return;
+
+ if ( !PIFinishFormer(d)) {
+ /*GGadgetSelectListItem(list,sel,false);*/
+ GGadgetSelectListItem(list,d->old_sel,true);
+return;
+ }
+ private = d->private ? d->private : sf->private;
+ if ( sel==-1 ) {
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_Remove),false);
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_Guess),false);
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_Hist),false);
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_PrivateValues),false);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_PrivateValues),nullstr);
+ } else {
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_Remove),true);
+ if ( strcmp(private->keys[sel],"BlueValues")==0 ||
+ strcmp(private->keys[sel],"OtherBlues")==0 ||
+ strcmp(private->keys[sel],"StdHW")==0 ||
+ strcmp(private->keys[sel],"StemSnapH")==0 ||
+ strcmp(private->keys[sel],"StdVW")==0 ||
+ strcmp(private->keys[sel],"StemSnapV")==0 ) {
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_Guess),true);
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_Hist),true);
+ } else {
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_Guess),false);
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_Hist),false);
+ }
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_PrivateValues),true);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_PrivateValues),
+ temp = uc_copy( private->values[sel]));
+ free( temp );
+ GTextFieldShow(GWidgetGetControl(d->gw,CID_PrivateValues),0);
+ }
+ d->old_sel = sel;
+}
+
+static int PI_Add(GGadget *g, GEvent *e) {
+ GWindow gw;
+ struct gfi_data *d;
+ GGadget *list;
+ int i;
+ char *newkey;
+ GTextInfo **ti;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ gw = GGadgetGetWindow(g);
+ d = GDrawGetUserData(gw);
+ if ( !PIFinishFormer(d))
+return(true);
+ newkey = AskKey(d->sf);
+ if ( newkey==NULL )
+return( true );
+ PIPrivateCheck(d);
+ if (( i = PSDictFindEntry(d->private,newkey))==-1 )
+ i = PSDictChangeEntry(d->private,newkey,"");
+ list = GWidgetGetControl(d->gw,CID_PrivateEntries);
+ ti = PI_ListArray(d->private);
+ if ( i>0 ) {
+ ti[0]->selected = false;
+ ti[i]->selected = true;
+ }
+ GGadgetSetList(list,ti,false);
+ d->old_sel = -1;
+ ProcessListSel(d);
+ free(newkey);
+ }
+return( true );
+}
+
+static void arraystring(char *buffer,real *array,int cnt) {
+ int i, ei;
+
+ for ( ei=cnt; ei>1 && array[ei-1]==0; --ei );
+ *buffer++ = '[';
+ for ( i=0; i<ei; ++i ) {
+ sprintf(buffer, "%d ", (int) array[i]);
+ buffer += strlen(buffer);
+ }
+ if ( buffer[-1] ==' ' ) --buffer;
+ *buffer++ = ']'; *buffer='\0';
+}
+
+static void SnapSet(struct psdict *private,real stemsnap[12], real snapcnt[12],
+ char *name1, char *name2 ) {
+ int i, mi;
+ char buffer[211];
+
+ mi = -1;
+ for ( i=0; stemsnap[i]!=0 && i<12; ++i )
+ if ( mi==-1 ) mi = i;
+ else if ( snapcnt[i]>snapcnt[mi] ) mi = i;
+ if ( mi==-1 )
+return;
+ sprintf( buffer, "[%d]", (int) stemsnap[mi]);
+ PSDictChangeEntry(private,name1,buffer);
+ arraystring(buffer,stemsnap,12);
+ PSDictChangeEntry(private,name2,buffer);
+}
+
+static int PI_Guess(GGadget *g, GEvent *e) {
+ GWindow gw;
+ struct gfi_data *d;
+ GGadget *list;
+ int sel;
+ SplineFont *sf;
+ real bluevalues[14], otherblues[10];
+ real snapcnt[12];
+ real stemsnap[12];
+ char buffer[211];
+ unichar_t *temp;
+ struct psdict *private;
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buts[3];
+ buts[0] = _("_OK"); buts[1] = _("_Cancel"); buts[2]=NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buts[] = { GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL };
+#endif
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ gw = GGadgetGetWindow(g);
+ d = GDrawGetUserData(gw);
+ sf = d->sf;
+ private = d->private ? d->private : sf->private;
+ list = GWidgetGetControl(d->gw,CID_PrivateEntries);
+ sel = GGadgetGetFirstListSelectedItem(list);
+ if ( strcmp(private->keys[sel],"BlueValues")==0 ||
+ strcmp(private->keys[sel],"OtherBlues")==0 ) {
+ if ( gwwv_ask(_("Guess"),(const char **) buts,0,1,_("This will change both BlueValues and OtherBlues.\nDo you want to continue?"))==1 )
+return( true );
+ PIPrivateCheck(d);
+ private = d->private;
+ FindBlues(sf,bluevalues,otherblues);
+ arraystring(buffer,bluevalues,14);
+ PSDictChangeEntry(private,"BlueValues",buffer);
+ if ( otherblues[0]!=0 || otherblues[1]!=0 ) {
+ arraystring(buffer,otherblues,10);
+ PSDictChangeEntry(private,"OtherBlues",buffer);
+ }
+ } else if ( strcmp(private->keys[sel],"StdHW")==0 ||
+ strcmp(private->keys[sel],"StemSnapH")==0 ) {
+ if ( gwwv_ask(_("Guess"),(const char **) buts,0,1,_("This will change both StdHW and StemSnapH.\nDo you want to continue?"))==1 )
+return( true );
+ FindHStems(sf,stemsnap,snapcnt);
+ PIPrivateCheck(d);
+ SnapSet(d->private,stemsnap,snapcnt,"StdHW","StemSnapH");
+ } else if ( strcmp(private->keys[sel],"StdVW")==0 ||
+ strcmp(private->keys[sel],"StemSnapV")==0 ) {
+ if ( gwwv_ask(_("Guess"),(const char **) buts,0,1,_("This will change both StdVW and StemSnapV.\nDo you want to continue?"))==1 )
+return( true );
+ FindVStems(sf,stemsnap,snapcnt);
+ PIPrivateCheck(d);
+ SnapSet(d->private,stemsnap,snapcnt,"StdVW","StemSnapV");
+ }
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_PrivateValues),
+ temp = uc_copy( d->private->values[sel]));
+ free( temp );
+ }
+return( true );
+}
+
+static int PI_Hist(GGadget *g, GEvent *e) {
+ GWindow gw;
+ struct gfi_data *d;
+ GGadget *list;
+ int sel;
+ SplineFont *sf;
+ struct psdict *private;
+ enum hist_type h;
+ unichar_t *temp;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ gw = GGadgetGetWindow(g);
+ d = GDrawGetUserData(gw);
+ sf = d->sf;
+ PIPrivateCheck(d);
+ private = d->private ? d->private : sf->private;
+ list = GWidgetGetControl(d->gw,CID_PrivateEntries);
+ sel = GGadgetGetFirstListSelectedItem(list);
+ if ( strcmp(private->keys[sel],"BlueValues")==0 ||
+ strcmp(private->keys[sel],"OtherBlues")==0 )
+ h = hist_blues;
+ else if ( strcmp(private->keys[sel],"StdHW")==0 ||
+ strcmp(private->keys[sel],"StemSnapH")==0 )
+ h = hist_hstem;
+ else if ( strcmp(private->keys[sel],"StdVW")==0 ||
+ strcmp(private->keys[sel],"StemSnapV")==0 )
+ h = hist_vstem;
+ else
+return( true ); /* can't happen */
+ SFHistogram(sf,private,NULL,NULL,h);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_PrivateValues),
+ temp = uc_copy( d->private->values[sel]));
+ free( temp );
+ }
+return( true );
+}
+
+static int PI_Delete(GGadget *g, GEvent *e) {
+ GWindow gw;
+ struct gfi_data *d;
+ GGadget *list;
+ int sel;
+ SplineFont *sf;
+ GTextInfo **ti;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ gw = GGadgetGetWindow(g);
+ d = GDrawGetUserData(gw);
+ PIPrivateCheck(d);
+ sf = d->sf;
+ list = GWidgetGetControl(d->gw,CID_PrivateEntries);
+ sel = GGadgetGetFirstListSelectedItem(list);
+ PSDictRemoveEntry(d->private, d->private->keys[sel]);
+ sf->changed = true;
+ ti = PI_ListArray(d->private);
+ --sel;
+ if ( d->private!=NULL && sel>=d->private->next )
+ sel = d->private->next-1;
+ if ( sel>0 ) {
+ ti[0]->selected = false;
+ ti[sel]->selected = true;
+ }
+ GGadgetSetList(list,ti,false);
+ d->old_sel = -2;
+ ProcessListSel(d);
+ }
+return( true );
+}
+
+static int PI_ListSel(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ ProcessListSel(GDrawGetUserData(GGadgetGetWindow(g)));
+ }
+return( true );
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+/* Use URW 4 letter abbreviations */
+static char *knownweights[] = { "Demi", "Bold", "Regu", "Medi", "Book", "Thin",
+ "Ligh", "Heav", "Blac", "Ultr", "Nord", "Norm", "Gras", "Stan", "Halb",
+ "Fett", "Mage", "Mitt", "Buch", NULL };
+static char *realweights[] = { "Demi", "Bold", "Regular", "Medium", "Book", "Thin",
+ "Light", "Heavy", "Black", "Ultra", "Nord", "Normal", "Gras", "Standard", "Halbfett",
+ "Fett", "Mager", "Mittel", "Buchschrift", NULL};
+#ifndef LUA_FF_LIB
+static char *moreweights[] = { "ExtraLight", "VeryLight", NULL };
+static char **noticeweights[] = { moreweights, realweights, knownweights, NULL };
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static int GFI_NameChange(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
+ GWindow gw = GGadgetGetWindow(g);
+ struct gfi_data *gfi = GDrawGetUserData(gw);
+ const unichar_t *uname = _GGadgetGetTitle(GWidgetGetControl(gw,CID_Fontname));
+ unichar_t ubuf[50];
+ int i,j;
+ for ( j=0; noticeweights[j]!=NULL; ++j ) {
+ for ( i=0; noticeweights[j][i]!=NULL; ++i ) {
+ if ( uc_strstrmatch(uname,noticeweights[j][i])!=NULL ) {
+ uc_strcpy(ubuf, noticeweights[j]==knownweights ?
+ realweights[i] : noticeweights[j][i]);
+ GGadgetSetTitle(GWidgetGetControl(gw,CID_Weight),ubuf);
+ break;
+ }
+ }
+ if ( noticeweights[j][i]!=NULL )
+ break;
+ }
+ if ( gfi->human_untitled )
+ GGadgetSetTitle(GWidgetGetControl(gw,CID_Human),uname);
+ if ( gfi->family_untitled ) {
+ const unichar_t *ept = uname+u_strlen(uname); unichar_t *temp;
+ for ( i=0; knownweights[i]!=NULL; ++i ) {
+ if (( temp = uc_strstrmatch(uname,knownweights[i]))!=NULL && temp<ept && temp!=uname )
+ ept = temp;
+ }
+ if (( temp = uc_strstrmatch(uname,"ital"))!=NULL && temp<ept && temp!=uname )
+ ept = temp;
+ if (( temp = uc_strstrmatch(uname,"obli"))!=NULL && temp<ept && temp!=uname )
+ ept = temp;
+ if (( temp = uc_strstrmatch(uname,"kurs"))!=NULL && temp<ept && temp!=uname )
+ ept = temp;
+ if (( temp = uc_strstrmatch(uname,"slanted"))!=NULL && temp<ept && temp!=uname )
+ ept = temp;
+ if (( temp = u_strchr(uname,'-'))!=NULL && temp!=uname )
+ ept = temp;
+ temp = u_copyn(uname,ept-uname);
+ GGadgetSetTitle(GWidgetGetControl(gw,CID_Family),temp);
+ }
+ }
+return( true );
+}
+
+static int GFI_FamilyChange(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ gfi->family_untitled = false;
+ }
+return( true );
+}
+
+static int GFI_DefBaseChange(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ GGadgetSetChecked(GWidgetGetControl(gfi->gw,*_GGadgetGetTitle(g)!='\0'?CID_HasDefBase:CID_SameAsFontname),
+ true);
+ }
+return( true );
+}
+
+static int GFI_HumanChange(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ gfi->human_untitled = false;
+ }
+return( true );
+}
+
+static int GFI_VMetricsCheck(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
+ GWindow gw = GGadgetGetWindow(g);
+ const unichar_t *vo = _GGadgetGetTitle(GWidgetGetControl(gw,CID_VOrigin));
+ int checked = GGadgetIsChecked(g);
+ if ( checked && *vo=='\0' ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ char space[10]; unichar_t uspace[10];
+ sprintf( space, "%d", d->sf->ascent );
+ uc_strcpy(uspace,space);
+ GGadgetSetTitle(GWidgetGetControl(gw,CID_VOrigin),uspace);
+ }
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_VOrigin),checked);
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_VOriginLab),checked);
+ GGadgetSetEnabled(GWidgetGetControl(GDrawGetParentWindow(gw),CID_VLineGap),checked);
+ GGadgetSetEnabled(GWidgetGetControl(GDrawGetParentWindow(gw),CID_VLineGapLab),checked);
+ }
+return( true );
+}
+
+static int GFI_EmChanged(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
+ char buf[20]; unichar_t ubuf[20];
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ const unichar_t *ret = _GGadgetGetTitle(g); unichar_t *end;
+ int val = u_strtol(ret,&end,10), ascent, descent;
+ if ( *end )
+return( true );
+ switch ( GGadgetGetCid(g)) {
+ case CID_Em:
+ ascent = rint( ((double) val)*d->sf->ascent/(d->sf->ascent+d->sf->descent) );
+ descent = val - ascent;
+ break;
+ case CID_Ascent:
+ ascent = val;
+ ret = _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Descent));
+ descent = u_strtol(ret,&end,10);
+ if ( *end )
+return( true );
+ break;
+ case CID_Descent:
+ descent = val;
+ ret = _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Ascent));
+ ascent = u_strtol(ret,&end,10);
+ if ( *end )
+return( true );
+ break;
+ }
+ sprintf( buf, "%d", ascent ); if ( ascent==0 ) buf[0]='\0'; uc_strcpy(ubuf,buf);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_Ascent),ubuf);
+ sprintf( buf, "%d", descent ); if ( descent==0 ) buf[0]='\0'; uc_strcpy(ubuf,buf);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_Descent),ubuf);
+ sprintf( buf, "%d", ascent+descent ); if ( ascent+descent==0 ) buf[0]='\0'; uc_strcpy(ubuf,buf);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_Em),ubuf);
+ }
+return( true );
+}
+
+static int GFI_GuessItalic(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ double val = SFGuessItalicAngle(d->sf);
+ char buf[30]; unichar_t ubuf[30];
+ sprintf( buf, "%.1f", val);
+ uc_strcpy(ubuf,buf);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_ItalicAngle),ubuf);
+ }
+return( true );
+}
+
+static void MCD_Close(struct markclassdlg *mcd);
+
+static void GFI_Close(struct gfi_data *d) {
+ FontView *fvs;
+ SplineFont *sf = d->sf;
+
+ if ( d->ccd )
+ CCD_Close(d->ccd);
+ if ( d->smd )
+ SMD_Close(d->smd);
+ if ( d->mcd )
+ MCD_Close(d->mcd );
+
+ PSDictFree(d->private);
+
+ GDrawDestroyWindow(d->gw);
+ if ( d->sf->fontinfo == d )
+ d->sf->fontinfo = NULL;
+ for ( fvs = d->sf->fv; fvs!=NULL; fvs = fvs->nextsame ) {
+ GDrawRequestExpose(sf->fv->v,NULL,false);
+ }
+ d->done = true;
+ /* d will be freed by destroy event */;
+}
+
+static void GFI_CancelClose(struct gfi_data *d) {
+ int isgpos,i,j;
+
+ MacFeatListFree(GGadgetGetUserData((GWidgetGetControl(
+ d->gw,CID_Features))));
+ MarkClassFree(d->mark_class_cnt,d->mark_classes,d->mark_class_names);
+ for ( isgpos=0; isgpos<2; ++isgpos ) {
+ struct lkdata *lk = &d->tables[isgpos];
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].new )
+ SFRemoveLookup(d->sf,lk->all[i].lookup);
+ else for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].new )
+ SFRemoveLookupSubTable(d->sf,lk->all[i].subtables[j].subtable);
+ }
+ free(lk->all[i].subtables);
+ }
+ free(lk->all);
+ }
+ GFI_Close(d);
+}
+
+static GTextInfo *MarkClassesList(SplineFont *sf) {
+ int cnt;
+ GTextInfo *ti;
+
+ if ( sf->mark_class_cnt==0 )
+return( NULL );
+
+ ti = gcalloc(sf->mark_class_cnt+1,sizeof(GTextInfo));
+ for ( cnt=1; cnt<sf->mark_class_cnt; ++cnt ) {
+ ti[cnt-1].text = uc_copy(sf->mark_class_names[cnt]);
+ ti[cnt-1].fg = ti[cnt-1].bg = COLOR_DEFAULT;
+ }
+return( ti );
+}
+
+#define CID_MCD_Name 1001
+#define CID_MCD_Set 1002
+#define CID_MCD_Select 1003
+#define CID_MCD_GlyphList 1004
+
+#define MCD_Width 250
+#define MCD_Height 210
+
+typedef struct markclassdlg {
+ GWindow gw;
+ struct gfi_data *d;
+ GGadget *list;
+ int which;
+} MarkClassDlg;
+
+static void MCD_Close(MarkClassDlg *mcd) {
+ mcd->d->mcd = NULL;
+ GDrawDestroyWindow(mcd->gw);
+ free(mcd);
+}
+
+static void MCD_DoCancel(MarkClassDlg *mcd) {
+ MCD_Close(mcd);
+}
+
+static int MCD_Cancel(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ MarkClassDlg *mcd = GDrawGetUserData(GGadgetGetWindow(g));
+ MCD_DoCancel(mcd);
+ }
+return( true );
+}
+
+static int MCD_InvalidClassList(const char *ret,char **classes, char **names,
+ int nclass, int which) {
+ const char *pt, *end;
+ char *tpt, *tend;
+ int i;
+
+ for ( pt = ret; *pt; pt = end ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ end = strchr(pt,' ');
+ if ( end==NULL ) end = pt+strlen(pt);
+ for ( i=1; (i < nclass) && (classes[i]!=NULL); ++i ) {
+ if ( which==i )
+ continue;
+ for ( tpt=classes[i]; *tpt; tpt = tend ) {
+ while ( *tpt==' ' ) ++tpt;
+ tend = strchr(tpt,' ');
+ if ( tend==NULL ) tend = tpt+strlen(tpt);
+ if ( tend-tpt==end-pt && strncmp(pt,tpt,end-pt)==0 ) {
+ char *dupname = copyn(pt,end-pt);
+ gwwv_post_error(_("Bad Class"),_("No glyphs from another class may appear here, but %.30s appears here and in class %.30s"), dupname, names[i]);
+ free(dupname);
+return( true );
+ }
+ }
+ }
+ }
+return( false );
+}
+
+static int MCD_OK(GGadget *g, GEvent *e) {
+ char *newname;
+ char *glyphs;
+ struct gfi_data *d;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ MarkClassDlg *mcd = GDrawGetUserData(GGadgetGetWindow(g));
+ newname = GGadgetGetTitle8(GWidgetGetControl(mcd->gw,CID_MCD_Name));
+ glyphs = GGadgetGetTitle8(GWidgetGetControl(mcd->gw,CID_MCD_GlyphList));
+ d = mcd->d;
+
+ if ( !CCD_NameListCheck(d->sf,glyphs,true,_("Bad Class")) ||
+ MCD_InvalidClassList(glyphs,d->mark_classes,d->mark_class_names,
+ d->mark_class_cnt,mcd->which )) {
+ free(newname); free(glyphs);
+return( true );
+ }
+
+ if ( mcd->which==-1 ) { /* New */
+
+ if ( d->mark_class_cnt==0 ) {
+ d->mark_class_cnt = 2; /* Class 0 is magic */
+ d->mark_classes = gcalloc(2,sizeof(char *));
+ d->mark_class_names = gcalloc(2,sizeof(unichar_t *));
+ } else {
+ ++d->mark_class_cnt;
+ d->mark_classes = grealloc(d->mark_classes,d->mark_class_cnt*sizeof(char*));
+ d->mark_class_names = grealloc(d->mark_class_names,d->mark_class_cnt*sizeof(unichar_t*));
+ }
+ d->mark_classes[d->mark_class_cnt-1] = copy(glyphs);
+ d->mark_class_names[d->mark_class_cnt-1] = copy(newname);
+ GListAppendLine8(mcd->list,newname,false);
+ } else {
+ free(d->mark_classes[mcd->which]); d->mark_classes[mcd->which] = copy(glyphs);
+ free(d->mark_class_names[mcd->which]); d->mark_class_names[mcd->which] = copy(newname);
+ GListChangeLine8(mcd->list,mcd->which,newname);
+ }
+ MCD_Close(mcd);
+ free(newname); free(glyphs);
+ }
+return( true );
+}
+
+static int MCD_ToSelection(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ MarkClassDlg *mcd = GDrawGetUserData(GGadgetGetWindow(g));
+ const unichar_t *ret = _GGadgetGetTitle(GWidgetGetControl(mcd->gw,CID_MCD_GlyphList));
+ SplineFont *sf = mcd->d->sf;
+ FontView *fv = sf->fv;
+ const unichar_t *end;
+ int pos, found=-1;
+ char *nm;
+
+ GDrawSetVisible(fv->gw,true);
+ GDrawRaise(fv->gw);
+ memset(fv->selected,0,fv->map->enccount);
+ while ( *ret ) {
+ end = u_strchr(ret,' ');
+ if ( end==NULL ) end = ret+u_strlen(ret);
+ nm = cu_copybetween(ret,end);
+ for ( ret = end; isspace(*ret); ++ret);
+ if (( pos = SFFindSlot(sf,fv->map,-1,nm))!=-1 ) {
+ if ( found==-1 ) found = pos;
+ if ( pos!=-1 )
+ fv->selected[pos] = true;
+ }
+ free(nm);
+ }
+
+ if ( found!=-1 )
+ FVScrollToChar(fv,found);
+ GDrawRequestExpose(fv->v,NULL,false);
+ }
+return( true );
+}
+
+static int MCD_FromSelection(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ MarkClassDlg *mcd = GDrawGetUserData(GGadgetGetWindow(g));
+ SplineFont *sf = mcd->d->sf;
+ FontView *fv = sf->fv;
+ unichar_t *vals, *pt;
+ int i, len, max, gid;
+ SplineChar *sc, dummy;
+
+ for ( i=len=max=0; i<fv->map->enccount; ++i ) if ( fv->selected[i]) {
+ gid = fv->map->map[i];
+ if ( gid!=-1 && sf->glyphs[gid]!=NULL )
+ sc = sf->glyphs[gid];
+ else
+ sc = SCBuildDummy(&dummy,sf,fv->map,i);
+ len += strlen(sc->name)+1;
+ if ( fv->selected[i]>max ) max = fv->selected[i];
+ }
+ pt = vals = galloc((len+1)*sizeof(unichar_t));
+ *pt = '\0';
+ /* in a class the order of selection is irrelevant */
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i]) {
+ gid = fv->map->map[i];
+ if ( gid!=-1 && sf->glyphs[gid]!=NULL )
+ sc = sf->glyphs[gid];
+ else
+ sc = SCBuildDummy(&dummy,sf,fv->map,i);
+ uc_strcpy(pt,sc->name);
+ pt += u_strlen(pt);
+ *pt++ = ' ';
+ }
+ if ( pt>vals ) pt[-1]='\0';
+
+ GGadgetSetTitle(GWidgetGetControl(mcd->gw,CID_MCD_GlyphList),vals);
+ free(vals);
+ }
+return( true );
+}
+
+void DropChars2Text(GWindow gw, GGadget *glyphs,GEvent *event) {
+ char *cnames;
+ const unichar_t *old;
+ unichar_t *new;
+ int32 len;
+
+ if ( !GDrawSelectionHasType(gw,sn_drag_and_drop,"STRING"))
+return;
+ cnames = GDrawRequestSelection(gw,sn_drag_and_drop,"STRING",&len);
+ if ( cnames==NULL )
+return;
+
+ old = _GGadgetGetTitle(glyphs);
+ if ( old==NULL || *old=='\0' ) {
+ new = uc_copy(cnames);
+ } else {
+ new = galloc(strlen(cnames)+u_strlen(old)+5);
+ u_strcpy(new,old);
+ if ( new[u_strlen(new)-1]!=' ' )
+ uc_strcat(new," ");
+ uc_strcat(new,cnames);
+ }
+ GGadgetSetTitle(glyphs,new);
+ free( cnames );
+ free( new );
+}
+
+static void MCD_Drop(MarkClassDlg *mcd,GEvent *event) {
+ DropChars2Text(mcd->gw,GWidgetGetControl(mcd->gw,CID_MCD_GlyphList),event);
+}
+
+static int mcd_e_h(GWindow gw, GEvent *event) {
+ MarkClassDlg *mcd = GDrawGetUserData(gw);
+
+ switch ( event->type ) {
+ case et_close:
+ MCD_DoCancel(mcd);
+ break;
+ case et_char:
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("fontinfo.html#MarkClass");
+return( true );
+ }
+return( false );
+ break;
+ case et_drop:
+ MCD_Drop(mcd,event);
+ break;
+ }
+return( true );
+}
+
+static void CreateMarkClassDlg(struct gfi_data *d, GGadget *list, int which) {
+ MarkClassDlg *mcd;
+ GWindow gw;
+ GRect pos;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[10];
+ GTextInfo label[10];
+ int k;
+ unichar_t *freeme = NULL;
+
+ if ( d->mcd!=NULL ) {
+ GDrawSetVisible(d->mcd->gw,true);
+ GDrawRaise(d->mcd->gw);
+return;
+ }
+
+ memset(&wattrs,0,sizeof(wattrs));
+ memset(&gcd,0,sizeof(gcd));
+ memset(&label,0,sizeof(label));
+
+ mcd = gcalloc(1,sizeof(MarkClassDlg));
+ mcd->d = d; mcd->list = list; mcd->which = which;
+
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = false;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Mark Classes");
+ wattrs.is_dlg = false;
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,MCD_Width));
+ pos.height = GDrawPointsToPixels(NULL,MCD_Height);
+ mcd->gw = gw = GDrawCreateTopWindow(NULL,&pos,mcd_e_h,mcd,&wattrs);
+
+ k = 0;
+
+ label[k].text = (unichar_t *) _("Class Name:");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = 10;
+ gcd[k].gd.flags = gg_visible | gg_enabled;
+ gcd[k++].creator = GLabelCreate;
+
+ if ( which!=-1 ) {
+ gcd[k].gd.label = &label[k];
+ label[k].text = (unichar_t *) d->mark_class_names[which];
+ label[k].text_is_1byte = true;
+ }
+ gcd[k].gd.pos.x = 70; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-4;
+ gcd[k].gd.flags = gg_visible | gg_enabled;
+ gcd[k].gd.cid = CID_MCD_Name;
+ gcd[k++].creator = GTextFieldCreate;
+
+ label[k].text = (unichar_t *) _("Set From Font");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+28;
+ gcd[k].gd.popup_msg = (unichar_t *) _("Set this glyph list to be the glyphs selected in the fontview");
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ gcd[k].gd.handle_controlevent = MCD_FromSelection;
+ gcd[k].gd.cid = CID_MCD_Set;
+ gcd[k++].creator = GButtonCreate;
+
+ label[k].text = (unichar_t *) _("Select In Font");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 110; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
+ gcd[k].gd.popup_msg = (unichar_t *) _("Set the fontview's selection to be the glyphs named here");
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ gcd[k].gd.handle_controlevent = MCD_ToSelection;
+ gcd[k].gd.cid = CID_MCD_Select;
+ gcd[k++].creator = GButtonCreate;
+
+ if ( which!=-1 ) {
+ gcd[k].gd.label = &label[k];
+ label[k].text = freeme = uc_copy(d->mark_classes[which]);
+ }
+ gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+30;
+ gcd[k].gd.pos.width = MCD_Width-20; gcd[k].gd.pos.height = 8*13+4;
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_textarea_wrap; /* Just ASCII text for glyph names, no need for xim */
+ gcd[k].gd.cid = CID_MCD_GlyphList;
+ gcd[k++].creator = GTextAreaCreate;
+
+ label[k].text = (unichar_t *) _("_OK");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 30; gcd[k].gd.pos.y = MCD_Height-30-3;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible|gg_enabled | gg_but_default;
+ gcd[k].gd.handle_controlevent = MCD_OK;
+ gcd[k++].creator = GButtonCreate;
+
+ label[k].text = (unichar_t *) _("_Cancel");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = -30+3; gcd[k].gd.pos.y = MCD_Height-30;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible|gg_enabled | gg_but_cancel;
+ gcd[k].gd.handle_controlevent = MCD_Cancel;
+ gcd[k++].creator = GButtonCreate;
+
+ gcd[k].gd.pos.x = 2; gcd[k].gd.pos.y = 2;
+ gcd[k].gd.pos.width = pos.width-4;
+ gcd[k].gd.pos.height = pos.height-4;
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_pos_in_pixels;
+ gcd[k++].creator = GGroupCreate;
+
+ GGadgetsCreate(mcd->gw,gcd);
+ GDrawSetVisible(mcd->gw,true);
+
+ free(freeme);
+}
+
+static int GFI_MarkNew(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ CreateMarkClassDlg(d, GWidgetGetControl(GGadgetGetWindow(g),CID_MarkClasses), -1);
+ }
+return( true );
+}
+
+static int GFI_MarkEdit(GGadget *g, GEvent *e) {
+ int i;
+ GGadget *list;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ list = GWidgetGetControl(GGadgetGetWindow(g),CID_MarkClasses);
+ if ( (i = GGadgetGetFirstListSelectedItem(list))==-1 && i+1 < d->mark_class_cnt )
+return( true );
+ CreateMarkClassDlg(d, list, i+1);
+ }
+return( true );
+}
+
+static int GFI_MarkSelChanged(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ int sel = GGadgetGetFirstListSelectedItem(g);
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_MarkEdit),sel!=-1);
+ } else if ( e->type==et_controlevent && e->u.control.subtype == et_listdoubleclick ) {
+ e->u.control.subtype = et_buttonactivate;
+ GFI_MarkEdit(g,e);
+ }
+return( true );
+}
+
+static char *OtfNameToText(int lang, const char *name) {
+ const char *langname;
+ char *text;
+ int i;
+
+ for ( i=sizeof(mslanguages)/sizeof(mslanguages[0])-1; i>=0 ; --i )
+ if ( mslanguages[i].userdata == (void *) (intpt) lang )
+ break;
+ if ( i==-1 )
+ for ( i=sizeof(mslanguages)/sizeof(mslanguages[0])-1; i>=0 ; --i )
+ if ( ((intpt) mslanguages[i].userdata&0xff) == (lang&0xff) )
+ break;
+ if ( i==-1 )
+ langname = "";
+ else
+ langname = (char*) (mslanguages[i].text);
+
+ text = galloc((strlen(langname)+strlen(name)+4));
+ strcpy(text,name);
+ strcat(text," | ");
+ strcat(text,langname);
+return( text );
+}
+
+static GTextInfo **StyleNames(struct otfname *otfn) {
+ int cnt;
+ struct otfname *on;
+ GTextInfo **tis;
+ char *cname;
+
+ for ( cnt=0, on=otfn; on!=NULL; on=on->next )
+ ++cnt;
+ tis = galloc((cnt+1)*sizeof(GTextInfo *));
+ for ( cnt=0, on=otfn; on!=NULL; on=on->next, ++cnt ) {
+ tis[cnt] = gcalloc(1,sizeof(GTextInfo));
+ tis[cnt]->fg = tis[cnt]->bg = COLOR_DEFAULT;
+ tis[cnt]->userdata = (void *) (intpt) otfn->lang;
+ cname = OtfNameToText(on->lang,on->name);
+ tis[cnt]->text = utf82u_copy(cname);
+ free(cname);
+ }
+ tis[cnt] = gcalloc(1,sizeof(GTextInfo));
+return( tis );
+}
+
+static struct otfname *OtfNameFromStyleNames(GGadget *list) {
+ int32 len; int i;
+ GTextInfo **old = GGadgetGetList(list,&len);
+ struct otfname *head=NULL, *last, *cur;
+ unichar_t *pt, *temp;
+
+ for ( i=0; i<len; ++i ) {
+ cur = chunkalloc(sizeof(struct otfname));
+ cur->lang = (intpt) old[i]->userdata;
+ pt = uc_strstr(old[i]->text," | ");
+ temp = u_copyn(old[i]->text,pt-old[i]->text);
+ cur->name = u2utf8_copy(temp);
+ free(temp);
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ }
+return( head );
+}
+
+static int sn_e_h(GWindow gw, GEvent *event) {
+
+ if ( event->type==et_close ) {
+ int *d = GDrawGetUserData(gw);
+ *d = true;
+ } else if ( event->type == et_char ) {
+return( false );
+ } else if ( event->type==et_controlevent && event->u.control.subtype == et_buttonactivate ) {
+ int *d = GDrawGetUserData(gw);
+ *d = GGadgetGetCid(event->u.control.g)+1;
+ }
+return( true );
+}
+
+static void AskForLangName(GGadget *list,int sel) {
+ int32 len; int i;
+ GTextInfo **old = GGadgetGetList(list,&len);
+ unichar_t *name, *pt;
+ char *cname;
+ int lang_index;
+ GGadgetCreateData gcd[7];
+ GTextInfo label[5];
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ int done = 0;
+ int k;
+ GTextInfo **ti;
+ char *temp;
+
+ for ( i=sizeof(mslanguages)/sizeof(mslanguages[0])-1; i>=0 ; --i )
+ mslanguages[i].fg = mslanguages[i].bg = COLOR_DEFAULT;
+ if ( sel==-1 ) {
+ for ( i=0; i<len; ++i )
+ if ( old[i]->userdata == (void *) 0x409 )
+ break;
+ if ( i==len ) {
+ for ( i=sizeof(mslanguages)/sizeof(mslanguages[0])-1; i>=0 ; --i )
+ if ( mslanguages[i].userdata == (void *) 0x409 )
+ break;
+ lang_index = i;
+ } else {
+ for ( lang_index=sizeof(mslanguages)/sizeof(mslanguages[0])-1; lang_index>=0 ; --lang_index ) {
+ for ( i=0; i<len; ++i )
+ if ( mslanguages[lang_index].userdata == old[i]->userdata )
+ break;
+ if ( i==len )
+ break;
+ }
+ }
+ if ( lang_index < 0 )
+ lang_index = 0;
+ name = uc_copy("");
+ } else {
+ for ( lang_index=sizeof(mslanguages)/sizeof(mslanguages[0])-1; lang_index>=0 ; --lang_index )
+ if ( mslanguages[lang_index].userdata == old[sel]->userdata )
+ break;
+ if ( lang_index < 0 )
+ lang_index = 0;
+ pt = uc_strstr(old[sel]->text," | ");
+ name = u_copyn(old[sel]->text,pt-old[sel]->text);
+ }
+
+ memset(gcd,0,sizeof(gcd));
+ memset(label,0,sizeof(label));
+
+ gcd[0].gd.pos.x = 7; gcd[0].gd.pos.y = 7;
+ gcd[0].gd.flags = gg_visible | gg_enabled | gg_list_alphabetic;
+ gcd[0].gd.cid = CID_Language;
+ gcd[0].gd.u.list = mslanguages;
+ gcd[0].creator = GListButtonCreate;
+ for ( i=0; mslanguages[i].text!=NULL; ++i )
+ mslanguages[i].selected = false;
+ mslanguages[lang_index].selected = true;
+
+ k = 1;
+ label[k].text = (unichar_t *) _("_Name:");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+30;
+ gcd[k].gd.flags = gg_visible | gg_enabled;
+ gcd[k++].creator = GLabelCreate;
+
+ label[k].text = name;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 50; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-4;
+ gcd[k].gd.pos.width = 122;
+ gcd[k].gd.flags = gg_visible | gg_enabled;
+ gcd[k].gd.cid = CID_StyleName;
+ gcd[k++].creator = GTextFieldCreate;
+
+ gcd[k].gd.pos.x = 25-3; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+30;
+ gcd[k].gd.pos.width = -1; gcd[k].gd.pos.height = 0;
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[k].text = (unichar_t *) _("_OK");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.cid = true;
+ gcd[k++].creator = GButtonCreate;
+
+ gcd[k].gd.pos.x = -25; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+3;
+ gcd[k].gd.pos.width = -1; gcd[k].gd.pos.height = 0;
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[k].text = (unichar_t *) _("_Cancel");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.cid = false;
+ gcd[k++].creator = GButtonCreate;
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.is_dlg = true;
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Style Name:");
+ pos.x = pos.y = 0;
+ pos.width =GDrawPointsToPixels(NULL,GGadgetScale(180));
+ pos.height = GDrawPointsToPixels(NULL,2*26+45);
+ gw = GDrawCreateTopWindow(NULL,&pos,sn_e_h,&done,&wattrs);
+
+ GGadgetsCreate(gw,gcd);
+ free(name);
+ ti = GGadgetGetList(gcd[0].ret,&len);
+ for ( i=0; i<len; ++i )
+ if ( ti[i]->userdata == mslanguages[lang_index].userdata ) {
+ GGadgetSelectOneListItem(gcd[0].ret,i);
+ break;
+ }
+ GDrawSetVisible(gw,true);
+
+ while ( !done )
+ GDrawProcessOneEvent(NULL);
+
+ if ( done==2 ) {
+ lang_index = GGadgetGetFirstListSelectedItem(gcd[0].ret);
+ cname = OtfNameToText((intpt) ti[lang_index]->userdata,
+ (temp = GGadgetGetTitle8(GWidgetGetControl(gw,CID_StyleName))));
+ free(temp);
+ if ( sel==-1 )
+ GListAppendLine8(list,cname,false)->userdata =
+ ti[lang_index]->userdata;
+ else
+ GListChangeLine8(list,sel,cname)->userdata =
+ ti[lang_index]->userdata;
+ free(name);
+ }
+
+ GDrawDestroyWindow(gw);
+}
+
+static int GFI_StyleNameNew(GGadget *g, GEvent *e) {
+ GGadget *list;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ list = GWidgetGetControl(GGadgetGetWindow(g),CID_StyleName);
+ AskForLangName(list,-1);
+ }
+return( true );
+}
+
+static int GFI_StyleNameDel(GGadget *g, GEvent *e) {
+ GGadget *list;
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ list = GWidgetGetControl(GGadgetGetWindow(g),CID_StyleName);
+ GListDelSelected(list);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_StyleNameDel),false);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_StyleNameRename),false);
+ }
+return( true );
+}
+
+static int GFI_StyleNameRename(GGadget *g, GEvent *e) {
+ GGadget *list;
+ int sel;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ list = GWidgetGetControl(GGadgetGetWindow(g),CID_StyleName);
+ if ( (sel=GGadgetGetFirstListSelectedItem(list))==-1 )
+return( true );
+ AskForLangName(list,sel);
+ }
+return( true );
+}
+
+static int GFI_StyleNameSelChanged(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ int sel = GGadgetGetFirstListSelectedItem(g);
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_StyleNameDel),sel!=-1);
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_StyleNameRename),sel!=-1);
+ } else if ( e->type==et_controlevent && e->u.control.subtype == et_listdoubleclick ) {
+ e->u.control.subtype = et_buttonactivate;
+ GFI_StyleNameRename(g,e);
+ }
+return( true );
+}
+
+void GListMoveSelected(GGadget *list,int offset) {
+ int32 len; int i,j;
+ GTextInfo **old, **new;
+
+ old = GGadgetGetList(list,&len);
+ new = gcalloc(len+1,sizeof(GTextInfo *));
+ j = (offset<0 ) ? 0 : len-1;
+ for ( i=0; i<len; ++i ) if ( old[i]->selected ) {
+ if ( offset==0x80000000 || offset==0x7fffffff )
+ /* Do Nothing */;
+ else if ( offset<0 ) {
+ if ( (j= i+offset)<0 ) j=0;
+ while ( new[j] ) ++j;
+ } else {
+ if ( (j= i+offset)>=len ) j=len-1;
+ while ( new[j] ) --j;
+ }
+ new[j] = galloc(sizeof(GTextInfo));
+ *new[j] = *old[i];
+ new[j]->text = u_copy(new[j]->text);
+ if ( offset<0 ) ++j; else --j;
+ }
+ for ( i=j=0; i<len; ++i ) if ( !old[i]->selected ) {
+ while ( new[j] ) ++j;
+ new[j] = galloc(sizeof(GTextInfo));
+ *new[j] = *old[i];
+ new[j]->text = u_copy(new[j]->text);
+ ++j;
+ }
+ new[len] = gcalloc(1,sizeof(GTextInfo));
+ GGadgetSetList(list,new,false);
+}
+
+void GListDelSelected(GGadget *list) {
+ int32 len; int i,j;
+ GTextInfo **old, **new;
+
+ old = GGadgetGetList(list,&len);
+ new = gcalloc(len+1,sizeof(GTextInfo *));
+ for ( i=j=0; i<len; ++i ) if ( !old[i]->selected ) {
+ new[j] = galloc(sizeof(GTextInfo));
+ *new[j] = *old[i];
+ new[j]->text = u_copy(new[j]->text);
+ ++j;
+ }
+ new[j] = gcalloc(1,sizeof(GTextInfo));
+ GGadgetSetList(list,new,false);
+}
+
+GTextInfo *GListChangeLine(GGadget *list,int pos, const unichar_t *line) {
+ GTextInfo **old, **new;
+ int32 i,len;
+
+ old = GGadgetGetList(list,&len);
+ new = gcalloc(len+1,sizeof(GTextInfo *));
+ for ( i=0; i<len; ++i ) {
+ new[i] = galloc(sizeof(GTextInfo));
+ *new[i] = *old[i];
+ if ( i!=pos )
+ new[i]->text = u_copy(new[i]->text);
+ else
+ new[i]->text = u_copy(line);
+ }
+ new[i] = gcalloc(1,sizeof(GTextInfo));
+ GGadgetSetList(list,new,false);
+ GGadgetScrollListToPos(list,pos);
+return( new[pos]);
+}
+
+GTextInfo *GListAppendLine(GGadget *list,const unichar_t *line,int select) {
+ GTextInfo **old, **new;
+ int32 i,len;
+
+ old = GGadgetGetList(list,&len);
+ new = gcalloc(len+2,sizeof(GTextInfo *));
+ for ( i=0; i<len; ++i ) {
+ new[i] = galloc(sizeof(GTextInfo));
+ *new[i] = *old[i];
+ new[i]->text = u_copy(new[i]->text);
+ if ( select ) new[i]->selected = false;
+ }
+ new[i] = gcalloc(1,sizeof(GTextInfo));
+ new[i]->fg = new[i]->bg = COLOR_DEFAULT;
+ new[i]->userdata = NULL;
+ new[i]->text = u_copy(line);
+ new[i]->selected = select;
+ new[i+1] = gcalloc(1,sizeof(GTextInfo));
+ GGadgetSetList(list,new,false);
+ GGadgetScrollListToPos(list,i);
+return( new[i]);
+}
+
+GTextInfo *GListChangeLine8(GGadget *list,int pos, const char *line) {
+ GTextInfo **old, **new;
+ int32 i,len;
+
+ old = GGadgetGetList(list,&len);
+ new = gcalloc(len+1,sizeof(GTextInfo *));
+ for ( i=0; i<len; ++i ) {
+ new[i] = galloc(sizeof(GTextInfo));
+ *new[i] = *old[i];
+ if ( i!=pos )
+ new[i]->text = u_copy(new[i]->text);
+ else
+ new[i]->text = utf82u_copy(line);
+ }
+ new[i] = gcalloc(1,sizeof(GTextInfo));
+ GGadgetSetList(list,new,false);
+ GGadgetScrollListToPos(list,pos);
+return( new[pos]);
+}
+
+GTextInfo *GListAppendLine8(GGadget *list,const char *line,int select) {
+ GTextInfo **old, **new;
+ int32 i,len;
+
+ old = GGadgetGetList(list,&len);
+ new = gcalloc(len+2,sizeof(GTextInfo *));
+ for ( i=0; i<len; ++i ) {
+ new[i] = galloc(sizeof(GTextInfo));
+ *new[i] = *old[i];
+ new[i]->text = u_copy(new[i]->text);
+ if ( select ) new[i]->selected = false;
+ }
+ new[i] = gcalloc(1,sizeof(GTextInfo));
+ new[i]->fg = new[i]->bg = COLOR_DEFAULT;
+ new[i]->userdata = NULL;
+ new[i]->text = utf82u_copy(line);
+ new[i]->selected = select;
+ new[i+1] = gcalloc(1,sizeof(GTextInfo));
+ GGadgetSetList(list,new,false);
+ GGadgetScrollListToPos(list,i);
+return( new[i]);
+}
+
+static int GFI_Cancel(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ GFI_CancelClose(d);
+ }
+return( true );
+}
+
+static int AskLoseUndoes() {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buts[3];
+ buts[0] = _("_OK"); buts[1] = _("_Cancel"); buts[2]=NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buts[] = { GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL };
+#endif
+return( gwwv_ask(_("Losing Undoes"),(const char **) buts,0,1,_("Changing the order of the splines in the font will lose all undoes.\nContinue anyway?")) );
+}
+
+static void BadFamily() {
+ gwwv_post_error(_("Bad Family Name"),_("Bad Family Name, must begin with an alphabetic character."));
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+static char *modifierlist[] = { "Ital", "Obli", "Kursive", "Cursive", "Slanted",
+ "Expa", "Cond", NULL };
+static char *modifierlistfull[] = { "Italic", "Oblique", "Kursive", "Cursive", "Slanted",
+ "Expanded", "Condensed", NULL };
+static char **mods[] = { knownweights, modifierlist, NULL };
+static char **fullmods[] = { realweights, modifierlistfull, NULL };
+
+char *_GetModifiers(char *fontname, char *familyname,char *weight) {
+ char *pt, *fpt;
+ int i, j;
+
+ /* URW fontnames don't match the familyname */
+ /* "NimbusSanL-Regu" vs "Nimbus Sans L" (note "San" vs "Sans") */
+ /* so look for a '-' if there is one and use that as the break point... */
+
+ if ( (fpt=strchr(fontname,'-'))!=NULL ) {
+ ++fpt;
+ if ( *fpt=='\0' )
+ fpt = NULL;
+ } else if ( familyname!=NULL ) {
+ for ( pt = fontname, fpt=familyname; *fpt!='\0' && *pt!='\0'; ) {
+ if ( *fpt == *pt ) {
+ ++fpt; ++pt;
+ } else if ( *fpt==' ' )
+ ++fpt;
+ else if ( *pt==' ' )
+ ++pt;
+ else if ( *fpt=='a' || *fpt=='e' || *fpt=='i' || *fpt=='o' || *fpt=='u' )
+ ++fpt; /* allow vowels to be omitted from family when in fontname */
+ else
+ break;
+ }
+ if ( *fpt=='\0' && *pt!='\0' )
+ fpt = pt;
+ else
+ fpt = NULL;
+ }
+
+ if ( fpt == NULL ) {
+ for ( i=0; mods[i]!=NULL; ++i ) for ( j=0; mods[i][j]!=NULL; ++j ) {
+ pt = strstr(fontname,mods[i][j]);
+ if ( pt!=NULL && (fpt==NULL || pt<fpt))
+ fpt = pt;
+ }
+ }
+ if ( fpt!=NULL ) {
+ for ( i=0; mods[i]!=NULL; ++i ) for ( j=0; mods[i][j]!=NULL; ++j ) {
+ if ( strcmp(fpt,mods[i][j])==0 )
+return( fullmods[i][j]);
+ }
+ if ( strcmp(fpt,"BoldItal")==0 )
+return( "BoldItalic" );
+ else if ( strcmp(fpt,"BoldObli")==0 )
+return( "BoldOblique" );
+
+return( fpt );
+ }
+
+return( weight==NULL || *weight=='\0' ? "Regular": weight );
+}
+
+char *SFGetModifiers(SplineFont *sf) {
+return( _GetModifiers(sf->fontname,sf->familyname,sf->weight));
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static const unichar_t *_uGetModifiers(const unichar_t *fontname, const unichar_t *familyname,
+ const unichar_t *weight) {
+ const unichar_t *pt, *fpt;
+ static unichar_t regular[] = { 'R','e','g','u','l','a','r', 0 };
+ static unichar_t space[20];
+ int i,j;
+
+ /* URW fontnames don't match the familyname */
+ /* "NimbusSanL-Regu" vs "Nimbus Sans L" (note "San" vs "Sans") */
+ /* so look for a '-' if there is one and use that as the break point... */
+
+ if ( (fpt=u_strchr(fontname,'-'))!=NULL ) {
+ ++fpt;
+ if ( *fpt=='\0' )
+ fpt = NULL;
+ } else if ( familyname!=NULL ) {
+ for ( pt = fontname, fpt=familyname; *fpt!='\0' && *pt!='\0'; ) {
+ if ( *fpt == *pt ) {
+ ++fpt; ++pt;
+ } else if ( *fpt==' ' )
+ ++fpt;
+ else if ( *pt==' ' )
+ ++pt;
+ else if ( *fpt=='a' || *fpt=='e' || *fpt=='i' || *fpt=='o' || *fpt=='u' )
+ ++fpt; /* allow vowels to be omitted from family when in fontname */
+ else
+ break;
+ }
+ if ( *fpt=='\0' && *pt!='\0' )
+ fpt = pt;
+ else
+ fpt = NULL;
+ }
+
+ if ( fpt==NULL ) {
+ for ( i=0; mods[i]!=NULL; ++i ) for ( j=0; mods[i][j]!=NULL; ++j ) {
+ pt = uc_strstr(fontname,mods[i][j]);
+ if ( pt!=NULL && (fpt==NULL || pt<fpt))
+ fpt = pt;
+ }
+ }
+
+ if ( fpt!=NULL ) {
+ for ( i=0; mods[i]!=NULL; ++i ) for ( j=0; mods[i][j]!=NULL; ++j ) {
+ if ( uc_strcmp(fpt,mods[i][j])==0 ) {
+ uc_strcpy(space,fullmods[i][j]);
+return( space );
+ }
+ }
+ if ( uc_strcmp(fpt,"BoldItal")==0 ) {
+ uc_strcpy(space,"BoldItalic");
+return( space );
+ } else if ( uc_strcmp(fpt,"BoldObli")==0 ) {
+ uc_strcpy(space,"BoldOblique");
+return( space );
+ }
+return( fpt );
+ }
+
+return( weight==NULL || *weight=='\0' ? regular: weight );
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+void SFSetFontName(SplineFont *sf, char *family, char *mods,char *full) {
+ char *n;
+ char *pt, *tpt;
+
+ n = galloc(strlen(family)+strlen(mods)+2);
+ strcpy(n,family); strcat(n," "); strcat(n,mods);
+ if ( full==NULL || *full == '\0' )
+ full = copy(n);
+ for ( pt=tpt=n; *pt; ) {
+ if ( !Isspace(*pt))
+ *tpt++ = *pt++;
+ else
+ ++pt;
+ }
+ *tpt = '\0';
+#if 0
+ for ( pt=tpt=family; *pt; ) {
+ if ( !Isspace(*pt))
+ *tpt++ = *pt++;
+ else
+ ++pt;
+ }
+ *tpt = '\0';
+#endif
+
+ free(sf->fullname); sf->fullname = copy(full);
+
+ /* In the URW world fontnames aren't just a simple concatenation of */
+ /* family name and modifiers, so neither the family name nor the modifiers */
+ /* changed, then don't change the font name */
+ if ( strcmp(family,sf->familyname)==0 && strcmp(n,sf->fontname)==0 )
+ /* Don't change the fontname */;
+ /* or anything else */
+ else {
+ free(sf->fontname); sf->fontname = n;
+ free(sf->familyname); sf->familyname = copy(family);
+ free(sf->weight); sf->weight = NULL;
+ if ( strstrmatch(mods,"extralight")!=NULL || strstrmatch(mods,"extra-light")!=NULL )
+ sf->weight = copy("ExtraLight");
+ else if ( strstrmatch(mods,"demilight")!=NULL || strstrmatch(mods,"demi-light")!=NULL )
+ sf->weight = copy("DemiLight");
+ else if ( strstrmatch(mods,"demibold")!=NULL || strstrmatch(mods,"demi-bold")!=NULL )
+ sf->weight = copy("DemiBold");
+ else if ( strstrmatch(mods,"semibold")!=NULL || strstrmatch(mods,"semi-bold")!=NULL )
+ sf->weight = copy("SemiBold");
+ else if ( strstrmatch(mods,"demiblack")!=NULL || strstrmatch(mods,"demi-black")!=NULL )
+ sf->weight = copy("DemiBlack");
+ else if ( strstrmatch(mods,"extrabold")!=NULL || strstrmatch(mods,"extra-bold")!=NULL )
+ sf->weight = copy("ExtraBold");
+ else if ( strstrmatch(mods,"extrablack")!=NULL || strstrmatch(mods,"extra-black")!=NULL )
+ sf->weight = copy("ExtraBlack");
+ else if ( strstrmatch(mods,"book")!=NULL )
+ sf->weight = copy("Book");
+ else if ( strstrmatch(mods,"regular")!=NULL )
+ sf->weight = copy("Regular");
+ else if ( strstrmatch(mods,"roman")!=NULL )
+ sf->weight = copy("Roman");
+ else if ( strstrmatch(mods,"normal")!=NULL )
+ sf->weight = copy("Normal");
+ else if ( strstrmatch(mods,"demi")!=NULL )
+ sf->weight = copy("Demi");
+ else if ( strstrmatch(mods,"medium")!=NULL )
+ sf->weight = copy("Medium");
+ else if ( strstrmatch(mods,"bold")!=NULL )
+ sf->weight = copy("Bold");
+ else if ( strstrmatch(mods,"heavy")!=NULL )
+ sf->weight = copy("Heavy");
+ else if ( strstrmatch(mods,"black")!=NULL )
+ sf->weight = copy("Black");
+ else if ( strstrmatch(mods,"Nord")!=NULL )
+ sf->weight = copy("Nord");
+/* Sigh. URW uses 4 letter abreviations... */
+ else if ( strstrmatch(mods,"Regu")!=NULL )
+ sf->weight = copy("Regular");
+ else if ( strstrmatch(mods,"Medi")!=NULL )
+ sf->weight = copy("Medium");
+ else if ( strstrmatch(mods,"blac")!=NULL )
+ sf->weight = copy("Black");
+ else
+ sf->weight = copy("Medium");
+ }
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( sf->fv!=NULL && sf->fv->gw!=NULL ) {
+ unichar_t *temp;
+ int i;
+ GDrawSetWindowTitles(sf->fv->gw,temp = uc_copy(sf->fontname),NULL);
+ free(temp);
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL && sf->glyphs[i]->views!=NULL ) {
+ char buffer[300]; unichar_t ubuf[300]; CharView *cv;
+ sprintf( buffer, "%.90s from %.90s", sf->glyphs[i]->name, sf->fontname );
+ uc_strcpy(ubuf,buffer);
+ for ( cv = sf->glyphs[i]->views; cv!=NULL; cv=cv->next )
+ GDrawSetWindowTitles(cv->gw,ubuf,NULL);
+ }
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+}
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+
+static int SetFontName(GWindow gw, SplineFont *sf) {
+ const unichar_t *ufamily = _GGadgetGetTitle(GWidgetGetControl(gw,CID_Family));
+ const unichar_t *ufont = _GGadgetGetTitle(GWidgetGetControl(gw,CID_Fontname));
+ const unichar_t *uweight = _GGadgetGetTitle(GWidgetGetControl(gw,CID_Weight));
+ const unichar_t *uhum = _GGadgetGetTitle(GWidgetGetControl(gw,CID_Human));
+ int diff = uc_strcmp(ufont,sf->fontname)!=0;
+
+ free(sf->familyname);
+ free(sf->fontname);
+ free(sf->weight);
+ free(sf->fullname);
+ sf->familyname = cu_copy(ufamily);
+ sf->fontname = cu_copy(ufont);
+ sf->weight = cu_copy(uweight);
+ sf->fullname = cu_copy(uhum);
+return( diff );
+}
+
+static int CheckNames(struct gfi_data *d) {
+ const unichar_t *ufamily = _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Family));
+ const unichar_t *ufont = _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Fontname));
+ unichar_t *end; const unichar_t *pt;
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buts[3];
+ buts[0] = _("_OK"); buts[1] = _("_Cancel"); buts[2]=NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buts[] = { GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL };
+#endif
+
+ if ( u_strlen(ufont)>63 ) {
+ gwwv_post_error(_("Bad Font Name"),_("A Postscript name should be ASCII\nand must not contain (){}[]<>%%/ or space\nand must be shorter than 63 characters"));
+return( false );
+ }
+
+ if ( *ufamily=='\0' ) {
+ gwwv_post_error(_("A Font Family name is required"),_("A Font Family name is required"));
+return( false );
+ }
+ /* A postscript name cannot be a number. There are two ways it can be a */
+ /* number, it can be a real (which we can check for with strtod) or */
+ /* it can be a "radix number" which is <intval>'#'<intval>. I'll only */
+ /* do a cursory test for that */
+ u_strtod(ufamily,&end);
+ if ( *end=='\0' || (isdigit(ufamily[0]) && u_strchr(ufamily,'#')!=NULL) ) {
+ gwwv_post_error(_("Bad Font Family Name"),_("A Postscript name may not be a number"));
+return( false );
+ }
+ if ( u_strlen(ufamily)>31 ) {
+ if ( gwwv_ask(_("Bad Font Family Name"),(const char **) buts,0,1,_("Some versions of Windows will refuse to install postscript fonts if the familyname is longer than 31 characters. Do you want to continue anyway?"))==1 )
+return( false );
+ } else {
+ if ( u_strlen(ufont)>31 ) {
+ if ( gwwv_ask(_("Bad Font Name"),(const char **) buts,0,1,_("Some versions of Windows will refuse to install postscript fonts if the fontname is longer than 31 characters. Do you want to continue anyway?"))==1 )
+return( false );
+ } else if ( u_strlen(ufont)>29 ) {
+ if ( gwwv_ask(_("Bad Font Name"),(const char **) buts,0,1,_("Adobe's fontname spec (5088.FontNames.pdf) says that fontnames must not be longer than 29 characters. Do you want to continue anyway?"))==1 )
+return( false );
+ }
+ }
+ while ( *ufamily ) {
+ if ( *ufamily<' ' || *ufamily>=0x7f ) {
+ gwwv_post_error(_("Bad Font Family Name"),_("A Postscript name should be ASCII\nand must not contain (){}[]<>%%/ or space"));
+return( false );
+ }
+ ++ufamily;
+ }
+
+ u_strtod(ufont,&end);
+ if ( (*end=='\0' || (isdigit(ufont[0]) && u_strchr(ufont,'#')!=NULL)) &&
+ *ufont!='\0' ) {
+ gwwv_post_error(_("Bad Font Name"),_("A Postscript name may not be a number"));
+return( false );
+ }
+ for ( pt=ufont; *pt; ++pt ) {
+ if ( *pt<=' ' || *pt>=0x7f ||
+ *pt=='(' || *pt=='[' || *pt=='{' || *pt=='<' ||
+ *pt==')' || *pt==']' || *pt=='}' || *pt=='>' ||
+ *pt=='%' || *pt=='/' ) {
+ gwwv_post_error(_("Bad Font Name"),_("A Postscript name should be ASCII\nand must not contain (){}[]<>%%/ or space"));
+return( false );
+ }
+ }
+return( true );
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+void TTF_PSDupsDefault(SplineFont *sf) {
+ struct ttflangname *english;
+ char versionbuf[40];
+
+ /* Ok, if we've just loaded a ttf file then we've got a bunch of langnames*/
+ /* we copied some of them (copyright, family, fullname, etc) into equiv */
+ /* postscript entries in the sf. If we then use FontInfo and change the */
+ /* obvious postscript entries we are left with the old ttf entries. If */
+ /* we generate a ttf file and then load it the old values pop up. */
+ /* Solution: Anything we can generate by default should be set to NULL */
+ for ( english=sf->names; english!=NULL && english->lang!=0x409; english=english->next );
+ if ( english==NULL )
+return;
+ if ( english->names[ttf_family]!=NULL &&
+ strcmp(english->names[ttf_family],sf->familyname)==0 ) {
+ free(english->names[ttf_family]);
+ english->names[ttf_family]=NULL;
+ }
+ if ( english->names[ttf_copyright]!=NULL &&
+ strcmp(english->names[ttf_copyright],sf->copyright)==0 ) {
+ free(english->names[ttf_copyright]);
+ english->names[ttf_copyright]=NULL;
+ }
+ if ( english->names[ttf_fullname]!=NULL &&
+ strcmp(english->names[ttf_fullname],sf->fullname)==0 ) {
+ free(english->names[ttf_fullname]);
+ english->names[ttf_fullname]=NULL;
+ }
+ if ( sf->subfontcnt!=0 || sf->version!=NULL ) {
+ if ( sf->subfontcnt!=0 )
+ sprintf( versionbuf, "Version %f", sf->cidversion );
+ else
+ sprintf(versionbuf,"Version %.20s ", sf->version);
+ if ( english->names[ttf_version]!=NULL &&
+ strcmp(english->names[ttf_version],versionbuf)==0 ) {
+ free(english->names[ttf_version]);
+ english->names[ttf_version]=NULL;
+ }
+ }
+ if ( english->names[ttf_subfamily]!=NULL &&
+ strcmp(english->names[ttf_subfamily],SFGetModifiers(sf))==0 ) {
+ free(english->names[ttf_subfamily]);
+ english->names[ttf_subfamily]=NULL;
+ }
+
+ /* User should not be allowed any access to this one, not ever */
+ free(english->names[ttf_postscriptname]);
+ english->names[ttf_postscriptname]=NULL;
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static int ttfspecials[] = { ttf_copyright, ttf_family, ttf_fullname,
+ ttf_subfamily, ttf_version, -1 };
+
+static char *tn_recalculatedef(struct gfi_data *d,int cur_id) {
+ char versionbuf[40], *v;
+
+ switch ( cur_id ) {
+ case ttf_copyright:
+return( GGadgetGetTitle8(GWidgetGetControl(d->gw,CID_Notice)));
+ case ttf_family:
+return( GGadgetGetTitle8(GWidgetGetControl(d->gw,CID_Family)));
+ case ttf_fullname:
+return( GGadgetGetTitle8(GWidgetGetControl(d->gw,CID_Human)));
+ case ttf_subfamily:
+return( u2utf8_copy(_uGetModifiers(
+ _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Fontname)),
+ _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Family)),
+ _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Weight)))));
+ case ttf_version:
+ sprintf(versionbuf,_("Version %.20s"),
+ v=GGadgetGetTitle8(GWidgetGetControl(d->gw,CID_Version)));
+ free(v);
+return( copy(versionbuf));
+ default:
+return( NULL );
+ }
+}
+
+static char *TN_DefaultName(GGadget *g, int r, int c) {
+ struct gfi_data *d = GGadgetGetUserData(g);
+ int rows;
+ struct matrix_data *strings = GMatrixEditGet(g, &rows);
+
+ if ( strings==NULL || !strings[3*r+2].user_bits )
+return( NULL );
+
+return( tn_recalculatedef(d,strings[3*r+1].u.md_ival ));
+}
+
+static const char *langname(int lang,char *buffer) {
+ int i;
+ for ( i=0; mslanguages[i].text!=NULL; ++i )
+ if ( mslanguages[i].userdata == (void *) (intpt) lang )
+return( (char *) mslanguages[i].text );
+
+ sprintf( buffer, "%04X", lang );
+return( buffer );
+}
+
+static int strid_sorter(const void *pt1, const void *pt2) {
+ const struct matrix_data *n1 = pt1, *n2 = pt2;
+ char buf1[20], buf2[20];
+ const char *l1, *l2;
+
+ if ( n1[1].u.md_ival!=n2[1].u.md_ival )
+return( n1[1].u.md_ival - n2[1].u.md_ival );
+
+ l1 = langname(n1[0].u.md_ival,buf1);
+ l2 = langname(n2[0].u.md_ival,buf2);
+return( strcoll(l1,l2));
+}
+
+static int lang_sorter(const void *pt1, const void *pt2) {
+ const struct matrix_data *n1 = pt1, *n2 = pt2;
+ char buf1[20], buf2[20];
+ const char *l1, *l2;
+
+ if ( n1[0].u.md_ival==n2[0].u.md_ival )
+return( n1[1].u.md_ival - n2[1].u.md_ival );
+
+ l1 = langname(n1[0].u.md_ival,buf1);
+ l2 = langname(n2[0].u.md_ival,buf2);
+return( strcoll(l1,l2));
+}
+
+static int ms_thislocale = 0;
+static int specialvals(const struct matrix_data *n) {
+ if ( n[0].u.md_ival == ms_thislocale )
+return( -10000000 );
+ else if ( (n[0].u.md_ival&0x3ff) == (ms_thislocale&0x3ff) )
+return( -10000000 + (n[0].u.md_ival&~0x3ff) );
+ if ( n[0].u.md_ival == 0x409 ) /* English */
+return( -1000000 );
+ else if ( (n[0].u.md_ival&0x3ff) == 9 )
+return( -1000000 + (n[0].u.md_ival&~0x3ff) );
+
+return( 1 );
+}
+
+static int speciallang_sorter(const void *pt1, const void *pt2) {
+ const struct matrix_data *n1 = pt1, *n2 = pt2;
+ char buf1[20], buf2[20];
+ const char *l1, *l2;
+ int pos1=1, pos2=1;
+
+ /* sort so that entries for the current language are first, then English */
+ /* then alphabetical order */
+ if ( n1[0].u.md_ival==n2[0].u.md_ival )
+return( n1[1].u.md_ival - n2[1].u.md_ival );
+
+ pos1 = specialvals(n1); pos2 = specialvals(n2);
+ if ( pos1<0 || pos2<0 )
+return( pos1-pos2 );
+ l1 = langname(n1[0].u.md_ival,buf1);
+ l2 = langname(n2[0].u.md_ival,buf2);
+return( strcoll(l1,l2));
+}
+
+static void TTFNames_Resort(struct gfi_data *d) {
+ int(*compar)(const void *, const void *);
+ GGadget *edit = GWidgetGetControl(d->gw,CID_TNames);
+ int rows;
+ struct matrix_data *strings = GMatrixEditGet(edit, &rows);
+
+ if ( strings==NULL )
+return;
+
+ if ( GGadgetIsChecked(GWidgetGetControl(d->gw,CID_TNLangSort)) )
+ compar = lang_sorter;
+ else if ( GGadgetIsChecked(GWidgetGetControl(d->gw,CID_TNStringSort)) )
+ compar = strid_sorter;
+ else
+ compar = speciallang_sorter;
+ ms_thislocale = d->langlocalecode;
+ qsort(strings,rows,3*sizeof(struct matrix_data),compar);
+}
+
+static void DefaultLanguage(struct gfi_data *d) {
+ const char *lang=NULL;
+ int i, langlen;
+ static char *envs[] = { "LC_ALL", "LC_MESSAGES", "LANG", NULL };
+ char langcountry[8], language[4];
+ int langcode, langlocalecode;
+
+ for ( i=0; envs[i]!=NULL; ++i ) {
+ lang = getenv(envs[i]);
+ if ( lang!=NULL ) {
+ langlen = strlen(lang);
+ if (( langlen>5 && lang[5]=='.' && lang[2]=='_' ) ||
+ (langlen==5 && lang[2]=='_' ) ||
+ (langlen==2) ||
+ (langlen==3)) /* Some obscure languages have a 3 letter code */
+ /* I understand this language */
+ break;
+ }
+ }
+ if ( lang==NULL )
+ lang = "en_US";
+ strncpy(langcountry,lang,5); langcountry[5] = '\0';
+ strncpy(language,lang,3); language[3] = '\0';
+ if ( language[2]=='_' ) language[2] = '\0';
+ langlen = strlen(language);
+
+ langcode = langlocalecode = -1;
+ for ( i=0; ms_2_locals[i].loc_name!=NULL; ++i ) {
+ if ( strmatch(langcountry,ms_2_locals[i].loc_name)==0 ) {
+ langlocalecode = ms_2_locals[i].local_id;
+ langcode = langlocalecode&0x3ff;
+ break;
+ } else if ( strncmp(language,ms_2_locals[i].loc_name,langlen)==0 )
+ langcode = ms_2_locals[i].local_id&0x3ff;
+ }
+ if ( langcode==-1 ) /* Default to English */
+ langcode = 0x9;
+ d->langlocalecode = langlocalecode==-1 ? (langcode|0x400) : langlocalecode;
+}
+
+static int GFI_Char(struct gfi_data *d,GEvent *event) {
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("fontinfo.html");
+return( true );
+ } else if ( event->u.chr.keysym=='s' &&
+ (event->u.chr.state&ksm_control) &&
+ (event->u.chr.state&ksm_meta) ) {
+ MenuSaveAll(NULL,NULL,NULL);
+return( true );
+ } else if ( event->u.chr.keysym=='q' && (event->u.chr.state&ksm_control)) {
+ if ( event->u.chr.state&ksm_shift ) {
+ GFI_CancelClose(d);
+ } else
+ MenuExit(NULL,NULL,NULL);
+return( true );
+ }
+return( false );
+}
+
+static int CheckActiveStyleTranslation(struct gfi_data *d,
+ struct matrix_data *strings,int r, int rows) {
+ int i,j, eng_pos, other_pos;
+ char *english, *new=NULL, *temp, *pt;
+ int other_lang = strings[3*r].u.md_ival;
+ int changed = false;
+
+ for ( i=rows-1; i>=0 ; --i )
+ if ( strings[3*i+1].u.md_ival==ttf_subfamily &&
+ strings[3*i].u.md_ival == 0x409 )
+ break;
+ if ( i<0 || (english = strings[3*i+2].u.md_str)==NULL )
+ new = tn_recalculatedef(d,ttf_subfamily);
+ else
+ new = copy(english);
+ for ( i=0; stylelist[i]!=NULL; ++i ) {
+ eng_pos = other_pos = -1;
+ for ( j=0; stylelist[i][j].str!=NULL; ++j ) {
+ if ( stylelist[i][j].lang == other_lang ) {
+ other_pos = j;
+ break;
+ }
+ }
+ if ( other_pos==-1 )
+ continue;
+ for ( j=0; stylelist[i][j].str!=NULL; ++j ) {
+ if ( stylelist[i][j].lang == 0x409 &&
+ (pt = strstrmatch(new,stylelist[i][j].str))!=NULL ) {
+ if ( pt==new && strlen(stylelist[i][j].str)==strlen(new) ) {
+ free(new);
+ free(strings[3*r+2].u.md_str);
+ if ( other_lang==0x415 ) {
+ /* polish needs a word before the translation */
+ strings[3*r+2].u.md_str = galloc(strlen("odmiana ")+strlen(stylelist[i][other_pos].str)+1);
+ strcpy(strings[3*r+2].u.md_str,"odmiana ");
+ strcat(strings[3*r+2].u.md_str,stylelist[i][other_pos].str);
+ } else
+ strings[3*r+2].u.md_str = copy(stylelist[i][other_pos].str);
+return( true );
+ }
+ temp = galloc((strlen(new)
+ + strlen(stylelist[i][other_pos].str)
+ - strlen(stylelist[i][j].str)
+ +1));
+ strncpy(temp,new,pt-new);
+ strcpy(temp+(pt-new),stylelist[i][other_pos].str);
+ strcat(temp+(pt-new),pt+strlen(stylelist[i][j].str));
+ free(new);
+ new = temp;
+ changed = true;
+ continue;
+ }
+ }
+ }
+ if ( changed ) {
+ free(strings[3*r+2].u.md_str);
+ if ( other_lang==0x415 ) {
+ /* polish needs a word before the translation */
+ strings[3*r+2].u.md_str = galloc(strlen("odmiana ")+strlen(new)+1);
+ strcpy(strings[3*r+2].u.md_str,"odmiana ");
+ strcat(strings[3*r+2].u.md_str,new);
+ free(new);
+ } else
+ strings[3*r+2].u.md_str = new;
+ } else
+ free(new);
+return( changed );
+}
+
+#define MID_ToggleBase 1
+#define MID_MultiEdit 2
+#define MID_Delete 3
+
+static void TN_StrPopupDispatch(GWindow gw, GMenuItem *mi, GEvent *e) {
+ struct gfi_data *d = GDrawGetUserData(GDrawGetParentWindow(gw));
+ GGadget *g = GWidgetGetControl(d->gw,CID_TNames);
+
+ switch ( mi->mid ) {
+ case MID_ToggleBase: {
+ int rows;
+ struct matrix_data *strings = GMatrixEditGet(g, &rows);
+ strings[3*d->tn_active+2].frozen = !strings[3*d->tn_active+2].frozen;
+ if ( strings[3*d->tn_active+2].frozen ) {
+ free( strings[3*d->tn_active+2].u.md_str );
+ strings[3*d->tn_active+2].u.md_str = NULL;
+ } else {
+ strings[3*d->tn_active+2].u.md_str = tn_recalculatedef(d,strings[3*d->tn_active+1].u.md_ival);
+ }
+ GGadgetRedraw(g);
+ } break;
+ case MID_MultiEdit:
+ GMatrixEditStringDlg(g,d->tn_active,2);
+ break;
+ case MID_Delete:
+ GMatrixEditDeleteRow(g,d->tn_active);
+ break;
+ }
+}
+
+static int menusort(const void *m1, const void *m2) {
+ const GMenuItem *mi1 = m1, *mi2 = m2;
+
+ /* Should do a strcoll here, but I never wrote one */
+ if ( mi1->ti.text_is_1byte && mi2->ti.text_is_1byte )
+return( strcoll( (char *) (mi1->ti.text), (char *) (mi2->ti.text)) );
+ else
+return( u_strcmp(mi1->ti.text,mi2->ti.text));
+}
+
+static void TN_StrIDEnable(GGadget *g,GMenuItem *mi, int r, int c) {
+ int rows, i, j;
+ struct matrix_data *strings = GMatrixEditGet(g, &rows);
+
+ for ( i=0; mi[i].ti.text!=NULL; ++i ) {
+ int strid = (intpt) mi[i].ti.userdata;
+ for ( j=0; j<rows; ++j ) if ( j!=r )
+ if ( strings[3*j].u.md_ival == strings[3*r].u.md_ival &&
+ strings[3*j+1].u.md_ival == strid ) {
+ mi[i].ti.disabled = true;
+ break;
+ }
+ }
+ qsort(mi,i,sizeof(mi[0]),menusort);
+}
+
+static void TN_LangEnable(GGadget *g,GMenuItem *mi, int r, int c) {
+ int i;
+
+ for ( i=0; mi[i].ti.text!=NULL; ++i )
+ qsort(mi,i,sizeof(mi[0]),menusort);
+}
+
+static void TN_NewName(GGadget *g,int row) {
+ int rows;
+ struct matrix_data *strings = GMatrixEditGet(g, &rows);
+
+ strings[3*row+1].u.md_ival = ttf_subfamily;
+}
+
+static void TN_FinishEdit(GGadget *g,int row,int col,int wasnew) {
+ int i,rows;
+ struct matrix_data *strings = GMatrixEditGet(g, &rows);
+ uint8 found[ttf_namemax];
+ struct gfi_data *d = (struct gfi_data *) GGadgetGetUserData(g);
+ int ret = false;
+
+ if ( col==2 ) {
+ if ( strings[3*row+2].u.md_str==NULL || *strings[3*row+2].u.md_str=='\0' ) {
+ GMatrixEditDeleteRow(g,row);
+ ret = true;
+ }
+ } else {
+ if ( col==0 ) {
+ memset(found,0,sizeof(found));
+ found[ttf_idontknow] = true; /* reserved name id */
+ for ( i=0; i<rows; ++i ) if ( i!=row ) {
+ if ( strings[3*i].u.md_ival == strings[3*row].u.md_ival ) /* Same language */
+ found[strings[3*i+1].u.md_ival] = true;
+ }
+ if ( found[ strings[3*row+1].u.md_ival ] ) {
+ /* This language already has an entry for this strid */
+ /* pick another */
+ if ( !found[ttf_subfamily] ) {
+ strings[3*row+1].u.md_ival = ttf_subfamily;
+ ret = true;
+ } else {
+ for ( i=0; i<ttf_namemax; ++i )
+ if ( !found[i] ) {
+ strings[3*row+1].u.md_ival = i;
+ ret = true;
+ break;
+ }
+ }
+ }
+ }
+ if ( (strings[3*row+2].u.md_str==NULL || *strings[3*row+2].u.md_str=='\0') ) {
+ for ( i=0; i<rows; ++i ) if ( i!=row ) {
+ if ( strings[3*row+1].u.md_ival == strings[3*i+1].u.md_ival &&
+ (strings[3*row].u.md_ival&0xff) == (strings[3*i].u.md_ival&0xff)) {
+ /* Same string, same language, different locale */
+ /* first guess is the same as the other string. */
+ if ( strings[3*i+2].u.md_str==NULL )
+ strings[3*row+2].u.md_str = tn_recalculatedef(d,strings[3*row+1].u.md_ival );
+ else
+ strings[3*row+2].u.md_str = copy(strings[3*i+2].u.md_str);
+ ret = true;
+ break;
+ }
+ }
+ /* If we didn't find anything above, and if we've got a style */
+ /* (subfamily) see if we can guess a translation from the english */
+ if ( i==rows && strings[3*row+1].u.md_ival == ttf_subfamily )
+ ret |= CheckActiveStyleTranslation(d,strings,row,rows);
+ }
+ }
+ if ( ret )
+ GGadgetRedraw(g);
+}
+
+static int TN_CanDelete(GGadget *g,int row) {
+ int rows;
+ struct matrix_data *strings = GMatrixEditGet(g, &rows);
+ if ( strings==NULL )
+return( false );
+
+return( !strings[3*row+2].user_bits );
+}
+
+static void TN_PopupMenu(GGadget *g,GEvent *event,int r,int c) {
+ struct gfi_data *d = (struct gfi_data *) GGadgetGetUserData(g);
+ int rows;
+ struct matrix_data *strings = GMatrixEditGet(g, &rows);
+ GMenuItem mi[5];
+ int i;
+
+ if ( strings==NULL )
+return;
+
+ d->tn_active = r;
+
+ memset(mi,'\0',sizeof(mi));
+ for ( i=0; i<3; ++i ) {
+ mi[i].ti.fg = COLOR_DEFAULT;
+ mi[i].ti.bg = COLOR_DEFAULT;
+ mi[i].mid = i+1;
+ mi[i].invoke = TN_StrPopupDispatch;
+ mi[i].ti.text_is_1byte = true;
+ }
+ mi[MID_Delete-1].ti.disabled = strings[3*r+2].user_bits;
+ mi[MID_ToggleBase-1].ti.disabled = !strings[3*r+2].user_bits;
+ if ( strings[3*r+2].frozen ) {
+ mi[MID_MultiEdit-1].ti.disabled = true;
+ mi[MID_ToggleBase-1].ti.text = (unichar_t *) _("Detach from PostScript Names");
+ } else {
+ char *temp;
+ mi[MID_ToggleBase-1].ti.text = (unichar_t *) _("Same as PostScript Names");
+ temp = tn_recalculatedef(d,strings[3*r+1].u.md_ival);
+ mi[MID_ToggleBase-1].ti.disabled = (temp==NULL);
+ free(temp);
+ }
+ if ( c!=2 )
+ mi[MID_MultiEdit-1].ti.disabled = true;
+ mi[MID_MultiEdit-1].ti.text = (unichar_t *) _("Multi-line edit");
+ mi[MID_Delete-1].ti.text = (unichar_t *) _("Delete");
+ GMenuCreatePopupMenu(event->w,event, mi);
+}
+
+static int TN_PassChar(GGadget *g,GEvent *e) {
+return( GFI_Char(GGadgetGetUserData(g),e));
+}
+
+static char *TN_BigEditTitle(GGadget *g,int r, int c) {
+ char buf[100], buf2[20];
+ const char *lang;
+ int k;
+ int rows;
+ struct matrix_data *strings = GMatrixEditGet(g, &rows);
+
+ lang = langname(strings[3*r].u.md_ival,buf2);
+ for ( k=0; ttfnameids[k].text!=NULL && ttfnameids[k].userdata!=(void *) (intpt) strings[3*r+1].u.md_ival;
+ ++k );
+ snprintf(buf,sizeof(buf),_("%1$.30s string for %2$.30s"),
+ lang, (char *) ttfnameids[k].text );
+return( copy( buf ));
+}
+
+static void TNMatrixInit(struct matrixinit *mi,struct gfi_data *d) {
+ SplineFont *sf = d->sf;
+ int i,j,k,cnt;
+ uint8 sawEnglishUS[ttf_namemax];
+ struct ttflangname *tln;
+ struct matrix_data *md;
+
+ DefaultLanguage(d);
+
+ memset(mi,0,sizeof(*mi));
+ mi->col_cnt = 3;
+ mi->col_init = ci;
+
+ md = NULL;
+ for ( k=0; k<2; ++k ) {
+ memset(sawEnglishUS,0,sizeof(sawEnglishUS));
+ cnt = 0;
+ for ( tln = sf->names; tln!=NULL; tln = tln->next ) {
+ for ( i=0; i<ttf_namemax; ++i ) if ( i!=ttf_postscriptname && tln->names[i]!=NULL ) {
+ if ( md!=NULL ) {
+ md[3*cnt ].u.md_ival = tln->lang;
+ md[3*cnt+1].u.md_ival = i;
+ md[3*cnt+2].u.md_str = copy(tln->names[i]);
+ }
+ ++cnt;
+ if ( tln->lang==0x409 )
+ sawEnglishUS[i] = true;
+ }
+ }
+ for ( i=0; ttfspecials[i]!=-1; ++i ) if ( !sawEnglishUS[ttfspecials[i]] ) {
+ if ( md!=NULL ) {
+ md[3*cnt ].u.md_ival = 0x409;
+ md[3*cnt+1].u.md_ival = ttfspecials[i];
+ md[3*cnt+2].u.md_str = NULL;
+/* if frozen is set then can't remove or edit. (old basedon bit) */
+ md[3*cnt].frozen = md[3*cnt+1].frozen = md[3*cnt+2].frozen = true;
+/* if user_bits is set then can't remove. (old cantremove bit) */
+ md[3*cnt].user_bits = md[3*cnt+1].user_bits = md[3*cnt+2].user_bits = true;
+ }
+ ++cnt;
+ }
+ if ( md==NULL )
+ md = gcalloc(3*(cnt+10),sizeof(struct matrix_data));
+ }
+ for ( i=0; i<cnt; ++i ) if ( md[3*cnt].u.md_ival==0x409 ) {
+ for ( j=0; ttfspecials[j]!=-1 && ttfspecials[j]!=md[3*cnt+1].u.md_ival; ++j );
+ md[3*i].user_bits = md[3*i+1].user_bits = md[3*i+2].user_bits =
+ ( ttfspecials[j]!=-1 );
+ }
+ mi->matrix_data = md;
+ mi->initial_row_cnt = cnt;
+
+ mi->initrow = TN_NewName;
+ mi->finishedit = TN_FinishEdit;
+ mi->candelete = TN_CanDelete;
+ mi->popupmenu = TN_PopupMenu;
+ mi->handle_key = TN_PassChar;
+ mi->bigedittitle = TN_BigEditTitle;
+}
+
+static int GFI_HelpOFL(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ help("http://scripts.sil.org/OFL");
+ }
+return( true );
+}
+
+static int GFI_AddOFL(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ GGadget *tng = GWidgetGetControl(GGadgetGetWindow(g),CID_TNames);
+ int rows;
+ struct matrix_data *tns, *newtns;
+ int i,j,k,l,m, extras, len;
+ char *all, *pt, **data;
+ char buffer[1024], *bpt;
+ const char *author = GetAuthor();
+ char *reservedname, *fallback;
+ time_t now;
+ struct tm *tm;
+
+ time(&now);
+ tm = localtime(&now);
+
+ tns = GMatrixEditGet(tng, &rows); newtns = NULL;
+ for ( k=0; k<2; ++k ) {
+ extras = 0;
+ for ( i=0; ofl_str_lang_data[i].data!=NULL; ++i ) {
+ for ( j=rows-1; j>=0; --j ) {
+ if ( tns[j*3+1].u.md_ival==ofl_str_lang_data[i].strid &&
+ tns[j*3+0].u.md_ival==ofl_str_lang_data[i].lang ) {
+ if ( k ) {
+ free(newtns[j*3+2].u.md_str);
+ newtns[j*3+2].u.md_str = NULL;
+ }
+ break;
+ }
+ }
+ if ( j<0 )
+ j = rows + extras++;
+ if ( k ) {
+ newtns[j*3+1].u.md_ival = ofl_str_lang_data[i].strid;
+ newtns[j*3+0].u.md_ival = ofl_str_lang_data[i].lang;
+ data = ofl_str_lang_data[i].data;
+ reservedname = fallback = NULL;
+ for ( m=0; m<rows; ++m ) {
+ if ( newtns[j*3+1].u.md_ival==ttf_family ) {
+ if ( newtns[j*3+0].u.md_ival==0x409 )
+ fallback = newtns[3*j+2].u.md_str;
+ else if ( newtns[j*3+0].u.md_ival==ofl_str_lang_data[i].lang )
+ reservedname = newtns[3*j+2].u.md_str;
+ }
+ }
+ if ( reservedname==NULL )
+ reservedname = fallback;
+ if ( reservedname==NULL )
+ reservedname = d->sf->familyname;
+ for ( m=0; m<2; ++m ) {
+ len = 0;
+ for ( l=0; data[l]!=NULL; ++l ) {
+ if ( l==0 || l==1 ) {
+ sprintf( buffer, data[l], tm->tm_year+1900, author, reservedname );
+ bpt = buffer;
+ } else
+ bpt = data[l];
+ if ( m ) {
+ strcpy( pt, bpt );
+ pt += strlen( bpt );
+ *pt++ = '\n';
+ } else
+ len += strlen( bpt ) + 1; /* for a new line */
+ }
+ if ( !m )
+ newtns[j*3+2].u.md_str = all = pt = galloc(len+2);
+ }
+ if ( pt>all ) pt[-1] = '\0';
+ else *pt = '\0';
+ }
+ }
+ if ( !k ) {
+ newtns = gcalloc((rows+extras)*3,sizeof(struct matrix_data));
+ memcpy(newtns,tns,rows*3*sizeof(struct matrix_data));
+ for ( i=0; i<rows; ++i )
+ newtns[3*i+2].u.md_str = copy(newtns[3*i+2].u.md_str);
+ }
+ }
+ GMatrixEditSet(tng, newtns, rows+extras, false);
+ gwwv_post_notice(_("Please read the OFL"),_(
+ "You should read the OFL and its FAQ \n"
+ "at http://scripts.sil.org/OFL."
+ "\n"
+ "If you are not very familiar with English,\n"
+ "please check if there is a translation of the \n"
+ "FAQ or an unofficial translation of the license \n"
+ "in your mother tongue or preferred language. \n"
+ "\n"
+ "Fontforge does not know about your email or URL,\n"
+ "you will need to add them manually. \n"
+ "Please fill in the copyright notice in the license\n"
+ "header along with any Reserved Font Name(s).\n"
+ "If you are branching from an existing font make sure\n"
+ "you have the right to do so and remember to add your\n"
+ "additional copyright notice along with any Reserved Font Name(s).\n" ));
+ }
+return( true );
+}
+
+static int Gasp_Default(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ GGadget *gg = GWidgetGetControl(GGadgetGetWindow(g),CID_Gasp);
+ int rows;
+ struct matrix_data *gasp;
+
+ if ( !SFHasInstructions(d->sf)) {
+ rows = 1;
+ gasp = gcalloc(5,sizeof(struct matrix_data));
+ gasp[0].u.md_ival = 65535;
+ gasp[1].u.md_ival = 0; /* no grid fit (we have no instructions, we can't grid fit) */
+ gasp[2].u.md_ival = 1; /* do anti-alias */
+ gasp[2].u.md_ival = 0; /* do symmetric smoothing */
+ gasp[2].u.md_ival = 0; /* do no grid fit w/ sym smooth */
+ } else {
+ rows = 3;
+ gasp = gcalloc(5,sizeof(struct matrix_data));
+ gasp[0].u.md_ival = 8; gasp[1].u.md_ival = 0; gasp[2].u.md_ival = 1;
+ gasp[3].u.md_ival = 0; gasp[4].u.md_ival = 0;
+ gasp[5].u.md_ival = 16; gasp[6].u.md_ival = 1; gasp[7].u.md_ival = 0;
+ gasp[8].u.md_ival = 0; gasp[9].u.md_ival = 0;
+ gasp[10].u.md_ival = 65535; gasp[11].u.md_ival = 1; gasp[12].u.md_ival = 1;
+ gasp[13].u.md_ival = 0; gasp[14].u.md_ival = 0;
+ }
+ GMatrixEditSet(gg,gasp,rows,false);
+ }
+return( true );
+}
+
+static int Gasp_CanDelete(GGadget *g,int row) {
+ int rows;
+ struct matrix_data *gasp = GMatrixEditGet(g, &rows);
+ if ( gasp==NULL )
+return( false );
+
+ /* Only allow them to delete the sentinal entry if that would give us an */
+ /* empty gasp table */
+return( gasp[5*row].u.md_ival!=0xffff || rows==1 );
+}
+
+static int gasp_comp(const void *_md1, const void *_md2) {
+ const struct matrix_data *md1 = _md1, *md2 = _md2;
+return( md1->u.md_ival - md2->u.md_ival );
+}
+
+static void Gasp_FinishEdit(GGadget *g,int row,int col,int wasnew) {
+ int rows;
+ struct matrix_data *gasp = GMatrixEditGet(g, &rows);
+
+ if ( col==0 ) {
+ qsort(gasp,rows,3*sizeof(struct matrix_data),gasp_comp);
+ GGadgetRedraw(g);
+ }
+}
+
+static void GaspMatrixInit(struct matrixinit *mi,struct gfi_data *d) {
+ SplineFont *sf = d->sf;
+ int i;
+ struct matrix_data *md;
+
+ memset(mi,0,sizeof(*mi));
+ mi->col_cnt = 5;
+ mi->col_init = gaspci;
+
+ if ( sf->gasp_cnt==0 ) {
+ md = gcalloc(5,sizeof(struct matrix_data));
+ mi->initial_row_cnt = 0;
+ } else {
+ md = gcalloc(5*sf->gasp_cnt,sizeof(struct matrix_data));
+ for ( i=0; i<sf->gasp_cnt; ++i ) {
+ md[5*i ].u.md_ival = sf->gasp[i].ppem;
+ md[5*i+1].u.md_ival = (sf->gasp[i].flags&1)?1:0;
+ md[5*i+2].u.md_ival = (sf->gasp[i].flags&2)?1:0;
+ md[5*i+3].u.md_ival = (sf->gasp[i].flags&4)?1:0;
+ md[5*i+4].u.md_ival = (sf->gasp[i].flags&8)?1:0;
+ }
+ mi->initial_row_cnt = sf->gasp_cnt;
+ }
+ mi->matrix_data = md;
+
+ mi->finishedit = Gasp_FinishEdit;
+ mi->candelete = Gasp_CanDelete;
+ mi->handle_key = TN_PassChar;
+}
+
+static int GFI_GaspVersion(GGadget *g, GEvent *e) {
+ if ( e->u.control.subtype == et_listselected ) {
+ int version = GGadgetGetFirstListSelectedItem(g);
+ GGadget *gasp = GWidgetGetControl(GGadgetGetWindow(g),CID_Gasp);
+ if ( version == 0 ) {
+ GMatrixEditEnableColumn(gasp,3,false);
+ GMatrixEditEnableColumn(gasp,4,false);
+ } else {
+ GMatrixEditEnableColumn(gasp,3,true);
+ GMatrixEditEnableColumn(gasp,4,true);
+ }
+ GGadgetRedraw(gasp);
+ }
+return( true );
+}
+
+static int GFI_SortBy(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
+ struct gfi_data *d = (struct gfi_data *) GDrawGetUserData(GGadgetGetWindow(g));
+ TTFNames_Resort(d);
+ GGadgetRedraw(GWidgetGetControl(d->gw,CID_TNames));
+ }
+return( true );
+}
+
+static void BDFsSetAsDs(SplineFont *sf) {
+ BDFFont *bdf;
+ real scale;
+
+ for ( bdf=sf->bitmaps; bdf!=NULL; bdf=bdf->next ) {
+ scale = bdf->pixelsize / (real) (sf->ascent+sf->descent);
+ bdf->ascent = rint(sf->ascent*scale);
+ bdf->descent = bdf->pixelsize-bdf->ascent;
+ }
+}
+
+static char *texparams[] = { N_("Slant:"), N_("Space:"), N_("Stretch:"),
+ N_("Shrink:"), N_("XHeight:"), N_("Quad:"),
+/* GT: Extra Space, see below for a full comment */
+ N_("Extra Sp:"), NULL };
+static char *texpopups[] = { N_("In an italic font the horizontal change per unit vertical change"),
+ N_("The amount of space between words when using this font"),
+ N_("The amount of strechable space between words when using this font"),
+ N_("The amount the space between words may shrink when using this font"),
+ N_("The height of the lower case letters with flat tops"),
+ N_("The width of one em"),
+ N_("Either:\nThe amount of extra space to be added after a sentence\nOr the space to be used within math formulae"),
+ NULL};
+
+static int ParseTeX(struct gfi_data *d) {
+ int i, err=false;
+ double em = (d->sf->ascent+d->sf->descent), val;
+
+ for ( i=0; texparams[i]!=0 ; ++i ) {
+ val = GetReal8(d->gw,CID_TeX+i,texparams[i],&err);
+ d->texdata.params[i] = rint( val/em * (1<<20) );
+ }
+ if ( GGadgetIsChecked(GWidgetGetControl(d->gw,CID_TeXText)) )
+ d->texdata.type = tex_text;
+ else if ( GGadgetIsChecked(GWidgetGetControl(d->gw,CID_TeXMathSym)) )
+ d->texdata.type = tex_math;
+ else
+ d->texdata.type = tex_mathext;
+return( !err );
+}
+
+static int ttfmultuniqueids(SplineFont *sf,struct gfi_data *d) {
+ struct ttflangname *tln;
+ int found = false;
+ int i;
+
+ if ( d->names_set ) {
+ GGadget *edit = GWidgetGetControl(d->gw,CID_TNames);
+ int rows;
+ struct matrix_data *strings = GMatrixEditGet(edit, &rows);
+ for ( i=0; i<rows; ++i )
+ if ( strings[3*i+1].u.md_ival==ttf_uniqueid ) {
+ if ( found )
+return( true );
+ found = true;
+ }
+ } else {
+ for ( tln = sf->names; tln!=NULL; tln=tln->next )
+ if ( tln->names[ttf_uniqueid]!=NULL ) {
+ if ( found )
+return( true );
+ found = true;
+ }
+ }
+return( false );
+}
+
+static int ttfuniqueidmatch(SplineFont *sf,struct gfi_data *d) {
+ struct ttflangname *tln;
+ int i;
+
+ if ( sf->names==NULL )
+return( false );
+
+ if ( !d->names_set ) {
+ for ( tln = sf->names; tln!=NULL; tln=tln->next )
+ if ( tln->names[ttf_uniqueid]!=NULL )
+return( true );
+ } else {
+ GGadget *edit = GWidgetGetControl(d->gw,CID_TNames);
+ int rows;
+ struct matrix_data *strings = GMatrixEditGet(edit, &rows);
+
+ for ( tln = sf->names; tln!=NULL; tln=tln->next ) {
+ if ( tln->names[ttf_uniqueid]==NULL )
+ continue; /* Not set, so if it has been given a new value */
+ /* that's a change, and if it hasn't that's ok */
+ for ( i=0; i<rows; ++i )
+ if ( strings[3*i+1].u.md_ival==ttf_uniqueid && strings[3*i].u.md_ival==tln->lang )
+ break;
+ if ( i==rows )
+ continue; /* removed. That's a change */
+ if ( strcmp(tln->names[ttf_uniqueid],strings[3*i+2].u.md_str )==0 )
+return( true ); /* name unchanged */
+ }
+ }
+return( false );
+}
+
+static void ttfuniqueidfixup(SplineFont *sf,struct gfi_data *d) {
+ struct ttflangname *tln;
+ char *changed = NULL;
+ int i;
+
+ if ( sf->names==NULL )
+return;
+
+ if ( !d->names_set ) {
+ for ( tln = sf->names; tln!=NULL; tln=tln->next ) {
+ free( tln->names[ttf_uniqueid]);
+ tln->names[ttf_uniqueid] = NULL;
+ }
+ } else {
+ GGadget *edit = GWidgetGetControl(d->gw,CID_TNames);
+ int rows;
+ struct matrix_data *strings = GMatrixEditGet(edit, &rows);
+
+ /* see if any instances of the name have changed */
+ for ( tln = sf->names; tln!=NULL; tln=tln->next ) {
+ if ( tln->names[ttf_uniqueid]==NULL )
+ continue;
+ for ( i=0; i<rows; ++i )
+ if ( strings[3*i+1].u.md_ival==ttf_uniqueid && strings[3*i].u.md_ival==tln->lang )
+ break;
+ if ( i==rows )
+ continue;
+ if ( strcmp(tln->names[ttf_uniqueid],strings[3*i+2].u.md_str )!=0 )
+ changed = copy(strings[3*i+2].u.md_str );
+ break;
+ }
+ /* All unique ids should be the same, if any changed set the unchanged */
+ /* ones to the one that did (or the first of many if several changed) */
+ for ( tln = sf->names; tln!=NULL; tln=tln->next ) {
+ if ( tln->names[ttf_uniqueid]==NULL )
+ continue;
+ for ( i=0; i<rows; ++i )
+ if ( strings[3*i+1].u.md_ival==ttf_uniqueid && strings[3*i].u.md_ival==tln->lang )
+ break;
+ if ( i==rows )
+ continue;
+ if ( strcmp(tln->names[ttf_uniqueid],strings[3*i+2].u.md_str)==0 ) {
+ free(strings[3*i+2].u.md_str);
+ strings[3*i+2].u.md_str = changed!=NULL
+ ? copy( changed )
+ : NULL;
+ }
+ }
+ }
+}
+
+static void StoreTTFNames(struct gfi_data *d) {
+ struct ttflangname *tln;
+ SplineFont *sf = d->sf;
+ int i;
+ GGadget *edit = GWidgetGetControl(d->gw,CID_TNames);
+ int rows;
+ struct matrix_data *strings = GMatrixEditGet(edit, &rows);
+
+ TTFLangNamesFree(sf->names); sf->names = NULL;
+
+ for ( i=0; i<rows; ++i ) {
+ for ( tln=sf->names; tln!=NULL && tln->lang!=strings[3*i].u.md_ival; tln=tln->next );
+ if ( tln==NULL ) {
+ tln = chunkalloc(sizeof(struct ttflangname));
+ tln->lang = strings[3*i].u.md_ival;
+ tln->next = sf->names;
+ sf->names = tln;
+ }
+ tln->names[strings[3*i+1].u.md_ival] = copy(strings[3*i+2].u.md_str );
+ }
+ TTF_PSDupsDefault(sf);
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+/* If we change the ascent/descent of a sub font then consider changing the */
+/* as/ds of the master font. I used to think this irrelevant, but as the */
+/* typoAscent/Descent is based on the master's ascent/descent it actually */
+/* is meaningful. Set the master to the subfont with the most glyphs */
+void CIDMasterAsDes(SplineFont *sf) {
+ SplineFont *cidmaster = sf->cidmaster;
+ SplineFont *best;
+ int i, cid, cnt, bcnt;
+
+ if ( cidmaster==NULL )
+return;
+ best = NULL; bcnt = 0;
+ for ( i=0; i<cidmaster->subfontcnt; ++i ) {
+ sf = cidmaster->subfonts[i];
+ for ( cid=cnt=0; cid<sf->glyphcnt; ++cid )
+ if ( sf->glyphs[cid]!=NULL )
+ ++cnt;
+ if ( cnt>bcnt ) {
+ best = sf;
+ bcnt = cnt;
+ }
+ }
+ if ( best==NULL && cidmaster->subfontcnt>0 )
+ best = cidmaster->subfonts[0];
+ if ( best!=NULL ) {
+ double ratio = 1000.0/(best->ascent+best->descent);
+ int ascent = rint(best->ascent*ratio);
+ if ( cidmaster->ascent!=ascent || cidmaster->descent!=1000-ascent ) {
+ cidmaster->ascent = ascent;
+ cidmaster->descent = 1000-ascent;
+ }
+ }
+}
+
+void SFSetModTime(SplineFont *sf) {
+ time_t now;
+ time(&now);
+ sf->modificationtime = now;
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static void GFI_ApplyLookupChanges(struct gfi_data *gfi) {
+ int i,j, isgpos;
+ OTLookup *last;
+ SplineFont *sf = gfi->sf;
+ struct lookup_subtable *sublast;
+
+ for ( isgpos=0; isgpos<2; ++isgpos ) {
+ struct lkdata *lk = &gfi->tables[isgpos];
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ SFRemoveLookup(gfi->sf,lk->all[i].lookup);
+ else for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].deleted )
+ SFRemoveLookupSubTable(gfi->sf,lk->all[i].subtables[j].subtable);
+ }
+ }
+ last = NULL;
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( !lk->all[i].deleted ) {
+ if ( last!=NULL )
+ last->next = lk->all[i].lookup;
+ else if ( isgpos )
+ sf->gpos_lookups = lk->all[i].lookup;
+ else
+ sf->gsub_lookups = lk->all[i].lookup;
+ last = lk->all[i].lookup;
+ sublast = NULL;
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( !lk->all[i].subtables[j].deleted ) {
+ if ( sublast!=NULL )
+ sublast->next = lk->all[i].subtables[j].subtable;
+ else
+ last->subtables = lk->all[i].subtables[j].subtable;
+ sublast = lk->all[i].subtables[j].subtable;
+ }
+ }
+ if ( sublast!=NULL )
+ sublast->next = NULL;
+ else
+ last->subtables = NULL;
+ }
+ free(lk->all[i].subtables);
+ }
+ if ( last!=NULL )
+ last->next = NULL;
+ else if ( isgpos )
+ sf->gpos_lookups = NULL;
+ else
+ sf->gsub_lookups = NULL;
+ free(lk->all);
+ }
+}
+
+static int GFI_OK(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GWindow gw = GGadgetGetWindow(g);
+ struct gfi_data *d = GDrawGetUserData(gw);
+ SplineFont *sf = d->sf, *_sf;
+ int interp;
+ int reformat_fv=0, retitle_fv=false;
+ int upos, uwid, as, des, err = false, weight=0;
+ int uniqueid, linegap=0, vlinegap=0, winascent=0, windescent=0;
+ int tlinegap=0, tascent=0, tdescent=0, hascent=0, hdescent=0;
+ int winaoff=true, windoff=true;
+ int taoff=true, tdoff=true, haoff = true, hdoff = true;
+ real ia, cidversion;
+ const unichar_t *txt, *fond; unichar_t *end;
+ int i,j, mcs;
+ int vmetrics, vorigin, namechange, order2;
+ int xuidchanged = false;
+ GTextInfo *pfmfam, *ibmfam, *fstype, *nlitem;
+ int32 len;
+ GTextInfo **ti;
+ int subs[4], super[4], strike[2];
+ int design_size, size_top, size_bottom, styleid;
+ int strokedfont = false;
+ real strokewidth;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ int multilayer = false;
+#endif
+ char os2_vendor[4];
+ NameList *nl;
+ extern int allow_utf8_glyphnames;
+ int os2version;
+ int rows, gasprows;
+ struct matrix_data *strings = GMatrixEditGet(GWidgetGetControl(d->gw,CID_TNames), &rows);
+ struct matrix_data *gasp = GMatrixEditGet(GWidgetGetControl(d->gw,CID_Gasp), &gasprows);
+
+ if ( strings==NULL || gasp==NULL )
+return( true );
+ if ( gasprows>0 && gasp[5*gasprows-5].u.md_ival!=65535 ) {
+ gwwv_post_error(_("Bad Grid Fiting table"),_("The 'gasp' (Grid Fit) table must end with a pixel entry of 65535"));
+return( true );
+ }
+ if ( !CheckNames(d))
+return( true );
+ if ( !PIFinishFormer(d))
+return( true );
+ if ( d->ccd )
+ CCD_Close(d->ccd);
+ if ( d->smd )
+ SMD_Close(d->smd);
+
+ if ( ttfmultuniqueids(sf,d)) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buts[3];
+ buts[0] = _("_OK"); buts[1] = _("_Cancel"); buts[2]=NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buts[] = { GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL };
+#endif
+ if ( gwwv_ask(_("Too many Unique Font IDs"),(const char **) buts,0,1,_("You should only specify the TrueType Unique Font Identification string in one language. This font has more. Do you want to continue anyway?"))==1 )
+return( true );
+ }
+ txt = _GGadgetGetTitle(GWidgetGetControl(gw,CID_Family));
+ if ( !isalpha(*txt)) {
+ BadFamily();
+return( true );
+ }
+ txt = _GGadgetGetTitle(GWidgetGetControl(gw,CID_ItalicAngle));
+ ia = u_strtod(txt,&end);
+ if ( *end!='\0' ) {
+ Protest8(_("_Italic Angle:"));
+return(true);
+ }
+ order2 = GGadgetIsChecked(GWidgetGetControl(gw,CID_IsOrder2));
+ strokedfont = GGadgetIsChecked(GWidgetGetControl(gw,CID_IsStrokedFont));
+ strokewidth = GetReal8(gw,CID_StrokeWidth,_("Stroke _Width:"),&err);
+#ifdef FONTFORGE_CONFIG_TYPE3
+ multilayer = GGadgetIsChecked(GWidgetGetControl(gw,CID_IsMultiLayer));
+#endif
+ vmetrics = GGadgetIsChecked(GWidgetGetControl(gw,CID_HasVerticalMetrics));
+ upos = GetReal8(gw,CID_UPos, _("Underline _Position:"),&err);
+ uwid = GetReal8(gw,CID_UWidth,S_("Underline|_Height:"),&err);
+ GetInt8(gw,CID_Em,_("_Em Size:"),&err); /* just check for errors. redundant info */
+ as = GetInt8(gw,CID_Ascent,_("_Ascent:"),&err);
+ des = GetInt8(gw,CID_Descent,_("_Descent:"),&err);
+ uniqueid = GetInt8(gw,CID_UniqueID,_("UniqueID"),&err);
+ design_size = rint(10*GetReal8(gw,CID_DesignSize,_("De_sign Size:"),&err));
+ size_bottom = rint(10*GetReal8(gw,CID_DesignBottom,_("_Bottom"),&err));
+ size_top = rint(10*GetReal8(gw,CID_DesignTop,_("_Top"),&err));
+ styleid = GetInt8(gw,CID_StyleID,_("Style _ID:"),&err);
+ if ( err )
+return(true);
+ if ( sf->subfontcnt!=0 ) {
+ cidversion = GetReal8(gw,CID_Version,_("_Version"),&err);
+ if ( err )
+return(true);
+ }
+ if ( vmetrics )
+ vorigin = GetInt8(gw,CID_VOrigin,_("Vertical _Origin:"),&err);
+ os2version = sf->os2_version;
+ if ( d->ttf_set ) {
+ char *os2v = GGadgetGetTitle8(GWidgetGetControl(gw,CID_OS2Version));
+ if ( strcasecmp(os2v,_( (char *) os2versions[0].text ))== 0 )
+ os2version = 0;
+ else
+ os2version = GetInt8(gw,CID_OS2Version,_("Weight, Width, Slope Only"),&err);
+ free(os2v);
+ /* Only use the normal routine if we get no value, because */
+ /* "400 Book" is a reasonable setting, but would cause GetInt */
+ /* to complain */
+ weight = u_strtol(_GGadgetGetTitle(GWidgetGetControl(gw,CID_WeightClass)),NULL,10);
+ if ( weight == 0 )
+ weight = GetInt8(gw,CID_WeightClass,_("_Weight Class"),&err);
+ linegap = GetInt8(gw,CID_LineGap,_("HHead _Line Gap:"),&err);
+ tlinegap = GetInt8(gw,CID_TypoLineGap,_("Typo Line _Gap:"),&err);
+ if ( vmetrics )
+ vlinegap = GetInt8(gw,CID_VLineGap,_("VHead _Column Spacing:"),&err);
+ winaoff = GGadgetIsChecked(GWidgetGetControl(gw,CID_WinAscentIsOff));
+ windoff = GGadgetIsChecked(GWidgetGetControl(gw,CID_WinDescentIsOff));
+ winascent = GetInt8(gw,CID_WinAscent,winaoff ? _("Win _Ascent Offset:") : _("Win Ascent:"),&err);
+ windescent = GetInt8(gw,CID_WinDescent,windoff ? _("Win _Descent Offset:") : _("Win Descent:"),&err);
+ taoff = GGadgetIsChecked(GWidgetGetControl(gw,CID_TypoAscentIsOff));
+ tdoff = GGadgetIsChecked(GWidgetGetControl(gw,CID_TypoDescentIsOff));
+ tascent = GetInt8(gw,CID_TypoAscent,taoff ? _("_Typo Ascent Offset:") : _("Typo Ascent:"),&err);
+ tdescent = GetInt8(gw,CID_TypoDescent,tdoff ? _("T_ypo Descent Offset:") : _("Typo Descent:"),&err);
+ haoff = GGadgetIsChecked(GWidgetGetControl(gw,CID_HHeadAscentIsOff));
+ hdoff = GGadgetIsChecked(GWidgetGetControl(gw,CID_HHeadDescentIsOff));
+ hascent = GetInt8(gw,CID_HHeadAscent,haoff ? _("_HHead Ascent Offset:") : _("HHead Ascent:"),&err);
+ hdescent = GetInt8(gw,CID_HHeadDescent,hdoff ? _("HHead De_scent Offset:") : _("HHead Descent:"),&err);
+ if ( err )
+return(true);
+
+ if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_SubSuperDefault)) ) {
+ for ( i=0; i<4; ++i )
+ subs[i] = GetInt8(gw,CID_SubXSize+i,_("Subscript"),&err);
+ for ( i=0; i<4; ++i )
+ super[i] = GetInt8(gw,CID_SuperXSize+i,_("Superscript"),&err);
+ for ( i=0; i<2; ++i )
+ strike[i] = GetInt8(gw,CID_StrikeoutSize+i,_("Strikeout"),&err);
+ }
+ txt = _GGadgetGetTitle(GWidgetGetControl(gw,CID_Vendor));
+ if ( u_strlen(txt)>4 || txt[0]>0x7e || (txt[0]!='\0' && (txt[1]>0x7e ||
+ (txt[1]!='\0' && (txt[2]>0x7e || (txt[2]!='\0' && txt[3]>0x7e))))) ) {
+ if ( u_strlen(txt)>4 )
+ gwwv_post_error(_("Bad IBM Family"),_("Tag must be 4 characters long"));
+ else
+ gwwv_post_error(_("Bad IBM Family"),_("A tag must be 4 ASCII characters"));
+return( true );
+ }
+ os2_vendor[0] = txt[0]==0 ? ' ' : txt[0];
+ os2_vendor[1] = txt[0]==0 || txt[1]=='\0' ? ' ' : txt[1];
+ os2_vendor[2] = txt[0]==0 || txt[1]=='\0' || txt[2]=='\0' ? ' ' : txt[2];
+ os2_vendor[3] = txt[0]==0 || txt[1]=='\0' || txt[2]=='\0' || txt[3]=='\0' ? ' ' : txt[3];
+ }
+ if ( err )
+return(true);
+ if ( d->tex_set ) {
+ if ( !ParseTeX(d))
+return( true );
+ }
+ if ( as+des>16384 || des<0 || as<0 ) {
+ gwwv_post_error(_("Bad Ascent/Descent"),_("Ascent and Descent must be positive and their sum less than 16384"));
+return( true );
+ }
+ mcs = -1;
+ if ( !GGadgetIsChecked(GWidgetGetControl(d->gw,CID_MacAutomatic)) ) {
+ mcs = 0;
+ ti = GGadgetGetList(GWidgetGetControl(d->gw,CID_MacStyles),&len);
+ for ( i=0; i<len; ++i )
+ if ( ti[i]->selected )
+ mcs |= (int) (intpt) ti[i]->userdata;
+ if ( (mcs&sf_condense) && (mcs&sf_extend)) {
+ gwwv_post_error(_("Bad Style"),_("A style may not have both condense and extend set (it makes no sense)"));
+return( true );
+ }
+ }
+ if ( order2!=sf->order2 && sf->changed && AskLoseUndoes())
+return( true );
+ if ( order2!=sf->order2 && !SFCloseAllInstrs(sf))
+return( true );
+
+ nlitem = GGadgetGetListItemSelected(GWidgetGetControl(gw,CID_Namelist));
+ if ( nlitem==NULL )
+ nl = DefaultNameListForNewFonts();
+ else {
+ char *name = u2utf8_copy(nlitem->text);
+ nl = NameListByName(name);
+ free(name);
+ }
+ if ( nl->uses_unicode && !allow_utf8_glyphnames ) {
+ gwwv_post_error(_("Namelist contains non-ASCII names"),_("Glyph names should be limited to characters in the ASCII character set,\nbut there are names in this namelist which use characters outside\nthat range."));
+return(true);
+ }
+#ifdef FONTFORGE_CONFIG_TYPE3
+ if ( strokedfont!=sf->strokedfont || multilayer!=sf->multilayer ) {
+ if ( sf->strokedfont && multilayer )
+ SFSetLayerWidthsStroked(sf,sf->strokewidth);
+ else if ( sf->multilayer )
+ SFSplinesFromLayers(sf,strokedfont);
+ SFReinstanciateRefs(sf);
+ if ( multilayer!=sf->multilayer ) {
+ sf->multilayer = multilayer;
+ SFLayerChange(sf);
+ }
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ sf->glyphs[i]->changedsincelasthinted = !strokedfont && !multilayer;
+ }
+#else
+ if ( strokedfont!=sf->strokedfont )
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ sf->glyphs[i]->changedsincelasthinted = !strokedfont;
+#endif
+ sf->strokedfont = strokedfont;
+ sf->strokewidth = strokewidth;
+ GDrawSetCursor(gw,ct_watch);
+ namechange = SetFontName(gw,sf);
+ if ( namechange ) retitle_fv = true;
+ txt = _GGadgetGetTitle(GWidgetGetControl(gw,CID_XUID));
+ xuidchanged = (sf->xuid==NULL && *txt!='\0') ||
+ (sf->xuid!=NULL && uc_strcmp(txt,sf->xuid)==0);
+ if ( namechange &&
+ ((uniqueid!=0 && uniqueid==sf->uniqueid) ||
+ (sf->xuid!=NULL && uc_strcmp(txt,sf->xuid)==0) ||
+ ttfuniqueidmatch(sf,d)) ) {
+ char *buts[4];
+ int ans;
+ buts[0] = _("Change");
+ buts[1] = _("Retain");
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ buts[2] = _("_Cancel");
+#elif defined(FONTFORGE_CONFIG_GTK)
+ buts[2] = GTK_STOCK_CANCEL;
+#endif
+ buts[3] = NULL;
+ ans = gwwv_ask(_("Change UniqueID?"),(const char **) buts,0,2,_("You have changed this font's name without changing the UniqueID (or XUID).\nThis is probably not a good idea, would you like me to\ngenerate a random new value?"));
+ if ( ans==2 ) {
+ GDrawSetCursor(gw,ct_pointer);
+return(true);
+ }
+ if ( ans==0 ) {
+ if ( uniqueid!=0 && uniqueid==sf->uniqueid )
+ uniqueid = 4000000 + (rand()&0x3ffff);
+ if ( sf->xuid!=NULL && uc_strcmp(txt,sf->xuid)==0 ) {
+ SFRandomChangeXUID(sf);
+ xuidchanged = true;
+ }
+ }
+ if ( ttfuniqueidmatch(sf,d))
+ ttfuniqueidfixup(sf,d);
+ } else {
+ free(sf->xuid);
+ sf->xuid = *txt=='\0'?NULL:cu_copy(txt);
+ }
+
+ free(sf->gasp);
+ sf->gasp_cnt = gasprows;
+ if ( gasprows==0 )
+ sf->gasp = NULL;
+ else {
+ sf->gasp = galloc(gasprows*sizeof(struct gasp));
+ sf->gasp_version = GGadgetGetFirstListSelectedItem(GWidgetGetControl(gw,CID_GaspVersion));
+ for ( i=0; i<gasprows; ++i ) {
+ sf->gasp[i].ppem = gasp[5*i].u.md_ival;
+ if ( sf->gasp_version==0 )
+ sf->gasp[i].flags = gasp[5*i+1].u.md_ival |
+ (gasp[5*i+2].u.md_ival<<1);
+ else
+ sf->gasp[i].flags = gasp[5*i+1].u.md_ival |
+ (gasp[5*i+2].u.md_ival<<1) |
+ (gasp[5*i+2].u.md_ival<<2) |
+ (gasp[5*i+2].u.md_ival<<3);
+ }
+ }
+ sf->head_optimized_for_cleartype = GGadgetIsChecked(GWidgetGetControl(gw,CID_HeadClearType));
+
+ OtfNameListFree(sf->fontstyle_name);
+ sf->fontstyle_name = OtfNameFromStyleNames(GWidgetGetControl(gw,CID_StyleName));
+ sf->design_size = design_size;
+ sf->design_range_bottom = size_bottom;
+ sf->design_range_top = size_top;
+ sf->fontstyle_id = styleid;
+
+ txt = _GGadgetGetTitle(GWidgetGetControl(gw,CID_Notice));
+ free(sf->copyright); sf->copyright = cu_copy(txt);
+ txt = _GGadgetGetTitle(GWidgetGetControl(gw,CID_Comment));
+ free(sf->comments); sf->comments = cu_copy(*txt?txt:NULL);
+ txt = _GGadgetGetTitle(GWidgetGetControl(gw,CID_DefBaseName));
+ if ( *txt=='\0' || GGadgetIsChecked(GWidgetGetControl(gw,CID_SameAsFontname)) )
+ txt = NULL;
+ free(sf->defbasefilename); sf->defbasefilename = u2utf8_copy(txt);
+ if ( sf->subfontcnt!=0 ) {
+ sf->cidversion = cidversion;
+ } else {
+ txt = _GGadgetGetTitle(GWidgetGetControl(gw,CID_Version));
+ free(sf->version); sf->version = cu_copy(txt);
+ }
+ fond = _GGadgetGetTitle(GWidgetGetControl(gw,CID_MacFOND));
+ free(sf->fondname); sf->fondname = NULL;
+ if ( *fond )
+ sf->fondname = cu_copy(fond);
+ sf->macstyle = mcs;
+ sf->italicangle = ia;
+ sf->upos = upos;
+ sf->uwidth = uwid;
+ sf->uniqueid = uniqueid;
+ sf->texdata = d->texdata;
+
+ interp = GGadgetGetFirstListSelectedItem(GWidgetGetControl(gw,CID_Interpretation));
+ if ( interp==-1 ) sf->uni_interp = ui_none;
+ else sf->uni_interp = (intpt) interpretations[interp].userdata;
+
+ sf->for_new_glyphs = nl;
+
+ if ( sf->hasvmetrics!=vmetrics )
+ CVPaletteDeactivate(); /* Force a refresh later */
+ _sf = sf->cidmaster?sf->cidmaster:sf;
+ _sf->hasvmetrics = vmetrics;
+ for ( j=0; j<_sf->subfontcnt; ++j )
+ _sf->subfonts[j]->hasvmetrics = vmetrics;
+ if ( vmetrics ) {
+ _sf->vertical_origin = vorigin;
+ for ( j=0; j<_sf->subfontcnt; ++j )
+ _sf->subfonts[j]->vertical_origin = vorigin;
+ }
+
+ if ( d->private!=NULL ) {
+ PSDictFree(sf->private);
+ sf->private = d->private;
+ d->private = NULL;
+ }
+ if ( d->names_set )
+ StoreTTFNames(d);
+ if ( d->ttf_set ) {
+ sf->os2_version = os2version;
+ sf->use_typo_metrics = GGadgetIsChecked(GWidgetGetControl(gw,CID_UseTypoMetrics));
+ sf->weight_width_slope_only = GGadgetIsChecked(GWidgetGetControl(gw,CID_WeightWidthSlopeOnly));
+ sf->pfminfo.weight = weight;
+ sf->pfminfo.width = GGadgetGetFirstListSelectedItem(GWidgetGetControl(gw,CID_WidthClass))+1;
+ pfmfam = GGadgetGetListItemSelected(GWidgetGetControl(gw,CID_PFMFamily));
+ if ( pfmfam!=NULL )
+ sf->pfminfo.pfmfamily = (intpt) (pfmfam->userdata);
+ else
+ sf->pfminfo.pfmfamily = 0x11;
+ ibmfam = GGadgetGetListItemSelected(GWidgetGetControl(gw,CID_IBMFamily));
+ if ( pfmfam!=NULL )
+ sf->pfminfo.os2_family_class = (intpt) (ibmfam->userdata);
+ else
+ sf->pfminfo.os2_family_class = 0x00;
+ memcpy(sf->pfminfo.os2_vendor,os2_vendor,sizeof(os2_vendor));
+ fstype = GGadgetGetListItemSelected(GWidgetGetControl(gw,CID_FSType));
+ if ( fstype!=NULL )
+ sf->pfminfo.fstype = (intpt) (fstype->userdata);
+ else
+ sf->pfminfo.fstype = 0xc;
+ if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_NoSubsetting)))
+ sf->pfminfo.fstype |=0x100;
+ if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_OnlyBitmaps)))
+ sf->pfminfo.fstype |=0x200;
+ for ( i=0; i<10; ++i )
+ sf->pfminfo.panose[i] = (intpt) (GGadgetGetListItemSelected(GWidgetGetControl(gw,CID_PanFamily+i))->userdata);
+ sf->pfminfo.panose_set = !GGadgetIsChecked(GWidgetGetControl(gw,CID_PanDefault));
+ sf->pfminfo.os2_typolinegap = tlinegap;
+ sf->pfminfo.linegap = linegap;
+ if ( vmetrics )
+ sf->pfminfo.vlinegap = vlinegap;
+ sf->pfminfo.os2_winascent = winascent;
+ sf->pfminfo.os2_windescent = windescent;
+ sf->pfminfo.winascent_add = winaoff;
+ sf->pfminfo.windescent_add = windoff;
+ sf->pfminfo.os2_typoascent = tascent;
+ sf->pfminfo.os2_typodescent = tdescent;
+ sf->pfminfo.typoascent_add = taoff;
+ sf->pfminfo.typodescent_add = tdoff;
+ sf->pfminfo.hhead_ascent = hascent;
+ sf->pfminfo.hhead_descent = hdescent;
+ sf->pfminfo.hheadascent_add = haoff;
+ sf->pfminfo.hheaddescent_add = hdoff;
+ sf->pfminfo.pfmset = true;
+
+ sf->pfminfo.subsuper_set = !GGadgetIsChecked(GWidgetGetControl(gw,CID_PanDefault));
+ if ( sf->pfminfo.subsuper_set ) {
+ sf->pfminfo.os2_subxsize = subs[0];
+ sf->pfminfo.os2_subysize = subs[1];
+ sf->pfminfo.os2_subxoff = subs[2];
+ sf->pfminfo.os2_subyoff = subs[3];
+ sf->pfminfo.os2_supxsize = super[0];
+ sf->pfminfo.os2_supysize = super[1];
+ sf->pfminfo.os2_supxoff = super[2];
+ sf->pfminfo.os2_supyoff = super[3];
+ sf->pfminfo.os2_strikeysize = strike[0];
+ sf->pfminfo.os2_strikeypos = strike[1];
+ }
+ }
+ /* must come after all scaleable fields (linegap, etc.) */
+ if ( as!=sf->ascent || des!=sf->descent ) {
+ if ( as+des != sf->ascent+sf->descent && GGadgetIsChecked(GWidgetGetControl(gw,CID_Scale)) )
+ SFScaleToEm(sf,as,des);
+ else {
+ sf->ascent = as;
+ sf->descent = des;
+ }
+ BDFsSetAsDs(sf);
+ reformat_fv = true;
+ CIDMasterAsDes(sf);
+ }
+ if ( order2!=sf->order2 ) {
+ if ( order2 )
+ SFConvertToOrder2(sf);
+ else
+ SFConvertToOrder3(sf);
+ }
+ GFI_ApplyLookupChanges(d);
+ if ( retitle_fv ) { FontView *fvs;
+ for ( fvs=sf->fv; fvs!=NULL; fvs=fvs->nextsame )
+ FVSetTitle(fvs);
+ }
+ if ( reformat_fv )
+ FontViewReformatAll(sf);
+ sf->changed = true;
+ SFSetModTime(sf);
+ sf->changed_since_autosave = true;
+ sf->changed_since_xuidchanged = !xuidchanged;
+ /* Just in case they changed the blue values and we are showing blues */
+ /* in outline views... */
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ CharView *cv;
+ for ( cv = sf->glyphs[i]->views; cv!=NULL; cv=cv->next ) {
+ cv->back_img_out_of_date = true;
+ GDrawRequestExpose(cv->v,NULL,false);
+ }
+ }
+ MacFeatListFree(sf->features);
+ sf->features = GGadgetGetUserData(GWidgetGetControl(d->gw,CID_Features));
+ last_aspect = d->old_aspect;
+
+ MarkClassFree(sf->mark_class_cnt,sf->mark_classes,sf->mark_class_names);
+ sf->mark_class_cnt = d->mark_class_cnt;
+ sf->mark_classes = d->mark_classes;
+ sf->mark_class_names = d->mark_class_names;
+
+ GFI_Close(d);
+
+ SFReplaceFontnameBDFProps(sf);
+ }
+return( true );
+}
+
+static void GFI_AsDsLab(struct gfi_data *d, int cid) {
+ int isoffset = GGadgetIsChecked(GWidgetGetControl(d->gw,cid));
+ DBounds b;
+ int ocid, labcid;
+ double val;
+ char buf[40];
+ char *offt, *baret;
+ int ismax=0;
+ unichar_t *end;
+
+ switch ( cid ) {
+ case CID_WinAscentIsOff:
+ offt = _("Win Ascent Offset:"); baret = _("Win Ascent:");
+ ocid = CID_WinAscent; labcid = CID_WinAscentLab;
+ ismax = true;
+ break;
+ case CID_WinDescentIsOff:
+ offt = _("Win Descent Offset:"); baret = _("Win Descent:");
+ ocid = CID_WinDescent; labcid = CID_WinDescentLab;
+ break;
+ case CID_TypoAscentIsOff:
+ offt = _("Typo Ascent Offset:"); baret = _("Typo Ascent:");
+ ocid = CID_TypoAscent; labcid = CID_TypoAscentLab;
+ ismax = true;
+ break;
+ case CID_TypoDescentIsOff:
+ offt = _("Typo Descent Offset:"); baret = _("Typo Descent:");
+ ocid = CID_TypoDescent; labcid = CID_TypoDescentLab;
+ break;
+ case CID_HHeadAscentIsOff:
+ offt = _("HHead Ascent Offset:"); baret = _("HHead Ascent:");
+ ocid = CID_HHeadAscent; labcid = CID_HHeadAscentLab;
+ ismax = true;
+ break;
+ case CID_HHeadDescentIsOff:
+ offt = _("HHead Descent Offset:"); baret = _("HHead Descent:");
+ ocid = CID_HHeadDescent; labcid = CID_HHeadDescentLab;
+ break;
+ default:
+return;
+ }
+
+ GGadgetSetTitle8(GWidgetGetControl(d->gw,labcid),
+ isoffset?offt:baret);
+ if ( cid == CID_TypoAscentIsOff ) {
+ const unichar_t *as = _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Ascent));
+ double av=u_strtod(as,&end);
+ b.maxy = *end=='\0' ? av : d->sf->ascent;
+ } else if ( cid == CID_TypoDescentIsOff ) {
+ const unichar_t *ds = _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Descent));
+ double dv=u_strtod(ds,&end);
+ b.miny = *end=='\0' ? -dv : -d->sf->descent;
+ } else {
+ CIDFindBounds(d->sf,&b);
+ if ( cid == CID_WinDescentIsOff ) b.miny = -b.miny;
+ }
+
+ val = u_strtod(_GGadgetGetTitle(GWidgetGetControl(d->gw,ocid)),NULL);
+ if ( isoffset )
+ sprintf( buf,"%g",rint( val-(ismax ? b.maxy : b.miny)) );
+ else
+ sprintf( buf,"%g",rint( val+(ismax ? b.maxy : b.miny)) );
+ GGadgetSetTitle8(GWidgetGetControl(d->gw,ocid),buf);
+}
+
+static int GFI_AsDesIsOff(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ GFI_AsDsLab(d,GGadgetGetCid(g));
+ }
+return( true );
+}
+
+static void _GFI_PanoseDefault(struct gfi_data *d) {
+ int i;
+ int isdefault = GGadgetIsChecked(GWidgetGetControl(d->gw,CID_PanDefault));
+
+ for ( i=0; i<10; ++i ) {
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_PanFamily+i),!isdefault);
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_PanFamilyLab+i),!isdefault);
+ }
+ if ( isdefault ) {
+ char *n = cu_copy(_GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Fontname)));
+ struct pfminfo info;
+ memset(&info,0,sizeof(info));
+ SFDefaultOS2Info(&info,d->sf,n);
+ free(n);
+ for ( i=0; i<10; ++i )
+ GGadgetSelectOneListItem(GWidgetGetControl(d->gw,CID_PanFamily+i),info.panose[i]);
+ }
+}
+
+static int GFI_PanoseDefault(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ _GFI_PanoseDefault(d);
+ }
+return( true );
+}
+
+static void GFI_SubSuperSet(struct gfi_data *d, struct pfminfo *info) {
+ char buffer[40];
+ unichar_t ubuf[40];
+
+ sprintf( buffer, "%d", info->os2_subxsize );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_SubXSize),ubuf);
+
+ sprintf( buffer, "%d", info->os2_subysize );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_SubYSize),ubuf);
+
+ sprintf( buffer, "%d", info->os2_subxoff );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_SubXOffset),ubuf);
+
+ sprintf( buffer, "%d", info->os2_subyoff );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_SubYOffset),ubuf);
+
+
+ sprintf( buffer, "%d", info->os2_supxsize );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_SuperXSize),ubuf);
+
+ sprintf( buffer, "%d", info->os2_supysize );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_SuperYSize),ubuf);
+
+ sprintf( buffer, "%d", info->os2_supxoff );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_SuperXOffset),ubuf);
+
+ sprintf( buffer, "%d", info->os2_supyoff );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_SuperYOffset),ubuf);
+
+
+ sprintf( buffer, "%d", info->os2_strikeysize );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_StrikeoutSize),ubuf);
+
+ sprintf( buffer, "%d", info->os2_strikeypos );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_StrikeoutPos),ubuf);
+}
+
+static void _GFI_SubSuperDefault(struct gfi_data *d) {
+ int i;
+ int isdefault = GGadgetIsChecked(GWidgetGetControl(d->gw,CID_SubSuperDefault));
+
+ for ( i=0; i<10; ++i )
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_SubXSize+i),!isdefault);
+ if ( isdefault ) {
+ const unichar_t *as = _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Ascent));
+ const unichar_t *ds = _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Descent));
+ const unichar_t *ia = _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Descent));
+ unichar_t *aend, *dend, *iend;
+ double av=u_strtod(as,&aend),dv=u_strtod(ds,&dend),iav=u_strtod(ia,&iend);
+ struct pfminfo info;
+ if ( *aend!='\0' ) av = d->sf->ascent;
+ if ( *dend!='\0' ) dv = d->sf->descent;
+ if ( *iend!='\0' ) iav = d->sf->italicangle;
+ memset(&info,0,sizeof(info));
+ SFDefaultOS2SubSuper(&info,(int) (dv+av), iav);
+ GFI_SubSuperSet(d,&info);
+ }
+}
+
+static int GFI_SubSuperDefault(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ _GFI_SubSuperDefault(d);
+ }
+return( true );
+}
+
+static void TTFSetup(struct gfi_data *d) {
+ struct pfminfo info;
+ char buffer[10]; unichar_t ubuf[10];
+ int i, lg, vlg, tlg;
+ const unichar_t *as = _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Ascent));
+ const unichar_t *ds = _GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Descent));
+ unichar_t *aend, *dend;
+ double av=u_strtod(as,&aend),dv=u_strtod(ds,&dend);
+
+ info = d->sf->pfminfo;
+ if ( !info.pfmset ) {
+ /* Base this stuff on the CURRENT name */
+ /* if the user just created a font, and named it *Bold, then the sf */
+ /* won't yet have Bold in its name, and basing the weight on it would*/
+ /* give the wrong answer. That's why we don't do this init until we */
+ /* get to one of the ttf aspects, it gives the user time to set the */
+ /* name properly */
+ /* And on CURRENT values of ascent and descent */
+ char *n = cu_copy(_GGadgetGetTitle(GWidgetGetControl(d->gw,CID_Fontname)));
+ if ( *aend=='\0' && *dend=='\0' ) {
+ if ( info.linegap==0 )
+ info.linegap = rint(.09*(av+dv));
+ if ( info.vlinegap==0 )
+ info.vlinegap = info.linegap;
+ if ( info.os2_typolinegap==0 )
+ info.os2_typolinegap = info.linegap;
+ }
+ lg = info.linegap; vlg = info.vlinegap; tlg = info.os2_typolinegap;
+ SFDefaultOS2Info(&info,d->sf,n);
+ if ( lg != 0 )
+ info.linegap = lg;
+ if ( vlg!= 0 )
+ info.vlinegap = vlg;
+ if ( tlg!=0 )
+ info.os2_typolinegap = tlg;
+ free(n);
+ }
+
+ if ( info.weight>0 && info.weight<=900 && info.weight%100==0 )
+ GGadgetSetTitle8(GWidgetGetControl(d->gw,CID_WeightClass),
+ (char *) weightclass[info.weight/100-1].text);
+ else {
+ sprintf( buffer, "%d", info.weight );
+ GGadgetSetTitle8(GWidgetGetControl(d->gw,CID_WeightClass),buffer);
+ }
+ GGadgetSelectOneListItem(GWidgetGetControl(d->gw,CID_WidthClass),info.width-1);
+ for ( i=0; pfmfamily[i].text!=NULL; ++i )
+ if ( (intpt) (pfmfamily[i].userdata)==info.pfmfamily ) {
+ GGadgetSelectOneListItem(GWidgetGetControl(d->gw,CID_PFMFamily),i);
+ break;
+ }
+
+ if ( d->sf->os2_version>=0 && d->sf->os2_version<=4 )
+ GGadgetSelectOneListItem(GWidgetGetControl(d->gw,CID_OS2Version),d->sf->os2_version);
+ else {
+ sprintf( buffer,"%d", d->sf->os2_version );
+ GGadgetSetTitle8(GWidgetGetControl(d->gw,CID_OS2Version),buffer);
+ }
+ GGadgetSetChecked(GWidgetGetControl(d->gw,CID_UseTypoMetrics),d->sf->use_typo_metrics);
+ GGadgetSetChecked(GWidgetGetControl(d->gw,CID_WeightWidthSlopeOnly),d->sf->weight_width_slope_only);
+
+ for ( i=0; ibmfamily[i].text!=NULL; ++i )
+ if ( (intpt) (ibmfamily[i].userdata)==info.os2_family_class ) {
+ GGadgetSelectOneListItem(GWidgetGetControl(d->gw,CID_IBMFamily),i);
+ break;
+ }
+ if ( info.os2_vendor[0]!='\0' ) {
+ ubuf[0] = info.os2_vendor[0];
+ ubuf[1] = info.os2_vendor[1];
+ ubuf[2] = info.os2_vendor[2];
+ ubuf[3] = info.os2_vendor[3];
+ ubuf[4] = 0;
+ } else if ( TTFFoundry!=NULL )
+ uc_strncpy(ubuf,TTFFoundry,4);
+ else
+ uc_strcpy(ubuf,"PfEd");
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_Vendor),ubuf);
+
+
+ GGadgetSetChecked(GWidgetGetControl(d->gw,CID_PanDefault),!info.panose_set);
+ _GFI_PanoseDefault(d);
+ if ( info.panose_set )
+ for ( i=0; i<10; ++i )
+ GGadgetSelectOneListItem(GWidgetGetControl(d->gw,CID_PanFamily+i),info.panose[i]);
+
+ GGadgetSetChecked(GWidgetGetControl(d->gw,CID_SubSuperDefault),!info.subsuper_set);
+ if ( info.subsuper_set )
+ GFI_SubSuperSet(d,&info);
+ _GFI_SubSuperDefault(d);
+
+ d->ttf_set = true;
+ /* FSType is already set */
+ sprintf( buffer, "%d", info.linegap );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_LineGap),ubuf);
+ sprintf( buffer, "%d", info.vlinegap );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_VLineGap),ubuf);
+ sprintf( buffer, "%d", info.os2_typolinegap );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_TypoLineGap),ubuf);
+
+ GGadgetSetChecked(GWidgetGetControl(d->gw,CID_WinAscentIsOff),info.winascent_add);
+ GFI_AsDsLab(d,CID_WinAscentIsOff);
+ sprintf( buffer, "%d", info.os2_winascent );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_WinAscent),ubuf);
+ GGadgetSetChecked(GWidgetGetControl(d->gw,CID_WinDescentIsOff),info.windescent_add);
+ GFI_AsDsLab(d,CID_WinDescentIsOff);
+ sprintf( buffer, "%d", info.os2_windescent );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_WinDescent),ubuf);
+
+ GGadgetSetChecked(GWidgetGetControl(d->gw,CID_TypoAscentIsOff),info.typoascent_add);
+ GFI_AsDsLab(d,CID_TypoAscentIsOff);
+ sprintf( buffer, "%d", info.os2_typoascent );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_TypoAscent),ubuf);
+ GGadgetSetChecked(GWidgetGetControl(d->gw,CID_TypoDescentIsOff),info.typodescent_add);
+ GFI_AsDsLab(d,CID_TypoDescentIsOff);
+ sprintf( buffer, "%d", info.os2_typodescent );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_TypoDescent),ubuf);
+
+ GGadgetSetChecked(GWidgetGetControl(d->gw,CID_HHeadAscentIsOff),info.hheadascent_add);
+ GFI_AsDsLab(d,CID_HHeadAscentIsOff);
+ sprintf( buffer, "%d", info.hhead_ascent );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_HHeadAscent),ubuf);
+ GGadgetSetChecked(GWidgetGetControl(d->gw,CID_HHeadDescentIsOff),info.hheaddescent_add);
+ GFI_AsDsLab(d,CID_HHeadDescentIsOff);
+ sprintf( buffer, "%d", info.hhead_descent );
+ uc_strcpy(ubuf,buffer);
+ GGadgetSetTitle(GWidgetGetControl(d->gw,CID_HHeadDescent),ubuf);
+}
+
+static char *mathparams[] = {
+/* GT: TeX parameters for math fonts. "Num" means numerator, "Denom" */
+/* GT: means denominator, "Sup" means superscript, "Sub" means subscript */
+ N_("Num1:"),
+ N_("Num2:"), N_("Num3:"), N_("Denom1:"),
+ N_("Denom2:"), N_("Sup1:"), N_("Sup2:"), N_("Sup3:"), N_("Sub1:"), N_("Sub2:"),
+ N_("SupDrop:"), N_("SubDrop:"), N_("Delim1:"), N_("Delim2:"), N_("Axis Ht:"),
+ 0 };
+static char *mathpopups[] = { N_("Amount to raise baseline for numerators in display styles"),
+ N_("Amount to raise baseline for numerators in non-display styles"),
+ N_("Amount to raise baseline for numerators in non-display atop styles"),
+ N_("Amount to lower baseline for denominators in display styles"),
+ N_("Amount to lower baseline for denominators in non-display styles"),
+ N_("Amount to raise baseline for superscripts in display styles"),
+ N_("Amount to raise baseline for superscripts in non-display styles"),
+ N_("Amount to raise baseline for superscripts in modified styles"),
+ N_("Amount to lower baseline for subscripts in display styles"),
+ N_("Amount to lower baseline for subscripts in non-display styles"),
+ N_("Amount above top of large box to place baseline of superscripts"),
+ N_("Amount below bottom of large box to place baseline of subscripts"),
+ N_("Size of comb delimiters in display styles"),
+ N_("Size of comb delimiters in non-display styles"),
+ N_("Height of fraction bar above base line"),
+ 0 };
+/* GT: Default Rule Thickness. A rule being a typographic term for a straight */
+/* GT: black line on a printed page. */
+static char *extparams[] = { N_("Def Rule Thick:"),
+/* GT: I don't really understand these "Big Op Space" things. They have */
+/* GT: something to do with TeX and are roughly defined a few strings down */
+ N_("Big Op Space1:"),
+ N_("Big Op Space2:"),
+ N_("Big Op Space3:"),
+ N_("Big Op Space4:"),
+ N_("Big Op Space5:"), 0 };
+static char *extpopups[] = { N_("Default thickness of over and overline bars"),
+ N_("The minimum glue space above a large displayed operator"),
+ N_("The minimum glue space below a large displayed operator"),
+ N_("The minimum distance between a limit's baseline and a large displayed\noperator when the limit is above the operator"),
+ N_("The minimum distance between a limit's baseline and a large displayed\noperator when the limit is below the operator"),
+ N_("The extra glue place above and below displayed limits"),
+ 0 };
+
+static int mp_e_h(GWindow gw, GEvent *event) {
+ int i;
+
+ if ( event->type==et_close ) {
+ struct gfi_data *d = GDrawGetUserData(gw);
+ d->mpdone = true;
+ } else if ( event->type == et_char ) {
+return( false );
+ } else if ( event->type==et_controlevent && event->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *d = GDrawGetUserData(gw);
+ if ( GGadgetGetCid(event->u.control.g)) {
+ int err=false;
+ double em = (d->sf->ascent+d->sf->descent), val;
+ char **params;
+ if ( GGadgetIsChecked(GWidgetGetControl(d->gw,CID_TeXMathSym)) )
+ params = mathparams;
+ else
+ params = extparams;
+ for ( i=0; params[i]!=0 && !err; ++i ) {
+ val = GetReal8(gw,CID_TeX+i,params[i],&err);
+ if ( !err )
+ d->texdata.params[i+7] = rint( val/em * (1<<20) );
+ }
+ if ( !err )
+ d->mpdone = true;
+ } else
+ d->mpdone = true;
+ }
+return( true );
+}
+
+static int GFI_MoreParams(GGadget *g, GEvent *e) {
+ int tot;
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GGadgetCreateData txgcd[35];
+ GTextInfo txlabel[35];
+ int i,y,k;
+ char **params, **popups;
+ char values[20][20];
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ if ( GGadgetIsChecked(GWidgetGetControl(d->gw,CID_TeXText)) )
+return( true );
+ else if ( GGadgetIsChecked(GWidgetGetControl(d->gw,CID_TeXMathSym)) ) {
+ tot = 22-7;
+ params = mathparams;
+ popups = mathpopups;
+ } else {
+ tot = 13-7;
+ params = extparams;
+ popups = extpopups;
+ }
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.is_dlg = true;
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+/* GT: More Parameters */
+ wattrs.utf8_window_title = _("More Params");
+ pos.x = pos.y = 0;
+ pos.width =GDrawPointsToPixels(NULL,GGadgetScale(180));
+ pos.height = GDrawPointsToPixels(NULL,tot*26+60);
+ gw = GDrawCreateTopWindow(NULL,&pos,mp_e_h,d,&wattrs);
+
+ memset(&txlabel,0,sizeof(txlabel));
+ memset(&txgcd,0,sizeof(txgcd));
+
+ k=0; y = 10;
+ for ( i=0; params[i]!=0; ++i ) {
+ txlabel[k].text = (unichar_t *) params[i];
+ txlabel[k].text_is_1byte = true;
+ txgcd[k].gd.label = &txlabel[k];
+ txgcd[k].gd.pos.x = 10; txgcd[k].gd.pos.y = y+4;
+ txgcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ txgcd[k].gd.popup_msg = (unichar_t *) popups[i];
+ txgcd[k++].creator = GLabelCreate;
+
+ sprintf( values[i], "%g", d->texdata.params[i+7]*(double) (d->sf->ascent+d->sf->descent)/(double) (1<<20));
+ txlabel[k].text = (unichar_t *) values[i];
+ txlabel[k].text_is_1byte = true;
+ txgcd[k].gd.label = &txlabel[k];
+ txgcd[k].gd.pos.x = 85; txgcd[k].gd.pos.y = y;
+ txgcd[k].gd.pos.width = 75;
+ txgcd[k].gd.flags = gg_visible | gg_enabled;
+ txgcd[k].gd.cid = CID_TeX + i;
+ txgcd[k++].creator = GTextFieldCreate;
+ y += 26;
+ }
+
+ txgcd[k].gd.pos.x = 30-3; txgcd[k].gd.pos.y = GDrawPixelsToPoints(NULL,pos.height)-35-3;
+ txgcd[k].gd.pos.width = -1; txgcd[k].gd.pos.height = 0;
+ txgcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ txlabel[k].text = (unichar_t *) _("_OK");
+ txlabel[k].text_is_1byte = true;
+ txlabel[k].text_in_resource = true;
+ txgcd[k].gd.label = &txlabel[k];
+ txgcd[k].gd.cid = true;
+ txgcd[k++].creator = GButtonCreate;
+
+ txgcd[k].gd.pos.x = -30; txgcd[k].gd.pos.y = txgcd[k-1].gd.pos.y+3;
+ txgcd[k].gd.pos.width = -1; txgcd[k].gd.pos.height = 0;
+ txgcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ txlabel[k].text = (unichar_t *) _("_Cancel");
+ txlabel[k].text_is_1byte = true;
+ txlabel[k].text_in_resource = true;
+ txgcd[k].gd.label = &txlabel[k];
+ txgcd[k].gd.cid = false;
+ txgcd[k++].creator = GButtonCreate;
+
+ txgcd[k].gd.pos.x = 2; txgcd[k].gd.pos.y = 2;
+ txgcd[k].gd.pos.width = pos.width-4; txgcd[k].gd.pos.height = pos.height-4;
+ txgcd[k].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
+ txgcd[k].creator = GGroupCreate;
+
+ GGadgetsCreate(gw,txgcd);
+ d->mpdone = false;
+ GDrawSetVisible(gw,true);
+
+ while ( !d->mpdone )
+ GDrawProcessOneEvent(NULL);
+ GDrawDestroyWindow(gw);
+ }
+return( true );
+}
+
+static int GFI_TeXChanged(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ if ( GGadgetGetCid(g)==CID_TeXText ) {
+ GGadgetSetTitle8(GWidgetGetControl(d->gw,CID_TeXExtraSpLabel),
+/* GT: Extra Space */
+ _("Extra Sp:"));
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_MoreParams),false);
+ } else {
+ GGadgetSetTitle8(GWidgetGetControl(d->gw,CID_TeXExtraSpLabel),
+ _("Math Sp:"));
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_MoreParams),true);
+ }
+ }
+return( true );
+}
+
+static void DefaultTeX(struct gfi_data *d) {
+ char buffer[20];
+ int i;
+ SplineFont *sf = d->sf;
+
+ d->tex_set = true;
+
+ if ( sf->texdata.type==tex_unset ) {
+ TeXDefaultParams(sf);
+ d->texdata = sf->texdata;
+ }
+
+ for ( i=0; i<7; ++i ) {
+ sprintf( buffer,"%g", d->texdata.params[i]*(sf->ascent+sf->descent)/(double) (1<<20));
+ GGadgetSetTitle8(GWidgetGetControl(d->gw,CID_TeX+i),buffer);
+ }
+ if ( sf->texdata.type==tex_math )
+ GGadgetSetChecked(GWidgetGetControl(d->gw,CID_TeXMathSym), true);
+ else if ( sf->texdata.type == tex_mathext )
+ GGadgetSetChecked(GWidgetGetControl(d->gw,CID_TeXMathExt), true);
+ else {
+ GGadgetSetChecked(GWidgetGetControl(d->gw,CID_TeXText), true);
+ GGadgetSetTitle8(GWidgetGetControl(d->gw,CID_TeXExtraSpLabel),
+/* GT: Extra Space */
+ _("Extra Sp:"));
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_MoreParams),false);
+ }
+}
+
+static int GFI_MacAutomatic(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ int autom = GGadgetIsChecked(GWidgetGetControl(d->gw,CID_MacAutomatic));
+ GGadgetSetEnabled(GWidgetGetControl(d->gw,CID_MacStyles),!autom);
+ }
+return( true );
+}
+
+static void FigureUnicode(struct gfi_data *d) {
+ int includeempties = GGadgetIsChecked(GWidgetGetControl(d->gw,CID_UnicodeEmpties));
+ GGadget *list = GWidgetGetControl(d->gw,CID_Unicode);
+ struct rangeinfo *ri;
+ int cnt, i;
+ GTextInfo **ti;
+ char buffer[200];
+
+ GGadgetClearList(list);
+ ri = SFUnicodeRanges(d->sf,(includeempties?ur_includeempty:0)|ur_sortbyunicode);
+ if ( ri==NULL ) cnt=0;
+ else
+ for ( cnt=0; ri[cnt].range!=NULL; ++cnt );
+
+ ti = galloc((cnt+1) * sizeof( GTextInfo * ));
+ for ( i=0; i<cnt; ++i ) {
+ if ( ri[i].range->first==-1 )
+ snprintf( buffer, sizeof(buffer),
+ "%s %d/0", _(ri[i].range->name), ri[i].cnt);
+ else
+ snprintf( buffer, sizeof(buffer),
+ "%s U+%04X-U+%04X %d/%d",
+ _(ri[i].range->name),
+ (int) ri[i].range->first, (int) ri[i].range->last,
+ ri[i].cnt, ri[i].range->actual );
+ ti[i] = gcalloc(1,sizeof(GTextInfo));
+ ti[i]->fg = ti[i]->bg = COLOR_DEFAULT;
+ ti[i]->text = utf82u_copy(buffer);
+ ti[i]->userdata = ri[i].range;
+ }
+ ti[i] = gcalloc(1,sizeof(GTextInfo));
+ GGadgetSetList(list,ti,false);
+ free(ri);
+}
+
+static int GFI_UnicodeRangeChange(GGadget *g, GEvent *e) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ GTextInfo *ti = GGadgetGetListItemSelected(g);
+ struct unicoderange *r;
+ int gid, first=-1;
+ SplineFont *sf = d->sf;
+ FontView *fv = sf->fv;
+ EncMap *map = fv->map;
+ int i, enc;
+
+ if ( ti==NULL )
+return( true );
+ if ( e->type!=et_controlevent ||
+ (e->u.control.subtype != et_listselected &&e->u.control.subtype != et_listdoubleclick))
+return( true );
+
+ r = ti->userdata;
+
+ for ( i=0; i<map->enccount; ++i )
+ fv->selected[i] = 0;
+
+ if ( e->u.control.subtype == et_listselected ) {
+ for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( sf->glyphs[gid]!=NULL ) {
+ enc = map->backmap[gid];
+ if ( sf->glyphs[gid]->unicodeenc>=r->first && sf->glyphs[gid]->unicodeenc<=r->last &&
+ enc!=-1 ) {
+ if ( first==-1 || enc<first ) first = enc;
+ fv->selected[enc] = true;
+ }
+ }
+ } else if ( e->u.control.subtype == et_listdoubleclick && !r->unassigned ) {
+ char *found = gcalloc(r->last-r->first+1,1);
+ for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( sf->glyphs[gid]!=NULL ) {
+ int u = sf->glyphs[gid]->unicodeenc;
+ if ( u>=r->first && u<=r->last ) {
+ found[u-r->first] = true;
+ }
+ }
+ for ( i=0; i<=r->last-r->first; ++i ) {
+ if ( isunicodepointassigned(i+r->first) && !found[i] ) {
+ enc = EncFromUni(i+r->first,map->enc);
+ if ( enc!=-1 ) {
+ if ( first==-1 || enc<first ) first = enc;
+ fv->selected[enc] = true;
+ }
+ }
+ }
+ free(found);
+ }
+ if ( first==-1 ) {
+ GDrawBeep(NULL);
+ } else {
+ FVScrollToChar(fv,first);
+ }
+ GDrawRequestExpose(fv->v,NULL,false);
+return( true );
+}
+
+static int GFI_UnicodeEmptiesChange(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ FigureUnicode(d);
+ }
+return( true );
+}
+
+static int GFI_AspectChange(GGadget *g, GEvent *e) {
+ if ( e==NULL || (e->type==et_controlevent && e->u.control.subtype == et_radiochanged )) {
+ struct gfi_data *d = GDrawGetUserData(GGadgetGetWindow(g));
+ int new_aspect = GTabSetGetSel(g);
+ int rows;
+
+ if ( d->old_aspect == d->tn_aspect )
+ GMatrixEditGet(GWidgetGetControl(d->gw,CID_TNames), &rows);
+ if ( !d->ttf_set && new_aspect == d->ttfv_aspect )
+ TTFSetup(d);
+ else if ( !d->names_set && new_aspect == d->tn_aspect ) {
+ TTFNames_Resort(d);
+ d->names_set = true;
+ } else if ( !d->tex_set && new_aspect == d->tx_aspect )
+ DefaultTeX(d);
+ else if ( new_aspect == d->unicode_aspect )
+ FigureUnicode(d);
+ d->old_aspect = new_aspect;
+ }
+return( true );
+}
+
+static int e_h(GWindow gw, GEvent *event) {
+ if ( event->type==et_close ) {
+ struct gfi_data *d = GDrawGetUserData(gw);
+ GFI_CancelClose(d);
+ } else if ( event->type==et_destroy ) {
+ struct gfi_data *d = GDrawGetUserData(gw);
+ free(d);
+ } else if ( event->type==et_char ) {
+return( GFI_Char(GDrawGetUserData(gw),event));
+ }
+return( true );
+}
+
+static void GFI_InitMarkClasses(struct gfi_data *d) {
+ SplineFont *sf = d->sf;
+ int i;
+
+ d->mark_class_cnt = sf->mark_class_cnt;
+ if ( d->mark_class_cnt!=0 ) {
+ d->mark_classes = galloc(d->mark_class_cnt*sizeof(char *));
+ d->mark_class_names = galloc(d->mark_class_cnt*sizeof(unichar_t *));
+ d->mark_classes[0] = NULL; d->mark_class_names[0] = NULL;
+ for ( i=1; i<d->mark_class_cnt; ++i ) {
+ d->mark_classes[i] = copy(sf->mark_classes[i]);
+ d->mark_class_names[i] = copy(sf->mark_class_names[i]);
+ }
+ }
+}
+
+static void LookupSetup(struct lkdata *lk,OTLookup *lookups) {
+ int cnt, subcnt;
+ OTLookup *otl;
+ struct lookup_subtable *sub;
+
+ for ( cnt=0, otl=lookups; otl!=NULL; ++cnt, otl=otl->next );
+ lk->cnt = cnt; lk->max = cnt+10;
+ lk->all = gcalloc(lk->max,sizeof(struct lkinfo));
+ for ( cnt=0, otl=lookups; otl!=NULL; ++cnt, otl=otl->next ) {
+ lk->all[cnt].lookup = otl;
+ for ( subcnt=0, sub=otl->subtables; sub!=NULL; ++subcnt, sub=sub->next );
+ lk->all[cnt].subtable_cnt = subcnt; lk->all[cnt].subtable_max = subcnt+10;
+ lk->all[cnt].subtables = gcalloc(lk->all[cnt].subtable_max,sizeof(struct lksubinfo));
+ for ( subcnt=0, sub=otl->subtables; sub!=NULL; ++subcnt, sub=sub->next )
+ lk->all[cnt].subtables[subcnt].subtable = sub;
+ }
+}
+
+static void LookupInfoFree(struct lkdata *lk) {
+ int cnt;
+
+ for ( cnt=0; cnt<lk->cnt; ++cnt )
+ free(lk->all[cnt].subtables);
+ free(lk->all);
+}
+
+#define LK_MARGIN 2
+
+struct selection_bits {
+ int lookup_cnt, sub_cnt; /* Number of selected lookups, and selected sub tables */
+ int a_lookup, a_sub; /* The index of one of those lookups, or subtables */
+ int a_sub_lookup; /* the index of the lookup containing a_sub */
+ int any_first, any_last; /* Whether any of the selected items is first or last in its catagory */
+ int sub_table_mergeable; /* Can we merge the selected subtables? */
+ int lookup_mergeable; /* Can we merge the selected lookups? */
+};
+
+static void LookupParseSelection(struct lkdata *lk, struct selection_bits *sel) {
+ int lookup_cnt, sub_cnt, any_first, any_last, all_one_lookup;
+ int a_lookup, a_sub, a_sub_lookup;
+ int sub_mergeable, lookup_mergeable;
+ int i,j;
+
+ lookup_cnt = sub_cnt = any_first = any_last = 0;
+ all_one_lookup = a_lookup = a_sub = a_sub_lookup = -1;
+ sub_mergeable = lookup_mergeable = true;
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ if ( lk->all[i].selected ) {
+ ++lookup_cnt;
+ if ( a_lookup==-1 )
+ a_lookup = i;
+ else if ( lk->all[i].lookup->lookup_type!=lk->all[a_lookup].lookup->lookup_type ||
+ lk->all[i].lookup->lookup_flags!=lk->all[a_lookup].lookup->lookup_flags )
+ lookup_mergeable = false;
+ if ( i==0 ) any_first=true;
+ if ( i==lk->cnt-1 ) any_last=true;
+ }
+ if ( lk->all[i].open ) {
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].deleted )
+ continue;
+ if ( lk->all[i].subtables[j].selected ) {
+ ++sub_cnt;
+ if ( a_sub==-1 ) {
+ a_sub = j; a_sub_lookup = i;
+ }
+ if ( j==0 ) any_first = true;
+ if ( j==lk->all[i].subtable_cnt-1 ) any_last = true;
+ if ( lk->all[i].subtables[j].subtable->kc!=NULL ||
+ lk->all[i].subtables[j].subtable->fpst!=NULL ||
+ lk->all[i].subtables[j].subtable->sm!=NULL )
+ sub_mergeable = false;
+ if ( all_one_lookup==-1 )
+ all_one_lookup = i;
+ else if ( all_one_lookup!=i )
+ all_one_lookup = -2;
+ }
+ }
+ }
+ }
+
+ sel->lookup_cnt = lookup_cnt;
+ sel->sub_cnt = sub_cnt;
+ sel->a_lookup = a_lookup;
+ sel->a_sub = a_sub;
+ sel->a_sub_lookup = a_sub_lookup;
+ sel->any_first = any_first;
+ sel->any_last = any_last;
+ sel->sub_table_mergeable = sub_mergeable && all_one_lookup && sub_cnt>=2 && lookup_cnt==0;
+ sel->lookup_mergeable = lookup_mergeable && lookup_cnt>=2 && sub_cnt==0;
+}
+
+void GFI_LookupEnableButtons(struct gfi_data *gfi, int isgpos) {
+ struct lkdata *lk = &gfi->tables[isgpos];
+ struct selection_bits sel;
+ FontView *ofv;
+
+ LookupParseSelection(lk,&sel);
+
+ GGadgetSetEnabled(GWidgetGetControl(gfi->gw,CID_LookupTop),!sel.any_first &&
+ sel.lookup_cnt+sel.sub_cnt==1);
+ GGadgetSetEnabled(GWidgetGetControl(gfi->gw,CID_LookupUp),!sel.any_first &&
+ sel.lookup_cnt+sel.sub_cnt!=0);
+ GGadgetSetEnabled(GWidgetGetControl(gfi->gw,CID_LookupDown),!sel.any_last &&
+ sel.lookup_cnt+sel.sub_cnt!=0);
+ GGadgetSetEnabled(GWidgetGetControl(gfi->gw,CID_LookupBottom),!sel.any_last &&
+ sel.lookup_cnt+sel.sub_cnt==1);
+ GGadgetSetEnabled(GWidgetGetControl(gfi->gw,CID_AddLookup),
+ (sel.lookup_cnt+sel.sub_cnt<=1));
+ GGadgetSetEnabled(GWidgetGetControl(gfi->gw,CID_AddSubtable),
+ (sel.lookup_cnt==1 && sel.sub_cnt<=1) || (sel.lookup_cnt==0 && sel.sub_cnt==1));
+ GGadgetSetEnabled(GWidgetGetControl(gfi->gw,CID_EditMetadata),
+ (sel.lookup_cnt==1 && sel.sub_cnt==0) ||
+ (sel.lookup_cnt==0 && sel.sub_cnt==1));
+ GGadgetSetEnabled(GWidgetGetControl(gfi->gw,CID_EditSubtable),sel.lookup_cnt==0 &&
+ sel.sub_cnt==1);
+ GGadgetSetEnabled(GWidgetGetControl(gfi->gw,CID_DeleteLookup),sel.lookup_cnt!=0 ||
+ sel.sub_cnt!=0);
+ GGadgetSetEnabled(GWidgetGetControl(gfi->gw,CID_MergeLookup),
+ (sel.lookup_cnt>=2 && sel.sub_cnt==0 && sel.lookup_mergeable) ||
+ (sel.lookup_cnt==0 && sel.sub_cnt>=2 && sel.sub_table_mergeable));
+ GGadgetSetEnabled(GWidgetGetControl(gfi->gw,CID_RevertLookups),true);
+ GGadgetSetEnabled(GWidgetGetControl(gfi->gw,CID_LookupSort),lk->cnt>1 );
+
+ for ( ofv=fv_list; ofv!=NULL; ofv = ofv->next ) {
+ SplineFont *osf = ofv->sf;
+ if ( osf->cidmaster ) osf = osf->cidmaster;
+ if ( osf==gfi->sf || gfi->sf->cidmaster==osf )
+ continue;
+ if ( (isgpos && osf->gpos_lookups!=NULL) || (!isgpos && osf->gsub_lookups!=NULL) )
+ break;
+ }
+ GGadgetSetEnabled(GWidgetGetControl(gfi->gw,CID_ImportLookups),ofv!=NULL);
+}
+
+void GFI_LookupScrollbars(struct gfi_data *gfi, int isgpos, int refresh) {
+ int lcnt, i,j;
+ int width=0, wmax;
+ GWindow gw = GDrawableGetWindow(GWidgetGetControl(gfi->gw,CID_LookupWin+isgpos));
+ struct lkdata *lk = &gfi->tables[isgpos];
+ GGadget *vsb = GWidgetGetControl(gfi->gw,CID_LookupVSB+isgpos);
+ GGadget *hsb = GWidgetGetControl(gfi->gw,CID_LookupHSB+isgpos);
+ int off_top, off_left;
+
+ GDrawSetFont(gw,gfi->font);
+ lcnt = 0;
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ ++lcnt;
+ wmax = GDrawGetText8Width(gw,lk->all[i].lookup->lookup_name,-1,NULL);
+ if ( wmax > width ) width = wmax;
+ if ( lk->all[i].open ) {
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].deleted )
+ continue;
+ ++lcnt;
+ wmax = gfi->fh+GDrawGetText8Width(gw,lk->all[i].subtables[j].subtable->subtable_name,-1,NULL);
+ if ( wmax > width ) width = wmax;
+ }
+ }
+ }
+ width += gfi->fh;
+ GScrollBarSetBounds(vsb,0,lcnt,(gfi->lkheight-2*LK_MARGIN)/gfi->fh);
+ GScrollBarSetBounds(hsb,0,width,gfi->lkwidth-2*LK_MARGIN);
+ off_top = lk->off_top;
+ if ( off_top+((gfi->lkheight-2*LK_MARGIN)/gfi->fh) > lcnt )
+ off_top = lcnt - (gfi->lkheight-2*LK_MARGIN)/gfi->fh;
+ if ( off_top<0 )
+ off_top = 0;
+ off_left = lk->off_left;
+ if ( off_left+gfi->lkwidth-2*LK_MARGIN > width )
+ off_left = width-(gfi->lkwidth-2*LK_MARGIN);
+ if ( off_left<0 )
+ off_left = 0;
+ if ( off_top!=lk->off_top || off_left!=lk->off_left ) {
+ lk->off_top = off_top; lk->off_left = off_left;
+ GScrollBarSetPos(vsb,off_top);
+ GScrollBarSetPos(hsb,off_left);
+ refresh = true;
+ }
+ if ( refresh )
+ GDrawRequestExpose(gw,NULL,true);
+}
+
+static int LookupsHScroll(GGadget *g,GEvent *event) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ int isgpos = GGadgetGetCid(g)-CID_LookupHSB;
+ struct lkdata *lk = &gfi->tables[isgpos];
+ int newpos = lk->off_left;
+ int32 sb_min, sb_max, sb_pagesize;
+
+ if ( event->type!=et_controlevent || event->u.control.subtype != et_scrollbarchange )
+return( true );
+
+ GScrollBarGetBounds(event->u.control.g,&sb_min,&sb_max,&sb_pagesize);
+ switch( event->u.control.u.sb.type ) {
+ case et_sb_top:
+ newpos = 0;
+ break;
+ case et_sb_uppage:
+ newpos -= 9*sb_pagesize/10;
+ break;
+ case et_sb_up:
+ newpos -= sb_pagesize/15;
+ break;
+ case et_sb_down:
+ newpos += sb_pagesize/15;
+ break;
+ case et_sb_downpage:
+ newpos += 9*sb_pagesize/10;
+ break;
+ case et_sb_bottom:
+ newpos = sb_max-sb_pagesize;
+ break;
+ case et_sb_thumb:
+ case et_sb_thumbrelease:
+ newpos = event->u.control.u.sb.pos;
+ break;
+ case et_sb_halfup:
+ newpos -= sb_pagesize/30;
+ break;
+ case et_sb_halfdown:
+ newpos += sb_pagesize/30;
+ break;
+ }
+ if ( newpos>sb_max-sb_pagesize )
+ newpos = sb_max-sb_pagesize;
+ if ( newpos<0 ) newpos = 0;
+ if ( newpos!=lk->off_left ) {
+ lk->off_left = newpos;
+ GScrollBarSetPos(event->u.control.g,newpos);
+ GDrawRequestExpose(GDrawableGetWindow(GWidgetGetControl(gfi->gw,CID_LookupWin+isgpos)),NULL,true);
+ }
+return( true );
+}
+
+static int LookupsVScroll(GGadget *g,GEvent *event) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ int isgpos = GGadgetGetCid(g)-CID_LookupVSB;
+ struct lkdata *lk = &gfi->tables[isgpos];
+ int newpos = lk->off_top;
+ int32 sb_min, sb_max, sb_pagesize;
+
+ if ( event->type!=et_controlevent || event->u.control.subtype != et_scrollbarchange )
+return( true );
+
+ GScrollBarGetBounds(event->u.control.g,&sb_min,&sb_max,&sb_pagesize);
+ switch( event->u.control.u.sb.type ) {
+ case et_sb_top:
+ newpos = 0;
+ break;
+ case et_sb_uppage:
+ newpos -= 9*sb_pagesize/10;
+ break;
+ case et_sb_up:
+ --newpos;
+ break;
+ case et_sb_down:
+ ++newpos;
+ break;
+ case et_sb_downpage:
+ newpos += 9*sb_pagesize/10;
+ break;
+ case et_sb_bottom:
+ newpos = (sb_max-sb_pagesize);
+ break;
+ case et_sb_thumb:
+ case et_sb_thumbrelease:
+ newpos = event->u.control.u.sb.pos;
+ break;
+ }
+ if ( newpos>(sb_max-sb_pagesize) )
+ newpos = (sb_max-sb_pagesize);
+ if ( newpos<0 ) newpos = 0;
+ if ( newpos!=lk->off_top ) {
+ /*int diff = newpos-lk->off_top;*/
+ lk->off_top = newpos;
+ GScrollBarSetPos(event->u.control.g,newpos);
+ /*GDrawScroll(GDrawableGetWindow(GWidgetGetControl(gfi->gw,CID_LookupWin+isgpos)),NULL,0,diff*gfi->fh);*/
+ GDrawRequestExpose(GDrawableGetWindow(GWidgetGetControl(gfi->gw,CID_LookupWin+isgpos)),NULL,true);
+ }
+return( true );
+}
+
+static int GFI_LookupOrder(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ int isgpos = GTabSetGetSel(GWidgetGetControl(gfi->gw,CID_Lookups));
+ struct lkdata *lk = &gfi->tables[isgpos];
+ int i,j,k;
+ struct lkinfo temp;
+ struct lksubinfo temp2;
+ int cid = GGadgetGetCid(g);
+ GWindow gw = GDrawableGetWindow(GWidgetGetControl(gfi->gw,CID_LookupWin+isgpos));
+
+ if ( cid==CID_LookupTop ) {
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ if ( lk->all[i].selected ) {
+ temp = lk->all[i];
+ for ( k=i-1; k>=0; --k )
+ lk->all[k+1] = lk->all[k];
+ lk->all[0] = temp;
+ goto done;
+ }
+ if ( lk->all[i].open ) {
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].deleted )
+ continue;
+ if ( lk->all[i].subtables[j].selected ) {
+ temp2 = lk->all[i].subtables[j];
+ for ( k=j-1; k>=0; --k )
+ lk->all[i].subtables[k+1] = lk->all[i].subtables[k];
+ lk->all[i].subtables[0] = temp2;
+ goto done;
+ }
+ }
+ }
+ }
+ } else if ( cid==CID_LookupBottom ) {
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ if ( lk->all[i].selected ) {
+ temp = lk->all[i];
+ for ( k=i; k<lk->cnt-1; --k )
+ lk->all[k] = lk->all[k+1];
+ lk->all[lk->cnt-1] = temp;
+ goto done;
+ }
+ if ( lk->all[i].open ) {
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].deleted )
+ continue;
+ if ( lk->all[i].subtables[j].selected ) {
+ temp2 = lk->all[i].subtables[j];
+ for ( k=j; k<lk->all[i].subtable_cnt-1; --k )
+ lk->all[i].subtables[k] = lk->all[i].subtables[k+1];
+ lk->all[i].subtables[lk->all[i].subtable_cnt-1] = temp2;
+ goto done;
+ }
+ }
+ }
+ }
+ } else if ( cid==CID_LookupUp ) {
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ if ( lk->all[i].selected && i!=0 ) {
+ temp = lk->all[i];
+ lk->all[i] = lk->all[i-1];
+ lk->all[i-1] = temp;
+ }
+ if ( lk->all[i].open ) {
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].deleted )
+ continue;
+ if ( lk->all[i].subtables[j].selected && j!=0 ) {
+ temp2 = lk->all[i].subtables[j];
+ lk->all[i].subtables[j] = lk->all[i].subtables[j-1];
+ lk->all[i].subtables[j-1] = temp2;
+ }
+ }
+ }
+ }
+ } else if ( cid==CID_LookupDown ) {
+ for ( i=lk->cnt-1; i>=0; --i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ if ( lk->all[i].selected && i!=lk->cnt-1 ) {
+ temp = lk->all[i];
+ lk->all[i] = lk->all[i+1];
+ lk->all[i+1] = temp;
+ }
+ if ( lk->all[i].open ) {
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].deleted )
+ continue;
+ if ( lk->all[i].subtables[j].selected && j!=lk->all[i].subtable_cnt-1 ) {
+ temp2 = lk->all[i].subtables[j];
+ lk->all[i].subtables[j] = lk->all[i].subtables[j+1];
+ lk->all[i].subtables[j+1] = temp2;
+ }
+ }
+ }
+ }
+ }
+ done:
+ GFI_LookupEnableButtons(gfi,isgpos);
+ GDrawRequestExpose(gw,NULL,true);
+ }
+return( true );
+}
+
+static int GFI_LookupSort(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ int isgpos = GTabSetGetSel(GWidgetGetControl(gfi->gw,CID_Lookups));
+ struct lkdata *lk = &gfi->tables[isgpos];
+ struct lkinfo temp;
+ int i,j;
+
+ for ( i=0; i<lk->cnt; ++i ) {
+ int order = FeatureOrderId(isgpos,lk->all[i].lookup->features);
+ for ( j=i+1; j<lk->cnt; ++j ) {
+ int jorder = FeatureOrderId(isgpos,lk->all[j].lookup->features);
+ if ( order>jorder) {
+ temp = lk->all[i];
+ lk->all[i] = lk->all[j];
+ lk->all[j] = temp;
+ order = jorder;
+ }
+ }
+ }
+ GFI_LookupEnableButtons(gfi,isgpos);
+ }
+return( true );
+}
+
+/* ??? *//* How about a series of buttons to show only by lookup_type, feat-tag, script-tag */
+
+void GFI_CCDEnd(struct gfi_data *d) {
+
+ d->ccd = NULL;
+}
+
+void GFI_FinishContextNew(struct gfi_data *d,FPST *fpst, int success) {
+ OTLookup *otl;
+ struct lookup_subtable *sub, *prev;
+ FPST *ftest, *fprev;
+
+ if ( !success ) {
+ /* We can't allow incomplete FPSTs to float around */
+ /* If they didn't fill it in, delete it */
+ otl = fpst->subtable->lookup;
+ prev = NULL;
+ for ( sub=otl->subtables; sub!=NULL && sub!=fpst->subtable; prev = sub, sub=sub->next );
+ if ( sub!=NULL ) {
+ if ( prev==NULL )
+ otl->subtables = sub->next;
+ else
+ prev->next = sub->next;
+ free(sub->subtable_name);
+ chunkfree(sub,sizeof(struct lookup_subtable));
+ }
+ fprev = NULL;
+ for ( ftest=d->sf->possub; ftest!=NULL && ftest!=fpst; fprev = ftest, ftest=ftest->next );
+ if ( ftest!=NULL ) {
+ if ( fprev==NULL )
+ d->sf->possub = fpst->next;
+ else
+ fprev->next = fpst->next;
+ }
+
+ chunkfree(fpst,sizeof(FPST));
+ }
+}
+
+void GFI_SMDEnd(struct gfi_data *d) {
+
+ d->smd = NULL;
+}
+
+void GFI_FinishSMNew(struct gfi_data *d,ASM *sm, int success, int isnew) {
+ OTLookup *otl;
+ struct lookup_subtable *sub, *prev;
+ ASM *smtest, *smprev;
+
+ if ( !success && isnew ) {
+ /* We can't allow incomplete state machines floating around */
+ /* If they didn't fill it in, delete it */
+ otl = sm->subtable->lookup;
+ prev = NULL;
+ for ( sub=otl->subtables; sub!=NULL && sub!=sm->subtable; prev = sub, sub=sub->next );
+ if ( sub!=NULL ) {
+ if ( prev==NULL )
+ otl->subtables = sub->next;
+ else
+ prev->next = sub->next;
+ free(sub->subtable_name);
+ chunkfree(sub,sizeof(struct lookup_subtable));
+ }
+ smprev = NULL;
+ for ( smtest=d->sf->sm; smtest!=NULL && smtest!=sm; smprev = smtest, smtest=smtest->next );
+ if ( smtest!=NULL ) {
+ if ( smprev==NULL )
+ d->sf->sm = sm->next;
+ else
+ smprev->next = sm->next;
+ }
+ chunkfree(sm,sizeof(ASM));
+ }
+}
+
+static void LookupSubtableContents(struct gfi_data *gfi,int isgpos) {
+ struct lkdata *lk = &gfi->tables[isgpos];
+ int i,j;
+
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ if ( lk->all[i].open ) {
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].deleted )
+ continue;
+ if ( lk->all[i].subtables[j].selected ) {
+ _LookupSubtableContents(gfi->sf,lk->all[i].subtables[j].subtable,NULL);
+return;
+ }
+ }
+ }
+ }
+}
+
+static int GFI_LookupEditSubtableContents(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ int isgpos = GTabSetGetSel(GWidgetGetControl(gfi->gw,CID_Lookups));
+ LookupSubtableContents(gfi,isgpos);
+ }
+return( true );
+}
+
+static int GFI_LookupAddLookup(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ int isgpos = GTabSetGetSel(GWidgetGetControl(gfi->gw,CID_Lookups));
+ struct lkdata *lk = &gfi->tables[isgpos];
+ int i,j,k,lcnt;
+ OTLookup *otl = chunkalloc(sizeof(OTLookup));
+
+ if ( !EditLookup(otl,isgpos,gfi->sf)) {
+ chunkfree(otl,sizeof(OTLookup));
+return( true );
+ }
+ for ( i=lk->cnt-1; i>=0; --i ) {
+ if ( !lk->all[i].deleted && lk->all[i].selected ) {
+ lk->all[i].selected = false;
+ break;
+ }
+ if ( !lk->all[i].deleted && lk->all[i].open ) {
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j )
+ if ( !lk->all[i].subtables[j].deleted &&
+ lk->all[i].subtables[j].selected ) {
+ lk->all[i].subtables[j].selected = false;
+ break;
+ }
+ if ( j<lk->all[i].subtable_cnt )
+ break;
+ }
+ }
+ if ( lk->cnt>=lk->max )
+ lk->all = grealloc(lk->all,(lk->max+=10)*sizeof(struct lkinfo));
+ for ( k=lk->cnt; k>i+1; --k )
+ lk->all[k] = lk->all[k-1];
+ memset(&lk->all[k],0,sizeof(struct lkinfo));
+ lk->all[k].lookup = otl;
+ lk->all[k].new = true;
+ lk->all[k].selected = true;
+ ++lk->cnt;
+ if ( isgpos ) {
+ otl->next = gfi->sf->gpos_lookups;
+ gfi->sf->gpos_lookups = otl;
+ } else {
+ otl->next = gfi->sf->gsub_lookups;
+ gfi->sf->gsub_lookups = otl;
+ }
+
+ /* Make sure the window is scrolled to display the new lookup */
+ lcnt=0;
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ if ( i==k )
+ break;
+ ++lcnt;
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].deleted )
+ continue;
+ ++lcnt;
+ }
+ }
+ if ( lcnt<lk->off_top || lcnt>=lk->off_top+(gfi->lkheight-2*LK_MARGIN)/gfi->fh )
+ lk->off_top = lcnt;
+
+ GFI_LookupScrollbars(gfi,isgpos, true);
+ GFI_LookupEnableButtons(gfi,isgpos);
+ }
+return( true );
+}
+
+static int GFI_LookupAddSubtable(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ int isgpos = GTabSetGetSel(GWidgetGetControl(gfi->gw,CID_Lookups));
+ struct lkdata *lk = &gfi->tables[isgpos];
+ int i,j,k,lcnt;
+ struct lookup_subtable *sub;
+
+ lcnt = 0;
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ j = -1;
+ ++lcnt;
+ if ( lk->all[i].selected )
+ break;
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].deleted )
+ continue;
+ ++lcnt;
+ if ( lk->all[i].subtables[j].selected )
+ goto break_2_loops;
+ }
+ }
+ break_2_loops:
+ if ( i==lk->cnt )
+return( true );
+
+ sub = chunkalloc(sizeof(struct lookup_subtable));
+ sub->lookup = lk->all[i].lookup;
+ if ( !EditSubtable(sub,isgpos,gfi->sf,NULL)) {
+ chunkfree(sub,sizeof(struct lookup_subtable));
+return( true );
+ }
+ if ( lk->all[i].subtable_cnt>=lk->all[i].subtable_max )
+ lk->all[i].subtables = grealloc(lk->all[i].subtables,(lk->all[i].subtable_max+=10)*sizeof(struct lksubinfo));
+ for ( k=lk->all[i].subtable_cnt; k>j+1; --k )
+ lk->all[i].subtables[k] = lk->all[i].subtables[k-1];
+ memset(&lk->all[i].subtables[k],0,sizeof(struct lksubinfo));
+ lk->all[i].subtables[k].subtable = sub;
+ lk->all[i].subtables[k].new = true;
+ sub->next = lk->all[i].lookup->subtables;
+ lk->all[i].lookup->subtables = sub;
+ ++lk->all[i].subtable_cnt;
+
+ /* Make sure the window is scrolled to display the new subtable */
+ if ( lcnt<lk->off_top || lcnt>=lk->off_top+(gfi->lkheight-2*LK_MARGIN)/gfi->fh )
+ lk->off_top = lcnt;
+
+ GFI_LookupScrollbars(gfi,isgpos, true);
+ GFI_LookupEnableButtons(gfi,isgpos);
+ }
+return( true );
+}
+
+static int GFI_LookupEditMetadata(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ int isgpos = GTabSetGetSel(GWidgetGetControl(gfi->gw,CID_Lookups));
+ struct lkdata *lk = &gfi->tables[isgpos];
+ int i,j;
+
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ if ( lk->all[i].selected ) {
+ EditLookup(lk->all[i].lookup,isgpos,gfi->sf);
+return( true );
+ } else if ( lk->all[i].open ) {
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].deleted )
+ continue;
+ if ( lk->all[i].subtables[j].selected ) {
+ EditSubtable(lk->all[i].subtables[j].subtable,isgpos,gfi->sf,NULL);
+return( true );
+ }
+ }
+ }
+ }
+ }
+return( true );
+}
+
+static int GFI_LookupMergeLookup(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ char *buts[3];
+ int isgpos = GTabSetGetSel(GWidgetGetControl(gfi->gw,CID_Lookups));
+ struct lkdata *lk = &gfi->tables[isgpos];
+ struct selection_bits sel;
+ int i,j;
+ struct lkinfo *lkfirst;
+ struct lksubinfo *sbfirst;
+ struct lookup_subtable *sub;
+
+ LookupParseSelection(lk,&sel);
+ if ( !sel.sub_table_mergeable && !sel.lookup_mergeable )
+return( true );
+
+ buts[0] = _("Do it");
+ buts[1] = _("_Cancel");
+ buts[2] = NULL;
+ if ( gwwv_ask(_("Cannot be Undone"),(const char **) buts,0,1,_("The Merge operation cannot be reverted.\nDo it anyway?"))==1 )
+return( true );
+ if ( sel.lookup_mergeable ) {
+ lkfirst = NULL;
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].selected && !lk->all[i].deleted ) {
+ if ( lkfirst==NULL )
+ lkfirst = &lk->all[i];
+ else {
+ FLMerge(lkfirst->lookup,lk->all[i].lookup);
+ if ( lkfirst->subtable_cnt+lk->all[i].subtable_cnt >= lkfirst->subtable_max )
+ lkfirst->subtables = grealloc(lkfirst->subtables,(lkfirst->subtable_max+=lk->all[i].subtable_cnt)*sizeof(struct lksubinfo));
+ memcpy(lkfirst->subtables+lkfirst->subtable_cnt,
+ lk->all[i].subtables,lk->all[i].subtable_cnt*sizeof(struct lksubinfo));
+ lkfirst->subtable_cnt += lk->all[i].subtable_cnt;
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j )
+ lk->all[i].subtables[j].subtable->lookup = lkfirst->lookup;
+ if ( lk->all[i].lookup->subtables!=NULL ) {
+ for ( sub = lk->all[i].lookup->subtables; sub->next!=NULL; sub = sub->next );
+ sub->next = lkfirst->lookup->subtables;
+ lkfirst->lookup->subtables = lk->all[i].lookup->subtables;
+ lk->all[i].lookup->subtables = NULL;
+ }
+ lk->all[i].subtable_cnt = 0;
+ lk->all[i].deleted = true;
+ lk->all[i].open = false;
+ lk->all[i].selected = false;
+ }
+ }
+ }
+ } else if ( sel.sub_table_mergeable ) {
+ sbfirst = NULL;
+ for ( i=0; i<lk->cnt; ++i ) if ( !lk->all[i].deleted && lk->all[i].open ) {
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) if ( !lk->all[i].subtables[j].deleted ) {
+ if ( lk->all[i].subtables[j].selected ) {
+ if ( sbfirst == NULL )
+ sbfirst = &lk->all[i].subtables[j];
+ else {
+ SFSubTablesMerge(gfi->sf,sbfirst->subtable,lk->all[i].subtables[j].subtable);
+ lk->all[i].subtables[j].deleted = true;
+ lk->all[i].subtables[j].selected = false;
+ }
+ }
+ }
+ if ( sbfirst!=NULL ) /* Can only merge subtables within a lookup, so if we found anything, in a lookup that's everything */
+ break;
+ }
+ }
+ GFI_LookupScrollbars(gfi,isgpos, true);
+ GFI_LookupEnableButtons(gfi,isgpos);
+ }
+return( true );
+}
+
+static int GFI_LookupDeleteLookup(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ int isgpos = GTabSetGetSel(GWidgetGetControl(gfi->gw,CID_Lookups));
+ struct lkdata *lk = &gfi->tables[isgpos];
+ int i,j;
+
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ if ( lk->all[i].selected )
+ lk->all[i].deleted = true;
+ else if ( lk->all[i].open ) {
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].deleted )
+ continue;
+ if ( lk->all[i].subtables[j].selected )
+ lk->all[i].subtables[j].deleted = true;
+ }
+ }
+ }
+
+ GFI_LookupScrollbars(gfi,isgpos, true);
+ GFI_LookupEnableButtons(gfi,isgpos);
+ }
+
+return( true );
+}
+
+static int GFI_LookupRevertLookup(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ int isgpos = GTabSetGetSel(GWidgetGetControl(gfi->gw,CID_Lookups));
+ struct lkdata *lk = &gfi->tables[isgpos];
+ int i,j;
+
+ /* First remove any new lookups, subtables */
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].new )
+ SFRemoveLookup(gfi->sf,lk->all[i].lookup);
+ else {
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j )
+ if ( lk->all[i].subtables[j].new )
+ SFRemoveLookupSubTable(gfi->sf,lk->all[i].subtables[j].subtable);
+ }
+ }
+
+ /* Now since we didn't actually delete anything we don't need to do */
+ /* anything to resurrect them */
+
+ /* Finally we need to restore the original order. */
+ /* But that just means regenerating the lk structure. So free it and */
+ /* regenerate it */
+
+ LookupInfoFree(lk);
+ LookupSetup(lk,isgpos?gfi->sf->gpos_lookups:gfi->sf->gsub_lookups);
+
+ GFI_LookupScrollbars(gfi,isgpos, true);
+ GFI_LookupEnableButtons(gfi,isgpos);
+ }
+return( true );
+}
+
+static int import_e_h(GWindow gw, GEvent *event) {
+ int *done = GDrawGetUserData(gw);
+
+ if ( event->type==et_close ) {
+ *done = true;
+ } else if ( event->type==et_char ) {
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("fontinfo.html#Lookups");
+return( true );
+ }
+return( false );
+ } else if ( event->type==et_controlevent && event->u.control.subtype == et_buttonactivate ) {
+ switch ( GGadgetGetCid(event->u.control.g)) {
+ case CID_OK:
+ *done = 2;
+ break;
+ case CID_Cancel:
+ *done = true;
+ break;
+ }
+ }
+return( true );
+}
+
+static int GFI_LookupImportLookup(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ int isgpos = GTabSetGetSel(GWidgetGetControl(gfi->gw,CID_Lookups));
+ FontView *ofv;
+ SplineFont *osf;
+ OTLookup *otl;
+ int i, j, cnt;
+ GTextInfo *ti;
+ GGadgetCreateData gcd[7], *varray[8], *harray[7];
+ GTextInfo label[7];
+ GWindowAttrs wattrs;
+ GRect pos;
+ GWindow gw;
+ int done = 0;
+
+ /* Figure out what lookups can be imported from which (open) fonts */
+ ti = NULL;
+ for ( j=0; j<2; ++j ) {
+ for ( ofv=fv_list; ofv!=NULL; ofv=ofv->next ) {
+ osf = ofv->sf;
+ if ( osf->cidmaster ) osf = osf->cidmaster;
+ osf->ticked = false;
+ }
+ cnt = 0;
+ for ( ofv=fv_list; ofv!=NULL; ofv=ofv->next ) {
+ osf = ofv->sf;
+ if ( osf->cidmaster ) osf = osf->cidmaster;
+ if ( osf->ticked || osf==gfi->sf || osf==gfi->sf->cidmaster ||
+ ( isgpos && osf->gpos_lookups==NULL) ||
+ (!isgpos && osf->gsub_lookups==NULL) )
+ continue;
+ osf->ticked = true;
+ if ( cnt!=0 ) {
+ if ( ti )
+ ti[cnt].line = true;
+ ++cnt;
+ }
+ if ( ti ) {
+ ti[cnt].text = (unichar_t *) copy( osf->fontname );
+ ti[cnt].text_is_1byte = true;
+ ti[cnt].disabled = true;
+ ti[cnt].userdata = osf;
+ }
+ ++cnt;
+ for ( otl = isgpos ? osf->gpos_lookups : osf->gsub_lookups; otl!=NULL; otl=otl->next ) {
+ if ( ti ) {
+ ti[cnt].text = (unichar_t *) strconcat( " ", otl->lookup_name );
+ ti[cnt].text_is_1byte = true;
+ ti[cnt].userdata = otl;
+ }
+ ++cnt;
+ }
+ }
+ if ( ti==NULL )
+ ti = gcalloc((cnt+1),sizeof(GTextInfo));
+ }
+
+ memset(gcd,0,sizeof(gcd));
+ memset(label,0,sizeof(label));
+
+ i = 0;
+ label[i].text = (unichar_t *) _("Select lookups from other fonts");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.pos.x = 12; gcd[i].gd.pos.y = 6+6;
+ gcd[i].gd.flags = gg_visible | gg_enabled;
+ gcd[i].creator = GLabelCreate;
+ varray[0] = &gcd[i++]; varray[1] = NULL;
+
+ gcd[i].gd.pos.height = 12*12+6;
+ gcd[i].gd.flags = gg_enabled|gg_visible|gg_list_multiplesel|gg_utf8_popup;
+ gcd[i].gd.u.list = ti;
+ gcd[i].creator = GListCreate;
+ varray[2] = &gcd[i++]; varray[3] = NULL;
+
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[i].text = (unichar_t *) _("_Import");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.cid = CID_OK;
+ harray[0] = GCD_Glue; harray[1] = &gcd[i]; harray[2] = GCD_Glue;
+ gcd[i++].creator = GButtonCreate;
+
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[i].text = (unichar_t *) _("_Cancel");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.cid = CID_Cancel;
+ harray[3] = GCD_Glue; harray[4] = &gcd[i]; harray[5] = GCD_Glue; harray[6] = NULL;
+ gcd[i++].creator = GButtonCreate;
+
+ gcd[i].gd.flags = gg_enabled|gg_visible;
+ gcd[i].gd.u.boxelements = harray;
+ gcd[i].creator = GHBoxCreate;
+ varray[4] = &gcd[i++]; varray[5] = NULL; varray[6] = NULL;
+
+ gcd[i].gd.pos.x = gcd[i].gd.pos.y = 2;
+ gcd[i].gd.flags = gg_enabled|gg_visible;
+ gcd[i].gd.u.boxelements = varray;
+ gcd[i].creator = GHVGroupCreate;
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Import Lookup...");
+ wattrs.is_dlg = true;
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,150));
+ pos.height = GDrawPointsToPixels(NULL,193);
+ gw = GDrawCreateTopWindow(NULL,&pos,import_e_h,&done,&wattrs);
+
+ GGadgetsCreate(gw,&gcd[i]);
+ GHVBoxSetExpandableRow(gcd[i].ret,1);
+ GHVBoxSetExpandableCol(gcd[i-1].ret,gb_expandgluesame);
+ GHVBoxFitWindow(gcd[i].ret);
+ GTextInfoListFree(ti);
+ GDrawSetVisible(gw,true);
+
+ while ( !done )
+ GDrawProcessOneEvent(NULL);
+ if ( done==2 ) {
+ int32 len;
+ GTextInfo **ti = GGadgetGetList(gcd[1].ret,&len);
+ osf = NULL;
+ for ( i=0; i<len; ++i ) {
+ if ( ti[i]->disabled )
+ osf = ti[i]->userdata;
+ else if ( ti[i]->selected && ti[i]->text!=NULL )
+ OTLookupCopyInto(gfi->sf,osf,(OTLookup *) ti[i]->userdata);
+ }
+ }
+ GDrawDestroyWindow(gw);
+
+ GFI_LookupScrollbars(gfi,isgpos, true);
+ GFI_LookupEnableButtons(gfi,isgpos);
+ }
+return( true );
+}
+
+static int GFI_LookupAspectChange(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
+ struct gfi_data *gfi = GDrawGetUserData(GGadgetGetWindow(g));
+ int isgpos = GTabSetGetSel(GWidgetGetControl(gfi->gw,CID_Lookups));
+ GFI_LookupEnableButtons(gfi,isgpos);
+ }
+return( true );
+}
+
+static void LookupExpose(GWindow pixmap, struct gfi_data *gfi, int isgpos) {
+ int lcnt, i,j;
+ struct lkdata *lk = &gfi->tables[isgpos];
+ GRect r, old;
+
+ r.x = LK_MARGIN; r.width = gfi->lkwidth-2*LK_MARGIN;
+ r.y = LK_MARGIN; r.height = gfi->lkheight-2*LK_MARGIN;
+ GDrawPushClip(pixmap,&r,&old);
+ GDrawSetFont(pixmap,gfi->font);
+
+ lcnt = 0;
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ if ( lcnt>=lk->off_top ) {
+ if ( lk->all[i].selected ) {
+ r.x = LK_MARGIN; r.width = gfi->lkwidth-2*LK_MARGIN;
+ r.y = (lcnt-lk->off_top)*gfi->fh; r.height = gfi->fh;
+ GDrawFillRect(pixmap,&r,0xffff00);
+ }
+ r.x = LK_MARGIN-lk->off_left; r.width = (gfi->as&~1);
+ r.y = LK_MARGIN+(lcnt-lk->off_top)*gfi->fh; r.height = r.width;
+ GDrawDrawRect(pixmap,&r,0x000000);
+ GDrawDrawLine(pixmap,r.x+2,r.y+(r.height/2), r.x+r.width-2,r.y+(r.height/2), 0x000000);
+ if ( !lk->all[i].open )
+ GDrawDrawLine(pixmap,r.x+(r.width/2),r.y+2, r.x+(r.width/2),r.y+r.height-2, 0x000000);
+ GDrawDrawText8(pixmap,r.x+gfi->fh, r.y+gfi->as,
+ lk->all[i].lookup->lookup_name,-1,NULL,0x000000);
+ }
+ ++lcnt;
+ if ( lk->all[i].open ) {
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].deleted )
+ continue;
+ if ( lcnt>=lk->off_top ) {
+ if ( lk->all[i].subtables[j].selected ) {
+ r.x = LK_MARGIN; r.width = gfi->lkwidth-2*LK_MARGIN;
+ r.y = LK_MARGIN+(lcnt-lk->off_top)*gfi->fh; r.height = gfi->fh;
+ GDrawFillRect(pixmap,&r,0xffff00);
+ }
+ r.x = LK_MARGIN+2*gfi->fh-lk->off_left;
+ r.y = LK_MARGIN+(lcnt-lk->off_top)*gfi->fh;
+ GDrawDrawText8(pixmap,r.x, r.y+gfi->as,
+ lk->all[i].subtables[j].subtable->subtable_name,-1,NULL,0x000000);
+ }
+ ++lcnt;
+ }
+ }
+ }
+ GDrawPopClip(pixmap,&old);
+}
+
+static void LookupDeselect(struct lkdata *lk) {
+ int i,j;
+
+ for ( i=0; i<lk->cnt; ++i ) {
+ lk->all[i].selected = false;
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j )
+ lk->all[i].subtables[j].selected = false;
+ }
+}
+
+static void LookupPopup(GWindow gw,OTLookup *otl,struct lookup_subtable *sub) {
+ extern char *lookup_type_names[2][10];
+ static char popup_msg[300];
+ int pos;
+ char *lookuptype;
+ FeatureScriptLangList *fl;
+ struct scriptlanglist *sl;
+ int l;
+
+ if ( (otl->lookup_type&0xff)>= 0xf0 ) {
+ if ( otl->lookup_type==kern_statemachine )
+ lookuptype = _("Kerning State Machine");
+ else if ( otl->lookup_type==morx_indic )
+ lookuptype = _("Indic State Machine");
+ else if ( otl->lookup_type==morx_context )
+ lookuptype = _("Contextual State Machine");
+ else
+ lookuptype = _("Contextual State Machine");
+ } else if ( (otl->lookup_type>>8)<2 && (otl->lookup_type&0xff)<10 )
+ lookuptype = _(lookup_type_names[otl->lookup_type>>8][otl->lookup_type&0xff]);
+ else
+ lookuptype = S_("LookupType|Unknown");
+ snprintf(popup_msg,sizeof(popup_msg), "%s\n", lookuptype);
+ pos = strlen(popup_msg);
+
+ if ( sub!=NULL && otl->lookup_type==gpos_pair && sub->kc!=NULL ) {
+ snprintf(popup_msg+pos,sizeof(popup_msg)-pos,_("(kerning class)\n") );
+ pos += strlen( popup_msg+pos );
+ }
+
+ if ( otl->features==NULL )
+ snprintf(popup_msg+pos,sizeof(popup_msg)-pos,_("Not attached to a feature"));
+ else {
+ for ( fl=otl->features; fl!=NULL && pos<sizeof(popup_msg)-2; fl=fl->next ) {
+ snprintf(popup_msg+pos,sizeof(popup_msg)-pos,"%c%c%c%c: ",
+ fl->featuretag>>24, fl->featuretag>>16,
+ fl->featuretag>>8, fl->featuretag&0xff );
+ pos += strlen( popup_msg+pos );
+ for ( sl=fl->scripts; sl!=NULL; sl=sl->next ) {
+ snprintf(popup_msg+pos,sizeof(popup_msg)-pos,"%c%c%c%c{",
+ sl->script>>24, sl->script>>16,
+ sl->script>>8, sl->script&0xff );
+ pos += strlen( popup_msg+pos );
+ for ( l=0; l<sl->lang_cnt; ++l ) {
+ uint32 lang = l<MAX_LANG ? sl->langs[l] : sl->morelangs[l-MAX_LANG];
+ snprintf(popup_msg+pos,sizeof(popup_msg)-pos,"%c%c%c%c,",
+ lang>>24, lang>>16,
+ lang>>8, lang&0xff );
+ pos += strlen( popup_msg+pos );
+ }
+ if ( popup_msg[pos-1]==',' )
+ popup_msg[pos-1] = '}';
+ else if ( pos<sizeof(popup_msg)-2 )
+ popup_msg[pos++] = '}';
+ if ( pos<sizeof(popup_msg)-2 )
+ popup_msg[pos++] = ' ';
+ }
+ if ( pos<sizeof(popup_msg)-2 )
+ popup_msg[pos++] = '\n';
+ }
+ }
+ if ( pos>=sizeof(popup_msg) )
+ pos = sizeof(popup_msg)-1;
+ popup_msg[pos]='\0';
+ GGadgetPreparePopup8(gw,popup_msg);
+}
+
+static void AddDFLT(OTLookup *otl) {
+ FeatureScriptLangList *fl;
+ struct scriptlanglist *sl;
+ int l;
+
+ for ( fl = otl->features; fl!=NULL; fl=fl->next ) {
+ int hasDFLT = false, hasdflt=false;
+ for ( sl=fl->scripts; sl!=NULL; sl=sl->next ) {
+ if ( sl->script == DEFAULT_SCRIPT )
+ hasDFLT = true;
+ for ( l=0; l<sl->lang_cnt; ++l ) {
+ uint32 lang = l<MAX_LANG ? sl->langs[l] : sl->morelangs[l-MAX_LANG];
+ if ( lang==DEFAULT_LANG ) {
+ hasdflt = true;
+ break;
+ }
+ }
+ if ( hasdflt && hasDFLT )
+ break;
+ }
+ if ( hasDFLT /* Already there */ ||
+ !hasdflt /* Shouldn't add it */ )
+ continue;
+ sl = chunkalloc(sizeof(struct scriptlanglist));
+ sl->script = DEFAULT_SCRIPT;
+ sl->lang_cnt = 1;
+ sl->langs[0] = DEFAULT_LANG;
+ sl->next = fl->scripts;
+ fl->scripts = sl;
+ }
+}
+
+static void AALTRemoveOld(SplineFont *sf,struct lkdata *lk) {
+ int i;
+ FeatureScriptLangList *fl, *prev;
+
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ prev = NULL;
+ for ( fl = lk->all[i].lookup->features; fl!=NULL; prev=fl, fl=fl->next ) {
+ if ( fl->featuretag==CHR('a','a','l','t') ) {
+ if ( fl==lk->all[i].lookup->features && fl->next==NULL )
+ lk->all[i].deleted = true;
+ else {
+ if ( prev==NULL )
+ lk->all[i].lookup->features = fl->next;
+ else
+ prev->next = fl->next;
+ fl->next = NULL;
+ FeatureScriptLangListFree(fl);
+ }
+ break;
+ }
+ }
+ }
+}
+
+
+struct sllk { uint32 script; int cnt, max; OTLookup **lookups; int lcnt, lmax; uint32 *langs; };
+
+static void AddOTLToSllk(struct sllk *sllk, OTLookup *otl, struct scriptlanglist *sl) {
+ int i,j,k,l;
+
+ if ( otl->lookup_type==gsub_single || otl->lookup_type==gsub_alternate ) {
+ for ( i=0; i<sllk->cnt; ++i )
+ if ( sllk->lookups[i]==otl )
+ break;
+ if ( i==sllk->cnt ) {
+ if ( sllk->cnt>=sllk->max )
+ sllk->lookups = grealloc(sllk->lookups,(sllk->max+=5)*sizeof(OTLookup *));
+ sllk->lookups[sllk->cnt++] = otl;
+ for ( l=0; l<sl->lang_cnt; ++l ) {
+ uint32 lang = l<MAX_LANG ? sl->langs[l] : sl->morelangs[l-MAX_LANG];
+ for ( j=0; j<sllk->lcnt; ++j )
+ if ( sllk->langs[j]==lang )
+ break;
+ if ( j==sllk->lcnt ) {
+ if ( sllk->lcnt>=sllk->lmax )
+ sllk->langs = grealloc(sllk->langs,(sllk->lmax+=sl->lang_cnt+MAX_LANG)*sizeof(uint32));
+ sllk->langs[sllk->lcnt++] = lang;
+ }
+ }
+ }
+ } else if ( otl->lookup_type==gsub_context || otl->lookup_type==gsub_contextchain ) {
+ struct lookup_subtable *sub;
+ for ( sub=otl->subtables; sub!=NULL; sub=sub->next ) {
+ FPST *fpst = sub->fpst;
+ for ( j=0; j<fpst->rule_cnt; ++j ) {
+ struct fpst_rule *r = &fpst->rules[j];
+ for ( k=0; k<r->lookup_cnt; ++k )
+ AddOTLToSllk(sllk,r->lookups[k].lookup,sl);
+ }
+ }
+ }
+ /* reverse contextual chaining is weird and I shall ignore it. Adobe does too*/
+}
+
+static char *ComponentsFromPSTs(PST **psts,int pcnt) {
+ char **names=NULL;
+ int ncnt=0, nmax=0;
+ int i,j,len;
+ char *ret;
+
+ /* First find all the names */
+ for ( i=0; i<pcnt; ++i ) {
+ char *nlist = psts[i]->u.alt.components;
+ char *start, *pt, ch;
+
+ for ( start = nlist; ; ) {
+ while ( *start==' ' )
+ ++start;
+ if ( *start=='\0' )
+ break;
+ for ( pt=start; *pt!=' ' && *pt!='\0'; ++pt );
+ ch = *pt; *pt = '\0';
+ for ( j=0; j<ncnt; ++j )
+ if ( strcmp( start,names[j])==0 )
+ break;
+ if ( j==ncnt ) {
+ if ( ncnt>=nmax )
+ names = grealloc(names,(nmax+=10)*sizeof(char *));
+ names[ncnt++] = copy(start);
+ }
+ *pt = ch;
+ start = pt;
+ }
+ }
+
+ len = 0;
+ for ( i=0; i<ncnt; ++i )
+ len += strlen(names[i])+1;
+ if ( len==0 ) len=1;
+ ret = galloc(len);
+ len = 0;
+ for ( i=0; i<ncnt; ++i ) {
+ strcpy(ret+len,names[i]);
+ len += strlen(names[i]);
+ ret[len++] = ' ';
+ }
+ if ( len==0 )
+ *ret = '\0';
+ else
+ ret[len-1] = '\0';
+
+ for ( i=0; i<ncnt; ++i )
+ free(names[i]);
+ free(names);
+return( ret );
+}
+
+static int SllkMatch(struct sllk *sllk,int s1,int s2) {
+ int i;
+
+ if ( sllk[s1].cnt != sllk[s2].cnt )
+return( false );
+
+ for ( i=0; i<sllk[s1].cnt; ++i ) {
+ if ( sllk[s1].lookups[i] != sllk[s2].lookups[i] )
+return( false );
+ }
+
+return( true );
+}
+
+static void AALTCreateNew(SplineFont *sf, struct lkdata *lk) {
+ /* different script/lang combinations may need different 'aalt' lookups */
+ /* well, let's just say different script combinations */
+ /* for each script/lang combo find all single/alternate subs for each */
+ /* glyph. Merge those choices and create new lookup with that info */
+ struct sllk *sllk = NULL;
+ int sllk_cnt=0, sllk_max = 0;
+ int i,s;
+ OTLookup *otl;
+ struct lookup_subtable *sub;
+ PST **psts, *pst;
+ FeatureScriptLangList *fl;
+ struct scriptlanglist *sl;
+ int l,k,j,gid,pcnt;
+ SplineFont *_sf;
+ SplineChar *sc;
+
+ /* Find all scripts, and all the single/alternate lookups for each */
+ /* and all the languages used for these in each script */
+ for ( i=0; i<lk->cnt; ++i ) {
+ otl = lk->all[i].lookup;
+ for ( fl=otl->features; fl!=NULL; fl=fl->next )
+ for ( sl=fl->scripts; sl!=NULL; sl=sl->next ) {
+ for ( s=0; s<sllk_cnt; ++s )
+ if ( sl->script == sllk[s].script )
+ break;
+ if ( s==sllk_cnt ) {
+ if ( sllk_cnt>=sllk_max )
+ sllk = grealloc(sllk,(sllk_max+=10)*sizeof(struct sllk));
+ memset(&sllk[sllk_cnt],0,sizeof(struct sllk));
+ sllk[sllk_cnt++].script = sl->script;
+ }
+ AddOTLToSllk(&sllk[s], otl,sl);
+ }
+ }
+ /* Each of these gets its own gsub_alternate lookup which gets inserted */
+ /* at the head of the lookup list. Each lookup has one subtable */
+ for ( i=0; i<sllk_cnt; ++i ) {
+ if ( sllk[i].cnt==0 ) /* Script used, but provides no alternates */
+ continue;
+ /* Make the new lookup (and all its supporting data structures) */
+ otl = chunkalloc(sizeof(OTLookup));
+ otl->lookup_type = gsub_alternate;
+ otl->lookup_flags = sllk[i].lookups[0]->lookup_flags & pst_r2l;
+ otl->features = fl = chunkalloc(sizeof(FeatureScriptLangList));
+ fl->featuretag = CHR('a','a','l','t');
+ /* Any other scripts with the same lookup set? */
+ for ( j=i; j<sllk_cnt; ++j ) {
+ if ( i==j || SllkMatch(sllk,i,j)) {
+ sl = chunkalloc(sizeof(struct scriptlanglist));
+ sl->next = fl->scripts;
+ fl->scripts = sl;
+ sl->script = sllk[j].script;
+ sl->lang_cnt = sllk[j].lcnt;
+ if ( sl->lang_cnt>MAX_LANG )
+ sl->morelangs = galloc((sl->lang_cnt-MAX_LANG)*sizeof(uint32));
+ for ( l=0; l<sl->lang_cnt; ++l )
+ if ( l<MAX_LANG )
+ sl->langs[l] = sllk[j].langs[l];
+ else
+ sl->morelangs[l-MAX_LANG] = sllk[j].langs[l];
+ if ( i!=j ) sllk[j].cnt = 0; /* Mark as processed */
+ }
+ }
+ otl->subtables = sub = chunkalloc(sizeof(struct lookup_subtable));
+ sub->lookup = otl;
+ sub->per_glyph_pst_or_kern = true;
+
+ /* Add it to the various lists it needs to be in */
+ if ( lk->cnt>=lk->max )
+ lk->all = grealloc(lk->all,(lk->max+=10)*sizeof(struct lkinfo));
+ for ( k=lk->cnt; k>0; --k )
+ lk->all[k] = lk->all[k-1];
+ memset(&lk->all[0],0,sizeof(struct lkinfo));
+ lk->all[0].lookup = otl;
+ lk->all[0].new = true;
+ ++lk->cnt;
+ otl->next = sf->gsub_lookups;
+ sf->gsub_lookups = otl;
+
+ /* Now add the new subtable */
+ lk->all[0].subtables = gcalloc(1,sizeof(struct lksubinfo));
+ lk->all[0].subtable_cnt = lk->all[0].subtable_max = 1;
+ lk->all[0].subtables[0].subtable = sub;
+ lk->all[0].subtables[0].new = true;
+
+ /* Now look at every glyph in the font, and see if it has any of the */
+ /* lookups we are interested in, and if it does, build a new pst */
+ /* containing all posibilities listed on any of them */
+ if ( sf->cidmaster ) sf = sf->cidmaster;
+ psts = galloc(sllk[i].cnt*sizeof(PST *));
+ k=0;
+ do {
+ _sf = k<sf->subfontcnt ? sf->subfonts[k] : sf;
+ for ( gid=0; gid<_sf->glyphcnt; ++gid ) if ( (sc = _sf->glyphs[gid])!=NULL ) {
+ pcnt = 0;
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable==NULL )
+ continue;
+ for ( j=0; j<sllk[i].cnt; ++j )
+ if ( pst->subtable->lookup == sllk[i].lookups[j] )
+ break;
+ if ( j<sllk[i].cnt )
+ psts[pcnt++] = pst;
+ }
+ if ( pcnt==0 )
+ continue;
+ pst = chunkalloc(sizeof(PST));
+ pst->subtable = sub;
+ pst->type = pst_alternate;
+ pst->next = sc->possub;
+ sc->possub = pst;
+ pst->u.alt.components = ComponentsFromPSTs(psts,pcnt);
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+ free(psts);
+ NameOTLookup(otl,sf);
+ }
+
+ for ( i=0; i<sllk_cnt; ++i ) {
+ free( sllk[i].langs );
+ free( sllk[i].lookups );
+ }
+ free(sllk);
+}
+
+static void lookupmenu_dispatch(GWindow v, GMenuItem *mi, GEvent *e) {
+ GEvent dummy;
+ struct gfi_data *gfi = GDrawGetUserData(v);
+ int i;
+ char *buts[4];
+
+ if ( mi->mid==CID_SaveFeat || mi->mid==CID_SaveLookup ) {
+ char *filename, *defname;
+ FILE *out;
+ int isgpos = GTabSetGetSel(GWidgetGetControl(gfi->gw,CID_Lookups));
+ struct lkdata *lk = &gfi->tables[isgpos];
+ OTLookup *otl = NULL;
+
+ if ( mi->mid==CID_SaveLookup ) {
+ for ( i=0; i<lk->cnt && (!lk->all[i].selected || lk->all[i].deleted); ++i );
+ if ( i==lk->cnt )
+return;
+ otl = lk->all[i].lookup;
+ }
+ defname = strconcat(gfi->sf->fontname,".fea");
+ filename = gwwv_save_filename(_("Feature file?"),defname,"*.fea");
+ free(defname);
+ if ( filename==NULL )
+return;
+ /* Convert to def encoding !!! */
+ out = fopen(filename,"w");
+ if ( out==NULL ) {
+ gwwv_post_error(_("Cannot open file"),_("Cannot open %s"), filename );
+ free(filename);
+return;
+ }
+ if ( otl!=NULL )
+ FeatDumpOneLookup( out,gfi->sf,otl );
+ else
+ FeatDumpFontLookups( out,gfi->sf );
+ if ( ferror(out)) {
+ gwwv_post_error(_("Output error"),_("An error occurred writing %s"), filename );
+ free(filename);
+ fclose(out);
+return;
+ }
+ free(filename);
+ fclose(out);
+ } else if ( mi->mid==CID_AddAllAlternates ) {
+ /* First we want to remove any old aalt-only lookups */
+ /* (and remove the 'aalt' tag from any lookups with multiple features) */
+ /* Then add the new ones */
+ struct lkdata *lk = &gfi->tables[0]; /* GSUB */
+ int has_aalt_only=false, has_aalt_mixed = false;
+ int i, ret;
+ FeatureScriptLangList *fl;
+
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ for ( fl = lk->all[i].lookup->features; fl!=NULL; fl=fl->next ) {
+ if ( fl->featuretag==CHR('a','a','l','t') ) {
+ if ( fl==lk->all[i].lookup->features && fl->next==NULL )
+ has_aalt_only = true;
+ else
+ has_aalt_mixed = true;
+ break;
+ }
+ }
+ }
+ if ( has_aalt_only || has_aalt_mixed ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ buts[0] = _("_OK"); buts[1] = _("_Cancel"); buts[2] = NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ buts[0] = GTK_STOCK_OK; buts[1] = GTK_STOCK_CANCEL; buts[2] = NULL;
+#endif
+ ret = gwwv_ask(has_aalt_only?_("Lookups will be removed"):_("Feature tags will be removed"),
+ (const char **) buts,0,1,
+ !has_aalt_mixed ?
+ _("Warning: There are already some 'aalt' lookups in\n"
+ "the font. If you proceed with this command those\n"
+ "lookups will be removed and new lookups will be\n"
+ "generated. The old information will be LOST.\n"
+ " Is that what you want?") :
+ !has_aalt_only ?
+ _("Warning: There are already some 'aalt' lookups in\n"
+ "the font but there are other feature tags associated\n"
+ "with these lookups. If you proceed with this command\n"
+ "the 'aalt' tag will be removed from those lookups,\n"
+ "and new lookups will be generate which will NOT be\n"
+ "associated with the other feature tag(s).\n"
+ " Is that what you want?") :
+ _("Warning: There are already some 'aalt' lookups in\n"
+ "the font, some have no other feature tags associated\n"
+ "with them and these will be removed, others have other\n"
+ "tags associated and these will remain while the 'aalt'\n"
+ "tag will be removed from the lookup -- a new lookup\n"
+ "will be generated which is not associated with any\n"
+ "other feature tags.\n"
+ " Is that what you want?") );
+ if ( ret==1 )
+return;
+ AALTRemoveOld(gfi->sf,lk);
+ }
+ AALTCreateNew(gfi->sf,lk);
+ GDrawRequestExpose(GDrawableGetWindow(GWidgetGetControl(gfi->gw,CID_LookupWin+0)),NULL,true);
+ } else if ( mi->mid==CID_AddDFLT ) {
+ struct selection_bits sel;
+ int toall, ret, i;
+ char *buts[4];
+ int isgpos = GTabSetGetSel(GWidgetGetControl(gfi->gw,CID_Lookups));
+ struct lkdata *lk = &gfi->tables[isgpos];
+
+ LookupParseSelection(lk,&sel);
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ if ( sel.lookup_cnt==0 ) {
+ buts[0] = _("_Apply to All"); buts[1] = _("_Cancel"); buts[2]=NULL;
+ } else {
+ buts[0] = _("_Apply to All"); buts[1] = _("_Apply to Selection"); buts[2] = _("_Cancel"); buts[3]=NULL;
+ }
+#elif defined(FONTFORGE_CONFIG_GTK)
+ if ( sel.lookup_cnt==0 ) {
+ buts[0] = _("_Apply to All"); buts[1] = GTK_STOCK_CANCEL; buts[2]=NULL;
+ } else {
+ buts[0] = _("_Apply to All"); buts[1] = _("_Apply to Selection"); buts[2] = GTK_STOCK_CANCEL; buts[3]=NULL;
+ }
+#endif
+ ret = gwwv_ask(_("Apply to:"),(const char **) buts,0,sel.lookup_cnt==0?1:2,_("Apply change to which lookups?"));
+ toall = false;
+ if ( ret==0 )
+ toall = true;
+ else if ( (ret==1 && sel.lookup_cnt==0) || (ret==2 && sel.lookup_cnt!=0))
+return;
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ if ( lk->all[i].selected || toall ) {
+ AddDFLT(lk->all[i].lookup);
+ }
+ }
+ } else {
+ memset(&dummy,0,sizeof(dummy));
+ dummy.type = et_controlevent;
+ dummy.u.control.subtype = et_buttonpress;
+ dummy.u.control.g = GWidgetGetControl(gfi->gw,mi->mid);
+ dummy.w = GGadgetGetWindow(dummy.u.control.g);
+ dummy.u.control.u.button.button = e->u.mouse.button;
+ GGadgetDispatchEvent(dummy.u.control.g,&dummy);
+ }
+}
+
+static GMenuItem lookuppopupmenu[] = {
+ { { (unichar_t *) N_("_Top"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 't' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_LookupTop },
+ { { (unichar_t *) N_("_Up"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_LookupUp },
+ { { (unichar_t *) N_("_Down"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_LookupDown },
+ { { (unichar_t *) N_("_Bottom"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_LookupBottom },
+ { { (unichar_t *) N_("_Sort"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_LookupSort },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Add _Lookup"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_AddLookup },
+ { { (unichar_t *) N_("Add Sub_table"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_AddSubtable },
+ { { (unichar_t *) N_("Edit _Metadata"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_EditMetadata },
+ { { (unichar_t *) N_("_Edit Data"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_EditSubtable },
+ { { (unichar_t *) N_("De_lete"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_DeleteLookup },
+ { { (unichar_t *) N_("_Merge"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_MergeLookup },
+ { { (unichar_t *) N_("Sa_ve Lookup"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_SaveLookup },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Add 'aalt' features"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_AddAllAlternates },
+ { { (unichar_t *) N_("Add 'D_FLT' script"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_AddDFLT },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Revert All"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_RevertLookups },
+ { { (unichar_t *) N_("_Import"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_RevertLookups },
+ { { (unichar_t *) N_("S_ave Feature File"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, lookupmenu_dispatch, CID_SaveFeat },
+ { NULL }};
+
+static void LookupMenu(struct gfi_data *gfi,struct lkdata *lk,GEvent *event) {
+ struct selection_bits sel;
+ int i,j;
+
+ LookupParseSelection(lk,&sel);
+ for ( i=0; lookuppopupmenu[i].ti.text!=NULL || lookuppopupmenu[i].ti.line; ++i ) {
+ switch ( lookuppopupmenu[i].mid ) {
+ case 0:
+ /* Lines */;
+ break;
+ case CID_LookupTop:
+ lookuppopupmenu[i].ti.disabled = sel.any_first || sel.lookup_cnt+sel.sub_cnt!=1;
+ break;
+ case CID_LookupUp:
+ lookuppopupmenu[i].ti.disabled = sel.any_first || sel.lookup_cnt+sel.sub_cnt==0;
+ break;
+ case CID_LookupDown:
+ lookuppopupmenu[i].ti.disabled = sel.any_last || sel.lookup_cnt+sel.sub_cnt==0;
+ break;
+ case CID_LookupBottom:
+ lookuppopupmenu[i].ti.disabled = sel.any_last || sel.lookup_cnt+sel.sub_cnt!=1;
+ break;
+ case CID_LookupSort:
+ lookuppopupmenu[i].ti.disabled = lk->cnt<=1;
+ break;
+ case CID_AddLookup:
+ lookuppopupmenu[i].ti.disabled = sel.lookup_cnt+sel.sub_cnt>1;
+ break;
+ case CID_AddSubtable:
+ lookuppopupmenu[i].ti.disabled = (sel.lookup_cnt!=1 || sel.sub_cnt>1) && (sel.lookup_cnt!=0 || sel.sub_cnt!=1);
+ break;
+ case CID_EditMetadata:
+ lookuppopupmenu[i].ti.disabled = (sel.lookup_cnt!=1 || sel.sub_cnt!=0) &&
+ (sel.lookup_cnt!=0 || sel.sub_cnt!=1);
+ break;
+ case CID_EditSubtable:
+ lookuppopupmenu[i].ti.disabled = sel.lookup_cnt!=0 || sel.sub_cnt!=1;
+ break;
+ case CID_DeleteLookup:
+ lookuppopupmenu[i].ti.disabled = sel.lookup_cnt==0 && sel.sub_cnt==0;
+ break;
+ case CID_MergeLookup:
+ lookuppopupmenu[i].ti.disabled = !(
+ (sel.lookup_cnt>=2 && sel.sub_cnt==0 && sel.lookup_mergeable) ||
+ (sel.lookup_cnt==0 && sel.sub_cnt>=2 && sel.sub_table_mergeable) );
+ break;
+ case CID_RevertLookups:
+ lookuppopupmenu[i].ti.disabled = false;
+ break;
+ case CID_SaveLookup:
+ lookuppopupmenu[i].ti.disabled = sel.lookup_cnt!=1 || sel.sub_cnt!=0;
+ for ( j=0; j<lk->cnt; ++j ) if ( lk->all[j].selected ) {
+ int type = lk->all[j].lookup->lookup_type;
+ if ( type==kern_statemachine || type==morx_indic ||
+ type==morx_context || type==morx_insert )
+ lookuppopupmenu[i].ti.disabled = true;
+ break;
+ }
+ break;
+ case CID_AddDFLT:
+ lookuppopupmenu[i].ti.disabled = lk->cnt==0;
+ break;
+ case CID_AddAllAlternates:
+ lookuppopupmenu[i].ti.disabled = lk->cnt==0 || lk==&gfi->tables[1]/*Only applies to GSUB*/;
+ break;
+ case CID_SaveFeat:
+ lookuppopupmenu[i].ti.disabled = lk->cnt<=1;
+ break;
+ }
+ }
+ GMenuCreatePopupMenu(event->w,event, lookuppopupmenu);
+}
+
+
+static void LookupMouse(struct gfi_data *gfi, int isgpos, GEvent *event) {
+ struct lkdata *lk = &gfi->tables[isgpos];
+ int l = (event->u.mouse.y-LK_MARGIN)/gfi->fh + lk->off_top;
+ int inbox = event->u.mouse.x>=LK_MARGIN &&
+ event->u.mouse.x>=LK_MARGIN-lk->off_left &&
+ event->u.mouse.x<=LK_MARGIN-lk->off_left+gfi->as+1;
+ GWindow gw = GDrawableGetWindow(GWidgetGetControl(gfi->gw,CID_LookupWin+isgpos));
+ int i,j,lcnt;
+
+ if ( l<0 || event->u.mouse.y>=(gfi->lkheight-2*LK_MARGIN) )
+return;
+
+ lcnt = 0;
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ if ( l==lcnt ) {
+ if ( event->type==et_mouseup )
+return;
+ else if ( event->type==et_mousemove ) {
+ LookupPopup(gw,lk->all[i].lookup,NULL);
+return;
+ } else {
+ if ( inbox || event->u.mouse.clicks>1 ) {
+ lk->all[i].open = !lk->all[i].open;
+ GFI_LookupScrollbars(gfi, isgpos, true);
+return;
+ }
+ if ( !(event->u.mouse.state&(ksm_shift|ksm_control)) ) {
+ LookupDeselect(lk);
+ lk->all[i].selected = true;
+ } else
+ lk->all[i].selected = !lk->all[i].selected;
+ GFI_LookupEnableButtons(gfi,isgpos);
+ GDrawRequestExpose(gw,NULL,true);
+ if ( event->u.mouse.button==3 )
+ LookupMenu(gfi,lk,event);
+return;
+ }
+ }
+ ++lcnt;
+ if ( lk->all[i].open ) {
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].deleted )
+ continue;
+ if ( l==lcnt ) {
+ if ( event->type==et_mouseup )
+return;
+ else if ( event->type==et_mousemove ) {
+ LookupPopup(gw,lk->all[i].lookup,lk->all[i].subtables[j].subtable);
+return;
+ } else {
+ if ( inbox )
+return; /* Can't open this guy */
+ if ( event->u.mouse.clicks>1 )
+ LookupSubtableContents(gfi,isgpos);
+ else {
+ if ( !(event->u.mouse.state&(ksm_shift|ksm_control)) ) {
+ LookupDeselect(lk);
+ lk->all[i].subtables[j].selected = true;
+ } else
+ lk->all[i].subtables[j].selected = !lk->all[i].subtables[j].selected;
+ GFI_LookupEnableButtons(gfi,isgpos);
+ GDrawRequestExpose(gw,NULL,true);
+ if ( event->u.mouse.button==3 )
+ LookupMenu(gfi,lk,event);
+ }
+return;
+ }
+ }
+ ++lcnt;
+ }
+ }
+ }
+}
+
+static int lookups_e_h(GWindow gw, GEvent *event, int isgpos) {
+ struct gfi_data *gfi = GDrawGetUserData(gw);
+
+ if (( event->type==et_mouseup || event->type==et_mousedown ) &&
+ (event->u.mouse.button==4 || event->u.mouse.button==5) ) {
+return( GGadgetDispatchEvent(GWidgetGetControl(gw,CID_LookupVSB+isgpos),event));
+ }
+
+ switch ( event->type ) {
+ case et_char:
+return( GFI_Char(gfi,event) );
+ case et_expose:
+ LookupExpose(gw,gfi,isgpos);
+ break;
+ case et_mousedown: case et_mousemove: case et_mouseup:
+ LookupMouse(gfi,isgpos,event);
+ break;
+ case et_resize: {
+ GRect r;
+ GDrawGetSize(gw,&r);
+ gfi->lkheight = r.height; gfi->lkwidth = r.width;
+ GFI_LookupScrollbars(gfi,false,false);
+ GFI_LookupScrollbars(gfi,true,false);
+ }
+ break;
+ }
+return( true );
+}
+
+static int gposlookups_e_h(GWindow gw, GEvent *event) {
+return( lookups_e_h(gw,event,true));
+}
+
+static int gsublookups_e_h(GWindow gw, GEvent *event) {
+return( lookups_e_h(gw,event,false));
+}
+
+void FontInfo(SplineFont *sf,int defaspect,int sync) {
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GTabInfo aspects[22], vaspects[5], lkaspects[3];
+ GGadgetCreateData mgcd[10], ngcd[17], psgcd[30], tngcd[8],
+ pgcd[8], vgcd[19], pangcd[22], comgcd[3], txgcd[23],
+ mfgcd[8], mcgcd[8], szgcd[19], mkgcd[5], metgcd[29], vagcd[3], ssgcd[23],
+ xugcd[7], dgcd[6], ugcd[4], gaspgcd[5], gaspgcd_def[2], lksubgcd[2][4],
+ lkgcd[2], lkbuttonsgcd[15];
+ GGadgetCreateData mb[2], mb2, nb[2], nb2, nb3, xub[2], psb[2], psb2[3], ppbox[3],
+ vbox[4], metbox[2], ssbox[2], panbox[2], combox[2], mkbox[3],
+ txbox[5], ubox[2], dbox[2],
+ mcbox[3], mfbox[3], szbox[6], tnboxes[4], gaspboxes[3],
+ lkbox[7];
+ GGadgetCreateData *marray[7], *marray2[9], *narray[26], *narray2[7], *narray3[3],
+ *xuarray[13], *psarray[10], *psarray2[21], *psarray3[3], *psarray4[10],
+ *ppbuttons[5], *pparray[4], *vradio[5], *varray[38], *metarray[46],
+ *ssarray[58], *panarray[38], *comarray[2],
+ *mkarray[3], *mkarray2[4], *txarray[5], *txarray2[30],
+ *txarray3[6], *txarray4[6], *uarray[3], *darray[10],
+ *mcarray[13], *mcarray2[7],
+ *mfarray[14], *szarray[7], *szarray2[5], *szarray3[7],
+ *szarray4[4], *szarray5[6], *tnvarray[4], *tnharray[6], *tnharray2[5], *gaspharray[6],
+ *gaspvarray[3], *lkarray[2][7], *lkbuttonsarray[17], *lkharray[3];
+ GTextInfo mlabel[10], nlabel[16], pslabel[30], tnlabel[7],
+ plabel[8], vlabel[19], panlabel[22], comlabel[3], txlabel[23],
+ mflabel[8], mclabel[8], szlabel[17], mklabel[5], metlabel[28],
+ sslabel[23], xulabel[6], dlabel[5], ulabel[1], gasplabel[5],
+ lkbuttonslabel[14];
+ GTextInfo *namelistnames;
+ struct gfi_data *d;
+ char iabuf[20], upbuf[20], uwbuf[20], asbuf[20], dsbuf[20],
+ vbuf[20], uibuf[12], vorig[20], embuf[20];
+ char dszbuf[20], dsbbuf[20], dstbuf[21], sibuf[20], swbuf[20];
+ int i,j,k, psrow;
+ int mcs;
+ char title[130];
+ /* static unichar_t monospace[] = { 'c','o','u','r','i','e','r',',','m', 'o', 'n', 'o', 's', 'p', 'a', 'c', 'e',',','c','a','s','l','o','n',',','c','l','e','a','r','l','y','u',',','u','n','i','f','o','n','t', '\0' };*/
+ static unichar_t sans[] = { 'h','e','l','v','e','t','i','c','a',',','c','l','e','a','r','l','y','u',',','u','n','i','f','o','n','t', '\0' };
+ FontRequest rq;
+ int as, ds, ld;
+ char **nlnames;
+ char createtime[200], modtime[200];
+ unichar_t *tmpcreatetime, *tmpmodtime;
+ time_t t;
+ const struct tm *tm;
+ struct matrixinit mi, gaspmi;
+
+ FontInfoInit();
+
+ if ( sf->fontinfo!=NULL ) {
+ GDrawSetVisible(((struct gfi_data *) (sf->fontinfo))->gw,true);
+ GDrawRaise( ((struct gfi_data *) (sf->fontinfo))->gw );
+return;
+ }
+ if ( defaspect==-1 )
+ defaspect = last_aspect;
+
+ d = gcalloc(1,sizeof(struct gfi_data));
+ sf->fontinfo = d;
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.is_dlg = true;
+ if ( sync ) {
+ wattrs.mask |= wam_restrict;
+ wattrs.restrict_input_to_me = 1;
+ }
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ snprintf(title,sizeof(title),_("Font Information for %.90s"),
+ sf->fontname);
+ wattrs.utf8_window_title = title;
+ pos.x = pos.y = 0;
+#ifndef FONTFORGE_CONFIG_INFO_HORIZONTAL
+ pos.width =GDrawPointsToPixels(NULL,GGadgetScale(268+85));
+#else
+ pos.width =GDrawPointsToPixels(NULL,GGadgetScale(268));
+#endif
+ pos.height = GDrawPointsToPixels(NULL,375);
+ gw = GDrawCreateTopWindow(NULL,&pos,e_h,d,&wattrs);
+
+ d->sf = sf;
+ d->gw = gw;
+ d->old_sel = -2;
+ d->texdata = sf->texdata;
+
+ memset(&nlabel,0,sizeof(nlabel));
+ memset(&ngcd,0,sizeof(ngcd));
+
+ nlabel[0].text = (unichar_t *) _("Fo_ntname:");
+ nlabel[0].text_is_1byte = true;
+ nlabel[0].text_in_resource = true;
+ ngcd[0].gd.label = &nlabel[0];
+ ngcd[0].gd.pos.x = 12; ngcd[0].gd.pos.y = 6+6;
+ ngcd[0].gd.flags = gg_visible | gg_enabled;
+ ngcd[0].creator = GLabelCreate;
+
+ ngcd[1].gd.pos.x = 115; ngcd[1].gd.pos.y = ngcd[0].gd.pos.y-6; ngcd[1].gd.pos.width = 137;
+ ngcd[1].gd.flags = gg_visible | gg_enabled;
+ nlabel[1].text = (unichar_t *) sf->fontname;
+ nlabel[1].text_is_1byte = true;
+ ngcd[1].gd.label = &nlabel[1];
+ ngcd[1].gd.cid = CID_Fontname;
+ ngcd[1].gd.handle_controlevent = GFI_NameChange;
+ ngcd[1].creator = GTextFieldCreate;
+
+ nlabel[2].text = (unichar_t *) _("_Family Name:");
+ nlabel[2].text_is_1byte = true;
+ nlabel[2].text_in_resource = true;
+ ngcd[2].gd.label = &nlabel[2];
+ ngcd[2].gd.pos.x = 12; ngcd[2].gd.pos.y = ngcd[0].gd.pos.y+26;
+ ngcd[2].gd.flags = gg_visible | gg_enabled;
+ ngcd[2].creator = GLabelCreate;
+
+ ngcd[3].gd.pos.x = ngcd[1].gd.pos.x; ngcd[3].gd.pos.y = ngcd[2].gd.pos.y-6; ngcd[3].gd.pos.width = 137;
+ ngcd[3].gd.flags = gg_visible | gg_enabled;
+ nlabel[3].text = (unichar_t *) (sf->familyname?sf->familyname:sf->fontname);
+ nlabel[3].text_is_1byte = true;
+ ngcd[3].gd.label = &nlabel[3];
+ ngcd[3].gd.cid = CID_Family;
+ ngcd[3].gd.handle_controlevent = GFI_FamilyChange;
+ ngcd[3].creator = GTextFieldCreate;
+ if ( sf->familyname==NULL || strstr(sf->familyname,"Untitled")==sf->familyname )
+ d->family_untitled = true;
+
+ ngcd[4].gd.pos.x = 12; ngcd[4].gd.pos.y = ngcd[3].gd.pos.y+26+6;
+ nlabel[4].text = (unichar_t *) _("Name For Human_s:");
+ nlabel[4].text_is_1byte = true;
+ nlabel[4].text_in_resource = true;
+ ngcd[4].gd.label = &nlabel[4];
+ ngcd[4].gd.flags = gg_visible | gg_enabled;
+ ngcd[4].creator = GLabelCreate;
+
+ ngcd[5].gd.pos.x = 115; ngcd[5].gd.pos.y = ngcd[4].gd.pos.y-6; ngcd[5].gd.pos.width = 137;
+ ngcd[5].gd.flags = gg_visible | gg_enabled;
+ nlabel[5].text = (unichar_t *) (sf->fullname?sf->fullname:sf->fontname);
+ nlabel[5].text_is_1byte = true;
+ ngcd[5].gd.label = &nlabel[5];
+ ngcd[5].gd.cid = CID_Human;
+ ngcd[5].gd.handle_controlevent = GFI_HumanChange;
+ ngcd[5].creator = GTextFieldCreate;
+ if ( sf->fullname==NULL || strstr(sf->fullname,"Untitled")==sf->fullname )
+ d->human_untitled = true;
+
+ nlabel[6].text = (unichar_t *) _("_Weight");
+ nlabel[6].text_is_1byte = true;
+ nlabel[6].text_in_resource = true;
+ ngcd[6].gd.label = &nlabel[6];
+ ngcd[6].gd.pos.x = ngcd[4].gd.pos.x; ngcd[6].gd.pos.y = ngcd[4].gd.pos.y+26;
+ ngcd[6].gd.flags = gg_visible | gg_enabled;
+ ngcd[6].creator = GLabelCreate;
+
+ ngcd[7].gd.pos.x = ngcd[1].gd.pos.x; ngcd[7].gd.pos.y = ngcd[6].gd.pos.y-6; ngcd[7].gd.pos.width = 137;
+ ngcd[7].gd.flags = gg_visible | gg_enabled;
+ nlabel[7].text = (unichar_t *) (sf->weight?sf->weight:"Regular");
+ nlabel[7].text_is_1byte = true;
+ ngcd[7].gd.label = &nlabel[7];
+ ngcd[7].gd.cid = CID_Weight;
+ ngcd[7].creator = GTextFieldCreate;
+
+ ngcd[8].gd.pos.x = 12; ngcd[8].gd.pos.y = ngcd[6].gd.pos.y+26;
+ nlabel[8].text = (unichar_t *) _("_Version:");
+ nlabel[8].text_is_1byte = true;
+ nlabel[8].text_in_resource = true;
+ ngcd[8].gd.label = &nlabel[8];
+ ngcd[8].gd.flags = gg_visible | gg_enabled;
+ ngcd[8].creator = GLabelCreate;
+
+ ngcd[9].gd.pos.x = 115; ngcd[9].gd.pos.y = ngcd[8].gd.pos.y-6; ngcd[9].gd.pos.width = 137;
+ ngcd[9].gd.flags = gg_visible | gg_enabled;
+ nlabel[9].text = (unichar_t *) (sf->version?sf->version:"");
+ nlabel[9].text_is_1byte = true;
+ if ( sf->subfontcnt!=0 ) {
+ sprintf( vbuf,"%g", sf->cidversion );
+ nlabel[9].text = (unichar_t *) vbuf;
+ }
+ ngcd[9].gd.label = &nlabel[9];
+ ngcd[9].gd.cid = CID_Version;
+ ngcd[9].creator = GTextFieldCreate;
+
+ ngcd[10].gd.pos.x = 12; ngcd[10].gd.pos.y = ngcd[8].gd.pos.y+28;
+ nlabel[10].text = (unichar_t *) _("_Base Filename:");
+ nlabel[10].text_is_1byte = true;
+ nlabel[10].text_in_resource = true;
+ ngcd[10].gd.label = &nlabel[10];
+ ngcd[10].gd.popup_msg = (unichar_t *) _("Use this as the default base for the filename\nwhen generating a font." );
+ ngcd[10].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ ngcd[10].creator = GLabelCreate;
+
+ ngcd[11].gd.pos.x = 95; ngcd[11].gd.pos.y = ngcd[10].gd.pos.y-11;
+/* GT: The space in front of "Same" makes things line up better */
+ nlabel[11].text = (unichar_t *) _(" Same as Fontname");
+ nlabel[11].text_is_1byte = true;
+ ngcd[11].gd.label = &nlabel[11];
+ ngcd[11].gd.flags = sf->defbasefilename==NULL ? (gg_visible | gg_enabled | gg_cb_on ) : (gg_visible | gg_enabled);
+ ngcd[11].gd.cid = CID_SameAsFontname;
+ ngcd[11].creator = GRadioCreate;
+
+ ngcd[12].gd.pos.x = 95; ngcd[12].gd.pos.y = ngcd[10].gd.pos.y+11;
+ nlabel[12].text = (unichar_t *) "";
+ nlabel[12].text_is_1byte = true;
+ ngcd[12].gd.label = &nlabel[12];
+ ngcd[12].gd.flags = sf->defbasefilename!=NULL ?
+ (gg_visible | gg_enabled | gg_cb_on | gg_rad_continueold ) :
+ (gg_visible | gg_enabled | gg_rad_continueold);
+ ngcd[12].gd.cid = CID_HasDefBase;
+ ngcd[12].creator = GRadioCreate;
+
+ ngcd[13].gd.pos.x = 115; ngcd[13].gd.pos.y = ngcd[12].gd.pos.y-4; ngcd[13].gd.pos.width = 137;
+ ngcd[13].gd.flags = gg_visible | gg_enabled;
+ nlabel[13].text = (unichar_t *) (sf->defbasefilename?sf->defbasefilename:"");
+ nlabel[13].text_is_1byte = true;
+ ngcd[13].gd.label = &nlabel[13];
+ ngcd[13].gd.cid = CID_DefBaseName;
+ ngcd[13].gd.handle_controlevent = GFI_DefBaseChange;
+ ngcd[13].creator = GTextFieldCreate;
+
+ ngcd[14].gd.pos.x = 12; ngcd[14].gd.pos.y = ngcd[10].gd.pos.y+22;
+ ngcd[14].gd.flags = gg_visible | gg_enabled;
+ nlabel[14].text = (unichar_t *) _("Copy_right:");
+ nlabel[14].text_is_1byte = true;
+ nlabel[14].text_in_resource = true;
+ ngcd[14].gd.label = &nlabel[14];
+ ngcd[14].creator = GLabelCreate;
+
+ ngcd[15].gd.pos.x = 12; ngcd[15].gd.pos.y = ngcd[14].gd.pos.y+14;
+ ngcd[15].gd.pos.width = ngcd[5].gd.pos.x+ngcd[5].gd.pos.width-26;
+ ngcd[15].gd.flags = gg_visible | gg_enabled | gg_textarea_wrap;
+ if ( sf->copyright!=NULL ) {
+ nlabel[15].text = (unichar_t *) sf->copyright;
+ nlabel[15].text_is_1byte = true;
+ ngcd[15].gd.label = &nlabel[15];
+ }
+ ngcd[15].gd.cid = CID_Notice;
+ ngcd[15].creator = GTextAreaCreate;
+
+ memset(&nb,0,sizeof(nb)); memset(&nb2,0,sizeof(nb2)); memset(&nb3,0,sizeof(nb3));
+
+ narray3[0] = &ngcd[12]; narray3[1] = &ngcd[13]; narray3[2] = NULL;
+
+ narray2[0] = &ngcd[10]; narray2[1] = &ngcd[11]; narray2[2] = NULL;
+ narray2[3] = GCD_RowSpan; narray2[4] = &nb3; narray2[5] = NULL;
+ narray2[6] = NULL;
+
+ narray[0] = &ngcd[0]; narray[1] = &ngcd[1]; narray[2] = NULL;
+ narray[3] = &ngcd[2]; narray[4] = &ngcd[3]; narray[5] = NULL;
+ narray[6] = &ngcd[4]; narray[7] = &ngcd[5]; narray[8] = NULL;
+ narray[9] = &ngcd[6]; narray[10] = &ngcd[7]; narray[11] = NULL;
+ narray[12] = &ngcd[8]; narray[13] = &ngcd[9]; narray[14] = NULL;
+ narray[15] = &nb2; narray[16] = GCD_ColSpan; narray[17] = NULL;
+ narray[18] = &ngcd[14]; narray[19] = GCD_ColSpan; narray[20] = NULL;
+ narray[21] = &ngcd[15]; narray[22] = GCD_ColSpan; narray[23] = NULL;
+ narray[24] = NULL;
+
+ nb3.gd.flags = gg_enabled|gg_visible;
+ nb3.gd.u.boxelements = narray3;
+ nb3.creator = GHBoxCreate;
+
+ nb2.gd.flags = gg_enabled|gg_visible;
+ nb2.gd.u.boxelements = narray2;
+ nb2.creator = GHVBoxCreate;
+
+ nb[0].gd.flags = gg_enabled|gg_visible;
+ nb[0].gd.u.boxelements = narray;
+ nb[0].creator = GHVBoxCreate;
+
+/******************************************************************************/
+ memset(&xulabel,0,sizeof(xulabel));
+ memset(&xugcd,0,sizeof(xugcd));
+
+ xugcd[0].gd.pos.x = 12; xugcd[0].gd.pos.y = 10+6;
+ xugcd[0].gd.flags = gg_visible | gg_enabled;
+ xulabel[0].text = (unichar_t *) _("_XUID:");
+ xulabel[0].text_is_1byte = true;
+ xulabel[0].text_in_resource = true;
+ xugcd[0].gd.label = &xulabel[0];
+ xugcd[0].creator = GLabelCreate;
+
+ xugcd[1].gd.pos.x = 103; xugcd[1].gd.pos.y = xugcd[0].gd.pos.y-6; xugcd[1].gd.pos.width = 142;
+ xugcd[1].gd.flags = gg_visible | gg_enabled;
+ if ( sf->xuid!=NULL ) {
+ xulabel[1].text = (unichar_t *) sf->xuid;
+ xulabel[1].text_is_1byte = true;
+ xugcd[1].gd.label = &xulabel[1];
+ }
+ xugcd[1].gd.cid = CID_XUID;
+ xugcd[1].creator = GTextFieldCreate;
+
+ xugcd[2].gd.pos.x = 12; xugcd[2].gd.pos.y = xugcd[1].gd.pos.y+26+6;
+ xulabel[2].text = (unichar_t *) _("_UniqueID:");
+ xulabel[2].text_is_1byte = true;
+ xulabel[2].text_in_resource = true;
+ xugcd[2].gd.label = &xulabel[2];
+ xugcd[2].gd.flags = gg_visible | gg_enabled;
+ xugcd[2].creator = GLabelCreate;
+
+ xugcd[3].gd.pos.x = xugcd[1].gd.pos.x; xugcd[3].gd.pos.y = xugcd[2].gd.pos.y-6; xugcd[3].gd.pos.width = 80;
+ xugcd[3].gd.flags = gg_visible | gg_enabled;
+ xulabel[3].text = (unichar_t *) "";
+ xulabel[3].text_is_1byte = true;
+ if ( sf->uniqueid!=0 ) {
+ sprintf( uibuf, "%d", sf->uniqueid );
+ xulabel[3].text = (unichar_t *) uibuf;
+ }
+ xugcd[3].gd.label = &xulabel[3];
+ xugcd[3].gd.cid = CID_UniqueID;
+ xugcd[3].creator = GTextFieldCreate;
+
+ xugcd[4].gd.pos.x = 8; xugcd[4].gd.pos.y = xugcd[3].gd.pos.y+26+6;
+ xulabel[4].text = (unichar_t *) _("(Adobe now considers XUID/UniqueID unnecessary)");
+ xulabel[4].text_is_1byte = true;
+ xulabel[4].text_in_resource = true;
+ xugcd[4].gd.label = &xulabel[4];
+ xugcd[4].gd.flags = gg_visible | gg_enabled;
+ xugcd[4].creator = GLabelCreate;
+
+ xuarray[0] = &xugcd[0]; xuarray[1] = &xugcd[1]; xuarray[2] = NULL;
+ xuarray[3] = &xugcd[2]; xuarray[4] = &xugcd[3]; xuarray[5] = NULL;
+ xuarray[6] = &xugcd[4]; xuarray[7] = GCD_ColSpan; xuarray[8] = NULL;
+ xuarray[9] = GCD_Glue; xuarray[10] = GCD_Glue; xuarray[11] = NULL;
+ xuarray[12] = NULL;
+
+ memset(xub,0,sizeof(xub));
+ xub[0].gd.flags = gg_enabled|gg_visible;
+ xub[0].gd.u.boxelements = xuarray;
+ xub[0].creator = GHVBoxCreate;
+
+/******************************************************************************/
+ memset(&pslabel,0,sizeof(pslabel));
+ memset(&psgcd,0,sizeof(psgcd));
+
+ psgcd[0].gd.pos.x = 12; psgcd[0].gd.pos.y = 12;
+ psgcd[0].gd.flags = gg_visible | gg_enabled;
+ pslabel[0].text = (unichar_t *) _("_Ascent:");
+ pslabel[0].text_is_1byte = true;
+ pslabel[0].text_in_resource = true;
+ psgcd[0].gd.label = &pslabel[0];
+ psgcd[0].creator = GLabelCreate;
+
+ psgcd[1].gd.pos.x = 103; psgcd[1].gd.pos.y = psgcd[0].gd.pos.y-6; psgcd[1].gd.pos.width = 47;
+ psgcd[1].gd.flags = gg_visible | gg_enabled;
+ sprintf( asbuf, "%d", sf->ascent );
+ pslabel[1].text = (unichar_t *) asbuf;
+ pslabel[1].text_is_1byte = true;
+ psgcd[1].gd.label = &pslabel[1];
+ psgcd[1].gd.cid = CID_Ascent;
+ psgcd[1].gd.handle_controlevent = GFI_EmChanged;
+ psgcd[1].creator = GTextFieldCreate;
+
+ psgcd[2].gd.pos.x = 155; psgcd[2].gd.pos.y = psgcd[0].gd.pos.y;
+ psgcd[2].gd.flags = gg_visible | gg_enabled;
+ pslabel[2].text = (unichar_t *) _("_Descent:");
+ pslabel[2].text_is_1byte = true;
+ pslabel[2].text_in_resource = true;
+ psgcd[2].gd.label = &pslabel[2];
+ psgcd[2].creator = GLabelCreate;
+
+ psgcd[3].gd.pos.x = 200; psgcd[3].gd.pos.y = psgcd[1].gd.pos.y; psgcd[3].gd.pos.width = 47;
+ psgcd[3].gd.flags = gg_visible | gg_enabled;
+ sprintf( dsbuf, "%d", sf->descent );
+ pslabel[3].text = (unichar_t *) dsbuf;
+ pslabel[3].text_is_1byte = true;
+ psgcd[3].gd.label = &pslabel[3];
+ psgcd[3].gd.cid = CID_Descent;
+ psgcd[3].gd.handle_controlevent = GFI_EmChanged;
+ psgcd[3].creator = GTextFieldCreate;
+
+ psgcd[4].gd.pos.x = psgcd[0].gd.pos.x+5; psgcd[4].gd.pos.y = psgcd[0].gd.pos.y+24;
+ psgcd[4].gd.flags = gg_visible | gg_enabled;
+ pslabel[4].text = (unichar_t *) _(" _Em Size:");
+ pslabel[4].text_is_1byte = true;
+ pslabel[4].text_in_resource = true;
+ psgcd[4].gd.label = &pslabel[4];
+ psgcd[4].creator = GLabelCreate;
+
+ psgcd[5].gd.pos.x = psgcd[1].gd.pos.x-20; psgcd[5].gd.pos.y = psgcd[1].gd.pos.y+24; psgcd[5].gd.pos.width = 67;
+ psgcd[5].gd.flags = gg_visible | gg_enabled;
+ sprintf( embuf, "%d", sf->descent+sf->ascent );
+ pslabel[5].text = (unichar_t *) embuf;
+ pslabel[5].text_is_1byte = true;
+ psgcd[5].gd.label = &pslabel[5];
+ psgcd[5].gd.cid = CID_Em;
+ psgcd[5].gd.u.list = emsizes;
+ psgcd[5].gd.handle_controlevent = GFI_EmChanged;
+ psgcd[5].creator = GListFieldCreate;
+
+ psgcd[6].gd.pos.x = psgcd[2].gd.pos.x; psgcd[6].gd.pos.y = psgcd[4].gd.pos.y-4;
+ psgcd[6].gd.flags = gg_visible | gg_enabled | gg_cb_on;
+ pslabel[6].text = (unichar_t *) _("_Scale Outlines");
+ pslabel[6].text_is_1byte = true;
+ pslabel[6].text_in_resource = true;
+ psgcd[6].gd.label = &pslabel[6];
+ psgcd[6].gd.cid = CID_Scale;
+ psgcd[6].creator = GCheckBoxCreate;
+
+/* I've reversed the label, text field order in the gcd here because */
+/* that way the text field will be displayed on top of the label rather */
+/* than the reverse, and in Russian that's important translation of */
+/* "Italic Angle" is too long. Oops, no it's the next one, might as well leave in here though */
+ psgcd[8].gd.pos.x = 12; psgcd[8].gd.pos.y = psgcd[5].gd.pos.y+26+6;
+ psgcd[8].gd.flags = gg_visible | gg_enabled;
+ pslabel[8].text = (unichar_t *) _("_Italic Angle:");
+ pslabel[8].text_is_1byte = true;
+ pslabel[8].text_in_resource = true;
+ psgcd[8].gd.label = &pslabel[8];
+ psgcd[8].creator = GLabelCreate;
+
+ psgcd[7].gd.pos.x = 103; psgcd[7].gd.pos.y = psgcd[8].gd.pos.y-6;
+ psgcd[7].gd.pos.width = 47;
+ psgcd[7].gd.flags = gg_visible | gg_enabled;
+ sprintf( iabuf, "%g", (double) sf->italicangle );
+ pslabel[7].text = (unichar_t *) iabuf;
+ pslabel[7].text_is_1byte = true;
+ psgcd[7].gd.label = &pslabel[7];
+ psgcd[7].gd.cid = CID_ItalicAngle;
+ psgcd[7].creator = GTextFieldCreate;
+
+ psgcd[9].gd.pos.y = psgcd[7].gd.pos.y;
+ psgcd[9].gd.pos.width = -1; psgcd[9].gd.pos.height = 0;
+ psgcd[9].gd.pos.x = psgcd[3].gd.pos.x+psgcd[3].gd.pos.width-
+ GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor);
+ /*if ( strstrmatch(sf->fontname,"Italic")!=NULL ||strstrmatch(sf->fontname,"Oblique")!=NULL )*/
+ psgcd[9].gd.flags = gg_visible | gg_enabled;
+ pslabel[9].text = (unichar_t *) _("_Guess");
+ pslabel[9].text_is_1byte = true;
+ pslabel[9].text_in_resource = true;
+ psgcd[9].gd.label = &pslabel[9];
+ psgcd[9].gd.handle_controlevent = GFI_GuessItalic;
+ psgcd[9].creator = GButtonCreate;
+
+/* I've reversed the label, text field order in the gcd here because */
+/* that way the text field will be displayed on top of the label rather */
+/* than the reverse, and in Russian that's important translation of */
+/* "Underline position" is too long. */
+ psgcd[11].gd.pos.x = 12; psgcd[11].gd.pos.y = psgcd[7].gd.pos.y+26+6;
+ psgcd[11].gd.flags = gg_visible | gg_enabled;
+ pslabel[11].text = (unichar_t *) _("Underline _Position:");
+ pslabel[11].text_is_1byte = true;
+ pslabel[11].text_in_resource = true;
+ psgcd[11].gd.label = &pslabel[11];
+ psgcd[11].creator = GLabelCreate;
+
+ psgcd[10].gd.pos.x = 103; psgcd[10].gd.pos.y = psgcd[11].gd.pos.y-6; psgcd[10].gd.pos.width = 47;
+ psgcd[10].gd.flags = gg_visible | gg_enabled;
+ sprintf( upbuf, "%g", (double) sf->upos );
+ pslabel[10].text = (unichar_t *) upbuf;
+ pslabel[10].text_is_1byte = true;
+ psgcd[10].gd.label = &pslabel[10];
+ psgcd[10].gd.cid = CID_UPos;
+ psgcd[10].creator = GTextFieldCreate;
+
+ psgcd[12].gd.pos.x = 155; psgcd[12].gd.pos.y = psgcd[11].gd.pos.y;
+ psgcd[12].gd.flags = gg_visible | gg_enabled;
+ pslabel[12].text = (unichar_t *) S_("Underline|_Height:");
+ pslabel[12].text_is_1byte = true;
+ pslabel[12].text_in_resource = true;
+ psgcd[12].gd.label = &pslabel[12];
+ psgcd[12].creator = GLabelCreate;
+
+ psgcd[13].gd.pos.x = 200; psgcd[13].gd.pos.y = psgcd[10].gd.pos.y; psgcd[13].gd.pos.width = 47;
+ psgcd[13].gd.flags = gg_visible | gg_enabled;
+ sprintf( uwbuf, "%g", (double) sf->uwidth );
+ pslabel[13].text = (unichar_t *) uwbuf;
+ pslabel[13].text_is_1byte = true;
+ psgcd[13].gd.label = &pslabel[13];
+ psgcd[13].gd.cid = CID_UWidth;
+ psgcd[13].creator = GTextFieldCreate;
+
+ psgcd[14].gd.pos.x = 12; psgcd[14].gd.pos.y = psgcd[13].gd.pos.y+26;
+ pslabel[14].text = (unichar_t *) _("Has _Vertical Metrics");
+ pslabel[14].text_is_1byte = true;
+ pslabel[14].text_in_resource = true;
+ psgcd[14].gd.label = &pslabel[14];
+ psgcd[14].gd.cid = CID_HasVerticalMetrics;
+ psgcd[14].gd.flags = gg_visible | gg_enabled;
+ if ( sf->hasvmetrics )
+ psgcd[14].gd.flags |= gg_cb_on;
+ psgcd[14].gd.handle_controlevent = GFI_VMetricsCheck;
+ psgcd[14].creator = GCheckBoxCreate;
+
+ psgcd[15].gd.pos.x = 12; psgcd[15].gd.pos.y = psgcd[14].gd.pos.y+22;
+ pslabel[15].text = (unichar_t *) _("Vertical _Origin:");
+ pslabel[15].text_is_1byte = true;
+ pslabel[15].text_in_resource = true;
+ psgcd[15].gd.label = &pslabel[15];
+ psgcd[15].gd.flags = sf->hasvmetrics ? (gg_visible | gg_enabled) : gg_visible;
+ psgcd[15].gd.cid = CID_VOriginLab;
+ psgcd[15].creator = GLabelCreate;
+
+ psgcd[16].gd.pos.x = psgcd[7].gd.pos.x; psgcd[16].gd.pos.y = psgcd[15].gd.pos.y-4; psgcd[16].gd.pos.width = psgcd[15].gd.pos.width;
+ psgcd[16].gd.flags = sf->hasvmetrics ? (gg_visible | gg_enabled) : gg_visible;
+ pslabel[16].text = (unichar_t *) "";
+ pslabel[16].text_is_1byte = true;
+ if ( sf->vertical_origin!=0 || sf->hasvmetrics ) {
+ sprintf( vorig, "%d", sf->vertical_origin );
+ pslabel[16].text = (unichar_t *) vorig;
+ }
+ psgcd[16].gd.label = &pslabel[16];
+ psgcd[16].gd.cid = CID_VOrigin;
+ psgcd[16].creator = GTextFieldCreate;
+
+ psgcd[17].gd.pos.x = 12; psgcd[17].gd.pos.y = psgcd[16].gd.pos.y+22;
+ pslabel[17].text = (unichar_t *) _("_Quadratic Splines");
+ pslabel[17].text_is_1byte = true;
+ pslabel[17].text_in_resource = true;
+ psgcd[17].gd.label = &pslabel[17];
+ psgcd[17].gd.flags = sf->order2 ? (gg_visible | gg_enabled | gg_cb_on | gg_utf8_popup) : (gg_visible | gg_enabled | gg_utf8_popup);
+ psgcd[17].gd.cid = CID_IsOrder2;
+ psgcd[17].creator = GCheckBoxCreate;
+ psgcd[17].gd.popup_msg = (unichar_t *) _("Use quadratic (that is truetype) splines to hold the outlines of this\nfont rather than cubic (postscript) splines. Set this option if you\nare editing truetype font. Unset it if you are editing an opentype\nor postscript font (FontForge will convert to the appropriate\nspline type when it generates fonts so this is not required).");
+
+#ifdef FONTFORGE_CONFIG_TYPE3
+ psgcd[18].gd.pos.x = 12; psgcd[18].gd.pos.y = psgcd[17].gd.pos.y+18;
+ pslabel[18].text = (unichar_t *) _("_Outline Font");
+ pslabel[18].text_is_1byte = true;
+ pslabel[18].text_in_resource = true;
+ psgcd[18].gd.label = &pslabel[18];
+ psgcd[18].gd.flags = (!sf->strokedfont && !sf->multilayer)?
+ (gg_visible | gg_enabled | gg_cb_on) : (gg_visible | gg_enabled);
+ psgcd[18].creator = GRadioCreate;
+
+ psgcd[19].gd.pos.x = 12; psgcd[19].gd.pos.y = psgcd[18].gd.pos.y+14;
+ pslabel[19].text = (unichar_t *) _("_Multi Layered Font");
+ pslabel[19].text_is_1byte = true;
+ pslabel[19].text_in_resource = true;
+ psgcd[19].gd.label = &pslabel[19];
+ psgcd[19].gd.flags = sf->multilayer ? (gg_visible | gg_enabled | gg_utf8_popup | gg_cb_on | gg_rad_continueold) : (gg_visible | gg_enabled | gg_utf8_popup | gg_rad_continueold);
+ psgcd[19].gd.cid = CID_IsMultiLayer;
+ psgcd[19].creator = GRadioCreate;
+ psgcd[19].gd.popup_msg = (unichar_t *) _("Allow editing of multiple colors and shades, fills and strokes.\nMulti layered fonts can only be output as type3 or svg fonts.");
+
+ psgcd[20].gd.pos.x = 12; psgcd[20].gd.pos.y = psgcd[19].gd.pos.y+14;
+ pslabel[20].text = (unichar_t *) _("_Stroked Font");
+ pslabel[20].text_is_1byte = true;
+ pslabel[20].text_in_resource = true;
+ psgcd[20].gd.label = &pslabel[20];
+ psgcd[20].gd.flags = sf->strokedfont ? (gg_visible | gg_enabled | gg_utf8_popup | gg_cb_on) : (gg_visible | gg_enabled | gg_utf8_popup);
+ psgcd[20].gd.cid = CID_IsStrokedFont;
+ psgcd[20].creator = GRadioCreate;
+ psgcd[20].gd.popup_msg = (unichar_t *) _("Glyphs will be composed of stroked lines rather than filled outlines.\nAll glyphs are stroked at the following width");
+
+ k=21;
+#else
+ psgcd[18].gd.pos.x = 12; psgcd[18].gd.pos.y = psgcd[17].gd.pos.y+16;
+ pslabel[18].text = (unichar_t *) _("_Stroked Font");
+ pslabel[18].text_is_1byte = true;
+ pslabel[18].text_in_resource = true;
+ psgcd[18].gd.label = &pslabel[18];
+ psgcd[18].gd.flags = sf->strokedfont ? (gg_visible | gg_enabled | gg_utf8_popup | gg_cb_on) : (gg_visible | gg_enabled | gg_utf8_popup);
+ psgcd[18].gd.cid = CID_IsStrokedFont;
+ psgcd[18].creator = GCheckBoxCreate;
+ psgcd[18].gd.popup_msg = (unichar_t *) _("Glyphs will be composed of stroked lines rather than filled outlines.\nAll glyphs are stroked at the following width");
+
+ k=19;
+#endif
+
+ psgcd[k].gd.pos.x = 12; psgcd[k].gd.pos.y = psgcd[k-1].gd.pos.y+20;
+ pslabel[k].text = (unichar_t *) _("Stroke _Width:");
+ pslabel[k].text_is_1byte = true;
+ pslabel[k].text_in_resource = true;
+ psgcd[k].gd.label = &pslabel[k];
+ psgcd[k].gd.flags = gg_visible | gg_enabled;
+ psgcd[k++].creator = GLabelCreate;
+
+ sprintf( swbuf,"%g", (double) sf->strokewidth );
+ psgcd[k].gd.pos.x = 115; psgcd[k].gd.pos.y = psgcd[k-1].gd.pos.y-6; psgcd[k].gd.pos.width = 137;
+ psgcd[k].gd.flags = gg_visible | gg_enabled;
+ pslabel[k].text = (unichar_t *) swbuf;
+ pslabel[k].text_is_1byte = true;
+ psgcd[k].gd.label = &pslabel[k];
+ psgcd[k].gd.cid = CID_StrokeWidth;
+ psgcd[k++].creator = GTextFieldCreate;
+
+ psgcd[k].gd.pos.x = psgcd[k-2].gd.pos.x; psgcd[k].gd.pos.y = psgcd[k-1].gd.pos.y+32;
+ psgcd[k].gd.flags = gg_visible | gg_enabled;
+ pslabel[k].text = (unichar_t *) _("Interpretation:");
+ pslabel[k].text_is_1byte = true;
+ pslabel[k].text_in_resource = true;
+ psgcd[k].gd.label = &pslabel[k];
+ psgcd[k++].creator = GLabelCreate;
+
+ psgcd[k].gd.pos.x = psgcd[k-2].gd.pos.x; psgcd[k].gd.pos.y = psgcd[k-1].gd.pos.y-6;
+ psgcd[k].gd.flags = gg_visible | gg_enabled;
+ psgcd[k].gd.u.list = interpretations;
+ psgcd[k].gd.cid = CID_Interpretation;
+ psgcd[k].creator = GListButtonCreate;
+ for ( i=0; interpretations[i].text!=NULL || interpretations[i].line; ++i ) {
+ if ( (void *) (sf->uni_interp)==interpretations[i].userdata &&
+ interpretations[i].text!=NULL ) {
+ interpretations[i].selected = true;
+ psgcd[k].gd.label = &interpretations[i];
+ } else
+ interpretations[i].selected = false;
+ }
+ ++k;
+
+ psgcd[k].gd.pos.x = psgcd[k-2].gd.pos.x; psgcd[k].gd.pos.y = psgcd[k-1].gd.pos.y+32;
+ psgcd[k].gd.flags = gg_visible | gg_enabled;
+ pslabel[k].text = (unichar_t *) _("Name List:");
+ pslabel[k].text_is_1byte = true;
+ pslabel[k].text_in_resource = true;
+ psgcd[k].gd.label = &pslabel[k];
+ psgcd[k++].creator = GLabelCreate;
+
+ psgcd[k].gd.pos.x = psgcd[k-2].gd.pos.x; psgcd[k].gd.pos.y = psgcd[k-1].gd.pos.y-6;
+ psgcd[k].gd.flags = gg_visible | gg_enabled;
+ psgcd[k].gd.cid = CID_Namelist;
+ psgcd[k].creator = GListButtonCreate;
+ nlnames = AllNamelistNames();
+ for ( i=0; nlnames[i]!=NULL; ++i);
+ namelistnames = gcalloc(i+1,sizeof(GTextInfo));
+ for ( i=0; nlnames[i]!=NULL; ++i) {
+ namelistnames[i].text = (unichar_t *) nlnames[i];
+ namelistnames[i].text_is_1byte = true;
+ if ( strcmp(_(sf->for_new_glyphs->title),nlnames[i])==0 ) {
+ namelistnames[i].selected = true;
+ psgcd[k].gd.label = &namelistnames[i];
+ }
+ }
+ psgcd[k++].gd.u.list = namelistnames;
+ free(nlnames);
+
+
+ if ( sf->subfontcnt!=0 ) {
+ for ( i=0; i<=13; ++i )
+ psgcd[i].gd.flags &= ~gg_enabled;
+ } else if ( sf->cidmaster!=NULL ) {
+ for ( i=14; i<=16; ++i )
+ psgcd[i].gd.flags &= ~gg_enabled;
+ }
+
+ psarray[0] = &psb2[0];
+ psarray[1] = &psgcd[14];
+ psarray[2] = &psb2[1];
+ psarray[3] = &psgcd[17];
+ psarray[4] = &psgcd[18];
+#ifdef FONTFORGE_CONFIG_TYPE3
+ psarray[5] = &psgcd[19];
+ psarray[6] = &psgcd[20];
+ j=7;
+#else
+ j=5;
+#endif
+ psarray[j++] = &psb2[2];
+ psrow = j;
+ psarray[j++] = GCD_Glue;
+ psarray[j++] = NULL;
+
+ psarray2[0] = &psgcd[0]; psarray2[1] = &psgcd[1]; psarray2[2] = &psgcd[2]; psarray2[3] = &psgcd[3]; psarray2[4] = NULL;
+ psarray2[5] = &psgcd[4]; psarray2[6] = &psgcd[5]; psarray2[7] = &psgcd[6]; psarray2[8] = GCD_ColSpan; psarray2[9] = NULL;
+ psarray2[10] = &psgcd[8]; psarray2[11] = &psgcd[7]; psarray2[12] = &psgcd[9]; psarray2[13] = GCD_ColSpan; psarray2[14] = NULL;
+ psarray2[15] = &psgcd[11]; psarray2[16] = &psgcd[10]; psarray2[17] = &psgcd[12]; psarray2[18] = &psgcd[13]; psarray2[19] = NULL;
+ psarray2[20] = NULL;
+
+ psarray3[0] = &psgcd[15]; psarray3[1] = &psgcd[16]; psarray3[2] = NULL;
+
+ psarray4[0] = &psgcd[k-6]; psarray4[1] = &psgcd[k-5]; psarray4[2] = NULL;
+ psarray4[3] = &psgcd[k-4]; psarray4[4] = &psgcd[k-3]; psarray4[5] = NULL;
+ psarray4[6] = &psgcd[k-2]; psarray4[7] = &psgcd[k-1]; psarray4[8] = NULL;
+ psarray4[9] = NULL;
+
+ memset(psb,0,sizeof(psb));
+ psb[0].gd.flags = gg_enabled|gg_visible;
+ psb[0].gd.u.boxelements = psarray;
+ psb[0].creator = GVBoxCreate;
+
+ memset(psb2,0,sizeof(psb2));
+ psb2[0].gd.flags = gg_enabled|gg_visible;
+ psb2[0].gd.u.boxelements = psarray2;
+ psb2[0].creator = GHVBoxCreate;
+
+ psb2[1].gd.flags = gg_enabled|gg_visible;
+ psb2[1].gd.u.boxelements = psarray3;
+ psb2[1].creator = GHBoxCreate;
+
+ psb2[2].gd.flags = gg_enabled|gg_visible;
+ psb2[2].gd.u.boxelements = psarray4;
+ psb2[2].creator = GHVBoxCreate;
+/******************************************************************************/
+
+ memset(&plabel,0,sizeof(plabel));
+ memset(&pgcd,0,sizeof(pgcd));
+
+ pgcd[0].gd.pos.x = 10; pgcd[0].gd.pos.y = 6;
+ pgcd[0].gd.pos.width = 240; pgcd[0].gd.pos.height = 8*12+10;
+ pgcd[0].gd.flags = gg_visible | gg_enabled;
+ pgcd[0].gd.cid = CID_PrivateEntries;
+ pgcd[0].gd.u.list = PI_ListSet(sf);
+ pgcd[0].gd.handle_controlevent = PI_ListSel;
+ pgcd[0].creator = GListCreate;
+
+ pgcd[1].gd.pos.x = 10; pgcd[1].gd.pos.y = pgcd[0].gd.pos.y+pgcd[0].gd.pos.height+10;
+ pgcd[1].gd.pos.width = pgcd[0].gd.pos.width; pgcd[1].gd.pos.height = 8*12+10;
+ pgcd[1].gd.flags = gg_visible | gg_enabled;
+ pgcd[1].gd.cid = CID_PrivateValues;
+ pgcd[1].creator = GTextAreaCreate;
+
+ pgcd[2].gd.pos.x = 10; pgcd[2].gd.pos.y = 300-35-30;
+ pgcd[2].gd.pos.width = -1; pgcd[2].gd.pos.height = 0;
+ pgcd[2].gd.flags = gg_visible | gg_enabled ;
+ plabel[2].text = (unichar_t *) _("_Add");
+ plabel[2].text_is_1byte = true;
+ plabel[2].text_in_resource = true;
+ pgcd[2].gd.label = &plabel[2];
+ pgcd[2].gd.handle_controlevent = PI_Add;
+ pgcd[2].gd.cid = CID_Add;
+ pgcd[2].creator = GButtonCreate;
+
+ pgcd[3].gd.pos.x = (260)/2-GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor)-5;
+ pgcd[3].gd.pos.y = pgcd[2].gd.pos.y;
+ pgcd[3].gd.pos.width = -1; pgcd[3].gd.pos.height = 0;
+ pgcd[3].gd.flags = gg_visible ;
+ plabel[3].text = (unichar_t *) _("_Guess");
+ plabel[3].text_is_1byte = true;
+ plabel[3].text_in_resource = true;
+ pgcd[3].gd.label = &plabel[3];
+ pgcd[3].gd.handle_controlevent = PI_Guess;
+ pgcd[3].gd.cid = CID_Guess;
+ pgcd[3].creator = GButtonCreate;
+
+ pgcd[4].gd.pos.x = -(260/2-GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor)-5);
+ pgcd[4].gd.pos.y = pgcd[2].gd.pos.y;
+ pgcd[4].gd.pos.width = -1; pgcd[4].gd.pos.height = 0;
+ pgcd[4].gd.flags = gg_visible | gg_utf8_popup ;
+/* GT: This is an abbreviation for Histogram */
+ plabel[4].text = (unichar_t *) _("_Hist.");
+ plabel[4].text_is_1byte = true;
+ plabel[4].text_in_resource = true;
+ pgcd[4].gd.label = &plabel[4];
+ pgcd[4].gd.handle_controlevent = PI_Hist;
+ pgcd[4].gd.cid = CID_Hist;
+ pgcd[4].gd.popup_msg = (unichar_t *) _("Histogram Dialog");
+ pgcd[4].creator = GButtonCreate;
+
+ pgcd[5].gd.pos.x = -10; pgcd[5].gd.pos.y = pgcd[2].gd.pos.y;
+ pgcd[5].gd.pos.width = -1; pgcd[5].gd.pos.height = 0;
+ pgcd[5].gd.flags = gg_visible | gg_enabled ;
+ plabel[5].text = (unichar_t *) _("_Remove");
+ plabel[5].text_is_1byte = true;
+ plabel[5].text_in_resource = true;
+ pgcd[5].gd.label = &plabel[5];
+ pgcd[5].gd.handle_controlevent = PI_Delete;
+ pgcd[5].gd.cid = CID_Remove;
+ pgcd[5].creator = GButtonCreate;
+
+ ppbuttons[0] = &pgcd[2]; ppbuttons[1] = &pgcd[3];
+ ppbuttons[2] = &pgcd[4]; ppbuttons[3] = &pgcd[5]; ppbuttons[4] = NULL;
+
+ pparray[0] = &pgcd[0]; pparray[1] = &pgcd[1]; pparray[2] = &ppbox[2];
+ pparray[3] = NULL;
+
+ memset(ppbox,0,sizeof(ppbox));
+ ppbox[0].gd.flags = gg_enabled|gg_visible;
+ ppbox[0].gd.u.boxelements = pparray;
+ ppbox[0].creator = GVBoxCreate;
+
+ ppbox[2].gd.flags = gg_enabled|gg_visible;
+ ppbox[2].gd.u.boxelements = ppbuttons;
+ ppbox[2].creator = GHBoxCreate;
+/******************************************************************************/
+ memset(&vlabel,0,sizeof(vlabel));
+ memset(&vgcd,0,sizeof(vgcd));
+
+ vgcd[0].gd.pos.x = 10; vgcd[0].gd.pos.y = 12;
+ vlabel[0].text = (unichar_t *) _("_Weight Class");
+ vlabel[0].text_is_1byte = true;
+ vlabel[0].text_in_resource = true;
+ vgcd[0].gd.label = &vlabel[0];
+ vgcd[0].gd.flags = gg_visible | gg_enabled;
+ vgcd[0].creator = GLabelCreate;
+
+ vgcd[1].gd.pos.x = 90; vgcd[1].gd.pos.y = vgcd[0].gd.pos.y-6; vgcd[1].gd.pos.width = 140;
+ vgcd[1].gd.flags = gg_visible | gg_enabled;
+ vgcd[1].gd.cid = CID_WeightClass;
+ vgcd[1].gd.u.list = weightclass;
+ vgcd[1].creator = GListFieldCreate;
+
+ vgcd[2].gd.pos.x = 10; vgcd[2].gd.pos.y = vgcd[1].gd.pos.y+26+6;
+ vlabel[2].text = (unichar_t *) _("Width _Class");
+ vlabel[2].text_is_1byte = true;
+ vlabel[2].text_in_resource = true;
+ vgcd[2].gd.label = &vlabel[2];
+ vgcd[2].gd.flags = gg_visible | gg_enabled;
+ vgcd[2].creator = GLabelCreate;
+
+ vgcd[3].gd.pos.x = 90; vgcd[3].gd.pos.y = vgcd[2].gd.pos.y-6;
+ vgcd[3].gd.flags = gg_visible | gg_enabled;
+ vgcd[3].gd.cid = CID_WidthClass;
+ vgcd[3].gd.u.list = widthclass;
+ vgcd[3].creator = GListButtonCreate;
+
+ vgcd[4].gd.pos.x = 10; vgcd[4].gd.pos.y = vgcd[3].gd.pos.y+26+6;
+ vlabel[4].text = (unichar_t *) _("P_FM Family");
+ vlabel[4].text_is_1byte = true;
+ vlabel[4].text_in_resource = true;
+ vgcd[4].gd.label = &vlabel[4];
+ vgcd[4].gd.flags = gg_visible | gg_enabled;
+ vgcd[4].creator = GLabelCreate;
+
+ vgcd[5].gd.pos.x = 90; vgcd[5].gd.pos.y = vgcd[4].gd.pos.y-6; vgcd[5].gd.pos.width = 140;
+ vgcd[5].gd.flags = gg_visible | gg_enabled;
+ vgcd[5].gd.cid = CID_PFMFamily;
+ vgcd[5].gd.u.list = pfmfamily;
+ vgcd[5].creator = GListButtonCreate;
+
+ vgcd[6].gd.pos.x = 10; vgcd[6].gd.pos.y = vgcd[5].gd.pos.y+26+6;
+ vlabel[6].text = (unichar_t *) _("_Embeddable");
+ vlabel[6].text_is_1byte = true;
+ vlabel[6].text_in_resource = true;
+ vgcd[6].gd.label = &vlabel[6];
+ vgcd[6].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ vgcd[6].gd.popup_msg = (unichar_t *) _("Can this font be embedded in a downloadable (pdf)\ndocument, and if so, what behaviors are permitted on\nboth the document and the font.");
+ vgcd[6].creator = GLabelCreate;
+
+ vgcd[7].gd.pos.x = 90; vgcd[7].gd.pos.y = vgcd[6].gd.pos.y-6;
+ vgcd[7].gd.pos.width = 140;
+ vgcd[7].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ vgcd[7].gd.cid = CID_FSType;
+ vgcd[7].gd.u.list = fstype;
+ vgcd[7].gd.popup_msg = vgcd[6].gd.popup_msg;
+ vgcd[7].creator = GListButtonCreate;
+ fstype[0].selected = fstype[1].selected =
+ fstype[2].selected = fstype[3].selected = false;
+ if ( sf->pfminfo.fstype&0x8 /* also catches the "not set" case == -1 */ )
+ i = 2;
+ else if ( sf->pfminfo.fstype&0x4 )
+ i = 1;
+ else if ( sf->pfminfo.fstype&0x2 )
+ i = 0;
+ else
+ i = 3;
+ fstype[i].selected = true;
+ vgcd[7].gd.label = &fstype[i];
+
+ vgcd[8].gd.pos.x = 20; vgcd[8].gd.pos.y = vgcd[7].gd.pos.y+26;
+ vlabel[8].text = (unichar_t *) _("No Subsetting");
+ vlabel[8].text_is_1byte = true;
+ vgcd[8].gd.label = &vlabel[8];
+ vgcd[8].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ if ( sf->pfminfo.fstype!=-1 && (sf->pfminfo.fstype&0x100) )
+ vgcd[8].gd.flags |= gg_cb_on;
+ vgcd[8].gd.popup_msg = (unichar_t *) _("If set then the entire font must be\nembedded in a document when any character is.\nOtherwise the document creator need\nonly include the characters it uses.");
+ vgcd[8].gd.cid = CID_NoSubsetting;
+ vgcd[8].creator = GCheckBoxCreate;
+
+ vgcd[9].gd.pos.x = 110; vgcd[9].gd.pos.y = vgcd[8].gd.pos.y;
+ vlabel[9].text = (unichar_t *) _("Only Embed Bitmaps");
+ vlabel[9].text_is_1byte = true;
+ vgcd[9].gd.label = &vlabel[9];
+ vgcd[9].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ if ( sf->pfminfo.fstype!=-1 && ( sf->pfminfo.fstype&0x200 ))
+ vgcd[9].gd.flags |= gg_cb_on;
+ vgcd[9].gd.popup_msg = (unichar_t *) _("Only Bitmaps may be embedded.\nOutline descriptions may not be\n(if font file contains no bitmaps\nthen nothing may be embedded).");
+ vgcd[9].gd.cid = CID_OnlyBitmaps;
+ vgcd[9].creator = GCheckBoxCreate;
+
+ vgcd[10].gd.pos.x = 10; vgcd[10].gd.pos.y = vgcd[9].gd.pos.y+24;
+ vlabel[10].text = (unichar_t *) _("Vendor ID:");
+ vlabel[10].text_is_1byte = true;
+ vgcd[10].gd.label = &vlabel[10];
+ vgcd[10].gd.flags = gg_visible | gg_enabled;
+ vgcd[10].creator = GLabelCreate;
+
+ vgcd[11].gd.pos.x = 90; vgcd[11].gd.pos.y = vgcd[11-1].gd.pos.y-4;
+ vgcd[11].gd.pos.width = 50;
+ vgcd[11].gd.flags = gg_visible | gg_enabled;
+ /* value set later */
+ vgcd[11].gd.cid = CID_Vendor;
+ vgcd[11].creator = GTextFieldCreate;
+
+ vgcd[12].gd.pos.x = 10; vgcd[12].gd.pos.y = vgcd[11].gd.pos.y+24+6;
+ vlabel[12].text = (unichar_t *) _("_IBM Family:");
+ vlabel[12].text_is_1byte = true;
+ vlabel[12].text_in_resource = true;
+ vgcd[12].gd.label = &vlabel[12];
+ vgcd[12].gd.flags = gg_visible | gg_enabled;
+ vgcd[12].creator = GLabelCreate;
+
+ vgcd[13].gd.pos.x = 90; vgcd[13].gd.pos.y = vgcd[12].gd.pos.y-4; vgcd[13].gd.pos.width = vgcd[7].gd.pos.width;
+ vgcd[13].gd.flags = gg_visible | gg_enabled;
+ vgcd[13].gd.cid = CID_IBMFamily;
+ vgcd[13].gd.u.list = ibmfamily;
+ vgcd[13].creator = GListButtonCreate;
+
+ vgcd[14].gd.pos.x = 10; vgcd[14].gd.pos.y = vgcd[13].gd.pos.y+24+6;
+ vlabel[14].text = (unichar_t *) _("Weight, Width, Slope Only");
+ vlabel[14].text_is_1byte = true;
+ vlabel[14].text_in_resource = true;
+ vgcd[14].gd.label = &vlabel[14];
+ vgcd[14].gd.cid = CID_WeightWidthSlopeOnly;
+ vgcd[14].gd.popup_msg = (unichar_t *) _("MS needs to know whether a font family's members differ\nonly in weight, width and slope (and not in other variables\nlike optical size)." );
+ vgcd[14].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ vgcd[14].creator = GCheckBoxCreate;
+
+ vgcd[15].gd.pos.x = 10; vgcd[15].gd.pos.y = vgcd[11].gd.pos.y+24+6;
+ vlabel[15].text = (unichar_t *) _("_OS/2 Version");
+ vlabel[15].text_is_1byte = true;
+ vlabel[15].text_in_resource = true;
+ vgcd[15].gd.label = &vlabel[15];
+ vgcd[15].gd.popup_msg = (unichar_t *) _("The 'OS/2' table has changed slightly over the years,\nGenerally fields have been added, but occasionally their\nmeanings have been redefined." );
+ vgcd[15].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ vgcd[15].creator = GLabelCreate;
+
+ vgcd[16].gd.pos.x = 90; vgcd[16].gd.pos.y = vgcd[15].gd.pos.y-4; vgcd[16].gd.pos.width = vgcd[7].gd.pos.width;
+ vgcd[16].gd.flags = gg_visible | gg_enabled;
+ vgcd[16].gd.cid = CID_OS2Version;
+ vgcd[16].gd.u.list = os2versions;
+ vgcd[16].creator = GListFieldCreate;
+
+ vradio[0] = GCD_Glue; vradio[1] = &vgcd[8]; vradio[2] = &vgcd[9]; vradio[3] = GCD_Glue; vradio[4] = NULL;
+
+ varray[0] = &vgcd[15]; varray[1] = &vgcd[16]; varray[2] = NULL;
+ varray[3] = &vgcd[0]; varray[4] = &vgcd[1]; varray[5] = NULL;
+ varray[6] = &vgcd[2]; varray[7] = &vgcd[3]; varray[8] = NULL;
+ varray[9] = &vgcd[4]; varray[10] = &vgcd[5]; varray[11] = NULL;
+ varray[12] = &vgcd[6]; varray[13] = &vgcd[7]; varray[14] = NULL;
+ varray[15] = &vbox[2]; varray[16] = GCD_ColSpan; varray[17] = NULL;
+ varray[18] = &vgcd[10]; varray[19] = &vgcd[11]; varray[20] = NULL;
+ varray[21] = &vgcd[12]; varray[22] = &vgcd[13]; varray[23] = NULL;
+ varray[24] = &vgcd[14]; varray[25] = GCD_ColSpan; varray[26] = NULL;
+ varray[27] = GCD_Glue; varray[28] = GCD_Glue; varray[29] = NULL;
+ varray[30] = GCD_Glue; varray[31] = GCD_Glue; varray[32] = NULL;
+ varray[33] = varray[37] = NULL;
+
+ memset(vbox,0,sizeof(vbox));
+ vbox[0].gd.flags = gg_enabled|gg_visible;
+ vbox[0].gd.u.boxelements = varray;
+ vbox[0].creator = GHVBoxCreate;
+
+ vbox[2].gd.flags = gg_enabled|gg_visible;
+ vbox[2].gd.u.boxelements = vradio;
+ vbox[2].creator = GHBoxCreate;
+
+/******************************************************************************/
+
+ memset(&metgcd,0,sizeof(metgcd));
+ memset(&metlabel,'\0',sizeof(metlabel));
+
+ i = j = 0;
+
+ metgcd[i].gd.pos.x = 10; metgcd[i].gd.pos.y = 9;
+ metlabel[i].text = (unichar_t *) _("Win _Ascent Offset:");
+ metlabel[i].text_is_1byte = true;
+ metlabel[i].text_in_resource = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ metgcd[i].gd.popup_msg = (unichar_t *) _("Anything outside the OS/2 WinAscent &\nWinDescent fields will be clipped by windows.\nThis includes marks, etc. that have been repositioned by GPOS.\n(The descent field is usually positive.)\nIf the \"[] Is Offset\" checkbox is clear then\nany number you enter will be the value used in OS/2.\nIf set then any number you enter will be added to the\nfont's bounds. You should leave this\nfield 0 and check \"[*] Is Offset\" in most cases.");
+ metgcd[i].gd.cid = CID_WinAscentLab;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GLabelCreate;
+
+ metgcd[i].gd.pos.x = 125; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y-4;
+ metgcd[i].gd.pos.width = 50;
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ /* value set later */
+ metgcd[i].gd.cid = CID_WinAscent;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GTextFieldCreate;
+
+ metgcd[i].gd.pos.x = 178; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y;
+ metlabel[i].text = (unichar_t *) _("Is Offset");
+ metlabel[i].text_is_1byte = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ /* value set later */
+ metgcd[i].gd.cid = CID_WinAscentIsOff;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metgcd[i].gd.handle_controlevent = GFI_AsDesIsOff;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GCheckBoxCreate;
+ metarray[j++] = NULL;
+
+ metgcd[i].gd.pos.x = 10; metgcd[i].gd.pos.y = metgcd[i-2].gd.pos.y+26+4;
+ metlabel[i].text = (unichar_t *) _("Win _Descent Offset:");
+ metlabel[i].text_is_1byte = true;
+ metlabel[i].text_in_resource = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metgcd[i].gd.cid = CID_WinDescentLab;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GLabelCreate;
+
+ metgcd[i].gd.pos.x = 125; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y-4;
+ metgcd[i].gd.pos.width = 50;
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ /* value set later */
+ metgcd[i].gd.cid = CID_WinDescent;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GTextFieldCreate;
+
+ metgcd[i].gd.pos.x = 178; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y;
+ metlabel[i].text = (unichar_t *) _("Is Offset");
+ metlabel[i].text_is_1byte = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ /* value set later */
+ metgcd[i].gd.cid = CID_WinDescentIsOff;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metgcd[i].gd.handle_controlevent = GFI_AsDesIsOff;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GCheckBoxCreate;
+ metarray[j++] = NULL;
+
+ metgcd[i].gd.pos.x = 10; metgcd[i].gd.pos.y = metgcd[i-2].gd.pos.y+26+4;
+ metlabel[i].text = (unichar_t *) _("_Typo Ascent Offset:");
+ metlabel[i].text_is_1byte = true;
+ metlabel[i].text_in_resource = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ metgcd[i].gd.popup_msg = (unichar_t *) _("The type ascent&descent fields are>supposed<\nto specify the line spacing on windows.\nIn fact usually the win ascent/descent fields do.\n(The descent field is usually negative.)\nIf the \"[] Is Offset\" checkbox is clear then\nany number you enter will be the value used in OS/2.\nIf set then any number you enter will be added to the\nEm-size. You should leave this\nfield 0 and check \"[*] Is Offset\" in most cases.");
+ metgcd[i].gd.cid = CID_TypoAscentLab;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GLabelCreate;
+
+ metgcd[i].gd.pos.x = 125; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y-4;
+ metgcd[i].gd.pos.width = 50;
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ /* value set later */
+ metgcd[i].gd.cid = CID_TypoAscent;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GTextFieldCreate;
+
+ metgcd[i].gd.pos.x = 178; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y;
+ metlabel[i].text = (unichar_t *) _("Is Offset");
+ metlabel[i].text_is_1byte = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ /* value set later */
+ metgcd[i].gd.cid = CID_TypoAscentIsOff;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metgcd[i].gd.handle_controlevent = GFI_AsDesIsOff;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GCheckBoxCreate;
+ metarray[j++] = NULL;
+
+ metgcd[i].gd.pos.x = 5; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y;
+ metlabel[i].text = (unichar_t *) _("Really use Typo metrics");
+ metlabel[i].text_is_1byte = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ /* value set later */
+ metgcd[i].gd.cid = CID_UseTypoMetrics;
+ metgcd[i].gd.popup_msg = (unichar_t *) _("The spec already says that the typeo metrics should be\nused to determine line spacing. But so many\nprograms fail to follow the spec that MS desided a bit\nwas needed to remind them to do so.");
+ metarray[j++] = &metgcd[i]; metarray[j++] = GCD_ColSpan; metarray[j++] = GCD_Glue;
+ metgcd[i++].creator = GCheckBoxCreate;
+ metarray[j++] = NULL;
+
+ metgcd[i].gd.pos.x = 10; metgcd[i].gd.pos.y = metgcd[i-2].gd.pos.y+26+4;
+ metlabel[i].text = (unichar_t *) _("T_ypo Descent Offset:");
+ metlabel[i].text_is_1byte = true;
+ metlabel[i].text_in_resource = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metgcd[i].gd.cid = CID_TypoDescentLab;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GLabelCreate;
+
+ metgcd[i].gd.pos.x = 125; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y-4;
+ metgcd[i].gd.pos.width = 50;
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ /* value set later */
+ metgcd[i].gd.cid = CID_TypoDescent;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GTextFieldCreate;
+
+ metgcd[i].gd.pos.x = 178; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y;
+ metlabel[i].text = (unichar_t *) _("Is Offset");
+ metlabel[i].text_is_1byte = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ /* value set later */
+ metgcd[i].gd.cid = CID_TypoDescentIsOff;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metgcd[i].gd.handle_controlevent = GFI_AsDesIsOff;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GCheckBoxCreate;
+ metarray[j++] = NULL;
+
+ metgcd[i].gd.pos.x = 10; metgcd[i].gd.pos.y = metgcd[i-2].gd.pos.y+26+4;
+ metlabel[i].text = (unichar_t *) _("Typo Line _Gap:");
+ metlabel[i].text_is_1byte = true;
+ metlabel[i].text_in_resource = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ metgcd[i].gd.popup_msg = (unichar_t *) _("Sets the TypoLinegap field in the OS/2 table, used on MS Windows");
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GLabelCreate;
+
+ metgcd[i].gd.pos.x = 125; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y-4;
+ metgcd[i].gd.pos.width = 50;
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ /* Line gap value set later */
+ metgcd[i].gd.cid = CID_TypoLineGap;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GTextFieldCreate;
+ metarray[j++] = GCD_Glue;
+ metarray[j++] = NULL;
+
+ metgcd[i].gd.pos.x = 10; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y+26+4;
+ metlabel[i].text = (unichar_t *) _("_HHead Ascent Offset:");
+ metlabel[i].text_is_1byte = true;
+ metlabel[i].text_in_resource = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ metgcd[i].gd.popup_msg = (unichar_t *) _("This specifies the line spacing on the mac.\n(The descent field is usually negative.)\nIf the \"[] Is Offset\" checkbox is clear then\nany number you enter will be the value used in hhea.\nIf set then any number you enter will be added to the\nfont's bounds. You should leave this\nfield 0 and check \"[*] Is Offset\" in most cases.");
+ metgcd[i].gd.cid = CID_HHeadAscentLab;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GLabelCreate;
+
+ metgcd[i].gd.pos.x = 125; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y-4;
+ metgcd[i].gd.pos.width = 50;
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ /* value set later */
+ metgcd[i].gd.cid = CID_HHeadAscent;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GTextFieldCreate;
+
+ metgcd[i].gd.pos.x = 178; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y;
+ metlabel[i].text = (unichar_t *) _("Is Offset");
+ metlabel[i].text_is_1byte = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ /* value set later */
+ metgcd[i].gd.cid = CID_HHeadAscentIsOff;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metgcd[i].gd.handle_controlevent = GFI_AsDesIsOff;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GCheckBoxCreate;
+ metarray[j++] = NULL;
+
+ metgcd[i].gd.pos.x = 10; metgcd[i].gd.pos.y = metgcd[i-2].gd.pos.y+26+4;
+ metlabel[i].text = (unichar_t *) _("HHead De_scent Offset:");
+ metlabel[i].text_in_resource = true;
+ metlabel[i].text_is_1byte = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metgcd[i].gd.cid = CID_HHeadDescentLab;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GLabelCreate;
+
+ metgcd[i].gd.pos.x = 125; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y-4;
+ metgcd[i].gd.pos.width = 50;
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ /* value set later */
+ metgcd[i].gd.cid = CID_HHeadDescent;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GTextFieldCreate;
+
+ metgcd[i].gd.pos.x = 178; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y;
+ metlabel[i].text = (unichar_t *) _("Is Offset");
+ metlabel[i].text_is_1byte = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ /* value set later */
+ metgcd[i].gd.cid = CID_HHeadDescentIsOff;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metgcd[i].gd.handle_controlevent = GFI_AsDesIsOff;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GCheckBoxCreate;
+ metarray[j++] = NULL;
+
+ metgcd[i].gd.pos.x = 10; metgcd[i].gd.pos.y = metgcd[i-2].gd.pos.y+26+4;
+ metlabel[i].text = (unichar_t *) _("HHead _Line Gap:");
+ metlabel[i].text_is_1byte = true;
+ metlabel[i].text_in_resource = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ metgcd[i].gd.popup_msg = (unichar_t *) _("Sets the linegap field in the hhea table, used on the mac");
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GLabelCreate;
+
+ metgcd[i].gd.pos.x = 125; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y-4;
+ metgcd[i].gd.pos.width = 50;
+ metgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ /* Line gap value set later */
+ metgcd[i].gd.cid = CID_LineGap;
+ metgcd[i].gd.popup_msg = metgcd[i-1].gd.popup_msg;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GTextFieldCreate;
+ metarray[j++] = GCD_Glue;
+ metarray[j++] = NULL;
+
+ metgcd[i].gd.pos.x = 10; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y+26+6;
+ metlabel[i].text = (unichar_t *) _("VHead _Column Spacing:");
+ metlabel[i].text_is_1byte = true;
+ metlabel[i].text_in_resource = true;
+ metgcd[i].gd.label = &metlabel[i];
+ metgcd[i].gd.flags = sf->hasvmetrics ? (gg_visible | gg_enabled | gg_utf8_popup) : (gg_visible | gg_utf8_popup);
+ metgcd[i].gd.popup_msg = (unichar_t *) _("Sets the linegap field in the vhea table.\nThis is the horizontal spacing between rows\nof vertically set text.");
+ metgcd[i].gd.cid = CID_VLineGapLab;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GLabelCreate;
+
+ metgcd[i].gd.pos.x = 125; metgcd[i].gd.pos.y = metgcd[i-1].gd.pos.y-6;
+ metgcd[i].gd.pos.width = 50;
+ metgcd[i].gd.flags = sf->hasvmetrics ? (gg_visible | gg_enabled | gg_utf8_popup) : (gg_visible | gg_utf8_popup);
+ /* V Line gap value set later */
+ metgcd[i].gd.cid = CID_VLineGap;
+ metgcd[i].gd.popup_msg = metgcd[17].gd.popup_msg;
+ metarray[j++] = &metgcd[i];
+ metgcd[i++].creator = GTextFieldCreate;
+ metarray[j++] = GCD_Glue;
+ metarray[j++] = NULL;
+ metarray[j++] = GCD_Glue; metarray[j++] = GCD_Glue; metarray[j++] = GCD_Glue;
+
+ metarray[j++] = NULL; metarray[j++] = NULL;
+
+ memset(metbox,0,sizeof(metbox));
+ metbox[0].gd.flags = gg_enabled|gg_visible;
+ metbox[0].gd.u.boxelements = metarray;
+ metbox[0].creator = GHVBoxCreate;
+/******************************************************************************/
+
+ memset(&ssgcd,0,sizeof(ssgcd));
+ memset(&sslabel,'\0',sizeof(sslabel));
+
+ i = j = 0;
+
+ ssgcd[i].gd.pos.x = 5; ssgcd[i].gd.pos.y = 5;
+ sslabel[i].text = (unichar_t *) S_("SubscriptSuperUse|Default");
+ sslabel[i].text_is_1byte = true;
+ ssgcd[i].gd.label = &sslabel[i];
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ /* value set later */
+ ssgcd[i].gd.cid = CID_SubSuperDefault;
+ ssgcd[i].gd.handle_controlevent = GFI_SubSuperDefault;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GCheckBoxCreate;
+ ssarray[j++] = GCD_Glue; ssarray[j++] = GCD_Glue; ssarray[j++] = GCD_Glue;
+ ssarray[j++] = NULL;
+
+ ssgcd[i].gd.pos.x = 5; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y+16;
+ sslabel[i].text = (unichar_t *) _("Subscript");
+ sslabel[i].text_is_1byte = true;
+ ssgcd[i].gd.label = &sslabel[i];
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GLabelCreate;
+
+ ssgcd[i].gd.pos.x = 120; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y-4;
+/* GT: X is a coordinate, the leading spaces help to align it */
+ sslabel[i].text = (unichar_t *) _(" X");
+ sslabel[i].text_is_1byte = true;
+ ssgcd[i].gd.label = &sslabel[i];
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GLabelCreate;
+
+ ssgcd[i].gd.pos.x = 180; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y;
+/* GT: Y is a coordinate, the leading spaces help to align it */
+ sslabel[i].text = (unichar_t *) _("Y");
+ sslabel[i].text_is_1byte = true;
+ ssgcd[i].gd.label = &sslabel[i];
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GLabelCreate;
+ ssarray[j++] = GCD_Glue; ssarray[j++] = NULL;
+
+ ssgcd[i].gd.pos.x = 10; ssgcd[i].gd.pos.y = ssgcd[i-3].gd.pos.y+14+4;
+ sslabel[i].text = (unichar_t *) _("Size");
+ sslabel[i].text_is_1byte = true;
+ ssgcd[i].gd.label = &sslabel[i];
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GLabelCreate;
+
+ ssgcd[i].gd.pos.x = 100; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y-6;
+ ssgcd[i].gd.pos.width = 50;
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ /* set later */
+ ssgcd[i].gd.cid = CID_SubXSize;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GTextFieldCreate;
+
+ ssgcd[i].gd.pos.x = 160; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y;
+ ssgcd[i].gd.pos.width = 50;
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ /* set later */
+ ssgcd[i].gd.cid = CID_SubYSize;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GTextFieldCreate;
+ ssarray[j++] = GCD_Glue; ssarray[j++] = NULL;
+
+ ssgcd[i].gd.pos.x = 10; ssgcd[i].gd.pos.y = ssgcd[i-3].gd.pos.y+26;
+ sslabel[i].text = (unichar_t *) _("Offset");
+ sslabel[i].text_is_1byte = true;
+ ssgcd[i].gd.label = &sslabel[i];
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GLabelCreate;
+
+ ssgcd[i].gd.pos.x = 100; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y-6;
+ ssgcd[i].gd.pos.width = 50;
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ /* set later */
+ ssgcd[i].gd.cid = CID_SubXOffset;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GTextFieldCreate;
+
+ ssgcd[i].gd.pos.x = 160; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y;
+ ssgcd[i].gd.pos.width = 50;
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ /* set later */
+ ssgcd[i].gd.cid = CID_SubYOffset;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GTextFieldCreate;
+ ssarray[j++] = GCD_Glue; ssarray[j++] = NULL;
+
+
+ ssgcd[i].gd.pos.x = 5; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y+30;
+ sslabel[i].text = (unichar_t *) _("Superscript");
+ sslabel[i].text_is_1byte = true;
+ ssgcd[i].gd.label = &sslabel[i];
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GLabelCreate;
+ ssarray[j++] = GCD_Glue; ssarray[j++] = GCD_Glue; ssarray[j++] = GCD_Glue;
+ ssarray[j++] = NULL;
+
+ ssgcd[i].gd.pos.x = 10; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y+14+4;
+ sslabel[i].text = (unichar_t *) _("Size");
+ sslabel[i].text_is_1byte = true;
+ ssgcd[i].gd.label = &sslabel[i];
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GLabelCreate;
+
+ ssgcd[i].gd.pos.x = 100; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y-6;
+ ssgcd[i].gd.pos.width = 50;
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ /* set later */
+ ssgcd[i].gd.cid = CID_SuperXSize;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GTextFieldCreate;
+
+ ssgcd[i].gd.pos.x = 160; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y;
+ ssgcd[i].gd.pos.width = 50;
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ /* set later */
+ ssgcd[i].gd.cid = CID_SuperYSize;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GTextFieldCreate;
+ ssarray[j++] = GCD_Glue; ssarray[j++] = NULL;
+
+ ssgcd[i].gd.pos.x = 10; ssgcd[i].gd.pos.y = ssgcd[i-3].gd.pos.y+26;
+ sslabel[i].text = (unichar_t *) _("Offset");
+ sslabel[i].text_is_1byte = true;
+ ssgcd[i].gd.label = &sslabel[i];
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GLabelCreate;
+
+ ssgcd[i].gd.pos.x = 100; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y-6;
+ ssgcd[i].gd.pos.width = 50;
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ /* set later */
+ ssgcd[i].gd.cid = CID_SuperXOffset;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GTextFieldCreate;
+
+ ssgcd[i].gd.pos.x = 160; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y;
+ ssgcd[i].gd.pos.width = 50;
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ /* set later */
+ ssgcd[i].gd.cid = CID_SuperYOffset;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GTextFieldCreate;
+ ssarray[j++] = GCD_Glue; ssarray[j++] = NULL;
+
+
+ ssgcd[i].gd.pos.x = 5; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y+30;
+ sslabel[i].text = (unichar_t *) _("Strikeout");
+ sslabel[i].text_is_1byte = true;
+ ssgcd[i].gd.label = &sslabel[i];
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GLabelCreate;
+ ssarray[j++] = GCD_Glue; ssarray[j++] = GCD_Glue; ssarray[j++] = GCD_Glue;
+ ssarray[j++] = NULL;
+
+ ssgcd[i].gd.pos.x = 10; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y+14+4;
+ sslabel[i].text = (unichar_t *) _("Size");
+ sslabel[i].text_is_1byte = true;
+ ssgcd[i].gd.label = &sslabel[i];
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GLabelCreate;
+ ssarray[j++] = GCD_Glue;
+
+ ssgcd[i].gd.pos.x = 160; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y-6;
+ ssgcd[i].gd.pos.width = 50;
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ /* set later */
+ ssgcd[i].gd.cid = CID_StrikeoutSize;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GTextFieldCreate;
+ ssarray[j++] = GCD_Glue; ssarray[j++] = NULL;
+
+ ssgcd[i].gd.pos.x = 10; ssgcd[i].gd.pos.y = ssgcd[i-2].gd.pos.y+26;
+ sslabel[i].text = (unichar_t *) _("Pos");
+ sslabel[i].text_is_1byte = true;
+ ssgcd[i].gd.label = &sslabel[i];
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GLabelCreate;
+ ssarray[j++] = GCD_Glue;
+
+ ssgcd[i].gd.pos.x = 160; ssgcd[i].gd.pos.y = ssgcd[i-1].gd.pos.y-6;
+ ssgcd[i].gd.pos.width = 50;
+ ssgcd[i].gd.flags = gg_visible | gg_enabled;
+ /* set later */
+ ssgcd[i].gd.cid = CID_StrikeoutPos;
+ ssarray[j++] = &ssgcd[i];
+ ssgcd[i++].creator = GTextFieldCreate;
+ ssarray[j++] = GCD_Glue; ssarray[j++] = NULL;
+
+ ssarray[j++] = GCD_Glue; ssarray[j++] = GCD_Glue; ssarray[j++] = GCD_Glue; ssarray[j++] = GCD_Glue;
+
+ ssarray[j++] = NULL; ssarray[j++] = NULL;
+
+ memset(ssbox,0,sizeof(ssbox));
+ ssbox[0].gd.flags = gg_enabled|gg_visible;
+ ssbox[0].gd.u.boxelements = ssarray;
+ ssbox[0].creator = GHVBoxCreate;
+/******************************************************************************/
+ memset(&panlabel,0,sizeof(panlabel));
+ memset(&pangcd,0,sizeof(pangcd));
+
+ i = j = 0;
+
+ pangcd[i].gd.pos.x = 5; pangcd[i].gd.pos.y = 5;
+ panlabel[i].text = (unichar_t *) S_("PanoseUse|Default");
+ panlabel[i].text_is_1byte = true;
+ pangcd[i].gd.label = &panlabel[i];
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ /* value set later */
+ pangcd[i].gd.cid = CID_PanDefault;
+ /*pangcd[i].gd.popup_msg = pangcd[i-1].gd.popup_msg;*/
+ pangcd[i].gd.handle_controlevent = GFI_PanoseDefault;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GCheckBoxCreate;
+ panarray[j++] = GCD_Glue; panarray[j++] = NULL;
+
+ pangcd[i].gd.pos.x = 20; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y+14+4;
+ panlabel[i].text = (unichar_t *) S_("Panose|_Family");
+ panlabel[i].text_is_1byte = true;
+ panlabel[i].text_in_resource = true;
+ pangcd[i].gd.label = &panlabel[i];
+ pangcd[i].gd.cid = CID_PanFamilyLab;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GLabelCreate;
+
+ pangcd[i].gd.pos.x = 100; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y-6; pangcd[i].gd.pos.width = 120;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ pangcd[i].gd.cid = CID_PanFamily;
+ pangcd[i].gd.u.list = panfamily;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GListButtonCreate;
+ panarray[j++] = NULL;
+
+ pangcd[i].gd.pos.x = 20; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y+26+5;
+ panlabel[i].text = (unichar_t *) _("_Serifs");
+ panlabel[i].text_is_1byte = true;
+ panlabel[i].text_in_resource = true;
+ pangcd[i].gd.label = &panlabel[i];
+ pangcd[i].gd.cid = CID_PanSerifsLab;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GLabelCreate;
+
+ pangcd[i].gd.pos.x = 100; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y-6; pangcd[i].gd.pos.width = 120;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ pangcd[i].gd.cid = CID_PanSerifs;
+ pangcd[i].gd.u.list = panserifs;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GListButtonCreate;
+ panarray[j++] = NULL;
+
+ pangcd[i].gd.pos.x = 20; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y+26+5;
+ panlabel[i].text = (unichar_t *) S_("Panose|_Weight");
+ panlabel[i].text_is_1byte = true;
+ panlabel[i].text_in_resource = true;
+ pangcd[i].gd.label = &panlabel[i];
+ pangcd[i].gd.cid = CID_PanWeightLab;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GLabelCreate;
+
+ pangcd[i].gd.pos.x = 100; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y-6; pangcd[i].gd.pos.width = 120;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ pangcd[i].gd.cid = CID_PanWeight;
+ pangcd[i].gd.u.list = panweight;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GListButtonCreate;
+ panarray[j++] = NULL;
+
+ pangcd[i].gd.pos.x = 20; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y+26+5;
+ panlabel[i].text = (unichar_t *) _("_Proportion");
+ panlabel[i].text_is_1byte = true;
+ panlabel[i].text_in_resource = true;
+ pangcd[i].gd.label = &panlabel[i];
+ pangcd[i].gd.cid = CID_PanPropLab;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GLabelCreate;
+
+ pangcd[i].gd.pos.x = 100; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y-6; pangcd[i].gd.pos.width = 120;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ pangcd[i].gd.cid = CID_PanProp;
+ pangcd[i].gd.u.list = panprop;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GListButtonCreate;
+ panarray[j++] = NULL;
+
+ pangcd[i].gd.pos.x = 20; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y+26+5;
+ panlabel[i].text = (unichar_t *) _("_Contrast");
+ panlabel[i].text_is_1byte = true;
+ panlabel[i].text_in_resource = true;
+ pangcd[i].gd.label = &panlabel[i];
+ pangcd[i].gd.cid = CID_PanContrastLab;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GLabelCreate;
+
+ pangcd[i].gd.pos.x = 100; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y-6; pangcd[i].gd.pos.width = 120;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ pangcd[i].gd.cid = CID_PanContrast;
+ pangcd[i].gd.u.list = pancontrast;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GListButtonCreate;
+ panarray[j++] = NULL;
+
+ pangcd[i].gd.pos.x = 20; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y+26+5;
+ panlabel[i].text = (unichar_t *) _("Stroke _Variation");
+ panlabel[i].text_is_1byte = true;
+ panlabel[i].text_in_resource = true;
+ pangcd[i].gd.label = &panlabel[i];
+ pangcd[i].gd.cid = CID_PanStrokeVarLab;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GLabelCreate;
+
+ pangcd[i].gd.pos.x = 100; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y-6; pangcd[i].gd.pos.width = 120;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ pangcd[i].gd.cid = CID_PanStrokeVar;
+ pangcd[i].gd.u.list = panstrokevar;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GListButtonCreate;
+ panarray[j++] = NULL;
+
+ pangcd[i].gd.pos.x = 20; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y+26+5;
+ panlabel[i].text = (unichar_t *) _("_Arm Style");
+ panlabel[i].text_is_1byte = true;
+ panlabel[i].text_in_resource = true;
+ pangcd[i].gd.label = &panlabel[i];
+ pangcd[i].gd.cid = CID_PanArmStyleLab;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GLabelCreate;
+
+ pangcd[i].gd.pos.x = 100; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y-6; pangcd[i].gd.pos.width = 120;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ pangcd[i].gd.cid = CID_PanArmStyle;
+ pangcd[i].gd.u.list = panarmstyle;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GListButtonCreate;
+ panarray[j++] = NULL;
+
+ pangcd[i].gd.pos.x = 20; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y+26+5;
+ panlabel[i].text = (unichar_t *) _("_Letterform");
+ panlabel[i].text_is_1byte = true;
+ panlabel[i].text_in_resource = true;
+ pangcd[i].gd.label = &panlabel[i];
+ pangcd[i].gd.cid = CID_PanLetterformLab;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GLabelCreate;
+
+ pangcd[i].gd.pos.x = 100; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y-6; pangcd[i].gd.pos.width = 120;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ pangcd[i].gd.cid = CID_PanLetterform;
+ pangcd[i].gd.u.list = panletterform;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GListButtonCreate;
+ panarray[j++] = NULL;
+
+ pangcd[i].gd.pos.x = 20; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y+26+5;
+ panlabel[i].text = (unichar_t *) _("_Midline");
+ panlabel[i].text_is_1byte = true;
+ panlabel[i].text_in_resource = true;
+ pangcd[i].gd.label = &panlabel[i];
+ pangcd[i].gd.cid = CID_PanMidLineLab;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GLabelCreate;
+
+ pangcd[i].gd.pos.x = 100; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y-6; pangcd[i].gd.pos.width = 120;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ pangcd[i].gd.cid = CID_PanMidLine;
+ pangcd[i].gd.u.list = panmidline;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GListButtonCreate;
+ panarray[j++] = NULL;
+
+ pangcd[i].gd.pos.x = 20; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y+26+5;
+ panlabel[i].text = (unichar_t *) _("_X-Height");
+ panlabel[i].text_is_1byte = true;
+ panlabel[i].text_in_resource = true;
+ pangcd[i].gd.label = &panlabel[i];
+ pangcd[i].gd.cid = CID_PanXHeightLab;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GLabelCreate;
+
+ pangcd[i].gd.pos.x = 100; pangcd[i].gd.pos.y = pangcd[i-1].gd.pos.y-6; pangcd[i].gd.pos.width = 120;
+ pangcd[i].gd.flags = gg_visible | gg_enabled;
+ pangcd[i].gd.cid = CID_PanXHeight;
+ pangcd[i].gd.u.list = panxheight;
+ panarray[j++] = &pangcd[i];
+ pangcd[i++].creator = GListButtonCreate;
+ panarray[j++] = NULL;
+
+ panarray[j++] = GCD_Glue; panarray[j++] = GCD_Glue;
+
+ panarray[j++] = NULL; panarray[j++] = NULL;
+
+ memset(panbox,0,sizeof(panbox));
+ panbox[0].gd.flags = gg_enabled|gg_visible;
+ panbox[0].gd.u.boxelements = panarray;
+ panbox[0].creator = GHVBoxCreate;
+/******************************************************************************/
+
+ memset(&vagcd,0,sizeof(vagcd));
+ memset(&vaspects,'\0',sizeof(vaspects));
+
+ i = 0;
+ vaspects[i].text = (unichar_t *) _("Misc.");
+ vaspects[i].text_is_1byte = true;
+ vaspects[i++].gcd = vbox;
+
+ vaspects[i].text = (unichar_t *) _("Metrics");
+ vaspects[i].text_is_1byte = true;
+ vaspects[i++].gcd = metbox;
+
+ vaspects[i].text = (unichar_t *) _("Sub/Super");
+ vaspects[i].text_is_1byte = true;
+ vaspects[i++].gcd = ssbox;
+
+ vaspects[i].text = (unichar_t *) _("Panose");
+ vaspects[i].text_is_1byte = true;
+ vaspects[i++].gcd = panbox;
+
+ vagcd[0].gd.pos.x = 4; vagcd[0].gd.pos.y = 6;
+ vagcd[0].gd.pos.width = 252;
+ vagcd[0].gd.pos.height = 300;
+ vagcd[0].gd.u.tabs = vaspects;
+ vagcd[0].gd.flags = gg_visible | gg_enabled;
+ /*vagcd[0].gd.handle_controlevent = GFI_TTFAspectChange;*/
+ vagcd[0].gd.cid = CID_TTFTabs;
+ vagcd[0].creator = GTabSetCreate;
+
+/******************************************************************************/
+ memset(&gaspboxes,0,sizeof(gaspboxes));
+ memset(&gaspgcd,0,sizeof(gaspgcd));
+ memset(&gasplabel,0,sizeof(gasplabel));
+ memset(&gaspgcd_def,0,sizeof(gaspgcd_def));
+
+ GaspMatrixInit(&gaspmi,d);
+
+ i = j = 0;
+
+ gasplabel[i].text = (unichar_t *) S_("Gasp|_Version");
+ gasplabel[i].text_is_1byte = true;
+ gasplabel[i].text_in_resource = true;
+ gaspgcd[i].gd.label = &gasplabel[i];
+ gaspgcd[i].gd.flags = gg_visible | gg_enabled;
+ gaspharray[j++] = &gaspgcd[i];
+ gaspgcd[i++].creator = GLabelCreate;
+
+ gaspgcd[i].gd.flags = gg_visible | gg_enabled;
+ gaspgcd[i].gd.cid = CID_GaspVersion;
+ gaspgcd[i].gd.label = &gaspversions[sf->gasp_version];
+ gaspgcd[i].gd.u.list = gaspversions;
+ gaspharray[j++] = &gaspgcd[i];
+ gaspgcd[i].gd.handle_controlevent = GFI_GaspVersion;
+ gaspgcd[i++].creator = GListButtonCreate;
+ gaspharray[j++] = GCD_HPad10;
+
+ gasplabel[i].text = (unichar_t *) _("Optimized For Cleartype");
+ gasplabel[i].text_is_1byte = true;
+ gasplabel[i].text_in_resource = true;
+ gaspgcd[i].gd.label = &gasplabel[i];
+ gaspgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ gaspgcd[i].gd.cid = CID_HeadClearType;
+ if ( sf->head_optimized_for_cleartype )
+ gaspgcd[i].gd.flags |= gg_cb_on;
+ gaspgcd[i].gd.popup_msg = (unichar_t *) _("Actually a bit in the 'head' table.\nIf unset then certain East Asian fonts will not be hinted");
+ gaspharray[j++] = &gaspgcd[i];
+ gaspgcd[i++].creator = GCheckBoxCreate;
+ gaspharray[j++] = NULL;
+
+ gaspboxes[2].gd.flags = gg_enabled|gg_visible;
+ gaspboxes[2].gd.u.boxelements = gaspharray;
+ gaspboxes[2].creator = GHBoxCreate;
+
+ gaspvarray[0] = &gaspboxes[2];
+
+ gaspgcd[i].gd.pos.width = 300; gaspgcd[i].gd.pos.height = 200;
+ gaspgcd[i].gd.flags = gg_enabled | gg_visible | gg_utf8_popup;
+ gaspgcd[i].gd.cid = CID_Gasp;
+ gaspgcd[i].gd.u.matrix = &gaspmi;
+ gaspgcd[i].gd.popup_msg = (unichar_t *) _(
+ "The 'gasp' table gives you control over when grid-fitting and\n"
+ "anti-aliased rasterizing are done.\n"
+ "The table consists of an (ordered) list of pixel sizes each with\n"
+ "a set of flags. Those flags apply to all pixel sizes bigger than\n"
+ "the previous table entry but less than or equal to the current.\n"
+ "The list must be terminated with a pixel size of 65535.\n"
+ "Version 1 of the table contains two additional flags that\n"
+ "apply to MS's ClearType rasterizer.\n\n"
+ "The 'gasp' table only applies to truetype fonts.");
+ gaspgcd[i].data = d;
+ gaspgcd[i].creator = GMatrixEditCreate;
+ gaspvarray[1] = &gaspgcd[i];
+ gaspvarray[2] = NULL;
+
+ gaspboxes[0].gd.flags = gg_enabled|gg_visible;
+ gaspboxes[0].gd.u.boxelements = gaspvarray;
+ gaspboxes[0].creator = GVBoxCreate;
+
+ gaspgcd_def[0].gd.flags = gg_visible | gg_enabled;
+ gasplabel[4].text = (unichar_t *) S_("Gasp|_Default");
+ gasplabel[4].text_is_1byte = true;
+ gasplabel[4].text_in_resource = true;
+ gaspgcd_def[0].gd.label = &gasplabel[4];
+ gaspgcd_def[0].gd.handle_controlevent = Gasp_Default;
+ gaspgcd_def[0].creator = GButtonCreate;
+/******************************************************************************/
+ memset(&tnlabel,0,sizeof(tnlabel));
+ memset(&tngcd,0,sizeof(tngcd));
+ memset(&tnboxes,0,sizeof(tnboxes));
+
+ TNMatrixInit(&mi,d);
+
+ tngcd[0].gd.pos.x = 5; tngcd[0].gd.pos.y = 6;
+ tngcd[0].gd.flags = gg_visible | gg_enabled;
+ tnlabel[0].text = (unichar_t *) _("Sort By:");
+ tnlabel[0].text_is_1byte = true;
+ tngcd[0].gd.label = &tnlabel[0];
+ tngcd[0].creator = GLabelCreate;
+ tnharray[0] = &tngcd[0];
+
+ tngcd[1].gd.pos.x = 50; tngcd[1].gd.pos.y = tngcd[0].gd.pos.y-4;
+ tngcd[1].gd.flags = gg_enabled | gg_visible;
+ tngcd[1].gd.cid = CID_TNLangSort;
+ tnlabel[1].text = (unichar_t *) _("_Language");
+ tnlabel[1].text_is_1byte = true;
+ tnlabel[1].text_in_resource = true;
+ tngcd[1].gd.label = &tnlabel[1];
+ tngcd[1].creator = GRadioCreate;
+ tngcd[1].gd.handle_controlevent = GFI_SortBy;
+ tnharray[1] = &tngcd[1];
+
+ tngcd[2].gd.pos.x = 120; tngcd[2].gd.pos.y = tngcd[1].gd.pos.y;
+ tngcd[2].gd.flags = gg_visible | gg_enabled | gg_rad_continueold;
+ tngcd[2].gd.cid = CID_TNStringSort;
+ tnlabel[2].text = (unichar_t *) _("_String Type");
+ tnlabel[2].text_is_1byte = true;
+ tnlabel[2].text_in_resource = true;
+ tngcd[2].gd.label = &tnlabel[2];
+ tngcd[2].creator = GRadioCreate;
+ tngcd[2].gd.handle_controlevent = GFI_SortBy;
+ tnharray[2] = &tngcd[2];
+
+ tngcd[3].gd.pos.x = 195; tngcd[3].gd.pos.y = tngcd[1].gd.pos.y;
+ tngcd[3].gd.flags = gg_visible | gg_enabled | gg_cb_on | gg_rad_continueold;
+ tnlabel[3].text = (unichar_t *) S_("SortingScheme|Default");
+ tnlabel[3].text_is_1byte = true;
+ tngcd[3].gd.label = &tnlabel[3];
+ tngcd[3].creator = GRadioCreate;
+ tngcd[3].gd.handle_controlevent = GFI_SortBy;
+ tnharray[3] = &tngcd[3]; tnharray[4] = GCD_Glue; tnharray[5] = NULL;
+
+ tngcd[4].gd.pos.x = 10; tngcd[4].gd.pos.y = tngcd[1].gd.pos.y+14;
+ tngcd[4].gd.pos.width = 300; tngcd[4].gd.pos.height = 200;
+ tngcd[4].gd.flags = gg_enabled | gg_visible | gg_utf8_popup;
+ tngcd[4].gd.cid = CID_TNames;
+ tngcd[4].gd.u.matrix = &mi;
+ tngcd[4].gd.popup_msg = (unichar_t *) _(
+ "To create a new name, left click on the <New> button, and select a locale.\n"
+ "To change the locale, left click on it.\n"
+ "To change the string type, left click on it.\n"
+ "To change the text, left click in it and then type.\n"
+ "To delete a name, right click on the name & select Delete from the menu.\n"
+ "To associate or disassocate a truetype name to its postscript equivalent\n"
+ "right click and select the appropriate menu item." );
+ tngcd[4].data = d;
+ tngcd[4].creator = GMatrixEditCreate;
+
+ tngcd[5].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+/* GT: when translating this please leave the "SIL Open Font License" in */
+/* GT: English (possibly translating it in parentheses). I believe there */
+/* GT: are legal reasons for this. */
+/* GT: So "A\303\261adir SIL Open Font License (licencia de fuentes libres)" */
+ tnlabel[5].text = (unichar_t *) S_("Add SIL ");
+ tnlabel[5].image_precedes = false;
+ tnlabel[5].image = &OFL_logo;
+ tnlabel[5].text_is_1byte = true;
+ tnlabel[5].text_in_resource = true;
+ tngcd[5].gd.label = &tnlabel[5];
+ tngcd[5].gd.handle_controlevent = GFI_AddOFL;
+ tngcd[5].gd.popup_msg = (unichar_t *) _(
+ "The SIL Open Font License (OFL) is designed for free/libre/open font projects.\n"
+ "Most other FLOSS licenses are designed for conventional software and are problematic for fonts.\n"
+ "The OFL is a community-approved license and is well-suited for releasing fonts to be freely \n"
+ "used, studied, copied, modified, embedded, merged and distributed while maintaining artistic integrity.\n"
+ "You are encouraged you to use it if you can.\n"
+ "\n"
+ "For more details about the OFL - and the corresponding FAQ - see http://scripts.sil.org/OFL \n"
+ "\n"
+ "Simply press this button to add the OFL metadata to your font.\n"
+ "\n");
+ tngcd[5].creator = GButtonCreate;
+
+ tngcd[6].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ tnlabel[6].text = (unichar_t *) S_("OFL website");
+ tnlabel[6].text_is_1byte = true;
+ tnlabel[6].text_in_resource = true;
+ tngcd[6].gd.label = &tnlabel[6];
+ tngcd[6].gd.handle_controlevent = GFI_HelpOFL;
+ tngcd[6].gd.popup_msg = (unichar_t *) _(
+ "\n"
+ "Click here to go to http://scripts.sil.org/OFL \n"
+ "to get all the details about the Open Font License \n"
+ "and to read the corresponding FAQ. \n"
+ "\n");
+ tngcd[6].creator = GButtonCreate;
+ tnharray2[0] = &tngcd[5]; tnharray2[1] = &tngcd[6]; tnharray2[2] = GCD_Glue; tnharray2[3] = NULL;
+ tnvarray[0] = &tnboxes[2]; tnvarray[1] = &tngcd[4]; tnvarray[2] = &tnboxes[3]; tnvarray[3] = NULL;
+
+ tnboxes[0].gd.flags = gg_enabled|gg_visible;
+ tnboxes[0].gd.u.boxelements = tnvarray;
+ tnboxes[0].creator = GVBoxCreate;
+
+ tnboxes[2].gd.flags = gg_enabled|gg_visible;
+ tnboxes[2].gd.u.boxelements = tnharray;
+ tnboxes[2].creator = GHBoxCreate;
+
+ tnboxes[3].gd.flags = gg_enabled|gg_visible;
+ tnboxes[3].gd.u.boxelements = tnharray2;
+ tnboxes[3].creator = GHBoxCreate;
+/******************************************************************************/
+ memset(&comlabel,0,sizeof(comlabel));
+ memset(&comgcd,0,sizeof(comgcd));
+
+ comgcd[0].gd.pos.x = 10; comgcd[0].gd.pos.y = 10;
+ comgcd[0].gd.pos.width = ngcd[11].gd.pos.width; comgcd[0].gd.pos.height = 230;
+ comgcd[0].gd.flags = gg_visible | gg_enabled | gg_textarea_wrap;
+ comgcd[0].gd.cid = CID_Comment;
+ comlabel[0].text = (unichar_t *) sf->comments;
+ comlabel[0].text_is_1byte = true;
+ if ( comlabel[0].text==NULL ) comlabel[0].text = (unichar_t *) "";
+ comgcd[0].gd.label = &comlabel[0];
+ comgcd[0].creator = GTextAreaCreate;
+
+ comarray[0] = &comgcd[0]; comarray[1] = NULL;
+ memset(combox,0,sizeof(combox));
+ combox[0].gd.flags = gg_enabled|gg_visible;
+ combox[0].gd.u.boxelements = comarray;
+ combox[0].creator = GHBoxCreate;
+
+/******************************************************************************/
+ memset(&mklabel,0,sizeof(mklabel));
+ memset(&mkgcd,0,sizeof(mkgcd));
+
+ mkgcd[0].gd.pos.x = 10; mkgcd[0].gd.pos.y = 10;
+ mkgcd[0].gd.pos.width = ngcd[15].gd.pos.width; mkgcd[0].gd.pos.height = 200;
+ mkgcd[0].gd.flags = gg_visible | gg_enabled;
+ mkgcd[0].gd.cid = CID_MarkClasses;
+ mkgcd[0].gd.u.list = MarkClassesList(sf);
+ mkgcd[0].gd.handle_controlevent = GFI_MarkSelChanged;
+ mkgcd[0].creator = GListCreate;
+
+ mkgcd[1].gd.pos.x = 10; mkgcd[1].gd.pos.y = mkgcd[0].gd.pos.y+mkgcd[0].gd.pos.height+4;
+ mkgcd[1].gd.pos.width = -1;
+ mkgcd[1].gd.flags = gg_visible | gg_enabled;
+/* GT: See the long comment at "Property|New" */
+/* GT: The msgstr should contain a translation of "_New...", ignore "Mark|" */
+ mklabel[1].text = (unichar_t *) S_("Mark|_New...");
+ mklabel[1].text_is_1byte = true;
+ mklabel[1].text_in_resource = true;
+ mkgcd[1].gd.label = &mklabel[1];
+ mkgcd[1].gd.cid = CID_MarkNew;
+ mkgcd[1].gd.handle_controlevent = GFI_MarkNew;
+ mkgcd[1].creator = GButtonCreate;
+
+ mkgcd[2].gd.pos.x = -10; mkgcd[2].gd.pos.y = mkgcd[1].gd.pos.y;
+ mkgcd[2].gd.pos.width = -1;
+ mkgcd[2].gd.flags = gg_visible;
+ mklabel[2].text = (unichar_t *) _("_Edit...");
+ mklabel[2].text_is_1byte = true;
+ mklabel[2].text_in_resource = true;
+ mkgcd[2].gd.label = &mklabel[2];
+ mkgcd[2].gd.cid = CID_MarkEdit;
+ mkgcd[2].gd.handle_controlevent = GFI_MarkEdit;
+ mkgcd[2].creator = GButtonCreate;
+
+ mkarray[0] = &mkgcd[0]; mkarray[1] = &mkbox[2]; mkarray[2] = NULL;
+ mkarray2[0] = &mkgcd[1]; mkarray2[1] = GCD_Glue; mkarray2[2] = &mkgcd[2];
+ mkarray2[3] = NULL;
+ memset(mkbox,0,sizeof(mkbox));
+ mkbox[0].gd.flags = gg_enabled|gg_visible;
+ mkbox[0].gd.u.boxelements = mkarray;
+ mkbox[0].creator = GVBoxCreate;
+
+ mkbox[2].gd.flags = gg_enabled|gg_visible;
+ mkbox[2].gd.u.boxelements = mkarray2;
+ mkbox[2].creator = GHBoxCreate;
+/******************************************************************************/
+ memset(&txlabel,0,sizeof(txlabel));
+ memset(&txgcd,0,sizeof(txgcd));
+
+ k=0;
+ txlabel[k].text = (unichar_t *) U_("\316\244\316\265\316\247 General");
+ txlabel[k].text_is_1byte = true;
+ txgcd[k].gd.label = &txlabel[k];
+ txgcd[k].gd.pos.x = 10; txgcd[k].gd.pos.y = 10;
+ txgcd[k].gd.flags = gg_visible | gg_enabled;
+ txgcd[k].gd.cid = CID_TeXText;
+ txgcd[k].gd.handle_controlevent = GFI_TeXChanged;
+ txgcd[k++].creator = GRadioCreate;
+
+ txlabel[k].text = (unichar_t *) U_("\316\244\316\265\316\247 Math Symbol");
+ txlabel[k].text_is_1byte = true;
+ txgcd[k].gd.label = &txlabel[k];
+ txgcd[k].gd.pos.x = 80; txgcd[k].gd.pos.y = txgcd[k-1].gd.pos.y;
+ txgcd[k].gd.flags = gg_visible | gg_enabled | gg_rad_continueold;
+ txgcd[k].gd.cid = CID_TeXMathSym;
+ txgcd[k].gd.handle_controlevent = GFI_TeXChanged;
+ txgcd[k++].creator = GRadioCreate;
+
+ txlabel[k].text = (unichar_t *) U_("\316\244\316\265\316\247 Math Extension");
+ txlabel[k].text_is_1byte = true;
+ txgcd[k].gd.label = &txlabel[k];
+ txgcd[k].gd.pos.x = 155; txgcd[k].gd.pos.y = txgcd[k-1].gd.pos.y;
+ txgcd[k].gd.flags = gg_visible | gg_enabled | gg_rad_continueold;
+ txgcd[k].gd.cid = CID_TeXMathExt;
+ txgcd[k].gd.handle_controlevent = GFI_TeXChanged;
+ txgcd[k++].creator = GRadioCreate;
+
+ for ( i=j=0; texparams[i]!=0; ++i ) {
+ txlabel[k].text = (unichar_t *) texparams[i];
+ txlabel[k].text_is_1byte = true;
+ txgcd[k].gd.label = &txlabel[k];
+ txgcd[k].gd.pos.x = 10; txgcd[k].gd.pos.y = txgcd[k-2].gd.pos.y+26;
+ txgcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ txgcd[k].gd.popup_msg = (unichar_t *) texpopups[i];
+ txarray2[j++] = &txgcd[k];
+ txgcd[k++].creator = GLabelCreate;
+
+ txgcd[k].gd.pos.x = 70; txgcd[k].gd.pos.y = txgcd[k-1].gd.pos.y-4;
+ txgcd[k].gd.flags = gg_visible | gg_enabled;
+ txgcd[k].gd.cid = CID_TeX + i;
+ txarray2[j++] = &txgcd[k];
+ txgcd[k++].creator = GTextFieldCreate;
+ txarray2[j++] = GCD_Glue;
+ txarray2[j++] = NULL;
+ }
+ txgcd[k-2].gd.cid = CID_TeXExtraSpLabel;
+ txarray2[j++] = NULL;
+
+/* GT: More Parameters */
+ txlabel[k].text = (unichar_t *) _("More Params");
+ txlabel[k].text_is_1byte = true;
+ txgcd[k].gd.label = &txlabel[k];
+ txgcd[k].gd.pos.x = 20; txgcd[k].gd.pos.y = txgcd[k-1].gd.pos.y+26;
+ txgcd[k].gd.flags = gg_visible | gg_enabled;
+ txgcd[k].gd.handle_controlevent = GFI_MoreParams;
+ txgcd[k].gd.cid = CID_MoreParams;
+ txgcd[k++].creator = GButtonCreate;
+
+ txarray[0] = &txbox[2]; txarray[1] = &txbox[3]; txarray[2] = &txbox[4]; txarray[3] = GCD_Glue; txarray[4] = NULL;
+ txarray3[0] = &txgcd[0]; txarray3[1] = GCD_Glue; txarray3[2] = &txgcd[1];
+ txarray3[3] = GCD_Glue; txarray3[4] = &txgcd[2]; txarray3[5] = NULL;
+ txarray4[0] = GCD_Glue; txarray4[1] = &txgcd[k-1];
+ txarray4[2] = txarray4[3] = txarray4[4] = GCD_Glue; txarray4[5] = NULL;
+ memset(txbox,0,sizeof(txbox));
+ txbox[0].gd.flags = gg_enabled|gg_visible;
+ txbox[0].gd.u.boxelements = txarray;
+ txbox[0].creator = GVBoxCreate;
+
+ txbox[2].gd.flags = gg_enabled|gg_visible;
+ txbox[2].gd.u.boxelements = txarray3;
+ txbox[2].creator = GHBoxCreate;
+
+ txbox[3].gd.flags = gg_enabled|gg_visible;
+ txbox[3].gd.u.boxelements = txarray2;
+ txbox[3].creator = GHVBoxCreate;
+
+ txbox[4].gd.flags = gg_enabled|gg_visible;
+ txbox[4].gd.u.boxelements = txarray4;
+ txbox[4].creator = GHBoxCreate;
+/******************************************************************************/
+ memset(&szlabel,0,sizeof(szlabel));
+ memset(&szgcd,0,sizeof(szgcd));
+
+ k=0;
+
+ szlabel[k].text = (unichar_t *) _("De_sign Size:");
+ szlabel[k].text_is_1byte = true;
+ szlabel[k].text_in_resource = true;
+ szgcd[k].gd.label = &szlabel[k];
+ szgcd[k].gd.pos.x = 10; szgcd[k].gd.pos.y = 9;
+ szgcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ szgcd[k].gd.popup_msg = (unichar_t *) _("The size (in points) for which this face was designed");
+ szgcd[k++].creator = GLabelCreate;
+
+ sprintf(dszbuf, "%.1f", sf->design_size/10.0);
+ szlabel[k].text = (unichar_t *) dszbuf;
+ szlabel[k].text_is_1byte = true;
+ szgcd[k].gd.label = &szlabel[k];
+ szgcd[k].gd.pos.x = 70; szgcd[k].gd.pos.y = szgcd[k-1].gd.pos.y-4;
+ szgcd[k].gd.pos.width = 60;
+ szgcd[k].gd.flags = gg_visible | gg_enabled;
+ szgcd[k].gd.cid = CID_DesignSize;
+ szgcd[k++].creator = GTextFieldCreate;
+
+ szlabel[k].text = (unichar_t *) S_("Size|Points");
+ szlabel[k].text_is_1byte = true;
+ szgcd[k].gd.label = &szlabel[k];
+ szgcd[k].gd.pos.x = 134; szgcd[k].gd.pos.y = szgcd[k-2].gd.pos.y;
+ szgcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ szgcd[k].gd.popup_msg = (unichar_t *) _("The size (in points) for which this face was designed");
+ szgcd[k++].creator = GLabelCreate;
+
+ szlabel[k].text = (unichar_t *) _("Design Range");
+ szlabel[k].text_is_1byte = true;
+ szgcd[k].gd.label = &szlabel[k];
+ szgcd[k].gd.pos.x = 14; szgcd[k].gd.pos.y = szgcd[k-2].gd.pos.y+24;
+ szgcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ szgcd[k].gd.popup_msg = (unichar_t *) _("The range of sizes (in points) to which this face applies.\nLower bound is exclusive, upper bound is inclusive.");
+ szgcd[k++].creator = GLabelCreate;
+
+ szgcd[k].gd.pos.x = 8; szgcd[k].gd.pos.y = GDrawPointsToPixels(NULL,szgcd[k-1].gd.pos.y+6);
+ szgcd[k].gd.pos.width = pos.width-32; szgcd[k].gd.pos.height = GDrawPointsToPixels(NULL,36);
+ szgcd[k].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
+ szgcd[k++].creator = GGroupCreate;
+
+ szlabel[k].text = (unichar_t *) _("_Bottom:");
+ szlabel[k].text_is_1byte = true;
+ szlabel[k].text_in_resource = true;
+ szgcd[k].gd.label = &szlabel[k];
+ szgcd[k].gd.pos.x = 14; szgcd[k].gd.pos.y = szgcd[k-2].gd.pos.y+18;
+ szgcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ szgcd[k].gd.popup_msg = (unichar_t *) _("The range of sizes (in points) to which this face applies.\nLower bound is exclusive, upper bound is inclusive.");
+ szgcd[k++].creator = GLabelCreate;
+
+ sprintf(dsbbuf, "%.1f", sf->design_range_bottom/10.0);
+ szlabel[k].text = (unichar_t *) dsbbuf;
+ szlabel[k].text_is_1byte = true;
+ szgcd[k].gd.label = &szlabel[k];
+ szgcd[k].gd.pos.x = 70; szgcd[k].gd.pos.y = szgcd[k-1].gd.pos.y-4;
+ szgcd[k].gd.pos.width = 60;
+ szgcd[k].gd.flags = gg_visible | gg_enabled;
+ szgcd[k].gd.cid = CID_DesignBottom;
+ szgcd[k++].creator = GTextFieldCreate;
+
+ szlabel[k].text = (unichar_t *) _("_Top:");
+ szlabel[k].text_is_1byte = true;
+ szlabel[k].text_in_resource = true;
+ szgcd[k].gd.label = &szlabel[k];
+ szgcd[k].gd.pos.x = 140; szgcd[k].gd.pos.y = szgcd[k-2].gd.pos.y;
+ szgcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ szgcd[k].gd.popup_msg = (unichar_t *) _("The range of sizes (in points) to which this face applies.\nLower bound is exclusive, upper bound is inclusive.");
+ szgcd[k++].creator = GLabelCreate;
+
+ sprintf(dstbuf, "%.1f", sf->design_range_top/10.0);
+ szlabel[k].text = (unichar_t *) dstbuf;
+ szlabel[k].text_is_1byte = true;
+ szgcd[k].gd.label = &szlabel[k];
+ szgcd[k].gd.pos.x = 180; szgcd[k].gd.pos.y = szgcd[k-1].gd.pos.y-4;
+ szgcd[k].gd.pos.width = 60;
+ szgcd[k].gd.flags = gg_visible | gg_enabled;
+ szgcd[k].gd.cid = CID_DesignTop;
+ szgcd[k++].creator = GTextFieldCreate;
+
+ szlabel[k].text = (unichar_t *) _("Style _ID:");
+ szlabel[k].text_is_1byte = true;
+ szlabel[k].text_in_resource = true;
+ szgcd[k].gd.label = &szlabel[k];
+ szgcd[k].gd.pos.x = 14; szgcd[k].gd.pos.y = GDrawPixelsToPoints(NULL,szgcd[k-5].gd.pos.y+szgcd[k-5].gd.pos.height)+10;
+ szgcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ szgcd[k].gd.popup_msg = (unichar_t *) _("This is an identifying number shared by all members of\nthis font family with the same style (I.e. 10pt Bold and\n24pt Bold would have the same id, but 10pt Italic would not");
+ szgcd[k++].creator = GLabelCreate;
+
+ sprintf(sibuf, "%d", sf->fontstyle_id);
+ szlabel[k].text = (unichar_t *) sibuf;
+ szlabel[k].text_is_1byte = true;
+ szgcd[k].gd.label = &szlabel[k];
+ szgcd[k].gd.pos.x = 70; szgcd[k].gd.pos.y = szgcd[k-1].gd.pos.y-4;
+ szgcd[k].gd.pos.width = 60;
+ szgcd[k].gd.flags = gg_visible | gg_enabled;
+ szgcd[k].gd.cid = CID_StyleID;
+ szgcd[k++].creator = GTextFieldCreate;
+
+ szlabel[k].text = (unichar_t *) _("Style Name:");
+ szlabel[k].text_is_1byte = true;
+ szgcd[k].gd.label = &szlabel[k];
+ szgcd[k].gd.pos.x = 14; szgcd[k].gd.pos.y = szgcd[k-2].gd.pos.y+22;
+ szgcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ szgcd[k].gd.popup_msg = (unichar_t *) _("This provides a set of names used to identify the\nstyle of this font. Names may be translated into multiple\nlanguages (English is required, others are optional)\nAll fonts with the same Style ID should share this name.");
+ szgcd[k++].creator = GLabelCreate;
+
+ szgcd[k].gd.pos.x = 10; szgcd[k].gd.pos.y = szgcd[k-1].gd.pos.y+14;
+ szgcd[k].gd.pos.width = ngcd[15].gd.pos.width; szgcd[k].gd.pos.height = 100;
+ szgcd[k].gd.flags = gg_visible | gg_enabled | gg_list_alphabetic;
+ szgcd[k].gd.cid = CID_StyleName;
+ szgcd[k].gd.handle_controlevent = GFI_StyleNameSelChanged;
+ szgcd[k++].creator = GListCreate;
+
+ szgcd[k].gd.pos.x = 10; szgcd[k].gd.pos.y = szgcd[k-1].gd.pos.y+szgcd[k-1].gd.pos.height+4;
+ szgcd[k].gd.pos.width = -1;
+ szgcd[k].gd.flags = gg_visible | gg_enabled;
+ szlabel[k].text = (unichar_t *) S_("StyleName|_New...");
+ szlabel[k].text_is_1byte = true;
+ szlabel[k].text_in_resource = true;
+ szgcd[k].gd.label = &szlabel[k];
+ szgcd[k].gd.cid = CID_StyleNameNew;
+ szgcd[k].gd.handle_controlevent = GFI_StyleNameNew;
+ szgcd[k++].creator = GButtonCreate;
+
+ szgcd[k].gd.pos.x = 20+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor);
+ szgcd[k].gd.pos.y = szgcd[k-1].gd.pos.y;
+ szgcd[k].gd.pos.width = -1;
+ szgcd[k].gd.flags = gg_visible;
+ szlabel[k].text = (unichar_t *) _("_Delete");
+ szlabel[k].text_is_1byte = true;
+ szlabel[k].text_in_resource = true;
+ szgcd[k].gd.label = &szlabel[k];
+ szgcd[k].gd.cid = CID_StyleNameDel;
+ szgcd[k].gd.handle_controlevent = GFI_StyleNameDel;
+ szgcd[k++].creator = GButtonCreate;
+
+ szgcd[k].gd.pos.x = 10 + 2*(10+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor));
+ szgcd[k].gd.pos.y = szgcd[k-1].gd.pos.y;
+ szgcd[k].gd.pos.width = -1;
+ szgcd[k].gd.flags = gg_visible;
+ szlabel[k].text = (unichar_t *) _("_Edit...");
+ szlabel[k].text_is_1byte = true;
+ szlabel[k].text_in_resource = true;
+ szgcd[k].gd.label = &szlabel[k];
+ szgcd[k].gd.cid = CID_StyleNameRename;
+ szgcd[k].gd.handle_controlevent = GFI_StyleNameRename;
+ szgcd[k++].creator = GButtonCreate;
+
+ szarray[0] = &szbox[2];
+ szarray[1] = &szbox[3];
+ szarray[2] = &szbox[4];
+ szarray[3] = &szgcd[11];
+ szarray[4] = &szgcd[12];
+ szarray[5] = &szbox[5];
+ szarray[6] = NULL;
+
+ szarray2[0] = &szgcd[0]; szarray2[1] = &szgcd[1]; szarray2[2] = &szgcd[2]; szarray2[3] = GCD_Glue; szarray2[4] = NULL;
+ szarray3[0] = &szgcd[5]; szarray3[1] = &szgcd[6]; szarray3[2] = &szgcd[7]; szarray3[3] = &szgcd[8]; szarray3[4] = GCD_Glue; szarray3[5] = NULL;
+ szarray3[6] = NULL;
+ szarray4[0] = &szgcd[9]; szarray4[1] = &szgcd[10]; szarray4[2] = GCD_Glue; szarray4[3] = NULL;
+ szarray5[0] = &szgcd[13]; szarray5[1] = GCD_Glue;
+ szarray5[2] = &szgcd[14]; szarray5[3] = GCD_Glue;
+ szarray5[4] = &szgcd[15]; szarray5[5] = NULL;
+
+ memset(szbox,0,sizeof(szbox));
+ szbox[0].gd.flags = gg_enabled|gg_visible;
+ szbox[0].gd.u.boxelements = szarray;
+ szbox[0].creator = GVBoxCreate;
+
+ szbox[2].gd.flags = gg_enabled|gg_visible;
+ szbox[2].gd.u.boxelements = szarray2;
+ szbox[2].creator = GHBoxCreate;
+
+ szbox[3].gd.flags = gg_enabled|gg_visible;
+ szbox[3].gd.label = (GTextInfo *) &szgcd[3];
+ szbox[3].gd.u.boxelements = szarray3;
+ szbox[3].creator = GHVGroupCreate;
+
+ szbox[4].gd.flags = gg_enabled|gg_visible;
+ szbox[4].gd.u.boxelements = szarray4;
+ szbox[4].creator = GHBoxCreate;
+
+ szbox[5].gd.flags = gg_enabled|gg_visible;
+ szbox[5].gd.u.boxelements = szarray5;
+ szbox[5].creator = GHBoxCreate;
+
+/******************************************************************************/
+ memset(&mcgcd,0,sizeof(mcgcd));
+ memset(&mclabel,'\0',sizeof(mclabel));
+
+ k=0;
+ mclabel[k].text = (unichar_t *) _("Mac Style Set:");
+ mclabel[k].text_is_1byte = true;
+ mcgcd[k].gd.label = &mclabel[k];
+ mcgcd[k].gd.pos.x = 10; mcgcd[k].gd.pos.y = 7;
+ mcgcd[k].gd.flags = gg_visible | gg_enabled;
+ mcgcd[k++].creator = GLabelCreate;
+
+ mclabel[k].text = (unichar_t *) _("Automatic");
+ mclabel[k].text_is_1byte = true;
+ mcgcd[k].gd.label = &mclabel[k];
+ mcgcd[k].gd.pos.x = 10; mcgcd[k].gd.pos.y = 20;
+ mcgcd[k].gd.flags = (sf->macstyle==-1) ? (gg_visible | gg_enabled | gg_cb_on) : (gg_visible | gg_enabled);
+ mcgcd[k].gd.cid = CID_MacAutomatic;
+ mcgcd[k].gd.handle_controlevent = GFI_MacAutomatic;
+ mcgcd[k++].creator = GRadioCreate;
+
+ mcgcd[k].gd.pos.x = 90; mcgcd[k].gd.pos.y = 20;
+ mcgcd[k].gd.flags = (sf->macstyle!=-1) ? (gg_visible | gg_enabled | gg_cb_on | gg_rad_continueold) : (gg_visible | gg_enabled | gg_rad_continueold);
+ mcgcd[k].gd.handle_controlevent = GFI_MacAutomatic;
+ mcgcd[k++].creator = GRadioCreate;
+
+ mcgcd[k].gd.pos.x = 110; mcgcd[k].gd.pos.y = 20;
+ mcgcd[k].gd.pos.width = 120; mcgcd[k].gd.pos.height = 7*12+10;
+ mcgcd[k].gd.flags = (sf->macstyle==-1) ? (gg_visible | gg_list_multiplesel) : (gg_visible | gg_enabled | gg_list_multiplesel);
+ mcgcd[k].gd.cid = CID_MacStyles;
+ mcgcd[k].gd.u.list = macstyles;
+ mcgcd[k++].creator = GListCreate;
+
+ mclabel[k].text = (unichar_t *) _("FOND Name:");
+ mclabel[k].text_is_1byte = true;
+ mcgcd[k].gd.label = &mclabel[k];
+ mcgcd[k].gd.pos.x = 10; mcgcd[k].gd.pos.y = mcgcd[k-1].gd.pos.y + mcgcd[k-1].gd.pos.height+8;
+ mcgcd[k].gd.flags = gg_visible | gg_enabled;
+ mcgcd[k++].creator = GLabelCreate;
+
+ mclabel[k].text = (unichar_t *) sf->fondname;
+ mclabel[k].text_is_1byte = true;
+ mcgcd[k].gd.label = sf->fondname==NULL ? NULL : &mclabel[k];
+ mcgcd[k].gd.pos.x = 90; mcgcd[k].gd.pos.y = mcgcd[k-1].gd.pos.y - 4;
+ mcgcd[k].gd.flags = gg_visible | gg_enabled;
+ mcgcd[k].gd.cid = CID_MacFOND;
+ mcgcd[k++].creator = GTextFieldCreate;
+
+
+ mcs = MacStyleCode(sf,NULL);
+ for ( i=0; macstyles[i].text!=NULL; ++i )
+ macstyles[i].selected = (mcs&(int) (intpt) macstyles[i].userdata)? 1 : 0;
+
+ mcarray[0] = &mcgcd[0]; mcarray[1] = GCD_Glue; mcarray[2] = NULL;
+ mcarray[3] = &mcbox[2]; mcarray[4] = &mcgcd[3]; mcarray[5] = NULL;
+ mcarray[6] = &mcgcd[4]; mcarray[7] = &mcgcd[5]; mcarray[8] = NULL;
+ mcarray[9] = GCD_Glue; mcarray[10] = GCD_Glue; mcarray[11] = NULL;
+ mcarray[12] = NULL;
+ mcarray2[0] = &mcgcd[1]; mcarray2[1] = &mcgcd[2]; mcarray2[2] = NULL;
+ mcarray2[3] = GCD_Glue; mcarray2[4] = GCD_Glue; mcarray2[5] = NULL;
+ mcarray2[6] = NULL;
+
+ memset(mcbox,0,sizeof(mcbox));
+ mcbox[0].gd.flags = gg_enabled|gg_visible;
+ mcbox[0].gd.u.boxelements = mcarray;
+ mcbox[0].creator = GHVBoxCreate;
+
+ mcbox[2].gd.flags = gg_enabled|gg_visible;
+ mcbox[2].gd.u.boxelements = mcarray2;
+ mcbox[2].creator = GHVBoxCreate;
+
+/******************************************************************************/
+ memset(&lksubgcd,0,sizeof(lksubgcd));
+ memset(&lkgcd,0,sizeof(lkgcd));
+ memset(&lkaspects,'\0',sizeof(lkaspects));
+ memset(&lkbox,'\0',sizeof(lkbox));
+ memset(&lkbuttonsgcd,'\0',sizeof(lkbuttonsgcd));
+ memset(&lkbuttonslabel,'\0',sizeof(lkbuttonslabel));
+
+ LookupSetup(&d->tables[0],sf->gsub_lookups);
+ LookupSetup(&d->tables[1],sf->gpos_lookups);
+
+ i=0;
+ lkbuttonsarray[i] = &lkbuttonsgcd[i];
+ lkbuttonsgcd[i].gd.flags = gg_visible | gg_utf8_popup ;
+ lkbuttonsgcd[i].gd.popup_msg = (unichar_t *) _("Moves the currently selected lookup to be first in the lookup ordering\nor moves the currently selected subtable to be first in its lookup.");
+ lkbuttonslabel[i].text = (unichar_t *) _("_Top");
+ lkbuttonslabel[i].text_is_1byte = true;
+ lkbuttonslabel[i].text_in_resource = true;
+ lkbuttonsgcd[i].gd.label = &lkbuttonslabel[i];
+ lkbuttonsgcd[i].gd.cid = CID_LookupTop;
+ lkbuttonsgcd[i].gd.handle_controlevent = GFI_LookupOrder;
+ lkbuttonsgcd[i++].creator = GButtonCreate;
+
+ lkbuttonsarray[i] = &lkbuttonsgcd[i];
+ lkbuttonsgcd[i].gd.flags = gg_visible | gg_utf8_popup ;
+ lkbuttonsgcd[i].gd.popup_msg = (unichar_t *) _("Moves the currently selected lookup before the previous lookup\nor moves the currently selected subtable before the previous subtable.");
+ lkbuttonslabel[i].text = (unichar_t *) _("_Up");
+ lkbuttonslabel[i].text_is_1byte = true;
+ lkbuttonslabel[i].text_in_resource = true;
+ lkbuttonsgcd[i].gd.label = &lkbuttonslabel[i];
+ lkbuttonsgcd[i].gd.cid = CID_LookupUp;
+ lkbuttonsgcd[i].gd.handle_controlevent = GFI_LookupOrder;
+ lkbuttonsgcd[i++].creator = GButtonCreate;
+
+ lkbuttonsarray[i] = &lkbuttonsgcd[i];
+ lkbuttonsgcd[i].gd.flags = gg_visible | gg_utf8_popup ;
+ lkbuttonsgcd[i].gd.popup_msg = (unichar_t *) _("Moves the currently selected lookup after the next lookup\nor moves the currently selected subtable after the next subtable.");
+ lkbuttonslabel[i].text = (unichar_t *) _("_Down");
+ lkbuttonslabel[i].text_is_1byte = true;
+ lkbuttonslabel[i].text_in_resource = true;
+ lkbuttonsgcd[i].gd.label = &lkbuttonslabel[i];
+ lkbuttonsgcd[i].gd.cid = CID_LookupDown;
+ lkbuttonsgcd[i].gd.handle_controlevent = GFI_LookupOrder;
+ lkbuttonsgcd[i++].creator = GButtonCreate;
+
+ lkbuttonsarray[i] = &lkbuttonsgcd[i];
+ lkbuttonsgcd[i].gd.flags = gg_visible | gg_utf8_popup ;
+ lkbuttonsgcd[i].gd.popup_msg = (unichar_t *) _("Moves the currently selected lookup to the end of the lookup chain\nor moves the currently selected subtable to be the last subtable in the lookup");
+ lkbuttonslabel[i].text = (unichar_t *) _("_Bottom");
+ lkbuttonslabel[i].text_is_1byte = true;
+ lkbuttonslabel[i].text_in_resource = true;
+ lkbuttonsgcd[i].gd.label = &lkbuttonslabel[i];
+ lkbuttonsgcd[i].gd.cid = CID_LookupBottom;
+ lkbuttonsgcd[i].gd.handle_controlevent = GFI_LookupOrder;
+ lkbuttonsgcd[i++].creator = GButtonCreate;
+
+ lkbuttonsarray[i] = &lkbuttonsgcd[i];
+ lkbuttonsgcd[i].gd.flags = gg_visible | gg_utf8_popup ;
+ lkbuttonsgcd[i].gd.popup_msg = (unichar_t *) _("Sorts the lookups in a default ordering based on feature tags");
+ lkbuttonslabel[i].text = (unichar_t *) _("_Sort");
+ lkbuttonslabel[i].text_is_1byte = true;
+ lkbuttonslabel[i].text_in_resource = true;
+ lkbuttonsgcd[i].gd.label = &lkbuttonslabel[i];
+ lkbuttonsgcd[i].gd.cid = CID_LookupSort;
+ lkbuttonsgcd[i].gd.handle_controlevent = GFI_LookupSort;
+ lkbuttonsgcd[i++].creator = GButtonCreate;
+
+ lkbuttonsarray[i] = &lkbuttonsgcd[i];
+ lkbuttonsgcd[i].gd.flags = gg_visible | gg_enabled ;
+ lkbuttonsgcd[i++].creator = GLineCreate;
+
+ lkbuttonsarray[i] = &lkbuttonsgcd[i];
+ lkbuttonsgcd[i].gd.flags = gg_visible | gg_enabled | gg_utf8_popup ;
+ lkbuttonsgcd[i].gd.popup_msg = (unichar_t *) _("Adds a new lookup after the selected lookup\nor at the start of the lookup list if nothing is selected.");
+ lkbuttonslabel[i].text = (unichar_t *) _("Add _Lookup");
+ lkbuttonslabel[i].text_is_1byte = true;
+ lkbuttonslabel[i].text_in_resource = true;
+ lkbuttonsgcd[i].gd.label = &lkbuttonslabel[i];
+ lkbuttonsgcd[i].gd.cid = CID_AddLookup;
+ lkbuttonsgcd[i].gd.handle_controlevent = GFI_LookupAddLookup;
+ lkbuttonsgcd[i++].creator = GButtonCreate;
+
+ lkbuttonsarray[i] = &lkbuttonsgcd[i];
+ lkbuttonsgcd[i].gd.flags = gg_visible | gg_utf8_popup ;
+ lkbuttonsgcd[i].gd.popup_msg = (unichar_t *) _("Adds a new lookup subtable after the selected subtable\nor at the start of the lookup if nothing is selected.");
+ lkbuttonslabel[i].text = (unichar_t *) _("Add Sub_table");
+ lkbuttonslabel[i].text_is_1byte = true;
+ lkbuttonslabel[i].text_in_resource = true;
+ lkbuttonsgcd[i].gd.label = &lkbuttonslabel[i];
+ lkbuttonsgcd[i].gd.cid = CID_AddSubtable;
+ lkbuttonsgcd[i].gd.handle_controlevent = GFI_LookupAddSubtable;
+ lkbuttonsgcd[i++].creator = GButtonCreate;
+
+ lkbuttonsarray[i] = &lkbuttonsgcd[i];
+ lkbuttonsgcd[i].gd.flags = gg_visible | gg_utf8_popup ;
+ lkbuttonsgcd[i].gd.popup_msg = (unichar_t *) _("Edits a lookup or lookup subtable.");
+ lkbuttonslabel[i].text = (unichar_t *) _("Edit _Metadata");
+ lkbuttonslabel[i].text_is_1byte = true;
+ lkbuttonslabel[i].text_in_resource = true;
+ lkbuttonsgcd[i].gd.label = &lkbuttonslabel[i];
+ lkbuttonsgcd[i].gd.cid = CID_EditMetadata;
+ lkbuttonsgcd[i].gd.handle_controlevent = GFI_LookupEditMetadata;
+ lkbuttonsgcd[i++].creator = GButtonCreate;
+
+ lkbuttonsarray[i] = &lkbuttonsgcd[i];
+ lkbuttonsgcd[i].gd.flags = gg_visible | gg_utf8_popup ;
+ lkbuttonsgcd[i].gd.popup_msg = (unichar_t *) _("Edits the transformations in a lookup subtable.");
+ lkbuttonslabel[i].text = (unichar_t *) _("_Edit Data");
+ lkbuttonslabel[i].text_is_1byte = true;
+ lkbuttonslabel[i].text_in_resource = true;
+ lkbuttonsgcd[i].gd.label = &lkbuttonslabel[i];
+ lkbuttonsgcd[i].gd.cid = CID_EditSubtable;
+ lkbuttonsgcd[i].gd.handle_controlevent = GFI_LookupEditSubtableContents;
+ lkbuttonsgcd[i++].creator = GButtonCreate;
+
+ lkbuttonsarray[i] = &lkbuttonsgcd[i];
+ lkbuttonsgcd[i].gd.flags = gg_visible | gg_utf8_popup ;
+ lkbuttonsgcd[i].gd.popup_msg = (unichar_t *) _("Deletes any selected lookups and their subtables, or deletes any selected subtables.\nThis will also delete any transformations associated with those subtables.");
+ lkbuttonslabel[i].text = (unichar_t *) _("De_lete");
+ lkbuttonslabel[i].text_is_1byte = true;
+ lkbuttonslabel[i].text_in_resource = true;
+ lkbuttonsgcd[i].gd.label = &lkbuttonslabel[i];
+ lkbuttonsgcd[i].gd.cid = CID_DeleteLookup;
+ lkbuttonsgcd[i].gd.handle_controlevent = GFI_LookupDeleteLookup;
+ lkbuttonsgcd[i++].creator = GButtonCreate;
+
+ lkbuttonsarray[i] = &lkbuttonsgcd[i];
+ lkbuttonsgcd[i].gd.flags = gg_visible | gg_utf8_popup ;
+ lkbuttonsgcd[i].gd.popup_msg = (unichar_t *) _("Merges two selected (and compatible) lookups into one,\nor merges two selected subtables of a lookup into one");
+ lkbuttonslabel[i].text = (unichar_t *) _("_Merge");
+ lkbuttonslabel[i].text_is_1byte = true;
+ lkbuttonslabel[i].text_in_resource = true;
+ lkbuttonsgcd[i].gd.label = &lkbuttonslabel[i];
+ lkbuttonsgcd[i].gd.cid = CID_MergeLookup;
+ lkbuttonsgcd[i].gd.handle_controlevent = GFI_LookupMergeLookup;
+ lkbuttonsgcd[i++].creator = GButtonCreate;
+
+ lkbuttonsarray[i] = &lkbuttonsgcd[i];
+ lkbuttonsgcd[i].gd.flags = gg_visible | gg_utf8_popup ;
+ lkbuttonsgcd[i].gd.popup_msg = (unichar_t *) _("Reverts the lookup list to its original condition.\nBut any changes to subtable data will remain.");
+ lkbuttonslabel[i].text = (unichar_t *) _("_Revert");
+ lkbuttonslabel[i].text_is_1byte = true;
+ lkbuttonslabel[i].text_in_resource = true;
+ lkbuttonsgcd[i].gd.label = &lkbuttonslabel[i];
+ lkbuttonsgcd[i].gd.cid = CID_RevertLookups;
+ lkbuttonsgcd[i].gd.handle_controlevent = GFI_LookupRevertLookup;
+ lkbuttonsgcd[i++].creator = GButtonCreate;
+
+ lkbuttonsarray[i] = &lkbuttonsgcd[i];
+ lkbuttonsgcd[i].gd.flags = gg_visible | gg_utf8_popup ;
+ lkbuttonsgcd[i].gd.popup_msg = (unichar_t *) _("Imports a lookup (and all its subtables) from another font.");
+ lkbuttonslabel[i].text = (unichar_t *) _("_Import");
+ lkbuttonslabel[i].text_is_1byte = true;
+ lkbuttonslabel[i].text_in_resource = true;
+ lkbuttonsgcd[i].gd.label = &lkbuttonslabel[i];
+ lkbuttonsgcd[i].gd.cid = CID_ImportLookups;
+ lkbuttonsgcd[i].gd.handle_controlevent = GFI_LookupImportLookup;
+ lkbuttonsgcd[i++].creator = GButtonCreate;
+ lkbuttonsarray[i] = GCD_Glue;
+ lkbuttonsarray[i+1] = NULL;
+
+ for ( i=0; i<2; ++i ) {
+ lkaspects[i].text = (unichar_t *) (i?"GPOS":"GSUB");
+ lkaspects[i].text_is_1byte = true;
+ lkaspects[i].gcd = &lkbox[2*i];
+
+ lksubgcd[i][0].gd.pos.x = 10; lksubgcd[i][0].gd.pos.y = 10;
+ lksubgcd[i][0].gd.pos.width = ngcd[15].gd.pos.width;
+ lksubgcd[i][0].gd.pos.height = 150;
+ lksubgcd[i][0].gd.flags = gg_visible | gg_enabled;
+ lksubgcd[i][0].gd.u.drawable_e_h = i ? gposlookups_e_h : gsublookups_e_h;
+ lksubgcd[i][0].gd.cid = CID_LookupWin+i;
+ lksubgcd[i][0].creator = GDrawableCreate;
+
+ lksubgcd[i][1].gd.pos.x = 10; lksubgcd[i][1].gd.pos.y = 10;
+ lksubgcd[i][1].gd.pos.height = 150;
+ lksubgcd[i][1].gd.flags = gg_visible | gg_enabled | gg_sb_vert;
+ lksubgcd[i][1].gd.cid = CID_LookupVSB+i;
+ lksubgcd[i][1].gd.handle_controlevent = LookupsVScroll;
+ lksubgcd[i][1].creator = GScrollBarCreate;
+
+ lksubgcd[i][2].gd.pos.x = 10; lksubgcd[i][2].gd.pos.y = 10;
+ lksubgcd[i][2].gd.pos.width = 150;
+ lksubgcd[i][2].gd.flags = gg_visible | gg_enabled;
+ lksubgcd[i][2].gd.cid = CID_LookupHSB+i;
+ lksubgcd[i][2].gd.handle_controlevent = LookupsHScroll;
+ lksubgcd[i][2].creator = GScrollBarCreate;
+
+ lksubgcd[i][3].gd.pos.x = 10; lksubgcd[i][3].gd.pos.y = 10;
+ lksubgcd[i][3].gd.pos.width = lksubgcd[i][3].gd.pos.height = _GScrollBar_Width;
+ lksubgcd[i][3].gd.flags = gg_visible | gg_enabled | gg_tabset_nowindow;
+ lksubgcd[i][3].creator = GDrawableCreate;
+
+ lkarray[i][0] = &lksubgcd[i][0]; lkarray[i][1] = &lksubgcd[i][1]; lkarray[i][2] = NULL;
+ lkarray[i][3] = &lksubgcd[i][2]; lkarray[i][4] = &lksubgcd[i][3]; lkarray[i][5] = NULL;
+ lkarray[i][6] = NULL;
+
+ lkbox[2*i].gd.flags = gg_enabled|gg_visible;
+ lkbox[2*i].gd.u.boxelements = lkarray[i];
+ lkbox[2*i].creator = GHVBoxCreate;
+ }
+
+ lkaspects[0].selected = true;
+
+ lkgcd[0].gd.pos.x = 4; lkgcd[0].gd.pos.y = 10;
+ lkgcd[0].gd.pos.width = 250;
+ lkgcd[0].gd.pos.height = 260;
+ lkgcd[0].gd.u.tabs = lkaspects;
+ lkgcd[0].gd.flags = gg_visible | gg_enabled;
+ lkgcd[0].gd.cid = CID_Lookups;
+ lkgcd[0].gd.handle_controlevent = GFI_LookupAspectChange;
+ lkgcd[0].creator = GTabSetCreate;
+
+ lkharray[0] = &lkgcd[0]; lkharray[1] = &lkbox[4]; lkharray[2] = NULL;
+
+ lkbox[4].gd.flags = gg_enabled|gg_visible;
+ lkbox[4].gd.u.boxelements = lkbuttonsarray;
+ lkbox[4].creator = GVBoxCreate;
+
+ lkbox[5].gd.flags = gg_enabled|gg_visible;
+ lkbox[5].gd.u.boxelements = lkharray;
+ lkbox[5].creator = GHBoxCreate;
+
+
+/******************************************************************************/
+ memset(&mfgcd,0,sizeof(mfgcd));
+ memset(&mflabel,'\0',sizeof(mflabel));
+ memset(mfbox,0,sizeof(mfbox));
+
+ GCDFillMacFeat(mfgcd,mflabel,250,sf->features, false, mfbox, mfarray);
+/******************************************************************************/
+
+ memset(&dlabel,0,sizeof(dlabel));
+ memset(&dgcd,0,sizeof(dgcd));
+
+ dlabel[0].text = (unichar_t *) _("Creation Date:");
+ dlabel[0].text_is_1byte = true;
+ dlabel[0].text_in_resource = true;
+ dgcd[0].gd.label = &dlabel[0];
+ dgcd[0].gd.pos.x = 12; dgcd[0].gd.pos.y = 6+6;
+ dgcd[0].gd.flags = gg_visible | gg_enabled;
+ dgcd[0].creator = GLabelCreate;
+
+ t = sf->creationtime;
+ tm = localtime(&t);
+ strftime(createtime,sizeof(createtime),"%c",tm);
+ tmpcreatetime = def2u_copy(createtime);
+ dgcd[1].gd.pos.x = 115; dgcd[1].gd.pos.y = dgcd[0].gd.pos.y;
+ dgcd[1].gd.flags = gg_visible | gg_enabled;
+ dlabel[1].text = tmpcreatetime;
+ dgcd[1].gd.label = &dlabel[1];
+ dgcd[1].creator = GLabelCreate;
+
+ dlabel[2].text = (unichar_t *) _("Modification Date:");
+ dlabel[2].text_is_1byte = true;
+ dlabel[2].text_in_resource = true;
+ dgcd[2].gd.label = &dlabel[2];
+ dgcd[2].gd.pos.x = 12; dgcd[2].gd.pos.y = dgcd[0].gd.pos.y+14;
+ dgcd[2].gd.flags = gg_visible | gg_enabled;
+ dgcd[2].creator = GLabelCreate;
+
+ t = sf->modificationtime;
+ tm = localtime(&t);
+ strftime(modtime,sizeof(modtime),"%c",tm);
+ tmpmodtime = def2u_copy(modtime);
+ dgcd[3].gd.pos.x = 115; dgcd[3].gd.pos.y = dgcd[2].gd.pos.y;
+ dgcd[3].gd.flags = gg_visible | gg_enabled;
+ dlabel[3].text = tmpmodtime;
+ dgcd[3].gd.label = &dlabel[3];
+ dgcd[3].creator = GLabelCreate;
+
+ darray[0] = &dgcd[0]; darray[1] = &dgcd[1]; darray[2] = NULL;
+ darray[3] = &dgcd[2]; darray[4] = &dgcd[3]; darray[5] = NULL;
+ darray[6] = GCD_Glue; darray[7] = GCD_Glue; darray[8] = NULL;
+ darray[9] = NULL;
+
+ memset(dbox,0,sizeof(dbox));
+ dbox[0].gd.flags = gg_enabled|gg_visible;
+ dbox[0].gd.u.boxelements = darray;
+ dbox[0].creator = GHVBoxCreate;
+/******************************************************************************/
+
+ memset(&ulabel,0,sizeof(ulabel));
+ memset(&ugcd,0,sizeof(ugcd));
+
+ ulabel[0].text = (unichar_t *) _("Include Empty Blocks");
+ ulabel[0].text_is_1byte = true;
+ ulabel[0].text_in_resource = true;
+ ugcd[0].gd.label = &ulabel[0];
+ ugcd[0].gd.pos.x = 12; ugcd[0].gd.pos.y = 10;
+ ugcd[0].gd.flags = gg_visible | gg_enabled;
+ ugcd[0].gd.handle_controlevent = GFI_UnicodeEmptiesChange;
+ ugcd[0].gd.cid = CID_UnicodeEmpties;
+ ugcd[0].creator = GCheckBoxCreate;
+
+ ugcd[1].gd.pos.x = 12; ugcd[1].gd.pos.y = 30;
+ ugcd[1].gd.pos.width = ngcd[15].gd.pos.width;
+ ugcd[1].gd.pos.height = 200;
+ ugcd[1].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ ugcd[1].gd.cid = CID_Unicode;
+ ugcd[1].gd.handle_controlevent = GFI_UnicodeRangeChange;
+ ugcd[1].gd.popup_msg = (unichar_t *) _("Click on a range to select characters in that range.\nDouble click on a range to see characters that should be\nin the range but aren't.");
+ ugcd[1].creator = GListCreate;
+
+ uarray[0] = &ugcd[0]; uarray[1] = &ugcd[1]; uarray[2] = NULL;
+
+ memset(ubox,0,sizeof(ubox));
+ ubox[0].gd.flags = gg_enabled|gg_visible;
+ ubox[0].gd.u.boxelements = uarray;
+ ubox[0].creator = GVBoxCreate;
+
+/******************************************************************************/
+
+ memset(&mlabel,0,sizeof(mlabel));
+ memset(&mgcd,0,sizeof(mgcd));
+ memset(&aspects,'\0',sizeof(aspects));
+
+ i = 0;
+
+ aspects[i].text = (unichar_t *) _("Names");
+ d->old_aspect = 0;
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = nb;
+
+ aspects[i].text = (unichar_t *) _("General");
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = psb;
+
+ aspects[i].text = (unichar_t *) _("PS UID");
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = xub;
+
+ d->private_aspect = i;
+ aspects[i].text = (unichar_t *) _("PS Private");
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = ppbox;
+
+ d->ttfv_aspect = i;
+ aspects[i].text = (unichar_t *) _("OS/2");
+ if ( sf->cidmaster!=NULL ) aspects[i].disabled = true;
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = vagcd;
+
+ d->tn_aspect = i;
+ if ( sf->cidmaster!=NULL ) aspects[i].disabled = true;
+ aspects[i].text = (unichar_t *) _("TTF Names");
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = tnboxes;
+
+ if ( sf->cidmaster!=NULL ) aspects[i].disabled = true;
+ aspects[i].text = (unichar_t *) _("Grid Fitting");
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = gaspboxes;
+
+ d->tx_aspect = i;
+/* xgettext won't use non-ASCII messages */
+ aspects[i].text = (unichar_t *) U_("\316\244\316\265\316\247"); /* Tau epsilon Chi, in greek */
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = txbox;
+
+ if ( sf->cidmaster!=NULL ) aspects[i].disabled = true;
+ aspects[i].text = (unichar_t *) _("Size");
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = szbox;
+
+ aspects[i].text = (unichar_t *) _("Comment");
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = combox;
+
+ if ( sf->cidmaster!=NULL ) aspects[i].disabled = true;
+ aspects[i].text = (unichar_t *) _("Mark Classes");
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = mkbox;
+
+/* GT: OpenType GPOS/GSUB lookups */
+ if ( sf->cidmaster!=NULL ) aspects[i].disabled = true;
+ aspects[i].text = (unichar_t *) S_("OpenType|Lookups");
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = &lkbox[5];
+
+ aspects[i].text = (unichar_t *) _("Mac");
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = mcbox;
+
+ aspects[i].text = (unichar_t *) _("Mac Features");
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = mfbox;
+
+#ifndef FONTFORGE_CONFIG_INFO_HORIZONTAL
+ aspects[i].text = (unichar_t *) _("Dates");
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = dbox;
+
+ d->unicode_aspect = i;
+ aspects[i].text = (unichar_t *) _("Unicode Ranges");
+ aspects[i].text_is_1byte = true;
+ aspects[i++].gcd = ubox;
+#endif
+
+ aspects[defaspect].selected = true;
+
+ mgcd[0].gd.pos.x = 4; mgcd[0].gd.pos.y = 6;
+ mgcd[0].gd.u.tabs = aspects;
+#ifndef FONTFORGE_CONFIG_INFO_HORIZONTAL
+ mgcd[0].gd.flags = gg_visible | gg_enabled | gg_tabset_vert;
+ mgcd[0].gd.pos.width = 260+85;
+ mgcd[0].gd.pos.height = 325;
+#else
+ mgcd[0].gd.flags = gg_visible | gg_enabled;
+ mgcd[0].gd.pos.width = 260;
+ mgcd[0].gd.pos.height = 325;
+#endif
+ mgcd[0].gd.handle_controlevent = GFI_AspectChange;
+ mgcd[0].gd.cid = CID_Tabs;
+ mgcd[0].creator = GTabSetCreate;
+
+ mgcd[1].gd.pos.x = 30-3; mgcd[1].gd.pos.y = GDrawPixelsToPoints(NULL,pos.height)-35-3;
+ mgcd[1].gd.pos.width = -1; mgcd[1].gd.pos.height = 0;
+ mgcd[1].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ mlabel[1].text = (unichar_t *) _("_OK");
+ mlabel[1].text_is_1byte = true;
+ mlabel[1].text_in_resource = true;
+ mgcd[1].gd.label = &mlabel[1];
+ mgcd[1].gd.handle_controlevent = GFI_OK;
+ mgcd[1].gd.cid = CID_OK;
+ mgcd[1].creator = GButtonCreate;
+
+ mgcd[2].gd.pos.x = -30; mgcd[2].gd.pos.y = mgcd[1].gd.pos.y+3;
+ mgcd[2].gd.pos.width = -1; mgcd[2].gd.pos.height = 0;
+ mgcd[2].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ mlabel[2].text = (unichar_t *) _("_Cancel");
+ mlabel[2].text_is_1byte = true;
+ mlabel[2].text_in_resource = true;
+ mgcd[2].gd.label = &mlabel[2];
+ mgcd[2].gd.handle_controlevent = GFI_Cancel;
+ mgcd[2].gd.cid = CID_Cancel;
+ mgcd[2].creator = GButtonCreate;
+
+ mgcd[3].gd.pos.x = 2; mgcd[3].gd.pos.y = 2;
+ mgcd[3].gd.pos.width = pos.width-4; mgcd[3].gd.pos.height = pos.height-4;
+ mgcd[3].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
+ mgcd[3].gd.cid = CID_MainGroup;
+ mgcd[3].creator = GGroupCreate;
+
+ marray2[0] = marray2[2] = marray2[3] = marray2[4] = marray2[6] = GCD_Glue; marray2[7] = NULL;
+ marray2[1] = &mgcd[1]; marray2[5] = &mgcd[2];
+
+ marray[0] = &mgcd[0]; marray[1] = NULL;
+ marray[2] = &mb2; marray[3] = NULL;
+ marray[4] = GCD_Glue; marray[5] = NULL;
+ marray[6] = NULL;
+
+ memset(mb,0,sizeof(mb));
+ mb[0].gd.pos.x = mb[0].gd.pos.y = 2;
+ mb[0].gd.flags = gg_enabled|gg_visible;
+ mb[0].gd.u.boxelements = marray;
+ mb[0].creator = GHVBoxCreate;
+
+ memset(&mb2,0,sizeof(mb2));
+ mb2.gd.flags = gg_enabled|gg_visible;
+ mb2.gd.u.boxelements = marray2;
+ mb2.creator = GHBoxCreate;
+
+ GGadgetsCreate(gw,mb);
+ GMatrixEditSetNewText(tngcd[4].ret,S_("TrueTypeName|New"));
+ GGadgetSelectOneListItem(gaspgcd[0].ret,sf->gasp_version);
+ GMatrixEditSetNewText(gaspgcd[3].ret,S_("gaspTableEntry|New"));
+ GMatrixEditAddButtons(gaspgcd[3].ret,gaspgcd_def);
+ if ( sf->gasp_version==0 ) {
+ GMatrixEditEnableColumn(gaspgcd[3].ret,3,false);
+ GMatrixEditEnableColumn(gaspgcd[3].ret,4,false);
+ }
+ GHVBoxSetExpandableCol(gaspboxes[2].ret,2);
+ GHVBoxSetExpandableRow(gaspboxes[0].ret,1);
+
+ GHVBoxSetExpandableRow(mb[0].ret,0);
+ GHVBoxSetExpandableCol(mb2.ret,gb_expandgluesame);
+
+ GHVBoxSetExpandableCol(nb[0].ret,1);
+ GHVBoxSetExpandableRow(nb[0].ret,7);
+ GHVBoxSetExpandableCol(nb2.ret,1);
+ GHVBoxSetExpandableCol(nb3.ret,1);
+
+ GHVBoxSetExpandableCol(xub[0].ret,1);
+ GHVBoxSetExpandableRow(xub[0].ret,3);
+
+ GHVBoxSetExpandableRow(psb[0].ret,psrow);
+ GHVBoxSetExpandableCol(psb2[0].ret,3);
+ GHVBoxSetExpandableCol(psb2[1].ret,1);
+ GHVBoxSetExpandableCol(psb2[2].ret,1);
+
+ GHVBoxSetExpandableRow(ppbox[0].ret,0);
+ GHVBoxSetExpandableCol(ppbox[2].ret,gb_samesize);
+
+ GHVBoxSetExpandableRow(vbox[0].ret,gb_expandglue);
+ GHVBoxSetExpandableCol(vbox[0].ret,1);
+ GHVBoxSetExpandableCol(vbox[2].ret,gb_expandglue);
+
+ GHVBoxSetExpandableRow(metbox[0].ret,10);
+ GHVBoxSetExpandableCol(metbox[0].ret,1);
+
+ GHVBoxSetExpandableRow(ssbox[0].ret,gb_expandglue);
+ GHVBoxSetExpandableCol(ssbox[0].ret,gb_expandglue);
+
+ GHVBoxSetExpandableRow(panbox[0].ret,gb_expandglue);
+ GHVBoxSetExpandableCol(panbox[0].ret,1);
+
+ GHVBoxSetExpandableRow(mkbox[0].ret,0);
+ GHVBoxSetExpandableCol(mkbox[2].ret,gb_expandglue);
+
+ GHVBoxSetExpandableRow(txbox[0].ret,gb_expandglue);
+ GHVBoxSetExpandableCol(txbox[2].ret,gb_expandglue);
+ GHVBoxSetExpandableCol(txbox[3].ret,gb_expandglue);
+ GHVBoxSetExpandableCol(txbox[4].ret,gb_expandglue);
+
+ GHVBoxSetExpandableRow(szbox[0].ret,4);
+ GHVBoxSetPadding(szbox[2].ret,6,2);
+ GHVBoxSetExpandableCol(szbox[2].ret,gb_expandglue);
+ GHVBoxSetPadding(szbox[3].ret,6,2);
+ GHVBoxSetExpandableCol(szbox[3].ret,gb_expandglue);
+ GHVBoxSetPadding(szbox[4].ret,6,2);
+ GHVBoxSetExpandableCol(szbox[4].ret,gb_expandglue);
+ GHVBoxSetExpandableCol(szbox[5].ret,gb_expandglue);
+
+ GHVBoxSetExpandableRow(tnboxes[0].ret,1);
+ GHVBoxSetExpandableCol(tnboxes[2].ret,gb_expandglue);
+ GHVBoxSetExpandableCol(tnboxes[3].ret,gb_expandglue);
+
+ GHVBoxSetExpandableRow(mcbox[0].ret,gb_expandglue);
+ GHVBoxSetExpandableCol(mcbox[0].ret,1);
+ GHVBoxSetExpandableRow(mcbox[2].ret,gb_expandglue);
+
+ GHVBoxSetExpandableRow(mfbox[0].ret,0);
+ GHVBoxSetExpandableRow(mfbox[2].ret,gb_expandglue);
+
+ GHVBoxSetExpandableRow(dbox[0].ret,gb_expandglue);
+ GHVBoxSetExpandableCol(dbox[0].ret,1);
+
+ GHVBoxSetExpandableRow(ubox[0].ret,1);
+
+ GHVBoxSetExpandableCol(lkbox[0].ret,0);
+ GHVBoxSetExpandableRow(lkbox[0].ret,0);
+ GHVBoxSetPadding(lkbox[0].ret,0,0);
+ GHVBoxSetExpandableCol(lkbox[2].ret,0);
+ GHVBoxSetExpandableRow(lkbox[2].ret,0);
+ GHVBoxSetPadding(lkbox[2].ret,0,0);
+ GHVBoxSetExpandableRow(lkbox[4].ret,gb_expandglue);
+ GHVBoxSetExpandableCol(lkbox[5].ret,0);
+
+ GFI_LookupEnableButtons(d,true);
+ GFI_LookupEnableButtons(d,false);
+
+ memset(&rq,0,sizeof(rq));
+ rq.family_name = sans;
+ rq.point_size = 12;
+ rq.weight = 400;
+ d->font = GDrawInstanciateFont(GDrawGetDisplayOfWindow(gw),&rq);
+ GDrawFontMetrics(d->font,&as,&ds,&ld);
+ d->as = as; d->fh = as+ds;
+
+ GTextInfoListFree(namelistnames);
+ GTextInfoListFree(pgcd[0].gd.u.list);
+
+ for ( i=0; i<mi.initial_row_cnt; ++i )
+ free( mi.matrix_data[3*i+2].u.md_str );
+ free( mi.matrix_data );
+
+ free(tmpcreatetime);
+ free(tmpmodtime);
+
+ GHVBoxFitWindow(mb[0].ret);
+#if 0
+ if ( GTabSetGetTabLines(mgcd[0].ret)>3 ) {
+ int offset = (GTabSetGetTabLines(mgcd[0].ret)-2)*GDrawPointsToPixels(NULL,20);
+ GDrawResize(gw,pos.width,pos.height+offset);
+ }
+#endif
+
+ GWidgetIndicateFocusGadget(ngcd[1].ret);
+ ProcessListSel(d);
+ GFI_AspectChange(mgcd[0].ret,NULL);
+ GFI_InitMarkClasses(d);
+ GGadgetSetList(GWidgetGetControl(gw,CID_StyleName),StyleNames(sf->fontstyle_name),false);
+
+ GWidgetHidePalettes();
+ GDrawSetVisible(gw,true);
+
+ if ( sync ) {
+ while ( !d->done )
+ GDrawProcessOneEvent(NULL);
+ }
+}
+
+void FontMenuFontInfo(void *_fv) {
+ FontInfo( ((FontView *) _fv)->sf,-1,false);
+}
+
+void FontInfoDestroy(SplineFont *sf) {
+ if ( sf->fontinfo )
+ GFI_CancelClose( (struct gfi_data *) (sf->fontinfo) );
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+
+void FontInfoInit(void) {
+ static int done = false;
+ int i, j;
+ static GTextInfo *needswork[] = {
+ macstyles, widthclass, weightclass, fstype, pfmfamily, ibmfamily,
+ panfamily, panserifs, panweight, panprop, pancontrast, panstrokevar,
+ panarmstyle, panletterform, panmidline, panxheight, mslanguages,
+ ttfnameids, interpretations, gridfit, antialias, os2versions,
+ NULL
+ };
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ static char **needswork2[] = { texparams, texpopups,
+ mathparams, mathpopups, extparams, extpopups,
+ NULL };
+#endif
+ if ( done )
+return;
+ done = true;
+#ifndef _NO_PYTHON
+ scriptingSaveEnglishNames(ttfnameids,mslanguages);
+#endif
+ for ( j=0; needswork[j]!=NULL; ++j ) {
+ for ( i=0; needswork[j][i].text!=NULL; ++i )
+ needswork[j][i].text = (unichar_t *) S_((char *) needswork[j][i].text);
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ for ( j=0; needswork2[j]!=NULL; ++j ) {
+ for ( i=0; needswork2[j][i]!=NULL; ++i )
+ needswork2[j][i] = _(needswork2[j][i]);
+ }
+
+ ci[0].title = S_(ci[0].title);
+ ci[1].title = S_(ci[1].title);
+ ci[2].title = S_(ci[2].title);
+
+ gaspci[0].title = S_(gaspci[0].title);
+ gaspci[1].title = S_(gaspci[1].title);
+ gaspci[2].title = S_(gaspci[2].title);
+ gaspci[3].title = S_(gaspci[3].title);
+ gaspci[4].title = S_(gaspci[4].title);
+#endif
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/fontview.c b/Build/source/libs/luafontforge/fontforge/fontforge/fontview.c
new file mode 100644
index 00000000000..f088bbb3c11
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/fontview.c
@@ -0,0 +1,11163 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaeditui.h"
+#include "groups.h"
+#include "psfont.h"
+#include <gfile.h>
+#ifdef FONTFORGE_CONFIG_GTK
+#include <gtkutype.h>
+#else
+#include <ustring.h>
+#include <gkeysym.h>
+#include <utype.h>
+#include <chardata.h>
+#include <gresource.h>
+#endif
+#include <math.h>
+#include <unistd.h>
+
+#ifdef LUA_FF_LIB
+/* from views.h */
+extern void SFAddGlyphAndEncode(SplineFont *sf,SplineChar *sc,EncMap *basemap, int baseenc);
+extern void SFAddEncodingSlot(SplineFont *sf,int gid);
+extern void SFRemoveGlyph(SplineFont *sf,SplineChar *sc, int *flags);
+
+extern int unic_iscombining(int);
+extern int unic_isalpha(int);
+extern void gwwv_post_error(char *a, ...);
+#define Iscombining unic_iscombining
+#define Isalpha unic_isalpha
+#else
+#define Iscombining iscombining
+#define Isalpha isalpha
+#endif
+
+int onlycopydisplayed = 0;
+int copymetadata = 0;
+int copyttfinstr = 0;
+
+struct compressors compressors[] = {
+ { ".gz", "gunzip", "gzip" },
+ { ".bz2", "bunzip2", "bzip2" },
+ { ".Z", "gunzip", "compress" },
+ {NULL}
+};
+
+#define XOR_COLOR 0x505050
+#define FV_LAB_HEIGHT 15
+
+#ifdef FONTFORGE_CONFIG_GDRAW
+/* GTK window icons are set by glade */
+#ifdef BIGICONS
+#define fontview_width 32
+#define fontview_height 32
+static unsigned char fontview_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x02, 0x20, 0x80, 0x00,
+ 0x82, 0x20, 0x86, 0x08, 0x42, 0x21, 0x8a, 0x14, 0xc2, 0x21, 0x86, 0x04,
+ 0x42, 0x21, 0x8a, 0x14, 0x42, 0x21, 0x86, 0x08, 0x02, 0x20, 0x80, 0x00,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 0x20, 0x80, 0x00, 0x82, 0xa0, 0x8f, 0x18,
+ 0x82, 0x20, 0x91, 0x24, 0x42, 0x21, 0x91, 0x02, 0x42, 0x21, 0x91, 0x02,
+ 0x22, 0x21, 0x8f, 0x02, 0xe2, 0x23, 0x91, 0x02, 0x12, 0x22, 0x91, 0x02,
+ 0x3a, 0x27, 0x91, 0x24, 0x02, 0xa0, 0x8f, 0x18, 0x02, 0x20, 0x80, 0x00,
+ 0xfe, 0xff, 0xff, 0xff, 0x02, 0x20, 0x80, 0x00, 0x42, 0x20, 0x86, 0x18,
+ 0xa2, 0x20, 0x8a, 0x04, 0xa2, 0x20, 0x86, 0x08, 0xa2, 0x20, 0x8a, 0x10,
+ 0x42, 0x20, 0x8a, 0x0c, 0x82, 0x20, 0x80, 0x00, 0x02, 0x20, 0x80, 0x00,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 0x20, 0x80, 0x00};
+#else
+#define fontview2_width 16
+#define fontview2_height 16
+static unsigned char fontview2_bits[] = {
+ 0x00, 0x07, 0x80, 0x08, 0x40, 0x17, 0x40, 0x15, 0x60, 0x09, 0x10, 0x02,
+ 0xa0, 0x01, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x50, 0x00, 0x52, 0x00,
+ 0x55, 0x00, 0x5d, 0x00, 0x22, 0x00, 0x1c, 0x00};
+#endif
+
+extern int _GScrollBar_Width;
+
+static int fv_fontsize = -13, fv_fs_init=0;
+#endif
+
+enum glyphlable { gl_glyph, gl_name, gl_unicode, gl_encoding };
+int default_fv_font_size = 24, default_fv_antialias=true,
+ default_fv_bbsized=true,
+ default_fv_showhmetrics=false, default_fv_showvmetrics=false,
+ default_fv_glyphlabel = gl_glyph;
+#define METRICS_BASELINE 0x0000c0
+#define METRICS_ORIGIN 0xc00000
+#define METRICS_ADVANCE 0x008000
+FontView *fv_list=NULL;
+
+#if defined(FONTFORGE_CONFIG_GTK)
+# define FV_From_MI(menuitem) \
+ (FontView *) g_object_get_data( \
+ G_OBJECT( gtk_widget_get_toplevel( GTK_WIDGET( menuitem ))),\
+ "data" )
+#endif
+
+void FVToggleCharChanged(SplineChar *sc) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ int i, j;
+ int pos;
+ FontView *fv;
+
+ for ( fv = sc->parent->fv; fv!=NULL; fv=fv->nextsame ) {
+ if ( fv->sf!=sc->parent ) /* Can happen in CID fonts if char's parent is not currently active */
+ continue;
+ if ( fv->v==NULL || fv->colcnt==0 ) /* Can happen in scripts */
+ continue;
+ for ( pos=0; pos<fv->map->enccount; ++pos ) if ( fv->map->map[pos]==sc->orig_pos ) {
+ if ( fv->mapping!=NULL ) {
+ for ( i=0; i<fv->mapcnt; ++i )
+ if ( fv->mapping[i]==pos )
+ break;
+ if ( i==fv->mapcnt ) /* Not currently displayed */
+ continue;
+ pos = i;
+ }
+ i = pos / fv->colcnt;
+ j = pos - i*fv->colcnt;
+ i -= fv->rowoff;
+ /* Normally we should be checking against fv->rowcnt (rather than <=rowcnt) */
+ /* but every now and then the WM forces us to use a window size which doesn't */
+ /* fit our expectations (maximized view) and we must be prepared for half */
+ /* lines */
+ if ( i>=0 && i<=fv->rowcnt ) {
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GRect r;
+#if 0
+ Color bg;
+ if ( sc->color!=COLOR_DEFAULT )
+ bg = sc->color;
+ else if ( sc->layers[ly_back].splines!=NULL || sc->layers[ly_back].images!=NULL )
+ bg = 0x808080;
+ else
+ bg = GDrawGetDefaultBackground(GDrawGetDisplayOfWindow(fv->v));
+#endif
+ r.x = j*fv->cbw+1; r.width = fv->cbw-1;
+ r.y = i*fv->cbh+1; r.height = fv->lab_height-1;
+ GDrawRequestExpose(fv->v,&r,false);
+#if 0
+ GDrawSetXORBase(fv->v,bg);
+ GDrawSetXORMode(fv->v);
+ GDrawFillRect(fv->v,&r,0x000000);
+ GDrawSetCopyMode(fv->v);
+#endif
+# elif defined(FONTFORGE_CONFIG_GTK)
+ GdkGC *gc = fv->v->style->fg_gc[fv->v->state];
+ GdkGCValues values;
+ GdkColor bg;
+ gdk_gc_get_values(gc,&values);
+ bg.pixel = -1;
+ if ( sc->color!=COLOR_DEFAULT ) {
+ bg.red = ((sc->color>>16)&0xff)*0x101;
+ bg.green = ((sc->color>>8 )&0xff)*0x101;
+ bg.blue = ((sc->color )&0xff)*0x101;
+ } else if ( sc->layers[ly_back].splines!=NULL || sc->layers[ly_back].images!=NULL )
+ bg.red = bg.green = bg.blue = 0x8000;
+ else
+ bg = values.background;
+ /* Bug!!! This only works on RealColor */
+ bg.red ^= values.foreground.red;
+ bg.green ^= values.foreground.green;
+ bg.blue ^= values.foreground.blue;
+ /* End bug */
+ gdk_gc_set_function(gc,GDK_XOR);
+ gdk_gc_set_foreground(gc, &bg);
+ gdk_draw_rectangle(fv->v->window, gc, TRUE,
+ j*fv->cbw+1, i*fv->cbh+1, fv->cbw-1, fv->lab_height);
+ gdk_gc_set_values(gc,&values,
+ GDK_GC_FOREGROUND | GDK_GC_FUNCTION );
+# endif
+ }
+ }
+ }
+#endif
+}
+
+void FVMarkHintsOutOfDate(SplineChar *sc) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ int i, j;
+ int pos;
+ FontView *fv;
+
+ if ( sc->parent->onlybitmaps || sc->parent->multilayer || sc->parent->strokedfont || sc->parent->order2 )
+return;
+ for ( fv = sc->parent->fv; fv!=NULL; fv=fv->nextsame ) {
+ if ( fv->sf!=sc->parent ) /* Can happen in CID fonts if char's parent is not currently active */
+ continue;
+ if ( fv->v==NULL || fv->colcnt==0 ) /* Can happen in scripts */
+ continue;
+ for ( pos=0; pos<fv->map->enccount; ++pos ) if ( fv->map->map[pos]==sc->orig_pos ) {
+ if ( fv->mapping!=NULL ) {
+ for ( i=0; i<fv->mapcnt; ++i )
+ if ( fv->mapping[i]==pos )
+ break;
+ if ( i==fv->mapcnt ) /* Not currently displayed */
+ continue;
+ pos = i;
+ }
+ i = pos / fv->colcnt;
+ j = pos - i*fv->colcnt;
+ i -= fv->rowoff;
+ /* Normally we should be checking against fv->rowcnt (rather than <=rowcnt) */
+ /* but every now and then the WM forces us to use a window size which doesn't */
+ /* fit our expectations (maximized view) and we must be prepared for half */
+ /* lines */
+ if ( i>=0 && i<=fv->rowcnt ) {
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GRect r;
+ Color hintcol = 0x0000ff;
+ r.x = j*fv->cbw+1; r.width = fv->cbw-1;
+ r.y = i*fv->cbh+1; r.height = fv->lab_height-1;
+ GDrawDrawLine(fv->v,r.x,r.y,r.x,r.y+r.height-1,hintcol);
+ GDrawDrawLine(fv->v,r.x+1,r.y,r.x+1,r.y+r.height-1,hintcol);
+ GDrawDrawLine(fv->v,r.x+r.width-1,r.y,r.x+r.width-1,r.y+r.height-1,hintcol);
+ GDrawDrawLine(fv->v,r.x+r.width-2,r.y,r.x+r.width-2,r.y+r.height-1,hintcol);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ GdkColor hintcol;
+ GdkRectangle r;
+ hintcol.red = hintcol.green = 0;
+ hintcol.blue = 0xffff;
+ gdk_gc_set_rgb_fg_color(fv->gc,&hintcol);
+ r.x = j*fv->cbw+1; r.width = fv->cbw-1;
+ r.y = i*fv->cbh+1; r.height = fv->lab_height-1;
+ gdk_draw_line(GDK_DRAWABLE(fv->v),fv->gc,r.x,r.y,r.x,r.y+r.height-1);
+ gdk_draw_line(GDK_DRAWABLE(fv->v),fv->gc,r.x+1,r.y,r.x+1,r.y+r.height-1);
+ gdk_draw_line(GDK_DRAWABLE(fv->v),fv->gc,r.x+r.width-1,r.y,r.x+r.width-1,r.y+r.height-1);
+ gdk_draw_line(GDK_DRAWABLE(fv->v),fv->gc,r.x+r.width-2,r.y,r.x+r.width-2,r.y+r.height-1);
+# endif
+ }
+ }
+ }
+#endif
+}
+
+static void FVToggleCharSelected(FontView *fv,int enc) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ int i, j;
+
+ if ( fv->v==NULL || fv->colcnt==0 ) /* Can happen in scripts */
+return;
+
+ i = enc / fv->colcnt;
+ j = enc - i*fv->colcnt;
+ i -= fv->rowoff;
+ /* Normally we should be checking against fv->rowcnt (rather than <=rowcnt) */
+ /* but every now and then the WM forces us to use a window size which doesn't */
+ /* fit our expectations (maximized view) and we must be prepared for half */
+ /* lines */
+ if ( i>=0 && i<=fv->rowcnt ) {
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GRect r;
+ r.x = j*fv->cbw+1; r.width = fv->cbw-1;
+ r.y = i*fv->cbh+fv->lab_height+1; r.height = fv->cbw;
+ GDrawSetXORBase(fv->v,GDrawGetDefaultBackground(GDrawGetDisplayOfWindow(fv->v)));
+ GDrawSetXORMode(fv->v);
+ GDrawFillRect(fv->v,&r,XOR_COLOR);
+ GDrawSetCopyMode(fv->v);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ GdkGC *gc = fv->v->style->fg_gc[fv->v->state];
+ GdkGCValues values;
+ gdk_gc_get_values(gc,&values);
+ gdk_gc_set_function(gc,GDK_XOR);
+ gdk_gc_set_foreground(gc, &values.background);
+ gdk_draw_rectangle(fv->v->window, gc, TRUE,
+ j*fv->cbw+1, i*fv->cbh+fv->lab_height+1, fv->cbw-1, fv->cbw);
+ gdk_gc_set_values(gc,&values,
+ GDK_GC_FOREGROUND | GDK_GC_FUNCTION );
+# endif
+ }
+#endif
+}
+
+void SFUntickAll(SplineFont *sf) {
+ int i;
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ sf->glyphs[i]->ticked = false;
+}
+
+void FVDeselectAll(FontView *fv) {
+ int i;
+
+ for ( i=0; i<fv->map->enccount; ++i ) {
+ if ( fv->selected[i] ) {
+ fv->selected[i] = false;
+ FVToggleCharSelected(fv,i);
+ }
+ }
+ fv->sel_index = 0;
+}
+
+#ifndef LUA_FF_LIB
+static void FVInvertSelection(FontView *fv) {
+ int i;
+
+ for ( i=0; i<fv->map->enccount; ++i ) {
+ fv->selected[i] = !fv->selected[i];
+ FVToggleCharSelected(fv,i);
+ }
+ fv->sel_index = 1;
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static void FVSelectAll(FontView *fv) {
+ int i;
+
+ for ( i=0; i<fv->map->enccount; ++i ) {
+ if ( !fv->selected[i] ) {
+ fv->selected[i] = true;
+ FVToggleCharSelected(fv,i);
+ }
+ }
+ fv->sel_index = 1;
+}
+
+static void FVSelectByName(FontView *fv) {
+ int j, gid;
+ char *ret, *end;
+ SplineChar *sc;
+ EncMap *map = fv->map;
+ SplineFont *sf = fv->sf;
+ struct altuni *alt;
+
+ ret = gwwv_ask_string(_("Select all instances of the named glyph"),".notdef",_("Select all instances of the named glyph"));
+ if ( ret==NULL )
+return;
+ FVDeselectAll(fv);
+ if (( *ret=='0' && ( ret[1]=='x' || ret[1]=='X' )) ||
+ ((*ret=='u' || *ret=='U') && ret[1]=='+' )) {
+ int uni = strtol(ret+2,&end,16);
+ if ( *end!='\0' || uni<0 || uni>=0x110000 ) {
+ free(ret);
+ gwwv_post_error( _("Bad Number"),_("Bad Number") );
+return;
+ }
+ for ( j=0; j<map->enccount; ++j ) if ( (gid=map->map[j])!=-1 && (sc=sf->glyphs[gid])!=NULL ) {
+ for ( alt=sc->altuni; alt!=NULL && alt->unienc!=uni; alt=alt->next );
+ if ( sc->unicodeenc == uni || alt!=NULL ) {
+ fv->selected[j] = true;
+ FVToggleCharSelected(fv,j);
+ }
+ }
+ } else {
+ for ( j=0; j<map->enccount; ++j ) if ( (gid=map->map[j])!=-1 && (sc=sf->glyphs[gid])!=NULL ) {
+ if ( strcmp(sc->name,ret)==0 ) {
+ fv->selected[j] = true;
+ FVToggleCharSelected(fv,j);
+ }
+ }
+ }
+ free(ret);
+ fv->sel_index = 1;
+}
+
+static void FVSelectColor(FontView *fv, uint32 col, int door) {
+ int i, any=0;
+ uint32 sccol;
+ SplineChar **glyphs = fv->sf->glyphs;
+
+ for ( i=0; i<fv->map->enccount; ++i ) {
+ int gid = fv->map->map[i];
+ sccol = ( gid==-1 || glyphs[gid]==NULL ) ? COLOR_DEFAULT : glyphs[gid]->color;
+ if ( (door && !fv->selected[i] && sccol==col) ||
+ (!door && fv->selected[i]!=(sccol==col)) ) {
+ fv->selected[i] = !fv->selected[i];
+ if ( fv->selected[i] ) any = true;
+ FVToggleCharSelected(fv,i);
+ }
+ }
+ fv->sel_index = any;
+}
+
+static void FVReselect(FontView *fv, int newpos) {
+ int i;
+
+ if ( newpos<0 ) newpos = 0;
+ else if ( newpos>=fv->map->enccount ) newpos = fv->map->enccount-1;
+
+ if ( fv->pressed_pos<fv->end_pos ) {
+ if ( newpos>fv->end_pos ) {
+ for ( i=fv->end_pos+1; i<=newpos; ++i ) if ( !fv->selected[i] ) {
+ fv->selected[i] = fv->sel_index;
+ FVToggleCharSelected(fv,i);
+ }
+ } else if ( newpos<fv->pressed_pos ) {
+ for ( i=fv->end_pos; i>fv->pressed_pos; --i ) if ( fv->selected[i] ) {
+ fv->selected[i] = false;
+ FVToggleCharSelected(fv,i);
+ }
+ for ( i=fv->pressed_pos-1; i>=newpos; --i ) if ( !fv->selected[i] ) {
+ fv->selected[i] = fv->sel_index;
+ FVToggleCharSelected(fv,i);
+ }
+ } else {
+ for ( i=fv->end_pos; i>newpos; --i ) if ( fv->selected[i] ) {
+ fv->selected[i] = false;
+ FVToggleCharSelected(fv,i);
+ }
+ }
+ } else {
+ if ( newpos<fv->end_pos ) {
+ for ( i=fv->end_pos-1; i>=newpos; --i ) if ( !fv->selected[i] ) {
+ fv->selected[i] = fv->sel_index;
+ FVToggleCharSelected(fv,i);
+ }
+ } else if ( newpos>fv->pressed_pos ) {
+ for ( i=fv->end_pos; i<fv->pressed_pos; ++i ) if ( fv->selected[i] ) {
+ fv->selected[i] = false;
+ FVToggleCharSelected(fv,i);
+ }
+ for ( i=fv->pressed_pos+1; i<=newpos; ++i ) if ( !fv->selected[i] ) {
+ fv->selected[i] = fv->sel_index;
+ FVToggleCharSelected(fv,i);
+ }
+ } else {
+ for ( i=fv->end_pos; i<newpos; ++i ) if ( fv->selected[i] ) {
+ fv->selected[i] = false;
+ FVToggleCharSelected(fv,i);
+ }
+ }
+ }
+ fv->end_pos = newpos;
+# ifdef FONTFORGE_CONFIG_GDRAW
+ if ( newpos>=0 && newpos<fv->map->enccount && (i = fv->map->map[newpos])!=-1 &&
+ fv->sf->glyphs[i]!=NULL &&
+ fv->sf->glyphs[i]->unicodeenc>=0 && fv->sf->glyphs[i]->unicodeenc<0x10000 )
+ GInsCharSetChar(fv->sf->glyphs[i]->unicodeenc);
+# endif
+}
+#endif
+
+static void _SplineFontSetUnChanged(SplineFont *sf) {
+ int i;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ int was = sf->changed;
+ FontView *fvs;
+#endif
+ BDFFont *bdf;
+
+ sf->changed = false;
+#ifndef LUA_FF_LIB
+ SFClearAutoSave(sf);
+#endif
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ if ( sf->glyphs[i]->changed ) {
+ sf->glyphs[i]->changed = false;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ SCRefreshTitles(sf->glyphs[i]);
+#endif
+ }
+ for ( bdf=sf->bitmaps; bdf!=NULL; bdf=bdf->next )
+ for ( i=0; i<bdf->glyphcnt; ++i ) if ( bdf->glyphs[i]!=NULL )
+ bdf->glyphs[i]->changed = false;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( was && sf->fv!=NULL && sf->fv->v!=NULL )
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawRequestExpose(sf->fv->v,NULL,false);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_queue_draw(sf->fv->v);
+# endif
+ if ( was )
+ for ( fvs=sf->fv; fvs!=NULL; fvs=fvs->next )
+ FVSetTitle(fvs);
+#endif
+ for ( i=0; i<sf->subfontcnt; ++i )
+ _SplineFontSetUnChanged(sf->subfonts[i]);
+}
+
+void SplineFontSetUnChanged(SplineFont *sf) {
+ int i;
+
+ if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
+ if ( sf->mm!=NULL ) sf = sf->mm->normal;
+ _SplineFontSetUnChanged(sf);
+ if ( sf->mm!=NULL )
+ for ( i=0; i<sf->mm->instance_count; ++i )
+ _SplineFontSetUnChanged(sf->mm->instances[i]);
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static void FVFlattenAllBitmapSelections(FontView *fv) {
+ BDFFont *bdf;
+ int i;
+
+ for ( bdf = fv->sf->bitmaps; bdf!=NULL; bdf=bdf->next ) {
+ for ( i=0; i<bdf->glyphcnt; ++i )
+ if ( bdf->glyphs[i]!=NULL && bdf->glyphs[i]->selection!=NULL )
+ BCFlattenFloat(bdf->glyphs[i]);
+ }
+}
+
+static int AskChanged(SplineFont *sf) {
+ int ret;
+ char *buts[4];
+ char *filename, *fontname;
+
+ if ( sf->cidmaster!=NULL )
+ sf = sf->cidmaster;
+
+ filename = sf->filename;
+ fontname = sf->fontname;
+
+ if ( filename==NULL && sf->origname!=NULL &&
+ sf->onlybitmaps && sf->bitmaps!=NULL && sf->bitmaps->next==NULL )
+ filename = sf->origname;
+ if ( filename==NULL ) filename = "untitled.sfd";
+ filename = GFileNameTail(filename);
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ buts[0] = _("_Save");
+ buts[2] = _("_Cancel");
+#elif defined(FONTFORGE_CONFIG_GTK)
+ buts[0] = GTK_STOCK_SAVE;
+ buts[2] = GTK_STOCK_CANCEL;
+#endif
+ buts[1] = _("_Don't Save");
+ buts[3] = NULL;
+ ret = gwwv_ask( _("Font changed"),(const char **) buts,0,2,_("Font %1$.40s in file %2$.40s has been changed.\nDo you want to save it?"),fontname,filename);
+return( ret );
+}
+
+static int RevertAskChanged(char *fontname,char *filename) {
+ int ret;
+ char *buts[3];
+
+ if ( filename==NULL ) filename = "untitled.sfd";
+ filename = GFileNameTail(filename);
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ buts[0] = _("_Revert");
+ buts[1] = _("_Cancel");
+#elif defined(FONTFORGE_CONFIG_GTK)
+ buts[0] = GTK_STOCK_REVERT_TO_SAVED;
+ buts[1] = GTK_STOCK_CANCEL;
+#endif
+ buts[2] = NULL;
+ ret = gwwv_ask( _("Font changed"),(const char **) buts,0,1,_("Font %1$.40s in file %2$.40s has been changed.\nReverting the file will lose those changes.\nIs that what you want?"),fontname,filename);
+return( ret==0 );
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+int _FVMenuGenerate(FontView *fv,int family) {
+ FVFlattenAllBitmapSelections(fv);
+return( SFGenerateFont(fv->sf,family,fv->normal==NULL?fv->map:fv->normal) );
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuGenerate(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+
+ _FVMenuGenerate(fv,false);
+}
+
+static void FVMenuGenerateFamily(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+
+ _FVMenuGenerate(fv,true);
+}
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Generate(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+
+ _FVMenuGenerate(fv,false);
+}
+
+void FontViewMenu_GenerateFamily(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+
+ _FVMenuGenerate(fv,true);
+}
+# endif
+
+extern int save_to_dir;
+
+static int SaveAs_FormatChange(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
+ GGadget *fc = GWidgetGetControl(GGadgetGetWindow(g),1000);
+ char *oldname = GGadgetGetTitle8(fc);
+ int *_s2d = GGadgetGetUserData(g);
+ int s2d = GGadgetIsChecked(g);
+ char *pt, *newname = galloc(strlen(oldname)+8);
+#ifdef VMS
+ char *pt2;
+
+ strcpy(newname,oldname);
+ pt = strrchr(newname,'.');
+ pt2 = strrchr(newname,'_');
+ if ( pt==NULL )
+ pt = pt2;
+ else if ( pt2!=NULL && pt<pt2 )
+ pt = pt2;
+ if ( pt==NULL )
+ pt = newname+strlen(newname);
+ strcpy(pt,s2d ? "_sfdir" : ".sfd" );
+#else
+ strcpy(newname,oldname);
+ pt = strrchr(newname,'.');
+ if ( pt==NULL )
+ pt = newname+strlen(newname);
+ strcpy(pt,s2d ? ".sfdir" : ".sfd" );
+#endif
+ GGadgetSetTitle8(fc,newname);
+ save_to_dir = *_s2d = s2d;
+ SavePrefs();
+ }
+return( true );
+}
+
+int _FVMenuSaveAs(FontView *fv) {
+ char *temp;
+ char *ret;
+ char *filename;
+ int ok;
+ int s2d = fv->cidmaster!=NULL ? fv->cidmaster->save_to_dir :
+ fv->sf->mm!=NULL ? fv->sf->mm->normal->save_to_dir :
+ fv->sf->save_to_dir;
+ GGadgetCreateData gcd;
+ GTextInfo label;
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+ if ( fv->cidmaster!=NULL && fv->cidmaster->filename!=NULL )
+ temp=def2utf8_copy(fv->cidmaster->filename);
+ else if ( fv->sf->mm!=NULL && fv->sf->mm->normal->filename!=NULL )
+ temp=def2utf8_copy(fv->sf->mm->normal->filename);
+ else if ( fv->sf->filename!=NULL )
+ temp=def2utf8_copy(fv->sf->filename);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gsize read, written;
+
+ if ( fv->cidmaster!=NULL && fv->cidmaster->filename!=NULL )
+ temp=g_filename_to_utf8(fv->cidmaster->filename,-1,&read,&written,NULL);
+ else if ( fv->sf->mm!=NULL && fv->sf->mm->normal->filename!=NULL )
+ temp=g_filename_to_utf8(fv->sf->mm->normal->filename,-1,&read,&written,NULL);
+ else if ( fv->sf->filename!=NULL )
+ temp=g_filename_to_utf8(fv->sf->filename,-1,&read,&written,NULL);
+#endif
+ else {
+ SplineFont *sf = fv->cidmaster?fv->cidmaster:
+ fv->sf->mm!=NULL?fv->sf->mm->normal:fv->sf;
+ char *fn = sf->defbasefilename ? sf->defbasefilename : sf->fontname;
+ temp = galloc((strlen(fn)+10));
+ strcpy(temp,fn);
+ if ( sf->defbasefilename!=NULL )
+ /* Don't add a default suffix, they've already told us what name to use */;
+ else if ( fv->cidmaster!=NULL )
+ strcat(temp,"CID");
+ else if ( sf->mm==NULL )
+ ;
+ else if ( sf->mm->apple )
+ strcat(temp,"Var");
+ else
+ strcat(temp,"MM");
+#ifdef VMS
+ strcat(temp,save_to_dir ? "_sfdir" : ".sfd");
+#else
+ strcat(temp,save_to_dir ? ".sfdir" : ".sfd");
+#endif
+ s2d = save_to_dir;
+ }
+
+ memset(&gcd,0,sizeof(gcd));
+ memset(&label,0,sizeof(label));
+ gcd.gd.flags = s2d ? (gg_visible | gg_enabled | gg_cb_on) : (gg_visible | gg_enabled);
+ label.text = (unichar_t *) _("Save as _Directory");
+ label.text_is_1byte = true;
+ label.text_in_resource = true;
+ gcd.gd.label = &label;
+ gcd.gd.handle_controlevent = SaveAs_FormatChange;
+ gcd.data = &s2d;
+ gcd.creator = GCheckBoxCreate;
+
+ ret = gwwv_save_filename_with_gadget(_("Save as..."),temp,NULL,&gcd);
+ free(temp);
+ if ( ret==NULL )
+return( 0 );
+# ifdef FONTFORGE_CONFIG_GDRAW
+ filename = utf82def_copy(ret);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ filename = g_filename_from_utf8(ret,-1,&read,&written,NULL);
+#endif
+ free(ret);
+ FVFlattenAllBitmapSelections(fv);
+ fv->sf->compression = 0;
+ ok = SFDWrite(filename,fv->sf,fv->map,fv->normal,s2d);
+ if ( ok ) {
+ SplineFont *sf = fv->cidmaster?fv->cidmaster:fv->sf->mm!=NULL?fv->sf->mm->normal:fv->sf;
+ free(sf->filename);
+ sf->filename = filename;
+ sf->save_to_dir = s2d;
+ free(sf->origname);
+ sf->origname = copy(filename);
+ sf->new = false;
+ if ( sf->mm!=NULL ) {
+ int i;
+ for ( i=0; i<sf->mm->instance_count; ++i ) {
+ free(sf->mm->instances[i]->filename);
+ sf->mm->instances[i]->filename = filename;
+ free(sf->mm->instances[i]->origname);
+ sf->mm->instances[i]->origname = copy(filename);
+ sf->mm->instances[i]->new = false;
+ }
+ }
+ SplineFontSetUnChanged(sf);
+ FVSetTitle(fv);
+ } else
+ free(filename);
+return( ok );
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuSaveAs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+
+ _FVMenuSaveAs(fv);
+}
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_SaveAs(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+
+ _FVMenuSaveAs(fv);
+}
+# endif
+
+int _FVMenuSave(FontView *fv) {
+ int ret = 0;
+ SplineFont *sf = fv->cidmaster?fv->cidmaster:
+ fv->sf->mm!=NULL?fv->sf->mm->normal:
+ fv->sf;
+
+#if 0 /* This seems inconsistant with normal behavior. Removed 6 Feb '04 */
+ if ( sf->filename==NULL && sf->origname!=NULL &&
+ sf->onlybitmaps && sf->bitmaps!=NULL && sf->bitmaps->next==NULL ) {
+ /* If it's a single bitmap font then just save back to the bdf file */
+ FVFlattenAllBitmapSelections(fv);
+ ret = BDFFontDump(sf->origname,sf->bitmaps,EncodingName(sf->encoding_name),sf->bitmaps->res);
+ if ( ret )
+ SplineFontSetUnChanged(sf);
+ } else
+#endif
+ if ( sf->filename==NULL )
+ ret = _FVMenuSaveAs(fv);
+ else {
+ FVFlattenAllBitmapSelections(fv);
+ if ( !SFDWriteBak(sf,fv->map,fv->normal) )
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_post_error(_("Save Failed"),_("Save Failed"));
+#endif
+ else {
+ SplineFontSetUnChanged(sf);
+ ret = true;
+ }
+ }
+return( ret );
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuSave(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ _FVMenuSave(fv);
+}
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Save(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+
+ _FVMenuSave(fv);
+}
+# endif
+#endif
+
+void _FVCloseWindows(FontView *fv) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ int i, j;
+ BDFFont *bdf;
+ MetricsView *mv, *mnext;
+ SplineFont *sf = fv->cidmaster?fv->cidmaster:fv->sf->mm!=NULL?fv->sf->mm->normal : fv->sf;
+
+ if ( fv->nextsame==NULL && fv->sf->fv==fv && fv->sf->kcld!=NULL )
+ KCLD_End(fv->sf->kcld);
+ if ( fv->nextsame==NULL && fv->sf->fv==fv && fv->sf->vkcld!=NULL )
+ KCLD_End(fv->sf->vkcld);
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ CharView *cv, *next;
+ for ( cv = sf->glyphs[i]->views; cv!=NULL; cv = next ) {
+ next = cv->next;
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawDestroyWindow(cv->gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_destroy(cv->gw);
+# endif
+ }
+ if ( sf->glyphs[i]->charinfo )
+ CharInfoDestroy(sf->glyphs[i]->charinfo);
+ }
+ if ( sf->mm!=NULL ) {
+ MMSet *mm = sf->mm;
+ for ( j=0; j<mm->instance_count; ++j ) {
+ SplineFont *sf = mm->instances[j];
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ CharView *cv, *next;
+ for ( cv = sf->glyphs[i]->views; cv!=NULL; cv = next ) {
+ next = cv->next;
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawDestroyWindow(cv->gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_destroy(cv->gw);
+# endif
+ }
+ if ( sf->glyphs[i]->charinfo )
+ CharInfoDestroy(sf->glyphs[i]->charinfo);
+ }
+ for ( mv=sf->metrics; mv!=NULL; mv = mnext ) {
+ mnext = mv->next;
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawDestroyWindow(mv->gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_destroy(mv->gw);
+# endif
+ }
+ }
+ } else if ( sf->subfontcnt!=0 ) {
+ for ( j=0; j<sf->subfontcnt; ++j ) {
+ for ( i=0; i<sf->subfonts[j]->glyphcnt; ++i ) if ( sf->subfonts[j]->glyphs[i]!=NULL ) {
+ CharView *cv, *next;
+ for ( cv = sf->subfonts[j]->glyphs[i]->views; cv!=NULL; cv = next ) {
+ next = cv->next;
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawDestroyWindow(cv->gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_destroy(cv->gw);
+# endif
+ if ( sf->subfonts[j]->glyphs[i]->charinfo )
+ CharInfoDestroy(sf->subfonts[j]->glyphs[i]->charinfo);
+ }
+ }
+ for ( mv=sf->subfonts[j]->metrics; mv!=NULL; mv = mnext ) {
+ mnext = mv->next;
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawDestroyWindow(mv->gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_destroy(mv->gw);
+# endif
+ }
+ }
+ } else {
+ for ( mv=sf->metrics; mv!=NULL; mv = mnext ) {
+ mnext = mv->next;
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawDestroyWindow(mv->gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_destroy(mv->gw);
+# endif
+ }
+ }
+ for ( bdf = sf->bitmaps; bdf!=NULL; bdf=bdf->next ) {
+ for ( i=0; i<bdf->glyphcnt; ++i ) if ( bdf->glyphs[i]!=NULL ) {
+ BitmapView *bv, *next;
+ for ( bv = bdf->glyphs[i]->views; bv!=NULL; bv = next ) {
+ next = bv->next;
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawDestroyWindow(bv->gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_destroy(bv->gw);
+# endif
+ }
+ }
+ }
+ if ( fv->sf->fontinfo!=NULL )
+ FontInfoDestroy(fv->sf);
+ SVDetachFV(fv);
+#endif
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static int SFAnyChanged(SplineFont *sf) {
+ if ( sf->mm!=NULL ) {
+ MMSet *mm = sf->mm;
+ int i;
+ if ( mm->changed )
+return( true );
+ for ( i=0; i<mm->instance_count; ++i )
+ if ( sf->mm->instances[i]->changed )
+return( true );
+ /* Changes to the blended font aren't real (for adobe fonts) */
+ if ( mm->apple && mm->normal->changed )
+return( true );
+
+return( false );
+ } else
+return( sf->changed );
+}
+
+static int _FVMenuClose(FontView *fv) {
+ int i;
+ SplineFont *sf = fv->cidmaster?fv->cidmaster:fv->sf;
+
+ if ( !SFCloseAllInstrs(fv->sf) )
+return( false );
+
+ if ( fv->nextsame!=NULL || fv->sf->fv!=fv ) {
+ /* There's another view, can close this one with no problems */
+ } else if ( SFAnyChanged(sf) ) {
+ i = AskChanged(fv->sf);
+ if ( i==2 ) /* Cancel */
+return( false );
+ if ( i==0 && !_FVMenuSave(fv)) /* Save */
+return(false);
+ else
+ SFClearAutoSave(sf); /* if they didn't save it, remove change record */
+ }
+ _FVCloseWindows(fv);
+ if ( sf->filename!=NULL )
+ RecentFilesRemember(sf->filename);
+#ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawDestroyWindow(fv->gw);
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_destroy(fv->gw);
+#endif
+return( true );
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+void MenuNew(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontNew();
+}
+
+static void FVMenuClose(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+
+ DelayEvent((void (*)(void *)) _FVMenuClose, fv);
+}
+# elif defined(FONTFORGE_CONFIG_GTK)
+void Menu_New(GtkMenuItem *menuitem, gpointer user_data) {
+ FontNew();
+}
+
+void FontViewMenu_Close(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+
+ _FVMenuClose(fv);
+}
+
+gboolean FontView_RequestClose(GtkWidget *widget, GdkEvent *event,
+ gpointer user_data) {
+ FontView *fv = (FontView *) g_object_get_data(G_OBJECT(widget),"data");
+
+ _FVMenuClose(fv);
+}
+# endif
+
+static void FVReattachCVs(SplineFont *old,SplineFont *new) {
+ int i, j, pos;
+ CharView *cv, *cvnext;
+ SplineFont *sub;
+
+ for ( i=0; i<old->glyphcnt; ++i ) {
+ if ( old->glyphs[i]!=NULL && old->glyphs[i]->views!=NULL ) {
+ if ( new->subfontcnt==0 ) {
+ pos = SFFindExistingSlot(new,old->glyphs[i]->unicodeenc,old->glyphs[i]->name);
+ sub = new;
+ } else {
+ pos = -1;
+ for ( j=0; j<new->subfontcnt && pos==-1 ; ++j ) {
+ sub = new->subfonts[j];
+ pos = SFFindExistingSlot(sub,old->glyphs[i]->unicodeenc,old->glyphs[i]->name);
+ }
+ }
+ if ( pos==-1 ) {
+ for ( cv=old->glyphs[i]->views; cv!=NULL; cv = cvnext ) {
+ cvnext = cv->next;
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawDestroyWindow(cv->gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_destroy(cv->gw);
+# endif
+ }
+ } else {
+ for ( cv=old->glyphs[i]->views; cv!=NULL; cv = cvnext ) {
+ cvnext = cv->next;
+ CVChangeSC(cv,sub->glyphs[pos]);
+ cv->layerheads[dm_grid] = &new->grid;
+ }
+ }
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawProcessPendingEvents(NULL); /* Don't want to many destroy_notify events clogging up the queue */
+# endif
+ }
+ }
+}
+#endif
+
+static char *Decompress(char *name, int compression) {
+ char *dir = getenv("TMPDIR");
+ char buf[1500];
+ char *tmpfile;
+
+ if ( dir==NULL ) dir = P_tmpdir;
+ tmpfile = galloc(strlen(dir)+strlen(GFileNameTail(name))+2);
+ strcpy(tmpfile,dir);
+ strcat(tmpfile,"/");
+ strcat(tmpfile,GFileNameTail(name));
+ *strrchr(tmpfile,'.') = '\0';
+#if defined( _NO_SNPRINTF ) || defined( __VMS )
+ sprintf( buf, "%s < %s > %s", compressors[compression].decomp, name, tmpfile );
+#else
+ snprintf( buf, sizeof(buf), "%s < %s > %s", compressors[compression].decomp, name, tmpfile );
+#endif
+ if ( system(buf)==0 )
+return( tmpfile );
+ free(tmpfile);
+return( NULL );
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+
+static void _FVRevert(FontView *fv,int tobackup) {
+ SplineFont *temp, *old = fv->cidmaster?fv->cidmaster:fv->sf;
+ BDFFont *tbdf, *fbdf;
+ BDFChar *bc;
+ BitmapView *bv, *bvnext;
+ MetricsView *mv, *mvnext;
+ int i;
+ FontView *fvs;
+
+ if ( old->origname==NULL )
+return;
+ if ( old->changed )
+ if ( !RevertAskChanged(old->fontname,old->origname))
+return;
+ if ( tobackup ) {
+ /* we can only revert to backup if it's an sfd file. So we use filename*/
+ /* here. In the normal case we revert to whatever file we read it from*/
+ /* (sfd or not) so we use origname */
+ char *buf = galloc(strlen(old->filename)+20);
+ strcpy(buf,old->filename);
+ if ( old->compression!=0 ) {
+ char *tmpfile;
+ strcat(buf,compressors[old->compression-1].ext);
+ strcat(buf,"~");
+ tmpfile = Decompress(buf,old->compression-1);
+ if ( tmpfile==NULL )
+ temp = NULL;
+ else {
+ temp = ReadSplineFont(tmpfile,0);
+ unlink(tmpfile);
+ free(tmpfile);
+ }
+ } else {
+ strcat(buf,"~");
+ temp = ReadSplineFont(buf,0);
+ }
+ free(buf);
+ } else {
+ if ( old->compression!=0 ) {
+ char *tmpfile;
+ char *buf = galloc(strlen(old->filename)+20);
+ strcpy(buf,old->filename);
+ strcat(buf,compressors[old->compression-1].ext);
+ tmpfile = Decompress(buf,old->compression-1);
+ if ( tmpfile==NULL )
+ temp = NULL;
+ else {
+ temp = ReadSplineFont(tmpfile,0);
+ unlink(tmpfile);
+ free(tmpfile);
+ }
+ } else
+ temp = ReadSplineFont(old->origname,0);
+ }
+ if ( temp==NULL ) {
+return;
+ }
+ if ( temp->filename!=NULL ) {
+ free(temp->filename);
+ temp->filename = copy(old->filename);
+ }
+ if ( temp->origname!=NULL ) {
+ free(temp->origname);
+ temp->origname = copy(old->origname);
+ }
+ temp->compression = old->compression;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FVReattachCVs(old,temp);
+ for ( i=0; i<old->subfontcnt; ++i )
+ FVReattachCVs(old->subfonts[i],temp);
+ for ( fbdf=old->bitmaps; fbdf!=NULL; fbdf=fbdf->next ) {
+ for ( tbdf=temp->bitmaps; tbdf!=NULL; tbdf=tbdf->next )
+ if ( tbdf->pixelsize==fbdf->pixelsize )
+ break;
+ for ( i=0; i<fv->sf->glyphcnt; ++i ) {
+ if ( i<fbdf->glyphcnt && fbdf->glyphs[i]!=NULL && fbdf->glyphs[i]->views!=NULL ) {
+ int pos = SFFindExistingSlot(temp,fv->sf->glyphs[i]->unicodeenc,fv->sf->glyphs[i]->name);
+ bc = pos==-1 || tbdf==NULL?NULL:tbdf->glyphs[pos];
+ if ( bc==NULL ) {
+ for ( bv=fbdf->glyphs[i]->views; bv!=NULL; bv = bvnext ) {
+ bvnext = bv->next;
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawDestroyWindow(bv->gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_destroy(bv->gw);
+# endif
+ }
+ } else {
+ for ( bv=fbdf->glyphs[i]->views; bv!=NULL; bv = bvnext ) {
+ bvnext = bv->next;
+ BVChangeBC(bv,bc,true);
+ }
+ }
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawProcessPendingEvents(NULL); /* Don't want to many destroy_notify events clogging up the queue */
+# endif
+ }
+ }
+ }
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawSync(NULL);
+ GDrawProcessPendingEvents(NULL);
+# endif
+ if ( fv->sf->fontinfo )
+ FontInfoDestroy(fv->sf);
+ for ( fvs=fv->sf->fv; fvs!=NULL; fvs=fvs->nextsame ) {
+ for ( mv=fvs->sf->metrics; mv!=NULL; mv = mvnext ) {
+ /* Don't bother trying to fix up metrics views, just not worth it */
+ mvnext = mv->next;
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawDestroyWindow(mv->gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_destroy(mv->gw);
+# endif
+ }
+ }
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawSync(NULL);
+ GDrawProcessPendingEvents(NULL);
+# endif
+#endif
+ if ( temp->map->enccount>fv->map->enccount ) {
+ fv->selected = grealloc(fv->selected,temp->map->enccount);
+ memset(fv->selected+fv->map->enccount,0,temp->map->enccount-fv->map->enccount);
+ }
+ EncMapFree(fv->map);
+ fv->map = temp->map;
+ SFClearAutoSave(old);
+ temp->fv = fv->sf->fv;
+ for ( fvs=fv->sf->fv; fvs!=NULL; fvs=fvs->nextsame )
+ fvs->sf = temp;
+ FontViewReformatAll(fv->sf);
+ SplineFontFree(old);
+}
+
+void FVRevert(FontView *fv) {
+ _FVRevert(fv,false);
+}
+
+void FVRevertBackup(FontView *fv) {
+ _FVRevert(fv,true);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuRevert(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_RevertFile(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVRevert(fv);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuRevertBackup(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_RevertBackup(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVRevertBackup(fv);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuRevertGlyph(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_RevertGlyph(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int i, gid;
+ int nc_state = -1;
+ SplineFont *sf = fv->sf;
+ SplineChar *sc, *tsc;
+ SplineChar temp;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ Undoes **undoes;
+ int layer, lc;
+#endif
+ EncMap *map = fv->map;
+ CharView *cvs;
+
+ if ( fv->sf->sfd_version<2 )
+ gwwv_post_error(_("Old sfd file"),_("This font comes from an old format sfd file. Not all aspects of it can be reverted successfully."));
+
+ for ( i=0; i<map->enccount; ++i ) if ( fv->selected[i] && (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL ) {
+ tsc = sf->glyphs[gid];
+ if ( tsc->namechanged ) {
+ if ( nc_state==-1 ) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_post_error(_("Glyph Name Changed"),_("The name of glyph %.40s has changed. This is what I use to find the glyph in the file, so I cannot revert this glyph.\n(You will not be warned for subsequent glyphs.)"),tsc->name);
+#endif
+ nc_state = 0;
+ }
+ } else {
+ sc = SFDReadOneChar(sf,tsc->name);
+ if ( sc==NULL ) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_post_error(_("Can't Find Glyph"),_("The glyph, %.80s, can't be found in the sfd file"),tsc->name);
+#endif
+ tsc->namechanged = true;
+ } else {
+ SCPreserveState(tsc,true);
+ SCPreserveBackground(tsc);
+ temp = *tsc;
+ tsc->dependents = NULL;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ lc = tsc->layer_cnt;
+ undoes = galloc(lc*sizeof(Undoes *));
+ for ( layer=0; layer<lc; ++layer ) {
+ undoes[layer] = tsc->layers[layer].undoes;
+ tsc->layers[layer].undoes = NULL;
+ }
+#else
+ tsc->layers[ly_back].undoes = tsc->layers[ly_fore].undoes = NULL;
+#endif
+ SplineCharFreeContents(tsc);
+ *tsc = *sc;
+ chunkfree(sc,sizeof(SplineChar));
+ tsc->parent = sf;
+ tsc->dependents = temp.dependents;
+ tsc->views = temp.views;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ for ( layer = 0; layer<lc && layer<tsc->layer_cnt; ++layer )
+ tsc->layers[layer].undoes = undoes[layer];
+ for ( ; layer<lc; ++layer )
+ UndoesFree(undoes[layer]);
+ free(undoes);
+#else
+ tsc->layers[ly_fore].undoes = temp.layers[ly_fore].undoes;
+ tsc->layers[ly_back].undoes = temp.layers[ly_back].undoes;
+#endif
+ /* tsc->changed = temp.changed; */
+ /* tsc->orig_pos = temp.orig_pos; */
+ for ( cvs=tsc->views; cvs!=NULL; cvs=cvs->next ) {
+ cvs->layerheads[dm_back] = &tsc->layers[ly_back];
+ cvs->layerheads[dm_fore] = &tsc->layers[ly_fore];
+ }
+ RevertedGlyphReferenceFixup(tsc, sf);
+ _SCCharChangedUpdate(tsc,false);
+ }
+ }
+ }
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+void MenuPrefs(GWindow base,struct gmenuitem *mi,GEvent *e) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void Menu_Preferences(GtkMenuItem *menuitem, gpointer user_data) {
+# endif
+ DoPrefs();
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+void MenuSaveAll(GWindow base,struct gmenuitem *mi,GEvent *e) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void Menu_SaveAll(GtkMenuItem *menuitem, gpointer user_data) {
+# endif
+ FontView *fv;
+
+ for ( fv = fv_list; fv!=NULL; fv = fv->next ) {
+ if ( SFAnyChanged(fv->sf) && !_FVMenuSave(fv))
+return;
+ }
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static void _MenuExit(void *junk) {
+ FontView *fv, *next;
+
+ for ( fv = fv_list; fv!=NULL; fv = next ) {
+ next = fv->next;
+ if ( !_FVMenuClose(fv))
+return;
+#ifdef FONTFORGE_CONFIG_GDRAW
+ if ( fv->nextsame!=NULL || fv->sf->fv!=fv ) {
+ GDrawSync(NULL);
+ GDrawProcessPendingEvents(NULL);
+ }
+#endif
+ }
+ exit(0);
+}
+
+# ifdef FONTFORGE_CONFIG_GTK
+static void Menu_Exit(GtkMenuItem *menuitem, gpointer user_data) {
+ _MenuExit(NULL);
+}
+
+char *GetPostscriptFontName(char *dir, int mult) {
+ /* Some people use pf3 as an extension for postscript type3 fonts */
+ /* Any of these extensions */
+ static char wild[] = "*.{"
+ "pfa,"
+ "pfb,"
+ "pt3,"
+ "t42,"
+ "sfd,"
+ "ttf,"
+ "bdf,"
+ "otf,"
+ "otb,"
+ "cff,"
+ "cef,"
+ "gai,"
+#ifndef _NO_LIBXML
+ "svg,"
+#endif
+ "pf3,"
+ "ttc,"
+ "gsf,"
+ "cid,"
+ "bin,"
+ "hqx,"
+ "dfont,"
+ "mf,"
+ "ik,"
+ "fon,"
+ "fnt,"
+ "pdb"
+ "}"
+/* With any of these methods of compression */
+ "{.gz,.Z,.bz2,}";
+ gsize read, written;
+ char *u_dir, *ret, *temp;
+
+ u_dir = g_filename_to_utf8(dir,-1,&read,&written,NULL);
+ ret = FVOpenFont(_("Open Font"), u_dir,wild,mult);
+ temp = g_filename_from_utf8(ret,-1,&read,&written,NULL);
+ free(u_dir); free(ret);
+
+return( temp );
+}
+
+void MergeKernInfo(SplineFont *sf,EncMap *map) {
+#ifndef __Mac
+ static char wild[] = "*.{afm,tfm,ofm,pfm,bin,hqx,dfont,fea}";
+ static char wild2[] = "*.{afm,amfm,tfm,ofm,pfm,bin,hqx,dfont,fea}";
+#else
+ static char wild[] = "*"; /* Mac resource files generally don't have extensions */
+ static char wild2[] = "*";
+#endif
+ char *ret = gwwv_open_filename(_("Merge Feature Info"),NULL,
+ sf->mm!=NULL?wild2:wild,NULL);
+
+ if ( ret==NULL ) /* Cancelled */
+return;
+
+ if ( !LoadKerningDataFromMetricsFile(sf,ret,map))
+ gwwv_post_error( _("Failed to load kern data from %s"), ret);
+ free(ret);
+}
+# elif defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuExit(GWindow base,struct gmenuitem *mi,GEvent *e) {
+ _MenuExit(NULL);
+}
+
+void MenuExit(GWindow base,struct gmenuitem *mi,GEvent *e) {
+ if ( e==NULL ) /* Not from the menu directly, but a shortcut */
+ _MenuExit(NULL);
+ else
+ DelayEvent(_MenuExit,NULL);
+}
+
+char *GetPostscriptFontName(char *dir, int mult) {
+ /* Some people use pf3 as an extension for postscript type3 fonts */
+ unichar_t *ret;
+ char *u_dir;
+ char *temp;
+
+ u_dir = def2utf8_copy(dir);
+ ret = FVOpenFont(_("Open Font"), u_dir,mult);
+ temp = u2def_copy(ret);
+
+ free(ret);
+return( temp );
+}
+
+void MergeKernInfo(SplineFont *sf,EncMap *map) {
+#ifndef __Mac
+ static char wild[] = "*.{afm,tfm,ofm,pfm,bin,hqx,dfont,fea}";
+ static char wild2[] = "*.{afm,amfm,tfm,ofm,pfm,bin,hqx,dfont,fea}";
+#else
+ static char wild[] = "*"; /* Mac resource files generally don't have extensions */
+ static char wild2[] = "*";
+#endif
+#if defined(FONTFORGE_CONFIG_GTK)
+ gsize read, written;
+#endif
+ char *ret = gwwv_open_filename(_("Merge Feature Info"),NULL,
+ sf->mm!=NULL?wild2:wild,NULL);
+ char *temp;
+
+ if ( ret==NULL )
+return; /* Cancelled */
+# ifdef FONTFORGE_CONFIG_GDRAW
+ temp = utf82def_copy(ret);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ temp = g_utf8_to_filename(ret,-1,&read,&written,NULL);
+#endif
+
+ if ( !LoadKerningDataFromMetricsFile(sf,temp,map))
+ gwwv_post_error(_("Load of Kerning Metrics Failed"),_("Failed to load kern data from %s"), temp);
+ free(ret); free(temp);
+}
+# endif
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuMergeKern(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_MergeKern(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ MergeKernInfo(fv->sf,fv->map);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+void MenuOpen(GWindow base,struct gmenuitem *mi,GEvent *e) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void Menu_Open(GtkMenuItem *menuitem, gpointer user_data) {
+# endif
+ char *temp;
+ char *eod, *fpt, *file, *full;
+ FontView *test; int fvcnt, fvtest;
+
+ for ( fvcnt=0, test=fv_list; test!=NULL; ++fvcnt, test=test->next );
+ do {
+ temp = GetPostscriptFontName(NULL,true);
+ if ( temp==NULL )
+return;
+ eod = strrchr(temp,'/');
+ *eod = '\0';
+ file = eod+1;
+ do {
+ fpt = strstr(file,"; ");
+ if ( fpt!=NULL ) *fpt = '\0';
+ full = galloc(strlen(temp)+1+strlen(file)+1);
+ strcpy(full,temp); strcat(full,"/"); strcat(full,file);
+ ViewPostscriptFont(full);
+ file = fpt+2;
+ free(full);
+ } while ( fpt!=NULL );
+ free(temp);
+ for ( fvtest=0, test=fv_list; test!=NULL; ++fvtest, test=test->next );
+ } while ( fvtest==fvcnt ); /* did the load fail for some reason? try again */
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuContextualHelp(GWindow base,struct gmenuitem *mi,GEvent *e) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ContextualHelp(GtkMenuItem *menuitem, gpointer user_data) {
+# endif
+ help("fontview.html");
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+void MenuHelp(GWindow base,struct gmenuitem *mi,GEvent *e) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void MenuHelp_Help(GtkMenuItem *menuitem, gpointer user_data) {
+# endif
+ help("overview.html");
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+void MenuIndex(GWindow base,struct gmenuitem *mi,GEvent *e) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void MenuHelp_Index(GtkMenuItem *menuitem, gpointer user_data) {
+# endif
+ help("IndexFS.html");
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+void MenuLicense(GWindow base,struct gmenuitem *mi,GEvent *e) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void MenuHelp_License(GtkMenuItem *menuitem, gpointer user_data) {
+# endif
+ help("license.html");
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+void MenuAbout(GWindow base,struct gmenuitem *mi,GEvent *e) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void MenuHelp_About(GtkMenuItem *menuitem, gpointer user_data) {
+# endif
+ ShowAboutScreen();
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuImport(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Import(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int empty = fv->sf->onlybitmaps && fv->sf->bitmaps==NULL;
+ BDFFont *bdf;
+ FVImport(fv);
+ if ( empty && fv->sf->bitmaps!=NULL ) {
+ for ( bdf= fv->sf->bitmaps; bdf->next!=NULL; bdf = bdf->next );
+ FVChangeDisplayBitmap(fv,bdf);
+ }
+}
+
+static int FVSelCount(FontView *fv) {
+ int i, cnt=0;
+
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] ) ++cnt;
+ if ( cnt>10 ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buts[3];
+ buts[0] = _("_OK");
+ buts[1] = _("_Cancel");
+ buts[2] = NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buts[] = { GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL };
+#endif
+ if ( gwwv_ask(_("Many Windows"),(const char **) buts,0,1,_("This involves opening more than 10 windows.\nIs that really what you want?"))==1 )
+return( false );
+ }
+return( true );
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuOpenOutline(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_OpenOutline(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int i;
+ SplineChar *sc;
+
+ if ( !FVSelCount(fv))
+return;
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] ) {
+ sc = FVMakeChar(fv,i);
+ CharViewCreate(sc,fv,i);
+ }
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuOpenBitmap(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_OpenBitmap(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int i;
+ SplineChar *sc;
+
+ if ( fv->cidmaster==NULL ? (fv->sf->bitmaps==NULL) : (fv->cidmaster->bitmaps==NULL) )
+return;
+ if ( !FVSelCount(fv))
+return;
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] ) {
+ sc = FVMakeChar(fv,i);
+ if ( sc!=NULL )
+ BitmapViewCreatePick(i,fv);
+ }
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+void _MenuWarnings(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void WindowMenu_Warnings(GtkMenuItem *menuitem, gpointer user_data) {
+# endif
+ ShowErrorWindow();
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuOpenMetrics(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_OpenMetrics(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ MetricsViewCreate(fv,NULL,fv->filled==fv->show?NULL:fv->show);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuPrint(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Print(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ PrintDlg(fv,NULL,NULL);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuDisplay(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Display(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ DisplayDlg(fv->sf);
+}
+
+#if !defined(_NO_FFSCRIPT) || !defined(_NO_PYTHON)
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuExecute(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ExecScript(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ ScriptDlg(fv);
+}
+#endif
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuFontInfo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_FontInfo(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FontMenuFontInfo(fv);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuFindProblems(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_FindProbs(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FindProblems(fv,NULL,NULL);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuMetaFont(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Metafont(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+#ifdef GWW_TEST
+ extern int ChangeWeight(SplineChar *sc,double factor,double add);
+ int i, gid;
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] && (gid=fv->map->map[i])!=-1 && fv->sf->glyphs[gid]!=NULL )
+ ChangeWeight(fv->sf->glyphs[gid],2.0,25);
+#else
+ MetaFont(fv,NULL,NULL);
+#endif
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+#define MID_24 2001
+#define MID_36 2002
+#define MID_48 2004
+#define MID_72 2014
+#define MID_96 2015
+#define MID_AntiAlias 2005
+#define MID_Next 2006
+#define MID_Prev 2007
+#define MID_NextDef 2012
+#define MID_PrevDef 2013
+#define MID_ShowHMetrics 2016
+#define MID_ShowVMetrics 2017
+#define MID_Ligatures 2020
+#define MID_KernPairs 2021
+#define MID_AnchorPairs 2022
+#define MID_FitToEm 2023
+#define MID_DisplaySubs 2024
+#define MID_32x8 2025
+#define MID_16x4 2026
+#define MID_8x2 2027
+#define MID_BitmapMag 2028
+#define MID_CharInfo 2201
+#define MID_FindProblems 2216
+#define MID_MetaFont 2217
+#define MID_Transform 2202
+#define MID_Stroke 2203
+#define MID_RmOverlap 2204
+#define MID_Simplify 2205
+#define MID_Correct 2206
+#define MID_BuildAccent 2208
+#define MID_AvailBitmaps 2210
+#define MID_RegenBitmaps 2211
+#define MID_Autotrace 2212
+#define MID_Round 2213
+#define MID_MergeFonts 2214
+#define MID_InterpolateFonts 2215
+#define MID_ShowDependentRefs 2222
+#define MID_AddExtrema 2224
+#define MID_CleanupGlyph 2225
+#define MID_TilePath 2226
+#define MID_BuildComposite 2227
+#define MID_NLTransform 2228
+#define MID_Intersection 2229
+#define MID_FindInter 2230
+#define MID_Effects 2231
+#define MID_SimplifyMore 2233
+#define MID_ShowDependentSubs 2234
+#define MID_DefaultATT 2235
+#define MID_POV 2236
+#define MID_BuildDuplicates 2237
+#define MID_StrikeInfo 2238
+#define MID_FontCompare 2239
+#define MID_CanonicalStart 2242
+#define MID_CanonicalContours 2243
+#define MID_RemoveBitmaps 2244
+#define MID_Center 2600
+#define MID_Thirds 2601
+#define MID_SetWidth 2602
+#define MID_SetLBearing 2603
+#define MID_SetRBearing 2604
+#define MID_SetVWidth 2605
+#define MID_RmHKern 2606
+#define MID_RmVKern 2607
+#define MID_VKernByClass 2608
+#define MID_VKernFromH 2609
+#define MID_AutoHint 2501
+#define MID_ClearHints 2502
+#define MID_ClearWidthMD 2503
+#define MID_AutoInstr 2504
+#define MID_EditInstructions 2505
+#define MID_Editfpgm 2506
+#define MID_Editprep 2507
+#define MID_ClearInstrs 2508
+#define MID_HStemHist 2509
+#define MID_VStemHist 2510
+#define MID_BlueValuesHist 2511
+#define MID_Editcvt 2512
+#define MID_HintSubsPt 2513
+#define MID_AutoCounter 2514
+#define MID_DontAutoHint 2515
+#define MID_PrivateToCvt 2516
+#define MID_Editmaxp 2517
+#define MID_OpenBitmap 2700
+#define MID_OpenOutline 2701
+#define MID_Revert 2702
+#define MID_Recent 2703
+#define MID_Print 2704
+#define MID_ScriptMenu 2705
+#define MID_Display 2706
+#define MID_RevertGlyph 2707
+#define MID_RevertToBackup 2708
+#define MID_Cut 2101
+#define MID_Copy 2102
+#define MID_Paste 2103
+#define MID_Clear 2104
+#define MID_SelAll 2106
+#define MID_CopyRef 2107
+#define MID_UnlinkRef 2108
+#define MID_Undo 2109
+#define MID_Redo 2110
+#define MID_CopyWidth 2111
+#define MID_AllFonts 2122
+#define MID_DisplayedFont 2123
+#define MID_CharName 2124
+#define MID_RemoveUndoes 2114
+#define MID_CopyFgToBg 2115
+#define MID_ClearBackground 2116
+#define MID_CopyLBearing 2125
+#define MID_CopyRBearing 2126
+#define MID_CopyVWidth 2127
+#define MID_Join 2128
+#define MID_PasteInto 2129
+#define MID_SameGlyphAs 2130
+#define MID_RplRef 2131
+#define MID_PasteAfter 2132
+#define MID_TTFInstr 2134
+#define MID_CopyLookupData 2135
+#define MID_Convert2CID 2800
+#define MID_Flatten 2801
+#define MID_InsertFont 2802
+#define MID_InsertBlank 2803
+#define MID_CIDFontInfo 2804
+#define MID_RemoveFromCID 2805
+#define MID_ConvertByCMap 2806
+#define MID_FlattenByCMap 2807
+#define MID_ChangeSupplement 2808
+#define MID_Reencode 2830
+#define MID_ForceReencode 2831
+#define MID_AddUnencoded 2832
+#define MID_RemoveUnused 2833
+#define MID_DetachGlyphs 2834
+#define MID_DetachAndRemoveGlyphs 2835
+#define MID_LoadEncoding 2836
+#define MID_MakeFromFont 2837
+#define MID_RemoveEncoding 2838
+#define MID_DisplayByGroups 2839
+#define MID_Compact 2840
+#define MID_SaveNamelist 2841
+#define MID_RenameGlyphs 2842
+#define MID_NameGlyphs 2843
+#define MID_CreateMM 2900
+#define MID_MMInfo 2901
+#define MID_MMValid 2902
+#define MID_ChangeMMBlend 2903
+#define MID_BlendToNew 2904
+#define MID_ModifyComposition 20902
+#define MID_BuildSyllables 20903
+
+#define MID_Warnings 3000
+# endif
+#endif
+
+#ifndef LUA_FF_LIB
+/* returns -1 if nothing selected, if exactly one char return it, -2 if more than one */
+static int FVAnyCharSelected(FontView *fv) {
+ int i, val=-1;
+
+ for ( i=0; i<fv->map->enccount; ++i ) {
+ if ( fv->selected[i]) {
+ if ( val==-1 )
+ val = i;
+ else
+return( -2 );
+ }
+ }
+return( val );
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static int FVAllSelected(FontView *fv) {
+ int i, any = false;
+ /* Is everything real selected? */
+
+ for ( i=0; i<fv->sf->glyphcnt; ++i ) if ( SCWorthOutputting(fv->sf->glyphs[i])) {
+ if ( !fv->selected[fv->map->backmap[i]] )
+return( false );
+ any = true;
+ }
+return( any );
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuCopyFrom(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ /*FontView *fv = (FontView *) GDrawGetUserData(gw);*/
+
+ if ( mi->mid==MID_CharName )
+ copymetadata = !copymetadata;
+ else if ( mi->mid==MID_TTFInstr )
+ copyttfinstr = !copyttfinstr;
+ else
+ onlycopydisplayed = (mi->mid==MID_DisplayedFont);
+ SavePrefs();
+}
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_CopyFromAll(GtkMenuItem *menuitem, gpointer user_data) {
+
+ onlycopydisplayed = false;
+ SavePrefs();
+}
+
+void FontViewMenu_CopyFromDisplayed(GtkMenuItem *menuitem, gpointer user_data) {
+
+ onlycopydisplayed = true;
+ SavePrefs();
+}
+
+void FontViewMenu_CopyFromMetadata(GtkMenuItem *menuitem, gpointer user_data) {
+
+ copymetadata = !copymetadata;
+ SavePrefs();
+}
+# endif
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuCopy(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Copy(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ if ( FVAnyCharSelected(fv)==-1 )
+return;
+ FVCopy(fv,ct_fullcopy);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuCopyLookupData(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_CopyLookupData(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ if ( FVAnyCharSelected(fv)==-1 )
+return;
+ FVCopy(fv,ct_lookups);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuCopyRef(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_CopyRef(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ if ( FVAnyCharSelected(fv)==-1 )
+return;
+ FVCopy(fv,ct_reference);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuCopyWidth(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+
+ if ( FVAnyCharSelected(fv)==-1 )
+return;
+ if ( mi->mid==MID_CopyVWidth && !fv->sf->hasvmetrics )
+return;
+ FVCopyWidth(fv,mi->mid==MID_CopyWidth?ut_width:
+ mi->mid==MID_CopyVWidth?ut_vwidth:
+ mi->mid==MID_CopyLBearing?ut_lbearing:
+ ut_rbearing);
+}
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_CopyWidth(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ if ( FVAnyCharSelected(fv)==-1 )
+return;
+ FVCopyWidth(fv,ut_width);
+}
+
+void FontViewMenu_CopyVWidth(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ if ( FVAnyCharSelected(fv)==-1 )
+return;
+ if ( !fv->sf->hasvmetrics )
+return;
+ FVCopyWidth(fv,ut_vwidth);
+}
+
+void FontViewMenu_CopyLBearing(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ if ( FVAnyCharSelected(fv)==-1 )
+return;
+ FVCopyWidth(fv,ut_lbearing);
+}
+
+void FontViewMenu_CopyRBearing(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ if ( FVAnyCharSelected(fv)==-1 )
+return;
+ FVCopyWidth(fv,ut_rbearing);
+}
+# endif
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuPaste(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Paste(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ if ( FVAnyCharSelected(fv)==-1 )
+return;
+ PasteIntoFV(fv,false,NULL);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuPasteInto(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_PasteInto(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ if ( FVAnyCharSelected(fv)==-1 )
+return;
+ PasteIntoFV(fv,true,NULL);
+}
+
+#ifdef FONTFORGE_CONFIG_PASTEAFTER
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuPasteAfter(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_PasteAfter(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int pos = FVAnyCharSelected(fv);
+ if ( pos<0 )
+return;
+ PasteIntoFV(fv,2,NULL);
+}
+#elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_PasteAfter(GtkMenuItem *menuitem, gpointer user_data) {
+}
+#endif
+#endif
+
+void AltUniRemove(SplineChar *sc,int uni) {
+ struct altuni *altuni, *prev;
+
+ if ( sc==NULL || uni==-1 )
+return;
+
+ if ( sc->unicodeenc==uni && sc->altuni!=NULL ) {
+ sc->unicodeenc = sc->altuni->unienc;
+ sc->altuni->unienc = uni;
+ }
+
+ if ( sc->unicodeenc==uni )
+return;
+ for ( prev=NULL, altuni=sc->altuni; altuni!=NULL && altuni->unienc!=uni;
+ prev = altuni, altuni = altuni->next );
+ if ( altuni ) {
+ if ( prev==NULL )
+ sc->altuni = altuni->next;
+ else
+ prev->next = altuni->next;
+ altuni->next = NULL;
+ AltUniFree(altuni);
+ }
+}
+
+void AltUniAdd(SplineChar *sc,int uni) {
+ struct altuni *altuni;
+
+ if ( sc!=NULL && uni!=-1 && uni!=sc->unicodeenc ) {
+ for ( altuni = sc->altuni; altuni!=NULL && altuni->unienc!=uni; altuni=altuni->next );
+ if ( altuni==NULL ) {
+ altuni = chunkalloc(sizeof(struct altuni));
+ altuni->next = sc->altuni;
+ sc->altuni = altuni;
+ altuni->unienc = uni;
+ }
+ }
+}
+
+static void LinkEncToGid(FontView *fv,int enc, int gid) {
+ EncMap *map = fv->map;
+ int old_gid;
+ int flags = -1;
+ int j;
+
+ if ( map->map[enc]!=-1 && map->map[enc]!=gid ) {
+ SplineFont *sf = fv->sf;
+ old_gid = map->map[enc];
+ for ( j=0; j<map->enccount; ++j )
+ if ( j!=enc && map->map[j]==old_gid )
+ break;
+ /* If the glyph is used elsewhere in the encoding then reusing this */
+ /* slot causes no problems */
+ if ( j==map->enccount ) {
+ /* However if this is the only use and the glyph is interesting */
+ /* then add it to the unencoded area. If it is uninteresting we*/
+ /* can just get rid of it */
+ if ( SCWorthOutputting(sf->glyphs[old_gid]) )
+ SFAddEncodingSlot(sf,old_gid);
+ else
+ SFRemoveGlyph(sf,sf->glyphs[old_gid],&flags);
+ }
+ }
+ map->map[enc] = gid;
+ if ( map->backmap[gid]==-1 )
+ map->backmap[gid] = enc;
+ if ( map->enc!=&custom ) {
+ int uni = UniFromEnc(enc,map->enc);
+ AltUniAdd(fv->sf->glyphs[gid],uni);
+ }
+}
+
+static void FVSameGlyphAs(FontView *fv) {
+ SplineFont *sf = fv->sf;
+ RefChar *base = CopyContainsRef(sf);
+ int i;
+ EncMap *map = fv->map;
+
+ if ( base==NULL || fv->cidmaster!=NULL )
+return;
+ for ( i=0; i<map->enccount; ++i ) if ( fv->selected[i] ) {
+ LinkEncToGid(fv,i,base->orig_pos);
+ }
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawRequestExpose(fv->v,NULL,false);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_queue_draw(fv->v);
+#endif
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuSameGlyphAs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_SameGlyphAs(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVSameGlyphAs(fv);
+}
+#endif
+
+
+static void FVCopyFgtoBg(FontView *fv) {
+ int i, gid;
+
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ fv->sf->glyphs[gid]!=NULL &&
+ fv->sf->glyphs[gid]->layers[1].splines!=NULL )
+ SCCopyFgToBg(fv->sf->glyphs[gid],true);
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuCopyFgBg(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_CopyFg2Bg(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVCopyFgtoBg( fv );
+}
+#endif
+
+void BCClearAll(BDFChar *bc) {
+ if ( bc==NULL )
+return;
+ BCPreserveState(bc);
+ BCFlattenFloat(bc);
+ memset(bc->bitmap,'\0',bc->bytes_per_line*(bc->ymax-bc->ymin+1));
+ BCCompressBitmap(bc);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ BCCharChangedUpdate(bc);
+#endif
+}
+
+void SCClearContents(SplineChar *sc) {
+ RefChar *refs, *next;
+ int layer;
+
+ if ( sc==NULL )
+return;
+ sc->widthset = false;
+ sc->width = sc->parent->ascent+sc->parent->descent;
+ for ( layer = ly_fore; layer<sc->layer_cnt; ++layer ) {
+ SplinePointListsFree(sc->layers[layer].splines);
+ sc->layers[layer].splines = NULL;
+ for ( refs=sc->layers[layer].refs; refs!=NULL; refs = next ) {
+ next = refs->next;
+ SCRemoveDependent(sc,refs);
+ }
+ sc->layers[layer].refs = NULL;
+ }
+ AnchorPointsFree(sc->anchor);
+ sc->anchor = NULL;
+ StemInfosFree(sc->hstem); sc->hstem = NULL;
+ StemInfosFree(sc->vstem); sc->vstem = NULL;
+ DStemInfosFree(sc->dstem); sc->dstem = NULL;
+ MinimumDistancesFree(sc->md); sc->md = NULL;
+ free(sc->ttf_instrs);
+ sc->ttf_instrs = NULL;
+ sc->ttf_instrs_len = 0;
+ SCOutOfDateBackground(sc);
+}
+
+void SCClearAll(SplineChar *sc) {
+
+ if ( sc==NULL )
+return;
+ if ( sc->layers[1].splines==NULL && sc->layers[ly_fore].refs==NULL && !sc->widthset &&
+ sc->hstem==NULL && sc->vstem==NULL && sc->anchor==NULL &&
+ (!copymetadata ||
+ (sc->unicodeenc==-1 && strcmp(sc->name,".notdef")==0)))
+return;
+ SCPreserveState(sc,2);
+ if ( copymetadata ) {
+ sc->unicodeenc = -1;
+ free(sc->name);
+ sc->name = copy(".notdef");
+ PSTFree(sc->possub);
+ sc->possub = NULL;
+ }
+ SCClearContents(sc);
+ SCCharChangedUpdate(sc);
+}
+
+void SCClearBackground(SplineChar *sc) {
+
+ if ( sc==NULL )
+return;
+ if ( sc->layers[0].splines==NULL && sc->layers[ly_back].images==NULL )
+return;
+ SCPreserveBackground(sc);
+ SplinePointListsFree(sc->layers[0].splines);
+ sc->layers[0].splines = NULL;
+ ImageListsFree(sc->layers[ly_back].images);
+ sc->layers[ly_back].images = NULL;
+ SCOutOfDateBackground(sc);
+ SCCharChangedUpdate(sc);
+}
+
+static int UnselectedDependents(FontView *fv, SplineChar *sc) {
+ struct splinecharlist *dep;
+
+ for ( dep=sc->dependents; dep!=NULL; dep=dep->next ) {
+ if ( !fv->selected[fv->map->backmap[dep->sc->orig_pos]] )
+return( true );
+ if ( UnselectedDependents(fv,dep->sc))
+return( true );
+ }
+return( false );
+}
+
+void UnlinkThisReference(FontView *fv,SplineChar *sc) {
+ /* We are about to clear out sc. But somebody refers to it and that we */
+ /* aren't going to delete. So (if the user asked us to) instanciate sc */
+ /* into all characters which refer to it and which aren't about to be */
+ /* cleared out */
+ struct splinecharlist *dep, *dnext;
+
+ for ( dep=sc->dependents; dep!=NULL; dep=dnext ) {
+ dnext = dep->next;
+ if ( fv==NULL || !fv->selected[fv->map->backmap[dep->sc->orig_pos]]) {
+ SplineChar *dsc = dep->sc;
+ RefChar *rf, *rnext;
+ /* May be more than one reference to us, colon has two refs to period */
+ /* but only one dlist entry */
+ for ( rf = dsc->layers[ly_fore].refs; rf!=NULL; rf=rnext ) {
+ rnext = rf->next;
+ if ( rf->sc == sc ) {
+ /* Even if we were to preserve the state there would be no */
+ /* way to undo the operation until we undid the delete... */
+ SCRefToSplines(dsc,rf);
+ SCUpdateAll(dsc);
+ }
+ }
+ }
+ }
+}
+
+#ifndef LUA_FF_LIB
+static void FVClear(FontView *fv) {
+ int i;
+ BDFFont *bdf;
+ int refstate = 0;
+ char *buts[6];
+ int yes, unsel, gid;
+ /* refstate==0 => ask, refstate==1 => clearall, refstate==-1 => skip all */
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] && (gid=fv->map->map[i])!=-1 ) {
+ if ( !onlycopydisplayed || fv->filled==fv->show ) {
+ /* If we are messing with the outline character, check for dependencies */
+ if ( refstate<=0 && fv->sf->glyphs[gid]!=NULL &&
+ fv->sf->glyphs[gid]->dependents!=NULL ) {
+ unsel = UnselectedDependents(fv,fv->sf->glyphs[gid]);
+ if ( refstate==-2 && unsel ) {
+ UnlinkThisReference(fv,fv->sf->glyphs[gid]);
+ } else if ( unsel ) {
+ if ( refstate<0 )
+ continue;
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ buts[0] = _("_Yes");
+ buts[4] = _("_No");
+#elif defined(FONTFORGE_CONFIG_GTK)
+ buts[0] = GTK_STOCK_YES;
+ buts[4] = GTK_STOCK_NO;
+#endif
+ buts[1] = _("Yes to _All");
+ buts[2] = _("_Unlink All");
+ buts[3] = _("No _to All");
+ buts[5] = NULL;
+ yes = gwwv_ask(_("Bad Reference"),(const char **) buts,2,4,_("You are attempting to clear %.30s which is referred to by\nanother character. Are you sure you want to clear it?"),fv->sf->glyphs[gid]->name);
+ if ( yes==1 )
+ refstate = 1;
+ else if ( yes==2 ) {
+ UnlinkThisReference(fv,fv->sf->glyphs[gid]);
+ refstate = -2;
+ } else if ( yes==3 )
+ refstate = -1;
+ if ( yes>=3 )
+ continue;
+ }
+ }
+ }
+
+ if ( onlycopydisplayed && fv->filled==fv->show ) {
+ SCClearAll(fv->sf->glyphs[gid]);
+ } else if ( onlycopydisplayed ) {
+ BCClearAll(fv->show->glyphs[gid]);
+ } else {
+ SCClearAll(fv->sf->glyphs[gid]);
+ for ( bdf=fv->sf->bitmaps; bdf!=NULL; bdf = bdf->next )
+ BCClearAll(bdf->glyphs[gid]);
+ }
+ }
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuClear(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Clear(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVClear( fv );
+}
+#endif
+
+static void FVClearBackground(FontView *fv) {
+ SplineFont *sf = fv->sf;
+ int i, gid;
+
+ if ( onlycopydisplayed && fv->filled!=fv->show )
+return;
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 && sf->glyphs[gid]!=NULL ) {
+ SCClearBackground(sf->glyphs[gid]);
+ }
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuClearBackground(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ClearBackground(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVClearBackground( fv );
+}
+#endif
+
+static void FVJoin(FontView *fv) {
+ SplineFont *sf = fv->sf;
+ int i,changed,gid;
+ extern float joinsnap;
+
+ if ( onlycopydisplayed && fv->filled!=fv->show )
+return;
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 && sf->glyphs[gid]!=NULL ) {
+ SCPreserveState(sf->glyphs[gid],false);
+ sf->glyphs[gid]->layers[ly_fore].splines = SplineSetJoin(sf->glyphs[gid]->layers[ly_fore].splines,true,joinsnap,&changed);
+ if ( changed )
+ SCCharChangedUpdate(sf->glyphs[gid]);
+ }
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuJoin(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Join(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVJoin( fv );
+}
+#endif
+
+static void FVUnlinkRef(FontView *fv) {
+ int i,layer, gid;
+ SplineChar *sc;
+ RefChar *rf, *next;
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 && (sc = fv->sf->glyphs[gid])!=NULL &&
+ sc->layers[ly_fore].refs!=NULL ) {
+ SCPreserveState(sc,false);
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ for ( rf=sc->layers[ly_fore].refs; rf!=NULL ; rf=next ) {
+ next = rf->next;
+ SCRefToSplines(sc,rf);
+ }
+ }
+ SCCharChangedUpdate(sc);
+ }
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuUnlinkRef(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_UnlinkRef(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVUnlinkRef( fv );
+}
+#endif
+
+void SFRemoveUndoes(SplineFont *sf,uint8 *selected, EncMap *map) {
+ SplineFont *sf_main = sf->cidmaster? sf->cidmaster : sf, *ssf;
+ int i,k, max, layer, gid;
+ SplineChar *sc;
+ BDFFont *bdf;
+
+ if ( selected!=NULL || sf_main->subfontcnt==0 )
+ max = sf->glyphcnt;
+ else {
+ max = 0;
+ for ( k=0; k<sf_main->subfontcnt; ++k )
+ if ( sf_main->subfonts[k]->glyphcnt>max ) max = sf_main->subfonts[k]->glyphcnt;
+ }
+ for ( i=0; ; ++i ) {
+ if ( selected==NULL || sf_main->subfontcnt!=0 ) {
+ if ( i>=max )
+ break;
+ gid = i;
+ } else {
+ if ( i>=map->enccount )
+ break;
+ if ( !selected[i])
+ continue;
+ gid = map->map[i];
+ if ( gid==-1 )
+ continue;
+ }
+ for ( bdf=sf_main->bitmaps; bdf!=NULL; bdf=bdf->next ) {
+ if ( bdf->glyphs[gid]!=NULL ) {
+ UndoesFree(bdf->glyphs[gid]->undoes); bdf->glyphs[gid]->undoes = NULL;
+ UndoesFree(bdf->glyphs[gid]->redoes); bdf->glyphs[gid]->redoes = NULL;
+ }
+ }
+ k = 0;
+ do {
+ ssf = sf_main->subfontcnt==0? sf_main: sf_main->subfonts[k];
+ if ( gid<ssf->glyphcnt && ssf->glyphs[gid]!=NULL ) {
+ sc = ssf->glyphs[gid];
+ for ( layer = 0; layer<sc->layer_cnt; ++layer ) {
+ UndoesFree(sc->layers[layer].undoes); sc->layers[layer].undoes = NULL;
+ UndoesFree(sc->layers[layer].redoes); sc->layers[layer].redoes = NULL;
+ }
+ }
+ ++k;
+ } while ( k<sf_main->subfontcnt );
+ }
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuRemoveUndoes(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_RemoveUndoes(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ SFRemoveUndoes(fv->sf,fv->selected,fv->map);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuUndo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Undo(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int i,j,layer, gid;
+ MMSet *mm = fv->sf->mm;
+ int was_blended = mm!=NULL && mm->normal==fv->sf;
+
+ SFUntickAll(fv->sf);
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ fv->sf->glyphs[gid]!=NULL && !fv->sf->glyphs[gid]->ticked) {
+ SplineChar *sc = fv->sf->glyphs[gid];
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ if ( sc->layers[layer].undoes!=NULL ) {
+ SCDoUndo(sc,layer);
+ if ( was_blended ) {
+ for ( j=0; j<mm->instance_count; ++j )
+ SCDoUndo(mm->instances[j]->glyphs[gid],layer);
+ }
+ }
+ }
+ sc->ticked = true;
+ }
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuRedo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Redo(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int i,j,layer, gid;
+ MMSet *mm = fv->sf->mm;
+ int was_blended = mm!=NULL && mm->normal==fv->sf;
+
+ SFUntickAll(fv->sf);
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ fv->sf->glyphs[gid]!=NULL && !fv->sf->glyphs[gid]->ticked) {
+ SplineChar *sc = fv->sf->glyphs[gid];
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ if ( sc->layers[layer].redoes!=NULL ) {
+ SCDoRedo(sc,layer);
+ if ( was_blended ) {
+ for ( j=0; j<mm->instance_count; ++j )
+ SCDoRedo(mm->instances[j]->glyphs[gid],layer);
+ }
+ }
+ }
+ sc->ticked = true;
+ }
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuCut(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Cut(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVCopy(fv,ct_fullcopy);
+ FVClear(fv);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuSelectAll(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_SelectAll(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ FVSelectAll(fv);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuInvertSelection(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_InvertSelection(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ FVInvertSelection(fv);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuDeselectAll(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_DeselectAll(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ FVDeselectAll(fv);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuSelectByName(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_SelectByName(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ FVSelectByName(fv);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuSelectWorthOutputting(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_SelectWorthOutputting(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int i, gid;
+ EncMap *map = fv->map;
+ SplineFont *sf = fv->sf;
+
+ for ( i=0; i< map->enccount; ++i )
+ fv->selected[i] = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
+ SCWorthOutputting(sf->glyphs[gid]) );
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawRequestExpose(fv->v,NULL,false);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_queue_draw(fv->v);
+#endif
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuSelectChanged(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_SelectChangedGlyphs(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int i, gid;
+ EncMap *map = fv->map;
+ SplineFont *sf = fv->sf;
+
+ for ( i=0; i< map->enccount; ++i )
+ fv->selected[i] = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL && sf->glyphs[gid]->changed );
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawRequestExpose(fv->v,NULL,false);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_queue_draw(fv->v);
+#endif
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuSelectHintingNeeded(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_SelectUnhintedGlyphs(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int i, gid;
+ EncMap *map = fv->map;
+ SplineFont *sf = fv->sf;
+ int order2 = sf->order2;
+
+ for ( i=0; i< map->enccount; ++i )
+ fv->selected[i] = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
+ ((!order2 && sf->glyphs[gid]->changedsincelasthinted ) ||
+ ( order2 && sf->glyphs[gid]->layers[ly_fore].splines!=NULL &&
+ sf->glyphs[gid]->ttf_instrs_len<=0 ) ||
+ ( order2 && sf->glyphs[gid]->instructions_out_of_date )) );
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawRequestExpose(fv->v,NULL,false);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_queue_draw(fv->v);
+#endif
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuSelectColor(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ FVSelectColor(fv,(uint32) (intpt) (mi->ti.userdata),(e->u.chr.state&ksm_shift)?1:0);
+}
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_SelectDefault(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ FVSelectColor(fv,COLOR_DEFAULT,false);
+}
+
+void FontViewMenu_SelectWhite(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ FVSelectColor(fv,0xffffff,false);
+}
+
+void FontViewMenu_SelectRed(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ FVSelectColor(fv,0xff0000,false);
+}
+
+void FontViewMenu_SelectGreen(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ FVSelectColor(fv,0x00ff00,false);
+}
+
+void FontViewMenu_SelectBlue(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ FVSelectColor(fv,0x0000ff,false);
+}
+
+void FontViewMenu_SelectYellow(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ FVSelectColor(fv,0xffff00,false);
+}
+
+void FontViewMenu_SelectCyan(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ FVSelectColor(fv,0x00ffff,false);
+}
+
+void FontViewMenu_SelectMagenta(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ FVSelectColor(fv,0xff00ff,false);
+}
+
+void FontViewMenu_SelectColorPicker(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ GtkWidget *color_picker = gtk_color_selection_dialog_new(_("Select Color"));
+ GtkWidget *color_sel = GTK_COLOR_SELECTION_DIALOG( color_picker )->colorsel;
+ static GdkColor last_col;
+
+ gtk_color_selection_set_current_color(
+ GTK_COLOR_SELECTION( color_sel ), &last_col );
+ if (gtk_dialog_run( GTK_DIALOG( color_picker )) == GTK_RESPONSE_ACCEPT) {
+ gtk_color_selection_get_current_color(
+ GTK_COLOR_SELECTION( color_sel ), &last_col );
+ FVSelectColor(fv,((last_col.red>>8)<<16) |
+ ((last_col.green>>8)<<8) |
+ (last_col.blue>>8),
+ false);
+ }
+ gtk_widget_destroy( color_picker );
+}
+# endif
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuSelectByPST(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_SelectByAtt(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ FVSelectByPST(fv);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuFindRpl(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_FindRpl(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ SVCreate(fv);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuReplaceWithRef(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_RplRef(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ FVReplaceOutlineWithReference(fv,.001);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuCharInfo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_CharInfo(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int pos = FVAnyCharSelected(fv);
+ if ( pos<0 )
+return;
+ if ( fv->cidmaster!=NULL &&
+ (fv->map->map[pos]==-1 || fv->sf->glyphs[fv->map->map[pos]]==NULL ))
+return;
+ SCCharInfo(SFMakeChar(fv->sf,fv->map,pos),fv->map,pos);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuBDFInfo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_BDFInfo(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ if ( fv->sf->bitmaps==NULL )
+return;
+ if ( fv->show!=fv->filled )
+ SFBdfProperties(fv->sf,fv->map,fv->show);
+ else
+ SFBdfProperties(fv->sf,fv->map,NULL);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuShowDependentRefs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ShowDependentRefs(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int pos = FVAnyCharSelected(fv);
+ SplineChar *sc;
+
+ if ( pos<0 || fv->map->map[pos]==-1 )
+return;
+ sc = fv->sf->glyphs[fv->map->map[pos]];
+ if ( sc==NULL || sc->dependents==NULL )
+return;
+ SCRefBy(sc);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuShowDependentSubs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ShowDependentSubs(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int pos = FVAnyCharSelected(fv);
+ SplineChar *sc;
+
+ if ( pos<0 || fv->map->map[pos]==-1 )
+return;
+ sc = fv->sf->glyphs[fv->map->map[pos]];
+ if ( sc==NULL )
+return;
+ SCSubBy(sc);
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static int getorigin(void *d,BasePoint *base,int index) {
+ /*FontView *fv = (FontView *) d;*/
+
+ base->x = base->y = 0;
+ switch ( index ) {
+ case 0: /* Character origin */
+ /* all done */
+ break;
+ case 1: /* Center of selection */
+ /*CVFindCenter(cv,base,!CVAnySel(cv,NULL,NULL,NULL,NULL));*/
+ break;
+ default:
+return( false );
+ }
+return( true );
+}
+#endif
+
+void TransHints(StemInfo *stem,real mul1, real off1, real mul2, real off2, int round_to_int ) {
+ HintInstance *hi;
+
+ for ( ; stem!=NULL; stem=stem->next ) {
+ stem->start = stem->start*mul1 + off1;
+ stem->width *= mul1;
+ if ( round_to_int ) {
+ stem->start = rint(stem->start);
+ stem->width = rint(stem->width);
+ }
+ if ( mul1<0 ) {
+ stem->start += stem->width;
+ stem->width = -stem->width;
+ }
+ for ( hi=stem->where; hi!=NULL; hi=hi->next ) {
+ hi->begin = hi->begin*mul2 + off2;
+ hi->end = hi->end*mul2 + off2;
+ if ( round_to_int ) {
+ hi->begin = rint(hi->begin);
+ hi->end = rint(hi->end);
+ }
+ if ( mul2<0 ) {
+ double temp = hi->begin;
+ hi->begin = hi->end;
+ hi->end = temp;
+ }
+ }
+ }
+}
+
+void VrTrans(struct vr *vr,real transform[6]) {
+ /* I'm interested in scaling and skewing. I think translation should */
+ /* not affect these guys (they are offsets, so offsets should be */
+ /* unchanged by translation */
+ double x,y;
+
+ x = vr->xoff; y=vr->yoff;
+ vr->xoff = rint(transform[0]*x + transform[1]*y);
+ vr->yoff = rint(transform[2]*x + transform[3]*y);
+ x = vr->h_adv_off; y=vr->v_adv_off;
+ vr->h_adv_off = rint(transform[0]*x + transform[1]*y);
+ vr->v_adv_off = rint(transform[2]*x + transform[3]*y);
+}
+
+static void KCTrans(KernClass *kc,double scale) {
+ /* Again these are offsets, so I don't apply translation */
+ int i;
+
+ for ( i=kc->first_cnt*kc->second_cnt-1; i>=0; --i )
+ kc->offsets[i] = rint(scale*kc->offsets[i]);
+}
+
+/* If sel is specified then we decide how to transform references based on */
+/* whether the refered glyph is selected. (If we tranform a reference that */
+/* is selected we are, in effect, transforming it twice -- since the glyph */
+/* itself will be transformed -- so instead we just transform the offsets */
+/* of the reference */
+/* If sel is NULL then we transform the reference */
+/* if flags&fvt_partialreftrans then we always just transform the offsets */
+void FVTrans(FontView *fv,SplineChar *sc,real transform[6], uint8 *sel,
+ enum fvtrans_flags flags) {
+ RefChar *refs;
+ real t[6];
+ AnchorPoint *ap;
+ int i,j;
+ KernPair *kp;
+ PST *pst;
+
+ if ( sc->blended ) {
+ int j;
+ MMSet *mm = sc->parent->mm;
+ for ( j=0; j<mm->instance_count; ++j )
+ FVTrans(fv,mm->instances[j]->glyphs[sc->orig_pos],transform,sel,flags);
+ }
+
+ SCPreserveState(sc,true);
+ if ( !(flags&fvt_dontmovewidth) )
+ if ( transform[0]>0 && transform[3]>0 && transform[1]==0 && transform[2]==0 ) {
+ int widthset = sc->widthset;
+ SCSynchronizeWidth(sc,sc->width*transform[0]+transform[4],sc->width,fv);
+ if ( !(flags&fvt_dontsetwidth) ) sc->widthset = widthset;
+ sc->vwidth = sc->vwidth*transform[3]+transform[5];
+ }
+ if ( flags & fvt_scalepstpos ) {
+ for ( kp=sc->kerns; kp!=NULL; kp=kp->next )
+ kp->off = rint(kp->off*transform[0]);
+ for ( kp=sc->vkerns; kp!=NULL; kp=kp->next )
+ kp->off = rint(kp->off*transform[3]);
+ for ( pst = sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->type == pst_position )
+ VrTrans(&pst->u.pos,transform);
+ else if ( pst->type==pst_pair ) {
+ VrTrans(&pst->u.pair.vr[0],transform);
+ VrTrans(&pst->u.pair.vr[1],transform);
+ } else if ( pst->type == pst_lcaret ) {
+ int j;
+ for ( j=0; j<pst->u.lcaret.cnt; ++j )
+ pst->u.lcaret.carets[j] = rint(pst->u.lcaret.carets[j]*transform[0]+transform[4]);
+ }
+ }
+ }
+ for ( ap=sc->anchor; ap!=NULL; ap=ap->next )
+ ApTransform(ap,transform);
+ for ( i=ly_fore; i<sc->layer_cnt; ++i ) {
+ SplinePointListTransform(sc->layers[i].splines,transform,true);
+ for ( refs = sc->layers[i].refs; refs!=NULL; refs=refs->next ) {
+ if ( (sel!=NULL && sel[fv->map->backmap[refs->sc->orig_pos]]) ||
+ (flags&fvt_partialreftrans)) {
+ /* if the character referred to is selected then it's going to */
+ /* be scaled too (or will have been) so we don't want to scale */
+ /* it twice */
+ t[4] = refs->transform[4]*transform[0] +
+ refs->transform[5]*transform[2] +
+ /*transform[4]*/0;
+ t[5] = refs->transform[4]*transform[1] +
+ refs->transform[5]*transform[3] +
+ /*transform[5]*/0;
+ t[0] = refs->transform[4]; t[1] = refs->transform[5];
+ refs->transform[4] = t[4];
+ refs->transform[5] = t[5];
+ /* Now update the splines to match */
+ t[4] -= t[0]; t[5] -= t[1];
+ if ( t[4]!=0 || t[5]!=0 ) {
+ t[0] = t[3] = 1; t[1] = t[2] = 0;
+ for ( j=0; j<refs->layer_cnt; ++j )
+ SplinePointListTransform(refs->layers[j].splines,t,true);
+ }
+ } else {
+ for ( j=0; j<refs->layer_cnt; ++j )
+ SplinePointListTransform(refs->layers[j].splines,transform,true);
+ t[0] = refs->transform[0]*transform[0] +
+ refs->transform[1]*transform[2];
+ t[1] = refs->transform[0]*transform[1] +
+ refs->transform[1]*transform[3];
+ t[2] = refs->transform[2]*transform[0] +
+ refs->transform[3]*transform[2];
+ t[3] = refs->transform[2]*transform[1] +
+ refs->transform[3]*transform[3];
+ t[4] = refs->transform[4]*transform[0] +
+ refs->transform[5]*transform[2] +
+ transform[4];
+ t[5] = refs->transform[4]*transform[1] +
+ refs->transform[5]*transform[3] +
+ transform[5];
+ memcpy(refs->transform,t,sizeof(t));
+ }
+ RefCharFindBounds(refs);
+ }
+ }
+ if ( transform[1]==0 && transform[2]==0 ) {
+ if ( transform[0]==1 && transform[3]==1 &&
+ transform[5]==0 && transform[4]!=0 &&
+ sc->unicodeenc!=-1 && sc->unicodeenc<0x10000 &&
+ Isalpha(sc->unicodeenc)) {
+ SCUndoSetLBearingChange(sc,(int) rint(transform[4]));
+ SCSynchronizeLBearing(sc,transform[4]); /* this moves the hints */
+ } else {
+ TransHints(sc->hstem,transform[3],transform[5],transform[0],transform[4],flags&fvt_round_to_int);
+ TransHints(sc->vstem,transform[0],transform[4],transform[3],transform[5],flags&fvt_round_to_int);
+ }
+ }
+ if ( flags&fvt_round_to_int )
+ SCRound2Int(sc,1.0);
+ if ( flags&fvt_dobackground ) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ ImageList *img;
+#endif
+ SCPreserveBackground(sc);
+ SplinePointListTransform(sc->layers[ly_back].splines,transform,true);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ for ( img = sc->layers[ly_back].images; img!=NULL; img=img->next )
+ BackgroundImageTransform(sc, img, transform);
+#endif
+ }
+ SCCharChangedUpdate(sc);
+}
+
+void FVTransFunc(void *_fv,real transform[6],int otype, BVTFunc *bvts,
+ enum fvtrans_flags flags ) {
+ FontView *fv = _fv;
+ real transx = transform[4], transy=transform[5];
+ DBounds bb;
+ BasePoint base;
+ int i, cnt=0, gid;
+ BDFFont *bdf;
+
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ SCWorthOutputting(fv->sf->glyphs[gid]) )
+ ++cnt;
+
+#if 0 /* Do this in scaletoem */
+ if ( cnt>fv->sf->glyphcnt/2 ) {
+ if ( transform[3]!=1.0 ) {
+ if ( transform[2]==0 ) {
+ fv->sf->pfminfo.os2_typoascent = rint( fv->sf->pfminfo.os2_typoascent * transform[3]);
+ fv->sf->pfminfo.os2_typodescent = rint( fv->sf->pfminfo.os2_typodescent * transform[3]);
+ fv->sf->pfminfo.os2_typolinegap = rint( fv->sf->pfminfo.os2_typolinegap * transform[3]);
+ fv->sf->pfminfo.os2_winascent = rint( fv->sf->pfminfo.os2_winascent * transform[3]);
+ fv->sf->pfminfo.os2_windescent = rint( fv->sf->pfminfo.os2_windescent * transform[3]);
+ fv->sf->pfminfo.hhead_ascent = rint( fv->sf->pfminfo.hhead_ascent * transform[3]);
+ fv->sf->pfminfo.hhead_descent = rint( fv->sf->pfminfo.hhead_descent * transform[3]);
+ fv->sf->pfminfo.linegap = rint( fv->sf->pfminfo.linegap * transform[3]);
+ fv->sf->pfminfo.os2_subysize = rint( fv->sf->pfminfo.os2_subysize * transform[3]);
+ fv->sf->pfminfo.os2_subyoff = rint( fv->sf->pfminfo.os2_subyoff * transform[3]);
+ fv->sf->pfminfo.os2_supysize = rint( fv->sf->pfminfo.os2_supysize * transform[3]);
+ fv->sf->pfminfo.os2_supyoff = rint( fv->sf->pfminfo.os2_supyoff * transform[3]);
+ fv->sf->pfminfo.os2_strikeysize = rint( fv->sf->pfminfo.os2_strikeysize * transform[3]);
+ fv->sf->pfminfo.os2_strikeypos = rint( fv->sf->pfminfo.os2_strikeypos * transform[3]);
+ fv->sf->pfminfo.upos *= transform[3];
+ fv->sf->pfminfo.uwidth *= transform[3];
+ }
+ }
+ if ( transform[1]==0 && transform[0]!=1.0 ) {
+ fv->sf->pfminfo.vlinegap = rint( fv->sf->pfminfo.vlinegap * transform[0]);
+ fv->sf->pfminfo.os2_subxsize = rint( fv->sf->pfminfo.os2_subxsize * transform[0]);
+ fv->sf->pfminfo.os2_subxoff = rint( fv->sf->pfminfo.os2_subxoff * transform[0]);
+ fv->sf->pfminfo.os2_supxsize = rint( fv->sf->pfminfo.os2_supxsize * transform[0]);
+ fv->sf->pfminfo.os2_supxoff = rint( fv->sf->pfminfo.os2_supxoff * transform[0]);
+ }
+ }
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_start_indicator(10,_("Transforming..."),_("Transforming..."),0,cnt,1);
+# endif
+
+ SFUntickAll(fv->sf);
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 &&
+ SCWorthOutputting(fv->sf->glyphs[gid]) &&
+ !fv->sf->glyphs[gid]->ticked ) {
+ SplineChar *sc = fv->sf->glyphs[gid];
+
+ if ( onlycopydisplayed && fv->show!=fv->filled ) {
+ if ( fv->show->glyphs[gid]!=NULL )
+ BCTrans(fv->show,fv->show->glyphs[gid],bvts,fv);
+ } else {
+ if ( otype==1 ) {
+ SplineCharFindBounds(sc,&bb);
+ base.x = (bb.minx+bb.maxx)/2;
+ base.y = (bb.miny+bb.maxy)/2;
+ transform[4]=transx+base.x-
+ (transform[0]*base.x+transform[2]*base.y);
+ transform[5]=transy+base.y-
+ (transform[1]*base.x+transform[3]*base.y);
+ }
+ FVTrans(fv,sc,transform,fv->selected,flags);
+ if ( !onlycopydisplayed ) {
+ for ( bdf = fv->sf->bitmaps; bdf!=NULL; bdf=bdf->next )
+ if ( gid<bdf->glyphcnt && bdf->glyphs[gid]!=NULL )
+ BCTrans(bdf,bdf->glyphs[gid],bvts,fv);
+ }
+ }
+ sc->ticked = true;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next())
+ break;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+ if ( flags&fvt_dogrid ) {
+ SFPreserveGuide(fv->sf);
+ SplinePointListTransform(fv->sf->grid.splines,transform,true);
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_end_indicator();
+# endif
+
+ if ( flags&fvt_scalekernclasses ) {
+ KernClass *kc;
+ SplineFont *sf = fv->cidmaster!=NULL ? fv->cidmaster : fv->sf;
+ for ( kc=sf->kerns; kc!=NULL; kc=kc->next )
+ KCTrans(kc,transform[0]);
+ for ( kc=sf->vkerns; kc!=NULL; kc=kc->next )
+ KCTrans(kc,transform[3]);
+ }
+}
+
+static char *scaleString(char *string, double scale) {
+ char *result;
+ char *pt;
+ char *end;
+ double val;
+
+ if ( string==NULL )
+return( NULL );
+
+ while ( *string==' ' ) ++string;
+ result = galloc(10*strlen(string)+1);
+ if ( *string!='[' ) {
+ val = strtod(string,&end);
+ if ( end==string ) {
+ free( result );
+return( NULL );
+ }
+ sprintf( result, "%g", val*scale);
+return( result );
+ }
+
+ pt = result;
+ *pt++ = '[';
+ ++string;
+ while ( *string!='\0' && *string!=']' ) {
+ val = strtod(string,&end);
+ if ( end==string ) {
+ free(result);
+return( NULL );
+ }
+ sprintf( pt, "%g ", val*scale);
+ pt += strlen(pt);
+ string = end;
+ }
+ if ( pt[-1] == ' ' ) pt[-1] = ']';
+ else *pt++ = ']';
+ *pt = '\0';
+return( result );
+}
+
+static char *iscaleString(char *string, double scale) {
+ char *result;
+ char *pt;
+ char *end;
+ double val;
+
+ if ( string==NULL )
+return( NULL );
+
+ while ( *string==' ' ) ++string;
+ result = galloc(10*strlen(string)+1);
+ if ( *string!='[' ) {
+ val = strtod(string,&end);
+ if ( end==string ) {
+ free( result );
+return( NULL );
+ }
+ sprintf( result, "%g", rint(val*scale));
+return( result );
+ }
+
+ pt = result;
+ *pt++ = '[';
+ ++string;
+ while ( *string!='\0' && *string!=']' ) {
+ val = strtod(string,&end);
+ if ( end==string ) {
+ free(result);
+return( NULL );
+ }
+ sprintf( pt, "%g ", rint(val*scale));
+ pt += strlen(pt);
+ string = end;
+ }
+ if ( pt[-1] == ' ' ) pt[-1] = ']';
+ else *pt++ = ']';
+ *pt = '\0';
+return( result );
+}
+
+static void SFScalePrivate(SplineFont *sf,double scale) {
+ static char *scalethese[] = {
+ NULL
+ };
+ static char *integerscalethese[] = {
+ "BlueValues", "OtherBlues",
+ "FamilyBlues", "FamilyOtherBlues",
+ "BlueShift", "BlueFuzz",
+ "StdHW", "StdVW", "StemSnapH", "StemSnapV",
+ NULL
+ };
+ int i;
+
+ for ( i=0; integerscalethese[i]!=NULL; ++i ) {
+ char *str = PSDictHasEntry(sf->private,integerscalethese[i]);
+ char *new = iscaleString(str,scale);
+ if ( new!=NULL )
+ PSDictChangeEntry(sf->private,integerscalethese[i],new);
+ free(new);
+ }
+ for ( i=0; scalethese[i]!=NULL; ++i ) {
+ char *str = PSDictHasEntry(sf->private,scalethese[i]);
+ char *new = scaleString(str,scale);
+ if ( new!=NULL )
+ PSDictChangeEntry(sf->private,scalethese[i],new);
+ free(new);
+ }
+}
+
+int SFScaleToEm(SplineFont *sf, int as, int des) {
+ double scale;
+ real transform[6];
+ BVTFunc bvts;
+ uint8 *oldselected = sf->fv->selected;
+
+ scale = (as+des)/(double) (sf->ascent+sf->descent);
+ sf->pfminfo.hhead_ascent = rint( sf->pfminfo.hhead_ascent * scale);
+ sf->pfminfo.hhead_descent = rint( sf->pfminfo.hhead_descent * scale);
+ sf->pfminfo.linegap = rint( sf->pfminfo.linegap * scale);
+ sf->pfminfo.vlinegap = rint( sf->pfminfo.vlinegap * scale);
+ sf->pfminfo.os2_winascent = rint( sf->pfminfo.os2_winascent * scale);
+ sf->pfminfo.os2_windescent = rint( sf->pfminfo.os2_windescent * scale);
+ sf->pfminfo.os2_typoascent = rint( sf->pfminfo.os2_typoascent * scale);
+ sf->pfminfo.os2_typodescent = rint( sf->pfminfo.os2_typodescent * scale);
+ sf->pfminfo.os2_typolinegap = rint( sf->pfminfo.os2_typolinegap * scale);
+
+ sf->pfminfo.os2_subxsize = rint( sf->pfminfo.os2_subxsize * scale);
+ sf->pfminfo.os2_subysize = rint( sf->pfminfo.os2_subysize * scale);
+ sf->pfminfo.os2_subxoff = rint( sf->pfminfo.os2_subxoff * scale);
+ sf->pfminfo.os2_subyoff = rint( sf->pfminfo.os2_subyoff * scale);
+ sf->pfminfo.os2_supxsize = rint( sf->pfminfo.os2_supxsize * scale);
+ sf->pfminfo.os2_supysize = rint(sf->pfminfo.os2_supysize * scale);
+ sf->pfminfo.os2_supxoff = rint( sf->pfminfo.os2_supxoff * scale);
+ sf->pfminfo.os2_supyoff = rint( sf->pfminfo.os2_supyoff * scale);
+ sf->pfminfo.os2_strikeysize = rint( sf->pfminfo.os2_strikeysize * scale);
+ sf->pfminfo.os2_strikeypos = rint( sf->pfminfo.os2_strikeypos * scale);
+ sf->upos *= scale;
+ sf->uwidth *= scale;
+
+ if ( sf->private!=NULL )
+ SFScalePrivate(sf,scale);
+
+ if ( as+des == sf->ascent+sf->descent ) {
+ if ( as!=sf->ascent && des!=sf->descent ) {
+ sf->ascent = as; sf->descent = des;
+ sf->changed = true;
+ }
+return( false );
+ }
+
+ transform[0] = transform[3] = scale;
+ transform[1] = transform[2] = transform[4] = transform[5] = 0;
+ bvts.func = bvt_none;
+ sf->fv->selected = galloc(sf->fv->map->enccount);
+ memset(sf->fv->selected,1,sf->fv->map->enccount);
+
+ sf->ascent = as; sf->descent = des;
+
+ FVTransFunc(sf->fv,transform,0,&bvts,
+ fvt_dobackground|fvt_round_to_int|fvt_dontsetwidth|fvt_scalekernclasses|fvt_scalepstpos);
+ free(sf->fv->selected);
+ sf->fv->selected = oldselected;
+
+ if ( !sf->changed ) {
+ sf->changed = true;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FVSetTitle(sf->fv);
+#endif
+ }
+
+return( true );
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static void FVDoTransform(FontView *fv) {
+ int flags=0x3;
+ if ( FVAnyCharSelected(fv)==-1 )
+return;
+ if ( FVAllSelected(fv))
+ flags = 0x7;
+ TransformDlgCreate(fv,FVTransFunc,getorigin,flags,cvt_none);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuTransform(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Transform(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVDoTransform(fv);
+}
+
+#if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuPOV(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ struct pov_data pov_data;
+ if ( FVAnyCharSelected(fv)==-1 || fv->sf->onlybitmaps )
+return;
+ if ( PointOfViewDlg(&pov_data,fv->sf,false)==-1 )
+return;
+ FVPointOfView(fv,&pov_data);
+}
+
+static void FVMenuNLTransform(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ if ( FVAnyCharSelected(fv)==-1 )
+return;
+ NonLinearDlg(fv,NULL);
+}
+#elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_PointOfView(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ struct pov_data pov_data;
+ if ( FVAnyCharSelected(fv)==-1 || fv->sf->onlybitmaps )
+return;
+ if ( PointOfViewDlg(&pov_data,fv->sf,false)==-1 )
+return;
+ FVPointOfView(fv,&pov_data);
+}
+
+void FontViewMenu_NonLinearTransform(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ if ( FVAnyCharSelected(fv)==-1 || fv->sf->onlybitmaps )
+return;
+ NonLinearDlg(fv,NULL);
+}
+#endif
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuBitmaps(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ BitmapDlg(fv,NULL,mi->mid==MID_RemoveBitmaps?-1:(mi->mid==MID_AvailBitmaps) );
+}
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_BitmapsAvail(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ BitmapDlg(fv,NULL,true );
+}
+
+void FontViewMenu_RegenBitmaps(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ BitmapDlg(fv,NULL,false );
+}
+
+void FontViewMenu_RemoveBitmaps(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ BitmapDlg(fv,NULL,-1 );
+}
+# endif
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuStroke(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ExpandStroke(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVStroke(fv);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+# ifdef FONTFORGE_CONFIG_TILEPATH
+static void FVMenuTilePath(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ FVTile(fv);
+}
+# endif
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_TilePath(GtkMenuItem *menuitem, gpointer user_data) {
+# ifdef FONTFORGE_CONFIG_TILEPATH
+ FontView *fv = FV_From_MI(menuitem);
+ FVTile(fv);
+# endif
+}
+# endif
+#endif
+
+static void FVOverlap(FontView *fv,enum overlap_type ot) {
+ int i, cnt=0, layer, gid;
+ SplineChar *sc;
+
+ /* We know it's more likely that we'll find a problem in the overlap code */
+ /* than anywhere else, so let's save the current state against a crash */
+ DoAutoSaves();
+
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ SCWorthOutputting(fv->sf->glyphs[gid]) )
+ ++cnt;
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_start_indicator(10,_("Removing overlaps..."),_("Removing overlaps..."),0,cnt,1);
+# endif
+
+ SFUntickAll(fv->sf);
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 &&
+ SCWorthOutputting((sc=fv->sf->glyphs[gid])) &&
+ !sc->ticked ) {
+ sc->ticked = true;
+ if ( !SCRoundToCluster(sc,-2,false,.03,.12))
+ SCPreserveState(sc,false);
+ MinimumDistancesFree(sc->md);
+ sc->md = NULL;
+ for ( layer = ly_fore; layer<sc->layer_cnt; ++layer )
+ sc->layers[layer].splines = SplineSetRemoveOverlap(sc,sc->layers[layer].splines,ot);
+ SCCharChangedUpdate(sc);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next())
+ break;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_end_indicator();
+# endif
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuOverlap(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+
+ if ( fv->sf->order2 || fv->sf->onlybitmaps )
+return;
+
+ /* We know it's more likely that we'll find a problem in the overlap code */
+ /* than anywhere else, so let's save the current state against a crash */
+ DoAutoSaves();
+
+ FVOverlap(fv,mi->mid==MID_RmOverlap ? over_remove :
+ mi->mid==MID_Intersection ? over_intersect :
+ over_findinter);
+}
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_RemoveOverlap(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+
+ /* We know it's more likely that we'll find a problem in the overlap code */
+ /* than anywhere else, so let's save the current state against a crash */
+ DoAutoSaves();
+
+ FVOverlap(fv,over_remove);
+}
+
+void FontViewMenu_Intersect(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ DoAutoSaves();
+ FVOverlap(fv,over_intersect);
+}
+
+void FontViewMenu_FindInter(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ DoAutoSaves();
+ FVOverlap(fv,over_findinter);
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuInline(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Inline(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ OutlineDlg(fv,NULL,NULL,true);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuOutline(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Outline(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ OutlineDlg(fv,NULL,NULL,false);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuShadow(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Shadow(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ ShadowDlg(fv,NULL,NULL,false);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuWireframe(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Wireframe(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ ShadowDlg(fv,NULL,NULL,true);
+}
+#endif
+
+void _FVSimplify(FontView *fv,struct simplifyinfo *smpl) {
+ int i, cnt=0, layer, gid;
+ SplineChar *sc;
+
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ SCWorthOutputting(fv->sf->glyphs[gid]) )
+ ++cnt;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_start_indicator(10,_("Simplifying..."),_("Simplifying..."),0,cnt,1);
+# endif
+
+ SFUntickAll(fv->sf);
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( (gid=fv->map->map[i])!=-1 && SCWorthOutputting((sc=fv->sf->glyphs[gid])) &&
+ fv->selected[i] && !sc->ticked ) {
+ sc->ticked = true;
+ SCPreserveState(sc,false);
+ for ( layer = ly_fore; layer<sc->layer_cnt; ++layer )
+ sc->layers[layer].splines = SplineCharSimplify(sc,sc->layers[layer].splines,smpl);
+ SCCharChangedUpdate(sc);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next())
+ break;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_end_indicator();
+# endif
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static void FVSimplify(FontView *fv,int type) {
+ static struct simplifyinfo smpls[] = {
+ { sf_normal },
+ { sf_normal,.75,.05,0,-1 },
+ { sf_normal,.75,.05,0,-1 }};
+ struct simplifyinfo *smpl = &smpls[type+1];
+
+ if ( smpl->linelenmax==-1 || (type==0 && !smpl->set_as_default)) {
+ smpl->err = (fv->sf->ascent+fv->sf->descent)/1000.;
+ smpl->linelenmax = (fv->sf->ascent+fv->sf->descent)/100.;
+ }
+
+ if ( type==1 ) {
+ if ( !SimplifyDlg(fv->sf,smpl))
+return;
+ if ( smpl->set_as_default )
+ smpls[1] = *smpl;
+ }
+ _FVSimplify(fv,smpl);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuSimplify(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FVSimplify( (FontView *) GDrawGetUserData(gw),false );
+}
+
+static void FVMenuSimplifyMore(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FVSimplify( (FontView *) GDrawGetUserData(gw),true );
+}
+
+static void FVMenuCleanup(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FVSimplify( (FontView *) GDrawGetUserData(gw),-1 );
+}
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Simplify(GtkMenuItem *menuitem, gpointer user_data) {
+ FVSimplify( (FontView *) FV_From_MI(menuitem), false);
+}
+
+void FontViewMenu_SimplifyMore(GtkMenuItem *menuitem, gpointer user_data) {
+ FVSimplify( (FontView *) FV_From_MI(menuitem), true);
+}
+
+void FontViewMenu_Cleanup(GtkMenuItem *menuitem, gpointer user_data) {
+ FVSimplify( (FontView *) FV_From_MI(menuitem), -1);
+}
+#endif
+
+static void FVCanonicalStart(FontView *fv) {
+ int i, gid;
+
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 )
+ SPLsStartToLeftmost(fv->sf->glyphs[gid]);
+}
+
+static void FVCanonicalContours(FontView *fv) {
+ int i, gid;
+
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 )
+ CanonicalContours(fv->sf->glyphs[gid]);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuCanonicalStart(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FVCanonicalStart( (FontView *) GDrawGetUserData(gw) );
+}
+
+static void FVMenuCanonicalContours(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FVCanonicalContours( (FontView *) GDrawGetUserData(gw) );
+}
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_CanonicalStart(GtkMenuItem *menuitem, gpointer user_data) {
+ FVCanonicalStart( (FontView *) FV_From_MI(menuitem));
+}
+
+void FontViewMenu_CanonicalContours(GtkMenuItem *menuitem, gpointer user_data) {
+ FVCanonicalContours( (FontView *) FV_From_MI(menuitem));
+}
+#endif
+#endif
+
+static void FVAddExtrema(FontView *fv) {
+ int i, cnt=0, layer, gid;
+ SplineChar *sc;
+ SplineFont *sf = fv->sf;
+ int emsize = sf->ascent+sf->descent;
+
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ SCWorthOutputting(fv->sf->glyphs[gid]) )
+ ++cnt;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_start_indicator(10,_("Adding points at Extrema..."),_("Adding points at Extrema..."),0,cnt,1);
+# endif
+
+ SFUntickAll(fv->sf);
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 &&
+ SCWorthOutputting((sc = fv->sf->glyphs[gid])) &&
+ !sc->ticked) {
+ sc->ticked = true;
+ SCPreserveState(sc,false);
+ for ( layer = ly_fore; layer<sc->layer_cnt; ++layer )
+ SplineCharAddExtrema(sc,sc->layers[layer].splines,ae_only_good,emsize);
+ SCCharChangedUpdate(sc);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next())
+ break;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_end_indicator();
+# endif
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuAddExtrema(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FVAddExtrema( (FontView *) GDrawGetUserData(gw) );
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_AddExtrema(GtkMenuItem *menuitem, gpointer user_data) {
+ FVAddExtrema( (FontView *) FV_From_MI(menuitem) );
+# endif
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuCorrectDir(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_CorrectDir(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int i, cnt=0, changed, refchanged, preserved, layer, gid;
+ int askedall=-1, asked;
+ RefChar *ref, *next;
+ SplineChar *sc;
+
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ SCWorthOutputting(fv->sf->glyphs[gid]) )
+ ++cnt;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_start_indicator(10,_("Correcting Direction..."),_("Correcting Direction..."),0,cnt,1);
+# endif
+
+ SFUntickAll(fv->sf);
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 && SCWorthOutputting((sc=fv->sf->glyphs[gid])) &&
+ !sc->ticked ) {
+ sc->ticked = true;
+ changed = refchanged = preserved = false;
+ asked = askedall;
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ for ( ref=sc->layers[layer].refs; ref!=NULL; ref=next ) {
+ next = ref->next;
+ if ( ref->transform[0]*ref->transform[3]<0 ||
+ (ref->transform[0]==0 && ref->transform[1]*ref->transform[2]>0)) {
+ if ( asked==-1 ) {
+ char *buts[5];
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ buts[2] = _("_Cancel");
+#elif defined(FONTFORGE_CONFIG_GTK)
+ buts[2] = GTK_STOCK_CANCEL;
+#endif
+ buts[0] = _("Unlink All");
+ buts[1] = _("Unlink");
+ buts[3] = NULL;
+ asked = gwwv_ask(_("Flipped Reference"),(const char **) buts,0,2,_("%.50s contains a flipped reference. This cannot be corrected as is. Would you like me to unlink it and then correct it?"), sc->name );
+ if ( asked==3 )
+return;
+ else if ( asked==2 )
+ break;
+ else if ( asked==0 )
+ askedall = 0;
+ }
+ if ( asked==0 || asked==1 ) {
+ if ( !preserved ) {
+ preserved = refchanged = true;
+ SCPreserveState(sc,false);
+ }
+ SCRefToSplines(sc,ref);
+ }
+ }
+ }
+
+ if ( !preserved && sc->layers[layer].splines!=NULL ) {
+ SCPreserveState(sc,false);
+ preserved = true;
+ }
+ sc->layers[layer].splines = SplineSetsCorrect(sc->layers[layer].splines,&changed);
+ }
+ if ( changed || refchanged )
+ SCCharChangedUpdate(sc);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next())
+ break;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_end_indicator();
+# endif
+}
+#endif
+
+static void FVRound2Int(FontView *fv,real factor) {
+ int i, cnt=0, gid;
+
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ SCWorthOutputting(fv->sf->glyphs[gid]) )
+ ++cnt;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_start_indicator(10,_("Rounding to integer..."),_("Rounding to integer..."),0,cnt,1);
+# endif
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 && SCWorthOutputting(fv->sf->glyphs[gid]) ) {
+ SplineChar *sc = fv->sf->glyphs[gid];
+
+ SCPreserveState(sc,false);
+ SCRound2Int( sc,factor);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next())
+ break;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_end_indicator();
+# endif
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuRound2Int(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FVRound2Int( (FontView *) GDrawGetUserData(gw), 1.0 );
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_RoundToInt(GtkMenuItem *menuitem, gpointer user_data) {
+ FVRound2Int( (FontView *) FV_From_MI(menuitem), 1.0);
+# endif
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuRound2Hundredths(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FVRound2Int( (FontView *) GDrawGetUserData(gw),100.0 );
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_RoundToHundredths(GtkMenuItem *menuitem, gpointer user_data) {
+ FVRound2Int( (FontView *) FV_From_MI(menuitem),100.0);
+# endif
+}
+
+static void FVCluster(FontView *fv) {
+ int i, cnt=0, gid;
+
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ SCWorthOutputting(fv->sf->glyphs[gid]) )
+ ++cnt;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_start_indicator(10,_("Rounding to integer..."),_("Rounding to integer..."),0,cnt,1);
+# endif
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 && SCWorthOutputting(fv->sf->glyphs[gid]) ) {
+ SCRoundToCluster(fv->sf->glyphs[gid],-2,false,.1,.5);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next())
+ break;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_end_indicator();
+# endif
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuCluster(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FVCluster( (FontView *) GDrawGetUserData(gw));
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Cluster(GtkMenuItem *menuitem, gpointer user_data) {
+ FVCluster( (FontView *) FV_From_MI(menuitem));
+# endif
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuAutotrace(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Autotrace(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVAutoTrace(fv,e!=NULL && (e->u.mouse.state&ksm_shift));
+}
+#endif
+
+#ifndef LUA_FF_LIB
+void FVBuildAccent(FontView *fv,int onlyaccents) {
+ int i, cnt=0, gid;
+ SplineChar dummy;
+ SplineChar *sc;
+
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ SCWorthOutputting(fv->sf->glyphs[gid]) )
+ ++cnt;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_start_indicator(10,_("Building accented glyphs"),
+ _("Building accented glyphs"),NULL,cnt,1);
+# endif
+
+ SFUntickAll(fv->sf);
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] ) {
+ gid = fv->map->map[i];
+ sc = NULL;
+ if ( gid!=-1 ) {
+ sc = fv->sf->glyphs[gid];
+ if ( sc!=NULL && sc->ticked )
+ continue;
+ }
+ if ( sc==NULL )
+ sc = SCBuildDummy(&dummy,fv->sf,fv->map,i);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ else if ( !no_windowing_ui && sc->unicodeenc == 0x00c5 /* Aring */ &&
+ sc->layers[ly_fore].splines!=NULL ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buts[3];
+ buts[0] = _("_Yes");
+ buts[1] = _("_No");
+ buts[2] = NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buts[] = { GTK_STOCK_YES, GTK_STOCK_NO, NULL };
+#endif
+ if ( gwwv_ask(U_("Replace Ã…"),(const char **) buts,0,1,U_("Are you sure you want to replace Ã…?\nThe ring will not join to the A."))==1 )
+ continue;
+ }
+#endif
+ if ( SFIsSomethingBuildable(fv->sf,sc,onlyaccents) ) {
+ sc = SFMakeChar(fv->sf,fv->map,i);
+ sc->ticked = true;
+ SCBuildComposit(fv->sf,sc,!onlycopydisplayed,fv);
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next())
+ break;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_end_indicator();
+# endif
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuBuildAccent(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FVBuildAccent( (FontView *) GDrawGetUserData(gw), true );
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_BuildAccent(GtkMenuItem *menuitem, gpointer user_data) {
+ FVBuildAccent( (FontView *) FV_From_MI(menuitem), true );
+# endif
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuBuildComposite(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FVBuildAccent( (FontView *) GDrawGetUserData(gw), false );
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_BuildComposite(GtkMenuItem *menuitem, gpointer user_data) {
+ FVBuildAccent( (FontView *) FV_From_MI(menuitem), false );
+# endif
+}
+#endif
+
+static int SFIsDuplicatable(SplineFont *sf, SplineChar *sc) {
+ extern const int cns14pua[], amspua[];
+ const int *pua = sf->uni_interp==ui_trad_chinese ? cns14pua : sf->uni_interp==ui_ams ? amspua : NULL;
+ int baseuni = 0;
+ const unichar_t *pt;
+
+ if ( pua!=NULL && sc->unicodeenc>=0xe000 && sc->unicodeenc<=0xf8ff )
+ baseuni = pua[sc->unicodeenc-0xe000];
+ if ( baseuni==0 && ( pt = SFGetAlternate(sf,sc->unicodeenc,sc,false))!=NULL &&
+ pt[0]!='\0' && pt[1]=='\0' )
+ baseuni = pt[0];
+ if ( baseuni!=0 && SFGetChar(sf,baseuni,NULL)!=NULL )
+return( true );
+
+return( false );
+}
+
+void FVBuildDuplicate(FontView *fv) {
+ extern const int cns14pua[], amspua[];
+ const int *pua = fv->sf->uni_interp==ui_trad_chinese ? cns14pua : fv->sf->uni_interp==ui_ams ? amspua : NULL;
+ int i, cnt=0, gid;
+ SplineChar dummy;
+ const unichar_t *pt;
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] )
+ ++cnt;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_start_indicator(10,_("Building duplicate encodings"),
+ _("Building duplicate encodings"),NULL,cnt,1);
+# endif
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] ) {
+ SplineChar *sc;
+ int baseuni = 0;
+ if ( (gid = fv->map->map[i])==-1 || (sc = fv->sf->glyphs[gid])==NULL )
+ sc = SCBuildDummy(&dummy,fv->sf,fv->map,i);
+ if ( pua!=NULL && sc->unicodeenc>=0xe000 && sc->unicodeenc<=0xf8ff )
+ baseuni = pua[sc->unicodeenc-0xe000];
+ if ( baseuni==0 && ( pt = SFGetAlternate(fv->sf,sc->unicodeenc,sc,false))!=NULL &&
+ pt[0]!='\0' && pt[1]=='\0' )
+ baseuni = pt[0];
+
+ if ( baseuni!=0 && (gid = SFFindExistingSlot(fv->sf,baseuni,NULL))!=-1 )
+ LinkEncToGid(fv,i,gid);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next())
+ break;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_end_indicator();
+# endif
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuBuildDuplicate(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FVBuildDuplicate( (FontView *) GDrawGetUserData(gw));
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_BuildDuplicatem(GtkMenuItem *menuitem, gpointer user_data) {
+ FVBuildDuplicate( (FontView *) FV_From_MI(menuitem));
+# endif
+}
+#endif
+#endif /* LUA_FF_LIB */
+
+#ifdef KOREAN
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuShowGroup(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ ShowGroup( ((FontView *) GDrawGetUserData(gw))->sf );
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ShowGroup(GtkMenuItem *menuitem, gpointer user_data) {
+ ShowGroup( ((FontView *) FV_From_MI(menuitem))->sf );
+# endif
+}
+#endif
+#endif
+
+#if HANYANG
+static void FVMenuModifyComposition(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ if ( fv->sf->rules!=NULL )
+ SFModifyComposition(fv->sf);
+}
+
+static void FVMenuBuildSyllables(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ if ( fv->sf->rules!=NULL )
+ SFBuildSyllables(fv->sf);
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuCompareFonts(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_CompareFonts(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FontCompareDlg(fv);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuMergeFonts(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_MergeFonts(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVMergeFonts(fv);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuInterpFonts(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Interpolate(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVInterpolateFonts(fv);
+}
+
+static void FVShowInfo(FontView *fv);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+void FVChangeChar(FontView *fv,int i) {
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( i!=-1 ) {
+ FVDeselectAll(fv);
+ fv->selected[i] = true;
+ fv->sel_index = 1;
+ fv->end_pos = fv->pressed_pos = i;
+ FVToggleCharSelected(fv,i);
+ FVScrollToChar(fv,i);
+ FVShowInfo(fv);
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+void FVScrollToChar(FontView *fv,int i) {
+
+ if ( fv->v==NULL || fv->colcnt==0 ) /* Can happen in scripts */
+return;
+
+ if ( i!=-1 ) {
+ if ( i/fv->colcnt<fv->rowoff || i/fv->colcnt >= fv->rowoff+fv->rowcnt ) {
+ fv->rowoff = i/fv->colcnt;
+ if ( fv->rowcnt>= 3 )
+ --fv->rowoff;
+ if ( fv->rowoff+fv->rowcnt>=fv->rowltot )
+ fv->rowoff = fv->rowltot-fv->rowcnt;
+ if ( fv->rowoff<0 ) fv->rowoff = 0;
+ GScrollBarSetPos(fv->vsb,fv->rowoff);
+ GDrawRequestExpose(fv->v,NULL,false);
+ }
+ }
+}
+
+static void _FVMenuChangeChar(FontView *fv,int mid ) {
+ SplineFont *sf = fv->sf;
+ EncMap *map = fv->map;
+ int pos = FVAnyCharSelected(fv);
+
+ if ( pos>=0 ) {
+ if ( mid==MID_Next )
+ ++pos;
+ else if ( mid==MID_Prev )
+ --pos;
+ else if ( mid==MID_NextDef ) {
+ for ( ++pos; pos<map->enccount &&
+ (map->map[pos]==-1 || !SCWorthOutputting(sf->glyphs[map->map[pos]]) ||
+ (fv->show!=fv->filled && fv->show->glyphs[map->map[pos]]==NULL ));
+ ++pos );
+ if ( pos>=map->enccount ) {
+ int selpos = FVAnyCharSelected(fv);
+ char *iconv_name = map->enc->iconv_name ? map->enc->iconv_name :
+ map->enc->enc_name;
+ if ( strstr(iconv_name,"2022")!=NULL && selpos<0x2121 )
+ pos = 0x2121;
+ else if ( strstr(iconv_name,"EUC")!=NULL && selpos<0xa1a1 )
+ pos = 0xa1a1;
+ else if ( map->enc->is_tradchinese ) {
+ if ( strstrmatch(map->enc->enc_name,"HK")!=NULL &&
+ selpos<0x8140 )
+ pos = 0x8140;
+ else
+ pos = 0xa140;
+ } else if ( map->enc->is_japanese ) {
+ if ( strstrmatch(iconv_name,"SJIS")!=NULL ||
+ (strstrmatch(iconv_name,"JIS")!=NULL && strstrmatch(iconv_name,"SHIFT")!=NULL )) {
+ if ( selpos<0x8100 )
+ pos = 0x8100;
+ else if ( selpos<0xb000 )
+ pos = 0xb000;
+ }
+ } else if ( map->enc->is_korean ) {
+ if ( strstrmatch(iconv_name,"JOHAB")!=NULL ) {
+ if ( selpos<0x8431 )
+ pos = 0x8431;
+ } else { /* Wansung, EUC-KR */
+ if ( selpos<0xa1a1 )
+ pos = 0xa1a1;
+ }
+ } else if ( map->enc->is_simplechinese ) {
+ if ( strmatch(iconv_name,"EUC-CN")==0 && selpos<0xa1a1 )
+ pos = 0xa1a1;
+ }
+ if ( pos>=map->enccount )
+return;
+ }
+ } else if ( mid==MID_PrevDef ) {
+ for ( --pos; pos>=0 &&
+ (map->map[pos]==-1 || !SCWorthOutputting(sf->glyphs[map->map[pos]]) ||
+ (fv->show!=fv->filled && fv->show->glyphs[map->map[pos]]==NULL ));
+ --pos );
+ if ( pos<0 )
+return;
+ }
+ }
+ if ( pos<0 ) pos = map->enccount-1;
+ else if ( pos>= map->enccount ) pos = 0;
+ if ( pos>=0 && pos<map->enccount )
+ FVChangeChar(fv,pos);
+}
+
+static void FVMenuChangeChar(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ _FVMenuChangeChar(fv,mi->mid);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuGotoChar(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Goto(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int pos = GotoChar(fv->sf,fv->map);
+ FVChangeChar(fv,pos);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuLigatures(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Ligatures(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ SFShowLigatures(fv->sf,NULL);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuKernPairs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_KernPairs(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ SFKernClassTempDecompose(fv->sf,false);
+ SFShowKernPairs(fv->sf,NULL,NULL);
+ SFKernCleanup(fv->sf,false);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuAnchorPairs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_AnchorPairs(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ SFShowKernPairs(fv->sf,NULL,mi->ti.userdata);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuShowAtt(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ShowAtt(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ ShowAtt(fv->sf);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuDisplaySubs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_DisplaySubstitutions(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ if ( fv->cur_subtable!=0 ) {
+ fv->cur_subtable = NULL;
+ } else {
+ SplineFont *sf = fv->sf;
+ OTLookup *otf;
+ struct lookup_subtable *sub;
+ int cnt, k;
+ char **names = NULL;
+ if ( sf->cidmaster ) sf=sf->cidmaster;
+ for ( k=0; k<2; ++k ) {
+ cnt = 0;
+ for ( otf = sf->gsub_lookups; otf!=NULL; otf=otf->next ) {
+ if ( otf->lookup_type==gsub_single ) {
+ for ( sub=otf->subtables; sub!=NULL; sub=sub->next ) {
+ if ( names )
+ names[cnt] = sub->subtable_name;
+ ++cnt;
+ }
+ }
+ }
+ if ( cnt==0 )
+ break;
+ if ( names==NULL )
+ names = galloc((cnt+3) * sizeof(char *));
+ else {
+ names[cnt++] = "-";
+ names[cnt++] = _("New Lookup Subtable...");
+ names[cnt] = NULL;
+ }
+ }
+ sub = NULL;
+ if ( names!=NULL ) {
+ int ret = gwwv_choose(_("Display Substitution..."), (const char **) names, cnt, 0,
+ _("Pick a substitution to display in the window."));
+ if ( ret!=-1 )
+ sub = SFFindLookupSubtable(sf,names[ret]);
+ free(names);
+ if ( ret==-1 )
+return;
+ }
+ if ( sub==NULL )
+ sub = SFNewLookupSubtableOfType(sf,gsub_single,NULL);
+ if ( sub!=NULL )
+ fv->cur_subtable = sub;
+ }
+ GDrawRequestExpose(fv->v,NULL,false);
+}
+
+static void FVChangeDisplayFont(FontView *fv,BDFFont *bdf) {
+ int samesize=0;
+ int rcnt, ccnt;
+ int oldr, oldc;
+ int first_time = fv->show==NULL;
+
+ if ( fv->v==NULL ) /* Can happen in scripts */
+return;
+
+ if ( fv->show!=bdf ) {
+ oldc = fv->cbw*fv->colcnt;
+ oldr = fv->cbh*fv->rowcnt;
+
+ fv->show = bdf;
+ if ( fv->user_requested_magnify!=-1 )
+ fv->magnify=fv->user_requested_magnify;
+ else if ( bdf->pixelsize<20 ) {
+ if ( bdf->pixelsize<=9 )
+ fv->magnify = 3;
+ else
+ fv->magnify = 2;
+ samesize = ( fv->show && fv->cbw == (bdf->pixelsize*fv->magnify)+1 );
+ } else
+ fv->magnify = 1;
+ if ( !first_time && fv->cbw == fv->magnify*bdf->pixelsize+1 )
+ samesize = true;
+ fv->cbw = (bdf->pixelsize*fv->magnify)+1;
+ fv->cbh = (bdf->pixelsize*fv->magnify)+1+fv->lab_height+1;
+ fv->resize_expected = !samesize;
+ ccnt = fv->sf->desired_col_cnt;
+ rcnt = fv->sf->desired_row_cnt;
+ if ((( bdf->pixelsize<=fv->sf->display_size || bdf->pixelsize<=-fv->sf->display_size ) &&
+ fv->sf->top_enc!=-1 /* Not defaulting */ ) ||
+ bdf->pixelsize<=48 ) {
+ /* use the desired sizes */
+ } else {
+ if ( bdf->pixelsize>48 ) {
+ ccnt = 8;
+ rcnt = 2;
+ } else if ( bdf->pixelsize>=96 ) {
+ ccnt = 4;
+ rcnt = 1;
+ }
+ if ( !first_time ) {
+ if ( ccnt < oldc/fv->cbw )
+ ccnt = oldc/fv->cbw;
+ if ( rcnt < oldr/fv->cbh )
+ rcnt = oldr/fv->cbh;
+ }
+ }
+#if defined(FONTFORGE_CONFIG_GTK)
+ if ( samesize ) {
+ gtk_widget_queue_draw(fv->v);
+ } else {
+ gtk_widget_set_size_request(fv->v,ccnt*fv->cbw+1,rcnt*fv->cbh+1);
+ /* If we try to make the window smaller, we must force a resize */
+ /* of the whole system, else the size will remain the same */
+ /* Also when we get a resize event we must set the widget size */
+ /* to be minimal so that the user can resize */
+ if (( ccnt*fv->cbw < oldc || rcnt*fv->cbh < oldr ) && !first_time )
+ gtk_window_resize( GTK_WINDOW(widget), 1,1 );
+ }
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+ if ( samesize ) {
+ GDrawRequestExpose(fv->v,NULL,false);
+ } else {
+ GDrawResize(fv->gw,
+ ccnt*fv->cbw+1+GDrawPointsToPixels(fv->gw,_GScrollBar_Width),
+ rcnt*fv->cbh+1+fv->mbh+fv->infoh);
+ }
+#endif
+ }
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+struct md_data {
+ int done;
+ int ish;
+ FontView *fv;
+};
+
+static int md_e_h(GWindow gw, GEvent *e) {
+ if ( e->type==et_close ) {
+ struct md_data *d = GDrawGetUserData(gw);
+ d->done = true;
+ } else if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct md_data *d = GDrawGetUserData(gw);
+ static int masks[] = { fvm_baseline, fvm_origin, fvm_advanceat, fvm_advanceto, -1 };
+ int i, metrics;
+ if ( GGadgetGetCid(e->u.control.g)==10 ) {
+ metrics = 0;
+ for ( i=0; masks[i]!=-1 ; ++i )
+ if ( GGadgetIsChecked(GWidgetGetControl(gw,masks[i])))
+ metrics |= masks[i];
+ if ( d->ish )
+ default_fv_showhmetrics = d->fv->showhmetrics = metrics;
+ else
+ default_fv_showvmetrics = d->fv->showvmetrics = metrics;
+ }
+ d->done = true;
+ } else if ( e->type==et_char ) {
+#if 0
+ if ( e->u.chr.keysym == GK_F1 || e->u.chr.keysym == GK_Help ) {
+ help("fontinfo.html");
+return( true );
+ }
+#endif
+return( false );
+ }
+return( true );
+}
+
+static void FVMenuShowMetrics(GWindow fvgw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(fvgw);
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ struct md_data d;
+ GGadgetCreateData gcd[7];
+ GTextInfo label[6];
+ int metrics = mi->mid==MID_ShowHMetrics ? fv->showhmetrics : fv->showvmetrics;
+
+ d.fv = fv;
+ d.done = 0;
+ d.ish = mi->mid==MID_ShowHMetrics;
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = d.ish?_("Show H. Metrics..."):_("Show V. Metrics...");
+ pos.x = pos.y = 0;
+ pos.width =GDrawPointsToPixels(NULL,GGadgetScale(170));
+ pos.height = GDrawPointsToPixels(NULL,130);
+ gw = GDrawCreateTopWindow(NULL,&pos,md_e_h,&d,&wattrs);
+
+ memset(&label,0,sizeof(label));
+ memset(&gcd,0,sizeof(gcd));
+
+ label[0].text = (unichar_t *) _("Baseline");
+ label[0].text_is_1byte = true;
+ gcd[0].gd.label = &label[0];
+ gcd[0].gd.pos.x = 8; gcd[0].gd.pos.y = 8;
+ gcd[0].gd.flags = gg_enabled|gg_visible|(metrics&fvm_baseline?gg_cb_on:0);
+ gcd[0].gd.cid = fvm_baseline;
+ gcd[0].creator = GCheckBoxCreate;
+
+ label[1].text = (unichar_t *) _("Origin");
+ label[1].text_is_1byte = true;
+ gcd[1].gd.label = &label[1];
+ gcd[1].gd.pos.x = 8; gcd[1].gd.pos.y = gcd[0].gd.pos.y+16;
+ gcd[1].gd.flags = gg_enabled|gg_visible|(metrics&fvm_origin?gg_cb_on:0);
+ gcd[1].gd.cid = fvm_origin;
+ gcd[1].creator = GCheckBoxCreate;
+
+ label[2].text = (unichar_t *) _("Advance Width as a Line");
+ label[2].text_is_1byte = true;
+ gcd[2].gd.label = &label[2];
+ gcd[2].gd.pos.x = 8; gcd[2].gd.pos.y = gcd[1].gd.pos.y+16;
+ gcd[2].gd.flags = gg_enabled|gg_visible|gg_utf8_popup|(metrics&fvm_advanceat?gg_cb_on:0);
+ gcd[2].gd.cid = fvm_advanceat;
+ gcd[2].gd.popup_msg = (unichar_t *) _("Display the advance width as a line\nperpendicular to the advance direction");
+ gcd[2].creator = GCheckBoxCreate;
+
+ label[3].text = (unichar_t *) _("Advance Width as a Bar");
+ label[3].text_is_1byte = true;
+ gcd[3].gd.label = &label[3];
+ gcd[3].gd.pos.x = 8; gcd[3].gd.pos.y = gcd[2].gd.pos.y+16;
+ gcd[3].gd.flags = gg_enabled|gg_visible|gg_utf8_popup|(metrics&fvm_advanceto?gg_cb_on:0);
+ gcd[3].gd.cid = fvm_advanceto;
+ gcd[3].gd.popup_msg = (unichar_t *) _("Display the advance width as a bar under the glyph\nshowing the extent of the advance");
+ gcd[3].creator = GCheckBoxCreate;
+
+ label[4].text = (unichar_t *) _("_OK");
+ label[4].text_is_1byte = true;
+ label[4].text_in_resource = true;
+ gcd[4].gd.label = &label[4];
+ gcd[4].gd.pos.x = 20-3; gcd[4].gd.pos.y = GDrawPixelsToPoints(NULL,pos.height)-35-3;
+ gcd[4].gd.pos.width = -1; gcd[4].gd.pos.height = 0;
+ gcd[4].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ gcd[4].gd.cid = 10;
+ gcd[4].creator = GButtonCreate;
+
+ label[5].text = (unichar_t *) _("_Cancel");
+ label[5].text_is_1byte = true;
+ label[5].text_in_resource = true;
+ gcd[5].gd.label = &label[5];
+ gcd[5].gd.pos.x = -20; gcd[5].gd.pos.y = gcd[4].gd.pos.y+3;
+ gcd[5].gd.pos.width = -1; gcd[5].gd.pos.height = 0;
+ gcd[5].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ gcd[5].creator = GButtonCreate;
+
+ GGadgetsCreate(gw,gcd);
+
+ GDrawSetVisible(gw,true);
+ while ( !d.done )
+ GDrawProcessOneEvent(NULL);
+ GDrawDestroyWindow(gw);
+
+ SavePrefs();
+ GDrawRequestExpose(fv->v,NULL,false);
+}
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ShowMetrics(GtkMenuItem *menuitem, gpointer user_data) {
+ GtkWidget *dlg = create_FontViewShowMetrics();
+ int isv = strcmp(gtk_widget_get_name(menuitem),"show_v_metrics1")==0;
+ int metrics = !isv ? fv->showhmetrics : fv->showvmetrics;
+
+ if ( isv )
+ gtk_window_set_title(GTK_WINDOW(dlg), _("Show Vertical Metrics"));
+ gtk_toggle_button_set_active(lookup_widget(dlg,"baseline"),
+ (metrics&fvm_baseline)?true:false);
+ gtk_toggle_button_set_active(lookup_widget(dlg,"origin"),
+ (metrics&fvm_origin)?true:false);
+ gtk_toggle_button_set_active(lookup_widget(dlg,"AWBar"),
+ (metrics&fvm_advanceto)?true:false);
+ gtk_toggle_button_set_active(lookup_widget(dlg,"AWLine"),
+ (metrics&fvm_advanceat)?true:false);
+ if ( gtk_dialog_run( GTK_DIALOG (dlg)) == GTK_RESPONSE_ACCEPT ) {
+ metrics = 0;
+ if ( gtk_toggle_button_get_active(lookup_widget(dlg,"baseline")) )
+ metrics |= fvm_baseline;
+ if ( gtk_toggle_button_get_active(lookup_widget(dlg,"origin")) )
+ metrics |= fvm_origin;
+ if ( gtk_toggle_button_get_active(lookup_widget(dlg,"AWBar")) )
+ metrics |= fvm_advanceto;
+ if ( gtk_toggle_button_get_active(lookup_widget(dlg,"AWLine")) )
+ metrics |= fvm_advanceat;
+ if ( isv )
+ fv->showvmetrics = metrics;
+ else
+ fv->showhmetrics = metrics;
+ }
+ gtk_widget_destroy( dlg );
+}
+#endif
+
+void FVChangeDisplayBitmap(FontView *fv,BDFFont *bdf) {
+ FVChangeDisplayFont(fv,bdf);
+ fv->sf->display_size = fv->show->pixelsize;
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuSize(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw), *fvs, *fvss;
+ int dspsize = fv->filled->pixelsize;
+ int changedmodifier = false;
+
+ fv->magnify = 1;
+ fv->user_requested_magnify = -1;
+ if ( mi->mid == MID_24 )
+ default_fv_font_size = dspsize = 24;
+ else if ( mi->mid == MID_36 )
+ default_fv_font_size = dspsize = 36;
+ else if ( mi->mid == MID_48 )
+ default_fv_font_size = dspsize = 48;
+ else if ( mi->mid == MID_72 )
+ default_fv_font_size = dspsize = 72;
+ else if ( mi->mid == MID_96 )
+ default_fv_font_size = dspsize = 96;
+ else if ( mi->mid == MID_FitToEm ) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_PixelSize(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ int dspsize = fv->filled->pixelsize;
+ int changedmodifier = false;
+ G_CONST_RETURN gchar *name = gtk_widget_get_name(menuitem);
+
+ fv->magnify = 1;
+ fv->user_requested_magnify = -1;
+ if ( strstr(name,"24")!=NULL )
+ default_fv_font_size = dspsize = 24;
+ else if ( strstr(name,"36")!=NULL )
+ default_fv_font_size = dspsize = 36;
+ else if ( strstr(name,"48")!=NULL )
+ default_fv_font_size = dspsize = 48;
+ else if ( strstr(name,"72")!=NULL )
+ default_fv_font_size = dspsize = 72;
+ else if ( strstr(name,"96")!=NULL )
+ default_fv_font_size = dspsize = 96;
+ else if ( strcmp(name,"fit_to_em1")==0 ) {
+# endif
+ default_fv_bbsized = fv->bbsized = !fv->bbsized;
+ fv->sf->display_bbsized = fv->bbsized;
+ changedmodifier = true;
+ } else {
+ default_fv_antialias = fv->antialias = !fv->antialias;
+ fv->sf->display_antialias = fv->antialias;
+ changedmodifier = true;
+ }
+
+ SavePrefs();
+ if ( fv->filled!=fv->show || fv->filled->pixelsize != dspsize || changedmodifier ) {
+ BDFFont *new, *old;
+ for ( fvs=fv->sf->fv; fvs!=NULL; fvs=fvs->nextsame )
+ fvs->touched = false;
+ while ( 1 ) {
+ for ( fvs=fv->sf->fv; fvs!=NULL; fvs=fvs->nextsame )
+ if ( !fvs->touched )
+ break;
+ if ( fvs==NULL )
+ break;
+ old = fvs->filled;
+ new = SplineFontPieceMeal(fvs->sf,dspsize,
+ (fvs->antialias?pf_antialias:0)|(fvs->bbsized?pf_bbsized:0),
+ NULL);
+ for ( fvss=fvs; fvss!=NULL; fvss = fvss->nextsame ) {
+ if ( fvss->filled==old ) {
+ fvss->filled = new;
+ fvss->antialias = fvs->antialias;
+ fvss->bbsized = fvs->bbsized;
+ if ( fvss->show==old || fvss==fv )
+ FVChangeDisplayFont(fvss,new);
+ fvss->touched = true;
+ }
+ }
+ BDFFontFree(old);
+ }
+ fv->sf->display_size = -dspsize;
+ if ( fv->cidmaster!=NULL ) {
+ int i;
+ for ( i=0; i<fv->cidmaster->subfontcnt; ++i )
+ fv->cidmaster->subfonts[i]->display_size = -dspsize;
+ }
+ }
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuMagnify(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int magnify = fv->user_requested_magnify!=-1 ? fv->user_requested_magnify : fv->magnify;
+ char def[20], *end, *ret;
+ int val;
+ BDFFont *show = fv->show;
+
+ sprintf( def, "%d", magnify );
+ ret = gwwv_ask_string(_("Bitmap Magnification..."),def,_("Please specify a bitmap magnification factor."));
+ if ( ret==NULL )
+return;
+ val = strtol(ret,&end,10);
+ if ( val<1 || val>5 || *end!='\0' )
+ gwwv_post_error( _("Bad Number"),_("Bad Number") );
+ else {
+ fv->user_requested_magnify = val;
+ fv->show = fv->filled;
+ FVChangeDisplayFont(fv,show);
+ }
+ free(ret);
+}
+#endif
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuWSize(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int h,v;
+ extern int default_fv_col_count, default_fv_row_count;
+
+ if ( mi->mid == MID_32x8 ) {
+ h = 32; v=8;
+ } else if ( mi->mid == MID_16x4 ) {
+ h = 16; v=4;
+ } else {
+ h = 8; v=2;
+ }
+ GDrawResize(fv->gw,
+ h*fv->cbw+1+GDrawPointsToPixels(fv->gw,_GScrollBar_Width),
+ v*fv->cbh+1+fv->mbh+fv->infoh);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_WindowSize(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ G_CONST_RETURN gchar *name = gtk_widget_get_name(menuitem);
+ int h=8,v=2;
+ extern int default_fv_col_count, default_fv_row_count;
+
+ sscanf(name,"%dx%d", &h, &v );
+ gtk_widget_set_size_request(fv->v,h*fv->cbw+1,v*fv->cbh+1);
+# endif
+ fv->sf->desired_col_cnt = default_fv_col_count = h;
+ fv->sf->desired_row_cnt = default_fv_row_count = v;
+
+ SavePrefs();
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuGlyphLabel(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+
+ default_fv_glyphlabel = fv->glyphlabel = mi->mid;
+
+ GDrawRequestExpose(fv->v,NULL,false);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_GlyphLabel(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ G_CONST_RETURN gchar *name = gtk_widget_get_name(menuitem);
+
+ if ( strstr(name,"glyph_image")!=NULL )
+ default_fv_glyphlabel = fv->glyphlabel = gl_glyph;
+ else if ( strstr(name,"glyph_name")!=NULL )
+ default_fv_glyphlabel = fv->glyphlabel = gl_name;
+ else if ( strstr(name,"unicode")!=NULL )
+ default_fv_glyphlabel = fv->glyphlabel = gl_unicode;
+ else if ( strstr(name,"encoding")!=NULL )
+ default_fv_glyphlabel = fv->glyphlabel = gl_encoding;
+
+ gtk_widget_queue_draw(fv->v);
+# endif
+
+ SavePrefs();
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuShowBitmap(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ BDFFont *bdf = mi->ti.userdata;
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ShowBitmap(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ BDFFont *bdf = user_data;
+# endif
+
+ FVChangeDisplayBitmap(fv,bdf); /* Let's not change any of the others */
+}
+
+void FVShowFilled(FontView *fv) {
+ FontView *fvs;
+
+ fv->magnify = 1;
+ fv->user_requested_magnify = 1;
+ for ( fvs=fv->sf->fv; fvs!=NULL; fvs=fvs->nextsame )
+ if ( fvs->show!=fvs->filled )
+ FVChangeDisplayFont(fvs,fvs->filled);
+ fv->sf->display_size = -fv->filled->pixelsize;
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+void FVMetricsCenter(FontView *fv,int docenter) {
+ int i, gid;
+ SplineChar *sc;
+ DBounds bb;
+ IBounds ib;
+ real transform[6];
+ BVTFunc bvts[2];
+ BDFFont *bdf;
+
+ transform[0] = transform[3] = 1.0;
+ transform[1] = transform[2] = transform[5] = 0.0;
+ bvts[1].func = bvt_none;
+ bvts[0].func = bvt_transmove; bvts[0].y = 0;
+ if ( !fv->sf->onlybitmaps ) {
+ for ( i=0; i<fv->map->enccount; ++i ) {
+ if ( fv->selected[i] && (gid=fv->map->map[i])!=-1 &&
+ (sc = fv->sf->glyphs[gid])!=NULL ) {
+ SplineCharFindBounds(sc,&bb);
+ if ( docenter )
+ transform[4] = (sc->width-(bb.maxx-bb.minx))/2 - bb.minx;
+ else
+ transform[4] = (sc->width-(bb.maxx-bb.minx))/3 - bb.minx;
+ if ( transform[4]!=0 ) {
+ FVTrans(fv,sc,transform,NULL,fvt_dontmovewidth);
+ bvts[0].x = transform[4];
+ for ( bdf = fv->sf->bitmaps; bdf!=NULL; bdf=bdf->next )
+ if ( gid<bdf->glyphcnt && bdf->glyphs[gid]!=NULL )
+ BCTrans(bdf,bdf->glyphs[gid],bvts,fv);
+ }
+ }
+ }
+ } else {
+ double scale = (fv->sf->ascent+fv->sf->descent)/(double) (fv->show->pixelsize);
+ for ( i=0; i<fv->map->enccount; ++i ) {
+ if ( fv->selected[i] && (gid=fv->map->map[i])!=-1 &&
+ fv->sf->glyphs[gid]!=NULL ) {
+ BDFChar *bc = fv->show->glyphs[gid];
+ if ( bc==NULL ) bc = BDFMakeChar(fv->show,fv->map,i);
+ BDFCharFindBounds(bc,&ib);
+ if ( docenter )
+ transform[4] = scale * ((bc->width-(ib.maxx-ib.minx))/2 - ib.minx);
+ else
+ transform[4] = scale * ((bc->width-(ib.maxx-ib.minx))/3 - ib.minx);
+ if ( transform[4]!=0 ) {
+ FVTrans(fv,fv->sf->glyphs[gid],transform,NULL,fvt_dontmovewidth);
+ bvts[0].x = transform[4];
+ for ( bdf = fv->sf->bitmaps; bdf!=NULL; bdf=bdf->next )
+ if ( gid<bdf->glyphcnt && bdf->glyphs[gid]!=NULL )
+ BCTrans(bdf,bdf->glyphs[gid],bvts,fv);
+ }
+ }
+ }
+ }
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuCenter(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Center(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVMetricsCenter(fv,mi->mid==MID_Center);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuSetWidth(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+
+ if ( FVAnyCharSelected(fv)==-1 )
+return;
+ if ( mi->mid == MID_SetVWidth && !fv->sf->hasvmetrics )
+return;
+ FVSetWidth(fv,mi->mid==MID_SetWidth ?wt_width:
+ mi->mid==MID_SetLBearing?wt_lbearing:
+ mi->mid==MID_SetRBearing?wt_rbearing:
+ wt_vwidth);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Setwidth(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ G_CONST_RETURN gchar *name = gtk_widget_get_name(menuitem);
+
+ if ( FVAnyCharSelected(fv)==-1 )
+return;
+ if ( strcmp(name,"set_vertical_advance1")==0 && !fv->sf->hasvmetrics )
+return;
+ FVSetWidth(fv,strcmp(name,"set_width1")==0 ?wt_width:
+ strcmp(name,"set_lbearing1")==0?wt_lbearing:
+ strcmp(name,"set_rbearing1")==0?wt_rbearing:
+ wt_vwidth);
+# endif
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuAutoWidth(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_AutoWidth(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ FVAutoWidth(fv);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuAutoKern(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_AutoKern(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ FVAutoKern(fv);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuKernByClasses(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_KernClasses(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ ShowKernClasses(fv->sf,NULL,false);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuVKernByClasses(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_VKernClasses(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ ShowKernClasses(fv->sf,NULL,true);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuRemoveKern(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_RemoveKP(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ FVRemoveKerns(fv);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuRemoveVKern(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_RemoveVKP(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ FVRemoveVKerns(fv);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuKPCloseup(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_KernPairCloseup(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int i;
+
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] )
+ break;
+ KernPairD(fv->sf,i==fv->map->enccount?NULL:
+ fv->map->map[i]==-1?NULL:
+ fv->sf->glyphs[fv->map->map[i]],NULL,false);
+}
+
+# if defined(FONTFORGE_CONFIG_GDRAW)
+static void FVMenuVKernFromHKern(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_VKernFromH(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+ FVVKernFromHKern(fv);
+}
+#endif
+
+#ifndef LUA_FF_LIB
+static void FVAutoHint(FontView *fv) {
+ int i, cnt=0, gid;
+ BlueData *bd = NULL, _bd;
+ SplineChar *sc;
+
+ if ( fv->sf->mm==NULL ) {
+ QuickBlues(fv->sf,&_bd);
+ bd = &_bd;
+ }
+
+ /* Tick the ones we don't want to AH, untick the ones that need AH */
+ for ( gid = 0; gid<fv->sf->glyphcnt; ++gid ) if ( (sc = fv->sf->glyphs[gid])!=NULL )
+ sc->ticked = true;
+
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ SCWorthOutputting(sc = fv->sf->glyphs[gid]) ) {
+ ++cnt;
+ sc->ticked = false;
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_start_indicator(10,_("Auto Hinting Font..."),_("Auto Hinting Font..."),0,cnt,1);
+# endif
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 && SCWorthOutputting(fv->sf->glyphs[gid]) ) {
+ sc = fv->sf->glyphs[gid];
+ sc->manualhints = false;
+ /* Hint undoes are done in _SplineCharAutoHint */
+ SFSCAutoHint(sc,bd);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next())
+ break;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_end_indicator();
+# endif
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ GDrawRequestExpose(fv->v,NULL,false); /* Clear any changedsincelasthinted marks */
+#endif
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuAutoHint(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_AutoHint(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVAutoHint( fv );
+}
+#endif
+
+static void FVAutoHintSubs(FontView *fv) {
+ int i, cnt=0, gid;
+
+ if ( fv->sf->mm!=NULL && fv->sf->mm->apple )
+return;
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ SCWorthOutputting(fv->sf->glyphs[gid]) )
+ ++cnt;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_start_indicator(10,_("Finding Substitution Points..."),_("Finding Substitution Points..."),0,cnt,1);
+# endif
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 && SCWorthOutputting(fv->sf->glyphs[gid]) ) {
+ SplineChar *sc = fv->sf->glyphs[gid];
+ SCFigureHintMasks(sc);
+ SCUpdateAll(sc);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next())
+ break;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_end_indicator();
+# endif
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuAutoHintSubs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_AutoHintSubs(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVAutoHintSubs( fv );
+}
+#endif
+
+static void FVAutoCounter(FontView *fv) {
+ int i, cnt=0, gid;
+
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ SCWorthOutputting(fv->sf->glyphs[gid]) )
+ ++cnt;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_start_indicator(10,_("Finding Counter Masks..."),_("Finding Counter Masks..."),0,cnt,1);
+# endif
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 && SCWorthOutputting(fv->sf->glyphs[gid]) ) {
+ SplineChar *sc = fv->sf->glyphs[gid];
+ SCFigureCounterMasks(sc);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next())
+ break;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_end_indicator();
+# endif
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuAutoCounter(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_AutoCounter(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVAutoCounter( fv );
+}
+#endif
+
+static void FVDontAutoHint(FontView *fv) {
+ int i, gid;
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 && SCWorthOutputting(fv->sf->glyphs[gid]) ) {
+ SplineChar *sc = fv->sf->glyphs[gid];
+ sc->manualhints = true;
+ }
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuDontAutoHint(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_DontAutoHint(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVDontAutoHint( fv );
+}
+#endif
+
+static void FVAutoInstr(FontView *fv) {
+ BlueData bd;
+ int i, cnt=0, gid;
+
+ QuickBlues(fv->sf,&bd);
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ SCWorthOutputting(fv->sf->glyphs[gid]) )
+ ++cnt;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_start_indicator(10,_("Auto Instructing Font..."),_("Auto Instructing Font..."),0,cnt,1);
+# endif
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 && SCWorthOutputting(fv->sf->glyphs[gid]) ) {
+ SplineChar *sc = fv->sf->glyphs[gid];
+ SCAutoInstr(sc,&bd);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next())
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ break;
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_end_indicator();
+# endif
+}
+
+static void FVClearInstrs(FontView *fv) {
+ SplineChar *sc;
+ int i, gid;
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+
+ if ( !SFCloseAllInstrs(fv->sf))
+return;
+#endif
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 && SCWorthOutputting((sc = fv->sf->glyphs[gid])) ) {
+ if ( sc->ttf_instrs_len!=0 ) {
+ free(sc->ttf_instrs);
+ sc->ttf_instrs = NULL;
+ sc->ttf_instrs_len = 0;
+ sc->instructions_out_of_date = false;
+ SCCharChangedUpdate(sc);
+ sc->complained_about_ptnums = false;
+ }
+ }
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuAutoInstr(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_AutoInstr(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVAutoInstr( fv );
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuEditInstrs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_EditInstrs(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int index = FVAnyCharSelected(fv);
+ SplineChar *sc;
+ if ( index<0 )
+return;
+ sc = SFMakeChar(fv->sf,fv->map,index);
+ SCEditInstructions(sc);
+}
+#endif /* LUA_FF_LIB */
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuEditTable(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ SFEditTable(fv->sf,
+ mi->mid==MID_Editprep?CHR('p','r','e','p'):
+ mi->mid==MID_Editfpgm?CHR('f','p','g','m'):
+ mi->mid==MID_Editmaxp?CHR('m','a','x','p'):
+ CHR('c','v','t',' '));
+}
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_EditTable(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ G_CONST_RETURN gchar *name = gtk_widget_get_name(menuitem);
+ SFEditTable(fv->sf,
+ strcmp(name,"edit_prep1")==0?CHR('p','r','e','p'):
+ strcmp(name,"edit_fpgm1")==0?CHR('f','p','g','m'):
+ CHR('c','v','t',' '));
+}
+# endif
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuPrivateToCvt(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_PrivateToCvt(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ CVT_ImportPrivate(fv->sf);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuClearInstrs(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ClearInstrs(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVClearInstrs(fv);
+}
+#endif
+
+#ifndef LUA_FF_LIB
+static void FVClearHints(FontView *fv) {
+ int i, gid;
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 && SCWorthOutputting(fv->sf->glyphs[gid]) ) {
+ SplineChar *sc = fv->sf->glyphs[gid];
+ sc->manualhints = true;
+ SCPreserveHints(sc);
+ SCClearHints(sc);
+ SCUpdateAll(sc);
+#if 0
+ if ( !gwwv_progress_next())
+ break;
+#endif
+ }
+#if 0
+ gwwv_progress_end_indicator();
+#endif
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuClearHints(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ClearHints(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ FVClearHints(fv);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuClearWidthMD(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ClearWidthMD(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ int i, changed, gid;
+ MinimumDistance *md, *prev, *next;
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] &&
+ (gid = fv->map->map[i])!=-1 && SCWorthOutputting(fv->sf->glyphs[gid]) ) {
+ SplineChar *sc = fv->sf->glyphs[gid];
+ prev=NULL; changed = false;
+ for ( md=sc->md; md!=NULL; md=next ) {
+ next = md->next;
+ if ( md->sp2==NULL ) {
+ if ( prev==NULL )
+ sc->md = next;
+ else
+ prev->next = next;
+ chunkfree(md,sizeof(MinimumDistance));
+ changed = true;
+ } else
+ prev = md;
+ }
+ if ( changed ) {
+ sc->manualhints = true;
+ SCOutOfDateBackground(sc);
+ SCUpdateAll(sc);
+ }
+ }
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuHistograms(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ SFHistogram(fv->sf, NULL, FVAnyCharSelected(fv)!=-1?fv->selected:NULL,
+ fv->map,
+ mi->mid==MID_HStemHist ? hist_hstem :
+ mi->mid==MID_VStemHist ? hist_vstem :
+ hist_blues);
+}
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Histograms(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ G_CONST_RETURN gchar *name = gtk_widget_get_name(menuitem);
+ SFHistogram(fv->sf, NULL, FVAnyCharSelected(fv)!=-1?fv->selected:NULL,
+ strcmp(name,"hstem1")==0 ? hist_hstem :
+ strcmp(name,"vstem1")==0 ? hist_vstem :
+ hist_blues);
+# endif
+
+void FVSetTitle(FontView *fv) {
+# ifdef FONTFORGE_CONFIG_GDRAW
+ unichar_t *title, *ititle, *temp;
+ char *file=NULL;
+ char *enc;
+ int len;
+
+ if ( fv->gw==NULL ) /* In scripting */
+return;
+
+ enc = SFEncodingName(fv->sf,fv->normal?fv->normal:fv->map);
+ len = strlen(fv->sf->fontname)+1 + strlen(enc)+6;
+ if ( fv->cidmaster!=NULL ) {
+ if ( (file = fv->cidmaster->filename)==NULL )
+ file = fv->cidmaster->origname;
+ } else {
+ if ( (file = fv->sf->filename)==NULL )
+ file = fv->sf->origname;
+ }
+ if ( file!=NULL )
+ len += 2+strlen(file);
+ title = galloc((len+1)*sizeof(unichar_t));
+ uc_strcpy(title,fv->sf->fontname);
+ if ( fv->sf->changed )
+ uc_strcat(title,"*");
+ if ( file!=NULL ) {
+ uc_strcat(title," ");
+ temp = def2u_copy(GFileNameTail(file));
+ u_strcat(title,temp);
+ free(temp);
+ }
+ uc_strcat(title, " (" );
+ if ( fv->normal ) { utf82u_strcat(title,_("Compact")); uc_strcat(title," "); }
+ uc_strcat(title,enc);
+ uc_strcat(title, ")" );
+ free(enc);
+
+ ititle = uc_copy(fv->sf->fontname);
+ GDrawSetWindowTitles(fv->gw,title,ititle);
+ free(title);
+ free(ititle);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ char *title, *ititle, *temp;
+ char *file=NULL;
+ char *enc;
+ int len;
+ gsize read, written;
+
+ if ( fv->gw==NULL ) /* In scripting */
+return;
+
+ enc = SFEncodingName(fv->sf,fv->map);
+ len = strlen(fv->sf->fontname)+1 + strlen(enc)+4;
+ if ( fv->cidmaster!=NULL ) {
+ if ( (file = fv->cidmaster->filename)==NULL )
+ file = fv->cidmaster->origname;
+ } else {
+ if ( (file = fv->sf->filename)==NULL )
+ file = fv->sf->origname;
+ }
+ if ( file!=NULL )
+ len += 2+strlen(file);
+ title = galloc((len+1));
+ strcpy(title,fv->sf->fontname);
+ if ( fv->sf->changed )
+ strcat(title,"*");
+ if ( file!=NULL ) {
+ char *temp;
+ strcat(title," ");
+ temp = g_filename_to_utf8(GFileNameTail(file),-1,&read,&written,NULL);
+ strcat(title,temp);
+ free(temp);
+ }
+ strcat(title, " (" );
+ strcat(title,enc);
+ strcat(title, ")" );
+ free(enc);
+
+ gdk_window_set_icon_name( GTK_WIDGET(fv->gw)->window, fv->sf->fontname );
+ gtk_window_set_title( GTK_WINDOW(fv->gw), title );
+ free(title);
+# endif
+}
+
+static void CIDSetEncMap(FontView *fv, SplineFont *new ) {
+ int gcnt = new->glyphcnt;
+
+ if ( fv->cidmaster!=NULL && gcnt!=fv->sf->glyphcnt ) {
+ int i;
+ if ( fv->map->encmax<gcnt ) {
+ fv->map->map = grealloc(fv->map->map,gcnt*sizeof(int));
+ fv->map->backmap = grealloc(fv->map->backmap,gcnt*sizeof(int));
+ fv->map->backmax = fv->map->encmax = gcnt;
+ }
+ for ( i=0; i<gcnt; ++i )
+ fv->map->map[i] = fv->map->backmap[i] = i;
+ if ( gcnt<fv->map->enccount )
+ memset(fv->selected+gcnt,0,fv->map->enccount-gcnt);
+ else {
+ free(fv->selected);
+ fv->selected = gcalloc(gcnt,sizeof(char));
+ }
+ fv->map->enccount = gcnt;
+ }
+ fv->sf = new;
+ new->fv = fv;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FVSetTitle(fv);
+ FontViewReformatOne(fv);
+#endif
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuShowSubFont(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+static void FontViewMenu_ShowSubFont(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ SplineFont *new = mi->ti.userdata;
+ MetricsView *mv, *mvnext;
+ BDFFont *newbdf;
+ int wascompact = fv->normal!=NULL;
+
+ for ( mv=fv->sf->metrics; mv!=NULL; mv = mvnext ) {
+ /* Don't bother trying to fix up metrics views, just not worth it */
+ mvnext = mv->next;
+ GDrawDestroyWindow(mv->gw);
+ }
+ if ( wascompact ) {
+ EncMapFree(fv->map);
+ fv->map = fv->normal;
+ fv->normal = NULL;
+ fv->selected = grealloc(fv->selected,fv->map->enccount);
+ memset(fv->selected,0,fv->map->enccount);
+ }
+ CIDSetEncMap(fv,new);
+ if ( wascompact ) {
+ fv->normal = EncMapCopy(fv->map);
+ CompactEncMap(fv->map,fv->sf);
+ FontViewReformatOne(fv);
+ FVSetTitle(fv);
+ }
+ newbdf = SplineFontPieceMeal(fv->sf,fv->filled->pixelsize,
+ (fv->antialias?pf_antialias:0)|(fv->bbsized?pf_bbsized:0),
+ NULL);
+ BDFFontFree(fv->filled);
+ if ( fv->filled == fv->show )
+ fv->show = newbdf;
+ fv->filled = newbdf;
+ GDrawRequestExpose(fv->v,NULL,true);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuConvert2CID(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Convert2CID(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ SplineFont *cidmaster = fv->cidmaster;
+
+ if ( cidmaster!=NULL )
+return;
+ MakeCIDMaster(fv->sf,fv->map,false,NULL,NULL);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuConvertByCMap(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ConvertByCMap(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ SplineFont *cidmaster = fv->cidmaster;
+
+ if ( cidmaster!=NULL )
+return;
+ MakeCIDMaster(fv->sf,fv->map,true,NULL,NULL);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuFlatten(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Flatten(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ SplineFont *cidmaster = fv->cidmaster;
+
+ if ( cidmaster==NULL )
+return;
+ SFFlatten(cidmaster);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuFlattenByCMap(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_FlattenByCMap(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ SplineFont *cidmaster = fv->cidmaster;
+
+ if ( cidmaster==NULL )
+return;
+ SFFlattenByCMap(cidmaster,NULL);
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static void FVInsertInCID(FontView *fv,SplineFont *sf) {
+ SplineFont *cidmaster = fv->cidmaster;
+ SplineFont **subs;
+ int i;
+
+ subs = galloc((cidmaster->subfontcnt+1)*sizeof(SplineFont *));
+ for ( i=0; i<cidmaster->subfontcnt && cidmaster->subfonts[i]!=fv->sf; ++i )
+ subs[i] = cidmaster->subfonts[i];
+ subs[i] = sf;
+ if ( sf->uni_interp == ui_none || sf->uni_interp == ui_unset )
+ sf->uni_interp = cidmaster->uni_interp;
+ for ( ; i<cidmaster->subfontcnt ; ++i )
+ subs[i+1] = cidmaster->subfonts[i];
+ ++cidmaster->subfontcnt;
+ free(cidmaster->subfonts);
+ cidmaster->subfonts = subs;
+ cidmaster->changed = true;
+ sf->cidmaster = cidmaster;
+
+ CIDSetEncMap(fv,sf);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuInsertFont(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_InsertFont(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ SplineFont *cidmaster = fv->cidmaster;
+ SplineFont *new;
+ struct cidmap *map;
+ char *filename;
+ extern NameList *force_names_when_opening;
+
+ if ( cidmaster==NULL || cidmaster->subfontcnt>=255 ) /* Open type allows 1 byte to specify the fdselect */
+return;
+
+ filename = GetPostscriptFontName(NULL,false);
+ if ( filename==NULL )
+return;
+ new = LoadSplineFont(filename,0);
+ free(filename);
+ if ( new==NULL )
+return;
+ if ( new->fv == fv ) /* Already part of us */
+return;
+ if ( new->fv != NULL ) {
+ if ( new->fv->gw!=NULL )
+ GDrawRaise(new->fv->gw);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_post_error(_("Please close font"),_("Please close %s before inserting it into a CID font"),new->origname);
+#endif
+return;
+ }
+ EncMapFree(new->map);
+ if ( force_names_when_opening!=NULL )
+ SFRenameGlyphsToNamelist(new,force_names_when_opening );
+
+ map = FindCidMap(cidmaster->cidregistry,cidmaster->ordering,cidmaster->supplement,cidmaster);
+ SFEncodeToMap(new,map);
+ if ( !PSDictHasEntry(new->private,"lenIV"))
+ PSDictChangeEntry(new->private,"lenIV","1"); /* It's 4 by default, in CIDs the convention seems to be 1 */
+ new->display_antialias = fv->sf->display_antialias;
+ new->display_bbsized = fv->sf->display_bbsized;
+ new->display_size = fv->sf->display_size;
+ FVInsertInCID(fv,new);
+ CIDMasterAsDes(new);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuInsertBlank(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_InsertBlank(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ SplineFont *cidmaster = fv->cidmaster, *sf;
+ struct cidmap *map;
+
+ if ( cidmaster==NULL || cidmaster->subfontcnt>=255 ) /* Open type allows 1 byte to specify the fdselect */
+return;
+ map = FindCidMap(cidmaster->cidregistry,cidmaster->ordering,cidmaster->supplement,cidmaster);
+ sf = SplineFontBlank(MaxCID(map));
+ sf->glyphcnt = sf->glyphmax;
+ sf->cidmaster = cidmaster;
+ sf->display_antialias = fv->sf->display_antialias;
+ sf->display_bbsized = fv->sf->display_bbsized;
+ sf->display_size = fv->sf->display_size;
+ sf->private = gcalloc(1,sizeof(struct psdict));
+ PSDictChangeEntry(sf->private,"lenIV","1"); /* It's 4 by default, in CIDs the convention seems to be 1 */
+ FVInsertInCID(fv,sf);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuRemoveFontFromCID(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ char *buts[3];
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_RemoveFontFromCID(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ static char *buts[] = { GTK_STOCK_REMOVE, GTK_STOCK_CANCEL, NULL };
+# endif
+ SplineFont *cidmaster = fv->cidmaster, *sf = fv->sf, *replace;
+ int i;
+ MetricsView *mv, *mnext;
+ FontView *fvs;
+
+ if ( cidmaster==NULL || cidmaster->subfontcnt<=1 ) /* Can't remove last font */
+return;
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ buts[0] = _("_Remove"); buts[1] = _("_Cancel"); buts[2] = NULL;
+#endif
+ if ( gwwv_ask(_("_Remove Font"),(const char **) buts,0,1,_("Are you sure you wish to remove sub-font %1$.40s from the CID font %2$.40s"),
+ sf->fontname,cidmaster->fontname)==1 )
+return;
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ CharView *cv, *next;
+ for ( cv = sf->glyphs[i]->views; cv!=NULL; cv = next ) {
+ next = cv->next;
+ GDrawDestroyWindow(cv->gw);
+ }
+ }
+ GDrawProcessPendingEvents(NULL);
+ for ( mv=fv->sf->metrics; mv!=NULL; mv = mnext ) {
+ mnext = mv->next;
+ GDrawDestroyWindow(mv->gw);
+ }
+ GDrawSync(NULL);
+ GDrawProcessPendingEvents(NULL);
+ /* Just in case... */
+ GDrawSync(NULL);
+ GDrawProcessPendingEvents(NULL);
+
+ for ( i=0; i<cidmaster->subfontcnt; ++i )
+ if ( cidmaster->subfonts[i]==sf )
+ break;
+ replace = i==0?cidmaster->subfonts[1]:cidmaster->subfonts[i-1];
+ while ( i<cidmaster->subfontcnt-1 ) {
+ cidmaster->subfonts[i] = cidmaster->subfonts[i+1];
+ ++i;
+ }
+ --cidmaster->subfontcnt;
+
+ for ( fvs=fv->sf->fv; fvs!=NULL; fvs=fvs->nextsame ) {
+ if ( fvs->sf==sf )
+ CIDSetEncMap(fvs,replace);
+ }
+ FontViewReformatAll(fv->sf);
+ SplineFontFree(sf);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuCIDFontInfo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_CIDFontInfo(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ SplineFont *cidmaster = fv->cidmaster;
+
+ if ( cidmaster==NULL )
+return;
+ FontInfo(cidmaster,-1,false);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuChangeSupplement(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ChangeSupplement(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ SplineFont *cidmaster = fv->cidmaster;
+ struct cidmap *cidmap;
+ char buffer[20];
+ char *ret, *end;
+ int supple;
+
+ if ( cidmaster==NULL )
+return;
+ sprintf(buffer,"%d",cidmaster->supplement);
+ ret = gwwv_ask_string(_("Change Supplement..."),buffer,_("Please specify a new supplement for %.20s-%.20s"),
+ cidmaster->cidregistry,cidmaster->ordering);
+ if ( ret==NULL )
+return;
+ supple = strtol(ret,&end,10);
+ if ( *end!='\0' || supple<=0 ) {
+ free(ret);
+ gwwv_post_error( _("Bad Number"),_("Bad Number") );
+return;
+ }
+ free(ret);
+ if ( supple!=cidmaster->supplement ) {
+ /* this will make noises if it can't find an appropriate cidmap */
+ cidmap = FindCidMap(cidmaster->cidregistry,cidmaster->ordering,supple,cidmaster);
+ cidmaster->supplement = supple;
+ FVSetTitle(fv);
+ }
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuReencode(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ Encoding *enc = NULL;
+ EncMap *map;
+
+ enc = FindOrMakeEncoding(mi->ti.userdata);
+ if ( enc==&custom )
+ fv->map->enc = &custom;
+ else {
+ map = EncMapFromEncoding(fv->sf,enc);
+ fv->selected = grealloc(fv->selected,map->enccount);
+ memset(fv->selected,0,map->enccount);
+ EncMapFree(fv->map);
+ fv->map = map;
+ }
+ if ( fv->normal!=NULL ) {
+ EncMapFree(fv->normal);
+ fv->normal = NULL;
+ }
+ SFReplaceEncodingBDFProps(fv->sf,fv->map);
+ FVSetTitle(fv);
+ FontViewReformatOne(fv);
+}
+
+static void FVMenuForceEncode(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ Encoding *enc = NULL;
+ int oldcnt = fv->map->enccount;
+
+ enc = FindOrMakeEncoding(mi->ti.userdata);
+ SFForceEncoding(fv->sf,fv->map,enc);
+ if ( oldcnt < fv->map->enccount ) {
+ fv->selected = grealloc(fv->selected,fv->map->enccount);
+ memset(fv->selected+oldcnt,0,fv->map->enccount-oldcnt);
+ }
+ if ( fv->normal!=NULL ) {
+ EncMapFree(fv->normal);
+ fv->normal = NULL;
+ }
+ SFReplaceEncodingBDFProps(fv->sf,fv->map);
+ FVSetTitle(fv);
+ FontViewReformatOne(fv);
+}
+
+static void FVMenuDisplayByGroups(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+
+ DisplayGroups(fv);
+}
+
+static void FVMenuDefineGroups(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+
+ DefineGroups(fv);
+}
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Reencode(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+void FontViewMenu_ForceEncode(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuMMValid(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_MMValid(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ MMSet *mm = fv->sf->mm;
+
+ if ( mm==NULL )
+return;
+ MMValid(mm,true);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuCreateMM(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_CreateMM(GtkMenuItem *menuitem, gpointer user_data) {
+# endif
+ MMWizard(NULL);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuMMInfo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_MMInfo(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ MMSet *mm = fv->sf->mm;
+
+ if ( mm==NULL )
+return;
+ MMWizard(mm);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuChangeMMBlend(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ChangeDefWeights(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ MMSet *mm = fv->sf->mm;
+
+ if ( mm==NULL || mm->apple )
+return;
+ MMChangeBlend(mm,fv,false);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuBlendToNew(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_Blend(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ MMSet *mm = fv->sf->mm;
+
+ if ( mm==NULL )
+return;
+ MMChangeBlend(mm,fv,true);
+}
+#endif
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void cflistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ /*FontView *fv = (FontView *) GDrawGetUserData(gw);*/
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_AllFonts:
+ mi->ti.checked = !onlycopydisplayed;
+ break;
+ case MID_DisplayedFont:
+ mi->ti.checked = onlycopydisplayed;
+ break;
+ case MID_CharName:
+ mi->ti.checked = copymetadata;
+ break;
+ case MID_TTFInstr:
+ mi->ti.checked = copyttfinstr;
+ break;
+ }
+ }
+}
+
+static void sllistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ fv = fv;
+}
+
+static void htlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int anychars = FVAnyCharSelected(fv);
+ int multilayer = fv->sf->multilayer;
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_AutoHint:
+ mi->ti.disabled = anychars==-1 || multilayer;
+ break;
+ case MID_HintSubsPt:
+ mi->ti.disabled = fv->sf->order2 || anychars==-1 || multilayer;
+ if ( fv->sf->mm!=NULL && fv->sf->mm->apple )
+ mi->ti.disabled = true;
+ break;
+ case MID_AutoCounter: case MID_DontAutoHint:
+ mi->ti.disabled = fv->sf->order2 || anychars==-1 || multilayer;
+ break;
+ case MID_AutoInstr: case MID_EditInstructions:
+ mi->ti.disabled = !fv->sf->order2 || anychars==-1 || multilayer;
+ break;
+ case MID_PrivateToCvt:
+ mi->ti.disabled = !fv->sf->order2 || multilayer ||
+ fv->sf->private==NULL || fv->sf->cvt_dlg!=NULL;
+ break;
+ case MID_Editfpgm: case MID_Editprep: case MID_Editcvt: case MID_Editmaxp:
+ mi->ti.disabled = !fv->sf->order2 || multilayer;
+ break;
+ case MID_ClearHints: case MID_ClearWidthMD: case MID_ClearInstrs:
+ mi->ti.disabled = anychars==-1;
+ break;
+ }
+ }
+}
+
+static void fllistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int anychars = FVAnyCharSelected(fv);
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_Revert:
+ mi->ti.disabled = fv->sf->origname==NULL || fv->sf->new;
+ break;
+ case MID_RevertToBackup:
+ /* We really do want to use filename here and origname above */
+ mi->ti.disabled = true;
+ if ( fv->sf->filename!=NULL ) {
+ if ( fv->sf->backedup == bs_dontknow ) {
+ char *buf = galloc(strlen(fv->sf->filename)+20);
+ strcpy(buf,fv->sf->filename);
+ if ( fv->sf->compression!=0 )
+ strcat(buf,compressors[fv->sf->compression-1].ext);
+ strcat(buf,"~");
+ if ( access(buf,F_OK)==0 )
+ fv->sf->backedup = bs_backedup;
+ else
+ fv->sf->backedup = bs_not;
+ free(buf);
+ }
+ if ( fv->sf->backedup == bs_backedup )
+ mi->ti.disabled = false;
+ }
+ break;
+ case MID_RevertGlyph:
+ mi->ti.disabled = fv->sf->origname==NULL || fv->sf->sfd_version<2 || anychars==-1 || fv->sf->compression!=0;
+ break;
+ case MID_Recent:
+ mi->ti.disabled = !RecentFilesAny();
+ break;
+ case MID_ScriptMenu:
+ mi->ti.disabled = script_menu_names[0]==NULL;
+ break;
+ case MID_Print:
+ mi->ti.disabled = fv->sf->onlybitmaps;
+ break;
+ case MID_Display:
+ mi->ti.disabled = (fv->sf->onlybitmaps && fv->sf->bitmaps==NULL) ||
+ fv->sf->multilayer;
+ break;
+ }
+ }
+}
+
+static void edlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int pos = FVAnyCharSelected(fv), i, gid;
+ int not_pasteable = pos==-1 ||
+ (!CopyContainsSomething() &&
+#ifndef _NO_LIBPNG
+ !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/png") &&
+#endif
+#ifndef _NO_LIBXML
+ !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/svg") &&
+#endif
+ !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/bmp") &&
+ !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/eps") &&
+ !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/ps"));
+ RefChar *base = CopyContainsRef(fv->sf);
+ int base_enc = base!=NULL ? fv->map->backmap[base->orig_pos] : -1;
+
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_Paste: case MID_PasteInto:
+ mi->ti.disabled = not_pasteable;
+ break;
+#ifdef FONTFORGE_CONFIG_PASTEAFTER
+ case MID_PasteAfter:
+ mi->ti.disabled = not_pasteable || pos<0;
+ break;
+#endif
+ case MID_SameGlyphAs:
+ mi->ti.disabled = not_pasteable || base==NULL || fv->cidmaster!=NULL ||
+ base_enc==-1 ||
+ fv->selected[base_enc]; /* Can't be self-referential */
+ break;
+ case MID_Join:
+ case MID_Cut: case MID_Copy: case MID_Clear:
+ case MID_CopyWidth: case MID_CopyLBearing: case MID_CopyRBearing:
+ case MID_CopyRef: case MID_UnlinkRef:
+ case MID_RemoveUndoes: case MID_CopyFgToBg:
+ case MID_RplRef:
+ mi->ti.disabled = pos==-1;
+ break;
+ case MID_CopyLookupData:
+ mi->ti.disabled = pos==-1 || (fv->sf->gpos_lookups==NULL && fv->sf->gsub_lookups==NULL);
+ break;
+ case MID_CopyVWidth:
+ mi->ti.disabled = pos==-1 || !fv->sf->hasvmetrics;
+ break;
+ case MID_ClearBackground:
+ mi->ti.disabled = true;
+ if ( pos!=-1 && !( onlycopydisplayed && fv->filled!=fv->show )) {
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ fv->sf->glyphs[gid]!=NULL )
+ if ( fv->sf->glyphs[gid]->layers[ly_back].images!=NULL ||
+ fv->sf->glyphs[gid]->layers[ly_back].splines!=NULL ) {
+ mi->ti.disabled = false;
+ break;
+ }
+ }
+ break;
+ case MID_Undo:
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ fv->sf->glyphs[gid]!=NULL )
+ if ( fv->sf->glyphs[gid]->layers[ly_fore].undoes!=NULL )
+ break;
+ mi->ti.disabled = i==fv->map->enccount;
+ break;
+ case MID_Redo:
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ fv->sf->glyphs[gid]!=NULL )
+ if ( fv->sf->glyphs[gid]->layers[ly_fore].redoes!=NULL )
+ break;
+ mi->ti.disabled = i==fv->map->enccount;
+ break;
+ }
+ }
+}
+
+static void trlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int anychars = FVAnyCharSelected(fv);
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_Transform:
+ mi->ti.disabled = anychars==-1;
+ break;
+ case MID_NLTransform: case MID_POV:
+ mi->ti.disabled = anychars==-1 || fv->sf->onlybitmaps;
+ break;
+ }
+ }
+}
+
+static void ellistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int anychars = FVAnyCharSelected(fv), gid;
+ int anybuildable, anytraceable;
+ int order2 = fv->sf->order2;
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_CharInfo:
+ mi->ti.disabled = anychars<0 || (gid = fv->map->map[anychars])==-1 ||
+ (fv->cidmaster!=NULL && fv->sf->glyphs[gid]==NULL);
+ break;
+ case MID_StrikeInfo:
+ mi->ti.disabled = fv->sf->bitmaps==NULL;
+ break;
+ case MID_FindProblems:
+ mi->ti.disabled = anychars==-1;
+ break;
+ case MID_Transform:
+ mi->ti.disabled = anychars==-1;
+ /* some Transformations make sense on bitmaps now */
+ break;
+ case MID_AddExtrema:
+ mi->ti.disabled = anychars==-1 || fv->sf->onlybitmaps;
+ break;
+ case MID_Simplify:
+ case MID_Stroke: case MID_RmOverlap:
+ mi->ti.disabled = anychars==-1 || fv->sf->onlybitmaps;
+ break;
+ case MID_MetaFont: case MID_Effects:
+ mi->ti.disabled = anychars==-1 || fv->sf->onlybitmaps || order2;
+ break;
+ case MID_Round: case MID_Correct:
+ mi->ti.disabled = anychars==-1 || fv->sf->onlybitmaps;
+ break;
+#ifdef FONTFORGE_CONFIG_TILEPATH
+ case MID_TilePath:
+ mi->ti.disabled = anychars==-1 || fv->sf->onlybitmaps || ClipBoardToSplineSet()==NULL || order2;
+ break;
+#endif
+ case MID_AvailBitmaps:
+ mi->ti.disabled = fv->sf->mm!=NULL;
+ break;
+ case MID_RegenBitmaps: case MID_RemoveBitmaps:
+ mi->ti.disabled = fv->sf->bitmaps==NULL || fv->sf->onlybitmaps ||
+ fv->sf->mm!=NULL;
+ break;
+ case MID_BuildAccent:
+ anybuildable = false;
+ if ( anychars!=-1 ) {
+ int i;
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] ) {
+ SplineChar *sc=NULL, dummy;
+ gid = fv->map->map[i];
+ if ( gid!=-1 )
+ sc = fv->sf->glyphs[gid];
+ if ( sc==NULL )
+ sc = SCBuildDummy(&dummy,fv->sf,fv->map,i);
+ if ( SFIsSomethingBuildable(fv->sf,sc,false) ||
+ SFIsDuplicatable(fv->sf,sc)) {
+ anybuildable = true;
+ break;
+ }
+ }
+ }
+ mi->ti.disabled = !anybuildable;
+ break;
+ case MID_Autotrace:
+ anytraceable = false;
+ if ( FindAutoTraceName()!=NULL && anychars!=-1 ) {
+ int i;
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ fv->sf->glyphs[gid]!=NULL &&
+ fv->sf->glyphs[gid]->layers[ly_back].images!=NULL ) {
+ anytraceable = true;
+ break;
+ }
+ }
+ mi->ti.disabled = !anytraceable;
+ break;
+ case MID_MergeFonts:
+ mi->ti.disabled = fv->sf->bitmaps!=NULL && fv->sf->onlybitmaps;
+ break;
+ case MID_FontCompare:
+ mi->ti.disabled = fv_list->next==NULL;
+ break;
+ case MID_InterpolateFonts:
+ mi->ti.disabled = fv->sf->onlybitmaps;
+ break;
+ }
+ }
+}
+
+static void mtlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int anychars = FVAnyCharSelected(fv);
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_Center: case MID_Thirds: case MID_SetWidth:
+ case MID_SetLBearing: case MID_SetRBearing:
+ mi->ti.disabled = anychars==-1;
+ break;
+ case MID_SetVWidth:
+ mi->ti.disabled = anychars==-1 || !fv->sf->hasvmetrics;
+ break;
+ case MID_VKernByClass:
+ case MID_VKernFromH:
+ case MID_RmVKern:
+ mi->ti.disabled = !fv->sf->hasvmetrics;
+ break;
+ }
+ }
+}
+
+#if HANYANG
+static void hglistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ if ( mi->mid==MID_BuildSyllables || mi->mid==MID_ModifyComposition )
+ mi->ti.disabled = fv->sf->rules==NULL;
+ }
+}
+
+static GMenuItem2 hglist[] = {
+ { { (unichar_t *) N_("_New Composition..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'N' }, H_("New Composition...|Ctl+Shft+N"), NULL, NULL, MenuNewComposition },
+ { { (unichar_t *) N_("_Modify Composition..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Modify Composition...|No Shortcut"), NULL, NULL, FVMenuModifyComposition, MID_ModifyComposition },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Build Syllables"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Build Syllables|No Shortcut"), NULL, NULL, FVMenuBuildSyllables, MID_BuildSyllables },
+ { NULL }
+};
+#endif
+
+static void balistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ if ( mi->mid==MID_BuildAccent || mi->mid==MID_BuildComposite ) {
+ int anybuildable = false;
+ int onlyaccents = mi->mid==MID_BuildAccent;
+ int i, gid;
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] ) {
+ SplineChar *sc=NULL, dummy;
+ if ( (gid=fv->map->map[i])!=-1 )
+ sc = fv->sf->glyphs[gid];
+ if ( sc==NULL )
+ sc = SCBuildDummy(&dummy,fv->sf,fv->map,i);
+ if ( SFIsSomethingBuildable(fv->sf,sc,onlyaccents)) {
+ anybuildable = true;
+ break;
+ }
+ }
+ mi->ti.disabled = !anybuildable;
+ } else if ( mi->mid==MID_BuildDuplicates ) {
+ int anybuildable = false;
+ int i, gid;
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] ) {
+ SplineChar *sc=NULL, dummy;
+ if ( (gid=fv->map->map[i])!=-1 )
+ sc = fv->sf->glyphs[gid];
+ if ( sc==NULL )
+ sc = SCBuildDummy(&dummy,fv->sf,fv->map,i);
+ if ( SFIsDuplicatable(fv->sf,sc)) {
+ anybuildable = true;
+ break;
+ }
+ }
+ mi->ti.disabled = !anybuildable;
+ }
+ }
+}
+
+static void delistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int i = FVAnyCharSelected(fv);
+ int gid = i<0 ? -1 : fv->map->map[i];
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_ShowDependentRefs:
+ mi->ti.disabled = gid<0 || fv->sf->glyphs[gid]==NULL ||
+ fv->sf->glyphs[gid]->dependents == NULL;
+ break;
+ case MID_ShowDependentSubs:
+ mi->ti.disabled = gid<0 || fv->sf->glyphs[gid]==NULL ||
+ !SCUsedBySubs(fv->sf->glyphs[gid]);
+ break;
+ }
+ }
+}
+
+static GMenuItem2 dummyitem[] = { { (unichar_t *) N_("Font|_New"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'N' }, NULL };
+static GMenuItem2 fllist[] = {
+ { { (unichar_t *) N_("Font|_New"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'N' }, H_("New|Ctl+N"), NULL, NULL, MenuNew },
+#if HANYANG
+ { { (unichar_t *) N_("_Hangul"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, NULL, hglist, hglistcheck, NULL, 0 },
+#endif
+ { { (unichar_t *) N_("_Open"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'O' }, H_("Open|Ctl+O"), NULL, NULL, MenuOpen },
+ { { (unichar_t *) N_("Recen_t"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 't' }, NULL, dummyitem, MenuRecentBuild, NULL, MID_Recent },
+ { { (unichar_t *) N_("_Close"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Close|Ctl+Shft+Q"), NULL, NULL, FVMenuClose },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Save"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Save|Ctl+S"), NULL, NULL, FVMenuSave },
+ { { (unichar_t *) N_("S_ave as..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'a' }, H_("Save as...|Ctl+Shft+S"), NULL, NULL, FVMenuSaveAs },
+ { { (unichar_t *) N_("Save A_ll"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Save All|Alt+Ctl+S"), NULL, NULL, MenuSaveAll },
+ { { (unichar_t *) N_("_Generate Fonts..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'G' }, H_("Generate Fonts...|Ctl+Shft+G"), NULL, NULL, FVMenuGenerate },
+ { { (unichar_t *) N_("Generate Mac _Family..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Generate Mac Family...|Alt+Ctl+G"), NULL, NULL, FVMenuGenerateFamily },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Import..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Import...|Ctl+Shft+I"), NULL, NULL, FVMenuImport },
+ { { (unichar_t *) N_("_Merge Feature Info..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Merge Kern Info...|Alt+Ctl+Shft+K"), NULL, NULL, FVMenuMergeKern },
+ { { (unichar_t *) N_("_Revert File"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Revert File|Ctl+Shft+R"), NULL, NULL, FVMenuRevert, MID_Revert },
+ { { (unichar_t *) N_("Revert To _Backup"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Revert To Backup|No Shortcut"), NULL, NULL, FVMenuRevertBackup, MID_RevertToBackup },
+ { { (unichar_t *) N_("Revert Gl_yph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Revert Glyph|Alt+Ctl+R"), NULL, NULL, FVMenuRevertGlyph, MID_RevertGlyph },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Print..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Print...|Ctl+P"), NULL, NULL, FVMenuPrint, MID_Print },
+ { { (unichar_t *) N_("_Display..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'D' }, H_("Display...|Alt+Ctl+P"), NULL, NULL, FVMenuDisplay, MID_Display },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+#if !defined(_NO_FFSCRIPT) || !defined(_NO_PYTHON)
+ { { (unichar_t *) N_("E_xecute Script..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'x' }, H_("Execute Script...|Ctl+."), NULL, NULL, FVMenuExecute },
+ { { (unichar_t *) N_("Script Menu"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'r' }, H_("Script Menu|No Shortcut"), dummyitem, MenuScriptsBuild, NULL, MID_ScriptMenu },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+#endif
+ { { (unichar_t *) N_("Pr_eferences..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'e' }, H_("Preferences...|No Shortcut"), NULL, NULL, MenuPrefs },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Quit"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'Q' }, H_("Quit|Ctl+Q"), NULL, NULL, FVMenuExit },
+ { NULL }
+};
+
+static GMenuItem2 cflist[] = {
+ { { (unichar_t *) N_("_All Fonts"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'A' }, H_("All Fonts|No Shortcut"), NULL, NULL, FVMenuCopyFrom, MID_AllFonts },
+ { { (unichar_t *) N_("_Displayed Font"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'D' }, H_("Displayed Font|No Shortcut"), NULL, NULL, FVMenuCopyFrom, MID_DisplayedFont },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Glyph _Metadata"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'N' }, H_("Glyph Metadata|No Shortcut"), NULL, NULL, FVMenuCopyFrom, MID_CharName },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_TrueType Instructions"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'N' }, H_("TrueType Instructions|No Shortcut"), NULL, NULL, FVMenuCopyFrom, MID_TTFInstr },
+ { NULL }
+};
+
+static GMenuItem2 sclist[] = {
+ { { (unichar_t *) N_("Color|Default"), &def_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) COLOR_DEFAULT, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Default|No Shortcut"), NULL, NULL, FVMenuSelectColor },
+ { { NULL, &white_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0xffffff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSelectColor },
+ { { NULL, &red_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0xff0000, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSelectColor },
+ { { NULL, &green_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0x00ff00, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSelectColor },
+ { { NULL, &blue_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0x0000ff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSelectColor },
+ { { NULL, &yellow_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0xffff00, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSelectColor },
+ { { NULL, &cyan_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0x00ffff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSelectColor },
+ { { NULL, &magenta_image, COLOR_DEFAULT, COLOR_DEFAULT, (void *) 0xff00ff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' }, NULL, NULL, NULL, FVMenuSelectColor },
+ { NULL }
+};
+
+static GMenuItem2 sllist[] = {
+ { { (unichar_t *) N_("Select _All"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Select All|Ctl+A"), NULL, NULL, FVMenuSelectAll },
+ { { (unichar_t *) N_("_Invert Selection"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Invert Selection|Ctl+Escape"), NULL, NULL, FVMenuInvertSelection },
+ { { (unichar_t *) N_("_Deselect All"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Deselect All|Escape"), NULL, NULL, FVMenuDeselectAll },
+ { { (unichar_t *) N_("_Select by Color"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Select by Color|No Shortcut"), sclist },
+ { { (unichar_t *) N_("Select by _Name..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Select by Name...|No Shortcut"), NULL, NULL, FVMenuSelectByName },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Glyphs Worth Outputting"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Glyphs Worth Outputting|No Shortcut"), NULL,NULL, FVMenuSelectWorthOutputting },
+ { { (unichar_t *) N_("_Changed Glyphs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Changed Glyphs|No Shortcut"), NULL,NULL, FVMenuSelectChanged },
+ { { (unichar_t *) N_("_Hinting Needed"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Hinting Needed|No Shortcut"), NULL,NULL, FVMenuSelectHintingNeeded },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Selec_t By Lookup Subtable..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Select By Lookup Subtable...|No Shortcut"), NULL, NULL, FVMenuSelectByPST },
+ { NULL }
+};
+
+static GMenuItem2 edlist[] = {
+ { { (unichar_t *) N_("_Undo"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 1, 0, 'U' }, H_("Undo|Ctl+Z"), NULL, NULL, FVMenuUndo, MID_Undo },
+ { { (unichar_t *) N_("_Redo"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Redo|Ctl+Y"), NULL, NULL, FVMenuRedo, MID_Redo},
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Cu_t"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 't' }, H_("Cut|Ctl+X"), NULL, NULL, FVMenuCut, MID_Cut },
+ { { (unichar_t *) N_("_Copy"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Copy|Ctl+C"), NULL, NULL, FVMenuCopy, MID_Copy },
+ { { (unichar_t *) N_("C_opy Reference"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Copy Reference|Ctl+G"), NULL, NULL, FVMenuCopyRef, MID_CopyRef },
+ { { (unichar_t *) N_("Copy _Lookup Data"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Copy Lookup Data|Alt+Ctl+C"), NULL, NULL, FVMenuCopyLookupData, MID_CopyLookupData },
+ { { (unichar_t *) N_("Copy _Width"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'W' }, H_("Copy Width|Ctl+W"), NULL, NULL, FVMenuCopyWidth, MID_CopyWidth },
+ { { (unichar_t *) N_("Copy _VWidth"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("Copy VWidth|No Shortcut"), NULL, NULL, FVMenuCopyWidth, MID_CopyVWidth },
+ { { (unichar_t *) N_("Co_py LBearing"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'p' }, H_("Copy LBearing|No Shortcut"), NULL, NULL, FVMenuCopyWidth, MID_CopyLBearing },
+ { { (unichar_t *) N_("Copy RBearin_g"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'g' }, H_("Copy RBearing|No Shortcut"), NULL, NULL, FVMenuCopyWidth, MID_CopyRBearing },
+ { { (unichar_t *) N_("_Paste"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Paste|Ctl+V"), NULL, NULL, FVMenuPaste, MID_Paste },
+ { { (unichar_t *) N_("Paste Into"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Paste Into|Ctl+Shft+V"), NULL, NULL, FVMenuPasteInto, MID_PasteInto },
+#ifdef FONTFORGE_CONFIG_PASTEAFTER
+ { { (unichar_t *) N_("Paste After"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Paste After|Alt+Ctl+Shft+V"), NULL, NULL, FVMenuPasteAfter, MID_PasteAfter },
+#endif
+ { { (unichar_t *) N_("Sa_me Glyph As"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'm' }, H_("Same Glyph As|No Shortcut"), NULL, NULL, FVMenuSameGlyphAs, MID_SameGlyphAs },
+ { { (unichar_t *) N_("C_lear"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Clear|No Shortcut"), NULL, NULL, FVMenuClear, MID_Clear },
+ { { (unichar_t *) N_("Clear _Background"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Clear Background|No Shortcut"), NULL, NULL, FVMenuClearBackground, MID_ClearBackground },
+ { { (unichar_t *) N_("Copy _Fg To Bg"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Copy Fg To Bg|Ctl+Shft+C"), NULL, NULL, FVMenuCopyFgBg, MID_CopyFgToBg },
+ { { (unichar_t *) N_("_Join"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'J' }, H_("Join|Ctl+Shft+J"), NULL, NULL, FVMenuJoin, MID_Join },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Select"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, NULL, sllist, sllistcheck },
+ { { (unichar_t *) N_("F_ind / Replace..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'i' }, H_("Find / Replace...|Alt+Ctl+F"), NULL, NULL, FVMenuFindRpl },
+ { { (unichar_t *) N_("Replace with Reference"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'i' }, H_("Replace with Reference|Alt+Ctl+Shft+F"), NULL, NULL, FVMenuReplaceWithRef, MID_RplRef },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("U_nlink Reference"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'U' }, H_("Unlink Reference|Ctl+U"), NULL, NULL, FVMenuUnlinkRef, MID_UnlinkRef },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Copy _From"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, NULL, cflist, cflistcheck, NULL, 0 },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Remo_ve Undoes"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'e' }, H_("Remove Undoes|No Shortcut"), NULL, NULL, FVMenuRemoveUndoes, MID_RemoveUndoes },
+ { NULL }
+};
+
+static GMenuItem2 smlist[] = {
+ { { (unichar_t *) N_("_Simplify"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Simplify|Ctl+Shft+M"), NULL, NULL, FVMenuSimplify, MID_Simplify },
+ { { (unichar_t *) N_("Simplify More..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Simplify More...|Alt+Ctl+Shft+M"), NULL, NULL, FVMenuSimplifyMore, MID_SimplifyMore },
+ { { (unichar_t *) N_("Clea_nup Glyph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'n' }, H_("Cleanup Glyph|No Shortcut"), NULL, NULL, FVMenuCleanup, MID_CleanupGlyph },
+ { { (unichar_t *) N_("Canonical Start _Point"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'n' }, H_("Canonical Start Point|No Shortcut"), NULL, NULL, FVMenuCanonicalStart, MID_CanonicalStart },
+ { { (unichar_t *) N_("Canonical _Contours"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'n' }, H_("Canonical Contours|No Shortcut"), NULL, NULL, FVMenuCanonicalContours, MID_CanonicalContours },
+ { NULL }
+};
+
+static GMenuItem2 rmlist[] = {
+ { { (unichar_t *) N_("_Remove Overlap"), &GIcon_rmoverlap, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'O' }, H_("Remove Overlap|Ctl+Shft+O"), NULL, NULL, FVMenuOverlap, MID_RmOverlap },
+ { { (unichar_t *) N_("_Intersect"), &GIcon_intersection, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Intersect|No Shortcut"), NULL, NULL, FVMenuOverlap, MID_Intersection },
+ { { (unichar_t *) N_("_Find Intersections"), &GIcon_findinter, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'O' }, H_("Find Intersections|No Shortcut"), NULL, NULL, FVMenuOverlap, MID_FindInter },
+ { NULL }
+};
+
+static GMenuItem2 eflist[] = {
+ { { (unichar_t *) N_("_Inline"), &GIcon_inline, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'O' }, H_("Inline|No Shortcut"), NULL, NULL, FVMenuInline },
+ { { (unichar_t *) N_("_Outline"), &GIcon_outline, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Outline|No Shortcut"), NULL, NULL, FVMenuOutline },
+ { { (unichar_t *) N_("_Shadow"), &GIcon_shadow, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Shadow|No Shortcut"), NULL, NULL, FVMenuShadow },
+ { { (unichar_t *) N_("_Wireframe"), &GIcon_wireframe, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, true, 0, 0, 0, 0, 1, 1, 0, 'W' }, H_("Wireframe|No Shortcut"), NULL, NULL, FVMenuWireframe },
+ { NULL }
+};
+
+static GMenuItem2 balist[] = {
+ { { (unichar_t *) N_("_Build Accented Glyph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Build Accented Glyph|Ctl+Shft+A"), NULL, NULL, FVMenuBuildAccent, MID_BuildAccent },
+ { { (unichar_t *) N_("Build _Composite Glyph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Build Composite Glyph|No Shortcut"), NULL, NULL, FVMenuBuildComposite, MID_BuildComposite },
+ { { (unichar_t *) N_("Buil_d Duplicate Glyph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Build Duplicate Glyph|No Shortcut"), NULL, NULL, FVMenuBuildDuplicate, MID_BuildDuplicates },
+#ifdef KOREAN
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) _STR_ShowGrp, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, NULL, NULL, NULL, FVMenuShowGroup },
+#endif
+ { NULL }
+};
+
+static GMenuItem2 delist[] = {
+ { { (unichar_t *) N_("_References..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'u' }, H_("References...|Alt+Ctl+I"), NULL, NULL, FVMenuShowDependentRefs, MID_ShowDependentRefs },
+ { { (unichar_t *) N_("_Substitutions..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Substitutions...|No Shortcut"), NULL, NULL, FVMenuShowDependentSubs, MID_ShowDependentSubs },
+ { NULL }
+};
+
+static GMenuItem2 trlist[] = {
+ { { (unichar_t *) N_("_Transform..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Transform...|No Shortcut"), NULL, NULL, FVMenuTransform, MID_Transform },
+ { { (unichar_t *) N_("_Point of View Projection..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Point of View Projection...|Ctl+Shft+<"), NULL, NULL, FVMenuPOV, MID_POV },
+ { { (unichar_t *) N_("_Non Linear Transform..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Non Linear Transform...|Ctl+Shft+|"), NULL, NULL, FVMenuNLTransform, MID_NLTransform },
+ { NULL }
+};
+
+static GMenuItem2 rndlist[] = {
+ { { (unichar_t *) N_("To _Int"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("To Int|Ctl+Shft+_"), NULL, NULL, FVMenuRound2Int, MID_Round },
+ { { (unichar_t *) N_("To _Hundredths"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("To Hundredths|No Shortcut"), NULL, NULL, FVMenuRound2Hundredths, 0 },
+ { { (unichar_t *) N_("_Cluster"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Cluster|No Shortcut"), NULL, NULL, FVMenuCluster },
+ { NULL }
+};
+
+static GMenuItem2 ellist[] = {
+ { { (unichar_t *) N_("_Font Info..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Font Info...|Ctl+Shft+F"), NULL, NULL, FVMenuFontInfo },
+ { { (unichar_t *) N_("Glyph _Info..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Glyph Info...|Ctl+I"), NULL, NULL, FVMenuCharInfo, MID_CharInfo },
+ { { (unichar_t *) N_("BDF Info..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("BDF Info...|No Shortcut"), NULL, NULL, FVMenuBDFInfo, MID_StrikeInfo },
+ { { (unichar_t *) N_("S_how Dependent"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'D' }, NULL, delist, delistcheck },
+ { { (unichar_t *) N_("Find Pr_oblems..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Find Problems...|Ctl+E"), NULL, NULL, FVMenuFindProblems, MID_FindProblems },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Bitm_ap Strikes Available..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Bitmap Strikes Available...|Ctl+Shft+B"), NULL, NULL, FVMenuBitmaps, MID_AvailBitmaps },
+ { { (unichar_t *) N_("Regenerate _Bitmap Glyphs..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Regenerate Bitmap Glyphs...|Ctl+B"), NULL, NULL, FVMenuBitmaps, MID_RegenBitmaps },
+ { { (unichar_t *) N_("Remove Bitmap Glyphs..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Remove Bitmap Glyphs...|No Shortcut"), NULL, NULL, FVMenuBitmaps, MID_RemoveBitmaps },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Transformations"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'T' }, NULL, trlist, trlistcheck, NULL, MID_Transform },
+ { { (unichar_t *) N_("_Expand Stroke..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'E' }, H_("Expand Stroke...|Ctl+Shft+E"), NULL, NULL, FVMenuStroke, MID_Stroke },
+#ifdef FONTFORGE_CONFIG_TILEPATH
+ { { (unichar_t *) N_("Tile _Path..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Tile Path...|No Shortcut"), NULL, NULL, FVMenuTilePath, MID_TilePath },
+#endif
+ { { (unichar_t *) N_("O_verlap"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'O' }, NULL, rmlist, NULL, NULL, MID_RmOverlap },
+ { { (unichar_t *) N_("_Simplify"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, NULL, smlist, NULL, NULL, MID_Simplify },
+ { { (unichar_t *) N_("Add E_xtrema"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'x' }, H_("Add Extrema|Ctl+Shft+X"), NULL, NULL, FVMenuAddExtrema, MID_AddExtrema },
+ { { (unichar_t *) N_("Roun_d"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, NULL, rndlist, NULL, NULL, MID_Round },
+ { { (unichar_t *) N_("Effects"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, NULL, eflist, NULL, NULL, MID_Effects },
+ { { (unichar_t *) N_("_Meta Font..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Meta Font...|Ctl+Shft+!"), NULL, NULL, FVMenuMetaFont, MID_MetaFont },
+ { { (unichar_t *) N_("Autot_race"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'r' }, H_("Autotrace|Ctl+Shft+T"), NULL, NULL, FVMenuAutotrace, MID_Autotrace },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Correct Direction"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'D' }, H_("Correct Direction|Ctl+Shft+D"), NULL, NULL, FVMenuCorrectDir, MID_Correct },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("B_uild"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, NULL, balist, balistcheck, NULL, MID_BuildAccent },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Merge Fonts..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Merge Fonts...|No Shortcut"), NULL, NULL, FVMenuMergeFonts, MID_MergeFonts },
+ { { (unichar_t *) N_("Interpo_late Fonts..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'p' }, H_("Interpolate Fonts...|No Shortcut"), NULL, NULL, FVMenuInterpFonts, MID_InterpolateFonts },
+ { { (unichar_t *) N_("Compare Fonts..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'p' }, H_("Compare Fonts...|No Shortcut"), NULL, NULL, FVMenuCompareFonts, MID_FontCompare },
+ { NULL }
+};
+
+static GMenuItem2 dummyall[] = {
+ { { (unichar_t *) N_("All"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 1, 0, 'K' }, H_("All|No Shortcut"), NULL, NULL, NULL },
+ NULL
+};
+
+/* Builds up a menu containing all the anchor classes */
+static void aplistbuild(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ extern void GMenuItemArrayFree(GMenuItem *mi);
+
+ GMenuItemArrayFree(mi->sub);
+ mi->sub = NULL;
+
+ _aplistbuild(mi,fv->sf,FVMenuAnchorPairs);
+}
+
+static GMenuItem2 cblist[] = {
+ { { (unichar_t *) N_("_Kern Pairs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'K' }, H_("Kern Pairs|No Shortcut"), NULL, NULL, FVMenuKernPairs, MID_KernPairs },
+ { { (unichar_t *) N_("_Anchored Pairs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'K' }, H_("Anchored Pairs|No Shortcut"), dummyall, aplistbuild, NULL, MID_AnchorPairs },
+ { { (unichar_t *) N_("_Ligatures"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'L' }, H_("Ligatures|No Shortcut"), NULL, NULL, FVMenuLigatures, MID_Ligatures },
+ NULL
+};
+
+static void cblistcheck(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ SplineFont *sf = fv->sf;
+ int i, anyligs=0, anykerns=0, gid;
+ PST *pst;
+
+ if ( sf->kerns ) anykerns=true;
+ for ( i=0; i<fv->map->enccount; ++i ) if ( (gid = fv->map->map[i])!=-1 && sf->glyphs[gid]!=NULL ) {
+ for ( pst=sf->glyphs[gid]->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->type==pst_ligature ) {
+ anyligs = true;
+ if ( anykerns )
+ break;
+ }
+ }
+ if ( sf->glyphs[gid]->kerns!=NULL ) {
+ anykerns = true;
+ if ( anyligs )
+ break;
+ }
+ }
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_Ligatures:
+ mi->ti.disabled = !anyligs;
+ break;
+ case MID_KernPairs:
+ mi->ti.disabled = !anykerns;
+ break;
+ case MID_AnchorPairs:
+ mi->ti.disabled = sf->anchor==NULL;
+ break;
+ }
+ }
+}
+
+
+static GMenuItem2 gllist[] = {
+ { { (unichar_t *) N_("_Glyph Image"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'K' }, H_("Glyph Image|No Shortcut"), NULL, NULL, FVMenuGlyphLabel, gl_glyph },
+ { { (unichar_t *) N_("_Name"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'K' }, H_("Name|No Shortcut"), NULL, NULL, FVMenuGlyphLabel, gl_name },
+ { { (unichar_t *) N_("_Unicode"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'L' }, H_("Unicode|No Shortcut"), NULL, NULL, FVMenuGlyphLabel, gl_unicode },
+ { { (unichar_t *) N_("_Encoding Hex"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'L' }, H_("Encoding Hex|No Shortcut"), NULL, NULL, FVMenuGlyphLabel, gl_encoding },
+ NULL
+};
+
+static void gllistcheck(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ mi->ti.checked = fv->glyphlabel == mi->mid;
+ }
+}
+
+static GMenuItem2 emptymenu[] = {
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { NULL }
+};
+
+static void FVEncodingMenuBuild(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ extern void GMenuItemArrayFree(GMenuItem *mi);
+
+ if ( mi->sub!=NULL ) {
+ GMenuItemArrayFree(mi->sub);
+ mi->sub = NULL;
+ }
+ mi->sub = GetEncodingMenu(FVMenuReencode,fv->map->enc);
+}
+
+static void FVForceEncodingMenuBuild(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ extern void GMenuItemArrayFree(GMenuItem *mi);
+
+ if ( mi->sub!=NULL ) {
+ GMenuItemArrayFree(mi->sub);
+ mi->sub = NULL;
+ }
+ mi->sub = GetEncodingMenu(FVMenuForceEncode,fv->map->enc);
+}
+
+static void FVMenuAddUnencoded(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ char *ret, *end;
+ int cnt, i;
+ EncMap *map = fv->map;
+
+ /* Add unused unencoded slots in the map */
+ ret = gwwv_ask_string(_("Add Encoding Slots..."),"1",fv->cidmaster?_("How many CID slots do you wish to add?"):_("How many unencoded glyph slots do you wish to add?"));
+ if ( ret==NULL )
+return;
+ cnt = strtol(ret,&end,10);
+ if ( *end!='\0' || cnt<=0 ) {
+ free(ret);
+ gwwv_post_error( _("Bad Number"),_("Bad Number") );
+return;
+ }
+ free(ret);
+ if ( fv->normal!=NULL ) {
+ /* If it's compacted, lose the base encoding and the fact that it's */
+ /* compact and make it be custom. That's what Alexey Kryukov asked */
+ /* for */
+ EncMapFree(fv->normal);
+ fv->normal = NULL;
+ fv->map->enc = &custom;
+ FVSetTitle(fv);
+ }
+ if ( fv->cidmaster ) {
+ SplineFont *sf = fv->sf;
+ FontView *fvs;
+ if ( sf->glyphcnt+cnt<sf->glyphmax )
+ sf->glyphs = grealloc(sf->glyphs,(sf->glyphmax = sf->glyphcnt+cnt+10)*sizeof(SplineChar *));
+ memset(sf->glyphs+sf->glyphcnt,0,cnt*sizeof(SplineChar *));
+ for ( fvs=sf->fv; fvs!=NULL; fvs=fvs->nextsame ) {
+ EncMap *map = fvs->map;
+ if ( map->enccount+cnt>=map->encmax )
+ map->map = grealloc(map->map,(map->encmax += cnt+10)*sizeof(int));
+ if ( sf->glyphcnt+cnt<map->backmax )
+ map->backmap = grealloc(map->map,(map->backmax += cnt+10)*sizeof(int));
+ for ( i=map->enccount; i<map->enccount+cnt; ++i )
+ map->map[i] = map->backmap[i] = i;
+ fvs->selected = grealloc(fvs->selected,(map->enccount+cnt));
+ memset(fvs->selected+map->enccount,0,cnt);
+ map->enccount += cnt;
+ if ( fv->filled!=NULL ) {
+ if ( fv->filled->glyphmax<sf->glyphmax )
+ fv->filled->glyphs = grealloc(fv->filled->glyphs,(sf->glyphmax = sf->glyphcnt+cnt+10)*sizeof(BDFChar *));
+ memset(fv->filled->glyphs+fv->filled->glyphcnt,0,cnt*sizeof(BDFChar *));
+ fv->filled->glyphcnt = fv->filled->glyphmax = sf->glyphcnt+cnt;
+ }
+ }
+ sf->glyphcnt += cnt;
+ FontViewReformatAll(fv->sf);
+ } else {
+ if ( map->enccount+cnt>=map->encmax )
+ map->map = grealloc(map->map,(map->encmax += cnt+10)*sizeof(int));
+ for ( i=map->enccount; i<map->enccount+cnt; ++i )
+ map->map[i] = -1;
+ fv->selected = grealloc(fv->selected,(map->enccount+cnt));
+ memset(fv->selected+map->enccount,0,cnt);
+ map->enccount += cnt;
+ FontViewReformatOne(fv);
+ FVScrollToChar(fv,map->enccount-cnt);
+ }
+}
+
+static void FVMenuRemoveUnused(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ SplineFont *sf = fv->sf;
+ EncMap *map = fv->map;
+ int oldcount = map->enccount;
+ int gid, i;
+ int flags = -1;
+
+ for ( i=map->enccount-1; i>=0 && ((gid=map->map[i])==-1 || !SCWorthOutputting(sf->glyphs[gid]));
+ --i ) {
+ if ( gid!=-1 )
+ SFRemoveGlyph(sf,sf->glyphs[gid],&flags);
+ map->enccount = i;
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ /* We reduced the encoding, so don't really need to reallocate the selection */
+ /* array. It's just bigger than it needs to be. */
+ if ( oldcount!=map->enccount )
+ FontViewReformatOne(fv);
+#endif
+}
+
+static void FVMenuCompact(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int oldcount = fv->map->enccount;
+
+ if ( fv->normal!=NULL ) {
+ EncMapFree(fv->map);
+ fv->map = fv->normal;
+ fv->normal = NULL;
+ fv->selected = grealloc(fv->selected,fv->map->enccount);
+ memset(fv->selected,0,fv->map->enccount);
+ } else {
+ /* We reduced the encoding, so don't really need to reallocate the selection */
+ /* array. It's just bigger than it needs to be. */
+ fv->normal = EncMapCopy(fv->map);
+ CompactEncMap(fv->map,fv->sf);
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( oldcount!=fv->map->enccount )
+ FontViewReformatOne(fv);
+ FVSetTitle(fv);
+#endif
+}
+
+static void FVMenuDetachGlyphs(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int i, j, gid;
+ EncMap *map = fv->map;
+ int altered = false;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FontView *fvs;
+#endif
+ SplineFont *sf = fv->sf;
+
+ for ( i=0; i<map->enccount; ++i ) if ( fv->selected[i] && (gid=map->map[i])!=-1 ) {
+ altered = true;
+ map->map[i] = -1;
+ if ( map->backmap[gid]==i ) {
+ for ( j=map->enccount-1; j>=0 && map->map[j]!=gid; --j );
+ map->backmap[gid] = j;
+ }
+ if ( sf->glyphs[gid]!=NULL && sf->glyphs[gid]->altuni != NULL && map->enc!=&custom )
+ AltUniRemove(sf->glyphs[gid],UniFromEnc(i,map->enc));
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( altered )
+ for ( fvs = fv->sf->fv; fvs!=NULL; fvs=fvs->nextsame )
+ GDrawRequestExpose(fvs->v,NULL,false);
+#endif
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuDetachAndRemoveGlyphs(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ char *buts[3];
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_DetachAndRemoveGlyphs(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ static char *buts[] = { GTK_STOCK_REMOVE, GTK_STOCK_CANCEL, NULL };
+# endif
+ int i, j, gid;
+ EncMap *map = fv->map;
+ SplineFont *sf = fv->sf;
+ int flags = -1;
+ int changed = false, altered = false;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FontView *fvs;
+#endif
+
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ buts[0] = _("_Remove");
+ buts[1] = _("_Cancel");
+ buts[2] = NULL;
+#endif
+
+ if ( gwwv_ask(_("Detach & Remo_ve Glyphs..."),(const char **) buts,0,1,_("Are you sure you wish to remove these glyphs? This operation cannot be undone."))==1 )
+return;
+
+ for ( i=0; i<map->enccount; ++i ) if ( fv->selected[i] && (gid=map->map[i])!=-1 ) {
+ altered = true;
+ map->map[i] = -1;
+ if ( map->backmap[gid]==i ) {
+ for ( j=map->enccount-1; j>=0 && map->map[j]!=gid; --j );
+ map->backmap[gid] = j;
+ if ( j==-1 ) {
+ SFRemoveGlyph(sf,sf->glyphs[gid],&flags);
+ changed = true;
+ } else if ( sf->glyphs[gid]!=NULL && sf->glyphs[gid]->altuni != NULL && map->enc!=&custom )
+ AltUniRemove(sf->glyphs[gid],UniFromEnc(i,map->enc));
+ }
+ }
+ if ( changed && !fv->sf->changed ) {
+ fv->sf->changed = true;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ for ( fvs = sf->fv; fvs!=NULL; fvs=fvs->nextsame )
+ FVSetTitle(fvs);
+#endif
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( altered )
+ for ( fvs = sf->fv; fvs!=NULL; fvs=fvs->nextsame )
+ GDrawRequestExpose(fvs->v,NULL,false);
+#endif
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuAddEncodingName(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_AddEncodingName(GtkMenuItem *menuitem, gpointer user_data) {
+# endif
+ char *ret;
+ Encoding *enc;
+
+ /* Search the iconv database for the named encoding */
+ ret = gwwv_ask_string(_("Add Encoding Name..."),NULL,_("Please provide the name of an encoding in the iconv database which you want in the menu."));
+ if ( ret==NULL )
+return;
+ enc = FindOrMakeEncoding(ret);
+ if ( enc==NULL )
+ gwwv_post_error(_("Invalid Encoding"),_("Invalid Encoding"));
+ free(ret);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuLoadEncoding(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_LoadEncoding(GtkMenuItem *menuitem, gpointer user_data) {
+# endif
+ LoadEncodingFile();
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuMakeFromFont(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_MakeFromFont(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ (void) MakeEncoding(fv->sf,fv->map);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuRemoveEncoding(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_RemoveEncoding(GtkMenuItem *menuitem, gpointer user_data) {
+# endif
+ RemoveEncoding();
+}
+
+static int isuniname(char *name) {
+ int i;
+ if ( name[0]!='u' || name[1]!='n' || name[2]!='i' )
+return( false );
+ for ( i=3; i<7; ++i )
+ if ( name[i]<'0' || (name[i]>'9' && name[i]<'A') || name[i]>'F' )
+return( false );
+ if ( name[7]!='\0' )
+return( false );
+
+return( true );
+}
+
+static int isuname(char *name) {
+ int i;
+ if ( name[0]!='u' )
+return( false );
+ for ( i=1; i<5; ++i )
+ if ( name[i]<'0' || (name[i]>'9' && name[i]<'A') || name[i]>'F' )
+return( false );
+ if ( name[5]!='\0' )
+return( false );
+
+return( true );
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuMakeNamelist(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_MakeNamelist(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ gsize read, written;
+# endif
+ char buffer[1025];
+ char *filename, *temp;
+ FILE *file;
+ SplineChar *sc;
+ int i;
+
+ snprintf(buffer, sizeof(buffer),"%s/%s.nam", getPfaEditDir(buffer), fv->sf->fontname );
+# ifdef FONTFORGE_CONFIG_GDRAW
+ temp = def2utf8_copy(buffer);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ temp = g_filename_to_utf8(buffer,-1,&read,&written,NULL);
+#endif
+ filename = gwwv_save_filename(_("Make Namelist"), temp,"*.nam");
+ free(temp);
+ if ( filename==NULL )
+return;
+# ifdef FONTFORGE_CONFIG_GDRAW
+ temp = utf82def_copy(filename);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ temp = g_utf8_to_filename(filename,-1,&read,&written,NULL);
+#endif
+ file = fopen(temp,"w");
+ free(temp);
+ if ( file==NULL ) {
+ gwwv_post_error(_("Namelist creation failed"),_("Could not write %s"), filename);
+ free(filename);
+return;
+ }
+ for ( i=0; i<fv->sf->glyphcnt; ++i ) {
+ if ( (sc = fv->sf->glyphs[i])!=NULL && sc->unicodeenc!=-1 ) {
+ if ( !isuniname(sc->name) && !isuname(sc->name ) )
+ fprintf( file, "0x%04X %s\n", sc->unicodeenc, sc->name );
+ }
+ }
+ fclose(file);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuLoadNamelist(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_LoadNamelist(GtkMenuItem *menuitem, gpointer user_data) {
+ gsize read, written;
+# endif
+ /* Read in a name list and copy it into the prefs dir so that we'll find */
+ /* it in the future */
+ /* Be prepared to update what we've already got if names match */
+ char buffer[1025];
+ char *ret = gwwv_open_filename(_("Load Namelist"),NULL,
+ "*.nam",NULL);
+ char *temp, *pt;
+ char *buts[3];
+ FILE *old, *new;
+ int ch, ans;
+ NameList *nl;
+
+ if ( ret==NULL )
+return; /* Cancelled */
+# ifdef FONTFORGE_CONFIG_GDRAW
+ temp = utf82def_copy(ret);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ temp = g_utf8_to_filename(ret,-1,&read,&written,NULL);
+#endif
+ pt = strrchr(temp,'/');
+ if ( pt==NULL )
+ pt = temp;
+ else
+ ++pt;
+ snprintf(buffer,sizeof(buffer),"%s/%s", getPfaEditDir(buffer), pt);
+ if ( access(buffer,F_OK)==0 ) {
+ buts[0] = _("_Replace");
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ buts[1] = _("_Cancel");
+#elif defined(FONTFORGE_CONFIG_GTK)
+ buts[1] = GTK_STOCK_CANCEL;
+#endif
+ buts[2] = NULL;
+ ans = gwwv_ask( _("Replace"),(const char **) buts,0,1,_("A name list with this name already exists. Replace it?"));
+ if ( ans==1 ) {
+ free(temp);
+ free(ret);
+return;
+ }
+ }
+
+ old = fopen( temp,"r");
+ if ( old==NULL ) {
+ gwwv_post_error(_("No such file"),_("Could not read %s"), ret );
+ free(ret); free(temp);
+return;
+ }
+ if ( (nl = LoadNamelist(temp))==NULL ) {
+ gwwv_post_error(_("Bad namelist file"),_("Could not parse %s"), ret );
+ free(ret); free(temp);
+return;
+ }
+ free(ret); free(temp);
+ if ( nl->uses_unicode ) {
+ if ( nl->a_utf8_name!=NULL )
+ ff_post_notice(_("Non-ASCII glyphnames"),_("This namelist contains at least one non-ASCII glyph name, namely: %s"), nl->a_utf8_name );
+ else
+ ff_post_notice(_("Non-ASCII glyphnames"),_("This namelist is based on a namelist which contains non-ASCII glyph names"));
+ }
+
+ new = fopen( buffer,"w");
+ if ( new==NULL ) {
+ gwwv_post_error(_("Create failed"),_("Could not write %s"), buffer );
+return;
+ }
+
+ while ( (ch=getc(old))!=EOF )
+ putc(ch,new);
+ fclose(old);
+ fclose(new);
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuRenameByNamelist(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_RenameByNamelist(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+# endif
+ char **namelists = AllNamelistNames();
+ int i;
+ int ret;
+ NameList *nl;
+ extern int allow_utf8_glyphnames;
+
+ for ( i=0; namelists[i]!=NULL; ++i );
+ ret = gwwv_choose(_("Rename by NameList"),(const char **) namelists,i,0,_("Rename the glyphs in this font to the names found in the selected namelist"));
+ if ( ret==-1 )
+return;
+ nl = NameListByName(namelists[ret]);
+ if ( nl==NULL ) {
+ IError("Couldn't find namelist");
+return;
+ } else if ( nl!=NULL && nl->uses_unicode && !allow_utf8_glyphnames) {
+ gwwv_post_error(_("Namelist contains non-ASCII names"),_("Glyph names should be limited to characters in the ASCII character set, but there are names in this namelist which use characters outside that range."));
+return;
+ }
+ SFRenameGlyphsToNamelist(fv->sf,nl);
+# if defined(FONTFORGE_CONFIG_GDRAW)
+ GDrawRequestExpose(fv->v,NULL,false);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_queue_draw(fv->v);
+# endif
+}
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+static void FVMenuNameGlyphs(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_NameGlyphs(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ gsize read, written;
+# endif
+ /* Read a file containing a list of names, and add an unencoded glyph for */
+ /* each name */
+ char buffer[33];
+ char *ret = gwwv_open_filename(_("Load glyph names"),NULL, "*",NULL);
+ char *temp, *pt;
+ FILE *file;
+ int ch;
+ SplineChar *sc;
+ FontView *fvs;
+
+ if ( ret==NULL )
+return; /* Cancelled */
+# ifdef FONTFORGE_CONFIG_GDRAW
+ temp = utf82def_copy(ret);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ temp = g_utf8_to_filename(ret,-1,&read,&written,NULL);
+#endif
+
+ file = fopen( temp,"r");
+ if ( file==NULL ) {
+ gwwv_post_error(_("No such file"),_("Could not read %s"), ret );
+ free(ret); free(temp);
+return;
+ }
+ pt = buffer;
+ forever {
+ ch = getc(file);
+ if ( ch!=EOF && !isspace(ch)) {
+ if ( pt<buffer+sizeof(buffer)-1 )
+ *pt++ = ch;
+ } else {
+ if ( pt!=buffer ) {
+ *pt = '\0';
+ sc = NULL;
+ for ( fvs=fv->sf->fv; fvs!=NULL; fvs=fvs->nextsame ) {
+ EncMap *map = fvs->map;
+ if ( map->enccount+1>=map->encmax )
+ map->map = grealloc(map->map,(map->encmax += 20)*sizeof(int));
+ map->map[map->enccount] = -1;
+ fvs->selected = grealloc(fvs->selected,(map->enccount+1));
+ memset(fvs->selected+map->enccount,0,1);
+ ++map->enccount;
+ if ( sc==NULL ) {
+ sc = SFMakeChar(fv->sf,map,map->enccount-1);
+ free(sc->name);
+ sc->name = copy(buffer);
+ sc->comment = copy("."); /* Mark as something for sfd file */
+ /*SCLigDefault(sc);*/
+ }
+ map->map[map->enccount-1] = sc->orig_pos;
+ map->backmap[sc->orig_pos] = map->enccount-1;
+ }
+ pt = buffer;
+ }
+ if ( ch==EOF )
+ break;
+ }
+ }
+ fclose(file);
+ free(ret); free(temp);
+ FontViewReformatAll(fv->sf);
+}
+
+static GMenuItem2 enlist[] = {
+ { { (unichar_t *) N_("_Reencode"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'E' }, H_("Reencode|No Shortcut"), emptymenu, FVEncodingMenuBuild, NULL, MID_Reencode },
+ { { (unichar_t *) N_("_Compact"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'C' }, H_("Compact|No Shortcut"), NULL, NULL, FVMenuCompact, MID_Compact },
+ { { (unichar_t *) N_("_Force Encoding"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Force Encoding|No Shortcut"), emptymenu, FVForceEncodingMenuBuild, NULL, MID_ForceReencode },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Add Encoding Slots..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Add Encoding Slots...|No Shortcut"), NULL, NULL, FVMenuAddUnencoded, MID_AddUnencoded },
+ { { (unichar_t *) N_("Remove _Unused Slots"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Remove Unused Slots|No Shortcut"), NULL, NULL, FVMenuRemoveUnused, MID_RemoveUnused },
+ { { (unichar_t *) N_("_Detach Glyphs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Detach Glyphs|No Shortcut"), NULL, NULL, FVMenuDetachGlyphs, MID_DetachGlyphs },
+ { { (unichar_t *) N_("Detach & Remo_ve Glyphs..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Detach & Remove Glyphs...|No Shortcut"), NULL, NULL, FVMenuDetachAndRemoveGlyphs, MID_DetachAndRemoveGlyphs },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Add E_ncoding Name..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Add Encoding Name...|No Shortcut"), NULL, NULL, FVMenuAddEncodingName },
+ { { (unichar_t *) N_("_Load Encoding..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Load Encoding...|No Shortcut"), NULL, NULL, FVMenuLoadEncoding, MID_LoadEncoding },
+ { { (unichar_t *) N_("Ma_ke From Font..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Make From Font...|No Shortcut"), NULL, NULL, FVMenuMakeFromFont, MID_MakeFromFont },
+ { { (unichar_t *) N_("Remove En_coding..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Remove Encoding...|No Shortcut"), NULL, NULL, FVMenuRemoveEncoding, MID_RemoveEncoding },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Display By _Groups..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Display By Groups...|No Shortcut"), NULL, NULL, FVMenuDisplayByGroups, MID_DisplayByGroups },
+ { { (unichar_t *) N_("D_efine Groups..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Define Groups...|No Shortcut"), NULL, NULL, FVMenuDefineGroups },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Save Namelist of Font..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Save Namelist of Font...|No Shortcut"), NULL, NULL, FVMenuMakeNamelist, MID_SaveNamelist },
+ { { (unichar_t *) N_("L_oad Namelist..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Load Namelist...|No Shortcut"), NULL, NULL, FVMenuLoadNamelist },
+ { { (unichar_t *) N_("Rename Gl_yphs..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Rename Glyphs...|No Shortcut"), NULL, NULL, FVMenuRenameByNamelist, MID_RenameGlyphs },
+ { { (unichar_t *) N_("Cre_ate Named Glyphs..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Create Named Glyphs...|No Shortcut"), NULL, NULL, FVMenuNameGlyphs, MID_NameGlyphs },
+ { NULL }
+};
+
+static void enlistcheck(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int i, gid;
+ SplineFont *sf = fv->sf;
+ EncMap *map = fv->map;
+ int anyglyphs = false;
+
+ for ( i=map->enccount-1; i>=0 ; --i )
+ if ( fv->selected[i] && (gid=map->map[i])!=-1 )
+ anyglyphs = true;
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_Compact:
+ mi->ti.checked = fv->normal!=NULL;
+ break;
+ case MID_Reencode: case MID_ForceReencode:
+ mi->ti.disabled = fv->cidmaster!=NULL;
+ break;
+#if 0
+ case MID_AddUnencoded:
+ mi->ti.disabled = fv->normal!=NULL;
+ break;
+#endif
+ case MID_DetachGlyphs: case MID_DetachAndRemoveGlyphs:
+ mi->ti.disabled = !anyglyphs;
+ break;
+ case MID_RemoveUnused:
+ gid = map->map[map->enccount-1];
+ mi->ti.disabled = gid!=-1 && SCWorthOutputting(sf->glyphs[gid]);
+ break;
+ case MID_MakeFromFont:
+ mi->ti.disabled = fv->cidmaster!=NULL || map->enccount>1024;
+ break;
+ case MID_RemoveEncoding:
+ break;
+ case MID_DisplayByGroups:
+ mi->ti.disabled = fv->cidmaster!=NULL || group_root==NULL;
+ break;
+ case MID_NameGlyphs:
+ mi->ti.disabled = fv->normal!=NULL || fv->cidmaster!=NULL;
+ break;
+ case MID_RenameGlyphs: case MID_SaveNamelist:
+ mi->ti.disabled = fv->cidmaster!=NULL;
+ break;
+ }
+ }
+}
+
+static GMenuItem2 vwlist[] = {
+ { { (unichar_t *) N_("_Next Glyph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'N' }, H_("Next Glyph|Ctl+]"), NULL, NULL, FVMenuChangeChar, MID_Next },
+ { { (unichar_t *) N_("_Prev Glyph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Prev Glyph|Ctl+["), NULL, NULL, FVMenuChangeChar, MID_Prev },
+ { { (unichar_t *) N_("Next _Defined Glyph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'D' }, H_("Next Defined Glyph|Alt+Ctl+]"), NULL, NULL, FVMenuChangeChar, MID_NextDef },
+ { { (unichar_t *) N_("Prev Defined Gl_yph"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'a' }, H_("Prev Defined Glyph|Alt+Ctl+["), NULL, NULL, FVMenuChangeChar, MID_PrevDef },
+ { { (unichar_t *) N_("_Goto"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'G' }, H_("Goto|Ctl+Shft+>"), NULL, NULL, FVMenuGotoChar },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Show ATT"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Show ATT|No Shortcut"), NULL, NULL, FVMenuShowAtt },
+ { { (unichar_t *) N_("Display S_ubstitutions..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'u' }, H_("Display Substitutions...|No Shortcut"), NULL, NULL, FVMenuDisplaySubs, MID_DisplaySubs },
+ { { (unichar_t *) N_("Com_binations"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'b' }, NULL, cblist, cblistcheck },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Label Glyph By"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'b' }, NULL, gllist, gllistcheck },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("S_how H. Metrics..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("Show H. Metrics...|No Shortcut"), NULL, NULL, FVMenuShowMetrics, MID_ShowHMetrics },
+ { { (unichar_t *) N_("Show _V. Metrics..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("Show V. Metrics...|No Shortcut"), NULL, NULL, FVMenuShowMetrics, MID_ShowVMetrics },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("32x8 cell window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, '2' }, H_("32x8 cell window|Ctl+Shft+%"), NULL, NULL, FVMenuWSize, MID_32x8 },
+ { { (unichar_t *) N_("1_6x4 cell window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, '3' }, H_("16x4 cell window|Ctl+Shft+^"), NULL, NULL, FVMenuWSize, MID_16x4 },
+ { { (unichar_t *) N_("_8x2 cell window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, '3' }, H_("8x2 cell window|Ctl+Shft+*"), NULL, NULL, FVMenuWSize, MID_8x2 },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_24 pixel outline"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, '2' }, H_("24 pixel outline|Ctl+2"), NULL, NULL, FVMenuSize, MID_24 },
+ { { (unichar_t *) N_("_36 pixel outline"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, '3' }, H_("36 pixel outline|Ctl+3"), NULL, NULL, FVMenuSize, MID_36 },
+ { { (unichar_t *) N_("_48 pixel outline"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, '4' }, H_("48 pixel outline|Ctl+4"), NULL, NULL, FVMenuSize, MID_48 },
+ { { (unichar_t *) N_("_72 pixel outline"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, '4' }, H_("72 pixel outline|Ctl+7"), NULL, NULL, FVMenuSize, MID_72 },
+ { { (unichar_t *) N_("_96 pixel outline"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, '4' }, H_("96 pixel outline|Ctl+9"), NULL, NULL, FVMenuSize, MID_96 },
+ { { (unichar_t *) N_("_Anti Alias"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'A' }, H_("Anti Alias|Ctl+5"), NULL, NULL, FVMenuSize, MID_AntiAlias },
+ { { (unichar_t *) N_("_Fit to em"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'F' }, H_("Fit to em|Ctl+6"), NULL, NULL, FVMenuSize, MID_FitToEm },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Bitmap _Magnification..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 1, 0, 0, 0, 1, 1, 0, 'F' }, H_("Bitmap Magnification...|No Shortcut"), NULL, NULL, FVMenuMagnify, MID_BitmapMag },
+ { NULL }, /* Some extra room to show bitmaps */
+ { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL },
+ { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL },
+ { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL },
+ { NULL }
+};
+
+static void vwlistcheck(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int anychars = FVAnyCharSelected(fv);
+ int i, base;
+ BDFFont *bdf;
+ char buffer[50];
+ extern void GMenuItemArrayFree(GMenuItem *mi);
+ extern GMenuItem *GMenuItem2ArrayCopy(GMenuItem2 *mi, uint16 *cnt);
+ int pos;
+ SplineFont *sf = fv->sf;
+ EncMap *map = fv->map;
+ OTLookup *otl;
+
+ for ( i=0; vwlist[i].ti.text==NULL || strcmp((char *) vwlist[i].ti.text, _("Bitmap _Magnification..."))!=0; ++i );
+ base = i+1;
+ for ( i=base; vwlist[i].ti.text!=NULL; ++i ) {
+ free( vwlist[i].ti.text);
+ vwlist[i].ti.text = NULL;
+ }
+
+ vwlist[base-1].ti.disabled = true;
+ if ( sf->bitmaps!=NULL ) {
+ for ( bdf = sf->bitmaps, i=base;
+ i<sizeof(vwlist)/sizeof(vwlist[0])-1 && bdf!=NULL;
+ ++i, bdf = bdf->next ) {
+ if ( BDFDepth(bdf)==1 )
+ sprintf( buffer, _("%d pixel bitmap"), bdf->pixelsize );
+ else
+ sprintf( buffer, _("%d@%d pixel bitmap"),
+ bdf->pixelsize, BDFDepth(bdf) );
+ vwlist[i].ti.text = (unichar_t *) uc_copy(buffer);
+ vwlist[i].ti.checkable = true;
+ vwlist[i].ti.checked = bdf==fv->show;
+ vwlist[i].ti.userdata = bdf;
+ vwlist[i].invoke = FVMenuShowBitmap;
+ vwlist[i].ti.fg = vwlist[i].ti.bg = COLOR_DEFAULT;
+ if ( bdf==fv->show )
+ vwlist[base-1].ti.disabled = false;
+ }
+ }
+ GMenuItemArrayFree(mi->sub);
+ mi->sub = GMenuItem2ArrayCopy(vwlist,NULL);
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_Next: case MID_Prev:
+ mi->ti.disabled = anychars<0;
+ break;
+ case MID_NextDef:
+ pos = anychars+1;
+ if ( anychars<0 ) pos = map->enccount;
+ for ( ; pos<map->enccount &&
+ (map->map[pos]==-1 || !SCWorthOutputting(sf->glyphs[map->map[pos]]));
+ ++pos );
+ mi->ti.disabled = pos==map->enccount;
+ break;
+ case MID_PrevDef:
+ for ( pos = anychars-1; pos>=0 &&
+ (map->map[pos]==-1 || !SCWorthOutputting(sf->glyphs[map->map[pos]]));
+ --pos );
+ mi->ti.disabled = pos<0;
+ break;
+ case MID_DisplaySubs: { SplineFont *_sf = sf;
+ mi->ti.checked = fv->cur_subtable!=NULL;
+ if ( _sf->cidmaster ) _sf = _sf->cidmaster;
+ for ( otl=_sf->gsub_lookups; otl!=NULL; otl=otl->next )
+ if ( otl->lookup_type == gsub_single && otl->subtables!=NULL )
+ break;
+ mi->ti.disabled = otl==NULL;
+ } break;
+ case MID_ShowHMetrics:
+ /*mi->ti.checked = fv->showhmetrics;*/
+ break;
+ case MID_ShowVMetrics:
+ /*mi->ti.checked = fv->showvmetrics;*/
+ mi->ti.disabled = !sf->hasvmetrics;
+ break;
+ case MID_32x8:
+ mi->ti.checked = (fv->rowcnt==8 && fv->colcnt==32);
+ break;
+ case MID_16x4:
+ mi->ti.checked = (fv->rowcnt==4 && fv->colcnt==16);
+ break;
+ case MID_8x2:
+ mi->ti.checked = (fv->rowcnt==2 && fv->colcnt==8);
+ break;
+ case MID_24:
+ mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==24);
+ mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
+ break;
+ case MID_36:
+ mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==36);
+ mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
+ break;
+ case MID_48:
+ mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==48);
+ mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
+ break;
+ case MID_72:
+ mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==72);
+ mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
+ break;
+ case MID_96:
+ mi->ti.checked = (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==96);
+ mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
+ break;
+ case MID_AntiAlias:
+ mi->ti.checked = (fv->show!=NULL && fv->show->clut!=NULL);
+ mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
+ break;
+ case MID_FitToEm:
+ mi->ti.checked = (fv->show!=NULL && !fv->show->bbsized);
+ mi->ti.disabled = sf->onlybitmaps && fv->show!=fv->filled;
+ break;
+ }
+ }
+}
+
+static GMenuItem2 histlist[] = {
+ { { (unichar_t *) N_("_HStem"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("HStem|No Shortcut"), NULL, NULL, FVMenuHistograms, MID_HStemHist },
+ { { (unichar_t *) N_("_VStem"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("VStem|No Shortcut"), NULL, NULL, FVMenuHistograms, MID_VStemHist },
+ { { (unichar_t *) N_("BlueValues"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("BlueValues|No Shortcut"), NULL, NULL, FVMenuHistograms, MID_BlueValuesHist },
+ { NULL }
+};
+
+static GMenuItem2 htlist[] = {
+ { { (unichar_t *) N_("Auto_Hint"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("AutoHint|Ctl+Shft+H"), NULL, NULL, FVMenuAutoHint, MID_AutoHint },
+ { { (unichar_t *) N_("Hint _Substitution Pts"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("Hint Substitution Pts|No Shortcut"), NULL, NULL, FVMenuAutoHintSubs, MID_HintSubsPt },
+ { { (unichar_t *) N_("Auto _Counter Hint"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("Auto Counter Hint|No Shortcut"), NULL, NULL, FVMenuAutoCounter, MID_AutoCounter },
+ { { (unichar_t *) N_("_Don't AutoHint"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("Don't AutoHint|No Shortcut"), NULL, NULL, FVMenuDontAutoHint, MID_DontAutoHint },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Auto_Instr"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("AutoInstr|Ctl+T"), NULL, NULL, FVMenuAutoInstr, MID_AutoInstr },
+ { { (unichar_t *) N_("_Edit Instructions..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Edit Instructions...|No Shortcut"), NULL, NULL, FVMenuEditInstrs, MID_EditInstructions },
+ { { (unichar_t *) N_("Edit 'fpgm'..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Edit 'fpgm'...|No Shortcut"), NULL, NULL, FVMenuEditTable, MID_Editfpgm },
+ { { (unichar_t *) N_("Edit 'prep'..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Edit 'prep'...|No Shortcut"), NULL, NULL, FVMenuEditTable, MID_Editprep },
+ { { (unichar_t *) N_("Edit 'maxp'..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Edit 'maxp'...|No Shortcut"), NULL, NULL, FVMenuEditTable, MID_Editmaxp },
+ { { (unichar_t *) N_("Edit 'cvt '..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Edit 'cvt '...|No Shortcut"), NULL, NULL, FVMenuEditTable, MID_Editcvt },
+ { { (unichar_t *) N_("Private to 'cvt'"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Private to 'cvt'|No Shortcut"), NULL, NULL, FVMenuPrivateToCvt, MID_PrivateToCvt },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Clear Hints"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Clear Hints|No Shortcut"), NULL, NULL, FVMenuClearHints, MID_ClearHints },
+ { { (unichar_t *) N_("Clear _Width MD"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Clear Width MD|No Shortcut"), NULL, NULL, FVMenuClearWidthMD, MID_ClearWidthMD },
+ { { (unichar_t *) N_("Clear Instructions"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Clear Instructions|No Shortcut"), NULL, NULL, FVMenuClearInstrs, MID_ClearInstrs },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Histograms"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, H_("Histograms|No Shortcut"), histlist },
+ { NULL }
+};
+
+static GMenuItem2 mtlist[] = {
+ { { (unichar_t *) N_("_Center in Width"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Center in Width|No Shortcut"), NULL, NULL, FVMenuCenter, MID_Center },
+ { { (unichar_t *) N_("_Thirds in Width"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'T' }, H_("Thirds in Width|No Shortcut"), NULL, NULL, FVMenuCenter, MID_Thirds },
+ { { (unichar_t *) N_("Set _Width..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'W' }, H_("Set Width...|Ctl+Shft+L"), NULL, NULL, FVMenuSetWidth, MID_SetWidth },
+ { { (unichar_t *) N_("Set _LBearing..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'L' }, H_("Set LBearing...|Ctl+L"), NULL, NULL, FVMenuSetWidth, MID_SetLBearing },
+ { { (unichar_t *) N_("Set _RBearing..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Set RBearing...|Ctl+R"), NULL, NULL, FVMenuSetWidth, MID_SetRBearing },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Set _Vertical Advance..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("Set Vertical Advance...|No Shortcut"), NULL, NULL, FVMenuSetWidth, MID_SetVWidth },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Auto Width..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Auto Width...|Ctl+Shft+W"), NULL, NULL, FVMenuAutoWidth },
+ { { (unichar_t *) N_("Auto _Kern..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'K' }, H_("Auto Kern...|Ctl+Shft+K"), NULL, NULL, FVMenuAutoKern },
+ { { (unichar_t *) N_("Ker_n By Classes..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'K' }, H_("Kern By Classes...|No Shortcut"), NULL, NULL, FVMenuKernByClasses },
+ { { (unichar_t *) N_("Remove All Kern _Pairs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Remove All Kern Pairs|No Shortcut"), NULL, NULL, FVMenuRemoveKern, MID_RmHKern },
+ { { (unichar_t *) N_("Kern Pair Closeup..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Kern Pair Closeup...|No Shortcut"), NULL, NULL, FVMenuKPCloseup },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("VKern By Classes..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'K' }, H_("VKern By Classes...|No Shortcut"), NULL, NULL, FVMenuVKernByClasses, MID_VKernByClass },
+ { { (unichar_t *) N_("VKern From HKern"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("VKern From HKern|No Shortcut"), NULL, NULL, FVMenuVKernFromHKern, MID_VKernFromH },
+ { { (unichar_t *) N_("Remove All VKern Pairs"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Remove All VKern Pairs|No Shortcut"), NULL, NULL, FVMenuRemoveVKern, MID_RmVKern },
+ { NULL }
+};
+
+static GMenuItem2 cdlist[] = {
+ { { (unichar_t *) N_("_Convert to CID"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Convert to CID|No Shortcut"), NULL, NULL, FVMenuConvert2CID, MID_Convert2CID },
+ { { (unichar_t *) N_("Convert By C_Map"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Convert By CMap|No Shortcut"), NULL, NULL, FVMenuConvertByCMap, MID_ConvertByCMap },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Flatten"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Flatten|No Shortcut"), NULL, NULL, FVMenuFlatten, MID_Flatten },
+ { { (unichar_t *) N_("Fl_attenByCMap"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("FlattenByCMap|No Shortcut"), NULL, NULL, FVMenuFlattenByCMap, MID_FlattenByCMap },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Insert F_ont..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Insert Font...|No Shortcut"), NULL, NULL, FVMenuInsertFont, MID_InsertFont },
+ { { (unichar_t *) N_("Insert _Blank"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Insert Blank|No Shortcut"), NULL, NULL, FVMenuInsertBlank, MID_InsertBlank },
+ { { (unichar_t *) N_("_Remove Font"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Remove Font|No Shortcut"), NULL, NULL, FVMenuRemoveFontFromCID, MID_RemoveFromCID },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Change Supplement..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Change Supplement...|No Shortcut"), NULL, NULL, FVMenuChangeSupplement, MID_ChangeSupplement },
+ { { (unichar_t *) N_("C_ID Font Info..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("CID Font Info...|No Shortcut"), NULL, NULL, FVMenuCIDFontInfo, MID_CIDFontInfo },
+ { NULL }, /* Extra room to show sub-font names */
+ { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL },
+ { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL },
+ { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL },
+ { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL },
+ { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL },
+ { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL },
+ { NULL }
+};
+
+static void cdlistcheck(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int i, base, j;
+ extern void GMenuItemArrayFree(GMenuItem *mi);
+ extern GMenuItem *GMenuItem2ArrayCopy(GMenuItem2 *mi, uint16 *cnt);
+ SplineFont *sub, *cidmaster = fv->cidmaster;
+
+ for ( i=0; cdlist[i].mid!=MID_CIDFontInfo; ++i );
+ base = i+2;
+ for ( i=base; cdlist[i].ti.text!=NULL; ++i ) {
+ free( cdlist[i].ti.text);
+ cdlist[i].ti.text = NULL;
+ }
+
+ cdlist[base-1].ti.fg = cdlist[base-1].ti.bg = COLOR_DEFAULT;
+ if ( cidmaster==NULL ) {
+ cdlist[base-1].ti.line = false;
+ } else {
+ cdlist[base-1].ti.line = true;
+ for ( j = 0, i=base;
+ i<sizeof(cdlist)/sizeof(cdlist[0])-1 && j<cidmaster->subfontcnt;
+ ++i, ++j ) {
+ sub = cidmaster->subfonts[j];
+ cdlist[i].ti.text = uc_copy(sub->fontname);
+ cdlist[i].ti.checkable = true;
+ cdlist[i].ti.checked = sub==fv->sf;
+ cdlist[i].ti.userdata = sub;
+ cdlist[i].invoke = FVMenuShowSubFont;
+ cdlist[i].ti.fg = cdlist[i].ti.bg = COLOR_DEFAULT;
+ }
+ }
+ GMenuItemArrayFree(mi->sub);
+ mi->sub = GMenuItem2ArrayCopy(cdlist,NULL);
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_Convert2CID: case MID_ConvertByCMap:
+ mi->ti.disabled = cidmaster!=NULL || fv->sf->mm!=NULL;
+ break;
+ case MID_InsertFont: case MID_InsertBlank:
+ /* OpenType allows at most 255 subfonts (PS allows more, but why go to the effort to make safe font check that? */
+ mi->ti.disabled = cidmaster==NULL || cidmaster->subfontcnt>=255;
+ break;
+ case MID_RemoveFromCID:
+ mi->ti.disabled = cidmaster==NULL || cidmaster->subfontcnt<=1;
+ break;
+ case MID_Flatten: case MID_FlattenByCMap: case MID_CIDFontInfo:
+ case MID_ChangeSupplement:
+ mi->ti.disabled = cidmaster==NULL;
+ break;
+ }
+ }
+}
+
+static GMenuItem2 mmlist[] = {
+/* GT: Here (and following) MM means "MultiMaster" */
+ { { (unichar_t *) N_("_Create MM..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Create MM...|No Shortcut"), NULL, NULL, FVMenuCreateMM, MID_CreateMM },
+ { { (unichar_t *) N_("MM _Validity Check"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("MM Validity Check|No Shortcut"), NULL, NULL, FVMenuMMValid, MID_MMValid },
+ { { (unichar_t *) N_("MM _Info..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("MM Info...|No Shortcut"), NULL, NULL, FVMenuMMInfo, MID_MMInfo },
+ { { (unichar_t *) N_("_Blend to New Font..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Blend to New Font...|No Shortcut"), NULL, NULL, FVMenuBlendToNew, MID_BlendToNew },
+ { { (unichar_t *) N_("MM Change Default _Weights..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("MM Change Default Weights...|No Shortcut"), NULL, NULL, FVMenuChangeMMBlend, MID_ChangeMMBlend },
+ { NULL }, /* Extra room to show sub-font names */
+};
+
+static void mmlistcheck(GWindow gw,struct gmenuitem *mi, GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int i, base, j;
+ extern void GMenuItemArrayFree(GMenuItem *mi);
+ extern GMenuItem *GMenuItem2ArrayCopy(GMenuItem2 *mi, uint16 *cnt);
+ MMSet *mm = fv->sf->mm;
+ SplineFont *sub;
+ GMenuItem2 *mml;
+
+ for ( i=0; mmlist[i].mid!=MID_ChangeMMBlend; ++i );
+ base = i+2;
+ if ( mm==NULL )
+ mml = mmlist;
+ else {
+ mml = gcalloc(base+mm->instance_count+2,sizeof(GMenuItem2));
+ memcpy(mml,mmlist,sizeof(mmlist));
+ mml[base-1].ti.fg = mml[base-1].ti.bg = COLOR_DEFAULT;
+ mml[base-1].ti.line = true;
+ for ( j = 0, i=base; j<mm->instance_count+1; ++i, ++j ) {
+ if ( j==0 )
+ sub = mm->normal;
+ else
+ sub = mm->instances[j-1];
+ mml[i].ti.text = uc_copy(sub->fontname);
+ mml[i].ti.checkable = true;
+ mml[i].ti.checked = sub==fv->sf;
+ mml[i].ti.userdata = sub;
+ mml[i].invoke = FVMenuShowSubFont;
+ mml[i].ti.fg = mml[i].ti.bg = COLOR_DEFAULT;
+ }
+ }
+ GMenuItemArrayFree(mi->sub);
+ mi->sub = GMenuItem2ArrayCopy(mml,NULL);
+ if ( mml!=mmlist ) {
+ for ( i=base; mml[i].ti.text!=NULL; ++i )
+ free( mml[i].ti.text);
+ free(mml);
+ }
+
+ for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
+ switch ( mi->mid ) {
+ case MID_CreateMM:
+ mi->ti.disabled = false;
+ break;
+ case MID_MMInfo: case MID_MMValid: case MID_BlendToNew:
+ mi->ti.disabled = mm==NULL;
+ break;
+ case MID_ChangeMMBlend:
+ mi->ti.disabled = mm==NULL || mm->apple;
+ break;
+ }
+ }
+}
+
+static GMenuItem2 wnmenu[] = {
+ { { (unichar_t *) N_("New O_utline Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'u' }, H_("New Outline Window|Ctl+H"), NULL, NULL, FVMenuOpenOutline, MID_OpenOutline },
+ { { (unichar_t *) N_("New _Bitmap Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("New Bitmap Window|Ctl+J"), NULL, NULL, FVMenuOpenBitmap, MID_OpenBitmap },
+ { { (unichar_t *) N_("New _Metrics Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("New Metrics Window|Ctl+K"), NULL, NULL, FVMenuOpenMetrics },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Warnings"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Warnings|No Shortcut"), NULL, NULL, _MenuWarnings, MID_Warnings },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { NULL }
+};
+
+static void FVWindowMenuBuild(GWindow gw,struct gmenuitem *mi,GEvent *e) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+ int anychars = FVAnyCharSelected(fv);
+ struct gmenuitem *wmi;
+
+ WindowMenuBuild(gw,mi,e);
+ for ( wmi = mi->sub; wmi->ti.text!=NULL || wmi->ti.line ; ++wmi ) {
+ switch ( wmi->mid ) {
+ case MID_OpenOutline:
+ wmi->ti.disabled = anychars==-1;
+ break;
+ case MID_OpenBitmap:
+ wmi->ti.disabled = anychars==-1 || fv->sf->bitmaps==NULL;
+ break;
+ case MID_Warnings:
+ wmi->ti.disabled = ErrorWindowExists();
+ break;
+ }
+ }
+}
+
+GMenuItem2 helplist[] = {
+ { { (unichar_t *) N_("_Help"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("Help|F1"), NULL, NULL, FVMenuContextualHelp },
+ { { (unichar_t *) N_("_Overview"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Overview|Shft+F1"), NULL, NULL, MenuHelp },
+ { { (unichar_t *) N_("_Index"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Index|Ctl+F1"), NULL, NULL, MenuIndex },
+ { { (unichar_t *) N_("_About..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("About...|No Shortcut"), NULL, NULL, MenuAbout },
+ { { (unichar_t *) N_("_License..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("License...|No Shortcut"), NULL, NULL, MenuLicense },
+ { NULL }
+};
+
+GMenuItem fvpopupmenu[] = {
+ { { (unichar_t *) N_("Cu_t"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 't' }, '\0', ksm_control, NULL, NULL, FVMenuCut, MID_Cut },
+ { { (unichar_t *) N_("_Copy"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, '\0', ksm_control, NULL, NULL, FVMenuCopy, MID_Copy },
+ { { (unichar_t *) N_("C_opy Reference"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'o' }, '\0', ksm_control, NULL, NULL, FVMenuCopyRef, MID_CopyRef },
+ { { (unichar_t *) N_("Copy _Width"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'W' }, '\0', ksm_control, NULL, NULL, FVMenuCopyWidth, MID_CopyWidth },
+ { { (unichar_t *) N_("_Paste"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, '\0', ksm_control, NULL, NULL, FVMenuPaste, MID_Paste },
+ { { (unichar_t *) N_("C_lear"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'l' }, 0, 0, NULL, NULL, FVMenuClear, MID_Clear },
+ { { (unichar_t *) N_("Copy _Fg To Bg"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuCopyFgBg, MID_CopyFgToBg },
+ { { (unichar_t *) N_("U_nlink Reference"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'U' }, '\0', ksm_control, NULL, NULL, FVMenuUnlinkRef, MID_UnlinkRef },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Glyph _Info..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, '\0', ksm_control, NULL, NULL, FVMenuCharInfo, MID_CharInfo },
+ { { (unichar_t *) N_("_Transform..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'T' }, '\0', ksm_control, NULL, NULL, FVMenuTransform, MID_Transform },
+ { { (unichar_t *) N_("_Expand Stroke..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'E' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuStroke, MID_Stroke },
+/* { { (unichar_t *) N_("_Remove Overlap"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'O' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuOverlap, MID_RmOverlap },*/
+/* { { (unichar_t *) N_("_Simplify"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'S' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuSimplify, MID_Simplify },*/
+/* { { (unichar_t *) N_("Add E_xtrema"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'x' }, 'X', ksm_control|ksm_shift, NULL, NULL, FVMenuAddExtrema, MID_AddExtrema },*/
+ { { (unichar_t *) N_("To _Int"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'I' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuRound2Int, MID_Round },
+ { { (unichar_t *) N_("_Correct Direction"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'D' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuCorrectDir, MID_Correct },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("Auto_Hint"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuAutoHint, MID_AutoHint },
+ { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 1, 0, 0, }},
+ { { (unichar_t *) N_("_Center in Width"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, '\0', ksm_control, NULL, NULL, FVMenuCenter, MID_Center },
+ { { (unichar_t *) N_("Set _Width..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'W' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuSetWidth, MID_SetWidth },
+ { { (unichar_t *) N_("Set _Vertical Advance..."), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'V' }, '\0', ksm_control|ksm_shift, NULL, NULL, FVMenuSetWidth, MID_SetVWidth },
+ { NULL }
+};
+
+static GMenuItem2 mblist[] = {
+ { { (unichar_t *) N_("_File"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'F' }, NULL, fllist, fllistcheck },
+ { { (unichar_t *) N_("_Edit"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'E' }, NULL, edlist, edlistcheck },
+ { { (unichar_t *) N_("E_lement"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'l' }, NULL, ellist, ellistcheck },
+ { { (unichar_t *) N_("H_ints"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'i' }, NULL, htlist, htlistcheck },
+ { { (unichar_t *) N_("E_ncoding"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'V' }, NULL, enlist, enlistcheck },
+ { { (unichar_t *) N_("_View"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'V' }, NULL, vwlist, vwlistcheck },
+ { { (unichar_t *) N_("_Metrics"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'M' }, NULL, mtlist, mtlistcheck },
+ { { (unichar_t *) N_("_CID"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, NULL, cdlist, cdlistcheck },
+/* GT: Here (and following) MM means "MultiMaster" */
+ { { (unichar_t *) N_("MM"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, '\0' }, NULL, mmlist, mmlistcheck },
+ { { (unichar_t *) N_("_Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'W' }, NULL, wnmenu, FVWindowMenuBuild, NULL },
+ { { (unichar_t *) N_("_Help"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'H' }, NULL, helplist, NULL },
+ { NULL }
+};
+# elif defined(FONTFORGE_CONFIG_GTK)
+void FontViewMenu_ActivateCopyFrom(GtkMenuItem *menuitem, gpointer user_data) {
+ GtkWidget *w;
+
+ w = lookup_widget( menuitem, "all_fonts1" );
+ gtk_widget_set_sensitive(w,!onlycopydisplayed);
+
+ w = lookup_widget( menuitem, "displayed_fonts1" );
+ gtk_widget_set_sensitive(w,onlycopydisplayed);
+
+ w = lookup_widget( menuitem, "char_metadata1" );
+ gtk_widget_set_sensitive(w,copymetadata);
+}
+
+struct fv_any {
+ FontView *fv;
+ int anychars;
+ void (*callback)(GtkWidget *w,gpointer user_data);
+};
+
+static void activate_file_items(GtkWidget *w, gpointer user_data) {
+ struct fv_any *fv_any = (struct fv_any *) user_data;
+ G_CONST_RETURN gchar *name = gtk_widget_get_name( GTK_WIDGET(w));
+
+ if ( strcmp(name,"open_outline_window1")==0 )
+ gtk_widget_set_sensitive(w,fv_any->anychars!=-1);
+ else if ( strcmp(name,"open_bitmap_window1")==0 )
+ gtk_widget_set_sensitive(w,fv_any->anychars!=-1 && fv_any->fv->sf->bitmaps!=NULL);
+ else if ( strcmp(name,"revert_file1")==0 )
+ gtk_widget_set_sensitive(w,fv_any->fv->sf->origname!=NULL);
+ else if ( strcmp(name,"revert_glyph1")==0 )
+ gtk_widget_set_sensitive(w,fv_any->anychars!=-1 && fv_any->fv->sf->origname!=NULL);
+ else if ( strcmp(name,"recent1")==0 )
+ gtk_widget_set_sensitive(w,RecentFilesAny());
+ else if ( strcmp(name,"script_menu1")==0 )
+ gtk_widget_set_sensitive(w,script_menu_names[0]!=NULL);
+ else if ( strcmp(name,"print2")==0 )
+ gtk_widget_set_sensitive(w,!fv_any->fv->onlybitmaps);
+ else if ( strcmp(name,"display1")==0 )
+ gtk_widget_set_sensitive(w,!((fv->sf->onlybitmaps && fv->sf->bitmaps==NULL) ||
+ fv->sf->multilayer));
+}
+
+void FontViewMenu_ActivateFile(GtkMenuItem *menuitem, gpointer user_data) {
+ struct fv_any data;
+
+ data.fv = FV_From_MI(menuitem);
+ data.anychars = FVAnyCharSelected(data.fv);
+
+ gtk_container_foreach( GTK_CONTAINER( gtk_menu_item_get_submenu(menuitem )),
+ activate_file_items, &data );
+}
+
+void FontViewMenu_ActivateEdit(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ int pos = FVAnyCharSelected(fv), i;
+ /* I can only determine the contents of the clipboard asyncronously */
+ /* hence I can't check to see if it contains something that is pastable */
+ /* So all I can do with paste is check that something is selected */
+#if 0
+ int not_pasteable = pos==-1 ||
+ (!CopyContainsSomething() &&
+ !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/png") &&
+ !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/svg") &&
+ !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/bmp") &&
+ !GDrawSelectionHasType(fv->gw,sn_clipboard,"image/eps"));
+#endif
+ RefChar *base = CopyContainsRef(fv->sf);
+ GtkWidget *w;
+ int gid;
+ static char *poslist[] = { "cut2", "copy2", "copy_reference1", "copy_width1",
+ "copy_lbearing1", "copy_rbearing1", "paste2", "paste_into1",
+ "paste_after1", "same_glyph_as1", "clear2", "clear_background1",
+ "copy_fg_to_bg1", "join1", "replace_with_reference1",
+ "unlink_reference1", "remove_undoes1", NULL };
+
+ w = lookup_widget( menuitem, "undo2" );
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ fv->sf->glyphs[gid]!=NULL ) {
+ if ( fv->sf->glyphs[gid]->layers[ly_fore].undoes!=NULL )
+ break;
+ gtk_widget_set_sensitive(w,i!=fv->map->enccount);
+
+ w = lookup_widget( menuitem, "redo2" );
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid = fv->map->map[i])!=-1 &&
+ fv->sf->glyphs[gid]!=NULL ) {
+ if ( fv->sf->glyphs[gid]->layers[ly_fore].redoes!=NULL )
+ break;
+ gtk_widget_set_sensitive(w,i!=fv->map->enccount);
+
+ for ( i=0; poslist[i]!=NULL; ++i ) {
+ w = lookup_widget( menuitem, poslist[i] );
+ if ( w!=NULL )
+ gtk_widget_set_sensitive(w,pos!=-1);
+ }
+
+ w = lookup_widget( menuitem, "copy_vwidth1" );
+ if ( w!=NULL )
+ gtk_widget_set_sensitive(w,pos!=-1 && fv->sf->hasvmetrics);
+
+# ifndef FONTFORGE_CONFIG_PASTEAFTER
+ w = lookup_widget( menuitem, "paste_after1" );
+ gtk_widget_hide(w);
+# endif
+}
+
+void FontViewMenu_ActivateDependents(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ int anychars = FVAnyCharSelected(fv);
+ int anygid = anychars<0 ? -1 : fv->map->map[anychars];
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "references1" ),
+ anygid>=0 &&
+ fv->sf->glyphs[anygid]!=NULL &&
+ fv->sf->glyphs[anygid]->dependents != NULL);
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "substitutions1" ),
+ anygid>=0 &&
+ fv->sf->glyphs[anygid]!=NULL &&
+ SCUsedBySubs(fv->sf->glyphs[anygid]));
+}
+
+void FontViewMenu_ActivateAAT(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ FontView *ofv;
+ int anychars = FVAnyCharSelected(fv);
+ int anygid = anychars<0 ? -1 : fv->map->map[anychars];
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "default_att1" ),
+ anygid>=0 );
+ for ( ofv=fv_list; ofv!=NULL && ofv->sf==fv->sf; ofv = ofv->next );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "copy_features_to_font1" ),
+ ofv!=NULL );
+}
+
+void FontViewMenu_ActivateBuild(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ int anybuildable = false;
+ int anybuildableaccents = false;
+ int i, gid;
+
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] && (gid=fv->map->map[i])!=-1 ) {
+ SplineChar *sc, dummy;
+ sc = fv->sf->glyphs[gid];
+ if ( sc==NULL )
+ sc = SCBuildDummy(&dummy,fv->sf,fv->map,i);
+ if ( SFIsSomethingBuildable(fv->sf,sc,true)) {
+ anybuildableaccents = anybuildable = true;
+ break;
+ else if ( SFIsSomethingBuildable(fv->sf,sc,false))
+ anybuildable = true;
+ }
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "build_accented_char1" ),
+ anybuildableaccents );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "build_composite_char1" ),
+ anybuildable );
+}
+
+void FontViewMenu_ActivateElement(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ int anychars = FVAnyCharSelected(fv);
+ int anygid = anychars<0 ? -1 : fv->map->map[anychars];
+ int anybuildable, anytraceable;
+ int order2 = fv->sf->order2;
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "char_info1" ),
+ anygid>=0 &&
+ (fv->cidmaster==NULL || fv->sf->glyphs[anygid]!=NULL));
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "find_problems1" ),
+ anygid!=-1);
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "transform1" ),
+ anygid!=-1);
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "non_linear_transform1" ),
+ anygid!=-1);
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "add_extrema1" ),
+ anygid!=-1 && !fv->sf->onlybitmaps );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "round_to_int1" ),
+ anygid!=-1 && !fv->sf->onlybitmaps );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "correct_direction1" ),
+ anygid!=-1 && !fv->sf->onlybitmaps );
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "simplify3" ),
+ anygid!=-1 && !fv->sf->onlybitmaps );
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "meta_font1" ),
+ anygid!=-1 && !fv->sf->onlybitmaps && !order2 );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "expand_stroke1" ),
+ anygid!=-1 && !fv->sf->onlybitmaps && !order2 );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "overlap1" ),
+ anygid!=-1 && !fv->sf->onlybitmaps && !order2 );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "effects1" ),
+ anygid!=-1 && !fv->sf->onlybitmaps && !order2 );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "tilepath1" ),
+ anygid!=-1 && !fv->sf->onlybitmaps && !order2 );
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "bitmaps_available1" ),
+ fv->mm==NULL );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "regenerate_bitmaps1" ),
+ fv->mm==NULL && fv->sf->bitmaps!=NULL && !fv->sf->onlybitmaps );
+
+ anybuildable = false;
+ if ( anygid!=-1 ) {
+ int i, gid;
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] ) {
+ SplineChar *sc=NULL, dummy;
+ if ( (gid=fv->map->map[i])!=-1 )
+ sc = fv->sf->glyphs[gid];
+ if ( sc==NULL )
+ sc = SCBuildDummy(&dummy,fv->sf,fv->map,i);
+ if ( SFIsSomethingBuildable(fv->sf,sc,false)) {
+ anybuildable = true;
+ break;
+ }
+ }
+ }
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "build1" ),
+ anybuildable );
+
+ anytraceable = false;
+ if ( FindAutoTraceName()!=NULL && anychars!=-1 ) {
+ int i;
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( fv->selected[i] && (gid=fv->map->map[i])!=-1 &&
+ fv->sf->glyphs[gid]!=NULL &&
+ fv->sf->glyphs[gid]->layers[ly_back].images!=NULL ) {
+ anytraceable = true;
+ break;
+ }
+ }
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "autotrace1" ),
+ anytraceable );
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "interpolate_fonts1" ),
+ !fv->sf->onlybitmaps );
+
+#ifndef FONTFORGE_CONFIG_NONLINEAR
+ w = lookup_widget( menuitem, "non_linear_transform1" );
+ gtk_widget_hide(w);
+#endif
+#ifndef FONTFORGE_CONFIG_TILEPATH
+ w = lookup_widget( menuitem, "tilepath1" );
+ gtk_widget_hide(w);
+#endif
+}
+
+void FontViewMenu_ActivateHints(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ int anychars = FVAnyCharSelected(fv);
+ int anygid = anychars<0 ? -1 : fv->map->map[anychars];
+ int multilayer = fv->sf->multilayer;
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "autohint1" ),
+ anygid!=-1 && !multilayer );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "hint_subsitution_pts1" ),
+ !fv->sf->order2 && anygid!=-1 && !multilayer );
+ if ( fv->sf->mm!=NULL && fv->sf->mm->apple )
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "hint_subsitution_pts1" ),
+ false);
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "auto_counter_hint1" ),
+ !fv->sf->order2 && anygid!=-1 && !multilayer );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "dont_autohint1" ),
+ !fv->sf->order2 && anygid!=-1 && !multilayer );
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "autoinstr1" ),
+ fv->sf->order2 && anygid!=-1 && !multilayer );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "edit_instructions1" ),
+ fv->sf->order2 && anygid>=0 && !multilayer );
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "edit_fpgm1" ),
+ fv->sf->order2 && !multilayer );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "edit_prep1" ),
+ fv->sf->order2 && !multilayer );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "edit_cvt_1" ),
+ fv->sf->order2 && !multilayer );
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "clear_hints1" ),
+ anygid!=-1 );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "clear_width_md1" ),
+ anygid!=-1 );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "clear_instructions1" ),
+ fv->sf->order2 && anygid!=-1 );
+}
+
+/* Builds up a menu containing all the anchor classes */
+void FontViewMenu_ActivateAnchoredPairs(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+
+ _aplistbuild(menuitem,fv->sf,FVMenuAnchorPairs);
+}
+
+void FontViewMenu_ActivateCombinations(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ SplineFont *sf = fv->sf;
+ int i, gid, anyligs=0, anykerns=0;
+ PST *pst;
+
+ if ( sf->kerns ) anykerns=true;
+ for ( i=0; i<map->enccount; ++i ) if ( (gid=fv->map->map[i]!=-1 && sf->glyphs[gid]!=NULL ) {
+ for ( pst=sf->glyphs[gid]->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->type==pst_ligature ) {
+ anyligs = true;
+ if ( anykerns )
+ break;
+ }
+ }
+ if ( sf->glyphs[gid]->kerns!=NULL ) {
+ anykerns = true;
+ if ( anyligs )
+ break;
+ }
+ }
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "ligatures2" ),
+ anyligs);
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "kern_pairs1" ),
+ anykerns);
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "anchored_pairs1" ),
+ sf->anchor!=NULL);
+}
+
+void FontViewMenu_ActivateView(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ int anychars = FVAnyCharSelected(fv);
+ int i,gid;
+ BDFFont *bdf;
+ int pos;
+ SplineFont *sf = fv->sf;
+ EncMap *map = fv->map;
+ GtkWidget *menu = gtk_menu_item_get_submenu(menuitem);
+ GList *kids, *next;
+ static int sizes[] = { 24, 36, 48, 72, 96, 0 };
+
+ /* First remove anything we might have added previously */
+ for ( kids = GTK_MENU_SHELL(menu)->children; kids!=NULL; kids = next ) {
+ GtkWidget *w = kids->data;
+ next = kids->next;
+ if ( strcmp(gtk_widget_get_name(w),"temporary")==0 )
+ gtk_container_remove(GTK_CONTAINER(menu),w);
+ }
+
+ /* Then add any pre-built bitmap sizes */
+ if ( sf->bitmaps!=NULL ) {
+ GtkWidget *w;
+
+ w = gtk_separator_menu_item_new();
+ gtk_widget_show(w);
+ gtk_widget_set_name(w,"temporary");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu),w);
+
+ for ( bdf = sf->bitmaps; bdf!=NULL; bdf=bdf->next ) {
+ if ( BDFDepth(bdf)==1 )
+ sprintf( buffer, _("%d pixel bitmap"), bdf->pixelsize );
+ else
+ sprintf( buffer, _("%d@%d pixel bitmap"),
+ bdf->pixelsize, BDFDepth(bdf) );
+ w = gtk_check_menu_item_new_with_label( buffer );
+ gtk_widget_show(w);
+ gtk_widget_set_name(w,"temporary");
+ gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(w), bdf==fv->show );
+ g_signal_connect ( G_OBJECT( w ), "activate",
+ G_CALLBACK (FontViewMenu_ShowBitmap),
+ bdf);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu),w);
+ }
+ }
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "next_char1" ),
+ anychars>=0 );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "prev_char1" ),
+ anychars>=0 );
+ if ( anychars<0 ) pos = map->enccount;
+ else for ( pos = anychars+1; pos<map->enccount &&
+ (map->map[pos]==-1 || !SCWorthOutputting(sf->glyphs[map->map[pos]]));
+ ++pos );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "prev_char1" ),
+ pos!=map->enccount );
+ for ( pos=anychars-1; pos>=0 &&
+ (map->map[pos]==-1 || !SCWorthOutputting(sf->glyphs[map->map[pos]]));
+ --pos );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "prev_char1" ),
+ pos>=0 );
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+ lookup_widget( menuitem, "encoded_view1" )),
+ !fv->sf->compacted);
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+ lookup_widget( menuitem, "compacted_view1" )),
+ fv->sf->compacted);
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "show_v_metrics1" ),
+ fv->sf->hasvmetrics );
+
+ for ( i=0; sizes[i]!=NULL; ++i ) {
+ char buffer[80];
+ sprintf( buffer, "%d_pixel_outline1", sizes[i]);
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+ lookup_widget( menuitem, buffer )),
+ (fv->show!=NULL && fv->show==fv->filled && fv->show->pixelsize==sizes[i]));
+ gtk_widget_set_sensitive(lookup_widget( menuitem, buffer ),
+ !fv->sf->onlybitmaps || fv->show==fv->filled );
+ }
+
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+ lookup_widget( menuitem, "anti_alias1" )),
+ (fv->show!=NULL && fv->show->clut!=NULL));
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "anti_alias1" ),
+ !fv->sf->onlybitmaps || fv->show==fv->filled );
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+ lookup_widget( menuitem, "fit_to_em1" )),
+ (fv->show!=NULL && !fv->show->bbsized));
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "fit_to_em1" ),
+ !fv->sf->onlybitmaps || fv->show==fv->filled );
+}
+
+void FontViewMenu_ActivateMetrics(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ int anychars = FVAnyCharSelected(fv);
+ char *argnames[] = { "center_in_width1", "thirds_in_width1", "set_width1",
+ "set_lbearing1", "set_rbearing1", "set_vertical_advance1", NULL };
+ char *vnames[] = { "vkern_by_classes1", "vkern_from_hkern1",
+ "remove_all_vkern_pairs1", NULL };
+
+ for ( i=0; argnames[i]!=NULL; ++i )
+ gtk_widget_set_sensitive(lookup_widget( menuitem, argnames[i] ),
+ anychars!=-1 );
+ if ( !fv->sf->hasvmetrics )
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "set_vertical_advance1" ),
+ false );
+ for ( i=0; vnames[i]!=NULL; ++i )
+ gtk_widget_set_sensitive(lookup_widget( menuitem, vnames[i] ),
+ fv->sf->hasvmetrics );
+}
+
+void FontViewMenu_ActivateCID(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ int i, j;
+ SplineFont *sub, *cidmaster = fv->cidmaster;
+ GtkWidget *menu = gtk_menu_item_get_submenu(menuitem);
+ GList *kids, *next;
+
+ /* First remove anything we might have added previously */
+ for ( kids = GTK_MENU_SHELL(menu)->children; kids!=NULL; kids = next ) {
+ GtkWidget *w = kids->data;
+ next = kids->next;
+ if ( strcmp(gtk_widget_get_name(w),"temporary")==0 )
+ gtk_container_remove(GTK_CONTAINER(menu),w);
+ }
+
+ /* Then add any sub-fonts */
+ if ( cidmaster!=NULL ) {
+ GtkWidget *w;
+
+ w = gtk_separator_menu_item_new();
+ gtk_widget_show(w);
+ gtk_widget_set_name(w,"temporary");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu),w);
+
+ for ( j = 0; j<cidmaster->subfontcnt; ++j ) {
+ sub = cidmaster->subfonts[j];
+ w = gtk_check_menu_item_new_with_label( sub->fontname );
+ gtk_widget_show(w);
+ gtk_widget_set_name(w,"temporary");
+ gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(w), sub==fv->sf );
+ g_signal_connect ( G_OBJECT( w ), "activate",
+ G_CALLBACK (FontViewMenu_ShowSubFont),
+ sub);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu),w);
+ }
+ }
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "convert_to_cid1" ),
+ cidmaster==NULL && fv->sf->mm==NULL );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "convert_by_cmap1" ),
+ cidmaster==NULL && fv->sf->mm==NULL );
+
+ /* OpenType allows at most 255 subfonts (PS allows more, but why go to the effort to make safe font check that? */
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "insert_font1" ),
+ cidmaster!=NULL && cidmaster->subfontcnt<255 );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "insert_empty_font1" ),
+ cidmaster!=NULL && cidmaster->subfontcnt<255 );
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "remove_font1" ),
+ cidmaster!=NULL && cidmaster->subfontcnt>1 );
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "flatten1" ),
+ cidmaster!=NULL );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "flatten_by_cmap1" ),
+ cidmaster!=NULL );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "cid_font_info1" ),
+ cidmaster!=NULL );
+}
+
+void FontViewMenu_ActivateMM(GtkMenuItem *menuitem, gpointer user_data) {
+ FontView *fv = FV_From_MI(menuitem);
+ int i, base, j;
+ MMSet *mm = fv->sf->mm;
+ SplineFont *sub;
+ GMenuItem *mml;
+ GtkWidget *menu = gtk_menu_item_get_submenu(menuitem);
+ GList *kids, *next;
+
+ /* First remove anything we might have added previously */
+ for ( kids = GTK_MENU_SHELL(menu)->children; kids!=NULL; kids = next ) {
+ GtkWidget *w = kids->data;
+ next = kids->next;
+ if ( strcmp(gtk_widget_get_name(w),"temporary")==0 )
+ gtk_container_remove(GTK_CONTAINER(menu),w);
+ }
+
+ /* Then add any sub-fonts */
+ if ( mm!=NULL ) {
+ GtkWidget *w;
+
+ w = gtk_separator_menu_item_new();
+ gtk_widget_show(w);
+ gtk_widget_set_name(w,"temporary");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu),w);
+
+ for ( j = 0; j<mm->instance_count+1; ++j ) {
+ if ( j==0 )
+ sub = mm->normal;
+ else
+ sub = mm->instances[j-1];
+ w = gtk_check_menu_item_new_with_label( sub->fontname );
+ gtk_widget_show(w);
+ gtk_widget_set_name(w,"temporary");
+ gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(w), sub==fv->sf );
+ g_signal_connect ( G_OBJECT( w ), "activate",
+ G_CALLBACK (FontViewMenu_ShowSubFont),
+ sub);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu),w);
+ }
+ }
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "mm_validity_check1" ),
+ mm!=NULL );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "mm_info1" ),
+ mm!=NULL );
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "blend_to_new_font1" ),
+ mm!=NULL );
+
+ gtk_widget_set_sensitive(lookup_widget( menuitem, "mm_change_def_weights1" ),
+ mm!=NULL && !mm->apple );
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static int FeatureTrans(FontView *fv, int enc) {
+ SplineChar *sc;
+ PST *pst;
+ char *pt;
+ int gid;
+
+ if ( enc<0 || enc>=fv->map->enccount || (gid = fv->map->map[enc])==-1 )
+return( -1 );
+ if ( fv->cur_subtable==NULL )
+return( gid );
+
+ sc = fv->sf->glyphs[gid];
+ if ( sc==NULL )
+return( -1 );
+ for ( pst = sc->possub; pst!=NULL; pst=pst->next ) {
+ if (( pst->type == pst_substitution || pst->type == pst_alternate ) &&
+ pst->subtable == fv->cur_subtable )
+ break;
+ }
+ if ( pst==NULL )
+return( -1 );
+ pt = strchr(pst->u.subs.variant,' ');
+ if ( pt!=NULL )
+ *pt = '\0';
+ gid = SFFindExistingSlot(fv->sf, -1, pst->u.subs.variant );
+ if ( pt!=NULL )
+ *pt = ' ';
+return( gid );
+}
+
+void FVRefreshChar(FontView *fv,int gid) {
+ BDFChar *bdfc;
+ int i, j, enc;
+ MetricsView *mv;
+
+ /* Can happen in scripts */ /* Can happen if we do an AutoHint when generating a tiny font for freetype context */
+ if ( fv->v==NULL || fv->colcnt==0 || fv->sf->glyphs[gid]== NULL )
+return;
+ if ( fv->cur_subtable==NULL && strchr(fv->sf->glyphs[gid]->name,'.')!=NULL ) {
+ char *temp = copy(fv->sf->glyphs[gid]->name);
+ SplineChar *sc2;
+ *strchr(temp,'.') = '\0';
+ sc2 = SFGetChar(fv->sf,-1,temp);
+ if ( sc2!=NULL && sc2->orig_pos!=gid )
+ gid = sc2->orig_pos;
+ free(temp);
+ }
+
+ for ( fv=fv->sf->fv; fv!=NULL; fv = fv->nextsame ) {
+ for ( mv=fv->sf->metrics; mv!=NULL; mv=mv->next )
+ MVRefreshChar(mv,fv->sf->glyphs[gid]);
+ bdfc = fv->show->glyphs[gid];
+ /* A glyph may be encoded in several places, all need updating */
+ for ( enc = 0; enc<fv->map->enccount; ++enc ) if ( fv->map->map[enc]==gid ) {
+ i = enc / fv->colcnt;
+ j = enc - i*fv->colcnt;
+ i -= fv->rowoff;
+ if ( i>=0 && i<fv->rowcnt ) {
+ struct _GImage base;
+ GImage gi;
+ GClut clut;
+ GRect old, box;
+
+ if ( bdfc==NULL )
+ bdfc = BDFPieceMeal(fv->show,gid);
+ if ( bdfc==NULL )
+ continue;
+
+ memset(&gi,'\0',sizeof(gi));
+ memset(&base,'\0',sizeof(base));
+ if ( bdfc->byte_data ) {
+ gi.u.image = &base;
+ base.image_type = it_index;
+ base.clut = fv->show->clut;
+ GDrawSetDither(NULL, false); /* on 8 bit displays we don't want any dithering */
+ base.trans = -1;
+ /*base.clut->trans_index = 0;*/
+ } else {
+ memset(&clut,'\0',sizeof(clut));
+ gi.u.image = &base;
+ base.image_type = it_mono;
+ base.clut = &clut;
+ clut.clut_len = 2;
+ clut.clut[0] = GDrawGetDefaultBackground(NULL);
+ }
+
+ base.data = bdfc->bitmap;
+ base.bytes_per_line = bdfc->bytes_per_line;
+ base.width = bdfc->xmax-bdfc->xmin+1;
+ base.height = bdfc->ymax-bdfc->ymin+1;
+ box.x = j*fv->cbw+1; box.width = fv->cbw-1;
+ box.y = i*fv->cbh+fv->lab_height+1; box.height = fv->cbw;
+ GDrawPushClip(fv->v,&box,&old);
+ GDrawFillRect(fv->v,&box,GDrawGetDefaultBackground(NULL));
+ if ( fv->magnify>1 ) {
+ GDrawDrawImageMagnified(fv->v,&gi,NULL,
+ j*fv->cbw+(fv->cbw-1-fv->magnify*base.width)/2,
+ i*fv->cbh+fv->lab_height+1+fv->magnify*(fv->show->ascent-bdfc->ymax),
+ fv->magnify*base.width,fv->magnify*base.height);
+ } else
+ GDrawDrawImage(fv->v,&gi,NULL,
+ j*fv->cbw+(fv->cbw-1-base.width)/2,
+ i*fv->cbh+fv->lab_height+1+fv->show->ascent-bdfc->ymax);
+ GDrawPopClip(fv->v,&old);
+ if ( fv->selected[enc] ) {
+ GDrawSetXORBase(fv->v,GDrawGetDefaultBackground(GDrawGetDisplayOfWindow(fv->v)));
+ GDrawSetXORMode(fv->v);
+ GDrawFillRect(fv->v,&box,XOR_COLOR);
+ GDrawSetCopyMode(fv->v);
+ }
+ GDrawSetDither(NULL, true);
+ }
+ }
+ }
+}
+
+void FVRegenChar(FontView *fv,SplineChar *sc) {
+ struct splinecharlist *dlist;
+ MetricsView *mv;
+
+ if ( fv->v==NULL ) /* Can happen in scripts */
+return;
+
+ /* sc->changedsincelasthinted = true;*/ /* Why was this here? */
+ if ( sc->orig_pos>=fv->filled->glyphcnt )
+ IError("Character out of bounds in bitmap font %d>=%d", sc->orig_pos, fv->filled->glyphcnt );
+ else
+ BDFCharFree(fv->filled->glyphs[sc->orig_pos]);
+ fv->filled->glyphs[sc->orig_pos] = NULL;
+ /* FVRefreshChar does NOT do this for us */
+ for ( mv=fv->sf->metrics; mv!=NULL; mv=mv->next )
+ MVRegenChar(mv,sc);
+
+ FVRefreshChar(fv,sc->orig_pos);
+#if HANYANG
+ if ( sc->compositionunit && fv->sf->rules!=NULL )
+ Disp_RefreshChar(fv->sf,sc);
+#endif
+
+ for ( dlist=sc->dependents; dlist!=NULL; dlist=dlist->next )
+ FVRegenChar(fv,dlist->sc);
+}
+#endif
+
+int32 UniFromEnc(int enc, Encoding *encname) {
+ char from[20];
+ unichar_t to[20];
+ ICONV_CONST char *fpt;
+ char *tpt;
+ size_t fromlen, tolen;
+
+ if ( encname->is_custom || encname->is_original )
+return( -1 );
+ if ( enc>=encname->char_cnt )
+return( -1 );
+ if ( encname->is_unicodebmp || encname->is_unicodefull )
+return( enc );
+ if ( encname->unicode!=NULL )
+return( encname->unicode[enc] );
+ else if ( encname->tounicode ) {
+ /* To my surprise, on RH9, doing a reset on conversion of CP1258->UCS2 */
+ /* causes subsequent calls to return garbage */
+ if ( encname->iso_2022_escape_len ) {
+ tolen = sizeof(to); fromlen = 0;
+ iconv(encname->tounicode,NULL,&fromlen,NULL,&tolen); /* Reset state */
+ }
+ fpt = from; tpt = (char *) to; tolen = sizeof(to);
+ if ( encname->has_1byte && enc<256 ) {
+ *(char *) fpt = enc;
+ fromlen = 1;
+ } else if ( encname->has_2byte ) {
+ if ( encname->iso_2022_escape_len )
+ strncpy(from,encname->iso_2022_escape,encname->iso_2022_escape_len );
+ fromlen = encname->iso_2022_escape_len;
+ from[fromlen++] = enc>>8;
+ from[fromlen++] = enc&0xff;
+ }
+ if ( iconv(encname->tounicode,&fpt,&fromlen,&tpt,&tolen)==(size_t) -1 )
+return( -1 );
+ if ( tpt-(char *) to == 0 ) {
+ /* This strange call appears to be what we need to make CP1258->UCS2 */
+ /* work. It's supposed to reset the state and give us the shift */
+ /* out. As there is no state, and no shift out I have no idea why*/
+ /* this works, but it does. */
+ if ( iconv(encname->tounicode,NULL,&fromlen,&tpt,&tolen)==(size_t) -1 )
+return( -1 );
+ }
+ if ( tpt-(char *) to == sizeof(unichar_t) )
+return( to[0] );
+#ifdef UNICHAR_16
+ else if ( tpt-(char *) to == 4 && to[0]>=0xd800 && to[0]<0xdc00 && to[1]>=0xdc00 )
+return( ((to[0]-0xd800)<<10) + (to[1]-0xdc00) + 0x10000 );
+#endif
+ } else if ( encname->tounicode_func!=NULL ) {
+return( (encname->tounicode_func)(enc) );
+ }
+return( -1 );
+}
+
+int32 EncFromUni(int32 uni, Encoding *enc) {
+ unichar_t from[20];
+ unsigned char to[20];
+ ICONV_CONST char *fpt;
+ char *tpt;
+ size_t fromlen, tolen;
+ int i;
+
+ if ( enc->is_custom || enc->is_original || enc->is_compact )
+return( -1 );
+ if ( enc->is_unicodebmp || enc->is_unicodefull )
+return( uni<enc->char_cnt ? uni : -1 );
+
+ if ( enc->unicode!=NULL ) {
+ for ( i=0; i<enc->char_cnt; ++i ) {
+ if ( enc->unicode[i]==uni )
+return( i );
+ }
+return( -1 );
+ } else if ( enc->fromunicode!=NULL ) {
+ /* I don't see how there can be any state to reset in this direction */
+ /* So I don't reset it */
+#ifdef UNICHAR_16
+ if ( uni<0x10000 ) {
+ from[0] = uni;
+ fromlen = sizeof(unichar_t);
+ } else {
+ uni -= 0x10000;
+ from[0] = 0xd800 + (uni>>10);
+ from[1] = 0xdc00 + (uni&0x3ff);
+ fromlen = 2*sizeof(unichar_t);
+ }
+#else
+ from[0] = uni;
+ fromlen = sizeof(unichar_t);
+#endif
+ fpt = (char *) from; tpt = (char *) to; tolen = sizeof(to);
+ iconv(enc->fromunicode,NULL,NULL,NULL,NULL); /* reset shift in/out, etc. */
+ if ( iconv(enc->fromunicode,&fpt,&fromlen,&tpt,&tolen)==(size_t) -1 )
+return( -1 );
+ if ( tpt-(char *) to == 1 )
+return( to[0] );
+ if ( enc->iso_2022_escape_len!=0 ) {
+ if ( tpt-(char *) to == enc->iso_2022_escape_len+2 &&
+ strncmp((char *) to,enc->iso_2022_escape,enc->iso_2022_escape_len)==0 )
+return( (to[enc->iso_2022_escape_len]<<8) | to[enc->iso_2022_escape_len+1] );
+ } else {
+ if ( tpt-(char *) to == sizeof(unichar_t) )
+return( (to[0]<<8) | to[1] );
+ }
+ } else if ( enc->fromunicode_func!=NULL ) {
+return( (enc->fromunicode_func)(uni) );
+ }
+return( -1 );
+}
+
+int32 EncFromName(const char *name,enum uni_interp interp,Encoding *encname) {
+ int i;
+ if ( encname->psnames!=NULL ) {
+ for ( i=0; i<encname->char_cnt; ++i )
+ if ( encname->psnames[i]!=NULL && strcmp(name,encname->psnames[i])==0 )
+return( i );
+ }
+ i = UniFromName(name,interp,encname);
+ if ( i==-1 && strlen(name)==4 ) {
+ /* MS says use this kind of name, Adobe says use the one above */
+ char *end;
+ i = strtol(name,&end,16);
+ if ( i<0 || i>0xffff || *end!='\0' )
+return( -1 );
+ }
+return( EncFromUni(i,encname));
+}
+
+SplineChar *SCBuildDummy(SplineChar *dummy,SplineFont *sf,EncMap *map,int i) {
+ static char namebuf[100];
+#ifdef FONTFORGE_CONFIG_TYPE3
+ static Layer layers[2];
+#endif
+
+ memset(dummy,'\0',sizeof(*dummy));
+ dummy->color = COLOR_DEFAULT;
+ dummy->layer_cnt = 2;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ dummy->layers = layers;
+#endif
+ if ( sf->cidmaster!=NULL ) {
+ /* CID fonts don't have encodings, instead we must look up the cid */
+ if ( sf->cidmaster->loading_cid_map )
+ dummy->unicodeenc = -1;
+ else
+ dummy->unicodeenc = CID2NameUni(FindCidMap(sf->cidmaster->cidregistry,sf->cidmaster->ordering,sf->cidmaster->supplement,sf->cidmaster),
+ i,namebuf,sizeof(namebuf));
+ } else
+ dummy->unicodeenc = UniFromEnc(i,map->enc);
+
+ if ( sf->cidmaster!=NULL )
+ dummy->name = namebuf;
+ else if ( map->enc->psnames!=NULL && i<map->enc->char_cnt &&
+ map->enc->psnames[i]!=NULL )
+ dummy->name = map->enc->psnames[i];
+ else if ( dummy->unicodeenc==-1 )
+ dummy->name = NULL;
+ else
+ dummy->name = (char *) StdGlyphName(namebuf,dummy->unicodeenc,sf->uni_interp,sf->for_new_glyphs);
+ if ( dummy->name==NULL ) {
+ /*if ( dummy->unicodeenc!=-1 || i<256 )
+ dummy->name = ".notdef";
+ else*/ {
+ int j;
+ sprintf( namebuf, "NameMe.%d", i);
+ j=0;
+ while ( SFFindExistingSlot(sf,-1,namebuf)!=-1 )
+ sprintf( namebuf, "NameMe.%d.%d", i, ++j);
+ dummy->name = namebuf;
+ }
+ }
+ dummy->width = dummy->vwidth = sf->ascent+sf->descent;
+ if ( dummy->unicodeenc>0 && dummy->unicodeenc<0x10000 &&
+ Iscombining(dummy->unicodeenc)) {
+ /* Mark characters should be 0 width */
+ dummy->width = 0;
+ /* Except in monospaced fonts on windows, where they should be the */
+ /* same width as everything else */
+ }
+ /* Actually, in a monospace font, all glyphs should be the same width */
+ /* whether mark or not */
+ if ( sf->pfminfo.panose_set && sf->pfminfo.panose[3]==9 &&
+ sf->glyphcnt>0 ) {
+ for ( i=sf->glyphcnt-1; i>=0; --i )
+ if ( SCWorthOutputting(sf->glyphs[i])) {
+ dummy->width = sf->glyphs[i]->width;
+ break;
+ }
+ }
+ dummy->parent = sf;
+ dummy->orig_pos = 0xffff;
+return( dummy );
+}
+
+ static SplineChar *_SFMakeChar(SplineFont *sf,EncMap *map,int enc) {
+ SplineChar dummy, *sc;
+ SplineFont *ssf;
+ int j, real_uni, gid;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ Layer *l;
+#endif
+ extern const int cns14pua[], amspua[];
+
+ if ( enc>=map->enccount )
+ gid = -1;
+ else
+ gid = map->map[enc];
+ if ( sf->subfontcnt!=0 && gid!=-1 ) {
+ ssf = NULL;
+ for ( j=0; j<sf->subfontcnt; ++j )
+ if ( gid<sf->subfonts[j]->glyphcnt ) {
+ ssf = sf->subfonts[j];
+ if ( ssf->glyphs[gid]!=NULL ) {
+return( ssf->glyphs[gid] );
+ }
+ }
+ sf = ssf;
+ }
+
+ if ( gid==-1 || (sc = sf->glyphs[gid])==NULL ) {
+ if (( map->enc->is_unicodebmp || map->enc->is_unicodefull ) &&
+ ( enc>=0xe000 && enc<=0xf8ff ) &&
+ ( sf->uni_interp==ui_ams || sf->uni_interp==ui_trad_chinese ) &&
+ ( real_uni = (sf->uni_interp==ui_ams ? amspua : cns14pua)[enc-0xe000])!=0 ) {
+ if ( real_uni<map->enccount ) {
+ SplineChar *sc;
+ /* if necessary, create the real unicode code point */
+ /* and then make us be a duplicate of it */
+ sc = _SFMakeChar(sf,map,real_uni);
+ map->map[enc] = gid = sc->orig_pos;
+ SCCharChangedUpdate(sc);
+return( sc );
+ }
+ }
+
+ SCBuildDummy(&dummy,sf,map,enc);
+ if ((sc = SFGetChar(sf,dummy.unicodeenc,dummy.name))!=NULL ) {
+ map->map[enc] = sc->orig_pos;
+return( sc );
+ }
+ sc = SplineCharCreate();
+#ifdef FONTFORGE_CONFIG_TYPE3
+ l = sc->layers;
+ *sc = dummy;
+ sc->layers = l; /* It's empty, no need to copy dummy's layers */
+ if ( sf->strokedfont ) {
+ l[ly_fore].dostroke = true;
+ l[ly_fore].dofill = false;
+ }
+#else
+ *sc = dummy;
+#endif
+ sc->name = copy(sc->name);
+ /*SCLigDefault(sc);*/
+ SFAddGlyphAndEncode(sf,sc,map,enc);
+ }
+return( sc );
+}
+
+SplineChar *SFMakeChar(SplineFont *sf,EncMap *map, int enc) {
+ int gid;
+
+ if ( enc==-1 )
+return( NULL );
+ if ( enc>=map->enccount )
+ gid = -1;
+ else
+ gid = map->map[enc];
+ if ( sf->mm!=NULL && (gid==-1 || sf->glyphs[gid]==NULL) ) {
+ int j;
+ _SFMakeChar(sf->mm->normal,map,enc);
+ for ( j=0; j<sf->mm->instance_count; ++j )
+ _SFMakeChar(sf->mm->instances[j],map,enc);
+ }
+return( _SFMakeChar(sf,map,enc));
+}
+
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+static void AddSubPST(SplineChar *sc,struct lookup_subtable *sub,char *variant) {
+ PST *pst;
+
+ pst = chunkalloc(sizeof(PST));
+ pst->type = pst_substitution;
+ pst->subtable = sub;
+ pst->u.alt.components = copy(variant);
+ pst->next = sc->possub;
+ sc->possub = pst;
+}
+
+SplineChar *FVMakeChar(FontView *fv,int enc) {
+ SplineFont *sf = fv->sf;
+ SplineChar *base_sc = SFMakeChar(sf,fv->map,enc), *feat_sc = NULL;
+ int feat_gid = FeatureTrans(fv,enc);
+
+ if ( fv->cur_subtable==NULL )
+return( base_sc );
+
+ if ( feat_gid==-1 ) {
+ int uni = -1;
+ FeatureScriptLangList *fl = fv->cur_subtable->lookup->features;
+
+ if ( base_sc->unicodeenc>=0x600 && base_sc->unicodeenc<=0x6ff &&
+ fl!=NULL &&
+ (fl->featuretag == CHR('i','n','i','t') ||
+ fl->featuretag == CHR('m','e','d','i') ||
+ fl->featuretag == CHR('f','i','n','a') ||
+ fl->featuretag == CHR('i','s','o','l')) ) {
+ uni = fl->featuretag == CHR('i','n','i','t') ? ArabicForms[base_sc->unicodeenc-0x600].initial :
+ fl->featuretag == CHR('m','e','d','i') ? ArabicForms[base_sc->unicodeenc-0x600].medial :
+ fl->featuretag == CHR('f','i','n','a') ? ArabicForms[base_sc->unicodeenc-0x600].final :
+ fl->featuretag == CHR('i','s','o','l') ? ArabicForms[base_sc->unicodeenc-0x600].isolated :
+ -1;
+ feat_sc = SFGetChar(sf,uni,NULL);
+ if ( feat_sc!=NULL )
+return( feat_sc );
+ }
+ feat_sc = SplineCharCreate();
+ feat_sc->parent = sf;
+ feat_sc->unicodeenc = uni;
+ if ( uni!=-1 ) {
+ feat_sc->name = galloc(8);
+ feat_sc->unicodeenc = uni;
+ sprintf( feat_sc->name,"uni%04X", uni );
+ } else if ( fv->cur_subtable->suffix!=NULL ) {
+ feat_sc->name = galloc(strlen(base_sc->name)+strlen(fv->cur_subtable->suffix)+2);
+ sprintf( feat_sc->name, "%s.%s", base_sc->name, fv->cur_subtable->suffix );
+ } else if ( fl==NULL ) {
+ feat_sc->name = strconcat(base_sc->name,".unknown");
+ } else if ( fl->ismac ) {
+ /* mac feature/setting */
+ feat_sc->name = galloc(strlen(base_sc->name)+14);
+ sprintf( feat_sc->name,"%s.m%d_%d", base_sc->name,
+ (int) (fl->featuretag>>16),
+ (int) ((fl->featuretag)&0xffff) );
+ } else {
+ /* OpenType feature tag */
+ feat_sc->name = galloc(strlen(base_sc->name)+6);
+ sprintf( feat_sc->name,"%s.%c%c%c%c", base_sc->name,
+ (int) (fl->featuretag>>24),
+ (int) ((fl->featuretag>>16)&0xff),
+ (int) ((fl->featuretag>>8)&0xff),
+ (int) ((fl->featuretag)&0xff) );
+ }
+ SFAddGlyphAndEncode(sf,feat_sc,fv->map,fv->map->enccount);
+ AddSubPST(base_sc,fv->cur_subtable,feat_sc->name);
+return( feat_sc );
+ } else
+return( base_sc );
+}
+#else
+SplineChar *FVMakeChar(FontView *fv,int enc) {
+ SplineFont *sf = fv->sf;
+return( SFMakeChar(sf,fv->map,enc) );
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static GImage *GImageCropAndRotate(GImage *unrot) {
+ struct _GImage *unbase = unrot->u.image, *rbase;
+ int xmin = unbase->width, xmax = -1, ymin = unbase->height, ymax = -1;
+ int i,j, ii;
+ GImage *rot;
+
+ for ( i=0; i<unbase->height; ++i ) {
+ for ( j=0; j<unbase->width; ++j ) {
+ if ( !(unbase->data[i*unbase->bytes_per_line+(j>>3)]&(0x80>>(j&7))) ) {
+ if ( j<xmin ) xmin = j;
+ if ( j>xmax ) xmax = j;
+ if ( i>ymax ) ymax = i;
+ if ( i<ymin ) ymin = i;
+ }
+ }
+ }
+ if ( xmax==-1 )
+return( NULL );
+
+ rot = GImageCreate(it_mono,ymax-ymin+1,xmax-xmin+1);
+ if ( rot==NULL )
+return( NULL );
+ rbase = rot->u.image;
+ memset(rbase->data,-1,rbase->height*rbase->bytes_per_line);
+ for ( i=ymin; i<=ymax; ++i ) {
+ for ( j=xmin; j<=xmax; ++j ) {
+ if ( !(unbase->data[i*unbase->bytes_per_line+(j>>3)]&(0x80>>(j&7)) )) {
+ ii = ymax-i;
+ rbase->data[(j-xmin)*rbase->bytes_per_line+(ii>>3)] &= ~(0x80>>(ii&7));
+ }
+ }
+ }
+ rbase->trans = 1;
+return( rot );
+}
+
+static GImage *UniGetRotatedGlyph(FontView *fv, SplineChar *sc,int uni) {
+ SplineFont *sf = fv->sf;
+ int cid=-1;
+ static GWindow pixmap=NULL;
+ GRect r;
+ unichar_t buf[2];
+ GImage *unrot, *rot;
+ SplineFont *cm = sf->cidmaster;
+
+ if ( uni!=-1 )
+ /* Do nothing */;
+ else if ( sscanf(sc->name,"vertuni%x", (unsigned *) &uni)==1 )
+ /* All done */;
+ else if ( cm!=NULL &&
+ ((cid=CIDFromName(sc->name,cm))!=-1 ||
+ sscanf( sc->name, "cid-%d", &cid)==1 || /* Obsolete names */
+ sscanf( sc->name, "vertcid_%d", &cid)==1 ||
+ sscanf( sc->name, "cid_%d", &cid)==1 )) {
+ uni = CID2Uni(FindCidMap(cm->cidregistry,cm->ordering,cm->supplement,cm),
+ cid);
+ }
+ if ( uni&0x10000 ) uni -= 0x10000; /* Bug in some old cidmap files */
+ if ( uni<0 || uni>0xffff )
+return( NULL );
+
+ if ( pixmap==NULL ) {
+ pixmap = GDrawCreateBitmap(NULL,2*fv->lab_height,2*fv->lab_height,NULL);
+ if ( pixmap==NULL )
+return( NULL );
+ GDrawSetFont(pixmap,sf->fv->fontset[0]);
+ }
+ r.x = r.y = 0;
+ r.width = r.height = 2*fv->lab_height;
+ GDrawFillRect(pixmap,&r,1);
+ buf[0] = uni; buf[1] = 0;
+ GDrawDrawText(pixmap,2,fv->lab_height,buf,1,NULL,0);
+ unrot = GDrawCopyScreenToImage(pixmap,&r);
+ if ( unrot==NULL )
+return( NULL );
+
+ rot = GImageCropAndRotate(unrot);
+ GImageDestroy(unrot);
+return( rot );
+}
+
+#if 0
+static int Use2ByteEnc(FontView *fv,SplineChar *sc, unichar_t *buf,FontMods *mods) {
+ int ch1 = sc->enc>>8, ch2 = sc->enc&0xff, newch;
+ Encoding *enc = fv->map->enc;
+ unsigned short *subtable;
+
+ retry:
+ switch ( enc ) {
+ case em_big5: case em_big5hkscs:
+ if ( !GDrawFontHasCharset(fv->fontset[0],em_big5))
+return( false);
+ if ( ch1<0xa1 || ch1>0xf9 || ch2<0x40 || ch2>0xfe || sc->enc> 0xf9fe )
+return( false );
+ mods->has_charset = true; mods->charset = em_big5;
+ buf[0] = sc->enc;
+ buf[1] = 0;
+return( true );
+ break;
+ case em_sjis:
+ if ( !GDrawFontHasCharset(fv->fontset[0],em_jis208))
+return( false);
+ if ( ch1>=129 && ch1<=159 )
+ ch1-=112;
+ else if ( ch1>=0xe0 && ch1<=0xef )
+ ch1-=176;
+ else
+return( false );
+ ch1<<=1;
+ if ( ch2 == 127 )
+return( false );
+ else if ( ch2>=159 )
+ ch2-=126;
+ else if ( ch2>127 ) {
+ --ch1;
+ ch2 -= 32;
+ } else {
+ -- ch1;
+ ch2 -= 31;
+ }
+ mods->has_charset = true; mods->charset = em_jis208;
+ buf[0] = (ch1<<8) | ch2;
+ buf[1] = 0;
+return( true );
+ break;
+ case em_wansung:
+ if ( !GDrawFontHasCharset(fv->fontset[0],em_ksc5601))
+return( false);
+ if ( ch1<0xa1 || ch1>0xfd || ch2<0xa1 || ch2>0xfe || sc->enc > 0xfdfe )
+return( false );
+ mods->has_charset = true; mods->charset = em_ksc5601;
+ buf[0] = sc->enc-0x8080;
+ buf[1] = 0;
+return( true );
+ break;
+ case em_jisgb:
+ if ( !GDrawFontHasCharset(fv->fontset[0],em_gb2312))
+return( false);
+ if ( ch1<0xa1 || ch1>0xfd || ch2<0xa1 || ch2>0xfe || sc->enc > 0xfdfe )
+return( false );
+ mods->has_charset = true; mods->charset = em_gb2312;
+ buf[0] = sc->enc-0x8080;
+ buf[1] = 0;
+return( true );
+ break;
+ case em_ksc5601: case em_jis208: case em_jis212: case em_gb2312:
+ if ( !GDrawFontHasCharset(fv->fontset[0],enc))
+return( false);
+ if ( ch1<0x21 || ch1>0x7e || ch2<0x21 || ch2>0x7e )
+return( false );
+ mods->has_charset = true; mods->charset = enc;
+ buf[0] = (ch1<<8)|ch2;
+ buf[1] = 0;
+return( true );
+ break;
+ default:
+ /* If possible, look at the unicode font using the appropriate glyphs */
+ /* for the CJ language for which the font was designed */
+ ch1 = sc->unicodeenc>>8, ch2 = sc->unicodeenc&0xff;
+ switch ( fv->sf->uni_interp ) {
+ case ui_japanese:
+ if ( ch1>=jis_from_unicode.first && ch1<=jis_from_unicode.last &&
+ (subtable = jis_from_unicode.table[ch1-jis_from_unicode.first])!=NULL &&
+ (newch = subtable[ch2])!=0 ) {
+ if ( newch&0x8000 ) {
+ if ( GDrawFontHasCharset(fv->fontset[0],em_jis212)) {
+ enc = em_jis212;
+ newch &= ~0x8000;
+ ch1 = newch>>8; ch2 = newch&0xff;
+ } else
+return( false );
+ } else {
+ if ( GDrawFontHasCharset(fv->fontset[0],em_jis208)) {
+ enc = em_jis208;
+ ch1 = newch>>8; ch2 = newch&0xff;
+ } else
+return( false );
+ }
+ } else
+return( false );
+ break;
+ case ui_korean:
+ /* Don't know what to do about korean hanga chars */
+ /* No ambiguity for hangul */
+return( false );
+ break;
+ case ui_trad_chinese:
+ if ( ch1>=big5hkscs_from_unicode.first && ch1<=big5hkscs_from_unicode.last &&
+ (subtable = big5hkscs_from_unicode.table[ch1-big5hkscs_from_unicode.first])!=NULL &&
+ (newch = subtable[ch2])!=0 &&
+ GDrawFontHasCharset(fv->fontset[0],em_big5)) {
+ enc = em_big5hkscs;
+ ch1 = newch>>8; ch2 = newch&0xff;
+ } else
+return( false );
+ break;
+ case ui_simp_chinese:
+ if ( ch1>=gb2312_from_unicode.first && ch1<=gb2312_from_unicode.last &&
+ (subtable = gb2312_from_unicode.table[ch1-gb2312_from_unicode.first])!=NULL &&
+ (newch = subtable[ch2])!=0 &&
+ GDrawFontHasCharset(fv->fontset[0],em_gb2312)) {
+ enc = em_gb2312;
+ ch1 = newch>>8; ch2 = newch&0xff;
+ } else
+return( false );
+ break;
+ default:
+return( false );
+ }
+ goto retry;
+ }
+}
+#endif
+
+/* Mathmatical Alphanumeric Symbols in the 1d400-1d7ff range are styled */
+/* variants on latin, greek, and digits */
+#define _uni_bold 0x1
+#define _uni_italic 0x2
+#define _uni_script (1<<2)
+#define _uni_fraktur (2<<2)
+#define _uni_doublestruck (3<<2)
+#define _uni_sans (4<<2)
+#define _uni_mono (5<<2)
+#define _uni_fontmax (6<<2)
+#define _uni_latin 0
+#define _uni_greek 1
+#define _uni_digit 2
+
+static int latinmap[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '\0'
+};
+static int greekmap[] = {
+ 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39a,
+ 0x39b, 0x39c, 0x39d, 0x39e, 0x39f, 0x3a0, 0x3a1, 0x3f4, 0x3a3, 0x3a4,
+ 0x3a5, 0x3a6, 0x3a7, 0x3a8, 0x3a9, 0x2207,
+ 0x3b1, 0x3b2, 0x3b3, 0x3b4, 0x3b5, 0x3b6, 0x3b7, 0x3b8, 0x3b9, 0x3ba,
+ 0x3bb, 0x3bc, 0x3bd, 0x3be, 0x3bf, 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4,
+ 0x3c5, 0x3c6, 0x3c7, 0x3c8, 0x3c9,
+ 0x2202, 0x3f5, 0x3d1, 0x3f0, 0x3d5, 0x3f1, 0x3d6,
+ 0
+};
+static int digitmap[] = { '0', '1', '2', '3', '4', '5', '6','7','8','9', '\0' };
+static int *maps[] = { latinmap, greekmap, digitmap };
+
+static struct { int start, last; int styles; int charset; } mathmap[] = {
+ { 0x1d400, 0x1d433, _uni_bold, _uni_latin },
+ { 0x1d434, 0x1d467, _uni_italic, _uni_latin },
+ { 0x1d468, 0x1d49b, _uni_bold|_uni_italic, _uni_latin },
+ { 0x1d49c, 0x1d4cf, _uni_script, _uni_latin },
+ { 0x1d4d0, 0x1d503, _uni_script|_uni_bold, _uni_latin },
+ { 0x1d504, 0x1d537, _uni_fraktur, _uni_latin },
+ { 0x1d538, 0x1d56b, _uni_doublestruck, _uni_latin },
+ { 0x1d56c, 0x1d59f, _uni_fraktur|_uni_bold, _uni_latin },
+ { 0x1d5a0, 0x1d5d3, _uni_sans, _uni_latin },
+ { 0x1d5d4, 0x1d607, _uni_sans|_uni_bold, _uni_latin },
+ { 0x1d608, 0x1d63b, _uni_sans|_uni_italic, _uni_latin },
+ { 0x1d63c, 0x1d66f, _uni_sans|_uni_bold|_uni_italic, _uni_latin },
+ { 0x1d670, 0x1d6a3, _uni_mono, _uni_latin },
+ { 0x1d6a8, 0x1d6e1, _uni_bold, _uni_greek },
+ { 0x1d6e2, 0x1d71b, _uni_italic, _uni_greek },
+ { 0x1d71c, 0x1d755, _uni_bold|_uni_italic, _uni_greek },
+ { 0x1d756, 0x1d78f, _uni_sans|_uni_bold, _uni_greek },
+ { 0x1d790, 0x1d7c9, _uni_sans|_uni_bold|_uni_italic, _uni_greek },
+ { 0x1d7ce, 0x1d7d7, _uni_bold, _uni_digit },
+ { 0x1d7d8, 0x1d7e1, _uni_doublestruck, _uni_digit },
+ { 0x1d7e2, 0x1d7eb, _uni_sans, _uni_digit },
+ { 0x1d7ec, 0x1d7f5, _uni_sans|_uni_bold, _uni_digit },
+ { 0x1d7f6, 0x1d7ff, _uni_mono, _uni_digit },
+ { 0, 0 }
+};
+
+static GFont *FVCheckFont(FontView *fv,int type) {
+ FontRequest rq;
+ int family = type>>2;
+ char *fontnames;
+ unichar_t *ufontnames;
+
+ static char *resourcenames[] = { "FontView.SerifFamily", "FontView.ScriptFamily",
+ "FontView.FrakturFamily", "FontView.DoubleStruckFamily",
+ "FontView.SansFamily", "FontView.MonoFamily", NULL };
+ static char *defaultfontnames[] = {
+ "times,serif,caslon,clearlyu,unifont",
+ "script,formalscript,clearlyu,unifont",
+ "fraktur,clearlyu,unifont",
+ "doublestruck,clearlyu,unifont",
+ "helvetica,caliban,sansserif,sans,clearlyu,unifont",
+ "courier,monospace,caslon,clearlyu,unifont",
+ NULL
+ };
+
+ if ( fv->fontset[type]==NULL ) {
+ fontnames = GResourceFindString(resourcenames[family]);
+ if ( fontnames==NULL )
+ fontnames = defaultfontnames[family];
+ ufontnames = uc_copy(fontnames);
+
+ memset(&rq,0,sizeof(rq));
+ rq.family_name = ufontnames;
+ rq.point_size = -13;
+ rq.weight = (type&_uni_bold) ? 700:400;
+ rq.style = (type&_uni_italic) ? fs_italic : 0;
+ fv->fontset[type] = GDrawInstanciateFont(GDrawGetDisplayOfWindow(fv->v),&rq);
+ }
+return( fv->fontset[type] );
+}
+
+extern unichar_t adobes_pua_alts[0x200][3];
+
+static void do_Adobe_Pua(unichar_t *buf,int sob,int uni) {
+ int i, j;
+
+ for ( i=j=0; j<sob-1 && i<3; ++i ) {
+ int ch = adobes_pua_alts[uni-0xf600][i];
+ if ( ch==0 )
+ break;
+ if ( ch>=0xf600 && ch<=0xf7ff && adobes_pua_alts[ch-0xf600]!=0 ) {
+ do_Adobe_Pua(buf+j,sob-j,ch);
+ while ( buf[j]!=0 ) ++j;
+ } else
+ buf[j++] = ch;
+ }
+ buf[j] = 0;
+}
+
+static void FVExpose(FontView *fv,GWindow pixmap,GEvent *event) {
+ int i, j, width, gid;
+ int changed;
+ GRect old, old2, box, r;
+ GClut clut;
+ struct _GImage base;
+ GImage gi;
+ SplineChar dummy;
+ int styles, laststyles=0;
+ GImage *rotated=NULL;
+ int em = fv->sf->ascent+fv->sf->descent;
+ int yorg = fv->magnify*(fv->show->ascent-fv->sf->vertical_origin*fv->show->pixelsize/em);
+ Color bg, def_fg;
+
+ def_fg = GDrawGetDefaultForeground(NULL);
+ memset(&gi,'\0',sizeof(gi));
+ memset(&base,'\0',sizeof(base));
+ if ( fv->show->clut!=NULL ) {
+ gi.u.image = &base;
+ base.image_type = it_index;
+ base.clut = fv->show->clut;
+ GDrawSetDither(NULL, false);
+ base.trans = -1;
+ /*base.clut->trans_index = 0;*/
+ } else {
+ memset(&clut,'\0',sizeof(clut));
+ gi.u.image = &base;
+ base.image_type = it_mono;
+ base.clut = &clut;
+ clut.clut_len = 2;
+ clut.clut[0] = GDrawGetDefaultBackground(NULL);
+ }
+
+ GDrawSetFont(pixmap,fv->fontset[0]);
+ GDrawSetLineWidth(pixmap,0);
+ GDrawPushClip(pixmap,&event->u.expose.rect,&old);
+ GDrawFillRect(pixmap,NULL,GDrawGetDefaultBackground(NULL));
+ for ( i=0; i<=fv->rowcnt; ++i ) {
+ GDrawDrawLine(pixmap,0,i*fv->cbh,fv->width,i*fv->cbh,def_fg);
+ GDrawDrawLine(pixmap,0,i*fv->cbh+fv->lab_height,fv->width,i*fv->cbh+fv->lab_height,0x808080);
+ }
+ for ( i=0; i<=fv->colcnt; ++i )
+ GDrawDrawLine(pixmap,i*fv->cbw,0,i*fv->cbw,fv->height,def_fg);
+ for ( i=event->u.expose.rect.y/fv->cbh; i<=fv->rowcnt &&
+ (event->u.expose.rect.y+event->u.expose.rect.height+fv->cbh-1)/fv->cbh; ++i ) for ( j=0; j<fv->colcnt; ++j ) {
+ int index = (i+fv->rowoff)*fv->colcnt+j;
+ int feat_gid;
+ styles = 0;
+ SplineChar *sc;
+ if ( fv->mapping!=NULL ) {
+ if ( index>=fv->mapcnt ) index = fv->map->enccount;
+ else
+ index = fv->mapping[index];
+ }
+ if ( index < fv->map->enccount && index!=-1 ) {
+ unichar_t buf[60]; char cbuf[8];
+ char utf8_buf[8];
+ int use_utf8 = false;
+ Color fg;
+ FontMods *mods=NULL;
+ extern const int amspua[];
+ int uni;
+ struct cidmap *cidmap = NULL;
+ sc = (gid=fv->map->map[index])!=-1 ? fv->sf->glyphs[gid]: NULL;
+
+ if ( fv->cidmaster!=NULL )
+ cidmap = FindCidMap(fv->cidmaster->cidregistry,fv->cidmaster->ordering,fv->cidmaster->supplement,fv->cidmaster);
+
+ if ( ( fv->map->enc==&custom && index<256 ) ||
+ ( fv->map->enc!=&custom && index<fv->map->enc->char_cnt ) ||
+ ( cidmap!=NULL && index<MaxCID(cidmap) ))
+ fg = def_fg;
+ else
+ fg = 0x505050;
+ if ( sc==NULL )
+ sc = SCBuildDummy(&dummy,fv->sf,fv->map,index);
+ uni = sc->unicodeenc;
+ buf[0] = buf[1] = 0;
+ if ( fv->sf->uni_interp==ui_ams && uni>=0xe000 && uni<=0xf8ff &&
+ amspua[uni-0xe000]!=0 )
+ uni = amspua[uni-0xe000];
+ switch ( fv->glyphlabel ) {
+ case gl_name:
+ uc_strncpy(buf,sc->name,sizeof(buf)/sizeof(buf[0]));
+ styles = _uni_sans;
+ break;
+ case gl_unicode:
+ if ( sc->unicodeenc!=-1 ) {
+ sprintf(cbuf,"%04x",sc->unicodeenc);
+ uc_strcpy(buf,cbuf);
+ } else
+ uc_strcpy(buf,"?");
+ styles = _uni_sans;
+ break;
+ case gl_encoding:
+ if ( fv->map->enc->only_1byte ||
+ (fv->map->enc->has_1byte && index<256))
+ sprintf(cbuf,"%02x",index);
+ else
+ sprintf(cbuf,"%04x",index);
+ uc_strcpy(buf,cbuf);
+ styles = _uni_sans;
+ break;
+ case gl_glyph:
+ if ( uni==0xad )
+ buf[0] = '-';
+ else if ( fv->sf->uni_interp==ui_adobe && uni>=0xf600 && uni<=0xf7ff &&
+ adobes_pua_alts[uni-0xf600]!=0 ) {
+ use_utf8 = false;
+ do_Adobe_Pua(buf,sizeof(buf),uni);
+ } else if ( uni>=0x1d400 && uni<=0x1d7ff ) {
+ int i;
+ for ( i=0; mathmap[i].start!=0; ++i ) {
+ if ( uni<=mathmap[i].last ) {
+ buf[0] = maps[mathmap[i].charset][uni-mathmap[i].start];
+ styles = mathmap[i].styles;
+ break;
+ }
+ }
+ } else if ( uni>=0xe0020 && uni<=0xe007e ) {
+ buf[0] = uni-0xe0000; /* A map of Ascii for language names */
+#if HANYANG
+ } else if ( sc->compositionunit ) {
+ if ( sc->jamo<19 )
+ buf[0] = 0x1100+sc->jamo;
+ else if ( sc->jamo<19+21 )
+ buf[0] = 0x1161 + sc->jamo-19;
+ else /* Leave a hole for the blank char */
+ buf[0] = 0x11a8 + sc->jamo-(19+21+1);
+#endif
+ } else if ( uni>0 && uni<unicode4_size ) {
+ char *pt = utf8_buf;
+ use_utf8 = true;
+ if ( uni<=0x7f )
+ *pt ++ = uni;
+ else if ( uni<=0x7ff ) {
+ *pt++ = 0xc0 | (uni>>6);
+ *pt++ = 0x80 | (uni&0x3f);
+ } else if ( uni<=0xffff ) {
+ *pt++ = 0xe0 | (uni>>12);
+ *pt++ = 0x80 | ((uni>>6)&0x3f);
+ *pt++ = 0x80 | (uni&0x3f);
+ } else {
+ uint32 val = uni-0x10000;
+ int u = ((val&0xf0000)>>16)+1, z=(val&0x0f000)>>12, y=(val&0x00fc0)>>6, x=val&0x0003f;
+ *pt++ = 0xf0 | (u>>2);
+ *pt++ = 0x80 | ((u&3)<<4) | z;
+ *pt++ = 0x80 | y;
+ *pt++ = 0x80 | x;
+ }
+ *pt = '\0';
+ } else {
+ char *pt = strchr(sc->name,'.');
+ buf[0] = '?';
+ fg = 0xff0000;
+ if ( pt!=NULL ) {
+ int i, n = pt-sc->name;
+ char *end;
+ SplineFont *cm = fv->sf->cidmaster;
+ if ( n==7 && sc->name[0]=='u' && sc->name[1]=='n' && sc->name[2]=='i' &&
+ (i=strtol(sc->name+3,&end,16), end-sc->name==7))
+ buf[0] = i;
+ else if ( n>=5 && n<=7 && sc->name[0]=='u' &&
+ (i=strtol(sc->name+1,&end,16), end-sc->name==n))
+ buf[0] = i;
+ else if ( cm!=NULL && (i=CIDFromName(sc->name,cm))!=-1 ) {
+ int uni;
+ uni = CID2Uni(FindCidMap(cm->cidregistry,cm->ordering,cm->supplement,cm),
+ i);
+ if ( uni!=-1 )
+ buf[0] = uni;
+ } else {
+ int uni;
+ *pt = '\0';
+ uni = UniFromName(sc->name,fv->sf->uni_interp,fv->map->enc);
+ if ( uni!=-1 )
+ buf[0] = uni;
+ *pt = '.';
+ }
+ if ( strstr(pt,".vert")!=NULL )
+ rotated = UniGetRotatedGlyph(fv,sc,buf[0]!='?'?buf[0]:-1);
+ if ( buf[0]!='?' ) {
+ fg = def_fg;
+ if ( strstr(pt,".italic")!=NULL )
+ styles = _uni_italic|_uni_mono;
+ }
+ } else if ( strncmp(sc->name,"hwuni",5)==0 ) {
+ int uni=-1;
+ sscanf(sc->name,"hwuni%x", (unsigned *) &uni );
+ if ( uni!=-1 ) buf[0] = uni;
+ } else if ( strncmp(sc->name,"italicuni",9)==0 ) {
+ int uni=-1;
+ sscanf(sc->name,"italicuni%x", (unsigned *) &uni );
+ if ( uni!=-1 ) { buf[0] = uni; styles=_uni_italic|_uni_mono; }
+ fg = def_fg;
+ } else if ( strncmp(sc->name,"vertcid_",8)==0 ||
+ strncmp(sc->name,"vertuni",7)==0 ) {
+ rotated = UniGetRotatedGlyph(fv,sc,-1);
+ }
+ }
+ break;
+ }
+ bg = COLOR_DEFAULT;
+ r.x = j*fv->cbw+1; r.width = fv->cbw-1;
+ r.y = i*fv->cbh+1; r.height = fv->lab_height-1;
+ if ( sc->layers[ly_back].splines!=NULL || sc->layers[ly_back].images!=NULL ||
+ sc->color!=COLOR_DEFAULT ) {
+ bg = sc->color!=COLOR_DEFAULT?sc->color:0x808080;
+ GDrawFillRect(pixmap,&r,bg);
+ }
+ if ( (!fv->sf->order2 && sc->changedsincelasthinted ) ||
+ ( fv->sf->order2 && sc->layers[ly_fore].splines!=NULL &&
+ sc->ttf_instrs_len<=0 ) ||
+ ( fv->sf->order2 && sc->instructions_out_of_date ) ) {
+ Color hintcol = 0x0000ff;
+ if ( fv->sf->order2 && sc->instructions_out_of_date && sc->ttf_instrs_len>0 )
+ hintcol = 0xff0000;
+ GDrawDrawLine(pixmap,r.x,r.y,r.x,r.y+r.height-1,hintcol);
+ GDrawDrawLine(pixmap,r.x+1,r.y,r.x+1,r.y+r.height-1,hintcol);
+ GDrawDrawLine(pixmap,r.x+2,r.y,r.x+2,r.y+r.height-1,hintcol);
+ GDrawDrawLine(pixmap,r.x+r.width-1,r.y,r.x+r.width-1,r.y+r.height-1,hintcol);
+ GDrawDrawLine(pixmap,r.x+r.width-2,r.y,r.x+r.width-2,r.y+r.height-1,hintcol);
+ GDrawDrawLine(pixmap,r.x+r.width-3,r.y,r.x+r.width-3,r.y+r.height-1,hintcol);
+ }
+ if ( rotated!=NULL ) {
+ GDrawPushClip(pixmap,&r,&old2);
+ GDrawDrawImage(pixmap,rotated,NULL,j*fv->cbw+2,i*fv->cbh+2);
+ GDrawPopClip(pixmap,&old2);
+ GImageDestroy(rotated);
+ rotated = NULL;
+ } else if ( use_utf8 ) {
+ GTextBounds size;
+ if ( styles!=laststyles ) GDrawSetFont(pixmap,FVCheckFont(fv,styles));
+ width = GDrawGetText8Bounds(pixmap,utf8_buf,-1,mods,&size);
+ if ( size.lbearing==0 && size.rbearing==0 ) {
+ utf8_buf[0] = 0xe0 | (0xfffd>>12);
+ utf8_buf[1] = 0x80 | ((0xfffd>>6)&0x3f);
+ utf8_buf[2] = 0x80 | (0xfffd&0x3f);
+ utf8_buf[3] = 0;
+ width = GDrawGetText8Bounds(pixmap,utf8_buf,-1,mods,&size);
+ }
+ width = size.rbearing - size.lbearing+1;
+ if ( width >= fv->cbw-1 ) {
+ GDrawPushClip(pixmap,&r,&old2);
+ width = fv->cbw-1;
+ }
+ if ( sc->unicodeenc<0x80 || sc->unicodeenc>=0xa0 )
+ GDrawDrawText8(pixmap,j*fv->cbw+(fv->cbw-1-width)/2-size.lbearing,i*fv->cbh+fv->lab_as+1,utf8_buf,-1,mods,fg);
+ if ( width >= fv->cbw-1 )
+ GDrawPopClip(pixmap,&old2);
+ laststyles = styles;
+ } else {
+ if ( styles!=laststyles ) GDrawSetFont(pixmap,FVCheckFont(fv,styles));
+ width = GDrawGetTextWidth(pixmap,buf,-1,mods);
+ if ( width >= fv->cbw-1 ) {
+ GDrawPushClip(pixmap,&r,&old2);
+ width = fv->cbw-1;
+ }
+ if ( sc->unicodeenc<0x80 || sc->unicodeenc>=0xa0 )
+ GDrawDrawText(pixmap,j*fv->cbw+(fv->cbw-1-width)/2,i*fv->cbh+fv->lab_as+1,buf,-1,mods,fg);
+ if ( width >= fv->cbw-1 )
+ GDrawPopClip(pixmap,&old2);
+ laststyles = styles;
+ }
+ changed = sc->changed;
+ if ( fv->sf->onlybitmaps )
+ changed = gid==-1 || fv->show->glyphs[gid]==NULL? false : fv->show->glyphs[gid]->changed;
+ if ( changed ) {
+ GRect r;
+ r.x = j*fv->cbw+1; r.width = fv->cbw-1;
+ r.y = i*fv->cbh+1; r.height = fv->lab_height-1;
+ if ( bg == COLOR_DEFAULT )
+ bg = GDrawGetDefaultBackground(GDrawGetDisplayOfWindow(fv->v));
+ GDrawSetXORBase(pixmap,bg);
+ GDrawSetXORMode(pixmap);
+ GDrawFillRect(pixmap,&r,0x000000);
+ GDrawSetCopyMode(pixmap);
+ }
+ }
+
+ feat_gid = FeatureTrans(fv,index);
+ sc = feat_gid!=-1 ? fv->sf->glyphs[feat_gid]: NULL;
+ if ( !SCWorthOutputting(sc) ) {
+ int x = j*fv->cbw+1, xend = x+fv->cbw-2;
+ int y = i*fv->cbh+fv->lab_height+1, yend = y+fv->cbw-1;
+ GDrawDrawLine(pixmap,x,y,xend,yend,0xd08080);
+ GDrawDrawLine(pixmap,x,yend,xend,y,0xd08080);
+ }
+ if ( sc!=NULL ) {
+ BDFChar *bdfc;
+
+ if ( fv->show!=NULL && fv->show->piecemeal &&
+ feat_gid!=-1 && fv->show->glyphs[feat_gid]==NULL &&
+ fv->sf->glyphs[feat_gid]!=NULL )
+ BDFPieceMeal(fv->show,feat_gid);
+
+ if ( fv->show!=NULL && feat_gid!=-1 &&
+ feat_gid < fv->show->glyphcnt &&
+ fv->show->glyphs[feat_gid]==NULL &&
+ SCWorthOutputting(fv->sf->glyphs[feat_gid]) ) {
+ /* If we have an outline but no bitmap for this slot */
+ box.x = j*fv->cbw+1; box.width = fv->cbw-2;
+ box.y = i*fv->cbh+fv->lab_height+2; box.height = box.width+1;
+ GDrawDrawRect(pixmap,&box,0xff0000);
+ ++box.x; ++box.y; box.width -= 2; box.height -= 2;
+ GDrawDrawRect(pixmap,&box,0xff0000);
+/* When reencoding a font we can find times where index>=show->charcnt */
+ } else if ( fv->show!=NULL && feat_gid<fv->show->glyphcnt && feat_gid!=-1 &&
+ fv->show->glyphs[feat_gid]!=NULL ) {
+ bdfc = fv->show->glyphs[feat_gid];
+ base.data = bdfc->bitmap;
+ base.bytes_per_line = bdfc->bytes_per_line;
+ base.width = bdfc->xmax-bdfc->xmin+1;
+ base.height = bdfc->ymax-bdfc->ymin+1;
+ box.x = j*fv->cbw; box.width = fv->cbw;
+ box.y = i*fv->cbh+fv->lab_height+1; box.height = box.width+1;
+ GDrawPushClip(pixmap,&box,&old2);
+ if ( !fv->sf->onlybitmaps && fv->show!=fv->filled &&
+ sc->layers[ly_fore].splines==NULL && sc->layers[ly_fore].refs==NULL &&
+ !sc->widthset &&
+ !(bdfc->xmax<=0 && bdfc->xmin==0 && bdfc->ymax<=0 && bdfc->ymax==0) ) {
+ /* If we have a bitmap but no outline character... */
+ GRect b;
+ b.x = box.x+1; b.y = box.y+1; b.width = box.width-2; b.height = box.height-2;
+ GDrawDrawRect(pixmap,&b,0x008000);
+ ++b.x; ++b.y; b.width -= 2; b.height -= 2;
+ GDrawDrawRect(pixmap,&b,0x008000);
+ }
+ /* I assume that the bitmap image matches the bounding*/
+ /* box. In some bitmap fonts the bitmap has white space on the*/
+ /* right. This can throw off the centering algorithem */
+ if ( fv->magnify>1 ) {
+ GDrawDrawImageMagnified(pixmap,&gi,NULL,
+ j*fv->cbw+(fv->cbw-1-fv->magnify*base.width)/2,
+ i*fv->cbh+fv->lab_height+1+fv->magnify*(fv->show->ascent-bdfc->ymax),
+ fv->magnify*base.width,fv->magnify*base.height);
+ } else
+ GDrawDrawImage(pixmap,&gi,NULL,
+ j*fv->cbw+(fv->cbw-1-base.width)/2,
+ i*fv->cbh+fv->lab_height+1+fv->show->ascent-bdfc->ymax);
+ if ( fv->showhmetrics ) {
+ int x1, x0 = j*fv->cbw+(fv->cbw-1-fv->magnify*base.width)/2- bdfc->xmin*fv->magnify;
+ /* Draw advance width & horizontal origin */
+ if ( fv->showhmetrics&fvm_origin )
+ GDrawDrawLine(pixmap,x0,i*fv->cbh+fv->lab_height+yorg-3,x0,
+ i*fv->cbh+fv->lab_height+yorg+2,METRICS_ORIGIN);
+ x1 = x0 + bdfc->width;
+ if ( fv->showhmetrics&fvm_advanceat )
+ GDrawDrawLine(pixmap,x1,i*fv->cbh+fv->lab_height+1,x1,
+ (i+1)*fv->cbh-1,METRICS_ADVANCE);
+ if ( fv->showhmetrics&fvm_advanceto )
+ GDrawDrawLine(pixmap,x0,(i+1)*fv->cbh-2,x1,
+ (i+1)*fv->cbh-2,METRICS_ADVANCE);
+ }
+ if ( fv->showvmetrics ) {
+ int x0 = j*fv->cbw+(fv->cbw-1-fv->magnify*base.width)/2- bdfc->xmin*fv->magnify
+ + fv->magnify*fv->show->pixelsize/2;
+ int y0 = i*fv->cbh+fv->lab_height+yorg;
+ int yvw = y0 + fv->magnify*sc->vwidth*fv->show->pixelsize/em;
+ if ( fv->showvmetrics&fvm_baseline )
+ GDrawDrawLine(pixmap,x0,i*fv->cbh+fv->lab_height+1,x0,
+ (i+1)*fv->cbh-1,METRICS_BASELINE);
+ if ( fv->showvmetrics&fvm_advanceat )
+ GDrawDrawLine(pixmap,j*fv->cbw,yvw,(j+1)*fv->cbw,
+ yvw,METRICS_ADVANCE);
+ if ( fv->showvmetrics&fvm_advanceto )
+ GDrawDrawLine(pixmap,j*fv->cbw+2,y0,j*fv->cbw+2,
+ yvw,METRICS_ADVANCE);
+ if ( fv->showvmetrics&fvm_origin )
+ GDrawDrawLine(pixmap,x0-3,i*fv->cbh+fv->lab_height+yorg,x0+2,i*fv->cbh+fv->lab_height+yorg,METRICS_ORIGIN);
+ }
+ GDrawPopClip(pixmap,&old2);
+ }
+ }
+ if ( index<fv->map->enccount && fv->selected[index] ) {
+ box.x = j*fv->cbw+1; box.width = fv->cbw-1;
+ box.y = i*fv->cbh+fv->lab_height+1; box.height = fv->cbw;
+ GDrawSetXORMode(pixmap);
+ GDrawSetXORBase(pixmap,GDrawGetDefaultBackground(NULL));
+ GDrawFillRect(pixmap,&box,XOR_COLOR);
+ GDrawSetCopyMode(pixmap);
+ }
+ }
+ if ( fv->showhmetrics&fvm_baseline ) {
+ int baseline = (fv->sf->ascent*fv->magnify*fv->show->pixelsize)/em+1;
+ for ( i=0; i<=fv->rowcnt; ++i )
+ GDrawDrawLine(pixmap,0,i*fv->cbh+fv->lab_height+baseline,fv->width,i*fv->cbh+fv->lab_height+baseline,METRICS_BASELINE);
+ }
+ GDrawPopClip(pixmap,&old);
+ GDrawSetDither(NULL, true);
+}
+
+static char *chosung[] = { "G", "GG", "N", "D", "DD", "L", "M", "B", "BB", "S", "SS", "", "J", "JJ", "C", "K", "T", "P", "H", NULL };
+static char *jungsung[] = { "A", "AE", "YA", "YAE", "EO", "E", "YEO", "YE", "O", "WA", "WAE", "OE", "YO", "U", "WEO", "WE", "WI", "YU", "EU", "YI", "I", NULL };
+static char *jongsung[] = { "", "G", "GG", "GS", "N", "NJ", "NH", "D", "L", "LG", "LM", "LB", "LS", "LT", "LP", "LH", "M", "B", "BS", "S", "SS", "NG", "J", "C", "K", "T", "P", "H", NULL };
+
+static void FVDrawInfo(FontView *fv,GWindow pixmap,GEvent *event) {
+ GRect old, r;
+ char buffer[250], *pt;
+ unichar_t ubuffer[250];
+ Color bg = GDrawGetDefaultBackground(GDrawGetDisplayOfWindow(pixmap));
+ SplineChar *sc, dummy;
+ SplineFont *sf = fv->sf;
+ EncMap *map = fv->map;
+ int gid;
+ int uni;
+ Color fg = 0xff0000;
+ int ulen, tlen;
+
+ if ( event->u.expose.rect.y+event->u.expose.rect.height<=fv->mbh )
+return;
+
+ GDrawSetFont(pixmap,fv->fontset[0]);
+ GDrawPushClip(pixmap,&event->u.expose.rect,&old);
+
+ r.x = 0; r.width = fv->width; r.y = fv->mbh; r.height = fv->infoh;
+ GDrawFillRect(pixmap,&r,bg);
+ if ( fv->end_pos>=map->enccount || fv->pressed_pos>=map->enccount ||
+ fv->end_pos<0 || fv->pressed_pos<0 )
+ fv->end_pos = fv->pressed_pos = -1; /* Can happen after reencoding */
+ if ( fv->end_pos == -1 )
+return;
+
+ if ( map->remap!=NULL ) {
+ int localenc = fv->end_pos;
+ struct remap *remap = map->remap;
+ while ( remap->infont!=-1 ) {
+ if ( localenc>=remap->infont && localenc<=remap->infont+(remap->lastenc-remap->firstenc) ) {
+ localenc += remap->firstenc-remap->infont;
+ break;
+ }
+ ++remap;
+ }
+ sprintf( buffer, "%-5d (0x%04x) ", localenc, localenc );
+ } else if ( map->enc->only_1byte ||
+ (map->enc->has_1byte && fv->end_pos<256))
+ sprintf( buffer, "%-3d (0x%02x) ", fv->end_pos, fv->end_pos );
+ else
+ sprintf( buffer, "%-5d (0x%04x) ", fv->end_pos, fv->end_pos );
+ sc = (gid=fv->map->map[fv->end_pos])!=-1 ? sf->glyphs[gid] : NULL;
+ SCBuildDummy(&dummy,sf,fv->map,fv->end_pos);
+ if ( sc==NULL ) sc = &dummy;
+ uni = dummy.unicodeenc!=-1 ? dummy.unicodeenc : sc->unicodeenc;
+ if ( uni!=-1 )
+ sprintf( buffer+strlen(buffer), "U+%04X", uni );
+ else
+ sprintf( buffer+strlen(buffer), "U+????" );
+ sprintf( buffer+strlen(buffer), " %.*s", (int) (sizeof(buffer)-strlen(buffer)-1),
+ sc->name );
+
+ strcat(buffer," ");
+ utf82u_strcpy(ubuffer,buffer);
+ ulen = u_strlen(ubuffer);
+
+ if ( uni==-1 && (pt=strchr(sc->name,'.'))!=NULL && pt-sc->name<30 ) {
+ strncpy(buffer,sc->name,pt-sc->name);
+ buffer[(pt-sc->name)] = '\0';
+ uni = UniFromName(buffer,fv->sf->uni_interp,map->enc);
+ if ( uni!=-1 ) {
+ sprintf( buffer, "U+%04X ", uni );
+ uc_strcat(ubuffer,buffer);
+ }
+ fg = 0x707070;
+ }
+ if ( uni!=-1 && uni<0x110000 && _UnicodeNameAnnot!=NULL &&
+ _UnicodeNameAnnot[uni>>16][(uni>>8)&0xff][uni&0xff].name!=NULL ) {
+ uc_strncat(ubuffer, _UnicodeNameAnnot[uni>>16][(uni>>8)&0xff][uni&0xff].name, 80);
+ } else if ( uni>=0xAC00 && uni<=0xD7A3 ) {
+ sprintf( buffer, "Hangul Syllable %s%s%s",
+ chosung[(uni-0xAC00)/(21*28)],
+ jungsung[(uni-0xAC00)/28%21],
+ jongsung[(uni-0xAC00)%28] );
+ uc_strncat(ubuffer,buffer,80);
+ } else if ( uni!=-1 ) {
+ uc_strncat(ubuffer, UnicodeRange(uni),80);
+ }
+
+ tlen = GDrawDrawText(pixmap,10,fv->mbh+fv->lab_as,ubuffer,ulen,NULL,0xff0000);
+ GDrawDrawText(pixmap,10+tlen,fv->mbh+fv->lab_as,ubuffer+ulen,-1,NULL,fg);
+ GDrawPopClip(pixmap,&old);
+}
+
+static void FVShowInfo(FontView *fv) {
+ GRect r;
+
+ if ( fv->v==NULL ) /* Can happen in scripts */
+return;
+
+ r.x = 0; r.width = fv->width; r.y = fv->mbh; r.height = fv->infoh;
+ GDrawRequestExpose(fv->gw,&r,false);
+}
+
+static void FVChar(FontView *fv,GEvent *event) {
+ int i,pos, cnt, gid;
+
+#if MyMemory
+ if ( event->u.chr.keysym == GK_F2 ) {
+ fprintf( stderr, "Malloc debug on\n" );
+ __malloc_debug(5);
+ } else if ( event->u.chr.keysym == GK_F3 ) {
+ fprintf( stderr, "Malloc debug off\n" );
+ __malloc_debug(0);
+ }
+#endif
+
+ if ( event->u.chr.keysym=='s' &&
+ (event->u.chr.state&ksm_control) &&
+ (event->u.chr.state&ksm_meta) )
+ MenuSaveAll(NULL,NULL,NULL);
+ else if ( event->u.chr.keysym=='q' &&
+ (event->u.chr.state&ksm_control) &&
+ (event->u.chr.state&ksm_meta) )
+ MenuExit(NULL,NULL,NULL);
+ else if ( event->u.chr.keysym=='I' &&
+ (event->u.chr.state&ksm_shift) &&
+ (event->u.chr.state&ksm_meta) )
+ FVMenuCharInfo(fv->gw,NULL,NULL);
+ else if ( (event->u.chr.keysym=='[' || event->u.chr.keysym==']') &&
+ (event->u.chr.state&ksm_control) ) {
+ _FVMenuChangeChar(fv,event->u.chr.keysym=='['?MID_Prev:MID_Next);
+ } else if ( (event->u.chr.keysym=='{' || event->u.chr.keysym=='}') &&
+ (event->u.chr.state&ksm_control) ) {
+ _FVMenuChangeChar(fv,event->u.chr.keysym=='{'?MID_PrevDef:MID_NextDef);
+ } else if ( event->u.chr.keysym=='\\' && (event->u.chr.state&ksm_control) ) {
+ /* European keyboards need a funky modifier to get \ */
+ FVDoTransform(fv);
+#if !defined(_NO_FFSCRIPT) || !defined(_NO_PYTHON)
+ } else if ( isdigit(event->u.chr.keysym) && (event->u.chr.state&ksm_control) &&
+ (event->u.chr.state&ksm_meta) ) {
+ /* The Script menu isn't always up to date, so we might get one of */
+ /* the shortcuts here */
+ int index = event->u.chr.keysym-'1';
+ if ( index<0 ) index = 9;
+ if ( script_filenames[index]!=NULL )
+ ExecuteScriptFile(fv,script_filenames[index]);
+#endif
+ } else if ( event->u.chr.keysym == GK_Left ||
+ event->u.chr.keysym == GK_Tab ||
+ event->u.chr.keysym == GK_BackTab ||
+ event->u.chr.keysym == GK_Up ||
+ event->u.chr.keysym == GK_Right ||
+ event->u.chr.keysym == GK_Down ||
+ event->u.chr.keysym == GK_KP_Left ||
+ event->u.chr.keysym == GK_KP_Up ||
+ event->u.chr.keysym == GK_KP_Right ||
+ event->u.chr.keysym == GK_KP_Down ||
+ event->u.chr.keysym == GK_Home ||
+ event->u.chr.keysym == GK_KP_Home ||
+ event->u.chr.keysym == GK_End ||
+ event->u.chr.keysym == GK_KP_End ||
+ event->u.chr.keysym == GK_Page_Up ||
+ event->u.chr.keysym == GK_KP_Page_Up ||
+ event->u.chr.keysym == GK_Prior ||
+ event->u.chr.keysym == GK_Page_Down ||
+ event->u.chr.keysym == GK_KP_Page_Down ||
+ event->u.chr.keysym == GK_Next ) {
+ int end_pos = fv->end_pos;
+ /* We move the currently selected char. If there is none, then pick */
+ /* something on the screen */
+ if ( end_pos==-1 )
+ end_pos = (fv->rowoff+fv->rowcnt/2)*fv->colcnt;
+ switch ( event->u.chr.keysym ) {
+ case GK_Tab:
+ pos = end_pos;
+ do {
+ if ( event->u.chr.state&ksm_shift )
+ --pos;
+ else
+ ++pos;
+ if ( pos>=fv->map->enccount ) pos = 0;
+ else if ( pos<0 ) pos = fv->map->enccount-1;
+ } while ( pos!=end_pos &&
+ ((gid=fv->map->map[pos])==-1 || !SCWorthOutputting(fv->sf->glyphs[gid])));
+ if ( pos==end_pos ) ++pos;
+ if ( pos>=fv->map->enccount ) pos = 0;
+ break;
+#if GK_Tab!=GK_BackTab
+ case GK_BackTab:
+ pos = end_pos;
+ do {
+ --pos;
+ if ( pos<0 ) pos = fv->map->enccount-1;
+ } while ( pos!=end_pos &&
+ ((gid=fv->map->map[pos])==-1 || !SCWorthOutputting(fv->sf->glyphs[gid])));
+ if ( pos==end_pos ) --pos;
+ if ( pos<0 ) pos = 0;
+ break;
+#endif
+ case GK_Left: case GK_KP_Left:
+ pos = end_pos-1;
+ break;
+ case GK_Right: case GK_KP_Right:
+ pos = end_pos+1;
+ break;
+ case GK_Up: case GK_KP_Up:
+ pos = end_pos-fv->colcnt;
+ break;
+ case GK_Down: case GK_KP_Down:
+ pos = end_pos+fv->colcnt;
+ break;
+ case GK_End: case GK_KP_End:
+ pos = fv->map->enccount;
+ break;
+ case GK_Home: case GK_KP_Home:
+ pos = 0;
+ if ( fv->sf->top_enc!=-1 && fv->sf->top_enc<fv->map->enccount )
+ pos = fv->sf->top_enc;
+ else {
+ pos = SFFindSlot(fv->sf,fv->map,'A',NULL);
+ if ( pos==-1 ) pos = 0;
+ }
+ break;
+ case GK_Page_Up: case GK_KP_Page_Up:
+#if GK_Prior!=GK_Page_Up
+ case GK_Prior:
+#endif
+ pos = (fv->rowoff-fv->rowcnt+1)*fv->colcnt;
+ break;
+ case GK_Page_Down: case GK_KP_Page_Down:
+#if GK_Next!=GK_Page_Down
+ case GK_Next:
+#endif
+ pos = (fv->rowoff+fv->rowcnt+1)*fv->colcnt;
+ break;
+ }
+ if ( pos<0 ) pos = 0;
+ if ( pos>=fv->map->enccount ) pos = fv->map->enccount-1;
+ if ( event->u.chr.state&ksm_shift && event->u.chr.keysym!=GK_Tab && event->u.chr.keysym!=GK_BackTab ) {
+ FVReselect(fv,pos);
+ } else {
+ FVDeselectAll(fv);
+ fv->selected[pos] = true;
+ FVToggleCharSelected(fv,pos);
+ fv->pressed_pos = pos;
+ fv->sel_index = 1;
+ }
+ fv->end_pos = pos;
+ FVShowInfo(fv);
+ FVScrollToChar(fv,pos);
+ } else if ( event->u.chr.keysym == GK_Help ) {
+ MenuHelp(NULL,NULL,NULL); /* Menu does F1 */
+ } else if ( event->u.chr.keysym == GK_Escape ) {
+ FVDeselectAll(fv);
+ } else if ( event->u.chr.chars[0]=='\r' || event->u.chr.chars[0]=='\n' ) {
+ for ( i=cnt=0; i<fv->map->enccount && cnt<10; ++i ) if ( fv->selected[i] ) {
+ SplineChar *sc = SFMakeChar(fv->sf,fv->map,i);
+ if ( fv->show==fv->filled ) {
+ CharViewCreate(sc,fv,i);
+ } else {
+ BDFFont *bdf = fv->show;
+ BitmapViewCreate(BDFMakeGID(bdf,sc->orig_pos),bdf,fv,i);
+ }
+ ++cnt;
+ }
+ } else if ( event->u.chr.chars[0]<=' ' || event->u.chr.chars[1]!='\0' ) {
+ /* Do Nothing */;
+ } else {
+ SplineFont *sf = fv->sf;
+ for ( i=0; i<sf->glyphcnt; ++i ) {
+ if ( sf->glyphs[i]!=NULL )
+ if ( sf->glyphs[i]->unicodeenc==event->u.chr.chars[0] )
+ break;
+ }
+ if ( i==sf->glyphcnt ) {
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->map->map[i]==-1 ) {
+ SplineChar dummy;
+ SCBuildDummy(&dummy,sf,fv->map,i);
+ if ( dummy.unicodeenc==event->u.chr.chars[0] )
+ break;
+ }
+ } else
+ i = fv->map->backmap[i];
+ if ( i!=fv->map->enccount && i!=-1 )
+ FVChangeChar(fv,i);
+ }
+}
+
+static void uc_annot_strncat(unichar_t *to, const char *from, int len) {
+ register unichar_t ch;
+
+ to += u_strlen(to);
+ while ( (ch = *(unsigned char *) from++) != '\0' && --len>=0 ) {
+ if ( from[-2]=='\t' ) {
+ if ( ch=='*' ) ch = 0x2022;
+ else if ( ch=='x' ) ch = 0x2192;
+ else if ( ch==':' ) ch = 0x224d;
+ else if ( ch=='#' ) ch = 0x2245;
+ } else if ( ch=='\t' ) {
+ *(to++) = ' ';
+ ch = ' ';
+ }
+ *(to++) = ch;
+ }
+ *to = 0;
+}
+
+void SCPreparePopup(GWindow gw,SplineChar *sc,struct remap *remap, int localenc,
+ int actualuni) {
+ static unichar_t space[810];
+ char cspace[162];
+ int upos=-1;
+ int done = false;
+
+ /* If a glyph is multiply mapped then the inbuild unicode enc may not be */
+ /* the actual one used to access the glyph */
+ if ( remap!=NULL ) {
+ while ( remap->infont!=-1 ) {
+ if ( localenc>=remap->infont && localenc<=remap->infont+(remap->lastenc-remap->firstenc) ) {
+ localenc += remap->firstenc-remap->infont;
+ break;
+ }
+ ++remap;
+ }
+ }
+
+ if ( actualuni!=-1 )
+ upos = actualuni;
+ else if ( sc->unicodeenc!=-1 )
+ upos = sc->unicodeenc;
+#if HANYANG
+ else if ( sc->compositionunit ) {
+ if ( sc->jamo<19 )
+ upos = 0x1100+sc->jamo;
+ else if ( sc->jamo<19+21 )
+ upos = 0x1161 + sc->jamo-19;
+ else /* Leave a hole for the blank char */
+ upos = 0x11a8 + sc->jamo-(19+21+1);
+ }
+#endif
+ else {
+#if defined( _NO_SNPRINTF ) || defined( __VMS )
+ sprintf( cspace, "%u 0x%x U+???? \"%.25s\" ", localenc, localenc, sc->name==NULL?"":sc->name );
+#else
+ snprintf( cspace, sizeof(cspace), "%u 0x%x U+???? \"%.25s\" ", localenc, localenc, sc->name==NULL?"":sc->name );
+#endif
+ uc_strcpy(space,cspace);
+ done = true;
+ }
+ if ( done )
+ /* Do Nothing */;
+ else if ( upos<0x110000 && _UnicodeNameAnnot!=NULL &&
+ _UnicodeNameAnnot[upos>>16][(upos>>8)&0xff][upos&0xff].name!=NULL ) {
+#if defined( _NO_SNPRINTF ) || defined( __VMS )
+ sprintf( cspace, "%u 0x%x U+%04x \"%.25s\" %.100s", localenc, localenc, upos, sc->name==NULL?"":sc->name,
+ _UnicodeNameAnnot[upos>>16][(upos>>8)&0xff][upos&0xff].name);
+#else
+ snprintf( cspace, sizeof(cspace), "%u 0x%x U+%04x \"%.25s\" %.100s", localenc, localenc, upos, sc->name==NULL?"":sc->name,
+ _UnicodeNameAnnot[upos>>16][(upos>>8)&0xff][upos&0xff].name);
+#endif
+ utf82u_strcpy(space,cspace);
+ } else if ( upos>=0xAC00 && upos<=0xD7A3 ) {
+#if defined( _NO_SNPRINTF ) || defined( __VMS )
+ sprintf( cspace, "%u 0x%x U+%04x \"%.25s\" Hangul Syllable %s%s%s",
+ localenc, localenc, upos, sc->name==NULL?"":sc->name,
+ chosung[(upos-0xAC00)/(21*28)],
+ jungsung[(upos-0xAC00)/28%21],
+ jongsung[(upos-0xAC00)%28] );
+#else
+ snprintf( cspace, sizeof(cspace), "%u 0x%x U+%04x \"%.25s\" Hangul Syllable %s%s%s",
+ localenc, localenc, upos, sc->name==NULL?"":sc->name,
+ chosung[(upos-0xAC00)/(21*28)],
+ jungsung[(upos-0xAC00)/28%21],
+ jongsung[(upos-0xAC00)%28] );
+#endif
+ utf82u_strcpy(space,cspace);
+ } else {
+#if defined( _NO_SNPRINTF ) || defined( __VMS )
+ sprintf( cspace, "%u 0x%x U+%04x \"%.25s\" %.50s", localenc, localenc, upos, sc->name==NULL?"":sc->name,
+ UnicodeRange(upos));
+#else
+ snprintf( cspace, sizeof(cspace), "%u 0x%x U+%04x \"%.25s\" %.50s", localenc, localenc, upos, sc->name==NULL?"":sc->name,
+ UnicodeRange(upos));
+#endif
+ utf82u_strcpy(space,cspace);
+ }
+ if ( upos>=0 && upos<0x110000 && _UnicodeNameAnnot!=NULL &&
+ _UnicodeNameAnnot[upos>>16][(upos>>8)&0xff][upos&0xff].annot!=NULL ) {
+ int left = sizeof(space)/sizeof(space[0]) - u_strlen(space)-1;
+ if ( left>4 ) {
+ uc_strcat(space,"\n");
+ uc_annot_strncat(space,_UnicodeNameAnnot[upos>>16][(upos>>8)&0xff][upos&0xff].annot,left-2);
+ }
+ }
+ if ( sc->comment!=NULL ) {
+ int left = sizeof(space)/sizeof(space[0]) - u_strlen(space)-1;
+ if ( left>4 ) {
+ uc_strcat(space,"\n\n");
+ utf82u_strncpy(space+u_strlen(space),sc->comment,left-2);
+ }
+ }
+ GGadgetPreparePopup(gw,space);
+}
+
+static void noop(void *_fv) {
+}
+
+static void *ddgencharlist(void *_fv,int32 *len) {
+ int i,j,cnt, gid;
+ FontView *fv = (FontView *) _fv;
+ SplineFont *sf = fv->sf;
+ EncMap *map = fv->map;
+ char *data;
+
+ for ( i=cnt=0; i<map->enccount; ++i ) if ( fv->selected[i] && (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL )
+ cnt += strlen(sf->glyphs[gid]->name)+1;
+ data = galloc(cnt+1); data[0] = '\0';
+ for ( cnt=0, j=1 ; j<=fv->sel_index; ++j ) {
+ for ( i=cnt=0; i<map->enccount; ++i )
+ if ( fv->selected[i] && (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL ) {
+ strcpy(data+cnt,sf->glyphs[gid]->name);
+ cnt += strlen(sf->glyphs[gid]->name);
+ strcpy(data+cnt++," ");
+ }
+ }
+ if ( cnt>0 )
+ data[--cnt] = '\0';
+ *len = cnt;
+return( data );
+}
+
+static void FVMouse(FontView *fv,GEvent *event) {
+ int pos = (event->u.mouse.y/fv->cbh + fv->rowoff)*fv->colcnt + event->u.mouse.x/fv->cbw;
+ int gid;
+ int realpos = pos;
+ SplineChar *sc, dummy;
+ int dopopup = true;
+ extern int OpenCharsInNewWindow;
+
+ if ( event->type==et_mousedown )
+ CVPaletteDeactivate();
+ if ( pos<0 ) {
+ pos = 0;
+ dopopup = false;
+ } else if ( pos>=fv->map->enccount ) {
+ pos = fv->map->enccount-1;
+ if ( pos<0 ) /* No glyph slots in font */
+return;
+ dopopup = false;
+ }
+
+ sc = (gid=fv->map->map[pos])!=-1 ? fv->sf->glyphs[gid] : NULL;
+ if ( sc==NULL )
+ sc = SCBuildDummy(&dummy,fv->sf,fv->map,pos);
+ if ( event->type == et_mouseup && event->u.mouse.clicks==2 ) {
+ if ( fv->cur_subtable!=NULL ) {
+ sc = FVMakeChar(fv,pos);
+ pos = fv->map->backmap[sc->orig_pos];
+ }
+ if ( sc==&dummy ) {
+ sc = SFMakeChar(fv->sf,fv->map,pos);
+ gid = fv->map->map[pos];
+ }
+ if ( fv->show==fv->filled ) {
+ SplineFont *sf = fv->sf;
+ gid = -1;
+ if ( !OpenCharsInNewWindow )
+ for ( gid=sf->glyphcnt-1; gid>=0; --gid )
+ if ( sf->glyphs[gid]!=NULL && sf->glyphs[gid]->views!=NULL )
+ break;
+ if ( gid!=-1 ) {
+ CharView *cv = sf->glyphs[gid]->views;
+ CVChangeSC(cv,sc);
+ GDrawSetVisible(cv->gw,true);
+ GDrawRaise(cv->gw);
+ } else
+ CharViewCreate(sc,fv,pos);
+ } else {
+ BDFFont *bdf = fv->show;
+ BDFChar *bc =BDFMakeGID(bdf,gid);
+ gid = -1;
+ if ( !OpenCharsInNewWindow )
+ for ( gid=bdf->glyphcnt-1; gid>=0; --gid )
+ if ( bdf->glyphs[gid]!=NULL && bdf->glyphs[gid]->views!=NULL )
+ break;
+ if ( gid!=-1 ) {
+ BitmapView *bv = bdf->glyphs[gid]->views;
+ BVChangeBC(bv,bc,true);
+ GDrawSetVisible(bv->gw,true);
+ GDrawRaise(bv->gw);
+ } else
+ BitmapViewCreate(bc,bdf,fv,pos);
+ }
+ } else if ( event->type == et_mousemove ) {
+ if ( dopopup )
+ SCPreparePopup(fv->v,sc,fv->map->remap,pos,sc==&dummy?dummy.unicodeenc: UniFromEnc(pos,fv->map->enc));
+ }
+ if ( event->type == et_mousedown ) {
+ if ( fv->drag_and_drop ) {
+ GDrawSetCursor(fv->v,ct_mypointer);
+ fv->any_dd_events_sent = fv->drag_and_drop = false;
+ }
+ if ( !(event->u.mouse.state&ksm_shift) && event->u.mouse.clicks<=1 ) {
+ if ( !fv->selected[pos] )
+ FVDeselectAll(fv);
+ else if ( event->u.mouse.button!=3 ) {
+ fv->drag_and_drop = fv->has_dd_no_cursor = true;
+ fv->any_dd_events_sent = false;
+ GDrawSetCursor(fv->v,ct_prohibition);
+ GDrawGrabSelection(fv->v,sn_drag_and_drop);
+ GDrawAddSelectionType(fv->v,sn_drag_and_drop,"STRING",fv,0,sizeof(char),
+ ddgencharlist,noop);
+ }
+ }
+ fv->pressed_pos = fv->end_pos = pos;
+ FVShowInfo(fv);
+ if ( !fv->drag_and_drop ) {
+ if ( !(event->u.mouse.state&ksm_shift))
+ fv->sel_index = 1;
+ else if ( fv->sel_index<255 )
+ ++fv->sel_index;
+ if ( fv->pressed!=NULL )
+ GDrawCancelTimer(fv->pressed);
+ else if ( event->u.mouse.state&ksm_shift ) {
+ fv->selected[pos] = fv->selected[pos] ? 0 : fv->sel_index;
+ FVToggleCharSelected(fv,pos);
+ } else if ( !fv->selected[pos] ) {
+ fv->selected[pos] = fv->sel_index;
+ FVToggleCharSelected(fv,pos);
+ }
+ if ( event->u.mouse.button==3 )
+ GMenuCreatePopupMenu(fv->v,event, fvpopupmenu);
+ else
+ fv->pressed = GDrawRequestTimer(fv->v,200,100,NULL);
+ }
+ } else if ( fv->drag_and_drop ) {
+ if ( event->u.mouse.x>=0 && event->u.mouse.y>=-fv->mbh-fv->infoh-4 &&
+ event->u.mouse.x<=fv->width+20 && event->u.mouse.y<fv->height ) {
+ if ( !fv->has_dd_no_cursor ) {
+ fv->has_dd_no_cursor = true;
+ GDrawSetCursor(fv->v,ct_prohibition);
+ }
+ } else {
+ if ( fv->has_dd_no_cursor ) {
+ fv->has_dd_no_cursor = false;
+ GDrawSetCursor(fv->v,ct_ddcursor);
+ }
+ GDrawPostDragEvent(fv->v,event,event->type==et_mouseup?et_drop:et_drag);
+ fv->any_dd_events_sent = true;
+ }
+ if ( event->type==et_mouseup ) {
+ fv->drag_and_drop = fv->has_dd_no_cursor = false;
+ GDrawSetCursor(fv->v,ct_mypointer);
+ if ( !fv->any_dd_events_sent )
+ FVDeselectAll(fv);
+ fv->any_dd_events_sent = false;
+ }
+ } else if ( fv->pressed!=NULL ) {
+ int showit = realpos!=fv->end_pos;
+ FVReselect(fv,realpos);
+ if ( showit )
+ FVShowInfo(fv);
+ if ( event->type==et_mouseup ) {
+ GDrawCancelTimer(fv->pressed);
+ fv->pressed = NULL;
+ }
+ }
+ if ( event->type==et_mouseup && dopopup )
+ SCPreparePopup(fv->v,sc,fv->map->remap,pos,sc==&dummy?dummy.unicodeenc: UniFromEnc(pos,fv->map->enc));
+ if ( event->type==et_mouseup )
+ SVAttachFV(fv,2);
+}
+
+#if defined(FONTFORGE_CONFIG_GTK)
+gboolean FontView_ViewportResize(GtkWidget *widget, GdkEventConfigure *event,
+ gpointer user_data) {
+ extern int default_fv_row_count, default_fv_col_count;
+ int cc, rc;
+ FontView *fv = (FontView *) g_object_get_data( widget, "data" );
+
+ cc = (event->width-1)/fv->cbw; rc = (event->height-1)/fv->cbh;
+ if ( cc==0 ) cc = 1; if ( rc==0 ) rc = 1;
+
+ if ( event->width==fv->width || event->height==fv->height )
+ /* Ok, the window manager didn't change the size. */
+ else if ( event->width!=cc*fv->cbw+1 || event->height!=rc*fv->cbh+1 ) {
+ gtk_widget_set_size_request( widget, cc*fv->cbw+1, rc*fv->cbh+1);
+return TRUE;
+ }
+ gtk_widget_set_size_request( lookup_widget(widget,"view"), 1, 1 );
+ fv->width = width; fv->height = height;
+
+ default_fv_row_count = rc;
+ default_fv_col_count = cc;
+ SavePrefs();
+
+return TRUE;
+}
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+static void FVResize(FontView *fv,GEvent *event) {
+ extern int default_fv_row_count, default_fv_col_count;
+ GRect pos,screensize;
+ int topchar;
+
+ if ( fv->colcnt!=0 )
+ topchar = fv->rowoff*fv->colcnt;
+ else if ( fv->sf->top_enc!=-1 && fv->sf->top_enc<fv->map->enccount )
+ topchar = fv->sf->top_enc;
+ else {
+ /* Position on 'A' if it exists */
+ topchar = SFFindSlot(fv->sf,fv->map,'A',NULL);
+ if ( topchar==-1 ) {
+ for ( topchar=0; topchar<fv->map->enccount; ++topchar )
+ if ( fv->map->map[topchar]!=-1 && fv->sf->glyphs[fv->map->map[topchar]]!=NULL )
+ break;
+ if ( topchar==fv->map->enccount )
+ topchar = 0;
+ }
+ }
+ if ( !event->u.resize.sized )
+ /* WM isn't responding to my resize requests, so no point in trying */;
+ else if ( (event->u.resize.size.width-
+ GDrawPointsToPixels(fv->gw,_GScrollBar_Width)-1)%fv->cbw!=0 ||
+ (event->u.resize.size.height-fv->mbh-fv->infoh-1)%fv->cbh!=0 ) {
+ int cc = (event->u.resize.size.width+fv->cbw/2-
+ GDrawPointsToPixels(fv->gw,_GScrollBar_Width)-1)/fv->cbw;
+ int rc = (event->u.resize.size.height-fv->mbh-fv->infoh-1)/fv->cbh;
+ if ( cc<=0 ) cc = 1;
+ if ( rc<=0 ) rc = 1;
+ GDrawGetSize(GDrawGetRoot(NULL),&screensize);
+ if ( cc*fv->cbw+GDrawPointsToPixels(fv->gw,_GScrollBar_Width)+10>screensize.width )
+ --cc;
+ if ( rc*fv->cbh+fv->mbh+fv->infoh+20>screensize.height )
+ --rc;
+ GDrawResize(fv->gw,
+ cc*fv->cbw+1+GDrawPointsToPixels(fv->gw,_GScrollBar_Width),
+ rc*fv->cbh+1+fv->mbh+fv->infoh);
+ /* somehow KDE loses this event of mine so to get even the vague effect */
+ /* we can't just return */
+/*return;*/
+ }
+
+ pos.width = GDrawPointsToPixels(fv->gw,_GScrollBar_Width);
+ pos.height = event->u.resize.size.height-fv->mbh-fv->infoh;
+ pos.x = event->u.resize.size.width-pos.width; pos.y = fv->mbh+fv->infoh;
+ GGadgetResize(fv->vsb,pos.width,pos.height);
+ GGadgetMove(fv->vsb,pos.x,pos.y);
+ pos.width = pos.x; pos.x = 0;
+ GDrawResize(fv->v,pos.width,pos.height);
+
+ fv->width = pos.width; fv->height = pos.height;
+ fv->colcnt = (fv->width-1)/fv->cbw;
+ if ( fv->colcnt<1 ) fv->colcnt = 1;
+ fv->rowcnt = (fv->height-1)/fv->cbh;
+ if ( fv->rowcnt<1 ) fv->rowcnt = 1;
+ fv->rowltot = (fv->map->enccount+fv->colcnt-1)/fv->colcnt;
+
+ GScrollBarSetBounds(fv->vsb,0,fv->rowltot,fv->rowcnt);
+ fv->rowoff = topchar/fv->colcnt;
+ if ( fv->rowoff>=fv->rowltot-fv->rowcnt )
+ fv->rowoff = fv->rowltot-fv->rowcnt;
+ if ( fv->rowoff<0 ) fv->rowoff =0;
+ GScrollBarSetPos(fv->vsb,fv->rowoff);
+ GDrawRequestExpose(fv->gw,NULL,true);
+ GDrawRequestExpose(fv->v,NULL,true);
+
+ default_fv_row_count = fv->rowcnt;
+ default_fv_col_count = fv->colcnt;
+ SavePrefs();
+}
+#endif
+
+static void FVTimer(FontView *fv,GEvent *event) {
+
+ if ( event->u.timer.timer==fv->pressed ) {
+ GEvent e;
+ GDrawGetPointerPosition(fv->v,&e);
+ if ( e.u.mouse.y<0 || e.u.mouse.y >= fv->height ) {
+ real dy = 0;
+ if ( e.u.mouse.y<0 )
+ dy = -1;
+ else if ( e.u.mouse.y>=fv->height )
+ dy = 1;
+ if ( fv->rowoff+dy<0 )
+ dy = 0;
+ else if ( fv->rowoff+dy+fv->rowcnt > fv->rowltot )
+ dy = 0;
+ fv->rowoff += dy;
+ if ( dy!=0 ) {
+ GScrollBarSetPos(fv->vsb,fv->rowoff);
+ GDrawScroll(fv->v,NULL,0,dy*fv->cbh);
+ }
+ }
+ } else if ( event->u.timer.timer==fv->resize ) {
+ /* It's a delayed resize event (for kde which sends continuous resizes) */
+ fv->resize = NULL;
+ FVResize(fv,(GEvent *) (event->u.timer.userdata));
+ } else if ( event->u.timer.userdata!=NULL ) {
+ /* It's a delayed function call */
+ void (*func)(FontView *) = (void (*)(FontView *)) (event->u.timer.userdata);
+ func(fv);
+ }
+}
+
+void FVDelay(FontView *fv,void (*func)(FontView *)) {
+ GDrawRequestTimer(fv->v,100,0,(void *) func);
+}
+
+static void FVScroll(FontView *fv,struct sbevent *sb) {
+ int newpos = fv->rowoff;
+
+ switch( sb->type ) {
+ case et_sb_top:
+ newpos = 0;
+ break;
+ case et_sb_uppage:
+ newpos -= fv->rowcnt;
+ break;
+ case et_sb_up:
+ --newpos;
+ break;
+ case et_sb_down:
+ ++newpos;
+ break;
+ case et_sb_downpage:
+ newpos += fv->rowcnt;
+ break;
+ case et_sb_bottom:
+ newpos = fv->rowltot-fv->rowcnt;
+ break;
+ case et_sb_thumb:
+ case et_sb_thumbrelease:
+ newpos = sb->pos;
+ break;
+ }
+ if ( newpos>fv->rowltot-fv->rowcnt )
+ newpos = fv->rowltot-fv->rowcnt;
+ if ( newpos<0 ) newpos =0;
+ if ( newpos!=fv->rowoff ) {
+ int diff = newpos-fv->rowoff;
+ fv->rowoff = newpos;
+ GScrollBarSetPos(fv->vsb,fv->rowoff);
+ GDrawScroll(fv->v,NULL,0,diff*fv->cbh);
+ }
+}
+
+static int v_e_h(GWindow gw, GEvent *event) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+
+ if (( event->type==et_mouseup || event->type==et_mousedown ) &&
+ (event->u.mouse.button==4 || event->u.mouse.button==5) ) {
+return( GGadgetDispatchEvent(fv->vsb,event));
+ }
+
+ GGadgetPopupExternalEvent(event);
+ switch ( event->type ) {
+ case et_expose:
+ GDrawSetLineWidth(gw,0);
+ FVExpose(fv,gw,event);
+ break;
+ case et_char:
+ FVChar(fv,event);
+ break;
+ case et_mousemove: case et_mousedown: case et_mouseup:
+ if ( event->type==et_mousedown )
+ GDrawSetGIC(gw,fv->gic,0,20);
+ FVMouse(fv,event);
+ break;
+ case et_timer:
+ FVTimer(fv,event);
+ break;
+ case et_focus:
+ if ( event->u.focus.gained_focus ) {
+ GDrawSetGIC(gw,fv->gic,0,20);
+#if 0
+ CVPaletteDeactivate();
+#endif
+ }
+ break;
+ }
+return( true );
+}
+
+void FontViewReformatOne(FontView *fv) {
+ FontView *fvs;
+
+ if ( fv->v==NULL || fv->colcnt==0 ) /* Can happen in scripts */
+return;
+
+ GDrawSetCursor(fv->v,ct_watch);
+ fv->rowltot = (fv->map->enccount+fv->colcnt-1)/fv->colcnt;
+ GScrollBarSetBounds(fv->vsb,0,fv->rowltot,fv->rowcnt);
+ if ( fv->rowoff>fv->rowltot-fv->rowcnt ) {
+ fv->rowoff = fv->rowltot-fv->rowcnt;
+ if ( fv->rowoff<0 ) fv->rowoff =0;
+ GScrollBarSetPos(fv->vsb,fv->rowoff);
+ }
+ for ( fvs=fv->sf->fv; fvs!=NULL; fvs=fvs->nextsame )
+ if ( fvs!=fv && fvs->sf==fv->sf )
+ break;
+ GDrawRequestExpose(fv->v,NULL,false);
+ GDrawSetCursor(fv->v,ct_pointer);
+}
+
+void FontViewReformatAll(SplineFont *sf) {
+ BDFFont *new, *old;
+ FontView *fvs, *fv;
+
+ if ( sf->fv->v==NULL || sf->fv->colcnt==0 ) /* Can happen in scripts */
+return;
+
+ for ( fvs=sf->fv; fvs!=NULL; fvs=fvs->nextsame )
+ fvs->touched = false;
+ while ( 1 ) {
+ for ( fv=sf->fv; fv!=NULL && fv->touched; fv=fv->nextsame );
+ if ( fv==NULL )
+ break;
+ old = fv->filled;
+ /* In CID fonts fv->sf may not be same as sf */
+ new = SplineFontPieceMeal(fv->sf,fv->filled->pixelsize,
+ (fv->antialias?pf_antialias:0)|(fv->bbsized?pf_bbsized:0),
+ NULL);
+ for ( fvs=fv; fvs!=NULL; fvs=fvs->nextsame )
+ if ( fvs->filled == old ) {
+ fvs->filled = new;
+ if ( fvs->show == old )
+ fvs->show = new;
+ fvs->touched = true;
+ }
+ BDFFontFree(old);
+ }
+ for ( fv=sf->fv; fv!=NULL; fv=fv->nextsame ) {
+ GDrawSetCursor(fv->v,ct_watch);
+ fv->rowltot = (fv->map->enccount+fv->colcnt-1)/fv->colcnt;
+ GScrollBarSetBounds(fv->vsb,0,fv->rowltot,fv->rowcnt);
+ if ( fv->rowoff>fv->rowltot-fv->rowcnt ) {
+ fv->rowoff = fv->rowltot-fv->rowcnt;
+ if ( fv->rowoff<0 ) fv->rowoff =0;
+ GScrollBarSetPos(fv->vsb,fv->rowoff);
+ }
+ GDrawRequestExpose(fv->v,NULL,false);
+ GDrawSetCursor(fv->v,ct_pointer);
+ }
+}
+
+static int fv_e_h(GWindow gw, GEvent *event) {
+ FontView *fv = (FontView *) GDrawGetUserData(gw);
+
+ if (( event->type==et_mouseup || event->type==et_mousedown ) &&
+ (event->u.mouse.button==4 || event->u.mouse.button==5) ) {
+return( GGadgetDispatchEvent(fv->vsb,event));
+ }
+
+ switch ( event->type ) {
+ case et_selclear:
+ ClipboardClear();
+ break;
+ case et_expose:
+ GDrawSetLineWidth(gw,0);
+ FVDrawInfo(fv,gw,event);
+ break;
+ case et_resize:
+ /* KDE sends a continuous stream of resize events, and gets very */
+ /* confused if I start resizing the window myself, try to wait for */
+ /* the user to finish before responding to resizes */
+ if ( event->u.resize.sized || fv->resize_expected ) {
+ if ( fv->resize )
+ GDrawCancelTimer(fv->resize);
+ fv->resize_event = *event;
+ fv->resize = GDrawRequestTimer(fv->v,300,0,(void *) &fv->resize_event);
+ fv->resize_expected = false;
+ }
+ break;
+ case et_char:
+ FVChar(fv,event);
+ break;
+ case et_controlevent:
+ switch ( event->u.control.subtype ) {
+ case et_scrollbarchange:
+ FVScroll(fv,&event->u.control.u.sb);
+ break;
+ }
+ break;
+ case et_close:
+ FVMenuClose(gw,NULL,NULL);
+ break;
+ case et_create:
+ fv->next = fv_list;
+ fv_list = fv;
+ break;
+ case et_destroy:
+ if ( fv_list==fv )
+ fv_list = fv->next;
+ else {
+ FontView *n;
+ for ( n=fv_list; n->next!=fv; n=n->next );
+ n->next = fv->next;
+ }
+ if ( fv_list!=NULL ) /* Freeing a large font can take forever, and if we're just going to exit there's no real reason to do so... */
+ FontViewFree(fv);
+ break;
+ }
+return( true );
+}
+
+static void FontViewOpenKids(FontView *fv) {
+ int k, i;
+ SplineFont *sf = fv->sf, *_sf;
+
+ if ( sf->cidmaster!=NULL )
+ sf = sf->cidmaster;
+
+ k=0;
+ do {
+ _sf = sf->subfontcnt==0 ? sf : sf->subfonts[k];
+ for ( i=0; i<_sf->glyphcnt; ++i )
+ if ( _sf->glyphs[i]!=NULL && _sf->glyphs[i]->wasopen ) {
+ _sf->glyphs[i]->wasopen = false;
+ CharViewCreate(_sf->glyphs[i],fv,-1);
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+}
+#endif
+
+FontView *_FontViewCreate(SplineFont *sf) {
+ FontView *fv = gcalloc(1,sizeof(FontView));
+ int i;
+ int ps = sf->display_size<0 ? -sf->display_size :
+ sf->display_size==0 ? default_fv_font_size : sf->display_size;
+
+ if ( ps>200 ) ps = 128;
+
+ fv->nextsame = sf->fv;
+ sf->fv = fv;
+ if ( sf->mm!=NULL ) {
+ sf->mm->normal->fv = fv;
+ for ( i = 0; i<sf->mm->instance_count; ++i )
+ sf->mm->instances[i]->fv = fv;
+ }
+ if ( sf->subfontcnt==0 ) {
+ fv->sf = sf;
+ if ( fv->nextsame!=NULL ) {
+ fv->map = EncMapCopy(fv->nextsame->map);
+ fv->normal = fv->nextsame->normal==NULL ? NULL : EncMapCopy(fv->nextsame->normal);
+ } else if ( sf->compacted ) {
+ fv->normal = sf->map;
+ fv->map = CompactEncMap(EncMapCopy(sf->map),sf);
+ } else {
+ fv->map = sf->map;
+ fv->normal = NULL;
+ }
+ } else {
+ fv->cidmaster = sf;
+ for ( i=0; i<sf->subfontcnt; ++i )
+ sf->subfonts[i]->fv = fv;
+ for ( i=0; i<sf->subfontcnt; ++i ) /* Search for a subfont that contains more than ".notdef" (most significant in .gai fonts) */
+ if ( sf->subfonts[i]->glyphcnt>1 ) {
+ fv->sf = sf->subfonts[i];
+ break;
+ }
+ if ( fv->sf==NULL )
+ fv->sf = sf->subfonts[0];
+ sf = fv->sf;
+ if ( fv->nextsame==NULL ) EncMapFree(sf->map);
+ fv->map = EncMap1to1(sf->glyphcnt);
+ }
+ fv->selected = gcalloc(fv->map->enccount,sizeof(char));
+ fv->user_requested_magnify = -1;
+ fv->magnify = (ps<=9)? 3 : (ps<20) ? 2 : 1;
+ fv->cbw = (ps*fv->magnify)+1;
+ fv->cbh = (ps*fv->magnify)+1+fv->lab_height+1;
+ fv->antialias = sf->display_antialias;
+ fv->bbsized = sf->display_bbsized;
+ fv->glyphlabel = default_fv_glyphlabel;
+
+ fv->end_pos = -1;
+return( fv );
+}
+
+#ifndef LUA_FF_LIB
+static void FontViewInit(void) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ mb2DoGetText(mblist);
+ mbDoGetText(fvpopupmenu);
+#endif
+}
+#endif
+
+FontView *FontViewCreate(SplineFont *sf) {
+ FontView *fv = _FontViewCreate(sf);
+#if defined(FONTFORGE_CONFIG_GTK)
+ static int done = false;
+ GtkWidget *status;
+ PangoContext *context;
+ PangoFont *font;
+ PangoFontMetrics *fm;
+ int as, ds;
+ BDFFont *bdf;
+
+ if ( !done ) { FontViewInit(); done=true;}
+
+ fv->gw = create_FontView();
+ g_object_set_data (G_OBJECT (fv->gw), "data", fv );
+ fv->v = lookup_widget( fv->gw,"view" );
+ status = lookup_widget( fv->gw,"status" );
+ context = gtk_widget_get_pango_context( status );
+ fv->gc = gdk_gc_new( fv->v );
+ gdk_gc_copy(fv->gc,fv->v->style->fg_gc[fv->v->state]);
+ font = pango_context_load_font( context, pango_context_get_font_description(context));
+ fm = pango_font_get_metrics(font,NULL);
+ as = pango_font_metrics_get_ascent(fm);
+ ds = pango_font_metrics_get_descent(fm);
+ fv->infoh = (as+ds)/1024;
+ gtk_widget_set_size_request(status,0,fv->infoh);
+
+ context = gtk_widget_get_pango_context( fv->v );
+ font = pango_context_load_font( context, pango_context_get_font_description(context));
+ fm = pango_font_get_metrics(font,NULL);
+ as = pango_font_metrics_get_ascent(fm);
+ ds = pango_font_metrics_get_descent(fm);
+ fv->lab_height = (as+ds)/1024;
+ fv->lab_as = as/1024;
+
+ g_object_set_data( fv->gw, "data", fv );
+ g_object_set_data( fv->v , "data", fv );
+
+ {
+ GdkGC *gc = fv->v->style->fg_gc[fv->v->state];
+ GdkGCValues values;
+ gdk_gc_get_values(gc,&values);
+ default_background = COLOR_CREATE(
+ ((values.background.red &0xff00)>>8) |
+ ((values.background.green&0xff00)>>8) |
+ ((values.background.blue &0xff00)>>8));
+ }
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+ static int done = false;
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GGadgetData gd;
+ GRect gsize;
+ FontRequest rq;
+ /* sadly, clearlyu is too big for the space I've got */
+ static unichar_t monospace[] = { 'f','o','n','t','v','i','e','w',',','c','o','u','r','i','e','r',',','m', 'o', 'n', 'o', 's', 'p', 'a', 'c', 'e',',','c','a','s','l','o','n',',','c','l','e','a','r','l','y','u',',','u','n','i','f','o','n','t', '\0' };
+ static unichar_t *fontnames=NULL;
+ static GWindow icon = NULL;
+ static int nexty=0;
+ GRect size;
+ BDFFont *bdf;
+ int as,ds,ld;
+
+ if ( !done ) { FontViewInit(); done=true;}
+ if ( icon==NULL ) {
+#ifdef BIGICONS
+ icon = GDrawCreateBitmap(NULL,fontview_width,fontview_height,fontview_bits);
+#else
+ icon = GDrawCreateBitmap(NULL,fontview2_width,fontview2_height,fontview2_bits);
+#endif
+ }
+
+ GDrawGetSize(GDrawGetRoot(NULL),&size);
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_icon;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.cursor = ct_pointer;
+ wattrs.icon = icon;
+ pos.width = sf->desired_col_cnt*fv->cbw+1;
+ pos.height = sf->desired_row_cnt*fv->cbh+1;
+ pos.x = size.width-pos.width-30; pos.y = nexty;
+ nexty += 2*fv->cbh+50;
+ if ( nexty+pos.height > size.height )
+ nexty = 0;
+ fv->gw = gw = GDrawCreateTopWindow(NULL,&pos,fv_e_h,fv,&wattrs);
+ FVSetTitle(fv);
+
+ if ( !fv_fs_init )
+ fv_fontsize = -GResourceFindInt("FontView.FontSize",13);
+
+ memset(&gd,0,sizeof(gd));
+ gd.flags = gg_visible | gg_enabled;
+ helplist[0].invoke = FVMenuContextualHelp;
+ gd.u.menu2 = mblist;
+ fv->mb = GMenu2BarCreate( gw, &gd, NULL);
+ GGadgetGetSize(fv->mb,&gsize);
+ fv->mbh = gsize.height;
+ fv->infoh = 1-fv_fontsize;
+ fv->lab_height = FV_LAB_HEIGHT-13-fv_fontsize;
+
+ gd.pos.y = fv->mbh+fv->infoh; gd.pos.height = pos.height;
+ gd.pos.width = GDrawPointsToPixels(gw,_GScrollBar_Width);
+ gd.pos.x = pos.width;
+ gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
+ fv->vsb = GScrollBarCreate(gw,&gd,fv);
+
+ wattrs.mask = wam_events|wam_cursor;
+ pos.x = 0; pos.y = fv->mbh+fv->infoh;
+ fv->v = GWidgetCreateSubWindow(gw,&pos,v_e_h,fv,&wattrs);
+ GDrawSetVisible(fv->v,true);
+
+ fv->gic = GDrawCreateInputContext(fv->v,gic_root|gic_orlesser);
+ GDrawSetGIC(fv->v,fv->gic,0,20);
+
+ if ( fontnames==NULL ) {
+ fontnames = uc_copy(GResourceFindString("FontView.FontFamily"));
+ if ( fontnames==NULL )
+ fontnames = monospace;
+ }
+ fv->fontset = gcalloc(_uni_fontmax,sizeof(GFont *));
+ memset(&rq,0,sizeof(rq));
+ rq.family_name = fontnames;
+ rq.point_size = fv_fontsize;
+ rq.weight = 400;
+ fv->fontset[0] = GDrawInstanciateFont(GDrawGetDisplayOfWindow(gw),&rq);
+ GDrawSetFont(fv->v,fv->fontset[0]);
+ GDrawFontMetrics(fv->fontset[0],&as,&ds,&ld);
+ fv->lab_as = as;
+#endif
+ fv->showhmetrics = default_fv_showhmetrics;
+ fv->showvmetrics = default_fv_showvmetrics && sf->hasvmetrics;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( fv->nextsame!=NULL ) {
+ fv->filled = fv->nextsame->filled;
+ bdf = fv->nextsame->show;
+ } else {
+ bdf = SplineFontPieceMeal(fv->sf,sf->display_size<0?-sf->display_size:default_fv_font_size,
+ (fv->antialias?pf_antialias:0)|(fv->bbsized?pf_bbsized:0),
+ NULL);
+ fv->filled = bdf;
+ if ( sf->display_size>0 ) {
+ for ( bdf=sf->bitmaps; bdf!=NULL && bdf->pixelsize!=sf->display_size ;
+ bdf=bdf->next );
+ if ( bdf==NULL )
+ bdf = fv->filled;
+ }
+ if ( sf->onlybitmaps && bdf==fv->filled && sf->bitmaps!=NULL )
+ bdf = sf->bitmaps;
+ }
+ fv->cbw = -1;
+ FVChangeDisplayFont(fv,bdf);
+#endif
+
+#if defined(FONTFORGE_CONFIG_GTK)
+ gtk_widget_show(fv->gw);
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+ /*GWidgetHidePalettes();*/
+ GDrawSetVisible(gw,true);
+ FontViewOpenKids(fv);
+#endif
+return( fv );
+}
+
+#ifdef LUA_FF_LIB
+
+extern void SplineFontMetaData(SplineFont *sf,struct fontdict *fd) ;
+
+static SplineFont *SFReadPostscriptInfo(char *filename) {
+ FontDict *fd=NULL;
+ SplineFont *sf=NULL;
+ fd = ReadPSFont(filename);
+ if ( fd!=NULL ) {
+ if ( fd->sf!=NULL ) {
+ sf = fd->sf;
+ } else {
+ sf = SplineFontEmpty();
+ SplineFontMetaData(sf,fd);
+ if ( fd->wascff ) {
+ SplineFontFree(sf);
+ sf = fd->sf;
+ }
+ }
+ }
+ PSFontFree(fd);
+ return( sf );
+}
+#endif
+
+static SplineFont *SFReadPostscript(char *filename) {
+ FontDict *fd=NULL;
+ SplineFont *sf=NULL;
+# ifdef FONTFORGE_CONFIG_GDRAW
+ gwwv_progress_change_stages(2);
+ fd = ReadPSFont(filename);
+ gwwv_progress_next_stage();
+ gwwv_progress_change_line2(_("Interpreting Glyphs"));
+# elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_progress_change_stages(2);
+ fd = ReadPSFont(filename);
+ gwwv_progress_next_stage();
+ gwwv_progress_change_line2(_("Interpreting Glyphs"));
+# else
+ fd = ReadPSFont(filename);
+# endif
+ if ( fd!=NULL ) {
+ sf = SplineFontFromPSFont(fd);
+ PSFontFree(fd);
+ if ( sf!=NULL )
+ CheckAfmOfPostscript(sf,filename,sf->map);
+ }
+return( sf );
+}
+
+
+/* This does not check currently existing fontviews, and should only be used */
+/* by LoadSplineFont (which does) and by RevertFile (which knows what it's doing) */
+SplineFont *ReadSplineFont(char *filename,enum openflags openflags) {
+ SplineFont *sf;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ char ubuf[250], *temp;
+#endif
+ int fromsfd = false;
+ int i;
+ char *pt, *strippedname, *oldstrippedname, *tmpfile=NULL, *paren=NULL, *fullname=filename;
+ int len;
+ FILE *foo;
+ int checked;
+ int compression=0;
+
+ if ( filename==NULL )
+return( NULL );
+
+ strippedname = filename;
+ pt = strrchr(filename,'/');
+ if ( pt==NULL ) pt = filename;
+ if ( (paren=strchr(pt,'('))!=NULL && strchr(paren,')')!=NULL ) {
+ strippedname = copy(filename);
+ strippedname[paren-filename] = '\0';
+ }
+
+ pt = strrchr(strippedname,'.');
+ i = -1;
+ if ( pt!=NULL ) for ( i=0; compressors[i].ext!=NULL; ++i )
+ if ( strcmp(compressors[i].ext,pt)==0 )
+ break;
+ oldstrippedname = strippedname;
+ if ( i==-1 || compressors[i].ext==NULL ) i=-1;
+ else {
+ tmpfile = Decompress(strippedname,i);
+ if ( tmpfile!=NULL ) {
+ strippedname = tmpfile;
+ } else {
+ gwwv_post_error(_("Decompress Failed!"),_("Decompress Failed!"));
+return( NULL );
+ }
+ compression = i+1;
+ if ( strippedname!=filename && paren!=NULL ) {
+ fullname = galloc(strlen(strippedname)+strlen(paren)+1);
+ strcpy(fullname,strippedname);
+ strcat(fullname,paren);
+ } else
+ fullname = strippedname;
+ }
+
+ /* If there are no pfaedit windows, give them something to look at */
+ /* immediately. Otherwise delay a bit */
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ strcpy(ubuf,_("Loading font from "));
+ len = strlen(ubuf);
+# ifdef FONTFORGE_CONFIG_GDRAW
+ strncat(ubuf,temp = def2utf8_copy(GFileNameTail(fullname)),100);
+# elif defined(FONTFORGE_CONFIG_GTK)
+ {
+ gsize read, written;
+ strncat(ubuf,temp = g_filename_to_utf8(GFileNameTail(fullname),-1,&read,&written,NULL),100);
+ }
+#endif
+ free(temp);
+ ubuf[100+len] = '\0';
+ gwwv_progress_start_indicator(fv_list==NULL?0:10,_("Loading..."),ubuf,_("Reading Glyphs"),0,1);
+ gwwv_progress_enable_stop(0);
+ if ( fv_list==NULL && !no_windowing_ui ) { GDrawSync(NULL); GDrawProcessPendingEvents(NULL); }
+#else
+ len = 0;
+#endif
+
+ sf = NULL;
+ foo = fopen(strippedname,"rb");
+
+ checked = false;
+/* checked == false => not checked */
+/* checked == 'u' => UFO */
+/* checked == 't' => TTF/OTF */
+/* checked == 'p' => pfb/general postscript */
+/* checked == 'P' => pdf */
+/* checked == 'c' => cff */
+/* checked == 'S' => svg */
+/* checked == 'f' => sfd */
+/* checked == 'F' => sfdir */
+/* checked == 'b' => bdf */
+/* checked == 'i' => ikarus */
+#ifndef LUA_FF_LIB
+ if ( GFileIsDir(strippedname) ) {
+ char *temp = galloc(strlen(strippedname)+strlen("/glyphs/contents.plist")+1);
+ strcpy(temp,strippedname);
+ strcat(temp,"/glyphs/contents.plist");
+ if ( GFileExists(temp)) {
+ sf = SFReadUFO(strippedname,0);
+ checked = 'u';
+ } else {
+ strcpy(temp,strippedname);
+ strcat(temp,"/font.props");
+ if ( GFileExists(temp)) {
+ sf = SFDirRead(strippedname);
+ checked = 'F';
+ }
+ }
+ free(temp);
+ if ( foo!=NULL )
+ fclose(foo);
+ } else if ( foo!=NULL ) {
+#else
+ {
+#endif
+ /* Try to guess the file type from the first few characters... */
+ int ch1 = getc(foo);
+ int ch2 = getc(foo);
+ int ch3 = getc(foo);
+ int ch4 = getc(foo);
+ int ch5 = getc(foo);
+ int ch6 = getc(foo);
+ int ch7 = getc(foo);
+ int ch9, ch10;
+ fseek(foo, 98, SEEK_SET);
+ ch9 = getc(foo);
+ ch10 = getc(foo);
+ fclose(foo);
+ if (( ch1==0 && ch2==1 && ch3==0 && ch4==0 ) ||
+ (ch1=='O' && ch2=='T' && ch3=='T' && ch4=='O') ||
+ (ch1=='t' && ch2=='r' && ch3=='u' && ch4=='e') ||
+ (ch1=='t' && ch2=='t' && ch3=='c' && ch4=='f') ) {
+ sf = SFReadTTF(fullname,0,openflags);
+ checked = 't';
+ } else if (( ch1=='%' && ch2=='!' ) ||
+ ( ch1==0x80 && ch2=='\01' ) ) { /* PFB header */
+ sf = SFReadPostscript(fullname);
+ checked = 'p';
+#ifndef LUA_FF_LIB
+ } else if ( ch1=='%' && ch2=='P' && ch3=='D' && ch4=='F' ) {
+ sf = SFReadPdfFont(fullname,openflags);
+ checked = 'P';
+#endif
+ } else if ( ch1==1 && ch2==0 && ch3==4 ) {
+ sf = CFFParse(fullname);
+ checked = 'c';
+ } else if ( ch1=='<' && ch2=='?' && (ch3=='x'||ch3=='X') && (ch4=='m'||ch4=='M') ) {
+ sf = SFReadSVG(fullname,0);
+ checked = 'S';
+ } else if ( ch1==0xef && ch2==0xbb && ch3==0xbf &&
+ ch4=='<' && ch5=='?' && (ch6=='x'||ch6=='X') && (ch7=='m'||ch7=='M') ) {
+ /* UTF-8 SVG with initial byte ordering mark */
+ sf = SFReadSVG(fullname,0);
+ checked = 'S';
+#if 0 /* I'm not sure if this is a good test for mf files... */
+ } else if ( ch1=='%' && ch2==' ' ) {
+ sf = SFFromMF(fullname);
+#endif
+#ifndef LUA_FF_LIB
+ } else if ( ch1=='S' && ch2=='p' && ch3=='l' && ch4=='i' ) {
+ sf = SFDRead(fullname);
+ checked = 'f';
+ fromsfd = true;
+ } else if ( ch1=='S' && ch2=='T' && ch3=='A' && ch4=='R' ) {
+ sf = SFFromBDF(fullname,0,false);
+ checked = 'b';
+ } else if ( ch1=='\1' && ch2=='f' && ch3=='c' && ch4=='p' ) {
+ sf = SFFromBDF(fullname,2,false);
+ } else if ( ch9=='I' && ch10=='K' && ch3==0 && ch4==55 ) {
+ /* Ikarus font type appears at word 50 (byte offset 98) */
+ /* Ikarus name section length (at word 2, byte offset 2) was 55 in the 80s at URW */
+ checked = 'i';
+ sf = SFReadIkarus(fullname);
+#endif
+ } /* Too hard to figure out a valid mark for a mac resource file */
+ }
+
+ if ( sf!=NULL )
+ /* good */;
+#ifndef LUA_FF_LIB
+ else if (( strmatch(fullname+strlen(fullname)-4, ".sfd")==0 ||
+ strmatch(fullname+strlen(fullname)-5, ".sfd~")==0 ) && checked!='f' ) {
+ sf = SFDRead(fullname);
+ fromsfd = true;
+ }
+#endif
+ else if (( strmatch(fullname+strlen(fullname)-4, ".ttf")==0 ||
+ strmatch(fullname+strlen(strippedname)-4, ".ttc")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".gai")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".otf")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".otb")==0 ) && checked!='t') {
+ sf = SFReadTTF(fullname,0,openflags);
+ } else if ( strmatch(fullname+strlen(fullname)-4, ".svg")==0 && checked!='S' ) {
+ sf = SFReadSVG(fullname,0);
+ } else if ( strmatch(fullname+strlen(fullname)-4, ".ufo")==0 && checked!='u' ) {
+ sf = SFReadUFO(fullname,0);
+#ifndef LUA_FF_LIB
+ } else if ( strmatch(fullname+strlen(fullname)-4, ".bdf")==0 && checked!='b' ) {
+ sf = SFFromBDF(fullname,0,false);
+ } else if ( strmatch(fullname+strlen(fullname)-2, "pk")==0 ) {
+ sf = SFFromBDF(fullname,1,true);
+ } else if ( strmatch(fullname+strlen(fullname)-2, "gf")==0 ) {
+ sf = SFFromBDF(fullname,3,true);
+ } else if ( strmatch(fullname+strlen(fullname)-4, ".pcf")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".pmf")==0 ) {
+ /* Sun seems to use a variant of the pcf format which they call pmf */
+ /* the encoding actually starts at 0x2000 and the one I examined was */
+ /* for a pixel size of 200. Some sort of printer font? */
+ sf = SFFromBDF(fullname,2,false);
+#endif
+ } else if ( strmatch(fullname+strlen(strippedname)-4, ".bin")==0 ||
+ strmatch(fullname+strlen(strippedname)-4, ".hqx")==0 ||
+ strmatch(fullname+strlen(strippedname)-6, ".dfont")==0 ) {
+ sf = SFReadMacBinary(fullname,0,openflags);
+#ifndef LUA_FF_LIB
+ } else if ( strmatch(fullname+strlen(strippedname)-4, ".fon")==0 ||
+ strmatch(fullname+strlen(strippedname)-4, ".fnt")==0 ) {
+ sf = SFReadWinFON(fullname,0);
+ } else if ( strmatch(fullname+strlen(strippedname)-4, ".pdb")==0 ) {
+ sf = SFReadPalmPdb(fullname,0);
+#endif
+ } else if ( (strmatch(fullname+strlen(fullname)-4, ".pfa")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".pfb")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".pf3")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".cid")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".gsf")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".pt3")==0 ||
+ strmatch(fullname+strlen(fullname)-3, ".ps")==0 ) && checked!='p' ) {
+ sf = SFReadPostscript(fullname);
+ } else if ( strmatch(fullname+strlen(fullname)-4, ".cff")==0 && checked!='c' ) {
+ sf = CFFParse(fullname);
+#ifndef LUA_FF_LIB
+ } else if ( strmatch(fullname+strlen(fullname)-3, ".mf")==0 ) {
+ sf = SFFromMF(fullname);
+ } else if ( strmatch(fullname+strlen(fullname)-4, ".pdf")==0 && checked!='P' ) {
+ sf = SFReadPdfFont(fullname,openflags);
+ } else if ( strmatch(fullname+strlen(fullname)-3, ".ik")==0 && checked!='i' ) {
+ sf = SFReadIkarus(fullname);
+#endif
+ } else {
+ sf = SFReadMacBinary(fullname,0,openflags);
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_end_indicator();
+# endif
+
+ if ( sf!=NULL ) {
+ SplineFont *norm = sf->mm!=NULL ? sf->mm->normal : sf;
+ if ( compression!=0 ) {
+ free(sf->filename);
+ *strrchr(oldstrippedname,'.') = '\0';
+ sf->filename = copy( oldstrippedname );
+ }
+ if ( fromsfd )
+ sf->compression = compression;
+ free( norm->origname );
+ if ( sf->chosenname!=NULL && strippedname==filename ) {
+ norm->origname = galloc(strlen(filename)+strlen(sf->chosenname)+8);
+ strcpy(norm->origname,filename);
+ strcat(norm->origname,"(");
+ strcat(norm->origname,sf->chosenname);
+ strcat(norm->origname,")");
+ } else
+ norm->origname = copy(filename);
+ free( sf->chosenname ); sf->chosenname = NULL;
+ if ( sf->mm!=NULL ) {
+ int j;
+ for ( j=0; j<sf->mm->instance_count; ++j ) {
+ free(sf->mm->instances[j]->origname);
+ sf->mm->instances[j]->origname = copy(norm->origname);
+ }
+ }
+ } else if ( !GFileExists(filename) )
+#if defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("Couldn't open font"),_("The requested file, %.100s, does not exist"),GFileNameTail(filename));
+#else
+ gwwv_post_error(_("Couldn't open font"),_("The requested file, %.100s, does not exist"),GFileNameTail(filename));
+#endif
+ else if ( !GFileReadable(filename) )
+#if defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("Couldn't open font"),_("You do not have permission to read %.100s"),GFileNameTail(filename));
+#else
+ gwwv_post_error(_("Couldn't open font"),_("You do not have permission to read %.100s"),GFileNameTail(filename));
+#endif
+ else
+#if defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("Couldn't open font"),_("%.100s is not in a known format (or is so badly corrupted as to be unreadable)"),GFileNameTail(filename));
+#else
+ gwwv_post_error(_("Couldn't open font"),_("%.100s is not in a known format (or is so badly corrupted as to be unreadable)"),GFileNameTail(filename));
+#endif
+
+ if ( oldstrippedname!=filename )
+ free(oldstrippedname);
+ if ( fullname!=filename && fullname!=strippedname )
+ free(fullname);
+ if ( tmpfile!=NULL ) {
+ unlink(tmpfile);
+ free(tmpfile);
+ }
+ if ( (openflags&of_fstypepermitted) && sf!=NULL && (sf->pfminfo.fstype&0xff)==0x0002 ) {
+ /* Ok, they have told us from a script they have access to the font */
+ } else if ( !fromsfd && sf!=NULL && (sf->pfminfo.fstype&0xff)==0x0002 ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buts[3];
+ buts[0] = _("_Yes"); buts[1] = _("_No"); buts[2] = NULL;
+ if ( gwwv_ask(_("Restricted Font"),(const char **) buts,1,1,_("This font is marked with an FSType of 2 (Restricted\nLicense). That means it is not editable without the\npermission of the legal owner.\n\nDo you have such permission?"))==1 ) {
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buts[] = { GTK_STOCK_YES, GTK_STOCK_NO, NULL };
+ if ( gwwv_ask(_("Restricted Font"),(const char **) buts,1,1,_("This font is marked with an FSType of 2 (Restricted\nLicense). That means it is not editable without the\npermission of the legal owner.\n\nDo you have such permission?"))==1 ) {
+#else
+ if ( true ) { /* In a script, if they didn't explicitly say so, fail */
+#endif
+ SplineFontFree(sf);
+return( NULL );
+ }
+ }
+return( sf );
+}
+
+#ifdef LUA_FF_LIB
+SplineFont *ReadSplineFontInfo(char *filename,enum openflags openflags) {
+ SplineFont *sf, *sf_ptr;
+ char **fontlist;
+ char *pt =NULL, *strippedname=filename, *paren=NULL, *fullname=filename;
+ FILE *foo = NULL;
+ int checked = 0;
+ char s[512] = {0};
+
+ if ( filename==NULL )
+return( NULL );
+
+ pt = strrchr(filename,'/');
+ if ( pt==NULL ) pt = filename;
+ if ( (paren=strchr(pt,'('))!=NULL && strchr(paren,')')!=NULL ) {
+ strippedname = copy(filename);
+ strippedname[paren-filename] = '\0';
+ }
+
+ sf = NULL;
+ foo = fopen(strippedname,"rb");
+ checked = false;
+ if ( foo!=NULL ) {
+ /* Try to guess the file type from the first few characters... */
+ int ch1 = getc(foo);
+ int ch2 = getc(foo);
+ int ch3 = getc(foo);
+ int ch4 = getc(foo);
+ fclose(foo);
+ if (( ch1==0 && ch2==1 && ch3==0 && ch4==0 ) ||
+ (ch1=='O' && ch2=='T' && ch3=='T' && ch4=='O') ||
+ (ch1=='t' && ch2=='r' && ch3=='u' && ch4=='e') ) {
+ sf = SFReadTTFInfo(fullname,0,openflags);
+ checked = 't';
+ } else if ((ch1=='t' && ch2=='t' && ch3=='c' && ch4=='f')) {
+ /* read all fonts in a collection */
+ fontlist = NamesReadTTF(fullname);
+ if (fontlist) {
+ while (*fontlist != NULL) {
+ snprintf(s,511, "%s(%s)", fullname,*fontlist);
+ sf_ptr = SFReadTTFInfo(s,0,openflags);
+ if (sf != NULL)
+ sf_ptr->next = sf;
+ sf = sf_ptr;
+ fontlist++;
+ }
+ }
+ } else if (( ch1=='%' && ch2=='!' ) ||
+ ( ch1==0x80 && ch2=='\01' ) ) { /* PFB header */
+ sf = SFReadPostscriptInfo(fullname);
+ checked = 'p';
+ } else if ( ch1==1 && ch2==0 && ch3==4 ) {
+ sf = CFFParseInfo(fullname);
+ checked = 'c';
+ } /* Too hard to figure out a valid mark for a mac resource file */
+ }
+
+ if ( sf!=NULL )
+ /* good */;
+ else if (( strmatch(fullname+strlen(fullname)-4, ".ttf")==0 ||
+ strmatch(fullname+strlen(strippedname)-4, ".ttc")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".gai")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".otf")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".otb")==0 ) && checked!='t') {
+ sf = SFReadTTFInfo(fullname,0,openflags);
+ } else if ( (strmatch(fullname+strlen(fullname)-4, ".pfa")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".pfb")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".pf3")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".cid")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".gsf")==0 ||
+ strmatch(fullname+strlen(fullname)-4, ".pt3")==0 ||
+ strmatch(fullname+strlen(fullname)-3, ".ps")==0 ) && checked!='p' ) {
+ sf = SFReadPostscriptInfo(fullname);
+ } else if ( strmatch(fullname+strlen(fullname)-4, ".cff")==0 && checked!='c' ) {
+ sf = CFFParseInfo(fullname);
+ } else {
+ sf = SFReadMacBinaryInfo(fullname,0,openflags);
+ }
+
+ if ( sf==NULL ) {
+ if ( !GFileExists(filename) )
+ gwwv_post_error(_("Couldn't open font"),_("The requested file, %.100s, does not exist"),GFileNameTail(filename));
+ else if ( !GFileReadable(filename) )
+ gwwv_post_error(_("Couldn't open font"),_("You do not have permission to read %.100s"),GFileNameTail(filename));
+ else
+ gwwv_post_error(_("Couldn't open font"),_("%.100s is not in a known format (or is so badly corrupted as to be unreadable)"),GFileNameTail(filename));
+ }
+ if ( fullname!=filename && fullname!=strippedname )
+ free(fullname);
+ return( sf );
+}
+#endif
+
+static SplineFont *AbsoluteNameCheck(char *filename) {
+ char buffer[1025];
+ FontView *fv;
+
+ GFileGetAbsoluteName(filename,buffer,sizeof(buffer));
+ for ( fv=fv_list; fv!=NULL ; fv=fv->next ) {
+ if ( fv->sf->filename!=NULL && strcmp(fv->sf->filename,buffer)==0 )
+return( fv->sf );
+ else if ( fv->sf->origname!=NULL && strcmp(fv->sf->origname,buffer)==0 )
+return( fv->sf );
+ }
+return( NULL );
+}
+
+char *ToAbsolute(char *filename) {
+ char buffer[1025];
+
+ GFileGetAbsoluteName(filename,buffer,sizeof(buffer));
+return( copy(buffer));
+}
+
+SplineFont *LoadSplineFont(char *filename,enum openflags openflags) {
+ FontView *fv;
+ SplineFont *sf;
+ char *pt, *ept, *tobefreed1=NULL, *tobefreed2=NULL;
+ static char *extens[] = { ".sfd", ".pfa", ".pfb", ".ttf", ".otf", ".ps", ".cid", ".bin", ".dfont", ".PFA", ".PFB", ".TTF", ".OTF", ".PS", ".CID", ".BIN", ".DFONT", NULL };
+ int i;
+
+ if ( filename==NULL )
+return( NULL );
+
+ if (( pt = strrchr(filename,'/'))==NULL ) pt = filename;
+ if ( strchr(pt,'.')==NULL ) {
+ /* They didn't give an extension. If there's a file with no extension */
+ /* see if it's a valid font file (and if so use the extensionless */
+ /* filename), otherwise guess at an extension */
+ /* For some reason Adobe distributes CID keyed fonts (both OTF and */
+ /* postscript) as extensionless files */
+ int ok = false;
+ FILE *test = fopen(filename,"rb");
+ if ( test!=NULL ) {
+#if 0
+ int ch1 = getc(test);
+ int ch2 = getc(test);
+ int ch3 = getc(test);
+ int ch4 = getc(test);
+ if ( ch1=='%' ) ok = true;
+ else if (( ch1==0 && ch2==1 && ch3==0 && ch4==0 ) ||
+ ( ch1==0 && ch2==2 && ch3==0 && ch4==0 ) ||
+ /* Windows 3.1 Chinese version used this version for some arphic fonts */
+ /* See discussion on freetype list, july 2004 */
+ (ch1=='O' && ch2=='T' && ch3=='T' && ch4=='O') ||
+ (ch1=='t' && ch2=='r' && ch3=='u' && ch4=='e') ||
+ (ch1=='t' && ch2=='t' && ch3=='c' && ch4=='f') ) ok = true;
+ else if ( ch1=='S' && ch2=='p' && ch3=='l' && ch4=='i' ) ok = true;
+#endif
+ ok = true; /* Mac resource files are too hard to check for */
+ /* If file exists, assume good */
+ fclose(test);
+ }
+ if ( !ok ) {
+ tobefreed1 = galloc(strlen(filename)+8);
+ strcpy(tobefreed1,filename);
+ ept = tobefreed1+strlen(tobefreed1);
+ for ( i=0; extens[i]!=NULL; ++i ) {
+ strcpy(ept,extens[i]);
+ if ( GFileExists(tobefreed1))
+ break;
+ }
+ if ( extens[i]!=NULL )
+ filename = tobefreed1;
+ else {
+ free(tobefreed1);
+ tobefreed1 = NULL;
+ }
+ }
+ } else
+ tobefreed1 = NULL;
+
+ sf = NULL;
+ /* Only one view per font */
+ for ( fv=fv_list; fv!=NULL && sf==NULL; fv=fv->next ) {
+ if ( fv->sf->filename!=NULL && strcmp(fv->sf->filename,filename)==0 )
+ sf = fv->sf;
+ else if ( fv->sf->origname!=NULL && strcmp(fv->sf->origname,filename)==0 )
+ sf = fv->sf;
+ }
+ if ( sf==NULL && *filename!='/' )
+ sf = AbsoluteNameCheck(filename);
+ if ( sf==NULL && *filename!='/' )
+ filename = tobefreed2 = ToAbsolute(filename);
+
+ if ( sf==NULL )
+ sf = ReadSplineFont(filename,openflags);
+
+ free(tobefreed1);
+ free(tobefreed2);
+return( sf );
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+FontView *ViewPostscriptFont(char *filename) {
+ SplineFont *sf = LoadSplineFont(filename,0);
+ extern NameList *force_names_when_opening;
+ if ( sf==NULL )
+return( NULL );
+ if ( sf->fv==NULL && force_names_when_opening!=NULL )
+ SFRenameGlyphsToNamelist(sf,force_names_when_opening );
+#if 0
+ if ( sf->fv!=NULL ) {
+ GDrawSetVisible(sf->fv->gw,true);
+ GDrawRaise(sf->fv->gw);
+return( sf->fv );
+ }
+#endif
+return( FontViewCreate(sf)); /* Always make a new view now */
+}
+
+FontView *FontNew(void) {
+return( FontViewCreate(SplineFontNew()));
+}
+#endif
+
+void FontViewFree(FontView *fv) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ int i;
+ FontView *prev;
+ FontView *fvs;
+#endif
+ if ( fv->sf == NULL ) /* Happens when usurping a font to put it into an MM */
+ BDFFontFree(fv->filled);
+ else if ( fv->nextsame==NULL && fv->sf->fv==fv ) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ EncMapFree(fv->map);
+#endif
+ SplineFontFree(fv->cidmaster?fv->cidmaster:fv->sf);
+ BDFFontFree(fv->filled);
+ } else {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ EncMapFree(fv->map);
+ for ( fvs=fv->sf->fv, i=0 ; fvs!=NULL; fvs = fvs->nextsame )
+ if ( fvs->filled==fv->filled ) ++i;
+ if ( i==1 )
+ BDFFontFree(fv->filled);
+ if ( fv->sf->fv==fv ) {
+ if ( fv->cidmaster==NULL )
+ fv->sf->fv = fv->nextsame;
+ else {
+ fv->cidmaster->fv = fv->nextsame;
+ for ( i=0; i<fv->cidmaster->subfontcnt; ++i )
+ fv->cidmaster->subfonts[i]->fv = fv->nextsame;
+ }
+ } else {
+ for ( prev = fv->sf->fv; prev->nextsame!=fv; prev=prev->nextsame );
+ prev->nextsame = fv->nextsame;
+ }
+#endif
+ }
+ DictionaryFree(fv->fontvars);
+ free(fv->fontvars);
+ free(fv->selected);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ free(fv->fontset);
+#ifndef _NO_PYTHON
+ PyFF_FreeFV(fv);
+#endif
+#endif
+ free(fv);
+}
+
+void FVFakeMenus(FontView *fv,int cmd) {
+ switch ( cmd ) {
+#ifndef LUA_FF_LIB
+ case 0: /* Cut */
+ FVCopy(fv,ct_fullcopy);
+ FVClear(fv);
+ break;
+ case 1:
+ FVCopy(fv,ct_fullcopy);
+ break;
+ case 2: /* Copy reference */
+ FVCopy(fv,ct_lookups);
+ break;
+ case 3:
+ FVCopyWidth(fv,ut_width);
+ break;
+#endif
+ case 4:
+ PasteIntoFV(fv,false,NULL);
+ break;
+#ifndef LUA_FF_LIB
+ case 5:
+ FVClear(fv);
+ break;
+#endif
+ case 6:
+ FVClearBackground(fv);
+ break;
+ case 7:
+ FVCopyFgtoBg(fv);
+ break;
+ case 8:
+ FVUnlinkRef(fv);
+ break;
+ case 9:
+ PasteIntoFV(fv,true,NULL);
+ break;
+#ifndef LUA_FF_LIB
+ case 10:
+ FVCopyWidth(fv,ut_vwidth);
+ break;
+ case 11:
+ FVCopyWidth(fv,ut_lbearing);
+ break;
+ case 12:
+ FVCopyWidth(fv,ut_rbearing);
+ break;
+#endif
+ case 13:
+ FVJoin(fv);
+ break;
+ case 14:
+ FVSameGlyphAs(fv);
+ break;
+
+ case 100:
+ FVOverlap(fv,over_remove);
+ break;
+#if 0 /* Not used any more */
+ case 101:
+ FVSimplify(fv,false);
+ break;
+#endif
+ case 102:
+ FVAddExtrema(fv);
+ break;
+ case 103:
+ FVRound2Int(fv,1.0);
+ break;
+ case 104:
+ FVOverlap(fv,over_intersect);
+ break;
+ case 105:
+ FVOverlap(fv,over_findinter);
+ break;
+
+#ifndef LUA_FF_LIB
+ case 200:
+ FVAutoHint(fv);
+ break;
+ case 201:
+ FVClearHints(fv);
+ break;
+ case 202:
+ FVAutoInstr(fv);
+ break;
+ case 203:
+ FVAutoHintSubs(fv);
+ break;
+ case 204:
+ FVAutoCounter(fv);
+ break;
+ case 205:
+ FVDontAutoHint(fv);
+ break;
+ case 206:
+ FVClearInstrs(fv);
+ break;
+#endif
+ }
+}
+
+int FVWinInfo(FontView *fv, int *cc, int *rc) {
+ if ( fv==NULL || fv->colcnt==0 || fv->rowcnt==0 ) {
+ *cc = 16; *rc = 4;
+return( -1 );
+ }
+
+ *cc = fv->colcnt;
+ *rc = fv->rowcnt;
+
+return( fv->rowoff*fv->colcnt );
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/fvfonts.c b/Build/source/libs/luafontforge/fontforge/fontforge/fvfonts.c
new file mode 100644
index 00000000000..eeb8d836dca
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/fvfonts.c
@@ -0,0 +1,1911 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaeditui.h"
+#include "ustring.h"
+#include "utype.h"
+#include "gfile.h"
+#include "chardata.h"
+
+#ifdef LUA_FF_LIB
+extern void SFAddGlyphAndEncode(SplineFont *sf,SplineChar *sc,EncMap *basemap, int baseenc);
+extern void gwwv_post_error(char *a, ...);
+#endif
+
+static RefChar *RefCharsCopy(RefChar *ref) {
+ RefChar *rhead=NULL, *last=NULL, *cur;
+
+ while ( ref!=NULL ) {
+ cur = RefCharCreate();
+#ifdef FONTFORGE_CONFIG_TYPE3
+ { struct reflayer *layers = cur->layers; int layer;
+ layers = grealloc(layers,ref->layer_cnt*sizeof(struct reflayer));
+ memcpy(layers,ref->layers,ref->layer_cnt*sizeof(struct reflayer));
+ *cur = *ref;
+ cur->layers = layers;
+ for ( layer=0; layer<cur->layer_cnt; ++layer ) {
+ cur->layers[layer].splines = NULL;
+ cur->layers[layer].images = NULL;
+ }
+ }
+#else
+ *cur = *ref;
+ cur->layers[0].splines = NULL; /* Leave the old sc, we'll fix it later */
+#endif
+ if ( cur->sc!=NULL )
+ cur->orig_pos = cur->sc->orig_pos;
+ cur->next = NULL;
+ if ( rhead==NULL )
+ rhead = cur;
+ else
+ last->next = cur;
+ last = cur;
+ ref = ref->next;
+ }
+return( rhead );
+}
+
+static OTLookup *MCConvertLookup(struct sfmergecontext *mc,OTLookup *otl) {
+ int l;
+ OTLookup *newotl;
+
+ if ( mc==NULL || mc->sf_from==mc->sf_to )
+return( otl ); /* No translation needed */
+
+ for ( l=0; l<mc->lcnt; ++l ) {
+ if ( mc->lks[l].from == otl )
+ break;
+ }
+ if ( l==mc->lcnt )
+return( NULL );
+ if ( mc->lks[l].to!=NULL )
+return( mc->lks[l].to );
+
+ mc->lks[l].to = newotl = chunkalloc(sizeof(struct lookup_subtable));
+ newotl->lookup_name = strconcat(mc->prefix,otl->lookup_name);
+ newotl->lookup_type = otl->lookup_type;
+ newotl->lookup_flags = otl->lookup_flags;
+ newotl->features = FeatureListCopy(otl->features);
+ newotl->store_in_afm = otl->store_in_afm;
+return( newotl );
+}
+
+struct lookup_subtable *MCConvertSubtable(struct sfmergecontext *mc,struct lookup_subtable *sub) {
+ int s;
+ struct lookup_subtable *newsub;
+
+ if ( mc==NULL || mc->sf_from==mc->sf_to )
+return( sub ); /* No translation needed */
+ if ( mc->prefix==NULL ) {
+ int lcnt, scnt;
+ OTLookup *otl;
+ struct lookup_subtable *subs;
+ int isgpos, doit;
+ char *temp;
+
+ /* Not initialized */
+ if ( mc->sf_from->cidmaster ) mc->sf_from = mc->sf_from->cidmaster;
+ else if ( mc->sf_from->mm!=NULL ) mc->sf_from = mc->sf_from->mm->normal;
+ if ( mc->sf_to->cidmaster ) mc->sf_to = mc->sf_to->cidmaster;
+ else if ( mc->sf_to->mm!=NULL ) mc->sf_to = mc->sf_to->mm->normal;
+ if ( mc->sf_from == mc->sf_to )
+return( sub );
+ mc->prefix = strconcat(mc->sf_from->fontname,"-");
+ for ( doit = 0; doit<2; ++doit ) {
+ lcnt = scnt = 0;
+ for ( isgpos=0; isgpos<2; ++isgpos ) {
+ for ( otl = isgpos ? mc->sf_from->gpos_lookups : mc->sf_from->gsub_lookups; otl!=NULL; otl=otl->next ) {
+ if ( doit ) {
+ mc->lks[lcnt].from = otl;
+ temp = strconcat(mc->prefix,otl->lookup_name);
+ mc->lks[lcnt].to = SFFindLookup(mc->sf_to,temp);
+ free(temp);
+ mc->lks[lcnt].old = mc->lks[lcnt].to!=NULL;
+ }
+ ++lcnt;
+ for ( subs=otl->subtables; subs!=NULL; subs=subs->next ) {
+ if ( doit ) {
+ mc->subs[scnt].from = subs;
+ temp = strconcat(mc->prefix,subs->subtable_name);
+ mc->subs[scnt].to = SFFindLookupSubtable(mc->sf_to,temp);
+ free(temp);
+ mc->subs[scnt].old = mc->subs[scnt].to!=NULL;
+ }
+ ++scnt;
+ }
+ }
+ }
+ if ( !doit ) {
+ mc->lcnt = lcnt; mc->scnt = scnt;
+ mc->lks = gcalloc(lcnt,sizeof(struct lookup_cvt));
+ mc->subs = gcalloc(scnt,sizeof(struct sub_cvt));
+ }
+ }
+ }
+
+ for ( s=0; s<mc->scnt; ++s ) {
+ if ( mc->subs[s].from == sub )
+ break;
+ }
+ if ( s==mc->scnt )
+return( NULL );
+ if ( mc->subs[s].to!=NULL )
+return( mc->subs[s].to );
+
+ mc->subs[s].to = newsub = chunkalloc(sizeof(struct lookup_subtable));
+ newsub->subtable_name = strconcat(mc->prefix,sub->subtable_name);
+ newsub->lookup = MCConvertLookup(mc,sub->lookup);
+ newsub->anchor_classes = sub->anchor_classes;
+ newsub->per_glyph_pst_or_kern = sub->per_glyph_pst_or_kern;
+return( newsub );
+}
+
+#ifndef LUA_FF_LIB
+
+AnchorClass *MCConvertAnchorClass(struct sfmergecontext *mc,AnchorClass *ac) {
+ int a;
+ AnchorClass *newac;
+
+ if ( mc==NULL || mc->sf_from==mc->sf_to )
+return( ac ); /* No translation needed */
+ if ( mc->acnt==0 ) {
+ int acnt;
+ AnchorClass *testac, *testac2;
+ int doit;
+ char *temp;
+
+ /* Not initialized */
+ for ( doit = 0; doit<2; ++doit ) {
+ acnt = 0;
+ for ( testac=mc->sf_from->anchor; testac!=NULL; testac=testac->next ) {
+ if ( doit ) {
+ mc->acs[acnt].from = testac;
+ temp = strconcat(mc->prefix,testac->name);
+ for ( testac2 = mc->sf_to->anchor; testac2!=NULL; testac2=testac2->next )
+ if ( strcmp(testac2->name,temp)==0 )
+ break;
+ mc->acs[acnt].to = testac2;
+ free(temp);
+ mc->acs[acnt].old = mc->acs[acnt].to!=NULL;
+ }
+ ++acnt;
+ }
+ if ( !doit ) {
+ mc->acnt = acnt;
+ mc->acs = gcalloc(acnt,sizeof(struct ac_cvt));
+ }
+ }
+ }
+
+ for ( a=0; a<mc->acnt; ++a ) {
+ if ( mc->acs[a].from == ac )
+ break;
+ }
+ if ( a==mc->acnt )
+return( NULL );
+ if ( mc->acs[a].to!=NULL )
+return( mc->acs[a].to );
+
+ mc->acs[a].to = newac = chunkalloc(sizeof(AnchorClass));
+ newac->name = strconcat(mc->prefix,ac->name);
+ newac->subtable = MCConvertSubtable(mc,ac->subtable);
+ newac->next = mc->sf_to->anchor;
+ mc->sf_to->anchor = newac;
+return( newac );
+}
+
+void SFFinishMergeContext(struct sfmergecontext *mc) {
+ int l,s,slast, isgpos;
+ OTLookup *otl, *last;
+ struct lookup_subtable *sub_last;
+
+ if ( mc->prefix==NULL ) /* Nothing to do, never initialized, no lookups needed */
+return;
+
+ /* Get all the subtables in the right order */
+ for ( s=0; s<mc->scnt; s=slast ) {
+ if ( mc->subs[s].to==NULL )
+ continue;
+ otl = mc->subs[s].to->lookup;
+ sub_last = otl->subtables = mc->subs[s].to;
+ for ( slast=s+1; slast<mc->scnt; ++slast ) {
+ if ( mc->subs[slast].to==NULL )
+ continue;
+ if ( mc->subs[slast].to->lookup!=otl )
+ break;
+ sub_last->next = mc->subs[slast].to;
+ sub_last = sub_last->next;
+ }
+ sub_last->next = NULL;
+ }
+
+ /* Then order the lookups. Leave the old lookups as they are, insert the */
+ /* new at the end of the list */
+ last = NULL;
+ for ( l=0; l<mc->lcnt; ++l ) {
+ if ( mc->lks[l].to==NULL || mc->lks[l].old )
+ continue;
+ otl = mc->lks[l].to;
+ isgpos = (otl->lookup_type>=gpos_start);
+ if ( last==NULL || (last->lookup_type>=gpos_start)!=isgpos) {
+ last = isgpos ? mc->sf_to->gpos_lookups : mc->sf_to->gsub_lookups;
+ if ( last!=NULL )
+ while ( last->next!=NULL )
+ last = last->next;
+ }
+ if ( last!=NULL )
+ last->next = otl;
+ else if ( isgpos )
+ mc->sf_to->gpos_lookups = otl;
+ else
+ mc->sf_to->gsub_lookups = otl;
+ last = otl;
+ }
+
+ free(mc->prefix);
+ free(mc->lks);
+ free(mc->subs);
+ free(mc->acs);
+}
+#endif
+
+PST *PSTCopy(PST *base,SplineChar *sc,struct sfmergecontext *mc) {
+ PST *head=NULL, *last=NULL, *cur;
+
+ for ( ; base!=NULL; base = base->next ) {
+ cur = chunkalloc(sizeof(PST));
+ *cur = *base;
+ cur->subtable = MCConvertSubtable(mc,base->subtable);
+ if ( cur->type==pst_ligature ) {
+ cur->u.lig.components = copy(cur->u.lig.components);
+ cur->u.lig.lig = sc;
+ } else if ( cur->type==pst_pair ) {
+ cur->u.pair.paired = copy(cur->u.pair.paired);
+ cur->u.pair.vr = chunkalloc(sizeof( struct vr [2]));
+ memcpy(cur->u.pair.vr,base->u.pair.vr,sizeof(struct vr [2]));
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ cur->u.pair.vr[0].adjust = ValDevTabCopy(base->u.pair.vr[0].adjust);
+ cur->u.pair.vr[1].adjust = ValDevTabCopy(base->u.pair.vr[1].adjust);
+#endif
+ } else if ( cur->type==pst_lcaret ) {
+ cur->u.lcaret.carets = galloc(cur->u.lcaret.cnt*sizeof(uint16));
+ memcpy(cur->u.lcaret.carets,base->u.lcaret.carets,cur->u.lcaret.cnt*sizeof(uint16));
+ } else if ( cur->type==pst_substitution || cur->type==pst_multiple || cur->type==pst_alternate )
+ cur->u.subs.variant = copy(cur->u.subs.variant);
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ }
+return( head );
+}
+
+static AnchorPoint *AnchorPointsDuplicate(AnchorPoint *base,SplineChar *sc) {
+ AnchorPoint *head=NULL, *last=NULL, *cur;
+ AnchorClass *ac;
+
+ for ( ; base!=NULL; base = base->next ) {
+ cur = chunkalloc(sizeof(AnchorPoint));
+ *cur = *base;
+ cur->next = NULL;
+ for ( ac=sc->parent->anchor; ac!=NULL; ac=ac->next )
+ if ( strcmp(ac->name,base->anchor->name)==0 )
+ break;
+ cur->anchor = ac;
+ if ( ac==NULL ) {
+ LogError( "No matching AnchorClass for %s", base->anchor->name);
+ chunkfree(cur,sizeof(AnchorPoint));
+ } else {
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ }
+ }
+return( head );
+}
+
+#ifndef LUA_FF_LIB
+static void AnchorClassesAdd(SplineFont *into, SplineFont *from, struct sfmergecontext *mc) {
+ AnchorClass *fac, *iac, *last, *cur;
+
+ if ( into->cidmaster!=NULL )
+ into = into->cidmaster;
+ if ( from->cidmaster!=NULL )
+ from = from->cidmaster;
+
+ for ( fac = from->anchor; fac!=NULL; fac=fac->next ) {
+ last = NULL;
+ for ( iac=into->anchor; iac!=NULL; iac=iac->next ) {
+ if ( strcmp(iac->name,fac->name)==0 )
+ break;
+ last = iac;
+ }
+ if ( iac==NULL ) {
+ cur = chunkalloc(sizeof(AnchorClass));
+ *cur = *fac;
+ cur->next = NULL;
+ cur->name = copy(cur->name);
+ cur->subtable = MCConvertSubtable(mc,cur->subtable);
+ if ( last==NULL )
+ into->anchor = cur;
+ else
+ last->next = cur;
+ } else {
+ /* Just use the one that's there and hope it's right. Not sure */
+ /* what else we can do... */
+ }
+ }
+}
+
+static void FPSTsAdd(SplineFont *into, SplineFont *from,struct sfmergecontext *mc) {
+ FPST *fpst, *nfpst, *last;
+ int i,k;
+
+ last = NULL;
+ if ( into->possub!=NULL )
+ for ( last = into->possub; last->next!=NULL; last=last->next );
+ for ( fpst = from->possub; fpst!=NULL; fpst=fpst->next ) {
+ nfpst = FPSTCopy(fpst);
+ nfpst->subtable = MCConvertSubtable(mc,fpst->subtable);
+ nfpst->subtable->fpst = nfpst;
+ for ( i=0; i<nfpst->rule_cnt; ++i ) {
+ struct fpst_rule *r = &nfpst->rules[i], *oldr = &fpst->rules[i];
+ for ( k=0; k<r->lookup_cnt; ++k ) {
+ r->lookups[k].lookup = MCConvertLookup(mc,oldr->lookups[k].lookup);
+ }
+ }
+ if ( last==NULL )
+ into->possub = nfpst;
+ else
+ last->next = nfpst;
+ last = nfpst;
+ }
+}
+
+static void ASMsAdd(SplineFont *into, SplineFont *from,struct sfmergecontext *mc) {
+ ASM *sm, *nsm, *last;
+ int i;
+
+ last = NULL;
+ if ( into->sm!=NULL )
+ for ( last = into->sm; last->next!=NULL; last=last->next );
+ for ( sm = from->sm; sm!=NULL; sm=sm->next ) {
+ nsm = chunkalloc(sizeof(ASM));
+ *nsm = *sm;
+ nsm->subtable = MCConvertSubtable(mc,sm->subtable);
+ nsm->subtable->sm = nsm;
+ nsm->classes = galloc(nsm->class_cnt*sizeof(char *));
+ for ( i=0; i<nsm->class_cnt; ++i )
+ nsm->classes[i] = copy(sm->classes[i]);
+ nsm->state = galloc(nsm->class_cnt*nsm->state_cnt*sizeof(struct asm_state));
+ memcpy(nsm->state,sm->state,nsm->class_cnt*nsm->state_cnt*sizeof(struct asm_state));
+ if ( nsm->type == asm_kern ) {
+ for ( i=nsm->class_cnt*nsm->state_cnt-1; i>=0; --i ) {
+ nsm->state[i].u.kern.kerns = galloc(nsm->state[i].u.kern.kcnt*sizeof(int16));
+ memcpy(nsm->state[i].u.kern.kerns,sm->state[i].u.kern.kerns,nsm->state[i].u.kern.kcnt*sizeof(int16));
+ }
+ } else if ( nsm->type == asm_context ) {
+ for ( i=0; i<nsm->class_cnt*nsm->state_cnt; ++i ) {
+ nsm->state[i].u.context.mark_lookup = MCConvertLookup(mc,
+ nsm->state[i].u.context.mark_lookup);
+ nsm->state[i].u.context.cur_lookup = MCConvertLookup(mc,
+ nsm->state[i].u.context.cur_lookup);
+ }
+ } else if ( nsm->type == asm_insert ) {
+ for ( i=nsm->class_cnt*nsm->state_cnt-1; i>=0; --i ) {
+ nsm->state[i].u.insert.mark_ins = copy(sm->state[i].u.insert.mark_ins);
+ nsm->state[i].u.insert.cur_ins = copy(sm->state[i].u.insert.cur_ins);
+ }
+ }
+ }
+}
+
+static KernClass *_KernClassCopy(KernClass *kc,SplineFont *into,SplineFont *from,struct sfmergecontext *mc) {
+ KernClass *nkc;
+
+ nkc = KernClassCopy(kc);
+ nkc->subtable = MCConvertSubtable(mc,kc->subtable);
+ nkc->subtable->kc = nkc;
+return( nkc );
+}
+
+static void KernClassesAdd(SplineFont *into, SplineFont *from,struct sfmergecontext *mc) {
+ /* Is this a good idea? We could end up with two kern classes that do */
+ /* the same thing and strange sets of slis so that they didn't all fit */
+ /* in one lookup... */
+ KernClass *kc, *last, *cur;
+
+ last = NULL;
+ if ( into->kerns!=NULL )
+ for ( last = into->kerns; last->next!=NULL; last=last->next );
+ for ( kc=from->kerns; kc!=NULL; kc=kc->next ) {
+ cur = _KernClassCopy(kc,into,from,mc);
+ if ( last==NULL )
+ into->kerns = cur;
+ else
+ last->next = cur;
+ last = cur;
+ }
+
+ last = NULL;
+ if ( into->vkerns!=NULL )
+ for ( last = into->vkerns; last->next!=NULL; last=last->next )
+ for ( kc=from->vkerns; kc!=NULL; kc=kc->next ) {
+ cur = _KernClassCopy(kc,into,from,mc);
+ if ( last==NULL )
+ into->vkerns = cur;
+ else
+ last->next = cur;
+ last = cur;
+ }
+}
+#endif
+
+static struct altuni *AltUniCopy(struct altuni *altuni,SplineFont *noconflicts) {
+ struct altuni *head=NULL, *last=NULL, *cur;
+
+ while ( altuni!=NULL ) {
+ if ( noconflicts==NULL || SFGetChar(noconflicts,altuni->unienc,NULL)==NULL ) {
+ cur = chunkalloc(sizeof(struct altuni));
+ cur->unienc = altuni->unienc;
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ }
+ altuni = altuni->next;
+ }
+return( head );
+}
+
+SplineChar *SplineCharCopy(SplineChar *sc,SplineFont *into,struct sfmergecontext *mc) {
+ SplineChar *nsc = SplineCharCreate();
+#ifdef FONTFORGE_CONFIG_TYPE3
+ Layer *layers = nsc->layers;
+ int layer;
+
+ *nsc = *sc;
+ if ( sc->layer_cnt!=2 )
+ layers = grealloc(layers,sc->layer_cnt*sizeof(Layer));
+ memcpy(layers,sc->layers,sc->layer_cnt*sizeof(Layer));
+ nsc->layers = layers;
+ for ( layer = ly_back; layer<sc->layer_cnt; ++layer ) {
+ layers[layer].splines = SplinePointListCopy(layers[layer].splines);
+ layers[layer].refs = RefCharsCopy(layers[layer].refs);
+ layers[layer].images = ImageListCopy(layers[layer].images);
+ layers[layer].undoes = NULL;
+ layers[layer].redoes = NULL;
+ }
+#else
+ *nsc = *sc;
+ nsc->layers[ly_fore].splines = SplinePointListCopy(nsc->layers[ly_fore].splines);
+ nsc->layers[ly_fore].refs = RefCharsCopy(nsc->layers[ly_fore].refs);
+ nsc->layers[ly_back].splines = SplinePointListCopy(nsc->layers[ly_back].splines);
+ nsc->layers[ly_back].images = ImageListCopy(nsc->layers[ly_back].images);
+#endif
+ nsc->parent = into;
+ nsc->orig_pos = -2;
+ nsc->name = copy(sc->name);
+ nsc->hstem = StemInfoCopy(nsc->hstem);
+ nsc->vstem = StemInfoCopy(nsc->vstem);
+ nsc->anchor = AnchorPointsDuplicate(nsc->anchor,nsc);
+ nsc->views = NULL;
+ nsc->changed = true;
+ nsc->dependents = NULL; /* Fix up later when we know more */
+ nsc->layers[ly_fore].undoes = nsc->layers[ly_back].undoes = NULL;
+ nsc->layers[ly_fore].redoes = nsc->layers[ly_back].redoes = NULL;
+ if ( nsc->ttf_instrs_len!=0 ) {
+ nsc->ttf_instrs = galloc(nsc->ttf_instrs_len);
+ memcpy(nsc->ttf_instrs,sc->ttf_instrs,nsc->ttf_instrs_len);
+ }
+ nsc->kerns = NULL;
+ nsc->possub = PSTCopy(nsc->possub,nsc,mc);
+ nsc->altuni = AltUniCopy(nsc->altuni,into);
+ if ( sc->parent!=NULL && into->order2!=sc->parent->order2 )
+ SCConvertOrder(nsc,into->order2);
+return(nsc);
+}
+
+#ifndef LUA_FF_LIB
+static KernPair *KernsCopy(KernPair *kp,int *mapping,SplineFont *into,
+ struct sfmergecontext *mc) {
+ KernPair *head = NULL, *last=NULL, *new;
+ int index;
+
+ while ( kp!=NULL ) {
+ if ( (index=mapping[kp->sc->orig_pos])>=0 && index<into->glyphcnt &&
+ into->glyphs[index]!=NULL ) {
+ new = chunkalloc(sizeof(KernPair));
+ new->off = kp->off;
+ new->subtable = MCConvertSubtable(mc,kp->subtable);
+ new->sc = into->glyphs[index];
+ if ( head==NULL )
+ head = new;
+ else
+ last->next = new;
+ last = new;
+ }
+ kp = kp->next;
+ }
+return( head );
+}
+
+
+BDFChar *BDFCharCopy(BDFChar *bc) {
+ BDFChar *nbc = galloc(sizeof( BDFChar ));
+
+ *nbc = *bc;
+ nbc->views = NULL;
+ nbc->selection = NULL;
+ nbc->undoes = NULL;
+ nbc->redoes = NULL;
+ nbc->bitmap = galloc((nbc->ymax-nbc->ymin+1)*nbc->bytes_per_line);
+ memcpy(nbc->bitmap,bc->bitmap,(nbc->ymax-nbc->ymin+1)*nbc->bytes_per_line);
+return( nbc );
+}
+
+void BitmapsCopy(SplineFont *to, SplineFont *from, int to_index, int from_index ) {
+ BDFFont *f_bdf, *t_bdf;
+
+ /* We assume that the bitmaps are ordered. They should be */
+ for ( t_bdf=to->bitmaps, f_bdf=from->bitmaps; t_bdf!=NULL && f_bdf!=NULL; ) {
+ if ( t_bdf->pixelsize == f_bdf->pixelsize ) {
+ if ( f_bdf->glyphs[from_index]!=NULL ) {
+ BDFCharFree(t_bdf->glyphs[to_index]);
+ t_bdf->glyphs[to_index] = BDFCharCopy(f_bdf->glyphs[from_index]);
+ t_bdf->glyphs[to_index]->sc = to->glyphs[to_index];
+ t_bdf->glyphs[to_index]->orig_pos = to_index;
+ }
+ t_bdf = t_bdf->next;
+ f_bdf = f_bdf->next;
+ } else if ( t_bdf->pixelsize < f_bdf->pixelsize ) {
+ t_bdf = t_bdf->next;
+ f_bdf = f_bdf->next;
+ }
+ }
+}
+#endif
+
+#define GN_HSIZE 257
+
+struct glyphnamebucket {
+ SplineChar *sc;
+ struct glyphnamebucket *next;
+};
+
+struct glyphnamehash {
+ struct glyphnamebucket *table[GN_HSIZE];
+};
+
+#ifndef __GNUC__
+# define __inline__
+#endif
+
+static __inline__ int hashname(const char *pt) {
+ int val = 0;
+
+ while ( *pt ) {
+ val = (val<<3)|((val>>29)&0x7);
+ val ^= (unsigned char)(*pt-'!');
+ pt++;
+ }
+ val ^= (val>>16);
+ val &= 0xffff;
+ val %= GN_HSIZE;
+return( val );
+}
+
+static void _GlyphHashFree(SplineFont *sf) {
+ struct glyphnamebucket *test, *next;
+ int i;
+
+ if ( sf->glyphnames==NULL )
+return;
+ for ( i=0; i<GN_HSIZE; ++i ) {
+ for ( test = sf->glyphnames->table[i]; test!=NULL; test = next ) {
+ next = test->next;
+ chunkfree(test,sizeof(struct glyphnamebucket));
+ }
+ }
+ free(sf->glyphnames);
+ sf->glyphnames = NULL;
+}
+
+void GlyphHashFree(SplineFont *sf) {
+ _GlyphHashFree(sf);
+ if ( sf->cidmaster )
+ _GlyphHashFree(sf->cidmaster);
+}
+
+static void GlyphHashCreate(SplineFont *sf) {
+ int i, k, hash;
+ SplineFont *_sf;
+ struct glyphnamehash *gnh;
+ struct glyphnamebucket *new;
+
+ if ( sf->glyphnames!=NULL )
+return;
+ sf->glyphnames = gnh = gcalloc(1,sizeof(*gnh));
+ k = 0;
+ do {
+ _sf = k<sf->subfontcnt ? sf->subfonts[k] : sf;
+ /* I walk backwards because there are some ttf files where multiple */
+ /* glyphs get the same name. In the cases I've seen only one of these */
+ /* has an encoding. That's the one we want. It will be earlier in the */
+ /* font than the others. If we build the list backwards then it will */
+ /* be the top name in the bucket, and will be the one we return */
+ for ( i=_sf->glyphcnt-1; i>=0; --i ) if ( _sf->glyphs[i]!=NULL ) {
+ new = chunkalloc(sizeof(struct glyphnamebucket));
+ new->sc = _sf->glyphs[i];
+ hash = hashname(new->sc->name);
+ new->next = gnh->table[hash];
+ gnh->table[hash] = new;
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+}
+
+void SFHashGlyph(SplineFont *sf,SplineChar *sc) {
+ /* sc just got added to the font. Put it in the lookup */
+ int hash;
+ struct glyphnamebucket *new;
+
+ if ( sf->glyphnames==NULL )
+return; /* No hash table, nothing to update */
+
+ new = chunkalloc(sizeof(struct glyphnamebucket));
+ new->sc = sc;
+ hash = hashname(sc->name);
+ new->next = sf->glyphnames->table[hash];
+ sf->glyphnames->table[hash] = new;
+}
+
+static SplineChar *SFHashName(SplineFont *sf,const char *name) {
+ struct glyphnamebucket *test;
+
+ if ( sf->glyphnames==NULL )
+ GlyphHashCreate(sf);
+
+ for ( test=sf->glyphnames->table[hashname(name)]; test!=NULL; test = test->next )
+ if ( strcmp(test->sc->name,name)==0 )
+return( test->sc );
+
+return( NULL );
+}
+
+/* Find the position in the glyph list where this code point/name is found. */
+/* Returns -1 else on error */
+int SFFindGID(SplineFont *sf, int unienc, const char *name ) {
+ struct altuni *altuni;
+ int gid;
+ SplineChar *sc;
+
+ if ( unienc!=-1 ) {
+ for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( sf->glyphs[gid]!=NULL ) {
+ if ( sf->glyphs[gid]->unicodeenc == unienc )
+return( gid );
+ for ( altuni = sf->glyphs[gid]->altuni; altuni!=NULL; altuni=altuni->next ) {
+ if ( altuni->unienc == unienc )
+return( gid );
+ }
+ }
+ }
+ if ( name!=NULL ) {
+ sc = SFHashName(sf,name);
+ if ( sc!=NULL )
+return( sc->orig_pos );
+ }
+
+return ( -1 );
+}
+
+/* Find the position in the current encoding where this code point/name should*/
+/* be found. (or for unencoded glyphs where it is found). Returns -1 else */
+int SFFindSlot(SplineFont *sf, EncMap *map, int unienc, const char *name ) {
+ int index=-1, pos;
+
+ if ( (map->enc->is_custom || map->enc->is_compact ||
+ map->enc->is_original) && unienc!=-1 ) {
+ if ( unienc<map->enccount && map->map[unienc]!=-1 &&
+ sf->glyphs[map->map[unienc]]!=NULL &&
+ sf->glyphs[map->map[unienc]]->unicodeenc==unienc )
+ index = unienc;
+ else for ( index = map->enccount-1; index>=0; --index ) {
+ if ( (pos = map->map[index])!=-1 && sf->glyphs[pos]!=NULL &&
+ sf->glyphs[pos]->unicodeenc==unienc )
+ break;
+ }
+ } else if ( unienc!=-1 &&
+ ((unienc<0x10000 && map->enc->is_unicodebmp) ||
+ (unienc<0x110000 && map->enc->is_unicodefull))) {
+ index = unienc;
+ } else if ( unienc!=-1 ) {
+ index = EncFromUni(unienc,map->enc);
+ if ( index<0 || index>=map->enccount ) {
+ for ( index=map->enc->char_cnt; index<map->enccount; ++index )
+ if ( (pos = map->map[index])!=-1 && sf->glyphs[pos]!=NULL &&
+ sf->glyphs[pos]->unicodeenc==unienc )
+ break;
+ if ( index>=map->enccount )
+ index = -1;
+ }
+ }
+ if ( index==-1 && name!=NULL ) {
+ SplineChar *sc = SFHashName(sf,name);
+ if ( sc!=NULL ) index = map->backmap[sc->orig_pos];
+ if ( index==-1 ) {
+ unienc = UniFromName(name,sf->uni_interp,map->enc);
+ if ( unienc!=-1 )
+return( SFFindSlot(sf,map,unienc,NULL));
+ if ( map->enc->psnames!=NULL ) {
+ for ( index = map->enc->char_cnt-1; index>=0; --index )
+ if ( map->enc->psnames[index]!=NULL &&
+ strcmp(map->enc->psnames[index],name)==0 )
+return( index );
+ }
+ }
+ }
+
+return( index );
+}
+
+int SFCIDFindExistingChar(SplineFont *sf, int unienc, const char *name ) {
+ int j,ret;
+
+ if ( sf->subfonts==NULL && sf->cidmaster==NULL )
+return( SFFindExistingSlot(sf,unienc,name));
+ if ( sf->cidmaster!=NULL )
+ sf=sf->cidmaster;
+ for ( j=0; j<sf->subfontcnt; ++j )
+ if (( ret = SFFindExistingSlot(sf,unienc,name))!=-1 )
+return( ret );
+return( -1 );
+}
+
+int SFCIDFindCID(SplineFont *sf, int unienc, const char *name ) {
+ int j,ret;
+ struct cidmap *cidmap;
+
+ if ( sf->cidmaster!=NULL || sf->subfontcnt!=0 ) {
+ if ( sf->cidmaster!=NULL )
+ sf=sf->cidmaster;
+ cidmap = FindCidMap(sf->cidregistry,sf->ordering,sf->supplement,sf);
+ ret = NameUni2CID(cidmap,unienc,name);
+ if ( ret!=-1 )
+return( ret );
+ }
+
+ if ( sf->subfonts==NULL && sf->cidmaster==NULL )
+return( SFFindGID(sf,unienc,name));
+
+ if ( sf->cidmaster!=NULL )
+ sf=sf->cidmaster;
+ for ( j=0; j<sf->subfontcnt; ++j )
+ if (( ret = SFFindGID(sf,unienc,name))!=-1 )
+return( ret );
+
+return( -1 );
+}
+
+int SFHasCID(SplineFont *sf,int cid) {
+ int i;
+ /* What subfont (if any) contains this cid? */
+ if ( sf->cidmaster!=NULL )
+ sf=sf->cidmaster;
+ for ( i=0; i<sf->subfontcnt; ++i )
+ if ( cid<sf->subfonts[i]->glyphcnt &&
+ SCWorthOutputting(sf->subfonts[i]->glyphs[cid]) )
+return( i );
+ for ( i=0; i<sf->subfontcnt; ++i )
+ if ( cid<sf->subfonts[i]->glyphcnt && sf->subfonts[i]->glyphs[cid]!=NULL )
+return( i );
+
+return( -1 );
+}
+
+SplineChar *SFGetChar(SplineFont *sf, int unienc, const char *name ) {
+ int ind;
+ int j;
+
+ ind = SFCIDFindCID(sf,unienc,name);
+ if ( ind==-1 )
+return( NULL );
+
+ if ( sf->subfonts==NULL && sf->cidmaster==NULL )
+return( sf->glyphs[ind]);
+
+ if ( sf->cidmaster!=NULL )
+ sf=sf->cidmaster;
+
+ j = SFHasCID(sf,ind);
+ if ( j==-1 )
+return( NULL );
+
+return( sf->subfonts[j]->glyphs[ind] );
+}
+
+#ifndef LUA_FF_LIB
+SplineChar *SFGetOrMakeChar(SplineFont *sf, int unienc, const char *name ) {
+ SplineChar *sc=NULL;
+
+ if ( sf->fv!=NULL ) {
+ int ind = SFFindSlot(sf,sf->fv->map,unienc,name);
+ if ( ind!=-1 )
+ sc = SFMakeChar(sf,sf->fv->map,ind);
+ } else
+ sc = SFGetChar(sf,unienc,name);
+ if ( sc==NULL && (unienc!=-1 || name!=NULL)) {
+ sc = SplineCharCreate();
+#ifdef FONTFORGE_CONFIG_TYPE3
+ if ( sf->strokedfont ) {
+ sc->layers[ly_fore].dostroke = true;
+ sc->layers[ly_fore].dofill = false;
+ }
+#endif
+ sc->unicodeenc = unienc;
+ if ( name!=NULL )
+ sc->name = copy(name);
+ else {
+ char buffer[40];
+ sprintf(buffer,"glyph%d", sf->glyphcnt);
+ sc->name = copy(buffer);
+ }
+ SFAddGlyphAndEncode(sf,sc,NULL,-1);
+ /*SCLigDefault(sc);*/
+ }
+return( sc );
+}
+#endif
+
+static int _SFFindExistingSlot(SplineFont *sf, int unienc, const char *name ) {
+ int gid = -1;
+ struct altuni *altuni;
+
+ if ( unienc!=-1 ) {
+ for ( gid=sf->glyphcnt-1; gid>=0; --gid ) if ( sf->glyphs[gid]!=NULL ) {
+ if ( sf->glyphs[gid]->unicodeenc==unienc )
+ break;
+ for ( altuni=sf->glyphs[gid]->altuni ; altuni!=NULL && altuni->unienc!=unienc ;
+ altuni=altuni->next );
+ if ( altuni!=NULL )
+ break;
+ }
+ }
+ if ( gid==-1 && name!=NULL ) {
+ SplineChar *sc = SFHashName(sf,name);
+ if ( sc==NULL )
+return( -1 );
+ gid = sc->orig_pos;
+ }
+return( gid );
+}
+
+int SFFindExistingSlot(SplineFont *sf, int unienc, const char *name ) {
+ int gid = _SFFindExistingSlot(sf,unienc,name);
+
+ if ( gid==-1 || !SCWorthOutputting(sf->glyphs[gid]) )
+return( -1 );
+
+return( gid );
+}
+
+
+#ifndef LUA_FF_LIB
+
+static void MFixupSC(SplineFont *sf, SplineChar *sc,int i) {
+ RefChar *ref, *prev;
+ FontView *fvs;
+
+ sc->orig_pos = i;
+ sc->parent = sf;
+ retry:
+ for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
+ /* The sc in the ref is from the old font. It's got to be in the */
+ /* new font too (was either already there or just got copied) */
+ ref->orig_pos = SFFindExistingSlot(sf,ref->sc->unicodeenc,ref->sc->name);
+ if ( ref->orig_pos==-1 ) {
+ IError("Bad reference, can't fix it up");
+ if ( ref==sc->layers[ly_fore].refs ) {
+ sc->layers[ly_fore].refs = ref->next;
+ goto retry;
+ } else {
+ for ( prev=sc->layers[ly_fore].refs; prev->next!=ref; prev=prev->next );
+ prev->next = ref->next;
+ chunkfree(ref,sizeof(*ref));
+ ref = prev;
+ }
+ } else {
+ ref->sc = sf->glyphs[ref->orig_pos];
+ if ( ref->sc->orig_pos==-2 )
+ MFixupSC(sf,ref->sc,ref->orig_pos);
+ SCReinstanciateRefChar(sc,ref);
+ SCMakeDependent(sc,ref->sc);
+ }
+ }
+ /* I shan't automagically generate bitmaps for any bdf fonts */
+ /* but I have copied over the ones which match */
+ for ( fvs=sf->fv; fvs!=NULL; fvs=fvs->nextsame ) if ( fvs->filled!=NULL )
+ fvs->filled->glyphs[i] = SplineCharRasterize(sc,fvs->filled->pixelsize);
+}
+
+static void MergeFixupRefChars(SplineFont *sf) {
+ int i;
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL && sf->glyphs[i]->orig_pos==-2 ) {
+ MFixupSC(sf,sf->glyphs[i], i);
+ }
+}
+
+int SFHasChar(SplineFont *sf, int unienc, const char *name ) {
+ SplineChar *sc = SFGetChar(sf,unienc,name);
+
+return( SCWorthOutputting(sc) );
+}
+
+static void FVMergeRefigureMapSel(FontView *fv,SplineFont *into,SplineFont *o_sf,
+ int *mapping, int emptypos, int cnt) {
+ int extras, doit, i;
+ EncMap *map = fv->map;
+ int base = map->enccount;
+
+ base = map->enccount;
+
+ for ( doit=0; doit<2; ++doit ) {
+ extras = 0;
+ for ( i=0; i<o_sf->glyphcnt; ++i ) if ( mapping[i]>=emptypos ) {
+ int index = SFFindSlot(into,map,o_sf->glyphs[i]->unicodeenc,o_sf->glyphs[i]->name);
+ if ( !doit ) {
+ if ( index==-1 )
+ ++extras;
+ } else {
+ if ( index==-1 )
+ index = base+ extras++;
+ map->map[index] = mapping[i];
+ map->backmap[mapping[i]] = index;
+ }
+ }
+ if ( !doit ) {
+ if ( into->glyphcnt+cnt>map->backmax ) {
+ map->backmap = grealloc(map->backmap,(into->glyphcnt+cnt)*sizeof(int));
+ map->backmax = into->glyphcnt+cnt;
+ }
+ memset(map->backmap+into->glyphcnt,-1,cnt*sizeof(int));
+ if ( map->enccount+extras>map->encmax ) {
+ map->map = grealloc(map->map,(map->enccount+extras)*sizeof(int));
+ map->encmax = map->enccount+extras;
+ }
+ memset(map->map+map->enccount,-1,extras*sizeof(int));
+ map->enccount += extras;
+ }
+ }
+ if ( extras!=0 ) {
+ fv->selected = grealloc(fv->selected,map->enccount);
+ memset(fv->selected+map->enccount-extras,0,extras);
+ }
+}
+
+static void _MergeFont(SplineFont *into,SplineFont *other,struct sfmergecontext *mc) {
+ int i,cnt, doit, emptypos, index, k;
+ SplineFont *o_sf, *bitmap_into;
+ BDFFont *bdf;
+ FontView *fvs;
+ int *mapping;
+
+ emptypos = into->glyphcnt;
+ mapping = galloc(other->glyphcnt*sizeof(int));
+ memset(mapping,-1,other->glyphcnt*sizeof(int));
+
+ bitmap_into = into->cidmaster!=NULL? into->cidmaster : into;
+
+ for ( doit=0; doit<2; ++doit ) {
+ cnt = 0;
+ k = 0;
+ do {
+ o_sf = ( other->subfonts==NULL ) ? other : other->subfonts[k];
+ for ( i=0; i<o_sf->glyphcnt; ++i ) if ( o_sf->glyphs[i]!=NULL ) {
+ if ( doit && (index = mapping[i])!=-1 ) {
+ /* Bug here. Suppose someone has a reference to our empty */
+ /* char */
+ SplineCharFree(into->glyphs[index]);
+ into->glyphs[index] = SplineCharCopy(o_sf->glyphs[i],into,mc);
+ if ( into->bitmaps!=NULL && other->bitmaps!=NULL )
+ BitmapsCopy(bitmap_into,other,index,i);
+ } else if ( !doit ) {
+ if ( !SCWorthOutputting(o_sf->glyphs[i] ))
+ /* Don't bother to copy it */;
+ else if ( !SFHasChar(into,o_sf->glyphs[i]->unicodeenc,o_sf->glyphs[i]->name)) {
+ /* Possible for a font to contain a glyph not worth outputting */
+ if ( (index = _SFFindExistingSlot(into,o_sf->glyphs[i]->unicodeenc,o_sf->glyphs[i]->name))==-1 )
+ index = emptypos+cnt++;
+ mapping[i] = index;
+ }
+ }
+ }
+ if ( !doit ) {
+ if ( emptypos+cnt >= into->glyphcnt && emptypos+cnt>0 ) {
+ into->glyphs = grealloc(into->glyphs,(emptypos+cnt)*sizeof(SplineChar *));
+ memset(into->glyphs+emptypos,0,cnt*sizeof(SplineChar *));
+ for ( bdf = bitmap_into->bitmaps; bdf!=NULL; bdf=bdf->next )
+ if ( emptypos+cnt > bdf->glyphcnt ) {
+ bdf->glyphs = grealloc(bdf->glyphs,(emptypos+cnt)*sizeof(BDFChar *));
+ memset(bdf->glyphs+emptypos,0,cnt*sizeof(BDFChar *));
+ bdf->glyphmax = bdf->glyphcnt = emptypos+cnt;
+ }
+ for ( fvs = into->fv; fvs!=NULL; fvs=fvs->nextsame )
+ if ( fvs->filled!=NULL ) {
+ fvs->filled->glyphs = grealloc(fvs->filled->glyphs,(emptypos+cnt)*sizeof(BDFChar *));
+ memset(fvs->filled->glyphs+emptypos,0,cnt*sizeof(BDFChar *));
+ fvs->filled->glyphmax = fvs->filled->glyphcnt = emptypos+cnt;
+ }
+ for ( fvs = into->fv; fvs!=NULL; fvs=fvs->nextsame )
+ if ( fvs->sf == into )
+ FVMergeRefigureMapSel(fvs,into,o_sf,mapping,emptypos,cnt);
+ into->glyphcnt = into->glyphmax = emptypos+cnt;
+ }
+ }
+ ++k;
+ } while ( k<other->subfontcnt );
+ }
+ for ( i=0; i<other->glyphcnt; ++i ) if ( (index=mapping[i])!=-1 )
+ into->glyphs[index]->kerns = KernsCopy(other->glyphs[i]->kerns,mapping,into,mc);
+ free(mapping);
+ GlyphHashFree(into);
+ MergeFixupRefChars(into);
+ if ( other->fv==NULL )
+ SplineFontFree(other);
+ into->changed = true;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FontViewReformatAll(into);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ GlyphHashFree(into);
+}
+
+static void __MergeFont(SplineFont *into,SplineFont *other) {
+ struct sfmergecontext mc;
+
+ memset(&mc,0,sizeof(mc));
+ mc.sf_from = other; mc.sf_to = into;
+
+ AnchorClassesAdd(into,other,&mc);
+ FPSTsAdd(into,other,&mc);
+ ASMsAdd(into,other,&mc);
+ KernClassesAdd(into,other,&mc);
+
+ _MergeFont(into,other,&mc);
+}
+
+static void CIDMergeFont(SplineFont *into,SplineFont *other) {
+ int i,j,k;
+ SplineFont *i_sf, *o_sf;
+ FontView *fvs;
+ struct sfmergecontext mc;
+
+ memset(&mc,0,sizeof(mc));
+ mc.sf_from = other; mc.sf_to = into;
+
+ AnchorClassesAdd(into,other,&mc);
+ FPSTsAdd(into,other,&mc);
+ ASMsAdd(into,other,&mc);
+ KernClassesAdd(into,other,&mc);
+
+ k = 0;
+ do {
+ o_sf = other->subfonts[k];
+ i_sf = into->subfonts[k];
+ for ( i=o_sf->glyphcnt-1; i>=0 && o_sf->glyphs[i]==NULL; --i );
+ if ( i>=i_sf->glyphcnt ) {
+ i_sf->glyphs = grealloc(i_sf->glyphs,(i+1)*sizeof(SplineChar *));
+ for ( j=i_sf->glyphcnt; j<=i; ++j )
+ i_sf->glyphs[j] = NULL;
+ for ( fvs = i_sf->fv; fvs!=NULL; fvs=fvs->nextsame )
+ if ( fvs->sf==i_sf ) {
+ fvs->selected = grealloc(fvs->selected,i+1);
+ for ( j=i_sf->glyphcnt; j<=i; ++j )
+ fvs->selected[j] = false;
+ }
+ i_sf->glyphcnt = i_sf->glyphmax = i+1;
+ }
+ for ( i=0; i<o_sf->glyphcnt; ++i ) if ( o_sf->glyphs[i]!=NULL ) {
+ if ( o_sf->glyphs[i]->layers[ly_fore].splines==NULL && o_sf->glyphs[i]->layers[ly_fore].refs==NULL &&
+ !o_sf->glyphs[i]->widthset )
+ /* Don't bother to copy it */;
+ else if ( SFHasCID(into,i)==-1 ) {
+ SplineCharFree(i_sf->glyphs[i]);
+ i_sf->glyphs[i] = SplineCharCopy(o_sf->glyphs[i],i_sf,&mc);
+ if ( into->bitmaps!=NULL && other->bitmaps!=NULL )
+ BitmapsCopy(into,other,i,i);
+ }
+ }
+ MergeFixupRefChars(i_sf);
+ ++k;
+ } while ( k<other->subfontcnt );
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FontViewReformatAll(into);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ into->changed = true;
+ GlyphHashFree(into);
+}
+
+void MergeFont(FontView *fv,SplineFont *other) {
+
+ if ( fv->sf==other ) {
+ gwwv_post_error(_("Merging Problem"),_("Merging a font with itself achieves nothing"));
+return;
+ }
+ if ( fv->sf->cidmaster!=NULL && other->subfonts!=NULL &&
+ (strcmp(fv->sf->cidmaster->cidregistry,other->cidregistry)!=0 ||
+ strcmp(fv->sf->cidmaster->ordering,other->ordering)!=0 ||
+ fv->sf->cidmaster->supplement<other->supplement ||
+ fv->sf->cidmaster->subfontcnt<other->subfontcnt )) {
+ gwwv_post_error(_("Merging Problem"),_("When merging two CID keyed fonts, they must have the same Registry and Ordering, and the font being merged into (the mergee) must have a supplement which is at least as recent as the other's. Furthermore the mergee must have at least as many subfonts as the merger."));
+return;
+ }
+ /* Ok. when merging CID fonts... */
+ /* If fv is normal and other is CID then just flatten other and merge everything into fv */
+ /* If fv is CID and other is normal then merge other into the currently active font */
+ /* If both are CID then merge each subfont seperately */
+ if ( fv->sf->cidmaster!=NULL && other->subfonts!=NULL )
+ CIDMergeFont(fv->sf->cidmaster,other);
+ else
+ __MergeFont(fv->sf,other);
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static void MergeAskFilename(FontView *fv) {
+ char *filename = GetPostscriptFontName(NULL,true);
+ SplineFont *sf;
+ char *eod, *fpt, *file, *full;
+
+ if ( filename==NULL )
+return;
+ eod = strrchr(filename,'/');
+ *eod = '\0';
+ file = eod+1;
+ do {
+ fpt = strstr(file,"; ");
+ if ( fpt!=NULL ) *fpt = '\0';
+ full = galloc(strlen(filename)+1+strlen(file)+1);
+ strcpy(full,filename); strcat(full,"/"); strcat(full,file);
+ sf = LoadSplineFont(full,0);
+ if ( sf!=NULL && sf->fv==NULL )
+ EncMapFree(sf->map);
+ free(full);
+ if ( sf==NULL )
+ /* Do Nothing */;
+ else if ( sf->fv==fv )
+ gwwv_post_error(_("Merging Problem"),_("Merging a font with itself achieves nothing"));
+ else
+ MergeFont(fv,sf);
+ file = fpt+2;
+ } while ( fpt!=NULL );
+ free(filename);
+}
+
+GTextInfo *BuildFontList(FontView *except) {
+ FontView *fv;
+ int cnt=0;
+ GTextInfo *tf;
+
+ for ( fv=fv_list; fv!=NULL; fv = fv->next )
+ ++cnt;
+ tf = gcalloc(cnt+3,sizeof(GTextInfo));
+ for ( fv=fv_list, cnt=0; fv!=NULL; fv = fv->next ) if ( fv!=except ) {
+ tf[cnt].fg = tf[cnt].bg = COLOR_DEFAULT;
+ tf[cnt].text = (unichar_t *) fv->sf->fontname;
+ tf[cnt].text_is_1byte = true;
+ ++cnt;
+ }
+ tf[cnt++].line = true;
+ tf[cnt].fg = tf[cnt].bg = COLOR_DEFAULT;
+ tf[cnt].text_is_1byte = true;
+ tf[cnt++].text = (unichar_t *) _("Other ...");
+return( tf );
+}
+
+void TFFree(GTextInfo *tf) {
+/*
+ int i;
+
+ for ( i=0; tf[i].text!=NULL || tf[i].line ; ++i )
+ if ( !tf[i].text_in_resource )
+ free( tf[i].text );
+*/
+ free(tf);
+}
+
+struct mf_data {
+ int done;
+ FontView *fv;
+ GGadget *other;
+ GGadget *amount;
+};
+
+static int MF_OK(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GWindow gw = GGadgetGetWindow(g);
+ struct mf_data *d = GDrawGetUserData(gw);
+ int i, index = GGadgetGetFirstListSelectedItem(d->other);
+ FontView *fv;
+ for ( i=0, fv=fv_list; fv!=NULL; fv=fv->next ) {
+ if ( fv==d->fv )
+ continue;
+ if ( i==index )
+ break;
+ ++i;
+ }
+ if ( fv==NULL )
+ MergeAskFilename(d->fv);
+ else
+ MergeFont(d->fv,fv->sf);
+ d->done = true;
+ }
+return( true );
+}
+
+static int MF_Cancel(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GWindow gw = GGadgetGetWindow(g);
+ struct mf_data *d = GDrawGetUserData(gw);
+ d->done = true;
+ }
+return( true );
+}
+
+static int mv_e_h(GWindow gw, GEvent *event) {
+ if ( event->type==et_close ) {
+ struct mf_data *d = GDrawGetUserData(gw);
+ d->done = true;
+ } else if ( event->type == et_char ) {
+return( false );
+ }
+return( true );
+}
+
+void FVMergeFonts(FontView *fv) {
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[6];
+ GTextInfo label[6];
+ struct mf_data d;
+ char buffer[80];
+
+ /* If there's only one font loaded, then it's the current one, and there's*/
+ /* no point asking the user if s/he wants to merge any of the loaded */
+ /* fonts, go directly to searching the disk */
+ if ( fv_list==fv && fv_list->next==NULL )
+ MergeAskFilename(fv);
+ else {
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Merge Fonts...");
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,150));
+ pos.height = GDrawPointsToPixels(NULL,88);
+ gw = GDrawCreateTopWindow(NULL,&pos,mv_e_h,&d,&wattrs);
+
+ memset(&label,0,sizeof(label));
+ memset(&gcd,0,sizeof(gcd));
+
+ sprintf( buffer, _("Font to merge into %.20s"), fv->sf->fontname );
+ label[0].text = (unichar_t *) buffer;
+ label[0].text_is_1byte = true;
+ gcd[0].gd.label = &label[0];
+ gcd[0].gd.pos.x = 12; gcd[0].gd.pos.y = 6;
+ gcd[0].gd.flags = gg_visible | gg_enabled;
+ gcd[0].creator = GLabelCreate;
+
+ gcd[1].gd.pos.x = 15; gcd[1].gd.pos.y = 21;
+ gcd[1].gd.pos.width = 120;
+ gcd[1].gd.flags = gg_visible | gg_enabled;
+ gcd[1].gd.u.list = BuildFontList(fv);
+ gcd[1].gd.label = &gcd[1].gd.u.list[0];
+ gcd[1].gd.u.list[0].selected = true;
+ gcd[1].creator = GListButtonCreate;
+
+ gcd[2].gd.pos.x = 15-3; gcd[2].gd.pos.y = 55-3;
+ gcd[2].gd.pos.width = -1; gcd[2].gd.pos.height = 0;
+ gcd[2].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[2].text = (unichar_t *) _("_OK");
+ label[2].text_is_1byte = true;
+ label[2].text_in_resource = true;
+ gcd[2].gd.mnemonic = 'O';
+ gcd[2].gd.label = &label[2];
+ gcd[2].gd.handle_controlevent = MF_OK;
+ gcd[2].creator = GButtonCreate;
+
+ gcd[3].gd.pos.x = -15; gcd[3].gd.pos.y = 55;
+ gcd[3].gd.pos.width = -1; gcd[3].gd.pos.height = 0;
+ gcd[3].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[3].text = (unichar_t *) _("_Cancel");
+ label[3].text_is_1byte = true;
+ label[3].text_in_resource = true;
+ gcd[3].gd.label = &label[3];
+ gcd[3].gd.mnemonic = 'C';
+ gcd[3].gd.handle_controlevent = MF_Cancel;
+ gcd[3].creator = GButtonCreate;
+
+ GGadgetsCreate(gw,gcd);
+
+ memset(&d,'\0',sizeof(d));
+ d.other = gcd[1].ret;
+ d.fv = fv;
+
+ GWidgetHidePalettes();
+ GDrawSetVisible(gw,true);
+ while ( !d.done )
+ GDrawProcessOneEvent(NULL);
+ GDrawDestroyWindow(gw);
+ TFFree(gcd[1].gd.u.list);
+ }
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+#ifndef LUA_FF_LIB
+static RefChar *InterpRefs(RefChar *base, RefChar *other, real amount, SplineChar *sc) {
+ RefChar *head=NULL, *last=NULL, *cur;
+ RefChar *test;
+ int i;
+
+ for ( test = other; test!=NULL; test=test->next )
+ test->checked = false;
+
+ while ( base!=NULL ) {
+ for ( test = other; test!=NULL; test=test->next ) {
+ if ( test->checked )
+ /* Do nothing */;
+ else if ( test->unicode_enc==base->unicode_enc &&
+ (test->unicode_enc!=-1 || strcmp(test->sc->name,base->sc->name)==0 ) )
+ break;
+ }
+ if ( test!=NULL ) {
+ test->checked = true;
+ cur = RefCharCreate();
+ *cur = *base;
+ cur->orig_pos = cur->sc->orig_pos;
+ for ( i=0; i<6; ++i )
+ cur->transform[i] = base->transform[i] + amount*(other->transform[i]-base->transform[i]);
+ cur->layers[0].splines = NULL;
+ cur->checked = false;
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ } else
+ LogError( _("In character %s, could not find reference to %s\n"),
+ sc->name, base->sc->name );
+ base = base->next;
+ if ( test==other && other!=NULL )
+ other = other->next;
+ }
+return( head );
+}
+
+static void InterpPoint(SplineSet *cur, SplinePoint *base, SplinePoint *other, real amount ) {
+ SplinePoint *p = chunkalloc(sizeof(SplinePoint));
+ int order2 = base->prev!=NULL ? base->prev->order2 : base->next!=NULL ? base->next->order2 : false;
+
+ p->me.x = base->me.x + amount*(other->me.x-base->me.x);
+ p->me.y = base->me.y + amount*(other->me.y-base->me.y);
+ if ( order2 && base->prev!=NULL && (base->prev->islinear || other->prev->islinear ))
+ p->prevcp = p->me;
+ else {
+ p->prevcp.x = base->prevcp.x + amount*(other->prevcp.x-base->prevcp.x);
+ p->prevcp.y = base->prevcp.y + amount*(other->prevcp.y-base->prevcp.y);
+ if ( order2 && cur->first!=NULL ) {
+ /* In the normal course of events this isn't needed, but if we have */
+ /* a different number of points on one path than on the other then */
+ /* all hell breaks lose without this */
+ cur->last->nextcp.x = p->prevcp.x = (cur->last->nextcp.x+p->prevcp.x)/2;
+ cur->last->nextcp.y = p->prevcp.y = (cur->last->nextcp.y+p->prevcp.y)/2;
+ }
+ }
+ if ( order2 && base->next!=NULL && (base->next->islinear || other->next->islinear ))
+ p->nextcp = p->me;
+ else {
+ p->nextcp.x = base->nextcp.x + amount*(other->nextcp.x-base->nextcp.x);
+ p->nextcp.y = base->nextcp.y + amount*(other->nextcp.y-base->nextcp.y);
+ }
+ p->nonextcp = ( p->nextcp.x==p->me.x && p->nextcp.y==p->me.y );
+ p->noprevcp = ( p->prevcp.x==p->me.x && p->prevcp.y==p->me.y );
+ p->prevcpdef = base->prevcpdef && other->prevcpdef;
+ p->nextcpdef = base->nextcpdef && other->nextcpdef;
+ p->selected = false;
+ p->pointtype = (base->pointtype==other->pointtype)?base->pointtype:pt_corner;
+ /*p->flex = 0;*/
+ if ( cur->first==NULL )
+ cur->first = p;
+ else
+ SplineMake(cur->last,p,order2);
+ cur->last = p;
+}
+
+static SplineSet *InterpSplineSet(SplineSet *base, SplineSet *other, real amount, SplineChar *sc) {
+ SplineSet *cur = chunkalloc(sizeof(SplineSet));
+ SplinePoint *bp, *op;
+
+ for ( bp=base->first, op = other->first; ; ) {
+ InterpPoint(cur,bp,op,amount);
+ if ( bp->next == NULL && op->next == NULL )
+return( cur );
+ if ( bp->next!=NULL && op->next!=NULL &&
+ bp->next->to==base->first && op->next->to==other->first ) {
+ SplineMake(cur->last,cur->first,bp->next->order2);
+ cur->last = cur->first;
+return( cur );
+ }
+ if ( bp->next == NULL || bp->next->to==base->first ) {
+ LogError( _("In character %s, there are too few points on a path in the base\n"), sc->name);
+ if ( bp->next!=NULL ) {
+ if ( bp->next->order2 ) {
+ cur->last->nextcp.x = cur->first->prevcp.x = (cur->last->nextcp.x+cur->first->prevcp.x)/2;
+ cur->last->nextcp.y = cur->first->prevcp.y = (cur->last->nextcp.y+cur->first->prevcp.y)/2;
+ }
+ SplineMake(cur->last,cur->first,bp->next->order2);
+ cur->last = cur->first;
+ }
+return( cur );
+ } else if ( op->next==NULL || op->next->to==other->first ) {
+ LogError( _("In character %s, there are too many points on a path in the base\n"), sc->name);
+ while ( bp->next!=NULL && bp->next->to!=base->first ) {
+ bp = bp->next->to;
+ InterpPoint(cur,bp,op,amount);
+ }
+ if ( bp->next!=NULL ) {
+ if ( bp->next->order2 ) {
+ cur->last->nextcp.x = cur->first->prevcp.x = (cur->last->nextcp.x+cur->first->prevcp.x)/2;
+ cur->last->nextcp.y = cur->first->prevcp.y = (cur->last->nextcp.y+cur->first->prevcp.y)/2;
+ }
+ SplineMake(cur->last,cur->first,bp->next->order2);
+ cur->last = cur->first;
+ }
+return( cur );
+ }
+ bp = bp->next->to;
+ op = op->next->to;
+ }
+}
+
+static SplineSet *InterpSplineSets(SplineSet *base, SplineSet *other, real amount, SplineChar *sc) {
+ SplineSet *head=NULL, *last=NULL, *cur;
+
+ /* we could do something really complex to try and figure out which spline*/
+ /* set goes with which, but I'm not sure that it would really accomplish */
+ /* much, if things are off the computer probably won't figure it out */
+ /* Could use path open/closed, direction, point count */
+ while ( base!=NULL && other!=NULL ) {
+ cur = InterpSplineSet(base,other,amount,sc);
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ base = base->next;
+ other = other->next;
+ }
+return( head );
+}
+
+static int SCSameChar(SplineChar *sc1,SplineChar *sc2) {
+ if ( sc1->unicodeenc!=-1 )
+return( sc1->unicodeenc==sc2->unicodeenc );
+
+return( strcmp(sc1->name,sc2->name)==0 );
+}
+
+static KernPair *InterpKerns(KernPair *kp1, KernPair *kp2, real amount,
+ SplineFont *new, SplineChar *scnew) {
+ KernPair *head=NULL, *last, *nkp, *k;
+
+ last = NULL;
+ if ( kp1==NULL || kp2==NULL )
+return( NULL );
+ while ( kp1!=NULL ) {
+ for ( k=kp2; k!=NULL && !SCSameChar(k->sc,kp1->sc); k=k->next );
+ if ( k!=NULL ) {
+ if ( k==kp2 ) kp2 = kp2->next;
+ nkp = chunkalloc(sizeof(KernPair));
+ nkp->sc = new->glyphs[kp1->sc->orig_pos];
+ nkp->off = kp1->off + amount*(k->off-kp1->off);
+ nkp->subtable = SFSubTableFindOrMake(new,CHR('k','e','r','n'),
+ SCScriptFromUnicode(scnew),gpos_pair);
+ if ( head==NULL )
+ head = nkp;
+ else
+ last->next = nkp;
+ last = nkp;
+ }
+ kp1 = kp1->next;
+ }
+return( head );
+}
+#endif
+
+#ifdef FONTFORGE_CONFIG_TYPE3
+static uint32 InterpColor( uint32 col1,uint32 col2, real amount ) {
+ int r1, g1, b1, r2, b2, g2;
+
+ r1 = (col1>>16)&0xff;
+ r2 = (col2>>16)&0xff;
+ g1 = (col1>>8 )&0xff;
+ g2 = (col2>>8 )&0xff;
+ b1 = (col1 )&0xff;
+ b2 = (col2 )&0xff;
+ r1 += amount * (r2-r1);
+ g1 += amount * (g2-g1);
+ b1 += amount * (b2-b1);
+return( (r1<<16) | (g1<<8) | b1 );
+}
+
+static void LayerInterpolate(Layer *to,Layer *base,Layer *other,real amount,SplineChar *sc, int lc) {
+
+ /* to already has things set to default values, so when an error occurs */
+ /* I just leave things as the default (and don't need to set it again) */
+ if ( base->dostroke==other->dostroke )
+ to->dostroke = base->dostroke;
+ else
+ LogError( _("Different settings on whether to stroke in layer %d of %s\n"), lc, sc->name );
+ if ( base->dofill==other->dofill )
+ to->dofill = base->dofill;
+ else
+ LogError( "Different settings on whether to fill in layer %d of %s\n", lc, sc->name );
+ if ( base->fill_brush.col==COLOR_INHERITED && other->fill_brush.col==COLOR_INHERITED )
+ to->fill_brush.col = COLOR_INHERITED;
+ else if ( base->fill_brush.col!=COLOR_INHERITED && other->fill_brush.col!=COLOR_INHERITED )
+ to->fill_brush.col = InterpColor( base->fill_brush.col,other->fill_brush.col, amount );
+ else
+ LogError( "Different settings on whether to inherit fill color in layer %d of %s\n", lc, sc->name );
+ if ( base->fill_brush.opacity<0 && other->fill_brush.opacity<0 )
+ to->fill_brush.opacity = WIDTH_INHERITED;
+ else if ( base->fill_brush.opacity>=0 && other->fill_brush.opacity>=0 )
+ to->fill_brush.opacity = base->fill_brush.opacity + amount*(other->fill_brush.opacity-base->fill_brush.opacity);
+ else
+ LogError( "Different settings on whether to inherit fill opacity in layer %d of %s\n", lc, sc->name );
+ if ( base->stroke_pen.brush.col==COLOR_INHERITED && other->stroke_pen.brush.col==COLOR_INHERITED )
+ to->stroke_pen.brush.col = COLOR_INHERITED;
+ else if ( base->stroke_pen.brush.col!=COLOR_INHERITED && other->stroke_pen.brush.col!=COLOR_INHERITED )
+ to->stroke_pen.brush.col = InterpColor( base->stroke_pen.brush.col,other->stroke_pen.brush.col, amount );
+ else
+ LogError( "Different settings on whether to inherit fill color in layer %d of %s\n", lc, sc->name );
+ if ( base->stroke_pen.brush.opacity<0 && other->stroke_pen.brush.opacity<0 )
+ to->stroke_pen.brush.opacity = WIDTH_INHERITED;
+ else if ( base->stroke_pen.brush.opacity>=0 && other->stroke_pen.brush.opacity>=0 )
+ to->stroke_pen.brush.opacity = base->stroke_pen.brush.opacity + amount*(other->stroke_pen.brush.opacity-base->stroke_pen.brush.opacity);
+ else
+ LogError( "Different settings on whether to inherit stroke opacity in layer %d of %s\n", lc, sc->name );
+ if ( base->stroke_pen.width<0 && other->stroke_pen.width<0 )
+ to->stroke_pen.width = WIDTH_INHERITED;
+ else if ( base->stroke_pen.width>=0 && other->stroke_pen.width>=0 )
+ to->stroke_pen.width = base->stroke_pen.width + amount*(other->stroke_pen.width-base->stroke_pen.width);
+ else
+ LogError( "Different settings on whether to inherit stroke width in layer %d of %s\n", lc, sc->name );
+ if ( base->stroke_pen.linecap==other->stroke_pen.linecap )
+ to->stroke_pen.linecap = base->stroke_pen.linecap;
+ else
+ LogError( "Different settings on stroke linecap in layer %d of %s\n", lc, sc->name );
+ if ( base->stroke_pen.linejoin==other->stroke_pen.linejoin )
+ to->stroke_pen.linejoin = base->stroke_pen.linejoin;
+ else
+ LogError( "Different settings on stroke linejoin in layer %d of %s\n", lc, sc->name );
+
+ to->splines = InterpSplineSets(base->splines,other->splines,amount,sc);
+ to->refs = InterpRefs(base->refs,other->refs,amount,sc);
+ if ( base->images!=NULL || other->images!=NULL )
+ LogError( "I can't even imagine how to attempt to interpolate images in layer %d of %s\n", lc, sc->name );
+}
+#endif
+
+#ifndef LUA_FF_LIB
+static void InterpolateChar(SplineFont *new, int orig_pos, SplineChar *base, SplineChar *other, real amount) {
+ SplineChar *sc;
+
+ if ( base==NULL || other==NULL )
+return;
+ sc = SplineCharCreate();
+ sc->orig_pos = orig_pos;
+ sc->unicodeenc = base->unicodeenc;
+ new->glyphs[orig_pos] = sc;
+ if ( orig_pos+1>new->glyphcnt )
+ new->glyphcnt = orig_pos+1;
+ sc->parent = new;
+ sc->changed = true;
+ sc->views = NULL;
+ sc->dependents = NULL;
+ sc->layers[ly_back].splines = NULL;
+ sc->layers[ly_back].images = NULL;
+ sc->layers[ly_fore].undoes = sc->layers[ly_back].undoes = NULL;
+ sc->layers[ly_fore].redoes = sc->layers[ly_back].redoes = NULL;
+ sc->kerns = NULL;
+ sc->name = copy(base->name);
+ sc->width = base->width + amount*(other->width-base->width);
+ sc->vwidth = base->vwidth + amount*(other->vwidth-base->vwidth);
+ sc->lsidebearing = base->lsidebearing + amount*(other->lsidebearing-base->lsidebearing);
+#ifdef FONTFORGE_CONFIG_TYPE3
+ if ( base->parent->multilayer && other->parent->multilayer ) {
+ int lc = base->layer_cnt,i;
+ if ( lc!=other->layer_cnt ) {
+ LogError( "Different numbers of layers in %s\n", base->name );
+ if ( other->layer_cnt<lc ) lc = other->layer_cnt;
+ }
+ if ( lc>2 ) {
+ sc->layers = grealloc(sc->layers,lc*sizeof(Layer));
+ for ( i=ly_fore+1; i<lc; ++i )
+ LayerDefault(&sc->layers[i]);
+ }
+ for ( i=ly_fore; i<lc; ++i )
+ LayerInterpolate(&sc->layers[i],&base->layers[i],&other->layers[i],amount,sc,i);
+ } else
+#endif
+ {
+ sc->layers[ly_fore].splines = InterpSplineSets(base->layers[ly_fore].splines,other->layers[ly_fore].splines,amount,sc);
+ sc->layers[ly_fore].refs = InterpRefs(base->layers[ly_fore].refs,other->layers[ly_fore].refs,amount,sc);
+ }
+ sc->changedsincelasthinted = true;
+ sc->widthset = base->widthset;
+ sc->glyph_class = base->glyph_class;
+}
+
+static void IFixupSC(SplineFont *sf, SplineChar *sc,int i) {
+ RefChar *ref;
+
+ for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) if ( !ref->checked ) {
+ /* The sc in the ref is from the base font. It's got to be in the */
+ /* new font too (the ref only gets created if it's present in both fonts)*/
+ ref->checked = true;
+ ref->orig_pos = SFFindExistingSlot(sf,ref->sc->unicodeenc,ref->sc->name);
+ ref->sc = sf->glyphs[ref->orig_pos];
+ IFixupSC(sf,ref->sc,ref->orig_pos);
+ SCReinstanciateRefChar(sc,ref);
+ SCMakeDependent(sc,ref->sc);
+ }
+}
+
+static void InterpFixupRefChars(SplineFont *sf) {
+ int i;
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ IFixupSC(sf,sf->glyphs[i], i);
+ }
+}
+
+SplineFont *InterpolateFont(SplineFont *base, SplineFont *other, real amount,
+ Encoding *enc) {
+ SplineFont *new;
+ int i, index;
+
+ if ( base==other ) {
+#if defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("Interpolating Problem"),_("Interpolating a font with itself achieves nothing"));
+#else
+ gwwv_post_error(_("Interpolating Problem"),_("Interpolating a font with itself achieves nothing"));
+#endif
+return( NULL );
+ } else if ( base->order2!=other->order2 ) {
+#if defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("Interpolating Problem"),_("Interpolating between fonts with different spline orders (i.e. between postscript and truetype)"));
+#else
+ gwwv_post_error(_("Interpolating Problem"),_("Interpolating between fonts with different spline orders (i.e. between postscript and truetype)"));
+#endif
+return( NULL );
+ }
+#ifdef FONTFORGE_CONFIG_TYPE3
+ else if ( base->multilayer && other->multilayer ) {
+# if defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("Interpolating Problem"),_("Interpolating between fonts with different editing types (ie. between type3 and type1)"));
+# else
+ gwwv_post_error(_("Interpolating Problem"),_("Interpolating between fonts with different editing types (ie. between type3 and type1)"));
+# endif
+return( NULL );
+ }
+#endif
+ new = SplineFontBlank(base->glyphcnt);
+ new->ascent = base->ascent + amount*(other->ascent-base->ascent);
+ new->descent = base->descent + amount*(other->descent-base->descent);
+ for ( i=0; i<base->glyphcnt; ++i ) if ( base->glyphs[i]!=NULL ) {
+ index = SFFindExistingSlot(other,base->glyphs[i]->unicodeenc,base->glyphs[i]->name);
+ if ( index!=-1 && other->glyphs[index]!=NULL ) {
+ InterpolateChar(new,i,base->glyphs[i],other->glyphs[index],amount);
+ if ( new->glyphs[i]!=NULL )
+ new->glyphs[i]->kerns = InterpKerns(base->glyphs[i]->kerns,
+ other->glyphs[index]->kerns,amount,new,new->glyphs[i]);
+ }
+ }
+ InterpFixupRefChars(new);
+ new->changed = true;
+ new->map = EncMapFromEncoding(new,enc);
+return( new );
+}
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static void InterAskFilename(FontView *fv, real amount) {
+ char *filename = GetPostscriptFontName(NULL,false);
+ SplineFont *sf;
+
+ if ( filename==NULL )
+return;
+ sf = LoadSplineFont(filename,0);
+ if ( sf!=NULL && sf->fv==NULL )
+ EncMapFree(sf->map);
+ free(filename);
+ if ( sf==NULL )
+return;
+ FontViewCreate(InterpolateFont(fv->sf,sf,amount,fv->map->enc));
+}
+
+#define CID_Amount 1000
+static double last_amount=50;
+
+static int IF_OK(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GWindow gw = GGadgetGetWindow(g);
+ struct mf_data *d = GDrawGetUserData(gw);
+ int i, index = GGadgetGetFirstListSelectedItem(d->other);
+ FontView *fv;
+ int err=false;
+ real amount;
+
+ amount = GetReal8(gw,CID_Amount, _("Amount"),&err);
+ if ( err )
+return( true );
+ last_amount = amount;
+ for ( i=0, fv=fv_list; fv!=NULL; fv=fv->next ) {
+ if ( fv==d->fv )
+ continue;
+ if ( i==index )
+ break;
+ ++i;
+ }
+ if ( fv==NULL )
+ InterAskFilename(d->fv,last_amount/100.0);
+ else
+ FontViewCreate(InterpolateFont(d->fv->sf,fv->sf,last_amount/100.0,d->fv->map->enc));
+ d->done = true;
+ }
+return( true );
+}
+
+void FVInterpolateFonts(FontView *fv) {
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[8];
+ GTextInfo label[8];
+ struct mf_data d;
+ char buffer[80]; char buf2[30];
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Interpolate Fonts...");
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,200));
+ pos.height = GDrawPointsToPixels(NULL,118);
+ gw = GDrawCreateTopWindow(NULL,&pos,mv_e_h,&d,&wattrs);
+
+ memset(&label,0,sizeof(label));
+ memset(&gcd,0,sizeof(gcd));
+
+ sprintf( buffer, _("Interpolating between %.20s and:"), fv->sf->fontname );
+ label[0].text = (unichar_t *) buffer;
+ label[0].text_is_1byte = true;
+ gcd[0].gd.label = &label[0];
+ gcd[0].gd.pos.x = 12; gcd[0].gd.pos.y = 6;
+ gcd[0].gd.flags = gg_visible | gg_enabled;
+ gcd[0].creator = GLabelCreate;
+
+ gcd[1].gd.pos.x = 20; gcd[1].gd.pos.y = 21;
+ gcd[1].gd.pos.width = 110;
+ gcd[1].gd.flags = gg_visible | gg_enabled;
+ gcd[1].gd.u.list = BuildFontList(fv);
+ if ( gcd[1].gd.u.list[0].text!=NULL ) {
+ gcd[1].gd.label = &gcd[1].gd.u.list[0];
+ gcd[1].gd.u.list[0].selected = true;
+ } else {
+ gcd[1].gd.label = &gcd[1].gd.u.list[1];
+ gcd[1].gd.u.list[1].selected = true;
+ gcd[1].gd.flags = gg_visible;
+ }
+ gcd[1].creator = GListButtonCreate;
+
+ sprintf( buf2, "%g", last_amount );
+ label[2].text = (unichar_t *) buf2;
+ label[2].text_is_1byte = true;
+ gcd[2].gd.pos.x = 20; gcd[2].gd.pos.y = 51;
+ gcd[2].gd.pos.width = 40;
+ gcd[2].gd.flags = gg_visible | gg_enabled;
+ gcd[2].gd.label = &label[2];
+ gcd[2].gd.cid = CID_Amount;
+ gcd[2].creator = GTextFieldCreate;
+
+ gcd[3].gd.pos.x = 5; gcd[3].gd.pos.y = 51+6;
+ gcd[3].gd.flags = gg_visible | gg_enabled;
+/* GT: The dialog looks like: */
+/* GT: Interpolating between <fontname> and: */
+/* GT: <list of possible fonts> */
+/* GT: by <50>% */
+/* GT: So "by" means how much to interpolate. */
+ label[3].text = (unichar_t *) _("by");
+ label[3].text_is_1byte = true;
+ gcd[3].gd.label = &label[3];
+ gcd[3].creator = GLabelCreate;
+
+ gcd[4].gd.pos.x = 20+40+3; gcd[4].gd.pos.y = 51+6;
+ gcd[4].gd.flags = gg_visible | gg_enabled;
+ label[4].text = (unichar_t *) "%";
+ label[4].text_is_1byte = true;
+ gcd[4].gd.label = &label[4];
+ gcd[4].creator = GLabelCreate;
+
+ gcd[5].gd.pos.x = 15-3; gcd[5].gd.pos.y = 85-3;
+ gcd[5].gd.pos.width = -1; gcd[5].gd.pos.height = 0;
+ gcd[5].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[5].text = (unichar_t *) _("_OK");
+ label[5].text_is_1byte = true;
+ label[5].text_in_resource = true;
+ gcd[5].gd.mnemonic = 'O';
+ gcd[5].gd.label = &label[5];
+ gcd[5].gd.handle_controlevent = IF_OK;
+ gcd[5].creator = GButtonCreate;
+
+ gcd[6].gd.pos.x = -15; gcd[6].gd.pos.y = 85;
+ gcd[6].gd.pos.width = -1; gcd[6].gd.pos.height = 0;
+ gcd[6].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[6].text = (unichar_t *) _("_Cancel");
+ label[6].text_is_1byte = true;
+ label[6].text_in_resource = true;
+ gcd[6].gd.label = &label[6];
+ gcd[6].gd.mnemonic = 'C';
+ gcd[6].gd.handle_controlevent = MF_Cancel;
+ gcd[6].creator = GButtonCreate;
+
+ GGadgetsCreate(gw,gcd);
+
+ memset(&d,'\0',sizeof(d));
+ d.other = gcd[1].ret;
+ d.fv = fv;
+
+ GWidgetHidePalettes();
+ GDrawSetVisible(gw,true);
+ while ( !d.done )
+ GDrawProcessOneEvent(NULL);
+ GDrawDestroyWindow(gw);
+ TFFree(gcd[1].gd.u.list);
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/groups.h b/Build/source/libs/luafontforge/fontforge/fontforge/groups.h
new file mode 100644
index 00000000000..95acdfb094a
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/groups.h
@@ -0,0 +1,49 @@
+/* Copyright (C) 2005-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _GROUPS_H
+#define _GROUPS_H
+
+typedef struct group {
+ char *name; /* The name of this group (utf8) */
+ struct group *parent; /* parent of this group (NULL for group root) */
+ int kid_cnt; /* Number of sub-groups */
+ struct group **kids; /* The sub-groups */
+ char *glyphs; /* Or, if a terminal node, a list of glyph names/Unicodes */
+ unsigned int unique: 1; /* If set => set in all kids & a glyph name may only appear once in all terminal groups */
+/* Used by the dialog */
+ unsigned int open: 1;
+ unsigned int selected : 1;
+ int lpos;
+} Group;
+
+extern Group *group_root;
+
+void SaveGroupList(void);
+void LoadGroupList(void);
+void DefineGroups(FontView *fv);
+void DisplayGroups(FontView *fv);
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/kernclass.c b/Build/source/libs/luafontforge/fontforge/fontforge/kernclass.c
new file mode 100644
index 00000000000..0a56a6e1108
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/kernclass.c
@@ -0,0 +1,3059 @@
+/* Copyright (C) 2003-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaeditui.h"
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+#include <gkeysym.h>
+#include <string.h>
+#include <ustring.h>
+#include <utype.h>
+#include <math.h>
+
+typedef struct kernclassdlg {
+ struct kernclasslistdlg *kcld;
+ KernClass *orig;
+ struct lookup_subtable *subtable;
+ int first_cnt, second_cnt;
+ int16 *offsets;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ DeviceTable *adjusts;
+ DeviceTable active_adjust; /* The one that is currently active */
+#endif
+ GWindow gw, cw, kw;
+ GFont *font;
+ int fh, as;
+ int kernh, kernw; /* Width of the box containing the kerning val */
+ int xstart, ystart; /* This is where the headers start */
+ int xstart2, ystart2; /* This is where the data start */
+ int width, height, fullwidth;
+ int canceldrop, sbdrop;
+ int offleft, offtop;
+ GGadget *hsb, *vsb;
+ int isedit, off;
+ int st_pos;
+ BDFChar *fsc, *ssc;
+ int pixelsize;
+ int magfactor;
+ int top;
+ int downpos, down, within, orig_kern;
+/* For the kern pair dlg */
+ int done;
+ SplineFont *sf;
+ SplineChar *sc1, *sc2;
+ int isv, iskernpair;
+ SplineChar *scf, *scs;
+ struct kernclassdlg *next;
+} KernClassDlg;
+
+typedef struct kernclasslistdlg {
+ SplineFont *sf;
+ GWindow gw;
+ int isv;
+} KernClassListDlg;
+
+#define KCL_Width 200
+#define KCL_Height 173
+#define KC_Width 400
+#define KC_Height 424
+#define KC_CANCELDROP 33
+
+#define CID_Subtable 1001
+
+#define CID_List 1040
+#define CID_New 1041
+#define CID_Delete 1042
+#define CID_Edit 1043
+
+#define CID_ClassList 1007 /* And 1107 for second char */
+#define CID_ClassNew 1008
+#define CID_ClassDel 1009
+#define CID_ClassEdit 1010
+#define CID_ClassLabel 1011
+#define CID_ClassUp 1012
+#define CID_ClassDown 1013
+#define CID_ClassSelect 1014
+
+#define CID_OK 1015
+#define CID_Cancel 1016
+
+#define CID_Set 1020
+#define CID_Select 1021
+#define CID_GlyphList 1022
+#define CID_Prev 1023
+#define CID_Next 1024
+
+#define CID_First 1030
+#define CID_Second 1031
+#define CID_KernOffset 1032
+#define CID_Prev2 1033
+#define CID_Next2 1034
+#define CID_Group3 1035
+#define CID_DisplaySize 1036
+#define CID_Correction 1037
+#define CID_FreeType 1038
+#define CID_Magnifications 1039
+
+extern int _GScrollBar_Width;
+
+static GTextInfo magnifications[] = {
+ { (unichar_t *) "100%", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 1, 0, 1},
+ { (unichar_t *) "200%", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "300%", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "400%", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }
+};
+
+static int KCD_SBReset(KernClassDlg *);
+static void KCD_HShow(KernClassDlg *, int pos);
+static void KCD_VShow(KernClassDlg *, int pos);
+
+static GTextInfo **KCLookupSubtableArray(SplineFont *sf,int isv) {
+ int cnt;
+ KernClass *kc, *head = isv ? sf->vkerns : sf->kerns;
+ GTextInfo **ti;
+
+ if ( sf->cidmaster!=NULL ) sf=sf->cidmaster;
+ else if ( sf->mm!=NULL ) sf = sf->mm->normal;
+
+ for ( kc=head, cnt=0; kc!=NULL; kc=kc->next, ++cnt );
+ ti = gcalloc(cnt+1,sizeof(GTextInfo*));
+ for ( kc=head, cnt=0; kc!=NULL; kc=kc->next, ++cnt ) {
+ ti[cnt] = gcalloc(1,sizeof(GTextInfo));
+ ti[cnt]->fg = ti[cnt]->bg = COLOR_DEFAULT;
+ ti[cnt]->text = utf82u_copy(kc->subtable->subtable_name);
+ }
+ ti[cnt] = gcalloc(1,sizeof(GTextInfo));
+return( ti );
+}
+
+static GTextInfo *KCLookupSubtableList(SplineFont *sf,int isv) {
+ int cnt;
+ KernClass *kc, *head = isv ? sf->vkerns : sf->kerns;
+ GTextInfo *ti;
+
+ if ( sf->cidmaster!=NULL ) sf=sf->cidmaster;
+ else if ( sf->mm!=NULL ) sf = sf->mm->normal;
+
+ for ( kc=head, cnt=0; kc!=NULL; kc=kc->next, ++cnt );
+ ti = gcalloc(cnt+1,sizeof(GTextInfo));
+ for ( kc=head, cnt=0; kc!=NULL; kc=kc->next, ++cnt )
+ ti[cnt].text = utf82u_copy(kc->subtable->subtable_name);
+return( ti );
+}
+
+/* ************************************************************************** */
+/* **************************** Edit/Add a Class **************************** */
+/* ************************************************************************** */
+
+static int KCD_ToSelection(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ const unichar_t *ret = _GGadgetGetTitle(GWidgetGetControl(kcd->gw,CID_GlyphList));
+ SplineFont *sf = kcd->sf;
+ FontView *fv = sf->fv;
+ const unichar_t *end;
+ int pos, found=-1;
+ char *nm;
+
+ GDrawSetVisible(fv->gw,true);
+ GDrawRaise(fv->gw);
+ memset(fv->selected,0,fv->map->enccount);
+ while ( *ret ) {
+ end = u_strchr(ret,' ');
+ if ( end==NULL ) end = ret+u_strlen(ret);
+ nm = cu_copybetween(ret,end);
+ for ( ret = end; isspace(*ret); ++ret);
+ if (( pos = SFFindSlot(sf,fv->map,-1,nm))!=-1 ) {
+ if ( found==-1 ) found = pos;
+ fv->selected[pos] = true;
+ }
+ free(nm);
+ }
+
+ if ( found!=-1 )
+ FVScrollToChar(fv,found);
+ GDrawRequestExpose(fv->v,NULL,false);
+ }
+return( true );
+}
+
+static int KCD_FromSelection(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ SplineFont *sf = kcd->sf;
+ FontView *fv = sf->fv;
+ unichar_t *vals, *pt;
+ int i, len, max, gid;
+ SplineChar *sc;
+
+ for ( i=len=max=0; i<fv->map->enccount; ++i ) if ( fv->selected[i]) {
+ sc = SFMakeChar(sf,fv->map,i);
+ len += strlen(sc->name)+1;
+ if ( fv->selected[i]>max ) max = fv->selected[i];
+ }
+ pt = vals = galloc((len+1)*sizeof(unichar_t));
+ *pt = '\0';
+ /* in a class the order of selection is irrelevant */
+ for ( i=0; i<fv->map->enccount; ++i ) if ( fv->selected[i] && (gid=fv->map->map[i])!=-1) {
+ uc_strcpy(pt,sf->glyphs[gid]->name);
+ pt += u_strlen(pt);
+ *pt++ = ' ';
+ }
+ if ( pt>vals ) pt[-1]='\0';
+
+ GGadgetSetTitle(GWidgetGetControl(kcd->gw,CID_GlyphList),vals);
+ }
+return( true );
+}
+
+static int KCD_Prev(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ GDrawSetVisible(kcd->cw,false);
+ }
+return( true );
+}
+
+static int isEverythingElse(unichar_t *text) {
+ /* GT: The string "{Everything Else}" is used in the context of a list */
+ /* GT: of classes (a set of kerning classes) where class 0 designates the */
+ /* GT: default class containing all glyphs not specified in the other classes */
+ unichar_t *everything_else = utf82u_copy( _("{Everything Else}") );
+ int ret = u_strcmp(text,everything_else);
+ free(everything_else);
+return( ret==0 );
+}
+
+static int KCD_Next(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ char *ret = GGadgetGetTitle8(GWidgetGetControl(kcd->gw,CID_GlyphList));
+ GGadget *list = GWidgetGetControl( kcd->gw, CID_ClassList+kcd->off );
+ int i;
+ char *pt;
+ int which = GGadgetGetFirstListSelectedItem(list);
+
+ for ( pt=ret; *pt==' '; ++pt );
+
+ if ( which==0 && *pt=='\0' )
+ /* Class 0 may contain no glyphs */;
+ else if ( !CCD_NameListCheck(kcd->sf,ret,true,_("Bad Class")) ||
+ CCD_InvalidClassList(ret,list,kcd->isedit)) {
+ free(ret);
+return( true );
+ }
+
+ if ( kcd->isedit ) {
+ if ( which==0 && *pt=='\0' )
+ GListChangeLine8(list,0,_("{Everything Else}"));
+ else
+ GListChangeLine8(list,GGadgetGetFirstListSelectedItem(list),ret);
+ } else {
+ GListAppendLine8(list,ret,false);
+ if ( kcd->off==0 ) {
+ kcd->offsets = grealloc(kcd->offsets,(kcd->first_cnt+1)*kcd->second_cnt*sizeof(int16));
+ memset(kcd->offsets+kcd->first_cnt*kcd->second_cnt,
+ 0, kcd->second_cnt*sizeof(int16));
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ kcd->adjusts = grealloc(kcd->adjusts,(kcd->first_cnt+1)*kcd->second_cnt*sizeof(DeviceTable));
+ memset(kcd->adjusts+kcd->first_cnt*kcd->second_cnt,
+ 0, kcd->second_cnt*sizeof(DeviceTable));
+#endif
+ ++kcd->first_cnt;
+ } else {
+ int16 *new = galloc(kcd->first_cnt*(kcd->second_cnt+1)*sizeof(int16));
+ for ( i=0; i<kcd->first_cnt; ++i ) {
+ memcpy(new+i*(kcd->second_cnt+1),kcd->offsets+i*kcd->second_cnt,
+ kcd->second_cnt*sizeof(int16));
+ new[i*(kcd->second_cnt+1)+kcd->second_cnt] = 0;
+ }
+ free( kcd->offsets );
+ kcd->offsets = new;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ {
+ DeviceTable *new = galloc(kcd->first_cnt*(kcd->second_cnt+1)*sizeof(DeviceTable));
+ for ( i=0; i<kcd->first_cnt; ++i ) {
+ memcpy(new+i*(kcd->second_cnt+1),kcd->adjusts+i*kcd->second_cnt,
+ kcd->second_cnt*sizeof(DeviceTable));
+ memset(&new[i*(kcd->second_cnt+1)+kcd->second_cnt],0,sizeof(DeviceTable));
+ }
+ free( kcd->adjusts );
+ kcd->adjusts = new;
+ }
+#endif
+ ++kcd->second_cnt;
+ }
+ KCD_SBReset(kcd);
+ }
+ GDrawSetVisible(kcd->cw,false); /* This will give us an expose so we needed ask for one */
+ free(ret);
+ }
+return( true );
+}
+
+static void _KCD_DoEditNew(KernClassDlg *kcd,int isedit,int off) {
+ static unichar_t nullstr[] = { 0 };
+
+ kcd->isedit = isedit;
+ kcd->off = off;
+ if ( isedit ) {
+ GGadget *list = GWidgetGetControl( kcd->gw, CID_ClassList+off);
+ GTextInfo *selected = GGadgetGetListItemSelected(list);
+ int which = GGadgetGetFirstListSelectedItem(list);
+ if ( selected==NULL )
+return;
+ if ( off==0 && which==0 && isEverythingElse(selected->text))
+ GGadgetSetTitle(GWidgetGetControl(kcd->cw,CID_GlyphList),nullstr);
+ else
+ GGadgetSetTitle(GWidgetGetControl(kcd->cw,CID_GlyphList),selected->text);
+ } else {
+ GGadgetSetTitle(GWidgetGetControl(kcd->cw,CID_GlyphList),nullstr);
+ }
+ GWidgetIndicateFocusGadget(GWidgetGetControl(kcd->cw,CID_GlyphList));
+ GDrawSetVisible(kcd->cw,true);
+}
+
+/* ************************************************************************** */
+/* ************************** Kern Class Display **************************** */
+/* ************************************************************************** */
+
+static void KPD_DoCancel(KernClassDlg *kcd) {
+ BDFCharFree(kcd->fsc); BDFCharFree(kcd->ssc);
+ kcd->fsc = kcd->ssc = NULL;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ free(kcd->active_adjust.corrections); kcd->active_adjust.corrections = NULL;
+#endif
+ kcd->done = true;
+}
+
+static int KPD_Cancel(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ KPD_DoCancel(kcd);
+ }
+return( true );
+}
+
+static int KPD_FinishKP(KernClassDlg *);
+
+static int KPD_OK(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ if ( !KPD_FinishKP(kcd))
+return( true );
+ BDFCharFree(kcd->fsc); BDFCharFree(kcd->ssc);
+ kcd->fsc = kcd->ssc = NULL;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ free(kcd->active_adjust.corrections); kcd->active_adjust.corrections = NULL;
+#endif
+ kcd->done = true;
+ }
+return( true );
+}
+
+static int KCD_Prev2(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ BDFCharFree(kcd->fsc); BDFCharFree(kcd->ssc);
+ kcd->fsc = kcd->ssc = NULL;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ free(kcd->active_adjust.corrections); kcd->active_adjust.corrections = NULL;
+#endif
+ GDrawSetVisible(kcd->kw,false);
+ }
+return( true );
+}
+
+static int KCD_Next2(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ const unichar_t *ret = _GGadgetGetTitle(GWidgetGetControl(kcd->gw,CID_KernOffset));
+ unichar_t *end;
+ int val = u_strtol(ret,&end,10);
+
+ if ( val<-32768 || val>32767 || *end!='\0' ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ gwwv_post_error( _("Bad Number"), _("Bad Number") );
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error( _("Bad Number"), _("Bad Number") );
+#endif
+return( true );
+ }
+ kcd->offsets[kcd->st_pos] = val;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ free(kcd->adjusts[kcd->st_pos].corrections);
+ kcd->adjusts[kcd->st_pos] = kcd->active_adjust;
+ kcd->active_adjust.corrections = NULL;
+#endif
+
+ BDFCharFree(kcd->fsc); BDFCharFree(kcd->ssc);
+ kcd->fsc = kcd->ssc = NULL;
+ GDrawSetVisible(kcd->kw,false); /* This will give us an expose so we needed ask for one */
+ }
+return( true );
+}
+
+void KCD_DrawGlyph(GWindow pixmap,int x,int baseline,BDFChar *bdfc,int mag) {
+ struct _GImage base;
+ GImage gi;
+ GClut clut;
+
+ memset(&gi,'\0',sizeof(gi));
+ memset(&base,'\0',sizeof(base));
+ memset(&clut,'\0',sizeof(clut));
+ gi.u.image = &base;
+ base.clut = &clut;
+ if ( !bdfc->byte_data ) {
+ base.image_type = it_mono;
+ clut.clut_len = 2;
+ clut.clut[0] = GDrawGetDefaultBackground(NULL);
+ clut.clut[1] = 0x000000;
+ } else {
+ int scale, l;
+ Color fg, bg;
+ scale = bdfc->depth == 8 ? 8 : 4;
+ base.image_type = it_index;
+ clut.clut_len = 1<<scale;
+ bg = GDrawGetDefaultBackground(NULL);
+ fg = GDrawGetDefaultForeground(NULL);
+ for ( l=0; l<(1<<scale); ++l )
+ clut.clut[l] =
+ COLOR_CREATE(
+ COLOR_RED(bg) + (l*(COLOR_RED(fg)-COLOR_RED(bg)))/((1<<scale)-1),
+ COLOR_GREEN(bg) + (l*(COLOR_GREEN(fg)-COLOR_GREEN(bg)))/((1<<scale)-1),
+ COLOR_BLUE(bg) + (l*(COLOR_BLUE(fg)-COLOR_BLUE(bg)))/((1<<scale)-1) );
+ }
+ base.data = bdfc->bitmap;
+ base.bytes_per_line = bdfc->bytes_per_line;
+ base.width = bdfc->xmax-bdfc->xmin+1;
+ base.height = bdfc->ymax-bdfc->ymin+1;
+ x += mag*bdfc->xmin;
+ if ( mag==1 )
+ GDrawDrawImage(pixmap,&gi,NULL,x,baseline-bdfc->ymax);
+ else
+ GDrawDrawImageMagnified(pixmap, &gi, NULL,
+ x,baseline-mag*bdfc->ymax,
+ base.width*mag,base.height*mag);
+}
+
+static int KCD_RightToLeft(KernClassDlg *kcd) {
+ if ( kcd->subtable!=NULL )
+return( kcd->subtable->lookup->lookup_flags&pst_r2l );
+
+ if ( kcd->scf!=NULL ) {
+ uint32 script = SCScriptFromUnicode(kcd->scf);
+ if ( script!=DEFAULT_SCRIPT )
+return( ScriptIsRightToLeft( script ));
+ }
+ if ( kcd->scs!=NULL ) {
+ uint32 script = SCScriptFromUnicode(kcd->scs);
+ if ( script!=DEFAULT_SCRIPT )
+return( ScriptIsRightToLeft( script ));
+ }
+return( false );
+}
+
+static void KCD_KernMouse(KernClassDlg *kcd,GEvent *event) {
+ int x, y, width;
+ char buf[20];
+ unichar_t ubuf[20];
+ int kern, pkern;
+ double scale;
+
+ scale = kcd->pixelsize/(double) (kcd->sf->ascent+kcd->sf->descent);
+ kern = u_strtol(_GGadgetGetTitle(GWidgetGetControl(kcd->kw,CID_KernOffset)),NULL,10);
+ pkern = kcd->magfactor*rint( kern*scale ); /* rounding can't include magnification */
+
+ if ( !kcd->isv ) {
+ /* Horizontal */
+ width = kcd->magfactor*((kcd->fsc!=NULL?kcd->fsc->width:0)+(kcd->ssc!=NULL?kcd->ssc->width:0))+pkern;
+ x = (kcd->fullwidth - width)/2;
+
+ if ( KCD_RightToLeft(kcd) ) {
+ if ( kcd->ssc!=NULL )
+ width -= kcd->magfactor*kcd->ssc->width;
+ } else {
+ if ( kcd->fsc!=NULL ) {
+ x += kcd->magfactor*kcd->fsc->width + pkern;
+ width -= kcd->magfactor*kcd->fsc->width + pkern;
+ }
+ }
+
+ if ( event->u.mouse.y<kcd->top || event->u.mouse.y>kcd->top+2*kcd->pixelsize*kcd->magfactor ||
+ event->u.mouse.x<x || event->u.mouse.x>x+width ) {
+ if ( event->type == et_mousedown )
+return;
+ if ( kcd->within ) {
+ GDrawSetCursor(kcd->kw,ct_pointer);
+ if ( kcd->down && kcd->orig_kern!=kern ) {
+ sprintf(buf, "%d", kcd->orig_kern);
+ uc_strcpy(ubuf,buf);
+ GGadgetSetTitle(GWidgetGetControl(kcd->kw,CID_KernOffset),ubuf);
+ GDrawRequestExpose(kcd->kw,NULL,false);
+ }
+ kcd->within = false;
+ }
+ if ( event->type==et_mouseup )
+ kcd->down = false;
+return;
+ }
+
+ if ( !kcd->within ) {
+ GDrawSetCursor(kcd->kw,ct_leftright);
+ kcd->within = true;
+ }
+ if ( event->type == et_mousedown ) {
+ kcd->orig_kern = kern;
+ kcd->down = true;
+ kcd->downpos = event->u.mouse.x;
+ } else if ( kcd->down ) {
+ /* I multiply by 2 here because I center the glyphs, so the kerning */
+ /* changes in both directions */
+ int nkern = kcd->orig_kern + rint(2*(event->u.mouse.x-kcd->downpos)/scale/kcd->magfactor);
+ if ( kern!=nkern ) {
+ sprintf(buf, "%d", nkern);
+ uc_strcpy(ubuf,buf);
+ GGadgetSetTitle(GWidgetGetControl(kcd->kw,CID_KernOffset),ubuf);
+ GDrawRequestExpose(kcd->kw,NULL,false);
+ }
+ if ( event->type==et_mouseup ) {
+ kcd->down = false;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( nkern!=kcd->orig_kern && kcd->active_adjust.corrections!=NULL ) {
+ free(kcd->active_adjust.corrections);
+ kcd->active_adjust.corrections = NULL;
+ ubuf[0] = '0'; ubuf[1] = '\0';
+ GGadgetSetTitle(GWidgetGetControl(kcd->kw,CID_Correction),ubuf);
+ GDrawRequestExpose(kcd->kw,NULL,false);
+ }
+#endif
+ }
+ }
+ } else {
+ /* Vertical */
+ y = kcd->top + kcd->pixelsize/3;
+ width = (kcd->ssc!=NULL ? kcd->magfactor*rint(kcd->ssc->sc->vwidth * scale) : 0);
+ if ( kcd->fsc!=NULL )
+ y += kcd->magfactor*rint(kcd->fsc->sc->vwidth * scale) + pkern;
+ x = (kcd->fullwidth/2 - kcd->pixelsize/2)*kcd->magfactor;
+
+ if ( event->u.mouse.y<y || event->u.mouse.y>y+width ||
+ event->u.mouse.x<x || event->u.mouse.x>x+kcd->pixelsize ) {
+ if ( event->type == et_mousedown )
+return;
+ if ( kcd->within ) {
+ GDrawSetCursor(kcd->kw,ct_pointer);
+ if ( kcd->down && kcd->orig_kern!=kern ) {
+ sprintf(buf, "%d", kcd->orig_kern);
+ uc_strcpy(ubuf,buf);
+ GGadgetSetTitle(GWidgetGetControl(kcd->kw,CID_KernOffset),ubuf);
+ GDrawRequestExpose(kcd->kw,NULL,false);
+ }
+ kcd->within = false;
+ }
+ if ( event->type==et_mouseup )
+ kcd->down = false;
+return;
+ }
+
+ if ( !kcd->within ) {
+ GDrawSetCursor(kcd->kw,ct_updown);
+ kcd->within = true;
+ }
+ if ( event->type == et_mousedown ) {
+ kcd->orig_kern = kern;
+ kcd->down = true;
+ kcd->downpos = event->u.mouse.y;
+ } else if ( kcd->down ) {
+ int nkern = kcd->orig_kern + rint((event->u.mouse.y-kcd->downpos)/scale)/kcd->magfactor;
+ if ( kern!=nkern ) {
+ sprintf(buf, "%d", nkern);
+ uc_strcpy(ubuf,buf);
+ GGadgetSetTitle(GWidgetGetControl(kcd->kw,CID_KernOffset),ubuf);
+ GDrawRequestExpose(kcd->kw,NULL,false);
+ }
+ if ( event->type==et_mouseup ) {
+ kcd->down = false;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( nkern!=kcd->orig_kern && kcd->active_adjust.corrections!=NULL ) {
+ free(kcd->active_adjust.corrections);
+ kcd->active_adjust.corrections = NULL;
+ ubuf[0] = '0'; ubuf[1] = '\0';
+ GGadgetSetTitle(GWidgetGetControl(kcd->kw,CID_Correction),ubuf);
+ GDrawRequestExpose(kcd->kw,NULL,false);
+ }
+#endif
+ }
+ }
+ }
+}
+
+static void KCD_KernExpose(KernClassDlg *kcd,GWindow pixmap,GEvent *event) {
+ GRect *area = &event->u.expose.rect;
+ GRect rect;
+ GRect old1;
+ int x, y;
+ SplineFont *sf = kcd->sf;
+ int em = sf->ascent+sf->descent;
+ int as = kcd->magfactor*rint(sf->ascent*kcd->pixelsize/(double) em);
+ const unichar_t *ret = _GGadgetGetTitle(GWidgetGetControl(kcd->gw,CID_KernOffset));
+ int kern = u_strtol(ret,NULL,10);
+ int baseline, xbaseline;
+
+ if ( area->y+area->height<kcd->top )
+return;
+ if ( area->y>kcd->top+3*kcd->pixelsize ||
+ (!kcd->isv && area->y>kcd->top+2*kcd->pixelsize ))
+return;
+
+ rect.x = 0; rect.y = kcd->top;
+ rect.width = kcd->fullwidth;
+ rect.height = kcd->isv ? 3*kcd->pixelsize*kcd->magfactor : 2*kcd->pixelsize*kcd->magfactor;
+ GDrawPushClip(pixmap,&rect,&old1);
+
+ kern = kcd->magfactor*rint(kern*kcd->pixelsize/(double) em);
+
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ { int correction;
+ unichar_t *end;
+
+ ret = _GGadgetGetTitle(GWidgetGetControl(kcd->gw,CID_Correction));
+ correction = u_strtol(ret,&end,10);
+ while ( *end==' ' ) ++end;
+ if ( *end=='\0' && correction>=-128 && correction<=127 )
+ kern += correction*kcd->magfactor;
+ }
+#endif
+
+ if ( !kcd->isv ) {
+ x = (kcd->fullwidth-( kcd->magfactor*(kcd->fsc!=NULL?kcd->fsc->width:0)+
+ kcd->magfactor*(kcd->ssc!=NULL?kcd->ssc->width:0)+
+ kern))/2;
+ baseline = kcd->top + as + kcd->magfactor*kcd->pixelsize/2;
+ if ( KCD_RightToLeft(kcd) ) {
+ if ( kcd->ssc!=NULL ) {
+ KCD_DrawGlyph(pixmap,x,baseline,kcd->ssc,kcd->magfactor);
+ x += kcd->magfactor*kcd->ssc->width + kern;
+ }
+ if ( kcd->fsc!=NULL )
+ KCD_DrawGlyph(pixmap,x,baseline,kcd->fsc,kcd->magfactor);
+ } else {
+ if ( kcd->fsc!=NULL ) {
+ KCD_DrawGlyph(pixmap,x,baseline,kcd->fsc,kcd->magfactor);
+ x += kcd->fsc->width*kcd->magfactor + kern;
+ }
+ if ( kcd->ssc!=NULL )
+ KCD_DrawGlyph(pixmap,x,baseline,kcd->ssc,kcd->magfactor);
+ }
+ } else {
+ /* I don't support top to bottom vertical */
+ y = kcd->top + kcd->magfactor*kcd->pixelsize/3 + as;
+ xbaseline = kcd->fullwidth/2;
+ if ( kcd->fsc!=NULL ) {
+ KCD_DrawGlyph(pixmap,xbaseline-kcd->magfactor*kcd->pixelsize/2,y,kcd->fsc,kcd->magfactor);
+ y += kcd->magfactor*rint(kcd->fsc->sc->vwidth * kcd->pixelsize/(double) em) + kern;
+ }
+ if ( kcd->ssc!=NULL )
+ KCD_DrawGlyph(pixmap,xbaseline-kcd->magfactor*kcd->pixelsize/2,y,kcd->ssc,kcd->magfactor);
+ }
+ GDrawPopClip(pixmap,&old1);
+}
+
+static int KCD_KernOffChanged(GGadget *g, GEvent *e) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged )
+ GDrawRequestExpose(kcd->kw,NULL,false);
+return( true );
+}
+
+static void KCD_UpdateGlyph(KernClassDlg *kcd,int which) {
+ BDFChar **scpos = which==0 ? &kcd->fsc : &kcd->ssc;
+ SplineChar **possc = which==0 ? &kcd->scf : &kcd->scs;
+ SplineChar *sc;
+ char *temp;
+ void *freetypecontext=NULL;
+
+ BDFCharFree(*scpos);
+ *scpos = NULL;
+ if ( kcd->iskernpair ) {
+ temp = cu_copy(_GGadgetGetTitle(GWidgetGetControl(kcd->kw,
+ which==0 ? CID_First : CID_Second )));
+ } else {
+ GTextInfo *sel = GGadgetGetListItemSelected(GWidgetGetControl(kcd->kw,
+ which==0 ? CID_First : CID_Second ));
+ if ( sel==NULL )
+return;
+ temp = cu_copy(sel->text);
+ }
+
+ *possc = sc = SFGetChar(kcd->sf,-1,temp);
+ free(temp);
+ if ( sc==NULL )
+return;
+ if ( GGadgetIsChecked(GWidgetGetControl(kcd->gw,CID_FreeType)) )
+ freetypecontext = FreeTypeFontContext(sc->parent,sc,sc->parent->fv);
+ if ( freetypecontext ) {
+ *scpos = SplineCharFreeTypeRasterize(freetypecontext,sc->orig_pos,kcd->pixelsize,8);
+ FreeTypeFreeContext(freetypecontext);
+ } else
+ *scpos = SplineCharAntiAlias(sc,kcd->pixelsize,4);
+}
+
+static int KCD_DisplaySizeChanged(GGadget *g, GEvent *e) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
+ const unichar_t *ret = _GGadgetGetTitle(GWidgetGetControl(kcd->gw,CID_DisplaySize));
+ unichar_t *end;
+ int pixelsize = u_strtol(ret,&end,10);
+
+ while ( *end==' ' ) ++end;
+ if ( pixelsize>4 && pixelsize<400 && *end=='\0' ) {
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ unichar_t ubuf[20]; char buffer[20];
+ ubuf[0] = '0'; ubuf[1] = '\0';
+ if ( kcd->active_adjust.corrections!=NULL &&
+ pixelsize>=kcd->active_adjust.first_pixel_size &&
+ pixelsize<=kcd->active_adjust.last_pixel_size ) {
+ sprintf( buffer, "%d", kcd->active_adjust.corrections[
+ pixelsize-kcd->active_adjust.first_pixel_size]);
+ uc_strcpy(ubuf,buffer);
+ }
+ GGadgetSetTitle(GWidgetGetControl(kcd->gw,CID_Correction),ubuf);
+#endif
+ kcd->pixelsize = pixelsize;
+ KCD_UpdateGlyph(kcd,0);
+ KCD_UpdateGlyph(kcd,1);
+ GDrawRequestExpose(kcd->kw,NULL,false);
+ }
+ }
+return( true );
+}
+
+static int KCD_MagnificationChanged(GGadget *g, GEvent *e) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ int mag = GGadgetGetFirstListSelectedItem(GWidgetGetControl(kcd->gw,CID_Magnifications));
+
+ if ( mag!=-1 && mag!=kcd->magfactor-1 ) {
+ kcd->magfactor = mag+1;
+ GDrawRequestExpose(kcd->kw,NULL,false);
+ }
+ }
+return( true );
+}
+
+static int KCB_FreeTypeChanged(GGadget *g, GEvent *e) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
+ KCD_UpdateGlyph(kcd,0);
+ KCD_UpdateGlyph(kcd,1);
+ GDrawRequestExpose(kcd->kw,NULL,false);
+ }
+return( true );
+}
+
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+static int KCD_CorrectionChanged(GGadget *g, GEvent *e) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
+ const unichar_t *ret = _GGadgetGetTitle(GWidgetGetControl(kcd->gw,CID_Correction));
+ unichar_t *end;
+ int correction = u_strtol(ret,&end,10);
+
+ while ( *end==' ' ) ++end;
+ if ( *end!='\0' )
+return( true );
+ if ( correction<-128 || correction>127 ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ gwwv_post_error(_("Value out of range"),_("Value out of range"));
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error( _("Out of Range"), _("Corrections must be between -128 and 127 (and should be smaller)") );
+#endif
+return( true );
+ }
+
+ DeviceTableSet(&kcd->active_adjust,kcd->pixelsize,correction);
+ GDrawRequestExpose(kcd->kw,NULL,false);
+ }
+return( true );
+}
+#endif
+
+static void KPD_RestoreGlyphs(KernClassDlg *kcd) {
+ if ( kcd->scf!=NULL )
+ GGadgetSetTitle8(GWidgetGetControl(kcd->gw,CID_First),kcd->scf->name);
+ if ( kcd->scs!=NULL )
+ GGadgetSetTitle8(GWidgetGetControl(kcd->gw,CID_Second),kcd->scs->name);
+}
+
+static int KPD_FinishKP(KernClassDlg *kcd) {
+ KernPair *kp;
+ const unichar_t *ret = _GGadgetGetTitle(GWidgetGetControl(kcd->gw,CID_KernOffset));
+ int offset = u_strtol(ret,NULL,10);
+
+ if ( kcd->scf!=NULL && kcd->scs!=NULL ) {
+ for ( kp = kcd->isv?kcd->scf->vkerns:kcd->scf->kerns; kp!=NULL && kp->sc!=kcd->scs; kp=kp->next );
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( kp==NULL && offset==0 && kcd->active_adjust.corrections==NULL )
+return(true);
+#else
+ if ( kp==NULL && offset==0 )
+return(true);
+#endif
+ if ( kcd->subtable==NULL ) {
+ gwwv_post_error(_("No lookup selected"),_("You must select a lookup subtable to contain this kerning pair" ));
+return(false);
+ }
+ if ( kp==NULL ) {
+ kp = chunkalloc(sizeof(KernPair));
+ kp->next = kcd->isv?kcd->scf->vkerns:kcd->scf->kerns;
+ kp->sc = kcd->scs;
+ if ( kcd->isv )
+ kcd->scf->vkerns = kp;
+ else
+ kcd->scf->kerns = kp;
+ }
+ kp->subtable = kcd->subtable;
+ kp->off = offset;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( kp->adjust!=NULL && kcd->active_adjust.corrections!=NULL ) {
+ free(kp->adjust->corrections);
+ *kp->adjust = kcd->active_adjust;
+ } else if ( kcd->active_adjust.corrections!=NULL ) {
+ kp->adjust = chunkalloc(sizeof(DeviceTable));
+ *kp->adjust = kcd->active_adjust;
+ } else if ( kp->adjust!=NULL ) {
+ DeviceTableFree(kp->adjust);
+ kp->adjust = NULL;
+ }
+ memset(&kcd->active_adjust,0,sizeof(DeviceTable));
+#endif
+ }
+return( true );
+}
+
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+static void KCD_SetDevTab(KernClassDlg *kcd) {
+ unichar_t ubuf[20];
+
+ ubuf[0] = '0'; ubuf[1] = '\0';
+ GGadgetClearList(GWidgetGetControl(kcd->gw,CID_DisplaySize));
+ if ( kcd->active_adjust.corrections!=NULL ) {
+ int i;
+ int len = kcd->active_adjust.last_pixel_size - kcd->active_adjust.first_pixel_size +1;
+ char buffer[20];
+ GTextInfo **ti = galloc((len+1)*sizeof(GTextInfo *));
+ for ( i=0; i<len; ++i ) {
+ ti[i] = gcalloc(1,sizeof(GTextInfo));
+ sprintf( buffer, "%d", i+kcd->active_adjust.first_pixel_size);
+ ti[i]->text = uc_copy(buffer);
+ ti[i]->fg = ti[i]->bg = COLOR_DEFAULT;
+ }
+ ti[i] = gcalloc(1,sizeof(GTextInfo));
+ GGadgetSetList(GWidgetGetControl(kcd->gw,CID_DisplaySize),ti,false);
+ if ( kcd->pixelsize>=kcd->active_adjust.first_pixel_size &&
+ kcd->pixelsize<=kcd->active_adjust.last_pixel_size ) {
+ sprintf( buffer, "%d", kcd->active_adjust.corrections[
+ kcd->pixelsize-kcd->active_adjust.first_pixel_size]);
+ uc_strcpy(ubuf,buffer);
+ }
+ }
+ GGadgetSetTitle(GWidgetGetControl(kcd->gw,CID_Correction),ubuf);
+}
+#endif
+
+static void KP_SelectSubtable(KernClassDlg *kcd,struct lookup_subtable *sub) {
+ int32 len;
+ GTextInfo **ti = GGadgetGetList(GWidgetGetControl(kcd->gw,CID_Subtable),&len);
+ int i, new_pos = -1;
+
+ for ( i=0; i<len; ++i ) if ( !ti[i]->line ) {
+ if ( ti[i]->userdata == sub )
+ break;
+ else if ( ti[i]->userdata == NULL )
+ new_pos = i;
+ }
+ if ( i==len )
+ i = new_pos;
+ if ( i!=-1 )
+ GGadgetSelectOneListItem(GWidgetGetControl(kcd->gw,CID_Subtable),i);
+ if ( sub!=NULL )
+ kcd->subtable = sub;
+}
+
+static int KP_Subtable(GGadget *g, GEvent *e) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ GTextInfo *ti;
+ struct lookup_subtable *sub;
+ struct subtable_data sd;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ ti = GGadgetGetListItemSelected(g);
+ if ( ti!=NULL ) {
+ if ( ti->userdata!=NULL )
+ kcd->subtable = ti->userdata;
+ else {
+ memset(&sd,0,sizeof(sd));
+ sd.flags = (kcd->isv ? sdf_verticalkern : sdf_horizontalkern ) |
+ sdf_kernpair;
+ sub = SFNewLookupSubtableOfType(kcd->sf,gpos_pair,&sd);
+ if ( sub!=NULL ) {
+ kcd->subtable = sub;
+ GGadgetSetList(g,SFSubtablesOfType(kcd->sf,gpos_pair,false),false);
+ }
+ KP_SelectSubtable(kcd,kcd->subtable);
+ }
+ }
+ }
+return( true );
+}
+
+static void KPD_PairSearch(KernClassDlg *kcd) {
+ int offset = 0;
+ KernPair *kp=NULL;
+ char buf[20];
+ unichar_t ubuf[20];
+
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ free(kcd->active_adjust.corrections); kcd->active_adjust.corrections = NULL;
+#endif
+ if ( kcd->scf!=NULL && kcd->scs!=NULL ) {
+ for ( kp = kcd->isv?kcd->scf->vkerns:kcd->scf->kerns; kp!=NULL && kp->sc!=kcd->scs; kp=kp->next );
+ if ( kp!=NULL ) {
+ offset = kp->off;
+ KP_SelectSubtable(kcd,kp->subtable);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( kp->adjust!=NULL ) {
+ int len = kp->adjust->last_pixel_size-kp->adjust->first_pixel_size+1;
+ kcd->active_adjust = *kp->adjust;
+ kcd->active_adjust.corrections = galloc(len);
+ memcpy(kcd->active_adjust.corrections,kp->adjust->corrections,len);
+ }
+#endif
+ }
+ }
+ if ( kp==NULL && kcd->scf!=NULL ) {
+ int32 len;
+ GTextInfo **ti = GGadgetGetList(GWidgetGetControl(kcd->gw,CID_Subtable),&len);
+ uint32 script = SCScriptFromUnicode(kcd->scf);
+ int i;
+ struct lookup_subtable *sub = NULL;
+
+ for ( i=0; i<len; ++i ) {
+ struct lookup_subtable *test = ti[i]->userdata;
+ if ( test!=NULL && ScriptInFeatureScriptList(script,test->lookup->features)) {
+ sub = test;
+ break;
+ }
+ }
+ KP_SelectSubtable(kcd,sub);
+ }
+
+ sprintf(buf, "%d", offset);
+ uc_strcpy(ubuf,buf);
+ GGadgetSetTitle(GWidgetGetControl(kcd->kw,CID_KernOffset),ubuf);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ KCD_SetDevTab(kcd);
+#endif
+}
+
+static void KPD_BuildKernList(KernClassDlg *kcd) {
+ int len;
+ KernPair *kp;
+ GTextInfo **ti;
+
+ len = 0;
+ if ( kcd->scf!=NULL )
+ for ( kp=kcd->isv?kcd->scf->vkerns:kcd->scf->kerns, len=0; kp!=NULL; kp=kp->next )
+ ++len;
+ ti = gcalloc(len+1,sizeof(GTextInfo*));
+ if ( kcd->scf!=NULL )
+ for ( kp=kcd->isv?kcd->scf->vkerns:kcd->scf->kerns, len=0; kp!=NULL; kp=kp->next, ++len ) {
+ ti[len] = gcalloc(1,sizeof(GTextInfo));
+ ti[len]->fg = ti[len]->bg = COLOR_DEFAULT;
+ ti[len]->text = uc_copy(kp->sc->name);
+ }
+ ti[len] = gcalloc(1,sizeof(GTextInfo));
+ GGadgetSetList(GWidgetGetControl(kcd->gw,CID_Second),ti,false);
+}
+
+static int KCD_GlyphSelected(GGadget *g, GEvent *e) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ int which = GGadgetGetCid(g)==CID_Second;
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ KCD_UpdateGlyph(kcd,which);
+ GDrawRequestExpose(kcd->kw,NULL,false);
+ } else if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
+ if ( !KPD_FinishKP(kcd)) {
+ KPD_RestoreGlyphs(kcd);
+return( true );
+ }
+ KCD_UpdateGlyph(kcd,which);
+ if ( which==0 )
+ KPD_BuildKernList(kcd);
+ KPD_PairSearch(kcd);
+ GDrawRequestExpose(kcd->kw,NULL,false);
+ }
+return( true );
+}
+
+static GTextInfo **TiNamesFromClass(GGadget *list,int class_index) {
+ /* Return a list containing all the names in this class */
+ unichar_t *upt, *end;
+ unichar_t *line;
+ GTextInfo *classti;
+ GTextInfo **ti;
+ int i, k;
+
+ classti = GGadgetGetListItem(list,class_index);
+ if ( classti==NULL || uc_strcmp(classti->text,_("{Everything Else}"))==0 ) {
+ i=0;
+ ti = galloc((i+1)*sizeof(GTextInfo*));
+ } else {
+ line = GGadgetGetListItem(list,class_index)->text;
+ for ( k=0 ; k<2; ++k ) {
+ for ( i=0, upt=line; *upt; ) {
+ while ( *upt==' ' ) ++upt;
+ if ( *upt=='\0' )
+ break;
+ for ( end = upt; *end!='\0' && *end!=' '; ++end );
+ if ( k==1 ) {
+ ti[i] = gcalloc(1,sizeof(GTextInfo));
+ ti[i]->text = u_copyn(upt,end-upt);
+ ti[i]->bg = ti[i]->fg = COLOR_DEFAULT;
+ }
+ ++i;
+ upt = end;
+ }
+ if ( k==0 )
+ ti = galloc((i+1)*sizeof(GTextInfo*));
+ }
+ }
+ if ( i>0 )
+ ti[0]->selected = true;
+ ti[i] = gcalloc(1,sizeof(GTextInfo));
+return( ti );
+}
+
+static void KCD_EditOffset(KernClassDlg *kcd) {
+ int first = kcd->st_pos/kcd->second_cnt, second = kcd->st_pos%kcd->second_cnt;
+ char buf[12];
+ unichar_t ubuf[12];
+ GTextInfo **ti;
+ static unichar_t nullstr[] = { 0 };
+
+ if ( second==0 )
+ ff_post_notice(_("Class 0"),_("The kerning values for class 0 (\"Everything Else\") should always be 0"));
+ GGadgetSetList(GWidgetGetControl(kcd->kw,CID_First),
+ ti = TiNamesFromClass(GWidgetGetControl(kcd->gw,CID_ClassList),first),false);
+ GGadgetSetTitle(GWidgetGetControl(kcd->kw,CID_First),
+ ti==NULL || ti[0]->text==NULL ? nullstr: ti[0]->text);
+ GGadgetSetList(GWidgetGetControl(kcd->kw,CID_Second),
+ ti = TiNamesFromClass(GWidgetGetControl(kcd->gw,CID_ClassList+100),second),false);
+ GGadgetSetTitle(GWidgetGetControl(kcd->kw,CID_Second),
+ ti==NULL || ti[0]->text==NULL ? nullstr: ti[0]->text);
+ KCD_UpdateGlyph(kcd,0);
+ KCD_UpdateGlyph(kcd,1);
+
+ sprintf( buf, "%d", kcd->offsets[kcd->st_pos]);
+ uc_strcpy(ubuf,buf);
+ GGadgetSetTitle(GWidgetGetControl(kcd->gw,CID_KernOffset),ubuf);
+
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ kcd->active_adjust = kcd->adjusts[kcd->st_pos];
+ if ( kcd->active_adjust.corrections!=NULL ) {
+ int len = kcd->active_adjust.last_pixel_size - kcd->active_adjust.first_pixel_size +1;
+ kcd->active_adjust.corrections = galloc(len);
+ memcpy(kcd->active_adjust.corrections,kcd->adjusts[kcd->st_pos].corrections,len);
+ }
+ KCD_SetDevTab(kcd);
+#endif
+
+ GDrawSetVisible(kcd->kw,true);
+}
+
+/* ************************************************************************** */
+/* *************************** Kern Class Dialog **************************** */
+/* ************************************************************************** */
+
+static int KC_OK(GGadget *g, GEvent *e) {
+ SplineFont *sf;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ KernClass *kc;
+ int i;
+ int32 len;
+ GTextInfo **ti;
+
+ sf = kcd->sf;
+ if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
+ else if ( sf->mm!=NULL ) sf = sf->mm->normal;
+
+ if ( GDrawIsVisible(kcd->cw))
+return( KCD_Next(g,e));
+ else if ( GDrawIsVisible(kcd->kw))
+return( KCD_Next2(g,e));
+
+ kc = kcd->orig;
+ for ( i=1; i<kc->first_cnt; ++i )
+ free( kc->firsts[i]);
+ for ( i=1; i<kc->second_cnt; ++i )
+ free( kc->seconds[i]);
+ free(kc->firsts);
+ free(kc->seconds);
+ free(kc->offsets);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ free(kc->adjusts);
+#endif
+ kc->first_cnt = kcd->first_cnt;
+ kc->second_cnt = kcd->second_cnt;
+ kc->firsts = galloc(kc->first_cnt*sizeof(char *));
+ kc->seconds = galloc(kc->second_cnt*sizeof(char *));
+ kc->firsts[0] = kc->seconds[0] = NULL;
+ ti = GGadgetGetList(GWidgetGetControl(kcd->gw,CID_ClassList),&len);
+ if ( uc_strcmp(ti[0]->text,_("{Everything Else}"))!=0 )
+ kc->firsts[0] = cu_copy(ti[0]->text);
+ for ( i=1; i<kc->first_cnt; ++i )
+ kc->firsts[i] = cu_copy(ti[i]->text);
+ ti = GGadgetGetList(GWidgetGetControl(kcd->gw,CID_ClassList+100),&len);
+ for ( i=1; i<kc->second_cnt; ++i )
+ kc->seconds[i] = cu_copy(ti[i]->text);
+ kc->offsets = kcd->offsets;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ kc->adjusts = kcd->adjusts;
+#endif
+ kcd->sf->changed = true;
+ sf->changed = true;
+
+ GDrawDestroyWindow(kcd->gw);
+ }
+return( true );
+}
+
+static void KC_DoCancel(KernClassDlg *kcd) {
+ if ( kcd->iskernpair )
+ KPD_DoCancel(kcd);
+ else {
+ free(kcd->offsets);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ { int i;
+ for ( i=0; i<kcd->first_cnt*kcd->second_cnt; ++i )
+ free(kcd->adjusts[i].corrections);
+ }
+ free(kcd->adjusts);
+#endif
+ GDrawDestroyWindow(kcd->gw);
+ }
+}
+
+static int KC_Cancel(GGadget *g, GEvent *e) {
+ KernClassDlg *kcd;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ if ( GDrawIsVisible(kcd->cw))
+return( KCD_Prev(g,e));
+ else if ( GDrawIsVisible(kcd->kw))
+return( KCD_Prev2(g,e));
+
+ KC_DoCancel(kcd);
+ }
+return( true );
+}
+
+static void _KCD_EnableButtons(KernClassDlg *kcd,int off) {
+ GGadget *list = GWidgetGetControl(kcd->gw,CID_ClassList+off);
+ int32 i, len, j;
+ GTextInfo **ti;
+
+ ti = GGadgetGetList(list,&len);
+ i = GGadgetGetFirstListSelectedItem(list);
+ GGadgetSetEnabled(GWidgetGetControl(kcd->gw,CID_ClassDel+off),i>=1);
+ for ( j=len-1; j>i; --j )
+ if ( ti[j]->selected )
+ break;
+ GGadgetSetEnabled(GWidgetGetControl(kcd->gw,CID_ClassEdit+off),(i>=1 || off==0) && j==i);
+ GGadgetSetEnabled(GWidgetGetControl(kcd->gw,CID_ClassUp+off),i>=2);
+ GGadgetSetEnabled(GWidgetGetControl(kcd->gw,CID_ClassDown+off),i>=1 && j<len-1);
+}
+
+static void OffsetMoveClasses(KernClassDlg *kcd, int dir, GTextInfo **movethese, int off ) {
+ int16 *new;
+ int i,j,k;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ DeviceTable *newd;
+#endif
+
+ movethese[0]->selected = false;
+
+ new = galloc(kcd->first_cnt*kcd->second_cnt*sizeof(int16));
+ memcpy(new,kcd->offsets,kcd->first_cnt*kcd->second_cnt*sizeof(int16));
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ newd = galloc(kcd->first_cnt*kcd->second_cnt*sizeof(DeviceTable));
+ memcpy(newd,kcd->adjusts,kcd->first_cnt*kcd->second_cnt*sizeof(DeviceTable));
+#endif
+ if ( off==0 ) {
+ for ( i=1; i<kcd->first_cnt; ++i ) {
+ if ( movethese[i]->selected ) {
+ for ( k=i; k<kcd->first_cnt && movethese[k]->selected; ++k );
+ memcpy(new+(i+dir)*kcd->second_cnt,kcd->offsets+i*kcd->second_cnt,
+ (k-i)*kcd->second_cnt*sizeof(int16));
+ if ( dir>0 )
+ memcpy(new+i*kcd->second_cnt,kcd->offsets+k*kcd->second_cnt,
+ kcd->second_cnt*sizeof(int16));
+ else
+ memcpy(new+(k-1)*kcd->second_cnt,kcd->offsets+(i-1)*kcd->second_cnt,
+ kcd->second_cnt*sizeof(int16));
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ memcpy(newd+(i+dir)*kcd->second_cnt,kcd->adjusts+i*kcd->second_cnt,
+ (k-i)*kcd->second_cnt*sizeof(DeviceTable));
+ if ( dir>0 )
+ memcpy(newd+i*kcd->second_cnt,kcd->adjusts+k*kcd->second_cnt,
+ kcd->second_cnt*sizeof(DeviceTable));
+ else
+ memcpy(newd+(k-1)*kcd->second_cnt,kcd->adjusts+(i-1)*kcd->second_cnt,
+ kcd->second_cnt*sizeof(DeviceTable));
+#endif
+ i=k-1;
+ }
+ }
+ } else {
+ for ( i=0; i<kcd->first_cnt; ++i ) {
+ for ( j=0; j<kcd->second_cnt; ++j ) {
+ if ( movethese[j]->selected ) {
+ for ( k=j; k<kcd->second_cnt && movethese[k]->selected; ++k );
+ memcpy(new+i*kcd->second_cnt+(j+dir),kcd->offsets+i*kcd->second_cnt+j,
+ (k-j)*sizeof(int16));
+ if ( dir>0 )
+ new[i*kcd->second_cnt+j] = kcd->offsets[i*kcd->second_cnt+k];
+ else
+ new[i*kcd->second_cnt+k-1] = kcd->offsets[i*kcd->second_cnt+j-1];
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ memcpy(newd+i*kcd->second_cnt+(j+dir),kcd->offsets+i*kcd->second_cnt+j,
+ (k-j)*sizeof(DeviceTable));
+ if ( dir>0 )
+ newd[i*kcd->second_cnt+j] = kcd->adjusts[i*kcd->second_cnt+k];
+ else
+ newd[i*kcd->second_cnt+k-1] = kcd->adjusts[i*kcd->second_cnt+j-1];
+#endif
+ j = k-1;
+ }
+ }
+ }
+ }
+
+ free(kcd->offsets);
+ kcd->offsets = new;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ free(kcd->adjusts);
+ kcd->adjusts = newd;
+#endif
+}
+
+static int KCD_Up(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_ClassUp;
+ GGadget *list = GWidgetGetControl(kcd->gw,CID_ClassList+off);
+ int32 len;
+
+ OffsetMoveClasses(kcd,-1,GGadgetGetList(list,&len),off);
+ GListMoveSelected(list,-1);
+ _KCD_EnableButtons(kcd,off);
+ KCD_SBReset(kcd);
+ GDrawRequestExpose(kcd->gw,NULL,false);
+ }
+return( true );
+}
+
+static int KCD_Down(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_ClassDown;
+ GGadget *list = GWidgetGetControl(kcd->gw,CID_ClassList+off);
+ int32 len;
+
+ OffsetMoveClasses(kcd,1,GGadgetGetList(list,&len),off);
+ GListMoveSelected(list,1);
+ _KCD_EnableButtons(kcd,off);
+ KCD_SBReset(kcd);
+ GDrawRequestExpose(kcd->gw,NULL,false);
+ }
+return( true );
+}
+
+static void OffsetRemoveClasses(KernClassDlg *kcd, GTextInfo **removethese, int off ) {
+ int16 *new;
+ int i,j,k, remove_cnt;
+ int old_cnt = off==0 ? kcd->first_cnt : kcd->second_cnt;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ DeviceTable *newd;
+#endif
+
+ removethese[0]->selected = false;
+ for ( remove_cnt=i=0; i<old_cnt; ++i )
+ if ( removethese[i]->selected )
+ ++remove_cnt;
+ if ( remove_cnt==0 )
+return;
+
+ if ( off==0 ) {
+ new = galloc((kcd->first_cnt-remove_cnt)*kcd->second_cnt*sizeof(int16));
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ newd = galloc((kcd->first_cnt-remove_cnt)*kcd->second_cnt*sizeof(DeviceTable));
+#endif
+ for ( i=k=0; i<kcd->first_cnt; ++i ) {
+#ifndef FONTFORGE_CONFIG_DEVICETABLES
+ if ( !removethese[i]->selected )
+ memcpy(new+(k++)*kcd->second_cnt,kcd->offsets+i*kcd->second_cnt,kcd->second_cnt*sizeof(int16));
+#else
+ if ( !removethese[i]->selected ) {
+ memcpy(new+k*kcd->second_cnt,kcd->offsets+i*kcd->second_cnt,kcd->second_cnt*sizeof(int16));
+ memcpy(newd+(k++)*kcd->second_cnt,kcd->adjusts+i*kcd->second_cnt,kcd->second_cnt*sizeof(DeviceTable));
+ } else {
+ for ( j=0; j<kcd->second_cnt; ++j )
+ free(kcd->adjusts[i*kcd->second_cnt+j].corrections);
+ }
+#endif
+ }
+ kcd->first_cnt = k;
+ } else {
+ new = galloc(kcd->first_cnt*(kcd->second_cnt-remove_cnt)*sizeof(int16));
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ newd = galloc(kcd->first_cnt*(kcd->second_cnt-remove_cnt)*sizeof(DeviceTable));
+#endif
+ for ( i=0; i<kcd->first_cnt; ++i ) {
+ for ( j=k=0; j<kcd->second_cnt; ++j ) {
+#ifndef FONTFORGE_CONFIG_DEVICETABLES
+ if ( !removethese[j]->selected )
+ new[i*(kcd->second_cnt-remove_cnt)+(k++)] = kcd->offsets[i*kcd->second_cnt+j];
+#else
+ if ( !removethese[j]->selected ) {
+ new[i*(kcd->second_cnt-remove_cnt)+k] = kcd->offsets[i*kcd->second_cnt+j];
+ newd[i*(kcd->second_cnt-remove_cnt)+(k++)] = kcd->adjusts[i*kcd->second_cnt+j];
+ } else
+ free(kcd->adjusts[i*kcd->second_cnt+j].corrections);
+#endif
+ }
+ }
+ kcd->second_cnt -= remove_cnt;
+ }
+
+ free(kcd->offsets);
+ kcd->offsets = new;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ free(kcd->adjusts);
+ kcd->adjusts = newd;
+#endif
+}
+
+static int KCD_Delete(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_ClassDel;
+ GGadget *list = GWidgetGetControl(kcd->gw,CID_ClassList+off);
+ int32 len;
+
+ OffsetRemoveClasses(kcd,GGadgetGetList(list,&len),off);
+ GListDelSelected(list);
+ _KCD_EnableButtons(kcd,off);
+ KCD_SBReset(kcd);
+ GDrawRequestExpose(kcd->gw,NULL,false);
+ }
+return( true );
+}
+
+static int KCD_Edit(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_ClassEdit;
+ if ( GGadgetGetFirstListSelectedItem(GWidgetGetControl(kcd->gw,CID_ClassList+off))>0 )
+ _KCD_DoEditNew(kcd,true,off);
+ }
+return( true );
+}
+
+static int KCD_New(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_ClassNew;
+ _KCD_DoEditNew(kcd,false,off);
+ }
+return( true );
+}
+
+static int KCD_ClassSelected(GGadget *g, GEvent *e) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_ClassList;
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ _KCD_EnableButtons(kcd,off);
+ if ( off==0 )
+ KCD_VShow(kcd,GGadgetGetFirstListSelectedItem(g));
+ else
+ KCD_HShow(kcd,GGadgetGetFirstListSelectedItem(g));
+ } else if ( e->type==et_controlevent && e->u.control.subtype == et_listdoubleclick ) {
+ /* Class 0 can contain something real on the first character but not the second */
+ if ( off==0 || GGadgetGetFirstListSelectedItem(g)>0 )
+ _KCD_DoEditNew(kcd,true,off);
+ }
+return( true );
+}
+
+static int KCD_TextSelect(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
+ KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g));
+ int off = GGadgetGetCid(g)-CID_ClassSelect;
+ const unichar_t *name = _GGadgetGetTitle(g);
+ GGadget *list = GWidgetGetControl(kcd->gw,CID_ClassList+off);
+ int32 len;
+ GTextInfo **ti = GGadgetGetList(list,&len);
+ int nlen=u_strlen(name);
+ unichar_t *start, *pt;
+ int i;
+
+ for ( i=0; i<len; ++i ) {
+ for ( start = ti[i]->text; start!=NULL && *start!='\0'; ) {
+ while ( *start==' ' ) ++start;
+ for ( pt=start; *pt!='\0' && *pt!=' '; ++pt );
+ if ( pt-start == nlen && u_strncmp(name,start,nlen)==0 ) {
+ GGadgetSelectOneListItem(list,i);
+ GGadgetScrollListToPos(list,i);
+ _KCD_EnableButtons(kcd,off);
+ if ( off==0 )
+ KCD_VShow(kcd,i);
+ else
+ KCD_HShow(kcd,i);
+return( true );
+ }
+ start = pt;
+ }
+ }
+
+ /* Otherwise deselect everything */
+ if ( nlen!=0 )
+ for ( i=0; i<len; ++i )
+ GGadgetSelectListItem(list,i,false);
+ }
+return( true );
+}
+
+static void KCD_Mouse(KernClassDlg *kcd,GEvent *event) {
+ static unichar_t space[200];
+ char buf[30];
+ int32 len;
+ GTextInfo **ti;
+ int pos = ((event->u.mouse.y-kcd->ystart2)/kcd->kernh + kcd->offtop) * kcd->second_cnt +
+ (event->u.mouse.x-kcd->xstart2)/kcd->kernw + kcd->offleft;
+
+ GGadgetEndPopup();
+
+ if (( event->type==et_mouseup || event->type==et_mousedown ) &&
+ (event->u.mouse.button==4 || event->u.mouse.button==5) ) {
+ GGadgetDispatchEvent(kcd->vsb,event);
+return;
+ }
+
+ if ( event->u.mouse.x<kcd->xstart || event->u.mouse.x>kcd->xstart2+kcd->fullwidth ||
+ event->u.mouse.y<kcd->ystart || event->u.mouse.y>kcd->ystart2+kcd->height )
+return;
+
+ if ( event->type==et_mousemove ) {
+ int c = (event->u.mouse.x - kcd->xstart2)/kcd->kernw + kcd->offleft;
+ int s = (event->u.mouse.y - kcd->ystart2)/kcd->kernh + kcd->offtop;
+ space[0] = '\0';
+ if ( event->u.mouse.y>=kcd->ystart2 && s<kcd->first_cnt ) {
+ sprintf( buf, "First Class %d\n", s );
+ uc_strcpy(space,buf);
+ ti = GGadgetGetList(GWidgetGetControl(kcd->gw,CID_ClassList),&len);
+ len = u_strlen(space);
+ u_strncpy(space+len,ti[s]->text,(sizeof(space)/sizeof(space[0]))/2-2 - len);
+ uc_strcat(space,"\n");
+ }
+ if ( event->u.mouse.x>=kcd->xstart2 && c<kcd->second_cnt ) {
+ sprintf( buf, "Second Class %d\n", c );
+ uc_strcat(space,buf);
+ ti = GGadgetGetList(GWidgetGetControl(kcd->gw,CID_ClassList+100),&len);
+ len = u_strlen(space);
+ u_strncpy(space+len,ti[c]->text,(sizeof(space)/sizeof(space[0]))-1 - len);
+ }
+ if ( space[0]=='\0' )
+return;
+ if ( space[u_strlen(space)-1]=='\n' )
+ space[u_strlen(space)-1]='\0';
+ GGadgetPreparePopup(kcd->gw,space);
+ } else if ( event->u.mouse.x<kcd->xstart2 || event->u.mouse.y<kcd->ystart2 )
+return;
+ else if ( event->type==et_mousedown )
+ kcd->st_pos = pos;
+ else if ( event->type==et_mouseup ) {
+ if ( pos==kcd->st_pos )
+ KCD_EditOffset(kcd);
+ }
+}
+
+static void KCD_Expose(KernClassDlg *kcd,GWindow pixmap,GEvent *event) {
+ GRect *area = &event->u.expose.rect;
+ GRect rect, select;
+ GRect clip,old1,old2;
+ int len, i, j, x, y;
+ unichar_t ubuf[8];
+ char buf[100];
+ int32 tilen;
+ GTextInfo **ti;
+
+ if ( area->y+area->height<kcd->ystart )
+return;
+ if ( area->y>kcd->ystart2+kcd->height )
+return;
+
+ GDrawPushClip(pixmap,area,&old1);
+ GDrawSetFont(pixmap,kcd->font);
+ GDrawSetLineWidth(pixmap,0);
+ rect.x = kcd->xstart; rect.y = kcd->ystart;
+ rect.width = kcd->width+(kcd->xstart2-kcd->xstart);
+ rect.height = kcd->height+(kcd->ystart2-kcd->ystart);
+ clip = rect;
+ GDrawPushClip(pixmap,&clip,&old2);
+
+ /* In the offsets list, show which classes are selected above in the class*/
+ /* lists */
+ ti = GGadgetGetList(GWidgetGetControl(kcd->gw,CID_ClassList),&tilen);
+ for ( i=0 ; kcd->offtop+i<=kcd->first_cnt && (i-1)*kcd->kernh<kcd->height; ++i ) {
+ if ( i+kcd->offtop<tilen && ti[i+kcd->offtop]->selected ) {
+ select.x = kcd->xstart+1; select.y = kcd->ystart2+i*kcd->kernh+1;
+ select.width = rect.width-1; select.height = kcd->kernh-1;
+ GDrawFillRect(pixmap,&select,0xffff00);
+ }
+ }
+ ti = GGadgetGetList(GWidgetGetControl(kcd->gw,CID_ClassList+100),&tilen);
+ for ( i=0 ; kcd->offleft+i<=kcd->second_cnt && (i-1)*kcd->kernw<kcd->fullwidth; ++i ) {
+ if ( i+kcd->offleft<tilen && ti[i+kcd->offleft]->selected ) {
+ select.x = kcd->xstart2+i*kcd->kernw+1; select.y = kcd->ystart+1;
+ select.width = kcd->kernw-1; select.height = rect.height-1;
+ GDrawFillRect(pixmap,&select,0xffff00);
+ }
+ }
+
+ for ( i=0 ; kcd->offtop+i<=kcd->first_cnt && (i-1)*kcd->kernh<kcd->height; ++i ) {
+ GDrawDrawLine(pixmap,kcd->xstart,kcd->ystart2+i*kcd->kernh,kcd->xstart+rect.width,kcd->ystart2+i*kcd->kernh,
+ 0x808080);
+ if ( i+kcd->offtop<kcd->first_cnt ) {
+ sprintf( buf, "%d", i+kcd->offtop );
+ uc_strcpy(ubuf,buf);
+ len = GDrawGetTextWidth(pixmap,ubuf,-1,NULL);
+ GDrawDrawText(pixmap,kcd->xstart+(kcd->kernw-len)/2,kcd->ystart2+i*kcd->kernh+kcd->as+1,
+ ubuf,-1,NULL,0xff0000);
+ }
+ }
+ for ( i=0 ; kcd->offleft+i<=kcd->second_cnt && (i-1)*kcd->kernw<kcd->fullwidth; ++i ) {
+ GDrawDrawLine(pixmap,kcd->xstart2+i*kcd->kernw,kcd->ystart,kcd->xstart2+i*kcd->kernw,kcd->ystart+rect.height,
+ 0x808080);
+ if ( i+kcd->offleft<kcd->second_cnt ) {
+ sprintf( buf, "%d", i+kcd->offleft );
+ uc_strcpy(ubuf,buf);
+ len = GDrawGetTextWidth(pixmap,ubuf,-1,NULL);
+ GDrawDrawText(pixmap,kcd->xstart2+i*kcd->kernw+(kcd->kernw-len)/2,kcd->ystart+kcd->as+1,
+ ubuf,-1,NULL,0xff0000);
+ }
+ }
+
+ for ( i=0 ; kcd->offtop+i<kcd->first_cnt && (i-1)*kcd->kernh<kcd->height; ++i ) {
+ y = kcd->ystart2+i*kcd->kernh;
+ if ( y>area->y+area->height )
+ break;
+ if ( y+kcd->kernh<area->y )
+ continue;
+ for ( j=0 ; kcd->offleft+j<kcd->second_cnt && (j-1)*kcd->kernw<kcd->fullwidth; ++j ) {
+ x = kcd->xstart2+j*kcd->kernw;
+ if ( x>area->x+area->width )
+ break;
+ if ( x+kcd->kernw<area->x )
+ continue;
+
+ sprintf( buf, "%d", kcd->offsets[(i+kcd->offtop)*kcd->second_cnt+j+kcd->offleft] );
+ uc_strcpy(ubuf,buf);
+ len = GDrawGetTextWidth(pixmap,ubuf,-1,NULL);
+ GDrawDrawText(pixmap,x+kcd->kernw-3-len,y+kcd->as+1,
+ ubuf,-1,NULL,0x000000);
+ }
+ }
+
+ GDrawDrawLine(pixmap,kcd->xstart,kcd->ystart2,kcd->xstart+rect.width,kcd->ystart2,
+ 0x000000);
+ GDrawDrawLine(pixmap,kcd->xstart2,kcd->ystart,kcd->xstart2,kcd->ystart+rect.height,
+ 0x000000);
+ GDrawPopClip(pixmap,&old2);
+ GDrawPopClip(pixmap,&old1);
+ GDrawDrawRect(pixmap,&rect,0x000000);
+ rect.y += rect.height;
+ rect.x += rect.width;
+ LogoExpose(pixmap,event,&rect,dm_fore);
+}
+
+static int KCD_SBReset(KernClassDlg *kcd) {
+ int oldtop = kcd->offtop, oldleft = kcd->offleft;
+
+ if ( kcd->height>=kcd->kernh )
+ GScrollBarSetBounds(kcd->vsb,0,kcd->first_cnt, kcd->height/kcd->kernh);
+ if ( kcd->width>=kcd->kernw )
+ GScrollBarSetBounds(kcd->hsb,0,kcd->second_cnt, kcd->width/kcd->kernw);
+ if ( kcd->offtop + (kcd->height/kcd->kernh) >= kcd->first_cnt )
+ kcd->offtop = kcd->first_cnt - (kcd->height/kcd->kernh);
+ if ( kcd->offtop < 0 ) kcd->offtop = 0;
+ if ( kcd->offleft + (kcd->width/kcd->kernw) >= kcd->second_cnt )
+ kcd->offleft = kcd->second_cnt - (kcd->width/kcd->kernw);
+ if ( kcd->offleft < 0 ) kcd->offleft = 0;
+ GScrollBarSetPos(kcd->vsb,kcd->offtop);
+ GScrollBarSetPos(kcd->hsb,kcd->offleft);
+
+return( oldtop!=kcd->offtop || oldleft!=kcd->offleft );
+}
+
+static void KCD_HShow(KernClassDlg *kcd, int pos) {
+ if ( pos>=0 && pos<kcd->second_cnt ) {
+#if 0
+ if ( pos>=kcd->offleft && pos<kcd->offleft+(kcd->width/kcd->kernw) )
+return; /* Already visible */
+#endif
+ --pos; /* One line of context */
+ if ( pos + (kcd->width/kcd->kernw) >= kcd->second_cnt )
+ pos = kcd->second_cnt - (kcd->width/kcd->kernw);
+ if ( pos < 0 ) pos = 0;
+ kcd->offleft = pos;
+ GScrollBarSetPos(kcd->hsb,pos);
+ }
+ GDrawRequestExpose(kcd->gw,NULL,false);
+}
+
+static void KCD_HScroll(KernClassDlg *kcd,struct sbevent *sb) {
+ int newpos = kcd->offleft;
+ GRect rect;
+
+ switch( sb->type ) {
+ case et_sb_top:
+ newpos = 0;
+ break;
+ case et_sb_uppage:
+ if ( kcd->width/kcd->kernw == 1 )
+ --newpos;
+ else
+ newpos -= kcd->width/kcd->kernw - 1;
+ break;
+ case et_sb_up:
+ --newpos;
+ break;
+ case et_sb_down:
+ ++newpos;
+ break;
+ case et_sb_downpage:
+ if ( kcd->width/kcd->kernw == 1 )
+ ++newpos;
+ else
+ newpos += kcd->width/kcd->kernw - 1;
+ break;
+ case et_sb_bottom:
+ newpos = kcd->second_cnt - (kcd->width/kcd->kernw);
+ break;
+ case et_sb_thumb:
+ case et_sb_thumbrelease:
+ newpos = sb->pos;
+ break;
+ }
+ if ( newpos + (kcd->width/kcd->kernw) >= kcd->second_cnt )
+ newpos = kcd->second_cnt - (kcd->width/kcd->kernw);
+ if ( newpos < 0 ) newpos = 0;
+ if ( newpos!=kcd->offleft ) {
+ int diff = newpos-kcd->offleft;
+ kcd->offleft = newpos;
+ GScrollBarSetPos(kcd->hsb,newpos);
+ rect.x = kcd->xstart2+1; rect.y = kcd->ystart;
+ rect.width = kcd->width-1;
+ rect.height = kcd->height+(kcd->ystart2-kcd->ystart);
+ GDrawScroll(kcd->gw,&rect,-diff*kcd->kernw,0);
+ }
+}
+
+static void KCD_VShow(KernClassDlg *kcd, int pos) {
+ if ( pos>=0 && pos<kcd->first_cnt ) {
+#if 0
+ if ( pos>=kcd->offtop && pos<kcd->offtop+(kcd->height/kcd->kernh) )
+return; /* Already visible */
+#endif
+ --pos; /* One line of context */
+ if ( pos + (kcd->height/kcd->kernh) >= kcd->first_cnt )
+ pos = kcd->first_cnt - (kcd->height/kcd->kernh);
+ if ( pos < 0 ) pos = 0;
+ kcd->offtop = pos;
+ GScrollBarSetPos(kcd->vsb,pos);
+ }
+ GDrawRequestExpose(kcd->gw,NULL,false);
+}
+
+static void KCD_VScroll(KernClassDlg *kcd,struct sbevent *sb) {
+ int newpos = kcd->offtop;
+ GRect rect;
+
+ switch( sb->type ) {
+ case et_sb_top:
+ newpos = 0;
+ break;
+ case et_sb_uppage:
+ if ( kcd->height/kcd->kernh == 1 )
+ --newpos;
+ else
+ newpos -= kcd->height/kcd->kernh - 1;
+ break;
+ case et_sb_up:
+ --newpos;
+ break;
+ case et_sb_down:
+ ++newpos;
+ break;
+ case et_sb_downpage:
+ if ( kcd->height/kcd->kernh == 1 )
+ ++newpos;
+ else
+ newpos += kcd->height/kcd->kernh - 1;
+ break;
+ case et_sb_bottom:
+ newpos = kcd->first_cnt - (kcd->height/kcd->kernh);
+ break;
+ case et_sb_thumb:
+ case et_sb_thumbrelease:
+ newpos = sb->pos;
+ break;
+ }
+ if ( newpos + (kcd->height/kcd->kernh) >= kcd->first_cnt )
+ newpos = kcd->first_cnt - (kcd->height/kcd->kernh);
+ if ( newpos < 0 ) newpos = 0;
+ if ( newpos!=kcd->offtop ) {
+ int diff = newpos-kcd->offtop;
+ kcd->offtop = newpos;
+ GScrollBarSetPos(kcd->vsb,newpos);
+ rect.x = kcd->xstart; rect.y = kcd->ystart2+1;
+ rect.width = kcd->width+(kcd->xstart2-kcd->xstart);
+ rect.height = kcd->height-1;
+ GDrawScroll(kcd->gw,&rect,0,diff*kcd->kernh);
+ }
+}
+
+static void KCD_Drop(KernClassDlg *kcd, GEvent *event) {
+ DropChars2Text(kcd->gw,GWidgetGetControl(kcd->cw,CID_GlyphList),event);
+}
+
+static int subkern_e_h(GWindow gw, GEvent *event) {
+ KernClassDlg *kcd = GDrawGetUserData(gw);
+
+ switch ( event->type ) {
+ case et_char:
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("metricsview.html#kernclass");
+return( true );
+ } else if ( event->u.chr.keysym=='q' && (event->u.chr.state&ksm_control)) {
+ if ( event->u.chr.state&ksm_shift )
+ KC_DoCancel(kcd);
+ else
+ MenuExit(NULL,NULL,NULL);
+return( true );
+ }
+return( false );
+ case et_mouseup: case et_mousedown: case et_mousemove:
+ KCD_KernMouse(kcd,event);
+ break;
+ case et_expose:
+ KCD_KernExpose(kcd,gw,event);
+ break;
+ case et_drop:
+ KCD_Drop(kcd,event);
+ break;
+ }
+return( true );
+}
+
+static int subkcd_e_h(GWindow gw, GEvent *event) {
+ KernClassDlg *kcd = GDrawGetUserData(gw);
+
+ switch ( event->type ) {
+ case et_char:
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("metricsview.html#kernclass");
+return( true );
+ } else if ( event->u.chr.keysym=='q' && (event->u.chr.state&ksm_control)) {
+ if ( event->u.chr.state&ksm_shift )
+ KC_DoCancel(kcd);
+ else
+ MenuExit(NULL,NULL,NULL);
+return( true );
+ }
+return( false );
+ }
+return( true );
+}
+
+static int kcd_e_h(GWindow gw, GEvent *event) {
+ KernClassDlg *kcd = GDrawGetUserData(gw);
+
+ switch ( event->type ) {
+ case et_close:
+ KC_DoCancel(kcd);
+ break;
+ case et_char:
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help(kcd->iskernpair ? "metricsview.html#kernpair":
+ "metricsview.html#kernclass");
+return( true );
+ }
+return( false );
+ break;
+ case et_destroy:
+ if ( kcd!=NULL ) {
+ SplineFont *sf = kcd->sf;
+ KernClassListDlg *kcld = kcd->isv ? sf->vkcld : sf->kcld;
+ KernClassDlg *prev, *test;
+ for ( prev=NULL, test=sf->kcd; test!=NULL && test!=kcd; prev=test, test=test->next );
+ if ( test==kcd ) {
+ if ( prev==NULL )
+ sf->kcd = test->next;
+ else
+ prev->next = test->next;
+ }
+ if ( kcld!=NULL ) {
+ GGadgetSetList(GWidgetGetControl(kcld->gw,CID_List),
+ KCLookupSubtableArray(sf,kcd->isv),false);
+ }
+ free(kcd);
+ }
+ break;
+ case et_mouseup: case et_mousemove: case et_mousedown:
+ if ( kcd->iskernpair )
+ KCD_KernMouse(kcd,event);
+ else
+ KCD_Mouse(kcd,event);
+ break;
+ case et_expose:
+ if ( kcd->iskernpair )
+ KCD_KernExpose(kcd,gw,event);
+ else
+ KCD_Expose(kcd,gw,event);
+ break;
+ case et_resize: {
+ GRect wsize, csize;
+
+ GDrawGetSize(kcd->gw,&wsize);
+
+ kcd->fullwidth = wsize.width;
+ if ( kcd->cw!=NULL ) {
+ GDrawResize(kcd->cw,wsize.width,wsize.height);
+ GDrawResize(kcd->kw,wsize.width,wsize.height);
+ GGadgetGetSize(kcd->hsb,&csize);
+ kcd->width = csize.width;
+ kcd->xstart2 = csize.x;
+ GGadgetGetSize(kcd->vsb,&csize);
+ kcd->ystart2 = csize.y;
+ kcd->height = csize.height;
+ kcd->xstart = kcd->xstart2-kcd->kernw;
+ kcd->ystart = kcd->ystart2-kcd->fh-1;
+ KCD_SBReset(kcd);
+ GDrawRequestExpose(kcd->kw,NULL,false);
+ GDrawRequestExpose(kcd->cw,NULL,false);
+ } else {
+ kcd->width = wsize.width-kcd->xstart2-5;
+ kcd->height = wsize.height-kcd->ystart2;
+ }
+ GDrawRequestExpose(kcd->gw,NULL,false);
+ } break;
+ case et_controlevent:
+ switch( event->u.control.subtype ) {
+ case et_scrollbarchange:
+ if ( event->u.control.g == kcd->hsb )
+ KCD_HScroll(kcd,&event->u.control.u.sb);
+ else
+ KCD_VScroll(kcd,&event->u.control.u.sb);
+ break;
+ }
+ break;
+ }
+return( true );
+}
+
+static int AddClassList(GGadgetCreateData *gcd, GTextInfo *label, int k, int off,
+ int x, int y, int width, GGadgetCreateData **harray,
+ GGadgetCreateData **varray ) {
+ int blen = GIntGetResource(_NUM_Buttonsize);
+ int space = 10;
+
+ harray[0] = GCD_HPad10;
+ label[k].text = (unichar_t *) (x<20?_("First Char"):_("Second Char"));
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = x+10; gcd[k].gd.pos.y = y;
+ gcd[k].gd.flags = gg_visible | gg_enabled;
+ gcd[k].gd.cid = CID_ClassLabel+off;
+ gcd[k++].creator = GLabelCreate;
+ harray[1] = &gcd[k-1]; harray[2] = GCD_Glue;
+
+ label[k].image = &GIcon_up;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = x+100; gcd[k].gd.pos.y = y-3;
+ gcd[k].gd.pos.height = 19;
+ gcd[k].gd.flags = gg_visible|gg_utf8_popup;
+ gcd[k].gd.handle_controlevent = KCD_Up;
+ gcd[k].gd.popup_msg = (unichar_t *) _("Move selected class up");
+ gcd[k].gd.cid = CID_ClassUp+off;
+ gcd[k++].creator = GButtonCreate;
+ harray[3] = &gcd[k-1];
+
+ label[k].image = &GIcon_down;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = x+120; gcd[k].gd.pos.y = y-3;
+ gcd[k].gd.pos.height = 19;
+ gcd[k].gd.flags = gg_visible|gg_utf8_popup;
+ gcd[k].gd.handle_controlevent = KCD_Down;
+ gcd[k].gd.popup_msg = (unichar_t *) _("Move selected class down");
+ gcd[k].gd.cid = CID_ClassDown+off;
+ gcd[k++].creator = GButtonCreate;
+ harray[4] = &gcd[k-1]; harray[5] = GCD_Glue; harray[6] = NULL;
+
+ gcd[k].gd.flags = gg_enabled|gg_visible;
+ gcd[k].gd.u.boxelements = harray;
+ gcd[k++].creator = GHBoxCreate;
+ varray[0] = &gcd[k-1];
+
+ gcd[k].gd.pos.x = x; gcd[k].gd.pos.y = y+17;
+ gcd[k].gd.pos.width = width;
+ gcd[k].gd.pos.height = 8*12+10;
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_list_multiplesel;
+ gcd[k].gd.handle_controlevent = KCD_ClassSelected;
+ gcd[k].gd.cid = CID_ClassList+off;
+ gcd[k++].creator = GListCreate;
+ varray[1] = &gcd[k-1];
+
+ label[k].text = (unichar_t *) S_("Class|New...");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+gcd[k-1].gd.pos.height+10;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible | gg_enabled;
+ gcd[k].gd.handle_controlevent = KCD_New;
+ gcd[k].gd.cid = CID_ClassNew+off;
+ gcd[k++].creator = GButtonCreate;
+ harray[7] = &gcd[k-1]; harray[8] = GCD_Glue;
+
+ label[k].text = (unichar_t *) _("Edit...");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = x+blen+space; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible;
+ gcd[k].gd.handle_controlevent = KCD_Edit;
+ gcd[k].gd.cid = CID_ClassEdit+off;
+ gcd[k++].creator = GButtonCreate;
+ harray[9] = &gcd[k-1]; harray[10] = GCD_Glue;
+
+ label[k].text = (unichar_t *) _("Delete");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = gcd[k-1].gd.pos.x+blen+space; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible;
+ gcd[k].gd.handle_controlevent = KCD_Delete;
+ gcd[k].gd.cid = CID_ClassDel+off;
+ gcd[k++].creator = GButtonCreate;
+ harray[11] = &gcd[k-1]; harray[12] = NULL;
+
+ gcd[k].gd.flags = gg_enabled|gg_visible;
+ gcd[k].gd.u.boxelements = harray+7;
+ gcd[k++].creator = GHBoxCreate;
+ varray[2] = &gcd[k-1];
+
+/* GT: Select the class containing the glyph named in the following text field */
+ label[k].text = (unichar_t *) _("Select Glyph Class:");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = gcd[k-3].gd.pos.x+5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+26+4;
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ gcd[k].gd.popup_msg = (unichar_t *) _("Select the class containing the named glyph");
+ gcd[k++].creator = GLabelCreate;
+ harray[13] = &gcd[k-1];
+
+ gcd[k].gd.pos.x = gcd[k-1].gd.pos.x+100; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-4;
+ gcd[k].gd.pos.width = 80;
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ gcd[k].gd.popup_msg = (unichar_t *) _("Select the class containing the named glyph");
+ gcd[k].gd.handle_controlevent = KCD_TextSelect;
+ gcd[k].gd.cid = CID_ClassSelect+off;
+ gcd[k++].creator = GTextFieldCreate;
+ harray[14] = &gcd[k-1]; harray[15] = NULL;
+
+ gcd[k].gd.flags = gg_enabled|gg_visible;
+ gcd[k].gd.u.boxelements = harray+13;
+ gcd[k++].creator = GHBoxCreate;
+ varray[3] = &gcd[k-1]; varray[4] = NULL;
+
+ gcd[k].gd.flags = gg_enabled|gg_visible;
+ gcd[k].gd.u.boxelements = varray;
+ gcd[k++].creator = GVBoxCreate;
+
+return( k );
+}
+
+static void FillShowKerningWindow(KernClassDlg *kcd, int for_class, SplineFont *sf) {
+ GGadgetCreateData gcd[30], hbox, flagbox, hvbox, buttonbox, mainbox[2];
+ GGadgetCreateData *harray[10], *hvarray[14], *flagarray[4], *buttonarray[9], *varray[12];
+ GTextInfo label[30];
+ int k,j;
+ char buffer[20];
+ GRect pos;
+
+ kcd->top = GDrawPointsToPixels(kcd->gw,100);
+ kcd->pixelsize = 150;
+ kcd->magfactor = 1;
+
+ memset(gcd,0,sizeof(gcd));
+ memset(label,0,sizeof(label));
+ memset(&hbox,0,sizeof(hbox));
+ memset(&flagbox,0,sizeof(flagbox));
+ memset(&hvbox,0,sizeof(hvbox));
+ memset(&buttonbox,0,sizeof(buttonbox));
+ memset(&mainbox,0,sizeof(mainbox));
+ k = j = 0;
+
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = 5;
+ gcd[k].gd.pos.width = 120;
+ gcd[k].gd.flags = gg_visible | gg_enabled;
+ gcd[k].gd.handle_controlevent = KCD_GlyphSelected;
+ gcd[k].gd.cid = CID_First;
+ gcd[k++].creator = for_class ? GListButtonCreate : GTextFieldCreate;
+ harray[0] = &gcd[k-1];
+
+ gcd[k].gd.pos.x = 130; gcd[k].gd.pos.y = 5;
+ gcd[k].gd.pos.width = 120;
+ gcd[k].gd.flags = gg_visible | gg_enabled;
+ if ( !for_class ) gcd[k].gd.flags |= gg_list_alphabetic;
+ gcd[k].gd.handle_controlevent = KCD_GlyphSelected;
+ gcd[k].gd.cid = CID_Second;
+ gcd[k++].creator = for_class ? GListButtonCreate : GListFieldCreate;
+ harray[1] = &gcd[k-1];
+
+ label[k].text = (unichar_t *) _("Use FreeType");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 260; gcd[k].gd.pos.y = 7;
+ if ( !hasFreeType() )
+ gcd[k].gd.flags = gg_visible;
+ else
+ gcd[k].gd.flags = gg_enabled|gg_visible|gg_cb_on;
+ gcd[k].gd.cid = CID_FreeType;
+ gcd[k].gd.handle_controlevent = KCB_FreeTypeChanged;
+ gcd[k++].creator = GCheckBoxCreate;
+ harray[2] = GCD_Glue; harray[3] = &gcd[k-1];
+ harray[4] = GCD_Glue; harray[5] = GCD_Glue;
+ harray[6] = GCD_Glue; harray[7] = GCD_Glue; harray[8] = NULL;
+
+ hbox.gd.flags = gg_enabled|gg_visible;
+ hbox.gd.u.boxelements = harray;
+ hbox.creator = GHBoxCreate;
+ varray[j++] = &hbox; varray[j++] = NULL;
+
+ label[k].text = (unichar_t *) _("Display Size:");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 30; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+30;
+ gcd[k].gd.flags = gg_visible|gg_enabled ;
+ gcd[k++].creator = GLabelCreate;
+ hvarray[0] = &gcd[k-1];
+
+ sprintf( buffer, "%d", kcd->pixelsize );
+ label[k].text = (unichar_t *) buffer;
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 92; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-4;
+ gcd[k].gd.pos.width = 80;
+ gcd[k].gd.flags = gg_visible|gg_enabled ;
+ gcd[k].gd.cid = CID_DisplaySize;
+ gcd[k].gd.handle_controlevent = KCD_DisplaySizeChanged;
+#ifndef FONTFORGE_CONFIG_DEVICETABLES
+ gcd[k++].creator = GTextFieldCreate;
+#else
+ gcd[k++].creator = GListFieldCreate;
+#endif
+ hvarray[1] = &gcd[k-1];
+
+ label[k].text = (unichar_t *) _("Magnification:");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 185; gcd[k].gd.pos.y = gcd[k-2].gd.pos.y;
+ gcd[k].gd.flags = gg_visible|gg_enabled ;
+ gcd[k++].creator = GLabelCreate;
+ hvarray[2] = &gcd[k-1];
+
+#ifndef FONTFORGE_CONFIG_DEVICETABLES
+ gcd[k].gd.pos.x = 255; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-4;
+#else
+ gcd[k].gd.pos.x = 305; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-4;
+#endif
+ gcd[k].gd.flags = gg_visible|gg_enabled ;
+ gcd[k].gd.cid = CID_Magnifications;
+ gcd[k].gd.u.list = magnifications;
+ gcd[k].gd.handle_controlevent = KCD_MagnificationChanged;
+ gcd[k++].creator = GListButtonCreate;
+ hvarray[3] = &gcd[k-1]; hvarray[4] = GCD_Glue; hvarray[5] = NULL;
+
+ label[k].text = (unichar_t *) _("Kern Offset:");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 30; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+30;
+ gcd[k].gd.flags = gg_visible|gg_enabled ;
+ gcd[k++].creator = GLabelCreate;
+ hvarray[6] = &gcd[k-1];
+
+ gcd[k].gd.pos.x = 90; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-4;
+ gcd[k].gd.pos.width = 60;
+ gcd[k].gd.flags = gg_visible|gg_enabled ;
+ gcd[k].gd.cid = CID_KernOffset;
+ gcd[k].gd.handle_controlevent = KCD_KernOffChanged;
+ gcd[k++].creator = GTextFieldCreate;
+ hvarray[7] = &gcd[k-1];
+
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ label[k].text = (unichar_t *) _("Device Table Correction:");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 185; gcd[k].gd.pos.y = gcd[k-2].gd.pos.y;
+ gcd[k].gd.flags = gg_visible|gg_enabled ;
+ gcd[k++].creator = GLabelCreate;
+ hvarray[8] = &gcd[k-1];
+
+ label[k].text = (unichar_t *) "0";
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 305; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-4;
+ gcd[k].gd.pos.width = 60;
+ gcd[k].gd.flags = gg_visible|gg_enabled ;
+ gcd[k].gd.cid = CID_Correction;
+ gcd[k].gd.handle_controlevent = KCD_CorrectionChanged;
+ gcd[k++].creator = GTextFieldCreate;
+ hvarray[9] = &gcd[k-1];
+#else
+ hvarray[8] = GCD_Glue;
+ hvarray[9] = GCD_Glue;
+#endif
+ hvarray[10] = GCD_Glue;
+ hvarray[11] = NULL; hvarray[12] = NULL;
+
+ hvbox.gd.flags = gg_enabled|gg_visible;
+ hvbox.gd.u.boxelements = hvarray;
+ hvbox.creator = GHVBoxCreate;
+ varray[j++] = &hvbox; varray[j++] = NULL;
+
+ varray[j++] = GCD_Glue; varray[j++] = NULL;
+
+ GDrawGetSize(kcd->kw,&pos);
+
+ if ( !for_class ) {
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = -40;
+ gcd[k].gd.flags = gg_enabled ;
+ label[k].text = (unichar_t *) _("Lookup subtable:");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k++].creator = GLabelCreate;
+ flagarray[0] = &gcd[k-1];
+
+ gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = KC_Height-KC_CANCELDROP-27;
+ gcd[k].gd.pos.width = GDrawPixelsToPoints(kcd->kw,pos.width)-20;
+ gcd[k].gd.flags = gg_enabled|gg_visible;
+ gcd[k].gd.cid = CID_Subtable;
+ gcd[k].gd.handle_controlevent = KP_Subtable;
+ gcd[k++].creator = GListButtonCreate;
+ flagarray[1] = &gcd[k-1]; flagarray[2] = GCD_Glue; flagarray[3] = NULL;
+
+ flagbox.gd.flags = gg_enabled|gg_visible;
+ flagbox.gd.u.boxelements = flagarray;
+ flagbox.creator = GHBoxCreate;
+ varray[j++] = &flagbox; varray[j++] = NULL;
+ }
+
+ label[k].text = (unichar_t *) (for_class ? _("< _Prev") : _("_OK"));
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 30; gcd[k].gd.pos.y = KC_Height-KC_CANCELDROP;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible|gg_enabled;
+ if ( !for_class ) gcd[k].gd.flags |= gg_but_default;
+ gcd[k].gd.handle_controlevent = for_class ? KCD_Prev2 : KPD_OK;
+ gcd[k].gd.cid = CID_Prev2;
+ gcd[k++].creator = GButtonCreate;
+
+ label[k].text = (unichar_t *) (for_class ? _("_Next >") : _("_Cancel"));
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = -30+3; gcd[k].gd.pos.y = KC_Height-KC_CANCELDROP;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible|gg_enabled ;
+ if ( !for_class ) gcd[k].gd.flags |= gg_but_cancel;
+ gcd[k].gd.handle_controlevent = for_class ? KCD_Next2 : KPD_Cancel;
+ gcd[k].gd.cid = CID_Next2;
+ gcd[k++].creator = GButtonCreate;
+
+ buttonarray[0] = GCD_Glue; buttonarray[1] = &gcd[k-2]; buttonarray[2] = GCD_Glue;
+ buttonarray[3] = GCD_Glue; buttonarray[4] = &gcd[k-1]; buttonarray[5] = GCD_Glue;
+ buttonarray[6] = NULL;
+ buttonbox.gd.flags = gg_enabled|gg_visible;
+ buttonbox.gd.u.boxelements = buttonarray;
+ buttonbox.creator = GHBoxCreate;
+ varray[j++] = &buttonbox; varray[j++] = NULL; varray[j++] = NULL;
+
+ mainbox[0].gd.pos.x = mainbox[0].gd.pos.y = 2;
+ mainbox[0].gd.flags = gg_enabled|gg_visible;
+ mainbox[0].gd.u.boxelements = varray;
+ mainbox[0].creator = GHVGroupCreate;
+
+ GGadgetsCreate(kcd->kw,mainbox);
+
+ GHVBoxSetExpandableRow(mainbox[0].ret,gb_expandglue);
+ GHVBoxSetExpandableCol(hbox.ret,gb_expandglue);
+ GHVBoxSetExpandableCol(hvbox.ret,gb_expandglue);
+ GHVBoxSetExpandableCol(buttonbox.ret,gb_expandgluesame);
+ if ( !for_class ) {
+ GHVBoxSetExpandableCol(flagbox.ret,gb_expandglue);
+ GGadgetSetList(flagarray[1]->ret,SFSubtablesOfType(sf,gpos_pair,false),false);
+ }
+}
+#endif
+
+void KernClassD(KernClass *kc, SplineFont *sf, int isv) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ GRect pos, subpos;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[46], classbox, hvbox, buttonbox, mainbox[2];
+ GGadgetCreateData selbox, *selarray[7], pane2[2];
+ GGadgetCreateData *harray1[17], *harray2[17], *varray1[5], *varray2[5];
+ GGadgetCreateData *hvarray[13], *buttonarray[8], *varray[15], *harrayclasses[6];
+ GTextInfo label[46];
+ KernClassDlg *kcd;
+ int i, kc_width, vi, y, k;
+ static unichar_t courier[] = { 'c', 'o', 'u', 'r', 'i', 'e', 'r', ',', 'm','o','n','o','s','p','a','c','e',',','c','l','e','a','r','l','y','u',',', 'u','n','i','f','o','n','t', '\0' };
+ int as, ds, ld, sbsize;
+ FontRequest rq;
+ static unichar_t kernw[] = { '-', '1', '2', '3', '4', '5', 0 };
+ GWindow gw;
+ char titlebuf[300];
+
+ for ( kcd = sf->kcd; kcd!=NULL && kcd->orig!=kc; kcd = kcd->next );
+ if ( kcd!=NULL ) {
+ GDrawSetVisible(kcd->gw,true);
+ GDrawRaise(kcd->gw);
+return;
+ }
+ kcd = gcalloc(1,sizeof(KernClassDlg));
+ kcd->orig = kc;
+ kcd->subtable = kc->subtable;
+ kcd->sf = sf;
+ kcd->isv = isv;
+ kcd->next = sf->kcd;
+ sf->kcd = kcd;
+
+ kcd->first_cnt = kc->first_cnt;
+ kcd->second_cnt = kc->second_cnt;
+ kcd->offsets = galloc(kc->first_cnt*kc->second_cnt*sizeof(int16));
+ memcpy(kcd->offsets,kc->offsets,kc->first_cnt*kc->second_cnt*sizeof(int16));
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ kcd->adjusts = galloc(kc->first_cnt*kc->second_cnt*sizeof(DeviceTable));
+ memcpy(kcd->adjusts,kc->adjusts,kc->first_cnt*kc->second_cnt*sizeof(DeviceTable));
+ for ( i=0; i<kcd->first_cnt*kcd->second_cnt; ++i ) {
+ if ( kcd->adjusts[i].corrections!=NULL ) {
+ int len = kcd->adjusts[i].last_pixel_size-kcd->adjusts[i].first_pixel_size+1;
+ kcd->adjusts[i].corrections = galloc(len);
+ memcpy(kcd->adjusts[i].corrections,kc->adjusts[i].corrections,len);
+ }
+ }
+#endif
+
+ memset(&wattrs,0,sizeof(wattrs));
+ memset(&gcd,0,sizeof(gcd));
+ memset(&classbox,0,sizeof(classbox));
+ memset(&hvbox,0,sizeof(hvbox));
+ memset(&buttonbox,0,sizeof(buttonbox));
+ memset(&mainbox,0,sizeof(mainbox));
+ memset(&label,0,sizeof(label));
+
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = false;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+/* GT: The %s is the name of the lookup subtable containing this kerning class */
+ snprintf( titlebuf, sizeof(titlebuf), _("Kerning by Classes: %s"), kc->subtable->subtable_name );
+ wattrs.utf8_window_title = titlebuf ;
+ wattrs.is_dlg = false;
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,KC_Width));
+ pos.height = GDrawPointsToPixels(NULL,KC_Height);
+ kcd->gw = gw = GDrawCreateTopWindow(NULL,&pos,kcd_e_h,kcd,&wattrs);
+
+ kc_width = GDrawPixelsToPoints(NULL,pos.width*100/GGadgetScale(100));
+
+ memset(&rq,'\0',sizeof(rq));
+ rq.point_size = 12;
+ rq.weight = 400;
+ rq.family_name = courier;
+ kcd->font = GDrawInstanciateFont(GDrawGetDisplayOfWindow(gw),&rq);
+ GDrawFontMetrics(kcd->font,&as,&ds,&ld);
+ kcd->fh = as+ds; kcd->as = as;
+ GDrawSetFont(gw,kcd->font);
+
+ kcd->kernh = kcd->fh+3;
+ kcd->kernw = GDrawGetTextWidth(gw,kernw,-1,NULL)+3;
+
+ i = 0;
+ snprintf( titlebuf, sizeof(titlebuf), _("Lookup Subtable: %s"), kc->subtable->subtable_name );
+ gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 5;
+ gcd[i].gd.flags = gg_visible | gg_enabled;
+ label[i].text = (unichar_t *) titlebuf;
+ label[i].text_is_1byte = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i++].creator = GLabelCreate;
+ varray[0] = &gcd[i-1]; varray[1] = NULL;
+
+ gcd[i].gd.pos.x = 10; gcd[i].gd.pos.y = GDrawPointsToPixels(gw,gcd[i-1].gd.pos.y+17);
+ gcd[i].gd.pos.width = pos.width-20;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_pos_in_pixels;
+ gcd[i++].creator = GLineCreate;
+ varray[2] = &gcd[i-1]; varray[3] = NULL;
+
+ y = gcd[i-2].gd.pos.y+23;
+ i = AddClassList(gcd,label,i,0,5,y,(kc_width-20)/2,harray1,varray1);
+ harrayclasses[0] = &gcd[i-1];
+ i = AddClassList(gcd,label,i,100,(kc_width-20)/2+10,y,(kc_width-20)/2,harray2,varray2);
+ harrayclasses[2] = &gcd[i-1]; harrayclasses[3] = NULL;
+
+ gcd[i].gd.pos.height = 20;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_line_vert;
+ gcd[i++].creator = GLineCreate;
+ harrayclasses[1] = &gcd[i-1];
+
+ classbox.gd.flags = gg_enabled|gg_visible;
+ classbox.gd.u.boxelements = harrayclasses;
+ classbox.creator = GHBoxCreate;
+ varray[4] = &classbox; varray[5] = NULL;
+
+ gcd[i].gd.pos.x = 10; gcd[i].gd.pos.y = GDrawPointsToPixels(gw,gcd[i-1].gd.pos.y+27);
+ gcd[i].gd.pos.width = pos.width-20;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_pos_in_pixels;
+ gcd[i++].creator = GLineCreate;
+ varray[6] = &gcd[i-1]; varray[7] = NULL;
+
+ kcd->canceldrop = GDrawPointsToPixels(gw,KC_CANCELDROP);
+ kcd->sbdrop = kcd->canceldrop+GDrawPointsToPixels(gw,7);
+ gcd[i].gd.pos.width = kcd->kernw;
+ gcd[i].gd.pos.height = kcd->kernh;
+ gcd[i].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels;
+ gcd[i++].creator = GSpacerCreate;
+ hvarray[0] = &gcd[i-1]; hvarray[1] = GCD_Glue; hvarray[2] = GCD_Glue; hvarray[3] = NULL;
+
+ gcd[i].gd.pos.width = kcd->kernw;
+ gcd[i].gd.pos.height = 4*kcd->kernh;
+ gcd[i].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels;
+ gcd[i++].creator = GSpacerCreate;
+
+ vi = i;
+ gcd[i].gd.pos.width = sbsize = GDrawPointsToPixels(gw,_GScrollBar_Width);
+ gcd[i].gd.pos.x = pos.width-sbsize;
+ gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+8;
+ gcd[i].gd.pos.height = pos.height-gcd[i].gd.pos.y-sbsize-kcd->sbdrop;
+ gcd[i].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
+ gcd[i++].creator = GScrollBarCreate;
+ hvarray[4] = &gcd[i-2]; hvarray[5] = GCD_Glue; hvarray[6] = &gcd[i-1]; hvarray[7] = NULL;
+
+ gcd[i].gd.pos.height = sbsize;
+ gcd[i].gd.pos.y = pos.height-sbsize-8;
+ gcd[i].gd.pos.x = 4;
+ gcd[i].gd.pos.width = pos.width-sbsize;
+ gcd[i].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels;
+ gcd[i++].creator = GScrollBarCreate;
+ hvarray[8] = GCD_Glue; hvarray[9] = &gcd[i-1]; hvarray[10] = GCD_Glue; hvarray[11] = NULL;
+ hvarray[12] = NULL;
+ kcd->width = gcd[i-1].gd.pos.width;
+ kcd->xstart = 5;
+
+ hvbox.gd.flags = gg_enabled|gg_visible;
+ hvbox.gd.u.boxelements = hvarray;
+ hvbox.creator = GHVBoxCreate;
+ varray[8] = &hvbox; varray[9] = NULL;
+
+ gcd[i].gd.pos.x = 10; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+24+3;
+ gcd[i].gd.pos.width = -1;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[i].text = (unichar_t *) _("_OK");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.handle_controlevent = KC_OK;
+ gcd[i].gd.cid = CID_OK;
+ gcd[i++].creator = GButtonCreate;
+
+ gcd[i].gd.pos.x = -10; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+3;
+ gcd[i].gd.pos.width = -1;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[i].text = (unichar_t *) _("_Cancel");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.handle_controlevent = KC_Cancel;
+ gcd[i].gd.cid = CID_Cancel;
+ gcd[i++].creator = GButtonCreate;
+
+ buttonarray[0] = GCD_Glue; buttonarray[1] = &gcd[i-2]; buttonarray[2] = GCD_Glue;
+ buttonarray[3] = GCD_Glue; buttonarray[4] = &gcd[i-1]; buttonarray[5] = GCD_Glue;
+ buttonarray[6] = NULL;
+ buttonbox.gd.flags = gg_enabled|gg_visible;
+ buttonbox.gd.u.boxelements = buttonarray;
+ buttonbox.creator = GHBoxCreate;
+ varray[10] = &buttonbox; varray[11] = NULL; varray[12] = NULL;
+
+ mainbox[0].gd.pos.x = mainbox[0].gd.pos.y = 2;
+ mainbox[0].gd.flags = gg_enabled|gg_visible;
+ mainbox[0].gd.u.boxelements = varray;
+ mainbox[0].creator = GHVGroupCreate;
+
+ GGadgetsCreate(kcd->gw,mainbox);
+ kcd->vsb = gcd[vi].ret;
+ kcd->hsb = gcd[vi+1].ret;
+
+ GHVBoxSetExpandableRow(mainbox[0].ret,4);
+
+ GHVBoxSetExpandableCol(buttonbox.ret,gb_expandgluesame);
+
+ GHVBoxSetPadding(hvbox.ret,0,0);
+ GHVBoxSetExpandableRow(hvbox.ret,1);
+ GHVBoxSetExpandableCol(hvbox.ret,1);
+
+ for ( i=0; i<2; ++i ) {
+ GGadgetCreateData *box = harrayclasses[2*i], **boxarray = box->gd.u.boxelements;
+ GHVBoxSetExpandableRow(box->ret,1);
+ GHVBoxSetExpandableCol(boxarray[0]->ret,gb_expandglue);
+ GHVBoxSetExpandableCol(boxarray[2]->ret,gb_expandgluesame);
+ GHVBoxSetExpandableCol(boxarray[3]->ret,1);
+ }
+
+ for ( i=0; i<2; ++i ) {
+ GGadget *list = GWidgetGetControl(kcd->gw,CID_ClassList+i*100);
+ if ( i==0 && kcd->orig!=NULL && kcd->orig->firsts!=NULL && kcd->orig->firsts[0]!=NULL ) {
+ /* OpenType can set class 0 of the first classes by using a coverage*/
+ /* table with more glyphs than are present in all the other classes */
+ unichar_t *temp = uc_copy(kcd->orig->firsts[0]);
+ GListAppendLine(list,temp,false);
+ free(temp);
+ } else
+ GListAppendLine8(list,_("{Everything Else}"),false);
+ if ( kcd->orig!=NULL ) {
+ for ( k=1; k<(&kcd->first_cnt)[i]; ++k ) {
+ unichar_t *temp = uc_copy((&kcd->orig->firsts)[i][k]);
+ GListAppendLine(list,temp,false);
+ free(temp);
+ }
+ }
+ }
+
+ wattrs.mask = wam_events;
+ subpos = pos; subpos.x = subpos.y = 0;
+ kcd->cw = GWidgetCreateSubWindow(kcd->gw,&subpos,subkcd_e_h,kcd,&wattrs);
+
+ memset(&selbox,0,sizeof(selbox));
+ memset(&buttonbox,0,sizeof(buttonbox));
+ memset(pane2,0,sizeof(pane2));
+ memset(gcd,0,sizeof(gcd));
+ memset(label,0,sizeof(label));
+ k = 0;
+
+ label[k].text = (unichar_t *) _("Set From Font");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = 5;
+ gcd[k].gd.popup_msg = (unichar_t *) _("Set this glyph list to be the characters selected in the fontview");
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ gcd[k].gd.handle_controlevent = KCD_FromSelection;
+ gcd[k].gd.cid = CID_Set;
+ gcd[k++].creator = GButtonCreate;
+ selarray[0] = &gcd[k-1]; selarray[1] = GCD_Glue;
+
+ label[k].text = (unichar_t *) _("Select In Font");
+ label[k].text_is_1byte = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 110; gcd[k].gd.pos.y = 5;
+ gcd[k].gd.popup_msg = (unichar_t *) _("Set the fontview's selection to be the characters named here");
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ gcd[k].gd.handle_controlevent = KCD_ToSelection;
+ gcd[k].gd.cid = CID_Select;
+ gcd[k++].creator = GButtonCreate;
+ selarray[2] = &gcd[k-1]; selarray[3] = GCD_Glue;
+ selarray[4] = GCD_Glue; selarray[5] = GCD_Glue; selarray[6] = NULL;
+
+ selbox.gd.flags = gg_enabled|gg_visible;
+ selbox.gd.u.boxelements = selarray;
+ selbox.creator = GHBoxCreate;
+ varray[0] = &selbox; varray[1] = NULL;
+
+ gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = 30;
+ gcd[k].gd.pos.width = KC_Width-25; gcd[k].gd.pos.height = 8*13+4;
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_textarea_wrap;
+ gcd[k].gd.cid = CID_GlyphList;
+ gcd[k++].creator = GTextAreaCreate;
+ varray[2] = &gcd[k-1]; varray[3] = NULL;
+ varray[4] = GCD_Glue; varray[5] = NULL;
+
+ label[k].text = (unichar_t *) _("< _Prev");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = 30; gcd[k].gd.pos.y = KC_Height-KC_CANCELDROP;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible|gg_enabled /*| gg_but_cancel*/;
+ gcd[k].gd.handle_controlevent = KCD_Prev;
+ gcd[k].gd.cid = CID_Prev;
+ gcd[k++].creator = GButtonCreate;
+
+ label[k].text = (unichar_t *) _("_Next >");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.pos.x = -30+3; gcd[k].gd.pos.y = KC_Height-KC_CANCELDROP;
+ gcd[k].gd.pos.width = -1;
+ gcd[k].gd.flags = gg_visible|gg_enabled /*| gg_but_default*/;
+ gcd[k].gd.handle_controlevent = KCD_Next;
+ gcd[k].gd.cid = CID_Next;
+ gcd[k++].creator = GButtonCreate;
+
+ buttonarray[0] = GCD_Glue; buttonarray[1] = &gcd[k-2]; buttonarray[2] = GCD_Glue;
+ buttonarray[3] = GCD_Glue; buttonarray[4] = &gcd[k-1]; buttonarray[5] = GCD_Glue;
+ buttonarray[6] = NULL;
+ buttonbox.gd.flags = gg_enabled|gg_visible;
+ buttonbox.gd.u.boxelements = buttonarray;
+ buttonbox.creator = GHBoxCreate;
+ varray[6] = &buttonbox; varray[7] = NULL; varray[8] = NULL;
+
+ pane2[0].gd.pos.x = pane2[0].gd.pos.y = 2;
+ pane2[0].gd.flags = gg_enabled|gg_visible;
+ pane2[0].gd.u.boxelements = varray;
+ pane2[0].creator = GHVGroupCreate;
+
+ GGadgetsCreate(kcd->cw,pane2);
+
+ GHVBoxSetExpandableRow(pane2[0].ret,gb_expandglue);
+ GHVBoxSetExpandableCol(selbox.ret,gb_expandglue);
+ GHVBoxSetExpandableCol(buttonbox.ret,gb_expandgluesame);
+
+
+ kcd->kw = GWidgetCreateSubWindow(kcd->gw,&subpos,subkern_e_h,kcd,&wattrs);
+ FillShowKerningWindow(kcd, true, kcd->sf);
+
+ GHVBoxFitWindow(mainbox[0].ret);
+ GDrawSetVisible(kcd->gw,true);
+#endif
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+
+static int KCL_New(GGadget *g, GEvent *e) {
+ KernClassListDlg *kcld;
+ struct subtable_data sd;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ kcld = GDrawGetUserData(GGadgetGetWindow(g));
+ memset(&sd,0,sizeof(sd));
+ sd.flags = (kcld->isv ? sdf_verticalkern : sdf_horizontalkern ) |
+ sdf_kernclass;
+ SFNewLookupSubtableOfType(kcld->sf,gpos_pair,&sd);
+ }
+return( true );
+}
+
+static int KCL_Delete(GGadget *g, GEvent *e) {
+ int32 len; int i,j;
+ GTextInfo **old, **new;
+ GGadget *list;
+ KernClassListDlg *kcld;
+ KernClassDlg *kcd;
+ KernClass *p, *kc, *n;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ kcld = GDrawGetUserData(GGadgetGetWindow(g));
+ list = GWidgetGetControl(kcld->gw,CID_List);
+ old = GGadgetGetList(list,&len);
+ new = gcalloc(len+1,sizeof(GTextInfo *));
+ p = NULL; kc = kcld->isv ? kcld->sf->vkerns : kcld->sf->kerns;
+ for ( i=j=0; i<len; ++i, kc = n ) {
+ n = kc->next;
+ if ( !old[i]->selected ) {
+ new[j] = galloc(sizeof(GTextInfo));
+ *new[j] = *old[i];
+ new[j]->text = u_copy(new[j]->text);
+ ++j;
+ p = kc;
+ } else {
+ if ( p!=NULL )
+ p->next = n;
+ else if ( kcld->isv )
+ kcld->sf->vkerns = n;
+ else
+ kcld->sf->kerns = n;
+ kc->next = NULL;
+ for ( kcd=kcld->sf->kcd; kcd!=NULL && kcd->orig!=kc; kcd=kcd->next );
+ if ( kcd!=NULL )
+ KC_DoCancel(kcd);
+ KernClassListFree(kc);
+ }
+ }
+ new[j] = gcalloc(1,sizeof(GTextInfo));
+ GGadgetSetList(list,new,false);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_Delete),false);
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_Edit),false);
+ }
+return( true );
+}
+
+static int KCL_Edit(GGadget *g, GEvent *e) {
+ int sel, i;
+ KernClassListDlg *kcld;
+ KernClass *kc;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ kcld = GDrawGetUserData(GGadgetGetWindow(g));
+ sel = GGadgetGetFirstListSelectedItem(GWidgetGetControl(GGadgetGetWindow(g),CID_List));
+ if ( sel==-1 )
+return( true );
+ for ( kc=kcld->isv?kcld->sf->vkerns:kcld->sf->kerns, i=0; i<sel; kc=kc->next, ++i );
+ KernClassD(kc,kcld->sf,kcld->isv);
+ }
+return( true );
+}
+
+static int KCL_Done(GGadget *g, GEvent *e) {
+ KernClassListDlg *kcld;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ kcld = GDrawGetUserData(GGadgetGetWindow(g));
+ GDrawDestroyWindow(kcld->gw);
+ }
+return( true );
+}
+
+static int KCL_SelChanged(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ KernClassListDlg *kcld = GDrawGetUserData(GGadgetGetWindow(g));
+ int sel = GGadgetGetFirstListSelectedItem(g);
+ GGadgetSetEnabled(GWidgetGetControl(kcld->gw,CID_Delete),sel!=-1);
+ GGadgetSetEnabled(GWidgetGetControl(kcld->gw,CID_Edit),sel!=-1);
+ } else if ( e->type==et_controlevent && e->u.control.subtype == et_listdoubleclick ) {
+ KernClassListDlg *kcld = GDrawGetUserData(GGadgetGetWindow(g));
+ e->u.control.subtype = et_buttonactivate;
+ e->u.control.g = GWidgetGetControl(kcld->gw,CID_Edit);
+ KCL_Edit(e->u.control.g,e);
+ }
+return( true );
+}
+
+static int kcl_e_h(GWindow gw, GEvent *event) {
+ if ( event->type==et_close ) {
+ KernClassListDlg *kcld = GDrawGetUserData(gw);
+ GDrawDestroyWindow(kcld->gw);
+ } else if ( event->type==et_char ) {
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("metricsview.html#kernclass");
+return( true );
+ }
+return( false );
+ } else if ( event->type == et_destroy ) {
+ KernClassListDlg *kcld = GDrawGetUserData(gw);
+ if ( kcld->isv )
+ kcld->sf->vkcld = NULL;
+ else
+ kcld->sf->kcld = NULL;
+ free(kcld);
+ }
+return( true );
+}
+
+void ShowKernClasses(SplineFont *sf,MetricsView *mv,int isv) {
+ KernClassListDlg *kcld;
+ GRect pos;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[7], boxes[4], *varray[10], *harray[9], *harray2[5];
+ GTextInfo label[7];
+ int kcl_width = KCL_Width, temp;
+
+ if ( sf->kcld && !isv ) {
+ GDrawSetVisible(sf->kcld->gw,true);
+ GDrawRaise(sf->kcld->gw);
+return;
+ } else if ( sf->vkcld && isv ) {
+ GDrawSetVisible(sf->vkcld->gw,true);
+ GDrawRaise(sf->vkcld->gw);
+return;
+ }
+
+ kcld = gcalloc(1,sizeof(KernClassListDlg));
+ kcld->sf = sf;
+ kcld->isv = isv;
+ if ( isv )
+ sf->vkcld = kcld;
+ else
+ sf->kcld = kcld;
+
+ memset(&wattrs,0,sizeof(wattrs));
+ memset(&gcd,0,sizeof(gcd));
+ memset(&label,0,sizeof(label));
+ memset(boxes,0,sizeof(boxes));
+
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = false;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = isv?_("VKern By Classes..."):_("Kern By Classes...");
+ wattrs.is_dlg = false;
+ pos.x = pos.y = 0;
+ temp = 40 + 300*GIntGetResource(_NUM_Buttonsize)/GGadgetScale(100);
+ if ( kcl_width<temp ) kcl_width = temp;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,kcl_width));
+ pos.height = GDrawPointsToPixels(NULL,KCL_Height);
+ kcld->gw = GDrawCreateTopWindow(NULL,&pos,kcl_e_h,kcld,&wattrs);
+
+ gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 5;
+ gcd[0].gd.pos.width = kcl_width-10; gcd[0].gd.pos.height = 7*12+10;
+ gcd[0].gd.flags = gg_visible | gg_enabled | gg_list_multiplesel;
+ gcd[0].gd.cid = CID_List;
+ gcd[0].gd.u.list = KCLookupSubtableList(sf,isv);
+ gcd[0].gd.handle_controlevent = KCL_SelChanged;
+ gcd[0].creator = GListCreate;
+ varray[0] = &gcd[0]; varray[1] = NULL;
+
+ gcd[1].gd.pos.x = 10; gcd[1].gd.pos.y = gcd[0].gd.pos.y+gcd[0].gd.pos.height+4;
+ gcd[1].gd.flags = gg_visible | gg_enabled;
+ label[1].text = (unichar_t *) S_("KernClass|_New Lookup...");
+ label[1].text_is_1byte = true;
+ label[1].text_in_resource = true;
+ gcd[1].gd.label = &label[1];
+ gcd[1].gd.cid = CID_New;
+ gcd[1].gd.handle_controlevent = KCL_New;
+ gcd[1].creator = GButtonCreate;
+ harray[0] = GCD_Glue; harray[1] = &gcd[1];
+
+ gcd[2].gd.pos.x = 20+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor); gcd[2].gd.pos.y = gcd[1].gd.pos.y;
+ gcd[2].gd.flags = gg_visible;
+ label[2].text = (unichar_t *) _("_Delete");
+ label[2].text_is_1byte = true;
+ label[2].text_in_resource = true;
+ gcd[2].gd.label = &label[2];
+ gcd[2].gd.cid = CID_Delete;
+ gcd[2].gd.handle_controlevent = KCL_Delete;
+ gcd[2].creator = GButtonCreate;
+ harray[2] = GCD_Glue; harray[3] = &gcd[2];
+
+ gcd[3].gd.pos.x = -10; gcd[3].gd.pos.y = gcd[1].gd.pos.y;
+ gcd[3].gd.pos.width = -1;
+ gcd[3].gd.flags = gg_visible;
+ label[3].text = (unichar_t *) _("_Edit...");
+ label[3].text_is_1byte = true;
+ label[3].text_in_resource = true;
+ gcd[3].gd.label = &label[3];
+ gcd[3].gd.cid = CID_Edit;
+ gcd[3].gd.handle_controlevent = KCL_Edit;
+ gcd[3].creator = GButtonCreate;
+ harray[4] = GCD_Glue; harray[5] = &gcd[3]; harray[6] = GCD_Glue; harray[7] = NULL;
+
+ boxes[0].gd.flags = gg_enabled|gg_visible;
+ boxes[0].gd.u.boxelements = harray;
+ boxes[0].creator = GHBoxCreate;
+ varray[2] = &boxes[0]; varray[3] = NULL;
+
+ gcd[4].gd.pos.x = 10; gcd[4].gd.pos.y = gcd[1].gd.pos.y+28;
+ gcd[4].gd.pos.width = kcl_width-20;
+ gcd[4].gd.flags = gg_visible;
+ gcd[4].creator = GLineCreate;
+ varray[4] = &gcd[4]; varray[5] = NULL;
+
+ gcd[5].gd.pos.x = (kcl_width-GIntGetResource(_NUM_Buttonsize))/2; gcd[5].gd.pos.y = gcd[4].gd.pos.y+7;
+ gcd[5].gd.flags = gg_visible|gg_enabled|gg_but_default|gg_but_cancel;
+ label[5].text = (unichar_t *) _("_Done");
+ label[5].text_is_1byte = true;
+ label[5].text_in_resource = true;
+ gcd[5].gd.label = &label[5];
+ gcd[5].gd.handle_controlevent = KCL_Done;
+ gcd[5].creator = GButtonCreate;
+ harray2[0] = GCD_Glue; harray2[1] = &gcd[5]; harray2[2] = GCD_Glue; harray2[3] = NULL;
+
+ boxes[1].gd.flags = gg_enabled|gg_visible;
+ boxes[1].gd.u.boxelements = harray2;
+ boxes[1].creator = GHBoxCreate;
+ varray[6] = &boxes[1]; varray[7] = NULL; varray[8] = NULL;
+
+ boxes[2].gd.pos.x = boxes[0].gd.pos.y = 2;
+ boxes[2].gd.flags = gg_enabled|gg_visible;
+ boxes[2].gd.u.boxelements = varray;
+ boxes[2].creator = GHVGroupCreate;
+
+ GGadgetsCreate(kcld->gw,&boxes[2]);
+ GHVBoxSetExpandableRow(boxes[2].ret,0);
+ GHVBoxSetExpandableCol(boxes[0].ret,gb_expandgluesame);
+ GHVBoxSetExpandableCol(boxes[1].ret,gb_expandgluesame);
+ GDrawSetVisible(kcld->gw,true);
+}
+
+void KCLD_End(KernClassListDlg *kcld) {
+ KernClassDlg *kcd, *kcdnext;
+ for ( kcd= kcld->sf->kcd; kcd!=NULL; kcd=kcdnext ) {
+ kcdnext = kcd->next;
+ KC_DoCancel(kcd);
+ }
+ if ( kcld==NULL )
+return;
+ GDrawDestroyWindow(kcld->gw);
+}
+
+void KCLD_MvDetach(KernClassListDlg *kcld,MetricsView *mv) {
+ if ( kcld==NULL )
+return;
+}
+
+/* ************************************************************************** */
+/* *************************** Kern Pair Dialog **************************** */
+/* ************************************************************************** */
+
+void KernPairD(SplineFont *sf,SplineChar *sc1,SplineChar *sc2,int isv) {
+ GRect pos;
+ GWindowAttrs wattrs;
+ KernClassDlg kcd;
+ GWindow gw;
+ int gid;
+
+ if ( sc1==NULL ) {
+ FontView *fv = sf->fv;
+ int start = fv->rowoff*fv->colcnt, end = start+fv->rowcnt*fv->colcnt;
+ int i;
+ for ( i=start; i<end && i<fv->map->enccount; ++i )
+ if ( (gid=fv->map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
+ (isv ? sf->glyphs[gid]->vkerns : sf->glyphs[gid]->kerns)!=NULL )
+ break;
+ if ( i==end || i==fv->map->enccount ) {
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( (gid=fv->map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
+ (isv ? sf->glyphs[gid]->vkerns : sf->glyphs[gid]->kerns)!=NULL )
+ break;
+ }
+ if ( i==fv->map->enccount ) {
+ for ( i=start; i<end && i<fv->map->enccount; ++i )
+ if ( (gid=fv->map->map[i])!=-1 && sf->glyphs[gid]!=NULL )
+ break;
+ if ( i==end || i==fv->map->enccount ) {
+ for ( i=0; i<fv->map->enccount; ++i )
+ if ( (gid=fv->map->map[i])!=-1 && sf->glyphs[gid]!=NULL )
+ break;
+ }
+ }
+ if ( i!=fv->map->enccount )
+ sc1 = sf->glyphs[gid];
+ }
+ if ( sc2==NULL && sc1!=NULL && (isv ? sc1->vkerns : sc1->kerns)!=NULL )
+ sc2 = (isv ? sc1->vkerns : sc1->kerns)->sc;
+
+ memset(&kcd,0,sizeof(kcd));
+ kcd.sf = sf;
+ kcd.scf = sc1;
+ kcd.scs = sc2;
+ kcd.isv = isv;
+ kcd.iskernpair = true;
+
+ memset(&wattrs,0,sizeof(wattrs));
+
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = true;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Kern Pair Closeup...");
+ wattrs.is_dlg = true;
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,KC_Width));
+ pos.height = GDrawPointsToPixels(NULL,KC_Height);
+ kcd.gw = gw = GDrawCreateTopWindow(NULL,&pos,kcd_e_h,&kcd,&wattrs);
+ kcd.canceldrop = GDrawPointsToPixels(gw,KC_CANCELDROP);
+
+
+ kcd.kw = gw;
+ FillShowKerningWindow(&kcd, false, kcd.sf);
+
+ if ( sc1!=NULL ) {
+ unichar_t *utemp;
+ GGadgetSetTitle(GWidgetGetControl(kcd.gw,CID_First),(utemp=uc_copy(sc1->name)));
+ free(utemp);
+ KPD_BuildKernList(&kcd);
+ KCD_UpdateGlyph(&kcd,0);
+ }
+ if ( sc2!=NULL ) {
+ unichar_t *utemp;
+ GGadgetSetTitle(GWidgetGetControl(kcd.gw,CID_Second),(utemp=uc_copy(sc2->name)));
+ free(utemp);
+ KCD_UpdateGlyph(&kcd,1);
+ KPD_PairSearch(&kcd);
+ }
+
+ GDrawSetVisible(kcd.gw,true);
+ while ( !kcd.done )
+ GDrawProcessOneEvent(NULL);
+ GDrawSetUserData(kcd.gw,NULL);
+ GDrawDestroyWindow(kcd.gw);
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+int KernClassContains(KernClass *kc, char *name1, char *name2, int ordered ) {
+ int infirst=0, insecond=0, scpos1=0, kwpos1=0, scpos2=0, kwpos2=0;
+ int i;
+
+ for ( i=1; i<kc->first_cnt; ++i ) {
+ if ( PSTContains(kc->firsts[i],name1) ) {
+ scpos1 = i;
+ if ( ++infirst>=3 ) /* The name occurs twice??? */
+ break;
+ } else if ( PSTContains(kc->firsts[i],name2) ) {
+ kwpos1 = i;
+ if ( (infirst+=2)>=3 )
+ break;
+ }
+ }
+ if ( infirst==0 || infirst>3 )
+return( 0 );
+ for ( i=1; i<kc->second_cnt; ++i ) {
+ if ( PSTContains(kc->seconds[i],name1) ) {
+ scpos2 = i;
+ if ( ++insecond>=3 )
+ break;
+ } else if ( PSTContains(kc->seconds[i],name2) ) {
+ kwpos2 = i;
+ if ( (insecond+=2)>=3 )
+ break;
+ }
+ }
+ if ( insecond==0 || insecond>3 )
+return( 0 );
+ if ( (infirst&1) && (insecond&2) ) {
+ if ( kc->offsets[scpos1*kc->second_cnt+kwpos2]!=0 )
+return( kc->offsets[scpos1*kc->second_cnt+kwpos2] );
+ }
+ if ( !ordered ) {
+ if ( (infirst&2) && (insecond&1) ) {
+ if ( kc->offsets[kwpos1*kc->second_cnt+scpos2]!=0 )
+return( kc->offsets[kwpos1*kc->second_cnt+scpos2] );
+ }
+ }
+return( 0 );
+}
+
+/* ************************************************************************** */
+/* ******************************* kerning ****************************** */
+/* ************************************************************************** */
+
+static int KCFindName(char *name, char **classnames, int cnt ) {
+ int i;
+ char *pt, *end, ch;
+
+ for ( i=0; i<cnt; ++i ) {
+ if ( classnames[i]==NULL )
+ continue;
+ for ( pt = classnames[i]; *pt; pt=end+1 ) {
+ end = strchr(pt,' ');
+ if ( end==NULL ) end = pt+strlen(pt);
+ ch = *end;
+ *end = '\0';
+ if ( strcmp(pt,name)==0 ) {
+ *end = ch;
+return( i );
+ }
+ *end = ch;
+ if ( ch=='\0' )
+ break;
+ }
+ }
+return( 0 );
+}
+
+int KCFindIndex(KernClass *kc,char *name1, char *name2) {
+ int f,l;
+
+ f = KCFindName(name1,kc->firsts,kc->first_cnt);
+ l = KCFindName(name2,kc->seconds,kc->second_cnt);
+ if ( (f!=0 || kc->firsts[0]!=NULL) && l!=0 )
+return( f*kc->second_cnt+l );
+
+return( -1 );
+}
+
+KernClass *SFFindKernClass(SplineFont *sf,SplineChar *first,SplineChar *last,
+ int *index,int allow_zero) {
+ int i,f,l;
+ KernClass *kc;
+
+ for ( i=0; i<=allow_zero; ++i ) {
+ for ( kc=sf->kerns; kc!=NULL; kc=kc->next ) {
+ f = KCFindName(first->name,kc->firsts,kc->first_cnt);
+ l = KCFindName(last->name,kc->seconds,kc->second_cnt);
+ if ( (f!=0 || kc->firsts[0]!=NULL) && l!=0 ) {
+ if ( i || kc->offsets[f*kc->second_cnt+l]!=0 ) {
+ *index = f*kc->second_cnt+l;
+return( kc );
+ }
+ }
+ }
+ }
+return( NULL );
+}
+
+KernClass *SFFindVKernClass(SplineFont *sf,SplineChar *first,SplineChar *last,
+ int *index,int allow_zero) {
+ int i,f,l;
+ KernClass *kc;
+
+ for ( i=0; i<=allow_zero; ++i ) {
+ for ( kc=sf->vkerns; kc!=NULL; kc=kc->next ) {
+ f = KCFindName(first->name,kc->firsts,kc->first_cnt);
+ l = KCFindName(last->name,kc->seconds,kc->second_cnt);
+ if ( (f!=0 || kc->firsts[0]!=NULL) && l!=0 ) {
+ if ( i || kc->offsets[f*kc->second_cnt+l]!=0 ) {
+ *index = f*kc->second_cnt+l;
+return( kc );
+ }
+ }
+ }
+ }
+return( NULL );
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/lff.opt b/Build/source/libs/luafontforge/fontforge/fontforge/lff.opt
new file mode 100644
index 00000000000..d8925e52fde
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/lff.opt
@@ -0,0 +1 @@
+[-.libs]libfontforge.exe/share
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/lookups.c b/Build/source/libs/luafontforge/fontforge/fontforge/lookups.c
new file mode 100644
index 00000000000..6ed72fe40af
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/lookups.c
@@ -0,0 +1,6916 @@
+/* Copyright (C) 2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaeditui.h"
+#include <chardata.h>
+#include <utype.h>
+#include <ustring.h>
+#include <math.h>
+#include <locale.h>
+#include <stdlib.h>
+#include "ttf.h"
+#include <gkeysym.h>
+
+static int uint32_cmp(const void *_ui1, const void *_ui2) {
+ if ( *(uint32 *) _ui1 > *(uint32 *)_ui2 )
+return( 1 );
+ if ( *(uint32 *) _ui1 < *(uint32 *)_ui2 )
+return( -1 );
+
+return( 0 );
+}
+
+static int lang_cmp(const void *_ui1, const void *_ui2) {
+ /* The default language is magic, and should come first in the list even */
+ /* if that is not true alphabetical order */
+ if ( *(uint32 *) _ui1 == DEFAULT_LANG )
+return( -1 );
+ if ( *(uint32 *) _ui2 == DEFAULT_LANG )
+return( 1 );
+
+ if ( *(uint32 *) _ui1 > *(uint32 *)_ui2 )
+return( 1 );
+ if ( *(uint32 *) _ui1 < *(uint32 *)_ui2 )
+return( -1 );
+
+return( 0 );
+}
+
+int FeatureTagInFeatureScriptList(uint32 tag, FeatureScriptLangList *fl) {
+
+ while ( fl!=NULL ) {
+ if ( fl->featuretag==tag )
+return( true );
+ fl = fl->next;
+ }
+return( false );
+}
+
+int ScriptInFeatureScriptList(uint32 script, FeatureScriptLangList *fl) {
+ struct scriptlanglist *sl;
+
+ while ( fl!=NULL ) {
+ for ( sl=fl->scripts; sl!=NULL; sl=sl->next ) {
+ if ( sl->script == script )
+return( true );
+ }
+ fl = fl->next;
+ }
+return( false );
+}
+
+int FeatureScriptTagInFeatureScriptList(uint32 feature, uint32 script, FeatureScriptLangList *fl) {
+ struct scriptlanglist *sl;
+
+ while ( fl!=NULL ) {
+ if ( fl->featuretag == feature ) {
+ for ( sl=fl->scripts; sl!=NULL; sl=sl->next ) {
+ if ( sl->script == script )
+return( true );
+ }
+ }
+ fl = fl->next;
+ }
+return( false );
+}
+
+int DefaultLangTagInOneScriptList(struct scriptlanglist *sl) {
+ int l;
+
+ for ( l=0; l<sl->lang_cnt; ++l ) {
+ uint32 lang = l<MAX_LANG ? sl->langs[l] : sl->morelangs[l-MAX_LANG];
+ if ( lang==DEFAULT_LANG )
+return( true );
+ }
+return( false );
+}
+
+struct scriptlanglist *DefaultLangTagInScriptList(struct scriptlanglist *sl, int DFLT_ok) {
+
+ while ( sl!=NULL ) {
+ if ( DFLT_ok || sl->script!=DEFAULT_SCRIPT ) {
+ if ( DefaultLangTagInOneScriptList(sl))
+return( sl );
+ }
+ sl = sl->next;
+ }
+return( NULL );
+}
+
+uint32 *SFScriptsInLookups(SplineFont *sf,int gpos) {
+ /* Presumes that either SFFindUnusedLookups or SFFindClearUnusedLookupBits */
+ /* has been called first */
+ /* Since MS will sometimes ignore a script if it isn't found in both */
+ /* GPOS and GSUB we want to return the same script list no matter */
+ /* what the setting of gpos ... so we totally ignore that argument */
+ /* and always look at both sets of lookups */
+
+/* Sergey Malkin from MicroSoft tells me:
+ Each shaping engine in Uniscribe can decide on its requirements for
+ layout tables - some of them require both GSUB and GPOS, in some cases
+ any table present is enough, or it can work without any table.
+
+ Sometimes, purpose of the check is to determine if font is supporting
+ particular script - if required tables are not there font is just
+ rejected by this shaping engine. Sometimes, shaping engine can not just
+ reject the font because there are fonts using older shaping technologies
+ we still have to support, so it uses some logic when to fallback to
+ legacy layout code.
+
+ In your case this is Hebrew, where both tables are required to use
+ OpenType processing. Arabic requires both tables too, Latin requires
+ GSUB to execute GPOS. But in general, if you have both tables you should
+ be safe with any script to get fully featured OpenType shaping.
+
+In other words, if we have a Hebrew font with just GPOS features they won't work,
+and MS will not use the font at all. We must add a GSUB table. In the unlikely
+event that we had a hebrew font with only GSUB it would not work either.
+
+So if we want our lookups to have a chance of executing under Uniscribe we
+better make sure that both tables have the same script set.
+
+(Sergey says we could optimize a little: A Latin GSUB table will run without
+a GPOS, but he says the GPOS won't work without a GSUB.)
+*/
+ int cnt=0, tot=0, i;
+ uint32 *scripts = NULL;
+ OTLookup *test;
+ FeatureScriptLangList *fl;
+ struct scriptlanglist *sl;
+
+ /* So here always give scripts for both (see comment above) no */
+ /* matter what they asked for */
+ for ( gpos=0; gpos<2; ++gpos ) {
+ for ( test = gpos ? sf->gpos_lookups : sf->gsub_lookups; test!=NULL; test = test->next ) {
+ if ( test->unused )
+ continue;
+ for ( fl=test->features; fl!=NULL; fl=fl->next ) {
+ if ( fl->ismac )
+ continue;
+ for ( sl=fl->scripts ; sl!=NULL; sl=sl->next ) {
+ for ( i=0; i<cnt; ++i ) {
+ if ( sl->script==scripts[i] )
+ break;
+ }
+ if ( i==cnt ) {
+ if ( cnt>=tot )
+ scripts = grealloc(scripts,(tot+=10)*sizeof(uint32));
+ scripts[cnt++] = sl->script;
+ }
+ }
+ }
+ }
+ }
+
+ if ( cnt==0 )
+return( NULL );
+
+ /* We want our scripts in alphabetic order */
+ qsort(scripts,cnt,sizeof(uint32),uint32_cmp);
+ /* add a 0 entry to mark the end of the list */
+ if ( cnt>=tot )
+ scripts = grealloc(scripts,(tot+1)*sizeof(uint32));
+ scripts[cnt] = 0;
+return( scripts );
+}
+
+uint32 *SFLangsInScript(SplineFont *sf,int gpos,uint32 script) {
+ /* However, the language lists (I think) are distinct */
+ /* But giving a value of -1 for gpos will give us the set of languages in */
+ /* both tables (for this script) */
+ int cnt=0, tot=0, i, g, l;
+ uint32 *langs = NULL;
+ OTLookup *test;
+ FeatureScriptLangList *fl;
+ struct scriptlanglist *sl;
+
+ for ( g=0; g<2; ++g ) {
+ if (( gpos==0 && g==1 ) || ( gpos==1 && g==0 ))
+ continue;
+ for ( test = gpos ? sf->gpos_lookups : sf->gsub_lookups; test!=NULL; test = test->next ) {
+ if ( test->unused )
+ continue;
+ for ( fl=test->features; fl!=NULL; fl=fl->next ) {
+ for ( sl=fl->scripts ; sl!=NULL; sl=sl->next ) {
+ if ( sl->script==script ) {
+ for ( l=0; l<sl->lang_cnt; ++l ) {
+ int lang;
+ if ( l<MAX_LANG )
+ lang = sl->langs[l];
+ else
+ lang = sl->morelangs[l-MAX_LANG];
+ for ( i=0; i<cnt; ++i ) {
+ if ( lang==langs[i] )
+ break;
+ }
+ if ( i==cnt ) {
+ if ( cnt>=tot )
+ langs = grealloc(langs,(tot+=10)*sizeof(uint32));
+ langs[cnt++] = lang;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( cnt==0 ) {
+ /* We add dummy script entries. Because Uniscribe will refuse to */
+ /* process some scripts if they don't have an entry in both GPOS */
+ /* an GSUB. So if a script appears in either table, force it to */
+ /* appear in both. That means we can get scripts with no lookups */
+ /* and hence no languages. It seems that Uniscribe doesn't like */
+ /* that either. So give each such script a dummy default language */
+ /* entry. This is what VOLT does */
+ langs = gcalloc(2,sizeof(uint32));
+ langs[0] = DEFAULT_LANG;
+return( langs );
+ }
+
+ /* We want our languages in alphabetic order */
+ qsort(langs,cnt,sizeof(uint32),lang_cmp);
+ /* add a 0 entry to mark the end of the list */
+ if ( cnt>=tot )
+ langs = grealloc(langs,(tot+1)*sizeof(uint32));
+ langs[cnt] = 0;
+return( langs );
+}
+
+uint32 *SFFeaturesInScriptLang(SplineFont *sf,int gpos,uint32 script,uint32 lang) {
+ int cnt=0, tot=0, i, l, isg;
+ uint32 *features = NULL;
+ OTLookup *test;
+ FeatureScriptLangList *fl;
+ struct scriptlanglist *sl;
+
+ if ( sf->cidmaster ) sf=sf->cidmaster;
+ for ( isg = 0; isg<2; ++isg ) {
+ if ( gpos!=-1 && isg!=gpos )
+ continue;
+ for ( test = isg ? sf->gpos_lookups : sf->gsub_lookups; test!=NULL; test = test->next ) {
+ if ( test->unused )
+ continue;
+ for ( fl=test->features; fl!=NULL; fl=fl->next ) {
+ if ( fl->ismac )
+ continue;
+ if ( script==0xffffffff ) {
+ for ( i=0; i<cnt; ++i ) {
+ if ( fl->featuretag==features[i] )
+ break;
+ }
+ if ( i==cnt ) {
+ if ( cnt>=tot )
+ features = grealloc(features,(tot+=10)*sizeof(uint32));
+ features[cnt++] = fl->featuretag;
+ }
+ } else for ( sl=fl->scripts ; sl!=NULL; sl=sl->next ) {
+ if ( sl->script==script ) {
+ for ( l=0; l<sl->lang_cnt; ++l ) {
+ int testlang;
+ if ( l<MAX_LANG )
+ testlang = sl->langs[l];
+ else
+ testlang = sl->morelangs[l-MAX_LANG];
+ if ( testlang==lang ) {
+ for ( i=0; i<cnt; ++i ) {
+ if ( fl->featuretag==features[i] )
+ break;
+ }
+ if ( i==cnt ) {
+ if ( cnt>=tot )
+ features = grealloc(features,(tot+=10)*sizeof(uint32));
+ features[cnt++] = fl->featuretag;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( sf->design_size!=0 && gpos ) {
+ /* The 'size' feature is like no other. It has no lookups and so */
+ /* we will never find it in the normal course of events. If the */
+ /* user has specified a design size, then every script/lang combo */
+ /* gets a 'size' feature which contains no lookups but feature */
+ /* params */
+ if ( cnt>=tot )
+ features = grealloc(features,(tot+=2)*sizeof(uint32));
+ features[cnt++] = CHR('s','i','z','e');
+ }
+
+ if ( cnt==0 )
+return( gcalloc(1,sizeof(uint32)) );
+
+ /* We don't care if our features are in alphabetical order here */
+ /* all that matters is whether the complete list of features is */
+ /* ordering here would be irrelevant */
+ /* qsort(features,cnt,sizeof(uint32),uint32_cmp); */
+
+ /* add a 0 entry to mark the end of the list */
+ if ( cnt>=tot )
+ features = grealloc(features,(tot+1)*sizeof(uint32));
+ features[cnt] = 0;
+return( features );
+}
+
+OTLookup **SFLookupsInScriptLangFeature(SplineFont *sf,int gpos,uint32 script,uint32 lang, uint32 feature) {
+ int cnt=0, tot=0, l;
+ OTLookup **lookups = NULL;
+ OTLookup *test;
+ FeatureScriptLangList *fl;
+ struct scriptlanglist *sl;
+
+ for ( test = gpos ? sf->gpos_lookups : sf->gsub_lookups; test!=NULL; test = test->next ) {
+ if ( test->unused )
+ continue;
+ for ( fl=test->features; fl!=NULL; fl=fl->next ) {
+ if ( fl->featuretag==feature ) {
+ for ( sl=fl->scripts ; sl!=NULL; sl=sl->next ) {
+ if ( sl->script==script ) {
+ for ( l=0; l<sl->lang_cnt; ++l ) {
+ int testlang;
+ if ( l<MAX_LANG )
+ testlang = sl->langs[l];
+ else
+ testlang = sl->morelangs[l-MAX_LANG];
+ if ( testlang==lang ) {
+ if ( cnt>=tot )
+ lookups = grealloc(lookups,(tot+=10)*sizeof(OTLookup *));
+ lookups[cnt++] = test;
+ goto found;
+ }
+ }
+ }
+ }
+ }
+ }
+ found:;
+ }
+
+ if ( cnt==0 )
+return( NULL );
+
+ /* lookup order is irrelevant here. might as well leave it in invocation order */
+ /* add a 0 entry to mark the end of the list */
+ if ( cnt>=tot )
+ lookups = grealloc(lookups,(tot+1)*sizeof(OTLookup *));
+ lookups[cnt] = 0;
+return( lookups );
+}
+
+static int LigaturesFirstComponentGID(SplineFont *sf,char *components) {
+ int gid, ch;
+ char *pt;
+
+ for ( pt = components; *pt!='\0' && *pt!=' '; ++pt );
+ ch = *pt; *pt = '\0';
+ gid = SFFindExistingSlot(sf,-1,components);
+ *pt = ch;
+return( gid );
+}
+
+static int PSTValid(SplineFont *sf,PST *pst) {
+ char *start, *pt, ch;
+ int ret;
+
+ switch ( pst->type ) {
+ case pst_position:
+return( true );
+ case pst_pair:
+return( SCWorthOutputting(SFGetChar(sf,-1,pst->u.pair.paired)) );
+ case pst_substitution: case pst_alternate: case pst_multiple:
+ case pst_ligature:
+ for ( start = pst->u.mult.components; *start ; ) {
+ for ( pt=start; *pt && *pt!=' '; ++pt );
+ ch = *pt; *pt = '\0';
+ ret = SCWorthOutputting(SFGetChar(sf,-1,start));
+ *pt = ch;
+ if ( !ret )
+return( false );
+ if ( ch==0 )
+ start = pt;
+ else
+ start = pt+1;
+ }
+ }
+return( true );
+}
+
+SplineChar **SFGlyphsWithPSTinSubtable(SplineFont *sf,struct lookup_subtable *subtable) {
+ uint8 *used = gcalloc(sf->glyphcnt,sizeof(uint8));
+ SplineChar **glyphs, *sc;
+ int i, k, gid, cnt;
+ KernPair *kp;
+ PST *pst;
+ int ispair = subtable->lookup->lookup_type == gpos_pair;
+ int isliga = subtable->lookup->lookup_type == gsub_ligature;
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sc = sf->glyphs[i]) ) {
+ if ( ispair ) {
+ for ( k=0; k<2; ++k ) {
+ for ( kp= k ? sc->kerns : sc->vkerns; kp!=NULL ; kp=kp->next ) {
+ if ( !SCWorthOutputting(kp->sc))
+ continue;
+ if ( kp->subtable == subtable ) {
+ used[i] = true;
+ goto continue_;
+ }
+ }
+ }
+ }
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable == subtable && PSTValid(sf,pst)) {
+ if ( !isliga ) {
+ used[i] = true;
+ goto continue_;
+ } else {
+ gid = LigaturesFirstComponentGID(sf,pst->u.lig.components);
+ pst->u.lig.lig = sc;
+ if ( gid!=-1 )
+ used[gid] = true;
+ /* can't continue here. ffi might be "f+f+i" and "ff+i" */
+ /* and we need to mark both "f" and "ff" as used */
+ }
+ }
+ }
+ continue_: ;
+ }
+
+ for ( i=cnt=0 ; i<sf->glyphcnt; ++i )
+ if ( used[i] )
+ ++cnt;
+
+ if ( cnt==0 ) {
+ free(used);
+return( NULL );
+ }
+ glyphs = galloc((cnt+1)*sizeof(SplineChar *));
+ for ( i=cnt=0 ; i<sf->glyphcnt; ++i ) {
+ if ( used[i] )
+ glyphs[cnt++] = sf->glyphs[i];
+ }
+ glyphs[cnt] = NULL;
+ free(used);
+return( glyphs );
+}
+
+SplineChar **SFGlyphsWithLigatureinLookup(SplineFont *sf,struct lookup_subtable *subtable) {
+ uint8 *used = gcalloc(sf->glyphcnt,sizeof(uint8));
+ SplineChar **glyphs, *sc;
+ int i, cnt;
+ PST *pst;
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sc = sf->glyphs[i]) ) {
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable == subtable ) {
+ used[i] = true;
+ goto continue_;
+ }
+ }
+ continue_: ;
+ }
+
+ for ( i=cnt=0 ; i<sf->glyphcnt; ++i )
+ if ( used[i] )
+ ++cnt;
+
+ if ( cnt==0 ) {
+ free(used);
+return( NULL );
+ }
+
+ glyphs = galloc((cnt+1)*sizeof(SplineChar *));
+ for ( i=cnt=0 ; i<sf->glyphcnt; ++i ) {
+ if ( used[i] )
+ glyphs[cnt++] = sf->glyphs[i];
+ }
+ glyphs[cnt] = NULL;
+ free(used);
+return( glyphs );
+}
+
+void SFFindUnusedLookups(SplineFont *sf) {
+ OTLookup *test;
+ struct lookup_subtable *sub;
+ int gpos;
+ AnchorClass *ac;
+ AnchorPoint *ap;
+ SplineChar *sc;
+ KernPair *kp;
+ PST *pst;
+ int k,gid,isv;
+ SplineFont *_sf = sf;
+
+ if ( _sf->cidmaster ) _sf = _sf->cidmaster;
+
+ /* Some things are obvious. If a subtable consists of a kernclass or some */
+ /* such, then obviously it is used. But more distributed info takes more */
+ /* work. So mark anything easy as used, and anything difficult as unused */
+ /* We'll work on the difficult things later */
+ for ( gpos=0; gpos<2; ++gpos ) {
+ for ( test = gpos ? _sf->gpos_lookups : _sf->gsub_lookups; test!=NULL; test = test->next ) {
+ for ( sub = test->subtables; sub!=NULL; sub=sub->next ) {
+ if ( sub->kc!=NULL || sub->fpst!=NULL || sub->sm!=NULL ) {
+ sub->unused = false;
+ continue;
+ }
+ sub->unused = true;
+ /* We'll turn the following bit back on if there turns out */
+ /* to be an anchor class attached to it -- that is subtly */
+ /* different than being unused -- unused will be set if all */
+ /* acs are unused, this bit will be on if there are unused */
+ /* classes that still refer to us. */
+ sub->anchor_classes = false;
+ }
+ }
+ }
+
+ /* To be useful an anchor class must have both at least one base and one mark */
+ /* (for cursive anchors that means at least one entry and at least one exit) */
+ /* Start by assuming the worst */
+ for ( ac = _sf->anchor; ac!=NULL; ac=ac->next )
+ ac->has_mark = ac->has_base = false;
+
+ /* Ok, for each glyph, look at all lookups (or anchor classes) it affects */
+ /* and mark the appropriate parts of them as used */
+ k = 0;
+ do {
+ sf = _sf->subfontcnt==0 ? _sf : _sf->subfonts[k];
+ for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( SCWorthOutputting(sc = sf->glyphs[gid]) ) {
+ for ( ap=sc->anchor; ap!=NULL; ap=ap->next ) {
+ switch ( ap->type ) {
+ case at_mark: case at_centry:
+ ap->anchor->has_mark = true;
+ break;
+ case at_basechar: case at_baselig: case at_basemark:
+ case at_cexit:
+ ap->anchor->has_base = true;
+ break;
+ }
+ }
+ for ( isv=0; isv<2; ++isv ) {
+ for ( kp= isv ? sc->kerns : sc->vkerns ; kp!=NULL; kp=kp->next ) {
+ if ( SCWorthOutputting(kp->sc))
+ kp->subtable->unused = false;
+ }
+ }
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable==NULL )
+ continue;
+ if ( !PSTValid(sf,pst))
+ continue;
+ pst->subtable->unused = false;
+ }
+ }
+ ++k;
+ } while ( k<_sf->subfontcnt );
+
+ /* Finally for any anchor class that has both a mark and a base then it is */
+ /* used, and its lookup is also used */
+ /* Also, even if unused, as long as the anchor class exists we must keep */
+ /* the subtable around */
+ for ( ac = _sf->anchor; ac!=NULL; ac=ac->next ) {
+ ac->subtable->anchor_classes = true;
+ if ( ac->has_mark && ac->has_base )
+ ac->subtable->unused = false;
+ }
+
+ /* Now for each lookup, a lookup is unused if ALL subtables are unused */
+ for ( gpos=0; gpos<2; ++gpos ) {
+ for ( test = gpos ? _sf->gpos_lookups : _sf->gsub_lookups; test!=NULL; test = test->next ) {
+ test->unused = test->empty = true;
+ for ( sub=test->subtables; sub!=NULL; sub=sub->next ) {
+ if ( !sub->unused )
+ test->unused = false;
+ if ( !sub->unused && !sub->anchor_classes ) {
+ test->empty = false;
+ break;
+ }
+ }
+ }
+ }
+}
+
+void SFFindClearUnusedLookupBits(SplineFont *sf) {
+ OTLookup *test;
+ int gpos;
+
+ for ( gpos=0; gpos<2; ++gpos ) {
+ for ( test = gpos ? sf->gpos_lookups : sf->gsub_lookups; test!=NULL; test = test->next ) {
+ test->unused = false;
+ test->empty = false;
+ test->def_lang_checked = false;
+ }
+ }
+}
+
+static void SFRemoveAnchorPointsOfAC(SplineFont *sf,AnchorClass *ac) {
+ int gid;
+ SplineChar *sc;
+ AnchorPoint *ap, *prev, *next;
+
+ for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( (sc = sf->glyphs[gid])!=NULL ) {
+ for ( prev=NULL, ap=sc->anchor; ap!=NULL; ap=next ) {
+ next = ap->next;
+ if ( ap->anchor!=ac )
+ prev = ap;
+ else {
+ if ( prev==NULL )
+ sc->anchor = next;
+ else
+ prev->next = next;
+ ap->next = NULL;
+ AnchorPointsFree(ap);
+ }
+ }
+ }
+}
+
+static void RemoveNestedReferences(SplineFont *sf,int isgpos,OTLookup *dying) {
+ OTLookup *otl;
+ struct lookup_subtable *sub;
+ int i,j,k;
+
+ for ( otl = isgpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl = otl->next ) {
+ if ( otl->lookup_type==morx_context ) {
+ for ( sub=otl->subtables; sub!=NULL; sub=sub->next ) {
+ ASM *sm = sub->sm;
+ if ( sm->type==asm_context ) {
+ for ( i=0; i<sm->state_cnt*sm->class_cnt; ++i ) {
+ struct asm_state *state = &sm->state[i];
+ if ( state->u.context.mark_lookup == otl )
+ state->u.context.mark_lookup = NULL;
+ if ( state->u.context.cur_lookup == otl )
+ state->u.context.cur_lookup = NULL;
+ }
+ }
+ }
+ /* Reverse chaining tables do not reference lookups. The match pattern*/
+ /* is a (exactly one) coverage table, and each glyph in that table */
+ /* as an inline replacement. There is no lookup to do the replacement*/
+ /* (so we ignore it here) */
+ } else if ( otl->lookup_type==gsub_context || otl->lookup_type==gsub_contextchain ||
+ otl->lookup_type==gpos_context || otl->lookup_type==gpos_contextchain ) {
+ for ( sub=otl->subtables; sub!=NULL; sub=sub->next ) {
+ FPST *fpst = sub->fpst;
+ for ( i=0; i<fpst->rule_cnt; ++i ) {
+ for ( j=0; j<fpst->rules[i].lookup_cnt; ++j ) {
+ if ( fpst->rules[i].lookups[j].lookup == otl ) {
+ for ( k=j+1; k<fpst->rules[i].lookup_cnt; ++k )
+ fpst->rules[i].lookups[k-1] = fpst->rules[i].lookups[k];
+ --fpst->rules[i].lookup_cnt;
+ --j;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void SFRemoveUnusedLookupSubTables(SplineFont *sf,
+ int remove_incomplete_anchorclasses,
+ int remove_unused_lookups) {
+ int gpos;
+ struct lookup_subtable *sub, *subnext, *prev;
+ AnchorClass *ac, *acprev, *acnext;
+ OTLookup *otl, *otlprev, *otlnext;
+
+ otlprev = NULL;
+ /* Presumes someone has called SFFindUnusedLookups first */
+
+ if ( remove_incomplete_anchorclasses ) {
+ for ( acprev=NULL, ac=sf->anchor; ac!=NULL; ac=acnext ) {
+ acnext = ac->next;
+ if ( ac->has_mark && ac->has_base )
+ acprev = ac;
+ else {
+ SFRemoveAnchorPointsOfAC(sf,ac);
+ ac->next = NULL;
+ AnchorClassesFree(ac);
+ if ( acprev==NULL )
+ sf->anchor = acnext;
+ else
+ acprev = acnext;
+ }
+ }
+ }
+
+ for ( gpos=0; gpos<2; ++gpos ) {
+ for ( otl = gpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl = otlnext ) {
+ otlnext = otl->next;
+ if ( remove_unused_lookups && (otl->empty ||
+ (otl->unused && remove_incomplete_anchorclasses)) ) {
+ if ( otlprev!=NULL )
+ otlprev->next = otlnext;
+ else if ( gpos )
+ sf->gpos_lookups = otlnext;
+ else
+ sf->gsub_lookups = otlnext;
+ RemoveNestedReferences(sf,gpos,otl);
+ OTLookupFree(otl);
+ } else {
+ for ( prev=NULL, sub=otl->subtables; sub!=NULL; sub=subnext ) {
+ subnext = sub->next;
+ if ( sub->unused &&
+ (!sub->anchor_classes ||
+ remove_incomplete_anchorclasses )) {
+ if ( prev==NULL )
+ otl->subtables = subnext;
+ else
+ prev->next = subnext;
+ free(sub->subtable_name);
+ chunkfree(sub,sizeof(*sub));
+ } else
+ prev = sub;
+ }
+ }
+ }
+ }
+}
+
+void SFRemoveLookupSubTable(SplineFont *sf,struct lookup_subtable *sub) {
+ OTLookup *otl = sub->lookup;
+ struct lookup_subtable *subprev, *subtest;
+
+ if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
+
+ if ( sub->sm!=NULL ) {
+ ASM *prev = NULL, *test;
+ for ( test=sf->sm; test!=NULL && test!=sub->sm; prev=test, test=test->next );
+ if ( prev==NULL )
+ sf->sm = sub->sm->next;
+ else
+ prev->next = sub->sm->next;
+ sub->sm->next = NULL;
+ ASMFree(sub->sm);
+ sub->sm = NULL;
+ } else if ( sub->fpst!=NULL ) {
+ FPST *prev = NULL, *test;
+ for ( test=sf->possub; test!=NULL && test!=sub->fpst; prev=test, test=test->next );
+ if ( prev==NULL )
+ sf->possub = sub->fpst->next;
+ else
+ prev->next = sub->fpst->next;
+ sub->fpst->next = NULL;
+ FPSTFree(sub->fpst);
+ sub->fpst = NULL;
+ } else if ( sub->kc!=NULL ) {
+ KernClass *prev = NULL, *test;
+ for ( test=sf->kerns; test!=NULL && test!=sub->kc; prev=test, test=test->next );
+ if ( test!=NULL ) {
+ if ( prev==NULL )
+ sf->kerns = sub->kc->next;
+ else
+ prev->next = sub->kc->next;
+ } else {
+ for ( prev=NULL,test=sf->vkerns; test!=NULL && test!=sub->kc; prev=test, test=test->next );
+ if ( prev==NULL )
+ sf->vkerns = sub->kc->next;
+ else
+ prev->next = sub->kc->next;
+ }
+ sub->kc->next = NULL;
+ KernClassListFree(sub->kc);
+ sub->kc = NULL;
+ } else if ( otl->lookup_type==gpos_cursive || otl->lookup_type==gpos_mark2base ||
+ otl->lookup_type==gpos_mark2ligature || otl->lookup_type==gpos_mark2mark ) {
+ AnchorClass *ac, *acnext;
+ for ( ac=sf->anchor; ac!=NULL; ac=acnext ) {
+ acnext = ac->next;
+ if ( ac->subtable==sub )
+ SFRemoveAnchorClass(sf,ac);
+ }
+ } else {
+ int i,k,v;
+ SplineChar *sc;
+ SplineFont *_sf;
+ PST *pst, *prev, *next;
+ KernPair *kp, *kpprev, *kpnext;
+ k=0;
+ i = 0;
+ do {
+ _sf = sf->subfontcnt==0 ? sf : sf->subfonts[i];
+ for ( i=0; i<_sf->glyphcnt; ++i ) if ( (sc=_sf->glyphs[i])!=NULL ) {
+ for ( pst=sc->possub, prev=NULL ; pst!=NULL; pst=next ) {
+ next = pst->next;
+ if ( pst->subtable==sub ) {
+ if ( prev==NULL )
+ sc->possub = next;
+ else
+ prev->next = next;
+ pst->next = NULL;
+ PSTFree(pst);
+ } else
+ prev = pst;
+ }
+ for ( v=0; v<2; ++v ) {
+ for ( kp=v ? sc->vkerns : sc->kerns, kpprev=NULL ; kp!=NULL; kp=kpnext ) {
+ kpnext = kp->next;
+ if ( kp->subtable==sub ) {
+ if ( kpprev!=NULL )
+ kpprev->next = kpnext;
+ else if ( v )
+ sc->vkerns = kpnext;
+ else
+ sc->kerns = kpnext;
+ kp->next = NULL;
+ KernPairsFree(kp);
+ } else
+ kpprev = kp;
+ }
+ }
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+ }
+
+ subprev = NULL;
+ for ( subtest = otl->subtables; subtest!=NULL && subtest!=sub; subprev = subtest, subtest=subtest->next );
+ if ( subprev==NULL )
+ otl->subtables = sub->next;
+ else
+ subprev->next = sub->next;
+ free(sub->subtable_name);
+ free(sub->suffix);
+ chunkfree(sub,sizeof(struct lookup_subtable));
+}
+
+void SFRemoveLookup(SplineFont *sf,OTLookup *otl) {
+ OTLookup *test, *prev;
+ int isgpos;
+ struct lookup_subtable *sub, *subnext;
+
+ if ( sf->cidmaster ) sf = sf->cidmaster;
+
+ for ( sub = otl->subtables; sub!=NULL; sub=subnext ) {
+ subnext = sub->next;
+ SFRemoveLookupSubTable(sf,sub);
+ }
+
+ for ( prev=NULL, test=sf->gpos_lookups; test!=NULL && test!=otl; prev=test, test=test->next );
+ if ( test==NULL ) {
+ isgpos = false;
+ for ( prev=NULL, test=sf->gsub_lookups; test!=NULL && test!=otl; prev=test, test=test->next );
+ } else
+ isgpos = true;
+ if ( prev!=NULL )
+ prev->next = otl->next;
+ else if ( isgpos )
+ sf->gpos_lookups = otl->next;
+ else
+ sf->gsub_lookups = otl->next;
+
+ RemoveNestedReferences(sf,isgpos,otl);
+
+ otl->next = NULL;
+ OTLookupFree(otl);
+}
+
+struct lookup_subtable *SFFindLookupSubtable(SplineFont *sf,char *name) {
+ int isgpos;
+ OTLookup *otl;
+ struct lookup_subtable *sub;
+
+ if ( sf->cidmaster ) sf = sf->cidmaster;
+
+ if ( name==NULL )
+return( NULL );
+
+ for ( isgpos=0; isgpos<2; ++isgpos ) {
+ for ( otl = isgpos ? sf->gpos_lookups : sf->gsub_lookups ; otl!=NULL; otl=otl->next ) {
+ for ( sub = otl->subtables; sub!=NULL; sub=sub->next ) {
+ if ( strcmp(name,sub->subtable_name)==0 )
+return( sub );
+ }
+ }
+ }
+return( NULL );
+}
+
+struct lookup_subtable *SFFindLookupSubtableAndFreeName(SplineFont *sf,char *name) {
+ struct lookup_subtable *sub = SFFindLookupSubtable(sf,name);
+ free(name);
+return( sub );
+}
+
+OTLookup *SFFindLookup(SplineFont *sf,char *name) {
+ int isgpos;
+ OTLookup *otl;
+
+ if ( sf->cidmaster ) sf = sf->cidmaster;
+
+ if ( name==NULL )
+return( NULL );
+
+ for ( isgpos=0; isgpos<2; ++isgpos ) {
+ for ( otl = isgpos ? sf->gpos_lookups : sf->gsub_lookups ; otl!=NULL; otl=otl->next ) {
+ if ( strcmp(name,otl->lookup_name)==0 )
+return( otl );
+ }
+ }
+return( NULL );
+}
+
+void FListAppendScriptLang(FeatureScriptLangList *fl,uint32 script_tag,uint32 lang_tag) {
+ struct scriptlanglist *sl;
+ int l;
+
+ for ( sl = fl->scripts; sl!=NULL && sl->script!=script_tag; sl=sl->next );
+ if ( sl==NULL ) {
+ sl = chunkalloc(sizeof(struct scriptlanglist));
+ sl->script = script_tag;
+ sl->next = fl->scripts;
+ fl->scripts = sl;
+ }
+ for ( l=0; l<MAX_LANG && l<sl->lang_cnt && sl->langs[l]!=lang_tag; ++l );
+ if ( l>=MAX_LANG && l<sl->lang_cnt ) {
+ while ( l<sl->lang_cnt && sl->morelangs[l-MAX_LANG]!=lang_tag )
+ ++l;
+ }
+ if ( l>=sl->lang_cnt ) {
+ if ( l<MAX_LANG )
+ sl->langs[l] = lang_tag;
+ else {
+ if ( l%MAX_LANG == 0 )
+ sl->morelangs = grealloc(sl->morelangs,l*sizeof(uint32));
+ /* We've just allocated MAX_LANG-1 more than we need */
+ /* so we don't do quite some many allocations */
+ sl->morelangs[l-MAX_LANG] = lang_tag;
+ }
+ ++sl->lang_cnt;
+ }
+}
+
+void FListsAppendScriptLang(FeatureScriptLangList *fl,uint32 script_tag,uint32 lang_tag) {
+ while ( fl!=NULL ) {
+ FListAppendScriptLang(fl,script_tag,lang_tag);
+ fl=fl->next;
+ }
+}
+
+static char *SuffixFromTags(FeatureScriptLangList *fl) {
+ static struct { uint32 tag; char *suffix; } tags2suffix[] = {
+ { CHR('v','r','t','2'), "vert" }, /* Will check for vrt2 later */
+ { CHR('o','n','u','m'), "oldstyle" },
+ { CHR('s','u','p','s'), "superior" },
+ { CHR('s','u','b','s'), "inferior" },
+ { CHR('s','w','s','h'), "swash" },
+ { CHR('f','w','i','d'), "full" },
+ { CHR('h','w','i','d'), "hw" },
+ { 0 }
+ };
+ int i;
+
+ while ( fl!=NULL ) {
+ for ( i=0; tags2suffix[i].tag!=0; ++i )
+ if ( tags2suffix[i].tag==fl->featuretag )
+return( copy( tags2suffix[i].suffix ));
+ fl = fl->next;
+ }
+return( NULL );
+}
+
+
+#ifdef LUA_FF_LIB
+/* ma = State Machine, un = Unknown */
+char *lookup_type_names[2][10] =
+ { { "us", "ss", "ms", "as", "ls", "cs", "ks", "es", "rk" },
+ { "up", "sp", "pp", "ca", "mb", "ml", "mm", "cp", "kp","ep" }};
+#else
+char *lookup_type_names[2][10] =
+ { { N_("Undefined substitution"), N_("Single Substitution"), N_("Multiple Substitution"),
+ N_("Alternate Substitution"), N_("Ligature Substitution"), N_("Contextual Substitution"),
+ N_("Contextual Chaining Substitution"), N_("Extension"),
+ N_("Reverse Contextual Chaining Substitution") },
+ { N_("Undefined positioning"), N_("Single Positioning"), N_("Pairwise Positioning (kerning)"),
+ N_("Cursive attachment"), N_("Mark to base attachment"),
+ N_("Mark to Ligature attachment"), N_("Mark to Mark attachment"),
+ N_("Contextual Positioning"), N_("Contextual Chaining Positioning"),
+ N_("Extension") }};
+#endif
+
+void NameOTLookup(OTLookup *otl,SplineFont *sf) {
+ char *userfriendly = NULL, *script;
+ FeatureScriptLangList *fl;
+ char *lookuptype;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ extern GTextInfo scripts[];
+#endif
+ char *format;
+ struct lookup_subtable *subtable;
+ int k;
+
+ if ( otl->lookup_name==NULL ) {
+ for ( k=0; k<2; ++k ) {
+ for ( fl=otl->features; fl!=NULL ; fl=fl->next ) {
+ /* look first for a feature attached to a default language */
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI /* because of the Gdraw dependant TagFullname */
+ if ( k==1 || DefaultLangTagInScriptList(fl->scripts,false)!=NULL ) {
+ userfriendly = TagFullName(sf,fl->featuretag, fl->ismac, true);
+ if ( userfriendly!=NULL )
+ break;
+ }
+#endif
+ }
+ if ( userfriendly!=NULL )
+ break;
+ }
+ if ( userfriendly==NULL ) {
+ if ( (otl->lookup_type&0xff)>= 0xf0 )
+#ifdef LUA_FF_LIB
+ lookuptype = "ma";
+#else
+ lookuptype = _("State Machine");
+#endif
+ else if ( (otl->lookup_type>>8)<2 && (otl->lookup_type&0xff)<10 )
+ lookuptype = _(lookup_type_names[otl->lookup_type>>8][otl->lookup_type&0xff]);
+ else
+#ifdef LUA_FF_LIB
+ lookuptype = "un";
+#else
+ lookuptype = S_("LookupType|Unknown");
+#endif
+ for ( fl=otl->features; fl!=NULL && !fl->ismac; fl=fl->next );
+ if ( fl==NULL )
+ userfriendly = copy(lookuptype);
+ else {
+ userfriendly = galloc( strlen(lookuptype) + 10);
+#ifdef LUA_FF_LIB
+ sprintf( userfriendly, "%s_%c%c%c%c", lookuptype,
+#else
+ sprintf( userfriendly, "%s '%c%c%c%c'", lookuptype,
+#endif
+ fl->featuretag>>24,
+ fl->featuretag>>16,
+ fl->featuretag>>8 ,
+ fl->featuretag );
+ }
+ }
+ script = NULL;
+ if ( fl==NULL ) fl = otl->features;
+ if ( fl!=NULL && fl->scripts!=NULL ) {
+ char buf[8];
+ /*int j;*/
+ struct scriptlanglist *sl, *found, *found2;
+ uint32 script_tag = fl->scripts->script;
+ found = found2 = NULL;
+ for ( sl = fl->scripts; sl!=NULL; sl=sl->next ) {
+ if ( sl->script == DEFAULT_SCRIPT )
+ /* Ignore it */;
+ else if ( DefaultLangTagInOneScriptList(sl)) {
+ if ( found==NULL )
+ found = sl;
+ else {
+ found = found2 = NULL;
+ break;
+ }
+ } else if ( found2 == NULL )
+ found2 = sl;
+ else
+ found2 = (struct scriptlanglist *) -1;
+ }
+ if ( found==NULL && found2!=NULL && found2 != (struct scriptlanglist *) -1 )
+ found = found2;
+ if ( found!=NULL ) {
+ script_tag = found->script;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ for ( j=0; scripts[j].text!=NULL && script_tag!=(uint32) (intpt) scripts[j].userdata; ++j );
+ if ( scripts[j].text!=NULL )
+ script = copy( S_((char *) scripts[j].text) );
+ else {
+#else
+ {
+#endif
+#ifdef LUA_FF_LIB
+ buf[0] = fl->scripts->script>>24;
+ buf[1] = (fl->scripts->script>>16)&0xff;
+ buf[2] = (fl->scripts->script>>8)&0xff;
+ buf[3] = fl->scripts->script&0xff;
+ buf[4] = 0;
+#else
+ buf[0] = '\'';
+ buf[1] = fl->scripts->script>>24;
+ buf[2] = (fl->scripts->script>>16)&0xff;
+ buf[3] = (fl->scripts->script>>8)&0xff;
+ buf[4] = fl->scripts->script&0xff;
+ buf[5] = '\'';
+ buf[6] = 0;
+#endif
+ script = copy(buf);
+ }
+ }
+ }
+/* GT: This string is used to generate a name for each OpenType lookup. */
+/* GT: The %s will be filled with the user friendly name of the feature used to invoke the lookup */
+/* GT: The second %s (if present) is the script */
+/* GT: While the %d is the index into the lookup list and is used to disambiguate it */
+/* GT: In case that is needed */
+ if ( script!=NULL ) {
+#ifdef LUA_FF_LIB
+ format = "%s_%s_l_%d";
+#else
+ format = _("%s in %s lookup %d");
+#endif
+ otl->lookup_name = galloc( strlen(userfriendly)+strlen(format)+strlen(script)+10 );
+ sprintf( otl->lookup_name, format, userfriendly, script, otl->lookup_index );
+ } else {
+#ifdef LUA_FF_LIB
+ format = "%s_l_%d";
+#else
+ format = _("%s lookup %d");
+#endif
+ otl->lookup_name = galloc( strlen(userfriendly)+strlen(format)+10 );
+ sprintf( otl->lookup_name, format, userfriendly, otl->lookup_index );
+ }
+ free(script);
+ free(userfriendly);
+ }
+
+ if ( otl->subtables==NULL )
+ /* IError( _("Lookup with no subtables"))*/;
+ else {
+ int cnt = 0;
+ for ( subtable = otl->subtables; subtable!=NULL; subtable=subtable->next, ++cnt )
+ if ( subtable->subtable_name==NULL ) {
+ if ( subtable==otl->subtables && subtable->next==NULL )
+/* GT: This string is used to generate a name for an OpenType lookup subtable. */
+/* GT: %s is the lookup name */
+#ifdef LUA_FF_LIB
+ format = "%s_s";
+#else
+ format = _("%s subtable");
+#endif
+ else if ( subtable->per_glyph_pst_or_kern )
+/* GT: This string is used to generate a name for an OpenType lookup subtable. */
+/* GT: %s is the lookup name, %d is the index of the subtable in the lookup */
+#ifdef LUA_FF_LIB
+ format = "%s_g_%d";
+#else
+ format = _("%s per glyph data %d");
+#endif
+ else if ( subtable->kc!=NULL )
+#ifdef LUA_FF_LIB
+ format = "%s_k_%d";
+#else
+ format = _("%s kerning class %d");
+#endif
+ else if ( subtable->fpst!=NULL )
+#ifdef LUA_FF_LIB
+ format = "%s_c_%d";
+#else
+ format = _("%s contextual %d");
+#endif
+ else if ( subtable->anchor_classes )
+#ifdef LUA_FF_LIB
+ format = "%s_a_%d";
+#else
+ format = _("%s anchor %d");
+#endif
+ else {
+ IError("Subtable status not filled in for %dth subtable of %s", cnt, otl->lookup_name );
+ format = "%s !!!!!!!! %d";
+ }
+ subtable->subtable_name = galloc( strlen(otl->lookup_name)+strlen(format)+10 );
+ sprintf( subtable->subtable_name, format, otl->lookup_name, cnt );
+ }
+ }
+ if ( otl->lookup_type==gsub_ligature ) {
+ for ( fl=otl->features; fl!=NULL; fl=fl->next )
+ if ( fl->featuretag==CHR('l','i','g','a') || fl->featuretag==CHR('r','l','i','g'))
+ otl->store_in_afm = true;
+ }
+
+ if ( otl->lookup_type==gsub_single )
+ for ( subtable = otl->subtables; subtable!=NULL; subtable=subtable->next )
+ subtable->suffix = SuffixFromTags(otl->features);
+}
+
+static void LangOrder(struct scriptlanglist *sl) {
+ int i,j;
+ uint32 lang, lang2;
+
+ for ( i=0; i<sl->lang_cnt; ++i ) {
+ lang = i<MAX_LANG ? sl->langs[i] : sl->morelangs[i-MAX_LANG];
+ for ( j=i+1; j<sl->lang_cnt; ++j ) {
+ lang2 = j<MAX_LANG ? sl->langs[j] : sl->morelangs[j-MAX_LANG];
+ if ( lang>lang2 ) {
+ if ( i<MAX_LANG )
+ sl->langs[i] = lang2;
+ else
+ sl->morelangs[i-MAX_LANG] = lang2;
+ if ( j<MAX_LANG )
+ sl->langs[j] = lang;
+ else
+ sl->morelangs[j-MAX_LANG] = lang;
+ lang = lang2;
+ }
+ }
+ }
+}
+
+static struct scriptlanglist *SLOrder(struct scriptlanglist *sl) {
+ int i,j, cnt;
+ struct scriptlanglist *sl2, *space[30], **allocked=NULL, **test = space;
+
+ for ( sl2=sl, cnt=0; sl2!=NULL; sl2=sl2->next, ++cnt )
+ LangOrder(sl2);
+ if ( cnt<=1 )
+return( sl );
+ if ( cnt>30 )
+ test = allocked = galloc(cnt*sizeof(struct scriptlanglist *));
+ for ( sl2=sl, cnt=0; sl2!=NULL; sl2=sl2->next, ++cnt )
+ test[cnt] = sl2;
+ for ( i=0; i<cnt; ++i ) for ( j=i+1; j<cnt; ++j ) {
+ if ( test[i]->script > test[j]->script ) {
+ struct scriptlanglist *temp;
+ temp = test[i];
+ test[i] = test[j];
+ test[j] = temp;
+ }
+ }
+ sl = test[0];
+ for ( i=1; i<cnt; ++i )
+ test[i-1]->next = test[i];
+ test[i-1]->next = NULL;
+ free( allocked );
+return( sl );
+}
+
+FeatureScriptLangList *FLOrder(FeatureScriptLangList *fl) {
+ int i,j, cnt;
+ FeatureScriptLangList *fl2, *space[30], **allocked=NULL, **test = space;
+
+ for ( fl2=fl, cnt=0; fl2!=NULL; fl2=fl2->next, ++cnt )
+ fl2->scripts = SLOrder(fl2->scripts);
+ if ( cnt<=1 )
+return( fl );
+ if ( cnt>30 )
+ test = allocked = galloc(cnt*sizeof(FeatureScriptLangList *));
+ for ( fl2=fl, cnt=0; fl2!=NULL; fl2=fl2->next, ++cnt )
+ test[cnt] = fl2;
+ for ( i=0; i<cnt; ++i ) for ( j=i+1; j<cnt; ++j ) {
+ if ( test[i]->featuretag > test[j]->featuretag ) {
+ FeatureScriptLangList *temp;
+ temp = test[i];
+ test[i] = test[j];
+ test[j] = temp;
+ }
+ }
+ fl = test[0];
+ for ( i=1; i<cnt; ++i )
+ test[i-1]->next = test[i];
+ test[i-1]->next = NULL;
+ free( allocked );
+return( fl );
+}
+
+struct scriptlanglist *SLCopy(struct scriptlanglist *sl) {
+ struct scriptlanglist *newsl;
+
+ newsl = chunkalloc(sizeof(struct scriptlanglist));
+ *newsl = *sl;
+ newsl->next = NULL;
+
+ if ( sl->lang_cnt>MAX_LANG ) {
+ newsl->morelangs = galloc((newsl->lang_cnt-MAX_LANG)*sizeof(uint32));
+ memcpy(newsl->morelangs,sl->morelangs,(newsl->lang_cnt-MAX_LANG)*sizeof(uint32));
+ }
+return( newsl );
+}
+
+FeatureScriptLangList *FeatureListCopy(FeatureScriptLangList *fl) {
+ FeatureScriptLangList *newfl;
+ struct scriptlanglist *sl, *prev;
+
+ newfl = chunkalloc(sizeof(FeatureScriptLangList));
+ *newfl = *fl;
+ newfl->next = NULL;
+
+ prev = NULL;
+ for ( sl=fl->scripts; sl!=NULL; sl=sl->next ) {
+ if ( prev==NULL )
+ newfl->scripts = prev = SLCopy(sl);
+ else {
+ prev->next = SLCopy(sl);
+ prev = prev->next;
+ }
+ }
+return( newfl );
+}
+
+static void LangMerge(struct scriptlanglist *into, struct scriptlanglist *from) {
+ int i,j;
+ uint32 flang, tlang;
+
+ for ( i=0 ; i<from->lang_cnt; ++i ) {
+ flang = i<MAX_LANG ? from->langs[i] : from->morelangs[i-MAX_LANG];
+ for ( j=0; j<into->lang_cnt; ++j ) {
+ tlang = j<MAX_LANG ? into->langs[j] : into->morelangs[j-MAX_LANG];
+ if ( tlang==flang )
+ break;
+ }
+ if ( j==into->lang_cnt ) {
+ if ( into->lang_cnt<MAX_LANG )
+ into->langs[into->lang_cnt++] = flang;
+ else {
+ into->morelangs = grealloc(into->morelangs,(into->lang_cnt+1-MAX_LANG)*sizeof(uint32));
+ into->morelangs[into->lang_cnt++-MAX_LANG] = flang;
+ }
+ }
+ }
+}
+
+void SLMerge(FeatureScriptLangList *into, struct scriptlanglist *fsl) {
+ struct scriptlanglist *isl;
+
+ for ( ; fsl!=NULL; fsl = fsl->next ) {
+ for ( isl=into->scripts; isl!=NULL; isl=isl->next ) {
+ if ( fsl->script==isl->script )
+ break;
+ }
+ if ( isl!=NULL )
+ LangMerge(fsl,isl);
+ else {
+ isl = SLCopy(fsl);
+ isl->next = into->scripts;
+ into->scripts = isl;
+ }
+ }
+}
+
+void FLMerge(OTLookup *into, OTLookup *from) {
+ /* Merge the feature list from "from" into "into" */
+ FeatureScriptLangList *ifl, *ffl;
+
+ /* first check for common featuretags and merge the scripts of each */
+ for ( ffl = from->features; ffl!=NULL; ffl = ffl->next ) {
+ for ( ifl=into->features; ifl!=NULL; ifl=ifl->next ) {
+ if ( ffl->featuretag==ifl->featuretag )
+ break;
+ }
+ if ( ifl!=NULL )
+ SLMerge(ffl,ifl->scripts);
+ else {
+ ifl = FeatureListCopy(ffl);
+ ifl->next = into->features;
+ into->features = ifl;
+ }
+ }
+ into->features = FLOrder(into->features);
+}
+
+void SFSubTablesMerge(SplineFont *_sf,struct lookup_subtable *subfirst,
+ struct lookup_subtable *subsecond) {
+ int lookup_type = subfirst->lookup->lookup_type;
+ int gid,k,isv;
+ SplineChar *sc;
+ SplineFont *sf = _sf;
+ PST *pst, *fpst, *spst, *pstprev, *pstnext;
+ KernPair *fkp, *skp, *kpprev, *kpnext;
+ AnchorClass *ac;
+
+ if ( lookup_type != subsecond->lookup->lookup_type ) {
+ IError("Attempt to merge lookup subtables with mismatch types");
+return;
+ }
+ if ( lookup_type != gsub_single &&
+ lookup_type != gsub_multiple &&
+ lookup_type != gsub_alternate &&
+ lookup_type != gsub_ligature &&
+ lookup_type != gpos_single &&
+ lookup_type != gpos_pair &&
+ lookup_type != gpos_cursive &&
+ lookup_type != gpos_mark2base &&
+ lookup_type != gpos_mark2ligature &&
+ lookup_type != gpos_mark2mark ) {
+ IError("Attempt to merge lookup subtables with bad types");
+return;
+ } else if ( subfirst->kc!=NULL || subsecond->kc != NULL ) {
+ IError("Attempt to merge lookup subtables with kerning classes");
+return;
+ }
+
+ if ( lookup_type==gpos_cursive || lookup_type==gpos_mark2base ||
+ lookup_type==gpos_mark2ligature || lookup_type==gpos_mark2mark ) {
+ for ( ac = sf->anchor; ac!=NULL ; ac=ac->next )
+ if ( ac->subtable == subsecond )
+ ac->subtable = subfirst;
+ } else {
+ k=0;
+ do {
+ sf = _sf->subfontcnt==0 ? _sf : _sf->subfonts[k];
+ for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( (sc=sf->glyphs[gid])!=NULL ) {
+ if ( lookup_type==gsub_single || lookup_type==gsub_multiple ||
+ lookup_type==gsub_alternate || lookup_type==gpos_single ) {
+ fpst = spst = NULL;
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable == subfirst ) {
+ fpst = pst;
+ if ( spst!=NULL )
+ break;
+ } else if ( pst->subtable == subsecond ) {
+ spst = pst;
+ if ( fpst!=NULL )
+ break;
+ }
+ }
+ if ( fpst==NULL && spst!=NULL )
+ spst->subtable = subfirst;
+ else if ( spst!=NULL ) {
+ LogError(_("The glyph, %s, contains a %s from %s and one from %s.\nThe one from %s will be removed.\n"),
+ sc->name,
+ lookup_type==gpos_single ? _("positioning") : _("substitution"),
+ subfirst->subtable_name, subsecond->subtable_name,
+ subsecond->subtable_name );
+ pstprev = NULL;
+ for ( pst=sc->possub; pst!=NULL && pst!=spst; pstprev=pst, pst=pst->next );
+ if ( pstprev==NULL )
+ sc->possub = spst->next;
+ else
+ pstprev = spst->next;
+ spst->next = NULL;
+ PSTFree(spst);
+ }
+ } else if ( lookup_type==gsub_ligature || lookup_type==gpos_pair ) {
+ pstprev = NULL;
+ for ( spst=sc->possub; spst!=NULL ; spst = pstnext ) {
+ pstnext = spst->next;
+ if ( spst->subtable == subsecond ) {
+ for ( fpst=sc->possub; fpst!=NULL; fpst=fpst->next ) {
+ if ( fpst->subtable == subfirst &&
+ strcmp(fpst->u.lig.components,spst->u.lig.components)==0 )
+ break;
+ }
+ if ( fpst==NULL )
+ spst->subtable = subfirst;
+ else {
+ LogError(_("The glyph, %s, contains the same %s from %s and from %s.\nThe one from %s will be removed.\n"),
+ sc->name,
+ lookup_type==gsub_ligature ? _("ligature") : _("kern pair"),
+ subfirst->subtable_name, subsecond->subtable_name,
+ subsecond->subtable_name );
+ if ( pstprev==NULL )
+ sc->possub = pstnext;
+ else
+ pstprev->next = pstnext;
+ spst->next = NULL;
+ PSTFree(spst);
+ spst = pstprev;
+ }
+ }
+ pstprev = spst;
+ }
+ for ( isv=0; isv<2; ++isv ) {
+ kpprev = NULL;
+ for ( skp=isv ? sc->vkerns : sc->kerns; skp!=NULL ; skp = kpnext ) {
+ kpnext = skp->next;
+ if ( skp->subtable == subsecond ) {
+ for ( fkp=isv ? sc->vkerns : sc->kerns; fkp!=NULL; fkp=fkp->next ) {
+ if ( fkp->subtable == subfirst && fkp->sc==skp->sc )
+ break;
+ }
+ if ( fkp==NULL )
+ skp->subtable = subfirst;
+ else {
+ LogError(_("The glyph, %s, contains the same kern pair from %s and from %s.\nThe one from %s will be removed.\n"),
+ sc->name,
+ subfirst->subtable_name, subsecond->subtable_name,
+ subsecond->subtable_name );
+ if ( kpprev!=NULL )
+ kpprev->next = kpnext;
+ else if ( isv )
+ sc->vkerns = kpnext;
+ else
+ sc->kerns = kpnext;
+ skp->next = NULL;
+ KernPairsFree(skp);
+ skp = kpprev;
+ }
+ }
+ kpprev = skp;
+ }
+ }
+ }
+ }
+ ++k;
+ } while ( k<_sf->subfontcnt );
+ }
+}
+
+/* ************************************************************************** */
+/* ******************************* copy lookup ****************************** */
+/* ************************************************************************** */
+
+static char **ClassCopy(int class_cnt,char **classes) {
+ char **newclasses;
+ int i;
+
+ if ( classes==NULL || class_cnt==0 )
+return( NULL );
+ newclasses = galloc(class_cnt*sizeof(char *));
+ for ( i=0; i<class_cnt; ++i )
+ newclasses[i] = copy(classes[i]);
+return( newclasses );
+}
+
+static OTLookup *OTLookupCopyNested(SplineFont *to_sf,SplineFont *from_sf, char *prefix,
+ OTLookup *from_otl) {
+ char *newname;
+ OTLookup *to_nested_otl;
+
+ if ( from_otl==NULL )
+return( NULL );
+ newname = strconcat(prefix,from_otl->lookup_name);
+ to_nested_otl = SFFindLookup(to_sf,newname);
+ free(newname);
+ if ( to_nested_otl==NULL )
+ to_nested_otl = OTLookupCopyInto(to_sf,from_sf, from_otl);
+return( to_nested_otl );
+}
+
+static KernClass *SF_AddKernClass(SplineFont *to_sf,KernClass *kc, struct lookup_subtable *sub,
+ SplineFont *from_sf, char *prefix) {
+ KernClass *newkc;
+
+ newkc = chunkalloc(sizeof(KernClass));
+ *newkc = *kc;
+ newkc->subtable = sub;
+ if ( sub->vertical_kerning ) {
+ newkc->next = to_sf->vkerns;
+ to_sf->vkerns = newkc;
+ } else {
+ newkc->next = to_sf->kerns;
+ to_sf->kerns = newkc;
+ }
+
+ newkc->firsts = ClassCopy(newkc->first_cnt,newkc->firsts);
+ newkc->seconds = ClassCopy(newkc->second_cnt,newkc->seconds);
+ newkc->offsets = galloc(newkc->first_cnt*newkc->first_cnt*sizeof(int16));
+ memcpy(newkc->offsets,kc->offsets,newkc->first_cnt*newkc->first_cnt*sizeof(int16));
+return( newkc );
+}
+
+static FPST *SF_AddFPST(SplineFont *to_sf,FPST *fpst, struct lookup_subtable *sub,
+ SplineFont *from_sf, char *prefix) {
+ FPST *newfpst;
+ int i, k, cur;
+
+ newfpst = chunkalloc(sizeof(FPST));
+ *newfpst = *fpst;
+ newfpst->subtable = sub;
+ newfpst->next = to_sf->possub;
+ to_sf->possub = newfpst;
+
+ newfpst->nclass = ClassCopy(newfpst->nccnt,newfpst->nclass);
+ newfpst->bclass = ClassCopy(newfpst->bccnt,newfpst->bclass);
+ newfpst->fclass = ClassCopy(newfpst->fccnt,newfpst->fclass);
+
+ newfpst->rules = galloc(newfpst->rule_cnt*sizeof(struct fpst_rule));
+ memcpy(newfpst->rules,fpst->rules,newfpst->rule_cnt*sizeof(struct fpst_rule));
+
+ cur = 0;
+ for ( i=0; i<newfpst->rule_cnt; ++i ) {
+ struct fpst_rule *r = &newfpst->rules[i], *oldr = &fpst->rules[i];
+
+ r->lookups = galloc(r->lookup_cnt*sizeof(struct seqlookup));
+ memcpy(r->lookups,oldr->lookups,r->lookup_cnt*sizeof(struct seqlookup));
+ for ( k=0; k<r->lookup_cnt; ++k ) {
+ r->lookups[k].lookup = OTLookupCopyNested(to_sf,from_sf, prefix,
+ r->lookups[k].lookup);
+ }
+
+ switch ( newfpst->format ) {
+ case pst_glyphs:
+ r->u.glyph.names = copy( r->u.glyph.names );
+ r->u.glyph.back = copy( r->u.glyph.back );
+ r->u.glyph.fore = copy( r->u.glyph.fore );
+ break;
+ case pst_class:
+ r->u.class.nclasses = galloc( r->u.class.ncnt*sizeof(uint16));
+ memcpy(r->u.class.nclasses,oldr->u.class.nclasses, r->u.class.ncnt*sizeof(uint16));
+ r->u.class.bclasses = galloc( r->u.class.bcnt*sizeof(uint16));
+ memcpy(r->u.class.bclasses,oldr->u.class.bclasses, r->u.class.ncnt*sizeof(uint16));
+ r->u.class.fclasses = galloc( r->u.class.fcnt*sizeof(uint16));
+ memcpy(r->u.class.fclasses,oldr->u.class.fclasses, r->u.class.fcnt*sizeof(uint16));
+ break;
+ case pst_coverage:
+ r->u.coverage.ncovers = ClassCopy( r->u.coverage.ncnt, r->u.coverage.ncovers );
+ r->u.coverage.bcovers = ClassCopy( r->u.coverage.bcnt, r->u.coverage.bcovers );
+ r->u.coverage.fcovers = ClassCopy( r->u.coverage.fcnt, r->u.coverage.fcovers );
+ break;
+ case pst_reversecoverage:
+ r->u.rcoverage.ncovers = ClassCopy( r->u.rcoverage.always1, r->u.rcoverage.ncovers );
+ r->u.rcoverage.bcovers = ClassCopy( r->u.rcoverage.bcnt, r->u.rcoverage.bcovers );
+ r->u.rcoverage.fcovers = ClassCopy( r->u.rcoverage.fcnt, r->u.rcoverage.fcovers );
+ r->u.rcoverage.replacements = copy( r->u.rcoverage.replacements );
+ break;
+ }
+ }
+return( newfpst );
+}
+
+static ASM *SF_AddASM(SplineFont *to_sf,ASM *sm, struct lookup_subtable *sub,
+ SplineFont *from_sf, char *prefix) {
+ ASM *newsm;
+ int i;
+
+ newsm = chunkalloc(sizeof(ASM));
+ *newsm = *sm;
+ newsm->subtable = sub;
+ newsm->next = to_sf->sm;
+ to_sf->sm = newsm;
+ to_sf->changed = true;
+ newsm->classes = ClassCopy(newsm->class_cnt, newsm->classes);
+ newsm->state = galloc(newsm->class_cnt*newsm->state_cnt*sizeof(struct asm_state));
+ memcpy(newsm->state,sm->state,
+ newsm->class_cnt*newsm->state_cnt*sizeof(struct asm_state));
+ if ( newsm->type == asm_kern ) {
+ for ( i=newsm->class_cnt*newsm->state_cnt-1; i>=0; --i ) {
+ newsm->state[i].u.kern.kerns = galloc(newsm->state[i].u.kern.kcnt*sizeof(int16));
+ memcpy(newsm->state[i].u.kern.kerns,sm->state[i].u.kern.kerns,newsm->state[i].u.kern.kcnt*sizeof(int16));
+ }
+ } else if ( newsm->type == asm_insert ) {
+ for ( i=0; i<newsm->class_cnt*newsm->state_cnt; ++i ) {
+ struct asm_state *this = &newsm->state[i];
+ this->u.insert.mark_ins = copy(this->u.insert.mark_ins);
+ this->u.insert.cur_ins = copy(this->u.insert.cur_ins);
+ }
+ } else if ( newsm->type == asm_context ) {
+ for ( i=0; i<newsm->class_cnt*newsm->state_cnt; ++i ) {
+ newsm->state[i].u.context.mark_lookup = OTLookupCopyNested(to_sf,from_sf, prefix,
+ newsm->state[i].u.context.mark_lookup);
+ newsm->state[i].u.context.cur_lookup = OTLookupCopyNested(to_sf,from_sf, prefix,
+ newsm->state[i].u.context.cur_lookup);
+ }
+ }
+return( newsm );
+}
+
+static SplineChar *SCFindOrMake(SplineFont *into,SplineChar *fromsc) {
+ int to_index;
+
+ if ( into->cidmaster==NULL && into->fv!=NULL ) {
+ to_index = SFFindSlot(into,into->fv->map,fromsc->unicodeenc,fromsc->name);
+ if ( to_index==-1 )
+return( NULL );
+return( SFMakeChar(into,into->fv->map,to_index));
+ }
+return( SFGetChar(into,fromsc->unicodeenc,fromsc->name));
+}
+
+static void SF_SCAddAP(SplineChar *tosc,AnchorPoint *ap, AnchorClass *newac) {
+ AnchorPoint *newap;
+
+ newap = chunkalloc(sizeof(AnchorPoint));
+ *newap = *ap;
+ newap->anchor = newac;
+ newap->next = tosc->anchor;
+ tosc->anchor = newap;
+}
+
+static void SF_AddAnchorClasses(SplineFont *to_sf,struct lookup_subtable *from_sub, struct lookup_subtable *sub,
+ SplineFont *from_sf, char *prefix) {
+ AnchorClass *ac, *nac;
+ int k, gid;
+ SplineFont *fsf;
+ AnchorPoint *ap;
+ SplineChar *fsc, *tsc;
+
+ for ( ac=from_sf->anchor; ac!=NULL; ac=ac->next ) if ( ac->subtable==from_sub ) {
+ nac = chunkalloc(sizeof(AnchorClass));
+ *nac = *ac;
+ nac->subtable = sub;
+ nac->name = strconcat(prefix,nac->name);
+ nac->next = to_sf->anchor;
+ to_sf->anchor = nac;
+
+ k=0;
+ do {
+ fsf = from_sf->subfontcnt==0 ? from_sf : from_sf->subfonts[k];
+ for ( gid = 0; gid<fsf->glyphcnt; ++gid ) if ( (fsc = fsf->glyphs[gid])!=NULL ) {
+ for ( ap=fsc->anchor; ap!=NULL; ap=ap->next ) {
+ if ( ap->anchor==ac ) {
+ tsc = SCFindOrMake(to_sf,fsc);
+ if ( tsc==NULL )
+ break;
+ SF_SCAddAP(tsc,ap,nac);
+ }
+ }
+ }
+ ++k;
+ } while ( k<from_sf->subfontcnt );
+ }
+}
+
+static int SF_SCAddPST(SplineChar *tosc,PST *pst,struct lookup_subtable *sub) {
+ PST *newpst;
+
+ newpst = chunkalloc(sizeof(PST));
+ *newpst = *pst;
+ newpst->subtable = sub;
+ newpst->next = tosc->possub;
+ tosc->possub = newpst;
+
+ switch( newpst->type ) {
+ case pst_pair:
+ newpst->u.pair.paired = copy(pst->u.pair.paired);
+ newpst->u.pair.vr = chunkalloc(sizeof(struct vr [2]));
+ memcpy(newpst->u.pair.vr,pst->u.pair.vr,sizeof(struct vr [2]));
+ break;
+ case pst_ligature:
+ newpst->u.lig.lig = tosc;
+ /* Fall through */
+ case pst_substitution:
+ case pst_alternate:
+ case pst_multiple:
+ newpst->u.subs.variant = copy(pst->u.subs.variant);
+ break;
+ }
+return( true );
+}
+
+static int SF_SCAddKP(SplineChar *tosc,KernPair *kp,struct lookup_subtable *sub,
+ int isvkern, SplineFont *to_sf ) {
+ SplineChar *tosecond;
+ KernPair *newkp;
+
+ tosecond = SFGetChar(to_sf,kp->sc->unicodeenc,kp->sc->name);
+ if ( tosecond==NULL )
+return( false );
+
+ newkp = chunkalloc(sizeof(KernPair));
+ *newkp = *kp;
+ newkp->subtable = sub;
+ newkp->sc = tosecond;
+ if ( isvkern ) {
+ newkp->next = tosc->vkerns;
+ tosc->vkerns = newkp;
+ } else {
+ newkp->next = tosc->kerns;
+ tosc->kerns = newkp;
+ }
+return(true);
+}
+
+static void SF_AddPSTKern(SplineFont *to_sf,struct lookup_subtable *from_sub, struct lookup_subtable *sub,
+ SplineFont *from_sf, char *prefix) {
+ int k, gid, isv;
+ SplineFont *fsf;
+ SplineChar *fsc, *tsc;
+ PST *pst;
+ KernPair *kp;
+ int iskern = sub->lookup->lookup_type==gpos_pair;
+
+ k=0;
+ do {
+ fsf = from_sf->subfontcnt==0 ? from_sf : from_sf->subfonts[k];
+ for ( gid = 0; gid<fsf->glyphcnt; ++gid ) if ( (fsc = fsf->glyphs[gid])!=NULL ) {
+ tsc = (SplineChar *) -1;
+ for ( pst = fsc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable==from_sub ) {
+ if ( tsc==(SplineChar *) -1 ) {
+ tsc = SCFindOrMake(to_sf,fsc);
+ if ( tsc==NULL )
+ break;
+ }
+ SF_SCAddPST(tsc,pst,sub);
+ }
+ }
+ if ( tsc!=NULL && iskern ) {
+ for ( isv=0; isv<2 && tsc!=NULL; ++isv ) {
+ for ( kp= isv ? fsc->vkerns : fsc->kerns; kp!=NULL; kp=kp->next ) {
+ if ( kp->subtable==sub ) {
+ /* Kerning data tend to be individualistic. Only copy if */
+ /* glyphs exist */
+ if ( tsc==(SplineChar *) -1 ) {
+ tsc = SFGetChar(to_sf,fsc->unicodeenc,fsc->name);
+ if ( tsc==NULL )
+ break;
+ }
+ SF_SCAddKP(tsc,kp,sub,isv,to_sf);
+ }
+ }
+ }
+ }
+ }
+ ++k;
+ } while ( k<from_sf->subfontcnt );
+}
+
+static void SortInsertLookup(SplineFont *sf, OTLookup *newotl) {
+ int isgpos = newotl->lookup_type>=gpos_start;
+ int pos, i, k;
+ OTLookup *prev, *otl;
+
+ pos = FeatureOrderId(isgpos,newotl->features);
+ for ( prev=NULL, otl= isgpos ? sf->gpos_lookups : sf->gsub_lookups ;
+ otl!=NULL && FeatureOrderId(isgpos,newotl->features)<pos;
+ prev = otl, otl=otl->next );
+ newotl->next = otl;
+ if ( prev!=NULL )
+ prev->next = newotl;
+ else if ( isgpos )
+ sf->gpos_lookups = newotl;
+ else
+ sf->gsub_lookups = newotl;
+
+ if ( sf->fontinfo ) {
+ struct lkdata *lk = &sf->fontinfo->tables[isgpos];
+ if ( lk->cnt>=lk->max )
+ lk->all = grealloc(lk->all,(lk->max+=10)*sizeof(struct lkinfo));
+ for ( i=0; i<lk->cnt && FeatureOrderId(isgpos,lk->all[i].lookup->features)<pos; ++i );
+ for ( k=lk->cnt; k>i+1; --k )
+ lk->all[k] = lk->all[k-1];
+ memset(&lk->all[k],0,sizeof(struct lkinfo));
+ lk->all[k].lookup = newotl;
+ ++lk->cnt;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ GFI_LookupScrollbars(sf->fontinfo,isgpos, true);
+ GFI_LookupEnableButtons(sf->fontinfo,isgpos);
+#endif
+ }
+}
+
+OTLookup *OTLookupCopyInto(SplineFont *into_sf,SplineFont *from_sf, OTLookup *from_otl) {
+ OTLookup *otl = chunkalloc(sizeof(OTLookup));
+ struct lookup_subtable *sub, *last, *from_sub;
+ char *prefix = strconcat(from_sf->fontname,"-");
+
+ into_sf->changed = true;
+
+ *otl = *from_otl;
+ otl->lookup_name = strconcat(prefix,from_otl->lookup_name);
+ otl->features = FeatureListCopy(from_otl->features);
+ otl->next = NULL; otl->subtables = NULL;
+ SortInsertLookup(into_sf,otl);
+
+ last = NULL;
+ for ( from_sub = from_otl->subtables; from_sub!=NULL; from_sub=from_sub->next ) {
+ sub = chunkalloc(sizeof(struct lookup_subtable));
+ *sub = *from_sub;
+ sub->lookup = otl;
+ sub->subtable_name = strconcat(prefix,from_sub->subtable_name);
+ sub->suffix = copy(sub->suffix);
+ if ( from_sub->kc!=NULL )
+ sub->kc = SF_AddKernClass(into_sf, from_sub->kc, sub, from_sf, prefix);
+ else if ( from_sub->fpst!=NULL )
+ sub->fpst = SF_AddFPST(into_sf, from_sub->fpst, sub, from_sf, prefix);
+ else if ( from_sub->sm!=NULL )
+ sub->sm = SF_AddASM(into_sf, from_sub->sm, sub, from_sf, prefix);
+ else if ( from_sub->anchor_classes )
+ SF_AddAnchorClasses(into_sf, from_sub, sub, from_sf, prefix);
+ else
+ SF_AddPSTKern(into_sf, from_sub, sub, from_sf, prefix);
+ }
+return( otl );
+}
+
+/* ************************************************************************** */
+/* ****************************** Apply lookups ***************************** */
+/* ************************************************************************** */
+
+struct lookup_data {
+ struct opentype_str *str;
+ int cnt, max;
+
+ uint32 script;
+ SplineFont *sf;
+
+ struct lookup_subtable *lig_owner;
+ int lcnt, lmax;
+ SplineChar ***ligs; /* For each ligature we have an array of SplineChars that are its components preceded by the ligature glyph itself */
+ /* NULL terminated */
+};
+
+static int ApplyLookupAtPos(uint32 tag, OTLookup *otl,struct lookup_data *data,int pos);
+
+static void LigatureFree(struct lookup_data *data) {
+ int i;
+
+ if ( data->ligs==NULL )
+return;
+ for ( i=0; data->ligs[i]!=NULL; ++i )
+ free(data->ligs[i]);
+}
+
+static void LigatureSearch(struct lookup_subtable *sub, struct lookup_data *data) {
+ SplineFont *sf = data->sf;
+ int gid, ccnt, cnt, ch, err;
+ SplineChar *sc;
+ PST *pst;
+ char *pt, *start;
+
+ LigatureFree(data);
+ cnt = 0;
+ for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( (sc=sf->glyphs[gid])!=NULL ) {
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) if ( pst->subtable==sub ) {
+ for ( pt = pst->u.lig.components, ccnt=0; *pt; ++pt )
+ if ( *pt==' ' )
+ ++ccnt;
+ if ( cnt>=data->lmax )
+ data->ligs = grealloc(data->ligs,(data->lmax+=100)*sizeof(SplineChar **));
+ data->ligs[cnt] = galloc((ccnt+3)*sizeof(SplineChar *));
+ data->ligs[cnt][0] = sc;
+ ccnt = 1;
+ err = 0;
+ for ( pt = pst->u.lig.components; *pt; ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ for ( start=pt; *pt!='\0' && *pt!=' '; ++pt );
+ ch = *pt; *pt = '\0';
+ data->ligs[cnt][ccnt++] = SFGetChar(sf,-1,start);
+ *pt = ch;
+ if ( data->ligs[cnt][ccnt-1]==NULL )
+ err = 1;
+ }
+ if ( !err )
+ data->ligs[cnt++][ccnt] = NULL;
+ }
+ }
+ if ( cnt>=data->lmax )
+ data->ligs = grealloc(data->ligs,(data->lmax+=1)*sizeof(SplineChar **));
+ data->ligs[cnt] = NULL;
+ data->lcnt = cnt;
+}
+
+static int GlyphNameInClass(char *name,char *class ) {
+ char *pt;
+ int len = strlen(name);
+
+ pt = class;
+ while ( (pt=strstr(pt,name))!=NULL ) {
+ if ( pt==NULL )
+return( false );
+ if ( (pt==class || pt[-1]==' ') && (pt[len]=='\0' || pt[len]==' '))
+return( true );
+ pt+=len;
+ }
+
+return( false );
+}
+
+static int skipglyphs(int lookup_flags, struct lookup_data *data, int pos) {
+ int mc, glyph_class;
+ /* The lookup flags tell us what glyphs to ignore. Skip over anything we */
+ /* should ignore */
+
+ if ( lookup_flags==0 )
+return( pos );
+ mc = (lookup_flags>>8);
+ if ( mc<0 || mc>=data->sf->mark_class_cnt )
+ mc = 0;
+ while ( pos<data->cnt ) {
+ glyph_class = gdefclass(data->str[pos].sc);
+ /* 1=>base, 2=>ligature, 3=>mark, 4=>component?, 0=>.notdef */
+ if ( (glyph_class==1 && (lookup_flags&pst_ignorebaseglyphs)) ||
+ (glyph_class==2 && (lookup_flags&pst_ignoreligatures)) ||
+ (glyph_class==3 && (lookup_flags&pst_ignorecombiningmarks)) ||
+ (glyph_class==3 && mc!=0 &&
+ !GlyphNameInClass(data->str[pos].sc->name,data->sf->mark_classes[mc])) ) {
+ ++pos;
+ } else
+ break;
+ }
+return( pos );
+}
+
+static int bskipglyphs(int lookup_flags, struct lookup_data *data, int pos) {
+ int mc, glyph_class;
+ /* The lookup flags tell us what glyphs to ignore. Skip over anything we */
+ /* should ignore. Here we skip backward */
+
+ if ( lookup_flags==0 )
+return( pos );
+ mc = (lookup_flags>>8);
+ if ( mc<0 || mc>=data->sf->mark_class_cnt )
+ mc = 0;
+ while ( pos>=0 ) {
+ glyph_class = gdefclass(data->str[pos].sc);
+ /* 1=>base, 2=>ligature, 3=>mark, 4=>component?, 0=>.notdef */
+ if ( (glyph_class==1 && (lookup_flags&pst_ignorebaseglyphs)) ||
+ (glyph_class==2 && (lookup_flags&pst_ignoreligatures)) ||
+ (glyph_class==3 && (lookup_flags&pst_ignorecombiningmarks)) ||
+ (glyph_class==3 && mc!=0 &&
+ !GlyphNameInClass(data->str[pos].sc->name,data->sf->mark_classes[mc])) ) {
+ --pos;
+ } else
+ break;
+ }
+return( pos );
+}
+
+static int ContextualMatch(struct lookup_subtable *sub,struct lookup_data *data,
+ int pos, struct fpst_rule **_rule) {
+ int i, cpos, retpos, r;
+ FPST *fpst = sub->fpst;
+ int lookup_flags = sub->lookup->lookup_flags;
+ char *pt;
+
+ /* If we should skip the current glyph then don't try for a match here */
+ cpos = skipglyphs(lookup_flags,data,pos);
+ if ( cpos!=pos )
+return( 0 );
+
+ for ( r=0; r<fpst->rule_cnt; ++r ) {
+ struct fpst_rule *rule = &fpst->rules[r];
+ for ( i=pos; i<data->cnt; ++i )
+ data->str[i].context_pos = -1;
+
+/* Handle backtrack (backtrace in the rule is stored in reverse textual order) */
+ if ( fpst->type == pst_chainpos || fpst->type == pst_chainsub ) {
+ if ( fpst->format==pst_glyphs ) {
+ pt = rule->u.glyph.back;
+ for ( i=bskipglyphs(lookup_flags,data,pos-1), cpos=0; i>=0; i = bskipglyphs(lookup_flags,data,i-1)) {
+ char *name = data->str[i].sc->name;
+ int len = strlen( name );
+ if ( strncmp(name,pt,len)!=0 || (pt[len]!='\0' && pt[len]!=' '))
+ break;
+ pt += len;
+ while ( *pt==' ' ) ++pt;
+ }
+ if ( *pt!='\0' )
+ continue; /* didn't match */
+ } else if ( fpst->format==pst_class ) {
+ for ( i=bskipglyphs(lookup_flags,data,pos-1), cpos=0; i>=0 && cpos<rule->u.class.bcnt; i = bskipglyphs(lookup_flags,data,i-1)) {
+ if ( !GlyphNameInClass(data->str[i].sc->name,fpst->bclass[rule->u.class.bclasses[cpos]]) )
+ break;
+ ++cpos;
+ }
+ if ( cpos!=rule->u.class.bcnt )
+ continue; /* didn't match */
+ } else if ( fpst->format==pst_coverage ) {
+ for ( i=bskipglyphs(lookup_flags,data,pos-1), cpos=0; i>=0 && cpos<rule->u.coverage.bcnt; i = bskipglyphs(lookup_flags,data,i-1)) {
+ if ( !GlyphNameInClass(data->str[i].sc->name,rule->u.coverage.bcovers[cpos]) )
+ break;
+ ++cpos;
+ }
+ if ( cpos<rule->u.coverage.bcnt )
+ continue; /* didn't match */
+ }
+ }
+/* Handle Match */
+ if ( fpst->format==pst_glyphs ) {
+ pt = rule->u.glyph.names;
+ for ( i=pos, cpos=0; i<data->cnt && *pt!='\0'; i = skipglyphs(lookup_flags,data,i+1)) {
+ char *name = data->str[i].sc->name;
+ int len = strlen( name );
+ if ( strncmp(name,pt,len)!=0 || (pt[len]!='\0' && pt[len]!=' '))
+ break;
+ data->str[i].context_pos = cpos++;
+ pt += len;
+ while ( *pt==' ' ) ++pt;
+ }
+ if ( *pt!='\0' )
+ continue; /* didn't match */
+ } else if ( fpst->format==pst_class ) {
+ for ( i=pos, cpos=0; i<data->cnt && cpos<rule->u.class.ncnt; i = skipglyphs(lookup_flags,data,i+1)) {
+ if ( !GlyphNameInClass(data->str[i].sc->name,fpst->nclass[rule->u.class.nclasses[cpos]]) )
+ break;
+ data->str[i].context_pos = cpos++;
+ }
+ if ( cpos<rule->u.class.ncnt )
+ continue; /* didn't match */
+ } else if ( fpst->format==pst_coverage ) {
+ for ( i=pos, cpos=0; i<data->cnt && cpos<rule->u.coverage.ncnt; i = skipglyphs(lookup_flags,data,i+1)) {
+ if ( !GlyphNameInClass(data->str[i].sc->name,rule->u.coverage.ncovers[cpos]) )
+ break;
+ data->str[i].context_pos = cpos++;
+ }
+ if ( cpos<rule->u.coverage.ncnt )
+ continue; /* didn't match */
+ } else
+return( 0 ); /* Not ready to deal with reverse chainging */
+
+ retpos = i;
+/* Handle lookahead */
+ if ( fpst->type == pst_chainpos || fpst->type == pst_chainsub ) {
+ if ( fpst->format==pst_glyphs ) {
+ pt = rule->u.glyph.fore;
+ for ( i=retpos; i<data->cnt && *pt!='\0'; i = skipglyphs(lookup_flags,data,i+1)) {
+ char *name = data->str[i].sc->name;
+ int len = strlen( name );
+ if ( strncmp(name,pt,len)!=0 || (pt[len]!='\0' && pt[len]!=' '))
+ break;
+ pt += len;
+ while ( *pt==' ' ) ++pt;
+ }
+ if ( *pt!='\0' )
+ continue; /* didn't match */
+ } else if ( fpst->format==pst_class ) {
+ for ( i=retpos, cpos=0; i<data->cnt && cpos<rule->u.class.fcnt; i = skipglyphs(lookup_flags,data,i+1)) {
+ if ( !GlyphNameInClass(data->str[i].sc->name,fpst->fclass[rule->u.class.fclasses[cpos]]) )
+ break;
+ cpos++;
+ }
+ if ( cpos<rule->u.class.fcnt )
+ continue; /* didn't match */
+ } else if ( fpst->format==pst_coverage ) {
+ for ( i=retpos, cpos=0; i<data->cnt && cpos<rule->u.coverage.fcnt; i = skipglyphs(lookup_flags,data,i+1)) {
+ if ( !GlyphNameInClass(data->str[i].sc->name,rule->u.coverage.fcovers[cpos]) )
+ break;
+ cpos++;
+ }
+ if ( cpos<rule->u.coverage.fcnt )
+ continue; /* didn't match */
+ }
+ }
+ *_rule = rule;
+return( retpos );
+ }
+return( 0 );
+}
+
+static int ApplySingleSubsAtPos(struct lookup_subtable *sub,struct lookup_data *data,int pos) {
+ PST *pst;
+ SplineChar *sc;
+
+ for ( pst=data->str[pos].sc->possub; pst!=NULL && pst->subtable!=sub; pst=pst->next );
+ if ( pst==NULL )
+return( 0 );
+
+ sc = SFGetChar(data->sf,-1,pst->u.subs.variant);
+ if ( sc==NULL )
+return( 0 );
+ data->str[pos].sc = sc;
+return( pos+1 );
+}
+
+static int ApplyMultSubsAtPos(struct lookup_subtable *sub,struct lookup_data *data,int pos) {
+ PST *pst;
+ SplineChar *sc;
+ char *start, *pt;
+ int mcnt, ch, i;
+ SplineChar *mults[20];
+
+ for ( pst=data->str[pos].sc->possub; pst!=NULL && pst->subtable!=sub; pst=pst->next );
+ if ( pst==NULL )
+return( 0 );
+
+ mcnt = 0;
+ for ( start = pst->u.alt.components; *start==' '; ++start);
+ for ( ; *start; ) {
+ for ( pt=start; *pt!='\0' && *pt!=' '; ++pt );
+ ch = *pt; *pt = '\0';
+ sc = SFGetChar(data->sf,-1,start);
+ *pt = ch;
+ if ( sc==NULL )
+return( 0 );
+ if ( mcnt<20 ) mults[mcnt++] = sc;
+ while ( *pt==' ' ) ++pt;
+ start = pt;
+ }
+
+ if ( mcnt==0 ) {
+ /* Is this legal? that is can we remove a glyph with an empty multiple? */
+ for ( i=pos+1; i<data->cnt; ++i )
+ data->str[i-1] = data->str[i];
+ --data->cnt;
+return( pos );
+ } else if ( mcnt==1 ) {
+ data->str[pos].sc = mults[0];
+return( pos+1 );
+ } else {
+ if ( data->cnt+mcnt-1 >= data->max )
+ data->str = grealloc(data->str,(data->max+=mcnt) * sizeof( struct opentype_str ));
+ for ( i=data->cnt-1; i>pos; --i )
+ data->str[i+mcnt-1] = data->str[i];
+ memset(data->str+pos,0,mcnt*sizeof(struct opentype_str));
+ for ( i=0; i<mcnt; ++i ) {
+ data->str[pos+i].sc = mults[i];
+ data->str[pos+i].orig_index = data->str[pos].orig_index;
+ }
+return( pos+mcnt );
+ }
+}
+
+static int ApplyAltSubsAtPos(struct lookup_subtable *sub,struct lookup_data *data,int pos) {
+ PST *pst;
+ SplineChar *sc;
+ char *start, *pt, ch;
+
+ for ( pst=data->str[pos].sc->possub; pst!=NULL && pst->subtable!=sub; pst=pst->next );
+ if ( pst==NULL )
+return( 0 );
+
+ for ( start = pst->u.alt.components; *start==' '; ++start);
+ for ( ; *start; ) {
+ for ( pt=start; *pt!='\0' && *pt!=' '; ++pt );
+ ch = *pt; *pt = '\0';
+ sc = SFGetChar(data->sf,-1,start);
+ *pt = ch;
+ if ( sc!=NULL ) {
+ data->str[pos].sc = sc;
+return( pos+1 );
+ }
+ while ( *pt==' ' ) ++pt;
+ start = pt;
+ }
+return( 0 );
+}
+
+static int ApplyLigatureSubsAtPos(struct lookup_subtable *sub,struct lookup_data *data,int pos) {
+ int i,k, lpos, npos;
+ int lookup_flags = sub->lookup->lookup_flags;
+ int match_found = -1, match_len=0;
+
+ if ( data->lig_owner!=sub )
+ LigatureSearch(sub,data);
+ for ( i=0; i<data->lcnt; ++i ) {
+ if ( data->ligs[i][1]==data->str[pos].sc ) {
+ lpos = 0;
+ npos = pos+1;
+ for ( k=2; data->ligs[i][k]!=NULL; ++k ) {
+ npos = skipglyphs(lookup_flags,data,npos);
+ if ( npos>=data->cnt || data->str[npos].sc != data->ligs[i][k] )
+ break;
+ ++npos;
+ }
+ if ( data->ligs[i][k]==NULL ) {
+ if ( match_found==-1 || k>match_len ) {
+ match_found = i;
+ match_len = k;
+ }
+ }
+ }
+ }
+ if ( match_found!=-1 ) {
+ /* Matched. Remove the component glyphs, and note which component */
+ /* any intervening marks should be attached to */
+ data->str[pos].sc = data->ligs[match_found][0];
+ npos = pos+1;
+ for ( k=2; data->ligs[match_found][k]!=NULL; ++k ) {
+ lpos = skipglyphs(lookup_flags,data,npos);
+ for ( ; npos<lpos; ++npos )
+ data->str[npos].lig_pos = k-2;
+ /* Remove this glyph */
+ for ( ++lpos; lpos<data->cnt; ++lpos )
+ data->str[lpos-1] = data->str[lpos];
+ --data->cnt;
+ }
+ /* Any marks after the last component (which should be attached */
+ /* to it) will not have been tagged, so do that now */
+ lpos = skipglyphs(lookup_flags,data,npos);
+ for ( ; npos<lpos; ++npos )
+ data->str[npos].lig_pos = k-2;
+return( pos+1 );
+ }
+
+return( 0 );
+}
+
+static int ApplyContextual(struct lookup_subtable *sub,struct lookup_data *data,int pos) {
+ /* On this level there is no difference between GPOS/GSUB contextuals */
+ /* If the contextual matches, then we apply the lookups, otherwise we */
+ /* don't. Now the lookups will be different, but we don't care here */
+ struct fpst_rule *rule;
+ int retpos, i,j;
+
+ retpos = ContextualMatch(sub,data,pos,&rule);
+ if ( retpos==0 )
+return( 0 );
+ for ( i=0; i<rule->lookup_cnt; ++i ) {
+ for ( j=pos; j<data->cnt; ++j ) {
+ if ( data->str[j].context_pos == rule->lookups[i].seq ) {
+ ApplyLookupAtPos(0,rule->lookups[i].lookup,data,j);
+ break;
+ }
+ }
+ }
+return( retpos );
+}
+
+static int ApplySinglePosAtPos(struct lookup_subtable *sub,struct lookup_data *data,int pos) {
+ PST *pst;
+
+ for ( pst=data->str[pos].sc->possub; pst!=NULL && pst->subtable!=sub; pst=pst->next );
+ if ( pst==NULL )
+return( 0 );
+
+ data->str[pos].vr.xoff += pst->u.pos.xoff;
+ data->str[pos].vr.yoff += pst->u.pos.yoff;
+ data->str[pos].vr.h_adv_off += pst->u.pos.h_adv_off;
+ data->str[pos].vr.v_adv_off += pst->u.pos.v_adv_off;
+return( pos+1 );
+}
+
+static int ApplyPairPosAtPos(struct lookup_subtable *sub,struct lookup_data *data,int pos) {
+ PST *pst;
+ int npos, isv, within;
+ KernPair *kp;
+
+ npos = skipglyphs(sub->lookup->lookup_flags,data,pos+1);
+ if ( npos>=data->cnt )
+return( 0 );
+ if ( sub->kc!=NULL ) {
+ within = KCFindIndex(sub->kc,data->str[pos].sc->name,data->str[npos].sc->name);
+ if ( within==-1 )
+return( 0 );
+ data->str[pos].kc_index = within;
+ data->str[pos].kc = sub->kc;
+ if ( sub->vertical_kerning )
+ data->str[pos].vr.v_adv_off += sub->kc->offsets[within];
+ else if ( sub->lookup->lookup_flags & pst_r2l )
+ data->str[npos].vr.h_adv_off += sub->kc->offsets[within];
+ else
+ data->str[pos].vr.h_adv_off += sub->kc->offsets[within];
+return( pos+1 );
+ } else {
+ for ( pst=data->str[pos].sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable==sub && strcmp(pst->u.pair.paired,data->str[npos].sc->name)==0 ) {
+ data->str[pos].vr.xoff += pst->u.pair.vr[0].xoff;
+ data->str[pos].vr.yoff += pst->u.pair.vr[0].yoff;
+ data->str[pos].vr.h_adv_off += pst->u.pair.vr[0].h_adv_off;
+ data->str[pos].vr.v_adv_off += pst->u.pair.vr[0].v_adv_off;
+ data->str[npos].vr.xoff += pst->u.pair.vr[1].xoff;
+ data->str[npos].vr.yoff += pst->u.pair.vr[1].yoff;
+ data->str[npos].vr.h_adv_off += pst->u.pair.vr[1].h_adv_off;
+ data->str[npos].vr.v_adv_off += pst->u.pair.vr[1].v_adv_off;
+return( pos+1 ); /* We do NOT want to return npos+1 */
+ }
+ }
+ for ( isv = 0; isv<2; ++isv ) {
+ for ( kp = isv ? data->str[pos].sc->vkerns : data->str[pos].sc->kerns; kp!=NULL; kp=kp->next ) {
+ if ( kp->subtable == sub && kp->sc == data->str[npos].sc ) {
+ data->str[pos].kp = kp;
+ if ( isv )
+ data->str[pos].vr.v_adv_off += kp->off;
+ else if ( sub->lookup->lookup_flags & pst_r2l )
+ data->str[npos].vr.h_adv_off += kp->off;
+ else
+ data->str[pos].vr.h_adv_off += kp->off;
+return( pos+1 );
+ }
+ }
+ }
+ }
+
+return( 0 );
+}
+
+static int ApplyAnchorPosAtPos(struct lookup_subtable *sub,struct lookup_data *data,int pos) {
+ AnchorPoint *ap1, *ap2;
+ int npos;
+
+ npos = skipglyphs(sub->lookup->lookup_flags,data,pos+1);
+ if ( npos>=data->cnt )
+return( 0 );
+ if ( sub->lookup->lookup_type == gpos_cursive ) {
+ for ( ap1=data->str[pos].sc->anchor; ap1!=NULL ; ap1=ap1->next ) {
+ if ( ap1->anchor->subtable==sub && ap1->type==at_cexit ) {
+ for ( ap2 = data->str[npos].sc->anchor; ap2!=NULL; ap2=ap2->next ) {
+ if ( ap2->anchor==ap1->anchor && ap2->type==at_centry )
+ break;
+ }
+ if ( ap2!=NULL )
+ break;
+ }
+ }
+ } else if ( sub->lookup->lookup_type == gpos_mark2ligature ) {
+ for ( ap1=data->str[pos].sc->anchor; ap1!=NULL ; ap1=ap1->next ) {
+ if ( ap1->anchor->subtable==sub && ap1->type==at_baselig &&
+ ap1->lig_index == data->str[npos].lig_pos ) {
+ for ( ap2 = data->str[npos].sc->anchor; ap2!=NULL; ap2=ap2->next ) {
+ if ( ap2->anchor==ap1->anchor && ap2->type==at_mark )
+ break;
+ }
+ if ( ap2!=NULL )
+ break;
+ }
+ }
+ } else {
+ for ( ap1=data->str[pos].sc->anchor; ap1!=NULL ; ap1=ap1->next ) {
+ if ( ap1->anchor->subtable==sub && (ap1->type==at_basechar || ap1->type==at_basemark)) {
+ for ( ap2 = data->str[npos].sc->anchor; ap2!=NULL; ap2=ap2->next ) {
+ if ( ap2->anchor==ap1->anchor && ap2->type==at_mark )
+ break;
+ }
+ if ( ap2!=NULL )
+ break;
+ }
+ }
+ }
+ if ( ap1==NULL )
+return( 0 );
+
+ data->str[npos].vr.yoff = ap1->me.y - ap2->me.y;
+ if ( sub->lookup->lookup_flags&pst_r2l ) {
+ data->str[npos].vr.xoff = -(ap1->me.x - ap2->me.x);
+ } else {
+ data->str[npos].vr.xoff = ap1->me.x - ap2->me.x - data->str[pos].sc->width;
+ }
+return( pos+1 );
+}
+
+static int ConditionalTagOk(uint32 tag, OTLookup *otl,struct lookup_data *data,int pos) {
+ int npos, bpos;
+ uint32 script;
+ int before_in_script, after_in_script;
+
+ if ( tag==CHR('i','n','i','t') || tag==CHR('i','s','o','l') ||
+ tag==CHR('f','i','n','a') || tag==CHR('m','e','d','i') ) {
+ npos = skipglyphs(otl->lookup_flags,data,pos+1);
+ bpos = bskipglyphs(otl->lookup_flags,data,pos-1);
+ script = SCScriptFromUnicode(data->str[pos].sc);
+ before_in_script = (bpos>=0 && SCScriptFromUnicode(data->str[bpos].sc)==script);
+ after_in_script = (npos<data->cnt && SCScriptFromUnicode(data->str[npos].sc)==script);
+ if ( tag==CHR('i','n','i','t') )
+return( !before_in_script && after_in_script );
+ else if ( tag==CHR('i','s','o','l') )
+return( !before_in_script && !after_in_script );
+ else if ( tag==CHR('f','i','n','a') )
+return( before_in_script && !after_in_script );
+ else
+return( before_in_script && after_in_script );
+ }
+
+return( true );
+}
+
+static int ApplyLookupAtPos(uint32 tag, OTLookup *otl,struct lookup_data *data,int pos) {
+ struct lookup_subtable *sub;
+ int newpos;
+
+ /* Some tags imply a conditional check. Do that now */
+ if ( !ConditionalTagOk(tag,otl,data,pos))
+return( 0 );
+
+ for ( sub=otl->subtables; sub!=NULL; sub=sub->next ) {
+ switch ( otl->lookup_type ) {
+ case gsub_single:
+ newpos = ApplySingleSubsAtPos(sub,data,pos);
+ break;
+ case gsub_multiple:
+ newpos = ApplyMultSubsAtPos(sub,data,pos);
+ break;
+ case gsub_alternate:
+ newpos = ApplyAltSubsAtPos(sub,data,pos);
+ break;
+ case gsub_ligature:
+ newpos = ApplyLigatureSubsAtPos(sub,data,pos);
+ break;
+ case gsub_context:
+ newpos = ApplyContextual(sub,data,pos);
+ break;
+ case gsub_contextchain:
+ newpos = ApplyContextual(sub,data,pos);
+ break;
+ case gsub_reversecchain:
+ newpos = ApplySingleSubsAtPos(sub,data,pos);
+ break;
+
+ case gpos_single:
+ newpos = ApplySinglePosAtPos(sub,data,pos);
+ break;
+ case gpos_pair:
+ newpos = ApplyPairPosAtPos(sub,data,pos);
+ break;
+ case gpos_cursive:
+ newpos = ApplyAnchorPosAtPos(sub,data,pos);
+ break;
+ case gpos_mark2base:
+ newpos = ApplyAnchorPosAtPos(sub,data,pos);
+ break;
+ case gpos_mark2ligature:
+ newpos = ApplyAnchorPosAtPos(sub,data,pos);
+ break;
+ case gpos_mark2mark:
+ newpos = ApplyAnchorPosAtPos(sub,data,pos);
+ break;
+ case gpos_context:
+ newpos = ApplyContextual(sub,data,pos);
+ break;
+ case gpos_contextchain:
+ newpos = ApplyContextual(sub,data,pos);
+ break;
+ default:
+ /* apple state machines */
+ newpos = 0;
+ break;
+ }
+ /* if a subtable worked, we don't try to apply the next one */
+ if ( newpos!=0 )
+return( newpos );
+ }
+return( 0 );
+}
+
+static void ApplyLookup(uint32 tag, OTLookup *otl,struct lookup_data *data) {
+ int pos, npos;
+
+ for ( pos = 0; pos<data->cnt; ) {
+ npos = ApplyLookupAtPos(tag,otl,data,pos);
+ if ( npos==0 )
+ npos = pos+1;
+ pos = npos;
+ }
+}
+
+static uint32 FSLLMatches(FeatureScriptLangList *fl,uint32 *flist,uint32 script,uint32 lang) {
+ int i,l;
+ struct scriptlanglist *sl;
+
+ while ( fl!=NULL ) {
+ for ( i=0; flist[i]!=0; ++i ) {
+ if ( fl->featuretag==flist[i] )
+ break;
+ }
+ if ( flist[i]!=0 ) {
+ for ( sl=fl->scripts; sl!=NULL; sl=sl->next ) {
+ if ( sl->script == script ) {
+ for ( l=0; l<sl->lang_cnt; ++l )
+ if ( (l<MAX_LANG && sl->langs[l]==lang) ||
+ (l>=MAX_LANG && sl->morelangs[l-MAX_LANG]==lang))
+return( fl->featuretag );
+ }
+ }
+ }
+ fl = fl->next;
+ }
+return( 0 );
+}
+
+/* This routine takes a string of glyphs and applies the opentype transformations */
+/* indicated by the features (and script and language) we are passed, it returns */
+/* a transformed string with substitutions applied and containing positioning */
+/* info */
+struct opentype_str *ApplyTickedFeatures(SplineFont *sf,uint32 *flist, uint32 script, uint32 lang,
+ SplineChar **glyphs) {
+ int isgpos, cnt;
+ OTLookup *otl;
+ struct lookup_data data;
+ uint32 *langs, templang;
+ int i;
+
+ memset(&data,0,sizeof(data));
+ for ( cnt=0; glyphs[cnt]!=NULL; ++cnt );
+ data.str = gcalloc(cnt+1,sizeof(struct opentype_str));
+ data.cnt = data.max = cnt;
+ for ( cnt=0; glyphs[cnt]!=NULL; ++cnt ) {
+ data.str[cnt].sc = glyphs[cnt];
+ data.str[cnt].orig_index = cnt;
+ }
+ if ( sf->cidmaster!=NULL ) sf=sf->cidmaster;
+ data.sf = sf;
+
+ /* Indic glyph reordering???? */
+ for ( isgpos=0; isgpos<2; ++isgpos ) {
+ /* Check that this table has an entry for this language */
+ /* if it doesn't use the default language */
+ /* GPOS/GSUB may have different language sets, so we must be prepared */
+ templang = lang;
+ langs = SFLangsInScript(sf,isgpos,script);
+ for ( i=0; langs[i]!=0 && langs[i]!=lang; ++i );
+ if ( langs[i]==0 )
+ templang = DEFAULT_LANG;
+ free(langs);
+
+ for ( otl = isgpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL ; otl = otl->next ) {
+ uint32 tag;
+ if ( (tag=FSLLMatches(otl->features,flist,script,templang))!=0 )
+ ApplyLookup(tag,otl,&data);
+ }
+ }
+ LigatureFree(&data);
+ free(data.ligs);
+
+ data.str = grealloc(data.str,(data.cnt+1)*sizeof(struct opentype_str));
+ memset(&data.str[data.cnt],0,sizeof(struct opentype_str));
+return( data.str );
+}
+
+/* ************************************************************************** */
+/* ******************************* UI routines ****************************** */
+/* ************************************************************************** */
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+
+GTextInfo **SFLookupListFromType(SplineFont *sf, int lookup_type ) {
+ int isgpos = (lookup_type>=gpos_start);
+ int k, cnt;
+ OTLookup *otl;
+ GTextInfo **ti;
+
+ for ( k=0; k<2; ++k ) {
+ cnt = 0;
+ for ( otl= isgpos ? sf->gpos_lookups : sf->gsub_lookups ; otl!=NULL; otl=otl->next ) {
+ if ( lookup_type==gsub_start || lookup_type==gpos_start ||
+ otl->lookup_type == lookup_type ) {
+ if ( k ) {
+ ti[cnt] = gcalloc(1,sizeof(GTextInfo));
+ ti[cnt]->userdata = (void *) otl;
+ ti[cnt]->fg = ti[cnt]->bg = COLOR_DEFAULT;
+ ti[cnt]->text = utf82u_copy(otl->lookup_name);
+ }
+ ++cnt;
+ }
+ }
+ if ( !k )
+ ti = gcalloc(cnt+2,sizeof(GTextInfo *));
+ else
+ ti[cnt] = gcalloc(1,sizeof(GTextInfo));
+ }
+return( ti );
+}
+
+/* ************************************************************************** */
+/* ********************** Lookup dialog and subdialogs ********************** */
+/* ************************************************************************** */
+
+static GTextInfo gsub_lookuptypes[] = {
+ { (unichar_t *) N_("Lookup Type|Unspecified"), NULL, 0, 0, (void *) ot_undef, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Single Substitution"), NULL, 0, 0, (void *) gsub_single, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Multiple Substitution"), NULL, 0, 0, (void *) gsub_multiple, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Alternate Substitution"), NULL, 0, 0, (void *) gsub_alternate, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Ligature Substitution"), NULL, 0, 0, (void *) gsub_ligature, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Contextual Substitution"), NULL, 0, 0, (void *) gsub_context, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Contextual Chaining Substitution"), NULL, 0, 0, (void *) gsub_contextchain, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Reverse Chaining Substitution"), NULL, 0, 0, (void *) gsub_reversecchain, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL, NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 1}, /* Line */
+ { (unichar_t *) N_("Mac Indic State Machine"), NULL, 0, 0, (void *) morx_indic, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Mac Contextual State Machine"), NULL, 0, 0, (void *) morx_context, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Mac Insertion State Machine"), NULL, 0, 0, (void *) morx_insert, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo gpos_lookuptypes[] = {
+ { (unichar_t *) N_("Lookup Type|Unspecified"), NULL, 0, 0, (void *) ot_undef, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Single Position"), NULL, 0, 0, (void *) gpos_single, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Pair Position (kerning)"), NULL, 0, 0, (void *) gpos_pair, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Cursive Position"), NULL, 0, 0, (void *) gpos_cursive, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Mark to Base Position"), NULL, 0, 0, (void *) gpos_mark2base, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Mark to Ligature Position"), NULL, 0, 0, (void *) gpos_mark2ligature, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Mark to Mark Position"), NULL, 0, 0, (void *) gpos_mark2mark, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Contextual Position"), NULL, 0, 0, (void *) gpos_context, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Contextual Chaining Position"), NULL, 0, 0, (void *) gpos_contextchain, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL, NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 1}, /* Line */
+ { (unichar_t *) N_("Mac Kerning State Machine"), NULL, 0, 0, (void *) kern_statemachine, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+static GTextInfo *lookuptypes[2] = { gsub_lookuptypes, gpos_lookuptypes };
+
+ /* see also list in tottfgpos.c mapping code points to scripts */
+GTextInfo scripts[] = {
+/* GT: See the long comment at "Property|New" */
+/* GT: The msgstr should contain a translation of "Arabic", ignore "Script|" */
+ { (unichar_t *) N_("Script|Arabic"), NULL, 0, 0, (void *) CHR('a','r','a','b'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Aramaic"), NULL, 0, 0, (void *) CHR('a','r','a','m'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Armenian"), NULL, 0, 0, (void *) CHR('a','r','m','n'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Avestan"), NULL, 0, 0, (void *) CHR('a','v','e','s'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Balinese"), NULL, 0, 0, (void *) CHR('b','a','l','i'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Batak"), NULL, 0, 0, (void *) CHR('b','a','t','k'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Bengali"), NULL, 0, 0, (void *) CHR('b','e','n','g'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Bengali2"), NULL, 0, 0, (void *) CHR('b','n','g','2'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Bliss Symbolics"), NULL, 0, 0, (void *) CHR('b','l','i','s'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Bopomofo"), NULL, 0, 0, (void *) CHR('b','o','p','o'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) NU_("BrÄhmÄ«"), NULL, 0, 0, (void *) CHR('b','r','a','h'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Braille"), NULL, 0, 0, (void *) CHR('b','r','a','i'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Buginese"), NULL, 0, 0, (void *) CHR('b','u','g','i'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Buhid"), NULL, 0, 0, (void *) CHR('b','u','h','d'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Byzantine Music"), NULL, 0, 0, (void *) CHR('b','y','z','m'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Canadian Syllabics"), NULL, 0, 0, (void *) CHR('c','a','n','s'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Cham"), NULL, 0, 0, (void *) CHR('c','h','a','m'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Cherokee"), NULL, 0, 0, (void *) CHR('c','h','e','r'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Cirth"), NULL, 0, 0, (void *) CHR('c','i','r','t'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("CJK Ideographic"), NULL, 0, 0, (void *) CHR('h','a','n','i'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Coptic"), NULL, 0, 0, (void *) CHR('c','o','p','t'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Cypro-Minoan"), NULL, 0, 0, (void *) CHR('c','p','r','t'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Cypriot syllabary"), NULL, 0, 0, (void *) CHR('c','p','m','n'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Cyrillic"), NULL, 0, 0, (void *) CHR('c','y','r','l'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Default"), NULL, 0, 0, (void *) CHR('D','F','L','T'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Deseret (Mormon)"), NULL, 0, 0, (void *) CHR('d','s','r','t'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Devanagari"), NULL, 0, 0, (void *) CHR('d','e','v','a'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Devanagari2"), NULL, 0, 0, (void *) CHR('d','e','v','2'), NULL, false, false, false, false, false, false, true },
+/* { (unichar_t *) N_("Egyptian demotic"), NULL, 0, 0, (void *) CHR('e','g','y','d'), NULL, false, false, false, false, false, false, true }, */
+/* { (unichar_t *) N_("Egyptian hieratic"), NULL, 0, 0, (void *) CHR('e','g','y','h'), NULL, false, false, false, false, false, false, true }, */
+/* GT: Someone asked if FontForge actually was prepared generate hieroglyph output */
+/* GT: because of this string. No. But OpenType and Unicode have placeholders for */
+/* GT: dealing with these scripts against the day someone wants to use them. So */
+/* GT: FontForge must be prepared to deal with those placeholders if nothing else. */
+/* { (unichar_t *) N_("Egyptian hieroglyphs"), NULL, 0, 0, (void *) CHR('e','g','y','p'), NULL, false, false, false, false, false, false, true }, */
+ { (unichar_t *) N_("Script|Ethiopic"), NULL, 0, 0, (void *) CHR('e','t','h','i'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Georgian"), NULL, 0, 0, (void *) CHR('g','e','o','r'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Glagolitic"), NULL, 0, 0, (void *) CHR('g','l','a','g'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Gothic"), NULL, 0, 0, (void *) CHR('g','o','t','h'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Greek"), NULL, 0, 0, (void *) CHR('g','r','e','k'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Gujarati"), NULL, 0, 0, (void *) CHR('g','u','j','r'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Gujarati2"), NULL, 0, 0, (void *) CHR('g','j','r','2'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Gurmukhi"), NULL, 0, 0, (void *) CHR('g','u','r','u'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Gurmukhi2"), NULL, 0, 0, (void *) CHR('g','u','r','2'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Hangul Jamo"), NULL, 0, 0, (void *) CHR('j','a','m','o'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Hangul"), NULL, 0, 0, (void *) CHR('h','a','n','g'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) NU_("Script|Hanunóo"), NULL, 0, 0, (void *) CHR('h','a','n','o'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Hebrew"), NULL, 0, 0, (void *) CHR('h','e','b','r'), NULL, false, false, false, false, false, false, true },
+/* { (unichar_t *) N_("Pahawh Hmong"), NULL, 0, 0, (void *) CHR('h','m','n','g'), NULL, false, false, false, false, false, false, true },*/
+/* { (unichar_t *) N_("Indus (Harappan)"), NULL, 0, 0, (void *) CHR('i','n','d','s'), NULL, false, false, false, false, false, false, true },*/
+ { (unichar_t *) N_("Script|Javanese"), NULL, 0, 0, (void *) CHR('j','a','v','a'), NULL, false, false, false, false, false, false, true },
+/* { (unichar_t *) N_("Kayah Li"), NULL, 0, 0, (void *) CHR('k','a','l','i'), NULL, false, false, false, false, false, false, true },*/
+ { (unichar_t *) N_("Hiragana & Katakana"), NULL, 0, 0, (void *) CHR('k','a','n','a'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) NU_("Kharoṣṭhī"), NULL, 0, 0, (void *) CHR('k','h','a','r'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Kannada"), NULL, 0, 0, (void *) CHR('k','n','d','a'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Kannada2"), NULL, 0, 0, (void *) CHR('k','n','d','2'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Khmer"), NULL, 0, 0, (void *) CHR('k','h','m','r'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Kharosthi"), NULL, 0, 0, (void *) CHR('k','h','a','r'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Lao") , NULL, 0, 0, (void *) CHR('l','a','o',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Latin"), NULL, 0, 0, (void *) CHR('l','a','t','n'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) NU_("Lepcha (Róng)"), NULL, 0, 0, (void *) CHR('l','e','p','c'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Limbu"), NULL, 0, 0, (void *) CHR('l','i','m','b'), NULL, false, false, false, false, false, false, true }, /* Not in ISO 15924 !!!!!, just guessing */
+ { (unichar_t *) N_("Linear A"), NULL, 0, 0, (void *) CHR('l','i','n','a'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Linear B"), NULL, 0, 0, (void *) CHR('l','i','n','b'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Mandaean"), NULL, 0, 0, (void *) CHR('m','a','n','d'), NULL, false, false, false, false, false, false, true },
+/* { (unichar_t *) N_("Mayan hieroglyphs"), NULL, 0, 0, (void *) CHR('m','a','y','a'), NULL, false, false, false, false, false, false, true },*/
+ { (unichar_t *) NU_("Script|MalayÄlam"), NULL, 0, 0, (void *) CHR('m','l','y','m'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) NU_("Script|MalayÄlam2"), NULL, 0, 0, (void *) CHR('m','l','y','2'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) NU_("Mathematical Alphanumeric Symbols"), NULL, 0, 0, (void *) CHR('m','a','t','h'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Mongolian"), NULL, 0, 0, (void *) CHR('m','o','n','g'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Musical"), NULL, 0, 0, (void *) CHR('m','u','s','i'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Myanmar"), NULL, 0, 0, (void *) CHR('m','y','m','r'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("N'Ko"), NULL, 0, 0, (void *) CHR('n','k','o',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ogham"), NULL, 0, 0, (void *) CHR('o','g','a','m'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Old Italic (Etruscan, Oscan, etc.)"), NULL, 0, 0, (void *) CHR('i','t','a','l'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Old Permic"), NULL, 0, 0, (void *) CHR('p','e','r','m'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Old Persian cuneiform"), NULL, 0, 0, (void *) CHR('x','p','e','o'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Oriya"), NULL, 0, 0, (void *) CHR('o','r','y','a'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Oriya2"), NULL, 0, 0, (void *) CHR('o','r','y','2'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Osmanya"), NULL, 0, 0, (void *) CHR('o','s','m','a'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Pahlavi"), NULL, 0, 0, (void *) CHR('p','a','l','v'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Phags-pa"), NULL, 0, 0, (void *) CHR('p','h','a','g'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Phoenician"), NULL, 0, 0, (void *) CHR('p','h','n','x'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Phaistos"), NULL, 0, 0, (void *) CHR('p','h','s','t'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Pollard Phonetic"), NULL, 0, 0, (void *) CHR('p','l','r','d'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Rongorongo"), NULL, 0, 0, (void *) CHR('r','o','r','o'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Runic"), NULL, 0, 0, (void *) CHR('r','u','n','r'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Shavian"), NULL, 0, 0, (void *) CHR('s','h','a','w'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Sinhala"), NULL, 0, 0, (void *) CHR('s','i','n','h'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Sumero-Akkadian Cuneiform"), NULL, 0, 0, (void *) CHR('x','s','u','x'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Syloti Nagri"), NULL, 0, 0, (void *) CHR('s','y','l','o'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Syriac"), NULL, 0, 0, (void *) CHR('s','y','r','c'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Tagalog"), NULL, 0, 0, (void *) CHR('t','g','l','g'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Tagbanwa"), NULL, 0, 0, (void *) CHR('t','a','g','b'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tai Le"), NULL, 0, 0, (void *) CHR('t','a','l','e'), NULL, false, false, false, false, false, false, true }, /* Not in ISO 15924 !!!!!, just guessing */
+ { (unichar_t *) N_("Tai Lu"), NULL, 0, 0, (void *) CHR('t','a','l','a'), NULL, false, false, false, false, false, false, true }, /* Not in ISO 15924 !!!!!, just guessing */
+ { (unichar_t *) N_("Script|Tamil"), NULL, 0, 0, (void *) CHR('t','a','m','l'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Tamil2"), NULL, 0, 0, (void *) CHR('t','m','l','2'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Telugu"), NULL, 0, 0, (void *) CHR('t','e','l','u'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Telugu2"), NULL, 0, 0, (void *) CHR('t','e','l','2'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tengwar"), NULL, 0, 0, (void *) CHR('t','e','n','g'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Thaana"), NULL, 0, 0, (void *) CHR('t','h','a','a'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Thai"), NULL, 0, 0, (void *) CHR('t','h','a','i'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Tibetan"), NULL, 0, 0, (void *) CHR('t','i','b','t'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tifinagh (Berber)"), NULL, 0, 0, (void *) CHR('t','f','n','g'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Ugaritic"), NULL, 0, 0, (void *) CHR('u','g','r','t'), NULL, false, false, false, false, false, false, true }, /* Not in ISO 15924 !!!!!, just guessing */
+ { (unichar_t *) N_("Script|Vai"), NULL, 0, 0, (void *) CHR('v','a','i',' '), NULL, false, false, false, false, false, false, true },
+/* { (unichar_t *) N_("Visible Speech"), NULL, 0, 0, (void *) CHR('v','i','s','p'), NULL, false, false, false, false, false, false, true },*/
+ { (unichar_t *) N_("Cuneiform, Ugaritic"), NULL, 0, 0, (void *) CHR('x','u','g','a'), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Script|Yi") , NULL, 0, 0, (void *) CHR('y','i',' ',' '), NULL, false, false, false, false, false, false, true },
+/* { (unichar_t *) N_("Private Use Script 1") , NULL, 0, 0, (void *) CHR('q','a','a','a'), NULL, false, false, false, false, false, false, true },*/
+/* { (unichar_t *) N_("Private Use Script 2") , NULL, 0, 0, (void *) CHR('q','a','a','b'), NULL, false, false, false, false, false, false, true },*/
+/* { (unichar_t *) N_("Undetermined Script") , NULL, 0, 0, (void *) CHR('z','y','y','y'), NULL, false, false, false, false, false, false, true },*/
+/* { (unichar_t *) N_("Uncoded Script") , NULL, 0, 0, (void *) CHR('z','z','z','z'), NULL, false, false, false, false, false, false, true },*/
+ { NULL }
+};
+
+GTextInfo languages[] = {
+ { (unichar_t *) N_("Abaza"), NULL, 0, 0, (void *) CHR('A','B','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Abkhazian"), NULL, 0, 0, (void *) CHR('A','B','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Adyghe"), NULL, 0, 0, (void *) CHR('A','D','Y',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Afrikaans"), NULL, 0, 0, (void *) CHR('A','F','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Afar"), NULL, 0, 0, (void *) CHR('A','F','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Agaw"), NULL, 0, 0, (void *) CHR('A','G','W',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Altai"), NULL, 0, 0, (void *) CHR('A','L','T',' '), NULL, false, false, false, false, false, false, true },
+/* GT: See the long comment at "Property|New" */
+/* GT: The msgstr should contain a translation of "Amharic", ignore "Lang|" */
+ { (unichar_t *) N_("Lang|Amharic"), NULL, 0, 0, (void *) CHR('A','M','H',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Arabic"), NULL, 0, 0, (void *) CHR('A','R','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Aari"), NULL, 0, 0, (void *) CHR('A','R','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Arakanese"), NULL, 0, 0, (void *) CHR('A','R','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Assamese"), NULL, 0, 0, (void *) CHR('A','S','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Athapaskan"), NULL, 0, 0, (void *) CHR('A','T','H',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Avar"), NULL, 0, 0, (void *) CHR('A','V','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Awadhi"), NULL, 0, 0, (void *) CHR('A','W','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Aymara"), NULL, 0, 0, (void *) CHR('A','Y','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Azeri"), NULL, 0, 0, (void *) CHR('A','Z','E',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Badaga"), NULL, 0, 0, (void *) CHR('B','A','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Baghelkhandi"), NULL, 0, 0, (void *) CHR('B','A','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Balkar"), NULL, 0, 0, (void *) CHR('B','A','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Baule"), NULL, 0, 0, (void *) CHR('B','A','U',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Berber"), NULL, 0, 0, (void *) CHR('B','B','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Bench"), NULL, 0, 0, (void *) CHR('B','C','H',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Bible Cree"), NULL, 0, 0, (void *) CHR('B','C','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Belarussian"), NULL, 0, 0, (void *) CHR('B','E','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Bemba"), NULL, 0, 0, (void *) CHR('B','E','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Bengali"), NULL, 0, 0, (void *) CHR('B','E','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Bulgarian"), NULL, 0, 0, (void *) CHR('B','G','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Bhili"), NULL, 0, 0, (void *) CHR('B','H','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Bhojpuri"), NULL, 0, 0, (void *) CHR('B','H','O',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Bikol"), NULL, 0, 0, (void *) CHR('B','I','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Bilen"), NULL, 0, 0, (void *) CHR('B','I','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Blackfoot"), NULL, 0, 0, (void *) CHR('B','K','F',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Balochi"), NULL, 0, 0, (void *) CHR('B','L','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Balante"), NULL, 0, 0, (void *) CHR('B','L','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Balti"), NULL, 0, 0, (void *) CHR('B','L','T',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Bambara"), NULL, 0, 0, (void *) CHR('B','M','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Bamileke"), NULL, 0, 0, (void *) CHR('B','M','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Breton"), NULL, 0, 0, (void *) CHR('B','R','E',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Brahui"), NULL, 0, 0, (void *) CHR('B','R','H',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Braj Bhasha"), NULL, 0, 0, (void *) CHR('B','R','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Burmese"), NULL, 0, 0, (void *) CHR('B','R','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Bashkir"), NULL, 0, 0, (void *) CHR('B','S','H',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Beti"), NULL, 0, 0, (void *) CHR('B','T','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Catalan"), NULL, 0, 0, (void *) CHR('C','A','T',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Cebuano"), NULL, 0, 0, (void *) CHR('C','E','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Chechen"), NULL, 0, 0, (void *) CHR('C','H','E',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Chaha Gurage"), NULL, 0, 0, (void *) CHR('C','H','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Chattisgarhi"), NULL, 0, 0, (void *) CHR('C','H','H',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Chichewa"), NULL, 0, 0, (void *) CHR('C','H','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Chukchi"), NULL, 0, 0, (void *) CHR('C','H','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Chipewyan"), NULL, 0, 0, (void *) CHR('C','H','P',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Cherokee"), NULL, 0, 0, (void *) CHR('C','H','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Chuvash"), NULL, 0, 0, (void *) CHR('C','H','U',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Comorian"), NULL, 0, 0, (void *) CHR('C','M','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Coptic"), NULL, 0, 0, (void *) CHR('C','O','P',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Cree"), NULL, 0, 0, (void *) CHR('C','R','E',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Carrier"), NULL, 0, 0, (void *) CHR('C','R','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Crimean Tatar"), NULL, 0, 0, (void *) CHR('C','R','T',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Church Slavonic"), NULL, 0, 0, (void *) CHR('C','S','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Czech"), NULL, 0, 0, (void *) CHR('C','S','Y',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Danish"), NULL, 0, 0, (void *) CHR('D','A','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Dargwa"), NULL, 0, 0, (void *) CHR('D','A','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Default"), NULL, 0, 0, (void *) DEFAULT_LANG, NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Woods Cree"), NULL, 0, 0, (void *) CHR('D','C','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("German (Standard)"), NULL, 0, 0, (void *) CHR('D','E','U',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Dogri"), NULL, 0, 0, (void *) CHR('D','G','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Dhivehi"), NULL, 0, 0, (void *) CHR('D','H','V',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Djerma"), NULL, 0, 0, (void *) CHR('D','J','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Dangme"), NULL, 0, 0, (void *) CHR('D','N','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Dinka"), NULL, 0, 0, (void *) CHR('D','N','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Dungan"), NULL, 0, 0, (void *) CHR('D','U','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Dzongkha"), NULL, 0, 0, (void *) CHR('D','Z','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ebira"), NULL, 0, 0, (void *) CHR('E','B','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Eastern Cree"), NULL, 0, 0, (void *) CHR('E','C','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Edo"), NULL, 0, 0, (void *) CHR('E','D','O',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Efik"), NULL, 0, 0, (void *) CHR('E','F','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Greek"), NULL, 0, 0, (void *) CHR('E','L','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("English"), NULL, 0, 0, (void *) CHR('E','N','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Erzya"), NULL, 0, 0, (void *) CHR('E','R','Z',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Spanish"), NULL, 0, 0, (void *) CHR('E','S','P',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Estonian"), NULL, 0, 0, (void *) CHR('E','T','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Basque"), NULL, 0, 0, (void *) CHR('E','U','Q',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Evenki"), NULL, 0, 0, (void *) CHR('E','V','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Even"), NULL, 0, 0, (void *) CHR('E','V','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ewe"), NULL, 0, 0, (void *) CHR('E','W','E',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("French Antillean"), NULL, 0, 0, (void *) CHR('F','A','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Farsi"), NULL, 0, 0, (void *) CHR('F','A','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Finnish"), NULL, 0, 0, (void *) CHR('F','I','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Fijian"), NULL, 0, 0, (void *) CHR('F','J','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Flemish"), NULL, 0, 0, (void *) CHR('F','L','E',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Forest Nenets"), NULL, 0, 0, (void *) CHR('F','N','E',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Fon"), NULL, 0, 0, (void *) CHR('F','O','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Faroese"), NULL, 0, 0, (void *) CHR('F','O','S',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("French (Standard)"), NULL, 0, 0, (void *) CHR('F','R','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Frisian"), NULL, 0, 0, (void *) CHR('F','R','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Friulian"), NULL, 0, 0, (void *) CHR('F','R','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Futa"), NULL, 0, 0, (void *) CHR('F','T','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Fulani"), NULL, 0, 0, (void *) CHR('F','U','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ga"), NULL, 0, 0, (void *) CHR('G','A','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Gaelic"), NULL, 0, 0, (void *) CHR('G','A','E',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Gagauz"), NULL, 0, 0, (void *) CHR('G','A','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Galician"), NULL, 0, 0, (void *) CHR('G','A','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Garshuni"), NULL, 0, 0, (void *) CHR('G','A','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Garhwali"), NULL, 0, 0, (void *) CHR('G','A','W',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Ge'ez"), NULL, 0, 0, (void *) CHR('G','E','Z',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Gilyak"), NULL, 0, 0, (void *) CHR('G','I','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Gumuz"), NULL, 0, 0, (void *) CHR('G','M','Z',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Gondi"), NULL, 0, 0, (void *) CHR('G','O','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Greenlandic"), NULL, 0, 0, (void *) CHR('G','R','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Garo"), NULL, 0, 0, (void *) CHR('G','R','O',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Guarani"), NULL, 0, 0, (void *) CHR('G','U','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Gujarati"), NULL, 0, 0, (void *) CHR('G','U','J',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Haitian"), NULL, 0, 0, (void *) CHR('H','A','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Halam"), NULL, 0, 0, (void *) CHR('H','A','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Harauti"), NULL, 0, 0, (void *) CHR('H','A','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Hausa"), NULL, 0, 0, (void *) CHR('H','A','U',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Hawaiin"), NULL, 0, 0, (void *) CHR('H','A','W',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Hammer-Banna"), NULL, 0, 0, (void *) CHR('H','B','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Hiligaynon"), NULL, 0, 0, (void *) CHR('H','I','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Hindi"), NULL, 0, 0, (void *) CHR('H','I','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("High Mari"), NULL, 0, 0, (void *) CHR('H','M','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Hindko"), NULL, 0, 0, (void *) CHR('H','N','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ho"), NULL, 0, 0, (void *) CHR('H','O',' ',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Harari"), NULL, 0, 0, (void *) CHR('H','R','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Croatian"), NULL, 0, 0, (void *) CHR('H','R','V',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Hungarian"), NULL, 0, 0, (void *) CHR('H','U','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Armenian"), NULL, 0, 0, (void *) CHR('H','Y','E',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Igbo"), NULL, 0, 0, (void *) CHR('I','B','O',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ijo"), NULL, 0, 0, (void *) CHR('I','J','O',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ilokano"), NULL, 0, 0, (void *) CHR('I','L','O',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Indonesian"), NULL, 0, 0, (void *) CHR('I','N','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ingush"), NULL, 0, 0, (void *) CHR('I','N','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Inuktitut"), NULL, 0, 0, (void *) CHR('I','N','U',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Irish"), NULL, 0, 0, (void *) CHR('I','R','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Irish Traditional"), NULL, 0, 0, (void *) CHR('I','R','T',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Icelandic"), NULL, 0, 0, (void *) CHR('I','S','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Inari Sami"), NULL, 0, 0, (void *) CHR('I','S','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Italian"), NULL, 0, 0, (void *) CHR('I','T','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Hebrew"), NULL, 0, 0, (void *) CHR('I','W','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Javanese"), NULL, 0, 0, (void *) CHR('J','A','V',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Yiddish"), NULL, 0, 0, (void *) CHR('J','I','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Japanese"), NULL, 0, 0, (void *) CHR('J','A','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Judezmo"), NULL, 0, 0, (void *) CHR('J','U','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Jula"), NULL, 0, 0, (void *) CHR('J','U','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kabardian"), NULL, 0, 0, (void *) CHR('K','A','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kachchi"), NULL, 0, 0, (void *) CHR('K','A','C',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kalenjin"), NULL, 0, 0, (void *) CHR('K','A','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Kannada"), NULL, 0, 0, (void *) CHR('K','A','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Karachay"), NULL, 0, 0, (void *) CHR('K','A','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Georgian"), NULL, 0, 0, (void *) CHR('K','A','T',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kazakh"), NULL, 0, 0, (void *) CHR('K','A','Z',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kebena"), NULL, 0, 0, (void *) CHR('K','E','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Khutsuri Georgian"), NULL, 0, 0, (void *) CHR('K','G','E',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Khakass"), NULL, 0, 0, (void *) CHR('K','H','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Khanty-Kazim"), NULL, 0, 0, (void *) CHR('K','H','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Khmer"), NULL, 0, 0, (void *) CHR('K','H','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Khanty-Shurishkar"), NULL, 0, 0, (void *) CHR('K','H','S',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Khanty-Vakhi"), NULL, 0, 0, (void *) CHR('K','H','V',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Khowar"), NULL, 0, 0, (void *) CHR('K','H','W',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kikuyu"), NULL, 0, 0, (void *) CHR('K','I','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kirghiz"), NULL, 0, 0, (void *) CHR('K','I','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kisii"), NULL, 0, 0, (void *) CHR('K','I','S',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kokni"), NULL, 0, 0, (void *) CHR('K','K','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kalmyk"), NULL, 0, 0, (void *) CHR('K','L','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kamba"), NULL, 0, 0, (void *) CHR('K','M','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kumaoni"), NULL, 0, 0, (void *) CHR('K','M','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Komo"), NULL, 0, 0, (void *) CHR('K','M','O',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Komso"), NULL, 0, 0, (void *) CHR('K','M','S',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kanuri"), NULL, 0, 0, (void *) CHR('K','N','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kodagu"), NULL, 0, 0, (void *) CHR('K','O','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Konkani"), NULL, 0, 0, (void *) CHR('K','O','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kikongo"), NULL, 0, 0, (void *) CHR('K','O','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Komi-Permyak"), NULL, 0, 0, (void *) CHR('K','O','P',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Korean"), NULL, 0, 0, (void *) CHR('K','O','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Komi-Zyrian"), NULL, 0, 0, (void *) CHR('K','O','Z',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kpelle"), NULL, 0, 0, (void *) CHR('K','P','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Krio"), NULL, 0, 0, (void *) CHR('K','R','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Karakalpak"), NULL, 0, 0, (void *) CHR('K','R','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Karelian"), NULL, 0, 0, (void *) CHR('K','R','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Karaim"), NULL, 0, 0, (void *) CHR('K','R','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Karen"), NULL, 0, 0, (void *) CHR('K','R','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Koorete"), NULL, 0, 0, (void *) CHR('K','R','T',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kashmiri"), NULL, 0, 0, (void *) CHR('K','S','H',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Khasi"), NULL, 0, 0, (void *) CHR('K','S','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kildin Sami"), NULL, 0, 0, (void *) CHR('K','S','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kui"), NULL, 0, 0, (void *) CHR('K','U','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kulvi"), NULL, 0, 0, (void *) CHR('K','U','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kumyk"), NULL, 0, 0, (void *) CHR('K','U','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kurdish"), NULL, 0, 0, (void *) CHR('K','U','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kurukh"), NULL, 0, 0, (void *) CHR('K','U','U',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Kuy"), NULL, 0, 0, (void *) CHR('K','U','Y',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Koryak"), NULL, 0, 0, (void *) CHR('K','Y','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ladin"), NULL, 0, 0, (void *) CHR('L','A','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lahuli"), NULL, 0, 0, (void *) CHR('L','A','H',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lak"), NULL, 0, 0, (void *) CHR('L','A','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lambani"), NULL, 0, 0, (void *) CHR('L','A','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Lao"), NULL, 0, 0, (void *) CHR('L','A','O',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Latin"), NULL, 0, 0, (void *) CHR('L','A','T',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Laz"), NULL, 0, 0, (void *) CHR('L','A','Z',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("L-Cree"), NULL, 0, 0, (void *) CHR('L','C','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ladakhi"), NULL, 0, 0, (void *) CHR('L','D','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lezgi"), NULL, 0, 0, (void *) CHR('L','E','Z',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lingala"), NULL, 0, 0, (void *) CHR('L','I','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Low Mari"), NULL, 0, 0, (void *) CHR('L','M','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Limbu"), NULL, 0, 0, (void *) CHR('L','M','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lomwe"), NULL, 0, 0, (void *) CHR('L','M','W',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lower Sorbian"), NULL, 0, 0, (void *) CHR('L','S','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lule Sami"), NULL, 0, 0, (void *) CHR('L','S','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lithuanian"), NULL, 0, 0, (void *) CHR('L','T','H',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Luba"), NULL, 0, 0, (void *) CHR('L','U','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Luganda"), NULL, 0, 0, (void *) CHR('L','U','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Luhya"), NULL, 0, 0, (void *) CHR('L','U','H',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Luo"), NULL, 0, 0, (void *) CHR('L','U','O',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Latvian"), NULL, 0, 0, (void *) CHR('L','V','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Majang"), NULL, 0, 0, (void *) CHR('M','A','J',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Makua"), NULL, 0, 0, (void *) CHR('M','A','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Malayalam Traditional"), NULL, 0, 0, (void *) CHR('M','A','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Mansi"), NULL, 0, 0, (void *) CHR('M','A','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Marathi"), NULL, 0, 0, (void *) CHR('M','A','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Marwari"), NULL, 0, 0, (void *) CHR('M','A','W',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Mbundu"), NULL, 0, 0, (void *) CHR('M','B','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Manchu"), NULL, 0, 0, (void *) CHR('M','C','H',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Moose Cree"), NULL, 0, 0, (void *) CHR('M','C','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Mende"), NULL, 0, 0, (void *) CHR('M','D','E',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Me'en"), NULL, 0, 0, (void *) CHR('M','E','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Mizo"), NULL, 0, 0, (void *) CHR('M','I','Z',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Macedonian"), NULL, 0, 0, (void *) CHR('M','K','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Male"), NULL, 0, 0, (void *) CHR('M','L','E',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Malagasy"), NULL, 0, 0, (void *) CHR('M','L','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Malinke"), NULL, 0, 0, (void *) CHR('M','L','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Malayalam Reformed"), NULL, 0, 0, (void *) CHR('M','L','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Malay"), NULL, 0, 0, (void *) CHR('M','L','Y',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Mandinka"), NULL, 0, 0, (void *) CHR('M','N','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Mongolian"), NULL, 0, 0, (void *) CHR('M','N','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Manipuri"), NULL, 0, 0, (void *) CHR('M','N','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Maninka"), NULL, 0, 0, (void *) CHR('M','N','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Manx Gaelic"), NULL, 0, 0, (void *) CHR('M','N','X',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Moksha"), NULL, 0, 0, (void *) CHR('M','O','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Moldavian"), NULL, 0, 0, (void *) CHR('M','O','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Mon"), NULL, 0, 0, (void *) CHR('M','O','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Moroccan"), NULL, 0, 0, (void *) CHR('M','O','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Maori"), NULL, 0, 0, (void *) CHR('M','R','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Maithili"), NULL, 0, 0, (void *) CHR('M','T','H',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Maltese"), NULL, 0, 0, (void *) CHR('M','T','S',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Mundari"), NULL, 0, 0, (void *) CHR('M','U','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Naga-Assamese"), NULL, 0, 0, (void *) CHR('N','A','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Nanai"), NULL, 0, 0, (void *) CHR('N','A','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Naskapi"), NULL, 0, 0, (void *) CHR('N','A','S',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("N-Cree"), NULL, 0, 0, (void *) CHR('N','C','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ndebele"), NULL, 0, 0, (void *) CHR('N','D','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ndonga"), NULL, 0, 0, (void *) CHR('N','D','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Nepali"), NULL, 0, 0, (void *) CHR('N','E','P',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Newari"), NULL, 0, 0, (void *) CHR('N','E','W',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Norway House Cree"), NULL, 0, 0, (void *) CHR('N','H','C',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Nisi"), NULL, 0, 0, (void *) CHR('N','I','S',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Niuean"), NULL, 0, 0, (void *) CHR('N','I','U',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Nkole"), NULL, 0, 0, (void *) CHR('N','K','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Dutch"), NULL, 0, 0, (void *) CHR('N','L','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Nogai"), NULL, 0, 0, (void *) CHR('N','O','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Norwegian"), NULL, 0, 0, (void *) CHR('N','O','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Northern Sami"), NULL, 0, 0, (void *) CHR('N','S','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Northern Tai"), NULL, 0, 0, (void *) CHR('N','T','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Esperanto"), NULL, 0, 0, (void *) CHR('N','T','O',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Nynorsk"), NULL, 0, 0, (void *) CHR('N','Y','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Oji-Cree"), NULL, 0, 0, (void *) CHR('O','C','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ojibway"), NULL, 0, 0, (void *) CHR('O','J','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Oriya"), NULL, 0, 0, (void *) CHR('O','R','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Oromo"), NULL, 0, 0, (void *) CHR('O','R','O',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ossetian"), NULL, 0, 0, (void *) CHR('O','S','S',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Palestinian Aramaic"), NULL, 0, 0, (void *) CHR('P','A','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Pali"), NULL, 0, 0, (void *) CHR('P','A','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Punjabi"), NULL, 0, 0, (void *) CHR('P','A','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Palpa"), NULL, 0, 0, (void *) CHR('P','A','P',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Pashto"), NULL, 0, 0, (void *) CHR('P','A','S',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Polytonic Greek"), NULL, 0, 0, (void *) CHR('P','G','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Pilipino"), NULL, 0, 0, (void *) CHR('P','I','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Palaung"), NULL, 0, 0, (void *) CHR('P','L','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Polish"), NULL, 0, 0, (void *) CHR('P','L','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Provencal"), NULL, 0, 0, (void *) CHR('P','R','O',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Portuguese"), NULL, 0, 0, (void *) CHR('P','T','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Chin"), NULL, 0, 0, (void *) CHR('Q','I','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Rajasthani"), NULL, 0, 0, (void *) CHR('R','A','J',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("R-Cree"), NULL, 0, 0, (void *) CHR('R','C','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Russian Buriat"), NULL, 0, 0, (void *) CHR('R','B','U',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Riang"), NULL, 0, 0, (void *) CHR('R','I','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Rhaeto-Romanic"), NULL, 0, 0, (void *) CHR('R','M','S',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Romanian"), NULL, 0, 0, (void *) CHR('R','O','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Romany"), NULL, 0, 0, (void *) CHR('R','O','Y',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Rusyn"), NULL, 0, 0, (void *) CHR('R','S','Y',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ruanda"), NULL, 0, 0, (void *) CHR('R','U','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Russian"), NULL, 0, 0, (void *) CHR('R','U','S',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Sadri"), NULL, 0, 0, (void *) CHR('S','A','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Sanskrit"), NULL, 0, 0, (void *) CHR('S','A','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Santali"), NULL, 0, 0, (void *) CHR('S','A','T',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Sayisi"), NULL, 0, 0, (void *) CHR('S','A','Y',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Sekota"), NULL, 0, 0, (void *) CHR('S','E','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Selkup"), NULL, 0, 0, (void *) CHR('S','E','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Sango"), NULL, 0, 0, (void *) CHR('S','G','O',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Shan"), NULL, 0, 0, (void *) CHR('S','H','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Sibe"), NULL, 0, 0, (void *) CHR('S','I','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Sidamo"), NULL, 0, 0, (void *) CHR('S','I','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Silte Gurage"), NULL, 0, 0, (void *) CHR('S','I','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Skolt Sami"), NULL, 0, 0, (void *) CHR('S','K','S',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Slovak"), NULL, 0, 0, (void *) CHR('S','K','Y',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Slavey"), NULL, 0, 0, (void *) CHR('S','L','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Slovenian"), NULL, 0, 0, (void *) CHR('S','L','V',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Somali"), NULL, 0, 0, (void *) CHR('S','M','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Samoan"), NULL, 0, 0, (void *) CHR('S','M','O',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Sena"), NULL, 0, 0, (void *) CHR('S','N','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Sindhi"), NULL, 0, 0, (void *) CHR('S','N','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Sinhalese"), NULL, 0, 0, (void *) CHR('S','N','H',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Soninke"), NULL, 0, 0, (void *) CHR('S','N','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Sodo Gurage"), NULL, 0, 0, (void *) CHR('S','O','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Sotho"), NULL, 0, 0, (void *) CHR('S','O','T',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Albanian"), NULL, 0, 0, (void *) CHR('S','Q','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Serbian"), NULL, 0, 0, (void *) CHR('S','R','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Saraiki"), NULL, 0, 0, (void *) CHR('S','R','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Serer"), NULL, 0, 0, (void *) CHR('S','R','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("South Slavey"), NULL, 0, 0, (void *) CHR('S','S','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Southern Sami"), NULL, 0, 0, (void *) CHR('S','S','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Suri"), NULL, 0, 0, (void *) CHR('S','U','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Svan"), NULL, 0, 0, (void *) CHR('S','V','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Swedish"), NULL, 0, 0, (void *) CHR('S','V','E',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Swadaya Aramaic"), NULL, 0, 0, (void *) CHR('S','W','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Swahili"), NULL, 0, 0, (void *) CHR('S','W','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Swazi"), NULL, 0, 0, (void *) CHR('S','W','Z',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Sutu"), NULL, 0, 0, (void *) CHR('S','X','T',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Syriac"), NULL, 0, 0, (void *) CHR('S','Y','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tabasaran"), NULL, 0, 0, (void *) CHR('T','A','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tajiki"), NULL, 0, 0, (void *) CHR('T','A','J',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Tamil"), NULL, 0, 0, (void *) CHR('T','A','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tatar"), NULL, 0, 0, (void *) CHR('T','A','T',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("TH-Cree"), NULL, 0, 0, (void *) CHR('T','C','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Telugu"), NULL, 0, 0, (void *) CHR('T','E','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tongan"), NULL, 0, 0, (void *) CHR('T','G','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tigre"), NULL, 0, 0, (void *) CHR('T','G','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tigrinya"), NULL, 0, 0, (void *) CHR('T','G','Y',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Thai"), NULL, 0, 0, (void *) CHR('T','H','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tahitian"), NULL, 0, 0, (void *) CHR('T','H','T',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Lang|Tibetan"), NULL, 0, 0, (void *) CHR('T','I','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Turkmen"), NULL, 0, 0, (void *) CHR('T','K','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Temne"), NULL, 0, 0, (void *) CHR('T','M','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tswana"), NULL, 0, 0, (void *) CHR('T','N','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tundra Nenets"), NULL, 0, 0, (void *) CHR('T','N','E',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tonga"), NULL, 0, 0, (void *) CHR('T','N','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Todo"), NULL, 0, 0, (void *) CHR('T','O','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Turkish"), NULL, 0, 0, (void *) CHR('T','R','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tsonga"), NULL, 0, 0, (void *) CHR('T','S','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Turoyo Aramaic"), NULL, 0, 0, (void *) CHR('T','U','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tulu"), NULL, 0, 0, (void *) CHR('T','U','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Tuvin"), NULL, 0, 0, (void *) CHR('T','U','V',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Twi"), NULL, 0, 0, (void *) CHR('T','W','I',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Udmurt"), NULL, 0, 0, (void *) CHR('U','D','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Ukrainian"), NULL, 0, 0, (void *) CHR('U','K','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Urdu"), NULL, 0, 0, (void *) CHR('U','R','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Upper Sorbian"), NULL, 0, 0, (void *) CHR('U','S','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Uyghur"), NULL, 0, 0, (void *) CHR('U','Y','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Uzbek"), NULL, 0, 0, (void *) CHR('U','Z','B',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Venda"), NULL, 0, 0, (void *) CHR('V','E','N',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Vietnamese"), NULL, 0, 0, (void *) CHR('V','I','T',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Wa"), NULL, 0, 0, (void *) CHR('W','A',' ',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Wagdi"), NULL, 0, 0, (void *) CHR('W','A','G',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("West-Cree"), NULL, 0, 0, (void *) CHR('W','C','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Welsh"), NULL, 0, 0, (void *) CHR('W','E','L',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Wolof"), NULL, 0, 0, (void *) CHR('W','L','F',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Xhosa"), NULL, 0, 0, (void *) CHR('X','H','S',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Yakut"), NULL, 0, 0, (void *) CHR('Y','A','K',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Yoruba"), NULL, 0, 0, (void *) CHR('Y','B','A',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Y-Cree"), NULL, 0, 0, (void *) CHR('Y','C','R',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Yi Classic"), NULL, 0, 0, (void *) CHR('Y','I','C',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Yi Modern"), NULL, 0, 0, (void *) CHR('Y','I','M',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Chinese Phonetic"), NULL, 0, 0, (void *) CHR('Z','H','P',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Chinese Simplified"), NULL, 0, 0, (void *) CHR('Z','H','S',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Chinese Traditional"), NULL, 0, 0, (void *) CHR('Z','H','T',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Zande"), NULL, 0, 0, (void *) CHR('Z','N','D',' '), NULL, false, false, false, false, false, false, true },
+ { (unichar_t *) N_("Zulu"), NULL, 0, 0, (void *) CHR('Z','U','L',' '), NULL, false, false, false, false, false, false, true },
+ { NULL }
+};
+
+struct opentype_feature_friendlynames friendlies[] = {
+/* I added these first three features to allow round-trip conversion of tfm files */
+ { CHR('I','T','L','C'), "ITLC", N_("Italic Correction"), gpos_single_mask },
+ { CHR('T','C','H','L'), "TCHL", N_("TeX Glyphlist"), gsub_alternate_mask },
+ { CHR('T','E','X','L'), "TEXL", N_("TeX Extension List"), gsub_multiple_mask },
+/* Normal OpenType features follow */
+ { CHR('a','a','l','t'), "aalt", N_("Access All Alternates"), gsub_single_mask|gsub_alternate_mask },
+ { CHR('a','b','v','f'), "abvf", N_("Above Base Forms"), gsub_single_mask },
+ { CHR('a','b','v','m'), "abvm", N_("Above Base Mark"), gpos_mark2base_mask|gpos_mark2ligature_mask },
+ { CHR('a','b','v','s'), "abvs", N_("Above Base Substitutions"), gsub_ligature_mask },
+ { CHR('a','f','r','c'), "afrc", N_("Vertical Fractions"), gsub_ligature_mask },
+ { CHR('a','k','h','n'), "akhn", N_("Akhand"), gsub_ligature_mask },
+ { CHR('a','l','i','g'), "alig", N_("Ancient Ligatures"), gsub_ligature_mask },
+ { CHR('b','l','w','f'), "blwf", N_("Below Base Forms"), gsub_ligature_mask },
+ { CHR('b','l','w','m'), "blwm", N_("Below Base Mark"), gpos_mark2base_mask|gpos_mark2ligature_mask },
+ { CHR('b','l','w','s'), "blws", N_("Below Base Substitutions"), gsub_ligature_mask },
+ { CHR('c','2','p','c'), "c2pc", N_("Capitals to Petite Capitals"), gsub_single_mask },
+ { CHR('c','2','s','c'), "c2sc", N_("Capitals to Small Capitals"), gsub_single_mask },
+ { CHR('c','a','l','t'), "calt", N_("Contextual Alternates"), gsub_context_mask|gsub_contextchain_mask|morx_context_mask },
+ { CHR('c','a','s','e'), "case", N_("Case-Sensitive Forms"), gsub_single_mask|gpos_single_mask },
+ { CHR('c','c','m','p'), "ccmp", N_("Glyph Composition/Decomposition"), gsub_multiple_mask|gsub_ligature_mask },
+ { CHR('c','l','i','g'), "clig", N_("Contextual Ligatures"), gsub_reversecchain_mask },
+ { CHR('c','p','s','p'), "cpsp", N_("Capital Spacing"), gpos_single_mask },
+ { CHR('c','s','w','h'), "cswh", N_("Contextual Swash"), gsub_reversecchain_mask },
+ { CHR('c','u','r','s'), "curs", N_("Cursive Attachment"), gpos_cursive_mask },
+ { CHR('d','i','s','t'), "dist", N_("Distance"), gpos_pair_mask },
+ { CHR('d','l','i','g'), "dlig", N_("Discretionary Ligatures"), gsub_ligature_mask },
+ { CHR('d','n','o','m'), "dnom", N_("Denominators"), gsub_single_mask },
+ { CHR('e','x','p','t'), "expt", N_("Expert Forms"), gsub_single_mask },
+ { CHR('f','a','l','t'), "falt", N_("Final Glyph On Line"), gsub_alternate_mask },
+ { CHR('f','i','n','2'), "fin2", N_("Terminal Forms #2"), gsub_context_mask|gsub_contextchain_mask|morx_context_mask },
+ { CHR('f','i','n','3'), "fin3", N_("Terminal Forms #3"), gsub_context_mask|gsub_contextchain_mask|morx_context_mask },
+ { CHR('f','i','n','a'), "fina", N_("Terminal Forms"), gsub_single_mask },
+ { CHR('f','r','a','c'), "frac", N_("Diagonal Fractions"), gsub_single_mask|gsub_ligature_mask },
+ { CHR('f','w','i','d'), "fwid", N_("Full Widths"), gsub_single_mask|gpos_single_mask },
+ { CHR('h','a','l','f'), "half", N_("Half Forms"), gsub_ligature_mask },
+ { CHR('h','a','l','n'), "haln", N_("Halant Forms"), gsub_ligature_mask },
+ { CHR('h','a','l','t'), "halt", N_("Alternative Half Widths"), gpos_single_mask },
+ { CHR('h','i','s','t'), "hist", N_("Historical Forms"), gsub_single_mask },
+ { CHR('h','k','n','a'), "hkna", N_("Horizontal Kana Alternatives"), gsub_single_mask },
+ { CHR('h','l','i','g'), "hlig", N_("Historic Ligatures"), gsub_ligature_mask },
+ { CHR('h','n','g','l'), "hngl", N_("Hanja to Hangul"), gsub_single_mask|gsub_alternate_mask },
+ { CHR('h','w','i','d'), "hwid", N_("Half Widths"), gsub_single_mask|gpos_single_mask },
+ { CHR('i','n','i','t'), "init", N_("Initial Forms"), gsub_single_mask },
+ { CHR('i','s','o','l'), "isol", N_("Isolated Forms"), gsub_single_mask },
+ { CHR('i','t','a','l'), "ital", N_("Italics"), gsub_single_mask },
+ { CHR('j','a','l','t'), "jalt", N_("Justification Alternatives"), gsub_alternate_mask },
+ { CHR('j','p','7','8'), "jp78", N_("JIS78 Forms"), gsub_single_mask|gsub_alternate_mask },
+ { CHR('j','p','8','3'), "jp83", N_("JIS83 Forms"), gsub_single_mask },
+ { CHR('j','p','9','0'), "jp90", N_("JIS90 Forms"), gsub_single_mask },
+ { CHR('k','e','r','n'), "kern", N_("Horizontal Kerning"), gpos_pair_mask|gpos_context_mask|gpos_contextchain_mask|kern_statemachine_mask },
+ { CHR('l','f','b','d'), "lfbd", N_("Left Bounds"), gpos_single_mask },
+ { CHR('l','i','g','a'), "liga", N_("Standard Ligatures"), gsub_ligature_mask },
+ { CHR('l','j','m','o'), "ljmo", N_("Leading Jamo Forms"), gsub_ligature_mask },
+ { CHR('l','n','u','m'), "lnum", N_("Lining Figures"), gsub_single_mask },
+ { CHR('l','o','c','l'), "locl", N_("Localized Forms"), gsub_single_mask },
+ { CHR('m','a','r','k'), "mark", N_("Mark Positioning"), gpos_mark2base_mask|gpos_mark2ligature_mask },
+ { CHR('m','e','d','2'), "med2", N_("Medial Forms 2"), gsub_context_mask|gsub_contextchain_mask|morx_context_mask },
+ { CHR('m','e','d','i'), "medi", N_("Medial Forms"), gsub_single_mask },
+ { CHR('m','g','r','k'), "mgrk", N_("Mathematical Greek"), gsub_single_mask },
+ { CHR('m','k','m','k'), "mkmk", N_("Mark to Mark"), gpos_mark2mark_mask },
+ { CHR('m','s','e','t'), "mset", N_("Mark Positioning via Substitution"), gsub_context_mask|gsub_contextchain_mask|morx_context_mask },
+ { CHR('n','a','l','t'), "nalt", N_("Alternate Annotation Forms"), gsub_single_mask|gsub_alternate_mask },
+ { CHR('n','u','k','t'), "nukt", N_("Nukta Forms"), gsub_ligature_mask },
+ { CHR('n','u','m','r'), "numr", N_("Numerators"), gsub_single_mask },
+ { CHR('o','n','u','m'), "onum", N_("Oldstyle Figures"), gsub_single_mask },
+ { CHR('o','p','b','d'), "opbd", N_("Optical Bounds"), gpos_single_mask },
+ { CHR('o','r','d','n'), "ordn", N_("Ordinals"), gsub_ligature_mask|gsub_context_mask|gsub_contextchain_mask|morx_context_mask },
+ { CHR('o','r','n','m'), "ornm", N_("Ornaments"), gsub_single_mask|gsub_alternate_mask },
+ { CHR('p','a','l','t'), "palt", N_("Proportional Alternate Metrics"), gpos_single_mask },
+ { CHR('p','c','a','p'), "pcap", N_("Lowercase to Petite Capitals"), gsub_single_mask },
+ { CHR('p','n','u','m'), "pnum", N_("Proportional Numbers"), gsub_single_mask },
+ { CHR('p','r','e','f'), "pref", N_("Pre Base Forms"), gsub_ligature_mask },
+ { CHR('p','r','e','s'), "pres", N_("Pre Base Substitutions"), gsub_ligature_mask|gsub_context_mask|gsub_contextchain_mask|morx_context_mask },
+ { CHR('p','s','t','f'), "pstf", N_("Post Base Forms"), gsub_ligature_mask },
+ { CHR('p','s','t','s'), "psts", N_("Post Base Substitutions"), gsub_ligature_mask },
+ { CHR('p','w','i','d'), "pwid", N_("Proportional Width"), gsub_single_mask },
+ { CHR('q','w','i','d'), "qwid", N_("Quarter Widths"), gsub_single_mask|gpos_single_mask },
+ { CHR('r','a','n','d'), "rand", N_("Randomize"), gsub_alternate_mask },
+ { CHR('r','l','i','g'), "rlig", N_("Required Ligatures"), gsub_ligature_mask },
+ { CHR('r','p','h','f'), "rphf", N_("Reph Form"), gsub_ligature_mask },
+ { CHR('r','t','b','d'), "rtbd", N_("Right Bounds"), gpos_single_mask },
+ { CHR('r','t','l','a'), "rtla", N_("Right to Left Alternates"), gsub_single_mask },
+ { CHR('r','u','b','y'), "ruby", N_("Ruby Notational Forms"), gsub_single_mask },
+ { CHR('s','a','l','t'), "salt", N_("Stylistic Alternatives"), gsub_single_mask|gsub_alternate_mask },
+ { CHR('s','i','n','f'), "sinf", N_("Scientific Inferiors"), gsub_single_mask },
+ { CHR('s','m','c','p'), "smcp", N_("Lowercase to Small Capitals"), gsub_single_mask },
+ { CHR('s','m','p','l'), "smpl", N_("Simplified Forms"), gsub_single_mask },
+ { CHR('s','s','0','1'), "ss01", N_("Style Set 1"), gsub_single_mask },
+ { CHR('s','s','0','2'), "ss02", N_("Style Set 2"), gsub_single_mask },
+ { CHR('s','s','0','3'), "ss03", N_("Style Set 3"), gsub_single_mask },
+ { CHR('s','s','0','4'), "ss04", N_("Style Set 4"), gsub_single_mask },
+ { CHR('s','s','0','5'), "ss05", N_("Style Set 5"), gsub_single_mask },
+ { CHR('s','s','0','6'), "ss06", N_("Style Set 6"), gsub_single_mask },
+ { CHR('s','s','0','7'), "ss07", N_("Style Set 7"), gsub_single_mask },
+ { CHR('s','s','0','8'), "ss08", N_("Style Set 8"), gsub_single_mask },
+ { CHR('s','s','0','9'), "ss09", N_("Style Set 9"), gsub_single_mask },
+ { CHR('s','s','1','0'), "ss10", N_("Style Set 10"), gsub_single_mask },
+ { CHR('s','s','1','1'), "ss11", N_("Style Set 11"), gsub_single_mask },
+ { CHR('s','s','1','2'), "ss12", N_("Style Set 12"), gsub_single_mask },
+ { CHR('s','s','1','3'), "ss13", N_("Style Set 13"), gsub_single_mask },
+ { CHR('s','s','1','4'), "ss14", N_("Style Set 14"), gsub_single_mask },
+ { CHR('s','s','1','5'), "ss15", N_("Style Set 15"), gsub_single_mask },
+ { CHR('s','s','1','6'), "ss16", N_("Style Set 16"), gsub_single_mask },
+ { CHR('s','s','1','7'), "ss17", N_("Style Set 17"), gsub_single_mask },
+ { CHR('s','s','1','8'), "ss18", N_("Style Set 18"), gsub_single_mask },
+ { CHR('s','s','1','9'), "ss19", N_("Style Set 19"), gsub_single_mask },
+ { CHR('s','s','2','0'), "ss20", N_("Style Set 20"), gsub_single_mask },
+ { CHR('s','u','b','s'), "subs", N_("Subscript"), gsub_single_mask },
+ { CHR('s','u','p','s'), "sups", N_("Superscript"), gsub_single_mask },
+ { CHR('s','w','s','h'), "swsh", N_("Swash"), gsub_single_mask|gsub_alternate_mask },
+ { CHR('t','i','t','l'), "titl", N_("Titling"), gsub_single_mask },
+ { CHR('t','j','m','o'), "tjmo", N_("Trailing Jamo Forms"), gsub_ligature_mask },
+ { CHR('t','n','a','m'), "tnam", N_("Traditional Name Forms"), gsub_single_mask },
+ { CHR('t','n','u','m'), "tnum", N_("Tabular Numbers"), gsub_single_mask },
+ { CHR('t','r','a','d'), "trad", N_("Traditional Forms"), gsub_single_mask|gsub_alternate_mask },
+ { CHR('t','w','i','d'), "twid", N_("Third Widths"), gsub_single_mask|gpos_single_mask },
+ { CHR('u','n','i','c'), "unic", N_("Unicase"), gsub_single_mask },
+ { CHR('v','a','l','t'), "valt", N_("Alternate Vertical Metrics"), gpos_single_mask },
+ { CHR('v','a','t','u'), "vatu", N_("Vattu Variants"), gsub_ligature_mask },
+ { CHR('v','e','r','t'), "vert", N_("Vertical Alternates (obs)"), gsub_single_mask },
+ { CHR('v','h','a','l'), "vhal", N_("Alternate Vertical Half Metrics"), gpos_single_mask },
+ { CHR('v','j','m','o'), "vjmo", N_("Vowel Jamo Forms"), gsub_ligature_mask },
+ { CHR('v','k','n','a'), "vkna", N_("Vertical Kana Alternates"), gsub_single_mask },
+ { CHR('v','k','r','n'), "vkrn", N_("Vertical Kerning"), gpos_pair_mask|gpos_context_mask|gpos_contextchain_mask|kern_statemachine_mask },
+ { CHR('v','p','a','l'), "vpal", N_("Proportional Alternate Vertical Metrics"), gpos_single_mask },
+ { CHR('v','r','t','2'), "vrt2", N_("Vertical Rotation & Alternates"), gsub_single_mask },
+ { CHR('z','e','r','o'), "zero", N_("Slashed Zero"), gsub_single_mask },
+/* This is my hack for setting the "Required feature" field of a script */
+ { CHR(' ','R','Q','D'), " RQD", N_("Required feature"), gsub_single_mask|gsub_multiple_mask|gsub_alternate_mask|gsub_ligature_mask|gsub_context_mask|gsub_contextchain_mask|gsub_reversecchain_mask|morx_context_mask|gpos_single_mask|gpos_pair_mask|gpos_cursive_mask|gpos_mark2base_mask|gpos_mark2ligature_mask|gpos_mark2mark_mask|gpos_context_mask|gpos_contextchain_mask },
+ { 0, NULL, 0 }
+};
+
+static char *LK_LangsDlg(GGadget *, int r, int c);
+static char *LK_ScriptsDlg(GGadget *, int r, int c);
+static struct col_init scriptci[] = {
+/* GT: English uses "script" to mean a general writing system (latin, greek, kanji) */
+/* GT: and the cursive handwriting style. Here we mean the general writing system. */
+ { me_stringchoicetag , NULL, scripts, NULL, N_("writing system|Script") },
+ { me_funcedit, LK_LangsDlg, NULL, NULL, N_("Language(s)") },
+ };
+static struct col_init featureci[] = {
+ { me_stringchoicetrans , NULL, NULL, NULL, N_("Feature") },
+ { me_funcedit, LK_ScriptsDlg, NULL, NULL, N_("Script(s) & Language(s)") },
+ };
+
+void LookupUIInit(void) {
+ static int done = false;
+ int i, j;
+ static GTextInfo *needswork[] = {
+ scripts, languages, gpos_lookuptypes, gsub_lookuptypes,
+ NULL
+ };
+
+ if ( done )
+return;
+ done = true;
+ for ( j=0; needswork[j]!=NULL; ++j ) {
+ for ( i=0; needswork[j][i].text!=NULL; ++i )
+ needswork[j][i].text = (unichar_t *) S_((char *) needswork[j][i].text);
+ }
+ for ( i=0; friendlies[i].friendlyname!=NULL; ++i )
+ friendlies[i].friendlyname = S_(friendlies[i].friendlyname);
+
+ featureci[0].title = S_(featureci[0].title);
+ featureci[1].title = S_(featureci[1].title);
+ scriptci[0].title = S_(scriptci[0].title);
+ scriptci[1].title = S_(scriptci[1].title);
+}
+
+#define CID_LookupType 1000
+#define CID_LookupFeatures 1001
+#define CID_Lookup_R2L 1002
+#define CID_Lookup_IgnBase 1003
+#define CID_Lookup_IgnLig 1004
+#define CID_Lookup_IgnMark 1005
+#define CID_Lookup_ProcessMark 1006
+#define CID_LookupName 1007
+#define CID_LookupAfm 1008
+#define CID_OK 1009
+#define CID_Cancel 1010
+
+#define CID_FeatureScripts 1020
+#define CID_ShowAnchors 1021
+
+struct lookup_dlg {
+ OTLookup *orig;
+ SplineFont *sf;
+ GWindow gw, scriptgw;
+ int isgpos;
+ int done, scriptdone, name_has_been_set;
+ int ok;
+ char *scriptret;
+};
+
+static int langs_e_h(GWindow gw, GEvent *event) {
+ int *done = GDrawGetUserData(gw);
+
+ if ( event->type==et_close ) {
+ *done = true;
+ } else if ( event->type==et_char ) {
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("lookups.html#scripts-dlg");
+return( true );
+ }
+return( false );
+ } else if ( event->type==et_controlevent && event->u.control.subtype == et_buttonactivate ) {
+ switch ( GGadgetGetCid(event->u.control.g)) {
+ case CID_OK:
+ *done = 2;
+ break;
+ case CID_Cancel:
+ *done = true;
+ break;
+ }
+ }
+return( true );
+}
+
+static char *LK_LangsDlg(GGadget *g, int r, int c) {
+ int rows, i;
+ struct matrix_data *strings = GMatrixEditGet(g, &rows);
+ char *langstr = strings[2*r+c].u.md_str, *pt, *start;
+ unsigned char tagstr[4], warnstr[8];
+ uint32 tag;
+ int warn_cnt = 0;
+ int j,done=0;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[5], *varray[6], *harray[7], boxes[3];
+ GTextInfo label[5];
+ GRect pos;
+ GWindow gw;
+ int32 len;
+ GTextInfo **ti;
+ char *ret;
+
+ for ( i=0; languages[i].text!=NULL; ++i )
+ languages[i].selected = false;
+
+ for ( start= langstr; *start; ) {
+ memset(tagstr,' ',sizeof(tagstr));
+ for ( pt=start, j=0; *pt!='\0' && *pt!=','; ++pt, ++j ) {
+ if ( j<4 )
+ tagstr[j] = *pt;
+ }
+ if ( *pt==',' ) ++pt;
+ tag = (tagstr[0]<<24) | (tagstr[1]<<16) | (tagstr[2]<<8) | tagstr[3];
+ for ( i=0; languages[i].text!=NULL; ++i )
+ if ( languages[i].userdata == (void *) (intpt) tag ) {
+ languages[i].selected = true;
+ break;
+ }
+ if ( languages[i].text==NULL ) {
+ ++warn_cnt;
+ memcpy(warnstr,tagstr,4);
+ warnstr[4] = '\0';
+ }
+ start = pt;
+ }
+ if ( warn_cnt!=0 ) {
+ if ( warn_cnt==1 )
+ gwwv_post_error(_("Unknown Language"),_("The language, '%s', is not in the list of known languages and will be omitted"), warnstr );
+ else
+ gwwv_post_error(_("Unknown Language"),_("Several language tags, including '%s', are not in the list of known languages and will be omitted"), warnstr );
+ }
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Language List");
+ wattrs.is_dlg = true;
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,150));
+ pos.height = GDrawPointsToPixels(NULL,193);
+ gw = GDrawCreateTopWindow(NULL,&pos,langs_e_h,&done,&wattrs);
+
+ memset(&gcd,0,sizeof(gcd));
+ memset(&boxes,0,sizeof(boxes));
+ memset(&label,0,sizeof(label));
+
+ i = 0;
+ gcd[i].gd.pos.x = 10; gcd[i].gd.pos.y = 5;
+ gcd[i].gd.pos.height = 12*12+6;
+ gcd[i].gd.flags = gg_enabled|gg_visible|gg_list_alphabetic|gg_list_multiplesel|gg_utf8_popup;
+ gcd[i].gd.u.list = languages;
+ gcd[i].gd.cid = 0;
+ gcd[i].gd.popup_msg = (unichar_t *) _(
+ "Select as many languages as needed\n"
+ "Hold down the control key when clicking\n"
+ "to make disjoint selections.");
+ varray[0] = &gcd[i]; varray[1] = NULL;
+ gcd[i++].creator = GListCreate;
+
+ gcd[i].gd.pos.x = 15-3; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+gcd[i-1].gd.pos.height+5;
+ gcd[i].gd.pos.width = -1; gcd[i].gd.pos.height = 0;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[i].text = (unichar_t *) _("_OK");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.mnemonic = 'O';
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.cid = CID_OK;
+ harray[0] = GCD_Glue; harray[1] = &gcd[i]; harray[2] = GCD_Glue;
+ gcd[i++].creator = GButtonCreate;
+
+ gcd[i].gd.pos.x = -15; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+3;
+ gcd[i].gd.pos.width = -1; gcd[i].gd.pos.height = 0;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[i].text = (unichar_t *) _("_Cancel");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.mnemonic = 'C';
+ gcd[i].gd.cid = CID_Cancel;
+ harray[3] = GCD_Glue; harray[4] = &gcd[i]; harray[5] = GCD_Glue; harray[6] = NULL;
+ gcd[i++].creator = GButtonCreate;
+
+ boxes[2].gd.flags = gg_enabled|gg_visible;
+ boxes[2].gd.u.boxelements = harray;
+ boxes[2].creator = GHBoxCreate;
+ varray[2] = &boxes[2]; varray[3] = NULL; varray[4] = NULL;
+
+ boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
+ boxes[0].gd.flags = gg_enabled|gg_visible;
+ boxes[0].gd.u.boxelements = varray;
+ boxes[0].creator = GHVGroupCreate;
+
+ GGadgetsCreate(gw,boxes);
+ GHVBoxSetExpandableRow(boxes[0].ret,0);
+ GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
+ GHVBoxFitWindow(boxes[0].ret);
+
+ GDrawSetVisible(gw,true);
+ retry:
+ while ( !done )
+ GDrawProcessOneEvent(NULL);
+ ret = NULL;
+ ti = GGadgetGetList(gcd[0].ret,&len);
+ if ( done==2 ) {
+ int lcnt=0;
+ for ( i=0; i<len; ++i ) {
+ if ( ti[i]->selected )
+ ++lcnt;
+ }
+ if ( lcnt==0 ) {
+ gwwv_post_error(_("Language Missing"),_("You must select at least one language.\nUse the \"Default\" language if nothing else fits."));
+ done = 0;
+ goto retry;
+ }
+ ret = galloc(5*lcnt+1);
+ *ret = '\0';
+ pt = ret;
+ for ( i=0; i<len; ++i ) {
+ if ( done==2 && ti[i]->selected ) {
+ uint32 tag = (uint32) (intpt) (ti[i]->userdata);
+ *pt++ = tag>>24;
+ *pt++ = tag>>16;
+ *pt++ = tag>>8;
+ *pt++ = tag&0xff;
+ *pt++ = ',';
+ }
+ }
+ if ( pt!=ret )
+ pt[-1] = '\0';
+ }
+ GDrawDestroyWindow(gw);
+return( ret );
+}
+
+static void LK_NewScript(GGadget *g,int row) {
+ int rows;
+ struct matrix_data *strings = GMatrixEditGet(g, &rows);
+ /* What's a good default lang list for a new script? */
+ /* well it depends on what the script is, but we don't know that yet */
+ /* dflt is safe */
+
+ strings[2*row+1].u.md_str = copy("dflt");
+}
+
+static void ScriptMatrixInit(struct matrixinit *mi,char *scriptstr) {
+ struct matrix_data *md;
+ int k, cnt;
+ char *start, *scriptend, *langsend;
+
+ memset(mi,0,sizeof(*mi));
+ mi->col_cnt = 2;
+ mi->col_init = scriptci;
+
+ md = NULL;
+ for ( k=0; k<2; ++k ) {
+ cnt = 0;
+ for ( start = scriptstr; *start; ) {
+ for ( scriptend=start; *scriptend!='\0' && *scriptend!='{'; ++scriptend );
+ langsend = scriptend;
+ if ( *scriptend=='{' )
+ for ( langsend=scriptend+1; *langsend!='\0' && *langsend!='}'; ++langsend );
+ if ( k ) {
+ md[2*cnt+0].u.md_str = copyn(start,scriptend-start);
+ if ( *scriptend=='{' )
+ md[2*cnt+1].u.md_str = copyn(scriptend+1,langsend-(scriptend+1));
+ else
+ md[2*cnt+1].u.md_str = copy("");
+ }
+ ++cnt;
+ if ( *langsend=='}' ) ++langsend;
+ if ( *langsend==' ' ) ++langsend;
+ start = langsend;
+ }
+ if ( md==NULL )
+ md = gcalloc(2*(cnt+10),sizeof(struct matrix_data));
+ }
+ mi->matrix_data = md;
+ mi->initial_row_cnt = cnt;
+
+ mi->initrow = LK_NewScript;
+ mi->finishedit = NULL;
+ mi->candelete = NULL;
+ mi->popupmenu = NULL;
+ mi->handle_key = NULL;
+ mi->bigedittitle = NULL;
+}
+
+static int Script_OK(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct lookup_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
+ int rows, i, j, script_cnt, lang_cnt;
+ struct matrix_data *strings = GMatrixEditGet(GWidgetGetControl(ld->scriptgw,CID_FeatureScripts), &rows);
+ char *pt, *start, *ret, *rpt;
+ char foo[4];
+
+ if ( rows==0 ) {
+ gwwv_post_error(_("No scripts"),_("You must select at least one script if you provide a feature tag."));
+return(true);
+ }
+ script_cnt = rows;
+ lang_cnt = 0;
+ for ( i=0; i<rows; ++i ) {
+ if ( strlen(strings[2*i+0].u.md_str)>4 ) {
+ gwwv_post_error(_("Bad script tag"),_("The script tag on line %d (%s) is too long. It may be at most 4 letters"),
+ i+1, strings[2*i+0].u.md_str);
+return(true);
+ } else {
+ for ( pt=strings[2*i+0].u.md_str; *pt!='\0' ; ++pt )
+ if ( *pt>0x7e ) {
+ gwwv_post_error(_("Bad script tag"),_("The script tag on line %d (%s) should be in ASCII.\n"),
+ i+1, strings[2*i+0].u.md_str);
+return( true );
+ }
+ }
+ /* Now check the languages */
+ if ( *strings[2*i+1].u.md_str=='\0' ) {
+ gwwv_post_error(_("No languages"),_("You must select at least one language for each script."));
+return(true);
+ }
+ for ( start=strings[2*i+1].u.md_str; *start!='\0'; ) {
+ for ( pt=start; *pt!=',' && *pt!='\0'; ++pt ) {
+ if ( *pt>0x7e ) {
+ gwwv_post_error(_("Bad language tag"),_("A language tag on line %d (%s) should be in ASCII.\n"),
+ i+1, strings[2*i+1].u.md_str);
+return( true );
+ }
+ }
+ if ( pt-start>4 ) {
+ gwwv_post_error(_("Bad language tag"),_("A language tag on line %d (%s) is too long. It may be at most 4 letters"),
+ i+1, strings[2*i+0].u.md_str);
+return(true);
+ }
+ ++lang_cnt;
+ start = pt;
+ if ( *start==',' ) ++start;
+ }
+ }
+
+ /* Ok, we validated the script lang list. Now parse it */
+ rpt = ret = galloc(6*script_cnt+5*lang_cnt+10);
+ for ( i=0; i<rows; ++i ) {
+ memset(foo,' ',sizeof(foo));
+ for ( j=0, pt = strings[2*i+0].u.md_str; j<4 && *pt; foo[j++] = *pt++ );
+ strncpy(rpt,foo,4);
+ rpt += 4;
+ *rpt++ = '{';
+ /* Now do the languages */
+ for ( start=strings[2*i+1].u.md_str; *start!='\0'; ) {
+ memset(foo,' ',sizeof(foo));
+ for ( j=0,pt=start; *pt!=',' && *pt!='\0'; ++pt )
+ foo[j++] = *pt;
+ strncpy(rpt,foo,4);
+ rpt += 4; *rpt++ = ',';
+ if ( *pt==',' ) ++pt;
+ start = pt;
+ }
+ if ( rpt>ret && rpt[-1]==',' )
+ rpt[-1] = '}';
+ *rpt++ = ' ';
+ }
+ if ( rpt>ret && rpt[-1]==' ' ) rpt[-1] = '\0';
+ else *rpt = '\0';
+ ld->scriptdone = true;
+ ld->scriptret = ret;
+ }
+return( true );
+}
+
+static int Script_Cancel(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct lookup_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
+ ld->scriptdone = true;
+ ld->scriptret = NULL;
+ }
+return( true );
+}
+
+static int script_e_h(GWindow gw, GEvent *event) {
+
+ if ( event->type==et_close ) {
+ struct lookup_dlg *ld = GDrawGetUserData(gw);
+ ld->scriptdone = true;
+ ld->scriptret = NULL;
+ } else if ( event->type == et_char ) {
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("lookups.html#scripts-dlg");
+return( true );
+ }
+return( false );
+ }
+
+return( true );
+}
+
+static char *LK_ScriptsDlg(GGadget *g, int r, int c) {
+ int rows, i, k, j;
+ struct matrix_data *strings = GMatrixEditGet(g, &rows);
+ char *scriptstr = strings[2*r+c].u.md_str;
+ struct lookup_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[4], boxes[3];
+ GGadgetCreateData *varray[6], *harray3[8];
+ GTextInfo label[4];
+ struct matrixinit mi;
+
+ ld->scriptdone = 0;
+ ld->scriptret = NULL;
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.is_dlg = true;
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Script(s)...");
+ pos.x = pos.y = 0;
+ pos.width =GDrawPointsToPixels(NULL,GGadgetScale(268));
+ pos.height = GDrawPointsToPixels(NULL,375);
+ ld->scriptgw = gw = GDrawCreateTopWindow(NULL,&pos,script_e_h,ld,&wattrs);
+
+ ScriptMatrixInit(&mi,scriptstr);
+
+ memset(&gcd,0,sizeof(gcd));
+ memset(&boxes,0,sizeof(boxes));
+ memset(&label,0,sizeof(label));
+ k=j=0;
+ gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[1].gd.pos.y+14;
+ gcd[k].gd.pos.width = 300; gcd[k].gd.pos.height = 90;
+ gcd[k].gd.flags = gg_enabled | gg_visible | gg_utf8_popup;
+ gcd[k].gd.cid = CID_FeatureScripts;
+ gcd[k].gd.u.matrix = &mi;
+ gcd[k].gd.popup_msg = (unichar_t *) _(
+ "Each feature is active for a specific set of\n"
+ "scripts and languages.\n"
+ "Usually only one script is specified, but\n"
+ "occasionally more will be.\n"
+ "A script is a four letter OpenType script tag\n");
+ gcd[k].creator = GMatrixEditCreate;
+ varray[j++] = &gcd[k++]; varray[j++] = NULL;
+
+ gcd[k].gd.pos.x = 30-3;
+ gcd[k].gd.pos.width = -1; gcd[k].gd.pos.height = 0;
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[k].text = (unichar_t *) _("_OK");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.handle_controlevent = Script_OK;
+ gcd[k].gd.cid = CID_OK;
+ gcd[k++].creator = GButtonCreate;
+
+ gcd[k].gd.pos.x = -30;
+ gcd[k].gd.pos.width = -1; gcd[k].gd.pos.height = 0;
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[k].text = (unichar_t *) _("_Cancel");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.handle_controlevent = Script_Cancel;
+ gcd[k].gd.cid = CID_Cancel;
+ gcd[k++].creator = GButtonCreate;
+
+ harray3[0] = harray3[2] = harray3[3] = harray3[4] = harray3[6] = GCD_Glue;
+ harray3[7] = NULL;
+ harray3[1] = &gcd[k-2]; harray3[5] = &gcd[k-1];
+
+ boxes[0].gd.flags = gg_enabled|gg_visible;
+ boxes[0].gd.u.boxelements = harray3;
+ boxes[0].creator = GHBoxCreate;
+ varray[j++] = &boxes[0]; varray[j++] = NULL; varray[j] = NULL;
+
+ boxes[1].gd.pos.x = boxes[1].gd.pos.y = 2;
+ boxes[1].gd.flags = gg_enabled|gg_visible;
+ boxes[1].gd.u.boxelements = varray;
+ boxes[1].creator = GHVGroupCreate;
+
+ GGadgetsCreate(gw,boxes+1);
+
+ for ( i=0; i<mi.initial_row_cnt; ++i ) {
+ free( mi.matrix_data[2*i+0].u.md_str );
+ free( mi.matrix_data[2*i+1].u.md_str );
+ }
+ free( mi.matrix_data );
+
+ GMatrixEditSetNewText(gcd[0].ret,S_("OpenTypeFeature|New"));
+ GHVBoxSetExpandableRow(boxes[1].ret,0);
+ GHVBoxSetExpandableCol(boxes[0].ret,gb_expandgluesame);
+
+ GHVBoxFitWindow(boxes[1].ret);
+
+ GDrawSetVisible(gw,true);
+ while ( !ld->scriptdone )
+ GDrawProcessOneEvent(NULL);
+ GDrawDestroyWindow(gw);
+return( ld->scriptret );
+}
+
+static FeatureScriptLangList *LK_ParseFL(struct matrix_data *strings, int rows ) {
+ int i,j;
+ char *pt, *start;
+ FeatureScriptLangList *fl, *fhead, *flast;
+ struct scriptlanglist *sl, *slast;
+ unsigned char foo[4];
+ uint32 *langs=NULL;
+ int lmax=0, lcnt=0;
+ int feature, setting;
+
+ fhead = flast = NULL;
+ for ( i=0; i<rows; ++i ) {
+ fl = chunkalloc(sizeof(FeatureScriptLangList));
+ if ( sscanf(strings[2*i+0].u.md_str,"<%d,%d>", &feature, &setting )== 2 ) {
+ fl->ismac = true;
+ fl->featuretag = (feature<<16)|setting;
+ } else {
+ memset(foo,' ',sizeof(foo));
+ for ( j=0, pt = strings[2*i+0].u.md_str; j<4 && *pt; foo[j++] = *pt++ );
+ fl->featuretag = (foo[0]<<24) | (foo[1]<<16) | (foo[2]<<8) | foo[3];
+ }
+ if ( flast==NULL )
+ fhead = fl;
+ else
+ flast->next = fl;
+ flast = fl;
+ /* Now do the script langs */
+ slast = NULL;
+ for ( start=strings[2*i+1].u.md_str; *start!='\0'; ) {
+ memset(foo,' ',sizeof(foo));
+ for ( j=0,pt=start; *pt!='{' && *pt!='\0'; ++pt )
+ foo[j++] = *pt;
+ sl = chunkalloc(sizeof( struct scriptlanglist ));
+ sl->script = (foo[0]<<24) | (foo[1]<<16) | (foo[2]<<8) | foo[3];
+ if ( slast==NULL )
+ fl->scripts = sl;
+ else
+ slast->next = sl;
+ slast = sl;
+ if ( *pt!='{' ) {
+ sl->lang_cnt = 1;
+ sl->langs[0] = DEFAULT_LANG;
+ start = pt;
+ } else {
+ lcnt=0;
+ for ( start=pt+1; *start!='}' && *start!='\0' ; ) {
+ memset(foo,' ',sizeof(foo));
+ for ( j=0,pt=start; *pt!='}' && *pt!=',' && *pt!='\0'; foo[j++] = *pt++ );
+ if ( lcnt>=lmax )
+ langs = grealloc(langs,(lmax+=20)*sizeof(uint32));
+ langs[lcnt++] = (foo[0]<<24) | (foo[1]<<16) | (foo[2]<<8) | foo[3];
+ start = ( *pt==',' ) ? pt+1 : pt;
+ }
+ if ( *start=='}' ) ++start;
+ for ( j=0; j<lcnt && j<MAX_LANG; ++j )
+ sl->langs[j] = langs[j];
+ if ( lcnt>MAX_LANG ) {
+ sl->morelangs = galloc((lcnt-MAX_LANG)*sizeof(uint32));
+ for ( ; j<lcnt; ++j )
+ sl->morelangs[j-MAX_LANG] = langs[j];
+ }
+ sl->lang_cnt = lcnt;
+ }
+ while ( *start==' ' ) ++start;
+ }
+ }
+ free(langs);
+return( fhead );
+}
+
+static void LK_FinishEdit(GGadget *g,int row, int col, int wasnew) {
+ struct lookup_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
+
+ if ( col==0 ) {
+ int rows;
+ struct matrix_data *strings = GMatrixEditGet(g, &rows);
+
+ if ( !ld->isgpos &&
+ (strcmp(strings[row].u.md_str,"liga")==0 ||
+ strcmp(strings[row].u.md_str,"rlig")==0 ))
+ GGadgetSetChecked( GWidgetGetControl(ld->gw,CID_LookupAfm ), true );
+ }
+ if ( row==0 && !ld->name_has_been_set && ld->orig->features==NULL ) {
+ int rows;
+ struct matrix_data *strings = GMatrixEditGet(g, &rows);
+ OTLookup *otl = ld->orig;
+ int old_type = otl->lookup_type;
+ FeatureScriptLangList *oldfl = otl->features;
+
+ otl->lookup_type = (intpt) GGadgetGetListItemSelected(GWidgetGetControl(ld->gw,CID_LookupType))->userdata;
+ otl->features = LK_ParseFL(strings,rows);
+ NameOTLookup(otl,ld->sf);
+ GGadgetSetTitle8(GWidgetGetControl(ld->gw,CID_LookupName),otl->lookup_name);
+ free(otl->lookup_name); otl->lookup_name = NULL;
+ FeatureScriptLangListFree(otl->features); otl->features = oldfl;
+ otl->lookup_type = old_type;
+ }
+}
+
+static void LK_NewFeature(GGadget *g,int row) {
+ int rows;
+ struct matrix_data *strings = GMatrixEditGet(g, &rows);
+ struct lookup_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
+ SplineFont *sf, *_sf = ld->sf;
+ SplineChar *sc;
+ /* What's a good default script / lang list for a new feature? */
+ /* well it depends on what the feature is, and on what's inside the lookup */
+ /* Neither of those has been set yet. */
+ /* So... give them everything we can think of. They can remove stuff */
+ /* which is inappropriate */
+ uint32 scripts[20], script, *langs;
+ int scnt = 0, i, l;
+ int gid, k;
+ char *buf;
+ int bmax, bpos;
+
+ k=0;
+ do {
+ sf = k<_sf->subfontcnt ? _sf->subfonts[k] : _sf;
+ for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( (sc = sf->glyphs[gid])!=NULL ) {
+ script = SCScriptFromUnicode(sc);
+ for ( i=0; i<scnt; ++i )
+ if ( script == scripts[i] )
+ break;
+ if ( i==scnt ) {
+ scripts[scnt++] = script;
+ if ( scnt>=20 ) /* If they've got lots of scripts, enumerating them all won't be much use... */
+ break;
+ }
+ }
+ ++k;
+ } while ( k<_sf->subfontcnt && scnt<20 );
+
+ if ( scnt==0 )
+ scripts[scnt++] = DEFAULT_SCRIPT;
+
+ buf = galloc(bmax = 100);
+ bpos = 0;
+ for ( i=0; i<scnt; ++i ) {
+ langs = SFLangsInScript(sf,-1,scripts[i]);
+ for ( l=0; langs[l]!=0; ++l );
+ if ( bpos + 5+5*l+4 > bmax )
+ buf = grealloc( buf, bmax += 5+5*l+100 );
+ sprintf( buf+bpos, "%c%c%c%c{", scripts[i]>>24, scripts[i]>>16, scripts[i]>>8, scripts[i] );
+ bpos+=5;
+ for ( l=0; langs[l]!=0; ++l ) {
+ sprintf( buf+bpos, "%c%c%c%c,", langs[l]>>24, langs[l]>>16, langs[l]>>8, langs[l] );
+ bpos += 5;
+ }
+ if ( l>0 )
+ --bpos;
+ strcpy(buf+bpos,"} ");
+ bpos += 2;
+ free(langs);
+ }
+ if ( bpos>0 )
+ buf[bpos-1] = '\0';
+
+ strings[2*row+1].u.md_str = copy(buf);
+ free(buf);
+}
+
+static void LKMatrixInit(struct matrixinit *mi,OTLookup *otl) {
+ struct matrix_data *md;
+ int k, cnt,j;
+ FeatureScriptLangList *fl;
+ struct scriptlanglist *sl;
+ char featbuf[32], *buf=NULL;
+ int blen=0, bpos=0;
+
+ memset(mi,0,sizeof(*mi));
+ mi->col_cnt = 2;
+ mi->col_init = featureci;
+
+ md = NULL;
+ for ( k=0; k<2; ++k ) {
+ cnt = 0;
+ for ( fl=otl->features; fl!=NULL; fl=fl->next ) {
+ if ( k ) {
+ if ( fl->ismac )
+ sprintf( featbuf, "<%d,%d>", fl->featuretag>>16, fl->featuretag&0xffff );
+ else
+ sprintf( featbuf, "%c%c%c%c", fl->featuretag>>24, fl->featuretag>>16,
+ fl->featuretag>>8, fl->featuretag );
+ md[2*cnt+0].u.md_str = copy(featbuf);
+ bpos=0;
+ for ( sl=fl->scripts; sl!=NULL; sl=sl->next ) {
+ if ( bpos+4/*script*/+1/*open brace*/+5*sl->lang_cnt+1+2 > blen )
+ buf = grealloc(buf,blen+=5+5*sl->lang_cnt+3+200);
+ sprintf( buf+bpos, "%c%c%c%c{", sl->script>>24, sl->script>>16,
+ sl->script>>8, sl->script );
+ bpos+=5;
+ for ( j=0; j<sl->lang_cnt; ++j ) {
+ uint32 tag = j<MAX_LANG ? sl->langs[j] : sl->morelangs[j-MAX_LANG];
+ sprintf( buf+bpos, "%c%c%c%c,", tag>>24, tag>>16,
+ tag>>8, tag );
+ bpos+=5;
+ }
+ if ( sl->lang_cnt!=0 )
+ --bpos;
+ buf[bpos++] = '}';
+ buf[bpos++] = ' ';
+ }
+ if ( bpos>0 )
+ --bpos;
+ buf[bpos] = '\0';
+ md[2*cnt+1].u.md_str = copy(buf);
+ }
+ ++cnt;
+ }
+ if ( md==NULL )
+ md = gcalloc(2*(cnt+10),sizeof(struct matrix_data));
+ }
+ mi->matrix_data = md;
+ mi->initial_row_cnt = cnt;
+
+ mi->initrow = LK_NewFeature;
+ mi->finishedit = LK_FinishEdit;
+ mi->candelete = NULL;
+ mi->popupmenu = NULL;
+ mi->handle_key = NULL;
+ mi->bigedittitle = NULL;
+ free(buf);
+}
+
+static GTextInfo *SFMarkClassList(SplineFont *sf,int class) {
+ int i;
+ GTextInfo *ti;
+
+ if ( sf->cidmaster ) sf = sf->cidmaster;
+ else if ( sf->mm!=NULL ) sf=sf->mm->normal;
+
+ i = sf->mark_class_cnt;
+ ti = gcalloc(i+4,sizeof( GTextInfo ));
+ ti[0].text = utf82u_copy( _("All"));
+ ti[0].selected = class==0;
+ for ( i=1; i<sf->mark_class_cnt; ++i ) {
+ ti[i].text = (unichar_t *) copy(sf->mark_class_names[i]);
+ ti[i].text_is_1byte = true;
+ if ( i==class ) ti[i].selected = true;
+ }
+return( ti );
+}
+
+static int MaskFromLookupType(int lookup_type ) {
+ switch ( lookup_type ) {
+ case gsub_single: case gsub_multiple: case gsub_alternate:
+ case gsub_ligature: case gsub_context: case gsub_contextchain:
+return( 1<<(lookup_type-1));
+ case gsub_reversecchain:
+return( gsub_reversecchain_mask );
+ case morx_indic: case morx_context: case morx_insert:
+return( morx_indic_mask<<(lookup_type-morx_indic) );
+ case gpos_single: case gpos_pair: case gpos_cursive:
+ case gpos_mark2base: case gpos_mark2ligature: case gpos_mark2mark:
+ case gpos_context: case gpos_contextchain:
+return( gpos_single_mask<<(lookup_type-gpos_single) );
+ case kern_statemachine:
+return( kern_statemachine_mask );
+ default:
+return( 0 );
+ }
+}
+
+static GTextInfo *FeatureListFromLookupType(int lookup_type) {
+ int k, i, cnt, mask;
+ GTextInfo *ti;
+
+ mask = MaskFromLookupType( lookup_type );
+ for ( k=0; k<2; ++k ) {
+ cnt = 0;
+ for ( i=0; friendlies[i].tag!=0; ++i ) if ( friendlies[i].masks&mask ) {
+ if ( k ) {
+ ti[cnt].text = (unichar_t *) copy( friendlies[i].friendlyname );
+ ti[cnt].text_is_1byte = true;
+ ti[cnt].userdata = friendlies[i].tagstr;
+ }
+ ++cnt;
+ }
+ if ( cnt==0 ) {
+ if ( k ) {
+ ti[cnt].text = (unichar_t *) copy( _("You must choose a lookup type") );
+ ti[cnt].text_is_1byte = true;
+ ti[cnt].userdata = "????";
+ }
+ ++cnt;
+ }
+ if ( !k )
+ ti = gcalloc(cnt+1,sizeof(GTextInfo));
+ }
+return( ti );
+}
+
+static int Lookup_NameChanged(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
+ struct lookup_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
+ if ( *_GGadgetGetTitle(g)!='\0' )
+ ld->name_has_been_set = true;
+ }
+return( true );
+}
+
+static int LK_TypeChanged(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ int lookup_type = (intpt) GGadgetGetListItemSelected(g)->userdata;
+ struct lookup_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
+ GTextInfo *ti = FeatureListFromLookupType( lookup_type );
+ GMatrixEditSetColumnChoices( GWidgetGetControl(ld->gw,CID_LookupFeatures), 0, ti );
+ GTextInfoListFree(ti);
+ if ( !ld->isgpos ) {
+ GGadgetSetEnabled( GWidgetGetControl(ld->gw,CID_LookupAfm ), lookup_type==gsub_ligature );
+ if ( lookup_type!=gsub_ligature )
+ GGadgetSetChecked( GWidgetGetControl(ld->gw,CID_LookupAfm ), false );
+ }
+ }
+return( true );
+}
+
+static int Lookup_OK(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct lookup_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
+ int lookup_type = (intpt) GGadgetGetListItemSelected(GWidgetGetControl(ld->gw,CID_LookupType))->userdata;
+ int rows, i, isgpos;
+ struct matrix_data *strings = GMatrixEditGet(GWidgetGetControl(ld->gw,CID_LookupFeatures), &rows);
+ char *pt, *start, *name;
+ OTLookup *otl = ld->orig, *test;
+ int flags, afm;
+ FeatureScriptLangList *fhead;
+
+ if ( lookup_type==ot_undef ) {
+ gwwv_post_error(_("No Lookup Type Selected"),_("You must select a Lookup Type."));
+return(true);
+ }
+ if ( *_GGadgetGetTitle(GWidgetGetControl(ld->gw,CID_LookupName))=='\0' ) {
+ gwwv_post_error(_("Unnamed lookup"),_("You must name the lookup."));
+return(true);
+ }
+ for ( i=0; i<rows; ++i ) {
+ if ( sscanf(strings[2*i+0].u.md_str,"<%*d,%*d>" )== 2 )
+ /* It's a mac feature/setting */;
+ else if ( strlen(strings[2*i+0].u.md_str)>4 ) {
+ gwwv_post_error(_("Bad feature tag"),_("The feature tag on line %d (%s) is too long. It may be at most 4 letters (or it could be a mac feature setting, two numbers in brokets <3,4>)"),
+ i+1, strings[2*i+0].u.md_str);
+return(true);
+ } else {
+ for ( pt=strings[2*i+0].u.md_str; *pt!='\0' ; ++pt )
+ if ( *pt>0x7e ) {
+ gwwv_post_error(_("Bad feature tag"),_("The feature tag on line %d (%s) should be in ASCII.\n"),
+ i+1, strings[2*i+0].u.md_str);
+return( true );
+ }
+ }
+ /* Now check the script langs */
+ for ( start=strings[2*i+1].u.md_str; *start!='\0'; ) {
+ for ( pt=start; *pt!='{' && *pt!='\0'; ++pt ) {
+ if ( *pt>0x7e ) {
+ gwwv_post_error(_("Bad script tag"),_("A script tag on line %d (%s) should be in ASCII.\n"),
+ i+1, strings[2*i+1].u.md_str);
+return( true );
+ }
+ }
+ if ( pt-start>4 ) {
+ gwwv_post_error(_("Bad script tag"),_("A script tag on line %d (%s) is too long. It may be at most 4 letters"),
+ i+1, strings[2*i+0].u.md_str);
+return(true);
+ }
+ if ( *pt=='{' ) {
+ for ( start=pt+1; *start!='}' && *start!='\0' ; ) {
+ for ( pt=start; *pt!='}' && *pt!=',' && *pt!='\0'; ++pt ) {
+ if ( *pt>0x7e ) {
+ gwwv_post_error(_("Bad language tag"),_("A language tag on line %d (%s) should be in ASCII.\n"),
+ i+1, strings[2*i+1].u.md_str);
+return( true );
+ }
+ }
+ if ( pt-start>4 ) {
+ gwwv_post_error(_("Bad language tag"),_("A language tag on line %d (%s) is too long. It may be at most 4 letters"),
+ i+1, strings[2*i+0].u.md_str);
+return(true);
+ }
+ start = ( *pt==',' ) ? pt+1 : pt;
+ }
+ if ( *start=='}' ) ++start;
+ } else
+ start = pt;
+ while ( *start==' ' ) ++start;
+ }
+ }
+ name = GGadgetGetTitle8(GWidgetGetControl(ld->gw,CID_LookupName));
+ for ( isgpos=0; isgpos<2; ++isgpos ) {
+ for ( test = isgpos ? ld->sf->gpos_lookups : ld->sf->gsub_lookups; test!=NULL; test=test->next ) {
+ if ( test!=otl && strcmp(test->lookup_name,name)==0 ) {
+ gwwv_post_error(_("Lookup name already used"),_("This name has already been used for another lookup.\nLookup names must be unique.") );
+ free(name);
+return(true);
+ }
+ }
+ }
+
+ flags = 0;
+ if ( GGadgetIsChecked(GWidgetGetControl(ld->gw,CID_Lookup_R2L)) ) flags |= pst_r2l;
+ if ( GGadgetIsChecked(GWidgetGetControl(ld->gw,CID_Lookup_IgnBase)) ) flags |= pst_ignorebaseglyphs;
+ if ( GGadgetIsChecked(GWidgetGetControl(ld->gw,CID_Lookup_IgnLig)) ) flags |= pst_ignoreligatures;
+ if ( GGadgetIsChecked(GWidgetGetControl(ld->gw,CID_Lookup_IgnMark)) ) flags |= pst_ignorecombiningmarks;
+ flags |= ((intpt) GGadgetGetListItemSelected(GWidgetGetControl(ld->gw,CID_Lookup_ProcessMark))->userdata)<<8;
+
+ if ( !ld->isgpos )
+ afm = GGadgetIsChecked( GWidgetGetControl(ld->gw,CID_LookupAfm ));
+ else
+ afm = false;
+
+ /* Ok, we validated the feature script lang list. Now parse it */
+ fhead = LK_ParseFL(strings,rows);
+ free( otl->lookup_name );
+ FeatureScriptLangListFree( otl->features );
+ otl->lookup_name = name;
+ otl->lookup_type = lookup_type;
+ otl->lookup_flags = flags;
+ otl->features = FLOrder(fhead);
+ otl->store_in_afm = afm;
+ ld->done = true;
+ ld->ok = true;
+ }
+return( true );
+}
+
+static int Lookup_Cancel(GGadget *g, GEvent *e) {
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct lookup_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
+ ld->done = true;
+ ld->ok = false;
+ }
+return( true );
+}
+
+static int lookup_e_h(GWindow gw, GEvent *event) {
+
+ if ( event->type==et_close ) {
+ struct lookup_dlg *ld = GDrawGetUserData(gw);
+ ld->done = true;
+ ld->ok = false;
+ } else if ( event->type == et_char ) {
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("lookups.html#Add-Lookup");
+return( true );
+ }
+return( false );
+ }
+
+return( true );
+}
+
+int EditLookup(OTLookup *otl,int isgpos,SplineFont *sf) {
+ /* Ok we must provide a lookup type (but only if otl->type==ot_undef) */
+ /* a set of lookup flags */
+ /* a name */
+ /* A potentially empty set of features, scripts and languages */
+ /* afm */
+ /* check to make sure the name isn't a duplicate */
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[14], boxes[7];
+ GGadgetCreateData *harray1[4], *varray[14], *flagharray[4], *flagarray[12],
+ *harray2[4], *harray3[8];
+ GTextInfo label[14];
+ struct lookup_dlg ld;
+ struct matrixinit mi;
+ int class, i, k, vpos;
+
+ LookupUIInit();
+
+ memset(&ld,0,sizeof(ld));
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.is_dlg = true;
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Lookup...");
+ pos.x = pos.y = 0;
+ pos.width =GDrawPointsToPixels(NULL,GGadgetScale(268));
+ pos.height = GDrawPointsToPixels(NULL,375);
+ ld.gw = gw = GDrawCreateTopWindow(NULL,&pos,lookup_e_h,&ld,&wattrs);
+
+ ld.orig = otl;
+ ld.sf = sf;
+ ld.isgpos = isgpos;
+
+ memset(boxes,0,sizeof(boxes));
+ memset(gcd,0,sizeof(gcd));
+ memset(label,0,sizeof(label));
+
+ label[0].text = (unichar_t *) _("Type:");
+ label[0].text_is_1byte = true;
+ label[0].text_in_resource = true;
+ gcd[0].gd.label = &label[0];
+ gcd[0].gd.pos.x = 12; gcd[0].gd.pos.y = 6+6;
+ gcd[0].gd.flags = gg_visible | gg_enabled;
+ gcd[0].creator = GLabelCreate;
+
+ gcd[1].gd.pos.x = 100; gcd[1].gd.pos.y = 6; gcd[1].gd.pos.width = 200;
+ gcd[1].gd.flags = otl->lookup_type!=ot_undef && otl->subtables!=NULL?
+ (gg_visible| gg_utf8_popup) : (gg_visible | gg_enabled| gg_utf8_popup);
+ gcd[1].gd.cid = CID_LookupType;
+ gcd[1].gd.u.list = lookuptypes[isgpos];
+ gcd[1].gd.handle_controlevent = LK_TypeChanged;
+ gcd[1].gd.popup_msg = (unichar_t *) _(
+ "Each lookup may contain many transformations,\n"
+ "but each transformation must be of the same type.");
+ gcd[1].creator = GListButtonCreate;
+
+ for ( i=0; lookuptypes[isgpos][i].text!=NULL || lookuptypes[isgpos][i].line; ++i ) {
+ if ( (void *) otl->lookup_type == lookuptypes[isgpos][i].userdata &&
+ !lookuptypes[isgpos][i].line) {
+ lookuptypes[isgpos][i].selected = true;
+ gcd[1].gd.label = &lookuptypes[isgpos][i];
+ } else
+ lookuptypes[isgpos][i].selected = false;
+ }
+ harray1[0] = &gcd[0]; harray1[1] = &gcd[1]; harray1[2] = GCD_Glue; harray1[3] = NULL;
+ boxes[0].gd.flags = gg_enabled|gg_visible;
+ boxes[0].gd.u.boxelements = harray1;
+ boxes[0].creator = GHBoxCreate;
+ varray[0] = &boxes[0]; varray[1] = NULL;
+
+ LKMatrixInit(&mi,otl);
+ featureci[0].enum_vals = FeatureListFromLookupType(otl->lookup_type);
+
+ gcd[2].gd.pos.x = 10; gcd[2].gd.pos.y = gcd[1].gd.pos.y+14;
+ gcd[2].gd.pos.width = 300; gcd[2].gd.pos.height = 90;
+ gcd[2].gd.flags = gg_enabled | gg_visible | gg_utf8_popup;
+ gcd[2].gd.cid = CID_LookupFeatures;
+ gcd[2].gd.u.matrix = &mi;
+ gcd[2].gd.popup_msg = (unichar_t *) _(
+ "Most lookups will be attached to a feature\n"
+ "active in a specific script for certain languages.\n"
+ "In some cases lookups will not be attached to any\n"
+ "feature, but will be invoked by another lookup,\n"
+ "a conditional one. In other cases a lookup might\n"
+ "be attached to several features.\n"
+ "A feature is either a four letter OpenType feature\n"
+ "tag, or a two number mac <feature,setting> combination.");
+ gcd[2].creator = GMatrixEditCreate;
+ varray[2] = &gcd[2]; varray[3] = NULL;
+
+
+ gcd[3].gd.pos.x = 5; gcd[3].gd.pos.y = 5;
+ gcd[3].gd.flags = gg_visible | gg_enabled | (otl->lookup_flags&pst_r2l?gg_cb_on:0);
+ label[3].text = (unichar_t *) _("Right To Left");
+ label[3].text_is_1byte = true;
+ gcd[3].gd.label = &label[3];
+ gcd[3].gd.cid = CID_Lookup_R2L;
+ gcd[3].creator = GCheckBoxCreate;
+ flagarray[0] = &gcd[3]; flagarray[1] = NULL;
+
+ gcd[4].gd.pos.x = 5; gcd[4].gd.pos.y = gcd[3].gd.pos.y+15;
+ gcd[4].gd.flags = gg_visible | gg_enabled | (otl->lookup_flags&pst_ignorebaseglyphs?gg_cb_on:0);
+ label[4].text = (unichar_t *) _("Ignore Base Glyphs");
+ label[4].text_is_1byte = true;
+ gcd[4].gd.label = &label[4];
+ gcd[4].gd.cid = CID_Lookup_IgnBase;
+ gcd[4].creator = GCheckBoxCreate;
+ flagarray[2] = &gcd[4]; flagarray[3] = NULL;
+
+ gcd[5].gd.pos.x = 5; gcd[5].gd.pos.y = gcd[4].gd.pos.y+15;
+ gcd[5].gd.flags = gg_visible | gg_enabled | (otl->lookup_flags&pst_ignoreligatures?gg_cb_on:0);
+ label[5].text = (unichar_t *) _("Ignore Ligatures");
+ label[5].text_is_1byte = true;
+ gcd[5].gd.label = &label[5];
+ gcd[5].gd.cid = CID_Lookup_IgnLig;
+ gcd[5].creator = GCheckBoxCreate;
+ flagarray[4] = &gcd[5]; flagarray[5] = NULL;
+
+ gcd[6].gd.pos.x = 5; gcd[6].gd.pos.y = gcd[5].gd.pos.y+15;
+ gcd[6].gd.flags = gg_visible | gg_enabled | (otl->lookup_flags&pst_ignorecombiningmarks?gg_cb_on:0);
+ label[6].text = (unichar_t *) _("Ignore Combining Marks");
+ label[6].text_is_1byte = true;
+ gcd[6].gd.label = &label[6];
+ gcd[6].gd.cid = CID_Lookup_IgnMark;
+ gcd[6].creator = GCheckBoxCreate;
+ flagarray[6] = &gcd[6]; flagarray[7] = NULL;
+
+/* GT: Process is a verb here and Mark is a noun. */
+/* GT: Marks of the given mark class are to be processed */
+ label[7].text = (unichar_t *) _("Process Marks:");
+ label[7].text_is_1byte = true;
+ gcd[7].gd.label = &label[7];
+ gcd[7].gd.pos.x = 5; gcd[7].gd.pos.y = gcd[6].gd.pos.y+16;
+ gcd[7].gd.flags = sf->mark_class_cnt<=1 ? gg_visible : (gg_enabled|gg_visible);
+ gcd[7].creator = GLabelCreate;
+ flagharray[0] = &gcd[7];
+
+ gcd[8].gd.pos.x = 10; gcd[8].gd.pos.y = gcd[7].gd.pos.y;
+ gcd[8].gd.pos.width = 140;
+ gcd[8].gd.flags = gcd[7].gd.flags;
+ if ( (class = ((otl->lookup_flags&0xff00)>>8) )>= sf->mark_class_cnt )
+ class = 0;
+ gcd[8].gd.u.list = SFMarkClassList(sf,class);
+ gcd[8].gd.label = &gcd[8].gd.u.list[class];
+ gcd[8].gd.cid = CID_Lookup_ProcessMark;
+ gcd[8].creator = GListButtonCreate;
+ flagharray[1] = &gcd[8]; flagharray[2] = GCD_Glue; flagharray[3] = NULL;
+
+ boxes[1].gd.flags = gg_enabled|gg_visible;
+ boxes[1].gd.u.boxelements = flagharray;
+ boxes[1].creator = GHBoxCreate;
+
+ flagarray[8] = &boxes[1]; flagarray[9] = NULL; flagarray[10] = NULL;
+
+ boxes[2].gd.pos.x = boxes[2].gd.pos.y = 2;
+ boxes[2].gd.flags = gg_enabled|gg_visible;
+ boxes[2].gd.u.boxelements = flagarray;
+ boxes[2].creator = GHVGroupCreate;
+ varray[4] = &boxes[2]; varray[5] = NULL;
+
+ label[9].text = (unichar_t *) _("Lookup Name:");
+ label[9].text_is_1byte = true;
+ gcd[9].gd.label = &label[9];
+ gcd[9].gd.pos.x = 5; gcd[9].gd.pos.y = gcd[8].gd.pos.y+16;
+ gcd[9].gd.flags = gg_enabled|gg_visible;
+ gcd[9].creator = GLabelCreate;
+ harray2[0] = &gcd[9];
+
+ label[10].text = (unichar_t *) otl->lookup_name;
+ label[10].text_is_1byte = true;
+ gcd[10].gd.pos.x = 10; gcd[10].gd.pos.y = gcd[9].gd.pos.y;
+ gcd[10].gd.pos.width = 140;
+ gcd[10].gd.flags = gcd[9].gd.flags;
+ gcd[10].gd.label = otl->lookup_name==NULL ? NULL : &label[10];
+ gcd[10].gd.cid = CID_LookupName;
+ gcd[10].gd.handle_controlevent = Lookup_NameChanged;
+ gcd[10].creator = GTextFieldCreate;
+ harray2[1] = &gcd[10]; harray2[2] = NULL;
+ if ( otl->lookup_name!=NULL && *otl->lookup_name!='\0' )
+ ld.name_has_been_set = true;
+
+ boxes[3].gd.flags = gg_enabled|gg_visible;
+ boxes[3].gd.u.boxelements = harray2;
+ boxes[3].creator = GHBoxCreate;
+ varray[6] = &boxes[3]; varray[7] = NULL;
+
+ k = 11; vpos = 8;
+ if ( !isgpos ) {
+ gcd[11].gd.pos.x = 5; gcd[11].gd.pos.y = gcd[5].gd.pos.y+15;
+ gcd[11].gd.flags = otl->lookup_type!=gsub_ligature ? gg_visible :
+ otl->store_in_afm ? (gg_visible | gg_enabled | gg_cb_on) :
+ (gg_visible | gg_enabled);
+ label[11].text = (unichar_t *) _("Store ligature data in AFM files");
+ label[11].text_is_1byte = true;
+ gcd[11].gd.label = &label[11];
+ gcd[11].gd.cid = CID_LookupAfm;
+ gcd[11].creator = GCheckBoxCreate;
+ varray[8] = &gcd[11]; varray[9] = NULL;
+ k = 12; vpos = 10;
+ }
+
+ gcd[k].gd.pos.x = 30-3;
+ gcd[k].gd.pos.width = -1; gcd[k].gd.pos.height = 0;
+ gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[k].text = (unichar_t *) _("_OK");
+ label[k].text_is_1byte = true;
+ label[k].text_in_resource = true;
+ gcd[k].gd.label = &label[k];
+ gcd[k].gd.handle_controlevent = Lookup_OK;
+ gcd[k].gd.cid = CID_OK;
+ gcd[k].creator = GButtonCreate;
+
+ gcd[k+1].gd.pos.x = -30;
+ gcd[k+1].gd.pos.width = -1; gcd[k+1].gd.pos.height = 0;
+ gcd[k+1].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[k+1].text = (unichar_t *) _("_Cancel");
+ label[k+1].text_is_1byte = true;
+ label[k+1].text_in_resource = true;
+ gcd[k+1].gd.label = &label[k+1];
+ gcd[k+1].gd.handle_controlevent = Lookup_Cancel;
+ gcd[k+1].gd.cid = CID_Cancel;
+ gcd[k+1].creator = GButtonCreate;
+
+ harray3[0] = harray3[2] = harray3[3] = harray3[4] = harray3[6] = GCD_Glue;
+ harray3[7] = NULL;
+ harray3[1] = &gcd[k]; harray3[5] = &gcd[k+1];
+
+ boxes[4].gd.flags = gg_enabled|gg_visible;
+ boxes[4].gd.u.boxelements = harray3;
+ boxes[4].creator = GHBoxCreate;
+ varray[vpos++] = &boxes[4]; varray[vpos++] = NULL; varray[vpos] = NULL;
+
+ boxes[5].gd.pos.x = boxes[5].gd.pos.y = 2;
+ boxes[5].gd.flags = gg_enabled|gg_visible;
+ boxes[5].gd.u.boxelements = varray;
+ boxes[5].creator = GHVGroupCreate;
+
+ GGadgetsCreate(gw,boxes+5);
+
+ GTextInfoListFree(gcd[8].gd.u.list);
+
+ for ( i=0; i<mi.initial_row_cnt; ++i ) {
+ free( mi.matrix_data[2*i+0].u.md_str );
+ free( mi.matrix_data[2*i+1].u.md_str );
+ }
+ free( mi.matrix_data );
+
+ GMatrixEditSetNewText(gcd[2].ret,S_("OpenTypeFeature|New"));
+ GHVBoxSetExpandableRow(boxes[5].ret,1);
+ GHVBoxSetExpandableCol(boxes[4].ret,gb_expandgluesame);
+ GHVBoxSetExpandableCol(boxes[3].ret,1);
+ GHVBoxSetExpandableCol(boxes[1].ret,1);
+ GHVBoxSetExpandableCol(boxes[0].ret,gb_expandglue);
+
+ GHVBoxFitWindow(boxes[5].ret);
+
+ GDrawSetVisible(gw,true);
+ while ( !ld.done )
+ GDrawProcessOneEvent(NULL);
+ GDrawDestroyWindow(gw);
+
+return( ld.ok );
+}
+#endif
+
+static int _FeatureOrderId( int isgpos,uint32 tag ) {
+ /* This is the order in which features should be executed */
+
+ if ( !isgpos ) switch ( tag ) {
+/* GSUB ordering */
+ case CHR('c','c','m','p'): /* Must be first? */
+return( -2 );
+ case CHR('l','o','c','l'): /* Language dependent letter forms (serbian uses some different glyphs than russian) */
+return( -1 );
+ case CHR('i','s','o','l'):
+return( 0 );
+ case CHR('j','a','l','t'): /* must come after 'isol' */
+return( 1 );
+ case CHR('f','i','n','a'):
+return( 2 );
+ case CHR('f','i','n','2'):
+ case CHR('f','a','l','t'): /* must come after 'fina' */
+return( 3 );
+ case CHR('f','i','n','3'):
+return( 4 );
+ case CHR('m','e','d','i'):
+return( 5 );
+ case CHR('m','e','d','2'):
+return( 6 );
+ case CHR('i','n','i','t'):
+return( 7 );
+
+ case CHR('r','t','l','a'):
+return( 100 );
+ case CHR('s','m','c','p'): case CHR('c','2','s','c'):
+return( 200 );
+
+ case CHR('r','l','i','g'):
+return( 300 );
+ case CHR('c','a','l','t'):
+return( 301 );
+ case CHR('l','i','g','a'):
+return( 302 );
+ case CHR('d','l','i','g'): case CHR('h','l','i','g'):
+return( 303 );
+ case CHR('c','s','w','h'):
+return( 304 );
+ case CHR('m','s','e','t'):
+return( 305 );
+
+ case CHR('f','r','a','c'):
+return( 306 );
+
+/* Indic processing */
+ case CHR('n','u','k','t'):
+ case CHR('p','r','e','f'):
+return( 301 );
+ case CHR('a','k','h','n'):
+return( 302 );
+ case CHR('r','p','h','f'):
+return( 303 );
+ case CHR('b','l','w','f'):
+return( 304 );
+ case CHR('h','a','l','f'):
+ case CHR('a','b','v','f'):
+return( 305 );
+ case CHR('p','s','t','f'):
+return( 306 );
+ case CHR('v','a','t','u'):
+return( 307 );
+
+ case CHR('p','r','e','s'):
+return( 310 );
+ case CHR('b','l','w','s'):
+return( 311 );
+ case CHR('a','b','v','s'):
+return( 312 );
+ case CHR('p','s','t','s'):
+return( 313 );
+ case CHR('c','l','i','g'):
+return( 314 );
+
+ case CHR('h','a','l','n'):
+return( 320 );
+/* end indic ordering */
+
+ case CHR('a','f','r','c'):
+ case CHR('l','j','m','o'):
+ case CHR('v','j','m','o'):
+return( 350 );
+ case CHR('v','r','t','2'): case CHR('v','e','r','t'):
+return( 1010 ); /* Documented to come last */
+
+/* Unknown things come after everything but vert/vrt2 */
+ default:
+return( 1000 );
+
+ } else switch ( tag ) {
+/* GPOS ordering */
+ case CHR('c','u','r','s'):
+return( 0 );
+ case CHR('d','i','s','t'):
+return( 100 );
+ case CHR('b','l','w','m'):
+return( 201 );
+ case CHR('a','b','v','m'):
+return( 202 );
+ case CHR('k','e','r','n'):
+return( 300 );
+ case CHR('m','a','r','k'):
+return( 400 );
+ case CHR('m','k','m','k'):
+return( 500 );
+/* Unknown things come after everything */
+ default:
+return( 1000 );
+ }
+}
+
+int FeatureOrderId( int isgpos,FeatureScriptLangList *fl ) {
+ int pos = 9999, temp;
+
+ if ( fl==NULL )
+return( 0 );
+
+ while ( fl!=NULL ) {
+ temp = _FeatureOrderId(isgpos,fl->featuretag );
+ if ( temp<pos ) pos = temp;
+ fl = fl->next;
+ }
+return( pos );
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+
+static OTLookup *CreateAndSortNewLookupOfType(SplineFont *sf, int lookup_type) {
+ OTLookup *newotl;
+ int isgpos = lookup_type>=gpos_start;
+
+ newotl = chunkalloc(sizeof(OTLookup));
+ newotl->lookup_type = lookup_type;
+ if ( !EditLookup(newotl,isgpos,sf)) {
+ chunkfree(newotl,sizeof(OTLookup));
+return( NULL );
+ }
+ SortInsertLookup(sf, newotl);
+return( newotl );
+}
+#endif
+
+/* ************************************************************************** */
+/* ***************************** Anchor Subtable **************************** */
+/* ************************************************************************** */
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+
+typedef struct anchorclassdlg {
+ SplineFont *sf;
+ struct lookup_subtable *sub;
+ GWindow gw;
+ int mag, pixelsize;
+ int orig_pos, orig_value, down;
+ BDFFont *display;
+ int done;
+} AnchorClassDlg, PSTKernDlg;
+#define CID_Anchors 2001
+
+#define CID_PSTList 2001
+#define CID_Alpha 2002
+#define CID_Unicode 2003
+#define CID_Scripts 2004
+#define CID_BaseChar 2005
+#define CID_Suffix 2006
+
+#define CID_KernDisplay 2022
+#define CID_PixelSize 2023
+#define CID_Magnification 2024
+
+static GTextInfo magnifications[] = {
+ { (unichar_t *) "100%", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 1, 0, 1},
+ { (unichar_t *) "200%", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "300%", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) "400%", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }
+};
+
+static AnchorClass *SFAddAnchorClass(SplineFont *sf,struct lookup_subtable *sub,
+ char *name) {
+ AnchorClass *ac;
+
+ ac = chunkalloc(sizeof(AnchorClass));
+ ac->name = copy(name);
+ ac->type = sub->lookup->lookup_type == gpos_mark2base ? act_mark :
+ sub->lookup->lookup_type == gpos_mark2ligature ? act_mklg :
+ sub->lookup->lookup_type == gpos_cursive ? act_curs :
+ act_mkmk;
+ ac->subtable = sub;
+ ac->next = sf->anchor;
+ sf->anchor = ac;
+return( ac );
+}
+
+static int AnchorClassD_ShowAnchors(GGadget *g, GEvent *e) {
+ AnchorClassDlg *acd;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct matrix_data *classes;
+ int32 class_cnt;
+ int row;
+ AnchorClass *ac;
+
+ acd = GDrawGetUserData(GGadgetGetWindow(g));
+ classes = GMatrixEditGet(GWidgetGetControl(acd->gw,CID_Anchors), &class_cnt);
+ row = GMatrixEditGetActiveRow(GWidgetGetControl(acd->gw,CID_Anchors));
+ if ( row==-1 )
+return( true );
+ for ( ac = acd->sf->anchor; ac!=NULL; ac=ac->next )
+ if ( strcmp(ac->name,classes[row].u.md_str)==0 )
+ break;
+ if ( ac==NULL ) {
+ ac = SFAddAnchorClass(acd->sf,acd->sub,classes[row].u.md_str);
+ } else if ( ac->subtable!=acd->sub ) {
+ gwwv_post_error(_("Name in use"),_("The name, %.80s, has already been used to identify an anchor class in a different lookup subtable (%.80s)"),
+ ac->name, ac->subtable->subtable_name );
+return( true );
+ }
+ AnchorControlClass(acd->sf,ac);
+ }
+return( true );
+}
+
+static void AC_EnableOtherButtons(GGadget *g,int r, int c) {
+ GGadgetSetEnabled(GWidgetGetControl(GGadgetGetWindow(g),CID_ShowAnchors),
+ r!=-1 );
+}
+
+static int AC_OK(GGadget *g, GEvent *e) {
+ AnchorClassDlg *acd;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct matrix_data *classes;
+ int32 class_cnt;
+ int i, justtest;
+ AnchorClass *ac, *acnext;
+
+ acd = GDrawGetUserData(GGadgetGetWindow(g));
+ classes = GMatrixEditGet(GWidgetGetControl(acd->gw,CID_Anchors), &class_cnt);
+ for ( justtest=1; justtest>=0 ; --justtest ) {
+ for ( ac = acd->sf->anchor; ac!=NULL; ac=ac->next )
+ ac->processed = false;
+ for ( i=0; i<class_cnt; ++i ) {
+ if ( *classes[i].u.md_str=='\0' )
+ continue; /* Ignore blank lines. They pressed return once too much or something */
+ for ( ac = acd->sf->anchor; ac!=NULL; ac=ac->next )
+ if ( strcmp(ac->name,classes[i].u.md_str)==0 )
+ break;
+ if ( ac==NULL ) {
+ if ( !justtest ) {
+ ac = SFAddAnchorClass(acd->sf,acd->sub,classes[i].u.md_str);
+ ac->processed = true;
+ }
+ } else if ( ac->subtable!=acd->sub ) {
+ gwwv_post_error(_("Name in use"),_("The name, %.80s, has already been used to identify an anchor class in a different lookup subtable (%.80s)"),
+ ac->name, ac->subtable->subtable_name );
+return( true );
+ } else if ( ac->processed ) {
+ gwwv_post_error(_("Name in use"),_("The name, %.80s, is used twice in this subtable"),
+ ac->name );
+return( true );
+ } else
+ ac->processed = true;
+ }
+ for ( ac = acd->sf->anchor; ac!=NULL; ac=acnext ) {
+ acnext = ac->next;
+ if ( !ac->processed && ac->subtable == acd->sub ) {
+ if ( justtest ) {
+ char *buts[3];
+ buts[0] = _("_Remove"); buts[1] = _("_Cancel"); buts[2]=NULL;
+ if ( gwwv_ask(_("Remove Anchor Class?"),(const char **) buts,0,1,_("Do you really want to remove the anchor class, %.80s?\nThis will remove all anchor points associated with that class."))==1 )
+return( true );
+ } else
+ SFRemoveAnchorClass(acd->sf,ac);
+ }
+ }
+ }
+ acd->done = true;
+ }
+return( true );
+}
+
+static void AC_DoCancel(AnchorClassDlg *acd) {
+ acd->done = true;
+}
+
+static int AC_Cancel(GGadget *g, GEvent *e) {
+ AnchorClassDlg *acd;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ acd = GDrawGetUserData(GGadgetGetWindow(g));
+ AC_DoCancel(acd);
+ }
+return( true );
+}
+
+static int acd_e_h(GWindow gw, GEvent *event) {
+ AnchorClassDlg *acd = GDrawGetUserData(gw);
+
+ switch ( event->type ) {
+ case et_close:
+ AC_DoCancel(acd);
+ break;
+ case et_char:
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("lookups.html#Anchor");
+return( true );
+ }
+return( false );
+ break;
+ case et_destroy:
+ break;
+ case et_mouseup: case et_mousemove: case et_mousedown:
+ break;
+ case et_expose:
+ break;
+ case et_resize:
+ break;
+ }
+return( true );
+}
+
+static void ACDMatrixInit(struct matrixinit *mi,SplineFont *sf, struct lookup_subtable *sub) {
+ int cnt;
+ AnchorClass *ac;
+ struct matrix_data *md;
+ static struct col_init ci[1] = {
+ { me_string , NULL, NULL, NULL, N_("Anchor Class Name") }
+ };
+ static int initted = false;
+
+ if ( !initted ) {
+ initted = true;
+ ci[0].title = S_(ci[0].title);
+ }
+
+ memset(mi,0,sizeof(*mi));
+ mi->col_cnt = 1;
+ mi->col_init = ci;
+
+ for ( ac=sf->anchor, cnt=0; ac!=NULL; ac=ac->next )
+ if ( ac->subtable == sub )
+ ++cnt;
+ if ( cnt==0 ) {
+ md = gcalloc(1,sizeof(struct matrix_data));
+ mi->initial_row_cnt = 0;
+ } else {
+ md = gcalloc(cnt,sizeof(struct matrix_data));
+ for ( ac=sf->anchor, cnt=0; ac!=NULL; ac=ac->next )
+ if ( ac->subtable == sub )
+ md[cnt++].u.md_str = ac->name;
+ mi->initial_row_cnt = cnt;
+ }
+ mi->matrix_data = md;
+}
+#endif
+
+/* Anchor list, [new], [delete], [edit], [show first mark/entry], [show first base/exit] */
+/* [ok], [cancel] */
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static void AnchorClassD(SplineFont *sf, struct lookup_subtable *sub) {
+ GRect pos;
+ GWindowAttrs wattrs;
+ AnchorClassDlg acd;
+ GWindow gw;
+ char buffer[200];
+ GGadgetCreateData gcd[6], buttonbox, mainbox[2];
+ GGadgetCreateData *buttonarray[8], *varray[7];
+ GTextInfo label[6];
+ int i;
+ struct matrixinit mi;
+
+ memset(&acd,0,sizeof(acd));
+ acd.sf = sf;
+ acd.sub = sub;
+
+ memset(&wattrs,0,sizeof(wattrs));
+ memset(&gcd,0,sizeof(gcd));
+ memset(&buttonbox,0,sizeof(buttonbox));
+ memset(&mainbox,0,sizeof(mainbox));
+ memset(&label,0,sizeof(label));
+
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = true;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ snprintf(buffer,sizeof(buffer),_("Anchor classes in subtable %.80s"),
+ sub->subtable_name );
+ wattrs.utf8_window_title = buffer;
+ wattrs.is_dlg = true;
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,300));
+ pos.height = GDrawPointsToPixels(NULL,200);
+ acd.gw = gw = GDrawCreateTopWindow(NULL,&pos,acd_e_h,&acd,&wattrs);
+
+ i = 0;
+
+ ACDMatrixInit(&mi,sf,sub);
+ gcd[i].gd.pos.width = 300; gcd[i].gd.pos.height = 200;
+ gcd[i].gd.flags = gg_enabled | gg_visible | gg_utf8_popup;
+ gcd[i].gd.cid = CID_Anchors;
+ gcd[i].gd.u.matrix = &mi;
+ gcd[i].data = &acd;
+ gcd[i++].creator = GMatrixEditCreate;
+ varray[0] = &gcd[i-1]; varray[1] = NULL;
+
+ gcd[i].gd.pos.x = 10; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+24+3;
+ gcd[i].gd.pos.width = -1;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[i].text = (unichar_t *) _("_OK");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.handle_controlevent = AC_OK;
+ gcd[i].gd.cid = CID_OK;
+ gcd[i++].creator = GButtonCreate;
+
+ gcd[i].gd.pos.x = -10; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+3;
+ gcd[i].gd.pos.width = -1;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[i].text = (unichar_t *) _("_Cancel");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.handle_controlevent = AC_Cancel;
+ gcd[i].gd.cid = CID_Cancel;
+ gcd[i++].creator = GButtonCreate;
+
+ buttonarray[0] = GCD_Glue; buttonarray[1] = &gcd[i-2]; buttonarray[2] = GCD_Glue;
+ buttonarray[3] = GCD_Glue; buttonarray[4] = &gcd[i-1]; buttonarray[5] = GCD_Glue;
+ buttonarray[6] = NULL;
+ buttonbox.gd.flags = gg_enabled|gg_visible;
+ buttonbox.gd.u.boxelements = buttonarray;
+ buttonbox.creator = GHBoxCreate;
+ varray[2] = &buttonbox; varray[3] = NULL; varray[4] = NULL;
+
+ mainbox[0].gd.pos.x = mainbox[0].gd.pos.y = 2;
+ mainbox[0].gd.flags = gg_enabled|gg_visible;
+ mainbox[0].gd.u.boxelements = varray;
+ mainbox[0].creator = GHVGroupCreate;
+
+ GGadgetsCreate(acd.gw,mainbox);
+ GHVBoxSetExpandableRow(mainbox[0].ret,0);
+ GHVBoxSetExpandableCol(buttonbox.ret,gb_expandgluesame);
+
+ gcd[i].gd.flags = gg_visible | gg_enabled;
+ label[i].text = (unichar_t *) S_("Anchor Control...");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.cid = CID_ShowAnchors;
+ gcd[i].gd.handle_controlevent = AnchorClassD_ShowAnchors;
+ gcd[i].creator = GButtonCreate;
+
+ GMatrixEditAddButtons(gcd[0].ret,gcd+i);
+ GMatrixEditSetOtherButtonEnable(gcd[0].ret,AC_EnableOtherButtons);
+ GMatrixEditSetNewText(gcd[0].ret,S_("New Anchor Class"));
+
+ GDrawSetVisible(acd.gw,true);
+ while ( !acd.done )
+ GDrawProcessOneEvent(NULL);
+ GDrawDestroyWindow(acd.gw);
+}
+#endif
+
+/* ************************************************************************** */
+/* ********************** Single/Double Glyph Subtables ********************* */
+/* ************************************************************************** */
+
+#ifndef LUA_FF_LIB
+
+static int isalphabetic = true, byscripts = true, stemming=true;
+int lookup_hideunused = true;
+static int ispair;
+
+struct sortinfo {
+ char *glyphname; /* We replace the glyph name with a pointer to*/
+ /* this structure, but must restore it when */
+ /* finished sorting */
+ SplineChar *sc; /* The glyph itself */
+ SplineChar *base; /* The base of Agrave would be A */
+ uint32 script;
+};
+
+static void SortPrep(PSTKernDlg *pstkd, struct matrix_data *md, struct sortinfo *si) {
+
+ si->glyphname = md->u.md_str;
+ md->u.md_ival = (intpt) si;
+
+ si->sc = SFGetChar(pstkd->sf,-1,si->glyphname);
+ if ( si->sc==NULL )
+return;
+ if ( byscripts )
+ si->script = SCScriptFromUnicode(si->sc);
+ if ( stemming ) {
+ const unichar_t *alt=NULL;
+ int uni = si->sc->unicodeenc;
+ char *pt;
+
+ if ( isdecompositionnormative(uni) &&
+ unicode_alternates[uni>>8]!=NULL &&
+ (alt = unicode_alternates[uni>>8][uni&0xff])!=NULL )
+ si->base = SFGetChar(pstkd->sf,alt[0],NULL);
+ if ( si->base==NULL &&
+ ((pt=strchr(si->glyphname,'.'))!=NULL ||
+ (pt=strchr(si->glyphname,'_'))!=NULL )) {
+ int ch = *pt;
+ *pt = '\0';
+ si->base = SFGetChar(pstkd->sf,-1,si->glyphname);
+ *pt = ch;
+ }
+ if ( si->base==NULL )
+ si->base = si->sc;
+ }
+}
+
+static void SortUnPrep(struct matrix_data *md) {
+ struct sortinfo *si = (struct sortinfo *) (md->u.md_ival);
+
+ md->u.md_str = si->glyphname;
+}
+
+static int _md_cmp(const struct sortinfo *md1, const struct sortinfo *md2) {
+
+ if ( md1->sc==NULL || md2->sc==NULL ) {
+ if ( md1->sc!=NULL )
+return( 1 );
+ else if ( md2->sc!=NULL )
+return( -1 );
+ else
+return( strcmp( md1->glyphname,md2->glyphname ));
+ }
+
+ if ( byscripts && md1->script!=md2->script ) {
+ if ( md1->script==DEFAULT_SCRIPT )
+return( 1 );
+ else if ( md2->script==DEFAULT_SCRIPT )
+return( -1 );
+ if ( md1->script>md2->script )
+return( 1 );
+ else
+return( -1 );
+ }
+
+ if ( !isalphabetic ) {
+ int uni1;
+ int uni2;
+
+ if ( stemming ) {
+ /* First ignore case */
+ uni1 = (md1->base->unicodeenc!=-1)? md1->base->unicodeenc : 0xffffff;
+ uni2 = (md2->base->unicodeenc!=-1)? md2->base->unicodeenc : 0xffffff;
+ if ( uni1<0x10000 && islower(uni1)) uni1 = toupper(uni1);
+ if ( uni2<0x10000 && islower(uni2)) uni2 = toupper(uni2);
+
+ if ( uni1>uni2 )
+return( 1 );
+ else if ( uni1<uni2 )
+return( -1 );
+
+ uni1 = (md1->base->unicodeenc!=-1)? md1->base->unicodeenc : 0xffffff;
+ uni2 = (md2->base->unicodeenc!=-1)? md2->base->unicodeenc : 0xffffff;
+ if ( uni1>uni2 )
+return( 1 );
+ else if ( uni1<uni2 )
+return( -1 );
+ }
+
+ uni1 = (md1->sc->unicodeenc!=-1)? md1->sc->unicodeenc : 0xffffff;
+ uni2 = (md2->sc->unicodeenc!=-1)? md2->sc->unicodeenc : 0xffffff;
+ if ( uni1>uni2 )
+return( 1 );
+ else if ( uni1<uni2 )
+return( -1 );
+ } else {
+ if ( stemming ) {
+ int ret;
+ ret = strcasecmp(md1->base->name,md2->base->name);
+ if ( ret!=0 )
+return( ret );
+ ret = strcmp(md1->base->name,md2->base->name);
+ if ( ret!=0 )
+return( ret );
+ }
+ }
+return( strcmp(md1->glyphname,md2->glyphname));
+}
+
+static int md_cmp(const void *_md1, const void *_md2) {
+ const struct matrix_data *md1 = _md1, *md2 = _md2;
+ int ret = _md_cmp((struct sortinfo *) md1->u.md_ival,(struct sortinfo *) md2->u.md_ival);
+
+ if ( ret==0 && ispair )
+ ret = _md_cmp((struct sortinfo *) md1[1].u.md_ival,(struct sortinfo *) md2[1].u.md_ival);
+return( ret );
+}
+
+static void PSTKD_DoSort(PSTKernDlg *pstkd,struct matrix_data *psts,int rows,int cols) {
+ struct sortinfo *primary, *secondary=NULL;
+ int i;
+
+ if ( pstkd->gw!=NULL && GWidgetGetControl(pstkd->gw,CID_Alpha)!=NULL ) {
+ isalphabetic = GGadgetIsChecked(GWidgetGetControl(pstkd->gw,CID_Alpha));
+ byscripts = GGadgetIsChecked(GWidgetGetControl(pstkd->gw,CID_Scripts));
+ stemming = GGadgetIsChecked(GWidgetGetControl(pstkd->gw,CID_BaseChar));
+ }
+ primary = gcalloc(rows,sizeof(struct sortinfo));
+ ispair = pstkd->sub->lookup->lookup_type == gpos_pair;
+ if ( ispair )
+ secondary = gcalloc(rows,sizeof(struct sortinfo));
+ for ( i=0; i<rows; ++i ) {
+ SortPrep(pstkd,&psts[i*cols+0],&primary[i]);
+ if ( ispair )
+ SortPrep(pstkd,&psts[i*cols+1],&secondary[i]);
+ }
+ qsort( psts, rows, cols*sizeof(struct matrix_data), md_cmp);
+ for ( i=0; i<rows; ++i ) {
+ SortUnPrep(&psts[i*cols+0]);
+ if ( ispair )
+ SortUnPrep(&psts[i*cols+1]);
+ }
+ free(primary);
+ free(secondary);
+}
+
+static void PSTMatrixInit(struct matrixinit *mi,SplineFont *_sf, struct lookup_subtable *sub, PSTKernDlg *pstkd) {
+ int cnt;
+ struct matrix_data *md;
+ static struct col_init simplesubsci[2] = {
+ { me_string , NULL, NULL, NULL, N_("Base Glyph Name") },
+ { me_string, NULL, NULL, NULL, N_("Replacement Glyph Name") }
+ };
+ static struct col_init ligatureci[2] = {
+ { me_string , NULL, NULL, NULL, N_("Ligature Glyph Name") },
+ { me_string, NULL, NULL, NULL, N_("Source Glyph Names") }
+ };
+ static struct col_init altmultsubsci[2] = {
+ { me_string , NULL, NULL, NULL, N_("Base Glyph Name") },
+ { me_string, NULL, NULL, NULL, N_("Replacement Glyph Names") }
+ };
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+#define SIM_DX 1
+#define SIM_DY 3
+#define SIM_DX_ADV 5
+#define SIM_DY_ADV 7
+#define PAIR_DX1 2
+#define PAIR_DY1 4
+#define PAIR_DX_ADV1 6
+#define PAIR_DY_ADV1 8
+#define PAIR_DX2 10
+#define PAIR_DY2 12
+#define PAIR_DX_ADV2 14
+#define PAIR_DY_ADV2 16
+ static struct col_init simpleposci[] = {
+ { me_string , NULL, NULL, NULL, N_("Base Glyph Name") },
+ { me_int, NULL, NULL, NULL, NU_("∆x") }, /* delta-x */
+/* GT: "Adjust" here means Device Table based pixel adjustments, an OpenType */
+/* GT: concept which allows small corrections for small pixel sizes where */
+/* GT: rounding errors (in kerning for example) may smush too glyphs together */
+/* GT: or space them too far apart. Generally not a problem for big pixelsizes*/
+ { me_string, NULL, NULL, NULL, N_("Adjust") },
+ { me_int, NULL, NULL, NULL, NU_("∆y") }, /* delta-y */
+ { me_string, NULL, NULL, NULL, N_("Adjust") },
+ { me_int, NULL, NULL, NULL, NU_("∆x_adv") }, /* delta-x-adv */
+ { me_string, NULL, NULL, NULL, N_("Adjust") },
+ { me_int, NULL, NULL, NULL, NU_("∆y_adv") }, /* delta-y-adv */
+ { me_string, NULL, NULL, NULL, N_("Adjust") }
+ };
+ static struct col_init pairposci[] = {
+ { me_string , NULL, NULL, NULL, N_("First Glyph Name") },
+ { me_string , NULL, NULL, NULL, N_("Second Glyph Name") },
+ { me_int, NULL, NULL, NULL, NU_("∆x #1") }, /* delta-x */
+ { me_string, NULL, NULL, NULL, N_("Adjust") },
+ { me_int, NULL, NULL, NULL, NU_("∆y #1") }, /* delta-y */
+ { me_string, NULL, NULL, NULL, N_("Adjust") },
+ { me_int, NULL, NULL, NULL, NU_("∆x_adv #1") }, /* delta-x-adv */
+ { me_string, NULL, NULL, NULL, N_("Adjust") },
+ { me_int, NULL, NULL, NULL, NU_("∆y_adv #1") }, /* delta-y-adv */
+ { me_string, NULL, NULL, NULL, N_("Adjust") },
+ { me_int, NULL, NULL, NULL, NU_("∆x #2") }, /* delta-x */
+ { me_string, NULL, NULL, NULL, N_("Adjust") },
+ { me_int, NULL, NULL, NULL, NU_("∆y #2") }, /* delta-y */
+ { me_string, NULL, NULL, NULL, N_("Adjust") },
+ { me_int, NULL, NULL, NULL, NU_("∆x_adv #2") }, /* delta-x-adv */
+ { me_string, NULL, NULL, NULL, N_("Adjust") },
+ { me_int, NULL, NULL, NULL, NU_("∆y_adv #2") }, /* delta-y-adv */
+ { me_string, NULL, NULL, NULL, N_("Adjust") }
+ };
+#else
+#define SIM_DX 1
+#define SIM_DY 2
+#define SIM_DX_ADV 3
+#define SIM_DY_ADV 4
+#define PAIR_DX1 2
+#define PAIR_DY1 3
+#define PAIR_DX_ADV1 4
+#define PAIR_DY_ADV1 5
+#define PAIR_DX2 6
+#define PAIR_DY2 7
+#define PAIR_DX_ADV2 8
+#define PAIR_DY_ADV2 9
+ static struct col_init simpleposci[5] = {
+ { me_string , NULL, NULL, NULL, N_("Base Glyph Name") },
+ { me_int, NULL, NULL, NULL, NU_("∆x") }, /* delta-x */
+ { me_int, NULL, NULL, NULL, NU_("∆y") }, /* delta-y */
+ { me_int, NULL, NULL, NULL, NU_("∆x_adv") }, /* delta-x-adv */
+ { me_int, NULL, NULL, NULL, NU_("∆y_adv") } /* delta-y-adv */
+ };
+ static struct col_init pairposci[10] = {
+ { me_string , NULL, NULL, NULL, N_("First Glyph Name") },
+ { me_string , NULL, NULL, NULL, N_("Second Glyph Name") },
+ { me_int, NULL, NULL, NULL, NU_("∆x #1") }, /* delta-x */
+ { me_int, NULL, NULL, NULL, NU_("∆y #1") }, /* delta-y */
+ { me_int, NULL, NULL, NULL, NU_("∆x_adv #1") }, /* delta-x-adv */
+ { me_int, NULL, NULL, NULL, NU_("∆y_adv #1") }, /* delta-y-adv */
+ { me_int, NULL, NULL, NULL, NU_("∆x #2") }, /* delta-x */
+ { me_int, NULL, NULL, NULL, NU_("∆y #2") }, /* delta-y */
+ { me_int, NULL, NULL, NULL, NU_("∆x_adv #2") }, /* delta-x-adv */
+ { me_int, NULL, NULL, NULL, NU_("∆y_adv #2") } /* delta-y-adv */
+ };
+#endif
+ static struct { int ltype; int cnt; struct col_init *ci; } fuf[] = {
+ { gsub_single, sizeof(simplesubsci)/sizeof(struct col_init), simplesubsci },
+ { gsub_multiple, sizeof(altmultsubsci)/sizeof(struct col_init), altmultsubsci },
+ { gsub_alternate, sizeof(altmultsubsci)/sizeof(struct col_init), altmultsubsci },
+ { gsub_ligature, sizeof(ligatureci)/sizeof(struct col_init), ligatureci },
+ { gpos_single, sizeof(simpleposci)/sizeof(struct col_init), simpleposci },
+ { gpos_pair, sizeof(pairposci)/sizeof(struct col_init), pairposci },
+ { 0 }
+ };
+ static int initted = false;
+ int lookup_type = sub->lookup->lookup_type;
+ int isv, r2l = sub->lookup->lookup_flags&pst_r2l;
+ int i,j, gid,k;
+ SplineFont *sf;
+ SplineChar *sc;
+ PST *pst;
+ KernPair *kp;
+
+ if ( !initted ) {
+ initted = true;
+ for ( i=0; fuf[i].ltype!=0; ++i ) if ( fuf[i].ltype!=gsub_alternate ) {
+ for ( j=0; j<fuf[i].cnt; ++j )
+ fuf[i].ci[j].title = S_(fuf[i].ci[j].title);
+ }
+ }
+
+ memset(mi,0,sizeof(*mi));
+ for ( i=0; fuf[i].ltype!=0 && fuf[i].ltype!=lookup_type; ++i );
+ if ( fuf[i].ltype==0 ) {
+ IError( "Unknown lookup type in PSTMatrixInit");
+ i -= 2;
+ }
+ mi->col_cnt = fuf[i].cnt;
+ mi->col_init = fuf[i].ci;
+
+ for ( j=0; j<2; ++j ) {
+ cnt = 0;
+ k = 0;
+ do {
+ sf = _sf->subfontcnt==0 ? _sf : _sf->subfonts[k];
+ for ( gid = 0; gid<sf->glyphcnt; ++gid ) if ( (sc=sf->glyphs[gid])!=NULL ) {
+ for ( pst = sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable == sub ) {
+ if ( j ) {
+ md[cnt*mi->col_cnt].u.md_str = copy( sc->name );
+ switch ( lookup_type ) {
+ case gsub_single:
+ md[cnt*mi->col_cnt+1].u.md_str = copy(pst->u.subs.variant);
+ break;
+ case gsub_multiple:
+ case gsub_alternate:
+ md[cnt*mi->col_cnt+1].u.md_str = copy(pst->u.mult.components);
+ break;
+ case gsub_ligature:
+ md[cnt*mi->col_cnt+1].u.md_str = copy(pst->u.lig.components);
+ break;
+ case gpos_single:
+ md[cnt*mi->col_cnt+SIM_DX].u.md_ival = pst->u.pos.xoff;
+ md[cnt*mi->col_cnt+SIM_DY].u.md_ival = pst->u.pos.yoff;
+ md[cnt*mi->col_cnt+SIM_DX_ADV].u.md_ival = pst->u.pos.h_adv_off;
+ md[cnt*mi->col_cnt+SIM_DY_ADV].u.md_ival = pst->u.pos.v_adv_off;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ ValDevTabToStrings(md,cnt*mi->col_cnt+SIM_DX+1,pst->u.pos.adjust);
+#endif
+ break;
+ case gpos_pair:
+ md[cnt*mi->col_cnt+1].u.md_str = copy( pst->u.pair.paired );
+ md[cnt*mi->col_cnt+PAIR_DX1].u.md_ival = pst->u.pair.vr[0].xoff;
+ md[cnt*mi->col_cnt+PAIR_DY1].u.md_ival = pst->u.pair.vr[0].yoff;
+ md[cnt*mi->col_cnt+PAIR_DX_ADV1].u.md_ival = pst->u.pair.vr[0].h_adv_off;
+ md[cnt*mi->col_cnt+PAIR_DY_ADV1].u.md_ival = pst->u.pair.vr[0].v_adv_off;
+ md[cnt*mi->col_cnt+PAIR_DX2].u.md_ival = pst->u.pair.vr[1].xoff;
+ md[cnt*mi->col_cnt+PAIR_DY2].u.md_ival = pst->u.pair.vr[1].yoff;
+ md[cnt*mi->col_cnt+PAIR_DX_ADV2].u.md_ival = pst->u.pair.vr[1].h_adv_off;
+ md[cnt*mi->col_cnt+PAIR_DY_ADV2].u.md_ival = pst->u.pair.vr[1].v_adv_off;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ ValDevTabToStrings(md,cnt*mi->col_cnt+PAIR_DX1+1,pst->u.pair.vr[0].adjust);
+ ValDevTabToStrings(md,cnt*mi->col_cnt+PAIR_DX2+1,pst->u.pair.vr[1].adjust);
+#endif
+ break;
+ }
+ }
+ ++cnt;
+ }
+ }
+ if ( lookup_type==gpos_pair ) {
+ for ( isv=0; isv<2; ++isv ) {
+ for ( kp = isv ? sc->vkerns : sc->kerns ; kp!=NULL; kp=kp->next ) {
+ if ( kp->subtable == sub ) {
+ if ( j ) {
+ md[cnt*mi->col_cnt+0].u.md_str = copy( sc->name );
+ md[cnt*mi->col_cnt+1].u.md_str = copy( kp->sc->name );
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( isv ) {
+ md[cnt*mi->col_cnt+PAIR_DY_ADV1].u.md_ival = kp->off;
+ DevTabToString(&md[cnt*mi->col_cnt+PAIR_DY_ADV1+1].u.md_str,kp->adjust);
+ } else if ( r2l ) {
+ md[cnt*mi->col_cnt+PAIR_DY_ADV1].u.md_ival = kp->off;
+ DevTabToString(&md[cnt*mi->col_cnt+PAIR_DY_ADV1+1].u.md_str,kp->adjust);
+ } else {
+ md[cnt*mi->col_cnt+PAIR_DX_ADV1].u.md_ival = kp->off;
+ DevTabToString(&md[cnt*mi->col_cnt+PAIR_DX_ADV1+1].u.md_str,kp->adjust);
+ }
+#else
+ if ( isv )
+ md[cnt*mi->col_cnt+PAIR_DY_ADV1].u.md_ival = kp->off;
+ else if ( r2l )
+ md[cnt*mi->col_cnt+PAIR_DX_ADV2].u.md_ival = kp->off;
+ else
+ md[cnt*mi->col_cnt+PAIR_DX_ADV1].u.md_ival = kp->off;
+#endif
+ }
+ ++cnt;
+ }
+ }
+ }
+ }
+ }
+ ++k;
+ } while ( k<_sf->subfontcnt );
+ if ( !j ) {
+ mi->initial_row_cnt = cnt;
+ if ( cnt==0 ) {
+ md = gcalloc(mi->col_cnt,sizeof(struct matrix_data));
+ break;
+ } else {
+ md = gcalloc(mi->col_cnt*cnt,sizeof(struct matrix_data));
+ }
+ }
+ }
+ PSTKD_DoSort(pstkd,md,cnt,mi->col_cnt);
+ mi->matrix_data = md;
+}
+
+static int PSTKD_Sort(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
+ PSTKernDlg *pstkd = GDrawGetUserData(GGadgetGetWindow(g));
+ GGadget *pstk = GWidgetGetControl(pstkd->gw,CID_PSTList);
+ int rows, cols = GMatrixEditGetColCnt(pstk);
+ struct matrix_data *old = GMatrixEditGet(pstk,&rows);
+ PSTKD_DoSort(pstkd,old,rows,cols);
+ GGadgetRedraw(pstk);
+ }
+return( true );
+}
+
+static void PSTKD_DoHideUnused(PSTKernDlg *pstkd) {
+ GGadget *pstk = GWidgetGetControl(pstkd->gw,CID_PSTList);
+ int rows, cols = GMatrixEditGetColCnt(pstk);
+ struct matrix_data *old = GMatrixEditGet(pstk,&rows);
+ uint8 cols_used[20];
+ int r, col, startc, tot;
+
+ startc = ( pstkd->sub->lookup->lookup_type == gpos_single ) ? 1 : 2;
+ if ( lookup_hideunused ) {
+ memset(cols_used,0,sizeof(cols_used));
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ for ( r=0; r<rows; ++r ) {
+ for ( col=startc; col<cols; col+=2 ) {
+ if ( old[cols*r+col].u.md_ival!=0 )
+ cols_used[col] = true;
+ if ( old[cols*r+col+1].u.md_str!=NULL && *old[cols*r+col+1].u.md_str!='\0' )
+ cols_used[col+1] = true;
+ }
+ }
+#else
+ for ( r=0; r<rows; ++r ) {
+ for ( col=startc; col<cols; ++col ) {
+ if ( old[cols*r+col].u.md_ival!=0 )
+ cols_used[col] = true;
+ }
+ }
+#endif
+ /* If no columns used (no info yet, all info is to preempt a kernclass and sets to 0) */
+ /* then show what we expect to be the default column for this kerning mode*/
+ for ( col=startc, tot=0; col<cols; ++col )
+ tot += cols_used[col];
+ if ( tot==0 ) {
+ if ( startc==1 ) {
+ cols_used[SIM_DX] = cols_used[SIM_DY] =
+ cols_used[SIM_DX_ADV] = cols_used[SIM_DY_ADV] = true;
+ } else {
+ if ( pstkd->sub->vertical_kerning )
+ cols_used[PAIR_DY_ADV1] = true;
+ else if ( pstkd->sub->lookup->lookup_flags&pst_r2l )
+ cols_used[PAIR_DX_ADV2] = true;
+ else
+ cols_used[PAIR_DX_ADV1] = true;
+ }
+ }
+ for ( col=startc; col<cols; ++col )
+ GMatrixEditShowColumn(pstk,col,cols_used[col]);
+ } else {
+ for ( col=startc; col<cols; ++col )
+ GMatrixEditShowColumn(pstk,col,true);
+ }
+ GWidgetToDesiredSize(pstkd->gw);
+
+ GGadgetRedraw(pstk);
+}
+
+static int PSTKD_HideUnused(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
+ PSTKernDlg *pstkd = GDrawGetUserData(GGadgetGetWindow(g));
+ lookup_hideunused = GGadgetIsChecked(g);
+ PSTKD_DoHideUnused(pstkd);
+ GGadgetRedraw(GWidgetGetControl(pstkd->gw,CID_PSTList));
+ }
+return( true );
+}
+
+static int PSTKD_MagnificationChanged(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ PSTKernDlg *pstkd = GDrawGetUserData(GGadgetGetWindow(g));
+ int mag = GGadgetGetFirstListSelectedItem(g);
+
+ if ( mag!=-1 && mag!=pstkd->mag-1 ) {
+ pstkd->mag = mag+1;
+ GGadgetRedraw(GWidgetGetControl(pstkd->gw,CID_KernDisplay));
+ }
+ }
+return( true );
+}
+
+static int PSTKD_DisplaySizeChanged(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
+ PSTKernDlg *pstkd = GDrawGetUserData(GGadgetGetWindow(g));
+ const unichar_t *ret = _GGadgetGetTitle(GWidgetGetControl(pstkd->gw,CID_PixelSize));
+ unichar_t *end;
+ int pixelsize = u_strtol(ret,&end,10);
+
+ while ( *end==' ' ) ++end;
+ if ( pixelsize>4 && pixelsize<400 && *end=='\0' ) {
+ pstkd->pixelsize = pixelsize;
+ if ( pstkd->display!=NULL ) {
+ BDFFontFree(pstkd->display);
+ pstkd->display = NULL;
+ }
+ GGadgetRedraw(GWidgetGetControl(pstkd->gw,CID_KernDisplay));
+ }
+ }
+return( true );
+}
+
+static void PSTKD_METextChanged(GGadget *g, int r, int c, GGadget *text) {
+ PSTKernDlg *pstkd = GDrawGetUserData(GGadgetGetWindow(g));
+ GGadgetRedraw(GWidgetGetControl(pstkd->gw,CID_KernDisplay));
+}
+
+static int FigureValue(struct matrix_data *old,int rcol,int c, int startc,
+ GGadget *tf,double scale, int pixelsize) {
+ int val;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ char *str, *freeme=NULL;
+ DeviceTable dt;
+#endif
+
+ if ( c==startc && tf!=NULL )
+ val = u_strtol(_GGadgetGetTitle(tf),NULL,10);
+ else
+ val = old[rcol+startc].u.md_ival;
+ val = rint(val*scale);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( c==startc+1 && tf!=NULL )
+ str = freeme = GGadgetGetTitle8(tf);
+ else
+ str = old[rcol+startc+1].u.md_str;
+ memset(&dt,0,sizeof(dt));
+ DeviceTableParse(&dt,str);
+ if ( pixelsize>=dt.first_pixel_size && pixelsize<=dt.last_pixel_size && dt.corrections!=NULL )
+ val += dt.corrections[pixelsize-dt.first_pixel_size];
+ free(dt.corrections);
+ free(freeme);
+#endif
+return( val );
+}
+
+static int ParsePSTKVR(PSTKernDlg *pstkd,GGadget *pstk,int startc,struct vr *vr) {
+ int rows, cols = GMatrixEditGetColCnt(pstk);
+ struct matrix_data *old = _GMatrixEditGet(pstk,&rows);
+ GGadget *tf = _GMatrixEditGetActiveTextField(pstk);
+ int r = GMatrixEditGetActiveRow(pstk);
+ int c = GMatrixEditGetActiveCol(pstk);
+ double scale = pstkd->pixelsize/(double) (pstkd->sf->ascent+pstkd->sf->descent);
+
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ vr->xoff = FigureValue(old,r*cols,c,startc,tf,scale,pstkd->pixelsize);
+ vr->yoff = FigureValue(old,r*cols,c,startc+2,tf,scale,pstkd->pixelsize);
+ vr->h_adv_off = FigureValue(old,r*cols,c,startc+4,tf,scale,pstkd->pixelsize);
+ vr->v_adv_off = FigureValue(old,r*cols,c,startc+6,tf,scale,pstkd->pixelsize);
+#else
+ vr->xoff = FigureValue(old,r*cols,c,startc,tf,scale,pstkd->pixelsize);
+ vr->yoff = FigureValue(old,r*cols,c,startc+1,tf,scale,pstkd->pixelsize);
+ vr->h_adv_off = FigureValue(old,r*cols,c,startc+2,tf,scale,pstkd->pixelsize);
+ vr->v_adv_off = FigureValue(old,r*cols,c,startc+3,tf,scale,pstkd->pixelsize);
+#endif
+return( true );
+}
+
+static void PSTKern_DrawGlyph(GWindow pixmap,int x,int y, BDFChar *bc, int mag) {
+ /* x,y is the location of the origin of the glyph, they need to */
+ /* be adjusted by the images xmin, ymax, etc. */
+ struct _GImage base;
+ GImage gi;
+ GClut clut;
+ int scale, l;
+ Color fg, bg;
+
+ scale = bc->depth == 8 ? 8 : 4;
+
+ memset(&gi,'\0',sizeof(gi));
+ memset(&base,'\0',sizeof(base));
+ memset(&clut,'\0',sizeof(clut));
+ gi.u.image = &base;
+ base.clut = &clut;
+ base.data = bc->bitmap;
+ base.bytes_per_line = bc->bytes_per_line;
+ base.width = bc->xmax-bc->xmin+1;
+ base.height = bc->ymax-bc->ymin+1;
+ base.image_type = it_index;
+ clut.clut_len = 1<<scale;
+ bg = GDrawGetDefaultBackground(NULL);
+ fg = GDrawGetDefaultForeground(NULL);
+ for ( l=0; l<(1<<scale); ++l )
+ clut.clut[l] =
+ COLOR_CREATE(
+ COLOR_RED(bg) + (l*(COLOR_RED(fg)-COLOR_RED(bg)))/((1<<scale)-1),
+ COLOR_GREEN(bg) + (l*(COLOR_GREEN(fg)-COLOR_GREEN(bg)))/((1<<scale)-1),
+ COLOR_BLUE(bg) + (l*(COLOR_BLUE(fg)-COLOR_BLUE(bg)))/((1<<scale)-1) );
+
+ x += bc->xmin;
+ y -= bc->ymax;
+
+ if ( mag==1 )
+ GDrawDrawImage(pixmap,&gi,NULL,x,y);
+ else
+ GDrawDrawImageMagnified(pixmap, &gi, NULL,
+ x*mag,y*mag,
+ base.width*mag,base.height*mag);
+}
+
+static void PSTKern_Expose(GWindow pixmap, PSTKernDlg *pstkd) {
+ GGadget *pstk = GWidgetGetControl(pstkd->gw,CID_PSTList);
+ int r;
+ int rows, cols = GMatrixEditGetColCnt(pstk);
+ struct matrix_data *old = _GMatrixEditGet(pstk,&rows);
+ SplineChar *sc1, *sc2;
+ BDFChar *bc1, *bc2;
+ struct vr vr1, vr2;
+ int xorig, yorig;
+ GRect size;
+ int mag = pstkd->mag;
+
+ if ( (r = GMatrixEditGetActiveRow(pstk))==-1 )
+return; /* No kerning pair is active */
+ if ( old[r*cols+0].u.md_str==NULL || old[r*cols+1].u.md_str==NULL )
+return; /* No glyphs specified to kern */
+ sc1 = SFGetChar(pstkd->sf,-1,old[r*cols+0].u.md_str);
+ sc2 = SFGetChar(pstkd->sf,-1,old[r*cols+1].u.md_str);
+ if ( sc1==NULL || sc2==NULL )
+return; /* The names specified weren't in the font */
+
+ if ( !ParsePSTKVR(pstkd,pstk,PAIR_DX1,&vr1) ||
+ !ParsePSTKVR(pstkd,pstk,PAIR_DX2,&vr2) )
+return; /* Couldn't parse the numeric kerning info */
+
+ if ( pstkd->display==NULL )
+ pstkd->display = SplineFontPieceMeal(pstkd->sf,pstkd->pixelsize,pf_antialias,NULL);
+ bc1 = BDFPieceMeal(pstkd->display,sc1->orig_pos);
+ bc2 = BDFPieceMeal(pstkd->display,sc2->orig_pos);
+
+ GDrawGetSize(GDrawableGetWindow(GWidgetGetControl(pstkd->gw,CID_KernDisplay)),&size);
+ if ( pstkd->sub->vertical_kerning ) {
+ double scale = pstkd->pixelsize/(double) (pstkd->sf->ascent+pstkd->sf->descent);
+ int vwidth1 = rint( sc1->vwidth*scale ), vwidth2 = rint( sc2->vwidth*scale );
+ xorig = size.width/10;
+ yorig = size.height/20;
+ xorig /= mag; yorig /= mag;
+ PSTKern_DrawGlyph(pixmap,xorig+vr1.xoff,yorig+vwidth1+vr1.yoff, bc1, mag);
+ PSTKern_DrawGlyph(pixmap,xorig+vr2.xoff,yorig+vwidth1+vwidth2+vr1.v_adv_off-vr2.yoff, bc2, mag);
+ } else if ( pstkd->sub->lookup->lookup_flags&pst_r2l ) {
+ xorig = 9*size.width/10;
+ yorig = pstkd->sf->ascent*size.height/(pstkd->sf->ascent+pstkd->sf->descent);
+ GDrawDrawLine(pixmap,xorig,0,xorig,size.height, 0x808080);
+ GDrawDrawLine(pixmap,0,yorig,size.width,yorig, 0x808080);
+ xorig /= mag; yorig /= mag;
+ PSTKern_DrawGlyph(pixmap,xorig-bc1->width-vr1.h_adv_off-vr1.xoff,yorig+vr1.yoff, bc1, mag);
+ PSTKern_DrawGlyph(pixmap,xorig-bc1->width-vr1.h_adv_off-bc2->width-vr2.h_adv_off-vr2.xoff,yorig+vr2.yoff, bc2, mag);
+ } else {
+ xorig = size.width/10;
+ yorig = pstkd->sf->ascent*size.height/(pstkd->sf->ascent+pstkd->sf->descent);
+ GDrawDrawLine(pixmap,xorig,0,xorig,size.height, 0x808080);
+ GDrawDrawLine(pixmap,0,yorig,size.width,yorig, 0x808080);
+ xorig /= mag; yorig /= mag;
+ PSTKern_DrawGlyph(pixmap,xorig+vr1.xoff,yorig+vr1.yoff, bc1, mag);
+ PSTKern_DrawGlyph(pixmap,xorig+bc1->width+vr1.h_adv_off+vr2.xoff,yorig+vr2.yoff, bc2, mag);
+ }
+}
+
+static void PSTKern_Mouse(PSTKernDlg *pstkd,GEvent *event) {
+ GGadget *pstk = GWidgetGetControl(pstkd->gw,CID_PSTList);
+ int r;
+ int rows, cols = GMatrixEditGetColCnt(pstk);
+ struct matrix_data *old = _GMatrixEditGet(pstk,&rows);
+ int c = GMatrixEditGetActiveCol(pstk);
+ GGadget *tf = _GMatrixEditGetActiveTextField(pstk);
+ double scale = pstkd->pixelsize/(double) (pstkd->sf->ascent+pstkd->sf->descent);
+ int diff, col;
+ char buffer[20];
+
+ if ( (r = GMatrixEditGetActiveRow(pstk))==-1 )
+return; /* No kerning pair is active */
+
+ if ( pstkd->sub->vertical_kerning ) {
+ diff = event->u.mouse.y - pstkd->orig_pos;
+ col = PAIR_DY_ADV1;
+ } else if ( pstkd->sub->lookup->lookup_flags&pst_r2l ) {
+ diff = pstkd->orig_pos - event->u.mouse.y;
+ col = PAIR_DX_ADV2;
+ } else {
+ diff = event->u.mouse.x - pstkd->orig_pos;
+ col = PAIR_DX_ADV1;
+ }
+
+ if ( event->type == et_mousedown ) {
+ pstkd->down = true;
+ pstkd->orig_pos = pstkd->sub->vertical_kerning ? event->u.mouse.y : event->u.mouse.x;
+ pstkd->orig_value = FigureValue(old,r*cols,c,col,tf,1.0,-1);
+ } else if ( pstkd->down ) {
+ diff = rint(diff/scale);
+ if ( col==c && tf!=NULL ) {
+ sprintf( buffer, "%d", pstkd->orig_value + diff);
+ GGadgetSetTitle8(tf,buffer);
+ GGadgetRedraw(tf);
+ } else {
+ old[r*cols+col].u.md_ival = pstkd->orig_value + diff;
+ GGadgetRedraw(pstk);
+ }
+ GGadgetRedraw(GWidgetGetControl(pstkd->gw,CID_KernDisplay));
+ if ( event->type == et_mouseup )
+ pstkd->down = false;
+ }
+}
+
+static int pstkern_e_h(GWindow gw, GEvent *event) {
+ switch ( event->type ) {
+ case et_char:
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("lookups.html#Pair");
+return( true );
+ }
+return( false );
+ case et_expose:
+ PSTKern_Expose(gw,GDrawGetUserData(gw));
+return( true );
+ case et_mousedown: case et_mouseup: case et_mousemove:
+ PSTKern_Mouse(GDrawGetUserData(gw),event);
+return( true );
+ }
+return( true );
+}
+
+static int SCReasonable(SplineChar *sc) {
+ if ( sc==NULL )
+return( false );
+ if ( strcmp(sc->name,".notdef")==0 ||
+ strcmp(sc->name,".null")==0 ||
+ strcmp(sc->name,"nonmarkingreturn")==0 )
+return( false );
+
+return( true );
+}
+
+static struct matrix_data *MDCopy(struct matrix_data *old,int rows,int cols) {
+ struct matrix_data *md = galloc(rows*cols*sizeof(struct matrix_data));
+ int r;
+
+ memcpy(md,old,rows*cols*sizeof(struct matrix_data));
+ for ( r=0; r<rows; ++r ) {
+ md[r*cols+0].u.md_str = copy(md[r*cols+0].u.md_str);
+ if ( cols==2 /* subs, lig, alt, etc. */ || cols==10 /* kerning */ )
+ md[r*cols+1].u.md_str = copy(md[r*cols+1].u.md_str);
+ }
+return( md );
+}
+
+static int SCNameUnused(char *name,struct matrix_data *old,int rows,int cols) {
+ int r;
+
+ for ( r=0; r<rows; ++r ) {
+ if ( old[r*cols+0].u.md_str!=NULL && strcmp(old[r*cols+0].u.md_str,name)==0 ) {
+ if (( cols==2 && (old[r*cols+1].u.md_str == NULL || *old[r*cols+1].u.md_str=='\0')) ||
+ (cols==5 && old[r*cols+1].u.md_ival==0 &&
+ old[r*cols+2].u.md_ival==0 &&
+ old[r*cols+3].u.md_ival==0 &&
+ old[r*cols+4].u.md_ival==0 ))
+return( r ); /* There's an entry, but it's blank, fill it if we can */
+ else
+return( -1 );
+ }
+ }
+return( r ); /* Off end of list */
+}
+
+static int SCIsLigature(SplineChar *sc) {
+ int len;
+ const unichar_t *alt=NULL;
+
+ if ( strchr(sc->name,'_')!=NULL )
+return( true );
+ len = strlen( sc->name );
+ if ( strncmp(sc->name,"uni",3)==0 && (len-3)%4==0 && len>7 )
+return( true );
+
+ if ( sc->unicodeenc==-1 || sc->unicodeenc>=0x10000 )
+return( false );
+ else if ( isdecompositionnormative(sc->unicodeenc) &&
+ unicode_alternates[sc->unicodeenc>>8]!=NULL &&
+ (alt = unicode_alternates[sc->unicodeenc>>8][sc->unicodeenc&0xff])!=NULL ) {
+ if ( alt[1]=='\0' )
+return( false ); /* Single replacements aren't ligatures */
+ else if ( iscombining(alt[1]) && ( alt[2]=='\0' || iscombining(alt[2])))
+return( false ); /* Nor am I interested in accented letters */
+ else
+return( true );
+ } else
+return( false );
+}
+
+static void PSTKD_DoPopulate(PSTKernDlg *pstkd,char *suffix) {
+ GGadget *pstk = GWidgetGetControl(pstkd->gw,CID_PSTList);
+ int rows, row_max, old_rows, cols = GMatrixEditGetColCnt(pstk);
+ struct matrix_data *old = GMatrixEditGet(pstk,&rows), *psts;
+ int pos;
+ int gid,k;
+ SplineChar *sc, *alt;
+ SplineFont *sf;
+
+ psts = MDCopy(old,rows,cols);
+ old_rows = row_max = rows;
+ k = 0;
+ do {
+ sf = pstkd->sf->subfontcnt==0 ? pstkd->sf : pstkd->sf->subfonts[k];
+ for ( gid=0; gid<sf->glyphcnt; ++gid ) {
+ if ( SCReasonable(sc = sf->glyphs[gid]) &&
+ ScriptInFeatureScriptList(SCScriptFromUnicode(sc),
+ pstkd->sub->lookup->features) &&
+ (pos = SCNameUnused(sc->name,old,old_rows,cols))!=-1 &&
+ (pstkd->sub->lookup->lookup_type!=gsub_ligature ||
+ SCIsLigature(sc)) ) {
+ alt = NULL;
+ if ( suffix!=NULL ) {
+ alt = SuffixCheck(sc,suffix);
+ if ( alt==NULL )
+ continue;
+ }
+ if ( pos==old_rows ) {
+ pos = rows;
+ if ( rows>=row_max ) {
+ if ( row_max< sf->glyphcnt-10 )
+ row_max = sf->glyphcnt;
+ else
+ row_max += 15;
+ psts = grealloc(psts,row_max*cols*sizeof(struct matrix_data));
+ }
+ memset(psts+rows*cols,0,cols*sizeof(struct matrix_data));
+ psts[rows*cols+0].u.md_str = copy(sc->name);
+ ++rows;
+ }
+ if ( alt!=NULL )
+ psts[pos*cols+1].u.md_str = copy(alt->name);
+ else if ( pstkd->sub->lookup->lookup_type!=gpos_pair )
+ SCSubtableDefaultSubsCheck(sc,pstkd->sub,psts,cols,pos);
+ }
+ }
+ ++k;
+ } while ( k<pstkd->sf->subfontcnt );
+ if ( rows<row_max )
+ psts = grealloc(psts,rows*cols*sizeof(struct matrix_data));
+ PSTKD_DoSort(pstkd,psts,rows,cols);
+ GMatrixEditSet(pstk,psts,rows,false);
+ GGadgetRedraw(pstk);
+}
+
+static void PSTKD_SetSuffix(PSTKernDlg *pstkd) {
+ char *suffix;
+
+ if ( pstkd->sub->lookup->lookup_type!=gsub_single )
+return; /* Not applicable */
+
+ suffix = GGadgetGetTitle8(GWidgetGetControl(pstkd->gw,CID_Suffix));
+ if ( *suffix!='\0' && ( suffix[0]!='.' || suffix[1]!='\0' )) {
+ free(pstkd->sub->suffix);
+ pstkd->sub->suffix = ( *suffix=='.' ) ? copy(suffix+1): copy(suffix);
+ free(suffix);
+ }
+}
+
+static int PSTKD_PopulateWithSuffix(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ PSTKernDlg *pstkd = GDrawGetUserData(GGadgetGetWindow(g));
+ char *suffix = GGadgetGetTitle8(GWidgetGetControl(pstkd->gw,CID_Suffix));
+ if ( *suffix!='\0' && ( suffix[0]!='.' || suffix[1]!='\0' )) {
+ PSTKD_DoPopulate(pstkd,suffix);
+ PSTKD_SetSuffix(pstkd);
+ }
+ free(suffix);
+ }
+return( true );
+}
+
+static int PSTKD_Populate(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ PSTKernDlg *pstkd = GDrawGetUserData(GGadgetGetWindow(g));
+ PSTKD_SetSuffix(pstkd);
+ PSTKD_DoPopulate(pstkd,NULL);
+ }
+return( true );
+}
+
+static int PSTKD_RemoveEmpty(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ PSTKernDlg *pstkd = GDrawGetUserData(GGadgetGetWindow(g));
+ GGadget *pstk = GWidgetGetControl(pstkd->gw,CID_PSTList);
+ int rows, cols = GMatrixEditGetColCnt(pstk);
+ struct matrix_data *old = GMatrixEditGet(pstk,&rows), *psts=NULL;
+ int r, empty, rm_cnt, j;
+
+ for ( r=rows-1, rm_cnt=0; r>=0; --r ) {
+ if ( pstkd->sub->lookup->lookup_type==gpos_single )
+ empty = old[r*cols+SIM_DX].u.md_ival==0 &&
+ old[r*cols+SIM_DY].u.md_ival==0 &&
+ old[r*cols+SIM_DX_ADV].u.md_ival==0 &&
+ old[r*cols+SIM_DY_ADV].u.md_ival==0;
+ else
+ empty = old[r*cols+1].u.md_str == NULL || *old[r*cols+1].u.md_str=='\0';
+ if ( empty ) {
+ if ( psts==NULL )
+ psts = MDCopy(old,rows,cols);
+ free(psts[r*cols+0].u.md_str);
+ if ( cols!=5 )
+ free(psts[r*cols+1].u.md_str);
+ for ( j=r+1; j<rows-rm_cnt; ++j )
+ memcpy(psts+(j-1)*cols,psts+j*cols,
+ cols*sizeof(struct matrix_data));
+ ++rm_cnt;
+ }
+ }
+ if ( rm_cnt!=0 ) {
+ psts = grealloc(psts,(rows-rm_cnt)*cols*sizeof(struct matrix_data));
+ GMatrixEditSet(pstk,psts,rows-rm_cnt,false);
+ }
+ }
+return( true );
+}
+
+static int PSTKD_Ok(GGadget *g, GEvent *e) {
+ PSTKernDlg *pstkd;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ pstkd = GDrawGetUserData(GGadgetGetWindow(g));
+ GGadget *pstk = GWidgetGetControl(pstkd->gw,CID_PSTList);
+ int rows, cols = GMatrixEditGetColCnt(pstk);
+ struct matrix_data *psts = GMatrixEditGet(pstk,&rows);
+ int r, r1, k, gid, isv, ch;
+ char *pt, *start;
+ int lookup_type = pstkd->sub->lookup->lookup_type;
+ SplineFont *sf = NULL;
+ SplineChar *sc, *found;
+ char *buts[3];
+ KernPair *kp, *kpprev, *kpnext;
+ PST *pst, *pstprev, *pstnext;
+ int _t = lookup_type == gpos_single ? pst_position
+ : lookup_type == gpos_pair ? pst_pair
+ : lookup_type == gsub_single ? pst_substitution
+ : lookup_type == gsub_alternate ? pst_alternate
+ : lookup_type == gsub_multiple ? pst_multiple
+ : pst_ligature;
+
+ /* First check for errors */
+ /* Glyph names that aren't in the font */
+ for ( r=0; r<rows; ++r ) {
+ if ( SFGetChar(pstkd->sf,-1,psts[r*cols+0].u.md_str)==NULL ) {
+ gwwv_post_error( _("Missing glyph"),_("There is no glyph named %s in the font"),
+ psts[cols*r+0].u.md_str );
+return( true );
+ }
+ }
+ /* Empty entries */
+ if ( cols==2 || cols==10 ) {
+ for ( r=0; r<rows; ++r ) {
+ start = psts[cols*r+1].u.md_str;
+ if ( start==NULL ) start="";
+ while ( *start== ' ' ) ++start;
+ if ( *start=='\0' ) {
+ gwwv_post_error( _("Missing glyph name"),_("You must specify a replacement glyph for %s"),
+ psts[cols*r+0].u.md_str );
+return( true );
+ }
+ /* Replacements which aren't in the font */
+ while ( *start ) {
+ for ( pt=start; *pt!='\0' && *pt!=' '; ++pt );
+ ch = *pt; *pt='\0';
+ found = SFGetChar(pstkd->sf,-1,start);
+ if ( found==NULL ) {
+ buts[0] = _("_Yes");
+ buts[1] = _("_Cancel");
+ buts[2] = NULL;
+ if ( gwwv_ask(_("Missing glyph"),(const char **) buts,0,1,_("For glyph %.60s you refer to a glyph named %.80s, which is not in the font yet. Was this intentional?"),
+ psts[cols*r+0].u.md_str, start)==1 ) {
+ *pt = ch;
+return( true );
+ }
+ }
+ *pt = ch;
+ while ( *pt== ' ' ) ++pt;
+ start = pt;
+ }
+ }
+ }
+ /* Duplicate entries */
+ for ( r=0; r<rows; ++r ) {
+ for ( r1=r+1; r1<rows; ++r1 ) {
+ if ( strcmp(psts[r*cols+0].u.md_str,psts[r1*cols+0].u.md_str)==0 ) {
+ if ( lookup_type==gpos_pair || lookup_type==gsub_ligature ) {
+ if ( strcmp(psts[r*cols+1].u.md_str,psts[r1*cols+1].u.md_str)==0 ) {
+ gwwv_post_error( _("Duplicate data"),_("There are two entries for the same glyph set (%.80s and %.80s)"),
+ psts[cols*r+0].u.md_str, psts[cols*r+1].u.md_str );
+return( true );
+ }
+ } else {
+ gwwv_post_error( _("Duplicate data"),_("There are two entries for the same glyph (%.80s)"),
+ psts[cols*r+0].u.md_str );
+return( true );
+ }
+ }
+ }
+ }
+
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ /* Check for badly specified device tables */
+ if ( _t==pst_position || _t==pst_pair ) {
+ int startc = _t==pst_position ? SIM_DX+1 : PAIR_DX1+1;
+ int low, high, c;
+ for ( r=0; r<rows; ++r ) {
+ for ( c=startc; c<cols; c+=2 ) {
+ if ( !DeviceTableOK(psts[r*cols+c].u.md_str,&low,&high) ) {
+ gwwv_post_error( _("Bad Device Table Adjustment"),_("A device table adjustment specified for %.80s is invalid"),
+ psts[cols*r+0].u.md_str );
+return( true );
+ }
+ }
+ }
+ }
+#endif
+
+ /* Ok, if we get here then there should be no errors and we can parse */
+ /* First mark all the current things as unused */
+ k=0;
+ do {
+ sf = pstkd->sf->subfontcnt==0 ? pstkd->sf : pstkd->sf->subfonts[k];
+ for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( (sc = sf->glyphs[gid])!=NULL ) {
+ for ( pst = sc->possub; pst!=NULL; pst=pst->next )
+ pst->ticked = false;
+ for ( isv=0; isv<2; ++isv )
+ for ( kp = isv ? sc->vkerns : sc->kerns; kp!=NULL; kp=kp->next )
+ kp->kcid = 0;
+ }
+ ++k;
+ } while ( k<pstkd->sf->subfontcnt );
+
+ if ( lookup_type!=gpos_pair ) {
+ for ( r=0; r<rows; ++r ) {
+ sc = SFGetChar(pstkd->sf,-1,psts[cols*r+0].u.md_str);
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable == pstkd->sub && !pst->ticked )
+ break;
+ }
+ if ( pst==NULL ) {
+ pst = chunkalloc(sizeof(PST));
+ pst->type = _t;
+ pst->subtable = pstkd->sub;
+ pst->next = sc->possub;
+ sc->possub = pst;
+ } else if ( lookup_type!=gpos_single )
+ free( pst->u.subs.variant );
+ pst->ticked = true;
+ if ( lookup_type==gpos_single ) {
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ VRDevTabParse(&pst->u.pos,&psts[cols*r+SIM_DX+1]);
+#endif
+ pst->u.pos.xoff = psts[cols*r+SIM_DX].u.md_ival;
+ pst->u.pos.yoff = psts[cols*r+SIM_DY].u.md_ival;
+ pst->u.pos.h_adv_off = psts[cols*r+SIM_DX_ADV].u.md_ival;
+ pst->u.pos.v_adv_off = psts[cols*r+SIM_DY_ADV].u.md_ival;
+ } else {
+ pst->u.subs.variant = copy( psts[cols*r+1].u.md_str );
+ if ( lookup_type==gsub_ligature )
+ pst->u.lig.lig = sc;
+ }
+ }
+ } else if ( lookup_type==gpos_pair ) {
+ for ( r=0; r<rows; ++r ) {
+ sc = SFGetChar(pstkd->sf,-1,psts[cols*r+0].u.md_str);
+ KpMDParse(pstkd->sf,sc,pstkd->sub,psts,rows,cols,r);
+ }
+ }
+
+ /* Now free anything with this subtable which did not get ticked */
+ k=0;
+ do {
+ sf = pstkd->sf->subfontcnt==0 ? pstkd->sf : pstkd->sf->subfonts[k];
+ for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( (sc = sf->glyphs[gid])!=NULL ) {
+ for ( pstprev=NULL, pst = sc->possub; pst!=NULL; pst=pstnext ) {
+ pstnext = pst->next;
+ if ( pst->ticked || pst->subtable!=pstkd->sub )
+ pstprev = pst;
+ else {
+ if ( pstprev==NULL )
+ sc->possub = pstnext;
+ else
+ pstprev->next = pstnext;
+ pst->next = NULL;
+ PSTFree(pst);
+ }
+ }
+ for ( isv=0; isv<2; ++isv ) {
+ for ( kpprev=NULL, kp = isv ? sc->vkerns : sc->kerns; kp!=NULL; kp=kpnext ) {
+ kpnext = kp->next;
+ if ( kp->kcid!=0 || kp->subtable!=pstkd->sub )
+ kpprev = kp;
+ else {
+ if ( kpprev!=NULL )
+ kpprev->next = kpnext;
+ else if ( isv )
+ sc->vkerns = kpnext;
+ else
+ sc->kerns = kpnext;
+ kp->next = NULL;
+ KernPairsFree(kp);
+ }
+ }
+ }
+ }
+ ++k;
+ } while ( k<pstkd->sf->subfontcnt );
+ PSTKD_SetSuffix(pstkd);
+ pstkd->done = true;
+ }
+return( true );
+}
+
+static void PSTKD_DoCancel(PSTKernDlg *pstkd) {
+ pstkd->done = true;
+}
+
+static int PSTKD_Cancel(GGadget *g, GEvent *e) {
+ PSTKernDlg *pstkd;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ pstkd = GDrawGetUserData(GGadgetGetWindow(g));
+ PSTKD_DoCancel(pstkd);
+ }
+return( true );
+}
+
+static int pstkd_e_h(GWindow gw, GEvent *event) {
+ PSTKernDlg *pstkd = GDrawGetUserData(gw);
+
+ switch ( event->type ) {
+ case et_close:
+ PSTKD_DoCancel(pstkd);
+ break;
+ case et_char:
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ int lookup_type = pstkd->sub->lookup->lookup_type;
+ if ( lookup_type==gpos_single )
+ help("lookups.html#Single-pos");
+ else if ( lookup_type==gpos_pair )
+ help("lookups.html#Pair");
+ else
+ help("lookups.html#basic-subs");
+return( true );
+ }
+return( false );
+ break;
+ case et_destroy:
+ break;
+ case et_mouseup: case et_mousemove: case et_mousedown:
+ break;
+ case et_expose:
+ break;
+ case et_resize:
+ break;
+ }
+return( true );
+}
+
+
+static void PSTKernD(SplineFont *sf, struct lookup_subtable *sub) {
+ PSTKernDlg pstkd;
+ GRect pos;
+ GWindowAttrs wattrs;
+ char title[300];
+ struct matrixinit mi;
+ GGadgetCreateData gcd[15], buttongcd[3], box[5];
+ GGadgetCreateData *h1array[8], *h2array[7], *h3array[7], *varray[16];
+ GTextInfo label[15], buttonlabel[2];
+ int i,k,mi_pos, mi_k;
+
+ memset(&pstkd,0,sizeof(pstkd));
+ pstkd.sf = sf;
+ pstkd.sub = sub;
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = true;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ snprintf(title,sizeof(title), _("Lookup Subtable, %s"), sub->subtable_name );
+ wattrs.utf8_window_title = title;
+ wattrs.is_dlg = true;
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,300));
+ pos.height = GDrawPointsToPixels(NULL,400);
+ pstkd.gw = GDrawCreateTopWindow(NULL,&pos,pstkd_e_h,&pstkd,&wattrs);
+
+ memset(&gcd,0,sizeof(gcd));
+ memset(&buttongcd,0,sizeof(buttongcd));
+ memset(&box,0,sizeof(box));
+ memset(&label,0,sizeof(label));
+ memset(&buttonlabel,0,sizeof(buttonlabel));
+
+ i = k = 0;
+ label[i].text = (unichar_t *) _("_Alphabetic");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 5+4;
+ gcd[i].gd.flags = isalphabetic ? (gg_enabled|gg_visible|gg_cb_on|gg_utf8_popup) : (gg_enabled|gg_visible|gg_utf8_popup);
+ gcd[i].gd.popup_msg = (unichar_t *) _("Sort this display based on the alphabetic name of the glyph");
+ gcd[i].gd.handle_controlevent = PSTKD_Sort;
+ gcd[i].gd.cid = CID_Alpha;
+ gcd[i].creator = GRadioCreate;
+ h1array[0] = &gcd[i++];
+
+ label[i].text = (unichar_t *) _("_Unicode");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 5+4;
+ gcd[i].gd.flags = !isalphabetic ? (gg_enabled|gg_visible|gg_cb_on|gg_utf8_popup) : (gg_enabled|gg_visible|gg_utf8_popup);
+ gcd[i].gd.popup_msg = (unichar_t *) _("Sort this display based on the unicode code of the glyph");
+ gcd[i].gd.handle_controlevent = PSTKD_Sort;
+ gcd[i].gd.cid = CID_Unicode;
+ gcd[i].creator = GRadioCreate;
+ h1array[1] = &gcd[i++]; h1array[2] = GCD_HPad10;
+
+ label[i].text = (unichar_t *) _("_By Base Char");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 5+4;
+ gcd[i].gd.flags = stemming ? (gg_enabled|gg_visible|gg_cb_on|gg_utf8_popup) : (gg_enabled|gg_visible|gg_utf8_popup);
+ gcd[i].gd.popup_msg = (unichar_t *) _("Sort first using the base glyph (if any).\nThus Agrave would sort with A");
+ gcd[i].gd.handle_controlevent = PSTKD_Sort;
+ gcd[i].gd.cid = CID_BaseChar;
+ gcd[i].creator = GCheckBoxCreate;
+ h1array[3] = &gcd[i++]; h1array[4] = GCD_HPad10;
+
+ label[i].text = (unichar_t *) _("By _Scripts");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 5+4;
+ gcd[i].gd.flags = byscripts ? (gg_enabled|gg_visible|gg_cb_on|gg_utf8_popup) : (gg_enabled|gg_visible|gg_utf8_popup);
+ gcd[i].gd.popup_msg = (unichar_t *) _("Sort first using the glyph's script.\nThus A and Z would sort together\nwhile Alpha would sort with Omega and not A");
+ if ( sub->lookup->features==NULL ||
+ (sub->lookup->features->next==NULL &&
+ (sub->lookup->features->scripts==NULL ||
+ sub->lookup->features->scripts->next==NULL)))
+ gcd[i].gd.flags = gg_visible|gg_cb_on; /* If there is only one script, we can't really sort by it */
+ gcd[i].gd.handle_controlevent = PSTKD_Sort;
+ gcd[i].gd.cid = CID_Scripts;
+ gcd[i].creator = GCheckBoxCreate;
+ h1array[5] = &gcd[i++]; h1array[6] = GCD_Glue; h1array[7] = NULL;
+
+ box[0].gd.flags = gg_enabled|gg_visible;
+ box[0].gd.u.boxelements = h1array;
+ box[0].creator = GHBoxCreate;
+ varray[k++] = &box[0]; varray[k++] = NULL;
+
+ if ( sub->lookup->lookup_type == gpos_pair || sub->lookup->lookup_type == gpos_single ) {
+ label[i].text = (unichar_t *) _("_Hide Unused Columns");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 5+4;
+ gcd[i].gd.flags = lookup_hideunused ? (gg_enabled|gg_visible|gg_cb_on|gg_utf8_popup) : (gg_enabled|gg_visible|gg_utf8_popup);
+ gcd[i].gd.popup_msg = (unichar_t *) _("Don't display columns of 0s.\nThe OpenType lookup allows for up to 8 kinds\nof data, but almost all lookups will use just one or two.\nOmitting the others makes the behavior clearer.");
+ gcd[i].gd.handle_controlevent = PSTKD_HideUnused;
+ gcd[i].creator = GCheckBoxCreate;
+ varray[k++] = &gcd[i++]; varray[k++] = NULL;
+ }
+
+ PSTMatrixInit(&mi,sf,sub,&pstkd);
+ mi_pos = i;
+ gcd[i].gd.pos.height = 200;
+ gcd[i].gd.flags = gg_enabled | gg_visible | gg_utf8_popup;
+ gcd[i].gd.cid = CID_PSTList;
+ gcd[i].gd.u.matrix = &mi;
+ gcd[i].data = &pstkd;
+ gcd[i].creator = GMatrixEditCreate;
+ mi_k = k;
+ varray[k++] = &gcd[i++]; varray[k++] = NULL;
+
+ buttonlabel[0].text = (unichar_t *) _("_Populate");
+ buttonlabel[0].text_is_1byte = true;
+ buttonlabel[0].text_in_resource = true;
+ buttongcd[0].gd.label = &buttonlabel[0];
+ buttongcd[0].gd.pos.x = 5; buttongcd[0].gd.pos.y = 5+4;
+ buttongcd[0].gd.flags = sub->lookup->features==NULL ? gg_visible|gg_utf8_popup :
+ gg_enabled|gg_visible|gg_utf8_popup;
+ buttongcd[0].gd.popup_msg = (unichar_t *) _("Add entries for all glyphs in the scripts to which this lookup applies.\nWhen FontForge can find a default value it will add that too.");
+ buttongcd[0].gd.handle_controlevent = PSTKD_Populate;
+ buttongcd[0].creator = GButtonCreate;
+
+ buttonlabel[1].text = (unichar_t *) _("_Remove Empty");
+ buttonlabel[1].text_is_1byte = true;
+ buttonlabel[1].text_in_resource = true;
+ buttongcd[1].gd.label = &buttonlabel[1];
+ buttongcd[1].gd.pos.x = 5; buttongcd[1].gd.pos.y = 5+4;
+ buttongcd[1].gd.flags = sub->lookup->features==NULL ? gg_visible|gg_utf8_popup :
+ gg_enabled|gg_visible|gg_utf8_popup;
+ buttongcd[1].gd.popup_msg = (unichar_t *)
+ (sub->lookup->lookup_type == gpos_single ? _("Remove all \"empty\" entries -- those where all fields are 0") :
+ sub->lookup->lookup_type == gpos_pair ? _("Remove all \"empty\" entries -- entries with no second glyph") :
+ sub->lookup->lookup_type == gsub_ligature ? _("Remove all \"empty\" entries -- those with no source glyphs") :
+ _("Remove all \"empty\" entries -- those with no replacement glyphs"));
+ buttongcd[1].gd.handle_controlevent = PSTKD_RemoveEmpty;
+ buttongcd[1].creator = GButtonCreate;
+
+ if ( sub->lookup->lookup_type == gsub_single ) {
+ label[i].text = (unichar_t *) _("_Default Using Suffix:");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 5+4;
+ gcd[i].gd.flags = gg_enabled|gg_visible|gg_utf8_popup;
+ gcd[i].gd.popup_msg = (unichar_t *) _(
+ "Add entries to the lookup based on the following suffix.\n"
+ "So if the suffix is set to \"superior\" and the font\n"
+ "contains glyphs named \"A\" and \"A.superior\" (and the\n"
+ "lookup applies to the latin script), then FontForge will\n"
+ "add an entry mapping \"A\" -> \"A.superior\"." );
+ gcd[i].gd.handle_controlevent = PSTKD_PopulateWithSuffix;
+ gcd[i].creator = GButtonCreate;
+ h2array[0] = &gcd[i++];
+
+ label[i].text = (unichar_t *) sub->suffix;
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = sub->suffix==NULL ? NULL : &label[i];
+ gcd[i].gd.flags = gg_enabled|gg_visible|gg_utf8_popup;
+ gcd[i].gd.popup_msg = (unichar_t *) _(
+ "Add entries to the lookup based on this suffix.\n"
+ "So if this is set to \"superior\" and the font\n"
+ "contains glyphs named \"A\" and \"A.superior\" (and the\n"
+ "lookup applies to the latin script), then FontForge will\n"
+ "add an entry mapping \"A\" -> \"A.superior\"." );
+ gcd[i].gd.cid = CID_Suffix;
+ gcd[i].creator = GTextFieldCreate;
+ h2array[1] = &gcd[i++]; h2array[2] = GCD_Glue; h2array[3] = NULL;
+
+ box[1].gd.flags = gg_enabled|gg_visible;
+ box[1].gd.u.boxelements = h2array;
+ box[1].creator = GHBoxCreate;
+ varray[k++] = &box[1]; varray[k++] = NULL;
+ } else if ( sub->lookup->lookup_type == gpos_pair ) {
+ label[i].text = (unichar_t *) _("Size:");
+ label[i].text_is_1byte = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.pos.x = 30; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+30;
+ gcd[i].gd.flags = gg_visible|gg_enabled ;
+ gcd[i++].creator = GLabelCreate;
+ h2array[0] = &gcd[i-1];
+
+ pstkd.pixelsize = 150;
+ label[i].text = (unichar_t *) "150";
+ label[i].text_is_1byte = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.pos.x = 92; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y-4;
+ gcd[i].gd.pos.width = 80;
+ gcd[i].gd.flags = gg_visible|gg_enabled ;
+ gcd[i].gd.cid = CID_PixelSize;
+ gcd[i].gd.handle_controlevent = PSTKD_DisplaySizeChanged;
+ gcd[i++].creator = GTextFieldCreate;
+ h2array[1] = &gcd[i-1]; h2array[2] = GCD_HPad10;
+
+/* GT: Short for "Magnification" */
+ label[i].text = (unichar_t *) _("Mag:");
+ label[i].text_is_1byte = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.pos.x = 185; gcd[i].gd.pos.y = gcd[i-2].gd.pos.y;
+ gcd[i].gd.flags = gg_visible|gg_enabled ;
+ gcd[i++].creator = GLabelCreate;
+ h2array[3] = &gcd[i-1];
+
+ pstkd.mag = 1;
+ gcd[i].gd.flags = gg_visible|gg_enabled ;
+ gcd[i].gd.cid = CID_Magnification;
+ gcd[i].gd.u.list = magnifications;
+ gcd[i].gd.handle_controlevent = PSTKD_MagnificationChanged;
+ gcd[i++].creator = GListButtonCreate;
+ h2array[4] = &gcd[i-1]; h2array[5] = GCD_Glue; h2array[6] = NULL;
+
+ box[1].gd.flags = gg_enabled|gg_visible;
+ box[1].gd.u.boxelements = h2array;
+ box[1].creator = GHBoxCreate;
+ varray[k++] = &box[1]; varray[k++] = NULL;
+
+ gcd[i].gd.pos.width = 200;
+ gcd[i].gd.pos.height = 200;
+ gcd[i].gd.flags = gg_visible | gg_enabled;
+ gcd[i].gd.u.drawable_e_h = pstkern_e_h;
+ gcd[i].gd.cid = CID_KernDisplay;
+ gcd[i].creator = GDrawableCreate;
+ varray[k++] = &gcd[i++]; varray[k++] = NULL;
+ }
+
+ gcd[i].gd.pos.x = 10; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+24+3;
+ gcd[i].gd.pos.width = -1;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[i].text = (unichar_t *) _("_OK");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.handle_controlevent = PSTKD_Ok;
+ gcd[i++].creator = GButtonCreate;
+
+ gcd[i].gd.pos.x = -10; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+3;
+ gcd[i].gd.pos.width = -1;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[i].text = (unichar_t *) _("_Cancel");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.handle_controlevent = PSTKD_Cancel;
+ gcd[i].gd.cid = CID_Cancel;
+ gcd[i++].creator = GButtonCreate;
+
+ h3array[0] = GCD_Glue; h3array[1] = &gcd[i-2]; h3array[2] = GCD_Glue;
+ h3array[3] = GCD_Glue; h3array[4] = &gcd[i-1]; h3array[5] = GCD_Glue;
+ h3array[6] = NULL;
+
+ box[2].gd.flags = gg_enabled|gg_visible;
+ box[2].gd.u.boxelements = h3array;
+ box[2].creator = GHBoxCreate;
+ varray[k++] = &box[2]; varray[k++] = NULL; varray[k++] = NULL;
+
+ box[3].gd.pos.x = box[3].gd.pos.y = 2;
+ box[3].gd.flags = gg_enabled|gg_visible;
+ box[3].gd.u.boxelements = varray;
+ box[3].creator = GHVGroupCreate;
+
+ GGadgetsCreate(pstkd.gw,box+3);
+ GHVBoxSetExpandableRow(box[3].ret,mi_k/2);
+ GHVBoxSetExpandableCol(box[2].ret,gb_expandgluesame);
+ if ( sub->lookup->lookup_type == gsub_single || sub->lookup->lookup_type==gpos_pair )
+ GHVBoxSetExpandableCol(box[1].ret,gb_expandglue);
+ GHVBoxSetExpandableCol(box[0].ret,gb_expandglue);
+ GMatrixEditAddButtons(gcd[mi_pos].ret,buttongcd);
+ if ( sub->lookup->lookup_type == gpos_pair )
+ GMatrixEditSetTextChangeReporter(gcd[mi_pos].ret,PSTKD_METextChanged);
+ if ( sub->lookup->lookup_type == gpos_pair || sub->lookup->lookup_type == gpos_single )
+ PSTKD_DoHideUnused(&pstkd);
+ /* GHVBoxFitWindow(boxes[3].ret); */ /* Done in DoHide */
+
+ GDrawSetVisible(pstkd.gw,true);
+
+ while ( !pstkd.done )
+ GDrawProcessOneEvent(NULL);
+ GDrawDestroyWindow(pstkd.gw);
+ if ( pstkd.display!=NULL ) {
+ BDFFontFree(pstkd.display);
+ pstkd.display = NULL;
+ }
+}
+
+
+/* ************************************************************************** */
+/* *************************** Subtable Selection *************************** */
+/* ************************************************************************** */
+
+static int SubtableNameInUse(char *subname, SplineFont *sf, struct lookup_subtable *exclude) {
+ int isgpos, i, j;
+ OTLookup *otl;
+ struct lookup_subtable *sub;
+
+ if ( sf->fontinfo!=NULL ) {
+ for ( isgpos=0; isgpos<2; ++isgpos ) {
+ struct lkdata *lk = &sf->fontinfo->tables[isgpos];
+ for ( i=0; i<lk->cnt; ++i ) {
+ if ( lk->all[i].deleted )
+ continue;
+ for ( j=0; j<lk->all[i].subtable_cnt; ++j ) {
+ if ( lk->all[i].subtables[j].deleted || lk->all[i].subtables[j].subtable==exclude )
+ continue;
+ if ( strcmp(lk->all[i].subtables[j].subtable->subtable_name,subname)==0 )
+return( true );
+ }
+ }
+ }
+ } else {
+ for ( isgpos=0; isgpos<2; ++isgpos ) {
+ for ( otl = isgpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl=otl->next ) {
+ for ( sub=otl->subtables; sub!=NULL; sub=sub->next ) {
+ if ( sub==exclude )
+ continue;
+ if ( strcmp(sub->subtable_name,subname)==0 )
+return( true );
+ }
+ }
+ }
+ }
+return( false );
+}
+
+int EditSubtable(struct lookup_subtable *sub,int isgpos,SplineFont *sf,
+ struct subtable_data *sd) {
+ char *def = sub->subtable_name;
+ int new = def==NULL;
+ char *freeme = NULL;
+ int name_search;
+
+ if ( new ) {
+ def = freeme = galloc(strlen(sub->lookup->lookup_name)+10);
+ name_search = 1;
+ do {
+ sprintf( def, "%s-%d", sub->lookup->lookup_name, name_search++ );
+ } while ( SubtableNameInUse(def,sf,sub));
+ }
+ forever {
+ def = gwwv_ask_string(_("Please name this subtable"),def,_("Please name this subtable"));
+ free(freeme);
+ if ( def==NULL )
+return( false );
+ freeme = def;
+ if ( SubtableNameInUse(def,sf,sub) )
+ gwwv_post_notice(_("Duplicate name"),_("There is already a subtable with that name, please pick another."));
+ else
+ break;
+ }
+ free(sub->subtable_name);
+ sub->subtable_name = def;
+ if ( new && sub->lookup->lookup_type == gsub_single )
+ sub->suffix = SuffixFromTags(sub->lookup->features);
+ if ( new && (sd==NULL || !(sd->flags&sdf_dontedit)) )
+ _LookupSubtableContents(sf, sub, sd);
+return( true );
+}
+
+static struct lookup_subtable *NewSubtable(OTLookup *otl,int isgpos,SplineFont *sf, struct subtable_data *sd) {
+ struct lookup_subtable *sub, *last;
+ int i,j;
+
+ sub = chunkalloc(sizeof(struct lookup_subtable));
+ sub->lookup = otl;
+ if ( !EditSubtable(sub,isgpos,sf,sd)) {
+ chunkfree(sub,sizeof(struct lookup_subtable));
+return( NULL );
+ }
+ if ( otl->subtables==NULL )
+ otl->subtables = sub;
+ else {
+ for ( last=otl->subtables; last->next!=NULL; last=last->next );
+ last->next = sub;
+ }
+ if ( sf->fontinfo!=NULL ) {
+ struct lkdata *lk = &sf->fontinfo->tables[isgpos];
+ for ( i=0; i<lk->cnt && lk->all[i].lookup!=otl; ++i );
+ if ( i==lk->cnt ) {
+ IError( "Lookup missing from FontInfo lookup list");
+ } else {
+ if ( lk->all[i].subtable_cnt>=lk->all[i].subtable_max )
+ lk->all[i].subtables = grealloc(lk->all[i].subtables,(lk->all[i].subtable_max+=10)*sizeof(struct lksubinfo));
+ j = lk->all[i].subtable_cnt++;
+ memset(&lk->all[i].subtables[j],0,sizeof(struct lksubinfo));
+ lk->all[i].subtables[j].subtable = sub;
+ GFI_LookupScrollbars(sf->fontinfo,isgpos, true);
+ GFI_LookupEnableButtons(sf->fontinfo,isgpos);
+ }
+ }
+return( sub );
+}
+
+GTextInfo **SFSubtablesOfType(SplineFont *sf, int lookup_type, int kernclass) {
+ int isgpos = (lookup_type>=gpos_start);
+ int k, cnt, lcnt, pos;
+ OTLookup *otl;
+ struct lookup_subtable *sub;
+ GTextInfo **ti;
+
+ if ( sf->cidmaster != NULL ) sf=sf->cidmaster;
+ else if ( sf->mm != NULL ) sf = sf->mm->normal;
+
+ for ( k=0; k<2; ++k ) {
+ cnt = lcnt = pos = 0;
+ for ( otl = isgpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl=otl->next ) {
+ if ( otl->lookup_type==lookup_type && otl->subtables!=NULL ) {
+ if ( k ) {
+ ti[pos] = gcalloc(1,sizeof(GTextInfo));
+ ti[pos]->text = galloc((utf82u_strlen(otl->lookup_name)+2)*sizeof(unichar_t));
+ ti[pos]->text[0] = ' ';
+ utf82u_strcpy(ti[pos]->text+1,otl->lookup_name);
+ ti[pos]->fg = ti[pos]->bg = COLOR_DEFAULT;
+ ti[pos++]->disabled = true;
+ }
+ ++lcnt;
+ for ( sub=otl->subtables; sub!=NULL; sub=sub->next ) {
+ if ( lookup_type!=gpos_pair || kernclass==-1 ||
+ (kernclass && sub->kc!=NULL) ||
+ (!kernclass && sub->per_glyph_pst_or_kern)) {
+ if ( k ) {
+ ti[pos] = gcalloc(1,sizeof(GTextInfo));
+ ti[pos]->text = utf82u_copy(sub->subtable_name);
+ ti[pos]->fg = ti[pos]->bg = COLOR_DEFAULT;
+ ti[pos++]->userdata = sub;
+ }
+ ++cnt;
+ }
+ }
+ }
+ }
+ if ( !k ) {
+ ti = gcalloc(cnt+lcnt+3,sizeof(GTextInfo*));
+ } else {
+ ti[pos] = gcalloc(1,sizeof(GTextInfo));
+ ti[pos]->fg = ti[pos]->bg = COLOR_DEFAULT;
+ ti[pos++]->line = true;
+ ti[pos] = gcalloc(1,sizeof(GTextInfo));
+ ti[pos]->fg = ti[pos]->bg = COLOR_DEFAULT;
+ ti[pos++]->text = utf82u_copy(_("New Lookup Subtable..."));
+ ti[pos] = gcalloc(1,sizeof(GTextInfo));
+return( ti );
+ }
+ }
+ /* We'll never get here */
+return( NULL );
+}
+
+GTextInfo *SFSubtableListOfType(SplineFont *sf, int lookup_type, int kernclass) {
+ GTextInfo **temp, *ti;
+ int cnt;
+
+ temp = SFSubtablesOfType(sf,lookup_type,kernclass);
+ if ( temp==NULL )
+return( NULL );
+ for ( cnt=0; temp[cnt]->text!=NULL || temp[cnt]->line; ++cnt );
+ ti = gcalloc(cnt+1,sizeof(GTextInfo));
+ for ( cnt=0; temp[cnt]->text!=NULL || temp[cnt]->line; ++cnt ) {
+ ti[cnt] = *temp[cnt];
+ free(temp[cnt]);
+ }
+ free(temp);
+return( ti );
+}
+
+struct lookup_subtable *SFNewLookupSubtableOfType(SplineFont *sf, int lookup_type, struct subtable_data *sd ) {
+ int isgpos = (lookup_type>=gpos_start);
+ OTLookup *otl, *found=NULL;
+ int cnt, ans;
+ struct lookup_subtable *sub;
+ char **choices;
+
+ if ( sf->cidmaster ) sf=sf->cidmaster;
+
+ cnt = 0;
+ for ( otl=isgpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl=otl->next )
+ if ( otl->lookup_type==lookup_type )
+ ++cnt;
+ if ( cnt==0 ) {
+ /* There are no lookups of this type, so there is nothing for them to */
+ /* pick from. So we must create a new lookup for them, and then add */
+ /* a subtable to it */
+ found = CreateAndSortNewLookupOfType(sf,lookup_type);
+ if ( found==NULL )
+return( NULL );
+ sub = NewSubtable(found,isgpos,sf,sd);
+ /* even if they canceled the subtable creation they are now stuck */
+ /* with the lookup */
+return( sub );
+ }
+
+ /* I thought briefly that if cnt were 1 I might want to automagically */
+ /* create a subtable in that lookup... but no. Still give them the */
+ /* option of creating a new lookup */
+
+ choices = galloc((cnt+2)*sizeof(char *));
+ for ( cnt=0, otl=isgpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl=otl->next )
+ if ( otl->lookup_type==lookup_type )
+ choices[cnt++] = otl->lookup_name;
+ choices[cnt++] = _("Create a new lookup");
+ choices[cnt] = NULL;
+ ans = gwwv_choose(_("Add a subtable to which lookup?"),(const char **) choices,cnt,cnt-1,
+ _("Add a subtable to which lookup?"));
+ if ( ans==-1 )
+ found = NULL;
+ else if ( ans==cnt )
+ found = CreateAndSortNewLookupOfType(sf,lookup_type);
+ else {
+ found = NULL;
+ for ( cnt=0, otl=isgpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl=otl->next ) {
+ if ( otl->lookup_type==lookup_type ) {
+ if ( cnt==ans ) {
+ found = otl;
+ break;
+ } else
+ ++cnt;
+ }
+ }
+ }
+ free(choices);
+ if ( found==NULL )
+return( NULL );
+
+return( NewSubtable(found,isgpos,sf,sd));
+}
+#endif
+
+int VerticalKernFeature(SplineFont *sf, OTLookup *otl, int ask) {
+ FeatureScriptLangList *fl;
+ struct lookup_subtable *sub;
+ KernClass *kc;
+#ifndef LUA_FF_LIB
+ char *buts[3];
+#endif
+
+ for ( fl=otl->features; fl!=NULL; fl=fl->next ) {
+ if ( fl->featuretag==CHR('k','e','r','n') )
+return( false );
+ else if ( fl->featuretag==CHR('v','k','r','n') )
+return( true );
+ }
+
+ for ( sub=otl->subtables; sub!=NULL; sub=sub->next ) {
+ if ( sub->kc!=NULL ) {
+ for ( kc=sf->kerns; kc!=NULL; kc=kc->next )
+ if ( kc==sub->kc )
+return( false );
+ for ( kc=sf->vkerns; kc!=NULL; kc=kc->next )
+ if ( kc==sub->kc )
+return( true );
+ }
+ }
+
+ if ( !ask )
+return( -1 );
+
+#ifndef LUA_FF_LIB
+ buts[0] = _("_Horizontal"); buts[1] = _("_Vertical"); buts[2] = NULL;
+return( gwwv_ask(_("Kerning direction"),(const char **) buts,0,1,_("Is this horizontal or vertical kerning data?")) );
+#else
+return( -1 );
+#endif
+}
+
+#ifndef LUA_FF_LIB
+void _LookupSubtableContents(SplineFont *sf, struct lookup_subtable *sub,
+ struct subtable_data *sd) {
+ int lookup_type = sub->lookup->lookup_type;
+
+ if ( (lookup_type == gsub_context || lookup_type == gsub_contextchain ||
+ lookup_type == gsub_reversecchain ||
+ lookup_type == gpos_context || lookup_type == gpos_contextchain) &&
+ sub->fpst==NULL ) {
+ sub->fpst = chunkalloc(sizeof(FPST));
+ sub->fpst->type = lookup_type == gsub_context ? pst_contextsub :
+ lookup_type == gsub_contextchain ? pst_chainsub :
+ lookup_type == gsub_reversecchain ? pst_reversesub :
+ lookup_type == gpos_context ? pst_contextpos :
+ pst_chainpos;
+ sub->fpst->subtable = sub;
+ sub->fpst->next = sf->possub;
+ sf->possub = sub->fpst;
+ } else if ( (lookup_type == morx_indic ||
+ lookup_type == morx_context ||
+ lookup_type == morx_insert ||
+ lookup_type == kern_statemachine) &&
+ sub->sm==NULL ) {
+ sub->sm = chunkalloc(sizeof(ASM));
+ sub->sm->type = lookup_type == morx_indic ? asm_indic :
+ lookup_type == morx_context ? asm_context :
+ lookup_type == morx_insert ? asm_insert :
+ asm_kern;
+ sub->sm->subtable = sub;
+ sub->sm->next = sf->sm;
+ sf->sm = sub->sm;
+ } else if ( lookup_type==gpos_pair &&
+ sub->kc==NULL &&
+ !sub->per_glyph_pst_or_kern ) {
+ char *buts[4];
+ int asked;
+
+ if ( sd!=NULL && sd->flags&sdf_verticalkern )
+ sub->vertical_kerning = true;
+ else if ( sd!=NULL && sd->flags&sdf_horizontalkern )
+ sub->vertical_kerning = false;
+ else
+ sub->vertical_kerning = VerticalKernFeature(sf,sub->lookup,true);
+
+ if ( sd!=NULL && sd->flags&sdf_kernclass )
+ asked = 1;
+ else if ( sd!=NULL && sd->flags&sdf_kernclass )
+ asked = 0;
+ else {
+ buts[0] = _("_Pairs"); buts[1] = _("C_lasses"); buts[2] = _("_Cancel"); buts[3]=NULL;
+ asked = gwwv_ask(_("Kerning format"),(const char **) buts,0,1,_("Kerning may be specified either by classes of glyphs\nor by pairwise combinatins of individual glyphs.\nWhich do you want for this subtable?") );
+ if ( asked==2 )
+return;
+ }
+ if ( asked==0 )
+ sub->per_glyph_pst_or_kern = true;
+ else {
+ sub->kc = chunkalloc(sizeof(KernClass));
+ if ( sub->vertical_kerning ) {
+ sub->kc->next = sf->vkerns;
+ sf->vkerns = sub->kc;
+ } else {
+ sub->kc->next = sf->kerns;
+ sf->kerns = sub->kc;
+ }
+ sub->kc->subtable = sub;
+ sub->kc->first_cnt = sub->kc->second_cnt = 1;
+ sub->kc->offsets = gcalloc(1,sizeof(int16));
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ sub->kc->adjusts = gcalloc(1,sizeof(DeviceTable));
+#endif
+ }
+ }
+
+ if ( sub->fpst && sf->fontinfo!=NULL ) {
+ if ( sf->fontinfo->ccd )
+return;
+ sf->fontinfo->ccd = ContextChainEdit(sf,sub->fpst,sf->fontinfo,NULL);
+ } else if ( sub->sm && sf->fontinfo!=NULL ) {
+ if ( sf->fontinfo->smd!=NULL )
+return;
+ sf->fontinfo->smd = StateMachineEdit(sf,sub->sm,sf->fontinfo);
+ } else if ( sub->kc!=NULL ) {
+ KernClassD(sub->kc,sf,sub->vertical_kerning);
+ } else if ( sub->lookup->lookup_type>=gpos_cursive &&
+ sub->lookup->lookup_type<=gpos_mark2mark )
+ AnchorClassD(sf,sub);
+ else
+ PSTKernD(sf,sub);
+}
+#endif
+
+struct lookup_subtable *SFSubTableMake(SplineFont *sf,uint32 tag,uint32 script,
+ int lookup_type ) {
+ OTLookup **base;
+ OTLookup *otl, *found=NULL;
+ int isgpos = lookup_type>=gpos_start;
+ struct lookup_subtable *sub;
+ int isnew = false;
+
+ if ( sf->cidmaster ) sf = sf->cidmaster;
+ base = isgpos ? &sf->gpos_lookups : &sf->gsub_lookups;
+ for ( otl= *base; otl!=NULL; otl=otl->next ) {
+ if ( otl->lookup_type==lookup_type &&
+ FeatureScriptTagInFeatureScriptList(tag,script,otl->features) ) {
+ found = otl;
+ }
+ }
+
+ if ( found==NULL ) {
+ found = chunkalloc(sizeof(OTLookup));
+ found->lookup_type = lookup_type;
+ found->features = chunkalloc(sizeof(FeatureScriptLangList));
+ found->features->featuretag = tag;
+ found->features->scripts = chunkalloc(sizeof(struct scriptlanglist));
+ found->features->scripts->script = script;
+ found->features->scripts->langs[0] = DEFAULT_LANG;
+ found->features->scripts->lang_cnt = 1;
+
+ SortInsertLookup(sf, found);
+ isnew = true;
+ }
+
+ sub = chunkalloc(sizeof(struct lookup_subtable));
+ sub->next = found->subtables;
+ found->subtables = sub;
+ sub->lookup = found;
+
+ if ( isnew )
+ NameOTLookup(found,sf);
+return( sub );
+}
+
+struct lookup_subtable *SFSubTableFindOrMake(SplineFont *sf,uint32 tag,uint32 script,
+ int lookup_type ) {
+ OTLookup **base;
+ OTLookup *otl, *found=NULL;
+ int isgpos = lookup_type>=gpos_start;
+ struct lookup_subtable *sub;
+ int isnew = false;
+
+ if ( sf->cidmaster ) sf = sf->cidmaster;
+ base = isgpos ? &sf->gpos_lookups : &sf->gsub_lookups;
+ for ( otl= *base; otl!=NULL; otl=otl->next ) {
+ if ( otl->lookup_type==lookup_type &&
+ FeatureScriptTagInFeatureScriptList(tag,script,otl->features) ) {
+ for ( sub = otl->subtables; sub!=NULL; sub=sub->next )
+ if ( sub->kc==NULL )
+return( sub );
+ found = otl;
+ }
+ }
+
+ if ( found==NULL ) {
+ found = chunkalloc(sizeof(OTLookup));
+ found->lookup_type = lookup_type;
+ found->features = chunkalloc(sizeof(FeatureScriptLangList));
+ found->features->featuretag = tag;
+ found->features->scripts = chunkalloc(sizeof(struct scriptlanglist));
+ found->features->scripts->script = script;
+ found->features->scripts->langs[0] = DEFAULT_LANG;
+ found->features->scripts->lang_cnt = 1;
+
+ SortInsertLookup(sf, found);
+ isnew = true;
+ }
+
+ sub = chunkalloc(sizeof(struct lookup_subtable));
+ sub->next = found->subtables;
+ found->subtables = sub;
+ sub->lookup = found;
+ sub->per_glyph_pst_or_kern = true;
+
+ if ( isnew )
+ NameOTLookup(found,sf);
+return( sub );
+}
+
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/macbinary.c b/Build/source/libs/luafontforge/fontforge/fontforge/macbinary.c
new file mode 100644
index 00000000000..f70103edf9d
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/macbinary.c
@@ -0,0 +1,3212 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaeditui.h"
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <ustring.h>
+#include "ttf.h"
+#include "psfont.h"
+#if __Mac
+# include <ctype.h>
+# include </Developer/Headers/FlatCarbon/Files.h>
+#else
+# include <utype.h>
+#undef __Mac
+#define __Mac 0
+#endif
+
+
+#ifdef LUA_FF_LIB
+/* no need for iconv here, since PS is 8-bit legacy */
+#define Isspace(a) ((a)==' '|| ((a) >= '\t' && (a) <= '\r'))
+#define Isdigit(a) ((a)>='0' && (a)<='9')
+#define Isalpha(a) (((a)>='a' && (a)<='z') || ((a)>='A' && (a)<='Z'))
+#define Islower(a) ((a)>='a' && (a)<='z')
+#define Isupper(a) ((a)>='A' && (a)<='Z')
+#define Isalnum(a) (Isalpha(a)||Isdigit(a))
+#define Ishexdigit(a) (((a)>='0' && (a)<='9')||((a)>='a' && (a)<='f')||((a)>='A' && (a)<='F'))
+static int Tolower (int c) {
+ if (Isupper(c))
+ return c-32;
+ else
+ return c;
+}
+#else
+#define Islower islower
+#define Tolower tolower
+#define Isspace isspace
+#define Isdigit isdigit
+#define Isalpha isalpha
+#define Isalnum isalnum
+#define Ishexdigit ishexdigit
+#endif
+
+
+
+
+const int mac_dpi = 72;
+/* I had always assumed that the mac still believed in 72dpi screens, but I */
+/* see that in geneva under OS/9, the pointsize does not match the pixel */
+/* size of the font. But the dpi is not constant (and the differences */
+/* excede those supplied by rounding errors) varying between 96 and 84dpi */
+
+/* A Mac Resource fork */
+/* http://developer.apple.com/techpubs/mac/MoreToolbox/MoreToolbox-9.html */
+/* begins with a 16 byte header containing: */
+/* resource start offset */
+/* map start offset */
+/* resource length */
+/* map length */
+/* then 256-16 bytes of zeros */
+/* the resource section consists of (many) */
+/* 4 byte length count */
+/* resource data */
+/* the map section contains */
+/* A copy of the 16 byte header */
+/* a 4 byte mac internal value (I hope) */
+/* another 4 bytes of mac internal values (I hope) */
+/* a 2 byte offset from the start of the map section to the list of resource types */
+/* a 2 byte offset from the start of the map section to the list of resource names */
+/* The resource type list consists of */
+/* a 2 byte count of the number of resource types (-1) */
+/* (many copies of) */
+/* a 4 byte resource type ('FOND' for example) */
+/* a 2 byte count of the number of resources of this type (-1) */
+/* a 2 byte offset from the type list start to the resource table */
+/* a resource table looks like */
+/* a 2 byte offset from the resource name table to a pascal */
+/* string containing this resource's name (or 0xffff for none) */
+/* 1 byte of resource flags */
+/* 3 bytes of offset from the resource section to the length & */
+/* data of this instance of the resource type */
+/* 4 bytes of 0 */
+/* The resource name section consists of */
+/* a bunch of pascal strings (ie. preceded by a length byte) */
+
+/* The POST resource isn't noticeably documented, it's pretty much a */
+/* straight copy of the pfb file cut up into 0x800 byte chunks. */
+/* (each section of the pfb file has it's own set of chunks, the last may be smaller than 0x800) */
+/* The NFNT resource http://developer.apple.com/techpubs/mac/Text/Text-250.html */
+/* The FOND resource http://developer.apple.com/techpubs/mac/Text/Text-269.html */
+/* The sfnt resource is basically a copy of the ttf file */
+
+/* A MacBinary file */
+/* http://www.lazerware.com/formats/macbinary.html */
+/* begins with a 128 byte header */
+/* (which specifies lengths for data/resource forks) */
+/* (and contains mac type/creator data) */
+/* (and other stuff) */
+/* (and finally a crc checksum) */
+/* is followed by the data section (padded to a mult of 128 bytes) */
+/* is followed by the resource section (padded to a mult of 128 bytes) */
+
+/* Crc code taken from: */
+/* http://www.ctan.org/tex-archive/tools/macutils/crc/ */
+/* MacBinary files use the same CRC that binhex does (in the MacBinary header) */
+extern unsigned long binhex_crc(unsigned char *buffer,int size);
+
+/* ******************************** Creation ******************************** */
+
+#ifndef LUA_FF_LIB
+static uint16 HashToId(char *fontname,SplineFont *sf,EncMap *map) {
+ int low = 128, high = 0x3fff;
+ /* A FOND ID should be between these two numbers for roman script (I think) */
+ uint32 hash = 0;
+ int i, gid;
+ SplineChar *sc;
+
+ /* Figure out what language we've got */
+ /* I'm not bothering with all of the apple scripts, and I don't know */
+ /* what to do about cjk fonts */
+ if ( sf->cidmaster!=NULL || sf->subfontcnt!=0 ) {
+ if ( sf->cidmaster != NULL ) sf = sf->cidmaster;
+ if ( sf->ordering != NULL ) {
+ if ( strstrmatch(sf->ordering,"Japan")!=NULL ) {
+ low = 0x4000; high = 0x41ff;
+ } else if ( strstrmatch(sf->ordering,"Korea")!=NULL ) {
+ low = 0x4400; high = 0x45ff;
+ } else if ( strstrmatch(sf->ordering,"CNS")!=NULL ) {
+ low = 0x4200; high = 0x43ff;
+ } else if ( strstrmatch(sf->ordering,"GB")!=NULL ) {
+ low = 0x7200; high = 0x73ff;
+ }
+ }
+ } else if ( map->enc->is_tradchinese ) {
+ low = 0x4200; high = 0x43ff;
+ } else if ( map->enc->is_japanese ) {
+ low = 0x4000; high = 0x41ff;
+ } else if ( map->enc->is_korean ) {
+ low = 0x4400; high = 0x45ff;
+ } else if ( map->enc->is_simplechinese ) {
+ low = 0x7200; high = 0x73ff;
+ } else for ( i=0; i<map->enccount && i<256; ++i ) if ( (gid=map->map[i])!=-1 && (sc = sf->glyphs[gid])!=NULL ) {
+ /* Japanese between 0x4000 and 0x41ff */
+ /* Trad Chinese 0x4200 and 0x43ff */
+ /* Simp Chinese 0x7200 and 0x73ff */
+ /* Korean 0x4400 and 0x45ff */
+ if (( sc->unicodeenc>=0x0600 && sc->unicodeenc<0x0700 ) ||
+ ( sc->unicodeenc>=0xFB50 && sc->unicodeenc<0xfe00 )) {
+ /* arabic */
+ low = 0x4600; high = 0x47ff;
+ break;
+ } else if (( sc->unicodeenc>=0x0590 && sc->unicodeenc<0x0600 ) ||
+ ( sc->unicodeenc>=0xFB1d && sc->unicodeenc<0xFB50 )) {
+ /* hebrew */
+ low = 0x4800; high = 0x49ff;
+ break;
+ } else if ((( sc->unicodeenc>=0x0370 && sc->unicodeenc<0x0400 ) ||
+ ( sc->unicodeenc>=0x1f00 && sc->unicodeenc<0x2000 )) &&
+ sc->unicodeenc!=0x3c0 ) { /* In mac encoding */
+ /* greek */
+ low = 0x4a00; high = 0x4bff;
+ break;
+ } else if ( sc->unicodeenc>=0x0400 && sc->unicodeenc<0x0530 ) {
+ /* cyrillic */
+ low = 0x4c00; high = 0x4dff;
+ break;
+ /* hebrew/arabic symbols 4e00-4fff */
+ } else if ( sc->unicodeenc>=0x0900 && sc->unicodeenc<0x0980 ) {
+ /* devanagari */
+ low = 0x5000; high = 0x51ff;
+ break;
+ } else if ( sc->unicodeenc>=0x0980 && sc->unicodeenc<0x0a00 ) {
+ /* bengali: script=13 */
+ low = 0x5800; high = 0x59ff;
+ break;
+ }
+ }
+ while ( *fontname ) {
+ int temp = (hash>>28)&0xf;
+ hash = (hash<<4) | temp;
+ hash ^= *fontname++-' ';
+ }
+ hash %= (high-low+1);
+ hash += low;
+return( hash );
+}
+
+static int IsMacMonospaced(SplineFont *sf,EncMap *map) {
+ /* Only look at first 256 */
+ int i;
+ double width = 0x80000000;
+
+ for ( i=0; i<256 && i<map->enccount; ++i ) {
+ int gid = map->map[i];
+ if ( gid!=-1 && SCWorthOutputting(sf->glyphs[gid]) ) {
+ if ( width == 0x80000000 )
+ width = sf->glyphs[gid]->width;
+ else if ( sf->glyphs[gid]->width!=width )
+return( false );
+ }
+ }
+return( true );
+}
+
+SplineChar *SFFindExistingCharMac(SplineFont *sf,EncMap *map,int unienc) {
+ int i, gid;
+
+ for ( i=0; i<map->enccount && i<256; ++i )
+ if ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL && sf->glyphs[gid]->unicodeenc==unienc )
+return( sf->glyphs[gid] );
+return( NULL );
+}
+
+static double SFMacWidthMax(SplineFont *sf, EncMap *map) {
+ /* Only look at first 256 */
+ int i, gid;
+ double width = -1;
+
+ for ( i=0; i<256 && i<map->enccount; ++i ) {
+ if ( (gid=map->map[i])!=-1 && SCWorthOutputting(sf->glyphs[gid]) ) {
+ if ( sf->glyphs[gid]->width>width )
+ width = sf->glyphs[gid]->width;
+ }
+ }
+ if ( width<0 ) /* No chars, or widths the mac doesn't support */
+return( 0 );
+
+return( width );
+}
+
+static int SFMacAnyKerns(SplineFont *sf, EncMap *map) {
+ /* Only look at first 256 */
+ int i, cnt=0, gid;
+ KernPair *kp;
+
+ for ( i=0; i<256 && i<map->enccount; ++i ) {
+ if ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL ) {
+ for ( kp=sf->glyphs[gid]->kerns; kp!=NULL; kp=kp->next )
+ if ( map->backmap[kp->sc->orig_pos]<256 )
+ ++cnt;
+ }
+ }
+return( cnt );
+}
+
+struct resource {
+ uint32 pos;
+ uint8 flags;
+ uint16 id;
+ char *name;
+ uint32 nameloc;
+ uint32 nameptloc;
+};
+
+struct resourcetype {
+ uint32 tag;
+ struct resource *res;
+ uint32 resloc;
+};
+
+struct macbinaryheader {
+ char *macfilename;
+ char *binfilename; /* if macfilename is null and this is set we will figure out macfilename by removing .bin */
+ uint32 type;
+ uint32 creator;
+};
+
+static struct resource *PSToResources(FILE *res,FILE *pfbfile) {
+ /* split the font up into as many small resources as we need and return */
+ /* an array pointing to the start of each */
+ struct stat statb;
+ int cnt, type;
+ struct resource *resstarts;
+ int len,i;
+
+ fstat(fileno(pfbfile),&statb);
+ cnt = 3*(statb.st_size+0x800)/(0x800-2)+1; /* should be (usually) a vast over estimate */
+ resstarts = gcalloc(cnt+1,sizeof(struct resource));
+
+ cnt = 0;
+ forever {
+ if ( getc(pfbfile)!=0x80 ) {
+ IError("We made a pfb file, but didn't get one. Hunh?" );
+return( NULL );
+ }
+ type = getc(pfbfile);
+ if ( type==3 ) {
+ /* 501 appears to be magic */
+ /* postscript resources seem to have flags of 0 */
+ resstarts[cnt].id = 501+cnt;
+ resstarts[cnt++].pos = ftell(res);
+ putlong(res,2); /* length */
+ putc(5,res); /* eof mark */
+ putc(0,res);
+ break;
+ }
+ len = getc(pfbfile);
+ len |= (getc(pfbfile))<<8;
+ len |= (getc(pfbfile))<<16;
+ len |= (getc(pfbfile))<<24;
+ while ( len>0 ) {
+ int ilen = len;
+ if ( ilen>0x800-2 )
+ ilen = 0x800-2;
+ len -= ilen;
+ resstarts[cnt].id = 501+cnt;
+ resstarts[cnt++].pos = ftell(res);
+ putlong(res,ilen+2); /* length */
+ putc(type,res); /* section type mark */
+ putc(0,res);
+ for ( i=0; i<ilen; ++i )
+ putc(getc(pfbfile),res);
+ }
+ }
+ resstarts[cnt].pos = 0;
+return( resstarts );
+}
+
+static uint32 TTFToResource(FILE *res,FILE *ttffile) {
+ /* A truetype font just gets dropped into a resource */
+ struct stat statb;
+ int ch;
+ uint32 resstart;
+
+ fstat(fileno(ttffile),&statb);
+ resstart = ftell(res);
+
+ putlong(res,statb.st_size);
+ while ( (ch=getc(ttffile))!=EOF )
+ putc(ch,res);
+return( resstart );
+}
+
+static int BDFCCopyBitmaps(uint8 **rows,int offset,BDFChar *bdfc, BDFFont *bdf) {
+ int i, r, y, ipos, j, c;
+
+ y = bdf->ascent-1; r = i = 0;
+ if ( bdfc->ymax > bdf->ascent-1 )
+ i = bdfc->ymax-(bdf->ascent-1);
+ else if ( bdfc->ymax<bdf->ascent-1 ) {
+ r = bdf->ascent-1-bdfc->ymax;
+ y = bdfc->ymax;
+ }
+ for ( ; y>=bdfc->ymin && y>=-bdf->descent; --y, ++i ) {
+ /* Mac characters may not extend above the ascent or below the descent */
+ /* but bdf chars can, so if a bdf char does, just ignore that part */
+ ipos = i*bdfc->bytes_per_line;
+ for ( j=0,c=offset; j<=bdfc->xmax-bdfc->xmin; ++j, ++c ) {
+ if ( bdfc->bitmap[ipos+(j>>3)] & (1<<(7-(j&7))) )
+ rows[r][c>>3] |= (1<<(7-(c&7)));
+ }
+ ++r;
+ }
+return( offset + bdfc->xmax-bdfc->xmin+1 );
+}
+
+static uint32 BDFToNFNT(FILE *res, BDFFont *bdf, EncMap *map) {
+ short widths[258], lbearings[258], locs[258]/*, idealwidths[256]*/;
+ uint8 **rows = galloc(bdf->pixelsize*sizeof(uint8 *));
+ int i, k, width, kernMax=1, descentMax=bdf->descent-1, rectMax=1, widMax=3;
+ uint32 rlenpos = ftell(res), end, owloc, owpos;
+ int gid;
+
+ for ( i=width=0; i<256 && i<map->enccount; ++i ) {
+ if ( (gid = map->map[i])!=-1 && gid<bdf->glyphcnt && bdf->glyphs[gid]!=NULL ) {
+ width += bdf->glyphs[gid]->xmax+1-bdf->glyphs[gid]->xmin;
+ if ( bdf->glyphs[gid]->width>widMax )
+ widMax = bdf->glyphs[gid]->width;
+ if ( bdf->glyphs[gid]->xmax+1-bdf->glyphs[gid]->xmin>rectMax )
+ rectMax = bdf->glyphs[gid]->xmax+1-bdf->glyphs[gid]->xmin;
+ if ( bdf->glyphs[gid]->xmin<kernMax )
+ kernMax = bdf->glyphs[gid]->xmin;
+ if ( bdf->glyphs[gid]->ymin<-descentMax )
+ descentMax = -bdf->glyphs[gid]->ymin;
+ }
+ }
+ if ( descentMax>bdf->descent ) descentMax = bdf->descent;
+ ++width; /* For the "undefined character */
+ for ( k=0; k<bdf->pixelsize; ++k )
+ rows[k] = gcalloc((width+7)/8 + 4 , sizeof(uint8));
+ for ( i=width=0; i<256 ; ++i ) {
+ locs[i] = width;
+ if ( i>=map->enccount || (gid=map->map[i])==-1 || gid>=bdf->glyphcnt || bdf->glyphs[gid]==NULL ||
+ !SCWorthOutputting(bdf->glyphs[gid]->sc) ) {
+ lbearings[i] = 0xff;
+ widths[i] = 0xff;
+ /*idealwidths[i] = 1<<12; */ /* 1 em */
+ } else {
+ lbearings[i] = bdf->glyphs[gid]->xmin-kernMax;
+ widths[i] = bdf->glyphs[gid]->width<0?0:
+ bdf->glyphs[gid]->width>=256?255:
+ bdf->glyphs[gid]->width;
+ /*idealwidths[i] = bdf->glyphs[gid]->sc->width*(1<<12)/(bdf->sf->ascent+bdf->sf->descent);*/
+ width = BDFCCopyBitmaps(rows,width,bdf->glyphs[gid],bdf);
+ }
+ }
+ /* Now for the "undefined character", just a simple vertical bar */
+ locs[i] = width;
+ lbearings[i] = 1;
+ widths[i++] = 3;
+ /*idealwidths[i++] = (3<<12)/bdf->pixelsize;*/
+ for ( k = 1; k<bdf->pixelsize-1; ++k )
+ rows[k][width>>3] |= (1<<(7-(width&7)));
+ /* And one more entry to give a size to the last character */
+ locs[i] = ++width;
+ lbearings[i] = widths[i] = 0xff;
+ /*idealwidths[i] = 0;*/
+
+ /* Mac magic */
+ lbearings[0] = widths[0] = 0;
+ lbearings['\r'] = widths['\r'] = 0;
+ lbearings['\t'] = 0; widths['\t'] = 6;
+
+ /* We've finished the bitmap conversion, now save it... */
+ putlong(res,0); /* Length, to be filled in later */
+ putshort(res,IsMacMonospaced(bdf->sf,map)?0xb000:0x9000); /* fontType */
+ putshort(res,0);
+ putshort(res,255);
+ putshort(res,widMax);
+ putshort(res,kernMax);
+ putshort(res,-descentMax);
+ putshort(res,rectMax);
+ putshort(res,bdf->pixelsize);
+ owpos = ftell(res);
+ putshort(res,0);
+ putshort(res,bdf->ascent);
+ putshort(res,bdf->descent);
+ putshort(res,(short) (bdf->sf->pfminfo.linegap*bdf->pixelsize/(bdf->sf->ascent+bdf->sf->descent)) );
+ putshort(res,(width+15)>>4);
+ /* bitmaps */
+ for ( k=0; k<bdf->pixelsize; ++k ) {
+ for ( i=0; i<((width+15)>>4) ; ++i ) {
+ putc(rows[k][2*i],res);
+ putc(rows[k][2*i+1],res);
+ }
+ }
+ for ( i=0; i<258; ++i )
+ putshort(res,locs[i]);
+ owloc = ftell(res); /* valgrind reports an error here (but not above). god knows why */
+ for ( i=0; i<258; ++i ) {
+ putc(lbearings[i],res);
+ putc(widths[i],res);
+ }
+ end = ftell(res);
+ fseek(res,rlenpos,SEEK_SET);
+ putlong(res,end-rlenpos-4);
+ fseek(res,owpos,SEEK_SET);
+ putshort(res,(owloc-owpos)/2);
+ fseek(res,0,SEEK_END);
+
+ for ( k=0; k<bdf->pixelsize; ++k )
+ free(rows[k]);
+ free(rows);
+
+return(rlenpos);
+}
+
+static uint32 DummyNFNT(FILE *res, BDFFont *bdf, EncMap *map) {
+ /* This produces a stub NFNT which appears when the real data lives inside */
+ /* an sfnt (truetype) resource. We still need to produce an NFNT to tell */
+ /* the system that the pointsize is available. This NFNT has almost nothing */
+ /* in it, just the initial header, no metrics, no bitmaps */
+ int i, width, kernMax=1, descentMax=bdf->descent-1, rectMax=1, widMax=3;
+ uint32 rlenpos = ftell(res);
+ int gid;
+
+ for ( i=width=0; i<256 && i<map->enccount; ++i ) if ( (gid=map->map[i])!=-1 && gid<bdf->glyphcnt && bdf->glyphs[gid]!=NULL ) {
+ width += bdf->glyphs[gid]->xmax+1-bdf->glyphs[gid]->xmin;
+ if ( bdf->glyphs[gid]->width>widMax )
+ widMax = bdf->glyphs[gid]->width;
+ if ( bdf->glyphs[gid]->xmax+1-bdf->glyphs[gid]->xmin>rectMax )
+ rectMax = bdf->glyphs[gid]->xmax+1-bdf->glyphs[gid]->xmin;
+ if ( bdf->glyphs[gid]->xmin<kernMax )
+ kernMax = bdf->glyphs[gid]->xmin;
+ if ( bdf->glyphs[gid]->ymin<-descentMax )
+ descentMax = -bdf->glyphs[gid]->ymin;
+ }
+ if ( descentMax>bdf->descent ) descentMax = bdf->descent;
+
+ putlong(res,26); /* Length */
+ putshort(res,SFOneWidth(bdf->sf)!=-1?0xf000:0xd000); /* fontType */
+ putshort(res,0);
+ putshort(res,255);
+ putshort(res,widMax);
+ putshort(res,kernMax);
+ putshort(res,-descentMax);
+ putshort(res,rectMax);
+ putshort(res,bdf->pixelsize);
+ putshort(res,0);
+ putshort(res,bdf->ascent);
+ putshort(res,bdf->descent);
+ putshort(res,(short) (bdf->sf->pfminfo.linegap*bdf->pixelsize/(bdf->sf->ascent+bdf->sf->descent)) );
+ putshort(res,0);
+
+return(rlenpos);
+}
+
+static struct resource *SFToNFNTs(FILE *res, SplineFont *sf, int32 *sizes,
+ EncMap *map) {
+ int i, baseresid = HashToId(sf->fontname,sf,map);
+ struct resource *resstarts;
+ BDFFont *bdf;
+
+ if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
+
+ for ( i=0; sizes[i]!=0; ++i );
+ resstarts = gcalloc(i+1,sizeof(struct resource));
+
+ for ( i=0; sizes[i]!=0; ++i ) {
+ if ( (sizes[i]>>16)!=1 )
+ continue;
+ if ( (sizes[i]&0xffff)>=256 )
+ continue;
+ for ( bdf=sf->bitmaps; bdf!=NULL && (bdf->pixelsize!=(sizes[i]&0xffff) || BDFDepth(bdf)!=1); bdf=bdf->next );
+ if ( bdf==NULL )
+ continue;
+ resstarts[i].id = baseresid+bdf->pixelsize;
+ resstarts[i].pos = BDFToNFNT(res,bdf,map);
+ /* NFNTs seem to have resource flags of 0 */
+ }
+return(resstarts);
+}
+
+static struct resource *SFsToNFNTs(FILE *res, struct sflist *sfs,int baseresid) {
+ int i, j, cnt;
+ struct resource *resstarts;
+ BDFFont *bdf;
+ struct sflist *sfi;
+ SplineFont *sf;
+
+ cnt = 0;
+ for ( sfi=sfs; sfi!=NULL; sfi=sfi->next ) {
+ if ( sfi->sizes!=NULL ) {
+ for ( i=0; sfi->sizes[i]!=0; ++i );
+ cnt += i;
+ sfi->ids = gcalloc(i+1,sizeof(int));
+ sfi->bdfs = gcalloc(i+1,sizeof(BDFFont *));
+ }
+ }
+
+ resstarts = gcalloc(cnt+1,sizeof(struct resource));
+
+ cnt = 0;
+ for ( sfi=sfs; sfi!=NULL; sfi=sfi->next ) {
+ sf = sfi->sf;
+ if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
+ j=0;
+ if ( sfi->sizes ) for ( i=0; sfi->sizes[i]!=0; ++i ) {
+ if ( (sfi->sizes[i]>>16)!=1 )
+ continue;
+ if ( (sfi->sizes[i]&0xffff)>=256 )
+ continue;
+ for ( bdf=sf->bitmaps; bdf!=NULL && (bdf->pixelsize!=(sfi->sizes[i]&0xffff) || BDFDepth(bdf)!=1); bdf=bdf->next );
+ if ( bdf==NULL )
+ continue;
+ sfi->ids[j] = baseresid;
+ sfi->bdfs[j] = bdf;
+ resstarts[cnt+j].id = baseresid++;
+ resstarts[cnt+j++].pos = BDFToNFNT(res,bdf,sfi->map);
+ /* NFNTs seem to have resource flags of 0 */
+ }
+ cnt += j;
+ }
+return(resstarts);
+}
+
+static struct resource *BuildDummyNFNTlist(FILE *res, SplineFont *sf,
+ int32 *sizes, int baseresid, EncMap *map) {
+ int i;
+ struct resource *resstarts;
+ BDFFont *bdf;
+
+ if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
+
+ for ( i=0; sizes[i]!=0; ++i );
+ resstarts = gcalloc(i+1,sizeof(struct resource));
+
+ for ( i=0; sizes[i]!=0; ++i ) {
+ if ( (sizes[i]>>16)!=1 )
+ continue;
+ if ( (sizes[i]&0xffff)>=256 )
+ continue;
+ for ( bdf=sf->bitmaps; bdf!=NULL && (bdf->pixelsize!=(sizes[i]&0xffff) || BDFDepth(bdf)!=1); bdf=bdf->next );
+ if ( bdf==NULL )
+ continue;
+ resstarts[i].id = baseresid+(sizes[i]&0xffff);
+ resstarts[i].pos = DummyNFNT(res,bdf,map);
+ /* NFNTs seem to have resource flags of 0 */
+ }
+return(resstarts);
+}
+
+static struct resource *BuildDummyNFNTfamilyList(FILE *res, struct sflist *sfs,
+ int baseresid) {
+ int i,j,cnt;
+ struct resource *resstarts;
+ BDFFont *bdf;
+ struct sflist *sfi;
+ SplineFont *sf;
+
+ cnt = 0;
+ for ( sfi=sfs; sfi!=NULL; sfi=sfi->next ) {
+ if ( sfi->sizes!=NULL ) {
+ for ( i=0; sfi->sizes[i]!=0; ++i );
+ cnt += i;
+ sfi->ids = gcalloc(i+1,sizeof(int));
+ sfi->bdfs = gcalloc(i+1,sizeof(BDFFont *));
+ }
+ }
+
+ resstarts = gcalloc(cnt+1,sizeof(struct resource));
+
+ cnt = 0;
+ for ( sfi=sfs; sfi!=NULL; sfi=sfi->next ) {
+ sf = sfi->sf;
+ j = 0;
+ if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
+ if ( sfi->sizes ) for ( i=0; sfi->sizes[i]!=0; ++i ) {
+ if ( (sfi->sizes[i]>>16)!=1 )
+ continue;
+ for ( bdf=sf->bitmaps; bdf!=NULL && (bdf->pixelsize!=(sfi->sizes[i]&0xffff) || BDFDepth(bdf)!=1); bdf=bdf->next );
+ if ( bdf==NULL )
+ continue;
+ sfi->ids[j] = baseresid;
+ sfi->bdfs[j] = bdf;
+ resstarts[cnt+j].id = baseresid++;
+ resstarts[cnt+j++].pos = DummyNFNT(res,bdf,sfi->map);
+ /* NFNTs seem to have resource flags of 0 */
+ }
+ cnt += j;
+ }
+return(resstarts);
+}
+#endif
+
+enum psstyle_flags { psf_bold = 1, psf_italic = 2, psf_outline = 4,
+ psf_shadow = 0x8, psf_condense = 0x10, psf_extend = 0x20 };
+
+uint16 _MacStyleCode( char *styles, SplineFont *sf, uint16 *psstylecode ) {
+ unsigned short stylecode= 0, psstyle=0;
+
+ if ( strstrmatch( styles, "Bold" ) || strstrmatch(styles,"Demi") ||
+ strstrmatch( styles,"Heav") || strstrmatch(styles,"Blac") ||
+/* A few fonts have German/French styles in their names */
+ strstrmatch( styles,"Fett") || strstrmatch(styles,"Gras") ) {
+ stylecode = sf_bold;
+ psstyle = psf_bold;
+ } else if ( sf!=NULL && sf->weight!=NULL &&
+ (strstrmatch( sf->weight, "Bold" ) || strstrmatch(sf->weight,"Demi") ||
+ strstrmatch( sf->weight,"Heav") || strstrmatch(sf->weight,"Blac") ||
+ strstrmatch( sf->weight,"Fett") || strstrmatch(sf->weight,"Gras")) ) {
+ stylecode = sf_bold;
+ psstyle = psf_bold;
+ }
+ /* URW uses four leter abbreviations of Italic and Oblique */
+ /* Somebody else uses two letter abbrevs */
+ if ( (sf!=NULL && sf->italicangle!=0) ||
+ strstrmatch( styles, "Ital" ) ||
+ strstrmatch( styles, "Obli" ) ||
+ strstrmatch(styles, "Slanted") ||
+ strstrmatch(styles, "Kurs") ||
+ strstr( styles,"It" ) ) {
+ stylecode |= sf_italic;
+ psstyle |= psf_italic;
+ }
+ if ( strstrmatch( styles, "Underline" ) ) {
+ stylecode |= sf_underline;
+ }
+ if ( strstrmatch( styles, "Outl" ) ) {
+ stylecode |= sf_outline;
+ psstyle |= psf_outline;
+ }
+ if ( strstr(styles,"Shadow")!=NULL ) {
+ stylecode |= sf_shadow;
+ psstyle |= psf_shadow;
+ }
+ if ( strstrmatch( styles, "Cond" ) || strstr( styles,"Cn") ||
+ strstrmatch( styles, "Narrow") ) {
+ stylecode |= sf_condense;
+ psstyle |= psf_condense;
+ }
+ if ( strstrmatch( styles, "Exte" ) || strstr( styles,"Ex") ) {
+ stylecode |= sf_extend;
+ psstyle |= psf_extend;
+ }
+ if ( (psstyle&psf_extend) && (psstyle&psf_condense) ) {
+ if ( sf!=NULL )
+ LogError( _("Warning: %s(%s) is both extended and condensed. That's impossible.\n"),
+ sf->fontname, sf->origname );
+ else
+ LogError( _("Warning: Both extended and condensed. That's impossible.\n") );
+ psstyle &= ~psf_extend;
+ stylecode &= ~sf_extend;
+ }
+ if ( psstylecode!=NULL )
+ *psstylecode = psstyle;
+return( stylecode );
+}
+
+uint16 MacStyleCode( SplineFont *sf, uint16 *psstylecode ) {
+ char *styles;
+
+ if ( sf->cidmaster!=NULL )
+ sf = sf->cidmaster;
+
+ if ( sf->macstyle!=-1 ) {
+ if ( psstylecode!=NULL )
+ *psstylecode = (sf->macstyle&0x3)|((sf->macstyle&0x6c)>>1);
+return( sf->macstyle );
+ }
+
+ styles = SFGetModifiers(sf);
+return( _MacStyleCode(styles,sf,psstylecode));
+}
+
+#ifndef LUA_FF_LIB
+static uint32 SFToFOND(FILE *res,SplineFont *sf,uint32 id,int dottf,
+ int32 *sizes, EncMap *map) {
+ uint32 rlenpos = ftell(res), widoffpos, widoffloc, kernloc, styleloc, end;
+ int i,j,k,cnt, strcnt, fontclass, stylecode, glyphenc, geoffset, realstylecode;
+ int gid;
+ KernPair *kp;
+ DBounds b;
+ char *pt;
+ /* Fonds are generally marked system heap and sometimes purgeable (resource flags) */
+
+ putlong(res,0); /* Fill in length later */
+ putshort(res,IsMacMonospaced(sf,map)?0x9000:0x1000);
+ putshort(res,id);
+ putshort(res,0); /* First character */
+ putshort(res,255); /* Last character */
+ putshort(res,(short) ((sf->ascent*(1<<12))/(sf->ascent+sf->descent)));
+ putshort(res,-(short) ((sf->descent*(1<<12))/(sf->ascent+sf->descent)));
+ putshort(res,(short) ((sf->pfminfo.linegap*(1<<12))/(sf->ascent+sf->descent)));
+ putshort(res,(short) ((SFMacWidthMax(sf,map)*(1<<12))/(sf->ascent+sf->descent)));
+ widoffpos = ftell(res);
+ putlong(res,0); /* Fill in width offset later */
+ putlong(res,0); /* Fill in kern offset later */
+ putlong(res,0); /* Fill in style offset later */
+ for ( i=0; i<9; ++i )
+ putshort(res,0); /* Extra width values */
+ putlong(res,0); /* Script for international */
+ putshort(res,2); /* FOND version */
+
+ /* Font association table */
+ stylecode = realstylecode = MacStyleCode( sf, NULL );
+ stylecode = 0; /* Debug !!!! */
+ for ( i=j=0; sizes!=NULL && sizes[i]!=0; ++i )
+ if ( (sizes[i]>>16)==1 && (sizes[i]&0xffff)<256 )
+ ++j;
+ if ( dottf ) {
+ putshort(res,j+1-1); /* Number of faces */
+ putshort(res,0); /* it's scaleable */
+ putshort(res,stylecode);
+ putshort(res,id); /* Give it the same ID as the fond */
+ } else
+ putshort(res,j-1); /* Number of faces */
+ if ( sizes!=NULL ) {
+ for ( i=0; sizes[i]!=0; ++i ) if (( sizes[i]>>16) == 1 ) {
+ putshort(res,sizes[i]&0xffff);
+ putshort(res,stylecode);
+ putshort(res,id+(sizes[i]&0xffff)); /* make up a unique ID */
+ }
+ }
+
+ /* offset table */
+ putshort(res,1-1); /* One table */
+ putlong(res,6); /* Offset from start of otab to next byte */
+
+ /* bounding box table */
+ putshort(res,1-1); /* One bounding box */
+ SplineFontFindBounds(sf,&b);
+ putshort(res,stylecode);
+ putshort(res,b.minx*(1<<12)/(sf->ascent+sf->descent));
+ putshort(res,b.miny*(1<<12)/(sf->ascent+sf->descent));
+ putshort(res,b.maxx*(1<<12)/(sf->ascent+sf->descent));
+ putshort(res,b.maxy*(1<<12)/(sf->ascent+sf->descent));
+
+ widoffloc = ftell(res);
+ putshort(res,1-1); /* One style in the width table too */
+ putshort(res,stylecode);
+ for ( k=0; k<=256; ++k ) {
+ if ( k>=map->enccount || k==256 || (gid=map->map[k])==-1 || sf->glyphs[gid]==NULL )
+ putshort(res,1<<12); /* 1 em is default size */
+ else
+ putshort(res,sf->glyphs[gid]->width*(1<<12)/(sf->ascent+sf->descent));
+ }
+
+ kernloc = 0;
+ if (( cnt = SFMacAnyKerns(sf,map))>0 ) {
+ kernloc = ftell(res);
+ putshort(res,1-1); /* One style in the width table too */
+ putshort(res,stylecode); /* style */
+ putshort(res,cnt); /* Count of kerning pairs */
+ for ( k=0; k<256 && k<map->enccount; ++k ) {
+ if ( (gid=map->map[k])!=-1 && sf->glyphs[gid]!=NULL ) {
+ for ( kp=sf->glyphs[gid]->kerns; kp!=NULL; kp=kp->next )
+ if ( map->backmap[kp->sc->orig_pos]<256 ) {
+ putc(k,res);
+ putc(map->backmap[kp->sc->orig_pos],res);
+ putshort(res,kp->off*(1<<12)/(sf->ascent+sf->descent));
+ }
+ }
+ }
+ }
+
+ /* Fontographer referenced a postscript font even in truetype FONDs */
+ styleloc = ftell(res);
+ fontclass = 0x1; /* font name needs coordinating? Font has its own encoding */
+ if ( !(realstylecode&sf_outline) ) fontclass |= 4;
+ if ( realstylecode&sf_bold ) fontclass |= 0x18;
+ if ( realstylecode&psf_italic ) fontclass |= 0x40;
+ if ( realstylecode&psf_condense ) fontclass |= 0x80;
+ if ( realstylecode&psf_extend ) fontclass |= 0x100;
+ putshort(res,fontclass); /* fontClass */
+ geoffset = ftell(res);
+ putlong(res,0); /* Offset to glyph encoding table */ /* Fill in later */
+ putlong(res,0); /* Reserved, MBZ */
+ if ( strnmatch(sf->familyname,sf->fontname,strlen(sf->familyname))!=0 )
+ strcnt = 1;
+ else if ( strmatch(sf->familyname,sf->fontname)==0 )
+ strcnt = 1;
+ else if ( sf->fontname[strlen(sf->familyname)]=='-' )
+ strcnt = 4;
+ else
+ strcnt = 3;
+ for ( k=0; k<48; ++k )
+ putc(strcnt==1?1:2,res); /* All indeces point to this font */
+ putshort(res,strcnt); /* strcnt strings */
+ pt = sf->fontname+strlen(sf->familyname);
+ if ( strcnt==1 ) {
+ putc(strlen(sf->fontname),res); /* basename is full name */
+ /* Mac expects this to be upper case */
+ if ( Islower(*sf->fontname)) putc(toupper(*sf->fontname),res);
+ else putc(*sf->fontname,res);
+ fwrite(sf->fontname+1,1,strlen(sf->fontname+1),res);
+ } else {
+ putc(strlen(sf->familyname),res);/* basename */
+ if ( Islower(*sf->familyname)) putc(toupper(*sf->familyname),res);
+ else putc(*sf->familyname,res);
+ fwrite(sf->familyname+1,1,strlen(sf->familyname+1),res);
+ if ( strcnt==3 ) {
+ putc(1,res); /* index string is one byte long */
+ putc(3,res); /* plain name is basename with string 2 */
+ putc(strlen(pt),res); /* length of... */
+ fwrite(pt,1,strlen(pt),res); /* everything else */
+ } else {
+ putc(2,res); /* index string is two bytes long */
+ putc(3,res); /* plain name is basename with hyphen */
+ putc(4,res); /* and everything else */
+ putc(1,res); /* Length of ... */
+ putc('-',res); /* String containing hyphen */
+ ++pt; /* skip over hyphen */
+ putc(strlen(pt),res); /* length of ... */
+ fwrite(pt,1,strlen(pt),res); /* everything else */
+ }
+ }
+ /* Greg: record offset for glyph encoding table */
+ /* We assume that the bitmap and postscript fonts are encoded similarly */
+ /* and so a null vector will do. */
+ /* GWW: Hmm. ATM refuses to use postscript fonts that have */
+ /* glyph encoding tables. Printer drivers use them ok. ATM will only */
+ /* work on fonts with mac roman encodings */
+ if ( strmatch(map->enc->enc_name,"mac")!=0 &&
+ strmatch(map->enc->enc_name,"macintosh")!=0 &&
+ strmatch(map->enc->enc_name,"macroman")!=0 ) {
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ if ( !dottf ) ff_post_notice(_("The generated font won't work with ATM"),_("ATM requires that fonts be encoded with the Macintosh Latin encoding. This postscript font will print fine, but only the bitmap versions will be displayed on the screen"));
+#endif
+ glyphenc = ftell( res );
+ fseek(res,geoffset,SEEK_SET);
+ putlong(res,glyphenc-geoffset+2);
+ fseek(res,glyphenc,SEEK_SET);
+#if 1
+ putshort(res,0);
+#else
+ putshort(res,sf->charcnt>256?128:sf->charcnt-128);
+ for ( i=0x80; i<sf->charcnt && i<256; ++i ) {
+ SplineChar *sc, dummy;
+ putc(i,res);
+ sc = SCBuildDummy(&dummy,sf,i);
+ putc(strlen(sc->name),res);
+ fwrite(sc->name,1,strlen(sc->name),res);
+ }
+#endif
+ }
+
+ end = ftell(res);
+ fseek(res,widoffpos,SEEK_SET);
+ putlong(res,widoffloc-rlenpos-4); /* Fill in width offset */
+ putlong(res,kernloc!=0?kernloc-rlenpos-4:0); /* Fill in kern offset */
+ putlong(res,styleloc!=0?styleloc-rlenpos-4:0); /* Fill in style offset */
+
+ fseek(res,rlenpos,SEEK_SET);
+ putlong(res,end-rlenpos-4); /* resource length */
+ fseek(res,end,SEEK_SET);
+return(rlenpos);
+}
+
+static void putpnsstring(FILE *res,char *fontname,int len) {
+ putc(len,res);
+ if ( *fontname && len>0 ) {
+ if ( Islower(*fontname))
+ putc(toupper(*fontname),res);
+ else
+ putc(*fontname,res);
+ --len;
+ for ( ++fontname; *fontname && len>0; ++fontname, --len )
+ putc(*fontname,res);
+ }
+}
+
+static void putpsstring(FILE *res,char *fontname) {
+ putc(strlen(fontname),res);
+ if ( *fontname ) {
+ for ( ; *fontname; ++fontname )
+ putc(*fontname,res);
+ }
+}
+
+struct sflistlist {
+ struct sflist *sfs;
+ struct sflistlist *next;
+ char *fondname;
+};
+
+static struct sflistlist *FondSplitter(struct sflist *sfs,int *fondcnt) {
+ struct sflist *psfaces[48], *sfi, *last, *start;
+ struct sflistlist *sfsl=NULL, *lastl=NULL, *cur, *test;
+ uint16 psstyle;
+ int fc = 0;
+
+ sfi = sfs;
+ if ( sfi->sf->fondname==NULL ) {
+ memset(psfaces,0,sizeof(psfaces));
+ MacStyleCode(sfi->sf,&psstyle);
+ last = NULL;
+ while ( sfi->sf->fondname==NULL && psfaces[psstyle]==NULL ) {
+ psfaces[psstyle] = sfi;
+ last = sfi;
+ sfi = sfi->next;
+ if ( sfi==NULL )
+ break;
+ MacStyleCode(sfi->sf,&psstyle);
+ }
+ cur = gcalloc(1,sizeof(struct sflistlist));
+ cur->sfs = sfs;
+ last->next = NULL;
+ for ( last=sfi; last!=NULL; last=last->next )
+ if ( last->sf->fondname!=NULL && strcmp(last->sf->fondname,sfs->sf->familyname)==0 )
+ break;
+ cur->fondname = copy( last==NULL ? sfs->sf->familyname : sfs->sf->fontname );
+ lastl = sfsl = cur;
+ ++fc;
+ }
+ while ( sfi!=NULL ) {
+ start = sfi;
+ if ( sfi->sf->fondname==NULL ) {
+ last = sfi;
+ sfi = sfi->next;
+ } else {
+ memset(psfaces,0,sizeof(psfaces));
+ MacStyleCode(sfi->sf,&psstyle);
+ while ( sfi!=NULL && sfi->sf->fondname!=NULL &&
+ strcmp(sfi->sf->fondname,start->sf->fondname)==0 &&
+ psfaces[psstyle]==NULL ) {
+ psfaces[psstyle] = sfi;
+ last = sfi;
+ sfi = sfi->next;
+ if ( sfi==NULL )
+ break;
+ MacStyleCode(sfi->sf,&psstyle);
+ }
+ }
+ cur = gcalloc(1,sizeof(struct sflistlist));
+ test = NULL;
+ if ( start->sf->fondname!=NULL ) {
+ for ( test = sfsl; test!=NULL; test=test->next )
+ if ( strcmp(test->fondname,start->sf->fondname)==0 )
+ break;
+ if ( test==NULL )
+ cur->fondname = copy(start->sf->fondname);
+ }
+ if ( cur->fondname==NULL )
+ cur->fondname = copy(start->sf->fontname);
+ if ( lastl!=NULL ) lastl->next = cur;
+ lastl = cur;
+ cur->sfs = start;
+ last->next = NULL;
+ if ( sfsl==NULL )
+ sfsl = cur;
+ ++fc;
+ }
+ *fondcnt = fc;
+return( sfsl );
+}
+
+static void SFListListFree(struct sflistlist *sfsl) {
+ struct sflist *last = NULL;
+ struct sflistlist *sfli, *sflnext;
+ /* free the fond list and restore the sfs list */
+
+ for ( sfli=sfsl; sfli!=NULL; sfli = sflnext ) {
+ sflnext = sfli->next;
+ if ( last!=NULL )
+ last->next = sfli->sfs;
+ for ( last = sfli->sfs; last->next!=NULL; last = last->next );
+ free(sfli->fondname);
+ free(sfli);
+ }
+}
+
+static uint32 SFsToFOND(FILE *res,struct sflist *sfs,uint32 id,int format,int bf) {
+ uint32 rlenpos = ftell(res), widoffpos, widoffloc, kernloc, styleloc, end;
+ int i,j,k,cnt, scnt, kcnt, pscnt, strcnt, fontclass, glyphenc, geoffset;
+ int gid;
+ int size;
+ uint16 psstyle, stylecode;
+ int exact, famlen, has_hyphen;
+ char *familyname;
+ KernPair *kp;
+ DBounds b;
+ /* Fonds are generally marked system heap and sometimes purgeable (resource flags) */
+ struct sflist *faces[96];
+ struct sflist *psfaces[48];
+ SplineFont *sf;
+ struct sflist *sfi;
+ char *pt;
+
+ memset(faces,0,sizeof(faces));
+ memset(psfaces,0,sizeof(psfaces));
+ for ( sfi = sfs ; sfi!=NULL; sfi = sfi->next ) {
+ stylecode = MacStyleCode(sfi->sf,&psstyle);
+ if ( sfs->next==NULL ) /* FONDs with a single entry should make that entry be "regular" no matter what we think it really is */
+ stylecode = psstyle = 0;
+ if ( faces[stylecode]==NULL )
+ faces[stylecode] = sfi;
+ if ( psfaces[psstyle]==NULL )
+ psfaces[psstyle] = sfi;
+ }
+ sf = faces[0]->sf;
+
+ putlong(res,0); /* Fill in length later */
+ putshort(res,IsMacMonospaced(sf,faces[0]->map)?0x9000:0x1000);
+ putshort(res,id);
+ putshort(res,0); /* First character */
+ putshort(res,255); /* Last character */
+ putshort(res,(short) ((sf->ascent*(1<<12))/(sf->ascent+sf->descent)));
+ putshort(res,-(short) ((sf->descent*(1<<12))/(sf->ascent+sf->descent)));
+ putshort(res,(short) ((sf->pfminfo.linegap*(1<<12))/(sf->ascent+sf->descent)));
+ putshort(res,(short) ((SFMacWidthMax(sf,faces[0]->map)*(1<<12))/(sf->ascent+sf->descent)));
+ widoffpos = ftell(res);
+ putlong(res,0); /* Fill in width offset later */
+ putlong(res,0); /* Fill in kern offset later */
+ putlong(res,0); /* Fill in style offset later */
+ for ( i=0; i<9; ++i )
+ putshort(res,0); /* Extra width values */
+ putlong(res,0); /* Script for international */
+ putshort(res,2); /* FOND version */
+
+ /* Font association table */
+ for ( i=cnt=scnt=kcnt=0; i<96; ++i ) if ( faces[i]!=NULL ) {
+ ++scnt;
+ if ( faces[i]->id!=0 ) ++cnt;
+ if ( faces[i]->ids!=NULL )
+ for ( j=0; faces[i]->ids[j]!=0; ++j ) ++cnt;
+ if ( SFMacAnyKerns(faces[i]->sf,faces[i]->map)>0 )
+ ++kcnt;
+ }
+ putshort(res,cnt-1); /* Number of faces */
+ /* do ttf faces (if any) first */
+ for ( i=cnt=0; i<96; ++i ) if ( faces[i]!=NULL && faces[i]->id!=0 ) {
+ putshort(res,0); /* it's scaleable */
+ putshort(res,i); /* style */
+ putshort(res,faces[i]->id);
+ }
+ /* then do bitmap faces (if any) */ /* Ordered by size damn it */
+ for ( size=1; size<256; ++size ) {
+ for ( i=0; i<96; ++i ) if ( faces[i]!=NULL && faces[i]->ids!=NULL ) {
+ for ( j=0; faces[i]->ids[j]!=0 ; ++j ) {
+ int pointsize = rint( (faces[i]->bdfs[j]->pixelsize*72.0/mac_dpi) );
+ if ( pointsize==size ) {
+ putshort(res,size);
+ putshort(res,i); /* style */
+ putshort(res,faces[i]->ids[j]);
+ }
+ }
+ }
+ }
+
+ /* offset table */
+ putshort(res,1-1); /* One table */
+ putlong(res,6); /* Offset from start of otab to next byte */
+
+ /* bounding box table */
+ putshort(res,scnt-1); /* One bounding box per style */
+ for ( i=0; i<96; ++i ) if ( faces[i]!=NULL ) {
+ SplineFontFindBounds(faces[i]->sf,&b);
+ putshort(res,i); /* style */
+ putshort(res,b.minx*(1<<12)/(faces[i]->sf->ascent+faces[i]->sf->descent));
+ putshort(res,b.miny*(1<<12)/(faces[i]->sf->ascent+faces[i]->sf->descent));
+ putshort(res,b.maxx*(1<<12)/(faces[i]->sf->ascent+faces[i]->sf->descent));
+ putshort(res,b.maxy*(1<<12)/(faces[i]->sf->ascent+faces[i]->sf->descent));
+ }
+
+ widoffloc = ftell(res);
+ putshort(res,scnt-1); /* One set of width metrics per style */
+ for ( i=0; i<96; ++i ) if ( faces[i]!=NULL ) {
+ putshort(res,i);
+ for ( k=0; k<=257; ++k ) {
+ if ( k>=faces[i]->map->enccount || k>=256 ||
+ (gid=faces[i]->map->map[k])==-1 || faces[i]->sf->glyphs[gid]==NULL )
+ putshort(res,1<<12); /* 1 em is default size */
+ else
+ putshort(res,faces[i]->sf->glyphs[gid]->width*(1<<12)/(faces[i]->sf->ascent+faces[i]->sf->descent));
+ }
+ }
+
+ kernloc = 0;
+ if ( kcnt>0 ) {
+ kernloc = ftell(res);
+ putshort(res,kcnt-1); /* Number of styles with kern pairs */
+ for ( i=0; i<96; ++i ) if ( faces[i]!=NULL && ( cnt = SFMacAnyKerns(faces[i]->sf,faces[i]->map))>0 ) {
+ putshort(res,i); /* style */
+ putshort(res,cnt); /* Count of kerning pairs */
+ for ( k=0; k<256 && k<faces[i]->map->enccount; ++k ) {
+ if ( (gid=faces[i]->map->map[k])!=-1 && faces[i]->sf->glyphs[gid]!=NULL ) {
+ for ( kp=faces[i]->sf->glyphs[gid]->kerns; kp!=NULL; kp=kp->next )
+ if ( faces[i]->map->backmap[kp->sc->orig_pos]<256 ) {
+ putc(k,res);
+ putc(faces[i]->map->backmap[kp->sc->orig_pos],res);
+ putshort(res,kp->off*(1<<12)/(sf->ascent+sf->descent));
+ }
+ }
+ }
+ }
+ }
+
+ /* Fontographer referenced a postscript font even in truetype FONDs */
+ styleloc = ftell(res);
+
+ exact = false;
+ familyname = psfaces[0]->sf->fontname;
+ famlen = strlen(familyname);
+ if ( (pt=strchr(familyname,'-'))!=NULL )
+ famlen = pt-familyname;
+ else if ( strnmatch(psfaces[0]->sf->familyname,psfaces[0]->sf->fontname,
+ strlen(psfaces[0]->sf->familyname))==0 )
+ famlen = strlen(psfaces[0]->sf->familyname);
+ has_hyphen = (familyname[famlen]=='-');
+ for ( i=pscnt=0; i<48; ++i ) if ( psfaces[i]!=NULL ) {
+ ++pscnt;
+ if ( strncmp(psfaces[i]->sf->fontname,familyname,famlen)!=0 ) {
+ while ( famlen>0 ) {
+ --famlen;
+ if ( strncmp(psfaces[i]->sf->fontname,familyname,famlen)==0 )
+ break;
+ }
+ }
+ }
+ if ( famlen!=0 ) for ( i=0; i<48; ++i ) if ( psfaces[i]!=NULL ) {
+ if ( psfaces[i]->sf->fontname[famlen]==0 )
+ exact = true;
+ }
+ fontclass = 0x1;
+ if ( psfaces[psf_outline]==NULL ) fontclass |= 4;
+ if ( psfaces[psf_bold]!=NULL ) fontclass |= 0x18;
+ if ( psfaces[psf_italic]!=NULL ) fontclass |= 0x40;
+ if ( psfaces[psf_condense]!=NULL ) fontclass |= 0x80;
+ if ( psfaces[psf_extend]!=NULL ) fontclass |= 0x100;
+ putshort(res,fontclass); /* fontClass */
+ geoffset = ftell(res);
+ putlong(res,0); /* Offset to glyph encoding table */ /* Fill in later */
+ putlong(res,0); /* Reserved, MBZ */
+ strcnt = 1/* Family Name */ + pscnt-exact /* count of format strings */ +
+ has_hyphen +
+ pscnt-exact /* count of additional strings */;
+ /* indeces to format strings */
+ for ( i=0,pscnt=2; i<48; ++i )
+ if ( psfaces[i]!=NULL && psfaces[i]->sf->fontname[famlen]!=0 )
+ putc(pscnt++,res);
+ else if ( exact )
+ putc(1,res);
+ else
+ putc(2,res);
+ putshort(res,strcnt); /* strcnt strings */
+ putpnsstring(res,familyname,famlen);
+ if ( has_hyphen ) has_hyphen = pscnt++; /* Space for hyphen if present */
+ /* Now the format strings */
+ for ( i=0; i<48; ++i ) if ( psfaces[i]!=NULL ) {
+ if ( psfaces[i]->sf->fontname[famlen]!=0 ) {
+ if ( has_hyphen && psfaces[i]->sf->fontname[famlen]==' ' ) {
+ putc(2,res);
+ putc(has_hyphen,res);
+ putc(pscnt++,res);
+ } else {
+ putc(1,res); /* Familyname with the following */
+ putc(pscnt++,res);
+ }
+ }
+ }
+ if ( has_hyphen ) {
+ putc(1,res);
+ putc('-',res);
+ }
+ /* Now the additional names */
+ for ( i=0; i<48; ++i ) if ( psfaces[i]!=NULL ) {
+ if ( psfaces[i]->sf->fontname[famlen]!=0 )
+ putpsstring(res,psfaces[i]->sf->fontname+famlen);
+ }
+ /* Greg: record offset for glyph encoding table */
+ /* We assume that the bitmap and postscript fonts are encoded similarly */
+ /* and so a null vector will do. */
+ /* GWW: Hmm. ATM refuses to use postscript fonts that have */
+ /* glyph encoding tables. Printer drivers use them ok. ATM will only */
+ /* work on fonts with mac roman encodings */
+ if ( strmatch(psfaces[0]->map->enc->enc_name,"mac")!=0 &&
+ strmatch(psfaces[0]->map->enc->enc_name,"macintosh")!=0 &&
+ strmatch(psfaces[0]->map->enc->enc_name,"macroman")!=0 ) {
+ if ( format==ff_pfbmacbin )
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ ff_post_notice(_("The generated font won't work with ATM"),_("ATM requires that fonts be encoded with the Macintosh Latin encoding. This postscript font will print fine, but only the bitmap versions will be displayed on the screen"));
+#endif
+ glyphenc = ftell( res );
+ fseek(res,geoffset,SEEK_SET);
+ putlong(res,glyphenc-geoffset+2);
+ fseek(res,glyphenc,SEEK_SET);
+ putshort(res,0); /* Greg: an empty Glyph encoding table */
+ }
+
+ end = ftell(res);
+ fseek(res,widoffpos,SEEK_SET);
+ putlong(res,widoffloc-rlenpos-4); /* Fill in width offset */
+ putlong(res,kernloc!=0?kernloc-rlenpos-4:0); /* Fill in kern offset */
+ putlong(res,styleloc!=0?styleloc-rlenpos-4:0); /* Fill in style offset */
+
+ fseek(res,rlenpos,SEEK_SET);
+ putlong(res,end-rlenpos-4); /* resource length */
+ fseek(res,end,SEEK_SET);
+return(rlenpos);
+}
+
+/* I presume this routine is called after all resources have been written */
+static void DumpResourceMap(FILE *res,struct resourcetype *rtypes,enum fontformat format) {
+ uint32 rfork_base = format>=ff_ttfdfont?0:128; /* space for mac binary header */
+ uint32 resource_base = rfork_base+0x100;
+ uint32 rend, rtypesstart, mend, namestart;
+ int i,j;
+
+ fseek(res,0,SEEK_END);
+ rend = ftell(res);
+
+ if ( format<ff_ttfdfont ) {
+ /* Duplicate resource header */
+ putlong(res,0x100); /* start of resource data */
+ putlong(res,rend-rfork_base); /* start of resource map */
+ putlong(res,rend-rfork_base-0x100); /* length of resource data */
+ putlong(res,0); /* don't know the length of the map section yet */
+ } else {
+ for ( i=0; i<16; ++i ) /* 16 bytes of zeroes */
+ putc(0,res);
+ }
+
+ putlong(res,0); /* Some mac specific thing I don't understand */
+ putshort(res,0); /* another */
+ putshort(res,0); /* another */
+
+ putshort(res,4+ftell(res)-rend); /* Offset to resource types */
+ putshort(res,0); /* Don't know where the names go yet */
+
+ rtypesstart = ftell(res);
+ for ( i=0; rtypes[i].tag!=0; ++i );
+ putshort(res,i-1); /* Count of different types */
+ for ( i=0; rtypes[i].tag!=0; ++i ) {
+ putlong(res,rtypes[i].tag); /* Resource type */
+ putshort(res,0); /* Number of resources of this type */
+ putshort(res,0); /* Offset to the resource list */
+ }
+
+ /* Now the resource lists... */
+ for ( i=0; rtypes[i].tag!=0; ++i ) {
+ rtypes[i].resloc = ftell(res);
+ for ( j=0; rtypes[i].res[j].pos!=0; ++j ) {
+ putshort(res,rtypes[i].res[j].id);
+ rtypes[i].res[j].nameptloc = ftell(res);
+ putshort(res,0xffff); /* assume no name at first */
+ putc(rtypes[i].res[j].flags,res); /* resource flags */
+ /* three byte resource offset */
+ putc( ((rtypes[i].res[j].pos-resource_base)>>16)&0xff, res );
+ putc( ((rtypes[i].res[j].pos-resource_base)>>8)&0xff, res );
+ putc( ((rtypes[i].res[j].pos-resource_base)&0xff), res );
+ putlong(res,0);
+ }
+ }
+ namestart = ftell(res);
+ /* Now the names, if any */
+ for ( i=0; rtypes[i].tag!=0; ++i ) {
+ for ( j=0; rtypes[i].res[j].pos!=0; ++j ) {
+ if ( rtypes[i].res[j].name!=NULL ) {
+ rtypes[i].res[j].nameloc = ftell(res);
+ putc(strlen(rtypes[i].res[j].name),res); /* Length */
+ fwrite(rtypes[i].res[j].name,1,strlen(rtypes[i].res[j].name),res);
+ }
+ }
+ }
+ mend = ftell(res);
+
+ /* Repeat the rtypes list now we know where they go */
+ fseek(res,rtypesstart+2,SEEK_SET); /* skip over the count */
+ for ( i=0; rtypes[i].tag!=0; ++i ) {
+ putlong(res,rtypes[i].tag); /* Resource type */
+ for ( j=0; rtypes[i].res[j].pos!=0; ++j );
+ putshort(res,j-1); /* Number of resources of this type */
+ putshort(res,rtypes[i].resloc-rtypesstart);
+ }
+ /* And go back and fixup any name pointers */
+ for ( i=0; rtypes[i].tag!=0; ++i ) {
+ for ( j=0; rtypes[i].res[j].pos!=0; ++j ) {
+ if ( rtypes[i].res[j].name!=NULL ) {
+ fseek(res,rtypes[i].res[j].nameptloc,SEEK_SET);
+ putshort(res,rtypes[i].res[j].nameloc-namestart);
+ }
+ }
+ }
+
+ fseek(res,rend,SEEK_SET);
+ /* Fixup duplicate header (and offset to the name list) */
+ if ( format<ff_ttfdfont ) {
+ putlong(res,0x100); /* start of resource data */
+ putlong(res,rend-rfork_base); /* start of resource map */
+ putlong(res,rend-rfork_base-0x100); /* length of resource data */
+ putlong(res,mend-rend); /* length of map section */
+ } else {
+ for ( i=0; i<16; ++i )
+ putc(0,res);
+ }
+
+ putlong(res,0); /* Some mac specific thing I don't understand */
+ putshort(res,0); /* another */
+ putshort(res,0); /* another */
+
+ putshort(res,4+ftell(res)-rend); /* Offset to resource types */
+ putshort(res,namestart-rend); /* name section */
+
+ fseek(res,rfork_base,SEEK_SET);
+ /* Fixup main resource header */
+ putlong(res,0x100); /* start of resource data */
+ putlong(res,rend-rfork_base); /* start of resource map */
+ putlong(res,rend-rfork_base-0x100); /* length of resource data */
+ putlong(res,mend-rend); /* length of map section */
+}
+
+long mactime(void) {
+ time_t now;
+ int i;
+
+ time(&now);
+ /* convert from 1970 based time to 1904 based time */
+ now += (1970-1904)*365L*24*60*60;
+ for ( i=1904; i<1970; i+=4 )
+ now += 24*60*60;
+ /* Ignore any leap seconds -- Sorry Steve */
+return( now );
+}
+
+static int DumpMacBinaryHeader(FILE *res,struct macbinaryheader *mb) {
+#if !__Mac
+ uint8 header[128], *hpt; char buffer[256], *pt, *dpt;
+ uint32 len;
+ time_t now;
+ int crc;
+
+ if ( mb->macfilename==NULL ) {
+ char *pt = strrchr(mb->binfilename,'/');
+ if ( pt==NULL ) pt = mb->binfilename;
+ else ++pt;
+ strcpy(buffer,pt);
+ dpt = strrchr(buffer,'.');
+ if ( dpt==NULL ) {
+ buffer[0] = '_';
+ strcpy(buffer+1,pt);
+ } else
+ *dpt = '\0';
+ mb->macfilename = buffer;
+ buffer[63] = '\0';
+ }
+
+ memset(header,'\0',sizeof(header));
+ hpt = header;
+ *hpt++ = '\0'; /* version number */
+ /* Mac Filename */
+ pt = mb->macfilename;
+ *hpt++ = strlen( pt );
+ while ( *pt )
+ *hpt++ = *pt++;
+ while ( hpt<header+65 )
+ *hpt++ = '\0';
+ /* Mac File Type */
+ *hpt++ = mb->type>>24; *hpt++ = mb->type>>16; *hpt++ = mb->type>>8; *hpt++ = mb->type;
+ /* Mac Creator */
+ *hpt++ = mb->creator>>24; *hpt++ = mb->creator>>16; *hpt++ = mb->creator>>8; *hpt++ = mb->creator;
+ *hpt++ = '\0'; /* No finder flags set */
+ *hpt++ = '\0'; /* (byte 74) MBZ */
+ *hpt++ = '\0'; *hpt++ = '\0'; /* Vert Position in folder */
+ *hpt++ = '\0'; *hpt++ = '\0'; /* Hor Position in folder */
+ *hpt++ = '\0'; *hpt++ = '\0'; /* window or folder id??? */
+ *hpt++ = '\0'; /* protected bit ??? */
+ *hpt++ = '\0'; /* (byte 82) MBZ */
+ /* Data fork length */
+ *hpt++ = '\0'; *hpt++ = '\0'; *hpt++ = '\0'; *hpt++ = '\0';
+ /* Resource fork length */
+ fseek(res,0,SEEK_END);
+ len = ftell(res)-sizeof(header);
+ *hpt++ = len>>24; *hpt++ = len>>16; *hpt++ = len>>8; *hpt++ = len;
+ /* Pad resource fork to be a multiple of 128 bytes */
+ while ( (len&127)!=0 )
+ { putc('\0',res); ++len; }
+
+ /* Creation time, (seconds from 1/1/1904) */
+ now = mactime();
+ time(&now);
+ *hpt++ = now>>24; *hpt++ = now>>16; *hpt++ = now>>8; *hpt++ = now;
+ /* Modification time, (seconds from 1/1/1904) */
+ *hpt++ = now>>24; *hpt++ = now>>16; *hpt++ = now>>8; *hpt++ = now;
+
+ *hpt++ = '\0'; *hpt++ = '\0'; /* Get Info comment length */
+ *hpt++ = 0; /* More finder flags */
+
+/* MacBinary 3 */
+ memcpy(header+102,"mBIN",4);
+ header[106] = 0; /* Script. I assume 0 is latin */
+ header[107] = 0; /* extended finder flags */
+/* End of MacBinary 3 */
+ header[122] = 130; /* MacBinary version 3, written in (129 is MB2) */
+ header[123] = 129; /* MacBinary Version 2, needed to read */
+
+ crc = binhex_crc(header,124);
+ header[124] = crc>>8;
+ header[125] = crc;
+
+ fseek(res,0,SEEK_SET);
+ fwrite(header,1,sizeof(header),res);
+return( true );
+#else
+ int ret;
+ FSRef ref, parentref;
+ short macfile;
+ char *buf, *dirname, *pt, *fname;
+ HFSUniStr255 resforkname;
+ FSCatalogInfo info;
+ long len;
+ unichar_t *filename;
+ ByteCount whocares;
+ /* When on the mac let's just create a real resource fork. We do this by */
+ /* creating a mac file with a resource fork, opening that fork, and */
+ /* dumping all the data in the temporary file after the macbinary header */
+
+ /* The mac file routines are really lovely. I can't convert a pathspec to */
+ /* an FSRef unless the file exists. That is incredibly stupid and annoying of them */
+ /* But the directory should exist... */
+ fname = mb->macfilename?mb->macfilename:mb->binfilename;
+ dirname = copy(fname);
+ pt = strrchr(dirname,'/');
+ if ( pt!=NULL )
+ pt[1] = '\0';
+ else {
+ free(dirname);
+ dirname = copy(".");
+ }
+ ret=FSPathMakeRef( (uint8 *) dirname,&parentref,NULL);
+ free(dirname);
+ if ( ret!=noErr )
+return( false );
+
+ pt = strrchr(fname,'/');
+ filename = def2u_copy(pt==NULL?fname:pt+1);
+ ((FInfo *) (info.finderInfo))->fdType = mb->type;
+ ((FInfo *) (info.finderInfo))->fdCreator = mb->creator;
+ ret = FSCreateFileUnicode(&parentref,u_strlen(filename), (UniChar *) filename,
+ kFSCatInfoFinderInfo, &info, &ref, NULL);
+ free(filename);
+ if ( ret==dupFNErr ) {
+ /* File already exists, create failed, didn't get an FSRef */
+ ret=FSPathMakeRef( (uint8 *) fname,&ref,NULL);
+ }
+ if ( ret!=noErr )
+return( false );
+
+ FSGetResourceForkName(&resforkname);
+ FSCreateFork(&ref,resforkname.length,resforkname.unicode); /* I don't think this is needed, but it doesn't hurt... */
+ ret = FSOpenFork(&ref,resforkname.length,resforkname.unicode,fsWrPerm,&macfile);
+ if ( ret!=noErr )
+return( false );
+ FSSetForkSize(macfile,fsFromStart,0);/* Truncate it just in case it existed... */
+ fseek(res,128,SEEK_SET); /* Everything after the mac binary header in */
+ /* the temp file is resource fork */
+ buf = galloc(8*1024);
+ while ( (len=fread(buf,1,8*1024,res))>0 )
+ FSWriteFork(macfile,fsAtMark,0,len,buf,&whocares);
+ FSCloseFork(macfile);
+ free(buf);
+return( true );
+#endif
+}
+
+static void WriteDummyMacHeaders(FILE *res) {
+ /* Leave space for the mac binary header (128bytes) and the mac resource */
+ /* file header (256 bytes) */
+ int i;
+ for ( i=0; i<128; ++i )
+ putc(0,res);
+ for ( i=0; i<256; ++i )
+ putc(0,res);
+}
+
+static void WriteDummyDFontHeaders(FILE *res) {
+ /* Leave space for the mac resource file header (256 bytes) */
+ /* dfonts have the format of a data fork resource file (which I've never */
+ /* seen documented, but appears to be just like a resource fork except */
+ /* the first 16 bytes are not duplicated at the map */
+ int i;
+ for ( i=0; i<256; ++i )
+ putc(0,res);
+}
+
+ /* The mac has rules about what the filename should be for a postscript*/
+ /* font. If you deviate from those rules the font will not be found */
+ /* The font name must begin with a capital letter */
+ /* The filename is designed by modifying the font name */
+ /* After the initial capital there can be at most 4 lower case letters (or digits) */
+ /* in the filename, any additional lc letters (or digits) in the fontname are ignored */
+ /* Every subsequent capital will be followed by at most 2 lc letters */
+ /* special characters ("-$", etc.) are removed entirely */
+ /* So Times-Bold => TimesBol, HelveticaDemiBold => HelveDemBol */
+ /* MacBinary limits the name to 63 characters, I dunno what happens if */
+ /* we excede that */
+static void MakeMacPSName(char buffer[63],SplineFont *sf) {
+ char *pt, *spt, *lcpt;
+
+ for ( pt = buffer, spt = sf->fontname; *spt && pt<buffer+63-1; ++spt ) {
+ if ( Isupper(*spt) || spt==sf->fontname ) {
+ *pt++ = *spt;
+ lcpt = (spt==sf->fontname?spt+5:spt+3);
+ } else if ( (Islower(*spt) || Isdigit(*spt)) && spt<lcpt )
+ *pt++ = *spt;
+ }
+ *pt = '\0';
+}
+
+int WriteMacPSFont(char *filename,SplineFont *sf,enum fontformat format,
+ int flags,EncMap *map) {
+#ifndef LUA_FF_LIB
+ FILE *res, *temppfb;
+ int ret = 1;
+ struct resourcetype resources[2];
+ struct macbinaryheader header;
+ int lcfn = false, lcfam = false;
+ char buffer[63];
+#if __Mac
+ char *pt;
+#endif
+
+ temppfb = tmpfile();
+ if ( temppfb==NULL )
+return( 0 );
+
+ /* The mac has rules about what the filename should be for a postscript*/
+ /* font. If you deviate from those rules the font will not be found */
+ /* The font name must begin with a capital letter */
+ /* The filename is designed by modifying the font name */
+ /* After the initial capital there can be at most 4 lower case letters (or digits) */
+ /* in the filename, any additional lc letters (or digits) in the fontname are ignored */
+ /* Every subsequent capital will be followed by at most 2 lc letters */
+ /* special characters ("-$", etc.) are removed entirely */
+ /* So Times-Bold => TimesBol, HelveticaDemiBold => HelveDemBol */
+ /* MacBinary limits the name to 63 characters, I dunno what happens if */
+ /* we excede that */
+ if ( Islower(*sf->fontname)) { *sf->fontname = toupper(*sf->fontname); lcfn = true; }
+ if ( Islower(*sf->familyname)) { *sf->familyname = toupper(*sf->familyname); lcfam = true; }
+ MakeMacPSName(buffer,sf);
+
+ ret = _WritePSFont(temppfb,sf,ff_pfb,flags,map,NULL);
+ if ( lcfn ) *sf->fontname = Tolower(*sf->fontname);
+ if ( lcfam ) *sf->familyname = Tolower(*sf->familyname);
+ if ( ret==0 || ferror(temppfb) ) {
+ fclose(temppfb);
+return( 0 );
+ }
+
+ if ( __Mac && format==ff_pfbmacbin )
+ res = tmpfile();
+ else
+ res = fopen(filename,"wb+");
+ if ( res==NULL ) {
+ fclose(temppfb);
+return( 0 );
+ }
+
+ WriteDummyMacHeaders(res);
+ memset(resources,'\0',sizeof(resources));
+ rewind(temppfb);
+
+ resources[0].tag = CHR('P','O','S','T');
+ resources[0].res = PSToResources(res,temppfb);
+ fclose(temppfb);
+ DumpResourceMap(res,resources,format);
+ free( resources[0].res );
+
+#if __Mac
+ header.macfilename = galloc(strlen(filename)+strlen(buffer)+1);
+ strcpy(header.macfilename,filename);
+ pt = strrchr(header.macfilename,'/');
+ if ( pt==NULL ) pt=header.macfilename-1;
+ strcpy(pt+1,buffer);
+#else
+ header.macfilename = buffer;
+#endif
+ /* Adobe uses a creator of ASPF (Adobe Systems Postscript Font I assume) */
+ /* Fontographer uses ACp1 (Altsys Corp. Postscript type 1???) */
+ /* Both include an FREF, BNDL, ICON* and comment */
+ /* I shan't bother with that... It'll look ugly with no icon, but oh well */
+ header.type = CHR('L','W','F','N');
+ header.creator = CHR('G','W','p','1');
+ ret = DumpMacBinaryHeader(res,&header);
+ if ( ferror(res) ) ret = 0;
+ if ( fclose(res)==-1 ) ret = 0;
+#if __Mac
+ free(header.macfilename);
+#endif
+return( ret );
+#else
+return( 0 );
+#endif
+}
+
+int WriteMacTTFFont(char *filename,SplineFont *sf,enum fontformat format,
+ int32 *bsizes, enum bitmapformat bf,int flags,EncMap *map) {
+ FILE *res, *tempttf;
+ int ret = 1, r;
+ struct resourcetype resources[4];
+ struct resource rlist[3][2], *dummynfnts=NULL;
+ struct macbinaryheader header;
+
+ tempttf = tmpfile();
+ if ( tempttf==NULL )
+return( 0 );
+
+ if ( _WriteTTFFont(tempttf,sf,format==ff_none?ff_none:
+ format==ff_ttfmacbin?ff_ttf:
+ format-1,bsizes,bf,flags,map)==0 || ferror(tempttf) ) {
+ fclose(tempttf);
+return( 0 );
+ }
+ if ( bf!=bf_ttf && bf!=bf_sfnt_dfont )
+ bsizes = NULL; /* as far as the FOND for the truetype is concerned anyway */
+
+ if ( __Mac && format==ff_ttfmacbin )
+ res = tmpfile();
+ else
+ res = fopen(filename,"wb+");
+ if ( res==NULL ) {
+ fclose(tempttf);
+return( 0 );
+ }
+
+ if ( format!=ff_ttfmacbin )
+ WriteDummyDFontHeaders(res);
+ else
+ WriteDummyMacHeaders(res);
+ memset(rlist,'\0',sizeof(rlist));
+ memset(resources,'\0',sizeof(resources));
+ rewind(tempttf);
+
+ r = 0;
+ resources[r].tag = CHR('s','f','n','t');
+ resources[r++].res = rlist[0];
+ rlist[0][0].pos = TTFToResource(res,tempttf);
+ rlist[0][0].id = HashToId(sf->fontname,sf,map);
+ rlist[0][0].flags = 0x00; /* sfnts generally have resource flags 0x20 */
+ if ( bsizes!=NULL ) {
+ resources[r].tag = CHR('N','F','N','T');
+ resources[r++].res = dummynfnts = BuildDummyNFNTlist(res,sf,bsizes,rlist[0][0].id,map);
+ }
+ resources[r].tag = CHR('F','O','N','D');
+ resources[r].res = rlist[1];
+ rlist[1][0].pos = SFToFOND(res,sf,rlist[0][0].id,true,bsizes,map);
+ rlist[1][0].flags = 0x00; /* I've seen FONDs with resource flags 0, 0x20, 0x60 */
+ rlist[1][0].id = rlist[0][0].id;
+ rlist[1][0].name = sf->fondname ? sf->fondname : sf->familyname;
+ fclose(tempttf);
+ DumpResourceMap(res,resources,format);
+ free(dummynfnts);
+
+ ret = true;
+ if ( format==ff_ttfmacbin ) {
+ header.macfilename = NULL;
+ header.binfilename = filename;
+ /* Fontographer uses the old suitcase format for both bitmaps and ttf */
+ header.type = CHR('F','F','I','L');
+ header.creator = CHR('D','M','O','V');
+ ret = DumpMacBinaryHeader(res,&header);
+ }
+ if ( ferror(res) ) ret = false;
+ if ( fclose(res)==-1 ) ret = 0;
+return( ret );
+}
+
+int WriteMacBitmaps(char *filename,SplineFont *sf, int32 *sizes, int is_dfont,
+ EncMap *map) {
+ FILE *res;
+ int ret = 1;
+ struct resourcetype resources[3];
+ struct resource rlist[2][2];
+ struct macbinaryheader header;
+ char *binfilename, *pt, *dpt;
+
+ /* The filename we've been given is for the outline font, which might or */
+ /* might not be stuffed inside a bin file */
+ binfilename = galloc(strlen(filename)+strlen(".bmap.dfont")+1);
+ strcpy(binfilename,filename);
+ pt = strrchr(binfilename,'/');
+ if ( pt==NULL ) pt = binfilename; else ++pt;
+ dpt = strrchr(pt,'.');
+ if ( dpt==NULL )
+ dpt = pt+strlen(pt);
+ else if ( strmatch(dpt,".bin")==0 || strmatch(dpt,".dfont")==0 ) {
+ *dpt = '\0';
+ dpt = strrchr(pt,'.');
+ if ( dpt==NULL )
+ dpt = pt+strlen(pt);
+ }
+ strcpy(dpt,is_dfont?".bmap.dfont":__Mac?".bmap":".bmap.bin");
+
+ if ( __Mac && !is_dfont )
+ res = tmpfile();
+ else
+ res = fopen(binfilename,"wb+");
+ if ( res==NULL ) {
+ free(binfilename);
+return( 0 );
+ }
+
+ if ( is_dfont )
+ WriteDummyDFontHeaders(res);
+ else
+ WriteDummyMacHeaders(res);
+ memset(rlist,'\0',sizeof(rlist));
+ memset(resources,'\0',sizeof(resources));
+
+ resources[0].tag = CHR('N','F','N','T');
+ resources[0].res = SFToNFNTs(res,sf,sizes,map);
+ resources[1].tag = CHR('F','O','N','D');
+ resources[1].res = rlist[1];
+ rlist[1][0].id = HashToId(sf->fontname,sf,map);
+ rlist[1][0].pos = SFToFOND(res,sf,rlist[1][0].id,false,sizes,map);
+ rlist[1][0].name = sf->fondname ? sf->fondname : sf->familyname;
+ DumpResourceMap(res,resources,is_dfont?ff_ttfdfont:ff_ttfmacbin);
+
+ ret = true;
+ if ( !is_dfont ) {
+ header.macfilename = NULL;
+ header.binfilename = binfilename;
+ /* Fontographer uses the old suitcase format for both bitmaps and ttf */
+ header.type = CHR('F','F','I','L');
+ header.creator = CHR('D','M','O','V');
+ ret = DumpMacBinaryHeader(res,&header);
+ }
+ if ( ferror(res)) ret = false;
+ if ( fclose(res)==-1 ) ret = 0;
+ free(resources[0].res);
+ free(binfilename);
+return( ret );
+}
+
+/* We have to worry about these font formats:
+ ff_pfbmacbin, ff_ttfmacbin, ff_ttfdfont, ff_otfdfont, ff_otfciddfont, ff_none
+ bf_ttf, bf_sfnt_dfont, bf_nfntmacbin,
+ bf_nfntdfont I no long support this. OS/X doesn't support NFNTs so there's no point
+*/
+
+int WriteMacFamily(char *filename,struct sflist *sfs,enum fontformat format,
+ enum bitmapformat bf,int flags, EncMap *map) {
+ FILE *res;
+ int ret = 1, r, i;
+ struct resourcetype resources[4];
+ struct resource *rlist;
+ struct macbinaryheader header;
+ struct sflist *sfi, *sfsub;
+ char buffer[80];
+ int freefilename = 0;
+ char *pt;
+ int id, fondcnt;
+ struct sflistlist *sfsl, *sfli;
+
+ if ( format==ff_pfbmacbin ) {
+ for ( sfi=sfs; sfi!=NULL; sfi = sfi->next ) {
+ char *tempname;
+ MakeMacPSName(buffer,sfi->sf);
+#if !__Mac
+ strcat(buffer,".bin");
+#endif
+ tempname = galloc(strlen(filename)+strlen(buffer)+1);
+ strcpy(tempname,filename);
+ pt = strrchr(tempname,'/');
+ if ( pt==NULL ) pt=tempname-1;
+ strcpy(pt+1,buffer);
+ if ( strcmp(tempname,filename)==0 ) {
+ char *tf = galloc(strlen(filename)+20);
+ strcpy(tf,filename);
+ filename = tf;
+ freefilename = true;
+ pt = strrchr(filename,'.');
+ if ( pt==NULL || pt<strrchr(filename,'/'))
+ pt = filename+strlen(filename)+1;
+#if __Mac
+ strcpy(pt-1,".fam");
+#else
+ strcpy(pt-1,".fam.bin");
+#endif
+ }
+ if ( WriteMacPSFont(tempname,sfi->sf,format,flags,sfi->map)==0 )
+return( 0 );
+ free(tempname);
+ }
+ } else if ( format!=ff_none || bf==bf_sfnt_dfont ) {
+ for ( sfi=sfs; sfi!=NULL; sfi = sfi->next ) {
+ sfi->tempttf = tmpfile();
+ if ( sfi->tempttf==NULL ||
+ _WriteTTFFont(sfi->tempttf,sfi->sf,format==ff_none?ff_none:
+ format==ff_ttfmacbin?ff_ttf:
+ format-1,sfi->sizes,bf,flags,sfi->map)==0 ||
+ ferror(sfi->tempttf) ) {
+ for ( sfsub=sfs; sfsub!=sfi; sfsub=sfsub->next )
+ fclose( sfsub->tempttf );
+return( 0 );
+ }
+ rewind(sfi->tempttf);
+ }
+ }
+
+ if ( __Mac && (format==ff_ttfmacbin || format==ff_pfbmacbin ||
+ (format==ff_none && bf==bf_nfntmacbin)))
+ res = tmpfile();
+ else
+ res = fopen(filename,"wb+");
+ if ( res==NULL ) {
+ for ( sfsub=sfs; sfsub!=NULL; sfsub=sfsub->next )
+ fclose( sfsub->tempttf );
+return( 0 );
+ }
+
+ if ( format==ff_ttfdfont || format==ff_otfdfont || format==ff_otfciddfont ||
+ bf==bf_sfnt_dfont /*|| (format==ff_none && bf==bf_nfntdfont)*/)
+ WriteDummyDFontHeaders(res);
+ else
+ WriteDummyMacHeaders(res);
+ memset(resources,'\0',sizeof(resources));
+
+ id = HashToId(sfs->sf->fontname,sfs->sf,sfs->map);
+
+ r = 0;
+ if ( format==ff_ttfmacbin || format==ff_ttfdfont || format==ff_otfdfont ||
+ format==ff_otfciddfont || (format==ff_none && bf==bf_sfnt_dfont )) {
+ resources[r].tag = CHR('s','f','n','t');
+ for ( sfi=sfs, i=0; sfi!=NULL; sfi=sfi->next, ++i );
+ resources[r].res = gcalloc(i+1,sizeof(struct resource));
+ for ( sfi=sfs, i=0; sfi!=NULL; sfi=sfi->next, ++i ) {
+ resources[r].res[i].pos = TTFToResource(res,sfi->tempttf);
+ resources[r].res[i].id = sfi->id = id+i;
+ resources[r].res[i].flags = 0x00; /* sfnts generally have resource flags 0x20 */
+ fclose(sfi->tempttf);
+ }
+ ++r;
+ if ( bf==bf_ttf || bf==bf_sfnt_dfont ) {
+ resources[r].tag = CHR('N','F','N','T');
+ resources[r++].res = BuildDummyNFNTfamilyList(res,sfs,id);
+ }
+ }
+ if ( bf==bf_nfntmacbin /*|| bf==bf_nfntdfont */) {
+ resources[r].tag = CHR('N','F','N','T');
+ resources[r++].res = SFsToNFNTs(res,sfs,id);
+ }
+
+ sfsl = FondSplitter(sfs,&fondcnt);
+ rlist = gcalloc(fondcnt+1,sizeof(struct resource));
+ resources[r].tag = CHR('F','O','N','D');
+ resources[r++].res = rlist;
+ for ( i=0, sfli=sfsl; i<fondcnt && sfli!=NULL; ++i, sfli = sfli->next ) {
+ rlist[i].pos = SFsToFOND(res,sfli->sfs,id,format,bf);
+ rlist[i].flags = 0x00; /* I've seen FONDs with resource flags 0, 0x20, 0x60 */
+ rlist[i].id = id+i;
+ rlist[i].name = sfli->fondname;
+ }
+ DumpResourceMap(res,resources,format!=ff_none?format:
+ bf==bf_nfntmacbin?ff_ttfmacbin:ff_ttfdfont);
+ SFListListFree(sfsl);
+ for ( i=0; i<r; ++i )
+ free(resources[i].res);
+
+ ret = true;
+ if ( format==ff_ttfmacbin || format==ff_pfbmacbin ||
+ (format==ff_none && bf==bf_nfntmacbin) ) {
+ header.macfilename = NULL;
+ header.binfilename = filename;
+ /* Fontographer uses the old suitcase format for both bitmaps and ttf */
+ header.type = CHR('F','F','I','L');
+ header.creator = CHR('D','M','O','V');
+ ret = DumpMacBinaryHeader(res,&header);
+ }
+ if ( ferror(res) ) ret = false;
+ if ( fclose(res)==-1 ) ret = 0;
+ if ( freefilename )
+ free(filename);
+ for ( sfi=sfs; sfi!=NULL; sfi=sfi->next ) {
+ free( sfi->ids );
+ free( sfi->bdfs );
+ }
+return( ret );
+}
+
+void SfListFree(struct sflist *sfs) {
+ struct sflist *sfi;
+
+ while ( sfs!=NULL ) {
+ sfi = sfs->next;
+ free(sfs->sizes);
+ EncMapFree(sfs->map);
+ chunkfree(sfs,sizeof(struct sflist));
+ sfs = sfi;
+ }
+}
+#endif
+
+/* ******************************** Reading ********************************* */
+
+static SplineFont *SearchPostscriptResources(FILE *f,long rlistpos,int subcnt,long rdata_pos,
+ long name_list, int flags) {
+ long here = ftell(f);
+ long *offsets, lenpos;
+ int rname = -1, tmp;
+ int ch1, ch2;
+ int len, type, i, j, rlen;
+ unsigned short id, *rsrcids;
+ /* I don't pretend to understand the rational behind the format of a */
+ /* postscript font. It appears to be split up into chunks where the */
+ /* maximum chunk size is 0x800, each section (ascii, binary, ascii, eof) */
+ /* has its own set of chunks (ie chunks don't cross sections) */
+ char *buffer=NULL;
+ int max = 0;
+ FILE *pfb;
+ FontDict *fd;
+ SplineFont *sf;
+
+ fseek(f,rlistpos,SEEK_SET);
+ rsrcids = gcalloc(subcnt,sizeof(short));
+ offsets = gcalloc(subcnt,sizeof(long));
+ for ( i=0; i<subcnt; ++i ) {
+ rsrcids[i] = getushort(f);
+ tmp = (short) getushort(f);
+ if ( rname==-1 ) rname = tmp;
+ /* flags = */ getc(f);
+ ch1 = getc(f); ch2 = getc(f);
+ offsets[i] = rdata_pos+((ch1<<16)|(ch2<<8)|getc(f));
+ /* mbz = */ getlong(f);
+ }
+
+ pfb = tmpfile();
+ if ( pfb==NULL ) {
+ LogError( _("Can't open temporary file for postscript output\n") );
+ fseek(f,here,SEEK_SET );
+ free(offsets);
+return(NULL);
+ }
+
+ putc(0x80,pfb);
+ putc(1,pfb);
+ lenpos = ftell(pfb);
+ putc(0,pfb);
+ putc(0,pfb);
+ putc(0,pfb);
+ putc(0,pfb);
+ len = 0; type = 1;
+ id = 501;
+ for ( i=0; i<subcnt; ++i ) {
+ for ( j=0; j<subcnt; ++j )
+ if ( rsrcids[j]==id )
+ break;
+ if ( j == subcnt ) {
+ LogError( _("Missing POST resource %u\n"), id );
+ break;
+ }
+ id = id + 1;
+ fseek(f,offsets[j],SEEK_SET);
+ rlen = getlong(f);
+ ch1 = getc(f); ch2 = getc(f);
+ rlen -= 2; /* those two bytes don't count as real data */
+ if ( ch1==type )
+ len += rlen;
+ else {
+ long hold = ftell(pfb);
+ fseek(pfb,lenpos,SEEK_SET);
+ putc(len>>24,pfb);
+ putc((len>>16)&0xff,pfb);
+ putc((len>>8)&0xff,pfb);
+ putc(len&0xff,pfb);
+ fseek(pfb,hold,SEEK_SET);
+ if ( ch1==5 ) /* end of font mark */
+ break;
+ putc(0x80,pfb);
+ putc(ch1,pfb);
+ lenpos = ftell(pfb);
+ putc(0,pfb);
+ putc(0,pfb);
+ putc(0,pfb);
+ putc(0,pfb);
+ type = ch1;
+ len = rlen;
+ }
+ if ( rlen>max ) {
+ free(buffer);
+ max = rlen;
+ if ( max<0x800 ) max = 0x800;
+ buffer=galloc(max);
+ if ( buffer==NULL ) {
+ LogError( _("Out of memory\n") );
+ exit( 1 );
+ }
+ }
+ fread(buffer,1,rlen,f);
+ fwrite(buffer,1,rlen,pfb);
+ }
+ free(buffer);
+ free(offsets);
+ free(rsrcids);
+ putc(0x80,pfb);
+ putc(3,pfb);
+ fseek(pfb,lenpos,SEEK_SET);
+ putc(len>>24,pfb);
+ putc((len>>16)&0xff,pfb);
+ putc((len>>8)&0xff,pfb);
+ putc(len&0xff,pfb);
+ fseek(f,here,SEEK_SET);
+ rewind(pfb);
+ if ( flags&ttf_onlynames )
+return( (SplineFont *) _NamesReadPostscript(pfb) ); /* This closes the font for us */
+
+ fd = _ReadPSFont(pfb);
+ sf = NULL;
+ if ( fd!=NULL ) {
+ sf = SplineFontFromPSFont(fd);
+ PSFontFree(fd);
+ /* There is no FOND in a postscript file, so we can't read any kerning*/
+ }
+ fclose(pfb);
+return( sf );
+}
+
+static SplineFont *SearchTtfResources(FILE *f,long rlistpos,int subcnt,long rdata_pos,
+ long name_list,char *filename,int flags,enum openflags openflags) {
+ long here, start = ftell(f);
+ long roff;
+ int rname = -1;
+ int ch1, ch2;
+ int len, i, rlen, ilen;
+ /* The sfnt resource is just a copy of the ttf file */
+ char *buffer=NULL;
+ int max = 0;
+ FILE *ttf;
+ SplineFont *sf;
+ int which = 0;
+ char **names;
+ char *pt,*lparen;
+ char *chosenname=NULL;
+
+ fseek(f,rlistpos,SEEK_SET);
+ if ( subcnt>1 || (flags&ttf_onlynames) ) {
+ names = gcalloc(subcnt+1,sizeof(char *));
+ for ( i=0; i<subcnt; ++i ) {
+ /* resource id = */ getushort(f);
+ /* rname = (short) */ getushort(f);
+ /* flags = */ getc(f);
+ ch1 = getc(f); ch2 = getc(f);
+ roff = rdata_pos+((ch1<<16)|(ch2<<8)|getc(f));
+ /* mbz = */ getlong(f);
+ here = ftell(f);
+ names[i] = TTFGetFontName(f,roff+4,roff+4);
+ if ( names[i]==NULL ) {
+ char buffer[32];
+ sprintf( buffer, "Nameless%d", i );
+ names[i] = copy(buffer);
+ }
+ fseek(f,here,SEEK_SET);
+ }
+ if ( flags&ttf_onlynames ) {
+return( (SplineFont *) names );
+ }
+ if ((pt = strrchr(filename,'/'))==NULL ) pt = filename;
+ if ( (lparen = strchr(pt,'('))!=NULL && strchr(lparen,')')!=NULL ) {
+ char *find = copy(lparen+1);
+ pt = strchr(find,')');
+ if ( pt!=NULL ) *pt='\0';
+ for ( which=subcnt-1; which>=0; --which )
+ if ( strcmp(names[which],find)==0 )
+ break;
+ if ( which==-1 ) {
+ char *fn = copy(filename);
+ fn[lparen-filename] = '\0';
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_post_error(_("Not in Collection"),_("%s is not in %.100s"),find,fn);
+#endif
+ free(fn);
+ }
+ free(find);
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ } else if ( no_windowing_ui )
+ which = 0;
+ else
+ which = gwwv_choose(_("Pick a font, any font..."),(const char **) names,subcnt,0,_("There are multiple fonts in this file, pick one"));
+#else
+ } else
+ which = 0;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ if ( lparen==NULL && which!=-1 )
+ chosenname = copy(names[which]);
+ for ( i=0; i<subcnt; ++i )
+ free(names[i]);
+ free(names);
+ fseek(f,rlistpos,SEEK_SET);
+ }
+
+ for ( i=0; i<subcnt; ++i ) {
+ /* resource id = */ getushort(f);
+ rname = (short) getushort(f);
+ /* flags = */ getc(f);
+ ch1 = getc(f); ch2 = getc(f);
+ roff = rdata_pos+((ch1<<16)|(ch2<<8)|getc(f));
+ /* mbz = */ getlong(f);
+ if ( i!=which )
+ continue;
+ here = ftell(f);
+
+ ttf = tmpfile();
+ if ( ttf==NULL ) {
+ LogError( _("Can't open temporary file for truetype output.\n") );
+ continue;
+ }
+
+ fseek(f,roff,SEEK_SET);
+ ilen = rlen = getlong(f);
+ if ( rlen>16*1024 )
+ ilen = 16*1024;
+ if ( ilen>max ) {
+ free(buffer);
+ max = ilen;
+ if ( max<0x800 ) max = 0x800;
+ buffer=malloc(max);
+ }
+ for ( len=0; len<rlen; ) {
+ int temp = ilen;
+ if ( rlen-len<ilen ) temp = rlen-len;
+ temp = fread(buffer,1,temp,f);
+ if ( temp==EOF )
+ break;
+ fwrite(buffer,1,temp,ttf);
+ len += temp;
+ }
+ rewind(ttf);
+ sf = _SFReadTTF(ttf,flags,openflags,NULL,NULL);
+ fclose(ttf);
+ if ( sf!=NULL ) {
+ free(buffer);
+ fseek(f,start,SEEK_SET);
+ if ( sf->chosenname==NULL ) sf->chosenname = chosenname;
+return( sf );
+ }
+ fseek(f,here,SEEK_SET);
+ }
+ free(chosenname);
+ free(buffer);
+ fseek(f,start,SEEK_SET);
+return( NULL );
+}
+
+typedef struct fond {
+ char *fondname;
+ int first, last;
+ int assoc_cnt;
+ struct assoc {
+ short size, style, id;
+ } *assoc;
+ /* size==0 => scalable */
+ /* style>>8 is the bit depth (0=>1, 1=>2, 2=>4, 3=>8) */
+ /* search order for ID is sfnt, NFNT, FONT */
+ int stylewidthcnt;
+ struct stylewidths {
+ short style;
+ short *widthtab; /* 4.12 fixed number with the width specified as a fraction of an em */
+ } *stylewidths;
+ int stylekerncnt;
+ struct stylekerns {
+ short style;
+ int kernpairs;
+ struct kerns {
+ unsigned char ch1, ch2;
+ short offset; /* 4.12 */
+ } *kerns;
+ } *stylekerns;
+ char *psnames[48];
+ struct fond *next;
+} FOND;
+
+struct MacFontRec {
+ short fontType;
+ short firstChar;
+ short lastChar;
+ short widthMax;
+ short kernMax; /* bb learing */
+ short Descent; /* maximum negative distance below baseline*/
+ short fRectWidth; /* bounding box width */
+ short fRectHeight; /* bounding box height */
+ unsigned short *offsetWidths;/* offset to start of offset/width table */
+ /* 0xffff => undefined, else high byte is offset in locTable, */
+ /* low byte is width */
+ short ascent;
+ short descent;
+ short leading;
+ short rowWords; /* shorts per row */
+ unsigned short *fontImage; /* rowWords*fRectHeight */
+ /* Images for all characters plus one extra for undefined */
+ unsigned short *locs; /* lastchar-firstchar+3 words */
+ /* Horizontal offset to start of n'th character. Note: applies */
+ /* to each row. Missing characters have same loc as following */
+};
+
+static void FondListFree(FOND *list) {
+ FOND *next;
+ int i;
+
+ while ( list!=NULL ) {
+ next = list->next;
+ free(list->assoc);
+ for ( i=0; i<list->stylewidthcnt; ++i )
+ free(list->stylewidths[i].widthtab);
+ free(list->stylewidths);
+ for ( i=0; i<list->stylekerncnt; ++i )
+ free(list->stylekerns[i].kerns);
+ free(list->stylekerns);
+ for ( i=0; i<48; ++i )
+ free(list->psnames[i]);
+ free(list);
+ list = next;
+ }
+}
+
+/* There's probably only one fond in the file, but there could be more so be */
+/* prepared... */
+/* I want the fond: */
+/* to get the fractional widths for the SWIDTH entry on bdf */
+/* to get the font name */
+/* to get the font association tables */
+/* to get the style flags */
+/* http://developer.apple.com/techpubs/mac/Text/Text-269.html */
+static FOND *BuildFondList(FILE *f,long rlistpos,int subcnt,long rdata_pos,
+ long name_list,int flags) {
+ long here, start = ftell(f);
+ long offset;
+ int rname = -1;
+ char name[300];
+ int ch1, ch2;
+ int i, j, k, cnt, isfixed;
+ FOND *head=NULL, *cur;
+ long widoff, kernoff, styleoff;
+
+ fseek(f,rlistpos,SEEK_SET);
+ for ( i=0; i<subcnt; ++i ) {
+ /* resource id = */ getushort(f);
+ rname = (short) getushort(f);
+ /* flags = */ getc(f);
+ ch1 = getc(f); ch2 = getc(f);
+ offset = rdata_pos+((ch1<<16)|(ch2<<8)|getc(f));
+ /* mbz = */ getlong(f);
+ here = ftell(f);
+
+ cur = gcalloc(1,sizeof(FOND));
+ cur->next = head;
+ head = cur;
+
+ if ( rname!=-1 ) {
+ fseek(f,name_list+rname,SEEK_SET);
+ ch1 = getc(f);
+ fread(name,1,ch1,f);
+ name[ch1] = '\0';
+ cur->fondname = copy(name);
+ }
+
+ offset += 4;
+ fseek(f,offset,SEEK_SET);
+ isfixed = getushort(f)&0x8000?1:0;
+ /* family id = */ getushort(f);
+ cur->first = getushort(f);
+ cur->last = getushort(f);
+/* on a 1 point font... */
+ /* ascent = */ getushort(f);
+ /* descent = */ getushort(f);
+ /* leading = */ getushort(f);
+ /* widmax = */ getushort(f);
+ if ( (widoff = getlong(f))!=0 ) widoff += offset;
+ if ( (kernoff = getlong(f))!=0 ) kernoff += offset;
+ if ( (styleoff = getlong(f))!=0 ) styleoff += offset;
+ for ( j=0; j<9; ++j )
+ getushort(f);
+ /* internal & undefined, for international scripts = */ getlong(f);
+ /* version = */ getushort(f);
+ cur->assoc_cnt = getushort(f)+1;
+ cur->assoc = gcalloc(cur->assoc_cnt,sizeof(struct assoc));
+ for ( j=0; j<cur->assoc_cnt; ++j ) {
+ cur->assoc[j].size = getushort(f);
+ cur->assoc[j].style = getushort(f);
+ cur->assoc[j].id = getushort(f);
+ }
+ if ( widoff!=0 ) {
+ fseek(f,widoff,SEEK_SET);
+ cnt = getushort(f)+1;
+ cur->stylewidthcnt = cnt;
+ cur->stylewidths = gcalloc(cnt,sizeof(struct stylewidths));
+ for ( j=0; j<cnt; ++j ) {
+ cur->stylewidths[j].style = getushort(f);
+ cur->stylewidths[j].widthtab = galloc((cur->last-cur->first+3)*sizeof(short));
+ for ( k=cur->first; k<=cur->last+2; ++k )
+ cur->stylewidths[j].widthtab[k] = getushort(f);
+ }
+ }
+ if ( kernoff!=0 && (flags&ttf_onlykerns) ) {
+ fseek(f,kernoff,SEEK_SET);
+ cnt = getushort(f)+1;
+ cur->stylekerncnt = cnt;
+ cur->stylekerns = gcalloc(cnt,sizeof(struct stylekerns));
+ for ( j=0; j<cnt; ++j ) {
+ cur->stylekerns[j].style = getushort(f);
+ cur->stylekerns[j].kernpairs = getushort(f);
+ cur->stylekerns[j].kerns = galloc(cur->stylekerns[j].kernpairs*sizeof(struct kerns));
+ for ( k=0; k<cur->stylekerns[j].kernpairs; ++k ) {
+ cur->stylekerns[j].kerns[k].ch1 = getc(f);
+ cur->stylekerns[j].kerns[k].ch2 = getc(f);
+ cur->stylekerns[j].kerns[k].offset = getushort(f);
+ }
+ }
+ }
+ if ( styleoff!=0 ) {
+ uint8 stringoffsets[48];
+ int strcnt, stringlen, format;
+ char **strings, *pt;
+ fseek(f,styleoff,SEEK_SET);
+ /* class = */ getushort(f);
+ /* glyph encoding offset = */ getlong(f);
+ /* reserved = */ getlong(f);
+ for ( j=0; j<48; ++j )
+ stringoffsets[j] = getc(f);
+ strcnt = getushort(f);
+ strings = galloc(strcnt*sizeof(char *));
+ for ( j=0; j<strcnt; ++j ) {
+ stringlen = getc(f);
+ strings[j] = galloc(stringlen+2);
+ strings[j][0] = stringlen;
+ strings[j][stringlen+1] = '\0';
+ for ( k=0; k<stringlen; ++k )
+ strings[j][k+1] = getc(f);
+ }
+ for ( j=0; j<48; ++j ) {
+ for ( k=j-1; k>=0; --k )
+ if ( stringoffsets[j]==stringoffsets[k] )
+ break;
+ if ( k!=-1 )
+ continue; /* this style doesn't exist */
+ format = stringoffsets[j]-1;
+ stringlen = strings[0][0];
+ if ( format!=0 )
+ for ( k=0; k<strings[format][0]; ++k )
+ stringlen += strings[ strings[format][k+1]-1 ][0];
+ pt = cur->psnames[j] = galloc(stringlen+1);
+ strcpy(pt,strings[ 0 ]+1);
+ pt += strings[ 0 ][0];
+ if ( format!=0 )
+ for ( k=0; k<strings[format][0]; ++k ) {
+ strcpy(pt,strings[ strings[format][k+1]-1 ]+1);
+ pt += strings[ strings[format][k+1]-1 ][0];
+ }
+ *pt = '\0';
+ }
+ for ( j=0; j<strcnt; ++j )
+ free(strings[j]);
+ free(strings);
+ }
+ fseek(f,here,SEEK_SET);
+ }
+ fseek(f,start,SEEK_SET);
+return( head );
+}
+
+static BDFChar *NFNTCvtBitmap(struct MacFontRec *font,int index,SplineFont *sf,int gid) {
+ BDFChar *bdfc;
+ int i,j, bits, bite, bit;
+
+ bdfc = chunkalloc(sizeof(BDFChar));
+ bdfc->xmin = (font->offsetWidths[index]>>8)+font->kernMax;
+ bdfc->xmax = bdfc->xmin + font->locs[index+1]-font->locs[index]-1;
+ if ( bdfc->xmax<bdfc->xmin )
+ bdfc->xmax = bdfc->xmin; /* Empty glyph mark */
+ bdfc->ymin = -font->descent;
+ bdfc->ymax = font->ascent-1;
+ bdfc->width = font->offsetWidths[index]&0xff;
+ bdfc->vwidth = font->ascent + font->descent;
+ bdfc->bytes_per_line = ((bdfc->xmax-bdfc->xmin)>>3) + 1;
+ bdfc->bitmap = gcalloc(bdfc->bytes_per_line*font->fRectHeight,sizeof(uint8));
+ bdfc->orig_pos = gid;
+ bdfc->sc = sf->glyphs[gid];
+
+ bits = font->locs[index]; bite = font->locs[index+1];
+ for ( i=0; i<font->fRectHeight; ++i ) {
+ uint16 *test = font->fontImage + i*font->rowWords;
+ uint8 *bpt = bdfc->bitmap + i*bdfc->bytes_per_line;
+ for ( bit=bits, j=0; bit<bite; ++bit, ++j ) {
+ if ( test[bit>>4]&(0x8000>>(bit&0xf)) )
+ bpt[j>>3] |= (0x80>>(j&7));
+ }
+ }
+ BCCompressBitmap(bdfc);
+return( bdfc );
+}
+
+static void LoadNFNT(FILE *f,long offset, SplineFont *sf, int size) {
+ long here = ftell(f);
+ long baseow;
+ long ow;
+ int i,gid;
+ struct MacFontRec font;
+ BDFFont *bdf;
+ SplineChar *sc;
+
+ offset += 4; /* skip over the length */
+ fseek(f,offset,SEEK_SET);
+ memset(&font,'\0',sizeof(struct MacFontRec));
+ font.fontType = getushort(f);
+ font.firstChar = getushort(f);
+ font.lastChar = getushort(f);
+ font.widthMax = getushort(f);
+ font.kernMax = (short) getushort(f);
+ font.Descent = (short) getushort(f);
+ font.fRectWidth = getushort(f);
+ font.fRectHeight = getushort(f);
+ baseow = ftell(f);
+ ow = getushort(f);
+ font.ascent = getushort(f);
+ font.descent = getushort(f);
+ if ( font.Descent>=0 ) {
+ ow |= (font.Descent<<16);
+ font.Descent = -font.descent; /* Possibly overkill, but should be safe */
+ }
+ font.leading = getushort(f);
+ font.rowWords = getushort(f);
+ if ( font.rowWords!=0 ) {
+ font.fontImage = gcalloc(font.rowWords*font.fRectHeight,sizeof(short));
+ font.locs = gcalloc(font.lastChar-font.firstChar+3,sizeof(short));
+ font.offsetWidths = gcalloc(font.lastChar-font.firstChar+3,sizeof(short));
+ for ( i=0; i<font.rowWords*font.fRectHeight; ++i )
+ font.fontImage[i] = getushort(f);
+ for ( i=0; i<font.lastChar-font.firstChar+3; ++i )
+ font.locs[i] = getushort(f);
+ fseek(f,baseow+2*ow,SEEK_SET);
+ for ( i=0; i<font.lastChar-font.firstChar+3; ++i )
+ font.offsetWidths[i] = getushort(f);
+ }
+ fseek(f,here,SEEK_SET);
+ if ( font.rowWords==0 )
+return;
+
+ /* Now convert the FONT record to one of my BDF structs */
+ bdf = gcalloc(1,sizeof(BDFFont));
+ bdf->sf = sf;
+ bdf->next = sf->bitmaps;
+ sf->bitmaps = bdf;
+ bdf->glyphcnt = bdf->glyphmax = sf->glyphcnt;
+ bdf->pixelsize = font.ascent+font.descent;
+ bdf->glyphs = gcalloc(sf->glyphcnt,sizeof(BDFChar *));
+ bdf->ascent = font.ascent;
+ bdf->descent = font.descent;
+ bdf->res = 72;
+ for ( i=font.firstChar; i<=font.lastChar+1; ++i ) {
+ if ( i!=font.lastChar+1 )
+ sc = SFMakeChar(sf,sf->map,i);
+ else {
+ sc = SFGetChar(sf,-1,".notdef");
+ if ( sc==NULL )
+ break;
+ }
+ gid = sc->orig_pos;
+ bdf->glyphs[gid] = NFNTCvtBitmap(&font,i-font.firstChar,sf,gid);
+ if ( !sf->glyphs[gid]->widthset ) {
+ sf->glyphs[gid]->width = bdf->glyphs[gid]->width*(sf->ascent+sf->descent)/bdf->pixelsize;
+ sf->glyphs[gid]->widthset = true;
+ }
+ }
+
+ free(font.fontImage);
+ free(font.locs);
+ free(font.offsetWidths);
+}
+
+static char *BuildName(char *family,int style) {
+ char buffer[350];
+
+ strncpy(buffer,family,200);
+ if ( style!=0 )
+ strcat(buffer,"-");
+ if ( style&sf_bold )
+ strcat(buffer,"Bold");
+ if ( style&sf_italic )
+ strcat(buffer,"Italic");
+ if ( style&sf_underline )
+ strcat(buffer,"Underline");
+ if ( style&sf_outline )
+ strcat(buffer,"Outline");
+ if ( style&sf_shadow )
+ strcat(buffer,"Shadow");
+ if ( style&sf_condense )
+ strcat(buffer,"Condensed");
+ if ( style&sf_extend )
+ strcat(buffer,"Extended");
+return( copy(buffer));
+}
+
+static int GuessStyle(char *fontname,int *styles,int style_cnt) {
+ int which, style;
+ char *stylenames = _GetModifiers(fontname,NULL,NULL);
+
+ style = _MacStyleCode(stylenames,NULL,NULL);
+ for ( which = style_cnt; which>=0; --which )
+ if ( styles[which] == style )
+return( which );
+
+return( -1 );
+}
+
+static FOND *PickFOND(FOND *fondlist,char *filename,char **name, int *style) {
+ int i,j;
+ FOND *test;
+ uint8 stylesused[96];
+ char **names;
+ int cnt, which;
+ char *pt, *lparen;
+ FOND **fonds = NULL, *fond = NULL;
+ int *styles = NULL;
+ char *find = NULL;
+
+ if ((pt = strrchr(filename,'/'))!=NULL ) pt = filename;
+ if ( (lparen = strchr(filename,'('))!=NULL && strchr(lparen,')')!=NULL ) {
+ find = copy(lparen+1);
+ pt = strchr(find,')');
+ if ( pt!=NULL ) *pt='\0';
+ for ( test=fondlist; test!=NULL; test=test->next ) {
+ for ( i=0; i<48; ++i )
+ if ( test->psnames[i]!=NULL && strcmp(find,test->psnames[i])==0 ) {
+ *style = (i&3) | ((i&~3)<<1); /* PS styles skip underline bit */
+ *name = copy(test->psnames[i]);
+return( test );
+ }
+ }
+ }
+
+ /* The file may contain multiple families, and each family may contain */
+ /* multiple styles (and each style may contain multiple sizes, but that's */
+ /* not an issue for us here) */
+ names = NULL;
+ for ( i=0; i<2; ++i ) {
+ cnt = 0;
+ for ( test=fondlist; test!=NULL; test=test->next ) if ( test->fondname!=NULL ) {
+ memset(stylesused,0,sizeof(stylesused));
+ for ( j=0; j<test->assoc_cnt; ++j ) {
+ if ( test->assoc[j].size!=0 && !stylesused[test->assoc[j].style]) {
+ stylesused[test->assoc[j].style]=true;
+ if ( names!=NULL ) {
+ names[cnt] = BuildName(test->fondname,test->assoc[j].style);
+ styles[cnt] = test->assoc[j].style;
+ fonds[cnt] = test;
+ }
+ ++cnt;
+ }
+ }
+ }
+ if ( names==NULL ) {
+ names = gcalloc(cnt+1,sizeof(char *));
+ fonds = galloc(cnt*sizeof(FOND *));
+ styles = galloc(cnt*sizeof(int));
+ }
+ }
+
+ if ( find!=NULL ) {
+ for ( which=cnt-1; which>=0; --which )
+ if ( strcmp(names[which],find)==0 )
+ break;
+ if ( which==-1 && strstrmatch(find,test->fondname)!=NULL )
+ which = GuessStyle(find,styles,cnt);
+ if ( which==-1 ) {
+ char *fn = copy(filename);
+ fn[lparen-filename] = '\0';
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_post_error(_("Not in Collection"),_("%s is not in %.100s"),find,fn);
+#endif
+ free(fn);
+ }
+ free(find);
+ } else if ( cnt==1 )
+ which = 0;
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ else if ( no_windowing_ui )
+ which = 0;
+ else
+ which = gwwv_choose(_("Pick a font, any font..."),(const char **) names,cnt,0,
+ _("There are multiple fonts in this file, pick one"));
+#elif defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ else
+ which = 0;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+ if ( which!=-1 ) {
+ fond = fonds[which];
+ *name = copy(names[which]);
+ *style = styles[which];
+ }
+ for ( i=0; i<cnt; ++i )
+ free(names[i]);
+ free(names); free(fonds); free(styles);
+ if ( which==-1 )
+return( NULL );
+
+return( fond );
+}
+
+static SplineFont *SearchBitmapResources(FILE *f,long rlistpos,int subcnt,long rdata_pos,
+ long name_list,char *filename,FOND *fondlist,int flags) {
+ long start = ftell(f);
+ long roff;
+ int rname = -1;
+ int ch1, ch2;
+ int i,j;
+ int res_id;
+ char *name;
+ FOND *fond;
+ int style;
+ SplineFont *sf;
+ int find_id;
+ SplineChar *sc;
+
+ fond = PickFOND(fondlist,filename,&name,&style);
+ if ( fond==NULL )
+return( NULL );
+
+ find_id=-1;
+ if ( flags&ttf_onlyonestrike ) {
+ int biggest = 0;
+ for ( i=0; i<fond->assoc_cnt; ++i ) {
+ if ( fond->assoc[i].style==style && fond->assoc[i].size>biggest ) {
+ biggest = fond->assoc[i].size;
+ find_id = fond->assoc[i].id;
+ }
+ }
+ }
+
+ sf = SplineFontBlank(257);
+ free(sf->fontname); sf->fontname = name;
+ free(sf->familyname); sf->familyname = copy(fond->fondname);
+ sf->fondname = copy(fond->fondname);
+ free(sf->fullname); sf->fullname = copy(name);
+ free(sf->origname); sf->origname = NULL;
+ if ( style & sf_bold ) {
+ free(sf->weight); sf->weight = copy("Bold");
+ }
+ free(sf->copyright); sf->copyright = NULL;
+ free(sf->comments); sf->comments = NULL;
+
+ sf->map = EncMapNew(257,257,FindOrMakeEncoding("mac"));
+
+ for ( i=0; i<fond->stylewidthcnt; ++i ) {
+ if ( fond->stylewidths[i].style == style ) {
+ short *widths = fond->stylewidths[i].widthtab;
+ for ( j=fond->first; j<=fond->last; ++j ) {
+ sc = SFMakeChar(sf,sf->map,j);
+ sc->width = ((widths[j-fond->first]*1000L+(1<<11))>>12);
+ sc->widthset = true;
+ }
+ sc = SplineCharCreate();
+ sc->parent = sf;
+ sc->orig_pos = sf->glyphcnt;
+ sf->glyphs[sf->glyphcnt++] = sc;
+ sc->name = copy(".notdef");
+ sc->width = (widths[fond->last+1-fond->first]*1000L+(1<<11))>>12;
+ sc->widthset = true;
+ }
+ }
+
+ fseek(f,rlistpos,SEEK_SET);
+ for ( i=0; i<subcnt; ++i ) {
+ res_id = getushort(f);
+ rname = (short) getushort(f);
+ /* flags = */ getc(f);
+ ch1 = getc(f); ch2 = getc(f);
+ roff = rdata_pos+((ch1<<16)|(ch2<<8)|getc(f));
+ /* mbz = */ getlong(f);
+ for ( j=fond->assoc_cnt-1; j>=0; --j )
+ if ( (find_id!=-1 && res_id==find_id) ||
+ ( fond->assoc[j].style==style && fond->assoc[j].id==res_id &&
+ fond->assoc[j].size!=0 ) )
+ LoadNFNT(f,roff,sf,fond->assoc[j].size);
+ }
+ fseek(f,start,SEEK_SET);
+
+ sf->onlybitmaps = true;
+ SFOrderBitmapList(sf);
+return( sf );
+}
+
+/* Look for kerning info and merge it into the currently existing font "into" */
+static SplineFont *FindFamilyStyleKerns(SplineFont *into,EncMap *map,FOND *fondlist,char *filename) {
+ char *name;
+ int style;
+ FOND *fond;
+ int i,j;
+ int ch1, ch2, offset;
+ KernPair *kp;
+ SplineChar *sc1, *sc2;
+
+ fond = PickFOND(fondlist,filename,&name,&style);
+ if ( fond==NULL || into==NULL )
+return( NULL );
+ for ( i=0; i<fond->stylekerncnt; ++i )
+ if ( fond->stylekerns[i].style==style )
+ break;
+ if ( i==fond->stylekerncnt ) {
+ LogError(_("No kerning table for %s\n"), name );
+ free(name);
+return( NULL );
+ }
+ for ( j=0; j<fond->stylekerns[i].kernpairs; ++j ) {
+ ch1 = fond->stylekerns[i].kerns[j].ch1;
+ ch2 = fond->stylekerns[i].kerns[j].ch2;
+ offset = (fond->stylekerns[i].kerns[j].offset*(into->ascent+into->descent)+(1<<11))>>12;
+ sc1 = SFMakeChar(into,map,ch1);
+ sc2 = SFMakeChar(into,map,ch2);
+ for ( kp=sc1->kerns; kp!=NULL; kp=kp->next )
+ if ( kp->sc==sc2 )
+ break;
+ if ( kp==NULL ) {
+ uint32 script;
+ kp = chunkalloc(sizeof(KernPair));
+ kp->sc = sc2;
+ kp->next = sc1->kerns;
+ sc1->kerns = kp;
+ script = SCScriptFromUnicode(sc1);
+ if ( script==DEFAULT_SCRIPT )
+ script = SCScriptFromUnicode(sc2);
+ kp->subtable = SFSubTableFindOrMake(sc1->parent,CHR('k','e','r','n'),
+ script, gpos_pair);
+ }
+ kp->off = offset;
+ }
+return( into );
+}
+
+/* Look for a bare truetype font in a binhex/macbinary wrapper */
+static SplineFont *MightBeTrueType(FILE *binary,int32 pos,int32 dlen,int flags,
+ enum openflags openflags) {
+ FILE *temp = tmpfile();
+ char *buffer = galloc(8192);
+ int len;
+ SplineFont *sf;
+
+ if ( flags&ttf_onlynames ) {
+ char **ret;
+ char *temp = TTFGetFontName(binary,pos,pos);
+ if ( temp==NULL )
+return( NULL );
+ ret = galloc(2*sizeof(char *));
+ ret[0] = temp;
+ ret[1] = NULL;
+return( (SplineFont *) ret );
+ }
+
+ fseek(binary,pos,SEEK_SET);
+ while ( dlen>0 ) {
+ len = dlen > 8192 ? 8192 : dlen;
+ len = fread(buffer,1,dlen > 8192 ? 8192 : dlen,binary);
+ if ( len==0 )
+ break;
+ fwrite(buffer,1,len,temp);
+ dlen -= len;
+ }
+ rewind(temp);
+ sf = _SFReadTTF(temp,flags,openflags,NULL,NULL);
+ fclose(temp);
+ free(buffer);
+return( sf );
+}
+
+static SplineFont *IsResourceFork(FILE *f, long offset,char *filename,int flags,
+ enum openflags openflags, SplineFont *into,EncMap *map) {
+ /* If it is a good resource fork then the first 16 bytes are repeated */
+ /* at the location specified in bytes 4-7 */
+ /* We include an offset because if we are looking at a mac binary file */
+ /* the resource fork will actually start somewhere in the middle of the */
+ /* file, not at the beginning */
+ unsigned char buffer[16], buffer2[16];
+ long rdata_pos, map_pos, type_list, name_list, rpos;
+ int32 rdata_len, map_len;
+ unsigned long tag;
+ int i, cnt, subcnt, nfnt_subcnt=0, font_subcnt=0, fond_subcnt=0;
+ SplineFont *sf;
+ uint32 nfnt_pos=0, font_pos=0, fond_pos=0;
+ FOND *fondlist=NULL;
+
+ fseek(f,offset,SEEK_SET);
+ if ( fread(buffer,1,16,f)!=16 )
+return( NULL );
+ rdata_pos = offset + ((buffer[0]<<24)|(buffer[1]<<16)|(buffer[2]<<8)|buffer[3]);
+ map_pos = offset + ((buffer[4]<<24)|(buffer[5]<<16)|(buffer[6]<<8)|buffer[7]);
+ rdata_len = ((buffer[8]<<24)|(buffer[9]<<16)|(buffer[10]<<8)|buffer[11]);
+ map_len = ((buffer[12]<<24)|(buffer[13]<<16)|(buffer[14]<<8)|buffer[15]);
+ if ( rdata_pos+rdata_len!=map_pos || rdata_len==0 )
+return( NULL );
+ fseek(f,map_pos,SEEK_SET);
+ buffer2[15] = buffer[15]+1; /* make it be different */
+ if ( fread(buffer2,1,16,f)!=16 )
+return( NULL );
+
+/* Apple's data fork resources appear to have a bunch of zeroes here instead */
+/* of a copy of the first 16 bytes */
+ for ( i=0; i<16; ++i )
+ if ( buffer2[i]!=0 )
+ break;
+ if ( i!=16 ) {
+ for ( i=0; i<16; ++i )
+ if ( buffer[i]!=buffer2[i] )
+return( NULL );
+ }
+ getlong(f); /* skip the handle to the next resource map */
+ getushort(f); /* skip the file resource number */
+ getushort(f); /* skip the attributes */
+ type_list = map_pos + getushort(f);
+ name_list = map_pos + getushort(f);
+
+ fseek(f,type_list,SEEK_SET);
+ cnt = getushort(f)+1;
+ for ( i=0; i<cnt; ++i ) {
+ tag = getlong(f);
+ /* printf( "%c%c%c%c\n", tag>>24, (tag>>16)&0xff, (tag>>8)&0xff, tag&0xff );*/
+ subcnt = getushort(f)+1;
+ rpos = type_list+getushort(f);
+ sf = NULL;
+ if ( tag==CHR('P','O','S','T') && !(flags&(ttf_onlystrikes|ttf_onlykerns))) /* No FOND */
+ sf = SearchPostscriptResources(f,rpos,subcnt,rdata_pos,name_list,flags);
+ else if ( tag==CHR('s','f','n','t') && !(flags&ttf_onlykerns))
+ sf = SearchTtfResources(f,rpos,subcnt,rdata_pos,name_list,filename,flags,openflags);
+ else if ( tag==CHR('N','F','N','T') ) {
+ nfnt_pos = rpos;
+ nfnt_subcnt = subcnt;
+ } else if ( tag==CHR('F','O','N','T') ) {
+ font_pos = rpos;
+ font_subcnt = subcnt;
+ } else if ( tag==CHR('F','O','N','D') ) {
+ fond_pos = rpos;
+ fond_subcnt = subcnt;
+ }
+ if ( sf!=NULL )
+return( sf );
+ }
+ if ( flags&ttf_onlynames ) /* Not interested in bitmap resources here */
+return( NULL );
+
+ if ( flags&ttf_onlykerns ) { /* For kerns */
+ if ( fond_subcnt!=0 )
+ fondlist = BuildFondList(f,fond_pos,fond_subcnt,rdata_pos,name_list,flags);
+ into = FindFamilyStyleKerns(into,map,fondlist,filename);
+ FondListFree(fondlist);
+return( into );
+ }
+ /* Ok. If no outline font, try for a bitmap */
+ if ( nfnt_subcnt==0 ) {
+ nfnt_pos = font_pos;
+ nfnt_subcnt = font_subcnt;
+ }
+ if ( nfnt_subcnt!=0 ) {
+ if ( fond_subcnt!=0 )
+ fondlist = BuildFondList(f,fond_pos,fond_subcnt,rdata_pos,name_list,flags);
+ sf = SearchBitmapResources(f,nfnt_pos,nfnt_subcnt,rdata_pos,name_list,
+ filename,fondlist,flags);
+ FondListFree(fondlist);
+ if ( sf!=NULL )
+return( sf );
+ }
+return( (SplineFont *) -1 ); /* It's a valid resource file, but just has no fonts */
+}
+
+#if __Mac
+static SplineFont *HasResourceFork(char *filename,int flags,enum openflags openflags,
+ SplineFont *into,EncMap *map) {
+ /* If we're on a mac, we can try to see if we've got a real resource fork */
+ /* (if we do, copy it into a temporary data file and then manipulate that)*/
+ SplineFont *ret;
+ FILE *resfork;
+ char *tempfn=filename, *pt, *lparen, *respath;
+
+ if (( pt=strrchr(filename,'/'))==NULL ) pt = filename;
+ if ( (lparen = strchr(pt,'('))!=NULL && strchr(lparen,')')!=NULL ) {
+ tempfn = copy(filename);
+ tempfn[lparen-filename] = '\0';
+ }
+ respath = galloc(strlen(tempfn)+strlen("/rsrc")+1);
+ strcpy(respath,tempfn);
+ strcat(respath,"/rsrc");
+ resfork = fopen(respath,"r");
+ free(respath);
+ if ( tempfn!=filename )
+ free(tempfn);
+ if ( resfork==NULL )
+return( NULL );
+ ret = IsResourceFork(resfork,0,filename,flags,openflags,into,map);
+ fclose(resfork);
+return( ret );
+}
+#endif
+
+static SplineFont *IsResourceInBinary(FILE *f,char *filename,int flags,
+ enum openflags openflags, SplineFont *into,EncMap *map) {
+ unsigned char header[128];
+ unsigned long offset, dlen, rlen;
+
+ if ( fread(header,1,128,f)!=128 )
+return( NULL );
+ if ( header[0]!=0 || header[74]!=0 || header[82]!=0 || header[1]<=0 ||
+ header[1]>33 || header[63]!=0 || header[2+header[1]]!=0 )
+return( NULL );
+ dlen = ((header[0x53]<<24)|(header[0x54]<<16)|(header[0x55]<<8)|header[0x56]);
+ rlen = ((header[0x57]<<24)|(header[0x58]<<16)|(header[0x59]<<8)|header[0x5a]);
+ /* 128 bytes for header, then the dlen is padded to a 128 byte boundary */
+ offset = 128 + ((dlen+127)&~127);
+/* Look for a bare truetype font in a binhex/macbinary wrapper */
+ if ( dlen!=0 && rlen<=dlen) {
+ int pos = ftell(f);
+ fread(header,1,4,f);
+ header[5] = '\0';
+ if ( strcmp((char *) header,"OTTO")==0 || strcmp((char *) header,"true")==0 ||
+ strcmp((char *) header,"ttcf")==0 ||
+ (header[0]==0 && header[1]==1 && header[2]==0 && header[3]==0))
+return( MightBeTrueType(f,pos,dlen,flags,openflags));
+ }
+return( IsResourceFork(f,offset,filename,flags,openflags,into,map));
+}
+
+static int lastch=0, repeat = 0;
+static void outchr(FILE *binary, int ch) {
+ int i;
+
+ if ( repeat ) {
+ if ( ch==0 ) {
+ /* no repeat, output a literal 0x90 (the repeat flag) */
+ lastch=0x90;
+ putc(lastch,binary);
+ } else {
+ for ( i=1; i<ch; ++i )
+ putc(lastch,binary);
+ }
+ repeat = 0;
+ } else if ( ch==0x90 ) {
+ repeat = 1;
+ } else {
+ putc(ch,binary);
+ lastch = ch;
+ }
+}
+
+static SplineFont *IsResourceInHex(FILE *f,char *filename,int flags,enum openflags openflags,
+ SplineFont *into,EncMap *map) {
+ /* convert file from 6bit to 8bit */
+ /* interesting data is enclosed between two colons */
+ FILE *binary = tmpfile();
+ char *sixbit = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
+ int ch, val, cnt, i, dlen, rlen;
+ unsigned char header[20]; char *pt;
+ SplineFont *ret;
+
+ if ( binary==NULL ) {
+ LogError( _("can't create temporary file\n") );
+return( NULL );
+ }
+
+ lastch = repeat = 0;
+ while ( (ch=getc(f))!=':' ); /* There may be comments before file start */
+ cnt = val = 0;
+ while ( (ch=getc(f))!=':' ) {
+ if ( Isspace(ch))
+ continue;
+ for ( pt=sixbit; *pt!=ch && *pt!='\0'; ++pt );
+ if ( *pt=='\0' ) {
+ fclose(binary);
+return( NULL );
+ }
+ val = (val<<6) | (pt-sixbit);
+ if ( ++cnt==4 ) {
+ outchr(binary,(val>>16)&0xff);
+ outchr(binary,(val>>8)&0xff);
+ outchr(binary,val&0xff);
+ val = cnt = 0;
+ }
+ }
+ if ( cnt!=0 ) {
+ if ( cnt==1 )
+ outchr(binary,val<<2);
+ else if ( cnt==2 ) {
+ val<<=4;
+ outchr(binary,(val>>8)&0xff);
+ outchr(binary,val&0xff);
+ } else if ( cnt==3 ) {
+ val<<=6;
+ outchr(binary,(val>>16)&0xff);
+ outchr(binary,(val>>8)&0xff);
+ outchr(binary,val&0xff);
+ }
+ }
+
+ rewind(binary);
+ ch = getc(binary); /* Name length */
+ /* skip name */
+ for ( i=0; i<ch; ++i )
+ getc(binary);
+ if ( getc(binary)!='\0' ) {
+ fclose(binary);
+return( NULL );
+ }
+ fread(header,1,20,binary);
+ dlen = (header[10]<<24)|(header[11]<<16)|(header[12]<<8)|header[13];
+ rlen = (header[14]<<24)|(header[15]<<16)|(header[16]<<8)|header[17];
+/* Look for a bare truetype font in a binhex/macbinary wrapper */
+ if ( dlen!=0 && rlen<dlen ) {
+ int pos = ftell(binary);
+ fread(header,1,4,binary);
+ header[5] = '\0';
+ if ( strcmp((char *) header,"OTTO")==0 || strcmp((char *) header,"true")==0 ||
+ strcmp((char *) header,"ttcf")==0 ||
+ (header[0]==0 && header[1]==1 && header[2]==0 && header[3]==0)) {
+ ret = MightBeTrueType(binary,pos,dlen,flags,openflags);
+ fclose(binary);
+return( ret );
+ }
+ }
+ if ( rlen==0 ) {
+ fclose(binary);
+return( NULL );
+ }
+
+ ret = IsResourceFork(binary,ftell(binary)+dlen+2,filename,flags,openflags,into,map);
+
+ fclose(binary);
+return( ret );
+}
+
+static SplineFont *IsResourceInFile(char *filename,int flags,enum openflags openflags,
+ SplineFont *into, EncMap *map) {
+ FILE *f;
+ char *spt, *pt;
+ SplineFont *sf;
+ char *temp=filename, *lparen;
+
+ if (( pt=strrchr(filename,'/'))==NULL ) pt = filename;
+ if ( (lparen = strchr(pt,'('))!=NULL && strchr(lparen,')')!=NULL ) {
+ temp = copy(filename);
+ temp[lparen-filename] = '\0';
+ }
+ f = fopen(temp,"rb");
+ if ( temp!=filename ) free(temp);
+ if ( f==NULL )
+return( NULL );
+ spt = strrchr(filename,'/');
+ if ( spt==NULL ) spt = filename;
+ pt = strrchr(spt,'.');
+ if ( pt!=NULL && (pt[1]=='b' || pt[1]=='B') && (pt[2]=='i' || pt[2]=='I') &&
+ (pt[3]=='n' || pt[3]=='N') && (pt[4]=='\0' || pt[4]=='(') ) {
+ if ( (sf = IsResourceInBinary(f,filename,flags,openflags,into,map))) {
+ fclose(f);
+return( sf );
+ }
+ } else if ( pt!=NULL && (pt[1]=='h' || pt[1]=='H') && (pt[2]=='q' || pt[2]=='Q') &&
+ (pt[3]=='x' || pt[3]=='X') && (pt[4]=='\0' || pt[4]=='(')) {
+ if ( (sf = IsResourceInHex(f,filename,flags,openflags,into,map))) {
+ fclose(f);
+return( sf );
+ }
+ }
+
+ sf = IsResourceFork(f,0,filename,flags,openflags,into,map);
+ fclose(f);
+#if __Mac
+ if ( sf==NULL )
+ sf = HasResourceFork(filename,flags,openflags,into,map);
+#endif
+return( sf );
+}
+
+static SplineFont *FindResourceFile(char *filename,int flags,enum openflags openflags,
+ SplineFont *into,EncMap *map) {
+ char *spt, *pt, *dpt;
+ char buffer[1400];
+ SplineFont *sf;
+
+ if ( (sf = IsResourceInFile(filename,flags,openflags,into,map)))
+return( sf );
+
+ /* Well, look in the resource fork directory (if it exists), the resource */
+ /* fork is placed there in a seperate file on (some) non-Mac disks */
+ strcpy(buffer,filename);
+ spt = strrchr(buffer,'/');
+ if ( spt==NULL ) { spt = buffer; pt = filename; }
+ else { ++spt; pt = filename + (spt-buffer); }
+ strcpy(spt,"resource.frk/");
+ strcat(spt,pt);
+ if ( (sf=IsResourceInFile(buffer,flags,openflags,into,map)))
+return( sf );
+
+ /* however the resource fork does not appear to do long names properly */
+ /* names are always lower case 8.3, do some simple things to check */
+ spt = strrchr(buffer,'/')+1;
+ for ( pt=spt; *pt; ++pt )
+ if ( Isupper( *pt ))
+ *pt = Tolower( *pt );
+ dpt = strchr(spt,'.');
+ if ( dpt==NULL ) dpt = spt+strlen(spt);
+ if ( dpt-spt>8 || strlen(dpt)>4 ) {
+ char exten[8];
+ strncpy(exten,dpt,7);
+ exten[4] = '\0'; /* it includes the dot */
+ if ( dpt-spt>6 )
+ dpt = spt+6;
+ *dpt++ = '~';
+ *dpt++ = '1';
+ strcpy(dpt,exten);
+ }
+return( IsResourceInFile(buffer,flags,openflags,into,map));
+}
+
+SplineFont *SFReadMacBinary(char *filename,int flags,enum openflags openflags) {
+ SplineFont *sf = FindResourceFile(filename,flags,openflags,NULL,NULL);
+
+ if ( sf==NULL )
+ LogError( _("Couldn't find a font file named %s\n"), filename );
+ else if ( sf==(SplineFont *) (-1) ) {
+ LogError( _("%s is a mac resource file but contains no postscript or truetype fonts\n"), filename );
+ sf = NULL;
+ }
+return( sf );
+}
+
+#ifdef LUA_FF_LIB
+SplineFont *SFReadMacBinaryInfo(char *filename,int flags,enum openflags openflags) {
+ SplineFont *sf = FindResourceFile(filename,flags,openflags,NULL,NULL);
+
+ if ( sf==NULL )
+ LogError( _("Couldn't find a font file named %s\n"), filename );
+ else if ( sf==(SplineFont *) (-1) ) {
+ LogError( _("%s is a mac resource file but contains no postscript or truetype fonts\n"), filename );
+ sf = NULL;
+ }
+return( sf );
+}
+#endif
+
+int LoadKerningDataFromMacFOND(SplineFont *sf, char *filename,EncMap *map) {
+ if ( FindResourceFile(filename,ttf_onlykerns,0,sf,map)==NULL )
+return ( false );
+
+return( true );
+}
+
+char **NamesReadMacBinary(char *filename) {
+return( (char **) FindResourceFile(filename,ttf_onlynames,0,NULL,NULL));
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/macenc.c b/Build/source/libs/luafontforge/fontforge/fontforge/macenc.c
new file mode 100644
index 00000000000..b1518e9099a
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/macenc.c
@@ -0,0 +1,3601 @@
+/* Copyright (C) 2003-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaeditui.h"
+#include <gkeysym.h>
+#include <ustring.h>
+
+/*
+ The original data for these mappings may be found at
+ http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/
+ unfortunately this site does not contain all the macintosh encodings
+ so we leave some blank
+*/
+/* Response (indirectly) from charsets@apple.com when asked about the missing
+ encodings:
+
+ > I don't believe any of those additional scripts are actually
+ > defined as character encodings. He can safely ignore anything
+ > that's not in the Apple folder on the Unicode site.
+ >
+ > I monitor charsets@apple.com and don't recall seeing any e-mail
+ > on this subject. It's possible it got lost in the voluminous
+ > spam the address receives.
+ >
+ > Deborah
+ I find this perplexing (unless the script is defined but unused, how can
+ it fail to have a defined encoding), but will accept it.
+*/
+
+/* Macintosh 1 byte encodings */
+static unichar_t arabic[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x00c4, 0x00a0, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
+ 0x00e0, 0x00e2, 0x00e4, 0x06ba, 0x00ab, 0x00e7, 0x00e9, 0x00e8,
+ 0x00ea, 0x00eb, 0x00ed, 0x2026, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
+ 0x00bb, 0x00f4, 0x00f6, 0x00f7, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x066a, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x060c, 0x002d, 0x002e, 0x002f,
+ 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667,
+ 0x0668, 0x0669, 0x003a, 0x061b, 0x003c, 0x003d, 0x003e, 0x061f,
+ 0x274a, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
+ 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f,
+ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637,
+ 0x0638, 0x0639, 0x063a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647,
+ 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f,
+ 0x0650, 0x0651, 0x0652, 0x067e, 0x0679, 0x0686, 0x06d5, 0x06a4,
+ 0x06af, 0x0688, 0x0691, 0x007b, 0x007c, 0x007d, 0x0698, 0x06d2
+};
+
+static unichar_t centeuro[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x00c4, 0x0100, 0x0101, 0x00c9, 0x0104, 0x00d6, 0x00dc, 0x00e1,
+ 0x0105, 0x010c, 0x00e4, 0x010d, 0x0106, 0x0107, 0x00e9, 0x0179,
+ 0x017a, 0x010e, 0x00ed, 0x010f, 0x0112, 0x0113, 0x0116, 0x00f3,
+ 0x0117, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x011a, 0x011b, 0x00fc,
+ 0x2020, 0x00b0, 0x0118, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
+ 0x00ae, 0x00a9, 0x2122, 0x0119, 0x00a8, 0x2260, 0x0123, 0x012e,
+ 0x012f, 0x012a, 0x2264, 0x2265, 0x012b, 0x0136, 0x2202, 0x2211,
+ 0x0142, 0x013b, 0x013c, 0x013d, 0x013e, 0x0139, 0x013a, 0x0145,
+ 0x0146, 0x0143, 0x00ac, 0x221a, 0x0144, 0x0147, 0x2206, 0x00ab,
+ 0x00bb, 0x2026, 0x00a0, 0x0148, 0x0150, 0x00d5, 0x0151, 0x014c,
+ 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
+ 0x014d, 0x0154, 0x0155, 0x0158, 0x2039, 0x203a, 0x0159, 0x0156,
+ 0x0157, 0x0160, 0x201a, 0x201e, 0x0161, 0x015a, 0x015b, 0x00c1,
+ 0x0164, 0x0165, 0x00cd, 0x017d, 0x017e, 0x016a, 0x00d3, 0x00d4,
+ 0x016b, 0x016e, 0x00da, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173,
+ 0x00dd, 0x00fd, 0x0137, 0x017b, 0x0141, 0x017c, 0x0122, 0x02c7
+};
+
+static unichar_t croatian[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
+ 0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
+ 0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
+ 0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
+ 0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
+ 0x00ae, 0x0160, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x017d, 0x00d8,
+ 0x221e, 0x00b1, 0x2264, 0x2265, 0x2206, 0x00b5, 0x2202, 0x2211,
+ 0x220f, 0x0161, 0x222b, 0x00aa, 0x00ba, 0x03a9, 0x017e, 0x00f8,
+ 0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x0106, 0x00ab,
+ 0x010c, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153,
+ 0x0110, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
+ 0xf8ff, 0x00a9, 0x2044, 0x20ac, 0x2039, 0x203a, 0x00c6, 0x00bb,
+ 0x2013, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x0107, 0x00c1,
+ 0x010d, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4,
+ 0x0111, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc,
+ 0x00af, 0x03c0, 0x00cb, 0x02da, 0x00b8, 0x00ca, 0x00e6, 0x02c7
+};
+
+static unichar_t cyrillic[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+ 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+ 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
+ 0x2020, 0x00b0, 0x0490, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x0406,
+ 0x00ae, 0x00a9, 0x2122, 0x0402, 0x0452, 0x2260, 0x0403, 0x0453,
+ 0x221e, 0x00b1, 0x2264, 0x2265, 0x0456, 0x00b5, 0x0491, 0x0408,
+ 0x0404, 0x0454, 0x0407, 0x0457, 0x0409, 0x0459, 0x040a, 0x045a,
+ 0x0458, 0x0405, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
+ 0x00bb, 0x2026, 0x00a0, 0x040b, 0x045b, 0x040c, 0x045c, 0x0455,
+ 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x201e,
+ 0x040e, 0x045e, 0x040f, 0x045f, 0x2116, 0x0401, 0x0451, 0x044f,
+ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+ 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x20ac
+};
+
+static unichar_t devanagari[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x00d7, 0x2212, 0x2013, 0x2014, 0x2018, 0x2019, 0x2026, 0x2022,
+ 0x00a9, 0x00ae, 0x2122, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0965, 0x0970, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x0901, 0x0902, 0x0903, 0x0905, 0x0906, 0x0907, 0x0908,
+ 0x0909, 0x090a, 0x090b, 0x090e, 0x090f, 0x0910, 0x090d, 0x0912,
+ 0x0913, 0x0914, 0x0911, 0x0915, 0x0916, 0x0917, 0x0918, 0x0919,
+ 0x091a, 0x091b, 0x091c, 0x091d, 0x091e, 0x091f, 0x0920, 0x0921,
+ 0x0922, 0x0923, 0x0924, 0x0925, 0x0926, 0x0927, 0x0928, 0x0929,
+ 0x092a, 0x092b, 0x092c, 0x092d, 0x092e, 0x092f, 0x095f, 0x0930,
+ 0x0931, 0x0932, 0x0933, 0x0934, 0x0935, 0x0936, 0x0937, 0x0938,
+ 0x0939, 0x200e, 0x093e, 0x093f, 0x0940, 0x0941, 0x0942, 0x0943,
+ 0x0946, 0x0947, 0x0948, 0x0945, 0x094a, 0x094b, 0x094c, 0x0949,
+ 0x094d, 0x093c, 0x0964, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x00f0, 0x0966, 0x0967, 0x0968, 0x0969, 0x096a, 0x096b, 0x096c,
+ 0x096d, 0x096e, 0x096f,
+};
+
+static unichar_t farsi[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x00c4, 0x00a0, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
+ 0x00e0, 0x00e2, 0x00e4, 0x06ba, 0x00ab, 0x00e7, 0x00e9, 0x00e8,
+ 0x00ea, 0x00eb, 0x00ed, 0x2026, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
+ 0x00bb, 0x00f4, 0x00f6, 0x00f7, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x066a, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x060c, 0x002d, 0x002e, 0x002f,
+ 0x06f0, 0x06f1, 0x06f2, 0x06f3, 0x06f4, 0x06f5, 0x06f6, 0x06f7,
+ 0x06f8, 0x06f9, 0x003a, 0x061b, 0x003c, 0x003d, 0x003e, 0x061f,
+ 0x274a, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
+ 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f,
+ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637,
+ 0x0638, 0x0639, 0x063a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647,
+ 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f,
+ 0x0650, 0x0651, 0x0652, 0x067e, 0x0679, 0x0686, 0x06d5, 0x06a4,
+ 0x06af, 0x0688, 0x0691, 0x007b, 0x007c, 0x007d, 0x0698, 0x06d2
+};
+
+static unichar_t greek[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x00c4, 0x00b9, 0x00b2, 0x00c9, 0x00b3, 0x00d6, 0x00dc, 0x0385,
+ 0x00e0, 0x00e2, 0x00e4, 0x0384, 0x00a8, 0x00e7, 0x00e9, 0x00e8,
+ 0x00ea, 0x00eb, 0x00a3, 0x2122, 0x00ee, 0x00ef, 0x2022, 0x00bd,
+ 0x2030, 0x00f4, 0x00f6, 0x00a6, 0x20ac, 0x00f9, 0x00fb, 0x00fc,
+ 0x2020, 0x0393, 0x0394, 0x0398, 0x039b, 0x039e, 0x03a0, 0x00df,
+ 0x00ae, 0x00a9, 0x03a3, 0x03aa, 0x00a7, 0x2260, 0x00b0, 0x00b7,
+ 0x0391, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x0392, 0x0395, 0x0396,
+ 0x0397, 0x0399, 0x039a, 0x039c, 0x03a6, 0x03ab, 0x03a8, 0x03a9,
+ 0x03ac, 0x039d, 0x00ac, 0x039f, 0x03a1, 0x2248, 0x03a4, 0x00ab,
+ 0x00bb, 0x2026, 0x00a0, 0x03a5, 0x03a7, 0x0386, 0x0388, 0x0153,
+ 0x2013, 0x2015, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x0389,
+ 0x038a, 0x038c, 0x038e, 0x03ad, 0x03ae, 0x03af, 0x03cc, 0x038f,
+ 0x03cd, 0x03b1, 0x03b2, 0x03c8, 0x03b4, 0x03b5, 0x03c6, 0x03b3,
+ 0x03b7, 0x03b9, 0x03be, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03bf,
+ 0x03c0, 0x03ce, 0x03c1, 0x03c3, 0x03c4, 0x03b8, 0x03c9, 0x03c2,
+ 0x03c7, 0x03c5, 0x03b6, 0x03ca, 0x03cb, 0x0390, 0x03b0, 0x00ad
+};
+
+static unichar_t gujarati[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x00d7, 0x2212, 0x2013, 0x2014, 0x2018, 0x2019, 0x2026, 0x2022,
+ 0x00a9, 0x00ae, 0x2122, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0965, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x0a81, 0x0a82, 0x0a83, 0x0a85, 0x0a86, 0x0a87, 0x0a88,
+ 0x0a89, 0x0a8a, 0x0a8b, 0x00ab, 0x0a8f, 0x0a90, 0x0a8d, 0x00af,
+ 0x0a93, 0x0a94, 0x0a91, 0x0a95, 0x0a96, 0x0a97, 0x0a98, 0x0a99,
+ 0x0a9a, 0x0a9b, 0x0a9c, 0x0a9d, 0x0a9e, 0x0a9f, 0x0aa0, 0x0aa1,
+ 0x0aa2, 0x0aa3, 0x0aa4, 0x0aa5, 0x0aa6, 0x0aa7, 0x0aa8, 0x00c7,
+ 0x0aaa, 0x0aab, 0x0aac, 0x0aad, 0x0aae, 0x0aaf, 0x00ce, 0x0ab0,
+ 0x00d0, 0x0ab2, 0x0ab3, 0x00d3, 0x0ab5, 0x0ab6, 0x0ab7, 0x0ab8,
+ 0x0ab9, 0x200e, 0x0abe, 0x0abf, 0x0ac0, 0x0ac1, 0x0ac2, 0x0ac3,
+ 0x00e0, 0x0ac7, 0x0ac8, 0x0ac5, 0x00e4, 0x0acb, 0x0acc, 0x0ac9,
+ 0x0acd, 0x0abc, 0x0964, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x00f0, 0x0ae6, 0x0ae7, 0x0ae8, 0x0ae9, 0x0aea, 0x0aeb, 0x0aec,
+ 0x0aed, 0x0aee, 0x0aef,
+};
+
+static unichar_t gurmukhi[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x00d7, 0x2212, 0x2013, 0x2014, 0x2018, 0x2019, 0x2026, 0x2022,
+ 0x00a9, 0x00ae, 0x2122, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0a71, 0x0a5c, 0x0a73, 0x0a72, 0x0a74, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x00a1, 0x0a02, 0x00a3, 0x0a05, 0x0a06, 0x0a07, 0x0a08,
+ 0x0a09, 0x0a0a, 0x00aa, 0x00ab, 0x0a0f, 0x0a10, 0x00ae, 0x00af,
+ 0x0a13, 0x0a14, 0x00b2, 0x0a15, 0x0a16, 0x0a17, 0x0a18, 0x0a19,
+ 0x0a1a, 0x0a1b, 0x0a1c, 0x0a1d, 0x0a1e, 0x0a1f, 0x0a20, 0x0a21,
+ 0x0a22, 0x0a23, 0x0a24, 0x0a25, 0x0a26, 0x0a27, 0x0a28, 0x00c7,
+ 0x0a2a, 0x0a2b, 0x0a2c, 0x0a2d, 0x0a2e, 0x0a2f, 0x00ce, 0x0a30,
+ 0x00d0, 0x0a32, 0x00d2, 0x00d3, 0x0a35, 0xf860, 0x00d6, 0x0a38,
+ 0x0a39, 0x200e, 0x0a3e, 0x0a3f, 0x0a40, 0x0a41, 0x0a42, 0x00df,
+ 0x00e0, 0x0a47, 0x0a48, 0x00e3, 0x00e4, 0x0a4b, 0x0a4c, 0x00e7,
+ 0x0a4d, 0x0a3c, 0x0964, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x00f0, 0x0a66, 0x0a67, 0x0a68, 0x0a69, 0x0a6a, 0x0a6b, 0x0a6c,
+ 0x0a6d, 0x0a6e, 0x0a6f,
+};
+
+static unichar_t hebrew[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x00c4, 0x05f2, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
+ 0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
+ 0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
+ 0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x20aa, 0x0027,
+ 0x0029, 0x0028, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0xf86a, 0x201e, 0xf89b, 0xf89c, 0xf89d, 0xf89e, 0x05bc, 0xfb4b,
+ 0xfb35, 0x2026, 0x00a0, 0x05b8, 0x05b7, 0x05b5, 0x05b6, 0x05b4,
+ 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xfb2a, 0xfb2b,
+ 0x05bf, 0x05b0, 0x05b2, 0x05b1, 0x05bb, 0x05b9, 0x05b8, 0x05b3,
+ 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7,
+ 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df,
+ 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7,
+ 0x05e8, 0x05e9, 0x05ea, 0x007d, 0x005d, 0x007b, 0x005b, 0x007c
+};
+
+static unichar_t iceland[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
+ 0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
+ 0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
+ 0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
+ 0x00dd, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
+ 0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8,
+ 0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211,
+ 0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x03a9, 0x00e6, 0x00f8,
+ 0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
+ 0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153,
+ 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
+ 0x00ff, 0x0178, 0x2044, 0x20ac, 0x00d0, 0x00f0, 0x00de, 0x00fe,
+ 0x00fd, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1,
+ 0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4,
+ 0xf8ff, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc,
+ 0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7
+};
+
+static unichar_t romanian[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
+ 0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
+ 0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
+ 0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
+ 0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
+ 0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x0102, 0x0218,
+ 0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211,
+ 0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x03a9, 0x0103, 0x0219,
+ 0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
+ 0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153,
+ 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
+ 0x00ff, 0x0178, 0x2044, 0x20ac, 0x2039, 0x203a, 0x021a, 0x021b,
+ 0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1,
+ 0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4,
+ 0xf8ff, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc,
+ 0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7
+};
+
+unichar_t MacRomanEnc[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
+ 0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
+ 0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
+ 0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
+ 0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
+ 0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8,
+ 0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211,
+ 0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x03a9, 0x00e6, 0x00f8,
+ 0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
+ 0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153,
+ 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
+ 0x00ff, 0x0178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
+ 0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1,
+ 0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4,
+ 0xf8ff, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc,
+ 0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7
+};
+
+static unichar_t thai[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x00ab, 0x00bb, 0x2026, 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c,
+ 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x201c, 0x201d, 0x0e4d,
+ 0x0090, 0x2022, 0x0e31, 0x0e47, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
+ 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x2018, 0x2019, 0x009f,
+ 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
+ 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
+ 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
+ 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
+ 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
+ 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
+ 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
+ 0x0e38, 0x0e39, 0x0e3a, 0x2060, 0x200b, 0x2013, 0x2014, 0x0e3f,
+ 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
+ 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x2122, 0x0e4f,
+ 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
+ 0x0e58, 0x0e59, 0x00ae, 0x00a9,
+};
+
+static unichar_t turkish[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
+ 0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
+ 0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
+ 0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
+ 0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
+ 0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8,
+ 0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211,
+ 0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x03a9, 0x00e6, 0x00f8,
+ 0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
+ 0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153,
+ 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
+ 0x00ff, 0x0178, 0x011e, 0x011f, 0x0130, 0x0131, 0x015e, 0x015f,
+ 0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1,
+ 0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4,
+ 0xf8ff, 0x00d2, 0x00da, 0x00db, 0x00d9, 0xf8a0, 0x02c6, 0x02dc,
+ 0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7
+};
+
+enum script_codes {
+ sm_roman, sm_japanese, sm_tradchinese, sm_korean,
+ sm_arabic, sm_hebrew, sm_greek, sm_cyrillic,
+ sm_rsymbol, sm_devanagari, sm_gurmukhi, sm_gujarati,
+ sm_oriya, sm_bengali, sm_tamil, sm_telugu,
+ sm_kannada, sm_malayalam, sm_sinhalese, sm_burmese,
+ sm_khmer, sm_thai, sm_laotian, sm_georgian,
+ sm_armenian, sm_simpchinese, sm_tibetan, sm_mongolian,
+ sm_geez, sm_slavic, sm_vietnamese, sm_sindhi,
+ sm_max };
+
+static unichar_t *macencodings[] = {
+ MacRomanEnc,
+ NULL/*Essentially SJIS*/,
+ NULL/*Essentially Big 5*/,
+ NULL/*Essentially Wansung*/,
+ arabic,
+ hebrew,
+ greek,
+ cyrillic,
+ NULL, /* rsymbol, whatever that is */
+ devanagari,
+/*10*/ gurmukhi,
+ gujarati,
+ NULL, /* oriya */
+ NULL, /* bengali */
+ NULL, /* Tamil */
+ NULL, /* Telugu */
+ NULL, /* Kannada */
+ NULL, /* Malayalam */
+ NULL, /* Sinhalese */
+ NULL, /* Burmese */
+/*20*/ NULL, /* Khmer */
+ thai,
+ NULL, /* Lao */
+ NULL, /* Georgian */
+ NULL, /* Armenian */
+/*25*/ NULL,/* SimpChinese, GB2312 offset by 0x8080 to 0xa1a1 */
+ NULL, /* Tibetan */
+ NULL, /* Mongolian */
+ NULL, /* Geex/Ethiopic */
+ centeuro, /* Baltic/Slavic */
+/*30*/ NULL, /* Vietnamese */
+ NULL, /* Extended Arabic for Sindhi */
+ NULL /* Uninterpretted */
+};
+
+/* The icelandic encoding also uses 0 (mac roman) encoding even though it's not*/
+/* The turkish encoding also uses 0 (mac roman) encoding even though it's not*/
+/* The croatian encoding also uses 0 (mac roman) encoding even though it's not*/
+/* The romanian encoding also uses 0 (mac roman) encoding even though it's not*/
+
+/* I've no idea what encoding code farsi uses, it isn't documented to be arabic 4, nor is it documented to have its own code */
+
+static uint8 _MacScriptFromLanguage[] = {
+ sm_roman, /* English */
+ sm_roman, /* French */
+ sm_roman, /* German */
+ sm_roman, /* Italian */
+ sm_roman, /* Dutch */
+ sm_roman, /* Swedish */
+ sm_roman, /* Spanish */
+ sm_roman, /* Danish */
+ sm_roman, /* Portuguese */
+ sm_roman, /* Norwegian */
+/*10*/ sm_hebrew, /* Hebrew */
+ sm_japanese, /* Japanese */
+ sm_arabic, /* Arabic */
+ sm_roman, /* Finnish */
+ sm_greek, /* Greek */
+ sm_roman, /* Icelandic */ /* Modified roman */
+ sm_roman, /* Maltese */
+ sm_roman, /* Turkish */ /* Modified roman */
+ sm_roman, /* Croatian */ /* Modified roman */
+ sm_tradchinese, /* Traditional Chinese */
+/*20*/ sm_arabic, /* Urdu (I assume arabic) */
+ sm_devanagari, /* Hindi (I assume) */
+ sm_thai, /* Thai */
+ sm_korean, /* Korean */
+ sm_slavic, /* Lithuanian */
+ sm_slavic, /* Polish */
+ sm_slavic, /* Hungarian */
+ sm_slavic, /* Estonian */
+ sm_slavic, /* Latvian */
+ sm_roman, /* Sami (Lappish) */
+/*30*/ sm_roman, /* Faroese (Icelandic) */ /* Modified roman */
+ sm_arabic, /* Farsi/Persian */ /* Modified Arabic */
+ sm_cyrillic, /* Russian */
+ sm_simpchinese, /* Simplified Chinese */
+ sm_roman, /* Flemish */
+ sm_roman, /* Irish Gaelic */
+ sm_roman, /* albanian (???) */
+ sm_roman, /* Romanian */ /* Modified roman */
+ sm_slavic, /* Czech */
+ sm_slavic, /* Slovak */
+/*40*/ sm_slavic, /* Slovenian */
+ sm_roman, /* Yiddish */
+ sm_cyrillic, /* Serbian */
+ sm_cyrillic, /* Macedonian */
+ sm_cyrillic, /* Bulgarian */
+ sm_cyrillic, /* Ukrainian */
+ sm_cyrillic, /* Byelorussian */
+ sm_cyrillic, /* Uzbek */
+ sm_cyrillic, /* Kazakh */
+ sm_cyrillic, /* Axerbaijani (Cyrillic) */
+/*50*/ sm_arabic, /* Axerbaijani (Arabic) */
+ sm_armenian, /* Armenian */
+ sm_georgian, /* Georgian */
+ sm_cyrillic, /* Moldavian */
+ sm_cyrillic, /* Kirghiz */
+ sm_cyrillic, /* Tajiki */
+ sm_cyrillic, /* Turkmen */
+ sm_mongolian, /* Mongolian (Mongolian) */
+ sm_cyrillic, /* Mongolian (cyrillic) */
+ sm_arabic, /* Pashto */
+/*60*/ sm_arabic, /* Kurdish */
+ sm_devanagari, /* Kashmiri (???) */
+ sm_sindhi, /* Sindhi */
+ sm_tibetan, /* Tibetan */
+ sm_tibetan, /* Nepali (???) */
+ sm_devanagari, /* Sanskrit */
+ sm_devanagari, /* Marathi */
+ sm_bengali, /* Bengali */
+ sm_bengali, /* Assamese (???) */
+ sm_gujarati, /* Gujarati */
+/*70*/ sm_gujarati, /* Punjabi (???) */
+ sm_oriya, /* Oriya */
+ sm_malayalam, /* Malayalam */
+ sm_kannada, /* Kannada */
+ sm_tamil, /* Tamil */
+ sm_telugu, /* Telugu */
+ sm_sinhalese, /* Sinhalese */
+ sm_burmese, /* Burmese */
+ sm_khmer, /* Khmer */
+ sm_laotian, /* Lao */
+/*80*/ sm_vietnamese, /* Vietnamese */
+ sm_arabic, /* Indonesian */
+ sm_roman, /* Tagalog (???) */
+ sm_roman, /* Malay (roman) */
+ sm_arabic, /* Malay (arabic) */
+ sm_roman, /* Amharic (???) */
+ sm_roman, /* Tigrinya (???) */
+ sm_roman, /* Galla (???) */
+ sm_roman, /* Somali (???) */
+ sm_roman, /* Swahili (???) */
+/*90*/ sm_roman, /* Kinyarwanda/Ruanda (???) */
+ sm_roman, /* Rundi (???) */
+ sm_roman, /* Nyanja/Chewa (???) */
+ sm_roman, /* Malagasy */
+/*94*/ sm_roman, /* Esperanto */
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+/*100*/ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+/*110*/ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+/*120*/ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+/*128*/ sm_roman, /* Welsh */
+ sm_roman, /* Basque */
+/*130*/ sm_roman, /* Catalan */
+ sm_roman, /* Latin */
+ sm_roman, /* Quechua (???) */
+ sm_roman, /* Guarani (???) */
+ sm_roman, /* Aymara (???) */
+ sm_cyrillic, /* Tatar (???) */
+ sm_cyrillic, /* Uighur (???) */
+ sm_cyrillic, /* Dzongkha (???) */
+ sm_roman, /* Javanese (roman) */
+ sm_roman, /* Sundanese (roman) */
+/*140*/ sm_roman, /* Galician */
+ sm_roman, /* Afrikaans */
+ sm_roman, /* Breton */
+ sm_roman, /* Inuktitut */
+ sm_roman, /* Scottish Gaelic */
+ sm_roman, /* Manx Gaelic */
+ sm_roman, /* Irish Gaelic (with dot) */
+ sm_roman, /* Tongan */
+ sm_greek, /* Greek (polytonic) */
+ sm_roman, /* Greenlandic */ /* Presumably icelandic? */
+/*150*/ sm_roman, /* Azebaijani (roman) */
+ 0xff
+};
+
+static uint16 _WinLangFromMac[] = {
+ 0x409, /* English */
+ 0x40c, /* French */
+ 0x407, /* German */
+ 0x410, /* Italian */
+ 0x413, /* Dutch */
+ 0x41d, /* Swedish */
+ 0x40a, /* Spanish */
+ 0x406, /* Danish */
+ 0x416, /* Portuguese */
+ 0x414, /* Norwegian */
+/*10*/ 0x40d, /* Hebrew */
+ 0x411, /* Japanese */
+ 0x401, /* Arabic */
+ 0x40b, /* Finnish */
+ 0x408, /* Greek */
+ 0x40f, /* Icelandic */
+ 0x43a, /* Maltese */
+ 0x41f, /* Turkish */
+ 0x41a, /* Croatian */
+ 0x404, /* Traditional Chinese */
+/*20*/ 0x420, /* Urdu */
+ 0x439, /* Hindi */
+ 0x41e, /* Thai */
+ 0x412, /* Korean */
+ 0x427, /* Lithuanian */
+ 0x415, /* Polish */
+ 0x40e, /* Hungarian */
+ 0x425, /* Estonian */
+ 0x426, /* Latvian */
+ 0x43b, /* Sami (Lappish) */
+/*30*/ 0x438, /* Faroese (Icelandic) */
+ 0x429, /* Farsi/Persian */
+ 0x419, /* Russian */
+ 0x804, /* Simplified Chinese */
+ 0x813, /* Flemish */
+ 0x43c, /* Irish Gaelic */
+ 0x41c, /* albanian */
+ 0x418, /* Romanian */
+ 0x405, /* Czech */
+ 0x41b, /* Slovak */
+/*40*/ 0x424, /* Slovenian */
+ 0x43d, /* Yiddish */
+ 0xc1a, /* Serbian */
+ 0x42f, /* Macedonian */
+ 0x402, /* Bulgarian */
+ 0x422, /* Ukrainian */
+ 0x423, /* Byelorussian */
+ 0x843, /* Uzbek */
+ 0x43f, /* Kazakh */
+ 0x42c, /* Azerbaijani (Cyrillic) */
+/*50*/ 0x82c, /* Azerbaijani (Arabic) */
+ 0x42b, /* Armenian */
+ 0x437, /* Georgian */
+ 0x818, /* Moldavian */
+ 0x440, /* Kirghiz */
+ 0x428, /* Tajiki */
+ 0x442, /* Turkmen */
+ 0x450, /* Mongolian (Mongolian) */
+ 0x850, /* Mongolian (cyrillic) */
+ 0x463, /* Pashto */
+/*60*/ 0xffff, /* Kurdish */
+ 0x860, /* Kashmiri */
+ 0x459, /* Sindhi */
+ 0xffff, /* Tibetan */
+ 0x461, /* Nepali */
+ 0x43b, /* Sanskrit */
+ 0x44e, /* Marathi */
+ 0x445, /* Bengali */
+ 0x44d, /* Assamese */
+ 0x447, /* Gujarati */
+/*70*/ 0x446, /* Punjabi */
+ 0x448, /* Oriya */
+ 0x44c, /* Malayalam */
+ 0x44b, /* Kannada */
+ 0x449, /* Tamil */
+ 0x44a, /* Telugu */
+ 0x45b, /* Sinhalese */
+ 0x455, /* Burmese */
+ 0x453, /* Khmer */
+ 0x454, /* Lao */
+/*80*/ 0x42a, /* Vietnamese */
+ 0x421, /* Indonesian */
+ 0x464, /* Tagalog */
+ 0x43e, /* Malay (latin) */
+ 0x83e, /* Malay (arabic) */
+ 0x45e, /* Amharic */
+ 0x473, /* Tigrinya */
+ 0x472, /* Galla, oromo, afan */
+ 0x477, /* Somali */
+ 0x441, /* Swahili */
+/*90*/ 0xffff, /* Kinyarwanda/Ruanda */
+ 0xffff, /* Rundi/Kirundi */
+ 0xffff, /* Nyanja/Chewa */
+ 0xffff, /* Malagasy */
+/*94*/ 0xffff, /* Esperanto */
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+/*100*/ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+/*110*/ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+/*120*/ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+ 0xffff,
+/*128*/ 0x452, /* Welsh */
+ 0x42d, /* Basque */
+/*130*/ 0x403, /* Catalan */
+ 0x476, /* Latin */
+ 0xffff, /* Quechua */
+ 0x474, /* Guarani */
+ 0xffff, /* Aymara */
+ 0x444, /* Tatar */
+ 0xffff, /* Uighur */
+ 0xffff, /* Dzongkha/Bhutani */
+ 0xffff, /* Javanese (roman) */
+ 0xffff, /* Sundanese (roman) */
+/*140*/ 0x456, /* Galician */
+ 0x436, /* Afrikaans */
+ 0xffff, /* Breton */
+ 0x45d, /* Inuktitut */
+ 0x43c, /* Scottish Gaelic */
+ 0xc3c, /* Manx Gaelic */
+ 0x83c, /* Irish Gaelic (with dot) */
+ 0xffff, /* Tongan */
+ 0xffff, /* Greek (polytonic) */
+ 0xffff, /* Greenlandic */ /* Presumably icelandic? */
+/*150*/ 0x42c, /* Azebaijani (roman) */
+ 0xffff
+};
+
+static char *LanguageCodesFromMacLang[] = {
+ "en", /* English */
+ "fr", /* French */
+ "de", /* German */
+ "it", /* Italian */
+ "nl", /* Dutch */
+ "sv", /* Swedish */
+ "es", /* Spanish */
+ "da", /* Danish */
+ "pt", /* Portuguese */
+ "no", /* Norwegian */
+/*10*/ "he", /* Hebrew */
+ "ja", /* Japanese */
+ "ar", /* Arabic */
+ "fi", /* Finnish */
+ "el", /* Greek */
+ "is", /* Icelandic */
+ "ml", /* Maltese */
+ "tr", /* Turkish */
+ "hr", /* Croatian */
+ "zh_TW", /* Traditional Chinese */ /* zh_HK */
+/*20*/ "ur", /* Urdu */
+ "hi", /* Hindi */
+ "th", /* Thai */
+ "ko", /* Korean */
+ "lt", /* Lithuanian */
+ "pl", /* Polish */
+ "hu", /* Hungarian */
+ "et", /* Estonian */
+ "lv", /* Latvian */
+ "smi", /* Sami (Lappish) */
+/*30*/ "fo", /* Faroese (Icelandic) */
+ "fa", /* Farsi/Persian */
+ "ru", /* Russian */
+ "zh_CN", /* Simplified Chinese */
+ "nl_BE", /* Flemish */ /* Flemish doesn't rate a language code, use dutch */
+ "ga", /* Irish Gaelic */
+ "sq", /* albanian */
+ "ro", /* Romanian */
+ "cs", /* Czech */
+ "sk", /* Slovak */
+/*40*/ "sl", /* Slovenian */
+ "yi", /* Yiddish */
+ "sr", /* Serbian */
+ "mk", /* Macedonian */
+ "bg", /* Bulgarian */
+ "uk", /* Ukrainian */
+ "be", /* Byelorussian */
+ "uz", /* Uzbek */
+ "kk", /* Kazakh */
+ "az", /* Axerbaijani (Cyrillic) */
+/*50*/ "az", /* Axerbaijani (Arabic) */
+ "hy", /* Armenian */
+ "ka", /* Georgian */
+ "mo", /* Moldavian */
+ "ky", /* Kirghiz */
+ "tg", /* Tajiki */
+ "tk", /* Turkmen */
+ "mn", /* Mongolian (Mongolian) */
+ "mn", /* Mongolian (cyrillic) */
+ "ps", /* Pashto */
+/*60*/ "ku", /* Kurdish */
+ "ks", /* Kashmiri */
+ "sd", /* Sindhi */
+ "bo", /* Tibetan */
+ "ne", /* Nepali */
+ "sa", /* Sanskrit */
+ "mr", /* Marathi */
+ "bn", /* Bengali */
+ "as", /* Assamese */
+ "gu", /* Gujarati */
+/*70*/ "pa", /* Punjabi */
+ "or", /* Oriya */
+ "mal", /* Malayalam */
+ "kn", /* Kannada */
+ "ta", /* Tamil */
+ "te", /* Telugu */
+ "si", /* Sinhalese */
+ "my", /* Burmese */
+ "km", /* Khmer */
+ "lo", /* Lao */
+/*80*/ "vi", /* Vietnamese */
+ "id", /* Indonesian */
+ "tl", /* Tagalog */
+ "ms", /* Malay (roman) */
+ "ms", /* Malay (arabic) */
+ "am", /* Amharic */
+ "ti", /* Tigrinya */
+ "om", /* Galla */
+ "so", /* Somali */
+ "sw", /* Swahili */
+/*90*/ "rw", /* Kinyarwanda/Ruanda */
+ "rn", /* Rundi */
+ "nya", /* Nyanja/Chewa */
+ "mg", /* Malagasy */
+/*94*/ "eo", /* Esperanto */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+/*100*/ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+/*110*/ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+/*120*/ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+/*128*/ "cy", /* Welsh */
+ "eu", /* Basque */
+/*130*/ "ca", /* Catalan */
+ "la", /* Latin */
+ "qu", /* Quechua */
+ "gn", /* Guarani */
+ "ay", /* Aymara */
+ "tt", /* Tatar */
+ "ug", /* Uighur */
+ "dz", /* Dzongkha */
+ "jv", /* Javanese (roman) */
+ "su", /* Sundanese (roman) */
+/*140*/ "gl", /* Galician */
+ "af", /* Afrikaans */
+ "be", /* Breton */
+ "iu", /* Inuktitut */
+ "gd", /* Scottish Gaelic */
+ "gv", /* Manx Gaelic */
+ NULL, /* Irish Gaelic (with dot) */
+ "to", /* Tongan */
+ "grc", /* Greek (polytonic) */
+ "kl", /* Greenlandic */ /* Presumably icelandic? */
+/*150*/ "az", /* Azebaijani (roman) */
+ NULL
+};
+
+static const unichar_t *MacEncLangToTable(int macenc,int maclang) {
+ const unichar_t *table = macencodings[macenc];
+
+ if ( maclang==15 /* Icelandic */ ||
+ maclang==30 /* Faroese */ ||
+ maclang==149 /* Greenlandic */ )
+ table = iceland;
+ else if ( maclang == 17 /* turkish */ )
+ table = turkish;
+ else if ( maclang == 18 /* croatian */ )
+ table = croatian;
+ else if ( maclang == 37 /* romanian */ )
+ table = romanian;
+ else if ( maclang == 31 /* Farsi/Persian */ )
+ table = farsi;
+return( table );
+}
+
+char *MacStrToUtf8(const char *str,int macenc,int maclang) {
+ const unichar_t *table;
+ char *ret, *rpt;
+ const uint8 *ustr = (uint8 *) str;
+
+ if ( str==NULL )
+return( NULL );
+
+ if ( macenc==sm_japanese || macenc==sm_korean || macenc==sm_tradchinese ||
+ macenc == sm_simpchinese ) {
+ Encoding *enc = FindOrMakeEncoding(macenc==sm_japanese ? "Sjis" :
+ macenc==sm_korean ? "EUC-KR" :
+ macenc==sm_tradchinese ? "Big5" :
+ "EUC-CN" );
+ iconv_t *toutf8;
+ ICONV_CONST char *in;
+ char *out;
+ size_t inlen, outlen;
+ if ( enc==NULL )
+return( NULL );
+ toutf8 = iconv_open("UTF-8",enc->iconv_name!=NULL?enc->iconv_name:enc->enc_name);
+ if ( toutf8==(iconv_t) -1 || toutf8==NULL )
+return( NULL );
+ in = (char *) str;
+ inlen = strlen(in);
+ outlen = (inlen+1)*4;
+ out = (char *) (ret = galloc(outlen+2));
+ iconv(toutf8,&in,&inlen,&out,&outlen);
+ out[0] = '\0';
+ iconv_close(toutf8);
+return( ret );
+ }
+
+ if ( macenc<0 || macenc>31 ) {
+ IError( "Invalid mac encoding %d.\n", macenc );
+return( NULL );
+ }
+ table = MacEncLangToTable(macenc,maclang);
+
+ if ( table==NULL )
+return( NULL );
+
+ ret = galloc((strlen(str)+1)*3);
+ for ( rpt = ret; *ustr; ++ustr ) {
+ int ch = table[*ustr];
+ rpt = utf8_idpb(rpt,ch);
+ }
+ *rpt = '\0';
+return( ret );
+}
+
+char *Utf8ToMacStr(const char *ustr,int macenc,int maclang) {
+ char *ret, *rpt;
+ const unichar_t *table;
+ int i, ch;
+
+ if ( ustr==NULL )
+return( NULL );
+
+ if ( macenc==sm_japanese || macenc==sm_korean || macenc==sm_tradchinese ||
+ macenc == sm_simpchinese ) {
+ Encoding *enc = FindOrMakeEncoding(macenc==sm_japanese ? "Sjis" :
+ macenc==sm_korean ? "EUC-KR" :
+ macenc==sm_tradchinese ? "Big5" :
+ "EUC-CN" );
+ iconv_t fromutf8;
+ ICONV_CONST char *in;
+ char *out;
+ size_t inlen, outlen;
+ if ( enc==NULL )
+return( NULL );
+ fromutf8 = iconv_open(enc->iconv_name!=NULL?enc->iconv_name:enc->enc_name,"UTF-8");
+ if ( fromutf8==(iconv_t) -1 || fromutf8==NULL )
+return( NULL );
+ in = (char *) ustr;
+ inlen = strlen(ustr);
+ outlen = sizeof(unichar_t)*strlen(ustr);
+ out = ret = galloc(outlen+sizeof(unichar_t));
+ iconv(fromutf8,&in,&inlen,&out,&outlen);
+ out[0] = out[1] = '\0';
+#ifndef UNICHAR_16
+ out[2] = out[3] = '\0';
+#endif
+ iconv_close(fromutf8);
+return( ret );
+ }
+
+ table = macencodings[macenc];
+
+ if ( maclang==15 /* Icelandic */ ||
+ maclang==30 /* Faroese */ ||
+ maclang==149 /* Greenlandic */ )
+ table = iceland;
+ else if ( maclang == 17 /* turkish */ )
+ table = turkish;
+ else if ( maclang == 18 /* croatian */ )
+ table = croatian;
+ else if ( maclang == 37 /* romanian */ )
+ table = romanian;
+ else if ( maclang == 31 /* Farsi/Persian */ )
+ table = farsi;
+
+ if ( table==NULL )
+return( NULL );
+
+ ret = galloc(strlen(ustr)+1);
+ for ( rpt = ret; (ch=utf8_ildb(&ustr)); ) {
+ for ( i=0; i<256; ++i )
+ if ( table[i]==ch ) {
+ *rpt++ = i;
+ break;
+ }
+ }
+ *rpt = '\0';
+return( ret );
+}
+
+uint8 MacEncFromMacLang(int maclang) {
+ if ( maclang<0 || maclang>=sizeof(_MacScriptFromLanguage)/sizeof(_MacScriptFromLanguage[0]))
+return( 0xff );
+
+return( _MacScriptFromLanguage[maclang] );
+}
+
+uint16 WinLangFromMac(int maclang) {
+
+ if ( maclang<0 || maclang>=sizeof(_WinLangFromMac)/sizeof(_WinLangFromMac[0]))
+return( 0xffff );
+
+return( _WinLangFromMac[maclang] );
+}
+
+uint16 WinLangToMac(int winlang) {
+ int i;
+
+ for ( i=0; i<sizeof(_WinLangFromMac)/sizeof(_WinLangFromMac[0]); ++i )
+ if ( _WinLangFromMac[i] == winlang )
+return( i );
+
+ winlang &= 0xff;
+ for ( i=0; i<sizeof(_WinLangFromMac)/sizeof(_WinLangFromMac[0]); ++i )
+ if ( (_WinLangFromMac[i]&0xff) == winlang )
+return( i );
+
+return( 0xffff );
+}
+
+int CanEncodingWinLangAsMac(int winlang) {
+ int maclang = WinLangToMac(winlang);
+ int macenc = MacEncFromMacLang(maclang);
+
+ if ( macenc==0xff )
+return( false );
+ if ( macencodings[macenc]==NULL )
+return( false );
+
+return( true );
+}
+
+const int32 *MacEncToUnicode(int script,int lang) {
+ static int32 temp[256];
+ int i;
+ const unichar_t *table;
+
+ table = MacEncLangToTable(script,lang);
+ if ( table==NULL )
+return( NULL );
+ for ( i=0; i<256; ++i )
+ temp[i] = table[i];
+return( temp );
+}
+
+int MacLangFromLocale(void) {
+ /*const char *loc = setlocale(LC_MESSAGES,NULL);*/ /* This always returns "C" for me, even when it shouldn't be */
+ const char *loc;
+ static int found=-1;
+ int i;
+
+ if ( found!=-1 )
+return( found );
+
+ loc = getenv("LC_ALL");
+ if ( loc==NULL ) loc = getenv("LC_MESSAGES");
+ if ( loc==NULL ) loc = getenv("LANG");
+
+ if ( loc==NULL ) {
+ found=0; /* Default to english */
+return(found);
+ }
+ if ( strncmp(loc,"nl_BE",5)==0 ) {
+ found = 34;
+return( found );
+ }
+ for ( i=0; i<sizeof(LanguageCodesFromMacLang)/sizeof(LanguageCodesFromMacLang[0]); ++i ) {
+ if ( LanguageCodesFromMacLang[i]!=NULL &&
+ strncmp(loc,LanguageCodesFromMacLang[i],strlen(LanguageCodesFromMacLang[i]))==0 ) {
+ found = i;
+return( found );
+ }
+ }
+ if ( strncmp(loc,"zh_HK",2)==0 ) /* I think there are other traditional locales than Hong Kong and Taiwan (?Singapore?) so any chinese we don't recognize */
+ found = 19;
+ else
+ found = 0;
+return( found );
+}
+
+char *PickNameFromMacName(struct macname *mn) {
+ int lang = MacLangFromLocale();
+ struct macname *first=mn, *english=NULL;
+
+ while ( mn!=NULL ) {
+ if ( mn->lang==lang )
+ break;
+ else if ( mn->lang==0 )
+ english = mn;
+ mn = mn->next;
+ }
+ if ( mn==NULL )
+ mn = english;
+ if ( mn==NULL )
+ mn = first;
+ if ( mn==NULL )
+return( NULL );
+
+return( MacStrToUtf8(mn->name,mn->enc,mn->lang));
+}
+
+char *FindEnglishNameInMacName(struct macname *mn) {
+
+ while ( mn!=NULL ) {
+ if ( mn->lang==0 )
+ break;
+ mn = mn->next;
+ }
+ if ( mn==NULL )
+return( NULL );
+
+return( MacStrToUtf8(mn->name,mn->enc,mn->lang));
+}
+
+MacFeat *FindMacFeature(SplineFont *sf, int feat, MacFeat **secondary) {
+ MacFeat *from_f, *from_p;
+
+ for ( from_f = sf->features; from_f!=NULL && from_f->feature!=feat; from_f=from_f->next );
+ for ( from_p = default_mac_feature_map; from_p!=NULL && from_p->feature!=feat; from_p=from_p->next );
+ if ( from_f!=NULL ) {
+ if ( secondary!=NULL ) *secondary = from_p;
+return( from_f );
+ }
+ if ( secondary!=NULL ) *secondary = NULL;
+return( from_p );
+}
+
+struct macsetting *FindMacSetting(SplineFont *sf, int feat, int set,
+ struct macsetting **secondary) {
+ MacFeat *from_f, *from_p;
+ struct macsetting *s_f, *s_p;
+
+ if ( sf!=NULL )
+ for ( from_f = sf->features; from_f!=NULL && from_f->feature!=feat; from_f=from_f->next );
+ else
+ from_f = NULL;
+ for ( from_p = default_mac_feature_map; from_p!=NULL && from_p->feature!=feat; from_p=from_p->next );
+ s_f = s_p = NULL;
+ if ( from_f!=NULL )
+ for ( s_f = from_f->settings; s_f!=NULL && s_f->setting!=set; s_f=s_f->next );
+ if ( from_p!=NULL )
+ for ( s_p = from_p->settings; s_p!=NULL && s_p->setting!=set; s_p=s_p->next );
+ if ( s_f!=NULL ) {
+ if ( secondary!=NULL ) *secondary = s_p;
+return( s_f );
+ }
+ if ( secondary!=NULL ) *secondary = NULL;
+return( s_p );
+}
+
+struct macname *FindMacSettingName(SplineFont *sf, int feat, int set) {
+ MacFeat *from_f, *from_p;
+ struct macsetting *s;
+
+ if ( sf != NULL )
+ for ( from_f = sf->features; from_f!=NULL && from_f->feature!=feat; from_f=from_f->next );
+ else
+ from_f = NULL;
+ for ( from_p = default_mac_feature_map; from_p!=NULL && from_p->feature!=feat; from_p=from_p->next );
+ if ( set==-1 ) {
+ if ( from_f!=NULL && from_f->featname!=NULL )
+return( from_f->featname );
+ else if ( from_p!=NULL )
+return( from_p->featname );
+return( NULL );
+ }
+ s = NULL;
+ if ( from_f!=NULL )
+ for ( s = from_f->settings; s!=NULL && s->setting!=set; s=s->next );
+ if ( (s==NULL || s->setname==NULL) && from_p!=NULL )
+ for ( s = from_p->settings; s!=NULL && s->setting!=set; s=s->next );
+ if ( s!=NULL )
+return( s->setname );
+
+return( NULL );
+}
+
+static struct macname fs_names[] = {
+ { &fs_names[146], 0, 0, "All Typographic Features" },
+ { &fs_names[147], 0, 0, "All Type Features" },
+ { &fs_names[148], 0, 0, "Ligatures" },
+ { &fs_names[149], 0, 0, "Required Ligatures" },
+ { &fs_names[150], 0, 0, "Common Ligatures" },
+ { &fs_names[151], 0, 0, "Rare Ligatures" },
+ { &fs_names[152], 0, 0, "Logo Ligatures" },
+ { &fs_names[153], 0, 0, "Rebus Ligatures" },
+ { &fs_names[154], 0, 0, "Diphthong Ligatures" },
+ { &fs_names[155], 0, 0, "Squared Ligatures" },
+ { &fs_names[156], 0, 0, "Abbreviated Squared Ligatures" },
+ { &fs_names[157], 0, 0, "Cursive connection" },
+ { &fs_names[158], 0, 0, "Unconnected" },
+ { &fs_names[159], 0, 0, "Partially connected" },
+ { &fs_names[160], 0, 0, "Cursive" },
+ { &fs_names[161], 0, 0, "Letter Case" },
+ { &fs_names[162], 0, 0, "Upper & Lower Case" },
+ { &fs_names[163], 0, 0, "All Capitals" },
+ { &fs_names[164], 0, 0, "All Lower Case" },
+ { &fs_names[165], 0, 0, "Small Caps" },
+ { &fs_names[166], 0, 0, "Initial Caps" },
+ { &fs_names[167], 0, 0, "Initial and Small Caps" },
+ { &fs_names[168], 0, 0, "Vertical Substitution" },
+ { &fs_names[169], 0, 0, "Vertical Substitution" },
+ { &fs_names[170], 0, 0, "No Vertical Substitution" },
+ { &fs_names[171], 0, 0, "Linguistic Rearrangement" },
+ { &fs_names[172], 0, 0, "Linguistic Rearrangement" },
+ { &fs_names[173], 0, 0, "No Linguistic Rearrangement" },
+ { &fs_names[174], 0, 0, "Number Spacing" },
+ { &fs_names[175], 0, 0, "Monospaced Numbers" },
+ { &fs_names[176], 0, 0, "Proportional Numbers" },
+ { &fs_names[177], 0, 0, "Smart Swashes" },
+ { &fs_names[178], 0, 0, "Word Initial Swashes" },
+ { &fs_names[179], 0, 0, "Word Final Swashes" },
+ { &fs_names[180], 0, 0, "Line Initial Swashes" },
+ { &fs_names[181], 0, 0, "Line Final Swashes" },
+ { &fs_names[182], 0, 0, "Non-Final Swashes" },
+ { &fs_names[183], 0, 0, "Diacritics" },
+ { &fs_names[184], 0, 0, "Show Diacritics" },
+ { &fs_names[185], 0, 0, "Hide Diacritics" },
+ { &fs_names[186], 0, 0, "Decompose Diacritics" },
+ { &fs_names[187], 0, 0, "Vertical Position" },
+ { &fs_names[188], 0, 0, "Normal Vertical Position" },
+ { &fs_names[189], 0, 0, "Superiors" },
+ { &fs_names[190], 0, 0, "Inferiors" },
+ { &fs_names[191], 0, 0, "Ordinals" },
+ { &fs_names[192], 0, 0, "Fractions" },
+ { &fs_names[193], 0, 0, "No Fractions" },
+ { &fs_names[194], 0, 0, "Vertical Fractions" },
+ { &fs_names[195], 0, 0, "Diagonal Fractions" },
+ { &fs_names[196], 0, 0, "Overlapping Characters" },
+ { &fs_names[197], 0, 0, "Prevent Overlap" },
+ { &fs_names[198], 0, 0, "Allow Overlap" },
+ { &fs_names[199], 0, 0, "Typographic Extras" },
+ { &fs_names[200], 0, 0, "Hyphens to Em-dash" },
+ { &fs_names[201], 0, 0, "Hyphen to En-dash" },
+ { &fs_names[202], 0, 0, "Unslashed Zero" },
+ { &fs_names[203], 0, 0, "Form Interrobang" },
+ { &fs_names[204], 0, 0, "Smart Quotes" },
+ { &fs_names[205], 0, 0, "Periods to Ellipsis" },
+ { &fs_names[206], 0, 0, "Mathematical Extras" },
+ { &fs_names[207], 0, 0, "Hyphen to Minus" },
+ { &fs_names[208], 0, 0, "Asterisk to Multiply" },
+ { &fs_names[209], 0, 0, "Slash to Divide" },
+ { &fs_names[210], 0, 0, "Inequality Ligatures" },
+ { &fs_names[211], 0, 0, "Exponents" },
+ { &fs_names[212], 0, 0, "Ornament Sets" },
+ { &fs_names[213], 0, 0, "No Ornaments" },
+ { &fs_names[214], 0, 0, "Dingbats" },
+ { &fs_names[215], 0, 0, "Pi Characters" },
+ { &fs_names[216], 0, 0, "Fleurons" },
+ { &fs_names[217], 0, 0, "Decorative Borders" },
+ { &fs_names[218], 0, 0, "International Symbols" },
+ { &fs_names[219], 0, 0, "Math Symbols" },
+ { &fs_names[220], 0, 0, "Character Alternates" },
+ { &fs_names[221], 0, 0, "No Alternates" },
+ { &fs_names[222], 0, 0, "Alternate Characters" },
+ { &fs_names[223], 0, 0, "Other Alternates" },
+ { &fs_names[224], 0, 0, "Design Complexity" },
+ { &fs_names[225], 0, 0, "Design Level 1" },
+ { &fs_names[226], 0, 0, "Design Level 2" },
+ { &fs_names[227], 0, 0, "Design Level 3" },
+ { &fs_names[228], 0, 0, "Design Level 4" },
+ { &fs_names[229], 0, 0, "Design Level 5" },
+ { &fs_names[230], 0, 0, "Style Options" },
+ { &fs_names[231], 0, 0, "No Style Options" },
+ { &fs_names[232], 0, 0, "Display Text" },
+ { &fs_names[233], 0, 0, "Engraved Text" },
+ { &fs_names[234], 0, 0, "Illuminated Caps" },
+ { &fs_names[235], 0, 0, "Titling Caps" },
+ { &fs_names[236], 0, 0, "Tall Caps" },
+ { &fs_names[237], 0, 0, "Character Shape" },
+ { &fs_names[238], 0, 0, "Traditional" },
+ { &fs_names[239], 0, 0, "Simplified" },
+ { &fs_names[240], 0, 0, "jis 1978" },
+ { &fs_names[241], 0, 0, "jis 1983" },
+ { &fs_names[242], 0, 0, "jis 1990" },
+ { &fs_names[243], 0, 0, "Traditional Alt 1" },
+ { &fs_names[244], 0, 0, "Traditional Alt 2" },
+ { &fs_names[245], 0, 0, "Traditional Alt 3" },
+ { &fs_names[246], 0, 0, "Traditional Alt 4" },
+ { &fs_names[247], 0, 0, "Traditional Alt 5" },
+ { &fs_names[248], 0, 0, "Expert" },
+ { &fs_names[249], 0, 0, "Number Case" },
+ { &fs_names[250], 0, 0, "Lower Case Numbers" },
+ { &fs_names[251], 0, 0, "Upper Case Numbers" },
+ { &fs_names[252], 0, 0, "Text Spacing" },
+ { &fs_names[253], 0, 0, "Proportional" },
+ { &fs_names[254], 0, 0, "Monospace" },
+ { &fs_names[255], 0, 0, "Transliteration" },
+ { &fs_names[256], 0, 0, "No Transliteration" },
+ { &fs_names[257], 0, 0, "Hanja To Hangul" },
+ { &fs_names[258], 0, 0, "Hiragana to Katakana" },
+ { &fs_names[259], 0, 0, "Katakana to Hiragana" },
+ { &fs_names[260], 0, 0, "Katakana to Roman" },
+ { &fs_names[261], 0, 0, "Roman to Hiragana" },
+ { &fs_names[262], 0, 0, "Roman to Katakana" },
+ { &fs_names[263], 0, 0, "Hanja To Hangul Alt 1" },
+ { &fs_names[264], 0, 0, "Hanja To Hangul Alt 2" },
+ { &fs_names[265], 0, 0, "Hanja To Hangul Alt 3" },
+ { &fs_names[266], 0, 0, "Annotation" },
+ { &fs_names[267], 0, 0, "No Annotation" },
+ { &fs_names[268], 0, 0, "Box Annotation" },
+ { &fs_names[269], 0, 0, "Rounded Box Annotation" },
+ { &fs_names[270], 0, 0, "Circle Annotation" },
+ { &fs_names[271], 0, 0, "Inverted Circle Annotation" },
+ { &fs_names[272], 0, 0, "Parenthesized Annotation" },
+ { &fs_names[273], 0, 0, "Period Annotation" },
+ { &fs_names[274], 0, 0, "Roman Numeral Annotation" },
+ { &fs_names[275], 0, 0, "Diamond Annotation" },
+ { &fs_names[276], 0, 0, "Kana Spacing" },
+ { &fs_names[277], 0, 0, "Full-Width" },
+ { &fs_names[278], 0, 0, "Proportional" },
+ { &fs_names[136], 0, 0, "Ideographic Spacing" },
+ { &fs_names[137], 0, 0, "Full-Width" },
+ { &fs_names[138], 0, 0, "Proportional" },
+ { &fs_names[279], 0, 0, "Ideographic Spacing" },
+ { &fs_names[280], 0, 0, "Full-Width" },
+ { &fs_names[281], 0, 0, "Proportional" },
+ { &fs_names[282], 0, 0, "CJK Roman Spacing" },
+ { &fs_names[283], 0, 0, "Half-Width" },
+ { &fs_names[284], 0, 0, "Proportional" },
+ { &fs_names[285], 0, 0, "Default" },
+ { &fs_names[286], 0, 0, "Full-Width" },
+ { &fs_names[287], 0, 0, "Unicode Decomposition" },
+ { &fs_names[288], 0, 0, "Canonical Decomposition" },
+ { &fs_names[289], 0, 1, "Fonctions typographiques" },
+ { &fs_names[290], 0, 1, "Toutes fonctions typographiques" },
+ { &fs_names[291], 0, 1, "Ligatures" },
+ { &fs_names[397], 0, 1, "Ligatures Requises" },
+ { &fs_names[292], 0, 1, "Ligatures Usuelles" },
+ { &fs_names[293], 0, 1, "Ligatures Rares" },
+ { &fs_names[400], 0, 1, "Ligatures Logos" },
+ { &fs_names[401], 0, 1, "Ligatures R\216bus" },
+ { &fs_names[334], 0, 1, "Ligatures Diphtongues" },
+ { &fs_names[403], 0, 1, "Ligatures Carr\216es" },
+ { &fs_names[404], 0, 1, "Ligatures Carr\216es Abr\217g\216es" },
+ { &fs_names[405], 0, 1, "Connection des Cursives" },
+ { &fs_names[406], 0, 1, "Non connect\216es" },
+ { &fs_names[407], 0, 1, "Partiellement connect\216es" },
+ { &fs_names[408], 0, 1, "Pleinement connect\216es" },
+ { &fs_names[409], 0, 1, "Casse" },
+ { &fs_names[295], 0, 1, "Majuscules & Minuscules" },
+ { &fs_names[296], 0, 1, "Tout Majuscule" },
+ { &fs_names[412], 0, 1, "Tout Minuscule" },
+ { &fs_names[297], 0, 1, "Petites Majuscules" },
+ { &fs_names[414], 0, 1, "Initiales Majuscules" },
+ { &fs_names[415], 0, 1, "Initiales + Petites Majuscules" },
+ { &fs_names[416], 0, 1, "Substitution Verticale" },
+ { &fs_names[417], 0, 1, "Substitution vertical" },
+ { &fs_names[418], 0, 1, "Aucun Substitution vertical" },
+ { &fs_names[419], 0, 1, "R\216arrangement Linguistique" },
+ { &fs_names[420], 0, 1, "Avec R\216arrangement Linguistique" },
+ { &fs_names[421], 0, 1, "Pas de R\216arrangement Linguistique" },
+ { &fs_names[422], 0, 1, "Espacement des chiffres" },
+ { &fs_names[299], 0, 1, "Chiffres de largeur fixe" },
+ { &fs_names[300], 0, 1, "Chiffres Proportionnels" },
+ { &fs_names[301], 0, 1, "Parafes" },
+ { &fs_names[304], 0, 1, "Parafes en d\216but de mot" },
+ { &fs_names[305], 0, 1, "Parafes en fin de mot" },
+ { &fs_names[303], 0, 1, "Parafes en d\216but de ligne" },
+ { &fs_names[302], 0, 1, "Parafes en fin de ligne" },
+ { &fs_names[306], 0, 1, "Autres Parafes" },
+ { &fs_names[431], 0, 1, "Signes Diacritiques" },
+ { &fs_names[339], 0, 1, "Montrer les Signes Diacritiques" },
+ { &fs_names[433], 0, 1, "Cacher les Signes Diacritiques" },
+ { &fs_names[337], 0, 1, "D\216composer les Signes Diacritiques" },
+ { &fs_names[435], 0, 1, "Position Verticale" },
+ { &fs_names[309], 0, 1, "Position Verticale Normale" },
+ { &fs_names[308], 0, 1, "Position Sup\216rieure" },
+ { &fs_names[310], 0, 1, "Position Inf\216rieure" },
+ { &fs_names[311], 0, 1, "Position Sup\216rieure Contextuelle (Num\216rique)" },
+ { &fs_names[440], 0, 1, "Fractions" },
+ { &fs_names[313], 0, 1, "Pas de Fractions" },
+ { &fs_names[442], 0, 1, "Fractions Verticales" },
+ { &fs_names[314], 0, 1, "Fractions en Diagonale" },
+ { &fs_names[444], 0, 1, "Chevauchement des caract\217res" },
+ { &fs_names[316], 0, 1, "\203viter le chevauchement" },
+ { &fs_names[446], 0, 1, "Laisser le Chevauchement" },
+ { &fs_names[317], 0, 1, "Extras Typographiques" },
+ { &fs_names[448], 0, 1, "Tirets vers Tiret Large" },
+ { &fs_names[449], 0, 1, "Tiret vers Tiret Moyen" },
+ { &fs_names[450], 0, 1, "Z\216ro non Barr\216" },
+ { &fs_names[451], 0, 1, "?! vers InterroExclam" },
+ { &fs_names[336], 0, 1, "Apostrophes Intelligentes" },
+ { &fs_names[453], 0, 1, "... vers Ellipse" },
+ { &fs_names[318], 0, 1, "Extras Math\216matiques" },
+ { &fs_names[319], 0, 1, "Tiret vers Moins" },
+ { &fs_names[320], 0, 1, "\203toile vers Multipli\216" },
+ { &fs_names[457], 0, 1, "Barre pench\216e vers Divis\216" },
+ { &fs_names[458], 0, 1, "Ligatures pour In\216galit\216s" },
+ { &fs_names[459], 0, 1, "Passage en Exposant" },
+ { &fs_names[460], 0, 1, "Ensembles Ornementaux" },
+ { &fs_names[322], 0, 1, "Pas d'Ornements" },
+ { &fs_names[462], 0, 1, "Dingbats" },
+ { &fs_names[463], 0, 1, "Symboles Sp\216cifiques \210 un Domaine" },
+ { &fs_names[323], 0, 1, "Fleurons" },
+ { &fs_names[465], 0, 1, "Bordures D\216coratives" },
+ { &fs_names[466], 0, 1, "Symboles Internationaux" },
+ { &fs_names[467], 0, 1, "Symboles Math\216matiques" },
+ { &fs_names[468], 0, 1, "Caract\217res Alternatifs" },
+ { &fs_names[325], 0, 1, "Sans Caract\217res Alternatifs" },
+ { &fs_names[470], 0, 1, "Avec Caract\217res Alternatifs" },
+ { &fs_names[471], 0, 1, "Autres Caract\217res Alternatifs" },
+ { &fs_names[472], 0, 1, "Complexit\216 du Dessin" },
+ { &fs_names[327], 0, 1, "Dessin Niveau 1" },
+ { &fs_names[328], 0, 1, "Dessin Niveau 2" },
+ { &fs_names[329], 0, 1, "Dessin Niveau 3" },
+ { &fs_names[330], 0, 1, "Dessin Niveau 4" },
+ { &fs_names[477], 0, 1, "Dessin Niveau 5" },
+ { &fs_names[478], 0, 1, "Options de Style" },
+ { &fs_names[479], 0, 1, "Texte Ordinaire" },
+ { &fs_names[480], 0, 1, "Texte Majeur" },
+ { &fs_names[481], 0, 1, "Texte en Relief" },
+ { &fs_names[482], 0, 1, "Majuscules Enlumin\216es" },
+ { &fs_names[483], 0, 1, "Majuscules de Titrage" },
+ { &fs_names[484], 0, 1, "Majuscules avec Descendantes" },
+ { &fs_names[485], 0, 1, "Forme des Caract\217res" },
+ { &fs_names[486], 0, 1, "Traditionelle" },
+ { &fs_names[487], 0, 1, "Simplifi\216e" },
+ { &fs_names[488], 0, 1, "jis 1978" },
+ { &fs_names[489], 0, 1, "jis 1983" },
+ { &fs_names[490], 0, 1, "jis 1990" },
+ { &fs_names[491], 0, 1, "Traditionelle Alt 1" },
+ { &fs_names[492], 0, 1, "Traditionelle Alt 2" },
+ { &fs_names[493], 0, 1, "Traditionelle Alt 3" },
+ { &fs_names[494], 0, 1, "Traditionelle Alt 4" },
+ { &fs_names[495], 0, 1, "Traditionelle Alt 5" },
+ { &fs_names[496], 0, 1, "Expert" },
+ { &fs_names[497], 0, 1, "Style des Chiffres" },
+ { &fs_names[332], 0, 1, "Chiffres Anciens (bas de casse)" },
+ { &fs_names[333], 0, 1, "Chiffres Conventionnels (alignants)" },
+ { &fs_names[500], 0, 1, "Espacement du Texte" },
+ { &fs_names[501], 0, 1, "Proportionel" },
+ { &fs_names[502], 0, 1, "Fixe" },
+ { &fs_names[503], 0, 1, "Translitt\216ration" },
+ { &fs_names[504], 0, 1, "Sans Translitt\216ration" },
+ { &fs_names[505], 0, 1, "Hanja vers Hangul" },
+ { &fs_names[506], 0, 1, "Hiragana vers Katakana" },
+ { &fs_names[507], 0, 1, "Katakana vers Hiragana" },
+ { &fs_names[508], 0, 1, "Katakana vers Roman" },
+ { &fs_names[509], 0, 1, "Roman vers Hiragana" },
+ { &fs_names[510], 0, 1, "Roman vers Katakana" },
+ { &fs_names[511], 0, 1, "Hanja vers Hangul Alt 1" },
+ { &fs_names[512], 0, 1, "Hanja vers Hangul Alt 2" },
+ { &fs_names[513], 0, 1, "Hanja vers Hangul Alt 3" },
+ { &fs_names[514], 0, 1, "Annotations" },
+ { &fs_names[515], 0, 1, "Sans Annotations" },
+ { &fs_names[516], 0, 1, "Annotations Encadr\216es" },
+ { &fs_names[517], 0, 1, "Annotations en Cadres arrondis" },
+ { &fs_names[518], 0, 1, "Annotations dans des Cercles" },
+ { &fs_names[519], 0, 1, "Annotations dans des Cercles inverses" },
+ { &fs_names[520], 0, 1, "Annotations Parenth\217s\216es" },
+ { &fs_names[521], 0, 1, "Annotations avec des ." },
+ { &fs_names[522], 0, 1, "Annotations en Chiffres Romains" },
+ { &fs_names[523], 0, 1, "Annotations Diamant" },
+ { &fs_names[524], 0, 1, "Espacement Kana" },
+ { &fs_names[525], 0, 1, "Pleine Taille" },
+ { &fs_names[526], 0, 1, "Proportionnel" },
+ { &fs_names[527], 0, 1, "Espacement des Id\216ogrammes" },
+ { &fs_names[528], 0, 1, "Pleine Taille" },
+ { &fs_names[529], 0, 1, "Proportionnel" },
+ { &fs_names[533], 0, 1, "Espacement des CJK romains" },
+ { &fs_names[534], 0, 1, "Pleine Taille" },
+ { &fs_names[535], 0, 1, "Proportionnel" },
+ { &fs_names[536], 0, 1, "Romains par D\216faut" },
+ { &fs_names[537], 0, 1, "Romains Pleine Taille" },
+ { &fs_names[340], 0, 1, "D\216composition Unicode" },
+ { &fs_names[341], 0, 1, "D\216composition Canonique" },
+ { &fs_names[342], 0, 2, "Alle typografischen M\232glichkeiten" },
+ { &fs_names[343], 0, 2, "Alle Auszeichnungsarten" },
+ { &fs_names[344], 0, 2, "Ligaturen" },
+ { &fs_names[346], 0, 2, "Normale Ligaturen" },
+ { &fs_names[345], 0, 2, "Seltene Ligaturen" },
+ { &fs_names[347], 0, 2, "Schreibweise" },
+ { &fs_names[348], 0, 2, "Gro\247/Klein" },
+ { &fs_names[349], 0, 2, "Gro\247" },
+ { &fs_names[350], 0, 2, "Kapit\212lchen" },
+ { &fs_names[351], 0, 2, "Ziffernabst\212nde" },
+ { &fs_names[352], 0, 2, "Tabellenziffern" },
+ { &fs_names[353], 0, 2, "Proportionalziffern" },
+ { &fs_names[354], 0, 2, "Zierbuchstabe" },
+ { &fs_names[355], 0, 2, "Zierbuchstabe Zeilenende" },
+ { &fs_names[356], 0, 2, "Zierbuchstabe Zeilenanfang" },
+ { &fs_names[357], 0, 2, "Zierbuchstabe Wortanfang" },
+ { &fs_names[358], 0, 2, "Zierbuchstabe Wortende" },
+ { &fs_names[359], 0, 2, "Zierbuchstabe Beliebig" },
+ { &fs_names[360], 0, 2, "Hoch-/Tiefstellen" },
+ { &fs_names[361], 0, 2, "Hochgestellt" },
+ { &fs_names[362], 0, 2, "Normal" },
+ { &fs_names[363], 0, 2, "Tiefgestellt" },
+ { &fs_names[364], 0, 2, "Ordnungszahlen" },
+ { &fs_names[365], 0, 2, "Br\237che" },
+ { &fs_names[367], 0, 2, "Kein Bruche" },
+ { &fs_names[366], 0, 2, "Diagonaler Bruch" },
+ { &fs_names[368], 0, 2, "\206berlappen" },
+ { &fs_names[369], 0, 2, "\206berlappen vermeiden" },
+ { &fs_names[335], 0, 2, "Typographische Extras" },
+ { &fs_names[370], 0, 2, "Mathematische Sonderzeichen" },
+ { &fs_names[371], 0, 2, "Minuszeichen" },
+ { &fs_names[372], 0, 2, "Malzeichen" },
+ { &fs_names[373], 0, 2, "Sonderzeichen" },
+ { &fs_names[374], 0, 2, "Keine Sonderzeichen" },
+ { &fs_names[375], 0, 2, "Pflanzenornamente" },
+ { &fs_names[376], 0, 2, "Alternative Zeichen" },
+ { &fs_names[377], 0, 2, "Keine Alternativ-Figuren" },
+ { &fs_names[378], 0, 2, "Modifikationsgrad" },
+ { &fs_names[379], 0, 2, "Design Stufe 1" },
+ { &fs_names[380], 0, 2, "Design Stufe 2" },
+ { &fs_names[381], 0, 2, "Design Stufe 3" },
+ { &fs_names[382], 0, 2, "Design Stufe 4" },
+ { &fs_names[383], 0, 2, "Zahlendarstellung" },
+ { &fs_names[384], 0, 2, "Medi\276val-Ziffern" },
+ { &fs_names[385], 0, 2, "Normale Ziffern" },
+ { &fs_names[386], 0, 2, "Diphtong Ligaturen" },
+ { &fs_names[387], 0, 2, "Typografische Extras" },
+ { &fs_names[388], 0, 2, "Ersetzen mit geschwungenen Anf\237hrungszeichen" },
+ { &fs_names[389], 0, 2, "Keine Ver\212nderung" },
+ { &fs_names[390], 0, 2, "Diakritische Zeichen" },
+ { &fs_names[391], 0, 2, "Diakritische Zeichen zeigen" },
+ { &fs_names[392], 0, 2, "In Unicode zerlegen" },
+ { &fs_names[393], 0, 2, "anerkannte Komposition" },
+ { &fs_names[394], 0, 3, "Funzioni Tipografiche" },
+ { &fs_names[395], 0, 3, "Tutte le Funzioni" },
+ { &fs_names[396], 0, 3, "Legature" },
+ { &fs_names[399], 0, 3, "Legature Rare" },
+ { &fs_names[398], 0, 3, "Legature pi\235 Comuni" },
+ { NULL, 0, 3, "Maiuscolo o Minuscolo" },
+ { &fs_names[410], 0, 3, "Maiuscolo & minuscolo" },
+ { &fs_names[411], 0, 3, "Tutto in Maiuscolo" },
+ { &fs_names[413], 0, 3, "Maiuscoletto" },
+ { NULL, 0, 3, "Spaziatura numeri" },
+ { &fs_names[423], 0, 3, "Monospaziata" },
+ { &fs_names[424], 0, 3, "Proporzionale" },
+ { &fs_names[425], 0, 3, "Lettere Ornate" },
+ { &fs_names[429], 0, 3, "Fine Riga" },
+ { &fs_names[428], 0, 3, "Inizio Riga" },
+ { &fs_names[426], 0, 3, "All'inizio" },
+ { &fs_names[427], 0, 3, "Alla Fine" },
+ { &fs_names[430], 0, 3, "All'interno" },
+ { NULL, 0, 3, "Posizione Verticale" },
+ { &fs_names[437], 0, 3, "Apice" },
+ { &fs_names[436], 0, 3, "Posizione Normale" },
+ { &fs_names[438], 0, 3, "Pedice" },
+ { &fs_names[439], 0, 3, "Ordinali" },
+ { NULL, 0, 3, "Frazioni" },
+ { &fs_names[443], 0, 3, "Frazioni Diagonali" },
+ { &fs_names[441], 0, 3, "Nessuna Frazione" },
+ { NULL, 0, 3, "Caratteri Sovrapposti" },
+ { &fs_names[445], 0, 3, "Nessuna Sovrapposizione" },
+ { &fs_names[454], 0, 3, "Conversioni Matematiche" },
+ { &fs_names[455], 0, 3, "Trattino per Sottrazione" },
+ { &fs_names[456], 0, 3, "Asterisco per Moltiplicazione" },
+ { NULL, 0, 3, "Impostazione Ornamenti" },
+ { &fs_names[461], 0, 3, "Nessun Ornamento" },
+ { &fs_names[464], 0, 3, "Fleurons" },
+ { NULL, 0, 3, "Caratteri Alternativi" },
+ { &fs_names[469], 0, 3, "Nessuna alternativa" },
+ { NULL, 0, 3, "Design Complexity" },
+ { &fs_names[473], 0, 3, "Livello 1" },
+ { &fs_names[474], 0, 3, "Livello 2" },
+ { &fs_names[475], 0, 3, "Livello 3" },
+ { &fs_names[476], 0, 3, "Livello 4" },
+ { NULL, 0, 3, "Posizione Numeri" },
+ { &fs_names[498], 0, 3, "Sopra la Linea Base" },
+ { &fs_names[499], 0, 3, "Tradizionale" },
+ { &fs_names[402], 0, 3, "Legature dittonghi" },
+ { &fs_names[447], 0, 3, "Extra tipografici" },
+ { &fs_names[452], 0, 3, "Virgolette eleganti" },
+ { &fs_names[434], 0, 3, "Nessuna modifica" },
+ { NULL, 0, 3, "Diacritici" },
+ { &fs_names[432], 0, 3, "Mostra diacritici" },
+ { &fs_names[538], 0, 3, "Scomposizione unicode" },
+ { &fs_names[539], 0, 3, "Composizione canonica" },
+ { NULL, 0, 4, "Alle typografische kenmerken" },
+ { NULL, 0, 4, "Alle typekenmerken" },
+ { NULL, 0, 4, "Ligaturen" },
+ { NULL, 0, 4, "Vereiste ligaturen" },
+ { NULL, 0, 4, "Gemeenschappelijke Ligaturen" },
+ { NULL, 0, 4, "Zeldzame ligaturen" },
+ { NULL, 0, 4, "Logoligaturen" },
+ { NULL, 0, 4, "Rebusligaturen" },
+ { NULL, 0, 4, "Tweeklankligaturen" },
+ { NULL, 0, 4, "Vierkante ligaturen" },
+ { NULL, 0, 4, "Afgekorte vierkante ligatures" },
+ { NULL, 0, 4, "Cursieve verbinding" },
+ { NULL, 0, 4, "Niet verbonden" },
+ { NULL, 0, 4, "Gedeeltelijk verbonden" },
+ { NULL, 0, 4, "Cursief" },
+ { NULL, 0, 4, "Hoofd/kleine letters" },
+ { NULL, 0, 4, "Hoofd- en kleine letters" },
+ { NULL, 0, 4, "Alles in hoofdletters" },
+ { NULL, 0, 4, "Alles in kleine letters" },
+ { NULL, 0, 4, "Kleine hoofdletters" },
+ { NULL, 0, 4, "Eerste hoofdletters" },
+ { NULL, 0, 4, "Eerste en kleine hoofdletters" },
+ { NULL, 0, 4, "Verticale vervanging" },
+ { NULL, 0, 4, "Verticale vervanging" },
+ { NULL, 0, 4, "Geen verticale vervanging" },
+ { NULL, 0, 4, "Taalkundige herschikking" },
+ { NULL, 0, 4, "Taalkundige herschikking" },
+ { NULL, 0, 4, "Geen taalkundige herschikking" },
+ { NULL, 0, 4, "Nummerafstanden" },
+ { NULL, 0, 4, "Vaste nummerafstanden" },
+ { NULL, 0, 4, "Proportionele nummers" },
+ { NULL, 0, 4, "Slimme versieringingen" },
+ { NULL, 0, 4, "Woordbegin-versieringingen" },
+ { NULL, 0, 4, "Woordeinde-versieringingen" },
+ { NULL, 0, 4, "Regelbegin-versieringingen" },
+ { NULL, 0, 4, "Regeleinde-versieringingen" },
+ { NULL, 0, 4, "Niet-einde-versieringingen" },
+ { NULL, 0, 4, "Accenten" },
+ { NULL, 0, 4, "Accenten tonen" },
+ { NULL, 0, 4, "Accenten verbergen" },
+ { NULL, 0, 4, "Accenten ontleden" },
+ { NULL, 0, 4, "Verticale positie" },
+ { NULL, 0, 4, "Normale verticale positie" },
+ { NULL, 0, 4, "Superieuren" },
+ { NULL, 0, 4, "Inferieuren" },
+ { NULL, 0, 4, "Ordinalen" },
+ { NULL, 0, 4, "Breuken" },
+ { NULL, 0, 4, "Geen breuken" },
+ { NULL, 0, 4, "Verticale breuken" },
+ { NULL, 0, 4, "Diagonale breuken" },
+ { NULL, 0, 4, "Overlappende tekens" },
+ { NULL, 0, 4, "Overlap voorkomen" },
+ { NULL, 0, 4, "Overlap toestaan" },
+ { NULL, 0, 4, "Typografische extras" },
+ { NULL, 0, 4, "Koppelteken naar em-streep" },
+ { NULL, 0, 4, "Koppelteken naar en-streepje" },
+ { NULL, 0, 4, "Nul zonder schuine streep" },
+ { NULL, 0, 4, "Vorm interrobang" },
+ { NULL, 0, 4, "Slimme aanhalingstekens" },
+ { NULL, 0, 4, "Punten naar ellipsen" },
+ { NULL, 0, 4, "Wiskundige extras" },
+ { NULL, 0, 4, "Koppelteken naar minteken" },
+ { NULL, 0, 4, "Sterretje naar multiplicatieteken" },
+ { NULL, 0, 4, "Schuine streep naar deelteken" },
+ { NULL, 0, 4, "Ongelijkheidsligaturen" },
+ { NULL, 0, 4, "Exponenten aan" },
+ { NULL, 0, 4, "Ornamentenverzamelingen" },
+ { NULL, 0, 4, "Geen ornamenten" },
+ { NULL, 0, 4, "Dingbats" },
+ { NULL, 0, 4, "Pi-tekens" },
+ { NULL, 0, 4, "Fleurons" },
+ { NULL, 0, 4, "Decoratieve randen" },
+ { NULL, 0, 4, "Internationale symbolen" },
+ { NULL, 0, 4, "Wiskundige Symbolen" },
+ { NULL, 0, 4, "Tekenalternatieven" },
+ { NULL, 0, 4, "Geen alternatieven" },
+ { NULL, 0, 4, "Alternatieve tekens" },
+ { NULL, 0, 4, "Andere alternatieven" },
+ { NULL, 0, 4, "Ontwepcomplexiteit" },
+ { NULL, 0, 4, "Ontwerpniveau 1" },
+ { NULL, 0, 4, "Ontwerpniveau 2" },
+ { NULL, 0, 4, "Ontwerpniveau 3" },
+ { NULL, 0, 4, "Ontwerpniveau 4" },
+ { NULL, 0, 4, "Ontwerpniveau 5" },
+ { NULL, 0, 4, "Stijlopties" },
+ { NULL, 0, 4, "Geen stijl ptions" },
+ { NULL, 0, 4, "Tekst tonen" },
+ { NULL, 0, 4, "Gegraveerde tekst" },
+ { NULL, 0, 4, "Uitgelichte koppen" },
+ { NULL, 0, 4, "Titelkoppen" },
+ { NULL, 0, 4, "Eindkoppen" },
+ { NULL, 0, 4, "Tekenvorm" },
+ { NULL, 0, 4, "Traditioneel" },
+ { NULL, 0, 4, "Vereenvoudigd" },
+ { NULL, 0, 4, "jis 1978" },
+ { NULL, 0, 4, "jis 1983" },
+ { NULL, 0, 4, "jis 1990" },
+ { NULL, 0, 4, "Traditioneel Alt 1" },
+ { NULL, 0, 4, "Traditioneel Alt 2" },
+ { NULL, 0, 4, "Traditioneel Alt 3" },
+ { NULL, 0, 4, "Traditioneel Alt 4" },
+ { NULL, 0, 4, "Traditioneel Alt 5" },
+ { NULL, 0, 4, "Expert" },
+ { NULL, 0, 4, "Nummerhoogte" },
+ { NULL, 0, 4, "Kleine nummers" },
+ { NULL, 0, 4, "Grote nummers" },
+ { NULL, 0, 4, "TekstspatiQring" },
+ { NULL, 0, 4, "Proportioneel" },
+ { NULL, 0, 4, "Gelijk gespatieerd" },
+ { NULL, 0, 4, "Transliteratie" },
+ { NULL, 0, 4, "Geen transliteratie" },
+ { NULL, 0, 4, "Hanja naar Hangul" },
+ { NULL, 0, 4, "Hiragana naar Katakana" },
+ { NULL, 0, 4, "Katakana naar Hiragana" },
+ { NULL, 0, 4, "Katakana naar Romeins" },
+ { NULL, 0, 4, "Romeins naar Hiragana" },
+ { NULL, 0, 4, "Romeins naar Katakana" },
+ { NULL, 0, 4, "Hanja naar Hangul Alt 1" },
+ { NULL, 0, 4, "Hanja naar Hangul Alt 2" },
+ { NULL, 0, 4, "Hanja naar Hangul Alt 3" },
+ { NULL, 0, 4, "Annotatie" },
+ { NULL, 0, 4, "Geen annotatie" },
+ { NULL, 0, 4, "Vierkantannotatie" },
+ { NULL, 0, 4, "Ronde-vierkantannotatie" },
+ { NULL, 0, 4, "Cirkelannotatie" },
+ { NULL, 0, 4, "Omgekeerde cirkelannotatie" },
+ { NULL, 0, 4, "Aanhalingstekenannotatie" },
+ { NULL, 0, 4, "Puntannotatie" },
+ { NULL, 0, 4, "Romeinse-cijferannotatie" },
+ { NULL, 0, 4, "Diamantannotatie" },
+ { NULL, 0, 4, "Kana spatiQring" },
+ { NULL, 0, 4, "Volledige breedte" },
+ { NULL, 0, 4, "Proportioneel" },
+ { &fs_names[530], 0, 4, "Ideographische spatiQring" },
+ { &fs_names[531], 0, 4, "Volledige breedte" },
+ { &fs_names[532], 0, 4, "Proportioneel" },
+ { NULL, 0, 4, "IdeograafspatiQring" },
+ { NULL, 0, 4, "Volledige breedte" },
+ { NULL, 0, 4, "Proportioneel" },
+ { NULL, 0, 4, "CJK Romeinse spatiQring" },
+ { NULL, 0, 4, "Halve breedte" },
+ { NULL, 0, 4, "Proportioneel" },
+ { NULL, 0, 4, "Default" },
+ { NULL, 0, 4, "Volledige breedte" },
+ { NULL, 0, 4, "Unicodeontleding" },
+ { NULL, 0, 4, "Canonieke ontleding" },
+ { NULL }
+};
+
+static struct macsetting fs_settings[] = {
+ { NULL, 0, 0, &fs_names[1], 0 },
+ { NULL, 14, 0, &fs_names[10], 0 },
+ { &fs_settings[1], 12, 0, &fs_names[9], 0 },
+ { &fs_settings[2], 10, 0, &fs_names[8], 0 },
+ { &fs_settings[3], 8, 0, &fs_names[7], 0 },
+ { &fs_settings[4], 6, 0, &fs_names[6], 0 },
+ { &fs_settings[5], 4, 0, &fs_names[5], 0 },
+ { &fs_settings[6], 2, 0, &fs_names[4], 1 },
+ { &fs_settings[7], 0, 0, &fs_names[3], 1 },
+ { NULL, 2, 0, &fs_names[14], 0 },
+ { &fs_settings[9], 1, 0, &fs_names[13], 0 },
+ { &fs_settings[10], 0, 0, &fs_names[12], 1 },
+ { NULL, 5, 0, &fs_names[21], 0 },
+ { &fs_settings[12], 4, 0, &fs_names[20], 0 },
+ { &fs_settings[13], 3, 0, &fs_names[19], 0 },
+ { &fs_settings[14], 2, 0, &fs_names[18], 0 },
+ { &fs_settings[15], 1, 0, &fs_names[17], 0 },
+ { &fs_settings[16], 0, 0, &fs_names[16], 1 },
+ { NULL, 1, 0, &fs_names[24], 0 },
+ { &fs_settings[18], 0, 0, &fs_names[23], 1 },
+ { NULL, 1, 0, &fs_names[27], 0 },
+ { &fs_settings[20], 0, 0, &fs_names[26], 1 },
+ { NULL, 1, 0, &fs_names[30], 0 },
+ { &fs_settings[22], 0, 0, &fs_names[29], 1 },
+ { NULL, 8, 0, &fs_names[36], 0 },
+ { &fs_settings[24], 6, 0, &fs_names[35], 0 },
+ { &fs_settings[25], 4, 0, &fs_names[34], 0 },
+ { &fs_settings[26], 2, 0, &fs_names[33], 0 },
+ { &fs_settings[27], 0, 0, &fs_names[32], 0 },
+ { NULL, 2, 0, &fs_names[40], 0 },
+ { &fs_settings[29], 1, 0, &fs_names[39], 0 },
+ { &fs_settings[30], 0, 0, &fs_names[38], 1 },
+ { NULL, 3, 0, &fs_names[45], 0 },
+ { &fs_settings[32], 2, 0, &fs_names[44], 0 },
+ { &fs_settings[33], 1, 0, &fs_names[43], 0 },
+ { &fs_settings[34], 0, 0, &fs_names[42], 1 },
+ { NULL, 2, 0, &fs_names[49], 0 },
+ { &fs_settings[36], 1, 0, &fs_names[48], 0 },
+ { &fs_settings[37], 0, 0, &fs_names[47], 1 },
+ { NULL, 1, 0, &fs_names[52], 0 },
+ { &fs_settings[39], 0, 0, &fs_names[51], 1 },
+ { NULL, 10, 0, &fs_names[59], 0 },
+ { &fs_settings[41], 8, 0, &fs_names[58], 0 },
+ { &fs_settings[42], 6, 0, &fs_names[57], 0 },
+ { &fs_settings[43], 4, 0, &fs_names[56], 0 },
+ { &fs_settings[44], 2, 0, &fs_names[55], 0 },
+ { &fs_settings[45], 0, 0, &fs_names[54], 0 },
+ { NULL, 8, 0, &fs_names[65], 0 },
+ { &fs_settings[47], 6, 0, &fs_names[64], 0 },
+ { &fs_settings[48], 4, 0, &fs_names[63], 0 },
+ { &fs_settings[49], 2, 0, &fs_names[62], 0 },
+ { &fs_settings[50], 0, 0, &fs_names[61], 0 },
+ { NULL, 6, 0, &fs_names[73], 0 },
+ { &fs_settings[52], 5, 0, &fs_names[72], 0 },
+ { &fs_settings[53], 4, 0, &fs_names[71], 0 },
+ { &fs_settings[54], 3, 0, &fs_names[70], 0 },
+ { &fs_settings[55], 2, 0, &fs_names[69], 0 },
+ { &fs_settings[56], 1, 0, &fs_names[68], 0 },
+ { &fs_settings[57], 0, 0, &fs_names[67], 1 },
+ { NULL, 2, 0, &fs_names[77], 0 },
+ { &fs_settings[59], 1, 0, &fs_names[76], 0 },
+ { &fs_settings[60], 0, 0, &fs_names[75], 1 },
+ { NULL, 4, 0, &fs_names[83], 0 },
+ { &fs_settings[62], 3, 0, &fs_names[82], 0 },
+ { &fs_settings[63], 2, 0, &fs_names[81], 0 },
+ { &fs_settings[64], 1, 0, &fs_names[80], 0 },
+ { &fs_settings[65], 0, 0, &fs_names[79], 1 },
+ { NULL, 5, 0, &fs_names[90], 0 },
+ { &fs_settings[67], 4, 0, &fs_names[89], 0 },
+ { &fs_settings[68], 3, 0, &fs_names[88], 0 },
+ { &fs_settings[69], 2, 0, &fs_names[87], 0 },
+ { &fs_settings[70], 1, 0, &fs_names[86], 0 },
+ { &fs_settings[71], 0, 0, &fs_names[85], 1 },
+ { NULL, 10, 0, &fs_names[102], 0 },
+ { &fs_settings[73], 9, 0, &fs_names[101], 0 },
+ { &fs_settings[74], 8, 0, &fs_names[100], 0 },
+ { &fs_settings[75], 7, 0, &fs_names[99], 0 },
+ { &fs_settings[76], 6, 0, &fs_names[98], 0 },
+ { &fs_settings[77], 5, 0, &fs_names[97], 0 },
+ { &fs_settings[78], 4, 0, &fs_names[96], 0 },
+ { &fs_settings[79], 3, 0, &fs_names[95], 0 },
+ { &fs_settings[80], 2, 0, &fs_names[94], 0 },
+ { &fs_settings[81], 1, 0, &fs_names[93], 0 },
+ { &fs_settings[82], 0, 0, &fs_names[92], 1 },
+ { NULL, 1, 0, &fs_names[105], 1 },
+ { &fs_settings[84], 0, 0, &fs_names[104], 0 },
+ { NULL, 1, 0, &fs_names[108], 0 },
+ { &fs_settings[86], 0, 0, &fs_names[107], 1 },
+ { NULL, 9, 0, &fs_names[119], 0 },
+ { &fs_settings[88], 8, 0, &fs_names[118], 0 },
+ { &fs_settings[89], 7, 0, &fs_names[117], 0 },
+ { &fs_settings[90], 6, 0, &fs_names[116], 0 },
+ { &fs_settings[91], 5, 0, &fs_names[115], 0 },
+ { &fs_settings[92], 4, 0, &fs_names[114], 0 },
+ { &fs_settings[93], 3, 0, &fs_names[113], 0 },
+ { &fs_settings[94], 2, 0, &fs_names[112], 0 },
+ { &fs_settings[95], 1, 0, &fs_names[111], 0 },
+ { &fs_settings[96], 0, 0, &fs_names[110], 1 },
+ { NULL, 8, 0, &fs_names[129], 0 },
+ { &fs_settings[98], 7, 0, &fs_names[128], 0 },
+ { &fs_settings[99], 6, 0, &fs_names[127], 0 },
+ { &fs_settings[100], 5, 0, &fs_names[126], 0 },
+ { &fs_settings[101], 4, 0, &fs_names[125], 0 },
+ { &fs_settings[102], 3, 0, &fs_names[124], 0 },
+ { &fs_settings[103], 2, 0, &fs_names[123], 0 },
+ { &fs_settings[104], 1, 0, &fs_names[122], 0 },
+ { &fs_settings[105], 0, 0, &fs_names[121], 1 },
+ { NULL, 1, 0, &fs_names[132], 0 },
+ { &fs_settings[107], 0, 0, &fs_names[131], 1 },
+ { NULL, 1, 0, &fs_names[135], 0 },
+ { &fs_settings[109], 0, 0, &fs_names[134], 1 },
+ { NULL, 0, 0, &fs_names[145], 0 },
+ { NULL, 3, 0, &fs_names[143], 0 },
+ { &fs_settings[112], 2, 0, &fs_names[142], 0 },
+ { &fs_settings[113], 1, 0, &fs_names[141], 0 },
+ { &fs_settings[114], 0, 0, &fs_names[140], 1 },
+ { NULL }
+};
+
+static MacFeat fs_features[] = {
+ { NULL, 103, 1, 0, 0, &fs_names[139], &fs_settings[115] },
+ { &fs_features[0], 27, 0, 0, 0, &fs_names[144], &fs_settings[111] },
+ { &fs_features[1], 26, 1, 0, 0, &fs_names[133], &fs_settings[110] },
+ { &fs_features[2], 25, 1, 0, 0, &fs_names[130], &fs_settings[108] },
+ { &fs_features[3], 24, 1, 0, 0, &fs_names[120], &fs_settings[106] },
+ { &fs_features[4], 23, 1, 0, 0, &fs_names[109], &fs_settings[97] },
+ { &fs_features[5], 22, 1, 0, 0, &fs_names[106], &fs_settings[87] },
+ { &fs_features[6], 21, 1, 1, 0, &fs_names[103], &fs_settings[85] },
+ { &fs_features[7], 20, 1, 0, 0, &fs_names[91], &fs_settings[83] },
+ { &fs_features[8], 19, 1, 0, 0, &fs_names[84], &fs_settings[72] },
+ { &fs_features[9], 18, 1, 0, 0, &fs_names[78], &fs_settings[66] },
+ { &fs_features[10], 17, 1, 0, 0, &fs_names[74], &fs_settings[61] },
+ { &fs_features[11], 16, 1, 0, 0, &fs_names[66], &fs_settings[58] },
+ { &fs_features[12], 15, 0, 0, 0, &fs_names[60], &fs_settings[51] },
+ { &fs_features[13], 14, 0, 0, 0, &fs_names[53], &fs_settings[46] },
+ { &fs_features[14], 13, 1, 0, 0, &fs_names[50], &fs_settings[40] },
+ { &fs_features[15], 11, 1, 0, 0, &fs_names[46], &fs_settings[38] },
+ { &fs_features[16], 10, 1, 0, 0, &fs_names[41], &fs_settings[35] },
+ { &fs_features[17], 9, 1, 0, 0, &fs_names[37], &fs_settings[31] },
+ { &fs_features[18], 8, 0, 0, 0, &fs_names[31], &fs_settings[28] },
+ { &fs_features[19], 6, 1, 0, 0, &fs_names[28], &fs_settings[23] },
+ { &fs_features[20], 5, 1, 0, 0, &fs_names[25], &fs_settings[21] },
+ { &fs_features[21], 4, 1, 0, 0, &fs_names[22], &fs_settings[19] },
+ { &fs_features[22], 3, 1, 0, 0, &fs_names[15], &fs_settings[17] },
+ { &fs_features[23], 2, 1, 0, 0, &fs_names[11], &fs_settings[11] },
+ { &fs_features[24], 1, 0, 0, 0, &fs_names[2], &fs_settings[8] },
+ { &fs_features[25], 0, 0, 0, 0, &fs_names[0], &fs_settings[0] },
+ { NULL }
+};
+
+MacFeat *default_mac_feature_map = &fs_features[26],
+ *builtin_mac_feature_map=&fs_features[26],
+ *user_mac_feature_map;
+
+static int MacNamesDiffer(struct macname *mn, struct macname *mn2) {
+
+ for ( ; mn!=NULL && mn2!=NULL; mn=mn->next, mn2 = mn2->next ) {
+ if ( mn->lang != mn2->lang || mn->enc!=mn2->enc ||
+ strcmp(mn->name,mn2->name)!=0 )
+return( true );
+ }
+ if ( mn==mn2 ) /* Both NULL */
+return( false );
+
+return( true );
+}
+
+static int MacSettingsDiffer(struct macsetting *ms, struct macsetting *ms2) {
+
+ for ( ; ms!=NULL && ms2!=NULL; ms=ms->next, ms2 = ms2->next ) {
+ if ( ms->setting != ms2->setting ||
+ ms->initially_enabled != ms2->initially_enabled ||
+ MacNamesDiffer(ms->setname,ms2->setname) )
+return( true );
+ }
+ if ( ms==ms2 ) /* Both NULL */
+return( false );
+
+return( true );
+}
+
+int UserFeaturesDiffer(void) {
+ MacFeat *mf, *mf2;
+ if ( user_mac_feature_map==NULL )
+return( false );
+ for ( mf=builtin_mac_feature_map, mf2=user_mac_feature_map;
+ mf!=NULL && mf2!=NULL; mf=mf->next, mf2 = mf2->next ) {
+ if ( mf->feature != mf2->feature || mf->ismutex != mf2->ismutex ||
+ mf->default_setting != mf2->default_setting ||
+ MacNamesDiffer(mf->featname,mf2->featname) ||
+ MacSettingsDiffer(mf->settings,mf2->settings))
+return( true );
+ }
+ if ( mf==mf2 ) /* Both NULL */
+return( false );
+
+return( true );
+}
+
+struct macname *MacNameCopy(struct macname *mn) {
+ struct macname *head=NULL, *last=NULL, *cur;
+
+ while ( mn!=NULL ) {
+ cur = chunkalloc(sizeof(struct macname));
+ cur->enc = mn->enc;
+ cur->lang = mn->lang;
+ cur->name = copy(mn->name);
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ mn = mn->next;
+ }
+return( head );
+}
+
+#ifndef LUA_FF_LIB
+static struct macsetting *MacSettingCopy(struct macsetting *ms) {
+ struct macsetting *head=NULL, *last, *cur;
+
+ while ( ms!=NULL ) {
+ cur = chunkalloc(sizeof(struct macsetting));
+ cur->setting = ms->setting;
+ cur->setname = MacNameCopy(ms->setname);
+ cur->initially_enabled = ms->initially_enabled;
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ ms = ms->next;
+ }
+return( head );
+}
+
+static MacFeat *MacFeatCopy(MacFeat *mf) {
+ MacFeat *head=NULL, *last, *cur;
+
+ while ( mf!=NULL ) {
+ cur = chunkalloc(sizeof(MacFeat));
+ cur->feature = mf->feature;
+ cur->featname = MacNameCopy(mf->featname);
+ cur->settings = MacSettingCopy(mf->settings);
+ cur->ismutex = mf->ismutex;
+ cur->default_setting = mf->default_setting;
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ mf = mf->next;
+ }
+return( head );
+}
+#endif
+
+/* ************************************************************************** */
+static GTextInfo maclanguages[] = {
+ { (unichar_t *) N_("English"), NULL, 0, 0, (void *) 0, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("French"), NULL, 0, 0, (void *) 1, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("German"), NULL, 0, 0, (void *) 2, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Italian"), NULL, 0, 0, (void *) 3, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Dutch"), NULL, 0, 0, (void *) 4, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Swedish"), NULL, 0, 0, (void *) 5, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Spanish"), NULL, 0, 0, (void *) 6, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Danish"), NULL, 0, 0, (void *) 7, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Portuguese"), NULL, 0, 0, (void *) 8, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Norwegian"), NULL, 0, 0, (void *) 9, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Hebrew"), NULL, 0, 0, (void *) 10, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Japanese"), NULL, 0, 0, (void *) 11, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Arabic"), NULL, 0, 0, (void *) 12, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Finnish"), NULL, 0, 0, (void *) 13, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Greek"), NULL, 0, 0, (void *) 14, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Icelandic"), NULL, 0, 0, (void *) 15, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Maltese"), NULL, 0, 0, (void *) 16, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Turkish"), NULL, 0, 0, (void *) 17, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Croatian"), NULL, 0, 0, (void *) 18, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Traditional Chinese"), NULL, 0, 0, (void *) 19, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Urdu"), NULL, 0, 0, (void *) 20, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Hindi"), NULL, 0, 0, (void *) 21, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Thai"), NULL, 0, 0, (void *) 22, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Korean"), NULL, 0, 0, (void *) 23, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lithuanian"), NULL, 0, 0, (void *) 24, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Polish"), NULL, 0, 0, (void *) 25, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Hungarian"), NULL, 0, 0, (void *) 26, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Estonian"), NULL, 0, 0, (void *) 27, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Latvian"), NULL, 0, 0, (void *) 28, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sami (Lappish)"), NULL, 0, 0, (void *) 29, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Faroese (Icelandic)"), NULL, 0, 0, (void *) 30, NULL, 0, 0, 0, 0, 0, 0, 1},
+/* GT: See the long comment at "Property|New" */
+/* GT: The msgstr should contain a translation of "Farsi/Persian", ignore "Lang|" */
+ { (unichar_t *) N_("Lang|Farsi/Persian"), NULL, 0, 0, (void *) 31, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Russian"), NULL, 0, 0, (void *) 32, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Simplified Chinese"), NULL, 0, 0, (void *) 33, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Flemish"), NULL, 0, 0, (void *) 34, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Irish Gaelic"), NULL, 0, 0, (void *) 35, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Albanian"), NULL, 0, 0, (void *) 36, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Romanian"), NULL, 0, 0, (void *) 37, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Czech"), NULL, 0, 0, (void *) 38, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Slovak"), NULL, 0, 0, (void *) 39, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Slovenian"), NULL, 0, 0, (void *) 40, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Yiddish"), NULL, 0, 0, (void *) 41, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Serbian"), NULL, 0, 0, (void *) 42, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Macedonian"), NULL, 0, 0, (void *) 43, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Bulgarian"), NULL, 0, 0, (void *) 44, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Ukrainian"), NULL, 0, 0, (void *) 45, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Byelorussian"), NULL, 0, 0, (void *) 46, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Uzbek"), NULL, 0, 0, (void *) 47, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Kazakh"), NULL, 0, 0, (void *) 48, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Axerbaijani (Cyrillic)"), NULL, 0, 0, (void *) 49, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Axerbaijani (Arabic)"), NULL, 0, 0, (void *) 50, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Armenian"), NULL, 0, 0, (void *) 51, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Georgian"), NULL, 0, 0, (void *) 52, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Moldavian"), NULL, 0, 0, (void *) 53, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Kirghiz"), NULL, 0, 0, (void *) 54, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Tajiki"), NULL, 0, 0, (void *) 55, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Turkmen"), NULL, 0, 0, (void *) 56, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Mongolian (Mongolian)"), NULL, 0, 0, (void *) 57, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Mongolian (cyrillic)"), NULL, 0, 0, (void *) 58, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Pashto"), NULL, 0, 0, (void *) 59, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Kurdish"), NULL, 0, 0, (void *) 60, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Kashmiri"), NULL, 0, 0, (void *) 61, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sindhi"), NULL, 0, 0, (void *) 62, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Tibetan"), NULL, 0, 0, (void *) 63, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Nepali"), NULL, 0, 0, (void *) 64, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sanskrit"), NULL, 0, 0, (void *) 65, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Marathi"), NULL, 0, 0, (void *) 66, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Bengali"), NULL, 0, 0, (void *) 67, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Assamese"), NULL, 0, 0, (void *) 68, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Gujarati"), NULL, 0, 0, (void *) 69, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Punjabi"), NULL, 0, 0, (void *) 70, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Oriya"), NULL, 0, 0, (void *) 71, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Malayalam"), NULL, 0, 0, (void *) 72, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Kannada"), NULL, 0, 0, (void *) 73, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Tamil"), NULL, 0, 0, (void *) 74, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Telugu"), NULL, 0, 0, (void *) 75, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Sinhalese"), NULL, 0, 0, (void *) 76, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Burmese"), NULL, 0, 0, (void *) 77, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Khmer"), NULL, 0, 0, (void *) 78, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Lao"), NULL, 0, 0, (void *) 79, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Vietnamese"), NULL, 0, 0, (void *) 80, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Indonesian"), NULL, 0, 0, (void *) 81, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Tagalog"), NULL, 0, 0, (void *) 82, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Malay (roman)"), NULL, 0, 0, (void *) 83, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Malay (arabic)"), NULL, 0, 0, (void *) 84, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Amharic"), NULL, 0, 0, (void *) 85, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Tigrinya"), NULL, 0, 0, (void *) 86, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Galla"), NULL, 0, 0, (void *) 87, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Somali"), NULL, 0, 0, (void *) 88, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Swahili"), NULL, 0, 0, (void *) 89, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Kinyarwanda/Ruanda"), NULL, 0, 0, (void *) 90, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Rundi"), NULL, 0, 0, (void *) 91, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Nyanja/Chewa"), NULL, 0, 0, (void *) 92, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Malagasy"), NULL, 0, 0, (void *) 93, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Esperanto"), NULL, 0, 0, (void *) 94, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Welsh"), NULL, 0, 0, (void *) 128, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Basque"), NULL, 0, 0, (void *) 129, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Catalan"), NULL, 0, 0, (void *) 130, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Latin"), NULL, 0, 0, (void *) 131, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Quechua"), NULL, 0, 0, (void *) 132, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Guarani"), NULL, 0, 0, (void *) 133, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Aymara"), NULL, 0, 0, (void *) 134, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Tatar"), NULL, 0, 0, (void *) 135, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Lang|Uighur"), NULL, 0, 0, (void *) 136, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Dzongkha"), NULL, 0, 0, (void *) 137, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Javanese (roman)"), NULL, 0, 0, (void *) 138, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Sundanese (roman)"), NULL, 0, 0, (void *) 139, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Galician"), NULL, 0, 0, (void *) 140, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Afrikaans"), NULL, 0, 0, (void *) 141, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Breton"), NULL, 0, 0, (void *) 142, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Inuktitut"), NULL, 0, 0, (void *) 143, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Scottish Gaelic"), NULL, 0, 0, (void *) 144, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Manx Gaelic"), NULL, 0, 0, (void *) 145, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Irish Gaelic (with dot)"), NULL, 0, 0, (void *) 146, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Tongan"), NULL, 0, 0, (void *) 147, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Greek (polytonic)"), NULL, 0, 0, (void *) 148, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Greenlandic"), NULL, 0, 0, (void *) 149, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { (unichar_t *) N_("Azebaijani (roman)"), NULL, 0, 0, (void *) 150, NULL, 0, 0, 0, 0, 0, 0, 1},
+ { NULL }};
+
+static void initmaclangs(void) {
+ static int inited = false;
+ int i;
+
+ if ( !inited ) {
+ inited = true;
+ for ( i=0; maclanguages[i].text!=NULL; ++i )
+ maclanguages[i].text = (unichar_t *) S_( (char *) maclanguages[i].text);
+ }
+}
+
+char *MacLanguageFromCode(int code) {
+ int i;
+
+ if ( code==-1 )
+return( _("Unspecified Language") );
+
+ initmaclangs();
+ for ( i=0; maclanguages[i].text!=NULL; ++i )
+ if ( (void *) (intpt) code == maclanguages[i].userdata )
+return( (char *) maclanguages[i].text );
+
+return( _("Unknown Language"));
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+
+ /* These first three must match the values in prefs.c */
+#define CID_Features 101
+#define CID_FeatureDel 103
+#define CID_FeatureEdit 105
+
+#define CID_Settings 101
+#define CID_SettingDel 103
+#define CID_SettingEdit 105
+
+#define CID_NameList 201
+#define CID_NameNew 202
+#define CID_NameDel 203
+#define CID_NameEdit 205
+
+#define CID_Cancel 300
+#define CID_OK 301
+#define CID_Id 302
+#define CID_Name 303
+#define CID_Language 304
+#define CID_On 305
+#define CID_Mutex 306
+
+static char *spacer = " ⇒ "; /* right double arrow */
+
+static GTextInfo *Pref_MacNamesList(struct macname *all) {
+ GTextInfo *ti;
+ int i, j;
+ struct macname *mn;
+ char *temp, *full;
+
+ initmaclangs();
+
+ for ( i=0, mn=all; mn!=NULL; mn=mn->next, ++i );
+ ti = gcalloc(i+1,sizeof( GTextInfo ));
+
+ for ( i=0, mn=all; mn!=NULL; mn=mn->next, ++i ) {
+ temp = MacStrToUtf8(mn->name,mn->enc,mn->lang);
+ if ( temp==NULL )
+ continue;
+ for ( j=0 ; maclanguages[j].text!=0; ++j )
+ if ( maclanguages[j].userdata == (void *) (intpt) (mn->lang ))
+ break;
+ if ( maclanguages[j].text!=0 ) {
+ char *lang = (char *) maclanguages[j].text;
+ full = galloc((strlen(lang)+strlen(temp)+strlen(spacer)+1));
+ strcpy(full,lang);
+ } else {
+ char *hunh = "???";
+ full = galloc((strlen(hunh)+strlen(temp)+strlen(spacer)+1));
+ strcpy(full,hunh);
+ }
+ strcat(full,spacer);
+ strcat(full,temp);
+ free(temp);
+ ti[i].text = (unichar_t *) full;
+ ti[i].text_is_1byte = true;
+ ti[i].userdata = (void *) mn;
+ }
+return( ti );
+}
+
+static GTextInfo *Pref_SettingsList(struct macsetting *all) {
+ GTextInfo *ti;
+ int i;
+ struct macsetting *ms;
+ unichar_t *full; char *temp;
+ char buf[20];
+
+ for ( i=0, ms=all; ms!=NULL; ms=ms->next, ++i );
+ ti = gcalloc(i+1,sizeof( GTextInfo ));
+
+ for ( i=0, ms=all; ms!=NULL; ms=ms->next, ++i ) {
+ temp = PickNameFromMacName(ms->setname);
+ sprintf(buf,"%3d ", ms->setting);
+ if ( temp==NULL )
+ full = uc_copy(buf);
+ else {
+ full = galloc((strlen(buf)+strlen(temp)+1)*sizeof(unichar_t));
+ uc_strcpy(full,buf);
+ utf82u_strcpy(full+u_strlen(full),temp);
+ free(temp);
+ }
+ ti[i].text = full;
+ ti[i].userdata = ms;
+ }
+return( ti );
+}
+
+static GTextInfo *Pref_FeaturesList(MacFeat *all) {
+ GTextInfo *ti;
+ int i;
+ MacFeat *mf;
+ char *temp;
+ unichar_t *full;
+ char buf[20];
+
+ for ( i=0, mf=all; mf!=NULL; mf=mf->next, ++i );
+ ti = gcalloc(i+1,sizeof( GTextInfo ));
+
+ for ( i=0, mf=all; mf!=NULL; mf=mf->next, ++i ) {
+ temp = PickNameFromMacName(mf->featname);
+ sprintf(buf,"%3d ", mf->feature);
+ if ( temp==NULL )
+ full = uc_copy(buf);
+ else {
+ full = galloc((strlen(buf)+strlen(temp)+1)*sizeof(unichar_t));
+ uc_strcpy(full,buf);
+ utf82u_strcpy(full+u_strlen(full),temp);
+ free(temp);
+ }
+ ti[i].text = full;
+ ti[i].userdata = mf;
+ }
+return( ti );
+}
+
+struct namedata {
+ GWindow gw;
+ int index;
+ int done;
+ struct macname *all, *changing;
+ GGadget *namelist; /* Not in this dlg, in the dlg which created us */
+};
+
+static int name_e_h(GWindow gw, GEvent *event) {
+ struct namedata *nd = GDrawGetUserData(gw);
+ int i;
+ int32 len;
+ GTextInfo **ti, *sel;
+ char *ret1, *temp; unichar_t *full;
+ int val1, val2;
+ struct macname *mn;
+ int language;
+
+ if ( event->type==et_close ) {
+ nd->done = true;
+ if ( nd->index==-1 )
+ MacNameListFree(nd->changing);
+ } else if ( event->type==et_char ) {
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("prefs.html#Features");
+return( true );
+ }
+return( false );
+ } else if ( event->type==et_controlevent && event->u.control.subtype == et_buttonactivate ) {
+ if ( GGadgetGetCid(event->u.control.g) == CID_Cancel ) {
+ nd->done = true;
+ if ( nd->index==-1 )
+ MacNameListFree(nd->changing);
+ } else if ( GGadgetGetCid(event->u.control.g) == CID_OK ) {
+ sel = GGadgetGetListItemSelected(GWidgetGetControl(nd->gw,CID_Language));
+ language = nd->changing->lang;
+ if ( sel!=NULL )
+ language = (intpt) sel->userdata;
+ else if ( nd->index==-1 ) {
+ gwwv_post_error(_("Bad Language"),_("Bad Language"));
+return( true );
+ } /* Otherwise use the original language, it might not be one we recognize */
+ if ( language != nd->changing->lang )
+ nd->changing->enc = MacEncFromMacLang(language);
+ nd->changing->lang = language;
+ val1 = (nd->changing->enc<<16) | nd->changing->lang;
+ ret1 = GGadgetGetTitle8(GWidgetGetControl(nd->gw,CID_Name));
+ free(nd->changing->name);
+ nd->changing->name = Utf8ToMacStr(ret1,nd->changing->enc,nd->changing->lang);
+ free(ret1);
+
+ ti = GGadgetGetList(nd->namelist,&len);
+ for ( i=0; i<len; ++i ) if ( i!=nd->index ) {
+ val2 = (((struct macname *) (ti[i]->userdata))->enc<<16) |
+ (((struct macname *) (ti[i]->userdata))->lang);
+ if ( val2==val1 ) {
+ gwwv_post_error(_("This feature code is already used"),_("This feature code is already used"));
+return( true );
+ }
+ }
+
+ temp = MacStrToUtf8(nd->changing->name,nd->changing->enc,nd->changing->lang);
+ if ( sel!=NULL ) {
+ const unichar_t *lang = sel->text;
+ full = galloc((u_strlen(lang)+strlen(temp)+6)*sizeof(unichar_t));
+ u_strcpy(full,lang);
+ } else {
+ char *hunh = "???";
+ full = galloc((strlen(hunh)+strlen(temp)+6)*sizeof(unichar_t));
+ uc_strcpy(full,hunh);
+ }
+ uc_strcat(full,spacer);
+ utf82u_strcpy(full+u_strlen(full),temp);
+
+ if ( nd->index==-1 )
+ GListAddStr(nd->namelist,full,nd->changing);
+ else {
+ GListReplaceStr(nd->namelist,nd->index,full,nd->changing);
+ if ( nd->all==nd->changing )
+ nd->all = nd->changing->next;
+ else {
+ for ( mn=nd->all ; mn!=NULL && mn->next!=nd->changing; mn=mn->next );
+ if ( mn!=NULL ) mn->next = nd->changing->next;
+ }
+ }
+ nd->changing->next = NULL;
+ if ( nd->all==NULL || val1< ((nd->all->enc<<16)|nd->all->lang) ) {
+ nd->changing->next = nd->all;
+ nd->all = nd->changing;
+ } else {
+ for ( mn=nd->all; mn->next!=NULL && ((mn->next->enc<<16)|mn->next->lang)<val1; mn=mn->next );
+ nd->changing->next = mn->next;
+ mn->next = nd->changing;
+ }
+ GGadgetSetUserData(nd->namelist,nd->all);
+ nd->done = true;
+ }
+ }
+return( true );
+}
+
+static char *AskName(struct macname *changing,struct macname *all,GGadget *list, int index) {
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[8];
+ GTextInfo label[8];
+ struct namedata nd;
+ int i;
+
+ initmaclangs();
+
+ memset(&nd,0,sizeof(nd));
+ nd.namelist = list;
+ nd.index = index;
+ nd.changing = changing;
+ nd.all = all;
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Setting");
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,270));
+ pos.height = GDrawPointsToPixels(NULL,98);
+ gw = GDrawCreateTopWindow(NULL,&pos,name_e_h,&nd,&wattrs);
+ nd.gw = gw;
+
+ memset(gcd,0,sizeof(gcd));
+ memset(label,0,sizeof(label));
+
+ label[0].text = (unichar_t *) _("_Language:");
+ label[0].text_is_1byte = true;
+ label[0].text_in_resource = true;
+ gcd[0].gd.label = &label[0];
+ gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 5+4;
+ gcd[0].gd.flags = gg_enabled|gg_visible;
+ gcd[0].creator = GLabelCreate;
+
+ gcd[1].gd.pos.x = 60; gcd[1].gd.pos.y = 5;
+ gcd[1].gd.pos.width = 200;
+ gcd[1].gd.flags = gg_enabled|gg_visible | gg_list_alphabetic;
+ gcd[1].gd.u.list = maclanguages;
+ gcd[1].gd.cid = CID_Language;
+ gcd[1].creator = GListButtonCreate;
+
+ for ( i=0; maclanguages[i].text!=NULL; ++i ) {
+ if ( maclanguages[i].userdata == (void *) (intpt) (changing->lang) )
+ maclanguages[i].selected = true;
+ else
+ maclanguages[i].selected = false;
+ if ( changing->lang==65535 )
+ maclanguages[0].selected = true;
+ }
+
+ label[2].text = (unichar_t *) _("_Name:");
+ label[2].text_is_1byte = true;
+ label[2].text_in_resource = true;
+ gcd[2].gd.label = &label[2];
+ gcd[2].gd.pos.x = 5; gcd[2].gd.pos.y = gcd[0].gd.pos.y+28;
+ gcd[2].gd.flags = gg_enabled|gg_visible;
+ gcd[2].creator = GLabelCreate;
+
+ label[3].text = (unichar_t *) MacStrToUtf8(changing->name,changing->enc,changing->lang);
+ label[3].text_is_1byte = true;
+ gcd[3].gd.label = changing->name==NULL ? NULL : &label[3];
+ gcd[3].gd.pos.x = gcd[1].gd.pos.x; gcd[3].gd.pos.y = gcd[2].gd.pos.y-4;
+ gcd[3].gd.pos.width = 200;
+ gcd[3].gd.flags = gg_enabled|gg_visible;
+ gcd[3].gd.cid = CID_Name;
+ gcd[3].creator = GTextFieldCreate;
+
+ i = 4;
+
+ gcd[i].gd.pos.x = 13-3; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+30;
+ gcd[i].gd.pos.width = -1; gcd[i].gd.pos.height = 0;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[i].text = (unichar_t *) _("_OK");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.cid = CID_OK;
+ /*gcd[i].gd.handle_controlevent = Prefs_Ok;*/
+ gcd[i++].creator = GButtonCreate;
+
+ gcd[i].gd.pos.x = -13; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+3;
+ gcd[i].gd.pos.width = -1; gcd[i].gd.pos.height = 0;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[i].text = (unichar_t *) _("_Cancel");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.cid = CID_Cancel;
+ gcd[i].creator = GButtonCreate;
+
+ GGadgetsCreate(gw,gcd);
+ GDrawSetVisible(gw,true);
+ GWidgetIndicateFocusGadget(gcd[1].ret);
+ while ( !nd.done )
+ GDrawProcessOneEvent(NULL);
+ GDrawDestroyWindow(gw);
+return( false );
+}
+
+static void ChangeName(GGadget *list,int index) {
+ struct macname *mn = GGadgetGetListItemSelected(list)->userdata,
+ *all = GGadgetGetUserData(list);
+
+ AskName(mn,all,list,index);
+}
+
+static int Pref_NewName(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GWindow gw = GGadgetGetWindow(g);
+ GGadget *list = GWidgetGetControl(gw,CID_NameList);
+ struct macname *new, *all;
+
+ all = GGadgetGetUserData(list);
+ new = chunkalloc(sizeof(struct macname));
+ new->lang = -1;
+ AskName(new,all,list,-1);
+ }
+return( true );
+}
+
+static int Pref_DelName(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct macname *mn, *p, *all, *next;
+ GWindow gw = GGadgetGetWindow(g);
+ GGadget *list = GWidgetGetControl(gw,CID_NameList);
+ int32 len;
+ GTextInfo **ti = GGadgetGetList(list,&len);
+ int i;
+
+ all = GGadgetGetUserData(list);
+ for ( mn = all, p=NULL; mn!=NULL; mn = next ) {
+ next = mn->next;
+ for ( i=len-1; i>=0; --i ) {
+ if ( ti[i]->selected && ti[i]->userdata==mn )
+ break;
+ }
+ if ( i>=0 ) {
+ if ( p==NULL )
+ all = next;
+ else
+ p->next = next;
+ mn->next = NULL;
+ MacNameListFree(mn);
+ } else
+ p = mn;
+ }
+ GGadgetSetUserData(list,all);
+ GListDelSelected(list);
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_NameDel),false);
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_NameEdit),false);
+ }
+return( true );
+}
+
+static int Pref_EditName(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GGadget *list = GWidgetGetControl(GGadgetGetWindow(g),CID_NameList);
+ ChangeName(list,GGadgetGetFirstListSelectedItem(list));
+ }
+return( true );
+}
+
+static int Pref_NameSel(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ int32 len;
+ GTextInfo **ti = GGadgetGetList(g,&len);
+ GWindow gw = GGadgetGetWindow(g);
+ int i, sel_cnt=0;
+ for ( i=0; i<len; ++i )
+ if ( ti[i]->selected ) ++sel_cnt;
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_NameDel),sel_cnt!=0);
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_NameEdit),sel_cnt==1);
+ } else if ( e->type==et_controlevent && e->u.control.subtype == et_listdoubleclick ) {
+ ChangeName(g,e->u.control.u.list.changed_index!=-1?e->u.control.u.list.changed_index:
+ GGadgetGetFirstListSelectedItem(g));
+ }
+return( true );
+}
+
+struct macname *NameGadgetsGetNames( GWindow gw ) {
+return( GGadgetGetUserData(GWidgetGetControl(gw,CID_NameList)) );
+}
+
+void NameGadgetsSetEnabled( GWindow gw, int enable ) {
+
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_NameList),enable);
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_NameNew),enable);
+ if ( !enable ) {
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_NameDel),false);
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_NameEdit),false);
+ } else {
+ int32 len;
+ GGadget *list = GWidgetGetControl(gw,CID_NameList);
+ GTextInfo **ti = GGadgetGetList(list,&len);
+ int i, sel_cnt=0;
+ for ( i=0; i<len; ++i )
+ if ( ti[i]->selected ) ++sel_cnt;
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_NameDel),sel_cnt>0);
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_NameEdit),sel_cnt=1);
+ }
+}
+
+int GCDBuildNames(GGadgetCreateData *gcd,GTextInfo *label,int pos,struct macname *names) {
+
+ gcd[pos].gd.pos.x = 6; gcd[pos].gd.pos.y = pos==0 ? 6 :
+ gcd[pos-1].creator==GTextFieldCreate ? gcd[pos-1].gd.pos.y+30 :
+ gcd[pos-1].gd.pos.y+14;
+ gcd[pos].gd.pos.width = 250; gcd[pos].gd.pos.height = 5*12+10;
+ gcd[pos].gd.flags = gg_visible | gg_enabled | gg_list_alphabetic | gg_list_multiplesel;
+ gcd[pos].gd.cid = CID_NameList;
+ gcd[pos].data = names = MacNameCopy(names);
+ gcd[pos].gd.u.list = Pref_MacNamesList(names);
+ gcd[pos].gd.handle_controlevent = Pref_NameSel;
+ gcd[pos++].creator = GListCreate;
+
+ gcd[pos].gd.pos.x = 6; gcd[pos].gd.pos.y = gcd[pos-1].gd.pos.y+gcd[pos-1].gd.pos.height+10;
+ gcd[pos].gd.flags = gg_visible | gg_enabled;
+ label[pos].text = (unichar_t *) S_("MacName|_New...");
+ label[pos].text_is_1byte = true;
+ label[pos].text_in_resource = true;
+ gcd[pos].gd.label = &label[pos];
+ gcd[pos].gd.handle_controlevent = Pref_NewName;
+ gcd[pos].gd.cid = CID_NameNew;
+ gcd[pos++].creator = GButtonCreate;
+
+ gcd[pos].gd.pos.x = gcd[pos-1].gd.pos.x+20+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor);
+ gcd[pos].gd.pos.y = gcd[pos-1].gd.pos.y;
+ gcd[pos].gd.flags = gg_visible ;
+ label[pos].text = (unichar_t *) _("_Delete");
+ label[pos].text_is_1byte = true;
+ label[pos].text_in_resource = true;
+ gcd[pos].gd.label = &label[pos];
+ gcd[pos].gd.cid = CID_NameDel;
+ gcd[pos].gd.handle_controlevent = Pref_DelName;
+ gcd[pos++].creator = GButtonCreate;
+
+ gcd[pos].gd.pos.x = gcd[pos-1].gd.pos.x+20+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor);
+ gcd[pos].gd.pos.y = gcd[pos-1].gd.pos.y;
+ gcd[pos].gd.flags = gg_visible ;
+ label[pos].text = (unichar_t *) _("_Edit...");
+ label[pos].text_is_1byte = true;
+ label[pos].text_in_resource = true;
+ gcd[pos].gd.label = &label[pos];
+ gcd[pos].gd.cid = CID_NameEdit;
+ gcd[pos].gd.handle_controlevent = Pref_EditName;
+ gcd[pos++].creator = GButtonCreate;
+
+return( pos );
+}
+
+struct setdata {
+ GWindow gw;
+ int index;
+ int done;
+ struct macsetting *all, *changing;
+ GGadget *settinglist; /* Not in this dlg, in the dlg which created us */
+};
+
+static int set_e_h(GWindow gw, GEvent *event) {
+ struct setdata *sd = GDrawGetUserData(gw);
+ int i;
+ int32 len;
+ GTextInfo **ti;
+ const unichar_t *ret1; unichar_t *end, *res; char *temp;
+ int val1, val2;
+ char buf[20];
+ struct macsetting *ms;
+
+ if ( event->type==et_close ) {
+ sd->done = true;
+ MacNameListFree(GGadgetGetUserData(GWidgetGetControl(sd->gw,CID_NameList)));
+ if ( sd->index==-1 )
+ MacSettingListFree(sd->changing);
+ } else if ( event->type==et_char ) {
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("prefs.html#Settings");
+return( true );
+ }
+return( false );
+ } else if ( event->type==et_controlevent && event->u.control.subtype == et_buttonactivate ) {
+ if ( GGadgetGetCid(event->u.control.g) == CID_Cancel ) {
+ sd->done = true;
+ MacNameListFree(GGadgetGetUserData(GWidgetGetControl(sd->gw,CID_NameList)));
+ if ( sd->index==-1 )
+ MacSettingListFree(sd->changing);
+ } else if ( GGadgetGetCid(event->u.control.g) == CID_OK ) {
+ ret1 = _GGadgetGetTitle(GWidgetGetControl(sd->gw,CID_Id));
+ val1 = u_strtol(ret1,&end,10);
+ if ( *end!='\0' ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ gwwv_post_error(_("Bad Number"),_("Bad Number"));
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("Bad Number"),_("Bad Number"));
+#endif
+return( true );
+ }
+ ti = GGadgetGetList(sd->settinglist,&len);
+ for ( i=0; i<len; ++i ) if ( i!=sd->index ) {
+ val2 = ((struct macsetting *) (ti[i]->userdata))->setting;
+ if ( val2==val1 ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ gwwv_post_error(_("This setting is already used"),_("This setting is already used"));
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("This setting is already used"),_("This setting is already used"));
+#endif
+return( true );
+ }
+ }
+ MacNameListFree(sd->changing->setname);
+ sd->changing->setname = GGadgetGetUserData(GWidgetGetControl(sd->gw,CID_NameList));
+ sd->changing->setting = val1;
+ sd->changing->initially_enabled = GGadgetIsChecked(GWidgetGetControl(sd->gw,CID_On));
+ if ( sd->changing->initially_enabled &&
+ GGadgetIsChecked(GWidgetGetControl(GGadgetGetWindow(sd->settinglist),CID_Mutex)) ) {
+ /* If the mutually exclusive bit were set in the feature then */
+ /* turning this guy on, means we must turn others off */
+ struct macsetting *test;
+ for ( test = sd->all; test!=NULL; test = test->next )
+ if ( test!=sd->changing )
+ test->initially_enabled = false;
+ }
+
+ sprintf(buf,"%3d ", val1);
+ temp = PickNameFromMacName(sd->changing->setname);
+ len = strlen(temp);
+ res = galloc( (strlen(buf)+len+3)*sizeof(unichar_t) );
+ uc_strcpy(res,buf);
+ utf82u_strcpy(res+u_strlen(res),temp);
+ free(temp);
+
+ if ( sd->index==-1 )
+ GListAddStr(sd->settinglist,res,sd->changing);
+ else {
+ GListReplaceStr(sd->settinglist,sd->index,res,sd->changing);
+ if ( sd->all==sd->changing )
+ sd->all = sd->changing->next;
+ else {
+ for ( ms=sd->all ; ms!=NULL && ms->next!=sd->changing; ms=ms->next );
+ if ( ms!=NULL ) ms->next = sd->changing->next;
+ }
+ }
+ sd->changing->next = NULL;
+ if ( sd->all==NULL || sd->changing->setting<sd->all->setting ) {
+ sd->changing->next = sd->all;
+ sd->all = sd->changing;
+ } else {
+ for ( ms=sd->all; ms->next!=NULL && ms->next->setting<sd->changing->setting; ms=ms->next );
+ sd->changing->next = ms->next;
+ ms->next = sd->changing;
+ }
+ GGadgetSetUserData(sd->settinglist,sd->all);
+ sd->done = true;
+ }
+ }
+return( true );
+}
+
+static char *AskSetting(struct macsetting *changing,struct macsetting *all,
+ GGadget *list, int index) {
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[12];
+ GTextInfo label[12];
+ struct setdata sd;
+ char buf[20];
+ int i;
+
+ memset(&sd,0,sizeof(sd));
+ sd.settinglist = list;
+ sd.index = index;
+ sd.changing = changing;
+ sd.all = all;
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Setting");
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,270));
+ pos.height = GDrawPointsToPixels(NULL,193);
+ gw = GDrawCreateTopWindow(NULL,&pos,set_e_h,&sd,&wattrs);
+ sd.gw = gw;
+
+ memset(gcd,0,sizeof(gcd));
+ memset(label,0,sizeof(label));
+
+ label[0].text = (unichar_t *) _("Setting Id:");
+ label[0].text_is_1byte = true;
+ gcd[0].gd.label = &label[0];
+ gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 5+4;
+ gcd[0].gd.flags = gg_enabled|gg_visible;
+ gcd[0].creator = GLabelCreate;
+
+ sprintf( buf, "%d", changing->setting );
+ label[1].text = (unichar_t *) buf;
+ label[1].text_is_1byte = true;
+ gcd[1].gd.label = &label[1];
+ gcd[1].gd.pos.x = 60; gcd[1].gd.pos.y = 5; gcd[1].gd.pos.width = 40;
+ gcd[1].gd.flags = gg_enabled|gg_visible;
+ gcd[1].gd.cid = CID_Id;
+ gcd[1].creator = GTextFieldCreate;
+
+ label[2].text = (unichar_t *) _("_Enabled");
+ label[2].text_is_1byte = true;
+ label[2].text_in_resource = true;
+ gcd[2].gd.label = &label[2];
+ gcd[2].gd.pos.x = 110; gcd[2].gd.pos.y = 5;
+ gcd[2].gd.flags = gg_enabled|gg_visible | (changing->initially_enabled?gg_cb_on:0);
+ gcd[2].gd.cid = CID_On;
+ gcd[2].creator = GCheckBoxCreate;
+
+ label[3].text = (unichar_t *) _("_Name:");
+ label[3].text_is_1byte = true;
+ label[3].text_in_resource = true;
+ gcd[3].gd.label = &label[3];
+ gcd[3].gd.pos.x = 5; gcd[3].gd.pos.y = 5+24;
+ gcd[3].gd.flags = gg_enabled|gg_visible;
+ gcd[3].creator = GLabelCreate;
+
+
+ i = GCDBuildNames(gcd,label,4,changing->setname);
+
+ gcd[i].gd.pos.x = 13-3; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+35;
+ gcd[i].gd.pos.width = -1; gcd[i].gd.pos.height = 0;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[i].text = (unichar_t *) _("_OK");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.cid = CID_OK;
+ /*gcd[i].gd.handle_controlevent = Prefs_Ok;*/
+ gcd[i++].creator = GButtonCreate;
+
+ gcd[i].gd.pos.x = -13; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+3;
+ gcd[i].gd.pos.width = -1; gcd[i].gd.pos.height = 0;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[i].text = (unichar_t *) _("_Cancel");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.cid = CID_Cancel;
+ gcd[i].creator = GButtonCreate;
+
+ GGadgetsCreate(gw,gcd);
+ GTextInfoListFree(gcd[4].gd.u.list);
+
+ GDrawSetVisible(gw,true);
+ GWidgetIndicateFocusGadget(gcd[1].ret);
+ while ( !sd.done )
+ GDrawProcessOneEvent(NULL);
+ GDrawDestroyWindow(gw);
+
+return( false );
+}
+
+static void ChangeSetting(GGadget *list,int index) {
+ struct macsetting *ms = GGadgetGetListItemSelected(list)->userdata,
+ *all = GGadgetGetUserData(list);
+
+ AskSetting(ms,all,list,index);
+}
+
+static int Pref_NewSetting(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GWindow gw = GGadgetGetWindow(g);
+ GGadget *list = GWidgetGetControl(gw,CID_Settings);
+ struct macsetting *new, *ms, *all;
+ int expected=0;
+
+ all = GGadgetGetUserData(list);
+ if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_Mutex)) ) {
+ for ( ms=all; ms!=NULL; ms=ms->next ) {
+ if ( ms->setting!=expected )
+ break;
+ ++expected;
+ }
+ } else {
+ for ( ms=all; ms!=NULL; ms=ms->next ) {
+ if ( ms->setting&1 ) /* Shouldn't be any odd settings for non-mutex */
+ continue;
+ if ( ms->setting!=expected )
+ break;
+ expected += 2;
+ }
+ }
+ new = chunkalloc(sizeof(struct macsetting));
+ new->setting = expected;
+ AskSetting(new,all,list,-1);
+ }
+return( true );
+}
+
+static int Pref_DelSetting(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct macsetting *ms, *p, *all, *next;
+ GWindow gw = GGadgetGetWindow(g);
+ GGadget *list = GWidgetGetControl(gw,CID_Settings);
+ int32 len;
+ GTextInfo **ti = GGadgetGetList(list,&len);
+ int i;
+
+ all = GGadgetGetUserData(list);
+ for ( ms = all, p=NULL; ms!=NULL; ms = next ) {
+ next = ms->next;
+ for ( i=len-1; i>=0; --i ) {
+ if ( ti[i]->selected && ti[i]->userdata==ms )
+ break;
+ }
+ if ( i>=0 ) {
+ if ( p==NULL )
+ all = next;
+ else
+ p->next = next;
+ ms->next = NULL;
+ MacSettingListFree(ms);
+ } else
+ p = ms;
+ }
+ GGadgetSetUserData(list,all);
+ GListDelSelected(list);
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_SettingDel),false);
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_SettingEdit),false);
+ }
+return( true );
+}
+
+static int Pref_EditSetting(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GGadget *list = GWidgetGetControl(GGadgetGetWindow(g),CID_Settings);
+ ChangeSetting(list,GGadgetGetFirstListSelectedItem(list));
+ }
+return( true );
+}
+
+static int Pref_SettingSel(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ int32 len;
+ GTextInfo **ti = GGadgetGetList(g,&len);
+ GWindow gw = GGadgetGetWindow(g);
+ int i, sel_cnt=0;
+ for ( i=0; i<len; ++i )
+ if ( ti[i]->selected ) ++sel_cnt;
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_SettingDel),sel_cnt!=0);
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_SettingEdit),sel_cnt==1);
+ } else if ( e->type==et_controlevent && e->u.control.subtype == et_listdoubleclick ) {
+ ChangeSetting(g,e->u.control.u.list.changed_index!=-1?e->u.control.u.list.changed_index:
+ GGadgetGetFirstListSelectedItem(g));
+ }
+return( true );
+}
+
+struct featdata {
+ GWindow gw;
+ int index;
+ int done;
+ MacFeat *all, *changing;
+ GGadget *featurelist; /* Not in this dlg, in the dlg which created us */
+};
+
+static int feat_e_h(GWindow gw, GEvent *event) {
+ struct featdata *fd = GDrawGetUserData(gw);
+ int i;
+ int32 len;
+ GTextInfo **ti;
+ const unichar_t *ret1; unichar_t *end, *res; char *temp;
+ int val1, val2;
+ char buf[20];
+ MacFeat *mf;
+
+ if ( event->type==et_close ) {
+ fd->done = true;
+ if ( fd->index==-1 )
+ MacFeatListFree(fd->changing);
+ MacSettingListFree(GGadgetGetUserData(GWidgetGetControl(fd->gw,CID_Settings)));
+ MacNameListFree(GGadgetGetUserData(GWidgetGetControl(fd->gw,CID_NameList)));
+ } else if ( event->type==et_char ) {
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("prefs.html#Features");
+return( true );
+ }
+return( false );
+ } else if ( event->type==et_controlevent && event->u.control.subtype == et_buttonactivate ) {
+ if ( GGadgetGetCid(event->u.control.g) == CID_Cancel ) {
+ fd->done = true;
+ if ( fd->index==-1 )
+ MacFeatListFree(fd->changing);
+ MacSettingListFree(GGadgetGetUserData(GWidgetGetControl(fd->gw,CID_Settings)));
+ MacNameListFree(GGadgetGetUserData(GWidgetGetControl(fd->gw,CID_NameList)));
+ } else if ( GGadgetGetCid(event->u.control.g) == CID_OK ) {
+ ret1 = _GGadgetGetTitle(GWidgetGetControl(fd->gw,CID_Id));
+ val1 = u_strtol(ret1,&end,10);
+ if ( *end!='\0' ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ gwwv_post_error(_("Bad Number"),_("Bad Number"));
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("Bad Number"),_("Bad Number"));
+#endif
+return( true );
+ }
+ ti = GGadgetGetList(fd->featurelist,&len);
+ for ( i=0; i<len; ++i ) if ( i!=fd->index ) {
+ val2 = ((MacFeat *) (ti[i]->userdata))->feature;
+ if ( val2==val1 ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ gwwv_post_error(_("This feature code is already used"),_("This feature code is already used"));
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("This feature code is already used"),_("This feature code is already used"));
+#endif
+return( true );
+ }
+ }
+ MacSettingListFree(fd->changing->settings);
+ MacNameListFree(fd->changing->featname);
+ fd->changing->featname = GGadgetGetUserData(GWidgetGetControl(fd->gw,CID_NameList));
+ fd->changing->settings = GGadgetGetUserData(GWidgetGetControl(fd->gw,CID_Settings));
+ fd->changing->ismutex = GGadgetIsChecked(GWidgetGetControl(fd->gw,CID_Mutex));
+ if ( fd->changing->ismutex ) {
+ struct macsetting *ms;
+ for ( i=0, ms = fd->changing->settings; ms!=NULL && !ms->initially_enabled; ms = ms->next, ++i );
+ if ( ms==NULL ) i = 0;
+ fd->changing->default_setting = i;
+ if ( ms!=NULL ) {
+ for ( ms=ms->next ; ms!=NULL; ms = ms->next )
+ ms->initially_enabled = false;
+ }
+ }
+
+ sprintf(buf,"%3d ", val1);
+ temp = PickNameFromMacName(fd->changing->featname);
+ len = strlen(temp);
+ res = galloc( (strlen(buf)+len+3)*sizeof(unichar_t) );
+ uc_strcpy(res,buf);
+ utf82u_strcpy(res+u_strlen(res),temp);
+ free(temp);
+
+ if ( fd->index==-1 )
+ GListAddStr(fd->featurelist,res,fd->changing);
+ else {
+ GListReplaceStr(fd->featurelist,fd->index,res,fd->changing);
+ if ( fd->all==fd->changing )
+ fd->all = fd->changing->next;
+ else {
+ for ( mf=fd->all ; mf!=NULL && mf->next!=fd->changing; mf=mf->next );
+ if ( mf!=NULL ) mf->next = fd->changing->next;
+ }
+ }
+ fd->changing->next = NULL;
+ if ( fd->all==NULL || fd->changing->feature<fd->all->feature ) {
+ fd->changing->next = fd->all;
+ fd->all = fd->changing;
+ } else {
+ for ( mf=fd->all; mf->next!=NULL && mf->next->feature<fd->changing->feature; mf=mf->next );
+ fd->changing->next = mf->next;
+ mf->next = fd->changing;
+ }
+ GGadgetSetUserData(fd->featurelist,fd->all);
+ fd->done = true;
+ }
+ }
+return( true );
+}
+
+static char *AskFeature(MacFeat *changing,MacFeat *all,GGadget *list, int index) {
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[16];
+ GTextInfo label[16], *freeme;
+ struct featdata fd;
+ char buf[20];
+ int i;
+
+ memset(&fd,0,sizeof(fd));
+ fd.featurelist = list;
+ fd.index = index;
+ fd.changing = changing;
+ fd.all = all;
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Feature");
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,265));
+ pos.height = GDrawPointsToPixels(NULL,353);
+ gw = GDrawCreateTopWindow(NULL,&pos,feat_e_h,&fd,&wattrs);
+ fd.gw = gw;
+
+ memset(gcd,0,sizeof(gcd));
+ memset(label,0,sizeof(label));
+
+ label[0].text = (unichar_t *) _("Feature _Id:");
+ label[0].text_is_1byte = true;
+ gcd[0].gd.label = &label[0];
+ gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 5+4;
+ gcd[0].gd.flags = gg_enabled|gg_visible;
+ gcd[0].creator = GLabelCreate;
+
+ sprintf( buf, "%d", changing->feature );
+ label[1].text = (unichar_t *) buf;
+ label[1].text_is_1byte = true;
+ gcd[1].gd.label = &label[1];
+ gcd[1].gd.pos.x = 60; gcd[1].gd.pos.y = 5; gcd[1].gd.pos.width = 40;
+ gcd[1].gd.flags = gg_enabled|gg_visible;
+ gcd[1].gd.cid = CID_Id;
+ gcd[1].creator = GTextFieldCreate;
+
+ label[2].text = (unichar_t *) _("Mutually Exclusive");
+ label[2].text_is_1byte = true;
+ gcd[2].gd.label = &label[2];
+ gcd[2].gd.pos.x = 105; gcd[2].gd.pos.y = 5+4;
+ gcd[2].gd.flags = gg_enabled|gg_visible | (changing->ismutex?gg_cb_on:0);
+ gcd[2].gd.cid = CID_Mutex;
+ gcd[2].creator = GCheckBoxCreate;
+
+ label[3].text = (unichar_t *) _("_Name:");
+ label[3].text_is_1byte = true;
+ label[3].text_in_resource = true;
+ gcd[3].gd.label = &label[3];
+ gcd[3].gd.pos.x = 5; gcd[3].gd.pos.y = 5+24;
+ gcd[3].gd.flags = gg_enabled|gg_visible;
+ gcd[3].creator = GLabelCreate;
+
+ i = GCDBuildNames(gcd,label,4,changing->featname);
+
+ label[i].text = (unichar_t *) _("Settings");
+ label[i].text_is_1byte = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+35;
+ gcd[i].gd.flags = gg_enabled|gg_visible;
+ gcd[i++].creator = GLabelCreate;
+
+ gcd[i].gd.pos.x = 6; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+14;
+ gcd[i].gd.pos.width = 250; gcd[i].gd.pos.height = 8*12+10;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_list_alphabetic | gg_list_multiplesel;
+ gcd[i].gd.cid = CID_Settings;
+ gcd[i].data = MacSettingCopy(changing->settings);
+ gcd[i].gd.u.list = freeme = Pref_SettingsList(gcd[i].data);
+ gcd[i].gd.handle_controlevent = Pref_SettingSel;
+ gcd[i++].creator = GListCreate;
+
+ gcd[i].gd.pos.x = 6; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+gcd[i-1].gd.pos.height+10;
+ gcd[i].gd.flags = gg_visible | gg_enabled;
+ label[i].text = (unichar_t *) S_("MacSetting|_New...");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.handle_controlevent = Pref_NewSetting;
+ gcd[i++].creator = GButtonCreate;
+
+ gcd[i].gd.pos.x = gcd[i-1].gd.pos.x+20+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor);
+ gcd[i].gd.pos.y = gcd[i-1].gd.pos.y;
+ gcd[i].gd.flags = gg_visible ;
+ label[i].text = (unichar_t *) _("_Delete");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.cid = CID_SettingDel;
+ gcd[i].gd.handle_controlevent = Pref_DelSetting;
+ gcd[i++].creator = GButtonCreate;
+
+ gcd[i].gd.pos.x = gcd[i-1].gd.pos.x+20+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor);
+ gcd[i].gd.pos.y = gcd[i-1].gd.pos.y;
+ gcd[i].gd.flags = gg_visible ;
+ label[i].text = (unichar_t *) _("_Edit...");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.cid = CID_SettingEdit;
+ gcd[i].gd.handle_controlevent = Pref_EditSetting;
+ gcd[i++].creator = GButtonCreate;
+
+ gcd[i].gd.pos.x = 13-3; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+30;
+ gcd[i].gd.pos.width = -1; gcd[i].gd.pos.height = 0;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[i].text = (unichar_t *) _("_OK");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.cid = CID_OK;
+ /*gcd[i].gd.handle_controlevent = Prefs_Ok;*/
+ gcd[i++].creator = GButtonCreate;
+
+ gcd[i].gd.pos.x = -13; gcd[i].gd.pos.y = gcd[i-1].gd.pos.y+3;
+ gcd[i].gd.pos.width = -1; gcd[i].gd.pos.height = 0;
+ gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[i].text = (unichar_t *) _("_Cancel");
+ label[i].text_is_1byte = true;
+ label[i].text_in_resource = true;
+ gcd[i].gd.label = &label[i];
+ gcd[i].gd.cid = CID_Cancel;
+ gcd[i].creator = GButtonCreate;
+
+ GGadgetsCreate(gw,gcd);
+ GTextInfoListFree(gcd[4].gd.u.list);
+ GTextInfoListFree(freeme);
+
+ GDrawSetVisible(gw,true);
+ GWidgetIndicateFocusGadget(gcd[1].ret);
+ while ( !fd.done )
+ GDrawProcessOneEvent(NULL);
+ GDrawDestroyWindow(gw);
+
+return( false );
+}
+
+static void ChangeFeature(GGadget *list,int index) {
+ MacFeat *mf = GGadgetGetListItemSelected(list)->userdata,
+ *all = GGadgetGetUserData(list);
+
+ AskFeature(mf,all,list,index);
+}
+
+static int Pref_NewFeat(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GWindow gw = GGadgetGetWindow(g);
+ GGadget *list = GWidgetGetControl(gw,CID_Features);
+ MacFeat *new, *mf, *all;
+ int expected=0;
+
+ all = GGadgetGetUserData(list);
+ for ( mf=all; mf!=NULL; mf=mf->next ) {
+ if ( mf->feature!=expected )
+ break;
+ ++expected;
+ }
+ new = chunkalloc(sizeof(MacFeat));
+ new->feature = expected;
+ AskFeature(new,all,list,-1);
+ }
+return( true );
+}
+
+static int Pref_DelFeat(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ MacFeat *mf, *p, *all, *next;
+ GWindow gw = GGadgetGetWindow(g);
+ GGadget *list = GWidgetGetControl(gw,CID_Features);
+ int32 len;
+ GTextInfo **ti = GGadgetGetList(list,&len);
+ int i;
+
+ all = GGadgetGetUserData(list);
+ for ( mf = all, p=NULL; mf!=NULL; mf = next ) {
+ next = mf->next;
+ for ( i=len-1; i>=0; --i ) {
+ if ( ti[i]->selected && ti[i]->userdata==mf )
+ break;
+ }
+ if ( i>=0 ) {
+ if ( p==NULL )
+ all = next;
+ else
+ p->next = next;
+ mf->next = NULL;
+ MacFeatListFree(mf);
+ } else
+ p = mf;
+ }
+ GGadgetSetUserData(list,all);
+ GListDelSelected(list);
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_FeatureDel),false);
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_FeatureEdit),false);
+ }
+return( true );
+}
+
+static int Pref_EditFeat(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GGadget *list = GWidgetGetControl(GGadgetGetWindow(g),CID_Features);
+ ChangeFeature(list,GGadgetGetFirstListSelectedItem(list));
+ }
+return( true );
+}
+
+static int Pref_FeatureSel(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ int32 len;
+ GTextInfo **ti = GGadgetGetList(g,&len);
+ GWindow gw = GGadgetGetWindow(g);
+ int i, sel_cnt=0;
+ for ( i=0; i<len; ++i )
+ if ( ti[i]->selected ) ++sel_cnt;
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_FeatureDel),sel_cnt!=0);
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_FeatureEdit),sel_cnt==1);
+ } else if ( e->type==et_controlevent && e->u.control.subtype == et_listdoubleclick ) {
+ ChangeFeature(g,e->u.control.u.list.changed_index!=-1?e->u.control.u.list.changed_index:
+ GGadgetGetFirstListSelectedItem(g));
+ }
+return( true );
+}
+
+static int Pref_DefaultFeat(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GGadget *list = GWidgetGetControl(GGadgetGetWindow(g),CID_Features);
+ int inprefs = (intpt) GGadgetGetUserData(g);
+ GTextInfo *ti, **arr;
+ uint16 cnt;
+ /* In preferences the default is the built in data. */
+ /* in a font the default is the preference data (which might be built in or might not) */
+ MacFeat *def = inprefs ? builtin_mac_feature_map : default_mac_feature_map;
+
+ def = MacFeatCopy(def);
+ MacFeatListFree(GGadgetGetUserData(list));
+ GGadgetSetUserData(list,def);
+ ti = Pref_FeaturesList(def);
+ arr = GTextInfoArrayFromList(ti,&cnt);
+ GGadgetSetList(list,arr,false);
+ GTextInfoListFree(ti);
+ }
+return( true );
+}
+
+void GCDFillMacFeat(GGadgetCreateData *mfgcd,GTextInfo *mflabels, int width,
+ MacFeat *all, int fromprefs, GGadgetCreateData *boxes,
+ GGadgetCreateData **array) {
+ int sgc;
+ GGadgetCreateData **butarray = array+4;
+
+ all = MacFeatCopy(all);
+
+ sgc = 0;
+
+ mfgcd[sgc].gd.pos.x = 6; mfgcd[sgc].gd.pos.y = 6;
+ mfgcd[sgc].gd.pos.width = 250; mfgcd[sgc].gd.pos.height = 16*12+10;
+ mfgcd[sgc].gd.flags = gg_visible | gg_enabled | gg_list_alphabetic | gg_list_multiplesel;
+ mfgcd[sgc].gd.cid = CID_Features;
+ mfgcd[sgc].gd.u.list = Pref_FeaturesList(all);
+ mfgcd[sgc].gd.handle_controlevent = Pref_FeatureSel;
+ mfgcd[sgc].data = all;
+ mfgcd[sgc++].creator = GListCreate;
+ array[0] = &mfgcd[sgc-1];
+
+ mfgcd[sgc].gd.pos.x = 6; mfgcd[sgc].gd.pos.y = mfgcd[sgc-1].gd.pos.y+mfgcd[sgc-1].gd.pos.height+10;
+ mfgcd[sgc].gd.flags = gg_visible | gg_enabled;
+ mflabels[sgc].text = (unichar_t *) S_("MacFeature|_New...");
+ mflabels[sgc].text_is_1byte = true;
+ mflabels[sgc].text_in_resource = true;
+ mfgcd[sgc].gd.label = &mflabels[sgc];
+ /*mfgcd[sgc].gd.cid = CID_AnchorRename;*/
+ mfgcd[sgc].gd.handle_controlevent = Pref_NewFeat;
+ mfgcd[sgc++].creator = GButtonCreate;
+ butarray[0] = GCD_Glue; butarray[1] = &mfgcd[sgc-1];
+
+ mfgcd[sgc].gd.pos.x = mfgcd[sgc-1].gd.pos.x+10+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor);
+ mfgcd[sgc].gd.pos.y = mfgcd[sgc-1].gd.pos.y;
+ mfgcd[sgc].gd.flags = gg_visible ;
+ mflabels[sgc].text = (unichar_t *) _("_Delete");
+ mflabels[sgc].text_is_1byte = true;
+ mflabels[sgc].text_in_resource = true;
+ mfgcd[sgc].gd.label = &mflabels[sgc];
+ mfgcd[sgc].gd.cid = CID_FeatureDel;
+ mfgcd[sgc].gd.handle_controlevent = Pref_DelFeat;
+ mfgcd[sgc++].creator = GButtonCreate;
+ butarray[2] = GCD_Glue; butarray[3] = &mfgcd[sgc-1];
+
+ mfgcd[sgc].gd.pos.x = mfgcd[sgc-1].gd.pos.x+10+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor);
+ mfgcd[sgc].gd.pos.y = mfgcd[sgc-1].gd.pos.y;
+ mfgcd[sgc].gd.flags = gg_visible ;
+ mflabels[sgc].text = (unichar_t *) _("_Edit...");
+ mflabels[sgc].text_is_1byte = true;
+ mflabels[sgc].text_in_resource = true;
+ mfgcd[sgc].gd.label = &mflabels[sgc];
+ mfgcd[sgc].gd.cid = CID_FeatureEdit;
+ mfgcd[sgc].gd.handle_controlevent = Pref_EditFeat;
+ mfgcd[sgc++].creator = GButtonCreate;
+ butarray[4] = GCD_Glue; butarray[5] = &mfgcd[sgc-1];
+
+ mfgcd[sgc].gd.pos.x = mfgcd[sgc-1].gd.pos.x+10+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor);
+ mfgcd[sgc].gd.pos.y = mfgcd[sgc-1].gd.pos.y;
+ mfgcd[sgc].gd.flags = gg_visible|gg_enabled ;
+ mflabels[sgc].text = (unichar_t *) S_("MacFeature|Default");
+ mflabels[sgc].text_is_1byte = true;
+ mfgcd[sgc].gd.label = &mflabels[sgc];
+ mfgcd[sgc].gd.handle_controlevent = Pref_DefaultFeat;
+ mfgcd[sgc].data = (void *) (intpt) fromprefs;
+ mfgcd[sgc++].creator = GButtonCreate;
+ butarray[6] = GCD_Glue; butarray[7] = &mfgcd[sgc-1];
+ butarray[8] = GCD_Glue; butarray[9] = NULL;
+
+ boxes[2].gd.flags = gg_enabled|gg_visible;
+ boxes[2].gd.u.boxelements = butarray;
+ boxes[2].creator = GHBoxCreate;
+ array[1] = GCD_Glue;
+ array[2] = &boxes[2];
+ array[3] = NULL;
+
+ boxes[0].gd.flags = gg_enabled|gg_visible;
+ boxes[0].gd.u.boxelements = array;
+ boxes[0].creator = GVBoxCreate;
+}
+
+void Prefs_ReplaceMacFeatures(GGadget *list) {
+ MacFeatListFree(user_mac_feature_map);
+ user_mac_feature_map = GGadgetGetUserData(list);
+ default_mac_feature_map = user_mac_feature_map;
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/namelist.c b/Build/source/libs/luafontforge/fontforge/fontforge/namelist.c
new file mode 100644
index 00000000000..ebc1fc8e4cf
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/namelist.c
@@ -0,0 +1,19852 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pfaeditui.h"
+#include "ustring.h"
+#include <utype.h>
+
+extern int recognizePUA;
+
+#ifdef LUA_FF_LIB
+extern int unic_isalpha(int);
+#define Isalpha unic_isalpha
+#else
+#define Isalpha isalpha
+#endif
+
+
+static struct psaltnames {
+ char *name;
+ int unicode;
+ int provenance; /* 1=> Adobe PUA, 2=>AMS PUA, 3=>TeX */
+} psaltnames[];
+
+static NameList agl_sans, agl, adobepua, greeksc, tex, ams;
+NameList *namelist_for_new_fonts = &agl;
+
+ /* Adobe's standard names are wrong for: */
+ /* 0x0162 is named Tcommaaccent, 0x21A should be */
+ /* 0x0163 is named tcommaaccent, 0x21B should be */
+/* The following have been corrected (at least by intent) or removed */
+ /* 0xf6be is named dotlessj, 0x237 should be */
+ /* 0x2206 is named Delta, 0x394 should be */
+ /* 0x2126 is named Omega, 0x3A9 should be */
+ /* 0x00b5 is named mu, 0x3BC should be */
+
+static int psnamesinited=false;
+#define HASH_SIZE 257
+struct psbucket { const char *name; int uni; struct psbucket *prev; } *psbuckets[HASH_SIZE];
+
+static int hashname(const char *_name) {
+ const unsigned char *name = (const unsigned char *) _name;
+ int hash=0;
+
+ while ( *name ) {
+ if ( *name<=' ' )
+ break;
+ hash = (hash<<3)|((hash>>29)&0x7);
+ hash ^= *name++-(' '+1);
+ }
+ hash ^= (hash>>16);
+ hash &= 0xffff;
+return( hash%HASH_SIZE );
+}
+
+static void psaddbucket(const char *name, int uni) {
+ int hash = hashname(name);
+ struct psbucket *buck = gcalloc(1,sizeof(struct psbucket));
+
+ buck->name = name;
+ buck->uni = uni;
+ buck->prev = psbuckets[hash];
+ psbuckets[hash] = buck;
+}
+
+static void NameListHash(NameList *nl) {
+ int i,j,k;
+ for ( i=0; i<17; ++i ) if ( nl->unicode[i]!=NULL ) {
+ for ( j=0; j<256; ++j ) if ( nl->unicode[i][j]!=NULL ) {
+ for ( k=0; k<256; ++k ) if ( nl->unicode[i][j][k]!=NULL )
+ psaddbucket(nl->unicode[i][j][k],(i<<16)|(j<<8)|k );
+ }
+ }
+}
+
+static void psinitnames(void) {
+ int i;
+ NameList *nl;
+
+ agl.next = &agl_sans;
+ agl_sans.next = &adobepua;
+ adobepua.next = &greeksc;
+ greeksc.next = &tex;
+ tex.next = &ams;
+
+ for ( i=0; psaltnames[i].name!=NULL ; ++i )
+ psaddbucket(psaltnames[i].name,psaltnames[i].unicode);
+ for ( nl=&agl; nl!=NULL; nl=nl->next )
+ NameListHash(nl);
+ psnamesinited = true;
+}
+
+#ifndef LUA_FF_LIB
+static void psreinitnames(void) {
+ /* If we reread a (loaded) namelist file, then we must remove the old defn*/
+ /* which means we must remove all the old hash entries before we can put */
+ /* in the new ones */
+ int i;
+ struct psbucket *cur, *prev;
+ NameList *nl;
+
+ for ( i=0; i<HASH_SIZE; ++i ) {
+ for ( cur = psbuckets[i]; cur!=NULL; cur=prev ) {
+ prev = cur->prev;
+ chunkfree(cur,sizeof(struct psbucket));
+ }
+ psbuckets[i] = NULL;
+ }
+
+ for ( i=0; psaltnames[i].name!=NULL ; ++i )
+ psaddbucket(psaltnames[i].name,psaltnames[i].unicode);
+ for ( nl=&agl; nl!=NULL; nl=nl->next )
+ NameListHash(nl);
+}
+#endif
+
+int UniFromName(const char *name,enum uni_interp interp,Encoding *encname) {
+ int i = -1;
+ char *end;
+ struct psbucket *buck;
+
+ if ( strncmp(name,"uni",3)==0 ) {
+ i = strtol(name+3,&end,16);
+ if ( *end || end-name!=7 ) /* uniXXXXXXXX means a ligature of uniXXXX and uniXXXX */
+ i = -1;
+ } else if ( (name[0]=='U' || name[0]=='u') && name[1]=='+' &&
+ (strlen(name)==6 || strlen(name)==7)) {
+ /* Unifont uses this convention */
+ i = strtol(name+2,&end,16);
+ if ( *end )
+ i = -1;
+ } else if ( name[0]=='u' && strlen(name)>=5 ) {
+ i = strtol(name+1,&end,16);
+ if ( *end )
+ i = -1;
+ else if ( encname!=NULL && !encname->is_unicodefull &&
+ (interp==ui_ams || interp==ui_trad_chinese)) {
+ int j;
+ extern const int cns14pua[], amspua[];
+ const int *pua = interp==ui_ams ? amspua : cns14pua;
+ for ( j=0xf8ff-0xe000; j>=0; --j )
+ if ( pua[j]==i ) {
+ i = j+0xe000;
+ break;
+ }
+ }
+ } else if ( name[0]!='\0' && name[1]=='\0' )
+ i = ((unsigned char *) name)[0];
+ if ( i==-1 ) {
+ if ( !psnamesinited )
+ psinitnames();
+ for ( buck = psbuckets[hashname(name)]; buck!=NULL; buck=buck->prev )
+ if ( strcmp(buck->name,name)==0 )
+ break;
+ if ( buck!=NULL )
+ i = buck->uni;
+ }
+ if ( !recognizePUA && i>=0xe000 && i<=0xf8ff )
+ i = -1;
+return( i );
+}
+
+const char *StdGlyphName(char *buffer, int uni,enum uni_interp interp,NameList *for_this_font) {
+ const char *name = NULL;
+ NameList *nl;
+ int up, ub, uc;
+
+ if ( for_this_font==NULL )
+ for_this_font = namelist_for_new_fonts;
+ else if ( for_this_font==(NameList *) -1 )
+ for_this_font = &agl;
+ if ( (uni>=0 && uni<' ') ||
+ (uni>=0x7f && uni<0xa0) )
+ /* standard controls */;
+ else if ( uni!=-1 ) {
+ if ( uni>=0xe000 && uni<=0xf8ff &&
+ (interp==ui_trad_chinese || for_this_font==&ams)) {
+ extern const int cns14pua[], amspua[];
+ const int *pua = interp==ui_trad_chinese ? cns14pua : amspua;
+ if ( pua[uni-0xe000]!=0 )
+ uni = pua[uni-0xe000];
+ }
+ up = uni>>16;
+ ub = (uni&0xff00)>>8;
+ uc = (uni&0xff);
+ if ( up<17 )
+ for ( nl=for_this_font; nl!=NULL; nl=nl->basedon ) {
+ if ( nl->unicode[up]!=NULL && nl->unicode[up][ub]!=NULL &&
+ (name = nl->unicode[up][ub][uc])!=NULL )
+ break;
+ }
+ }
+ if ( name==NULL ) {
+ if ( uni>=0x10000 )
+ sprintf( buffer, "u%04X", uni);
+ else
+ sprintf( buffer, "uni%04X", uni);
+ name = buffer;
+ }
+return( name );
+}
+
+#ifndef LUA_FF_LIB
+#define RefMax 40
+
+static int transcmp(RefChar *r1, RefChar *r2) {
+ double d1, d2;
+
+ if ( r1->transform[4]<r2->transform[4] )
+return( -1 );
+ else if ( r1->transform[4]>r2->transform[4] )
+return( 1 );
+ if ( (d1 = r1->transform[5])<0 ) d1 = -d1;
+ if ( (d2 = r2->transform[5])<0 ) d2 = -d2;
+ if ( d1<d2 )
+return( -1 );
+ else if ( d1==d2 )
+return( 0 );
+ else
+return( 1 );
+}
+
+static int FindAllRefs(SplineChar *sc,SplineChar *rsc[RefMax], int *au) {
+ RefChar *refs[RefMax], *alp[RefMax], *out[RefMax];
+ RefChar *ref;
+ int layer, rcnt, acnt, ocnt, i,j;
+ int alluni;
+ /* We also order the reference. The order stored in the splinechar doesn't*/
+ /* mean anything, so try and guess what is intended semantically. */
+
+ if ( sc==NULL )
+return( 0 );
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer )
+ if ( sc->layers[layer].splines!=NULL || sc->layers[layer].images!=NULL )
+return( 0 );
+ rcnt = 0;
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ for ( ref = sc->layers[layer].refs; ref!=NULL; ref = ref->next ) {
+ if ( rcnt>=RefMax )
+return( 0 );
+ refs[rcnt++] = ref;
+ }
+ }
+ alluni = true;
+ for ( i=0; i<rcnt; ++i ) {
+ if ( refs[i]->sc->unicodeenc==-1 ) {
+ alluni = false;
+ break;
+ }
+ }
+ if ( !alluni ) {
+ /* If not all unicode we can't make any guesses about meaning, so */
+ /* order by transformation */
+ for ( i=0; i<rcnt; ++i ) for ( j=i+1; j<rcnt; ++j ) {
+ if ( transcmp(refs[i],refs[j])>0 ) {
+ ref = refs[i];
+ refs[i] = refs[j];
+ refs[j] = ref;
+ }
+ }
+ } else {
+ acnt = 0;
+ for ( i=0; i<rcnt; ++i ) {
+ if ( Isalpha(refs[i]->sc->unicodeenc )) {
+ alp[acnt++] = refs[i];
+ --rcnt;
+ for ( j=i; j<rcnt; ++j )
+ refs[j] = refs[j+1];
+ --i;
+ }
+ }
+ for ( i=0; i<acnt; ++i ) for ( j=i+1; j<acnt; ++j ) {
+ if ( transcmp(alp[i],alp[j])>0 ) {
+ ref = alp[i];
+ alp[i] = alp[j];
+ alp[j] = ref;
+ }
+ }
+ for ( i=0; i<rcnt; ++i ) for ( j=i+1; j<rcnt; ++j ) {
+ if ( transcmp(refs[i],refs[j])>0 ) {
+ ref = refs[i];
+ refs[i] = refs[j];
+ refs[j] = ref;
+ }
+ }
+ if ( acnt!=0 ) {
+ int a=0, r=0;
+ real cutpoint;
+ ocnt = 0;
+ out[ocnt++] = alp[a++];
+ forever {
+ if ( a<acnt ) cutpoint = (alp[a]->transform[4]+3*alp[a-1]->transform[4])/4;
+ else cutpoint = 1e30;
+ while ( r<rcnt && refs[r]->transform[4]<cutpoint )
+ out[ocnt++] = refs[r++];
+ if ( a>=acnt )
+ break;
+ out[ocnt++] = alp[a++];
+ }
+ memcpy(refs,out,ocnt*sizeof(RefChar *));
+ rcnt = ocnt;
+ }
+ }
+ for ( i=0; i<rcnt; ++i )
+ rsc[i] = refs[i]->sc;
+ /* alluni now means can be written as uniXXXX.XXXX.XXXX... */
+ for ( i=0; i<rcnt; ++i ) {
+ if ( refs[i]->sc->unicodeenc>0x10000 ) {
+ alluni = false;
+ break;
+ }
+ }
+ *au = alluni;
+return( rcnt );
+}
+
+/* Return a list of all alternate or standard glyph names for this encoding */
+char **AllGlyphNames(int uni, NameList *for_this_font, SplineChar *sc) {
+ int cnt, k, j, i, len;
+ NameList *nl, *nl2, *nl3;
+ char **names = NULL;
+ const char *name;
+ int up, ub, uc;
+ char buffer[40], *pt;
+ SplineChar *refs[RefMax];
+ int rcnt, alluni;
+
+ rcnt = FindAllRefs(sc,refs,&alluni);
+
+ up = uni>>16;
+ ub = (uni&0xff00)>>8;
+ uc = (uni&0xff);
+
+ for ( k=0; k<2; ++k ) {
+ cnt = 0;
+ /* try the default namelist first to put that at the head of the list */
+ name = NULL;
+ nl = nl3 = NULL;
+ if ( uni>=0 && up<17 ) {
+ if ( for_this_font!=NULL ) {
+ for ( nl3=for_this_font; nl3!=NULL; nl3=nl3->basedon ) {
+ if ( nl3->unicode[up]!=NULL && nl3->unicode[up][ub]!=NULL &&
+ (name = nl3->unicode[up][ub][uc])!=NULL )
+ break;
+ }
+ if ( name!=NULL ) {
+ if ( names )
+ names[cnt] = copy(name);
+ ++cnt;
+ }
+ }
+ if ( for_this_font!=namelist_for_new_fonts ) {
+ for ( nl=namelist_for_new_fonts; nl!=NULL; nl=nl->basedon ) if ( nl!=nl3 ) {
+ if ( nl->unicode[up]!=NULL && nl->unicode[up][ub]!=NULL &&
+ (name = nl->unicode[up][ub][uc])!=NULL )
+ break;
+ }
+ if ( name!=NULL ) {
+ if ( names )
+ names[cnt] = copy(name);
+ ++cnt;
+ }
+ }
+ for ( nl2 = &agl; nl2!=NULL; nl2=nl2->next ) if ( nl2!=nl && nl2!=nl3) {
+ if ( nl2->unicode[up]!=NULL && nl2->unicode[up][ub]!=NULL &&
+ (name = nl2->unicode[up][ub][uc])!=NULL ) {
+ if ( names )
+ names[cnt] = copy(name);
+ ++cnt;
+ }
+ }
+ for ( i=0; psaltnames[i].name!=NULL ; ++i ) {
+ if ( psaltnames[i].unicode==uni ) {
+ if ( names )
+ names[cnt] = copy(psaltnames[i].name);
+ ++cnt;
+ }
+ }
+ if ( uni<0x10000 ) {
+ if ( names ) {
+ sprintf( buffer, "uni%04X", uni);
+ names[cnt] = copy(buffer);
+ }
+ ++cnt;
+ }
+ if ( names ) {
+ sprintf( buffer, "u%04X", uni);
+ names[cnt] = copy(buffer);
+ }
+ ++cnt;
+ }
+ if ( rcnt>1 && alluni && (uni<0 || (uni>=0xe000 && uni<0xf900) || uni>=0xf0000 ) ) {
+ if ( names ) {
+ names[cnt] = galloc(4+4*rcnt);
+ strcpy(names[cnt],"uni");
+ pt = names[cnt]+3;
+ for ( i=0; i<rcnt; ++i ) {
+ if ( refs[i]->unicodeenc==0x131 || refs[i]->unicodeenc==0x237 ||
+ refs[i]->unicodeenc==0xf6be )
+ sprintf( pt,"%04X", refs[i]->unicodeenc==0x131?'i':'j' );
+ else
+ sprintf( pt,"%04X", CanonicalCombiner(refs[i]->unicodeenc));
+ pt += 4;
+ }
+ }
+ ++cnt;
+ }
+ if ( rcnt>1 ) {
+ if ( names ) {
+ for ( i=len=0; i<rcnt; ++i )
+ len += strlen( refs[i]->name )+1;
+ names[cnt] = pt = galloc(len);
+ for ( i=len=0; i<rcnt; ++i ) {
+ strcpy(pt,refs[i]->name);
+ pt += strlen(pt);
+ *pt++ = '_';
+ }
+ pt[-1] = '\0';
+ }
+ ++cnt;
+ }
+ if ( uni<0 || up>=17 ) {
+ if ( names )
+ names[cnt] = copy(".notdef");
+ ++cnt;
+ }
+ if ( k==0 ) {
+ names = galloc((cnt+1)*sizeof(char *));
+ names[cnt] = NULL;
+ }
+ }
+ /* Remove any names from multiiple namelists */
+ for ( i=0; i<cnt; ++i ) for ( j=i+1; j<cnt; ++j ) {
+ if ( strcmp(names[i],names[j])==0 ) {
+ for ( k=j+1; k<cnt; ++k )
+ names[k-1] = names[k];
+ names[--cnt] = NULL;
+ --j;
+ }
+ }
+return( names );
+}
+
+
+char **AllNamelistNames(void) {
+ NameList *nl;
+ int cnt;
+ char **names;
+
+ for ( nl = &agl, cnt=0; nl!=NULL; nl=nl->next, ++cnt );
+ names = galloc((cnt+1) *sizeof(char *));
+ for ( nl = &agl, cnt=0; nl!=NULL; nl=nl->next, ++cnt )
+ names[cnt] = copy(_(nl->title));
+ names[cnt] = NULL;
+return( names );
+}
+#endif
+
+#if 0
+uint8 *AllNamelistUnicodes(void) {
+ NameList *nl;
+ int cnt;
+ uint8 *uses;
+
+ for ( nl = &agl, cnt=0; nl!=NULL; nl=nl->next, ++cnt );
+ uses = galloc((cnt+1) *sizeof(uint8));
+ for ( nl = &agl, cnt=0; nl!=NULL; nl=nl->next, ++cnt )
+ uses[cnt] = nl->uses_unicode;
+ uses[cnt] = 0xff;
+return( uses );
+}
+#endif
+
+NameList *DefaultNameListForNewFonts(void) {
+return( namelist_for_new_fonts );
+}
+
+#ifndef LUA_FF_LIB
+NameList *NameListByName(char *name) {
+ NameList *nl;
+ for ( nl = &agl; nl!=NULL; nl=nl->next ) {
+ if ( strcmp(_(nl->title),name)==0 || strcmp(nl->title,name)==0 )
+return( nl );
+ }
+return( NULL );
+}
+
+static void NameListFreeContents(NameList *nl) {
+ int np, nb, nc, i;
+
+ for ( np=0; np<17; ++np ) if ( nl->unicode[np]!=NULL ) {
+ for ( nb=0; nb<256; ++nb ) if ( nl->unicode[np][nb]!=NULL ) {
+ for ( nc=0; nc<256; ++nc ) if ( nl->unicode[np][nb][nc]!=NULL )
+ free((char *)nl->unicode[np][nb][nc] );
+ free( (char **) nl->unicode[np][nb]);
+ }
+ free( (char ***) nl->unicode[np]);
+ }
+ free( nl->title );
+ if ( nl->renames!=NULL ) {
+ for ( i=0; nl->renames[i].from!=NULL; ++i ) {
+ free(nl->renames[i].from);
+ free(nl->renames[i].to);
+ }
+ free(nl->renames);
+ }
+ free(nl->a_utf8_name);
+}
+
+static void NameListFree(NameList *nl) {
+ NameListFreeContents(nl);
+ chunkfree(nl,sizeof(NameList));
+}
+#endif
+/* ************************************************************************** */
+
+#ifndef LUA_FF_LIB
+
+#include <sys/types.h>
+#include <dirent.h>
+
+NameList *LoadNamelist(char *filename) {
+ FILE *file = fopen(filename,"r");
+ NameList *nl, *nl2;
+ char buffer[400];
+ char *pt, *end, *test;
+ int uni;
+ int len;
+ int up, ub, uc;
+ int rn_cnt=0, rn_max = 0;
+ int uses_unicode = false;
+# if defined(FONTFORGE_CONFIG_GTK)
+ gsize read, written;
+# endif
+
+ if ( file==NULL )
+return( NULL );
+
+ if ( !psnamesinited )
+ psinitnames();
+
+ nl = chunkalloc(sizeof(NameList));
+ pt = strrchr(filename,'/');
+ if ( pt==NULL ) pt = filename; else ++pt;
+# if defined(FONTFORGE_CONFIG_GTK)
+ nl->title = g_filename_to_utf8(pt,-1,&read,&written,NULL);
+# else
+ nl->title = def2utf8_copy(pt);
+# endif
+ pt = strrchr(nl->title,'.');
+ if ( pt!=NULL ) *pt = '\0';
+
+ while ( fgets(buffer,sizeof(buffer),file)!=NULL ) {
+ if ( buffer[0]=='#' || buffer[0]=='\n' || buffer[0]=='\r' )
+ continue;
+ len = strlen( buffer );
+ if ( buffer[len-1]=='\n' ) buffer[--len] = '\0';
+ if ( buffer[len-1]=='\r' ) buffer[--len] = '\0';
+ if ( strncmp(buffer,"Based:",6)==0 ) {
+ for ( pt=buffer+6; *pt==' ' || *pt=='\t'; ++pt);
+ for ( nl2 = &agl; nl2!=NULL; nl2 = nl2->next )
+ if ( strcmp( nl2->title,pt )==0 )
+ break;
+ if ( nl2==NULL ) {
+ gwwv_post_error(_("NameList base missing"),_("NameList %s based on %s which could not be found"), nl->title, pt );
+ NameListFree(nl);
+return( NULL );
+ } else if ( nl->basedon!=NULL ) {
+ gwwv_post_error(_("NameList based twice"),_("NameList %s based on two NameLists"), nl->title );
+ NameListFree(nl);
+return( NULL );
+ }
+ nl->basedon = nl2;
+ } else if ( strncmp(buffer,"Rename:",7)==0 ) {
+ for ( pt=buffer+7; *pt==' ' || *pt=='\t'; ++pt);
+ for ( test=pt; *test!=' ' && *test!='\t' && *test!='\0'; ++test );
+ if ( *test=='\0' ) {
+ gwwv_post_error(_("NameList parsing error"),_("Missing rename \"to\" name %s\n%s"), nl->title, buffer );
+ NameListFree(nl);
+return( NULL );
+ }
+ *test='\0';
+ for ( ++test; *test==' ' || *test=='\t'; ++test);
+ if ( (test[0]=='-' || test[0]=='=') && test[1]=='>' )
+ for ( test+=2; *test==' ' || *test=='\t'; ++test);
+ if ( *test=='\0' ) {
+ gwwv_post_error(_("NameList parsing error"),_("Missing rename \"to\" name %s\n%s"), nl->title, buffer );
+ NameListFree(nl);
+return( NULL );
+ }
+ if ( rn_cnt>=rn_max-1 )
+ nl->renames = grealloc(nl->renames,(rn_max+=20)*sizeof(struct renames));
+ nl->renames[rn_cnt].from = copy(pt);
+ nl->renames[rn_cnt].to = copy(test);
+ nl->renames[++rn_cnt].from = NULL; /* End mark */
+ } else {
+ pt = buffer;
+ if ( *pt=='0' && (pt[1]=='x' || pt[1]=='X'))
+ pt += 2;
+ else if (( *pt=='u' || *pt=='U') && pt[1]=='+' )
+ pt += 2;
+ uni = strtol(pt,&end,16);
+ if ( end==pt || uni<0 || uni>=unicode4_size ) {
+ gwwv_post_error(_("NameList parsing error"),_("Bad unicode value when parsing %s\n%s"), nl->title, buffer );
+ NameListFree(nl);
+return( NULL );
+ }
+ pt = end;
+ while ( *pt==' ' || *pt==';' || *pt=='\t' ) ++pt;
+ if ( *pt=='\0' ) {
+ gwwv_post_error(_("NameList parsing error"),_("Missing name when parsing %s for unicode %x"), nl->title, uni );
+ NameListFree(nl);
+return( NULL );
+ }
+ for ( test=pt; *test; ++test ) {
+ if ( (*test<=' ' && *test>=0) ||
+ *test=='(' || *test=='[' || *test=='{' || *test=='<' ||
+ *test==')' || *test==']' || *test=='}' || *test=='>' ||
+ *test=='%' || *test=='/' ) {
+ gwwv_post_error(_("NameList parsing error"),_("Bad name when parsing %s for unicode %x"), nl->title, uni );
+ NameListFree(nl);
+return( NULL );
+ }
+ if ( *test&0x80 ) {
+ uses_unicode = true;
+ if ( nl->a_utf8_name==NULL )
+ nl->a_utf8_name = copy(pt);
+ }
+ }
+ up = uni>>16;
+ ub = (uni&0xff00)>>8;
+ uc = uni&0xff;
+ if ( nl->unicode[up]==NULL )
+ nl->unicode[up] = gcalloc(256,sizeof(char **));
+ if ( nl->unicode[up][ub]==NULL )
+ nl->unicode[up][ub] = gcalloc(256,sizeof(char *));
+ if ( nl->unicode[up][ub][uc]==NULL )
+ nl->unicode[up][ub][uc]=copy(pt);
+ else {
+ gwwv_post_error(_("NameList parsing error"),_("Multiple names when parsing %s for unicode %x"), nl->title, uni );
+ NameListFree(nl);
+return( NULL );
+ }
+ }
+ }
+
+ nl->uses_unicode = uses_unicode;
+ if ( nl->basedon!=NULL && nl->basedon->uses_unicode )
+ nl->uses_unicode = true;
+ fclose(file);
+ for ( nl2 = &agl; nl2->next!=NULL; nl2=nl2->next ) {
+ if ( strcmp(nl2->title,nl->title)==0 ) { /* Replace old version */
+ NameList *next = nl2->next;
+ NameListFreeContents(nl2);
+ *nl2 = *nl;
+ nl2->next = next;
+ chunkfree(nl,sizeof(NameList));
+ psreinitnames();
+return( nl2 );
+ }
+ }
+ NameListHash(nl);
+ nl2->next = nl;
+return( nl );
+}
+
+static int isnamelist(char *filename) {
+ char *pt;
+
+ pt = strrchr(filename,'.');
+ if ( pt==NULL )
+return( false );
+ if ( strcmp(pt,".nam")==0 )
+return( true );
+
+return( false );
+}
+
+void LoadNamelistDir(char *dir) {
+ char prefdir[1024];
+ DIR *diro;
+ struct dirent *ent;
+ char buffer[1025];
+
+ if ( dir == NULL )
+ dir = getPfaEditDir(prefdir);
+ if ( dir == NULL )
+return;
+
+ diro = opendir(dir);
+ if ( diro==NULL ) /* It's ok not to have any */
+return;
+
+ while ( (ent = readdir(diro))!=NULL ) {
+ if ( isnamelist(ent->d_name) ) {
+ sprintf( buffer, "%s/%s", dir, ent->d_name );
+ LoadNamelist(buffer);
+ }
+ }
+ closedir(diro);
+}
+#endif
+
+#ifndef LUA_FF_LIB
+/* ************************************************************************** */
+const char *RenameGlyphToNamelist(char *buffer, SplineChar *sc,NameList *old,NameList *new) {
+ int i, up, ub, uc, ch;
+ char space[80]; /* glyph names are supposed to be less<=31 chars */
+ char tempbuf[32];
+ char *pt, *start, *opt, *oend; const char *newsubname;
+ SplineChar *tempsc;
+ NameList *nl;
+
+ if ( sc->unicodeenc!=-1 ) {
+ up = sc->unicodeenc>>16;
+ ub = (sc->unicodeenc>>8)&0xff;
+ uc = (sc->unicodeenc&0xff);
+ for ( nl=new; nl!=NULL; nl=nl->basedon )
+ if ( nl->unicode[up]!=NULL && nl->unicode[up][ub]!=NULL && nl->unicode[up][ub][uc]!=NULL )
+return( nl->unicode[up][ub][uc] );
+ if ( up==0 )
+ sprintf( buffer, "uni%04X", sc->unicodeenc );
+ else
+ sprintf( buffer, "u%04X", sc->unicodeenc );
+return( buffer );
+ } else {
+ if ( old!=NULL && old->renames!=NULL ) {
+ for ( i=0; old->renames[i].from!=NULL; ++i )
+ if ( strcmp(sc->name,old->renames[i].from)==0 )
+return( old->renames[i].to );
+ }
+ if ( new->renames!=NULL ) {
+ for ( i=0; new->renames[i].from!=NULL; ++i )
+ if ( strcmp(sc->name,new->renames[i].to)==0 )
+return( new->renames[i].from );
+ }
+ if ( strlen(sc->name)>sizeof(space)-1 )
+return( sc->name );
+ strcpy(space,sc->name);
+ opt = buffer; oend = buffer+31;
+ start = space;
+ /* Check for composite names f_i, A.small */
+ while ( *start ) {
+ for ( pt=start; *pt!='\0' && *pt!='.' && *pt!='_'; ++pt );
+ if ( *pt=='\0' && start==space )
+return( sc->name );
+ ch = *pt;
+ *pt = '\0';
+ tempsc = SFGetChar(sc->parent,-1,start);
+ if ( tempsc==NULL )
+return( sc->name );
+ newsubname = RenameGlyphToNamelist(tempbuf,tempsc,old,new);
+ while ( opt<oend && *newsubname )
+ *opt++ = *newsubname++;
+ if ( *newsubname )
+return( sc->name );
+ if ( ch=='\0' ) {
+ *opt = '\0';
+return( buffer );
+ } else if ( ch=='.' ) {
+ /* don't attempt to translate anything after a '.' just copy that litterally */
+ while ( opt<oend && *pt )
+ *opt++ = *pt++;
+ if ( *pt )
+return( sc->name );
+ *opt = '\0';
+return( buffer );
+ } else { /* _ */
+ *opt++ = '_';
+ start = pt+1;
+ }
+ }
+ *opt = '\0';
+return( buffer );
+ }
+}
+
+void SFRenameGlyphsToNamelist(SplineFont *sf,NameList *new) {
+ int gid;
+ char buffer[40]; const char *name;
+ SplineChar *sc;
+
+ if ( new==NULL )
+return;
+
+ for ( gid = 0; gid<sf->glyphcnt; ++gid ) if ( (sc=sf->glyphs[gid])!=NULL ) {
+ name = RenameGlyphToNamelist(buffer,sc,sf->for_new_glyphs,new);
+ if ( name!=sc->name ) {
+ free(sc->name);
+ sc->name = copy(name);
+ }
+ }
+ sf->for_new_glyphs = new;
+}
+
+
+char **SFTemporaryRenameGlyphsToNamelist(SplineFont *sf,NameList *new) {
+ int gid;
+ char buffer[40]; const char *name;
+ SplineChar *sc;
+ char **ret;
+
+ if ( new==NULL )
+return( NULL );
+
+ ret = gcalloc(sf->glyphcnt,sizeof(char *));
+ for ( gid = 0; gid<sf->glyphcnt; ++gid ) if ( (sc=sf->glyphs[gid])!=NULL ) {
+ name = RenameGlyphToNamelist(buffer,sc,sf->for_new_glyphs,new);
+ if ( name!=sc->name ) {
+ ret[gid] = sc->name;
+ sc->name = copy(name);
+ }
+ }
+return( ret );
+}
+
+void SFTemporaryRestoreGlyphNames(SplineFont *sf,char **former) {
+ int gid;
+ SplineChar *sc;
+
+ for ( gid = 0; gid<sf->glyphcnt; ++gid ) if ( (sc=sf->glyphs[gid])!=NULL ) {
+ if ( former[gid]!=NULL ) {
+ free(sc->name);
+ sc->name = former[gid];
+ }
+ }
+ free(former);
+}
+
+#endif
+/* ************************************************************************** */
+static const char *agl_sans_p0_b0[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quotesingle",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "grave",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+ "braceright",
+ "asciitilde",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "exclamdown",
+ "cent",
+ "sterling",
+ "currency",
+ "yen",
+ "brokenbar",
+ "section",
+ "dieresis",
+ "copyright",
+ "ordfeminine",
+ "guillemotleft",
+ "logicalnot",
+ NULL,
+ "registered",
+ "macron",
+ "degree",
+ "plusminus",
+ NULL,
+ NULL,
+ "acute",
+ NULL,
+ "paragraph",
+ "periodcentered",
+ "cedilla",
+ NULL,
+ "ordmasculine",
+ "guillemotright",
+ "onequarter",
+ "onehalf",
+ "threequarters",
+ "questiondown",
+ "Agrave",
+ "Aacute",
+ "Acircumflex",
+ "Atilde",
+ "Adieresis",
+ "Aring",
+ "AE",
+ "Ccedilla",
+ "Egrave",
+ "Eacute",
+ "Ecircumflex",
+ "Edieresis",
+ "Igrave",
+ "Iacute",
+ "Icircumflex",
+ "Idieresis",
+ "Eth",
+ "Ntilde",
+ "Ograve",
+ "Oacute",
+ "Ocircumflex",
+ "Otilde",
+ "Odieresis",
+ "multiply",
+ "Oslash",
+ "Ugrave",
+ "Uacute",
+ "Ucircumflex",
+ "Udieresis",
+ "Yacute",
+ "Thorn",
+ "germandbls",
+ "agrave",
+ "aacute",
+ "acircumflex",
+ "atilde",
+ "adieresis",
+ "aring",
+ "ae",
+ "ccedilla",
+ "egrave",
+ "eacute",
+ "ecircumflex",
+ "edieresis",
+ "igrave",
+ "iacute",
+ "icircumflex",
+ "idieresis",
+ "eth",
+ "ntilde",
+ "ograve",
+ "oacute",
+ "ocircumflex",
+ "otilde",
+ "odieresis",
+ "divide",
+ "oslash",
+ "ugrave",
+ "uacute",
+ "ucircumflex",
+ "udieresis",
+ "yacute",
+ "thorn",
+ "ydieresis"
+};
+
+static const char *agl_sans_p0_b1[] = {
+ "Amacron",
+ "amacron",
+ "Abreve",
+ "abreve",
+ "Aogonek",
+ "aogonek",
+ "Cacute",
+ "cacute",
+ "Ccircumflex",
+ "ccircumflex",
+ "Cdotaccent",
+ "cdotaccent",
+ "Ccaron",
+ "ccaron",
+ "Dcaron",
+ "dcaron",
+ "Dcroat",
+ "dcroat",
+ "Emacron",
+ "emacron",
+ "Ebreve",
+ "ebreve",
+ "Edotaccent",
+ "edotaccent",
+ "Eogonek",
+ "eogonek",
+ "Ecaron",
+ "ecaron",
+ "Gcircumflex",
+ "gcircumflex",
+ "Gbreve",
+ "gbreve",
+ "Gdotaccent",
+ "gdotaccent",
+ "Gcommaaccent",
+ "gcommaaccent",
+ "Hcircumflex",
+ "hcircumflex",
+ "Hbar",
+ "hbar",
+ "Itilde",
+ "itilde",
+ "Imacron",
+ "imacron",
+ "Ibreve",
+ "ibreve",
+ "Iogonek",
+ "iogonek",
+ "Idotaccent",
+ "dotlessi",
+ "IJ",
+ "ij",
+ "Jcircumflex",
+ "jcircumflex",
+ "Kcommaaccent",
+ "kcommaaccent",
+ "kgreenlandic",
+ "Lacute",
+ "lacute",
+ "Lcommaaccent",
+ "lcommaaccent",
+ "Lcaron",
+ "lcaron",
+ "Ldot",
+ "ldot",
+ "Lslash",
+ "lslash",
+ "Nacute",
+ "nacute",
+ "Ncommaaccent",
+ "ncommaaccent",
+ "Ncaron",
+ "ncaron",
+ "napostrophe",
+ "Eng",
+ "eng",
+ "Omacron",
+ "omacron",
+ "Obreve",
+ "obreve",
+ "Ohungarumlaut",
+ "ohungarumlaut",
+ "OE",
+ "oe",
+ "Racute",
+ "racute",
+ "Rcommaaccent",
+ "rcommaaccent",
+ "Rcaron",
+ "rcaron",
+ "Sacute",
+ "sacute",
+ "Scircumflex",
+ "scircumflex",
+ "Scedilla",
+ "scedilla",
+ "Scaron",
+ "scaron",
+ NULL,
+ NULL,
+ "Tcaron",
+ "tcaron",
+ "Tbar",
+ "tbar",
+ "Utilde",
+ "utilde",
+ "Umacron",
+ "umacron",
+ "Ubreve",
+ "ubreve",
+ "Uring",
+ "uring",
+ "Uhungarumlaut",
+ "uhungarumlaut",
+ "Uogonek",
+ "uogonek",
+ "Wcircumflex",
+ "wcircumflex",
+ "Ycircumflex",
+ "ycircumflex",
+ "Ydieresis",
+ "Zacute",
+ "zacute",
+ "Zdotaccent",
+ "zdotaccent",
+ "Zcaron",
+ "zcaron",
+ "longs",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "florin",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Ohorn",
+ "ohorn",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Uhorn",
+ "uhorn",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Gcaron",
+ "gcaron",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Aringacute",
+ "aringacute",
+ "AEacute",
+ "aeacute",
+ "Oslashacute",
+ "oslashacute"
+};
+
+static const char *agl_sans_p0_b2[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Scommaaccent",
+ "scommaaccent",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "circumflex",
+ "caron",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "breve",
+ "dotaccent",
+ "ring",
+ "ogonek",
+ "tilde",
+ "hungarumlaut",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *agl_sans_p0_b3[] = {
+ "gravecomb",
+ "acutecomb",
+ NULL,
+ "tildecomb",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "hookabovecomb",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "dotbelowcomb",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "tonos",
+ "dieresistonos",
+ "Alphatonos",
+ "anoteleia",
+ "Epsilontonos",
+ "Etatonos",
+ "Iotatonos",
+ NULL,
+ "Omicrontonos",
+ NULL,
+ "Upsilontonos",
+ "Omegatonos",
+ "iotadieresistonos",
+ "Alpha",
+ "Beta",
+ "Gamma",
+ "Delta",
+ "Epsilon",
+ "Zeta",
+ "Eta",
+ "Theta",
+ "Iota",
+ "Kappa",
+ "Lambda",
+ "Mu",
+ "Nu",
+ "Xi",
+ "Omicron",
+ "Pi",
+ "Rho",
+ NULL,
+ "Sigma",
+ "Tau",
+ "Upsilon",
+ "Phi",
+ "Chi",
+ "Psi",
+ "Omega",
+ "Iotadieresis",
+ "Upsilondieresis",
+ "alphatonos",
+ "epsilontonos",
+ "etatonos",
+ "iotatonos",
+ "upsilondieresistonos",
+ "alpha",
+ "beta",
+ "gamma",
+ "delta",
+ "epsilon",
+ "zeta",
+ "eta",
+ "theta",
+ "iota",
+ "kappa",
+ "lambda",
+ "mu",
+ "nu",
+ "xi",
+ "omicron",
+ "pi",
+ "rho",
+ "sigma1",
+ "sigma",
+ "tau",
+ "upsilon",
+ "phi",
+ "chi",
+ "psi",
+ "omega",
+ "iotadieresis",
+ "upsilondieresis",
+ "omicrontonos",
+ "upsilontonos",
+ "omegatonos",
+ NULL,
+ NULL,
+ "theta1",
+ "Upsilon1",
+ NULL,
+ NULL,
+ "phi1",
+ "omega1",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *agl_sans_p0_b1e[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Wgrave",
+ "wgrave",
+ "Wacute",
+ "wacute",
+ "Wdieresis",
+ "wdieresis",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Ygrave",
+ "ygrave",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *agl_sans_p0_b20[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "figuredash",
+ "endash",
+ "emdash",
+ NULL,
+ NULL,
+ "underscoredbl",
+ "quoteleft",
+ "quoteright",
+ "quotesinglbase",
+ "quotereversed",
+ "quotedblleft",
+ "quotedblright",
+ "quotedblbase",
+ NULL,
+ "dagger",
+ "daggerdbl",
+ "bullet",
+ NULL,
+ "onedotenleader",
+ "twodotenleader",
+ "ellipsis",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "perthousand",
+ NULL,
+ "minute",
+ "second",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "guilsinglleft",
+ "guilsinglright",
+ NULL,
+ "exclamdbl",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "fraction",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "colonmonetary",
+ NULL,
+ "franc",
+ "lira",
+ NULL,
+ NULL,
+ "peseta",
+ NULL,
+ NULL,
+ NULL,
+ "dong",
+ "Euro",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *agl_sans_p0_b21[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Ifraktur",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "weierstrass",
+ NULL,
+ NULL,
+ NULL,
+ "Rfraktur",
+ NULL,
+ "prescription",
+ NULL,
+ NULL,
+ NULL,
+ "trademark",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "estimated",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "aleph",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "onethird",
+ "twothirds",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "oneeighth",
+ "threeeighths",
+ "fiveeighths",
+ "seveneighths",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "arrowleft",
+ "arrowup",
+ "arrowright",
+ "arrowdown",
+ "arrowboth",
+ "arrowupdn",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "arrowupdnbse",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "carriagereturn",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "arrowdblleft",
+ "arrowdblup",
+ "arrowdblright",
+ "arrowdbldown",
+ "arrowdblboth",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *agl_sans_p0_b22[] = {
+ "universal",
+ NULL,
+ "partialdiff",
+ "existential",
+ NULL,
+ "emptyset",
+ NULL,
+ "gradient",
+ "element",
+ "notelement",
+ NULL,
+ "suchthat",
+ NULL,
+ NULL,
+ NULL,
+ "product",
+ NULL,
+ "summation",
+ "minus",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "asteriskmath",
+ NULL,
+ NULL,
+ "radical",
+ NULL,
+ NULL,
+ "proportional",
+ "infinity",
+ "orthogonal",
+ "angle",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "logicaland",
+ "logicalor",
+ "intersection",
+ "union",
+ "integral",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "therefore",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "similar",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "congruent",
+ NULL,
+ NULL,
+ "approxequal",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "notequal",
+ "equivalence",
+ NULL,
+ NULL,
+ "lessequal",
+ "greaterequal",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "propersubset",
+ "propersuperset",
+ "notsubset",
+ NULL,
+ "reflexsubset",
+ "reflexsuperset",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "circleplus",
+ NULL,
+ "circlemultiply",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "perpendicular",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "dotmath",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *agl_sans_p0_b23[] = {
+ NULL,
+ NULL,
+ "house",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "revlogicalnot",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "integraltp",
+ "integralbt",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "angleleft",
+ "angleright",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *agl_sans_p0_b25[] = {
+ "SF100000",
+ NULL,
+ "SF110000",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "SF010000",
+ NULL,
+ NULL,
+ NULL,
+ "SF030000",
+ NULL,
+ NULL,
+ NULL,
+ "SF020000",
+ NULL,
+ NULL,
+ NULL,
+ "SF040000",
+ NULL,
+ NULL,
+ NULL,
+ "SF080000",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "SF090000",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "SF060000",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "SF070000",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "SF050000",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "SF430000",
+ "SF240000",
+ "SF510000",
+ "SF520000",
+ "SF390000",
+ "SF220000",
+ "SF210000",
+ "SF250000",
+ "SF500000",
+ "SF490000",
+ "SF380000",
+ "SF280000",
+ "SF270000",
+ "SF260000",
+ "SF360000",
+ "SF370000",
+ "SF420000",
+ "SF190000",
+ "SF200000",
+ "SF230000",
+ "SF470000",
+ "SF480000",
+ "SF410000",
+ "SF450000",
+ "SF460000",
+ "SF400000",
+ "SF540000",
+ "SF530000",
+ "SF440000",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "upblock",
+ NULL,
+ NULL,
+ NULL,
+ "dnblock",
+ NULL,
+ NULL,
+ NULL,
+ "block",
+ NULL,
+ NULL,
+ NULL,
+ "lfblock",
+ NULL,
+ NULL,
+ NULL,
+ "rtblock",
+ "ltshade",
+ "shade",
+ "dkshade",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "filledbox",
+ "H22073",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "H18543",
+ "H18551",
+ "filledrect",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "triagup",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "triagrt",
+ NULL,
+ "triagdn",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "triaglf",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "lozenge",
+ "circle",
+ NULL,
+ NULL,
+ NULL,
+ "H18533",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "invbullet",
+ "invcircle",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "openbullet",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *agl_sans_p0_b26[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "smileface",
+ "invsmileface",
+ "sun",
+ NULL,
+ NULL,
+ NULL,
+ "female",
+ NULL,
+ "male",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "spade",
+ NULL,
+ NULL,
+ "club",
+ NULL,
+ "heart",
+ "diamond",
+ NULL,
+ NULL,
+ NULL,
+ "musicalnote",
+ "musicalnotedbl",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char **agl_sans_p0[] = {
+ agl_sans_p0_b0,
+ agl_sans_p0_b1,
+ agl_sans_p0_b2,
+ agl_sans_p0_b3,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ agl_sans_p0_b1e,
+ NULL,
+ agl_sans_p0_b20,
+ agl_sans_p0_b21,
+ agl_sans_p0_b22,
+ agl_sans_p0_b23,
+ NULL,
+ agl_sans_p0_b25,
+ agl_sans_p0_b26,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static NameList agl_sans = {
+ NULL,
+ N_("AGL without afii"),
+ { agl_sans_p0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+};
+/* ************************************************************************** */
+static const char *agl_p0_b1[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Tcommaaccent",
+ "tcommaaccent",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *agl_p0_b2[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57929",
+ "afii64937",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *agl_p0_b4[] = {
+ NULL,
+ "afii10023",
+ "afii10051",
+ "afii10052",
+ "afii10053",
+ "afii10054",
+ "afii10055",
+ "afii10056",
+ "afii10057",
+ "afii10058",
+ "afii10059",
+ "afii10060",
+ "afii10061",
+ NULL,
+ "afii10062",
+ "afii10145",
+ "afii10017",
+ "afii10018",
+ "afii10019",
+ "afii10020",
+ "afii10021",
+ "afii10022",
+ "afii10024",
+ "afii10025",
+ "afii10026",
+ "afii10027",
+ "afii10028",
+ "afii10029",
+ "afii10030",
+ "afii10031",
+ "afii10032",
+ "afii10033",
+ "afii10034",
+ "afii10035",
+ "afii10036",
+ "afii10037",
+ "afii10038",
+ "afii10039",
+ "afii10040",
+ "afii10041",
+ "afii10042",
+ "afii10043",
+ "afii10044",
+ "afii10045",
+ "afii10046",
+ "afii10047",
+ "afii10048",
+ "afii10049",
+ "afii10065",
+ "afii10066",
+ "afii10067",
+ "afii10068",
+ "afii10069",
+ "afii10070",
+ "afii10072",
+ "afii10073",
+ "afii10074",
+ "afii10075",
+ "afii10076",
+ "afii10077",
+ "afii10078",
+ "afii10079",
+ "afii10080",
+ "afii10081",
+ "afii10082",
+ "afii10083",
+ "afii10084",
+ "afii10085",
+ "afii10086",
+ "afii10087",
+ "afii10088",
+ "afii10089",
+ "afii10090",
+ "afii10091",
+ "afii10092",
+ "afii10093",
+ "afii10094",
+ "afii10095",
+ "afii10096",
+ "afii10097",
+ NULL,
+ "afii10071",
+ "afii10099",
+ "afii10100",
+ "afii10101",
+ "afii10102",
+ "afii10103",
+ "afii10104",
+ "afii10105",
+ "afii10106",
+ "afii10107",
+ "afii10108",
+ "afii10109",
+ NULL,
+ "afii10110",
+ "afii10193",
+ NULL,
+ NULL,
+ "afii10146",
+ "afii10194",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii10147",
+ "afii10195",
+ "afii10148",
+ "afii10196",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii10050",
+ "afii10098",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii10846",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *agl_p0_b5[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57799",
+ "afii57801",
+ "afii57800",
+ "afii57802",
+ "afii57793",
+ "afii57794",
+ "afii57795",
+ "afii57798",
+ "afii57797",
+ "afii57806",
+ NULL,
+ "afii57796",
+ "afii57807",
+ "afii57839",
+ "afii57645",
+ "afii57841",
+ "afii57842",
+ "afii57804",
+ "afii57803",
+ "afii57658",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57664",
+ "afii57665",
+ "afii57666",
+ "afii57667",
+ "afii57668",
+ "afii57669",
+ "afii57670",
+ "afii57671",
+ "afii57672",
+ "afii57673",
+ "afii57674",
+ "afii57675",
+ "afii57676",
+ "afii57677",
+ "afii57678",
+ "afii57679",
+ "afii57680",
+ "afii57681",
+ "afii57682",
+ "afii57683",
+ "afii57684",
+ "afii57685",
+ "afii57686",
+ "afii57687",
+ "afii57688",
+ "afii57689",
+ "afii57690",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57716",
+ "afii57717",
+ "afii57718",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *agl_p0_b6[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57388",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57403",
+ NULL,
+ NULL,
+ NULL,
+ "afii57407",
+ NULL,
+ "afii57409",
+ "afii57410",
+ "afii57411",
+ "afii57412",
+ "afii57413",
+ "afii57414",
+ "afii57415",
+ "afii57416",
+ "afii57417",
+ "afii57418",
+ "afii57419",
+ "afii57420",
+ "afii57421",
+ "afii57422",
+ "afii57423",
+ "afii57424",
+ "afii57425",
+ "afii57426",
+ "afii57427",
+ "afii57428",
+ "afii57429",
+ "afii57430",
+ "afii57431",
+ "afii57432",
+ "afii57433",
+ "afii57434",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57440",
+ "afii57441",
+ "afii57442",
+ "afii57443",
+ "afii57444",
+ "afii57445",
+ "afii57446",
+ "afii57470",
+ "afii57448",
+ "afii57449",
+ "afii57450",
+ "afii57451",
+ "afii57452",
+ "afii57453",
+ "afii57454",
+ "afii57455",
+ "afii57456",
+ "afii57457",
+ "afii57458",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57392",
+ "afii57393",
+ "afii57394",
+ "afii57395",
+ "afii57396",
+ "afii57397",
+ "afii57398",
+ "afii57399",
+ "afii57400",
+ "afii57401",
+ "afii57381",
+ NULL,
+ NULL,
+ "afii63167",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57511",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57506",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57507",
+ NULL,
+ "afii57512",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57513",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57508",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57505",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57509",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57514",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57519",
+ NULL,
+ NULL,
+ "afii57534",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *agl_p0_b20[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii61664",
+ "afii301",
+ "afii299",
+ "afii300",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii00208",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii61573",
+ "afii61574",
+ "afii61575",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii57636",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *agl_p0_b21[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii61248",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii61289",
+ NULL,
+ NULL,
+ "afii61352",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char **agl_p0[] = {
+ NULL,
+ agl_p0_b1,
+ agl_p0_b2,
+ NULL,
+ agl_p0_b4,
+ agl_p0_b5,
+ agl_p0_b6,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ agl_p0_b20,
+ agl_p0_b21,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static NameList agl = {
+ &agl_sans,
+ N_("Adobe Glyph List"),
+ { agl_p0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+};
+/* ************************************************************************** */
+static const char *adobepua_p0_bf6[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "perthousand.oldstyle",
+ "cent.denominator",
+ "dollar.denominator",
+ "hyphen.denominator",
+ "parenleft.denominator",
+ "parenright.denominator",
+ "cent.numerator",
+ "dollar.numerator",
+ "hyphen.numerator",
+ "parenleft.numerator",
+ "parenright.numerator",
+ "at.cap",
+ "commaaccent.cap",
+ "commaaccent.small",
+ "pi.math",
+ "h.superior",
+ "zero.slash",
+ "zero.fitted",
+ "two.fitted",
+ "three.fitted",
+ "four.fitted",
+ "five.fitted",
+ "six.fitted",
+ "seven.fitted",
+ "eight.fitted",
+ "nine.fitted",
+ "percent.oldstyle",
+ "zero.taboldstyle",
+ "one.taboldstyle",
+ "two.taboldstyle",
+ "three.taboldstyle",
+ "four.taboldstyle",
+ "five.taboldstyle",
+ "six.taboldstyle",
+ "seven.taboldstyle",
+ "eight.taboldstyle",
+ "nine.taboldstyle",
+ "colonmonetary.taboldstyle",
+ "Euro.taboldstyle",
+ "florin.taboldstyle",
+ "numbersign.taboldstyle",
+ "sterling.taboldstyle",
+ "yen.taboldstyle",
+ "dollar.taboldstyle",
+ "cent.taboldstyle",
+ "zero.denominator",
+ "one.denominator",
+ "two.denominator",
+ "three.denominator",
+ "four.denominator",
+ "five.denominator",
+ "six.denominator",
+ "seven.denominator",
+ "eight.denominator",
+ "nine.denominator",
+ "comma.denominator",
+ "period.denominator",
+ "zero.numerator",
+ "one.numerator",
+ "two.numerator",
+ "three.numerator",
+ "four.numerator",
+ "five.numerator",
+ "six.numerator",
+ "seven.numerator",
+ "eight.numerator",
+ "nine.numerator",
+ "comma.numerator",
+ "period.numerator",
+ "Abreve.small",
+ "Amacron.small",
+ "Aogonek.small",
+ "AEacute.small",
+ "Cacute.small",
+ "Ccaron.small",
+ "Ccircumflex.small",
+ "Cdotaccent.small",
+ "Dcaron.small",
+ "Dcroat.small",
+ "Ebreve.small",
+ "Ecaron.small",
+ "Edotaccent.small",
+ "Emacron.small",
+ "Eng.small",
+ "Eogonek.small",
+ "Gbreve.small",
+ "Gcircumflex.small",
+ "Gcommaaccent.small",
+ "Gdotaccent.small",
+ "Hbar.small",
+ "Hcircumflex.small",
+ "Ibreve.small",
+ "IJ.small",
+ "Imacron.small",
+ "Iogonek.small",
+ "Itilde.small",
+ "Jcircumflex.small",
+ "Kcommaaccent.small",
+ "Lacute.small",
+ "Lcaron.small",
+ "Lcommaaccent.small",
+ "Ldot.small",
+ "Nacute.small",
+ "Ncaron.small",
+ "Ncommaaccent.small",
+ "Obreve.small",
+ "Ohungarumlaut.small",
+ "Omacron.small",
+ "Oslashacute.small",
+ "Racute.small",
+ "Rcaron.small",
+ "Rcommaaccent.small",
+ "Sacute.small",
+ "Scedilla.small",
+ "Scircumflex.small",
+ "Scommaaccent.small",
+ "Tbar.small",
+ "Tcaron.small",
+ "Tcommaaccent.small",
+ "Ubreve.small",
+ "Uhungarumlaut.small",
+ "Umacron.small",
+ "Uogonek.small",
+ "Uring.small",
+ "Utilde.small",
+ "Wacute.small",
+ "Wcircumflex.small",
+ "Wdieresis.small",
+ "Wgrave.small",
+ "Ycircumflex.small",
+ "Ygrave.small",
+ "Zacute.small",
+ "Zdotaccent.small",
+ "Idotaccent.small",
+ "parenleft.cap",
+ "parenright.cap",
+ "bracketleft.cap",
+ "bracketright.cap",
+ "braceleft.cap",
+ "braceright.cap",
+ "exclamdown.cap",
+ "questiondown.cap",
+ "guillemotleft.cap",
+ "guillemotright.cap",
+ "guilsinglleft.cap",
+ "guilsinglright.cap",
+ "hyphen.cap",
+ "endash.cap",
+ "emdash.cap",
+ "periodcentered.cap",
+ "j.dotless",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "afii10068.ital",
+ "afii10066.ital",
+ "afii10069.ital",
+ "afii10081.ital",
+ "afii10084.ital",
+ "acute.cap",
+ "caron.cap",
+ "dieresis.cap",
+ "space_uni0308_uni0301.cap",
+ "space_uni0308_uni0300.cap",
+ "grave.cap",
+ "hungarumlaut.cap",
+ "macron.cap",
+ "breve.cyrcap",
+ "circumflex.cyrcap",
+ "space_uni030F.cap",
+ "breve.cyr",
+ "circumflex.cyr",
+ "space_uni030F",
+ "space_uni0308_uni0301",
+ "space_uni0308_uni0300",
+ "copyright.serif",
+ "registered.serif",
+ "trademark.serif",
+ "one.fitted",
+ "R_p",
+ "uni2014.alt",
+ "cent.inferior",
+ "cent.superior",
+ "comma.inferior",
+ "comma.superior",
+ "dollar.inferior",
+ "dollar.superior",
+ "hyphen.inferior",
+ "hyphen.superior",
+ "period.inferior",
+ "period.superior",
+ "a.superior",
+ "b.superior",
+ "d.superior",
+ "e.superior",
+ "i.superior",
+ "l.superior",
+ "m.superior",
+ "o.superior",
+ "r.superior",
+ "s.superior",
+ "t.superior",
+ "breve.sc",
+ "caron.sc",
+ "circumflex.sc",
+ "dotaccent.sc",
+ "hungarumlaut.sc",
+ "lslash.sc",
+ "oe.sc",
+ "ogonek.sc",
+ "ring.sc",
+ "scaron.sc",
+ "tilde.sc",
+ "zcaron.sc"
+};
+
+static const char *adobepua_p0_bf7[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "exclam.sc",
+ NULL,
+ NULL,
+ "dollar.oldstyle",
+ NULL,
+ "ampersand.sc",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "zero.oldstyle",
+ "one.oldstyle",
+ "two.oldstyle",
+ "three.oldstyle",
+ "four.oldstyle",
+ "five.oldstyle",
+ "six.oldstyle",
+ "seven.oldstyle",
+ "eight.oldstyle",
+ "nine.oldstyle",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "question.sc",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "grave.sc",
+ "a.sc",
+ "b.sc",
+ "c.sc",
+ "d.sc",
+ "e.sc",
+ "f.sc",
+ "g.sc",
+ "h.sc",
+ "i.sc",
+ "j.sc",
+ "k.sc",
+ "l.sc",
+ "m.sc",
+ "n.sc",
+ "o.sc",
+ "p.sc",
+ "q.sc",
+ "r.sc",
+ "s.sc",
+ "t.sc",
+ "u.sc",
+ "v.sc",
+ "w.sc",
+ "x.sc",
+ "y.sc",
+ "z.sc",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "exclamdown.sc",
+ "cent.oldstyle",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "dieresis.sc",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "macron.sc",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "acute.sc",
+ NULL,
+ NULL,
+ NULL,
+ "cedilla.sc",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "questiondown.sc",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "agrave.sc",
+ "aacute.sc",
+ "acircumflex.sc",
+ "atilde.sc",
+ "adieresis.sc",
+ "aring.sc",
+ "ae.sc",
+ "ccedilla.sc",
+ "egrave.sc",
+ "eacute.sc",
+ "ecircumflex.sc",
+ "edieresis.sc",
+ "igrave.sc",
+ "iacute.sc",
+ "icircumflex.sc",
+ "idieresis.sc",
+ "eth.sc",
+ "ntilde.sc",
+ "ograve.sc",
+ "oacute.sc",
+ "ocircumflex.sc",
+ "otilde.sc",
+ "odieresis.sc",
+ NULL,
+ "oslash.sc",
+ "ugrave.sc",
+ "uacute.sc",
+ "ucircumflex.sc",
+ "udieresis.sc",
+ "yacute.sc",
+ "thorn.sc",
+ "ydieresis.sc"
+};
+
+static const char *adobepua_p0_bf8[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "registered.sans",
+ "copyright.sans",
+ "trademark.sans",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *adobepua_p0_bfb[] = {
+ "f_f",
+ "f_i",
+ "f_l",
+ "f_f_i",
+ "f_f_l",
+ "longs_t",
+ "s_t",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char **adobepua_p0[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ adobepua_p0_bf6,
+ adobepua_p0_bf7,
+ adobepua_p0_bf8,
+ NULL,
+ NULL,
+ adobepua_p0_bfb,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static NameList adobepua = {
+ &agl,
+ N_("AGL with PUA"),
+ { adobepua_p0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+};
+/* ************************************************************************** */
+static const char *greeksc_p0_bf5[] = {
+ "alpha.sc",
+ "beta.sc",
+ "gamma.sc",
+ "delta.sc",
+ "epsilon.sc",
+ "zeta.sc",
+ "eta.sc",
+ "theta.sc",
+ "iota.sc",
+ "kappa.sc",
+ "lambda.sc",
+ "mu.sc",
+ "nu.sc",
+ "xi.sc",
+ "omicron.sc",
+ "pi.sc",
+ "rho.sc",
+ NULL,
+ "sigma.sc",
+ "tau.sc",
+ "upsilon.sc",
+ "phi.sc",
+ "chi.sc",
+ "psi.sc",
+ "omega.sc",
+ "iotadieresis.sc",
+ "upsilondieresis.sc",
+ "alphaiota.sc",
+ "etaiota.sc",
+ "omegaiota.sc",
+ "prosgegrammeni.sc",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char **greeksc_p0[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ greeksc_p0_bf5,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static NameList greeksc = {
+ &adobepua,
+ N_("Greek small caps"),
+ { greeksc_p0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+};
+/* ************************************************************************** */
+static const char *tex_p0_b20[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "closure",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "leftharpoonaccent",
+ "rightharpoonaccent",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *tex_p0_b21[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "shortleftarrow",
+ "shortuparrow",
+ "shortrightarrow",
+ "shortdownarrow",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "leftwavyarrow",
+ "rightwavyarrow",
+ NULL,
+ "twoheaduparrow",
+ NULL,
+ "twoheaddownarrow",
+ NULL,
+ NULL,
+ NULL,
+ "mapsup",
+ NULL,
+ "mapsdown",
+ "updownarrowbar",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "leftrightwavyarrow",
+ NULL,
+ "downzigzagarrow",
+ NULL,
+ NULL,
+ "Ldsh",
+ "Rdsh",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "acwopencirclearrow",
+ "cwopencirclearrow",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "updownarrows",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Nwarrow",
+ "Nearrow",
+ "Searrow",
+ "Swarrow",
+ NULL,
+ NULL,
+ "longleftzigzagarrow",
+ "rightzigzagarrow",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "barleftarrow",
+ "rightarrowbar",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "downuparrows",
+ "rightthreearrows",
+ "nvleftarrow",
+ "nvrightarrow",
+ "nvleftrightarrow",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *tex_p0_b22[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "ltrpar",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "difference",
+ NULL,
+ "ac",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "approxident",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "arceq",
+ NULL,
+ "veeeq",
+ "stareq",
+ NULL,
+ "eqdef",
+ "measeq",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Equiv",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "prurel",
+ "scurel",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "origof",
+ "imageof",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "eqless",
+ "eqgtr",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "disin",
+ NULL,
+ "isins",
+ "isindot",
+ NULL,
+ NULL,
+ "isinvb",
+ "isinE",
+ "nisd",
+ NULL,
+ "nis",
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *tex_p0_b23[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "invnot",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "turnednot",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "solbar",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "rangledownzigzagarrow",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *tex_p0_b27[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "longrightzigzagarrow"
+};
+
+static const char *tex_p0_b29[] = {
+ NULL,
+ NULL,
+ "nvLeftarrow",
+ "nvRightarrow",
+ "nvLeftrightarrow",
+ "twoheadmapsto",
+ NULL,
+ NULL,
+ "downarrowbarred",
+ "uparrowbarred",
+ "Uuparrow",
+ "Ddownarrow",
+ "leftbkarrow",
+ "rightbkarrow",
+ "leftdbkarrow",
+ NULL,
+ NULL,
+ "rightdotarrow",
+ "baruparrow",
+ "downarrowbar",
+ NULL,
+ NULL,
+ "twoheadrightarrowtail",
+ NULL,
+ NULL,
+ "lefttail",
+ "righttail",
+ "leftdbltail",
+ "rightdbltail",
+ "diamondleftarrow",
+ "rightarrowdiamond",
+ "diamondleftarrowbar",
+ "barrightarrowdiamond",
+ "nwsearrow",
+ "neswarrow",
+ "hknwarrow",
+ "hknearrow",
+ "hksearrow",
+ "hkswarrow",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "rdiagovfdiag",
+ "fdiagovrdiag",
+ "seovnearrow",
+ "neovsearrow",
+ "fdiagovnearrow",
+ "rdiagovsearrow",
+ "neovnwarrow",
+ "nwovnearrow",
+ "rightcurvedarrow",
+ NULL,
+ NULL,
+ "leftdowncurvedarrow",
+ "rightdowncurvedarrow",
+ "cwhalfcirclearrow",
+ "acwhalfcirclearrow",
+ NULL,
+ "acwundercurvearrow",
+ "curvearrowrightminus",
+ "curvearrowleftplus",
+ "cwundercurvearrow",
+ NULL,
+ NULL,
+ NULL,
+ "rightarrowshortleftarrow",
+ "leftarrowshortrightarrow",
+ "shortrightarrowleftarrow",
+ "rightarrowplus",
+ "leftarrowplus",
+ "rightarrowx",
+ "leftrightarrowcircle",
+ "twoheaduparrowcircle",
+ "leftrightharpoonupdown",
+ "leftrightharpoondownup",
+ "updownharpoonrightleft",
+ "updownharpoonleftright",
+ "leftrightharpoonupup",
+ "updownharpoonrightright",
+ "leftrightharpoondowndown",
+ "updownharpoonleftleft",
+ "barleftharpoonup",
+ "rightharpoonupbar",
+ "barupharpoonright",
+ "downharpoonrightbar",
+ "barleftharpoondown",
+ "rightharpoondownbar",
+ "barupharpoonleft",
+ "downharpoonleftbar",
+ "leftharpoonupbar",
+ "barrightharpoonup",
+ "upharpoonrightbar",
+ "bardownharpoonright",
+ "leftharpoondownbar",
+ "barrightharpoondown",
+ "upharpoonleftbar",
+ "bardownharpoonleft",
+ "leftharpoonsupdown",
+ "upharpoonsleftright",
+ "rightharpoonsupdown",
+ "downharpoonsleftright",
+ "leftrightharpoonsup",
+ "leftrightharpoonsdown",
+ "rightleftharpoonsup",
+ "rightleftharpoonsdown",
+ "leftharpoonupdash",
+ "dashleftharpoondown",
+ "rightharpoonupdash",
+ "dashrightharpoondown",
+ "updownharpoonsleftright",
+ "downupharpoonsleftright",
+ "rightimply",
+ "equalrightarrow",
+ "similarrightarrow",
+ "leftarrowsimilar",
+ "rightarrowsimilar",
+ "rightarrowapprox",
+ "ltlarr",
+ "leftarrowless",
+ "gtrarr",
+ "subrarr",
+ "leftarrowsubset",
+ "suplarr",
+ "leftfishtail",
+ "rightfishtail",
+ "upfishtail",
+ "downfishtail",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "rtriltri",
+ "ltrivb",
+ "vbrtri",
+ "lfbowtie",
+ "rfbowtie",
+ "fbowtie",
+ "lftimes",
+ "rftimes",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "eqvparsl",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "ruledelayed",
+ NULL,
+ "dsol",
+ "rsolbar",
+ "xsol",
+ "xbsol",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *tex_p0_b2a[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "congdot",
+ NULL,
+ NULL,
+ "approxeqq",
+ NULL,
+ NULL,
+ "eqqsim",
+ "Coloneq",
+ "eqeq",
+ NULL,
+ NULL,
+ "equivDD",
+ "ltcir",
+ "gtcir",
+ "ltquest",
+ "gtquest",
+ NULL,
+ NULL,
+ "lesdot",
+ "gesdot",
+ "lesdoto",
+ "gesdoto",
+ "lesdotor",
+ "gesdotol",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "lsime",
+ "gsime",
+ "lsimg",
+ "gsiml",
+ "lgE",
+ "glE",
+ "lesges",
+ "gesles",
+ NULL,
+ NULL,
+ "elsdot",
+ "egsdot",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "simless",
+ "simgtr",
+ "simlE",
+ "simgE",
+ "Lt",
+ "Gt",
+ NULL,
+ "glj",
+ "gla",
+ "ltcc",
+ "gtcc",
+ "lescc",
+ "gescc",
+ "smt",
+ "lat",
+ "smte",
+ "late",
+ "bumpeqq",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "prE",
+ "scE",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Pr",
+ "Sc",
+ "subsetdot",
+ "supsetdot",
+ "subsetplus",
+ "supsetplus",
+ "submult",
+ "supmult",
+ "subedot",
+ "supedot",
+ NULL,
+ NULL,
+ "subsim",
+ "supsim",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "csub",
+ "csup",
+ "csube",
+ "csupe",
+ "subsup",
+ "supsub",
+ "subsub",
+ "supsup",
+ "suphsub",
+ "supdsub",
+ "forkv",
+ "topfork",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Barv",
+ "vBar",
+ "vBarv",
+ "barV",
+ "Vbar",
+ "Not",
+ "bNot",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *tex_p0_be2[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "rightdbkarrow",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "nrightwavyarrow",
+ NULL,
+ "nrightcurvedarrow",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "race",
+ "acE",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *tex_p0_be3[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "lesg",
+ "gesl",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "smtes",
+ "lates",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "bsolhsub",
+ "suphsol",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "congruence",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *tex_p0_be4[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "mostpos",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *tex_p0_be6[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "varrightfishtail",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char **tex_p0[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ tex_p0_b20,
+ tex_p0_b21,
+ tex_p0_b22,
+ tex_p0_b23,
+ NULL,
+ NULL,
+ NULL,
+ tex_p0_b27,
+ NULL,
+ tex_p0_b29,
+ tex_p0_b2a,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ tex_p0_be2,
+ tex_p0_be3,
+ tex_p0_be4,
+ NULL,
+ tex_p0_be6,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static NameList tex = {
+ &agl,
+ NU_("ΤεΧ Names"),
+ { tex_p0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+};
+/* ************************************************************************** */
+static const char *ams_p0_be2[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni219D0338",
+ NULL,
+ "uni29330338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2192.short",
+ "uni2190.short",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni222AFE00",
+ "uni2229FE00",
+ "uni2294FE00",
+ "uni2293FE00",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni223E0332.reversed",
+ "uni223E0333",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2269FE00",
+ NULL,
+ NULL,
+ "uni2268FE00",
+ "uni22670338",
+ "uni2A7E0338",
+ "uni2A7D0338",
+ "uni22660338",
+ NULL,
+ "uni2224.short",
+ "uni2226.short",
+ "uni228220D2",
+ "uni228620D2",
+ "uni2AC50338",
+ "uni228320D2",
+ "uni2AC60338",
+ "uni228720D2",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2ACBFE00",
+ "uni228AFE00",
+ "uni228BFE00",
+ "uni2ACCFE00",
+ "uni224B0338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni226420D2",
+ "uni226520D2",
+ "uni003C20D2",
+ "uni003E20D2",
+ "uni2A6D0338",
+ "uni224820D2",
+ "uni2A700338",
+ NULL,
+ "uni2AA120D2",
+ "uni2AA220D2",
+ "uni226A0338",
+ "uni226B0338",
+ "uni22D80338",
+ "uni22D90338",
+ "uni22B520D2",
+ "uni22B420D2",
+ NULL,
+ NULL,
+ NULL,
+ "uni006A.dotless",
+ "uni210F.var",
+ NULL,
+ NULL,
+ "uni222020D2",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *ams_p0_be3[] = {
+ NULL,
+ "uni2223.short",
+ "uni2225.short",
+ NULL,
+ NULL,
+ NULL,
+ "uni2248.bold",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni22DAFE00",
+ "uni22DBFE00",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2AACFE00",
+ "uni2AADFE00",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni220B20D2",
+ "uni220D0338",
+ NULL,
+ NULL,
+ "uni220820D2",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2A15.up",
+ "uni2A16.up",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni226120E5",
+ "uni003D20E5",
+ "uni2AFD20E5",
+ "uni22500338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni22020338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2A10.up",
+ NULL,
+ "uni2A12.up",
+ "uni2A13.up",
+ "uni2A14.up",
+ "uni2A17.up",
+ "uni2A11.up",
+ NULL,
+ "uni22F50338",
+ NULL,
+ "uni22F90338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2026.em",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni220A0338",
+ "uni227320D2",
+ "uni227220D2",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni223E.reversed",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni0265.superscript",
+ "uni0252.superscript",
+ NULL,
+ NULL,
+ NULL,
+ "uni2A0F.up",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2A9B20D2",
+ "uni2A9C20D2",
+ "uni2A9B0338",
+ "uni2A9C0338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *ams_p0_be4[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni223E.var",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni223C20D2",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *ams_p0_be5[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2A3CFE00",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2AAF0338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni224220D2",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2AB00338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *ams_p0_be6[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni228F0338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni22900338",
+ "uni224E0338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2205.var",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni0077.subscript",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni1D0B.reversed",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni025102DE",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni025B02DE",
+ "uni025402DE",
+ NULL,
+ "uni03C9.inverted",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni297D.var",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni223C.bold",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *ams_p0_be8[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni227E0338",
+ "uni227F0338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2216.var",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni224F0338",
+ "uni22420338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *ams_p0_bea[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni00730336",
+ NULL,
+ "uni006C0321",
+ NULL,
+ NULL,
+ "uni03040304",
+ NULL,
+ NULL,
+ "uni229CFE00",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni03020302",
+ NULL,
+ "uni03030303",
+ "uni033103310331",
+ "uni0331033103310331",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni03070302",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni03040303",
+ "uni03310330",
+ "uni03040308",
+ "uni03300331",
+ NULL,
+ "uni00640321",
+ "uni00680321",
+ "uni006B0321",
+ "uni00780321",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni00730321",
+ "uni007A0321",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2034.notsup",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2A0B.up",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni227620D2",
+ "uni227720D2",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *ams_p0_bec[] = {
+ NULL,
+ NULL,
+ "uni2A3DFE00",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *ams_p0_bed[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni220A20D2",
+ "uni220D20D2",
+ "uni22F60338",
+ "uni22FD0338",
+ "uni22F620D2",
+ "uni22FD20D2",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2295FE00",
+ "uni2297FE00",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni224320D2",
+ "uni224520D2",
+ NULL,
+ "uni2A6C0338",
+ "uni2A6C20D2",
+ "uni2A7020D2",
+ "uni224D20D2",
+ "uni223F.reversed",
+ "uni003D20D2",
+ NULL,
+ "uni226120D2",
+ "uni22630338",
+ "uni226320D2",
+ NULL,
+ NULL,
+ "uni2A7D20D2",
+ "uni2A7E20D2",
+ "uni226620D2",
+ "uni226720D2",
+ "uni2A950338",
+ "uni2A960338",
+ "uni2A9520D2",
+ "uni2A9620D2",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2A990338",
+ "uni2A9A0338",
+ "uni2A9920D2",
+ "uni2A9A20D2",
+ "uni2272FE00",
+ "uni2273FE00",
+ "uni2A9DFE00",
+ "uni2A9EFE00",
+ NULL,
+ NULL,
+ "uni227A20D2",
+ "uni227B20D2",
+ "uni227C20D2",
+ "uni227D20D2",
+ "uni22DE20D2",
+ "uni22DF20D2",
+ "uni22DE0338",
+ "uni22DF0338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2AC520D2",
+ "uni2AC620D2",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2AF40338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2A0A.lgdisplay",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni220A.narrow",
+ "uni220D.narrow",
+ NULL,
+ "u1D6FB.narrow",
+ "uni002820090029",
+ "uni002822C50029",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *ams_p0_bee[] = {
+ "stixEE00",
+ "stixEE01",
+ "stixEE02",
+ "stixEE03",
+ "stixEE04",
+ "stixEE05",
+ "stixEE06",
+ "stixEE07",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "stixEE10",
+ "stixEE11",
+ "stixEE12",
+ "stixEE13",
+ "stixEE14",
+ "stixEE15",
+ "stixEE16",
+ "stixEE17",
+ "stixEE18",
+ "stixEE19",
+ "stixEE1A",
+ "stixEE1B",
+ "stixEE1C",
+ "stixEE1D",
+ "stixEE1E",
+ "stixEE1F",
+ "stixEE20",
+ "stixEE21",
+ "stixEE22",
+ "stixEE23",
+ "stixEE24",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "stixEE30",
+ "stixEE31",
+ "stixEE32",
+ "stixEE33",
+ "stixEE34",
+ "stixEE35",
+ "stixEE36",
+ "stixEE37",
+ "stixEE38",
+ "stixEE39",
+ "stixEE3A",
+ "stixEE3B",
+ "stixEE3C",
+ "stixEE3D",
+ "stixEE3E",
+ NULL,
+ "stixEE40",
+ "stixEE41",
+ "stixEE42",
+ "stixEE43",
+ "stixEE44",
+ "stixEE45",
+ "stixEE46",
+ "stixEE47",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "stixEE50",
+ "stixEE51",
+ "stixEE52",
+ "stixEE53",
+ "stixEE54",
+ "stixEE55",
+ "stixEE56",
+ "stixEE57",
+ "stixEE58",
+ "stixEE59",
+ "stixEE5A",
+ "stixEE5B",
+ "stixEE5C",
+ "stixEE5D",
+ "stixEE5E",
+ "stixEE5F",
+ "stixEE60",
+ "stixEE61",
+ "stixEE62",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "stixEE70",
+ "stixEE71",
+ "stixEE72",
+ "stixEE73",
+ "stixEE74",
+ "stixEE75",
+ "stixEE76",
+ "stixEE77",
+ "stixEE78",
+ "stixEE79",
+ "stixEE7A",
+ "stixEE7B",
+ "stixEE7C",
+ "stixEE7D",
+ "stixEE7E",
+ "stixEE7F",
+ "stixEE80",
+ "stixEE81",
+ "stixEE82",
+ "stixEE83",
+ "stixEE84",
+ "stixEE85",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "stixEE90",
+ "stixEE91",
+ "stixEE92",
+ "stixEE93",
+ "stixEE94",
+ "stixEE95",
+ "stixEE96",
+ "stixEE97",
+ "stixEE98",
+ "stixEE99",
+ "stixEE9A",
+ "stixEE9B",
+ "stixEE9C",
+ "stixEE9D",
+ "stixEE9E",
+ "stixEE9F",
+ "stixEEA0",
+ "stixEEA1",
+ "stixEEA2",
+ "stixEEA3",
+ "stixEEA4",
+ "stixEEA5",
+ "stixEEA6",
+ "stixEEA7",
+ "stixEEA8",
+ "stixEEA9",
+ "stixEEAA",
+ "stixEEAB",
+ "stixEEAC",
+ NULL,
+ NULL,
+ NULL,
+ "stixEEB0",
+ "stixEEB1",
+ "stixEEB2",
+ "stixEEB3",
+ "stixEEB4",
+ "stixEEB5",
+ "stixEEB6",
+ "stixEEB7",
+ "stixEEB8",
+ "stixEEB9",
+ "stixEEBA",
+ "stixEEBB",
+ "stixEEBC",
+ "stixEEBD",
+ "stixEEBE",
+ "stixEEBF",
+ "stixEEC0",
+ "stixEEC1",
+ "stixEEC2",
+ "stixEEC3",
+ "stixEEC4",
+ "stixEEC5",
+ "stixEEC6",
+ "stixEEC7",
+ "stixEEC8",
+ "stixEEC9",
+ "stixEECA",
+ "stixEECB",
+ NULL,
+ "stixEECD",
+ "stixEECE",
+ "stixEECF",
+ "stixEED0",
+ "stixEED1",
+ "stixEED2",
+ "stixEED3",
+ "stixEED4",
+ "stixEED5",
+ "stixEED6",
+ "stixEED7",
+ "stixEED8",
+ "stixEED9",
+ "stixEEDA",
+ "stixEEDB",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *ams_p0_bf4[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni29CF0338",
+ "uni29D00338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2AA10338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2AA20338",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *ams_p0_bf5[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "uni2191.short",
+ "uni2193.short",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char **ams_p0[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ams_p0_be2,
+ ams_p0_be3,
+ ams_p0_be4,
+ ams_p0_be5,
+ ams_p0_be6,
+ NULL,
+ ams_p0_be8,
+ NULL,
+ ams_p0_bea,
+ NULL,
+ ams_p0_bec,
+ ams_p0_bed,
+ ams_p0_bee,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ams_p0_bf4,
+ ams_p0_bf5,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static NameList ams = {
+ &tex,
+ N_("AMS Names"),
+ { ams_p0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+};
+/* ************************************************************************** */
+
+static struct psaltnames psaltnames[] = {
+ { "AEmacron", 0x01e2 },
+ { "AEsmall", 0xf7e6 },
+ { "Aacutesmall", 0xf7e1 },
+ { "Abreveacute", 0x1eae },
+ { "Abrevecyrillic", 0x04d0 },
+ { "Abrevedotbelow", 0x1eb6 },
+ { "Abrevegrave", 0x1eb0 },
+ { "Abrevehookabove", 0x1eb2 },
+ { "Abrevetilde", 0x1eb4 },
+ { "Acaron", 0x01cd },
+ { "Acircle", 0x24b6 },
+ { "Acircumflexacute", 0x1ea4 },
+ { "Acircumflexdotbelow", 0x1eac },
+ { "Acircumflexgrave", 0x1ea6 },
+ { "Acircumflexhookabove", 0x1ea8 },
+ { "Acircumflexsmall", 0xf7e2 },
+ { "Acircumflextilde", 0x1eaa },
+ { "Acute", 0xf6c9 },
+ { "Acutesmall", 0xf7b4 },
+ { "Acyrillic", 0x0410 },
+ { "Adblgrave", 0x0200 },
+ { "Adieresiscyrillic", 0x04d2 },
+ { "Adieresismacron", 0x01de },
+ { "Adieresissmall", 0xf7e4 },
+ { "Adotbelow", 0x1ea0 },
+ { "Adotmacron", 0x01e0 },
+ { "Agravesmall", 0xf7e0 },
+ { "Ahookabove", 0x1ea2 },
+ { "Aiecyrillic", 0x04d4 },
+ { "Ainvertedbreve", 0x0202 },
+ { "Amonospace", 0xff21 },
+ { "Aringbelow", 0x1e00 },
+ { "Aringsmall", 0xf7e5 },
+ { "Asmall", 0xf761 },
+ { "Atildesmall", 0xf7e3 },
+ { "Aybarmenian", 0x0531 },
+ { "Bcircle", 0x24b7 },
+ { "Bdotaccent", 0x1e02 },
+ { "Bdotbelow", 0x1e04 },
+ { "Becyrillic", 0x0411 },
+ { "Benarmenian", 0x0532 },
+ { "Bhook", 0x0181 },
+ { "Blinebelow", 0x1e06 },
+ { "Bmonospace", 0xff22 },
+ { "Brevesmall", 0xf6f4 },
+ { "Bsmall", 0xf762 },
+ { "Btopbar", 0x0182 },
+ { "Caarmenian", 0x053e },
+ { "Caron", 0xf6ca },
+ { "Caronsmall", 0xf6f5 },
+ { "Ccedillaacute", 0x1e08 },
+ { "Ccedillasmall", 0xf7e7 },
+ { "Ccircle", 0x24b8 },
+ { "Cdot", 0x010a },
+ { "Cedillasmall", 0xf7b8 },
+ { "Chaarmenian", 0x0549 },
+ { "Cheabkhasiancyrillic", 0x04bc },
+ { "Checyrillic", 0x0427 },
+ { "Chedescenderabkhasiancyrillic", 0x04be },
+ { "Chedescendercyrillic", 0x04b6 },
+ { "Chedieresiscyrillic", 0x04f4 },
+ { "Cheharmenian", 0x0543 },
+ { "Chekhakassiancyrillic", 0x04cb },
+ { "Cheverticalstrokecyrillic", 0x04b8 },
+ { "Chook", 0x0187 },
+ { "Circumflexsmall", 0xf6f6 },
+ { "Cmonospace", 0xff23 },
+ { "Coarmenian", 0x0551 },
+ { "Csmall", 0xf763 },
+ { "DZ", 0x01f1 },
+ { "DZcaron", 0x01c4 },
+ { "Daarmenian", 0x0534 },
+ { "Dafrican", 0x0189 },
+ { "Dcedilla", 0x1e10 },
+ { "Dcircle", 0x24b9 },
+ { "Dcircumflexbelow", 0x1e12 },
+ { "Ddotaccent", 0x1e0a },
+ { "Ddotbelow", 0x1e0c },
+ { "Decyrillic", 0x0414 },
+ { "Deicoptic", 0x03ee },
+ { "Deltagreek", 0x0394 },
+ { "Dhook", 0x018a },
+ { "Dieresis", 0xf6cb },
+ { "diaeresis", 0x00a8 },
+ { "Diaeresis", 0xf6cb },
+ { "DieresisAcute", 0xf6cc },
+ { "DieresisGrave", 0xf6cd },
+ { "Dieresissmall", 0xf7a8 },
+ { "Digammagreek", 0x03dc },
+ { "Djecyrillic", 0x0402 },
+ { "Dlinebelow", 0x1e0e },
+ { "Dmonospace", 0xff24 },
+ { "Dotaccentsmall", 0xf6f7 },
+ { "Dslash", 0x0110 },
+ { "Dsmall", 0xf764 },
+ { "Dtopbar", 0x018b },
+ { "Dz", 0x01f2 },
+ { "Dzcaron", 0x01c5 },
+ { "Dzeabkhasiancyrillic", 0x04e0 },
+ { "Dzecyrillic", 0x0405 },
+ { "Dzhecyrillic", 0x040f },
+ { "Eacutesmall", 0xf7e9 },
+ { "Ecedillabreve", 0x1e1c },
+ { "Echarmenian", 0x0535 },
+ { "Ecircle", 0x24ba },
+ { "Ecircumflexacute", 0x1ebe },
+ { "Ecircumflexbelow", 0x1e18 },
+ { "Ecircumflexdotbelow", 0x1ec6 },
+ { "Ecircumflexgrave", 0x1ec0 },
+ { "Ecircumflexhookabove", 0x1ec2 },
+ { "Ecircumflexsmall", 0xf7ea },
+ { "Ecircumflextilde", 0x1ec4 },
+ { "Ecyrillic", 0x0404 },
+ { "Edblgrave", 0x0204 },
+ { "Edieresissmall", 0xf7eb },
+ { "Edot", 0x0116 },
+ { "Edotbelow", 0x1eb8 },
+ { "Efcyrillic", 0x0424 },
+ { "Egravesmall", 0xf7e8 },
+ { "Eharmenian", 0x0537 },
+ { "Ehookabove", 0x1eba },
+ { "Eightroman", 0x2167 },
+ { "Einvertedbreve", 0x0206 },
+ { "Eiotifiedcyrillic", 0x0464 },
+ { "Elcyrillic", 0x041b },
+ { "Elevenroman", 0x216a },
+ { "Emacronacute", 0x1e16 },
+ { "Emacrongrave", 0x1e14 },
+ { "Emcyrillic", 0x041c },
+ { "Emonospace", 0xff25 },
+ { "Encyrillic", 0x041d },
+ { "Endescendercyrillic", 0x04a2 },
+ { "Enghecyrillic", 0x04a4 },
+ { "Enhookcyrillic", 0x04c7 },
+ { "Eopen", 0x0190 },
+ { "Ercyrillic", 0x0420 },
+ { "Ereversed", 0x018e },
+ { "Ereversedcyrillic", 0x042d },
+ { "Escyrillic", 0x0421 },
+ { "Esdescendercyrillic", 0x04aa },
+ { "Esh", 0x01a9 },
+ { "Esmall", 0xf765 },
+ { "Etarmenian", 0x0538 },
+ { "Ethsmall", 0xf7f0 },
+ { "Etilde", 0x1ebc },
+ { "Etildebelow", 0x1e1a },
+ { "Ezh", 0x01b7 },
+ { "Ezhcaron", 0x01ee },
+ { "Ezhreversed", 0x01b8 },
+ { "Fcircle", 0x24bb },
+ { "Fdotaccent", 0x1e1e },
+ { "Feharmenian", 0x0556 },
+ { "Feicoptic", 0x03e4 },
+ { "Fhook", 0x0191 },
+ { "Fitacyrillic", 0x0472 },
+ { "Fiveroman", 0x2164 },
+ { "Fmonospace", 0xff26 },
+ { "Fourroman", 0x2163 },
+ { "Fsmall", 0xf766 },
+ { "GBsquare", 0x3387 },
+ { "Gacute", 0x01f4 },
+ { "Gammaafrican", 0x0194 },
+ { "Gangiacoptic", 0x03ea },
+ { "Gcedilla", 0x0122 },
+ { "Gcircle", 0x24bc },
+ { "Gdot", 0x0120 },
+ { "Gecyrillic", 0x0413 },
+ { "Ghadarmenian", 0x0542 },
+ { "Ghemiddlehookcyrillic", 0x0494 },
+ { "Ghestrokecyrillic", 0x0492 },
+ { "Gheupturncyrillic", 0x0490 },
+ { "Ghook", 0x0193 },
+ { "Gimarmenian", 0x0533 },
+ { "Gjecyrillic", 0x0403 },
+ { "Gmacron", 0x1e20 },
+ { "Gmonospace", 0xff27 },
+ { "Grave", 0xf6ce },
+ { "Gravesmall", 0xf760 },
+ { "Gsmall", 0xf767 },
+ { "Gsmallhook", 0x029b },
+ { "Gstroke", 0x01e4 },
+ { "HPsquare", 0x33cb },
+ { "Haabkhasiancyrillic", 0x04a8 },
+ { "Hadescendercyrillic", 0x04b2 },
+ { "Hardsigncyrillic", 0x042a },
+ { "Hbrevebelow", 0x1e2a },
+ { "Hcedilla", 0x1e28 },
+ { "Hcircle", 0x24bd },
+ { "Hdieresis", 0x1e26 },
+ { "Hdotaccent", 0x1e22 },
+ { "Hdotbelow", 0x1e24 },
+ { "Hmonospace", 0xff28 },
+ { "Hoarmenian", 0x0540 },
+ { "Horicoptic", 0x03e8 },
+ { "Hsmall", 0xf768 },
+ { "Hungarumlaut", 0xf6cf },
+ { "Hungarumlautsmall", 0xf6f8 },
+ { "Hzsquare", 0x3390 },
+ { "IAcyrillic", 0x042f },
+ { "IUcyrillic", 0x042e },
+ { "Iacutesmall", 0xf7ed },
+ { "Icaron", 0x01cf },
+ { "Icircle", 0x24be },
+ { "Icircumflexsmall", 0xf7ee },
+ { "Icyrillic", 0x0406 },
+ { "Idblgrave", 0x0208 },
+ { "Idieresisacute", 0x1e2e },
+ { "Idieresiscyrillic", 0x04e4 },
+ { "Idieresissmall", 0xf7ef },
+ { "Idot", 0x0130 },
+ { "Idotbelow", 0x1eca },
+ { "Iebrevecyrillic", 0x04d6 },
+ { "Iecyrillic", 0x0415 },
+ { "Igravesmall", 0xf7ec },
+ { "Ihookabove", 0x1ec8 },
+ { "Iicyrillic", 0x0418 },
+ { "Iinvertedbreve", 0x020a },
+ { "Iishortcyrillic", 0x0419 },
+ { "Imacroncyrillic", 0x04e2 },
+ { "Imonospace", 0xff29 },
+ { "Iniarmenian", 0x053b },
+ { "Iocyrillic", 0x0401 },
+ { "Iotaafrican", 0x0196 },
+ { "Ismall", 0xf769 },
+ { "Istroke", 0x0197 },
+ { "Itildebelow", 0x1e2c },
+ { "Izhitsacyrillic", 0x0474 },
+ { "Izhitsadblgravecyrillic", 0x0476 },
+ { "Jaarmenian", 0x0541 },
+ { "Jcircle", 0x24bf },
+ { "Jecyrillic", 0x0408 },
+ { "Jheharmenian", 0x054b },
+ { "Jmonospace", 0xff2a },
+ { "Jsmall", 0xf76a },
+ { "KBsquare", 0x3385 },
+ { "KKsquare", 0x33cd },
+ { "Kabashkircyrillic", 0x04a0 },
+ { "Kacute", 0x1e30 },
+ { "Kacyrillic", 0x041a },
+ { "Kadescendercyrillic", 0x049a },
+ { "Kahookcyrillic", 0x04c3 },
+ { "Kastrokecyrillic", 0x049e },
+ { "Kaverticalstrokecyrillic", 0x049c },
+ { "Kcaron", 0x01e8 },
+ { "Kcedilla", 0x0136 },
+ { "Kcircle", 0x24c0 },
+ { "Kdotbelow", 0x1e32 },
+ { "Keharmenian", 0x0554 },
+ { "Kenarmenian", 0x053f },
+ { "Khacyrillic", 0x0425 },
+ { "Kheicoptic", 0x03e6 },
+ { "Khook", 0x0198 },
+ { "Kjecyrillic", 0x040c },
+ { "Klinebelow", 0x1e34 },
+ { "Kmonospace", 0xff2b },
+ { "Koppacyrillic", 0x0480 },
+ { "Koppagreek", 0x03de },
+ { "Ksicyrillic", 0x046e },
+ { "Ksmall", 0xf76b },
+ { "LJ", 0x01c7 },
+ { "LL", 0xf6bf },
+ { "Lcedilla", 0x013b },
+ { "Lcircle", 0x24c1 },
+ { "Lcircumflexbelow", 0x1e3c },
+ { "Ldotaccent", 0x013f },
+ { "Ldotbelow", 0x1e36 },
+ { "Ldotbelowmacron", 0x1e38 },
+ { "Liwnarmenian", 0x053c },
+ { "Lj", 0x01c8 },
+ { "Ljecyrillic", 0x0409 },
+ { "Llinebelow", 0x1e3a },
+ { "Lmonospace", 0xff2c },
+ { "Lslashsmall", 0xf6f9 },
+ { "Lsmall", 0xf76c },
+ { "MBsquare", 0x3386 },
+ { "Macron", 0xf6d0 },
+ { "Macronsmall", 0xf7af },
+ { "Macute", 0x1e3e },
+ { "Mcircle", 0x24c2 },
+ { "Mdotaccent", 0x1e40 },
+ { "Mdotbelow", 0x1e42 },
+ { "Menarmenian", 0x0544 },
+ { "Mmonospace", 0xff2d },
+ { "Msmall", 0xf76d },
+ { "Mturned", 0x019c },
+ { "NJ", 0x01ca },
+ { "Ncedilla", 0x0145 },
+ { "Ncircle", 0x24c3 },
+ { "Ncircumflexbelow", 0x1e4a },
+ { "Ndotaccent", 0x1e44 },
+ { "Ndotbelow", 0x1e46 },
+ { "Nhookleft", 0x019d },
+ { "Nineroman", 0x2168 },
+ { "Nj", 0x01cb },
+ { "Njecyrillic", 0x040a },
+ { "Nlinebelow", 0x1e48 },
+ { "Nmonospace", 0xff2e },
+ { "Nowarmenian", 0x0546 },
+ { "Nsmall", 0xf76e },
+ { "Ntildesmall", 0xf7f1 },
+ { "OEsmall", 0xf6fa },
+ { "Oacutesmall", 0xf7f3 },
+ { "Obarredcyrillic", 0x04e8 },
+ { "Obarreddieresiscyrillic", 0x04ea },
+ { "Ocaron", 0x01d1 },
+ { "Ocenteredtilde", 0x019f },
+ { "Ocircle", 0x24c4 },
+ { "Ocircumflexacute", 0x1ed0 },
+ { "Ocircumflexdotbelow", 0x1ed8 },
+ { "Ocircumflexgrave", 0x1ed2 },
+ { "Ocircumflexhookabove", 0x1ed4 },
+ { "Ocircumflexsmall", 0xf7f4 },
+ { "Ocircumflextilde", 0x1ed6 },
+ { "Ocyrillic", 0x041e },
+ { "Odblacute", 0x0150 },
+ { "Odblgrave", 0x020c },
+ { "Odieresiscyrillic", 0x04e6 },
+ { "Odieresissmall", 0xf7f6 },
+ { "Odotbelow", 0x1ecc },
+ { "Ogoneksmall", 0xf6fb },
+ { "Ogravesmall", 0xf7f2 },
+ { "Oharmenian", 0x0555 },
+ { "Ohm", 0x2126 },
+ { "Ohookabove", 0x1ece },
+ { "Ohornacute", 0x1eda },
+ { "Ohorndotbelow", 0x1ee2 },
+ { "Ohorngrave", 0x1edc },
+ { "Ohornhookabove", 0x1ede },
+ { "Ohorntilde", 0x1ee0 },
+ { "Oi", 0x01a2 },
+ { "Oinvertedbreve", 0x020e },
+ { "Omacronacute", 0x1e52 },
+ { "Omacrongrave", 0x1e50 },
+ { "Omegacyrillic", 0x0460 },
+ { "Omegagreek", 0x03a9 },
+ { "Omegaroundcyrillic", 0x047a },
+ { "Omegatitlocyrillic", 0x047c },
+ { "Omonospace", 0xff2f },
+ { "Oneroman", 0x2160 },
+ { "Oogonek", 0x01ea },
+ { "Oogonekmacron", 0x01ec },
+ { "Oopen", 0x0186 },
+ { "Oslashsmall", 0xf7f8 },
+ { "Osmall", 0xf76f },
+ { "Ostrokeacute", 0x01fe },
+ { "Otcyrillic", 0x047e },
+ { "Otildeacute", 0x1e4c },
+ { "Otildedieresis", 0x1e4e },
+ { "Otildesmall", 0xf7f5 },
+ { "Pacute", 0x1e54 },
+ { "Pcircle", 0x24c5 },
+ { "Pdotaccent", 0x1e56 },
+ { "Pecyrillic", 0x041f },
+ { "Peharmenian", 0x054a },
+ { "Pemiddlehookcyrillic", 0x04a6 },
+ { "Phook", 0x01a4 },
+ { "Piwrarmenian", 0x0553 },
+ { "Pmonospace", 0xff30 },
+ { "Psicyrillic", 0x0470 },
+ { "Psmall", 0xf770 },
+ { "Qcircle", 0x24c6 },
+ { "Qmonospace", 0xff31 },
+ { "Qsmall", 0xf771 },
+ { "Raarmenian", 0x054c },
+ { "Rcedilla", 0x0156 },
+ { "Rcircle", 0x24c7 },
+ { "Rdblgrave", 0x0210 },
+ { "Rdotaccent", 0x1e58 },
+ { "Rdotbelow", 0x1e5a },
+ { "Rdotbelowmacron", 0x1e5c },
+ { "Reharmenian", 0x0550 },
+ { "Ringsmall", 0xf6fc },
+ { "Rinvertedbreve", 0x0212 },
+ { "Rlinebelow", 0x1e5e },
+ { "Rmonospace", 0xff32 },
+ { "Rsmall", 0xf772 },
+ { "Rsmallinverted", 0x0281 },
+ { "Rsmallinvertedsuperior", 0x02b6 },
+ { "Sacutedotaccent", 0x1e64 },
+ { "Sampigreek", 0x03e0 },
+ { "Scarondotaccent", 0x1e66 },
+ { "Scaronsmall", 0xf6fd },
+ { "Schwa", 0x018f },
+ { "Schwacyrillic", 0x04d8 },
+ { "Schwadieresiscyrillic", 0x04da },
+ { "Scircle", 0x24c8 },
+ { "Sdotaccent", 0x1e60 },
+ { "Sdotbelow", 0x1e62 },
+ { "Sdotbelowdotaccent", 0x1e68 },
+ { "Seharmenian", 0x054d },
+ { "Sevenroman", 0x2166 },
+ { "Shaarmenian", 0x0547 },
+ { "Shacyrillic", 0x0428 },
+ { "Shchacyrillic", 0x0429 },
+ { "Sheicoptic", 0x03e2 },
+ { "Shhacyrillic", 0x04ba },
+ { "Shimacoptic", 0x03ec },
+ { "Sixroman", 0x2165 },
+ { "Smonospace", 0xff33 },
+ { "Softsigncyrillic", 0x042c },
+ { "Ssmall", 0xf773 },
+ { "Stigmagreek", 0x03da },
+ { "Tcedilla", 0x0162 },
+ { "Tcircle", 0x24c9 },
+ { "Tcircumflexbelow", 0x1e70 },
+ { "Tdotaccent", 0x1e6a },
+ { "Tdotbelow", 0x1e6c },
+ { "Tecyrillic", 0x0422 },
+ { "Tedescendercyrillic", 0x04ac },
+ { "Tenroman", 0x2169 },
+ { "Tetsecyrillic", 0x04b4 },
+ { "Thook", 0x01ac },
+ { "Thornsmall", 0xf7fe },
+ { "Threeroman", 0x2162 },
+ { "Tildesmall", 0xf6fe },
+ { "Tiwnarmenian", 0x054f },
+ { "Tlinebelow", 0x1e6e },
+ { "Tmonospace", 0xff34 },
+ { "Toarmenian", 0x0539 },
+ { "Tonefive", 0x01bc },
+ { "Tonesix", 0x0184 },
+ { "Tonetwo", 0x01a7 },
+ { "Tretroflexhook", 0x01ae },
+ { "Tsecyrillic", 0x0426 },
+ { "Tshecyrillic", 0x040b },
+ { "Tsmall", 0xf774 },
+ { "Twelveroman", 0x216b },
+ { "Tworoman", 0x2161 },
+ { "Uacutesmall", 0xf7fa },
+ { "Ucaron", 0x01d3 },
+ { "Ucircle", 0x24ca },
+ { "Ucircumflexbelow", 0x1e76 },
+ { "Ucircumflexsmall", 0xf7fb },
+ { "Ucyrillic", 0x0423 },
+ { "Udblacute", 0x0170 },
+ { "Udblgrave", 0x0214 },
+ { "Udieresisacute", 0x01d7 },
+ { "Udieresisbelow", 0x1e72 },
+ { "Udieresiscaron", 0x01d9 },
+ { "Udieresiscyrillic", 0x04f0 },
+ { "Udieresisgrave", 0x01db },
+ { "Udieresismacron", 0x01d5 },
+ { "Udieresissmall", 0xf7fc },
+ { "Udotbelow", 0x1ee4 },
+ { "Ugravesmall", 0xf7f9 },
+ { "Uhookabove", 0x1ee6 },
+ { "Uhornacute", 0x1ee8 },
+ { "Uhorndotbelow", 0x1ef0 },
+ { "Uhorngrave", 0x1eea },
+ { "Uhornhookabove", 0x1eec },
+ { "Uhorntilde", 0x1eee },
+ { "Uhungarumlautcyrillic", 0x04f2 },
+ { "Uinvertedbreve", 0x0216 },
+ { "Ukcyrillic", 0x0478 },
+ { "Umacroncyrillic", 0x04ee },
+ { "Umacrondieresis", 0x1e7a },
+ { "Umonospace", 0xff35 },
+ { "Upsilonacutehooksymbolgreek", 0x03d3 },
+ { "Upsilonafrican", 0x01b1 },
+ { "Upsilondieresishooksymbolgreek", 0x03d4 },
+ { "Upsilonhooksymbol", 0x03d2 },
+ { "Ushortcyrillic", 0x040e },
+ { "Usmall", 0xf775 },
+ { "Ustraightcyrillic", 0x04ae },
+ { "Ustraightstrokecyrillic", 0x04b0 },
+ { "Utildeacute", 0x1e78 },
+ { "Utildebelow", 0x1e74 },
+ { "Vcircle", 0x24cb },
+ { "Vdotbelow", 0x1e7e },
+ { "Vecyrillic", 0x0412 },
+ { "Vewarmenian", 0x054e },
+ { "Vhook", 0x01b2 },
+ { "Vmonospace", 0xff36 },
+ { "Voarmenian", 0x0548 },
+ { "Vsmall", 0xf776 },
+ { "Vtilde", 0x1e7c },
+ { "Wcircle", 0x24cc },
+ { "Wdotaccent", 0x1e86 },
+ { "Wdotbelow", 0x1e88 },
+ { "Wmonospace", 0xff37 },
+ { "Wsmall", 0xf777 },
+ { "Xcircle", 0x24cd },
+ { "Xdieresis", 0x1e8c },
+ { "Xdotaccent", 0x1e8a },
+ { "Xeharmenian", 0x053d },
+ { "Xmonospace", 0xff38 },
+ { "Xsmall", 0xf778 },
+ { "Yacutesmall", 0xf7fd },
+ { "Yatcyrillic", 0x0462 },
+ { "Ycircle", 0x24ce },
+ { "Ydieresissmall", 0xf7ff },
+ { "Ydotaccent", 0x1e8e },
+ { "Ydotbelow", 0x1ef4 },
+ { "Yericyrillic", 0x042b },
+ { "Yerudieresiscyrillic", 0x04f8 },
+ { "Yhook", 0x01b3 },
+ { "Yhookabove", 0x1ef6 },
+ { "Yiarmenian", 0x0545 },
+ { "Yicyrillic", 0x0407 },
+ { "Yiwnarmenian", 0x0552 },
+ { "Ymonospace", 0xff39 },
+ { "Ysmall", 0xf779 },
+ { "Ytilde", 0x1ef8 },
+ { "Yusbigcyrillic", 0x046a },
+ { "Yusbigiotifiedcyrillic", 0x046c },
+ { "Yuslittlecyrillic", 0x0466 },
+ { "Yuslittleiotifiedcyrillic", 0x0468 },
+ { "Zaarmenian", 0x0536 },
+ { "Zcaronsmall", 0xf6ff },
+ { "Zcircle", 0x24cf },
+ { "Zcircumflex", 0x1e90 },
+ { "Zdot", 0x017b },
+ { "Zdotbelow", 0x1e92 },
+ { "Zecyrillic", 0x0417 },
+ { "Zedescendercyrillic", 0x0498 },
+ { "Zedieresiscyrillic", 0x04de },
+ { "Zhearmenian", 0x053a },
+ { "Zhebrevecyrillic", 0x04c1 },
+ { "Zhecyrillic", 0x0416 },
+ { "Zhedescendercyrillic", 0x0496 },
+ { "Zhedieresiscyrillic", 0x04dc },
+ { "Zlinebelow", 0x1e94 },
+ { "Zmonospace", 0xff3a },
+ { "Zsmall", 0xf77a },
+ { "Zstroke", 0x01b5 },
+ { "aabengali", 0x0986 },
+ { "aadeva", 0x0906 },
+ { "aagujarati", 0x0a86 },
+ { "aagurmukhi", 0x0a06 },
+ { "aamatragurmukhi", 0x0a3e },
+ { "aarusquare", 0x3303 },
+ { "aavowelsignbengali", 0x09be },
+ { "aavowelsigndeva", 0x093e },
+ { "aavowelsigngujarati", 0x0abe },
+ { "abbreviationmarkarmenian", 0x055f },
+ { "abbreviationsigndeva", 0x0970 },
+ { "abengali", 0x0985 },
+ { "abopomofo", 0x311a },
+ { "abreveacute", 0x1eaf },
+ { "abrevecyrillic", 0x04d1 },
+ { "abrevedotbelow", 0x1eb7 },
+ { "abrevegrave", 0x1eb1 },
+ { "abrevehookabove", 0x1eb3 },
+ { "abrevetilde", 0x1eb5 },
+ { "acaron", 0x01ce },
+ { "acircle", 0x24d0 },
+ { "acircumflexacute", 0x1ea5 },
+ { "acircumflexdotbelow", 0x1ead },
+ { "acircumflexgrave", 0x1ea7 },
+ { "acircumflexhookabove", 0x1ea9 },
+ { "acircumflextilde", 0x1eab },
+ { "acutebelowcmb", 0x0317 },
+ { "acutecmb", 0x0301 },
+ { "acutedeva", 0x0954 },
+ { "acutelowmod", 0x02cf },
+ { "acutetonecmb", 0x0341 },
+ { "acyrillic", 0x0430 },
+ { "adblgrave", 0x0201 },
+ { "addakgurmukhi", 0x0a71 },
+ { "adeva", 0x0905 },
+ { "adieresiscyrillic", 0x04d3 },
+ { "adieresismacron", 0x01df },
+ { "adotbelow", 0x1ea1 },
+ { "adotmacron", 0x01e1 },
+ { "aekorean", 0x3150 },
+ { "aemacron", 0x01e3 },
+ { "afii08941", 0x20a4 },
+ { "afii10063", 0xf6c4 },
+ { "afii10064", 0xf6c5 },
+ { "afii10192", 0xf6c6 },
+ { "afii10831", 0xf6c7 },
+ { "afii10832", 0xf6c8 },
+ { "afii57694", 0xfb2a },
+ { "afii57695", 0xfb2b },
+ { "afii57700", 0xfb4b },
+ { "afii57705", 0xfb1f },
+ { "afii57723", 0xfb35 },
+ { "agujarati", 0x0a85 },
+ { "agurmukhi", 0x0a05 },
+ { "ahiragana", 0x3042 },
+ { "ahookabove", 0x1ea3 },
+ { "aibengali", 0x0990 },
+ { "aibopomofo", 0x311e },
+ { "aideva", 0x0910 },
+ { "aiecyrillic", 0x04d5 },
+ { "aigujarati", 0x0a90 },
+ { "aigurmukhi", 0x0a10 },
+ { "aimatragurmukhi", 0x0a48 },
+ { "ainarabic", 0x0639 },
+ { "ainfinalarabic", 0xfeca },
+ { "aininitialarabic", 0xfecb },
+ { "ainmedialarabic", 0xfecc },
+ { "ainvertedbreve", 0x0203 },
+ { "aivowelsignbengali", 0x09c8 },
+ { "aivowelsigndeva", 0x0948 },
+ { "aivowelsigngujarati", 0x0ac8 },
+ { "akatakana", 0x30a2 },
+ { "akatakanahalfwidth", 0xff71 },
+ { "akorean", 0x314f },
+ { "alef", 0x05d0 },
+ { "alefarabic", 0x0627 },
+ { "alefdageshhebrew", 0xfb30 },
+ { "aleffinalarabic", 0xfe8e },
+ { "alefhamzaabovearabic", 0x0623 },
+ { "alefhamzaabovefinalarabic", 0xfe84 },
+ { "alefhamzabelowarabic", 0x0625 },
+ { "alefhamzabelowfinalarabic", 0xfe88 },
+ { "alefhebrew", 0x05d0 },
+ { "aleflamedhebrew", 0xfb4f },
+ { "alefmaddaabovearabic", 0x0622 },
+ { "alefmaddaabovefinalarabic", 0xfe82 },
+ { "alefmaksuraarabic", 0x0649 },
+ { "alefmaksurafinalarabic", 0xfef0 },
+ { "alefmaksurainitialarabic", 0xfef3 },
+ { "alefmaksuramedialarabic", 0xfef4 },
+ { "alefpatahhebrew", 0xfb2e },
+ { "alefqamatshebrew", 0xfb2f },
+ { "allequal", 0x224c },
+ { "amonospace", 0xff41 },
+ { "ampersandmonospace", 0xff06 },
+ { "ampersandsmall", 0xf726 },
+ { "amsquare", 0x33c2 },
+ { "anbopomofo", 0x3122 },
+ { "angbopomofo", 0x3124 },
+ { "angkhankhuthai", 0x0e5a },
+ { "anglebracketleft", 0x3008 },
+ { "anglebracketleftvertical", 0xfe3f },
+ { "anglebracketright", 0x3009 },
+ { "anglebracketrightvertical", 0xfe40 },
+ { "angstrom", 0x212b },
+ { "anudattadeva", 0x0952 },
+ { "anusvarabengali", 0x0982 },
+ { "anusvaradeva", 0x0902 },
+ { "anusvaragujarati", 0x0a82 },
+ { "apaatosquare", 0x3300 },
+ { "aparen", 0x249c },
+ { "apostrophearmenian", 0x055a },
+ { "apostrophemod", 0x02bc },
+ { "apple", 0xf8ff },
+ { "approaches", 0x2250 },
+ { "approxequalorimage", 0x2252 },
+ { "approximatelyequal", 0x2245 },
+ { "araeaekorean", 0x318e },
+ { "araeakorean", 0x318d },
+ { "arc", 0x2312 },
+ { "arighthalfring", 0x1e9a },
+ { "aringbelow", 0x1e01 },
+ { "arrowdashdown", 0x21e3 },
+ { "arrowdashleft", 0x21e0 },
+ { "arrowdashright", 0x21e2 },
+ { "arrowdashup", 0x21e1 },
+ { "arrowdownleft", 0x2199 },
+ { "arrowdownright", 0x2198 },
+ { "arrowdownwhite", 0x21e9 },
+ { "arrowheaddownmod", 0x02c5 },
+ { "arrowheadleftmod", 0x02c2 },
+ { "arrowheadrightmod", 0x02c3 },
+ { "arrowheadupmod", 0x02c4 },
+ { "arrowhorizex", 0xf8e7 },
+ { "arrowleftdbl", 0x21d0 },
+ { "arrowleftdblstroke", 0x21cd },
+ { "arrowleftoverright", 0x21c6 },
+ { "arrowleftwhite", 0x21e6 },
+ { "arrowrightdblstroke", 0x21cf },
+ { "arrowrightheavy", 0x279e },
+ { "arrowrightoverleft", 0x21c4 },
+ { "arrowrightwhite", 0x21e8 },
+ { "arrowtableft", 0x21e4 },
+ { "arrowtabright", 0x21e5 },
+ { "arrowupdownbase", 0x21a8 },
+ { "arrowupleft", 0x2196 },
+ { "arrowupleftofdown", 0x21c5 },
+ { "arrowupright", 0x2197 },
+ { "arrowupwhite", 0x21e7 },
+ { "arrowvertex", 0xf8e6 },
+ { "asciicircummonospace", 0xff3e },
+ { "asciitildemonospace", 0xff5e },
+ { "ascript", 0x0251 },
+ { "ascriptturned", 0x0252 },
+ { "asmallhiragana", 0x3041 },
+ { "asmallkatakana", 0x30a1 },
+ { "asmallkatakanahalfwidth", 0xff67 },
+ { "asteriskaltonearabic", 0x066d },
+ { "asteriskarabic", 0x066d },
+ { "asteriskmonospace", 0xff0a },
+ { "asterisksmall", 0xfe61 },
+ { "asterism", 0x2042 },
+ { "asuperior", 0xf6e9 },
+ { "asymptoticallyequal", 0x2243 },
+ { "atmonospace", 0xff20 },
+ { "atsmall", 0xfe6b },
+ { "aturned", 0x0250 },
+ { "aubengali", 0x0994 },
+ { "aubopomofo", 0x3120 },
+ { "audeva", 0x0914 },
+ { "augujarati", 0x0a94 },
+ { "augurmukhi", 0x0a14 },
+ { "aulengthmarkbengali", 0x09d7 },
+ { "aumatragurmukhi", 0x0a4c },
+ { "auvowelsignbengali", 0x09cc },
+ { "auvowelsigndeva", 0x094c },
+ { "auvowelsigngujarati", 0x0acc },
+ { "avagrahadeva", 0x093d },
+ { "aybarmenian", 0x0561 },
+ { "ayin", 0x05e2 },
+ { "ayinaltonehebrew", 0xfb20 },
+ { "ayinhebrew", 0x05e2 },
+ { "babengali", 0x09ac },
+ { "backslashmonospace", 0xff3c },
+ { "badeva", 0x092c },
+ { "bagujarati", 0x0aac },
+ { "bagurmukhi", 0x0a2c },
+ { "bahiragana", 0x3070 },
+ { "bahtthai", 0x0e3f },
+ { "bakatakana", 0x30d0 },
+ { "barmonospace", 0xff5c },
+ { "bbopomofo", 0x3105 },
+ { "bcircle", 0x24d1 },
+ { "bdotaccent", 0x1e03 },
+ { "bdotbelow", 0x1e05 },
+ { "beamedsixteenthnotes", 0x266c },
+ { "because", 0x2235 },
+ { "becyrillic", 0x0431 },
+ { "beharabic", 0x0628 },
+ { "behfinalarabic", 0xfe90 },
+ { "behinitialarabic", 0xfe91 },
+ { "behiragana", 0x3079 },
+ { "behmedialarabic", 0xfe92 },
+ { "behmeeminitialarabic", 0xfc9f },
+ { "behmeemisolatedarabic", 0xfc08 },
+ { "behnoonfinalarabic", 0xfc6d },
+ { "bekatakana", 0x30d9 },
+ { "benarmenian", 0x0562 },
+ { "bet", 0x05d1 },
+ { "betasymbolgreek", 0x03d0 },
+ { "betdagesh", 0xfb31 },
+ { "betdageshhebrew", 0xfb31 },
+ { "bethebrew", 0x05d1 },
+ { "betrafehebrew", 0xfb4c },
+ { "bhabengali", 0x09ad },
+ { "bhadeva", 0x092d },
+ { "bhagujarati", 0x0aad },
+ { "bhagurmukhi", 0x0a2d },
+ { "bhook", 0x0253 },
+ { "bihiragana", 0x3073 },
+ { "bikatakana", 0x30d3 },
+ { "bilabialclick", 0x0298 },
+ { "bindigurmukhi", 0x0a02 },
+ { "birusquare", 0x3331 },
+ { "blackcircle", 0x25cf },
+ { "blackdiamond", 0x25c6 },
+ { "blackdownpointingtriangle", 0x25bc },
+ { "blackleftpointingpointer", 0x25c4 },
+ { "blackleftpointingtriangle", 0x25c0 },
+ { "blacklenticularbracketleft", 0x3010 },
+ { "blacklenticularbracketleftvertical", 0xfe3b },
+ { "blacklenticularbracketright", 0x3011 },
+ { "blacklenticularbracketrightvertical", 0xfe3c },
+ { "blacklowerlefttriangle", 0x25e3 },
+ { "blacklowerrighttriangle", 0x25e2 },
+ { "blackrectangle", 0x25ac },
+ { "blackrightpointingpointer", 0x25ba },
+ { "blackrightpointingtriangle", 0x25b6 },
+ { "blacksmallsquare", 0x25aa },
+ { "blacksmilingface", 0x263b },
+ { "blacksquare", 0x25a0 },
+ { "blackstar", 0x2605 },
+ { "blackupperlefttriangle", 0x25e4 },
+ { "blackupperrighttriangle", 0x25e5 },
+ { "blackuppointingsmalltriangle", 0x25b4 },
+ { "blackuppointingtriangle", 0x25b2 },
+ { "blank", 0x2423 },
+ { "blinebelow", 0x1e07 },
+ { "bmonospace", 0xff42 },
+ { "bobaimaithai", 0x0e1a },
+ { "bohiragana", 0x307c },
+ { "bokatakana", 0x30dc },
+ { "bparen", 0x249d },
+ { "bqsquare", 0x33c3 },
+ { "braceex", 0xf8f4 },
+ { "braceleftbt", 0xf8f3 },
+ { "braceleftmid", 0xf8f2 },
+ { "braceleftmonospace", 0xff5b },
+ { "braceleftsmall", 0xfe5b },
+ { "bracelefttp", 0xf8f1 },
+ { "braceleftvertical", 0xfe37 },
+ { "bracerightbt", 0xf8fe },
+ { "bracerightmid", 0xf8fd },
+ { "bracerightmonospace", 0xff5d },
+ { "bracerightsmall", 0xfe5c },
+ { "bracerighttp", 0xf8fc },
+ { "bracerightvertical", 0xfe38 },
+ { "bracketleftbt", 0xf8f0 },
+ { "bracketleftex", 0xf8ef },
+ { "bracketleftmonospace", 0xff3b },
+ { "bracketlefttp", 0xf8ee },
+ { "bracketrightbt", 0xf8fb },
+ { "bracketrightex", 0xf8fa },
+ { "bracketrightmonospace", 0xff3d },
+ { "bracketrighttp", 0xf8f9 },
+ { "brevebelowcmb", 0x032e },
+ { "brevecmb", 0x0306 },
+ { "breveinvertedbelowcmb", 0x032f },
+ { "breveinvertedcmb", 0x0311 },
+ { "breveinverteddoublecmb", 0x0361 },
+ { "bridgebelowcmb", 0x032a },
+ { "bridgeinvertedbelowcmb", 0x033a },
+ { "bstroke", 0x0180 },
+ { "bsuperior", 0xf6ea },
+ { "btopbar", 0x0183 },
+ { "buhiragana", 0x3076 },
+ { "bukatakana", 0x30d6 },
+ { "bulletinverse", 0x25d8 },
+ { "bulletoperator", 0x2219 },
+ { "bullseye", 0x25ce },
+ { "caarmenian", 0x056e },
+ { "cabengali", 0x099a },
+ { "cadeva", 0x091a },
+ { "cagujarati", 0x0a9a },
+ { "cagurmukhi", 0x0a1a },
+ { "calsquare", 0x3388 },
+ { "candrabindubengali", 0x0981 },
+ { "candrabinducmb", 0x0310 },
+ { "candrabindudeva", 0x0901 },
+ { "candrabindugujarati", 0x0a81 },
+ { "capslock", 0x21ea },
+ { "careof", 0x2105 },
+ { "caronbelowcmb", 0x032c },
+ { "caroncmb", 0x030c },
+ { "cbopomofo", 0x3118 },
+ { "ccedillaacute", 0x1e09 },
+ { "ccircle", 0x24d2 },
+ { "ccurl", 0x0255 },
+ { "cdot", 0x010b },
+ { "cdsquare", 0x33c5 },
+ { "cedillacmb", 0x0327 },
+ { "centigrade", 0x2103 },
+ { "centinferior", 0xf6df },
+ { "centmonospace", 0xffe0 },
+ { "centoldstyle", 0xf7a2 },
+ { "centsuperior", 0xf6e0 },
+ { "chaarmenian", 0x0579 },
+ { "chabengali", 0x099b },
+ { "chadeva", 0x091b },
+ { "chagujarati", 0x0a9b },
+ { "chagurmukhi", 0x0a1b },
+ { "chbopomofo", 0x3114 },
+ { "cheabkhasiancyrillic", 0x04bd },
+ { "checkmark", 0x2713 },
+ { "checyrillic", 0x0447 },
+ { "chedescenderabkhasiancyrillic", 0x04bf },
+ { "chedescendercyrillic", 0x04b7 },
+ { "chedieresiscyrillic", 0x04f5 },
+ { "cheharmenian", 0x0573 },
+ { "chekhakassiancyrillic", 0x04cc },
+ { "cheverticalstrokecyrillic", 0x04b9 },
+ { "chieuchacirclekorean", 0x3277 },
+ { "chieuchaparenkorean", 0x3217 },
+ { "chieuchcirclekorean", 0x3269 },
+ { "chieuchkorean", 0x314a },
+ { "chieuchparenkorean", 0x3209 },
+ { "chochangthai", 0x0e0a },
+ { "chochanthai", 0x0e08 },
+ { "chochingthai", 0x0e09 },
+ { "chochoethai", 0x0e0c },
+ { "chook", 0x0188 },
+ { "cieucacirclekorean", 0x3276 },
+ { "cieucaparenkorean", 0x3216 },
+ { "cieuccirclekorean", 0x3268 },
+ { "cieuckorean", 0x3148 },
+ { "cieucparenkorean", 0x3208 },
+ { "cieucuparenkorean", 0x321c },
+ { "circleot", 0x2299 },
+ { "circlepostalmark", 0x3036 },
+ { "circlewithlefthalfblack", 0x25d0 },
+ { "circlewithrighthalfblack", 0x25d1 },
+ { "circumflexbelowcmb", 0x032d },
+ { "circumflexcmb", 0x0302 },
+ { "clear", 0x2327 },
+ { "clickalveolar", 0x01c2 },
+ { "clickdental", 0x01c0 },
+ { "clicklateral", 0x01c1 },
+ { "clickretroflex", 0x01c3 },
+ { "clubsuitblack", 0x2663 },
+ { "clubsuitwhite", 0x2667 },
+ { "cmcubedsquare", 0x33a4 },
+ { "cmonospace", 0xff43 },
+ { "cmsquaredsquare", 0x33a0 },
+ { "coarmenian", 0x0581 },
+ { "colonmonospace", 0xff1a },
+ { "colonsign", 0x20a1 },
+ { "colonsmall", 0xfe55 },
+ { "colontriangularhalfmod", 0x02d1 },
+ { "colontriangularmod", 0x02d0 },
+ { "commaabovecmb", 0x0313 },
+ { "commaaboverightcmb", 0x0315 },
+ { "commaaccent", 0xf6c3 },
+ { "commaarabic", 0x060c },
+ { "commaarmenian", 0x055d },
+ { "commainferior", 0xf6e1 },
+ { "commamonospace", 0xff0c },
+ { "commareversedabovecmb", 0x0314 },
+ { "commareversedmod", 0x02bd },
+ { "commasmall", 0xfe50 },
+ { "commasuperior", 0xf6e2 },
+ { "commaturnedabovecmb", 0x0312 },
+ { "commaturnedmod", 0x02bb },
+ { "compass", 0x263c },
+ { "contourintegral", 0x222e },
+ { "control", 0x2303 },
+ { "controlACK", 0x0006 },
+ { "controlBEL", 0x0007 },
+ { "controlBS", 0x0008 },
+ { "controlCAN", 0x0018 },
+ { "controlCR", 0x000d },
+ { "controlDC1", 0x0011 },
+ { "controlDC2", 0x0012 },
+ { "controlDC3", 0x0013 },
+ { "controlDC4", 0x0014 },
+ { "controlDEL", 0x007f },
+ { "controlDLE", 0x0010 },
+ { "controlEM", 0x0019 },
+ { "controlENQ", 0x0005 },
+ { "controlEOT", 0x0004 },
+ { "controlESC", 0x001b },
+ { "controlETB", 0x0017 },
+ { "controlETX", 0x0003 },
+ { "controlFF", 0x000c },
+ { "controlFS", 0x001c },
+ { "controlGS", 0x001d },
+ { "controlHT", 0x0009 },
+ { "controlLF", 0x000a },
+ { "controlNAK", 0x0015 },
+ { "controlRS", 0x001e },
+ { "controlSI", 0x000f },
+ { "controlSO", 0x000e },
+ { "controlSOT", 0x0002 },
+ { "controlSTX", 0x0001 },
+ { "controlSUB", 0x001a },
+ { "controlSYN", 0x0016 },
+ { "controlUS", 0x001f },
+ { "controlVT", 0x000b },
+ { "copyrightsans", 0xf8e9 },
+ { "copyrightserif", 0xf6d9 },
+ { "cornerbracketleft", 0x300c },
+ { "cornerbracketlefthalfwidth", 0xff62 },
+ { "cornerbracketleftvertical", 0xfe41 },
+ { "cornerbracketright", 0x300d },
+ { "cornerbracketrighthalfwidth", 0xff63 },
+ { "cornerbracketrightvertical", 0xfe42 },
+ { "corporationsquare", 0x337f },
+ { "cosquare", 0x33c7 },
+ { "coverkgsquare", 0x33c6 },
+ { "cparen", 0x249e },
+ { "cruzeiro", 0x20a2 },
+ { "cstretched", 0x0297 },
+ { "curlyand", 0x22cf },
+ { "curlyor", 0x22ce },
+ { "cyrBreve", 0xf6d1 },
+ { "cyrFlex", 0xf6d2 },
+ { "cyrbreve", 0xf6d4 },
+ { "cyrflex", 0xf6d5 },
+ { "daarmenian", 0x0564 },
+ { "dabengali", 0x09a6 },
+ { "dadarabic", 0x0636 },
+ { "dadeva", 0x0926 },
+ { "dadfinalarabic", 0xfebe },
+ { "dadinitialarabic", 0xfebf },
+ { "dadmedialarabic", 0xfec0 },
+ { "dagesh", 0x05bc },
+ { "dageshhebrew", 0x05bc },
+ { "dagujarati", 0x0aa6 },
+ { "dagurmukhi", 0x0a26 },
+ { "dahiragana", 0x3060 },
+ { "dakatakana", 0x30c0 },
+ { "dalarabic", 0x062f },
+ { "dalet", 0x05d3 },
+ { "daletdagesh", 0xfb33 },
+ { "daletdageshhebrew", 0xfb33 },
+ { "dalethatafpatah", 0x05d3 },
+ { "dalethatafpatahhebrew", 0x05d3 },
+ { "dalethatafsegol", 0x05d3 },
+ { "dalethatafsegolhebrew", 0x05d3 },
+ { "dalethebrew", 0x05d3 },
+ { "dalethiriq", 0x05d3 },
+ { "dalethiriqhebrew", 0x05d3 },
+ { "daletholam", 0x05d3 },
+ { "daletholamhebrew", 0x05d3 },
+ { "daletpatah", 0x05d3 },
+ { "daletpatahhebrew", 0x05d3 },
+ { "daletqamats", 0x05d3 },
+ { "daletqamatshebrew", 0x05d3 },
+ { "daletqubuts", 0x05d3 },
+ { "daletqubutshebrew", 0x05d3 },
+ { "daletsegol", 0x05d3 },
+ { "daletsegolhebrew", 0x05d3 },
+ { "daletsheva", 0x05d3 },
+ { "daletshevahebrew", 0x05d3 },
+ { "dalettsere", 0x05d3 },
+ { "dalettserehebrew", 0x05d3 },
+ { "dalfinalarabic", 0xfeaa },
+ { "dammaarabic", 0x064f },
+ { "dammalowarabic", 0x064f },
+ { "dammatanaltonearabic", 0x064c },
+ { "dammatanarabic", 0x064c },
+ { "danda", 0x0964 },
+ { "dargahebrew", 0x05a7 },
+ { "dargalefthebrew", 0x05a7 },
+ { "dasiapneumatacyrilliccmb", 0x0485 },
+ { "dblGrave", 0xf6d3 },
+ { "dblanglebracketleft", 0x300a },
+ { "dblanglebracketleftvertical", 0xfe3d },
+ { "dblanglebracketright", 0x300b },
+ { "dblanglebracketrightvertical", 0xfe3e },
+ { "dblarchinvertedbelowcmb", 0x032b },
+ { "dblarrowleft", 0x21d4 },
+ { "dblarrowright", 0x21d2 },
+ { "dbldanda", 0x0965 },
+ { "dblgrave", 0xf6d6 },
+ { "dblgravecmb", 0x030f },
+ { "dblintegral", 0x222c },
+ { "dbllowline", 0x2017 },
+ { "dbllowlinecmb", 0x0333 },
+ { "dbloverlinecmb", 0x033f },
+ { "dblprimemod", 0x02ba },
+ { "dblverticalbar", 0x2016 },
+ { "dblverticallineabovecmb", 0x030e },
+ { "dbopomofo", 0x3109 },
+ { "dbsquare", 0x33c8 },
+ { "dcedilla", 0x1e11 },
+ { "dcircle", 0x24d3 },
+ { "dcircumflexbelow", 0x1e13 },
+ { "ddabengali", 0x09a1 },
+ { "ddadeva", 0x0921 },
+ { "ddagujarati", 0x0aa1 },
+ { "ddagurmukhi", 0x0a21 },
+ { "ddalarabic", 0x0688 },
+ { "ddalfinalarabic", 0xfb89 },
+ { "dddhadeva", 0x095c },
+ { "ddhabengali", 0x09a2 },
+ { "ddhadeva", 0x0922 },
+ { "ddhagujarati", 0x0aa2 },
+ { "ddhagurmukhi", 0x0a22 },
+ { "ddotaccent", 0x1e0b },
+ { "ddotbelow", 0x1e0d },
+ { "decimalseparatorarabic", 0x066b },
+ { "decimalseparatorpersian", 0x066b },
+ { "decyrillic", 0x0434 },
+ { "dehihebrew", 0x05ad },
+ { "dehiragana", 0x3067 },
+ { "deicoptic", 0x03ef },
+ { "dekatakana", 0x30c7 },
+ { "deleteleft", 0x232b },
+ { "deleteright", 0x2326 },
+ { "deltaturned", 0x018d },
+ { "denominatorminusonenumeratorbengali", 0x09f8 },
+ { "dezh", 0x02a4 },
+ { "dhabengali", 0x09a7 },
+ { "dhadeva", 0x0927 },
+ { "dhagujarati", 0x0aa7 },
+ { "dhagurmukhi", 0x0a27 },
+ { "dhook", 0x0257 },
+ { "dialytikatonos", 0x0385 },
+ { "dialytikatonoscmb", 0x0344 },
+ { "diamondsuitwhite", 0x2662 },
+ { "dieresisacute", 0xf6d7 },
+ { "dieresisbelowcmb", 0x0324 },
+ { "dieresiscmb", 0x0308 },
+ { "dieresisgrave", 0xf6d8 },
+ { "dihiragana", 0x3062 },
+ { "dikatakana", 0x30c2 },
+ { "dittomark", 0x3003 },
+ { "divides", 0x2223 },
+ { "divisionslash", 0x2215 },
+ { "djecyrillic", 0x0452 },
+ { "dlinebelow", 0x1e0f },
+ { "dlsquare", 0x3397 },
+ { "dmacron", 0x0111 },
+ { "dmonospace", 0xff44 },
+ { "dochadathai", 0x0e0e },
+ { "dodekthai", 0x0e14 },
+ { "dohiragana", 0x3069 },
+ { "dokatakana", 0x30c9 },
+ { "dollarinferior", 0xf6e3 },
+ { "dollarmonospace", 0xff04 },
+ { "dollaroldstyle", 0xf724 },
+ { "dollarsmall", 0xfe69 },
+ { "dollarsuperior", 0xf6e4 },
+ { "dorusquare", 0x3326 },
+ { "dotaccentcmb", 0x0307 },
+ { "dotbelowcmb", 0x0323 },
+ { "dotkatakana", 0x30fb },
+ { "dotlessj", 0x0237 }, /* !!!! AGL Still says this is 0xf6be */
+ { "dotlessjstrokehook", 0x0284 },
+ { "dottedcircle", 0x25cc },
+ { "doubleyodpatah", 0xfb1f },
+ { "doubleyodpatahhebrew", 0xfb1f },
+ { "downtackbelowcmb", 0x031e },
+ { "downtackmod", 0x02d5 },
+ { "dparen", 0x249f },
+ { "dsuperior", 0xf6eb },
+ { "dtail", 0x0256 },
+ { "dtopbar", 0x018c },
+ { "duhiragana", 0x3065 },
+ { "dukatakana", 0x30c5 },
+ { "dz", 0x01f3 },
+ { "dzaltone", 0x02a3 },
+ { "dzcaron", 0x01c6 },
+ { "dzcurl", 0x02a5 },
+ { "dzeabkhasiancyrillic", 0x04e1 },
+ { "dzecyrillic", 0x0455 },
+ { "dzhecyrillic", 0x045f },
+ { "earth", 0x2641 },
+ { "ebengali", 0x098f },
+ { "ebopomofo", 0x311c },
+ { "ecandradeva", 0x090d },
+ { "ecandragujarati", 0x0a8d },
+ { "ecandravowelsigndeva", 0x0945 },
+ { "ecandravowelsigngujarati", 0x0ac5 },
+ { "ecedillabreve", 0x1e1d },
+ { "echarmenian", 0x0565 },
+ { "echyiwnarmenian", 0x0587 },
+ { "ecircle", 0x24d4 },
+ { "ecircumflexacute", 0x1ebf },
+ { "ecircumflexbelow", 0x1e19 },
+ { "ecircumflexdotbelow", 0x1ec7 },
+ { "ecircumflexgrave", 0x1ec1 },
+ { "ecircumflexhookabove", 0x1ec3 },
+ { "ecircumflextilde", 0x1ec5 },
+ { "ecyrillic", 0x0454 },
+ { "edblgrave", 0x0205 },
+ { "edeva", 0x090f },
+ { "edot", 0x0117 },
+ { "edotbelow", 0x1eb9 },
+ { "eegurmukhi", 0x0a0f },
+ { "eematragurmukhi", 0x0a47 },
+ { "efcyrillic", 0x0444 },
+ { "egujarati", 0x0a8f },
+ { "eharmenian", 0x0567 },
+ { "ehbopomofo", 0x311d },
+ { "ehiragana", 0x3048 },
+ { "ehookabove", 0x1ebb },
+ { "eibopomofo", 0x311f },
+ { "eightarabic", 0x0668 },
+ { "eightbengali", 0x09ee },
+ { "eightcircle", 0x2467 },
+ { "eightcircleinversesansserif", 0x2791 },
+ { "eightdeva", 0x096e },
+ { "eighteencircle", 0x2471 },
+ { "eighteenparen", 0x2485 },
+ { "eighteenperiod", 0x2499 },
+ { "eightgujarati", 0x0aee },
+ { "eightgurmukhi", 0x0a6e },
+ { "eighthackarabic", 0x0668 },
+ { "eighthangzhou", 0x3028 },
+ { "eighthnotebeamed", 0x266b },
+ { "eightideographicparen", 0x3227 },
+ { "eightinferior", 0x2088 },
+ { "eightmonospace", 0xff18 },
+ { "eightoldstyle", 0xf738 },
+ { "eightparen", 0x247b },
+ { "eightperiod", 0x248f },
+ { "eightpersian", 0x06f8 },
+ { "eightroman", 0x2177 },
+ { "eightsuperior", 0x2078 },
+ { "eightthai", 0x0e58 },
+ { "einvertedbreve", 0x0207 },
+ { "eiotifiedcyrillic", 0x0465 },
+ { "ekatakana", 0x30a8 },
+ { "ekatakanahalfwidth", 0xff74 },
+ { "ekonkargurmukhi", 0x0a74 },
+ { "ekorean", 0x3154 },
+ { "elcyrillic", 0x043b },
+ { "elevencircle", 0x246a },
+ { "elevenparen", 0x247e },
+ { "elevenperiod", 0x2492 },
+ { "elevenroman", 0x217a },
+ { "ellipsisvertical", 0x22ee },
+ { "emacronacute", 0x1e17 },
+ { "emacrongrave", 0x1e15 },
+ { "emcyrillic", 0x043c },
+ { "emdashvertical", 0xfe31 },
+ { "emonospace", 0xff45 },
+ { "emphasismarkarmenian", 0x055b },
+ { "enbopomofo", 0x3123 },
+ { "encyrillic", 0x043d },
+ { "endashvertical", 0xfe32 },
+ { "endescendercyrillic", 0x04a3 },
+ { "engbopomofo", 0x3125 },
+ { "enghecyrillic", 0x04a5 },
+ { "enhookcyrillic", 0x04c8 },
+ { "enspace", 0x2002 },
+ { "eokorean", 0x3153 },
+ { "eopen", 0x025b },
+ { "eopenclosed", 0x029a },
+ { "eopenreversed", 0x025c },
+ { "eopenreversedclosed", 0x025e },
+ { "eopenreversedhook", 0x025d },
+ { "eparen", 0x24a0 },
+ { "equalmonospace", 0xff1d },
+ { "equalsmall", 0xfe66 },
+ { "equalsuperior", 0x207c },
+ { "erbopomofo", 0x3126 },
+ { "ercyrillic", 0x0440 },
+ { "ereversed", 0x0258 },
+ { "ereversedcyrillic", 0x044d },
+ { "escyrillic", 0x0441 },
+ { "esdescendercyrillic", 0x04ab },
+ { "esh", 0x0283 },
+ { "eshcurl", 0x0286 },
+ { "eshortdeva", 0x090e },
+ { "eshortvowelsigndeva", 0x0946 },
+ { "eshreversedloop", 0x01aa },
+ { "eshsquatreversed", 0x0285 },
+ { "esmallhiragana", 0x3047 },
+ { "esmallkatakana", 0x30a7 },
+ { "esmallkatakanahalfwidth", 0xff6a },
+ { "esuperior", 0xf6ec },
+ { "etarmenian", 0x0568 },
+ { "etilde", 0x1ebd },
+ { "etildebelow", 0x1e1b },
+ { "etnahtafoukhhebrew", 0x0591 },
+ { "etnahtafoukhlefthebrew", 0x0591 },
+ { "etnahtahebrew", 0x0591 },
+ { "etnahtalefthebrew", 0x0591 },
+ { "eturned", 0x01dd },
+ { "eukorean", 0x3161 },
+ { "euro", 0x20ac },
+ { "evowelsignbengali", 0x09c7 },
+ { "evowelsigndeva", 0x0947 },
+ { "evowelsigngujarati", 0x0ac7 },
+ { "exclamarmenian", 0x055c },
+ { "exclamdownsmall", 0xf7a1 },
+ { "exclammonospace", 0xff01 },
+ { "exclamsmall", 0xf721 },
+ { "ezh", 0x0292 },
+ { "ezhcaron", 0x01ef },
+ { "ezhcurl", 0x0293 },
+ { "ezhreversed", 0x01b9 },
+ { "ezhtail", 0x01ba },
+ { "fadeva", 0x095e },
+ { "fagurmukhi", 0x0a5e },
+ { "fahrenheit", 0x2109 },
+ { "fathaarabic", 0x064e },
+ { "fathalowarabic", 0x064e },
+ { "fathatanarabic", 0x064b },
+ { "fbopomofo", 0x3108 },
+ { "fcircle", 0x24d5 },
+ { "fdotaccent", 0x1e1f },
+ { "feharabic", 0x0641 },
+ { "feharmenian", 0x0586 },
+ { "fehfinalarabic", 0xfed2 },
+ { "fehinitialarabic", 0xfed3 },
+ { "fehmedialarabic", 0xfed4 },
+ { "feicoptic", 0x03e5 },
+ { "ff", 0xfb00 },
+ { "ffi", 0xfb03 },
+ { "ffl", 0xfb04 },
+ { "fi", 0xfb01 },
+ { "fifteencircle", 0x246e },
+ { "fifteenparen", 0x2482 },
+ { "fifteenperiod", 0x2496 },
+ { "finalkaf", 0x05da },
+ { "finalkafdagesh", 0xfb3a },
+ { "finalkafdageshhebrew", 0xfb3a },
+ { "finalkafhebrew", 0x05da },
+ { "finalkafqamats", 0x05da },
+ { "finalkafqamatshebrew", 0x05da },
+ { "finalkafsheva", 0x05da },
+ { "finalkafshevahebrew", 0x05da },
+ { "finalmem", 0x05dd },
+ { "finalmemhebrew", 0x05dd },
+ { "finalnun", 0x05df },
+ { "finalnunhebrew", 0x05df },
+ { "finalpe", 0x05e3 },
+ { "finalpehebrew", 0x05e3 },
+ { "finaltsadi", 0x05e5 },
+ { "finaltsadihebrew", 0x05e5 },
+ { "firsttonechinese", 0x02c9 },
+ { "fisheye", 0x25c9 },
+ { "fitacyrillic", 0x0473 },
+ { "fivearabic", 0x0665 },
+ { "fivebengali", 0x09eb },
+ { "fivecircle", 0x2464 },
+ { "fivecircleinversesansserif", 0x278e },
+ { "fivedeva", 0x096b },
+ { "fivegujarati", 0x0aeb },
+ { "fivegurmukhi", 0x0a6b },
+ { "fivehackarabic", 0x0665 },
+ { "fivehangzhou", 0x3025 },
+ { "fiveideographicparen", 0x3224 },
+ { "fiveinferior", 0x2085 },
+ { "fivemonospace", 0xff15 },
+ { "fiveoldstyle", 0xf735 },
+ { "fiveparen", 0x2478 },
+ { "fiveperiod", 0x248c },
+ { "fivepersian", 0x06f5 },
+ { "fiveroman", 0x2174 },
+ { "fivesuperior", 0x2075 },
+ { "fivethai", 0x0e55 },
+ { "fl", 0xfb02 },
+ { "fmonospace", 0xff46 },
+ { "fmsquare", 0x3399 },
+ { "fofanthai", 0x0e1f },
+ { "fofathai", 0x0e1d },
+ { "fongmanthai", 0x0e4f },
+ { "forall", 0x2200 },
+ { "fourarabic", 0x0664 },
+ { "fourbengali", 0x09ea },
+ { "fourcircle", 0x2463 },
+ { "fourcircleinversesansserif", 0x278d },
+ { "fourdeva", 0x096a },
+ { "fourgujarati", 0x0aea },
+ { "fourgurmukhi", 0x0a6a },
+ { "fourhackarabic", 0x0664 },
+ { "fourhangzhou", 0x3024 },
+ { "fourideographicparen", 0x3223 },
+ { "fourinferior", 0x2084 },
+ { "fourmonospace", 0xff14 },
+ { "fournumeratorbengali", 0x09f7 },
+ { "fouroldstyle", 0xf734 },
+ { "fourparen", 0x2477 },
+ { "fourperiod", 0x248b },
+ { "fourpersian", 0x06f4 },
+ { "fourroman", 0x2173 },
+ { "foursuperior", 0x2074 },
+ { "fourteencircle", 0x246d },
+ { "fourteenparen", 0x2481 },
+ { "fourteenperiod", 0x2495 },
+ { "fourthai", 0x0e54 },
+ { "fourthtonechinese", 0x02cb },
+ { "fparen", 0x24a1 },
+ { "gabengali", 0x0997 },
+ { "gacute", 0x01f5 },
+ { "gadeva", 0x0917 },
+ { "gafarabic", 0x06af },
+ { "gaffinalarabic", 0xfb93 },
+ { "gafinitialarabic", 0xfb94 },
+ { "gafmedialarabic", 0xfb95 },
+ { "gagujarati", 0x0a97 },
+ { "gagurmukhi", 0x0a17 },
+ { "gahiragana", 0x304c },
+ { "gakatakana", 0x30ac },
+ { "gammalatinsmall", 0x0263 },
+ { "gammasuperior", 0x02e0 },
+ { "gangiacoptic", 0x03eb },
+ { "gbopomofo", 0x310d },
+ { "gcedilla", 0x0123 },
+ { "gcircle", 0x24d6 },
+ { "gdot", 0x0121 },
+ { "gecyrillic", 0x0433 },
+ { "gehiragana", 0x3052 },
+ { "gekatakana", 0x30b2 },
+ { "geometricallyequal", 0x2251 },
+ { "gereshaccenthebrew", 0x059c },
+ { "gereshhebrew", 0x05f3 },
+ { "gereshmuqdamhebrew", 0x059d },
+ { "gershayimaccenthebrew", 0x059e },
+ { "gershayimhebrew", 0x05f4 },
+ { "getamark", 0x3013 },
+ { "ghabengali", 0x0998 },
+ { "ghadarmenian", 0x0572 },
+ { "ghadeva", 0x0918 },
+ { "ghagujarati", 0x0a98 },
+ { "ghagurmukhi", 0x0a18 },
+ { "ghainarabic", 0x063a },
+ { "ghainfinalarabic", 0xfece },
+ { "ghaininitialarabic", 0xfecf },
+ { "ghainmedialarabic", 0xfed0 },
+ { "ghemiddlehookcyrillic", 0x0495 },
+ { "ghestrokecyrillic", 0x0493 },
+ { "gheupturncyrillic", 0x0491 },
+ { "ghhadeva", 0x095a },
+ { "ghhagurmukhi", 0x0a5a },
+ { "ghook", 0x0260 },
+ { "ghzsquare", 0x3393 },
+ { "gihiragana", 0x304e },
+ { "gikatakana", 0x30ae },
+ { "gimarmenian", 0x0563 },
+ { "gimel", 0x05d2 },
+ { "gimeldagesh", 0xfb32 },
+ { "gimeldageshhebrew", 0xfb32 },
+ { "gimelhebrew", 0x05d2 },
+ { "gjecyrillic", 0x0453 },
+ { "glottalinvertedstroke", 0x01be },
+ { "glottalstop", 0x0294 },
+ { "glottalstopinverted", 0x0296 },
+ { "glottalstopmod", 0x02c0 },
+ { "glottalstopreversed", 0x0295 },
+ { "glottalstopreversedmod", 0x02c1 },
+ { "glottalstopreversedsuperior", 0x02e4 },
+ { "glottalstopstroke", 0x02a1 },
+ { "glottalstopstrokereversed", 0x02a2 },
+ { "gmacron", 0x1e21 },
+ { "gmonospace", 0xff47 },
+ { "gohiragana", 0x3054 },
+ { "gokatakana", 0x30b4 },
+ { "gparen", 0x24a2 },
+ { "gpasquare", 0x33ac },
+ { "gravebelowcmb", 0x0316 },
+ { "gravecmb", 0x0300 },
+ { "gravedeva", 0x0953 },
+ { "gravelowmod", 0x02ce },
+ { "gravemonospace", 0xff40 },
+ { "gravetonecmb", 0x0340 },
+ { "greaterequalorless", 0x22db },
+ { "greatermonospace", 0xff1e },
+ { "greaterorequivalent", 0x2273 },
+ { "greaterorless", 0x2277 },
+ { "greateroverequal", 0x2267 },
+ { "greatersmall", 0xfe65 },
+ { "gscript", 0x0261 },
+ { "gstroke", 0x01e5 },
+ { "guhiragana", 0x3050 },
+ { "gukatakana", 0x30b0 },
+ { "guramusquare", 0x3318 },
+ { "gysquare", 0x33c9 },
+ { "haabkhasiancyrillic", 0x04a9 },
+ { "haaltonearabic", 0x06c1 },
+ { "habengali", 0x09b9 },
+ { "hadescendercyrillic", 0x04b3 },
+ { "hadeva", 0x0939 },
+ { "hagujarati", 0x0ab9 },
+ { "hagurmukhi", 0x0a39 },
+ { "haharabic", 0x062d },
+ { "hahfinalarabic", 0xfea2 },
+ { "hahinitialarabic", 0xfea3 },
+ { "hahiragana", 0x306f },
+ { "hahmedialarabic", 0xfea4 },
+ { "haitusquare", 0x332a },
+ { "hakatakana", 0x30cf },
+ { "hakatakanahalfwidth", 0xff8a },
+ { "halantgurmukhi", 0x0a4d },
+ { "hamzaarabic", 0x0621 },
+ { "hamzadammaarabic", 0x0621 },
+ { "hamzadammatanarabic", 0x0621 },
+ { "hamzafathaarabic", 0x0621 },
+ { "hamzafathatanarabic", 0x0621 },
+ { "hamzalowarabic", 0x0621 },
+ { "hamzalowkasraarabic", 0x0621 },
+ { "hamzalowkasratanarabic", 0x0621 },
+ { "hamzasukunarabic", 0x0621 },
+ { "hangulfiller", 0x3164 },
+ { "hardsigncyrillic", 0x044a },
+ { "harpoonleftbarbup", 0x21bc },
+ { "harpoonrightbarbup", 0x21c0 },
+ { "hasquare", 0x33ca },
+ { "hatafpatah", 0x05b2 },
+ { "hatafpatah16", 0x05b2 },
+ { "hatafpatah23", 0x05b2 },
+ { "hatafpatah2f", 0x05b2 },
+ { "hatafpatahhebrew", 0x05b2 },
+ { "hatafpatahnarrowhebrew", 0x05b2 },
+ { "hatafpatahquarterhebrew", 0x05b2 },
+ { "hatafpatahwidehebrew", 0x05b2 },
+ { "hatafqamats", 0x05b3 },
+ { "hatafqamats1b", 0x05b3 },
+ { "hatafqamats28", 0x05b3 },
+ { "hatafqamats34", 0x05b3 },
+ { "hatafqamatshebrew", 0x05b3 },
+ { "hatafqamatsnarrowhebrew", 0x05b3 },
+ { "hatafqamatsquarterhebrew", 0x05b3 },
+ { "hatafqamatswidehebrew", 0x05b3 },
+ { "hatafsegol", 0x05b1 },
+ { "hatafsegol17", 0x05b1 },
+ { "hatafsegol24", 0x05b1 },
+ { "hatafsegol30", 0x05b1 },
+ { "hatafsegolhebrew", 0x05b1 },
+ { "hatafsegolnarrowhebrew", 0x05b1 },
+ { "hatafsegolquarterhebrew", 0x05b1 },
+ { "hatafsegolwidehebrew", 0x05b1 },
+ { "hbopomofo", 0x310f },
+ { "hbrevebelow", 0x1e2b },
+ { "hcedilla", 0x1e29 },
+ { "hcircle", 0x24d7 },
+ { "hdieresis", 0x1e27 },
+ { "hdotaccent", 0x1e23 },
+ { "hdotbelow", 0x1e25 },
+ { "he", 0x05d4 },
+ { "heartsuitblack", 0x2665 },
+ { "heartsuitwhite", 0x2661 },
+ { "hedagesh", 0xfb34 },
+ { "hedageshhebrew", 0xfb34 },
+ { "hehaltonearabic", 0x06c1 },
+ { "heharabic", 0x0647 },
+ { "hehebrew", 0x05d4 },
+ { "hehfinalaltonearabic", 0xfba7 },
+ { "hehfinalalttwoarabic", 0xfeea },
+ { "hehfinalarabic", 0xfeea },
+ { "hehhamzaabovefinalarabic", 0xfba5 },
+ { "hehhamzaaboveisolatedarabic", 0xfba4 },
+ { "hehinitialaltonearabic", 0xfba8 },
+ { "hehinitialarabic", 0xfeeb },
+ { "hehiragana", 0x3078 },
+ { "hehmedialaltonearabic", 0xfba9 },
+ { "hehmedialarabic", 0xfeec },
+ { "heiseierasquare", 0x337b },
+ { "hekatakana", 0x30d8 },
+ { "hekatakanahalfwidth", 0xff8d },
+ { "hekutaarusquare", 0x3336 },
+ { "henghook", 0x0267 },
+ { "herutusquare", 0x3339 },
+ { "het", 0x05d7 },
+ { "hethebrew", 0x05d7 },
+ { "hhook", 0x0266 },
+ { "hhooksuperior", 0x02b1 },
+ { "hieuhacirclekorean", 0x327b },
+ { "hieuhaparenkorean", 0x321b },
+ { "hieuhcirclekorean", 0x326d },
+ { "hieuhkorean", 0x314e },
+ { "hieuhparenkorean", 0x320d },
+ { "hihiragana", 0x3072 },
+ { "hikatakana", 0x30d2 },
+ { "hikatakanahalfwidth", 0xff8b },
+ { "hiriq", 0x05b4 },
+ { "hiriq14", 0x05b4 },
+ { "hiriq21", 0x05b4 },
+ { "hiriq2d", 0x05b4 },
+ { "hiriqhebrew", 0x05b4 },
+ { "hiriqnarrowhebrew", 0x05b4 },
+ { "hiriqquarterhebrew", 0x05b4 },
+ { "hiriqwidehebrew", 0x05b4 },
+ { "hlinebelow", 0x1e96 },
+ { "hmonospace", 0xff48 },
+ { "hoarmenian", 0x0570 },
+ { "hohipthai", 0x0e2b },
+ { "hohiragana", 0x307b },
+ { "hokatakana", 0x30db },
+ { "hokatakanahalfwidth", 0xff8e },
+ { "holam", 0x05b9 },
+ { "holam19", 0x05b9 },
+ { "holam26", 0x05b9 },
+ { "holam32", 0x05b9 },
+ { "holamhebrew", 0x05b9 },
+ { "holamnarrowhebrew", 0x05b9 },
+ { "holamquarterhebrew", 0x05b9 },
+ { "holamwidehebrew", 0x05b9 },
+ { "honokhukthai", 0x0e2e },
+ { "hookcmb", 0x0309 },
+ { "hookpalatalizedbelowcmb", 0x0321 },
+ { "hookretroflexbelowcmb", 0x0322 },
+ { "hoonsquare", 0x3342 },
+ { "horicoptic", 0x03e9 },
+ { "horizontalbar", 0x2015 },
+ { "horncmb", 0x031b },
+ { "hotsprings", 0x2668 },
+ { "hparen", 0x24a3 },
+ { "hsuperior", 0x02b0 },
+ { "hturned", 0x0265 },
+ { "huhiragana", 0x3075 },
+ { "huiitosquare", 0x3333 },
+ { "hukatakana", 0x30d5 },
+ { "hukatakanahalfwidth", 0xff8c },
+ { "hungarumlautcmb", 0x030b },
+ { "hv", 0x0195 },
+ { "hypheninferior", 0xf6e5 },
+ { "hyphenmonospace", 0xff0d },
+ { "hyphensmall", 0xfe63 },
+ { "hyphensuperior", 0xf6e6 },
+ { "hyphentwo", 0x2010 },
+ { "iacyrillic", 0x044f },
+ { "ibengali", 0x0987 },
+ { "ibopomofo", 0x3127 },
+ { "icaron", 0x01d0 },
+ { "icircle", 0x24d8 },
+ { "icyrillic", 0x0456 },
+ { "idblgrave", 0x0209 },
+ { "ideographearthcircle", 0x328f },
+ { "ideographfirecircle", 0x328b },
+ { "ideographicallianceparen", 0x323f },
+ { "ideographiccallparen", 0x323a },
+ { "ideographiccentrecircle", 0x32a5 },
+ { "ideographicclose", 0x3006 },
+ { "ideographiccomma", 0x3001 },
+ { "ideographiccommaleft", 0xff64 },
+ { "ideographiccongratulationparen", 0x3237 },
+ { "ideographiccorrectcircle", 0x32a3 },
+ { "ideographicearthparen", 0x322f },
+ { "ideographicenterpriseparen", 0x323d },
+ { "ideographicexcellentcircle", 0x329d },
+ { "ideographicfestivalparen", 0x3240 },
+ { "ideographicfinancialcircle", 0x3296 },
+ { "ideographicfinancialparen", 0x3236 },
+ { "ideographicfireparen", 0x322b },
+ { "ideographichaveparen", 0x3232 },
+ { "ideographichighcircle", 0x32a4 },
+ { "ideographiciterationmark", 0x3005 },
+ { "ideographiclaborcircle", 0x3298 },
+ { "ideographiclaborparen", 0x3238 },
+ { "ideographicleftcircle", 0x32a7 },
+ { "ideographiclowcircle", 0x32a6 },
+ { "ideographicmedicinecircle", 0x32a9 },
+ { "ideographicmetalparen", 0x322e },
+ { "ideographicmoonparen", 0x322a },
+ { "ideographicnameparen", 0x3234 },
+ { "ideographicperiod", 0x3002 },
+ { "ideographicprintcircle", 0x329e },
+ { "ideographicreachparen", 0x3243 },
+ { "ideographicrepresentparen", 0x3239 },
+ { "ideographicresourceparen", 0x323e },
+ { "ideographicrightcircle", 0x32a8 },
+ { "ideographicsecretcircle", 0x3299 },
+ { "ideographicselfparen", 0x3242 },
+ { "ideographicsocietyparen", 0x3233 },
+ { "ideographicspace", 0x3000 },
+ { "ideographicspecialparen", 0x3235 },
+ { "ideographicstockparen", 0x3231 },
+ { "ideographicstudyparen", 0x323b },
+ { "ideographicsunparen", 0x3230 },
+ { "ideographicsuperviseparen", 0x323c },
+ { "ideographicwaterparen", 0x322c },
+ { "ideographicwoodparen", 0x322d },
+ { "ideographiczero", 0x3007 },
+ { "ideographmetalcircle", 0x328e },
+ { "ideographmooncircle", 0x328a },
+ { "ideographnamecircle", 0x3294 },
+ { "ideographsuncircle", 0x3290 },
+ { "ideographwatercircle", 0x328c },
+ { "ideographwoodcircle", 0x328d },
+ { "ideva", 0x0907 },
+ { "idieresisacute", 0x1e2f },
+ { "idieresiscyrillic", 0x04e5 },
+ { "idotbelow", 0x1ecb },
+ { "iebrevecyrillic", 0x04d7 },
+ { "iecyrillic", 0x0435 },
+ { "ieungacirclekorean", 0x3275 },
+ { "ieungaparenkorean", 0x3215 },
+ { "ieungcirclekorean", 0x3267 },
+ { "ieungkorean", 0x3147 },
+ { "ieungparenkorean", 0x3207 },
+ { "igujarati", 0x0a87 },
+ { "igurmukhi", 0x0a07 },
+ { "ihiragana", 0x3044 },
+ { "ihookabove", 0x1ec9 },
+ { "iibengali", 0x0988 },
+ { "iicyrillic", 0x0438 },
+ { "iideva", 0x0908 },
+ { "iigujarati", 0x0a88 },
+ { "iigurmukhi", 0x0a08 },
+ { "iimatragurmukhi", 0x0a40 },
+ { "iinvertedbreve", 0x020b },
+ { "iishortcyrillic", 0x0439 },
+ { "iivowelsignbengali", 0x09c0 },
+ { "iivowelsigndeva", 0x0940 },
+ { "iivowelsigngujarati", 0x0ac0 },
+ { "ikatakana", 0x30a4 },
+ { "ikatakanahalfwidth", 0xff72 },
+ { "ikorean", 0x3163 },
+ { "ilde", 0x02dc },
+ { "iluyhebrew", 0x05ac },
+ { "imacroncyrillic", 0x04e3 },
+ { "imageorapproximatelyequal", 0x2253 },
+ { "imatragurmukhi", 0x0a3f },
+ { "imonospace", 0xff49 },
+ { "increment", 0x2206 },
+ { "iniarmenian", 0x056b },
+ { "integralbottom", 0x2321 },
+ { "integralex", 0xf8f5 },
+ { "integraltop", 0x2320 },
+ { "intisquare", 0x3305 },
+ { "iocyrillic", 0x0451 },
+ { "iotalatin", 0x0269 },
+ { "iparen", 0x24a4 },
+ { "irigurmukhi", 0x0a72 },
+ { "ismallhiragana", 0x3043 },
+ { "ismallkatakana", 0x30a3 },
+ { "ismallkatakanahalfwidth", 0xff68 },
+ { "issharbengali", 0x09fa },
+ { "istroke", 0x0268 },
+ { "isuperior", 0xf6ed },
+ { "iterationhiragana", 0x309d },
+ { "iterationkatakana", 0x30fd },
+ { "itildebelow", 0x1e2d },
+ { "iubopomofo", 0x3129 },
+ { "iucyrillic", 0x044e },
+ { "ivowelsignbengali", 0x09bf },
+ { "ivowelsigndeva", 0x093f },
+ { "ivowelsigngujarati", 0x0abf },
+ { "izhitsacyrillic", 0x0475 },
+ { "izhitsadblgravecyrillic", 0x0477 },
+ { "jaarmenian", 0x0571 },
+ { "jabengali", 0x099c },
+ { "jadeva", 0x091c },
+ { "jagujarati", 0x0a9c },
+ { "jagurmukhi", 0x0a1c },
+ { "jbopomofo", 0x3110 },
+ { "jcaron", 0x01f0 },
+ { "jcircle", 0x24d9 },
+ { "jcrossedtail", 0x029d },
+ { "jdotlessstroke", 0x025f },
+ { "jecyrillic", 0x0458 },
+ { "jeemarabic", 0x062c },
+ { "jeemfinalarabic", 0xfe9e },
+ { "jeeminitialarabic", 0xfe9f },
+ { "jeemmedialarabic", 0xfea0 },
+ { "jeharabic", 0x0698 },
+ { "jehfinalarabic", 0xfb8b },
+ { "jhabengali", 0x099d },
+ { "jhadeva", 0x091d },
+ { "jhagujarati", 0x0a9d },
+ { "jhagurmukhi", 0x0a1d },
+ { "jheharmenian", 0x057b },
+ { "jis", 0x3004 },
+ { "jmonospace", 0xff4a },
+ { "jparen", 0x24a5 },
+ { "jsuperior", 0x02b2 },
+ { "kabashkircyrillic", 0x04a1 },
+ { "kabengali", 0x0995 },
+ { "kacute", 0x1e31 },
+ { "kacyrillic", 0x043a },
+ { "kadescendercyrillic", 0x049b },
+ { "kadeva", 0x0915 },
+ { "kaf", 0x05db },
+ { "kafarabic", 0x0643 },
+ { "kafdagesh", 0xfb3b },
+ { "kafdageshhebrew", 0xfb3b },
+ { "kaffinalarabic", 0xfeda },
+ { "kafhebrew", 0x05db },
+ { "kafinitialarabic", 0xfedb },
+ { "kafmedialarabic", 0xfedc },
+ { "kafrafehebrew", 0xfb4d },
+ { "kagujarati", 0x0a95 },
+ { "kagurmukhi", 0x0a15 },
+ { "kahiragana", 0x304b },
+ { "kahookcyrillic", 0x04c4 },
+ { "kakatakana", 0x30ab },
+ { "kakatakanahalfwidth", 0xff76 },
+ { "kappasymbolgreek", 0x03f0 },
+ { "kapyeounmieumkorean", 0x3171 },
+ { "kapyeounphieuphkorean", 0x3184 },
+ { "kapyeounpieupkorean", 0x3178 },
+ { "kapyeounssangpieupkorean", 0x3179 },
+ { "karoriisquare", 0x330d },
+ { "kashidaautoarabic", 0x0640 },
+ { "kashidaautonosidebearingarabic", 0x0640 },
+ { "kasmallkatakana", 0x30f5 },
+ { "kasquare", 0x3384 },
+ { "kasraarabic", 0x0650 },
+ { "kasratanarabic", 0x064d },
+ { "kastrokecyrillic", 0x049f },
+ { "katahiraprolongmarkhalfwidth", 0xff70 },
+ { "kaverticalstrokecyrillic", 0x049d },
+ { "kbopomofo", 0x310e },
+ { "kcalsquare", 0x3389 },
+ { "kcaron", 0x01e9 },
+ { "kcedilla", 0x0137 },
+ { "kcircle", 0x24da },
+ { "kdotbelow", 0x1e33 },
+ { "keharmenian", 0x0584 },
+ { "kehiragana", 0x3051 },
+ { "kekatakana", 0x30b1 },
+ { "kekatakanahalfwidth", 0xff79 },
+ { "kenarmenian", 0x056f },
+ { "kesmallkatakana", 0x30f6 },
+ { "khabengali", 0x0996 },
+ { "khacyrillic", 0x0445 },
+ { "khadeva", 0x0916 },
+ { "khagujarati", 0x0a96 },
+ { "khagurmukhi", 0x0a16 },
+ { "khaharabic", 0x062e },
+ { "khahfinalarabic", 0xfea6 },
+ { "khahinitialarabic", 0xfea7 },
+ { "khahmedialarabic", 0xfea8 },
+ { "kheicoptic", 0x03e7 },
+ { "khhadeva", 0x0959 },
+ { "khhagurmukhi", 0x0a59 },
+ { "khieukhacirclekorean", 0x3278 },
+ { "khieukhaparenkorean", 0x3218 },
+ { "khieukhcirclekorean", 0x326a },
+ { "khieukhkorean", 0x314b },
+ { "khieukhparenkorean", 0x320a },
+ { "khokhaithai", 0x0e02 },
+ { "khokhonthai", 0x0e05 },
+ { "khokhuatthai", 0x0e03 },
+ { "khokhwaithai", 0x0e04 },
+ { "khomutthai", 0x0e5b },
+ { "khook", 0x0199 },
+ { "khorakhangthai", 0x0e06 },
+ { "khzsquare", 0x3391 },
+ { "kihiragana", 0x304d },
+ { "kikatakana", 0x30ad },
+ { "kikatakanahalfwidth", 0xff77 },
+ { "kiroguramusquare", 0x3315 },
+ { "kiromeetorusquare", 0x3316 },
+ { "kirosquare", 0x3314 },
+ { "kiyeokacirclekorean", 0x326e },
+ { "kiyeokaparenkorean", 0x320e },
+ { "kiyeokcirclekorean", 0x3260 },
+ { "kiyeokkorean", 0x3131 },
+ { "kiyeokparenkorean", 0x3200 },
+ { "kiyeoksioskorean", 0x3133 },
+ { "kjecyrillic", 0x045c },
+ { "klinebelow", 0x1e35 },
+ { "klsquare", 0x3398 },
+ { "kmcubedsquare", 0x33a6 },
+ { "kmonospace", 0xff4b },
+ { "kmsquaredsquare", 0x33a2 },
+ { "kohiragana", 0x3053 },
+ { "kohmsquare", 0x33c0 },
+ { "kokaithai", 0x0e01 },
+ { "kokatakana", 0x30b3 },
+ { "kokatakanahalfwidth", 0xff7a },
+ { "kooposquare", 0x331e },
+ { "koppacyrillic", 0x0481 },
+ { "koreanstandardsymbol", 0x327f },
+ { "koroniscmb", 0x0343 },
+ { "kparen", 0x24a6 },
+ { "kpasquare", 0x33aa },
+ { "ksicyrillic", 0x046f },
+ { "ktsquare", 0x33cf },
+ { "kturned", 0x029e },
+ { "kuhiragana", 0x304f },
+ { "kukatakana", 0x30af },
+ { "kukatakanahalfwidth", 0xff78 },
+ { "kvsquare", 0x33b8 },
+ { "kwsquare", 0x33be },
+ { "labengali", 0x09b2 },
+ { "ladeva", 0x0932 },
+ { "lagujarati", 0x0ab2 },
+ { "lagurmukhi", 0x0a32 },
+ { "lakkhangyaothai", 0x0e45 },
+ { "lamaleffinalarabic", 0xfefc },
+ { "lamalefhamzaabovefinalarabic", 0xfef8 },
+ { "lamalefhamzaaboveisolatedarabic", 0xfef7 },
+ { "lamalefhamzabelowfinalarabic", 0xfefa },
+ { "lamalefhamzabelowisolatedarabic", 0xfef9 },
+ { "lamalefisolatedarabic", 0xfefb },
+ { "lamalefmaddaabovefinalarabic", 0xfef6 },
+ { "lamalefmaddaaboveisolatedarabic", 0xfef5 },
+ { "lamarabic", 0x0644 },
+ { "lambdastroke", 0x019b },
+ { "lamed", 0x05dc },
+ { "lameddagesh", 0xfb3c },
+ { "lameddageshhebrew", 0xfb3c },
+ { "lamedhebrew", 0x05dc },
+ { "lamedholam", 0x05dc },
+ { "lamedholamdagesh", 0x05dc },
+ { "lamedholamdageshhebrew", 0x05dc },
+ { "lamedholamhebrew", 0x05dc },
+ { "lamfinalarabic", 0xfede },
+ { "lamhahinitialarabic", 0xfcca },
+ { "laminitialarabic", 0xfedf },
+ { "lamjeeminitialarabic", 0xfcc9 },
+ { "lamkhahinitialarabic", 0xfccb },
+ { "lamlamhehisolatedarabic", 0xfdf2 },
+ { "lammedialarabic", 0xfee0 },
+ { "lammeemhahinitialarabic", 0xfd88 },
+ { "lammeeminitialarabic", 0xfccc },
+ { "lammeemjeeminitialarabic", 0xfedf },
+ { "lammeemkhahinitialarabic", 0xfedf },
+ { "largecircle", 0x25ef },
+ { "lbar", 0x019a },
+ { "lbelt", 0x026c },
+ { "lbopomofo", 0x310c },
+ { "lcedilla", 0x013c },
+ { "lcircle", 0x24db },
+ { "lcircumflexbelow", 0x1e3d },
+ { "ldotaccent", 0x0140 },
+ { "ldotbelow", 0x1e37 },
+ { "ldotbelowmacron", 0x1e39 },
+ { "leftangleabovecmb", 0x031a },
+ { "lefttackbelowcmb", 0x0318 },
+ { "lessequalorgreater", 0x22da },
+ { "lessmonospace", 0xff1c },
+ { "lessorequivalent", 0x2272 },
+ { "lessorgreater", 0x2276 },
+ { "lessoverequal", 0x2266 },
+ { "lesssmall", 0xfe64 },
+ { "lezh", 0x026e },
+ { "lhookretroflex", 0x026d },
+ { "liwnarmenian", 0x056c },
+ { "lj", 0x01c9 },
+ { "ljecyrillic", 0x0459 },
+ { "ll", 0xf6c0 },
+ { "lladeva", 0x0933 },
+ { "llagujarati", 0x0ab3 },
+ { "llinebelow", 0x1e3b },
+ { "llladeva", 0x0934 },
+ { "llvocalicbengali", 0x09e1 },
+ { "llvocalicdeva", 0x0961 },
+ { "llvocalicvowelsignbengali", 0x09e3 },
+ { "llvocalicvowelsigndeva", 0x0963 },
+ { "lmiddletilde", 0x026b },
+ { "lmonospace", 0xff4c },
+ { "lmsquare", 0x33d0 },
+ { "lochulathai", 0x0e2c },
+ { "logicalnotreversed", 0x2310 },
+ { "lolingthai", 0x0e25 },
+ { "lowlinecenterline", 0xfe4e },
+ { "lowlinecmb", 0x0332 },
+ { "lowlinedashed", 0xfe4d },
+ { "lparen", 0x24a7 },
+ { "lsquare", 0x2113 },
+ { "lsuperior", 0xf6ee },
+ { "luthai", 0x0e26 },
+ { "lvocalicbengali", 0x098c },
+ { "lvocalicdeva", 0x090c },
+ { "lvocalicvowelsignbengali", 0x09e2 },
+ { "lvocalicvowelsigndeva", 0x0962 },
+ { "lxsquare", 0x33d3 },
+ { "mabengali", 0x09ae },
+ { "macronbelowcmb", 0x0331 },
+ { "macroncmb", 0x0304 },
+ { "macronlowmod", 0x02cd },
+ { "macronmonospace", 0xffe3 },
+ { "macute", 0x1e3f },
+ { "madeva", 0x092e },
+ { "magujarati", 0x0aae },
+ { "magurmukhi", 0x0a2e },
+ { "mahapakhhebrew", 0x05a4 },
+ { "mahapakhlefthebrew", 0x05a4 },
+ { "mahiragana", 0x307e },
+ { "maichattawalowleftthai", 0xf895 },
+ { "maichattawalowrightthai", 0xf894 },
+ { "maichattawathai", 0x0e4b },
+ { "maichattawaupperleftthai", 0xf893 },
+ { "maieklowleftthai", 0xf88c },
+ { "maieklowrightthai", 0xf88b },
+ { "maiekthai", 0x0e48 },
+ { "maiekupperleftthai", 0xf88a },
+ { "maihanakatleftthai", 0xf884 },
+ { "maihanakatthai", 0x0e31 },
+ { "maitaikhuleftthai", 0xf889 },
+ { "maitaikhuthai", 0x0e47 },
+ { "maitholowleftthai", 0xf88f },
+ { "maitholowrightthai", 0xf88e },
+ { "maithothai", 0x0e49 },
+ { "maithoupperleftthai", 0xf88d },
+ { "maitrilowleftthai", 0xf892 },
+ { "maitrilowrightthai", 0xf891 },
+ { "maitrithai", 0x0e4a },
+ { "maitriupperleftthai", 0xf890 },
+ { "maiyamokthai", 0x0e46 },
+ { "makatakana", 0x30de },
+ { "makatakanahalfwidth", 0xff8f },
+ { "mansyonsquare", 0x3347 },
+ { "maqafhebrew", 0x05be },
+ { "mars", 0x2642 },
+ { "masoracirclehebrew", 0x05af },
+ { "masquare", 0x3383 },
+ { "mbopomofo", 0x3107 },
+ { "mbsquare", 0x33d4 },
+ { "mcircle", 0x24dc },
+ { "mcubedsquare", 0x33a5 },
+ { "mdotaccent", 0x1e41 },
+ { "mdotbelow", 0x1e43 },
+ { "meemarabic", 0x0645 },
+ { "meemfinalarabic", 0xfee2 },
+ { "meeminitialarabic", 0xfee3 },
+ { "meemmedialarabic", 0xfee4 },
+ { "meemmeeminitialarabic", 0xfcd1 },
+ { "meemmeemisolatedarabic", 0xfc48 },
+ { "meetorusquare", 0x334d },
+ { "mehiragana", 0x3081 },
+ { "meizierasquare", 0x337e },
+ { "mekatakana", 0x30e1 },
+ { "mekatakanahalfwidth", 0xff92 },
+ { "mem", 0x05de },
+ { "memdagesh", 0xfb3e },
+ { "memdageshhebrew", 0xfb3e },
+ { "memhebrew", 0x05de },
+ { "menarmenian", 0x0574 },
+ { "merkhahebrew", 0x05a5 },
+ { "merkhakefulahebrew", 0x05a6 },
+ { "merkhakefulalefthebrew", 0x05a6 },
+ { "merkhalefthebrew", 0x05a5 },
+ { "mhook", 0x0271 },
+ { "mhzsquare", 0x3392 },
+ { "middledotkatakanahalfwidth", 0xff65 },
+ { "middot", 0x00b7 },
+ { "mieumacirclekorean", 0x3272 },
+ { "mieumaparenkorean", 0x3212 },
+ { "mieumcirclekorean", 0x3264 },
+ { "mieumkorean", 0x3141 },
+ { "mieumpansioskorean", 0x3170 },
+ { "mieumparenkorean", 0x3204 },
+ { "mieumpieupkorean", 0x316e },
+ { "mieumsioskorean", 0x316f },
+ { "mihiragana", 0x307f },
+ { "mikatakana", 0x30df },
+ { "mikatakanahalfwidth", 0xff90 },
+ { "minusbelowcmb", 0x0320 },
+ { "minuscircle", 0x2296 },
+ { "minusmod", 0x02d7 },
+ { "minusplus", 0x2213 },
+ { "miribaarusquare", 0x334a },
+ { "mirisquare", 0x3349 },
+ { "mlonglegturned", 0x0270 },
+ { "mlsquare", 0x3396 },
+ { "mmcubedsquare", 0x33a3 },
+ { "mmonospace", 0xff4d },
+ { "mmsquaredsquare", 0x339f },
+ { "mohiragana", 0x3082 },
+ { "mohmsquare", 0x33c1 },
+ { "mokatakana", 0x30e2 },
+ { "mokatakanahalfwidth", 0xff93 },
+ { "molsquare", 0x33d6 },
+ { "momathai", 0x0e21 },
+ { "moverssquare", 0x33a7 },
+ { "moverssquaredsquare", 0x33a8 },
+ { "mparen", 0x24a8 },
+ { "mpasquare", 0x33ab },
+ { "mssquare", 0x33b3 },
+ { "msuperior", 0xf6ef },
+ { "mturned", 0x026f },
+ { "mu1", 0x00b5 },
+ { "muasquare", 0x3382 },
+ { "muchgreater", 0x226b },
+ { "muchless", 0x226a },
+ { "mufsquare", 0x338c },
+ { "mugreek", 0x03bc },
+ { "mugsquare", 0x338d },
+ { "muhiragana", 0x3080 },
+ { "mukatakana", 0x30e0 },
+ { "mukatakanahalfwidth", 0xff91 },
+ { "mulsquare", 0x3395 },
+ { "mumsquare", 0x339b },
+ { "munahhebrew", 0x05a3 },
+ { "munahlefthebrew", 0x05a3 },
+ { "musicflatsign", 0x266d },
+ { "musicsharpsign", 0x266f },
+ { "mussquare", 0x33b2 },
+ { "muvsquare", 0x33b6 },
+ { "muwsquare", 0x33bc },
+ { "mvmegasquare", 0x33b9 },
+ { "mvsquare", 0x33b7 },
+ { "mwmegasquare", 0x33bf },
+ { "mwsquare", 0x33bd },
+ { "nabengali", 0x09a8 },
+ { "nabla", 0x2207 },
+ { "nadeva", 0x0928 },
+ { "nagujarati", 0x0aa8 },
+ { "nagurmukhi", 0x0a28 },
+ { "nahiragana", 0x306a },
+ { "nakatakana", 0x30ca },
+ { "nakatakanahalfwidth", 0xff85 },
+ { "nasquare", 0x3381 },
+ { "nbopomofo", 0x310b },
+ { "nbspace", 0x00a0 },
+ { "ncedilla", 0x0146 },
+ { "ncircle", 0x24dd },
+ { "ncircumflexbelow", 0x1e4b },
+ { "ndotaccent", 0x1e45 },
+ { "ndotbelow", 0x1e47 },
+ { "nehiragana", 0x306d },
+ { "nekatakana", 0x30cd },
+ { "nekatakanahalfwidth", 0xff88 },
+ { "newsheqelsign", 0x20aa },
+ { "nfsquare", 0x338b },
+ { "ngabengali", 0x0999 },
+ { "ngadeva", 0x0919 },
+ { "ngagujarati", 0x0a99 },
+ { "ngagurmukhi", 0x0a19 },
+ { "ngonguthai", 0x0e07 },
+ { "nhiragana", 0x3093 },
+ { "nhookleft", 0x0272 },
+ { "nhookretroflex", 0x0273 },
+ { "nieunacirclekorean", 0x326f },
+ { "nieunaparenkorean", 0x320f },
+ { "nieuncieuckorean", 0x3135 },
+ { "nieuncirclekorean", 0x3261 },
+ { "nieunhieuhkorean", 0x3136 },
+ { "nieunkorean", 0x3134 },
+ { "nieunpansioskorean", 0x3168 },
+ { "nieunparenkorean", 0x3201 },
+ { "nieunsioskorean", 0x3167 },
+ { "nieuntikeutkorean", 0x3166 },
+ { "nihiragana", 0x306b },
+ { "nikatakana", 0x30cb },
+ { "nikatakanahalfwidth", 0xff86 },
+ { "nikhahitleftthai", 0xf899 },
+ { "nikhahitthai", 0x0e4d },
+ { "ninearabic", 0x0669 },
+ { "ninebengali", 0x09ef },
+ { "ninecircle", 0x2468 },
+ { "ninecircleinversesansserif", 0x2792 },
+ { "ninedeva", 0x096f },
+ { "ninegujarati", 0x0aef },
+ { "ninegurmukhi", 0x0a6f },
+ { "ninehackarabic", 0x0669 },
+ { "ninehangzhou", 0x3029 },
+ { "nineideographicparen", 0x3228 },
+ { "nineinferior", 0x2089 },
+ { "ninemonospace", 0xff19 },
+ { "nineoldstyle", 0xf739 },
+ { "nineparen", 0x247c },
+ { "nineperiod", 0x2490 },
+ { "ninepersian", 0x06f9 },
+ { "nineroman", 0x2178 },
+ { "ninesuperior", 0x2079 },
+ { "nineteencircle", 0x2472 },
+ { "nineteenparen", 0x2486 },
+ { "nineteenperiod", 0x249a },
+ { "ninethai", 0x0e59 },
+ { "nj", 0x01cc },
+ { "njecyrillic", 0x045a },
+ { "nkatakana", 0x30f3 },
+ { "nkatakanahalfwidth", 0xff9d },
+ { "nlegrightlong", 0x019e },
+ { "nlinebelow", 0x1e49 },
+ { "nmonospace", 0xff4e },
+ { "nmsquare", 0x339a },
+ { "nnabengali", 0x09a3 },
+ { "nnadeva", 0x0923 },
+ { "nnagujarati", 0x0aa3 },
+ { "nnagurmukhi", 0x0a23 },
+ { "nnnadeva", 0x0929 },
+ { "nohiragana", 0x306e },
+ { "nokatakana", 0x30ce },
+ { "nokatakanahalfwidth", 0xff89 },
+ { "nonbreakingspace", 0x00a0 },
+ { "nonenthai", 0x0e13 },
+ { "nonuthai", 0x0e19 },
+ { "noonarabic", 0x0646 },
+ { "noonfinalarabic", 0xfee6 },
+ { "noonghunnaarabic", 0x06ba },
+ { "noonghunnafinalarabic", 0xfb9f },
+ { "noonhehinitialarabic", 0xfee7 },
+ { "nooninitialarabic", 0xfee7 },
+ { "noonjeeminitialarabic", 0xfcd2 },
+ { "noonjeemisolatedarabic", 0xfc4b },
+ { "noonmedialarabic", 0xfee8 },
+ { "noonmeeminitialarabic", 0xfcd5 },
+ { "noonmeemisolatedarabic", 0xfc4e },
+ { "noonnoonfinalarabic", 0xfc8d },
+ { "notcontains", 0x220c },
+ { "notelementof", 0x2209 },
+ { "notgreater", 0x226f },
+ { "notgreaternorequal", 0x2271 },
+ { "notgreaternorless", 0x2279 },
+ { "notidentical", 0x2262 },
+ { "notless", 0x226e },
+ { "notlessnorequal", 0x2270 },
+ { "notparallel", 0x2226 },
+ { "notprecedes", 0x2280 },
+ { "notsucceeds", 0x2281 },
+ { "notsuperset", 0x2285 },
+ { "nowarmenian", 0x0576 },
+ { "nparen", 0x24a9 },
+ { "nssquare", 0x33b1 },
+ { "nsuperior", 0x207f },
+ { "nuhiragana", 0x306c },
+ { "nukatakana", 0x30cc },
+ { "nukatakanahalfwidth", 0xff87 },
+ { "nuktabengali", 0x09bc },
+ { "nuktadeva", 0x093c },
+ { "nuktagujarati", 0x0abc },
+ { "nuktagurmukhi", 0x0a3c },
+ { "numbersignmonospace", 0xff03 },
+ { "numbersignsmall", 0xfe5f },
+ { "numeralsigngreek", 0x0374 },
+ { "numeralsignlowergreek", 0x0375 },
+ { "numero", 0x2116 },
+ { "nun", 0x05e0 },
+ { "nundagesh", 0xfb40 },
+ { "nundageshhebrew", 0xfb40 },
+ { "nunhebrew", 0x05e0 },
+ { "nvsquare", 0x33b5 },
+ { "nwsquare", 0x33bb },
+ { "nyabengali", 0x099e },
+ { "nyadeva", 0x091e },
+ { "nyagujarati", 0x0a9e },
+ { "nyagurmukhi", 0x0a1e },
+ { "oangthai", 0x0e2d },
+ { "obarred", 0x0275 },
+ { "obarredcyrillic", 0x04e9 },
+ { "obarreddieresiscyrillic", 0x04eb },
+ { "obengali", 0x0993 },
+ { "obopomofo", 0x311b },
+ { "ocandradeva", 0x0911 },
+ { "ocandragujarati", 0x0a91 },
+ { "ocandravowelsigndeva", 0x0949 },
+ { "ocandravowelsigngujarati", 0x0ac9 },
+ { "ocaron", 0x01d2 },
+ { "ocircle", 0x24de },
+ { "ocircumflexacute", 0x1ed1 },
+ { "ocircumflexdotbelow", 0x1ed9 },
+ { "ocircumflexgrave", 0x1ed3 },
+ { "ocircumflexhookabove", 0x1ed5 },
+ { "ocircumflextilde", 0x1ed7 },
+ { "ocyrillic", 0x043e },
+ { "odblacute", 0x0151 },
+ { "odblgrave", 0x020d },
+ { "odeva", 0x0913 },
+ { "odieresiscyrillic", 0x04e7 },
+ { "odotbelow", 0x1ecd },
+ { "oekorean", 0x315a },
+ { "ogonekcmb", 0x0328 },
+ { "ogujarati", 0x0a93 },
+ { "oharmenian", 0x0585 },
+ { "ohiragana", 0x304a },
+ { "ohookabove", 0x1ecf },
+ { "ohornacute", 0x1edb },
+ { "ohorndotbelow", 0x1ee3 },
+ { "ohorngrave", 0x1edd },
+ { "ohornhookabove", 0x1edf },
+ { "ohorntilde", 0x1ee1 },
+ { "oi", 0x01a3 },
+ { "oinvertedbreve", 0x020f },
+ { "okatakana", 0x30aa },
+ { "okatakanahalfwidth", 0xff75 },
+ { "okorean", 0x3157 },
+ { "olehebrew", 0x05ab },
+ { "omacronacute", 0x1e53 },
+ { "omacrongrave", 0x1e51 },
+ { "omdeva", 0x0950 },
+ { "omegacyrillic", 0x0461 },
+ { "omegalatinclosed", 0x0277 },
+ { "omegaroundcyrillic", 0x047b },
+ { "omegatitlocyrillic", 0x047d },
+ { "omgujarati", 0x0ad0 },
+ { "omonospace", 0xff4f },
+ { "onearabic", 0x0661 },
+ { "onebengali", 0x09e7 },
+ { "onecircle", 0x2460 },
+ { "onecircleinversesansserif", 0x278a },
+ { "onedeva", 0x0967 },
+ { "onefitted", 0xf6dc },
+ { "onegujarati", 0x0ae7 },
+ { "onegurmukhi", 0x0a67 },
+ { "onehackarabic", 0x0661 },
+ { "onehangzhou", 0x3021 },
+ { "oneideographicparen", 0x3220 },
+ { "oneinferior", 0x2081 },
+ { "onemonospace", 0xff11 },
+ { "onenumeratorbengali", 0x09f4 },
+ { "oneoldstyle", 0xf731 },
+ { "oneparen", 0x2474 },
+ { "oneperiod", 0x2488 },
+ { "onepersian", 0x06f1 },
+ { "oneroman", 0x2170 },
+ { "onesuperior", 0x00b9 },
+ { "onethai", 0x0e51 },
+ { "oogonek", 0x01eb },
+ { "oogonekmacron", 0x01ed },
+ { "oogurmukhi", 0x0a13 },
+ { "oomatragurmukhi", 0x0a4b },
+ { "oopen", 0x0254 },
+ { "oparen", 0x24aa },
+ { "option", 0x2325 },
+ { "oshortdeva", 0x0912 },
+ { "oshortvowelsigndeva", 0x094a },
+ { "osmallhiragana", 0x3049 },
+ { "osmallkatakana", 0x30a9 },
+ { "osmallkatakanahalfwidth", 0xff6b },
+ { "ostrokeacute", 0x01ff },
+ { "osuperior", 0xf6f0 },
+ { "otcyrillic", 0x047f },
+ { "otildeacute", 0x1e4d },
+ { "otildedieresis", 0x1e4f },
+ { "oubopomofo", 0x3121 },
+ { "overline", 0x203e },
+ { "overlinecenterline", 0xfe4a },
+ { "overlinecmb", 0x0305 },
+ { "overlinedashed", 0xfe49 },
+ { "overlinedblwavy", 0xfe4c },
+ { "overlinewavy", 0xfe4b },
+ { "overscore", 0x00af },
+ { "ovowelsignbengali", 0x09cb },
+ { "ovowelsigndeva", 0x094b },
+ { "ovowelsigngujarati", 0x0acb },
+ { "paampssquare", 0x3380 },
+ { "paasentosquare", 0x332b },
+ { "pabengali", 0x09aa },
+ { "pacute", 0x1e55 },
+ { "padeva", 0x092a },
+ { "pagedown", 0x21df },
+ { "pageup", 0x21de },
+ { "pagujarati", 0x0aaa },
+ { "pagurmukhi", 0x0a2a },
+ { "pahiragana", 0x3071 },
+ { "paiyannoithai", 0x0e2f },
+ { "pakatakana", 0x30d1 },
+ { "palatalizationcyrilliccmb", 0x0484 },
+ { "palochkacyrillic", 0x04c0 },
+ { "pansioskorean", 0x317f },
+ { "parallel", 0x2225 },
+ { "parenleftaltonearabic", 0xfd3e },
+ { "parenleftbt", 0xf8ed },
+ { "parenleftex", 0xf8ec },
+ { "parenleftinferior", 0x208d },
+ { "parenleftmonospace", 0xff08 },
+ { "parenleftsmall", 0xfe59 },
+ { "parenleftsuperior", 0x207d },
+ { "parenlefttp", 0xf8eb },
+ { "parenleftvertical", 0xfe35 },
+ { "parenrightaltonearabic", 0xfd3f },
+ { "parenrightbt", 0xf8f8 },
+ { "parenrightex", 0xf8f7 },
+ { "parenrightinferior", 0x208e },
+ { "parenrightmonospace", 0xff09 },
+ { "parenrightsmall", 0xfe5a },
+ { "parenrightsuperior", 0x207e },
+ { "parenrighttp", 0xf8f6 },
+ { "parenrightvertical", 0xfe36 },
+ { "paseqhebrew", 0x05c0 },
+ { "pashtahebrew", 0x0599 },
+ { "pasquare", 0x33a9 },
+ { "patah", 0x05b7 },
+ { "patah11", 0x05b7 },
+ { "patah1d", 0x05b7 },
+ { "patah2a", 0x05b7 },
+ { "patahhebrew", 0x05b7 },
+ { "patahnarrowhebrew", 0x05b7 },
+ { "patahquarterhebrew", 0x05b7 },
+ { "patahwidehebrew", 0x05b7 },
+ { "pazerhebrew", 0x05a1 },
+ { "pbopomofo", 0x3106 },
+ { "pcircle", 0x24df },
+ { "pdotaccent", 0x1e57 },
+ { "pe", 0x05e4 },
+ { "pecyrillic", 0x043f },
+ { "pedagesh", 0xfb44 },
+ { "pedageshhebrew", 0xfb44 },
+ { "peezisquare", 0x333b },
+ { "pefinaldageshhebrew", 0xfb43 },
+ { "peharabic", 0x067e },
+ { "peharmenian", 0x057a },
+ { "pehebrew", 0x05e4 },
+ { "pehfinalarabic", 0xfb57 },
+ { "pehinitialarabic", 0xfb58 },
+ { "pehiragana", 0x307a },
+ { "pehmedialarabic", 0xfb59 },
+ { "pekatakana", 0x30da },
+ { "pemiddlehookcyrillic", 0x04a7 },
+ { "perafehebrew", 0xfb4e },
+ { "percentarabic", 0x066a },
+ { "percentmonospace", 0xff05 },
+ { "percentsmall", 0xfe6a },
+ { "periodarmenian", 0x0589 },
+ { "periodhalfwidth", 0xff61 },
+ { "periodinferior", 0xf6e7 },
+ { "periodmonospace", 0xff0e },
+ { "periodsmall", 0xfe52 },
+ { "periodsuperior", 0xf6e8 },
+ { "perispomenigreekcmb", 0x0342 },
+ { "pfsquare", 0x338a },
+ { "phabengali", 0x09ab },
+ { "phadeva", 0x092b },
+ { "phagujarati", 0x0aab },
+ { "phagurmukhi", 0x0a2b },
+ { "phieuphacirclekorean", 0x327a },
+ { "phieuphaparenkorean", 0x321a },
+ { "phieuphcirclekorean", 0x326c },
+ { "phieuphkorean", 0x314d },
+ { "phieuphparenkorean", 0x320c },
+ { "philatin", 0x0278 },
+ { "phinthuthai", 0x0e3a },
+ { "phisymbolgreek", 0x03d5 },
+ { "phook", 0x01a5 },
+ { "phophanthai", 0x0e1e },
+ { "phophungthai", 0x0e1c },
+ { "phosamphaothai", 0x0e20 },
+ { "pieupacirclekorean", 0x3273 },
+ { "pieupaparenkorean", 0x3213 },
+ { "pieupcieuckorean", 0x3176 },
+ { "pieupcirclekorean", 0x3265 },
+ { "pieupkiyeokkorean", 0x3172 },
+ { "pieupkorean", 0x3142 },
+ { "pieupparenkorean", 0x3205 },
+ { "pieupsioskiyeokkorean", 0x3174 },
+ { "pieupsioskorean", 0x3144 },
+ { "pieupsiostikeutkorean", 0x3175 },
+ { "pieupthieuthkorean", 0x3177 },
+ { "pieuptikeutkorean", 0x3173 },
+ { "pihiragana", 0x3074 },
+ { "pikatakana", 0x30d4 },
+ { "pisymbolgreek", 0x03d6 },
+ { "piwrarmenian", 0x0583 },
+ { "plusbelowcmb", 0x031f },
+ { "pluscircle", 0x2295 },
+ { "plusmod", 0x02d6 },
+ { "plusmonospace", 0xff0b },
+ { "plussmall", 0xfe62 },
+ { "plussuperior", 0x207a },
+ { "pmonospace", 0xff50 },
+ { "pmsquare", 0x33d8 },
+ { "pohiragana", 0x307d },
+ { "pointingindexdownwhite", 0x261f },
+ { "pointingindexleftwhite", 0x261c },
+ { "pointingindexrightwhite", 0x261e },
+ { "pointingindexupwhite", 0x261d },
+ { "pokatakana", 0x30dd },
+ { "poplathai", 0x0e1b },
+ { "postalmark", 0x3012 },
+ { "postalmarkface", 0x3020 },
+ { "pparen", 0x24ab },
+ { "precedes", 0x227a },
+ { "primemod", 0x02b9 },
+ { "primereversed", 0x2035 },
+ { "projective", 0x2305 },
+ { "prolongedkana", 0x30fc },
+ { "propellor", 0x2318 },
+ { "proportion", 0x2237 },
+ { "psicyrillic", 0x0471 },
+ { "psilipneumatacyrilliccmb", 0x0486 },
+ { "pssquare", 0x33b0 },
+ { "puhiragana", 0x3077 },
+ { "pukatakana", 0x30d7 },
+ { "pvsquare", 0x33b4 },
+ { "pwsquare", 0x33ba },
+ { "qadeva", 0x0958 },
+ { "qadmahebrew", 0x05a8 },
+ { "qafarabic", 0x0642 },
+ { "qaffinalarabic", 0xfed6 },
+ { "qafinitialarabic", 0xfed7 },
+ { "qafmedialarabic", 0xfed8 },
+ { "qamats", 0x05b8 },
+ { "qamats10", 0x05b8 },
+ { "qamats1a", 0x05b8 },
+ { "qamats1c", 0x05b8 },
+ { "qamats27", 0x05b8 },
+ { "qamats29", 0x05b8 },
+ { "qamats33", 0x05b8 },
+ { "qamatsde", 0x05b8 },
+ { "qamatshebrew", 0x05b8 },
+ { "qamatsnarrowhebrew", 0x05b8 },
+ { "qamatsqatanhebrew", 0x05b8 },
+ { "qamatsqatannarrowhebrew", 0x05b8 },
+ { "qamatsqatanquarterhebrew", 0x05b8 },
+ { "qamatsqatanwidehebrew", 0x05b8 },
+ { "qamatsquarterhebrew", 0x05b8 },
+ { "qamatswidehebrew", 0x05b8 },
+ { "qarneyparahebrew", 0x059f },
+ { "qbopomofo", 0x3111 },
+ { "qcircle", 0x24e0 },
+ { "qhook", 0x02a0 },
+ { "qmonospace", 0xff51 },
+ { "qof", 0x05e7 },
+ { "qofdagesh", 0xfb47 },
+ { "qofdageshhebrew", 0xfb47 },
+ { "qofhatafpatah", 0x05e7 },
+ { "qofhatafpatahhebrew", 0x05e7 },
+ { "qofhatafsegol", 0x05e7 },
+ { "qofhatafsegolhebrew", 0x05e7 },
+ { "qofhebrew", 0x05e7 },
+ { "qofhiriq", 0x05e7 },
+ { "qofhiriqhebrew", 0x05e7 },
+ { "qofholam", 0x05e7 },
+ { "qofholamhebrew", 0x05e7 },
+ { "qofpatah", 0x05e7 },
+ { "qofpatahhebrew", 0x05e7 },
+ { "qofqamats", 0x05e7 },
+ { "qofqamatshebrew", 0x05e7 },
+ { "qofqubuts", 0x05e7 },
+ { "qofqubutshebrew", 0x05e7 },
+ { "qofsegol", 0x05e7 },
+ { "qofsegolhebrew", 0x05e7 },
+ { "qofsheva", 0x05e7 },
+ { "qofshevahebrew", 0x05e7 },
+ { "qoftsere", 0x05e7 },
+ { "qoftserehebrew", 0x05e7 },
+ { "qparen", 0x24ac },
+ { "quarternote", 0x2669 },
+ { "qubuts", 0x05bb },
+ { "qubuts18", 0x05bb },
+ { "qubuts25", 0x05bb },
+ { "qubuts31", 0x05bb },
+ { "qubutshebrew", 0x05bb },
+ { "qubutsnarrowhebrew", 0x05bb },
+ { "qubutsquarterhebrew", 0x05bb },
+ { "qubutswidehebrew", 0x05bb },
+ { "questionarabic", 0x061f },
+ { "questionarmenian", 0x055e },
+ { "questiondownsmall", 0xf7bf },
+ { "questiongreek", 0x037e },
+ { "questionmonospace", 0xff1f },
+ { "questionsmall", 0xf73f },
+ { "quotedblmonospace", 0xff02 },
+ { "quotedblprime", 0x301e },
+ { "quotedblprimereversed", 0x301d },
+ { "quoteleftreversed", 0x201b },
+ { "quoterightn", 0x0149 },
+ { "quotesinglemonospace", 0xff07 },
+ { "raarmenian", 0x057c },
+ { "rabengali", 0x09b0 },
+ { "radeva", 0x0930 },
+ { "radicalex", 0xf8e5 },
+ { "radoverssquare", 0x33ae },
+ { "radoverssquaredsquare", 0x33af },
+ { "radsquare", 0x33ad },
+ { "rafe", 0x05bf },
+ { "rafehebrew", 0x05bf },
+ { "ragujarati", 0x0ab0 },
+ { "ragurmukhi", 0x0a30 },
+ { "rahiragana", 0x3089 },
+ { "rakatakana", 0x30e9 },
+ { "rakatakanahalfwidth", 0xff97 },
+ { "ralowerdiagonalbengali", 0x09f1 },
+ { "ramiddlediagonalbengali", 0x09f0 },
+ { "ramshorn", 0x0264 },
+ { "ratio", 0x2236 },
+ { "rbopomofo", 0x3116 },
+ { "rcedilla", 0x0157 },
+ { "rcircle", 0x24e1 },
+ { "rdblgrave", 0x0211 },
+ { "rdotaccent", 0x1e59 },
+ { "rdotbelow", 0x1e5b },
+ { "rdotbelowmacron", 0x1e5d },
+ { "referencemark", 0x203b },
+ { "registersans", 0xf8e8 },
+ { "registerserif", 0xf6da },
+ { "reharabic", 0x0631 },
+ { "reharmenian", 0x0580 },
+ { "rehfinalarabic", 0xfeae },
+ { "rehiragana", 0x308c },
+ { "rehyehaleflamarabic", 0x0631 },
+ { "rekatakana", 0x30ec },
+ { "rekatakanahalfwidth", 0xff9a },
+ { "resh", 0x05e8 },
+ { "reshdageshhebrew", 0xfb48 },
+ { "reshhatafpatah", 0x05e8 },
+ { "reshhatafpatahhebrew", 0x05e8 },
+ { "reshhatafsegol", 0x05e8 },
+ { "reshhatafsegolhebrew", 0x05e8 },
+ { "reshhebrew", 0x05e8 },
+ { "reshhiriq", 0x05e8 },
+ { "reshhiriqhebrew", 0x05e8 },
+ { "reshholam", 0x05e8 },
+ { "reshholamhebrew", 0x05e8 },
+ { "reshpatah", 0x05e8 },
+ { "reshpatahhebrew", 0x05e8 },
+ { "reshqamats", 0x05e8 },
+ { "reshqamatshebrew", 0x05e8 },
+ { "reshqubuts", 0x05e8 },
+ { "reshqubutshebrew", 0x05e8 },
+ { "reshsegol", 0x05e8 },
+ { "reshsegolhebrew", 0x05e8 },
+ { "reshsheva", 0x05e8 },
+ { "reshshevahebrew", 0x05e8 },
+ { "reshtsere", 0x05e8 },
+ { "reshtserehebrew", 0x05e8 },
+ { "reversedtilde", 0x223d },
+ { "reviahebrew", 0x0597 },
+ { "reviamugrashhebrew", 0x0597 },
+ { "rfishhook", 0x027e },
+ { "rfishhookreversed", 0x027f },
+ { "rhabengali", 0x09dd },
+ { "rhadeva", 0x095d },
+ { "rhook", 0x027d },
+ { "rhookturned", 0x027b },
+ { "rhookturnedsuperior", 0x02b5 },
+ { "rhosymbolgreek", 0x03f1 },
+ { "rhotichookmod", 0x02de },
+ { "rieulacirclekorean", 0x3271 },
+ { "rieulaparenkorean", 0x3211 },
+ { "rieulcirclekorean", 0x3263 },
+ { "rieulhieuhkorean", 0x3140 },
+ { "rieulkiyeokkorean", 0x313a },
+ { "rieulkiyeoksioskorean", 0x3169 },
+ { "rieulkorean", 0x3139 },
+ { "rieulmieumkorean", 0x313b },
+ { "rieulpansioskorean", 0x316c },
+ { "rieulparenkorean", 0x3203 },
+ { "rieulphieuphkorean", 0x313f },
+ { "rieulpieupkorean", 0x313c },
+ { "rieulpieupsioskorean", 0x316b },
+ { "rieulsioskorean", 0x313d },
+ { "rieulthieuthkorean", 0x313e },
+ { "rieultikeutkorean", 0x316a },
+ { "rieulyeorinhieuhkorean", 0x316d },
+ { "rightangle", 0x221f },
+ { "righttackbelowcmb", 0x0319 },
+ { "righttriangle", 0x22bf },
+ { "rihiragana", 0x308a },
+ { "rikatakana", 0x30ea },
+ { "rikatakanahalfwidth", 0xff98 },
+ { "ringbelowcmb", 0x0325 },
+ { "ringcmb", 0x030a },
+ { "ringhalfleft", 0x02bf },
+ { "ringhalfleftarmenian", 0x0559 },
+ { "ringhalfleftbelowcmb", 0x031c },
+ { "ringhalfleftcentered", 0x02d3 },
+ { "ringhalfright", 0x02be },
+ { "ringhalfrightbelowcmb", 0x0339 },
+ { "ringhalfrightcentered", 0x02d2 },
+ { "rinvertedbreve", 0x0213 },
+ { "rittorusquare", 0x3351 },
+ { "rlinebelow", 0x1e5f },
+ { "rlongleg", 0x027c },
+ { "rlonglegturned", 0x027a },
+ { "rmonospace", 0xff52 },
+ { "rohiragana", 0x308d },
+ { "rokatakana", 0x30ed },
+ { "rokatakanahalfwidth", 0xff9b },
+ { "roruathai", 0x0e23 },
+ { "rparen", 0x24ad },
+ { "rrabengali", 0x09dc },
+ { "rradeva", 0x0931 },
+ { "rragurmukhi", 0x0a5c },
+ { "rreharabic", 0x0691 },
+ { "rrehfinalarabic", 0xfb8d },
+ { "rrvocalicbengali", 0x09e0 },
+ { "rrvocalicdeva", 0x0960 },
+ { "rrvocalicgujarati", 0x0ae0 },
+ { "rrvocalicvowelsignbengali", 0x09c4 },
+ { "rrvocalicvowelsigndeva", 0x0944 },
+ { "rrvocalicvowelsigngujarati", 0x0ac4 },
+ { "rsuperior", 0xf6f1 },
+ { "rturned", 0x0279 },
+ { "rturnedsuperior", 0x02b4 },
+ { "ruhiragana", 0x308b },
+ { "rukatakana", 0x30eb },
+ { "rukatakanahalfwidth", 0xff99 },
+ { "rupeemarkbengali", 0x09f2 },
+ { "rupeesignbengali", 0x09f3 },
+ { "rupiah", 0xf6dd },
+ { "ruthai", 0x0e24 },
+ { "rvocalicbengali", 0x098b },
+ { "rvocalicdeva", 0x090b },
+ { "rvocalicgujarati", 0x0a8b },
+ { "rvocalicvowelsignbengali", 0x09c3 },
+ { "rvocalicvowelsigndeva", 0x0943 },
+ { "rvocalicvowelsigngujarati", 0x0ac3 },
+ { "sabengali", 0x09b8 },
+ { "sacutedotaccent", 0x1e65 },
+ { "sadarabic", 0x0635 },
+ { "sadeva", 0x0938 },
+ { "sadfinalarabic", 0xfeba },
+ { "sadinitialarabic", 0xfebb },
+ { "sadmedialarabic", 0xfebc },
+ { "sagujarati", 0x0ab8 },
+ { "sagurmukhi", 0x0a38 },
+ { "sahiragana", 0x3055 },
+ { "sakatakana", 0x30b5 },
+ { "sakatakanahalfwidth", 0xff7b },
+ { "sallallahoualayhewasallamarabic", 0xfdfa },
+ { "samekh", 0x05e1 },
+ { "samekhdagesh", 0xfb41 },
+ { "samekhdageshhebrew", 0xfb41 },
+ { "samekhhebrew", 0x05e1 },
+ { "saraaathai", 0x0e32 },
+ { "saraaethai", 0x0e41 },
+ { "saraaimaimalaithai", 0x0e44 },
+ { "saraaimaimuanthai", 0x0e43 },
+ { "saraamthai", 0x0e33 },
+ { "saraathai", 0x0e30 },
+ { "saraethai", 0x0e40 },
+ { "saraiileftthai", 0xf886 },
+ { "saraiithai", 0x0e35 },
+ { "saraileftthai", 0xf885 },
+ { "saraithai", 0x0e34 },
+ { "saraothai", 0x0e42 },
+ { "saraueeleftthai", 0xf888 },
+ { "saraueethai", 0x0e37 },
+ { "saraueleftthai", 0xf887 },
+ { "sarauethai", 0x0e36 },
+ { "sarauthai", 0x0e38 },
+ { "sarauuthai", 0x0e39 },
+ { "sbopomofo", 0x3119 },
+ { "scarondotaccent", 0x1e67 },
+ { "schwa", 0x0259 },
+ { "schwacyrillic", 0x04d9 },
+ { "schwadieresiscyrillic", 0x04db },
+ { "schwahook", 0x025a },
+ { "scircle", 0x24e2 },
+ { "sdotaccent", 0x1e61 },
+ { "sdotbelow", 0x1e63 },
+ { "sdotbelowdotaccent", 0x1e69 },
+ { "seagullbelowcmb", 0x033c },
+ { "secondtonechinese", 0x02ca },
+ { "seenarabic", 0x0633 },
+ { "seenfinalarabic", 0xfeb2 },
+ { "seeninitialarabic", 0xfeb3 },
+ { "seenmedialarabic", 0xfeb4 },
+ { "segol", 0x05b6 },
+ { "segol13", 0x05b6 },
+ { "segol1f", 0x05b6 },
+ { "segol2c", 0x05b6 },
+ { "segolhebrew", 0x05b6 },
+ { "segolnarrowhebrew", 0x05b6 },
+ { "segolquarterhebrew", 0x05b6 },
+ { "segoltahebrew", 0x0592 },
+ { "segolwidehebrew", 0x05b6 },
+ { "seharmenian", 0x057d },
+ { "sehiragana", 0x305b },
+ { "sekatakana", 0x30bb },
+ { "sekatakanahalfwidth", 0xff7e },
+ { "semicolonarabic", 0x061b },
+ { "semicolonmonospace", 0xff1b },
+ { "semicolonsmall", 0xfe54 },
+ { "semivoicedmarkkana", 0x309c },
+ { "semivoicedmarkkanahalfwidth", 0xff9f },
+ { "sentisquare", 0x3322 },
+ { "sentosquare", 0x3323 },
+ { "sevenarabic", 0x0667 },
+ { "sevenbengali", 0x09ed },
+ { "sevencircle", 0x2466 },
+ { "sevencircleinversesansserif", 0x2790 },
+ { "sevendeva", 0x096d },
+ { "sevengujarati", 0x0aed },
+ { "sevengurmukhi", 0x0a6d },
+ { "sevenhackarabic", 0x0667 },
+ { "sevenhangzhou", 0x3027 },
+ { "sevenideographicparen", 0x3226 },
+ { "seveninferior", 0x2087 },
+ { "sevenmonospace", 0xff17 },
+ { "sevenoldstyle", 0xf737 },
+ { "sevenparen", 0x247a },
+ { "sevenperiod", 0x248e },
+ { "sevenpersian", 0x06f7 },
+ { "sevenroman", 0x2176 },
+ { "sevensuperior", 0x2077 },
+ { "seventeencircle", 0x2470 },
+ { "seventeenparen", 0x2484 },
+ { "seventeenperiod", 0x2498 },
+ { "seventhai", 0x0e57 },
+ { "sfthyphen", 0x00ad },
+ { "shaarmenian", 0x0577 },
+ { "shabengali", 0x09b6 },
+ { "shacyrillic", 0x0448 },
+ { "shaddaarabic", 0x0651 },
+ { "shaddadammaarabic", 0xfc61 },
+ { "shaddadammatanarabic", 0xfc5e },
+ { "shaddafathaarabic", 0xfc60 },
+ { "shaddafathatanarabic", 0x0651 },
+ { "shaddakasraarabic", 0xfc62 },
+ { "shaddakasratanarabic", 0xfc5f },
+ { "shadedark", 0x2593 },
+ { "shadelight", 0x2591 },
+ { "shademedium", 0x2592 },
+ { "shadeva", 0x0936 },
+ { "shagujarati", 0x0ab6 },
+ { "shagurmukhi", 0x0a36 },
+ { "shalshelethebrew", 0x0593 },
+ { "shbopomofo", 0x3115 },
+ { "shchacyrillic", 0x0449 },
+ { "sheenarabic", 0x0634 },
+ { "sheenfinalarabic", 0xfeb6 },
+ { "sheeninitialarabic", 0xfeb7 },
+ { "sheenmedialarabic", 0xfeb8 },
+ { "sheicoptic", 0x03e3 },
+ { "sheqel", 0x20aa },
+ { "sheqelhebrew", 0x20aa },
+ { "sheva", 0x05b0 },
+ { "sheva115", 0x05b0 },
+ { "sheva15", 0x05b0 },
+ { "sheva22", 0x05b0 },
+ { "sheva2e", 0x05b0 },
+ { "shevahebrew", 0x05b0 },
+ { "shevanarrowhebrew", 0x05b0 },
+ { "shevaquarterhebrew", 0x05b0 },
+ { "shevawidehebrew", 0x05b0 },
+ { "shhacyrillic", 0x04bb },
+ { "shimacoptic", 0x03ed },
+ { "shin", 0x05e9 },
+ { "shindagesh", 0xfb49 },
+ { "shindageshhebrew", 0xfb49 },
+ { "shindageshshindot", 0xfb2c },
+ { "shindageshshindothebrew", 0xfb2c },
+ { "shindageshsindot", 0xfb2d },
+ { "shindageshsindothebrew", 0xfb2d },
+ { "shindothebrew", 0x05c1 },
+ { "shinhebrew", 0x05e9 },
+ { "shinshindot", 0xfb2a },
+ { "shinshindothebrew", 0xfb2a },
+ { "shinsindot", 0xfb2b },
+ { "shinsindothebrew", 0xfb2b },
+ { "shook", 0x0282 },
+ { "sigmafinal", 0x03c2 },
+ { "sigmalunatesymbolgreek", 0x03f2 },
+ { "sihiragana", 0x3057 },
+ { "sikatakana", 0x30b7 },
+ { "sikatakanahalfwidth", 0xff7c },
+ { "siluqhebrew", 0x05bd },
+ { "siluqlefthebrew", 0x05bd },
+ { "sindothebrew", 0x05c2 },
+ { "siosacirclekorean", 0x3274 },
+ { "siosaparenkorean", 0x3214 },
+ { "sioscieuckorean", 0x317e },
+ { "sioscirclekorean", 0x3266 },
+ { "sioskiyeokkorean", 0x317a },
+ { "sioskorean", 0x3145 },
+ { "siosnieunkorean", 0x317b },
+ { "siosparenkorean", 0x3206 },
+ { "siospieupkorean", 0x317d },
+ { "siostikeutkorean", 0x317c },
+ { "sixarabic", 0x0666 },
+ { "sixbengali", 0x09ec },
+ { "sixcircle", 0x2465 },
+ { "sixcircleinversesansserif", 0x278f },
+ { "sixdeva", 0x096c },
+ { "sixgujarati", 0x0aec },
+ { "sixgurmukhi", 0x0a6c },
+ { "sixhackarabic", 0x0666 },
+ { "sixhangzhou", 0x3026 },
+ { "sixideographicparen", 0x3225 },
+ { "sixinferior", 0x2086 },
+ { "sixmonospace", 0xff16 },
+ { "sixoldstyle", 0xf736 },
+ { "sixparen", 0x2479 },
+ { "sixperiod", 0x248d },
+ { "sixpersian", 0x06f6 },
+ { "sixroman", 0x2175 },
+ { "sixsuperior", 0x2076 },
+ { "sixteencircle", 0x246f },
+ { "sixteencurrencydenominatorbengali", 0x09f9 },
+ { "sixteenparen", 0x2483 },
+ { "sixteenperiod", 0x2497 },
+ { "sixthai", 0x0e56 },
+ { "slashmonospace", 0xff0f },
+ { "slong", 0x017f },
+ { "slongdotaccent", 0x1e9b },
+ { "smonospace", 0xff53 },
+ { "sofpasuqhebrew", 0x05c3 },
+ { "softhyphen", 0x00ad },
+ { "softsigncyrillic", 0x044c },
+ { "sohiragana", 0x305d },
+ { "sokatakana", 0x30bd },
+ { "sokatakanahalfwidth", 0xff7f },
+ { "soliduslongoverlaycmb", 0x0338 },
+ { "solidusshortoverlaycmb", 0x0337 },
+ { "sorusithai", 0x0e29 },
+ { "sosalathai", 0x0e28 },
+ { "sosothai", 0x0e0b },
+ { "sosuathai", 0x0e2a },
+ { "spacehackarabic", 0x0020 },
+ { "spadesuitblack", 0x2660 },
+ { "spadesuitwhite", 0x2664 },
+ { "sparen", 0x24ae },
+ { "squarebelowcmb", 0x033b },
+ { "squarecc", 0x33c4 },
+ { "squarecm", 0x339d },
+ { "squarediagonalcrosshatchfill", 0x25a9 },
+ { "squarehorizontalfill", 0x25a4 },
+ { "squarekg", 0x338f },
+ { "squarekm", 0x339e },
+ { "squarekmcapital", 0x33ce },
+ { "squareln", 0x33d1 },
+ { "squarelog", 0x33d2 },
+ { "squaremg", 0x338e },
+ { "squaremil", 0x33d5 },
+ { "squaremm", 0x339c },
+ { "squaremsquared", 0x33a1 },
+ { "squareorthogonalcrosshatchfill", 0x25a6 },
+ { "squareupperlefttolowerrightfill", 0x25a7 },
+ { "squareupperrighttolowerleftfill", 0x25a8 },
+ { "squareverticalfill", 0x25a5 },
+ { "squarewhitewithsmallblack", 0x25a3 },
+ { "srsquare", 0x33db },
+ { "ssabengali", 0x09b7 },
+ { "ssadeva", 0x0937 },
+ { "ssagujarati", 0x0ab7 },
+ { "ssangcieuckorean", 0x3149 },
+ { "ssanghieuhkorean", 0x3185 },
+ { "ssangieungkorean", 0x3180 },
+ { "ssangkiyeokkorean", 0x3132 },
+ { "ssangnieunkorean", 0x3165 },
+ { "ssangpieupkorean", 0x3143 },
+ { "ssangsioskorean", 0x3146 },
+ { "ssangtikeutkorean", 0x3138 },
+ { "ssuperior", 0xf6f2 },
+ { "sterlingmonospace", 0xffe1 },
+ { "strokelongoverlaycmb", 0x0336 },
+ { "strokeshortoverlaycmb", 0x0335 },
+ { "subset", 0x2282 },
+ { "subsetnotequal", 0x228a },
+ { "subsetorequal", 0x2286 },
+ { "succeeds", 0x227b },
+ { "suhiragana", 0x3059 },
+ { "sukatakana", 0x30b9 },
+ { "sukatakanahalfwidth", 0xff7d },
+ { "sukunarabic", 0x0652 },
+ { "superset", 0x2283 },
+ { "supersetnotequal", 0x228b },
+ { "supersetorequal", 0x2287 },
+ { "svsquare", 0x33dc },
+ { "syouwaerasquare", 0x337c },
+ { "tabengali", 0x09a4 },
+ { "tackdown", 0x22a4 },
+ { "tackleft", 0x22a3 },
+ { "tadeva", 0x0924 },
+ { "tagujarati", 0x0aa4 },
+ { "tagurmukhi", 0x0a24 },
+ { "taharabic", 0x0637 },
+ { "tahfinalarabic", 0xfec2 },
+ { "tahinitialarabic", 0xfec3 },
+ { "tahiragana", 0x305f },
+ { "tahmedialarabic", 0xfec4 },
+ { "taisyouerasquare", 0x337d },
+ { "takatakana", 0x30bf },
+ { "takatakanahalfwidth", 0xff80 },
+ { "tatweelarabic", 0x0640 },
+ { "tav", 0x05ea },
+ { "tavdages", 0xfb4a },
+ { "tavdagesh", 0xfb4a },
+ { "tavdageshhebrew", 0xfb4a },
+ { "tavhebrew", 0x05ea },
+ { "tbopomofo", 0x310a },
+ { "tccurl", 0x02a8 },
+ { "tcedilla", 0x0163 },
+ { "tcheharabic", 0x0686 },
+ { "tchehfinalarabic", 0xfb7b },
+ { "tchehinitialarabic", 0xfb7c },
+ { "tchehmedialarabic", 0xfb7d },
+ { "tchehmeeminitialarabic", 0xfb7c },
+ { "tcircle", 0x24e3 },
+ { "tcircumflexbelow", 0x1e71 },
+ { "tdieresis", 0x1e97 },
+ { "tdotaccent", 0x1e6b },
+ { "tdotbelow", 0x1e6d },
+ { "tecyrillic", 0x0442 },
+ { "tedescendercyrillic", 0x04ad },
+ { "teharabic", 0x062a },
+ { "tehfinalarabic", 0xfe96 },
+ { "tehhahinitialarabic", 0xfca2 },
+ { "tehhahisolatedarabic", 0xfc0c },
+ { "tehinitialarabic", 0xfe97 },
+ { "tehiragana", 0x3066 },
+ { "tehjeeminitialarabic", 0xfca1 },
+ { "tehjeemisolatedarabic", 0xfc0b },
+ { "tehmarbutaarabic", 0x0629 },
+ { "tehmarbutafinalarabic", 0xfe94 },
+ { "tehmedialarabic", 0xfe98 },
+ { "tehmeeminitialarabic", 0xfca4 },
+ { "tehmeemisolatedarabic", 0xfc0e },
+ { "tehnoonfinalarabic", 0xfc73 },
+ { "tekatakana", 0x30c6 },
+ { "tekatakanahalfwidth", 0xff83 },
+ { "telephone", 0x2121 },
+ { "telephoneblack", 0x260e },
+ { "telishagedolahebrew", 0x05a0 },
+ { "telishaqetanahebrew", 0x05a9 },
+ { "tencircle", 0x2469 },
+ { "tenideographicparen", 0x3229 },
+ { "tenparen", 0x247d },
+ { "tenperiod", 0x2491 },
+ { "tenroman", 0x2179 },
+ { "tesh", 0x02a7 },
+ { "tet", 0x05d8 },
+ { "tetdagesh", 0xfb38 },
+ { "tetdageshhebrew", 0xfb38 },
+ { "tethebrew", 0x05d8 },
+ { "tetsecyrillic", 0x04b5 },
+ { "tevirhebrew", 0x059b },
+ { "tevirlefthebrew", 0x059b },
+ { "thabengali", 0x09a5 },
+ { "thadeva", 0x0925 },
+ { "thagujarati", 0x0aa5 },
+ { "thagurmukhi", 0x0a25 },
+ { "thalarabic", 0x0630 },
+ { "thalfinalarabic", 0xfeac },
+ { "thanthakhatlowleftthai", 0xf898 },
+ { "thanthakhatlowrightthai", 0xf897 },
+ { "thanthakhatthai", 0x0e4c },
+ { "thanthakhatupperleftthai", 0xf896 },
+ { "theharabic", 0x062b },
+ { "thehfinalarabic", 0xfe9a },
+ { "thehinitialarabic", 0xfe9b },
+ { "thehmedialarabic", 0xfe9c },
+ { "thereexists", 0x2203 },
+ { "thetasymbolgreek", 0x03d1 },
+ { "thieuthacirclekorean", 0x3279 },
+ { "thieuthaparenkorean", 0x3219 },
+ { "thieuthcirclekorean", 0x326b },
+ { "thieuthkorean", 0x314c },
+ { "thieuthparenkorean", 0x320b },
+ { "thirteencircle", 0x246c },
+ { "thirteenparen", 0x2480 },
+ { "thirteenperiod", 0x2494 },
+ { "thonangmonthothai", 0x0e11 },
+ { "thook", 0x01ad },
+ { "thophuthaothai", 0x0e12 },
+ { "thothahanthai", 0x0e17 },
+ { "thothanthai", 0x0e10 },
+ { "thothongthai", 0x0e18 },
+ { "thothungthai", 0x0e16 },
+ { "thousandcyrillic", 0x0482 },
+ { "thousandsseparatorarabic", 0x066c },
+ { "thousandsseparatorpersian", 0x066c },
+ { "threearabic", 0x0663 },
+ { "threebengali", 0x09e9 },
+ { "threecircle", 0x2462 },
+ { "threecircleinversesansserif", 0x278c },
+ { "threedeva", 0x0969 },
+ { "threegujarati", 0x0ae9 },
+ { "threegurmukhi", 0x0a69 },
+ { "threehackarabic", 0x0663 },
+ { "threehangzhou", 0x3023 },
+ { "threeideographicparen", 0x3222 },
+ { "threeinferior", 0x2083 },
+ { "threemonospace", 0xff13 },
+ { "threenumeratorbengali", 0x09f6 },
+ { "threeoldstyle", 0xf733 },
+ { "threeparen", 0x2476 },
+ { "threeperiod", 0x248a },
+ { "threepersian", 0x06f3 },
+ { "threequartersemdash", 0xf6de },
+ { "threeroman", 0x2172 },
+ { "threesuperior", 0x00b3 },
+ { "threethai", 0x0e53 },
+ { "thzsquare", 0x3394 },
+ { "tihiragana", 0x3061 },
+ { "tikatakana", 0x30c1 },
+ { "tikatakanahalfwidth", 0xff81 },
+ { "tikeutacirclekorean", 0x3270 },
+ { "tikeutaparenkorean", 0x3210 },
+ { "tikeutcirclekorean", 0x3262 },
+ { "tikeutkorean", 0x3137 },
+ { "tikeutparenkorean", 0x3202 },
+ { "tildebelowcmb", 0x0330 },
+ { "tildecmb", 0x0303 },
+ { "tildedoublecmb", 0x0360 },
+ { "tildeoperator", 0x223c },
+ { "tildeoverlaycmb", 0x0334 },
+ { "tildeverticalcmb", 0x033e },
+ { "timescircle", 0x2297 },
+ { "tipehahebrew", 0x0596 },
+ { "tipehalefthebrew", 0x0596 },
+ { "tippigurmukhi", 0x0a70 },
+ { "titlocyrilliccmb", 0x0483 },
+ { "tiwnarmenian", 0x057f },
+ { "tlinebelow", 0x1e6f },
+ { "tmonospace", 0xff54 },
+ { "toarmenian", 0x0569 },
+ { "tohiragana", 0x3068 },
+ { "tokatakana", 0x30c8 },
+ { "tokatakanahalfwidth", 0xff84 },
+ { "tonebarextrahighmod", 0x02e5 },
+ { "tonebarextralowmod", 0x02e9 },
+ { "tonebarhighmod", 0x02e6 },
+ { "tonebarlowmod", 0x02e8 },
+ { "tonebarmidmod", 0x02e7 },
+ { "tonefive", 0x01bd },
+ { "tonesix", 0x0185 },
+ { "tonetwo", 0x01a8 },
+ { "tonsquare", 0x3327 },
+ { "topatakthai", 0x0e0f },
+ { "tortoiseshellbracketleft", 0x3014 },
+ { "tortoiseshellbracketleftsmall", 0xfe5d },
+ { "tortoiseshellbracketleftvertical", 0xfe39 },
+ { "tortoiseshellbracketright", 0x3015 },
+ { "tortoiseshellbracketrightsmall", 0xfe5e },
+ { "tortoiseshellbracketrightvertical", 0xfe3a },
+ { "totaothai", 0x0e15 },
+ { "tpalatalhook", 0x01ab },
+ { "tparen", 0x24af },
+ { "trademarksans", 0xf8ea },
+ { "trademarkserif", 0xf6db },
+ { "tretroflexhook", 0x0288 },
+ { "ts", 0x02a6 },
+ { "tsadi", 0x05e6 },
+ { "tsadidagesh", 0xfb46 },
+ { "tsadidageshhebrew", 0xfb46 },
+ { "tsadihebrew", 0x05e6 },
+ { "tsecyrillic", 0x0446 },
+ { "tsere", 0x05b5 },
+ { "tsere12", 0x05b5 },
+ { "tsere1e", 0x05b5 },
+ { "tsere2b", 0x05b5 },
+ { "tserehebrew", 0x05b5 },
+ { "tserenarrowhebrew", 0x05b5 },
+ { "tserequarterhebrew", 0x05b5 },
+ { "tserewidehebrew", 0x05b5 },
+ { "tshecyrillic", 0x045b },
+ { "tsuperior", 0xf6f3 },
+ { "ttabengali", 0x099f },
+ { "ttadeva", 0x091f },
+ { "ttagujarati", 0x0a9f },
+ { "ttagurmukhi", 0x0a1f },
+ { "tteharabic", 0x0679 },
+ { "ttehfinalarabic", 0xfb67 },
+ { "ttehinitialarabic", 0xfb68 },
+ { "ttehmedialarabic", 0xfb69 },
+ { "tthabengali", 0x09a0 },
+ { "tthadeva", 0x0920 },
+ { "tthagujarati", 0x0aa0 },
+ { "tthagurmukhi", 0x0a20 },
+ { "tturned", 0x0287 },
+ { "tuhiragana", 0x3064 },
+ { "tukatakana", 0x30c4 },
+ { "tukatakanahalfwidth", 0xff82 },
+ { "tusmallhiragana", 0x3063 },
+ { "tusmallkatakana", 0x30c3 },
+ { "tusmallkatakanahalfwidth", 0xff6f },
+ { "twelvecircle", 0x246b },
+ { "twelveparen", 0x247f },
+ { "twelveperiod", 0x2493 },
+ { "twelveroman", 0x217b },
+ { "twentycircle", 0x2473 },
+ { "twentyhangzhou", 0x5344 },
+ { "twentyparen", 0x2487 },
+ { "twentyperiod", 0x249b },
+ { "twoarabic", 0x0662 },
+ { "twobengali", 0x09e8 },
+ { "twocircle", 0x2461 },
+ { "twocircleinversesansserif", 0x278b },
+ { "twodeva", 0x0968 },
+ { "twodotleader", 0x2025 },
+ { "twodotleadervertical", 0xfe30 },
+ { "twogujarati", 0x0ae8 },
+ { "twogurmukhi", 0x0a68 },
+ { "twohackarabic", 0x0662 },
+ { "twohangzhou", 0x3022 },
+ { "twoideographicparen", 0x3221 },
+ { "twoinferior", 0x2082 },
+ { "twomonospace", 0xff12 },
+ { "twonumeratorbengali", 0x09f5 },
+ { "twooldstyle", 0xf732 },
+ { "twoparen", 0x2475 },
+ { "twoperiod", 0x2489 },
+ { "twopersian", 0x06f2 },
+ { "tworoman", 0x2171 },
+ { "twostroke", 0x01bb },
+ { "twosuperior", 0x00b2 },
+ { "twothai", 0x0e52 },
+ { "ubar", 0x0289 },
+ { "ubengali", 0x0989 },
+ { "ubopomofo", 0x3128 },
+ { "ucaron", 0x01d4 },
+ { "ucircle", 0x24e4 },
+ { "ucircumflexbelow", 0x1e77 },
+ { "ucyrillic", 0x0443 },
+ { "udattadeva", 0x0951 },
+ { "udblacute", 0x0171 },
+ { "udblgrave", 0x0215 },
+ { "udeva", 0x0909 },
+ { "udieresisacute", 0x01d8 },
+ { "udieresisbelow", 0x1e73 },
+ { "udieresiscaron", 0x01da },
+ { "udieresiscyrillic", 0x04f1 },
+ { "udieresisgrave", 0x01dc },
+ { "udieresismacron", 0x01d6 },
+ { "udotbelow", 0x1ee5 },
+ { "ugujarati", 0x0a89 },
+ { "ugurmukhi", 0x0a09 },
+ { "uhiragana", 0x3046 },
+ { "uhookabove", 0x1ee7 },
+ { "uhornacute", 0x1ee9 },
+ { "uhorndotbelow", 0x1ef1 },
+ { "uhorngrave", 0x1eeb },
+ { "uhornhookabove", 0x1eed },
+ { "uhorntilde", 0x1eef },
+ { "uhungarumlautcyrillic", 0x04f3 },
+ { "uinvertedbreve", 0x0217 },
+ { "ukatakana", 0x30a6 },
+ { "ukatakanahalfwidth", 0xff73 },
+ { "ukcyrillic", 0x0479 },
+ { "ukorean", 0x315c },
+ { "umacroncyrillic", 0x04ef },
+ { "umacrondieresis", 0x1e7b },
+ { "umatragurmukhi", 0x0a41 },
+ { "umonospace", 0xff55 },
+ { "underscoremonospace", 0xff3f },
+ { "underscorevertical", 0xfe33 },
+ { "underscorewavy", 0xfe4f },
+ { "uparen", 0x24b0 },
+ { "upperdothebrew", 0x05c4 },
+ { "upsilonlatin", 0x028a },
+ { "uptackbelowcmb", 0x031d },
+ { "uptackmod", 0x02d4 },
+ { "uragurmukhi", 0x0a73 },
+ { "ushortcyrillic", 0x045e },
+ { "usmallhiragana", 0x3045 },
+ { "usmallkatakana", 0x30a5 },
+ { "usmallkatakanahalfwidth", 0xff69 },
+ { "ustraightcyrillic", 0x04af },
+ { "ustraightstrokecyrillic", 0x04b1 },
+ { "utildeacute", 0x1e79 },
+ { "utildebelow", 0x1e75 },
+ { "uubengali", 0x098a },
+ { "uudeva", 0x090a },
+ { "uugujarati", 0x0a8a },
+ { "uugurmukhi", 0x0a0a },
+ { "uumatragurmukhi", 0x0a42 },
+ { "uuvowelsignbengali", 0x09c2 },
+ { "uuvowelsigndeva", 0x0942 },
+ { "uuvowelsigngujarati", 0x0ac2 },
+ { "uvowelsignbengali", 0x09c1 },
+ { "uvowelsigndeva", 0x0941 },
+ { "uvowelsigngujarati", 0x0ac1 },
+ { "vadeva", 0x0935 },
+ { "vagujarati", 0x0ab5 },
+ { "vagurmukhi", 0x0a35 },
+ { "vakatakana", 0x30f7 },
+ { "vav", 0x05d5 },
+ { "vavdagesh", 0xfb35 },
+ { "vavdagesh65", 0xfb35 },
+ { "vavdageshhebrew", 0xfb35 },
+ { "vavhebrew", 0x05d5 },
+ { "vavholam", 0xfb4b },
+ { "vavholamhebrew", 0xfb4b },
+ { "vavvavhebrew", 0x05f0 },
+ { "vavyodhebrew", 0x05f1 },
+ { "vcircle", 0x24e5 },
+ { "vdotbelow", 0x1e7f },
+ { "vecyrillic", 0x0432 },
+ { "veharabic", 0x06a4 },
+ { "vehfinalarabic", 0xfb6b },
+ { "vehinitialarabic", 0xfb6c },
+ { "vehmedialarabic", 0xfb6d },
+ { "vekatakana", 0x30f9 },
+ { "venus", 0x2640 },
+ { "verticalbar", 0x007c },
+ { "verticallineabovecmb", 0x030d },
+ { "verticallinebelowcmb", 0x0329 },
+ { "verticallinelowmod", 0x02cc },
+ { "verticallinemod", 0x02c8 },
+ { "vewarmenian", 0x057e },
+ { "vhook", 0x028b },
+ { "vikatakana", 0x30f8 },
+ { "viramabengali", 0x09cd },
+ { "viramadeva", 0x094d },
+ { "viramagujarati", 0x0acd },
+ { "visargabengali", 0x0983 },
+ { "visargadeva", 0x0903 },
+ { "visargagujarati", 0x0a83 },
+ { "vmonospace", 0xff56 },
+ { "voarmenian", 0x0578 },
+ { "voicediterationhiragana", 0x309e },
+ { "voicediterationkatakana", 0x30fe },
+ { "voicedmarkkana", 0x309b },
+ { "voicedmarkkanahalfwidth", 0xff9e },
+ { "vokatakana", 0x30fa },
+ { "vparen", 0x24b1 },
+ { "vtilde", 0x1e7d },
+ { "vturned", 0x028c },
+ { "vuhiragana", 0x3094 },
+ { "vukatakana", 0x30f4 },
+ { "waekorean", 0x3159 },
+ { "wahiragana", 0x308f },
+ { "wakatakana", 0x30ef },
+ { "wakatakanahalfwidth", 0xff9c },
+ { "wakorean", 0x3158 },
+ { "wasmallhiragana", 0x308e },
+ { "wasmallkatakana", 0x30ee },
+ { "wattosquare", 0x3357 },
+ { "wavedash", 0x301c },
+ { "wavyunderscorevertical", 0xfe34 },
+ { "wawarabic", 0x0648 },
+ { "wawfinalarabic", 0xfeee },
+ { "wawhamzaabovearabic", 0x0624 },
+ { "wawhamzaabovefinalarabic", 0xfe86 },
+ { "wbsquare", 0x33dd },
+ { "wcircle", 0x24e6 },
+ { "wdotaccent", 0x1e87 },
+ { "wdotbelow", 0x1e89 },
+ { "wehiragana", 0x3091 },
+ { "wekatakana", 0x30f1 },
+ { "wekorean", 0x315e },
+ { "weokorean", 0x315d },
+ { "whitebullet", 0x25e6 },
+ { "whitecircle", 0x25cb },
+ { "whitecircleinverse", 0x25d9 },
+ { "whitecornerbracketleft", 0x300e },
+ { "whitecornerbracketleftvertical", 0xfe43 },
+ { "whitecornerbracketright", 0x300f },
+ { "whitecornerbracketrightvertical", 0xfe44 },
+ { "whitediamond", 0x25c7 },
+ { "whitediamondcontainingblacksmalldiamond", 0x25c8 },
+ { "whitedownpointingsmalltriangle", 0x25bf },
+ { "whitedownpointingtriangle", 0x25bd },
+ { "whiteleftpointingsmalltriangle", 0x25c3 },
+ { "whiteleftpointingtriangle", 0x25c1 },
+ { "whitelenticularbracketleft", 0x3016 },
+ { "whitelenticularbracketright", 0x3017 },
+ { "whiterightpointingsmalltriangle", 0x25b9 },
+ { "whiterightpointingtriangle", 0x25b7 },
+ { "whitesmallsquare", 0x25ab },
+ { "whitesmilingface", 0x263a },
+ { "whitesquare", 0x25a1 },
+ { "whitestar", 0x2606 },
+ { "whitetelephone", 0x260f },
+ { "whitetortoiseshellbracketleft", 0x3018 },
+ { "whitetortoiseshellbracketright", 0x3019 },
+ { "whiteuppointingsmalltriangle", 0x25b5 },
+ { "whiteuppointingtriangle", 0x25b3 },
+ { "wihiragana", 0x3090 },
+ { "wikatakana", 0x30f0 },
+ { "wikorean", 0x315f },
+ { "wmonospace", 0xff57 },
+ { "wohiragana", 0x3092 },
+ { "wokatakana", 0x30f2 },
+ { "wokatakanahalfwidth", 0xff66 },
+ { "won", 0x20a9 },
+ { "wonmonospace", 0xffe6 },
+ { "wowaenthai", 0x0e27 },
+ { "wparen", 0x24b2 },
+ { "wring", 0x1e98 },
+ { "wsuperior", 0x02b7 },
+ { "wturned", 0x028d },
+ { "wynn", 0x01bf },
+ { "xabovecmb", 0x033d },
+ { "xbopomofo", 0x3112 },
+ { "xcircle", 0x24e7 },
+ { "xdieresis", 0x1e8d },
+ { "xdotaccent", 0x1e8b },
+ { "xeharmenian", 0x056d },
+ { "xmonospace", 0xff58 },
+ { "xparen", 0x24b3 },
+ { "xsuperior", 0x02e3 },
+ { "yaadosquare", 0x334e },
+ { "yabengali", 0x09af },
+ { "yadeva", 0x092f },
+ { "yaekorean", 0x3152 },
+ { "yagujarati", 0x0aaf },
+ { "yagurmukhi", 0x0a2f },
+ { "yahiragana", 0x3084 },
+ { "yakatakana", 0x30e4 },
+ { "yakatakanahalfwidth", 0xff94 },
+ { "yakorean", 0x3151 },
+ { "yamakkanthai", 0x0e4e },
+ { "yasmallhiragana", 0x3083 },
+ { "yasmallkatakana", 0x30e3 },
+ { "yasmallkatakanahalfwidth", 0xff6c },
+ { "yatcyrillic", 0x0463 },
+ { "ycircle", 0x24e8 },
+ { "ydotaccent", 0x1e8f },
+ { "ydotbelow", 0x1ef5 },
+ { "yeharabic", 0x064a },
+ { "yehbarreearabic", 0x06d2 },
+ { "yehbarreefinalarabic", 0xfbaf },
+ { "yehfinalarabic", 0xfef2 },
+ { "yehhamzaabovearabic", 0x0626 },
+ { "yehhamzaabovefinalarabic", 0xfe8a },
+ { "yehhamzaaboveinitialarabic", 0xfe8b },
+ { "yehhamzaabovemedialarabic", 0xfe8c },
+ { "yehinitialarabic", 0xfef3 },
+ { "yehmedialarabic", 0xfef4 },
+ { "yehmeeminitialarabic", 0xfcdd },
+ { "yehmeemisolatedarabic", 0xfc58 },
+ { "yehnoonfinalarabic", 0xfc94 },
+ { "yehthreedotsbelowarabic", 0x06d1 },
+ { "yekorean", 0x3156 },
+ { "yenmonospace", 0xffe5 },
+ { "yeokorean", 0x3155 },
+ { "yeorinhieuhkorean", 0x3186 },
+ { "yerahbenyomohebrew", 0x05aa },
+ { "yerahbenyomolefthebrew", 0x05aa },
+ { "yericyrillic", 0x044b },
+ { "yerudieresiscyrillic", 0x04f9 },
+ { "yesieungkorean", 0x3181 },
+ { "yesieungpansioskorean", 0x3183 },
+ { "yesieungsioskorean", 0x3182 },
+ { "yetivhebrew", 0x059a },
+ { "yhook", 0x01b4 },
+ { "yhookabove", 0x1ef7 },
+ { "yiarmenian", 0x0575 },
+ { "yicyrillic", 0x0457 },
+ { "yikorean", 0x3162 },
+ { "yinyang", 0x262f },
+ { "yiwnarmenian", 0x0582 },
+ { "ymonospace", 0xff59 },
+ { "yod", 0x05d9 },
+ { "yoddagesh", 0xfb39 },
+ { "yoddageshhebrew", 0xfb39 },
+ { "yodhebrew", 0x05d9 },
+ { "yodyodhebrew", 0x05f2 },
+ { "yodyodpatahhebrew", 0xfb1f },
+ { "yohiragana", 0x3088 },
+ { "yoikorean", 0x3189 },
+ { "yokatakana", 0x30e8 },
+ { "yokatakanahalfwidth", 0xff96 },
+ { "yokorean", 0x315b },
+ { "yosmallhiragana", 0x3087 },
+ { "yosmallkatakana", 0x30e7 },
+ { "yosmallkatakanahalfwidth", 0xff6e },
+ { "yotgreek", 0x03f3 },
+ { "yoyaekorean", 0x3188 },
+ { "yoyakorean", 0x3187 },
+ { "yoyakthai", 0x0e22 },
+ { "yoyingthai", 0x0e0d },
+ { "yparen", 0x24b4 },
+ { "ypogegrammeni", 0x037a },
+ { "ypogegrammenigreekcmb", 0x0345 },
+ { "yr", 0x01a6 },
+ { "yring", 0x1e99 },
+ { "ysuperior", 0x02b8 },
+ { "ytilde", 0x1ef9 },
+ { "yturned", 0x028e },
+ { "yuhiragana", 0x3086 },
+ { "yuikorean", 0x318c },
+ { "yukatakana", 0x30e6 },
+ { "yukatakanahalfwidth", 0xff95 },
+ { "yukorean", 0x3160 },
+ { "yusbigcyrillic", 0x046b },
+ { "yusbigiotifiedcyrillic", 0x046d },
+ { "yuslittlecyrillic", 0x0467 },
+ { "yuslittleiotifiedcyrillic", 0x0469 },
+ { "yusmallhiragana", 0x3085 },
+ { "yusmallkatakana", 0x30e5 },
+ { "yusmallkatakanahalfwidth", 0xff6d },
+ { "yuyekorean", 0x318b },
+ { "yuyeokorean", 0x318a },
+ { "yyabengali", 0x09df },
+ { "yyadeva", 0x095f },
+ { "zaarmenian", 0x0566 },
+ { "zadeva", 0x095b },
+ { "zagurmukhi", 0x0a5b },
+ { "zaharabic", 0x0638 },
+ { "zahfinalarabic", 0xfec6 },
+ { "zahinitialarabic", 0xfec7 },
+ { "zahiragana", 0x3056 },
+ { "zahmedialarabic", 0xfec8 },
+ { "zainarabic", 0x0632 },
+ { "zainfinalarabic", 0xfeb0 },
+ { "zakatakana", 0x30b6 },
+ { "zaqefgadolhebrew", 0x0595 },
+ { "zaqefqatanhebrew", 0x0594 },
+ { "zarqahebrew", 0x0598 },
+ { "zayin", 0x05d6 },
+ { "zayindagesh", 0xfb36 },
+ { "zayindageshhebrew", 0xfb36 },
+ { "zayinhebrew", 0x05d6 },
+ { "zbopomofo", 0x3117 },
+ { "zcircle", 0x24e9 },
+ { "zcircumflex", 0x1e91 },
+ { "zcurl", 0x0291 },
+ { "zdot", 0x017c },
+ { "zdotbelow", 0x1e93 },
+ { "zecyrillic", 0x0437 },
+ { "zedescendercyrillic", 0x0499 },
+ { "zedieresiscyrillic", 0x04df },
+ { "zehiragana", 0x305c },
+ { "zekatakana", 0x30bc },
+ { "zeroarabic", 0x0660 },
+ { "zerobengali", 0x09e6 },
+ { "zerodeva", 0x0966 },
+ { "zerogujarati", 0x0ae6 },
+ { "zerogurmukhi", 0x0a66 },
+ { "zerohackarabic", 0x0660 },
+ { "zeroinferior", 0x2080 },
+ { "zeromonospace", 0xff10 },
+ { "zerooldstyle", 0xf730 },
+ { "zeropersian", 0x06f0 },
+ { "zerosuperior", 0x2070 },
+ { "zerothai", 0x0e50 },
+ { "zerowidthjoiner", 0xfeff },
+ { "zerowidthnonjoiner", 0x200c },
+ { "zerowidthspace", 0x200b },
+ { "zhbopomofo", 0x3113 },
+ { "zhearmenian", 0x056a },
+ { "zhebrevecyrillic", 0x04c2 },
+ { "zhecyrillic", 0x0436 },
+ { "zhedescendercyrillic", 0x0497 },
+ { "zhedieresiscyrillic", 0x04dd },
+ { "zihiragana", 0x3058 },
+ { "zikatakana", 0x30b8 },
+ { "zinorhebrew", 0x05ae },
+ { "zlinebelow", 0x1e95 },
+ { "zmonospace", 0xff5a },
+ { "zohiragana", 0x305e },
+ { "zokatakana", 0x30be },
+ { "zparen", 0x24b5 },
+ { "zretroflexhook", 0x0290 },
+ { "zstroke", 0x01b6 },
+ { "zuhiragana", 0x305a },
+ { "zukatakana", 0x30ba },
+ { "dotaccent.cap", 0xefed },
+ { "breve.cap", 0xefee },
+ { "ogonek.cap", 0xeff1 },
+ { "cedilla.cap", 0xeff2 },
+ { "ring.cap", 0xeff3 },
+ { "tilde.cap", 0xeff5 },
+ { "circumflex.cap", 0xeff7 },
+ { "a1", 0x2701 },
+ { "a2", 0x2702 },
+ { "a202", 0x2703 },
+ { "a3", 0x2704 },
+ { "a4", 0x260e },
+ { "a5", 0x2706 },
+ { "a119", 0x2707 },
+ { "a118", 0x2708 },
+ { "a117", 0x2709 },
+ { "a11", 0x261b },
+ { "a12", 0x261e },
+ { "a13", 0x270c },
+ { "a14", 0x270d },
+ { "a15", 0x270e },
+ { "a16", 0x270f },
+ { "a105", 0x2710 },
+ { "a17", 0x2711 },
+ { "a18", 0x2712 },
+ { "a19", 0x2713 },
+ { "a20", 0x2714 },
+ { "a21", 0x2715 },
+ { "a22", 0x2716 },
+ { "a23", 0x2717 },
+ { "a24", 0x2718 },
+ { "a25", 0x2719 },
+ { "a26", 0x271a },
+ { "a27", 0x271b },
+ { "a28", 0x271c },
+ { "a6", 0x271d },
+ { "a7", 0x271e },
+ { "a8", 0x271f },
+ { "a9", 0x2720 },
+ { "a10", 0x2721 },
+ { "a29", 0x2722 },
+ { "a30", 0x2723 },
+ { "a31", 0x2724 },
+ { "a32", 0x2725 },
+ { "a33", 0x2726 },
+ { "a34", 0x2727 },
+ { "a35", 0x2605 },
+ { "a36", 0x2729 },
+ { "a37", 0x272a },
+ { "a38", 0x272b },
+ { "a39", 0x272c },
+ { "a40", 0x272d },
+ { "a41", 0x272e },
+ { "a42", 0x272f },
+ { "a43", 0x2730 },
+ { "a44", 0x2731 },
+ { "a45", 0x2732 },
+ { "a46", 0x2733 },
+ { "a47", 0x2734 },
+ { "a48", 0x2735 },
+ { "a49", 0x2736 },
+ { "a50", 0x2737 },
+ { "a51", 0x2738 },
+ { "a52", 0x2739 },
+ { "a53", 0x273a },
+ { "a54", 0x273b },
+ { "a55", 0x273c },
+ { "a56", 0x273d },
+ { "a57", 0x273e },
+ { "a58", 0x273f },
+ { "a59", 0x2740 },
+ { "a60", 0x2741 },
+ { "a61", 0x2742 },
+ { "a62", 0x2743 },
+ { "a63", 0x2744 },
+ { "a64", 0x2745 },
+ { "a65", 0x2746 },
+ { "a66", 0x2747 },
+ { "a67", 0x2748 },
+ { "a68", 0x2749 },
+ { "a69", 0x274a },
+ { "a70", 0x274b },
+ { "a71", 0x25cf },
+ { "a72", 0x274d },
+ { "a73", 0x25a0 },
+ { "a74", 0x274f },
+ { "a203", 0x2750 },
+ { "a75", 0x2751 },
+ { "a204", 0x2752 },
+ { "a76", 0x25b2 },
+ { "a77", 0x25bc },
+ { "a78", 0x25c6 },
+ { "a79", 0x2756 },
+ { "a81", 0x25d7 },
+ { "a82", 0x2758 },
+ { "a83", 0x2759 },
+ { "a84", 0x275a },
+ { "a97", 0x275b },
+ { "a98", 0x275c },
+ { "a99", 0x275d },
+ { "a100", 0x275e },
+ { "a89", 0x2768 },
+ { "a90", 0x2769 },
+ { "a93", 0x276a },
+ { "a94", 0x276b },
+ { "a91", 0x276c },
+ { "a92", 0x276d },
+ { "a205", 0x276e },
+ { "a85", 0x276f },
+ { "a206", 0x2770 },
+ { "a86", 0x2771 },
+ { "a87", 0x2772 },
+ { "a88", 0x2773 },
+ { "a95", 0x2774 },
+ { "a96", 0x2775 },
+ { "a101", 0x2761 },
+ { "a102", 0x2762 },
+ { "a103", 0x2763 },
+ { "a104", 0x2764 },
+ { "a106", 0x2765 },
+ { "a107", 0x2766 },
+ { "a108", 0x2767 },
+ { "a112", 0x2663 },
+ { "a111", 0x2666 },
+ { "a110", 0x2665 },
+ { "a109", 0x2660 },
+ { "a120", 0x2460 },
+ { "a121", 0x2461 },
+ { "a122", 0x2462 },
+ { "a123", 0x2463 },
+ { "a124", 0x2464 },
+ { "a125", 0x2465 },
+ { "a126", 0x2466 },
+ { "a127", 0x2467 },
+ { "a128", 0x2468 },
+ { "a129", 0x2469 },
+ { "a130", 0x2776 },
+ { "a131", 0x2777 },
+ { "a132", 0x2778 },
+ { "a133", 0x2779 },
+ { "a134", 0x277a },
+ { "a135", 0x277b },
+ { "a136", 0x277c },
+ { "a137", 0x277d },
+ { "a138", 0x277e },
+ { "a139", 0x277f },
+ { "a140", 0x2780 },
+ { "a141", 0x2781 },
+ { "a142", 0x2782 },
+ { "a143", 0x2783 },
+ { "a144", 0x2784 },
+ { "a145", 0x2785 },
+ { "a146", 0x2786 },
+ { "a147", 0x2787 },
+ { "a148", 0x2788 },
+ { "a149", 0x2789 },
+ { "a150", 0x278a },
+ { "a151", 0x278b },
+ { "a152", 0x278c },
+ { "a153", 0x278d },
+ { "a154", 0x278e },
+ { "a155", 0x278f },
+ { "a156", 0x2790 },
+ { "a157", 0x2791 },
+ { "a158", 0x2792 },
+ { "a159", 0x2793 },
+ { "a160", 0x2794 },
+ { "a161", 0x2192 },
+ { "a163", 0x2194 },
+ { "a164", 0x2195 },
+ { "a196", 0x2798 },
+ { "a165", 0x2799 },
+ { "a192", 0x279a },
+ { "a166", 0x279b },
+ { "a167", 0x279c },
+ { "a168", 0x279d },
+ { "a169", 0x279e },
+ { "a170", 0x279f },
+ { "a171", 0x27a0 },
+ { "a172", 0x27a1 },
+ { "a173", 0x27a2 },
+ { "a162", 0x27a3 },
+ { "a174", 0x27a4 },
+ { "a175", 0x27a5 },
+ { "a176", 0x27a6 },
+ { "a177", 0x27a7 },
+ { "a178", 0x27a8 },
+ { "a179", 0x27a9 },
+ { "a193", 0x27aa },
+ { "a180", 0x27ab },
+ { "a199", 0x27ac },
+ { "a181", 0x27ad },
+ { "a200", 0x27ae },
+ { "a182", 0x27af },
+ { "a201", 0x27b1 },
+ { "a183", 0x27b2 },
+ { "a184", 0x27b3 },
+ { "a197", 0x27b4 },
+ { "a185", 0x27b5 },
+ { "a194", 0x27b6 },
+ { "a198", 0x27b7 },
+ { "a186", 0x27b8 },
+ { "a195", 0x27b9 },
+ { "a187", 0x27ba },
+ { "a188", 0x27bb },
+ { "a189", 0x27bc },
+ { "a190", 0x27bd },
+ { "a191", 0x27be },
+ { "register.sans", 0xf8e8 },
+ { "register.serif", 0xf6da },
+ { "one.superior", 0x00b9 },
+ { "two.superior", 0x00b2 },
+ { "three.superior", 0x00b3 },
+ { "parenleft.superior", 0x207d },
+ { "parenright.superior", 0x207e },
+ { "n.superior", 0x207f },
+ { "parenleft.inferior", 0x208d },
+ { "parenright.inferior", 0x208e },
+ { "zero.superior", 0x2070 },
+ { "four.superior", 0x2074 },
+ { "five.superior", 0x2075 },
+ { "six.superior", 0x2076 },
+ { "seven.superior", 0x2077 },
+ { "eight.superior", 0x2078 },
+ { "nine.superior", 0x2079 },
+ { "zero.inferior", 0x2080 },
+ { "one.inferior", 0x2081 },
+ { "two.inferior", 0x2082 },
+ { "three.inferior", 0x2083 },
+ { "four.inferior", 0x2084 },
+ { "five.inferior", 0x2085 },
+ { "six.inferior", 0x2086 },
+ { "seven.inferior", 0x2087 },
+ { "eight.inferior", 0x2088 },
+ { "nine.inferior", 0x2089 },
+ { "mu.greek", 0x03bc },
+ { "Delta.greek", 0x0394 },
+ { "Omega.greek", 0x03a9 },
+ { "sigma.end", 0x03c2 },
+ { "beta.alt", 0x03d0 },
+ { "kappa.alt", 0x03f0 },
+ { "theta.alt", 0x03d1 },
+ { "Upsilon.alt", 0x03d2 },
+ { "phi.alt", 0x03d5 },
+ { "pi.alt", 0x03d6 },
+ { "A.cyr", 0x0410 },
+ { "Ghe.up", 0x0490 },
+ { "I.cyr", 0x0418 },
+ { "I.short", 0x0419 },
+ { "O.cyr", 0x041e },
+ { "U.cyr", 0x0423 },
+ { "E.cyr", 0x042d },
+ { "Ie.ukran", 0x0404 },
+ { "I.ukran", 0x0406 },
+ { "U.short", 0x040e },
+ { "a.cyr", 0x0430 },
+ { "ghe.up", 0x0491 },
+ { "i.cyr", 0x0438 },
+ { "i.short", 0x0439 },
+ { "o.cyr", 0x043e },
+ { "u.cyr", 0x0443 },
+ { "e.cyr", 0x044d },
+ { "ie.ukran", 0x0454 },
+ { "i.ukran", 0x0456 },
+ { "u.short", 0x045e },
+ { "ghe.ital", 0xf6c4 },
+ { "afii10068.ital", 0xf6c4 },
+ { "afii10066.ital", 0xf6c5 },
+ { "be.alt", 0xf6c5 },
+ { "afii10069.ital", 0xf6c6 },
+ { "de.ital", 0xf6c6 },
+ { "afii10081.ital", 0xf6c7 },
+ { "pe.ital", 0xf6c7 },
+ { "afii10084.ital", 0xf6c8 },
+ { "te.ital", 0xf6c8 },
+ { "Omega.math", 0x2126 },
+ { "Delta.math", 0x2206 },
+ { "afii57689_afii57804", 0xfb2a },
+ { "afii57689_afii57803", 0xfb2b },
+ { "afii57669_afii57806", 0xfb4b },
+ { "afii57718_afii57798", 0xfb1f },
+ { "afii57669_afii57807", 0xfb35 },
+ { ".null", 0x0000 },
+ { "dialytika_perispomeni", 0x1fc1 },
+ { "psili_varia", 0x1fcd },
+ { "psili_oxia", 0x1fce },
+ { "psili_perispomeni", 0x1fcf },
+ { "dasia_varia", 0x1fdd },
+ { "dasia_oxia", 0x1fde },
+ { "dasia_perispomeni", 0x1fdf },
+ { "dialytika_varia", 0x1fed },
+ { "dialytika_oxia", 0x1fee },
+ { "Alphaacute", 0x1fbb },
+ { "Alphaasper", 0x1f09 },
+ { "Alphaasperacute", 0x1f0d },
+ { "Alphaaspergrave", 0x1f0b },
+ { "Alphaaspertilde", 0x1f0f },
+ { "Alphabreve", 0x1fb8 },
+ { "Alphagrave", 0x1fba },
+ { "Alphaiotasub", 0x1fbc },
+ { "Alphaiotasubasper", 0x1f89 },
+ { "Alphaiotasubasperacute", 0x1f8d },
+ { "Alphaiotasubaspergrave", 0x1f8b },
+ { "Alphaiotasubaspertilde", 0x1f8f },
+ { "Alphaiotasublenis", 0x1f88 },
+ { "Alphaiotasublenisacute", 0x1f8c },
+ { "Alphaiotasublenisgrave", 0x1f8a },
+ { "Alphaiotasublenistilde", 0x1f8e },
+ { "Alphalenis", 0x1f08 },
+ { "Alphalenisacute", 0x1f0c },
+ { "Alphalenisgrave", 0x1f0a },
+ { "Alphalenistilde", 0x1f0e },
+ { "Alphamacron", 0x1fb9 },
+ { "Epsilonacute", 0x1fc9 },
+ { "Epsilonasper", 0x1f19 },
+ { "Epsilonasperacute", 0x1f1d },
+ { "Epsilonaspergrave", 0x1f1b },
+ { "Epsilongrave", 0x1fc8 },
+ { "Epsilonlenis", 0x1f18 },
+ { "Epsilonlenisacute", 0x1f1c },
+ { "Epsilonlenisgrave", 0x1f1a },
+ { "Etaacute", 0x1fcb },
+ { "Etaasper", 0x1f29 },
+ { "Etaasperacute", 0x1f2d },
+ { "Etaaspergrave", 0x1f2b },
+ { "Etaaspertilde", 0x1f2f },
+ { "Etagrave", 0x1fca },
+ { "Etaiotasub", 0x1fcc },
+ { "Etaiotasubasper", 0x1f99 },
+ { "Etaiotasubasperacute", 0x1f9d },
+ { "Etaiotasubaspergrave", 0x1f9b },
+ { "Etaiotasubaspertilde", 0x1f9f },
+ { "Etaiotasublenis", 0x1f98 },
+ { "Etaiotasublenisacute", 0x1f9c },
+ { "Etaiotasublenisgrave", 0x1f9a },
+ { "Etaiotasublenistilde", 0x1f9e },
+ { "Etalenis", 0x1f28 },
+ { "Etalenisacute", 0x1f2c },
+ { "Etalenisgrave", 0x1f2a },
+ { "Etalenistilde", 0x1f2e },
+ { "Iotaacute", 0x1fdb },
+ { "Iotaasper", 0x1f39 },
+ { "Iotaasperacute", 0x1f3d },
+ { "Iotaaspergrave", 0x1f3b },
+ { "Iotaaspertilde", 0x1f3f },
+ { "Iotabreve", 0x1fd8 },
+ { "Iotagrave", 0x1fda },
+ { "Iotalenis", 0x1f38 },
+ { "Iotalenisacute", 0x1f3c },
+ { "Iotalenisgrave", 0x1f3a },
+ { "Iotalenistilde", 0x1f3e },
+ { "Iotamacron", 0x1fd9 },
+ { "Omegaacute", 0x1ffb },
+ { "Omegaasper", 0x1f69 },
+ { "Omegaasperacute", 0x1f6d },
+ { "Omegaaspergrave", 0x1f6b },
+ { "Omegaaspertilde", 0x1f6f },
+ { "Omegagrave", 0x1ffa },
+ { "Omegaiotasub", 0x1ffc },
+ { "Omegaiotasubasper", 0x1fa9 },
+ { "Omegaiotasubasperacute", 0x1fad },
+ { "Omegaiotasubaspergrave", 0x1fab },
+ { "Omegaiotasubaspertilde", 0x1faf },
+ { "Omegaiotasublenis", 0x1fa8 },
+ { "Omegaiotasublenisacute", 0x1fac },
+ { "Omegaiotasublenisgrave", 0x1faa },
+ { "Omegaiotasublenistilde", 0x1fae },
+ { "Omegalenis", 0x1f68 },
+ { "Omegalenisacute", 0x1f6c },
+ { "Omegalenisgrave", 0x1f6a },
+ { "Omegalenistilde", 0x1f6e },
+ { "Omicronacute", 0x1ff9 },
+ { "Omicronasper", 0x1f49 },
+ { "Omicronasperacute", 0x1f4d },
+ { "Omicronaspergrave", 0x1f4b },
+ { "Omicrongrave", 0x1ff8 },
+ { "Omicronlenis", 0x1f48 },
+ { "Omicronlenisacute", 0x1f4c },
+ { "Omicronlenisgrave", 0x1f4a },
+ { "Rhoasper", 0x1fec },
+ { "Upsilonacute", 0x1feb },
+ { "Upsilonasper", 0x1f59 },
+ { "Upsilonasperacute", 0x1f5d },
+ { "Upsilonaspergrave", 0x1f5b },
+ { "Upsilonaspertilde", 0x1f5f },
+ { "Upsilonbreve", 0x1fe8 },
+ { "Upsilongrave", 0x1fea },
+ { "Upsilonmacron", 0x1fe9 },
+ { "numeralsign", 0x0374 },
+ { "lownumeralsign", 0x0375 },
+ { "lowcomma", 0x037a },
+ { "stigma", 0x03da },
+ { "koppa", 0x03de },
+ { "sampi", 0x03e0 },
+ { "lenis", 0x1fbd },
+ { "iotasubscript", 0x1fbe },
+ { "dieresistilde", 0x1fc1 },
+ { "lenisgrave", 0x1fcd },
+ { "lenisacute", 0x1fce },
+ { "lenistilde", 0x1fcf },
+ { "aspergrave", 0x1fdd },
+ { "asperacute", 0x1fde },
+ { "aspertilde", 0x1fdf },
+ { "dialytikagrave", 0x1fed },
+ { "dialytikaacute", 0x1fee },
+ { "asper", 0x1ffe },
+ { "alphalenis", 0x1f00 },
+ { "alphaasper", 0x1f01 },
+ { "alphalenisgrave", 0x1f02 },
+ { "alphaaspergrave", 0x1f03 },
+ { "alphalenisacute", 0x1f04 },
+ { "alphaasperacute", 0x1f05 },
+ { "alphalenistilde", 0x1f06 },
+ { "alphaaspertilde", 0x1f07 },
+ { "epsilonlenis", 0x1f10 },
+ { "epsilonasper", 0x1f11 },
+ { "epsilonlenisgrave", 0x1f12 },
+ { "epsilonaspergrave", 0x1f13 },
+ { "epsilonlenisacute", 0x1f14 },
+ { "epsilonasperacute", 0x1f15 },
+ { "etalenis", 0x1f20 },
+ { "etaasper", 0x1f21 },
+ { "etalenisgrave", 0x1f22 },
+ { "etaaspergrave", 0x1f23 },
+ { "etalenisacute", 0x1f24 },
+ { "etaasperacute", 0x1f25 },
+ { "etalenistilde", 0x1f26 },
+ { "etaaspertilde", 0x1f27 },
+ { "iotalenis", 0x1f30 },
+ { "iotaasper", 0x1f31 },
+ { "iotalenisgrave", 0x1f32 },
+ { "iotaaspergrave", 0x1f33 },
+ { "iotalenisacute", 0x1f34 },
+ { "iotaasperacute", 0x1f35 },
+ { "iotalenistilde", 0x1f36 },
+ { "iotaaspertilde", 0x1f37 },
+ { "omicronlenis", 0x1f40 },
+ { "omicronasper", 0x1f41 },
+ { "omicronlenisgrave", 0x1f42 },
+ { "omicronaspergrave", 0x1f43 },
+ { "omicronlenisacute", 0x1f44 },
+ { "omicronasperacute", 0x1f45 },
+ { "upsilonlenis", 0x1f50 },
+ { "upsilonasper", 0x1f51 },
+ { "upsilonlenisgrave", 0x1f52 },
+ { "upsilonaspergrave", 0x1f53 },
+ { "upsilonlenisacute", 0x1f54 },
+ { "upsilonasperacute", 0x1f55 },
+ { "upsilonlenistilde", 0x1f56 },
+ { "upsilonaspertilde", 0x1f57 },
+ { "omegalenis", 0x1f60 },
+ { "omegaasper", 0x1f61 },
+ { "omegalenisgrave", 0x1f62 },
+ { "omegaaspergrave", 0x1f63 },
+ { "omegalenisacute", 0x1f64 },
+ { "omegaasperacute", 0x1f65 },
+ { "omegalenistilde", 0x1f66 },
+ { "omegaaspertilde", 0x1f67 },
+ { "alphagrave", 0x1f70 },
+ { "alphaacute", 0x1f71 },
+ { "epsilongrave", 0x1f72 },
+ { "epsilonacute", 0x1f73 },
+ { "etagrave", 0x1f74 },
+ { "etaacute", 0x1f75 },
+ { "iotagrave", 0x1f76 },
+ { "iotaacute", 0x1f77 },
+ { "omicrongrave", 0x1f78 },
+ { "omicronacute", 0x1f79 },
+ { "upsilongrave", 0x1f7a },
+ { "upsilonacute", 0x1f7b },
+ { "omegagrave", 0x1f7c },
+ { "omegaacute", 0x1f7d },
+ { "alphaiotasublenis", 0x1f80 },
+ { "alphaiotasubasper", 0x1f81 },
+ { "alphaiotasublenisgrave", 0x1f82 },
+ { "alphaiotasubaspergrave", 0x1f83 },
+ { "alphaiotasublenisacute", 0x1f84 },
+ { "alphaiotasubasperacute", 0x1f85 },
+ { "alphaiotasublenistilde", 0x1f86 },
+ { "alphaiotasubaspertilde", 0x1f87 },
+ { "etaiotasublenis", 0x1f90 },
+ { "etaiotasubasper", 0x1f91 },
+ { "etaiotasublenisgrave", 0x1f92 },
+ { "etaiotasubaspergrave", 0x1f93 },
+ { "etaiotasublenisacute", 0x1f94 },
+ { "etaiotasubasperacute", 0x1f95 },
+ { "etaiotasublenistilde", 0x1f96 },
+ { "etaiotasubaspertilde", 0x1f97 },
+ { "omegaiotasublenis", 0x1fa0 },
+ { "omegaiotasubasper", 0x1fa1 },
+ { "omegaiotasublenisgrave", 0x1fa2 },
+ { "omegaiotasubaspergrave", 0x1fa3 },
+ { "omegaiotasublenisacute", 0x1fa4 },
+ { "omegaiotasubasperacute", 0x1fa5 },
+ { "omegaiotasublenistilde", 0x1fa6 },
+ { "omegaiotasubaspertilde", 0x1fa7 },
+ { "alphabreve", 0x1fb0 },
+ { "alphamacron", 0x1fb1 },
+ { "alphaiotasubgrave", 0x1fb2 },
+ { "alphaiotasub", 0x1fb3 },
+ { "alphatilde", 0x1fb6 },
+ { "alphaiotasubtilde", 0x1fb7 },
+ { "etaiotasubgrave", 0x1fc2 },
+ { "etaiotasub", 0x1fc3 },
+ { "etaiotasubacute", 0x1fc4 },
+ { "etatilde", 0x1fc6 },
+ { "etaiotasubtilde", 0x1fc7 },
+ { "iotabreve", 0x1fd0 },
+ { "iotamacron", 0x1fd1 },
+ { "iotadieresisgrave", 0x1fd2 },
+ { "iotadieresisacute", 0x1fd3 },
+ { "iotatilde", 0x1fd6 },
+ { "iotadieresistilde", 0x1fd7 },
+ { "upsilonbreve", 0x1fe0 },
+ { "upsilonmacron", 0x1fe1 },
+ { "upsilondieresisgrave", 0x1fe2 },
+ { "upsilondieresisacute", 0x1fe3 },
+ { "rholenis", 0x1fe4 },
+ { "rhoasper", 0x1fe5 },
+ { "upsilontilde", 0x1fe6 },
+ { "omegaiotasubgrave", 0x1ff2 },
+ { "omegaiotasub", 0x1ff3 },
+ { "omegaiotasubacute", 0x1ff4 },
+ { "omegatilde", 0x1ff6 },
+ { "omegaiotasubtilde", 0x1ff7 },
+ { "alphaiotasubacute", 0x1fb4 },
+ { "upsilondieresistilde", 0x1fe7 },
+ { "digamma", 0xefd5 },
+ { "Be", 0x0411 },
+ { "Ve", 0x0412 },
+ { "Ghe", 0x0413 },
+ { "De", 0x0414 },
+ { "Ie", 0x0415 },
+ { "Zhe", 0x0416 },
+ { "Ze", 0x0417 },
+ { "Ka", 0x041a },
+ { "El", 0x041b },
+ { "Em", 0x041c },
+ { "En", 0x041d },
+ { "Pe", 0x041f },
+ { "Er", 0x0420 },
+ { "Es", 0x0421 },
+ { "Te", 0x0422 },
+ { "Ef", 0x0424 },
+ { "Ha", 0x0425 },
+ { "Tse", 0x0426 },
+ { "Che", 0x0427 },
+ { "Sha", 0x0428 },
+ { "Shcha", 0x0429 },
+ { "Hard", 0x042a },
+ { "Yeru", 0x042b },
+ { "Soft", 0x042c },
+ { "Yu", 0x042e },
+ { "Ya", 0x042f },
+ { "Io", 0x0401 },
+ { "Dje", 0x0402 },
+ { "Gje", 0x0403 },
+ { "Dze", 0x0405 },
+ { "Yi", 0x0407 },
+ { "Je", 0x0408 },
+ { "Lje", 0x0409 },
+ { "Nje", 0x040a },
+ { "Tshe", 0x040b },
+ { "Kje", 0x040c },
+ { "Dzhe", 0x040f },
+ { "Yat", 0x0462 },
+ { "Fita", 0x0472 },
+ { "Izhitsa", 0x0474 },
+ { "be", 0x0431 },
+ { "ve", 0x0432 },
+ { "ghe", 0x0433 },
+ { "de", 0x0434 },
+ { "ie", 0x0435 },
+ { "zhe", 0x0436 },
+ { "ze", 0x0437 },
+ { "ka", 0x043a },
+ { "el", 0x043b },
+ { "em", 0x043c },
+ { "en", 0x043d },
+ { "er", 0x0440 },
+ { "es", 0x0441 },
+ { "te", 0x0442 },
+ { "ef", 0x0444 },
+ { "ha", 0x0445 },
+ { "tse", 0x0446 },
+ { "che", 0x0447 },
+ { "sha", 0x0448 },
+ { "shcha", 0x0449 },
+ { "hard", 0x044a },
+ { "yeru", 0x044b },
+ { "soft", 0x044c },
+ { "yu", 0x044e },
+ { "ya", 0x044f },
+ { "io", 0x0451 },
+ { "dje", 0x0452 },
+ { "gje", 0x0453 },
+ { "dze", 0x0455 },
+ { "yi", 0x0457 },
+ { "je", 0x0458 },
+ { "lje", 0x0459 },
+ { "nje", 0x045a },
+ { "tshe", 0x045b },
+ { "kje", 0x045c },
+ { "dzhe", 0x045f },
+ { "yat", 0x0463 },
+ { "fita", 0x0473 },
+ { "izhitsa", 0x0475 },
+ { "litre", 0x2113 },
+ { "Dotaccent", 0xefed },
+ { "Breve", 0xefee },
+ { "Ogonek", 0xeff1 },
+ { "Cedilla", 0xeff2 },
+ { "Ring", 0xeff3 },
+ { "Tilde", 0xeff5 },
+ { "Circumflex", 0xeff7 },
+ { "dbar", 0x0111 },
+ { "st", 0xfb06 },
+ { "TeXtext32", 0x0337 },
+ { "DD070", 0x2014 },
+ { "monospacedash", 0x2014 },
+ { "Dash1cent", 0x2015 },
+ { "apostrophereverse", 0x201b },
+ { "Pts", 0x20a7 },
+ { "SM760000", 0x2195 },
+ { "SM770000", 0x21a8 },
+ { "SP320000", 0x2219 },
+ { "SD630000", 0x22c5 },
+ { "SM790000", 0x2302 },
+ { "caretinverted", 0x2304 },
+ { "SM680000", 0x2310 },
+ { "SA420000", 0x2319 },
+ { "BorderULCorner1", 0x231c },
+ { "DD010", 0x231c },
+ { "DD101", 0x231c },
+ { "BorderURCorner1", 0x231d },
+ { "DD012", 0x231d },
+ { "DD104", 0x231d },
+ { "BorderLLCorner1", 0x231e },
+ { "DD014", 0x231e },
+ { "DD109", 0x231e },
+ { "BorderLRCorner1", 0x231f },
+ { "DD015", 0x231f },
+ { "DD112", 0x231f },
+ { "SS260000", 0x2320 },
+ { "SS270000", 0x2321 },
+ { "hook", 0x2440 },
+ { "chair", 0x2441 },
+ { "fork", 0x2442 },
+ { "SF600000", 0x2580 },
+ { "BorderLower1", 0x2581 },
+ { "DD011", 0x2581 },
+ { "DD021", 0x2581 },
+ { "DD110", 0x2581 },
+ { "Flower1l", 0x2581 },
+ { "SF570000", 0x2584 },
+ { "SF610000", 0x2588 },
+ { "Tile", 0x2588 },
+ { "HalfTile", 0x258c },
+ { "SF580000", 0x258c },
+ { "BorderLeftVertical1", 0x258f },
+ { "DD013", 0x258f },
+ { "DD034", 0x258f },
+ { "DD105", 0x258f },
+ { "Flower1d", 0x258f },
+ { "SF590000", 0x2590 },
+ { "SF140000", 0x2591 },
+ { "SF150000", 0x2592 },
+ { "SF160000", 0x2593 },
+ { "BorderUpper1", 0x2594 },
+ { "DD024", 0x2594 },
+ { "DD102", 0x2594 },
+ { "BorderRightVertical1", 0x2595 },
+ { "DD031", 0x2595 },
+ { "DD106", 0x2595 },
+ { "Flower2dr", 0x2595 },
+ { "SM600000", 0x25b2 },
+ { "SM590000", 0x25b6 },
+ { "SV040000", 0x25bc },
+ { "SM630000", 0x25c0 },
+ { "SM750000", 0x25cb },
+ { "SM570001", 0x25d8 },
+ { "SM750002", 0x25d9 },
+ { "ShootingStar", 0x2604 },
+ { "DD130", 0x2605 },
+ { "StarDingbat1", 0x2605 },
+ { "TheSun", 0x2609 },
+ { "FleuronLeft", 0x2619 },
+ { "cross", 0x2629 },
+ { "SS000000", 0x263a },
+ { "SS010000", 0x263b },
+ { "SM690000", 0x263c },
+ { "TheMoon", 0x263d },
+ { "Moon", 0x263e },
+ { "Mercury", 0x263f },
+ { "Venus", 0x2640 },
+ { "Earth", 0x2641 },
+ { "Mars", 0x2642 },
+ { "Jupiter", 0x2643 },
+ { "Saturn", 0x2644 },
+ { "Uranus", 0x2645 },
+ { "Neptune", 0x2646 },
+ { "Pluto", 0x2647 },
+ { "Aries", 0x2648 },
+ { "Taurus", 0x2649 },
+ { "Gemini", 0x264a },
+ { "Cancer", 0x264b },
+ { "Leo", 0x264c },
+ { "Virgo", 0x264d },
+ { "Libra", 0x264e },
+ { "Scorpio", 0x264f },
+ { "Sagittarius", 0x2650 },
+ { "Capricorn", 0x2651 },
+ { "Aquarius", 0x2652 },
+ { "Pisces", 0x2653 },
+ { "diamondopen", 0x2662 },
+ { "FleuronCenter", 0x2766 },
+ { "FleuronRight", 0x2767 },
+ { "st1", 0xfb06 },
+ { "zeroslash", 0xf638 },
+ { "pi1", 0x03d6 },
+ { "hyphen-minus", 0x002d },
+ { "hyphenminus", 0x002d },
+ { "nonmarkingreturn", 0x000c },
+ { "micro", 0x00b5 },
+ { "Dmacron", 0x0110 },
+ { "kra", 0x0138 },
+ { "bbar", 0x0180 },
+ { "Dbar", 0x0189 },
+ { "deltaturn", 0x018d },
+ { "Eturn", 0x018e },
+ { "Epsilonlatin", 0x0190 },
+ { "Gammalatin", 0x0194 },
+ { "Iotalatin", 0x0196 },
+ { "Ibar", 0x0197 },
+ { "lambdabar", 0x019b },
+ { "mcapturn", 0x019c },
+ { "Nhook", 0x019d },
+ { "nleg", 0x019e },
+ { "Obar", 0x019f },
+ { "OI", 0x01a2 },
+ { "YR", 0x01a6 },
+ { "eshlooprev", 0x01aa },
+ { "Trthook", 0x01ae },
+ { "Upsilonlatin", 0x01b1 },
+ { "Vcursive", 0x01b2 },
+ { "Zbar", 0x01b5 },
+ { "zbar", 0x01b6 },
+ { "Yogh", 0x01b7 },
+ { "Yoghrev", 0x01b8 },
+ { "yoghrev", 0x01b9 },
+ { "yoghtail", 0x01ba },
+ { "twobar", 0x01bb },
+ { "glottalstopbarinv", 0x01be },
+ { "pipe", 0x01c0 },
+ { "pipedbl", 0x01c1 },
+ { "pipedblbar", 0x01c2 },
+ { "exclamlatin", 0x01c3 },
+ { "DZhacek", 0x01c4 },
+ { "Dzhacek", 0x01c5 },
+ { "dzhacek", 0x01c6 },
+ { "Ahacek", 0x01cd },
+ { "ahacek", 0x01ce },
+ { "Ihacek", 0x01cf },
+ { "ihacek", 0x01d0 },
+ { "Ohacek", 0x01d1 },
+ { "ohacek", 0x01d2 },
+ { "Uhacek", 0x01d3 },
+ { "uhacek", 0x01d4 },
+ { "Udieresishacek", 0x01d9 },
+ { "udieresishacek", 0x01da },
+ { "eturn", 0x01dd },
+ { "Gbar", 0x01e4 },
+ { "gbar", 0x01e5 },
+ { "Ghacek", 0x01e6 },
+ { "ghacek", 0x01e7 },
+ { "Khacek", 0x01e8 },
+ { "khacek", 0x01e9 },
+ { "Yoghhacek", 0x01ee },
+ { "yoghhacek", 0x01ef },
+ { "jhacek", 0x01f0 },
+ { "aturn", 0x0250 },
+ { "ascriptturn", 0x0252 },
+ { "cturn", 0x0254 },
+ { "drthook", 0x0256 },
+ { "erev", 0x0258 },
+ { "epsilonlatin", 0x025b },
+ { "epsilonlatinrev", 0x025c },
+ { "epsilonlatinrevhook", 0x025d },
+ { "epsilonlatinrevclosed", 0x025e },
+ { "jdotlessbar", 0x025f },
+ { "gcursive", 0x0261 },
+ { "Gsmallcap", 0x0262 },
+ { "gammalatin", 0x0263 },
+ { "babygamma", 0x0264 },
+ { "hturn", 0x0265 },
+ { "ibar", 0x0268 },
+ { "Ismallcap", 0x026a },
+ { "lmidtilde", 0x026b },
+ { "lrthook", 0x026d },
+ { "lyogh", 0x026e },
+ { "mturn", 0x026f },
+ { "mturndescend", 0x0270 },
+ { "nlftlfthook", 0x0272 },
+ { "nrthook", 0x0273 },
+ { "Nsmallcap", 0x0274 },
+ { "obar", 0x0275 },
+ { "OEsmallcap", 0x0276 },
+ { "omegaclosed", 0x0277 },
+ { "rturn", 0x0279 },
+ { "rturnascend", 0x027a },
+ { "rturnrthook", 0x027b },
+ { "rdescend", 0x027c },
+ { "rrthook", 0x027d },
+ { "rfishhookrev", 0x027f },
+ { "Rsmallcap", 0x0280 },
+ { "Rsmallcapinv", 0x0281 },
+ { "srthook", 0x0282 },
+ { "jhookdblbar", 0x0284 },
+ { "eshshortrev", 0x0285 },
+ { "tturn", 0x0287 },
+ { "trthook", 0x0288 },
+ { "vscript", 0x028b },
+ { "vturn", 0x028c },
+ { "wturn", 0x028d },
+ { "yturn", 0x028e },
+ { "Ysmallcap", 0x028f },
+ { "zrthook", 0x0290 },
+ { "yogh", 0x0292 },
+ { "yoghcurl", 0x0293 },
+ { "glottalstoprevinv", 0x0295 },
+ { "glottalstopinv", 0x0296 },
+ { "cstretch", 0x0297 },
+ { "kiss", 0x0298 },
+ { "Bsmallcap", 0x0299 },
+ { "epsilonclosed", 0x029a },
+ { "Gsmallcaphook", 0x029b },
+ { "Hsmallcap", 0x029c },
+ { "jcrosstail", 0x029d },
+ { "kturn", 0x029e },
+ { "Lsmallcap", 0x029f },
+ { "glottalstopbar", 0x02a1 },
+ { "glottalstopbarrev", 0x02a2 },
+ { "dyogh", 0x02a4 },
+ { "hsuper", 0x02b0 },
+ { "hhooksuper", 0x02b1 },
+ { "jsuper", 0x02b2 },
+ { "rsuper", 0x02b3 },
+ { "rturnsuper", 0x02b4 },
+ { "rturnrthooksuper", 0x02b5 },
+ { "Rturnsuper", 0x02b6 },
+ { "wsuper", 0x02b7 },
+ { "ysuper", 0x02b8 },
+ { "primedblmod", 0x02ba },
+ { "quoteleftmod", 0x02bb },
+ { "apostrophe", 0x02bc },
+ { "apostropherev", 0x02bd },
+ { "ringrighthalfsuper", 0x02be },
+ { "ringlefthalfsuper", 0x02bf },
+ { "glottal", 0x02c0 },
+ { "glottalrev", 0x02c1 },
+ { "fronted", 0x02c2 },
+ { "backed", 0x02c3 },
+ { "raised", 0x02c4 },
+ { "lowered", 0x02c5 },
+ { "linevert", 0x02c8 },
+ { "macronmodifier", 0x02c9 },
+ { "acutemodifier", 0x02ca },
+ { "gravemodifier", 0x02cb },
+ { "linevertsub", 0x02cc },
+ { "macronsub", 0x02cd },
+ { "gravesub", 0x02ce },
+ { "acutesub", 0x02cf },
+ { "length", 0x02d0 },
+ { "halflength", 0x02d1 },
+ { "ringrighthalfcenter", 0x02d2 },
+ { "ringlefthalfsup", 0x02d3 },
+ { "tackupmid", 0x02d4 },
+ { "tackdownmid", 0x02d5 },
+ { "rhotichook", 0x02de },
+ { "gammasuper", 0x02e0 },
+ { "lsuper", 0x02e1 },
+ { "ssuper", 0x02e2 },
+ { "xsuper", 0x02e3 },
+ { "glottalrevsuper", 0x02e4 },
+ { "toneextrahigh", 0x02e5 },
+ { "tonehigh", 0x02e6 },
+ { "tonemid", 0x02e7 },
+ { "tonelow", 0x02e8 },
+ { "toneextralow", 0x02e9 },
+ { "gravenosp", 0x0300 },
+ { "acutenosp", 0x0301 },
+ { "circumflexnosp", 0x0302 },
+ { "tildenosp", 0x0303 },
+ { "macronnosp", 0x0304 },
+ { "overscorenosp", 0x0305 },
+ { "brevenosp", 0x0306 },
+ { "dotnosp", 0x0307 },
+ { "dieresisnosp", 0x0308 },
+ { "hooksupnosp", 0x0309 },
+ { "ringnosp", 0x030a },
+ { "acutedblnosp", 0x030b },
+ { "haceknosp", 0x030c },
+ { "linevertnosp", 0x030d },
+ { "linevertdblnosp", 0x030e },
+ { "gravedblnosp", 0x030f },
+ { "candrabindunosp", 0x0310 },
+ { "breveinvnosp", 0x0311 },
+ { "commaturnsupnosp", 0x0312 },
+ { "apostrophesupnosp", 0x0313 },
+ { "commasuprevnosp", 0x0314 },
+ { "commasuprightnosp", 0x0315 },
+ { "gravesubnosp", 0x0316 },
+ { "acutesubnosp", 0x0317 },
+ { "tackleftsubnosp", 0x0318 },
+ { "tackrightsubnosp", 0x0319 },
+ { "anglesupnosp", 0x031a },
+ { "hornnosp", 0x031b },
+ { "ringlefthalfsubnosp", 0x031c },
+ { "tackupsubnosp", 0x031d },
+ { "tackdownsubnosp", 0x031e },
+ { "plussubnosp", 0x031f },
+ { "minussubnosp", 0x0320 },
+ { "hooksubpalatnosp", 0x0321 },
+ { "hooksubretronosp", 0x0322 },
+ { "dotsubnosp", 0x0323 },
+ { "dotdblsubnosp", 0x0324 },
+ { "ringsubnosp", 0x0325 },
+ { "commasubnosp", 0x0326 },
+ { "cedillanosp", 0x0327 },
+ { "ogoneknosp", 0x0328 },
+ { "linevertsubnosp", 0x0329 },
+ { "bridgesubnosp", 0x032a },
+ { "archdblsubnosp", 0x032b },
+ { "haceksubnosp", 0x032c },
+ { "circumflexsubnosp", 0x032d },
+ { "brevesubnosp", 0x032e },
+ { "breveinvsubnosp", 0x032f },
+ { "tildesubnosp", 0x0330 },
+ { "macronsubnosp", 0x0331 },
+ { "underscorenosp", 0x0332 },
+ { "underscoredblnosp", 0x0333 },
+ { "tildemidnosp", 0x0334 },
+ { "barmidshortnosp", 0x0335 },
+ { "barmidlongnosp", 0x0336 },
+ { "slashshortnosp", 0x0337 },
+ { "slashlongnosp", 0x0338 },
+ { "ringrighthalfsubnosp", 0x0339 },
+ { "bridgeinvsubnosp", 0x033a },
+ { "squaresubnosp", 0x033b },
+ { "seagullsubnosp", 0x033c },
+ { "xsupnosp", 0x033d },
+ { "tildevertsupnosp", 0x033e },
+ { "overscoredblnosp", 0x033f },
+ { "graveleftnosp", 0x0340 },
+ { "acuterightnosp", 0x0341 },
+ { "wavyoverscorenosp", 0x0342 },
+ { "zigzagoverscorenosp", 0x0343 },
+ { "diaeresistonosnosp", 0x0344 },
+ { "iotasubnosp", 0x0345 },
+ { "iotasub", 0x037a },
+ { "diaeresistonos", 0x0385 },
+ { "iotadiaeresistonos", 0x0390 },
+ { "Iotadiaeresis", 0x03aa },
+ { "Upsilondiaeresis", 0x03ab },
+ { "upsilondiaeresistonos", 0x03b0 },
+ { "iotadiaeresis", 0x03ca },
+ { "upsilondiaeresis", 0x03cb },
+ { "betacurled", 0x03d0 },
+ { "thetascript", 0x03d1 },
+ { "Upsilonhook", 0x03d2 },
+ { "Upsilonhooktonos", 0x03d3 },
+ { "Upsilonhookdiaeresis", 0x03d4 },
+ { "phiscript", 0x03d5 },
+ { "omegapi", 0x03d6 },
+ { "Stigma", 0x03da },
+ { "stigma", 0x03db },
+ { "Digamma", 0x03dc },
+ { "digamma", 0x03dd },
+ { "Koppa", 0x03de },
+ { "koppa", 0x03df },
+ { "Sampi", 0x03e0 },
+ { "sampi", 0x03e1 },
+ { "Shei", 0x03e2 },
+ { "shei", 0x03e3 },
+ { "Fei", 0x03e4 },
+ { "fei", 0x03e5 },
+ { "Khei", 0x03e6 },
+ { "khei", 0x03e7 },
+ { "Hori", 0x03e8 },
+ { "hori", 0x03e9 },
+ { "Gangia", 0x03ea },
+ { "gangia", 0x03eb },
+ { "Shima", 0x03ec },
+ { "shima", 0x03ed },
+ { "Dei", 0x03ee },
+ { "dei", 0x03ef },
+ { "kappascript", 0x03f0 },
+ { "sigmalunate", 0x03f2 },
+ { "Io", 0x0401 },
+ { "Dje", 0x0402 },
+ { "Gje", 0x0403 },
+ { "Ecyril", 0x0404 },
+ { "Dze", 0x0405 },
+ { "Icyril", 0x0406 },
+ { "Yi", 0x0407 },
+ { "Je", 0x0408 },
+ { "Lje", 0x0409 },
+ { "Nje", 0x040a },
+ { "Tshe", 0x040b },
+ { "Kje", 0x040c },
+ { "Ucyrilbreve", 0x040e },
+ { "Dzhe", 0x040f },
+ { "Acyril", 0x0410 },
+ { "Be", 0x0411 },
+ { "Ve", 0x0412 },
+ { "Ge", 0x0413 },
+ { "De", 0x0414 },
+ { "Ie", 0x0415 },
+ { "Zhe", 0x0416 },
+ { "Ze", 0x0417 },
+ { "Ii", 0x0418 },
+ { "Iibreve", 0x0419 },
+ { "Ka", 0x041a },
+ { "El", 0x041b },
+ { "Em", 0x041c },
+ { "En", 0x041d },
+ { "Ocyril", 0x041e },
+ { "Pecyril", 0x041f },
+ { "Er", 0x0420 },
+ { "Es", 0x0421 },
+ { "Te", 0x0422 },
+ { "Ucyril", 0x0423 },
+ { "Ef", 0x0424 },
+ { "Kha", 0x0425 },
+ { "Tse", 0x0426 },
+ { "Che", 0x0427 },
+ { "Sha", 0x0428 },
+ { "Shcha", 0x0429 },
+ { "Hard", 0x042a },
+ { "Yeri", 0x042b },
+ { "Soft", 0x042c },
+ { "Ecyrilrev", 0x042d },
+ { "Iu", 0x042e },
+ { "Ia", 0x042f },
+ { "acyril", 0x0430 },
+ { "be", 0x0431 },
+ { "ve", 0x0432 },
+ { "ge", 0x0433 },
+ { "de", 0x0434 },
+ { "ie", 0x0435 },
+ { "zhe", 0x0436 },
+ { "ze", 0x0437 },
+ { "ii", 0x0438 },
+ { "iibreve", 0x0439 },
+ { "ka", 0x043a },
+ { "el", 0x043b },
+ { "em", 0x043c },
+ { "en", 0x043d },
+ { "ocyril", 0x043e },
+ { "pecyril", 0x043f },
+ { "er", 0x0440 },
+ { "es", 0x0441 },
+ { "te", 0x0442 },
+ { "ucyril", 0x0443 },
+ { "ef", 0x0444 },
+ { "kha", 0x0445 },
+ { "tse", 0x0446 },
+ { "che", 0x0447 },
+ { "sha", 0x0448 },
+ { "shcha", 0x0449 },
+ { "hard", 0x044a },
+ { "yeri", 0x044b },
+ { "soft", 0x044c },
+ { "ecyrilrev", 0x044d },
+ { "iu", 0x044e },
+ { "ia", 0x044f },
+ { "io", 0x0451 },
+ { "dje", 0x0452 },
+ { "gje", 0x0453 },
+ { "ecyril", 0x0454 },
+ { "dze", 0x0455 },
+ { "icyril", 0x0456 },
+ { "yi", 0x0457 },
+ { "je", 0x0458 },
+ { "lje", 0x0459 },
+ { "nje", 0x045a },
+ { "tshe", 0x045b },
+ { "kje", 0x045c },
+ { "ucyrilbreve", 0x045e },
+ { "dzhe", 0x045f },
+ { "Yat", 0x0462 },
+ { "yat", 0x0463 },
+ { "Yusbig", 0x046a },
+ { "yusbig", 0x046b },
+ { "Psicyril", 0x0470 },
+ { "psicyril", 0x0471 },
+ { "Fita", 0x0472 },
+ { "fita", 0x0473 },
+ { "Izhitsa", 0x0474 },
+ { "izhitsa", 0x0475 },
+ { "Izhitsagravedbl", 0x0476 },
+ { "izhitsagravedbl", 0x0477 },
+ { "Digraphuk", 0x0478 },
+ { "digraphuk", 0x0479 },
+ { "Omegaround", 0x047a },
+ { "omegaround", 0x047b },
+ { "Omegatitlo", 0x047c },
+ { "omegatitlo", 0x047d },
+ { "OT", 0x047e },
+ { "ot", 0x047f },
+ { "Geupturn", 0x0490 },
+ { "geupturn", 0x0491 },
+ { "Gebar", 0x0492 },
+ { "gebar", 0x0493 },
+ { "Gehook", 0x0494 },
+ { "gehook", 0x0495 },
+ { "Zhertdes", 0x0496 },
+ { "zhertdes", 0x0497 },
+ { "Zecedilla", 0x0498 },
+ { "zecedilla", 0x0499 },
+ { "Kartdes", 0x049a },
+ { "kartdes", 0x049b },
+ { "Kavertbar", 0x049c },
+ { "kavertbar", 0x049d },
+ { "Kabar", 0x049e },
+ { "kabar", 0x049f },
+ { "GeKarev", 0x04a0 },
+ { "gekarev", 0x04a1 },
+ { "Enrtdes", 0x04a2 },
+ { "enrtdes", 0x04a3 },
+ { "EnGe", 0x04a4 },
+ { "enge", 0x04a5 },
+ { "Pehook", 0x04a6 },
+ { "pehook", 0x04a7 },
+ { "Ohook", 0x04a8 },
+ { "ohook", 0x04a9 },
+ { "Escedilla", 0x04aa },
+ { "escedilla", 0x04ab },
+ { "Tertdes", 0x04ac },
+ { "tertdes", 0x04ad },
+ { "Ustrt", 0x04ae },
+ { "ustrt", 0x04af },
+ { "Ustrtbar", 0x04b0 },
+ { "ustrtbar", 0x04b1 },
+ { "Khartdes", 0x04b2 },
+ { "khartdes", 0x04b3 },
+ { "TeTse", 0x04b4 },
+ { "tetse", 0x04b5 },
+ { "Chertdes", 0x04b6 },
+ { "chertdes", 0x04b7 },
+ { "Chevertbar", 0x04b8 },
+ { "chevertbar", 0x04b9 },
+ { "Hcyril", 0x04ba },
+ { "hcyril", 0x04bb },
+ { "Iehook", 0x04bc },
+ { "iehook", 0x04bd },
+ { "Iehookogonek", 0x04be },
+ { "iehookogonek", 0x04bf },
+ { "Icyril1", 0x04c0 },
+ { "Zhebreve", 0x04c1 },
+ { "zhebreve", 0x04c2 },
+ { "Kahook", 0x04c3 },
+ { "kahook", 0x04c4 },
+ { "Enhook", 0x04c7 },
+ { "enhook", 0x04c8 },
+ { "Cheleftdes", 0x04cb },
+ { "cheleftdes", 0x04cc },
+ { "qibuts", 0x05bb },
+ { "meteg", 0x05bd },
+ { "maqaf", 0x05be },
+ { "paseq", 0x05c0 },
+ { "shindot", 0x05c1 },
+ { "sindot", 0x05c2 },
+ { "sofpasuq", 0x05c3 },
+ { "kaffinal", 0x05da },
+ { "memfinal", 0x05dd },
+ { "nunfinal", 0x05df },
+ { "pefinal", 0x05e3 },
+ { "tsadifinal", 0x05e5 },
+ { "vavdbl", 0x05f0 },
+ { "vavyod", 0x05f1 },
+ { "yoddbl", 0x05f2 },
+ { "geresh", 0x05f3 },
+ { "gershayim", 0x05f4 },
+ { "varika", 0x05f5 },
+ { "enquad", 0x2000 },
+ { "emquad", 0x2001 },
+ { "emspace", 0x2003 },
+ { "threeperemspace", 0x2004 },
+ { "fourperemspace", 0x2005 },
+ { "sixperemspace", 0x2006 },
+ { "figurespace", 0x2007 },
+ { "punctuationspace", 0x2008 },
+ { "thinspace", 0x2009 },
+ { "hairspace", 0x200a },
+ { "zerospace", 0x200b },
+ { "zeronojoin", 0x200c },
+ { "zerojoin", 0x200d },
+ { "hyphennobreak", 0x2011 },
+ { "quotedash", 0x2015 },
+ { "dashdbl", 0x2016 },
+ { "quotesinglrev", 0x201b },
+ { "quotedblrev", 0x201f },
+ { "trianglebullet", 0x2023 },
+ { "onedotlead", 0x2024 },
+ { "twodotlead", 0x2025 },
+ { "hyphendot", 0x2027 },
+ { "lineseparator", 0x2028 },
+ { "paragraphseparator", 0x2029 },
+ { "lre", 0x202a },
+ { "rle", 0x202b },
+ { "pdf", 0x202c },
+ { "lro", 0x202d },
+ { "rlo", 0x202e },
+ { "pertenthousand", 0x2031 },
+ { "prime", 0x2032 },
+ { "primedbl", 0x2033 },
+ { "primetriple", 0x2034 },
+ { "primerev", 0x2035 },
+ { "primedblrev", 0x2036 },
+ { "primetriplerev", 0x2037 },
+ { "caret", 0x2038 },
+ { "refmark", 0x203b },
+ { "interrobang", 0x203d },
+ { "tie", 0x2040 },
+ { "caretinsert", 0x2041 },
+ { "hyphenbullet", 0x2043 },
+ { "minussuperior", 0x207b },
+ { "plusinferior", 0x208a },
+ { "equalinferior", 0x208c },
+ { "eurocurrency", 0x20a0 },
+ { "coloncurrency", 0x20a1 },
+ { "mill", 0x20a5 },
+ { "naira", 0x20a6 },
+ { "pesetas", 0x20a7 },
+ { "rupee", 0x20a8 },
+ { "newsheqel", 0x20aa },
+ { "accountof", 0x2100 },
+ { "addresssubject", 0x2101 },
+ { "Cbb", 0x2102 },
+ { "degreecentigrade", 0x2103 },
+ { "CL", 0x2104 },
+ { "cadauna", 0x2106 },
+ { "Euler", 0x2107 },
+ { "scruple", 0x2108 },
+ { "degreefarenheit", 0x2109 },
+ { "Hscript", 0x210b },
+ { "Hblackletter", 0x210c },
+ { "Hbb", 0x210d },
+ { "planck", 0x210e },
+ { "planckover2pi", 0x210f },
+ { "Iscript", 0x2110 },
+ { "Lscript", 0x2112 },
+ { "lscript", 0x2113 },
+ { "lbbar", 0x2114 },
+ { "Nbb", 0x2115 },
+ { "recordright", 0x2117 },
+ { "Pbb", 0x2119 },
+ { "Qbb", 0x211a },
+ { "Rscript", 0x211b },
+ { "Rfractur", 0x211c },
+ { "Rbb", 0x211d },
+ { "Rx", 0x211e },
+ { "response", 0x211f },
+ { "servicemark", 0x2120 },
+ { "tel", 0x2121 },
+ { "versicle", 0x2123 },
+ { "Zbb", 0x2124 },
+ { "ounce", 0x2125 },
+ { "ohm", 0x2126 },
+ { "mho", 0x2127 },
+ { "Zblackletter", 0x2128 },
+ { "iotaturn", 0x2129 },
+ { "degreekelvin", 0x212a },
+ { "Bscript", 0x212c },
+ { "Cblackletter", 0x212d },
+ { "escript", 0x212f },
+ { "Escript", 0x2130 },
+ { "Fscript", 0x2131 },
+ { "Fturn", 0x2132 },
+ { "Mscript", 0x2133 },
+ { "u0scrip", 0x2134 },
+ { "alephmath", 0x2135 },
+ { "gimelmath", 0x2137 },
+ { "dalethmath", 0x2138 },
+ { "twothird", 0x2154 },
+ { "onefifth", 0x2155 },
+ { "twofifths", 0x2156 },
+ { "threefifths", 0x2157 },
+ { "fourfifths", 0x2158 },
+ { "onesixth", 0x2159 },
+ { "fivesixths", 0x215a },
+ { "onenumerator", 0x215f },
+ { "arrowlongboth", 0x2194 },
+ { "arrowlongbothv", 0x2195 },
+ { "arrownorthwest", 0x2196 },
+ { "arrownortheast", 0x2197 },
+ { "arrowsoutheast", 0x2198 },
+ { "arrowsouthwest", 0x2199 },
+ { "arrowleftnot", 0x219a },
+ { "arrowrightnot", 0x219b },
+ { "arrowwaveleft", 0x219c },
+ { "arrowwaveright", 0x219d },
+ { "dblarrowheadleft", 0x219e },
+ { "dblarrowheadup", 0x219f },
+ { "dblarrowheadright", 0x21a0 },
+ { "dblarrowheaddown", 0x21a1 },
+ { "arrowtailleft", 0x21a2 },
+ { "arrowtailright", 0x21a3 },
+ { "arrowbarleft", 0x21a4 },
+ { "arrowbarup", 0x21a5 },
+ { "arrowbarright", 0x21a6 },
+ { "arrowbardown", 0x21a7 },
+ { "arrowbothvbase", 0x21a8 },
+ { "arrowhookleft", 0x21a9 },
+ { "arrowhookright", 0x21aa },
+ { "arrowloopleft", 0x21ab },
+ { "arrowloopright", 0x21ac },
+ { "arrowwaveboth", 0x21ad },
+ { "arrowlongbothnot", 0x21ae },
+ { "arrowzigzag", 0x21af },
+ { "arrowrightdown", 0x21b4 },
+ { "carriagerreturn", 0x21b5 },
+ { "arrowsemanticlockw", 0x21b6 },
+ { "arrowsemclockw", 0x21b7 },
+ { "home", 0x21b8 },
+ { "tableftright", 0x21b9 },
+ { "arrowanticlockw", 0x21ba },
+ { "arrowclockw", 0x21bb },
+ { "arrowlefttophalf", 0x21bc },
+ { "arrowleftbothalf", 0x21bd },
+ { "harpoonupright", 0x21be },
+ { "harpoonupleft", 0x21bf },
+ { "arrowrighttophalf", 0x21c0 },
+ { "arrowrightbothalf", 0x21c1 },
+ { "harpoondownright", 0x21c2 },
+ { "harpoondownleft", 0x21c3 },
+ { "arrowparrrightleft", 0x21c4 },
+ { "dblarrowupdown", 0x21c5 },
+ { "arrowparrleftright", 0x21c6 },
+ { "dblarrowup", 0x21c8 },
+ { "dblarrowdown", 0x21ca },
+ { "harpoonleftright", 0x21cb },
+ { "harpoonrightleft", 0x21cc },
+ { "arrowdblleftnot", 0x21cd },
+ { "arrowdbllongbothnot", 0x21ce },
+ { "arrowdblrightnot", 0x21cf },
+ { "arrowdbllongboth", 0x21d4 },
+ { "arrowdbllongbothv", 0x21d5 },
+ { "arrowdblnw", 0x21d6 },
+ { "arrowdblne", 0x21d7 },
+ { "arrowdblse", 0x21d8 },
+ { "arrowdblsw", 0x21d9 },
+ { "arrowtripleleft", 0x21da },
+ { "arrowtripleright", 0x21db },
+ { "arrowsquiggleleft", 0x21dc },
+ { "arrowsquiggleright", 0x21dd },
+ { "arrowopenleft", 0x21e6 },
+ { "arrowopenup", 0x21e7 },
+ { "arrowopenright", 0x21e8 },
+ { "arrowopendown", 0x21e9 },
+ { "complement", 0x2201 },
+ { "notexistential", 0x2204 },
+ { "elementsmall", 0x220a },
+ { "owner", 0x220b },
+ { "notowner", 0x220c },
+ { "ownersmall", 0x220d },
+ { "eop", 0x220e },
+ { "coproduct", 0x2210 },
+ { "dotplus", 0x2214 },
+ { "slashmath", 0x2215 },
+ { "backslashmath", 0x2216 },
+ { "ringoperator", 0x2218 },
+ { "bulletmath", 0x2219 },
+ { "cuberoot", 0x221b },
+ { "fourthroot", 0x221c },
+ { "measuredangle", 0x2221 },
+ { "sphericalangle", 0x2222 },
+ { "notbar", 0x2224 },
+ { "parallelto", 0x2225 },
+ { "notbardbl", 0x2226 },
+ { "integraldbl", 0x222c },
+ { "integraltrpl", 0x222d },
+ { "contintegral", 0x222e },
+ { "surfintegral", 0x222f },
+ { "volintegral", 0x2230 },
+ { "clwintegral", 0x2231 },
+ { "clwcontintegral", 0x2232 },
+ { "cclwcontintegral", 0x2233 },
+ { "dotminus", 0x2238 },
+ { "excess", 0x2239 },
+ { "geomproportion", 0x223a },
+ { "homothetic", 0x223b },
+ { "revsimilar", 0x223d },
+ { "lazysinv", 0x223e },
+ { "sine", 0x223f },
+ { "wreathproduct", 0x2240 },
+ { "notsimilar", 0x2241 },
+ { "minustilde", 0x2242 },
+ { "asymptequal", 0x2243 },
+ { "notasymptequal", 0x2244 },
+ { "approxorequal", 0x2245 },
+ { "approxnotequal", 0x2246 },
+ { "notapproxequal", 0x2247 },
+ { "almostequal", 0x2248 },
+ { "notalmostequal", 0x2249 },
+ { "almostorequal", 0x224a },
+ { "tildetrpl", 0x224b },
+ { "equivasymptotic", 0x224d },
+ { "geomequivalent", 0x224e },
+ { "difference", 0x224f },
+ { "approachlimit", 0x2250 },
+ { "geomequal", 0x2251 },
+ { "imageorapproxequal", 0x2253 },
+ { "colonequal", 0x2254 },
+ { "equalcolon", 0x2255 },
+ { "ringinequal", 0x2256 },
+ { "ringequal", 0x2257 },
+ { "corresponds", 0x2258 },
+ { "estimates", 0x2259 },
+ { "equiangular", 0x225a },
+ { "starequal", 0x225b },
+ { "deltaequal", 0x225c },
+ { "definequal", 0x225d },
+ { "measurequal", 0x225e },
+ { "questionequal", 0x225f },
+ { "notequivalence", 0x2262 },
+ { "strictequivalence", 0x2263 },
+ { "lessdblequal", 0x2266 },
+ { "greaterdblequal", 0x2267 },
+ { "lessnotdblequal", 0x2268 },
+ { "greaternotdblequal", 0x2269 },
+ { "lessmuch", 0x226a },
+ { "greatermuch", 0x226b },
+ { "between", 0x226c },
+ { "notequivasymptotic", 0x226d },
+ { "notlessequal", 0x2270 },
+ { "notgreaterequal", 0x2271 },
+ { "lessequivlnt", 0x2272 },
+ { "greaterequivlnt", 0x2273 },
+ { "notlessequivlnt", 0x2274 },
+ { "notgreaterequivlnt", 0x2275 },
+ { "notlessgreater", 0x2278 },
+ { "notgreaterless", 0x2279 },
+ { "follows", 0x227b },
+ { "precedesequal", 0x227c },
+ { "followsequal", 0x227d },
+ { "precedequivlnt", 0x227e },
+ { "followsequivlnt", 0x227f },
+ { "notpreceeds", 0x2280 },
+ { "notfollows", 0x2281 },
+ { "notpropersubset", 0x2284 },
+ { "notpropersuperset", 0x2285 },
+ { "notreflexsubset", 0x2288 },
+ { "notreflexsuperset", 0x2289 },
+ { "multiset", 0x228c },
+ { "multiplymultiset", 0x228d },
+ { "unionmulti", 0x228e },
+ { "squareimage", 0x228f },
+ { "squareoriginal", 0x2290 },
+ { "subsetsqequal", 0x2291 },
+ { "supersetsqequal", 0x2292 },
+ { "intersectionsq", 0x2293 },
+ { "unionsq", 0x2294 },
+ { "circleminus", 0x2296 },
+ { "circledivide", 0x2298 },
+ { "circledot", 0x2299 },
+ { "circlering", 0x229a },
+ { "circleasterisk", 0x229b },
+ { "circleequal", 0x229c },
+ { "circlevertbar", 0x229d },
+ { "squareplus", 0x229e },
+ { "squareminus", 0x229f },
+ { "squaremultiply", 0x22a0 },
+ { "squaredot", 0x22a1 },
+ { "turnstileleft", 0x22a2 },
+ { "turnstileright", 0x22a3 },
+ { "latticetop", 0x22a4 },
+ { "assertion", 0x22a6 },
+ { "truestate", 0x22a7 },
+ { "satisfy", 0x22a8 },
+ { "force", 0x22a9 },
+ { "tacktrpl", 0x22aa },
+ { "forceextr", 0x22ab },
+ { "notturnstileleft", 0x22ac },
+ { "notsatisfy", 0x22ad },
+ { "notforce", 0x22ae },
+ { "notforceextr", 0x22af },
+ { "lowerrank", 0x22b0 },
+ { "higherrank", 0x22b1 },
+ { "triangleright", 0x22b2 },
+ { "triangleleft", 0x22b3 },
+ { "triangleftequal", 0x22b4 },
+ { "triangrightequal", 0x22b5 },
+ { "original", 0x22b6 },
+ { "image", 0x22b7 },
+ { "multimap", 0x22b8 },
+ { "hermitconjmatrix", 0x22b9 },
+ { "intercal", 0x22ba },
+ { "xor", 0x22bb },
+ { "nand", 0x22bc },
+ { "nor", 0x22bd },
+ { "rightanglearc", 0x22be },
+ { "narylogicaland", 0x22c0 },
+ { "narylogicalor", 0x22c1 },
+ { "naryintersection", 0x22c2 },
+ { "naryunion", 0x22c3 },
+ { "diamondmath", 0x22c4 },
+ { "divideonmultiply", 0x22c7 },
+ { "bowtie", 0x22c8 },
+ { "multicloseleft", 0x22c9 },
+ { "multicloseright", 0x22ca },
+ { "multiopenleft", 0x22cb },
+ { "multiopenright", 0x22cc },
+ { "revasymptequal", 0x22cd },
+ { "curlor", 0x22ce },
+ { "curland", 0x22cf },
+ { "subsetdbl", 0x22d0 },
+ { "supersetdbl", 0x22d1 },
+ { "uniondbl", 0x22d2 },
+ { "intersectiondbl", 0x22d3 },
+ { "fork", 0x22d4 },
+ { "equalparallel", 0x22d5 },
+ { "lessdot", 0x22d6 },
+ { "greaterdot", 0x22d7 },
+ { "verymuchless", 0x22d8 },
+ { "verymuchgreater", 0x22d9 },
+ { "lessequalgreater", 0x22da },
+ { "greaterequalless", 0x22db },
+ { "equalless", 0x22dc },
+ { "equalgreater", 0x22dd },
+ { "equalprecedes", 0x22de },
+ { "equalfollows", 0x22df },
+ { "preceedsnotequal", 0x22e0 },
+ { "followsnotequal", 0x22e1 },
+ { "notsubsetsqequal", 0x22e2 },
+ { "notsupersetsqequal", 0x22e3 },
+ { "sqimageornotequal", 0x22e4 },
+ { "sqoriginornotequal", 0x22e5 },
+ { "lessnotequivlnt", 0x22e6 },
+ { "greaternotequivlnt", 0x22e7 },
+ { "preceedsnotsimilar", 0x22e8 },
+ { "followsnotequivlnt", 0x22e9 },
+ { "nottriangleleft", 0x22ea },
+ { "nottriangleright", 0x22eb },
+ { "nottriangleleftequal", 0x22ec },
+ { "nottrianglerightequal", 0x22ed },
+ { "vertellipsis", 0x22ee },
+ { "midhorizellipsis", 0x22ef },
+ { "upslopeellipsis", 0x22f0 },
+ { "downslopeellipsis", 0x22f1 },
+ { "perspcorrespond", 0x2306 },
+ { "ceilingleft", 0x2308 },
+ { "ceilingright", 0x2309 },
+ { "floorleft", 0x230a },
+ { "floorright", 0x230b },
+ { "slurabove", 0x2322 },
+ { "slurbelow", 0x2323 },
+ { "null", 0x2400 },
+ { "startofhead", 0x2401 },
+ { "starttext", 0x2402 },
+ { "endtext", 0x2403 },
+ { "endtrans", 0x2404 },
+ { "enquiry", 0x2405 },
+ { "acknowledge", 0x2406 },
+ { "bell", 0x2407 },
+ { "backspace", 0x2408 },
+ { "horiztab", 0x2409 },
+ { "linefeed", 0x240a },
+ { "verttab", 0x240b },
+ { "formfeed", 0x240c },
+ { "shiftout", 0x240e },
+ { "shiftin", 0x240f },
+ { "datalinkescape", 0x2410 },
+ { "devcon1", 0x2411 },
+ { "devcon2", 0x2412 },
+ { "devcon3", 0x2413 },
+ { "devcon4", 0x2414 },
+ { "negacknowledge", 0x2415 },
+ { "synch", 0x2416 },
+ { "endtransblock", 0x2417 },
+ { "cancel", 0x2418 },
+ { "endmedium", 0x2419 },
+ { "substitute", 0x241a },
+ { "escape", 0x241b },
+ { "fileseparator", 0x241c },
+ { "groupseparator", 0x241d },
+ { "recordseparator", 0x241e },
+ { "unitseparator", 0x241f },
+ { "spaceliteral", 0x2420 },
+ { "delete", 0x2421 },
+ { "blankb", 0x2422 },
+ { "spaceopenbox", 0x2423 },
+ { "newline", 0x2424 },
+ { "lthorizform", 0x2500 },
+ { "hvhorizform", 0x2501 },
+ { "ltvertform", 0x2502 },
+ { "hvvertform", 0x2503 },
+ { "ltdashtriphorizform", 0x2504 },
+ { "hvdashtriphorizform", 0x2505 },
+ { "ltdashtripvertform", 0x2506 },
+ { "hvdashtripvertform", 0x2507 },
+ { "ltdashquadhorizform", 0x2508 },
+ { "hvdashquadhorizform", 0x2509 },
+ { "ltdashquadvertform", 0x250a },
+ { "hvdashquadvertform", 0x250b },
+ { "ltdnrtform", 0x250c },
+ { "dnltrthvform", 0x250d },
+ { "dnhvrtltform", 0x250e },
+ { "hvdnrtform", 0x250f },
+ { "ltdnleftform", 0x2510 },
+ { "dnltlefthvform", 0x2511 },
+ { "dnhvleftltform", 0x2512 },
+ { "hvdnleftform", 0x2513 },
+ { "ltuprtform", 0x2514 },
+ { "upltrthvform", 0x2515 },
+ { "uphvrtltform", 0x2516 },
+ { "hvuprtform", 0x2517 },
+ { "ltupleftform", 0x2518 },
+ { "upltlefthvform", 0x2519 },
+ { "uphvleftltform", 0x251a },
+ { "hvupleftform", 0x251b },
+ { "ltvertrightform", 0x251c },
+ { "vertltrthvform", 0x251d },
+ { "uphvrtdnltform", 0x251e },
+ { "dnhvrtupltform", 0x251f },
+ { "verthvrtltform", 0x2520 },
+ { "dnltrtuphvform", 0x2521 },
+ { "upltrtdnhvform", 0x2522 },
+ { "hvvertrtform", 0x2523 },
+ { "ltvertleftform", 0x2524 },
+ { "vtltlefthvform", 0x2525 },
+ { "uphvleftdnltform", 0x2526 },
+ { "dnhvleftupltform", 0x2527 },
+ { "verthvleftltform", 0x2528 },
+ { "dnltleftuphvform", 0x2529 },
+ { "upltleftdnhvform", 0x252a },
+ { "hvvertleftform", 0x252b },
+ { "ltdnhorizform", 0x252c },
+ { "lefthvrtdnltform", 0x252d },
+ { "rthvleftdnltform", 0x252e },
+ { "dnlthorizhvform", 0x252f },
+ { "dnhvhorizltform", 0x2530 },
+ { "rtltrtdnhvform", 0x2531 },
+ { "leftltrtdnhvform", 0x2532 },
+ { "hvdnhorizform", 0x2533 },
+ { "ltuphorizform", 0x2534 },
+ { "lefthvrtupltform", 0x2535 },
+ { "rthvleftupltform", 0x2536 },
+ { "uplthorizhvform", 0x2537 },
+ { "uphvhorizltform", 0x2538 },
+ { "rtltleftuphvform", 0x2539 },
+ { "leftltrtuphvform", 0x253a },
+ { "hvuphorizform", 0x253b },
+ { "ltverthorizform", 0x253c },
+ { "lefthvrtvertltform", 0x253d },
+ { "rthvleftvertltform", 0x253e },
+ { "vertlthorizhvform", 0x253f },
+ { "uphvdnhorizltform", 0x2540 },
+ { "dnhvuphorizltform", 0x2541 },
+ { "verthvhorizltform", 0x2542 },
+ { "leftuphvrtdnltform", 0x2543 },
+ { "rtuphvleftdnltform", 0x2544 },
+ { "leftdnhvrtupltform", 0x2545 },
+ { "rtdnhvleftupltform", 0x2546 },
+ { "dnltuphorizhvform", 0x2547 },
+ { "upltdnhorizhvform", 0x2548 },
+ { "rtltleftverthvform", 0x2549 },
+ { "leftltrtverthvform", 0x254a },
+ { "hvverthorizform", 0x254b },
+ { "ltdashdblhorizform", 0x254c },
+ { "hvdashdblhorizform", 0x254d },
+ { "ltdashdblvertform", 0x254e },
+ { "hvdashdblvertform", 0x254f },
+ { "horizdblbar", 0x2550 },
+ { "vertdblbar", 0x2551 },
+ { "dnrtdblform", 0x2552 },
+ { "dndblrtform", 0x2553 },
+ { "dbldnrtform", 0x2554 },
+ { "dnleftdblform", 0x2555 },
+ { "dndblleftform", 0x2556 },
+ { "dbldnleftform", 0x2557 },
+ { "uprtdblform", 0x2558 },
+ { "updblrtform", 0x2559 },
+ { "dbluprtform", 0x255a },
+ { "upleftdblform", 0x255b },
+ { "updblleftform", 0x255c },
+ { "dblupleftform", 0x255d },
+ { "vertrtdblform", 0x255e },
+ { "vertdblrtform", 0x255f },
+ { "dblvertrtform", 0x2560 },
+ { "vertleftdblform", 0x2561 },
+ { "vertdblleftform", 0x2562 },
+ { "dblvertleftform", 0x2563 },
+ { "dnhorizdblform", 0x2564 },
+ { "dndblhorizform", 0x2565 },
+ { "dbldnhorizform", 0x2566 },
+ { "uphorizdblform", 0x2567 },
+ { "updblhorizform", 0x2568 },
+ { "dbluphorizform", 0x2569 },
+ { "verthorizdblform", 0x256a },
+ { "vertdblhorizform", 0x256b },
+ { "dblverthorizform", 0x256c },
+ { "ltarcdnrtform", 0x256d },
+ { "ltarcdnleftform", 0x256e },
+ { "ltarcupleftform", 0x256f },
+ { "ltarcuprtform", 0x2570 },
+ { "forwarddiagonal", 0x2571 },
+ { "backwarddiagonal", 0x2572 },
+ { "ltdiagonalcross", 0x2573 },
+ { "dneighthblock", 0x2581 },
+ { "dnquarterblock", 0x2582 },
+ { "dnthreeeighthblock", 0x2583 },
+ { "dnfiveeighthblock", 0x2585 },
+ { "dnthreequarterblock", 0x2586 },
+ { "dnseveneighthblock", 0x2587 },
+ { "lfseveneighthblock", 0x2589 },
+ { "lfthreequarterblock", 0x258a },
+ { "lffiveeighthblock", 0x258b },
+ { "lfthreeeighthblock", 0x258d },
+ { "lfquarterblock", 0x258e },
+ { "lfeighthblock", 0x258f },
+ { "upeighthblock", 0x2594 },
+ { "rteighthblock", 0x2595 },
+ { "box", 0x25a1 },
+ { "boxrounded", 0x25a2 },
+ { "boxnested", 0x25a3 },
+ { "boxhorizhatch", 0x25a4 },
+ { "boxverthatch", 0x25a5 },
+ { "boxcrosshatch", 0x25a6 },
+ { "boxleftdiaghatch", 0x25a7 },
+ { "boxrtdiaghatch", 0x25a8 },
+ { "boxcrossdiaghatch", 0x25a9 },
+ { "smallboxfilled", 0x25aa },
+ { "smallbox", 0x25ab },
+ { "rectangle", 0x25ad },
+ { "filledvertrect", 0x25ae },
+ { "vertrectangle", 0x25af },
+ { "filledparallelogram", 0x25b0 },
+ { "parallelogram", 0x25b1 },
+ { "triangle", 0x25b3 },
+ { "smalltrianglesld", 0x25b4 },
+ { "smalltriangle", 0x25b5 },
+ { "trianglerightsld1", 0x25b6 },
+ { "triangleright1", 0x25b7 },
+ { "smalltrianglerightsld", 0x25b8 },
+ { "smalltriangleright", 0x25b9 },
+ { "triagrtopen", 0x25bb },
+ { "triangleinv", 0x25bd },
+ { "smalltriangleinvsld", 0x25be },
+ { "smalltriangleinv", 0x25bf },
+ { "triangleleftsld1", 0x25c0 },
+ { "triangleleft1", 0x25c1 },
+ { "smalltriangleleftsld", 0x25c2 },
+ { "smalltriangleleft", 0x25c3 },
+ { "triaglfopen", 0x25c5 },
+ { "diamondrhombsolid", 0x25c6 },
+ { "diamondrhomb", 0x25c7 },
+ { "diamondrhombnested", 0x25c8 },
+ { "circledash", 0x25cc },
+ { "circleverthatch", 0x25cd },
+ { "circlesolid", 0x25cf },
+ { "circleleftsld", 0x25d0 },
+ { "circlerightsld", 0x25d1 },
+ { "circlebottomsld", 0x25d2 },
+ { "circletopsld", 0x25d3 },
+ { "circlenesld", 0x25d4 },
+ { "circlenwopen", 0x25d5 },
+ { "semicircleleftsld", 0x25d6 },
+ { "semicirclelertsld", 0x25d7 },
+ { "invsemicircleup", 0x25da },
+ { "invsemicircledn", 0x25db },
+ { "nwquadarc", 0x25dc },
+ { "nequadarc", 0x25dd },
+ { "sequadarc", 0x25de },
+ { "swquadarc", 0x25df },
+ { "toparc", 0x25e0 },
+ { "bottomarc", 0x25e1 },
+ { "trianglesesld", 0x25e2 },
+ { "triangleswsld", 0x25e3 },
+ { "tranglenwsld", 0x25e4 },
+ { "trianglenesld", 0x25e5 },
+ { "squareleftsld", 0x25e7 },
+ { "squarerightsld", 0x25e8 },
+ { "squarenwsld", 0x25e9 },
+ { "squaresesld", 0x25ea },
+ { "squarevertbisect", 0x25eb },
+ { "triangledot", 0x25ec },
+ { "triangleleftsld", 0x25ed },
+ { "trianglerightsld", 0x25ee },
+ { "heartopen", 0x2661 },
+ { "diamondopen", 0x2662 },
+ { "spadeopen", 0x2664 },
+ { "Omegaiotasubleniscircumflex", 0x1fae },
+ { "Omegaleniscircumflex", 0x1f6e },
+ { "Upsilonaspercircumflex", 0x1f5f },
+ { "dieresiscircumflex", 0x1fc1 },
+ { "leniscircumflex", 0x1fcf },
+ { "aspercircumflex", 0x1fdf },
+ { "alphaleniscircumflex", 0x1f06 },
+ { "alphaaspercircumflex", 0x1f07 },
+ { "etaleniscircumflex", 0x1f26 },
+ { "etaaspercircumflex", 0x1f27 },
+ { "iotaleniscircumflex", 0x1f36 },
+ { "iotaaspercircumflex", 0x1f37 },
+ { "upsilonleniscircumflex", 0x1f56 },
+ { "upsilonaspercircumflex", 0x1f57 },
+ { "omegaleniscircumflex", 0x1f66 },
+ { "omegaaspercircumflex", 0x1f67 },
+ { "alphaiotasubleniscircumflex", 0x1f86 },
+ { "alphaiotasubaspercircumflex", 0x1f87 },
+ { "etaiotasubleniscircumflex", 0x1f96 },
+ { "etaiotasubaspercircumflex", 0x1f97 },
+ { "omegaiotasubleniscircumflex", 0x1fa6 },
+ { "omegaiotasubaspercircumflex", 0x1fa7 },
+ { "alphacircumflex", 0x1fb6 },
+ { "alphaiotasubcircumflex", 0x1fb7 },
+ { "etacircumflex", 0x1fc6 },
+ { "etaiotasubcircumflex", 0x1fc7 },
+ { "iotacircumflex", 0x1fd6 },
+ { "iotadieresiscircumflex", 0x1fd7 },
+ { "upsiloncircumflex", 0x1fe6 },
+ { "omegacircumflex", 0x1ff6 },
+ { "omegaiotasubcircumflex", 0x1ff7 },
+ { "upsilondieresiscircumflex", 0x1fe7 },
+ { "dialytika", 0x0308 },
+ { "koronis", 0x1fbd },
+ { "prosgegrammeni", 0x1fbe },
+ { "psili", 0x1fbf },
+ { "perispomeni", 0x1fc0 },
+ { "varia", 0x1fef },
+ { "oxia", 0x1ffd },
+ { "dasia", 0x1ffe },
+ { "Alphasmall", 0xf500 },
+ { "Betasmall", 0xf501 },
+ { "Gammasmall", 0xf502 },
+ { "Deltasmall", 0xf503 },
+ { "Epsilonsmall", 0xf504 },
+ { "Zetasmall", 0xf505 },
+ { "Etasmall", 0xf506 },
+ { "Thetasmall", 0xf507 },
+ { "Iotasmall", 0xf508 },
+ { "Kappasmall", 0xf509 },
+ { "Lambdasmall", 0xf50a },
+ { "Musmall", 0xf50b },
+ { "Nusmall", 0xf50c },
+ { "Xismall", 0xf50d },
+ { "Omicronsmall", 0xf50e },
+ { "Pismall", 0xf50f },
+ { "Rhosmall", 0xf510 },
+ { "Sigmasmall", 0xf512 },
+ { "Tausmall", 0xf513 },
+ { "Upsilonsmall", 0xf514 },
+ { "Phismall", 0xf515 },
+ { "Chismall", 0xf516 },
+ { "Psismall", 0xf517 },
+ { "Omegasmall", 0xf518 },
+ { "Iotadieresissmall", 0xf519 },
+ { "Upsilondieresissmall", 0xf51a },
+ { "uni2A0B.lgdisplay", 0xea57 },
+ { "uni2A0B.uplgdisplay", 0xea57 },
+ { "uni2A15.lgdisplay", 0xe376 },
+ { "uni2A15.uplgdisplay", 0xe376 },
+ { "uni2A16.lgdisplay", 0xe377 },
+ { "uni2A16.uplgdisplay", 0xe377 },
+ { "uni2A10.lgdisplay", 0xe395 },
+ { "uni2A10.uplgdisplay", 0xe395 },
+ { "uni2A12.lgdisplay", 0xe397 },
+ { "uni2A12.uplgdisplay", 0xe397 },
+ { "uni2A13.lgdisplay", 0xe398 },
+ { "uni2A13.uplgdisplay", 0xe398 },
+ { "uni2A14.lgdisplay", 0xe399 },
+ { "uni2A14.uplgdisplay", 0xe399 },
+ { "uni2A17.lgdisplay", 0xe39a },
+ { "uni2A17.uplgdisplay", 0xe39a },
+ { "uni2A11.uplgdisplay", 0xe39b },
+ { "uni2A11.lgdisplay", 0xe39b },
+ { "uni2A0F.lgdisplay", 0xe3d3 },
+ { "uni2A0F.uplgdisplay", 0xe3d3 },
+/* From Richard Kinch's TeX list of glyph aliases */
+ { "fscript", 0x192 },
+ { "fraction1", 0x2215 },
+ { "negationslash", 0x2215 },
+ { "circleR", 0xae },
+ { "circlecopyrt", 0xa9 },
+ { "smile", 0x263a },
+ { "Ifractur", 0x2111 },
+ { "Rfractur", 0x211C },
+ { "Omegainv", 0x2127 },
+ { "mho", 0x2127 },
+ { "alephmath", 0x2135 },
+ { "beth", 0x2136 },
+ { "bethmath", 0x2136 },
+ { "gimelmath", 0x2137 },
+ { "daleth", 0x2138 },
+ { "daletmath", 0x2138 },
+ { "arrowbothv", 0x2195 },
+ { "prime1", 0x2032 },
+ { "primerev1", 0x2035 },
+ { "primereverse", 0x2035 },
+ { "followsequal1", 0x227d },
+ { "similarequal", 0x2243 },
+ { "square", 0x25a1 },
+ { "squaresolid", 0x25a0 },
+ { "squaresmallsolid", 0x25aa },
+ { "diamondsolid", 0x25c6 },
+ { "clockwise", 0x21bb },
+ { "anticlockwise", 0x21ba },
+ { "forces", 0x22a9 },
+ { "forcesbar", 0x22aa },
+ { "satisfies", 0x22a8 },
+ { "dblarrowdwn", 0x21ca },
+ { "shiftleft", 0x2196 },
+ { "shiftright", 0x2197 },
+ { "squiggleright", 0x21dd },
+ { "squiggleleft", 0x21dc },
+ { "squiggleleftright", 0x21ad },
+ { "curlyleft", 0x21ab },
+ { "curlyright", 0x21ac },
+ { "followsorequal", 0x227d },
+ { "equalsdots", 0x2251 },
+ { "defines", 0x225c },
+ { "ng", 0x014b },
+ { "Ng", 0x014a },
+ { "visiblespace", 0x2420 },
+ { "dslash", 0x0111 },
+ { "tie1", 0x2040 },
+ { "arrowdblbothv", 0x21d5 },
+ { "precedesequal1", 0x227c },
+ { "greaterorsimilar", 0x2273 },
+ { "precedesorequal", 0x227e },
+ { "lessorsimilar", 0x2272 },
+ { "equalorgreater", 0x22dd },
+ { "lessorequalslant", 0x2264 },
+ { "equaldotrightleft", 0x2253 },
+ { "equaldotleftright", 0x2252 },
+ { "followsorcurly", 0x227d },
+ { "greaterorequalslant", 0x2265 },
+ { "trianglerightequal", 0x22b5 },
+ { "triangleleftequal", 0x22b4 },
+ { "triangledownsld", 0x25bc },
+ { "arrowaxisright", 0x2192 },
+ { "arrowaxisleft", 0x2190 },
+ { "trianglesolid", 0x25b2 },
+ { "greaterlessequal", 0x22db },
+ { "orunderscore", 0x22bb },
+ { "frown", 0x2322 },
+ { "uprise", 0x22cf },
+ { "downfall", 0x22ce },
+ { "subsetdblequal", 0x2286 },
+ { "supersetdblequal", 0x2287 },
+ { "Finv", 0x2132 },
+ { "notarrowboth", 0x21ae },
+ { "archleftdown", 0x21b6 },
+ { "archrightdown", 0x21b7 },
+ { "notdblarrowleft", 0x21cd },
+ { "notdblarrowboth", 0x21ce },
+ { "notdblarrowright", 0x21cf },
+ { "epsiloninv", 0x220a },
+ { "equalorsimilar", 0x2242 },
+ { "notprecedes", 0x2280 },
+ { "notsubseteql", 0x2288 },
+ { "notsuperseteql", 0x2289 },
+ { "subsetnoteql", 0x228a },
+ { "supersetnoteql", 0x228b },
+ { "notturnstile", 0x22ac },
+ { "notforcesextra", 0x22af },
+ { "dividemultiply", 0x22c7 },
+ { "notprecedesoreql", 0x22e0 },
+ { "notfollowsoreql", 0x22e1 },
+ { "lessornotsimilar", 0x22e6 },
+ { "greaterornotsimilar", 0x22e7 },
+ { "precedeornoteqvlnt", 0x22e8 },
+ { "followornoteqvlnt", 0x22e9 },
+ { "nottriangeqlleft", 0x22ec },
+ { "nottriangeqlright", 0x22ed },
+ { "angbracketleft", 0x3008 },
+ { "angbracketright", 0x3009 },
+ { "check", 0x2713 },
+ { "circleS", 0x24c8 },
+ { "rightanglenw", 0x250c },
+ { "rightanglene", 0x2510 },
+ { "rightanglesw", 0x2514 },
+ { "rightanglese", 0x2518 },
+ { "Yen", 0x00a5 },
+ { "permill", 0x2030 },
+ { "recipe", 0x211e },
+ { "pertenmill", 0x2031 },
+ { "lnot", 0x00ac },
+ { "circleP", 0x2117 },
+ { "surd", 0x221a },
+ { "asciigrave", 0x60 },
+ { "asciigrave", 0x60 },
+ { "asciiacute", 0xb4 },
+ { "asciidieresis", 0xa8 },
+ { "pilcrow", 0xb6 },
+/* Useful names to use to find glyphs */
+ { "circumflexcomb", 0x302 },
+ { "macroncomb", 0x304 },
+ { "brevecomb", 0x306 },
+ { "diaeresiscomb", 0x308 },
+ { "caroncomb", 0x30c },
+ { "vrachycomb", 0x306 },
+ { "psilicomb", 0x313 },
+ { "dasiacomb", 0x314 },
+ { "psilivaria", 0x1fcd },
+ { "psilioxia", 0x1fce },
+ { "psiliperispomeni", 0x1fcf },
+ { "dasiavaria", 0x1fdd },
+ { "dasiaoxia", 0x1fde },
+ { "dasiaperispomeni", 0x1fdf },
+ { "dialytikavaria", 0x1fed },
+ { "dialytikaoxia", 0x1fee },
+ { "dialytikaperispomeni", 0x1fc1 },
+/* Adobe spells diaeresis the American way, as dieresis */
+ { "diaeresis", 0xa8 },
+ { "Adiaeresis", 0xC4 },
+ { "Ediaeresis", 0xCB },
+ { "Idiaeresis", 0xCF },
+ { "Odiaeresis", 0xD6 },
+ { "Udiaeresis", 0xDC },
+ { "adiaeresis", 0xE4 },
+ { "ediaeresis", 0xEB },
+ { "idiaeresis", 0xEF },
+ { "odiaeresis", 0xF6 },
+ { "udiaeresis", 0xFC },
+ { "Ydiaeresis", 0x178 },
+ { "diaeresistonos", 0x385 },
+ { "iotadiaeresistonos", 0x390 },
+ { "Iotadiaeresis", 0x3AA },
+ { "Upsilondiaeresis", 0x3AB },
+ { "upsilondiaeresistonos", 0x3B0 },
+ { "iotadiaeresis", 0x3CA },
+ { "upsilondiaeresis", 0x3CB },
+ { "Wdiaeresis", 0x1e84 },
+ { "wdiaeresis", 0x1e85 },
+ { "ETH", 0xd0 },
+ { "THORN", 0xde },
+ { "ssharp", 0xdf },
+ { "Ooblique", 0xd8 },
+ { "notsign", 0xac },
+/* Sun has used "masculine" for ordmasculine */
+ {NULL}
+};
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/ofl.h b/Build/source/libs/luafontforge/fontforge/fontforge/ofl.h
new file mode 100644
index 00000000000..bafa27e9e87
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/ofl.h
@@ -0,0 +1,7 @@
+#include "splinefont.h"
+
+extern struct str_lang_data {
+ enum ttfnames strid;
+ int lang;
+ char **data;
+} ofl_str_lang_data[];
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/parsepfa.c b/Build/source/libs/luafontforge/fontforge/fontforge/parsepfa.c
new file mode 100644
index 00000000000..8b18e2a63b5
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/parsepfa.c
@@ -0,0 +1,2762 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ustring.h>
+#include <utype.h>
+
+#ifdef LUA_FF_LIB
+/* no need for iconv here, since PS is 8-bit legacy */
+#define Isspace(a) ((a)==' '|| ((a) >= '\t' && (a) <= '\r'))
+#define Isdigit(a) ((a)>='0' && (a)<='9')
+#define Isalpha(a) (((a)>='a' && (a)<='z') || ((a)>='A' && (a)<='Z'))
+#define Isalnum(a) (Isalpha(a)||Isdigit(a))
+#define Ishexdigit(a) (((a)>='0' && (a)<='9')||((a)>='a' && (a)<='f')||((a)>='A' && (a)<='F'))
+#else
+#define Isspace isspace
+#define Isdigit isdigit
+#define Isalpha isalpha
+#define Isalnum isalnum
+#define Ishexdigit ishexdigit
+#endif
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "psfont.h"
+#include <locale.h>
+
+struct fontparse {
+ FontDict *fd, *mainfd;
+ /* always in font data */
+ unsigned int infi:1;
+ unsigned int inchars:1;
+ unsigned int inprivate:1;
+ unsigned int insubs:1;
+ unsigned int inmetrics: 1;
+ unsigned int inmetrics2: 1;
+ unsigned int inbb: 1;
+ unsigned int inencoding: 1;
+ unsigned int simpleencoding: 1;
+ unsigned int multiline: 1;
+ unsigned int incidsysteminfo: 1;
+ unsigned int inblendfi:1;
+ unsigned int inblendprivate:1;
+ unsigned int skipping_mbf: 1;
+ unsigned int inblend: 1;
+ unsigned int iscid: 1;
+ unsigned int iscff: 1;
+ unsigned int useshexstrings: 1;
+ unsigned int doneencoding: 1;
+ unsigned int ignore: 1;
+ int simple_enc_pos;
+ int instring;
+ int fdindex;
+ char **pending_parse;
+ FILE *sfnts;
+
+ unsigned int alreadycomplained: 1;
+
+ char *vbuf, *vmax, *vpt;
+ int depth;
+};
+
+static void copyenc(char *encoding[256],char *std[256]) {
+ int i;
+ for ( i=0; i<256; ++i )
+ encoding[i] = copy(std[i]);
+}
+
+char *AdobeStandardEncoding[] = {
+/* 0000 */ ".notdef",
+/* 0001 */ ".notdef",
+/* 0002 */ ".notdef",
+/* 0003 */ ".notdef",
+/* 0004 */ ".notdef",
+/* 0005 */ ".notdef",
+/* 0006 */ ".notdef",
+/* 0007 */ ".notdef",
+/* 0008 */ ".notdef",
+/* 0009 */ ".notdef",
+/* 000a */ ".notdef",
+/* 000b */ ".notdef",
+/* 000c */ ".notdef",
+/* 000d */ ".notdef",
+/* 000e */ ".notdef",
+/* 000f */ ".notdef",
+/* 0010 */ ".notdef",
+/* 0011 */ ".notdef",
+/* 0012 */ ".notdef",
+/* 0013 */ ".notdef",
+/* 0014 */ ".notdef",
+/* 0015 */ ".notdef",
+/* 0016 */ ".notdef",
+/* 0017 */ ".notdef",
+/* 0018 */ ".notdef",
+/* 0019 */ ".notdef",
+/* 001a */ ".notdef",
+/* 001b */ ".notdef",
+/* 001c */ ".notdef",
+/* 001d */ ".notdef",
+/* 001e */ ".notdef",
+/* 001f */ ".notdef",
+/* 0020 */ "space",
+/* 0021 */ "exclam",
+/* 0022 */ "quotedbl",
+/* 0023 */ "numbersign",
+/* 0024 */ "dollar",
+/* 0025 */ "percent",
+/* 0026 */ "ampersand",
+/* 0027 */ "quoteright",
+/* 0028 */ "parenleft",
+/* 0029 */ "parenright",
+/* 002a */ "asterisk",
+/* 002b */ "plus",
+/* 002c */ "comma",
+/* 002d */ "hyphen",
+/* 002e */ "period",
+/* 002f */ "slash",
+/* 0030 */ "zero",
+/* 0031 */ "one",
+/* 0032 */ "two",
+/* 0033 */ "three",
+/* 0034 */ "four",
+/* 0035 */ "five",
+/* 0036 */ "six",
+/* 0037 */ "seven",
+/* 0038 */ "eight",
+/* 0039 */ "nine",
+/* 003a */ "colon",
+/* 003b */ "semicolon",
+/* 003c */ "less",
+/* 003d */ "equal",
+/* 003e */ "greater",
+/* 003f */ "question",
+/* 0040 */ "at",
+/* 0041 */ "A",
+/* 0042 */ "B",
+/* 0043 */ "C",
+/* 0044 */ "D",
+/* 0045 */ "E",
+/* 0046 */ "F",
+/* 0047 */ "G",
+/* 0048 */ "H",
+/* 0049 */ "I",
+/* 004a */ "J",
+/* 004b */ "K",
+/* 004c */ "L",
+/* 004d */ "M",
+/* 004e */ "N",
+/* 004f */ "O",
+/* 0050 */ "P",
+/* 0051 */ "Q",
+/* 0052 */ "R",
+/* 0053 */ "S",
+/* 0054 */ "T",
+/* 0055 */ "U",
+/* 0056 */ "V",
+/* 0057 */ "W",
+/* 0058 */ "X",
+/* 0059 */ "Y",
+/* 005a */ "Z",
+/* 005b */ "bracketleft",
+/* 005c */ "backslash",
+/* 005d */ "bracketright",
+/* 005e */ "asciicircum",
+/* 005f */ "underscore",
+/* 0060 */ "quoteleft",
+/* 0061 */ "a",
+/* 0062 */ "b",
+/* 0063 */ "c",
+/* 0064 */ "d",
+/* 0065 */ "e",
+/* 0066 */ "f",
+/* 0067 */ "g",
+/* 0068 */ "h",
+/* 0069 */ "i",
+/* 006a */ "j",
+/* 006b */ "k",
+/* 006c */ "l",
+/* 006d */ "m",
+/* 006e */ "n",
+/* 006f */ "o",
+/* 0070 */ "p",
+/* 0071 */ "q",
+/* 0072 */ "r",
+/* 0073 */ "s",
+/* 0074 */ "t",
+/* 0075 */ "u",
+/* 0076 */ "v",
+/* 0077 */ "w",
+/* 0078 */ "x",
+/* 0079 */ "y",
+/* 007a */ "z",
+/* 007b */ "braceleft",
+/* 007c */ "bar",
+/* 007d */ "braceright",
+/* 007e */ "asciitilde",
+/* 007f */ ".notdef",
+/* 0080 */ ".notdef",
+/* 0081 */ ".notdef",
+/* 0082 */ ".notdef",
+/* 0083 */ ".notdef",
+/* 0084 */ ".notdef",
+/* 0085 */ ".notdef",
+/* 0086 */ ".notdef",
+/* 0087 */ ".notdef",
+/* 0088 */ ".notdef",
+/* 0089 */ ".notdef",
+/* 008a */ ".notdef",
+/* 008b */ ".notdef",
+/* 008c */ ".notdef",
+/* 008d */ ".notdef",
+/* 008e */ ".notdef",
+/* 008f */ ".notdef",
+/* 0090 */ ".notdef",
+/* 0091 */ ".notdef",
+/* 0092 */ ".notdef",
+/* 0093 */ ".notdef",
+/* 0094 */ ".notdef",
+/* 0095 */ ".notdef",
+/* 0096 */ ".notdef",
+/* 0097 */ ".notdef",
+/* 0098 */ ".notdef",
+/* 0099 */ ".notdef",
+/* 009a */ ".notdef",
+/* 009b */ ".notdef",
+/* 009c */ ".notdef",
+/* 009d */ ".notdef",
+/* 009e */ ".notdef",
+/* 009f */ ".notdef",
+/* 00a0 */ ".notdef",
+/* 00a1 */ "exclamdown",
+/* 00a2 */ "cent",
+/* 00a3 */ "sterling",
+/* 00a4 */ "fraction",
+/* 00a5 */ "yen",
+/* 00a6 */ "florin",
+/* 00a7 */ "section",
+/* 00a8 */ "currency",
+/* 00a9 */ "quotesingle",
+/* 00aa */ "quotedblleft",
+/* 00ab */ "guillemotleft",
+/* 00ac */ "guilsinglleft",
+/* 00ad */ "guilsinglright",
+/* 00ae */ "fi",
+/* 00af */ "fl",
+/* 00b0 */ ".notdef",
+/* 00b1 */ "endash",
+/* 00b2 */ "dagger",
+/* 00b3 */ "daggerdbl",
+/* 00b4 */ "periodcentered",
+/* 00b5 */ ".notdef",
+/* 00b6 */ "paragraph",
+/* 00b7 */ "bullet",
+/* 00b8 */ "quotesinglbase",
+/* 00b9 */ "quotedblbase",
+/* 00ba */ "quotedblright",
+/* 00bb */ "guillemotright",
+/* 00bc */ "ellipsis",
+/* 00bd */ "perthousand",
+/* 00be */ ".notdef",
+/* 00bf */ "questiondown",
+/* 00c0 */ ".notdef",
+/* 00c1 */ "grave",
+/* 00c2 */ "acute",
+/* 00c3 */ "circumflex",
+/* 00c4 */ "tilde",
+/* 00c5 */ "macron",
+/* 00c6 */ "breve",
+/* 00c7 */ "dotaccent",
+/* 00c8 */ "dieresis",
+/* 00c9 */ ".notdef",
+/* 00ca */ "ring",
+/* 00cb */ "cedilla",
+/* 00cc */ ".notdef",
+/* 00cd */ "hungarumlaut",
+/* 00ce */ "ogonek",
+/* 00cf */ "caron",
+/* 00d0 */ "emdash",
+/* 00d1 */ ".notdef",
+/* 00d2 */ ".notdef",
+/* 00d3 */ ".notdef",
+/* 00d4 */ ".notdef",
+/* 00d5 */ ".notdef",
+/* 00d6 */ ".notdef",
+/* 00d7 */ ".notdef",
+/* 00d8 */ ".notdef",
+/* 00d9 */ ".notdef",
+/* 00da */ ".notdef",
+/* 00db */ ".notdef",
+/* 00dc */ ".notdef",
+/* 00dd */ ".notdef",
+/* 00de */ ".notdef",
+/* 00df */ ".notdef",
+/* 00e0 */ ".notdef",
+/* 00e1 */ "AE",
+/* 00e2 */ ".notdef",
+/* 00e3 */ "ordfeminine",
+/* 00e4 */ ".notdef",
+/* 00e5 */ ".notdef",
+/* 00e6 */ ".notdef",
+/* 00e7 */ ".notdef",
+/* 00e8 */ "Lslash",
+/* 00e9 */ "Oslash",
+/* 00ea */ "OE",
+/* 00eb */ "ordmasculine",
+/* 00ec */ ".notdef",
+/* 00ed */ ".notdef",
+/* 00ee */ ".notdef",
+/* 00ef */ ".notdef",
+/* 00f0 */ ".notdef",
+/* 00f1 */ "ae",
+/* 00f2 */ ".notdef",
+/* 00f3 */ ".notdef",
+/* 00f4 */ ".notdef",
+/* 00f5 */ "dotlessi",
+/* 00f6 */ ".notdef",
+/* 00f7 */ ".notdef",
+/* 00f8 */ "lslash",
+/* 00f9 */ "oslash",
+/* 00fa */ "oe",
+/* 00fb */ "germandbls",
+/* 00fc */ ".notdef",
+/* 00fd */ ".notdef",
+/* 00fe */ ".notdef",
+/* 00ff */ ".notdef"
+};
+static void setStdEnc(char *encoding[256]) {
+ copyenc(encoding,AdobeStandardEncoding);
+}
+
+static void setLatin1Enc(char *encoding[256]) {
+ static char *latin1enc[] = {
+/* 0000 */ ".notdef",
+/* 0001 */ ".notdef",
+/* 0002 */ ".notdef",
+/* 0003 */ ".notdef",
+/* 0004 */ ".notdef",
+/* 0005 */ ".notdef",
+/* 0006 */ ".notdef",
+/* 0007 */ ".notdef",
+/* 0008 */ ".notdef",
+/* 0009 */ ".notdef",
+/* 000a */ ".notdef",
+/* 000b */ ".notdef",
+/* 000c */ ".notdef",
+/* 000d */ ".notdef",
+/* 000e */ ".notdef",
+/* 000f */ ".notdef",
+/* 0010 */ ".notdef",
+/* 0011 */ ".notdef",
+/* 0012 */ ".notdef",
+/* 0013 */ ".notdef",
+/* 0014 */ ".notdef",
+/* 0015 */ ".notdef",
+/* 0016 */ ".notdef",
+/* 0017 */ ".notdef",
+/* 0018 */ ".notdef",
+/* 0019 */ ".notdef",
+/* 001a */ ".notdef",
+/* 001b */ ".notdef",
+/* 001c */ ".notdef",
+/* 001d */ ".notdef",
+/* 001e */ ".notdef",
+/* 001f */ ".notdef",
+/* 0020 */ "space",
+/* 0021 */ "exclam",
+/* 0022 */ "quotedbl",
+/* 0023 */ "numbersign",
+/* 0024 */ "dollar",
+/* 0025 */ "percent",
+/* 0026 */ "ampersand",
+/* 0027 */ "quoteright",
+/* 0028 */ "parenleft",
+/* 0029 */ "parenright",
+/* 002a */ "asterisk",
+/* 002b */ "plus",
+/* 002c */ "comma",
+/* 002d */ "hyphen",
+/* 002e */ "period",
+/* 002f */ "slash",
+/* 0030 */ "zero",
+/* 0031 */ "one",
+/* 0032 */ "two",
+/* 0033 */ "three",
+/* 0034 */ "four",
+/* 0035 */ "five",
+/* 0036 */ "six",
+/* 0037 */ "seven",
+/* 0038 */ "eight",
+/* 0039 */ "nine",
+/* 003a */ "colon",
+/* 003b */ "semicolon",
+/* 003c */ "less",
+/* 003d */ "equal",
+/* 003e */ "greater",
+/* 003f */ "question",
+/* 0040 */ "at",
+/* 0041 */ "A",
+/* 0042 */ "B",
+/* 0043 */ "C",
+/* 0044 */ "D",
+/* 0045 */ "E",
+/* 0046 */ "F",
+/* 0047 */ "G",
+/* 0048 */ "H",
+/* 0049 */ "I",
+/* 004a */ "J",
+/* 004b */ "K",
+/* 004c */ "L",
+/* 004d */ "M",
+/* 004e */ "N",
+/* 004f */ "O",
+/* 0050 */ "P",
+/* 0051 */ "Q",
+/* 0052 */ "R",
+/* 0053 */ "S",
+/* 0054 */ "T",
+/* 0055 */ "U",
+/* 0056 */ "V",
+/* 0057 */ "W",
+/* 0058 */ "X",
+/* 0059 */ "Y",
+/* 005a */ "Z",
+/* 005b */ "bracketleft",
+/* 005c */ "backslash",
+/* 005d */ "bracketright",
+/* 005e */ "asciicircum",
+/* 005f */ "underscore",
+/* 0060 */ "grave",
+/* 0061 */ "a",
+/* 0062 */ "b",
+/* 0063 */ "c",
+/* 0064 */ "d",
+/* 0065 */ "e",
+/* 0066 */ "f",
+/* 0067 */ "g",
+/* 0068 */ "h",
+/* 0069 */ "i",
+/* 006a */ "j",
+/* 006b */ "k",
+/* 006c */ "l",
+/* 006d */ "m",
+/* 006e */ "n",
+/* 006f */ "o",
+/* 0070 */ "p",
+/* 0071 */ "q",
+/* 0072 */ "r",
+/* 0073 */ "s",
+/* 0074 */ "t",
+/* 0075 */ "u",
+/* 0076 */ "v",
+/* 0077 */ "w",
+/* 0078 */ "x",
+/* 0079 */ "y",
+/* 007a */ "z",
+/* 007b */ "braceleft",
+/* 007c */ "bar",
+/* 007d */ "braceright",
+/* 007e */ "asciitilde",
+/* 007f */ ".notdef",
+/* 0080 */ ".notdef",
+/* 0081 */ ".notdef",
+/* 0082 */ ".notdef",
+/* 0083 */ ".notdef",
+/* 0084 */ ".notdef",
+/* 0085 */ ".notdef",
+/* 0086 */ ".notdef",
+/* 0087 */ ".notdef",
+/* 0088 */ ".notdef",
+/* 0089 */ ".notdef",
+/* 008a */ ".notdef",
+/* 008b */ ".notdef",
+/* 008c */ ".notdef",
+/* 008d */ ".notdef",
+/* 008e */ ".notdef",
+/* 008f */ ".notdef",
+/* 0090 */ "dotlessi", /* Um, Adobe's Latin1 has some extra chars */
+/* 0091 */ "grave",
+/* 0092 */ "accute", /* This is a duplicate... */
+/* 0093 */ "circumflex",
+/* 0094 */ "tilde",
+/* 0095 */ "macron",
+/* 0096 */ "breve",
+/* 0097 */ "dotaccent",
+/* 0098 */ "dieresis",
+/* 0099 */ ".notdef",
+/* 009a */ "ring",
+/* 009b */ "cedilla",
+/* 009c */ ".notdef",
+/* 009d */ "hungarumlaut",
+/* 009e */ "ogonek",
+/* 009f */ "caron",
+/* 00a0 */ "space",
+/* 00a1 */ "exclamdown",
+/* 00a2 */ "cent",
+/* 00a3 */ "sterling",
+/* 00a4 */ "currency",
+/* 00a5 */ "yen",
+/* 00a6 */ "brokenbar",
+/* 00a7 */ "section",
+/* 00a8 */ "dieresis",
+/* 00a9 */ "copyright",
+/* 00aa */ "ordfeminine",
+/* 00ab */ "guillemotleft",
+/* 00ac */ "logicalnot",
+/* 00ad */ "hyphen",
+/* 00ae */ "registered",
+/* 00af */ "macron",
+/* 00b0 */ "degree",
+/* 00b1 */ "plusminus",
+/* 00b2 */ "twosuperior",
+/* 00b3 */ "threesuperior",
+/* 00b4 */ "acute",
+/* 00b5 */ "mu",
+/* 00b6 */ "paragraph",
+/* 00b7 */ "periodcentered",
+/* 00b8 */ "cedilla",
+/* 00b9 */ "onesuperior",
+/* 00ba */ "ordmasculine",
+/* 00bb */ "guillemotright",
+/* 00bc */ "onequarter",
+/* 00bd */ "onehalf",
+/* 00be */ "threequarters",
+/* 00bf */ "questiondown",
+/* 00c0 */ "Agrave",
+/* 00c1 */ "Aacute",
+/* 00c2 */ "Acircumflex",
+/* 00c3 */ "Atilde",
+/* 00c4 */ "Adieresis",
+/* 00c5 */ "Aring",
+/* 00c6 */ "AE",
+/* 00c7 */ "Ccedilla",
+/* 00c8 */ "Egrave",
+/* 00c9 */ "Eacute",
+/* 00ca */ "Ecircumflex",
+/* 00cb */ "Edieresis",
+/* 00cc */ "Igrave",
+/* 00cd */ "Iacute",
+/* 00ce */ "Icircumflex",
+/* 00cf */ "Idieresis",
+/* 00d0 */ "Eth",
+/* 00d1 */ "Ntilde",
+/* 00d2 */ "Ograve",
+/* 00d3 */ "Oacute",
+/* 00d4 */ "Ocircumflex",
+/* 00d5 */ "Otilde",
+/* 00d6 */ "Odieresis",
+/* 00d7 */ "multiply",
+/* 00d8 */ "Oslash",
+/* 00d9 */ "Ugrave",
+/* 00da */ "Uacute",
+/* 00db */ "Ucircumflex",
+/* 00dc */ "Udieresis",
+/* 00dd */ "Yacute",
+/* 00de */ "Thorn",
+/* 00df */ "germandbls",
+/* 00e0 */ "agrave",
+/* 00e1 */ "aacute",
+/* 00e2 */ "acircumflex",
+/* 00e3 */ "atilde",
+/* 00e4 */ "adieresis",
+/* 00e5 */ "aring",
+/* 00e6 */ "ae",
+/* 00e7 */ "ccedilla",
+/* 00e8 */ "egrave",
+/* 00e9 */ "eacute",
+/* 00ea */ "ecircumflex",
+/* 00eb */ "edieresis",
+/* 00ec */ "igrave",
+/* 00ed */ "iacute",
+/* 00ee */ "icircumflex",
+/* 00ef */ "idieresis",
+/* 00f0 */ "eth",
+/* 00f1 */ "ntilde",
+/* 00f2 */ "ograve",
+/* 00f3 */ "oacute",
+/* 00f4 */ "ocircumflex",
+/* 00f5 */ "otilde",
+/* 00f6 */ "odieresis",
+/* 00f7 */ "divide",
+/* 00f8 */ "oslash",
+/* 00f9 */ "ugrave",
+/* 00fa */ "uacute",
+/* 00fb */ "ucircumflex",
+/* 00fc */ "udieresis",
+/* 00fd */ "yacute",
+/* 00fe */ "thorn",
+/* 00ff */ "ydieresis"
+ };
+ copyenc(encoding,latin1enc);
+}
+
+char *AdobeExpertEncoding[] = {
+/* 0000 */ ".notdef",
+/* 0001 */ ".notdef",
+/* 0002 */ ".notdef",
+/* 0003 */ ".notdef",
+/* 0004 */ ".notdef",
+/* 0005 */ ".notdef",
+/* 0006 */ ".notdef",
+/* 0007 */ ".notdef",
+/* 0008 */ ".notdef",
+/* 0009 */ ".notdef",
+/* 000a */ ".notdef",
+/* 000b */ ".notdef",
+/* 000c */ ".notdef",
+/* 000d */ ".notdef",
+/* 000e */ ".notdef",
+/* 000f */ ".notdef",
+/* 0010 */ ".notdef",
+/* 0011 */ ".notdef",
+/* 0012 */ ".notdef",
+/* 0013 */ ".notdef",
+/* 0014 */ ".notdef",
+/* 0015 */ ".notdef",
+/* 0016 */ ".notdef",
+/* 0017 */ ".notdef",
+/* 0018 */ ".notdef",
+/* 0019 */ ".notdef",
+/* 001a */ ".notdef",
+/* 001b */ ".notdef",
+/* 001c */ ".notdef",
+/* 001d */ ".notdef",
+/* 001e */ ".notdef",
+/* 001f */ ".notdef",
+/* 0020 */ "space",
+/* 0021 */ "exclamsmall",
+/* 0022 */ "Hungarumlautsmal",
+/* 0023 */ ".notdef",
+/* 0024 */ "dollaroldstyle",
+/* 0025 */ "dollarsuperior",
+/* 0026 */ "ampersandsmall",
+/* 0027 */ "Acutesmall",
+/* 0028 */ "parenleftsuperior",
+/* 0029 */ "parenrightsuperior",
+/* 002a */ "twodotenleader",
+/* 002b */ "onedotenleader",
+/* 002c */ "comma",
+/* 002d */ "hyphen",
+/* 002e */ "period",
+/* 002f */ "fraction",
+/* 0030 */ "zerooldstyle",
+/* 0031 */ "oneoldstyle",
+/* 0032 */ "twooldstyle",
+/* 0033 */ "threeoldstyle",
+/* 0034 */ "fouroldstyle",
+/* 0035 */ "fiveoldstyle",
+/* 0036 */ "sixoldstyle",
+/* 0037 */ "sevenoldstyle",
+/* 0038 */ "eightoldstyle",
+/* 0039 */ "nineoldstyle",
+/* 003a */ "colon",
+/* 003b */ "semicolon",
+/* 003c */ "commasuperior",
+/* 003d */ "threequartersemdash",
+/* 003e */ "periodsuperior",
+/* 003f */ "questionsmall",
+/* 0040 */ ".notdef",
+/* 0041 */ "asuperior",
+/* 0042 */ "bsuperior",
+/* 0043 */ "centsuperior",
+/* 0044 */ "dsuperior",
+/* 0045 */ "esuperior",
+/* 0046 */ ".notdef",
+/* 0047 */ ".notdef",
+/* 0048 */ ".notdef",
+/* 0049 */ "isuperior",
+/* 004a */ ".notdef",
+/* 004b */ ".notdef",
+/* 004c */ "lsuperior",
+/* 004d */ "msuperior",
+/* 004e */ "nsuperior",
+/* 004f */ "osuperior",
+/* 0050 */ ".notdef",
+/* 0051 */ ".notdef",
+/* 0052 */ "rsuperior",
+/* 0053 */ "ssuperior",
+/* 0054 */ "tsuperior",
+/* 0055 */ ".notdef",
+/* 0056 */ "ff",
+/* 0057 */ "fi",
+/* 0058 */ "fl",
+/* 0059 */ "ffi",
+/* 005a */ "ffl",
+/* 005b */ "parenleftinferior",
+/* 005c */ ".notdef",
+/* 005d */ "parenrightinferior",
+/* 005e */ "Circumflexsmall",
+/* 005f */ "hyphensuperior",
+/* 0060 */ "Gravesmall",
+/* 0061 */ "Asmall",
+/* 0062 */ "Bsmall",
+/* 0063 */ "Csmall",
+/* 0064 */ "Dsmall",
+/* 0065 */ "Esmall",
+/* 0066 */ "Fsmall",
+/* 0067 */ "Gsmall",
+/* 0068 */ "Hsmall",
+/* 0069 */ "Ismall",
+/* 006a */ "Jsmall",
+/* 006b */ "Ksmall",
+/* 006c */ "Lsmall",
+/* 006d */ "Msmall",
+/* 006e */ "Nsmall",
+/* 006f */ "Osmall",
+/* 0070 */ "Psmall",
+/* 0071 */ "Qsmall",
+/* 0072 */ "Rsmall",
+/* 0073 */ "Ssmall",
+/* 0074 */ "Tsmall",
+/* 0075 */ "Usmall",
+/* 0076 */ "Vsmall",
+/* 0077 */ "Wsmall",
+/* 0078 */ "Xsmall",
+/* 0079 */ "Ysmall",
+/* 007a */ "Zsmall",
+/* 007b */ "colonmonetary",
+/* 007c */ "onefitted",
+/* 007d */ "rupiah",
+/* 007e */ "Tildesmall",
+/* 007f */ ".notdef",
+/* 0080 */ ".notdef",
+/* 0081 */ ".notdef",
+/* 0082 */ ".notdef",
+/* 0083 */ ".notdef",
+/* 0084 */ ".notdef",
+/* 0085 */ ".notdef",
+/* 0086 */ ".notdef",
+/* 0087 */ ".notdef",
+/* 0088 */ ".notdef",
+/* 0089 */ ".notdef",
+/* 008a */ ".notdef",
+/* 008b */ ".notdef",
+/* 008c */ ".notdef",
+/* 008d */ ".notdef",
+/* 008e */ ".notdef",
+/* 008f */ ".notdef",
+/* 0090 */ ".notdef",
+/* 0091 */ ".notdef",
+/* 0092 */ ".notdef",
+/* 0093 */ ".notdef",
+/* 0094 */ ".notdef",
+/* 0095 */ ".notdef",
+/* 0096 */ ".notdef",
+/* 0097 */ ".notdef",
+/* 0098 */ ".notdef",
+/* 0099 */ ".notdef",
+/* 009a */ ".notdef",
+/* 009b */ ".notdef",
+/* 009c */ ".notdef",
+/* 009d */ ".notdef",
+/* 009e */ ".notdef",
+/* 009f */ ".notdef",
+/* 00a0 */ ".notdef",
+/* 00a1 */ "exclamdownsmall",
+/* 00a2 */ "centoldstyle",
+/* 00a3 */ "Lslashsmall",
+/* 00a4 */ ".notdef",
+/* 00a5 */ ".notdef",
+/* 00a6 */ "Scaronsmall",
+/* 00a7 */ "Zcaronsmall",
+/* 00a8 */ "Dieresissmall",
+/* 00a9 */ "Brevesmall",
+/* 00aa */ "Caronsmall",
+/* 00ab */ ".notdef",
+/* 00ac */ "Dotaccentsmall",
+/* 00ad */ ".notdef",
+/* 00ae */ ".notdef",
+/* 00af */ "Macronsmall",
+/* 00b0 */ ".notdef",
+/* 00b1 */ ".notdef",
+/* 00b2 */ "figuredash",
+/* 00b3 */ "hypheninferior",
+/* 00b4 */ ".notdef",
+/* 00b5 */ ".notdef",
+/* 00b6 */ "Ogoneksmall",
+/* 00b7 */ "Ringsmall",
+/* 00b8 */ "Cedillasmall",
+/* 00b9 */ ".notdef",
+/* 00ba */ ".notdef",
+/* 00bb */ ".notdef",
+/* 00bc */ "onequarter",
+/* 00bd */ "onehalf",
+/* 00be */ "threequarters",
+/* 00bf */ "questiondownsmall",
+/* 00c0 */ "oneeighth",
+/* 00c1 */ "threeeighths",
+/* 00c2 */ "fiveeighths",
+/* 00c3 */ "seveneighths",
+/* 00c4 */ "onethird",
+/* 00c5 */ "twothirds",
+/* 00c6 */ ".notdef",
+/* 00c7 */ ".notdef",
+/* 00c8 */ "zerosuperior",
+/* 00c9 */ "onesuperior",
+/* 00ca */ "twosuperior",
+/* 00cb */ "threesuperior",
+/* 00cc */ "foursuperior",
+/* 00cd */ "fivesuperior",
+/* 00ce */ "sixsuperior",
+/* 00cf */ "sevensuperior",
+/* 00d0 */ "eightsuperior",
+/* 00d1 */ "ninesuperior",
+/* 00d2 */ "zeroinferior",
+/* 00d3 */ "oneinferior",
+/* 00d4 */ "twoinferior",
+/* 00d5 */ "threeinferior",
+/* 00d6 */ "fourinferior",
+/* 00d7 */ "fiveinferior",
+/* 00d8 */ "sixinferior",
+/* 00d9 */ "seveninferior",
+/* 00da */ "eightinferior",
+/* 00db */ "nineinferior",
+/* 00dc */ "centinferior",
+/* 00dd */ "dollarinferior",
+/* 00de */ "periodinferior",
+/* 00df */ "commainferior",
+/* 00e0 */ "Agravesmall",
+/* 00e1 */ "Aacutesmall",
+/* 00e2 */ "Acircumflexsmall",
+/* 00e3 */ "Atildesmall",
+/* 00e4 */ "Adieresissmall",
+/* 00e5 */ "Aringsmall",
+/* 00e6 */ "AEsmall",
+/* 00e7 */ "Ccedillasmall",
+/* 00e8 */ "Egravesmall",
+/* 00e9 */ "Eacutesmall",
+/* 00ea */ "Ecircumflexsmall",
+/* 00eb */ "Edieresissmall",
+/* 00ec */ "Igravesmall",
+/* 00ed */ "Iacutesmall",
+/* 00ee */ "Icircumflexsmall",
+/* 00ef */ "Idieresissmall",
+/* 00f0 */ "Ethsmall",
+/* 00f1 */ "Ntildesmall",
+/* 00f2 */ "Ogravesmall",
+/* 00f3 */ "Oacutesmall",
+/* 00f4 */ "Ocircumflexsmall",
+/* 00f5 */ "Otildesmall",
+/* 00f6 */ "Odieresissmall",
+/* 00f7 */ "OEsmall",
+/* 00f8 */ "Oslashsmall",
+/* 00f9 */ "Ugravesmall",
+/* 00fa */ "Uacutesmall",
+/* 00fb */ "Ucircumflexsmall",
+/* 00fc */ "Udieresissmall",
+/* 00fd */ "Yacutesmall",
+/* 00fe */ "Thornsmall",
+/* 00ff */ "Ydieresissmall"
+};
+
+static struct fontdict *MakeEmptyFont(void) {
+ struct fontdict *ret;
+
+ ret = gcalloc(1,sizeof(struct fontdict));
+ ret->fontinfo = gcalloc(1,sizeof(struct fontinfo));
+ ret->chars = gcalloc(1,sizeof(struct pschars));
+ ret->private = gcalloc(1,sizeof(struct private));
+ ret->private->subrs = gcalloc(1,sizeof(struct pschars));
+ ret->private->private = gcalloc(1,sizeof(struct psdict));
+ ret->private->leniv = 4;
+ ret->encoding_name = &custom;
+ ret->fontinfo->fstype = -1;
+return( ret );
+}
+
+static struct fontdict *PSMakeEmptyFont(void) {
+ struct fontdict *ret;
+
+ ret = gcalloc(1,sizeof(struct fontdict));
+ ret->fontinfo = gcalloc(1,sizeof(struct fontinfo));
+ ret->chars = gcalloc(1,sizeof(struct pschars));
+ ret->private = gcalloc(1,sizeof(struct private));
+ ret->private->subrs = gcalloc(1,sizeof(struct pschars));
+ ret->private->private = gcalloc(1,sizeof(struct psdict));
+ ret->private->leniv = 4;
+ ret->charprocs = gcalloc(1,sizeof(struct charprocs));
+ ret->encoding_name = &custom;
+ ret->fontinfo->fstype = -1;
+return( ret );
+}
+
+static char *myfgets(char *str, int len, FILE *file) {
+ char *pt, *end;
+ int ch=0;
+
+ for ( pt = str, end = str+len-1; pt<end && (ch=getc(file))!=EOF && ch!='\r' && ch!='\n';
+ *pt++ = ch );
+ if ( ch=='\n' )
+ *pt++ = '\n';
+ else if ( ch=='\r' ) {
+ *pt++ = '\r';
+ if ((ch=getc(file))!='\n' )
+ ungetc(ch,file);
+ else
+ *pt++ = '\n';
+ }
+ if ( pt==str )
+return( NULL );
+ *pt = '\0';
+return( str );
+}
+
+static char *myfgetsNoNulls(char *str, int len, FILE *file) {
+ char *pt, *end;
+ int ch=0;
+
+ for ( pt = str, end = str+len-1; pt<end && (ch=getc(file))!=EOF && ch!='\r' && ch!='\n'; ) {
+ if ( ch!='\0' )
+ *pt++ = ch;
+ }
+ if ( ch=='\n' )
+ *pt++ = '\n';
+ else if ( ch=='\r' ) {
+ *pt++ = '\r';
+ if ((ch=getc(file))!='\n' )
+ ungetc(ch,file);
+ else
+ *pt++ = '\n';
+ }
+ if ( pt==str )
+return( NULL );
+ *pt = '\0';
+return( str );
+}
+
+static char *getstring(char *start,FILE *in) {
+ char *end, *ret;
+ int parencnt=0, len=0;
+ char buffer[512];
+
+ forever {
+ while ( *start!='\0' && *start!='(' ) ++start;
+ if ( *start=='\0' ) {
+ if ( myfgetsNoNulls(buffer,sizeof(buffer),in)==NULL )
+return( copy(""));
+ start = buffer;
+ } else
+ break;
+ }
+ ++start;
+ ret = NULL; len = 1;
+ forever {
+ for ( end = start; *end!='\0' && (*end!=')' || parencnt>0); ++end ) {
+ if ( *end=='\\' && (end[1]=='(' || end[1]==')'))
+ ++end;
+ else if ( *end=='(' ) ++parencnt;
+ else if ( *end==')' ) --parencnt;
+ }
+ if ( end>start ) {
+ if ( ret==NULL )
+ ret = galloc(end-start+1);
+ else
+ ret = grealloc(ret,len+end-start);
+ strncpy(ret+len-1,start,end-start);
+ len += end-start;
+ ret[len-1] = '\0';
+ }
+ if ( *end!='\0' )
+ break;
+ if ( myfgetsNoNulls(buffer,sizeof(buffer),in)==NULL )
+return( ret );
+ start = buffer;
+ }
+return( ret );
+}
+
+static char *gettoken(char *start) {
+ char *end, *ret;
+
+ while ( *start!='\0' && *start!='/' && *start!='(' ) ++start;
+ if ( *start=='/' || *start=='(' ) ++start;
+ for ( end = start; *end!='\0' && !Isspace(*end) && *end!='[' && *end!='/' && *end!='{' && *end!='(' && *end!=')'; ++end );
+ ret = galloc(end-start+1);
+ if ( end>start )
+ strncpy(ret,start,end-start);
+ ret[end-start] = '\0';
+return( ret );
+}
+
+static int getbool(char *start) {
+
+ while ( Isspace(*start) ) ++start;
+ if ( *start=='T' || *start=='t' )
+return( 1 );
+
+return( 0 );
+}
+
+static void fillintarray(int *array,char *start,int maxentries) {
+ int i;
+ char *end;
+
+ while ( *start!='\0' && *start!='[' && *start!='{' ) ++start;
+ if ( *start=='[' || *start=='{' ) ++start;
+ for ( i=0; i<maxentries && *start!=']' && *start!='}'; ++i ) {
+ array[i] = (int) strtod(start,&end);
+ if ( start==end )
+return;
+ start = end;
+ while ( Isspace(*start) ) ++start;
+ }
+}
+
+static void fillrealarray(real *array,char *start,int maxentries) {
+ int i;
+ char *end;
+
+ while ( *start!='\0' && *start!='[' && *start!='{' ) ++start;
+ if ( *start=='[' || *start=='{' ) ++start;
+ for ( i=0; i<maxentries && *start!=']' && *start!='}'; ++i ) {
+ while ( Isspace( *start )) ++start;
+ if ( Isdigit(*start) || *start=='-' || *start=='.' )
+ array[i] = strtod(start,&end);
+ else if ( strncmp(start,"div",3)==0 && i>=2 ) {
+ /* Some of Luc Devroye's fonts have a "div" in the FontMatrix */
+ array[i-2] /= array[i-1];
+ i -= 2;
+ end = start+3;
+ } else
+return;
+ if ( start==end )
+return;
+ start = end;
+ while ( Isspace(*start) ) ++start;
+ }
+}
+
+static void InitDict(struct psdict *dict,char *line) {
+ while ( *line!='/' && *line!='\0' ) ++line;
+ while ( !Isspace(*line) && *line!='\0' ) ++line;
+ dict->cnt += strtol(line,NULL,10);
+ if ( dict->next>0 ) { int i; /* Shouldn't happen, but did in a bad file */
+ dict->keys = grealloc(dict->keys,dict->cnt*sizeof(char *));
+ dict->values = grealloc(dict->values,dict->cnt*sizeof(char *));
+ for ( i=dict->next; i<dict->cnt; ++i ) {
+ dict->keys[i] = NULL; dict->values[i] = NULL;
+ }
+ } else {
+ dict->keys = gcalloc(dict->cnt,sizeof(char *));
+ dict->values = gcalloc(dict->cnt,sizeof(char *));
+ }
+}
+
+static void InitChars(struct pschars *chars,char *line) {
+ while ( *line!='/' && *line!='\0' ) ++line;
+ while ( !Isspace(*line) && *line!='\0' ) ++line;
+ chars->cnt = strtol(line,NULL,10);
+ if ( chars->cnt>0 ) {
+ chars->keys = gcalloc(chars->cnt,sizeof(char *));
+ chars->values = gcalloc(chars->cnt,sizeof(char *));
+ chars->lens = gcalloc(chars->cnt,sizeof(int));
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_change_total(chars->cnt);
+#endif
+ }
+}
+
+static void InitCharProcs(struct charprocs *cp, char *line) {
+ while ( *line!='/' && *line!='\0' ) ++line;
+ while ( !Isspace(*line) && *line!='\0' ) ++line;
+ cp->cnt = strtol(line,NULL,10);
+ if ( cp->cnt>0 ) {
+ cp->keys = gcalloc(cp->cnt,sizeof(char *));
+ cp->values = gcalloc(cp->cnt,sizeof(SplineChar *));
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_change_total(cp->cnt);
+#endif
+ }
+}
+
+static int mycmp(char *str,char *within, char *end ) {
+ while ( within<end ) {
+ if ( *str!=*within )
+return( *str-*within );
+ ++str; ++within;
+ }
+return( *str=='\0'?0:1 );
+}
+
+static void ContinueValue(struct fontparse *fp, struct psdict *dict, char *line) {
+ int incomment = false;
+
+ while ( *line ) {
+ if ( !fp->instring && fp->depth==0 &&
+ (strncmp(line,"def",3)==0 ||
+ strncmp(line,"|-",2)==0 || strncmp(line,"ND",2)==0)) {
+ while ( 1 ) {
+ while ( fp->vpt>fp->vbuf+1 && Isspace(fp->vpt[-1]) )
+ --fp->vpt;
+ if ( fp->vpt>fp->vbuf+8 && strncmp(fp->vpt-8,"noaccess",8)==0 )
+ fp->vpt -= 8;
+ else if ( fp->vpt>fp->vbuf+8 && strncmp(fp->vpt-8,"readonly",8)==0 )
+ fp->vpt -= 8;
+ else if ( fp->vpt>fp->vbuf+4 && strncmp(fp->vpt-4,"bind",4)==0 )
+ fp->vpt -= 4;
+ else
+ break;
+ }
+ /* In some URW fonts (Nimbus Sans L, n019003l) we get a complex */
+ /* expression rather than just an array. This is ok. The expression */
+ /* converts itself into an array. We could just truncate to the */
+ /* default array, but I don't see any reason to do so */
+ if ( fp->pending_parse!=NULL ) {
+ *fp->pending_parse = copyn(fp->vbuf,fp->vpt-fp->vbuf);
+ fp->pending_parse = NULL;
+ } else {
+ dict->values[dict->next] = copyn(fp->vbuf,fp->vpt-fp->vbuf);
+ ++dict->next;
+ }
+ fp->vpt = fp->vbuf;
+ fp->multiline = false;
+return;
+ }
+ if ( fp->vpt>=fp->vmax ) {
+ int len = fp->vmax-fp->vbuf+1000, off=fp->vpt-fp->vbuf;
+ fp->vbuf = grealloc(fp->vbuf,len);
+ fp->vpt = fp->vbuf+off;
+ fp->vmax = fp->vbuf+len;
+ }
+ if ( fp->instring ) {
+ if ( *line==')' ) --fp->instring;
+ } else if ( incomment ) {
+ /* Do Nothing */;
+ } else if ( *line=='(' )
+ ++fp->instring;
+ else if ( *line=='%' )
+ incomment = true;
+ else if ( *line=='[' || *line=='{' )
+ ++fp->depth;
+ else if ( *line=='}' || *line==']' )
+ --fp->depth;
+ *fp->vpt++ = *line++;
+ }
+}
+
+static void AddValue(struct fontparse *fp, struct psdict *dict, char *line, char *endtok) {
+ char *pt;
+
+ if ( dict!=NULL ) {
+ if ( dict->next>=dict->cnt ) {
+ dict->cnt += 10;
+ dict->keys = grealloc(dict->keys,dict->cnt*sizeof(char *));
+ dict->values = grealloc(dict->values,dict->cnt*sizeof(char *));
+ }
+ dict->keys[dict->next] = copyn(line+1,endtok-(line+1));
+ }
+ pt = line+strlen(line)-1;
+ while ( Isspace(*endtok)) ++endtok;
+ while ( pt>endtok && Isspace(*pt)) --pt;
+ ++pt;
+ if ( strncmp(pt-3,"def",3)==0 )
+ pt -= 3;
+ else if ( strncmp(pt-2,"|-",2)==0 || strncmp(pt-2,"ND",2)==0 )
+ pt -= 2;
+ else {
+ fp->multiline = true;
+ ContinueValue(fp,dict,endtok);
+return;
+ }
+ forever {
+ while ( pt-1>endtok && Isspace(pt[-1])) --pt;
+ if ( pt-8>endtok && strncmp(pt-8,"noaccess",8)==0 )
+ pt -= 8;
+ else if ( pt-8>endtok && strncmp(pt-8,"readonly",8)==0 )
+ pt -= 8;
+ else if ( pt-4>endtok && strncmp(pt-4,"bind",4)==0 )
+ pt -= 4;
+ else
+ break;
+ }
+ if ( dict!=NULL ) {
+ dict->values[dict->next] = copyn(endtok,pt-endtok);
+ ++dict->next;
+ } else {
+ *fp->pending_parse = copyn(endtok,pt-endtok);
+ fp->pending_parse = NULL;
+ }
+}
+
+static int hex(int ch1, int ch2) {
+ if ( ch1>='0' && ch1<='9' )
+ ch1 -= '0';
+ else if ( ch1>='a' )
+ ch1 -= 'a'-10;
+ else
+ ch1 -= 'A'-10;
+ if ( ch2>='0' && ch2<='9' )
+ ch2 -= '0';
+ else if ( ch2>='a' )
+ ch2 -= 'a'-10;
+ else
+ ch2 -= 'A'-10;
+return( (ch1<<4)|ch2 );
+}
+
+unsigned short r;
+#define c1 52845
+#define c2 22719
+
+static void initcode(void) {
+ r = 55665;
+}
+
+static int decode(unsigned char cypher) {
+ unsigned char plain = ( cypher ^ (r>>8));
+ r = (cypher + r) * c1 + c2;
+return( plain );
+}
+
+static void dumpzeros(FILE *out, unsigned char *zeros, int zcnt) {
+ while ( --zcnt >= 0 )
+ fputc(*zeros++,out);
+}
+
+static void decodestr(unsigned char *str, int len) {
+ unsigned short r = 4330;
+ unsigned char plain, cypher;
+
+ while ( len-->0 ) {
+ cypher = *str;
+ plain = ( cypher ^ (r>>8));
+ r = (cypher + r) * c1 + c2;
+ *str++ = plain;
+ }
+}
+
+static void findstring(struct fontparse *fp,struct pschars *subrs,int index,char *nametok,char *str) {
+ char buffer[1024], *bpt, *bs, *end = buffer+sizeof(buffer)-1;
+ int val;
+
+ while ( Isspace(*str)) ++str;
+ if ( *str=='(' ) {
+ ++str;
+ bpt = buffer;
+ while ( *str!=')' && *str!='\0' ) {
+ if ( *str!='\\' )
+ val = *str++;
+ else {
+ if ( Isdigit( *++str )) {
+ val = *str++-'0';
+ if ( Isdigit( *str )) {
+ val = (val<<3) | (*str++-'0');
+ if ( Isdigit( *str ))
+ val = (val<<3) | (*str++-'0');
+ }
+ } else
+ val = *str++;
+ }
+ if ( bpt<end )
+ *bpt++ = val;
+ }
+ decodestr((unsigned char *) buffer,bpt-buffer);
+ bs = buffer + fp->fd->private->leniv;
+ if ( bpt<bs ) bs=bpt; /* garbage */
+ subrs->lens[index] = bpt-bs;
+ subrs->keys[index] = copy(nametok);
+ subrs->values[index] = galloc(bpt-bs);
+ memcpy(subrs->values[index],bs,bpt-bs);
+ if ( index>=subrs->next ) subrs->next = index+1;
+ }
+}
+
+/* Type42 charstrings are actually numbers */
+static void findnumbers(struct fontparse *fp,struct pschars *chars,char *str) {
+ int val;
+ char *end;
+
+ forever {
+ int index = chars->next;
+ char *namestrt;
+
+ while ( Isspace(*str)) ++str;
+ if ( *str!='/' )
+ break;
+ namestrt = ++str;
+ while ( Isalnum(*str) || *str=='.' ) ++str;
+ *str = '\0';
+ index = chars->next;
+
+ ++str;
+ val = strtol(str,&end,10);
+ chars->lens[index] = 0;
+ chars->keys[index] = copy(namestrt);
+ chars->values[index] = (void *) (intpt) val;
+ chars->next = index+1;
+ str = end;
+ while ( Isspace(*str)) ++str;
+ if ( str[0]=='d' && str[1]=='e' && str[2]=='f' )
+ str += 3;
+ }
+}
+
+static char *rmbinary(char *line) {
+ char *pt;
+
+ for ( pt=line; *pt; ++pt ) {
+ if (( *pt<' ' || *pt>=0x7f ) && *pt!='\n' ) {
+ if ( strlen(pt)>5 ) {
+ pt[0] = '.';
+ pt[1] = '.';
+ pt[2] = '.';
+ pt[3] = '\n';
+ pt[4] = '\0';
+ } else {
+ pt[0] = '\n';
+ pt[1] = '\0';
+ }
+ break;
+ }
+ }
+return( line );
+}
+
+static void sfnts2tempfile(struct fontparse *fp,FILE *in,char *line) {
+ char *pt;
+ int instring = false, firstnibble=true, sofar=0, nibble;
+ int complained = false;
+ int ch=0;
+
+ fp->sfnts = tmpfile();
+
+ /* first finish off anything in the current line */
+ while ( (pt=strpbrk(line,"<]" ))!=NULL ) {
+ if ( *pt==']' )
+ goto skip_to_eol;
+
+ instring = true;
+ for ( ++pt; *pt && *pt!='>'; ++pt ) {
+ if ( Isspace(*pt))
+ continue;
+ if ( Isdigit(*pt))
+ nibble = *pt-'0';
+ else if ( *pt>='a' && *pt<='f' )
+ nibble = *pt-'a'+10;
+ else if ( *pt>='A' && *pt<='F' )
+ nibble = *pt-'A'+10;
+ else {
+ if ( !complained ) {
+ LogError( _("Invalid hex digit in sfnts array\n") );
+ complained = true;
+ }
+ ++pt;
+ continue;
+ }
+ if ( firstnibble ) {
+ sofar = nibble<<4;
+ firstnibble = false;
+ } else {
+ putc(sofar|nibble,fp->sfnts);
+ sofar = 0;
+ firstnibble = true;
+ }
+ }
+ if ( *pt=='>' ) {
+ if ( ftell(fp->sfnts)&1 ) { /* Strings must be contain an even number of bytes */
+ /* But may be padded with a trailing NUL */
+ fseek(fp->sfnts,-1,SEEK_CUR);
+ }
+ ++pt;
+ instring = false;
+ }
+ line = pt;
+ }
+
+ while ( (ch=getc(in))!=EOF ) {
+ if ( ch==']' )
+ goto skip_to_eol;
+ if ( Isspace(ch))
+ continue;
+ if ( !instring && ch=='<' ) {
+ instring = true;
+ firstnibble = true;
+ sofar = 0;
+ } else if ( !instring ) {
+ if ( !complained ) {
+ LogError( _("Invalid character outside of string in sfnts array\n") );
+ complained = true;
+ }
+ } else if ( instring && ch=='>' ) {
+ if ( ftell(fp->sfnts)&1 ) { /* Strings must be contain an even number of bytes */
+ /* But may be padded with a trailing NUL */
+ fseek(fp->sfnts,-1,SEEK_CUR);
+ }
+ instring = false;
+ } else {
+ if ( Isdigit(ch))
+ nibble = ch-'0';
+ else if ( ch>='a' && ch<='f' )
+ nibble = ch-'a'+10;
+ else if ( ch>='A' && ch<='F' )
+ nibble = ch-'A'+10;
+ else {
+ if ( !complained ) {
+ LogError( _("Invalid hex digit in sfnts array\n") );
+ complained = true;
+ }
+ continue;
+ }
+ if ( firstnibble ) {
+ sofar = nibble<<4;
+ firstnibble = false;
+ } else {
+ putc(sofar|nibble,fp->sfnts);
+ sofar = 0;
+ firstnibble = true;
+ }
+ }
+ }
+ skip_to_eol:
+ while ( ch!=EOF && ch!='\n' && ch!='\r' )
+ ch = getc(in);
+ rewind(fp->sfnts);
+}
+
+static void ParseSimpleEncoding(struct fontparse *fp,char *line) {
+ char tok[200], *pt;
+
+ while ( *line!='\0' && *line!=']' ) {
+ while ( Isspace(*line)) ++line;
+ if ( *line==']' )
+ break;
+ if ( *line!='/' ) {
+ ++line;
+ continue;
+ }
+ ++line;
+ while ( Isspace(*line)) ++line;
+ for ( pt=tok; !Isspace(*line) && *line!='\0' && *line!='/' && *line!=']'; ) {
+ if ( pt<tok+sizeof(tok)-2 )
+ *pt++ = *line++;
+ else
+ ++line;
+ }
+ *pt = '\0';
+ if ( fp->simple_enc_pos<256 )
+ fp->fd->encoding[fp->simple_enc_pos++] = copy(tok);
+ }
+ if ( *line==']' ) {
+ fp->simpleencoding = false;
+ fp->inencoding = false;
+ }
+}
+
+static void parseline(struct fontparse *fp,char *line,FILE *in) {
+ char buffer[200], *pt, *endtok;
+
+ while ( *line==' ' || *line=='\t' ) ++line;
+ if ( line[0]=='%' && !fp->multiline )
+return;
+
+ if ( fp->simpleencoding ) {
+ ParseSimpleEncoding(fp,line);
+return;
+ } else if (( fp->inencoding && strncmp(line,"dup",3)==0 ) ||
+ ( strncmp(line,"dup ",4)==0 && Isdigit(line[4]) &&
+ strstr(line+strlen(line)-6," put")!=NULL && strchr(line,'/')!=NULL )) {
+ /* Fontographer's type3 fonts claim to be standard, but then aren't */
+ fp->fd->encoding_name = &custom;
+ /* Metamorphasis has multiple entries on a line */
+ while ( strncmp(line,"dup",3)==0 ) {
+ char *end;
+ int pos = strtol(line+3,&end,10);
+ line = end;
+ while ( Isspace( *line )) ++line;
+ if ( *line=='/' ) ++line;
+ for ( pt = buffer; !Isspace(*line); *pt++ = *line++ );
+ *pt = '\0';
+ if ( pos>=0 && pos<256 ) {
+ free(fp->fd->encoding[pos]);
+ fp->fd->encoding[pos] = copy(buffer);
+ }
+ while ( Isspace(*line)) ++line;
+ if ( strncmp(line,"put",3)==0 ) line+=3;
+ while ( Isspace(*line)) ++line;
+ }
+return;
+ } else if ( fp->inencoding && strstr(line,"for")!=NULL && strstr(line,"/.notdef")!=NULL ) {
+ /* the T1 spec I've got doesn't allow for this, but I've seen it anyway*/
+ /* 0 1 255 {1 index exch /.notdef put} for */
+ /* 0 1 31 { 1 index exch /.notdef put } bind for */
+ int i;
+ for ( i=0; i<256; ++i )
+ if ( fp->fd->encoding[i]==NULL )
+ fp->fd->encoding[i] = copy(".notdef");
+return;
+ } else if ( fp->inencoding && strstr(line,"Encoding")!=NULL && strstr(line,"put")!=NULL ) {
+ /* Saw a type 3 font with lines like "Encoding 1 /_a0 put" */
+ char *end;
+ int pos;
+ while ( Isspace(*line)) ++line;
+ if ( strncmp(line,"Encoding ",9)==0 ) {
+ line+=9;
+ pos = strtol(line,&end,10);
+ line = end;
+ while ( Isspace(*line)) ++line;
+ if ( *line=='/' ) {
+ ++line;
+ for ( pt = buffer; !Isspace(*line); *pt++ = *line++ );
+ *pt = '\0';
+ if ( pos>=0 && pos<256 )
+ fp->fd->encoding[pos] = copy(buffer);
+ }
+ }
+return;
+ } else if ( fp->insubs ) {
+ struct pschars *subrs = fp->fd->private->subrs;
+ while ( Isspace(*line)) ++line;
+ if ( strncmp(line,"dup ",4)==0 ) {
+ int i;
+ char *ept;
+ for ( line += 4; *line==' '; ++line );
+ i = strtol(line,&ept,10);
+ if ( fp->ignore )
+ /* Do Nothing */;
+ else if ( i<subrs->cnt ) {
+ findstring(fp,subrs,i,NULL,ept);
+ } else if ( !fp->alreadycomplained ) {
+ LogError( _("Index too big (must be <%d) \"%s"), subrs->cnt, rmbinary(line));
+ fp->alreadycomplained = true;
+ }
+ } else if ( strncmp(line, "readonly put", 12)==0 || strncmp(line, "ND", 2)==0 || strncmp(line, "|-", 2)==0 ) {
+ fp->insubs = false;
+ fp->ignore = false;
+ } else if ( *line=='\n' || *line=='\0' ) {
+ /* Ignore blank lines */;
+ } else if ( !fp->alreadycomplained ) {
+ LogError( _("Didn't understand \"%s"), rmbinary(line) );
+ fp->alreadycomplained = true;
+ }
+ } else if ( fp->inchars ) {
+ struct pschars *chars = fp->fd->chars;
+ while ( Isspace(*line)) ++line;
+ if ( strncmp(line,"end",3)==0 )
+ fp->ignore = fp->inchars = false;
+ else if ( *line=='\n' || *line=='\0' )
+ /* Ignore it */;
+ else if ( *line!='/' || !(Isalpha(line[1]) || line[1]=='.')) {
+ LogError( _("No name for CharStrings dictionary \"%s"), rmbinary(line) );
+ fp->alreadycomplained = true;
+ } else if ( fp->ignore ) {
+ /* Do Nothing */;
+ } else if ( chars->next>=chars->cnt )
+ LogError( _("Too many entries in CharStrings dictionary \"%s"), rmbinary(line) );
+ else if ( fp->fd->fonttype==42 || fp->fd->fonttype==11 || fp->fd->cidfonttype==2 )
+ findnumbers(fp,chars,line);
+ else {
+ int i = chars->next;
+ char *namestrt = ++line;
+ while ( Isalnum(*line) || *line=='.' ) ++line;
+ *line = '\0';
+ findstring(fp,chars,i,namestrt,line+1);
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_next();
+#endif
+ }
+return;
+ }
+ fp->inencoding = 0;
+
+ while ( Isspace(*line)) ++line;
+ endtok = NULL;
+ if ( *line=='/' )
+ for ( endtok=line+1; !Isspace(*endtok) && *endtok!='(' &&
+ *endtok!='{' && *endtok!='[' && *endtok!='\0'; ++endtok );
+
+ if ( strstr(line,"/shareddict")!=NULL && strstr(line,"where")!=NULL ) {
+ fp->infi = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->inprivate = fp->inblendprivate = fp->inblendfi = false;
+ fp->skipping_mbf = true;
+return;
+ }
+
+ if ( mycmp("Encoding",line+1,endtok)==0 && !fp->doneencoding ) {
+ if ( strstr(endtok,"StandardEncoding")!=NULL ) {
+ fp->fd->encoding_name = FindOrMakeEncoding("AdobeStandard");
+ setStdEnc(fp->fd->encoding);
+ } else if ( strstr(endtok,"ISOLatin1Encoding")!=NULL ) {
+ fp->fd->encoding_name = FindOrMakeEncoding("ISO8859-1");
+ setLatin1Enc(fp->fd->encoding);
+ } else {
+ fp->fd->encoding_name = &custom;
+ fp->inencoding = 1;
+ }
+ if ( fp->fd->encoding_name==NULL )
+ fp->fd->encoding_name = &custom;
+ fp->infi = fp->inprivate = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->doneencoding = true;
+ while ( *endtok==' ' || *endtok=='\t' ) ++endtok;
+ if ( *endtok=='[' ) { /* It's a literal array */
+ fp->simpleencoding = true;
+ fp->simple_enc_pos = 0;
+ ParseSimpleEncoding(fp,endtok+1);
+ }
+ } else if ( mycmp("BoundingBoxes",line+1,endtok)==0 ) {
+ fp->infi = fp->inprivate = fp->inencoding = fp->inmetrics = fp->inmetrics2 = false;
+ fp->inbb = true;
+ } else if ( mycmp("Metrics",line+1,endtok)==0 ) {
+ fp->infi = fp->inprivate = fp->inbb = fp->inencoding = fp->inmetrics2 = false;
+ fp->inmetrics = true;
+ fp->fd->metrics = gcalloc(1,sizeof(struct psdict));
+ fp->fd->metrics->cnt = strtol(endtok,NULL,10);
+ fp->fd->metrics->keys = galloc(fp->fd->metrics->cnt*sizeof(char *));
+ fp->fd->metrics->values = galloc(fp->fd->metrics->cnt*sizeof(char *));
+ } else if ( strstr(line,"/Private")!=NULL && strstr(line,"/Blend")!=NULL ) {
+ fp->infi = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->inprivate = fp->inblendprivate = fp->inblendfi = false;
+ fp->inblendprivate = 1;
+ fp->fd->blendprivate = gcalloc(1,sizeof(struct psdict));
+ InitDict(fp->fd->blendprivate,line);
+return;
+ } else if ( strstr(line,"/FontInfo")!=NULL && strstr(line,"/Blend")!=NULL ) {
+ fp->infi = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->inprivate = fp->inblendprivate = fp->inblendfi = false;
+ fp->inblendfi = 1;
+ fp->fd->blendfontinfo = gcalloc(1,sizeof(struct psdict));
+ InitDict(fp->fd->blendfontinfo,line);
+return;
+ } else if ( fp->infi ) {
+ if ( fp->multiline ) {
+ ContinueValue(fp,NULL,line);
+return;
+ }
+ if ( endtok==NULL && (strncmp(line,"end", 3)==0 || strncmp(line,">>",2)==0)) {
+ fp->infi=0;
+return;
+ } else if ( endtok==NULL )
+return;
+ if ( mycmp("version",line+1,endtok)==0 ) {
+ free(fp->fd->fontinfo->version);
+ fp->fd->fontinfo->version = getstring(endtok,in);
+ } else if ( mycmp("Notice",line+1,endtok)==0 ) {
+ if ( fp->fd->fontinfo->notice!=NULL )
+ free(fp->fd->fontinfo->notice);
+ fp->fd->fontinfo->notice = getstring(endtok,in);
+ } else if ( mycmp("Copyright",line+1,endtok)==0 ) { /* cff spec allows for copyright and notice */
+ if ( fp->fd->fontinfo->notice!=NULL )
+ free(fp->fd->fontinfo->notice);
+ fp->fd->fontinfo->notice = getstring(endtok,in);
+ } else if ( mycmp("FullName",line+1,endtok)==0 ) {
+ if ( fp->fd->fontinfo->fullname==NULL )
+ fp->fd->fontinfo->fullname = getstring(endtok,in);
+ else
+ free(getstring(endtok,in));
+ } else if ( mycmp("FamilyName",line+1,endtok)==0 ) {
+ free( fp->fd->fontinfo->familyname );
+ fp->fd->fontinfo->familyname = getstring(endtok,in);
+ } else if ( mycmp("Weight",line+1,endtok)==0 ) {
+ free( fp->fd->fontinfo->weight );
+ fp->fd->fontinfo->weight = getstring(endtok,in);
+ } else if ( mycmp("ItalicAngle",line+1,endtok)==0 )
+ fp->fd->fontinfo->italicangle = strtod(endtok,NULL);
+ else if ( mycmp("UnderlinePosition",line+1,endtok)==0 )
+ fp->fd->fontinfo->underlineposition = strtod(endtok,NULL);
+ else if ( mycmp("UnderlineThickness",line+1,endtok)==0 )
+ fp->fd->fontinfo->underlinethickness = strtod(endtok,NULL);
+ else if ( mycmp("isFixedPitch",line+1,endtok)==0 )
+ fp->fd->fontinfo->isfixedpitch = getbool(endtok);
+ else if ( mycmp("em",line+1,endtok)==0 )
+ fp->fd->fontinfo->em = strtol(endtok,NULL,10);
+ else if ( mycmp("ascent",line+1,endtok)==0 )
+ fp->fd->fontinfo->ascent = strtol(endtok,NULL,10);
+ else if ( mycmp("descent",line+1,endtok)==0 )
+ fp->fd->fontinfo->descent = strtol(endtok,NULL,10);
+ else if ( mycmp("FSType",line+1,endtok)==0 )
+ fp->fd->fontinfo->fstype = strtol(endtok,NULL,10);
+ else if ( mycmp("BlendDesignPositions",line+1,endtok)==0 ) {
+ fp->pending_parse = &fp->fd->fontinfo->blenddesignpositions;
+ AddValue(fp,NULL,line,endtok);
+ } else if ( mycmp("BlendDesignMap",line+1,endtok)==0 ) {
+ fp->pending_parse = &fp->fd->fontinfo->blenddesignmap;
+ AddValue(fp,NULL,line,endtok);
+ } else if ( mycmp("BlendAxisTypes",line+1,endtok)==0 ) {
+ fp->pending_parse = &fp->fd->fontinfo->blendaxistypes;
+ AddValue(fp,NULL,line,endtok);
+ } else if ( !fp->alreadycomplained ) {
+ LogError( _("Didn't understand \"%s"), rmbinary(line) );
+ fp->alreadycomplained = true;
+ }
+ } else if ( fp->inblend ) {
+ if ( endtok==NULL ) {
+ if ( *line!='/' && strstr(line,"end")!=NULL )
+ fp->inblend = false;
+return;
+ }
+ /* Ignore anything in the blend dict defn */
+ } else if ( fp->inblendprivate || fp->inblendfi ) {
+ struct psdict *subdict = fp->inblendfi ? fp->fd->blendfontinfo : fp->fd->blendprivate;
+ if ( fp->multiline ) {
+ ContinueValue(fp,subdict,line);
+return;
+ } else if ( endtok==NULL ) {
+ if ( *line!='/' && strstr(line,"end")!=NULL ) {
+ fp->inblendprivate = fp->inblendfi = false;
+ fp->inprivate = true;
+ }
+return;
+ } else
+ AddValue(fp,subdict,line,endtok);
+ } else if ( fp->inprivate ) {
+ if ( strstr(line,"/CharStrings")!=NULL && strstr(line,"dict")!=NULL ) {
+ if ( fp->fd->chars->next==0 ) {
+ InitChars(fp->fd->chars,line);
+ fp->ignore = false;
+ } else {
+ fp->ignore = true;
+ LogError( _("Ignoring duplicate /CharStrings entry\n") );
+ }
+ fp->inchars = 1;
+ fp->insubs = 0;
+return;
+ } else if ( strstr(line,"/Subrs")!=NULL ) {
+ if ( fp->fd->private->subrs->next>0 ) {
+ fp->ignore = true;
+ LogError( _("Ignoring duplicate /Subrs entry\n") );
+ } else {
+ InitChars(fp->fd->private->subrs,line);
+ fp->ignore = false;
+ }
+ fp->insubs = 1;
+ fp->inchars = 0;
+return;
+ } else if ( fp->multiline ) {
+ ContinueValue(fp,fp->fd->private->private,line);
+return;
+ }
+ if ( endtok==NULL ) {
+ char *pt = line;
+ if ( *pt!='/' ) while ( (pt=strstr(pt,"end"))!=NULL ) {
+ if ( fp->inchars ) fp->inchars = false;
+ else fp->inprivate = false;
+ pt += 3;
+ }
+return;
+ }
+ if ( mycmp("ND",line+1,endtok)==0 || mycmp("|-",line+1,endtok)==0 ||
+ mycmp("NP",line+1,endtok)==0 || mycmp("|",line+1,endtok)==0 ||
+ mycmp("RD",line+1,endtok)==0 || mycmp("-|",line+1,endtok)==0 ||
+ mycmp("password",line+1,endtok)==0 ||
+ mycmp("MinFeature",line+1,endtok)==0 )
+ /* These conveigh no information, but are required */;
+ else if ( mycmp("UniqueID",line+1,endtok)==0 ) {
+ if ( fp->fd->uniqueid==0 )
+ fp->fd->uniqueid = strtol(endtok,NULL,10);
+ } else {
+ if ( mycmp("lenIV",line+1,endtok)==0 )
+ fp->fd->private->leniv = strtol(endtok,NULL,10); /* We need this value */
+ AddValue(fp,fp->fd->private->private,line,endtok);
+ }
+ } else if ( fp->incidsysteminfo ) {
+ if ( endtok==NULL && strncmp(line,"end", 3)==0 ) {
+ fp->incidsysteminfo=0;
+return;
+ } else if ( endtok==NULL )
+return;
+ if ( mycmp("Registry",line+1,endtok)==0 ) {
+ free( fp->fd->registry );
+ fp->fd->registry = getstring(endtok,in);
+ } else if ( mycmp("Ordering",line+1,endtok)==0 ) {
+ free( fp->fd->ordering );
+ fp->fd->ordering = getstring(endtok,in);
+ } else if ( mycmp("Supplement",line+1,endtok)==0 ) /* cff spec allows for copyright and notice */
+ fp->fd->supplement = strtol(endtok,NULL,0);
+ } else {
+ if ( strstr(line,"/Private")!=NULL && (strstr(line,"dict")!=NULL || strstr(line,"<<")!=NULL )) {
+ fp->infi = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->inprivate = fp->inblendprivate = fp->inblendfi = false;
+ if ( strstr(line,"/Blend")!=NULL ) {
+ fp->inblendprivate = 1;
+ fp->fd->blendprivate = gcalloc(1,sizeof(struct psdict));
+ InitDict(fp->fd->blendprivate,line);
+ } else {
+ fp->inprivate = 1;
+ InitDict(fp->fd->private->private,line);
+ }
+return;
+ } else if ( strstr(line,"/FontInfo")!=NULL && (strstr(line,"dict")!=NULL || strstr(line,"<<")!=NULL)) {
+ fp->inprivate = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->infi = fp->inblendprivate = fp->inblendfi = false;
+ if ( strstr(line,"/Blend")!=NULL ) {
+ fp->inblendfi = 1;
+ fp->fd->blendfontinfo = gcalloc(1,sizeof(struct psdict));
+ InitDict(fp->fd->blendfontinfo,line);
+ } else {
+ fp->infi = 1;
+ }
+return;
+ } else if ( strstr(line,"/Blend")!=NULL && strstr(line,"dict")!=NULL ) {
+ fp->inprivate = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->infi = fp->inblendprivate = fp->inblendfi = false;
+ fp->inblend = true;
+return;
+ } else if ( strstr(line,"/sfnts")!=NULL && strstr(line,"[")!=NULL ) {
+ sfnts2tempfile(fp,in,line);
+return;
+ } else if ( strstr(line,"/CharStrings")!=NULL && strstr(line,"dict")!=NULL
+ && fp->fd->fonttype!=3 ) {
+ if ( fp->fd->chars->next==0 ) {
+ InitChars(fp->fd->chars,line);
+ fp->ignore = false;
+ } else {
+ fp->ignore = true;
+ LogError( _("Ignoring duplicate /CharStrings entry\n") );
+ }
+ fp->inchars = 1;
+ fp->insubs = 0;
+ fp->infi = fp->inprivate = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->inblendprivate = fp->inblendfi = false;
+return;
+ } else if ( mycmp("/CharProcs",line,endtok)==0 ) {
+ InitCharProcs(fp->fd->charprocs,line);
+ fp->infi = fp->inprivate = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->insubs = 0;
+return;
+ } else if ( strstr(line,"/CIDSystemInfo")!=NULL ) {
+ fp->incidsysteminfo = 1;
+return;
+ } else if ( fp->inmetrics ) {
+ if ( endtok!=NULL )
+ AddValue(fp,fp->fd->metrics,line,endtok);
+return;
+ } else if ( fp->inbb ) {
+ /* Ignore it */;
+return;
+ }
+
+ if ( fp->multiline ) {
+ ContinueValue(fp,NULL,line);
+return;
+ }
+
+ if ( endtok==NULL ) {
+ if ( fp->skipping_mbf )
+ ;
+ else if ( fp->fdindex!=-1 && strstr(line,"end")!=NULL ) {
+ if ( ++fp->fdindex>=fp->mainfd->fdcnt )
+ fp->fd = fp->mainfd;
+ else
+ fp->fd = fp->mainfd->fds[fp->fdindex];
+ }
+return;
+ }
+ if ( mycmp("FontName",line+1,endtok)==0 ) {
+ if ( fp->fd->fontname==NULL )
+ fp->fd->fontname = gettoken(endtok);
+ else
+ free(gettoken(endtok)); /* skip it */
+ } else if ( mycmp("PaintType",line+1,endtok)==0 )
+ fp->fd->painttype = strtol(endtok,NULL,10);
+ else if ( mycmp("FontType",line+1,endtok)==0 )
+ fp->fd->fonttype = strtol(endtok,NULL,10);
+ else if ( mycmp("FontMatrix",line+1,endtok)==0 ) {
+ if ( fp->fd->fontmatrix[0]==0 )
+ fillrealarray(fp->fd->fontmatrix,endtok,6);
+ else {
+ real temp[6];
+ fillrealarray(temp,endtok,6);
+ }
+ } else if ( mycmp("LanguageLevel",line+1,endtok)==0 )
+ fp->fd->languagelevel = strtol(endtok,NULL,10);
+ else if ( mycmp("WMode",line+1,endtok)==0 )
+ fp->fd->wmode = strtol(endtok,NULL,10);
+ else if ( mycmp("FontBBox",line+1,endtok)==0 )
+ fillrealarray(fp->fd->fontbb,endtok,4);
+ else if ( mycmp("UniqueID",line+1,endtok)==0 ) {
+ if ( fp->fd->uniqueid==0 )
+ fp->fd->uniqueid = strtol(endtok,NULL,10);
+ } else if ( mycmp("UniqueId",line+1,endtok)==0 ) {
+ LogError(_("This font contains a \"UniqueId\" variable, but the correct name for it is\n\t\"UniqueID\" (postscript is case concious)\n") );
+ if ( fp->fd->uniqueid==0 )
+ fp->fd->uniqueid = strtol(endtok,NULL,10);
+ } else if ( mycmp("XUID",line+1,endtok)==0 ) {
+ if ( fp->fd->xuid[0]==0 )
+ fillintarray(fp->fd->xuid,endtok,20);
+ } else if ( mycmp("StrokeWidth",line+1,endtok)==0 )
+ fp->fd->strokewidth = strtod(endtok,NULL);
+ else if ( mycmp("WeightVector",line+1,endtok)==0 ) {
+ if ( fp->fd->weightvector==NULL ) {
+ fp->pending_parse = &fp->fd->weightvector;
+ AddValue(fp,NULL,line,endtok);
+ }
+ } else if ( mycmp("$Blend",line+1,endtok)==0 ) {
+ fp->pending_parse = &fp->fd->blendfunc;
+ AddValue(fp,NULL,line,endtok);
+ } else if ( strstr( line,"/NormalizeDesignVector" )!=NULL ) {
+ fp->pending_parse = &fp->fd->ndv;
+ AddValue(fp,NULL,line,endtok);
+ } else if ( strstr( line,"/ConvertDesignVector" )!=NULL ) {
+ fp->pending_parse = &fp->fd->cdv;
+ AddValue(fp,NULL,line,endtok);
+ } else if ( mycmp("BuildChar",line+1,endtok)==0 )
+ /* Do Nothing */;
+ else if ( mycmp("BuildGlyph",line+1,endtok)==0 )
+ /* Do Nothing */;
+ else if ( mycmp("CIDFontName",line+1,endtok)==0 ) {
+ free( fp->fd->cidfontname );
+ fp->fd->cidfontname = gettoken(endtok);
+ } else if ( mycmp("CIDFontVersion",line+1,endtok)==0 ) {
+ fp->fd->cidversion = strtod(endtok,NULL);
+#if 0
+ if ( fp->fd->fontinfo->version==NULL ) {
+ char temp[40];
+ sprintf(temp,"%f", fp->fd->cidversion);
+ fp->fd->fontinfo->version = copy(temp);
+ }
+#endif
+ } else if ( mycmp("CIDFontType",line+1,endtok)==0 )
+ fp->fd->cidfonttype = strtol(endtok,NULL,10);
+ else if ( mycmp("UIDBase",line+1,endtok)==0 )
+ fp->fd->uniqueid = strtol(endtok,NULL,10);
+ else if ( mycmp("CIDMapOffset",line+1,endtok)==0 )
+ fp->fd->mapoffset = strtol(endtok,NULL,10);
+ else if ( mycmp("FDBytes",line+1,endtok)==0 )
+ fp->fd->fdbytes = strtol(endtok,NULL,10);
+ else if ( mycmp("GDBytes",line+1,endtok)==0 )
+ fp->fd->gdbytes = strtol(endtok,NULL,10);
+ else if ( mycmp("CIDCount",line+1,endtok)==0 )
+ fp->fd->cidcnt = strtol(endtok,NULL,10);
+ else if ( mycmp("FDArray",line+1,endtok)==0 ) { int i;
+ fp->mainfd = fp->fd;
+ fp->fd->fdcnt = strtol(endtok,NULL,10);
+ fp->fd->fds = gcalloc(fp->fd->fdcnt,sizeof(struct fontdict *));
+ for ( i=0; i<fp->fd->fdcnt; ++i )
+ fp->fd->fds[i] = MakeEmptyFont();
+ fp->fdindex = 0;
+ fp->fd = fp->fd->fds[0];
+ } else if ( mycmp("FontSetInit",line+1,endtok)==0 ) {
+ fp->iscff = true;
+ fp->iscid = false;
+ } else if ( mycmp("CIDInit",line+1,endtok)==0 ) {
+ fp->iscid = true;
+ fp->iscff = false;
+ } else if ( fp->skipping_mbf ) { /* Skip over the makeblendedfont defn in a multimaster font */
+ /* Do Nothing */
+ } else if ( !fp->alreadycomplained ) {
+ LogError( _("Didn't understand \"%s"), rmbinary(line) );
+ fp->alreadycomplained = true;
+ }
+ }
+}
+
+static void addinfo(struct fontparse *fp,char *line,char *tok,char *binstart,int binlen,FILE *in) {
+ char *pt;
+
+ decodestr((unsigned char *) binstart,binlen);
+ binstart += fp->fd->private->leniv;
+ binlen -= fp->fd->private->leniv;
+ if ( binlen<0 ) {
+ LogError( _("Bad CharString. Does not include lenIV bytes.\n") );
+return;
+ }
+
+ retry:
+ if ( fp->insubs ) {
+ struct pschars *chars = /*fp->insubs ?*/ fp->fd->private->subrs /*: fp->fd->private->othersubrs*/;
+ while ( Isspace(*line)) ++line;
+ if ( strncmp(line,"dup ",4)==0 ) {
+ int i = strtol(line+4,NULL,10);
+ if ( fp->ignore )
+ /* Do Nothing */;
+ else if ( i<chars->cnt ) {
+ if ( chars->values[i]!=NULL )
+ LogError( _("Duplicate definition of subroutine %d\n"), i );
+ chars->lens[i] = binlen;
+ chars->values[i] = galloc(binlen);
+ memcpy(chars->values[i],binstart,binlen);
+ if ( i>=chars->next ) chars->next = i+1;
+ } else if ( !fp->alreadycomplained ) {
+ LogError( _("Index too big (must be <%d) \"%s"), chars->cnt, rmbinary(line));
+ fp->alreadycomplained = true;
+ }
+ } else if ( !fp->alreadycomplained ) {
+ LogError( _("Didn't understand \"%s"), rmbinary(line) );
+ fp->alreadycomplained = true;
+ }
+ } else if ( fp->inchars ) {
+ struct pschars *chars = fp->fd->chars;
+ if ( *tok=='\0' )
+ LogError( _("No name for CharStrings dictionary \"%s"), rmbinary(line) );
+ else if ( fp->ignore )
+ /* Do Nothing */;
+ else if ( chars->next>=chars->cnt )
+ LogError( _("Too many entries in CharStrings dictionary \"%s"), rmbinary(line) );
+ else {
+ int i = chars->next;
+ chars->lens[i] = binlen;
+ chars->keys[i] = copy(tok);
+ chars->values[i] = galloc(binlen);
+ memcpy(chars->values[i],binstart,binlen);
+ ++chars->next;
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_next();
+#endif
+ }
+ } else if ( !fp->alreadycomplained ) {
+ /* Special hacks for known badly formatted fonts */
+ if ( strstr(line,"/CharStrings")!=NULL ) {
+ for ( pt=line; *pt!='/'; ++pt );
+ pt = strchr(pt+1,'/');
+ if ( pt!=NULL )
+ *pt = '\0';
+ parseline(fp,line,in);
+ if ( pt!=NULL ) {
+ *pt = '/';
+ line = pt;
+ goto retry;
+ }
+return;
+ } else if ( strstr(line,"/Subrs")!=NULL ) {
+ pt = strstr(line,"dup");
+ if ( pt!=NULL )
+ *pt = '\0';
+ parseline(fp,line,in);
+ if ( pt!=NULL ) {
+ *pt = 'd';
+ line = pt;
+ goto retry;
+ }
+return;
+ }
+ LogError( _("Shouldn't be in addinfo \"%s"), rmbinary(line) );
+ fp->alreadycomplained = true;
+ }
+}
+
+/* In the book the token which starts a character description is always RD but*/
+/* it's just the name of a subroutine which is defined in the private diction*/
+/* and it could be anything. in one case it was "-|" (hyphen bar) so we can't*/
+/* just look for RD we must be a bit smarter and figure out what the token is*/
+/* (oh. I see now. it's allowed to be either one "RD" or "-|", but nothing else*/
+/* right) */
+/* It's defined as {string currentfile exch readstring pop} so look for that */
+/* Except that in gsf files we've also got "/-!{string currentfile exch readhexstring pop} readonly def" */
+/* NOTE: readhexstring!!! */
+/* And in files generated by GNU fontutils */
+static int glorpline(struct fontparse *fp, FILE *temp, char *rdtok) {
+ static char *buffer=NULL, *end;
+ char *pt, *binstart;
+ int binlen;
+ int ch;
+ int innum, val=0, inbinary, cnt=0, inr, wasspace, nownum, nowr, nowspace, sptok;
+ char *rdline = "{string currentfile exch readstring pop}", *rpt;
+ char *rdline2 = "{string currentfile exch readhexstring pop}";
+ char *tokpt = NULL, *rdpt;
+ char temptok[255];
+ int intok, first;
+ int wasminus=false, isminus, nibble=0, firstnibble=true, inhex;
+ int willbehex = false;
+
+ ch = getc(temp);
+ if ( ch==EOF )
+return( 0 );
+ ungetc(ch,temp);
+
+ if ( buffer==NULL ) {
+ buffer = galloc(3000);
+ end = buffer+3000;
+ }
+ innum = inr = 0; wasspace = 0; inbinary = 0; rpt = NULL; rdpt = NULL;
+ inhex = 0;
+ pt = buffer; binstart=NULL; binlen = 0; intok=0; sptok=0; first=1;
+ temptok[0] = '\0';
+ while ( (ch=getc(temp))!=EOF ) {
+ if ( pt>=end ) {
+ char *old = buffer;
+ int len = (end-buffer)+2000;
+ buffer = grealloc(buffer,len);
+ end = buffer+len;
+ pt = buffer+(pt-old);
+ if ( binstart!=NULL )
+ binstart = buffer+(binstart-old);
+ }
+ *pt++ = ch;
+ isminus = ch=='-' && wasspace;
+ nownum = nowspace = nowr = 0;
+ if ( rpt!=NULL && ch!=*rpt && ch=='h' && rpt-rdline>25 && rpt-rdline<30 &&
+ rdline2[rpt-rdline]=='h' ) {
+ rpt = rdline2 + (rpt-rdline);
+ willbehex = true;
+ }
+ if ( inbinary ) {
+ if ( --cnt==0 )
+ inbinary = 0;
+ } else if ( inhex ) {
+ if ( Ishexdigit(ch)) {
+ int h;
+ if ( Isdigit(ch)) h = ch-'0';
+ else if ( ch>='a' && ch<='f' ) h = ch-'a'+10;
+ else h = ch-'A'+10;
+ if ( firstnibble ) {
+ nibble = h;
+ --pt;
+ } else {
+ pt[-1] = (nibble<<4)|h;
+ if ( --cnt==0 )
+ inbinary = inhex = 0;
+ }
+ firstnibble = !firstnibble;
+ } else {
+ --pt;
+ /* skip everything not hex */
+ }
+ } else if ( ch=='/' ) {
+ intok = 1;
+ tokpt = temptok;
+ } else if ( intok && !Isspace(ch) && ch!='{' && ch!='[' ) {
+ *tokpt++ = ch;
+ } else if ( (intok||sptok) && (ch=='{' || ch=='[')) {
+ *tokpt = '\0';
+ rpt = rdline+1;
+ intok = sptok = 0;
+ } else if ( intok ) {
+ *tokpt = '\0';
+ intok = 0;
+ sptok = 1;
+ } else if ( sptok && Isspace(ch)) {
+ nowspace = 1;
+ if ( ch=='\n' || ch=='\r' )
+ break;
+ } else if ( sptok && !Isdigit(ch))
+ sptok = 0;
+ else if ( rpt!=NULL && ch==*rpt ) {
+ if ( *++rpt=='\0' ) {
+ /* it matched the character definition string so this is the */
+ /* token we want to search for */
+ strcpy(rdtok,temptok);
+ fp->useshexstrings = willbehex;
+ rpt = NULL;
+ }
+ } else if ( rpt!=NULL && ch==' ' ) {
+ /* Extra spaces are ok */
+ } else if ( rpt!=NULL ) {
+ rpt = NULL;
+ willbehex = false;
+ } else if ( Isdigit(ch)) {
+ sptok = 0;
+ nownum = 1;
+ if ( innum )
+ val = 10*val + ch-'0';
+ else
+ val = ch-'0';
+ } else if ( Isspace(ch)) {
+ nowspace = 1;
+ if ( ch=='\n' || ch=='\r' )
+ break;
+ } else if ( wasspace && ch==*rdtok ) {
+ nowr = 1;
+ fp->useshexstrings = willbehex;
+ rdpt = rdtok+1;
+ } else if ( wasspace && ch=='-' ) { /* fonts produced by type1fix seem to define both "RD" and "-|" which confused me. so just respond to either */
+ nowr = 1;
+ fp->useshexstrings = false;
+ rdpt = "|";
+ } else if ( wasspace && ch=='R' ) { /* fonts produced by type1fix seem to define both "RD" and "-|" which confused me. so just respond to either */
+ nowr = 1;
+ fp->useshexstrings = false;
+ rdpt = "D";
+ } else if ( inr && ch==*rdpt ) {
+ if ( *++rdpt =='\0' ) {
+ ch = getc(temp);
+ *pt++ = ch;
+ if ( Isspace(ch) && val!=0 ) {
+ inhex = fp->useshexstrings;
+ inbinary = !fp->useshexstrings;
+ firstnibble = true;
+ cnt = val;
+ binstart = pt;
+ binlen = val;
+ }
+ } else
+ nowr = 1;
+ } else if ( wasminus && ch=='!' ) {
+ ch = getc(temp);
+ *pt++ = ch;
+ if ( Isspace(ch) && val!=0 ) {
+ inhex = 1;
+ cnt = val;
+ binstart = pt;
+ binlen = val;
+ firstnibble = true;
+ }
+ }
+ innum = nownum; wasspace = nowspace; inr = nowr;
+ wasminus = isminus;
+ first = 0;
+ }
+ *pt = '\0';
+ if ( binstart==NULL ) {
+ parseline(fp,buffer,temp);
+ } else {
+ addinfo(fp,buffer,temptok,binstart,binlen,temp);
+ }
+return( 1 );
+}
+
+static int nrandombytes[4];
+#define EODMARKLEN 16
+
+#define bgetc(extra,in) (*(extra)=='\0' ? getc(in) : (unsigned char ) *(extra)++ )
+
+static void decrypteexec(FILE *in,FILE *temp, int hassectionheads,char *extra) {
+ int ch1, ch2, ch3, ch4, binary;
+ int zcnt;
+ unsigned char zeros[EODMARKLEN+6+1];
+ int sect_len=0x7fffffff;
+
+ if ( extra==(void *) 5 ) extra = "";
+
+ /* The PLRM defines white space to include form-feed and null. The t1_spec*/
+ /* does not. The t1_spec wins here. Someone gave me a font which began */
+ /* with a formfeed and that was part of the encrypted body */
+ while ( (ch1=bgetc(extra,in))!=EOF && (ch1==' ' || ch1=='\t' || ch1=='\n' || ch1=='\r'));
+ if ( ch1==0200 && hassectionheads ) {
+ /* skip the 6 byte section header in pfb files that follows eexec */
+ ch1 = bgetc(extra,in);
+ sect_len = bgetc(extra,in);
+ sect_len |= bgetc(extra,in)<<8;
+ sect_len |= bgetc(extra,in)<<16;
+ sect_len |= bgetc(extra,in)<<24;
+ sect_len -= 3;
+ ch1 = bgetc(extra,in);
+ }
+ ch2 = bgetc(extra,in); ch3 = bgetc(extra,in); ch4 = bgetc(extra,in);
+ binary = 0;
+ if ( ch1<'0' || (ch1>'9' && ch1<'A') || ( ch1>'F' && ch1<'a') || (ch1>'f') ||
+ ch2<'0' || (ch2>'9' && ch2<'A') || (ch2>'F' && ch2<'a') || (ch2>'f') ||
+ ch3<'0' || (ch3>'9' && ch3<'A') || (ch3>'F' && ch3<'a') || (ch3>'f') ||
+ ch4<'0' || (ch4>'9' && ch4<'A') || (ch4>'F' && ch4<'a') || (ch4>'f') )
+ binary = 1;
+ if ( ch1==EOF || ch2==EOF || ch3==EOF || ch4==EOF ) {
+return;
+ }
+
+ initcode();
+ if ( binary ) {
+ nrandombytes[0] = decode(ch1);
+ nrandombytes[1] = decode(ch2);
+ nrandombytes[2] = decode(ch3);
+ nrandombytes[3] = decode(ch4);
+ zcnt = 0;
+ while (( ch1=bgetc(extra,in))!=EOF ) {
+ --sect_len;
+ if ( hassectionheads ) {
+ if ( sect_len==0 && ch1==0200 ) {
+ ch1 = bgetc(extra,in);
+ sect_len = bgetc(extra,in);
+ sect_len |= bgetc(extra,in)<<8;
+ sect_len |= bgetc(extra,in)<<16;
+ sect_len |= bgetc(extra,in)<<24;
+ sect_len += 1;
+ if ( ch1=='\1' )
+ break;
+ } else {
+ dumpzeros(temp,zeros,zcnt);
+ zcnt = 0;
+ putc(decode(ch1),temp);
+ }
+ } else {
+ if ( ch1=='0' ) ++zcnt; else {dumpzeros(temp,zeros,zcnt); zcnt = 0; }
+ if ( zcnt>EODMARKLEN )
+ break;
+ if ( zcnt==0 )
+ putc(decode(ch1),temp);
+ else
+ zeros[zcnt-1] = decode(ch1);
+ }
+ }
+ } else {
+ nrandombytes[0] = decode(hex(ch1,ch2));
+ nrandombytes[1] = decode(hex(ch3,ch4));
+ ch1 = bgetc(extra,in); ch2 = bgetc(extra,in); ch3 = bgetc(extra,in); ch4 = bgetc(extra,in);
+ nrandombytes[2] = decode(hex(ch1,ch2));
+ nrandombytes[3] = decode(hex(ch3,ch4));
+ zcnt = 0;
+ while (( ch1=bgetc(extra,in))!=EOF ) {
+ while ( ch1!=EOF && Isspace(ch1)) ch1 = bgetc(extra,in);
+ while ( (ch2=bgetc(extra,in))!=EOF && Isspace(ch2));
+ if ( ch1=='0' && ch2=='0' ) ++zcnt; else { dumpzeros(temp,zeros,zcnt); zcnt = 0;}
+ if ( zcnt>EODMARKLEN )
+ break;
+ if ( zcnt==0 )
+ putc(decode(hex(ch1,ch2)),temp);
+ else
+ zeros[zcnt-1] = decode(hex(ch1,ch2));
+ }
+ }
+ while (( ch1=bgetc(extra,in))=='0' || Isspace(ch1) );
+ if ( ch1!=EOF ) ungetc(ch1,in);
+}
+
+static void decryptagain(struct fontparse *fp,FILE *temp,char *rdtok) {
+ while ( glorpline(fp,temp,rdtok));
+}
+
+static void parsetype3(struct fontparse *fp,FILE *in) {
+ PSFontInterpretPS(in,fp->fd->charprocs,fp->fd->encoding );
+}
+
+static unsigned char *readt1str(FILE *temp,int offset,int len,int leniv) {
+ int i;
+ unsigned char *str, *pt;
+ unsigned short r = 4330;
+ unsigned char plain, cypher;
+ /* The CID spec doesn't mention this, but the type 1 strings are all */
+ /* eexec encrupted (with the nested encryption). Remember leniv varies */
+ /* from fd to fd (potentially) */
+ /* I'm told (by Ian Kemmish) that leniv==-1 => no eexec encryption */
+
+ fseek(temp,offset,SEEK_SET);
+ if ( leniv<0 ) {
+ str = pt = galloc(len+1);
+ for ( i=0 ; i<len; ++i )
+ *pt++ = getc(temp);
+ } else {
+ for ( i=0; i<leniv; ++i ) {
+ cypher = getc(temp);
+ plain = ( cypher ^ (r>>8));
+ r = (cypher + r) * c1 + c2;
+ }
+ str = pt = galloc(len-leniv+1);
+ for (; i<len; ++i ) {
+ cypher = getc(temp);
+ plain = ( cypher ^ (r>>8));
+ r = (cypher + r) * c1 + c2;
+ *pt++ = plain;
+ }
+ }
+ *pt = '\0';
+return( str );
+}
+
+static void figurecids(struct fontparse *fp,FILE *temp) {
+ struct fontdict *fd = fp->mainfd;
+ int i,j,k,val;
+ int *offsets;
+ int cidcnt = fd->cidcnt;
+ int leniv;
+ /* Some cid formats don't have any of these */
+
+ fd->cidstrs = galloc(cidcnt*sizeof(uint8 *));
+ fd->cidlens = galloc(cidcnt*sizeof(int16));
+ fd->cidfds = galloc((cidcnt+1)*sizeof(int16));
+ offsets = galloc((cidcnt+1)*sizeof(int));
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_change_total(cidcnt);
+#endif
+
+ fseek(temp,fd->mapoffset,SEEK_SET);
+ for ( i=0; i<=fd->cidcnt; ++i ) {
+ for ( j=val=0; j<fd->fdbytes; ++j )
+ val = (val<<8) + getc(temp);
+ if ( val >= fd->fdcnt && val!=255 ) { /* 255 is a special mark */
+ LogError( _("Invalid FD (%d) assigned to CID %d.\n"), val, i );
+ val = 0;
+ }
+ fd->cidfds[i] = val;
+ for ( j=val=0; j<fd->gdbytes; ++j )
+ val = (val<<8) + getc(temp);
+ offsets[i] = val;
+ if ( i!=0 ) {
+ fd->cidlens[i-1] = offsets[i]-offsets[i-1];
+ if ( fd->cidlens[i-1]<0 ) {
+ LogError( _("Bad CID offset for CID %d\n"), i-1 );
+ fd->cidlens[i-1] = 0;
+ }
+ }
+ }
+
+ for ( i=0; i<fd->cidcnt; ++i ) {
+ if ( fd->cidlens[i]== 0 )
+ fd->cidstrs[i] = NULL;
+ else {
+ fd->cidstrs[i] = readt1str(temp,offsets[i],fd->cidlens[i],
+ fd->fds[fd->cidfds[i]]->private->leniv);
+ fd->cidlens[i] -= fd->fds[fd->cidfds[i]]->private->leniv;
+ }
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_next();
+#endif
+ }
+ free(offsets);
+
+ for ( k=0; k<fd->fdcnt; ++k ) {
+ struct private *private = fd->fds[k]->private;
+ char *ssubroff = PSDictHasEntry(private->private,"SubrMapOffset");
+ char *ssdbytes = PSDictHasEntry(private->private,"SDBytes");
+ char *ssubrcnt = PSDictHasEntry(private->private,"SubrCount");
+ int subroff, sdbytes, subrcnt;
+
+ if ( ssubroff!=NULL && ssdbytes!=NULL && ssubrcnt!=NULL &&
+ (subroff=strtol(ssubroff,NULL,10))>=0 &&
+ (sdbytes=strtol(ssdbytes,NULL,10))>0 &&
+ (subrcnt=strtol(ssubrcnt,NULL,10))>0 ) {
+ private->subrs->cnt = subrcnt;
+ private->subrs->values = gcalloc(subrcnt,sizeof(char *));
+ private->subrs->lens = gcalloc(subrcnt,sizeof(int));
+ leniv = private->leniv;
+ offsets = galloc((subrcnt+1)*sizeof(int));
+ fseek(temp,subroff,SEEK_SET);
+ for ( i=0; i<=subrcnt; ++i ) {
+ for ( j=val=0; j<sdbytes; ++j )
+ val = (val<<8) + getc(temp);
+ offsets[i] = val;
+ if ( i!=0 )
+ private->subrs->lens[i-1] = offsets[i]-offsets[i-1];
+ }
+ for ( i=0; i<subrcnt; ++i ) {
+ private->subrs->values[i] = readt1str(temp,offsets[i],
+ private->subrs->lens[i],leniv);
+ }
+ private->subrs->next = i;
+ free(offsets);
+ }
+ PSDictRemoveEntry(private->private,"SubrMapOffset");
+ PSDictRemoveEntry(private->private,"SDBytes");
+ PSDictRemoveEntry(private->private,"SubrCount");
+ }
+}
+
+static void dodata( struct fontparse *fp, FILE *in, FILE *temp) {
+ int binary, cnt, len;
+ int ch, ch2;
+ char *pt;
+ char fontsetname[256];
+
+ while ( (ch=getc(in))!='(' && ch!='/' && ch!=EOF );
+ if ( ch=='/' ) {
+ /* There appears to be no provision for a hex encoding here */
+ /* Why can't they use the same format for routines with the same name? */
+ binary = true;
+ for ( pt=fontsetname; (ch=getc(in))!=' ' && ch!=EOF; )
+ if ( pt<fontsetname+sizeof(fontsetname)-1 )
+ *pt++= ch;
+ *pt = '\0';
+ } else {
+ if ( (ch=getc(in))=='B' || ch=='b' ) binary = true;
+ else if ( ch=='H' || ch=='h' ) binary = false;
+ else {
+ binary = true; /* Who knows? */
+ LogError( _("Failed to parse the StartData command properly\n") );
+ }
+ fontsetname[0] = '\0';
+ while ( (ch=getc(in))!=')' && ch!=EOF );
+ }
+ if ( fscanf( in, "%d", &len )!=1 || len<=0 ) {
+ len = 0;
+ LogError( _("Failed to parse the StartData command properly, bad count\n") );
+ }
+ cnt = len;
+ while ( Isspace(ch=getc(in)) );
+ ungetc(ch,in);
+ for ( pt="StartData "; *pt; ++pt )
+ getc(in); /* And if it didn't match, what could I do about it? */
+ if ( binary ) {
+ while ( cnt>0 ) {
+ ch = getc(in);
+ putc(ch,temp);
+ --cnt;
+ }
+ } else {
+ while ( cnt>0 ) {
+ /* Hex data are allowed to contain whitespace */
+ while ( Isspace(ch=getc(in)) );
+ while ( Isspace(ch2=getc(in)) );
+ ch = hex(ch,ch2);
+ putc(ch,temp);
+ --cnt;
+ }
+ if ( (ch=getc(in))!='>' ) ungetc(ch,in);
+ }
+ rewind(temp);
+ if ( fp->iscid )
+ figurecids(fp,temp);
+ else {
+ fp->fd->sf = _CFFParse(temp,len,fontsetname);
+ fp->fd->wascff = true;
+ }
+}
+
+static void realdecrypt(struct fontparse *fp,FILE *in, FILE *temp) {
+ char buffer[256];
+ int first, hassectionheads;
+ char rdtok[20];
+ int saw_blend = false;
+
+ strcpy(rdtok,"RD");
+
+ first = 1; hassectionheads = 0;
+ while ( myfgets(buffer,sizeof(buffer),in)!=NULL ) {
+ if ( strstr(buffer, "Blend")!=NULL )
+ saw_blend = true;
+ if ( first && buffer[0]=='\200' ) {
+ hassectionheads = 1;
+ fp->fd->wasbinary = true;
+ parseline(fp,buffer+6,in);
+ } else if ( strstr(buffer,"CharProcs")!=NULL && strstr(buffer,"begin")!=NULL ) {
+ parsetype3(fp,in);
+return;
+ } else if ( fp->fd->fonttype!=42 && strstr(buffer,"CharStrings")!=NULL && strstr(buffer,"begin")!=NULL ) {
+ /* Fontographer uses CharStrings even though they aren't */
+ parsetype3(fp,in);
+return;
+ } else if ( !fp->iscid ) {
+ if ( saw_blend )
+ parseline(fp,buffer,in);
+ /* But if it's a multi master font, don't do the special private hack */
+ else if ( strstr(buffer,"/CharStrings")!=NULL &&
+ strstr(buffer,"begin")!=NULL &&
+ (fp->fd->fonttype!=42 && fp->fd->cidfonttype!=2)) {
+ /* gsf files are not eexec encoded, but the charstrings are encoded*/
+ InitChars(fp->fd->chars,buffer);
+ fp->inchars = 1;
+ decryptagain(fp,in,rdtok);
+return;
+ } else if ( strstr(buffer,"/Subrs")!=NULL && strstr(buffer,"array")!=NULL ) {
+ /* Same case as above */
+ InitChars(fp->fd->private->subrs,buffer);
+ fp->insubs = 1;
+ decryptagain(fp,in,rdtok);
+return;
+ } else if ( strstr(buffer,"/Private")!=NULL && (strstr(buffer,"dict")!=NULL || strstr(buffer,"<<")!=NULL )) {
+ /* files produced by GNU fontutils have some of the same issues */
+ fp->inprivate = 1;
+ fp->infi = false;
+ decryptagain(fp,in,rdtok);
+return;
+ } else
+ parseline(fp,buffer,in);
+ } else
+ parseline(fp,buffer,in);
+ first = 0;
+ if ( strstr(buffer,"%%BeginData: ")!=NULL )
+ break;
+ if ( strstr(buffer,"currentfile")!=NULL && strstr(buffer, "eexec")!=NULL ) {
+ fp->skipping_mbf = false;
+ break;
+ }
+ /* Hmm. These lines were put in to handle parsing type42 fonts, but */
+ /* they break multimaster fonts, and they don't seem to be needed */
+ /* for type42s any more either. So... Away with them */
+#if 0
+ if ( strstr(buffer,"definefont")!=NULL )
+ break;
+#endif
+ }
+
+ if ( strstr(buffer,"%%BeginData: ")!=NULL ) {
+ /* used by both CID fonts and CFF fonts (and chameleons, whatever they are) */
+ dodata(fp,in,temp);
+ } else if ( strstr(buffer,"eexec")!=NULL ) {
+ decrypteexec(in,temp,hassectionheads,strstr(buffer, "eexec")+5);
+ rewind(temp);
+ decryptagain(fp,temp,rdtok);
+ while ( myfgets(buffer,sizeof(buffer),in)!=NULL ) {
+ if ( buffer[0]!='\200' || !hassectionheads )
+ parseline(fp,buffer,in);
+ }
+ } else if (( fp->fd->fonttype==42 || fp->fd->cidfonttype==2 ) && fp->sfnts!=NULL ) {
+ fp->fd->sf = _SFReadTTF(fp->sfnts,0,0,"<Temp File>",fp->fd);
+ fclose(fp->sfnts);
+ }
+}
+
+FontDict *_ReadPSFont(FILE *in) {
+ FILE *temp;
+ struct fontparse fp;
+ char *oldloc;
+ struct stat b;
+
+ temp = tmpfile();
+ if ( temp==NULL ) {
+ LogError( _("Cannot open a temporary file\n") );
+ fclose(in);
+return(NULL);
+ }
+
+ oldloc = setlocale(LC_NUMERIC,"C");
+ memset(&fp,'\0',sizeof(fp));
+ fp.fd = fp.mainfd = PSMakeEmptyFont();
+ fp.fdindex = -1;
+ realdecrypt(&fp,in,temp);
+ free(fp.vbuf);
+ setlocale(LC_NUMERIC,oldloc);
+
+ fclose(temp);
+
+ if ( fstat(fileno(in),&b)!=-1 ) {
+ fp.fd->modificationtime = b.st_mtime;
+ fp.fd->creationtime = b.st_mtime;
+ }
+return( fp.fd );
+}
+
+FontDict *ReadPSFont(char *fontname) {
+ FILE *in;
+ FontDict *fd;
+
+ in = fopen(fontname,"rb");
+ if ( in==NULL ) {
+ LogError( _("Cannot open %s\n"), fontname );
+return(NULL);
+ }
+ fd = _ReadPSFont(in);
+ fclose(in);
+return( fd );
+}
+
+void PSCharsFree(struct pschars *chrs) {
+ int i;
+
+ if ( chrs==NULL )
+return;
+ for ( i=0; i<chrs->next; ++i ) {
+ if ( chrs->keys!=NULL ) free(chrs->keys[i]);
+ free(chrs->values[i]);
+ }
+ free(chrs->lens);
+ free(chrs->keys);
+ free(chrs->values);
+ free(chrs);
+}
+
+void PSDictFree(struct psdict *dict) {
+ int i;
+
+ if ( dict==NULL )
+return;
+ for ( i=0; i<dict->next; ++i ) {
+ if ( dict->keys!=NULL ) free(dict->keys[i]);
+ free(dict->values[i]);
+ }
+ free(dict->keys);
+ free(dict->values);
+ free(dict);
+}
+
+static void PrivateFree(struct private *prv) {
+ PSCharsFree(prv->subrs);
+#if 1
+ PSDictFree(prv->private);
+#else
+ PSCharsFree(prv->othersubrs);
+ free(prv->minfeature);
+ free(prv->nd);
+ free(prv->np);
+ free(prv->rd);
+#endif
+ free(prv);
+}
+
+static void FontInfoFree(struct fontinfo *fi) {
+ free(fi->familyname);
+ free(fi->fullname);
+ free(fi->notice);
+ free(fi->weight);
+ free(fi->version);
+ free(fi->blenddesignpositions);
+ free(fi->blenddesignmap);
+ free(fi->blendaxistypes);
+ free(fi);
+}
+
+void PSFontFree(FontDict *fd) {
+ int i;
+
+ if ( fd->encoding!=NULL )
+ for ( i=0; i<256; ++i )
+ free( fd->encoding[i]);
+ free(fd->fontname);
+ free(fd->cidfontname);
+ free(fd->registry);
+ free(fd->ordering);
+ FontInfoFree(fd->fontinfo);
+ PSCharsFree(fd->chars);
+ PrivateFree(fd->private);
+ if ( fd->charprocs!=NULL ) {
+ for ( i=0; i<fd->charprocs->cnt; ++i )
+ free(fd->charprocs->keys[i]);
+ free(fd->charprocs->keys);
+ free(fd->charprocs->values);
+ free(fd->charprocs);
+ }
+ if ( fd->cidstrs!=NULL ) {
+ for ( i=0; i<fd->cidcnt; ++i )
+ free( fd->cidstrs[i]);
+ free(fd->cidstrs);
+ }
+ free(fd->cidlens);
+ free(fd->cidfds);
+ if ( fd->fds!=NULL ) {
+ for ( i=0; i<fd->fdcnt; ++i )
+ PSFontFree(fd->fds[i]);
+ free(fd->fds);
+ }
+ free(fd->blendfunc);
+ free(fd->weightvector);
+ free(fd->cdv);
+ free(fd->ndv);
+
+ PSDictFree(fd->blendprivate);
+ PSDictFree(fd->blendfontinfo);
+
+ free(fd);
+}
+
+char **_NamesReadPostscript(FILE *ps) {
+ char **ret = NULL;
+ char buffer[2000], *pt, *end;
+
+ if ( ps!=NULL ) {
+ while ( fgets(buffer,sizeof(buffer),ps)!=NULL ) {
+ if ( strstr(buffer,"/FontName")!=NULL ||
+ strstr(buffer,"/CIDFontName")!=NULL ) {
+ pt = strstr(buffer,"FontName");
+ pt += strlen("FontName");
+ while ( Isspace(*pt)) ++pt;
+ if ( *pt=='/' ) ++pt;
+ for ( end = pt; *end!='\0' && !Isspace(*end); ++end );
+ ret = galloc(2*sizeof(char *));
+ ret[0] = copyn(pt,end-pt);
+ ret[1] = NULL;
+ break;
+ } else if ( strstr(buffer,"currentfile")!=NULL && strstr(buffer,"eexec")!=NULL )
+ break;
+ else if ( strstr(buffer,"%%BeginData")!=NULL )
+ break;
+ }
+ fclose(ps);
+ }
+return( ret );
+}
+
+char **NamesReadPostscript(char *filename) {
+return( _NamesReadPostscript( fopen(filename,"rb")));
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/parsettf.c b/Build/source/libs/luafontforge/fontforge/fontforge/parsettf.c
new file mode 100644
index 00000000000..accfe87e1eb
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/parsettf.c
@@ -0,0 +1,5558 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include <chardata.h>
+#include <utype.h>
+#include <ustring.h>
+#include <math.h>
+#include <locale.h>
+#include <gwidget.h>
+#include "ttf.h"
+
+
+/* needed for ps validation */
+#ifdef LUA_FF_LIB
+#define Isdigit(a) ((a)>='0' && (a)<='9')
+#else
+#define Isdigit isdigit
+#endif
+
+/* True Type is a really icky format. Nothing is together. It's badly described */
+/* much of the description is misleading */
+/* Apple's version: */
+/* http://fonts.apple.com/TTRefMan/index.html */
+/* MS's version: */
+/* http://www.microsoft.com/typography/tt/tt.htm */
+/* An helpful but incomplete description is given at */
+/* http://www.truetype.demon.co.uk/ttoutln.htm */
+/* For some things I looked at freetype's code to see how they did it */
+/* (I think only for what happens if !ARGS_ARE_XY) */
+/* http://freetype.sourceforge.net/ */
+/* It grows on you though... now that I understand it better it seems better designed */
+/* but the docs remain in conflict. Sometimes badly so */
+
+/* !!!I don't currently parse instructions to get hints, but I do save them */
+
+int prefer_cjk_encodings=false;
+
+int getushort(FILE *ttf) {
+ int ch1 = getc(ttf);
+ int ch2 = getc(ttf);
+ if ( ch2==EOF )
+return( EOF );
+return( (ch1<<8)|ch2 );
+}
+
+int get3byte(FILE *ttf) {
+ int ch1 = getc(ttf);
+ int ch2 = getc(ttf);
+ int ch3 = getc(ttf);
+ if ( ch3==EOF )
+return( EOF );
+return( (ch1<<16)|(ch2<<8)|ch3 );
+}
+
+int32 getlong(FILE *ttf) {
+ int ch1 = getc(ttf);
+ int ch2 = getc(ttf);
+ int ch3 = getc(ttf);
+ int ch4 = getc(ttf);
+ if ( ch4==EOF )
+return( EOF );
+return( (ch1<<24)|(ch2<<16)|(ch3<<8)|ch4 );
+}
+
+static int32 getoffset(FILE *ttf, int offsize) {
+ if ( offsize==1 )
+return( getc(ttf));
+ else if ( offsize==2 )
+return( getushort(ttf));
+ else if ( offsize==3 )
+return( get3byte(ttf));
+ else
+return( getlong(ttf));
+}
+
+real getfixed(FILE *ttf) {
+ int32 val = getlong(ttf);
+ int mant = val&0xffff;
+ /* This oddity may be needed to deal with the first 16 bits being signed */
+ /* and the low-order bits unsigned */
+return( (real) (val>>16) + (mant/65536.0) );
+}
+
+real get2dot14(FILE *ttf) {
+ int32 val = getushort(ttf);
+ int mant = val&0x3fff;
+ /* This oddity may be needed to deal with the first 2 bits being signed */
+ /* and the low-order bits unsigned */
+return( (real) ((val<<16)>>(16+14)) + (mant/16384.0) );
+}
+
+static Encoding *enc_from_platspec(int platform,int specific) {
+ char *enc;
+ Encoding *e;
+
+ enc = "Custom";
+ if ( platform==0 ) {
+ enc = "Unicode";
+ if ( specific==4 )
+ enc = "UnicodeFull";
+ } else if ( platform==1 ) {
+ if ( specific==0 )
+ enc = "Mac";
+ else if ( specific==1 )
+ enc = "Sjis";
+ else if ( specific==2 )
+ enc = "Big5hkscs"; /* Or should we just guess big5? Both are wrong sometimes */
+ else if ( specific==3 )
+ enc = "EUC-KR";
+ else if ( specific==25 )
+ enc = "EUC-CN";
+ } else if ( platform==2 ) { /* obselete */
+ if ( specific==0 )
+ enc = "ASCII";
+ else if ( specific==1 )
+ enc = "Unicode";
+ else if ( specific==2 )
+ enc = "ISO8859-1";
+ } else if ( platform==3 ) {
+ if ( specific==1 || specific==0 ) /* symbol (sp=0) is just unicode (PUA) */
+ enc = "Unicode";
+ else if ( specific==2 )
+ enc = "Sjis";
+ else if ( specific==3 )
+ enc = "EUC-CN";
+ else if ( specific==4 )
+ enc = "Big5hkscs";
+ else if ( specific==5 )
+ enc = "EUC-KR";
+ else if ( specific==6 )
+ enc = "Johab";
+ else if ( specific==10 )
+ enc = "UnicodeFull";
+ } else if ( platform==7 ) { /* Used internally in freetype, but */
+ if ( specific==0 ) /* there's no harm in looking for it */
+ enc = "AdobeStandard"; /* even if it never happens */
+ else if ( specific==1 )
+ /* adobe_expert */;
+ else if ( specific==2 )
+ /* adobe_custom */;
+ }
+ e = FindOrMakeEncoding(enc);
+ if ( e==NULL ) {
+ static int p = -1,s = -1;
+ if ( p!=platform || s!=specific ) {
+ LogError( _("The truetype encoding specified by platform=%d specific=%d (which we map to %s) is not supported by your version of iconv(3).\n"),
+ platform, specific, enc );
+ p = platform; s = specific;
+ }
+ }
+return( e );
+}
+
+static char *_readencstring(FILE *ttf,int offset,int len,
+ int platform,int specific,int language) {
+ long pos = ftell(ttf);
+ unichar_t *str, *pt;
+ char *ret;
+ int i, ch;
+ Encoding *enc;
+
+ fseek(ttf,offset,SEEK_SET);
+
+ if ( platform==1 ) {
+ /* Mac is screwy, there are several different varients of MacRoman */
+ /* depending on the language, they didn't get it right when they */
+ /* invented their script system */
+ char *cstr, *cpt;
+ cstr = cpt = galloc(len+1);
+ for ( i=0; i<len; ++i )
+ *cpt++ = getc(ttf);
+ *cpt = '\0';
+ ret = MacStrToUtf8(cstr,specific,language);
+ free(cstr);
+ } else {
+ enc = enc_from_platspec(platform,specific);
+ if ( enc==NULL )
+return( NULL );
+ if ( enc->is_unicodebmp ) {
+ str = pt = galloc((sizeof(unichar_t)/2)*len+sizeof(unichar_t));
+ for ( i=0; i<len/2; ++i ) {
+ ch = getc(ttf)<<8;
+ *pt++ = ch | getc(ttf);
+ }
+ *pt = 0;
+ } else if ( enc->unicode!=NULL ) {
+ str = pt = galloc(sizeof(unichar_t)*len+sizeof(unichar_t));
+ for ( i=0; i<len; ++i )
+ *pt++ = enc->unicode[getc(ttf)];
+ *pt = 0;
+ } else if ( enc->tounicode!=NULL ) {
+ size_t inlen = len+1, outlen = sizeof(unichar_t)*(len+1);
+ char *cstr = galloc(inlen);
+ ICONV_CONST char *in = cstr;
+ char *out;
+ str = galloc(outlen+2);
+ out = (char *) str;
+ iconv(enc->tounicode,&in,&inlen,&out,&outlen);
+ out[0] = '\0'; out[1] = '\0';
+#ifndef UNICHAR_16
+ out[2] = '\0'; out[3] = '\0';
+#endif
+ free(cstr);
+ } else {
+ str = uc_copy("");
+ }
+ ret = u2utf8_copy(str);
+ free(str);
+ }
+ fseek(ttf,pos,SEEK_SET);
+return( ret );
+}
+
+char *TTFGetFontName(FILE *ttf,int32 offset,int32 off2) {
+ int i,num;
+ int32 tag, nameoffset, length, stringoffset;
+ int plat, spec, lang, name, len, off, val;
+ int fullval, fullstr, fulllen, famval, famstr, famlen;
+ Encoding *enc;
+ int fullplat, fullspec, fulllang, famplat, famspec, famlang;
+
+ nameoffset = 0; fullstr=0; fulllen=0; famval=0; famstr=0; famlen=0;
+ fullplat=0; fullspec=0; fulllang=0; famplat=0; famspec=0; famlang=0;
+ fseek(ttf,offset,SEEK_SET);
+ /* version = */ getlong(ttf);
+ num = getushort(ttf);
+ /* srange = */ getushort(ttf);
+ /* esel = */ getushort(ttf);
+ /* rshift = */ getushort(ttf);
+ for ( i=0; i<num; ++i ) {
+ tag = getlong(ttf);
+ /* checksum = */ getlong(ttf);
+ nameoffset = off2+getlong(ttf);
+ length = getlong(ttf);
+ if ( tag==CHR('n','a','m','e'))
+ break;
+ }
+ if ( i==num )
+return( NULL );
+
+ fseek(ttf,nameoffset,SEEK_SET);
+ /* format = */ getushort(ttf);
+ num = getushort(ttf);
+ stringoffset = nameoffset+getushort(ttf);
+ fullval = famval = 0;
+ for ( i=0; i<num; ++i ) {
+ plat = getushort(ttf);
+ spec = getushort(ttf);
+ lang = getushort(ttf);
+ name = getushort(ttf);
+ len = getushort(ttf);
+ off = getushort(ttf);
+ enc = enc_from_platspec(plat,spec);
+ if ( enc==NULL )
+ continue;
+ val = 0;
+ /* I really want an english name */
+ if ( (plat==0 || plat==1) && !enc->is_custom && lang==0 )
+ val = 11;
+ else if ( plat==3 && !enc->is_custom && (lang&0xff)==0x09 )
+ val = 12;
+ /* failing that I'll take what I can get */
+ else if ( !enc->is_custom )
+ val = 1;
+ if ( name==4 && val>fullval ) {
+ fullval = val;
+ fullstr = off;
+ fulllen = len;
+ fullplat = plat;
+ fullspec = spec;
+ fulllang = lang;
+ if ( val==12 )
+ break;
+ } else if ( name==1 && val>famval ) {
+ famval = val;
+ famstr = off;
+ famlen = len;
+ famplat = plat;
+ famspec = spec;
+ famlang = lang;
+ }
+ }
+ if ( fullval==0 ) {
+ if ( famval==0 )
+return( NULL );
+ fullstr = famstr;
+ fulllen = famlen;
+ fullplat = famplat;
+ fullspec = famspec;
+ fulllang = famlang;
+ }
+return( _readencstring(ttf,stringoffset+fullstr,fulllen,fullplat,fullspec,fulllang));
+}
+
+static int PickTTFFont(FILE *ttf,char *filename,char **chosenname) {
+ int32 *offsets, cnt, i, choice, j;
+ char **names;
+ char *pt, *lparen;
+
+ /* TTCF version = */ getlong(ttf);
+ cnt = getlong(ttf);
+ if ( cnt==1 ) {
+ /* This is easy, don't bother to ask the user, there's no choice */
+ int32 offset = getlong(ttf);
+ fseek(ttf,offset,SEEK_SET);
+return( true );
+ }
+ offsets = galloc(cnt*sizeof(int32));
+ for ( i=0; i<cnt; ++i )
+ offsets[i] = getlong(ttf);
+ names = galloc(cnt*sizeof(char *));
+ for ( i=j=0; i<cnt; ++i ) {
+ names[j] = TTFGetFontName(ttf,offsets[i],0);
+ if ( names[j]!=NULL ) ++j;
+ }
+ pt = strrchr(filename,'/');
+ if ( pt==NULL ) pt = filename;
+ if ( (lparen = strchr(pt,'('))!=NULL && strchr(lparen,')')!=NULL ) {
+ char *find = copy(lparen+1);
+ pt = strchr(find,')');
+ if ( pt!=NULL ) *pt='\0';
+ for ( choice=cnt-1; choice>=0; --choice )
+ if ( strcmp(names[choice],find)==0 )
+ break;
+ if ( choice==-1 ) {
+ char *fn = copy(filename);
+ fn[lparen-filename] = '\0';
+ gwwv_post_error(_("Not in Collection"),
+/* GT: The user is trying to open a font file which contains multiple fonts and */
+/* GT: has asked for a font which is not in that file. */
+/* GT: The string will look like: <fontname> is not in <filename> */
+ _("%1$s is not in %2$.100s"),find,fn);
+ free(fn);
+ }
+ free(find);
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ } else if ( no_windowing_ui )
+ choice = 0;
+ else
+ choice = gwwv_choose(_("Pick a font, any font..."),(const char **) names,j,0,_("There are multiple fonts in this file, pick one"));
+#else
+ } else
+ choice = 0;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ if ( choice!=-1 ) {
+ fseek(ttf,offsets[choice],SEEK_SET);
+ *chosenname = copy(names[choice]);
+ }
+ for ( i=0; i<j; ++i )
+ free(names[i]);
+ free(names);
+ free(offsets);
+return( choice!=-1);
+}
+
+static int PickCFFFont(char **fontnames) {
+ unichar_t **names;
+ int cnt, i, choice;
+
+ for ( cnt=0; fontnames[cnt]!=NULL; ++cnt);
+ names = gcalloc(cnt+1,sizeof(unichar_t *));
+ for ( i=0; i<cnt; ++i )
+ names[i] = uc_copy(fontnames[i]);
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ if ( no_windowing_ui )
+ choice = 0;
+ else
+ choice = gwwv_choose(_("Pick a font, any font..."),
+ (const char **) names,cnt,0,_("There are multiple fonts in this file, pick one"));
+#elif defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ choice = 0;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ for ( i=0; i<cnt; ++i )
+ free(names[i]);
+ free(names);
+return( choice );
+}
+
+static void ParseSaveTablesPref(struct ttfinfo *info) {
+ extern char *SaveTablesPref;
+ char *pt, *spt;
+ int cnt;
+
+ info->savecnt = 0;
+ info->savetab = NULL;
+ if ( SaveTablesPref==NULL || *SaveTablesPref=='\0' )
+return;
+ for ( pt=SaveTablesPref, cnt=0; *pt; ++pt )
+ if ( *pt==',' )
+ ++cnt;
+ info->savecnt = cnt+1;
+ info->savetab = gcalloc(cnt+1,sizeof(struct savetab));
+ for ( pt=spt=SaveTablesPref, cnt=0; ; ++pt ) {
+ if ( *pt==',' || *pt=='\0' ) {
+ uint32 tag;
+ tag = ( ( spt <pt )? spt[0] : ' ' )<<24;
+ tag |= ( ( spt+1<pt )? spt[1] : ' ' )<<16;
+ tag |= ( ( spt+2<pt )? spt[2] : ' ' )<<8 ;
+ tag |= ( ( spt+3<pt )? spt[3] : ' ' ) ;
+ info->savetab[cnt++].tag = tag;
+ if ( *pt )
+ spt = pt+1;
+ else
+ break;
+ }
+ }
+}
+
+static int readttfheader(FILE *ttf, struct ttfinfo *info,char *filename,
+ char **choosenname) {
+ int i, j;
+ int tag, checksum, offset, length, version;
+
+ version=getlong(ttf);
+ if ( version==CHR('t','t','c','f')) {
+ /* TrueType font collection */
+ info->is_ttc = true;
+ if ( !PickTTFFont(ttf,filename,choosenname))
+return( 0 );
+ /* If they picked a font, then we should be left pointing at the */
+ /* start of the Table Directory for that font */
+ info->one_of_many = true;
+ version = getlong(ttf);
+ }
+
+ /* Apple says that 'typ1' is a valid code for a type1 font wrapped up in */
+ /* a truetype table structure, but gives no docs on what tables get used */
+ /* or how */
+ if ( version==CHR('t','y','p','1')) {
+ LogError( _("Nifty, you've got one of the old Apple/Adobe type1 sfnts here\n") );
+ } else if ( version!=0x00010000 && version!=CHR('t','r','u','e') &&
+ version!=0x00020000 && /* Windows 3.1 Chinese version used this version for some arphic fonts */
+ /* See discussion on freetype list, july 2004 */
+ version!=CHR('O','T','T','O'))
+return( 0 ); /* Not version 1 of true type, nor Open Type */
+ info->numtables = getushort(ttf);
+ /* searchRange = */ getushort(ttf);
+ /* entrySelector = */ getushort(ttf);
+ /* rangeshift = */ getushort(ttf);
+
+ ParseSaveTablesPref(info);
+
+ for ( i=0; i<info->numtables; ++i ) {
+ tag = getlong(ttf);
+ checksum = getlong(ttf);
+ offset = getlong(ttf);
+ length = getlong(ttf);
+#ifdef DEBUG
+ printf( "%c%c%c%c\n", tag>>24, (tag>>16)&0xff, (tag>>8)&0xff, tag&0xff );
+#endif
+ switch ( tag ) {
+ case CHR('C','F','F',' '):
+ info->cff_start = offset;
+ info->cff_length = length;
+ break;
+ case CHR('c','m','a','p'):
+ info->encoding_start = offset;
+ break;
+ case CHR('g','a','s','p'):
+ info->gasp_start = offset;
+ break;
+ case CHR('g','l','y','f'):
+ info->glyph_start = offset;
+ info->glyph_length = length;
+ break;
+ case CHR('G','D','E','F'):
+ info->gdef_start = offset;
+ info->gdef_length = length;
+ break;
+ case CHR('G','P','O','S'):
+ info->gpos_start = offset;
+ info->gpos_length = length;
+ break;
+ case CHR('G','S','U','B'):
+ info->gsub_start = offset;
+ info->gsub_length = length;
+ break;
+ case CHR('b','d','a','t'): /* Apple/MS use a different tag, but the same format. Great. */
+ case CHR('E','B','D','T'):
+ info->bitmapdata_start = offset;
+ info->bitmapdata_length = length;
+ break;
+ case CHR('b','l','o','c'): /* Apple/MS use a different tag. Great. */
+ case CHR('E','B','L','C'):
+ info->bitmaploc_start = offset;
+ info->bitmaploc_length = length;
+ break;
+ case CHR('b','h','e','d'): /* Apple uses bhed for fonts with only bitmaps */
+ case CHR('h','e','a','d'):
+ info->head_start = offset;
+ break;
+ case CHR('h','h','e','a'):
+ info->hhea_start = offset;
+ break;
+ case CHR('h','m','t','x'):
+ info->hmetrics_start = offset;
+ break;
+ case CHR('k','e','r','n'):
+ info->kern_start = offset;
+ break;
+ case CHR('l','o','c','a'):
+ info->glyphlocations_start = offset;
+ info->loca_length = length;
+ info->glyph_cnt = length/2-1; /* the minus one is because there is one extra entry to give the length of the last glyph */
+ if ( info->glyph_cnt<0 ) info->glyph_cnt = 0;
+ break;
+ case CHR('m','a','x','p'):
+ info->maxp_start = offset;
+ info->maxp_len = length;
+ break;
+ case CHR('n','a','m','e'):
+ info->copyright_start = offset;
+ break;
+ case CHR('p','o','s','t'):
+ info->postscript_start = offset;
+ break;
+ case CHR('O','S','/','2'):
+ info->os2_start = offset;
+ break;
+ case CHR('T','Y','P','1'):
+ info->typ1_start = offset;
+ info->typ1_length = length;
+ break;
+ case CHR('v','h','e','a'):
+ info->vhea_start = offset;
+ break;
+ case CHR('v','m','t','x'):
+ info->vmetrics_start = offset;
+ break;
+ case CHR('V','O','R','G'):
+ info->vorg_start = offset;
+ break;
+ /* Apple stuff */
+ case CHR('a','c','n','t'):
+ info->acnt_start = offset;
+ break;
+ case CHR('f','e','a','t'):
+ info->feat_start = offset;
+ break;
+ case CHR('l','c','a','r'):
+ info->lcar_start = offset;
+ break;
+ case CHR('m','o','r','t'):
+ info->mort_start = offset;
+ break;
+ case CHR('m','o','r','x'):
+ info->morx_start = offset;
+ break;
+ case CHR('o','p','b','d'):
+ info->opbd_start = offset;
+ break;
+ case CHR('p','r','o','p'):
+ info->prop_start = offset;
+ break;
+ /* to make sense of instrs */
+ case CHR('c','v','t',' '):
+ info->cvt_start = offset;
+ info->cvt_len = length;
+ break;
+ case CHR('p','r','e','p'):
+ info->prep_start = offset;
+ info->prep_len = length;
+ break;
+ case CHR('f','p','g','m'):
+ info->fpgm_start = offset;
+ info->fpgm_len = length;
+ break;
+
+ /* non-standard tables I've added */
+ case CHR('P','f','E','d'):
+ info->pfed_start = offset;
+ break;
+ case CHR('F','F','T','M'):
+ info->fftm_start = offset;
+ break;
+ case CHR('T','e','X',' '):
+ info->tex_start = offset;
+ break;
+ case CHR('B','D','F',' '):
+ info->bdf_start = offset;
+ break;
+
+ /* Apple's mm fonts */
+ case CHR('g','v','a','r'):
+ info->gvar_start = offset;
+ info->gvar_len = length;
+ break;
+ case CHR('f','v','a','r'):
+ info->fvar_start = offset;
+ info->fvar_len = length;
+ break;
+ case CHR('a','v','a','r'):
+ info->avar_start = offset;
+ info->avar_len = length;
+ break;
+ case CHR('c','v','a','r'):
+ info->cvar_start = offset;
+ info->cvar_len = length;
+ break;
+
+ default:
+ for ( j=0; j<info->savecnt; ++j ) if ( info->savetab[j].tag == tag ) {
+ info->savetab[j].offset = offset;
+ info->savetab[j].len = length;
+ break;
+ }
+ }
+ }
+return( true );
+}
+
+static void readdate(FILE *ttf,struct ttfinfo *info,int ismod) {
+ int date[4], date1970[4], year[2];
+ int i;
+ /* Dates in sfnt files are seconds since 1904. I adjust to unix time */
+ /* seconds since 1970 by figuring out how many seconds were in between */
+
+ date[3] = getushort(ttf);
+ date[2] = getushort(ttf);
+ date[1] = getushort(ttf);
+ date[0] = getushort(ttf);
+ memset(date1970,0,sizeof(date1970));
+ year[0] = (60*60*24*365L)&0xffff;
+ year[1] = (60*60*24*365L)>>16;
+ for ( i=1904; i<1970; ++i ) {
+ date1970[0] += year[0];
+ date1970[1] += year[1];
+ if ( (i&3)==0 && (i%100!=0 || i%400==0))
+ date1970[0] += 24*60*60L; /* Leap year */
+ date1970[1] += (date1970[0]>>16);
+ date1970[0] &= 0xffff;
+ date1970[2] += date1970[1]>>16;
+ date1970[1] &= 0xffff;
+ date1970[3] += date1970[2]>>16;
+ date1970[2] &= 0xffff;
+ }
+
+ for ( i=0; i<3; ++i ) {
+ date[i] -= date1970[i];
+ date[i+1] += date[i]>>16;
+ date[i] &= 0xffff;
+ }
+ date[3] -= date1970[3];
+
+ *(ismod ? &info->modificationtime : &info->creationtime) =
+#ifdef _HAS_LONGLONG
+ (((long long) date[3])<<48) |
+ (((long long) date[2])<<32) |
+#endif
+ ( date[1] <<16) |
+ date[0];
+}
+
+static void readttfhead(FILE *ttf,struct ttfinfo *info) {
+ /* Here I want units per em, and size of loca entries */
+ /* oh... also creation/modification times */
+ int i, flags;
+
+ fseek(ttf,info->head_start+4*4,SEEK_SET); /* skip over the version number and a bunch of junk */
+ flags = getushort(ttf);
+ info->optimized_for_cleartype = (flags&(1<<13))?1:0;
+ info->emsize = getushort(ttf);
+ for ( i=0; i<12; ++i )
+ getushort(ttf);
+ info->macstyle = getushort(ttf);
+ for ( i=0; i<2; ++i )
+ getushort(ttf);
+ info->index_to_loc_is_long = getushort(ttf);
+ if ( info->index_to_loc_is_long )
+ info->glyph_cnt = info->loca_length/4-1;
+ if ( info->glyph_cnt<0 ) info->glyph_cnt = 0;
+
+ if ( info->fftm_start!=0 ) {
+ fseek(ttf,info->fftm_start+3*4,SEEK_SET);
+ } else {
+ fseek(ttf,info->head_start+4*4+2+2,SEEK_SET);
+ }
+ readdate(ttf,info,0);
+ readdate(ttf,info,1);
+}
+
+static void readttfhhea(FILE *ttf,struct ttfinfo *info) {
+ /* Here I want ascent, descent and the number of horizontal metrics */
+ int i;
+
+ fseek(ttf,info->hhea_start+4,SEEK_SET); /* skip over the version number */
+ info->pfminfo.hhead_ascent = getushort(ttf);
+ info->pfminfo.hhead_descent = (short) getushort(ttf);
+ info->pfminfo.hheadascent_add = info->pfminfo.hheaddescent_add = false;
+ info->pfminfo.linegap = getushort(ttf);
+ info->pfminfo.hheadset = true;
+ /*info->ascent = info->pfminfo.hhead_ascent;*/
+
+ info->ascent = .8*info->emsize;
+ info->descent = info->emsize-info->ascent;
+
+ for ( i=0; i<12; ++i )
+ getushort(ttf);
+ info->width_cnt = getushort(ttf);
+}
+
+static void readttfmaxp(FILE *ttf,struct ttfinfo *info) {
+ /* All I want here is the number of glyphs */
+ int cnt;
+ fseek(ttf,info->maxp_start+4,SEEK_SET); /* skip over the version number */
+ cnt = getushort(ttf);
+ if ( info->glyph_cnt==0 && info->glyph_length==0 && info->loca_length<=4 &&
+ info->cff_length==0 && info->typ1_start==0 ) {
+ /* X11 OpenType bitmap format */;
+ info->onlystrikes = true;
+ } else if ( cnt!=info->glyph_cnt && info->loca_length!=0 ) {
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ ff_post_notice(_("Bad Glyph Count"), _("Font file has bad glyph count field. maxp says: %d sizeof(loca)=>%d"), cnt, info->glyph_cnt);
+#endif
+ if ( cnt>info->glyph_cnt )
+ cnt = info->glyph_cnt; /* Use the smaller of the two values */
+ }
+ /* Open Type fonts have no loca table, so we can't calculate the glyph */
+ /* count from it */
+ info->glyph_cnt = cnt;
+ if ( cnt<0 ) info->glyph_cnt = 0;
+}
+
+static char *stripspaces(char *str) {
+ char *str2 = str, *base = str;
+
+ if ( str==NULL )
+return( NULL );
+
+ while ( *str ) {
+ if ( *str==' ' )
+ ++str;
+ else
+ *str2++ = *str++;
+ }
+ *str2 = '\0';
+return( base );
+}
+
+static struct macname *AddMacName(FILE *ttf,
+ int strlen, int stroff,int spec,int language, struct macname *last) {
+ struct macname *new = chunkalloc(sizeof(struct macname));
+ long pos = ftell(ttf);
+ char *pt;
+ int i;
+
+ new->next = last;
+ new->enc = spec;
+ new->lang = language;
+ new->name = pt = galloc(strlen+1);
+
+ fseek(ttf,stroff,SEEK_SET);
+
+ for ( i=0; i<strlen; ++i )
+ *pt++ = getc(ttf);
+ *pt = '\0';
+
+ fseek(ttf,pos,SEEK_SET);
+return( new );
+}
+
+static void MacFeatureAdd(FILE *ttf, struct ttfinfo *info, int id,
+ int strlen, int stroff,int spec,int language) {
+ MacFeat *f;
+ struct macsetting *s;
+
+ for ( f=info->features; f!=NULL; f=f->next ) {
+ if ( f->strid==id ) {
+ f->featname = AddMacName(ttf,strlen,stroff,spec,language,f->featname);
+return;
+ } else {
+ for ( s=f->settings; s!=NULL; s=s->next ) {
+ if ( s->strid==id ) {
+ s->setname = AddMacName(ttf,strlen,stroff,spec,language,s->setname);
+return;
+ }
+ }
+ }
+ }
+ /* Well, there are some things in the name table other than feature/setting*/
+ /* names. Let's keep track of everything just in case.... */
+ if ( info->fvar_start!=0 ) {
+ struct macidname *mi, *p;
+ for ( p=NULL, mi=info->macstrids; mi!=NULL && mi->id!=id; p = mi, mi=mi->next );
+ if ( mi==NULL ) {
+ mi = chunkalloc(sizeof(struct macidname));
+ mi->id = id;
+ mi->last = mi->head = AddMacName(ttf,strlen,stroff,spec,language,NULL);
+ if ( p==NULL )
+ info->macstrids = mi;
+ else
+ p->next = mi;
+ } else {
+ mi->last->next = AddMacName(ttf,strlen,stroff,spec,language,NULL);
+ mi->last = mi->last->next;
+ }
+ }
+}
+
+static void ValidatePostScriptFontName(char *str) {
+ char *end, *pt, *npt;
+ int complained = false;
+
+ /* someone gave me a font where the fontname started with the utf8 byte */
+ /* order mark. PLRM says only ASCII encoding is supported. CFF says */
+ /* only printable ASCII should be used */
+ if ( ((uint8 *) str)[0] == 0xef && ((uint8 *) str)[1]==0xbb && ((uint8 *) str)[2] == 0xbf ) {
+ LogError(_("The fontname begins with the utf8 byte order sequence. This is illegal. %s"), str+3 );
+ for ( pt=str+3; *pt; ++pt )
+ pt[-3] = *pt; /* ANSI says we can't strcpy overlapping strings */
+ }
+ strtod(str,&end);
+ if ( (*end=='\0' || (Isdigit(str[0]) && strchr(str,'#')!=NULL)) &&
+ *str!='\0' ) {
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_post_error(_("Bad Font Name"),_("A Postscript name may not be a number"));
+#endif
+ *str = 'a';
+ complained = true;
+ }
+ for ( pt=str; *pt; ++pt ) {
+ if ( *pt<=' ' || *pt>=0x7f ||
+ *pt=='(' || *pt=='[' || *pt=='{' || *pt=='<' ||
+ *pt==')' || *pt==']' || *pt=='}' || *pt=='>' ||
+ *pt=='%' || *pt=='/' ) {
+ if ( !complained ) {
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_post_error(_("Bad Font Name"),_("The Postscript font name \"%.63s\" is invalid.\nIt should be printable ASCII,\nmust not contain (){}[]<>%%/ or space\nand must be shorter than 63 characters"),str);
+#endif
+ }
+ complained = true;
+ for ( npt=pt; npt[1]; ++npt )
+ *npt = npt[1];
+ *npt = '\0';
+ --pt;
+ }
+ }
+ if ( strlen(str)>63 ) {
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_post_error(_("Bad Font Name"),_("The Postscript font name \"%.63s\" is invalid.\nIt should be printable ASCII,\nmust not contain (){}[]<>%%/ or space\nand must be shorter than 63 characters"),str);
+#endif
+ str[63] = '\0';
+ }
+}
+
+char *EnforcePostScriptName(char *old) {
+ char *end, *pt, *npt, *str = copy(old);
+
+ if ( old==NULL )
+return( old );
+
+ strtod(str,&end);
+ if ( (*end=='\0' || (Isdigit(str[0]) && strchr(str,'#')!=NULL)) &&
+ *str!='\0' ) {
+ free(str);
+ str=galloc(strlen(old)+2);
+ *str = 'a';
+ strcpy(str+1,old);
+ }
+ for ( pt=str; *pt; ++pt ) {
+ if ( *pt<=' ' || *pt>=0x7f ||
+ *pt=='(' || *pt=='[' || *pt=='{' || *pt=='<' ||
+ *pt==')' || *pt==']' || *pt=='}' || *pt=='>' ||
+ *pt=='%' || *pt=='/' ) {
+ for ( npt=pt; npt[1]; ++npt )
+ *npt = npt[1];
+ *npt = '\0';
+ }
+ }
+ if ( strlen(str)>63 )
+ str[63] = '\0';
+return( str );
+}
+
+#ifndef LUA_FF_LIB
+static int IsSubSetOf(const char *substr,const char *fullstr ) {
+ /* The mac string is often a subset of the unicode string. Certain */
+ /* characters can't be expressed in the mac encoding and are omitted */
+ /* or turned to question marks or some such */
+ const char *pt1, *pt2;
+ uint32 ch1, ch2;
+
+ for ( pt1=substr, pt2=fullstr, ch1=utf8_ildb(&pt1); ch1!=0 ; ) {
+ if ( *pt2=='\0' )
+ break;
+ ch2 = utf8_ildb(&pt2);
+ if ( ch1==ch2 )
+ ch1 = utf8_ildb(&pt1);
+ }
+ if ( ch1=='\0' )
+return( true );
+
+ for ( pt1=substr, pt2=fullstr, ch1=utf8_ildb(&pt1); ch1!=0 ; ) {
+ if ( *pt2=='\0' )
+ break;
+ ch2 = utf8_ildb(&pt2);
+ if ( ch1==ch2 || ch1=='?' )
+ ch1 = utf8_ildb(&pt1);
+ }
+return( ch1=='\0' );
+}
+#endif
+
+static void TTFAddLangStr(FILE *ttf, struct ttfinfo *info, int id,
+ int strlen, int stroff,int plat,int spec,int language) {
+ struct ttflangname *cur, *prev;
+ char *str;
+
+ if ( plat==1 && id>=256 && (info->features!=NULL || info->fvar_start!=0)) {
+ MacFeatureAdd(ttf,info,id,strlen,stroff,spec,language);
+return;
+ } else if ( id<0 || id>=ttf_namemax )
+return;
+
+ str = _readencstring(ttf,stroff,strlen,plat,spec,language);
+ if ( str==NULL ) /* we didn't understand the encoding */
+return;
+ if ( id==ttf_postscriptname )
+ ValidatePostScriptFontName(str);
+ if ( *str=='\0' ) {
+ free(str);
+return;
+ }
+
+ if ( plat==1 || plat==0 )
+ language = WinLangFromMac(language);
+ if ( (language&0xff00)==0 ) language |= 0x400;
+
+ for ( prev=NULL, cur=info->names; cur!=NULL && cur->lang!=language; prev = cur, cur=cur->next );
+ if ( cur==NULL ) {
+ cur = chunkalloc(sizeof(struct ttflangname));
+ cur->lang = language;
+ if ( prev==NULL )
+ info->names = cur;
+ else
+ prev->next = cur;
+ }
+ if ( cur->names[id]==NULL ) {
+ cur->names[id] = str;
+ if ( plat==1 || plat==0 )
+ cur->frommac[id/32] |= (1<<(id&0x1f));
+/* There's some wacky bug in gcc. If the optimizer is on then strcmp gets turned */
+/* into some inline call. Which would be fine, except the following line goes */
+/* bluey. "Called object is not a function", etc. Compiles fine if we turn off */
+/* the inlining magic */
+#ifdef strcmp
+# undef strcmp
+#endif
+ } else if ( strcmp(str,cur->names[id])==0 ) {
+ free(str);
+ if ( plat==3 )
+ cur->frommac[id/32] &= ~(1<<(id&0x1f));
+ } else if ( plat==1 ) {
+ /* Mac string doesn't match mac unicode string */
+#ifndef LUA_FF_LIB
+ if ( !IsSubSetOf(str,cur->names[id]) )
+ LogError( _("Warning: Mac and Unicode entries in the 'name' table differ for the\n %s string in the language %s\n Mac String: %s\nMac Unicode String: %s\n"),
+ TTFNameIds(id),MSLangString(language),
+ str,cur->names[id]);
+ else
+ LogError( _("Warning: Mac string is a subset of the Unicode string in the 'name' table\n for the %s string in the %s language.\n"),
+ TTFNameIds(id),MSLangString(language));
+#endif
+ free(str);
+ } else if ( plat==3 && (cur->frommac[id/32] & (1<<(id&0x1f))) ) {
+#ifndef LUA_FF_LIB
+ if ( !IsSubSetOf(cur->names[id],str) )
+ LogError( _("Warning: Mac and Windows entries in the 'name' table differ for the\n %s string in the language %s\n Mac String: %s\nWindows String: %s\n"),
+ TTFNameIds(id),MSLangString(language),
+ cur->names[id],str);
+ else
+ LogError( _("Warning: Mac string is a subset of the Windows string in the 'name' table\n for the %s string in the %s language.\n"),
+ TTFNameIds(id),MSLangString(language));
+#endif
+ free(cur->names[id]);
+ cur->names[id] = str;
+ cur->frommac[id/32] &= ~(1<<(id&0x1f));
+ } else {
+ int ret;
+ extern int running_script;
+ if ( info->dupnamestate!=0 )
+ ret = info->dupnamestate;
+ else if ( running_script )
+ ret = 3;
+ else {
+ char *buts[5];
+ buts[0] = _("Use _First");
+ buts[1] = _("First to _All");
+ buts[2] = _("Second _to All");
+ buts[3] = _("Use _Second");
+ buts[4] = NULL;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ ret = gwwv_ask(_("Multiple names for language"),(const char **)buts,0,3,
+ _("The 'name' table contains (at least) two strings for the %s in language %s, the first '%.12s...' the second '%.12s...'.\nWhich do you prefer?"),
+ TTFNameIds(id),MSLangString(language),
+ cur->names[id],str);
+#else
+ ret = 3;
+#endif
+ if ( ret==1 || ret==2 )
+ info->dupnamestate = ret;
+ }
+ if ( ret==0 || ret==1 )
+ free(str);
+ else {
+ free(cur->names[id]);
+ cur->names[id] = str;
+ }
+ }
+}
+
+static int is_ascii(char *str) { /* isascii is in ctype */
+ if ( str==NULL )
+return( false );
+ while ( *str && *str<127 && *str>=' ' )
+ ++str;
+return( *str=='\0' );
+}
+
+static char *FindLangEntry(struct ttfinfo *info, int id ) {
+ /* Look for an entry with string id */
+ /* we prefer english, if we can't find english look for something in ascii */
+ struct ttflangname *cur;
+ char *ret;
+
+ for ( cur=info->names; cur!=NULL && cur->lang!=0x409; cur=cur->next );
+ if ( cur!=NULL && cur->names[id]==NULL ) cur = NULL;
+ if ( cur==NULL )
+ for ( cur=info->names; cur!=NULL && (cur->lang&0xf)!=0x09; cur=cur->next );
+ if ( cur!=NULL && cur->names[id]==NULL ) cur = NULL;
+ if ( cur==NULL )
+ for ( cur=info->names; cur!=NULL && !is_ascii(cur->names[id]); cur=cur->next );
+ if ( cur==NULL )
+ for ( cur=info->names; cur!=NULL && cur->names[id]==NULL; cur=cur->next );
+ if ( cur==NULL )
+return( NULL );
+ ret = copy(cur->names[id]);
+return( ret );
+}
+
+struct otfname *FindAllLangEntries(FILE *ttf, struct ttfinfo *info, int id ) {
+ /* Look for all entries with string id under windows platform */
+ int32 here = ftell(ttf);
+ int i, cnt, tableoff;
+ int platform, specific, language, name, str_len, stroff;
+ struct otfname *head=NULL, *cur;
+
+ if ( info->copyright_start!=0 && id!=0 ) {
+ fseek(ttf,info->copyright_start,SEEK_SET);
+ /* format selector = */ getushort(ttf);
+ cnt = getushort(ttf);
+ tableoff = info->copyright_start+getushort(ttf);
+ for ( i=0; i<cnt; ++i ) {
+ platform = getushort(ttf);
+ specific = getushort(ttf);
+ language = getushort(ttf);
+ name = getushort(ttf);
+ str_len = getushort(ttf);
+ stroff = getushort(ttf);
+
+ if ( platform==3 && name==id ) {
+ char *temp = _readencstring(ttf,tableoff+stroff,str_len,platform,specific,language);
+ if ( temp!=NULL ) {
+ cur = chunkalloc(sizeof(struct otfname));
+ cur->next = head;
+ head = cur;
+ cur->lang = language;
+ cur->name = temp;
+ }
+ }
+ }
+ fseek(ttf,here,SEEK_SET);
+ }
+return( head );
+}
+
+static struct macname *reversemacnames(struct macname *mn) {
+ struct macname *next, *prev=NULL;
+
+ if ( mn==NULL )
+return( NULL );
+
+ next = mn->next;
+ while ( next!=NULL ) {
+ mn->next = prev;
+ prev = mn;
+ mn = next;
+ next = mn->next;
+ }
+ mn->next = prev;
+return( mn );
+}
+
+static void readttfcopyrights(FILE *ttf,struct ttfinfo *info) {
+ int i, cnt, tableoff;
+ int platform, specific, language, name, str_len, stroff;
+
+ if ( info->feat_start!=0 )
+ readmacfeaturemap(ttf,info);
+ if ( info->copyright_start!=0 ) {
+ fseek(ttf,info->copyright_start,SEEK_SET);
+ /* format selector = */ getushort(ttf);
+ cnt = getushort(ttf);
+ tableoff = info->copyright_start+getushort(ttf);
+ for ( i=0; i<cnt; ++i ) {
+ platform = getushort(ttf);
+ specific = getushort(ttf);
+ language = getushort(ttf);
+ name = getushort(ttf);
+ str_len = getushort(ttf);
+ stroff = getushort(ttf);
+
+ TTFAddLangStr(ttf,info,name,str_len,tableoff+stroff,
+ platform,specific,language);
+ }
+ }
+
+ if ( info->copyright==NULL )
+ info->copyright = FindLangEntry(info,ttf_copyright);
+ if ( info->familyname==NULL )
+ info->familyname = FindLangEntry(info,ttf_family);
+ if ( info->fullname==NULL )
+ info->fullname = FindLangEntry(info,ttf_fullname);
+ if ( info->version==NULL )
+ info->version = FindLangEntry(info,ttf_version);
+ if ( info->fontname==NULL )
+ info->fontname = FindLangEntry(info,ttf_postscriptname);
+
+ if ( info->fontname != NULL && *info->fontname=='\0' ) {
+ free(info->fontname);
+ info->fontname = NULL;
+ }
+ if ( info->familyname != NULL && *info->familyname=='\0' ) {
+ free(info->familyname);
+ info->familyname = NULL;
+ }
+ if ( info->fullname != NULL && *info->fullname=='\0' ) {
+ free(info->fullname);
+ info->fullname = NULL;
+ }
+
+ /* OpenType spec says the version string should begin with "Version " and */
+ /* end with a space and have a number in between */
+ if ( info->version==NULL ) info->version = copy("1.0");
+ else if ( strnmatch(info->version,"Version ",8)==0 ) {
+ char *temp = copy(info->version+8);
+ if ( temp[strlen(temp)-1]==' ' )
+ temp[strlen(temp)-1] = '\0';
+ free(info->version);
+ info->version = temp;
+ }
+ if ( info->fontname==NULL ) {
+ if ( info->fullname!=NULL )
+ info->fontname = stripspaces(copy(info->fullname));
+ if ( info->fontname==NULL && info->familyname!=NULL )
+ info->fontname = stripspaces(copy(info->familyname));
+ if ( info->fontname!=NULL )
+ ValidatePostScriptFontName(info->fontname);
+ }
+
+ if ( info->features ) {
+ MacFeat *mf;
+ struct macsetting *ms;
+ for ( mf=info->features; mf!=NULL; mf = mf->next ) {
+ mf->featname = reversemacnames(mf->featname);
+ for ( ms=mf->settings; ms!=NULL; ms=ms->next )
+ ms->setname = reversemacnames(ms->setname);
+ }
+ }
+}
+
+static void readttfpreglyph(FILE *ttf,struct ttfinfo *info) {
+ if ( info->head_start!=0 )
+ readttfhead(ttf,info);
+ if ( info->hhea_start!=0 )
+ readttfhhea(ttf,info);
+ if ( info->maxp_start!=0 )
+ readttfmaxp(ttf,info);
+ readttfcopyrights(ttf,info); /* This one has internal checks */
+}
+
+#define _On_Curve 1
+#define _X_Short 2
+#define _Y_Short 4
+#define _Repeat 8
+#define _X_Same 0x10
+#define _Y_Same 0x20
+
+static void FigureControls(SplinePoint *from, SplinePoint *to, BasePoint *cp,
+ int is_order2) {
+ /* What are the control points for 2 cp bezier which will provide the same*/
+ /* curve as that for the 1 cp bezier specified above */
+ real b, c, d;
+
+ if ( is_order2 ) {
+ from->nextcp = to->prevcp = *cp;
+ if ( cp->x==to->me.x && cp->y==to->me.y ) {
+ /* I would lose track of the proper location of this cp if I left */
+ /* it here (would end up with from->nonextcp, which would mean I'd*/
+ /* use from->me rather than to->me in tottf.c:SSAddPoints. So we */
+ /* distort it a little */
+ BasePoint off;
+ double len;
+ off.x = from->me.x-to->me.x; off.y = from->me.y-to->me.y;
+ len = sqrt(off.x*off.x+off.y*off.y);
+ if ( len>3 ) {
+ /* move the cp slightly toward from, but on the line between the two */
+ from->nextcp.x = (to->prevcp.x += rint(off.x/len));
+ from->nextcp.y = (to->prevcp.y += rint(off.y/len));
+ }
+ }
+ } else {
+ d = from->me.x;
+ c = 2*cp->x - 2*from->me.x;
+ b = to->me.x+from->me.x-2*cp->x;
+ from->nextcp.x = d+c/3;
+ to->prevcp.x = from->nextcp.x + (c+b)/3;
+
+ d = from->me.y;
+ c = 2*cp->y - 2*from->me.y;
+ b = to->me.y+from->me.y-2*cp->y;
+ from->nextcp.y = d+c/3;
+ to->prevcp.y = from->nextcp.y + (c+b)/3;
+ }
+
+ if ( from->me.x!=from->nextcp.x || from->me.y!=from->nextcp.y )
+ from->nonextcp = false;
+ if ( to->me.x!=to->prevcp.x || to->me.y!=to->prevcp.y )
+ to->noprevcp = false;
+ if ( is_order2 && (to->noprevcp || from->nonextcp)) {
+ to->noprevcp = from->nonextcp = true;
+ from->nextcp = from->me;
+ to->prevcp = to->me;
+ }
+}
+
+static SplineSet *ttfbuildcontours(int path_cnt,uint16 *endpt, char *flags,
+ BasePoint *pts, int is_order2) {
+ SplineSet *head=NULL, *last=NULL, *cur;
+ int i, path, start, last_off;
+ SplinePoint *sp;
+
+ for ( path=i=0; path<path_cnt; ++path ) {
+ if ( endpt[path]<i ) /* Sigh. Yes there are fonts with bad endpt info */
+ continue;
+ cur = chunkalloc(sizeof(SplineSet));
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ last_off = false;
+ start = i;
+ sp = NULL;
+ while ( i<=endpt[path] ) {
+ if ( flags[i]&_On_Curve ) {
+ sp = chunkalloc(sizeof(SplinePoint));
+ sp->me = sp->nextcp = sp->prevcp = pts[i];
+ sp->nonextcp = sp->noprevcp = true;
+ sp->ttfindex = i;
+ sp->nextcpindex = 0xffff;
+ if ( last_off && cur->last!=NULL )
+ FigureControls(cur->last,sp,&pts[i-1],is_order2);
+ last_off = false;
+ } else if ( last_off ) {
+ /* two off curve points get a third on curve point created */
+ /* half-way between them. Now isn't that special */
+ sp = chunkalloc(sizeof(SplinePoint));
+ sp->me.x = (pts[i].x+pts[i-1].x)/2;
+ sp->me.y = (pts[i].y+pts[i-1].y)/2;
+ sp->nextcp = sp->prevcp = sp->me;
+ sp->nonextcp = true;
+ sp->ttfindex = 0xffff;
+ sp->nextcpindex = i;
+ if ( last_off && cur->last!=NULL )
+ FigureControls(cur->last,sp,&pts[i-1],is_order2);
+ /* last_off continues to be true */
+ } else {
+ if ( cur->first!=NULL )
+ cur->last->nextcpindex = i;
+ last_off = true;
+ sp = NULL;
+ }
+ if ( sp!=NULL ) {
+ if ( cur->first==NULL )
+ cur->first = sp;
+ else
+ SplineMake(cur->last,sp,is_order2);
+ cur->last = sp;
+ }
+ ++i;
+ }
+ if ( start==i-1 ) {
+ /* MS chinese fonts have contours consisting of a single off curve*/
+ /* point. What on earth do they think that means? */
+ /* Oh. I see. It's used to possition marks and such */
+ if ( cur->first==NULL ) {
+ sp = chunkalloc(sizeof(SplinePoint));
+ sp->me.x = pts[start].x;
+ sp->me.y = pts[start].y;
+ sp->nextcp = sp->prevcp = sp->me;
+ sp->nonextcp = sp->noprevcp = true;
+ sp->ttfindex = i-1;
+ sp->nextcpindex = 0xffff;
+ cur->first = cur->last = sp;
+ }
+ } else if ( !(flags[start]&_On_Curve) && !(flags[i-1]&_On_Curve) ) {
+ sp = chunkalloc(sizeof(SplinePoint));
+ sp->me.x = (pts[start].x+pts[i-1].x)/2;
+ sp->me.y = (pts[start].y+pts[i-1].y)/2;
+ sp->nextcp = sp->prevcp = sp->me;
+ sp->nonextcp = true;
+ sp->ttfindex = 0xffff;
+ sp->nextcpindex = start;
+ FigureControls(cur->last,sp,&pts[i-1],is_order2);
+ SplineMake(cur->last,sp,is_order2);
+ cur->last = sp;
+ FigureControls(sp,cur->first,&pts[start],is_order2);
+ } else if ( !(flags[i-1]&_On_Curve)) {
+ FigureControls(cur->last,cur->first,&pts[i-1],is_order2);
+ cur->last->nextcpindex = i-1;
+ } else if ( !(flags[start]&_On_Curve) ) {
+ FigureControls(cur->last,cur->first,&pts[start],is_order2);
+ sp->nextcpindex = start;
+ }
+ if ( cur->last!=cur->first ) {
+ SplineMake(cur->last,cur->first,is_order2);
+ cur->last = cur->first;
+ }
+ for ( sp=cur->first; ; ) {
+ if ( sp->ttfindex!=0xffff && SPInterpolate(sp) )
+ sp->dontinterpolate = true;
+ if ( sp->next==NULL )
+ break;
+ sp=sp->next->to;
+ if ( sp==cur->first )
+ break;
+ }
+ }
+return( head );
+}
+
+static void readttfsimpleglyph(FILE *ttf,struct ttfinfo *info,SplineChar *sc, int path_cnt) {
+ uint16 *endpt = galloc((path_cnt+1)*sizeof(uint16));
+ uint8 *instructions;
+ char *flags;
+ BasePoint *pts;
+ int i, j, tot, len;
+ int last_pos;
+
+ for ( i=0; i<path_cnt; ++i ) {
+ endpt[i] = getushort(ttf);
+ if ( i!=0 && endpt[i]<endpt[i-1] ) {
+ LogError( _("Bad tt font: contour ends make no sense in glyph %d.\n"),
+ sc->orig_pos );
+return;
+ }
+ }
+ if ( path_cnt==0 ) {
+ tot = 0;
+ pts = galloc(sizeof(BasePoint));
+ } else {
+ tot = endpt[path_cnt-1]+1;
+ pts = galloc(tot*sizeof(BasePoint));
+ }
+
+ len = getushort(ttf);
+ instructions = galloc(len);
+ for ( i=0; i<len; ++i )
+ instructions[i] = getc(ttf);
+
+ flags = galloc(tot);
+ for ( i=0; i<tot; ++i ) {
+ flags[i] = getc(ttf);
+ if ( flags[i]&_Repeat ) {
+ int cnt = getc(ttf);
+ if ( i+cnt>=tot ) {
+ IError("Flag count is wrong (or total is): %d %d", i+cnt, tot );
+ cnt = tot-i-1;
+ }
+ for ( j=0; j<cnt; ++j )
+ flags[i+j+1] = flags[i];
+ i += cnt;
+ }
+ if ( feof(ttf))
+ break;
+ }
+ if ( i!=tot )
+ IError("Flag count is wrong (or total is): %d %d in glyph %d", i, tot, sc->orig_pos );
+
+ last_pos = 0;
+ for ( i=0; i<tot; ++i ) {
+ if ( flags[i]&_X_Short ) {
+ int off = getc(ttf);
+ if ( !(flags[i]&_X_Same ) )
+ off = -off;
+ pts[i].x = last_pos + off;
+ } else if ( flags[i]&_X_Same )
+ pts[i].x = last_pos;
+ else
+ pts[i].x = last_pos + (short) getushort(ttf);
+ last_pos = pts[i].x;
+ }
+
+ last_pos = 0;
+ for ( i=0; i<tot; ++i ) {
+ if ( flags[i]&_Y_Short ) {
+ int off = getc(ttf);
+ if ( !(flags[i]&_Y_Same ) )
+ off = -off;
+ pts[i].y = last_pos + off;
+ } else if ( flags[i]&_Y_Same )
+ pts[i].y = last_pos;
+ else
+ pts[i].y = last_pos + (short) getushort(ttf);
+ last_pos = pts[i].y;
+ }
+
+ sc->layers[ly_fore].splines = ttfbuildcontours(path_cnt,endpt,flags,pts,info->to_order2);
+ if ( info->to_order2 && len!=0 ) {
+ sc->ttf_instrs_len = len;
+ sc->ttf_instrs = instructions;
+ } else
+ free(instructions);
+ SCCatagorizePoints(sc);
+ free(endpt);
+ free(flags);
+ free(pts);
+ if ( feof(ttf))
+ LogError( _("Reached end of file when reading simple glyph\n") );
+}
+
+static void readttfcompositglyph(FILE *ttf,struct ttfinfo *info,SplineChar *sc, int32 end) {
+ RefChar *head=NULL, *last=NULL, *cur;
+ int flags=0, arg1, arg2;
+
+ if ( ftell(ttf)>=end ) {
+ LogError( _("Empty composite %d\n"), sc->orig_pos );
+return;
+ }
+
+ do {
+ if ( ftell(ttf)>=end ) {
+ LogError( _("Bad flags value, implied MORE components at end of glyph %d\n"), sc->orig_pos );
+ break;
+ }
+ cur = RefCharCreate();
+ flags = getushort(ttf);
+ cur->orig_pos = getushort(ttf);
+ if ( feof(ttf) || cur->orig_pos>=info->glyph_cnt ) {
+ LogError(_("Reference to glyph %d out of bounds when parsing 'glyf' table.\n"), cur->orig_pos );
+ cur->orig_pos = 0;
+ }
+ if ( info->inuse!=NULL )
+ info->inuse[cur->orig_pos] = true;
+ if ( flags&_ARGS_ARE_WORDS ) {
+ arg1 = (short) getushort(ttf);
+ arg2 = (short) getushort(ttf);
+ } else {
+ arg1 = (signed char) getc(ttf);
+ arg2 = (signed char) getc(ttf);
+ }
+ cur->use_my_metrics = (flags & _USE_MY_METRICS) ? 1 : 0;
+ cur->round_translation_to_grid = (flags & _ROUND) ? 1 : 0;
+ if ( flags & _ARGS_ARE_XY ) {
+ /* There is some very strange stuff (half-)documented on the apple*/
+ /* site about how these should be interpretted when there are */
+ /* scale factors, or rotations */
+ /* It isn't well enough described to be comprehensible */
+ /* http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html */
+ /* Microsoft says nothing about this */
+ /* Adobe implies this is a difference between MS and Apple */
+ /* MS doesn't do this, Apple does (GRRRGH!!!!) */
+ /* Adobe says that setting bit 12 means that this will not happen */
+ /* Adobe says that setting bit 11 means that this will happen */
+ /* So if either bit is set we know when this happens, if neither */
+ /* we guess... But I still don't know how to interpret the */
+ /* apple mode under rotation... */
+ /* I notice that FreeType does nothing about rotation nor does it */
+ /* interpret bits 11&12 */
+ /* Ah. It turns out that even Apple does not do what Apple's docs */
+ /* claim it does. I think I've worked it out (see below), but... */
+ /* Bleah! */
+ cur->transform[4] = arg1;
+ cur->transform[5] = arg2;
+ } else {
+ /* Somehow we can get offsets by looking at the points in the */
+ /* points so far generated and comparing them to the points in */
+ /* the current componant */
+ /* How exactly is not described on any of the Apple, MS, Adobe */
+ /* freetype looks up arg1 in the set of points we've got so far */
+ /* looks up arg2 in the new component (before renumbering) */
+ /* offset.x = arg1.x - arg2.x; offset.y = arg1.y - arg2.y; */
+ /* This fixup needs to be done later though (after all glyphs */
+ /* have been loaded) */
+ cur->match_pt_base = arg1;
+ cur->match_pt_ref = arg2;
+ cur->point_match = true;
+ }
+ cur->transform[0] = cur->transform[3] = 1.0;
+ if ( flags & _SCALE )
+ cur->transform[0] = cur->transform[3] = get2dot14(ttf);
+ else if ( flags & _XY_SCALE ) {
+ cur->transform[0] = get2dot14(ttf);
+ cur->transform[3] = get2dot14(ttf);
+ } else if ( flags & _MATRIX ) {
+ cur->transform[0] = get2dot14(ttf);
+ cur->transform[1] = get2dot14(ttf);
+ cur->transform[2] = get2dot14(ttf);
+ cur->transform[3] = get2dot14(ttf);
+ }
+ if ( flags & _ARGS_ARE_XY ) { /* Only muck with these guys if they are real offsets and not point matching */
+#ifdef __Mac
+ /* On mac assume scaled offsets unless told unscaled explicitly */
+ if ( !(flags&_UNSCALED_OFFSETS) &&
+#else
+ /* everywhere else assume unscaled offsets unless told scaled explicitly */
+ if ( (flags & _SCALED_OFFSETS) &&
+#endif
+ (flags & _ARGS_ARE_XY) && (flags&(_SCALE|_XY_SCALE|_MATRIX))) {
+ /*static int asked = 0;*/
+ /* This is not what Apple documents on their website. But it is */
+ /* what appears to match the behavior of their rasterizer */
+ /* Apple has changed their documentation (without updating their */
+ /* changelog), but I believe they are still incorrect */
+ cur->transform[4] *= sqrt(cur->transform[0]*cur->transform[0]+
+ cur->transform[1]*cur->transform[1]);
+ cur->transform[5] *= sqrt(cur->transform[2]*cur->transform[2]+
+ cur->transform[3]*cur->transform[3]);
+#if 0
+ /* Apple's Chicago is an example */
+ if ( info->fontname!=NULL && strcmp(info->fontname,"CompositeMac")!=0 && !asked ) {
+ /* Not interested in the test font I generated myself */
+ asked = true;
+ fprintf( stderr, "Neat! You've got a font that actually uses Apple's scaled composite offsets.\n" );
+ fprintf( stderr, " I've never seen one, could you send me a copy of %s?\n", info->fontname );
+ fprintf( stderr, " Thanks. gww@silcom.com\n" );
+ }
+#endif
+ }
+ }
+ if ( cur->orig_pos>=info->glyph_cnt ) {
+ LogError(_("Glyph %d attempts to reference glyph %d which is outside the font\n"), sc->orig_pos, cur->orig_pos );
+ chunkfree(cur,sizeof(*cur));
+ } else {
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ }
+ if ( feof(ttf)) {
+ LogError(_("Reached end of file when reading composit glyph\n") );
+ break;
+ }
+ } while ( flags&_MORE );
+ if ( (flags & _INSTR ) && info->to_order2 && ftell(ttf)<end ) {
+ sc->ttf_instrs_len = getushort(ttf);
+ if ( sc->ttf_instrs_len > 0 && ftell(ttf)+sc->ttf_instrs_len<=end ) {
+ uint8 *instructions = galloc(sc->ttf_instrs_len);
+ int i;
+ for ( i=0; i<sc->ttf_instrs_len; ++i )
+ instructions[i] = getc(ttf);
+ sc->ttf_instrs = instructions;
+ } else
+ sc->ttf_instrs_len = 0;
+ }
+ /* I'm ignoring many things that I don't understand here */
+ /* what happens if ARGS AREN'T XY */
+ /* ROUND means that offsets should rounded to the grid before being added */
+ /* (it's irrelevant for my purposes) */
+ sc->layers[ly_fore].refs = head;
+}
+
+static SplineChar *readttfglyph(FILE *ttf,struct ttfinfo *info,int start, int end,int gid) {
+ int path_cnt;
+ SplineChar *sc = SplineCharCreate();
+
+ sc->unicodeenc = -1;
+ sc->vwidth = info->emsize;
+ /* sc->manualhints = 1; */ /* But only when I know how to read them in!!!! */
+
+ if ( end>info->glyph_length ) {
+ if ( !info->complainedbeyondglyfend )
+ LogError(_("Bad glyph (%d), its definition extends beyond the end of the glyf table\n"), gid );
+ info->complainedbeyondglyfend = true;
+ SplineCharFree(sc);
+return( NULL );
+ }
+ if ( start==end ) {
+ /* This isn't mentioned, but we seem to get some glyphs with no size,*/
+ /* not even a path cnt. They appear to be empty glyphs */
+return( sc );
+ }
+ fseek(ttf,info->glyph_start+start,SEEK_SET);
+ path_cnt = (short) getushort(ttf);
+#ifdef LUA_FF_LIB
+ sc->xmin = getushort(ttf);
+ sc->ymin = getushort(ttf);
+ sc->xmax = getushort(ttf);
+ sc->ymax = getushort(ttf);
+ /* TH: this was ugly, and not needed
+ sc->lsidebearing = sc->ymax;
+ */
+#else
+ /* xmin = */ getushort(ttf);
+ /* ymin = */ getushort(ttf);
+ /* xmax = */ getushort(ttf);
+ /* ymax = */ sc->lsidebearing = getushort(ttf);
+#endif
+ sc->orig_pos = gid;
+ if ( path_cnt>=0 )
+ readttfsimpleglyph(ttf,info,sc,path_cnt);
+ else
+ readttfcompositglyph(ttf,info,sc,info->glyph_start+end);
+ if ( start>end )
+ LogError(_("Bad glyph (%d), disordered 'loca' table (start comes after end)\n"), gid );
+ else if ( ftell(ttf)>info->glyph_start+end )
+ LogError(_("Bad glyph (%d), its definition extends beyond the space allowed for it\n"), gid );
+return( sc );
+}
+
+static void readttfencodings(FILE *ttf,struct ttfinfo *info, int justinuse);
+
+static void readttfglyphs(FILE *ttf,struct ttfinfo *info) {
+ int i, anyread;
+ uint32 *goffsets = galloc((info->glyph_cnt+1)*sizeof(uint32));
+
+ /* First we read all the locations. This might not be needed, they may */
+ /* just follow one another, but nothing I've noticed says that so let's */
+ /* be careful */
+ fseek(ttf,info->glyphlocations_start,SEEK_SET);
+ if ( info->index_to_loc_is_long ) {
+ for ( i=0; i<=info->glyph_cnt ; ++i )
+ goffsets[i] = getlong(ttf);
+ } else {
+ for ( i=0; i<=info->glyph_cnt ; ++i )
+ goffsets[i] = 2*getushort(ttf);
+ }
+
+ info->chars = gcalloc(info->glyph_cnt,sizeof(SplineChar *));
+ if ( !info->is_ttc ) {
+ /* read all the glyphs */
+ for ( i=0; i<info->glyph_cnt ; ++i ) {
+ info->chars[i] = readttfglyph(ttf,info,goffsets[i],goffsets[i+1],i);
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_next();
+#endif
+ }
+ } else {
+ /* only read the glyphs we actually use in this font */
+ /* this is complicated by references (and substitutions), */
+ /* we can't just rely on the encoding to tell us what is used */
+ info->inuse = gcalloc(info->glyph_cnt,sizeof(char));
+ readttfencodings(ttf,info,true);
+ if ( info->gsub_start!=0 ) /* Some glyphs may appear in substitutions and not in the encoding... */
+ readttfgsubUsed(ttf,info);
+ /* I don't bother to read the morx table because mac doesn't */
+ /* support ttc files */
+ anyread = true;
+ while ( anyread ) {
+ anyread = false;
+ for ( i=0; i<info->glyph_cnt ; ++i ) {
+ if ( info->inuse[i] && info->chars[i]==NULL ) {
+ info->chars[i] = readttfglyph(ttf,info,goffsets[i],goffsets[i+1],i);
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_next();
+#endif
+ anyread = info->chars[i]!=NULL;
+ }
+ }
+ }
+ free(info->inuse); info->inuse = NULL;
+ }
+ free(goffsets);
+ for ( i=0; i<info->glyph_cnt ; ++i )
+ if ( info->chars[i]!=NULL )
+ info->chars[i]->orig_pos = i;
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_next_stage();
+#endif
+}
+
+/* Standard names for cff */
+const char *cffnames[] = {
+ ".notdef",
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quoteright",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "quoteleft",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+ "braceright",
+ "asciitilde",
+ "exclamdown",
+ "cent",
+ "sterling",
+ "fraction",
+ "yen",
+ "florin",
+ "section",
+ "currency",
+ "quotesingle",
+ "quotedblleft",
+ "guillemotleft",
+ "guilsinglleft",
+ "guilsinglright",
+ "fi",
+ "fl",
+ "endash",
+ "dagger",
+ "daggerdbl",
+ "periodcentered",
+ "paragraph",
+ "bullet",
+ "quotesinglbase",
+ "quotedblbase",
+ "quotedblright",
+ "guillemotright",
+ "ellipsis",
+ "perthousand",
+ "questiondown",
+ "grave",
+ "acute",
+ "circumflex",
+ "tilde",
+ "macron",
+ "breve",
+ "dotaccent",
+ "dieresis",
+ "ring",
+ "cedilla",
+ "hungarumlaut",
+ "ogonek",
+ "caron",
+ "emdash",
+ "AE",
+ "ordfeminine",
+ "Lslash",
+ "Oslash",
+ "OE",
+ "ordmasculine",
+ "ae",
+ "dotlessi",
+ "lslash",
+ "oslash",
+ "oe",
+ "germandbls",
+ "onesuperior",
+ "logicalnot",
+ "mu",
+ "trademark",
+ "Eth",
+ "onehalf",
+ "plusminus",
+ "Thorn",
+ "onequarter",
+ "divide",
+ "brokenbar",
+ "degree",
+ "thorn",
+ "threequarters",
+ "twosuperior",
+ "registered",
+ "minus",
+ "eth",
+ "multiply",
+ "threesuperior",
+ "copyright",
+ "Aacute",
+ "Acircumflex",
+ "Adieresis",
+ "Agrave",
+ "Aring",
+ "Atilde",
+ "Ccedilla",
+ "Eacute",
+ "Ecircumflex",
+ "Edieresis",
+ "Egrave",
+ "Iacute",
+ "Icircumflex",
+ "Idieresis",
+ "Igrave",
+ "Ntilde",
+ "Oacute",
+ "Ocircumflex",
+ "Odieresis",
+ "Ograve",
+ "Otilde",
+ "Scaron",
+ "Uacute",
+ "Ucircumflex",
+ "Udieresis",
+ "Ugrave",
+ "Yacute",
+ "Ydieresis",
+ "Zcaron",
+ "aacute",
+ "acircumflex",
+ "adieresis",
+ "agrave",
+ "aring",
+ "atilde",
+ "ccedilla",
+ "eacute",
+ "ecircumflex",
+ "edieresis",
+ "egrave",
+ "iacute",
+ "icircumflex",
+ "idieresis",
+ "igrave",
+ "ntilde",
+ "oacute",
+ "ocircumflex",
+ "odieresis",
+ "ograve",
+ "otilde",
+ "scaron",
+ "uacute",
+ "ucircumflex",
+ "udieresis",
+ "ugrave",
+ "yacute",
+ "ydieresis",
+ "zcaron",
+ "exclamsmall",
+ "Hungarumlautsmall",
+ "dollaroldstyle",
+ "dollarsuperior",
+ "ampersandsmall",
+ "Acutesmall",
+ "parenleftsuperior",
+ "parenrightsuperior",
+ "twodotenleader",
+ "onedotenleader",
+ "zerooldstyle",
+ "oneoldstyle",
+ "twooldstyle",
+ "threeoldstyle",
+ "fouroldstyle",
+ "fiveoldstyle",
+ "sixoldstyle",
+ "sevenoldstyle",
+ "eightoldstyle",
+ "nineoldstyle",
+ "commasuperior",
+ "threequartersemdash",
+ "periodsuperior",
+ "questionsmall",
+ "asuperior",
+ "bsuperior",
+ "centsuperior",
+ "dsuperior",
+ "esuperior",
+ "isuperior",
+ "lsuperior",
+ "msuperior",
+ "nsuperior",
+ "osuperior",
+ "rsuperior",
+ "ssuperior",
+ "tsuperior",
+ "ff",
+ "ffi",
+ "ffl",
+ "parenleftinferior",
+ "parenrightinferior",
+ "Circumflexsmall",
+ "hyphensuperior",
+ "Gravesmall",
+ "Asmall",
+ "Bsmall",
+ "Csmall",
+ "Dsmall",
+ "Esmall",
+ "Fsmall",
+ "Gsmall",
+ "Hsmall",
+ "Ismall",
+ "Jsmall",
+ "Ksmall",
+ "Lsmall",
+ "Msmall",
+ "Nsmall",
+ "Osmall",
+ "Psmall",
+ "Qsmall",
+ "Rsmall",
+ "Ssmall",
+ "Tsmall",
+ "Usmall",
+ "Vsmall",
+ "Wsmall",
+ "Xsmall",
+ "Ysmall",
+ "Zsmall",
+ "colonmonetary",
+ "onefitted",
+ "rupiah",
+ "Tildesmall",
+ "exclamdownsmall",
+ "centoldstyle",
+ "Lslashsmall",
+ "Scaronsmall",
+ "Zcaronsmall",
+ "Dieresissmall",
+ "Brevesmall",
+ "Caronsmall",
+ "Dotaccentsmall",
+ "Macronsmall",
+ "figuredash",
+ "hypheninferior",
+ "Ogoneksmall",
+ "Ringsmall",
+ "Cedillasmall",
+ "questiondownsmall",
+ "oneeighth",
+ "threeeighths",
+ "fiveeighths",
+ "seveneighths",
+ "onethird",
+ "twothirds",
+ "zerosuperior",
+ "foursuperior",
+ "fivesuperior",
+ "sixsuperior",
+ "sevensuperior",
+ "eightsuperior",
+ "ninesuperior",
+ "zeroinferior",
+ "oneinferior",
+ "twoinferior",
+ "threeinferior",
+ "fourinferior",
+ "fiveinferior",
+ "sixinferior",
+ "seveninferior",
+ "eightinferior",
+ "nineinferior",
+ "centinferior",
+ "dollarinferior",
+ "periodinferior",
+ "commainferior",
+ "Agravesmall",
+ "Aacutesmall",
+ "Acircumflexsmall",
+ "Atildesmall",
+ "Adieresissmall",
+ "Aringsmall",
+ "AEsmall",
+ "Ccedillasmall",
+ "Egravesmall",
+ "Eacutesmall",
+ "Ecircumflexsmall",
+ "Edieresissmall",
+ "Igravesmall",
+ "Iacutesmall",
+ "Icircumflexsmall",
+ "Idieresissmall",
+ "Ethsmall",
+ "Ntildesmall",
+ "Ogravesmall",
+ "Oacutesmall",
+ "Ocircumflexsmall",
+ "Otildesmall",
+ "Odieresissmall",
+ "OEsmall",
+ "Oslashsmall",
+ "Ugravesmall",
+ "Uacutesmall",
+ "Ucircumflexsmall",
+ "Udieresissmall",
+ "Yacutesmall",
+ "Thornsmall",
+ "Ydieresissmall",
+ "001.000",
+ "001.001",
+ "001.002",
+ "001.003",
+ "Black",
+ "Bold",
+ "Book",
+ "Light",
+ "Medium",
+ "Regular",
+ "Roman",
+ "Semibold",
+ NULL
+};
+const int nStdStrings = sizeof(cffnames)/sizeof(cffnames[0])-1;
+
+static char **readcfffontnames(FILE *ttf,int *cnt) {
+ uint16 count = getushort(ttf);
+ int offsize;
+ uint32 *offsets;
+ char **names;
+ int i,j;
+
+ if ( cnt!=NULL ) *cnt = count;
+
+ if ( count==0 )
+return( NULL );
+ offsets = galloc((count+1)*sizeof(uint32));
+ offsize = getc(ttf);
+ for ( i=0; i<=count; ++i )
+ offsets[i] = getoffset(ttf,offsize);
+ names = galloc((count+1)*sizeof(char *));
+ for ( i=0; i<count; ++i ) {
+ if ( offsets[i+1]<offsets[i] ) {
+/* GT: The CFF font type contains a thing called a name INDEX, and that INDEX */
+/* GT: is bad. It is an index of many of the names used in the CFF font. */
+/* GT: We hope the user will never see this. */
+ LogError( _("Bad CFF name INDEX\n") );
+ while ( i<count ) {
+ names[i] = copy("");
+ ++i;
+ }
+ --i;
+ } else {
+ names[i] = galloc(offsets[i+1]-offsets[i]+1);
+ for ( j=0; j<offsets[i+1]-offsets[i]; ++j )
+ names[i][j] = getc(ttf);
+ names[i][j] = '\0';
+ }
+ }
+ names[i] = NULL;
+ free(offsets);
+return( names );
+}
+
+static char *addnibble(char *pt, int nib) {
+ if ( nib<=9 )
+ *pt++ = nib+'0';
+ else if ( nib==10 )
+ *pt++ = '.';
+ else if ( nib==11 )
+ *pt++ = 'E';
+ else if ( nib==12 ) {
+ *pt++ = 'E';
+ *pt++ = '-';
+ } else if ( nib==14 )
+ *pt++ = '-';
+ else if ( nib==15 )
+ *pt++ = '\0';
+return( pt );
+}
+
+static int readcffthing(FILE *ttf,int *_ival,real *dval,int *operand) {
+ char buffer[50], *pt;
+ int ch, ival;
+
+ ch = getc(ttf);
+ if ( ch==12 ) {
+ *operand = (12<<8) | getc(ttf);
+return( 3 );
+ } else if ( ch<=21 ) {
+ *operand = ch;
+return( 3 );
+ } else if ( ch==30 ) {
+ /* fixed format doesn't exist in dict data but does in type2 strings */
+ pt = buffer;
+ do {
+ ch = getc(ttf);
+ if ( pt<buffer+44 || (ch&0xf)==0xf || (ch&0xf0)==0xf0 ) {
+ pt = addnibble(pt,ch>>4);
+ pt = addnibble(pt,ch&0xf);
+ }
+ } while ( pt[-1]!='\0' );
+ *dval = strtod(buffer,NULL);
+return( 2 );
+ } else if ( ch>=32 && ch<=246 ) {
+ *_ival = ch-139;
+return( 1 );
+ } else if ( ch>=247 && ch<=250 ) {
+ *_ival = ((ch-247)<<8) + getc(ttf)+108;
+return( 1 );
+ } else if ( ch>=251 && ch<=254 ) {
+ *_ival = -((ch-251)<<8) - getc(ttf)-108;
+return( 1 );
+ } else if ( ch==28 ) {
+ ival = getc(ttf)<<8;
+ *_ival = (short) (ival | getc(ttf));
+return( 1 );
+ } else if ( ch==29 ) {
+ /* 4 byte integers exist in dict data but not in type2 strings */
+ ival = getc(ttf)<<24;
+ ival = ival | getc(ttf)<<16;
+ ival = ival | getc(ttf)<<8;
+ *_ival = (int) (ival | getc(ttf));
+return( 1 );
+ }
+ LogError(_("Unexpected value in dictionary %d\n"), ch );
+ *_ival = 0;
+return( 0 );
+}
+
+static void skipcfft2thing(FILE *ttf) {
+ /* The old CFF spec allows little type2 programs to live in the CFF dict */
+ /* indices. These are designed to allow interpolation of values for mm */
+ /* fonts. */
+ /* The Type2 program is terminated by an "endchar" operator */
+ /* I don't support this, but I shall try to skip over them properly */
+ /* There's no discussion about how values move from the t2 stack to the */
+ /* cff stack, as there are no examples of this, it's hard to guess */
+ int ch;
+
+/* GT: DICT is a magic term inside CFF fonts, as is INDEX, and I guess CFF and type2 */
+ LogError( _("FontForge does not support type2 programs embedded in CFF DICT INDICES.\n") );
+ forever {
+ ch = getc(ttf);
+ if ( ch>=247 && ch<=254 )
+ getc(ttf); /* Two byte number */
+ else if ( ch==255 ) {
+ getc(ttf); getc(ttf); getc(ttf); getc(ttf);
+ /* 16.16 number */
+ } else if ( ch==28 ) {
+ getc(ttf);
+ getc(ttf);
+ } else if ( ch==12 ) {
+ getc(ttf); /* Two byte operator */
+ } else if ( ch==14 ) {
+return;
+ }
+ }
+}
+
+struct topdicts {
+ int32 cff_start;
+
+ char *fontname; /* From Name Index */
+
+ int version; /* SID */
+ int notice; /* SID */
+ int copyright; /* SID */
+ int fullname; /* SID */
+ int familyname; /* SID */
+ int weight; /* SID */
+ int isfixedpitch;
+ real italicangle;
+ real underlinepos;
+ real underlinewidth;
+ int painttype;
+ int charstringtype;
+ real fontmatrix[6];
+ int uniqueid;
+ real fontbb[4];
+ real strokewidth;
+ int xuid[20];
+ int charsetoff; /* from start of file */
+ int encodingoff; /* from start of file */
+ int charstringsoff; /* from start of file */
+ int private_size;
+ int private_offset; /* from start of file */
+ int synthetic_base; /* font index */
+ int postscript_code; /* SID */
+ /* synthetic fonts only (whatever they are) */
+ int basefontname; /* SID */
+ /* Multiple master/synthetic fonts */
+ real basefontblend[16]; /* delta */ /* No description of why this is relevant for mm fonts */
+ /* Multiple master fonts only */
+ int blendaxistypes[17]; /* SID */
+ int nMasters;
+ int nAxes;
+ real weightvector[17];
+ int lenBuildCharArray; /* No description of what this means */
+ int NormalizeDesignVector; /* SID */ /* No description of what this does */
+ int ConvertDesignVector; /* SID */ /* No description of what this does */
+ /* CID fonts only */
+ int ros_registry; /* SID */
+ int ros_ordering; /* SID */
+ int ros_supplement;
+ real cidfontversion;
+ int cidfontrevision;
+ int cidfonttype;
+ int cidcount;
+ int uidbase;
+ int fdarrayoff; /* from start of file */
+ int fdselectoff; /* from start of file */
+ int sid_fontname; /* SID */
+/* Private stuff */
+ real bluevalues[14];
+ real otherblues[10];
+ real familyblues[14];
+ real familyotherblues[10];
+ real bluescale;
+ real blueshift;
+ real bluefuzz;
+ int stdhw;
+ int stdvw;
+ real stemsnaph[10];
+ real stemsnapv[10];
+ int forcebold;
+ real forceboldthreshold;
+ int languagegroup;
+ real expansionfactor;
+ int initialRandomSeed;
+ int subrsoff; /* from start of this private table */
+ int defaultwidthx;
+ int nominalwidthx;
+
+ struct pschars glyphs;
+ struct pschars local_subrs;
+ uint16 *charset;
+};
+
+static void TopDictFree(struct topdicts *dict) {
+ int i;
+
+ free(dict->charset);
+ for ( i=0; i<dict->glyphs.cnt; ++i )
+ free(dict->glyphs.values[i]);
+ free(dict->glyphs.values);
+ free(dict->glyphs.lens);
+ for ( i=0; i<dict->local_subrs.cnt; ++i )
+ free(dict->local_subrs.values[i]);
+ free(dict->local_subrs.values);
+ free(dict->local_subrs.lens);
+ free(dict);
+}
+
+static void readcffsubrs(FILE *ttf, struct pschars *subs) {
+ uint16 count = getushort(ttf);
+ int offsize;
+ uint32 *offsets;
+ int i,j, base;
+ int err = false;
+
+ memset(subs,'\0',sizeof(struct pschars));
+ if ( count==0 )
+return;
+ subs->cnt = count;
+ subs->lens = galloc(count*sizeof(int));
+ subs->values = galloc(count*sizeof(uint8 *));
+ offsets = galloc((count+1)*sizeof(uint32));
+ offsize = getc(ttf);
+ for ( i=0; i<=count; ++i )
+ offsets[i] = getoffset(ttf,offsize);
+ base = ftell(ttf)-1;
+ for ( i=0; i<count; ++i ) {
+ if ( offsets[i+1]>offsets[i] && offsets[i+1]-offsets[i]<0x10000 ) {
+ subs->lens[i] = offsets[i+1]-offsets[i];
+ subs->values[i] = galloc(offsets[i+1]-offsets[i]+1);
+ for ( j=0; j<offsets[i+1]-offsets[i]; ++j )
+ subs->values[i][j] = getc(ttf);
+ subs->values[i][j] = '\0';
+ } else {
+ if ( !err )
+ LogError( _("Bad subroutine INDEX in cff font.\n" ));
+ err = true;
+ subs->lens[i] = 1;
+ subs->values[i] = galloc(2);
+ subs->values[i][0] = 11; /* return */
+ subs->values[i][1] = '\0';
+ fseek(ttf,base+offsets[i+1],SEEK_SET);
+ }
+ }
+ free(offsets);
+}
+
+static struct topdicts *readcfftopdict(FILE *ttf, char *fontname, int len) {
+ struct topdicts *td = gcalloc(1,sizeof(struct topdicts));
+ long base = ftell(ttf);
+ int ival, oval, sp, ret, i;
+ real stack[50];
+
+ if ( fontname!=NULL )
+ ValidatePostScriptFontName(fontname);
+
+ td->fontname = fontname;
+ td->underlinepos = -100;
+ td->underlinewidth = 50;
+ td->charstringtype = 2;
+ td->fontmatrix[0] = td->fontmatrix[3] = .001;
+
+ td->notice = td->copyright = td->fullname = td->familyname = td->weight = td->version = -1;
+ td->postscript_code = td->basefontname = -1;
+ td->synthetic_base = td->ros_registry = -1;
+ td->fdarrayoff = td->fdselectoff = td->sid_fontname = -1;
+ td->blendaxistypes[0] = -1;
+
+ /* Multiple master fonts can have Type2 operators here, particularly */
+ /* blend operators. We're ignoring that */
+ while ( ftell(ttf)<base+len ) {
+ sp = 0;
+ while ( (ret=readcffthing(ttf,&ival,&stack[sp],&oval))!=3 && ftell(ttf)<base+len ) {
+ if ( ret==1 )
+ stack[sp]=ival;
+ if ( ret!=0 && sp<45 )
+ ++sp;
+ }
+ if ( ret==3 && oval==31 /* "T2" operator, can have 0 arguments */ ) {
+ skipcfft2thing(ttf);
+ } else if ( sp==0 )
+ LogError( _("No argument to operator\n") );
+ else if ( ret==3 ) switch( oval ) {
+ case 0:
+ td->version = stack[sp-1];
+ break;
+ case 1:
+ td->notice = stack[sp-1];
+ break;
+ case (12<<8)+0:
+ td->copyright = stack[sp-1];
+ break;
+ case 2:
+ td->fullname = stack[sp-1];
+ break;
+ case 3:
+ td->familyname = stack[sp-1];
+ break;
+ case 4:
+ td->weight = stack[sp-1];
+ break;
+ case (12<<8)+1:
+ td->isfixedpitch = stack[sp-1];
+ break;
+ case (12<<8)+2:
+ td->italicangle = stack[sp-1];
+ break;
+ case (12<<8)+3:
+ td->underlinepos = stack[sp-1];
+ break;
+ case (12<<8)+4:
+ td->underlinewidth = stack[sp-1];
+ break;
+ case (12<<8)+5:
+ td->painttype = stack[sp-1];
+ break;
+ case (12<<8)+6:
+ td->charstringtype = stack[sp-1];
+ break;
+ case (12<<8)+7:
+ memcpy(td->fontmatrix,stack,(sp>=6?6:sp)*sizeof(real));
+ break;
+ case 13:
+ td->uniqueid = stack[sp-1];
+ break;
+ case 5:
+ memcpy(td->fontbb,stack,(sp>=4?4:sp)*sizeof(real));
+ break;
+ case (12<<8)+8:
+ td->strokewidth = stack[sp-1];
+ break;
+ case 14:
+ for ( i=0; i<sp && i<20; ++i )
+ td->xuid[i] = stack[i];
+ break;
+ case 15:
+ td->charsetoff = stack[sp-1];
+ break;
+ case 16:
+ td->encodingoff = stack[sp-1];
+ break;
+ case 17:
+ td->charstringsoff = stack[sp-1];
+ break;
+ case 18:
+ td->private_size = stack[0];
+ td->private_offset = stack[1];
+ break;
+ case (12<<8)+20:
+ LogError( _("FontForge does not support synthetic fonts\n") );
+ td->synthetic_base = stack[sp-1];
+ break;
+ case (12<<8)+21:
+ td->postscript_code = stack[sp-1];
+ break;
+ case (12<<8)+22:
+ td->basefontname = stack[sp-1];
+ break;
+ case (12<<8)+23:
+ for ( i=0; i<sp && i<16; ++i )
+ td->basefontblend[i] = stack[i];
+ break;
+ case (12<<8)+24:
+ LogError( _("FontForge does not support type2 multiple master fonts\n") );
+ td->nMasters = stack[0];
+ td->nAxes = sp-4;
+ memcpy(td->weightvector,stack+1,(sp-4)*sizeof(real));
+ td->lenBuildCharArray = stack[sp-3];
+ td->NormalizeDesignVector = stack[sp-2]; /* These are type2 charstrings, even in type1 fonts */
+ td->ConvertDesignVector = stack[sp-1];
+ break;
+ case (12<<8)+26:
+ for ( i=0; i<sp && i<16; ++i )
+ td->blendaxistypes[i] = stack[i];
+ td->blendaxistypes[i] = -1;
+ break;
+ case (12<<8)+30:
+ td->ros_registry = stack[0];
+ td->ros_ordering = stack[1];
+ td->ros_supplement = stack[2];
+ break;
+ case (12<<8)+31:
+ td->cidfontversion = stack[sp-1];
+ break;
+ case (12<<8)+32:
+ td->cidfontrevision = stack[sp-1];
+ break;
+ case (12<<8)+33:
+ td->cidfonttype = stack[sp-1];
+ break;
+ case (12<<8)+34:
+ td->cidcount = stack[sp-1];
+ break;
+ case (12<<8)+35:
+ td->uidbase = stack[sp-1];
+ break;
+ case (12<<8)+36:
+ td->fdarrayoff = stack[sp-1];
+ break;
+ case (12<<8)+37:
+ td->fdselectoff = stack[sp-1];
+ break;
+ case (12<<8)+38:
+ td->sid_fontname = stack[sp-1];
+ break;
+ case (12<<8)+39:
+ LogError(_("FontForge does not support Chameleon fonts\n"));;
+ break;
+ default:
+ LogError(_("Unknown operator in %s: %x\n"), fontname, oval );
+ break;
+ }
+ }
+return( td );
+}
+
+static void readcffprivate(FILE *ttf, struct topdicts *td) {
+ int ival, oval, sp, ret, i;
+ real stack[50];
+ int32 end = td->cff_start+td->private_offset+td->private_size;
+
+ fseek(ttf,td->cff_start+td->private_offset,SEEK_SET);
+
+ td->subrsoff = -1;
+ td->expansionfactor = .06;
+ td->bluefuzz = 1;
+ td->blueshift = 7;
+ td->bluescale = .039625;
+
+ while ( ftell(ttf)<end ) {
+ sp = 0;
+ while ( (ret=readcffthing(ttf,&ival,&stack[sp],&oval))!=3 && ftell(ttf)<end ) {
+ if ( ret==1 )
+ stack[sp]=ival;
+ if ( ret!=0 && sp<45 )
+ ++sp;
+ }
+ if ( ret==3 && oval==31 /* "T2" operator, can have 0 arguments */ ) {
+ skipcfft2thing(ttf);
+ } else if ( sp==0 && oval!=6 && oval!=7 && oval!=8 && oval!=9 && oval !=(12<<8)+12 && oval !=(12<<8)+13)
+ LogError( _("No argument to operator %d in private dict\n"), oval );
+ else if ( ret==3 ) switch( oval ) {
+ case 6:
+ for ( i=0; i<sp && i<14; ++i ) {
+ td->bluevalues[i] = stack[i];
+ if ( i!=0 )
+ td->bluevalues[i] += td->bluevalues[i-1];
+ }
+ break;
+ case 7:
+ for ( i=0; i<sp && i<10; ++i ) {
+ td->otherblues[i] = stack[i];
+ if ( i!=0 )
+ td->otherblues[i] += td->otherblues[i-1];
+ }
+ break;
+ case 8:
+ for ( i=0; i<sp && i<14; ++i ) {
+ td->familyblues[i] = stack[i];
+ if ( i!=0 )
+ td->familyblues[i] += td->familyblues[i-1];
+ }
+ break;
+ case 9:
+ for ( i=0; i<sp && i<10; ++i ) {
+ td->familyotherblues[i] = stack[i];
+ if ( i!=0 )
+ td->familyotherblues[i] += td->familyotherblues[i-1];
+ }
+ break;
+ case (12<<8)+9:
+ td->bluescale = stack[sp-1];
+ break;
+ case (12<<8)+10:
+ td->blueshift = stack[sp-1];
+ break;
+ case (12<<8)+11:
+ td->bluefuzz = stack[sp-1];
+ break;
+ case 10:
+ td->stdhw = stack[sp-1];
+ break;
+ case 11:
+ td->stdvw = stack[sp-1];
+ break;
+ case (12<<8)+12:
+ for ( i=0; i<sp && i<10; ++i ) {
+ td->stemsnaph[i] = stack[i];
+ if ( i!=0 )
+ td->stemsnaph[i] += td->stemsnaph[i-1];
+ }
+ break;
+ case (12<<8)+13:
+ for ( i=0; i<sp && i<10; ++i ) {
+ td->stemsnapv[i] = stack[i];
+ if ( i!=0 )
+ td->stemsnapv[i] += td->stemsnapv[i-1];
+ }
+ break;
+ case (12<<8)+14:
+ td->forcebold = stack[sp-1];
+ break;
+ case (12<<8)+15:
+ td->forceboldthreshold = stack[sp-1];
+ break;
+ case (12<<8)+16:
+ /* lenIV. -1 => unencrypted charstrings */
+ /* obsolete */
+ break;
+ case (12<<8)+17:
+ td->languagegroup = stack[sp-1];
+ break;
+ case (12<<8)+18:
+ td->expansionfactor = stack[sp-1];
+ break;
+ case (12<<8)+19:
+ td->initialRandomSeed = stack[sp-1];
+ break;
+ case 19:
+ td->subrsoff = stack[sp-1];
+ break;
+ case 20:
+ td->defaultwidthx = stack[sp-1];
+ break;
+ case 21:
+ td->nominalwidthx = stack[sp-1];
+ break;
+ default:
+ LogError(_("Unknown operator in %s: %x\n"), td->fontname, oval );
+ break;
+ }
+ }
+
+ if ( td->subrsoff!=-1 ) {
+ fseek(ttf,td->cff_start+td->private_offset+td->subrsoff,SEEK_SET);
+ readcffsubrs(ttf,&td->local_subrs);
+ }
+}
+
+static struct topdicts **readcfftopdicts(FILE *ttf, char **fontnames, int32 cff_start) {
+ uint16 count = getushort(ttf);
+ int offsize;
+ uint32 *offsets;
+ struct topdicts **dicts;
+ int i;
+
+ if ( count==0 )
+return( NULL );
+ offsets = galloc((count+1)*sizeof(uint32));
+ offsize = getc(ttf);
+ for ( i=0; i<=count; ++i )
+ offsets[i] = getoffset(ttf,offsize);
+ dicts = galloc((count+1)*sizeof(struct topdicts *));
+ for ( i=0; i<count; ++i ) {
+ dicts[i] = readcfftopdict(ttf,fontnames!=NULL?fontnames[i]:NULL,
+ offsets[i+1]-offsets[i]);
+ dicts[i]->cff_start = cff_start;
+ }
+ dicts[i] = NULL;
+ free(offsets);
+return( dicts );
+}
+
+static const char *getsid(int sid,char **strings,int scnt) {
+ if ( sid==-1 )
+return( NULL );
+ else if ( sid<nStdStrings )
+return( cffnames[sid] );
+ else if ( sid-nStdStrings>scnt ) {
+ LogError( _("Bad sid %d (must be less than %d)\n"), sid, scnt+nStdStrings );
+return( NULL );
+ } else
+return( strings[sid-nStdStrings]);
+}
+
+/* I really expect to deal with encodings in ttf cmap, but ocasionally we */
+/* get a bare cff */
+static void readcffenc(FILE *ttf,struct topdicts *dict,struct ttfinfo *info,
+ char **strings, int scnt) {
+ int format, cnt, i, j, pos, first, last, dupenc, sid;
+ extern char *AdobeStandardEncoding[], *AdobeExpertEncoding[];
+ const char *name;
+ EncMap *map;
+
+ if ( info->encoding_start!=0 ) /* Use the cmap instead */
+return;
+ if ( info->subfontcnt!=0 )
+return; /* Use cids instead */
+
+ for ( i=0; i<info->glyph_cnt; ++i ) {
+ if ( info->chars[i]->unicodeenc==-1 )
+ info->chars[i]->unicodeenc = UniFromName(info->chars[i]->name,ui_none,&custom);
+ }
+
+ map = EncMapNew(256,256,&custom);
+ if ( dict->encodingoff==0 || dict->encodingoff==1 ) {
+ /* Standard Encodings */
+ char **enc = dict->encodingoff==0 ? AdobeStandardEncoding : AdobeExpertEncoding;
+ map->enc = FindOrMakeEncoding( dict->encodingoff==0 ?
+ "AdobeStandard" : "Custom" );
+ if ( map->enc==NULL )
+ map->enc = &custom;
+ for ( i=0; i<info->glyph_cnt; ++i ) {
+ for ( pos=0; pos<256; ++pos )
+ if ( strcmp(info->chars[i]->name,enc[pos])==0 )
+ break;
+ if ( pos<256 )
+ map->map[pos] = i;
+ }
+ } else {
+ fseek(ttf,dict->cff_start+dict->encodingoff,SEEK_SET);
+ format = getc(ttf);
+ if ( (format&0x7f)==0 ) {
+ cnt = getc(ttf);
+ for ( i=1; i<=cnt && i<info->glyph_cnt; ++i )
+ map->map[getc(ttf)] = i;
+ } else if ( (format&0x7f)==1 ) {
+ cnt = getc(ttf);
+ pos = 0;
+ for ( i=0; i<cnt ; ++i ) {
+ first = getc(ttf);
+ last = first + getc(ttf)-1;
+ while ( first<=last && first<256 ) {
+ if ( pos<info->glyph_cnt )
+ map->map[first] = pos;
+ ++pos;
+ ++first;
+ }
+ }
+ } else
+ LogError( _("Unexpected encoding format in cff: %d\n"), format );
+ if ( format&0x80 ) {
+ cnt = getc(ttf);
+ for ( i=0; i<cnt; ++i ) {
+ dupenc = getc(ttf);
+ sid = getushort(ttf);
+ name = getsid(sid,strings,scnt);
+ if ( name==NULL ) /* Table is erroneous */
+ break;
+ for ( j=0; j<info->glyph_cnt; ++j )
+ if ( strcmp(name,info->chars[j]->name)==0 )
+ break;
+ if ( j!=info->glyph_cnt )
+ map->map[dupenc] = j;
+ }
+ }
+ }
+ info->map = map;
+}
+
+static void readcffset(FILE *ttf,struct topdicts *dict) {
+ int len = dict->glyphs.cnt;
+ int i;
+ int format, cnt, j, first;
+
+ i = 0;
+ if ( dict->charsetoff==0 ) {
+ /* ISO Adobe charset */
+ dict->charset = galloc(len*sizeof(uint16));
+ for ( i=0; i<len && i<=228; ++i )
+ dict->charset[i] = i;
+ } else if ( dict->charsetoff==1 ) {
+ /* Expert charset */
+ dict->charset = galloc((len<162?162:len)*sizeof(uint16));
+ dict->charset[0] = 0; /* .notdef */
+ dict->charset[1] = 1;
+ for ( i=2; i<len && i<=238-227; ++i )
+ dict->charset[i] = i+227;
+ dict->charset[12] = 13;
+ dict->charset[13] = 14;
+ dict->charset[14] = 15;
+ dict->charset[15] = 99;
+ for ( i=16; i<len && i<=248-223; ++i )
+ dict->charset[i] = i+223;
+ dict->charset[25] = 27;
+ dict->charset[26] = 28;
+ for ( i=27; i<len && i<=266-222; ++i )
+ dict->charset[i] = i+222;
+ dict->charset[44] = 109;
+ dict->charset[45] = 110;
+ for ( i=46; i<len && i<=318-221; ++i )
+ dict->charset[i] = i+221;
+ dict->charset[96] = 158;
+ dict->charset[97] = 155;
+ dict->charset[98] = 163;
+ for ( i=99; i<len && i<=326-220; ++i )
+ dict->charset[i] = i+220;
+ dict->charset[107] = 150;
+ dict->charset[108] = 164;
+ dict->charset[109] = 169;
+ for ( i=110; i<len && i<=378-217; ++i )
+ dict->charset[i] = i+217;
+ } else if ( dict->charsetoff==2 ) {
+ /* Expert subset charset */
+ dict->charset = galloc((len<130?130:len)*sizeof(uint16));
+ dict->charset[0] = 0; /* .notdef */
+ dict->charset[1] = 1;
+ for ( i=2; i<len && i<=238-227; ++i )
+ dict->charset[i] = i+227;
+ dict->charset[12] = 13;
+ dict->charset[13] = 14;
+ dict->charset[14] = 15;
+ dict->charset[15] = 99;
+ for ( i=16; i<len && i<=248-223; ++i )
+ dict->charset[i] = i+223;
+ dict->charset[25] = 27;
+ dict->charset[26] = 28;
+ for ( i=27; i<len && i<=266-222; ++i )
+ dict->charset[i] = i+222;
+ dict->charset[44] = 109;
+ dict->charset[45] = 110;
+ for ( i=46; i<len && i<=272-221; ++i )
+ dict->charset[i] = i+221;
+ dict->charset[51] = 300;
+ dict->charset[52] = 301;
+ dict->charset[53] = 302;
+ dict->charset[54] = 305;
+ dict->charset[55] = 314;
+ dict->charset[56] = 315;
+ dict->charset[57] = 158;
+ dict->charset[58] = 155;
+ dict->charset[59] = 163;
+ for ( i=60; i<len && i<=326-260; ++i )
+ dict->charset[i] = i+260;
+ dict->charset[67] = 150;
+ dict->charset[68] = 164;
+ dict->charset[69] = 169;
+ for ( i=110; i<len && i<=346-217; ++i )
+ dict->charset[i] = i+217;
+ } else {
+ dict->charset = galloc(len*sizeof(uint16));
+ dict->charset[0] = 0; /* .notdef */
+ fseek(ttf,dict->cff_start+dict->charsetoff,SEEK_SET);
+ format = getc(ttf);
+ if ( format==0 ) {
+ for ( i=1; i<len; ++i )
+ dict->charset[i] = getushort(ttf);
+ } else if ( format==1 ) {
+ for ( i = 1; i<len; ) {
+ first = dict->charset[i++] = getushort(ttf);
+ cnt = getc(ttf);
+ for ( j=0; j<cnt; ++j )
+ dict->charset[i++] = ++first;
+ }
+ } else if ( format==2 ) {
+ for ( i = 1; i<len; ) {
+ first = dict->charset[i++] = getushort(ttf);
+ cnt = getushort(ttf);
+ for ( j=0; j<cnt; ++j )
+ dict->charset[i++] = ++first;
+ }
+ } else
+ LogError( _("Unexpected charset format in cff: %d\n"), format );
+ }
+ while ( i<len ) dict->charset[i++] = 0;
+}
+
+static uint8 *readfdselect(FILE *ttf,int numglyphs) {
+ uint8 *fdselect = gcalloc(numglyphs,sizeof(uint8));
+ int i, j, format, nr, first, end, fd;
+
+ format = getc(ttf);
+ if ( format==0 ) {
+ for ( i=0; i<numglyphs; ++i )
+ fdselect[i] = getc(ttf);
+ } else if ( format==3 ) {
+ nr = getushort(ttf);
+ first = getushort(ttf);
+ for ( i=0; i<nr; ++i ) {
+ fd = getc(ttf);
+ end = getushort(ttf);
+ for ( j=first; j<end; ++j ) {
+ if ( j>=numglyphs )
+ LogError( _("Bad fdselect\n") );
+ else
+ fdselect[j] = fd;
+ }
+ first = end;
+ }
+ } else {
+ LogError( _("Didn't understand format for fdselect %d\n"), format );
+ }
+return( fdselect );
+}
+
+
+static char *intarray2str(int *array, int size) {
+ int i,j;
+ char *pt, *ret;
+
+ for ( i=size-1; i>=0 && array[i]==0; --i );
+ if ( i==-1 )
+return( NULL );
+ ret = pt = galloc((i+1)*12+12);
+ *pt++ = '[';
+ for ( j=0; j<=i; ++j ) {
+ sprintf( pt, "%d ", array[j]);
+ pt += strlen(pt);
+ }
+ pt[-1]=']';
+return( ret );
+}
+
+static char *realarray2str(real *array, int size) {
+ int i,j;
+ char *pt, *ret;
+
+ for ( i=size-1; i>=0 && array[i]==0; --i );
+ if ( i==-1 )
+return( NULL );
+ ret = pt = galloc((i+1)*20+12);
+ *pt++ = '[';
+ for ( j=0; j<=i; ++j ) {
+ sprintf( pt, "%g ", (double) array[j]);
+ pt += strlen(pt);
+ }
+ pt[-1]=']';
+return( ret );
+}
+
+static void privateadd(struct psdict *private,char *key,char *value) {
+ if ( value==NULL )
+return;
+ private->keys[private->next] = copy(key);
+ private->values[private->next++] = value;
+}
+
+static void privateaddint(struct psdict *private,char *key,int val) {
+ char buf[10];
+ if ( val==0 )
+return;
+ sprintf( buf,"%d", val );
+ privateadd(private,key,copy(buf));
+}
+
+static void privateaddintarray(struct psdict *private,char *key,int val) {
+ char buf[10];
+ if ( val==0 )
+return;
+ sprintf( buf,"[%d]", val );
+ privateadd(private,key,copy(buf));
+}
+
+static void privateaddreal(struct psdict *private,char *key,double val) {
+ char buf[10];
+ if ( val==0 )
+return;
+ sprintf( buf,"%g", val );
+ privateadd(private,key,copy(buf));
+}
+
+static void cffprivatefillup(struct psdict *private, struct topdicts *dict) {
+ private->cnt = 14;
+ private->keys = galloc(14*sizeof(char *));
+ private->values = galloc(14*sizeof(char *));
+ privateadd(private,"BlueValues",
+ realarray2str(dict->bluevalues,sizeof(dict->bluevalues)/sizeof(dict->bluevalues[0])));
+ privateadd(private,"OtherBlues",
+ realarray2str(dict->otherblues,sizeof(dict->otherblues)/sizeof(dict->otherblues[0])));
+ privateadd(private,"FamilyBlues",
+ realarray2str(dict->familyblues,sizeof(dict->familyblues)/sizeof(dict->familyblues[0])));
+ privateadd(private,"FamilyOtherBlues",
+ realarray2str(dict->familyotherblues,sizeof(dict->familyotherblues)/sizeof(dict->familyotherblues[0])));
+ privateaddreal(private,"BlueScale",dict->bluescale);
+ privateaddreal(private,"BlueShift",dict->blueshift);
+ privateaddreal(private,"BlueFuzz",dict->bluefuzz);
+ privateaddintarray(private,"StdHW",dict->stdhw);
+ privateaddintarray(private,"StdVW",dict->stdvw);
+ privateadd(private,"SnapStemH",
+ realarray2str(dict->stemsnaph,sizeof(dict->stemsnaph)/sizeof(dict->stemsnaph[0])));
+ privateadd(private,"SnapStemV",
+ realarray2str(dict->stemsnapv,sizeof(dict->stemsnapv)/sizeof(dict->stemsnapv[0])));
+ if ( dict->forcebold )
+ privateadd(private,"ForceBold",copy("true"));
+ if ( dict->forceboldthreshold!=0 )
+ privateaddreal(private,"ForceBoldThreshold",dict->forceboldthreshold);
+ privateaddint(private,"LanguageGroup",dict->languagegroup);
+ privateaddreal(private,"ExpansionFactor",dict->expansionfactor);
+}
+
+static SplineFont *cffsffillup(struct topdicts *subdict, char **strings,
+ int scnt) {
+ SplineFont *sf = SplineFontEmpty();
+ int emsize;
+ static int nameless;
+
+ sf->fontname = utf8_verify_copy(getsid(subdict->sid_fontname,strings,scnt));
+ if ( sf->fontname==NULL ) {
+ char buffer[40];
+ sprintf(buffer,"UntitledSubFont_%d", ++nameless );
+ sf->fontname = copy(buffer);
+ }
+
+ if ( subdict->fontmatrix[0]==0 )
+ emsize = 1000;
+ else
+ emsize = rint( 1/subdict->fontmatrix[0] );
+ sf->ascent = .8*emsize;
+ sf->descent = emsize - sf->ascent;
+ if ( subdict->copyright!=-1 )
+ sf->copyright = utf8_verify_copy(getsid(subdict->copyright,strings,scnt));
+ else
+ sf->copyright = utf8_verify_copy(getsid(subdict->notice,strings,scnt));
+ sf->familyname = utf8_verify_copy(getsid(subdict->familyname,strings,scnt));
+ sf->fullname = utf8_verify_copy(getsid(subdict->fullname,strings,scnt));
+ sf->weight = utf8_verify_copy(getsid(subdict->weight,strings,scnt));
+ sf->version = utf8_verify_copy(getsid(subdict->version,strings,scnt));
+ sf->italicangle = subdict->italicangle;
+ sf->upos = subdict->underlinepos;
+ sf->uwidth = subdict->underlinewidth;
+ sf->xuid = intarray2str(subdict->xuid,sizeof(subdict->xuid)/sizeof(subdict->xuid[0]));
+ sf->uniqueid = subdict->uniqueid;
+ sf->strokewidth = subdict->strokewidth;
+ sf->strokedfont = subdict->painttype==2;
+
+ if ( subdict->private_size>0 ) {
+ sf->private = gcalloc(1,sizeof(struct psdict));
+ cffprivatefillup(sf->private,subdict);
+ }
+return( sf );
+}
+
+static void cffinfofillup(struct ttfinfo *info, struct topdicts *dict,
+ char **strings, int scnt ) {
+
+ info->glyph_cnt = dict->glyphs.cnt;
+ if ( info->glyph_cnt<0 ) info->glyph_cnt = 0;
+
+ if ( dict->fontmatrix[0]==0 )
+ info->emsize = 1000;
+ else
+ info->emsize = rint( 1/dict->fontmatrix[0] );
+#if 1
+ info->ascent = .8*info->emsize;
+#else
+ info->ascent = dict->fontbb[3]*info->emsize/(dict->fontbb[3]-dict->fontbb[1]);
+#endif
+ info->descent = info->emsize - info->ascent;
+ if ( dict->copyright!=-1 || dict->notice!=-1 )
+ free( info->copyright );
+ if ( dict->copyright!=-1 )
+ info->copyright = utf8_verify_copy(getsid(dict->copyright,strings,scnt));
+ else if ( dict->notice!=-1 )
+ info->copyright = utf8_verify_copy(getsid(dict->notice,strings,scnt));
+ if ( dict->familyname!=-1 ) {
+ free(info->familyname);
+ info->familyname = utf8_verify_copy(getsid(dict->familyname,strings,scnt));
+ }
+ if ( dict->fullname!=-1 ) {
+ free(info->fullname);
+ info->fullname = utf8_verify_copy(getsid(dict->fullname,strings,scnt));
+ }
+ if ( dict->weight!=-1 ) {
+ free(info->weight);
+ info->weight = utf8_verify_copy(getsid(dict->weight,strings,scnt));
+ }
+ if ( dict->version!=-1 ) {
+ free(info->version);
+ info->version = utf8_verify_copy(getsid(dict->version,strings,scnt));
+ }
+ if ( dict->fontname!=NULL ) {
+ free(info->fontname);
+ info->fontname = utf8_verify_copy(dict->fontname);
+ }
+ info->italicAngle = dict->italicangle;
+ info->upos = dict->underlinepos;
+ info->uwidth = dict->underlinewidth;
+ info->xuid = intarray2str(dict->xuid,sizeof(dict->xuid)/sizeof(dict->xuid[0]));
+ info->uniqueid = dict->uniqueid;
+ info->strokewidth = dict->strokewidth;
+ info->strokedfont = dict->painttype==2;
+
+ if ( dict->private_size>0 ) {
+ info->private = gcalloc(1,sizeof(struct psdict));
+ cffprivatefillup(info->private,dict);
+ }
+ if ( dict->ros_registry!=-1 ) {
+ info->cidregistry = copy(getsid(dict->ros_registry,strings,scnt));
+ info->ordering = copy(getsid(dict->ros_ordering,strings,scnt));
+ info->supplement = dict->ros_supplement;
+ info->cidfontversion = dict->cidfontversion;
+ }
+}
+
+static void cfffigure(struct ttfinfo *info, struct topdicts *dict,
+ char **strings, int scnt, struct pschars *gsubrs) {
+ int i, cstype;
+ struct pschars *subrs;
+ struct pscontext pscontext;
+#ifdef LUA_FF_LIB
+ DBounds bb;
+#endif
+ memset(&pscontext,0,sizeof(pscontext));
+
+ cffinfofillup(info, dict, strings, scnt );
+
+/* The format allows for some dicts that are type1 strings and others that */
+/* are type2s. Which means that the global subrs will have a different bias */
+/* as we flip from font to font. So we can't set the bias when we read in */
+/* the subrs but must wait until we know which font we're working on. */
+ cstype = dict->charstringtype;
+ pscontext.is_type2 = cstype-1;
+ pscontext.painttype = dict->painttype;
+ gsubrs->bias = cstype==1 ? 0 :
+ gsubrs->cnt < 1240 ? 107 :
+ gsubrs->cnt <33900 ? 1131 : 32768;
+ subrs = &dict->local_subrs;
+ subrs->bias = cstype==1 ? 0 :
+ subrs->cnt < 1240 ? 107 :
+ subrs->cnt <33900 ? 1131 : 32768;
+
+ info->chars = gcalloc(info->glyph_cnt,sizeof(SplineChar *));
+ for ( i=0; i<info->glyph_cnt; ++i ) {
+ info->chars[i] = PSCharStringToSplines(
+ dict->glyphs.values[i], dict->glyphs.lens[i],&pscontext,
+ subrs,gsubrs,getsid(dict->charset[i],strings,scnt));
+#ifdef LUA_FF_LIB
+ SplineCharFindBounds(info->chars[i],&bb);
+ info->chars[i]->xmin = bb.minx;
+ info->chars[i]->ymin = bb.miny;
+ info->chars[i]->xmax = bb.maxx;
+ info->chars[i]->ymax = bb.maxy;
+#endif
+ info->chars[i]->vwidth = info->emsize;
+ if ( cstype==2 ) {
+ if ( info->chars[i]->width == (int16) 0x8000 )
+ info->chars[i]->width = dict->defaultwidthx;
+ else
+ info->chars[i]->width += dict->nominalwidthx;
+ }
+ }
+ /* Need to do a reference fixup here !!!!! just in case some idiot */
+ /* used type1 char strings -- or used the depreciated meaning of */
+ /* endchar (==seac) */
+}
+
+static void cidfigure(struct ttfinfo *info, struct topdicts *dict,
+ char **strings, int scnt, struct pschars *gsubrs, struct topdicts **subdicts,
+ uint8 *fdselect) {
+ int i, j, cstype, uni, cid;
+ struct pschars *subrs;
+ SplineFont *sf;
+ struct cidmap *map;
+ char buffer[100];
+ struct pscontext pscontext;
+#ifdef LUA_FF_LIB
+ DBounds bb;
+#endif
+ EncMap *encmap = NULL;
+
+ memset(&pscontext,0,sizeof(pscontext));
+
+ cffinfofillup(info, dict, strings, scnt );
+
+ /* We'll set the encmap later */
+ /*info->map = encmap = EncMapNew(info->glyph_cnt,info->glyph_cnt,&custom);*/
+
+ for ( j=0; subdicts[j]!=NULL; ++j );
+ info->subfontcnt = j;
+ info->subfonts = gcalloc(j+1,sizeof(SplineFont *));
+ for ( j=0; subdicts[j]!=NULL; ++j ) {
+ info->subfonts[j] = cffsffillup(subdicts[j],strings,scnt);
+ info->subfonts[j]->map = encmap;
+ }
+ for ( i=0; i<info->glyph_cnt; ++i ) {
+ sf = info->subfonts[ fdselect[i] ];
+ cid = dict->charset[i];
+ if ( cid>=sf->glyphcnt ) sf->glyphcnt = sf->glyphmax = cid+1;
+ /*if ( cid>=encmap->enccount ) encmap->enccount = cid+1;*/
+ }
+ for ( j=0; subdicts[j]!=NULL; ++j )
+ info->subfonts[j]->glyphs = gcalloc(info->subfonts[j]->glyphcnt,sizeof(SplineChar *));
+ /*encmap->encmax = encmap->enccount;*/
+ /*encmap->map = galloc(encmap->enccount*sizeof(int));*/
+ /*memset(encmap->map,-1,encmap->enccount*sizeof(int));*/
+
+ info->chars = gcalloc(info->glyph_cnt,sizeof(SplineChar *));
+
+ /* info->chars provides access to the chars ordered by glyph, which the */
+ /* ttf routines care about */
+ /* sf->glyphs provides access to the chars ordered by CID. Not sure what */
+ /* would happen to a kern from one font to another... */
+
+ map = FindCidMap(info->cidregistry,info->ordering,info->supplement,NULL);
+
+ for ( i=0; i<info->glyph_cnt; ++i ) {
+ j = fdselect[i];
+ sf = info->subfonts[ j ];
+/* The format allows for some dicts that are type1 strings and others that */
+/* are type2s. Which means that the global subrs will have a different bias */
+/* as we flip from font to font. So we can't set the bias when we read in */
+/* the subrs but must wait until we know which font we're working on. */
+ cstype = subdicts[j]->charstringtype;
+ pscontext.is_type2 = cstype-1;
+ pscontext.painttype = subdicts[j]->painttype;
+ gsubrs->bias = cstype==1 ? 0 :
+ gsubrs->cnt < 1240 ? 107 :
+ gsubrs->cnt <33900 ? 1131 : 32768;
+ subrs = &subdicts[j]->local_subrs;
+ subrs->bias = cstype==1 ? 0 :
+ subrs->cnt < 1240 ? 107 :
+ subrs->cnt <33900 ? 1131 : 32768;
+
+ cid = dict->charset[i];
+ /*encmap->map[cid] = cid;*/
+ uni = CID2NameUni(map,cid,buffer,sizeof(buffer));
+ info->chars[i] = PSCharStringToSplines(
+ dict->glyphs.values[i], dict->glyphs.lens[i],&pscontext,
+ subrs,gsubrs,buffer);
+
+#ifdef LUA_FF_LIB
+ SplineCharFindBounds(info->chars[i],&bb);
+ info->chars[i]->xmin = bb.minx;
+ info->chars[i]->ymin = bb.miny;
+ info->chars[i]->xmax = bb.maxx;
+ info->chars[i]->ymax = bb.maxy;
+#endif
+
+ info->chars[i]->vwidth = sf->ascent+sf->descent;
+ info->chars[i]->unicodeenc = uni;
+ sf->glyphs[cid] = info->chars[i];
+ sf->glyphs[cid]->parent = sf;
+ sf->glyphs[cid]->orig_pos = cid; /* Bug! should be i, but I assume sf->chars[orig_pos]->orig_pos==orig_pos */
+ if ( sf->glyphs[cid]->layers[ly_fore].refs!=NULL )
+ IError( "Reference found in CID font. Can't fix it up");
+ if ( cstype==2 ) {
+ if ( sf->glyphs[cid]->width == (int16) 0x8000 )
+ sf->glyphs[cid]->width = subdicts[j]->defaultwidthx;
+ else
+ sf->glyphs[cid]->width += subdicts[j]->nominalwidthx;
+ }
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_next();
+#endif
+ }
+ /* No need to do a reference fixup here-- the chars aren't associated */
+ /* with any encoding as is required for seac */
+}
+
+static int readcffglyphs(FILE *ttf,struct ttfinfo *info) {
+ int offsize;
+ int hdrsize;
+ char **fontnames, **strings;
+ struct topdicts **dicts, **subdicts;
+ int i, j, which;
+ struct pschars gsubs;
+ uint8 *fdselect;
+ int scnt;
+
+ fseek(ttf,info->cff_start,SEEK_SET);
+ if ( getc(ttf)!='\1' ) { /* Major version */
+ LogError( _("CFF version mismatch\n" ));
+return( 0 );
+ }
+ getc(ttf); /* Minor version */
+ hdrsize = getc(ttf);
+ offsize = getc(ttf);
+ if ( hdrsize!=4 )
+ fseek(ttf,info->cff_start+hdrsize,SEEK_SET);
+ fontnames = readcfffontnames(ttf,NULL);
+ which = 0;
+ if ( fontnames[1]!=NULL ) { /* More than one? Can that even happen in OpenType? */
+ which = PickCFFFont(fontnames);
+ if ( which==-1 ) {
+ for ( i=0; fontnames[i]!=NULL; ++i )
+ free(fontnames[i]);
+ free(fontnames);
+return( 0 );
+ }
+ }
+ dicts = readcfftopdicts(ttf,fontnames,info->cff_start);
+ /* String index is just the same as fontname index */
+ strings = readcfffontnames(ttf,&scnt);
+ readcffsubrs(ttf,&gsubs );
+ /* Can be many fonts here. Only decompose the one */
+ if ( dicts[which]->charstringsoff!=-1 ) {
+ fseek(ttf,info->cff_start+dicts[which]->charstringsoff,SEEK_SET);
+ readcffsubrs(ttf,&dicts[which]->glyphs);
+ }
+ if ( dicts[which]->private_offset!=-1 )
+ readcffprivate(ttf,dicts[which]);
+ if ( dicts[which]->charsetoff!=-1 )
+ readcffset(ttf,dicts[which]);
+ if ( dicts[which]->fdarrayoff==-1 )
+ cfffigure(info,dicts[which],strings,scnt,&gsubs);
+ else {
+ fseek(ttf,info->cff_start+dicts[which]->fdarrayoff,SEEK_SET);
+ subdicts = readcfftopdicts(ttf,NULL,info->cff_start);
+ fseek(ttf,info->cff_start+dicts[which]->fdselectoff,SEEK_SET);
+ fdselect = readfdselect(ttf,dicts[which]->glyphs.cnt);
+ for ( j=0; subdicts[j]!=NULL; ++j ) {
+ if ( subdicts[j]->private_offset!=-1 )
+ readcffprivate(ttf,subdicts[j]);
+ if ( subdicts[j]->charsetoff!=-1 )
+ readcffset(ttf,subdicts[j]);
+ }
+ cidfigure(info,dicts[which],strings,scnt,&gsubs,subdicts,fdselect);
+ for ( j=0; subdicts[j]!=NULL; ++j )
+ TopDictFree(subdicts[j]);
+ free(subdicts); free(fdselect);
+ }
+ if ( dicts[which]->encodingoff!=-1 )
+ readcffenc(ttf,dicts[which],info,strings,scnt);
+
+ if ( dicts[which]->fdarrayoff==-1 ) {
+ for ( i=0; i<info->glyph_cnt ; ++i )
+ if ( info->chars[i]!=NULL )
+ info->chars[i]->orig_pos = i;
+ }
+
+ if ( info->to_order2 ) {
+ for ( i=0; i<info->glyph_cnt; ++i )
+ SCConvertToOrder2(info->chars[i]);
+ }
+
+ for ( i=0; fontnames[i]!=NULL && i<1; ++i ) {
+ free(fontnames[i]);
+ TopDictFree(dicts[i]);
+ }
+ free(fontnames); free(dicts);
+ if ( strings!=NULL ) {
+ for ( i=0; strings[i]!=NULL; ++i )
+ free(strings[i]);
+ free(strings);
+ }
+ for ( i=0; i<gsubs.cnt; ++i )
+ free(gsubs.values[i]);
+ free(gsubs.values); free(gsubs.lens);
+
+return( 1 );
+}
+
+static int readtyp1glyphs(FILE *ttf,struct ttfinfo *info) {
+ FontDict *fd;
+ FILE *tmp;
+ int i;
+
+ fseek(ttf,info->typ1_start,SEEK_SET);
+ tmp = tmpfile();
+ for ( i=0; i<info->typ1_length; ++i )
+ putc(getc(ttf),tmp);
+ rewind(tmp);
+ fd = _ReadPSFont(tmp);
+ fclose(tmp);
+ if ( fd!=NULL ) {
+ SplineFont *sf = SplineFontFromPSFont(fd);
+ PSFontFree(fd);
+ info->chars = sf->glyphs;
+ info->glyph_cnt = sf->glyphcnt;
+ info->emsize = (sf->ascent+sf->descent);
+ info->ascent = sf->ascent;
+ info->descent = sf->descent;
+ sf->glyphs = NULL;
+ sf->glyphcnt = 0;
+ SplineFontFree(sf);
+return( true );
+ }
+return( false );
+}
+
+static void readttfwidths(FILE *ttf,struct ttfinfo *info) {
+ int i,j;
+ int lastwidth = info->emsize;
+ /* I'm not interested in the lsb, I'm not sure what it means if it differs*/
+ /* from that is specified in the outline. Do we move the outline? */
+ int check_width_consistency = info->cff_start!=0 && info->glyph_start==0;
+ SplineChar *sc;
+
+ fseek(ttf,info->hmetrics_start,SEEK_SET);
+ for ( i=0; i<info->width_cnt && i<info->glyph_cnt; ++i ) {
+ lastwidth = getushort(ttf);
+ if ( (sc = info->chars[i])!=NULL ) { /* can happen in ttc files */
+ if ( check_width_consistency && sc->width!=lastwidth ) {
+ if ( info->fontname!=NULL && sc->name!=NULL )
+ LogError("In %s, in glyph %s, 'CFF ' advance width (%d) and\n 'hmtx' width (%d) do not match. (Subsequent mismatches will not be reported)\n",
+ info->fontname, sc->name, sc->width, lastwidth );
+ else
+ LogError("In GID %d, 'CFF ' advance width (%d) and 'hmtx' width (%d) do not match.\n (Subsequent mismatches will not be reported)\n",
+ i, sc->width, lastwidth );
+ check_width_consistency = false;
+ }
+ sc->width = lastwidth;
+ sc->widthset = true;
+ }
+ /* lsb = */ getushort(ttf);
+ }
+ if ( i==0 )
+ LogError( _("Invalid ttf hmtx table (or hhea), numOfLongMetrics is 0\n") );
+
+ for ( j=i; j<info->glyph_cnt; ++j ) {
+ if ( info->chars[j]!=NULL ) { /* In a ttc file we may skip some */
+ info->chars[j]->width = lastwidth;
+ info->chars[j]->widthset = true;
+ }
+ }
+}
+
+static void dummywidthsfromstrike(FILE *ttf,struct ttfinfo *info) {
+ BDFFont *bdf;
+ int i, cnt;
+ double scaled_sum;
+
+ if ( info->bitmaps==NULL )
+return;
+#if 0
+ for ( bdf=info->bitmaps; bdf->next!=NULL; bdf=bdf->next );
+ for ( i=0; i<bdf->glyphcnt; ++i ) if ( bdf->glyphs[i]!=NULL ) {
+ bdf->glyphs[i]->sc->width = info->emsize*bdf->glyphs[i]->width/bdf->pixelsize;
+ bdf->glyphs[i]->sc->widthset = true;
+ }
+#else
+ for ( i=0; i<info->glyph_cnt; ++i ) if ( info->chars[i]!=NULL ) {
+ cnt = 0; scaled_sum = 0;
+ for ( bdf=info->bitmaps; bdf->next!=NULL; bdf=bdf->next ) {
+ if ( i<bdf->glyphcnt && bdf->glyphs[i]!=NULL ) {
+ scaled_sum += ((double) (info->emsize*bdf->glyphs[i]->width))/bdf->pixelsize;
+ ++cnt;
+ }
+ }
+ if ( cnt!=0 ) {
+ info->chars[i]->width = scaled_sum/cnt;
+ info->chars[i]->widthset = true;
+ }
+ }
+#endif
+}
+
+static void readttfvwidths(FILE *ttf,struct ttfinfo *info) {
+ int i,j;
+ int lastvwidth = info->emsize, vwidth_cnt, tsb, cnt=0;
+ int32 voff=0;
+
+ fseek(ttf,info->vhea_start+4+4,SEEK_SET); /* skip over the version number & typo right/left */
+ info->pfminfo.vlinegap = getushort(ttf);
+ info->pfminfo.vheadset = true;
+
+ for ( i=0; i<12; ++i )
+ getushort(ttf);
+ vwidth_cnt = getushort(ttf);
+
+ fseek(ttf,info->vmetrics_start,SEEK_SET);
+ for ( i=0; i<vwidth_cnt && i<info->glyph_cnt; ++i ) {
+ lastvwidth = getushort(ttf);
+ tsb = getushort(ttf);
+ if ( info->chars[i]!=NULL ) { /* can happen in ttc files */
+ info->chars[i]->vwidth = lastvwidth;
+ if ( info->cff_start==0 ) {
+ voff += tsb + info->chars[i]->lsidebearing /* actually maxy */;
+ ++cnt;
+ }
+ }
+ }
+ if ( i==0 )
+ LogError( _("Invalid ttf vmtx table (or vhea), numOfLongVerMetrics is 0\n") );
+
+ for ( j=i; j<info->glyph_cnt; ++j ) {
+ if ( info->chars[j]!=NULL ) /* In a ttc file we may skip some */
+ info->chars[j]->vwidth = lastvwidth;
+ }
+
+ /* for truetype fonts the vertical offset is found by adding the ymax of a */
+ /* character to the top side bearing. I set the font wide value to the */
+ /* average of them all */
+ /* But opentype doesn't give us the ymax easily, and rather than compute */
+ /* the bounding box I'll just punt and pick a reasonable value */
+ /* Of course I hope it will be over riden by the VORG table */
+ if ( cnt!=0 )
+ info->vertical_origin = (voff+cnt/2)/cnt;
+ if ( info->vertical_origin==0 )
+ info->vertical_origin = info->ascent;
+ if ( info->vorg_start!=0 ) {
+ fseek(ttf,info->vorg_start+4,SEEK_SET);
+ info->vertical_origin = (short) getushort(ttf);
+ }
+}
+
+static int modenc(int enc,int modtype) {
+return( enc );
+}
+
+static int umodenc(int enc,int modtype) {
+ if ( modtype==-1 )
+return( -1 );
+ if ( modtype<=1 /* Unicode */ ) {
+ /* No conversion */;
+ } else if ( modtype==2 /* SJIS */ ) {
+ if ( enc<=127 ) {
+ /* Latin */
+ if ( enc=='\\' ) enc = 0xa5; /* Yen */
+ } else if ( enc>=161 && enc<=223 ) {
+ /* Katakana */
+ enc = unicode_from_jis201[enc];
+ } else {
+ int ch1 = enc>>8, ch2 = enc&0xff;
+ if ( ch1 >= 129 && ch1<= 159 )
+ ch1 -= 112;
+ else
+ ch1 -= 176;
+ ch1 <<= 1;
+ if ( ch2>=159 )
+ ch2-= 126;
+ else if ( ch2>127 ) {
+ --ch1;
+ ch2 -= 32;
+ } else {
+ --ch1;
+ ch2 -= 31;
+ }
+ enc = unicode_from_jis208[(ch1-0x21)*94+(ch2-0x21)];
+ }
+ } else if ( modtype==3 /* GB2312 offset by 0x8080, parse just like wansung */ ) {
+ if ( enc>0xa1a1 ) {
+ enc -= 0xa1a1;
+ enc = (enc>>8)*94 + (enc&0xff);
+ enc = unicode_from_gb2312[enc];
+ if ( enc==0 ) enc = -1;
+ } else if ( enc>0x100 )
+ enc = -1;
+ } else if ( modtype==4 /* BIG5 */ ) { /* old ms docs say big5 is modtype==3, but new ones say 4 */
+ if ( enc>0x8100 )
+ enc = unicode_from_big5hkscs[enc-0x8100];
+ else if ( enc>0x100 )
+ enc = -1;
+ } else if ( modtype==5 /* Wansung == KSC 5601-1987, I hope */ ) {
+ if ( enc>0xa1a1 ) {
+ enc -= 0xa1a1;
+ enc = (enc>>8)*94 + (enc&0xff);
+ enc = unicode_from_ksc5601[enc];
+ if ( enc==0 ) enc = -1;
+ } else if ( enc>0x100 )
+ enc = -1;
+ } else if ( modtype==6 /* Johab */ ) {
+ if ( enc>0x8400 )
+ enc = unicode_from_johab[enc-0x8400];
+ else if ( enc>0x100 )
+ enc = -1;
+ }
+ if ( enc==0 )
+ enc = -1;
+return( enc );
+}
+
+struct cmap_encs {
+ int platform;
+ int specific;
+ int offset;
+ int lang;
+ int format;
+ Encoding *enc;
+};
+
+static int SubtableIsntSupported(FILE *ttf,uint32 offset,struct cmap_encs *cmap_enc) {
+ uint32 here = ftell(ttf);
+ int format, len, ret=false;
+
+ fseek(ttf,offset,SEEK_SET);
+
+ cmap_enc->format = format = getushort(ttf);
+ if ( format<0 || (format&1) || format>12 ) {
+ LogError( _("Encoding subtable for platform=%d, specific=%d has an unsupported format %d.\n"),
+ cmap_enc->platform, cmap_enc->specific, format );
+ ret = true;
+ }
+
+ if ( format!=12 && format!=10 && format!=8 ) {
+ len = getushort(ttf);
+ cmap_enc->lang = getushort(ttf);
+ } else {
+ /* padding */ getushort(ttf);
+ len = getlong(ttf);
+ cmap_enc->lang = getlong(ttf);
+ }
+ if ( len==0 ) {
+ LogError( _("Encoding subtable for platform=%d, specific=%d has a 0 length subtable.\n"),
+ cmap_enc->platform, cmap_enc->specific );
+ ret = true;
+ }
+ fseek(ttf,here,SEEK_SET);
+return( ret );
+}
+
+static enum uni_interp amscheck(struct ttfinfo *info, EncMap *map) {
+ int cnt = 0;
+ /* Try to guess if the font uses the AMS math PUA assignments */
+
+ if ( map==NULL )
+return( ui_none );
+
+ if ( 0xe668<map->enccount && map->map[0xe668]!=-1 &&
+ info->chars[map->map[0xe668]]->unicodeenc=='b' )
+ ++cnt;
+ if ( 0xe3c8<map->enccount && map->map[0xe626]!=-1 &&
+ info->chars[map->map[0xe626]]->unicodeenc==0xe626 )
+ ++cnt;
+ if ( 0xe3c8<map->enccount && map->map[0xe3c8]!=-1 &&
+ info->chars[map->map[0xe3c8]]->unicodeenc==0x29e1 )
+ ++cnt;
+ if ( 0x2A7C<map->enccount && map->map[0x2A7C]!=-1 &&
+ info->chars[map->map[0x2A7C]]->unicodeenc==0xE32A )
+ ++cnt;
+ if ( 0x2920<map->enccount && map->map[0x2920]!=-1 &&
+ info->chars[map->map[0x2920]]->unicodeenc==0xE221 )
+ ++cnt;
+return( cnt>=2 ? ui_ams : ui_none );
+}
+
+static int PickCMap(struct cmap_encs *cmap_encs,int enccnt,int def) {
+ char buffer[500];
+ char **choices, *encname;
+ int i, ret;
+ static char *macscripts[]= { N_("Script|Roman"), N_("Script|Japanese"), N_("Script|Traditional Chinese"), N_("Script|Korean"),
+ N_("Script|Arabic"), N_("Script|Hebrew"), N_("Script|Greek"),
+/* GT: Don't ask me what RSymbol means, I don't know either. It's in apple's */
+/* GT: docs though */
+ N_("Script|Cyrillic"), N_("Script|RSymbol"), N_("Script|Devanagari"),
+/* 10*/ N_("Script|Gurmukhi"), N_("Script|Gujarati"), NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+/* 20*/ NULL, N_("Script|Thai"), NULL, NULL, NULL, N_("Script|Simplified Chinese"),
+ NULL, NULL, NULL, N_("Script|Central European"),
+/* 30*/ NULL, NULL, NULL };
+
+ choices = galloc(enccnt*sizeof(char *));
+ for ( i=0; i<enccnt; ++i ) {
+ encname = NULL;
+ if ( cmap_encs[i].platform==1 && cmap_encs[i].specific<32 ) {
+ encname = macscripts[cmap_encs[i].specific];
+ if ( encname!=NULL )
+ encname = S_(encname);
+ } else if ( cmap_encs[i].platform==0 ) {
+ switch ( cmap_encs[i].specific ) {
+ case 0:
+ encname = N_("Unicode 1.0");
+ break;
+ case 1:
+ encname = N_("Unicode 1.1");
+ break;
+ case 2:
+ encname = N_("ISO 10646:1993");
+ break;
+ case 3:
+ encname = N_("Unicode 2.0+, BMP only");
+ break;
+ case 4:
+ encname = N_("Unicode 2.0+, all planes");
+ break;
+ }
+ } else if ( cmap_encs[i].platform==3 && cmap_encs[i].specific==0 )
+ encname = N_("\"Symbol\"");
+ if ( encname==NULL )
+ encname = cmap_encs[i].enc->enc_name;
+
+ sprintf(buffer,"%d (%s) %d %s %s %s",
+ cmap_encs[i].platform,
+ cmap_encs[i].platform==0 ? _("Apple Unicode") :
+ cmap_encs[i].platform==1 ? _("Apple") :
+ cmap_encs[i].platform==2 ? _("ISO (Deprecated)") :
+ cmap_encs[i].platform==3 ? _("MicroSoft") :
+ cmap_encs[i].platform==4 ? _("Custom") :
+ cmap_encs[i].platform==7 ? _("FreeType internals") :
+ _("Unknown"),
+ cmap_encs[i].specific,
+ encname,
+ cmap_encs[i].platform==1 && cmap_encs[i].lang!=0? MacLanguageFromCode(cmap_encs[i].lang-1) : "",
+ cmap_encs[i].format == 0 ? "Byte encoding table" :
+ cmap_encs[i].format == 2 ? "High-byte mapping through table" :
+ cmap_encs[i].format == 4 ? "Segment mapping to delta values" :
+ cmap_encs[i].format == 6 ? "Trimmed table mapping" :
+ cmap_encs[i].format == 8 ? "mixed 16-bit and 32-bit coverage" :
+ cmap_encs[i].format == 10 ? "Trimmed array" :
+ cmap_encs[i].format == 12 ? "Segmented coverage" :
+ "Unknown format" );
+ choices[i] = copy(buffer);
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ ret = gwwv_choose(_("Pick a CMap subtable"),(const char **) choices,enccnt,def,
+ _("Pick a CMap subtable"));
+#else
+ ret = -1;
+#endif
+ for ( i=0; i<enccnt; ++i )
+ free(choices[i]);
+ free(choices);
+return( ret );
+}
+
+/* 'cmap' table: readttfcmap */
+static void readttfencodings(FILE *ttf,struct ttfinfo *info, int justinuse) {
+ int i,j, def, unicode_cmap, unicode4_cmap, dcnt, dcmap_cnt, dc;
+ int nencs, version, usable_encs;
+ Encoding *enc = &custom;
+ const int32 *trans=NULL;
+ enum uni_interp interp = ui_none;
+ int platform, specific;
+ int offset, encoff=0;
+ int format, len;
+ uint16 table[256];
+ int segCount;
+ uint16 *endchars, *startchars, *delta, *rangeOffset, *glyphs;
+ int index, last;
+ int mod = 0;
+ SplineChar *sc;
+ uint8 *used;
+ int badencwarned=false;
+ int glyph_tot;
+ Encoding *temp;
+ EncMap *map;
+ struct cmap_encs *cmap_encs, desired_cmaps[2], *dcmap;
+ extern int ask_user_for_cmap;
+
+ fseek(ttf,info->encoding_start,SEEK_SET);
+ version = getushort(ttf);
+ nencs = getushort(ttf);
+ if ( version!=0 && nencs==0 )
+ nencs = version; /* Sometimes they are backwards */
+ cmap_encs = galloc(nencs*sizeof(struct cmap_encs));
+ for ( i=usable_encs=0; i<nencs; ++i ) {
+ cmap_encs[usable_encs].platform = getushort(ttf);
+ cmap_encs[usable_encs].specific = getushort(ttf);
+ cmap_encs[usable_encs].offset = getlong(ttf);
+ temp = enc_from_platspec(cmap_encs[usable_encs].platform,cmap_encs[usable_encs].specific);
+ if ( temp==NULL ) /* iconv doesn't support this. Some sun iconvs seem limited */
+ temp = FindOrMakeEncoding("Custom");
+ cmap_encs[usable_encs].enc = temp;
+ if ( SubtableIsntSupported(ttf,info->encoding_start+cmap_encs[usable_encs].offset,
+ &cmap_encs[usable_encs]))
+ continue;
+ ++usable_encs;
+ }
+ if ( usable_encs==0 ) {
+ LogError( _("Could not find any valid encoding tables" ));
+ free(cmap_encs);
+return;
+ }
+ def = -1;
+ enc = &custom;
+ unicode_cmap = unicode4_cmap = -1;
+ for ( i=0; i<usable_encs; ++i ) {
+ temp = cmap_encs[i].enc;
+ platform = cmap_encs[i].platform;
+ specific = cmap_encs[i].specific;
+ offset = cmap_encs[i].offset;
+
+ if ( (platform==3 && specific==10) || (platform==0 && specific==4) ) { /* MS Unicode 4 byte */
+ enc = temp;
+ def = i;
+ unicode4_cmap = i;
+ } else if ( !enc->is_unicodefull && (!prefer_cjk_encodings ||
+ (!enc->is_japanese && !enc->is_korean && !enc->is_tradchinese &&
+ !enc->is_simplechinese)) &&
+ (( platform==3 && specific==1 ) || /* MS Unicode */
+/* Well I should only deal with apple unicode specific==0 (default) and 3 (U2.0 semantics) */
+/* but apple ships dfonts with specific==1 (Unicode 1.1 semantics) */
+/* which is stupid of them */
+ ( platform==0 /*&& (specific==0 || specific==3)*/ ))) { /* Apple Unicode */
+ enc = temp;
+ def = i;
+ } else if ( platform==3 && specific==0 && enc->is_custom ) {
+ /* Only select symbol if we don't have something better */
+ enc = temp;
+ def = i;
+ /* Now I had assumed this would be a 1 byte encoding, but it turns*/
+ /* out to map into the unicode private use area at U+f000-U+F0FF */
+ /* so it's a 2 byte enc */
+/* Mac platform specific encodings are script numbers. 0=>roman, 1=>jap, 2=>big5, 3=>korean, 4=>arab, 5=>hebrew, 6=>greek, 7=>cyrillic, ... 25=>simplified chinese */
+ } else if ( platform==1 && specific==0 && enc->is_custom ) {
+ enc = temp;
+ def = i;
+ } else if ( platform==1 && (specific==2 ||specific==1||specific==3||specific==25) &&
+ !enc->is_unicodefull &&
+ (prefer_cjk_encodings || !enc->is_unicodebmp) ) {
+ enc = temp;
+ def = i;
+ } else if ( platform==3 && (specific>=2 && specific<=6 ) &&
+ !enc->is_unicodefull &&
+ (prefer_cjk_encodings || !enc->is_unicodebmp) ) {
+ /* Old ms docs say that specific==3 => big 5, new docs say specific==4 => big5 */
+ /* Ain't that jus' great? */
+ enc = temp;
+ def = i;
+ }
+ if ( (platform==3 && specific==1) ||
+ (platform==0 && specific==3))
+ unicode_cmap = i;
+ }
+
+ if ( justinuse || !ask_user_for_cmap || (i = PickCMap(cmap_encs,usable_encs,def))==-1 )
+ i = def;
+ info->platform = cmap_encs[i].platform;
+ info->specific = cmap_encs[i].specific;
+
+ desired_cmaps[0] = cmap_encs[i]; dcnt = 1;
+ if ( unicode4_cmap!=-1 ) {
+ if ( i!=unicode4_cmap ) {
+ desired_cmaps[1] = cmap_encs[unicode4_cmap];
+ ++dcnt;
+ }
+ } else if ( unicode_cmap!=-1 ) {
+ if ( i!=unicode_cmap ) {
+ desired_cmaps[1] = cmap_encs[unicode_cmap];
+ ++dcnt;
+ }
+ } else {
+ if ( i!=def ) {
+ desired_cmaps[1] = cmap_encs[def];
+ ++dcnt;
+ }
+ }
+
+ map = NULL;
+ if ( justinuse ) {
+ dcmap_cnt = usable_encs;
+ dcmap = cmap_encs;
+ } else {
+ dcmap_cnt = dcnt;
+ dcmap = desired_cmaps;
+ }
+ for ( dc=dcmap_cnt-1; dc>=0; --dc ) {
+ /* if justinuse then look at all cmaps and tick the glyphs they use */
+ /* otherwise dcmap_cnt will be either 1 or 2. If 1 then this subtable */
+ /* contains both the encoding and the source for unicode encodings */
+ /* if dcmap_cnt==2 then when dc==0 we are setting up the encoding */
+ /* and when dc==1 we are setting up the unicode code points */
+ int dounicode = (dc==dcmap_cnt-1);
+ enc = dcmap[dc].enc;
+ encoff = dcmap[dc].offset;
+
+ if ( dc==0 && !justinuse ) {
+ interp = interp_from_encoding(enc,ui_none);
+ mod = 0;
+ if ( dcmap[dc].platform==3 && (dcmap[dc].specific>=2 && dcmap[dc].specific<=6 ))
+ mod = dcmap[dc].specific;
+ else if ( dcmap[dc].platform==1 && (dcmap[dc].specific==2 ||dcmap[dc].specific==1||dcmap[dc].specific==3||dcmap[dc].specific==25))
+ mod = dcmap[dc].specific==1?2:dcmap[dc].specific==2?4:dcmap[dc].specific==3?5:3; /* convert to ms specific */
+ info->map = map = EncMapNew(enc->char_cnt,info->glyph_cnt,enc);
+ info->uni_interp = interp;
+ }
+
+ fseek(ttf,info->encoding_start+encoff,SEEK_SET);
+ format = getushort(ttf);
+ if ( format!=12 && format!=10 && format!=8 ) {
+ len = getushort(ttf);
+ /* version/language = */ getushort(ttf);
+ } else {
+ /* padding */ getushort(ttf);
+ len = getlong(ttf);
+ /* language = */ getlong(ttf);
+ }
+ if ( enc->is_unicodebmp && (format==8 || format==10 || format==12))
+ enc = FindOrMakeEncoding("UnicodeFull");
+
+ if ( format==0 ) {
+ if ( !justinuse && map!=NULL && map->enccount<256 ) {
+ map->map = grealloc(map->map,256*sizeof(int));
+ memset(map->map,-1,(256-map->enccount)*sizeof(int));
+ map->enccount = map->encmax = 256;
+ }
+ for ( i=0; i<len-6; ++i )
+ table[i] = getc(ttf);
+ trans = enc->unicode;
+ if ( trans==NULL && dcmap[dc].platform==1 )
+ trans = MacEncToUnicode(dcmap[dc].specific,dcmap[dc].lang-1);
+ for ( i=0; i<256 && i<len-6; ++i )
+ if ( !justinuse ) {
+ if ( table[i]<info->glyph_cnt && info->chars[table[i]]!=NULL ) {
+ if ( map!=NULL )
+ map->map[i] = table[i];
+ if ( dounicode && trans!=NULL )
+ info->chars[table[i]]->unicodeenc = trans[i];
+ }
+ } else if ( table[i]<info->glyph_cnt && info->chars[table[i]]!=NULL )
+ info->inuse[table[i]] = 1;
+ } else if ( format==4 ) {
+ segCount = getushort(ttf)/2;
+ /* searchRange = */ getushort(ttf);
+ /* entrySelector = */ getushort(ttf);
+ /* rangeShift = */ getushort(ttf);
+ endchars = galloc(segCount*sizeof(uint16));
+ used = gcalloc(65536,sizeof(uint8));
+ for ( i=0; i<segCount; ++i )
+ endchars[i] = getushort(ttf);
+ if ( getushort(ttf)!=0 )
+ IError("Expected 0 in 'cmap' format 4 subtable");
+ startchars = galloc(segCount*sizeof(uint16));
+ for ( i=0; i<segCount; ++i )
+ startchars[i] = getushort(ttf);
+ delta = galloc(segCount*sizeof(uint16));
+ for ( i=0; i<segCount; ++i )
+ delta[i] = getushort(ttf);
+ rangeOffset = galloc(segCount*sizeof(uint16));
+ for ( i=0; i<segCount; ++i )
+ rangeOffset[i] = getushort(ttf);
+ len -= 8*sizeof(uint16) +
+ 4*segCount*sizeof(uint16);
+ /* that's the amount of space left in the subtable and it must */
+ /* be filled with glyphIDs */
+ if ( len<0 ) {
+ IError("This font has an illegal format 4 subtable with too little space for all the segments.\nThis error is not recoverable.\nBye" );
+ exit(1);
+ }
+ glyphs = galloc(len);
+ glyph_tot = len/2;
+ for ( i=0; i<glyph_tot; ++i )
+ glyphs[i] = getushort(ttf);
+ for ( i=0; i<segCount; ++i ) {
+ if ( rangeOffset[i]==0 && startchars[i]==0xffff )
+ /* Done */;
+ else if ( rangeOffset[i]==0 ) {
+ for ( j=startchars[i]; j<=endchars[i]; ++j ) {
+ if ( justinuse && (uint16) (j+delta[i])<info->glyph_cnt )
+ info->inuse[(uint16) (j+delta[i])] = true;
+ else if ( (uint16) (j+delta[i])>=info->glyph_cnt || info->chars[(uint16) (j+delta[i])]==NULL )
+ LogError( _("Attempt to encode missing glyph %d to %d (0x%x)\n"),
+ (uint16) (j+delta[i]), modenc(j,mod), modenc(j,mod));
+ else {
+ int uenc = umodenc(j,mod);
+ int lenc = modenc(j,mod);
+ if ( uenc!=-1 && used[uenc] ) {
+ if ( !badencwarned ) {
+ LogError( _("Multiple glyphs map to the same unicode encoding U+%04X, only one will be used\n"), uenc );
+ badencwarned = true;
+ }
+ } else {
+ if ( uenc!=-1 && dounicode ) used[uenc] = true;
+ if ( dounicode && info->chars[(uint16) (j+delta[i])]->unicodeenc==-1 )
+ info->chars[(uint16) (j+delta[i])]->unicodeenc = uenc;
+ if ( map!=NULL && lenc<map->enccount )
+ map->map[lenc] = (uint16) (j+delta[i]);
+ }
+ }
+ }
+ } else if ( rangeOffset[i]!=0xffff ) {
+ /* Apple says a rangeOffset of 0xffff means no glyph */
+ /* OpenType doesn't mention this */
+ for ( j=startchars[i]; j<=endchars[i]; ++j ) {
+ int temp = (i-segCount+rangeOffset[i]/2) + j-startchars[i];
+ if ( temp<glyph_tot )
+ index = glyphs[ temp ];
+ else {
+ /* This happened in mingliu.ttc(PMingLiU) */
+ if ( !justinuse )
+ LogError( _("Glyph index out of bounds. Was %d, must be less than %d.\n In attempt to associate a glyph with encoding %x in segment %d\n with platform=%d, specific=%d (in 'cmap')\n"),
+ temp, glyph_tot, j, i, dcmap[dc].platform, dcmap[dc].specific );
+ index = 0;
+ }
+ if ( index!=0 ) {
+ index = (unsigned short) (index+delta[i]);
+ if ( index>=info->glyph_cnt )
+ /* This isn't mentioned either, but in some */
+ /* MS Chinese fonts (kaiu.ttf) the index */
+ /* goes out of bounds. and MS's ttf dump */
+ /* program says it is treated as 0 */
+ LogError( _("Attempt to encode missing glyph %d to %d (0x%x)\n"),
+ index, modenc(j,mod), modenc(j,mod));
+ else if ( justinuse )
+ info->inuse[index] = 1;
+ else if ( info->chars[index]==NULL )
+ LogError( _("Attempt to encode missing glyph %d to %d (0x%x)\n"),
+ index, modenc(j,mod), modenc(j,mod));
+ else {
+ int uenc = umodenc(j,mod);
+ int lenc = modenc(j,mod);
+ if ( uenc!=-1 && used[uenc] ) {
+ if ( !badencwarned ) {
+ LogError( _("Multiple glyphs map to the same unicode encoding U+%04X, only one will be used\n"), uenc );
+ badencwarned = true;
+ }
+ } else {
+ if ( uenc!=-1 && dounicode ) used[uenc] = true;
+ if ( dounicode && info->chars[index]->unicodeenc==-1 )
+ info->chars[index]->unicodeenc = uenc;
+ if ( map!=NULL && lenc<map->enccount )
+ map->map[lenc] = index;
+ }
+ }
+ }
+ }
+ } else
+ LogError( _("Use of a range offset of 0xffff to mean a missing glyph in cmap table\n") );
+ }
+ free(glyphs);
+ free(rangeOffset);
+ free(delta);
+ free(startchars);
+ free(endchars);
+ free(used);
+ } else if ( format==6 ) {
+ /* trimmed array format */
+ /* Well, the docs say it's for 2byte encodings, but Apple actually*/
+ /* uses it for 1 byte encodings which don't fit into the require-*/
+ /* ments for a format 0 sub-table. See Zapfino.dfont */
+ int first, count;
+ first = getushort(ttf);
+ count = getushort(ttf);
+ trans = enc->unicode;
+ if ( trans==NULL && dcmap[dc].platform==1 && first+count<=256 )
+ trans = MacEncToUnicode(dcmap[dc].specific,dcmap[dc].lang-1);
+ if ( justinuse )
+ for ( i=0; i<count; ++i )
+ info->inuse[getushort(ttf)]= 1;
+ else {
+ for ( i=0; i<count; ++i ) {
+ int gid = getushort(ttf);
+ if ( dounicode )
+ info->chars[gid]->unicodeenc = trans==NULL ? trans[first+1] : first+i;
+ if ( map!=NULL && first+i < map->enccount )
+ map->map[first+i] = gid;
+ }
+ }
+ } else if ( format==2 ) {
+ int max_sub_head_key = 0, cnt, max_pos= -1;
+ struct subhead *subheads;
+
+ for ( i=0; i<256; ++i ) {
+ table[i] = getushort(ttf)/8; /* Sub-header keys */
+ if ( table[i]>max_sub_head_key ) {
+ max_sub_head_key = table[i]; /* The entry is a byte pointer, I want a pointer in units of struct subheader */
+ max_pos = i;
+ }
+ }
+ subheads = galloc((max_sub_head_key+1)*sizeof(struct subhead));
+ for ( i=0; i<=max_sub_head_key; ++i ) {
+ subheads[i].first = getushort(ttf);
+ subheads[i].cnt = getushort(ttf);
+ subheads[i].delta = getushort(ttf);
+ subheads[i].rangeoff = (getushort(ttf)-
+ (max_sub_head_key-i)*sizeof(struct subhead)-
+ sizeof(short))/sizeof(short);
+ }
+ cnt = (len-(ftell(ttf)-(info->encoding_start+encoff)))/sizeof(short);
+ /* The count is the number of glyph indexes to read. it is the */
+ /* length of the entire subtable minus that bit we've read so far */
+ glyphs = galloc(cnt*sizeof(short));
+ for ( i=0; i<cnt; ++i )
+ glyphs[i] = getushort(ttf);
+ last = -1;
+ for ( i=0; i<256; ++i ) {
+ if ( table[i]==0 ) {
+ /* Special case, single byte encoding entry, look it up in */
+ /* subhead */
+ /* In the one example I've got of this encoding (wcl-02.ttf) the chars */
+ /* 0xfd, 0xfe, 0xff are said to exist but there is no mapping */
+ /* for them. */
+ if ( i>=max_pos )
+ index = 0; /* the subhead says there are 256 entries, but in fact there are only 193, so attempting to find these guys should give an error */
+ else if ( i<subheads[0].first || i>=subheads[0].first+subheads[0].cnt ||
+ subheads[0].rangeoff+(i-subheads[0].first)>=cnt )
+ index = 0;
+ else if ( (index = glyphs[subheads[0].rangeoff+(i-subheads[0].first)])!= 0 )
+ index = (uint32) (index+subheads[0].delta);
+ /* I assume the single byte codes are just ascii or latin1*/
+ if ( index!=0 && index<info->glyph_cnt ) {
+ if ( justinuse )
+ info->inuse[index] = 1;
+ else if ( info->chars[index]==NULL )
+ /* Do Nothing */;
+ else {
+ int lenc = modenc(i,mod);
+ if ( dounicode && info->chars[index]->unicodeenc==-1 )
+ info->chars[index]->unicodeenc = i;
+ if ( map!=NULL && lenc<map->enccount )
+ map->map[lenc] = index;
+ }
+ }
+ } else {
+ int k = table[i];
+ for ( j=0; j<subheads[k].cnt; ++j ) {
+ int enc, lenc;
+ if ( subheads[k].rangeoff+j>=cnt )
+ index = 0;
+ else if ( (index = glyphs[subheads[k].rangeoff+j])!= 0 )
+ index = (uint16) (index+subheads[k].delta);
+ if ( index!=0 && index<info->glyph_cnt ) {
+ enc = (i<<8)|(j+subheads[k].first);
+ lenc = modenc(enc,mod);
+ if ( justinuse )
+ info->inuse[index] = 1;
+ else if ( info->chars[index]==NULL )
+ /* Do Nothing */;
+ else {
+ if ( dounicode && info->chars[index]->unicodeenc==-1 )
+ info->chars[index]->unicodeenc = umodenc(enc,mod);
+ if ( map!=NULL && lenc<map->enccount )
+ map->map[lenc] = index;
+ }
+ }
+ }
+ /*if ( last==-1 ) last = i;*/
+ }
+ }
+ free(subheads);
+ free(glyphs);
+ } else if ( format==8 ) {
+ uint32 ngroups, start, end, startglyph;
+ if ( !enc->is_unicodefull ) {
+ IError("I don't support 32 bit characters except for the UCS-4 (MS platform, specific=10)" );
+ enc = FindOrMakeEncoding("UnicodeFull");
+ }
+ /* I'm now assuming unicode surrogate encoding, so I just ignore */
+ /* the is32 table (it will be set for the surrogates and not for */
+ /* anything else */
+ fseek(ttf,8192,SEEK_CUR);
+ ngroups = getlong(ttf);
+ for ( j=0; j<ngroups; ++j ) {
+ start = getlong(ttf);
+ end = getlong(ttf);
+ startglyph = getlong(ttf);
+ if ( justinuse )
+ for ( i=start; i<=end; ++i )
+ info->inuse[startglyph+i-start]= 1;
+ else
+ for ( i=start; i<=end; ++i ) {
+ int uenc = ((i>>16)-0xd800)*0x400 + (i&0xffff)-0xdc00 + 0x10000;
+ sc = info->chars[startglyph+i-start];
+ if ( dounicode && sc->unicodeenc==-1 )
+ sc->unicodeenc = uenc;
+ if ( map!=NULL && sc->unicodeenc < map->enccount )
+ map->map[uenc] = startglyph+i-start;
+ }
+ }
+ } else if ( format==10 ) {
+ /* same as format 6, except for 4byte chars */
+ int first, count;
+ if ( !enc->is_unicodefull ) {
+ IError("I don't support 32 bit characters except for the UCS-4 (MS platform, specific=10)" );
+ enc = FindOrMakeEncoding("UnicodeFull");
+ }
+ first = getlong(ttf);
+ count = getlong(ttf);
+ if ( justinuse )
+ for ( i=0; i<count; ++i )
+ info->inuse[getushort(ttf)]= 1;
+ else
+ for ( i=0; i<count; ++i ) {
+ int gid = getushort(ttf);
+ if ( dounicode )
+ info->chars[gid]->unicodeenc = first+i;
+ if ( map!=NULL && first+i < map->enccount )
+ map->map[first+i] = gid;
+ }
+ } else if ( format==12 ) {
+ uint32 ngroups, start, end, startglyph;
+ if ( !enc->is_unicodefull ) {
+ IError("I don't support 32 bit characters except for the UCS-4 (MS platform, specific=10)" );
+ enc = FindOrMakeEncoding("UnicodeFull");
+ }
+ ngroups = getlong(ttf);
+ for ( j=0; j<ngroups; ++j ) {
+ start = getlong(ttf);
+ end = getlong(ttf);
+ startglyph = getlong(ttf);
+ if ( justinuse ) {
+ for ( i=start; i<=end; ++i )
+ if ( startglyph+i-start < info->glyph_cnt )
+ info->inuse[startglyph+i-start]= 1;
+ else
+ break;
+ } else
+ for ( i=start; i<=end; ++i ) {
+ if ( startglyph+i-start >= info->glyph_cnt ||
+ info->chars[startglyph+i-start]==NULL ) {
+ LogError( _("Bad font: Encoding data out of range.\n") );
+ break;
+ } else {
+ if ( dounicode )
+ info->chars[startglyph+i-start]->unicodeenc = i;
+ if ( map!=NULL && i < map->enccount )
+ map->map[i] = startglyph+i-start;
+ }
+ }
+ }
+ }
+ }
+ free(cmap_encs);
+ if ( info->chars!=NULL )
+ for ( i=0; i<info->glyph_cnt; ++i )
+ if ( info->chars[i]!=NULL && info->chars[i]->unicodeenc==0xffff )
+ info->chars[i]->unicodeenc = -1;
+ if ( !justinuse ) {
+ if ( interp==ui_none )
+ info->uni_interp = amscheck(info,map);
+ map->enc = enc; /* This can be changed from the initial value */
+ }
+ info->map = map;
+}
+
+static void readttfos2metrics(FILE *ttf,struct ttfinfo *info) {
+ int i, sel;
+
+ fseek(ttf,info->os2_start,SEEK_SET);
+ info->os2_version = getushort(ttf);
+#ifdef LUA_FF_LIB
+ info->pfminfo.avgwidth = getushort(ttf);
+#else
+ /* avgwidth */ getushort(ttf);
+#endif
+ info->pfminfo.weight = getushort(ttf);
+ info->pfminfo.width = getushort(ttf);
+ info->pfminfo.fstype = getushort(ttf);
+ info->pfminfo.os2_subxsize = getushort(ttf);
+ info->pfminfo.os2_subysize = getushort(ttf);
+ info->pfminfo.os2_subxoff = getushort(ttf);
+ info->pfminfo.os2_subyoff = getushort(ttf);
+ info->pfminfo.os2_supxsize = getushort(ttf);
+ info->pfminfo.os2_supysize = getushort(ttf);
+ info->pfminfo.os2_supxoff = getushort(ttf);
+ info->pfminfo.os2_supyoff = getushort(ttf);
+ info->pfminfo.os2_strikeysize = getushort(ttf);
+ info->pfminfo.os2_strikeypos = getushort(ttf);
+ info->pfminfo.os2_family_class = getushort(ttf);
+ for ( i=0; i<10; ++i )
+ info->pfminfo.panose[i] = getc(ttf);
+ info->pfminfo.pfmfamily = info->pfminfo.panose[0]==2 ? 0x11 : /* might be 0x21 */ /* Text & Display maps to either serif 0x11 or sans 0x21 or monospace 0x31 */
+ info->pfminfo.panose[0]==3 ? 0x41 : /* Script */
+ info->pfminfo.panose[0]==4 ? 0x51 : /* Decorative */
+ 0x51; /* And pictorial doesn't fit into pfm */
+ /* unicoderange[] */ getlong(ttf);
+ /* unicoderange[] */ getlong(ttf);
+ /* unicoderange[] */ getlong(ttf);
+ /* unicoderange[] */ getlong(ttf);
+ info->pfminfo.os2_vendor[0] = getc(ttf);
+ info->pfminfo.os2_vendor[1] = getc(ttf);
+ info->pfminfo.os2_vendor[2] = getc(ttf);
+ info->pfminfo.os2_vendor[3] = getc(ttf);
+ sel = getushort(ttf);
+ if ( info->os2_version>=4 ) {
+ info->use_typo_metrics = (sel&128)?1:0;
+ info->weight_width_slope_only = (sel&256)?1:0;
+ }
+#ifdef LUA_FF_LIB
+ info->pfminfo.firstchar = getushort(ttf);
+ info->pfminfo.lastchar = getushort(ttf);
+#else
+ /* firstchar */ getushort(ttf);
+ /* lastchar */ getushort(ttf);
+#endif
+ info->pfminfo.os2_typoascent = getushort(ttf);
+ info->pfminfo.os2_typodescent = (short) getushort(ttf);
+ if ( info->pfminfo.os2_typoascent-info->pfminfo.os2_typodescent == info->emsize ) {
+ info->ascent = info->pfminfo.os2_typoascent;
+ info->descent = -info->pfminfo.os2_typodescent;
+ }
+ info->pfminfo.os2_typolinegap = getushort(ttf);
+ info->pfminfo.os2_winascent = getushort(ttf);
+ info->pfminfo.os2_windescent = getushort(ttf);
+#ifdef LUA_FF_LIB
+ if ( info->os2_version>=3 ) { /* TH just in case */
+ /* unicoderange[] */ getlong(ttf);
+ /* unicoderange[] */ getlong(ttf);
+ info->pfminfo.os2_xheight = getushort(ttf); /* four new fields */
+ info->pfminfo.os2_capheight = getushort(ttf);
+ info->pfminfo.os2_defaultchar = getushort(ttf);
+ info->pfminfo.os2_breakchar = getushort(ttf);
+ }
+#endif
+ info->pfminfo.winascent_add = info->pfminfo.windescent_add = false;
+ info->pfminfo.typoascent_add = info->pfminfo.typodescent_add = false;
+
+ info->pfminfo.pfmset = true;
+ info->pfminfo.panose_set = true;
+ info->pfminfo.subsuper_set = true;
+}
+
+static int cmapEncFromName(struct ttfinfo *info,const char *nm, int glyphid) {
+ int uni;
+ int i;
+
+ if ( info->map!=NULL )
+ uni = EncFromName(nm,info->uni_interp,info->map->enc);
+ else
+ uni = EncFromName(nm,ui_none,&custom);
+ if ( uni==-1 )
+return( -1 );
+
+ for ( i=0; i<info->glyph_cnt; ++i ) if ( info->chars[i]!=NULL ) {
+ if ( info->chars[i]->unicodeenc==uni ) {
+ if ( info->complainedmultname )
+ /* Don't do it again */;
+ else if ( info->chars[i]->name!=NULL && strcmp(info->chars[i]->name,nm)==0 )
+ LogError( _("Warning: Glyph %d has the same name (%s) as Glyph %d\n"),
+ i, nm, glyphid );
+ else
+ LogError( _("Warning: Glyph %d is named %s which should mean it is mapped to\n Unicode U+%04X, but Glyph %d already has that encoding.\n"),
+ glyphid, nm, uni, i);
+ info->complainedmultname = true;
+return( -1 );
+ }
+ }
+return( uni );
+}
+
+static void readttfpostnames(FILE *ttf,struct ttfinfo *info) {
+ int i,j;
+ int format, len, gc, gcbig, val;
+ const char *name;
+ char buffer[30];
+ uint16 *indexes;
+ extern const char *ttfstandardnames[];
+ int notdefwarned = false;
+
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_change_line2(_("Reading Names"));
+#endif
+
+ /* Give ourselves an xuid, just in case they want to convert to PostScript*/
+ /* (even type42) */
+ if ( xuid!=NULL && info->fd==NULL && info->xuid==NULL ) {
+ info->xuid = galloc(strlen(xuid)+20);
+ sprintf(info->xuid,"[%s %d]", xuid, (rand()&0xffffff));
+ }
+
+ if ( info->postscript_start!=0 ) {
+ fseek(ttf,info->postscript_start,SEEK_SET);
+ format = getlong(ttf);
+ info->italicAngle = getfixed(ttf);
+ info->upos = (short) getushort(ttf);
+ info->uwidth = (short) getushort(ttf);
+ /* fixedpitch = */ getlong(ttf);
+ /* mem1 = */ getlong(ttf);
+ /* mem2 = */ getlong(ttf);
+ /* mem3 = */ getlong(ttf);
+ /* mem4 = */ getlong(ttf);
+ if ( format==0x00020000 ) {
+ gc = getushort(ttf);
+ indexes = gcalloc(65536,sizeof(uint16));
+ /* the index table is backwards from the way I want to use it */
+ gcbig = 0;
+ for ( i=0; i<gc; ++i ) {
+ indexes[val = getushort(ttf)] = i;
+ if ( val>=258 ) ++gcbig;
+ }
+
+ /* if we are only loading bitmaps, we can get holes in our data */
+ for ( i=0; i<258; ++i ) if ( indexes[i]!=0 || i==0 ) if ( indexes[i]<info->glyph_cnt && info->chars[indexes[i]]!=NULL ) {
+ info->chars[indexes[i]]->name = copy(ttfstandardnames[i]);
+ if ( info->chars[indexes[i]]->unicodeenc==-1 )
+ info->chars[indexes[i]]->unicodeenc = cmapEncFromName(info,ttfstandardnames[i],indexes[i]);
+ }
+ gcbig += 258;
+ for ( i=258; i<gcbig; ++i ) {
+ char *nm;
+ len = getc(ttf);
+ if ( len<0 ) /* Don't crash on EOF */
+ break;
+ nm = galloc(len+1);
+ for ( j=0; j<len; ++j )
+ nm[j] = getc(ttf);
+ nm[j] = '\0';
+ if ( indexes[i]<info->glyph_cnt && info->chars[indexes[i]]!=NULL ) {
+ info->chars[indexes[i]]->name = nm;
+ if ( info->chars[indexes[i]]->unicodeenc==-1 )
+ info->chars[indexes[i]]->unicodeenc = cmapEncFromName(info,nm,indexes[i]);
+ }
+ }
+ free(indexes);
+ }
+ }
+
+ if ( info->fd!=NULL && info->fd->chars!=NULL) {
+ EncMap *map = NULL;
+ struct pschars *chars = info->fd->chars;
+ if ( info->map==NULL )
+ info->map = map = EncMapNew(65536,65536,FindOrMakeEncoding("UnicodeBmp"));
+ /* In type42 fonts the names are stored in a postscript /CharStrings dictionary */
+ for ( i=0; i<chars->next; ++i ) {
+ int gid = (intpt) (chars->values[i]);
+ if ( gid>=0 && gid<info->glyph_cnt && chars->keys[i]!=NULL ) {
+ free(info->chars[gid]->name);
+ info->chars[gid]->name = chars->keys[i];
+ info->chars[gid]->unicodeenc = UniFromName(chars->keys[i],info->uni_interp,info->map->enc);
+ if ( map!=NULL && info->chars[gid]->unicodeenc!=-1 &&
+ info->chars[gid]->unicodeenc<map->enccount)
+ map->map[ info->chars[gid]->unicodeenc ] = gid;
+ chars->keys[i] = NULL;
+ chars->values[i] = NULL;
+ } else
+ chars->values[i] = NULL;
+ }
+ }
+
+ /* where no names are given, but we've got a unicode encoding use */
+ /* that to guess at them */
+ for ( i=0; i<info->glyph_cnt; ++i ) if ( info->chars[i]!=NULL ) {
+ /* info->chars[i] can be null in some TTC files */
+ if ( i!=0 && info->chars[i]->name!=NULL &&
+ strcmp(info->chars[i]->name,".notdef")==0 ) {
+ /* for some reason MS puts out fonts where several characters */
+ /* are called .notdef (and only one is a real notdef). So if we */
+ /* find a glyph other than 0 called ".notdef" then pretend it had */
+ /* no name */
+ if ( !notdefwarned ) {
+ notdefwarned = true;
+ LogError( _("Glyph %d is called \".notdef\", a singularly inept choice of name (only glyph 0\n may be called .notdef)\nFontForge will rename it.\n"), i );
+ }
+ free(info->chars[i]->name);
+ info->chars[i]->name = NULL;
+ }
+ /* And some volt files actually assign nul strings to the name */
+ if ( (info->chars[i]->name!=NULL && *info->chars[i]->name!='\0' ))
+ continue;
+ free(info->chars[i]->name); /* If it's a null string get rid of it */
+ if ( i==0 )
+ name = ".notdef";
+ else if ( info->chars[i]->unicodeenc==-1 ) {
+ /* Do this later */;
+ name = NULL;
+ } else
+ name = StdGlyphName(buffer,info->chars[i]->unicodeenc,info->uni_interp,NULL);
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_next();
+#endif
+ info->chars[i]->name = copy(name);
+ }
+
+ /* If we have a GSUB table we can give some unencoded glyphs names */
+ /* for example if we have a vrt2 substitution of A to <unencoded> */
+ /* we could name the unencoded "A.vrt2" (though in this case we might */
+ /* try A.vert instead */ /* Werner suggested this */
+ /* We could try this from morx too, except that apple features don't */
+ /* use meaningful ids. That is A.15,3 isn't very readable */
+ for ( i=info->glyph_cnt-1; i>=0 ; --i )
+ if ( info->chars[i]!=NULL && info->chars[i]->name==NULL )
+ break;
+ if ( i>=0 && info->gsub_start!=0 )
+ GuessNamesFromGSUB(ttf,info);
+
+ for ( i=0; i<info->glyph_cnt; ++i ) {
+ /* info->chars[i] can be null in some TTC files */
+ if ( info->chars[i]==NULL )
+ continue;
+ if ( info->chars[i]->name!=NULL )
+ continue;
+ if ( info->ordering!=NULL )
+ sprintf(buffer, "%.20s-%d", info->ordering, i );
+ else if ( info->map!=NULL && info->map->map[i]!=-1 )
+ sprintf(buffer, "nounicode.%d.%d.%x", info->platform, info->specific,
+ (int) info->map->map[i] );
+ else
+ sprintf( buffer, "glyph%d", i );
+ info->chars[i]->name = copy(buffer);
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_next();
+#endif
+ }
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_next_stage();
+#endif
+}
+
+static void readttfgasp(FILE *ttf,struct ttfinfo *info) {
+ int i, cnt;
+
+ if ( info->gasp_start==0 )
+return;
+
+ fseek(ttf,info->gasp_start,SEEK_SET);
+ info->gasp_version = getushort(ttf);
+ if ( info->gasp_version!=0 && info->gasp_version!=1 )
+return; /* We only support 'gasp' versions 0&1 (no other versions currently) */
+ info->gasp_cnt = cnt = getushort(ttf);
+ if ( cnt==0 )
+return;
+ info->gasp = galloc(cnt*sizeof(struct gasp));
+ for ( i=0; i<cnt; ++i ) {
+ info->gasp[i].ppem = getushort(ttf);
+ info->gasp[i].flags = getushort(ttf);
+ }
+}
+
+static void UnfigureControls(Spline *spline,BasePoint *pos) {
+ pos->x = rint( (spline->splines[0].c+2*spline->splines[0].d)/2 );
+ pos->y = rint( (spline->splines[1].c+2*spline->splines[1].d)/2 );
+}
+
+int ttfFindPointInSC(SplineChar *sc,int pnum,BasePoint *pos,
+ RefChar *bound) {
+ SplineSet *ss;
+ SplinePoint *sp;
+ int last=0, ret;
+ RefChar *refs;
+
+ for ( ss = sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) {
+ for ( sp=ss->first; ; ) {
+ if ( sp->ttfindex==pnum ) {
+ *pos = sp->me;
+return(-1);
+ } else if ( sp->nextcpindex==pnum ) {
+ if ( sp->next!=NULL && sp->next->order2 )
+ *pos = sp->nextcp;
+ else {
+ /* fix this up to be 2 degree bezier control point */
+ UnfigureControls(sp->next,pos);
+ }
+return( -1 );
+ }
+ if ( !sp->nonextcp && last<sp->nextcpindex )
+ last = sp->nextcpindex;
+ else if ( sp->ttfindex!=0xffff )
+ last = sp->ttfindex;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ }
+ for ( refs=sc->layers[ly_fore].refs; refs!=NULL; refs=refs->next ) {
+ if ( refs==bound ) {
+ LogError( _("Invalid point match. Point would be after this reference.\n") );
+return( 0x800000 );
+ }
+ ret = ttfFindPointInSC(refs->sc,pnum-last,pos,NULL);
+ if ( ret==-1 ) {
+ BasePoint p;
+ p.x = refs->transform[0]*pos->x + refs->transform[2]*pos->y + refs->transform[4];
+ p.y = refs->transform[1]*pos->x + refs->transform[3]*pos->y + refs->transform[5];
+ *pos = p;
+return( -1 );
+ }
+ last += ret;
+ }
+return( last ); /* Count of number of points in the character */
+}
+
+static void ttfPointMatch(SplineChar *sc,RefChar *rf) {
+ BasePoint sofar, inref;
+
+ if ( ttfFindPointInSC(sc,rf->match_pt_base,&sofar,rf)!=-1 ||
+ ttfFindPointInSC(rf->sc,rf->match_pt_ref,&inref,NULL)!=-1 ) {
+ LogError( _("Could not match points in composite glyph (%d to %d) when adding %s to %s\n"),
+ rf->match_pt_base, rf->match_pt_ref, rf->sc->name, sc->name);
+return;
+ }
+ rf->transform[4] = sofar.x-inref.x;
+ rf->transform[5] = sofar.y-inref.y;
+}
+
+int ttfFixupRef(SplineChar **chars,int i) {
+ RefChar *ref, *prev, *next;
+
+ if ( chars[i]==NULL ) /* Can happen in ttc files */
+return( false );
+ if ( chars[i]->ticked )
+return( false );
+ chars[i]->ticked = true;
+ prev = NULL;
+ for ( ref=chars[i]->layers[ly_fore].refs; ref!=NULL; ref=next ) {
+ if ( ref->sc!=NULL )
+ break; /* Already done */
+ next = ref->next;
+ if ( !ttfFixupRef(chars,ref->orig_pos)) {
+ if ( prev==NULL )
+ chars[i]->layers[ly_fore].refs = next;
+ else
+ prev->next = next;
+ chunkfree(ref,sizeof(RefChar));
+ } else {
+ ref->sc = chars[ref->orig_pos];
+ ref->adobe_enc = getAdobeEnc(ref->sc->name);
+ if ( ref->point_match )
+ ttfPointMatch(chars[i],ref);
+ SCReinstanciateRefChar(chars[i],ref);
+ SCMakeDependent(chars[i],ref->sc);
+ prev = ref;
+ }
+ }
+ chars[i]->ticked = false;
+return( true );
+}
+
+static void ttfFixupReferences(struct ttfinfo *info) {
+ int i;
+
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_change_line2(_("Fixing up References"));
+#endif
+ for ( i=0; i<info->glyph_cnt; ++i ) {
+ ttfFixupRef(info->chars,i);
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_next();
+#endif
+ }
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_next_stage();
+#endif
+}
+
+static void TtfCopyTableBlindly(struct ttfinfo *info,FILE *ttf,
+ uint32 start,uint32 len,uint32 tag) {
+ struct ttf_table *tab;
+
+ if ( start==0 || len==0 )
+return;
+ if ( len>0x1000000 ) {
+ LogError( _("Unlikely length for table, so I'm ignoring it. %u\n"), len );
+return;
+ }
+
+ tab = chunkalloc(sizeof(struct ttf_table));
+ tab->tag = tag;
+ tab->len = len;
+ tab->data = galloc(len);
+ fseek(ttf,start,SEEK_SET);
+ fread(tab->data,1,len,ttf);
+ tab->next = info->tabs;
+ info->tabs = tab;
+}
+
+static int readttf(FILE *ttf, struct ttfinfo *info, char *filename) {
+ char *oldloc;
+ int i;
+
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_change_stages(3);
+#endif
+ if ( !readttfheader(ttf,info,filename,&info->chosenname)) {
+return( 0 );
+ }
+ oldloc = setlocale(LC_NUMERIC,"C"); /* TrueType doesn't need this but opentype dictionaries do */
+ readttfpreglyph(ttf,info);
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_progress_change_total(info->glyph_cnt);
+#endif
+
+ /* If font only contains bitmaps, then only read bitmaps */
+ if ( (info->glyphlocations_start==0 || info->glyph_length==0) &&
+ info->cff_start==0 && info->typ1_start==0 &&
+ info->bitmapdata_start!=0 && info->bitmaploc_start!=0 )
+ info->onlystrikes = true;
+
+ if ( !info->onlystrikes &&
+ info->glyphlocations_start!=0 && info->glyph_start!=0 &&
+ info->cff_start!=0 ) {
+ char *buts[4];
+ int choice;
+ buts[0] = _("TTF 'glyf'");
+ buts[1] = _("OTF 'CFF '");
+ buts[3] = NULL;
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ buts[2] = _("_Cancel");
+ choice = gwwv_ask(_("Pick a font, any font..."),(const char **) buts,0,2,_("This font contains both a TrueType 'glyf' table and an OpenType 'CFF ' table. FontForge can only deal with one at a time, please pick which one you want to use"));
+#elif defined(FONTFORGE_CONFIG_GTK)
+ buts[2] = GTK_STOCK_CANCEL;
+ choice = gwwv_ask(_("Pick a font, any font..."),(const char **) buts,0,2,_("This font contains both a TrueType 'glyf' table and an OpenType 'CFF ' table. FontForge can only deal with one at a time, please pick which one you want to use"));
+#else
+ choice = 0;
+#endif
+ if ( choice==2 ) {
+ setlocale(LC_NUMERIC,oldloc);
+return( 0 );
+ } else if ( choice==0 )
+ info->cff_start=0;
+ else
+ info->glyph_start = info->glyphlocations_start = 0;
+ }
+
+ if ( info->onlystrikes ) {
+ info->chars = gcalloc(info->glyph_cnt+1,sizeof(SplineChar *));
+ info->to_order2 = new_fonts_are_order2;
+ } else if ( info->glyphlocations_start!=0 && info->glyph_start!=0 ) {
+ info->to_order2 = (!loaded_fonts_same_as_new ||
+ (loaded_fonts_same_as_new && new_fonts_are_order2));
+ /* If it's an apple mm font, then we don't want to change the order */
+ /* This messes up the point count */
+ if ( info->gvar_start!=0 && info->fvar_start!=0 )
+ info->to_order2 = true;
+ readttfglyphs(ttf,info);
+ } else if ( info->cff_start!=0 ) {
+ info->to_order2 = (loaded_fonts_same_as_new && new_fonts_are_order2);
+ if ( !readcffglyphs(ttf,info) ) {
+ setlocale(LC_NUMERIC,oldloc);
+return( 0 );
+ }
+ } else if ( info->typ1_start!=0 ) {
+ if ( !readtyp1glyphs(ttf,info) ) {
+ setlocale(LC_NUMERIC,oldloc);
+return( 0 );
+ }
+ } else {
+ setlocale(LC_NUMERIC,oldloc);
+return( 0 );
+ }
+ if ( info->bitmapdata_start!=0 && info->bitmaploc_start!=0 )
+#ifndef LUA_FF_LIB
+ TTFLoadBitmaps(ttf,info,info->onlyonestrike);
+#endif
+ ;
+ else if ( info->onlystrikes )
+#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ gwwv_post_error( _("No Bitmap Strikes"), _("No (useable) bitmap strikes in this TTF font: %s"), filename==NULL ? "<unknown>" : filename );
+#else
+ ;
+#endif
+ if ( info->onlystrikes && info->bitmaps==NULL ) {
+ free(info->chars);
+ setlocale(LC_NUMERIC,oldloc);
+return( 0 );
+ }
+ if ( info->hmetrics_start!=0 )
+ readttfwidths(ttf,info);
+ else if ( info->bitmapdata_start!=0 && info->bitmaploc_start!=0 )
+ dummywidthsfromstrike(ttf,info);
+ if ( info->vmetrics_start!=0 && info->vhea_start!=0 )
+ readttfvwidths(ttf,info);
+ /* 'cmap' is not meaningful for cid keyed fonts, and not supplied for */
+ /* type42 fonts */
+ if ( info->cidregistry==NULL && info->encoding_start!=0 )
+ readttfencodings(ttf,info,false);
+ if ( info->os2_start!=0 )
+ readttfos2metrics(ttf,info);
+ readttfpostnames(ttf,info); /* If no postscript table we'll guess at names */
+ if ( info->gdef_start!=0 ) /* ligature caret positioning info */
+ readttfgdef(ttf,info);
+ else {
+ if ( info->prop_start!=0 )
+ readttfprop(ttf,info);
+ if ( info->lcar_start!=0 )
+ readttflcar(ttf,info);
+ }
+ if ( info->gasp_start!=0 )
+ readttfgasp(ttf,info);
+ /* read the cvt table before reading variation data */
+ if ( info->to_order2 ) {
+ /* Yes, even though we've looked at maxp already, let's make a blind */
+ /* copy too for those fields we can't compute on our own */
+ /* Like size of twilight zone, etc. */
+ TtfCopyTableBlindly(info,ttf,info->maxp_start,info->maxp_len,CHR('m','a','x','p'));
+#ifndef LUA_FF_LIB
+ TtfCopyTableBlindly(info,ttf,info->cvt_start,info->cvt_len,CHR('c','v','t',' '));
+ TtfCopyTableBlindly(info,ttf,info->fpgm_start,info->fpgm_len,CHR('f','p','g','m'));
+ TtfCopyTableBlindly(info,ttf,info->prep_start,info->prep_len,CHR('p','r','e','p'));
+#endif
+ }
+ for ( i=0; i<info->savecnt; ++i ) if ( info->savetab[i].offset!=0 )
+ TtfCopyTableBlindly(info,ttf,info->savetab[i].offset,info->savetab[i].len,info->savetab[i].tag);
+ /* Do this before reading kerning info */
+ if ( info->to_order2 && info->gvar_start!=0 && info->fvar_start!=0 )
+ readttfvariations(info,ttf);
+ if ( info->gpos_start!=0 ) /* kerning info may live in the gpos table too */
+ readttfgpossub(ttf,info,true);
+ else {
+ if ( info->kern_start!=0 )
+ readttfkerns(ttf,info);
+ if ( info->opbd_start!=0 )
+ readttfopbd(ttf,info);
+ }
+ if ( info->gsub_start!=0 )
+ readttfgpossub(ttf,info,false);
+ else {
+ /* We will default the gsub table later... */;
+ if ( info->morx_start!=0 || info->mort_start!=0 )
+ readttfmort(ttf,info);
+ }
+ if ( info->pfed_start!=0 )
+ pfed_read(ttf,info);
+ if ( info->tex_start!=0 )
+ tex_read(ttf,info);
+ setlocale(LC_NUMERIC,oldloc);
+ if ( !info->onlystrikes && info->glyphlocations_start!=0 && info->glyph_start!=0 )
+ ttfFixupReferences(info);
+ /* Can't fix up any postscript references until we create a SplineFont */
+ /* so the check for cff is delayed. Generally there aren't any cff refs */
+ /* anyway */
+return( true );
+}
+
+
+#ifdef LUA_FF_LIB
+static int readttfinfo(FILE *ttf, struct ttfinfo *info, char *filename) {
+
+ if ( !readttfheader(ttf,info,filename,&info->chosenname)) {
+return( 0 );
+ }
+ readttfpreglyph(ttf,info);
+ if ( info->os2_start!=0 )
+ readttfos2metrics(ttf,info);
+ if ( info->postscript_start!=0 ) {
+ fseek(ttf,info->postscript_start,SEEK_SET);
+ (void)getlong(ttf);
+ info->italicAngle = getfixed(ttf);
+ }
+return( true );
+}
+#endif
+
+static void SymbolFixup(struct ttfinfo *info) {
+ /* convert a two-byte symbol encoding (one using PUA) into expected */
+ /* one-byte encoding. */
+ int i, max;
+ EncMap *map = info->map;
+
+ max = -1;
+ for ( i=map->enccount-1; i>=0; --i ) {
+ if ( map->map[i]==-1 )
+ continue;
+ if ( i>=0xf000 && i<=0xf0ff ) {
+ map->map[i-0xf000] = map->map[i];
+ map->map[i] = -1;
+ continue;
+ }
+ if ( i>max ) max = i;
+ }
+ map->enccount = max;
+}
+
+void AltUniFigure(SplineFont *sf,EncMap *map) {
+ int i,gid;
+
+ if ( map->enc!=&custom ) {
+ for ( i=0; i<map->enccount; ++i ) if ( (gid = map->map[i])!=-1 ) {
+ int uni = UniFromEnc(i,map->enc);
+ AltUniAdd(sf->glyphs[gid],uni);
+ }
+ }
+}
+
+static void UseGivenEncoding(SplineFont *sf,struct ttfinfo *info) {
+ int i;
+ RefChar *rf, *prev, *next;
+
+ sf->glyphs = info->chars;
+ sf->glyphcnt = sf->glyphmax = info->glyph_cnt;
+ for ( i=0; i<sf->glyphcnt; ++i )
+ if ( sf->glyphs[i]!=NULL )
+ sf->glyphs[i]->parent = sf;
+
+ /* A CFF font could contain type1 charstrings, or a type2 font could use */
+ /* the depreciated convention that endchar =~ seac */
+ if ( info->cff_length!=0 )
+ SFInstanciateRefs(sf);
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ for ( rf = sf->glyphs[i]->layers[ly_fore].refs, prev=NULL; rf!=NULL; rf = next ) {
+ next = rf->next;
+ if ( rf->sc==NULL ) {
+ if ( prev==NULL ) sf->glyphs[i]->layers[ly_fore].refs = next;
+ else prev->next = next;
+ RefCharFree(rf);
+ } else {
+ rf->orig_pos = rf->sc->orig_pos;
+ rf->unicode_enc = rf->sc->unicodeenc;
+ prev = rf;
+ }
+ }
+ }
+ sf->map = info->map;
+ sf->uni_interp = info->uni_interp;
+ AltUniFigure(sf,sf->map);
+}
+
+static char *AxisNameConvert(uint32 tag) {
+ char buffer[8];
+
+ if ( tag==CHR('w','g','h','t'))
+return( copy("Weight"));
+ if ( tag==CHR('w','d','t','h'))
+return( copy("Width"));
+ if ( tag==CHR('o','p','s','z'))
+return( copy("OpticalSize"));
+ if ( tag==CHR('s','l','n','t'))
+return( copy("Slant"));
+
+ buffer[0] = tag>>24;
+ buffer[1] = tag>>16;
+ buffer[2] = tag>>8;
+ buffer[3] = tag&0xff;
+ buffer[4] = 0;
+return( copy(buffer ));
+}
+
+static struct macname *FindMacName(struct ttfinfo *info, int strid) {
+ struct macidname *sid;
+
+ for ( sid=info->macstrids; sid!=NULL; sid=sid->next ) {
+ if ( sid->id == strid )
+return( sid->head );
+ }
+return( NULL );
+}
+
+static SplineFont *SFFromTuple(SplineFont *basesf,struct variations *v,int tuple,
+ MMSet *mm, struct ttfinfo *info) {
+ SplineFont *sf;
+ int i;
+ RefChar *r;
+
+ sf = SplineFontEmpty();
+ sf->display_size = basesf->display_size;
+ sf->display_antialias = basesf->display_antialias;
+
+ sf->fontname = MMMakeMasterFontname(mm,tuple,&sf->fullname);
+ sf->familyname = copy(basesf->familyname);
+ sf->weight = copy("All");
+ sf->italicangle = basesf->italicangle;
+ sf->strokewidth = basesf->strokewidth;
+ sf->strokedfont = basesf->strokedfont;
+ sf->upos = basesf->upos;
+ sf->uwidth = basesf->uwidth;
+ sf->ascent = basesf->ascent;
+ sf->vertical_origin = basesf->vertical_origin;
+ sf->hasvmetrics = basesf->hasvmetrics;
+ sf->descent = basesf->descent;
+ sf->kerns = v->tuples[tuple].khead;
+ sf->vkerns = v->tuples[tuple].vkhead;
+ sf->map = basesf->map;
+ sf->mm = mm;
+ sf->glyphmax = sf->glyphcnt = basesf->glyphcnt;
+ sf->glyphs = v->tuples[tuple].chars;
+ sf->order2 = true;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( basesf->glyphs[i]!=NULL ) {
+ sf->glyphs[i]->orig_pos = i;
+ sf->glyphs[i]->parent = sf;
+ }
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ for ( r=sf->glyphs[i]->layers[ly_fore].refs; r!=NULL; r=r->next )
+ SCReinstanciateRefChar(sf->glyphs[i],r);
+ }
+
+ sf->ttf_tables = v->tuples[tuple].cvt;
+
+ v->tuples[tuple].chars = NULL;
+ v->tuples[tuple].khead = NULL;
+ v->tuples[tuple].vkhead = NULL;
+ v->tuples[tuple].cvt = NULL;
+return( sf );
+}
+
+static void MMFillFromVAR(SplineFont *sf, struct ttfinfo *info) {
+ MMSet *mm = chunkalloc(sizeof(MMSet));
+ struct variations *v = info->variations;
+ int i,j;
+
+ sf->mm = mm;
+ mm->normal = sf;
+ mm->apple = true;
+ mm->axis_count = v->axis_count;
+ mm->instance_count = v->tuple_count;
+ mm->instances = galloc(v->tuple_count*sizeof(SplineFont *));
+ mm->positions = galloc(v->tuple_count*v->axis_count*sizeof(real));
+ for ( i=0; i<v->tuple_count; ++i ) for ( j=0; j<v->axis_count; ++j )
+ mm->positions[i*v->axis_count+j] = v->tuples[i].coords[j];
+ mm->defweights = gcalloc(v->tuple_count,sizeof(real)); /* Doesn't apply */
+ mm->axismaps = gcalloc(v->axis_count,sizeof(struct axismap));
+ for ( i=0; i<v->axis_count; ++i ) {
+ mm->axes[i] = AxisNameConvert(v->axes[i].tag);
+ mm->axismaps[i].min = v->axes[i].min;
+ mm->axismaps[i].def = v->axes[i].def;
+ mm->axismaps[i].max = v->axes[i].max;
+ if ( v->axes[i].paircount==0 ) {
+ mm->axismaps[i].points = 3;
+ mm->axismaps[i].blends = galloc(3*sizeof(real));
+ mm->axismaps[i].designs = galloc(3*sizeof(real));
+ mm->axismaps[i].blends[0] = -1; mm->axismaps[i].designs[0] = mm->axismaps[i].min;
+ mm->axismaps[i].blends[1] = 0; mm->axismaps[i].designs[1] = mm->axismaps[i].def;
+ mm->axismaps[i].blends[2] = 1; mm->axismaps[i].designs[2] = mm->axismaps[i].max;
+ } else {
+ mm->axismaps[i].points = v->axes[i].paircount;
+ mm->axismaps[i].blends = galloc(v->axes[i].paircount*sizeof(real));
+ mm->axismaps[i].designs = galloc(v->axes[i].paircount*sizeof(real));
+ for ( j=0; j<v->axes[i].paircount; ++j ) {
+ if ( v->axes[i].mapfrom[j]<=0 ) {
+ mm->axismaps[i].designs[j] = mm->axismaps[i].def +
+ v->axes[i].mapfrom[j]*(mm->axismaps[i].def-mm->axismaps[i].min);
+ } else {
+ mm->axismaps[i].designs[j] = mm->axismaps[i].def +
+ v->axes[i].mapfrom[j]*(mm->axismaps[i].max-mm->axismaps[i].def);
+ }
+ mm->axismaps[i].blends[j] = v->axes[i].mapto[j];
+ }
+ }
+ mm->axismaps[i].axisnames = MacNameCopy(FindMacName(info, v->axes[i].nameid));
+ }
+ mm->named_instance_count = v->instance_count;
+ mm->named_instances = galloc(v->instance_count*sizeof(struct named_instance));
+ for ( i=0; i<v->instance_count; ++i ) {
+ mm->named_instances[i].coords = v->instances[i].coords;
+ v->instances[i].coords = NULL;
+ mm->named_instances[i].names = MacNameCopy(FindMacName(info, v->instances[i].nameid));
+ }
+ for ( i=0; i<mm->instance_count; ++i )
+ mm->instances[i] = SFFromTuple(sf,v,i,mm,info);
+ VariationFree(info);
+}
+
+static void SFRelativeWinAsDs(SplineFont *sf) {
+ if ( !sf->pfminfo.winascent_add || !sf->pfminfo.windescent_add ||
+ !sf->pfminfo.hheadascent_add || !sf->pfminfo.hheaddescent_add ) {
+ DBounds b;
+ CIDFindBounds(sf,&b);
+ if ( !sf->pfminfo.winascent_add ) {
+ sf->pfminfo.winascent_add = true;
+ if ( sf->pfminfo.os2_winascent < sf->ascent/8 ) {
+ /* There was a bug for a while which gave us really bad values */
+ sf->pfminfo.os2_winascent = 0;
+ sf->pfminfo.windescent_add = true;
+ sf->pfminfo.os2_windescent = 0;
+ } else
+ sf->pfminfo.os2_winascent -= b.maxy;
+ }
+ if ( !sf->pfminfo.windescent_add ) {
+ sf->pfminfo.windescent_add = true;
+ sf->pfminfo.os2_windescent += b.miny;
+ }
+ if ( !sf->pfminfo.hheadascent_add ) {
+ sf->pfminfo.hheadascent_add = true;
+ sf->pfminfo.hhead_ascent -= b.maxy;
+ }
+ if ( !sf->pfminfo.hheaddescent_add ) {
+ sf->pfminfo.hheaddescent_add = true;
+ sf->pfminfo.hhead_descent -= b.miny;
+ }
+ }
+ if ( !sf->pfminfo.typoascent_add ) {
+ sf->pfminfo.typoascent_add = true;
+ sf->pfminfo.os2_typoascent -= sf->ascent;
+ }
+ if ( !sf->pfminfo.typodescent_add ) {
+ sf->pfminfo.typodescent_add = true;
+ sf->pfminfo.os2_typodescent -= -sf->descent;
+ }
+}
+
+static void PsuedoEncodeUnencoded(EncMap *map,struct ttfinfo *info) {
+ int extras, base;
+ int i;
+
+ for ( i=0; i<info->glyph_cnt; ++i )
+ if ( info->chars[i]!=NULL )
+ info->chars[i]->ticked = false;
+ for ( i=0; i<map->enccount; ++i )
+ if ( map->map[i]!=-1 )
+ info->chars[map->map[i]]->ticked = true;
+ extras = 0;
+ for ( i=0; i<info->glyph_cnt; ++i )
+ if ( info->chars[i]!=NULL && !info->chars[i]->ticked )
+ ++extras;
+ if ( extras!=0 ) {
+ if ( map->enccount<=256 )
+ base = 256;
+ else if ( map->enccount<=65536 )
+ base = 65536;
+ else if ( map->enccount<=17*65536 )
+ base = 17*65536;
+ else
+ base = map->enccount;
+ if ( base+extras>map->encmax ) {
+ map->map = grealloc(map->map,(base+extras)*sizeof(int));
+ memset(map->map+map->enccount,-1,(base+extras-map->enccount)*sizeof(int));
+ map->encmax = base+extras;
+ }
+ map->enccount = base+extras;
+ extras = 0;
+ for ( i=0; i<info->glyph_cnt; ++i )
+ if ( info->chars[i]!=NULL && !info->chars[i]->ticked )
+ map->map[base+extras++] = i;
+ }
+}
+
+static void MapDoBack(EncMap *map,struct ttfinfo *info) {
+ int i;
+
+ if ( map==NULL ) /* CID fonts */
+return;
+ free(map->backmap); /* CFF files have this */
+ map->backmax = info->glyph_cnt;
+ map->backmap = galloc(info->glyph_cnt*sizeof(int));
+ memset(map->backmap,-1,info->glyph_cnt*sizeof(int));
+ for ( i = map->enccount-1; i>=0; --i )
+ if ( map->map[i]>=0 && map->map[i]<info->glyph_cnt )
+ if ( map->backmap[map->map[i]]==-1 )
+ map->backmap[map->map[i]] = i;
+}
+
+static SplineFont *SFFillFromTTF(struct ttfinfo *info) {
+ SplineFont *sf, *_sf;
+ int i,k;
+ BDFFont *bdf;
+ SplineChar *sc;
+ struct ttf_table *last[2], *tab, *next;
+
+
+ sf = SplineFontEmpty();
+#ifdef LUA_FF_LIB
+ sf->units_per_em = info->emsize;
+#endif
+ sf->display_size = -default_fv_font_size;
+ sf->display_antialias = default_fv_antialias;
+ sf->fontname = info->fontname;
+ sf->fullname = info->fullname;
+ sf->familyname = info->familyname;
+ sf->chosenname = info->chosenname;
+ sf->onlybitmaps = info->onlystrikes;
+ sf->order2 = info->to_order2;
+ sf->comments = info->fontcomments;
+
+ sf->creationtime = info->creationtime;
+ sf->modificationtime = info->modificationtime;
+
+ sf->design_size = info->design_size;
+ sf->design_range_bottom = info->design_range_bottom;
+ sf->design_range_top = info->design_range_top;
+ sf->fontstyle_id = info->fontstyle_id;
+ sf->fontstyle_name = info->fontstyle_name;
+
+ sf->gasp_cnt = info->gasp_cnt;
+ sf->gasp = info->gasp;
+
+ sf->texdata = info->texdata;
+
+ sf->mark_class_cnt = info->mark_class_cnt;
+ sf->mark_classes = info->mark_classes;
+ sf->mark_class_names = info->mark_class_names;
+
+ if ( info->fd!=NULL ) { /* Special hack for type42 fonts */
+ sf->fontname = copy(info->fd->fontname);
+ sf->uniqueid = info->fd->uniqueid;
+ sf->xuid = XUIDFromFD(info->fd->xuid);
+ if ( info->fd->fontinfo!=NULL ) {
+ sf->familyname = utf8_verify_copy(info->fd->fontinfo->familyname);
+ sf->fullname = utf8_verify_copy(info->fd->fontinfo->fullname);
+ sf->copyright = utf8_verify_copy(info->fd->fontinfo->notice);
+ sf->weight = utf8_verify_copy(info->fd->fontinfo->weight);
+ sf->version = utf8_verify_copy(info->fd->fontinfo->version);
+ sf->italicangle = info->fd->fontinfo->italicangle;
+ sf->upos = info->fd->fontinfo->underlineposition*(sf->ascent+sf->descent);
+ sf->uwidth = info->fd->fontinfo->underlinethickness*(sf->ascent+sf->descent);
+ }
+ }
+
+ if ( sf->fontname==NULL ) {
+ sf->fontname = EnforcePostScriptName(sf->fullname);
+ if ( sf->fontname==NULL )
+ sf->fontname = EnforcePostScriptName(sf->familyname);
+ if ( sf->fontname==NULL ) sf->fontname = EnforcePostScriptName("UntitledTTF");
+ }
+ if ( sf->fullname==NULL ) sf->fullname = copy( sf->fontname );
+ if ( sf->familyname==NULL ) sf->familyname = copy( sf->fontname );
+ if ( sf->weight==NULL ) {
+ if ( info->weight != NULL )
+ sf->weight = info->weight;
+ else if ( info->pfminfo.pfmset )
+ sf->weight = copy( info->pfminfo.weight <= 100 ? "Thin" :
+ info->pfminfo.weight <= 200 ? "Extra-Light" :
+ info->pfminfo.weight <= 300 ? "Light" :
+ info->pfminfo.weight <= 400 ? "Book" :
+ info->pfminfo.weight <= 500 ? "Medium" :
+ info->pfminfo.weight <= 600 ? "Demi" :
+ info->pfminfo.weight <= 700 ? "Bold" :
+ info->pfminfo.weight <= 800 ? "Heavy" :
+ "Black" );
+ else
+ sf->weight = copy("");
+ } else
+ free( info->weight );
+ if ( sf->copyright==NULL )
+ sf->copyright = info->copyright;
+ else
+ free( info->copyright );
+ sf->version = info->version;
+ sf->italicangle = info->italicAngle;
+ sf->strokewidth = info->strokewidth;
+ sf->strokedfont = info->strokedfont;
+ sf->upos = info->upos;
+ sf->uwidth = info->uwidth;
+ sf->ascent = info->ascent;
+ sf->vertical_origin = info->vertical_origin;
+ if ( info->vhea_start!=0 && info->vmetrics_start!=0 )
+ sf->hasvmetrics = true;
+ sf->descent = info->descent;
+ sf->private = info->private;
+ sf->xuid = info->xuid;
+ sf->uniqueid = info->uniqueid;
+ sf->pfminfo = info->pfminfo;
+ sf->os2_version = info->os2_version;
+ sf->use_typo_metrics = info->use_typo_metrics;
+ sf->weight_width_slope_only = info->weight_width_slope_only;
+ sf->head_optimized_for_cleartype = info->optimized_for_cleartype;
+ sf->gasp_version = info->gasp_version;
+ sf->names = info->names;
+ sf->anchor = info->ahead;
+ sf->kerns = info->khead;
+ sf->vkerns = info->vkhead;
+ sf->possub = info->possub;
+ sf->sm = info->sm;
+ sf->features = info->features;
+ sf->gpos_lookups = info->gpos_lookups;
+ sf->gsub_lookups = info->gsub_lookups;
+
+ last[0] = sf->ttf_tables;
+ last[1] = NULL;
+ for ( tab=info->tabs; tab!=NULL; tab = next ) {
+ next = tab->next;
+ if ( tab->tag==CHR('f','p','g','m') || tab->tag==CHR('p','r','e','p') ||
+ tab->tag==CHR('c','v','t',' ') || tab->tag==CHR('m','a','x','p')) {
+ if ( last[0]==NULL )
+ sf->ttf_tables = tab;
+ else
+ last[0]->next = tab;
+ last[0] = tab;
+ } else {
+ if ( last[1]==NULL )
+ sf->ttf_tab_saved = tab;
+ else
+ last[1]->next = tab;
+ last[1] = tab;
+ }
+ tab->next = NULL;
+ }
+
+ if ( info->twobytesymbol )
+ /* rework ms symbol encodings */
+ SymbolFixup(info);
+ if ( info->map==NULL && info->subfonts==NULL ) /* Can happen when reading a ttf from a pdf */
+ info->map = EncMapFromEncoding(sf,FindOrMakeEncoding("original"));
+ if ( info->subfontcnt==0 )
+ PsuedoEncodeUnencoded(info->map,info);
+ MapDoBack(info->map,info);
+ sf->map = info->map;
+ sf->cidregistry = info->cidregistry;
+ sf->ordering = info->ordering;
+ sf->supplement = info->supplement;
+ sf->cidversion = info->cidfontversion;
+ sf->bitmaps = info->bitmaps;
+ for ( bdf = info->bitmaps; bdf!=NULL; bdf = bdf->next ) {
+ bdf->sf = sf;
+ }
+ SFDefaultAscent(sf);
+
+ for ( i=0; i<info->glyph_cnt; ++i ) if ( info->chars[i]!=NULL ) {
+ SCOrderAP(info->chars[i]);
+ }
+
+ if ( info->subfontcnt == 0 ) {
+ UseGivenEncoding(sf,info);
+ } else {
+ sf->subfontcnt = info->subfontcnt;
+ sf->subfonts = info->subfonts;
+ free(info->chars); /* This is the GID->char index, don't need it now */
+ for ( i=0; i<sf->subfontcnt; ++i ) {
+ sf->subfonts[i]->cidmaster = sf;
+ sf->subfonts[i]->vertical_origin = sf->vertical_origin;
+ sf->subfonts[i]->hasvmetrics = sf->hasvmetrics;
+ }
+ }
+ TTF_PSDupsDefault(sf);
+#if 0
+ if ( info->gsub_start==0 && info->mort_start==0 && info->morx_start==0 ) {
+ /* Get default ligature values, etc. */
+ k=0;
+ do {
+ _sf = k<sf->subfontcnt?sf->subfonts[k]:sf;
+ for ( i=0; i<sf->glyphcnt; ++i ) {
+ if ( _sf->glyphs[i]!=NULL ) /* Might be null in ttc files */
+ SCLigDefault(_sf->glyphs[i]);
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+ }
+#endif
+
+ /* I thought the languages were supposed to be ordered, but it seems */
+ /* that is not always the case. Order everything, just in case */
+ { int isgpos; OTLookup *otl;
+ for ( isgpos=0; isgpos<2; ++isgpos )
+ for ( otl= isgpos? sf->gpos_lookups:sf->gsub_lookups; otl!=NULL; otl=otl->next )
+ otl->features = FLOrder(otl->features);
+ }
+
+ if ( info->variations!=NULL )
+ MMFillFromVAR(sf,info);
+
+ if ( info->cff_length!=0 && !sf->order2 ) {
+ /* Clean up the hint masks, We create an initial hintmask whether we */
+ /* need it or not */
+ k=0;
+ do {
+ _sf = k<sf->subfontcnt?sf->subfonts[k]:sf;
+ for ( i=0; i<sf->glyphcnt; ++i ) {
+ if ( (sc = _sf->glyphs[i])!=NULL && !sc->hconflicts && !sc->vconflicts &&
+ sc->layers[ly_fore].splines!=NULL ) {
+ chunkfree( sc->layers[ly_fore].splines->first->hintmask,sizeof(HintMask) );
+ sc->layers[ly_fore].splines->first->hintmask = NULL;
+ }
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+ }
+ SFRelativeWinAsDs(sf);
+ free(info->savetab);
+return( sf );
+}
+
+SplineFont *_SFReadTTF(FILE *ttf, int flags,enum openflags openflags, char *filename,struct fontdict *fd) {
+ struct ttfinfo info;
+ int ret;
+
+ memset(&info,'\0',sizeof(struct ttfinfo));
+ info.onlystrikes = (flags&ttf_onlystrikes)?1:0;
+ info.onlyonestrike = (flags&ttf_onlyonestrike)?1:0;
+ info.use_typo_metrics = true;
+ info.fd = fd;
+ ret = readttf(ttf,&info,filename);
+ if ( !ret )
+return( NULL );
+return( SFFillFromTTF(&info));
+}
+
+SplineFont *SFReadTTF(char *filename, int flags, enum openflags openflags) {
+ FILE *ttf;
+ SplineFont *sf;
+ char *temp=filename, *pt, *lparen;
+
+ pt = strrchr(filename,'/');
+ if ( pt==NULL ) pt = filename;
+ if ( (lparen=strchr(pt,'('))!=NULL && strchr(lparen,')')!=NULL ) {
+ temp = copy(filename);
+ pt = temp + (lparen-filename);
+ *pt = '\0';
+ }
+ ttf = fopen(temp,"rb");
+ if ( temp!=filename ) free(temp);
+ if ( ttf==NULL )
+return( NULL );
+
+ sf = _SFReadTTF(ttf,flags,openflags,filename,NULL);
+ fclose(ttf);
+return( sf );
+}
+
+#ifdef LUA_FF_LIB
+
+/* I am not sure what happens to the ttinfo struct's members.
+ perhaps some need free()-ing
+*/
+
+static SplineFont *SFFillFromTTFInfo(struct ttfinfo *info) {
+ SplineFont *sf ;
+
+ sf = SplineFontEmpty();
+
+ sf->fontname = info->fontname;
+ sf->fullname = info->fullname;
+ sf->familyname = info->familyname;
+
+ if ( info->fd!=NULL ) { /* Special hack for type42 fonts */
+ sf->fontname = copy(info->fd->fontname);
+ if ( info->fd->fontinfo!=NULL ) {
+ sf->familyname = utf8_verify_copy(info->fd->fontinfo->familyname);
+ sf->fullname = utf8_verify_copy(info->fd->fontinfo->fullname);
+ sf->weight = utf8_verify_copy(info->fd->fontinfo->weight);
+ }
+ }
+ if ( sf->fontname==NULL ) sf->fontname = EnforcePostScriptName(sf->fullname);
+ if ( sf->fontname==NULL ) sf->fontname = EnforcePostScriptName(sf->familyname);
+ if ( sf->fontname==NULL ) sf->fontname = EnforcePostScriptName("UntitledTTF");
+
+ if ( sf->fullname==NULL ) sf->fullname = copy( sf->fontname );
+ if ( sf->familyname==NULL ) sf->familyname = copy( sf->fontname );
+ if ( sf->weight==NULL ) {
+ if ( info->weight != NULL )
+ sf->weight = info->weight;
+ else if ( info->pfminfo.pfmset )
+ sf->weight = copy( info->pfminfo.weight <= 100 ? "Thin" :
+ info->pfminfo.weight <= 200 ? "Extra-Light" :
+ info->pfminfo.weight <= 300 ? "Light" :
+ info->pfminfo.weight <= 400 ? "Book" :
+ info->pfminfo.weight <= 500 ? "Medium" :
+ info->pfminfo.weight <= 600 ? "Demi" :
+ info->pfminfo.weight <= 700 ? "Bold" :
+ info->pfminfo.weight <= 800 ? "Heavy" :
+ "Black" );
+ else
+ sf->weight = copy("");
+ } else
+ free( info->weight );
+ sf->version = info->version;
+ sf->italicangle = info->italicAngle;
+
+return( sf );
+}
+
+SplineFont *_SFReadTTFInfo(FILE *ttf, int flags,enum openflags openflags, char *filename,struct fontdict *fd) {
+ struct ttfinfo info;
+ int ret;
+
+ memset(&info,'\0',sizeof(struct ttfinfo));
+ info.onlystrikes = (flags&ttf_onlystrikes)?1:0;
+ info.onlyonestrike = (flags&ttf_onlyonestrike)?1:0;
+ info.use_typo_metrics = true;
+ info.fd = fd;
+ ret = readttfinfo(ttf,&info,filename);
+ if ( !ret )
+return( NULL );
+return( SFFillFromTTFInfo(&info));
+}
+
+
+SplineFont *SFReadTTFInfo(char *filename, int flags, enum openflags openflags) {
+ FILE *ttf;
+ SplineFont *sf;
+ char *temp=filename, *pt, *lparen;
+
+ pt = strrchr(filename,'/');
+ if ( pt==NULL ) pt = filename;
+ if ( (lparen=strchr(pt,'('))!=NULL && strchr(lparen,')')!=NULL ) {
+ temp = copy(filename);
+ pt = temp + (lparen-filename);
+ *pt = '\0';
+ }
+ ttf = fopen(temp,"rb");
+ if ( temp!=filename ) free(temp);
+ if ( ttf==NULL )
+return( NULL );
+
+ sf = _SFReadTTFInfo(ttf,flags,openflags,filename,NULL);
+ fclose(ttf);
+return( sf );
+}
+#endif
+
+
+SplineFont *_CFFParse(FILE *temp,int len, char *fontsetname) {
+ struct ttfinfo info;
+
+ memset(&info,'\0',sizeof(info));
+ info.cff_start = 0;
+ info.cff_length = len;
+ info.barecff = true;
+ if ( !readcffglyphs(temp,&info) )
+return( NULL );
+return( SFFillFromTTF(&info));
+}
+
+SplineFont *CFFParse(char *filename) {
+ FILE *cff = fopen(filename,"rb");
+ SplineFont *sf;
+ long len;
+
+ if ( cff == NULL )
+return( NULL );
+ fseek(cff,0,SEEK_END);
+ len = ftell(cff);
+ fseek(cff,0,SEEK_SET);
+ sf = _CFFParse(cff,len,NULL);
+ fclose(cff);
+return( sf );
+}
+
+#ifdef LUA_FF_LIB
+SplineFont *_CFFParseInfo(FILE *temp,int len, char *fontsetname) {
+ struct ttfinfo info;
+
+ memset(&info,'\0',sizeof(info));
+ info.cff_start = 0;
+ info.cff_length = len;
+ info.barecff = true;
+ if ( !readcffglyphs(temp,&info) )
+return( NULL );
+return( SFFillFromTTFInfo(&info));
+}
+
+SplineFont *CFFParseInfo(char *filename) {
+ FILE *cff = fopen(filename,"rb");
+ SplineFont *sf;
+ long len;
+
+ if ( cff == NULL )
+return( NULL );
+ fseek(cff,0,SEEK_END);
+ len = ftell(cff);
+ fseek(cff,0,SEEK_SET);
+ sf = _CFFParseInfo(cff,len,NULL);
+ fclose(cff);
+return( sf );
+}
+#endif
+
+char **NamesReadCFF(char *filename) {
+ FILE *cff = fopen(filename,"rb");
+ int32 hdrsize, offsize;
+ char **fontnames;
+
+ if ( cff==NULL )
+return( NULL );
+ if ( getc(cff)!='\1' ) { /* Major version */
+ LogError( _("CFF version mismatch\n") );
+ fclose(cff);
+return( NULL );
+ }
+ getc(cff); /* Minor version */
+ hdrsize = getc(cff);
+ offsize = getc(cff);
+ if ( hdrsize!=4 )
+ fseek(cff,hdrsize,SEEK_SET);
+ fontnames = readcfffontnames(cff,NULL);
+ fclose(cff);
+return( fontnames );
+}
+
+char **NamesReadTTF(char *filename) {
+ FILE *ttf = fopen(filename,"rb");
+ int32 version, cnt, *offsets;
+ int i,j;
+ char **ret = NULL;
+ char *temp;
+
+ if ( ttf==NULL )
+return( NULL );
+ version=getlong(ttf);
+ if ( version==CHR('t','t','c','f')) {
+ /* TTCF version = */ getlong(ttf);
+ cnt = getlong(ttf);
+ offsets = galloc(cnt*sizeof(int32));
+ for ( i=0; i<cnt; ++i )
+ offsets[i] = getlong(ttf);
+ ret = galloc((cnt+1)*sizeof(char *));
+ for ( i=j=0; i<cnt; ++i ) {
+ temp = TTFGetFontName(ttf,offsets[i],0);
+ if ( temp!=NULL )
+ ret[j++] = temp;
+ }
+ ret[j] = NULL;
+ free(offsets);
+ } else {
+ temp = TTFGetFontName(ttf,0,0);
+ if ( temp!=NULL ) {
+ ret = galloc(2*sizeof(char *));
+ ret[0] = temp;
+ ret[1] = NULL;
+ }
+ }
+ fclose(ttf);
+return(ret);
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/parsettfatt.c b/Build/source/libs/luafontforge/fontforge/fontforge/parsettfatt.c
new file mode 100644
index 00000000000..6f068ec921d
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/parsettfatt.c
@@ -0,0 +1,4635 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include <chardata.h>
+#include <utype.h>
+#include <ustring.h>
+#include <math.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <ggadget.h> /* For GTextInfo */
+#include "ttf.h"
+
+static uint16 *getAppleClassTable(FILE *ttf, int classdef_offset, int cnt, int sub, int div) {
+ uint16 *class = gcalloc(cnt,sizeof(uint16));
+ int first, i, n;
+ /* Apple stores its class tables as containing offsets. I find it hard to */
+ /* think that way and convert them to indeces (by subtracting off a base */
+ /* offset and dividing by the item's size) before doing anything else */
+
+ fseek(ttf,classdef_offset,SEEK_SET);
+ first = getushort(ttf);
+ n = getushort(ttf);
+ if ( first+n-1>=cnt )
+ LogError( _("Bad Apple Kern Class\n") );
+ for ( i=0; i<n && i+first<cnt; ++i )
+ class[first+i] = (getushort(ttf)-sub)/div;
+return( class );
+}
+
+static char **ClassToNames(struct ttfinfo *info,int class_cnt,uint16 *class,int glyph_cnt) {
+ char **ret = galloc(class_cnt*sizeof(char *));
+ int *lens = gcalloc(class_cnt,sizeof(int));
+ int i;
+
+ ret[0] = NULL;
+ for ( i=0 ; i<glyph_cnt; ++i ) if ( class[i]!=0 && info->chars[i]!=NULL && class[i]<class_cnt )
+ lens[class[i]] += strlen(info->chars[i]->name)+1;
+ for ( i=1; i<class_cnt ; ++i )
+ ret[i] = galloc(lens[i]+1);
+ memset(lens,0,class_cnt*sizeof(int));
+ for ( i=0 ; i<glyph_cnt; ++i ) if ( class[i]!=0 && info->chars[i]!=NULL ) {
+ if ( class[i]<class_cnt ) {
+ strcpy(ret[class[i]]+lens[class[i]], info->chars[i]->name );
+ lens[class[i]] += strlen(info->chars[i]->name)+1;
+ ret[class[i]][lens[class[i]]-1] = ' ';
+ } else
+ LogError( _("Class index out of range %d (must be <%d)\n"),class[i], class_cnt );
+ }
+ for ( i=1; i<class_cnt ; ++i )
+ if ( lens[i]==0 )
+ ret[i][0] = '\0';
+ else
+ ret[i][lens[i]-1] = '\0';
+ free(lens);
+return( ret );
+}
+
+static char *CoverageMinusClasses(uint16 *coverageglyphs,uint16 *classed,
+ struct ttfinfo *info ) {
+ int i, j, len;
+ uint8 *glyphs = gcalloc(info->glyph_cnt,1);
+ char *ret;
+
+ for ( i=0; coverageglyphs[i]!=0xffff; ++i )
+ glyphs[coverageglyphs[i]] = 1;
+ for ( i=0; i<info->glyph_cnt; ++i )
+ if ( classed[i]!=0 )
+ glyphs[i] = 0;
+ for ( i=0; i<info->glyph_cnt; ++i )
+ if ( glyphs[i]!=0 )
+ break;
+ /* coverage table matches glyphs in classes. No need for special treatment*/
+ if ( i==info->glyph_cnt ) {
+ free(glyphs);
+return( NULL );
+ }
+ /* Otherwise we need to generate a class string of glyph names in the coverage */
+ /* table but not in any class. These become the glyphs in class 0 */
+ ret = NULL;
+ for ( j=0; j<2; ++j ) {
+ len = 0;
+ for ( i=0; i<info->glyph_cnt; ++i ) {
+ if ( glyphs[i]!=0 ) {
+ if ( j ) {
+ strcpy( ret+len, info->chars[i]->name );
+ strcat( ret+len, " ");
+ }
+ len += strlen(info->chars[i]->name)+1;
+ }
+ }
+ if ( j==0 )
+ ret = galloc(len+1);
+ else
+ ret[len-1] = '\0';
+ }
+ free(glyphs);
+return( ret );
+}
+
+static int ClassFindCnt(uint16 *class,int tot) {
+ int i, max=0;
+
+ for ( i=0; i<tot; ++i )
+ if ( class[i]>max ) max = class[i];
+return( max+1 );
+}
+
+static int cmpuint16(const void *u1, const void *u2) {
+return( ((int) *((const uint16 *) u1)) - ((int) *((const uint16 *) u2)) );
+}
+
+static char *GlyphsToNames(struct ttfinfo *info,uint16 *glyphs, int make_uniq) {
+ int i, j, len, off;
+ char *ret, *pt;
+
+ if ( glyphs==NULL )
+return( copy(""));
+
+ /* Adobe produces coverage tables containing duplicate glyphs in */
+ /* GaramondPremrPro.otf. We want unique glyphs, so enforce that */
+ if ( make_uniq ) {
+ for ( i=0 ; glyphs[i]!=0xffff; ++i );
+ qsort(glyphs,i,sizeof(uint16),cmpuint16);
+ for ( i=0; glyphs[i]!=0xffff; ++i ) {
+ if ( glyphs[i+1]==glyphs[i] ) {
+ for ( j=i+1; glyphs[j]==glyphs[i]; ++j );
+ off = j-i -1;
+ for ( j=i+1; ; ++j ) {
+ glyphs[j] = glyphs[j+off];
+ if ( glyphs[j]==0xffff )
+ break;
+ }
+ }
+ }
+ }
+
+ for ( i=len=0 ; glyphs[i]!=0xffff; ++i )
+ if ( info->chars[glyphs[i]]!=NULL )
+ len += strlen(info->chars[glyphs[i]]->name)+1;
+ ret = pt = galloc(len+1); *pt = '\0';
+ for ( i=0 ; glyphs[i]!=0xffff; ++i ) if ( info->chars[glyphs[i]]!=NULL ) {
+ strcpy(pt,info->chars[glyphs[i]]->name);
+ pt += strlen(pt);
+ *pt++ = ' ';
+ }
+ if ( pt>ret ) pt[-1] = '\0';
+return( ret );
+}
+
+struct scripts {
+ uint32 offset;
+ uint32 tag;
+ int langcnt; /* the default language is included as a */
+ struct language { /* normal entry with lang tag 'dflt' */
+ uint32 tag;
+ uint32 offset;
+ uint16 req; /* required feature index. 0xffff for null */
+ int fcnt;
+ uint16 *features;
+ } *languages;
+};
+
+struct feature {
+ uint32 offset;
+ uint32 tag;
+ int lcnt;
+ uint16 *lookups;
+};
+
+struct lookup {
+ uint16 type;
+ uint16 flags;
+ /* uint16 lookup; */ /* ???? can't imagine what this is*/
+ uint32 offset;
+ int subtabcnt;
+ int32 *subtab_offsets;
+ OTLookup *otlookup;
+};
+
+enum gsub_inusetype { git_normal, git_justinuse, git_findnames };
+
+static uint16 *getCoverageTable(FILE *ttf, int coverage_offset, struct ttfinfo *info) {
+ int format, cnt, i,j, rcnt;
+ uint16 *glyphs=NULL;
+ int start, end, ind, max;
+
+ fseek(ttf,coverage_offset,SEEK_SET);
+ format = getushort(ttf);
+ if ( format==1 ) {
+ cnt = getushort(ttf);
+ glyphs = galloc((cnt+1)*sizeof(uint16));
+ if ( ftell(ttf)+2*cnt > info->g_bounds ) {
+ LogError( _("coverage table extends beyond end of table\n") );
+ if ( ftell(ttf)>info->g_bounds )
+return( NULL );
+ cnt = (info->g_bounds-ftell(ttf))/2;
+ }
+ for ( i=0; i<cnt; ++i ) {
+ if ( cnt&0xffff0000 )
+ LogError( _("Bad count.\n"));
+ glyphs[i] = getushort(ttf);
+ if ( feof(ttf) ) {
+ LogError( _("End of file found in coverage table.\n") );
+ free(glyphs);
+return( NULL );
+ }
+ if ( glyphs[i]>=info->glyph_cnt ) {
+ LogError( _("Bad coverage table. Glyph %d out of range [0,%d)\n"), glyphs[i], info->glyph_cnt );
+ glyphs[i] = 0;
+ }
+ }
+ } else if ( format==2 ) {
+ glyphs = gcalloc((max=256),sizeof(uint16));
+ rcnt = getushort(ttf); cnt = 0;
+ if ( ftell(ttf)+6*rcnt > info->g_bounds ) {
+ LogError( _("coverage table extends beyond end of table\n") );
+ rcnt = (info->g_bounds-ftell(ttf))/6;
+ }
+
+ for ( i=0; i<rcnt; ++i ) {
+ start = getushort(ttf);
+ end = getushort(ttf);
+ ind = getushort(ttf);
+ if ( feof(ttf) ) {
+ LogError( _("End of file found in coverage table.\n") );
+ free(glyphs);
+return( NULL );
+ }
+ if ( start>end || end>=info->glyph_cnt ) {
+ LogError( _("Bad coverage table. Glyph range %d-%d out of range [0,%d)\n"), start, end, info->glyph_cnt );
+ start = end = 0;
+ }
+ if ( ind+end-start+2 >= max ) {
+ int oldmax = max;
+ max = ind+end-start+2;
+ glyphs = grealloc(glyphs,max*sizeof(uint16));
+ memset(glyphs+oldmax,0,(max-oldmax)*sizeof(uint16));
+ }
+ for ( j=start; j<=end; ++j ) {
+ glyphs[j-start+ind] = j;
+ if ( j>=info->glyph_cnt )
+ glyphs[j-start+ind] = 0;
+ }
+ if ( ind+end-start+1>cnt )
+ cnt = ind+end-start+1;
+ }
+ } else {
+ LogError( _("Bad format for coverage table %d\n"), format );
+return( NULL );
+ }
+ glyphs[cnt] = 0xffff;
+
+return( glyphs );
+}
+
+struct valuerecord {
+ int16 xplacement, yplacement;
+ int16 xadvance, yadvance;
+ uint16 offXplaceDev, offYplaceDev;
+ uint16 offXadvanceDev, offYadvanceDev;
+};
+
+static uint16 *getClassDefTable(FILE *ttf, int classdef_offset, int cnt,
+ uint32 g_bounds) {
+ int format, i, j;
+ uint16 start, glyphcnt, rangecnt, end, class;
+ uint16 *glist=NULL;
+ int warned = false;
+
+ fseek(ttf, classdef_offset, SEEK_SET);
+ glist = gcalloc(cnt,sizeof(uint16)); /* Class 0 is default */
+ format = getushort(ttf);
+ if ( format==1 ) {
+ start = getushort(ttf);
+ glyphcnt = getushort(ttf);
+ if ( start+(int) glyphcnt>cnt ) {
+ LogError( _("Bad class def table. start=%d cnt=%d, max glyph=%d\n"), start, glyphcnt, cnt );
+ glyphcnt = cnt-start;
+ } else if ( ftell(ttf)+2*glyphcnt > g_bounds ) {
+ LogError( _("Class definition table extends beyond end of table\n") );
+ glyphcnt = (g_bounds-ftell(ttf))/2;
+ }
+ for ( i=0; i<glyphcnt; ++i )
+ glist[start+i] = getushort(ttf);
+ } else if ( format==2 ) {
+ rangecnt = getushort(ttf);
+ if ( ftell(ttf)+6*rangecnt > g_bounds ) {
+ LogError( _("Class definition table extends beyond end of table\n") );
+ rangecnt = (g_bounds-ftell(ttf))/6;
+ }
+ for ( i=0; i<rangecnt; ++i ) {
+ start = getushort(ttf);
+ end = getushort(ttf);
+ if ( start>end || end>=cnt )
+ LogError( _("Bad class def table. Glyph range %d-%d out of range [0,%d)\n"), start, end, cnt );
+ class = getushort(ttf);
+ for ( j=start; j<=end; ++j ) if ( j<cnt )
+ glist[j] = class;
+ }
+ } else
+ LogError( _("Unknown class table format: %d\n"), format );
+
+ /* Do another validity test */
+ for ( i=0; i<cnt; ++i ) {
+ if ( glist[i]>=cnt+1 ) {
+ if ( !warned ) {
+ LogError( _("Nonsensical class assigned to a glyph-- class=%d is too big. Glyph=%d\n"),
+ glist[i], i );
+ warned = true;
+ }
+ glist[i] = 0;
+ }
+ }
+
+return glist;
+}
+
+static void readvaluerecord(struct valuerecord *vr,int vf,FILE *ttf) {
+ memset(vr,'\0',sizeof(struct valuerecord));
+ if ( vf&1 )
+ vr->xplacement = getushort(ttf);
+ if ( vf&2 )
+ vr->yplacement = getushort(ttf);
+ if ( vf&4 )
+ vr->xadvance = getushort(ttf);
+ if ( vf&8 )
+ vr->yadvance = getushort(ttf);
+ if ( vf&0x10 )
+ vr->offXplaceDev = getushort(ttf);
+ if ( vf&0x20 )
+ vr->offYplaceDev = getushort(ttf);
+ if ( vf&0x40 )
+ vr->offXadvanceDev = getushort(ttf);
+ if ( vf&0x80 )
+ vr->offYadvanceDev = getushort(ttf);
+}
+
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+static void ReadDeviceTable(FILE *ttf,DeviceTable *adjust,uint32 devtab) {
+ long here;
+ int pack;
+ int w,b,i,c;
+
+ if ( devtab==0 )
+return;
+ here = ftell(ttf);
+ fseek(ttf,devtab,SEEK_SET);
+ adjust->first_pixel_size = getushort(ttf);
+ adjust->last_pixel_size = getushort(ttf);
+ pack = getushort(ttf);
+ if ( adjust->first_pixel_size>adjust->last_pixel_size || pack==0 || pack>3 ) {
+ LogError(_("Bad device table\n" ));
+ adjust->first_pixel_size = adjust->last_pixel_size = 0;
+ } else {
+ c = adjust->last_pixel_size-adjust->first_pixel_size+1;
+ adjust->corrections = galloc(c);
+ if ( pack==1 ) {
+ for ( i=0; i<c; i+=8 ) {
+ w = getushort(ttf);
+ for ( b=0; b<8 && i+b<c; ++b )
+ adjust->corrections[i+b] = ((int16) ((w<<(b*2))&0xc000))>>14;
+ }
+ } else if ( pack==2 ) {
+ for ( i=0; i<c; i+=4 ) {
+ w = getushort(ttf);
+ for ( b=0; b<4 && i+b<c; ++b )
+ adjust->corrections[i+b] = ((int16) ((w<<(b*4))&0xf000))>>12;
+ }
+ } else {
+ for ( i=0; i<c; ++i )
+ adjust->corrections[i] = (int8) getc(ttf);
+ }
+ }
+ fseek(ttf,here,SEEK_SET);
+}
+
+static ValDevTab *readValDevTab(FILE *ttf,struct valuerecord *vr,uint32 base) {
+ ValDevTab *ret;
+
+ if ( vr->offXplaceDev==0 && vr->offYplaceDev==0 &&
+ vr->offXadvanceDev==0 && vr->offYadvanceDev==0 )
+return( NULL );
+ ret = chunkalloc(sizeof(ValDevTab));
+ if ( vr->offXplaceDev!=0 )
+ ReadDeviceTable(ttf,&ret->xadjust,base + vr->offXplaceDev);
+ if ( vr->offYplaceDev!=0 )
+ ReadDeviceTable(ttf,&ret->yadjust,base + vr->offYplaceDev);
+ if ( vr->offXadvanceDev!=0 )
+ ReadDeviceTable(ttf,&ret->xadv,base + vr->offXadvanceDev);
+ if ( vr->offYadvanceDev!=0 )
+ ReadDeviceTable(ttf,&ret->yadv,base + vr->offYadvanceDev);
+return( ret );
+}
+#endif
+
+static void addPairPos(struct ttfinfo *info, int glyph1, int glyph2,
+ struct lookup *l, struct lookup_subtable *subtable, struct valuerecord *vr1,struct valuerecord *vr2,
+ uint32 base,FILE *ttf) {
+
+ if ( glyph1<info->glyph_cnt && glyph2<info->glyph_cnt ) {
+ PST *pos = chunkalloc(sizeof(PST));
+ pos->type = pst_pair;
+ pos->subtable = subtable;
+ pos->next = info->chars[glyph1]->possub;
+ info->chars[glyph1]->possub = pos;
+ pos->u.pair.vr = chunkalloc(sizeof(struct vr [2]));
+ pos->u.pair.paired = copy(info->chars[glyph2]->name);
+ pos->u.pair.vr[0].xoff = vr1->xplacement;
+ pos->u.pair.vr[0].yoff = vr1->yplacement;
+ pos->u.pair.vr[0].h_adv_off = vr1->xadvance;
+ pos->u.pair.vr[0].v_adv_off = vr1->yadvance;
+ pos->u.pair.vr[1].xoff = vr2->xplacement;
+ pos->u.pair.vr[1].yoff = vr2->yplacement;
+ pos->u.pair.vr[1].h_adv_off = vr2->xadvance;
+ pos->u.pair.vr[1].v_adv_off = vr2->yadvance;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ pos->u.pair.vr[0].adjust = readValDevTab(ttf,vr1,base);
+ pos->u.pair.vr[1].adjust = readValDevTab(ttf,vr2,base);
+#endif
+ } else
+ LogError( _("Bad pair position: glyphs %d & %d should have been < %d\n"),
+ glyph1, glyph2, info->glyph_cnt );
+}
+
+static int addKernPair(struct ttfinfo *info, int glyph1, int glyph2,
+ int16 offset, uint32 devtab, struct lookup *l, struct lookup_subtable *subtable,int isv,
+ FILE *ttf) {
+ KernPair *kp;
+ if ( glyph1<info->glyph_cnt && glyph2<info->glyph_cnt &&
+ info->chars[glyph1]!=NULL && info->chars[glyph2]!=NULL ) {
+ for ( kp=isv ? info->chars[glyph1]->vkerns : info->chars[glyph1]->kerns;
+ kp!=NULL; kp=kp->next ) {
+ if ( kp->sc == info->chars[glyph2] )
+ break;
+ }
+ if ( kp==NULL ) {
+ kp = chunkalloc(sizeof(KernPair));
+ kp->sc = info->chars[glyph2];
+ kp->off = offset;
+ kp->subtable = subtable;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( devtab!=0 ) {
+ kp->adjust = chunkalloc(sizeof(DeviceTable));
+ ReadDeviceTable(ttf,kp->adjust,devtab);
+ }
+#endif
+ if ( isv ) {
+ kp->next = info->chars[glyph1]->vkerns;
+ info->chars[glyph1]->vkerns = kp;
+ } else {
+ kp->next = info->chars[glyph1]->kerns;
+ info->chars[glyph1]->kerns = kp;
+ }
+ } else if ( kp->subtable!=subtable )
+return( true );
+ } else
+ LogError( _("Bad kern pair: glyphs %d & %d should have been < %d\n"),
+ glyph1, glyph2, info->glyph_cnt );
+return( false );
+}
+
+static void gposKernSubTable(FILE *ttf, int stoffset, struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable) {
+ int coverage, cnt, i, j, pair_cnt, vf1, vf2, glyph2;
+ int cd1, cd2, c1_cnt, c2_cnt;
+ uint16 format;
+ uint16 *ps_offsets;
+ uint16 *glyphs, *class1, *class2;
+ struct valuerecord vr1, vr2;
+ long foffset;
+ KernClass *kc;
+ int isv, r2l;
+
+ format=getushort(ttf);
+ if ( format!=1 && format!=2 ) /* Unknown subtable format */
+return;
+ coverage = getushort(ttf);
+ vf1 = getushort(ttf);
+ vf2 = getushort(ttf);
+ r2l = 0;
+ if ( (vf1==0x0088 || vf1==0x0008) && vf2==0x0000 )
+ isv = 1; /* Top to bottom */
+ else if ( vf1==0x0000 && (vf2==0x0044 || vf2==0x0004)) {
+ isv = 0; /* Right to left */
+ r2l = 1;
+ } else if ( (vf1==0x0044 || vf1==0x0004) && vf2==0x0000 )
+ isv = 0; /* Left to right */
+ else
+ isv = 2;
+ if ( format==1 ) {
+ subtable->per_glyph_pst_or_kern = true;
+ cnt = getushort(ttf);
+ ps_offsets = galloc(cnt*sizeof(uint16));
+ for ( i=0; i<cnt; ++i )
+ ps_offsets[i]=getushort(ttf);
+ glyphs = getCoverageTable(ttf,stoffset+coverage,info);
+ if ( glyphs==NULL )
+return;
+ for ( i=0; i<cnt; ++i ) if ( glyphs[i]<info->glyph_cnt ) {
+ fseek(ttf,stoffset+ps_offsets[i],SEEK_SET);
+ pair_cnt = getushort(ttf);
+ for ( j=0; j<pair_cnt; ++j ) {
+ glyph2 = getushort(ttf);
+ readvaluerecord(&vr1,vf1,ttf);
+ readvaluerecord(&vr2,vf2,ttf);
+ if ( isv==2 )
+ addPairPos(info, glyphs[i], glyph2,l,subtable,&vr1,&vr2, stoffset,ttf);
+ else if ( isv ) {
+ if ( addKernPair(info, glyphs[i], glyph2, vr1.yadvance,
+ vr1.offYadvanceDev==0?0:stoffset+vr1.offYadvanceDev,
+ l,subtable,isv,ttf))
+ addPairPos(info, glyphs[i], glyph2,l,subtable,&vr1,&vr2, stoffset,ttf);
+ /* If we've already got kern data for this pair of */
+ /* glyphs, then we can't make it be a true KernPair */
+ /* but we can save the info as a pst_pair */
+ } else if ( r2l ) { /* R2L */
+ if ( addKernPair(info, glyphs[i], glyph2, vr2.xadvance,
+ vr2.offXadvanceDev==0?0:stoffset+vr2.offXadvanceDev,
+ l,subtable,isv,ttf))
+ addPairPos(info, glyphs[i], glyph2,l,subtable,&vr1,&vr2,stoffset,ttf);
+ } else {
+ if ( addKernPair(info, glyphs[i], glyph2, vr1.xadvance,
+ vr1.offXadvanceDev==0?0:stoffset+vr1.offXadvanceDev,
+ l,subtable,isv,ttf))
+ addPairPos(info, glyphs[i], glyph2,l,subtable,&vr1,&vr2,stoffset,ttf);
+ }
+ }
+ }
+ free(ps_offsets); free(glyphs);
+ } else if ( format==2 ) { /* Class-based kerning */
+ cd1 = getushort(ttf);
+ cd2 = getushort(ttf);
+ foffset = ftell(ttf);
+ class1 = getClassDefTable(ttf, stoffset+cd1, info->glyph_cnt, info->g_bounds);
+ class2 = getClassDefTable(ttf, stoffset+cd2, info->glyph_cnt, info->g_bounds);
+ glyphs = getCoverageTable(ttf,stoffset+coverage,info);
+ fseek(ttf, foffset, SEEK_SET); /* come back */
+ c1_cnt = getushort(ttf);
+ c2_cnt = getushort(ttf);
+ if ( isv!=2 ) {
+ if ( isv ) {
+ if ( info->vkhead==NULL )
+ info->vkhead = kc = chunkalloc(sizeof(KernClass));
+ else
+ kc = info->vklast->next = chunkalloc(sizeof(KernClass));
+ info->vklast = kc;
+ } else {
+ if ( info->khead==NULL )
+ info->khead = kc = chunkalloc(sizeof(KernClass));
+ else
+ kc = info->klast->next = chunkalloc(sizeof(KernClass));
+ info->klast = kc;
+ }
+ subtable->vertical_kerning = isv;
+ subtable->kc = kc;
+ kc->first_cnt = c1_cnt; kc->second_cnt = c2_cnt;
+ kc->subtable = subtable;
+ kc->offsets = galloc(c1_cnt*c2_cnt*sizeof(int16));
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ kc->adjusts = gcalloc(c1_cnt*c2_cnt,sizeof(DeviceTable));
+#endif
+ kc->firsts = ClassToNames(info,c1_cnt,class1,info->glyph_cnt);
+ kc->seconds = ClassToNames(info,c2_cnt,class2,info->glyph_cnt);
+ /* Now if the coverage table contains entries which are not in */
+ /* the list of first classes, then those glyphs are the real */
+ /* values for kc->firsts[0] */
+ kc->firsts[0] = CoverageMinusClasses(glyphs,class1,info);
+ for ( i=0; i<c1_cnt; ++i) {
+ for ( j=0; j<c2_cnt; ++j) {
+ readvaluerecord(&vr1,vf1,ttf);
+ readvaluerecord(&vr2,vf2,ttf);
+ if ( isv )
+ kc->offsets[i*c2_cnt+j] = vr1.yadvance;
+ else if ( r2l )
+ kc->offsets[i*c2_cnt+j] = vr2.xadvance;
+ else
+ kc->offsets[i*c2_cnt+j] = vr1.xadvance;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( isv ) {
+ if ( vr1.offYadvanceDev!=0 )
+ ReadDeviceTable(ttf,&kc->adjusts[i*c2_cnt+j],stoffset+vr1.offYadvanceDev);
+ } else if ( r2l ) {
+ if ( vr2.offXadvanceDev!=0 )
+ ReadDeviceTable(ttf,&kc->adjusts[i*c2_cnt+j],stoffset+vr2.offXadvanceDev);
+ } else {
+ if ( vr1.offXadvanceDev!=0 )
+ ReadDeviceTable(ttf,&kc->adjusts[i*c2_cnt+j],stoffset+vr1.offXadvanceDev);
+ }
+#endif
+ }
+ }
+ } else { /* This happens when we have a feature which is neither 'kern' nor 'vkrn' we don't know what to do with it so we make it into kern pairs */
+ int k,m;
+ subtable->per_glyph_pst_or_kern = true;
+ for ( i=0; i<c1_cnt; ++i) {
+ for ( j=0; j<c2_cnt; ++j) {
+ readvaluerecord(&vr1,vf1,ttf);
+ readvaluerecord(&vr2,vf2,ttf);
+ if ( vr1.xadvance!=0 || vr1.xplacement!=0 || vr1.yadvance!=0 || vr1.yplacement!=0 ||
+ vr2.xadvance!=0 || vr2.xplacement!=0 || vr2.yadvance!=0 || vr2.yplacement!=0 )
+ for ( k=0; k<info->glyph_cnt; ++k )
+ if ( class1[k]==i )
+ for ( m=0; m<info->glyph_cnt; ++m )
+ if ( class2[m]==j )
+ addPairPos(info, k,m,l,subtable,&vr1,&vr2,stoffset,ttf);
+ }
+ }
+ }
+ free(class1); free(class2);
+ free(glyphs);
+ }
+}
+
+static AnchorPoint *readAnchorPoint(FILE *ttf,uint32 base,AnchorClass *class,
+ enum anchor_type type,AnchorPoint *last) {
+ AnchorPoint *ap;
+ int format;
+
+ fseek(ttf,base,SEEK_SET);
+
+ ap = chunkalloc(sizeof(AnchorPoint));
+ ap->anchor = class;
+ /* All anchor types have the same initial 3 entries, format */
+ /* x,y pos. format 2 contains a truetype positioning point, and */
+ /* format==3 may also have device tables */
+ format = getushort(ttf);
+ ap->me.x = (int16) getushort(ttf);
+ ap->me.y = (int16) getushort(ttf);
+ ap->type = type;
+ if ( format==2 ) {
+ ap->ttf_pt_index = getushort(ttf);
+ ap->has_ttf_pt = true;
+ }
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ else if ( format==3 ) {
+ int devoff;
+ devoff = getushort(ttf);
+ if ( devoff!=0 )
+ ReadDeviceTable(ttf,&ap->xadjust,base+devoff);
+ devoff = getushort(ttf);
+ if ( devoff!=0 )
+ ReadDeviceTable(ttf,&ap->yadjust,base+devoff);
+ }
+#endif
+ ap->next = last;
+return( ap );
+}
+
+static void gposCursiveSubTable(FILE *ttf, int stoffset, struct ttfinfo *info,struct lookup *l, struct lookup_subtable *subtable) {
+ int coverage, cnt, format, i;
+ struct ee_offsets { int entry, exit; } *offsets;
+ uint16 *glyphs;
+ AnchorClass *class;
+ SplineChar *sc;
+ char buf[50];
+
+ format=getushort(ttf);
+ if ( format!=1 ) /* Unknown subtable format */
+return;
+ coverage = getushort(ttf);
+ cnt = getushort(ttf);
+ if ( cnt==0 )
+return;
+ offsets = galloc(cnt*sizeof(struct ee_offsets));
+ for ( i=0; i<cnt; ++i ) {
+ offsets[i].entry = getushort(ttf);
+ offsets[i].exit = getushort(ttf);
+ }
+ glyphs = getCoverageTable(ttf,stoffset+coverage,info);
+
+ class = chunkalloc(sizeof(AnchorClass));
+ snprintf(buf,sizeof(buf),_("Cursive-%d"),
+ info->anchor_class_cnt++ );
+ class->name = copy(buf);
+ subtable->anchor_classes = true;
+ class->subtable = subtable;
+ class->type = act_curs;
+ if ( info->ahead==NULL )
+ info->ahead = class;
+ else
+ info->alast->next = class;
+ info->alast = class;
+
+ for ( i=0; i<cnt; ++i ) {
+ sc = info->chars[glyphs[i]];
+ if ( offsets[i].entry!=0 ) {
+ sc->anchor = readAnchorPoint(ttf,stoffset+offsets[i].entry,class,
+ at_centry,sc->anchor);
+ }
+ if ( offsets[i].exit!=0 ) {
+ sc->anchor = readAnchorPoint(ttf,stoffset+offsets[i].exit,class,
+ at_cexit,sc->anchor);
+ }
+ }
+ free(offsets);
+ free(glyphs);
+}
+
+static AnchorClass **MarkGlyphsProcessMarks(FILE *ttf,int markoffset,
+ struct ttfinfo *info,struct lookup *l, struct lookup_subtable *subtable,uint16 *markglyphs,
+ int classcnt) {
+ AnchorClass **classes = gcalloc(classcnt,sizeof(AnchorClass *)), *ac;
+ char buf[50];
+ int i, cnt;
+ struct mr { uint16 class, offset; } *at_offsets;
+ SplineChar *sc;
+
+ for ( i=0; i<classcnt; ++i ) {
+ snprintf(buf,sizeof(buf),_("Anchor-%d"),
+ info->anchor_class_cnt+i );
+ classes[i] = ac = chunkalloc(sizeof(AnchorClass));
+ ac->name = copy(buf);
+ subtable->anchor_classes = true;
+ ac->subtable = subtable;
+ /*ac->merge_with = info->anchor_merge_cnt+1;*/
+ ac->type = l->otlookup->lookup_type==gpos_mark2mark ? act_mkmk : act_mark;
+ /* I don't distinguish between mark to base and mark to lig */
+ if ( info->ahead==NULL )
+ info->ahead = ac;
+ else
+ info->alast->next = ac;
+ info->alast = ac;
+ }
+
+ fseek(ttf,markoffset,SEEK_SET);
+ cnt = getushort(ttf);
+ if ( feof(ttf) ) {
+ LogError( _("Bad mark table.\n") );
+return( NULL );
+ }
+ at_offsets = galloc(cnt*sizeof(struct mr));
+ for ( i=0; i<cnt; ++i ) {
+ at_offsets[i].class = getushort(ttf);
+ at_offsets[i].offset = getushort(ttf);
+ if ( at_offsets[i].class>=classcnt ) {
+ at_offsets[i].class = 0;
+ LogError( _("Class out of bounds in GPOS mark sub-table\n") );
+ }
+ }
+ for ( i=0; i<cnt; ++i ) {
+ if ( markglyphs[i]>=info->glyph_cnt )
+ continue;
+ sc = info->chars[markglyphs[i]];
+ if ( sc==NULL || at_offsets[i].offset==0 )
+ continue;
+ sc->anchor = readAnchorPoint(ttf,markoffset+at_offsets[i].offset,
+ classes[at_offsets[i].class],at_mark,sc->anchor);
+ }
+ free(at_offsets);
+return( classes );
+}
+
+static void MarkGlyphsProcessBases(FILE *ttf,int baseoffset,
+ struct ttfinfo *info,struct lookup *l, struct lookup_subtable *subtable,uint16 *baseglyphs,int classcnt,
+ AnchorClass **classes,enum anchor_type at) {
+ int basecnt,i, j, ibase;
+ uint16 *offsets;
+ SplineChar *sc;
+
+ fseek(ttf,baseoffset,SEEK_SET);
+ basecnt = getushort(ttf);
+ if ( feof(ttf) ) {
+ LogError( _("Bad base table.\n") );
+return;
+ }
+ offsets = galloc(basecnt*classcnt*sizeof(uint16));
+ for ( i=0; i<basecnt*classcnt; ++i )
+ offsets[i] = getushort(ttf);
+ for ( i=ibase=0; i<basecnt; ++i, ibase+= classcnt ) {
+ if ( baseglyphs[i]>=info->glyph_cnt )
+ continue;
+ sc = info->chars[baseglyphs[i]];
+ if ( sc==NULL )
+ continue;
+ for ( j=0; j<classcnt; ++j ) if ( offsets[ibase+j]!=0 ) {
+ sc->anchor = readAnchorPoint(ttf,baseoffset+offsets[ibase+j],
+ classes[j], at,sc->anchor);
+ }
+ }
+ free(offsets);
+}
+
+static void MarkGlyphsProcessLigs(FILE *ttf,int baseoffset,
+ struct ttfinfo *info,struct lookup *l, struct lookup_subtable *subtable,uint16 *baseglyphs,int classcnt,
+ AnchorClass **classes) {
+ int basecnt,compcnt, i, j, k, kbase;
+ uint16 *loffsets, *aoffsets;
+ SplineChar *sc;
+
+ fseek(ttf,baseoffset,SEEK_SET);
+ basecnt = getushort(ttf);
+ if ( feof(ttf) ) {
+ LogError( _("Bad ligature base table.\n") );
+return;
+ }
+ loffsets = galloc(basecnt*sizeof(uint16));
+ for ( i=0; i<basecnt; ++i )
+ loffsets[i] = getushort(ttf);
+ for ( i=0; i<basecnt; ++i ) {
+ sc = info->chars[baseglyphs[i]];
+ if ( baseglyphs[i]>=info->glyph_cnt || sc==NULL )
+ continue;
+ fseek(ttf,baseoffset+loffsets[i],SEEK_SET);
+ compcnt = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError(_("Bad ligature anchor count.\n"));
+ continue;
+ }
+ aoffsets = galloc(compcnt*classcnt*sizeof(uint16));
+ for ( k=0; k<compcnt*classcnt; ++k )
+ aoffsets[k] = getushort(ttf);
+ for ( k=kbase=0; k<compcnt; ++k, kbase+=classcnt ) {
+ for ( j=0; j<classcnt; ++j ) if ( aoffsets[kbase+j]!=0 ) {
+ sc->anchor = readAnchorPoint(ttf,baseoffset+loffsets[i]+aoffsets[kbase+j],
+ classes[j], at_baselig,sc->anchor);
+ sc->anchor->lig_index = k;
+ }
+ }
+ free(aoffsets);
+ }
+ free(loffsets);
+}
+
+static void gposMarkSubTable(FILE *ttf, uint32 stoffset,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable) {
+ int markcoverage, basecoverage, classcnt, markoffset, baseoffset;
+ uint16 *markglyphs, *baseglyphs;
+ AnchorClass **classes;
+
+ /* The header for the three different mark tables is the same */
+ /* Type = */ getushort(ttf);
+ markcoverage = getushort(ttf);
+ basecoverage = getushort(ttf);
+ classcnt = getushort(ttf);
+ markoffset = getushort(ttf);
+ baseoffset = getushort(ttf);
+ markglyphs = getCoverageTable(ttf,stoffset+markcoverage,info);
+ baseglyphs = getCoverageTable(ttf,stoffset+basecoverage,info);
+ if ( baseglyphs==NULL || markglyphs==NULL ) {
+ free(baseglyphs); free(markglyphs);
+return;
+ }
+ /* as is the (first) mark table */
+ classes = MarkGlyphsProcessMarks(ttf,stoffset+markoffset,
+ info,l,subtable,markglyphs,classcnt);
+ if ( classes==NULL )
+return;
+ switch ( l->otlookup->lookup_type ) {
+ case gpos_mark2base:
+ case gpos_mark2mark:
+ MarkGlyphsProcessBases(ttf,stoffset+baseoffset,
+ info,l,subtable,baseglyphs,classcnt,classes,
+ l->otlookup->lookup_type==gpos_mark2base?at_basechar:at_basemark);
+ break;
+ case gpos_mark2ligature:
+ MarkGlyphsProcessLigs(ttf,stoffset+baseoffset,
+ info,l,subtable,baseglyphs,classcnt,classes);
+ break;
+ default:
+ break;
+ }
+ info->anchor_class_cnt += classcnt;
+ ++ info->anchor_merge_cnt;
+ free(markglyphs); free(baseglyphs);
+ free(classes);
+}
+
+static void gposSimplePos(FILE *ttf, int stoffset, struct ttfinfo *info,
+ struct lookup *l, struct lookup_subtable *subtable) {
+ int coverage, cnt, i, vf;
+ uint16 format;
+ uint16 *glyphs;
+ struct valuerecord *vr=NULL, _vr, *which;
+
+ format=getushort(ttf);
+ if ( format!=1 && format!=2 ) /* Unknown subtable format */
+return;
+ coverage = getushort(ttf);
+ vf = getushort(ttf);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( vf==0 )
+return;
+#else
+ if ( (vf&0xf)==0 ) /* Not interested in things whose data just live in device tables */
+return;
+#endif
+ if ( format==1 ) {
+ memset(&_vr,0,sizeof(_vr));
+ readvaluerecord(&_vr,vf,ttf);
+ } else {
+ cnt = getushort(ttf);
+ vr = gcalloc(cnt,sizeof(struct valuerecord));
+ for ( i=0; i<cnt; ++i )
+ readvaluerecord(&vr[i],vf,ttf);
+ }
+ glyphs = getCoverageTable(ttf,stoffset+coverage,info);
+ if ( glyphs==NULL ) {
+ free(vr);
+return;
+ }
+ for ( i=0; glyphs[i]!=0xffff; ++i ) if ( glyphs[i]<info->glyph_cnt ) {
+ PST *pos = chunkalloc(sizeof(PST));
+ pos->type = pst_position;
+ pos->subtable = subtable;
+ pos->next = info->chars[glyphs[i]]->possub;
+ info->chars[glyphs[i]]->possub = pos;
+ which = format==1 ? &_vr : &vr[i];
+ pos->u.pos.xoff = which->xplacement;
+ pos->u.pos.yoff = which->yplacement;
+ pos->u.pos.h_adv_off = which->xadvance;
+ pos->u.pos.v_adv_off = which->yadvance;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ pos->u.pos.adjust = readValDevTab(ttf,which,stoffset);
+#endif
+ }
+ subtable->per_glyph_pst_or_kern = true;
+ free(vr);
+ free(glyphs);
+}
+
+static void ProcessSubLookups(FILE *ttf,struct ttfinfo *info,int gpos,
+ struct lookup *alllooks,struct seqlookup *sl) {
+ int i;
+
+ i = (intpt) sl->lookup;
+ if ( i<0 || i>=info->lookup_cnt ) {
+ LogError( _("Attempt to reference lookup %d (within a contextual lookup), but there are\n only %d lookups in %s\n"),
+ i, info->lookup_cnt, gpos ? "'GPOS'" : "'GSUB'" );
+ sl->lookup = NULL;
+return;
+ }
+ sl->lookup = alllooks[i].otlookup;
+}
+
+static void g___ContextSubTable1(FILE *ttf, int stoffset,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
+ struct lookup *alllooks, int gpos) {
+ int i, j, k, rcnt, cnt;
+ uint16 coverage;
+ uint16 *glyphs;
+ struct subrule {
+ uint32 offset;
+ int gcnt;
+ int scnt;
+ uint16 *glyphs;
+ struct seqlookup *sl;
+ };
+ struct rule {
+ uint32 offsets;
+ int scnt;
+ struct subrule *subrules;
+ } *rules;
+ FPST *fpst;
+ struct fpst_rule *rule;
+ int warned = false, warned2 = false;
+
+ coverage = getushort(ttf);
+ rcnt = getushort(ttf); /* glyph count in coverage table */
+ rules = galloc(rcnt*sizeof(struct rule));
+ for ( i=0; i<rcnt; ++i )
+ rules[i].offsets = getushort(ttf)+stoffset;
+ glyphs = getCoverageTable(ttf,stoffset+coverage,info);
+ cnt = 0;
+ for ( i=0; i<rcnt; ++i ) {
+ fseek(ttf,rules[i].offsets,SEEK_SET);
+ rules[i].scnt = getushort(ttf);
+ cnt += rules[i].scnt;
+ rules[i].subrules = galloc(rules[i].scnt*sizeof(struct subrule));
+ for ( j=0; j<rules[i].scnt; ++j )
+ rules[i].subrules[j].offset = getushort(ttf)+rules[i].offsets;
+ for ( j=0; j<rules[i].scnt; ++j ) {
+ fseek(ttf,rules[i].subrules[j].offset,SEEK_SET);
+ rules[i].subrules[j].gcnt = getushort(ttf);
+ rules[i].subrules[j].scnt = getushort(ttf);
+ rules[i].subrules[j].glyphs = galloc((rules[i].subrules[j].gcnt+1)*sizeof(uint16));
+ rules[i].subrules[j].glyphs[0] = glyphs[i];
+ for ( k=1; k<rules[i].subrules[j].gcnt; ++k ) {
+ rules[i].subrules[j].glyphs[k] = getushort(ttf);
+ if ( rules[i].subrules[j].glyphs[k]>=info->glyph_cnt ) {
+ if ( !warned )
+ LogError( _("Bad contextual or chaining sub table. Glyph %d out of range [0,%d)\n"),
+ rules[i].subrules[j].glyphs[k], info->glyph_cnt );
+ warned = true;
+ rules[i].subrules[j].glyphs[k] = 0;
+ }
+ }
+ rules[i].subrules[j].glyphs[k] = 0xffff;
+ rules[i].subrules[j].sl = galloc(rules[i].subrules[j].scnt*sizeof(struct seqlookup));
+ for ( k=0; k<rules[i].subrules[j].scnt; ++k ) {
+ rules[i].subrules[j].sl[k].seq = getushort(ttf);
+ if ( rules[i].subrules[j].sl[k].seq >= rules[i].subrules[j].gcnt+1 )
+ if ( !warned2 ) {
+ LogError( _("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d max=%d\n"),
+ rules[i].subrules[j].sl[k].seq, rules[i].subrules[j].gcnt );
+ warned2 = true;
+ }
+ rules[i].subrules[j].sl[k].lookup = (void *) (intpt) getushort(ttf);
+ }
+ }
+ }
+
+ if ( justinuse==git_justinuse ) {
+ /* Nothing to do. This lookup doesn't really reference any glyphs */
+ /* any lookups it invokes will be processed on their own */
+ } else {
+ fpst = chunkalloc(sizeof(FPST));
+ fpst->type = gpos ? pst_contextpos : pst_contextsub;
+ fpst->format = pst_glyphs;
+ fpst->subtable = subtable;
+ fpst->next = info->possub;
+ info->possub = fpst;
+ subtable->fpst = fpst;
+
+ fpst->rules = rule = gcalloc(cnt,sizeof(struct fpst_rule));
+ fpst->rule_cnt = cnt;
+
+ cnt = 0;
+ for ( i=0; i<rcnt; ++i ) for ( j=0; j<rules[i].scnt; ++j ) {
+ rule[cnt].u.glyph.names = GlyphsToNames(info,rules[i].subrules[j].glyphs,false);
+ rule[cnt].lookup_cnt = rules[i].subrules[j].scnt;
+ rule[cnt].lookups = rules[i].subrules[j].sl;
+ rules[i].subrules[j].sl = NULL;
+ for ( k=0; k<rule[cnt].lookup_cnt; ++k )
+ ProcessSubLookups(ttf,info,gpos,alllooks,&rule[cnt].lookups[k]);
+ ++cnt;
+ }
+ }
+
+ for ( i=0; i<rcnt; ++i ) {
+ for ( j=0; j<rules[i].scnt; ++j ) {
+ free(rules[i].subrules[j].glyphs);
+ free(rules[i].subrules[j].sl);
+ }
+ free(rules[i].subrules);
+ }
+ free(rules);
+ free(glyphs);
+}
+
+static void g___ChainingSubTable1(FILE *ttf, int stoffset,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
+ struct lookup *alllooks, int gpos) {
+ int i, j, k, rcnt, cnt, which;
+ uint16 coverage;
+ uint16 *glyphs;
+ struct subrule {
+ uint32 offset;
+ int gcnt, bcnt, fcnt;
+ int scnt;
+ uint16 *glyphs, *bglyphs, *fglyphs;
+ struct seqlookup *sl;
+ };
+ struct rule {
+ uint32 offsets;
+ int scnt;
+ struct subrule *subrules;
+ } *rules;
+ FPST *fpst;
+ struct fpst_rule *rule;
+ int warned = false, warned2 = false;
+
+ coverage = getushort(ttf);
+ rcnt = getushort(ttf); /* glyph count in coverage table */
+ rules = galloc(rcnt*sizeof(struct rule));
+ for ( i=0; i<rcnt; ++i )
+ rules[i].offsets = getushort(ttf)+stoffset;
+ glyphs = getCoverageTable(ttf,stoffset+coverage,info);
+ if ( glyphs==NULL ) {
+ free(rules);
+return;
+ }
+ cnt = 0;
+ for ( i=0; i<rcnt; ++i ) {
+ fseek(ttf,rules[i].offsets,SEEK_SET);
+ rules[i].scnt = getushort(ttf);
+ cnt += rules[i].scnt;
+ rules[i].subrules = galloc(rules[i].scnt*sizeof(struct subrule));
+ for ( j=0; j<rules[i].scnt; ++j )
+ rules[i].subrules[j].offset = getushort(ttf)+rules[i].offsets;
+ for ( j=0; j<rules[i].scnt; ++j ) {
+ fseek(ttf,rules[i].subrules[j].offset,SEEK_SET);
+ rules[i].subrules[j].bcnt = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError( _("Unexpected end of file in contextual chaining subtable.\n") );
+return;
+ }
+ rules[i].subrules[j].bglyphs = galloc((rules[i].subrules[j].bcnt+1)*sizeof(uint16));
+ for ( k=0; k<rules[i].subrules[j].bcnt; ++k )
+ rules[i].subrules[j].bglyphs[k] = getushort(ttf);
+ rules[i].subrules[j].bglyphs[k] = 0xffff;
+
+ rules[i].subrules[j].gcnt = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError( _("Unexpected end of file in contextual chaining subtable.\n") );
+return;
+ }
+ rules[i].subrules[j].glyphs = galloc((rules[i].subrules[j].gcnt+1)*sizeof(uint16));
+ rules[i].subrules[j].glyphs[0] = glyphs[i];
+ for ( k=1; k<rules[i].subrules[j].gcnt; ++k )
+ rules[i].subrules[j].glyphs[k] = getushort(ttf);
+ rules[i].subrules[j].glyphs[k] = 0xffff;
+
+ rules[i].subrules[j].fcnt = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError( _("Unexpected end of file in contextual chaining subtable.\n") );
+return;
+ }
+ rules[i].subrules[j].fglyphs = galloc((rules[i].subrules[j].fcnt+1)*sizeof(uint16));
+ for ( k=0; k<rules[i].subrules[j].fcnt; ++k )
+ rules[i].subrules[j].fglyphs[k] = getushort(ttf);
+ rules[i].subrules[j].fglyphs[k] = 0xffff;
+
+ for ( which = 0; which<3; ++which ) {
+ for ( k=0; k<(&rules[i].subrules[j].gcnt)[which]; ++k ) {
+ if ( (&rules[i].subrules[j].glyphs)[which][k]>=info->glyph_cnt ) {
+ if ( !warned )
+ LogError( _("Bad contextual or chaining sub table. Glyph %d out of range [0,%d)\n"),
+ (&rules[i].subrules[j].glyphs)[which][k], info->glyph_cnt );
+ warned = true;
+ (&rules[i].subrules[j].glyphs)[which][k] = 0;
+ }
+ }
+ }
+
+ rules[i].subrules[j].scnt = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError( _("Unexpected end of file in contextual chaining subtable.\n") );
+return;
+ }
+ rules[i].subrules[j].sl = galloc(rules[i].subrules[j].scnt*sizeof(struct seqlookup));
+ for ( k=0; k<rules[i].subrules[j].scnt; ++k ) {
+ rules[i].subrules[j].sl[k].seq = getushort(ttf);
+ if ( rules[i].subrules[j].sl[k].seq >= rules[i].subrules[j].gcnt+1 )
+ if ( !warned2 ) {
+ LogError( _("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d max=%d\n"),
+ rules[i].subrules[j].sl[k].seq, rules[i].subrules[j].gcnt );
+ warned2 = true;
+ }
+ rules[i].subrules[j].sl[k].lookup = (void *) (intpt) getushort(ttf);
+ }
+ }
+ }
+
+ if ( justinuse==git_justinuse ) {
+ /* Nothing to do. This lookup doesn't really reference any glyphs */
+ /* any lookups it invokes will be processed on their own */
+ } else {
+ fpst = chunkalloc(sizeof(FPST));
+ fpst->type = gpos ? pst_chainpos : pst_chainsub;
+ fpst->format = pst_glyphs;
+ fpst->subtable = subtable;
+ fpst->next = info->possub;
+ info->possub = fpst;
+ subtable->fpst = fpst;
+
+ fpst->rules = rule = gcalloc(cnt,sizeof(struct fpst_rule));
+ fpst->rule_cnt = cnt;
+
+ cnt = 0;
+ for ( i=0; i<rcnt; ++i ) for ( j=0; j<rules[i].scnt; ++j ) {
+ rule[cnt].u.glyph.back = GlyphsToNames(info,rules[i].subrules[j].bglyphs,false);
+ rule[cnt].u.glyph.names = GlyphsToNames(info,rules[i].subrules[j].glyphs,false);
+ rule[cnt].u.glyph.fore = GlyphsToNames(info,rules[i].subrules[j].fglyphs,false);
+ rule[cnt].lookup_cnt = rules[i].subrules[j].scnt;
+ rule[cnt].lookups = rules[i].subrules[j].sl;
+ rules[i].subrules[j].sl = NULL;
+ for ( k=0; k<rule[cnt].lookup_cnt; ++k )
+ ProcessSubLookups(ttf,info,gpos,alllooks,&rule[cnt].lookups[k]);
+ ++cnt;
+ }
+ }
+
+ for ( i=0; i<rcnt; ++i ) {
+ for ( j=0; j<rules[i].scnt; ++j ) {
+ free(rules[i].subrules[j].bglyphs);
+ free(rules[i].subrules[j].glyphs);
+ free(rules[i].subrules[j].fglyphs);
+ free(rules[i].subrules[j].sl);
+ }
+ free(rules[i].subrules);
+ }
+ free(rules);
+ free(glyphs);
+}
+
+static void g___ContextSubTable2(FILE *ttf, int stoffset,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
+ struct lookup *alllooks, int gpos) {
+ int i, j, k, rcnt, cnt;
+ uint16 coverage;
+ uint16 classoff;
+ struct subrule {
+ uint32 offset;
+ int ccnt;
+ int scnt;
+ uint16 *classindeces;
+ struct seqlookup *sl;
+ };
+ struct rule {
+ uint32 offsets;
+ int scnt;
+ struct subrule *subrules;
+ } *rules;
+ FPST *fpst;
+ struct fpst_rule *rule;
+ uint16 *class;
+ int warned2 = false;
+
+ coverage = getushort(ttf);
+ classoff = getushort(ttf);
+ rcnt = getushort(ttf); /* class count in coverage table *//* == number of top level rules */
+ rules = gcalloc(rcnt,sizeof(struct rule));
+ for ( i=0; i<rcnt; ++i )
+ rules[i].offsets = getushort(ttf)+stoffset;
+ cnt = 0;
+ for ( i=0; i<rcnt; ++i ) if ( rules[i].offsets!=stoffset ) { /* some classes might be unused */
+ fseek(ttf,rules[i].offsets,SEEK_SET);
+ rules[i].scnt = getushort(ttf);
+ if ( rules[i].scnt<0 ) {
+ LogError( _("Bad count in context chaining sub-table.\n") );
+return;
+ }
+ cnt += rules[i].scnt;
+ rules[i].subrules = galloc(rules[i].scnt*sizeof(struct subrule));
+ for ( j=0; j<rules[i].scnt; ++j )
+ rules[i].subrules[j].offset = getushort(ttf)+rules[i].offsets;
+ for ( j=0; j<rules[i].scnt; ++j ) {
+ fseek(ttf,rules[i].subrules[j].offset,SEEK_SET);
+ rules[i].subrules[j].ccnt = getushort(ttf);
+ rules[i].subrules[j].scnt = getushort(ttf);
+ if ( rules[i].subrules[j].ccnt<0 ) {
+ LogError( _("Bad class count in contextual chaining sub-table.\n") );
+ free(rules);
+return;
+ }
+ rules[i].subrules[j].classindeces = galloc(rules[i].subrules[j].ccnt*sizeof(uint16));
+ rules[i].subrules[j].classindeces[0] = i;
+ for ( k=1; k<rules[i].subrules[j].ccnt; ++k )
+ rules[i].subrules[j].classindeces[k] = getushort(ttf);
+ if ( rules[i].subrules[j].scnt<0 ) {
+ LogError( _("Bad count in contextual chaining sub-table.\n") );
+ free(rules);
+return;
+ }
+ rules[i].subrules[j].sl = galloc(rules[i].subrules[j].scnt*sizeof(struct seqlookup));
+ for ( k=0; k<rules[i].subrules[j].scnt; ++k ) {
+ rules[i].subrules[j].sl[k].seq = getushort(ttf);
+ if ( rules[i].subrules[j].sl[k].seq >= rules[i].subrules[j].ccnt )
+ if ( !warned2 ) {
+ LogError( _("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d max=%d\n"),
+ rules[i].subrules[j].sl[k].seq, rules[i].subrules[j].ccnt-1);
+ warned2 = true;
+ }
+ rules[i].subrules[j].sl[k].lookup = (void *) (intpt) getushort(ttf);
+ }
+ }
+ }
+
+ if ( justinuse==git_justinuse ) {
+ /* Nothing to do. This lookup doesn't really reference any glyphs */
+ /* any lookups it invokes will be processed on their own */
+ } else {
+ fpst = chunkalloc(sizeof(FPST));
+ fpst->type = gpos ? pst_contextpos : pst_contextsub;
+ fpst->format = pst_class;
+ fpst->subtable = subtable;
+ subtable->fpst = fpst;
+ fpst->next = info->possub;
+ info->possub = fpst;
+
+ fpst->rules = rule = gcalloc(cnt,sizeof(struct fpst_rule));
+ fpst->rule_cnt = cnt;
+ class = getClassDefTable(ttf, stoffset+classoff, info->glyph_cnt, info->g_bounds);
+ fpst->nccnt = ClassFindCnt(class,info->glyph_cnt);
+ fpst->nclass = ClassToNames(info,fpst->nccnt,class,info->glyph_cnt);
+ free(class); class = NULL;
+
+ cnt = 0;
+ for ( i=0; i<rcnt; ++i ) for ( j=0; j<rules[i].scnt; ++j ) {
+ rule[cnt].u.class.nclasses = rules[i].subrules[j].classindeces;
+ rule[cnt].u.class.ncnt = rules[i].subrules[j].ccnt;
+ rules[i].subrules[j].classindeces = NULL;
+ rule[cnt].lookup_cnt = rules[i].subrules[j].scnt;
+ rule[cnt].lookups = rules[i].subrules[j].sl;
+ rules[i].subrules[j].sl = NULL;
+ for ( k=0; k<rule[cnt].lookup_cnt; ++k )
+ ProcessSubLookups(ttf,info,gpos,alllooks,&rule[cnt].lookups[k]);
+ ++cnt;
+ }
+ }
+
+ for ( i=0; i<rcnt; ++i ) {
+ for ( j=0; j<rules[i].scnt; ++j ) {
+ free(rules[i].subrules[j].classindeces);
+ free(rules[i].subrules[j].sl);
+ }
+ free(rules[i].subrules);
+ }
+ free(rules);
+}
+
+static void g___ChainingSubTable2(FILE *ttf, int stoffset,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
+ struct lookup *alllooks, int gpos) {
+ int i, j, k, rcnt, cnt;
+ uint16 coverage, offset;
+ uint16 bclassoff, classoff, fclassoff;
+ struct subrule {
+ uint32 offset;
+ int ccnt, bccnt, fccnt;
+ int scnt;
+ uint16 *classindeces, *bci, *fci;
+ struct seqlookup *sl;
+ };
+ struct rule {
+ uint32 offsets;
+ int scnt;
+ struct subrule *subrules;
+ } *rules;
+ FPST *fpst;
+ struct fpst_rule *rule;
+ uint16 *class;
+ int warned2 = false;
+
+ coverage = getushort(ttf);
+ bclassoff = getushort(ttf);
+ classoff = getushort(ttf);
+ fclassoff = getushort(ttf);
+ rcnt = getushort(ttf); /* class count *//* == max number of top level rules */
+ rules = gcalloc(rcnt,sizeof(struct rule));
+ for ( i=0; i<rcnt; ++i ) {
+ offset = getushort(ttf);
+ rules[i].offsets = offset==0 ? 0 : offset+stoffset;
+ }
+ cnt = 0;
+ for ( i=0; i<rcnt; ++i ) if ( rules[i].offsets!=0 ) { /* some classes might be unused */
+ fseek(ttf,rules[i].offsets,SEEK_SET);
+ rules[i].scnt = getushort(ttf);
+ if ( rules[i].scnt<0 ) {
+ LogError( _("Bad count in context chaining sub-table.\n") );
+return;
+ }
+ cnt += rules[i].scnt;
+ rules[i].subrules = galloc(rules[i].scnt*sizeof(struct subrule));
+ for ( j=0; j<rules[i].scnt; ++j )
+ rules[i].subrules[j].offset = getushort(ttf)+rules[i].offsets;
+ for ( j=0; j<rules[i].scnt; ++j ) {
+ fseek(ttf,rules[i].subrules[j].offset,SEEK_SET);
+ rules[i].subrules[j].bccnt = getushort(ttf);
+ if ( rules[i].subrules[j].bccnt<0 ) {
+ LogError( _("Bad class count in contextual chaining sub-table.\n") );
+ free(rules);
+return;
+ }
+ rules[i].subrules[j].bci = galloc(rules[i].subrules[j].bccnt*sizeof(uint16));
+ for ( k=0; k<rules[i].subrules[j].bccnt; ++k )
+ rules[i].subrules[j].bci[k] = getushort(ttf);
+ rules[i].subrules[j].ccnt = getushort(ttf);
+ if ( rules[i].subrules[j].ccnt<0 ) {
+ LogError( _("Bad class count in contextual chaining sub-table.\n") );
+ free(rules);
+return;
+ }
+ rules[i].subrules[j].classindeces = galloc(rules[i].subrules[j].ccnt*sizeof(uint16));
+ rules[i].subrules[j].classindeces[0] = i;
+ for ( k=1; k<rules[i].subrules[j].ccnt; ++k )
+ rules[i].subrules[j].classindeces[k] = getushort(ttf);
+ rules[i].subrules[j].fccnt = getushort(ttf);
+ if ( rules[i].subrules[j].fccnt<0 ) {
+ LogError( _("Bad class count in contextual chaining sub-table.\n") );
+ free(rules);
+return;
+ }
+ rules[i].subrules[j].fci = galloc(rules[i].subrules[j].fccnt*sizeof(uint16));
+ for ( k=0; k<rules[i].subrules[j].fccnt; ++k )
+ rules[i].subrules[j].fci[k] = getushort(ttf);
+ rules[i].subrules[j].scnt = getushort(ttf);
+ if ( rules[i].subrules[j].scnt<0 ) {
+ LogError( _("Bad count in contextual chaining sub-table.\n") );
+ free(rules);
+return;
+ }
+ rules[i].subrules[j].sl = galloc(rules[i].subrules[j].scnt*sizeof(struct seqlookup));
+ for ( k=0; k<rules[i].subrules[j].scnt; ++k ) {
+ rules[i].subrules[j].sl[k].seq = getushort(ttf);
+ if ( rules[i].subrules[j].sl[k].seq >= rules[i].subrules[j].ccnt )
+ if ( !warned2 ) {
+ LogError( _("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d max=%d\n"),
+ rules[i].subrules[j].sl[k].seq, rules[i].subrules[j].ccnt-1);
+ warned2 = true;
+ }
+ rules[i].subrules[j].sl[k].lookup = (void *) (intpt) getushort(ttf);
+ }
+ }
+ }
+
+ if ( justinuse==git_justinuse ) {
+ /* Nothing to do. This lookup doesn't really reference any glyphs */
+ /* any lookups it invokes will be processed on their own */
+ } else {
+ fpst = chunkalloc(sizeof(FPST));
+ fpst->type = gpos ? pst_chainpos : pst_chainsub;
+ fpst->format = pst_class;
+ fpst->subtable = subtable;
+ subtable->fpst = fpst;
+ fpst->next = info->possub;
+ info->possub = fpst;
+
+ fpst->rules = rule = gcalloc(cnt,sizeof(struct fpst_rule));
+ fpst->rule_cnt = cnt;
+
+ class = getClassDefTable(ttf, stoffset+classoff, info->glyph_cnt, info->g_bounds);
+ fpst->nccnt = ClassFindCnt(class,info->glyph_cnt);
+ fpst->nclass = ClassToNames(info,fpst->nccnt,class,info->glyph_cnt);
+ free(class);
+ /* The docs don't mention this, but in mangal.ttf fclassoff==0 NULL */
+ if ( bclassoff!=0 )
+ class = getClassDefTable(ttf, stoffset+bclassoff, info->glyph_cnt, info->g_bounds);
+ else
+ class = gcalloc(info->glyph_cnt,sizeof(uint16));
+ fpst->bccnt = ClassFindCnt(class,info->glyph_cnt);
+ fpst->bclass = ClassToNames(info,fpst->bccnt,class,info->glyph_cnt);
+ free(class);
+ if ( fclassoff!=0 )
+ class = getClassDefTable(ttf, stoffset+fclassoff, info->glyph_cnt, info->g_bounds);
+ else
+ class = gcalloc(info->glyph_cnt,sizeof(uint16));
+ fpst->fccnt = ClassFindCnt(class,info->glyph_cnt);
+ fpst->fclass = ClassToNames(info,fpst->fccnt,class,info->glyph_cnt);
+ free(class);
+
+ cnt = 0;
+ for ( i=0; i<rcnt; ++i ) for ( j=0; j<rules[i].scnt; ++j ) {
+ rule[cnt].u.class.nclasses = rules[i].subrules[j].classindeces;
+ rule[cnt].u.class.ncnt = rules[i].subrules[j].ccnt;
+ rules[i].subrules[j].classindeces = NULL;
+ rule[cnt].u.class.bclasses = rules[i].subrules[j].bci;
+ rule[cnt].u.class.bcnt = rules[i].subrules[j].bccnt;
+ rules[i].subrules[j].bci = NULL;
+ rule[cnt].u.class.fclasses = rules[i].subrules[j].fci;
+ rule[cnt].u.class.fcnt = rules[i].subrules[j].fccnt;
+ rules[i].subrules[j].fci = NULL;
+ rule[cnt].lookup_cnt = rules[i].subrules[j].scnt;
+ rule[cnt].lookups = rules[i].subrules[j].sl;
+ rules[i].subrules[j].sl = NULL;
+ for ( k=0; k<rule[cnt].lookup_cnt; ++k )
+ ProcessSubLookups(ttf,info,gpos,alllooks,&rule[cnt].lookups[k]);
+ ++cnt;
+ }
+ }
+
+ for ( i=0; i<rcnt; ++i ) {
+ for ( j=0; j<rules[i].scnt; ++j ) {
+ free(rules[i].subrules[j].classindeces);
+ free(rules[i].subrules[j].sl);
+ }
+ free(rules[i].subrules);
+ }
+ free(rules);
+}
+
+static void g___ContextSubTable3(FILE *ttf, int stoffset,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
+ struct lookup *alllooks, int gpos) {
+ int i, k, scnt, gcnt;
+ uint16 *coverage;
+ struct seqlookup *sl;
+ uint16 *glyphs;
+ FPST *fpst;
+ struct fpst_rule *rule;
+ int warned2 = false;
+
+ gcnt = getushort(ttf);
+ scnt = getushort(ttf);
+ if ( feof(ttf) ) {
+ LogError( _("Bad count in context chaining sub-table.\n") );
+return;
+ }
+ coverage = galloc(gcnt*sizeof(uint16));
+ for ( i=0; i<gcnt; ++i )
+ coverage[i] = getushort(ttf);
+ sl = galloc(scnt*sizeof(struct seqlookup));
+ for ( k=0; k<scnt; ++k ) {
+ sl[k].seq = getushort(ttf);
+ if ( sl[k].seq >= gcnt && !warned2 ) {
+ LogError( _("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d, max=%d\n"),
+ sl[k].seq, gcnt-1 );
+ warned2 = true;
+ }
+ sl[k].lookup = (void *) (intpt) getushort(ttf);
+ }
+
+ if ( justinuse==git_justinuse ) {
+ /* Nothing to do. This lookup doesn't really reference any glyphs */
+ /* any lookups it invokes will be processed on their own */
+ } else {
+ fpst = chunkalloc(sizeof(FPST));
+ fpst->type = gpos ? pst_contextpos : pst_contextsub;
+ fpst->format = pst_coverage;
+ fpst->subtable = subtable;
+ subtable->fpst = fpst;
+ fpst->next = info->possub;
+ info->possub = fpst;
+
+ fpst->rules = rule = gcalloc(1,sizeof(struct fpst_rule));
+ fpst->rule_cnt = 1;
+ rule->u.coverage.ncnt = gcnt;
+ rule->u.coverage.ncovers = galloc(gcnt*sizeof(char **));
+ for ( i=0; i<gcnt; ++i ) {
+ glyphs = getCoverageTable(ttf,stoffset+coverage[i],info);
+ rule->u.coverage.ncovers[i] = GlyphsToNames(info,glyphs,true);
+ free(glyphs);
+ }
+ rule->lookup_cnt = scnt;
+ rule->lookups = sl;
+ for ( k=0; k<scnt; ++k )
+ ProcessSubLookups(ttf,info,gpos,alllooks,&sl[k]);
+ }
+
+ free(coverage);
+}
+
+static void g___ChainingSubTable3(FILE *ttf, int stoffset,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
+ struct lookup *alllooks, int gpos) {
+ int i, k, scnt, gcnt, bcnt, fcnt;
+ uint16 *coverage, *bcoverage, *fcoverage;
+ struct seqlookup *sl;
+ uint16 *glyphs;
+ FPST *fpst;
+ struct fpst_rule *rule;
+ int warned2 = false;
+
+ bcnt = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError( _("End of file in context chaining subtable.\n") );
+return;
+ }
+ bcoverage = galloc(bcnt*sizeof(uint16));
+ for ( i=0; i<bcnt; ++i )
+ bcoverage[i] = getushort(ttf);
+ gcnt = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError( _("End of file in context chaining subtable.\n") );
+return;
+ }
+ coverage = galloc(gcnt*sizeof(uint16));
+ for ( i=0; i<gcnt; ++i )
+ coverage[i] = getushort(ttf);
+ fcnt = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError( _("End of file in context chaining subtable.\n") );
+return;
+ }
+ fcoverage = galloc(fcnt*sizeof(uint16));
+ for ( i=0; i<fcnt; ++i )
+ fcoverage[i] = getushort(ttf);
+ scnt = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError( _("End of file in context chaining subtable.\n") );
+return;
+ }
+ sl = galloc(scnt*sizeof(struct seqlookup));
+ for ( k=0; k<scnt; ++k ) {
+ sl[k].seq = getushort(ttf);
+ if ( sl[k].seq >= gcnt && !warned2 ) {
+ LogError( _("Attempt to apply a lookup to a location out of the range of this contextual\n lookup seq=%d, max=%d\n"),
+ sl[k].seq, gcnt-1 );
+ warned2 = true;
+ }
+ sl[k].lookup = (void *) (intpt) getushort(ttf);
+ }
+
+ if ( justinuse==git_justinuse ) {
+ /* Nothing to do. This lookup doesn't really reference any glyphs */
+ /* any lookups it invokes will be processed on their own */
+ } else {
+ fpst = chunkalloc(sizeof(FPST));
+ fpst->type = gpos ? pst_chainpos : pst_chainsub;
+ fpst->format = pst_coverage;
+ fpst->subtable = subtable;
+ subtable->fpst = fpst;
+ fpst->next = info->possub;
+ info->possub = fpst;
+
+ fpst->rules = rule = gcalloc(1,sizeof(struct fpst_rule));
+ fpst->rule_cnt = 1;
+
+ rule->u.coverage.bcnt = bcnt;
+ rule->u.coverage.bcovers = galloc(bcnt*sizeof(char **));
+ for ( i=0; i<bcnt; ++i ) {
+ glyphs = getCoverageTable(ttf,stoffset+bcoverage[i],info);
+ rule->u.coverage.bcovers[i] = GlyphsToNames(info,glyphs,true);
+ free(glyphs);
+ }
+
+ rule->u.coverage.ncnt = gcnt;
+ rule->u.coverage.ncovers = galloc(gcnt*sizeof(char **));
+ for ( i=0; i<gcnt; ++i ) {
+ glyphs = getCoverageTable(ttf,stoffset+coverage[i],info);
+ rule->u.coverage.ncovers[i] = GlyphsToNames(info,glyphs,true);
+ free(glyphs);
+ }
+
+ rule->u.coverage.fcnt = fcnt;
+ rule->u.coverage.fcovers = galloc(fcnt*sizeof(char **));
+ for ( i=0; i<fcnt; ++i ) {
+ glyphs = getCoverageTable(ttf,stoffset+fcoverage[i],info);
+ rule->u.coverage.fcovers[i] = GlyphsToNames(info,glyphs,true);
+ free(glyphs);
+ }
+
+ rule->lookup_cnt = scnt;
+ rule->lookups = sl;
+ for ( k=0; k<scnt; ++k )
+ ProcessSubLookups(ttf,info,gpos,alllooks,&sl[k]);
+ }
+
+ free(bcoverage);
+ free(coverage);
+ free(fcoverage);
+}
+
+static void gposContextSubTable(FILE *ttf, int stoffset,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable,
+ struct lookup *alllooks) {
+ switch( getushort(ttf)) {
+ case 1:
+ g___ContextSubTable1(ttf,stoffset,info,l,subtable,git_normal,alllooks,true);
+ break;
+ case 2:
+ g___ContextSubTable2(ttf,stoffset,info,l,subtable,git_normal,alllooks,true);
+ break;
+ case 3:
+ g___ContextSubTable3(ttf,stoffset,info,l,subtable,git_normal,alllooks,true);
+ break;
+ }
+}
+
+static void gposChainingSubTable(FILE *ttf, int stoffset,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable,
+ struct lookup *alllooks) {
+ switch( getushort(ttf)) {
+ case 1:
+ g___ChainingSubTable1(ttf,stoffset,info,l,subtable,git_normal,alllooks,true);
+ break;
+ case 2:
+ g___ChainingSubTable2(ttf,stoffset,info,l,subtable,git_normal,alllooks,true);
+ break;
+ case 3:
+ g___ChainingSubTable3(ttf,stoffset,info,l,subtable,git_normal,alllooks,true);
+ break;
+ }
+}
+
+static struct { uint32 tag; char *str; } tagstr[] = {
+ { CHR('v','r','t','2'), "vert" },
+ { CHR('s','m','c','p'), "sc" },
+ { CHR('s','m','c','p'), "small" },
+ { CHR('o','n','u','m'), "oldstyle" },
+ { CHR('s','u','p','s'), "superior" },
+ { CHR('s','u','b','s'), "inferior" },
+ { CHR('s','w','s','h'), "swash" },
+ { 0, NULL }
+};
+
+static void gsubSimpleSubTable(FILE *ttf, int stoffset, struct ttfinfo *info,
+ struct lookup *l, struct lookup_subtable *subtable, int justinuse) {
+ int coverage, cnt, i, j, which;
+ uint16 format;
+ uint16 *glyphs, *glyph2s=NULL;
+ int delta=0;
+
+ format=getushort(ttf);
+ if ( format!=1 && format!=2 ) /* Unknown subtable format */
+return;
+ coverage = getushort(ttf);
+ if ( format==1 ) {
+ delta = getushort(ttf);
+ } else {
+ cnt = getushort(ttf);
+ glyph2s = galloc(cnt*sizeof(uint16));
+ for ( i=0; i<cnt; ++i )
+ glyph2s[i] = getushort(ttf);
+ /* in range check comes later */
+ }
+ glyphs = getCoverageTable(ttf,stoffset+coverage,info);
+ if ( glyphs==NULL ) {
+ free(glyph2s);
+return;
+ }
+ if ( justinuse==git_findnames ) {
+ FeatureScriptLangList *fl;
+ fl = l->otlookup->features;
+ /* Unnamed glyphs get a name built of the base name and the feature tag */
+ /* assuming this lookup is tagged with a feature... */
+ if ( fl!=NULL )
+ for ( i=0; glyphs[i]!=0xffff; ++i ) if ( glyphs[i]<info->glyph_cnt ) {
+ if ( info->chars[glyphs[i]]->name!=NULL ) {
+ which = format==1 ? (uint16) (glyphs[i]+delta) : glyph2s[i];
+ if ( which<info->glyph_cnt && which>=0 && info->chars[which]!=NULL &&
+ info->chars[which]->name==NULL ) {
+ char *basename = info->chars[glyphs[i]]->name;
+ char *str;
+ char tag[5], *pt=tag;
+ for ( j=0; tagstr[j].tag!=0 && tagstr[j].tag!=fl->featuretag; ++j );
+ if ( tagstr[j].tag!=0 )
+ pt = tagstr[j].str;
+ else {
+ tag[0] = fl->featuretag>>24;
+ if ( (tag[1] = (fl->featuretag>>16)&0xff)==' ' ) tag[1] = '\0';
+ if ( (tag[2] = (fl->featuretag>>8)&0xff)==' ' ) tag[2] = '\0';
+ if ( (tag[3] = (fl->featuretag)&0xff)==' ' ) tag[3] = '\0';
+ tag[4] = '\0';
+ pt = tag;
+ }
+ str = galloc(strlen(basename)+strlen(pt)+2);
+ sprintf(str,"%s.%s", basename, pt );
+ info->chars[which]->name = str;
+ }
+ }
+ }
+ } else if ( justinuse==git_justinuse ) {
+ for ( i=0; glyphs[i]!=0xffff; ++i ) if ( glyphs[i]<info->glyph_cnt ) {
+ info->inuse[glyphs[i]]= true;
+ which = format==1 ? (uint16) (glyphs[i]+delta) : glyph2s[i];
+ info->inuse[which]= true;
+ }
+ } else if ( justinuse==git_normal ) {
+ for ( i=0; glyphs[i]!=0xffff; ++i ) if ( glyphs[i]<info->glyph_cnt && info->chars[glyphs[i]]!=NULL ) {
+ which = format==1 ? (uint16) (glyphs[i]+delta) : glyph2s[i];
+ if ( which>=info->glyph_cnt ) {
+ LogError( _("Bad substitution glyph: GID %d not less than %d\n"),
+ which, info->glyph_cnt);
+ which = 0;
+ }
+ if ( info->chars[which]!=NULL ) { /* Might be in a ttc file */
+ PST *pos = chunkalloc(sizeof(PST));
+ pos->type = pst_substitution;
+ pos->subtable = subtable;
+ pos->next = info->chars[glyphs[i]]->possub;
+ info->chars[glyphs[i]]->possub = pos;
+ pos->u.subs.variant = copy(info->chars[which]->name);
+ }
+ }
+ }
+ subtable->per_glyph_pst_or_kern = true;
+ free(glyph2s);
+ free(glyphs);
+}
+
+/* Multiple and alternate substitution lookups have the same format */
+static void gsubMultipleSubTable(FILE *ttf, int stoffset, struct ttfinfo *info,
+ struct lookup *l, struct lookup_subtable *subtable, int justinuse) {
+ int coverage, cnt, i, j, len, max;
+ uint16 format;
+ uint16 *offsets;
+ uint16 *glyphs, *glyph2s;
+ char *pt;
+ int bad;
+ int badcnt = 0;
+
+ if ( justinuse==git_findnames )
+return;
+
+ format=getushort(ttf);
+ if ( format!=1 ) /* Unknown subtable format */
+return;
+ coverage = getushort(ttf);
+ cnt = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError( _("Unexpected end of file in GSUB sub-table.\n"));
+return;
+ }
+ offsets = galloc(cnt*sizeof(uint16));
+ for ( i=0; i<cnt; ++i )
+ offsets[i] = getushort(ttf);
+ glyphs = getCoverageTable(ttf,stoffset+coverage,info);
+ if ( glyphs==NULL ) {
+ free(offsets);
+return;
+ }
+ for ( i=0; glyphs[i]!=0xffff; ++i );
+ if ( i!=cnt ) {
+ LogError( _("Coverage table specifies a different number of glyphs than the sub-table expects.\n" ));
+ if ( cnt<i )
+ glyphs[cnt] = 0xffff;
+ else
+ cnt = i;
+ }
+ max = 20;
+ glyph2s = galloc(max*sizeof(uint16));
+ for ( i=0; glyphs[i]!=0xffff; ++i ) {
+ PST *alt;
+ fseek(ttf,stoffset+offsets[i],SEEK_SET);
+ cnt = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError( _("Unexpected end of file in GSUB sub-table.\n"));
+return;
+ }
+ if ( cnt>max ) {
+ max = cnt+30;
+ glyph2s = grealloc(glyph2s,max*sizeof(uint16));
+ }
+ len = 0; bad = false;
+ for ( j=0; j<cnt; ++j ) {
+ glyph2s[j] = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError( _("Unexpected end of file in GSUB sub-table.\n" ));
+return;
+ }
+ if ( glyph2s[j]>=info->glyph_cnt ) {
+ if ( !justinuse )
+ LogError( _("Bad Multiple/Alternate substitution glyph. GID %d not less than %d\n"),
+ glyph2s[j], info->glyph_cnt );
+ if ( ++badcnt>20 )
+return;
+ glyph2s[j] = 0;
+ }
+ if ( justinuse==git_justinuse )
+ /* Do Nothing */;
+ else if ( info->chars[glyph2s[j]]==NULL )
+ bad = true;
+ else
+ len += strlen( info->chars[glyph2s[j]]->name) +1;
+ }
+ if ( justinuse==git_justinuse ) {
+ info->inuse[glyphs[i]] = 1;
+ for ( j=0; j<cnt; ++j )
+ info->inuse[glyph2s[j]] = 1;
+ } else if ( info->chars[glyphs[i]]!=NULL && !bad ) {
+ alt = chunkalloc(sizeof(PST));
+ alt->type = l->otlookup->lookup_type==gsub_multiple?pst_multiple:pst_alternate;
+ alt->subtable = subtable;
+ alt->next = info->chars[glyphs[i]]->possub;
+ info->chars[glyphs[i]]->possub = alt;
+ pt = alt->u.subs.variant = galloc(len+1);
+ *pt = '\0';
+ for ( j=0; j<cnt; ++j ) {
+ strcat(pt,info->chars[glyph2s[j]]->name);
+ strcat(pt," ");
+ }
+ if ( *pt!='\0' && pt[strlen(pt)-1]==' ' )
+ pt[strlen(pt)-1] = '\0';
+ }
+ }
+ subtable->per_glyph_pst_or_kern = true;
+ free(glyphs);
+ free(glyph2s);
+ free(offsets);
+}
+
+static void gsubLigatureSubTable(FILE *ttf, int stoffset,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse) {
+ int coverage, cnt, i, j, k, lig_cnt, cc, len;
+ uint16 *ls_offsets, *lig_offsets;
+ uint16 *glyphs, *lig_glyphs, lig;
+ char *pt;
+ PST *liga;
+
+ /* Format = */ getushort(ttf);
+ coverage = getushort(ttf);
+ cnt = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError( _("Unexpected end of file in GSUB ligature sub-table.\n" ));
+return;
+ }
+ ls_offsets = galloc(cnt*sizeof(uint16));
+ for ( i=0; i<cnt; ++i )
+ ls_offsets[i]=getushort(ttf);
+ glyphs = getCoverageTable(ttf,stoffset+coverage,info);
+ if ( glyphs==NULL )
+return;
+ for ( i=0; i<cnt; ++i ) {
+ fseek(ttf,stoffset+ls_offsets[i],SEEK_SET);
+ lig_cnt = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError( _("Unexpected end of file in GSUB ligature sub-table.\n" ));
+return;
+ }
+ lig_offsets = galloc(lig_cnt*sizeof(uint16));
+ for ( j=0; j<lig_cnt; ++j )
+ lig_offsets[j] = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError( _("Unexpected end of file in GSUB ligature sub-table.\n" ));
+return;
+ }
+ for ( j=0; j<lig_cnt; ++j ) {
+ fseek(ttf,stoffset+ls_offsets[i]+lig_offsets[j],SEEK_SET);
+ lig = getushort(ttf);
+ if ( lig>=info->glyph_cnt ) {
+ LogError( _("Bad ligature glyph. GID %d not less than %d\n"),
+ lig, info->glyph_cnt );
+ lig = 0;
+ }
+ cc = getushort(ttf);
+ if ( cc<0 || cc>100 ) {
+ LogError( _("Unlikely count of ligature components (%d), I suspect this ligature sub-\n table is garbage, I'm giving up on it.\n"), cc );
+ free(glyphs); free(lig_offsets);
+return;
+ }
+ lig_glyphs = galloc(cc*sizeof(uint16));
+ lig_glyphs[0] = glyphs[i];
+ for ( k=1; k<cc; ++k ) {
+ lig_glyphs[k] = getushort(ttf);
+ if ( lig_glyphs[k]>=info->glyph_cnt ) {
+ if ( justinuse==git_normal )
+ LogError( _("Bad ligature component glyph. GID %d not less than %d (in ligature %d)\n"),
+ lig_glyphs[k], info->glyph_cnt, lig );
+ lig_glyphs[k] = 0;
+ }
+ }
+ if ( justinuse==git_justinuse ) {
+ info->inuse[lig] = 1;
+ for ( k=0; k<cc; ++k )
+ info->inuse[lig_glyphs[k]] = 1;
+ } else if ( justinuse==git_findnames ) {
+ FeatureScriptLangList *fl = l->otlookup->features;
+ /* If our ligature glyph has no name (and its components do) */
+ /* give it a name by concatenating components with underscores */
+ /* between them, and appending the tag */
+ if ( fl!=NULL && info->chars[lig]!=NULL && info->chars[lig]->name==NULL ) {
+ int len=0;
+ for ( k=0; k<cc; ++k ) {
+ if ( info->chars[lig_glyphs[k]]==NULL || info->chars[lig_glyphs[k]]->name==NULL )
+ break;
+ len += strlen(info->chars[lig_glyphs[k]]->name)+1;
+ }
+ if ( k==cc ) {
+ char *str = galloc(len+6), *pt;
+ char tag[5];
+ tag[0] = fl->featuretag>>24;
+ if ( (tag[1] = (fl->featuretag>>16)&0xff)==' ' ) tag[1] = '\0';
+ if ( (tag[2] = (fl->featuretag>>8)&0xff)==' ' ) tag[2] = '\0';
+ if ( (tag[3] = (fl->featuretag)&0xff)==' ' ) tag[3] = '\0';
+ tag[4] = '\0';
+ *str='\0';
+ for ( k=0; k<cc; ++k ) {
+ strcat(str,info->chars[lig_glyphs[k]]->name);
+ strcat(str,"_");
+ }
+ pt = str+strlen(str);
+ pt[-1] = '.';
+ strcpy(pt,tag);
+ info->chars[lig]->name = str;
+ }
+ }
+ } else if ( info->chars[lig]!=NULL ) {
+ for ( k=len=0; k<cc; ++k )
+ if ( lig_glyphs[k]<info->glyph_cnt &&
+ info->chars[lig_glyphs[k]]!=NULL )
+ len += strlen(info->chars[lig_glyphs[k]]->name)+1;
+ liga = chunkalloc(sizeof(PST));
+ liga->type = pst_ligature;
+ liga->subtable = subtable;
+ liga->next = info->chars[lig]->possub;
+ info->chars[lig]->possub = liga;
+ liga->u.lig.lig = info->chars[lig];
+ liga->u.lig.components = pt = galloc(len);
+ for ( k=0; k<cc; ++k ) {
+ if ( lig_glyphs[k]<info->glyph_cnt &&
+ info->chars[lig_glyphs[k]]!=NULL ) {
+ strcpy(pt,info->chars[lig_glyphs[k]]->name);
+ pt += strlen(pt);
+ *pt++ = ' ';
+ }
+ }
+ pt[-1] = '\0';
+ }
+ free(lig_glyphs);
+ }
+ free(lig_offsets);
+ }
+ subtable->per_glyph_pst_or_kern = true;
+ free(ls_offsets); free(glyphs);
+}
+
+static void gsubContextSubTable(FILE *ttf, int stoffset,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
+ struct lookup *alllooks) {
+ if ( justinuse==git_findnames )
+return; /* Don't give names to these guys, they might not be unique */
+ /* ie. because these are context based there is not a one to one */
+ /* mapping between input glyphs and output glyphs. One input glyph */
+ /* may go to several output glyphs (depending on context) and so */
+ /* <input-glyph-name>"."<tag-name> would be used for several glyphs */
+ switch( getushort(ttf)) {
+ case 1:
+ g___ContextSubTable1(ttf,stoffset,info,l,subtable,justinuse,alllooks,false);
+ break;
+ case 2:
+ g___ContextSubTable2(ttf,stoffset,info,l,subtable,justinuse,alllooks,false);
+ break;
+ case 3:
+ g___ContextSubTable3(ttf,stoffset,info,l,subtable,justinuse,alllooks,false);
+ break;
+ }
+}
+
+static void gsubChainingSubTable(FILE *ttf, int stoffset,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
+ struct lookup *alllooks) {
+ if ( justinuse==git_findnames )
+return; /* Don't give names to these guys, the names might not be unique */
+ switch( getushort(ttf)) {
+ case 1:
+ g___ChainingSubTable1(ttf,stoffset,info,l,subtable,justinuse,alllooks,false);
+ break;
+ case 2:
+ g___ChainingSubTable2(ttf,stoffset,info,l,subtable,justinuse,alllooks,false);
+ break;
+ case 3:
+ g___ChainingSubTable3(ttf,stoffset,info,l,subtable,justinuse,alllooks,false);
+ break;
+ }
+}
+
+static void gsubReverseChainSubTable(FILE *ttf, int stoffset,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse) {
+ int scnt, bcnt, fcnt, i;
+ uint16 coverage, *bcoverage, *fcoverage, *sglyphs, *glyphs;
+ FPST *fpst;
+ struct fpst_rule *rule;
+
+ if ( justinuse==git_findnames )
+return; /* Don't give names to these guys, they might not be unique */
+ if ( getushort(ttf)!=1 )
+return; /* Don't understand this format type */
+
+ coverage = getushort(ttf);
+ bcnt = getushort(ttf);
+ bcoverage = galloc(bcnt*sizeof(uint16));
+ for ( i = 0 ; i<bcnt; ++i )
+ bcoverage[i] = getushort(ttf);
+ fcnt = getushort(ttf);
+ fcoverage = galloc(fcnt*sizeof(uint16));
+ for ( i = 0 ; i<fcnt; ++i )
+ fcoverage[i] = getushort(ttf);
+ scnt = getushort(ttf);
+ sglyphs = galloc((scnt+1)*sizeof(uint16));
+ for ( i = 0 ; i<scnt; ++i )
+ if (( sglyphs[i] = getushort(ttf))>=info->glyph_cnt ) {
+ LogError( _("Bad reverse contextual chaining substitution glyph: %d is not less than %d\n"),
+ sglyphs[i], info->glyph_cnt );
+ sglyphs[i] = 0;
+ }
+ sglyphs[i] = 0xffff;
+
+ if ( justinuse==git_justinuse ) {
+ for ( i = 0 ; i<scnt; ++i )
+ info->inuse[sglyphs[i]] = 1;
+ } else {
+ fpst = chunkalloc(sizeof(FPST));
+ fpst->type = pst_reversesub;
+ fpst->format = pst_reversecoverage;
+ fpst->subtable = subtable;
+ fpst->next = info->possub;
+ info->possub = fpst;
+ subtable->fpst = fpst;
+
+ fpst->rules = rule = gcalloc(1,sizeof(struct fpst_rule));
+ fpst->rule_cnt = 1;
+
+ rule->u.rcoverage.always1 = 1;
+ rule->u.rcoverage.bcnt = bcnt;
+ rule->u.rcoverage.fcnt = fcnt;
+ rule->u.rcoverage.ncovers = galloc(sizeof(char *));
+ rule->u.rcoverage.bcovers = galloc(bcnt*sizeof(char *));
+ rule->u.rcoverage.fcovers = galloc(fcnt*sizeof(char *));
+ rule->u.rcoverage.replacements = GlyphsToNames(info,sglyphs,false);
+ glyphs = getCoverageTable(ttf,stoffset+coverage,info);
+ rule->u.rcoverage.ncovers[0] = GlyphsToNames(info,glyphs,false);
+ free(glyphs);
+ for ( i=0; i<bcnt; ++i ) {
+ glyphs = getCoverageTable(ttf,stoffset+bcoverage[i],info);
+ rule->u.rcoverage.bcovers[i] = GlyphsToNames(info,glyphs,true);
+ free(glyphs);
+ }
+ for ( i=0; i<fcnt; ++i ) {
+ glyphs = getCoverageTable(ttf,stoffset+fcoverage[i],info);
+ rule->u.rcoverage.fcovers[i] = GlyphsToNames(info,glyphs,true);
+ free(glyphs);
+ }
+ rule->lookup_cnt = 0; /* substitution lookups needed for reverse chaining */
+ }
+ free(sglyphs);
+ free(fcoverage);
+ free(bcoverage);
+}
+
+static void readttfsizeparameters(FILE *ttf,int32 broken_pos,int32 correct_pos,
+ struct ttfinfo *info) {
+ int32 here;
+ /* Both of the two fonts I've seen that contain a 'size' feature */
+ /* have multiple features all of which point to the same parameter */
+ /* area. Odd. */
+ /* When Adobe first released fonts containing the 'size' feature */
+ /* they did not follow the spec, and the offset to the size parameters */
+ /* was relative to the wrong location. They claim (Aug 2006) that */
+ /* this has been fixed. Be prepared to read either style of 'size' */
+ /* following the heuristics Adobe provides */
+ int32 test[2];
+ int i, nid;
+
+ if ( info->last_size_pos==broken_pos || info->last_size_pos==correct_pos )
+return;
+
+ if ( info->last_size_pos!=0 ) {
+ LogError( _("This font, %s, has multiple GPOS 'size' features. I'm not sure how to interpret that. I shall pick one arbitrarily.\n"),
+ info->fontname==NULL? _("<Untitled>") : info->fontname );
+return;
+ }
+
+ test[0] = correct_pos; test[1] = broken_pos;
+ here = ftell(ttf);
+ for ( i=0; i<2; ++i ) {
+ fseek(ttf,test[i],SEEK_SET);
+ info->last_size_pos = test[i];
+ info->design_size = getushort(ttf);
+ if ( info->design_size==0 )
+ continue;
+ info->fontstyle_id = getushort(ttf);
+ nid = getushort(ttf);
+ info->design_range_bottom = getushort(ttf);
+ info->design_range_top = getushort(ttf);
+ if ( info->fontstyle_id == 0 && nid==0 &&
+ info->design_range_bottom==0 && info->design_range_top==0 ) {
+ /* Reasonable spec, only design size provided */
+ info->fontstyle_name = NULL;
+ break;
+ }
+ if ( info->design_size < info->design_range_bottom ||
+ info->design_size > info->design_range_top ||
+ info->design_range_bottom > info->design_range_top ||
+ nid<256 || nid>32767 )
+ continue;
+ info->fontstyle_name = FindAllLangEntries(ttf,info,nid);
+ if ( info->fontstyle_name==NULL )
+ continue;
+ else
+ break;
+ }
+ if ( i==2 ) {
+ LogError(_("The 'size' feature does not seem to follow the standard,\nnor does it conform to Adobe's early misinterpretation of\nthe standard. I cannot parse it.\n") );
+ info->design_size = info->design_range_bottom = info->design_range_top = info->fontstyle_id = 0;
+ info->fontstyle_name = NULL;
+ } else if ( i==1 ) {
+ LogError(_("The 'size' feature of this font conforms to Adobe's early misinterpretation of the otf standard.\n") );
+ }
+ fseek(ttf,here,SEEK_SET);
+
+#if 0
+ printf( "pos=%d size=%g, range=(%g,%g] id=%d name=%d\n", pos,
+ info->design_size/10.0, info->design_range_bottom/10.0, info->design_range_top/10.0,
+ info->fontstyle_id, info->fontstyle_name );
+#endif
+}
+
+static struct scripts *readttfscripts(FILE *ttf,int32 pos) {
+ int i,j,k,cnt;
+ int deflang, lcnt;
+ struct scripts *scripts;
+
+ fseek(ttf,pos,SEEK_SET);
+ cnt = getushort(ttf);
+ if ( cnt<=0 )
+return( NULL );
+ else if ( cnt>1000 ) {
+ LogError( _("Too many scripts %d\n"), cnt );
+return( NULL );
+ }
+
+ scripts = gcalloc(cnt+1,sizeof(struct scripts));
+ for ( i=0; i<cnt; ++i ) {
+ scripts[i].tag = getlong(ttf);
+ scripts[i].offset = getushort(ttf);
+ }
+ for ( i=0; i<cnt; ++i ) {
+ fseek(ttf,pos+scripts[i].offset,SEEK_SET);
+ deflang = getushort(ttf);
+ lcnt = getushort(ttf);
+ lcnt += (deflang!=0);
+ scripts[i].langcnt = lcnt;
+ scripts[i].languages = gcalloc(lcnt+1,sizeof(struct language));
+ j = 0;
+ if ( deflang!=0 ) {
+ scripts[i].languages[0].tag = CHR('d','f','l','t');
+ scripts[i].languages[0].offset = deflang+scripts[i].offset;
+ ++j;
+ }
+ for ( ; j<lcnt; ++j ) {
+ scripts[i].languages[j].tag = getlong(ttf);
+ scripts[i].languages[j].offset = scripts[i].offset+getushort(ttf);
+ }
+ for ( j=0; j<lcnt; ++j ) {
+ fseek(ttf,pos+scripts[i].languages[j].offset,SEEK_SET);
+ (void) getushort(ttf); /* lookup ordering table undefined */
+ scripts[i].languages[j].req = getushort(ttf);
+ scripts[i].languages[j].fcnt = getushort(ttf);
+ scripts[i].languages[j].features = galloc(scripts[i].languages[j].fcnt*sizeof(uint16));
+ for ( k=0; k<scripts[i].languages[j].fcnt; ++k )
+ scripts[i].languages[j].features[k] = getushort(ttf);
+ }
+ }
+return( scripts );
+}
+
+static struct feature *readttffeatures(FILE *ttf,int32 pos,int isgpos, struct ttfinfo *info) {
+ /* read the features table returning an array containing all interesting */
+ /* features */
+ int cnt;
+ int i,j;
+ struct feature *features;
+ int parameters;
+
+ fseek(ttf,pos,SEEK_SET);
+ info->feature_cnt = cnt = getushort(ttf);
+ if ( cnt<=0 )
+return( NULL );
+ else if ( cnt>1000 ) {
+ LogError( _("Too many features %d\n"), cnt );
+return( NULL );
+ }
+
+ features = gcalloc(cnt+1,sizeof(struct feature));
+ for ( i=0; i<cnt; ++i ) {
+ features[i].tag = getlong(ttf);
+ features[i].offset = getushort(ttf);
+ }
+
+ for ( i=0; i<cnt; ++i ) {
+ fseek(ttf,pos+features[i].offset,SEEK_SET);
+ parameters = getushort(ttf);
+ if ( features[i].tag==CHR('s','i','z','e') && parameters!=0 )
+ readttfsizeparameters(ttf,pos+parameters,
+ pos+parameters+features[i].offset,info);
+ features[i].lcnt = getushort(ttf);
+ if ( features[i].lcnt<0 ) {
+ LogError(_("Bad lookup count in feature.\n") );
+ features[i].lcnt = 0;
+ }
+ features[i].lookups = galloc(features[i].lcnt*sizeof(uint16));
+ for ( j=0; j<features[i].lcnt; ++j )
+ features[i].lookups[j] = getushort(ttf);
+ }
+
+return( features );
+}
+
+static struct lookup *readttflookups(FILE *ttf,int32 pos, struct ttfinfo *info, int isgpos) {
+ int cnt,i,j;
+ struct lookup *lookups;
+ OTLookup *otlookup, *last=NULL;
+ struct lookup_subtable *st;
+
+ fseek(ttf,pos,SEEK_SET);
+ info->lookup_cnt = cnt = getushort(ttf);
+ info->cur_lookups = NULL;
+ if ( cnt<=0 )
+return( NULL );
+ else if ( cnt>1000 ) {
+ LogError( _("Too many lookups %d\n"), cnt );
+return( NULL );
+ }
+
+ lookups = gcalloc(cnt+1,sizeof(struct lookup));
+ for ( i=0; i<cnt; ++i )
+ lookups[i].offset = getushort(ttf);
+ for ( i=0; i<cnt; ++i ) {
+ fseek(ttf,pos+lookups[i].offset,SEEK_SET);
+ lookups[i].type = getushort(ttf);
+ lookups[i].flags = getushort(ttf);
+ lookups[i].subtabcnt = getushort(ttf);
+ lookups[i].subtab_offsets = galloc(lookups[i].subtabcnt*sizeof(int32));
+ for ( j=0; j<lookups[i].subtabcnt; ++j )
+ lookups[i].subtab_offsets[j] = pos+lookups[i].offset+getushort(ttf);
+
+ lookups[i].otlookup = otlookup = chunkalloc(sizeof(OTLookup));
+ otlookup->lookup_index = i;
+ if ( last==NULL )
+ info->cur_lookups = otlookup;
+ else
+ last->next = otlookup;
+ last = otlookup;
+ otlookup->lookup_type = (isgpos<<8) | lookups[i].type;
+ otlookup->lookup_flags = lookups[i].flags;
+ otlookup->lookup_index = i;
+ for ( j=0; j<lookups[i].subtabcnt; ++j ) {
+ st = chunkalloc(sizeof(struct lookup_subtable));
+ st->next = otlookup->subtables;
+ st->lookup = otlookup;
+ otlookup->subtables = st;
+ }
+ }
+ if ( isgpos )
+ info->gpos_lookups = info->cur_lookups;
+ else
+ info->gsub_lookups = info->cur_lookups;
+return( lookups );
+}
+
+static void tagLookupsWithFeature(uint32 script_tag,uint32 lang_tag,
+ int required_feature, struct feature *feature, struct lookup *lookups,
+ struct ttfinfo *info) {
+ uint32 feature_tag = required_feature ? REQUIRED_FEATURE : feature->tag;
+ int i;
+ OTLookup *otlookup;
+ FeatureScriptLangList *fl;
+
+ /* The otf docs are ambiguous as to the capitalization of the default */
+ /* script. The capitalized version is correct (uncapitalized is used for languages) */
+ if ( script_tag == DEFAULT_LANG )
+ script_tag = DEFAULT_SCRIPT;
+
+ for ( i=0; i < feature->lcnt; ++i ) {
+ if ( feature->lookups[i]>=info->lookup_cnt )
+ LogError( _("Lookup out of bounds in feature table.\n") );
+ else {
+ otlookup = lookups[feature->lookups[i]].otlookup;
+ for ( fl = otlookup->features; fl!=NULL && fl->featuretag!=feature_tag; fl=fl->next );
+ if ( fl==NULL ) {
+ fl = chunkalloc(sizeof(FeatureScriptLangList));
+ fl->featuretag = feature_tag;
+ fl->next = otlookup->features;
+ otlookup->features = fl;
+ }
+ FListAppendScriptLang(fl,script_tag,lang_tag);
+ }
+ }
+}
+
+static void tagLookupsWithScript(struct scripts *scripts,
+ struct feature *features, struct lookup *lookups,struct ttfinfo *info ) {
+ int i,j;
+ struct scripts *s;
+ struct language *lang;
+ struct lookup *l;
+
+ if ( scripts==NULL || features==NULL )
+return; /* Legal, I'd guess, but not very interesting. Perhaps all lookups are controlled by the JSTF table or something */
+
+ /* First tag every lookup with all script, lang, feature combinations that*/
+ /* invoke it */
+ for ( s=scripts; s->tag!=0; ++s ) {
+ for ( lang=s->languages, i=0; i<s->langcnt; ++i, ++lang ) {
+ if ( lang->req==0xffff )
+ /* Do Nothing */;
+ else if ( lang->req>= info->feature_cnt )
+ LogError( _("Required feature out of bounds in script table.\n") );
+ else
+ tagLookupsWithFeature(s->tag,lang->tag,true,&features[lang->req],
+ lookups,info);
+ for ( j=0; j<lang->fcnt; ++j ) {
+ if ( lang->features[j]>=info->feature_cnt )
+ LogError( _("Feature out of bounds in script table.\n") );
+ else
+ tagLookupsWithFeature(s->tag,lang->tag,false,&features[lang->features[j]],
+ lookups,info);
+ }
+ }
+ }
+
+ /* The scripts got added backwards so reverse to put them in */
+ /* alphabetic order again */
+ for ( l=lookups, i=0; l->offset!=0; ++l, ++i ) {
+ OTLookup *otl = l->otlookup;
+ FeatureScriptLangList *fl;
+ struct scriptlanglist *sl, *next, *prev;
+ for ( fl=otl->features; fl!=NULL; fl=fl->next ) {
+ prev = NULL;
+ for ( sl=fl->scripts; sl!=NULL; sl = next ) {
+ next = sl->next;
+ sl->next = prev;
+ prev = sl;
+ }
+ fl->scripts = prev;
+ }
+ }
+}
+
+static void gposExtensionSubTable(FILE *ttf, int stoffset,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable,
+ struct lookup *alllooks) {
+ uint32 base = ftell(ttf), st, offset;
+ int lu_type;
+
+ /* Format = */ getushort(ttf);
+ lu_type = getushort(ttf);
+ offset = getlong(ttf);
+
+ l->otlookup->lookup_type = 0x100|lu_type;
+
+ fseek(ttf,st = base+offset,SEEK_SET);
+ switch ( lu_type ) {
+ case 1:
+ gposSimplePos(ttf,st,info,l,subtable);
+ break;
+ case 2:
+ gposKernSubTable(ttf,st,info,l,subtable);
+ break;
+ case 3:
+ gposCursiveSubTable(ttf,st,info,l,subtable);
+ break;
+ case 4: case 5: case 6:
+ gposMarkSubTable(ttf,st,info,l,subtable);
+ break;
+ case 7:
+ gposContextSubTable(ttf,st,info,l,subtable,alllooks);
+ break;
+ case 8:
+ gposChainingSubTable(ttf,st,info,l,subtable,alllooks);
+ break;
+ case 9:
+ LogError( _("This font is erroneous: it has a GPOS extension subtable that points to\nanother extension sub-table.\n") );
+ break;
+/* Any cases added here also need to go in the gposLookupSwitch */
+ default:
+ LogError( _("Unknown GPOS sub-table type: %d\n"), lu_type );
+ break;
+ }
+ if ( ftell(ttf)>info->gpos_start+info->gpos_length )
+ LogError( _("Subtable extends beyond end of GPOS table\n") );
+}
+
+static void gsubExtensionSubTable(FILE *ttf, int stoffset,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
+ struct lookup *alllooks) {
+ uint32 base = ftell(ttf), st, offset;
+ int lu_type;
+
+ /* Format = */ getushort(ttf);
+ lu_type = getushort(ttf);
+ offset = getlong(ttf);
+
+ l->otlookup->lookup_type = lu_type;
+
+ fseek(ttf,st = base+offset,SEEK_SET);
+ switch ( lu_type ) {
+ case 1:
+ gsubSimpleSubTable(ttf,st,info,l,subtable,justinuse);
+ break;
+ case 2: case 3: /* Multiple and alternate have same format, different semantics */
+ gsubMultipleSubTable(ttf,st,info,l,subtable,justinuse);
+ break;
+ case 4:
+ gsubLigatureSubTable(ttf,st,info,l,subtable,justinuse);
+ break;
+ case 5:
+ gsubContextSubTable(ttf,st,info,l,subtable,justinuse,alllooks);
+ break;
+ case 6:
+ gsubChainingSubTable(ttf,st,info,l,subtable,justinuse,alllooks);
+ break;
+ case 7:
+ LogError( _("This font is erroneous: it has a GSUB extension subtable that points to\nanother extension sub-table.\n") );
+ break;
+ case 8:
+ gsubReverseChainSubTable(ttf,st,info,l,subtable,justinuse);
+ break;
+/* Any cases added here also need to go in the gsubLookupSwitch */
+ default:
+ LogError( _("Unknown GSUB sub-table type: %d\n"), lu_type );
+ break;
+ }
+ if ( ftell(ttf)>info->gsub_start+info->gsub_length )
+ LogError( _("Subtable extends beyond end of GSUB table\n") );
+}
+
+static void gposLookupSwitch(FILE *ttf, int st,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable,
+ struct lookup *alllooks) {
+
+ switch ( l->otlookup->lookup_type ) {
+ case gpos_single:
+ gposSimplePos(ttf,st,info,l,subtable);
+ break;
+ case gpos_pair:
+ gposKernSubTable(ttf,st,info,l,subtable);
+ break;
+ case gpos_cursive:
+ gposCursiveSubTable(ttf,st,info,l,subtable);
+ break;
+ case gpos_mark2base: case gpos_mark2ligature: case gpos_mark2mark:
+ gposMarkSubTable(ttf,st,info,l,subtable);
+ break;
+ case gpos_context:
+ gposContextSubTable(ttf,st,info,l,subtable,alllooks);
+ break;
+ case gpos_contextchain:
+ gposChainingSubTable(ttf,st,info,l,subtable,alllooks);
+ break;
+ case 0x109:
+ gposExtensionSubTable(ttf,st,info,l,subtable,alllooks);
+ break;
+/* Any cases added here also need to go in the gposExtensionSubTable */
+ default:
+ LogError( _("Unknown GPOS sub-table type: %d\n"), l->otlookup->lookup_type );
+ break;
+ }
+ if ( ftell(ttf)>info->gpos_start+info->gpos_length )
+ LogError( _("Subtable extends beyond end of GPOS table\n") );
+}
+
+static void gsubLookupSwitch(FILE *ttf, int st,
+ struct ttfinfo *info, struct lookup *l, struct lookup_subtable *subtable, int justinuse,
+ struct lookup *alllooks) {
+
+ switch ( l->otlookup->lookup_type ) {
+ case gsub_single:
+ gsubSimpleSubTable(ttf,st,info,l,subtable,justinuse);
+ break;
+ case gsub_multiple: case gsub_alternate: /* Multiple and alternate have same format, different semantics */
+ gsubMultipleSubTable(ttf,st,info,l,subtable,justinuse);
+ break;
+ case gsub_ligature:
+ gsubLigatureSubTable(ttf,st,info,l,subtable,justinuse);
+ break;
+ case gsub_context:
+ gsubContextSubTable(ttf,st,info,l,subtable,justinuse,alllooks);
+ break;
+ case gsub_contextchain:
+ gsubChainingSubTable(ttf,st,info,l,subtable,justinuse,alllooks);
+ break;
+ case 7:
+ gsubExtensionSubTable(ttf,st,info,l,subtable,justinuse,alllooks);
+ break;
+ case gsub_reversecchain:
+ gsubReverseChainSubTable(ttf,st,info,l,subtable,justinuse);
+ break;
+/* Any cases added here also need to go in the gsubExtensionSubTable */
+ default:
+ LogError( _("Unknown GSUB sub-table type: %d\n"), l->otlookup->lookup_type );
+ break;
+ }
+ if ( ftell(ttf)>info->g_bounds )
+ LogError( _("Subtable extends beyond end of GSUB table\n" ));
+}
+
+static void ScriptsFree(struct scripts *scripts) {
+ int i,j;
+
+ if ( scripts==NULL )
+return;
+ for ( i=0; scripts[i].offset!=0 ; ++i ) {
+ for ( j=0; j<scripts[i].langcnt; ++j )
+ free( scripts[i].languages[j].features);
+ free(scripts[i].languages);
+ }
+ free(scripts);
+}
+
+static void FeaturesFree(struct feature *features) {
+ int i;
+
+ if ( features==NULL )
+return;
+ for ( i=0; features[i].offset!=0 ; ++i )
+ free(features[i].lookups);
+ free(features);
+}
+
+static void LookupsFree(struct lookup *lookups) {
+ int i;
+
+ for ( i=0; lookups[i].offset!=0 ; ++i ) {
+ free( lookups[i].subtab_offsets );
+ }
+ free(lookups);
+}
+
+static void ProcessGPOSGSUB(FILE *ttf,struct ttfinfo *info,int gpos,int inusetype) {
+ int k;
+ int32 base, lookup_start, st;
+ int32 script_off, feature_off;
+ struct scripts *scripts;
+ struct feature *features;
+ struct lookup *lookups, *l;
+ struct lookup_subtable *subtable;
+
+ if ( gpos ) {
+ base = info->gpos_start;
+ info->g_bounds = base + info->gpos_length;
+ } else {
+ base = info->gsub_start;
+ info->g_bounds = base + info->gsub_length;
+ }
+ fseek(ttf,base,SEEK_SET);
+ /* version = */ getlong(ttf);
+ script_off = getushort(ttf);
+ feature_off = getushort(ttf);
+ lookup_start = base+getushort(ttf);
+
+ scripts = readttfscripts(ttf,base+script_off);
+ features = readttffeatures(ttf,base+feature_off,gpos,info);
+ /* It is legal to have lookups with no features or scripts */
+ /* For example if all the lookups were controlled by the JSTF table */
+ lookups = readttflookups(ttf,lookup_start,info,gpos);
+ if ( lookups==NULL ) {
+ ScriptsFree(scripts);
+ FeaturesFree(features);
+return;
+ }
+ tagLookupsWithScript(scripts,features,lookups,info);
+ ScriptsFree(scripts); scripts = NULL;
+ FeaturesFree(features); features = NULL;
+
+ for ( l = lookups; l->offset!=0; ++l ) {
+ for ( k=0, subtable=l->otlookup->subtables; k<l->subtabcnt; ++k, subtable=subtable->next ) {
+ st = l->subtab_offsets[k];
+ fseek(ttf,st,SEEK_SET);
+ if ( gpos ) {
+ gposLookupSwitch(ttf,st,info,l,subtable,lookups);
+ } else {
+ gsubLookupSwitch(ttf,st,info,l,subtable,inusetype,lookups);
+ }
+ }
+ }
+
+ /* Then generate some user-friendly names for the all the lookups */
+ if ( inusetype==git_normal )
+ for ( l=lookups; l->offset!=0; ++l )
+ NameOTLookup(l->otlookup,NULL);
+
+ LookupsFree(lookups);
+ if ( inusetype!=git_normal && !gpos ) {
+ OTLookupListFree(info->gsub_lookups);
+ info->gsub_lookups = info->cur_lookups = NULL;
+ }
+}
+
+void readttfgsubUsed(FILE *ttf,struct ttfinfo *info) {
+ ProcessGPOSGSUB(ttf,info,false,git_justinuse);
+ info->g_bounds = 0;
+}
+
+void GuessNamesFromGSUB(FILE *ttf,struct ttfinfo *info) {
+ ProcessGPOSGSUB(ttf,info,false,git_findnames);
+ info->g_bounds = 0;
+}
+
+void readttfgpossub(FILE *ttf,struct ttfinfo *info,int gpos) {
+ ProcessGPOSGSUB(ttf,info,gpos,git_normal);
+ info->g_bounds = 0;
+}
+
+void readttfgdef(FILE *ttf,struct ttfinfo *info) {
+ int lclo, gclass, mac;
+ int coverage, cnt, i,j, format;
+ uint16 *glyphs, *lc_offsets, *offsets;
+ uint32 caret_base;
+ PST *pst;
+ SplineChar *sc;
+
+ fseek(ttf,info->gdef_start,SEEK_SET);
+ if ( getlong(ttf)!=0x00010000 )
+return;
+ info->g_bounds = info->gdef_start + info->gdef_length;
+ gclass = getushort(ttf);
+ /* attach list = */ getushort(ttf);
+ lclo = getushort(ttf); /* ligature caret list */
+ mac = getushort(ttf); /* mark attach class */
+
+ if ( gclass!=0 ) {
+ uint16 *gclasses = getClassDefTable(ttf,info->gdef_start+gclass,info->glyph_cnt, info->g_bounds);
+ for ( i=0; i<info->glyph_cnt; ++i )
+ if ( info->chars[i]!=NULL && gclasses[i]!=0 )
+ info->chars[i]->glyph_class = gclasses[i]+1;
+ free(gclasses);
+ }
+
+ if ( mac!=0 ) {
+ uint16 *mclasses = getClassDefTable(ttf,info->gdef_start+mac,info->glyph_cnt, info->g_bounds);
+ const char *format_spec = _("MarkClass-%d");
+ info->mark_class_cnt = ClassFindCnt(mclasses,info->glyph_cnt);
+ info->mark_classes = ClassToNames(info,info->mark_class_cnt,mclasses,info->glyph_cnt);
+ info->mark_class_names = galloc(info->mark_class_cnt*sizeof(char *));
+ info->mark_class_names[0] = NULL;
+ for ( i=1; i<info->mark_class_cnt; ++i ) {
+ info->mark_class_names[i] = galloc((strlen(format_spec)+10));
+ sprintf( info->mark_class_names[i], format_spec, i );
+ }
+ free(mclasses);
+ }
+
+ if ( lclo!=0 ) {
+ lclo += info->gdef_start;
+ fseek(ttf,lclo,SEEK_SET);
+ coverage = getushort(ttf);
+ cnt = getushort(ttf);
+ if ( cnt==0 )
+return;
+ lc_offsets = galloc(cnt*sizeof(uint16));
+ for ( i=0; i<cnt; ++i )
+ lc_offsets[i]=getushort(ttf);
+ glyphs = getCoverageTable(ttf,lclo+coverage,info);
+ if ( glyphs==NULL )
+return;
+ for ( i=0; i<cnt; ++i ) if ( glyphs[i]<info->glyph_cnt ) {
+ fseek(ttf,lclo+lc_offsets[i],SEEK_SET);
+ sc = info->chars[glyphs[i]];
+ for ( pst=sc->possub; pst!=NULL && pst->type!=pst_lcaret; pst=pst->next );
+ if ( pst==NULL ) {
+ pst = chunkalloc(sizeof(PST));
+ pst->next = sc->possub;
+ sc->possub = pst;
+ pst->type = pst_lcaret;
+ pst->subtable = NULL;
+ }
+ caret_base = ftell(ttf);
+ pst->u.lcaret.cnt = getushort(ttf);
+ if ( pst->u.lcaret.carets!=NULL ) free(pst->u.lcaret.carets);
+ offsets = galloc(pst->u.lcaret.cnt*sizeof(uint16));
+ for ( j=0; j<pst->u.lcaret.cnt; ++j )
+ offsets[j] = getushort(ttf);
+ pst->u.lcaret.carets = galloc(pst->u.lcaret.cnt*sizeof(int16));
+ for ( j=0; j<pst->u.lcaret.cnt; ++j ) {
+ fseek(ttf,caret_base+offsets[j],SEEK_SET);
+ format=getushort(ttf);
+ if ( format==1 ) {
+ pst->u.lcaret.carets[j] = getushort(ttf);
+ } else if ( format==2 ) {
+ pst->u.lcaret.carets[j] = 0;
+ /* point = */ getushort(ttf);
+ } else if ( format==3 ) {
+ pst->u.lcaret.carets[j] = getushort(ttf);
+ /* in device table = */ getushort(ttf);
+ } else {
+ LogError( _("!!!! Unknown caret format %d !!!!\n"), format );
+ }
+ }
+ free(offsets);
+ }
+ free(lc_offsets);
+ free(glyphs);
+ }
+ info->g_bounds = 0;
+}
+
+static void readttf_applelookup(FILE *ttf,struct ttfinfo *info,
+ void (*apply_values)(struct ttfinfo *info, int gfirst, int glast,FILE *ttf),
+ void (*apply_value)(struct ttfinfo *info, int gfirst, int glast,FILE *ttf),
+ void (*apply_default)(struct ttfinfo *info, int gfirst, int glast,void *def),
+ void *def, int allow_out_of_bounds) {
+ int format, i, first, last, data_off, cnt, prev;
+ uint32 here;
+ uint32 base = ftell(ttf);
+
+ format = getushort(ttf);
+ switch ( format ) {
+ case 0: /* Simple array */
+ apply_values(info,0,info->glyph_cnt-1,ttf);
+ break;
+ case 2: /* Segment Single */
+ /* Entry size */ getushort(ttf);
+ cnt = getushort(ttf);
+ /* search range */ getushort(ttf);
+ /* log2(cnt) */ getushort(ttf);
+ /* range shift */ getushort(ttf);
+ prev = 0;
+ for ( i=0; i<cnt; ++i ) {
+ last = getushort(ttf);
+ first = getushort(ttf);
+ if ( last<first || last>=0xffff ||
+ (!allow_out_of_bounds && last>=info->glyph_cnt )) {
+ LogError( _("Bad lookup table: format=2 (%d/%d), first=%d last=%d total glyphs in font=%d\n"),
+ i,cnt,first,last,info->glyph_cnt );
+ } else {
+ if ( apply_default!=NULL )
+ apply_default(info,prev,first-1,def);
+ apply_value(info,first,last,ttf);
+ prev = last+1;
+ }
+ }
+ break;
+ case 4: /* Segment multiple */
+ /* Entry size */ getushort(ttf);
+ cnt = getushort(ttf);
+ /* search range */ getushort(ttf);
+ /* log2(cnt) */ getushort(ttf);
+ /* range shift */ getushort(ttf);
+ prev = 0;
+ for ( i=0; i<cnt; ++i ) {
+ last = getushort(ttf);
+ first = getushort(ttf);
+ data_off = getushort(ttf);
+ if ( last<first || last>=0xffff ||
+ (!allow_out_of_bounds && last>=info->glyph_cnt )) {
+ LogError( _("Bad lookup table: format=4 (%d/%d), first=%d last=%d total glyphs in font=%d\n"),
+ i,cnt,first,last,info->glyph_cnt );
+ } else {
+ here = ftell(ttf);
+ if ( apply_default!=NULL )
+ apply_default(info,prev,first-1,def);
+ fseek(ttf,base+data_off,SEEK_SET);
+ apply_values(info,first,last,ttf);
+ fseek(ttf,here,SEEK_SET);
+ prev = last+1;
+ }
+ }
+ break;
+ case 6: /* Single table */
+ /* Entry size */ getushort(ttf);
+ cnt = getushort(ttf);
+ /* search range */ getushort(ttf);
+ /* log2(cnt) */ getushort(ttf);
+ /* range shift */ getushort(ttf);
+ prev = 0;
+ for ( i=0; i<cnt; ++i ) {
+ first = getushort(ttf);
+ if ( first>=0xffff || (!allow_out_of_bounds && first>=info->glyph_cnt )) {
+ LogError( _("Bad lookup table: format=6, first=%d total glyphs in font=%d\n"),
+ first,info->glyph_cnt );
+ } else {
+ if ( apply_default!=NULL )
+ apply_default(info,prev,first-1,def);
+ apply_value(info,first,first,ttf);
+ prev = first+1;
+ }
+ }
+ break;
+ case 8: /* Simple array */
+ first = getushort(ttf);
+ cnt = getushort(ttf);
+ if ( first+cnt>=0xffff || (!allow_out_of_bounds && first+cnt>=info->glyph_cnt )) {
+ LogError( _("Bad lookup table: format=8, first=%d cnt=%d total glyphs in font=%d\n"),
+ first,cnt,info->glyph_cnt );
+ } else {
+ if ( apply_default!=NULL ) {
+ apply_default(info,0,first-1,def);
+ apply_default(info,first+cnt,info->glyph_cnt-1,def);
+ }
+ apply_values(info,first,first+cnt-1,ttf);
+ }
+ break;
+ default:
+ LogError( _("Invalid lookup table format. %d\n"), format );
+ break;
+ }
+}
+
+static void OTLAppend(struct ttfinfo *info,OTLookup *otl,int gpos) {
+ OTLookup *prev;
+ int pos=0;
+
+ if ( gpos && info->gpos_lookups == NULL )
+ info->gpos_lookups = otl;
+ else if ( !gpos && info->gsub_lookups == NULL )
+ info->gsub_lookups = otl;
+ else {
+ prev = gpos ? info->gpos_lookups : info->gsub_lookups;
+ pos = 1;
+ while ( prev->next!=NULL ) {
+ prev = prev->next;
+ ++pos;
+ }
+ prev->next = otl;
+ }
+ otl->lookup_index = pos;
+}
+
+static OTLookup *NewMacLookup(struct ttfinfo *info,int gpos) {
+ OTLookup *otl;
+
+ otl = chunkalloc(sizeof(OTLookup));
+ otl->lookup_type = gpos ? kern_statemachine : morx_context;
+ otl->subtables = chunkalloc(sizeof(struct lookup_subtable));
+ otl->subtables->lookup = otl;
+ otl->features = chunkalloc(sizeof(FeatureScriptLangList));
+ if ( gpos )
+ otl->features->featuretag = CHR('k','e','r','n');
+ else {
+ otl->features->featuretag = (info->mort_feat<<16) | (info->mort_setting);
+ otl->features->ismac = true;
+ }
+ OTLAppend(info,otl,gpos);
+return( otl );
+}
+
+static OTLookup *NewMacSubsLookup(struct ttfinfo *info,OTLookup *parent,
+ int nest_index, OTLookup **subs) {
+ OTLookup *otl;
+ char *name, *format;
+
+ if ( subs[nest_index]!=NULL )
+return( subs[nest_index] );
+
+ /* These are nested lookups, only to be activated by a state machine */
+ /* as such they have no feature tags nor scripts of their own. */
+ otl = chunkalloc(sizeof(OTLookup));
+ otl->lookup_type = gsub_single;
+ otl->subtables = chunkalloc(sizeof(struct lookup_subtable));
+ otl->subtables->lookup = otl;
+/* GT: This is to give the name to a nested substitution lookup invoked by */
+/* GT: a statemachine. The %s is the name of the statemachine('s lookup) */
+/* GT: and the %d is n, where this lookup is the n'th defined for this state */
+/* GT: machine */
+ format = _("%s nested-substitutions %d");
+ name = galloc(strlen(parent->lookup_name)+strlen(format)+10);
+ sprintf( name, format, parent->lookup_name, nest_index );
+ otl->lookup_name = name;
+ OTLAppend(info,otl,false);
+ subs[nest_index] = otl;
+return( otl );
+}
+
+static void InfoNameOTLookup(OTLookup *otl,struct ttfinfo *info) {
+ SplineFont sf;
+
+ memset(&sf,0,sizeof(sf));
+ sf.features = info->features;
+ NameOTLookup(otl,&sf);
+}
+
+static void TTF_SetProp(struct ttfinfo *info,int gnum, int prop) {
+ int offset;
+ PST *pst;
+
+ if ( gnum<0 || gnum>=info->glyph_cnt ) {
+ LogError( _("Glyph out of bounds in 'prop' table %d\n"), gnum );
+return;
+ }
+
+ if ( prop&0x1000 ) { /* Mirror */
+ offset = (prop<<20)>>28;
+ if ( gnum+offset>=0 && gnum+offset<info->glyph_cnt &&
+ info->chars[gnum+offset]->name!=NULL ) {
+ pst = chunkalloc(sizeof(PST));
+ pst->type = pst_substitution;
+ pst->subtable = info->mort_subs_lookup->subtables;
+ FListAppendScriptLang(info->mort_subs_lookup->features,SCScriptFromUnicode(info->chars[gnum]),
+ DEFAULT_LANG);
+ pst->next = info->chars[gnum]->possub;
+ info->chars[gnum]->possub = pst;
+ pst->u.subs.variant = copy(info->chars[gnum+offset]->name);
+ }
+ }
+}
+
+static void prop_apply_values(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
+ int i;
+
+ for ( i=gfirst; i<=glast; ++i )
+ TTF_SetProp(info,i, getushort(ttf));
+}
+
+static void prop_apply_value(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
+ int i;
+ int prop;
+
+ prop = getushort(ttf);
+ for ( i=gfirst; i<=glast; ++i )
+ TTF_SetProp(info,i, prop);
+}
+
+static void prop_apply_default(struct ttfinfo *info, int gfirst, int glast,void *def) {
+ int def_prop, i;
+
+ def_prop = (intpt) def;
+ for ( i=gfirst; i<=glast; ++i )
+ TTF_SetProp(info,i, def_prop);
+}
+
+void readttfprop(FILE *ttf,struct ttfinfo *info) {
+ int def;
+
+ fseek(ttf,info->prop_start,SEEK_SET);
+ /* The one example that I've got has a wierd version, so I don't check it */
+ /* the three versions that I know about are all pretty much the same, just a few extra flags */
+ /* version = */ getlong(ttf);
+ /* format = */ getushort(ttf);
+ def = getushort(ttf);
+ info->mort_subs_lookup = NewMacLookup(info,false);
+ info->mort_subs_lookup->lookup_type = gsub_single;
+ info->mort_subs_lookup->features->featuretag = CHR('r','t','l','a');
+ info->mort_subs_lookup->features->ismac = false;
+ info->mort_subs_lookup->subtables->per_glyph_pst_or_kern = true;
+ readttf_applelookup(ttf,info,
+ prop_apply_values,prop_apply_value,
+ prop_apply_default,(void *) (intpt) def, false);
+ InfoNameOTLookup(info->mort_subs_lookup,info);
+}
+
+static void TTF_SetLcaret(struct ttfinfo *info, int gnum, int offset, FILE *ttf) {
+ uint32 here = ftell(ttf);
+ PST *pst;
+ SplineChar *sc;
+ int cnt, i;
+
+ if ( gnum<0 || gnum>=info->glyph_cnt ) {
+ LogError( _("Glyph out of bounds in 'lcar' table %d\n"), gnum );
+return;
+ } else if ( (sc=info->chars[gnum])==NULL )
+return;
+
+ fseek(ttf,info->lcar_start+offset+6,SEEK_SET); /* skip over the lcar table header */
+ cnt = getushort(ttf);
+ pst = chunkalloc(sizeof(PST));
+ pst->type = pst_lcaret;
+ pst->subtable = NULL;
+ pst->next = sc->possub;
+ sc->possub = pst;
+ pst->u.lcaret.cnt = cnt;
+ pst->u.lcaret.carets = galloc(cnt*sizeof(uint16));
+ for ( i=0; i<cnt; ++i )
+ pst->u.lcaret.carets[i] = getushort(ttf);
+ fseek(ttf,here,SEEK_SET);
+}
+
+static void lcar_apply_values(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
+ int i;
+
+ for ( i=gfirst; i<=glast; ++i )
+ TTF_SetLcaret(info,i, getushort(ttf), ttf);
+}
+
+static void lcar_apply_value(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
+ int i;
+ int offset;
+
+ offset = getushort(ttf);
+ for ( i=gfirst; i<=glast; ++i )
+ TTF_SetLcaret(info,i, offset, ttf);
+}
+
+void readttflcar(FILE *ttf,struct ttfinfo *info) {
+
+ fseek(ttf,info->lcar_start,SEEK_SET);
+ /* version = */ getlong(ttf);
+ if ( getushort(ttf)!=0 ) /* A format type of 1 has the caret locations */
+return; /* indicated by points */
+ readttf_applelookup(ttf,info,
+ lcar_apply_values,lcar_apply_value,NULL,NULL,false);
+}
+
+static void TTF_SetOpticalBounds(struct ttfinfo *info, int gnum, int left, int right) {
+ PST *pst;
+ SplineChar *sc;
+
+ if ( left==0 && right==0 )
+return;
+
+ if ( gnum<0 || gnum>=info->glyph_cnt ) {
+ LogError( _("Glyph out of bounds in 'opbd' table %d\n"), gnum );
+return;
+ } else if ( (sc=info->chars[gnum])==NULL )
+return;
+
+ if ( left!=0 ) {
+ pst = chunkalloc(sizeof(PST));
+ pst->type = pst_position;
+ pst->subtable = info->mort_subs_lookup->subtables;
+ FListAppendScriptLang(info->mort_subs_lookup->features,SCScriptFromUnicode(sc),
+ DEFAULT_LANG);
+ pst->next = sc->possub;
+ sc->possub = pst;
+ pst->u.pos.xoff = left;
+ pst->u.pos.h_adv_off = left;
+ }
+ if ( right!=0 ) {
+ pst = chunkalloc(sizeof(PST));
+ pst->type = pst_position;
+ pst->subtable = info->mort_pos_lookup2->subtables;
+ FListAppendScriptLang(info->mort_pos_lookup2->features,SCScriptFromUnicode(sc),
+ DEFAULT_LANG);
+ pst->next = sc->possub;
+ sc->possub = pst;
+ pst->u.pos.h_adv_off = -right;
+ }
+}
+
+static void opbd_apply_values(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
+ int i, left, right, offset;
+ uint32 here;
+
+ for ( i=gfirst; i<=glast; ++i ) {
+ offset = getushort(ttf);
+ here = ftell(ttf);
+ fseek(ttf,info->opbd_start+6/*opbd header*/+offset,SEEK_SET);
+ left = (int16) getushort(ttf);
+ /* top = (int16) */ getushort(ttf);
+ right = (int16) getushort(ttf);
+ /* bottom = (int16) */ getushort(ttf);
+ fseek(ttf,here,SEEK_SET);
+ TTF_SetOpticalBounds(info,i, left, right);
+ }
+}
+
+static void opbd_apply_value(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
+ int i, left, right, offset;
+ uint32 here;
+
+ offset = getushort(ttf);
+ here = ftell(ttf);
+ fseek(ttf,info->opbd_start+offset,SEEK_SET);
+ left = (int16) getushort(ttf);
+ /* top = (int16) */ getushort(ttf);
+ right = (int16) getushort(ttf);
+ /* bottom = (int16) */ getushort(ttf);
+ fseek(ttf,here,SEEK_SET);
+
+ for ( i=gfirst; i<=glast; ++i )
+ TTF_SetOpticalBounds(info,i, left, right);
+}
+
+void readttfopbd(FILE *ttf,struct ttfinfo *info) {
+
+ fseek(ttf,info->opbd_start,SEEK_SET);
+ /* version = */ getlong(ttf);
+ if ( getushort(ttf)!=0 ) /* A format type of 1 has the bounds */
+return; /* indicated by points */
+ info->mort_subs_lookup = NewMacLookup(info,true);
+ info->mort_subs_lookup->lookup_type = gpos_single;
+ info->mort_subs_lookup->features->featuretag = CHR('l','f','b','d');
+ info->mort_subs_lookup->features->ismac = false;
+ info->mort_subs_lookup->subtables->per_glyph_pst_or_kern = true;
+
+ info->mort_pos_lookup2 = NewMacLookup(info,true);
+ info->mort_pos_lookup2->lookup_type = gpos_single;
+ info->mort_pos_lookup2->features->featuretag = CHR('r','t','b','d');
+ info->mort_pos_lookup2->features->ismac = false;
+ info->mort_pos_lookup2->subtables->per_glyph_pst_or_kern = true;
+
+ readttf_applelookup(ttf,info,
+ opbd_apply_values,opbd_apply_value,NULL,NULL,false);
+ InfoNameOTLookup(info->mort_subs_lookup,info);
+ InfoNameOTLookup(info->mort_pos_lookup2,info);
+}
+
+/* Interesting. The mac allows the creation of temporary gids beyond the */
+/* range specified by the font, as long as the user never sees them. So */
+/* it seems perfectly legal for one substitution to use a gid of 1111 */
+/* if that gid never reaches output but will be converted into a real gid */
+/* by a subsequent substitution. I saw this used in a conditional situation */
+/* to provide a temporary context for a later match. */
+static SplineChar *CreateBadGid(struct ttfinfo *info,int badgid) {
+ int i;
+ SplineChar *fake;
+ char name[60];
+
+ if ( badgid<0 || badgid>=0xffff ) /* <0 should never happen, 0xffff is the special "deleted" glyph, >0xffff should never happen */
+return( NULL );
+
+ for ( i=0; i<info->badgid_cnt; ++i )
+ if ( info->badgids[i]->orig_pos == badgid )
+return( info->badgids[i] );
+
+ if ( info->badgid_cnt>=info->badgid_max )
+ info->badgids = grealloc(info->badgids,(info->badgid_max += 20)*sizeof(SplineChar *));
+ fake = SplineCharCreate();
+ fake->orig_pos = badgid;
+ sprintf( name, "Out-Of-Range-GID-%d", badgid );
+ fake->name = copy(name);
+ fake->widthset = true; /* So it doesn't just vanish on us */
+ fake->width = fake->vwidth = info->emsize;
+ info->badgids[info->badgid_cnt++] = fake;
+return( fake );
+}
+
+static void TTF_SetMortSubs(struct ttfinfo *info, int gnum, int gsubs) {
+ PST *pst;
+ SplineChar *sc, *ssc;
+
+ if ( gsubs==0 )
+return;
+
+ if ( gnum<0 || gnum>=info->glyph_cnt ) {
+ if ( !info->warned_morx_out_of_bounds_glyph ) {
+ LogError( _("Glyph out of bounds in 'mort'/'morx' table %d\n"), gnum );
+ info->warned_morx_out_of_bounds_glyph = true;
+ }
+ sc = CreateBadGid(info,gnum);
+ } else
+ sc = info->chars[gnum];
+ ssc = NULL;
+ if ( gsubs<0 || (gsubs>=info->glyph_cnt && gsubs!=0xffff)) {
+ if ( !info->warned_morx_out_of_bounds_glyph ) {
+ LogError( _("Substitute glyph out of bounds in 'mort'/'morx' table %d\n"), gsubs );
+ info->warned_morx_out_of_bounds_glyph = true;
+ }
+ ssc = CreateBadGid(info,gsubs);
+ } else if ( gsubs!=0xffff )
+ ssc=info->chars[gsubs];
+ if ( sc==NULL || (gsubs!=0xffff && ssc==NULL) )
+return;
+
+ pst = chunkalloc(sizeof(PST));
+ pst->type = pst_substitution;
+ pst->subtable = info->mort_subs_lookup->subtables;
+ if ( info->mort_subs_lookup->features!=NULL )
+ FListsAppendScriptLang(info->mort_subs_lookup->features,SCScriptFromUnicode(sc),
+ DEFAULT_LANG);
+ pst->next = sc->possub;
+ sc->possub = pst;
+ pst->u.subs.variant = gsubs!=0xffff ? copy(ssc->name) : copy(MAC_DELETED_GLYPH_NAME);
+}
+
+static void mort_apply_values(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
+ uint16 gnum;
+ int i;
+
+ for ( i=gfirst; i<=glast; ++i ) {
+ gnum = getushort(ttf);
+ TTF_SetMortSubs(info,i, gnum);
+ }
+}
+
+static void mort_apply_value(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
+ uint16 gnum;
+ int i;
+
+ gnum = getushort(ttf);
+
+ for ( i=gfirst; i<=glast; ++i )
+ TTF_SetMortSubs(info,i, gnum );
+}
+
+static void mortclass_apply_values(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
+ int i;
+
+ for ( i=gfirst; i<=glast; ++i )
+ info->morx_classes[i] = getushort(ttf);
+}
+
+static void mortclass_apply_value(struct ttfinfo *info, int gfirst, int glast,FILE *ttf) {
+ uint16 class;
+ int i;
+
+ class = getushort(ttf);
+
+ for ( i=gfirst; i<=glast; ++i )
+ info->morx_classes[i] = class;
+}
+
+int32 memlong(uint8 *data,int len, int offset) {
+ if ( offset>=0 && offset+3<len ) {
+ int ch1 = data[offset], ch2 = data[offset+1], ch3 = data[offset+2], ch4 = data[offset+3];
+return( (ch1<<24)|(ch2<<16)|(ch3<<8)|ch4 );
+ } else {
+ LogError( _("Bad font, offset out of bounds.\n") );
+return( 0 );
+ }
+}
+
+int memushort(uint8 *data,int len, int offset) {
+ if ( offset>=0 && offset+1<len ) {
+ int ch1 = data[offset], ch2 = data[offset+1];
+return( (ch1<<8)|ch2 );
+ } else {
+ LogError( _("Bad font, offset out of bounds.\n") );
+return( 0 );
+ }
+}
+
+void memputshort(uint8 *data,int offset,uint16 val) {
+ data[offset] = (val>>8);
+ data[offset+1] = val&0xff;
+}
+
+#define MAX_LIG_COMP 16
+struct statemachine {
+ uint8 *data;
+ int length;
+ uint32 nClasses;
+ uint32 classOffset, stateOffset, entryOffset, ligActOff, compOff, ligOff;
+ uint16 *classes;
+ uint16 lig_comp_classes[MAX_LIG_COMP];
+ uint16 lig_comp_glyphs[MAX_LIG_COMP];
+ int lcp;
+ uint8 *states_in_use;
+ int smax;
+ struct ttfinfo *info;
+ int cnt;
+};
+
+static void mort_figure_ligatures(struct statemachine *sm, int lcp, int off, int32 lig_offset) {
+ uint32 lig;
+ int i, j, lig_glyph;
+ PST *pst;
+ int len;
+
+ if ( lcp<0 || off+3>sm->length )
+return;
+
+ lig = memlong(sm->data,sm->length, off);
+ off += sizeof(int32);
+
+ for ( i=0; i<sm->info->glyph_cnt; ++i ) if ( sm->classes[i]==sm->lig_comp_classes[lcp] ) {
+ sm->lig_comp_glyphs[lcp] = i;
+ lig_offset += memushort(sm->data,sm->length,2*( ((((int32) lig)<<2)>>2) + i ) );
+ if ( lig&0xc0000000 ) {
+ if ( lig_offset+1 > sm->length ) {
+ LogError( _("Invalid ligature offset\n") );
+ break;
+ }
+ lig_glyph = memushort(sm->data,sm->length,lig_offset);
+ if ( lig_glyph>=sm->info->glyph_cnt ) {
+ LogError( _("Attempt to make a ligature for glyph %d out of "),
+ lig_glyph );
+ for ( j=lcp; j<sm->lcp; ++j )
+ LogError("%d ",sm->lig_comp_glyphs[j]);
+ LogError("\n");
+ } else {
+ char *comp;
+ for ( len=0, j=lcp; j<sm->lcp; ++j )
+ if ( sm->lig_comp_glyphs[j]<sm->info->glyph_cnt &&
+ sm->info->chars[sm->lig_comp_glyphs[j]]!=NULL )
+ len += strlen(sm->info->chars[sm->lig_comp_glyphs[j]]->name)+1;
+ comp = galloc(len+1);
+ *comp = '\0';
+ for ( j=lcp; j<sm->lcp; ++j ) {
+ if ( sm->lig_comp_glyphs[j]<sm->info->glyph_cnt &&
+ sm->info->chars[sm->lig_comp_glyphs[j]]!=NULL ) {
+ if ( *comp!='\0' )
+ strcat(comp," ");
+ strcat(comp,sm->info->chars[sm->lig_comp_glyphs[j]]->name);
+ }
+ }
+ if ( lig_glyph<sm->info->glyph_cnt && sm->info->chars[lig_glyph]!=NULL ) {
+ for ( pst=sm->info->chars[lig_glyph]->possub; pst!=NULL; pst=pst->next )
+ if ( pst->type==pst_ligature && pst->subtable==sm->info->mort_subs_lookup->subtables &&
+ strcmp(comp,pst->u.lig.components)==0 )
+ break;
+ /* There are cases where there will be multiple entries for */
+ /* the same lig. ie. if we have "ff" and "ffl" then there */
+ /* will be multiple entries for "ff" */
+ if ( pst == NULL ) {
+ pst = chunkalloc(sizeof(PST));
+ pst->type = pst_ligature;
+ pst->subtable = sm->info->mort_subs_lookup->subtables;
+ if ( sm->info->mort_subs_lookup->features!=NULL )
+ FListsAppendScriptLang(sm->info->mort_subs_lookup->features,
+ SCScriptFromUnicode(sm->info->chars[lig_glyph]),
+ DEFAULT_LANG);
+ pst->u.lig.components = comp;
+ pst->u.lig.lig = sm->info->chars[lig_glyph];
+ pst->next = sm->info->chars[lig_glyph]->possub;
+ sm->info->chars[lig_glyph]->possub = pst;
+ } else
+ free(comp);
+ } else {
+ LogError( _("Bad font: Ligature glyph %d is missing\n"), lig_glyph );
+ }
+ }
+ } else
+ mort_figure_ligatures(sm,lcp-1,off,lig_offset);
+ lig_offset -= memushort(sm->data,sm->length,2*( ((((int32) lig)<<2)>>2) + i ) );
+ }
+}
+
+static void follow_mort_state(struct statemachine *sm,int offset,int class) {
+ int state = (offset-sm->stateOffset)/sm->nClasses;
+ int class_top, class_bottom;
+
+ if ( state<0 || state>=sm->smax || sm->states_in_use[state] || sm->lcp>=MAX_LIG_COMP )
+return;
+ ++ sm->cnt;
+ if ( sm->cnt>=10000 ) {
+ if ( sm->cnt==10000 )
+/* GT: This is a reference to "Much Ado About Nothing". The string should read */
+/* GT: "A ligature sub-table in Apple's 'mort'/'morx' table is too\ncomplex for me to understand. I shall give up on it.\nYour ligatures may not be complete." */
+ LogError(_("In an attempt to process the ligatures of this font, I've concluded\nthat the state machine in Apple's mort/morx table is\n(like the learned constable) too cunning to be understood.\nI shall give up on it. Your ligatures may be incomplete.\n") );
+return;
+ }
+ sm->states_in_use[state] = true;
+
+ if ( class==-1 ) { class_bottom = 0; class_top = sm->nClasses; }
+ else { class_bottom = class; class_top = class+1; }
+ for ( class=class_bottom; class<class_top; ++class ) {
+ int ent = sm->data[offset+class];
+ int newState = memushort(sm->data,sm->length,sm->entryOffset+4*ent);
+ int flags = memushort(sm->data,sm->length,sm->entryOffset+4*ent+2);
+ /* If we have the same entry as state 0, then presumably we are */
+ /* ignoring the components read so far and starting over with a new */
+ /* lig (similarly for state 1) */
+ if (( state!=0 && sm->data[sm->stateOffset+class] == ent ) ||
+ (state>1 && sm->data[sm->stateOffset+sm->nClasses+class]==ent ))
+ continue;
+ if ( flags&0x8000 ) /* Set component */
+ sm->lig_comp_classes[sm->lcp++] = class;
+ if ( flags&0x3fff ) {
+ mort_figure_ligatures(sm, sm->lcp-1, flags & 0x3fff, 0);
+ } else if ( flags&0x8000 )
+ follow_mort_state(sm,newState,(flags&0x4000)?class:-1);
+ if ( flags&0x8000 )
+ --sm->lcp;
+ }
+ sm->states_in_use[state] = false;
+}
+
+static void morx_figure_ligatures(struct statemachine *sm, int lcp, int ligindex, int32 lig_offset) {
+ uint32 lig;
+ int i, j, lig_glyph;
+ PST *pst;
+ int len;
+
+ if ( lcp<0 || sm->ligActOff+4*ligindex+3>sm->length )
+return;
+
+ lig = memlong(sm->data,sm->length, sm->ligActOff+4*ligindex);
+ ++ligindex;
+
+ for ( i=0; i<sm->info->glyph_cnt; ++i ) if ( sm->classes[i]==sm->lig_comp_classes[lcp] ) {
+ sm->lig_comp_glyphs[lcp] = i;
+ lig_offset += memushort(sm->data,sm->length,sm->compOff + 2*( ((((int32) lig)<<2)>>2) + i ) );
+ if ( lig&0xc0000000 ) {
+ if ( sm->ligOff+2*lig_offset+1 > sm->length ) {
+ LogError( _("Invalid ligature offset\n") );
+ break;
+ }
+ lig_glyph = memushort(sm->data,sm->length,sm->ligOff+2*lig_offset);
+ if ( lig_glyph>=sm->info->glyph_cnt || sm->info->chars[lig_glyph]==NULL ) {
+ LogError( _("Attempt to make a ligature for (non-existent) glyph %d out of "),
+ lig_glyph );
+ for ( j=lcp; j<sm->lcp; ++j )
+ LogError("%d ",sm->lig_comp_glyphs[j]);
+ LogError("\n");
+ } else {
+ char *comp;
+ for ( len=0, j=lcp; j<sm->lcp; ++j )
+ len += strlen(sm->info->chars[sm->lig_comp_glyphs[j]]->name)+1;
+ comp = galloc(len);
+ *comp = '\0';
+ for ( j=lcp; j<sm->lcp; ++j ) {
+ if ( *comp!='\0' )
+ strcat(comp," ");
+ strcat(comp,sm->info->chars[sm->lig_comp_glyphs[j]]->name);
+ }
+ for ( pst=sm->info->chars[lig_glyph]->possub; pst!=NULL; pst=pst->next )
+ if ( pst->type==pst_ligature && pst->subtable==sm->info->mort_subs_lookup->subtables &&
+ strcmp(comp,pst->u.lig.components)==0 )
+ break;
+ /* There are cases where there will be multiple entries for */
+ /* the same lig. ie. if we have "ff" and "ffl" then there */
+ /* will be multiple entries for "ff" */
+ if ( pst == NULL ) {
+ pst = chunkalloc(sizeof(PST));
+ pst->type = pst_ligature;
+ pst->subtable = sm->info->mort_subs_lookup->subtables;
+ if ( sm->info->mort_subs_lookup->features!=NULL )
+ FListsAppendScriptLang(sm->info->mort_subs_lookup->features,
+ SCScriptFromUnicode(sm->info->chars[lig_glyph]),
+ DEFAULT_LANG);
+ pst->u.lig.components = comp;
+ pst->u.lig.lig = sm->info->chars[lig_glyph];
+ pst->next = sm->info->chars[lig_glyph]->possub;
+ sm->info->chars[lig_glyph]->possub = pst;
+ } else
+ free(comp);
+ }
+ } else
+ morx_figure_ligatures(sm,lcp-1,ligindex,lig_offset);
+ lig_offset -= memushort(sm->data,sm->length,sm->compOff + 2*( ((((int32) lig)<<2)>>2) + i ) );
+ }
+}
+
+static void follow_morx_state(struct statemachine *sm,int state,int class) {
+ int class_top, class_bottom;
+
+ if ( state<0 || state>=sm->smax || sm->states_in_use[state] || sm->lcp>=MAX_LIG_COMP )
+return;
+ ++ sm->cnt;
+ if ( sm->cnt>=10000 ) {
+ if ( sm->cnt==10000 )
+ LogError(_("In an attempt to process the ligatures of this font, I've concluded\nthat the state machine in Apple's mort/morx table is\n(like the learned constable) too cunning to be understood.\nI shall give up on it. Your ligatures may be incomplete.\n") );
+return;
+ }
+ sm->states_in_use[state] = true;
+
+ if ( class==-1 ) { class_bottom = 0; class_top = sm->nClasses; }
+ else { class_bottom = class; class_top = class+1; }
+ for ( class=class_bottom; class<class_top; ++class ) {
+ int ent = memushort(sm->data, sm->length,sm->stateOffset + 2*(state*sm->nClasses+class) );
+ int newState = memushort(sm->data,sm->length,sm->entryOffset+6*ent);
+ int flags = memushort(sm->data,sm->length,sm->entryOffset+6*ent+2);
+ int ligindex = memushort(sm->data,sm->length,sm->entryOffset+6*ent+4);
+ /* If we have the same entry as state 0, then presumably we are */
+ /* ignoring the components read so far and starting over with a new */
+ /* lig (similarly for state 1) */
+ if (( state!=0 && memushort(sm->data, sm->length,sm->stateOffset + 2*class) == ent ) ||
+ (state>1 && memushort(sm->data,sm->length, sm->stateOffset + 2*(sm->nClasses+class))==ent ))
+ continue;
+ if ( flags&0x8000 ) /* Set component */
+ sm->lig_comp_classes[sm->lcp++] = class;
+ if ( flags&0x2000 ) {
+ morx_figure_ligatures(sm, sm->lcp-1, ligindex, 0);
+ } else if ( flags&0x8000 )
+ follow_morx_state(sm,newState,(flags&0x4000)?class:-1);
+ if ( flags&0x8000 )
+ --sm->lcp;
+ }
+ sm->states_in_use[state] = false;
+}
+
+static void readttf_mortx_lig(FILE *ttf,struct ttfinfo *info,int ismorx,uint32 base,uint32 length) {
+ uint32 here;
+ struct statemachine sm;
+ int first, cnt, i;
+
+ memset(&sm,0,sizeof(sm));
+ sm.info = info;
+ here = ftell(ttf);
+ length -= here-base;
+ sm.data = galloc(length);
+ sm.length = length;
+ if ( fread(sm.data,1,length,ttf)!=length ) {
+ free(sm.data);
+ LogError( _("Bad mort ligature table. Not long enough\n"));
+return;
+ }
+ fseek(ttf,here,SEEK_SET);
+ if ( ismorx ) {
+ sm.nClasses = memlong(sm.data,sm.length, 0);
+ sm.classOffset = memlong(sm.data,sm.length, sizeof(int32));
+ sm.stateOffset = memlong(sm.data,sm.length, 2*sizeof(int32));
+ sm.entryOffset = memlong(sm.data,sm.length, 3*sizeof(int32));
+ sm.ligActOff = memlong(sm.data,sm.length, 4*sizeof(int32));
+ sm.compOff = memlong(sm.data,sm.length, 5*sizeof(int32));
+ sm.ligOff = memlong(sm.data,sm.length, 6*sizeof(int32));
+ fseek(ttf,here+sm.classOffset,SEEK_SET);
+ /* I used only to allocate space for info->glyph_cnt entries */
+ /* but some fonts use out of bounds gids as flags to contextual */
+ /* morx subtables, so allocate a full 65536 */
+ sm.classes = info->morx_classes = galloc(65536*sizeof(uint16));
+ for ( i=0; i<65536; ++i )
+ sm.classes[i] = 1; /* Out of bounds */
+ readttf_applelookup(ttf,info,
+ mortclass_apply_values,mortclass_apply_value,NULL,NULL,true);
+ sm.smax = length/(2*sm.nClasses);
+ sm.states_in_use = gcalloc(sm.smax,sizeof(uint8));
+ follow_morx_state(&sm,0,-1);
+ } else {
+ sm.nClasses = memushort(sm.data,sm.length, 0);
+ sm.classOffset = memushort(sm.data,sm.length, sizeof(uint16));
+ sm.stateOffset = memushort(sm.data,sm.length, 2*sizeof(uint16));
+ sm.entryOffset = memushort(sm.data,sm.length, 3*sizeof(uint16));
+ sm.ligActOff = memushort(sm.data,sm.length, 4*sizeof(uint16));
+ sm.compOff = memushort(sm.data,sm.length, 5*sizeof(uint16));
+ sm.ligOff = memushort(sm.data,sm.length, 6*sizeof(uint16));
+ sm.classes = galloc(info->glyph_cnt*sizeof(uint16));
+ for ( i=0; i<info->glyph_cnt; ++i )
+ sm.classes[i] = 1; /* Out of bounds */
+ first = memushort(sm.data,sm.length, sm.classOffset);
+ cnt = memushort(sm.data,sm.length, sm.classOffset+sizeof(uint16));
+ for ( i=0; i<cnt; ++i )
+ sm.classes[first+i] = sm.data[sm.classOffset+2*sizeof(uint16)+i];
+ sm.smax = length/sm.nClasses;
+ sm.states_in_use = gcalloc(sm.smax,sizeof(uint8));
+ follow_mort_state(&sm,sm.stateOffset,-1);
+ }
+ free(sm.data);
+ free(sm.states_in_use);
+ free(sm.classes);
+}
+
+struct statetable {
+ uint32 state_start;
+ int nclasses;
+ int nstates;
+ int nentries;
+ int state_offset;
+ int entry_size; /* size of individual entry */
+ int entry_extras; /* Number of extra glyph offsets */
+ int first_glyph; /* that's classifyable */
+ int nglyphs;
+ uint8 *classes;
+ uint8 *state_table; /* state_table[nstates][nclasses], each entry is an */
+ /* index into the following array */
+ uint16 *state_table2; /* morx version. States are have 2 byte entries */
+ uint16 *classes2;
+ uint8 *transitions;
+ uint32 extra_offsets[3];
+};
+
+static struct statetable *read_statetable(FILE *ttf, int ent_extras, int ismorx, struct ttfinfo *info) {
+ struct statetable *st = gcalloc(1,sizeof(struct statetable));
+ uint32 here = ftell(ttf);
+ int nclasses, class_off, state_off, entry_off;
+ int state_max, ent_max, old_state_max, old_ent_max;
+ int i, j, ent, new_state, ent_size;
+ int error;
+
+ st->state_start = here;
+
+ if ( ismorx ) {
+ nclasses = getlong(ttf);
+ class_off = getlong(ttf);
+ state_off = getlong(ttf);
+ entry_off = getlong(ttf);
+ st->extra_offsets[0] = getlong(ttf);
+ st->extra_offsets[1] = getlong(ttf);
+ st->extra_offsets[2] = getlong(ttf);
+ } else {
+ nclasses = getushort(ttf); /* Number of bytes per state in state subtable, equal to number of classes */
+ class_off = getushort(ttf);
+ state_off = getushort(ttf);
+ entry_off = getushort(ttf);
+ st->extra_offsets[0] = getushort(ttf);
+ st->extra_offsets[1] = getushort(ttf);
+ st->extra_offsets[2] = getushort(ttf);
+ }
+ st->nclasses = nclasses;
+ st->state_offset = state_off;
+
+ /* parse class subtable */
+ fseek(ttf,here+class_off,SEEK_SET);
+ error = 0;
+ if ( ismorx ) {
+ /* I used only to allocate space for info->glyph_cnt entries */
+ /* but some fonts use out of bounds gids as flags to contextual */
+ /* morx subtables, so allocate a full 65536 */
+ st->classes2 = info->morx_classes = galloc(65536*sizeof(uint16));
+ for ( i=0; i<65536; ++i )
+ st->classes2[i] = 1; /* Out of bounds */
+ readttf_applelookup(ttf,info,
+ mortclass_apply_values,mortclass_apply_value,NULL,NULL,true);
+ for ( i=0; i<65536; ++i ) {
+ if ( /*st->classes2[i]<0 ||*/ st->classes2[i]>=st->nclasses ) {
+ if ( !error )
+ LogError( _("Bad class in state machine.\n" ));
+ error = true;
+ st->classes2[i] = 1; /* Out of bounds */
+ }
+ }
+ } else {
+ st->first_glyph = getushort(ttf);
+ st->nglyphs = getushort(ttf);
+ if ( feof(ttf)) {
+ LogError(_("Bad glyph count in mort table.\n"));
+ st->nglyphs = 0;
+ }
+ st->classes = galloc(st->nglyphs);
+ fread(st->classes,1,st->nglyphs,ttf);
+ for ( i=0; i<st->nglyphs; ++i ) {
+ if ( /*st->classes[i]<0 ||*/ st->classes[i]>=st->nclasses ) {
+ if ( !error )
+ LogError( _("Bad class in state machine.\n" ));
+ error = true;
+ st->classes[i] = 1; /* Out of bounds */
+ }
+ }
+ }
+
+
+ /* The size of an entry is variable. There are 2 uint16 fields at the begin-*/
+ /* ning of all entries. There may be some number of shorts following these*/
+ /* used for indexing special tables. */
+ ent_size = 4 + 2*ent_extras;
+ st->entry_size = ent_size;
+ st->entry_extras = ent_extras;
+
+ /* Apple does not provide a way of figuring out the size of either of the */
+ /* state or entry tables, so we must parse both as we go and try to work */
+ /* out the maximum values... */
+ /* There are always at least 2 states defined. Parse them and find what */
+ /* is the biggest entry they use, then parse those entries and find what */
+ /* is the biggest state they use, and then repeat until we don't find any*/
+ /* more states or entries */
+ old_state_max = 0; old_ent_max = 0;
+ state_max = 2; ent_max = 0;
+ while ( old_state_max!=state_max ) {
+ i = old_state_max*nclasses;
+ fseek(ttf,here+state_off+(ismorx?i*sizeof(uint16):i),SEEK_SET);
+ old_state_max = state_max;
+ for ( ; i<state_max*nclasses; ++i ) {
+ ent = ismorx ? getushort(ttf) : getc(ttf);
+ if ( ent+1 > ent_max )
+ ent_max = ent+1;
+ }
+ if ( ent_max==old_ent_max ) /* Nothing more */
+ break;
+ if ( ent_max>1000 ) {
+ LogError( _("It looks to me as though there's a morx sub-table with more than 1000\n transitions. Which makes me think there's probably an error\n" ));
+ free(st);
+return( NULL );
+ }
+ fseek(ttf,here+entry_off+old_ent_max*ent_size,SEEK_SET);
+ i = old_ent_max;
+ old_ent_max = ent_max;
+ for ( ; i<ent_max; ++i ) {
+ new_state = getushort(ttf);
+ if ( !ismorx )
+ new_state = (new_state-state_off)/nclasses;
+ /* flags = */ getushort(ttf);
+ for ( j=0; j<ent_extras; ++j )
+ /* glyphOffsets[j] = */ getushort(ttf);
+ if ( new_state+1>state_max )
+ state_max = new_state+1;
+ }
+ if ( state_max>1000 ) {
+ LogError( _("It looks to me as though there's a morx sub-table with more than 1000\n states. Which makes me think there's probably an error\n" ));
+ free(st);
+return( NULL );
+ }
+ }
+
+ st->nstates = state_max;
+ st->nentries = ent_max;
+
+ fseek(ttf,here+state_off,SEEK_SET);
+ /* an array of arrays of state transitions, each represented by one byte */
+ /* which is an index into the Entry subtable, which comes next. */
+ /* One dimension is the number of states, and the other the */
+ /* number of classes (classes vary faster than states) */
+ /* The first two states are predefined, 0 is start of text, 1 start of line*/
+ if ( ismorx ) {
+ st->state_table2 = galloc(st->nstates*st->nclasses*sizeof(uint16));
+ for ( i=0; i<st->nstates*st->nclasses; ++i )
+ st->state_table2[i] = getushort(ttf);
+ } else {
+ st->state_table = galloc(st->nstates*st->nclasses);
+ fread(st->state_table,1,st->nstates*st->nclasses,ttf);
+ }
+
+ /* parse the entry subtable */
+ fseek(ttf,here+entry_off,SEEK_SET);
+ st->transitions = galloc(st->nentries*st->entry_size);
+ fread(st->transitions,1,st->nentries*st->entry_size,ttf);
+return( st );
+}
+
+static void statetablefree(struct statetable *st) {
+ free( st->classes );
+ free( st->state_table );
+ free( st->classes2 );
+ free( st->state_table2 );
+ free( st->transitions );
+ free( st );
+}
+
+static void tagSMWithScriptLang(FeatureScriptLangList *fl,
+ struct statetable *st,int ismorx,struct ttfinfo *info) {
+ int i;
+
+ if ( ismorx ) {
+ for ( i=0; i<info->glyph_cnt; ++i )
+ if ( st->classes2[i]>=4 && info->chars[i]!=NULL )
+ FListsAppendScriptLang(fl,SCScriptFromUnicode(info->chars[i]),
+ DEFAULT_LANG);
+ } else {
+ for ( i=st->first_glyph; i<st->first_glyph+st->nglyphs && i<info->glyph_cnt; ++i )
+ if ( info->chars[i]!=NULL )
+ FListsAppendScriptLang(fl,SCScriptFromUnicode(info->chars[i]),
+ DEFAULT_LANG);
+ }
+}
+
+static char **ClassesFromStateTable(struct statetable *st,int ismorx,struct ttfinfo *info) {
+ /* On the mac the first four classes should be left blank. only class 1 */
+ /* (out of bounds) is supposed to be used in the class array anyway */
+ char **classes = galloc(st->nclasses*sizeof(char *));
+ int *lens = gcalloc(st->nclasses,sizeof(int));
+ int i;
+
+
+ if ( ismorx ) {
+ for ( i=0; i<info->glyph_cnt; ++i ) if ( info->chars[i]!=NULL )
+ lens[st->classes2[i]] += strlen( info->chars[i]->name )+1;
+ if ( info->badgids!=NULL )
+ for ( i=0; i<info->badgid_cnt; ++i ) if ( info->badgids[i]!=NULL )
+ lens[st->classes2[info->badgids[i]->orig_pos]] += strlen( info->badgids[i]->name )+1;
+ } else {
+ for ( i=st->first_glyph; i<st->first_glyph+st->nglyphs && i<info->glyph_cnt; ++i )
+ if ( info->chars[i]!=NULL )
+ lens[st->classes[i-st->first_glyph]] += strlen( info->chars[i]->name )+1;
+ }
+ classes[0] = classes[1] = classes[2] = classes[3] = NULL;
+ for ( i=4; i<st->nclasses; ++i ) {
+ classes[i] = galloc(lens[i]+1);
+ *classes[i] = '\0';
+ }
+ if ( ismorx ) {
+ for ( i=0; i<info->glyph_cnt; ++i ) if ( st->classes2[i]>=4 && info->chars[i]!=NULL ) {
+ strcat(classes[st->classes2[i]],info->chars[i]->name );
+ strcat(classes[st->classes2[i]]," ");
+ }
+ if ( info->badgids!=NULL )
+ for ( i=0; i<info->badgid_cnt; ++i ) if ( info->badgids[i]!=NULL && st->classes2[info->badgids[i]->orig_pos]>=4) {
+ strcat(classes[st->classes2[info->badgids[i]->orig_pos]],info->badgids[i]->name );
+ strcat(classes[st->classes2[info->badgids[i]->orig_pos]]," ");
+ }
+ } else {
+ for ( i=st->first_glyph; i<st->first_glyph+st->nglyphs && i<info->glyph_cnt; ++i ) if ( st->classes[i-st->first_glyph]>=4 && info->chars[i]!=NULL ) {
+ strcat(classes[st->classes[i-st->first_glyph]],info->chars[i]->name );
+ strcat(classes[st->classes[i-st->first_glyph]]," " );
+ }
+ }
+ for ( i=4; i<st->nclasses; ++i ) {
+ int len = strlen(classes[i]);
+ if ( len!=0 )
+ classes[i][len-1] = '\0'; /* Remove trailing space */
+ }
+ free(lens);
+return( classes );
+}
+
+static char *NamesOfList(uint32 pos,int cnt, FILE *ttf, struct ttfinfo *info) {
+ int i, len, glyph;
+ char *str;
+
+ if ( cnt==0 )
+return(NULL);
+
+ fseek(ttf,pos,SEEK_SET);
+ for ( i=len=0; i<cnt; ++i ) {
+ glyph = getushort(ttf);
+ if ( glyph<info->glyph_cnt )
+ len += strlen(info->chars[glyph]->name)+1;
+ }
+ if ( len==0 )
+return( NULL );
+ str = galloc(len+1);
+ fseek(ttf,pos,SEEK_SET);
+ for ( i=len=0; i<cnt; ++i ) {
+ glyph = getushort(ttf);
+ if ( glyph<info->glyph_cnt ) {
+ strcpy(str+len,info->chars[glyph]->name);
+ len += strlen(info->chars[glyph]->name);
+ str[len++] = ' ';
+ }
+ }
+ str[len-1] = '\0';
+return( str );
+}
+
+#if 0
+static void RunStateFindKernDepth_(ASM *as,int state,int kdepth,uint8 *used) {
+ int j, kd;
+
+ if ( used[state] )
+return;
+ used[state] = true;
+
+ for ( j=0; j<as->class_cnt; ++j ) {
+ kd = kdepth;
+ flags = as->state[state*as->class_cnt+j];
+ if ( flags&0x8000 )
+ ++kd;
+ if ( (flags&0x3fff)!=0 ) {
+ as->state[state*as->class_cnt+j].u.kern.kcnt = kd;
+ kd = 0;
+ }
+ RunStateFindKernDepth_(as,as->state[state*as->class_cnt+j].next_state,kd,used);
+ }
+}
+
+static void RunStateFindKernDepth(ASM *as) {
+ uint8 *used = gcalloc(as->class_cnt);
+ int i;
+
+ for ( i=0; i<as->class_cnt*as->state_cnt; ++i ) {
+ as->state[i].u.kern.kerns = NULL;
+ as->state[i].u.kern.kcnt = (as->state[i].flags&0x3fff)==0 ? 0 : -1;
+ }
+ RunStateFindKernDepth_(as,0,0,used);
+ RunStateFindKernDepth_(as,1,0,used);
+}
+#endif
+
+static void KernReadKernList(FILE *ttf,uint32 pos, struct asm_state *trans) {
+/* Apple does not document how to detect the end of the list */
+/* They say "an odd value that depends on coverage" */
+/* They should say "an odd value". Any odd value terminates the list. */
+/* coverage is irrelevant */
+/* Note: List is backwards (glyphs are popped of LIFO so last glyph on */
+/* in stack gets first kern value) */
+/* There are at most 8 glyphs */
+ int i,j,k;
+ int16 buffer[8]; /* At most 8 kerns are supported */
+
+ fseek(ttf,pos,SEEK_SET);
+ for ( i=0; i<8; ++i ) {
+ buffer[i]=(int16) getushort(ttf);
+ if ( buffer[i]&1 ) {
+ buffer[i] &= ~1;
+ ++i;
+ break;
+ }
+ }
+ if ( i==0 ) {
+ trans->u.kern.kerns = NULL;
+ } else {
+ trans->u.kern.kerns = galloc(i*sizeof(int16));
+ for ( j=i-1, k=0; k<i; ++k, --j )
+ trans->u.kern.kerns[k] = buffer[j];
+ }
+ trans->u.kern.kcnt = i;
+}
+
+static void read_perglyph_subs(FILE *ttf,struct ttfinfo *info,
+ int subs_base,int subs_end,struct statetable *st,
+ uint8 *classes_subbed, int evermarked, uint8 *used) {
+ /* The file is positioned at the start of a per-glyph substitution table */
+ /* Sadly great chunks of this table have been omitted. We are where glyph */
+ /* 0 would be if it were present. We've no idea what has been omitted */
+ /* Simple checks: if the file pointer is outside of the area devoted to */
+ /* substitutions then we know it is ignorable. */
+ /* If the current glyph is not in the list of glyphs which could ever */
+ /* be substituted then we know it is ignorable. */
+ /* Note: the above list is easily figured for substitutions on the current*/
+ /* glyph, but if a substitution ever happens to a marked glyph then we */
+ /* can't guess. We could check for all classes that get marked, but that*/
+ /* doesn't work if there is a current substitution before the class is */
+ /* marked, after that we don't know what class the glyph might have */
+ /* Instead, for marked subs, we keep track of all locations which were */
+ /* used in a current-only sub, and assume that they aren't valid for us */
+ /* If the putative substitution glyph is not a valid glyph then we know */
+ /* it is ignorable */
+ int i, subs, was = info->mort_tag_mac;
+ uint32 here;
+
+ info->mort_tag_mac = false;
+ for ( i=0; i<info->glyph_cnt; ++i ) {
+ here = ftell(ttf);
+ subs = getushort(ttf);
+ if ( subs>=info->glyph_cnt && subs!=0xffff ) /* 0xffff means delete the substituted glyph */
+ continue;
+ if ( subs==0 ) /* A little risky, one could substitute notdef */
+ continue; /* but they shouldn't */
+ if ( here<subs_base )
+ continue;
+ if ( here>=subs_end )
+ break;
+ if ( evermarked ) {
+ if ( used[(here-subs_base)/2] )
+ continue;
+ } else if ( i<st->first_glyph || i>=st->first_glyph+st->nglyphs ) {
+ if ( !classes_subbed[1]) { /* Out of bounds class */
+ if ( i>=st->first_glyph+st->nglyphs )
+ break;
+ continue;
+ }
+ } else {
+ if ( !classes_subbed[st->classes[i-st->first_glyph]] )
+ continue;
+ }
+
+ if ( !evermarked )
+ used[(here-subs_base)/2] = true;
+ TTF_SetMortSubs(info, i, subs);
+ }
+ info->mort_tag_mac = was;
+}
+
+static int sm_lookupfind(int32 *lookups,int *_lm,int off) {
+ int lm = *_lm, i;
+ for ( i=0; i<=lm; ++i )
+ if ( lookups[i]==off )
+return( i );
+ (*_lm)++;
+ lookups[i] = off;
+return( i );
+}
+
+static ASM *readttf_mortx_asm(FILE *ttf,struct ttfinfo *info,int ismorx,
+ uint32 subtab_len,enum asm_type type,int extras,
+ uint32 coverage, OTLookup *otl) {
+ struct statetable *st;
+ ASM *as;
+ int i,j;
+ uint32 here = ftell(ttf);
+
+ st = read_statetable(ttf,extras,ismorx,info);
+ if ( st==NULL )
+return(NULL);
+
+ as = chunkalloc(sizeof(ASM));
+ as->type = type;
+ as->flags = coverage>>16;
+ as->class_cnt = st->nclasses;
+ as->state_cnt = st->nstates;
+ as->classes = ClassesFromStateTable(st,ismorx,info);
+ as->state = galloc(st->nclasses*st->nstates*sizeof(struct asm_state));
+ if ( otl==NULL )
+ otl = NewMacLookup(info,false);
+ otl->lookup_type = type==asm_indic ? morx_indic : type==asm_context ? morx_context : morx_insert;
+ as->subtable = otl->subtables; otl->subtables->sm = as;
+ tagSMWithScriptLang(otl->features,st,ismorx,info);
+ InfoNameOTLookup(otl,info);
+ for ( i=0; i<st->nclasses*st->nstates; ++i ) {
+ int trans;
+ if ( ismorx ) {
+ trans = st->state_table2[i];
+ as->state[i].next_state = memushort(st->transitions,st->nentries*st->entry_size,trans*st->entry_size);
+ } else {
+ trans = st->state_table[i];
+ as->state[i].next_state = (memushort(st->transitions,st->nentries*st->entry_size,trans*st->entry_size)-st->state_offset)/st->nclasses;
+ }
+ as->state[i].flags = memushort(st->transitions,st->nentries*st->entry_size,trans*st->entry_size+2);
+ if ( extras>0 )
+ as->state[i].u.context.mark_lookup = (void *) (intpt) memushort(st->transitions,st->nentries*st->entry_size, trans*st->entry_size+2+2);
+ if ( extras>1 )
+ as->state[i].u.context.cur_lookup = (void *) (intpt) memushort(st->transitions,st->nentries*st->entry_size, trans*st->entry_size+2+2+2);
+ }
+ /* Indic tables have no attached subtables, just a verb in the flag field */
+ /* so for them we are done. For the others... */
+ if ( !ismorx && type==asm_insert ) {
+ for ( i=0; i<st->nclasses*st->nstates; ++i ) {
+ char *cur=NULL, *mark=NULL;
+ if ( (as->state[i].flags&0x3e0)!=0 && as->state[i].u.context.mark_lookup!=NULL ) {
+ cur = NamesOfList(here+(intpt) as->state[i].u.context.mark_lookup,
+ (as->state[i].flags&0x3e0)>>5,ttf,info);
+ }
+ if ( (as->state[i].flags&0x01f)!=0 && as->state[i].u.context.cur_lookup!=NULL ) {
+ mark = NamesOfList(here+(intpt) as->state[i].u.context.cur_lookup,
+ as->state[i].flags&0x01f,ttf,info);
+ }
+ as->state[i].u.insert.cur_ins=cur;
+ as->state[i].u.insert.mark_ins=mark;
+ }
+ } else if ( ismorx && type == asm_insert ) {
+ for ( i=0; i<st->nclasses*st->nstates; ++i ) {
+ char *cur=NULL, *mark=NULL;
+ if ( (as->state[i].flags&0x3e0)!=0 && (intpt) as->state[i].u.context.mark_lookup!=0xffff ) {
+ cur = NamesOfList(here+st->extra_offsets[0]+((intpt) as->state[i].u.context.mark_lookup)*2,
+ (as->state[i].flags&0x3e0)>>5,ttf,info);
+ }
+ if ( (as->state[i].flags&0x01f)!=0 && ((intpt) as->state[i].u.context.cur_lookup)!=0xffff ) {
+ mark = NamesOfList(here+st->extra_offsets[0]+((intpt) as->state[i].u.context.cur_lookup)*2,
+ as->state[i].flags&0x01f,ttf,info);
+ }
+ as->state[i].u.insert.cur_ins=cur;
+ as->state[i].u.insert.mark_ins=mark;
+ }
+ } else if ( !ismorx && type == asm_context ) {
+ /* I don't see any good way to parse a per-glyph substitution table */
+ /* the problem being that most of the per-glyph table is missing */
+ /* but I don't know which bits. The offsets I'm given point to */
+ /* where glyph 0 would be if it were present in the table, but */
+ /* mostly only the bit used is present... */
+ /* I could walk though the state machine and find all classes that */
+ /* go to a specific substitution (which would tell me what glyphs */
+ /* were active). That's not hard for substitutions of the current */
+ /* glyph, but it is intractibable for marked glyphs. And I can't */
+ /* do one without the other. So I do neither. */
+ /* One thing I could test fairly easily would be to see whether */
+ /* class 1 (out of bounds) is ever available for a substitution */
+ /* (if it ever has a mark set on it or has a current substitution)*/
+ /* if not, then I can ignore any putative substitutions for class */
+ /* 1 glyphs (actually I should do this for all classes)*/
+ /* Damn. That doesn't work for marks. Because a current substitution*/
+ /* may be applied, and then the glyph gets marked. So we've no idea*/
+ /* what class the newly marked glyph might live in */
+ /* Apple's docs say the substitutions are offset from the "state */
+ /* subtable", but it seems much more likely that they are offset */
+ /* from the substitution table (given that Apple's docs are often */
+ /* wrong */ /* Apple's docs are right. not clear why that offset */
+ /* is there */
+ uint8 *classes_subbed = gcalloc(st->nclasses,1);
+ int lookup_max = -1, index, index_max;
+ int32 *lookups = galloc(st->nclasses*st->nstates*sizeof(int32));
+ uint8 *evermarked = gcalloc(st->nclasses*st->nstates,sizeof(uint8));
+ uint8 *used;
+ OTLookup **subs;
+
+ index_max = 0;
+ for ( i=0; i<st->nclasses*st->nstates; ++i ) {
+ if ( as->state[i].u.context.mark_lookup!=NULL ) {
+ index = sm_lookupfind(lookups,&lookup_max,(int16) (intpt) as->state[i].u.context.mark_lookup);
+ if ( index>index_max ) index_max = index;
+ }
+ if ( as->state[i].u.context.cur_lookup!=NULL ) {
+ index = sm_lookupfind(lookups,&lookup_max,(int16) (intpt) as->state[i].u.context.cur_lookup);
+ if ( index>index_max ) index_max = index;
+ }
+ }
+ subs = gcalloc(index_max,sizeof(OTLookup *));
+
+ for ( i=0; i<st->nclasses*st->nstates; ++i ) {
+ if ( as->state[i].u.context.mark_lookup!=NULL ) {
+ index = sm_lookupfind(lookups,&lookup_max,(int16) (intpt) as->state[i].u.context.mark_lookup);
+ evermarked[index] = true;
+ as->state[i].u.context.mark_lookup = NewMacSubsLookup(info,otl,index,subs);
+ }
+ if ( as->state[i].u.context.cur_lookup!=NULL ) {
+ index = sm_lookupfind(lookups,&lookup_max,(int16) (intpt) as->state[i].u.context.cur_lookup);
+ as->state[i].u.context.cur_lookup = NewMacSubsLookup(info,otl,index,subs);
+ }
+ }
+ used = gcalloc((subtab_len-st->extra_offsets[0]+1)/2,sizeof(uint8));
+ /* first figure things that only appear in current subs */
+ /* then go back and work on things that apply to things which are also in marked subs */
+ for ( j=0; j<2; ++j ) for ( i=0; i<=lookup_max; ++i ) if ( evermarked[i]==j ) {
+ info->mort_subs_lookup = NewMacSubsLookup(info,otl,i,subs);
+ info->mort_is_nested = true;
+ if ( !evermarked[i] ) { int k,l;
+ memset(classes_subbed,0,st->nclasses);
+ for ( k=0; k<st->nstates; ++k ) for ( l=0; l<st->nclasses; ++l ) {
+ if ( as->state[k*st->nclasses+l].u.context.cur_lookup == info->mort_subs_lookup )
+ classes_subbed[l] = true;
+ }
+ }
+ fseek(ttf,here/*+st->extra_offsets[0]*/+lookups[i]*2,SEEK_SET);
+ read_perglyph_subs(ttf,info,here+st->extra_offsets[0],here+subtab_len,
+ st,classes_subbed,evermarked[i],used);
+ }
+ info->mort_is_nested = false;
+ free(classes_subbed);
+ free(lookups);
+ free(used);
+ free(evermarked);
+ free(subs);
+ } else if ( ismorx && type == asm_context ) {
+ int lookup_max= -1;
+ uint32 *lookups;
+ OTLookup **subs;
+
+ for ( i=0; i<st->nclasses*st->nstates; ++i ) {
+ if ( (intpt) as->state[i].u.context.mark_lookup!=0xffff ) {
+ if ( ((int) (intpt) as->state[i].u.context.mark_lookup)>lookup_max )
+ lookup_max = (intpt) as->state[i].u.context.mark_lookup;
+ }
+ if ( (intpt) as->state[i].u.context.cur_lookup!=0xffff ) {
+ if ( ((int) (intpt) as->state[i].u.context.cur_lookup)>lookup_max )
+ lookup_max = (intpt) as->state[i].u.context.cur_lookup;
+ }
+ }
+ ++lookup_max;
+ subs = gcalloc(lookup_max,sizeof(OTLookup *));
+ for ( i=0; i<st->nclasses*st->nstates; ++i ) {
+ if ( (intpt) as->state[i].u.context.mark_lookup!=0xffff ) {
+ as->state[i].u.context.mark_lookup = NewMacSubsLookup(info,otl,(intpt) as->state[i].u.context.mark_lookup,subs);
+ } else
+ as->state[i].u.context.mark_lookup = NULL;
+ if ( (intpt) as->state[i].u.context.cur_lookup!=0xffff ) {
+ as->state[i].u.context.cur_lookup = NewMacSubsLookup(info,otl,(intpt) as->state[i].u.context.cur_lookup,subs);
+ } else
+ as->state[i].u.context.cur_lookup = NULL;
+ }
+ lookups = galloc(lookup_max*sizeof(uint32));
+ fseek(ttf,here+st->extra_offsets[0],SEEK_SET);
+ for ( i=0; i<lookup_max; ++i )
+ lookups[i] = getlong(ttf) + here+st->extra_offsets[0];
+ for ( i=0; i<lookup_max; ++i ) {
+ fseek(ttf,lookups[i],SEEK_SET);
+ info->mort_subs_lookup = NewMacSubsLookup(info,otl,i,subs);
+ info->mort_is_nested = true;
+ readttf_applelookup(ttf,info,
+ mort_apply_values,mort_apply_value,NULL,NULL,true);
+ }
+ info->mort_is_nested = false;
+ free(subs);
+ free(lookups);
+ } else if ( type == asm_kern ) {
+ for ( i=0; i<st->nclasses*st->nstates; ++i ) {
+ if ( (as->state[i].flags&0x3fff)!=0 ) {
+ KernReadKernList(ttf,here+(as->state[i].flags&0x3fff),
+ &as->state[i]);
+ as->state[i].flags &= ~0x3fff;
+ } else {
+ as->state[i].u.kern.kcnt = 0;
+ as->state[i].u.kern.kerns = NULL;
+ }
+ }
+ }
+ as->next = info->sm;
+ info->sm = as;
+ statetablefree(st);
+return( as );
+}
+
+static void FeatMarkAsEnabled(struct ttfinfo *info,int featureType,
+ int featureSetting);
+
+static uint32 readmortchain(FILE *ttf,struct ttfinfo *info, uint32 base, int ismorx) {
+ uint32 chain_len, nfeatures, nsubtables, default_flags;
+ uint32 enable_flags, disable_flags, flags;
+ int featureType, featureSetting;
+ int i,j,k;
+ uint32 length, coverage;
+ uint32 here;
+ uint32 tag;
+ struct tagmaskfeature { uint32 tag, enable_flags; uint16 ismac, feat, set; } tmf[32];
+ int r2l;
+
+ default_flags = getlong(ttf);
+ chain_len = getlong(ttf);
+ if ( ismorx ) {
+ nfeatures = getlong(ttf);
+ nsubtables = getlong(ttf);
+ } else {
+ nfeatures = getushort(ttf);
+ nsubtables = getushort(ttf);
+ }
+
+ k = 0;
+ for ( i=0; i<nfeatures; ++i ) {
+ featureType = getushort(ttf);
+ featureSetting = getushort(ttf);
+ enable_flags = getlong(ttf);
+ disable_flags = getlong(ttf);
+ if ( feof(ttf))
+return( chain_len );
+ if ( enable_flags & default_flags )
+ FeatMarkAsEnabled(info,featureType,featureSetting);
+ tag = MacFeatureToOTTag(featureType,featureSetting);
+ if ( enable_flags!=0 && k<32 ) {
+ if ( tag==0 ) {
+ tmf[k].tag = (featureType<<16) | featureSetting;
+ tmf[k].ismac = true;
+ } else {
+ tmf[k].tag = tag;
+ tmf[k].ismac = false;
+ }
+ tmf[k].feat = featureType;
+ tmf[k].set = featureSetting;
+ tmf[k++].enable_flags = enable_flags;
+ }
+ }
+ if ( k==0 )
+return( chain_len );
+
+ for ( i=0; i<nsubtables; ++i ) {
+ here = ftell(ttf);
+ if ( ismorx ) {
+ length = getlong(ttf);
+ coverage = getlong(ttf);
+ } else {
+ length = getushort(ttf);
+ coverage = getushort(ttf);
+ coverage = ((coverage&0xe000)<<16) | (coverage&7); /* convert to morx format */
+ }
+ r2l = (coverage & 0x40000000)? 1 : 0;
+ flags = getlong(ttf);
+ for ( j=k-1; j>=0 && (!(flags&tmf[j].enable_flags) || (tmf[j].enable_flags&~flags)!=0); --j );
+ if ( j==-1 )
+ for ( j=k-1; j>=0 && (!(flags&tmf[j].enable_flags) || tmf[j].feat==0); --j );
+ if ( j>=0 ) {
+ if ( !tmf[j].ismac &&
+ ((coverage&0xff)==0 ||
+ (coverage&0xff)==1 ||
+ (coverage&0xff)==5 )) {
+ /* Only do the opentype tag conversion if we've got a format */
+ /* we can convert to opentype. Otherwise it is useless and */
+ /* confusing */
+ tmf[j].ismac = true;
+ tmf[j].tag = (tmf[j].feat<<16) | tmf[j].set;
+ }
+ info->mort_r2l = r2l;
+ info->mort_tag_mac = tmf[j].ismac;
+ info->mort_feat = tmf[j].feat; info->mort_setting = tmf[j].set;
+ switch( coverage&0xff ) {
+ case 0: /* Indic rearangement */
+ readttf_mortx_asm(ttf,info,ismorx,length,asm_indic,0,
+ coverage,NULL);
+ break;
+ case 1: /* contextual glyph substitution */
+ readttf_mortx_asm(ttf,info,ismorx,length,asm_context,2,
+ coverage,NULL);
+ break;
+ case 2: /* ligature substitution */
+ /* Apple's ligature state machines are too weird to be */
+ /* represented easily, but I can parse them into a set */
+ /* of ligatures -- assuming they are unconditional */
+ info->mort_subs_lookup = NewMacLookup(info,false);
+ info->mort_subs_lookup->lookup_type = gsub_ligature;
+ if ( !tmf[j].ismac ) {
+ info->mort_subs_lookup->features->next = chunkalloc(sizeof(FeatureScriptLangList));
+ info->mort_subs_lookup->features->next->featuretag = tmf[j].tag;
+ info->mort_subs_lookup->features->next->ismac = false;
+ }
+ info->mort_subs_lookup->subtables->per_glyph_pst_or_kern = true;
+ readttf_mortx_lig(ttf,info,ismorx,here,length);
+ InfoNameOTLookup(info->mort_subs_lookup,info);
+ /* We can give the lookup a better name after we've made a */
+ /* guess at what scripts it involves => substitutions first */
+ break;
+ case 4: /* non-contextual glyph substitutions */
+ info->mort_subs_lookup = NewMacLookup(info,false);
+ info->mort_subs_lookup->lookup_type = gsub_single;
+ if ( !tmf[j].ismac ) {
+ info->mort_subs_lookup->features->next = chunkalloc(sizeof(FeatureScriptLangList));
+ info->mort_subs_lookup->features->next->featuretag = tmf[j].tag;
+ info->mort_subs_lookup->features->next->ismac = false;
+ }
+ info->mort_subs_lookup->subtables->per_glyph_pst_or_kern = true;
+ readttf_applelookup(ttf,info,
+ mort_apply_values,mort_apply_value,NULL,NULL,true);
+ InfoNameOTLookup(info->mort_subs_lookup,info);
+ break;
+ case 5: /* contextual glyph insertion */
+ readttf_mortx_asm(ttf,info,ismorx,length,asm_insert,2,
+ coverage,NULL);
+ break;
+ }
+ }
+ fseek(ttf, here+length, SEEK_SET );
+ }
+
+return( chain_len );
+}
+
+void readttfmort(FILE *ttf,struct ttfinfo *info) {
+ uint32 base = info->morx_start!=0 ? info->morx_start : info->mort_start;
+ uint32 here, len;
+ int ismorx;
+ int32 version;
+ int i, nchains;
+
+ fseek(ttf,base,SEEK_SET);
+ version = getlong(ttf);
+ ismorx = version == 0x00020000;
+ if ( version!=0x00010000 && version != 0x00020000 )
+return;
+ nchains = getlong(ttf);
+ if ( feof(ttf)) {
+ LogError( _("Unexpected end of file found in morx chain.\n" ));
+return;
+ }
+ info->mort_max = nchains*33; /* Maximum of one feature per bit ? */
+ for ( i=0; i<nchains; ++i ) {
+ here = ftell(ttf);
+ len = readmortchain(ttf,info,base,ismorx);
+ if ( feof(ttf)) {
+ LogError( _("Unexpected end of file found in morx chain.\n"));
+ break;
+ }
+ fseek(ttf,here+len,SEEK_SET);
+ }
+ /* Some Apple fonts use out of range gids as flags in conditional substitutions */
+ /* generally to pass information from one sub-table to another which then */
+ /* removes the flag */
+ if ( info->badgid_cnt!=0 ) {
+ /* Merge the fake glyphs in with the real ones */
+ info->chars = grealloc(info->chars,(info->glyph_cnt+info->badgid_cnt)*sizeof(SplineChar *));
+ for ( i=0; i<info->badgid_cnt; ++i ) {
+ info->chars[info->glyph_cnt+i] = info->badgids[i];
+ info->badgids[i]->orig_pos = info->glyph_cnt+i;
+ }
+ info->glyph_cnt += info->badgid_cnt;
+ free(info->badgids);
+ }
+}
+
+/* Apple's docs imply that kerning info is always provided left to right, even*/
+/* for right to left scripts. My guess is that their docs are wrong, as they */
+/* often are, but if that be so then we need code in here to reverse */
+/* the order of the characters for right to left since pfaedit's convention */
+/* is to follow writing order rather than to go left to right */
+void readttfkerns(FILE *ttf,struct ttfinfo *info) {
+ int tabcnt, len, coverage,i,j, npairs, version, format, flags_good, tab;
+ int left, right, offset, array, rowWidth;
+ int header_size;
+ KernPair *kp;
+ KernClass *kc;
+ uint32 begin_table;
+ uint16 *class1, *class2;
+ int tupleIndex;
+ int isv;
+ SplineChar **chars;
+ OTLookup *otl;
+
+ fseek(ttf,info->kern_start,SEEK_SET);
+ version = getushort(ttf);
+ tabcnt = getushort(ttf);
+ if ( version!=0 ) {
+ fseek(ttf,info->kern_start,SEEK_SET);
+ version = getlong(ttf);
+ tabcnt = getlong(ttf);
+ }
+ for ( tab=0; tab<tabcnt; ++tab ) {
+ begin_table = ftell(ttf);
+ if ( version==0 ) {
+ /* version = */ getushort(ttf);
+ len = getushort(ttf);
+ coverage = getushort(ttf);
+ format = coverage>>8;
+ flags_good = ((coverage&7)<=1);
+ isv = !(coverage&1);
+ tupleIndex = -1;
+ header_size = 6;
+ } else {
+ len = getlong(ttf);
+ coverage = getushort(ttf);
+ /* Apple has reordered the bits */
+ format = (coverage&0xff);
+ flags_good = ((coverage&0xdf00)==0 || (coverage&0xdf00)==0x8000);
+ isv = coverage&0x8000? 1 : 0;
+ tupleIndex = getushort(ttf);
+ if ( coverage&0x2000 ) {
+ if ( info->variations==NULL )
+ flags_good = false; /* Ignore if we failed to load the tuple data */
+ else if ( tupleIndex>=info->variations->tuple_count )
+ flags_good = false; /* Bad tuple */
+ } else
+ tupleIndex = -1;
+ header_size = 8;
+ }
+ otl = NULL;
+ if ( flags_good ) {
+ otl = NewMacLookup(info,true);
+ otl->lookup_type = gpos_pair;
+ if ( isv ) {
+ otl->features->featuretag = CHR('v','k','r','n');
+ otl->features->ismac = false;
+ }
+ otl->subtables->per_glyph_pst_or_kern = true;
+ otl->subtables->vertical_kerning = isv;
+ }
+ if ( flags_good && format==0 ) {
+ /* format 0, horizontal kerning data (as pairs) not perpendicular */
+ chars = tupleIndex==-1 ? info->chars : info->variations->tuples[tupleIndex].chars;
+ npairs = getushort(ttf);
+ /* searchRange = */ getushort(ttf);
+ /* entrySelector = */ getushort(ttf);
+ /* rangeShift = */ getushort(ttf);
+ otl->subtables[0].per_glyph_pst_or_kern = true;
+ for ( j=0; j<npairs; ++j ) {
+ left = getushort(ttf);
+ right = getushort(ttf);
+ offset = (short) getushort(ttf);
+ if ( left<info->glyph_cnt && right<info->glyph_cnt &&
+ chars[left]!=NULL && chars[right]!=NULL ) {
+ kp = chunkalloc(sizeof(KernPair));
+ kp->sc = chars[right];
+ kp->off = offset;
+ kp->subtable = otl->subtables;
+ FListsAppendScriptLang(otl->features,SCScriptFromUnicode(chars[left]),
+ DEFAULT_LANG);
+ if ( isv ) {
+ kp->next = chars[left]->vkerns;
+ chars[left]->vkerns = kp;
+ } else {
+ kp->next = chars[left]->kerns;
+ chars[left]->kerns = kp;
+ }
+ } else
+ LogError( _("Bad kern pair: glyphs %d & %d must be less than %d\n"),
+ left, right, info->glyph_cnt );
+ }
+ InfoNameOTLookup(otl,info);
+ } else if ( flags_good && format==1 ) {
+ /* format 1 is an apple state machine which can handle weird cases */
+ /* OpenType's spec doesn't document this */
+ /* Apple's docs are wrong about this table, they claim */
+ /* there is a special value which marks the end of the kerning */
+ /* lists. In fact there is no such value, the list is as long */
+ /* as there are things on the kern stack */
+ otl->lookup_type = kern_statemachine;
+ readttf_mortx_asm(ttf,info,false,len-header_size,asm_kern,0,
+ isv ? 0x80000000 : 0 /* coverage doesn't really apply */,otl);
+ fseek(ttf,begin_table+len,SEEK_SET);
+ } else if ( flags_good && (format==2 || format==3 )) {
+ /* two class based formats */
+ KernClass **khead, **klast;
+ if ( isv && tupleIndex==-1 ) {
+ khead = &info->vkhead;
+ klast = &info->vklast;
+ } else if ( tupleIndex==-1 ) {
+ khead = &info->khead;
+ klast = &info->klast;
+ } else if ( isv ) {
+ khead = &info->variations->tuples[tupleIndex].vkhead;
+ klast = &info->variations->tuples[tupleIndex].vklast;
+ } else {
+ khead = &info->variations->tuples[tupleIndex].khead;
+ klast = &info->variations->tuples[tupleIndex].klast;
+ }
+ if ( *khead==NULL )
+ *khead = kc = chunkalloc(sizeof(KernClass));
+ else
+ kc = (*klast)->next = chunkalloc(sizeof(KernClass));
+ *klast = kc;
+ if ( format==2 ) {
+ rowWidth = getushort(ttf);
+ left = getushort(ttf);
+ right = getushort(ttf);
+ array = getushort(ttf);
+ kc->second_cnt = rowWidth/sizeof(uint16);
+ class1 = getAppleClassTable(ttf, begin_table+left, info->glyph_cnt, array, rowWidth );
+ class2 = getAppleClassTable(ttf, begin_table+right, info->glyph_cnt, 0, sizeof(uint16) );
+ for ( i=0; i<info->glyph_cnt; ++i )
+ if ( class1[i]>kc->first_cnt )
+ kc->first_cnt = class1[i];
+ ++ kc->first_cnt;
+ kc->offsets = galloc(kc->first_cnt*kc->second_cnt*sizeof(int16));
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ kc->adjusts = gcalloc(kc->first_cnt*kc->second_cnt,sizeof(DeviceTable));
+#endif
+ fseek(ttf,begin_table+array,SEEK_SET);
+ for ( i=0; i<kc->first_cnt*kc->second_cnt; ++i )
+ kc->offsets[i] = getushort(ttf);
+ } else {
+ /* format 3, horizontal kerning data (as classes limited to 256 entries) */
+ /* OpenType's spec doesn't document this */
+ int gc, kv, flags;
+ int16 *kvs;
+ gc = getushort(ttf);
+ kv = getc(ttf);
+ kc->first_cnt = getc(ttf);
+ kc->second_cnt = getc(ttf);
+ flags = getc(ttf);
+ if ( gc>info->glyph_cnt )
+ LogError( _("Kerning subtable 3 says the glyph count is %d, but maxp says %d\n"),
+ gc, info->glyph_cnt );
+ class1 = gcalloc(gc>info->glyph_cnt?gc:info->glyph_cnt,sizeof(uint16));
+ class2 = gcalloc(gc>info->glyph_cnt?gc:info->glyph_cnt,sizeof(uint16));
+ kvs = galloc(kv*sizeof(int16));
+ kc->offsets = galloc(kc->first_cnt*kc->second_cnt*sizeof(int16));
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ kc->adjusts = gcalloc(kc->first_cnt*kc->second_cnt,sizeof(DeviceTable));
+#endif
+ for ( i=0; i<kv; ++i )
+ kvs[i] = (int16) getushort(ttf);
+ for ( i=0; i<gc; ++i )
+ class1[i] = getc(ttf);
+ for ( i=0; i<gc; ++i )
+ class2[i] = getc(ttf);
+ for ( i=0; i<kc->first_cnt*kc->second_cnt; ++i )
+ kc->offsets[i] = kvs[getc(ttf)];
+ free(kvs);
+ }
+ kc->firsts = ClassToNames(info,kc->first_cnt,class1,info->glyph_cnt);
+ kc->seconds = ClassToNames(info,kc->second_cnt,class2,info->glyph_cnt);
+ for ( i=0; i<info->glyph_cnt; ++i ) {
+ if ( class1[i]>=4 && info->chars[i]!=NULL )
+ FListsAppendScriptLang(otl->features,
+ SCScriptFromUnicode(info->chars[i]),
+ DEFAULT_LANG);
+ }
+ free(class1); free(class2);
+ fseek(ttf,begin_table+len,SEEK_SET);
+ otl->subtables[0].kc = kc;
+ kc->subtable = otl->subtables;
+ InfoNameOTLookup(otl,info);
+ } else {
+ fseek(ttf,len-header_size,SEEK_CUR);
+ }
+ }
+}
+
+void readmacfeaturemap(FILE *ttf,struct ttfinfo *info) {
+ MacFeat *last=NULL, *cur;
+ struct macsetting *slast, *scur;
+ struct fs { int n; int off; } *fs;
+ int featcnt, i, j, flags;
+
+ fseek(ttf,info->feat_start,SEEK_SET);
+ /* version =*/ getfixed(ttf);
+ featcnt = getushort(ttf);
+ /* reserved */ getushort(ttf);
+ /* reserved */ getlong(ttf);
+ if ( feof(ttf)) {
+ LogError( _("End of file in feat table.\n" ));
+return;
+ }
+
+ fs = galloc(featcnt*sizeof(struct fs));
+ for ( i=0; i<featcnt; ++i ) {
+ cur = chunkalloc(sizeof(MacFeat));
+ if ( last==NULL )
+ info->features = cur;
+ else
+ last->next = cur;
+ last = cur;
+
+ cur->feature = getushort(ttf);
+ fs[i].n = getushort(ttf);
+ fs[i].off = getlong(ttf);
+ flags = getushort(ttf);
+ cur->strid = getushort(ttf);
+ if ( flags&0x8000 ) cur->ismutex = true;
+ if ( flags&0x4000 )
+ cur->default_setting = flags&0xff;
+ if ( feof(ttf)) {
+ free(fs);
+ LogError( _("End of file in feat table.\n" ));
+return;
+ }
+ }
+
+ for ( i=0, cur=info->features; i<featcnt; ++i, cur = cur->next ) {
+ fseek(ttf,info->feat_start+fs[i].off,SEEK_SET);
+ slast = NULL;
+ for ( j=0; j<fs[i].n; ++j ) {
+ scur = chunkalloc(sizeof(struct macsetting));
+ if ( slast==NULL )
+ cur->settings = scur;
+ else
+ slast->next = scur;
+ slast = scur;
+
+ scur->setting = getushort(ttf);
+ scur->strid = getushort(ttf);
+ if ( feof(ttf)) {
+ free(fs);
+ LogError( _("End of file in feat table.\n") );
+return;
+ }
+ }
+ }
+ free(fs);
+}
+
+static void FeatMarkAsEnabled(struct ttfinfo *info,int featureType,
+ int featureSetting) {
+ MacFeat *f;
+ struct macsetting *s;
+
+ for ( f = info->features; f!=NULL && f->feature!=featureType; f=f->next );
+ if ( f==NULL )
+return;
+ if ( f->ismutex ) {
+ for ( s=f->settings ; s!=NULL; s=s->next )
+ s->initially_enabled = ( s->setting==featureSetting );
+ f->default_setting = featureSetting;
+ } else {
+ for ( s=f->settings ; s!=NULL && s->setting!=featureSetting; s=s->next );
+ if ( s!=NULL )
+ s->initially_enabled = true;
+ }
+return;
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/parsettfvar.c b/Build/source/libs/luafontforge/fontforge/fontforge/parsettfvar.c
new file mode 100644
index 00000000000..07852f9f648
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/parsettfvar.c
@@ -0,0 +1,778 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include <chardata.h>
+#include <utype.h>
+#include <ustring.h>
+#include <math.h>
+#include <locale.h>
+#include <gwidget.h>
+#include "ttf.h"
+
+/***************************************************************************/
+/* */
+/* Apple documents these tables at */
+/* http:// developer.apple.com/fonts/TTRefMan/RM06/Chap6[fgca]var.html */
+/* The documentation for fvar is inconsistant. At one point it says that */
+/* countSizePairs should be 3, at another point 2. It should be 2. */
+/* The documentation for gvar is not intelligable, cvar refers you to gvar */
+/* and is thus also incomprehensible */
+/* The documentation for avar appears correct, but as Apple has no fonts */
+/* with an 'avar' table, so it's hard to test. */
+/* */
+/***************************************************************************/
+
+/* Parse Apple's variation tables (font, glyph, cvt and axis) */
+/* To be interesting a font must have an fvar and a gvar */
+/* If it's hinted it better have a cvar */
+/* It may have an avar if it wants to be complicated */
+
+void VariationFree(struct ttfinfo *info) {
+ int i,j;
+ struct variations *variation = info->variations;
+
+ if ( variation==NULL )
+return;
+ if ( variation->axes!=NULL ) {
+ for ( i=0; i<variation->axis_count; ++i ) {
+ free(variation->axes[i].mapfrom);
+ free(variation->axes[i].mapto);
+ }
+ free(variation->axes);
+ }
+ if ( variation->instances!=NULL ) {
+ for ( i=0; i<variation->instance_count; ++i ) {
+ free(variation->instances[i].coords);
+ }
+ free(variation->instances);
+ }
+ if ( variation->tuples!=NULL ) {
+ for ( i=0; i<variation->tuple_count; ++i ) {
+ free(variation->tuples[i].coords);
+ if ( variation->tuples[i].chars!=NULL )
+ for ( j=0; j<info->glyph_cnt; ++j )
+ SplineCharFree(variation->tuples[i].chars[j]);
+ free(variation->tuples[i].chars);
+ KernClassListFree(variation->tuples[i].khead);
+ KernClassListFree(variation->tuples[i].vkhead);
+ }
+ free(variation->tuples);
+ }
+ free(variation);
+ info->variations = NULL;
+}
+
+static void parsefvar(struct ttfinfo *info, FILE *ttf) {
+ int data_off, axis_count, instance_count, cnt;
+ int i,j;
+
+ fseek(ttf,info->fvar_start,SEEK_SET);
+ if ( getlong(ttf)!=0x00010000 ) /* I only understand version 1 */
+return;
+ data_off = getushort(ttf);
+ cnt = getushort(ttf);
+ if ( cnt>2 )
+ LogError( _("Hmm, this 'fvar' table has more count/size pairs than I expect\n") );
+ else if ( cnt<2 ) {
+ LogError( _("Hmm, this 'fvar' table has too few count/size pairs, I shan't parse it\n") );
+return;
+ }
+ axis_count = getushort(ttf);
+ if ( axis_count==0 || axis_count>4 ) {
+ if ( axis_count==0 )
+ LogError( _("Hmm, this 'fvar' table has no axes, that doesn't make sense.\n") );
+ else
+ LogError( _("Hmm, this 'fvar' table has more axes than FontForge can handle.\n") );
+return;
+ }
+ if ( getushort(ttf)!=20 ) {
+ LogError( _("Hmm, this 'fvar' table has an unexpected size for an axis, I shan't parse it\n") );
+return;
+ }
+ instance_count = getushort(ttf);
+ if ( getushort(ttf)!=4+4*axis_count ) {
+ LogError( _("Hmm, this 'fvar' table has an unexpected size for an instance, I shan't parse it\n") );
+return;
+ }
+ if ( data_off+axis_count*20+instance_count*(4+4*axis_count)> info->fvar_len ) {
+ LogError( _("Hmm, this 'fvar' table is too short\n") );
+return;
+ }
+
+ info->variations = gcalloc(1,sizeof(struct variations));
+ info->variations->axis_count = axis_count;
+ info->variations->instance_count = instance_count;
+ info->variations->axes = gcalloc(axis_count,sizeof(struct taxis));
+ info->variations->instances = gcalloc(instance_count,sizeof(struct tinstance));
+ for ( i=0; i<instance_count; ++i )
+ info->variations->instances[i].coords = galloc(axis_count*sizeof(real));
+
+ fseek(ttf,info->fvar_start+data_off,SEEK_SET);
+ for ( i=0; i<axis_count; ++i ) {
+ struct taxis *a = &info->variations->axes[i];
+ a->tag = getlong(ttf);
+ a->min = getlong(ttf)/65536.0;
+ a->def = getlong(ttf)/65536.0;
+ a->max = getlong(ttf)/65536.0;
+ /* flags = */ getushort(ttf);
+ a->nameid = getushort(ttf);
+ }
+ for ( i=0; i<instance_count; ++i ) {
+ struct tinstance *ti = &info->variations->instances[i];
+ ti->nameid = getushort(ttf);
+ /* flags = */ getushort(ttf);
+ for ( j=0 ; j<axis_count; ++j )
+ ti->coords[j] = getlong(ttf)/65536.0;
+ }
+}
+
+static void parseavar(struct ttfinfo *info, FILE *ttf) {
+ int axis_count, pair_count;
+ int i,j;
+
+ if ( info->variations==NULL || info->avar_start==0 || info->avar_len==0 )
+return;
+
+ fseek(ttf,info->avar_start,SEEK_SET);
+ if ( getlong(ttf)!=0x00010000 ) { /* I only understand version 1 */
+ VariationFree(info);
+return;
+ }
+ axis_count = getlong(ttf);
+ if ( axis_count!=info->variations->axis_count ) {
+ LogError( _("Hmm, the axis count in the 'avar' table is different from that in the 'fvar' table.\n") );
+ VariationFree(info);
+return;
+ }
+ for ( i=0; i<axis_count; ++i ) {
+ pair_count = getushort(ttf);
+ if ( pair_count!=0 ) {
+ info->variations->axes[i].mapfrom = galloc(pair_count*sizeof(real));
+ info->variations->axes[i].mapto= galloc(pair_count*sizeof(real));
+ for ( j=0; j<pair_count; ++j ) {
+ info->variations->axes[i].mapfrom[j] = getushort(ttf)/16384.0;
+ info->variations->axes[i].mapto[j] = getushort(ttf)/16384.0;
+ }
+ }
+ }
+ if ( ftell(ttf)-info->avar_start>info->avar_len) {
+ LogError( _("Hmm, the the 'avar' table is too long.\n") );
+ VariationFree(info);
+return;
+ }
+}
+
+static SplineChar **InfoCopyGlyphs(struct ttfinfo *info) {
+ SplineChar **chars = galloc(info->glyph_cnt*sizeof(SplineChar *));
+ int i;
+ RefChar *r;
+
+ for ( i=0; i<info->glyph_cnt; ++i ) {
+ if ( info->chars[i]==NULL )
+ chars[i] = NULL;
+ else {
+ chars[i] = SplineCharCopy(info->chars[i],NULL,NULL);
+ free(chars[i]->ttf_instrs); chars[i]->ttf_instrs = NULL;
+ chars[i]->ttf_instrs_len = 0;
+ PSTFree(chars[i]->possub); chars[i]->possub = NULL;
+ for ( r=chars[i]->layers[ly_fore].refs; r!=NULL; r=r->next )
+ r->sc = NULL;
+ chars[i]->changed = false;
+ chars[i]->ticked = false;
+ }
+ }
+
+ for ( i=0; i<info->glyph_cnt; ++i )
+ ttfFixupRef(chars,i);
+return( chars );
+}
+
+#define BAD_DELTA 0x10001
+static int *readpackeddeltas(FILE *ttf,int n) {
+ int *deltas;
+ int runcnt, i, j;
+
+ deltas = galloc(n*sizeof(int));
+
+ i = 0;
+ while ( i<n ) {
+ runcnt = getc(ttf);
+ if ( runcnt&0x80 ) {
+ /* runcnt zeros get added */
+ for ( j=0; j<=(runcnt&0x3f) && i<n ; ++j )
+ deltas[i++] = 0;
+ } else if ( runcnt&0x40 ) {
+ /* runcnt shorts from the stack */
+ for ( j=0 ; j<=(runcnt&0x3f) && i<n ; ++j )
+ deltas[i++] = (int16) getushort(ttf);
+ } else {
+ /* runcnt signed bytes from the stack */
+ for ( j=0; j<=(runcnt&0x3f) && i<n; ++j )
+ deltas[i++] = (int8) getc(ttf);
+ }
+ if ( j<=(runcnt&0x3f) ) {
+ if ( n>0 )
+ deltas[0] = BAD_DELTA;
+ }
+ }
+return( deltas );
+}
+
+#define ALL_POINTS 0x10001
+#define END_OF_POINTS 0x10000
+
+static int *readpackedpoints(FILE *ttf) {
+ int *points;
+ int n, runcnt, i, j, first;
+
+ n = getc(ttf);
+ if ( n==EOF )
+ n = 0;
+ if ( n&0x80 )
+ n = getc(ttf)|((n&0x7f)<<8);
+ points = galloc((n+1)*sizeof(int));
+ if ( n==0 )
+ points[0] = ALL_POINTS;
+ else {
+ i = 0;
+ while ( i<n ) {
+ runcnt = getc(ttf);
+ if ( runcnt&0x80 ) {
+ runcnt = (runcnt&0x7f);
+ points[i++] = first = getushort(ttf);
+ /* first point not included in runcount */
+ for ( j=0; j<runcnt && i<n; ++j )
+ points[i++] = (first += getushort(ttf));
+ } else {
+ points[i++] = first = getc(ttf);
+ for ( j=0; j<runcnt && i<n; ++j )
+ points[i++] = (first += getc(ttf));
+ }
+ }
+ points[n] = END_OF_POINTS;
+ }
+return( points );
+}
+
+static int TuplesMatch(struct variations *v, int vtest, int dbase) {
+ /* variations for [0,1] make up part of design [1,1], but not the other */
+ /* way round */
+ int i;
+
+ if ( dbase>=v->tuple_count )
+return( false );
+
+ if ( vtest==dbase )
+return( true );
+ for ( i=0; i<v->axis_count; ++i ) {
+ if ( v->tuples[vtest].coords[i]==0 && v->tuples[dbase].coords[i]!=0 )
+return( false );
+ if ( v->tuples[dbase].coords[i]!=0 &&
+ v->tuples[dbase].coords[i]!=v->tuples[vtest].coords[i] )
+return( false );
+ }
+return( true );
+}
+
+static int PointCount(SplineChar *sc) {
+ int i;
+ RefChar *ref;
+ SplineSet *ss;
+ SplinePoint *sp;
+
+ if ( sc->layers[ly_fore].refs!=NULL )
+ for ( i=0, ref=sc->layers[ly_fore].refs; ref!=NULL; ++i, ref=ref->next );
+ else {
+ for ( i=0, ss = sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) {
+ for ( sp=ss->first; sp!=NULL ; ) {
+ if ( sp->ttfindex!=0xffff && sp->ttfindex!=0xfffe )
+ ++i;
+ if ( sp->nextcpindex!=0xffff && sp->nextcpindex!=0xfffe )
+ ++i;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ }
+ }
+return( i );
+}
+
+static void SCShiftAllBy(SplineChar *sc,int xd, int yd) {
+ /* If they change the left/right side-bearing, I think that means everything */
+ /* should be shifted over */
+ SplineSet *ss;
+ SplinePoint *sp;
+ RefChar *ref;
+
+ if ( xd==0 && yd==0 )
+return;
+
+ for ( ss = sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) {
+ for ( sp=ss->first; sp!=NULL ; ) {
+ if ( sp->ttfindex!=0xffff && sp->ttfindex!=0xfffe ) {
+ sp->me.x += xd;
+ sp->me.y += yd;
+ }
+ if ( sp->nextcpindex!=0xffff && sp->nextcpindex!=0xfffe ) {
+ sp->nextcp.x += xd;
+ sp->nextcp.y += yd;
+ if ( sp->next!=NULL )
+ sp->next->to->prevcp = sp->nextcp;
+ }
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp == ss->first )
+ break;
+ }
+ }
+ for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
+ ref->transform[4] += xd;
+ ref->transform[5] += yd;
+ SCReinstanciateRefChar(sc,ref);
+ }
+}
+
+static void VaryGlyph(SplineChar *sc,int *points, int *xdeltas, int *ydeltas,
+ int pcnt) {
+ /* A character contains either composites or contours */
+ int i,j;
+ RefChar *ref;
+ SplineSet *ss;
+ SplinePoint *sp;
+ Spline *s, *first;
+
+ if ( points[0]==ALL_POINTS ) {
+ if ( sc->layers[ly_fore].refs!=NULL ) {
+ for ( i=0, ref=sc->layers[ly_fore].refs; ref!=NULL; ++i, ref=ref->next ) {
+ if ( xdeltas[i]!=0 || ydeltas[i]!=0 ) {
+ ref->transform[4] += xdeltas[i];
+ ref->transform[5] += ydeltas[i];
+ SCReinstanciateRefChar(sc,ref);
+ }
+ }
+ } else {
+ for ( ss = sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) {
+ for ( sp=ss->first; sp!=NULL ; ) {
+ if ( sp->ttfindex!=0xffff && sp->ttfindex!=0xfffe ) {
+ sp->me.x += xdeltas[sp->ttfindex];
+ sp->me.y += ydeltas[sp->ttfindex];
+ }
+ if ( sp->nextcpindex!=0xffff && sp->nextcpindex!=0xfffe ) {
+ sp->nextcp.x += xdeltas[sp->nextcpindex];
+ sp->nextcp.y += ydeltas[sp->nextcpindex];
+ if ( sp->next!=NULL )
+ sp->next->to->prevcp = sp->nextcp;
+ }
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp == ss->first )
+ break;
+ }
+ }
+ }
+ SCShiftAllBy(sc,-xdeltas[pcnt-4],0);
+ SCShiftAllBy(sc,0,-ydeltas[pcnt-2]);
+ sc->width += xdeltas[pcnt-3];
+ sc->vwidth += ydeltas[pcnt-1];
+ } else {
+ j = 0;
+ if ( sc->layers[ly_fore].refs!=NULL ) {
+ for ( i=0, ref=sc->layers[ly_fore].refs; ref!=NULL; ++i, ref=ref->next ) {
+ if ( points[j]==i ) {
+ if ( xdeltas[j]!=0 || ydeltas[j]!=0 ) {
+ ref->transform[4] += xdeltas[j];
+ ref->transform[5] += ydeltas[j];
+ SCReinstanciateRefChar(sc,ref);
+ }
+ ++j;
+ }
+ }
+ } else {
+ for ( i=0, ss = sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) {
+ if ( ss->first->prev!=NULL && ss->first->prev->from->nextcpindex==points[j] ) {
+ ss->first->prevcp.x += xdeltas[j];
+ ss->first->prevcp.y += ydeltas[j];
+ ss->first->prev->from->nextcp = ss->first->prevcp;
+ ++j;
+ }
+ for ( sp=ss->first; sp!=NULL ; ++i ) {
+ if ( sp->ttfindex!=0xffff && sp->ttfindex!=0xfffe )
+ ++i;
+ if ( sp->ttfindex==points[j] ) {
+ sp->me.x += xdeltas[j];
+ sp->me.y += ydeltas[j++];
+ }
+ if ( sp->nextcpindex!=0xffff && sp->nextcpindex!=0xfffe )
+ ++i;
+ if ( sp->nextcpindex==points[j] ) {
+ sp->nextcp.x += xdeltas[j];
+ sp->nextcp.y += ydeltas[j++];
+ if ( sp->next!=NULL )
+ sp->next->to->prevcp = sp->nextcp;
+ } else if ( sp->nonextcp ) {
+ sp->nextcp = sp->me;
+ }
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp == ss->first )
+ break;
+ }
+ first = NULL;
+ }
+ }
+ if ( points[j]==i )
+ SCShiftAllBy(sc,-xdeltas[j++],0);
+ if ( points[j]==i+1 )
+ sc->width += xdeltas[j++];
+ if ( points[j]==i+2 )
+ SCShiftAllBy(sc,0,-ydeltas[j++]);
+ if ( points[j]==i+3 )
+ sc->vwidth += ydeltas[j++];
+ }
+ if ( sc->layers[ly_fore].refs==NULL ) {
+ for ( ss = sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) {
+ for ( sp=ss->first; sp!=NULL ; ++i ) {
+ if ( sp->ttfindex==0xffff ) {
+ sp->me.x = ( sp->nextcp.x + sp->prevcp.x )/2;
+ sp->me.y = ( sp->nextcp.y + sp->prevcp.y )/2;
+ }
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp == ss->first )
+ break;
+ }
+
+ first = NULL;
+ for ( s=ss->first->next; s!=NULL && s!=first; s=s->to->next ) {
+ SplineRefigure(s);
+ if ( first==NULL ) first = s;
+ }
+ }
+ }
+}
+
+static void VaryGlyphs(struct ttfinfo *info,int tupleIndex,int gnum,
+ int *points, FILE *ttf ) {
+ /* one annoying thing about gvar, is that the variations do not describe */
+ /* designs. well variations for [0,1] describes that design, but the */
+ /* design for [1,1] includes the variations [0,1], [1,0], and [1,1] */
+ int pcnt, tc;
+ int *xdeltas, *ydeltas;
+ struct variations *v = info->variations;
+
+ if ( info->chars[gnum]==NULL ) /* Apple doesn't support ttc so this */
+return; /* can't happen */
+ if ( points==NULL ) {
+ LogError( _("Mismatched local and shared tuple flags.\n") );
+return;
+ }
+
+ if ( points[0]==ALL_POINTS )
+ pcnt = PointCount(info->chars[gnum])+4;
+ else {
+ for ( pcnt=0; points[pcnt]!=END_OF_POINTS; ++pcnt );
+ }
+ xdeltas = readpackeddeltas(ttf,pcnt);
+ ydeltas = readpackeddeltas(ttf,pcnt);
+ if ( xdeltas[0]!=BAD_DELTA && ydeltas[0]!=BAD_DELTA )
+ for ( tc = 0; tc<v->tuple_count; ++tc ) {
+ if ( TuplesMatch(v,tc,tupleIndex))
+ VaryGlyph(v->tuples[tc].chars[gnum],points,xdeltas,ydeltas,pcnt);
+ } else {
+ static int warned = false;
+ if ( !warned )
+ LogError( _("Incorrect number of deltas in glyph %d (%s)\n"), gnum,
+ info->chars[gnum]->name!=NULL?info->chars[gnum]->name:"<Nameless>" );
+ warned = true;
+ }
+ free(xdeltas);
+ free(ydeltas);
+}
+
+static void parsegvar(struct ttfinfo *info, FILE *ttf) {
+ /* I'm only going to support a subset of the gvar. Only the global tuples */
+ int axiscount, globaltc, gvarflags, gc, i,j,g;
+ uint32 tupoff, dataoff, *gvars;
+ struct variations *v = info->variations;
+ int warned=false;
+
+ fseek(ttf,info->gvar_start,SEEK_SET);
+ if ( getlong(ttf)!=0x00010000 ) { /* I only understand version 1 */
+ VariationFree(info);
+return;
+ }
+ axiscount = getushort(ttf);
+ if ( axiscount!=info->variations->axis_count ) {
+ LogError( _("Hmm, the axis count in the 'gvar' table is different from that in the 'fvar' table.\n") );
+ VariationFree(info);
+return;
+ }
+ globaltc = getushort(ttf);
+ tupoff = getlong(ttf) + info->gvar_start;
+ gc = getushort(ttf);
+ gvarflags = getushort(ttf);
+ dataoff = getlong(ttf) + info->gvar_start;
+ if ( globaltc==0 || globaltc>AppleMmMax ) {
+ if ( globaltc==0 )
+ LogError( _("Hmm, no global tuples specified in the 'gvar' table.\n") );
+ else
+ LogError( _("Hmm, too many global tuples specified in the 'gvar' table.\n FontForge only supports %d\n"), AppleMmMax );
+ VariationFree(info);
+return;
+ }
+ if ( gc>info->glyph_cnt ) {
+ LogError( _("Hmm, more glyph variation data specified than there are glyphs in font.\n") );
+ VariationFree(info);
+return;
+ }
+
+ gvars = galloc((gc+1)*sizeof(uint32));
+ if ( gvarflags&1 ) { /* 32 bit data */
+ for ( i=0; i<=gc; ++i )
+ gvars[i] = getlong(ttf)+dataoff;
+ } else {
+ for ( i=0; i<=gc; ++i )
+ gvars[i] = getushort(ttf)*2 +dataoff; /* Undocumented *2 */
+ }
+
+ v->tuple_count = globaltc;
+ v->tuples = gcalloc(globaltc,sizeof(struct tuples));
+ fseek(ttf,tupoff,SEEK_SET);
+ for ( i=0; i<globaltc; ++i ) {
+ v->tuples[i].coords = galloc(axiscount*sizeof(float));
+ for ( j=0; j<axiscount; ++j )
+ v->tuples[i].coords[j] = ((short) getushort(ttf))/16384.0;
+ v->tuples[i].chars = InfoCopyGlyphs(info);
+ }
+
+ for ( g=0; g<gc; ++g ) if ( gvars[g]!=gvars[g+1] ) {
+ int tc;
+ uint32 datoff;
+ int *sharedpoints=NULL;
+ fseek(ttf,gvars[g],SEEK_SET);
+ tc = getushort(ttf);
+ datoff = gvars[g]+getushort(ttf);
+ if ( tc&0x8000 ) {
+ uint32 here = ftell(ttf);
+ fseek(ttf,datoff,SEEK_SET);
+ sharedpoints = readpackedpoints(ttf);
+ datoff = ftell(ttf);
+ fseek(ttf,here,SEEK_SET);
+ }
+ for ( i=0; i<(tc&0xfff); ++i ) {
+ int tupleDataSize, tupleIndex;
+ tupleDataSize = getushort(ttf);
+ tupleIndex = getushort(ttf);
+ if ( tupleIndex&0xc000 ) {
+ if ( !warned )
+ LogError( _("Warning: Glyph %d contains either private or intermediate tuple data.\n FontForge supports neither.\n"),
+ g);
+ warned = true;
+ if ( tupleIndex&0x8000 )
+ fseek(ttf,2*axiscount,SEEK_CUR);
+ if ( tupleIndex&0x4000 )
+ fseek(ttf,4*axiscount,SEEK_CUR);
+ } else {
+ int *localpoints=NULL;
+ uint32 here = ftell(ttf);
+ fseek(ttf,datoff,SEEK_SET);
+ if ( tupleIndex&0x2000 )
+ localpoints = readpackedpoints(ttf);
+ VaryGlyphs(info,tupleIndex&0xfff,g,
+ (tupleIndex&0x2000)?localpoints:sharedpoints,ttf);
+ free(localpoints);
+ fseek(ttf,here,SEEK_SET);
+ }
+ datoff += tupleDataSize;
+ }
+ free(sharedpoints);
+ }
+ free(gvars);
+}
+
+static void AlterEntry(struct ttf_table *cvt, int i, int delta ) {
+ int val = memushort(cvt->data,cvt->len,2*i);
+ memputshort(cvt->data,2*i,val+delta);
+}
+
+static void VaryCvt(struct tuples *tuple,int *points, int *deltas,
+ int pcnt, struct ttf_table *orig_cvt) {
+ struct ttf_table *cvt;
+ int i;
+
+ if ( (cvt = tuple->cvt)==NULL ) {
+ cvt = tuple->cvt = chunkalloc(sizeof(struct ttf_table));
+ cvt->tag = orig_cvt->tag;
+ cvt->len = cvt->maxlen = orig_cvt->len;
+ cvt->data = galloc(cvt->len);
+ memcpy(cvt->data,orig_cvt->data,cvt->len);
+ }
+ if ( points[0]==ALL_POINTS ) {
+ for ( i=0; i<pcnt; ++i )
+ AlterEntry(cvt,i,deltas[i]);
+ } else {
+ for ( i=0; i<pcnt; ++i )
+ AlterEntry(cvt,points[i],deltas[i]);
+ }
+}
+
+static void VaryCvts(struct ttfinfo *info,int tupleIndex, int *points, FILE *ttf,
+ struct ttf_table *origcvt ) {
+ /* one annoying thing about gvar, is that the variations do not describe */
+ /* designs. well variations for [0,1] describes that design, but the */
+ /* design for [1,1] includes the variations [0,1], [1,0], and [1,1] */
+ /* And same is true of cvar */
+ int pcnt, tc;
+ int *deltas;
+ struct variations *v = info->variations;
+
+ if ( points[0]==ALL_POINTS )
+ pcnt = origcvt->len/sizeof(uint16);
+ else {
+ for ( pcnt=0; points[pcnt]!=END_OF_POINTS; ++pcnt );
+ }
+ deltas = readpackeddeltas(ttf,pcnt);
+ if ( deltas[0]!=BAD_DELTA )
+ for ( tc = 0; tc<v->tuple_count; ++tc ) {
+ if ( TuplesMatch(v,tc,tupleIndex))
+ VaryCvt(&v->tuples[tc],points,deltas,pcnt,origcvt);
+ } else {
+ static int warned = false;
+ if ( !warned )
+ LogError( _("Incorrect number of deltas in cvt\n") );
+ warned = true;
+ }
+ free(deltas);
+}
+
+static void parsecvar(struct ttfinfo *info, FILE *ttf) {
+ struct ttf_table *cvt;
+ int tuplecount;
+ uint32 offset;
+ int *sharedpoints=NULL;
+ int i;
+ int warned = false;
+
+ for ( cvt = info->tabs; cvt!=NULL && cvt->tag!=CHR('c','v','t',' '); cvt=cvt->next );
+ if ( cvt==NULL )
+return;
+
+ fseek(ttf,info->cvar_start,SEEK_SET);
+ if ( getlong(ttf)!=0x00010000 ) { /* I only understand version 1 */
+ /* I think I can live without cvt variations... */
+ /* So I shan't free the structure */
+return;
+ }
+
+ tuplecount = getushort(ttf);
+ offset = info->cvar_start+getushort(ttf);
+ /* The documentation implies there are flags packed into the tuplecount */
+ /* but John Jenkins tells me that shared points don't apply to cvar */
+ /* Might as well parse it just in case */
+ if ( tuplecount&0x8000 ) {
+ uint32 here = ftell(ttf);
+ fseek(ttf,offset,SEEK_SET);
+ sharedpoints = readpackedpoints(ttf);
+ offset = ftell(ttf);
+ fseek(ttf,here,SEEK_SET);
+ }
+ for ( i=0; i<(tuplecount&0xfff); ++i ) {
+ int tupleDataSize, tupleIndex;
+ tupleDataSize = getushort(ttf);
+ tupleIndex = getushort(ttf);
+ /* there is no provision here for a global tuple coordinate section */
+ /* so John says there are no tuple indeces. Just embedded tuples */
+ if ( tupleIndex&0x4000 ) {
+ if ( !warned )
+ LogError( _("Warning: 'cvar' contains intermediate tuple data.\n FontForge doesn't support this.\n") );
+ warned = true;
+ if ( tupleIndex&0x8000 )
+ fseek(ttf,2*info->variations->axis_count,SEEK_CUR);
+ if ( tupleIndex&0x4000 )
+ fseek(ttf,4*info->variations->axis_count,SEEK_CUR);
+ } else {
+ int *localpoints=NULL;
+ uint32 here;
+ int j,k,ti;
+ ti = tupleIndex&0xfff;
+ if ( tupleIndex&0x8000 ) {
+ real *coords = galloc(info->variations->axis_count*sizeof(real));
+ for ( j=0; j<info->variations->axis_count; ++j )
+ coords[j] = ((int16) getushort(ttf))/16384.0;
+ for ( k=0 ; k<info->variations->tuple_count; ++k ) {
+ for ( j=0; j<info->variations->axis_count; ++j )
+ if ( coords[j]!=info->variations->tuples[k].coords[j] )
+ break;
+ if ( j==info->variations->axis_count )
+ break;
+ }
+ ti = -1;
+ if ( k!=info->variations->tuple_count )
+ ti = k;
+ }
+ if ( ti!=-1 ) {
+ here = ftell(ttf);
+ fseek(ttf,offset,SEEK_SET);
+ if ( tupleIndex&0x2000 )
+ localpoints = readpackedpoints(ttf);
+ VaryCvts(info,ti,(tupleIndex&0x2000)?localpoints:sharedpoints,ttf,cvt);
+ free(localpoints);
+ fseek(ttf,here,SEEK_SET);
+ }
+ }
+ offset += tupleDataSize;
+ }
+ free(sharedpoints);
+}
+
+void readttfvariations(struct ttfinfo *info, FILE *ttf) {
+ if ( info->gvar_start==0 || info->gvar_len==0 || info->fvar_start==0 || info->fvar_len==0 )
+return;
+
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ gwwv_progress_change_line2(_("Processing Variations"));
+ if ( !no_windowing_ui )
+ GDrawProcessPendingEvents(NULL);
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_progress_change_line2(_("Processing Variations"));
+ /* !!! force an expose */
+#endif
+ parsefvar(info,ttf);
+ if ( info->variations!=NULL && info->avar_start!=0 )
+ parseavar(info,ttf);
+ if ( info->variations!=NULL )
+ parsegvar(info,ttf);
+ if ( info->variations!=NULL && info->cvar_start!=0 && info->cvt_start!=0 )
+ parsecvar(info,ttf);
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/pfaedit.h b/Build/source/libs/luafontforge/fontforge/fontforge/pfaedit.h
new file mode 100644
index 00000000000..1e257cef0c3
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/pfaedit.h
@@ -0,0 +1,111 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _PFAEDIT_H_
+#define _PFAEDIT_H_
+
+#include "configure-pfaedit.h"
+#if defined( FONTFORGE_CONFIG_GTK )
+# include "basics.h"
+# include "gimage.h"
+# include <gtk/gtk.h>
+# include <gwwv.h>
+#else /*if defined( FONTFORGE_CONFIG_GDRAW )*/
+# include <basics.h>
+# include <stdio.h>
+# include <string.h>
+# if defined( FONTFORGE_CONFIG_GDRAW )
+# include <gprogress.h>
+# endif
+#endif
+#include "splinefont.h"
+
+#if defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+#include "intl.h"
+#endif
+
+static const int unicode4_size = 17*65536;
+ /* Unicode goes up to 0x10ffff */
+
+
+extern void IError(const char *fmt,...);
+extern int ErrorWindowExists(void);
+extern void ShowErrorWindow(void);
+extern void LogError(const char *format,...);
+extern void ff_post_notice(const char *title,const char *statement,...);
+
+extern void CheckIsScript(int argc, char *argv[]);
+
+extern char *AdobeStandardEncoding[256];
+extern int32 unicode_from_adobestd[256];
+
+struct unicode_nameannot {
+ const char *name, *annot;
+};
+extern const struct unicode_nameannot * const *const *_UnicodeNameAnnot;
+
+extern int default_fv_font_size;
+extern int default_fv_antialias;
+extern int default_fv_bbsized;
+extern Encoding *default_encoding, custom;
+extern int adjustwidth;
+extern int adjustlbearing;
+extern int autohint_before_rasterize;
+extern int autohint_before_generate;
+extern int seperate_hint_controls;
+extern int ItalicConstrained;
+extern int no_windowing_ui;
+extern uint32 default_background;
+extern int use_utf8_in_script;
+
+extern int new_em_size;
+extern int new_fonts_are_order2;
+extern int loaded_fonts_same_as_new;
+
+extern char *BDFFoundry, *TTFFoundry;
+extern char *xuid;
+
+extern int pagewidth, pageheight, printtype; /* Printer defaults */
+extern char *printcommand, *printlazyprinter;
+
+extern Encoding *enclist;
+
+#define RECENT_MAX 4
+extern char *RecentFiles[RECENT_MAX];
+
+#define SCRIPT_MENU_MAX 10
+#if defined( FONTFORGE_CONFIG_GTK )
+extern char *script_menu_names[SCRIPT_MENU_MAX];
+#else
+extern unichar_t *script_menu_names[SCRIPT_MENU_MAX];
+#endif
+extern char *script_filenames[SCRIPT_MENU_MAX];
+
+
+extern MacFeat *default_mac_feature_map;
+
+
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/pfaeditui.h b/Build/source/libs/luafontforge/fontforge/fontforge/pfaeditui.h
new file mode 100644
index 00000000000..b4fd05a7a27
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/pfaeditui.h
@@ -0,0 +1,189 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _PFAEDITUI_H_
+#define _PFAEDITUI_H_
+
+#include "pfaedit.h"
+
+extern void help(char *filename);
+extern int FontForgeMain( int argc, char **argv );
+
+#if defined(FONTFORGE_CONFIG_GTK)
+# include <gtk/gtk.h>
+# include "interface.h"
+# include "callbacks.h"
+# include "support.h"
+# include "views.h"
+extern GdkCursor *ct_magplus, *ct_magminus, *ct_mypointer,
+ *ct_circle, *ct_square, *ct_triangle, *ct_pen,
+ *ct_ruler, *ct_knife, *ct_rotate, *ct_skew, *ct_scale, *ct_flip,
+ *ct_3drotate, *ct_perspective,
+ *ct_updown, *ct_leftright, *ct_nesw, *ct_nwse,
+ *ct_rect, *ct_elipse, *ct_poly, *ct_star, *ct_filledrect, *ct_filledelipse,
+ *ct_pencil, *ct_shift, *ct_line, *ct_myhand, *ct_setwidth,
+ *ct_kerning, *ct_rbearing, *ct_lbearing, *ct_eyedropper,
+ *ct_prohibition, *ct_ddcursor;
+
+/*
+extern GImage GIcon_midtangent, GIcon_midcurve, GIcon_midcorner;
+extern GImage GIcon_tangent, GIcon_curve, GIcon_corner, GIcon_ruler,
+ GIcon_pointer, GIcon_magnify, GIcon_pen, GIcon_knife, GIcon_scale,
+ GIcon_flip, GIcon_rotate, GIcon_skew,
+ GIcon_squarecap, GIcon_roundcap, GIcon_buttcap,
+ GIcon_miterjoin, GIcon_roundjoin, GIcon_beveljoin,
+ GIcon_rect, GIcon_elipse, GIcon_rrect, GIcon_poly, GIcon_star,
+ GIcon_pencil, GIcon_shift, GIcon_line, GIcon_hand,
+ GIcon_press2ptr, GIcon_freehand, GIcon_greyfree;
+extern GImage GIcon_smallskew, GIcon_smallscale, GIcon_smallrotate,
+ GIcon_smallflip, GIcon_smalltangent, GIcon_smallcorner,
+ GIcon_smallcurve, GIcon_smallmag, GIcon_smallknife, GIcon_smallpen,
+ GIcon_smallpointer, GIcon_smallruler, GIcon_smallelipse,
+ GIcon_smallrect, GIcon_smallpoly, GIcon_smallstar,
+ GIcon_smallpencil, GIcon_smallhand,
+ GIcon_FontForgeLogo, GIcon_FontForgeBack, GIcon_FontForgeGuide;
+extern GImage GIcon_sel2ptr, GIcon_rightpointer, GIcon_angle, GIcon_distance,
+ GIcon_selectedpoint, GIcon_mag;
+extern GImage GIcon_menumark;
+extern GImage GIcon_rmoverlap, GIcon_exclude, GIcon_intersection, GIcon_findinter;
+extern GImage GIcon_outline, GIcon_inline, GIcon_shadow, GIcon_wireframe;
+extern GImage def_image, red_image, blue_image, green_image, magenta_image,
+ yellow_image, cyan_image, white_image;
+extern GImage GIcon_continue, GIcon_stepout, GIcon_stepover, GIcon_stepinto,
+ GIcon_watchpnt, GIcon_menudelta, GIcon_exit;
+extern GImage GIcon_Stopped, GIcon_Stop;
+extern GWindow logo_icon;
+
+extern GTextInfo encodingtypes[];
+extern GTextInfo *EncodingTypesFindEnc(GTextInfo *encodingtypes, Encoding *enc);
+extern Encoding *ParseEncodingNameFromList(GGadget *listfield);
+extern GTextInfo *GetEncodingTypes(void);
+*/
+
+extern void InitCursors(void);
+
+/*
+extern real GetReal(GWindow gw,int cid,char *name,int *err);
+extern int GetInt(GWindow gw,int cid,char *name,int *err);
+extern void Protest(char *label);
+extern real GetCalmReal8(GWindow gw,int cid,char *namer,int *err);
+extern real GetReal8(GWindow gw,int cid,char *namer,int *err);
+extern int GetInt8(GWindow gw,int cid,char *namer,int *err);
+extern void Protest8(char *labelr);
+*/
+
+/* I would like these to be const ints, but gcc doesn't treat them as consts */
+/*
+#define et_sb_halfup et_sb_thumbrelease+1
+#define et_sb_halfdown et_sb_thumbrelease+2
+*/
+
+#elif defined( FONTFORGE_CONFIG_GDRAW )
+
+# include "gdraw.h"
+# include "gwidget.h"
+# include "ggadget.h"
+# include "views.h"
+
+extern GCursor ct_magplus, ct_magminus, ct_mypointer,
+ ct_circle, ct_square, ct_triangle, ct_pen,
+ ct_ruler, ct_knife, ct_rotate, ct_skew, ct_scale, ct_flip,
+ ct_3drotate, ct_perspective,
+ ct_updown, ct_leftright, ct_nesw, ct_nwse,
+ ct_rect, ct_elipse, ct_poly, ct_star, ct_filledrect, ct_filledelipse,
+ ct_pencil, ct_shift, ct_line, ct_myhand, ct_setwidth,
+ ct_kerning, ct_rbearing, ct_lbearing, ct_eyedropper,
+ ct_prohibition, ct_ddcursor;
+extern GImage GIcon_midtangent, GIcon_midcurve, GIcon_midcorner;
+extern GImage GIcon_tangent, GIcon_curve, GIcon_corner, GIcon_ruler,
+ GIcon_pointer, GIcon_magnify, GIcon_pen, GIcon_knife, GIcon_scale,
+ GIcon_flip, GIcon_rotate, GIcon_skew,
+ GIcon_3drotate, GIcon_perspective,
+ GIcon_squarecap, GIcon_roundcap, GIcon_buttcap,
+ GIcon_miterjoin, GIcon_roundjoin, GIcon_beveljoin,
+ GIcon_rect, GIcon_elipse, GIcon_rrect, GIcon_poly, GIcon_star,
+ GIcon_pencil, GIcon_shift, GIcon_line, GIcon_hand,
+ GIcon_press2ptr, GIcon_freehand, GIcon_greyfree;
+extern GImage GIcon_smallskew, GIcon_smallscale, GIcon_smallrotate,
+ GIcon_small3drotate, GIcon_smallperspective,
+ GIcon_smallflip, GIcon_smalltangent, GIcon_smallcorner,
+ GIcon_smallcurve, GIcon_smallmag, GIcon_smallknife, GIcon_smallpen,
+ GIcon_smallpointer, GIcon_smallruler, GIcon_smallelipse,
+ GIcon_smallrect, GIcon_smallpoly, GIcon_smallstar,
+ GIcon_smallpencil, GIcon_smallhand,
+ GIcon_FontForgeLogo, GIcon_FontForgeBack, GIcon_FontForgeGuide;
+extern GImage GIcon_lock;
+extern GImage GIcon_menumark;
+extern GImage GIcon_rmoverlap, GIcon_exclude, GIcon_intersection, GIcon_findinter;
+extern GImage GIcon_outline, GIcon_inline, GIcon_shadow, GIcon_wireframe;
+extern GImage def_image, red_image, blue_image, green_image, magenta_image,
+ yellow_image, cyan_image, white_image;
+extern GImage GIcon_continue, GIcon_stepout, GIcon_stepover, GIcon_stepinto,
+ GIcon_watchpnt, GIcon_menudelta, GIcon_exit;
+extern GImage GIcon_Stopped, GIcon_Stop;
+extern GWindow logo_icon;
+extern GImage GIcon_sel2ptr, GIcon_rightpointer, GIcon_angle, GIcon_distance,
+ GIcon_selectedpoint, GIcon_mag;
+extern GImage GIcon_up, GIcon_down;
+extern GImage OFL_logo;
+
+extern GTextInfo encodingtypes[];
+extern GTextInfo *EncodingTypesFindEnc(GTextInfo *encodingtypes, Encoding *enc);
+extern Encoding *ParseEncodingNameFromList(GGadget *listfield);
+extern GTextInfo *GetEncodingTypes(void);
+
+extern void InitCursors(void);
+extern void InitToolIconClut(Color bg);
+
+extern real GetReal(GWindow gw,int cid,char *name,int *err);
+extern int GetInt(GWindow gw,int cid,char *name,int *err);
+extern void Protest(char *label);
+extern real GetCalmReal8(GWindow gw,int cid,char *namer,int *err);
+extern real GetReal8(GWindow gw,int cid,char *namer,int *err);
+extern int GetInt8(GWindow gw,int cid,char *namer,int *err);
+extern void Protest8(char *labelr);
+
+/* I would like these to be const ints, but gcc doesn't treat them as consts */
+#define et_sb_halfup et_sb_thumbrelease+1
+#define et_sb_halfdown et_sb_thumbrelease+2
+#else
+# include "views.h"
+#endif
+
+extern FontView *fv_list;
+
+extern struct openfilefilters { char *name, *filter; } def_font_filters[], *user_font_filters;
+extern int default_font_filter_index;
+
+#if !defined( FONTFORGE_CONFIG_CAPSLOCK_FOR_ALT ) || FONTFORGE_CONFIG_CAPSLOCK_FOR_ALT==0
+# define ksm_alt ksm_meta
+#elif FONTFORGE_CONFIG_CAPSLOCK_FOR_ALT-2 == 0 /* I use this peculiar construction just in case it is defined as the empty string */
+# define ksm_alt (ksm_meta|ksm_capslock)
+#else
+# define ksm_alt ksm_capslock
+#endif
+
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/plugins.h b/Build/source/libs/luafontforge/fontforge/fontforge/plugins.h
new file mode 100644
index 00000000000..6e1079c768e
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/plugins.h
@@ -0,0 +1,99 @@
+/* Copyright (C) 2005-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* If a user wants to write a fontforge plugin s/he should include this file */
+
+/*
+ I envision that there will eventually be three types of plug-ins. At the
+ moment I am only supporing two of them.
+
+ * A plug in which adds a new encoding to the encoding/force encoding
+ menus.
+ * A plug in which adds a new scripting command
+ * A plug in which adds a new menu item.
+ (I haven't figure out how I want to do this last. So I'm not currently
+ supporting it.)
+
+ A plug-in should be a dynamic library.
+ Plug-ins will be loaded at start up if they are in the default plugin
+ directory, or a script may explicitly invoke a LoadPlugin() call
+ and pass a filename.
+ Each plug-in should contain an entry-point:
+ void FontForgeInit(void);
+ When FF loads a plug-in it will call this entry point.
+ I expect that this routine in term will call one (or more) of the install
+ routines (though it can do whatever it likes):
+ * AddEncoding(name,enc-to-unicode-func,unicode-to-enc-func)
+ * AddScriptingCommand(name,func,needs-font)
+
+ Once loaded, there is no way to remove a plug in -- but you can map a
+ plug in's name to do something else.
+
+ I am presuming that plugins will be linked against libfontforge and
+ that it will have access to all routines declared in fontforge's
+ header files. I do not expect to turn this into a real library with
+ a true API. It's just a catch all bag of routines I have needed.
+ It's not documented either.
+*/
+
+ /* Entry point all plugins must contain */
+extern int FontForgeInit(void);
+ /* If the load fails, then this routine should return 0, else 1 */
+ /* if it returns 0, fontforge will dlclose the shared lib */
+ /* FontForge will not complain itself. FontForgeInit should */
+ /* call LogError (or gwwv_post_error or whatever) if it wants */
+ /* to report failure */
+
+ /* AddScriptingCommand is documented within */
+#include "scripting.h"
+
+ /* AddEncoding is documented here */
+typedef int (*EncFunc)(int);
+extern int AddEncoding(char *name,EncFunc enc_to_uni,EncFunc uni_to_enc,int max);
+ /* The "Encoding" here is a little different from what you normally see*/
+ /* It isn't a mapping from a byte stream to unicode, but from an int */
+ /* to unicode. If we have an 8/16 encoding (EUC or SJIS) then the */
+ /* single byte entries will be numbers less than <256 and the */
+ /* multibyte entries will be numbers >=256. So an encoding might be */
+ /* valid for the domain [0x20..0x7f] [0xa1a1..0xfefe] */
+ /* In other words, we're interested in the ordering displayed in the */
+ /* fontview. Nothing else */
+ /* The max value need not be exact (though it should be at least as big)*/
+ /* if you create a new font with the given encoding, then the font will */
+ /* have max slots in it by default */
+ /* A return value of -1 (from an EncFunc) indicates no mapping */
+ /* AddEncoding returns 1 if the encoding was added, 2 if it replaced */
+ /* an existing encoding, 0 if you attempt to replace a builtin */
+ /* encoding */
+
+
+ /* Internal routines. Plugins shouldn't need these */
+extern void LoadPlugin(char *dynamic_lib_name);
+ /* Loads a single plugin file */
+extern void LoadPluginDir(char *dir);
+ /* Loads any dynamic libs from this directory. if dir is NULL loads from */
+ /* default directory */
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/prefs.c b/Build/source/libs/luafontforge/fontforge/fontforge/prefs.c
new file mode 100644
index 00000000000..3b4dad9d716
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/prefs.c
@@ -0,0 +1,2282 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaeditui.h"
+#include "groups.h"
+#include "plugins.h"
+#include <charset.h>
+#include <gfile.h>
+#include <gresource.h>
+#include <ustring.h>
+#include <gkeysym.h>
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <locale.h>
+#include <time.h>
+#include <sys/time.h>
+#include <stdlib.h>
+
+#include "ttf.h"
+
+#if HAVE_LANGINFO_H
+#ifndef LUA_FF_LIB
+# include <langinfo.h>
+#endif
+#endif
+
+#ifndef N_
+#define N_(a) a
+#endif
+
+int splash = 1;
+int adjustwidth = true;
+int adjustlbearing = true;
+Encoding *default_encoding = NULL;
+int autohint_before_rasterize = 1;
+int autohint_before_generate = 1;
+int use_freetype_to_rasterize_fv = 1;
+int OpenCharsInNewWindow = 1;
+int ItalicConstrained=true;
+int accent_offset = 6;
+int GraveAcuteCenterBottom = 1;
+int PreferSpacingAccents = true;
+int CharCenterHighest = 1;
+int ask_user_for_resolution = true;
+int stop_at_join = false;
+int cv_auto_goto = true;
+int recognizePUA = true;
+float arrowAmount=1;
+float snapdistance=3.5;
+float joinsnap=0;
+char *BDFFoundry=NULL;
+char *TTFFoundry=NULL;
+char *xuid=NULL;
+char *SaveTablesPref=NULL;
+char *RecentFiles[RECENT_MAX] = { NULL };
+/*struct cvshows CVShows = { 1, 1, 1, 1, 1, 0, 1 };*/ /* in charview */
+/* int default_fv_font_size = 24; */ /* in fontview */
+/* int default_fv_antialias = false */ /* in fontview */
+/* int default_fv_bbsized = false */ /* in fontview */
+int default_fv_row_count = 4;
+int default_fv_col_count = 16;
+extern int default_fv_showhmetrics; /* in fontview */
+extern int default_fv_showvmetrics; /* in fontview */
+extern int default_fv_glyphlabel; /* in fontview */
+int save_to_dir = 0; /* in fontview, use sfdir rather than sfd */
+extern int palettes_docked; /* in cvpalettes */
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+extern int cvvisible[2], bvvisible[3]; /* in cvpalettes.c */
+#endif
+extern int maxundoes; /* in cvundoes */
+extern int prefer_cjk_encodings; /* in parsettf */
+extern int onlycopydisplayed, copymetadata, copyttfinstr;
+extern struct cvshows CVShows;
+extern int oldformatstate; /* in savefontdlg.c */
+extern int oldbitmapstate; /* in savefontdlg.c */
+extern int old_ttf_flags; /* in savefontdlg.c */
+extern int old_ps_flags; /* in savefontdlg.c */
+extern int old_otf_flags; /* in savefontdlg.c */
+extern int oldsystem; /* in bitmapdlg.c */
+#ifndef LUA_FF_LIB
+extern int preferpotrace; /* in autotrace.c */
+extern int autotrace_ask; /* in autotrace.c */
+extern int mf_ask; /* in autotrace.c */
+extern int mf_clearbackgrounds; /* in autotrace.c */
+extern int mf_showerrors; /* in autotrace.c */
+extern char *mf_args; /* in autotrace.c */
+#endif
+static int glyph_2_name_map=0; /* was in tottf.c, now a flag in savefont options dlg */
+extern int coverageformatsallowed; /* in tottfgpos.c */
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+extern int debug_wins; /* in cvdebug.c */
+extern int gridfit_dpi, gridfit_depth; /* in cvgridfit.c */
+extern float gridfit_pointsize; /* in cvgridfit.c */
+#endif
+extern int hint_diagonal_ends; /* in stemdb.c */
+extern int hint_diagonal_intersections; /* in stemdb.c */
+extern int hint_bounding_boxes; /* in stemdb.c */
+unichar_t *script_menu_names[SCRIPT_MENU_MAX];
+char *script_filenames[SCRIPT_MENU_MAX];
+static char *xdefs_filename;
+int new_em_size = 1000;
+int new_fonts_are_order2 = false;
+int loaded_fonts_same_as_new = false;
+int use_second_indic_scripts = false;
+char *helpdir;
+char *othersubrsfile;
+extern MacFeat *default_mac_feature_map, /* from macenc.c */
+ *user_mac_feature_map;
+int updateflex = false;
+int allow_utf8_glyphnames = false;
+int clear_tt_instructions_when_needed = true;
+int ask_user_for_cmap = false;
+
+extern int rectelipse, polystar, regular_star; /* from cvpalettes.c */
+extern int center_out[2]; /* from cvpalettes.c */
+extern float rr_radius; /* from cvpalettes.c */
+extern int ps_pointcnt; /* from cvpalettes.c */
+extern float star_percent; /* from cvpalettes.c */
+
+NameList *force_names_when_opening=NULL;
+NameList *force_names_when_saving=NULL;
+extern NameList *namelist_for_new_fonts;
+
+int default_font_filter_index=0;
+struct openfilefilters *user_font_filters = NULL;
+static int alwaysgenapple=false, alwaysgenopentype=false;
+
+static int pointless;
+
+ /* These first three must match the values in macenc.c */
+#define CID_Features 101
+#define CID_FeatureDel 103
+#define CID_FeatureEdit 105
+
+#define CID_Mapping 102
+#define CID_MappingDel 104
+#define CID_MappingEdit 106
+
+#define CID_ScriptMNameBase 200
+#define CID_ScriptMFileBase (200+SCRIPT_MENU_MAX)
+#define CID_ScriptMBrowseBase (200+2*SCRIPT_MENU_MAX)
+
+#define CID_PrefsBase 1000
+#define CID_PrefsOffset 100
+#define CID_PrefsBrowseOffset (CID_PrefsOffset/2)
+
+/* ************************************************************************** */
+/* ***************************** mac data ***************************** */
+/* ************************************************************************** */
+
+struct macsettingname macfeat_otftag[] = {
+ { 1, 0, CHR('r','l','i','g') }, /* Required ligatures */
+ { 1, 2, CHR('l','i','g','a') }, /* Common ligatures */
+ { 1, 4, CHR('d','l','i','g') }, /* rare ligatures => discretionary */
+#if 0
+ { 1, 4, CHR('h','l','i','g') }, /* rare ligatures => historic */
+ { 1, 4, CHR('a','l','i','g') }, /* rare ligatures => ?ancient? */
+#endif
+ /* 2, 1, partially connected cursive */
+ { 2, 2, CHR('i','s','o','l') }, /* Arabic forms */
+ { 2, 2, CHR('c','a','l','t') }, /* ??? */
+ /* 3, 1, all caps */
+ /* 3, 2, all lower */
+ { 3, 3, CHR('s','m','c','p') }, /* small caps */
+ /* 3, 4, initial caps */
+ /* 3, 5, initial caps, small caps */
+ { 4, 0, CHR('v','r','t','2') }, /* vertical forms => vertical rotation */
+#if 0
+ { 4, 0, CHR('v','k','n','a') }, /* vertical forms => vertical kana */
+#endif
+ { 6, 0, CHR('t','n','u','m') }, /* monospace numbers => Tabular numbers */
+ { 10, 1, CHR('s','u','p','s') }, /* superior vertical position => superscript */
+ { 10, 2, CHR('s','u','b','s') }, /* inferior vertical position => subscript */
+#if 0
+ { 10, 3, CHR('s','u','p','s') }, /* ordinal vertical position => superscript */
+#endif
+ { 11, 1, CHR('a','f','r','c') }, /* vertical fraction => fraction ligature */
+ { 11, 2, CHR('f','r','a','c') }, /* diagonal fraction => fraction ligature */
+ { 16, 1, CHR('o','r','n','m') }, /* vertical fraction => fraction ligature */
+ { 20, 0, CHR('t','r','a','d') }, /* traditional characters => traditional forms */
+#if 0
+ { 20, 0, CHR('t','n','a','m') }, /* traditional characters => traditional names */
+#endif
+ { 20, 1, CHR('s','m','p','l') }, /* simplified characters */
+ { 20, 2, CHR('j','p','7','8') }, /* jis 1978 */
+ { 20, 3, CHR('j','p','8','3') }, /* jis 1983 */
+ { 20, 4, CHR('j','p','9','0') }, /* jis 1990 */
+ { 21, 0, CHR('o','n','u','m') }, /* lower case number => old style numbers */
+ { 22, 0, CHR('p','w','i','d') }, /* proportional text => proportional widths */
+ { 22, 2, CHR('h','w','i','d') }, /* half width text => half widths */
+ { 22, 3, CHR('f','w','i','d') }, /* full width text => full widths */
+ { 25, 0, CHR('f','w','i','d') }, /* full width kana => full widths */
+ { 25, 1, CHR('p','w','i','d') }, /* proportional kana => proportional widths */
+ { 26, 0, CHR('f','w','i','d') }, /* full width ideograph => full widths */
+ { 26, 1, CHR('p','w','i','d') }, /* proportional ideograph => proportional widths */
+ { 103, 0, CHR('h','w','i','d') }, /* half width cjk roman => half widths */
+ { 103, 1, CHR('p','w','i','d') }, /* proportional cjk roman => proportional widths */
+ { 103, 3, CHR('f','w','i','d') }, /* full width cjk roman => full widths */
+ { 0, 0, 0 }
+}, *user_macfeat_otftag;
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static void UserSettingsFree(void) {
+
+ free( user_macfeat_otftag );
+ user_macfeat_otftag = NULL;
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+static int UserSettingsDiffer(void) {
+ int i,j;
+
+ if ( user_macfeat_otftag==NULL )
+return( false );
+
+ for ( i=0; user_macfeat_otftag[i].otf_tag!=0; ++i );
+ for ( j=0; macfeat_otftag[j].otf_tag!=0; ++j );
+ if ( i!=j )
+return( true );
+ for ( i=0; user_macfeat_otftag[i].otf_tag!=0; ++i ) {
+ for ( j=0; macfeat_otftag[j].otf_tag!=0; ++j ) {
+ if ( macfeat_otftag[j].mac_feature_type ==
+ user_macfeat_otftag[i].mac_feature_type &&
+ macfeat_otftag[j].mac_feature_setting ==
+ user_macfeat_otftag[i].mac_feature_setting &&
+ macfeat_otftag[j].otf_tag ==
+ user_macfeat_otftag[i].otf_tag )
+ break;
+ }
+ if ( macfeat_otftag[j].otf_tag==0 )
+return( true );
+ }
+return( false );
+}
+
+/**************************************************************************** */
+
+
+/* don't use mnemonics 'C' or 'O' (Cancel & OK) */
+enum pref_types { pr_int, pr_real, pr_bool, pr_enum, pr_encoding, pr_string,
+ pr_file, pr_namelist };
+struct enums { char *name; int value; };
+
+struct enums fvsize_enums[] = { {NULL} };
+
+static struct prefs_list {
+ char *name;
+ /* In the prefs file the untranslated name will always be used, but */
+ /* in the UI that name may be translated. */
+ enum pref_types type;
+ void *val;
+ void *(*get)(void);
+ void (*set)(void *);
+ char mn;
+ struct enums *enums;
+ unsigned int dontdisplay: 1;
+ char *popup;
+} general_list[] = {
+ { N_("ResourceFile"), pr_file, &xdefs_filename, NULL, NULL, 'R', NULL, 0, N_("When FontForge starts up, it loads display related resources from a\nproperty on the screen. Sometimes it is useful to be able to store\nthese resources in a file. These resources are only read at start\nup, so changing this has no effect until the next time you start\nFontForge.") },
+ { N_("HelpDir"), pr_file, &helpdir, NULL, NULL, 'H', NULL, 0, N_("The directory on your local system in which FontForge will search for help\nfiles. If a file is not found there, then FontForge will look for it on the net.") },
+ { N_("OtherSubrsFile"), pr_file, &othersubrsfile, NULL, NULL, 'O', NULL, 0, N_("If you wish to replace Adobe's OtherSubrs array (for Type1 fonts)\nwith an array of your own, set this to point to a file containing\na list of up to 14 PostScript subroutines. Each subroutine must\nbe preceded by a line starting with '%%%%' (any text before the\nfirst '%%%%' line will be treated as an initial copyright notice).\nThe first three subroutines are for flex hints, the next for hint\nsubstitution (this MUST be present), the 14th (or 13 as the\nnumbering actually starts with 0) is for counter hints.\nThe subroutines should not be enclosed in a [ ] pair.") },
+ { N_("FreeTypeInFontView"), pr_bool, &use_freetype_to_rasterize_fv, NULL, NULL, 'O', NULL, 0, N_("Use the FreeType rasterizer (when available)\nto rasterize glyphs in the font view.\nThis generally results in better quality.") },
+ { N_("AutoHint"), pr_bool, &autohint_before_rasterize, NULL, NULL, 'A', NULL, 0, N_("AutoHint before rasterizing") },
+ { N_("SplashScreen"), pr_bool, &splash, NULL, NULL, 'S', NULL, 0, N_("Show splash screen on start-up") },
+ { NULL }
+},
+ new_list[] = {
+ { N_("NewCharset"), pr_encoding, &default_encoding, NULL, NULL, 'N', NULL, 0, N_("Default encoding for\nnew fonts") },
+ { N_("NewEmSize"), pr_int, &new_em_size, NULL, NULL, 'S', NULL, 0, N_("The default size of the Em-Square in a newly created font.") },
+ { N_("NewFontsQuadratic"), pr_bool, &new_fonts_are_order2, NULL, NULL, 'Q', NULL, 0, N_("Whether new fonts should contain splines of quadratic (truetype)\nor cubic (postscript & opentype).") },
+ { N_("LoadedFontsAsNew"), pr_bool, &loaded_fonts_same_as_new, NULL, NULL, 'L', NULL, 0, N_("Whether fonts loaded from the disk should retain their splines\nwith the original order (quadratic or cubic), or whether the\nsplines should be converted to the default order for new fonts\n(see NewFontsQuadratic).") },
+ { NULL }
+},
+ open_list[] = {
+ { N_("PreferCJKEncodings"), pr_bool, &prefer_cjk_encodings, NULL, NULL, 'C', NULL, 0, N_("When loading a truetype or opentype font which has both a unicode\nand a CJK encoding table, use this flag to specify which\nshould be loaded for the font.") },
+ { N_("AskUserForCMap"), pr_bool, &ask_user_for_cmap, NULL, NULL, 'O', NULL, 0, N_("When loading a font in sfnt format (TrueType, OpenType, etc.),\nask the user to specify which cmap to use initially.") },
+ { N_("PreserveTables"), pr_string, &SaveTablesPref, NULL, NULL, 'P', NULL, 0, N_("Enter a list of 4 letter table tags, separated by commas.\nFontForge will make a binary copy of these tables when it\nloads a True/OpenType font, and will output them (unchanged)\nwhen it generates the font. Do not include table tags which\nFontForge thinks it understands.") },
+ { NULL }
+},
+ navigation_list[] = {
+ { N_("GlyphAutoGoto"), pr_bool, &cv_auto_goto, NULL, NULL, '\0', NULL, 0, N_("Typing a normal character in the glyph view window changes the window to look at that character") },
+ { N_("OpenCharsInNewWindow"), pr_bool, &OpenCharsInNewWindow, NULL, NULL, '\0', NULL, 0, N_("When double clicking on a character in the font view\nopen that character in a new window, otherwise\nreuse an existing one.") },
+ { NULL }
+},
+ editing_list[] = {
+ { N_("ItalicConstrained"), pr_bool, &ItalicConstrained, NULL, NULL, '\0', NULL, 0, N_("In the Outline View, the Shift key constrains motion to be parallel to the ItalicAngle rather than constraining it to be vertical.") },
+ { N_("ArrowMoveSize"), pr_real, &arrowAmount, NULL, NULL, '\0', NULL, 0, N_("The number of em-units by which an arrow key will move a selected point") },
+ { N_("SnapDistance"), pr_real, &snapdistance, NULL, NULL, '\0', NULL, 0, N_("When the mouse pointer is within this many pixels\nof one of the various interesting features (baseline,\nwidth, grid splines, etc.) the pointer will snap\nto that feature.") },
+ { N_("JoinSnap"), pr_real, &joinsnap, NULL, NULL, '\0', NULL, 0, N_("The Edit->Join command will join points which are this close together\nA value of 0 means they must be coincident") },
+ { N_("StopAtJoin"), pr_bool, &stop_at_join, NULL, NULL, '\0', NULL, 0, N_("When dragging points in the outline view a join may occur\n(two open contours may connect at their endpoints). When\nthis is On a join will cause FontForge to stop moving the\nselection (as if the user had released the mouse button).\nThis is handy if your fingers are inclined to wiggle a bit.") },
+ { N_("CopyMetaData"), pr_bool, &copymetadata, NULL, NULL, '\0', NULL, 0, N_("When copying glyphs from the font view, also copy the\nglyphs' metadata (name, encoding, comment, etc).") },
+ { N_("UndoDepth"), pr_int, &maxundoes, NULL, NULL, '\0', NULL, 0, N_("The maximum number of Undoes/Redoes stored in a glyph") },
+ { N_("UpdateFlex"), pr_bool, &updateflex, NULL, NULL, '\0', NULL, 0, N_("Figure out flex hints after every change") },
+ { NULL }
+},
+ sync_list[] = {
+ { N_("AutoWidthSync"), pr_bool, &adjustwidth, NULL, NULL, '\0', NULL, 0, N_("Changing the width of a glyph\nchanges the widths of all accented\nglyphs based on it.") },
+ { N_("AutoLBearingSync"), pr_bool, &adjustlbearing, NULL, NULL, '\0', NULL, 0, N_("Changing the left side bearing\nof a glyph adjusts the lbearing\nof other references in all accented\nglyphs based on it.") },
+ { NULL }
+},
+ tt_list[] = {
+ { N_("ClearInstrsBigChanges"), pr_bool, &clear_tt_instructions_when_needed, NULL, NULL, 'C', NULL, 0, N_("Instructions in a TrueType font refer to\npoints by number, so if you edit a glyph\nin such a way that some points have different\nnumbers (add points, remove them, etc.) then\nthe instructions will be applied to the wrong\npoints with disasterous results.\n Normally FontForge will remove the instructions\nif it detects that the points have been renumbered\nin order to avoid the above problem. You may turn\nthis behavior off -- but be careful!") },
+ { N_("CopyTTFInstrs"), pr_bool, &copyttfinstr, NULL, NULL, '\0', NULL, 0, N_("When copying glyphs from the font view, also copy the\nglyphs' metadata (name, encoding, comment, etc).") },
+ { NULL }
+},
+ accent_list[] = {
+ { N_("AccentOffsetPercent"), pr_int, &accent_offset, NULL, NULL, '\0', NULL, 0, N_("The percentage of an em by which an accent is offset from its base glyph in Build Accent") },
+ { N_("AccentCenterLowest"), pr_bool, &GraveAcuteCenterBottom, NULL, NULL, '\0', NULL, 0, N_("When placing grave and acute accents above letters, should\nFontForge center them based on their full width, or\nshould it just center based on the lowest point\nof the accent.") },
+ { N_("CharCenterHighest"), pr_bool, &CharCenterHighest, NULL, NULL, '\0', NULL, 0, N_("When centering an accent over a glyph, should the accent\nbe centered on the highest point(s) of the glyph,\nor the middle of the glyph?") },
+ { N_("PreferSpacingAccents"), pr_bool, &PreferSpacingAccents, NULL, NULL, '\0', NULL, 0, N_("Use spacing accents (Unicode: 02C0-02FF) rather than\ncombining accents (Unicode: 0300-036F) when\nbuilding accented glyphs.") },
+ { NULL }
+},
+ args_list[] = {
+#ifndef LUA_FF_LIB
+ { N_("PreferPotrace"), pr_bool, &preferpotrace, NULL, NULL, '\0', NULL, 0, N_("FontForge supports two different helper applications to do autotracing\n autotrace and potrace\nIf your system only has one it will use that one, if you have both\nuse this option to tell FontForge which to pick.") },
+ { N_("AutotraceArgs"), pr_string, NULL, GetAutoTraceArgs, SetAutoTraceArgs, '\0', NULL, 0, N_("Extra arguments for configuring the autotrace program\n(either autotrace or potrace)") },
+ { N_("AutotraceAsk"), pr_bool, &autotrace_ask, NULL, NULL, '\0', NULL, 0, N_("Ask the user for autotrace arguments each time autotrace is invoked") },
+ { N_("MfArgs"), pr_string, &mf_args, NULL, NULL, '\0', NULL, 0, N_("Commands to pass to mf (metafont) program, the filename will follow these") },
+ { N_("MfAsk"), pr_bool, &mf_ask, NULL, NULL, '\0', NULL, 0, N_("Ask the user for mf commands each time mf is invoked") },
+ { N_("MfClearBg"), pr_bool, &mf_clearbackgrounds, NULL, NULL, '\0', NULL, 0, N_("FontForge loads large images into the background of each glyph\nprior to autotracing them. You may retain those\nimages to look at after mf processing is complete, or\nremove them to save space") },
+ { N_("MfShowErr"), pr_bool, &mf_showerrors, NULL, NULL, '\0', NULL, 0, N_("MetaFont (mf) generates lots of verbiage to stdout.\nMost of the time I find it an annoyance but it is\nimportant to see if something goes wrong.") },
+#endif
+ { NULL }
+},
+ fontinfo_list[] = {
+ { N_("FoundryName"), pr_string, &BDFFoundry, NULL, NULL, 'F', NULL, 0, N_("Name used for foundry field in bdf\nfont generation") },
+ { N_("TTFFoundry"), pr_string, &TTFFoundry, NULL, NULL, 'T', NULL, 0, N_("Name used for Vendor ID field in\nttf (OS/2 table) font generation.\nMust be no more than 4 characters") },
+ { N_("NewFontNameList"), pr_namelist, &namelist_for_new_fonts, NULL, NULL, '\0', NULL, 0, N_("FontForge will use this namelist when assigning\nglyph names to code points in a new font.") },
+ { N_("RecognizePUANames"), pr_bool, &recognizePUA, NULL, NULL, 'U', NULL, 0, N_("Once upon a time, Adobe assigned PUA (public use area) encodings\nfor many stylistic variants of characters (small caps, old style\nnumerals, etc.). Adobe no longer believes this to be a good idea,\nand recommends that these encodings be ignored.\n\n The assignments were originally made because most applications\ncould not handle OpenType features for accessing variants. Adobe\nnow believes that all apps that matter can now do so. Applications\nlike Word and OpenOffice still can't handle these features, so\n fontforge's default behavior is to ignore Adobe's current\nrecommendations.\n\nNote: This does not affect figuring out unicode from the font's encoding,\nit just controls determining unicode from a name.") },
+ { N_("UnicodeGlyphNames"), pr_bool, &allow_utf8_glyphnames, NULL, NULL, 'O', NULL, 0, N_("Allow the full unicode character set in glyph names.\nThis does not conform to adobe's glyph name standard.\nSuch names should be for internal use only and\nshould NOT end up in production fonts." ) },
+ { N_("XUID-Base"), pr_string, &xuid, NULL, NULL, 'X', NULL, 0, N_("If specified this should be a space separated list of integers each\nless than 16777216 which uniquely identify your organization\nFontForge will generate a random number for the final component.") },
+ { NULL }
+},
+ generate_list[] = {
+ { N_("AskBDFResolution"), pr_bool, &ask_user_for_resolution, NULL, NULL, 'B', NULL, 0, N_("When generating a set of BDF fonts ask the user\nto specify the screen resolution of the fonts\notherwise FontForge will guess depending on the pixel size.") },
+ { N_("HintForGen"), pr_bool, &autohint_before_generate, NULL, NULL, 'H', NULL, 0, N_("AutoHint changed glyphs before generating a font") },
+ { NULL }
+},
+ hints_list[] = {
+ { N_("HintBoundingBoxes"), pr_bool, &hint_bounding_boxes, NULL, NULL, '\0', NULL, 0, N_("FontForge will place vertical or horizontal hints to describe the bounding boxes of suitable glyphs.") },
+ { N_("HintDiagonalEnds"), pr_bool, &hint_diagonal_ends, NULL, NULL, '\0', NULL, 0, N_("FontForge will place vertical or horizontal hints at the ends of diagonal stems.") },
+ { N_("HintDiagonalInter"), pr_bool, &hint_diagonal_intersections, NULL, NULL, '\0', NULL, 0, N_("FontForge will place vertical or horizontal hints at the intersections of diagonal stems.") },
+ { NULL }
+},
+ opentype_list[] = {
+ { N_("UseNewIndicScripts"), pr_bool, &use_second_indic_scripts, NULL, NULL, 'C', NULL, 0, N_("MS has changed (in August 2006) the inner workings of their Indic shaping\nengine, and to disambiguate this change has created a parallel set of script\ntags (generally ending in '2') for Indic writing systems. If you are working\nwith the new system set this flag, if you are working with the old unset it.\n(if you aren't doing Indic work, this flag is irrelevant).") },
+ { NULL }
+},
+/* These are hidden, so will never appear in ui, hence, no "N_(" */
+ hidden_list[] = {
+ { "AntiAlias", pr_bool, &default_fv_antialias, NULL, NULL, '\0', NULL, 1 },
+ { "DefaultFVShowHmetrics", pr_int, &default_fv_showhmetrics, NULL, NULL, '\0', NULL, 1 },
+ { "DefaultFVShowVmetrics", pr_int, &default_fv_showvmetrics, NULL, NULL, '\0', NULL, 1 },
+ { "DefaultFVSize", pr_int, &default_fv_font_size, NULL, NULL, 'S', NULL, 1 },
+ { "DefaultFVRowCount", pr_int, &default_fv_row_count, NULL, NULL, 'S', NULL, 1 },
+ { "DefaultFVColCount", pr_int, &default_fv_col_count, NULL, NULL, 'S', NULL, 1 },
+ { "DefaultFVGlyphLabel", pr_int, &default_fv_glyphlabel, NULL, NULL, 'S', NULL, 1 },
+ { "SaveToDir", pr_int, &save_to_dir, NULL, NULL, 'S', NULL, 1 },
+ { "OnlyCopyDisplayed", pr_bool, &onlycopydisplayed, NULL, NULL, '\0', NULL, 1 },
+#ifndef LUA_FF_LIB
+ { "PalettesDocked", pr_bool, &palettes_docked, NULL, NULL, '\0', NULL, 1 },
+#endif
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ { "CVVisible0", pr_bool, &cvvisible[0], NULL, NULL, '\0', NULL, 1 },
+ { "CVVisible1", pr_bool, &cvvisible[1], NULL, NULL, '\0', NULL, 1 },
+ { "BVVisible0", pr_bool, &bvvisible[0], NULL, NULL, '\0', NULL, 1 },
+ { "BVVisible1", pr_bool, &bvvisible[1], NULL, NULL, '\0', NULL, 1 },
+ { "BVVisible2", pr_bool, &bvvisible[2], NULL, NULL, '\0', NULL, 1 },
+ { "MarkExtrema", pr_int, &CVShows.markextrema, NULL, NULL, '\0', NULL, 1 },
+ { "MarkPointsOfInflect", pr_int, &CVShows.markpoi, NULL, NULL, '\0', NULL, 1 },
+ { "ShowRulers", pr_bool, &CVShows.showrulers, NULL, NULL, '\0', NULL, 1, N_("Display rulers in the Outline Glyph View") },
+ { "ShowCPInfo", pr_int, &CVShows.showcpinfo, NULL, NULL, '\0', NULL, 1 },
+ { "ShowSideBearings", pr_int, &CVShows.showsidebearings, NULL, NULL, '\0', NULL, 1 },
+ { "ShowPoints", pr_bool, &CVShows.showpoints, NULL, NULL, '\0', NULL, 1 },
+ { "ShowFilled", pr_int, &CVShows.showfilled, NULL, NULL, '\0', NULL, 1 },
+ { "ShowTabs", pr_int, &CVShows.showtabs, NULL, NULL, '\0', NULL, 1 },
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+#ifndef LUA_FF_LIB
+ { "DefaultScreenDpiSystem", pr_int, &oldsystem, NULL, NULL, '\0', NULL, 1 },
+ { "DefaultOutputFormat", pr_int, &oldformatstate, NULL, NULL, '\0', NULL, 1 },
+ { "DefaultBitmapFormat", pr_int, &oldbitmapstate, NULL, NULL, '\0', NULL, 1 },
+ { "DefaultTTFflags", pr_int, &old_ttf_flags, NULL, NULL, '\0', NULL, 1 },
+ { "DefaultPSflags", pr_int, &old_ps_flags, NULL, NULL, '\0', NULL, 1 },
+ { "DefaultOTFflags", pr_int, &old_otf_flags, NULL, NULL, '\0', NULL, 1 },
+ { "PageWidth", pr_int, &pagewidth, NULL, NULL, '\0', NULL, 1 },
+ { "PageHeight", pr_int, &pageheight, NULL, NULL, '\0', NULL, 1 },
+ { "PrintType", pr_int, &printtype, NULL, NULL, '\0', NULL, 1 },
+ { "PrintCommand", pr_string, &printcommand, NULL, NULL, '\0', NULL, 1 },
+ { "PageLazyPrinter", pr_string, &printlazyprinter, NULL, NULL, '\0', NULL, 1 },
+ { "RegularStar", pr_bool, &regular_star, NULL, NULL, '\0', NULL, 1 },
+ { "PolyStar", pr_bool, &polystar, NULL, NULL, '\0', NULL, 1 },
+ { "RectEllipse", pr_bool, &rectelipse, NULL, NULL, '\0', NULL, 1 },
+ { "RectCenterOut", pr_bool, &center_out[0], NULL, NULL, '\0', NULL, 1 },
+ { "EllipseCenterOut", pr_bool, &center_out[1], NULL, NULL, '\0', NULL, 1 },
+ { "PolyStartPointCnt", pr_int, &ps_pointcnt, NULL, NULL, '\0', NULL, 1 },
+ { "RoundRectRadius", pr_real, &rr_radius, NULL, NULL, '\0', NULL, 1 },
+ { "StarPercent", pr_real, &star_percent, NULL, NULL, '\0', NULL, 1 },
+ { "CoverageFormatsAllowed", pr_int, &coverageformatsallowed, NULL, NULL, '\0', NULL, 1 },
+#endif
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ { "DebugWins", pr_int, &debug_wins, NULL, NULL, '\0', NULL, 1 },
+ { "GridFitDpi", pr_int, &gridfit_dpi, NULL, NULL, '\0', NULL, 1 },
+ { "GridFitDepth", pr_int, &gridfit_depth, NULL, NULL, '\0', NULL, 1 },
+ { "GridFitPointSize", pr_real, &gridfit_pointsize, NULL, NULL, '\0', NULL, 1 },
+#endif
+ { "ForceNamesWhenOpening", pr_namelist, &force_names_when_opening, NULL, NULL, '\0', NULL, 1 },
+ { "ForceNamesWhenSaving", pr_namelist, &force_names_when_saving, NULL, NULL, '\0', NULL, 1 },
+ { "DefaultFontFilterIndex", pr_int, &default_font_filter_index, NULL, NULL, '\0', NULL, 1 },
+ { NULL }
+},
+ oldnames[] = {
+ { "DumpGlyphMap", pr_bool, &glyph_2_name_map, NULL, NULL, '\0', NULL, 0, N_("When generating a truetype or opentype font it is occasionally\nuseful to know the mapping between truetype glyph ids and\nglyph names. Setting this option will cause FontForge to\nproduce a file (with extension .g2n) containing those data.") },
+ { "DefaultTTFApple", pr_int, &pointless, NULL, NULL, '\0', NULL, 1 },
+ { "AcuteCenterBottom", pr_bool, &GraveAcuteCenterBottom, NULL, NULL, '\0', NULL, 1, N_("When placing grave and acute accents above letters, should\nFontForge center them based on their full width, or\nshould it just center based on the lowest point\nof the accent.") },
+ { "AlwaysGenApple", pr_bool, &alwaysgenapple, NULL, NULL, 'A', NULL, 0, N_("Apple and MS/Adobe differ about the format of truetype and opentype files.\nThis controls the default setting of the Apple checkbox in the\nFile->Generate Font dialog.\nThe main differences are:\n Bitmap data are stored in different tables\n Scaled composite glyphs are treated differently\n Use of GSUB rather than morx(t)/feat\n Use of GPOS rather than kern/opbd\n Use of GDEF rather than lcar/prop\nIf both this and OpenType are set, both formats are generated") },
+ { "AlwaysGenOpenType", pr_bool, &alwaysgenopentype, NULL, NULL, 'O', NULL, 0, N_("Apple and MS/Adobe differ about the format of truetype and opentype files.\nThis controls the default setting of the OpenType checkbox in the\nFile->Generate Font dialog.\nThe main differences are:\n Bitmap data are stored in different tables\n Scaled composite glyphs are treated differently\n Use of GSUB rather than morx(t)/feat\n Use of GPOS rather than kern/opbd\n Use of GDEF rather than lcar/prop\nIf both this and Apple are set, both formats are generated") },
+ { NULL }
+},
+ *prefs_list[] = { general_list, new_list, open_list, navigation_list, sync_list, editing_list, accent_list, args_list, fontinfo_list, generate_list, tt_list, opentype_list, hints_list, hidden_list, NULL },
+ *load_prefs_list[] = { general_list, new_list, open_list, navigation_list, sync_list, editing_list, accent_list, args_list, fontinfo_list, generate_list, tt_list, opentype_list, hints_list, hidden_list, oldnames, NULL };
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+struct visible_prefs_list { char *tab_name; int nest; struct prefs_list *pl; } visible_prefs_list[] = {
+ { N_("Generic"), 0, general_list},
+ { N_("New Font"), 0, new_list},
+ { N_("Open Font"), 0, open_list},
+ { N_("Navigation"), 0, navigation_list},
+ { N_("Editing"), 0, editing_list},
+ { N_("Synchronize"), 1, sync_list},
+ { N_("TT"), 1, tt_list},
+ { N_("Accents"), 1, accent_list},
+ { N_("Apps"), 1, args_list},
+ { N_("Font Info"), 0, fontinfo_list},
+ { N_("Generate"), 0, generate_list},
+ { N_("PS Hints"), 1, hints_list},
+ { N_("OpenType"), 1, opentype_list},
+ { 0 }
+ };
+
+#define TOPICS (sizeof(visible_prefs_list)/sizeof(visible_prefs_list[0])-1)
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+int GetPrefs(char *name,Val *val) {
+ int i,j;
+
+ /* Support for obsolete preferences */
+#ifndef LUA_FF_LIB
+ alwaysgenapple=(old_ttf_flags&ttf_flag_applemode)?1:0;
+ alwaysgenopentype=(old_ttf_flags&ttf_flag_otmode)?1:0;
+#else
+ alwaysgenapple=0;
+ alwaysgenopentype=0;
+#endif
+
+ for ( i=0; prefs_list[i]!=NULL; ++i ) for ( j=0; prefs_list[i][j].name!=NULL; ++j ) {
+ if ( strcmp(prefs_list[i][j].name,name)==0 ) {
+ struct prefs_list *pf = &prefs_list[i][j];
+ if ( pf->type == pr_bool || pf->type == pr_int ) {
+ val->type = v_int;
+ val->u.ival = *((int *) (pf->val));
+ } else if ( pf->type == pr_string || pf->type == pr_file ) {
+ val->type = v_str;
+ val->u.sval = copy( *((char **) (pf->val)));
+ } else if ( pf->type == pr_encoding ) {
+ val->type = v_str;
+ if ( *((NameList **) (pf->val))==NULL )
+ val->u.sval = copy( "NULL" );
+ else
+ val->u.sval = copy( (*((Encoding **) (pf->val)))->enc_name );
+ } else if ( pf->type == pr_namelist ) {
+ val->type = v_str;
+ val->u.sval = copy( (*((NameList **) (pf->val)))->title );
+ } else if ( pf->type == pr_real ) {
+ val->type = v_real;
+ val->u.fval = *((float *) (pf->val));
+ } else
+return( false );
+
+return( true );
+ }
+ }
+return( false );
+}
+
+static void CheckObsoletePrefs(void) {
+#ifndef LUA_FF_LIB
+ if ( alwaysgenapple==false ) {
+ old_ttf_flags &= ~ttf_flag_applemode;
+ old_otf_flags &= ~ttf_flag_applemode;
+ } else if ( alwaysgenapple==true ) {
+ old_ttf_flags |= ttf_flag_applemode;
+ old_otf_flags |= ttf_flag_applemode;
+ }
+ if ( alwaysgenopentype==false ) {
+ old_ttf_flags &= ~ttf_flag_otmode;
+ old_otf_flags &= ~ttf_flag_otmode;
+ } else if ( alwaysgenopentype==true ) {
+ old_ttf_flags |= ttf_flag_otmode;
+ old_otf_flags |= ttf_flag_otmode;
+ }
+#endif
+}
+
+int SetPrefs(char *name,Val *val1, Val *val2) {
+ int i,j;
+
+ /* Support for obsolete preferences */
+ alwaysgenapple=-1; alwaysgenopentype=-1;
+
+ for ( i=0; prefs_list[i]!=NULL; ++i ) for ( j=0; prefs_list[i][j].name!=NULL; ++j ) {
+ if ( strcmp(prefs_list[i][j].name,name)==0 ) {
+ struct prefs_list *pf = &prefs_list[i][j];
+ if ( pf->type == pr_bool || pf->type == pr_int ) {
+ if ( (val1->type!=v_int && val1->type!=v_unicode) || val2!=NULL )
+return( -1 );
+ *((int *) (pf->val)) = val1->u.ival;
+ } else if ( pf->type == pr_real ) {
+ if ( val1->type==v_real && val2==NULL )
+ *((float *) (pf->val)) = val1->u.fval;
+ else if ( val1->type!=v_int || (val2!=NULL && val2->type!=v_int ))
+return( -1 );
+ else
+ *((float *) (pf->val)) = (val2==NULL ? val1->u.ival : val1->u.ival / (double) val2->u.ival);
+ } else if ( pf->type == pr_string || pf->type == pr_file ) {
+ if ( val1->type!=v_str || val2!=NULL )
+return( -1 );
+ if ( pf->set ) {
+ pf->set( val1->u.sval );
+ } else {
+ free( *((char **) (pf->val)));
+ *((char **) (pf->val)) = copy( val1->u.sval );
+ }
+ } else if ( pf->type == pr_encoding ) {
+ if ( val2!=NULL )
+return( -1 );
+ else if ( val1->type==v_str && pf->val == &default_encoding) {
+ Encoding *enc = FindOrMakeEncoding(val1->u.sval);
+ if ( enc==NULL )
+return( -1 );
+ *((Encoding **) (pf->val)) = enc;
+ } else
+return( -1 );
+ } else if ( pf->type == pr_namelist ) {
+ if ( val2!=NULL )
+return( -1 );
+ else if ( val1->type==v_str ) {
+#ifndef LUA_FF_LIB
+ NameList *nl = NameListByName(val1->u.sval);
+ if ( strcmp(val1->u.sval,"NULL")==0 && pf->val != &namelist_for_new_fonts )
+ nl = NULL;
+ else if ( nl==NULL )
+ return( -1 );
+ *((NameList **) (pf->val)) = nl;
+#endif
+ } else
+ return( -1 );
+ } else
+return( false );
+
+ CheckObsoletePrefs();
+ SavePrefs();
+return( true );
+ }
+ }
+return( false );
+}
+
+static char *getPfaEditPrefs(void) {
+ static char *prefs=NULL;
+ char buffer[1025];
+
+ if ( prefs!=NULL )
+return( prefs );
+ if ( getPfaEditDir(buffer)==NULL )
+return( NULL );
+ sprintf(buffer,"%s/prefs", getPfaEditDir(buffer));
+ prefs = copy(buffer);
+return( prefs );
+}
+
+char *getPfaEditShareDir(void) {
+ static char *sharedir=NULL;
+ static int set=false;
+ char *pt = NULL;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ int len;
+#endif
+
+ if ( set )
+return( sharedir );
+
+ set = true;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ pt = strstr(GResourceProgramDir,"/bin");
+#endif
+ if ( pt==NULL )
+return( NULL );
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ len = (pt-GResourceProgramDir)+strlen("/share/fontforge")+1;
+ sharedir = galloc(len);
+ strncpy(sharedir,GResourceProgramDir,pt-GResourceProgramDir);
+ strcpy(sharedir+(pt-GResourceProgramDir),"/share/fontforge");
+return( sharedir );
+#endif
+return( NULL );
+}
+
+#if !defined(FONTFORGE_CONFIG_GTK)
+#ifndef LUA_FF_LIB
+# include <charset.h> /* we still need the charsets & encoding to set local_encoding */
+static int encmatch(const char *enc,int subok) {
+ static struct { char *name; int enc; } encs[] = {
+ { "US-ASCII", e_usascii },
+ { "ASCII", e_usascii },
+ { "ISO646-NO", e_iso646_no },
+ { "ISO646-SE", e_iso646_se },
+ { "LATIN1", e_iso8859_1 },
+ { "ISO-8859-1", e_iso8859_1 },
+ { "ISO-8859-2", e_iso8859_2 },
+ { "ISO-8859-3", e_iso8859_3 },
+ { "ISO-8859-4", e_iso8859_4 },
+ { "ISO-8859-5", e_iso8859_4 },
+ { "ISO-8859-6", e_iso8859_4 },
+ { "ISO-8859-7", e_iso8859_4 },
+ { "ISO-8859-8", e_iso8859_4 },
+ { "ISO-8859-9", e_iso8859_4 },
+ { "ISO-8859-10", e_iso8859_10 },
+ { "ISO-8859-11", e_iso8859_11 },
+ { "ISO-8859-13", e_iso8859_13 },
+ { "ISO-8859-14", e_iso8859_14 },
+ { "ISO-8859-15", e_iso8859_15 },
+ { "ISO_8859-1", e_iso8859_1 },
+ { "ISO_8859-2", e_iso8859_2 },
+ { "ISO_8859-3", e_iso8859_3 },
+ { "ISO_8859-4", e_iso8859_4 },
+ { "ISO_8859-5", e_iso8859_4 },
+ { "ISO_8859-6", e_iso8859_4 },
+ { "ISO_8859-7", e_iso8859_4 },
+ { "ISO_8859-8", e_iso8859_4 },
+ { "ISO_8859-9", e_iso8859_4 },
+ { "ISO_8859-10", e_iso8859_10 },
+ { "ISO_8859-11", e_iso8859_11 },
+ { "ISO_8859-13", e_iso8859_13 },
+ { "ISO_8859-14", e_iso8859_14 },
+ { "ISO_8859-15", e_iso8859_15 },
+ { "ISO8859-1", e_iso8859_1 },
+ { "ISO8859-2", e_iso8859_2 },
+ { "ISO8859-3", e_iso8859_3 },
+ { "ISO8859-4", e_iso8859_4 },
+ { "ISO8859-5", e_iso8859_4 },
+ { "ISO8859-6", e_iso8859_4 },
+ { "ISO8859-7", e_iso8859_4 },
+ { "ISO8859-8", e_iso8859_4 },
+ { "ISO8859-9", e_iso8859_4 },
+ { "ISO8859-10", e_iso8859_10 },
+ { "ISO8859-11", e_iso8859_11 },
+ { "ISO8859-13", e_iso8859_13 },
+ { "ISO8859-14", e_iso8859_14 },
+ { "ISO8859-15", e_iso8859_15 },
+ { "ISO88591", e_iso8859_1 },
+ { "ISO88592", e_iso8859_2 },
+ { "ISO88593", e_iso8859_3 },
+ { "ISO88594", e_iso8859_4 },
+ { "ISO88595", e_iso8859_4 },
+ { "ISO88596", e_iso8859_4 },
+ { "ISO88597", e_iso8859_4 },
+ { "ISO88598", e_iso8859_4 },
+ { "ISO88599", e_iso8859_4 },
+ { "ISO885910", e_iso8859_10 },
+ { "ISO885911", e_iso8859_11 },
+ { "ISO885913", e_iso8859_13 },
+ { "ISO885914", e_iso8859_14 },
+ { "ISO885915", e_iso8859_15 },
+ { "8859_1", e_iso8859_1 },
+ { "8859_2", e_iso8859_2 },
+ { "8859_3", e_iso8859_3 },
+ { "8859_4", e_iso8859_4 },
+ { "8859_5", e_iso8859_4 },
+ { "8859_6", e_iso8859_4 },
+ { "8859_7", e_iso8859_4 },
+ { "8859_8", e_iso8859_4 },
+ { "8859_9", e_iso8859_4 },
+ { "8859_10", e_iso8859_10 },
+ { "8859_11", e_iso8859_11 },
+ { "8859_13", e_iso8859_13 },
+ { "8859_14", e_iso8859_14 },
+ { "8859_15", e_iso8859_15 },
+ { "KOI8-R", e_koi8_r },
+ { "KOI8R", e_koi8_r },
+ { "WINDOWS-1252", e_win },
+ { "CP1252", e_win },
+ { "Big5", e_big5 },
+ { "Big-5", e_big5 },
+ { "BigFive", e_big5 },
+ { "Big-Five", e_big5 },
+ { "Big5HKSCS", e_big5hkscs },
+ { "Big5-HKSCS", e_big5hkscs },
+ { "UTF-8", e_utf8 },
+ { "ISO-10646/UTF-8", e_utf8 },
+ { "ISO_10646/UTF-8", e_utf8 },
+ { "UCS2", e_unicode },
+ { "UCS-2", e_unicode },
+ { "UCS-2-INTERNAL", e_unicode },
+ { "ISO-10646", e_unicode },
+ { "ISO_10646", e_unicode },
+#if 0
+ { "eucJP", e_euc },
+ { "EUC-JP", e_euc },
+ { "ujis", ??? },
+ { "EUC-KR", e_euckorean },
+#endif
+ { NULL }};
+ int i;
+#if HAVE_ICONV_H
+ static char *last_complaint;
+#endif
+ char buffer[80];
+
+#if HAVE_ICONV_H
+ iconv_t test;
+ free(iconv_local_encoding_name);
+ iconv_local_encoding_name= NULL;
+#endif
+
+ if ( strchr(enc,'@')!=NULL && strlen(enc)<sizeof(buffer)-1 ) {
+ strcpy(buffer,enc);
+ *strchr(buffer,'@') = '\0';
+ enc = buffer;
+ }
+
+ for ( i=0; encs[i].name!=NULL; ++i )
+ if ( strmatch(enc,encs[i].name)==0 )
+return( encs[i].enc );
+
+ if ( subok ) {
+ for ( i=0; encs[i].name!=NULL; ++i )
+ if ( strstrmatch(enc,encs[i].name)!=NULL )
+return( encs[i].enc );
+
+#if HAVE_ICONV_H
+ /* I only try to use iconv if the encoding doesn't match one I support*/
+ /* loading iconv unicode data takes a while */
+ test = iconv_open(enc,FindUnicharName());
+ if ( test==(iconv_t) (-1) || test==NULL ) {
+ if ( last_complaint==NULL || strcmp(last_complaint,enc)!=0 ) {
+ fprintf( stderr, "Neither FontForge nor iconv() supports your encoding (%s) we will pretend\n you asked for latin1 instead.\n", enc );
+ free( last_complaint );
+ last_complaint = copy(enc);
+ }
+ } else {
+ if ( last_complaint==NULL || strcmp(last_complaint,enc)!=0 ) {
+ fprintf( stderr, "FontForge does not support your encoding (%s), it will try to use iconv()\n or it will pretend the local encoding is latin1\n", enc );
+ free( last_complaint );
+ last_complaint = copy(enc);
+ }
+ iconv_local_encoding_name= copy(enc);
+ iconv_close(test);
+ }
+#else
+ fprintf( stderr, "FontForge does not support your encoding (%s), it will pretend the local encoding is latin1\n", enc );
+#endif
+
+return( e_iso8859_1 );
+ }
+return( e_unknown );
+}
+
+static int DefaultEncoding(void) {
+ const char *loc;
+ int enc;
+
+#if HAVE_LANGINFO_H
+ loc = nl_langinfo(CODESET);
+ enc = encmatch(loc,false);
+ if ( enc!=e_unknown )
+return( enc );
+#endif
+ loc = getenv("LC_ALL");
+ if ( loc==NULL ) loc = getenv("LC_CTYPE");
+ /*if ( loc==NULL ) loc = getenv("LC_MESSAGES");*/
+ if ( loc==NULL ) loc = getenv("LANG");
+
+ if ( loc==NULL )
+return( e_iso8859_1 );
+
+ enc = encmatch(loc,false);
+ if ( enc==e_unknown ) {
+ loc = strrchr(loc,'.');
+ if ( loc==NULL )
+return( e_iso8859_1 );
+ enc = encmatch(loc+1,true);
+ }
+ if ( enc==e_unknown )
+return( e_iso8859_1 );
+
+return( enc );
+}
+#endif
+#endif
+
+static void ParseMacMapping(char *pt,struct macsettingname *ms) {
+ char *end;
+
+ ms->mac_feature_type = strtol(pt,&end,10);
+ if ( *end==',' ) ++end;
+ ms->mac_feature_setting = strtol(end,&end,10);
+ if ( *end==' ' ) ++end;
+ ms->otf_tag =
+ ((end[0]&0xff)<<24) |
+ ((end[1]&0xff)<<16) |
+ ((end[2]&0xff)<<8) |
+ (end[3]&0xff);
+}
+
+#ifndef LUA_FF_LIB
+static void ParseNewMacFeature(FILE *p,char *line) {
+ fseek(p,-(strlen(line)-strlen("MacFeat:")),SEEK_CUR);
+ line[strlen("MacFeat:")] ='\0';
+ default_mac_feature_map = SFDParseMacFeatures(p,line);
+ fseek(p,-strlen(line),SEEK_CUR);
+ if ( user_mac_feature_map!=NULL )
+ MacFeatListFree(user_mac_feature_map);
+ user_mac_feature_map = default_mac_feature_map;
+}
+#endif
+
+static void DefaultXUID(void) {
+ /* Adobe has assigned PfaEdit a base XUID of 1021. Each new user is going */
+ /* to get a couple of random numbers appended to that, hoping that will */
+ /* make for a fairly safe system. */
+ /* FontForge will use the same scheme */
+ int r1 = 0, r2 = 0;
+ char buffer[50];
+#ifndef LUA_FF_LIB /* TH odd, the crosscompiler gets ld errors from gettimeofday() */
+ struct timeval tv;
+
+ gettimeofday(&tv,NULL);
+ srand(tv.tv_usec);
+ do {
+ r1 = rand()&0x3ff;
+ } while ( r1==0 ); /* I reserve "0" for me! */
+ gettimeofday(&tv,NULL);
+ srandom(tv.tv_usec+1);
+ r2 = random();
+#endif
+ sprintf( buffer, "1021 %d %d", r1, r2 );
+ free(xuid);
+ xuid = copy(buffer);
+}
+
+static void DefaultHelp(void) {
+ if ( helpdir==NULL ) {
+#ifdef DOCDIR
+ helpdir = copy(DOCDIR "/");
+#elif defined(SHAREDIR)
+ helpdir = copy(SHAREDIR "/../doc/fontforge/");
+#else
+ helpdir = copy("/usr/local/share/doc/fontforge/");
+#endif
+ }
+}
+
+void SetDefaults(void) {
+
+ DefaultXUID();
+ DefaultHelp();
+}
+
+void LoadPrefs(void) {
+ char *prefs = getPfaEditPrefs();
+ FILE *p;
+ char line[1100];
+ int i=0, j=0, ri=0, mn=0, ms=0, fn=0, ff=0, filt_max=0;
+ int msp=0, msc=0;
+ char *pt;
+ struct prefs_list *pl;
+
+#if !defined(NOPLUGIN)
+ LoadPluginDir(NULL);
+#endif
+ LoadPfaEditEncodings();
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ LoadGroupList();
+#endif
+
+ if ( prefs!=NULL && (p=fopen(prefs,"r"))!=NULL ) {
+ while ( fgets(line,sizeof(line),p)!=NULL ) {
+ if ( *line=='#' )
+ continue;
+ pt = strchr(line,':');
+ if ( pt==NULL )
+ continue;
+ for ( j=0; load_prefs_list[j]!=NULL; ++j ) {
+ for ( i=0; load_prefs_list[j][i].name!=NULL; ++i )
+ if ( strncmp(line,load_prefs_list[j][i].name,pt-line)==0 )
+ break;
+ if ( load_prefs_list[j][i].name!=NULL )
+ break;
+ }
+ pl = NULL;
+ if ( load_prefs_list[j]!=NULL )
+ pl = &load_prefs_list[j][i];
+ for ( ++pt; *pt=='\t'; ++pt );
+ if ( line[strlen(line)-1]=='\n' )
+ line[strlen(line)-1] = '\0';
+ if ( line[strlen(line)-1]=='\r' )
+ line[strlen(line)-1] = '\0';
+ if ( pl==NULL ) {
+ if ( strncmp(line,"Recent:",strlen("Recent:"))==0 && ri<RECENT_MAX )
+ RecentFiles[ri++] = copy(pt);
+ else if ( strncmp(line,"MenuScript:",strlen("MenuScript:"))==0 && ms<SCRIPT_MENU_MAX )
+ script_filenames[ms++] = copy(pt);
+ else if ( strncmp(line,"MenuName:",strlen("MenuName:"))==0 && mn<SCRIPT_MENU_MAX )
+ script_menu_names[mn++] = utf82u_copy(pt);
+ else if ( strncmp(line,"FontFilterName:",strlen("FontFilterName:"))==0 ) {
+ if ( fn>=filt_max )
+ user_font_filters = grealloc(user_font_filters,((filt_max+=10)+1)*sizeof( struct openfilefilters));
+ user_font_filters[fn].filter = NULL;
+ user_font_filters[fn++].name = copy(pt);
+ user_font_filters[fn].name = NULL;
+ } else if ( strncmp(line,"FontFilter:",strlen("FontFilter:"))==0 ) {
+ if ( ff<filt_max )
+ user_font_filters[ff++].filter = copy(pt);
+ } else if ( strncmp(line,"MacMapCnt:",strlen("MacSetCnt:"))==0 ) {
+ sscanf( pt, "%d", &msc );
+ msp = 0;
+ user_macfeat_otftag = gcalloc(msc+1,sizeof(struct macsettingname));
+ } else if ( strncmp(line,"MacMapping:",strlen("MacMapping:"))==0 && msp<msc ) {
+ ParseMacMapping(pt,&user_macfeat_otftag[msp++]);
+#ifndef LUA_FF_LIB
+ } else if ( strncmp(line,"MacFeat:",strlen("MacFeat:"))==0 ) {
+ ParseNewMacFeature(p,line);
+#endif
+ }
+ continue;
+ }
+ switch ( pl->type ) {
+ case pr_encoding:
+ { Encoding *enc = FindOrMakeEncoding(pt);
+ if ( enc==NULL )
+ enc = FindOrMakeEncoding("ISO8859-1");
+ if ( enc==NULL )
+ enc = &custom;
+ *((Encoding **) (pl->val)) = enc;
+ }
+ break;
+ case pr_namelist:
+#ifndef LUA_FF_LIB
+ { NameList *nl = NameListByName(pt);
+ if ( strcmp(pt,"NULL")==0 && pl->val != &namelist_for_new_fonts )
+ *((NameList **) (pl->val)) = NULL;
+ else if ( nl!=NULL )
+ *((NameList **) (pl->val)) = nl;
+ }
+#endif
+ break;
+ case pr_bool: case pr_int:
+ sscanf( pt, "%d", (int *) pl->val );
+ break;
+ case pr_real:
+ sscanf( pt, "%f", (float *) pl->val );
+ break;
+ case pr_string: case pr_file:
+ if ( *pt=='\0' ) pt=NULL;
+ if ( pl->val!=NULL )
+ *((char **) (pl->val)) = copy(pt);
+ else
+ (pl->set)(copy(pt));
+ break;
+ case pr_enum:
+ break;
+ }
+ }
+ fclose(p);
+ }
+#if defined(FONTFORGE_CONFIG_GTK)
+ /* Nothing */;
+#else
+#ifndef LUA_FF_LIB
+ local_encoding = DefaultEncoding();
+#endif
+#endif
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ if ( xdefs_filename!=NULL )
+ GResourceAddResourceFile(xdefs_filename,GResourceProgramName);
+#endif
+#ifndef LUA_FF_LIB
+ if ( othersubrsfile!=NULL && ReadOtherSubrsFile(othersubrsfile)<=0 )
+ fprintf( stderr, "Failed to read OtherSubrs from %s\n", othersubrsfile );
+
+#endif
+ if ( glyph_2_name_map ) {
+#ifndef LUA_FF_LIB
+ old_ttf_flags |= ttf_flag_glyphmap;
+ old_otf_flags |= ttf_flag_glyphmap;
+#endif
+ }
+#ifndef LUA_FF_LIB
+ LoadNamelistDir(NULL);
+#endif
+}
+
+void PrefDefaultEncoding(void) {
+#ifndef LUA_FF_LIB
+ local_encoding = DefaultEncoding();
+#endif
+}
+
+void _SavePrefs(void) {
+ char *prefs = getPfaEditPrefs();
+ FILE *p;
+ int i, j;
+ char *temp;
+ struct prefs_list *pl;
+
+ if ( prefs==NULL )
+return;
+ if ( (p=fopen(prefs,"w"))==NULL )
+return;
+
+ for ( j=0; prefs_list[j]!=NULL; ++j ) for ( i=0; prefs_list[j][i].name!=NULL; ++i ) {
+ pl = &prefs_list[j][i];
+ switch ( pl->type ) {
+ case pr_encoding:
+ fprintf( p, "%s:\t%s\n", pl->name, (*((Encoding **) (pl->val)))->enc_name );
+ break;
+ case pr_namelist:
+ fprintf( p, "%s:\t%s\n", pl->name, *((NameList **) (pl->val))==NULL ? "NULL" :
+ (*((NameList **) (pl->val)))->title );
+ break;
+ case pr_bool: case pr_int:
+ fprintf( p, "%s:\t%d\n", pl->name, *(int *) (pl->val) );
+ break;
+ case pr_real:
+ fprintf( p, "%s:\t%g\n", pl->name, (double) *(float *) (pl->val) );
+ break;
+ case pr_string: case pr_file:
+ if ( (pl->val)!=NULL )
+ temp = *(char **) (pl->val);
+ else
+ temp = (char *) (pl->get());
+ if ( temp!=NULL )
+ fprintf( p, "%s:\t%s\n", pl->name, temp );
+ if ( (pl->val)==NULL )
+ free(temp);
+ break;
+ case pr_enum:
+ break;
+ }
+ }
+
+ for ( i=0; i<RECENT_MAX && RecentFiles[i]!=NULL; ++i )
+ fprintf( p, "Recent:\t%s\n", RecentFiles[i]);
+ for ( i=0; i<SCRIPT_MENU_MAX && script_filenames[i]!=NULL; ++i ) {
+ fprintf( p, "MenuScript:\t%s\n", script_filenames[i]);
+ fprintf( p, "MenuName:\t%s\n", temp = u2utf8_copy(script_menu_names[i]));
+ free(temp);
+ }
+ if ( user_font_filters!=NULL ) {
+ for ( i=0; user_font_filters[i].name!=NULL; ++i ) {
+ fprintf( p, "FontFilterName:\t%s\n", user_font_filters[i].name);
+ fprintf( p, "FontFilter:\t%s\n", user_font_filters[i].filter);
+ }
+ }
+ if ( user_macfeat_otftag!=NULL && UserSettingsDiffer()) {
+ for ( i=0; user_macfeat_otftag[i].otf_tag!=0; ++i );
+ fprintf( p, "MacMapCnt: %d\n", i );
+ for ( i=0; user_macfeat_otftag[i].otf_tag!=0; ++i ) {
+ fprintf( p, "MacMapping: %d,%d %c%c%c%c\n",
+ user_macfeat_otftag[i].mac_feature_type,
+ user_macfeat_otftag[i].mac_feature_setting,
+ (int) (user_macfeat_otftag[i].otf_tag>>24),
+ (int) ((user_macfeat_otftag[i].otf_tag>>16)&0xff),
+ (int) ((user_macfeat_otftag[i].otf_tag>>8)&0xff),
+ (int) (user_macfeat_otftag[i].otf_tag&0xff) );
+ }
+ }
+
+#ifndef LUA_FF_LIB
+ if ( UserFeaturesDiffer())
+ SFDDumpMacFeat(p,default_mac_feature_map);
+#endif
+ fclose(p);
+}
+
+void SavePrefs(void) {
+ extern int running_script;
+ if ( running_script )
+return;
+ _SavePrefs();
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+struct pref_data {
+ int done;
+};
+
+static int Prefs_ScriptBrowse(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GWindow gw = GGadgetGetWindow(g);
+ GGadget *tf = GWidgetGetControl(gw,GGadgetGetCid(g)-SCRIPT_MENU_MAX);
+ char *cur = GGadgetGetTitle8(tf); char *ret;
+
+ if ( *cur=='\0' ) cur=NULL;
+ ret = gwwv_open_filename(_("Call Script"), cur, "*.pe", NULL);
+ free(cur);
+ if ( ret==NULL )
+return(true);
+ GGadgetSetTitle8(tf,ret);
+ free(ret);
+ }
+return( true );
+}
+
+static int Prefs_BrowseFile(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GWindow gw = GGadgetGetWindow(g);
+ GGadget *tf = GWidgetGetControl(gw,GGadgetGetCid(g)-CID_PrefsBrowseOffset);
+ char *cur = GGadgetGetTitle8(tf); char *ret;
+ struct prefs_list *pl = GGadgetGetUserData(tf);
+
+ ret = gwwv_open_filename(pl->name, *cur=='\0'? NULL : cur, NULL, NULL);
+ free(cur);
+ if ( ret==NULL )
+return(true);
+ GGadgetSetTitle8(tf,ret);
+ free(ret);
+ }
+return( true );
+}
+
+static GTextInfo *Pref_MappingList(int use_user) {
+ struct macsettingname *msn = use_user && user_macfeat_otftag!=NULL ?
+ user_macfeat_otftag :
+ macfeat_otftag;
+ GTextInfo *ti;
+ int i;
+ char buf[60];
+
+ for ( i=0; msn[i].otf_tag!=0; ++i );
+ ti = gcalloc(i+1,sizeof( GTextInfo ));
+
+ for ( i=0; msn[i].otf_tag!=0; ++i ) {
+ sprintf(buf,"%3d,%2d %c%c%c%c",
+ msn[i].mac_feature_type, msn[i].mac_feature_setting,
+ (int) (msn[i].otf_tag>>24), (int) ((msn[i].otf_tag>>16)&0xff), (int) ((msn[i].otf_tag>>8)&0xff), (int) (msn[i].otf_tag&0xff) );
+ ti[i].text = uc_copy(buf);
+ }
+return( ti );
+}
+
+void GListAddStr(GGadget *list,unichar_t *str, void *ud) {
+ int32 i,len;
+ GTextInfo **ti = GGadgetGetList(list,&len);
+ GTextInfo **replace = galloc((len+2)*sizeof(GTextInfo *));
+
+ replace[len+1] = gcalloc(1,sizeof(GTextInfo));
+ for ( i=0; i<len; ++i ) {
+ replace[i] = galloc(sizeof(GTextInfo));
+ *replace[i] = *ti[i];
+ replace[i]->text = u_copy(ti[i]->text);
+ }
+ replace[i] = gcalloc(1,sizeof(GTextInfo));
+ replace[i]->fg = replace[i]->bg = COLOR_DEFAULT;
+ replace[i]->text = str;
+ replace[i]->userdata = ud;
+ GGadgetSetList(list,replace,false);
+}
+
+void GListReplaceStr(GGadget *list,int index, unichar_t *str, void *ud) {
+ int32 i,len;
+ GTextInfo **ti = GGadgetGetList(list,&len);
+ GTextInfo **replace = galloc((len+2)*sizeof(GTextInfo *));
+
+ for ( i=0; i<len; ++i ) {
+ replace[i] = galloc(sizeof(GTextInfo));
+ *replace[i] = *ti[i];
+ if ( i!=index )
+ replace[i]->text = u_copy(ti[i]->text);
+ }
+ replace[i] = gcalloc(1,sizeof(GTextInfo));
+ replace[index]->text = str;
+ replace[index]->userdata = ud;
+ GGadgetSetList(list,replace,false);
+}
+
+struct setdata {
+ GWindow gw;
+ GGadget *list;
+ GGadget *flist;
+ GGadget *feature;
+ GGadget *set_code;
+ GGadget *otf;
+ GGadget *ok;
+ GGadget *cancel;
+ int index;
+ int done;
+ unichar_t *ret;
+};
+
+static int set_e_h(GWindow gw, GEvent *event) {
+ struct setdata *sd = GDrawGetUserData(gw);
+ int i;
+ int32 len;
+ GTextInfo **ti;
+ const unichar_t *ret1; unichar_t *end;
+ int on, feat, val1, val2;
+ unichar_t ubuf[4];
+ char buf[40];
+
+ if ( event->type==et_close ) {
+ sd->done = true;
+ } else if ( event->type==et_char ) {
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("prefs.html#Features");
+return( true );
+ }
+return( false );
+ } else if ( event->type==et_controlevent && event->u.control.subtype == et_buttonactivate ) {
+ if ( event->u.control.g == sd->cancel ) {
+ sd->done = true;
+ } else if ( event->u.control.g == sd->ok ) {
+ ret1 = _GGadgetGetTitle(sd->set_code);
+ on = u_strtol(ret1,&end,10);
+ if ( *end!='\0' ) {
+ gwwv_post_error(_("Bad Number"),_("Bad Number"));
+return( true );
+ }
+ ret1 = _GGadgetGetTitle(sd->feature);
+ feat = u_strtol(ret1,&end,10);
+ if ( *end!='\0' && *end!=' ' ) {
+ gwwv_post_error(_("Bad Number"),_("Bad Number"));
+return( true );
+ }
+ ti = GGadgetGetList(sd->list,&len);
+ for ( i=0; i<len; ++i ) if ( i!=sd->index ) {
+ val1 = u_strtol(ti[i]->text,&end,10);
+ val2 = u_strtol(end+1,NULL,10);
+ if ( val1==feat && val2==on ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ static char *buts[3];
+ buts[0] = _("_Yes");
+ buts[1] = _("_No");
+ buts[2] = NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buts[] = { GTK_STOCK_YES, GTK_STOCK_NO, NULL };
+#endif
+ if ( gwwv_ask(_("This feature, setting combination is already used"),(const char **) buts,0,1,
+ _("This feature, setting combination is already used\nDo you really wish to reuse it?"))==1 )
+return( true );
+ }
+ }
+
+ ret1 = _GGadgetGetTitle(sd->otf);
+ if ( (ubuf[0] = ret1[0])==0 )
+ ubuf[0] = ubuf[1] = ubuf[2] = ubuf[3] = ' ';
+ else if ( (ubuf[1] = ret1[1])==0 )
+ ubuf[1] = ubuf[2] = ubuf[3] = ' ';
+ else if ( (ubuf[2] = ret1[2])==0 )
+ ubuf[2] = ubuf[3] = ' ';
+ else if ( (ubuf[3] = ret1[3])==0 )
+ ubuf[3] = ' ';
+ len = u_strlen(ret1);
+ if ( len<2 || len>4 || ubuf[0]>=0x7f || ubuf[1]>=0x7f || ubuf[2]>=0x7f || ubuf[3]>=0x7f ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ gwwv_post_error(_("Tag too long"),_("Feature tags must be exactly 4 ASCII characters"));
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("Tag too long"),_("Feature tags must be exactly 4 ASCII characters"));
+#endif
+return( true );
+ }
+ sprintf(buf,"%3d,%2d %c%c%c%c",
+ feat, on,
+ ubuf[0], ubuf[1], ubuf[2], ubuf[3]);
+ sd->done = true;
+ sd->ret = uc_copy(buf);
+ }
+ }
+return( true );
+}
+
+static unichar_t *AskSetting(struct macsettingname *temp,GGadget *list, int index,GGadget *flist) {
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GGadgetCreateData gcd[17];
+ GTextInfo label[17];
+ struct setdata sd;
+ char buf[20];
+ unichar_t ubuf3[6];
+ int32 len, i;
+ GTextInfo **ti;
+
+ memset(&sd,0,sizeof(sd));
+ sd.list = list;
+ sd.flist = flist;
+ sd.index = index;
+
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Mapping");
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,240));
+ pos.height = GDrawPointsToPixels(NULL,120);
+ gw = GDrawCreateTopWindow(NULL,&pos,set_e_h,&sd,&wattrs);
+ sd.gw = gw;
+
+ memset(gcd,0,sizeof(gcd));
+ memset(label,0,sizeof(label));
+
+ label[0].text = (unichar_t *) _("_Feature:");
+ label[0].text_is_1byte = true;
+ label[0].text_in_resource = true;
+ gcd[0].gd.label = &label[0];
+ gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 5+4;
+ gcd[0].gd.flags = gg_enabled|gg_visible;
+ gcd[0].creator = GLabelCreate;
+
+ gcd[1].gd.pos.x = 50; gcd[1].gd.pos.y = 5; gcd[1].gd.pos.width = 170;
+ gcd[1].gd.flags = gg_enabled|gg_visible;
+ gcd[1].creator = GListButtonCreate;
+
+ label[2].text = (unichar_t *) _("Setting");
+ label[2].text_is_1byte = true;
+ gcd[2].gd.label = &label[2];
+ gcd[2].gd.pos.x = 5; gcd[2].gd.pos.y = gcd[0].gd.pos.y+26;
+ gcd[2].gd.flags = gg_enabled|gg_visible;
+ gcd[2].creator = GLabelCreate;
+
+ sprintf( buf, "%d", temp->mac_feature_setting );
+ label[3].text = (unichar_t *) buf;
+ label[3].text_is_1byte = true;
+ gcd[3].gd.label = &label[3];
+ gcd[3].gd.pos.x = gcd[1].gd.pos.x; gcd[3].gd.pos.y = gcd[2].gd.pos.y-4; gcd[3].gd.pos.width = 50;
+ gcd[3].gd.flags = gg_enabled|gg_visible;
+ gcd[3].creator = GTextFieldCreate;
+
+ label[4].text = (unichar_t *) _("_Tag:");
+ label[4].text_is_1byte = true;
+ label[4].text_in_resource = true;
+ gcd[4].gd.label = &label[4];
+ gcd[4].gd.pos.x = 5; gcd[4].gd.pos.y = gcd[3].gd.pos.y+26;
+ gcd[4].gd.flags = gg_enabled|gg_visible;
+ gcd[4].creator = GLabelCreate;
+
+ ubuf3[0] = temp->otf_tag>>24; ubuf3[1] = (temp->otf_tag>>16)&0xff; ubuf3[2] = (temp->otf_tag>>8)&0xff; ubuf3[3] = temp->otf_tag&0xff; ubuf3[4] = 0;
+ label[5].text = ubuf3;
+ gcd[5].gd.label = &label[5];
+ gcd[5].gd.pos.x = gcd[3].gd.pos.x; gcd[5].gd.pos.y = gcd[4].gd.pos.y-4; gcd[5].gd.pos.width = 50;
+ gcd[5].gd.flags = gg_enabled|gg_visible;
+ /*gcd[5].gd.u.list = tags;*/
+ gcd[5].creator = GTextFieldCreate;
+
+ gcd[6].gd.pos.x = 13-3; gcd[6].gd.pos.y = gcd[5].gd.pos.y+30;
+ gcd[6].gd.pos.width = -1; gcd[6].gd.pos.height = 0;
+ gcd[6].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[6].text = (unichar_t *) _("_OK");
+ label[6].text_is_1byte = true;
+ label[6].text_in_resource = true;
+ gcd[6].gd.label = &label[6];
+ /*gcd[6].gd.handle_controlevent = Prefs_Ok;*/
+ gcd[6].creator = GButtonCreate;
+
+ gcd[7].gd.pos.x = -13; gcd[7].gd.pos.y = gcd[7-1].gd.pos.y+3;
+ gcd[7].gd.pos.width = -1; gcd[7].gd.pos.height = 0;
+ gcd[7].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[7].text = (unichar_t *) _("_Cancel");
+ label[7].text_is_1byte = true;
+ label[7].text_in_resource = true;
+ gcd[7].gd.label = &label[7];
+ gcd[7].creator = GButtonCreate;
+
+ GGadgetsCreate(gw,gcd);
+ sd.feature = gcd[1].ret;
+ sd.set_code = gcd[3].ret;
+ sd.otf = gcd[5].ret;
+ sd.ok = gcd[6].ret;
+ sd.cancel = gcd[7].ret;
+
+ ti = GGadgetGetList(flist,&len);
+ GGadgetSetList(sd.feature,ti,true);
+ for ( i=0; i<len; ++i ) {
+ int val = u_strtol(ti[i]->text,NULL,10);
+ if ( val==temp->mac_feature_type ) {
+ GGadgetSetTitle(sd.feature,ti[i]->text);
+ break;
+ }
+ }
+
+ GDrawSetVisible(gw,true);
+ GWidgetIndicateFocusGadget(gcd[1].ret);
+ while ( !sd.done )
+ GDrawProcessOneEvent(NULL);
+ GDrawDestroyWindow(gw);
+
+return( sd.ret );
+}
+
+static void ChangeSetting(GGadget *list,int index,GGadget *flist) {
+ struct macsettingname temp;
+ int32 len;
+ GTextInfo **ti = GGadgetGetList(list,&len);
+ char *str;
+ unichar_t *ustr;
+
+ str = cu_copy(ti[index]->text);
+ ParseMacMapping(str,&temp);
+ free(str);
+ if ( (ustr=AskSetting(&temp,list,index,flist))==NULL )
+return;
+ GListReplaceStr(list,index,ustr,NULL);
+}
+
+static int Pref_NewMapping(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GWindow gw = GGadgetGetWindow(g);
+ GGadget *list = GWidgetGetControl(gw,CID_Mapping);
+ GGadget *flist = GWidgetGetControl(GDrawGetParentWindow(gw),CID_Features);
+ struct macsettingname temp;
+ unichar_t *str;
+
+ memset(&temp,0,sizeof(temp));
+ temp.mac_feature_type = -1;
+ if ( (str=AskSetting(&temp,list,-1,flist))==NULL )
+return( true );
+ GListAddStr(list,str,NULL);
+ /*free(str);*/
+ }
+return( true );
+}
+
+static int Pref_DelMapping(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GWindow gw = GGadgetGetWindow(g);
+ GListDelSelected(GWidgetGetControl(gw,CID_Mapping));
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_MappingDel),false);
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_MappingEdit),false);
+ }
+return( true );
+}
+
+static int Pref_EditMapping(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GWindow gw = GDrawGetParentWindow(GGadgetGetWindow(g));
+ GGadget *list = GWidgetGetControl(gw,CID_Mapping);
+ GGadget *flist = GWidgetGetControl(gw,CID_Features);
+ ChangeSetting(list,GGadgetGetFirstListSelectedItem(list),flist);
+ }
+return( true );
+}
+
+static int Pref_MappingSel(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
+ int32 len;
+ GTextInfo **ti = GGadgetGetList(g,&len);
+ GWindow gw = GGadgetGetWindow(g);
+ int i, sel_cnt=0;
+ for ( i=0; i<len; ++i )
+ if ( ti[i]->selected ) ++sel_cnt;
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_MappingDel),sel_cnt!=0);
+ GGadgetSetEnabled(GWidgetGetControl(gw,CID_MappingEdit),sel_cnt==1);
+ } else if ( e->type==et_controlevent && e->u.control.subtype == et_listdoubleclick ) {
+ GGadget *flist = GWidgetGetControl( GDrawGetParentWindow(GGadgetGetWindow(g)),CID_Features);
+ ChangeSetting(g,e->u.control.u.list.changed_index!=-1?e->u.control.u.list.changed_index:
+ GGadgetGetFirstListSelectedItem(g),flist);
+ }
+return( true );
+}
+
+static int Pref_DefaultMapping(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ GGadget *list = GWidgetGetControl(GGadgetGetWindow(g),CID_Mapping);
+ GTextInfo *ti, **arr;
+ uint16 cnt;
+
+ ti = Pref_MappingList(false);
+ arr = GTextInfoArrayFromList(ti,&cnt);
+ GGadgetSetList(list,arr,false);
+ GTextInfoListFree(ti);
+ }
+return( true );
+}
+
+static int Prefs_Ok(GGadget *g, GEvent *e) {
+ int i, j, mi;
+ int err=0, enc;
+ struct pref_data *p;
+ GWindow gw;
+ const unichar_t *ret;
+ const unichar_t *names[SCRIPT_MENU_MAX], *scripts[SCRIPT_MENU_MAX];
+ struct prefs_list *pl;
+ GTextInfo **list;
+ int32 len;
+ int maxl, t;
+ char *str;
+
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ gw = GGadgetGetWindow(g);
+ p = GDrawGetUserData(gw);
+ for ( i=0; i<SCRIPT_MENU_MAX; ++i ) {
+ names[i] = _GGadgetGetTitle(GWidgetGetControl(gw,CID_ScriptMNameBase+i));
+ scripts[i] = _GGadgetGetTitle(GWidgetGetControl(gw,CID_ScriptMFileBase+i));
+ if ( *names[i]=='\0' ) names[i] = NULL;
+ if ( *scripts[i]=='\0' ) scripts[i] = NULL;
+ if ( scripts[i]==NULL && names[i]!=NULL ) {
+ gwwv_post_error(_("Menu name with no associated script"),_("Menu name with no associated script"));
+return( true );
+ } else if ( scripts[i]!=NULL && names[i]==NULL ) {
+ gwwv_post_error(_("Script with no associated menu name"),_("Script with no associated menu name"));
+return( true );
+ }
+ }
+ for ( i=mi=0; i<SCRIPT_MENU_MAX; ++i ) {
+ if ( names[i]!=NULL ) {
+ names[mi] = names[i];
+ scripts[mi] = scripts[i];
+ ++mi;
+ }
+ }
+ for ( j=0; visible_prefs_list[j].tab_name!=0; ++j ) for ( i=0; visible_prefs_list[j].pl[i].name!=NULL; ++i ) {
+ pl = &visible_prefs_list[j].pl[i];
+ /* before assigning values, check for any errors */
+ /* if any errors, then NO values should be assigned, in case they cancel */
+ if ( pl->dontdisplay )
+ continue;
+ if ( pl->type==pr_int ) {
+ GetInt8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err);
+ } else if ( pl->type==pr_int ) {
+ GetReal8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err);
+ }
+ }
+ if ( err )
+return( true );
+
+ for ( j=0; visible_prefs_list[j].tab_name!=0; ++j ) for ( i=0; visible_prefs_list[j].pl[i].name!=NULL; ++i ) {
+ pl = &visible_prefs_list[j].pl[i];
+ if ( pl->dontdisplay )
+ continue;
+ switch( pl->type ) {
+ case pr_int:
+ *((int *) (pl->val)) = GetInt8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err);
+ break;
+ case pr_bool:
+ *((int *) (pl->val)) = GGadgetIsChecked(GWidgetGetControl(gw,j*CID_PrefsOffset+CID_PrefsBase+i));
+ break;
+ case pr_real:
+ *((float *) (pl->val)) = GetReal8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err);
+ break;
+ case pr_encoding:
+ { Encoding *e;
+ e = ParseEncodingNameFromList(GWidgetGetControl(gw,j*CID_PrefsOffset+CID_PrefsBase+i));
+ if ( e!=NULL )
+ *((Encoding **) (pl->val)) = e;
+ enc = 1; /* So gcc doesn't complain about unused. It is unused, but why add the ifdef and make the code even messier? Sigh. icc complains anyway */
+ }
+ break;
+ case pr_namelist:
+ { NameList *nl;
+ GTextInfo *ti = GGadgetGetListItemSelected(GWidgetGetControl(gw,j*CID_PrefsOffset+CID_PrefsBase+i));
+ if ( ti!=NULL ) {
+ char *name = u2utf8_copy(ti->text);
+ nl = NameListByName(name);
+ free(name);
+ if ( nl!=NULL && nl->uses_unicode && !allow_utf8_glyphnames)
+ gwwv_post_error(_("Namelist contains non-ASCII names"),_("Glyph names should be limited to characters in the ASCII character set, but there are names in this namelist which use characters outside that range."));
+ else if ( nl!=NULL )
+ *((NameList **) (pl->val)) = nl;
+ }
+ }
+ break;
+ case pr_string: case pr_file:
+ ret = _GGadgetGetTitle(GWidgetGetControl(gw,j*CID_PrefsOffset+CID_PrefsBase+i));
+ if ( pl->val!=NULL ) {
+ free( *((char **) (pl->val)) );
+ *((char **) (pl->val)) = NULL;
+ if ( ret!=NULL && *ret!='\0' )
+ *((char **) (pl->val)) = /* u2def_*/ cu_copy(ret);
+ } else {
+ char *cret = cu_copy(ret);
+ (pl->set)(cret);
+ free(cret);
+ }
+ break;
+ }
+ }
+ for ( i=0; i<SCRIPT_MENU_MAX; ++i ) {
+ free(script_menu_names[i]); script_menu_names[i] = NULL;
+ free(script_filenames[i]); script_filenames[i] = NULL;
+ }
+ for ( i=0; i<mi; ++i ) {
+ script_menu_names[i] = u_copy(names[i]);
+ script_filenames[i] = u2def_copy(scripts[i]);
+ }
+
+ list = GGadgetGetList(GWidgetGetControl(gw,CID_Mapping),&len);
+ UserSettingsFree();
+ user_macfeat_otftag = galloc((len+1)*sizeof(struct macsettingname));
+ user_macfeat_otftag[len].otf_tag = 0;
+ maxl = 0;
+ for ( i=0; i<len; ++i ) {
+ t = u_strlen(list[i]->text);
+ if ( t>maxl ) maxl = t;
+ }
+ str = galloc(maxl+3);
+ for ( i=0; i<len; ++i ) {
+ u2encoding_strncpy(str,list[i]->text,maxl+1,e_mac);
+ ParseMacMapping(str,&user_macfeat_otftag[i]);
+ }
+ free(str);
+
+ Prefs_ReplaceMacFeatures(GWidgetGetControl(gw,CID_Features));
+
+ if ( xuid!=NULL ) {
+ char *pt;
+ for ( pt=xuid; *pt==' ' ; ++pt );
+ if ( *pt=='[' ) { /* People who know PS well, might want to put brackets arround the xuid base array, but I don't want them */
+ pt = copy(pt+1);
+ free( xuid );
+ xuid = pt;
+ }
+ for ( pt=xuid+strlen(xuid)-1; pt>xuid && *pt==' '; --pt );
+ if ( pt >= xuid && *pt==']' ) *pt = '\0';
+ }
+
+ p->done = true;
+ SavePrefs();
+ if ( maxundoes==0 ) { FontView *fv;
+ for ( fv=fv_list ; fv!=NULL; fv=fv->next )
+ SFRemoveUndoes(fv->sf,NULL,NULL);
+ }
+ if ( othersubrsfile!=NULL && ReadOtherSubrsFile(othersubrsfile)<=0 )
+ fprintf( stderr, "Failed to read OtherSubrs from %s\n", othersubrsfile );
+ }
+return( true );
+}
+
+static int Prefs_Cancel(GGadget *g, GEvent *e) {
+ if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
+ struct pref_data *p = GDrawGetUserData(GGadgetGetWindow(g));
+ MacFeatListFree(GGadgetGetUserData((GWidgetGetControl(
+ GGadgetGetWindow(g),CID_Features))));
+ p->done = true;
+ }
+return( true );
+}
+
+static int e_h(GWindow gw, GEvent *event) {
+ if ( event->type==et_close ) {
+ struct pref_data *p = GDrawGetUserData(gw);
+ p->done = true;
+ MacFeatListFree(GGadgetGetUserData((GWidgetGetControl(gw,CID_Features))));
+ } else if ( event->type==et_char ) {
+ if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
+ help("prefs.html");
+return( true );
+ }
+return( false );
+ }
+return( true );
+}
+
+static void PrefsInit(void) {
+ static int done = false;
+ int i;
+
+ if ( done )
+return;
+ done = true;
+ for ( i=0; visible_prefs_list[i].tab_name!=NULL; ++i )
+ visible_prefs_list[i].tab_name = _(visible_prefs_list[i].tab_name);
+}
+
+void DoPrefs(void) {
+ GRect pos;
+ GWindow gw;
+ GWindowAttrs wattrs;
+ GGadgetCreateData *pgcd, gcd[5], sgcd[45], mgcd[3], mfgcd[9], msgcd[9];
+ GGadgetCreateData mfboxes[3], *mfarray[14];
+ GGadgetCreateData mpboxes[3], *mparray[14];
+ GGadgetCreateData sboxes[2], *sarray[50];
+ GGadgetCreateData mboxes[3], *varray[5], *harray[8];
+ GTextInfo *plabel, **list, label[5], slabel[45], *plabels[TOPICS+5], mflabels[9], mslabels[9];
+ GTabInfo aspects[TOPICS+5], subaspects[3];
+ GGadgetCreateData **hvarray, boxes[2*TOPICS];
+ struct pref_data p;
+ int i, gc, sgc, j, k, line, line_max, y, y2, ii, si;
+ int32 llen;
+ char buf[20];
+ int gcnt[20];
+ static unichar_t nullstr[] = { 0 };
+ struct prefs_list *pl;
+ char *tempstr;
+ static unichar_t monospace[] = { 'c','o','u','r','i','e','r',',','m', 'o', 'n', 'o', 's', 'p', 'a', 'c', 'e',',','c','a','s','l','o','n',',','c','l','e','a','r','l','y','u',',','u','n','i','f','o','n','t', '\0' };
+ FontRequest rq;
+ GFont *font;
+
+ PrefsInit();
+
+ MfArgsInit();
+ for ( k=line_max=0; visible_prefs_list[k].tab_name!=0; ++k ) {
+ for ( i=line=gcnt[k]=0; visible_prefs_list[k].pl[i].name!=NULL; ++i ) {
+ if ( visible_prefs_list[k].pl[i].dontdisplay )
+ continue;
+ gcnt[k] += 2;
+ if ( visible_prefs_list[k].pl[i].type==pr_bool ) ++gcnt[k];
+ else if ( visible_prefs_list[k].pl[i].type==pr_file ) ++gcnt[k];
+ ++line;
+ }
+ if ( visible_prefs_list[k].pl == args_list ) {
+ gcnt[k] += 6;
+ line += 6;
+ }
+ if ( line>line_max ) line_max = line;
+ }
+
+ memset(&p,'\0',sizeof(p));
+ memset(&wattrs,0,sizeof(wattrs));
+ wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.restrict_input_to_me = 1;
+ wattrs.undercursor = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = _("Preferences...");
+ pos.x = pos.y = 0;
+ pos.width = GGadgetScale(GDrawPointsToPixels(NULL,290));
+ pos.height = GDrawPointsToPixels(NULL,line_max*26+69);
+ gw = GDrawCreateTopWindow(NULL,&pos,e_h,&p,&wattrs);
+
+ memset(sgcd,0,sizeof(sgcd));
+ memset(slabel,0,sizeof(slabel));
+ memset(&mfgcd,0,sizeof(mfgcd));
+ memset(&msgcd,0,sizeof(msgcd));
+ memset(&mflabels,0,sizeof(mflabels));
+ memset(&mslabels,0,sizeof(mslabels));
+ memset(&mfboxes,0,sizeof(mfboxes));
+ memset(&mpboxes,0,sizeof(mpboxes));
+ memset(&sboxes,0,sizeof(sboxes));
+ memset(&boxes,0,sizeof(boxes));
+
+ GCDFillMacFeat(mfgcd,mflabels,250,default_mac_feature_map, true, mfboxes, mfarray);
+
+ sgc = 0;
+
+ msgcd[sgc].gd.pos.x = 6; msgcd[sgc].gd.pos.y = 6;
+ msgcd[sgc].gd.pos.width = 250; msgcd[sgc].gd.pos.height = 16*12+10;
+ msgcd[sgc].gd.flags = gg_visible | gg_enabled | gg_list_alphabetic | gg_list_multiplesel;
+ msgcd[sgc].gd.cid = CID_Mapping;
+ msgcd[sgc].gd.u.list = Pref_MappingList(true);
+ msgcd[sgc].gd.handle_controlevent = Pref_MappingSel;
+ msgcd[sgc++].creator = GListCreate;
+ mparray[0] = &msgcd[sgc-1];
+
+ msgcd[sgc].gd.pos.x = 6; msgcd[sgc].gd.pos.y = msgcd[sgc-1].gd.pos.y+msgcd[sgc-1].gd.pos.height+10;
+ msgcd[sgc].gd.flags = gg_visible | gg_enabled;
+ mslabels[sgc].text = (unichar_t *) S_("MacMap|_New...");
+ mslabels[sgc].text_is_1byte = true;
+ mslabels[sgc].text_in_resource = true;
+ msgcd[sgc].gd.label = &mslabels[sgc];
+ msgcd[sgc].gd.handle_controlevent = Pref_NewMapping;
+ msgcd[sgc++].creator = GButtonCreate;
+ mparray[4] = GCD_Glue; mparray[5] = &msgcd[sgc-1];
+
+ msgcd[sgc].gd.pos.x = msgcd[sgc-1].gd.pos.x+10+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor);
+ msgcd[sgc].gd.pos.y = msgcd[sgc-1].gd.pos.y;
+ msgcd[sgc].gd.flags = gg_visible ;
+ mslabels[sgc].text = (unichar_t *) _("_Delete");
+ mslabels[sgc].text_is_1byte = true;
+ mslabels[sgc].text_in_resource = true;
+ msgcd[sgc].gd.label = &mslabels[sgc];
+ msgcd[sgc].gd.cid = CID_MappingDel;
+ msgcd[sgc].gd.handle_controlevent = Pref_DelMapping;
+ msgcd[sgc++].creator = GButtonCreate;
+ mparray[5] = GCD_Glue; mparray[6] = &msgcd[sgc-1];
+
+ msgcd[sgc].gd.pos.x = msgcd[sgc-1].gd.pos.x+10+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor);
+ msgcd[sgc].gd.pos.y = msgcd[sgc-1].gd.pos.y;
+ msgcd[sgc].gd.flags = gg_visible ;
+ mslabels[sgc].text = (unichar_t *) _("_Edit...");
+ mslabels[sgc].text_is_1byte = true;
+ mslabels[sgc].text_in_resource = true;
+ msgcd[sgc].gd.label = &mslabels[sgc];
+ msgcd[sgc].gd.cid = CID_MappingEdit;
+ msgcd[sgc].gd.handle_controlevent = Pref_EditMapping;
+ msgcd[sgc++].creator = GButtonCreate;
+ mparray[7] = GCD_Glue; mparray[8] = &msgcd[sgc-1];
+
+ msgcd[sgc].gd.pos.x = msgcd[sgc-1].gd.pos.x+10+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor);
+ msgcd[sgc].gd.pos.y = msgcd[sgc-1].gd.pos.y;
+ msgcd[sgc].gd.flags = gg_visible | gg_enabled;
+ mslabels[sgc].text = (unichar_t *) S_("MacMapping|Default");
+ mslabels[sgc].text_is_1byte = true;
+ mslabels[sgc].text_in_resource = true;
+ msgcd[sgc].gd.label = &mslabels[sgc];
+ msgcd[sgc].gd.handle_controlevent = Pref_DefaultMapping;
+ msgcd[sgc++].creator = GButtonCreate;
+ mparray[9] = GCD_Glue; mparray[10] = &msgcd[sgc-1];
+ mparray[11] = GCD_Glue; mparray[12] = NULL;
+
+ mpboxes[2].gd.flags = gg_enabled|gg_visible;
+ mpboxes[2].gd.u.boxelements = mparray+4;
+ mpboxes[2].creator = GHBoxCreate;
+ mparray[1] = GCD_Glue;
+ mparray[2] = &mpboxes[2];
+ mparray[3] = NULL;
+
+ mpboxes[0].gd.flags = gg_enabled|gg_visible;
+ mpboxes[0].gd.u.boxelements = mparray;
+ mpboxes[0].creator = GVBoxCreate;
+
+ sgc = 0;
+ y2=5;
+ si = 0;
+
+ slabel[sgc].text = (unichar_t *) _("Menu Name");
+ slabel[sgc].text_is_1byte = true;
+ sgcd[sgc].gd.label = &slabel[sgc];
+ sgcd[sgc].gd.popup_msg = (unichar_t *) _("You may create a script menu containing up to 10 frequently used scripts.\nEach entry in the menu needs both a name to display in the menu and\na script file to execute. The menu name may contain any unicode characters.\nThe button labeled \"...\" will allow you to browse for a script file.");
+ sgcd[sgc].gd.pos.x = 8;
+ sgcd[sgc].gd.pos.y = y2;
+ sgcd[sgc].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ sgcd[sgc++].creator = GLabelCreate;
+ sarray[si++] = &sgcd[sgc-1];
+
+ slabel[sgc].text = (unichar_t *) _("Script File");
+ slabel[sgc].text_is_1byte = true;
+ sgcd[sgc].gd.label = &slabel[sgc];
+ sgcd[sgc].gd.popup_msg = (unichar_t *) _("You may create a script menu containing up to 10 frequently used scripts\nEach entry in the menu needs both a name to display in the menu and\na script file to execute. The menu name may contain any unicode characters.\nThe button labeled \"...\" will allow you to browse for a script file.");
+ sgcd[sgc].gd.pos.x = 110;
+ sgcd[sgc].gd.pos.y = y2;
+ sgcd[sgc].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ sgcd[sgc++].creator = GLabelCreate;
+ sarray[si++] = &sgcd[sgc-1];
+ sarray[si++] = GCD_Glue;
+ sarray[si++] = NULL;
+
+ y2 += 14;
+
+ for ( i=0; i<SCRIPT_MENU_MAX; ++i ) {
+ sgcd[sgc].gd.pos.x = 8; sgcd[sgc].gd.pos.y = y2;
+ sgcd[sgc].gd.flags = gg_visible | gg_enabled | gg_text_xim;
+ slabel[sgc].text = script_menu_names[i]==NULL?nullstr:script_menu_names[i];
+ sgcd[sgc].gd.label = &slabel[sgc];
+ sgcd[sgc].gd.cid = i+CID_ScriptMNameBase;
+ sgcd[sgc++].creator = GTextFieldCreate;
+ sarray[si++] = &sgcd[sgc-1];
+
+ sgcd[sgc].gd.pos.x = 110; sgcd[sgc].gd.pos.y = y2;
+ sgcd[sgc].gd.flags = gg_visible | gg_enabled;
+ slabel[sgc].text = (unichar_t *) (script_filenames[i]==NULL?"":script_filenames[i]);
+ slabel[sgc].text_is_1byte = true;
+ sgcd[sgc].gd.label = &slabel[sgc];
+ sgcd[sgc].gd.cid = i+CID_ScriptMFileBase;
+ sgcd[sgc++].creator = GTextFieldCreate;
+ sarray[si++] = &sgcd[sgc-1];
+
+ sgcd[sgc].gd.pos.x = 210; sgcd[sgc].gd.pos.y = y2;
+ sgcd[sgc].gd.flags = gg_visible | gg_enabled;
+ slabel[sgc].text = (unichar_t *) _("...");
+ slabel[sgc].text_is_1byte = true;
+ sgcd[sgc].gd.label = &slabel[sgc];
+ sgcd[sgc].gd.cid = i+CID_ScriptMBrowseBase;
+ sgcd[sgc].gd.handle_controlevent = Prefs_ScriptBrowse;
+ sgcd[sgc++].creator = GButtonCreate;
+ sarray[si++] = &sgcd[sgc-1];
+ sarray[si++] = NULL;
+
+ y2 += 26;
+ }
+ sarray[si++] = GCD_Glue; sarray[si++] = GCD_Glue; sarray[si++] = GCD_Glue;
+ sarray[si++] = NULL;
+ sarray[si++] = NULL;
+
+ sboxes[0].gd.flags = gg_enabled|gg_visible;
+ sboxes[0].gd.u.boxelements = sarray;
+ sboxes[0].creator = GHVBoxCreate;
+
+ memset(&mgcd,0,sizeof(mgcd));
+ memset(&mgcd,0,sizeof(mgcd));
+ memset(&subaspects,'\0',sizeof(subaspects));
+ memset(&label,0,sizeof(label));
+ memset(&gcd,0,sizeof(gcd));
+ memset(&aspects,'\0',sizeof(aspects));
+ aspects[0].selected = true;
+
+ for ( k=0; visible_prefs_list[k].tab_name!=0; ++k ) {
+ pgcd = gcalloc(gcnt[k]+4,sizeof(GGadgetCreateData));
+ plabel = gcalloc(gcnt[k]+4,sizeof(GTextInfo));
+ hvarray = gcalloc((gcnt[k]+6)*5+2,sizeof(GGadgetCreateData *));
+
+ aspects[k].text = (unichar_t *) visible_prefs_list[k].tab_name;
+ aspects[k].text_is_1byte = true;
+ aspects[k].gcd = &boxes[2*k];
+ aspects[k].nesting = visible_prefs_list[k].nest;
+ plabels[k] = plabel;
+
+ gc = si = 0;
+ for ( i=line=0, y=5; visible_prefs_list[k].pl[i].name!=NULL; ++i ) {
+ pl = &visible_prefs_list[k].pl[i];
+ if ( pl->dontdisplay )
+ continue;
+ plabel[gc].text = (unichar_t *) _(pl->name);
+ plabel[gc].text_is_1byte = true;
+ pgcd[gc].gd.label = &plabel[gc];
+ pgcd[gc].gd.mnemonic = '\0';
+ pgcd[gc].gd.popup_msg = (unichar_t *) _(pl->popup);
+ pgcd[gc].gd.pos.x = 8;
+ pgcd[gc].gd.pos.y = y + 6;
+ pgcd[gc].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ pgcd[gc++].creator = GLabelCreate;
+ hvarray[si++] = &pgcd[gc-1];
+
+ plabel[gc].text_is_1byte = true;
+ pgcd[gc].gd.label = &plabel[gc];
+ pgcd[gc].gd.mnemonic = '\0';
+ pgcd[gc].gd.popup_msg = (unichar_t *) _(pl->popup);
+ pgcd[gc].gd.pos.x = 110;
+ pgcd[gc].gd.pos.y = y;
+ pgcd[gc].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
+ pgcd[gc].data = pl;
+ pgcd[gc].gd.cid = k*CID_PrefsOffset+CID_PrefsBase+i;
+ switch ( pl->type ) {
+ case pr_bool:
+ plabel[gc].text = (unichar_t *) _("On");
+ pgcd[gc].gd.pos.y += 3;
+ pgcd[gc++].creator = GRadioCreate;
+ hvarray[si++] = &pgcd[gc-1];
+ pgcd[gc] = pgcd[gc-1];
+ pgcd[gc].gd.pos.x += 50;
+ pgcd[gc].gd.cid = 0;
+ pgcd[gc].gd.label = &plabel[gc];
+ plabel[gc].text = (unichar_t *) _("Off");
+ plabel[gc].text_is_1byte = true;
+ hvarray[si++] = &pgcd[gc];
+ hvarray[si++] = GCD_Glue;
+ if ( *((int *) pl->val))
+ pgcd[gc-1].gd.flags |= gg_cb_on;
+ else
+ pgcd[gc].gd.flags |= gg_cb_on;
+ ++gc;
+ y += 22;
+ break;
+ case pr_int:
+ sprintf(buf,"%d", *((int *) pl->val));
+ plabel[gc].text = (unichar_t *) copy( buf );
+ pgcd[gc++].creator = GTextFieldCreate;
+ hvarray[si++] = &pgcd[gc-1];
+ hvarray[si++] = GCD_Glue; hvarray[si++] = GCD_Glue;
+ y += 26;
+ break;
+ case pr_real:
+ sprintf(buf,"%g", *((float *) pl->val));
+ plabel[gc].text = (unichar_t *) copy( buf );
+ pgcd[gc++].creator = GTextFieldCreate;
+ hvarray[si++] = &pgcd[gc-1];
+ hvarray[si++] = GCD_Glue; hvarray[si++] = GCD_Glue;
+ y += 26;
+ break;
+ case pr_encoding:
+ pgcd[gc].gd.u.list = GetEncodingTypes();
+ pgcd[gc].gd.label = EncodingTypesFindEnc(pgcd[gc].gd.u.list,
+ *(Encoding **) pl->val);
+ for ( ii=0; pgcd[gc].gd.u.list[ii].text!=NULL ||pgcd[gc].gd.u.list[ii].line; ++ii )
+ if ( pgcd[gc].gd.u.list[ii].userdata!=NULL &&
+ (strcmp(pgcd[gc].gd.u.list[ii].userdata,"Compacted")==0 ||
+ strcmp(pgcd[gc].gd.u.list[ii].userdata,"Original")==0 ))
+ pgcd[gc].gd.u.list[ii].disabled = true;
+ pgcd[gc].creator = GListFieldCreate;
+ pgcd[gc].gd.pos.width = 160;
+ if ( pgcd[gc].gd.label==NULL ) pgcd[gc].gd.label = &encodingtypes[0];
+ ++gc;
+ hvarray[si++] = &pgcd[gc-1];
+ hvarray[si++] = GCD_ColSpan; hvarray[si++] = GCD_ColSpan;
+ y += 28;
+ break;
+ case pr_namelist:
+ { char **nlnames = AllNamelistNames();
+ int cnt;
+ GTextInfo *namelistnames;
+ for ( cnt=0; nlnames[cnt]!=NULL; ++cnt);
+ namelistnames = gcalloc(cnt+1,sizeof(GTextInfo));
+ for ( cnt=0; nlnames[cnt]!=NULL; ++cnt) {
+ namelistnames[cnt].text = (unichar_t *) nlnames[cnt];
+ namelistnames[cnt].text_is_1byte = true;
+ if ( strcmp(_((*(NameList **) (pl->val))->title),nlnames[cnt])==0 ) {
+ namelistnames[cnt].selected = true;
+ pgcd[gc].gd.label = &namelistnames[cnt];
+ }
+ }
+ pgcd[gc].gd.u.list = namelistnames;
+ pgcd[gc].creator = GListButtonCreate;
+ pgcd[gc].gd.pos.width = 160;
+ ++gc;
+ hvarray[si++] = &pgcd[gc-1];
+ hvarray[si++] = GCD_ColSpan; hvarray[si++] = GCD_ColSpan;
+ y += 28;
+ } break;
+ case pr_string: case pr_file:
+ if ( pl->set==SetAutoTraceArgs || ((char **) pl->val)==&mf_args )
+ pgcd[gc].gd.pos.width = 160;
+ if ( pl->val!=NULL )
+ tempstr = *((char **) (pl->val));
+ else
+ tempstr = (char *) ((pl->get)());
+ if ( tempstr!=NULL )
+ plabel[gc].text = /* def2u_*/ uc_copy( tempstr );
+ else if ( ((char **) pl->val)==&BDFFoundry )
+ plabel[gc].text = /* def2u_*/ uc_copy( "FontForge" );
+ else
+ plabel[gc].text = /* def2u_*/ uc_copy( "" );
+ plabel[gc].text_is_1byte = false;
+ pgcd[gc++].creator = GTextFieldCreate;
+ hvarray[si++] = &pgcd[gc-1];
+ if ( pl->type==pr_file ) {
+ pgcd[gc] = pgcd[gc-1];
+ pgcd[gc-1].gd.pos.width = 140;
+ hvarray[si++] = GCD_ColSpan;
+ pgcd[gc].gd.pos.x += 145;
+ pgcd[gc].gd.cid += CID_PrefsBrowseOffset;
+ pgcd[gc].gd.label = &plabel[gc];
+ plabel[gc].text = (unichar_t *) "...";
+ plabel[gc].text_is_1byte = true;
+ pgcd[gc].gd.handle_controlevent = Prefs_BrowseFile;
+ pgcd[gc++].creator = GButtonCreate;
+ hvarray[si++] = &pgcd[gc-1];
+ } else if ( pl->set==SetAutoTraceArgs || ((char **) pl->val)==&mf_args ) {
+ hvarray[si++] = GCD_ColSpan;
+ hvarray[si++] = GCD_Glue;
+ } else {
+ hvarray[si++] = GCD_Glue;
+ hvarray[si++] = GCD_Glue;
+ }
+ y += 26;
+ if ( pl->val==NULL )
+ free(tempstr);
+ break;
+ }
+ ++line;
+ hvarray[si++] = NULL;
+ }
+ if ( visible_prefs_list[k].pl == args_list ) {
+ static char *text[] = {
+/* GT: See the long comment at "Property|New" */
+/* GT: This and the next few strings show a limitation of my widget set which */
+/* GT: cannot handle multi-line text labels. These strings should be concatenated */
+/* GT: (after striping off "Prefs|App|") together, translated, and then broken up */
+/* GT: to fit the dialog. There is an extra blank line, not used in English, */
+/* GT: into which your text may extend if needed. */
+ N_("Prefs|App|Normally FontForge will find applications by searching for"),
+ N_("Prefs|App|them in your PATH environment variable, if you want"),
+ N_("Prefs|App|to alter that behavior you may set an environment"),
+ N_("Prefs|App|variable giving the full path spec of the application."),
+ N_("Prefs|App|FontForge recognizes BROWSER, MF and AUTOTRACE."),
+ N_("Prefs|App| "), /* A blank line */
+ NULL };
+ y += 8;
+ for ( i=0; text[i]!=0; ++i ) {
+ plabel[gc].text = (unichar_t *) S_(text[i]);
+ plabel[gc].text_is_1byte = true;
+ pgcd[gc].gd.label = &plabel[gc];
+ pgcd[gc].gd.pos.x = 8;
+ pgcd[gc].gd.pos.y = y;
+ pgcd[gc].gd.flags = gg_visible | gg_enabled;
+ pgcd[gc++].creator = GLabelCreate;
+ hvarray[si++] = &pgcd[gc-1];
+ hvarray[si++] = GCD_ColSpan; hvarray[si++] = GCD_ColSpan;
+ hvarray[si++] = NULL;
+ y += 12;
+ }
+ }
+ if ( y>y2 ) y2 = y;
+ hvarray[si++] = GCD_Glue; hvarray[si++] = GCD_Glue;
+ hvarray[si++] = GCD_Glue; hvarray[si++] = GCD_Glue;
+ hvarray[si++] = NULL;
+ hvarray[si++] = NULL;
+ boxes[2*k].gd.flags = gg_enabled|gg_visible;
+ boxes[2*k].gd.u.boxelements = hvarray;
+ boxes[2*k].creator = GHVBoxCreate;
+ }
+
+ aspects[k].text = (unichar_t *) _("Script Menu");
+ aspects[k].text_is_1byte = true;
+ aspects[k++].gcd = sboxes;
+
+ subaspects[0].text = (unichar_t *) _("Features");
+ subaspects[0].text_is_1byte = true;
+ subaspects[0].gcd = mfboxes;
+
+ subaspects[1].text = (unichar_t *) _("Mapping");
+ subaspects[1].text_is_1byte = true;
+ subaspects[1].gcd = mpboxes;
+
+ mgcd[0].gd.pos.x = 4; gcd[0].gd.pos.y = 6;
+ mgcd[0].gd.pos.width = GDrawPixelsToPoints(NULL,pos.width)-20;
+ mgcd[0].gd.pos.height = y2;
+ mgcd[0].gd.u.tabs = subaspects;
+ mgcd[0].gd.flags = gg_visible | gg_enabled;
+ mgcd[0].creator = GTabSetCreate;
+
+ aspects[k].text = (unichar_t *) _("Mac");
+ aspects[k].text_is_1byte = true;
+ aspects[k++].gcd = mgcd;
+
+ gc = 0;
+
+ gcd[gc].gd.pos.x = gcd[gc].gd.pos.y = 2;
+ gcd[gc].gd.pos.width = pos.width-4; gcd[gc].gd.pos.height = pos.height-2;
+ gcd[gc].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
+ gcd[gc++].creator = GGroupCreate;
+
+ gcd[gc].gd.pos.x = 4; gcd[gc].gd.pos.y = 6;
+ gcd[gc].gd.pos.width = GDrawPixelsToPoints(NULL,pos.width)-8;
+ gcd[gc].gd.pos.height = y2+20+18+4;
+ gcd[gc].gd.u.tabs = aspects;
+ gcd[gc].gd.flags = gg_visible | gg_enabled | gg_tabset_vert;
+ gcd[gc++].creator = GTabSetCreate;
+ varray[0] = &gcd[gc-1]; varray[1] = NULL;
+
+ y = gcd[gc-1].gd.pos.y+gcd[gc-1].gd.pos.height;
+
+ gcd[gc].gd.pos.x = 30-3; gcd[gc].gd.pos.y = y+5-3;
+ gcd[gc].gd.pos.width = -1; gcd[gc].gd.pos.height = 0;
+ gcd[gc].gd.flags = gg_visible | gg_enabled | gg_but_default;
+ label[gc].text = (unichar_t *) _("_OK");
+ label[gc].text_is_1byte = true;
+ label[gc].text_in_resource = true;
+ gcd[gc].gd.mnemonic = 'O';
+ gcd[gc].gd.label = &label[gc];
+ gcd[gc].gd.handle_controlevent = Prefs_Ok;
+ gcd[gc++].creator = GButtonCreate;
+ harray[0] = GCD_Glue; harray[1] = &gcd[gc-1]; harray[2] = GCD_Glue; harray[3] = GCD_Glue;
+
+ gcd[gc].gd.pos.x = -30; gcd[gc].gd.pos.y = gcd[gc-1].gd.pos.y+3;
+ gcd[gc].gd.pos.width = -1; gcd[gc].gd.pos.height = 0;
+ gcd[gc].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
+ label[gc].text = (unichar_t *) _("_Cancel");
+ label[gc].text_is_1byte = true;
+ label[gc].text_in_resource = true;
+ gcd[gc].gd.label = &label[gc];
+ gcd[gc].gd.mnemonic = 'C';
+ gcd[gc].gd.handle_controlevent = Prefs_Cancel;
+ gcd[gc++].creator = GButtonCreate;
+ harray[4] = GCD_Glue; harray[5] = &gcd[gc-1]; harray[6] = GCD_Glue; harray[7] = NULL;
+
+ memset(mboxes,0,sizeof(mboxes));
+ mboxes[2].gd.flags = gg_enabled|gg_visible;
+ mboxes[2].gd.u.boxelements = harray;
+ mboxes[2].creator = GHBoxCreate;
+ varray[2] = &mboxes[2];
+ varray[3] = NULL;
+ varray[4] = NULL;
+
+ mboxes[0].gd.pos.x = mboxes[0].gd.pos.y = 2;
+ mboxes[0].gd.flags = gg_enabled|gg_visible;
+ mboxes[0].gd.u.boxelements = varray;
+ mboxes[0].creator = GHVGroupCreate;
+
+ y = GDrawPointsToPixels(NULL,y+37);
+ gcd[0].gd.pos.height = y-4;
+
+ GGadgetsCreate(gw,mboxes);
+ GTextInfoListFree(mfgcd[0].gd.u.list);
+ GTextInfoListFree(msgcd[0].gd.u.list);
+
+ GHVBoxSetExpandableRow(mboxes[0].ret,0);
+ GHVBoxSetExpandableCol(mboxes[2].ret,gb_expandgluesame);
+ GHVBoxSetExpandableRow(mfboxes[0].ret,0);
+ GHVBoxSetExpandableCol(mfboxes[2].ret,gb_expandgluesame);
+ GHVBoxSetExpandableRow(mpboxes[0].ret,0);
+ GHVBoxSetExpandableCol(mpboxes[2].ret,gb_expandgluesame);
+ GHVBoxSetExpandableRow(sboxes[0].ret,gb_expandglue);
+ for ( k=0; k<TOPICS; ++k )
+ GHVBoxSetExpandableRow(boxes[2*k].ret,gb_expandglue);
+
+ memset(&rq,0,sizeof(rq));
+ rq.family_name = monospace;
+ rq.point_size = 12;
+ rq.weight = 400;
+ font = GDrawInstanciateFont(GDrawGetDisplayOfWindow(gw),&rq);
+ GGadgetSetFont(mfgcd[0].ret,font);
+ GGadgetSetFont(msgcd[0].ret,font);
+ GHVBoxFitWindow(mboxes[0].ret);
+
+ for ( k=0; visible_prefs_list[k].tab_name!=0; ++k ) for ( gc=0,i=0; visible_prefs_list[k].pl[i].name!=NULL; ++i ) {
+ GGadgetCreateData *gcd = aspects[k].gcd[0].gd.u.boxelements[0];
+ pl = &visible_prefs_list[k].pl[i];
+ if ( pl->dontdisplay )
+ continue;
+ switch ( pl->type ) {
+ case pr_bool:
+ ++gc;
+ break;
+ case pr_encoding: {
+ GGadget *g = gcd[gc+1].ret;
+ list = GGadgetGetList(g,&llen);
+ for ( j=0; j<llen ; ++j ) {
+ if ( list[j]->text!=NULL &&
+ (void *) (intpt) ( *((int *) pl->val)) == list[j]->userdata )
+ list[j]->selected = true;
+ else
+ list[j]->selected = false;
+ }
+ if ( gcd[gc+1].gd.u.list!=encodingtypes )
+ GTextInfoListFree(gcd[gc+1].gd.u.list);
+ } break;
+ case pr_namelist:
+ free(gcd[gc+1].gd.u.list);
+ break;
+ case pr_string: case pr_file: case pr_int: case pr_real:
+ free(plabels[k][gc+1].text);
+ if ( pl->type==pr_file )
+ ++gc;
+ break;
+ }
+ gc += 2;
+ }
+
+ for ( k=0; visible_prefs_list[k].tab_name!=0; ++k ) {
+ free(aspects[k].gcd->gd.u.boxelements[0]);
+ free(aspects[k].gcd->gd.u.boxelements);
+ free(plabels[k]);
+ }
+
+ GWidgetHidePalettes();
+ GDrawSetVisible(gw,true);
+ while ( !p.done )
+ GDrawProcessOneEvent(NULL);
+ GDrawDestroyWindow(gw);
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+#ifndef LUA_FF_LIB
+void RecentFilesRemember(char *filename) {
+ int i;
+
+ for ( i=0; i<RECENT_MAX && RecentFiles[i]!=NULL; ++i )
+ if ( strcmp(RecentFiles[i],filename)==0 )
+ break;
+
+ if ( i<RECENT_MAX && RecentFiles[i]!=NULL ) {
+ if ( i!=0 ) {
+ filename = RecentFiles[i];
+ RecentFiles[i] = RecentFiles[0];
+ RecentFiles[0] = filename;
+ }
+ } else {
+ if ( RecentFiles[RECENT_MAX-1]!=NULL )
+ free( RecentFiles[RECENT_MAX-1]);
+ for ( i=RECENT_MAX-1; i>0; --i )
+ RecentFiles[i] = RecentFiles[i-1];
+ RecentFiles[0] = copy(filename);
+ }
+ SavePrefs();
+}
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/psfont.h b/Build/source/libs/luafontforge/fontforge/fontforge/psfont.h
new file mode 100644
index 00000000000..72c4efa4ef5
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/psfont.h
@@ -0,0 +1,191 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _PSFONT_H_
+#define _PSFONT_H_
+
+#include "splinefont.h"
+
+/* pfb section headers.
+ There seem to be three and a half of them. the first is a the start of the
+ file and is 6 bytes long "\200\001x\005\000\000", the second is right after
+ the newline after eexec and is 6 bytes "\200\002I\224\000\000", the third
+ is right before the zeros (after the encoded data) and is "\200\001\024\002\000\000"
+ the last is at the end of file and is only two bytes "\200\003"
+ I think that the \200 byte indicates a header, the next byte is 1 for ascii,
+ 2 for binary and 3 for eof, then next 4 bytes are the length (not present
+ for eof headers) with the first byte the least significant.
+*/
+
+struct charprocs {
+ int cnt, next;
+ char **keys;
+ SplineChar **values;
+};
+
+struct fontinfo {
+ char *familyname;
+ char *fullname;
+ char *notice;
+ char *weight;
+ char *version;
+ real italicangle;
+ unsigned int isfixedpitch:1;
+ real underlineposition;
+ real underlinethickness;
+ int em, ascent, descent; /* Generated by Fontographer (and us) */
+ int fstype; /* 2=>no embedding, 4=>print, 8=>edit */
+ /* Multiple master */
+ char *blenddesignpositions;
+ char *blenddesignmap;
+ char *blendaxistypes;
+};
+
+struct private {
+ struct psdict *private;
+ struct pschars *subrs; /* (optional, required if othersubrs is present) */
+ /* 0-2 part of Flex, 3 hint replacement, 4 and up for charstrings */
+ int leniv; /* (optional) must be 4 for old interpreters (number of rand chars at start of charstrings entries) */
+#if 0
+ int bluefuzz; /* (optional) (expand bluezones by this much, def=1) */
+ real bluescale; /* (optional) if the current pointsize in pixels is less than this value then do overshoot hinting */
+ int blueshift; /* (optional) */
+ real bluevalues[14]; /* <=7 pairs of integers, first less than second, (may be empty) */
+ /* first pair is baseline overshoots, other pairs above baseline */
+ real expansionfactor; /* (optional) only for languagegroup==1 (CJK) */
+ real familyblues[14]; /* (optional) bluevalues for family, can override local entry at small pointsizes */
+ real familyotherblues[10];/* (optional) otherblues for family */
+ unsigned int forcebold:1; /* (optional) */
+ int languagegroup; /* (optional) (0=>latin, greek, cyril, etc.), (1=>CJK)*/
+ int leniv; /* (optional) must be 4 for old interpreters (number of rand chars at start of charstrings entries) */
+ char *minfeature; /* obsolete, required must be {16 16} */
+ char *nd; /* "noaccess def" (may also be named "|-") */
+ char *np; /* "noaccess put" (may also be named "|") */
+ real otherblues[10]; /* (optional) descender blue zones */
+ struct pschars *othersubrs; /* (optional) shouldn't contain user defined subs */
+ int password; /* obsolete, required must be 5839 */
+ char *rd; /* "{string currentfile exch readstring pop}" (may also be named "-|") */
+ unsigned int rndstemup:1; /* (optional) obsolete, false if languagegroud==1 */
+ real stdhw[1]; /* (optional) dominant horizontal stem width */
+ real stdvw[1]; /* (optional) dominant vert */
+ real stemsnaph[12]; /* (optional) common h stem widths (at most 12, includes stdhw, sorted by increasing size) */
+ real stemsnapv[12]; /* (optional) common v stem widths*/
+ struct pschars *subrs; /* (optional, required if othersubrs is present) */
+ /* 0-2 part of Flex, 3 hint replacement, 4 and up for charstrings */
+ int uniqueid; /* (optional) seems same as fontdict entry. why's it here too? what of XUID? */
+/* CID entries */
+ int subrmapoffset; /* Offset to the start of this font's subr strings map */
+ int sdbytes; /* bytes in each pointer in the map */
+ int subrcnt; /* number of subroutines, number of pointers-1 in the map */
+#endif
+};
+
+typedef struct fontdict {
+ int fonttype;
+ real fontmatrix[6];
+ char *fontname; /* (optional) */
+ struct fontinfo *fontinfo;
+ int languagelevel; /* (optional) */
+ int wmode; /* (optional) chooses between alternate metric sets */
+/* non-type0 entries */
+ char *encoding[256];
+ real fontbb[4];
+ int uniqueid; /* (optional) open range between 4,000,000 and 4,999,999 */
+ int xuid[20]; /* (optional) */
+/* Type1 specific values */
+ int painttype; /* 0 (filled) 2 (stroked) */
+ real strokewidth; /* (optional) only if painttype==2 */
+ struct psdict *metrics; /* (optional) */
+ struct psdict *metrics2; /* (optional) */
+ struct pschars *chars;
+ struct charprocs *charprocs;
+ struct private *private;
+ unsigned int wasbinary: 1;
+ unsigned int wascff: 1;
+ Encoding *encoding_name;
+/* CID stuff */
+ int fdcnt; /* For the underlying dictionaries */
+ struct fontdict **fds;
+ char *cidfontname;
+ int cidfonttype;
+ real cidversion;
+ char *registry;
+ char *ordering;
+ int supplement;
+ int mapoffset;
+ int fdbytes;
+ int gdbytes;
+ int cidcnt;
+ uint8 **cidstrs;
+ int16 *cidlens;
+ int16 *cidfds;
+/* CFF stuff */
+ struct splinefont *sf;
+/* MM stuff */
+ char *blendfunc;
+ char *weightvector;
+ char *cdv;
+ char *ndv;
+ struct psdict *blendprivate;
+ struct psdict *blendfontinfo;
+#ifdef _HAS_LONGLONG
+ long long creationtime; /* seconds since 1970 */
+ long long modificationtime;
+#else
+ long creationtime;
+ long modificationtime;
+#endif
+} FontDict;
+
+struct cidbytes {
+ int fdbytes, gdbytes, cidcnt;
+ int cidmapoffset;
+ int fdcnt;
+ struct fddata {
+ int leniv;
+ int subrmapoff, sdbytes, subrcnt;
+ int flexmax;
+ unsigned int iscjk:1;
+ struct pschars *subrs;
+ } *fds;
+ int *fdind;
+ int errors;
+};
+
+struct fd2data {
+ int defwid, nomwid; /* For Type2 charstrings */
+ struct pschars *subrs;
+ FILE *private; /* Subroutines get stored in the private file immediately after the private dict */
+ int eodictmark, fillindictmark;
+ int privatelen;
+};
+
+extern char *AdobeStandardEncoding[256];
+
+extern FontDict *_ReadPSFont(FILE *ps);
+extern FontDict *ReadPSFont(char *fontname);
+extern void PSFontFree(FontDict *fd);
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/psread.c b/Build/source/libs/luafontforge/fontforge/fontforge/psread.c
new file mode 100644
index 00000000000..2c3ece7d11d
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/psread.c
@@ -0,0 +1,4671 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include <math.h>
+#include <locale.h>
+#include <ustring.h>
+#include <utype.h>
+#include "psfont.h"
+#include "sd.h"
+#if defined(FONTFORGE_CONFIG_TYPE3) && !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+# include "views.h" /* For CharView */
+#endif
+#ifdef HAVE_IEEEFP_H
+# include <ieeefp.h> /* Solaris defines isnan in ieeefp rather than math.h */
+#endif
+
+#ifdef LUA_FF_LIB
+/* no need for iconv here, since PS is 8-bit legacy */
+#define Isspace(a) ((a)==' '|| ((a) >= '\t' && (a) <= '\r'))
+#define Isdigit(a) ((a)>='0' && (a)<='9')
+#else
+#define Isspace isspace
+#define Isdigit isdigit
+#endif
+
+typedef struct _io {
+ char *macro, *start;
+ FILE *ps, *fog;
+ char fogbuf[60];
+ int backedup, cnt, isloop, isstopped, fogns;
+ struct _io *prev;
+} _IO;
+
+typedef struct io {
+ struct _io *top;
+ int endedstopped;
+} IO;
+
+typedef struct growbuf {
+ char *pt;
+ char *base;
+ char *end;
+} GrowBuf;
+
+#define GARBAGE_MAX 64
+struct garbage {
+ int cnt;
+ struct garbage *next;
+ struct pskeyval *entries[GARBAGE_MAX];
+ int16 cnts[GARBAGE_MAX];
+};
+
+static void GrowBuffer(GrowBuf *gb,int len) {
+ if ( len<400 ) len = 400;
+ if ( gb->base==NULL ) {
+ gb->base = gb->pt = galloc(len);
+ gb->end = gb->base + len;
+ } else {
+ int off = gb->pt-gb->base;
+ len += (gb->end-gb->base);
+ gb->base = grealloc(gb->base,len);
+ gb->end = gb->base + len;
+ gb->pt = gb->base+off;
+ }
+}
+
+static void AddTok(GrowBuf *gb,char *buf,int islit) {
+ int len = islit + strlen(buf) + 1;
+
+ if ( gb->pt+len+1 >= gb->end )
+ GrowBuffer(gb,len+1);
+ if ( islit )
+ *(gb->pt++) = '/';
+ strcpy(gb->pt,buf);
+ gb->pt += strlen(buf);
+ *gb->pt++ = ' ';
+}
+
+static struct pskeyval *lookup(struct pskeydict *dict,char *tokbuf) {
+ int i;
+
+ for ( i=0; i<dict->cnt; ++i )
+ if ( strcmp(dict->entries[i].key,tokbuf)==0 )
+return( &dict->entries[i] );
+
+return( NULL );
+}
+
+static void dictfree(struct pskeydict *dict) {
+ int i;
+
+ for ( i=0; i<dict->cnt; ++i ) {
+ if ( dict->entries[i].type==ps_string || dict->entries[i].type==ps_instr ||
+ dict->entries[i].type==ps_lit )
+ free(dict->entries[i].u.str);
+ else if ( dict->entries[i].type==ps_array || dict->entries[i].type==ps_dict )
+ dictfree(&dict->entries[i].u.dict);
+ }
+}
+
+static void garbagefree(struct garbage *all) {
+ struct garbage *junk, *next;
+ int i,j;
+
+ for ( junk = all; junk!=NULL; junk = next ) {
+ next = junk->next;
+ for ( j=0; j<junk->cnt; ++j ) {
+ for ( i=0; i<junk->cnts[j]; ++i ) {
+ if ( junk->entries[j][i].type==ps_string || junk->entries[j][i].type==ps_instr ||
+ junk->entries[j][i].type==ps_lit )
+ free(junk->entries[j][i].u.str);
+ }
+ free(junk->entries[j]);
+ }
+ if ( junk!=all )
+ chunkfree(junk,sizeof(struct garbage));
+ }
+}
+/**************************** Postscript Importer *****************************/
+/* It's really dumb. It ignores almost everything except linetos and curvetos */
+/* anything else, function calls, ... is thrown out, if this breaks a lineto */
+/* or curveto or moveto (if there aren't enough things on the stack) then we */
+/* ignore that too */
+
+enum pstoks { pt_eof=-1, pt_moveto, pt_rmoveto, pt_curveto, pt_rcurveto,
+ pt_lineto, pt_rlineto, pt_arc, pt_arcn, pt_arct, pt_arcto,
+ pt_newpath, pt_closepath, pt_dup, pt_pop, pt_index,
+ pt_exch, pt_roll, pt_clear, pt_copy, pt_count,
+ pt_setcachedevice, pt_setcharwidth,
+ pt_translate, pt_scale, pt_rotate, pt_concat, pt_end, pt_exec,
+ pt_add, pt_sub, pt_mul, pt_div, pt_idiv, pt_mod, pt_neg,
+ pt_abs, pt_round, pt_ceiling, pt_floor, pt_truncate, pt_max, pt_min,
+ pt_ne, pt_eq, pt_gt, pt_ge, pt_lt, pt_le, pt_and, pt_or, pt_xor, pt_not,
+ pt_exp, pt_sqrt, pt_ln, pt_log, pt_atan, pt_sin, pt_cos,
+ pt_true, pt_false,
+ pt_if, pt_ifelse, pt_for, pt_loop, pt_repeat, pt_exit,
+ pt_stopped, pt_stop,
+ pt_def, pt_bind, pt_load,
+ pt_setlinecap, pt_setlinejoin, pt_setlinewidth, pt_setdash,
+ pt_currentlinecap, pt_currentlinejoin, pt_currentlinewidth, pt_currentdash,
+ pt_setgray, pt_currentgray, pt_sethsbcolor, pt_currenthsbcolor,
+ pt_setrgbcolor, pt_currentrgbcolor, pt_setcmykcolor, pt_currentcmykcolor,
+ pt_currentpoint,
+ pt_fill, pt_stroke,
+
+ pt_imagemask,
+
+ pt_transform, pt_itransform, pt_dtransform, pt_idtransform,
+
+ /* things we sort of pretend to do, but actually do something wrong */
+ pt_gsave, pt_grestore, pt_save, pt_restore, pt_currentmatrix, pt_setmatrix,
+ pt_null,
+
+ pt_currentflat, pt_setflat,
+ pt_currentglobal, pt_setglobal,
+ pt_currentmiterlimit, pt_setmiterlimit,
+ pt_currentobjectformat, pt_setobjectformat,
+ pt_currentoverprint, pt_setoverprint,
+ pt_currentpacking, pt_setpacking,
+ pt_currentshared,
+ pt_currentsmoothness, pt_setsmoothness,
+ pt_currentstrokeadjust, pt_setstrokeadjust,
+
+ pt_mark, pt_counttomark, pt_cleartomark, pt_array, pt_aload, pt_astore,
+ pt_print, pt_cvi, pt_cvlit, pt_cvn, pt_cvr, pt_cvrs, pt_cvs, pt_cvx, pt_stringop,
+
+ pt_opencurly, pt_closecurly, pt_openarray, pt_closearray, pt_string,
+ pt_number, pt_unknown, pt_namelit, pt_output, pt_outputd };
+
+static char *toknames[] = { "moveto", "rmoveto", "curveto", "rcurveto",
+ "lineto", "rlineto", "arc", "arcn", "arct", "arcto",
+ "newpath", "closepath", "dup", "pop", "index",
+ "exch", "roll", "clear", "copy", "count",
+ "setcachedevice", "setcharwidth",
+ "translate", "scale", "rotate", "concat", "end", "exec",
+ "add", "sub", "mul", "div", "idiv", "mod", "neg",
+ "abs", "round", "ceiling", "floor", "truncate", "max", "min",
+ "ne", "eq", "gt", "ge", "lt", "le", "and", "or", "xor", "not",
+ "exp", "sqrt", "ln", "log", "atan", "sin", "cos",
+ "true", "false",
+ "if", "ifelse", "for", "loop", "repeat", "exit",
+ "stopped", "stop",
+ "def", "bind", "load",
+ "setlinecap", "setlinejoin", "setlinewidth", "setdash",
+ "currentlinecap", "currentlinejoin", "currentlinewidth", "currentdash",
+ "setgray", "currentgray", "sethsbcolor", "currenthsbcolor",
+ "setrgbcolor", "currentrgbcolor", "setcmykcolor", "currentcmykcolor",
+ "currentpoint",
+ "fill", "stroke",
+
+ "imagemask",
+
+ "transform", "itransform", "dtransform", "idtransform",
+
+ "gsave", "grestore", "save", "restore", "currentmatrix", "setmatrix",
+ "null",
+
+ "currentflat", "setflat",
+ "currentglobal", "setglobal",
+ "currentmiterlimit", "setmiterlimit",
+ "currentobjectformat", "setobjectformat",
+ "currentoverprint", "setoverprint",
+ "currentpacking", "setpacking",
+ "currentshared",
+ "currentsmoothness", "setsmoothness",
+ "currentstrokeadjust", "setstrokeadjust",
+
+ "mark", "counttomark", "cleartomark", "array", "aload", "astore",
+ "print", "cvi", "cvlit", "cvn", "cvr", "cvrs", "cvs", "cvx", "string",
+
+ "opencurly", "closecurly", "openarray", "closearray", "string",
+ "number", "unknown", "namelit", "=", "==",
+
+ NULL };
+
+/* length (of string)
+ fill eofill stroke
+ gsave grestore
+*/
+
+static int getfoghex(_IO *io) {
+ int ch,val;
+
+ while ( Isspace( ch = getc(io->fog)));
+ if ( Isdigit(ch))
+ val = ch-'0';
+ else if ( ch >= 'A' && ch <= 'F' )
+ val = ch-'A'+10;
+ else if ( ch >= 'a' && ch <= 'f' )
+ val = ch-'a'+10;
+ else
+return(EOF);
+
+ val <<= 4;
+ while ( Isspace( ch = getc(io->fog)));
+ if ( Isdigit(ch))
+ val |= ch-'0';
+ else if ( ch >= 'A' && ch <= 'F' )
+ val |= ch-'A'+10;
+ else if ( ch >= 'a' && ch <= 'f' )
+ val |= ch-'a'+10;
+ else
+return(EOF);
+
+return( val );
+}
+
+static int nextch(IO *wrapper) {
+ int ch;
+ _IO *io = wrapper->top;
+/* This works for fog 4.1. Fonts generated by 2.4 seem to use a different */
+/* vector, and a different number parsing scheme */
+ static char *foguvec[]= { "moveto ", "rlineto ", "rrcurveto ", " ", " ",
+ "Cache ", "10 div setlinewidth ", "ShowInt ", " ", " ", " ", " ",
+ "FillStroke ", " ", " ", "SetWid ", "100 mul add ", "togNS_ ",
+ " ", "closepath ", " ", "SG " };
+
+ while ( io!=NULL ) {
+ if ( io->backedup!=EOF ) {
+ ch = io->backedup;
+ io->backedup = EOF;
+return( ch );
+ } else if ( io->ps!=NULL ) {
+ if ( (ch = getc(io->ps))!=EOF )
+return( ch );
+ } else if ( io->fog!=NULL ) {
+ if ( io->macro!=NULL && *io->macro!='\0' )
+return( *(io->macro++) );
+ ch = getfoghex(io);
+ if ( ch>=233 ) {
+ io->macro = foguvec[ch-233];
+return( *(io->macro++) );
+ } else if ( ch!=EOF && ch<200 ) {
+ sprintf( io->fogbuf, "%d ", ch-100);
+ io->macro=io->fogbuf;
+return( *(io->macro++) );
+ } else if (ch!=EOF) {
+ sprintf( io->fogbuf, "%d %s ", ch-233+17, io->fogns
+ ? "2 exch exp 3 1 roll 100 mul add mul"
+ : "100 mul add" );
+ io->macro=io->fogbuf;
+return( *(io->macro++) );
+ }
+ } else {
+ if ( (ch = *(io->macro++))!='\0' )
+return( ch );
+ if ( --io->cnt>0 ) {
+ io->macro = io->start;
+return( nextch(wrapper));
+ }
+ }
+ wrapper->top = io->prev;
+ if ( io->isstopped )
+ wrapper->endedstopped = true;
+ free(io->start);
+ free(io);
+ io = wrapper->top;
+ }
+return( EOF );
+}
+
+static void unnextch(int ch,IO *wrapper) {
+ if ( ch==EOF )
+return;
+ if ( wrapper->top==NULL )
+ LogError( _("Can't back up with nothing on stack\n") );
+ else if ( wrapper->top->backedup!=EOF )
+ LogError( _("Attempt to back up twice\n") );
+ else if ( wrapper->top->ps!=NULL )
+ ungetc(ch,wrapper->top->ps);
+ else
+ wrapper->top->backedup = ch;
+}
+
+static void pushio(IO *wrapper, FILE *ps, char *macro, int cnt) {
+ _IO *io = gcalloc(1,sizeof(_IO));
+
+ io->prev = wrapper->top;
+ io->ps = ps;
+ io->macro = io->start = copy(macro);
+ io->backedup = EOF;
+ if ( cnt==-1 ) {
+ io->cnt = 1;
+ io->isstopped = true;
+ } else if ( cnt==0 ) {
+ io->cnt = 1;
+ io->isloop = false;
+ } else {
+ io->cnt = cnt;
+ io->isloop = true;
+ }
+ wrapper->top = io;
+}
+
+static void pushfogio(IO *wrapper, FILE *fog) {
+ _IO *io = gcalloc(1,sizeof(_IO));
+
+ io->prev = wrapper->top;
+ io->fog = fog;
+ io->backedup = EOF;
+ io->cnt = 1;
+ io->isloop = false;
+ wrapper->top = io;
+}
+
+static void ioescapeloop(IO *wrapper) {
+ _IO *io = wrapper->top, *iop;
+ int wasloop;
+
+ while ( io->prev!=NULL && !io->isstopped ) {
+ iop = io->prev;
+ wasloop = io->isloop;
+ free(io->start);
+ free(io);
+ if ( wasloop ) {
+ wrapper->top = iop;
+return;
+ }
+ io = iop;
+ }
+
+/* GT: This is part of the PostScript language. "exit" should not be translated */
+/* GT: as it is a PostScript keyword. (FF contains a small PostScript interpreter */
+/* GT: so it can understand some PostScript fonts, and can generate errors when */
+/* GT: handed bad PostScript). */
+ LogError( _("Use of \"exit\" when not in a loop\n") );
+ wrapper->top = io;
+}
+
+static int ioescapestopped(IO *wrapper, struct psstack *stack, int sp) {
+ _IO *io = wrapper->top, *iop;
+ int wasstopped;
+
+ while ( io->prev!=NULL ) {
+ iop = io->prev;
+ wasstopped = io->isstopped;
+ free(io->start);
+ free(io);
+ if ( wasstopped ) {
+ wrapper->top = iop;
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_bool;
+ stack[sp++].u.tf = true;
+ }
+return(sp);
+ }
+ io = iop;
+ }
+
+/* GT: This is part of the PostScript language. Neither "stop" nor "stopped" */
+/* GT: should be translated as both are PostScript keywords. */
+ LogError( _("Use of \"stop\" when not in a stopped\n") );
+ wrapper->top = io;
+return( sp );
+}
+
+static int endedstopped(IO *wrapper) {
+ if ( wrapper->endedstopped ) {
+ wrapper->endedstopped = false;
+return( true );
+ }
+return( false );
+}
+
+static int CheckCodePointsComment(IO *wrapper) {
+ /* Check to see if this encoding includes the special comment we use */
+ /* to indicate that the encoding is based on unicode code points rather */
+ /* than glyph names */
+ char commentbuffer[128], *pt;
+ int ch;
+
+ /* Eat whitespace and comments. Comments last to eol (or formfeed) */
+ while ( Isspace(ch = nextch(wrapper)) );
+ if ( ch!='%' ) {
+ unnextch(ch,wrapper);
+return( false );
+ }
+
+ pt = commentbuffer;
+ while ( (ch=nextch(wrapper))!=EOF && ch!='\r' && ch!='\n' && ch!='\f' ) {
+ if ( pt-commentbuffer < sizeof(commentbuffer)-1 )
+ *pt++ = ch;
+ }
+ *pt = '\0';
+ if ( strcmp(commentbuffer," Use codepoints.")== 0 )
+return( true );
+
+return( false );
+}
+
+static int nextpstoken(IO *wrapper, real *val, char *tokbuf, int tbsize) {
+ int ch, r, i;
+ char *pt, *end;
+
+ /* Eat whitespace and comments. Comments last to eol (or formfeed) */
+ while ( 1 ) {
+ while ( Isspace(ch = nextch(wrapper)) );
+ if ( ch!='%' )
+ break;
+ while ( (ch=nextch(wrapper))!=EOF && ch!='\r' && ch!='\n' && ch!='\f' );
+ }
+
+ if ( ch==EOF )
+return( pt_eof );
+
+ pt = tokbuf;
+ end = pt+tbsize-1;
+ *pt++ = ch; *pt='\0';
+
+ if ( ch=='(' ) {
+ int nest=1, quote=0;
+ while ( (ch=nextch(wrapper))!=EOF ) {
+ if ( pt<end ) *pt++ = ch;
+ if ( quote )
+ quote=0;
+ else if ( ch=='(' )
+ ++nest;
+ else if ( ch==')' ) {
+ if ( --nest==0 )
+ break;
+ } else if ( ch=='\\' )
+ quote = 1;
+ }
+ *pt='\0';
+return( pt_string );
+ } else if ( ch=='<' ) {
+ ch = nextch(wrapper);
+ if ( pt<end ) *pt++ = ch;
+ if ( ch=='>' )
+ /* Done */;
+ else if ( ch!='~' ) {
+ while ( (ch=nextch(wrapper))!=EOF && ch!='>' )
+ if ( pt<end ) *pt++ = ch;
+ } else {
+ int twiddle=0;
+ while ( (ch=nextch(wrapper))!=EOF ) {
+ if ( pt<end ) *pt++ = ch;
+ if ( ch=='~' ) twiddle = 1;
+ else if ( twiddle && ch=='>' )
+ break;
+ else twiddle = 0;
+ }
+ }
+ *pt='\0';
+return( pt_string );
+ } else if ( ch==')' || ch=='>' || ch=='[' || ch==']' || ch=='{' || ch=='}' ) {
+ if ( ch=='{' )
+return( pt_opencurly );
+ else if ( ch=='}' )
+return( pt_closecurly );
+ if ( ch=='[' )
+return( pt_openarray );
+ else if ( ch==']' )
+return( pt_closearray );
+
+return( pt_unknown ); /* single character token */
+ } else if ( ch=='/' ) {
+ pt = tokbuf;
+ while ( (ch=nextch(wrapper))!=EOF && !Isspace(ch) && ch!='%' &&
+ ch!='(' && ch!=')' && ch!='<' && ch!='>' && ch!='[' && ch!=']' &&
+ ch!='{' && ch!='}' && ch!='/' )
+ if ( pt<tokbuf+tbsize-2 )
+ *pt++ = ch;
+ *pt = '\0';
+ unnextch(ch,wrapper);
+return( pt_namelit ); /* name literal */
+ } else {
+ while ( (ch=nextch(wrapper))!=EOF && !Isspace(ch) && ch!='%' &&
+ ch!='(' && ch!=')' && ch!='<' && ch!='>' && ch!='[' && ch!=']' &&
+ ch!='{' && ch!='}' && ch!='/' ) {
+ if ( pt<tokbuf+tbsize-2 )
+ *pt++ = ch;
+ }
+ *pt = '\0';
+ unnextch(ch,wrapper);
+ r = strtol(tokbuf,&end,10);
+ pt = end;
+ if ( *pt=='\0' ) { /* It's a normal integer */
+ *val = r;
+return( pt_number );
+ } else if ( *pt=='#' ) {
+ r = strtol(pt+1,&end,r);
+ if ( *end=='\0' ) { /* It's a radix integer */
+ *val = r;
+return( pt_number );
+ }
+ } else {
+ *val = strtod(tokbuf,&end);
+ if ( !finite(*val) ) {
+/* GT: NaN is a concept in IEEE floating point which means "Not a Number" */
+/* GT: it is used to represent errors like 0/0 or sqrt(-1). */
+ LogError( _("Bad number, infinity or nan: %s\n"), tokbuf );
+ *val = 0;
+ }
+ if ( *end=='\0' ) /* It's a real */
+return( pt_number );
+ }
+ /* It's not a number */
+ for ( i=0; toknames[i]!=NULL; ++i )
+ if ( strcmp(tokbuf,toknames[i])==0 )
+return( i );
+
+return( pt_unknown );
+ }
+}
+
+static void Transform(BasePoint *to, BasePoint *from, real trans[6]) {
+ to->x = trans[0]*from->x+trans[2]*from->y+trans[4];
+ to->y = trans[1]*from->x+trans[3]*from->y+trans[5];
+}
+
+void MatMultiply(real m1[6], real m2[6], real to[6]) {
+ real trans[6];
+
+ trans[0] = m1[0]*m2[0] +
+ m1[1]*m2[2];
+ trans[1] = m1[0]*m2[1] +
+ m1[1]*m2[3];
+ trans[2] = m1[2]*m2[0] +
+ m1[3]*m2[2];
+ trans[3] = m1[2]*m2[1] +
+ m1[3]*m2[3];
+ trans[4] = m1[4]*m2[0] +
+ m1[5]*m2[2] +
+ m2[4];
+ trans[5] = m1[4]*m2[1] +
+ m1[5]*m2[3] +
+ m2[5];
+ memcpy(to,trans,sizeof(trans));
+}
+
+void MatInverse(real into[6], real orig[6]) {
+ real det = orig[0]*orig[3] - orig[1]*orig[2];
+
+ if ( det==0 ) {
+ LogError( _("Attempt to invert a singular matrix\n") );
+ memset(into,0,sizeof(*into));
+ } else {
+ into[0] = orig[3]/det;
+ into[1] = -orig[1]/det;
+ into[2] = -orig[2]/det;
+ into[3] = orig[0]/det;
+ into[4] = -orig[4]*into[0] - orig[5]*into[2];
+ into[5] = -orig[4]*into[1] - orig[5]*into[3];
+ }
+}
+
+static void ECCatagorizePoints( EntityChar *ec ) {
+ Entity *ent;
+
+ for ( ent=ec->splines; ent!=NULL; ent=ent->next ) if ( ent->type == et_splines ) {
+ SPLCatagorizePoints( ent->u.splines.splines );
+ }
+}
+
+static int AddEntry(struct pskeydict *dict,struct psstack *stack, int sp) {
+ int i;
+
+ if ( dict->cnt>=dict->max ) {
+ if ( dict->cnt==0 ) {
+ dict->max = 30;
+ dict->entries = galloc(dict->max*sizeof(struct pskeyval));
+ } else {
+ dict->max += 30;
+ dict->entries = grealloc(dict->entries,dict->max*sizeof(struct pskeyval));
+ }
+ }
+ if ( sp<2 )
+return(sp);
+ if ( stack[sp-2].type!=ps_string && stack[sp-2].type!=ps_lit ) {
+/* GT: Here "def" is a PostScript keyword, (meaning define). */
+/* GT: This "def" should not be translated as it is part of the PostScript language. */
+ LogError( _("Key for a def must be a string or name literal\n") );
+return(sp-2);
+ }
+ for ( i=0; i<dict->cnt; ++i )
+ if ( strcmp(dict->entries[i].key,stack[sp-2].u.str)==0 )
+ break;
+ if ( i!=dict->cnt ) {
+ free(stack[sp-2].u.str);
+ if ( dict->entries[i].type==ps_string || dict->entries[i].type==ps_instr ||
+ dict->entries[i].type==ps_lit )
+ free(dict->entries[i].u.str);
+ } else {
+ memset(&dict->entries[i],'\0',sizeof(struct pskeyval));
+ dict->entries[i].key = stack[sp-2].u.str;
+ ++dict->cnt;
+ }
+ dict->entries[i].type = stack[sp-1].type;
+ dict->entries[i].u = stack[sp-1].u;
+return(sp-2);
+}
+
+static int forgetstack(struct psstack *stack, int forgets, int sp) {
+ /* forget the bottom most "forgets" entries on the stack */
+ /* we presume they are garbage that has accumulated because we */
+ /* don't understand all of PS */
+ int i;
+ for ( i=0; i<forgets; ++i ) {
+ if ( stack[i].type==ps_string || stack[i].type==ps_instr ||
+ stack[i].type==ps_lit )
+ free(stack[i].u.str);
+ else if ( stack[i].type==ps_array || stack[i].type==ps_dict )
+ dictfree(&stack[i].u.dict);
+ }
+ for ( i=forgets; i<sp; ++i )
+ stack[i-forgets] = stack[i];
+return( sp-forgets );
+}
+
+static int rollstack(struct psstack *stack, int sp) {
+ int n,j,i;
+ struct psstack *temp;
+
+ if ( sp>1 ) {
+ n = stack[sp-2].u.val;
+ j = stack[sp-1].u.val;
+ sp-=2;
+ if ( sp>=n && n>0 ) {
+ j %= n;
+ if ( j<0 ) j += n;
+ temp = galloc(n*sizeof(struct psstack));
+ for ( i=0; i<n; ++i )
+ temp[i] = stack[sp-n+i];
+ for ( i=0; i<n; ++i )
+ stack[sp-n+(i+j)%n] = temp[i];
+ free(temp);
+ }
+ }
+return( sp );
+}
+
+static void CheckMakeB(BasePoint *test, BasePoint *good) {
+ if ( !finite(test->x) || test->x>100000 || test->x<-100000 ) {
+ LogError( _("Value out of bounds in spline.\n") );
+ if ( good!=NULL )
+ test->x = good->x;
+ else
+ test->x = 0;
+ }
+ if ( !finite(test->y) || test->y>100000 || test->y<-100000 ) {
+ LogError( _("Value out of bounds in spline.\n") );
+ if ( good!=NULL )
+ test->y = good->y;
+ else
+ test->y = 0;
+ }
+}
+
+static void CheckMake(SplinePoint *from, SplinePoint *to) {
+ CheckMakeB(&from->me,NULL);
+ CheckMakeB(&from->nextcp,&from->me);
+ CheckMakeB(&to->prevcp,&from->nextcp);
+ CheckMakeB(&to->me,&to->prevcp);
+}
+
+static void circlearcto(real a1, real a2, real cx, real cy, real r,
+ SplineSet *cur, real *transform ) {
+ SplinePoint *pt;
+ BasePoint temp, base, cp;
+ real cplen;
+ int sign=1;
+ real s1, s2, c1, c2;
+
+ if ( a1==a2 )
+return;
+
+ cplen = (a2-a1)/90 * r * .552;
+ a1 *= 3.1415926535897932/180; a2 *= 3.1415926535897932/180;
+ s1 = sin(a1); s2 = sin(a2); c1 = cos(a1); c2 = cos(a2);
+ temp.x = cx+r*c2; temp.y = cy+r*s2;
+ base.x = cx+r*c1; base.y = cy+r*s1;
+ pt = chunkalloc(sizeof(SplinePoint));
+ Transform(&pt->me,&temp,transform);
+ cp.x = temp.x-cplen*s2; cp.y = temp.y + cplen*c2;
+ if ( (cp.x-base.x)*(cp.x-base.x)+(cp.y-base.y)*(cp.y-base.y) >
+ (temp.x-base.x)*(temp.x-base.x)+(temp.y-base.y)*(temp.y-base.y) ) {
+ sign = -1;
+ cp.x = temp.x+cplen*s2; cp.y = temp.y - cplen*c2;
+ }
+ Transform(&pt->prevcp,&cp,transform);
+ pt->nonextcp = true;
+ cp.x = base.x + sign*cplen*s1; cp.y = base.y - sign*cplen*c1;
+ Transform(&cur->last->nextcp,&cp,transform);
+ cur->last->nonextcp = false;
+ CheckMake(cur->last,pt);
+ SplineMake3(cur->last,pt);
+ cur->last = pt;
+}
+
+static void circlearcsto(real a1, real a2, real cx, real cy, real r,
+ SplineSet *cur, real *transform, int clockwise ) {
+ int a;
+ real last;
+
+ while ( a1<0 ) { a1 += 360; a2 +=360;} while ( a2-a1<=-360 ) a2 += 360;
+ while ( a1>360 ) { a1 -= 360; a2 -= 360; } while ( a2-a1>360 ) a2 -= 360;
+ if ( !clockwise ) {
+ if ( a1>a2 )
+ a2 += 360;
+ last = a1;
+ for ( a=((int) (a1+90)/90)*90; a<a2; a += 90 ) {
+ circlearcto(last,a,cx,cy,r,cur,transform);
+ last = a;
+ }
+ circlearcto(last,a2,cx,cy,r,cur,transform);
+ } else {
+ if ( a2>a1 )
+ a1 += 360;
+ last = a1;
+ for ( a=((int) (a1-90)/90)*90+90; a>a2; a -= 90 ) {
+ circlearcto(last,a,cx,cy,r,cur,transform);
+ last = a;
+ }
+ circlearcto(last,a2,cx,cy,r,cur,transform);
+ }
+}
+
+static void collectgarbage(struct garbage *tofrees,struct pskeydict *to) {
+ struct garbage *into;
+
+ /* Garbage collection pointers */
+ into = tofrees;
+ if ( tofrees->cnt>=GARBAGE_MAX && tofrees->next!=NULL )
+ into = tofrees->next;
+ if ( into->cnt>=GARBAGE_MAX ) {
+ into = chunkalloc(sizeof(struct garbage));
+ into->next = tofrees->next;
+ tofrees->next = into;
+ }
+ into->cnts[ into->cnt ] = to->cnt;
+ into->entries[ into->cnt++ ] = to->entries;
+}
+
+static void copyarray(struct pskeydict *to,struct pskeydict *from, struct garbage *tofrees) {
+ int i;
+ struct pskeyval *oldent = from->entries;
+
+ *to = *from;
+ to->entries = gcalloc(to->cnt,sizeof(struct pskeyval));
+ for ( i=0; i<to->cnt; ++i ) {
+ to->entries[i] = oldent[i];
+ if ( to->entries[i].type==ps_string || to->entries[i].type==ps_instr ||
+ to->entries[i].type==ps_lit )
+ to->entries[i].u.str = copy(to->entries[i].u.str);
+ else if ( to->entries[i].type==ps_array || to->entries[i].type==ps_dict )
+ copyarray(&to->entries[i].u.dict,&oldent[i].u.dict,tofrees);
+ }
+ collectgarbage(tofrees,to);
+}
+
+static int aload(int sp, struct psstack *stack,int stacktop, struct garbage *tofrees) {
+ int i;
+
+ if ( sp>=1 && stack[sp-1].type==ps_array ) {
+ struct pskeydict dict;
+ --sp;
+ dict = stack[sp].u.dict;
+ for ( i=0; i<dict.cnt; ++i ) {
+ if ( sp<stacktop ) {
+ stack[sp].type = dict.entries[i].type;
+ stack[sp].u = dict.entries[i].u;
+ if ( stack[sp].type==ps_string || stack[sp].type==ps_instr ||
+ stack[sp].type==ps_lit )
+ stack[sp].u.str = copy(stack[sp].u.str);
+/* The following is incorrect behavior, but as I don't do garbage collection */
+/* and I'm not going to implement reference counts, this will work in most cases */
+ else if ( stack[sp].type==ps_array )
+ copyarray(&stack[sp].u.dict,&stack[sp].u.dict,tofrees);
+ ++sp;
+ }
+ }
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_array;
+ stack[sp].u.dict = dict;
+ ++sp;
+ }
+ }
+return( sp );
+}
+
+static void printarray(struct pskeydict *dict) {
+ int i;
+
+ printf("[" );
+ for ( i=0; i<dict->cnt; ++i ) {
+ switch ( dict->entries[i].type ) {
+ case ps_num:
+ printf( "%g", (double) dict->entries[i].u.val );
+ break;
+ case ps_bool:
+ printf( "%s", dict->entries[i].u.tf ? "true" : "false" );
+ break;
+ case ps_string: case ps_instr: case ps_lit:
+ printf( dict->entries[i].type==ps_lit ? "/" :
+ dict->entries[i].type==ps_string ? "(" : "{" );
+ printf( "%s", dict->entries[i].u.str );
+ printf( dict->entries[i].type==ps_lit ? "" :
+ dict->entries[i].type==ps_string ? ")" : "}" );
+ break;
+ case ps_array:
+ printarray(&dict->entries[i].u.dict);
+ break;
+ case ps_void:
+ printf( "-- void --" );
+ break;
+ default:
+ printf( "-- nostringval --" );
+ break;
+ }
+ printf(" ");
+ }
+ printf( "]" );
+}
+
+static void freestuff(struct psstack *stack, int sp, struct pskeydict *dict,
+ GrowBuf *gb, struct garbage *tofrees) {
+ int i;
+
+ free(gb->base);
+ for ( i=0; i<dict->cnt; ++i ) {
+ if ( dict->entries[i].type==ps_string || dict->entries[i].type==ps_instr ||
+ dict->entries[i].type==ps_lit )
+ free(dict->entries[i].u.str);
+ free(dict->entries[i].key);
+ }
+ free( dict->entries );
+ for ( i=0; i<sp; ++i ) {
+ if ( stack[i].type==ps_string || stack[i].type==ps_instr ||
+ stack[i].type==ps_lit )
+ free(stack[i].u.str);
+#if 0 /* Garbage collection should get these */
+ else if ( stack[i].type==ps_array || stack[i].type==ps_dict )
+ dictfree(&stack[i].u.dict);
+#endif
+ }
+ garbagefree(tofrees);
+}
+
+static void DoMatTransform(int tok,int sp,struct psstack *stack) {
+ real invt[6], t[6];
+
+ if ( stack[sp-1].u.dict.cnt==6 && stack[sp-1].u.dict.entries[0].type==ps_num ) {
+ double x = stack[sp-3].u.val, y = stack[sp-2].u.val;
+ --sp;
+ t[5] = stack[sp].u.dict.entries[5].u.val;
+ t[4] = stack[sp].u.dict.entries[4].u.val;
+ t[3] = stack[sp].u.dict.entries[3].u.val;
+ t[2] = stack[sp].u.dict.entries[2].u.val;
+ t[1] = stack[sp].u.dict.entries[1].u.val;
+ t[0] = stack[sp].u.dict.entries[0].u.val;
+ dictfree(&stack[sp].u.dict);
+ if ( tok==pt_itransform || tok==pt_idtransform ) {
+ MatInverse(invt,t);
+ memcpy(t,invt,sizeof(t));
+ }
+ stack[sp-2].u.val = t[0]*x + t[1]*y;
+ stack[sp-1].u.val = t[2]*x + t[3]*y;
+ if ( tok==pt_transform || tok==pt_itransform ) {
+ stack[sp-2].u.val += t[4];
+ stack[sp-1].u.val += t[5];
+ }
+ }
+}
+
+static int DoMatOp(int tok,int sp,struct psstack *stack) {
+ real temp[6], t[6];
+ int nsp=sp;
+
+ if ( stack[sp-1].u.dict.cnt==6 && stack[sp-1].u.dict.entries[0].type==ps_num ) {
+ t[5] = stack[sp-1].u.dict.entries[5].u.val;
+ t[4] = stack[sp-1].u.dict.entries[4].u.val;
+ t[3] = stack[sp-1].u.dict.entries[3].u.val;
+ t[2] = stack[sp-1].u.dict.entries[2].u.val;
+ t[1] = stack[sp-1].u.dict.entries[1].u.val;
+ t[0] = stack[sp-1].u.dict.entries[0].u.val;
+ switch ( tok ) {
+ case pt_translate:
+ if ( sp>=3 ) {
+ stack[sp-1].u.dict.entries[5].u.val += stack[sp-3].u.val*t[0]+stack[sp-2].u.val*t[2];
+ stack[sp-1].u.dict.entries[4].u.val += stack[sp-3].u.val*t[1]+stack[sp-2].u.val*t[3];
+ nsp = sp-2;
+ }
+ break;
+ case pt_scale:
+ if ( sp>=2 ) {
+ stack[sp-1].u.dict.entries[0].u.val *= stack[sp-3].u.val;
+ stack[sp-1].u.dict.entries[1].u.val *= stack[sp-3].u.val;
+ stack[sp-1].u.dict.entries[2].u.val *= stack[sp-2].u.val;
+ stack[sp-1].u.dict.entries[3].u.val *= stack[sp-2].u.val;
+ /* transform[4,5] are unchanged */
+ nsp = sp-2;
+ }
+ break;
+ case pt_rotate:
+ if ( sp>=1 ) {
+ --sp;
+ temp[0] = temp[3] = cos(stack[sp].u.val);
+ temp[1] = sin(stack[sp].u.val);
+ temp[2] = -temp[1];
+ temp[4] = temp[5] = 0;
+ MatMultiply(temp,t,t);
+ stack[sp-1].u.dict.entries[5].u.val = t[5];
+ stack[sp-1].u.dict.entries[4].u.val = t[4];
+ stack[sp-1].u.dict.entries[3].u.val = t[3];
+ stack[sp-1].u.dict.entries[2].u.val = t[2];
+ stack[sp-1].u.dict.entries[1].u.val = t[1];
+ stack[sp-1].u.dict.entries[0].u.val = t[0];
+ nsp = sp-1;
+ }
+ break;
+ }
+ stack[nsp-1] = stack[sp-1];
+ }
+return(nsp);
+}
+
+static Entity *EntityCreate(SplinePointList *head,int linecap,int linejoin,
+ real linewidth, real *transform) {
+ Entity *ent = gcalloc(1,sizeof(Entity));
+ ent->type = et_splines;
+ ent->u.splines.splines = head;
+ ent->u.splines.cap = linecap;
+ ent->u.splines.join = linejoin;
+ ent->u.splines.stroke_width = linewidth;
+ ent->u.splines.fill.col = 0xffffffff;
+ ent->u.splines.stroke.col = 0xffffffff;
+ ent->u.splines.fill.opacity = 1.0;
+ ent->u.splines.stroke.opacity = 1.0;
+ memcpy(ent->u.splines.transform,transform,6*sizeof(real));
+return( ent );
+}
+
+#ifdef FONTFORGE_CONFIG_TYPE3
+static uint8 *StringToBytes(struct psstack *stackel,int *len) {
+ char *pt;
+ uint8 *upt, *base, *ret;
+ int half, sofar, val, nesting;
+ int i,j;
+
+ pt = stackel->u.str;
+ if ( stackel->type==ps_instr ) {
+ /* imagemask operators take strings or procedures or files */
+ /* we support strings, or procedures containing strings */
+ while ( Isspace(*pt)) ++pt;
+ if ( *pt=='{' || *pt=='[' ) ++pt;
+ while ( Isspace(*pt)) ++pt;
+ } else if ( stackel->type!=pt_string )
+return( NULL );
+
+ upt = base = galloc(65536+1); /* Maximum size of ps string */
+
+ if ( *pt=='(' ) {
+ /* A conventional string */
+ ++pt;
+ nesting = 0;
+ while ( *pt!='\0' && (nesting!=0 || *pt!=')') ) {
+ if ( *pt=='(' ) {
+ ++nesting;
+ *upt++ = *pt++;
+ } else if ( *pt==')' ) {
+ --nesting;
+ *upt++ = *pt++;
+ } else if ( *pt=='\r' || *pt=='\n' ) {
+ /* any of lf, cr, crlf gets translated to \n */
+ if ( *pt=='\r' && pt[1]=='\n' ) ++pt;
+ *upt++ = '\n';
+ ++pt;
+ } else if ( *pt!='\\' ) {
+ *upt++ = *pt++;
+ } else {
+ ++pt;
+ if ( *pt=='\r' || *pt=='\n' ) {
+ /* any of \lf, \cr, \crlf gets ignored */
+ if ( *pt=='\r' && pt[1]=='\n' ) ++pt;
+ ++pt;
+ } else if ( *pt=='n' ) {
+ *upt++ = '\n';
+ ++pt;
+ } else if ( *pt=='r' ) {
+ *upt++ = '\r';
+ ++pt;
+ } else if ( *pt=='t' ) {
+ *upt++ = '\t';
+ ++pt;
+ } else if ( *pt=='b' ) {
+ *upt++ = '\b';
+ ++pt;
+ } else if ( *pt=='f' ) {
+ *upt++ = '\f';
+ ++pt;
+ } else if ( *pt>='0' && *pt<='7' ) {
+ if ( pt[1]<'0' || pt[1]>'7' ) /* This isn't really legal postscript */
+ *upt++ = *pt++ - '0';
+ else if ( pt[2]<'0' || pt[2]>'7' ) {/* 3 octal digits are required */
+ *upt++ = ((*pt - '0')<<3) + (pt[1]-'0');
+ pt += 2;
+ } else {
+ *upt++ = ((*pt - '0')<<6) + ((pt[1]-'0')<<3) + (pt[2]-'0');
+ pt += 3;
+ }
+ } else if ( *pt=='(' || *pt==')' || *pt=='\\' )
+ *upt++ = *pt++;
+ else {
+ LogError( _("Unknown character after backslash in literal string.\n"));
+ *upt++ = *pt++;
+ }
+ }
+ }
+ } else if ( *pt!='<' ) {
+ LogError( _("Unknown string type\n" ));
+return( NULL );
+ } else if ( pt[1]!='~' ) {
+ /* A hex string. Ignore any characters which aren't hex */
+ half = sofar = 0;
+ ++pt;
+ while ( *pt!='>' && *pt!='\0' ) {
+ if ( *pt>='a' && *pt<='f' )
+ val = *pt++-'a'+10;
+ else if ( *pt>='A' && *pt<='F' )
+ val = *pt++-'A'+10;
+ else if ( Isdigit(*pt))
+ val = *pt++-'0';
+ else {
+ ++pt; /* Not hex */
+ continue;
+ }
+ if ( !half ) {
+ half = true;
+ sofar = val<<4;
+ } else {
+ *upt++ = sofar|val;
+ half = false;
+ }
+ }
+ if ( half )
+ *upt++ = sofar;
+ } else {
+ /* An ASCII-85 string */
+ /* c1 c2 c3 c4 c5 (c>='!' && c<='u') => ((c1-'!')*85+(c2-'!'))*85... */
+ /* z => 32bits of 0 */
+ pt += 2;
+ while ( *pt!='\0' && *pt!='~' ) {
+ if ( upt-base+4 > 65536 )
+ break;
+ if ( *pt=='z' ) {
+ *upt++ = 0;
+ *upt++ = 0;
+ *upt++ = 0;
+ *upt++ = 0;
+ ++pt;
+ } else if ( *pt>='!' && *pt<='u' ) {
+ val = 0;
+ for ( i=0; i<5 && *pt>='!' && *pt<='u'; ++i )
+ val = (val*85) + *pt++ - '!';
+ for ( j=i; j<5; ++j )
+ val *= 85;
+ *upt++ = val>>24 ;
+ if ( i>2 )
+ *upt++ = (val>>16)&0xff;
+ if ( i>3 )
+ *upt++ = (val>>8 )&0xff;
+ if ( i>4 )
+ *upt++ = val &0xff;
+ if ( i<5 )
+ break;
+ } else if ( Isspace( *pt ) ) {
+ ++pt;
+ } else
+ break;
+ }
+ }
+ *len = upt-base;
+ ret = galloc(upt-base);
+ memcpy(ret,base,upt-base);
+ free(base);
+return(ret);
+}
+
+static int PSAddImagemask(EntityChar *ec,struct psstack *stack,int sp,
+ real transform[6],Color fillcol) {
+ uint8 *data;
+ int datalen, width, height, polarity;
+ real trans[6];
+ struct _GImage *base;
+ GImage *gi;
+ Entity *ent;
+ int i,j;
+
+ if ( sp<5 || (stack[sp-1].type!=ps_instr && stack[sp-1].type!=ps_string)) {
+ LogError( _("FontForge does not support dictionary based imagemask operators.\n" ));
+return( sp-1 );
+ }
+
+ if ( stack[sp-2].type!=ps_array || stack[sp-2].u.dict.cnt!=6 ) {
+ LogError( _("Fourth argument of imagemask must be a 6-element transformation matrix.\n" ));
+return( sp-5 );
+ }
+
+ if ( stack[sp-3].type!=ps_bool ) {
+ LogError( _("Third argument of imagemask must be a boolean.\n" ));
+return( sp-5 );
+ }
+ polarity = stack[sp-3].u.tf;
+
+ if ( stack[sp-4].type!=ps_num || stack[sp-5].type!=ps_num ) {
+ LogError( _("First and second arguments of imagemask must be integers.\n" ));
+return( sp-5 );
+ }
+ height = stack[sp-4].u.val;
+ width = stack[sp-5].u.val;
+
+ data = StringToBytes(&stack[sp-1],&datalen);
+
+ if ( width<=0 || height<=0 || ((width+7)/8)*height>datalen ) {
+ LogError( _("Width or height arguments to imagemask contain invalid values\n(either negative or they require more data than provided).\n" ));
+ free(data);
+return( sp-5 );
+ }
+ trans[0] = stack[sp-2].u.dict.entries[0].u.val;
+ trans[1] = stack[sp-2].u.dict.entries[1].u.val;
+ trans[2] = stack[sp-2].u.dict.entries[2].u.val;
+ trans[3] = stack[sp-2].u.dict.entries[3].u.val;
+ trans[4] = stack[sp-2].u.dict.entries[4].u.val;
+ trans[5] = stack[sp-2].u.dict.entries[5].u.val;
+
+ gi = GImageCreate(it_mono,width,height);
+ base = gi->u.image;
+ base->trans = 1;
+ if ( polarity ) {
+ for ( i=0; i<datalen; ++i )
+ data[i] ^= 0xff;
+ }
+ if ( trans[0]>0 && trans[3]<0 )
+ memcpy(base->data,data,datalen);
+ else if ( trans[0]>0 && trans[3]>0 ) {
+ for ( i=0; i<height; ++i )
+ memcpy(base->data+i*base->bytes_per_line,data+(height-i)*base->bytes_per_line,
+ base->bytes_per_line);
+ } else if ( trans[0]<0 && trans[3]<0 ) {
+ for ( i=0; i<height; ++i ) for ( j=0; j<width; ++j ) {
+ if ( data[i*base->bytes_per_line+ (j>>3)]&(0x80>>(j&7)) )
+ base->data[i*base->bytes_per_line + ((width-j-1)>>3)] |=
+ (0x80>>((width-j-1)&7));
+ }
+ } else {
+ for ( i=0; i<height; ++i ) for ( j=0; j<width; ++j ) {
+ if ( data[i*base->bytes_per_line+ (j>>3)]&(0x80>>(j&7)) )
+ base->data[(height-i-1)*base->bytes_per_line + ((width-j-1)>>3)] |=
+ (0x80>>((width-j-1)&7));
+ }
+ }
+ free(data);
+
+ ent = gcalloc(1,sizeof(Entity));
+ ent->type = et_image;
+ ent->u.image.image = gi;
+ memcpy(ent->u.image.transform,transform,sizeof(real[6]));
+ ent->u.image.transform[0] /= width;
+ ent->u.image.transform[3] /= height;
+ ent->u.image.transform[5] += height;
+ ent->u.image.col = fillcol;
+
+ ent->next = ec->splines;
+ ec->splines = ent;
+return( sp-5 );
+}
+#endif
+
+static void HandleType3Reference(IO *wrapper,EntityChar *ec,real transform[6],
+ char *tokbuf, int toksize) {
+ int tok;
+ real dval;
+ char *glyphname;
+ RefChar *ref;
+
+ tok = nextpstoken(wrapper,&dval,tokbuf,toksize);
+ if ( strcmp(tokbuf,"get")!=0 )
+return; /* Hunh. I don't understand it. I give up */
+ tok = nextpstoken(wrapper,&dval,tokbuf,toksize);
+ if ( tok!=pt_namelit )
+return; /* Hunh. I don't understand it. I give up */
+ glyphname = copy(tokbuf);
+ tok = nextpstoken(wrapper,&dval,tokbuf,toksize);
+ if ( strcmp(tokbuf,"get")!=0 )
+return; /* Hunh. I don't understand it. I give up */
+ tok = nextpstoken(wrapper,&dval,tokbuf,toksize);
+ if ( strcmp(tokbuf,"exec")!=0 )
+return; /* Hunh. I don't understand it. I give up */
+
+ /* Ok, it looks very much like a reference to glyphname */
+ ref = chunkalloc(sizeof(RefChar));
+ memcpy(ref->transform,transform,sizeof(ref->transform));
+ ref->sc = (SplineChar *) glyphname;
+ ref->next = ec->refs;
+ ec->refs = ref;
+}
+
+static void _InterpretPS(IO *wrapper, EntityChar *ec, RetStack *rs) {
+ SplinePointList *cur=NULL, *head=NULL;
+ BasePoint current, temp;
+ int tok, i, j;
+ struct psstack stack[100];
+ real dval;
+ int sp=0;
+ SplinePoint *pt;
+ RefChar *ref, *lastref=NULL;
+ real transform[6], t[6];
+ struct graphicsstate {
+ real transform[6];
+ BasePoint current;
+ real linewidth;
+ int linecap, linejoin;
+ Color fore;
+ DashType dashes[DASH_MAX];
+ } gsaves[30];
+ int gsp = 0;
+ int ccnt=0;
+ GrowBuf gb;
+ struct pskeydict dict;
+ struct pskeyval *kv;
+ Color fore=COLOR_INHERITED;
+ int linecap=lc_inherited, linejoin=lj_inherited; real linewidth=WIDTH_INHERITED;
+ DashType dashes[DASH_MAX];
+ int dash_offset = 0;
+ Entity *ent;
+ char *oldloc;
+ int warned = 0;
+ struct garbage tofrees;
+#if !defined(FONTFORGE_CONFIG_TYPE3)
+ char tokbuf[100];
+ const int tokbufsize = 100;
+#else
+ char *tokbuf;
+ const int tokbufsize = 2*65536+10;
+
+ tokbuf = galloc(tokbufsize);
+#endif
+
+ oldloc = setlocale(LC_NUMERIC,"C");
+
+ memset(&gb,'\0',sizeof(GrowBuf));
+ memset(&dict,'\0',sizeof(dict));
+ tofrees.cnt = 0; tofrees.next = NULL;
+
+ transform[0] = transform[3] = 1.0;
+ transform[1] = transform[2] = transform[4] = transform[5] = 0;
+ current.x = current.y = 0;
+ dashes[0] = 0; dashes[1] = DASH_INHERITED;
+
+ if ( ec->fromtype3 ) {
+ /* My type3 fonts have two things pushed on the stack when they */
+ /* start. One is a dictionary, the other a flag (number). If the */
+ /* flag is non-zero then we are a nested call (a reference char) */
+ /* if 0, we're normal. We don't want to do setcachedevice for */
+ /* reference chars. We can't represent a dictionary on the stack */
+ /* so just push two 0s */
+ stack[0].type = stack[1].type = ps_num;
+ stack[0].u.val = stack[1].u.val = 0;
+ sp = 2;
+ }
+
+ while ( (tok = nextpstoken(wrapper,&dval,tokbuf,tokbufsize))!=pt_eof ) {
+ if ( endedstopped(wrapper)) {
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_bool;
+ stack[sp++].u.tf = false;
+ }
+ }
+ if ( sp>sizeof(stack)/sizeof(stack[0])*4/5 ) {
+ /* We don't interpret all of postscript */
+ /* Sometimes we leave garbage on the stack that a real PS interp */
+ /* would have handled. If the stack gets too deep, clean out the */
+ /* oldest entries */
+ sp = forgetstack(stack,sizeof(stack)/sizeof(stack[0])/3,sp );
+ }
+ if ( ccnt>0 ) {
+ if ( tok==pt_closecurly )
+ --ccnt;
+ else if ( tok==pt_opencurly )
+ ++ccnt;
+ if ( ccnt>0 )
+ AddTok(&gb,tokbuf,tok==pt_namelit);
+ else {
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_instr;
+ if ( gb.pt==NULL )
+ stack[sp++].u.str = copy("");
+ else {
+ *gb.pt = '\0'; gb.pt = gb.base;
+ stack[sp++].u.str = copy(gb.base);
+ }
+ }
+ }
+ } else if ( tok==pt_unknown && (kv=lookup(&dict,tokbuf))!=NULL ) {
+ if ( kv->type == ps_instr )
+ pushio(wrapper,NULL,copy(kv->u.str),0);
+ else if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = kv->type;
+ stack[sp++].u = kv->u;
+ if ( kv->type==ps_instr || kv->type==ps_lit || kv->type==ps_string )
+ stack[sp-1].u.str = copy(stack[sp-1].u.str);
+ else if ( kv->type==ps_array || kv->type==ps_dict ) {
+ copyarray(&stack[sp-1].u.dict,&stack[sp-1].u.dict,&tofrees);
+ if ( stack[sp-1].u.dict.is_executable )
+ sp = aload(sp,stack,sizeof(stack)/sizeof(stack[0]),&tofrees);
+ }
+ }
+ } else {
+#if 0 /* /ps{count /foo exch def count copy foo array astore ==}def */
+ /* printstack */
+int ii;
+for ( ii=0; ii<sp; ++ii )
+ if ( stack[ii].type==ps_num )
+ printf( "%g ", stack[ii].u.val );
+ else if ( stack[ii].type==ps_bool )
+ printf( "%s ", stack[ii].u.tf ? "true" : "false" );
+ else if ( stack[ii].type==ps_string )
+ printf( "(%s) ", stack[ii].u.str );
+ else if ( stack[ii].type==ps_lit )
+ printf( "/%s ", stack[ii].u.str );
+ else if ( stack[ii].type==ps_instr )
+ printf( "-%s- ", stack[ii].u.str );
+ else if ( stack[ii].type==ps_mark )
+ printf( "--mark-- " );
+ else if ( stack[ii].type==ps_array )
+ printf( "--[]-- " );
+ else
+ printf( "--" "???" "-- " );
+printf( "-%s-\n", toknames[tok]);
+#endif
+ if ( tok==pt_unknown ) {
+ if ( strcmp(tokbuf,"Cache")==0 ) /* Fontographer type3s */
+ tok = pt_setcachedevice;
+ else if ( strcmp(tokbuf,"SetWid")==0 ) {
+ tok = pt_setcharwidth;
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_num;
+ stack[sp++].u.val = 0;
+ }
+ } else if ( strcmp(tokbuf,"rrcurveto")==0 ) {
+ if ( sp>=6 ) {
+ stack[sp-4].u.val += stack[sp-6].u.val;
+ stack[sp-3].u.val += stack[sp-5].u.val;
+ stack[sp-2].u.val += stack[sp-4].u.val;
+ stack[sp-1].u.val += stack[sp-3].u.val;
+ tok = pt_rcurveto;
+ }
+ } else if ( strcmp(tokbuf,"FillStroke")==0 ) {
+ if ( sp>0 )
+ --sp;
+ tok = linewidth!=WIDTH_INHERITED ? pt_stroke : pt_fill;
+ if ( wrapper->top!=NULL && wrapper->top->ps!=NULL &&
+ linewidth!=WIDTH_INHERITED )
+ linewidth /= 10.0; /* bug in Fontographer's unencrypted type3 fonts */
+ } else if ( strcmp(tokbuf,"SG")==0 ) {
+ if ( linewidth!=WIDTH_INHERITED && sp>1 )
+ stack[sp-2].u.val = stack[sp-1].u.val;
+ if ( sp>0 )
+ --sp;
+ if ( sp>0 )
+ stack[sp-1].u.val = (stack[sp-1].u.val+99)/198.0;
+ tok = pt_setgray;
+ } else if ( strcmp(tokbuf,"ShowInt")==0 ) {
+ /* Fontographer reference */
+ if ( (!wrapper->top->fogns && sp>0 && stack[sp-1].type == ps_num &&
+ stack[sp-1].u.val>=0 && stack[sp-1].u.val<=255 ) ||
+ (wrapper->top->fogns && sp>6 && stack[sp-7].type == ps_num &&
+ stack[sp-7].u.val>=0 && stack[sp-7].u.val<=255 )) {
+ ref = chunkalloc(sizeof(RefChar));
+ memcpy(ref->transform,transform,sizeof(ref->transform));
+ if ( wrapper->top->fogns ) {
+ sp -= 6;
+ t[0] = stack[sp+0].u.val;
+ t[1] = stack[sp+1].u.val;
+ t[2] = stack[sp+2].u.val;
+ t[3] = stack[sp+3].u.val;
+ t[4] = stack[sp+4].u.val;
+ t[5] = stack[sp+5].u.val;
+ MatMultiply(t,ref->transform,ref->transform);
+ wrapper->top->fogns = false;
+ }
+ ref->orig_pos = stack[--sp].u.val;
+ ref->next = ec->refs;
+ ec->refs = ref;
+ continue;
+ }
+ } else if ( strcmp(tokbuf,"togNS_")==0 ) {
+ wrapper->top->fogns = !wrapper->top->fogns;
+ continue;
+ }
+ }
+ switch ( tok ) {
+ case pt_number:
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_num;
+ stack[sp++].u.val = dval;
+ }
+ break;
+ case pt_string:
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_string;
+ stack[sp++].u.str = copyn(tokbuf+1,strlen(tokbuf)-2);
+ }
+ break;
+ case pt_true: case pt_false:
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_bool;
+ stack[sp++].u.tf = tok==pt_true;
+ }
+ break;
+ case pt_opencurly:
+ ++ccnt;
+ break;
+ case pt_closecurly:
+ --ccnt;
+ if ( ccnt<0 ) {
+ goto done;
+ }
+ break;
+ case pt_count:
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_num;
+ stack[sp].u.val = sp;
+ ++sp;
+ }
+ break;
+ case pt_pop:
+ if ( sp>0 ) {
+ --sp;
+ if ( stack[sp].type==ps_string || stack[sp].type==ps_instr ||
+ stack[sp].type==ps_lit )
+ free(stack[sp].u.str);
+ else if ( stack[sp].type==ps_array || stack[sp].type==ps_dict )
+ dictfree(&stack[sp].u.dict);
+ }
+ break;
+ case pt_clear:
+ while ( sp>0 ) {
+ --sp;
+ if ( stack[sp].type==ps_string || stack[sp].type==ps_instr ||
+ stack[sp].type==ps_lit )
+ free(stack[sp].u.str);
+ else if ( stack[sp].type==ps_array || stack[sp].type==ps_dict )
+ dictfree(&stack[sp].u.dict);
+ }
+ break;
+ case pt_dup:
+ if ( sp>0 && sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp] = stack[sp-1];
+ if ( stack[sp].type==ps_string || stack[sp].type==ps_instr ||
+ stack[sp].type==ps_lit )
+ stack[sp].u.str = copy(stack[sp].u.str);
+ /* The following is incorrect behavior, but as I don't do garbage collection */
+ /* and I'm not going to implement reference counts, this will work in most cases */
+ else if ( stack[sp].type==ps_array )
+ copyarray(&stack[sp].u.dict,&stack[sp].u.dict,&tofrees);
+ ++sp;
+ }
+ break;
+ case pt_copy:
+ if ( sp>0 ) {
+ int n = stack[--sp].u.val;
+ if ( n+sp<sizeof(stack)/sizeof(stack[0]) ) {
+ int i;
+ for ( i=0; i<n; ++i ) {
+ stack[sp] = stack[sp-n];
+ if ( stack[sp].type==ps_string || stack[sp].type==ps_instr ||
+ stack[sp].type==ps_lit )
+ stack[sp].u.str = copy(stack[sp].u.str);
+ /* The following is incorrect behavior, but as I don't do garbage collection */
+ /* and I'm not going to implement reference counts, this will work in most cases */
+ else if ( stack[sp].type==ps_array )
+ copyarray(&stack[sp].u.dict,&stack[sp].u.dict,&tofrees);
+ ++sp;
+ }
+ }
+ }
+ break;
+ case pt_exch:
+ if ( sp>1 ) {
+ struct psstack temp;
+ temp = stack[sp-1];
+ stack[sp-1] = stack[sp-2];
+ stack[sp-2] = temp;
+ }
+ break;
+ case pt_roll:
+ sp = rollstack(stack,sp);
+ break;
+ case pt_index:
+ if ( sp>0 ) {
+ i = stack[--sp].u.val;
+ if ( sp>i && i>=0 ) {
+ stack[sp] = stack[sp-i-1];
+ if ( stack[sp].type==ps_string || stack[sp].type==ps_instr ||
+ stack[sp].type==ps_lit )
+ stack[sp].u.str = copy(stack[sp].u.str);
+ /* The following is incorrect behavior, but as I don't do garbage collection */
+ /* and I'm not going to implement reference counts, this will work in most cases */
+ else if ( stack[sp].type==ps_array )
+ copyarray(&stack[sp].u.dict,&stack[sp].u.dict,&tofrees);
+ ++sp;
+ }
+ }
+ break;
+ case pt_add:
+ if ( sp>=2 && stack[sp-1].type==ps_num && stack[sp-2].type==ps_num ) {
+ stack[sp-2].u.val += stack[sp-1].u.val;
+ --sp;
+ }
+ break;
+ case pt_sub:
+ if ( sp>=2 && stack[sp-1].type==ps_num && stack[sp-2].type==ps_num ) {
+ stack[sp-2].u.val -= stack[sp-1].u.val;
+ --sp;
+ }
+ break;
+ case pt_mul:
+ if ( sp>=2 && stack[sp-1].type==ps_num && stack[sp-2].type==ps_num ) {
+ stack[sp-2].u.val *= stack[sp-1].u.val;
+ --sp;
+ }
+ break;
+ case pt_div:
+ if ( sp>=2 && stack[sp-1].type==ps_num && stack[sp-2].type==ps_num ) {
+ if ( stack[sp-1].u.val == 0 )
+ LogError( _("Divide by zero in postscript code.\n" ));
+ else
+ stack[sp-2].u.val /= stack[sp-1].u.val;
+ --sp;
+ }
+ break;
+ case pt_idiv:
+ if ( sp>=2 && stack[sp-1].type==ps_num && stack[sp-2].type==ps_num ) {
+ if ( stack[sp-1].u.val == 0 )
+ LogError( _("Divide by zero in postscript code.\n" ));
+ else
+ stack[sp-2].u.val = ((int) stack[sp-2].u.val) / ((int) stack[sp-1].u.val);
+ --sp;
+ }
+ break;
+ case pt_mod:
+ if ( sp>=2 && stack[sp-1].type==ps_num && stack[sp-2].type==ps_num ) {
+ if ( stack[sp-1].u.val == 0 )
+ LogError( _("Divide by zero in postscript code.\n" ));
+ else
+ stack[sp-2].u.val = ((int) stack[sp-2].u.val) % ((int) stack[sp-1].u.val);
+ --sp;
+ }
+ break;
+ case pt_max:
+ if ( sp>=2 && stack[sp-1].type==ps_num && stack[sp-2].type==ps_num ) {
+ if ( stack[sp-2].u.val < stack[sp-1].u.val )
+ stack[sp-2].u.val = stack[sp-1].u.val;
+ --sp;
+ }
+ break;
+ case pt_min:
+ if ( sp>=2 && stack[sp-1].type==ps_num && stack[sp-2].type==ps_num ) {
+ if ( stack[sp-2].u.val > stack[sp-1].u.val )
+ stack[sp-2].u.val = stack[sp-1].u.val;
+ --sp;
+ }
+ break;
+ case pt_neg:
+ if ( sp>=1 ) {
+ if ( stack[sp-1].type == ps_num )
+ stack[sp-1].u.val = -stack[sp-1].u.val;
+ }
+ break;
+ case pt_abs:
+ if ( sp>=1 ) {
+ if ( stack[sp-1].type == ps_num )
+ if ( stack[sp-1].u.val < 0 )
+ stack[sp-1].u.val = -stack[sp-1].u.val;
+ }
+ break;
+ case pt_round:
+ if ( sp>=1 ) {
+ if ( stack[sp-1].type == ps_num )
+ stack[sp-1].u.val = rint(stack[sp-1].u.val);
+ /* rint isn't quite right, round will take 6.5 to 7, 5.5 to 6, etc. while rint() will take both to 6 */
+ }
+ break;
+ case pt_floor:
+ if ( sp>=1 ) {
+ if ( stack[sp-1].type == ps_num )
+ stack[sp-1].u.val = floor(stack[sp-1].u.val);
+ }
+ break;
+ case pt_ceiling:
+ if ( sp>=1 ) {
+ if ( stack[sp-1].type == ps_num )
+ stack[sp-1].u.val = ceil(stack[sp-1].u.val);
+ }
+ break;
+ case pt_truncate:
+ if ( sp>=1 ) {
+ if ( stack[sp-1].type == ps_num ) {
+ if ( stack[sp-1].u.val<0 )
+ stack[sp-1].u.val = ceil(stack[sp-1].u.val);
+ else
+ stack[sp-1].u.val = floor(stack[sp-1].u.val);
+ }
+ }
+ break;
+ case pt_ne: case pt_eq:
+ if ( sp>=2 ) {
+ if ( stack[sp-2].type!=stack[sp-1].type )
+ stack[sp-2].u.tf = false;
+ else if ( stack[sp-2].type==ps_num )
+ stack[sp-2].u.tf = (stack[sp-2].u.val == stack[sp-1].u.val);
+ else if ( stack[sp-2].type==ps_bool )
+ stack[sp-2].u.tf = (stack[sp-2].u.tf == stack[sp-1].u.tf);
+ else
+ stack[sp-2].u.tf = strcmp(stack[sp-2].u.str,stack[sp-1].u.str)==0 ;
+ stack[sp-2].type = ps_bool;
+ if ( tok==pt_ne ) stack[sp-2].u.tf = !stack[sp-2].u.tf;
+ --sp;
+ }
+ break;
+ case pt_gt: case pt_le: case pt_lt: case pt_ge:
+ if ( sp>=2 ) {
+ if ( stack[sp-2].type!=stack[sp-1].type )
+ stack[sp-2].u.tf = false;
+ else if ( stack[sp-2].type==ps_array )
+ LogError( _("Can't compare arrays\n" ));
+ else {
+ int cmp;
+ if ( stack[sp-2].type==ps_num )
+ cmp = (stack[sp-2].u.val > stack[sp-1].u.val)?1:
+ (stack[sp-2].u.val == stack[sp-1].u.val)?0:-1;
+ else if ( stack[sp-2].type==ps_bool )
+ cmp = (stack[sp-2].u.tf - stack[sp-1].u.tf);
+ else
+ cmp = strcmp(stack[sp-2].u.str,stack[sp-1].u.str);
+ if ( tok==pt_gt )
+ stack[sp-2].u.tf = cmp>0;
+ else if ( tok==pt_lt )
+ stack[sp-2].u.tf = cmp<0;
+ else if ( tok==pt_le )
+ stack[sp-2].u.tf = cmp<=0;
+ else
+ stack[sp-2].u.tf = cmp>=0;
+ }
+ stack[sp-2].type = ps_bool;
+ --sp;
+ }
+ break;
+ case pt_not:
+ if ( sp>=1 ) {
+ if ( stack[sp-1].type == ps_bool )
+ stack[sp-1].u.tf = !stack[sp-1].u.tf;
+ }
+ break;
+ case pt_and:
+ if ( sp>=2 ) {
+ if ( stack[sp-2].type == ps_num )
+ stack[sp-2].u.val = ((int) stack[sp-1].u.val) & (int) stack[sp-1].u.val;
+ else if ( stack[sp-2].type == ps_bool )
+ stack[sp-2].u.tf &= stack[sp-1].u.tf;
+ --sp;
+ }
+ break;
+ case pt_or:
+ if ( sp>=2 ) {
+ if ( stack[sp-2].type == ps_num )
+ stack[sp-2].u.val = ((int) stack[sp-1].u.val) | (int) stack[sp-1].u.val;
+ else if ( stack[sp-2].type == ps_bool )
+ stack[sp-2].u.tf |= stack[sp-1].u.tf;
+ --sp;
+ }
+ break;
+ case pt_xor:
+ if ( sp>=2 ) {
+ if ( stack[sp-2].type == ps_num )
+ stack[sp-2].u.val = ((int) stack[sp-1].u.val) ^ (int) stack[sp-1].u.val;
+ else if ( stack[sp-2].type == ps_bool )
+ stack[sp-2].u.tf ^= stack[sp-1].u.tf;
+ --sp;
+ }
+ break;
+ case pt_exp:
+ if ( sp>=2 && stack[sp-1].type==ps_num && stack[sp-2].type==ps_num ) {
+ stack[sp-2].u.val = pow(stack[sp-2].u.val,stack[sp-1].u.val);
+ --sp;
+ }
+ break;
+ case pt_sqrt:
+ if ( sp>=1 && stack[sp-1].type==ps_num ) {
+ stack[sp-1].u.val = sqrt(stack[sp-1].u.val);
+ }
+ break;
+ case pt_ln:
+ if ( sp>=1 && stack[sp-1].type==ps_num ) {
+ stack[sp-1].u.val = log(stack[sp-1].u.val);
+ }
+ break;
+ case pt_log:
+ if ( sp>=1 && stack[sp-1].type==ps_num ) {
+ stack[sp-1].u.val = log10(stack[sp-1].u.val);
+ }
+ break;
+ case pt_atan:
+ if ( sp>=2 && stack[sp-1].type==ps_num && stack[sp-2].type==ps_num ) {
+ stack[sp-2].u.val = atan2(stack[sp-2].u.val,stack[sp-1].u.val)*
+ 180/3.1415926535897932;
+ --sp;
+ }
+ break;
+ case pt_sin:
+ if ( sp>=1 && stack[sp-1].type==ps_num ) {
+ stack[sp-1].u.val = sin(stack[sp-1].u.val*3.1415926535897932/180);
+ }
+ break;
+ case pt_cos:
+ if ( sp>=1 && stack[sp-1].type==ps_num ) {
+ stack[sp-1].u.val = cos(stack[sp-1].u.val*3.1415926535897932/180);
+ }
+ break;
+ case pt_if:
+ if ( sp>=2 ) {
+ if ( ((stack[sp-2].type == ps_bool && stack[sp-2].u.tf) ||
+ (stack[sp-2].type == ps_num && strstr(stack[sp-1].u.str,"setcachedevice")!=NULL)) &&
+ stack[sp-1].type==ps_instr )
+ pushio(wrapper,NULL,stack[sp-1].u.str,0);
+ if ( stack[sp-1].type==ps_string || stack[sp-1].type==ps_instr || stack[sp-1].type==ps_lit )
+ free(stack[sp-1].u.str);
+ sp -= 2;
+ } else if ( sp==1 && stack[sp-1].type==ps_instr ) {
+ /*This can happen when reading our type3 fonts, we get passed */
+ /* values on the stack which the interpreter knows nothing */
+ /* about, but the interp needs to learn the width of the char */
+ if ( strstr(stack[sp-1].u.str,"setcachedevice")!=NULL ||
+ strstr(stack[sp-1].u.str,"setcharwidth")!=NULL )
+ pushio(wrapper,NULL,stack[sp-1].u.str,0);
+ free(stack[sp-1].u.str);
+ sp = 0;
+ }
+ break;
+ case pt_ifelse:
+ if ( sp>=3 ) {
+ if ( stack[sp-3].type == ps_bool && stack[sp-3].u.tf ) {
+ if ( stack[sp-2].type==ps_instr )
+ pushio(wrapper,NULL,stack[sp-2].u.str,0);
+ } else {
+ if ( stack[sp-1].type==ps_instr )
+ pushio(wrapper,NULL,stack[sp-1].u.str,0);
+ }
+ if ( stack[sp-1].type==ps_string || stack[sp-1].type==ps_instr || stack[sp-1].type==ps_lit )
+ free(stack[sp-1].u.str);
+ if ( stack[sp-2].type==ps_string || stack[sp-2].type==ps_instr || stack[sp-2].type==ps_lit )
+ free(stack[sp-2].u.str);
+ sp -= 3;
+ }
+ break;
+ case pt_for:
+ if ( sp>=4 ) {
+ real init, incr, limit;
+ char *func;
+ int cnt;
+
+ if ( stack[sp-4].type == ps_num && stack[sp-3].type==ps_num &&
+ stack[sp-2].type==ps_num && stack[sp-1].type==ps_instr ) {
+ init = stack[sp-4].u.val;
+ incr = stack[sp-3].u.val;
+ limit = stack[sp-2].u.val;
+ func = stack[sp-1].u.str;
+ sp -= 4;
+ cnt = 0;
+ if ( incr>0 ) {
+ while ( init<=limit ) { ++cnt; init += incr; }
+ } else if ( incr<0 ) {
+ while ( init>=limit ) { ++cnt; init += incr; }
+ }
+ pushio(wrapper,NULL,func,cnt);
+ free(func);
+ }
+ }
+ break;
+ case pt_loop:
+ if ( sp>=1 ) {
+ char *func;
+ int cnt;
+
+ if ( stack[sp-1].type==ps_instr ) {
+ cnt = 0x7fffffff; /* Loop for ever */
+ func = stack[sp-1].u.str;
+ --sp;
+ pushio(wrapper,NULL,func,cnt);
+ free(func);
+ }
+ }
+ break;
+ case pt_repeat:
+ if ( sp>=2 ) {
+ char *func;
+ int cnt;
+
+ if ( stack[sp-2].type==ps_num && stack[sp-1].type==ps_instr ) {
+ cnt = stack[sp-2].u.val;
+ func = stack[sp-1].u.str;
+ sp -= 2;
+ pushio(wrapper,NULL,func,cnt);
+ free(func);
+ }
+ }
+ break;
+ case pt_exit:
+ ioescapeloop(wrapper);
+ break;
+ case pt_stopped:
+ if ( sp>=1 ) {
+ char *func;
+
+ if ( stack[sp-1].type==ps_instr ) {
+ func = stack[sp-1].u.str;
+ --sp;
+ pushio(wrapper,NULL,func,-1);
+ free(func);
+ }
+ }
+ break;
+ case pt_stop:
+ sp = ioescapestopped(wrapper,stack,sp);
+ break;
+ case pt_load:
+ if ( sp>=1 && stack[sp-1].type==ps_lit ) {
+ kv = lookup(&dict,stack[sp-1].u.str);
+ if ( kv!=NULL ) {
+ free( stack[sp-1].u.str );
+ stack[sp-1].type = kv->type;
+ stack[sp-1].u = kv->u;
+ if ( kv->type==ps_instr || kv->type==ps_lit )
+ stack[sp-1].u.str = copy(stack[sp-1].u.str);
+ } else
+ stack[sp-1].type = ps_instr;
+ }
+ break;
+ case pt_def:
+ sp = AddEntry(&dict,stack,sp);
+ break;
+ case pt_bind:
+ /* a noop in this context */
+ break;
+ case pt_setcachedevice:
+ if ( sp>=6 ) {
+ ec->width = stack[sp-6].u.val;
+ ec->vwidth = stack[sp-5].u.val;
+ /* I don't care about the bounding box */
+ sp-=6;
+ }
+ break;
+ case pt_setcharwidth:
+ if ( sp>=2 )
+ ec->width = stack[sp-=2].u.val;
+ break;
+ case pt_translate:
+ if ( sp>=1 && stack[sp-1].type==ps_array )
+ sp = DoMatOp(tok,sp,stack);
+ else if ( sp>=2 ) {
+ transform[4] += stack[sp-2].u.val*transform[0]+stack[sp-1].u.val*transform[2];
+ transform[5] += stack[sp-2].u.val*transform[1]+stack[sp-1].u.val*transform[3];
+ sp -= 2;
+ }
+ break;
+ case pt_scale:
+ if ( sp>=1 && stack[sp-1].type==ps_array )
+ sp = DoMatOp(tok,sp,stack);
+ else if ( sp>=2 ) {
+ transform[0] *= stack[sp-2].u.val;
+ transform[1] *= stack[sp-2].u.val;
+ transform[2] *= stack[sp-1].u.val;
+ transform[3] *= stack[sp-1].u.val;
+ /* transform[4,5] are unchanged */
+ sp -= 2;
+ }
+ break;
+ case pt_rotate:
+ if ( sp>=1 && stack[sp-1].type==ps_array )
+ sp = DoMatOp(tok,sp,stack);
+ else if ( sp>=1 ) {
+ --sp;
+ t[0] = t[3] = cos(stack[sp].u.val);
+ t[1] = sin(stack[sp].u.val);
+ t[2] = -t[1];
+ t[4] = t[5] = 0;
+ MatMultiply(t,transform,transform);
+ }
+ break;
+ case pt_concat:
+ if ( sp>=1 ) {
+ if ( stack[sp-1].type==ps_array ) {
+ if ( stack[sp-1].u.dict.cnt==6 && stack[sp-1].u.dict.entries[0].type==ps_num ) {
+ --sp;
+ t[5] = stack[sp].u.dict.entries[5].u.val;
+ t[4] = stack[sp].u.dict.entries[4].u.val;
+ t[3] = stack[sp].u.dict.entries[3].u.val;
+ t[2] = stack[sp].u.dict.entries[2].u.val;
+ t[1] = stack[sp].u.dict.entries[1].u.val;
+ t[0] = stack[sp].u.dict.entries[0].u.val;
+ dictfree(&stack[sp].u.dict);
+ MatMultiply(t,transform,transform);
+ }
+ }
+ }
+ break;
+ case pt_transform:
+ if ( sp>=1 && stack[sp-1].type==ps_array ) {
+ if ( sp>=3 ) {
+ DoMatTransform(tok,sp,stack);
+ --sp;
+ }
+ } else if ( sp>=2 ) {
+ double x = stack[sp-2].u.val, y = stack[sp-1].u.val;
+ stack[sp-2].u.val = transform[0]*x + transform[1]*y + transform[4];
+ stack[sp-1].u.val = transform[2]*x + transform[3]*y + transform[5];
+ }
+ break;
+ case pt_itransform:
+ if ( sp>=1 && stack[sp-1].type==ps_array ) {
+ if ( sp>=3 ) {
+ DoMatTransform(tok,sp,stack);
+ --sp;
+ }
+ } else if ( sp>=2 ) {
+ double x = stack[sp-2].u.val, y = stack[sp-1].u.val;
+ MatInverse(t,transform);
+ stack[sp-2].u.val = t[0]*x + t[1]*y + t[4];
+ stack[sp-1].u.val = t[2]*x + t[3]*y + t[5];
+ }
+ break;
+ case pt_dtransform:
+ if ( sp>=1 && stack[sp-1].type==ps_array ) {
+ if ( sp>=3 ) {
+ DoMatTransform(tok,sp,stack);
+ --sp;
+ }
+ } else if ( sp>=2 ) {
+ double x = stack[sp-2].u.val, y = stack[sp-1].u.val;
+ stack[sp-2].u.val = transform[0]*x + transform[1]*y;
+ stack[sp-1].u.val = transform[2]*x + transform[3]*y;
+ }
+ break;
+ case pt_idtransform:
+ if ( sp>=1 && stack[sp-1].type==ps_array ) {
+ if ( sp>=3 ) {
+ DoMatTransform(tok,sp,stack);
+ --sp;
+ }
+ } else if ( sp>=2 ) {
+ double x = stack[sp-2].u.val, y = stack[sp-1].u.val;
+ MatInverse(t,transform);
+ stack[sp-2].u.val = t[0]*x + t[1]*y;
+ stack[sp-1].u.val = t[2]*x + t[3]*y;
+ }
+ break;
+ case pt_namelit:
+ if ( strcmp(tokbuf,"CharProcs")==0 && ec!=NULL ) {
+ HandleType3Reference(wrapper,ec,transform,tokbuf,tokbufsize);
+ } else if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_lit;
+ stack[sp++].u.str = copy(tokbuf);
+ }
+ break;
+ case pt_exec:
+ if ( sp>0 && stack[sp-1].type == ps_lit ) {
+ ref = RefCharCreate();
+ ref->sc = (SplineChar *) stack[--sp].u.str;
+ memcpy(ref->transform,transform,sizeof(transform));
+ if ( ec->refs==NULL )
+ ec->refs = ref;
+ else
+ lastref->next = ref;
+ lastref = ref;
+ }
+ break;
+ case pt_newpath:
+ break;
+ case pt_lineto: case pt_rlineto:
+ case pt_moveto: case pt_rmoveto:
+ if ( sp>=2 || tok==pt_newpath ) {
+ if ( tok==pt_rlineto || tok==pt_rmoveto ) {
+ current.x += stack[sp-2].u.val;
+ current.y += stack[sp-1].u.val;
+ sp -= 2;
+ } else if ( tok==pt_lineto || tok == pt_moveto ) {
+ current.x = stack[sp-2].u.val;
+ current.y = stack[sp-1].u.val;
+ sp -= 2;
+ }
+ pt = chunkalloc(sizeof(SplinePoint));
+ Transform(&pt->me,&current,transform);
+ pt->noprevcp = true; pt->nonextcp = true;
+ if ( tok==pt_moveto || tok==pt_rmoveto ) {
+ SplinePointList *spl = chunkalloc(sizeof(SplinePointList));
+ spl->first = spl->last = pt;
+ if ( cur!=NULL )
+ cur->next = spl;
+ else
+ head = spl;
+ cur = spl;
+ } else {
+ if ( cur!=NULL && cur->first!=NULL && (cur->first!=cur->last || cur->first->next==NULL) ) {
+ CheckMake(cur->last,pt);
+ SplineMake3(cur->last,pt);
+ cur->last = pt;
+ }
+ }
+ } else
+ sp = 0;
+ break;
+ case pt_curveto: case pt_rcurveto:
+ if ( sp>=6 ) {
+ if ( tok==pt_rcurveto ) {
+ stack[sp-1].u.val += current.y;
+ stack[sp-3].u.val += current.y;
+ stack[sp-5].u.val += current.y;
+ stack[sp-2].u.val += current.x;
+ stack[sp-4].u.val += current.x;
+ stack[sp-6].u.val += current.x;
+ }
+ current.x = stack[sp-2].u.val;
+ current.y = stack[sp-1].u.val;
+ if ( cur!=NULL && cur->first!=NULL && (cur->first!=cur->last || cur->first->next==NULL) ) {
+ temp.x = stack[sp-6].u.val; temp.y = stack[sp-5].u.val;
+ Transform(&cur->last->nextcp,&temp,transform);
+ cur->last->nonextcp = false;
+ pt = chunkalloc(sizeof(SplinePoint));
+ temp.x = stack[sp-4].u.val; temp.y = stack[sp-3].u.val;
+ Transform(&pt->prevcp,&temp,transform);
+ Transform(&pt->me,&current,transform);
+ pt->nonextcp = true;
+ CheckMake(cur->last,pt);
+ SplineMake3(cur->last,pt);
+ cur->last = pt;
+ }
+ sp -= 6;
+ } else
+ sp = 0;
+ break;
+ case pt_arc: case pt_arcn:
+ if ( sp>=5 ) {
+ real cx, cy, r, a1, a2;
+ cx = stack[sp-5].u.val;
+ cy = stack[sp-4].u.val;
+ r = stack[sp-3].u.val;
+ a1 = stack[sp-2].u.val;
+ a2 = stack[sp-1].u.val;
+ sp -= 5;
+ temp.x = cx+r*cos(a1/180 * 3.1415926535897932);
+ temp.y = cy+r*sin(a1/180 * 3.1415926535897932);
+ if ( temp.x!=current.x || temp.y!=current.y ||
+ !( cur!=NULL && cur->first!=NULL && (cur->first!=cur->last || cur->first->next==NULL) )) {
+ pt = chunkalloc(sizeof(SplinePoint));
+ Transform(&pt->me,&temp,transform);
+ pt->noprevcp = true; pt->nonextcp = true;
+ if ( cur!=NULL && cur->first!=NULL && (cur->first!=cur->last || cur->first->next==NULL) ) {
+ CheckMake(cur->last,pt);
+ SplineMake3(cur->last,pt);
+ cur->last = pt;
+ } else { /* if no current point, then start here */
+ SplinePointList *spl = chunkalloc(sizeof(SplinePointList));
+ spl->first = spl->last = pt;
+ if ( cur!=NULL )
+ cur->next = spl;
+ else
+ head = spl;
+ cur = spl;
+ }
+ }
+ circlearcsto(a1,a2,cx,cy,r,cur,transform,tok==pt_arcn);
+ current.x = cx+r*cos(a2/180 * 3.1415926535897932);
+ current.y = cy+r*sin(a2/180 * 3.1415926535897932);
+ } else
+ sp = 0;
+ break;
+ case pt_arct: case pt_arcto:
+ if ( sp>=5 ) {
+ real x1, y1, x2, y2, r;
+ real xt1, xt2, yt1, yt2;
+ x1 = stack[sp-5].u.val;
+ y1 = stack[sp-4].u.val;
+ x2 = stack[sp-3].u.val;
+ y2 = stack[sp-2].u.val;
+ r = stack[sp-1].u.val;
+ sp -= 5;
+
+ xt1 = xt2 = x1; yt1 = yt2 = y1;
+ if ( cur==NULL || cur->first==NULL || (cur->first==cur->last && cur->first->next!=NULL) )
+ /* Error */;
+ else if ( current.x==x1 && current.y==y1 )
+ /* Error */;
+ else if (( x1==x2 && y1==y2 ) ||
+ (current.x-x1)*(y2-y1) == (x2-x1)*(current.y-y1) ) {
+ /* Degenerate case */
+ current.x = x1; current.y = y1;
+ pt = chunkalloc(sizeof(SplinePoint));
+ Transform(&pt->me,&current,transform);
+ pt->noprevcp = true; pt->nonextcp = true;
+ CheckMake(cur->last,pt);
+ SplineMake3(cur->last,pt);
+ cur->last = pt;
+ } else {
+ real l1 = sqrt((current.x-x1)*(current.x-x1)+(current.y-y1)*(current.y-y1));
+ real l2 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
+ real dx = ((current.x-x1)/l1 + (x2-x1)/l2);
+ real dy = ((current.y-y1)/l1 + (y2-y1)/l2);
+ /* the line from (x1,y1) to (x1+dx,y1+dy) contains the center*/
+ real l3 = sqrt(dx*dx+dy*dy);
+ real cx, cy, t, tmid;
+ real a1, amid, a2;
+ int clockwise = true;
+ dx /= l3; dy /= l3;
+ a1 = atan2(current.y-y1,current.x-x1);
+ a2 = atan2(y2-y1,x2-x1);
+ amid = atan2(dy,dx) - a1;
+ tmid = r/sin(amid);
+ t = r/tan(amid);
+ if ( t<0 ) {
+ clockwise = false;
+ t = -t;
+ tmid = -tmid;
+ }
+ cx = x1+ tmid*dx; cy = y1 + tmid*dy;
+ xt1 = x1 + t*(current.x-x1)/l1; yt1 = y1 + t*(current.y-y1)/l1;
+ xt2 = x1 + t*(x2-x1)/l2; yt2 = y1 + t*(y2-y1)/l2;
+ if ( xt1!=current.x || yt1!=current.y ) {
+ BasePoint temp;
+ temp.x = xt1; temp.y = yt1;
+ pt = chunkalloc(sizeof(SplinePoint));
+ Transform(&pt->me,&temp,transform);
+ pt->noprevcp = true; pt->nonextcp = true;
+ CheckMake(cur->last,pt);
+ SplineMake3(cur->last,pt);
+ cur->last = pt;
+ }
+ a1 = 3*3.1415926535897932/2+a1;
+ a2 = 3.1415926535897932/2+a2;
+ if ( !clockwise ) {
+ a1 += 3.1415926535897932;
+ a2 += 3.1415926535897932;
+ }
+ circlearcsto(a1*180/3.1415926535897932,a2*180/3.1415926535897932,
+ cx,cy,r,cur,transform,clockwise);
+ }
+ if ( tok==pt_arcto ) {
+ stack[sp].type = stack[sp+1].type = stack[sp+2].type = stack[sp+3].type = ps_num;
+ stack[sp++].u.val = xt1;
+ stack[sp++].u.val = yt1;
+ stack[sp++].u.val = xt2;
+ stack[sp++].u.val = yt2;
+ }
+ current.x = xt2; current.y = yt2;
+ }
+ break;
+ case pt_closepath:
+ if ( cur!=NULL && cur->first!=NULL && cur->first!=cur->last ) {
+ if ( RealNear(cur->first->me.x,cur->last->me.x) && RealNear(cur->first->me.y,cur->last->me.y) ) {
+ SplinePoint *oldlast = cur->last;
+ cur->first->prevcp = oldlast->prevcp;
+ cur->first->noprevcp = false;
+ oldlast->prev->from->next = NULL;
+ cur->last = oldlast->prev->from;
+ SplineFree(oldlast->prev);
+ SplinePointFree(oldlast);
+ }
+ CheckMake(cur->last,cur->first);
+ SplineMake3(cur->last,cur->first);
+ cur->last = cur->first;
+ }
+ break;
+ case pt_setlinecap:
+ if ( sp>=1 )
+ linecap = stack[--sp].u.val;
+ break;
+ case pt_setlinejoin:
+ if ( sp>=1 )
+ linejoin = stack[--sp].u.val;
+ break;
+ case pt_setlinewidth:
+ if ( sp>=1 )
+ linewidth = stack[--sp].u.val;
+ break;
+ case pt_setdash:
+ if ( sp>=2 && stack[sp-1].type==ps_num && stack[sp-2].type==ps_array ) {
+ sp -= 2;
+ dash_offset = stack[sp+1].u.val;
+ for ( i=0; i<DASH_MAX && i<stack[sp].u.dict.cnt; ++i )
+ dashes[i] = stack[sp].u.dict.entries[i].u.val;
+ dictfree(&stack[sp].u.dict);
+ }
+ break;
+ case pt_currentlinecap: case pt_currentlinejoin:
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_num;
+ stack[sp++].u.val = tok==pt_currentlinecap?linecap:linejoin;
+ }
+ break;
+ case pt_currentlinewidth:
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_num;
+ stack[sp++].u.val = linewidth;
+ }
+ break;
+ case pt_currentdash:
+ if ( sp+1<sizeof(stack)/sizeof(stack[0]) ) {
+ struct pskeydict dict;
+ for ( i=0; i<DASH_MAX && dashes[i]!=0; ++i );
+ dict.is_executable = 0;
+ dict.cnt = dict.max = i;
+ dict.entries = gcalloc(i,sizeof(struct pskeyval));
+ for ( j=0; j<i; ++j ) {
+ dict.entries[j].type = ps_num;
+ dict.entries[j].u.val = dashes[j];
+ }
+ stack[sp].type = ps_array;
+ stack[sp++].u.dict = dict;
+ stack[sp].type = ps_num;
+ stack[sp++].u.val = dash_offset;
+ }
+ break;
+ case pt_currentgray:
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_num;
+ stack[sp++].u.val = (3*((fore>>16)&0xff) + 6*((fore>>8)&0xff) + (fore&0xff))/2550.;
+ }
+ break;
+ case pt_setgray:
+ if ( sp>=1 ) {
+ fore = stack[--sp].u.val*255;
+ fore *= 0x010101;
+ }
+ break;
+ case pt_setrgbcolor:
+ if ( sp>=3 ) {
+ fore = (((int) (stack[sp-3].u.val*255))<<16) +
+ (((int) (stack[sp-2].u.val*255))<<8) +
+ (int) (stack[sp-1].u.val*255);
+ sp -= 3;
+ }
+ break;
+ case pt_currenthsbcolor: case pt_currentrgbcolor:
+ if ( sp+2<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = stack[sp+1].type = stack[sp+2].type = ps_num;
+ if ( tok==pt_currentrgbcolor ) {
+ stack[sp++].u.val = ((fore>>16)&0xff)/255.;
+ stack[sp++].u.val = ((fore>>8)&0xff)/255.;
+ stack[sp++].u.val = (fore&0xff)/255.;
+ } else {
+ int r=fore>>16, g=(fore>>8)&0xff, bl=fore&0xff;
+ int mx, mn;
+ real h, s, b;
+ mx = mn = r;
+ if ( mx>g ) mn=g; else mx=g;
+ if ( mx<bl ) mx = bl; if ( mn>bl ) mn = bl;
+ b = mx/255.;
+ s = h = 0;
+ if ( mx>0 )
+ s = ((real) (mx-mn))/mx;
+ if ( s!=0 ) {
+ real rdiff = ((real) (mx-r))/(mx-mn);
+ real gdiff = ((real) (mx-g))/(mx-mn);
+ real bdiff = ((real) (mx-bl))/(mx-mn);
+ if ( rdiff==0 )
+ h = bdiff-gdiff;
+ else if ( gdiff==0 )
+ h = 2 + rdiff-bdiff;
+ else
+ h = 4 + gdiff-rdiff;
+ h /= 6;
+ if ( h<0 ) h += 1;
+ }
+ stack[sp++].u.val = h;
+ stack[sp++].u.val = s;
+ stack[sp++].u.val = b;
+ }
+ }
+ break;
+ case pt_sethsbcolor:
+ if ( sp>=3 ) {
+ real h = stack[sp-3].u.val, s = stack[sp-2].u.val, b = stack[sp-1].u.val;
+ int r = 0,g = 0,bl =0 ;
+ if ( s==0 ) /* it's grey */
+ fore = ((int) (b*255)) * 0x010101;
+ else {
+ real sextant = (h-floor(h))*6;
+ real mod = sextant-floor(sextant);
+ real p = b*(1-s), q = b*(1-s*mod), t = b*(1-s*(1-mod));
+ switch( (int) sextant) {
+ case 0:
+ r = b*255.; g = t*255.; bl = p*255.;
+ break;
+ case 1:
+ r = q*255.; g = b*255.; bl = p*255.;
+ break;
+ case 2:
+ r = p*255.; g = b*255.; bl = t*255.;
+ break;
+ case 3:
+ r = p*255.; g = q*255.; bl = b*255.;
+ break;
+ case 4:
+ r = t*255.; g = p*255.; bl = b*255.;
+ break;
+ case 5:
+ r = b*255.; g = p*255.; bl = q*255.;
+ break;
+ }
+ fore = COLOR_CREATE(r,g,bl);
+ }
+ sp -= 3;
+ }
+ break;
+ case pt_currentcmykcolor:
+ if ( sp+3<sizeof(stack)/sizeof(stack[0]) ) {
+ real c,m,y,k;
+ stack[sp].type = stack[sp+1].type = stack[sp+2].type = stack[sp+3].type = ps_num;
+ y = 1.-(fore&0xff)/255.;
+ m = 1.-((fore>>8)&0xff)/255.;
+ c = 1.-((fore>>16)&0xff)/255.;
+ k = y; if ( k>m ) k=m; if ( k>c ) k=c;
+ if ( k!=1 ) {
+ y = (y-k)/(1-k);
+ m = (m-k)/(1-k);
+ c = (c-k)/(1-k);
+ } else
+ y = m = c = 0;
+ stack[sp++].u.val = c;
+ stack[sp++].u.val = m;
+ stack[sp++].u.val = y;
+ stack[sp++].u.val = k;
+ }
+ break;
+ case pt_setcmykcolor:
+ if ( sp>=4 ) {
+ real c=stack[sp-4].u.val,m=stack[sp-3].u.val,y=stack[sp-2].u.val,k=stack[sp-1].u.val;
+ sp -= 4;
+ if ( k==1 )
+ fore = 0x000000;
+ else {
+ if (( y = (1-k)*y+k )<0 ) y=0; else if ( y>1 ) y=1;
+ if (( m = (1-k)*m+k )<0 ) m=0; else if ( m>1 ) m=1;
+ if (( c = (1-k)*c+k )<0 ) c=0; else if ( c>1 ) c=1;
+ fore = ((int) ((1-c)*255.)<<16) |
+ ((int) ((1-m)*255.)<<8) |
+ ((int) ((1-y)*255.));
+ }
+ }
+ break;
+ case pt_currentpoint:
+ if ( sp+1<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_num;
+ stack[sp++].u.val = current.x;
+ stack[sp].type = ps_num;
+ stack[sp++].u.val = current.y;
+ }
+ break;
+ case pt_fill: case pt_stroke:
+ if ( head==NULL && ec->splines!=NULL ) {
+ /* assume they did a "gsave fill grestore stroke" (or reverse)*/
+ ent = ec->splines;
+ if ( tok==pt_stroke ) {
+ ent->u.splines.cap = linecap; ent->u.splines.join = linejoin;
+ ent->u.splines.stroke_width = linewidth;
+ memcpy(ent->u.splines.transform,transform,sizeof(transform));
+ }
+ } else {
+ ent = EntityCreate(head,linecap,linejoin,linewidth,transform);
+ ent->next = ec->splines;
+ ec->splines = ent;
+ }
+ if ( tok==pt_fill )
+ ent->u.splines.fill.col = fore;
+ else
+ ent->u.splines.stroke.col = fore;
+ head = NULL; cur = NULL;
+ break;
+
+ case pt_imagemask:
+#ifdef FONTFORGE_CONFIG_TYPE3
+ i = PSAddImagemask(ec,stack,sp,transform,fore);
+ while ( sp>i ) {
+ --sp;
+ if ( stack[sp].type==ps_string || stack[sp].type==ps_instr ||
+ stack[sp].type==ps_lit )
+ free(stack[sp].u.str);
+ else if ( stack[sp].type==ps_array || stack[sp].type==ps_dict )
+ dictfree(&stack[sp].u.dict);
+ }
+#else
+ LogError( _("This version of FontForge does not support the imagemask operator.\nFor support configure --with-multilayer.\n") );
+ if ( sp>=5 && (stack[sp-1].type==ps_instr || stack[sp-1].type==ps_string))
+ sp -= 5;
+#endif
+ break;
+
+ /* We don't do these right, but at least we'll avoid some errors with this hack */
+ case pt_save: case pt_currentmatrix:
+ /* push some junk on the stack */
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_num;
+ stack[sp++].u.val = 0;
+ }
+ /* Fall through into gsave */;
+ case pt_gsave:
+ if ( gsp<30 ) {
+ memcpy(gsaves[gsp].transform,transform,sizeof(transform));
+ gsaves[gsp].current = current;
+ gsaves[gsp].linewidth = linewidth;
+ gsaves[gsp].linecap = linecap;
+ gsaves[gsp].linejoin = linejoin;
+ gsaves[gsp].fore = fore;
+ ++gsp;
+ /* I should be saving the "current path" too, but that's too hard */
+ }
+ break;
+ case pt_restore: case pt_setmatrix:
+ /* pop some junk off the stack */
+ if ( sp>=1 )
+ --sp;
+ /* Fall through into grestore */;
+ case pt_grestore:
+ if ( gsp>0 ) {
+ --gsp;
+ memcpy(transform,gsaves[gsp].transform,sizeof(transform));
+ current = gsaves[gsp].current;
+ linewidth = gsaves[gsp].linewidth;
+ linecap = gsaves[gsp].linecap;
+ linejoin = gsaves[gsp].linejoin;
+ fore = gsaves[gsp].fore;
+ }
+ break;
+ case pt_null:
+ /* push a 0. I don't handle pointers properly */
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].u.val = 0;
+ stack[sp++].type = ps_num;
+ }
+ break;
+ case pt_currentoverprint:
+ /* push false. I don't handle this properly */
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].u.val = 0;
+ stack[sp++].type = ps_bool;
+ }
+ break;
+ case pt_setoverprint:
+ /* pop one item on stack */
+ if ( sp>=1 )
+ --sp;
+ break;
+ case pt_currentflat:
+ /* push 1.0 (default value). I don't handle this properly */
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].u.val = 1.0;
+ stack[sp++].type = ps_num;
+ }
+ break;
+ case pt_setflat:
+ /* pop one item on stack */
+ if ( sp>=1 )
+ --sp;
+ break;
+ case pt_currentmiterlimit:
+ /* push 10.0 (default value). I don't handle this properly */
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].u.val = 10.0;
+ stack[sp++].type = ps_num;
+ }
+ break;
+ case pt_setmiterlimit:
+ /* pop one item off stack */
+ if ( sp>=1 )
+ --sp;
+ break;
+ case pt_currentpacking:
+ /* push false (default value). I don't handle this properly */
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].u.val = 0;
+ stack[sp++].type = ps_bool;
+ }
+ break;
+ case pt_setpacking:
+ /* pop one item on stack */
+ if ( sp>=1 )
+ --sp;
+ break;
+ case pt_currentstrokeadjust:
+ /* push false (default value). I don't handle this properly */
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].u.val = 0;
+ stack[sp++].type = ps_bool;
+ }
+ break;
+ case pt_setstrokeadjust:
+ /* pop one item on stack */
+ if ( sp>=1 )
+ --sp;
+ break;
+ case pt_currentsmoothness:
+ /* default value is installation dependant. I don't handle this properly */
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].u.val = 1.0;
+ stack[sp++].type = ps_num;
+ }
+ break;
+ case pt_setsmoothness:
+ /* pop one item on stack */
+ if ( sp>=1 )
+ --sp;
+ break;
+ case pt_currentobjectformat:
+ /* default value is installation dependant. I don't handle this properly */
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].u.val = 0.0;
+ stack[sp++].type = ps_num;
+ }
+ break;
+ case pt_setobjectformat:
+ /* pop one item on stack */
+ if ( sp>=1 )
+ --sp;
+ break;
+ case pt_currentglobal: case pt_currentshared:
+ /* push false (default value). I don't handle this properly */
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].u.val = 0;
+ stack[sp++].type = ps_bool;
+ }
+ break;
+ case pt_setglobal:
+ /* pop one item on stack */
+ if ( sp>=1 )
+ --sp;
+ break;
+
+ case pt_openarray: case pt_mark:
+ if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp++].type = ps_mark;
+ }
+ break;
+ case pt_counttomark:
+ for ( i=0; i<sp; ++i )
+ if ( stack[sp-1-i].type==ps_mark )
+ break;
+ if ( i==sp )
+ LogError( _("No mark in counttomark\n") );
+ else if ( sp<sizeof(stack)/sizeof(stack[0]) ) {
+ stack[sp].type = ps_num;
+ stack[sp++].u.val = i;
+ }
+ break;
+ case pt_cleartomark:
+ for ( i=0; i<sp; ++i )
+ if ( stack[sp-1-i].type==ps_mark )
+ break;
+ if ( i==sp )
+ LogError( _("No mark in cleartomark\n") );
+ else {
+ while ( sp>=i ) {
+ --sp;
+ if ( stack[sp].type==ps_string || stack[sp].type==ps_instr ||
+ stack[sp].type==ps_lit )
+ free(stack[sp].u.str);
+ else if ( stack[sp].type==ps_array || stack[sp].type==ps_dict )
+ dictfree(&stack[sp].u.dict);
+ }
+ }
+ break;
+ case pt_closearray:
+ for ( i=0; i<sp; ++i )
+ if ( stack[sp-1-i].type==ps_mark )
+ break;
+ if ( i==sp )
+ LogError( _("No mark in ] (close array)\n") );
+ else {
+ struct pskeydict dict;
+ dict.cnt = dict.max = i;
+ dict.entries = gcalloc(i,sizeof(struct pskeyval));
+ for ( j=0; j<i; ++j ) {
+ dict.entries[j].type = stack[sp-i+j].type;
+ dict.entries[j].u = stack[sp-i+j].u;
+ /* don't need to copy because the things on the stack */
+ /* are being popped (don't need to free either) */
+ }
+ collectgarbage(&tofrees,&dict);
+ sp = sp-i;
+ stack[sp-1].type = ps_array;
+ stack[sp-1].u.dict = dict;
+ }
+ break;
+ case pt_array:
+ if ( sp>=1 && stack[sp-1].type==ps_num ) {
+ struct pskeydict dict;
+ dict.is_executable = 0;
+ dict.cnt = dict.max = stack[sp-1].u.val;
+ dict.entries = gcalloc(dict.cnt,sizeof(struct pskeyval));
+ /* all entries are inited to void */
+ stack[sp-1].type = ps_array;
+ stack[sp-1].u.dict = dict;
+ }
+ break;
+ case pt_aload:
+ sp = aload(sp,stack,sizeof(stack)/sizeof(stack[0]),&tofrees);
+ break;
+ case pt_astore:
+ if ( sp>=1 && stack[sp-1].type==ps_array ) {
+ struct pskeydict dict;
+ --sp;
+ dict = stack[sp].u.dict;
+ if ( sp>=dict.cnt ) {
+ for ( i=dict.cnt-1; i>=0 ; --i ) {
+ --sp;
+ dict.entries[i].type = stack[sp].type;
+ dict.entries[i].u = stack[sp].u;
+ }
+ }
+ stack[sp].type = ps_array;
+ stack[sp].u.dict = dict;
+ ++sp;
+ }
+ break;
+
+ case pt_output: case pt_outputd: case pt_print:
+ if ( sp>=1 ) {
+ --sp;
+ switch ( stack[sp].type ) {
+ case ps_num:
+ printf( "%g", (double) stack[sp].u.val );
+ break;
+ case ps_bool:
+ printf( "%s", stack[sp].u.tf ? "true" : "false" );
+ break;
+ case ps_string: case ps_instr: case ps_lit:
+ if ( tok==pt_outputd )
+ printf( stack[sp].type==ps_lit ? "/" :
+ stack[sp].type==ps_string ? "(" : "{" );
+ printf( "%s", stack[sp].u.str );
+ if ( tok==pt_outputd )
+ printf( stack[sp].type==ps_lit ? "" :
+ stack[sp].type==ps_string ? ")" : "}" );
+ free(stack[sp].u.str);
+ break;
+ case ps_void:
+ printf( "-- void --" );
+ break;
+ case ps_array:
+ if ( tok==pt_outputd ) {
+ printarray(&stack[sp].u.dict);
+ dictfree(&stack[sp].u.dict);
+ break;
+ } /* else fall through */
+ dictfree(&stack[sp].u.dict);
+ default:
+ printf( "-- nostringval --" );
+ break;
+ }
+ if ( tok==pt_output || tok==pt_outputd )
+ printf( "\n" );
+ } else
+ LogError( _("Nothing on stack to print\n") );
+ break;
+
+ case pt_cvi: case pt_cvr:
+ /* I shan't distinguish between integers and reals */
+ if ( sp>=1 && stack[sp-1].type==ps_string ) {
+ double val = strtod(stack[sp-1].u.str,NULL);
+ free(stack[sp-1].u.str);
+ stack[sp-1].u.val = val;
+ stack[sp-1].type = ps_num;
+ }
+ break;
+ case pt_cvlit:
+ if ( sp>=1 ) {
+ if ( stack[sp-1].type==ps_array )
+ stack[sp-1].u.dict.is_executable = false;
+ }
+ case pt_cvn:
+ if ( sp>=1 ) {
+ if ( stack[sp-1].type==ps_string )
+ stack[sp-1].type = ps_lit;
+ }
+ case pt_cvx:
+ if ( sp>=1 ) {
+ if ( stack[sp-1].type==ps_array )
+ stack[sp-1].u.dict.is_executable = true;
+ }
+ break;
+ case pt_cvrs:
+ if ( sp>=3 && stack[sp-1].type==ps_string &&
+ stack[sp-2].type==ps_num &&
+ stack[sp-3].type==ps_num ) {
+ if ( stack[sp-2].u.val==8 )
+ sprintf( stack[sp-1].u.str, "%o", (int) stack[sp-3].u.val );
+ else if ( stack[sp-2].u.val==16 )
+ sprintf( stack[sp-1].u.str, "%X", (int) stack[sp-3].u.val );
+ else /* default to radix 10 no matter what they asked for */
+ sprintf( stack[sp-1].u.str, "%g", (double) stack[sp-3].u.val );
+ stack[sp-3] = stack[sp-1];
+ sp-=2;
+ }
+ break;
+ case pt_cvs:
+ if ( sp>=2 && stack[sp-1].type==ps_string ) {
+ switch ( stack[sp].type ) {
+ case ps_num:
+ sprintf( stack[sp-1].u.str, "%g", (double) stack[sp-2].u.val );
+ break;
+ case ps_bool:
+ sprintf( stack[sp-1].u.str, "%s", stack[sp-2].u.tf ? "true" : "false" );
+ break;
+ case ps_string: case ps_instr: case ps_lit:
+ sprintf( stack[sp-1].u.str, "%s", stack[sp-2].u.str );
+ free(stack[sp].u.str);
+ break;
+ case ps_void:
+ printf( "-- void --" );
+ break;
+ case ps_array:
+ dictfree(&stack[sp].u.dict);
+ default:
+ sprintf( stack[sp-1].u.str, "-- nostringval --" );
+ break;
+ }
+ stack[sp-2] = stack[sp-1];
+ --sp;
+ }
+ break;
+ case pt_stringop: /* the string keyword, not the () thingy */
+ if ( sp>=1 && stack[sp-1].type==ps_num ) {
+ stack[sp-1].type = ps_string;
+ stack[sp-1].u.str = gcalloc(stack[sp-1].u.val+1,1);
+ }
+ break;
+
+ case pt_unknown:
+ if ( !warned ) {
+ LogError( _("Warning: Unable to parse token %s, some features may be lost\n"), tokbuf );
+ warned = true;
+ }
+ break;
+
+ default:
+ break;
+ }}
+ }
+ done:
+ if ( rs!=NULL ) {
+ int i, cnt, j;
+ for ( i=sp-1; i>=0; --i )
+ if ( stack[i].type!=ps_num )
+ break;
+ cnt = sp-1-i;
+ if ( cnt>rs->max ) cnt = rs->max;
+ rs->cnt = cnt;
+ for ( j=i+1; j<sp; ++j )
+ rs->stack[j-i-1] = stack[j].u.val;
+ }
+ freestuff(stack,sp,&dict,&gb,&tofrees);
+ if ( head!=NULL ) {
+ ent = EntityCreate(head,linecap,linejoin,linewidth,transform);
+ ent->next = ec->splines;
+ ec->splines = ent;
+ }
+ ECCatagorizePoints(ec);
+ setlocale(LC_NUMERIC,oldloc);
+#ifdef FONTFORGE_CONFIG_TYPE3
+ free(tokbuf);
+#endif
+}
+
+static void InterpretPS(FILE *ps, char *psstr, EntityChar *ec, RetStack *rs) {
+ IO wrapper;
+
+ memset(&wrapper,0,sizeof(wrapper));
+ pushio(&wrapper,ps,psstr,0);
+ _InterpretPS(&wrapper,ec,rs);
+}
+
+static SplinePointList *EraseStroke(SplineChar *sc,SplinePointList *head,SplinePointList *erase) {
+ SplineSet *spl, *last;
+ SplinePoint *sp;
+
+ if ( head==NULL ) {
+ /* Pointless, but legal */
+ SplinePointListsFree(erase);
+return( NULL );
+ }
+
+ last = NULL;
+ for ( spl=head; spl!=NULL; spl=spl->next ) {
+ for ( sp=spl->first; sp!=NULL; ) {
+ sp->selected = false;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ last = spl;
+ }
+ for ( spl=erase; spl!=NULL; spl=spl->next ) {
+ for ( sp=spl->first; sp!=NULL; ) {
+ sp->selected = true;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ }
+ last->next = erase;
+return( SplineSetRemoveOverlap(sc,head,over_exclude) );
+}
+
+static Entity *EntityReverse(Entity *ent) {
+ Entity *next, *last = NULL;
+
+ while ( ent!=NULL ) {
+ next = ent->next;
+ ent->next = last;
+ last = ent;
+ ent = next;
+ }
+return( last );
+}
+
+#ifdef FONTFORGE_CONFIG_TYPE3
+static SplinePointList *SplinesFromLayers(SplineChar *sc,int *flags, int tostroke) {
+ int layer;
+ SplinePointList *head=NULL, *last, *new, *nlast, *temp, *each, *transed;
+ StrokeInfo si;
+ /*SplineSet *spl;*/
+ int handle_eraser;
+ real inversetrans[6], transform[6];
+ int changed;
+
+ if ( tostroke ) {
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ if ( sc->layers[layer].splines==NULL )
+ continue;
+ else if ( head==NULL )
+ head = sc->layers[layer].splines;
+ else
+ last->next = sc->layers[layer].splines;
+ for ( last = sc->layers[layer].splines; last->next!=NULL; last=last->next );
+ sc->layers[layer].splines = NULL;
+ }
+return( head );
+ }
+
+ if ( *flags==-1 )
+ *flags = PsStrokeFlagsDlg();
+
+ if ( *flags & sf_correctdir ) {
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) if ( sc->layers[layer].dofill )
+ SplineSetsCorrect(sc->layers[layer].splines,&changed);
+ }
+
+ handle_eraser = *flags & sf_handle_eraser;
+
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ if ( sc->layers[layer].dostroke ) {
+ memset(&si,'\0',sizeof(si));
+ si.toobigwarn = *flags & sf_toobigwarn ? 1 : 0;
+ si.join = sc->layers[layer].stroke_pen.linejoin;
+ si.cap = sc->layers[layer].stroke_pen.linecap;
+ si.removeoverlapifneeded = *flags & sf_removeoverlap ? 1 : 0;
+ si.radius = sc->layers[layer].stroke_pen.width/2.0;
+ if ( sc->layers[layer].stroke_pen.width==WIDTH_INHERITED )
+ si.radius = .5;
+ if ( si.cap == lc_inherited ) si.cap = lc_butt;
+ if ( si.join == lc_inherited ) si.join = lj_miter;
+ new = NULL;
+ memcpy(transform,sc->layers[layer].stroke_pen.trans,4*sizeof(real));
+ transform[4] = transform[5] = 0;
+ MatInverse(inversetrans,transform);
+ transed = SplinePointListTransform(SplinePointListCopy(
+ sc->layers[layer].splines),inversetrans,true);
+ for ( each = transed; each!=NULL; each=each->next ) {
+ temp = SplineSetStroke(each,&si,sc);
+ if ( new==NULL )
+ new=temp;
+ else
+ nlast->next = temp;
+ if ( temp!=NULL )
+ for ( nlast=temp; nlast->next!=NULL; nlast=nlast->next );
+ }
+ new = SplinePointListTransform(new,transform,true);
+ SplinePointListsFree(transed);
+ if ( handle_eraser && sc->layers[layer].stroke_pen.brush.col==0xffffff ) {
+ head = EraseStroke(sc,head,new);
+ last = head;
+ if ( last!=NULL )
+ for ( ; last->next!=NULL; last=last->next );
+ } else {
+ if ( head==NULL )
+ head = new;
+ else
+ last->next = new;
+ if ( new!=NULL )
+ for ( last = new; last->next!=NULL; last=last->next );
+ }
+ if ( si.toobigwarn )
+ *flags |= sf_toobigwarn;
+ }
+ if ( sc->layers[layer].dofill ) {
+ if ( handle_eraser && sc->layers[layer].fill_brush.col==0xffffff ) {
+ head = EraseStroke(sc,head,sc->layers[layer].splines);
+ last = head;
+ if ( last!=NULL )
+ for ( ; last->next!=NULL; last=last->next );
+ } else {
+ new = SplinePointListCopy(sc->layers[layer].splines);
+ if ( head==NULL )
+ head = new;
+ else
+ last->next = new;
+ if ( new!=NULL )
+ for ( last = new; last->next!=NULL; last=last->next );
+ }
+ }
+ }
+return( head );
+}
+
+void SFSplinesFromLayers(SplineFont *sf,int tostroke) {
+ /* User has turned off multi-layer, flatten the font */
+ int i, layer;
+ int flags= -1;
+ Layer *new;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ CharView *cv;
+#endif
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ SplineChar *sc = sf->glyphs[i];
+ SplineSet *splines = SplinesFromLayers(sc,&flags,tostroke);
+ RefChar *head=NULL, *last=NULL;
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ if ( head==NULL )
+ head = last = sc->layers[layer].refs;
+ else
+ last->next = sc->layers[layer].refs;
+ if ( last!=NULL )
+ while ( last->next!=NULL ) last = last->next;
+ sc->layers[layer].refs = NULL;
+ }
+ new = gcalloc(2,sizeof(Layer));
+ new[ly_back] = sc->layers[ly_back];
+ memset(&sc->layers[ly_back],0,sizeof(Layer));
+ LayerDefault(&new[ly_fore]);
+ new[ly_fore].splines = splines;
+ new[ly_fore].refs = head;
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ SplinePointListsMDFree(sc,sc->layers[layer].splines);
+ RefCharsFree(sc->layers[layer].refs);
+ ImageListsFree(sc->layers[layer].images);
+ }
+ free(sc->layers);
+ sc->layers = new;
+ sc->layer_cnt = 2;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ for ( cv=sc->views; cv!=NULL; cv=cv->next ) {
+ cv->layerheads[dm_back] = &sc->layers[ly_back];
+ cv->layerheads[dm_fore] = &sc->layers[ly_fore];
+ }
+#endif
+ }
+ SFReinstanciateRefs(sf);
+}
+
+void SFSetLayerWidthsStroked(SplineFont *sf, real strokewidth) {
+ int i;
+ /* We changed from a stroked font to a multilayered font */
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ SplineChar *sc = sf->glyphs[i];
+ sc->layers[ly_fore].dofill = false;
+ sc->layers[ly_fore].dostroke = true;
+ sc->layers[ly_fore].stroke_pen.width = strokewidth;
+ }
+}
+#else
+void SFSplinesFromLayers(SplineFont *sf, int tostroke) {
+}
+#endif
+
+static void EntityCharCorrectDir(EntityChar *ec) {
+ SplineSet *ss;
+ Entity *ent;
+ int changed;
+
+ for ( ent=ec->splines; ent!=NULL; ent = ent->next ) {
+ /* ignore splines which are only stoked, but not filled */
+ if ( ent->type == et_splines && ent->u.splines.fill.col!=0xffffffff ) {
+ /* Correct the direction of each stroke or fill with respect to */
+ /* the splines in it */
+ SplineSetsCorrect(ent->u.splines.splines,&changed);
+ if ( ent->u.splines.fill.col==0xffffff ) {
+ /* If they are filling with white, then assume they mean */
+ /* an internal area that should be drawn backwards */
+ for ( ss=ent->u.splines.splines; ss!=NULL; ss=ss->next )
+ SplineSetReverse(ss);
+ }
+ }
+ }
+}
+
+void EntityDefaultStrokeFill(Entity *ent) {
+ while ( ent!=NULL ) {
+ if ( ent->type == et_splines &&
+ ent->u.splines.stroke.col==0xffffffff &&
+ ent->u.splines.fill.col==0xffffffff ) {
+ SplineSet *spl;
+ int all=1;
+ for ( spl=ent->u.splines.splines; spl!=NULL; spl=spl->next )
+ if ( spl->first->prev!=NULL ) {
+ all = false;
+ break;
+ }
+ if ( all && ent->u.splines.splines!=NULL &&
+ (ent->u.splines.stroke_width==0 || ent->u.splines.stroke_width==WIDTH_INHERITED))
+ ent->u.splines.stroke_width=40; /* random guess */
+ if (ent->u.splines.stroke_width==0 || ent->u.splines.stroke_width==WIDTH_INHERITED)
+ ent->u.splines.fill.col = COLOR_INHERITED;
+ else
+ ent->u.splines.stroke.col = COLOR_INHERITED;
+ }
+ ent = ent->next;
+ }
+}
+
+SplinePointList *SplinesFromEntityChar(EntityChar *ec,int *flags,int is_stroked) {
+ Entity *ent, *next;
+ SplinePointList *head=NULL, *last, *new, *nlast, *temp, *each, *transed;
+ StrokeInfo si;
+ real inversetrans[6];
+ /*SplineSet *spl;*/
+ int handle_eraser = false;
+ int ask = false;
+ nlast = NULL; last = NULL;
+ EntityDefaultStrokeFill(ec->splines);
+
+ if ( !is_stroked ) {
+
+ if ( *flags==-1 ) {
+ for ( ent=ec->splines; ent!=NULL; ent = ent->next ) {
+ if ( ent->type == et_splines &&
+ (ent->u.splines.fill.col==0xffffff ||
+ (ent->u.splines.stroke_width!=0 && ent->u.splines.stroke.col!=0xffffffff))) {
+ ask = true;
+ break;
+ }
+ }
+#ifndef LUA_FF_LIB
+ if ( ask )
+ *flags = PsStrokeFlagsDlg();
+#endif
+ }
+
+ if ( *flags & sf_correctdir ) /* Will happen if flags still unset (-1) */
+ EntityCharCorrectDir(ec);
+
+ handle_eraser = *flags!=-1 && (*flags & sf_handle_eraser);
+ if ( handle_eraser )
+ ec->splines = EntityReverse(ec->splines);
+ }
+
+ for ( ent=ec->splines; ent!=NULL; ent = next ) {
+ next = ent->next;
+ if ( ent->type == et_splines && is_stroked ) {
+ if ( head==NULL )
+ head = ent->u.splines.splines;
+ else
+ last->next = ent->u.splines.splines;
+ if ( ent->u.splines.splines!=NULL )
+ for ( last = ent->u.splines.splines; last->next!=NULL; last=last->next );
+ ent->u.splines.splines = NULL;
+ } else if ( ent->type == et_splines ) {
+ if ( ent->u.splines.stroke.col!=0xffffffff &&
+ (ent->u.splines.fill.col==0xffffffff || ent->u.splines.stroke_width!=0)) {
+ /* What does a stroke width of 0 mean? PS Says minimal width line */
+ /* How do we implement that? Special case: If filled and stroked 0, then */
+ /* ignore the stroke. This idiom is used by MetaPost sometimes and means */
+ /* no stroke */
+ memset(&si,'\0',sizeof(si));
+ si.toobigwarn = *flags & sf_toobigwarn ? 1 : 0;
+ si.join = ent->u.splines.join;
+ si.cap = ent->u.splines.cap;
+ si.removeoverlapifneeded = *flags & sf_removeoverlap ? 1 : 0;
+ si.radius = ent->u.splines.stroke_width/2;
+ if ( ent->u.splines.stroke_width==WIDTH_INHERITED )
+ si.radius = .5;
+ if ( si.cap == lc_inherited ) si.cap = lc_butt;
+ if ( si.join == lc_inherited ) si.join = lj_miter;
+ new = NULL;
+#if 0
+ SSBisectTurners(ent->u.splines.splines);
+#endif
+ MatInverse(inversetrans,ent->u.splines.transform);
+ transed = SplinePointListTransform(SplinePointListCopy(
+ ent->u.splines.splines),inversetrans,true);
+ for ( each = transed; each!=NULL; each=each->next ) {
+ temp = SplineSetStroke(each,&si,ec->sc);
+ if ( new==NULL )
+ new=temp;
+ else
+ nlast->next = temp;
+ if ( temp!=NULL )
+ for ( nlast=temp; nlast->next!=NULL; nlast=nlast->next );
+ }
+ new = SplinePointListTransform(new,ent->u.splines.transform,true);
+ SplinePointListsFree(transed);
+ if ( handle_eraser && ent->u.splines.stroke.col==0xffffff ) {
+ head = EraseStroke(ec->sc,head,new);
+ last = head;
+ if ( last!=NULL )
+ for ( ; last->next!=NULL; last=last->next );
+ } else {
+ if ( head==NULL )
+ head = new;
+ else
+ last->next = new;
+ if ( new!=NULL )
+ for ( last = new; last->next!=NULL; last=last->next );
+ }
+ if ( si.toobigwarn )
+ *flags |= sf_toobigwarn;
+ }
+ /* If they have neither a stroke nor a fill, pretend they said fill */
+ if ( ent->u.splines.fill.col==0xffffffff && ent->u.splines.stroke.col!=0xffffffff )
+ SplinePointListsFree(ent->u.splines.splines);
+ else if ( handle_eraser && ent->u.splines.fill.col==0xffffff ) {
+ head = EraseStroke(ec->sc,head,ent->u.splines.splines);
+ last = head;
+ if ( last!=NULL )
+ for ( ; last->next!=NULL; last=last->next );
+ } else {
+ new = ent->u.splines.splines;
+ if ( head==NULL )
+ head = new;
+ else
+ last->next = new;
+ if ( new!=NULL )
+ for ( last = new; last->next!=NULL; last=last->next );
+ }
+ }
+ free(ent);
+ }
+return( head );
+}
+
+SplinePointList *SplinesFromEntities(Entity *ent,int *flags,int is_stroked) {
+ EntityChar ec;
+
+ memset(&ec,'\0',sizeof(ec));
+ ec.splines = ent;
+return( SplinesFromEntityChar(&ec,flags,is_stroked));
+}
+
+SplinePointList *SplinePointListInterpretPS(FILE *ps,int flags,int is_stroked) {
+ EntityChar ec;
+ SplineChar sc;
+
+ memset(&ec,'\0',sizeof(ec));
+ memset(&sc,0,sizeof(sc)); sc.name = "<No particular character>";
+ ec.sc = &sc;
+ InterpretPS(ps,NULL,&ec,NULL);
+return( SplinesFromEntityChar(&ec,&flags,is_stroked));
+}
+
+Entity *EntityInterpretPS(FILE *ps) {
+ EntityChar ec;
+
+ memset(&ec,'\0',sizeof(ec));
+ InterpretPS(ps,NULL,&ec,NULL);
+return( ec.splines );
+}
+
+static RefChar *revrefs(RefChar *cur) {
+ RefChar *p, *n;
+
+ if ( cur==NULL )
+return( NULL );
+
+ p = NULL;
+ for ( ; (n=cur->next)!=NULL; cur = n ) {
+ cur->next = p;
+ p = cur;
+ }
+ cur->next = p;
+return( cur );
+}
+
+static void SCInterpretPS(FILE *ps,SplineChar *sc, int *flags) {
+ EntityChar ec;
+ real dval;
+ char tokbuf[10];
+ IO wrapper;
+ int ch;
+
+ while ( Isspace(ch = getc(ps)) );
+ ungetc(ch,ps);
+
+ memset(&wrapper,0,sizeof(wrapper));
+ if ( ch!='<' ) {
+ pushio(&wrapper,ps,NULL,0);
+
+ if ( nextpstoken(&wrapper,&dval,tokbuf,sizeof(tokbuf))!=pt_opencurly )
+ LogError( _("We don't understand this font\n") );
+ } else {
+ (void) getc(ps);
+ pushfogio(&wrapper,ps);
+ }
+ memset(&ec,'\0',sizeof(ec));
+ ec.fromtype3 = true;
+ ec.sc = sc;
+ _InterpretPS(&wrapper,&ec,NULL);
+ sc->width = ec.width;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ sc->layer_cnt = 1;
+ SCAppendEntityLayers(sc,ec.splines);
+ if ( sc->layer_cnt==1 ) ++sc->layer_cnt;
+#else
+ sc->layers[ly_fore].splines = SplinesFromEntityChar(&ec,flags,false);
+#endif
+ sc->layers[ly_fore].refs = revrefs(ec.refs);
+ free(wrapper.top);
+}
+
+void PSFontInterpretPS(FILE *ps,struct charprocs *cp,char **encoding) {
+ char tokbuf[100];
+ int tok,i, j;
+ real dval;
+ SplineChar *sc; EntityChar dummy;
+ RefChar *p, *ref, *next;
+ IO wrapper;
+ int flags = -1;
+
+ wrapper.top = NULL;
+ pushio(&wrapper,ps,NULL,0);
+
+ while ( (tok = nextpstoken(&wrapper,&dval,tokbuf,sizeof(tokbuf)))!=pt_eof && tok!=pt_end ) {
+ if ( tok==pt_namelit ) {
+ if ( cp->next>=cp->cnt ) {
+ ++cp->cnt;
+ cp->keys = grealloc(cp->keys,cp->cnt*sizeof(char *));
+ cp->values = grealloc(cp->values,cp->cnt*sizeof(char *));
+ }
+ if ( cp->next<cp->cnt ) {
+ sc = SplineCharCreate();
+ cp->keys[cp->next] = copy(tokbuf);
+ cp->values[cp->next++] = sc;
+ sc->name = copy(tokbuf);
+ SCInterpretPS(ps,sc,&flags);
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ gwwv_progress_next();
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_progress_next();
+#endif
+ } else {
+ memset(&dummy,0,sizeof(dummy));
+ dummy.fromtype3 = true;
+ InterpretPS(ps,NULL,&dummy,NULL);
+ }
+ }
+ }
+ free(wrapper.top);
+
+ /* References were done by name in the postscript. we stored the names in */
+ /* ref->sc (which is a hack). Now look up all those names and replace */
+ /* with the appropriate splinechar. If we can't find anything then throw */
+ /* out the reference */
+ /* Further fixups come later, where all ps refs are fixedup */
+ for ( i=0; i<cp->next; ++i ) {
+ for ( p=NULL, ref=cp->values[i]->layers[ly_fore].refs; ref!=NULL; ref=next ) {
+ char *refname = (char *) (ref->sc);
+ next = ref->next;
+ if ( ref->sc==NULL )
+ refname=encoding[ref->orig_pos];
+ for ( j=0; j<cp->next; ++j )
+ if ( strcmp(cp->keys[j],refname)==0 )
+ break;
+ free(ref->sc); /* a string, not a splinechar */
+ if ( j!=cp->next ) {
+ ref->sc = cp->values[j];
+ SCMakeDependent(cp->values[i],ref->sc);
+ ref->adobe_enc = getAdobeEnc(ref->sc->name);
+ ref->checked = true;
+ p = ref;
+ } else {
+ if ( p==NULL )
+ cp->values[i]->layers[ly_fore].refs = next;
+ else
+ p->next = next;
+ ref->next = NULL;
+ RefCharFree(ref);
+ }
+ }
+ }
+}
+
+/* Slurp up an encoding in the form:
+ /Enc-name [
+ /charname
+ ...
+ ] def
+We're not smart here no: 0 1 255 {1 index exch /.notdef put} for */
+Encoding *PSSlurpEncodings(FILE *file) {
+ char *names[1024];
+ int32 encs[1024];
+ Encoding *item, *head = NULL, *last = NULL;
+ char *encname;
+ char tokbuf[200];
+ IO wrapper;
+ real dval;
+ int i, max, any, enc, codepointsonly;
+ int tok;
+
+ wrapper.top = NULL;
+ pushio(&wrapper,file,NULL,0);
+
+ while ( (tok = nextpstoken(&wrapper,&dval,tokbuf,sizeof(tokbuf)))!=pt_eof ) {
+ encname = NULL;
+ if ( tok==pt_namelit ) {
+ encname = copy(tokbuf);
+ tok = nextpstoken(&wrapper,&dval,tokbuf,sizeof(tokbuf));
+ }
+ if ( tok!=pt_openarray && tok!=pt_opencurly )
+return( head );
+ for ( i=0; i<sizeof(names)/sizeof(names[0]); ++i ) {
+ encs[i] = -1;
+ names[i]=NULL;
+ }
+ codepointsonly = CheckCodePointsComment(&wrapper);
+
+ max = -1; any = 0; i=0;
+ while ( (tok = nextpstoken(&wrapper,&dval,tokbuf,sizeof(tokbuf)))!=pt_eof &&
+ tok!=pt_closearray && tok!=pt_closecurly ) {
+ if ( tok==pt_namelit && i<sizeof(names)/sizeof(names[0]) ) {
+ max = i;
+ if ( strcmp(tokbuf,".notdef")==0 ) {
+ encs[i] = -1;
+ } else if ( (enc=UniFromName(tokbuf,ui_none,&custom))!=-1 ) {
+ encs[i] = enc;
+ /* Used not to do this, but there are several legal names */
+ /* for some slots and people get unhappy (rightly) if we */
+ /* use the wrong one */
+ names[i] = copy(tokbuf);
+ any = 1;
+ } else {
+ names[i] = copy(tokbuf);
+ any = 1;
+ }
+ }
+ ++i;
+ }
+ if ( encname!=NULL ) {
+ tok = nextpstoken(&wrapper,&dval,tokbuf,sizeof(tokbuf));
+ if ( tok==pt_def )
+ /* Good */;
+ }
+ if ( max!=-1 ) {
+ if ( ++max<256 ) max = 256;
+ item = gcalloc(1,sizeof(Encoding));
+ item->enc_name = encname;
+ item->char_cnt = max;
+ item->unicode = galloc(max*sizeof(int32));
+ memcpy(item->unicode,encs,max*sizeof(int32));
+ if ( any && !codepointsonly ) {
+ item->psnames = gcalloc(max,sizeof(char *));
+ memcpy(item->psnames,names,max*sizeof(char *));
+ } else {
+ for ( i=0; i<max; ++i )
+ free(names[i]);
+ }
+ if ( head==NULL )
+ head = item;
+ else
+ last->next = item;
+ last = item;
+ }
+ }
+
+return( head );
+}
+
+int EvaluatePS(char *str,real *stack,int size) {
+ EntityChar ec;
+ RetStack rs;
+
+ memset(&ec,'\0',sizeof(ec));
+ memset(&rs,'\0',sizeof(rs));
+ rs.max = size;
+ rs.stack = stack;
+ InterpretPS(NULL,str,&ec,&rs);
+return( rs.cnt );
+}
+
+static void closepath(SplinePointList *cur, int is_type2) {
+ if ( cur!=NULL && cur->first==cur->last && cur->first->prev==NULL && is_type2 )
+return; /* The "path" is just a single point created by a moveto */
+ /* Probably we're just doing another moveto */
+ if ( cur!=NULL && cur->first!=NULL && cur->first!=cur->last ) {
+ if ( RealNear(cur->first->me.x,cur->last->me.x) && RealNear(cur->first->me.y,cur->last->me.y) ) {
+ SplinePoint *oldlast = cur->last;
+ cur->first->prevcp = oldlast->prevcp;
+ cur->first->noprevcp = false;
+ oldlast->prev->from->next = NULL;
+ cur->last = oldlast->prev->from;
+ chunkfree(oldlast->prev,sizeof(*oldlast));
+ chunkfree(oldlast->hintmask,sizeof(HintMask));
+ chunkfree(oldlast,sizeof(*oldlast));
+ }
+ CheckMake(cur->last,cur->first);
+ SplineMake3(cur->last,cur->first);
+ cur->last = cur->first;
+ }
+}
+
+static void UnblendFree(StemInfo *h ) {
+ while ( h!=NULL ) {
+ chunkfree(h->u.unblended,sizeof(real [2][MmMax]));
+ h->u.unblended = NULL;
+ h = h->next;
+ }
+}
+
+static StemInfo *HintsAppend(StemInfo *to,StemInfo *extra) {
+ StemInfo *h;
+
+ if ( to==NULL )
+return( extra );
+ if ( extra==NULL )
+return( to );
+ for ( h=to; h->next!=NULL; h=h->next );
+ h->next = extra;
+return( to );
+}
+
+static StemInfo *HintNew(double start,double width) {
+ StemInfo *h;
+
+ h = chunkalloc(sizeof(StemInfo));
+ h->start = start;
+ h->width = width;
+return( h );
+}
+
+static void RemapHintMask(HintMask *hm,int mapping[96],int max) {
+ HintMask rpl;
+ int i, mb;
+
+ if ( hm==NULL )
+return;
+
+ if ( max>96 ) max = 96;
+ mb = (max+7)>>3;
+
+ memset(&rpl,0,mb);
+ for ( i=0; i<max; ++i ) if ( (*hm)[i>>3]&(0x80>>(i&0x7)) )
+ rpl[mapping[i]>>3] |= (0x80>>(mapping[i]&0x7));
+ memcpy(hm,&rpl,mb);
+}
+
+static void HintsRenumber(SplineChar *sc) {
+ /* In a type1 font the hints may get added to our hint list in a semi- */
+ /* random order. In an incorrect type2 font the same thing could happen. */
+ /* Force the order to be correct, and then update all masks */
+ int mapping[96];
+ int i, max;
+ StemInfo *h;
+ SplineSet *spl;
+ SplinePoint *sp;
+
+ for ( i=0; i<96; ++i ) mapping[i] = i;
+
+ i = 0;
+ for ( h=sc->hstem; h!=NULL; h=h->next ) {
+ if ( h->hintnumber<96 && i<96 ) {
+ mapping[h->hintnumber] = i;
+ h->hintnumber = i++;
+ }
+ chunkfree(h->u.unblended,sizeof(real [2][MmMax]));
+ h->u.unblended = NULL;
+ }
+ for ( h=sc->vstem; h!=NULL; h=h->next ) {
+ if ( h->hintnumber<96 && i<96 ) {
+ mapping[h->hintnumber] = i;
+ h->hintnumber = i++;
+ }
+ chunkfree(h->u.unblended,sizeof(real [2][MmMax]));
+ h->u.unblended = NULL;
+ }
+ max = i;
+ for ( i=0; i<max; ++i )
+ if ( mapping[i]!=i )
+ break;
+ if ( i==max )
+return; /* Didn't change the order */
+
+ for ( i=0; i<sc->countermask_cnt; ++i )
+ RemapHintMask(&sc->countermasks[i],mapping,max);
+ for ( spl = sc->layers[ly_fore].splines; spl!=NULL; spl=spl->next ) {
+ for ( sp = spl->first; ; ) {
+ RemapHintMask(sp->hintmask,mapping,max);
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ }
+}
+
+int UnblendedCompare(real u1[MmMax], real u2[MmMax], int cnt) {
+ int i;
+
+ for ( i=0; i<cnt; ++i ) {
+ if ( u1[i]!=u2[i] )
+return( u1[i]>u2[i]?1:-1 );
+ }
+return( 0 );
+}
+
+static StemInfo *SameH(StemInfo *old,real start, real width,
+ real unblended[2][MmMax], int instance_count) {
+ StemInfo *sameh;
+
+ if ( instance_count==0 ) {
+ for ( sameh=old; sameh!=NULL; sameh=sameh->next )
+ if ( sameh->start==start && sameh->width==width)
+ break;
+ } else { int j;
+ for ( j=1; j<instance_count; ++j ) {
+ unblended[0][j] += unblended[0][j-1];
+ unblended[1][j] += unblended[1][j-1];
+ }
+ for ( sameh=old; sameh!=NULL; sameh=sameh->next ) {
+ if ( (*sameh->u.unblended)[0] == NULL || (*sameh->u.unblended)[1]==NULL )
+ continue;
+ if ( UnblendedCompare((*sameh->u.unblended)[0],unblended[0],instance_count)==0 &&
+ UnblendedCompare((*sameh->u.unblended)[1],unblended[1],instance_count)==0)
+ break;
+ }
+ }
+return( sameh );
+}
+
+static real Blend(real u[MmMax],struct pscontext *context) {
+ real sum = u[0];
+ int i;
+
+ for ( i=1; i<context->instance_count; ++i )
+ sum += context->blend_values[i]*u[i];
+return( sum );
+}
+
+/* this handles either Type1 or Type2 charstrings. Type2 charstrings have */
+/* more operators than Type1s and the old operators have extended meanings */
+/* (ie. the rlineto operator can produce more than one line). But pretty */
+/* much it's a superset and if we parse for type2 (with a few additions) */
+/* we'll get it right */
+/* Char width is done differently. Moveto starts a newpath. 0xff starts a 16.16*/
+/* number rather than a 32 bit number */
+SplineChar *PSCharStringToSplines(uint8 *type1, int len, struct pscontext *context,
+ struct pschars *subrs, struct pschars *gsubrs, const char *name) {
+ int is_type2 = context->is_type2;
+ real stack[50]; int sp=0, v; /* Type1 stack is about 25 long, Type2 stack is 48 */
+ real transient[32];
+ SplineChar *ret = SplineCharCreate();
+ SplinePointList *cur=NULL, *oldcur=NULL;
+ RefChar *r1, *r2, *rlast=NULL;
+ BasePoint current;
+ real dx, dy, dx2, dy2, dx3, dy3, dx4, dy4, dx5, dy5, dx6, dy6;
+ SplinePoint *pt;
+ /* subroutines may be nested to a depth of 10 */
+ struct substate { unsigned char *type1; int len; int subnum; } pcstack[11];
+ int pcsp=0;
+ StemInfo *hint, *hp;
+ real pops[30];
+ int popsp=0;
+ int base, polarity;
+ real coord;
+ struct pschars *s;
+ int hint_cnt = 0;
+ StemInfo *activeh=NULL, *activev=NULL, *sameh;
+ HintMask *pending_hm = NULL;
+ HintMask *counters[96];
+ int cp=0;
+ real unblended[2][MmMax];
+ int last_was_b1=false, old_last_was_b1;
+
+ dx6=0; /* compiler warning */
+ if ( !is_type2 && context->instance_count>1 )
+ memset(unblended,0,sizeof(unblended));
+
+ ret->name = copy( name );
+ ret->unicodeenc = -1;
+ ret->width = (int16) 0x8000;
+ if ( name==NULL ) name = "unnamed";
+ ret->manualhints = true;
+
+ current.x = current.y = 0;
+ while ( len>0 ) {
+ if ( sp>48 ) {
+ LogError( _("Stack got too big in %s\n"), name );
+ sp = 48;
+ }
+ base = 0;
+ --len;
+ if ( (v = *type1++)>=32 ) {
+ if ( v<=246) {
+ stack[sp++] = v - 139;
+ } else if ( v<=250 ) {
+ stack[sp++] = (v-247)*256 + *type1++ + 108;
+ --len;
+ } else if ( v<=254 ) {
+ stack[sp++] = -(v-251)*256 - *type1++ - 108;
+ --len;
+ } else {
+ int val = (*type1<<24) | (type1[1]<<16) | (type1[2]<<8) | type1[3];
+ stack[sp++] = val;
+ type1 += 4;
+ len -= 4;
+ if ( is_type2 ) {
+#ifndef PSFixed_Is_TTF /* The type2 spec is contradictory. It says this is a */
+ /* two's complement number, but it also says it is a */
+ /* Fixed, which in truetype is not two's complement */
+ /* (mantisa is always unsigned) */
+ stack[sp-1] /= 65536.;
+#else
+ int mant = val&0xffff;
+ stack[sp-1] = (val>>16) + mant/65536.;
+#endif
+ }
+ }
+ } else if ( v==28 ) {
+ stack[sp++] = (short) ((type1[0]<<8) | type1[1]);
+ type1 += 2;
+ len -= 2;
+ /* In the Dict tables of CFF, a 5byte fixed value is prefixed by a */
+ /* 29 code. In Type2 strings the prefix is 255. */
+ } else if ( v==12 ) {
+ old_last_was_b1 = last_was_b1; last_was_b1 = false;
+ v = *type1++;
+ --len;
+ switch ( v ) {
+ case 0: /* dotsection */
+ sp = 0;
+ break;
+ case 1: /* vstem3 */ /* specifies three v hints zones at once */
+ if ( sp<6 ) LogError( _("Stack underflow on vstem3 in %s\n"), name );
+ /* according to the standard, if there is a vstem3 there can't */
+ /* be any vstems, so there can't be any confusion about hint order */
+ /* so we don't need to worry about unblended stuff */
+ sameh = NULL;
+ if ( !is_type2 )
+ sameh = SameH(ret->vstem,stack[0] + ret->lsidebearing,stack[1],
+ unblended,0);
+ hint = HintNew(stack[0] + ret->lsidebearing,stack[1]);
+ hint->hintnumber = sameh!=NULL ? sameh->hintnumber : hint_cnt++;
+ if ( activev==NULL )
+ activev = hp = hint;
+ else {
+ for ( hp=activev; hp->next!=NULL; hp = hp->next );
+ hp->next = hint;
+ hp = hint;
+ }
+ sameh = NULL;
+ if ( !is_type2 )
+ sameh = SameH(ret->vstem,stack[2] + ret->lsidebearing,stack[3],
+ unblended,0);
+ hp->next = HintNew(stack[2] + ret->lsidebearing,stack[3]);
+ hp->next->hintnumber = sameh!=NULL ? sameh->hintnumber : hint_cnt++;
+ if ( !is_type2 )
+ sameh = SameH(ret->vstem,stack[4] + ret->lsidebearing,stack[5],
+ unblended,0);
+ hp->next->next = HintNew(stack[4] + ret->lsidebearing,stack[5]);
+ hp->next->next->hintnumber = sameh!=NULL ? sameh->hintnumber : hint_cnt++;
+ if ( !is_type2 && hp->next->next->hintnumber<96 ) {
+ if ( pending_hm==NULL )
+ pending_hm = chunkalloc(sizeof(HintMask));
+ (*pending_hm)[hint->hintnumber>>3] |= 0x80>>(hint->hintnumber&0x7);
+ (*pending_hm)[hint->next->hintnumber>>3] |= 0x80>>(hint->next->hintnumber&0x7);
+ (*pending_hm)[hint->next->next->hintnumber>>3] |= 0x80>>(hint->next->next->hintnumber&0x7);
+ }
+ hp = hp->next->next;
+ sp = 0;
+ break;
+ case 2: /* hstem3 */ /* specifies three h hints zones at once */
+ if ( sp<6 ) LogError( _("Stack underflow on hstem3 in %s\n"), name );
+ sameh = NULL;
+ if ( !is_type2 )
+ sameh = SameH(ret->hstem,stack[0],stack[1], unblended,0);
+ hint = HintNew(stack[0],stack[1]);
+ hint->hintnumber = sameh!=NULL ? sameh->hintnumber : hint_cnt++;
+ if ( activeh==NULL )
+ activeh = hp = hint;
+ else {
+ for ( hp=activeh; hp->next!=NULL; hp = hp->next );
+ hp->next = hint;
+ hp = hint;
+ }
+ sameh = NULL;
+ if ( !is_type2 )
+ sameh = SameH(ret->hstem,stack[2],stack[3], unblended,0);
+ hp->next = HintNew(stack[2],stack[3]);
+ hp->next->hintnumber = sameh!=NULL ? sameh->hintnumber : hint_cnt++;
+ sameh = NULL;
+ if ( !is_type2 )
+ sameh = SameH(ret->hstem,stack[4],stack[5], unblended,0);
+ hp->next->next = HintNew(stack[4],stack[5]);
+ hp->next->next->hintnumber = sameh!=NULL ? sameh->hintnumber : hint_cnt++;
+ if ( !is_type2 && hp->next->next->hintnumber<96 ) {
+ if ( pending_hm==NULL )
+ pending_hm = chunkalloc(sizeof(HintMask));
+ (*pending_hm)[hint->hintnumber>>3] |= 0x80>>(hint->hintnumber&0x7);
+ (*pending_hm)[hint->next->hintnumber>>3] |= 0x80>>(hint->next->hintnumber&0x7);
+ (*pending_hm)[hint->next->next->hintnumber>>3] |= 0x80>>(hint->next->next->hintnumber&0x7);
+ }
+ hp = hp->next->next;
+ sp = 0;
+ break;
+ case 6: /* seac */ /* build accented characters */
+ seac:
+ if ( sp<5 ) LogError( _("Stack underflow on seac in %s\n"), name );
+ /* stack[0] must be the lsidebearing of the accent. I'm not sure why */
+ r1 = RefCharCreate();
+ r2 = RefCharCreate();
+ r2->transform[0] = 1; r2->transform[3]=1;
+ r2->transform[4] = stack[1] - (stack[0]-ret->lsidebearing);
+ r2->transform[5] = stack[2];
+ /* the translation of the accent here is said to be relative */
+ /* to the origins of the base character. I think they place */
+ /* the origin at the left bearing. And they don't mean the */
+ /* base char at all, they mean the current char's lbearing */
+ /* (which is normally the same as the base char's, except */
+ /* when I has a big accent (like diaerisis) */
+ r1->transform[0] = 1; r1->transform[3]=1;
+ r1->adobe_enc = stack[3];
+ r2->adobe_enc = stack[4];
+ if ( stack[3]<0 || stack[3]>=256 || stack[4]<0 || stack[4]>=256 ) {
+ LogError( _("Reference encoding out of bounds in %s\n"), name );
+ r1->adobe_enc = 0;
+ r2->adobe_enc = 0;
+ }
+ r1->next = r2;
+ if ( rlast!=NULL ) rlast->next = r1;
+ else ret->layers[ly_fore].refs = r1;
+ ret->changedsincelasthinted = true; /* seac glyphs contain no hints */
+ rlast = r2;
+ sp = 0;
+ break;
+ case 7: /* sbw */ /* generalized width/sidebearing command */
+ if ( sp<4 ) LogError( _("Stack underflow on sbw in %s\n"), name );
+ ret->lsidebearing = stack[0];
+ /* stack[1] is lsidebearing y (only for vertical writing styles, CJK) */
+ ret->width = stack[2];
+ /* stack[3] is height (for vertical writing styles, CJK) */
+ sp = 0;
+ break;
+ case 5: case 9: case 14: case 26:
+ if ( sp<1 ) LogError( _("Stack underflow on unary operator in %s\n"), name );
+ switch ( v ) {
+ case 5: stack[sp-1] = (stack[sp-1]==0); break; /* not */
+ case 9: if ( stack[sp-1]<0 ) stack[sp-1]= -stack[sp-1]; break; /* abs */
+ case 14: stack[sp-1] = -stack[sp-1]; break; /* neg */
+ case 26: stack[sp-1] = sqrt(stack[sp-1]); break; /* sqrt */
+ }
+ break;
+ case 3: case 4: case 10: case 11: case 12: case 15: case 24:
+ if ( sp<2 ) LogError( _("Stack underflow on binary operator in %s\n"), name );
+ else switch ( v ) {
+ case 3: /* and */
+ stack[sp-2] = (stack[sp-1]!=0 && stack[sp-2]!=0);
+ break;
+ case 4: /* and */
+ stack[sp-2] = (stack[sp-1]!=0 || stack[sp-2]!=0);
+ break;
+ case 10: /* add */
+ stack[sp-2] += stack[sp-1];
+ break;
+ case 11: /* sub */
+ stack[sp-2] -= stack[sp-1];
+ break;
+ case 12: /* div */
+ stack[sp-2] /= stack[sp-1];
+ break;
+ case 24: /* mul */
+ stack[sp-2] *= stack[sp-1];
+ break;
+ case 15: /* eq */
+ stack[sp-2] = (stack[sp-1]==stack[sp-2]);
+ break;
+ }
+ --sp;
+ break;
+ case 22: /* ifelse */
+ if ( sp<4 ) LogError( _("Stack underflow on ifelse in %s\n"), name );
+ else {
+ if ( stack[sp-2]>stack[sp-1] )
+ stack[sp-4] = stack[sp-3];
+ sp -= 3;
+ }
+ break;
+ case 23: /* random */
+ /* This function returns something (0,1]. It's not clear to me*/
+ /* if rand includes 0 and RAND_MAX or not, but this approach */
+ /* should work no matter what */
+ do {
+ stack[sp] = (rand()/(RAND_MAX-1));
+ } while ( stack[sp]==0 || stack[sp]>1 );
+ ++sp;
+ break;
+ case 16: /* callothersubr */
+ /* stack[sp-1] is the number of the thing to call in the othersubr array */
+ /* stack[sp-2] is the number of args to grab off our stack and put on the */
+ /* real postscript stack */
+ if ( is_type2 )
+ LogError( _("Type2 fonts do not support the Type1 callothersubrs operator") );
+ if ( sp<2 || sp < 2+stack[sp-2] ) {
+ LogError( _("Stack underflow on callothersubr in %s\n"), name );
+ sp = 0;
+ } else {
+ int tot = stack[sp-2], i, k, j;
+ popsp = 0;
+ for ( k=sp-3; k>=sp-2-tot; --k )
+ pops[popsp++] = stack[k];
+ /* othersubrs 0-3 must be interpretted. 0-2 are Flex, 3 is Hint Replacement */
+ /* othersubrs 12,13 are for counter hints. We don't need to */
+ /* do anything to ignore them */
+ /* Subroutines 14-18 are multiple master blenders. We need */
+ /* to pay attention to them too */
+ switch ( (int) stack[sp-1] ) {
+ case 3: {
+ /* when we weren't capabable of hint replacement we */
+ /* punted by putting 3 on the stack (T1 spec page 70) */
+ /* subroutine 3 is a noop */
+ /*pops[popsp-1] = 3;*/
+ ret->manualhints = false;
+ /* We can manage hint substitution from hintmask though*/
+ /* well enough that we needn't clear the manualhints bit */
+ ret->hstem = HintsAppend(ret->hstem,activeh); activeh=NULL;
+ ret->vstem = HintsAppend(ret->vstem,activev); activev=NULL;
+ } break;
+ case 1: {
+ /* Essentially what we want to do is draw a line from */
+ /* where we are at the beginning to where we are at */
+ /* the end. So we save the beginning here (this starts*/
+ /* the flex sequence), we ignore all calls to othersub*/
+ /* 2, and when we get to othersub 0 we put everything*/
+ /* back to where it should be and free up whatever */
+ /* extranious junk we created along the way and draw */
+ /* our line. */
+ /* Let's punt a little less, and actually figure out */
+ /* the appropriate rrcurveto commands and put in a */
+ /* dished serif */
+ /* We should never get here in a type2 font. But we did*/
+ /* this code won't work if we follow type2 conventions*/
+ /* so turn off type2 until we get 0 callothersubrs */
+ /* which marks the end of the flex sequence */
+ is_type2 = false;
+ if ( cur!=NULL ) {
+ oldcur = cur;
+ cur->next = NULL;
+ } else
+ LogError( _("Bad flex subroutine in %s\n"), name );
+ } break;
+ case 2: {
+ /* No op */;
+ } break;
+ case 0: if ( oldcur!=NULL ) {
+ SplinePointList *spl = oldcur->next;
+ if ( spl!=NULL && spl->next!=NULL &&
+ spl->next->next!=NULL &&
+ spl->next->next->next!=NULL &&
+ spl->next->next->next->next!=NULL &&
+ spl->next->next->next->next->next!=NULL &&
+ spl->next->next->next->next->next->next!=NULL ) {
+ BasePoint old_nextcp, mid_prevcp, mid, mid_nextcp,
+ end_prevcp, end;
+ old_nextcp = spl->next->first->me;
+ mid_prevcp = spl->next->next->first->me;
+ mid = spl->next->next->next->first->me;
+ mid_nextcp = spl->next->next->next->next->first->me;
+ end_prevcp = spl->next->next->next->next->next->first->me;
+ end = spl->next->next->next->next->next->next->first->me;
+ cur = oldcur;
+ if ( cur!=NULL && cur->first!=NULL && (cur->first!=cur->last || cur->first->next==NULL) ) {
+ cur->last->nextcp = old_nextcp;
+ cur->last->nonextcp = false;
+ pt = chunkalloc(sizeof(SplinePoint));
+ pt->hintmask = pending_hm; pending_hm = NULL;
+ pt->prevcp = mid_prevcp;
+ pt->me = mid;
+ pt->nextcp = mid_nextcp;
+ /*pt->flex = pops[2];*/
+ CheckMake(cur->last,pt);
+ SplineMake3(cur->last,pt);
+ cur->last = pt;
+ pt = chunkalloc(sizeof(SplinePoint));
+ pt->prevcp = end_prevcp;
+ pt->me = end;
+ pt->nonextcp = true;
+ CheckMake(cur->last,pt);
+ SplineMake3(cur->last,pt);
+ cur->last = pt;
+ } else
+ LogError( _("No previous point on path in curveto from flex 0 in %s\n"), name );
+ } else {
+ /* Um, something's wrong. Let's just draw a line */
+ /* do the simple method, which consists of creating */
+ /* the appropriate line */
+ pt = chunkalloc(sizeof(SplinePoint));
+ pt->me.x = pops[1]; pt->me.y = pops[0];
+ pt->noprevcp = true; pt->nonextcp = true;
+ SplinePointListFree(oldcur->next); oldcur->next = NULL; spl = NULL;
+ cur = oldcur;
+ if ( cur!=NULL && cur->first!=NULL && (cur->first!=cur->last || cur->first->next==NULL) ) {
+ CheckMake(cur->last,pt);
+ SplineMake3(cur->last,pt);
+ cur->last = pt;
+ } else
+ LogError( _("No previous point on path in lineto from flex 0 in %s\n"), name );
+ }
+ --popsp;
+ cur->next = NULL;
+ SplinePointListsFree(spl);
+ oldcur = NULL;
+ } else
+ LogError( _("Bad flex subroutine in %s\n"), name );
+
+ is_type2 = context->is_type2;
+ /* If we found a type2 font with a type1 flex sequence */
+ /* (an illegal idea, but never mind, someone gave us one)*/
+ /* then we had to turn off type2 untill the end of the */
+ /* flex sequence. Which is here */
+ break;
+ case 14: /* results in 1 blended value */
+ case 15: /* results in 2 blended values */
+ case 16: /* results in 3 blended values */
+ case 17: /* results in 4 blended values */
+ case 18: { /* results in 6 blended values */
+ int cnt = stack[sp-1]-13;
+ if ( cnt==5 ) cnt=6;
+ if ( context->instance_count==0 )
+ LogError( _("Attempt to use a multiple master subroutine in a non-mm font in %s.\n"), name );
+ else if ( tot!=cnt*context->instance_count )
+ LogError( _("Multiple master subroutine called with the wrong number of arguments in %s.\n"), name );
+ else {
+ /* Hints need to keep track of the original blends */
+ if ( cnt==1 && !is_type2 ) {
+ if ( sp-2-tot>=1 && (!old_last_was_b1 || stack[0]!=Blend(unblended[1],context))) {
+ unblended[0][0] = stack[0];
+ for ( i=1; i<context->instance_count; ++i )
+ unblended[0][i] = 0;
+ } else
+ memcpy(unblended,unblended+1,context->instance_count*sizeof(real));
+ for ( j=0; j<context->instance_count; ++j )
+ unblended[1][j] = stack[sp-2-tot+j];
+ } else if ( cnt==2 && !is_type2 ) {
+ unblended[0][0] = stack[sp-2-tot];
+ unblended[1][0] = stack[sp-2-tot+1];
+ for ( i=0; i<2; ++i )
+ for ( j=1; j<context->instance_count; ++j )
+ unblended[i][j] = stack[sp-2-tot+2+i*(context->instance_count-1)+(j-1)];
+ }
+ popsp = 0;
+ for ( i=0; i<cnt; ++i ) {
+ double sum = stack[sp-2-tot+ i];
+ for ( j=1; j<context->instance_count; ++j )
+ sum += context->blend_values[j]*
+ stack[sp-2-tot+ cnt +i*(context->instance_count-1)+ j-1];
+ pops[cnt-1-popsp++] = sum;
+ }
+ }
+ } break;
+ }
+ sp = k+1;
+ }
+ break;
+ case 20: /* put */
+ if ( sp<2 ) LogError( _("Too few items on stack for put in %s\n"), name );
+ else if ( stack[sp-1]<0 || stack[sp-1]>=32 ) LogError( _("Reference to transient memory out of bounds in put in %s\n"), name );
+ else {
+ transient[(int)stack[sp-1]] = stack[sp-2];
+ sp -= 2;
+ }
+ break;
+ case 21: /* get */
+ if ( sp<1 ) LogError( _("Too few items on stack for get in %s\n"), name );
+ else if ( stack[sp-1]<0 || stack[sp-1]>=32 ) LogError( _("Reference to transient memory out of bounds in put in %s\n"), name );
+ else
+ stack[sp-1] = transient[(int)stack[sp-1]];
+ break;
+ case 17: /* pop */
+ /* pops something from the postscript stack and pushes it on ours */
+ /* used to get a return value from an othersubr call */
+ /* Bleah. Adobe wants the pops to return the arguments if we */
+ /* don't understand the call. What use is the subroutine then?*/
+ if ( popsp<=0 )
+ LogError( _("Pop stack underflow on pop in %s\n"), name );
+ else
+ stack[sp++] = pops[--popsp];
+ break;
+ case 18: /* drop */
+ if ( sp>0 ) --sp;
+ break;
+ case 27: /* dup */
+ if ( sp>=1 ) {
+ stack[sp] = stack[sp-1];
+ ++sp;
+ }
+ break;
+ case 28: /* exch */
+ if ( sp>=2 ) {
+ real temp = stack[sp-1];
+ stack[sp-1] = stack[sp-2]; stack[sp-2] = temp;
+ }
+ break;
+ case 29: /* index */
+ if ( sp>=1 ) {
+ int index = stack[--sp];
+ if ( index<0 || sp<index+1 )
+ LogError( _("Index out of range in %s\n"), name );
+ else {
+ stack[sp] = stack[sp-index-1];
+ ++sp;
+ }
+ }
+ break;
+ case 30: /* roll */
+ if ( sp>=2 ) {
+ int j = stack[sp-1], N=stack[sp-2];
+ if ( N>sp || j>=N || j<0 || N<0 )
+ LogError( _("roll out of range in %s\n"), name );
+ else if ( j==0 || N==0 )
+ /* No op */;
+ else {
+ real *temp = galloc(N*sizeof(real));
+ int i;
+ for ( i=0; i<N; ++i )
+ temp[i] = stack[sp-N+i];
+ for ( i=0; i<N; ++i )
+ stack[sp-N+i] = temp[(i+j)%N];
+ free(temp);
+ }
+ }
+ break;
+ case 33: /* setcurrentpoint */
+ if ( sp<2 ) LogError( _("Stack underflow on setcurrentpoint in %s\n"), name );
+ else {
+ current.x = stack[0];
+ current.y = stack[1];
+ }
+ sp = 0;
+ break;
+ case 34: /* hflex */
+ case 35: /* flex */
+ case 36: /* hflex1 */
+ case 37: /* flex1 */
+ dy = dy3 = dy4 = dy5 = dy6 = 0;
+ dx = stack[base++];
+ if ( v!=34 )
+ dy = stack[base++];
+ dx2 = stack[base++];
+ dy2 = stack[base++];
+ dx3 = stack[base++];
+ if ( v!=34 && v!=36 )
+ dy3 = stack[base++];
+ dx4 = stack[base++];
+ if ( v!=34 && v!=36 )
+ dy4 = stack[base++];
+ dx5 = stack[base++];
+ if ( v==34 )
+ dy5 = -dy2;
+ else
+ dy5 = stack[base++];
+ switch ( v ) {
+ real xt, yt;
+ case 35: /* flex */
+ dx6 = stack[base++];
+ dy6 = stack[base++];
+ break;
+ case 34: /* hflex */
+ dx6 = stack[base++];
+ break;
+ case 36: /* hflex1 */
+ dx6 = stack[base++];
+ dy6 = -dy-dy2-dy5;
+ break;
+ case 37: /* flex1 */
+ xt = dx+dx2+dx3+dx4+dx5;
+ yt = dy+dy2+dy3+dy4+dy5;
+ if ( xt<0 ) xt= -xt;
+ if ( yt<0 ) yt= -yt;
+ if ( xt>yt ) {
+ dx6 = stack[base++];
+ dy6 = -dy-dy2-dy3-dy4-dy5;
+ } else {
+ dy6 = stack[base++];
+ dx6 = -dx-dx2-dx3-dx4-dx5;
+ }
+ break;
+ }
+ if ( cur!=NULL && cur->first!=NULL && (cur->first!=cur->last || cur->first->next==NULL) ) {
+ current.x = rint((current.x+dx)*1024)/1024; current.y = rint((current.y+dy)*1024)/1024;
+ cur->last->nextcp = current;
+ cur->last->nonextcp = false;
+ current.x = rint((current.x+dx2)*1024)/1024; current.y = rint((current.y+dy2)*1024)/1024;
+ pt = chunkalloc(sizeof(SplinePoint));
+ pt->hintmask = pending_hm; pending_hm = NULL;
+ pt->prevcp = current;
+ current.x = rint((current.x+dx3)*1024)/1024; current.y = rint((current.y+dy3)*1024)/1024;
+ pt->me = current;
+ pt->nonextcp = true;
+ CheckMake(cur->last,pt);
+ SplineMake3(cur->last,pt);
+ cur->last = pt;
+
+ current.x = rint((current.x+dx4)*1024)/1024; current.y = rint((current.y+dy4)*1024)/1024;
+ cur->last->nextcp = current;
+ cur->last->nonextcp = false;
+ current.x = rint((current.x+dx5)*1024)/1024; current.y = rint((current.y+dy5)*1024)/1024;
+ pt = chunkalloc(sizeof(SplinePoint));
+ pt->prevcp = current;
+ current.x = rint((current.x+dx6)*1024)/1024; current.y = rint((current.y+dy6)*1024)/1024;
+ pt->me = current;
+ pt->nonextcp = true;
+ CheckMake(cur->last,pt);
+ SplineMake3(cur->last,pt);
+ cur->last = pt;
+ } else
+ LogError( _("No previous point on path in flex operator in %s\n"), name );
+ sp = 0;
+ break;
+ default:
+ LogError( _("Uninterpreted opcode 12,%d in %s\n"), v, name );
+ break;
+ }
+ } else { last_was_b1 = false; switch ( v ) {
+ case 1: /* hstem */
+ case 18: /* hstemhm */
+ base = 0;
+ if ( sp&1 ) {
+ ret->width = stack[0];
+ base=1;
+ }
+ if ( sp-base<2 )
+ LogError( _("Stack underflow on hstem in %s\n"), name );
+ /* stack[0] is absolute y for start of horizontal hint */
+ /* (actually relative to the y specified as lsidebearing y in sbw*/
+ /* stack[1] is relative y for height of hint zone */
+ coord = 0;
+ hp = NULL;
+ if ( activeh!=NULL )
+ for ( hp=activeh; hp->next!=NULL; hp = hp->next );
+ while ( sp-base>=2 ) {
+ sameh = NULL;
+ if ( !is_type2 )
+ sameh = SameH(ret->hstem,stack[base]+coord,stack[base+1],
+ unblended,context->instance_count);
+ hint = HintNew(stack[base]+coord,stack[base+1]);
+ hint->hintnumber = sameh!=NULL ? sameh->hintnumber : hint_cnt++;
+ if ( !is_type2 && context->instance_count!=0 ) {
+ hint->u.unblended = chunkalloc(sizeof(real [2][MmMax]));
+ memcpy(hint->u.unblended,unblended,sizeof(real [2][MmMax]));
+ }
+ if ( activeh==NULL )
+ activeh = hint;
+ else
+ hp->next = hint;
+ hp = hint;
+ if ( !is_type2 && hint->hintnumber<96 ) {
+ if ( pending_hm==NULL )
+ pending_hm = chunkalloc(sizeof(HintMask));
+ (*pending_hm)[hint->hintnumber>>3] |= 0x80>>(hint->hintnumber&0x7);
+ }
+ base+=2;
+ coord = hint->start+hint->width;
+ }
+ sp = 0;
+ break;
+ case 19: /* hintmask */
+ case 20: /* cntrmask */
+ /* If there's anything on the stack treat it as a vstem hint */
+ base = 0;
+ case 3: /* vstem */
+ case 23: /* vstemhm */
+ if ( cur==NULL || v==3 || v==23 ) {
+ if ( (sp&1) && is_type2 ) {
+ ret->width = stack[0];
+ base=1;
+ }
+ /* I've seen a vstemhm with no arguments. I've no idea what that */
+ /* means. It came right after a hintmask */
+ /* I'm confused about v/hstemhm because the manual says it needs */
+ /* to be used if one uses a hintmask, but that's not what the */
+ /* examples show. Or I'm not understanding. */
+ if ( sp-base<2 && v!=19 && v!=20 )
+ LogError( _("Stack underflow on vstem in %s\n"), name );
+ /* stack[0] is absolute x for start of vertical hint */
+ /* (actually relative to the x specified as lsidebearing in h/sbw*/
+ /* stack[1] is relative x for height of hint zone */
+ coord = ret->lsidebearing;
+ hp = NULL;
+ if ( activev!=NULL )
+ for ( hp=activev; hp->next!=NULL; hp = hp->next );
+ while ( sp-base>=2 ) {
+ sameh = NULL;
+ if ( !is_type2 )
+ sameh = SameH(ret->vstem,stack[base]+coord,stack[base+1],
+ unblended,context->instance_count);
+ hint = HintNew(stack[base]+coord,stack[base+1]);
+ hint->hintnumber = sameh!=NULL ? sameh->hintnumber : hint_cnt++;
+ if ( !is_type2 && context->instance_count!=0 ) {
+ hint->u.unblended = chunkalloc(sizeof(real [2][MmMax]));
+ memcpy(hint->u.unblended,unblended,sizeof(real [2][MmMax]));
+ }
+ if ( !is_type2 && hint->hintnumber<96 ) {
+ if ( pending_hm==NULL )
+ pending_hm = chunkalloc(sizeof(HintMask));
+ (*pending_hm)[hint->hintnumber>>3] |= 0x80>>(hint->hintnumber&0x7);
+ }
+ if ( activev==NULL )
+ activev = hint;
+ else
+ hp->next = hint;
+ hp = hint;
+ base+=2;
+ coord = hint->start+hint->width;
+ }
+ sp = 0;
+ }
+ if ( v==19 || v==20 ) { /* hintmask, cntrmask */
+ int bytes = (hint_cnt+7)/8;
+ if ( bytes>sizeof(HintMask) ) bytes = sizeof(HintMask);
+ if ( v==19 ) {
+ ret->hstem = HintsAppend(ret->hstem,activeh); activeh=NULL;
+ ret->vstem = HintsAppend(ret->vstem,activev); activev=NULL;
+ if ( pending_hm==NULL )
+ pending_hm = chunkalloc(sizeof(HintMask));
+ memcpy(pending_hm,type1,bytes);
+ } else if ( cp<sizeof(counters)/sizeof(counters[0]) ) {
+ counters[cp] = chunkalloc(sizeof(HintMask));
+ memcpy(counters[cp],type1,bytes);
+ ++cp;
+ }
+ type1 += bytes;
+ len -= bytes;
+ }
+ break;
+ case 14: /* endchar */
+ /* endchar is allowed to terminate processing even within a subroutine */
+ if ( (sp&1) && is_type2 )
+ ret->width = stack[0];
+ if ( context->painttype!=2 )
+ closepath(cur,is_type2);
+ pcsp = 0;
+ if ( sp==4 ) {
+ /* In Type2 strings endchar has a depreciated function of doing */
+ /* a seac (which doesn't exist at all). Except enchar takes */
+ /* 4 args and seac takes 5. Bleah */
+ stack[4] = stack[3]; stack[3] = stack[2]; stack[2] = stack[1]; stack[1] = stack[0];
+ stack[0] = 0;
+ sp = 5;
+ goto seac;
+ } else if ( sp==5 ) {
+ /* same as above except also specified a width */
+ stack[0] = 0;
+ goto seac;
+ }
+ /* the docs say that endchar must be the last command in a char */
+ /* (or the last command in a subroutine which is the last in the */
+ /* char) So in theory if there's anything left we should complain*/
+ /* In practice though, the EuroFont has a return statement after */
+ /* the endchar in a subroutine. So we won't try to catch that err*/
+ /* and just stop. */
+ /* Adobe says it's not an error, but I can't understand their */
+ /* logic */
+ goto done;
+ break;
+ case 13: /* hsbw (set left sidebearing and width) */
+ if ( sp<2 ) LogError( _("Stack underflow on hsbw in %s\n"), name );
+ ret->lsidebearing = stack[0];
+ current.x = stack[0]; /* sets the current point too */
+ ret->width = stack[1];
+ sp = 0;
+ break;
+ case 9: /* closepath */
+ sp = 0;
+ closepath(cur,is_type2);
+ break;
+ case 21: /* rmoveto */
+ case 22: /* hmoveto */
+ case 4: /* vmoveto */
+ if ( is_type2 ) {
+ if ( (v==21 && sp==3) || (v!=21 && sp==2)) {
+ /* Character's width may be specified on the first moveto */
+ ret->width = stack[0];
+ stack[0] = stack[1]; stack[1] = stack[2]; --sp;
+ }
+ if ( context->painttype!=2 )
+ closepath(cur,true);
+ }
+#if 0 /* This doesn't work. It breaks type1 flex hinting. */
+ /* There's now a special hack just before returning which closes any */
+ /* open paths */
+ else if ( cur!=NULL && cur->first->prev==NULL )
+ closepath(cur,false); /* Even in type1 fonts closepath is optional */
+#endif
+ case 5: /* rlineto */
+ case 6: /* hlineto */
+ case 7: /* vlineto */
+ polarity = 0;
+ base = 0;
+ while ( base<sp ) {
+ dx = dy = 0;
+ if ( v==5 || v==21 ) {
+ if ( sp<base+2 ) {
+ LogError( _("Stack underflow on rlineto/rmoveto in %s\n"), name );
+ break;
+ }
+ dx = stack[base++];
+ dy = stack[base++];
+ } else if ( (v==6 && !(polarity&1)) || (v==7 && (polarity&1)) || v==22 ) {
+ if ( sp<=base ) {
+ LogError( _("Stack underflow on hlineto/hmoveto in %s\n"), name );
+ break;
+ }
+ dx = stack[base++];
+ } else /*if ( (v==7 && !(parity&1)) || (v==6 && (parity&1) || v==4 )*/ {
+ if ( sp<=base ) {
+ LogError( _("Stack underflow on vlineto/vmoveto in %s\n"), name );
+ break;
+ }
+ dy = stack[base++];
+ }
+ ++polarity;
+ current.x = rint((current.x+dx)*1024)/1024; current.y = rint((current.y+dy)*1024)/1024;
+ pt = chunkalloc(sizeof(SplinePoint));
+ pt->hintmask = pending_hm; pending_hm = NULL;
+ pt->me = current;
+ pt->noprevcp = true; pt->nonextcp = true;
+ if ( v==4 || v==21 || v==22 ) {
+ if ( cur!=NULL && cur->first==cur->last && cur->first->prev==NULL && is_type2 ) {
+ /* Two adjacent movetos should not create single point paths */
+ cur->first->me = current;
+ SplinePointFree(pt);
+ } else {
+ SplinePointList *spl = chunkalloc(sizeof(SplinePointList));
+ spl->first = spl->last = pt;
+ if ( cur!=NULL )
+ cur->next = spl;
+ else
+ ret->layers[ly_fore].splines = spl;
+ cur = spl;
+ }
+ break;
+ } else {
+ if ( cur!=NULL && cur->first!=NULL && (cur->first!=cur->last || cur->first->next==NULL) ) {
+ CheckMake(cur->last,pt);
+ SplineMake3(cur->last,pt);
+ cur->last = pt;
+ } else
+ LogError( _("No previous point on path in lineto in %s\n"), name );
+ if ( !is_type2 )
+ break;
+ }
+ }
+ sp = 0;
+ break;
+ case 25: /* rlinecurve */
+ base = 0;
+ while ( sp>base+6 ) {
+ current.x = rint((current.x+stack[base++])*1024)/1024; current.y = rint((current.y+stack[base++])*1024)/1024;
+ if ( cur!=NULL ) {
+ pt = chunkalloc(sizeof(SplinePoint));
+ pt->hintmask = pending_hm; pending_hm = NULL;
+ pt->me = current;
+ pt->noprevcp = true; pt->nonextcp = true;
+ CheckMake(cur->last,pt);
+ SplineMake3(cur->last,pt);
+ cur->last = pt;
+ }
+ }
+ case 24: /* rcurveline */
+ case 8: /* rrcurveto */
+ case 31: /* hvcurveto */
+ case 30: /* vhcurveto */
+ case 27: /* hhcurveto */
+ case 26: /* vvcurveto */
+ polarity = 0;
+ while ( sp>base+2 ) {
+ dx = dy = dx2 = dy2 = dx3 = dy3 = 0;
+ if ( v==8 || v==25 || v==24 ) {
+ if ( sp<6+base ) {
+ LogError( _("Stack underflow on rrcurveto in %s\n"), name );
+ base = sp;
+ } else {
+ dx = stack[base++];
+ dy = stack[base++];
+ dx2 = stack[base++];
+ dy2 = stack[base++];
+ dx3 = stack[base++];
+ dy3 = stack[base++];
+ }
+ } else if ( v==27 ) { /* hhcurveto */
+ if ( sp<4+base ) {
+ LogError( _("Stack underflow on hhcurveto in %s\n"), name );
+ base = sp;
+ } else {
+ if ( (sp-base)&1 ) dy = stack[base++];
+ dx = stack[base++];
+ dx2 = stack[base++];
+ dy2 = stack[base++];
+ dx3 = stack[base++];
+ }
+ } else if ( v==26 ) { /* vvcurveto */
+ if ( sp<4+base ) {
+ LogError( _("Stack underflow on hhcurveto in %s\n"), name );
+ base = sp;
+ } else {
+ if ( (sp-base)&1 ) dx = stack[base++];
+ dy = stack[base++];
+ dx2 = stack[base++];
+ dy2 = stack[base++];
+ dy3 = stack[base++];
+ }
+ } else if ( (v==31 && !(polarity&1)) || (v==30 && (polarity&1)) ) {
+ if ( sp<4+base ) {
+ LogError( _("Stack underflow on hvcurveto in %s\n"), name );
+ base = sp;
+ } else {
+ dx = stack[base++];
+ dx2 = stack[base++];
+ dy2 = stack[base++];
+ dy3 = stack[base++];
+ if ( sp==base+1 )
+ dx3 = stack[base++];
+ }
+ } else /*if ( (v==30 && !(polarity&1)) || (v==31 && (polarity&1)) )*/ {
+ if ( sp<4+base ) {
+ LogError( _("Stack underflow on vhcurveto in %s\n"), name );
+ base = sp;
+ } else {
+ dy = stack[base++];
+ dx2 = stack[base++];
+ dy2 = stack[base++];
+ dx3 = stack[base++];
+ if ( sp==base+1 )
+ dy3 = stack[base++];
+ }
+ }
+ ++polarity;
+ if ( cur!=NULL && cur->first!=NULL && (cur->first!=cur->last || cur->first->next==NULL) ) {
+ current.x = rint((current.x+dx)*1024)/1024; current.y = rint((current.y+dy)*1024)/1024;
+ cur->last->nextcp = current;
+ cur->last->nonextcp = false;
+ current.x = rint((current.x+dx2)*1024)/1024; current.y = rint((current.y+dy2)*1024)/1024;
+ pt = chunkalloc(sizeof(SplinePoint));
+ pt->hintmask = pending_hm; pending_hm = NULL;
+ pt->prevcp = current;
+ current.x = rint((current.x+dx3)*1024)/1024; current.y = rint((current.y+dy3)*1024)/1024;
+ pt->me = current;
+ pt->nonextcp = true;
+ CheckMake(cur->last,pt);
+ SplineMake3(cur->last,pt);
+ cur->last = pt;
+ } else
+ LogError( _("No previous point on path in curveto in %s\n"), name );
+ }
+ if ( v==24 ) {
+ current.x = rint((current.x+stack[base++])*1024)/1024; current.y = rint((current.y+stack[base++])*1024)/1024;
+ if ( cur!=NULL ) { /* In legal code, cur can't be null here, but I got something illegal... */
+ pt = chunkalloc(sizeof(SplinePoint));
+ pt->hintmask = pending_hm; pending_hm = NULL;
+ pt->me = current;
+ pt->noprevcp = true; pt->nonextcp = true;
+ CheckMake(cur->last,pt);
+ SplineMake3(cur->last,pt);
+ cur->last = pt;
+ }
+ }
+ sp = 0;
+ break;
+ case 29: /* callgsubr */
+ case 10: /* callsubr */
+ /* stack[sp-1] contains the number of the subroutine to call */
+ if ( sp<1 ) {
+ LogError( _("Stack underflow on callsubr in %s\n"), name );
+ break;
+ } else if ( pcsp>10 ) {
+ LogError( _("Too many subroutine calls in %s\n"), name );
+ break;
+ }
+ s=subrs; if ( v==29 ) s = gsubrs;
+ if ( s!=NULL ) stack[sp-1] += s->bias;
+ /* Type2 subrs have a bias that must be added to the subr-number */
+ /* Type1 subrs do not. We set the bias on them to 0 */
+ if ( s==NULL || stack[sp-1]>=s->cnt || stack[sp-1]<0 ||
+ s->values[(int) stack[sp-1]]==NULL )
+ LogError( _("Subroutine number out of bounds in %s\n"), name );
+ else {
+ pcstack[pcsp].type1 = type1;
+ pcstack[pcsp].len = len;
+ pcstack[pcsp].subnum = stack[sp-1];
+ ++pcsp;
+ type1 = s->values[(int) stack[sp-1]];
+ len = s->lens[(int) stack[sp-1]];
+ }
+ if ( --sp<0 ) sp = 0;
+ break;
+ case 11: /* return */
+ /* return from a subr outine */
+ if ( pcsp<1 ) LogError( _("return when not in subroutine in %s\n"), name );
+ else {
+ --pcsp;
+ type1 = pcstack[pcsp].type1;
+ len = pcstack[pcsp].len;
+ }
+ break;
+ case 16: { /* blend -- obsolete type 2 multiple master operator */
+ int cnt,i,j;
+ if ( context->instance_count==0 )
+ LogError( _("Attempt to use a multiple master subroutine in a non-mm font.\n") );
+ else if ( sp<1 || sp<context->instance_count*stack[sp-1]+1 )
+ LogError( _("Too few items on stack for blend in %s\n"), name );
+ else {
+ if ( !context->blend_warn ) {
+ LogError( _("Use of obsolete blend operator.\n") );
+ context->blend_warn = true;
+ }
+ cnt = stack[sp-1];
+ sp -= context->instance_count*stack[sp-1]+1;
+ for ( i=0; i<cnt; ++i ) {
+ for ( j=1; j<context->instance_count; ++j )
+ stack[sp+i] += context->blend_values[j]*stack[sp+
+ cnt+ i*(context->instance_count-1)+ j-1];
+ }
+ /* there will always be fewer pushes than there were pops */
+ /* so I don't bother to check the stack */
+ sp += cnt;
+ }
+ }
+ break;
+ default:
+ LogError( _("Uninterpreted opcode %d in %s\n"), v, name );
+ break;
+ }}
+ }
+ done:
+ if ( pcsp!=0 )
+ LogError( _("end of subroutine reached with no return in %s\n"), name );
+ SCCatagorizePoints(ret);
+
+ ret->hstem = HintsAppend(ret->hstem,activeh); activeh=NULL;
+ ret->vstem = HintsAppend(ret->vstem,activev); activev=NULL;
+
+ if ( cp!=0 ) { int i;
+ ret->countermasks = galloc(cp*sizeof(HintMask));
+ ret->countermask_cnt = cp;
+ for ( i=0; i<cp; ++i ) {
+ memcpy(&ret->countermasks[i],counters[i],sizeof(HintMask));
+ chunkfree(counters[i],sizeof(HintMask));
+ }
+ }
+
+ /* Even in type1 fonts all paths should be closed. But if we close them at*/
+ /* the obvious moveto, that breaks flex hints. So we have a hack here at */
+ /* the end which closes any open paths. */
+ /* If we do have a PaintType 2 font, then presumably the difference between*/
+ /* open and closed paths matters */
+ if ( !is_type2 && !context->painttype )
+ for ( cur = ret->layers[ly_fore].splines; cur!=NULL; cur = cur->next ) if ( cur->first->prev==NULL ) {
+ CheckMake(cur->last,cur->first);
+ SplineMake3(cur->last,cur->first);
+ cur->last = cur->first;
+ }
+
+ /* Oh, I see. PS and TT disagree on which direction to use, so Fontographer*/
+ /* chose the TT direction and we must reverse postscript */
+ for ( cur = ret->layers[ly_fore].splines; cur!=NULL; cur = cur->next )
+ SplineSetReverse(cur);
+ if ( ret->hstem==NULL && ret->vstem==NULL )
+ ret->manualhints = false;
+ if ( !is_type2 && context->instance_count!=0 ) {
+ UnblendFree(ret->hstem);
+ UnblendFree(ret->vstem);
+ }
+ ret->hstem = HintCleanup(ret->hstem,true,context->instance_count);
+ ret->vstem = HintCleanup(ret->vstem,true,context->instance_count);
+ SCGuessHHintInstancesList(ret);
+ SCGuessVHintInstancesList(ret);
+ ret->hconflicts = StemListAnyConflicts(ret->hstem);
+ ret->vconflicts = StemListAnyConflicts(ret->vstem);
+ if ( context->instance_count==1 && !ret->hconflicts && !ret->vconflicts )
+ SCClearHintMasks(ret,false);
+ HintsRenumber(ret);
+ if ( name!=NULL && strcmp(name,".notdef")!=0 )
+ ret->widthset = true;
+return( ret );
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/pua.c b/Build/source/libs/luafontforge/fontforge/fontforge/pua.c
new file mode 100644
index 00000000000..3e7582829bf
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/pua.c
@@ -0,0 +1,1612 @@
+/* A number of encodings use the public use area to map to glyphs that are */
+/* defined in planes other than the BMP (chinese), or just multiple encodings*/
+/* for the same glyph (ams) */
+
+/* These data are taken from http://www.ams.org/STIX/bnb/stix-tbl.asc-2003-10-10 */
+const int amspua[] = {
+/* E000 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E008 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E010 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E018 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E020 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E028 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E030 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E038 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E040 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E048 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E050 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E058 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E060 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E068 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E070 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E078 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E080 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E088 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E090 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E098 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E0A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E0A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E0B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E0B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E0C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E0C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E0D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E0D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E0E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E0E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E0F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E0F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E100 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E108 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E110 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E118 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E120 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E128 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E130 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E138 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E140 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E148 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E150 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E158 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E160 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E168 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E170 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E178 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E180 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E188 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E190 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E198 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E1A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E1A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E1B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E1B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E1C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E1C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E1D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E1D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E1E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E1E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E1F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E1F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E200 */ 0x027f8, 0x027f5, 0x027fa, 0x027f7, 0x027f9, 0x027f6, 0x0290e, 0x0290f,
+/* E208 */ 0x027fc, 0x02910, 0x02926, 0x02925, 0x02923, 0x02924, 0x02928, 0x02929,
+/* E210 */ 0x0292a, 0x02927, 0x02905, 0x0, 0x0297c, 0x0297d, 0x021f5, 0x0296f,
+/* E218 */ 0x0296e, 0x02937, 0x02936, 0x0, 0x02933, 0x0, 0x02945, 0x02946,
+/* E220 */ 0x0291f, 0x02920, 0x0291d, 0x0291e, 0x02964, 0x02962, 0x02963, 0x02965,
+/* E228 */ 0x0294b, 0x0294a, 0x02968, 0x02966, 0x02967, 0x02969, 0x0296a, 0x0296d,
+/* E230 */ 0x0296c, 0x0296b, 0x02192, 0x02190, 0x02972, 0x02975, 0x02971, 0x02949,
+/* E238 */ 0x02911, 0x02916, 0x0291a, 0x0291c, 0x02919, 0x0291b, 0x02938, 0x02939,
+/* E240 */ 0x02948, 0x021fe, 0x021fd, 0x021ff, 0x021dd, 0x02904, 0x02903, 0x02902,
+/* E248 */ 0x0237c, 0x0293c, 0x0293d, 0x0297e, 0x0297f, 0x02974, 0x02973, 0x02af0,
+/* E250 */ 0x02aef, 0x02a3f, 0x0, 0x0, 0x02a00, 0x02a01, 0x02a02, 0x02a06,
+/* E258 */ 0x02a04, 0x02a3c, 0x02a25, 0x02a2a, 0x02a2d, 0x02a2e, 0x02a34, 0x02a35,
+/* E260 */ 0x029b5, 0x02a40, 0x02abd, 0x02abe, 0x02a33, 0x02a5f, 0x02a22, 0x02a72,
+/* E268 */ 0x02a71, 0x02a27, 0x02a23, 0x02a24, 0x02a26, 0x02a30, 0x02a46, 0x02a47,
+/* E270 */ 0x02a48, 0x02a49, 0x02a4a, 0x02a4b, 0x0, 0x0, 0x0, 0x0,
+/* E278 */ 0x02a4c, 0x02a4d, 0x02a50, 0x02a39, 0x02a3a, 0x02a3b, 0x029cd, 0x029c4,
+/* E280 */ 0x029c5, 0x02a44, 0x02a45, 0x02a42, 0x02a43, 0x02a38, 0x029bc, 0x029bf,
+/* E288 */ 0x029c0, 0x029c1, 0x029b7, 0x029b9, 0x02a37, 0x02a36, 0x02a31, 0x0,
+/* E290 */ 0x0, 0x02994, 0x02993, 0x023b1, 0x023b0, 0x02996, 0x02995, 0x02991,
+/* E298 */ 0x02992, 0x0298b, 0x0298c, 0x0298d, 0x0298e, 0x0298f, 0x02990, 0x02a8a,
+/* E2A0 */ 0x02a88, 0x02269, 0x02a89, 0x02a87, 0x02268, 0x02271, 0x02271, 0x02270,
+/* E2A8 */ 0x02270, 0x0, 0x02224, 0x02226, 0x02284, 0x02288, 0x02288, 0x02285,
+/* E2B0 */ 0x02289, 0x02289, 0x02ab9, 0x02ab5, 0x02aba, 0x02ab6, 0x02acb, 0x02acc,
+/* E2B8 */ 0x02acb, 0x0228a, 0x0228b, 0x02acc, 0x0, 0x0, 0x0, 0x0,
+/* E2C0 */ 0x0, 0x02270, 0x02271, 0x0226e, 0x0226f, 0x0, 0x02249, 0x0,
+/* E2C8 */ 0x02af3, 0x0f423, 0x0f428, 0x0, 0x0, 0x0, 0x0, 0x022ed,
+/* E2D0 */ 0x022ec, 0x02aee, 0x0, 0x0, 0x0, 0x0210f, 0x029a4, 0x029a5,
+/* E2D8 */ 0x0, 0x029a8, 0x029a9, 0x029aa, 0x029ab, 0x029ac, 0x029ad, 0x029ae,
+/* E2E0 */ 0x029af, 0x0299d, 0x025f9, 0x0, 0x025f8, 0x025fa, 0x029c9, 0x029b1,
+/* E2E8 */ 0x029b2, 0x029b3, 0x029b4, 0x0299a, 0x0ee39, 0x0204f, 0x023b5, 0x023b4,
+/* E2F0 */ 0x023b6, 0x029c2, 0x029c3, 0x0, 0x02a86, 0x02a8c, 0x02a7e, 0x02aa2,
+/* E2F8 */ 0x02a85, 0x02a8b, 0x02a7d, 0x02aa1, 0x0, 0x02ab7, 0x02aaf, 0x02ab8,
+/* E300 */ 0x02ab0, 0x02223, 0x02225, 0x02323, 0x02ac5, 0x02ac6, 0x02248, 0x0,
+/* E308 */ 0x0, 0x02a77, 0x02adb, 0x02a9d, 0x02a9e, 0x02aeb, 0x02a74, 0x02ae4,
+/* E310 */ 0x02ae8, 0x02ae7, 0x02ae9, 0x02ae6, 0x02a6d, 0x02a70, 0x02aae, 0x02a73,
+/* E318 */ 0x02a78, 0x02a66, 0x02a29, 0x02ad9, 0x02ada, 0x02a7f, 0x02a80, 0x02a81,
+/* E320 */ 0x02a82, 0x02a83, 0x02a84, 0x02a97, 0x02a98, 0x02a79, 0x02a7a, 0x0,
+/* E328 */ 0x0, 0x02a7b, 0x02a7c, 0x022da, 0x022db, 0x02a91, 0x02a92, 0x02aa4,
+/* E330 */ 0x02aa5, 0x02a93, 0x02a94, 0x02a8d, 0x02a8e, 0x02a8f, 0x02a90, 0x02a9f,
+/* E338 */ 0x02aa0, 0x02aaa, 0x02aab, 0x02aac, 0x02aad, 0x0, 0x0, 0x02979,
+/* E340 */ 0x0297b, 0x02abf, 0x02ac0, 0x02ac1, 0x02ac2, 0x02ac7, 0x02ac8, 0x02ad3,
+/* E348 */ 0x02ad4, 0x02ad5, 0x02ad6, 0x02ad7, 0x02ad8, 0x0ee40, 0x0ee41, 0x02ac3,
+/* E350 */ 0x02ac4, 0x02acf, 0x02ad0, 0x02ad1, 0x02ad2, 0x02aa6, 0x02aa7, 0x02aa8,
+/* E358 */ 0x02aa9, 0x029ce, 0x02ab3, 0x02ab4, 0x02abb, 0x02abc, 0x02976, 0x02978,
+/* E360 */ 0x0, 0x02218, 0x0, 0x022a5, 0x1d453, 0x021d4, 0x0, 0x0,
+/* E368 */ 0x0, 0x0, 0x0204e, 0x0, 0x0220c, 0x0220c, 0x02a55, 0x02a56,
+/* E370 */ 0x02209, 0x02057, 0x029dc, 0x0299c, 0x02a53, 0x02a54, 0x02a15, 0x02a16,
+/* E378 */ 0x02a0c, 0x0, 0x0, 0x022f7, 0x022f6, 0x022fe, 0x022fd, 0x001b5,
+/* E380 */ 0x0ee44, 0x0ee45, 0x02afd, 0x02af1, 0x029e3, 0x029e4, 0x029e5, 0x0,
+/* E388 */ 0x0, 0x0, 0x0, 0x02a6a, 0x02a6f, 0x02af2, 0x029de, 0x029dd,
+/* E390 */ 0x0, 0x02a5a, 0x02a5b, 0x02a5d, 0x02a5c, 0x02a10, 0x02a0d, 0x02a12,
+/* E398 */ 0x02a13, 0x02a14, 0x02a17, 0x02a11, 0x022f5, 0x0, 0x022f9, 0x0,
+/* E3A0 */ 0x022f2, 0x022fa, 0x022f3, 0x022fb, 0x022f4, 0x022fc, 0x0ee46, 0x0ee47,
+/* E3A8 */ 0x029bb, 0x02052, 0x029a6, 0x029a7, 0x02aec, 0x02aed, 0x02a57, 0x02a58,
+/* E3B0 */ 0x02a61, 0x02218, 0x0ee24, 0x0, 0x02026, 0x0ee30, 0x00308, 0x02aea,
+/* E3B8 */ 0x022f8, 0x0, 0x0, 0x0, 0x02209, 0x02275, 0x02274, 0x0,
+/* E3C0 */ 0x02053, 0x0, 0x0, 0x0, 0x02ae2, 0x0, 0x0, 0x0299f,
+/* E3C8 */ 0x029e1, 0x0, 0x02a51, 0x02a52, 0x003b1, 0x0026b, 0x0, 0x0,
+/* E3D0 */ 0x003c3, 0x00067, 0x025aa, 0x02a0f, 0x022bd, 0x0007c, 0x02934, 0x02935,
+/* E3D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E3E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E3E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E3F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E3F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E400 */ 0x0, 0x0, 0x0290c, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E408 */ 0x0, 0x029be, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E410 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x02241, 0x0, 0x0,
+/* E418 */ 0x0, 0x0, 0x029b0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E420 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E428 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E430 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E438 */ 0x0, 0x0, 0x0, 0x0ee3b, 0x0ee3c, 0x0, 0x0, 0x0,
+/* E440 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E448 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E450 */ 0x00308, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E458 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E460 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E468 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E470 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E478 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E480 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E488 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E490 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E498 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E4A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E4A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E4B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E4B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E4C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E4C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E4D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E4D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E4E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E4E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E4F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E4F8 */ 0x0, 0x02423, 0x0, 0x0, 0x0ee31, 0x0, 0x0, 0x0ee32,
+/* E500 */ 0x1d538, 0x1d539, 0x02102, 0x1d53b, 0x1d53c, 0x1d53d, 0x1d53e, 0x0210d,
+/* E508 */ 0x1d540, 0x1d541, 0x1d542, 0x1d543, 0x1d544, 0x02115, 0x1d546, 0x02119,
+/* E510 */ 0x0211a, 0x0211d, 0x1d54a, 0x1d54b, 0x1d54c, 0x1d54d, 0x1d54e, 0x1d54f,
+/* E518 */ 0x1d550, 0x02124, 0x0213f, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E520 */ 0x1d49c, 0x0212c, 0x1d49e, 0x1d49f, 0x02130, 0x02131, 0x1d4a2, 0x0210b,
+/* E528 */ 0x02110, 0x1d4a5, 0x1d4a6, 0x02112, 0x02133, 0x1d4a9, 0x1d4aa, 0x1d4ab,
+/* E530 */ 0x1d4ac, 0x0211b, 0x1d4ae, 0x1d4af, 0x1d4b0, 0x1d4b1, 0x1d4b2, 0x1d4b3,
+/* E538 */ 0x1d4b4, 0x1d4b5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E540 */ 0x1d4b6, 0x1d4b7, 0x1d4b8, 0x1d4b9, 0x0212f, 0x1d4bb, 0x0210a, 0x1d4bd,
+/* E548 */ 0x1d4be, 0x1d4bf, 0x1d4c0, 0x02113, 0x1d4c2, 0x1d4c3, 0x02134, 0x1d4c5,
+/* E550 */ 0x1d4c6, 0x1d4c7, 0x1d4c8, 0x1d4c9, 0x1d4ca, 0x1d4cb, 0x1d4cc, 0x1d4cd,
+/* E558 */ 0x1d4ce, 0x1d4cf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E560 */ 0x1d504, 0x1d505, 0x1d506, 0x1d507, 0x1d508, 0x1d509, 0x1d50a, 0x0210c,
+/* E568 */ 0x02111, 0x1d50d, 0x1d50e, 0x1d50f, 0x1d510, 0x1d511, 0x1d512, 0x1d513,
+/* E570 */ 0x1d514, 0x0211c, 0x1d516, 0x1d517, 0x1d518, 0x1d519, 0x1d51a, 0x1d51b,
+/* E578 */ 0x1d51c, 0x12128, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E580 */ 0x1d51e, 0x1d51f, 0x1d520, 0x1d521, 0x1d522, 0x1d523, 0x1d524, 0x1d525,
+/* E588 */ 0x1d526, 0x1d527, 0x1d528, 0x1d529, 0x1d52a, 0x1d52b, 0x1d52c, 0x1d52d,
+/* E590 */ 0x1d52e, 0x1d52f, 0x1d530, 0x1d531, 0x1d532, 0x1d533, 0x1d534, 0x1d535,
+/* E598 */ 0x1d536, 0x1d537, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E5A0 */ 0x02942, 0x02944, 0x02947, 0x02940, 0x02941, 0x0, 0x0, 0x0,
+/* E5A8 */ 0x02985, 0x0, 0x02980, 0x0, 0x0ec01, 0x0, 0x0, 0x02986,
+/* E5B0 */ 0x02af6, 0x0, 0x02999, 0x0, 0x0ee33, 0x0ee34, 0x0ee35, 0x0ee36,
+/* E5B8 */ 0x025a9, 0x0ee37, 0x0ee38, 0x0, 0x0ee80, 0x0, 0x0, 0x02222,
+/* E5C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x02a08, 0x02a07, 0x02a63,
+/* E5C8 */ 0x02a5e, 0x0, 0x029ca, 0x0, 0x0, 0x0, 0x0, 0x02a95,
+/* E5D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E5D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x02a96,
+/* E5E0 */ 0x0, 0x0, 0x0, 0x0, 0x0e84e, 0x0, 0x0, 0x0ee50,
+/* E5E8 */ 0x0ee51, 0x0ee52, 0x0ee53, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E5F0 */ 0x0, 0x0, 0x0ee3a, 0x0, 0x0ee54, 0x0, 0x0ee55, 0x0ee56,
+/* E5F8 */ 0x0ee57, 0x0ee58, 0x0, 0x0ee59, 0x0ee5a, 0x0ee5b, 0x029f8, 0x029f9,
+/* E600 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0ee5c, 0x0ee5d, 0x0ee5e,
+/* E608 */ 0x0ee5f, 0x0ee60, 0x0ee61, 0x0ee62, 0x0224c, 0x0224c, 0x0, 0x029cb,
+/* E610 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E618 */ 0x0, 0x02a2f, 0x0, 0x029b6, 0x0, 0x0, 0x0, 0x0,
+/* E620 */ 0x0, 0x0, 0x0, 0x02205, 0x0ee10, 0x00326, 0x000b7, 0x0,
+/* E628 */ 0x0, 0x003f5, 0x0, 0x0, 0x0, 0x0ee14, 0x00061, 0x0,
+/* E630 */ 0x0ee15, 0x0, 0x0ee18, 0x0ee19, 0x0ee1a, 0x0ee1b, 0x0ee1c, 0x0,
+/* E638 */ 0x0ee1d, 0x0ee1e, 0x0026e, 0x0, 0x002af, 0x0, 0x00235, 0x00236,
+/* E640 */ 0x0ee1f, 0x00221, 0x0ee12, 0x02afd, 0x0ee20, 0x0, 0x0, 0x02afb,
+/* E648 */ 0x0, 0x0, 0x0005c, 0x0ee13, 0x0ee16, 0x0, 0x0, 0x0,
+/* E650 */ 0x021f9, 0x0, 0x0, 0x0, 0x0e215, 0x0, 0x0, 0x0,
+/* E658 */ 0x0, 0x1d5b2, 0x0, 0x02a05, 0x0, 0x0, 0x0, 0x0,
+/* E660 */ 0x003d8, 0x003d9, 0x0223c, 0x003d2, 0x003f4, 0x0, 0x0, 0x0,
+/* E668 */ 0x00062, 0x00063, 0x00064, 0x00065, 0x00066, 0x00068, 0x00069, 0x0006a,
+/* E670 */ 0x0006b, 0x0006c, 0x0006d, 0x0006e, 0x0006f, 0x00070, 0x00071, 0x00072,
+/* E678 */ 0x00073, 0x00074, 0x00075, 0x00076, 0x00077, 0x00078, 0x00079, 0x0007a,
+/* E680 */ 0x0030f, 0x003c7, 0x003b2, 0x001a5, 0x01d1c, 0x01d07, 0x0004d, 0x0002f,
+/* E688 */ 0x01d00, 0x0029c, 0x0e2d4, 0x003b8, 0x003bb, 0x02260, 0x00110, 0x003c9,
+/* E690 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E698 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E6A0 */ 0x0ee17, 0x0ee70, 0x0ee71, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E6A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E6B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E6B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E6C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E6C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E6D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E6D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E6E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E6E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E6F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E6F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E700 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E708 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E710 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E718 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E720 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E728 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E730 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E738 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E740 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E748 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E750 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E758 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E760 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E768 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E770 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E778 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E780 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E788 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E790 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E798 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E7A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E7A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E7B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E7B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E7C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E7C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E7D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E7D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E7E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E7E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E7F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E7F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E800 */ 0x003f6, 0x0213f, 0x0, 0x1d7d9, 0x1d7d8, 0x02a03, 0x0, 0x0,
+/* E808 */ 0x0, 0x02a09, 0x0290d, 0x029eb, 0x0, 0x029c6, 0x0, 0x0,
+/* E810 */ 0x029c7, 0x0, 0x02a32, 0x02ae3, 0x0, 0x0, 0x0, 0x0,
+/* E818 */ 0x0, 0x029df, 0x02adc, 0x02add, 0x02141, 0x0, 0x0, 0x0,
+/* E820 */ 0x0, 0x02a0e, 0x02a19, 0x02a1a, 0x02af4, 0x02a18, 0x0, 0x0,
+/* E828 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x027fb, 0x027fd, 0x0,
+/* E830 */ 0x027fe, 0x0, 0x0, 0x0, 0x02906, 0x02907, 0x0, 0x0,
+/* E838 */ 0x0, 0x029b8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E840 */ 0x02aa3, 0x0, 0x0, 0x02322, 0x02216, 0x0, 0x0214b, 0x0221d,
+/* E848 */ 0x0, 0x00303, 0x0, 0x0, 0x0, 0x0, 0x0e84e, 0x0,
+/* E850 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E858 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E860 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E868 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E870 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E878 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E880 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E888 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E890 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E898 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E8A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E8A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E8B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E8B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E8C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E8C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E8D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E8D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E8E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E8E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E8F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E8F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E900 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E908 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E910 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E918 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E920 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E928 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E930 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E938 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E940 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E948 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E950 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E958 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E960 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E968 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E970 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E978 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E980 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E988 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E990 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E998 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA00 */ 0x029a2, 0x0299e, 0x029a3, 0x0ee73, 0x0ee74, 0x0, 0x0ee75, 0x02943,
+/* EA08 */ 0x02051, 0x00319, 0x0ee11, 0x0, 0x0ee76, 0x0, 0x0, 0x0,
+/* EA10 */ 0x0, 0x029f3, 0x029f1, 0x0, 0x0, 0x029bd, 0x029ec, 0x029ed,
+/* EA18 */ 0x0, 0x029ba, 0x02050, 0x0ee77, 0x029ef, 0x0, 0x0, 0x0,
+/* EA20 */ 0x0, 0x0, 0x025a0, 0x0, 0x0, 0x0223c, 0x0ee21, 0x0ee22,
+/* EA28 */ 0x029ea, 0x02908, 0x0ee72, 0x0, 0x0ee78, 0x0ee79, 0x0ee7a, 0x0ee7b,
+/* EA30 */ 0x0ee7c, 0x0ee7d, 0x0ee23, 0x0, 0x0, 0x0, 0x0, 0x0ee7e,
+/* EA38 */ 0x0, 0x0, 0x0, 0x0, 0x02142, 0x029e0, 0x0293e, 0x029d1,
+/* EA40 */ 0x029d4, 0x0, 0x0, 0x02983, 0x02922, 0x02921, 0x029f2, 0x029f0,
+/* EA48 */ 0x029ee, 0x0, 0x029d6, 0x02034, 0x021f6, 0x0293b, 0x029d2, 0x029d5,
+/* EA50 */ 0x02984, 0x02143, 0x1d5ab, 0x0ee42, 0x0ee43, 0x025fb, 0x025fc, 0x02a0b,
+/* EA58 */ 0x020e8, 0x0297a, 0x02a28, 0x029cc, 0x02909, 0x0ee7f, 0x02144, 0x029c8,
+/* EA60 */ 0x027d0, 0x029d3, 0x029d7, 0x00318, 0x02977, 0x02278, 0x02279, 0x0,
+/* EA68 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA70 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA78 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA80 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA88 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA90 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA98 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EAA0 */ 0x02987, 0x02988, 0x02989, 0x0298a, 0x02982, 0x02a3e, 0x02a1f, 0x02a20,
+/* EAA8 */ 0x02040, 0x02a21, 0x02a64, 0x02a65, 0x022ff, 0x02a41, 0x020e6, 0x0,
+/* EAB0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EAB8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EAC0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EAC8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EAD0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EAD8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EAE0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EAE8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EAF0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EAF8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB00 */ 0x0ee3d, 0x0, 0x0ee3e, 0x029e7, 0x0ee81, 0x029e8, 0x029e9, 0x0,
+/* EB08 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB10 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB18 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB20 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB28 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB30 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB38 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB40 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB48 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB50 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB58 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB60 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB68 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB70 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB78 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB80 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB88 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB90 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EB98 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EBA0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EBA8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EBB0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EBB8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EBC0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EBC8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EBD0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EBD8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EBE0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EBE8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EBF0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EBF8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC00 */ 0x02a3d, 0x0e5ac, 0x0e5a5, 0x00302, 0x0030c, 0x00330, 0x020e7, 0x029e2,
+/* EC08 */ 0x0290a, 0x0290b, 0x02140, 0x02a1b, 0x02a1c, 0x02a1d, 0x02a1e, 0x0,
+/* EC10 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC18 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC20 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC28 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC30 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC38 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC40 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC48 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC50 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC58 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC60 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC68 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC70 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC78 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC80 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC88 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC90 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EC98 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ECA0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ECA8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ECB0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ECB8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ECC0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ECC8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ECD0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ECD8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ECE0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ECE8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ECF0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ECF8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ED00 */ 0x0292b, 0x0292c, 0x0292d, 0x0292e, 0x0292f, 0x02930, 0x02931, 0x02932,
+/* ED08 */ 0x0294c, 0x0294d, 0x021f7, 0x021f8, 0x021fa, 0x0, 0x021fb, 0x021fc,
+/* ED10 */ 0x02900, 0x02901, 0x02914, 0x02915, 0x02917, 0x02918, 0x0, 0x0,
+/* ED18 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ED20 */ 0x0293f, 0x0293a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ED28 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ED30 */ 0x0e370, 0x0e36c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ED38 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ED40 */ 0x0, 0x0, 0x02a2c, 0x02a2b, 0x02a62, 0x02a60, 0x0, 0x0,
+/* ED48 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ED50 */ 0x02a6b, 0x0, 0x0, 0x02a6c, 0x0, 0x0, 0x0, 0x0,
+/* ED58 */ 0x0, 0x0, 0x02a67, 0x0, 0x0, 0x0, 0x02a76, 0x0,
+/* ED60 */ 0x02270, 0x02271, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ED68 */ 0x02a99, 0x02a9a, 0x02a9b, 0x02a9c, 0x0, 0x0, 0x0, 0x0,
+/* ED70 */ 0x02272, 0x02273, 0x02a9d, 0x02a9e, 0x02ab1, 0x02ab2, 0x0, 0x0,
+/* ED78 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ED80 */ 0x02ac9, 0x02aca, 0x02288, 0x02289, 0x02a59, 0x02a4e, 0x02a4f, 0x02acd,
+/* ED88 */ 0x02ace, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ED90 */ 0x02ae0, 0x02ade, 0x02adf, 0x02ae5, 0x02ae1, 0x0299b, 0x029a0, 0x029a1,
+/* ED98 */ 0x0, 0x02af5, 0x02a68, 0x02a69, 0x02af7, 0x02af8, 0x02a0a, 0x0213e,
+/* EDA0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDA8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDB0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDB8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDC0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDC8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDD0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDD8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDE0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDE8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDF0 */ 0x0ee82, 0x0ee83, 0x0ee84, 0x0220a, 0x0220d, 0x0ee85, 0x0, 0x0,
+/* EDF8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE00 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE08 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE10 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE18 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE20 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE28 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE30 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE38 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE40 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE48 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE50 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE58 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE60 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE68 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE70 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE78 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE80 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE88 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE90 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE98 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEA0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEA8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEB0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEB8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEC0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEC8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EED0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EED8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEE0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEE8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEF0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEF8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF00 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF08 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF10 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF18 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF20 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF28 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF30 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF38 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF40 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF48 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF50 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF58 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF60 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF68 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF70 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF78 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF80 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF88 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF90 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF98 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFA0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFA8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFB0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFB8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFC0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFC8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFD0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFD8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFE0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFE8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFF0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFF8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F000 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F008 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F010 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F018 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F020 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F028 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F030 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F038 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F040 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F048 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F050 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F058 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F060 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F068 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F070 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F078 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F080 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F088 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F090 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F098 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F100 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F108 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F110 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F118 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F120 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F128 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F130 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F138 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F140 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F148 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F150 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F158 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F160 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F168 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F170 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F178 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F180 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F188 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F190 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F198 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F200 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F208 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F210 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F218 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F220 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F228 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F230 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F238 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F240 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F248 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F250 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F258 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F260 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F268 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F270 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F278 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F280 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F288 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F290 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F298 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F300 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F308 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F310 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F318 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F320 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F328 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F330 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F338 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F340 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F348 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F350 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F358 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F360 */ 0x0, 0x0, 0x0, 0x0, 0x0205f, 0x0, 0x0, 0x0,
+/* F368 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F370 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F378 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F380 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F388 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F390 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F398 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3B0 */ 0x0, 0x0, 0x0ee90, 0x0, 0x0, 0x0, 0x02062, 0x02061,
+/* F3B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F400 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F408 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F410 */ 0x029cf, 0x029d0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F418 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F420 */ 0x0, 0x0, 0x0, 0x0f423, 0x0, 0x0, 0x0, 0x0,
+/* F428 */ 0x0f428, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F430 */ 0x0, 0x02a75, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F438 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F440 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F448 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F450 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F458 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F460 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F468 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F470 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F478 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F480 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F488 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F490 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F498 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F4A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F4A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F4B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F4B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F4C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F4C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F4D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F4D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F4E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F4E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F4F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F4F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F500 */ 0x0, 0x0, 0x0, 0x02912, 0x02913, 0x0294e, 0x0, 0x02952,
+/* F508 */ 0x02953, 0x0295a, 0x0295b, 0x02950, 0x02956, 0x02957, 0x0295e, 0x0295f,
+/* F510 */ 0x0294f, 0x02954, 0x02955, 0x0295c, 0x0295d, 0x02951, 0x02958, 0x02959,
+/* F518 */ 0x02960, 0x02961, 0x0, 0x0, 0x0, 0x0, 0x0, 0x029f4,
+/* F520 */ 0x0ee05, 0x0, 0x0, 0x0, 0x02970, 0x0, 0x0, 0x0ee06,
+/* F528 */ 0x0ee07, 0x025fe, 0x02191, 0x02193, 0x0, 0x0, 0x0, 0x0,
+/* F530 */ 0x025fd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F538 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F540 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F548 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F550 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F558 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F560 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F568 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F570 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F578 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F580 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F588 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F590 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F598 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F600 */ 0x0, 0x0ee91, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F608 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F610 */ 0x0, 0x0, 0x0, 0x0, 0x00346, 0x0033a, 0x0, 0x0,
+/* F618 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F620 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F628 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F630 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F638 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F640 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F648 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F650 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F658 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F660 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F668 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F670 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F678 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F680 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F688 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F690 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F698 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d552, 0x1d553,
+/* F6E8 */ 0x1d554, 0x1d555, 0x1d556, 0x1d557, 0x1d558, 0x1d559, 0x1d55a, 0x1d55b,
+/* F6F0 */ 0x1d55c, 0x1d55d, 0x1d55e, 0x1d55f, 0x1d560, 0x1d561, 0x1d562, 0x1d563,
+/* F6F8 */ 0x1d564, 0x1d565, 0x1d566, 0x1d567, 0x1d568, 0x1d569, 0x1d56a, 0x1d56b,
+/* F700 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F708 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F710 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F718 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F720 */ 0x0, 0x0ee92, 0x0ee93, 0x0ee94, 0x0, 0x026a0, 0x0, 0x0,
+/* F728 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F730 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F738 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F740 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F748 */ 0x0, 0x0ee00, 0x0213d, 0x02145, 0x02146, 0x02147, 0x02148, 0x02149,
+/* F750 */ 0x02981, 0x0ee95, 0x0ee96, 0x0ee97, 0x0, 0x0, 0x0ee98, 0x0ee99,
+/* F758 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F760 */ 0x0, 0x0, 0x0, 0x0ee9d, 0x0ee9a, 0x0, 0x0ee9e, 0x0ee9b,
+/* F768 */ 0x0ee9c, 0x0ee9f, 0x0eea0, 0x0eeab, 0x0eeac, 0x0, 0x0, 0x0,
+/* F770 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F778 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F780 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F788 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F790 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F798 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0eea1, 0x0eea2,
+/* F7C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7D0 */ 0x0eea3, 0x0eea4, 0x0eea5, 0x0eea6, 0x0eea7, 0x0eea8, 0x0eea9, 0x0eeaa,
+/* F7D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F800 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F808 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F810 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F818 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F820 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F828 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F830 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F838 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F840 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F848 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F850 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F858 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F860 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F868 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F870 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F878 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F880 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F888 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F890 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F898 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
+};
+
+/* These data are taken from adobe's cid2code.txt for ac14 */
+const int cns14pua[] = { /* Big5 and friends */
+/* E000 */ 0x20547, 0x0, 0x205df, 0x23fc5, 0x0, 0x0, 0x0, 0x0,
+/* E008 */ 0x0, 0x24942, 0x289e4, 0x0, 0x219db, 0x0, 0x23cc8, 0x0,
+/* E010 */ 0x0, 0x0, 0x24933, 0x289aa, 0x202a0, 0x26bb3, 0x21305, 0x0,
+/* E018 */ 0x224ed, 0x0, 0x26d29, 0x27a84, 0x23600, 0x24ab1, 0x22513, 0x0,
+/* E020 */ 0x2037e, 0x0, 0x20380, 0x20347, 0x0, 0x2041f, 0x0, 0x0,
+/* E028 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x249a4, 0x20487, 0x0,
+/* E030 */ 0x233b4, 0x0, 0x20bff, 0x220fc, 0x202e5, 0x22530, 0x2058e, 0x23233,
+/* E038 */ 0x21983, 0x0, 0x0, 0x205b3, 0x23c99, 0x0, 0x0, 0x0,
+/* E040 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x24aa6, 0x0, 0x0,
+/* E048 */ 0x0, 0x0, 0x0, 0x0, 0x2372d, 0x0, 0x0, 0x0,
+/* E050 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E058 */ 0x0, 0x0, 0x26b13, 0x0, 0x28ade, 0x0, 0x0, 0x23f80,
+/* E060 */ 0x20954, 0x23fec, 0x0, 0x0, 0x20be2, 0x0, 0x21726, 0x0,
+/* E068 */ 0x0, 0x0, 0x0, 0x0, 0x216e8, 0x0, 0x0, 0x0,
+/* E070 */ 0x0, 0x286ab, 0x0, 0x0, 0x21596, 0x21613, 0x0, 0x0,
+/* E078 */ 0x28a9b, 0x0, 0x0, 0x0, 0x0, 0x25772, 0x0, 0x0,
+/* E080 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20b8f,
+/* E088 */ 0x0, 0x23feb, 0x22da3, 0x0, 0x20c77, 0x0, 0x0, 0x0,
+/* E090 */ 0x0, 0x0, 0x0, 0x26b53, 0x20d74, 0x0, 0x0, 0x0,
+/* E098 */ 0x0, 0x2170d, 0x20edd, 0x0, 0x20d4d, 0x289bc, 0x22698, 0x0,
+/* E0A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x218d7, 0x2403a,
+/* E0A8 */ 0x0, 0x24435, 0x0, 0x210b4, 0x0, 0x0, 0x2328a, 0x0,
+/* E0B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E0B8 */ 0x0, 0x0, 0x28b66, 0x0, 0x2124f, 0x0, 0x241a5, 0x0,
+/* E0C0 */ 0x0, 0x0, 0x0, 0x26c7e, 0x0, 0x21416, 0x0, 0x21454,
+/* E0C8 */ 0x24363, 0x0, 0x24bf5, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E0D0 */ 0x2123c, 0x0, 0x0, 0x0, 0x2a150, 0x24278, 0x0, 0x0,
+/* E0D8 */ 0x0, 0x0, 0x0, 0x0, 0x2163e, 0x0, 0x0, 0x21692,
+/* E0E0 */ 0x0, 0x0, 0x20d4e, 0x26c81, 0x26d2a, 0x217dc, 0x0, 0x217fb,
+/* E0E8 */ 0x217b2, 0x26da6, 0x0, 0x21828, 0x216d5, 0x0, 0x26e45, 0x0,
+/* E0F0 */ 0x0, 0x0, 0x249a9, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E0F8 */ 0x26fa1, 0x22554, 0x0, 0x21911, 0x0, 0x216b8, 0x0, 0x0,
+/* E100 */ 0x0, 0x0, 0x0, 0x27a0e, 0x0, 0x0, 0x20204, 0x0,
+/* E108 */ 0x0, 0x21a34, 0x259cc, 0x205a5, 0x0, 0x0, 0x0, 0x0,
+/* E110 */ 0x21b44, 0x0, 0x0, 0x0, 0x21ca5, 0x26b28, 0x0, 0x0,
+/* E118 */ 0x0, 0x0, 0x0, 0x0, 0x21df9, 0x21e37, 0x0, 0x0,
+/* E120 */ 0x0, 0x21ea4, 0x0, 0x0, 0x0, 0x0, 0x24901, 0x22049,
+/* E128 */ 0x22173, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E130 */ 0x244bc, 0x20cd3, 0x0, 0x0, 0x0, 0x0, 0x21771, 0x0,
+/* E138 */ 0x0, 0x28482, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E140 */ 0x0, 0x201c1, 0x2f894, 0x0, 0x0, 0x2133a, 0x0, 0x26888,
+/* E148 */ 0x223d0, 0x0, 0x22471, 0x0, 0x0, 0x26e6e, 0x0, 0x0,
+/* E150 */ 0x28a36, 0x0, 0x0, 0x0, 0x25250, 0x21f6a, 0x270f8, 0x22668,
+/* E158 */ 0x0, 0x2029e, 0x28a29, 0x0, 0x0, 0x21877, 0x0, 0x0,
+/* E160 */ 0x0, 0x0, 0x227b4, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E168 */ 0x24982, 0x2498f, 0x27a53, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E170 */ 0x0, 0x2f8a6, 0x26ed2, 0x0, 0x0, 0x20656, 0x0, 0x0,
+/* E178 */ 0x23fb7, 0x2285f, 0x0, 0x28b9d, 0x2995d, 0x0, 0x0, 0x22980,
+/* E180 */ 0x228c1, 0x0, 0x0, 0x0, 0x0, 0x20118, 0x0, 0x21770,
+/* E188 */ 0x0, 0x22e0d, 0x0, 0x249df, 0x0, 0x0, 0x0, 0x2138e,
+/* E190 */ 0x217fc, 0x0, 0x0, 0x22e36, 0x0, 0x2408c, 0x2571d, 0x0,
+/* E198 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24a28,
+/* E1A0 */ 0x24a23, 0x0, 0x0, 0x0, 0x2307e, 0x0, 0x24940, 0x0,
+/* E1A8 */ 0x0, 0x0, 0x21829, 0x0, 0x0, 0x0, 0x23400, 0x0,
+/* E1B0 */ 0x231f7, 0x231f8, 0x0, 0x231a4, 0x231a5, 0x0, 0x20e75, 0x0,
+/* E1B8 */ 0x251e6, 0x0, 0x0, 0x21e3d, 0x23231, 0x285f4, 0x231c8, 0x25313,
+/* E1C0 */ 0x0, 0x228f7, 0x0, 0x0, 0x2439c, 0x24a21, 0x0, 0x0,
+/* E1C8 */ 0x237c2, 0x0, 0x0, 0x0, 0x241cd, 0x290ed, 0x0, 0x0,
+/* E1D0 */ 0x0, 0x0, 0x0, 0x0, 0x233e6, 0x26da0, 0x0, 0x2346f,
+/* E1D8 */ 0x0, 0x0, 0x28adf, 0x0, 0x0, 0x235cd, 0x0, 0x0,
+/* E1E0 */ 0x0, 0x0, 0x2363c, 0x0, 0x0, 0x0, 0x28a4a, 0x0,
+/* E1E8 */ 0x0, 0x0, 0x0, 0x203c9, 0x0, 0x0, 0x0, 0x23659,
+/* E1F0 */ 0x2212a, 0x0, 0x23703, 0x0, 0x0, 0x0, 0x0, 0x2919c,
+/* E1F8 */ 0x0, 0x0, 0x20923, 0x0, 0x0, 0x0, 0x227cd, 0x0,
+/* E200 */ 0x23adb, 0x203b5, 0x21958, 0x0, 0x0, 0x23b5a, 0x0, 0x23efc,
+/* E208 */ 0x0, 0x0, 0x2248b, 0x248f1, 0x26b51, 0x0, 0x0, 0x0,
+/* E210 */ 0x23dbc, 0x0, 0x23dbd, 0x241a4, 0x2490c, 0x24900, 0x23cc9, 0x0,
+/* E218 */ 0x0, 0x20d32, 0x0, 0x231f9, 0x22491, 0x0, 0x0, 0x26d25,
+/* E220 */ 0x26da1, 0x26deb, 0x0, 0x0, 0x0, 0x0, 0x2497f, 0x24085,
+/* E228 */ 0x26e72, 0x0, 0x26f74, 0x0, 0x0, 0x0, 0x0, 0x28b21,
+/* E230 */ 0x0, 0x23e2f, 0x0, 0x23f82, 0x0, 0x0, 0x0, 0x2304b,
+/* E238 */ 0x0, 0x0, 0x0, 0x23e30, 0x0, 0x21497, 0x2403d, 0x0,
+/* E240 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x29170, 0x0, 0x0,
+/* E248 */ 0x24144, 0x0, 0x24091, 0x24155, 0x24039, 0x23ff0, 0x23fb4, 0x2413f,
+/* E250 */ 0x0, 0x24156, 0x24157, 0x24140, 0x261dd, 0x0, 0x0, 0x0,
+/* E258 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E260 */ 0x0, 0x24277, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E268 */ 0x24365, 0x0, 0x0, 0x242c1, 0x0, 0x2445a, 0x24a27, 0x24a22,
+/* E270 */ 0x0, 0x28be8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E278 */ 0x0, 0x0, 0x25605, 0x0, 0x0, 0x24974, 0x0, 0x0,
+/* E280 */ 0x0, 0x0, 0x23044, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E288 */ 0x24823, 0x2882b, 0x0, 0x28804, 0x0, 0x0, 0x0, 0x0,
+/* E290 */ 0x20c3a, 0x26a2e, 0x0, 0x0, 0x241e2, 0x216e7, 0x24a24, 0x0,
+/* E298 */ 0x0, 0x249b7, 0x2498d, 0x249fb, 0x0, 0x0, 0x0, 0x24a26,
+/* E2A0 */ 0x0, 0x205c3, 0x0, 0x0, 0x228ad, 0x0, 0x28eb2, 0x0,
+/* E2A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E2B0 */ 0x0, 0x0, 0x24a8c, 0x2415f, 0x24a79, 0x28b8f, 0x0, 0x28c03,
+/* E2B8 */ 0x2189e, 0x0, 0x21988, 0x0, 0x0, 0x0, 0x28ed9, 0x21a4b,
+/* E2C0 */ 0x0, 0x28eac, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24f82,
+/* E2C8 */ 0x0, 0x24d13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E2D0 */ 0x0, 0x0, 0x0, 0x0, 0x263f5, 0x0, 0x0, 0x0,
+/* E2D8 */ 0x26911, 0x2690e, 0x0, 0x0, 0x0, 0x0, 0x26f9f, 0x0,
+/* E2E0 */ 0x2509d, 0x2517d, 0x21e1c, 0x0, 0x0, 0x0, 0x0, 0x25220,
+/* E2E8 */ 0x0, 0x232ac, 0x0, 0x28964, 0x28968, 0x216c1, 0x0, 0x0,
+/* E2F0 */ 0x21376, 0x24a12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E2F8 */ 0x255e0, 0x0, 0x0, 0x0, 0x2760c, 0x0, 0x0, 0x28b2b,
+/* E300 */ 0x26083, 0x2261c, 0x0, 0x0, 0x0, 0x0, 0x25857, 0x0,
+/* E308 */ 0x27b39, 0x0, 0x0, 0x0, 0x27126, 0x0, 0x0, 0x2910d,
+/* E310 */ 0x0, 0x23ed7, 0x0, 0x26ed3, 0x0, 0x257e0, 0x0, 0x0,
+/* E318 */ 0x28be9, 0x0, 0x0, 0x258e1, 0x294d9, 0x0, 0x0, 0x259ac,
+/* E320 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x2648d, 0x0, 0x0,
+/* E328 */ 0x0, 0x0, 0x0, 0x0, 0x25c01, 0x0, 0x0, 0x0,
+/* E330 */ 0x2530e, 0x25cfe, 0x0, 0x0, 0x0, 0x25bb4, 0x26c7f, 0x0,
+/* E338 */ 0x0, 0x0, 0x0, 0x25d20, 0x0, 0x25c65, 0x0, 0x0,
+/* E340 */ 0x0, 0x0, 0x25cc1, 0x0, 0x0, 0x24882, 0x0, 0x0,
+/* E348 */ 0x24578, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E350 */ 0x0, 0x0, 0x26e44, 0x0, 0x26ed6, 0x0, 0x0, 0x0,
+/* E358 */ 0x0, 0x0, 0x0, 0x24057, 0x26029, 0x0, 0x0, 0x0,
+/* E360 */ 0x217f9, 0x0, 0x2836d, 0x0, 0x26121, 0x2615a, 0x0, 0x0,
+/* E368 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x262d0,
+/* E370 */ 0x0, 0x0, 0x26351, 0x0, 0x21661, 0x20068, 0x0, 0x23766,
+/* E378 */ 0x0, 0x2833a, 0x0, 0x26489, 0x0, 0x0, 0x0, 0x0,
+/* E380 */ 0x0, 0x2a087, 0x26cc3, 0x0, 0x0, 0x0, 0x22714, 0x0,
+/* E388 */ 0x26626, 0x23de3, 0x266e8, 0x0, 0x0, 0x28a48, 0x0, 0x0,
+/* E390 */ 0x0, 0x226f6, 0x0, 0x26498, 0x24fb8, 0x0, 0x2148a, 0x0,
+/* E398 */ 0x2185e, 0x0, 0x24a65, 0x24a95, 0x0, 0x0, 0x20b0d, 0x26a52,
+/* E3A0 */ 0x23d7e, 0x0, 0x214fd, 0x0, 0x0, 0x26b0a, 0x249a7, 0x23530,
+/* E3A8 */ 0x21773, 0x23df8, 0x0, 0x0, 0x2f994, 0x0, 0x0, 0x0,
+/* E3B0 */ 0x0, 0x20e16, 0x217b4, 0x0, 0x2317d, 0x2355a, 0x0, 0x0,
+/* E3B8 */ 0x0, 0x23e8b, 0x26da3, 0x26b05, 0x26b97, 0x235ce, 0x0, 0x0,
+/* E3C0 */ 0x0, 0x0, 0x0, 0x26da5, 0x0, 0x0, 0x0, 0x0,
+/* E3C8 */ 0x26ed4, 0x0, 0x0, 0x0, 0x26e42, 0x22eef, 0x0, 0x25be4,
+/* E3D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x23cb5, 0x0, 0x0,
+/* E3D8 */ 0x26b96, 0x26e77, 0x26e43, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E3E0 */ 0x0, 0x25c91, 0x0, 0x25cc0, 0x0, 0x0, 0x0, 0x26e99,
+/* E3E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x28625, 0x2863b, 0x0,
+/* E3F0 */ 0x27088, 0x0, 0x21582, 0x270cd, 0x2f9b2, 0x0, 0x0, 0x0,
+/* E3F8 */ 0x218a2, 0x0, 0x2739a, 0x0, 0x0, 0x2a0f8, 0x0, 0x22c27,
+/* E400 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E408 */ 0x0, 0x275e0, 0x23db9, 0x275e4, 0x0, 0x0, 0x0, 0x0,
+/* E410 */ 0x0, 0x0, 0x0, 0x0, 0x2770f, 0x0, 0x0, 0x0,
+/* E418 */ 0x0, 0x0, 0x0, 0x28a25, 0x0, 0x27924, 0x27abd, 0x0,
+/* E420 */ 0x0, 0x0, 0x0, 0x27a59, 0x0, 0x27b3a, 0x23f8f, 0x0,
+/* E428 */ 0x27b38, 0x0, 0x0, 0x0, 0x25430, 0x25565, 0x0, 0x0,
+/* E430 */ 0x0, 0x0, 0x24a7a, 0x0, 0x0, 0x0, 0x216df, 0x0,
+/* E438 */ 0x0, 0x0, 0x27d54, 0x27d8f, 0x2f9d4, 0x0, 0x27d53, 0x0,
+/* E440 */ 0x27d98, 0x27dbd, 0x0, 0x0, 0x21910, 0x0, 0x0, 0x0,
+/* E448 */ 0x24cc9, 0x0, 0x0, 0x0, 0x28002, 0x21014, 0x2498a, 0x0,
+/* E450 */ 0x281bc, 0x2710c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E458 */ 0x0, 0x28365, 0x28412, 0x0, 0x0, 0x2a29f, 0x20a50, 0x0,
+/* E460 */ 0x0, 0x289de, 0x2853d, 0x23dbb, 0x0, 0x23262, 0x0, 0x2a014,
+/* E468 */ 0x286bc, 0x28501, 0x22325, 0x0, 0x26ed7, 0x0, 0x2853c, 0x27abe,
+/* E470 */ 0x0, 0x2856c, 0x2860b, 0x0, 0x28713, 0x0, 0x286e6, 0x0,
+/* E478 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28933, 0x21e89,
+/* E480 */ 0x0, 0x0, 0x0, 0x0, 0x255b9, 0x0, 0x28ac6, 0x23c9b,
+/* E488 */ 0x28b0c, 0x255db, 0x20d31, 0x0, 0x0, 0x28ae1, 0x28beb, 0x0,
+/* E490 */ 0x0, 0x28ae2, 0x28ae5, 0x0, 0x0, 0x28bec, 0x28c39, 0x28bff,
+/* E498 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E4A0 */ 0x0, 0x2267a, 0x286d8, 0x2127c, 0x23e2e, 0x0, 0x0, 0x0,
+/* E4A8 */ 0x0, 0x0, 0x0, 0x26ed5, 0x0, 0x0, 0x0, 0x28ae0,
+/* E4B0 */ 0x0, 0x0, 0x0, 0x26cb8, 0x20274, 0x26410, 0x290af, 0x290e5,
+/* E4B8 */ 0x24ad1, 0x21915, 0x2330a, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E4C0 */ 0x0, 0x24ae9, 0x0, 0x0, 0x0, 0x0, 0x291d5, 0x0,
+/* E4C8 */ 0x0, 0x291eb, 0x0, 0x0, 0x0, 0x230b7, 0x230bc, 0x0,
+/* E4D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2546c, 0x0,
+/* E4D8 */ 0x0, 0x29433, 0x0, 0x0, 0x2941d, 0x2797a, 0x0, 0x0,
+/* E4E0 */ 0x0, 0x0, 0x0, 0x0, 0x27175, 0x0, 0x20630, 0x2415c,
+/* E4E8 */ 0x25706, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26d27, 0x216d3,
+/* E4F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24a29, 0x0,
+/* E4F8 */ 0x29857, 0x29905, 0x0, 0x0, 0x0, 0x0, 0x0, 0x25725,
+/* E500 */ 0x0, 0x290b1, 0x29bd5, 0x0, 0x0, 0x29b05, 0x0, 0x0,
+/* E508 */ 0x0, 0x0, 0x28600, 0x0, 0x0, 0x269a8, 0x0, 0x2307d,
+/* E510 */ 0x0, 0x0, 0x29d3e, 0x0, 0x21863, 0x0, 0x2424b, 0x0,
+/* E518 */ 0x0, 0x0, 0x29e68, 0x0, 0x29fb7, 0x2a192, 0x2a1ab, 0x2a0e1,
+/* E520 */ 0x2a123, 0x2a1df, 0x0, 0x0, 0x2a134, 0x0, 0x0, 0x0,
+/* E528 */ 0x2215b, 0x2a193, 0x2a220, 0x2193b, 0x2a233, 0x0, 0x2a0b9, 0x2a2b4,
+/* E530 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24364,
+/* E538 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28c2b, 0x0,
+/* E540 */ 0x0, 0x0, 0x0, 0x26da2, 0x0, 0x0, 0x0, 0x0,
+/* E548 */ 0x0, 0x0, 0x0, 0x2908b, 0x0, 0x0, 0x0, 0x0,
+/* E550 */ 0x0, 0x0, 0x0, 0x0, 0x24975, 0x249bb, 0x0, 0x249f8,
+/* E558 */ 0x24348, 0x24a51, 0x0, 0x28bda, 0x218fa, 0x0, 0x2897e, 0x28e36,
+/* E560 */ 0x0, 0x0, 0x28a44, 0x0, 0x0, 0x0, 0x2896c, 0x244b9,
+/* E568 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x24473, 0x243f8, 0x0,
+/* E570 */ 0x217ef, 0x0, 0x218be, 0x23599, 0x0, 0x21885, 0x2542f, 0x217f8,
+/* E578 */ 0x0, 0x216fb, 0x21839, 0x0, 0x21774, 0x218d1, 0x25f4b, 0x0,
+/* E580 */ 0x216c0, 0x0, 0x24a25, 0x213fe, 0x212a8, 0x213c6, 0x214b6, 0x0,
+/* E588 */ 0x236a6, 0x0, 0x0, 0x24994, 0x27165, 0x23e31, 0x2555c, 0x23efb,
+/* E590 */ 0x27052, 0x0, 0x236ee, 0x2999d, 0x26f26, 0x0, 0x0, 0x0,
+/* E598 */ 0x0, 0x0, 0x21922, 0x0, 0x0, 0x2373f, 0x240e1, 0x2408b,
+/* E5A0 */ 0x2410f, 0x26c21, 0x0, 0x0, 0x266b1, 0x0, 0x20fdf, 0x20ba8,
+/* E5A8 */ 0x20e0d, 0x0, 0x28b13, 0x0, 0x0, 0x0, 0x0, 0x24436,
+/* E5B0 */ 0x0, 0x20465, 0x2037f, 0x0, 0x0, 0x25651, 0x0, 0x201ab,
+/* E5B8 */ 0x203cb, 0x0, 0x2030a, 0x20414, 0x0, 0x0, 0x202c0, 0x28eb3,
+/* E5C0 */ 0x20275, 0x0, 0x2020c, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E5C8 */ 0x24a0e, 0x23e8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E5D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x23595,
+/* E5D8 */ 0x23e39, 0x23ebf, 0x0, 0x21884, 0x23e89, 0x0, 0x0, 0x205e0,
+/* E5E0 */ 0x0, 0x204a3, 0x20492, 0x20491, 0x0, 0x28a9c, 0x2070e, 0x0,
+/* E5E8 */ 0x0, 0x20873, 0x0, 0x0, 0x0, 0x0, 0x2438c, 0x20c20,
+/* E5F0 */ 0x249ac, 0x210e4, 0x0, 0x20e1d, 0x0, 0x0, 0x0, 0x0,
+/* E5F8 */ 0x0, 0x0, 0x0, 0x24abc, 0x2408d, 0x0, 0x0, 0x0,
+/* E600 */ 0x240c9, 0x0, 0x20345, 0x0, 0x20bc6, 0x0, 0x0, 0x0,
+/* E608 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28a46,
+/* E610 */ 0x216fa, 0x2176f, 0x21710, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E618 */ 0x0, 0x25946, 0x219f3, 0x21861, 0x24295, 0x0, 0x0, 0x0,
+/* E620 */ 0x0, 0x25e83, 0x0, 0x28bd7, 0x20413, 0x0, 0x0, 0x21303,
+/* E628 */ 0x0, 0x0, 0x0, 0x289fb, 0x0, 0x0, 0x0, 0x0,
+/* E630 */ 0x0, 0x0, 0x21996, 0x2197c, 0x23aee, 0x0, 0x0, 0x21903,
+/* E638 */ 0x21904, 0x0, 0x218a0, 0x0, 0x216fe, 0x0, 0x0, 0x28a47,
+/* E640 */ 0x21dba, 0x23472, 0x289a8, 0x0, 0x0, 0x21927, 0x217ab, 0x0,
+/* E648 */ 0x2173b, 0x0, 0x0, 0x275fd, 0x0, 0x0, 0x22860, 0x2262b,
+/* E650 */ 0x0, 0x0, 0x225af, 0x225be, 0x29088, 0x26f73, 0x0, 0x2003e,
+/* E658 */ 0x20046, 0x2261b, 0x0, 0x0, 0x0, 0x22c9b, 0x22d07, 0x246d4,
+/* E660 */ 0x2914d, 0x0, 0x24665, 0x22b6a, 0x0, 0x22b22, 0x23450, 0x298ea,
+/* E668 */ 0x22e78, 0x0, 0x2a45b, 0x0, 0x0, 0x0, 0x249e3, 0x22d67,
+/* E670 */ 0x0, 0x22ca1, 0x0, 0x0, 0x0, 0x0, 0x2308e, 0x232ad,
+/* E678 */ 0x24989, 0x232ab, 0x0, 0x232e0, 0x218d9, 0x2943f, 0x0, 0x23289,
+/* E680 */ 0x231b3, 0x0, 0x0, 0x25584, 0x28b22, 0x2558f, 0x216fc, 0x2555b,
+/* E688 */ 0x25425, 0x0, 0x23103, 0x2182a, 0x23234, 0x0, 0x2320f, 0x23182,
+/* E690 */ 0x242c9, 0x0, 0x26d24, 0x0, 0x0, 0x0, 0x27870, 0x21deb,
+/* E698 */ 0x0, 0x232d2, 0x232e1, 0x0, 0x25872, 0x0, 0x2383a, 0x237bc,
+/* E6A0 */ 0x0, 0x237a2, 0x233fe, 0x0, 0x0, 0x0, 0x2462a, 0x0,
+/* E6A8 */ 0x0, 0x0, 0x0, 0x0, 0x237d5, 0x24487, 0x0, 0x0,
+/* E6B0 */ 0x0, 0x0, 0x21912, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E6B8 */ 0x0, 0x23fc0, 0x23c9a, 0x0, 0x0, 0x28bea, 0x28acb, 0x0,
+/* E6C0 */ 0x2801e, 0x289dc, 0x0, 0x0, 0x0, 0x249ec, 0x0, 0x23f7f,
+/* E6C8 */ 0x0, 0x0, 0x2403c, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E6D0 */ 0x0, 0x2431a, 0x24276, 0x0, 0x0, 0x0, 0x0, 0x2478f,
+/* E6D8 */ 0x24725, 0x0, 0x24aa4, 0x205eb, 0x0, 0x23ef8, 0x2365f, 0x24a4a,
+/* E6E0 */ 0x24917, 0x25fe1, 0x0, 0x0, 0x24adf, 0x28c23, 0x23f35, 0x0,
+/* E6E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26dea, 0x0,
+/* E6F0 */ 0x0, 0x0, 0x24cd9, 0x24d06, 0x0, 0x0, 0x0, 0x2a5c6,
+/* E6F8 */ 0x0, 0x0, 0x28acc, 0x249ab, 0x2498e, 0x0, 0x0, 0x24a4e,
+/* E700 */ 0x0, 0x249c5, 0x248f3, 0x0, 0x0, 0x0, 0x28ae3, 0x21864,
+/* E708 */ 0x0, 0x25221, 0x251e7, 0x0, 0x23232, 0x0, 0x0, 0x0,
+/* E710 */ 0x24697, 0x23781, 0x0, 0x248f0, 0x0, 0x0, 0x0, 0x24aba,
+/* E718 */ 0x24ac7, 0x0, 0x24a96, 0x261ae, 0x0, 0x25581, 0x0, 0x0,
+/* E720 */ 0x0, 0x0, 0x0, 0x0, 0x27741, 0x256e3, 0x0, 0x0,
+/* E728 */ 0x0, 0x0, 0x0, 0x23efa, 0x0, 0x0, 0x0, 0x216e6,
+/* E730 */ 0x0, 0x0, 0x0, 0x20d4c, 0x2498c, 0x20299, 0x23dba, 0x2176e,
+/* E738 */ 0x0, 0x0, 0x0, 0x0, 0x201d4, 0x20c0d, 0x0, 0x0,
+/* E740 */ 0x226f5, 0x25aaf, 0x25a9c, 0x0, 0x2025b, 0x0, 0x0, 0x25bc6,
+/* E748 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x25bb3, 0x25ebc, 0x25ea6,
+/* E750 */ 0x0, 0x249f9, 0x217b0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E758 */ 0x0, 0x0, 0x0, 0x26261, 0x2615c, 0x27b48, 0x0, 0x25e82,
+/* E760 */ 0x0, 0x26b75, 0x20916, 0x0, 0x2004e, 0x235cf, 0x0, 0x26412,
+/* E768 */ 0x263f8, 0x24962, 0x0, 0x0, 0x2082c, 0x25ae9, 0x25d43, 0x0,
+/* E770 */ 0x25e0e, 0x0, 0x0, 0x0, 0x0, 0x2343f, 0x0, 0x249f7,
+/* E778 */ 0x265ad, 0x0, 0x265a0, 0x0, 0x27127, 0x26cd1, 0x0, 0x0,
+/* E780 */ 0x0, 0x0, 0x0, 0x0, 0x267b4, 0x0, 0x26a42, 0x0,
+/* E788 */ 0x0, 0x26a51, 0x0, 0x26da7, 0x0, 0x2721b, 0x0, 0x0,
+/* E790 */ 0x21840, 0x0, 0x218a1, 0x0, 0x218d8, 0x0, 0x2f9bc, 0x23d8f,
+/* E798 */ 0x0, 0x27422, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E7A0 */ 0x0, 0x0, 0x25683, 0x0, 0x27785, 0x27784, 0x28bf5, 0x28bd9,
+/* E7A8 */ 0x28b9c, 0x289f9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E7B0 */ 0x0, 0x29448, 0x0, 0x0, 0x24284, 0x0, 0x0, 0x0,
+/* E7B8 */ 0x21845, 0x0, 0x0, 0x0, 0x27ddc, 0x0, 0x0, 0x0,
+/* E7C0 */ 0x0, 0x0, 0x0, 0x0, 0x24c09, 0x0, 0x0, 0x0,
+/* E7C8 */ 0x0, 0x0, 0x22321, 0x0, 0x0, 0x0, 0x217da, 0x0,
+/* E7D0 */ 0x0, 0x2492f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E7D8 */ 0x28a4b, 0x0, 0x28afc, 0x0, 0x28c1d, 0x28c3b, 0x0, 0x0,
+/* E7E0 */ 0x0, 0x0, 0x0, 0x0, 0x28d34, 0x0, 0x0, 0x248ff,
+/* E7E8 */ 0x24a42, 0x243ea, 0x0, 0x23225, 0x0, 0x28ee7, 0x28e66, 0x28e65,
+/* E7F0 */ 0x0, 0x249ed, 0x24a78, 0x23fee, 0x0, 0x0, 0x0, 0x0,
+/* E7F8 */ 0x290b0, 0x0, 0x0, 0x29093, 0x257df, 0x0, 0x0, 0x28989,
+/* E800 */ 0x28c26, 0x28b2f, 0x263be, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E808 */ 0x2421b, 0x0, 0x0, 0x0, 0x20f26, 0x0, 0x28bc5, 0x24ab2,
+/* E810 */ 0x0, 0x294da, 0x0, 0x295d7, 0x0, 0x0, 0x28b50, 0x24a67,
+/* E818 */ 0x28b64, 0x0, 0x28a45, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E820 */ 0x0, 0x27b06, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28b65,
+/* E828 */ 0x258c8, 0x0, 0x0, 0x0, 0x0, 0x298f1, 0x0, 0x29948,
+/* E830 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x21302, 0x0, 0x249b8,
+/* E838 */ 0x214e8, 0x0, 0x2271f, 0x23db8, 0x0, 0x0, 0x0, 0x0,
+/* E840 */ 0x0, 0x22781, 0x2296b, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E848 */ 0x0, 0x0, 0x0, 0x29e2d, 0x0, 0x2a1f5, 0x2a0fe, 0x0,
+/* E850 */ 0x0, 0x24104, 0x0, 0x0, 0x0, 0x2a1b4, 0x2a0ed, 0x2a0f3,
+/* E858 */ 0x2992f, 0x0, 0x0, 0x26e12, 0x26fdf, 0x26b82, 0x0, 0x0,
+/* E860 */ 0x26da4, 0x26e84, 0x26df0, 0x0, 0x0, 0x26e00, 0x237d7, 0x26064,
+/* E868 */ 0x0, 0x2359c, 0x23640, 0x0, 0x249de, 0x0, 0x0, 0x0,
+/* E870 */ 0x0, 0x202bf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E878 */ 0x2555d, 0x0, 0x0, 0x0, 0x0, 0x21757, 0x231c9, 0x24941,
+/* E880 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x241b5,
+/* E888 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x241ac,
+/* E890 */ 0x0, 0x26c40, 0x24f97, 0x0, 0x217b5, 0x28a49, 0x0, 0x0,
+/* E898 */ 0x0, 0x0, 0x24488, 0x0, 0x0, 0x289fc, 0x0, 0x0,
+/* E8A0 */ 0x218d6, 0x20f1d, 0x0, 0x26cc0, 0x21413, 0x242fa, 0x22c26, 0x243c1,
+/* E8A8 */ 0x0, 0x23db7, 0x26741, 0x0, 0x2615b, 0x260a4, 0x249b9, 0x2498b,
+/* E8B0 */ 0x289fa, 0x0, 0x0, 0x0, 0x0, 0x28b63, 0x2189f, 0x0,
+/* E8B8 */ 0x24ab3, 0x0, 0x0, 0x0, 0x0, 0x24a3e, 0x24a94, 0x217d9,
+/* E8C0 */ 0x24a66, 0x203a7, 0x21424, 0x249e5, 0x0, 0x24916, 0x0, 0x24976,
+/* E8C8 */ 0x0, 0x0, 0x0, 0x204fe, 0x0, 0x28ace, 0x28a16, 0x0,
+/* E8D0 */ 0x28be7, 0x255d5, 0x0, 0x28a82, 0x0, 0x24943, 0x20cff, 0x0,
+/* E8D8 */ 0x2061a, 0x20beb, 0x20cb8, 0x0, 0x0, 0x217fa, 0x0, 0x216c2,
+/* E8E0 */ 0x24a50, 0x21852, 0x0, 0x0, 0x0, 0x28ac0, 0x249ad, 0x0,
+/* E8E8 */ 0x218bf, 0x21883, 0x27484, 0x0, 0x0, 0x23d5b, 0x0, 0x0,
+/* E8F0 */ 0x0, 0x28a81, 0x21862, 0x0, 0x0, 0x20ab4, 0x0, 0x0,
+/* E8F8 */ 0x0, 0x0, 0x0, 0x2139c, 0x0, 0x0, 0x28218, 0x0,
+/* E900 */ 0x290e4, 0x0, 0x0, 0x27e4f, 0x0, 0x0, 0x0, 0x23fed,
+/* E908 */ 0x23e2d, 0x0, 0x0, 0x0, 0x203f5, 0x0, 0x0, 0x0,
+/* E910 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28c1c,
+/* E918 */ 0x26bc0, 0x0, 0x0, 0x0, 0x21452, 0x0, 0x24362, 0x24a71,
+/* E920 */ 0x22fe3, 0x212b0, 0x223bd, 0x0, 0x0, 0x21398, 0x234e5, 0x27bf4,
+/* E928 */ 0x236df, 0x28a83, 0x237d6, 0x233fa, 0x24c9f, 0x0, 0x236ad, 0x26cb7,
+/* E930 */ 0x0, 0x0, 0x0, 0x26d26, 0x26d51, 0x26c82, 0x26fde, 0x0,
+/* E938 */ 0x27109, 0x0, 0x2173a, 0x0, 0x26c80, 0x27053, 0x217db, 0x0,
+/* E940 */ 0x0, 0x217b3, 0x0, 0x0, 0x21905, 0x241fc, 0x0, 0x0,
+/* E948 */ 0x2173c, 0x0, 0x0, 0x0, 0x0, 0x242a5, 0x0, 0x0,
+/* E950 */ 0x24293, 0x0, 0x23ef9, 0x27736, 0x2445b, 0x242ca, 0x0, 0x24259,
+/* E958 */ 0x289e1, 0x0, 0x26d28, 0x0, 0x244ce, 0x27e4d, 0x243bd, 0x0,
+/* E960 */ 0x24256, 0x21304, 0x0, 0x0, 0x243e9, 0x0, 0x0, 0x2f825,
+/* E968 */ 0x24a4f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24a5d, 0x217df,
+/* E970 */ 0x0, 0x0, 0x0, 0x23afa, 0x23300, 0x20214, 0x0, 0x208d5,
+/* E978 */ 0x20619, 0x0, 0x21f9e, 0x2a2b6, 0x0, 0x2915b, 0x0, 0x0,
+/* E980 */ 0x0, 0x28a59, 0x29420, 0x0, 0x0, 0x0, 0x0, 0x27af4,
+/* E988 */ 0x0, 0x0, 0x256f6, 0x0, 0x0, 0x0, 0x27b18, 0x0,
+/* E990 */ 0x0, 0x248f2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E998 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9B0 */ 0x24f5c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9C8 */ 0x0, 0x0, 0x0, 0x25535, 0x0, 0x0, 0x0, 0x0,
+/* E9D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20ccf,
+/* E9F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* E9F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA00 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA08 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA10 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA18 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA20 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA28 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA30 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA38 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA40 */ 0x0, 0x0, 0x0, 0x27967, 0x0, 0x0, 0x0, 0x0,
+/* EA48 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA50 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA58 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA60 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA68 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA70 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA78 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA80 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA88 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA90 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EA98 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EAA0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EAA8 */ 0x0, 0x21bc2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EAB0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EAB8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20094,
+/* EAC0 */ 0x202b7, 0x203a0, 0x0, 0x0, 0x0, 0x204d7, 0x0, 0x0,
+/* EAC8 */ 0x0, 0x205d5, 0x20615, 0x20676, 0x216ba, 0x0, 0x0, 0x20ac2,
+/* EAD0 */ 0x20acd, 0x20bbf, 0x0, 0x2f83b, 0x20bcb, 0x0, 0x20bfb, 0x20c3b,
+/* EAD8 */ 0x20c53, 0x20c65, 0x20c7c, 0x0, 0x20c8d, 0x0, 0x20cb5, 0x20cdd,
+/* EAE0 */ 0x20ced, 0x20d6f, 0x20db2, 0x20dc8, 0x0, 0x0, 0x0, 0x20e04,
+/* EAE8 */ 0x20e0e, 0x20ed7, 0x20f90, 0x20f2d, 0x20e73, 0x0, 0x20fbc, 0x0,
+/* EAF0 */ 0x2105c, 0x2104f, 0x21076, 0x0, 0x2107b, 0x21088, 0x21096, 0x0,
+/* EAF8 */ 0x210bf, 0x210d3, 0x2112f, 0x2113b, 0x0, 0x0, 0x212e3, 0x21375,
+/* EB00 */ 0x21336, 0x0, 0x21577, 0x21619, 0x217c3, 0x217c7, 0x0, 0x0,
+/* EB08 */ 0x2182d, 0x2196a, 0x21a2d, 0x21a45, 0x21c2a, 0x21c70, 0x21cac, 0x21ec8,
+/* EB10 */ 0x0, 0x21ed5, 0x21f15, 0x0, 0x0, 0x22045, 0x0, 0x0,
+/* EB18 */ 0x2227c, 0x223d7, 0x223fa, 0x2272a, 0x22871, 0x2294f, 0x0, 0x22967,
+/* EB20 */ 0x22993, 0x22ad5, 0x0, 0x22ae8, 0x0, 0x22b0e, 0x0, 0x22b3f,
+/* EB28 */ 0x0, 0x0, 0x22c4c, 0x0, 0x22c88, 0x22cb7, 0x25be8, 0x22d08,
+/* EB30 */ 0x22d12, 0x22db7, 0x22d95, 0x22e42, 0x22f74, 0x22fcc, 0x23033, 0x23066,
+/* EB38 */ 0x2331f, 0x233de, 0x0, 0x0, 0x0, 0x27a79, 0x23567, 0x235f3,
+/* EB40 */ 0x0, 0x249ba, 0x0, 0x2361a, 0x23716, 0x0, 0x20346, 0x0,
+/* EB48 */ 0x0, 0x0, 0x23aa7, 0x27657, 0x25fe2, 0x23e11, 0x23eb9, 0x275fe,
+/* EB50 */ 0x2209a, 0x0, 0x0, 0x24119, 0x28a9a, 0x242ee, 0x2430d, 0x2403b,
+/* EB58 */ 0x24334, 0x24396, 0x24a45, 0x205ca, 0x0, 0x20611, 0x0, 0x21ea8,
+/* EB60 */ 0x0, 0x23cff, 0x24404, 0x244d6, 0x0, 0x24674, 0x0, 0x2472f,
+/* EB68 */ 0x285e8, 0x299c9, 0x0, 0x221c3, 0x0, 0x28b4e, 0x0, 0x24812,
+/* EB70 */ 0x248fb, 0x24a15, 0x0, 0x24ac0, 0x20c78, 0x0, 0x24ea5, 0x24f86,
+/* EB78 */ 0x20779, 0x0, 0x2502c, 0x0, 0x0, 0x0, 0x25299, 0x25419,
+/* EB80 */ 0x23f4a, 0x24aa7, 0x0, 0x25446, 0x2546e, 0x26b52, 0x0, 0x0,
+/* EB88 */ 0x2553f, 0x27632, 0x2555e, 0x0, 0x25562, 0x25566, 0x257c7, 0x2493f,
+/* EB90 */ 0x2585d, 0x0, 0x0, 0x233cc, 0x0, 0x25903, 0x0, 0x28948,
+/* EB98 */ 0x25aae, 0x25b89, 0x25c06, 0x21d90, 0x0, 0x0, 0x0, 0x26102,
+/* EBA0 */ 0x27c12, 0x0, 0x261b2, 0x24f9a, 0x0, 0x26402, 0x2644a, 0x0,
+/* EBA8 */ 0x26bf7, 0x0, 0x26484, 0x2191c, 0x0, 0x249f6, 0x26488, 0x23fef,
+/* EBB0 */ 0x26512, 0x0, 0x265bf, 0x266b5, 0x2271b, 0x0, 0x257e1, 0x0,
+/* EBB8 */ 0x0, 0x2f8cd, 0x0, 0x0, 0x24521, 0x266fc, 0x0, 0x24934,
+/* EBC0 */ 0x0, 0x0, 0x26cbd, 0x0, 0x0, 0x26799, 0x2686e, 0x26411,
+/* EBC8 */ 0x2685e, 0x0, 0x268c7, 0x0, 0x290c0, 0x20a11, 0x26926, 0x0,
+/* EBD0 */ 0x26939, 0x0, 0x0, 0x269fa, 0x0, 0x26a2d, 0x0, 0x26469,
+/* EBD8 */ 0x20021, 0x0, 0x26a34, 0x26b5b, 0x0, 0x23519, 0x0, 0x26b9d,
+/* EBE0 */ 0x0, 0x26ca4, 0x0, 0x0, 0x26dae, 0x0, 0x0, 0x2258d,
+/* EBE8 */ 0x2704b, 0x271cd, 0x0, 0x27280, 0x27285, 0x0, 0x2217a, 0x2728b,
+/* EBF0 */ 0x0, 0x272e6, 0x249d0, 0x0, 0x0, 0x27450, 0x20ef8, 0x0,
+/* EBF8 */ 0x0, 0x22926, 0x28473, 0x217b1, 0x0, 0x24a2a, 0x21820, 0x0,
+/* EC00 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x29cad, 0x298a4, 0x0,
+/* EC08 */ 0x277cc, 0x27858, 0x0, 0x0, 0x2160a, 0x0, 0x2372f, 0x280e8,
+/* EC10 */ 0x213c5, 0x0, 0x0, 0x279dd, 0x291a8, 0x0, 0x0, 0x270af,
+/* EC18 */ 0x289ab, 0x279fd, 0x27a0a, 0x27b0b, 0x27d66, 0x2417a, 0x0, 0x0,
+/* EC20 */ 0x28009, 0x0, 0x2a2df, 0x0, 0x28318, 0x0, 0x26e07, 0x0,
+/* EC28 */ 0x0, 0x0, 0x2816f, 0x28023, 0x269b5, 0x213ed, 0x2322f, 0x28048,
+/* EC30 */ 0x0, 0x28c30, 0x28083, 0x0, 0x0, 0x28949, 0x0, 0x24988,
+/* EC38 */ 0x0, 0x0, 0x0, 0x24aa5, 0x23f81, 0x0, 0x0, 0x28090,
+/* EC40 */ 0x280f4, 0x2812e, 0x21fa1, 0x2814f, 0x28189, 0x281af, 0x2821a, 0x28306,
+/* EC48 */ 0x2832f, 0x2838a, 0x0, 0x28468, 0x286aa, 0x0, 0x0, 0x28956,
+/* EC50 */ 0x0, 0x0, 0x289b8, 0x0, 0x289e7, 0x0, 0x289e8, 0x28b46,
+/* EC58 */ 0x28bd4, 0x0, 0x28c09, 0x0, 0x28fc5, 0x290ec, 0x0, 0x29110,
+/* EC60 */ 0x2913c, 0x0, 0x2915e, 0x24aca, 0x0, 0x0, 0x0, 0x294e7,
+/* EC68 */ 0x295e9, 0x295b0, 0x295b8, 0x29732, 0x298d1, 0x29949, 0x2996a, 0x299c3,
+/* EC70 */ 0x29a28, 0x29b0e, 0x29d5a, 0x29d9b, 0x0, 0x29ef8, 0x29f23, 0x0,
+/* EC78 */ 0x0, 0x2a293, 0x0, 0x2a2ff, 0x0, 0x0, 0x2a5cb, 0x0,
+/* EC80 */ 0x20c9c, 0x0, 0x0, 0x0, 0x224b0, 0x0, 0x24a93, 0x0,
+/* EC88 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x28b2c, 0x2789d, 0x0,
+/* EC90 */ 0x0, 0x217f5, 0x28024, 0x28b6c, 0x28b99, 0x27a3e, 0x266af, 0x0,
+/* EC98 */ 0x27655, 0x23cb7, 0x25635, 0x25956, 0x0, 0x25e81, 0x26258, 0x0,
+/* ECA0 */ 0x20e6d, 0x0, 0x0, 0x23e88, 0x24c9e, 0x0, 0x0, 0x217f6,
+/* ECA8 */ 0x2187b, 0x0, 0x0, 0x25c4a, 0x0, 0x25311, 0x0, 0x29d98,
+/* ECB0 */ 0x0, 0x0, 0x0, 0x0, 0x25ed8, 0x0, 0x23d40, 0x0,
+/* ECB8 */ 0x0, 0x20fea, 0x20d49, 0x236ba, 0x0, 0x0, 0x0, 0x0,
+/* ECC0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ECC8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20e9d,
+/* ECD0 */ 0x0, 0x0, 0x0, 0x0, 0x282e2, 0x0, 0x0, 0x0,
+/* ECD8 */ 0x0, 0x0, 0x0, 0x20c41, 0x20c96, 0x0, 0x25148, 0x20e76,
+/* ECE0 */ 0x22c62, 0x20ea2, 0x0, 0x0, 0x0, 0x21075, 0x0, 0x0,
+/* ECE8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ECF0 */ 0x22b43, 0x0, 0x22eb3, 0x0, 0x0, 0x20da7, 0x0, 0x0,
+/* ECF8 */ 0x0, 0x0, 0x0, 0x0, 0x2688a, 0x0, 0x0, 0x0,
+/* ED00 */ 0x0, 0x0, 0x0, 0x0, 0x210c1, 0x0, 0x0, 0x24706,
+/* ED08 */ 0x0, 0x0, 0x26893, 0x0, 0x226f4, 0x27d2f, 0x241a3, 0x27d73,
+/* ED10 */ 0x26ed0, 0x272b6, 0x0, 0x211d9, 0x0, 0x23cfc, 0x2a6a9, 0x20eac,
+/* ED18 */ 0x20ef9, 0x0, 0x21ca2, 0x0, 0x24fc2, 0x27ff9, 0x20feb, 0x0,
+/* ED20 */ 0x0, 0x0, 0x22da0, 0x0, 0x247e0, 0x29d7c, 0x20fec, 0x20e0a,
+/* ED28 */ 0x0, 0x275a3, 0x20fed, 0x0, 0x26048, 0x21187, 0x0, 0x0,
+/* ED30 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ED38 */ 0x0, 0x0, 0x0, 0x24618, 0x0, 0x24b6e, 0x0, 0x0,
+/* ED40 */ 0x0, 0x25a95, 0x20979, 0x0, 0x0, 0x22465, 0x0, 0x29eac,
+/* ED48 */ 0x0, 0x0, 0x23cfe, 0x29f30, 0x0, 0x24fa9, 0x2959e, 0x29fde,
+/* ED50 */ 0x0, 0x23db6, 0x272b2, 0x267b3, 0x23720, 0x0, 0x0, 0x23ef7,
+/* ED58 */ 0x23e2c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2048e,
+/* ED60 */ 0x0, 0x0, 0x20eb6, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ED68 */ 0x0, 0x0, 0x0, 0x2a434, 0x0, 0x0, 0x0, 0x0,
+/* ED70 */ 0x0, 0x230da, 0x243f2, 0x0, 0x0, 0x212a9, 0x0, 0x24963,
+/* ED78 */ 0x29e06, 0x0, 0x270ae, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ED80 */ 0x0, 0x2176c, 0x0, 0x0, 0x294d0, 0x26335, 0x27164, 0x0,
+/* ED88 */ 0x20d28, 0x26d22, 0x24ae2, 0x20d71, 0x0, 0x0, 0x21f0f, 0x0,
+/* ED90 */ 0x0, 0x21dd1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* ED98 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDA0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2493e, 0x0,
+/* EDA8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDB0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDB8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDC0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2176d, 0x0,
+/* EDC8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28e97,
+/* EDD0 */ 0x0, 0x26d23, 0x0, 0x0, 0x0, 0x0, 0x0, 0x203fc,
+/* EDD8 */ 0x0, 0x0, 0x25c21, 0x23cfd, 0x0, 0x24919, 0x0, 0x0,
+/* EDE0 */ 0x0, 0x20cd4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDE8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x201f2, 0x0, 0x0,
+/* EDF0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EDF8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE00 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE08 */ 0x2a64a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE10 */ 0x0, 0x2837d, 0x0, 0x0, 0x0, 0x24a77, 0x0, 0x0,
+/* EE18 */ 0x0, 0x0, 0x0, 0x28a5a, 0x0, 0x0, 0x0, 0x0,
+/* EE20 */ 0x2a2b2, 0x0, 0x2f840, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE28 */ 0x0, 0x0, 0x24abb, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE30 */ 0x2183b, 0x26e05, 0x0, 0x0, 0x2251b, 0x0, 0x0, 0x0,
+/* EE38 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE40 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE48 */ 0x26159, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE50 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x233f5, 0x0,
+/* EE58 */ 0x0, 0x0, 0x0, 0x28bc2, 0x0, 0x28e39, 0x0, 0x0,
+/* EE60 */ 0x21d46, 0x0, 0x0, 0x0, 0x20f3b, 0x0, 0x0, 0x0,
+/* EE68 */ 0x0, 0x0, 0x25f1a, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE70 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x27486, 0x0,
+/* EE78 */ 0x0, 0x0, 0x0, 0x0, 0x267cc, 0x0, 0x26ed1, 0x0,
+/* EE80 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE88 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE90 */ 0x0, 0x24011, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EE98 */ 0x0, 0x0, 0x0, 0x0, 0x28b2d, 0x0, 0x0, 0x0,
+/* EEA0 */ 0x0, 0x0, 0x23cc7, 0x25ed7, 0x27656, 0x25531, 0x21944, 0x212fe,
+/* EEA8 */ 0x29903, 0x26ddc, 0x270ad, 0x0, 0x261ad, 0x28a0f, 0x23677, 0x200ee,
+/* EEB0 */ 0x26846, 0x24f0e, 0x0, 0x0, 0x2634c, 0x0, 0x0, 0x2626b,
+/* EEB8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEC0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEC8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EED0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EED8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEE0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEE8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEF0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EEF8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF00 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF08 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF10 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF18 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF20 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF28 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF30 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF38 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF40 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF48 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF50 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF58 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF60 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF68 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF70 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF78 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF80 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF88 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF90 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EF98 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFA0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFA8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFB0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFB8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFC0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFC8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFD0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFD8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFE0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFE8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFF0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* EFF8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F000 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F008 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F010 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F018 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F020 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F028 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F030 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F038 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F040 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F048 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F050 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F058 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F060 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F068 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F070 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F078 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F080 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F088 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F090 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F098 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F0F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F100 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F108 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F110 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F118 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F120 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F128 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F130 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F138 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F140 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F148 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F150 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F158 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F160 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F168 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F170 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F178 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F180 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F188 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F190 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F198 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F1F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F200 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F208 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F210 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F218 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F220 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F228 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F230 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F238 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F240 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F248 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F250 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F258 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F260 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F268 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F270 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F278 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F280 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F288 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F290 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F298 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F2F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F300 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F308 */ 0x2010c, 0x0, 0x200d1, 0x200cd, 0x0, 0x0, 0x200cb, 0x21fe8,
+/* F310 */ 0x0, 0x200ca, 0x0, 0x0, 0x0, 0x0, 0x2010e, 0x0,
+/* F318 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F320 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F328 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F330 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F338 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F340 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F348 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F350 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F358 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F360 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F368 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F370 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F378 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F380 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F388 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F390 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F398 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3A0 */ 0x2a3a9, 0x21145, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3A8 */ 0x0, 0x0, 0x0, 0x0, 0x27735, 0x0, 0x0, 0x0,
+/* F3B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3F0 */ 0x209e7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F3F8 */ 0x0, 0x29df6, 0x2700e, 0x0, 0x2a133, 0x0, 0x0, 0x0,
+/* F400 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F408 */ 0x2846c, 0x21dca, 0x205d0, 0x22ae6, 0x0, 0x0, 0x0, 0x0,
+/* F410 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F418 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F420 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F428 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F430 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F438 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x27d84, 0x0, 0x0,
+/* F440 */ 0x20c42, 0x20d15, 0x2512b, 0x0, 0x22cc6, 0x0, 0x20341, 0x0,
+/* F448 */ 0x24db8, 0x294e5, 0x0, 0x280be, 0x0, 0x22c38, 0x0, 0x0,
+/* F450 */ 0x2815d, 0x269f2, 0x24dea, 0x0, 0x20d7c, 0x20fb4, 0x20cd5, 0x210f4,
+/* F458 */ 0x0, 0x0, 0x20e96, 0x20c0b, 0x20f64, 0x22ca9, 0x28256, 0x244d3,
+/* F460 */ 0x0, 0x20d46, 0x29a4d, 0x280e9, 0x0, 0x24ea7, 0x22cc2, 0x0,
+/* F468 */ 0x0, 0x295f4, 0x0, 0x0, 0x252c7, 0x297d4, 0x278c8, 0x22d44,
+/* F470 */ 0x0, 0x0, 0x0, 0x0, 0x260a5, 0x0, 0x0, 0x22d4c,
+/* F478 */ 0x22bca, 0x21077, 0x0, 0x2106f, 0x266da, 0x26716, 0x279a0, 0x0,
+/* F480 */ 0x25052, 0x20c43, 0x0, 0x221a1, 0x28b4c, 0x20731, 0x0, 0x0,
+/* F488 */ 0x201a9, 0x0, 0x0, 0x22d8d, 0x0, 0x245c8, 0x204fc, 0x26097,
+/* F490 */ 0x20f4c, 0x20d96, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22a66,
+/* F498 */ 0x2109d, 0x0, 0x0, 0x20d9c, 0x0, 0x0, 0x22775, 0x0,
+/* F4A0 */ 0x0, 0x0, 0x0, 0x0, 0x2a601, 0x20e09, 0x22acf, 0x22cc9,
+/* F4A8 */ 0x0, 0x210c8, 0x239c2, 0x0, 0x0, 0x2829b, 0x0, 0x25e49,
+/* F4B0 */ 0x220c7, 0x0, 0x20f31, 0x22cb2, 0x29720, 0x0, 0x0, 0x24e3b,
+/* F4B8 */ 0x0, 0x0, 0x27574, 0x22e8b, 0x22208, 0x2a65b, 0x28ccd, 0x20e7a,
+/* F4C0 */ 0x20c34, 0x2681c, 0x0, 0x210cf, 0x22803, 0x22939, 0x0, 0x251e3,
+/* F4C8 */ 0x20e8c, 0x20f8d, 0x20eaa, 0x0, 0x20f30, 0x20d47, 0x2114f, 0x20e4c,
+/* F4D0 */ 0x0, 0x20eab, 0x20ba9, 0x20d48, 0x210c0, 0x2113d, 0x0, 0x22696,
+/* F4D8 */ 0x0, 0x20fad, 0x233f4, 0x27639, 0x22bce, 0x20d7e, 0x20d7f, 0x22c51,
+/* F4E0 */ 0x22c55, 0x0, 0x20e98, 0x210c7, 0x20f2e, 0x2a632, 0x26b50, 0x28cd2,
+/* F4E8 */ 0x28d99, 0x28cca, 0x0, 0x0, 0x0, 0x0, 0x0, 0x29ec3,
+/* F4F0 */ 0x0, 0x0, 0x2775e, 0x22dee, 0x0, 0x0, 0x0, 0x0,
+/* F4F8 */ 0x26572, 0x0, 0x0, 0x0, 0x280bd, 0x0, 0x20efa, 0x20e0f,
+/* F500 */ 0x20e77, 0x20efb, 0x0, 0x24deb, 0x0, 0x20cd6, 0x0, 0x227b5,
+/* F508 */ 0x210c9, 0x20e10, 0x20e78, 0x21078, 0x21148, 0x28207, 0x21455, 0x20e79,
+/* F510 */ 0x24e50, 0x22da4, 0x0, 0x2101d, 0x2101e, 0x210f5, 0x210f6, 0x0,
+/* F518 */ 0x20e11, 0x27694, 0x282cd, 0x20fb5, 0x20e7b, 0x2517e, 0x0, 0x20fb6,
+/* F520 */ 0x21180, 0x252d8, 0x2a2bd, 0x249da, 0x2183a, 0x24177, 0x2827c, 0x0,
+/* F528 */ 0x0, 0x0, 0x2573d, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F530 */ 0x0, 0x0, 0x0, 0x25b74, 0x2313d, 0x0, 0x0, 0x0,
+/* F538 */ 0x0, 0x0, 0x21bc1, 0x2f878, 0x0, 0x20086, 0x0, 0x0,
+/* F540 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F548 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x248e9, 0x0,
+/* F550 */ 0x0, 0x0, 0x0, 0x2626a, 0x0, 0x0, 0x2634b, 0x0,
+/* F558 */ 0x0, 0x26612, 0x26951, 0x0, 0x0, 0x0, 0x278b2, 0x0,
+/* F560 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x28e0f, 0x0, 0x0,
+/* F568 */ 0x0, 0x0, 0x0, 0x29810, 0x0, 0x0, 0x0, 0x0,
+/* F570 */ 0x0, 0x0, 0x20087, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F578 */ 0x0, 0x29c73, 0x0, 0x0, 0x0, 0x2414e, 0x0, 0x0,
+/* F580 */ 0x0, 0x251cd, 0x0, 0x25d30, 0x0, 0x28a32, 0x0, 0x0,
+/* F588 */ 0x0, 0x0, 0x0, 0x23281, 0x2a107, 0x0, 0x21980, 0x0,
+/* F590 */ 0x0, 0x0, 0x0, 0x2870f, 0x0, 0x0, 0x2a2ba, 0x0,
+/* F598 */ 0x0, 0x0, 0x0, 0x29947, 0x28aea, 0x0, 0x0, 0x0,
+/* F5A0 */ 0x2207e, 0x0, 0x0, 0x289e3, 0x0, 0x0, 0x0, 0x0,
+/* F5A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5B0 */ 0x21db6, 0x0, 0x0, 0x0, 0x22712, 0x0, 0x233f9, 0x0,
+/* F5B8 */ 0x0, 0x23c63, 0x0, 0x0, 0x0, 0x24505, 0x0, 0x0,
+/* F5C0 */ 0x24a13, 0x0, 0x0, 0x0, 0x25ca4, 0x25695, 0x0, 0x0,
+/* F5C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28db9, 0x2143f,
+/* F5D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5E0 */ 0x0, 0x0, 0x0, 0x0, 0x2497b, 0x0, 0x2710d, 0x0,
+/* F5E8 */ 0x26d74, 0x0, 0x26b15, 0x26fbe, 0x0, 0x0, 0x0, 0x0,
+/* F5F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F5F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F600 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F608 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F610 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F618 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F620 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F628 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F630 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F638 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F640 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F648 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F650 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F658 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F660 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F668 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F670 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F678 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F680 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F688 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F690 */ 0x0, 0x0, 0x0, 0x0, 0x289c0, 0x0, 0x0, 0x0,
+/* F698 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x23f41, 0x0,
+/* F6A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x20325, 0x0, 0x0,
+/* F6B0 */ 0x20ed8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F6F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F700 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F708 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F710 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F718 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F720 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F728 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F730 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F738 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F740 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F748 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F750 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F758 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F760 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F768 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F770 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F778 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F780 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F788 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F790 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F798 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200cc, 0x0,
+/* F7E8 */ 0x2008a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x27607, 0x0,
+/* F7F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F7F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F800 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F808 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F810 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F818 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F820 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F828 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F830 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F838 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F840 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F848 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F850 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F858 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F860 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F868 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F870 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F878 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F880 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F888 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F890 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F898 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* F8F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
+};
+
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/scriptfuncs.h b/Build/source/libs/luafontforge/fontforge/fontforge/scriptfuncs.h
new file mode 100644
index 00000000000..f00fb737b81
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/scriptfuncs.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 2006,2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SCRIPTFUNCS_H
+#define _SCRIPTFUNCS_H
+
+#include "scripting.h"
+
+extern int CompareGlyphs(Context *c, real pt_err, real spline_err,
+ real pixel_off_frac, int bb_err, int comp_hints, int diffs_are_errors );
+extern int CompareLayer(Context *c, const SplineSet *ss1,const SplineSet *ss2,
+ const RefChar *refs1, const RefChar *refs2,
+ real pt_err, real spline_err, const char *name, int diffs_are_errors,
+ SplinePoint **_hmfail);
+#endif /* _SCRIPTFUNCS_H */
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/scripting.h b/Build/source/libs/luafontforge/fontforge/fontforge/scripting.h
new file mode 100644
index 00000000000..0e5756c5b31
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/scripting.h
@@ -0,0 +1,129 @@
+/* Copyright (C) 2005-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SCRIPTING_H
+#define _SCRIPTING_H
+
+#include "pfaeditui.h"
+#include <setjmp.h>
+#include <stdarg.h>
+
+/* If users want to write user defined scripting built-in functions they will */
+/* need this file. The most relevant structure is the Context */
+
+struct dictentry {
+ char *name;
+ Val val;
+};
+
+struct dictionary {
+ struct dictentry *entries;
+ int cnt, max;
+};
+
+typedef struct array {
+ int argc;
+ Val *vals;
+} Array;
+
+#define TOK_MAX 256
+enum token_type { tt_name, tt_string, tt_number, tt_unicode, tt_real,
+ tt_lparen, tt_rparen, tt_comma, tt_eos, /* eos is end of statement, semicolon, newline */
+ tt_lbracket, tt_rbracket,
+ tt_minus, tt_plus, tt_not, tt_bitnot, tt_colon,
+ tt_mul, tt_div, tt_mod, tt_and, tt_or, tt_bitand, tt_bitor, tt_xor,
+ tt_eq, tt_ne, tt_gt, tt_lt, tt_ge, tt_le,
+ tt_assign, tt_pluseq, tt_minuseq, tt_muleq, tt_diveq, tt_modeq,
+ tt_incr, tt_decr,
+
+ tt_if, tt_else, tt_elseif, tt_endif, tt_while, tt_foreach, tt_endloop,
+ tt_shift, tt_return, tt_break,
+
+ tt_eof,
+
+ tt_error = -1
+};
+
+typedef struct context {
+ struct context *caller; /* The context of the script that called us */
+ Array a; /* The argument array */
+ Array **dontfree; /* Irrelevant for user defined funcs */
+ struct dictionary locals; /* Irrelevant for user defined funcs */
+ FILE *script; /* Irrelevant for user defined funcs */
+ unsigned int backedup: 1; /* Irrelevant for user defined funcs */
+ unsigned int donteval: 1; /* Irrelevant for user defined funcs */
+ unsigned int returned: 1; /* Irrelevant for user defined funcs */
+ unsigned int broken: 1; /* Irrelevant for user defined funcs */
+ char tok_text[TOK_MAX+1]; /* Irrelevant for user defined funcs */
+ enum token_type tok; /* Irrelevant for user defined funcs */
+ Val tok_val; /* Irrelevant for user defined funcs */
+ Val return_val; /* Initialized to void. If user wants */
+ /* return something set the return */
+ /* value here */
+ Val trace; /* Irrelevant for user defined funcs */
+ Val argsval; /* Irrelevant for user defined funcs */
+ char *filename; /* Irrelevant for user defined funcs */
+ int lineno; /* Irrelevant for user defined funcs */
+ int ungotch; /* Irrelevant for user defined funcs */
+ FontView *curfv; /* Current fontview */
+ jmp_buf *err_env; /* place to longjump to on an error */
+} Context;
+
+void FontImage(SplineFont *sf,char *filename,Array *arr,int width,int height);
+
+ /* Adds a user defined scripting function to the interpretter */
+ /* (you can't override a built-in name) */
+ /* (you can replace a previous user defined function */
+ /* Most functions will require a font to be loaded, but a few do not */
+ /* Open(), Exit(), Sin() don't. ff uses the needs_font flag to perform */
+ /* this check for you */
+ /* Returns 1 if the addition was successful, 2 if it replaced a previous func */
+ /* Returns 0 on failure (ie. if it attempts to replace a builtin function) */
+typedef void (*UserDefScriptFunc)(Context *);
+extern int AddScriptingCommand(char *name,UserDefScriptFunc func,int needs_font);
+
+ /* Returns whether a user defined scripting command already exists with the */
+ /* given name */
+extern UserDefScriptFunc HasUserScriptingCommand(char *name);
+
+ /* Scripts used to be in latin1, and we still support that if the user sets */
+ /* an environment variable. Now scripts are by default utf8. These two funcs */
+ /* will interconvert between latin1 & utf8 if appropriate, or just make a */
+ /* utf8 copy if not. They always make a copy. */
+extern char *utf82script_copy(const char *ustr);
+extern char *script2utf8_copy(const char *str);
+
+ /* Various error routines. */
+void ScriptError( Context *c, const char *msg );
+ /* Prints an error message and exits. msg is in the script's encoding */
+void ScriptErrorString( Context *c, const char *msg, const char *name);
+ /* Prints an error message followed by a string and exits. */
+ /* both strings are in the script's encoding */
+void ScriptErrorF( Context *c, const char *fmt, ... );
+ /* Standard printf-style spec. All string arguments assumed to be in */
+ /* utf8 */
+#endif /* _SCRIPTING_H */
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/sd.h b/Build/source/libs/luafontforge/fontforge/fontforge/sd.h
new file mode 100644
index 00000000000..6428c079537
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/sd.h
@@ -0,0 +1,170 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _SD_H
+#define _SD_H
+
+/* All coordinates are in millimeters */
+/* they will be displayed to the user scaled by the units field of the design */
+
+#include "splinefont.h"
+#if defined(FONTFORGE_CONFIG_GTK)
+# include <gtk/gtk.h>
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+# include "gdraw.h"
+#else
+# include <ggadget.h> /* Need GImage, gettext, etc. even if no UI */
+#endif
+
+typedef struct entpen {
+ Color col;
+ struct tile *tile;
+ float scale;
+ float opacity;
+} Pen;
+
+typedef struct textunit {
+ unichar_t *text;
+ SplineFont *sf;
+ float size; /* in points */
+ float kernafter;
+ Pen fill;
+ struct textunit *next;
+} TextUnit;
+
+typedef struct entity {
+ enum entity_type { et_splines, et_text, et_image, et_group } type;
+ union {
+ struct filledsplines {
+ SplineSet *splines;
+ unsigned int isfillable: 1; /* All splinesets are closed */
+ Pen fill, stroke; /* A value of 0xffffffff means do not fill or stroke */
+ float stroke_width;
+ enum linejoin join;
+ enum linecap cap;
+ real transform[6]; /* The stroke may be quite different depending on the transformation (ie. ellipse not circle, rotated, etc) */
+ } splines;
+ struct text {
+ TextUnit *text;
+ real transform[6];
+ struct entity *bound;
+ } text;
+ struct image {
+ GImage *image;
+ real transform[6];
+ Color col; /* that gets poured into imagemasks */
+ } image;
+ struct group {
+ struct entity *group;
+ } group;
+ } u;
+ DBounds bb;
+ struct entity *next;
+} Entity;
+
+typedef struct entlayer {
+ Entity *entities;
+ char *name;
+ unsigned int isvisible: 1;
+} EntLayer;
+
+typedef struct tile {
+ Entity *tile;
+#ifdef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ struct tileinstance { real scale;struct tileinstance *next; }
+ *instances;
+#elif defined( FONTFORGE_CONFIG_GTK )
+ struct tileinstance { real scale; GdkWindow pixmap; struct tileinstance *next; }
+ *instances;
+#elif defined( FONTFORGE_CONFIG_GDRAW )
+ struct tileinstance { real scale; GWindow pixmap; struct tileinstance *next; }
+ *instances;
+#endif
+ char *name;
+} Tile;
+
+typedef struct splinedesign {
+ int lcnt, lmax, active;
+ EntLayer *layers;
+
+ real width, height; /* in millimeters */
+ int16 hpages, vpages;
+ real pwidth, pheight; /* in millimeters */
+ real units; /* if user wants to see things in */
+ /* centimeters then units will be 10, if inches then 25.4, if points */
+ /* then 25.4/72, if 1/1200" then 25.4/1200, etc. */
+ struct dview *dvs;
+} SplineDesign, Design;
+
+extern Entity *EntityInterpretPS(FILE *ps);
+extern Entity *EntityInterpretSVG(char *filename,char *memory, int memlen, int em_size,int ascent);
+extern SplinePointList *SplinesFromEntities(Entity *ent,int *flags,int is_stroked);
+extern void SCAppendEntityLayers(SplineChar *sc, Entity *ent);
+extern void EntityDefaultStrokeFill(Entity *ent);
+
+ /* Used for type3 fonts briefly */
+/* This is not a "real" structure. It is a temporary hack that encompasses */
+/* various possibilities, the combination of which won't occur in reality */
+typedef struct entitychar {
+ Entity *splines;
+ RefChar *refs;
+ int width, vwidth;
+ SplineChar *sc;
+ uint8 fromtype3;
+} EntityChar;
+
+extern SplinePointList *SplinesFromEntityChar(EntityChar *ec,int *flags,int is_stroked);
+
+struct pskeydict {
+ int16 cnt, max;
+ uint8 is_executable;
+ struct pskeyval *entries;
+};
+
+struct psstack {
+ enum pstype { ps_void, ps_num, ps_bool, ps_string, ps_instr, ps_lit,
+ ps_mark, ps_array, ps_dict } type;
+ union vals {
+ real val;
+ int tf;
+ char *str;
+ struct pskeydict dict; /* and for arrays too */
+ } u;
+};
+
+struct pskeyval {
+ enum pstype type;
+ union vals u;
+ char *key;
+};
+
+typedef struct retstack {
+ int max;
+ int cnt;
+ real *stack;
+} RetStack;
+
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/sfd1.h b/Build/source/libs/luafontforge/fontforge/fontforge/sfd1.h
new file mode 100644
index 00000000000..b8fd236689f
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/sfd1.h
@@ -0,0 +1,112 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _SFD1_H
+#define _SFD1_H
+/* This file contains the data structures needed to read in an old sfd file */
+/* features and lookups and scripts are handled differently. That means that */
+/* the KernPair, KernClass, PST, FPST, AnchorClass, StateMachine data structures */
+/* are organized differently. Also we've got a script language list which */
+/* doesn't exist in the new format and we don't have OTLookup */
+
+#include "splinefont.h"
+
+#define SLI_UNKNOWN 0xffff
+#define SLI_NESTED 0xfffe
+
+typedef struct anchorclass1 {
+ AnchorClass ac;
+ uint32 feature_tag;
+ uint16 script_lang_index;
+ uint16 flags;
+ uint16 merge_with;
+ uint8 has_bases;
+ uint8 has_ligatures;
+} AnchorClass1;
+
+typedef struct kernpair1 {
+ KernPair kp;
+ uint16 sli, flags;
+} KernPair1;
+
+typedef struct kernclass1 {
+ KernClass kc;
+ uint16 sli;
+ uint16 flags;
+} KernClass1;
+
+typedef struct generic_pst1 {
+ PST pst;
+ uint8 macfeature; /* tag should be interpretted as <feature,setting> rather than 'abcd' */
+ uint16 flags;
+ uint16 script_lang_index; /* 0xffff means none */
+ uint32 tag;
+} PST1;
+
+typedef struct generic_fpst1 {
+ FPST fpst;
+ uint16 script_lang_index;
+ uint16 flags;
+ uint32 tag;
+} FPST1;
+
+typedef struct generic_asm1 { /* Apple State Machine */
+ ASM sm;
+ uint16 feature, setting;
+ uint32 opentype_tag; /* If converted from opentype */
+} ASM1;
+
+typedef struct splinefont1 {
+ SplineFont sf;
+
+ struct table_ordering { uint32 table_tag; uint32 *ordered_features; struct table_ordering *next; } *orders;
+
+ /* Any GPOS/GSUB entry (PST, AnchorClass, kerns, FPST */
+ /* Has an entry saying what scripts/languages it should appear it */
+ /* Things like fractions will appear in almost all possible script/lang */
+ /* combinations, while alphabetic ligatures will only live in one script */
+ /* Rather than store the complete list of possibilities in each PST we */
+ /* store all choices used here, and just store an index into this list */
+ /* in the PST. All lists are terminated by a 0 entry */
+ struct script_record {
+ uint32 script;
+ uint32 *langs;
+ } **script_lang;
+ int16 sli_cnt;
+
+ struct gentagtype {
+ uint16 tt_cur, tt_max;
+ struct tagtype {
+ enum possub_type type;
+ uint32 tag;
+ } *tagtype;
+ } gentags;
+} SplineFont1;
+
+extern int SFFindBiggestScriptLangIndex(SplineFont *_sf,uint32 script,uint32 lang);
+extern int SFAddScriptIndex(SplineFont1 *sf,uint32 *scripts,int scnt);
+extern void SFD_AssignLookups(SplineFont1 *sf);
+#endif /* _SFD1_H */
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/splinefill.c b/Build/source/libs/luafontforge/fontforge/fontforge/splinefill.c
new file mode 100644
index 00000000000..0334054ac81
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/splinefill.c
@@ -0,0 +1,1864 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include <stdio.h>
+#include <string.h>
+#include <ustring.h>
+#include <math.h>
+#include "gdraw.h"
+#include "splinefont.h"
+#include "edgelist.h"
+
+uint32 default_background = 0xffffff; /* white */
+
+static void HintsFree(Hints *h) {
+ Hints *hnext;
+ for ( ; h!=NULL; h = hnext ) {
+ hnext = h->next;
+ free(h);
+ }
+}
+
+static void _FreeEdgeList(EdgeList *es) {
+ int i;
+
+ /* edges will be NULL if the user tries to make an enormous bitmap */
+ /* if the linear size is bigger than several thousand, we just */
+ /* ignore the request */
+ if ( es->edges!=NULL ) {
+ for ( i=0; i<es->cnt; ++i ) {
+ Edge *e, *next;
+ for ( e = es->edges[i]; e!=NULL; e = next ) {
+ next = e->esnext;
+ free(e);
+ }
+ es->edges[i] = NULL;
+ }
+ }
+}
+
+void FreeEdges(EdgeList *es) {
+ _FreeEdgeList(es);
+ free(es->edges);
+ free(es->interesting);
+ HintsFree(es->hhints);
+ HintsFree(es->vhints);
+}
+
+extended IterateSplineSolve(const Spline1D *sp, extended tmin, extended tmax,
+ extended sought,double err) {
+ extended t, low, high, test;
+ Spline1D temp;
+ int cnt;
+
+ /* Now the closed form CubicSolver can have rounding errors so if we know */
+ /* the spline to be monotonic, an iterative approach is more accurate */
+
+ temp = *sp;
+ temp.d -= sought;
+
+ if ( temp.a==0 && temp.b==0 && temp.c!=0 ) {
+ t = -temp.d/(extended) temp.c;
+ if ( t<0 || t>1 )
+return( -1 );
+return( t );
+ }
+
+ low = ((temp.a*tmin+temp.b)*tmin+temp.c)*tmin+temp.d;
+ high = ((temp.a*tmax+temp.b)*tmax+temp.c)*tmax+temp.d;
+ if ( low<err && low>-err )
+return(tmin);
+ if ( high<err && high>-err )
+return(tmax);
+ if (( low<0 && high>0 ) ||
+ ( low>0 && high<0 )) {
+
+ for ( cnt=0; cnt<1000; ++cnt ) { /* Avoid impossible error limits */
+ t = (tmax+tmin)/2;
+ test = ((temp.a*t+temp.b)*t+temp.c)*t+temp.d;
+ if ( test>-err && test<err )
+return( t );
+ if ( (low<0 && test<0) || (low>0 && test>0) )
+ tmin=t;
+ else
+ tmax = t;
+ }
+return( (tmax+tmin)/2 );
+ }
+return( -1 );
+}
+
+double TOfNextMajor(Edge *e, EdgeList *es, double sought_m ) {
+ /* We want to find t so that Mspline(t) = sought_m */
+ /* the curve is monotonic */
+ Spline1D *msp = &e->spline->splines[es->major];
+ double new_t;
+
+ if ( es->is_overlap ) {
+
+ /* if we've adjusted the height then we won't be able to find it restricting */
+ /* t between [0,1] as we do. So it's a special case. (this is to handle */
+ /* hstem hints) */
+ if ( e->max_adjusted && sought_m==e->mmax ) {
+ e->m_cur = sought_m;
+return( e->up?1.0:0.0 );
+ }
+
+ new_t = IterateSplineSolve(msp,e->t_mmin,e->t_mmax,(sought_m+es->mmin)/es->scale,.001);
+ if ( new_t==-1 )
+ IError( "No Solution");
+ e->m_cur = (((msp->a*new_t + msp->b)*new_t+msp->c)*new_t + msp->d)*es->scale - es->mmin;
+return( new_t );
+ } else {
+ Spline *sp = e->spline;
+
+ if ( sp->islinear ) {
+ new_t = e->t_cur + (sought_m-e->m_cur)/(es->scale * msp->c);
+ e->m_cur = (msp->c*new_t + msp->d)*es->scale - es->mmin;
+return( new_t );
+ }
+ /* if we have a spline that is nearly horizontal at its max. endpoint */
+ /* then finding A value of t for which y has the right value isn't good */
+ /* enough (at least not when finding intersections) */
+ if ( sought_m+1>e->mmax ) {
+ e->m_cur = e->mmax;
+return( e->t_mmax );
+ }
+
+ /* if we've adjusted the height then we won't be able to find it restricting */
+ /* t between [0,1] as we do. So it's a special case. (this is to handle */
+ /* hstem hints) */
+ if ( e->max_adjusted && sought_m==e->mmax ) {
+ e->m_cur = sought_m;
+return( e->up?1.0:0.0 );
+ }
+ new_t = IterateSplineSolve(msp,e->t_mmin,e->t_mmax,(sought_m+es->mmin)/es->scale,.001);
+ if ( new_t==-1 )
+ IError( "No Solution");
+ e->m_cur = (((msp->a*new_t + msp->b)*new_t+msp->c)*new_t + msp->d)*es->scale - es->mmin;
+return( new_t );
+ }
+}
+
+static int SlopeLess(Edge *e, Edge *p, int other) {
+ Spline1D *osp = &e->spline->splines[other];
+ Spline1D *psp = &p->spline->splines[other];
+ Spline1D *msp = &e->spline->splines[!other];
+ Spline1D *qsp = &p->spline->splines[!other];
+ real os = (3*osp->a*e->t_cur+2*osp->b)*e->t_cur+osp->c,
+ ps = (3*psp->a*p->t_cur+2*psp->b)*p->t_cur+psp->c;
+ real ms = (3*msp->a*e->t_cur+2*msp->b)*e->t_cur+msp->c,
+ qs = (3*qsp->a*p->t_cur+2*qsp->b)*p->t_cur+qsp->c;
+ if ( ms<.0001 && ms>-.0001 ) ms = 0;
+ if ( qs<.0001 && qs>-.0001 ) qs = 0;
+ if ( qs==0 ) {
+ if ( p->t_cur==1 ) {
+ qs = (3*qsp->a*.9999+2*qsp->b)*.9999+qsp->c;
+ ps = (3*psp->a*.9999+2*psp->b)*.9999+psp->c;
+ } else {
+ qs = (3*qsp->a*(p->t_cur+.0001)+2*qsp->b)*(p->t_cur+.0001)+qsp->c;
+ ps = (3*psp->a*(p->t_cur+.0001)+2*psp->b)*(p->t_cur+.0001)+psp->c;
+ }
+ }
+ if ( ms==0 ) {
+ if ( e->t_cur==1 ) {
+ ms = (3*msp->a*.9999+2*msp->b)*.9999+msp->c;
+ os = (3*osp->a*.9999+2*osp->b)*.9999+osp->c;
+ } else {
+ ms = (3*msp->a*(e->t_cur+.0001)+2*msp->b)*(e->t_cur+.0001)+msp->c;
+ os = (3*osp->a*(e->t_cur+.0001)+2*osp->b)*(e->t_cur+.0001)+osp->c;
+ }
+ }
+ if ( e->t_cur-e->tmin > e->tmax-e->t_cur ) { os = -os; ms = -ms; }
+ if ( p->t_cur-p->tmin > p->tmax-p->t_cur ) { ps = -ps; qs = -qs; }
+ if ( ms!=0 && qs!=0 ) { os /= ms; ps /= qs; }
+ else if ( ms==0 && qs==0 ) /* Do Nothing */;
+ else if ( (ms==0 && os>0) || (qs==0 && ps<0) ) /* Does this make sense? */
+return( false );
+ else if ( (ms==0 && os<0) || (qs==0 && ps>0) ) /* Does this make sense? */
+return( true );
+
+ if ( os==ps || ms==0 || qs==0 )
+return( e->o_mmax<p->o_mmax );
+
+return( os<ps );
+}
+
+static void AddEdge(EdgeList *es, Spline *sp, real tmin, real tmax ) {
+ Edge *e, *pr;
+ real m1, m2;
+ int mpos;
+ Hints *hint;
+ Spline1D *msp = &sp->splines[es->major], *osp = &sp->splines[es->other];
+
+ e = gcalloc(1,sizeof(Edge));
+ e->spline = sp;
+
+ m1 = ( ((msp->a*tmin+msp->b)*tmin+msp->c)*tmin + msp->d ) * es->scale;
+ m2 = ( ((msp->a*tmax+msp->b)*tmax+msp->c)*tmax + msp->d ) * es->scale;
+ if ( m1>m2 ) {
+ e->mmin = m2;
+ e->t_mmin = tmax;
+ e->mmax = m1;
+ e->t_mmax = tmin;
+ e->up = false;
+ } else {
+ e->mmax = m2;
+ e->t_mmax = tmax;
+ e->mmin = m1;
+ e->t_mmin = tmin;
+ e->up = true;
+ }
+ if ( RealNear(e->mmin,es->mmin)) e->mmin = es->mmin;
+ e->o_mmin = ( ((osp->a*e->t_mmin+osp->b)*e->t_mmin+osp->c)*e->t_mmin + osp->d ) * es->scale;
+ e->o_mmax = ( ((osp->a*e->t_mmax+osp->b)*e->t_mmax+osp->c)*e->t_mmax + osp->d ) * es->scale;
+ e->mmin -= es->mmin; e->mmax -= es->mmin;
+ e->t_cur = e->t_mmin;
+ e->o_cur = e->o_mmin;
+ e->m_cur = e->mmin;
+ e->last_opos = e->last_mpos = -2;
+ e->tmin = tmin; e->tmax = tmax;
+
+ if ( e->mmin<0 || e->mmin>=e->mmax ) {
+ /*IError("Probably not serious, but we've got a zero length spline in AddEdge in %s",es->sc==NULL?<nameless>:es->sc->name);*/
+ free(e);
+return;
+ }
+
+ if ( es->sc!=NULL ) for ( hint=es->hhints; hint!=NULL; hint=hint->next ) {
+ if ( hint->adjustb ) {
+ if ( e->m_cur>hint->b1 && e->m_cur<hint->b2 ) {
+ e->m_cur = e->mmin = hint->ab;
+ e->min_adjusted = true;
+ } else if ( e->mmax>hint->b1 && e->mmax<hint->b2 ) {
+ e->mmax = hint->ab;
+ e->max_adjusted = true;
+ }
+ } else if ( hint->adjuste ) {
+ if ( e->m_cur>hint->e1 && e->m_cur<hint->e2 ) {
+ e->m_cur = e->mmin = hint->ae;
+ e->min_adjusted = true;
+ } else if ( e->mmax>hint->e1 && e->mmax<hint->e2 ) {
+ e->mmax = hint->ae;
+ e->max_adjusted = true;
+ }
+ }
+ }
+
+ mpos = (int) ceil(e->m_cur);
+ if ( mpos>e->mmax || mpos>=es->cnt ) {
+ free(e);
+return;
+ }
+
+ if ( e->m_cur!=ceil(e->m_cur) ) {
+ /* bring the new edge up to its first scan line */
+ e->t_cur = TOfNextMajor(e,es,ceil(e->m_cur));
+ e->o_cur = ( ((osp->a*e->t_cur+osp->b)*e->t_cur+osp->c)*e->t_cur + osp->d ) * es->scale;
+ }
+
+ e->before = es->last;
+ if ( es->last!=NULL )
+ es->last->after = e;
+ if ( es->last==NULL )
+ es->splinesetfirst = e;
+ es->last = e;
+
+ if ( es->edges[mpos]==NULL || e->o_cur<es->edges[mpos]->o_cur ||
+ (e->o_cur==es->edges[mpos]->o_cur && SlopeLess(e,es->edges[mpos],es->other))) {
+ e->esnext = es->edges[mpos];
+ es->edges[mpos] = e;
+ } else {
+ for ( pr=es->edges[mpos]; pr->esnext!=NULL && pr->esnext->o_cur<e->o_cur ;
+ pr = pr->esnext );
+ /* When two splines share a vertex which is a local minimum, then */
+ /* o_cur will be equal for both (to the vertex's o value) and so */
+ /* the above code randomly picked one to go first. That screws up */
+ /* the overlap code, which wants them properly ordered from the */
+ /* start. so look at the end point, nope the end point isn't always */
+ /* meaningful, look at the slope... */
+ if ( pr->esnext!=NULL && pr->esnext->o_cur==e->o_cur &&
+ SlopeLess(e,pr->esnext,es->other)) {
+ pr = pr->esnext;
+ }
+ e->esnext = pr->esnext;
+ pr->esnext = e;
+ }
+ if ( es->interesting ) {
+ /* Mark the other end of the spline as interesting */
+ es->interesting[(int) ceil(e->mmax)]=1;
+ }
+}
+
+static void AddMajorEdge(EdgeList *es, Spline *sp) {
+ Edge *e, *pr;
+ real m1;
+ Spline1D *msp = &sp->splines[es->major], *osp = &sp->splines[es->other];
+
+ e = gcalloc(1,sizeof(Edge));
+ e->spline = sp;
+
+ e->mmin = e->mmax = m1 = msp->d * es->scale - es->mmin;
+ e->t_mmin = 0;
+ e->t_mmax = 1;
+ e->up = false;
+ e->o_mmin = osp->d * es->scale;
+ e->o_mmax = ( osp->a + osp->b + osp->c + osp->d ) * es->scale;
+ if ( e->o_mmin == e->o_mmax ) { /* Just a point? */
+ free(e);
+return;
+ }
+ if ( e->mmin<0 )
+ IError("Grg!");
+
+ if ( ceil(e->m_cur)>e->mmax ) {
+ free(e);
+return;
+ }
+
+ if ( es->majors==NULL || es->majors->mmin>=m1 ) {
+ e->esnext = es->majors;
+ es->majors = e;
+ } else {
+ for ( pr=es->majors; pr->esnext!=NULL && pr->esnext->mmin<m1; pr = pr->esnext );
+ e->esnext = pr->esnext;
+ pr->esnext = e;
+ }
+}
+
+static void AddSpline(EdgeList *es, Spline *sp ) {
+ real t1=2, t2=2, t;
+ real b2_fourac;
+ real fm, tm;
+ Spline1D *msp = &sp->splines[es->major], *osp = &sp->splines[es->other];
+
+ /* Find the points of extrema on the curve discribing y behavior */
+ if ( !RealNear(msp->a,0) ) {
+ /* cubic, possibly 2 extrema (possibly none) */
+ b2_fourac = 4*msp->b*msp->b - 12*msp->a*msp->c;
+ if ( b2_fourac>=0 ) {
+ b2_fourac = sqrt(b2_fourac);
+ t1 = CheckExtremaForSingleBitErrors(msp,(-2*msp->b - b2_fourac) / (6*msp->a));
+ t2 = CheckExtremaForSingleBitErrors(msp,(-2*msp->b + b2_fourac) / (6*msp->a));
+ if ( t1>t2 ) { real temp = t1; t1 = t2; t2 = temp; }
+ else if ( t1==t2 ) t2 = 2.0;
+
+ /* check for curves which have such a small slope they might */
+ /* as well be horizontal */
+ fm = es->major==1?sp->from->me.y:sp->from->me.x;
+ tm = es->major==1?sp->to->me.y:sp->to->me.x;
+ if ( fm==tm ) {
+ real m1, m2, d1, d2;
+ m1 = m2 = fm;
+ if ( t1>0 && t1<1 )
+ m1 = ((msp->a*t1+msp->b)*t1+msp->c)*t1 + msp->d;
+ if ( t2>0 && t2<1 )
+ m2 = ((msp->a*t2+msp->b)*t2+msp->c)*t2 + msp->d;
+ d1 = (m1-fm)*es->scale;
+ d2 = (m2-fm)*es->scale;
+ if ( d1>-.5 && d1<.5 && d2>-.5 && d2<.5 ) {
+ sp->ishorvert = true;
+ if ( es->genmajoredges )
+ AddMajorEdge(es,sp);
+return; /* Pretend it's horizontal, ignore it */
+ }
+ }
+ }
+ } else if ( !RealNear(msp->b,0) ) {
+ /* Quadratic, at most one extremum */
+ t1 = -msp->c/(2.0*msp->b);
+ } else if ( !RealNear(msp->c,0) ) {
+ /* linear, no points of extrema */
+ } else {
+ sp->ishorvert = true;
+ if ( es->genmajoredges )
+ AddMajorEdge(es,sp);
+return; /* Horizontal line, ignore it */
+ }
+
+ if ( RealNear(t1,0)) t1=0;
+ if ( RealNear(t1,1)) t1=1;
+ if ( RealNear(t2,0)) t2=0;
+ if ( RealNear(t2,1)) t2=1;
+ if ( RealNear(t1,t2)) t2=2;
+ t=0;
+ if ( t1>0 && t1<1 ) {
+ AddEdge(es,sp,0,t1);
+ t = t1;
+ }
+ if ( t2>0 && t2<1 ) {
+ AddEdge(es,sp,t,t2);
+ t = t2;
+ }
+ AddEdge(es,sp,t,1.0);
+ if ( es->interesting ) {
+ /* Also store up points of extrema in X as interesting (we got the endpoints, just internals now)*/
+ extended ot1, ot2;
+ int mpos;
+ SplineFindExtrema(osp,&ot1,&ot2);
+ if ( ot1>0 && ot1<1 ) {
+ mpos = (int) ceil( ( ((msp->a*ot1+msp->b)*ot1+msp->c)*ot1+msp->d )*es->scale-es->mmin );
+ es->interesting[mpos] = 1;
+ }
+ if ( ot2>0 && ot2<1 ) {
+ mpos = (int) ceil( ( ((msp->a*ot2+msp->b)*ot2+msp->c)*ot2+msp->d )*es->scale-es->mmin );
+ es->interesting[mpos] = 1;
+ }
+ }
+}
+
+void FindEdgesSplineSet(SplinePointList *spl, EdgeList *es) {
+ Spline *spline, *first;
+
+ for ( ; spl!=NULL; spl = spl->next ) if ( spl->first->prev!=NULL && spl->first->prev->from!=spl->first ) {
+ first = NULL;
+ es->last = es->splinesetfirst = NULL;
+ /* Set so there is no previous point!!! */
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) {
+ AddSpline(es,spline);
+ if ( first==NULL ) first = spline;
+ }
+ if ( es->last!=NULL ) {
+ es->splinesetfirst->before = es->last;
+ es->last->after = es->splinesetfirst;
+ }
+ }
+}
+
+
+#ifndef LUA_FF_LIB
+
+static void FindEdges(SplineChar *sc, EdgeList *es) {
+ RefChar *rf;
+
+ for ( rf=sc->layers[ly_fore].refs; rf!=NULL; rf = rf->next )
+ FindEdgesSplineSet(rf->layers[0].splines,es);
+
+ FindEdgesSplineSet(sc->layers[ly_fore].splines,es);
+}
+#endif
+
+Edge *ActiveEdgesInsertNew(EdgeList *es, Edge *active,int i) {
+ Edge *apt, *pr, *npt;
+
+ for ( pr=NULL, apt=active, npt=es->edges[(int) i]; apt!=NULL && npt!=NULL; ) {
+ if ( npt->o_cur<apt->o_cur ) {
+ npt->aenext = apt;
+ if ( pr==NULL )
+ active = npt;
+ else
+ pr->aenext = npt;
+ pr = npt;
+ npt = npt->esnext;
+ } else {
+ pr = apt;
+ apt = apt->aenext;
+ }
+ }
+ while ( npt!=NULL ) {
+ npt->aenext = NULL;
+ if ( pr==NULL )
+ active = npt;
+ else
+ pr->aenext = npt;
+ pr = npt;
+ npt = npt->esnext;
+ }
+return( active );
+}
+
+Edge *ActiveEdgesRefigure(EdgeList *es, Edge *active,real i) {
+ Edge *apt, *pr;
+ int any;
+
+ /* first remove any entry which doesn't intersect the new scan line */
+ /* (ie. stopped on last line) */
+ for ( pr=NULL, apt=active; apt!=NULL; apt = apt->aenext ) {
+ if ( apt->mmax<i ) {
+ if ( pr==NULL )
+ active = apt->aenext;
+ else
+ pr->aenext = apt->aenext;
+ } else
+ pr = apt;
+ }
+ /* then move the active list to the next line */
+ for ( apt=active; apt!=NULL; apt = apt->aenext ) {
+ Spline1D *osp = &apt->spline->splines[es->other];
+ apt->t_cur = TOfNextMajor(apt,es,i);
+ apt->o_cur = ( ((osp->a*apt->t_cur+osp->b)*apt->t_cur+osp->c)*apt->t_cur + osp->d ) * es->scale;
+ }
+ /* reorder list */
+ if ( active!=NULL ) {
+ any = true;
+ while ( any ) {
+ any = false;
+ for ( pr=NULL, apt=active; apt->aenext!=NULL; ) {
+ if ( apt->o_cur <= apt->aenext->o_cur ) {
+ /* still ordered */;
+ pr = apt;
+ apt = apt->aenext;
+ } else if ( pr==NULL ) {
+ active = apt->aenext;
+ apt->aenext = apt->aenext->aenext;
+ active->aenext = apt;
+ /* don't need to set any, since this reorder can't disorder the list */
+ pr = active;
+ } else {
+ pr->aenext = apt->aenext;
+ apt->aenext = apt->aenext->aenext;
+ pr->aenext->aenext = apt;
+ any = true;
+ pr = pr->aenext;
+ }
+ }
+ }
+ }
+ /* Insert new nodes */
+ active = ActiveEdgesInsertNew(es,active,i);
+return( active );
+}
+
+#ifndef LUA_FF_LIB
+Edge *ActiveEdgesFindStem(Edge *apt, Edge **prev, real i) {
+ int cnt=apt->up?1:-1;
+ Edge *pr, *e;
+
+ for ( pr=apt, e=apt->aenext; e!=NULL && cnt!=0; pr=e, e=e->aenext ) {
+ if ( pr->up!=e->up )
+ cnt += (e->up?1:-1);
+ else if ( (pr->before==e || pr->after==e ) &&
+ (( pr->mmax==i && e->mmin==i ) ||
+ ( pr->mmin==i && e->mmax==i )) )
+ /* This just continues the line and doesn't change count */;
+ else
+ cnt += (e->up?1:-1);
+ }
+ /* color a horizontal line that comes out of the last vertex */
+ if ( e!=NULL && (e->before==pr || e->after==pr) &&
+ (( pr->mmax==i && e->mmin==i ) ||
+ ( pr->mmin==i && e->mmax==i )) ) {
+ pr = e;
+ e = e->aenext;
+ } else if ( e!=NULL && ((pr->up && !e->up) || (!pr->up && e->up)) &&
+ pr->spline!=e->spline &&
+ ((pr->after==e && pr->spline->to->next!=NULL &&
+ pr->spline->to->next!=e->spline &&
+ pr->spline->to->next->to->next==e->spline ) ||
+ (pr->before==e && pr->spline->from->prev!=NULL &&
+ pr->spline->from->prev!=e->spline &&
+ pr->spline->from->prev->from->prev!=e->spline )) &&
+ ((pr->mmax == i && e->mmax==i ) ||
+ (pr->mmin == i && e->mmin==i )) ) {
+ pr = e;
+ }
+ *prev = pr;
+return( e );
+}
+
+static int isvstem(EdgeList *es,real stem,int *vval) {
+ Hints *hint;
+
+ for ( hint=es->vhints; hint!=NULL ; hint=hint->next ) {
+ if ( stem>=hint->b1 && stem<=hint->b2 ) {
+ *vval = hint->ab;
+return( true );
+ } else if ( stem>=hint->e1 && stem<=hint->e2 ) {
+ *vval = hint->ae;
+return( true );
+ }
+ }
+return( false );
+}
+
+static void FillChar(EdgeList *es) {
+ Edge *active=NULL, *apt, *pr, *e, *prev;
+ int i, k, end, width, oldk;
+ uint8 *bpt;
+
+ for ( i=0; i<es->cnt; ++i ) {
+ active = ActiveEdgesRefigure(es,active,i);
+
+ /* process scanline */
+ bpt = es->bitmap+((es->cnt-1-i)*es->bytes_per_line);
+ for ( apt=active; apt!=NULL; ) {
+ e = ActiveEdgesFindStem(apt,&prev,i);
+ pr = prev;
+ width = rint(pr->o_cur-apt->o_cur);
+ if ( width<=0 ) width=1;
+ k=rint(apt->o_cur-es->omin);
+ if ( k<0 ) k=0;
+ end =rint(pr->o_cur-es->omin);
+ if ( end-k > width-1 ) {
+ int kval = -999999, eval= -999999;
+ if ( isvstem(es,apt->o_cur,&kval) )
+ k = kval;
+ if ( isvstem(es,pr->o_cur,&eval))
+ end = eval;
+ if ( end-k > width-1 ) {
+ if ( k!=kval && (end==eval || (apt->o_cur-es->omin)-k > end-(pr->o_cur-es->omin) ))
+ ++k;
+ else if ( end!=eval )
+ --end;
+ }
+ }
+ oldk = k;
+ if ( apt->last_mpos==i-1 || pr->last_mpos==i-1 ) {
+ int lx1=apt->last_opos, lx2=pr->last_opos;
+ if ( apt->last_mpos!=i-1 ) lx1 = lx2;
+ else if ( pr->last_mpos!=i-1 ) lx2 = lx1;
+ if ( lx1>lx2 ) { int temp = lx1; lx1=lx2; lx2=temp; }
+ if ( lx2<k-1 ) {
+ int mid = (lx2+k)/2;
+ for ( ; lx2<mid; ++lx2 )
+ bpt[(lx2>>3)+es->bytes_per_line] |= (1<<(7-(lx2&7)));
+ for ( ; lx2<k; ++lx2 )
+ bpt[(lx2>>3)] |= (1<<(7-(lx2&7)));
+ } else if ( lx1>end+1 ) {
+ int mid = (lx1+end)/2;
+ for ( ; lx1<mid; --lx1 )
+ bpt[(lx1>>3)+es->bytes_per_line] |= (1<<(7-(lx1&7)));
+ for ( ; lx1<end; --lx1 )
+ bpt[(lx1>>3)] |= (1<<(7-(lx1&7)));
+ }
+ }
+ for ( ; k<=end; ++k )
+ bpt[k>>3] |= (1<<(7-(k&7)));
+ apt->last_mpos = pr->last_mpos = i;
+ apt->last_opos = oldk;
+ pr->last_opos = end;
+ apt = e;
+ }
+ }
+}
+
+static void InitializeHints(SplineChar *sc, EdgeList *es) {
+ Hints *hint, *last;
+ StemInfo *s;
+ real t1, t2;
+ int k,end,width;
+
+ /* we only care about hstem hints, and only if they fail to cross a */
+ /* vertical pixel boundary. If that happens, adjust either the top */
+ /* or bottom position so that a boundary forcing is crossed. Any */
+ /* vertexes at those points will be similarly adjusted later... */
+
+ last = NULL; es->hhints = NULL;
+ for ( s=sc->hstem; s!=NULL; s=s->next ) {
+ hint = gcalloc(1,sizeof(Hints));
+ hint->base = s->start; hint->width = s->width;
+ if ( last==NULL ) es->hhints = hint;
+ else last->next = hint;
+ last = hint;
+ hint->adjuste = hint->adjustb = false;
+ t1 = hint->base*es->scale -es->mmin;
+ t2 = (hint->base+hint->width)*es->scale -es->mmin;
+ if ( floor(t1)==floor(t2) && t1!=floor(t1) && t2!=floor(t2) ) {
+ if ( t1<t2 ) {
+ if ( t1-floor(t1) > ceil(t2)-t2 ) {
+ hint->adjuste = true;
+ hint->ae = ceil(t2);
+ } else {
+ hint->adjustb = true;
+ hint->ab = floor(t1);
+ }
+ } else {
+ if ( t2-floor(t2) > ceil(t1)-t1 ) {
+ hint->adjustb = true;
+ hint->ab = ceil(t1);
+ } else {
+ hint->adjuste = true;
+ hint->ae = floor(t2);
+ }
+ }
+ }
+ hint->b1 = t1-.2; hint->b2 = t1 + .2;
+ hint->e1 = t2-.2; hint->e2 = t2 + .2;
+ }
+
+ /* Nope. We care about vstems too now, but in a different case */
+ last = NULL; es->vhints = NULL;
+ for ( s=sc->vstem; s!=NULL; s=s->next ) {
+ hint = gcalloc(1,sizeof(Hints));
+ hint->base = s->start; hint->width = s->width;
+ if ( last==NULL ) es->vhints = hint;
+ else last->next = hint;
+ last = hint;
+ if ( hint->width<0 ) {
+ width = -rint(-hint->width*es->scale);
+ t1 = (hint->base+hint->width)*es->scale;
+ t2 = hint->base*es->scale;
+ } else {
+ width = rint(hint->width*es->scale);
+ t1 = hint->base*es->scale;
+ t2 = (hint->base+hint->width)*es->scale;
+ }
+ k = rint(t1-es->omin); end = rint(t2-es->omin);
+ if ( end-k > width-1 )
+ if ( end-k > width-1 ) {
+ if ( (t1-es->omin)-k > end-(t2-es->omin) )
+ ++k;
+ else
+ --end;
+ }
+ hint->ab = k; hint->ae = end;
+ hint->b1 = t1-.2; hint->b2 = t1 + .2;
+ hint->e1 = t2-.2; hint->e2 = t2 + .2;
+ }
+}
+#endif
+
+/* After a bitmap has been compressed, it's sizes may not comply with the */
+/* expectations for saving images */
+void BCRegularizeBitmap(BDFChar *bdfc) {
+ int bpl =(bdfc->xmax-bdfc->xmin)/8+1;
+ int i;
+
+ if ( bdfc->bytes_per_line!=bpl ) {
+ uint8 *bitmap = galloc(bpl*(bdfc->ymax-bdfc->ymin+1));
+ for ( i=0; i<=(bdfc->ymax-bdfc->ymin); ++i )
+ memcpy(bitmap+i*bpl,bdfc->bitmap+i*bdfc->bytes_per_line,bpl);
+ free(bdfc->bitmap);
+ bdfc->bitmap= bitmap;
+ bdfc->bytes_per_line = bpl;
+ }
+}
+
+void BCRegularizeGreymap(BDFChar *bdfc) {
+ int bpl = bdfc->xmax-bdfc->xmin+1;
+ int i;
+
+ if ( bdfc->bytes_per_line!=bpl ) {
+ uint8 *bitmap = galloc(bpl*(bdfc->ymax-bdfc->ymin+1));
+ for ( i=0; i<=(bdfc->ymax-bdfc->ymin); ++i )
+ memcpy(bitmap+i*bpl,bdfc->bitmap+i*bdfc->bytes_per_line,bpl);
+ free(bdfc->bitmap);
+ bdfc->bitmap= bitmap;
+ bdfc->bytes_per_line = bpl;
+ }
+}
+
+void BCCompressBitmap(BDFChar *bdfc) {
+ /* Now we may have allocated a bit more than we need to the bitmap */
+ /* check to see if there are any unused rows or columns.... */
+ int i,j,any, off, last;
+
+ /* we can use the same code to lop off rows whether we deal with bytes or bits */
+ for ( i=0; i<bdfc->ymax-bdfc->ymin; ++i ) {
+ any = 0;
+ for ( j=0; j<bdfc->bytes_per_line; ++j )
+ if ( bdfc->bitmap[i*bdfc->bytes_per_line+j]!=0 ) any = 1;
+ if ( any )
+ break;
+ }
+ if ( i!=0 ) {
+ bdfc->ymax -= i;
+ memmove(bdfc->bitmap,bdfc->bitmap+i*bdfc->bytes_per_line,(bdfc->ymax-bdfc->ymin+1)*bdfc->bytes_per_line );
+ }
+
+ for ( i=bdfc->ymax-bdfc->ymin; i>0; --i ) {
+ any = 0;
+ for ( j=0; j<bdfc->bytes_per_line; ++j )
+ if ( bdfc->bitmap[i*bdfc->bytes_per_line+j]!=0 ) any = 1;
+ if ( any )
+ break;
+ }
+ if ( i!=bdfc->ymax-bdfc->ymin ) {
+ bdfc->ymin += bdfc->ymax-bdfc->ymin-i;
+ }
+
+ if ( !bdfc->byte_data ) {
+ for ( j=0; j<bdfc->xmax-bdfc->xmin; ++j ) {
+ any = 0;
+ for ( i=0; i<bdfc->ymax-bdfc->ymin+1; ++i )
+ if ( bdfc->bitmap[i*bdfc->bytes_per_line+(j>>3)] & (1<<(7-(j&7))) )
+ any = 1;
+ if ( any )
+ break;
+ }
+ off = j;
+ if ( off/8>0 ) {
+ for ( i=0; i<bdfc->ymax-bdfc->ymin+1; ++i ) {
+ memmove(bdfc->bitmap+i*bdfc->bytes_per_line,
+ bdfc->bitmap+i*bdfc->bytes_per_line+off/8,
+ bdfc->bytes_per_line-off/8);
+ memset(bdfc->bitmap+(i+1)*bdfc->bytes_per_line-off/8,
+ 0, off/8);
+ }
+ bdfc->xmin += off-off%8;
+ off %= 8;
+ }
+ if ( off!=0 ) {
+ for ( i=0; i<bdfc->ymax-bdfc->ymin+1; ++i ) {
+ last = 0;
+ for ( j=bdfc->bytes_per_line-1; j>=0; --j ) {
+ int index = i*bdfc->bytes_per_line+j;
+ int temp = bdfc->bitmap[index]>>(8-off);
+ bdfc->bitmap[index] = (bdfc->bitmap[index]<<off)|last;
+ last = temp;
+ }
+ if ( last!=0 )
+ IError("Sigh");
+ }
+ bdfc->xmin += off;
+ }
+
+ for ( j=bdfc->xmax-bdfc->xmin; j>0; --j ) {
+ any = 0;
+ for ( i=0; i<bdfc->ymax-bdfc->ymin+1; ++i )
+ if ( bdfc->bitmap[i*bdfc->bytes_per_line+(j>>3)] & (1<<(7-(j&7))) )
+ any = 1;
+ if ( any )
+ break;
+ }
+ if ( j!=bdfc->xmax+bdfc->xmin ) {
+ bdfc->xmax -= bdfc->xmax-bdfc->xmin-j;
+ }
+ BCRegularizeBitmap(bdfc);
+ } else {
+ for ( j=0; j<bdfc->xmax-bdfc->xmin; ++j ) {
+ any = 0;
+ for ( i=0; i<bdfc->ymax-bdfc->ymin+1; ++i )
+ if ( bdfc->bitmap[i*bdfc->bytes_per_line+j] != 0 )
+ any = 1;
+ if ( any )
+ break;
+ }
+ off = j;
+ if ( off!=0 ) {
+ for ( i=0; i<bdfc->ymax-bdfc->ymin+1; ++i ) {
+ memmove(bdfc->bitmap+i*bdfc->bytes_per_line,
+ bdfc->bitmap+i*bdfc->bytes_per_line+off,
+ bdfc->bytes_per_line-off);
+ memset(bdfc->bitmap+(i+1)*bdfc->bytes_per_line-off,
+ 0, off);
+ }
+ bdfc->xmin += off;
+ }
+
+ for ( j=bdfc->xmax-bdfc->xmin; j>0; --j ) {
+ any = 0;
+ for ( i=0; i<bdfc->ymax-bdfc->ymin+1; ++i )
+ if ( bdfc->bitmap[i*bdfc->bytes_per_line+j] != 0 )
+ any = 1;
+ if ( any )
+ break;
+ }
+ if ( j!=bdfc->xmax+bdfc->xmin ) {
+ bdfc->xmax -= bdfc->xmax-bdfc->xmin-j;
+ }
+ BCRegularizeGreymap(bdfc);
+ }
+ if ( bdfc->xmax<bdfc->xmin || bdfc->ymax<bdfc->ymin ) {
+ bdfc->ymax = bdfc->ymin-1;
+ bdfc->xmax = bdfc->xmin-1;
+ }
+}
+
+#ifndef LUA_FF_LIB
+static void Bresenham(uint8 *bytemap,EdgeList *es,int x1,int x2,int y1,int y2,
+ int grey) {
+ int dx, dy, incr1, incr2, d, x, y;
+ int incr3;
+ int bytes_per_line = es->bytes_per_line<<3;
+ int ymax = es->cnt;
+
+ /* We are guarenteed x1<=x2 */
+ dx = x2-x1;
+ if ( (dy = y1-y2)<0 ) dy=-dy;
+ if ( dx>=dy ) {
+ d = 2 * dy - dx;
+ incr1 = 2*dy;
+ incr2 = 2*(dy-dx);
+ incr3 = y2>y1 ? 1 : -1;
+ x = x1;
+ y = y1;
+ if ( x>=0 && y>=0 && x<bytes_per_line && y<ymax )
+ bytemap[y*bytes_per_line+x] = grey;
+ while ( x<x2 ) {
+ ++x;
+ if ( d<0 )
+ d += incr1;
+ else {
+ y += incr3;
+ d += incr2;
+ }
+ if ( x>=0 && y>=0 && x<bytes_per_line && y<ymax )
+ bytemap[y*bytes_per_line+x] = grey;
+ }
+ } else {
+ if ( y1>y2 ) {
+ incr1 = y1; y1 = y2; y2 = incr1;
+ incr1 = x1; x1 = x2; x2 = incr1;
+ }
+ d = 2 * dx - dy;
+ incr1 = 2*dx;
+ incr2 = 2*(dx-dy);
+ incr3 = x2>x1 ? 1 : -1;
+ x = x1;
+ y = y1;
+ if ( x>=0 && y>=0 && x<bytes_per_line && y<ymax )
+ bytemap[y*bytes_per_line+x] = grey;
+ while ( y<y2 ) {
+ ++y;
+ if ( d<0 )
+ d += incr1;
+ else {
+ x += incr3;
+ d += incr2;
+ }
+ if ( x>=0 && y>=0 && x<bytes_per_line && y<ymax )
+ bytemap[y*bytes_per_line+x] = grey;
+ }
+ }
+}
+
+static void StrokeLine(uint8 *bytemap,IPoint *from, IPoint *to,EdgeList *es,int grey,int width) {
+ int x1, x2, y1, y2;
+ int dx, dy;
+ int i, w2;
+
+ x1 = from->x - es->omin;
+ x2 = to->x - es->omin;
+ if ( (y1 = (es->cnt-1 - (from->y - es->mmin)))<0 ) y1=0;
+ if ( (y2 = (es->cnt-1 - (to->y - es->mmin)))<0 ) y2=0;
+
+ if ( x1>x2 ) {
+ dx = x1; x1 = x2; x2 = dx;
+ dy = y1; y1 = y2; y2 = dy;
+ }
+
+ if ( width>1 ) {
+ w2 = width/2;
+ dx = x2-x1;
+ if ( (dy = y1-y2)<0 ) dy=-dy;
+ if ( dy>2*dx ) {
+ x1 -= w2; x2 -= w2;
+ for ( i=0; i<width; ++i )
+ Bresenham(bytemap,es,x1+i,x2+i,y1,y2,grey);
+ } else if ( dx>2*dy ) {
+ y1 -= w2; y2 -= w2;
+ for ( i=0; i<width; ++i )
+ Bresenham(bytemap,es,x1,x2,y1+i,y2+i,grey);
+ } else if ( y2>y1 ) {
+ width *= 1.414; w2 = width/2;
+ x1-=w2/2; y1+=w2/2; x2-=w2/2; y2+=w2/2;
+ for ( i=0; 2*i<width; ++i ) {
+ Bresenham(bytemap,es,x1+i,x2+i,y1-i,y2-i,grey);
+ Bresenham(bytemap,es,x1+i+1,x2+i+1,y1-i,y2-i,grey);
+ }
+ } else {
+ width *= 1.414; w2 = width/2;
+ x1-=w2/2; y1-=w2/2; x2-=w2/2; y2-=w2/2;
+ for ( i=0; 2*i<width; ++i ) {
+ Bresenham(bytemap,es,x1+i,x2+i,y1+i,y2+i,grey);
+ Bresenham(bytemap,es,x1+i+1,x2+i+1,y1+i,y2+i,grey);
+ }
+ }
+ } else
+ Bresenham(bytemap,es,x1,x2,y1,y2,grey);
+}
+
+static void StrokeSS(uint8 *bytemap,EdgeList *es,int width,int grey,SplineSet *ss) {
+ LinearApprox *lap;
+ LineList *line, *prev;
+ Spline *spline, *first;
+
+ for ( ; ss!=NULL; ss=ss->next ) {
+ first = NULL;
+ for ( spline = ss->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) {
+ lap = SplineApproximate(spline,es->scale);
+ if ( lap->lines!=NULL ) {
+ for ( prev = lap->lines, line=prev->next; line!=NULL; prev = line, line=line->next )
+ StrokeLine(bytemap,&prev->here,&line->here,es,grey,width);
+ }
+ if ( first == NULL ) first = spline;
+ }
+ }
+}
+
+static void StrokeGlyph(uint8 *bytemap,EdgeList *es,real wid, SplineChar *sc) {
+ RefChar *ref;
+ int width = rint(wid*es->scale);
+
+ StrokeSS(bytemap,es,width,0xff,sc->layers[ly_fore].splines);
+ for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref = ref->next )
+ StrokeSS(bytemap,es,width,0xff,ref->layers[0].splines);
+}
+#endif
+
+#ifdef FONTFORGE_CONFIG_TYPE3
+static void StrokePaths(uint8 *bytemap,EdgeList *es,Layer *layer,Layer *alt) {
+ uint32 col;
+ int width;
+ int grey;
+
+ if ( layer->stroke_pen.brush.col!=COLOR_INHERITED )
+ col = layer->stroke_pen.brush.col;
+ else if ( alt!=NULL && alt->stroke_pen.brush.col!=COLOR_INHERITED )
+ col = alt->stroke_pen.brush.col;
+ else
+ col = 0x000000;
+ if ( layer->stroke_pen.width!=WIDTH_INHERITED )
+ width = rint(layer->stroke_pen.width*layer->stroke_pen.trans[0]*es->scale);
+ else if ( alt!=NULL && alt->stroke_pen.width!=WIDTH_INHERITED )
+ width = rint(alt->stroke_pen.width*alt->stroke_pen.trans[0]*es->scale);
+ else
+ width = 1;
+ grey = ( ((col>>16)&0xff)*3 + ((col>>8)&0xff)*6 + (col&0xff) )/ 10;
+ /* but our internal greymap convention is backwards */
+ grey = 255-grey;
+
+ StrokeSS(bytemap,es,width,grey,layer->splines);
+}
+
+static void SetByteMapToGrey(uint8 *bytemap,EdgeList *es,Layer *layer,Layer *alt) {
+ uint32 col;
+ int grey,i,j;
+ uint8 *pt, *bpt;
+
+ if ( layer->fill_brush.col!=COLOR_INHERITED )
+ col = layer->fill_brush.col;
+ else if ( alt!=NULL && alt->fill_brush.col!=COLOR_INHERITED )
+ col = alt->fill_brush.col;
+ else
+ col = 0x000000;
+ grey = ( ((col>>16)&0xff)*3 + ((col>>8)&0xff)*6 + (col&0xff) )/ 10;
+ /* but our internal greymap convention is backwards */
+ grey = 255-grey;
+
+ for ( i=0; i<es->cnt; ++i ) {
+ bpt = es->bitmap + i*es->bytes_per_line;
+ pt = bytemap + i*8*es->bytes_per_line;
+ for ( j=0; j<8*es->bytes_per_line; ++j ) {
+ if ( bpt[j>>3]&(0x80>>(j&7)) )
+ pt[j] = grey;
+ }
+ }
+}
+
+#ifdef FONTFORGE_CONFIG_GTK
+static void FillImages(uint8 *bytemap,EdgeList *es,ImageList *img,Layer *layer,Layer *alt) {
+}
+#else
+static void FillImages(uint8 *bytemap,EdgeList *es,ImageList *img,Layer *layer,Layer *alt) {
+ uint32 fillcol, col;
+ int grey,i,j,x1,x2,y1,y2,jj,ii;
+
+ if ( layer->fill_brush.col!=COLOR_INHERITED )
+ fillcol = layer->fill_brush.col;
+ else if ( alt!=NULL && alt->fill_brush.col!=COLOR_INHERITED )
+ fillcol = alt->fill_brush.col;
+ else
+ fillcol = 0x000000;
+
+ while ( img!=NULL ) {
+ struct _GImage *base = img->image->list_len==0?
+ img->image->u.image:img->image->u.images[0];
+
+ y1 = es->cnt-1 - (img->yoff*es->scale - es->mmin);
+ y2 = es->cnt-1 - ((img->yoff-base->height*img->yscale)*es->scale -es->mmin);
+ x1 = img->xoff*es->scale - es->omin;
+ x2 = (img->xoff+base->width*img->xscale)*es->scale - es->omin;
+ if ( y1==y2 || x1==x2 ) /* too small to show */
+ continue;
+ for ( i=0; i<=y2-y1; ++i ) {
+ if ( i+y1<0 || i+y1>=es->cnt ) /* Shouldn't happen, rounding errors might gives us off by 1s though */
+ continue;
+ ii = i*(base->height-1)/(y2-y1);
+ for ( j=0; j<x2-x1; ++j ) {
+ if ( j+x1<0 || j+x1>=8*es->bytes_per_line )
+ continue;
+ jj = j*(base->width-1)/(x2-x1);
+ if ( base->image_type==it_true )
+ col = ((uint32 *) (base->data + ii*base->bytes_per_line))[jj];
+ else if ( base->image_type==it_index ) {
+ col = (base->data + ii*base->bytes_per_line)[jj];
+ col = base->clut->clut[col];
+ } else if ( layer->dofill && base->trans!=-1) { /* Equivalent to imagemask */
+ if ( (base->trans==0 && !( (base->data + ii*base->bytes_per_line)[jj>>3]&(0x80>>(jj&7)) ) ) ||
+ (base->trans!=0 && ( (base->data + ii*base->bytes_per_line)[jj>>3]&(0x80>>(jj&7)) ) ))
+ continue; /* transparent */
+ col = fillcol;
+ } else {
+ int index = 0;
+ if ( (base->data + ii*base->bytes_per_line)[jj>>3]&(0x80>>(j&7)) )
+ index = 1;
+ if ( base->clut!=NULL ) {
+ col = base->clut->clut[index];
+ if ( col==0xb0b0b0 ) col = 0xffffff;
+ } else if ( index==1 )
+ col = 0xffffff;
+ else
+ col = 0x000000;
+ }
+ grey = ( ((col>>16)&0xff)*3 + ((col>>8)&0xff)*6 + (col&0xff) )/ 10;
+ /* but our internal greymap convention is backwards */
+ grey = 255-grey;
+ bytemap[(i+y1)*8*es->bytes_per_line + j+x1] = grey;
+ }
+ }
+ img = img->next;
+ }
+}
+#endif
+
+static void ProcessLayer(uint8 *bytemap,EdgeList *es,Layer *layer,
+ Layer *alt) {
+ ImageList *img;
+
+ if ( !layer->fillfirst && layer->dostroke )
+ StrokePaths(bytemap,es,layer,alt);
+ if ( layer->dofill ) {
+ memset(es->bitmap,0,es->cnt*es->bytes_per_line);
+ FindEdgesSplineSet(layer->splines,es);
+ FillChar(es);
+ SetByteMapToGrey(bytemap,es,layer,alt);
+ _FreeEdgeList(es);
+ }
+ for ( img = layer->images; img!=NULL; img=img->next )
+ FillImages(bytemap,es,img,layer,alt);
+ if ( layer->fillfirst && layer->dostroke )
+ StrokePaths(bytemap,es,layer,alt);
+}
+#endif
+
+#ifndef LUA_FF_LIB
+
+static void FlattenBytemap(EdgeList *es,uint8 *bytemap) {
+ int i,j;
+ uint8 *bpt, *pt;
+
+ memset(es->bitmap,0,es->cnt*es->bytes_per_line);
+ for ( i=0; i<es->cnt; ++i ) {
+ bpt = es->bitmap + i*es->bytes_per_line;
+ pt = bytemap + i*8*es->bytes_per_line;
+ for ( j=0; j<8*es->bytes_per_line; ++j )
+ if ( pt[j]>=128 )
+ bpt[j>>3] |= (0x80>>(j&7));
+ }
+}
+
+static int FigureBitmap(EdgeList *es,uint8 *bytemap, int is_aa) {
+ if ( is_aa ) {
+ free(es->bitmap);
+ es->bitmap = bytemap;
+return( 8 );
+ } else {
+ FlattenBytemap(es,bytemap);
+ free(bytemap);
+return( 0 );
+ }
+}
+
+
+/* Yes, I really do want a double, even though it will almost always be an */
+/* integer value there are a few cases (fill pattern for charview) where */
+/* I need more precision and the pixelsize itself is largely irrelevant */
+/* (I care about the scale though) */
+static BDFChar *_SplineCharRasterize(SplineChar *sc, double pixelsize, int is_aa) {
+ EdgeList es;
+ DBounds b;
+ BDFChar *bdfc;
+ int depth = 0;
+
+ if ( sc==NULL )
+return( NULL );
+ memset(&es,'\0',sizeof(es));
+ if ( sc==NULL ) {
+ es.mmin = es.mmax = es.omin = es.omax = 0;
+ es.bitmap = gcalloc(1,1);
+ es.bytes_per_line = 1;
+ is_aa = false;
+ } else {
+ SplineCharFindBounds(sc,&b);
+ es.scale = (pixelsize-.1) / (real) (sc->parent->ascent+sc->parent->descent);
+ es.mmin = floor(b.miny*es.scale);
+ es.mmax = ceil(b.maxy*es.scale);
+ es.omin = b.minx*es.scale;
+ es.omax = b.maxx*es.scale;
+ es.cnt = (int) (es.mmax-es.mmin) + 1;
+ if ( es.cnt<4000 && es.omax-es.omin<4000 && es.cnt>1 ) {
+ es.edges = gcalloc(es.cnt,sizeof(Edge *));
+ es.sc = sc;
+ es.major = 1; es.other = 0;
+ es.bytes_per_line = ((int) ceil(es.omax-es.omin) + 8)/8;
+ es.bitmap = gcalloc(es.cnt*es.bytes_per_line,1);
+
+ InitializeHints(sc,&es);
+#ifdef FONTFORGE_CONFIG_TYPE3
+ if ( sc->parent->multilayer ) {
+ uint8 *bytemap = gcalloc(es.cnt*es.bytes_per_line*8,1);
+ int layer, i;
+ RefChar *rf;
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ ProcessLayer(bytemap,&es,&sc->layers[layer],NULL);
+
+ for ( rf=sc->layers[layer].refs; rf!=NULL; rf = rf->next ) {
+ for ( i=0; i<rf->layer_cnt; ++i ) {
+ ProcessLayer(bytemap,&es,(Layer *) (&rf->layers[i]),
+ &sc->layers[layer]);
+ }
+ }
+ }
+ depth = FigureBitmap(&es,bytemap,is_aa);
+ } else
+#endif
+ if ( sc->parent->strokedfont ) {
+ uint8 *bytemap = gcalloc(es.cnt*es.bytes_per_line*8,1);
+ StrokeGlyph(bytemap,&es,sc->parent->strokewidth,sc);
+ depth = FigureBitmap(&es,bytemap,is_aa);
+ } else {
+ FindEdges(sc,&es);
+ FillChar(&es);
+ depth = 0;
+ }
+ } else {
+ /* If they want a bitmap so enormous it threatens our memory */
+ /* then just give 'em a blank. It's probably by mistake anyway */
+ es.mmin = es.mmax = es.omin = es.omax = 0;
+ es.bitmap = gcalloc(1,1);
+ es.bytes_per_line = 1;
+ }
+ }
+
+ bdfc = chunkalloc(sizeof(BDFChar));
+ bdfc->sc = sc;
+ bdfc->xmin = rint(es.omin);
+ bdfc->ymin = es.mmin;
+ bdfc->xmax = (int) ceil(es.omax-es.omin) + bdfc->xmin;
+ bdfc->ymax = es.mmax;
+ if ( sc!=NULL ) {
+ bdfc->width = rint(sc->width*pixelsize / (real) (sc->parent->ascent+sc->parent->descent));
+ bdfc->vwidth = rint(sc->vwidth*pixelsize / (real) (sc->parent->ascent+sc->parent->descent));
+ bdfc->orig_pos = sc->orig_pos;
+ }
+ bdfc->bitmap = es.bitmap;
+ bdfc->depth = depth;
+ bdfc->bytes_per_line = es.bytes_per_line;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ if ( depth==8 ) {
+ bdfc->byte_data = true;
+ bdfc->bytes_per_line *= 8;
+ }
+#endif
+ BCCompressBitmap(bdfc);
+ FreeEdges(&es);
+return( bdfc );
+}
+
+BDFChar *SplineCharRasterize(SplineChar *sc, double pixelsize) {
+return( _SplineCharRasterize(sc,pixelsize,false));
+}
+
+BDFFont *SplineFontToBDFHeader(SplineFont *_sf, int pixelsize, int indicate) {
+ BDFFont *bdf = gcalloc(1,sizeof(BDFFont));
+ int i;
+ real scale;
+ char size[40];
+ char aa[200];
+ int max;
+ SplineFont *sf; /* The complexity here is to pick the appropriate subfont of a CID font */
+
+ sf = _sf;
+ max = sf->glyphcnt;
+ for ( i=0; i<_sf->subfontcnt; ++i ) {
+ sf = _sf->subfonts[i];
+ if ( sf->glyphcnt>max ) max = sf->glyphcnt;
+ }
+ scale = pixelsize / (real) (sf->ascent+sf->descent);
+
+ if ( indicate ) {
+ sprintf(size,_("%d pixels"), pixelsize );
+ strcpy(aa,_("Generating bitmap font"));
+ if ( sf->fontname!=NULL ) {
+ strcat(aa,": ");
+ strncat(aa,sf->fontname,sizeof(aa)-strlen(aa));
+ aa[sizeof(aa)-1] = '\0';
+ }
+ gwwv_progress_start_indicator(10,_("Rasterizing..."),
+ aa,size,sf->glyphcnt,1);
+ gwwv_progress_enable_stop(0);
+ }
+ bdf->sf = _sf;
+ bdf->glyphcnt = bdf->glyphmax = max;
+ bdf->pixelsize = pixelsize;
+ bdf->glyphs = galloc(max*sizeof(BDFChar *));
+ bdf->ascent = rint(sf->ascent*scale);
+ bdf->descent = pixelsize-bdf->ascent;
+ bdf->res = -1;
+return( bdf );
+}
+#endif
+
+#ifndef LUA_FF_LIB
+#if 0
+/* This code was an attempt to do better at rasterizing by making a big bitmap*/
+/* and shrinking it down. It did make curved edges look better, but it made */
+/* straight edges worse. So I don't think it's worth it. */
+static int countsquare(BDFChar *bc, int i, int j, int linear_scale) {
+ int ii,jj,jjj, cnt;
+ uint8 *bpt;
+
+ cnt = 0;
+ for ( ii=0; ii<linear_scale; ++ii ) {
+ if ( i*linear_scale+ii>bc->ymax-bc->ymin )
+ break;
+ bpt = bc->bitmap + (i*linear_scale+ii)*bc->bytes_per_line;
+ for ( jj=0; jj<linear_scale; ++jj ) {
+ jjj = j*linear_scale+jj;
+ if ( jjj>bc->xmax-bc->xmin )
+ break;
+ if ( bpt[jjj>>3]& (1<<(7-(jjj&7))) )
+ ++cnt;
+ }
+ }
+return( cnt );
+}
+
+static int makesleftedge(BDFChar *bc, int i, int j, int linear_scale) {
+ int ii,jjj;
+ uint8 *bpt;
+
+ for ( ii=0; ii<linear_scale; ++ii ) {
+ if ( i*linear_scale+ii>bc->ymax-bc->ymin )
+return( false );
+ bpt = bc->bitmap + (i*linear_scale+ii)*bc->bytes_per_line;
+ jjj = j*linear_scale;
+ if ( !( bpt[jjj>>3]& (1<<(7-(jjj&7))) ))
+return( false );
+ }
+return( true );
+}
+
+static int makesbottomedge(BDFChar *bc, int i, int j, int linear_scale) {
+ int jj,jjj;
+ uint8 *bpt;
+
+ for ( jj=0; jj<linear_scale; ++jj ) {
+ jjj = j*linear_scale+jj;
+ if ( jjj>bc->xmax-bc->xmin )
+return( false );
+ bpt = bc->bitmap + (i*linear_scale)*bc->bytes_per_line;
+ if ( !( bpt[jjj>>3]& (1<<(7-(jjj&7))) ))
+return( false );
+ }
+return( true );
+}
+
+static int makesline(BDFChar *bc, int i, int j, int linear_scale) {
+ int ii,jj,jjj;
+ int across, any, alltop, allbottom; /* alltop is sometimes allleft, and allbottom allright */
+ uint8 *bpt;
+ /* If we have a line that goes all the way across a square then we want */
+ /* to turn on the pixel that corresponds to that square. Exception: */
+ /* if that line is on an edge of the square, and the square adjacent to */
+ /* it has more pixels, then let the adjacent square get the pixel */
+ /* if two squares are essentially equal, choose the top one */
+
+ across = alltop = allbottom = true;
+ for ( ii=0; ii<linear_scale; ++ii ) {
+ if ( i*linear_scale+ii>bc->ymax-bc->ymin ) {
+ across = alltop = allbottom = false;
+ break;
+ }
+ bpt = bc->bitmap + (i*linear_scale+ii)*bc->bytes_per_line;
+ jjj = j*linear_scale;
+ if ( !( bpt[jjj>>3]& (1<<(7-(jjj&7))) ))
+ allbottom = 0;
+ jjj += linear_scale-1;
+ if ( jjj>bc->xmax-bc->xmin )
+ alltop = false;
+ else if ( !( bpt[jjj>>3]& (1<<(7-(jjj&7))) ))
+ alltop = 0;
+ any = false;
+ for ( jj=0; jj<linear_scale; ++jj ) {
+ jjj = j*linear_scale+jj;
+ if ( jjj>bc->xmax-bc->xmin )
+ break;
+ if ( bpt[jjj>>3]& (1<<(7-(jjj&7))) )
+ any = true;
+ }
+ if ( !any )
+ across = false;
+ }
+ if ( across ) {
+ if ( (!alltop && !allbottom ) || (alltop && allbottom))
+return( true );
+ if ( allbottom ) {
+ if ( j==0 )
+return( true );
+ if ( countsquare(bc,i,j-1,linear_scale)>=linear_scale*linear_scale/2 )
+return( false );
+return( true );
+ }
+ if ( alltop ) {
+ if ( j==(bc->xmax-bc->xmin)/linear_scale )
+return( true );
+ if ( countsquare(bc,i,j+1,linear_scale)>=linear_scale*linear_scale/2 )
+return( false );
+ if ( makesleftedge(bc,i,j+1,linear_scale))
+return( false );
+return( true );
+ }
+ }
+
+ /* now the other dimension */
+ across = alltop = allbottom = true;
+ for ( jj=0; jj<linear_scale; ++jj ) {
+ jjj = j*linear_scale+jj;
+ if ( jjj>bc->xmax-bc->xmin ) {
+ across = alltop = allbottom = false;
+ break;
+ }
+ bpt = bc->bitmap + (i*linear_scale)*bc->bytes_per_line;
+ if ( !( bpt[jjj>>3]& (1<<(7-(jjj&7))) ))
+ allbottom = 0;
+ if ( i*linear_scale + linear_scale-1>bc->ymax-bc->ymin )
+ alltop = 0;
+ else {
+ bpt = bc->bitmap + (i*linear_scale+linear_scale-1)*bc->bytes_per_line;
+ if ( !( bpt[jjj>>3]& (1<<(7-(jjj&7))) ))
+ alltop = 0;
+ }
+ any = false;
+ for ( ii=0; ii<linear_scale; ++ii ) {
+ if ( (i*linear_scale+ii)>bc->xmax-bc->xmin )
+ break;
+ bpt = bc->bitmap + (i*linear_scale+ii)*bc->bytes_per_line;
+ if ( bpt[jjj>>3]& (1<<(7-(jjj&7))) )
+ any = true;
+ }
+ if ( !any )
+ across = false;
+ }
+ if ( across ) {
+ if ( (!alltop && !allbottom ) || (alltop && allbottom))
+return( true );
+ if ( allbottom ) {
+ if ( i==0 )
+return( true );
+ if ( countsquare(bc,i-1,j,linear_scale)>=linear_scale*linear_scale/2 )
+return( false );
+return( true );
+ }
+ if ( alltop ) {
+ if ( i==(bc->ymax-bc->ymin)/linear_scale )
+return( true );
+ if ( countsquare(bc,i+1,j,linear_scale)>=linear_scale*linear_scale/2 )
+return( false );
+ if ( makesbottomedge(bc,i+1,j,linear_scale))
+return( false );
+return( true );
+ }
+ }
+
+return( false ); /* No line */
+}
+
+/* Make a much larger bitmap than we need, and then shrink it */
+static void BDFCShrinkBitmap(BDFChar *bc, int linear_scale) {
+ BDFChar new;
+ int i,j, mid = linear_scale*linear_scale/2;
+ int cnt;
+ uint8 *pt;
+
+ if ( bc==NULL )
+return;
+
+ memset(&new,'\0',sizeof(new));
+ new.xmin = floor( ((real) bc->xmin)/linear_scale );
+ new.ymin = floor( ((real) bc->ymin)/linear_scale );
+ new.xmax = new.xmin + (bc->xmax-bc->xmin+linear_scale-1)/linear_scale;
+ new.ymax = new.ymin + (bc->ymax-bc->ymin+linear_scale-1)/linear_scale;
+ new.width = rint( ((real) bc->width)/linear_scale );
+
+ new.bytes_per_line = (new.xmax-new.xmin+1);
+ new.enc = bc->enc;
+ new.sc = bc->sc;
+ new.byte_data = true;
+ new.bitmap = gcalloc( (new.ymax-new.ymin+1) * new.bytes_per_line, sizeof(uint8));
+ for ( i=0; i<=new.ymax-new.ymin; ++i ) {
+ pt = new.bitmap + i*new.bytes_per_line;
+ for ( j=0; j<=new.xmax-new.xmin; ++j ) {
+ cnt = countsquare(bc,i,j,linear_scale);
+ if ( cnt>=mid )
+ pt[j>>3] |= (1<<(7-(j&7)));
+ else if ( cnt>=linear_scale && makesline(bc,i,j,linear_scale))
+ pt[j>>3] |= (1<<(7-(j&7)));
+ }
+ }
+ free(bc->bitmap);
+ *bc = new;
+}
+
+BDFChar *SplineCharSlowerRasterize(SplineChar *sc, int pixelsize) {
+ BDFChar *bc;
+ int linear_scale = 1;
+
+ if ( pixelsize<=30 )
+ linear_scale = 4;
+ else if ( pixelsize<=40 )
+ linear_scale = 3;
+ else if ( pixelsize<=60 )
+ linear_scale = 2;
+
+ bc = SplineCharRasterize(sc,pixelsize*linear_scale);
+ if ( linear_scale==1 )
+return( bc );
+ BDFCShrinkBitmap(bc,linear_scale);
+return( bc );
+}
+
+BDFFont *SplineFontRasterize(SplineFont *_sf, int pixelsize, int indicate, int slower) {
+#else
+BDFFont *SplineFontRasterize(SplineFont *_sf, int pixelsize, int indicate) {
+#endif
+ BDFFont *bdf = SplineFontToBDFHeader(_sf,pixelsize,indicate);
+ int i,k;
+ SplineFont *sf=_sf; /* The complexity here is to pick the appropriate subfont of a CID font */
+
+ for ( i=0; i<bdf->glyphcnt; ++i ) {
+ if ( _sf->subfontcnt!=0 ) {
+ for ( k=0; k<_sf->subfontcnt; ++k ) if ( _sf->subfonts[k]->glyphcnt>i ) {
+ sf = _sf->subfonts[k];
+ if ( SCWorthOutputting(sf->glyphs[i]))
+ break;
+ }
+ }
+#if 0
+ bdf->glyphs[i] = slower ? SplineCharSlowerRasterize(sf->glyphs[i],pixelsize):
+ SplineCharRasterize(sf->glyphs[i],pixelsize);
+#else
+ bdf->glyphs[i] = SplineCharRasterize(sf->glyphs[i],pixelsize);
+#endif
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ if ( indicate ) gwwv_progress_next();
+#elif defined(FONTFORGE_CONFIG_GTK)
+ if ( indicate ) gwwv_progress_next();
+#endif
+ }
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ if ( indicate ) gwwv_progress_end_indicator();
+#elif defined(FONTFORGE_CONFIG_GTK)
+ if ( indicate ) gwwv_progress_end_indicator();
+#endif
+return( bdf );
+}
+
+void BDFCAntiAlias(BDFChar *bc, int linear_scale) {
+ BDFChar new;
+ int i,j, max = linear_scale*linear_scale-1;
+ uint8 *bpt, *pt;
+
+ if ( bc==NULL )
+return;
+
+ memset(&new,'\0',sizeof(new));
+ new.xmin = floor( ((real) bc->xmin)/linear_scale );
+ new.ymin = floor( ((real) bc->ymin)/linear_scale );
+ new.xmax = new.xmin + (bc->xmax-bc->xmin+linear_scale-1)/linear_scale;
+ new.ymax = new.ymin + (bc->ymax-bc->ymin+linear_scale-1)/linear_scale;
+ new.width = rint( ((real) bc->width)/linear_scale );
+
+ new.bytes_per_line = (new.xmax-new.xmin+1);
+ new.orig_pos = bc->orig_pos;
+ new.sc = bc->sc;
+ new.byte_data = true;
+ new.depth = max==3 ? 2 : max==15 ? 4 : 8;
+ new.bitmap = gcalloc( (new.ymax-new.ymin+1) * new.bytes_per_line, sizeof(uint8));
+#ifdef FONTFORGE_CONFIG_TYPE3
+ if ( bc->depth>1 ) {
+ uint32 *sum = gcalloc(new.bytes_per_line,sizeof(uint32));
+ for ( i=0; i<=bc->ymax-bc->ymin; ++i ) {
+ bpt = bc->bitmap + i*bc->bytes_per_line;
+ for ( j=0; j<=bc->xmax-bc->xmin; ++j ) {
+ sum[j/linear_scale] += bpt[j];
+ }
+ if ( (i+1)%linear_scale==0 ) {
+ pt = new.bitmap + (i/linear_scale)*new.bytes_per_line;
+ for ( j=(bc->xmax-bc->xmin)/linear_scale-1; j>=0 ; --j ) {
+ int val = rint( (sum[j]+128)/255 );
+ if ( val>max ) val = max;
+ pt[j] = val;
+ }
+ memset(sum,0,new.bytes_per_line*sizeof(uint32));
+ }
+ }
+ } else {
+#else
+ {
+#endif
+ for ( i=0; i<=bc->ymax-bc->ymin; ++i ) {
+ bpt = bc->bitmap + i*bc->bytes_per_line;
+ pt = new.bitmap + (i/linear_scale)*new.bytes_per_line;
+ for ( j=0; j<=bc->xmax-bc->xmin; ++j ) {
+ if ( bpt[(j>>3)] & (1<<(7-(j&7))) )
+ /* we can get values between 0..2^n we want values between 0..(2^n-1) */
+ if ( pt[ j/linear_scale ]!=max )
+ ++pt[ j/linear_scale ];
+ }
+ }
+ }
+ free(bc->bitmap);
+ *bc = new;
+}
+#endif
+
+#ifndef LUA_FF_LIB
+GClut *_BDFClut(int linear_scale) {
+ int scale = linear_scale*linear_scale, i;
+ Color bg = default_background;
+ int bgr=((bg>>16)&0xff), bgg=((bg>>8)&0xff), bgb= (bg&0xff);
+ GClut *clut;
+
+ clut = gcalloc(1,sizeof(GClut));
+ clut->clut_len = scale;
+ clut->is_grey = (bgr==bgg && bgb==bgr);
+ clut->trans_index = -1;
+ for ( i=0; i<scale; ++i ) {
+ clut->clut[i] =
+ COLOR_CREATE( bgr- (i*(bgr))/(scale-1),
+ bgg- (i*(bgg))/(scale-1),
+ bgb- (i*(bgb))/(scale-1));
+ }
+ clut->clut[scale-1] = 0; /* avoid rounding errors */
+return( clut );
+}
+
+void BDFClut(BDFFont *bdf, int linear_scale) {
+ bdf->clut = _BDFClut(linear_scale);
+}
+#endif
+
+int BDFDepth(BDFFont *bdf) {
+ if ( bdf->clut==NULL )
+return( 1 );
+
+return( bdf->clut->clut_len==256 ? 8 :
+ bdf->clut->clut_len==16 ? 4 : 2);
+}
+
+#ifndef LUA_FF_LIB
+BDFChar *SplineCharAntiAlias(SplineChar *sc, int pixelsize, int linear_scale) {
+ BDFChar *bc;
+
+ bc = _SplineCharRasterize(sc,pixelsize*linear_scale,true);
+ if ( linear_scale!=1 )
+ BDFCAntiAlias(bc,linear_scale);
+ BCCompressBitmap(bc);
+return( bc );
+}
+
+BDFFont *SplineFontAntiAlias(SplineFont *_sf, int pixelsize, int linear_scale) {
+ BDFFont *bdf;
+ int i,k;
+ real scale;
+ char size[40];
+ char aa[200];
+ int max;
+ SplineFont *sf; /* The complexity here is to pick the appropriate subfont of a CID font */
+
+ if ( linear_scale==1 )
+return( SplineFontRasterize(_sf,pixelsize,true));
+
+ bdf = gcalloc(1,sizeof(BDFFont));
+ sf = _sf;
+ max = sf->glyphcnt;
+ for ( i=0; i<_sf->subfontcnt; ++i ) {
+ sf = _sf->subfonts[i];
+ if ( sf->glyphcnt>max ) max = sf->glyphcnt;
+ }
+ scale = pixelsize / (real) (sf->ascent+sf->descent);
+
+ sprintf(size,_("%d pixels"), pixelsize );
+ strcpy(aa,_("Generating anti-alias font"));
+ if ( sf->fontname!=NULL ) {
+ strcat(aa,": ");
+ strncat(aa,sf->fontname,sizeof(aa)-strlen(aa));
+ aa[sizeof(aa)-1] = '\0';
+ }
+ gwwv_progress_start_indicator(10,_("Rasterizing..."),
+ aa,size,sf->glyphcnt,1);
+ gwwv_progress_enable_stop(0);
+
+ if ( linear_scale>16 ) linear_scale = 16; /* can't deal with more than 256 levels of grey */
+ if ( linear_scale<=1 ) linear_scale = 2;
+ bdf->sf = _sf;
+ bdf->glyphcnt = bdf->glyphmax = max;
+ bdf->pixelsize = pixelsize;
+ bdf->glyphs = galloc(max*sizeof(BDFChar *));
+ bdf->ascent = rint(sf->ascent*scale);
+ bdf->descent = pixelsize-bdf->ascent;
+ bdf->res = -1;
+ for ( i=0; i<max; ++i ) {
+ if ( _sf->subfontcnt!=0 ) {
+ for ( k=0; k<_sf->subfontcnt; ++k ) if ( _sf->subfonts[k]->glyphcnt>i ) {
+ sf = _sf->subfonts[k];
+ if ( SCWorthOutputting(sf->glyphs[i]))
+ break;
+ }
+ scale = pixelsize / (real) (sf->ascent+sf->descent);
+ }
+ bdf->glyphs[i] = SplineCharRasterize(sf->glyphs[i],pixelsize*linear_scale);
+ BDFCAntiAlias(bdf->glyphs[i],linear_scale);
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ gwwv_progress_next();
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_progress_next();
+#endif
+ }
+ BDFClut(bdf,linear_scale);
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ gwwv_progress_end_indicator();
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_progress_end_indicator();
+#endif
+return( bdf );
+}
+
+
+BDFChar *BDFPieceMeal(BDFFont *bdf, int index) {
+ SplineChar *sc;
+ extern int use_freetype_to_rasterize_fv;
+
+ if ( index==-1 )
+return( NULL );
+ if ( bdf->glyphcnt<bdf->sf->glyphcnt ) {
+ if ( bdf->glyphmax<bdf->sf->glyphcnt )
+ bdf->glyphs = grealloc(bdf->glyphs,(bdf->glyphmax = bdf->sf->glyphmax)*sizeof(BDFChar *));
+ memset(bdf->glyphs+bdf->glyphcnt,0,(bdf->glyphmax-bdf->glyphcnt)*sizeof(SplineChar *));
+ bdf->glyphcnt = bdf->sf->glyphcnt;
+ }
+ sc = bdf->sf->glyphs[index];
+ if ( sc==NULL )
+return(NULL);
+ if ( bdf->freetype_context )
+#ifndef LUA_FF_LIB
+ bdf->glyphs[index] = SplineCharFreeTypeRasterize(bdf->freetype_context,
+ sc->orig_pos,bdf->truesize,bdf->clut?8:1);
+#endif
+ ;
+ else {
+#ifndef LUA_FF_LIB
+ if ( use_freetype_to_rasterize_fv && !sc->parent->multilayer &&
+ !sc->parent->strokedfont )
+ bdf->glyphs[index] = SplineCharFreeTypeRasterizeNoHints(sc,
+ bdf->truesize,bdf->clut?4:1);
+ else
+#endif
+ bdf->glyphs[index] = NULL;
+ if ( bdf->glyphs[index]==NULL ) {
+ if ( bdf->clut )
+ bdf->glyphs[index] = SplineCharAntiAlias(sc,bdf->truesize,4);
+ else
+ bdf->glyphs[index] = SplineCharRasterize(sc,bdf->truesize);
+ }
+ }
+return( bdf->glyphs[index] );
+}
+
+/* Piecemeal fonts are only used as the display font in the fontview */
+/* as such they are simple fonts (ie. we only display the current cid subfont) */
+BDFFont *SplineFontPieceMeal(SplineFont *sf,int pixelsize,int flags,void *ftc) {
+ BDFFont *bdf = gcalloc(1,sizeof(BDFFont));
+ real scale;
+ int truesize = pixelsize;
+
+ if ( flags&pf_bbsized ) {
+ DBounds bb;
+ SplineFontQuickConservativeBounds(sf,&bb);
+ if ( bb.maxy<sf->ascent ) bb.maxy = sf->ascent;
+ if ( bb.miny>-sf->descent ) bb.miny = -sf->descent;
+ /* Ignore absurd values */
+ if ( bb.maxy>10*(sf->ascent+sf->descent) ) bb.maxy = 2*(sf->ascent+sf->descent);
+ if ( bb.maxx>10*(sf->ascent+sf->descent) ) bb.maxx = 2*(sf->ascent+sf->descent);
+ if ( bb.miny<-10*(sf->ascent+sf->descent) ) bb.miny = -2*(sf->ascent+sf->descent);
+ if ( bb.minx<-10*(sf->ascent+sf->descent) ) bb.minx = -2*(sf->ascent+sf->descent);
+ scale = pixelsize/ (real) (bb.maxy-bb.miny);
+ bdf->ascent = rint(bb.maxy*scale);
+ truesize = rint( (sf->ascent+sf->descent)*scale );
+ } else {
+ scale = pixelsize / (real) (sf->ascent+sf->descent);
+ bdf->ascent = rint(sf->ascent*scale);
+ }
+
+ bdf->sf = sf;
+ bdf->glyphcnt = bdf->glyphmax = sf->glyphcnt;
+ bdf->pixelsize = pixelsize;
+ bdf->glyphs = gcalloc(sf->glyphcnt,sizeof(BDFChar *));
+ bdf->descent = pixelsize-bdf->ascent;
+ bdf->piecemeal = true;
+ bdf->bbsized = (flags&pf_bbsized)?1:0;
+ bdf->res = -1;
+ bdf->truesize = truesize;
+ bdf->freetype_context = ftc;
+ if ( ftc && (flags&pf_antialias) )
+ BDFClut(bdf,16);
+ else if ( flags&pf_antialias )
+ BDFClut(bdf,4);
+return( bdf );
+}
+#endif
+
+void BDFCharFree(BDFChar *bdfc) {
+ if ( bdfc==NULL )
+return;
+ free(bdfc->bitmap);
+ chunkfree(bdfc,sizeof(BDFChar));
+}
+
+void BDFPropsFree(BDFFont *bdf) {
+ int i;
+
+ for ( i=0; i<bdf->prop_cnt; ++i ) {
+ free(bdf->props[i].name);
+ if ( (bdf->props[i].type&~prt_property)==prt_string ||
+ (bdf->props[i].type&~prt_property)==prt_atom )
+ free(bdf->props[i].u.str);
+ }
+ free( bdf->props );
+}
+
+void BDFFontFree(BDFFont *bdf) {
+ int i;
+
+ if ( bdf==NULL )
+return;
+ for ( i=0; i<bdf->glyphcnt; ++i )
+ BDFCharFree(bdf->glyphs[i]);
+ free(bdf->glyphs);
+ if ( bdf->clut!=NULL )
+ free(bdf->clut);
+#ifndef LUA_FF_LIB
+ if ( bdf->freetype_context!=NULL )
+ FreeTypeFreeContext(bdf->freetype_context);
+#endif
+ BDFPropsFree(bdf);
+ free( bdf->foundry );
+ free(bdf);
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/splinefont.h b/Build/source/libs/luafontforge/fontforge/fontforge/splinefont.h
new file mode 100644
index 00000000000..57c6f1547a0
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/splinefont.h
@@ -0,0 +1,2303 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _SPLINEFONT_H
+#define _SPLINEFONT_H
+
+#include "basics.h"
+#include "configure-pfaedit.h"
+#ifdef HAVE_ICONV_H
+# include <iconv.h>
+/* libiconv.h defines iconv as taking a const pointer for inbuf. iconv doesn't*/
+# ifdef _LIBICONV_VERSION
+# define ICONV_CONST const
+# else
+# define ICONV_CONST
+# endif
+#else
+# include <gwwiconv.h>
+# define ICONV_CONST
+#endif
+
+#if defined( FONTFORGE_CONFIG_USE_LONGDOUBLE )
+# define real long double
+# define bigreal long double
+#elif defined( FONTFORGE_CONFIG_USE_DOUBLE )
+# define real double
+# define bigreal double
+#else
+# define real float
+# define bigreal double
+#endif
+
+#if defined( HAVE_LONG_DOUBLE ) && defined( This_does_not_seem_to_make_a_difference )
+# define extended long double
+# define CheckExtremaForSingleBitErrors(sp,t) (t)
+# define EXTENDED_IS_LONG_DOUBLE 1
+#else
+# define extended double
+#endif
+ /* Solaris wants to define extended to be unsigned [3] unless we do this*/
+#define _EXTENDED
+
+#define CHR(ch1,ch2,ch3,ch4) (((ch1)<<24)|((ch2)<<16)|((ch3)<<8)|(ch4))
+
+#define MmMax 16 /* PS says at most this many instances for type1/2 mm fonts */
+#define AppleMmMax 26 /* Apple sort of has a limit of 4095, but we only support this many */
+
+typedef struct val {
+ enum val_type { v_int, v_real, v_str, v_unicode, v_lval, v_arr, v_arrfree,
+ v_int32pt, v_int16pt, v_int8pt, v_void } type;
+ union {
+ int ival;
+ real fval;
+ char *sval;
+ struct val *lval;
+ struct array *aval;
+ uint32 *u32ptval;
+ uint16 *u16ptval;
+ uint8 *u8ptval;
+ } u;
+} Val; /* Used by scripting */
+
+struct psdict {
+ int cnt, next;
+ char **keys;
+ char **values;
+};
+
+struct pschars {
+ int cnt, next;
+ char **keys;
+ uint8 **values;
+ int *lens;
+ int bias; /* for type2 strings */
+};
+
+enum linejoin {
+ lj_miter, /* Extend lines until they meet */
+ lj_round, /* circle centered at the join of expand radius */
+ lj_bevel, /* Straight line between the ends of next and prev */
+ lj_inherited
+};
+enum linecap {
+ lc_butt, /* equiv to lj_bevel, straight line extends from one side to other */
+ lc_round, /* semi-circle */
+ lc_square, /* Extend lines by radius, then join them */
+ lc_inherited
+};
+#define COLOR_INHERITED 0xfffffffe
+struct brush {
+ uint32 col;
+ /*void *pattern;*/ /* Don't know how to deal with these yet */
+ /*void *gradient;*/
+ float opacity; /* number between [0,1], only for svg */
+};
+#define WIDTH_INHERITED (-1)
+#define DASH_INHERITED 255 /* if the dashes[0]==0 && dashes[1]==DASH_INHERITED */
+#define DASH_MAX 8
+typedef unsigned char DashType;
+struct pen {
+ struct brush brush;
+ uint8 linejoin;
+ uint8 linecap;
+ float width;
+ real trans[4];
+ DashType dashes[DASH_MAX];
+};
+
+struct spline;
+enum si_type { si_std, si_caligraphic, si_elipse, si_centerline };
+/* If you change this structure you may need to update MakeStrokeDlg */
+/* and cvpalettes.c both contain statically initialized StrokeInfos */
+typedef struct strokeinfo {
+ real radius; /* or major axis of pen */
+ enum linejoin join;
+ enum linecap cap;
+ enum si_type stroke_type;
+ unsigned int toobigwarn: 1;
+ unsigned int removeinternal: 1;
+ unsigned int removeexternal: 1;
+ unsigned int removeoverlapifneeded: 1;
+ unsigned int gottoobig: 1;
+ unsigned int gottoobiglocal: 1;
+ real penangle;
+ real ratio; /* ratio of minor pen axis to major */
+/* For eplipse */
+ real minorradius;
+/* For freehand tool */
+ real radius2;
+ int pressure1, pressure2;
+/* End freehand tool */
+ bigreal c,s;
+ real xoff[8], yoff[8];
+ void *data;
+ bigreal (*factor)(void *data,struct spline *spline,real t);
+} StrokeInfo;
+
+enum overlap_type { over_remove, over_rmselected, over_intersect, over_intersel,
+ over_exclude, over_findinter, over_fisel };
+
+enum simpify_flags { sf_cleanup=-1, sf_normal=0, sf_ignoreslopes=1,
+ sf_ignoreextremum=2, sf_smoothcurves=4, sf_choosehv=8,
+ sf_forcelines=0x10, sf_nearlyhvlines=0x20,
+ sf_mergelines=0x40, sf_setstart2extremum=0x80,
+ sf_rmsingletonpoints=0x100 };
+struct simplifyinfo {
+ int flags;
+ bigreal err;
+ bigreal tan_bounds;
+ bigreal linefixup;
+ bigreal linelenmax; /* Don't simplify any straight lines longer than this */
+ int set_as_default;
+ int check_selected_contours;
+};
+
+typedef struct ipoint {
+ int x;
+ int y;
+} IPoint;
+
+typedef struct basepoint {
+ real x;
+ real y;
+} BasePoint;
+
+typedef struct tpoint {
+ real x;
+ real y;
+ real t;
+} TPoint;
+
+typedef struct dbounds {
+ real minx, maxx;
+ real miny, maxy;
+} DBounds;
+
+typedef struct ibounds {
+ int minx, maxx;
+ int miny, maxy;
+} IBounds;
+
+typedef struct bluedata {
+ real xheight, xheighttop; /* height of "x" and "o" (u,v,w,x,y,z) */
+ real caph, caphtop; /* height of "I" and "O" */
+ real base, basebelow; /* bottom of "I" and "O" */
+ real ascent; /* height of "l" */
+ real descent; /* depth of "p" */
+ real numh, numhtop; /* height of "7" and "8" */ /* numbers with ascenders */
+ int bluecnt; /* If the private dica contains bluevalues... */
+ real blues[12][2]; /* 7 pairs from bluevalues, 5 from otherblues */
+} BlueData;
+
+typedef struct bdffloat {
+ int16 xmin,xmax,ymin,ymax;
+ int16 bytes_per_line;
+ unsigned int byte_data:1;
+ uint8 depth;
+ uint8 *bitmap;
+} BDFFloat;
+
+/* OpenType does not document 'dflt' as a language, but we'll use it anyway. */
+/* (Adobe uses it too) we'll turn it into a default entry when we output it. */
+#define DEFAULT_LANG CHR('d','f','l','t')
+/* The OpenType spec says in one place that the default script is 'dflt' and */
+/* in another that it is 'DFLT'. 'DFLT' is correct */
+#define DEFAULT_SCRIPT CHR('D','F','L','T')
+#define REQUIRED_FEATURE CHR(' ','R','Q','D')
+
+enum otlookup_type {
+ ot_undef = 0, /* Not a lookup type */
+ gsub_start = 0x000, /* Not a lookup type */
+ gsub_single = 0x001,
+ gsub_multiple = 0x002,
+ gsub_alternate = 0x003,
+ gsub_ligature = 0x004,
+ gsub_context = 0x005,
+ gsub_contextchain = 0x006,
+ /* GSUB extension 7 */
+ gsub_reversecchain = 0x008,
+ /* mac state machines */
+ morx_indic = 0x0fd,
+ morx_context = 0x0fe,
+ morx_insert = 0x0ff,
+ /* ********************* */
+ gpos_start = 0x100, /* Not a lookup type */
+
+ gpos_single = 0x101,
+ gpos_pair = 0x102,
+ gpos_cursive = 0x103,
+ gpos_mark2base = 0x104,
+ gpos_mark2ligature = 0x105,
+ gpos_mark2mark = 0x106,
+ gpos_context = 0x107,
+ gpos_contextchain = 0x108,
+ /* GPOS extension 9 */
+ kern_statemachine = 0x1ff
+
+ /* otlookup&0xff == lookup type for the appropriate table */
+ /* otlookup>>8: 0=>GSUB, 1=>GPOS */
+};
+
+enum otlookup_typemasks {
+ gsub_single_mask = 0x00001,
+ gsub_multiple_mask = 0x00002,
+ gsub_alternate_mask = 0x00004,
+ gsub_ligature_mask = 0x00008,
+ gsub_context_mask = 0x00010,
+ gsub_contextchain_mask = 0x00020,
+ gsub_reversecchain_mask = 0x00040,
+ morx_indic_mask = 0x00080,
+ morx_context_mask = 0x00100,
+ morx_insert_mask = 0x00200,
+ /* ********************* */
+ gpos_single_mask = 0x00400,
+ gpos_pair_mask = 0x00800,
+ gpos_cursive_mask = 0x01000,
+ gpos_mark2base_mask = 0x02000,
+ gpos_mark2ligature_mask = 0x04000,
+ gpos_mark2mark_mask = 0x08000,
+ gpos_context_mask = 0x10000,
+ gpos_contextchain_mask = 0x20000,
+ kern_statemachine_mask = 0x40000
+};
+
+#define MAX_LANG 4 /* If more than this we allocate more_langs in chunks of MAX_LANG */
+struct scriptlanglist {
+ uint32 script;
+ uint32 langs[MAX_LANG];
+ uint32 *morelangs;
+ int lang_cnt;
+ struct scriptlanglist *next;
+};
+
+extern struct opentype_feature_friendlynames {
+ uint32 tag;
+ char *tagstr;
+ char *friendlyname;
+ int masks;
+} friendlies[];
+
+typedef struct featurescriptlanglist {
+ uint32 featuretag;
+ struct scriptlanglist *scripts;
+ struct featurescriptlanglist *next;
+ unsigned int ismac: 1; /* treat the featuretag as a mac feature/setting */
+} FeatureScriptLangList;
+
+enum pst_flags { pst_r2l=1, pst_ignorebaseglyphs=2, pst_ignoreligatures=4,
+ pst_ignorecombiningmarks=8 };
+
+typedef struct otlookup {
+ struct otlookup *next;
+ enum otlookup_type lookup_type;
+ uint16 lookup_flags;
+ char *lookup_name;
+ FeatureScriptLangList *features;
+ struct lookup_subtable {
+ char *subtable_name;
+ char *suffix; /* for gsub_single, used to find a default replacement */
+ struct otlookup *lookup;
+ unsigned int unused: 1;
+ unsigned int per_glyph_pst_or_kern: 1;
+ unsigned int anchor_classes: 1;
+ unsigned int vertical_kerning: 1;
+ unsigned int ticked: 1;
+ struct kernclass *kc;
+ struct generic_fpst *fpst;
+ struct generic_asm *sm;
+ /* Each time an item is added to a lookup we must place it into a */
+ /* subtable. If it's a kerning class, fpst or state machine it has */
+ /* a subtable all to itself. If it's an anchor class it can share */
+ /* a subtable with other anchor classes (merge with). If it's a glyph */
+ /* PST it may share a subtable with other PSTs */
+ /* Note items may only be placed in lookups in which they fit. Can't */
+ /* put kerning data in a gpos_single lookup, etc. */
+ struct lookup_subtable *next;
+ int32 subtable_offset;
+ int32 *extra_subtables;
+ /* If a kerning subtable has too much stuff in it, we are prepared to */
+ /* break it up into several smaller subtables, each of which has */
+ /* an offset in this list (extra-subtables[0]==subtable_offset) */
+ /* the list is terminated by an entry of -1 */
+ } *subtables;
+ unsigned int unused: 1; /* No subtable is used (call SFFindUnusedLookups before examining) */
+ unsigned int empty: 1; /* No subtable is used, and no anchor classes are used */
+ unsigned int store_in_afm: 1; /* Used for ligatures, some get stored */
+ /* 'liga' generally does, but 'frac' doesn't */
+ unsigned int needs_extension: 1; /* Used during opentype generation */
+ unsigned int temporary_kern: 1; /* Used when decomposing kerning classes into kern pairs for older formats */
+ unsigned int def_lang_checked: 1;
+ unsigned int def_lang_found: 1;
+ unsigned int ticked: 1;
+ int16 subcnt; /* Actual number of subtables we will output */
+ /* Some of our subtables may contain no data */
+ /* Some may be too big and need to be broken up.*/
+ /* So this field may be different than just counting the subtables */
+ int lookup_index; /* used during opentype generation */
+ uint32 lookup_offset;
+ uint32 lookup_length;
+ char *tempname;
+} OTLookup;
+
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+typedef struct devicetab {
+ uint16 first_pixel_size, last_pixel_size; /* A range of point sizes to which this table applies */
+ int8 *corrections; /* a set of pixel corrections, one for each point size */
+} DeviceTable;
+
+typedef struct valdev { /* Value records can have four associated device tables */
+ DeviceTable xadjust;
+ DeviceTable yadjust;
+ DeviceTable xadv;
+ DeviceTable yadv;
+} ValDevTab;
+#endif
+
+enum anchorclass_type { act_mark, act_mkmk, act_curs, act_mklg };
+typedef struct anchorclass {
+ char *name; /* in utf8 */
+ struct lookup_subtable *subtable;
+ uint8 type; /* anchorclass_type */
+ uint8 has_base;
+ uint8 processed, has_mark, matches, ac_num;
+ struct anchorclass *next;
+} AnchorClass;
+
+enum anchor_type { at_mark, at_basechar, at_baselig, at_basemark, at_centry, at_cexit, at_max };
+typedef struct anchorpoint {
+ AnchorClass *anchor;
+ BasePoint me;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ DeviceTable xadjust, yadjust;
+#endif
+ unsigned int type: 4;
+ unsigned int selected: 1;
+ unsigned int ticked: 1;
+ unsigned int has_ttf_pt: 1;
+ uint16 ttf_pt_index;
+ int16 lig_index;
+ struct anchorpoint *next;
+} AnchorPoint;
+
+typedef struct kernpair {
+ struct lookup_subtable *subtable;
+ struct splinechar *sc;
+ int16 off;
+ uint16 kcid; /* temporary value */
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ DeviceTable *adjust; /* Only adjustment in one dimen, if more needed use pst */
+#endif
+ struct kernpair *next;
+} KernPair;
+
+typedef struct kernclass {
+ int first_cnt, second_cnt; /* Count of classes for first and second chars */
+ char **firsts; /* list of a space seperated list of char names */
+ char **seconds; /* one entry for each class. Entry 0 is null */
+ /* and means everything not specified elsewhere */
+ struct lookup_subtable *subtable;
+ uint16 kcid; /* Temporary value, used for many things briefly */
+ int16 *offsets; /* array of first_cnt*second_cnt entries */
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ DeviceTable *adjusts; /* array of first_cnt*second_cnt entries */
+#endif
+ struct kernclass *next;
+} KernClass;
+
+enum possub_type { pst_null, pst_position, pst_pair,
+ pst_substitution, pst_alternate,
+ pst_multiple, pst_ligature,
+ pst_lcaret /* must be pst_max-1, see charinfo.c*/,
+ pst_max,
+ /* These are not psts but are related so it's handly to have values for them */
+ pst_kerning = pst_max, pst_vkerning, pst_anchors,
+ /* And these are fpsts */
+ pst_contextpos, pst_contextsub, pst_chainpos, pst_chainsub,
+ pst_reversesub, fpst_max,
+ /* And these are used to specify a kerning pair where the current */
+ /* char is the final glyph rather than the initial one */
+ /* A kludge used when cutting and pasting features */
+ pst_kernback, pst_vkernback
+ };
+
+struct vr {
+ int16 xoff, yoff, h_adv_off, v_adv_off;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ ValDevTab *adjust;
+#endif
+};
+
+typedef struct generic_pst {
+ unsigned int ticked: 1;
+ unsigned int temporary: 1; /* Used in afm ligature closure */
+ /* enum possub_type*/ uint8 type;
+ struct lookup_subtable *subtable;
+ struct generic_pst *next;
+ union {
+ struct vr pos;
+ struct { char *paired; struct vr *vr; } pair;
+ struct { char *variant; } subs;
+ struct { char *components; } mult, alt;
+ struct { char *components; struct splinechar *lig; } lig;
+ struct { int16 *carets; int cnt; } lcaret; /* Ligature caret positions */
+ } u;
+} PST;
+
+typedef struct liglist {
+ PST *lig;
+ struct splinechar *first; /* First component */
+ struct splinecharlist *components; /* Other than the first */
+ struct liglist *next;
+ int ccnt; /* Component count. (includes first component) */
+} LigList;
+
+enum fpossub_format { pst_glyphs, pst_class, pst_coverage,
+ pst_reversecoverage, pst_formatmax };
+
+typedef struct generic_fpst {
+ uint16 /*enum sfpossub_type*/ type;
+ uint16 /*enum fpossub_format*/ format;
+ struct lookup_subtable *subtable;
+ struct generic_fpst *next;
+ uint16 nccnt, bccnt, fccnt;
+ uint16 rule_cnt;
+ char **nclass, **bclass, **fclass;
+ struct fpst_rule {
+ union {
+ struct fpg { char *names, *back, *fore; } glyph;
+ struct fpc { int ncnt, bcnt, fcnt; uint16 *nclasses, *bclasses, *fclasses, *allclasses; } class;
+ struct fpv { int ncnt, bcnt, fcnt; char **ncovers, **bcovers, **fcovers; } coverage;
+ struct fpr { int always1, bcnt, fcnt; char **ncovers, **bcovers, **fcovers; char *replacements; } rcoverage;
+ } u;
+ int lookup_cnt;
+ struct seqlookup {
+ int seq;
+ struct otlookup *lookup;
+ } *lookups;
+ } *rules;
+ uint8 ticked;
+ uint8 effectively_by_glyphs;
+} FPST;
+
+enum asm_type { asm_indic, asm_context, asm_lig, asm_simple=4, asm_insert,
+ asm_kern=0x11 };
+enum asm_flags { asm_vert=0x8000, asm_descending=0x4000, asm_always=0x2000 };
+
+typedef struct generic_asm { /* Apple State Machine */
+ struct generic_asm *next;
+ uint16 /*enum asm_type*/ type;
+ struct lookup_subtable *subtable; /* Lookup contains feature setting info */
+ uint16 flags; /* 0x8000=>vert, 0x4000=>r2l, 0x2000=>hor&vert */
+ uint8 ticked;
+
+ uint16 class_cnt, state_cnt;
+ char **classes;
+ struct asm_state {
+ uint16 next_state;
+ uint16 flags;
+ union {
+ struct {
+ struct otlookup *mark_lookup; /* for contextual glyph subs (tag of a nested lookup) */
+ struct otlookup *cur_lookup; /* for contextual glyph subs */
+ } context;
+ struct {
+ char *mark_ins;
+ char *cur_ins;
+ } insert;
+ struct {
+ int16 *kerns;
+ int kcnt;
+ } kern;
+ } u;
+ } *state;
+ uint32 opentype_tag; /* If converted from opentype */
+} ASM;
+/* State Flags:
+ Indic:
+ 0x8000 mark current glyph as first in rearrangement
+ 0x4000 don't advance to next glyph
+ 0x2000 mark current glyph as last
+ 0x000f verb
+ 0 = no change 8 = AxCD => CDxA
+ 1 = Ax => xA 9 = AxCD => DCxA
+ 2 = xD => Dx a = ABxD => DxAB
+ 3 = AxD => DxA b = ABxD => DxBA
+ 4 = ABx => xAB c = ABxCD => CDxAB
+ 5 = ABx => xBA d = ABxCD => CDxBA
+ 6 = xCD => CDx e = ABxCD => DCxAB
+ 7 = xCD => DCx f = ABxCD => DCxBA
+ Contextual:
+ 0x8000 mark current glyph
+ 0x4000 don't advance to next glyph
+ Insert:
+ 0x8000 mark current glyph
+ 0x4000 don't advance to next glyph
+ 0x2000 current is Kashida like
+ 0x1000 mark is Kashida like
+ 0x0800 current insert before
+ 0x0400 mark insert before
+ 0x03e0 count of chars to be inserted at current (31 max)
+ 0x001f count of chars to be inserted at mark (31 max)
+ Kern:
+ 0x8000 add current glyph to kerning stack
+ 0x4000 don't advance to next glyph
+ 0x3fff value offset
+*/
+
+struct opentype_str {
+ struct splinechar *sc;
+ struct vr vr;
+ struct kernpair *kp;
+ struct kernclass *kc;
+ int kc_index;
+ int16 lig_pos; /* when skipping marks to form a ligature keep track of what ligature element a mark was attached to */
+ int16 context_pos; /* When doing a contextual match remember which glyphs are used, and where in the match they occur. Skipped glyphs have -1 */
+ int16 orig_index;
+};
+
+struct macname {
+ struct macname *next;
+ uint16 enc; /* Platform specific encoding. 0=>mac roman, 1=>sjis, 7=>russian */
+ uint16 lang; /* Mac languages 0=>english, 1=>french, 2=>german */
+ char *name; /* Not a unicode string, uninterpreted mac encoded string */
+};
+
+/* Wow, the GPOS 'size' feature stores a string in the name table just as mac */
+/* features do */
+struct otfname {
+ struct otfname *next;
+ uint16 lang; /* windows language code */
+ char *name; /* utf8 */
+};
+
+typedef struct macfeat {
+ struct macfeat *next;
+ uint16 feature;
+ uint8 ismutex;
+ uint8 default_setting; /* Apple's docs say both that this is a byte and a short. It's a byte */
+ uint16 strid; /* Temporary value, used when reading in */
+ struct macname *featname;
+ struct macsetting {
+ struct macsetting *next;
+ uint16 setting;
+ uint16 strid;
+ struct macname *setname;
+ unsigned int initially_enabled: 1;
+ } *settings;
+} MacFeat;
+
+typedef struct undoes {
+ struct undoes *next;
+ enum undotype { ut_none=0, ut_state, ut_tstate, ut_statehint, ut_statename,
+ ut_statelookup,
+ ut_anchors,
+ ut_width, ut_vwidth, ut_lbearing, ut_rbearing, ut_possub,
+ ut_hints, ut_bitmap, ut_bitmapsel, ut_composit, ut_multiple, ut_layers,
+ ut_noop } undotype;
+ unsigned int was_modified: 1;
+ unsigned int was_order2: 1;
+ union {
+ struct {
+ int16 width, vwidth;
+ int16 lbearingchange;
+ int unicodeenc; /* only for ut_statename */
+ char *charname; /* only for ut_statename */
+ char *comment; /* in utf8 */
+ PST *possub; /* only for ut_statename */
+ struct splinepointlist *splines;
+ struct refchar *refs;
+ struct minimumdistance *md;
+
+ struct imagelist *images;
+ void *hints; /* ut_statehint, ut_statename */
+ uint8 *instrs;
+ int instrs_len;
+ AnchorPoint *anchor;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ struct brush fill_brush;
+ struct pen stroke_pen;
+ unsigned int dofill: 1;
+ unsigned int dostroke: 1;
+ unsigned int fillfirst: 1;
+#endif
+ } state;
+ int width; /* used by both ut_width and ut_vwidth */
+ int lbearing; /* used by ut_lbearing */
+ int rbearing; /* used by ut_rbearing */
+ struct {
+ int16 width; /* width should be controled by postscript, but people don't like that */
+ int16 xmin,xmax,ymin,ymax;
+ int16 bytes_per_line;
+ int16 pixelsize;
+ int16 depth;
+ uint8 *bitmap;
+ BDFFloat *selection;
+ } bmpstate;
+ struct { /* copy contains an outline state and a set of bitmap states */
+ struct undoes *state;
+ struct undoes *bitmaps;
+ } composit;
+ struct {
+ struct undoes *mult; /* copy contains several sub copies (composits, or states or widths or...) */
+ /* Also used for ut_layers, each sub copy is a state (first is ly_fore, next ly_fore+1...) */
+ } multiple;
+ struct {
+ enum possub_type pst;
+ char **data; /* First 4 bytes is tag, then space then data */
+ struct undoes *more_pst;
+ short cnt,max; /* Not always set */
+ } possub;
+ uint8 *bitmap;
+ } u;
+ struct splinefont *copied_from;
+} Undoes;
+
+typedef struct bdfchar {
+ struct splinechar *sc;
+ int16 xmin,xmax,ymin,ymax;
+ int16 width;
+ int16 bytes_per_line;
+ uint8 *bitmap;
+ int orig_pos;
+ struct bitmapview *views;
+ Undoes *undoes;
+ Undoes *redoes;
+ unsigned int changed: 1;
+ unsigned int byte_data: 1; /* for anti-aliased chars entries are grey-scale bytes not bw bits */
+ unsigned int widthgroup: 1; /* for ttf bitmap output */
+ unsigned int isreference: 1; /* for ttf bitmap input, */
+ unsigned int ticked: 1;
+ uint8 depth; /* for ttf bitmap output */
+ uint16 vwidth;
+ BDFFloat *selection;
+} BDFChar;
+
+typedef struct enc {
+ char *enc_name;
+ int char_cnt; /* Size of the next two arrays */
+ int32 *unicode; /* unicode value for each encoding point */
+ char **psnames; /* optional postscript name for each encoding point */
+ struct enc *next;
+ unsigned int builtin: 1;
+ unsigned int hidden: 1;
+ unsigned int only_1byte: 1;
+ unsigned int has_1byte: 1;
+ unsigned int has_2byte: 1;
+ unsigned int is_unicodebmp: 1;
+ unsigned int is_unicodefull: 1;
+ unsigned int is_custom: 1;
+ unsigned int is_original: 1;
+ unsigned int is_compact: 1;
+ unsigned int is_japanese: 1;
+ unsigned int is_korean: 1;
+ unsigned int is_tradchinese: 1;
+ unsigned int is_simplechinese: 1;
+ char iso_2022_escape[8];
+ int iso_2022_escape_len;
+ int low_page, high_page;
+ char *iconv_name; /* For compatibility to old versions we might use a different name from that used by iconv. */
+ iconv_t *tounicode;
+ iconv_t *fromunicode;
+ int (*tounicode_func)(int);
+ int (*fromunicode_func)(int);
+ unsigned int is_temporary: 1; /* freed when the map gets freed */
+ int char_max; /* Used by temporary encodings */
+} Encoding;
+
+typedef struct namelist {
+ struct namelist *basedon;
+ char *title;
+ const char ***unicode[17];
+ struct namelist *next;
+ struct renames { char *from; char *to; } *renames;
+ int uses_unicode;
+ char *a_utf8_name;
+} NameList;
+
+enum uni_interp { ui_unset= -1, ui_none, ui_adobe, ui_greek, ui_japanese,
+ ui_trad_chinese, ui_simp_chinese, ui_korean, ui_ams };
+
+struct remap { uint32 firstenc, lastenc; int32 infont; };
+
+typedef struct encmap { /* A per-font map of encoding to glyph id */
+ int32 *map; /* Map from encoding to glyphid */
+ int32 *backmap; /* Map from glyphid to encoding */
+ int enccount; /* used size of the map array */
+ /* strictly speaking this might include */
+ /* glyphs that are not encoded, but which */
+ /* are displayed after the proper encoding */
+ int encmax; /* allocated size of the map array */
+ int backmax; /* allocated size of the backmap array */
+ struct remap *remap;
+ Encoding *enc;
+ unsigned int ticked: 1;
+} EncMap;
+
+enum property_type { prt_string, prt_atom, prt_int, prt_uint, prt_property=0x10 };
+
+typedef struct bdfprops {
+ char *name; /* These include both properties (like SLANT) and non-properties (like FONT) */
+ int type;
+ union {
+ char *str;
+ char *atom;
+ int val;
+ } u;
+} BDFProperties;
+
+typedef struct bdffont {
+ struct splinefont *sf;
+ int glyphcnt, glyphmax; /* used & allocated sizes of glyphs array */
+ BDFChar **glyphs; /* an array of charcnt entries */
+ int16 pixelsize;
+ int16 ascent, descent;
+ unsigned int piecemeal: 1;
+ unsigned int bbsized: 1;
+ unsigned int ticked: 1;
+ struct bdffont *next;
+ struct clut *clut;
+ char *foundry;
+ int res;
+ void *freetype_context;
+ uint16 truesize; /* for bbsized fonts */
+ int16 prop_cnt;
+ int16 prop_max; /* only used within bdfinfo dlg */
+ BDFProperties *props;
+} BDFFont;
+
+#define HntMax 96 /* PS says at most 96 hints */
+typedef uint8 HintMask[HntMax/8];
+
+enum pointtype { pt_curve, pt_corner, pt_tangent };
+typedef struct splinepoint {
+ BasePoint me;
+ BasePoint nextcp; /* control point */
+ BasePoint prevcp; /* control point */
+ unsigned int nonextcp:1;
+ unsigned int noprevcp:1;
+ unsigned int nextcpdef:1;
+ unsigned int prevcpdef:1;
+ unsigned int selected:1; /* for UI */
+ unsigned int pointtype:2;
+ unsigned int isintersection: 1;
+ unsigned int flexy: 1;
+ unsigned int flexx: 1;
+ unsigned int roundx: 1; /* For true type hinting */
+ unsigned int roundy: 1; /* For true type hinting */
+ unsigned int dontinterpolate: 1; /* in ttf, don't imply point by interpolating between cps */
+ unsigned int ticked: 1;
+ unsigned int watched: 1;
+ /* 1 bits left... */
+ uint16 ptindex; /* Temporary value used by metafont routine */
+ uint16 ttfindex; /* Truetype point index */
+ /* Special values 0xffff => point implied by averaging control points */
+ /* 0xfffe => point created with no real number yet */
+ /* (or perhaps point in context where no number is possible as in a glyph with points & refs) */
+ uint16 nextcpindex; /* Truetype point index */
+ struct spline *next;
+ struct spline *prev;
+ HintMask *hintmask;
+} SplinePoint;
+
+typedef struct linelist {
+ IPoint here;
+ struct linelist *next;
+ /* The first two fields are constant for the linelist, the next ones */
+ /* refer to a particular screen. If some portion of the line from */
+ /* this point to the next one is on the screen then set cvli_onscreen */
+ /* if this point needs to be clipped then set cvli_clipped */
+ /* asend and asstart are the actual screen locations where this point */
+ /* intersects the clip edge. */
+ enum { cvli_onscreen=0x1, cvli_clipped=0x2 } flags;
+ IPoint asend, asstart;
+} LineList;
+
+typedef struct linearapprox {
+ real scale;
+ unsigned int oneline: 1;
+ unsigned int onepoint: 1;
+ unsigned int any: 1; /* refers to a particular screen */
+ struct linelist *lines;
+ struct linearapprox *next;
+} LinearApprox;
+
+typedef struct spline1d {
+ real a, b, c, d;
+} Spline1D;
+
+typedef struct spline {
+ unsigned int islinear: 1; /* No control points */
+ unsigned int isquadratic: 1; /* probably read in from ttf */
+ unsigned int isticked: 1;
+ unsigned int isneeded: 1; /* Used in remove overlap */
+ unsigned int isunneeded: 1; /* Used in remove overlap */
+ unsigned int exclude: 1; /* Used in remove overlap varient: exclude */
+ unsigned int ishorvert: 1;
+ unsigned int knowncurved: 1; /* We know that it curves */
+ unsigned int knownlinear: 1; /* it might have control points, but still traces out a line */
+ /* If neither knownlinear nor curved then we haven't checked */
+ unsigned int order2: 1; /* It's a bezier curve with only one cp */
+ unsigned int touched: 1;
+ unsigned int leftedge: 1;
+ unsigned int rightedge: 1;
+ SplinePoint *from, *to;
+ Spline1D splines[2]; /* splines[0] is the x spline, splines[1] is y */
+ struct linearapprox *approx;
+ /* Posible optimizations:
+ Precalculate bounding box
+ Precalculate min/max/ points of inflection
+ */
+} Spline;
+
+typedef struct splinepointlist {
+ SplinePoint *first, *last;
+ struct splinepointlist *next;
+} SplinePointList, SplineSet;
+
+typedef struct imagelist {
+ struct gimage *image;
+ real xoff, yoff; /* position in character space of upper left corner of image */
+ real xscale, yscale; /* scale to convert one pixel of image to one unit of character space */
+ DBounds bb;
+ struct imagelist *next;
+ unsigned int selected: 1;
+} ImageList;
+
+typedef struct refchar {
+ unsigned int checked: 1;
+ unsigned int selected: 1;
+ unsigned int point_match: 1; /* match_pt* are point indexes */
+ /* and need to be converted to a */
+ /* translation after truetype readin */
+ unsigned int encoded: 1; /* orig_pos is actually an encoded value, used for old sfd files */
+ unsigned int justtranslated: 1; /* The transformation matrix specifies a translation (or is identity) */
+ unsigned int use_my_metrics: 1; /* Retain the ttf "use_my_metrics" info. */
+ /* important for glyphs with instructions which change the width used */
+ /* inside composites */
+ unsigned int round_translation_to_grid: 1; /* Retain the ttf "round_to_grid" info. */
+ unsigned int point_match_out_of_date: 1; /* Someone has edited a base glyph */
+ int16 adobe_enc;
+ int orig_pos;
+ int unicode_enc; /* used by paste */
+ real transform[6]; /* transformation matrix (first 2 rows of a 3x3 matrix, missing row is 0,0,1) */
+#ifdef FONTFORGE_CONFIG_TYPE3
+ struct reflayer {
+ struct brush fill_brush;
+ struct pen stroke_pen;
+ unsigned int dofill: 1;
+ unsigned int dostroke: 1;
+ unsigned int fillfirst: 1;
+ SplinePointList *splines;
+ ImageList *images;
+ } *layers;
+#else
+ struct reflayer {
+ SplinePointList *splines;
+ } layers[1];
+#endif
+ int layer_cnt;
+ struct refchar *next;
+ DBounds bb;
+ struct splinechar *sc;
+ BasePoint top;
+ uint16 match_pt_base, match_pt_ref;
+} RefChar;
+
+/* Some stems may appear, disappear, reapear several times */
+/* Serif stems on I which appear at 0, disappear, reappear at top */
+/* Or the major vertical stems on H which disappear at the cross bar */
+typedef struct hintinstance {
+ real begin; /* location in the non-major direction*/
+ real end; /* width/height in non-major direction*/
+ unsigned int closed: 1;
+ short int counternumber;
+ struct hintinstance *next;
+} HintInstance;
+
+enum hinttypes { ht_unspecified=0, ht_h, ht_v, ht_d };
+typedef real _MMArray[2][MmMax];
+
+typedef struct steminfo {
+ struct steminfo *next;
+ unsigned int hinttype: 2; /* Only used by undoes */
+ unsigned int ghost: 1; /* this is a ghost stem hint. As such truetype should ignore it, type2 output should negate it, and type1 should use as is */
+ /* stored width will be either 20 or 21 */
+ /* Type2 says: -20 is "width" of top edge, -21 is "width" of bottom edge, type1 accepts either */
+ unsigned int haspointleft:1;
+ unsigned int haspointright:1;
+ unsigned int hasconflicts:1;/* Does this stem have conflicts within its cluster? */
+ unsigned int used: 1; /* Temporary for counter hints or hint substitution */
+ unsigned int tobeused: 1; /* Temporary for counter hints or hint substitution */
+ unsigned int active: 1; /* Currently active hint in Review Hints dlg */
+ /* displayed differently in char display */
+ unsigned int enddone: 1; /* Used by ttf instructing, indicates a prev */
+ /* hint had the same end as this one (so */
+ /* the points on the end line have been */
+ /* instructed already */
+ unsigned int startdone: 1; /* Used by ttf instructing */
+ /*unsigned int backwards: 1;*/ /* If we think this hint is better done with a negative width */
+ unsigned int reordered: 1; /* In AutoHinting. Means we changed the start of the hint, need to test for out of order */
+ unsigned int pendingpt: 1; /* A pending stem creation, not a true stem */
+ unsigned int linearedges: 1;/* If we have a nice rectangle then we aren't */
+ /* interested in the orientation which is */
+ /* wider than long */
+ unsigned int bigsteminfo: 1;/* See following structure */
+ int16 hintnumber; /* when dumping out hintmasks we need to know */
+ /* what bit to set for this hint */
+ union {
+ int mask; /* Mask of all references that use this hint */
+ /* in type2 output */
+ _MMArray *unblended /*[2][MmMax]*/; /* Used when reading in type1 mm hints */
+ } u;
+ real start; /* location at which the stem starts */
+ real width; /* or height */
+ HintInstance *where; /* location(s) in the other coord */
+} StemInfo;
+
+typedef struct pointlist { struct pointlist *next; SplinePoint *sp; } PointList;
+typedef struct bigsteminfo {
+ StemInfo s;
+ PointList *left, *right;
+} BigStemInfo;
+
+typedef struct dsteminfo {
+ struct dsteminfo *next; /* First two fields match those in steminfo */
+ unsigned int hinttype: 2; /* Only used by undoes */
+ unsigned int used: 1; /* used only by tottf.c:gendinstrs, metafont.c to mark a hint that has been dealt with */
+ unsigned int bigsteminfo: 1;/* See following structure */
+ BasePoint leftedgetop, leftedgebottom, rightedgetop, rightedgebottom; /* this order is important in tottf.c: DStemInteresect */
+} DStemInfo;
+
+typedef struct bigdsteminfo {
+ DStemInfo s;
+ PointList *left, *right;
+} BigDStemInfo;
+
+typedef struct minimumdistance {
+ /* If either point is NULL it will be assumed to mean either the origin */
+ /* or the width point (depending on which is closer). This allows user */
+ /* to control metrics... */
+ SplinePoint *sp1, *sp2;
+ unsigned int x: 1;
+ unsigned int done: 1;
+ struct minimumdistance *next;
+} MinimumDistance;
+
+typedef struct layer /* : reflayer */{
+#ifdef FONTFORGE_CONFIG_TYPE3
+ struct brush fill_brush;
+ struct pen stroke_pen;
+ unsigned int dofill: 1;
+ unsigned int dostroke: 1;
+ unsigned int fillfirst: 1;
+#endif
+ SplinePointList *splines;
+ ImageList *images; /* Only in background or type3 layer(s) */
+ RefChar *refs; /* Only in foreground layer(s) */
+ Undoes *undoes;
+ Undoes *redoes;
+} Layer;
+
+enum layer_type { ly_grid= -1, ly_back=0, ly_fore=1 /* Possibly other foreground layers for multi-layered things */ };
+
+typedef struct splinechar {
+ char *name;
+ int unicodeenc;
+ int orig_pos; /* Original position in the glyph list */
+ int16 width, vwidth;
+#ifdef LUA_FF_LIB
+ int16 xmin, ymin, xmax, ymax;
+#endif
+ int16 lsidebearing; /* only used when reading in a type1 font */
+ /* Or an otf font where it is the subr number of a refered character */
+ /* or a ttf font with vert metrics where it is the ymax value */
+ /* or when generating morx where it is the mask of tables in which the glyph occurs */
+ /* Always a temporary value */
+ int ttf_glyph; /* only used when writing out a ttf or otf font */
+#ifdef FONTFORGE_CONFIG_TYPE3
+ Layer *layers; /* layer[0] is background, layer[1-n] foreground */
+#else
+ Layer layers[2]; /* layer[0] is background, layer[1] foreground */
+#endif
+ int layer_cnt;
+ StemInfo *hstem; /* hstem hints have a vertical offset but run horizontally */
+ StemInfo *vstem; /* vstem hints have a horizontal offset but run vertically */
+ DStemInfo *dstem; /* diagonal hints for ttf */
+ MinimumDistance *md;
+ struct charview *views;
+ struct charinfo *charinfo;
+ struct splinefont *parent;
+ unsigned int changed: 1;
+ unsigned int changedsincelasthinted: 1;
+ unsigned int manualhints: 1;
+ unsigned int ticked: 1; /* For reference character processing */
+ /* And fontview processing */
+ unsigned int changed_since_autosave: 1;
+ unsigned int widthset: 1; /* needed so an emspace char doesn't disappear */
+ unsigned int vconflicts: 1; /* Any hint overlaps in the vstem list? */
+ unsigned int hconflicts: 1; /* Any hint overlaps in the hstem list? */
+ unsigned int anyflexes: 1;
+ unsigned int searcherdummy: 1;
+ unsigned int changed_since_search: 1;
+ unsigned int wasopen: 1;
+ unsigned int namechanged: 1;
+ unsigned int blended: 1; /* An MM blended character */
+ unsigned int unused_so_far: 1;
+ unsigned int glyph_class: 3; /* 0=> fontforge determines class automagically, else one more than the class value in gdef */
+ unsigned int numberpointsbackards: 1;
+ unsigned int instructions_out_of_date: 1;
+ unsigned int complained_about_ptnums: 1;
+ /* 10 bits left (one more if we ignore compositionunit below) */
+#if HANYANG
+ unsigned int compositionunit: 1;
+ int16 jamo, varient;
+#endif
+ struct splinecharlist { struct splinechar *sc; struct splinecharlist *next;} *dependents;
+ /* The dependents list is a list of all characters which refenence*/
+ /* the current character directly */
+ KernPair *kerns;
+ KernPair *vkerns;
+ PST *possub; /* If we are a ligature then this tells us what */
+ /* It may also contain a bunch of other stuff now */
+ LigList *ligofme; /* If this is the first character of a ligature then this gives us the list of possible ones */
+ /* this field must be regenerated before the font is saved */
+ char *comment; /* in utf8 */
+ uint32 /*Color*/ color;
+ AnchorPoint *anchor;
+ uint8 *ttf_instrs;
+ int16 ttf_instrs_len;
+ int16 countermask_cnt;
+ HintMask *countermasks;
+ int16 tex_height, tex_depth;
+ int16 tex_sub_pos, tex_super_pos; /* Only for math fonts */
+ struct altuni { struct altuni *next; int unienc; } *altuni;
+#ifndef _NO_PYTHON
+ void *python_sc_object;
+ void *python_data;
+#endif
+} SplineChar;
+
+#define TEX_UNDEF 0x7fff
+
+enum ttfnames { ttf_copyright=0, ttf_family, ttf_subfamily, ttf_uniqueid,
+ ttf_fullname, ttf_version, ttf_postscriptname, ttf_trademark,
+ ttf_manufacturer, ttf_designer, ttf_descriptor, ttf_venderurl,
+ ttf_designerurl, ttf_license, ttf_licenseurl, ttf_idontknow/*reserved*/,
+ ttf_preffamilyname, ttf_prefmodifiers, ttf_compatfull, ttf_sampletext,
+ ttf_cidfindfontname, ttf_namemax };
+struct ttflangname {
+ int lang;
+ char *names[ttf_namemax]; /* in utf8 */
+ int frommac[(ttf_namemax+31)/32]; /* Used when parsing the 'name' table */
+ struct ttflangname *next;
+};
+
+enum backedup_state { bs_dontknow=0, bs_not=1, bs_backedup=2 };
+typedef struct splinefont {
+ char *fontname, *fullname, *familyname, *weight;
+ char *copyright;
+ char *filename; /* sfd name. NULL if we open a font, that's origname */
+ char *defbasefilename;
+ char *version;
+ real italicangle, upos, uwidth; /* In font info */
+#ifdef LUA_FF_LIB
+ int units_per_em;
+ struct splinefont *next;
+#endif
+ int ascent, descent;
+ int vertical_origin; /* height of vertical origin in character coordinate system */
+ int uniqueid; /* Not copied when reading in!!!! */
+ int glyphcnt, glyphmax; /* allocated size of glyphs array */
+ SplineChar **glyphs;
+ unsigned int changed: 1;
+ unsigned int changed_since_autosave: 1;
+ unsigned int changed_since_xuidchanged: 1;
+ unsigned int display_antialias: 1;
+ unsigned int display_bbsized: 1;
+ unsigned int dotlesswarn: 1; /* User warned that font doesn't have a dotless i character */
+ unsigned int onlybitmaps: 1; /* it's a bdf editor, not a postscript editor */
+ unsigned int serifcheck: 1; /* Have we checked to see if we have serifs? */
+ unsigned int issans: 1; /* We have no serifs */
+ unsigned int isserif: 1; /* We have serifs. If neither set then we don't know. */
+ unsigned int hasvmetrics: 1; /* We've got vertical metric data and should output vhea/vmtx/VORG tables */
+ unsigned int loading_cid_map: 1;
+ unsigned int dupnamewarn: 1; /* Warn about duplicate names when loading bdf font */
+ unsigned int encodingchanged: 1; /* Font's encoding has changed since it was loaded */
+ unsigned int order2: 1; /* Font's data are order 2 bezier splines (truetype) rather than order 3 (postscript) */
+ unsigned int multilayer: 1; /* only applies if TYPE3 is set, means this font can contain strokes & fills */
+ /* I leave it in so as to avoid cluttering up code with #ifdefs */
+ unsigned int strokedfont: 1;
+ unsigned int new: 1; /* A new and unsaved font */
+ unsigned int compacted: 1; /* only used when opening a font */
+ unsigned int backedup: 2; /* 0=>don't know, 1=>no, 2=>yes */
+ unsigned int use_typo_metrics: 1; /* The standard says to. But MS */
+ /* seems to feel that isn't good */
+ /* enough and has created a bit */
+ /* to mean "really use them" */
+ unsigned int weight_width_slope_only: 1; /* This bit seems stupid to me */
+ unsigned int save_to_dir: 1; /* Loaded from an sfdir collection rather than a simple sfd file */
+ unsigned int head_optimized_for_cleartype: 1;/* Bit in the 'head' flags field, if unset "East Asian fonts in the Windows Presentation Framework (Avalon) will not be hinted" */
+ unsigned int ticked: 1;
+ /* 6 bits left */
+ struct fontview *fv;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ struct metricsview *metrics;
+#else
+ void *metrics;
+#endif
+ enum uni_interp uni_interp;
+ NameList *for_new_glyphs;
+ EncMap *map; /* only used when opening a font to provide original default encoding */
+ Layer grid;
+ BDFFont *bitmaps;
+ char *origname; /* filename of font file (ie. if not an sfd) */
+ char *autosavename;
+ int display_size; /* a val <0 => Generate our own images from splines, a value >0 => find a bdf font of that size */
+ struct psdict *private; /* read in from type1 file or provided by user */
+ char *xuid;
+ struct pfminfo { /* A misnomer now. OS/2 info would be more accurate, but that's stuff in here from all over ttf files */
+ unsigned int pfmset: 1;
+ unsigned int winascent_add: 1;
+ unsigned int windescent_add: 1;
+ unsigned int hheadascent_add: 1;
+ unsigned int hheaddescent_add: 1;
+ unsigned int typoascent_add: 1;
+ unsigned int typodescent_add: 1;
+ unsigned int subsuper_set: 1;
+ unsigned int panose_set: 1;
+ unsigned int hheadset: 1;
+ unsigned int vheadset: 1;
+ unsigned char pfmfamily;
+ int16 weight;
+ int16 width;
+ char panose[10];
+ int16 fstype;
+ int16 linegap; /* from hhea */
+ int16 vlinegap; /* from vhea */
+ int16 hhead_ascent, hhead_descent;
+ int16 os2_typoascent, os2_typodescent, os2_typolinegap;
+ int16 os2_winascent, os2_windescent;
+ int16 os2_subxsize, os2_subysize, os2_subxoff, os2_subyoff;
+ int16 os2_supxsize, os2_supysize, os2_supxoff, os2_supyoff;
+ int16 os2_strikeysize, os2_strikeypos;
+ char os2_vendor[4];
+ int16 os2_family_class;
+#ifdef LUA_FF_LIB
+ uint16 avgwidth;
+ uint16 firstchar;
+ uint16 lastchar;
+ int16 os2_xheight;
+ int16 os2_capheight;
+ uint16 os2_defaultchar;
+ uint16 os2_breakchar;
+#endif
+ } pfminfo;
+ struct ttflangname *names;
+ char *cidregistry, *ordering;
+ int supplement;
+ int subfontcnt;
+ struct splinefont **subfonts;
+ struct splinefont *cidmaster; /* Top level cid font */
+ float cidversion;
+#if HANYANG
+ struct compositionrules *rules;
+#endif
+ char *comments;
+ int tempuniqueid;
+ int top_enc;
+ uint16 desired_row_cnt, desired_col_cnt;
+ struct glyphnamehash *glyphnames;
+ struct ttf_table {
+ uint32 tag;
+ int32 len, maxlen;
+ uint8 *data;
+ struct ttf_table *next;
+ FILE *temp; /* Temporary storage used during generation */
+ } *ttf_tables, *ttf_tab_saved;
+ /* We copy: fpgm, prep, cvt, maxp */
+ struct instrdata *instr_dlgs; /* Pointer to all table and character instruction dlgs in this font */
+ struct shortview *cvt_dlg;
+ struct kernclasslistdlg *kcld, *vkcld;
+ struct kernclassdlg *kcd;
+ struct texdata {
+ enum { tex_unset, tex_text, tex_math, tex_mathext } type;
+ int32 params[22]; /* param[6] has different meanings in normal and math fonts */
+ } texdata;
+ OTLookup *gsub_lookups, *gpos_lookups;
+ /* Apple morx subtables become gsub, and kern subtables become gpos */
+ AnchorClass *anchor;
+ KernClass *kerns, *vkerns;
+ FPST *possub;
+ ASM *sm; /* asm is a keyword */
+ MacFeat *features;
+ char *chosenname; /* Set for files with multiple fonts in them */
+ struct mmset *mm; /* If part of a multiple master set */
+ int16 macstyle;
+ char *fondname; /* For use in generating mac families */
+ /* from the GPOS 'size' feature. design_size, etc. are measured in tenths of a point */
+ /* bottom is exclusive, top is inclusive */
+ /* if any field is 0, it is undefined. All may be undefined, All may be */
+ /* defined, or design_size may be defined without any of the others */
+ /* but we can't define the range without defining the other junk */
+ /* Name must contain an English language name, may contain others */
+ uint16 design_size;
+ uint16 fontstyle_id;
+ struct otfname *fontstyle_name;
+ uint16 design_range_bottom, design_range_top;
+ real strokewidth;
+/* For GDEF Mark Attachment Class -- used in lookup flags */
+/* As usual, class 0 is unused */
+ int mark_class_cnt;
+ char **mark_classes; /* glyph name list */
+ char **mark_class_names; /* used within ff, utf8 (the name we've given to this class of marks) */
+#ifdef _HAS_LONGLONG
+ long long creationtime; /* seconds since 1970 */
+ long long modificationtime;
+#else
+ long creationtime;
+ long modificationtime;
+#endif
+ short os2_version; /* 0 means default rather than the real version 0 */
+ short compression; /* If we opened a compressed sfd file, then save it out compressed too */
+ short gasp_version; /* 0/1 currently */
+ short gasp_cnt;
+ struct gasp {
+ uint16 ppem;
+ uint16 flags;
+ } *gasp;
+ uint8 sfd_version; /* Used only when reading in an sfd file */
+ struct gfi_data *fontinfo;
+} SplineFont;
+
+/* I am going to simplify my life and not encourage intermediate designs */
+/* this means I can easily calculate ConvertDesignVector, and don't have */
+/* to bother the user with specifying it. */
+/* (NormalizeDesignVector is fairly basic and shouldn't need user help ever) */
+/* (As long as they want piecewise linear) */
+/* I'm not going to support intermediate designs at all for apple var tables */
+typedef struct mmset {
+ int axis_count;
+ char *axes[4];
+ int instance_count;
+ SplineFont **instances;
+ SplineFont *normal;
+ real *positions; /* array[instance][axis] saying where each instance lies on each axis */
+ real *defweights; /* array[instance] saying how much of each instance makes the normal font */
+ /* for adobe */
+ struct axismap {
+ int points; /* size of the next two arrays */
+ real *blends; /* between [0,1] ordered so that blend[0]<blend[1]<... */
+ real *designs; /* between the design ranges for this axis, typically [1,999] or [6,72] */
+ real min, def, max; /* For mac */
+ struct macname *axisnames; /* For mac */
+ } *axismaps; /* array[axis] */
+ char *cdv, *ndv; /* for adobe */
+ int named_instance_count;
+ struct named_instance { /* For mac */
+ real *coords; /* array[axis], these are in user units */
+ struct macname *names;
+ } *named_instances;
+ unsigned int changed: 1;
+ unsigned int apple: 1;
+} MMSet;
+
+/* mac styles. Useful idea we'll just steal it */
+enum style_flags { sf_bold = 1, sf_italic = 2, sf_underline = 4, sf_outline = 8,
+ sf_shadow = 0x10, sf_condense = 0x20, sf_extend = 0x40 };
+
+struct sflist {
+ SplineFont *sf;
+ int32 *sizes;
+ FILE *tempttf; /* For ttf */
+ int id; /* For ttf */
+ int* ids; /* One for each size */
+ BDFFont **bdfs; /* Ditto */
+ EncMap *map;
+ struct sflist *next;
+ char **former_names;
+};
+
+ /* Used for drawing text with mark to base anchors */
+typedef struct anchorpos {
+ SplineChar *sc; /* This is the mark being positioned */
+ int x,y; /* Its origin should be shifted this much relative to that of the original base char */
+ AnchorPoint *apm; /* The anchor point in sc used to position it */
+ AnchorPoint *apb; /* The anchor point in the base character against which we are positioned */
+ int base_index; /* Index in this array to the base character (-1=> original base char) */
+ unsigned int ticked: 1; /* Used as a mark to mark */
+} AnchorPos;
+
+enum ttf_flags { ttf_flag_shortps = 1, ttf_flag_nohints = 2,
+ ttf_flag_applemode=4,
+ ttf_flag_pfed_comments=8, ttf_flag_pfed_colors=0x10,
+ ttf_flag_otmode=0x20,
+ ttf_flag_glyphmap=0x40,
+ ttf_flag_TeXtable=0x80,
+ ttf_flag_ofm=0x100,
+ ttf_flag_oldkern=0x200, /* never set in conjunction with applemode */
+ ttf_flag_brokensize=0x400 /* Adobe originally issued fonts with a bug in the size feature. They now claim (Aug 2006) that this has been fixed. Legacy programs will do the wrong thing with the fixed feature though */
+ };
+enum openflags { of_fstypepermitted=1, of_askcmap=2 };
+enum ps_flags { ps_flag_nohintsubs = 0x10000, ps_flag_noflex=0x20000,
+ ps_flag_nohints = 0x40000, ps_flag_restrict256=0x80000,
+ ps_flag_afm = 0x100000, ps_flag_pfm = 0x200000,
+ ps_flag_tfm = 0x400000,
+ ps_flag_round = 0x800000,
+/* CFF fonts are wrapped up in some postscript sugar -- unless they are to */
+/* go into a pdf file or an otf font */
+ ps_flag_nocffsugar = 0x1000000,
+/* in type42 cid fonts we sometimes want an identity map from gid to cid */
+ ps_flag_identitycidmap = 0x2000000,
+ ps_flag_afmwithmarks = 0x4000000,
+ ps_flag_noseac = 0x8000000,
+ ps_flag_mask = (ps_flag_nohintsubs|ps_flag_noflex|
+ ps_flag_afm|ps_flag_pfm|ps_flag_tfm|ps_flag_round)
+ };
+
+struct compressors { char *ext, *decomp, *recomp; };
+
+struct fontdict;
+struct pschars;
+struct findsel;
+struct charprocs;
+struct enc;
+
+extern void *chunkalloc(int size);
+extern void chunkfree(void *, int size);
+
+extern char *strconcat(const char *str, const char *str2);
+extern char *strconcat3(const char *str, const char *str2, const char *str3);
+
+extern char *XUIDFromFD(int xuid[20]);
+extern SplineFont *SplineFontFromPSFont(struct fontdict *fd);
+extern int CheckAfmOfPostscript(SplineFont *sf,char *psname,EncMap *map);
+extern int LoadKerningDataFromAmfm(SplineFont *sf, char *filename, EncMap *map);
+extern int LoadKerningDataFromAfm(SplineFont *sf, char *filename, EncMap *map);
+extern int LoadKerningDataFromTfm(SplineFont *sf, char *filename, EncMap *map);
+extern int LoadKerningDataFromOfm(SplineFont *sf, char *filename, EncMap *map);
+extern int LoadKerningDataFromPfm(SplineFont *sf, char *filename, EncMap *map);
+extern int LoadKerningDataFromMacFOND(SplineFont *sf, char *filename, EncMap *map);
+extern int LoadKerningDataFromMetricsFile(SplineFont *sf, char *filename, EncMap *map);
+extern void FeatDumpFontLookups(FILE *out,SplineFont *sf);
+extern void FeatDumpOneLookup(FILE *out,SplineFont *sf, OTLookup *otl);
+extern void SFApplyFeatureFile(SplineFont *sf,FILE *file,char *filename);
+extern void SFApplyFeatureFilename(SplineFont *sf,char *filename);
+extern void SubsNew(SplineChar *to,enum possub_type type,int tag,char *components,
+ SplineChar *default_script);
+extern void PosNew(SplineChar *to,int tag,int dx, int dy, int dh, int dv);
+extern int SFOneWidth(SplineFont *sf);
+extern int CIDOneWidth(SplineFont *sf);
+extern int SFOneHeight(SplineFont *sf);
+extern int SFIsCJK(SplineFont *sf,EncMap *map);
+extern void CIDMasterAsDes(SplineFont *sf);
+enum fontformat { ff_pfa, ff_pfb, ff_pfbmacbin, ff_multiple, ff_mma, ff_mmb,
+ ff_ptype3, ff_ptype0, ff_cid, ff_cff, ff_cffcid,
+ ff_type42, ff_type42cid,
+ ff_ttf, ff_ttfsym, ff_ttfmacbin, ff_ttfdfont, ff_otf, ff_otfdfont,
+ ff_otfcid, ff_otfciddfont, ff_svg, ff_ufo, ff_none };
+extern struct pschars *SplineFont2ChrsSubrs(SplineFont *sf, int iscjk,
+ struct pschars *subrs,int flags,enum fontformat format);
+extern int CanonicalCombiner(int uni);
+struct cidbytes;
+struct fd2data;
+struct ttfinfo;
+struct alltabs;
+struct growbuf;
+struct glyphdata;
+extern int UnitsParallel(BasePoint *u1,BasePoint *u2);
+extern int CvtPsStem3(struct growbuf *gb, SplineChar *scs[MmMax], int instance_count,
+ int ishstem, int round);
+extern struct pschars *CID2ChrsSubrs(SplineFont *cidmaster,struct cidbytes *cidbytes,int flags);
+extern struct pschars *SplineFont2ChrsSubrs2(SplineFont *sf, int nomwid,
+ int defwid, const int *bygid, int cnt, int flags,
+ struct pschars **_subrs);
+extern struct pschars *CID2ChrsSubrs2(SplineFont *cidmaster,struct fd2data *fds,
+ int flags, struct pschars **_glbls);
+enum bitmapformat { bf_bdf, bf_ttf, bf_sfnt_dfont, bf_sfnt_ms, bf_otb,
+ bf_nfntmacbin, /*bf_nfntdfont, */bf_fon, bf_fnt, bf_palm,
+ bf_ptype3,
+ bf_none };
+extern const char *GetAuthor(void);
+extern SplineChar *SFFindExistingCharMac(SplineFont *,EncMap *map, int unienc);
+extern void SC_PSDump(void (*dumpchar)(int ch,void *data), void *data,
+ SplineChar *sc, int refs_to_splines, int pdfopers );
+extern int _WritePSFont(FILE *out,SplineFont *sf,enum fontformat format,int flags,EncMap *enc,SplineFont *fullsf);
+extern int WritePSFont(char *fontname,SplineFont *sf,enum fontformat format,int flags,EncMap *enc,SplineFont *fullsf);
+extern int WriteMacPSFont(char *fontname,SplineFont *sf,enum fontformat format,
+ int flags,EncMap *enc);
+extern int _WriteTTFFont(FILE *ttf,SplineFont *sf, enum fontformat format,
+ int32 *bsizes, enum bitmapformat bf,int flags,EncMap *enc);
+extern int WriteTTFFont(char *fontname,SplineFont *sf, enum fontformat format,
+ int32 *bsizes, enum bitmapformat bf,int flags,EncMap *enc);
+extern int _WriteType42SFNTS(FILE *type42,SplineFont *sf,enum fontformat format,
+ int flags,EncMap *enc);
+extern int WriteMacTTFFont(char *fontname,SplineFont *sf, enum fontformat format,
+ int32 *bsizes, enum bitmapformat bf,int flags,EncMap *enc);
+extern int WriteMacBitmaps(char *filename,SplineFont *sf, int32 *sizes,
+ int is_dfont,EncMap *enc);
+extern int WritePalmBitmaps(char *filename,SplineFont *sf, int32 *sizes,EncMap *enc);
+extern int WriteMacFamily(char *filename,struct sflist *sfs,enum fontformat format,
+ enum bitmapformat bf,int flags,EncMap *enc);
+extern long mactime(void);
+extern int WriteSVGFont(char *fontname,SplineFont *sf,enum fontformat format,int flags,EncMap *enc);
+extern int WriteUFOFont(char *fontname,SplineFont *sf,enum fontformat format,int flags,EncMap *enc);
+extern void SfListFree(struct sflist *sfs);
+extern void TTF_PSDupsDefault(SplineFont *sf);
+extern void DefaultTTFEnglishNames(struct ttflangname *dummy, SplineFont *sf);
+extern void TeXDefaultParams(SplineFont *sf);
+extern void OS2FigureCodePages(SplineFont *sf, uint32 CodePage[2]);
+extern void SFDefaultOS2Info(struct pfminfo *pfminfo,SplineFont *sf,char *fontname);
+extern void SFDefaultOS2Simple(struct pfminfo *pfminfo,SplineFont *sf);
+extern void SFDefaultOS2SubSuper(struct pfminfo *pfminfo,int emsize,double italicangle);
+extern void VerifyLanguages(SplineFont *sf);
+extern int ScriptIsRightToLeft(uint32 script);
+extern uint32 ScriptFromUnicode(int u,SplineFont *sf);
+extern uint32 SCScriptFromUnicode(SplineChar *sc);
+extern int SCRightToLeft(SplineChar *sc);
+extern int SLIContainsR2L(SplineFont *sf,int sli);
+extern void SFFindNearTop(SplineFont *);
+extern void SFRestoreNearTop(SplineFont *);
+extern int SFForceEncoding(SplineFont *sf,EncMap *old,Encoding *new_map);
+extern int CountOfEncoding(Encoding *encoding_name);
+extern void SFMatchGlyphs(SplineFont *sf,SplineFont *target,int addempties);
+extern void MMMatchGlyphs(MMSet *mm);
+extern char *_GetModifiers(char *fontname, char *familyname,char *weight);
+extern char *SFGetModifiers(SplineFont *sf);
+extern void SFSetFontName(SplineFont *sf, char *family, char *mods, char *full);
+extern void ttfdumpbitmap(SplineFont *sf,struct alltabs *at,int32 *sizes);
+extern void ttfdumpbitmapscaling(SplineFont *sf,struct alltabs *at,int32 *sizes);
+
+extern int RealNear(real a,real b);
+extern int RealNearish(real a,real b);
+extern int RealApprox(real a,real b);
+extern int RealWithin(real a,real b,real fudge);
+extern int RealRatio(real a,real b,real fudge);
+
+extern void LineListFree(LineList *ll);
+extern void LinearApproxFree(LinearApprox *la);
+extern void SplineFree(Spline *spline);
+extern SplinePoint *SplinePointCreate(real x, real y);
+extern void SplinePointFree(SplinePoint *sp);
+extern void SplinePointMDFree(SplineChar *sc,SplinePoint *sp);
+extern void SplinePointsFree(SplinePointList *spl);
+extern void SplinePointListFree(SplinePointList *spl);
+extern void SplinePointListMDFree(SplineChar *sc,SplinePointList *spl);
+extern void SplinePointListsMDFree(SplineChar *sc,SplinePointList *spl);
+extern void SplinePointListsFree(SplinePointList *head);
+extern void RefCharFree(RefChar *ref);
+extern void RefCharsFree(RefChar *ref);
+extern void RefCharsFreeRef(RefChar *ref);
+extern void CopyBufferFree(void);
+extern void CopyBufferClearCopiedFrom(SplineFont *dying);
+extern void UndoesFree(Undoes *undo);
+extern void StemInfosFree(StemInfo *h);
+extern void StemInfoFree(StemInfo *h);
+extern void DStemInfosFree(DStemInfo *h);
+extern void DStemInfoFree(DStemInfo *h);
+extern void KernPairsFree(KernPair *kp);
+extern void SCOrderAP(SplineChar *sc);
+extern void AnchorPointsFree(AnchorPoint *ap);
+extern AnchorPoint *AnchorPointsCopy(AnchorPoint *alist);
+extern void SFRemoveAnchorClass(SplineFont *sf,AnchorClass *an);
+extern int AnchorClassesNextMerge(AnchorClass *ac);
+extern int IsAnchorClassUsed(SplineChar *sc,AnchorClass *an);
+extern AnchorPoint *APAnchorClassMerge(AnchorPoint *anchors,AnchorClass *into,AnchorClass *from);
+extern void AnchorClassMerge(SplineFont *sf,AnchorClass *into,AnchorClass *from);
+extern void AnchorClassesFree(AnchorClass *kp);
+extern void TtfTablesFree(struct ttf_table *tab);
+extern AnchorClass *AnchorClassMatch(SplineChar *sc1,SplineChar *sc2,
+ AnchorClass *restrict_, AnchorPoint **_ap1,AnchorPoint **_ap2 );
+extern AnchorClass *AnchorClassMkMkMatch(SplineChar *sc1,SplineChar *sc2,
+ AnchorPoint **_ap1,AnchorPoint **_ap2 );
+extern AnchorClass *AnchorClassCursMatch(SplineChar *sc1,SplineChar *sc2,
+ AnchorPoint **_ap1,AnchorPoint **_ap2 );
+extern void SCInsertPST(SplineChar *sc,PST *new);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+extern void ValDevFree(ValDevTab *adjust);
+extern ValDevTab *ValDevTabCopy(ValDevTab *orig);
+extern void DeviceTableFree(DeviceTable *adjust);
+extern DeviceTable *DeviceTableCopy(DeviceTable *orig);
+extern void DeviceTableSet(DeviceTable *adjust, int size, int correction);
+#endif
+extern void PSTFree(PST *lig);
+extern uint16 PSTDefaultFlags(enum possub_type type,SplineChar *sc );
+extern int PSTContains(const char *components,const char *name);
+extern StemInfo *StemInfoCopy(StemInfo *h);
+extern DStemInfo *DStemInfoCopy(DStemInfo *h);
+extern MinimumDistance *MinimumDistanceCopy(MinimumDistance *h);
+struct sfmergecontext {
+ SplineFont *sf_from, *sf_to;
+ int lcnt;
+ struct lookup_cvt { OTLookup *from, *to; int old;} *lks;
+ int scnt;
+ struct sub_cvt { struct lookup_subtable *from, *to; int old;} *subs;
+ int acnt;
+ struct ac_cvt { AnchorClass *from, *to; int old;} *acs;
+ char *prefix;
+};
+extern PST *PSTCopy(PST *base,SplineChar *sc,struct sfmergecontext *mc);
+extern struct lookup_subtable *MCConvertSubtable(struct sfmergecontext *mc,struct lookup_subtable *sub);
+extern AnchorClass *MCConvertAnchorClass(struct sfmergecontext *mc,AnchorClass *ac);
+extern void SFFinishMergeContext(struct sfmergecontext *mc);
+extern SplineChar *SplineCharCopy(SplineChar *sc,SplineFont *into,struct sfmergecontext *);
+extern BDFChar *BDFCharCopy(BDFChar *bc);
+extern void BitmapsCopy(SplineFont *to, SplineFont *from, int to_index, int from_index );
+extern struct gimage *ImageAlterClut(struct gimage *image);
+extern void ImageListsFree(ImageList *imgs);
+extern void TTFLangNamesFree(struct ttflangname *l);
+extern void AltUniFree(struct altuni *altuni);
+extern void AltUniFigure(SplineFont *sf,EncMap *map);
+extern void AltUniRemove(SplineChar *sc,int uni);
+extern void AltUniAdd(SplineChar *sc,int uni);
+extern void MinimumDistancesFree(MinimumDistance *md);
+extern void LayerDefault(Layer *);
+extern SplineChar *SplineCharCreate(void);
+extern RefChar *RefCharCreate(void);
+extern void SCAddRef(SplineChar *sc,SplineChar *rsc,real xoff, real yoff);
+extern void _SCAddRef(SplineChar *sc,SplineChar *rsc,real transform[6]);
+extern KernClass *KernClassCopy(KernClass *kc);
+extern void KernClassFreeContents(KernClass *kc);
+extern void KernClassListFree(KernClass *kc);
+extern int KernClassContains(KernClass *kc, char *name1, char *name2, int ordered );
+extern void OTLookupFree(OTLookup *lookup);
+extern void OTLookupListFree(OTLookup *lookup );
+extern FPST *FPSTCopy(FPST *fpst);
+extern void FPSTFree(FPST *fpst);
+extern void ASMFree(ASM *sm);
+extern struct macname *MacNameCopy(struct macname *mn);
+extern void MacNameListFree(struct macname *mn);
+extern void MacSettingListFree(struct macsetting *ms);
+extern void MacFeatListFree(MacFeat *mf);
+extern void SplineCharListsFree(struct splinecharlist *dlist);
+extern void SplineCharFreeContents(SplineChar *sc);
+extern void SplineCharFree(SplineChar *sc);
+extern void EncMapFree(EncMap *map);
+extern EncMap *EncMapFromEncoding(SplineFont *sf,Encoding *enc);
+extern EncMap *CompactEncMap(EncMap *map, SplineFont *sf);
+extern EncMap *EncMapNew(int encmax, int backmax, Encoding *enc);
+extern EncMap *EncMap1to1(int enccount);
+extern EncMap *EncMapCopy(EncMap *map);
+extern void SFExpandGlyphCount(SplineFont *sf, int newcnt);
+extern void ScriptLangListFree(struct scriptlanglist *sl);
+extern void FeatureScriptLangListFree(FeatureScriptLangList *fl);
+extern void SplineFontFree(SplineFont *sf);
+extern void OtfNameListFree(struct otfname *on);
+extern void MarkClassFree(int cnt,char **classes,char **names);
+extern void MMSetFreeContents(MMSet *mm);
+extern void MMSetFree(MMSet *mm);
+extern void SFRemoveUndoes(SplineFont *sf,uint8 *selected,EncMap *map);
+extern void SplineRefigure3(Spline *spline);
+extern void SplineRefigure(Spline *spline);
+extern Spline *SplineMake3(SplinePoint *from, SplinePoint *to);
+extern LinearApprox *SplineApproximate(Spline *spline, real scale);
+extern int SplinePointListIsClockwise(const SplineSet *spl);
+extern void SplineSetFindBounds(const SplinePointList *spl, DBounds *bounds);
+extern void SplineCharFindBounds(SplineChar *sc,DBounds *bounds);
+extern void SplineFontFindBounds(SplineFont *sf,DBounds *bounds);
+extern void CIDFindBounds(SplineFont *sf,DBounds *bounds);
+extern void SplineSetQuickBounds(SplineSet *ss,DBounds *b);
+extern void SplineCharQuickBounds(SplineChar *sc, DBounds *b);
+extern void SplineSetQuickConservativeBounds(SplineSet *ss,DBounds *b);
+extern void SplineCharQuickConservativeBounds(SplineChar *sc, DBounds *b);
+extern void SplineFontQuickConservativeBounds(SplineFont *sf,DBounds *b);
+extern void SplinePointCatagorize(SplinePoint *sp);
+extern int SplinePointIsACorner(SplinePoint *sp);
+extern void SPLCatagorizePoints(SplinePointList *spl);
+extern void SCCatagorizePoints(SplineChar *sc);
+extern SplinePointList *SplinePointListCopy1(const SplinePointList *spl);
+extern SplinePointList *SplinePointListCopy(const SplinePointList *base);
+extern SplinePointList *SplinePointListCopySelected(SplinePointList *base);
+extern ImageList *ImageListCopy(ImageList *cimg);
+extern ImageList *ImageListTransform(ImageList *cimg,real transform[6]);
+extern void ApTransform(AnchorPoint *ap, real transform[6]);
+extern SplinePointList *SplinePointListTransform(SplinePointList *base, real transform[6], int allpoints );
+extern SplinePointList *SplinePointListShift(SplinePointList *base, real xoff, int allpoints );
+extern HintMask *HintMaskFromTransformedRef(RefChar *ref,BasePoint *trans,
+ SplineChar *basesc,HintMask *hm);
+extern SplinePointList *SPLCopyTranslatedHintMasks(SplinePointList *base,
+ SplineChar *basesc, SplineChar *subsc, BasePoint *trans);
+extern SplinePointList *SPLCopyTransformedHintMasks(RefChar *r,
+ SplineChar *basesc, BasePoint *trans);
+extern SplinePointList *SplinePointListRemoveSelected(SplineChar *sc,SplinePointList *base);
+extern void SplinePointListSet(SplinePointList *tobase, SplinePointList *frombase);
+extern void SplinePointListSelect(SplinePointList *spl,int sel);
+extern void SCRefToSplines(SplineChar *sc,RefChar *rf);
+extern void RefCharFindBounds(RefChar *rf);
+extern void SCReinstanciateRefChar(SplineChar *sc,RefChar *rf);
+extern void SCReinstanciateRef(SplineChar *sc,SplineChar *rsc);
+extern void SFReinstanciateRefs(SplineFont *sf);
+extern void SFInstanciateRefs(SplineFont *sf);
+extern SplineChar *MakeDupRef(SplineChar *base, int local_enc, int uni_enc);
+extern void SCRemoveDependent(SplineChar *dependent,RefChar *rf);
+extern void SCRemoveLayerDependents(SplineChar *dependent,int layer);
+extern void SCRemoveDependents(SplineChar *dependent);
+extern int SCDependsOnSC(SplineChar *parent, SplineChar *child);
+extern void BCCompressBitmap(BDFChar *bdfc);
+extern void BCRegularizeBitmap(BDFChar *bdfc);
+extern void BCRegularizeGreymap(BDFChar *bdfc);
+extern void BCPasteInto(BDFChar *bc,BDFChar *rbc,int ixoff,int iyoff, int invert, int cleartoo);
+extern void BCRotateCharForVert(BDFChar *bc,BDFChar *from, BDFFont *frombdf);
+extern BDFChar *SplineCharRasterize(SplineChar *sc, double pixelsize);
+extern BDFFont *SplineFontToBDFHeader(SplineFont *_sf, int pixelsize, int indicate);
+extern BDFFont *SplineFontRasterize(SplineFont *sf, int pixelsize, int indicate);
+extern void BDFCAntiAlias(BDFChar *bc, int linear_scale);
+extern BDFChar *SplineCharAntiAlias(SplineChar *sc, int pixelsize,int linear_scale);
+extern BDFFont *SplineFontAntiAlias(SplineFont *sf, int pixelsize,int linear_scale);
+extern struct clut *_BDFClut(int linear_scale);
+extern void BDFClut(BDFFont *bdf, int linear_scale);
+extern int BDFDepth(BDFFont *bdf);
+extern BDFChar *BDFPieceMeal(BDFFont *bdf, int index);
+enum piecemeal_flags { pf_antialias=1, pf_bbsized=2 };
+extern BDFFont *SplineFontPieceMeal(SplineFont *sf,int pixelsize,int flags,void *freetype_context);
+extern void BDFCharFindBounds(BDFChar *bc,IBounds *bb);
+extern BDFFont *BitmapFontScaleTo(BDFFont *old, int to);
+extern void BDFCharFree(BDFChar *bdfc);
+extern void BDFPropsFree(BDFFont *bdf);
+extern void BDFFontFree(BDFFont *bdf);
+extern void SFDefaultAscent(SplineFont *sf);
+extern int PSBitmapDump(char *filename,BDFFont *font, EncMap *map);
+extern int BDFFontDump(char *filename,BDFFont *font, EncMap *map, int res);
+extern int FNTFontDump(char *filename,BDFFont *font, EncMap *map, int res);
+extern int FONFontDump(char *filename,SplineFont *sf, int32 *sizes,int res,
+ EncMap *map);
+extern void SFReplaceEncodingBDFProps(SplineFont *sf,EncMap *map);
+extern void SFReplaceFontnameBDFProps(SplineFont *sf);
+extern int IsUnsignedBDFKey(char *key);
+extern int BdfPropHasInt(BDFFont *font,const char *key, int def );
+extern void BDFDefaultProps(BDFFont *bdf, EncMap *map, int res);
+struct xlfd_components {
+ char foundry[80];
+ char family[100];
+ char weight[80];
+ char slant[40];
+ char setwidth[50];
+ char add_style[50];
+ int pixel_size;
+ int point_size;
+ int res_x;
+ int res_y;
+ char spacing[40];
+ int avg_width;
+ char cs_reg[80]; /* encoding */
+ char cs_enc[80]; /* encoding version? */
+ int char_cnt;
+};
+extern void XLFD_GetComponents(char *xlfd,struct xlfd_components *comp);
+extern void XLFD_CreateComponents(BDFFont *bdf,EncMap *map,int res,struct xlfd_components *comp);
+/* Two lines intersect in at most 1 point */
+/* Two quadratics intersect in at most 4 points */
+/* Two cubics intersect in at most 9 points */ /* Plus an extra space for a trailing -1 */
+extern int SplinesIntersect(const Spline *s1, const Spline *s2, BasePoint pts[9],
+ extended t1s[10], extended t2s[10]);
+extern SplineSet *LayerAllSplines(Layer *layer);
+extern SplineSet *LayerUnAllSplines(Layer *layer);
+extern int SplineSetIntersect(SplineSet *spl, Spline **_spline, Spline **_spline2 );
+extern int LineTangentToSplineThroughPt(Spline *s, BasePoint *pt, extended ts[4],
+ extended tmin, extended tmax);
+extern int CubicSolve(const Spline1D *sp,extended ts[3]);
+extern extended IterateSplineSolve(const Spline1D *sp, extended tmin, extended tmax, extended sought_y, double err);
+extern extended SplineSolve(const Spline1D *sp, real tmin, real tmax, extended sought_y, real err);
+extern int SplineSolveFull(const Spline1D *sp,extended val, extended ts[3]);
+extern void SplineFindExtrema(const Spline1D *sp, extended *_t1, extended *_t2 );
+
+#define CURVATURE_ERROR -1e9
+extern double SplineCurvature(Spline *s, double t);
+
+#ifndef EXTENDED_IS_LONG_DOUBLE
+extern double CheckExtremaForSingleBitErrors(const Spline1D *sp, double t);
+#define esqrt(d) sqrt(d)
+#else
+extern extended esqrt(extended e);
+#endif
+extern int Spline2DFindExtrema(const Spline *sp, extended extrema[4] );
+extern int Spline2DFindPointsOfInflection(const Spline *sp, extended poi[2] );
+extern int SplineAtInflection(Spline1D *sp, double t );
+extern int SplineAtMinMax(Spline1D *sp, double t );
+extern void SplineRemoveExtremaTooClose(Spline1D *sp, extended *_t1, extended *_t2 );
+extern int NearSpline(struct findsel *fs, Spline *spline);
+extern real SplineNearPoint(Spline *spline, BasePoint *bp, real fudge);
+extern void SCMakeDependent(SplineChar *dependent,SplineChar *base);
+extern SplinePoint *SplineBisect(Spline *spline, extended t);
+extern Spline *SplineSplit(Spline *spline, extended ts[3]);
+extern Spline *ApproximateSplineFromPoints(SplinePoint *from, SplinePoint *to,
+ TPoint *mid, int cnt,int order2);
+extern Spline *ApproximateSplineFromPointsSlopes(SplinePoint *from, SplinePoint *to,
+ TPoint *mid, int cnt,int order2);
+extern double SplineLength(Spline *spline);
+extern int SplineIsLinear(Spline *spline);
+extern int SplineIsLinearMake(Spline *spline);
+extern int SplineInSplineSet(Spline *spline, SplineSet *spl);
+extern int SSPointWithin(SplineSet *spl,BasePoint *pt);
+extern SplineSet *SSRemoveZeroLengthSplines(SplineSet *base);
+extern void SSRemoveStupidControlPoints(SplineSet *base);
+extern void SSOverlapClusterCpAngles(SplineSet *base,double within);
+extern void SplinesRemoveBetween(SplineChar *sc, SplinePoint *from, SplinePoint *to,int type);
+extern void SplineCharMerge(SplineChar *sc,SplineSet **head,int type);
+extern void SPLNearlyHvCps(SplineChar *sc,SplineSet *ss,double err);
+extern void SPLNearlyHvLines(SplineChar *sc,SplineSet *ss,double err);
+extern int SPLNearlyLines(SplineChar *sc,SplineSet *ss,double err);
+extern int SPInterpolate(SplinePoint *sp);
+extern void SplinePointListSimplify(SplineChar *sc,SplinePointList *spl,
+ struct simplifyinfo *smpl);
+extern SplineSet *SplineCharSimplify(SplineChar *sc,SplineSet *head,
+ struct simplifyinfo *smpl);
+extern void SPLStartToLeftmost(SplineChar *sc,SplinePointList *spl, int *changed);
+extern void SPLsStartToLeftmost(SplineChar *sc);
+extern void CanonicalContours(SplineChar *sc);
+extern SplineSet *SplineSetJoin(SplineSet *start,int doall,real fudge,int *changed);
+enum ae_type { ae_all, ae_between_selected, ae_only_good, ae_only_good_rm_later };
+extern Spline *SplineAddExtrema(Spline *s,int always,real lenbound,
+ real offsetbound,DBounds *b);
+extern void SplineSetAddExtrema(SplineChar *sc,SplineSet *ss,enum ae_type between_selected, int emsize);
+extern void SplineCharAddExtrema(SplineChar *sc,SplineSet *head,enum ae_type between_selected,int emsize);
+extern SplineSet *SplineCharRemoveTiny(SplineChar *sc,SplineSet *head);
+extern SplineFont *SplineFontNew(void);
+extern char *GetNextUntitledName(void);
+extern SplineFont *SplineFontEmpty(void);
+extern SplineFont *SplineFontBlank(int charcnt);
+extern void SFIncrementXUID(SplineFont *sf);
+extern void SFRandomChangeXUID(SplineFont *sf);
+extern SplineSet *SplineSetReverse(SplineSet *spl);
+extern SplineSet *SplineSetsExtractOpen(SplineSet **tbase);
+extern void SplineSetsInsertOpen(SplineSet **tbase,SplineSet *open);
+extern SplineSet *SplineSetsCorrect(SplineSet *base,int *changed);
+extern SplineSet *SplineSetsAntiCorrect(SplineSet *base);
+extern SplineSet *SplineSetsDetectDir(SplineSet **_base, int *lastscan);
+extern void SPAverageCps(SplinePoint *sp);
+extern void SPLAverageCps(SplinePointList *spl);
+extern void SPWeightedAverageCps(SplinePoint *sp);
+extern void SplineCharDefaultPrevCP(SplinePoint *base);
+extern void SplineCharDefaultNextCP(SplinePoint *base);
+extern void SplineCharTangentNextCP(SplinePoint *sp);
+extern void SplineCharTangentPrevCP(SplinePoint *sp);
+extern void SPSmoothJoint(SplinePoint *sp);
+extern int PointListIsSelected(SplinePointList *spl);
+extern void SplineSetsUntick(SplineSet *spl);
+extern void SFOrderBitmapList(SplineFont *sf);
+extern int KernThreshold(SplineFont *sf, int cnt);
+extern real SFGuessItalicAngle(SplineFont *sf);
+extern void SFHasSerifs(SplineFont *sf);
+
+extern SplinePoint *SplineTtfApprox(Spline *ps);
+extern SplineSet *SSttfApprox(SplineSet *ss);
+extern SplineSet *SplineSetsTTFApprox(SplineSet *ss);
+extern SplineSet *SSPSApprox(SplineSet *ss);
+extern SplineSet *SplineSetsPSApprox(SplineSet *ss);
+extern SplineSet *SplineSetsConvertOrder(SplineSet *ss, int to_order2);
+extern void SplineRefigure2(Spline *spline);
+extern void SplineRefigureFixup(Spline *spline);
+extern Spline *SplineMake2(SplinePoint *from, SplinePoint *to);
+extern Spline *SplineMake(SplinePoint *from, SplinePoint *to, int order2);
+extern Spline *SFSplineMake(SplineFont *sf,SplinePoint *from, SplinePoint *to);
+extern void SCConvertToOrder2(SplineChar *sc);
+extern void SFConvertToOrder2(SplineFont *sf);
+extern void SCConvertToOrder3(SplineChar *sc);
+extern void SFConvertToOrder3(SplineFont *sf);
+extern void SCConvertOrder(SplineChar *sc, int to_order2);
+extern void SplinePointPrevCPChanged2(SplinePoint *sp);
+extern void SplinePointNextCPChanged2(SplinePoint *sp);
+extern int IntersectLines(BasePoint *inter,
+ BasePoint *line1_1, BasePoint *line1_2,
+ BasePoint *line2_1, BasePoint *line2_2);
+extern int IntersectLinesClip(BasePoint *inter,
+ BasePoint *line1_1, BasePoint *line1_2,
+ BasePoint *line2_1, BasePoint *line2_2);
+
+#if 0
+extern void SSBisectTurners(SplineSet *spl);
+#endif
+extern void SSRemoveBacktracks(SplineSet *ss);
+extern SplineSet *SplineSetStroke(SplineSet *spl,StrokeInfo *si,SplineChar *sc);
+extern SplineSet *SSStroke(SplineSet *spl,StrokeInfo *si,SplineChar *sc);
+extern SplineSet *SplineSetRemoveOverlap(SplineChar *sc,SplineSet *base,enum overlap_type);
+
+extern double BlueScaleFigure(struct psdict *private,real bluevalues[], real otherblues[]);
+extern void FindBlues( SplineFont *sf, real blues[14], real otherblues[10]);
+extern void QuickBlues(SplineFont *sf, BlueData *bd);
+extern void FindHStems( SplineFont *sf, real snaps[12], real cnt[12]);
+extern void FindVStems( SplineFont *sf, real snaps[12], real cnt[12]);
+extern int SplineCharIsFlexible(SplineChar *sc);
+extern void SCGuessHHintInstancesAndAdd(SplineChar *sc, StemInfo *stem, real guess1, real guess2);
+extern void SCGuessVHintInstancesAndAdd(SplineChar *sc, StemInfo *stem, real guess1, real guess2);
+extern void SCGuessHHintInstancesList(SplineChar *sc);
+extern void SCGuessVHintInstancesList(SplineChar *sc);
+extern real HIlen( StemInfo *stems);
+extern real HIoverlap( HintInstance *mhi, HintInstance *thi);
+extern int StemInfoAnyOverlaps(StemInfo *stems);
+extern int StemListAnyConflicts(StemInfo *stems);
+extern HintInstance *HICopyTrans(HintInstance *hi, real mul, real offset);
+extern void MDAdd(SplineChar *sc, int x, SplinePoint *sp1, SplinePoint *sp2);
+extern int SFNeedsAutoHint( SplineFont *_sf);
+extern void SCAutoInstr( SplineChar *sc,BlueData *bd );
+extern void CVT_ImportPrivate(SplineFont *sf);
+extern void SCModifyHintMasksAdd(SplineChar *sc,StemInfo *new);
+extern void SCClearHints(SplineChar *sc);
+extern void SCClearHintMasks(SplineChar *sc,int counterstoo);
+extern void SCFigureVerticalCounterMasks(SplineChar *sc);
+extern void SCFigureCounterMasks(SplineChar *sc);
+extern void SCFigureHintMasks(SplineChar *sc);
+extern void _SplineCharAutoHint( SplineChar *sc, BlueData *bd, struct glyphdata *gd2 );
+extern void SplineCharAutoHint( SplineChar *sc,BlueData *bd);
+extern void SFSCAutoHint( SplineChar *sc,BlueData *bd);
+extern void SplineFontAutoHint( SplineFont *sf);
+extern void SplineFontAutoHintRefs( SplineFont *sf);
+extern StemInfo *HintCleanup(StemInfo *stem,int dosort,int instance_count);
+extern int SplineFontIsFlexible(SplineFont *sf,int flags);
+extern int SCDrawsSomething(SplineChar *sc);
+extern int SCWorthOutputting(SplineChar *sc);
+extern int SFFindNotdef(SplineFont *sf, int fixed);
+extern int IsntBDFChar(BDFChar *bdfc);
+extern int CIDWorthOutputting(SplineFont *cidmaster, int enc); /* Returns -1 on failure, font number on success */
+extern int AmfmSplineFont(FILE *afm, MMSet *mm,int formattype,EncMap *map);
+extern int AfmSplineFont(FILE *afm, SplineFont *sf,int formattype,EncMap *map, int docc, SplineFont *fullsf);
+extern int PfmSplineFont(FILE *pfm, SplineFont *sf,int type0,EncMap *map);
+extern int TfmSplineFont(FILE *afm, SplineFont *sf,int formattype,EncMap *map);
+extern int OfmSplineFont(FILE *afm, SplineFont *sf,int formattype,EncMap *map);
+extern char *EncodingName(Encoding *map);
+extern char *SFEncodingName(SplineFont *sf,EncMap *map);
+extern void SFLigaturePrepare(SplineFont *sf);
+extern void SFLigatureCleanup(SplineFont *sf);
+extern void SFKernClassTempDecompose(SplineFont *sf,int isv);
+extern void SFKernCleanup(SplineFont *sf,int isv);
+extern int SCSetMetaData(SplineChar *sc,char *name,int unienc,
+ const char *comment);
+
+extern enum uni_interp interp_from_encoding(Encoding *enc,enum uni_interp interp);
+extern const char *EncName(Encoding *encname);
+extern const char*FindUnicharName(void);
+extern Encoding *_FindOrMakeEncoding(const char *name,int make_it);
+extern Encoding *FindOrMakeEncoding(const char *name);
+extern void SFDDumpMacFeat(FILE *sfd,MacFeat *mf);
+extern MacFeat *SFDParseMacFeatures(FILE *sfd, char *tok);
+extern int SFDWrite(char *filename,SplineFont *sf,EncMap *map,EncMap *normal, int todir);
+extern int SFDWriteBak(SplineFont *sf,EncMap *map,EncMap *normal);
+extern SplineFont *SFDRead(char *filename);
+extern SplineFont *SFDirRead(char *filename);
+extern SplineChar *SFDReadOneChar(SplineFont *sf,const char *name);
+extern char *TTFGetFontName(FILE *ttf,int32 offset,int32 off2);
+extern void TTFLoadBitmaps(FILE *ttf,struct ttfinfo *info, int onlyone);
+enum ttfflags { ttf_onlystrikes=1, ttf_onlyonestrike=2, ttf_onlykerns=4, ttf_onlynames=8 };
+extern SplineFont *_SFReadTTF(FILE *ttf,int flags,enum openflags openflags,
+ char *filename,struct fontdict *fd);
+extern SplineFont *SFReadTTF(char *filename,int flags,enum openflags openflags);
+extern SplineFont *SFReadSVG(char *filename,int flags);
+extern SplineFont *SFReadUFO(char *filename,int flags);
+extern SplineFont *_CFFParse(FILE *temp,int len,char *fontsetname);
+extern SplineFont *CFFParse(char *filename);
+extern SplineFont *SFReadMacBinary(char *filename,int flags,enum openflags openflags);
+extern SplineFont *SFReadWinFON(char *filename,int toback);
+extern SplineFont *SFReadPalmPdb(char *filename,int toback);
+extern SplineFont *LoadSplineFont(char *filename,enum openflags);
+extern SplineFont *ReadSplineFont(char *filename,enum openflags); /* Don't use this, use LoadSF instead */
+extern SplineFont *SFFromBDF(char *filename,int ispk,int toback);
+extern SplineFont *SFFromMF(char *filename);
+extern void SFCheckPSBitmap(SplineFont *sf);
+extern uint16 _MacStyleCode( char *styles, SplineFont *sf, uint16 *psstyle );
+extern uint16 MacStyleCode( SplineFont *sf, uint16 *psstyle );
+extern SplineFont *SFReadIkarus(char *fontname);
+extern SplineFont *_SFReadPdfFont(FILE *ttf,char *filename,char *select_this_font, enum openflags openflags);
+extern SplineFont *SFReadPdfFont(char *filename, enum openflags openflags);
+extern char **GetFontNames(char *filename);
+extern char **NamesReadSFD(char *filename);
+extern char **NamesReadTTF(char *filename);
+extern char **NamesReadCFF(char *filename);
+extern char **NamesReadPostscript(char *filename);
+extern char **_NamesReadPostscript(FILE *ps);
+extern char **NamesReadSVG(char *filename);
+extern char **NamesReadUFO(char *filename);
+extern char **NamesReadMacBinary(char *filename);
+
+extern void SFSetOrder(SplineFont *sf,int order2);
+extern int SFFindOrder(SplineFont *sf);
+
+extern const char *UnicodeRange(int unienc);
+extern SplineChar *SCBuildDummy(SplineChar *dummy,SplineFont *sf,EncMap *map,int i);
+extern SplineChar *SFMakeChar(SplineFont *sf,EncMap *map,int i);
+extern char *AdobeLigatureFormat(char *name);
+extern uint32 LigTagFromUnicode(int uni);
+extern void SCLigCaretCheck(SplineChar *sc,int clean);
+extern BDFChar *BDFMakeGID(BDFFont *bdf,int gid);
+extern BDFChar *BDFMakeChar(BDFFont *bdf,EncMap *map,int enc);
+
+extern void SCUndoSetLBearingChange(SplineChar *sc,int lb);
+extern Undoes *SCPreserveHints(SplineChar *sc);
+extern Undoes *SCPreserveLayer(SplineChar *sc,int layer,int dohints);
+extern Undoes *SCPreserveState(SplineChar *sc,int dohints);
+extern Undoes *SCPreserveBackground(SplineChar *sc);
+extern Undoes *SFPreserveGuide(SplineFont *sf);
+extern Undoes *SCPreserveWidth(SplineChar *sc);
+extern Undoes *SCPreserveVWidth(SplineChar *sc);
+extern Undoes *BCPreserveState(BDFChar *bc);
+extern void BCDoRedo(BDFChar *bc,struct fontview *fv);
+extern void BCDoUndo(BDFChar *bc,struct fontview *fv);
+
+extern int SFIsCompositBuildable(SplineFont *sf,int unicodeenc,SplineChar *sc);
+extern int SFIsSomethingBuildable(SplineFont *sf,SplineChar *sc,int onlyaccents);
+extern int SFIsRotatable(SplineFont *sf,SplineChar *sc);
+extern int SCMakeDotless(SplineFont *sf, SplineChar *dotless, int copybmp, int doit);
+extern void SCBuildComposit(SplineFont *sf, SplineChar *sc, int copybmp,
+ struct fontview *fv);
+extern int SCAppendAccent(SplineChar *sc,char *glyph_name,int uni,int pos);
+#ifdef FONTFORGE_CONFIG_GTK
+extern const char *SFGetAlternate(SplineFont *sf, int base,SplineChar *sc,int nocheck);
+#else
+extern const unichar_t *SFGetAlternate(SplineFont *sf, int base,SplineChar *sc,int nocheck);
+#endif
+
+extern int getAdobeEnc(char *name);
+
+extern void SFSplinesFromLayers(SplineFont *sf,int tostroke);
+extern void SFSetLayerWidthsStroked(SplineFont *sf, real strokewidth);
+extern SplineSet *SplinePointListInterpretSVG(char *filename,char *memory, int memlen, int em_size, int ascent,int stroked);
+extern SplineSet *SplinePointListInterpretGlif(char *filename,char *memory, int memlen, int em_size, int ascent,int stroked);
+extern SplinePointList *SplinePointListInterpretPS(FILE *ps,int flags,int stroked);
+extern void PSFontInterpretPS(FILE *ps,struct charprocs *cp,char **encoding);
+extern struct enc *PSSlurpEncodings(FILE *file);
+extern int EvaluatePS(char *str,real *stack,int size);
+struct pscontext {
+ int is_type2;
+ int painttype;
+ int instance_count;
+ real blend_values[17];
+ int blend_warn;
+};
+extern int UnblendedCompare(real u1[MmMax], real u2[MmMax], int cnt);
+extern SplineChar *PSCharStringToSplines(uint8 *type1, int len, struct pscontext *context,
+ struct pschars *subrs, struct pschars *gsubrs, const char *name);
+extern void MatMultiply(real m1[6], real m2[6], real to[6]);
+
+extern int NameToEncoding(SplineFont *sf,EncMap *map,const char *uname);
+extern void GlyphHashFree(SplineFont *sf);
+extern void SFHashGlyph(SplineFont *sf,SplineChar *sc);
+extern int SFFindGID(SplineFont *sf, int unienc, const char *name );
+extern int SFFindSlot(SplineFont *sf, EncMap *map, int unienc, const char *name );
+extern int SFCIDFindCID(SplineFont *sf, int unienc, const char *name );
+extern SplineChar *SFGetChar(SplineFont *sf, int unienc, const char *name );
+extern int SFHasChar(SplineFont *sf, int unienc, const char *name );
+extern SplineChar *SFGetOrMakeChar(SplineFont *sf, int unienc, const char *name );
+extern int SFFindExistingSlot(SplineFont *sf, int unienc, const char *name );
+extern int SFCIDFindExistingChar(SplineFont *sf, int unienc, const char *name );
+extern int SFHasCID(SplineFont *sf, int cid);
+
+extern char *getPfaEditDir(char *buffer);
+extern void DoAutoSaves(void);
+extern void CleanAutoRecovery(void);
+extern int DoAutoRecovery(void);
+extern SplineFont *SFRecoverFile(char *autosavename);
+extern void SFAutoSave(SplineFont *sf,EncMap *map);
+extern void SFClearAutoSave(SplineFont *sf);
+
+extern void PSCharsFree(struct pschars *chrs);
+extern void PSDictFree(struct psdict *chrs);
+extern struct psdict *PSDictCopy(struct psdict *dict);
+extern int PSDictFindEntry(struct psdict *dict, char *key);
+extern char *PSDictHasEntry(struct psdict *dict, char *key);
+extern int PSDictRemoveEntry(struct psdict *dict, char *key);
+extern int PSDictChangeEntry(struct psdict *dict, char *key, char *newval);
+
+extern void SplineSetsRound2Int(SplineSet *spl,real factor);
+extern void SCRound2Int(SplineChar *sc,real factor);
+extern int SCRoundToCluster(SplineChar *sc,int layer,int sel,double within,double max);
+extern int SplineSetsRemoveAnnoyingExtrema(SplineSet *ss,double err);
+extern int hascomposing(SplineFont *sf,int u,SplineChar *sc);
+#if 0
+extern void SFFigureGrid(SplineFont *sf);
+#endif
+extern int FVWinInfo(struct fontview *,int *cc,int *rc);
+
+struct cidmap; /* private structure to encoding.c */
+extern int CIDFromName(char *name,SplineFont *cidmaster);
+extern int CID2Uni(struct cidmap *map,int cid);
+extern int CID2NameUni(struct cidmap *map,int cid, char *buffer, int len);
+extern int NameUni2CID(struct cidmap *map,int uni, const char *name);
+extern int MaxCID(struct cidmap *map);
+extern struct cidmap *LoadMapFromFile(char *file,char *registry,char *ordering,
+ int supplement);
+extern struct cidmap *FindCidMap(char *registry,char *ordering,int supplement,
+ SplineFont *sf);
+extern void SFEncodeToMap(SplineFont *sf,struct cidmap *map);
+extern struct cidmap *AskUserForCIDMap(SplineFont *sf);
+extern SplineFont *CIDFlatten(SplineFont *cidmaster,SplineChar **chars,int charcnt);
+extern void SFFlatten(SplineFont *cidmaster);
+extern int SFFlattenByCMap(SplineFont *sf,char *cmapname);
+extern SplineFont *MakeCIDMaster(SplineFont *sf,EncMap *oldmap,int bycmap,char *cmapfilename,struct cidmap *cidmap);
+
+int getushort(FILE *ttf);
+int32 getlong(FILE *ttf);
+int get3byte(FILE *ttf);
+real getfixed(FILE *ttf);
+real get2dot14(FILE *ttf);
+void putshort(FILE *file,int sval);
+void putlong(FILE *file,int val);
+void putfixed(FILE *file,real dval);
+int ttfcopyfile(FILE *ttf, FILE *other, int pos, char *table_name);
+
+extern void SCCopyFgToBg(SplineChar *sc,int show);
+extern void SCCopyBgToFg(SplineChar *sc,int show);
+
+extern int hasFreeType(void);
+extern int hasFreeTypeDebugger(void);
+extern int hasFreeTypeByteCode(void);
+extern int FreeTypeAtLeast(int major, int minor, int patch);
+extern void doneFreeType(void);
+extern void *_FreeTypeFontContext(SplineFont *sf,SplineChar *sc,struct fontview *fv,
+ enum fontformat ff,int flags,void *shared_ftc);
+extern void *FreeTypeFontContext(SplineFont *sf,SplineChar *sc,struct fontview *fv);
+extern BDFFont *SplineFontFreeTypeRasterize(void *freetypecontext,int pixelsize,int depth);
+extern BDFChar *SplineCharFreeTypeRasterize(void *freetypecontext,int gid,
+ int pixelsize,int depth);
+extern void FreeTypeFreeContext(void *freetypecontext);
+extern SplineSet *FreeType_GridFitChar(void *single_glyph_context,
+ int enc, real ptsize, int dpi, int16 *width, SplineChar *sc);
+extern struct freetype_raster *FreeType_GetRaster(void *single_glyph_context,
+ int enc, real ptsize, int dpi,int depth);
+extern BDFChar *SplineCharFreeTypeRasterizeNoHints(SplineChar *sc,
+ int pixelsize,int depth);
+extern BDFFont *SplineFontFreeTypeRasterizeNoHints(SplineFont *sf,int pixelsize,int depth);
+extern void FreeType_FreeRaster(struct freetype_raster *raster);
+struct TT_ExecContextRec_;
+extern struct freetype_raster *DebuggerCurrentRaster(struct TT_ExecContextRec_ *exc,int depth);
+
+extern int UniFromName(const char *name,enum uni_interp interp, Encoding *encname);
+extern const char *StdGlyphName(char *buffer, int uni, enum uni_interp interp, NameList *for_this_font);
+extern char **AllGlyphNames(int uni, NameList *for_this_font,SplineChar *sc/* May be NULL*/);
+extern char **AllNamelistNames(void);
+extern NameList *DefaultNameListForNewFonts(void);
+extern NameList *NameListByName(char *name);
+extern NameList *LoadNamelist(char *filename);
+extern void LoadNamelistDir(char *dir);
+extern const char *RenameGlyphToNamelist(char *buffer, SplineChar *sc,NameList *old,NameList *new);
+extern void SFRenameGlyphsToNamelist(SplineFont *sf,NameList *new);
+extern char **SFTemporaryRenameGlyphsToNamelist(SplineFont *sf,NameList *new);
+extern void SFTemporaryRestoreGlyphNames(SplineFont *sf,char **former);
+
+extern void doversion(void);
+
+#ifdef FONTFORGE_CONFIG_GTK
+extern AnchorPos *AnchorPositioning(SplineChar *sc,char *ustr,SplineChar **sstr );
+#else
+extern AnchorPos *AnchorPositioning(SplineChar *sc,unichar_t *ustr,SplineChar **sstr );
+#endif
+extern void AnchorPosFree(AnchorPos *apos);
+
+extern int SFCloseAllInstrs(SplineFont *sf);
+extern void SCMarkInstrDlgAsChanged(SplineChar *sc);
+extern int SSTtfNumberPoints(SplineSet *ss);
+extern int SCNumberPoints(SplineChar *sc);
+extern int SCPointsNumberedProperly(SplineChar *sc);
+extern int ttfFindPointInSC(SplineChar *sc,int pnum,BasePoint *pos,
+ RefChar *bound);
+
+int SFFigureDefWidth(SplineFont *sf, int *_nomwid);
+
+extern int SFRenameTheseFeatureTags(SplineFont *sf, uint32 tag, int sli, int flags,
+ uint32 totag, int tosli, int toflags, int ismac);
+extern int SFRemoveUnusedNestedFeatures(SplineFont *sf);
+extern int SFHasNestedLookupWithTag(SplineFont *sf,uint32 tag,int ispos);
+extern int ClassesMatch(int cnt1,char **classes1,int cnt2,char **classes2);
+extern FPST *FPSTGlyphToClass(FPST *fpst);
+
+extern ASM *ASMFromOpenTypeForms(SplineFont *sf,uint32 script);
+extern ASM *ASMFromFPST(SplineFont *sf,FPST *fpst,int ordered);
+
+extern char *utf8_verify_copy(const char *str);
+
+extern char *MacStrToUtf8(const char *str,int macenc,int maclang);
+extern char *Utf8ToMacStr(const char *ustr,int macenc,int maclang);
+extern uint8 MacEncFromMacLang(int maclang);
+extern uint16 WinLangFromMac(int maclang);
+extern uint16 WinLangToMac(int winlang);
+extern int CanEncodingWinLangAsMac(int winlang);
+extern const int32 *MacEncToUnicode(int script,int lang);
+extern int MacLangFromLocale(void);
+extern char *MacLanguageFromCode(int code);
+extern char *FindEnglishNameInMacName(struct macname *mn);
+extern char *PickNameFromMacName(struct macname *mn);
+extern MacFeat *FindMacFeature(SplineFont *sf, int feat,MacFeat **secondary);
+extern struct macsetting *FindMacSetting(SplineFont *sf, int feat, int set,struct macsetting **secondary);
+extern struct macname *FindMacSettingName(SplineFont *sf, int feat, int set);
+
+extern int32 UniFromEnc(int enc, Encoding *encname);
+extern int32 EncFromUni(int32 uni, Encoding *encname);
+extern int32 EncFromName(const char *name,enum uni_interp interp,Encoding *encname);
+
+extern void MatInverse(real into[6], real orig[6]);
+
+extern int BpColinear(BasePoint *first, BasePoint *mid, BasePoint *last);
+
+enum psstrokeflags { sf_toobigwarn=1, sf_removeoverlap=2, sf_handle_eraser=4,
+ sf_correctdir=8, sf_clearbeforeinput=16 };
+extern enum psstrokeflags PsStrokeFlagsDlg(void);
+
+extern char *MMAxisAbrev(char *axis_name);
+extern char *MMMakeMasterFontname(MMSet *mm,int ipos,char **fullname);
+extern char *MMGuessWeight(MMSet *mm,int ipos,char *def);
+extern char *MMExtractNth(char *pt,int ipos);
+extern char *MMExtractArrayNth(char *pt,int ipos);
+extern int MMValid(MMSet *mm,int complain);
+extern void MMKern(SplineFont *sf,SplineChar *first,SplineChar *second,int diff,
+ struct lookup_subtable *sub,KernPair *oldkp);
+extern char *MMBlendChar(MMSet *mm, int gid);
+extern int MMReblend(struct fontview *fv, MMSet *mm);
+struct fontview *MMCreateBlendedFont(MMSet *mm,struct fontview *fv,real blends[MmMax],int tonew );
+
+extern char *EnforcePostScriptName(char *old);
+
+extern const char *TTFNameIds(int id);
+extern const char *MSLangString(int language);
+extern void FontInfoInit(void);
+extern void LookupUIInit(void);
+extern char *ToAbsolute(char *filename);
+
+enum Compare_Ret { SS_DiffContourCount = 1,
+ SS_MismatchOpenClosed = 2,
+ SS_DisorderedContours = 4,
+ SS_DisorderedStart = 8,
+ SS_DisorderedDirection = 16,
+ SS_PointsMatch = 32,
+ SS_ContourMatch = 64,
+ SS_NoMatch = 128,
+ SS_RefMismatch = 256,
+ SS_WidthMismatch = 512,
+ SS_VWidthMismatch = 1024,
+ SS_HintMismatch = 2048,
+ SS_HintMaskMismatch = 4096,
+ SS_LayerCntMismatch = 8192,
+ SS_ContourMismatch = 16384,
+ SS_UnlinkRefMatch = 32768,
+
+ BC_DepthMismatch = 1<<16,
+ BC_BoundingBoxMismatch = 2<<16,
+ BC_BitmapMismatch = 4<<16,
+ BC_NoMatch = 8<<16,
+ BC_Match = 16<<16,
+
+ SS_RefPtMismatch = 32<<16
+ };
+
+extern enum Compare_Ret BitmapCompare(BDFChar *bc1, BDFChar *bc2, int err, int bb_err);
+extern enum Compare_Ret SSsCompare(const SplineSet *ss1, const SplineSet *ss2,
+ real pt_err, real spline_err, SplinePoint **hmfail);
+enum font_compare_flags { fcf_outlines=1, fcf_exact=2, fcf_warn_not_exact=4,
+ fcf_hinting=8, fcf_hintmasks=0x10, fcf_hmonlywithconflicts=0x20,
+ fcf_warn_not_ref_exact=0x40,
+ fcf_bitmaps=0x80, fcf_names = 0x100, fcf_gpos=0x200, fcf_gsub=0x400,
+ fcf_adddiff2sf1=0x800, fcf_addmissing=0x1000 };
+extern int CompareFonts(SplineFont *sf1, EncMap *map1, SplineFont *sf2,
+ FILE *diffs, int flags);
+
+
+# if HANYANG
+extern void SFDDumpCompositionRules(FILE *sfd,struct compositionrules *rules);
+extern struct compositionrules *SFDReadCompositionRules(FILE *sfd);
+extern void SFModifyComposition(SplineFont *sf);
+extern void SFBuildSyllables(SplineFont *sf);
+# endif
+
+extern void DefaultOtherSubrs(void);
+extern int ReadOtherSubrsFile(char *filename);
+
+extern char *utf8toutf7_copy(const char *_str);
+extern char *utf7toutf8_copy(const char *_str);
+
+extern void SFSetModTime(SplineFont *sf);
+extern void SFTimesFromFile(SplineFont *sf,FILE *);
+
+extern int SFHasInstructions(SplineFont *sf);
+
+extern SplineChar *SCHasSubs(SplineChar *sc,uint32 tag);
+
+extern char *TagFullName(SplineFont *sf,uint32 tag, int ismac, int onlyifknown);
+
+extern uint32 *SFScriptsInLookups(SplineFont *sf,int gpos);
+extern uint32 *SFLangsInScript(SplineFont *sf,int gpos,uint32 script);
+extern uint32 *SFFeaturesInScriptLang(SplineFont *sf,int gpos,uint32 script,uint32 lang);
+extern OTLookup **SFLookupsInScriptLangFeature(SplineFont *sf,int gpos,uint32 script,uint32 lang, uint32 feature);
+extern SplineChar **SFGlyphsWithPSTinSubtable(SplineFont *sf,struct lookup_subtable *subtable);
+extern SplineChar **SFGlyphsWithLigatureinLookup(SplineFont *sf,struct lookup_subtable *subtable);
+extern void SFFindUnusedLookups(SplineFont *sf);
+extern void SFFindClearUnusedLookupBits(SplineFont *sf);
+extern void SFRemoveUnusedLookupSubTables(SplineFont *sf,
+ int remove_incomplete_anchorclasses,
+ int remove_unused_lookups);
+extern void SFRemoveLookupSubTable(SplineFont *sf,struct lookup_subtable *sub);
+extern void SFRemoveLookup(SplineFont *sf,OTLookup *otl);
+extern struct lookup_subtable *SFFindLookupSubtable(SplineFont *sf,char *name);
+extern struct lookup_subtable *SFFindLookupSubtableAndFreeName(SplineFont *sf,char *name);
+extern OTLookup *SFFindLookup(SplineFont *sf,char *name);
+extern void NameOTLookup(OTLookup *otl,SplineFont *sf);
+extern void FListAppendScriptLang(FeatureScriptLangList *fl,uint32 script_tag,uint32 lang_tag);
+extern void FListsAppendScriptLang(FeatureScriptLangList *fl,uint32 script_tag,uint32 lang_tag);
+struct scriptlanglist *SLCopy(struct scriptlanglist *sl);
+extern FeatureScriptLangList *FeatureListCopy(FeatureScriptLangList *fl);
+extern void SLMerge(FeatureScriptLangList *into, struct scriptlanglist *fsl);
+extern void FLMerge(OTLookup *into, OTLookup *from);
+extern FeatureScriptLangList *FLOrder(FeatureScriptLangList *fl);
+extern int FeatureScriptTagInFeatureScriptList(uint32 tag, uint32 script, FeatureScriptLangList *fl);
+extern int FeatureTagInFeatureScriptList(uint32 tag, FeatureScriptLangList *fl);
+extern int DefaultLangTagInOneScriptList(struct scriptlanglist *sl);
+extern struct scriptlanglist *DefaultLangTagInScriptList(struct scriptlanglist *sl, int DFLT_ok);
+extern int ScriptInFeatureScriptList(uint32 script, FeatureScriptLangList *fl);
+extern int FeatureOrderId( int isgpos,FeatureScriptLangList *fl );
+extern void SFSubTablesMerge(SplineFont *_sf,struct lookup_subtable *subfirst,
+ struct lookup_subtable *subsecond);
+extern struct lookup_subtable *SFSubTableFindOrMake(SplineFont *sf,uint32 tag,uint32 script,
+ int lookup_type );
+extern struct lookup_subtable *SFSubTableMake(SplineFont *sf,uint32 tag,uint32 script,
+ int lookup_type );
+extern OTLookup *OTLookupCopyInto(SplineFont *into_sf,SplineFont *from_sf, OTLookup *from_otl);
+extern struct opentype_str *ApplyTickedFeatures(SplineFont *sf,uint32 *flist, uint32 script, uint32 lang,
+ SplineChar **glyphs);
+extern int VerticalKernFeature(SplineFont *sf, OTLookup *otl, int ask);
+
+extern int KCFindIndex(KernClass *kc,char *name1, char *name2);
+extern KernClass *SFFindKernClass(SplineFont *sf,SplineChar *first,SplineChar *last,
+ int *index,int allow_zero);
+extern KernClass *SFFindVKernClass(SplineFont *sf,SplineChar *first,SplineChar *last,
+ int *index,int allow_zero);
+
+#ifdef LUA_FF_LIB
+extern SplineFont *SFReadTTFInfo(char *filename,int flags,enum openflags openflags);
+extern SplineFont *CFFParseInfo(char *filename);
+extern SplineFont *SFReadMacBinaryInfo(char *filename,int flags,enum openflags openflags);
+extern SplineFont *ReadSplineFontInfo(char *filename,enum openflags);
+#endif
+
+#if !defined(_NO_PYTHON)
+extern void FontForge_PythonInit(void);
+extern void PyFF_ErrorString(const char *msg,const char *str);
+extern void PyFF_ErrorF3(const char *frmt, const char *str, int size, int depth);
+extern void PyFF_Stdin(void);
+extern void PyFF_Main(int argc,char **argv,int start);
+extern void PyFF_ScriptFile(struct fontview *fv,char *filename);
+extern void PyFF_ScriptString(struct fontview *fv,char *str);
+extern void PyFF_FreeFV(struct fontview *fv);
+extern void PyFF_FreeSC(SplineChar *sc);
+struct gtextinfo;
+extern void scriptingSaveEnglishNames(struct gtextinfo *ids,struct gtextinfo *langs);
+#endif
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/splineorder2.c b/Build/source/libs/luafontforge/fontforge/fontforge/splineorder2.c
new file mode 100644
index 00000000000..2c2aa350a67
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/splineorder2.c
@@ -0,0 +1,1484 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+#include <locale.h>
+#include <utype.h>
+#include <ustring.h>
+#include <chardata.h>
+#ifdef HAVE_IEEEFP_H
+# include <ieeefp.h> /* Solaris defines isnan in ieeefp rather than math.h */
+#endif
+
+/* This file contains utility routines for second order bezier splines */
+/* (ie. truetype) */
+/* The most interesting thing */
+/* it does is to figure out a quadratic approximation to the cubic splines */
+/* that postscript uses. We do this by looking at each spline and running */
+/* from the end toward the beginning, checking approximately every emunit */
+/* There is only one quadratic spline possible for any given interval of the */
+/* cubic. The start and end points are the interval end points (obviously) */
+/* the control point is where the two slopes (at start and end) intersect. */
+/* If this spline is a close approximation to the cubic spline (doesn't */
+/* deviate from it by more than an emunit or so), then we use this interval */
+/* as one of our quadratic splines. */
+/* It may turn out that the "quadratic" spline above is actually linear. Well */
+/* that's ok. It may also turn out that we can't find a good approximation. */
+/* If that's true then just insert a linear segment for an emunit stretch. */
+/* (actually this failure mode may not be possible), but I'm not sure */
+/* Then we play the same trick for the rest of the cubic spline (if any) */
+
+/* Does the quadratic spline in ttf approximate the cubic spline in ps */
+/* within one pixel between tmin and tmax (on ps. presumably ttf between 0&1 */
+/* dim is the dimension in which there is the greatest change */
+static int comparespline(Spline *ps, Spline *ttf, real tmin, real tmax, real err) {
+ int dim=0, other;
+ real dx, dy, ddim, dt, t;
+ real d, o;
+ real ttf_t, sq, val;
+ DBounds bb;
+ extended ts[3];
+ int i;
+
+ /* Are all points on ttf near points on ps? */
+ /* This doesn't answer that question, but rules out gross errors */
+ bb.minx = bb.maxx = ps->from->me.x; bb.miny = bb.maxy = ps->from->me.y;
+ if ( ps->from->nextcp.x>bb.maxx ) bb.maxx = ps->from->nextcp.x;
+ else bb.minx = ps->from->nextcp.x;
+ if ( ps->from->nextcp.y>bb.maxy ) bb.maxy = ps->from->nextcp.y;
+ else bb.miny = ps->from->nextcp.y;
+ if ( ps->to->prevcp.x>bb.maxx ) bb.maxx = ps->to->prevcp.x;
+ else if ( ps->to->prevcp.x<bb.minx ) bb.minx = ps->to->prevcp.x;
+ if ( ps->to->prevcp.y>bb.maxy ) bb.maxy = ps->to->prevcp.y;
+ else if ( ps->to->prevcp.y<bb.miny ) bb.miny = ps->to->prevcp.y;
+ if ( ps->to->me.x>bb.maxx ) bb.maxx = ps->to->me.x;
+ else if ( ps->to->me.x<bb.minx ) bb.minx = ps->to->me.x;
+ if ( ps->to->me.y>bb.maxy ) bb.maxy = ps->to->me.y;
+ else if ( ps->to->me.y<bb.miny ) bb.miny = ps->to->me.y;
+ for ( t=.1; t<1; t+= .1 ) {
+ d = (ttf->splines[0].b*t+ttf->splines[0].c)*t+ttf->splines[0].d;
+ o = (ttf->splines[1].b*t+ttf->splines[1].c)*t+ttf->splines[1].d;
+ if ( d<bb.minx || d>bb.maxx || o<bb.miny || o>bb.maxy )
+return( false );
+ }
+
+ /* Are all points on ps near points on ttf? */
+ dx = ((ps->splines[0].a*tmax+ps->splines[0].b)*tmax+ps->splines[0].c)*tmax -
+ ((ps->splines[0].a*tmin+ps->splines[0].b)*tmin+ps->splines[0].c)*tmin ;
+ dy = ((ps->splines[1].a*tmax+ps->splines[1].b)*tmax+ps->splines[1].c)*tmax -
+ ((ps->splines[1].a*tmin+ps->splines[1].b)*tmin+ps->splines[1].c)*tmin ;
+ if ( dx<0 ) dx = -dx;
+ if ( dy<0 ) dy = -dy;
+ if ( dx>dy ) {
+ dim = 0;
+ ddim = dx;
+ } else {
+ dim = 1;
+ ddim = dy;
+ }
+ other = !dim;
+
+ t = tmin;
+ dt = (tmax-tmin)/ddim;
+ for ( t=tmin; t<=tmax; t+= dt ) {
+ if ( t>tmax-dt/8. ) t = tmax; /* Avoid rounding errors */
+ d = ((ps->splines[dim].a*t+ps->splines[dim].b)*t+ps->splines[dim].c)*t+ps->splines[dim].d;
+ o = ((ps->splines[other].a*t+ps->splines[other].b)*t+ps->splines[other].c)*t+ps->splines[other].d;
+ if ( ttf->splines[dim].b == 0 ) {
+ ttf_t = (d-ttf->splines[dim].d)/ttf->splines[dim].c;
+ } else {
+ sq = ttf->splines[dim].c*ttf->splines[dim].c -
+ 4*ttf->splines[dim].b*(ttf->splines[dim].d-d);
+ if ( sq<0 )
+return( false );
+ sq = sqrt(sq);
+ ttf_t = (-ttf->splines[dim].c-sq)/(2*ttf->splines[dim].b);
+ if ( ttf_t>=-0.1 && ttf_t<=1.1 ) { /* Optimizer gives us rounding errors */
+ /* And tmin/tmax are no longer exact */
+ val = (ttf->splines[other].b*ttf_t+ttf->splines[other].c)*ttf_t+
+ ttf->splines[other].d;
+ if ( val>o-err && val<o+err )
+ continue;
+ }
+ ttf_t = (-ttf->splines[dim].c+sq)/(2*ttf->splines[dim].b);
+ }
+ if ( ttf_t>=-0.1 && ttf_t<=1.1 ) {
+ val = (ttf->splines[other].b*ttf_t+ttf->splines[other].c)*ttf_t+
+ ttf->splines[other].d;
+ if ( val>o-err && val<o+err )
+ continue;
+ }
+return( false );
+ }
+
+ /* Are representative points on ttf near points on ps? */
+ for ( t=.125; t<1; t+= .125 ) {
+ d = (ttf->splines[dim].b*t+ttf->splines[dim].c)*t+ttf->splines[dim].d;
+ o = (ttf->splines[other].b*t+ttf->splines[other].c)*t+ttf->splines[other].d;
+ SplineSolveFull(&ps->splines[dim],d,ts);
+ for ( i=0; i<3; ++i ) if ( ts[i]!=-1 ) {
+ val = ((ps->splines[other].a*ts[i]+ps->splines[other].b)*ts[i]+ps->splines[other].c)*ts[i]+ps->splines[other].d;
+ if ( val>o-err && val<o+err )
+ break;
+ }
+ if ( i==3 )
+return( false );
+ }
+
+return( true );
+}
+
+static SplinePoint *MakeQuadSpline(SplinePoint *start,Spline *ttf,real x,
+ real y, real tmax,SplinePoint *oldend) {
+ Spline *new = chunkalloc(sizeof(Spline));
+ SplinePoint *end = chunkalloc(sizeof(SplinePoint));
+
+ if ( tmax==1 ) {
+ end->roundx = oldend->roundx; end->roundy = oldend->roundy; end->dontinterpolate = oldend->dontinterpolate;
+ x = oldend->me.x; y = oldend->me.y; /* Want it to compare exactly */
+ }
+ end->ttfindex = 0xfffe;
+ end->nextcpindex = 0xfffe;
+ end->me.x = end->nextcp.x = x;
+ end->me.y = end->nextcp.y = y;
+ end->nonextcp = true;
+
+ *new = *ttf;
+ new->from = start; start->next = new;
+ new->to = end; end->prev = new;
+ if ( new->splines[0].b==0 && new->splines[1].b==0 ) {
+ end->noprevcp = true;
+ end->prevcp.x = x; end->prevcp.y = y;
+ new->islinear = new->knownlinear = true;
+ } else {
+ end->prevcp.x = start->nextcp.x = ttf->splines[0].c/2+ttf->splines[0].d;
+ end->prevcp.y = start->nextcp.y = ttf->splines[1].c/2+ttf->splines[1].d;
+ start->nonextcp = end->noprevcp = false;
+ new->isquadratic = true;
+ }
+ new->order2 = true;
+return( end );
+}
+
+static int buildtestquads(Spline *ttf,real xmin,real ymin,real cx,real cy,
+ real x,real y,real tmin,real t,real err,Spline *ps, DBounds *psbb) {
+ real fudge;
+
+ /* test the control points are reasonable */
+ fudge = (psbb->maxx-psbb->minx) + (psbb->maxy-psbb->miny);
+ if ( cx<psbb->minx-fudge || cx>psbb->maxx+fudge )
+return( false );
+ if ( cy<psbb->miny-fudge || cy>psbb->maxy+fudge )
+return( false );
+
+ ttf->splines[0].d = xmin;
+ ttf->splines[0].c = 2*(cx-xmin);
+ ttf->splines[0].b = xmin+x-2*cx;
+ ttf->splines[1].d = ymin;
+ ttf->splines[1].c = 2*(cy-ymin);
+ ttf->splines[1].b = ymin+y-2*cy;
+ if ( comparespline(ps,ttf,tmin,t,err) )
+return( true );
+
+#if 0
+ /* In a few cases, the following code will find a match when the above */
+ /* would not. We move the control point slightly along a vector normal */
+ /* to the vector between the end-points. What I really want is along */
+ /* a vector midway between the two slopes, but that's too hard to figure */
+ sq = sqrt((x-xmin)*(x-xmin) + (y-ymin)*(y-ymin));
+ norm.x = (ymin-y)/sq; norm.y = (x-xmin)/sq;
+
+ ttf->splines[0].c += err*norm.x;
+ ttf->splines[0].b -= err*norm.x;
+ ttf->splines[1].c += err*norm.y;
+ ttf->splines[1].b -= err*norm.y;
+ if ( comparespline(ps,ttf,tmin,t,err) )
+return( true );
+
+ ttf->splines[0].c -= 2*err*norm.x;
+ ttf->splines[0].b += 2*err*norm.x;
+ ttf->splines[1].c -= 2*err*norm.y;
+ ttf->splines[1].b += 2*err*norm.y;
+ if ( comparespline(ps,ttf,tmin,t,err) )
+return( true );
+
+ ttf->splines[0].c = 2*(cx-xmin);
+ ttf->splines[0].b = xmin+x-2*cx;
+ ttf->splines[1].c = 2*(cy-ymin);
+ ttf->splines[1].b = ymin+y-2*cy;
+#endif
+return( false );
+}
+
+static SplinePoint *LinearSpline(Spline *ps,SplinePoint *start, real tmax) {
+ real x,y;
+ Spline *new = chunkalloc(sizeof(Spline));
+ SplinePoint *end = chunkalloc(sizeof(SplinePoint));
+
+ x = ((ps->splines[0].a*tmax+ps->splines[0].b)*tmax+ps->splines[0].c)*tmax+ps->splines[0].d;
+ y = ((ps->splines[1].a*tmax+ps->splines[1].b)*tmax+ps->splines[1].c)*tmax+ps->splines[1].d;
+ if ( tmax==1 ) {
+ SplinePoint *oldend = ps->to;
+ end->roundx = oldend->roundx; end->roundy = oldend->roundy; end->dontinterpolate = oldend->dontinterpolate;
+ x = oldend->me.x; y = oldend->me.y; /* Want it to compare exactly */
+ }
+ end->ttfindex = 0xfffe;
+ end->nextcpindex = 0xfffe;
+ end->me.x = end->nextcp.x = end->prevcp.x = x;
+ end->me.y = end->nextcp.y = end->prevcp.y = y;
+ end->nonextcp = end->noprevcp = start->nonextcp = true;
+ new->from = start; start->next = new;
+ new->to = end; end->prev = new;
+ new->splines[0].d = start->me.x;
+ new->splines[0].c = (x-start->me.x);
+ new->splines[1].d = start->me.y;
+ new->splines[1].c = (y-start->me.y);
+ new->order2 = true;
+ new->islinear = new->knownlinear = true;
+return( end );
+}
+
+static SplinePoint *_ttfapprox(Spline *ps,real tmin, real tmax, SplinePoint *start) {
+ int dim=0;
+ real dx, dy, ddim, dt, t, err;
+ real x,y, xmin, ymin;
+ real dxdtmin, dydtmin, dxdt, dydt;
+ SplinePoint *sp;
+ real cx, cy;
+ Spline ttf;
+ int cnt = -1, forceit, unforceable;
+ BasePoint end, rend, dend;
+ DBounds bb;
+
+ rend.x = ((ps->splines[0].a*tmax+ps->splines[0].b)*tmax+ps->splines[0].c)*tmax + ps->splines[0].d;
+ rend.y = ((ps->splines[1].a*tmax+ps->splines[1].b)*tmax+ps->splines[1].c)*tmax + ps->splines[1].d;
+ end.x = rint( rend.x );
+ end.y = rint( rend.y );
+ dend.x = (3*ps->splines[0].a*tmax+2*ps->splines[0].b)*tmax+ps->splines[0].c;
+ dend.y = (3*ps->splines[1].a*tmax+2*ps->splines[1].b)*tmax+ps->splines[1].c;
+ memset(&ttf,'\0',sizeof(ttf));
+
+ bb.minx = bb.maxx = ps->from->me.x;
+ if ( ps->from->nextcp.x > bb.maxx ) bb.maxx = ps->from->nextcp.x;
+ else if ( ps->from->nextcp.x < bb.minx ) bb.minx = ps->from->nextcp.x;
+ if ( ps->to->prevcp.x > bb.maxx ) bb.maxx = ps->to->prevcp.x;
+ else if ( ps->to->prevcp.x < bb.minx ) bb.minx = ps->to->prevcp.x;
+ if ( ps->to->me.x > bb.maxx ) bb.maxx = ps->to->me.x;
+ else if ( ps->to->me.x < bb.minx ) bb.minx = ps->to->me.x;
+ bb.miny = bb.maxy = ps->from->me.y;
+ if ( ps->from->nextcp.y > bb.maxy ) bb.maxy = ps->from->nextcp.y;
+ else if ( ps->from->nextcp.y < bb.miny ) bb.miny = ps->from->nextcp.y;
+ if ( ps->to->prevcp.y > bb.maxy ) bb.maxy = ps->to->prevcp.y;
+ else if ( ps->to->prevcp.y < bb.miny ) bb.miny = ps->to->prevcp.y;
+ if ( ps->to->me.y > bb.maxy ) bb.maxy = ps->to->me.y;
+ else if ( ps->to->me.y < bb.miny ) bb.miny = ps->to->me.y;
+
+ tail_recursion:
+ ++cnt;
+
+ xmin = start->me.x;
+ ymin = start->me.y;
+ dxdtmin = (3*ps->splines[0].a*tmin+2*ps->splines[0].b)*tmin + ps->splines[0].c;
+ dydtmin = (3*ps->splines[1].a*tmin+2*ps->splines[1].b)*tmin + ps->splines[1].c;
+
+ dx = ((ps->splines[0].a*tmax+ps->splines[0].b)*tmax+ps->splines[0].c)*tmax -
+ ((ps->splines[0].a*tmin+ps->splines[0].b)*tmin+ps->splines[0].c)*tmin ;
+ dy = ((ps->splines[1].a*tmax+ps->splines[1].b)*tmax+ps->splines[1].c)*tmax -
+ ((ps->splines[1].a*tmin+ps->splines[1].b)*tmin+ps->splines[1].c)*tmin ;
+ if ( dx<0 ) dx = -dx;
+ if ( dy<0 ) dy = -dy;
+ if ( dx>dy ) {
+ dim = 0;
+ ddim = dx;
+ } else {
+ dim = 1;
+ ddim = dy;
+ }
+ if (( err = ddim/3000 )<1 ) err = 1;
+
+ if ( ddim<2 ||
+ (dend.x==0 && rint(start->me.x)==end.x && dy<=10 && cnt!=0) ||
+ (dend.y==0 && rint(start->me.y)==end.y && dx<=10 && cnt!=0) ) {
+ if ( cnt==0 || start->noprevcp )
+return( LinearSpline(ps,start,tmax));
+ /* If the end point is very close to where we want to be, then just */
+ /* pretend it's right */
+ start->prev->splines[0].b += ps->to->me.x-start->me.x;
+ start->prev->splines[1].b += ps->to->me.y-start->me.y;
+ start->prevcp.x += rend.x-start->me.x;
+ start->prevcp.y += rend.y-start->me.y;
+ if ( start->prev!=NULL && !start->prev->from->nonextcp )
+ start->prev->from->nextcp = start->prevcp;
+ start->me = rend;
+return( start );
+ }
+
+ dt = (tmax-tmin)/ddim;
+ forceit = false;
+ force_end:
+ unforceable = false;
+ for ( t=tmax; t>tmin+dt/128; t-= dt ) { /* dt/128 is a hack to avoid rounding errors */
+ x = ((ps->splines[0].a*t+ps->splines[0].b)*t+ps->splines[0].c)*t+ps->splines[0].d;
+ y = ((ps->splines[1].a*t+ps->splines[1].b)*t+ps->splines[1].c)*t+ps->splines[1].d;
+ dxdt = (3*ps->splines[0].a*t+2*ps->splines[0].b)*t + ps->splines[0].c;
+ dydt = (3*ps->splines[1].a*t+2*ps->splines[1].b)*t + ps->splines[1].c;
+ /* if the slopes are parallel at the ends there can be no bezier quadratic */
+ /* (control point is where the splines intersect. But if they are */
+ /* parallel and colinear then there is a line between 'em */
+ if ( ( dxdtmin==0 && dxdt==0 ) || (dydtmin==0 && dydt==0) ||
+ ( dxdt!=0 && dxdtmin!=0 &&
+ RealNearish(dydt/dxdt,dydtmin/dxdtmin)) )
+ continue;
+
+ if ( dxdt==0 )
+ cx=x;
+ else if ( dxdtmin==0 )
+ cx=xmin;
+ else
+ cx = -(ymin-(dydtmin/dxdtmin)*xmin-y+(dydt/dxdt)*x)/(dydtmin/dxdtmin-dydt/dxdt);
+ if ( dydt==0 )
+ cy=y;
+ else if ( dydtmin==0 )
+ cy=ymin;
+ else
+ cy = -(xmin-(dxdtmin/dydtmin)*ymin-x+(dxdt/dydt)*y)/(dxdtmin/dydtmin-dxdt/dydt);
+ if ( t==tmax && ((cy==y && cx==x) || (cy==ymin && cx==xmin)) )
+ unforceable = true;
+ /* Make the quadratic spline from (xmin,ymin) through (cx,cy) to (x,y)*/
+ if ( forceit || buildtestquads(&ttf,xmin,ymin,cx,cy,x,y,tmin,t,err,ps,&bb)) {
+ if ( !forceit && !unforceable && (rend.x-x)*(rend.x-x)+(rend.y-y)*(rend.y-y)<4*4 ) {
+ forceit = true;
+ goto force_end;
+ }
+ sp = MakeQuadSpline(start,&ttf,x,y,t,ps->to);
+ forceit = false;
+ if ( t==tmax )
+return( sp );
+ tmin = t;
+ start = sp;
+ goto tail_recursion;
+ }
+ ttf.splines[0].d = xmin;
+ ttf.splines[0].c = x-xmin;
+ ttf.splines[0].b = 0;
+ ttf.splines[1].d = ymin;
+ ttf.splines[1].c = y-ymin;
+ ttf.splines[1].b = 0;
+ if ( comparespline(ps,&ttf,tmin,t,err) ) {
+ sp = LinearSpline(ps,start,t);
+ if ( t==tmax )
+return( sp );
+ tmin = t;
+ start = sp;
+ goto tail_recursion;
+ }
+ }
+ tmin += dt;
+ start = LinearSpline(ps,start,tmin);
+ goto tail_recursion;
+}
+
+static SplinePoint *__ttfApprox(Spline *ps,real tmin, real tmax, SplinePoint *start) {
+ extended inflect[2];
+ int i=0;
+#if 1
+ SplinePoint *end;
+ Spline *s, *next;
+
+ end = _ttfapprox(ps,tmin,tmax,start);
+ if ( ps->knownlinear )
+return( end );
+ for ( s=start->next; s!=NULL && !s->islinear; s=s->to->next );
+ if ( s==NULL )
+return( end );
+ for ( s=start->next; s!=NULL ; s=next ) {
+ next = s->to->next;
+ SplinePointFree(s->to);
+ SplineFree(s);
+ }
+#endif
+/* Hmm. With my algorithem, checking for points of inflection actually makes */
+/* things worse. It uses more points and the splines don't join as nicely */
+/* However if we get a bad match (a line) in the normal approx, then check */
+/* Err... I was computing POI incorrectly. Above statement might not be correct*/
+ /* no points of inflection in quad splines */
+
+ i = Spline2DFindPointsOfInflection(ps, inflect);
+ if ( i==2 ) {
+ if ( RealNearish(inflect[0],inflect[1]) )
+ --i;
+ else if ( inflect[0]>inflect[1] ) {
+ real temp = inflect[0];
+ inflect[0] = inflect[1];
+ inflect[1] = temp;
+ }
+ }
+ if ( i!=0 ) {
+ start = _ttfapprox(ps,tmin,inflect[0],start);
+ tmin = inflect[0];
+ if ( i==2 ) {
+ start = _ttfapprox(ps,tmin,inflect[1],start);
+ tmin = inflect[1];
+ }
+ }
+return( _ttfapprox(ps,tmin,tmax,start));
+}
+
+#if !defined(FONTFORGE_CONFIG_NON_SYMMETRIC_QUADRATIC_CONVERSION)
+typedef struct qpoint {
+ BasePoint bp;
+ BasePoint cp;
+ double t;
+} QPoint;
+
+static int comparedata(Spline *ps,QPoint *data,int qfirst,int qlast,
+ int round_to_int ) {
+ Spline ttf;
+ int i;
+ double err = round_to_int ? 1.5 : 1;
+
+ if ( qfirst==qlast ) /* happened (was a bug) */
+return( false );
+
+ /* Control points diametrically opposed */
+ if ( (data[qlast-2].cp.x-ps->to->me.x)*(ps->to->prevcp.x-ps->to->me.x) +
+ (data[qlast-2].cp.y-ps->to->me.y)*(ps->to->prevcp.y-ps->to->me.y)<0 )
+return( false );
+ if ( (data[qfirst-1].cp.x-ps->from->me.x)*(ps->from->nextcp.x-ps->from->me.x) +
+ (data[qfirst-1].cp.y-ps->from->me.y)*(ps->from->nextcp.y-ps->from->me.y)<0 )
+return( false );
+
+ memset(&ttf,0,sizeof(ttf));
+ for ( i=qfirst; i<qlast; ++i ) {
+ ttf.splines[0].d = data[i-1].bp.x;
+ ttf.splines[0].c = 2*(data[i-1].cp.x-data[i-1].bp.x);
+ ttf.splines[0].b = data[i-1].bp.x+data[i].bp.x-2*data[i-1].cp.x;
+ ttf.splines[1].d = data[i-1].bp.y;
+ ttf.splines[1].c = 2*(data[i-1].cp.y-data[i-1].bp.y);
+ ttf.splines[1].b = data[i-1].bp.y+data[i].bp.y-2*data[i-1].cp.y;
+ if ( !comparespline(ps,&ttf,data[i-1].t,data[i].t,err) )
+return( false );
+ }
+return( true );
+}
+
+static SplinePoint *CvtDataToSplines(QPoint *data,int qfirst,int qlast,SplinePoint *start) {
+ SplinePoint *end;
+ int i;
+
+ for ( i=qfirst; i<qlast; ++i ) {
+ end = SplinePointCreate(data[i].bp.x,data[i].bp.y);
+ start->nextcp = end->prevcp = data[i-1].cp;
+ start->nonextcp = end->noprevcp = false;
+ SplineMake2(start,end);
+ start = end;
+ }
+return( start );
+}
+
+static int PrettyApprox(Spline *ps,double tmin, double tmax,
+ QPoint *data, int qcnt, int round_to_int ) {
+ int ptcnt, q, i;
+ double distance, dx, dy, tstart;
+ BasePoint end, mid, slopemin, slopemid, slopeend;
+ QPoint data2[12];
+
+ if ( qcnt==-1 )
+return( -1 );
+
+ slopemin.x = (3*ps->splines[0].a*tmin+2*ps->splines[0].b)*tmin+ps->splines[0].c;
+ slopemin.y = (3*ps->splines[1].a*tmin+2*ps->splines[1].b)*tmin+ps->splines[1].c;
+
+ end.x = ((ps->splines[0].a*tmax+ps->splines[0].b)*tmax+ps->splines[0].c)*tmax+ps->splines[0].d;
+ end.y = ((ps->splines[1].a*tmax+ps->splines[1].b)*tmax+ps->splines[1].c)*tmax+ps->splines[1].d;
+ slopeend.x = (3*ps->splines[0].a*tmax+2*ps->splines[0].b)*tmax+ps->splines[0].c;
+ slopeend.y = (3*ps->splines[1].a*tmax+2*ps->splines[1].b)*tmax+ps->splines[1].c;
+
+ if ( round_to_int && tmax!=1 ) {
+ end.x = rint( end.x );
+ end.y = rint( end.y );
+ }
+
+ dx = end.x-data[qcnt-1].bp.x; dy = end.y-data[qcnt-1].bp.y;
+ distance = dx*dx + dy*dy;
+
+ for ( ptcnt=0; ptcnt<10; ++ptcnt ) {
+ if ( ptcnt>1 && distance/(ptcnt*ptcnt)<100 )
+return( -1 ); /* Points too close for a good approx */
+ q = qcnt;
+ data2[ptcnt+1].bp = end;
+ for ( i=0; i<=ptcnt; ++i ) {
+ tstart = (tmin*(ptcnt-i) + tmax*(i+1))/(ptcnt+1);
+ mid.x = ((ps->splines[0].a*tstart+ps->splines[0].b)*tstart+ps->splines[0].c)*tstart+ps->splines[0].d;
+ mid.y = ((ps->splines[1].a*tstart+ps->splines[1].b)*tstart+ps->splines[1].c)*tstart+ps->splines[1].d;
+ if ( i==0 ) {
+ slopemid.x = (3*ps->splines[0].a*tstart+2*ps->splines[0].b)*tstart+ps->splines[0].c;
+ slopemid.y = (3*ps->splines[1].a*tstart+2*ps->splines[1].b)*tstart+ps->splines[1].c;
+ if ( slopemid.x==0 )
+ data[q-1].cp.x=mid.x;
+ else if ( slopemin.x==0 )
+ data[q-1].cp.x=data[q-1].bp.x;
+ else if ( RealNear(slopemin.y/slopemin.x,slopemid.y/slopemid.x) )
+ break;
+ else
+ data[q-1].cp.x = -(data[q-1].bp.y-(slopemin.y/slopemin.x)*data[q-1].bp.x-mid.y+(slopemid.y/slopemid.x)*mid.x)/(slopemin.y/slopemin.x-slopemid.y/slopemid.x);
+ if ( slopemid.y==0 )
+ data[q-1].cp.y=mid.y;
+ else if ( slopemin.y==0 )
+ data[q-1].cp.y=data[q-1].bp.y;
+ else if ( RealNear(slopemin.x/slopemin.y,slopemid.x/slopemid.y) )
+ break;
+ else
+ data[q-1].cp.y = -(data[q-1].bp.x-(slopemin.x/slopemin.y)*data[q-1].bp.y-mid.x+(slopemid.x/slopemid.y)*mid.y)/(slopemin.x/slopemin.y-slopemid.x/slopemid.y);
+ } else {
+ data[q-1].cp.x = 2*data[q-1].bp.x - data[q-2].cp.x;
+ data[q-1].cp.y = 2*data[q-1].bp.y - data[q-2].cp.y;
+ }
+ data[q].bp = mid;
+ data[q++].t = tstart;
+
+ tstart = (tmax*(ptcnt-i) + tmin*(i+1))/(ptcnt+1);
+ mid.x = ((ps->splines[0].a*tstart+ps->splines[0].b)*tstart+ps->splines[0].c)*tstart+ps->splines[0].d;
+ mid.y = ((ps->splines[1].a*tstart+ps->splines[1].b)*tstart+ps->splines[1].c)*tstart+ps->splines[1].d;
+ if ( i==0 ) {
+ slopemid.x = (3*ps->splines[0].a*tstart+2*ps->splines[0].b)*tstart+ps->splines[0].c;
+ slopemid.y = (3*ps->splines[1].a*tstart+2*ps->splines[1].b)*tstart+ps->splines[1].c;
+ if ( slopemid.x==0 )
+ data2[ptcnt-i].cp.x=mid.x;
+ else if ( slopeend.x==0 )
+ data2[ptcnt-i].cp.x=data2[ptcnt-i+1].bp.x;
+ else if ( RealNear(slopeend.y/slopeend.x,slopemid.y/slopemid.x) )
+ break;
+ else
+ data2[ptcnt-i].cp.x = -(data2[ptcnt-i+1].bp.y-(slopeend.y/slopeend.x)*data2[ptcnt-i+1].bp.x-mid.y+(slopemid.y/slopemid.x)*mid.x)/(slopeend.y/slopeend.x-slopemid.y/slopemid.x);
+ if ( slopemid.y==0 )
+ data2[ptcnt-i].cp.y=mid.y;
+ else if ( slopeend.y==0 )
+ data2[ptcnt-i].cp.y=data2[ptcnt-i+1].bp.y;
+ else if ( RealNear(slopeend.x/slopeend.y,slopemid.x/slopemid.y) )
+ break;
+ else
+ data2[ptcnt-i].cp.y = -(data2[ptcnt-i+1].bp.x-(slopeend.x/slopeend.y)*data2[ptcnt-i+1].bp.y-mid.x+(slopemid.x/slopemid.y)*mid.y)/(slopeend.x/slopeend.y-slopemid.x/slopemid.y);
+ } else {
+ data2[ptcnt-i].cp.x = 2*data2[ptcnt-i+1].bp.x - data2[ptcnt-i+1].cp.x;
+ data2[ptcnt-i].cp.y = 2*data2[ptcnt-i+1].bp.y - data2[ptcnt-i+1].cp.y;
+ }
+ data2[ptcnt-i].bp = mid;
+ }
+ if ( i==0 )
+ continue;
+ if ( (data2[ptcnt+1].bp.x-data2[ptcnt].bp.x)*(data2[ptcnt].cp.x-data2[ptcnt].bp.x)<0 ||
+ (data2[ptcnt+1].bp.y-data2[ptcnt].bp.y)*(data2[ptcnt].cp.y-data2[ptcnt].bp.y)<0 ) {
+ /* data2 are bad ... don't use them */;
+ } else if ( (data[qcnt-1].bp.x-data[qcnt].bp.x)*(data[qcnt-1].cp.x-data[qcnt].bp.x)<0 ||
+ (data[qcnt-1].bp.y-data[qcnt].bp.y)*(data[qcnt-1].cp.y-data[qcnt].bp.y)<0 ) {
+ /* data are bad */;
+ for ( i=0; i<=ptcnt; ++i ) {
+ data[qcnt+i-1].cp = data2[i].cp;
+ data[qcnt+i-1].bp = data2[i].bp;
+ }
+ } else {
+ for ( i=0; i<=ptcnt; ++i ) {
+ if ( ptcnt!=0 ) {
+ data[qcnt+i-1].cp.x = (data[qcnt+i-1].cp.x*(ptcnt-i) + data2[i].cp.x*i)/ptcnt;
+ data[qcnt+i-1].cp.y = (data[qcnt+i-1].cp.y*(ptcnt-i) + data2[i].cp.y*i)/ptcnt;
+ }
+ }
+ }
+ if ( round_to_int ) {
+ for ( i=0; i<=ptcnt; ++i ) {
+ data[qcnt+i-1].cp.x = rint( data[qcnt+i-1].cp.x );
+ data[qcnt+i-1].cp.y = rint( data[qcnt+i-1].cp.y );
+ }
+ }
+ for ( i=0; i<ptcnt; ++i ) {
+ data[qcnt+i].bp.x = (data[qcnt+i].cp.x + data[qcnt+i-1].cp.x)/2;
+ data[qcnt+i].bp.y = (data[qcnt+i].cp.y + data[qcnt+i-1].cp.y)/2;
+ }
+ if ( comparedata(ps,data,qcnt,q,round_to_int))
+return( q );
+ }
+return( -1 );
+}
+#endif
+
+static SplinePoint *AlreadyQuadraticCheck(Spline *ps, SplinePoint *start) {
+ SplinePoint *sp;
+
+ if ( (RealNearish(ps->splines[0].a,0) && RealNearish(ps->splines[1].a,0)) ||
+ ((ps->splines[0].b!=0 && RealNearish(ps->splines[0].a/ps->splines[0].b,0)) &&
+ (ps->splines[1].b!=0 && RealNearish(ps->splines[1].a/ps->splines[1].b,0))) ) {
+ /* Already Quadratic, just need to find the control point */
+ /* Or linear, in which case we don't need to do much of anything */
+ Spline *spline;
+ sp = chunkalloc(sizeof(SplinePoint));
+ sp->me.x = ps->to->me.x; sp->me.y = ps->to->me.y;
+ sp->roundx = ps->to->roundx; sp->roundy = ps->to->roundy; sp->dontinterpolate = ps->to->dontinterpolate;
+ sp->ttfindex = 0xfffe;
+ sp->nextcpindex = 0xfffe;
+ sp->nonextcp = true;
+ spline = chunkalloc(sizeof(Spline));
+ spline->order2 = true;
+ spline->from = start;
+ spline->to = sp;
+ spline->splines[0] = ps->splines[0]; spline->splines[1] = ps->splines[1];
+ start->next = sp->prev = spline;
+ if ( ps->knownlinear ) {
+ spline->islinear = spline->knownlinear = true;
+ start->nonextcp = sp->noprevcp = true;
+ start->nextcp = start->me;
+ sp->prevcp = sp->me;
+ } else {
+ start->nonextcp = sp->noprevcp = false;
+ start->nextcp.x = sp->prevcp.x = (ps->splines[0].c+2*ps->splines[0].d)/2;
+ start->nextcp.y = sp->prevcp.y = (ps->splines[1].c+2*ps->splines[1].d)/2;
+ }
+return( sp );
+ }
+return( NULL );
+}
+
+static SplinePoint *ttfApprox(Spline *ps, SplinePoint *start) {
+#if !defined(FONTFORGE_CONFIG_NON_SYMMETRIC_QUADRATIC_CONVERSION)
+ extended magicpoints[6], last;
+ int cnt, i, j, qcnt;
+ QPoint data[8*10];
+ int round_to_int =
+ /* The end points are at integer points, or one coord is at half while */
+ /* the other is at an integer (ie. condition for ttf interpolated point)*/
+ ((ps->from->me.x==rint(ps->from->me.x) &&
+ ps->from->me.y==rint(ps->from->me.y)) ||
+ (ps->from->me.x==rint(ps->from->me.x) &&
+ ps->from->me.x==ps->from->nextcp.x &&
+ ps->from->me.y!=ps->from->nextcp.y &&
+ 2*ps->from->me.y==rint(2*ps->from->me.y)) ||
+ (ps->from->me.y==rint(ps->from->me.y) &&
+ ps->from->me.y==ps->from->nextcp.y &&
+ ps->from->me.x!=ps->from->nextcp.x &&
+ 2*ps->from->me.x==rint(2*ps->from->me.x)) ) &&
+ ((ps->to->me.x == rint(ps->to->me.x) &&
+ ps->to->me.y == rint(ps->to->me.y)) ||
+ (ps->to->me.x==rint(ps->to->me.x) &&
+ ps->to->me.x==ps->to->prevcp.x &&
+ ps->to->me.y!=ps->to->prevcp.y &&
+ 2*ps->to->me.y==rint(2*ps->to->me.y)) ||
+ (ps->to->me.y==rint(ps->to->me.y) &&
+ ps->to->me.y==ps->to->prevcp.y &&
+ ps->to->me.x!=ps->to->prevcp.x &&
+ 2*ps->to->me.x==rint(2*ps->to->me.x)) );
+#endif
+ SplinePoint *ret;
+/* Divide the spline up at extrema and points of inflection. The first */
+/* because ttf splines should have points at their extrema, the second */
+/* because quadratic splines can't have points of inflection. */
+/* Let's not do the first (extrema) AddExtrema does this better and we */
+/* don't want unneeded extrema. */
+/* And sometimes we don't want to look at the points of inflection either*/
+
+ if (( ret = AlreadyQuadraticCheck(ps,start))!=NULL )
+return( ret );
+
+#if !defined(FONTFORGE_CONFIG_NON_SYMMETRIC_QUADRATIC_CONVERSION)
+ qcnt = 1;
+ data[0].bp = ps->from->me;
+ data[0].t = 0;
+ qcnt = PrettyApprox(ps,0,1,data,qcnt,round_to_int);
+ if ( qcnt!=-1 )
+return( CvtDataToSplines(data,1,qcnt,start));
+
+ cnt = 0;
+ /* cnt = Spline2DFindExtrema(ps,magicpoints);*/
+
+ cnt += Spline2DFindPointsOfInflection(ps,magicpoints+cnt);
+
+ /* remove points outside range */
+ for ( i=0; i<cnt; ++i ) {
+ if ( magicpoints[i]<=0 || magicpoints[i]>=1 ) {
+ for ( j=i+1; j<cnt; ++j )
+ magicpoints[j-1] = magicpoints[j];
+ --cnt;
+ --i;
+ }
+ }
+ /* sort points */
+ for ( i=0; i<cnt; ++i ) for ( j=i+1; j<cnt; ++j ) {
+ if ( magicpoints[i]>magicpoints[j] ) {
+ double temp = magicpoints[i];
+ magicpoints[i] = magicpoints[j];
+ magicpoints[j] = temp;
+ }
+ }
+ /* Remove duplicates */
+ for ( i=1; i<cnt; ++i ) {
+ while ( i<cnt && RealNear(magicpoints[i-1],magicpoints[i])) {
+ --cnt;
+ for ( j=i ; j<cnt; ++j )
+ magicpoints[j] = magicpoints[j+1];
+ magicpoints[cnt] = -1;
+ }
+ }
+
+ qcnt = 1;
+ last = 0;
+ for ( i=0; i<cnt; ++i ) {
+ qcnt = PrettyApprox(ps,last,magicpoints[i],data,qcnt,round_to_int);
+ last = magicpoints[i];
+ }
+ qcnt = PrettyApprox(ps,last,1,data,qcnt,round_to_int);
+ if ( qcnt!=-1 )
+return( CvtDataToSplines(data,1,qcnt,start));
+#endif
+
+return( __ttfApprox(ps,0,1,start));
+}
+
+static void ttfCleanup(SplinePoint *from) {
+ SplinePoint *test, *next;
+
+ for ( test = from; test->next!=NULL; test = next ) {
+ next = test->next->to;
+ /* Too close together to be meaningful when output as ttf */
+ if ( rint(test->me.x) == rint(next->me.x) &&
+ rint(test->me.y) == rint(next->me.y) ) {
+ if ( next->next==NULL || next==from ) {
+ if ( test==from )
+ break;
+ next->prevcp = test->prevcp;
+ next->noprevcp = test->noprevcp;
+ next->prev = test->prev;
+ next->prev->to = next;
+ SplineFree(test->next);
+ SplinePointFree(test);
+ } else {
+ test->nextcp = next->nextcp;
+ test->nonextcp = next->nonextcp;
+ test->next = next->next;
+ test->next->from = test;
+ SplineFree(next->prev);
+ SplinePointFree(next);
+ next = test->next->to;
+ }
+ }
+ if ( next==from )
+ break;
+ }
+}
+
+SplinePoint *SplineTtfApprox(Spline *ps) {
+ SplinePoint *from;
+ from = chunkalloc(sizeof(SplinePoint));
+ *from = *ps->from;
+ from->hintmask = NULL;
+ ttfApprox(ps,from);
+return( from );
+}
+
+SplineSet *SSttfApprox(SplineSet *ss) {
+ SplineSet *ret = chunkalloc(sizeof(SplineSet));
+ Spline *spline, *first;
+
+ ret->first = chunkalloc(sizeof(SplinePoint));
+ *ret->first = *ss->first;
+ if ( ret->first->hintmask != NULL ) {
+ ret->first->hintmask = chunkalloc(sizeof(HintMask));
+ memcpy(ret->first->hintmask,ss->first->hintmask,sizeof(HintMask));
+ }
+ ret->last = ret->first;
+
+ first = NULL;
+ for ( spline=ss->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) {
+ ret->last = ttfApprox(spline,ret->last);
+ if ( spline->to->hintmask != NULL ) {
+ ret->last->hintmask = chunkalloc(sizeof(HintMask));
+ memcpy(ret->last->hintmask,spline->to->hintmask,sizeof(HintMask));
+ }
+ if ( first==NULL ) first = spline;
+ }
+ if ( ss->first==ss->last ) {
+ if ( ret->last!=ret->first ) {
+ ret->first->prevcp = ret->last->prevcp;
+ ret->first->noprevcp = ret->last->noprevcp;
+ ret->first->prev = ret->last->prev;
+ ret->last->prev->to = ret->first;
+ SplinePointFree(ret->last);
+ ret->last = ret->first;
+ }
+ }
+ ttfCleanup(ret->first);
+ SPLCatagorizePoints(ret);
+return( ret );
+}
+
+SplineSet *SplineSetsTTFApprox(SplineSet *ss) {
+ SplineSet *head=NULL, *last=NULL, *cur;
+
+ while ( ss!=NULL ) {
+ cur = SSttfApprox(ss);
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ ss = ss->next;
+ }
+return( head );
+}
+
+SplineSet *SSPSApprox(SplineSet *ss) {
+ SplineSet *ret = chunkalloc(sizeof(SplineSet));
+ Spline *spline, *first;
+ SplinePoint *to;
+
+ ret->first = chunkalloc(sizeof(SplinePoint));
+ *ret->first = *ss->first;
+ if ( ret->first->hintmask != NULL ) {
+ ret->first->hintmask = chunkalloc(sizeof(HintMask));
+ memcpy(ret->first->hintmask,ss->first->hintmask,sizeof(HintMask));
+ }
+ ret->last = ret->first;
+
+ first = NULL;
+ for ( spline=ss->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) {
+ to = chunkalloc(sizeof(SplinePoint));
+ *to = *spline->to;
+ if ( to->hintmask != NULL ) {
+ to->hintmask = chunkalloc(sizeof(HintMask));
+ memcpy(to->hintmask,spline->to->hintmask,sizeof(HintMask));
+ }
+ if ( !spline->knownlinear ) {
+ ret->last->nextcp.x = spline->splines[0].c/3 + ret->last->me.x;
+ ret->last->nextcp.y = spline->splines[1].c/3 + ret->last->me.y;
+ to->prevcp.x = ret->last->nextcp.x+ (spline->splines[0].b+spline->splines[0].c)/3;
+ to->prevcp.y = ret->last->nextcp.y+ (spline->splines[1].b+spline->splines[1].c)/3;
+ }
+ SplineMake3(ret->last,to);
+ ret->last = to;
+ if ( first==NULL ) first = spline;
+ }
+ if ( ss->first==ss->last ) {
+ if ( ret->last!=ret->first ) {
+ ret->first->prevcp = ret->last->prevcp;
+ ret->first->noprevcp = ret->last->noprevcp;
+ ret->first->prev = ret->last->prev;
+ ret->last->prev->to = ret->first;
+ SplinePointFree(ret->last);
+ ret->last = ret->first;
+ }
+ }
+return( ret );
+}
+
+SplineSet *SplineSetsPSApprox(SplineSet *ss) {
+ SplineSet *head=NULL, *last=NULL, *cur;
+
+ while ( ss!=NULL ) {
+ cur = SSPSApprox(ss);
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ ss = ss->next;
+ }
+return( head );
+}
+
+SplineSet *SplineSetsConvertOrder(SplineSet *ss, int to_order2) {
+ SplineSet *new;
+
+ if ( to_order2 )
+ new = SplineSetsTTFApprox(ss);
+ else
+ new = SplineSetsPSApprox(ss);
+ SplinePointListsFree(ss);
+return( new );
+}
+
+void SCConvertToOrder2(SplineChar *sc) {
+ SplineSet *new;
+
+ if ( sc==NULL )
+return;
+
+ new = SplineSetsTTFApprox(sc->layers[ly_fore].splines);
+ SplinePointListsFree(sc->layers[ly_fore].splines);
+ sc->layers[ly_fore].splines = new;
+
+ new = SplineSetsTTFApprox(sc->layers[ly_back].splines);
+ SplinePointListsFree(sc->layers[ly_back].splines);
+ sc->layers[ly_back].splines = new;
+
+ UndoesFree(sc->layers[ly_fore].undoes); UndoesFree(sc->layers[ly_back].undoes);
+ UndoesFree(sc->layers[ly_fore].redoes); UndoesFree(sc->layers[ly_back].redoes);
+ sc->layers[ly_fore].undoes = sc->layers[ly_back].undoes = NULL;
+ sc->layers[ly_fore].redoes = sc->layers[ly_back].redoes = NULL;
+
+ MinimumDistancesFree(sc->md); sc->md = NULL;
+}
+
+static void SCConvertRefs(SplineChar *sc) {
+ RefChar *rf;
+
+ sc->ticked = true;
+ for ( rf=sc->layers[ly_fore].refs; rf!=NULL; rf=rf->next ) {
+ if ( !rf->sc->ticked )
+ SCConvertRefs(rf->sc);
+ SCReinstanciateRefChar(sc,rf); /* Conversion is done by reinstanciating */
+ /* Since the base thing will have been converted, all we do is copy its data */
+ }
+}
+
+void SFConvertToOrder2(SplineFont *_sf) {
+ int i, k;
+ SplineSet *new;
+ SplineFont *sf;
+
+ if ( _sf->cidmaster!=NULL ) _sf=_sf->cidmaster;
+ k = 0;
+ do {
+ sf = _sf->subfonts==NULL ? _sf : _sf->subfonts[k];
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ SCConvertToOrder2(sf->glyphs[i]);
+ sf->glyphs[i]->ticked = false;
+ sf->glyphs[i]->changedsincelasthinted = false;
+ }
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL && !sf->glyphs[i]->ticked )
+ SCConvertRefs(sf->glyphs[i]);
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ SCNumberPoints(sf->glyphs[i]);
+
+ new = SplineSetsTTFApprox(sf->grid.splines);
+ SplinePointListsFree(sf->grid.splines);
+ sf->grid.splines = new;
+
+ UndoesFree(sf->grid.undoes); UndoesFree(sf->grid.redoes);
+ sf->grid.undoes = sf->grid.redoes = NULL;
+ sf->order2 = true;
+ ++k;
+ } while ( k<_sf->subfontcnt );
+ _sf->order2 = true;
+}
+
+void SCConvertToOrder3(SplineChar *sc) {
+ SplineSet *new;
+ RefChar *ref;
+ AnchorPoint *ap;
+
+ new = SplineSetsPSApprox(sc->layers[ly_fore].splines);
+ SplinePointListsFree(sc->layers[ly_fore].splines);
+ sc->layers[ly_fore].splines = new;
+
+ new = SplineSetsPSApprox(sc->layers[ly_back].splines);
+ SplinePointListsFree(sc->layers[ly_back].splines);
+ sc->layers[ly_back].splines = new;
+
+ UndoesFree(sc->layers[ly_fore].undoes); UndoesFree(sc->layers[ly_back].undoes);
+ UndoesFree(sc->layers[ly_fore].redoes); UndoesFree(sc->layers[ly_back].redoes);
+ sc->layers[ly_fore].undoes = sc->layers[ly_back].undoes = NULL;
+ sc->layers[ly_fore].redoes = sc->layers[ly_back].redoes = NULL;
+
+ MinimumDistancesFree(sc->md); sc->md = NULL;
+
+ /* OpenType/PostScript fonts don't support point matching to position */
+ /* references or anchors */
+ for ( ref = sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next )
+ ref->point_match = false;
+ for ( ap = sc->anchor; ap!=NULL; ap=ap->next )
+ ap->has_ttf_pt = false;
+
+ free(sc->ttf_instrs);
+ sc->ttf_instrs = NULL; sc->ttf_instrs_len = 0;
+ /* If this character has any cv's showing instructions then remove the instruction pane!!!!! */
+}
+
+void SCConvertOrder(SplineChar *sc, int to_order2) {
+ if ( to_order2 )
+ SCConvertToOrder2(sc);
+ else
+ SCConvertToOrder3(sc);
+}
+
+void SFConvertToOrder3(SplineFont *_sf) {
+ int i, k;
+ SplineSet *new;
+ SplineFont *sf;
+
+ if ( _sf->cidmaster!=NULL ) _sf=_sf->cidmaster;
+ k = 0;
+ do {
+ sf = _sf->subfonts==NULL ? _sf : _sf->subfonts[k];
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ SCConvertToOrder3(sf->glyphs[i]);
+ sf->glyphs[i]->ticked = false;
+ sf->glyphs[i]->changedsincelasthinted = true;
+ }
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL && !sf->glyphs[i]->ticked )
+ SCConvertRefs(sf->glyphs[i]);
+
+ new = SplineSetsPSApprox(sf->grid.splines);
+ SplinePointListsFree(sf->grid.splines);
+ sf->grid.splines = new;
+
+ UndoesFree(sf->grid.undoes); UndoesFree(sf->grid.redoes);
+ sf->grid.undoes = sf->grid.redoes = NULL;
+
+ TtfTablesFree(sf->ttf_tables);
+ sf->ttf_tables = NULL;
+
+ sf->order2 = false;
+ ++k;
+ } while ( k<_sf->subfontcnt );
+ _sf->order2 = false;
+}
+
+/* ************************************************************************** */
+
+void SplineRefigure2(Spline *spline) {
+ SplinePoint *from = spline->from, *to = spline->to;
+ Spline1D *xsp = &spline->splines[0], *ysp = &spline->splines[1];
+
+#ifdef DEBUG
+ if ( RealNear(from->me.x,to->me.x) && RealNear(from->me.y,to->me.y))
+ IError("Zero length spline created");
+#endif
+
+ if ( from->nonextcp || to->noprevcp ||
+ ( from->nextcp.x==from->me.x && from->nextcp.y == from->me.y ) ||
+ ( to->prevcp.x==to->me.x && to->prevcp.y == to->me.y )) {
+ from->nonextcp = to->noprevcp = true;
+ from->nextcp = from->me;
+ to->prevcp = to->me;
+ }
+
+ if ( from->nonextcp && to->noprevcp )
+ /* Ok */;
+ else if ( from->nonextcp || to->noprevcp || from->nextcp.x!=to->prevcp.x ||
+ from->nextcp.y!=to->prevcp.y ) {
+ if ( RealNear(from->nextcp.x,to->prevcp.x) &&
+ RealNear(from->nextcp.y,to->prevcp.y)) {
+ from->nextcp.x = to->prevcp.x = (from->nextcp.x+to->prevcp.x)/2;
+ from->nextcp.y = to->prevcp.y = (from->nextcp.y+to->prevcp.y)/2;
+ } else
+ IError("Invalid 2nd order spline in SplineRefigure2" );
+ }
+
+ xsp->d = from->me.x; ysp->d = from->me.y;
+ if ( from->nonextcp && to->noprevcp ) {
+ spline->islinear = true;
+ xsp->c = to->me.x-from->me.x;
+ ysp->c = to->me.y-from->me.y;
+ xsp->a = xsp->b = 0;
+ ysp->a = ysp->b = 0;
+ } else {
+ /* from p. 393 (Operator Details, curveto) Postscript Lang. Ref. Man. (Red book) */
+ xsp->c = 2*(from->nextcp.x-from->me.x);
+ ysp->c = 2*(from->nextcp.y-from->me.y);
+ xsp->b = to->me.x-from->me.x-xsp->c;
+ ysp->b = to->me.y-from->me.y-ysp->c;
+ xsp->a = 0;
+ ysp->a = 0;
+ if ( RealNear(xsp->c,0)) xsp->c=0;
+ if ( RealNear(ysp->c,0)) ysp->c=0;
+ if ( RealNear(xsp->b,0)) xsp->b=0;
+ if ( RealNear(ysp->b,0)) ysp->b=0;
+ spline->islinear = false;
+ if ( ysp->b==0 && xsp->b==0 )
+ spline->islinear = true; /* This seems extremely unlikely... */
+ }
+ if ( isnan(ysp->b) || isnan(xsp->b) )
+ IError("NaN value in spline creation");
+ LinearApproxFree(spline->approx);
+ spline->approx = NULL;
+ spline->knowncurved = false;
+ spline->knownlinear = spline->islinear;
+ SplineIsLinear(spline);
+ spline->isquadratic = !spline->knownlinear;
+ spline->order2 = true;
+}
+
+void SplineRefigure(Spline *spline) {
+ if ( spline==NULL )
+return;
+ if ( spline->order2 )
+ SplineRefigure2(spline);
+ else
+ SplineRefigure3(spline);
+}
+
+void SplineRefigureFixup(Spline *spline) {
+ SplinePoint *from, *to, *prev, *next;
+ BasePoint foff, toff, unit, new;
+ double len;
+
+ if ( !spline->order2 ) {
+ SplineRefigure3(spline);
+return;
+ }
+ from = spline->from; to = spline->to;
+
+ unit.x = from->nextcp.x-from->me.x;
+ unit.y = from->nextcp.y-from->me.y;
+ len = sqrt(unit.x*unit.x + unit.y*unit.y);
+ if ( len!=0 )
+ unit.x /= len; unit.y /= len;
+
+ if ( from->nextcpdef && to->prevcpdef ) switch ( from->pointtype*3+to->pointtype ) {
+ case pt_corner*3+pt_corner:
+ case pt_corner*3+pt_tangent:
+ case pt_tangent*3+pt_corner:
+ case pt_tangent*3+pt_tangent:
+ from->nonextcp = to->noprevcp = true;
+ from->nextcp = from->me;
+ to->prevcp = to->me;
+ break;
+ case pt_curve*3+pt_curve:
+ case pt_curve*3+pt_corner:
+ case pt_corner*3+pt_curve:
+ case pt_tangent*3+pt_curve:
+ case pt_curve*3+pt_tangent:
+ if ( from->prev!=NULL && from->pointtype==pt_tangent ) {
+ prev = from->prev->from;
+ foff.x = prev->me.x;
+ foff.y = prev->me.y;
+ } else if ( from->prev!=NULL ) {
+ prev = from->prev->from;
+ foff.x = to->me.x-prev->me.x + from->me.x;
+ foff.y = to->me.y-prev->me.y + from->me.y;
+ } else {
+ foff.x = from->me.x + (to->me.x-from->me.x)-(to->me.y-from->me.y);
+ foff.y = from->me.y + (to->me.x-from->me.x)+(to->me.y-from->me.y);
+ prev = NULL;
+ }
+ if ( to->next!=NULL && to->pointtype==pt_tangent ) {
+ next = to->next->to;
+ toff.x = next->me.x;
+ toff.y = next->me.y;
+ } else if ( to->next!=NULL ) {
+ next = to->next->to;
+ toff.x = next->me.x-from->me.x + to->me.x;
+ toff.y = next->me.y-from->me.y + to->me.y;
+ } else {
+ toff.x = to->me.x + (to->me.x-from->me.x)+(to->me.y-from->me.y);
+ toff.y = to->me.y - (to->me.x-from->me.x)+(to->me.y-from->me.y);
+ next = NULL;
+ }
+ if ( IntersectLinesClip(&from->nextcp,&foff,&from->me,&toff,&to->me)) {
+ from->nonextcp = to->noprevcp = false;
+ to->prevcp = from->nextcp;
+ if ( from->pointtype==pt_curve && !from->noprevcp && from->prev!=NULL ) {
+ prev = from->prev->from;
+ if ( IntersectLinesClip(&from->prevcp,&from->nextcp,&from->me,&prev->nextcp,&prev->me)) {
+ prev->nextcp = from->prevcp;
+ SplineRefigure2(from->prev);
+ }
+ }
+ if ( to->pointtype==pt_curve && !to->nonextcp && to->next!=NULL ) {
+ next = to->next->to;
+ if ( IntersectLinesClip(&to->nextcp,&to->prevcp,&to->me,&next->prevcp,&next->me)) {
+ next->prevcp = to->nextcp;
+ SplineRefigure(to->next);
+ }
+ }
+ }
+ break;
+ } else {
+ /* Can't set things arbetrarily here, but make sure they are consistant */
+ if ( from->pointtype==pt_curve && !from->noprevcp && !from->nonextcp ) {
+ unit.x = from->nextcp.x-from->me.x;
+ unit.y = from->nextcp.y-from->me.y;
+ len = sqrt(unit.x*unit.x + unit.y*unit.y);
+ if ( len!=0 ) {
+ unit.x /= len; unit.y /= len;
+ len = sqrt((from->prevcp.x-from->me.x)*(from->prevcp.x-from->me.x) + (from->prevcp.y-from->me.y)*(from->prevcp.y-from->me.y));
+ new.x = -len*unit.x + from->me.x; new.y = -len*unit.y + from->me.y;
+ if ( new.x-from->prevcp.x<-1 || new.x-from->prevcp.x>1 ||
+ new.y-from->prevcp.y<-1 || new.y-from->prevcp.y>1 ) {
+ prev = NULL;
+ if ( from->prev!=NULL && (prev = from->prev->from)!=NULL &&
+ IntersectLinesClip(&from->prevcp,&new,&from->me,&prev->nextcp,&prev->me)) {
+ prev->nextcp = from->prevcp;
+ SplineRefigure2(from->prev);
+ } else {
+ from->prevcp = new;
+ if ( prev!=NULL )
+ prev->nextcp = new;
+ }
+ }
+ }
+ } else if ( from->pointtype==pt_tangent ) {
+ if ( from->prev!=NULL ) {
+ prev = from->prev->from;
+ if ( !from->noprevcp && !prev->nonextcp &&
+ IntersectLinesClip(&from->prevcp,&to->me,&from->me,&prev->nextcp,&prev->me)) {
+ prev->nextcp = from->prevcp;
+ SplineRefigure2(from->prev);
+ }
+ if ( !from->nonextcp && !to->noprevcp &&
+ IntersectLinesClip(&from->nextcp,&prev->me,&from->me,&to->prevcp,&to->me))
+ to->prevcp = from->nextcp;
+ }
+ }
+ if ( to->pointtype==pt_curve && !to->noprevcp && !to->nonextcp ) {
+ unit.x = to->prevcp.x-to->nextcp.x;
+ unit.y = to->prevcp.y-to->nextcp.y;
+ len = sqrt(unit.x*unit.x + unit.y*unit.y);
+ if ( len!=0 ) {
+ unit.x /= len; unit.y /= len;
+ len = sqrt((to->nextcp.x-to->me.x)*(to->nextcp.x-to->me.x) + (to->nextcp.y-to->me.y)*(to->nextcp.y-to->me.y));
+ new.x = -len*unit.x + to->me.x; new.y = -len*unit.y + to->me.y;
+ if ( new.x-to->nextcp.x<-1 || new.x-to->nextcp.x>1 ||
+ new.y-to->nextcp.y<-1 || new.y-to->nextcp.y>1 ) {
+ if ( to->next!=NULL && (next = to->next->to)!=NULL &&
+ IntersectLinesClip(&to->nextcp,&new,&to->me,&next->prevcp,&next->me)) {
+ next->prevcp = to->nextcp;
+ SplineRefigure2(to->next);
+ } else {
+ to->nextcp = new;
+ if ( to->next!=NULL ) {
+ to->next->to->prevcp = new;
+ SplineRefigure(to->next);
+ }
+ }
+ }
+ }
+ } else if ( to->pointtype==pt_tangent ) {
+ if ( to->next!=NULL ) {
+ next = to->next->to;
+ if ( !to->nonextcp && !next->noprevcp &&
+ IntersectLinesClip(&to->nextcp,&from->me,&to->me,&next->prevcp,&next->me)) {
+ next->prevcp = to->nextcp;
+ SplineRefigure2(to->next);
+ }
+ if ( !from->nonextcp && !to->noprevcp &&
+ IntersectLinesClip(&from->nextcp,&next->me,&to->me,&from->nextcp,&from->me))
+ to->prevcp = from->nextcp;
+ }
+ }
+ }
+ if ( from->nonextcp && to->noprevcp )
+ /* Ok */;
+ else if ( from->nonextcp || to->noprevcp ) {
+ from->nonextcp = to->noprevcp = true;
+ } else if (( from->nextcp.x==from->me.x && from->nextcp.y==from->me.y ) ||
+ ( to->prevcp.x==to->me.x && to->prevcp.y==to->me.y ) ) {
+ from->nonextcp = to->noprevcp = true;
+ } else if ( from->nonextcp || to->noprevcp || from->nextcp.x!=to->prevcp.x ||
+ from->nextcp.y!=to->prevcp.y ) {
+ if ( !IntersectLinesClip(&from->nextcp,
+ (from->pointtype==pt_tangent && from->prev!=NULL)?&from->prev->from->me:&from->nextcp, &from->me,
+ (to->pointtype==pt_tangent && to->next!=NULL)?&to->next->to->me:&to->prevcp, &to->me)) {
+ from->nextcp.x = (from->me.x+to->me.x)/2;
+ from->nextcp.y = (from->me.y+to->me.y)/2;
+ }
+ to->prevcp = from->nextcp;
+ if (( from->nextcp.x==from->me.x && from->nextcp.y==from->me.y ) ||
+ ( to->prevcp.x==to->me.x && to->prevcp.y==to->me.y ) ) {
+ from->nonextcp = to->noprevcp = true;
+ from->nextcp = from->me;
+ to->prevcp = to->me;
+ }
+ }
+ SplineRefigure2(spline);
+}
+
+Spline *SplineMake2(SplinePoint *from, SplinePoint *to) {
+ Spline *spline = chunkalloc(sizeof(Spline));
+
+ spline->from = from; spline->to = to;
+ from->next = to->prev = spline;
+ spline->order2 = true;
+ SplineRefigure2(spline);
+return( spline );
+}
+
+Spline *SplineMake(SplinePoint *from, SplinePoint *to, int order2) {
+ if ( order2 )
+return( SplineMake2(from,to));
+ else
+return( SplineMake3(from,to));
+}
+
+int IntersectLines(BasePoint *inter,
+ BasePoint *line1_1, BasePoint *line1_2,
+ BasePoint *line2_1, BasePoint *line2_2) {
+ double s1, s2;
+
+ if ( line1_1->x == line1_2->x ) {
+ inter->x = line1_1->x;
+ if ( line2_1->x == line2_2->x ) {
+ if ( line2_1->x!=line1_1->x )
+return( false ); /* Parallel vertical lines */
+ inter->y = (line1_1->y+line2_1->y)/2;
+ } else
+ inter->y = line2_1->y + (inter->x-line2_1->x) * (line2_2->y - line2_1->y)/(line2_2->x - line2_1->x);
+return( true );
+ } else if ( line2_1->x == line2_2->x ) {
+ inter->x = line2_1->x;
+ inter->y = line1_1->y + (inter->x-line1_1->x) * (line1_2->y - line1_1->y)/(line1_2->x - line1_1->x);
+return( true );
+ } else {
+ s1 = (line1_2->y - line1_1->y)/(line1_2->x - line1_1->x);
+ s2 = (line2_2->y - line2_1->y)/(line2_2->x - line2_1->x);
+ if ( RealNear(s1,s2)) {
+ if ( !RealNear(line1_1->y + (line2_1->x-line1_1->x) * s1,line2_1->y))
+return( false );
+ inter->x = (line1_2->x+line2_2->x)/2;
+ inter->y = (line1_2->y+line2_2->y)/2;
+ } else {
+ inter->x = (s1*line1_1->x - s2*line2_1->x - line1_1->y + line2_1->y)/(s1-s2);
+ inter->y = line1_1->y + (inter->x-line1_1->x) * s1;
+ }
+return( true );
+ }
+}
+
+int IntersectLinesClip(BasePoint *inter,
+ BasePoint *line1_1, BasePoint *line1_2,
+ BasePoint *line2_1, BasePoint *line2_2) {
+ BasePoint old = *inter, unit;
+ double len, val;
+
+ if ( !IntersectLines(inter,line1_1,line1_2,line2_1,line2_2))
+return( false );
+ else {
+ unit.x = line2_2->x-line1_2->x;
+ unit.y = line2_2->y-line1_2->y;
+ len = sqrt(unit.x*unit.x + unit.y*unit.y);
+ if ( len==0 )
+return( false );
+ else {
+ unit.x /= len; unit.y /= len;
+ val = unit.x*(inter->x-line1_2->x) + unit.y*(inter->y-line1_2->y);
+ if ( val<=0 || val>=len ) {
+ *inter = old;
+return( false );
+ }
+ }
+ }
+return( true );
+}
+
+void SplinePointPrevCPChanged2(SplinePoint *sp) {
+ SplinePoint *p, *pp;
+ BasePoint p_pcp;
+
+ if ( sp->prev!=NULL ) {
+ p = sp->prev->from;
+ if ( SPInterpolate(p) && !sp->noprevcp ) {
+ p->nextcp = sp->prevcp;
+ p->me.x = ( p->prevcp.x+p->nextcp.x)/2;
+ p->me.y = ( p->prevcp.y+p->nextcp.y)/2;
+ SplineRefigure2(sp->prev);
+ if (p->prev != NULL) SplineRefigure2(p->prev);
+ } else {
+ p->nextcp = sp->prevcp;
+ p->nonextcp = sp->noprevcp;
+ if ( sp->noprevcp ) {
+ p->nonextcp = true;
+ p->nextcp = p->me;
+ SplineRefigure2(sp->prev);
+ } else if ( p->pointtype==pt_curve && !p->noprevcp ) {
+ SplineRefigure2(sp->prev);
+ if ( p->prev==NULL ) {
+ double len1, len2;
+ len1 = sqrt((p->nextcp.x-p->me.x)*(p->nextcp.x-p->me.x) +
+ (p->nextcp.y-p->me.y)*(p->nextcp.y-p->me.y));
+ len2 = sqrt((p->prevcp.x-p->me.x)*(p->prevcp.x-p->me.x) +
+ (p->prevcp.y-p->me.y)*(p->prevcp.y-p->me.y));
+ len2 /= len1;
+ p->prevcp.x = len2 * (p->me.x-p->prevcp.x) + p->me.x;
+ p->prevcp.y = len2 * (p->me.y-p->prevcp.y) + p->me.y;
+ } else {
+ pp = p->prev->from;
+ /* Find the intersection (if any) of the lines between */
+ /* pp->nextcp&pp->me with p->prevcp&p->me */
+ if ( IntersectLines(&p_pcp,&pp->nextcp,&pp->me,&p->nextcp,&p->me)) {
+ double len = (pp->me.x-p->me.x)*(pp->me.x-p->me.x) + (pp->me.y-p->me.y)*(pp->me.y-p->me.y);
+ double d1 = (p_pcp.x-p->me.x)*(pp->me.x-p->me.x) + (p_pcp.y-p->me.y)*(pp->me.y-p->me.y);
+ double d2 = (p_pcp.x-pp->me.x)*(p->me.x-pp->me.x) + (p_pcp.y-pp->me.y)*(p->me.y-pp->me.y);
+ if ( d1>=0 && d1<=len && d2>=0 && d2<=len ) {
+ p->prevcp = pp->nextcp = p_pcp;
+ SplineRefigure2(p->prev);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void SplinePointNextCPChanged2(SplinePoint *sp) {
+ SplinePoint *n, *nn;
+ BasePoint n_ncp;
+
+ if ( sp->next!=NULL ) {
+ n = sp->next->to;
+ if ( SPInterpolate(n) && !sp->nonextcp ) {
+ n->prevcp = sp->nextcp;
+ n->me.x = ( n->prevcp.x+n->nextcp.x)/2;
+ n->me.y = ( n->prevcp.y+n->nextcp.y)/2;
+ SplineRefigure2(sp->next);
+ if (n->next != NULL) SplineRefigure2(n->next);
+ } else {
+ n->prevcp = sp->nextcp;
+ n->noprevcp = sp->nonextcp;
+ if ( sp->nonextcp ) {
+ n->noprevcp = true;
+ n->prevcp = n->me;
+ SplineRefigure2(sp->next);
+ } else if ( n->pointtype==pt_curve && !n->nonextcp ) {
+ SplineRefigure2(sp->next);
+ if ( n->next==NULL ) {
+ double len1, len2;
+ len1 = sqrt((n->prevcp.x-n->me.x)*(n->prevcp.x-n->me.x) +
+ (n->prevcp.y-n->me.y)*(n->prevcp.y-n->me.y));
+ len2 = sqrt((n->nextcp.x-n->me.x)*(n->nextcp.x-n->me.x) +
+ (n->nextcp.y-n->me.y)*(n->nextcp.y-n->me.y));
+ len2 /= len1;
+ n->nextcp.x = len2 * (n->me.x-n->nextcp.x) + n->me.x;
+ n->nextcp.y = len2 * (n->me.y-n->nextcp.y) + n->me.y;
+ } else {
+ nn = n->next->to;
+ /* Find the intersection (if any) of the lines between */
+ /* nn->prevcp&nn->me with n->nextcp&.->me */
+ if ( IntersectLines(&n_ncp,&nn->prevcp,&nn->me,&n->prevcp,&n->me)) {
+ double len = (nn->me.x-n->me.x)*(nn->me.x-n->me.x) + (nn->me.y-n->me.y)*(nn->me.y-n->me.y);
+ double d1 = (n_ncp.x-n->me.x)*(nn->me.x-n->me.x) + (n_ncp.y-n->me.y)*(nn->me.y-n->me.y);
+ double d2 = (n_ncp.x-nn->me.x)*(n->me.x-nn->me.x) + (n_ncp.y-nn->me.y)*(n->me.y-nn->me.y);
+ if ( d1>=0 && d1<=len && d2>=0 && d2<=len ) {
+ n->nextcp = nn->prevcp = n_ncp;
+ SplineRefigure2(n->next);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/splineoverlap.c b/Build/source/libs/luafontforge/fontforge/fontforge/splineoverlap.c
new file mode 100644
index 00000000000..62a6e4267f1
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/splineoverlap.c
@@ -0,0 +1,2527 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include "splinefont.h"
+#include "edgelist2.h"
+#include <math.h>
+#ifdef HAVE_IEEEFP_H
+# include <ieeefp.h> /* Solaris defines isnan in ieeefp rather than math.h */
+#endif
+#include <stdarg.h>
+
+#include <gwidget.h> /* For PostNotice */
+
+/* First thing we do is divide each spline into a set of sub-splines each of */
+/* which is monotonic in both x and y (always increasing or decreasing) */
+/* Then we compare each monotonic spline with every other one and see if they*/
+/* intersect. If they do, split each up into sub-sub-segments and create an*/
+/* intersection point (note we need to be a little careful if an intersec- */
+/* tion happens at an end point. We don't need to create a intersection for */
+/* two adjacent splines, there isn't a real intersection... but if a third */
+/* spline crosses that point (or ends there) then all three (four) splines */
+/* need to be joined into an intersection point) */
+/* Nasty things happen if splines are coincident. They will almost never be */
+/* perfectly coincident and will keep crossing and recrossing as rounding */
+/* errors suggest one is before the other. Look for coincident splines and */
+/* treat the places they start and stop being coincident as intersections */
+/* then when we find needed splines below look for these guys and ignore */
+/* recrossings of splines which are close together */
+/* Figure out if each monotonic sub-spline is needed or not */
+/* (Note: It was tempting to split the bits up into real splines rather */
+/* than keeping them as sub-sections of the original. Unfortunately this */
+/* splitting introduced rounding errors which meant that we got more */
+/* intersections, which meant that splines could be both needed and un. */
+/* so I don't do that until later) */
+/* if the spline hasn't been tagged yet: */
+/* does the spline change greater in x or y? */
+/* draw a line parallel to the OTHER axis which hits our spline and doesn't*/
+/* hit any endpoints (or intersections, which are end points too now) */
+/* count the winding number (as we do this we can mark other splines as */
+/* needed or not) and figure out if our spline is needed */
+/* So run through the list of intersections */
+/* At an intersection there should be an even number of needed monos. */
+/* Use this as the basis of a new splineset, trace it around until */
+/* we get back to the start intersection (should happen) */
+/* (Note: We may need to reverse a monotonic sub-spline or two) */
+/* As we go, mark each monotonic as having been used */
+/* Keep doing this until all needed exits from all intersections have been */
+/* used. */
+/* The free up our temporary data structures, merge in any open splinesets */
+/* free the old closed splinesets */
+
+typedef struct mlist {
+ Spline *s;
+ Monotonic *m; /* May get slightly munched but will */
+ /* always have right spline. we fix when we need it */
+ extended t;
+ int isend;
+ BasePoint unit;
+ struct mlist *next;
+} MList;
+
+typedef struct intersection {
+ MList *monos;
+ BasePoint inter;
+ struct intersection *next;
+} Intersection;
+
+static char *glyphname=NULL;
+
+static void SOError(char *format,...) {
+ va_list ap;
+ va_start(ap,format);
+ if ( glyphname==NULL )
+ fprintf(stderr, "Internal Error: " );
+ else
+ fprintf(stderr, "Internal Error in %s: ", glyphname );
+ vfprintf(stderr,format,ap);
+}
+
+static Monotonic *SplineToMonotonic(Spline *s,extended startt,extended endt,
+ Monotonic *last,int exclude) {
+ Monotonic *m;
+ BasePoint start, end;
+
+ start.x = ((s->splines[0].a*startt+s->splines[0].b)*startt+s->splines[0].c)*startt
+ + s->splines[0].d;
+ start.y = ((s->splines[1].a*startt+s->splines[1].b)*startt+s->splines[1].c)*startt
+ + s->splines[1].d;
+ end.x = ((s->splines[0].a*endt+s->splines[0].b)*endt+s->splines[0].c)*endt
+ + s->splines[0].d;
+ end.y = ((s->splines[1].a*endt+s->splines[1].b)*endt+s->splines[1].c)*endt
+ + s->splines[1].d;
+ if ( (real) (((start.x+end.x)/2)==start.x || (real) ((start.x+end.x)/2)==end.x) &&
+ (real) (((start.y+end.y)/2)==start.y || (real) ((start.y+end.y)/2)==end.y) ) {
+ /* The distance between the two extrema is so small */
+ /* as to be unobservable. In other words we'd end up with a zero*/
+ /* length spline */
+ if ( endt==1.0 && last!=NULL && last->s==s )
+ last->tend = endt;
+return( last );
+ }
+
+ m = chunkalloc(sizeof(Monotonic));
+ m->s = s;
+ m->tstart = startt;
+ m->tend = endt;
+ m->exclude = exclude;
+
+ if ( end.x>start.x ) {
+ m->xup = true;
+ m->b.minx = start.x;
+ m->b.maxx = end.x;
+ } else {
+ m->b.minx = end.x;
+ m->b.maxx = start.x;
+ }
+ if ( end.y>start.y ) {
+ m->yup = true;
+ m->b.miny = start.y;
+ m->b.maxy = end.y;
+ } else {
+ m->b.miny = end.y;
+ m->b.maxy = start.y;
+ }
+
+ if ( last!=NULL ) {
+ last->next = m;
+ last->linked = m;
+ m->prev = last;
+ }
+return( m );
+}
+
+static int SSIsSelected(SplineSet *spl) {
+ SplinePoint *sp;
+
+ for ( sp=spl->first; ; ) {
+ if ( sp->selected )
+return( true );
+ if ( sp->next==NULL )
+return( false );
+ sp = sp->next->to;
+ if ( sp==spl->first )
+return( false );
+ }
+}
+
+static int BpSame(BasePoint *bp1, BasePoint *bp2) {
+ BasePoint mid;
+
+ mid.x = (bp1->x+bp2->x)/2; mid.y = (bp1->y+bp2->y)/2;
+ if ( (bp1->x==mid.x || bp2->x==mid.x) &&
+ (bp1->y==mid.y || bp2->y==mid.y))
+return( true );
+
+return( false );
+}
+
+static int SSRmNullSplines(SplineSet *spl) {
+ Spline *s, *first, *next;
+
+ first = NULL;
+ for ( s=spl->first->next ; s!=first; s=next ) {
+ next = s->to->next;
+ if ( ((s->splines[0].a>-.01 && s->splines[0].a<.01 &&
+ s->splines[0].b>-.01 && s->splines[0].b<.01 &&
+ s->splines[1].a>-.01 && s->splines[1].a<.01 &&
+ s->splines[1].b>-.01 && s->splines[1].b<.01) ||
+ /* That describes a null spline (a line between the same end-point) */
+ RealNear((s->from->nextcp.x-s->from->me.x)*(s->to->me.y-s->to->prevcp.y)-
+ (s->from->nextcp.y-s->from->me.y)*(s->to->me.x-s->to->prevcp.x),0)) &&
+ /* And the above describes a point with a spline between it */
+ /* and itself where the spline covers no area (the two cps */
+ /* point in the same direction) */
+ BpSame(&s->from->me,&s->to->me)) {
+ if ( next==s )
+return( true );
+ if ( next->from->selected ) s->from->selected = true;
+ s->from->next = next;
+ s->from->nextcp = next->from->nextcp;
+ s->from->nonextcp = next->from->nonextcp;
+ s->from->nextcpdef = next->from->nextcpdef;
+ SplinePointFree(next->from);
+ if ( spl->first==next->from )
+ spl->last = spl->first = s->from;
+ next->from = s->from;
+ SplineFree(s);
+ } else {
+ if ( first==NULL )
+ first = s;
+ }
+ }
+return( false );
+}
+
+static Monotonic *SSToMContour(SplineSet *spl, Monotonic *start,
+ Monotonic **end, enum overlap_type ot) {
+ extended ts[4];
+ Spline *first, *s;
+ Monotonic *head=NULL, *last=NULL;
+ int cnt, i, selected = false;
+ extended lastt;
+
+ if ( spl->first->prev==NULL )
+return( start ); /* Open contours have no interior, ignore 'em */
+ if ( spl->first->prev->from==spl->first &&
+ spl->first->noprevcp && spl->first->nonextcp )
+return( start ); /* Let's just remove single points */
+
+ if ( ot==over_rmselected || ot==over_intersel || ot==over_fisel || ot==over_exclude ) {
+ selected = SSIsSelected(spl);
+ if ( ot==over_rmselected || ot==over_intersel || ot==over_fisel ) {
+ if ( !selected )
+return( start );
+ selected = false;
+ }
+ }
+
+ /* We blow up on zero length splines. And a zero length contour is nasty */
+ if ( SSRmNullSplines(spl))
+return( start );
+
+ first = NULL;
+ for ( s=spl->first->next; s!=first; s=s->to->next ) {
+ if ( first==NULL ) first = s;
+ cnt = Spline2DFindExtrema(s,ts);
+ lastt = 0;
+ for ( i=0; i<cnt; ++i ) {
+ last = SplineToMonotonic(s,lastt,ts[i],last,selected);
+ if ( head==NULL ) head = last;
+ lastt=ts[i];
+ }
+ if ( lastt!=1.0 ) {
+ last = SplineToMonotonic(s,lastt,1.0,last,selected);
+ if ( head==NULL ) head = last;
+ }
+ }
+ head->prev = last;
+ last->next = head;
+ if ( start==NULL )
+ start = head;
+ else
+ (*end)->linked = head;
+ *end = last;
+return( start );
+}
+
+Monotonic *SSsToMContours(SplineSet *spl, enum overlap_type ot) {
+ Monotonic *head=NULL, *last = NULL;
+
+ while ( spl!=NULL ) {
+ if ( spl->first->prev!=NULL )
+ head = SSToMContour(spl,head,&last,ot);
+ spl = spl->next;
+ }
+return( head );
+}
+
+static void _AddSpline(Intersection *il,Monotonic *m,extended t,int isend) {
+ MList *ml;
+
+ for ( ml=il->monos; ml!=NULL; ml=ml->next ) {
+ if ( ml->s==m->s && RealNear( ml->t,t ) && ml->isend==isend )
+return;
+ }
+
+ ml = chunkalloc(sizeof(MList));
+ ml->next = il->monos;
+ il->monos = ml;
+ ml->s = m->s;
+ ml->m = m; /* This may change. We'll fix it up later */
+ ml->t = t;
+ ml->isend = isend;
+ if ( isend ) {
+ if ( m->end!=NULL && m->end!=il )
+ SOError("Resetting end.\n");
+ m->end = il;
+ } else {
+ if ( m->start!=NULL && m->start!=il )
+ SOError("Resetting start.\n");
+ m->start = il;
+ }
+return;
+}
+
+static void AddSpline(Intersection *il,Monotonic *m,extended t) {
+ MList *ml;
+
+ if ( m->start==il || m->end==il )
+return;
+
+ for ( ml=il->monos; ml!=NULL; ml=ml->next ) {
+ if ( ml->s==m->s && RealWithin( ml->t,t,.0001 ))
+return;
+ }
+
+ ml = chunkalloc(sizeof(MList));
+ ml->next = il->monos;
+ il->monos = ml;
+ ml->s = m->s;
+ ml->m = m; /* This may change. We'll fix it up later */
+ ml->t = t;
+ ml->isend = true;
+ if ( t-m->tstart < m->tend-t && RealNear(m->tstart,t) ) {
+ if ( m->start!=NULL && m->start!=il )
+ SOError("Resetting start.\n");
+ m->start = il;
+ ml->t = m->tstart;
+ ml->isend = false;
+ _AddSpline(il,m->prev,m->prev->tend,true);
+ } else if ( RealNear(m->tend,t)) {
+ if ( m->end!=NULL && m->end!=il )
+ SOError("Resetting end.\n");
+ m->end = il;
+ ml->t = m->tend;
+ _AddSpline(il,m->next,m->next->tstart,false);
+ } else {
+ /* Ok, if we've got a new intersection on this spline then break up */
+ /* the monotonic into two bits which end and start at this inter */
+ if ( t<m->tstart || t>m->tend )
+ SOError( "Attempt to subset monotonic rejoin inappropriately: %g should be [%g,%g]\n",
+ t, m->tstart, m->tend );
+ else {
+ /* It is monotonic, so a subset of it must also be */
+ Monotonic *m2 = chunkalloc(sizeof(Monotonic));
+ BasePoint pt;
+ *m2 = *m;
+ m->next = m2;
+ m2->prev = m;
+ m2->next->prev = m2;
+ m->linked = m2;
+ m->tend = t;
+ m->end = il;
+ m2->start = il;
+ m2->tstart = t;
+ pt.x = ((m->s->splines[0].a*m->tstart+m->s->splines[0].b)*m->tstart+
+ m->s->splines[0].c)*m->tstart+m->s->splines[0].d;
+ pt.y = ((m->s->splines[1].a*m->tstart+m->s->splines[1].b)*m->tstart+
+ m->s->splines[1].c)*m->tstart+m->s->splines[1].d;
+ if ( pt.x>il->inter.x ) {
+ m->b.minx = il->inter.x;
+ m->b.maxx = pt.x;
+ } else {
+ m->b.minx = pt.x;
+ m->b.maxx = il->inter.x;
+ }
+ if ( pt.y>il->inter.y ) {
+ m->b.miny = il->inter.y;
+ m->b.maxy = pt.y;
+ } else {
+ m->b.miny = pt.y;
+ m->b.maxy = il->inter.y;
+ }
+ pt.x = ((m2->s->splines[0].a*m2->tend+m2->s->splines[0].b)*m2->tend+
+ m2->s->splines[0].c)*m2->tend+m2->s->splines[0].d;
+ pt.y = ((m2->s->splines[1].a*m2->tend+m2->s->splines[1].b)*m2->tend+
+ m2->s->splines[1].c)*m2->tend+m2->s->splines[1].d;
+ if ( pt.x>il->inter.x ) {
+ m2->b.minx = il->inter.x;
+ m2->b.maxx = pt.x;
+ } else {
+ m2->b.minx = pt.x;
+ m2->b.maxx = il->inter.x;
+ }
+ if ( pt.y>il->inter.y ) {
+ m2->b.miny = il->inter.y;
+ m2->b.maxy = pt.y;
+ } else {
+ m2->b.miny = pt.y;
+ m2->b.maxy = il->inter.y;
+ }
+ _AddSpline(il,m2,t,false);
+ }
+ }
+}
+
+static void SetStartPoint(BasePoint *pt,Monotonic *m) {
+ if ( m->tstart==0 )
+ *pt = m->s->from->me;
+ else if ( m->start!=NULL )
+ *pt = m->start->inter;
+ else {
+ pt->x = ((m->s->splines[0].a*m->tstart+m->s->splines[0].b)*m->tstart +
+ m->s->splines[0].c)*m->tstart + m->s->splines[0].d;
+ pt->y = ((m->s->splines[1].a*m->tstart+m->s->splines[1].b)*m->tstart +
+ m->s->splines[1].c)*m->tstart + m->s->splines[1].d;
+ }
+}
+
+static void SetEndPoint(BasePoint *pt,Monotonic *m) {
+ if ( m->tend==1.0 )
+ *pt = m->s->to->me;
+ else if ( m->end!=NULL )
+ *pt = m->end->inter;
+ else {
+ pt->x = ((m->s->splines[0].a*m->tend+m->s->splines[0].b)*m->tend +
+ m->s->splines[0].c)*m->tend + m->s->splines[0].d;
+ pt->y = ((m->s->splines[1].a*m->tend+m->s->splines[1].b)*m->tend +
+ m->s->splines[1].c)*m->tend + m->s->splines[1].d;
+ }
+}
+
+static extended RoundToEndpoints(Monotonic *m,extended t,BasePoint *inter) {
+ BasePoint end;
+ extended bound;
+
+ if ( t==0 || t==1 ) {
+ if ( t==0 )
+ *inter = m->s->from->me;
+ else
+ *inter = m->s->to->me;
+return( t );
+ }
+
+ if ( t-m->tstart < m->tend-t ) {
+ bound = m->tstart;
+ SetStartPoint(&end,m);
+ } else {
+ bound = m->tend;
+ SetEndPoint(&end,m);
+ }
+ if ( BpSame(&end,inter) || RealWithin(t,bound,.00001)) {
+ *inter = end;
+return( bound );
+ }
+
+return( t );
+}
+
+static extended Grad1(Spline1D *s1, Spline1D *s2,
+ extended t1,extended t2 ) {
+ /* d/dt[12] (m1(t1).x-m2(t2).x)^2 + (m1(t1).y-m2(t2).y)^2 */
+ /* d/dt[12] (m1(t1).x^2 -2m1(t1).x*m2(t2).x + m2(t2).x^2) + (m1(t1).y^2 -2m1(t1).y*m2(t2).y + m2(t2).y^2) */
+ extended val2 = ((s2->a*t2+s2->b)*t2+s2->c)*t2+s2->d;
+
+return( ((((6*(extended)s1->a*s1->a*t1 +
+ 5*2*(extended)s1->a*s1->b)*t1 +
+ 4*(s1->b*(extended)s1->b+2*s1->a*(extended)s1->c))*t1 +
+ 3*2*(s1->a*(extended)s1->d+s1->b*(extended)s1->c))*t1 +
+ 2*(s1->c*(extended)s1->c+2*s1->b*(extended)s1->d))*t1 +
+ 2*s1->c*(extended)s1->d -
+ 2*val2 * ((3*s1->a*t1 + 2*s1->b)*t1 + s1->c) );
+}
+
+static void GradImproveInter(Monotonic *m1, Monotonic *m2,
+ extended *_t1,extended *_t2,BasePoint *inter) {
+ Spline *s1 = m1->s, *s2 = m2->s;
+ extended x1, x2, y1, y2;
+ extended gt1=0, gt2=0, glen=1;
+ extended error, olderr=1e10;
+ extended factor = 4096;
+ extended t1=*_t1, t2=*_t2;
+ extended off, off2, yoff;
+ int cnt=0;
+ /* We want to find (t1,t2) so that (m1(t1)-m2(t2))^2==0 */
+ /* Find the gradiant and move in the reverse direction */
+ /* We know that the current values of (t1,t2) are close to an intersection*/
+ /* so the grad should point correctly */
+ /* d/dt[12] (m1(t1).x-m2(t2).x)^2 + (m1(t1).y-m2(t2).y)^2 */
+ /* d/dt[12] (m1(t1).x^2 -2m1(t1).x*m2(t2).x + m2(t2).x^2) + (m1(t1).y^2 -2m1(t1).y*m2(t2).y + m2(t2).y^2) */
+
+ forever {
+ x1 = ((s1->splines[0].a*t1 + s1->splines[0].b)*t1 + s1->splines[0].c)*t1 + s1->splines[0].d;
+ x2 = ((s2->splines[0].a*t2 + s2->splines[0].b)*t2 + s2->splines[0].c)*t2 + s2->splines[0].d;
+ y1 = ((s1->splines[1].a*t1 + s1->splines[1].b)*t1 + s1->splines[1].c)*t1 + s1->splines[1].d;
+ y2 = ((s2->splines[1].a*t2 + s2->splines[1].b)*t2 + s2->splines[1].c)*t2 + s2->splines[1].d;
+ error = (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2);
+ if ( error>olderr ) {
+ if ( olderr==1e10 )
+ break;
+ factor *= 2;
+ if ( factor>4096*4096 )
+ break;
+ glen *= 2;
+ t1 += gt1/glen;
+ t2 += gt2/glen;
+ continue;
+ } else
+ factor /= 1.4;
+ if ( error<1e-11 ) /* Error is actually the square of the error */
+ break; /* So this isn't as constraining as it looks */
+
+ gt1 = Grad1(&s1->splines[0],&s2->splines[0],t1,t2) + Grad1(&s1->splines[1],&s2->splines[1],t1,t2);
+ gt2 = Grad1(&s2->splines[0],&s1->splines[0],t2,t1) + Grad1(&s2->splines[1],&s1->splines[1],t2,t1);
+ glen = esqrt(gt1*gt1 + gt2*gt2) * factor;
+ if ( glen==0 )
+ break;
+ *_t1 = t1; *_t2 = t2;
+ t1 -= gt1/glen;
+ t2 -= gt2/glen;
+ if ( isnan(t1) || isnan(t2)) {
+ IError( "Nan in grad" );
+ break;
+ }
+ olderr = error;
+ ++cnt;
+ if ( cnt>1000 )
+ break;
+ }
+#if 0
+ if ( cnt<=1 && error>=1e-11 )
+ fprintf(stderr,"No Improvement\n" );
+ else if ( cnt>1 )
+ fprintf(stderr,"Improvement\n" );
+#endif
+ t1 = *_t1; t2 = *_t2;
+ if ( t1<0 && t1>-.00001 ) *_t1 = t1 = 0;
+ else if ( t1>1 && t1<1.00001 ) *_t1 = t1 = 1.0;
+ if ( t2<0 && t2>-.00001 ) *_t2 = t2 = 0;
+ else if ( t2>1 && t2<1.00001 ) *_t2 = t2 = 1.0;
+ x1 = ((s1->splines[0].a*t1 + s1->splines[0].b)*t1 + s1->splines[0].c)*t1 + s1->splines[0].d;
+ x2 = ((s2->splines[0].a*t2 + s2->splines[0].b)*t2 + s2->splines[0].c)*t2 + s2->splines[0].d;
+ y1 = ((s1->splines[1].a*t1 + s1->splines[1].b)*t1 + s1->splines[1].c)*t1 + s1->splines[1].d;
+ y2 = ((s2->splines[1].a*t2 + s2->splines[1].b)*t2 + s2->splines[1].c)*t2 + s2->splines[1].d;
+ inter->x = (x1+x2)/2; inter->y = (y1+y2)/2;
+
+ if ( (off=x1-x2)<0 ) off = -off;
+ if ( (yoff=y1-y2)<0 ) yoff = -yoff;
+ off += yoff;
+
+ if ( t1<.0001 ) {
+ t1 = 0;
+ x1 = s1->splines[0].d;
+ y1 = s1->splines[1].d;
+ } else if ( t1>.9999 ) {
+ t1 = 1.0;
+ x1 = s1->splines[0].a+s1->splines[0].b+s1->splines[0].c+s1->splines[0].d;
+ y1 = s1->splines[1].a+s1->splines[1].b+s1->splines[1].c+s1->splines[1].d;
+ }
+ if ( t2<.0001 ) {
+ t2=0;
+ x2 = s2->splines[0].d;
+ y2 = s2->splines[1].d;
+ } else if ( t2>.9999 ) {
+ t2=1.0;
+ x2 = s2->splines[0].a+s2->splines[0].b+s2->splines[0].c+s2->splines[0].d;
+ y2 = s2->splines[1].a+s2->splines[1].b+s2->splines[1].c+s2->splines[1].d;
+ }
+ if ( (off2=x1-x2)<0 ) off2 = -off2;
+ if ( (yoff=y1-y2)<0 ) yoff = -yoff;
+ off2 += yoff;
+ if ( off2<=off ) {
+ *_t1 = t1; *_t2 = t2;
+ inter->x = (x1+x2)/2; inter->y = (y1+y2)/2;
+ }
+}
+
+static Intersection *AddIntersection(Intersection *ilist,Monotonic *m1,
+ Monotonic *m2,extended t1,extended t2,BasePoint *inter) {
+ Intersection *il;
+ extended ot1 = t1, ot2 = t2;
+
+ /* Fixup some rounding errors */
+ GradImproveInter(m1,m2,&t1,&t2,inter);
+ if ( t1<m1->tstart || t1>m1->tend || t2<m2->tstart || t2>m2->tend )
+return( ilist );
+
+#if 0
+ if (( m1->start==m2->start && m1->start!=NULL && RealNear(t1,m1->tstart) && RealNear(t2,m2->tstart)) ||
+ ( m1->start==m2->end && m1->start!=NULL && RealNear(t1,m1->tstart) && RealNear(t2,m2->tend)) ||
+ ( m1->end==m2->start && m1->end!=NULL && RealNear(t1,m1->tend) && RealNear(t2,m2->tstart)) ||
+ ( m1->end==m2->end && m1->end!=NULL && RealNear(t1,m1->tend) && RealNear(t2,m2->tend)) )
+return( ilist );
+ else
+ if ( RealWithin(t1,1.0,.01) && RealWithin(t2,0.0,.01) && BpSame(&m1->s->to->me,&m2->s->from->me)) {
+ t1 = 1.0;
+ t2 = 0.0;
+ } else if ( RealWithin(t2,1.0,.01) && RealWithin(t1,0.0,.01) && BpSame(&m2->s->to->me,&m1->s->from->me)) {
+ t1 = 0.0;
+ t2 = 1.0;
+ } else {
+#endif
+ t1 = RoundToEndpoints(m1,t1,inter);
+ t2 = RoundToEndpoints(m2,t2,inter);
+ t1 = RoundToEndpoints(m1,t1,inter); /* Do it twice. rounding t2 can mean we now need to round t1 */
+#if 0
+ }
+#endif
+
+ if (( m1->s->to == m2->s->from && RealWithin(t1,1.0,.01) && RealWithin(t2,0,.01)) ||
+ ( m1->s->from == m2->s->to && RealWithin(t1,0,.01) && RealWithin(t2,1.0,.01)))
+return( ilist );
+
+ if (( t1==m1->tstart && m1->start!=NULL &&
+ (inter->x!=m1->start->inter.x || inter->y!=m1->start->inter.y)) ||
+ ( t1==m1->tend && m1->end!=NULL &&
+ (inter->x!=m1->end->inter.x || inter->y!=m1->end->inter.y)))
+ t1 = ot1;
+ if (( t2==m2->tstart && m2->start!=NULL &&
+ (inter->x!=m2->start->inter.x || inter->y!=m2->start->inter.y)) ||
+ ( t2==m2->tend && m2->end!=NULL &&
+ (inter->x!=m2->end->inter.x || inter->y!=m2->end->inter.y)))
+ t2 = ot2;
+
+ /* The ordinary join of one spline to the next doesn't really count */
+ /* Or one monotonic sub-spline to the next either */
+ if (( m1->next==m2 && RealNear(t1,m1->tend) && RealNear(t2,m2->tstart)) ||
+ (m2->next==m1 && RealNear(t1,m1->tstart) && RealNear(t2,m2->tend)) )
+return( ilist );
+
+ if ( RealWithin(m1->tstart,t1,.01) )
+ il = m1->start;
+ else if ( RealWithin(m1->tend,t1,.01) )
+ il = m1->end;
+ else
+ il = NULL;
+ if ( il!=NULL &&
+ ((RealWithin(m2->tstart,t2,.01) && m2->start==il) ||
+ (RealWithin(m2->tend,t2,.01) && m2->end==il)) )
+return( ilist );
+
+ for ( il = ilist; il!=NULL; il=il->next ) {
+ if ( RealWithin(il->inter.x,inter->x,.01) && RealWithin(il->inter.y,inter->y,.01)) {
+ AddSpline(il,m1,t1);
+ AddSpline(il,m2,t2);
+return( ilist );
+ }
+ }
+
+ il = chunkalloc(sizeof(Intersection));
+ il->inter = *inter;
+ il->next = ilist;
+ AddSpline(il,m1,t1);
+ AddSpline(il,m2,t2);
+return( il );
+}
+
+static extended BoundIterateSplineSolve(Spline1D *sp, extended tmin, extended tmax,
+ extended sought,double err) {
+ extended t = IterateSplineSolve(sp,tmin,tmax,sought,err);
+ if ( t<tmin || t>tmax )
+return( -1 );
+
+return( t );
+}
+
+static Intersection *FindMonotonicIntersection(Intersection *ilist,Monotonic *m1,Monotonic *m2) {
+ /* I believe that two monotonic cubics can still intersect in two points */
+ /* so we can't just check if the splines are on oposite sides of each */
+ /* other at top and bottom */
+ DBounds b;
+ const double error = .0001;
+ BasePoint pt;
+ extended t1,t2;
+
+ b.minx = m1->b.minx>m2->b.minx ? m1->b.minx : m2->b.minx;
+ b.maxx = m1->b.maxx<m2->b.maxx ? m1->b.maxx : m2->b.maxx;
+ b.miny = m1->b.miny>m2->b.miny ? m1->b.miny : m2->b.miny;
+ b.maxy = m1->b.maxy<m2->b.maxy ? m1->b.maxy : m2->b.maxy;
+
+ if ( b.maxy==b.miny && b.minx==b.maxx ) {
+ extended x1,y1, x2,y2;
+ if ( m1->next==m2 || m2->next==m1 )
+return( ilist ); /* Not interesting. Only intersection is at an endpoint */
+ if ( ((m1->start==m2->start || m1->end==m2->start) && m2->start!=NULL) ||
+ ((m1->start==m2->end || m1->end==m2->end ) && m2->end!=NULL ))
+return( ilist );
+ pt.x = b.minx; pt.y = b.miny;
+ if ( m1->b.maxx-m1->b.minx > m1->b.maxy-m1->b.miny )
+ t1 = BoundIterateSplineSolve(&m1->s->splines[0],m1->tstart,m1->tend,b.minx,error);
+ else
+ t1 = BoundIterateSplineSolve(&m1->s->splines[1],m1->tstart,m1->tend,b.miny,error);
+ if ( m2->b.maxx-m2->b.minx > m2->b.maxy-m2->b.miny )
+ t2 = BoundIterateSplineSolve(&m2->s->splines[0],m2->tstart,m2->tend,b.minx,error);
+ else
+ t2 = BoundIterateSplineSolve(&m2->s->splines[1],m2->tstart,m2->tend,b.miny,error);
+ if ( t1!=-1 && t2!=-1 ) {
+ x1 = ((m1->s->splines[0].a*t1+m1->s->splines[0].b)*t1+m1->s->splines[0].c)*t1+m1->s->splines[0].d;
+ y1 = ((m1->s->splines[1].a*t1+m1->s->splines[1].b)*t1+m1->s->splines[1].c)*t1+m1->s->splines[1].d;
+ x2 = ((m2->s->splines[0].a*t2+m2->s->splines[0].b)*t2+m2->s->splines[0].c)*t2+m2->s->splines[0].d;
+ y2 = ((m2->s->splines[1].a*t2+m2->s->splines[1].b)*t2+m2->s->splines[1].c)*t2+m2->s->splines[1].d;
+ if ( x1-x2>-.01 && x1-x2<.01 && y1-y2>-.01 && y1-y2<.01 )
+ ilist = AddIntersection(ilist,m1,m2,t1,t2,&pt);
+ }
+ } else if ( b.maxy==b.miny ) {
+ extended x1,x2;
+ if ( m1->next==m2 || m2->next==m1 )
+return( ilist ); /* Not interesting. Only intersection is at an endpoint */
+ t1 = BoundIterateSplineSolve(&m1->s->splines[1],m1->tstart,m1->tend,b.miny,error);
+ t2 = BoundIterateSplineSolve(&m2->s->splines[1],m2->tstart,m2->tend,b.miny,error);
+ if ( t1!=-1 && t2!=-1 ) {
+ x1 = ((m1->s->splines[0].a*t1+m1->s->splines[0].b)*t1+m1->s->splines[0].c)*t1+m1->s->splines[0].d;
+ x2 = ((m2->s->splines[0].a*t2+m2->s->splines[0].b)*t2+m2->s->splines[0].c)*t2+m2->s->splines[0].d;
+ if ( x1-x2>-.01 && x1-x2<.01 ) {
+ pt.x = (x1+x2)/2; pt.y = b.miny;
+ ilist = AddIntersection(ilist,m1,m2,t1,t2,&pt);
+ }
+ }
+ } else if ( b.maxx==b.minx ) {
+ extended y1,y2;
+ if ( m1->next==m2 || m2->next==m1 )
+return( ilist ); /* Not interesting. Only intersection is at an endpoint */
+ t1 = BoundIterateSplineSolve(&m1->s->splines[0],m1->tstart,m1->tend,b.minx,error);
+ t2 = BoundIterateSplineSolve(&m2->s->splines[0],m2->tstart,m2->tend,b.minx,error);
+ if ( t1!=-1 && t2!=-1 ) {
+ y1 = ((m1->s->splines[1].a*t1+m1->s->splines[1].b)*t1+m1->s->splines[1].c)*t1+m1->s->splines[1].d;
+ y2 = ((m2->s->splines[1].a*t2+m2->s->splines[1].b)*t2+m2->s->splines[1].c)*t2+m2->s->splines[1].d;
+ if ( y1-y2>-.01 && y1-y2<.01 ) {
+ pt.x = b.minx; pt.y = (y1+y2)/2;
+ ilist = AddIntersection(ilist,m1,m2,t1,t2,&pt);
+ }
+ }
+ } else if ( b.maxy-b.miny > b.maxx-b.minx ) {
+ extended diff, y, x1,x2, x1o,x2o;
+ extended t1=0,t2=0, t1o=0,t2o=0 ;
+
+ diff = (b.maxy-b.miny)/32;
+ y = b.miny;
+ x1o = x2o = 0;
+ while ( y<b.maxy ) {
+ while ( y<b.maxy ) {
+ t1o = BoundIterateSplineSolve(&m1->s->splines[1],m1->tstart,m1->tend,b.miny,error);
+ t2o = BoundIterateSplineSolve(&m2->s->splines[1],m2->tstart,m2->tend,b.miny,error);
+ if ( t1o!=-1 && t2o!=-1 )
+ break;
+ y += diff;
+ }
+ x1o = ((m1->s->splines[0].a*t1o+m1->s->splines[0].b)*t1o+m1->s->splines[0].c)*t1o+m1->s->splines[0].d;
+ x2o = ((m2->s->splines[0].a*t2o+m2->s->splines[0].b)*t2o+m2->s->splines[0].c)*t2o+m2->s->splines[0].d;
+ if ( x1o!=x2o )
+ break;
+ y += diff;
+ }
+#if 0
+ if ( x1o==x2o ) {
+ pt.x = x1o; pt.y = y;
+ ilist = AddIntersection(ilist,m1,m2,t1o,t2o,&pt);
+ }
+#endif
+ for ( y+=diff; ; y += diff ) {
+ /* I used to say y<=b.maxy in the above for statement. */
+ /* that seemed to get rounding errors on the mac, so we do it */
+ /* like this now: */
+ if ( y>b.maxy ) {
+ if ( y<b.maxy+diff/4 ) y = b.maxy;
+ else
+ break;
+ }
+ t1 = BoundIterateSplineSolve(&m1->s->splines[1],m1->tstart,m1->tend,y,error);
+ t2 = BoundIterateSplineSolve(&m2->s->splines[1],m2->tstart,m2->tend,y,error);
+ if ( t1==-1 || t2==-1 )
+ continue;
+ x1 = ((m1->s->splines[0].a*t1+m1->s->splines[0].b)*t1+m1->s->splines[0].c)*t1+m1->s->splines[0].d;
+ x2 = ((m2->s->splines[0].a*t2+m2->s->splines[0].b)*t2+m2->s->splines[0].c)*t2+m2->s->splines[0].d;
+#if 0
+ if ( x1==x2 && x1o!=x2o ) {
+ pt.x = x1; pt.y = y;
+ ilist = AddIntersection(ilist,m1,m2,t1,t2,&pt);
+ if ( m1->tend==t1 && m1->s==m1->next->s ) m1 = m1->next;
+ if ( m2->tend==t2 && m2->s==m2->next->s ) m2 = m2->next;
+ } else
+#endif
+ if ( x1o!=x2o && (x1o>x2o) != ( x1>x2 ) ) {
+ /* A cross over has occured. (assume we have a small enough */
+ /* region that three cross-overs can't have occurred) */
+ /* Use a binary search to track it down */
+ extended ytop, ybot;
+ ytop = y;
+ ybot = y-diff;
+ while ( ytop!=ybot ) {
+ extended ytest = (ytop+ybot)/2;
+ extended t1t, t2t;
+ t1t = BoundIterateSplineSolve(&m1->s->splines[1],m1->tstart,m1->tend,ytest,error);
+ t2t = BoundIterateSplineSolve(&m2->s->splines[1],m2->tstart,m2->tend,ytest,error);
+ x1 = ((m1->s->splines[0].a*t1t+m1->s->splines[0].b)*t1t+m1->s->splines[0].c)*t1t+m1->s->splines[0].d;
+ x2 = ((m2->s->splines[0].a*t2t+m2->s->splines[0].b)*t2t+m2->s->splines[0].c)*t2t+m2->s->splines[0].d;
+ if ( t1t==-1 || t2t==-1 ) {
+ SOError( "Can't find something in range.\n" );
+ break;
+ } else if (( x1-x2<error && x1-x2>-error ) || ytop==ytest || ybot==ytest ) {
+ pt.y = ytest; pt.x = (x1+x2)/2;
+ ilist = AddIntersection(ilist,m1,m2,t1t,t2t,&pt);
+ b.maxy = m1->b.maxy<m2->b.maxy ? m1->b.maxy : m2->b.maxy;
+ break;
+ } else if ( (x1o>x2o) != ( x1>x2 ) ) {
+ ytop = ytest;
+ } else {
+ ybot = ytest;
+ }
+ }
+ x1 = x1o; x1o = x2o; x2o = x1;
+ } else {
+ x1o = x1; x2o = x2;
+ }
+ }
+ } else {
+ extended diff, x, y1,y2, y1o,y2o;
+ extended t1=0,t2=0, t1o=0,t2o=0 ;
+
+ diff = (b.maxx-b.minx)/32;
+ x = b.minx;
+ y1o = y2o = 0;
+ while ( x<b.maxx ) {
+ while ( x<b.maxx ) {
+ t1o = BoundIterateSplineSolve(&m1->s->splines[0],m1->tstart,m1->tend,b.minx,error);
+ t2o = BoundIterateSplineSolve(&m2->s->splines[0],m2->tstart,m2->tend,b.minx,error);
+ if ( t1o!=-1 && t2o!=-1 )
+ break;
+ x += diff;
+ }
+ y1o = ((m1->s->splines[1].a*t1o+m1->s->splines[1].b)*t1o+m1->s->splines[1].c)*t1o+m1->s->splines[1].d;
+ y2o = ((m2->s->splines[1].a*t2o+m2->s->splines[1].b)*t2o+m2->s->splines[1].c)*t2o+m2->s->splines[1].d;
+ if ( y1o!=y2o )
+ break;
+ x += diff;
+ }
+#if 0
+ if ( y1o==y2o ) {
+ pt.y = y1o; pt.x = x;
+ ilist = AddIntersection(ilist,m1,m2,t1o,t2o,&pt);
+ }
+#endif
+ y1 = y2 = 0;
+ for ( x+=diff; ; x += diff ) {
+ if ( x>b.maxx ) {
+ if ( x<b.maxx+diff/4 ) x = b.maxx;
+ else
+ break;
+ }
+ t1 = BoundIterateSplineSolve(&m1->s->splines[0],m1->tstart,m1->tend,x,error);
+ t2 = BoundIterateSplineSolve(&m2->s->splines[0],m2->tstart,m2->tend,x,error);
+ if ( t1==-1 || t2==-1 )
+ continue;
+ y1 = ((m1->s->splines[1].a*t1+m1->s->splines[1].b)*t1+m1->s->splines[1].c)*t1+m1->s->splines[1].d;
+ y2 = ((m2->s->splines[1].a*t2+m2->s->splines[1].b)*t2+m2->s->splines[1].c)*t2+m2->s->splines[1].d;
+#if 0
+ if ( y1==y2 && y1o!=y2o ) {
+ pt.y = y1; pt.x = x;
+ ilist = AddIntersection(ilist,m1,m2,t1,t2,&pt);
+ if ( m1->tend==t1 && m1->s==m1->next->s ) m1 = m1->next;
+ if ( m2->tend==t2 && m2->s==m2->next->s ) m2 = m2->next;
+ } else
+#endif
+ if ( (y1o>y2o) != ( y1>y2 ) ) {
+ /* A cross over has occured. (assume we have a small enough */
+ /* region that three cross-overs can't have occurred) */
+ /* Use a binary search to track it down */
+ extended xtop, xbot;
+ xtop = x;
+ xbot = x-diff;
+ while ( xtop!=xbot ) {
+ extended xtest = (xtop+xbot)/2;
+ extended t1t, t2t;
+ t1t = BoundIterateSplineSolve(&m1->s->splines[0],m1->tstart,m1->tend,xtest,error);
+ t2t = BoundIterateSplineSolve(&m2->s->splines[0],m2->tstart,m2->tend,xtest,error);
+ y1 = ((m1->s->splines[1].a*t1t+m1->s->splines[1].b)*t1t+m1->s->splines[1].c)*t1t+m1->s->splines[1].d;
+ y2 = ((m2->s->splines[1].a*t2t+m2->s->splines[1].b)*t2t+m2->s->splines[1].c)*t2t+m2->s->splines[1].d;
+ if ( t1t==-1 || t2t==-1 ) {
+ SOError( "Can't find something in range.\n" );
+ break;
+ } else if (( y1-y2<error && y1-y2>-error ) || xtop==xtest || xbot==xtest ) {
+ pt.x = xtest; pt.y = (y1+y2)/2;
+ ilist = AddIntersection(ilist,m1,m2,t1t,t2t,&pt);
+ b.maxx = m1->b.maxx<m2->b.maxx ? m1->b.maxx : m2->b.maxx;
+ break;
+ } else if ( (y1o>y2o) != ( y1>y2 ) ) {
+ xtop = xtest;
+ } else {
+ xbot = xtest;
+ }
+ }
+ y1 = y1o; y1o = y2o; y2o = y1;
+ } else {
+ y1o = y1; y2o = y2;
+ }
+ }
+ }
+return( ilist );
+}
+
+#if 0
+static void SubsetSpline1(Spline1D *subset,Spline1D *orig,
+ extended tstart,extended tend,extended d) {
+ extended f = tend-tstart;
+
+ subset->a = orig->a*f*f*f;
+ subset->b = (orig->b + 3*orig->a*tstart) *f*f;
+ subset->c = (orig->c + (2*orig->b + 3*orig->a*tstart)*tstart) * f;
+ subset->d = d;
+}
+#endif
+
+static extended SplineContainsPoint(Monotonic *m,BasePoint *pt) {
+ int which, nw;
+ extended t;
+ BasePoint slope;
+ const double error = .0001;
+
+ which = ( m->b.maxx-m->b.minx > m->b.maxy-m->b.miny )? 0 : 1;
+ nw = !which;
+ t = BoundIterateSplineSolve(&m->s->splines[which],m->tstart,m->tend,(&pt->x)[which],error);
+ if ( (slope.x = (3*m->s->splines[0].a*t+2*m->s->splines[0].b)*t+m->s->splines[0].c)<0 )
+ slope.x = -slope.x;
+ if ( (slope.y = (3*m->s->splines[1].a*t+2*m->s->splines[1].b)*t+m->s->splines[1].c)<0 )
+ slope.y = -slope.y;
+ if ( t==-1 || (slope.y>slope.x)!=which ) {
+ nw = which;
+ which = 1-which;
+ t = BoundIterateSplineSolve(&m->s->splines[which],m->tstart,m->tend,(&pt->x)[which],error);
+ }
+ if ( t!=-1 && RealWithin((&pt->x)[nw],
+ ((m->s->splines[nw].a*t+m->s->splines[nw].b)*t +
+ m->s->splines[nw].c)*t + m->s->splines[nw].d,.1 ))
+return( t );
+
+return( -1 );
+}
+
+/* If two splines are coincident, then pretend they intersect at both */
+/* end-points and nowhere else */
+static int CoincidentIntersect(Monotonic *m1,Monotonic *m2,BasePoint *pts,
+ extended *t1s,extended *t2s) {
+ const double error = .0001;
+ int cnt=0;
+ extended t, t2, diff;
+
+ if ( m1==m2 || m1->next==m2 || m1->prev==m2 )
+return( false ); /* Can't be coincident. Adjacent */
+ /* Actually adjacent splines can double back on themselves */
+
+ if ( (m1->xup==m2->xup && m1->yup==m2->yup) ||
+ ((m1->xup!=m2->xup || (m1->b.minx==m1->b.maxx && m2->b.minx==m2->b.maxx)) ||
+ (m1->yup!=m2->yup || (m1->b.miny==m1->b.maxy && m2->b.miny==m2->b.maxy))))
+ /* A match is possible */;
+ else
+return( false );
+
+ SetStartPoint(&pts[cnt],m1);
+ t1s[cnt] = m1->tstart;
+ if ( (t2s[cnt] = SplineContainsPoint(m2,&pts[cnt]))!=-1 )
+ ++cnt;
+
+ SetEndPoint(&pts[cnt],m1);
+ t1s[cnt] = m1->tend;
+ if ( (t2s[cnt] = SplineContainsPoint(m2,&pts[cnt]))!=-1 )
+ ++cnt;
+
+ if ( cnt!=2 ) {
+ SetStartPoint(&pts[cnt],m2);
+ t2s[cnt] = m2->tstart;
+ if ( (t1s[cnt] = SplineContainsPoint(m1,&pts[cnt]))!=-1 )
+ ++cnt;
+ }
+
+ if ( cnt!=2 ) {
+ SetEndPoint(&pts[cnt],m2);
+ t2s[cnt] = m2->tend;
+ if ( (t1s[cnt] = SplineContainsPoint(m1,&pts[cnt]))!=-1 )
+ ++cnt;
+ }
+
+ if ( cnt!=2 )
+return( false );
+
+ if ( RealWithin(t1s[0],t1s[1],.01) )
+return( false );
+
+ /* Ok, if we've gotten this far we know that two of the end points are */
+ /* on both splines. */
+#if 0
+ /* Interesting. The following algorithem does not produce a unique */
+ /* representation of the subset spline. Must test each point */
+ /* Then subset each spline so that [0,1] runs along the range we just */
+ /* found for it. Compare these two subsets, if they are almost equal */
+ /* then assume they are coincident, and return the two endpoints as */
+ /* the intersection points. */
+ SubsetSpline1(&subs1,&m1->s->splines[0],t1s[0],t1s[1],pts[0].x);
+ SubsetSpline1(&subs2,&m2->s->splines[0],t2s[0],t2s[1],pts[0].x);
+ if ( !RealWithin(subs1.a,subs2.a,.1) || !RealWithin(subs1.b,subs2.b,.1) ||
+ !RealWithin(subs1.c,subs2.c,.2) /* Don't need to check d, it's always pts[0].x */)
+return( false );
+
+ SubsetSpline1(&subs1,&m1->s->splines[1],t1s[0],t1s[1],pts[0].y);
+ SubsetSpline1(&subs2,&m2->s->splines[1],t2s[0],t2s[1],pts[0].y);
+ if ( !RealWithin(subs1.a,subs2.a,.1) || !RealWithin(subs1.b,subs2.b,.1) ||
+ !RealWithin(subs1.c,subs2.c,.2) /* Don't need to check d, it's always pts[0].x */)
+return( false );
+
+ t1s[2] = t2s[2] = -1;
+return( true );
+#else
+ t1s[2] = t2s[2] = -1;
+ if ( !m1->s->knownlinear || !m1->s->knownlinear ) {
+ if ( t1s[1]<t1s[0] ) {
+ extended temp = t1s[1]; t1s[1] = t1s[0]; t1s[0] = temp;
+ temp = t2s[1]; t2s[1] = t2s[0]; t2s[0] = temp;
+ }
+ diff = (t1s[1]-t1s[0])/16;
+ for ( t=t1s[0]+diff; t<t1s[1]-diff/4; t += diff ) {
+ BasePoint here, slope;
+ here.x = ((m1->s->splines[0].a*t+m1->s->splines[0].b)*t+m1->s->splines[0].c)*t+m1->s->splines[0].d;
+ here.y = ((m1->s->splines[1].a*t+m1->s->splines[1].b)*t+m1->s->splines[1].c)*t+m1->s->splines[1].d;
+ if ( (slope.x = (3*m1->s->splines[0].a*t+2*m1->s->splines[0].b)*t+m1->s->splines[0].c)<0 )
+ slope.x = -slope.x;
+ if ( (slope.y = (3*m1->s->splines[1].a*t+2*m1->s->splines[1].b)*t+m1->s->splines[1].c)<0 )
+ slope.y = -slope.y;
+ if ( slope.y>slope.x ) {
+ t2 = BoundIterateSplineSolve(&m2->s->splines[1],t2s[0],t2s[1],here.y,error);
+ if ( t2==-1 || !RealWithin(here.x,((m2->s->splines[0].a*t2+m2->s->splines[0].b)*t2+m2->s->splines[0].c)*t2+m2->s->splines[0].d,.1))
+return( false );
+ } else {
+ t2 = BoundIterateSplineSolve(&m2->s->splines[0],t2s[0],t2s[1],here.x,error);
+ if ( t2==-1 || !RealWithin(here.y,((m2->s->splines[1].a*t2+m2->s->splines[1].b)*t2+m2->s->splines[1].c)*t2+m2->s->splines[1].d,.1))
+return( false );
+ }
+ }
+ }
+
+return( true );
+#endif
+}
+
+static void FigureProperMonotonicsAtIntersections(Intersection *ilist) {
+ MList *ml, *ml2, *mlnext, *prev, *p2;
+
+ while ( ilist!=NULL ) {
+ for ( ml=ilist->monos; ml!=NULL; ml=ml->next ) {
+ if ( (ml->t==ml->m->tstart && !ml->isend) ||
+ (ml->t==ml->m->tend && ml->isend))
+ /* It's right */;
+ else if ( ml->t>ml->m->tstart ) {
+ while ( ml->t>ml->m->tend ) {
+ ml->m = ml->m->next;
+ if ( ml->m->s!=ml->s ) {
+ SOError("we could not find a matching monotonic\n" );
+ break;
+ }
+ }
+ } else {
+ while ( ml->t<ml->m->tstart ) {
+ ml->m = ml->m->prev;
+ if ( ml->m->s!=ml->s ) {
+ SOError( "we could not find a matching monotonic\n" );
+ break;
+ }
+ }
+ }
+ if ( ml->t==ml->m->tstart && ml->isend )
+ ml->m = ml->m->prev;
+ else if ( ml->t==ml->m->tend && !ml->isend )
+ ml->m = ml->m->next;
+ if ( ml->t!=ml->m->tstart && ml->t!=ml->m->tend )
+ SOError( "we could not find a matching monotonic time\n" );
+ }
+ for ( prev=NULL, ml=ilist->monos; ml!=NULL; ml = mlnext ) {
+ mlnext = ml->next;
+ if ( ml->m->start==ml->m->end ) {
+ for ( p2 = ml, ml2=ml->next; ml2!=NULL; p2=ml2, ml2 = ml2->next ) {
+ if ( ml2->m==ml->m )
+ break;
+ }
+ if ( ml2!=NULL ) {
+ if ( ml2==mlnext ) mlnext = ml2->next;
+ p2->next = ml2->next;
+ chunkfree(ml2,sizeof(*ml2));
+ }
+ if ( prev==NULL )
+ ilist->monos = mlnext;
+ else
+ prev->next = mlnext;
+ chunkfree(ml,sizeof(*ml));
+ }
+ }
+#if 0
+ for ( ml=ilist->monos; ml!=NULL; ml=ml->next ) {
+ Monotonic *search;
+ MList *ml2;
+ extended t;
+ if ( ml->m->start == ilist ) {
+ search = ml->m->prev;
+ t = ( ml->m->tstart==0 ) ? 1.0 : ml->m->tstart;
+ } else {
+ search = ml->m->next;
+ t = ( ml->m->tend==1.0 ) ? 0.0 : ml->m->tend;
+ }
+ for ( ml2=ilist->monos; ml2!=NULL && ml2->m!=search; ml2=ml2->next );
+ if ( ml2==NULL ) {
+ ml2 = chunkalloc(sizeof(MList));
+ ml2->m = search;
+ ml2->s = search->s;
+ ml2->t = t;
+ ml2->next = ml->next;
+ ml->next = ml2;
+ ml = ml2;
+ }
+ }
+#endif
+ ilist = ilist->next;
+ }
+}
+
+static void Validate(Monotonic *ms, Intersection *ilist) {
+ MList *ml;
+ int mcnt;
+
+ while ( ilist!=NULL ) {
+ for ( mcnt=0, ml=ilist->monos; ml!=NULL; ml=ml->next ) {
+ if ( ml->m->isneeded ) ++mcnt;
+ if ( ml->m->start!=ilist && ml->m->end!=ilist )
+ SOError( "Intersection (%g,%g) not on a monotonic which should contain it.\n",
+ ilist->inter.x, ilist->inter.y );
+ }
+ if ( mcnt&1 )
+ SOError( "Odd number of needed monotonic sections at intersection. (%g,%g)\n",
+ ilist->inter.x,ilist->inter.y );
+ ilist = ilist->next;
+ }
+
+ while ( ms!=NULL ) {
+ if ( ms->prev->end!=ms->start )
+ SOError( "Mismatched intersection.\n");
+ ms = ms->linked;
+ }
+}
+
+static Intersection *FindIntersections(Monotonic *ms, enum overlap_type ot) {
+ Monotonic *m1, *m2;
+ BasePoint pts[9];
+ extended t1s[10], t2s[10];
+ Intersection *ilist=NULL;
+ int i;
+ int wasc;
+
+ for ( m1=ms; m1!=NULL; m1=m1->linked ) {
+ for ( m2=m1->linked; m2!=NULL; m2=m2->linked ) {
+ if ( m2->b.minx > m1->b.maxx ||
+ m2->b.maxx < m1->b.minx ||
+ m2->b.miny > m1->b.maxy ||
+ m2->b.maxy < m1->b.miny )
+ continue; /* Can't intersect */;
+ wasc = CoincidentIntersect(m1,m2,pts,t1s,t2s);
+ if ( wasc || m1->s->knownlinear || m2->s->knownlinear ||
+ (m1->s->splines[0].a==0 && m1->s->splines[1].a==0 &&
+ m2->s->splines[0].a==0 && m2->s->splines[1].a==0 )) {
+ if ( !wasc && SplinesIntersect(m1->s,m2->s,pts,t1s,t2s)<=0 )
+ continue;
+ for ( i=0; i<4 && t1s[i]!=-1; ++i ) {
+ if ( t1s[i]>=m1->tstart && t1s[i]<=m1->tend &&
+ t2s[i]>=m2->tstart && t2s[i]<=m2->tend ) {
+ ilist = AddIntersection(ilist,m1,m2,t1s[i],t2s[i],&pts[i]);
+ }
+ }
+ continue;
+ }
+ ilist = FindMonotonicIntersection(ilist,m1,m2);
+ }
+ }
+
+ FigureProperMonotonicsAtIntersections(ilist);
+
+ /* Now suppose we have a contour which intersects nothing? */
+ /* with no intersections we lose track of it and it will vanish */
+ /* That's not a good idea. Make sure each contour has at least one inter */
+ if ( ot!=over_findinter && ot!=over_fisel ) {
+ for ( m1=ms; m1!=NULL; m1=m2->linked ) {
+ if ( m1->start==NULL && m1->end==NULL ) {
+ Intersection *il;
+ il = chunkalloc(sizeof(Intersection));
+ il->inter = m1->s->from->me;
+ il->next = ilist;
+ AddSpline(il,m1,0);
+ AddSpline(il,m1->prev,1.0);
+ ilist = il;
+ }
+ for ( m2=m1; m2->linked==m2->next; m2=m2->linked );
+ }
+ }
+
+return( ilist );
+}
+
+static int dcmp(const void *_p1, const void *_p2) {
+ const extended *dpt1 = _p1, *dpt2 = _p2;
+ if ( *dpt1>*dpt2 )
+return( 1 );
+ else if ( *dpt1<*dpt2 )
+return( -1 );
+
+return( 0 );
+}
+
+static extended *FindOrderedEndpoints(Monotonic *ms,int which) {
+ int cnt;
+ Monotonic *m;
+ extended *ends;
+ int i,j,k;
+
+ for ( m=ms, cnt=0; m!=NULL; m=m->linked, ++cnt );
+ ends = galloc((2*cnt+1)*sizeof(extended));
+ for ( m=ms, cnt=0; m!=NULL; m=m->linked, cnt+=2 ) {
+ if ( m->start!=NULL )
+ ends[cnt] = (&m->start->inter.x)[which];
+ else if ( m->tstart==0 )
+ ends[cnt] = (&m->s->from->me.x)[which];
+ else
+ ends[cnt] = ((m->s->splines[which].a*m->tstart+m->s->splines[which].b)*m->tstart+
+ m->s->splines[which].c)*m->tstart+m->s->splines[which].d;
+ if ( m->end!=NULL )
+ ends[cnt+1] = (&m->end->inter.x)[which];
+ else if ( m->tend==1.0 )
+ ends[cnt+1] = (&m->s->to->me.x)[which];
+ else
+ ends[cnt+1] = ((m->s->splines[which].a*m->tend+m->s->splines[which].b)*m->tend+
+ m->s->splines[which].c)*m->tend+m->s->splines[which].d;
+ }
+
+ qsort(ends,cnt,sizeof(extended),dcmp);
+ for ( i=0; i<cnt; ++i ) {
+ for ( j=i; j<cnt && ends[i]==ends[j]; ++j );
+ if ( j>i+1 ) {
+ for ( k=i+1; j<cnt; ends[k++] = ends[j++]);
+ cnt-= j-k;
+ }
+ }
+ ends[cnt] = 1e10;
+return( ends );
+}
+
+static int mcmp(const void *_p1, const void *_p2) {
+ const Monotonic * const *mpt1 = _p1, * const *mpt2 = _p2;
+ if ( (*mpt1)->other>(*mpt2)->other )
+return( 1 );
+ else if ( (*mpt1)->other<(*mpt2)->other )
+return( -1 );
+
+return( 0 );
+}
+
+int MonotonicFindAt(Monotonic *ms,int which, extended test, Monotonic **space ) {
+ /* Find all monotonic sections which intersect the line (x,y)[which] == test */
+ /* find the value of the other coord on that line */
+ /* Order them (by the other coord) */
+ /* then run along that line figuring out which monotonics are needed */
+ extended t;
+ Monotonic *m, *mm;
+ int i, j, k, cnt;
+ const double error = .0001;
+ int nw = !which;
+
+ for ( m=ms, i=0; m!=NULL; m=m->linked ) {
+ if (( which==0 && test >= m->b.minx && test <= m->b.maxx ) ||
+ ( which==1 && test >= m->b.miny && test <= m->b.maxy )) {
+ /* Lines parallel to the direction we are testing just get in the */
+ /* way and don't add any useful info */
+ if ( m->s->knownlinear &&
+ (( which==1 && m->s->from->me.y==m->s->to->me.y ) ||
+ (which==0 && m->s->from->me.x==m->s->to->me.x)))
+ continue;
+ t = BoundIterateSplineSolve(&m->s->splines[which],m->tstart,m->tend,test,error);
+ if ( t==-1 )
+ continue;
+ m->t = t;
+ if ( t==m->tend ) t -= (m->tend-m->tstart)/100;
+ else if ( t==m->tstart ) t += (m->tend-m->tstart)/100;
+ m->other = ((m->s->splines[nw].a*t+m->s->splines[nw].b)*t+
+ m->s->splines[nw].c)*t+m->s->splines[nw].d;
+ space[i++] = m;
+ }
+ }
+ cnt = i;
+
+ /* Things get a little tricky at end-points */
+ for ( i=0; i<cnt; ++i ) {
+ m = space[i];
+ if ( m->t==m->tend ) {
+ /* Ignore horizontal/vertical lines (as appropriate) */
+ for ( mm=m->next; mm!=m; mm=mm->next ) {
+ if ( !mm->s->knownlinear )
+ break;
+ if (( which==1 && mm->s->from->me.y!=m->s->to->me.y ) ||
+ (which==0 && mm->s->from->me.x!=m->s->to->me.x))
+ break;
+ }
+ } else if ( m->t==m->tstart ) {
+ for ( mm=m->prev; mm!=m; mm=mm->prev ) {
+ if ( !mm->s->knownlinear )
+ break;
+ if (( which==1 && mm->s->from->me.y!=m->s->to->me.y ) ||
+ (which==0 && mm->s->from->me.x!=m->s->to->me.x))
+ break;
+ }
+ } else
+ break;
+ /* If the next monotonic continues in the same direction, and we found*/
+ /* it too, then don't count both. They represent the same intersect */
+ /* If they are in oposite directions then they cancel each other out */
+ /* and that is correct */
+ if ( mm!=m && /* Should always be true */
+ (&mm->xup)[which]==(&m->xup)[which] ) {
+ for ( j=cnt-1; j>=0; --j )
+ if ( space[j]==mm )
+ break;
+ if ( j!=-1 ) {
+ /* remove mm */
+ for ( k=j+1; k<cnt; ++k )
+ space[k-1] = space[k];
+ --cnt;
+ if ( i>j ) --i;
+ }
+ }
+ }
+
+ space[cnt] = NULL; space[cnt+1] = NULL;
+ qsort(space,cnt,sizeof(Monotonic *),mcmp);
+return(cnt);
+}
+
+static void FigureNeeds(Monotonic *ms,int which, extended test, Monotonic **space,
+ enum overlap_type ot, int ignore_close) {
+ /* Find all monotonic sections which intersect the line (x,y)[which] == test */
+ /* find the value of the other coord on that line */
+ /* Order them (by the other coord) */
+ /* then run along that line figuring out which monotonics are needed */
+ int i, j, winding, ew, was_close, close;
+
+ MonotonicFindAt(ms,which,test,space);
+
+#if 0 /* Really slow, and it fixes some problems at the expense of causing others */
+ for ( i=0; space[i+1]!=NULL; ++i ) {
+ /* If two splines are very close to each other, we may miss an */
+ /* intersection. If that has happened, reorder the splines */
+ if ( space[i+1]->other - space[i]->other < .1 ) {
+ extended oi, oi1, ti, ti1, test2;
+ if ( which==1 ) {
+ if ( space[i+1]->b.miny > space[i]->b.miny )
+ test2 = space[i]->b.miny;
+ else
+ test2 = space[i+1]->b.miny;
+ } else {
+ if ( space[i+1]->b.minx > space[i]->b.minx )
+ test2 = space[i]->b.minx;
+ else
+ test2 = space[i+1]->b.minx;
+ }
+ ti = BoundIterateSplineSolve(&space[i]->s->splines[which],
+ space[i]->tstart,space[i]->tend,test2,error);
+ ti1= BoundIterateSplineSolve(&space[i+1]->s->splines[which],
+ space[i+1]->tstart,space[i+1]->tend,test2,error);
+ oi = ((space[i]->s->splines[nw].a*ti+space[i]->s->splines[nw].b)*ti+
+ space[i]->s->splines[nw].c)*ti+space[i]->s->splines[nw].d;
+ oi1= ((space[i+1]->s->splines[nw].a*ti1+space[i+1]->s->splines[nw].b)*ti1+
+ space[i+1]->s->splines[nw].c)*ti1+space[i+1]->s->splines[nw].d;
+ if ( oi1<oi ) {
+ m = space[i];
+ space[i] = space[i+1];
+ space[i+1] = m;
+ fprintf( stderr, "Flipped\n" );
+ }
+ }
+ }
+#endif
+
+ winding = 0; ew = 0; was_close = false;
+ for ( i=0; space[i]!=NULL; ++i ) {
+ int needed, unneeded, inverted=false;
+ Monotonic *m;
+ int new;
+ int nwinding;
+ retry:
+ needed = false, unneeded = false;
+ nwinding=winding;
+ new=ew;
+ m = space[i];
+ if ( m->exclude )
+ new += ( (&m->xup)[which] ? 1 : -1 );
+ else
+ nwinding += ( (&m->xup)[which] ? 1 : -1 );
+ if ( ot==over_remove || ot==over_rmselected ) {
+ if ( winding==0 || nwinding==0 )
+ needed = true;
+ else
+ unneeded = true;
+ } else if ( ot==over_intersect || ot==over_intersel ) {
+ if ( (winding>-2 && winding<2 && nwinding>-2 && nwinding<2) ||
+ ((winding<=-2 || winding>=2) && (nwinding<=-2 && nwinding>=2)))
+ unneeded = true;
+ else
+ needed = true;
+ } else if ( ot == over_exclude ) {
+ if ( (( winding==0 || nwinding==0 ) && ew==0 && new==0 ) ||
+ (winding!=0 && (( ew!=0 && new==0 ) || ( ew==0 && new!=0))) )
+ needed = true;
+ else
+ unneeded = true;
+ }
+ if ( space[i+1]!=NULL )
+ close = space[i+1]->other-space[i]->other < 1;
+ else
+ close = false;
+ if (( !close && !was_close ) || ignore_close ) {
+ if (( m->isneeded || m->isunneeded ) && m->isneeded!=needed ) {
+ for ( j=i+1; space[j]!=NULL && space[j]->other-m->other<.5; ++j ) {
+ if ( space[j]->start==m->start && space[j]->end==m->end &&
+ (space[j]->isneeded == needed ||
+ (!space[j]->isneeded && !space[j]->isunneeded))) {
+ space[i] = space[j];
+ space[j] = m;
+ m = space[i];
+ break;
+ } else if ( !inverted && space[j]->other-m->other<.001 &&
+ (((&space[j]->xup)[which] == (&m->xup)[which] &&
+ (space[j]->isneeded == needed ||
+ (!space[j]->isneeded && !space[j]->isunneeded))) ||
+ ((&space[j]->xup)[which] != (&m->xup)[which] &&
+ (space[j]->isneeded != needed ||
+ (!space[j]->isneeded && !space[j]->isunneeded)))) ) {
+ space[i] = space[j];
+ space[j] = m;
+ inverted = true;
+ goto retry;
+ }
+ }
+ }
+ if ( !m->isneeded && !m->isunneeded ) {
+ m->isneeded = needed; m->isunneeded = unneeded;
+ m->when_set = test; /* Debugging */
+ } else if ( m->isneeded!=needed || m->isunneeded!=unneeded )
+ SOError( "monotonic is both needed and unneeded.\n" );
+ }
+ winding = nwinding;
+ ew = new;
+ was_close = close;
+ }
+ if ( winding!=0 )
+ SOError( "Winding number did not return to 0 when %s=%g\n",
+ which ? "y" : "x", test );
+}
+
+struct gaps { extended test, len; int which; };
+
+static int gcmp(const void *_p1, const void *_p2) {
+ const struct gaps *gpt1 = _p1, *gpt2 = _p2;
+ if ( gpt1->len > gpt2->len )
+return( 1 );
+ else if ( gpt1->len < gpt2->len )
+return( -1 );
+
+return( 0 );
+}
+
+static void FindNeeded(Monotonic *ms,enum overlap_type ot) {
+ extended *ends[2];
+ Monotonic *m, **space;
+ extended top, bottom, test;
+ int t,b,i,j,k,cnt,which;
+ struct gaps *gaps;
+ extended min_gap;
+
+ if ( ms==NULL )
+return;
+
+ ends[0] = FindOrderedEndpoints(ms,0);
+ ends[1] = FindOrderedEndpoints(ms,1);
+
+ for ( m=ms, cnt=0; m!=NULL; m=m->linked, ++cnt );
+ space = galloc((cnt+2)*sizeof(Monotonic*));
+ gaps = galloc(2*cnt*sizeof(struct gaps));
+
+ /* Look for the longest splines without interruptions first. These are */
+ /* least likely to cause problems and will give us a good basis from which*/
+ /* to make guesses should rounding errors occur later */
+ for ( j=k=0; j<2; ++j )
+ for ( i=0; ends[j][i+1]!=1e10; ++i ) {
+ gaps[k].which = j;
+ gaps[k].len = (ends[j][i+1]-ends[j][i]);
+ gaps[k++].test = (ends[j][i+1]+ends[j][i])/2;
+ }
+ qsort(gaps,k,sizeof(struct gaps),gcmp);
+ min_gap = 1e10;
+ for ( m=ms; m!=NULL; m=m->linked ) {
+ if ( m->b.maxx-m->b.minx > m->b.maxy-m->b.miny ) {
+ if ( min_gap > m->b.maxx-m->b.minx ) min_gap = m->b.maxx-m->b.minx;
+ } else {
+ if ( m->b.maxy-m->b.miny==0 )
+ fprintf( stderr, "Foo\n");
+ if ( min_gap > m->b.maxy-m->b.miny ) min_gap = m->b.maxy-m->b.miny;
+ }
+ }
+ if ( min_gap<.5 ) min_gap = .5;
+ for ( i=0; i<k && gaps[i].len>=min_gap; ++i )
+ FigureNeeds(ms,gaps[i].which,gaps[i].test,space,ot,0);
+
+ for ( m=ms; m!=NULL; m=m->linked ) if ( !m->isneeded && !m->isunneeded ) {
+ if ( m->b.maxx-m->b.minx > m->b.maxy-m->b.miny ) {
+ top = m->b.maxx;
+ bottom = m->b.minx;
+ which = 0;
+ } else {
+ top = m->b.maxy;
+ bottom = m->b.miny;
+ which = 1;
+ }
+ for ( b=0; ends[which][b]<=bottom; ++b );
+ for ( t=b; ends[which][t]<top; ++t );
+ --t;
+ /* b points to an endpoint which is greater than bottom */
+ /* t points to an endpoint which is less than top */
+ test = (top+bottom)/2;
+ for ( i=b; i<=t; ++i ) {
+ if ( RealNearish(test,ends[which][i]) ) {
+ if ( i==b )
+ test = (bottom+ends[which][i])/2;
+ else
+ test = (ends[which][i-1]+ends[which][i])/2;
+ break;
+ }
+ }
+ FigureNeeds(ms,which,test,space,ot,1);
+ }
+ free(ends[0]);
+ free(ends[1]);
+ free(space);
+ free(gaps);
+}
+
+static void FindUnitVectors(Intersection *ilist) {
+ MList *ml;
+ Intersection *il;
+ BasePoint u;
+ double len;
+
+ for ( il=ilist; il!=NULL; il=il->next ) {
+ for ( ml=il->monos; ml!=NULL; ml=ml->next ) {
+ if ( ml->m->isneeded ) {
+ Spline *s = ml->m->s;
+ double t1, t2;
+ t1 = ml->t;
+ if ( ml->isend )
+ t2 = ml->t - (ml->t-ml->m->tstart)/20.0;
+ else
+ t2 = ml->t + (ml->m->tend-ml->t)/20.0;
+ u.x = ((s->splines[0].a*t1 + s->splines[0].b)*t1 + s->splines[0].c)*t1 -
+ ((s->splines[0].a*t2 + s->splines[0].b)*t2 + s->splines[0].c)*t2;
+ u.y = ((s->splines[1].a*t1 + s->splines[1].b)*t1 + s->splines[1].c)*t1 -
+ ((s->splines[1].a*t2 + s->splines[1].b)*t2 + s->splines[1].c)*t2;
+ len = u.x*u.x + u.y*u.y;
+ if ( len!=0 ) {
+ len = sqrt(len);
+ u.x /= len;
+ u.y /= len;
+ }
+ ml->unit = u;
+ }
+ }
+ }
+}
+
+static void TestForBadDirections(Intersection *ilist) {
+ /* If we have a glyph with at least two contours one drawn clockwise, */
+ /* one counter, and these two intersect, then our algorithm will */
+ /* not remove what appears to the user to be an overlap. Warn about */
+ /* this. */
+ /* I think it happens iff all exits from an intersection are needed */
+ MList *ml, *ml2;
+ int cnt, ncnt;
+ Intersection *il;
+
+ /* If we have two splines one going from a->b and the other from b->a */
+ /* tracing exactly the same route, then they should cancel each other */
+ /* out. But depending on the order we hit them they may both be marked */
+ /* needed */ /* OverlapBugs.sfd: asciicircumflex */
+ for ( il=ilist; il!=NULL; il=il->next ) {
+ for ( ml=il->monos; ml!=NULL; ml=ml->next ) {
+ if ( ml->m->isneeded && ml->m->s->knownlinear &&
+ ml->m->start!=NULL && ml->m->end!=NULL ) {
+ for ( ml2 = ml->next; ml2!=NULL; ml2=ml2->next ) {
+ if ( ml2->m->isneeded && ml2->m->s->knownlinear &&
+ ml2->m->start == ml->m->end &&
+ ml2->m->end == ml->m->start ) {
+ ml2->m->isneeded = false;
+ ml->m->isneeded = false;
+ ml2->m->isunneeded = true;
+ ml->m->isunneeded = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ while ( ilist!=NULL ) {
+ cnt = ncnt = 0;
+ for ( ml = ilist->monos; ml!=NULL; ml=ml->next ) {
+ ++cnt;
+ if ( ml->m->isneeded ) ++ncnt;
+ }
+#if 0
+ if ( cnt>=4 && ncnt==cnt ) {
+ ff_post_notice(_("Warning"),_("Glyph %.40s contains an overlapped region where two contours with opposite orientations intersect. This will not be removed. In many cases doing Element->Correct Direction before Remove Overlap will improve matters."),
+ glyphname );
+ fprintf( stderr, "%s: Fully needed intersection at (%g,%g)\n",
+ glyphname,
+ ilist->inter.x, ilist->inter.y );
+ break;
+ }
+#endif
+ ilist = ilist->next;
+ }
+}
+
+static void MonoFigure(Spline *s,extended firstt,extended endt, SplinePoint *first,
+ SplinePoint *end) {
+ extended f;
+ Spline1D temp;
+
+ f = endt - firstt;
+ /*temp.d = first->me.x;*/
+ /*temp.a = s->splines[0].a*f*f*f;*/
+ temp.b = (s->splines[0].b + 3*s->splines[0].a*firstt) *f*f;
+ temp.c = (s->splines[0].c + 2*s->splines[0].b*firstt + 3*s->splines[0].a*firstt*firstt) * f;
+ first->nextcp.x = first->me.x + temp.c/3;
+ end->prevcp.x = first->nextcp.x + (temp.b+temp.c)/3;
+ if ( temp.c>-.01 && temp.c<.01 ) first->nextcp.x = first->me.x;
+ if ( (temp.b+temp.c)>-.01 && (temp.b+temp.c)<.01 ) end->prevcp.x = end->me.x;
+
+ temp.b = (s->splines[1].b + 3*s->splines[1].a*firstt) *f*f;
+ temp.c = (s->splines[1].c + 2*s->splines[1].b*firstt + 3*s->splines[1].a*firstt*firstt) * f;
+ first->nextcp.y = first->me.y + temp.c/3;
+ end->prevcp.y = first->nextcp.y + (temp.b+temp.c)/3;
+ if ( temp.c>-.01 && temp.c<.01 ) first->nextcp.y = first->me.y;
+ if ( (temp.b+temp.c)>-.01 && (temp.b+temp.c)<.01 ) end->prevcp.y = end->me.y;
+ first->nonextcp = false; end->noprevcp = false;
+ SplineMake3(first,end);
+ if ( SplineIsLinear(first->next)) {
+ first->nextcp = first->me;
+ end->prevcp = end->me;
+ first->nonextcp = end->noprevcp = true;
+ SplineRefigure(first->next);
+ }
+}
+
+static Intersection *MonoFollow(Intersection *curil, Monotonic *m) {
+ Monotonic *mstart=m;
+
+ if ( m->start==curil ) {
+ while ( m!=NULL && m->end==NULL ) {
+ m=m->next;
+ if ( m==mstart )
+ break;
+ }
+ if ( m==NULL )
+return( NULL );
+
+return( m->end );
+ } else {
+ while ( m!=NULL && m->start==NULL ) {
+ m=m->prev;
+ if ( m==mstart )
+ break;
+ }
+ if ( m==NULL )
+return( NULL );
+
+return( m->start );
+ }
+}
+
+static int MonoGoesSomewhereUseful(Intersection *curil, Monotonic *m) {
+ Intersection *nextil = MonoFollow(curil,m);
+ MList *ml;
+ int cnt;
+
+ if ( nextil==NULL )
+return( false );
+ cnt = 0;
+ for ( ml=nextil->monos; ml!=NULL ; ml=ml->next )
+ if ( ml->m->isneeded )
+ ++cnt;
+ if ( cnt>=2 ) /* One for the mono that one in, one for another going out... */
+return( true );
+
+return( false );
+}
+
+static MList *FindMLOfM(Intersection *curil,Monotonic *finalm) {
+ MList *ml;
+
+ for ( ml=curil->monos; ml!=NULL; ml=ml->next ) {
+ if ( ml->m==finalm )
+return( ml );
+ }
+#if 0
+ if ( ml->isend ) {
+ for ( m=ml->m; m!=NULL ; m=m->prev ) {
+ if ( m==finalm )
+return( ml );
+ if ( m->start != NULL )
+ break;
+ }
+ } else {
+ for ( m=ml->m; m!=NULL; m=m->next ) {
+ if ( m==finalm )
+return( ml );
+ if ( m->end!=NULL )
+ break;
+ }
+ }
+ }
+#endif
+return( NULL );
+}
+
+static SplinePoint *MonoFollowForward(Intersection **curil, MList *ml,
+ SplinePoint *last, Monotonic **finalm) {
+ SplinePoint *mid;
+ Monotonic *m = ml->m, *mstart;
+
+ forever {
+ for ( mstart = m; m->s==mstart->s; m=m->next) {
+ if ( !m->isneeded )
+ SOError( "Expected needed monotonic.\n" );
+ m->isneeded = false; /* Mark as used */
+ if ( m->end!=NULL )
+ break;
+ }
+ if ( m->s==mstart->s ) {
+ if ( m->end==NULL ) SOError( "Invariant condition does not hold.\n" );
+ mid = SplinePointCreate(m->end->inter.x,m->end->inter.y);
+ } else {
+ m = m->prev;
+ mid = SplinePointCreate(m->s->to->me.x,m->s->to->me.y);
+ }
+ if ( mstart->tstart==0 && m->tend==1.0 ) {
+ /* I check for this special case to avoid rounding errors */
+ last->nextcp = m->s->from->nextcp;
+ last->nonextcp = m->s->from->nonextcp;
+ mid->prevcp = m->s->to->prevcp;
+ mid->noprevcp = m->s->to->noprevcp;
+ SplineMake3(last,mid);
+ } else {
+ MonoFigure(m->s,mstart->tstart,m->tend,last,mid);
+ }
+ last = mid;
+ if ( m->end!=NULL ) {
+ *curil = m->end;
+ *finalm = m;
+return( last );
+ }
+ m = m->next;
+ }
+}
+
+static SplinePoint *MonoFollowBackward(Intersection **curil, MList *ml,
+ SplinePoint *last, Monotonic **finalm) {
+ SplinePoint *mid;
+ Monotonic *m = ml->m, *mstart;
+
+ forever {
+ for ( mstart=m; m->s==mstart->s; m=m->prev) {
+ if ( !m->isneeded )
+ SOError( "Expected needed monotonic.\n" );
+ m->isneeded = false; /* Mark as used */
+ if ( m->start!=NULL )
+ break;
+ }
+ if ( m->s==mstart->s ) {
+ if ( m->start==NULL ) SOError( "Invariant condition does not hold.\n" );
+ mid = SplinePointCreate(m->start->inter.x,m->start->inter.y);
+ } else {
+ m = m->next;
+ mid = SplinePointCreate(m->s->from->me.x,m->s->from->me.y);
+ }
+ if ( m->s->knownlinear ) mid->pointtype = pt_corner;
+ if ( mstart->tend==1.0 && m->tstart==0 ) {
+ /* I check for this special case to avoid rounding errors */
+ last->nextcp = m->s->to->prevcp;
+ last->nonextcp = m->s->to->noprevcp;
+ mid->prevcp = m->s->from->nextcp;
+ mid->noprevcp = m->s->from->nonextcp;
+ SplineMake3(last,mid);
+ } else {
+ MonoFigure(m->s,mstart->tend,m->tstart,last,mid);
+ }
+ last = mid;
+ if ( m->start!=NULL ) {
+ *curil = m->start;
+ *finalm = m;
+return( last );
+ }
+ m = m->prev;
+ }
+}
+
+static SplineSet *JoinAContour(Intersection *startil,MList *ml) {
+ SplineSet *ss = chunkalloc(sizeof(SplineSet));
+ SplinePoint *last;
+ Intersection *curil;
+ int allexclude = ml->m->exclude;
+ Monotonic *finalm;
+ MList *lastml;
+
+ ss->first = last = SplinePointCreate(startil->inter.x,startil->inter.y);
+ curil = startil;
+ forever {
+ if ( allexclude && !ml->m->exclude ) allexclude = false;
+ finalm = NULL;
+ if ( ml->m->start==curil ) {
+ last = MonoFollowForward(&curil,ml,last,&finalm);
+ } else if ( ml->m->end==curil ) {
+ last = MonoFollowBackward(&curil,ml,last,&finalm);
+ } else {
+ SOError( "Couldn't find endpoint (%g,%g).\n",
+ curil->inter.x, curil->inter.y );
+ ml->m->isneeded = false; /* Prevent infinite loops */
+ ss->last = last;
+ break;
+ }
+ if ( curil==startil ) {
+ ss->first->prev = last->prev;
+ ss->first->prevcp = last->prevcp;
+ ss->first->noprevcp = last->noprevcp;
+ last->prev->to = ss->first;
+ SplinePointFree(last);
+ ss->last = ss->first;
+ break;
+ }
+ lastml = FindMLOfM(curil,finalm);
+ if ( lastml==NULL ) {
+ IError("Could not find finalm");
+ /* Try to preserve direction */
+ for ( ml=curil->monos; ml!=NULL && (!ml->m->isneeded || ml->m->end==curil); ml=ml->next );
+ if ( ml==NULL )
+ for ( ml=curil->monos; ml!=NULL && !ml->m->isneeded; ml=ml->next );
+ } else {
+ int k; MList *bestml; double bestdot;
+ for ( k=0; k<2; ++k ) {
+ bestml = NULL; bestdot = -2;
+ for ( ml=curil->monos; ml!=NULL ; ml=ml->next ) {
+ if ( ml->m->isneeded && (ml->m->start==curil || k) ) {
+ double dot = lastml->unit.x*ml->unit.x + lastml->unit.y*ml->unit.y;
+ if ( dot>bestdot ) {
+ bestml = ml;
+ bestdot = dot;
+ }
+ }
+ }
+ if ( bestml!=NULL )
+ break;
+ }
+ ml = bestml;
+ }
+ if ( ml==NULL ) {
+ for ( ml=curil->monos; ml!=NULL ; ml=ml->next )
+ if ( ml->m->isunneeded && ml->m->start==curil &&
+ MonoFollow(curil,ml->m)==startil )
+ break;
+ if ( ml==NULL )
+ for ( ml=curil->monos; ml!=NULL ; ml=ml->next )
+ if ( ml->m->isunneeded && ml->m->end==curil &&
+ MonoFollow(curil,ml->m)==startil )
+ break;
+ if ( ml!=NULL ) {
+ SOError("Closing contour with unneeded path\n" );
+ ml->m->isneeded = true;
+ }
+ }
+ if ( ml==NULL ) {
+ SOError( "couldn't find a needed exit from an intersection\n" );
+ ss->last = last;
+ break;
+ }
+ }
+ SPLCatagorizePoints(ss);
+ if ( allexclude && SplinePointListIsClockwise(ss))
+ SplineSetReverse(ss);
+return( ss );
+}
+
+static SplineSet *FindMatchingContour(SplineSet *head,SplineSet *cur) {
+ SplineSet *test;
+
+ for ( test=head; test!=NULL; test=test->next ) {
+ if ( test->first->prev==NULL &&
+ test->first->me.x==cur->last->me.x && test->first->me.y==cur->last->me.y &&
+ test->last->me.x==cur->first->me.x && test->last->me.y==cur->first->me.y )
+ break;
+ }
+ if ( test==NULL ) {
+ for ( test=head; test!=NULL; test=test->next ) {
+ if ( test->first->prev==NULL &&
+ test->last->me.x==cur->last->me.x && test->last->me.y==cur->last->me.y &&
+ test->first->me.x==cur->first->me.x && test->first->me.y==cur->first->me.y ) {
+ SplineSetReverse(cur);
+ break;
+ }
+ }
+ }
+ if ( test==NULL ) {
+ for ( test=head; test!=NULL; test=test->next ) {
+ if ( test->first->prev==NULL &&
+ ((test->first->me.x==cur->last->me.x && test->first->me.y==cur->last->me.y) ||
+ (test->last->me.x==cur->first->me.x && test->last->me.y==cur->first->me.y )))
+ break;
+ }
+ }
+ if ( test==NULL ) {
+ for ( test=head; test!=NULL; test=test->next ) {
+ if ( test->first->prev==NULL &&
+ ((test->last->me.x==cur->last->me.x && test->last->me.y==cur->last->me.y) ||
+ (test->first->me.x==cur->first->me.x && test->first->me.y==cur->first->me.y ))) {
+ SplineSetReverse(cur);
+ break;
+ }
+ }
+ }
+return( test );
+}
+
+static SplineSet *JoinAllNeeded(Intersection *ilist) {
+ Intersection *il;
+ SplineSet *head=NULL, *last=NULL, *cur, *test;
+ MList *ml;
+
+ for ( il=ilist; il!=NULL; il=il->next ) {
+ /* Try to preserve direction */
+ forever {
+ for ( ml=il->monos; ml!=NULL && (!ml->m->isneeded || ml->m->end==il); ml=ml->next );
+ if ( ml==NULL )
+ for ( ml=il->monos; ml!=NULL && !ml->m->isneeded; ml=ml->next );
+ if ( ml==NULL )
+ break;
+ if ( !MonoGoesSomewhereUseful(il,ml->m)) {
+ SOError("Humph. This monotonic leads nowhere.\n" );
+ /* break; */
+ }
+ cur = JoinAContour(il,ml);
+ if ( head==NULL )
+ head = cur;
+ else {
+ if ( cur->first->prev==NULL ) {
+ /* Open contours are errors. See if we had an earlier error */
+ /* to which we can join this */
+ test = FindMatchingContour(head,cur);
+ if ( test!=NULL ) {
+ if ( test->first->me.x==cur->last->me.x && test->first->me.y==cur->last->me.y ) {
+ test->first->prev = cur->last->prev;
+ cur->last->prev->to = test->first;
+ SplinePointFree(cur->last);
+ if ( test->last->me.x==cur->first->me.x && test->last->me.y==cur->first->me.y ) {
+ test->last->next = cur->first->next;
+ cur->first->next->from = test->last;
+ SplinePointFree(cur->first);
+ test->last = test->first;
+ } else
+ test->first = cur->first;
+ } else {
+ if ( test->last->me.x!=cur->first->me.x || test->last->me.y!=cur->first->me.y )
+ SOError( "Join failed");
+ else {
+ test->last->next = cur->first->next;
+ cur->first->next->from = test->last;
+ SplinePointFree(cur->first);
+ test->last = test->first;
+ }
+ }
+ cur->first = cur->last = NULL;
+ SplinePointListFree(cur);
+ cur=NULL;
+ }
+ }
+ if ( cur!=NULL )
+ last->next = cur;
+ }
+ if ( cur!=NULL )
+ last = cur;
+ }
+ }
+return( head );
+}
+
+static SplineSet *MergeOpenAndFreeClosed(SplineSet *new,SplineSet *old,
+ enum overlap_type ot) {
+ SplineSet *next;
+
+ while ( old!=NULL ) {
+ next = old->next;
+ if ( old->first->prev==NULL ||
+ (( ot==over_rmselected || ot==over_intersel || ot==over_fisel) &&
+ !SSIsSelected(old)) ) {
+ old->next = new;
+ new = old;
+ } else {
+ old->next = NULL;
+ SplinePointListFree(old);
+ }
+ old = next;
+ }
+return(new);
+}
+
+void FreeMonotonics(Monotonic *m) {
+ Monotonic *next;
+
+ while ( m!=NULL ) {
+ next = m->linked;
+ chunkfree(m,sizeof(*m));
+ m = next;
+ }
+}
+
+static void FreeMList(MList *ml) {
+ MList *next;
+
+ while ( ml!=NULL ) {
+ next = ml->next;
+ chunkfree(ml,sizeof(*ml));
+ ml = next;
+ }
+}
+
+static void FreeIntersections(Intersection *ilist) {
+ Intersection *next;
+
+ while ( ilist!=NULL ) {
+ next = ilist->next;
+ FreeMList(ilist->monos);
+ chunkfree(ilist,sizeof(*ilist));
+ ilist = next;
+ }
+}
+
+static void MonoSplit(Monotonic *m) {
+ Spline *s = m->s;
+ SplinePoint *last = s->from;
+ SplinePoint *final = s->to;
+ extended lastt = 0;
+
+ last->next = NULL;
+ final->prev = NULL;
+ while ( m!=NULL && m->s==s && m->tend<1 ) {
+ if ( m->end!=NULL ) {
+ SplinePoint *mid = SplinePointCreate(m->end->inter.x,m->end->inter.y);
+ if ( m->s->knownlinear ) mid->pointtype = pt_corner;
+ MonoFigure(s,lastt,m->tend,last,mid);
+ lastt = m->tend;
+ last = mid;
+ }
+ m = m->linked;
+ }
+ MonoFigure(s,lastt,1.0,last,final);
+ SplineFree(s);
+}
+
+static void FixupIntersectedSplines(Monotonic *ms) {
+ /* If all we want is intersections, then the contours are already correct */
+ /* all we need to do is run through the Monotonic list and when we find */
+ /* an intersection, make sure it has real splines around it */
+ Monotonic *m;
+ int needs_split;
+
+ while ( ms!=NULL ) {
+ needs_split = false;
+ for ( m=ms; m!=NULL && m->s==ms->s; m=m->linked ) {
+ if ( (m->tstart!=0 && m->start!=NULL) || (m->tend!=1 && m->end!=NULL))
+ needs_split = true;
+ }
+ if ( needs_split )
+ MonoSplit(ms);
+ ms = m;
+ }
+}
+
+static int BpClose(BasePoint *here, BasePoint *there, double error) {
+ extended dx, dy;
+
+ if ( (dx = here->x-there->x)<0 ) dx= -dx;
+ if ( (dy = here->y-there->y)<0 ) dy= -dy;
+ if ( dx<error && dy<error )
+return( true );
+
+return( false );
+}
+
+static SplineSet *SSRemoveTiny(SplineSet *base) {
+ DBounds b;
+ double error;
+ extended test, dx, dy;
+ SplineSet *prev = NULL, *head = base, *ssnext;
+ SplinePoint *sp, *nsp;
+
+ SplineSetQuickBounds(base,&b);
+ error = b.maxy-b.miny;
+ test = b.maxx-b.minx;
+ if ( test>error ) error = test;
+ if ( (test = b.maxy)<0 ) test = -test;
+ if ( test>error ) error = test;
+ if ( (test = b.maxx)<0 ) test = -test;
+ if ( test>error ) error = test;
+ error /= 30000;
+
+ while ( base!=NULL ) {
+ ssnext = base->next;
+ for ( sp=base->first; ; ) {
+ if ( sp->next==NULL )
+ break;
+ nsp = sp->next->to;
+ if ( BpClose(&sp->me,&nsp->me,error) ) {
+ if ( BpClose(&sp->me,&sp->nextcp,2*error) &&
+ BpClose(&nsp->me,&nsp->prevcp,2*error)) {
+ /* Remove the spline */
+ if ( nsp==sp ) {
+ /* Only this spline in the contour, so remove the contour */
+ base->next = NULL;
+ SplinePointListFree(base);
+ if ( prev==NULL )
+ head = ssnext;
+ else
+ prev->next = ssnext;
+ base = NULL;
+ break;
+ }
+ SplineFree(sp->next);
+ if ( nsp->nonextcp ) {
+ sp->nextcp = sp->me;
+ sp->nonextcp = true;
+ } else {
+ sp->nextcp = nsp->nextcp;
+ sp->nonextcp = false;
+ }
+ sp->nextcpdef = nsp->nextcpdef;
+ sp->next = nsp->next;
+ if ( nsp->next!=NULL ) {
+ nsp->next->from = sp;
+ SplineRefigure(sp->next);
+ }
+ if ( nsp==base->last )
+ base->last = sp;
+ if ( nsp==base->first )
+ base->first = sp;
+ SplinePointFree(nsp);
+ if ( sp->next==NULL )
+ break;
+ nsp = sp->next->to;
+ } else {
+ /* Leave the spline, but move the two points together */
+ BasePoint new;
+ new.x = (sp->me.x+nsp->me.x)/2;
+ new.y = (sp->me.y+nsp->me.y)/2;
+ dx = new.x-sp->me.x; dy = new.y-sp->me.y;
+ sp->me = new;
+ sp->nextcp.x += dx; sp->nextcp.y += dy;
+ sp->prevcp.x += dx; sp->prevcp.y += dy;
+ dx = new.x-nsp->me.x; dy = new.y-nsp->me.y;
+ nsp->me = new;
+ nsp->nextcp.x += dx; nsp->nextcp.y += dy;
+ nsp->prevcp.x += dx; nsp->prevcp.y += dy;
+ SplineRefigure(sp->next);
+ if ( sp->prev ) SplineRefigure(sp->prev);
+ if ( nsp->next ) SplineRefigure(nsp->next);
+ }
+ }
+ sp = nsp;
+ if ( sp==base->first )
+ break;
+ }
+ if ( sp->prev!=NULL && !sp->noprevcp ) {
+ int refigure = false;
+ if ( sp->me.x-sp->prevcp.x>-error && sp->me.x-sp->prevcp.x<error ) {
+ sp->prevcp.x = sp->me.x;
+ refigure = true;
+ }
+ if ( sp->me.y-sp->prevcp.y>-error && sp->me.y-sp->prevcp.y<error ) {
+ sp->prevcp.y = sp->me.y;
+ refigure = true;
+ }
+ if ( sp->me.x==sp->prevcp.x && sp->me.y==sp->prevcp.y )
+ sp->noprevcp = true;
+ if ( refigure )
+ SplineRefigure(sp->prev);
+ }
+ if ( sp->next!=NULL && !sp->nonextcp ) {
+ int refigure = false;
+ if ( sp->me.x-sp->nextcp.x>-error && sp->me.x-sp->nextcp.x<error ) {
+ sp->nextcp.x = sp->me.x;
+ refigure = true;
+ }
+ if ( sp->me.y-sp->nextcp.y>-error && sp->me.y-sp->nextcp.y<error ) {
+ sp->nextcp.y = sp->me.y;
+ refigure = true;
+ }
+ if ( sp->me.x==sp->nextcp.x && sp->me.y==sp->nextcp.y )
+ sp->nonextcp = true;
+ if ( refigure )
+ SplineRefigure(sp->next);
+ }
+ if ( base!=NULL )
+ prev = base;
+ base = ssnext;
+ }
+
+return( head );
+}
+
+static void RemoveNextSP(SplinePoint *psp,SplinePoint *sp,SplinePoint *nsp,
+ SplineSet *base) {
+ if ( psp==nsp ) {
+ SplineFree(psp->next);
+ psp->next = psp->prev;
+ psp->next->from = psp;
+ SplinePointFree(sp);
+ SplineRefigure(psp->prev);
+ } else {
+ psp->next = nsp->next;
+ psp->next->from = psp;
+ psp->nextcp = nsp->nextcp;
+ psp->nonextcp = nsp->nonextcp;
+ psp->nextcpdef = nsp->nextcpdef;
+ SplineFree(sp->prev);
+ SplineFree(sp->next);
+ SplinePointFree(sp);
+ SplinePointFree(nsp);
+ SplineRefigure(psp->next);
+ }
+ if ( base->first==sp || base->first==nsp )
+ base->first = psp;
+ if ( base->last==sp || base->last==nsp )
+ base->last = psp;
+}
+
+static void RemovePrevSP(SplinePoint *psp,SplinePoint *sp,SplinePoint *nsp,
+ SplineSet *base) {
+ if ( psp==nsp ) {
+ SplineFree(nsp->prev);
+ nsp->prev = nsp->next;
+ nsp->prev->to = nsp;
+ SplinePointFree(sp);
+ SplineRefigure(nsp->next);
+ } else {
+ nsp->prev = psp->prev;
+ nsp->prev->to = nsp;
+ nsp->prevcp = nsp->me;
+ nsp->noprevcp = true;
+ nsp->prevcpdef = psp->prevcpdef;
+ SplineFree(sp->prev);
+ SplineFree(sp->next);
+ SplinePointFree(sp);
+ SplinePointFree(psp);
+ SplineRefigure(nsp->prev);
+ }
+ if ( base->first==sp || base->first==psp )
+ base->first = nsp;
+ if ( base->last==sp || base->last==psp )
+ base->last = nsp;
+}
+
+static SplinePoint *SameLine(SplinePoint *psp, SplinePoint *sp, SplinePoint *nsp) {
+ BasePoint noff, poff;
+ real nlen, plen, normal;
+
+ noff.x = nsp->me.x-sp->me.x; noff.y = nsp->me.y-sp->me.y;
+ poff.x = psp->me.x-sp->me.x; poff.y = psp->me.y-sp->me.y;
+ nlen = esqrt(noff.x*noff.x + noff.y*noff.y);
+ plen = esqrt(poff.x*poff.x + poff.y*poff.y);
+ if ( nlen==0 )
+return( nsp );
+ if ( plen==0 )
+return( psp );
+ normal = (noff.x*poff.y - noff.y*poff.x)/nlen/plen;
+ if ( normal<-.0001 || normal>.0001 )
+return( NULL );
+
+ if ( noff.x*poff.x < 0 || noff.y*poff.y < 0 )
+return( NULL ); /* Same line, but different directions */
+ if ( (noff.x>0 && noff.x>poff.x) ||
+ (noff.x<0 && noff.x<poff.x) ||
+ (noff.y>0 && noff.y>poff.y) ||
+ (noff.y<0 && noff.y<poff.y))
+return( nsp );
+
+return( psp );
+}
+
+static double AdjacentSplinesMatch(Spline *s1,Spline *s2,int s2forward) {
+ /* Is every point on s2 close to a point on s1 */
+ double t, tdiff, t1 = -1;
+ double xoff, yoff;
+ double t1start, t1end;
+ extended ts[2];
+ int i;
+
+ if ( (xoff = s2->to->me.x-s2->from->me.x)<0 ) xoff = -xoff;
+ if ( (yoff = s2->to->me.y-s2->from->me.y)<0 ) yoff = -yoff;
+ if ( xoff>yoff )
+ SplineFindExtrema(&s1->splines[0],&ts[0],&ts[1]);
+ else
+ SplineFindExtrema(&s1->splines[1],&ts[0],&ts[1]);
+ if ( s2forward ) {
+ t = 0;
+ tdiff = 1/16.0;
+ t1end = 1;
+ for ( i=1; i>=0 && ts[i]==-1; --i );
+ t1start = i<0 ? 0 : ts[i];
+ } else {
+ t = 1;
+ tdiff = -1/16.0;
+ t1start = 0;
+ t1end = ( ts[0]==-1 ) ? 1.0 : ts[0];
+ }
+
+ for ( ; (s2forward && t<=1) || (!s2forward && t>=0 ); t += tdiff ) {
+ double x1, y1, xo, yo;
+ double x = ((s2->splines[0].a*t+s2->splines[0].b)*t+s2->splines[0].c)*t+s2->splines[0].d;
+ double y = ((s2->splines[1].a*t+s2->splines[1].b)*t+s2->splines[1].c)*t+s2->splines[1].d;
+ if ( xoff>yoff )
+ t1 = IterateSplineSolve(&s1->splines[0],t1start,t1end,x,.001);
+ else
+ t1 = IterateSplineSolve(&s1->splines[1],t1start,t1end,y,.001);
+ if ( t1<0 || t1>1 )
+return( -1 );
+ x1 = ((s1->splines[0].a*t1+s1->splines[0].b)*t1+s1->splines[0].c)*t1+s1->splines[0].d;
+ y1 = ((s1->splines[1].a*t1+s1->splines[1].b)*t1+s1->splines[1].c)*t1+s1->splines[1].d;
+ if ( (xo = (x-x1))<0 ) xo = -xo;
+ if ( (yo = (y-y1))<0 ) yo = -yo;
+ if ( xo+yo>.5 )
+return( -1 );
+ }
+return( t1 );
+}
+
+void SSRemoveBacktracks(SplineSet *ss) {
+ SplinePoint *sp;
+
+ if ( ss==NULL )
+return;
+ for ( sp=ss->first; ; ) {
+ if ( sp->next!=NULL && sp->prev!=NULL ) {
+ SplinePoint *nsp = sp->next->to, *psp = sp->prev->from, *isp;
+ BasePoint ndir, pdir;
+ double dot, pdot, nlen, plen, t = -1;
+
+ ndir.x = (nsp->me.x - sp->me.x); ndir.y = (nsp->me.y - sp->me.y);
+ pdir.x = (psp->me.x - sp->me.x); pdir.y = (psp->me.y - sp->me.y);
+ nlen = ndir.x*ndir.x + ndir.y*ndir.y; plen = pdir.x*pdir.x + pdir.y*pdir.y;
+ dot = ndir.x*pdir.x + ndir.y*pdir.y;
+ if ( (pdot = ndir.x*pdir.y - ndir.y*pdir.x)<0 ) pdot = -pdot;
+ if ( dot>0 && dot>pdot ) {
+ if ( nlen>plen && (t=AdjacentSplinesMatch(sp->next,sp->prev,false))!=-1 ) {
+ isp = SplineBisect(sp->next,t);
+ psp->nextcp.x = psp->me.x + (isp->nextcp.x-isp->me.x);
+ psp->nextcp.y = psp->me.y + (isp->nextcp.y-isp->me.y);
+ psp->nonextcp = isp->nonextcp;
+ psp->next = isp->next;
+ isp->next->from = psp;
+ SplineFree(isp->prev);
+ SplineFree(sp->prev);
+ SplinePointFree(isp);
+ SplinePointFree(sp);
+ SplineRefigure(psp->next);
+ if ( ss->first==sp )
+ ss->first = psp;
+ if ( ss->last==sp )
+ ss->last = psp;
+ sp=psp;
+ } else if ( nlen<plen && (t=AdjacentSplinesMatch(sp->prev,sp->next,true))!=-1 ) {
+ isp = SplineBisect(sp->prev,t);
+ nsp->prevcp.x = nsp->me.x + (isp->prevcp.x-isp->me.x);
+ nsp->prevcp.y = nsp->me.y + (isp->prevcp.y-isp->me.y);
+ nsp->noprevcp = isp->noprevcp;
+ nsp->prev = isp->prev;
+ isp->prev->to = nsp;
+ SplineFree(isp->next);
+ SplineFree(sp->next);
+ SplinePointFree(isp);
+ SplinePointFree(sp);
+ SplineRefigure(nsp->prev);
+ if ( ss->first==sp )
+ ss->first = psp;
+ if ( ss->last==sp )
+ ss->last = psp;
+ sp=psp;
+ }
+ }
+ }
+ if ( sp->next==NULL )
+ break;
+ sp=sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+}
+
+/* If we have a contour with no width, say a line from A to B and then from B */
+/* to A, then it will be ambiguous, depending on how we hit the contour, as */
+/* to whether it is needed or not. Which will cause us to complain. Since */
+/* they contain no area, they achieve nothing, so we might as well say they */
+/* overlap themselves and remove them here */
+static SplineSet *SSRemoveReversals(SplineSet *base) {
+ SplineSet *head = base, *prev=NULL, *next;
+ SplinePoint *sp;
+ int changed;
+
+ while ( base!=NULL ) {
+ next = base->next;
+ changed = true;
+ while ( changed ) {
+ changed = false;
+ if ( base->first->next==NULL ||
+ (base->first->next->to==base->first &&
+ base->first->nextcp.x==base->first->prevcp.x &&
+ base->first->nextcp.y==base->first->prevcp.y)) {
+ /* remove single points */
+ if ( prev==NULL )
+ head = next;
+ else
+ prev->next = next;
+ base->next = NULL;
+ SplinePointListFree(base);
+ base = prev;
+ break;
+ }
+ for ( sp=base->first; ; ) {
+ if ( sp->next!=NULL && sp->prev!=NULL &&
+ sp->nextcp.x==sp->prevcp.x && sp->nextcp.y==sp->prevcp.y ) {
+ SplinePoint *nsp = sp->next->to, *psp = sp->prev->from, *isp;
+ if ( psp->me.x==nsp->me.x && psp->me.y==nsp->me.y &&
+ psp->nextcp.x==nsp->prevcp.x && psp->nextcp.y==nsp->prevcp.y ) {
+ /* We wish to remove sp, sp->next, sp->prev & one of nsp/psp */
+ RemoveNextSP(psp,sp,nsp,base);
+ changed = true;
+ break;
+ } else if ( sp->nonextcp /* which implies sp->noprevcp */ &&
+ psp->nonextcp && nsp->noprevcp &&
+ (isp = SameLine(psp,sp,nsp))!=NULL ) {
+ /* We have a line that backtracks, but doesn't cover */
+ /* the entire spline, so we intersect */
+ /* We want to remove sp, the shorter of sp->next, sp->prev */
+ /* and a bit of the other one. Also reomve one of nsp,psp */
+ if ( isp==psp ) {
+ RemoveNextSP(psp,sp,nsp,base);
+ psp->nextcp = psp->me;
+ psp->nonextcp = true;
+ } else {
+ RemovePrevSP(psp,sp,nsp,base);
+ }
+ changed = true;
+ break;
+ }
+ }
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==base->first )
+ break;
+ }
+ }
+ SSRemoveBacktracks(base);
+ prev = base;
+ base = next;
+ }
+return( head );
+}
+
+SplineSet *SplineSetRemoveOverlap(SplineChar *sc, SplineSet *base,enum overlap_type ot) {
+ Monotonic *ms;
+ Intersection *ilist;
+ SplineSet *ret;
+ SplineSet *order3 = NULL;
+ int is_o2 = false;
+ SplineSet *ss;
+
+ for ( ss=base; ss!=NULL; ss=ss->next )
+ if ( ss->first->next!=NULL ) {
+ is_o2 = ss->first->next->order2;
+ break;
+ }
+ if ( is_o2 ) {
+ order3 = SplineSetsPSApprox(base);
+ SplinePointListsFree(base);
+ base = order3;
+ }
+
+ if ( sc!=NULL )
+ glyphname = sc->name;
+
+ base = SSRemoveTiny(base);
+ SSRemoveStupidControlPoints(base);
+ SplineSetsRemoveAnnoyingExtrema(base,.3);
+ SSOverlapClusterCpAngles(base,.01);
+ base = SSRemoveReversals(base);
+ ms = SSsToMContours(base,ot);
+ ilist = FindIntersections(ms,ot);
+ Validate(ms,ilist);
+ if ( ot==over_findinter || ot==over_fisel ) {
+ FixupIntersectedSplines(ms);
+ ret = base;
+ } else {
+ FindNeeded(ms,ot);
+ FindUnitVectors(ilist);
+ if ( ot==over_remove || ot == over_rmselected )
+ TestForBadDirections(ilist);
+ ret = JoinAllNeeded(ilist);
+ ret = MergeOpenAndFreeClosed(ret,base,ot);
+ }
+ FreeMonotonics(ms);
+ FreeIntersections(ilist);
+ glyphname = NULL;
+ if ( order3!=NULL ) {
+ ss = SplineSetsTTFApprox(ret);
+ SplinePointListsFree(ret);
+ ret = ss;
+ }
+return( ret );
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/splinerefigure.c b/Build/source/libs/luafontforge/fontforge/fontforge/splinerefigure.c
new file mode 100644
index 00000000000..59472ad6409
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/splinerefigure.c
@@ -0,0 +1,101 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include <stdio.h>
+#include <math.h>
+#include "splinefont.h"
+#ifdef HAVE_IEEEFP_H
+# include <ieeefp.h> /* Solaris defines isnan in ieeefp rather than math.h */
+#endif
+
+/* The slight errors introduced by the optimizer turn out to have nasty */
+/* side effects. An error on the order of 7e-8 in splines[1].b caused */
+/* the rasterizer to have kaniptions */
+void SplineRefigure3(Spline *spline) {
+ SplinePoint *from = spline->from, *to = spline->to;
+ Spline1D *xsp = &spline->splines[0], *ysp = &spline->splines[1];
+
+#ifdef DEBUG
+ if ( RealNear(from->me.x,to->me.x) && RealNear(from->me.y,to->me.y))
+ IError("Zero length spline created");
+#endif
+ xsp->d = from->me.x; ysp->d = from->me.y;
+ if ( from->nonextcp ) from->nextcp = from->me;
+ else if ( from->nextcp.x==from->me.x && from->nextcp.y == from->me.y ) from->nonextcp = true;
+ if ( to->noprevcp ) to->prevcp = to->me;
+ else if ( to->prevcp.x==to->me.x && to->prevcp.y == to->me.y ) to->noprevcp = true;
+ if ( from->nonextcp && to->noprevcp ) {
+ spline->islinear = true;
+ xsp->c = to->me.x-from->me.x;
+ ysp->c = to->me.y-from->me.y;
+ xsp->a = xsp->b = 0;
+ ysp->a = ysp->b = 0;
+ } else {
+ /* from p. 393 (Operator Details, curveto) Postscript Lang. Ref. Man. (Red book) */
+ xsp->c = 3*(from->nextcp.x-from->me.x);
+ ysp->c = 3*(from->nextcp.y-from->me.y);
+ xsp->b = 3*(to->prevcp.x-from->nextcp.x)-xsp->c;
+ ysp->b = 3*(to->prevcp.y-from->nextcp.y)-ysp->c;
+ xsp->a = to->me.x-from->me.x-xsp->c-xsp->b;
+ ysp->a = to->me.y-from->me.y-ysp->c-ysp->b;
+ if ( RealNear(xsp->c,0)) xsp->c=0;
+ if ( RealNear(ysp->c,0)) ysp->c=0;
+ if ( RealNear(xsp->b,0)) xsp->b=0;
+ if ( RealNear(ysp->b,0)) ysp->b=0;
+ if ( RealNear(xsp->a,0)) xsp->a=0;
+ if ( RealNear(ysp->a,0)) ysp->a=0;
+ spline->islinear = false;
+ if ( ysp->a==0 && xsp->a==0 && ysp->b==0 && xsp->b==0 )
+ spline->islinear = true; /* This seems extremely unlikely... */
+ }
+ if ( isnan(ysp->a) || isnan(xsp->a) )
+ IError("NaN value in spline creation");
+ LinearApproxFree(spline->approx);
+ spline->approx = NULL;
+ spline->knowncurved = false;
+ spline->knownlinear = spline->islinear;
+ SplineIsLinear(spline);
+ spline->isquadratic = false;
+ if ( !spline->knownlinear && xsp->a==0 && ysp->a==0 )
+ spline->isquadratic = true; /* Only likely if we read in a TTF */
+ spline->order2 = false;
+
+#if 0
+ _SplineRefigure3(&s);
+# define RealNear(a,b) ((a)==(b))
+
+ if ( !RealNear(spline->splines[0].a,s.splines[0].a) ||
+ !RealNear(spline->splines[0].b,s.splines[0].b) ||
+ !RealNear(spline->splines[0].c,s.splines[0].c) ||
+ !RealNear(spline->splines[0].d,s.splines[0].d) ||
+ !RealNear(spline->splines[1].a,s.splines[1].a) ||
+ !RealNear(spline->splines[1].b,s.splines[1].b) ||
+ !RealNear(spline->splines[1].c,s.splines[1].c) ||
+ !RealNear(spline->splines[1].d,s.splines[1].d) )
+ fprintf( stderr, "error\n" );
+#endif
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/splinesave.c b/Build/source/libs/luafontforge/fontforge/fontforge/splinesave.c
new file mode 100644
index 00000000000..46cf2cd2604
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/splinesave.c
@@ -0,0 +1,3616 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include <stdio.h>
+#include <math.h>
+#include "splinefont.h"
+#include "psfont.h"
+#include <ustring.h>
+#include <string.h>
+#include <utype.h>
+#include <gwidget.h>
+
+/* Let's talk about references. */
+/* If we are doing Type1 output, then the obvious way of doing them is seac */
+/* but that's so limitting. It only works for exactly two characters both */
+/* of which are in Adobe's Standard Enc. Only translations allowed. Only */
+/* one reference may be translated and the width of the char must match */
+/* that of the non-translated reference */
+/* The first extension we can make is to allow a single character reference */
+/* by making the other character be a space */
+/* But if we want to do more than that we must use subrs. If we have two */
+/* refs in subrs then we can do translations by preceding the subr calls by */
+/* appropriate rmovetos. Actually the specs say that only one rmoveto should */
+/* precede a path, so that means we can't allow the subroutines to position */
+/* themselves, they must just assume that they are called with the current */
+/* position correct for the first point. But then we need to know where the */
+/* first point should be placed, so we allocate a BasePoint to hold that info*/
+/* and store it into the "keys" array (which the subrs don't use). Similarly */
+/* we need to know where the subr will leave us, so we actually allocate 2 */
+/* BasePoints, one containing the start point, one the end point */
+/* But that's still not good enough, hints are defined in such a way that */
+/* they are not relocateable. So our subrs can't include any hint definitions*/
+/* (or if they do then that subr can't be translated at all). So hints must */
+/* be set outside the subrs, and the subrs can't be for chars that need hint */
+/* substitution. Unless... The subr will never be relocated. */
+/* So we generate two types of reference subrs, one containing no hints, the*/
+/* other containing all the hints, stems and flexes. The first type may be */
+/* translated, the second cannot */
+/* Type2 doesn't allow any seacs */
+/* So everything must go in subrs. We have a slightly different problem here:*/
+/* hintmasks need to know exactly how many stem hints there are in the char */
+/* so we can't include any hintmask operators inside a subr (unless we */
+/* guarantee that all invocations of that subr are done with the same number */
+/* of hints in the character). This again means that no char with hint subs- */
+/* titutions may be put in a subr. UNLESS all the other references in a */
+/* refering character contain no hints */
+
+/* That's very complex. And it doesn't do a very good job. */
+/* Instead let's take all strings bounded by either moveto or hintmask operators */
+/* store these as potential subroutines. So a glyph becomes a sequence of */
+/* potential subroutine calls preceded by the glyph header (width, hint decl,*/
+/* counter declarations, etc.) and intersperced by hintmask/moveto operators */
+/* Each time we get a potential subr we hash it and see if we've used that */
+/* string before. If we have then we merge the two. Otherwise it's a new one.*/
+/* Then at the end we see what strings get used often enough to go into subrs */
+/* we create the subrs array from that. */
+/* Then each glyph. We insert the preamble. We check of the potential subroutine */
+/* became a real subroutine. If so we call it, else we insert the data inline*/
+/* Do the same for the next hintmask/moveto and potential subroutine... */
+
+/* Then, on top of that I tried generating some full glyph subroutines, and */
+/* to my surprise, it just made things worse. */
+
+typedef struct growbuf {
+ unsigned char *pt;
+ unsigned char *base;
+ unsigned char *end;
+} GrowBuf;
+
+#define HSH_SIZE 511
+/* In type2 charstrings we divide every character into bits where a bit is */
+/* bounded by a hintmask/moveto. Each of these is a potential subroutine and */
+/* is stored here */
+typedef struct glyphinfo {
+ struct potentialsubrs {
+ uint8 *data; /* the charstring of the subr */
+ int len; /* the length of the charstring */
+ int idx; /* initially index into psubrs array */
+ /* then index into subrs array or -1 if none */
+ int cnt; /* the usage count */
+ int fd; /* Which sub font is it in */
+ /* -1 => used in more than one */
+ int next;
+ int full_glyph_index; /* Into the glyphbits array */
+ /* for full references */
+ BasePoint *startstop; /* Again for full references */
+ } *psubrs;
+ int pcnt, pmax;
+ int hashed[HSH_SIZE];
+ struct glyphbits {
+ SplineChar *sc;
+ int fd; /* Which subfont is it in */
+ int bcnt;
+ struct bits {
+ uint8 *data;
+ int dlen;
+ int psub_index;
+ } *bits;
+ uint8 wasseac;
+ } *gb, *active;
+ SplineFont *sf;
+ int glyphcnt;
+ int subfontcnt;
+ int bcnt, bmax;
+ struct bits *bits; /* For current glyph */
+ const int *bygid;
+ int justbroken;
+ int instance_count;
+} GlyphInfo;
+
+struct mhlist {
+ uint8 mask[HntMax/8];
+ int subr;
+ struct mhlist *next;
+};
+
+struct hintdb {
+ uint8 mask[HntMax/8];
+ int cnt; /* number of hints */
+ struct mhlist *sublist;
+ struct pschars *subrs;
+ /*SplineChar *sc;*/
+ SplineChar **scs;
+ int instance_count;
+ unsigned int iscjk: 1; /* If cjk then don't do stem3 hints */
+ /* Will be done with counters instead */
+ /* actually, most of the time we can't use stem3s, only if those three*/
+ /* stems are always active and there are no other stems !(h/v)hasoverlap*/
+ unsigned int noconflicts: 1;
+ unsigned int startset: 1;
+ unsigned int skiphm: 1; /* Set when coming back to the start point of a contour. hintmask should be set the first time, not the second */
+ unsigned int donefirsthm: 1;
+ int cursub; /* Current subr number */
+ BasePoint current;
+ GlyphInfo *gi;
+};
+
+static void GIContentsFree(GlyphInfo *gi,SplineChar *dummynotdef) {
+ int i,j;
+
+ if ( gi->glyphcnt>0 && gi->gb[0].sc == dummynotdef ) {
+ SplinePointListsFree(dummynotdef->layers[ly_fore].splines);
+ StemInfosFree(dummynotdef->hstem);
+ StemInfosFree(dummynotdef->vstem);
+ dummynotdef->layers[ly_fore].splines = NULL;
+ dummynotdef->vstem = dummynotdef->hstem = NULL;
+ }
+
+ for ( i=0; i<gi->pcnt; ++i ) {
+ free(gi->psubrs[i].data);
+ free(gi->psubrs[i].startstop);
+ gi->psubrs[i].data = NULL;
+ gi->psubrs[i].startstop = NULL;
+ }
+ for ( i=0; i<gi->glyphcnt; ++i ) {
+ for ( j=0; j<gi->gb[i].bcnt; ++j )
+ free(gi->gb[i].bits[j].data);
+ free(gi->gb[i].bits);
+ gi->gb[i].bits = NULL;
+ gi->gb[i].bcnt = 0;
+ }
+
+ gi->pcnt = 0;
+ gi->bcnt = 0;
+ gi->justbroken = 0;
+}
+
+static void GIFree(GlyphInfo *gi,SplineChar *dummynotdef) {
+
+ GIContentsFree(gi,dummynotdef);
+
+ free(gi->gb);
+ free(gi->psubrs);
+ free(gi->bits);
+}
+
+static void GrowBuffer(GrowBuf *gb) {
+ if ( gb->base==NULL ) {
+ gb->base = gb->pt = galloc(200);
+ gb->end = gb->base + 200;
+ } else {
+ int len = (gb->end-gb->base) + 400;
+ int off = gb->pt-gb->base;
+ gb->base = grealloc(gb->base,len);
+ gb->end = gb->base + len;
+ gb->pt = gb->base+off;
+ }
+}
+
+static void StartNextSubroutine(GrowBuf *gb,struct hintdb *hdb) {
+ GlyphInfo *gi;
+
+ if ( hdb==NULL )
+return;
+ gi = hdb->gi;
+ if ( gi==NULL )
+return;
+ /* Store everything in the grow buf into the data/dlen of the next bit */
+ if ( gi->bcnt==-1 ) gi->bcnt = 0;
+ if ( gi->bcnt>=gi->bmax )
+ gi->bits = grealloc(gi->bits,(gi->bmax+=20)*sizeof(struct bits));
+ gi->bits[gi->bcnt].dlen = gb->pt-gb->base;
+ gi->bits[gi->bcnt].data = galloc(gi->bits[gi->bcnt].dlen);
+ gi->bits[gi->bcnt].psub_index = -1;
+ memcpy(gi->bits[gi->bcnt].data,gb->base,gi->bits[gi->bcnt].dlen);
+ gb->pt = gb->base;
+ gi->justbroken = false;
+}
+
+static int hashfunc(uint8 *data, int len) {
+ uint8 *end = data+len;
+ unsigned int hash = 0, r;
+
+ while ( data<end ) {
+ r = (hash>>30)&3;
+ hash <<= 2;
+ hash = (hash|r)&0xffffffff;
+ hash ^= *data++;
+ }
+return( hash%HSH_SIZE );
+}
+
+static void BreakSubroutine(GrowBuf *gb,struct hintdb *hdb) {
+ GlyphInfo *gi;
+ struct potentialsubrs *ps;
+ int hash;
+ int pi;
+
+ if ( hdb==NULL )
+return;
+ gi = hdb->gi;
+ if ( gi==NULL )
+return;
+ /* The stuff before the first moveto in a glyph (the header that sets */
+ /* the width, sets up the hints, counters, etc.) can't go into a subr */
+ if ( gi->bcnt==-1 ) {
+ gi->bcnt=0;
+ gi->justbroken = true;
+return;
+ } else if ( gi->justbroken )
+return;
+ /* Otherwise stuff everything in the growbuffer into a subr */
+ hash = hashfunc(gb->base,gb->pt-gb->base);
+ ps = NULL;
+ for ( pi=gi->hashed[hash]; pi!=-1; pi=gi->psubrs[pi].next ) {
+ ps = &gi->psubrs[pi];
+ if ( ps->len==gb->pt-gb->base && memcmp(ps->data,gb->base,gb->pt-gb->base)==0 )
+ break;
+ }
+ if ( pi==-1 ) {
+ if ( gi->pcnt>=gi->pmax )
+ gi->psubrs = grealloc(gi->psubrs,(gi->pmax+=gi->glyphcnt)*sizeof(struct potentialsubrs));
+ ps = &gi->psubrs[gi->pcnt];
+ memset(ps,0,sizeof(*ps)); /* set cnt to 0 */
+ ps->idx = gi->pcnt++;
+ ps->len = gb->pt-gb->base;
+ ps->data = galloc(ps->len);
+ memcpy(ps->data,gb->base,ps->len);
+ ps->next = gi->hashed[hash];
+ gi->hashed[hash] = ps->idx;
+ ps->fd = gi->active->fd;
+ ps->full_glyph_index = -1;
+ }
+ if ( ps->fd!=gi->active->fd )
+ ps->fd = -1; /* used in multiple cid sub-fonts */
+ gi->bits[gi->bcnt].psub_index = ps->idx;
+ ++ps->cnt;
+ gb->pt = gb->base;
+ ++gi->bcnt;
+ gi->justbroken = true;
+}
+
+static void MoveSubrsToChar(GlyphInfo *gi) {
+ struct glyphbits *active;
+
+ if ( gi==NULL )
+return;
+ active = gi->active;
+ active->bcnt = gi->bcnt;
+ active->bits = galloc(active->bcnt*sizeof(struct bits));
+ memcpy(active->bits,gi->bits,active->bcnt*sizeof(struct bits));
+ gi->bcnt = 0;
+}
+
+static int NumberHints(SplineChar *scs[MmMax], int instance_count) {
+ int i,j, cnt=-1;
+ StemInfo *s;
+
+ for ( j=0; j<instance_count; ++j ) {
+ for ( s=scs[j]->hstem, i=0; s!=NULL; s=s->next ) {
+ if ( i<HntMax )
+ s->hintnumber = i++;
+ else
+ s->hintnumber = -1;
+ }
+ for ( s=scs[j]->vstem; s!=NULL; s=s->next ) {
+ if ( i<HntMax )
+ s->hintnumber = i++;
+ else
+ s->hintnumber = -1;
+ }
+ if ( cnt==-1 )
+ cnt = i;
+ else if ( cnt!=i )
+ IError("MM font with different hint counts");
+ }
+return( cnt );
+}
+
+void RefCharsFreeRef(RefChar *ref) {
+ RefChar *rnext;
+
+ while ( ref!=NULL ) {
+ rnext = ref->next;
+ /* don't free the splines */
+#ifdef FONTFORGE_CONFIG_TYPE3
+ free(ref->layers);
+#endif
+ chunkfree(ref,sizeof(RefChar));
+ ref = rnext;
+ }
+}
+
+static void MarkTranslationRefs(SplineFont *sf) {
+ int i;
+ SplineChar *sc;
+ RefChar *r;
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( (sc = sf->glyphs[i])!=NULL ) {
+ for ( r = sc->layers[ly_fore].refs; r!=NULL; r=r->next )
+ r->justtranslated = (r->transform[0]==1 && r->transform[3]==1 &&
+ r->transform[1]==0 && r->transform[2]==0);
+ }
+}
+
+/* ************************************************************************** */
+/* ********************** Type1 PostScript CharStrings ********************** */
+/* ************************************************************************** */
+
+static real myround( real pos, int round ) {
+ if ( round )
+return( rint( pos ));
+ else
+return( rint( pos*100. )/100. );
+}
+
+static void AddNumber(GrowBuf *gb, real pos, int round) {
+ int dodiv = 0;
+ int val;
+ unsigned char *str;
+
+ if ( gb->pt+8>=gb->end )
+ GrowBuffer(gb);
+
+ pos = rint(100*pos)/100;
+
+ if ( !round && pos!=floor(pos)) {
+ pos *= 100;
+ dodiv = true;
+ }
+ str = gb->pt;
+ val = rint(pos);
+ if ( pos>=-107 && pos<=107 )
+ *str++ = val+139;
+ else if ( pos>=108 && pos<=1131 ) {
+ val -= 108;
+ *str++ = (val>>8)+247;
+ *str++ = val&0xff;
+ } else if ( pos>=-1131 && pos<=-108 ) {
+ val = -val;
+ val -= 108;
+ *str++ = (val>>8)+251;
+ *str++ = val&0xff;
+ } else {
+ *str++ = '\377';
+ *str++ = (val>>24)&0xff;
+ *str++ = (val>>16)&0xff;
+ *str++ = (val>>8)&0xff;
+ *str++ = val&0xff;
+ }
+ if ( dodiv ) {
+ *str++ = 100+139; /* 100 */
+ *str++ = 12; /* div (byte1) */
+ *str++ = 12; /* div (byte2) */
+ }
+ gb->pt = str;
+}
+
+/* When doing a multiple master font we have multiple instances of the same data */
+/* which must all be added, and then a call made to the appropriate blend routine */
+/* This is complicated because all the data may not fit on the stack so we */
+/* may need to make multiple calls */
+static void AddData(GrowBuf *gb, real data[MmMax][6], int instances, int num_coords,
+ int round) {
+ int allsame = true, alls[6];
+ int i,j, chunk,min,max,subr;
+
+ for ( j=0; j<num_coords; ++j ) {
+ alls[j] = true;
+ for ( i=1; i<instances; ++i ) {
+ if ( data[i][j]!=data[0][j] ) {
+ alls[j] = false;
+ allsame = false;
+ break;
+ }
+ }
+ }
+
+ if ( allsame ) { /* No need for blending */
+ /* Probably a normal font, but possible in an mm */
+ for ( j=0; j<num_coords; ++j )
+ AddNumber(gb,data[0][j],round);
+return;
+ }
+
+ chunk = 22/instances;
+ if ( chunk == 5 ) chunk = 4; /* No subroutine for 5 items */
+ min = 0;
+ while ( min<num_coords ) {
+ while ( min<num_coords && alls[min] ) {
+ AddNumber(gb,data[0][min],round);
+ ++min;
+ }
+ max = min+chunk;
+ if ( max>num_coords ) max = num_coords;
+ while ( max-1>min && alls[max-1] )
+ --max;
+ if ( max-min==5 ) max=min+4;
+ if ( min<max ) {
+ for ( j=min; j<max; ++j )
+ AddNumber(gb,data[0][j],round);
+ for ( j=min; j<max; ++j )
+ for ( i=1; i<instances; ++i )
+ AddNumber(gb,data[i][j]-data[0][j],round);
+ subr = (j-min) + 4;
+ if ( j-min==6 ) subr = 9;
+ AddNumber(gb,subr,round);
+ if ( gb->pt+1>=gb->end )
+ GrowBuffer(gb);
+ *gb->pt++ = 10; /* callsubr */
+ min = j;
+ }
+ }
+}
+
+int CvtPsStem3(GrowBuf *gb, SplineChar *scs[MmMax], int instance_count,
+ int ishstem, int round) {
+ StemInfo *h1, *h2, *h3;
+ StemInfo _h1, _h2, _h3;
+ real data[MmMax][6];
+ int i;
+ real off;
+
+ for ( i=0; i<instance_count; ++i ) {
+ if ( (ishstem && scs[i]->hconflicts) || (!ishstem && scs[i]->vconflicts))
+return( false );
+ h1 = ishstem ? scs[i]->hstem : scs[i]->vstem;
+ if ( h1==NULL || (h2 = h1->next)==NULL || (h3=h2->next)==NULL )
+return( false );
+ if ( h3->next!=NULL )
+return( false );
+ off = ishstem ? 0 : scs[i]->lsidebearing;
+ if ( h1->width<0 ) {
+ _h1 = *h1;
+ _h1.start += _h1.width;
+ _h1.width = -_h1.width;
+ h1 = &_h1;
+ }
+ if ( h2->width<0 ) {
+ _h2 = *h2;
+ _h2.start += _h2.width;
+ _h2.width = -_h2.width;
+ h2 = &_h2;
+ }
+ if ( h3->width<0 ) {
+ _h3 = *h3;
+ _h3.start += _h3.width;
+ _h3.width = -_h3.width;
+ h3 = &_h3;
+ }
+
+ if ( h1->start>h2->start ) {
+ StemInfo *ht = h1; h1 = h2; h2 = ht;
+ }
+ if ( h1->start>h3->start ) {
+ StemInfo *ht = h1; h1 = h3; h3 = ht;
+ }
+ if ( h2->start>h3->start ) {
+ StemInfo *ht = h2; h2 = h3; h3 = ht;
+ }
+ if ( h1->width != h3->width )
+return( false );
+ if ( (h2->start+h2->width/2) - (h1->start+h1->width/2) !=
+ (h3->start+h3->width/2) - (h2->start+h2->width/2) )
+return( false );
+ data[i][0] = h1->start-off;
+ data[i][1] = h1->width;
+ data[i][2] = h2->start-off;
+ data[i][3] = h2->width;
+ data[i][4] = h3->start-off;
+ data[i][5] = h3->width;
+ }
+ if ( gb==NULL )
+return( true );
+ AddData(gb,data,instance_count,6,round);
+ if ( gb->pt+3>=gb->end )
+ GrowBuffer(gb);
+ *(gb->pt)++ = 12;
+ *(gb->pt)++ = ishstem?2:1; /* h/v stem3 */
+return( true );
+}
+
+static void CvtPsHints(GrowBuf *gb, SplineChar *scs[MmMax], int instance_count,
+ int ishstem, int round, int iscjk, real *offsets ) {
+ StemInfo *hs[MmMax];
+ real data[MmMax][6];
+ int i;
+ real off;
+
+ for ( i=0; i<instance_count; ++i )
+ hs[i] = ishstem ? scs[i]->hstem : scs[i]->vstem;
+
+ if ( hs[0]!=NULL && hs[0]->next!=NULL && hs[0]->next->next!=NULL &&
+ hs[0]->next->next->next==NULL )
+ if ( !iscjk && CvtPsStem3(gb, scs, instance_count, ishstem, round))
+return;
+
+ while ( hs[0]!=NULL ) {
+ for ( i=0; i<instance_count; ++i ) {
+ off = offsets!=NULL ? offsets[i] :
+ ishstem ? 0 : scs[i]->lsidebearing;
+ if ( hs[i]->ghost ) {
+ data[i][0] = hs[i]->start-off+hs[i]->width;
+ data[i][1] = -hs[i]->width;
+ } else {
+ data[i][0] = hs[i]->start-off;
+ data[i][1] = hs[i]->width;
+ }
+ }
+ AddData(gb,data,instance_count,2,round);
+ if ( gb->pt+1>=gb->end )
+ GrowBuffer(gb);
+ *(gb->pt)++ = ishstem?1:3; /* h/v stem */
+ for ( i=0; i<instance_count; ++i )
+ hs[i] = hs[i]->next;
+ }
+}
+
+static void CvtPsMasked(GrowBuf *gb,SplineChar *scs[MmMax], int instance_count,
+ int ishstem, int round, uint8 mask[12] ) {
+ StemInfo *hs[MmMax];
+ real data[MmMax][6], off;
+ int i;
+
+ for ( i=0; i<instance_count; ++i )
+ hs[i] = ishstem ? scs[i]->hstem : scs[i]->vstem;
+
+ while ( hs[0]!=NULL ) {
+ if ( hs[0]->hintnumber!=-1 &&
+ (mask[hs[0]->hintnumber>>3]&(0x80>>(hs[0]->hintnumber&7))) ) {
+ for ( i=0; i<instance_count; ++i ) {
+ off = ishstem ? 0 : scs[i]->lsidebearing;
+ if ( hs[i]->ghost ) {
+ data[i][0] = hs[i]->start-off+hs[i]->width;
+ data[i][1] = -hs[i]->width;
+ } else {
+ data[i][0] = hs[i]->start-off;
+ data[i][1] = hs[i]->width;
+ }
+ }
+ AddData(gb,data,instance_count,2,round);
+ if ( gb->pt+1>=gb->end )
+ GrowBuffer(gb);
+ *(gb->pt)++ = ishstem?1:3; /* h/v stem */
+ }
+ for ( i=0; i<instance_count; ++i )
+ hs[i] = hs[i]->next;
+ }
+}
+
+static int FigureCounters(StemInfo *stems,real *hints,int base,real offset,
+ int countermask_cnt, HintMask *counters) {
+ StemInfo *h;
+ int pos = base+1, subbase, cnt=0;
+ real last = offset;
+ int i;
+
+ for ( i=0; i<countermask_cnt; ++i ) {
+ subbase = pos;
+ for ( h=stems; h!=NULL ; h=h->next ) {
+ if ( h->hintnumber!=-1 && (counters[i][h->hintnumber>>3]&(0x80>>(h->hintnumber&7))) ) {
+ hints[pos++] = h->start-last;
+ hints[pos++] = h->width;
+ last = h->start+h->width;
+ }
+ }
+ if ( pos!=subbase ) {
+ hints[pos-2] += hints[pos-1];
+ hints[pos-1] = -hints[pos-1]; /* Mark end of group */
+ last = offset; /* Each new group starts at 0 or lbearing */
+ ++cnt;
+ }
+ }
+ hints[base] = cnt;
+return( pos );
+}
+
+static void CounterHints1(GrowBuf *gb, SplineChar *sc, int round) {
+ real hints[HntMax*2+2]; /* At most 96 hints, no hint used more than once */
+ int pos, i, j;
+
+ if ( sc->countermask_cnt==0 )
+return;
+
+ pos = FigureCounters(sc->hstem,hints,0,0,sc->countermask_cnt,
+ sc->countermasks);
+ /* Adobe's docs (T1_Supp.pdf, section 2.4) say these should be offset from*/
+ /* the left side bearing. The example (T1_Supp.pdf, 2.6) shows them offset*/
+ /* from 0. I've no idea which is correct, so I'll follow the words, think-*/
+ /* that the lbearing might have been set to 0 even though it shouldn't */
+ /* have been. */
+ pos = FigureCounters(sc->vstem,hints,pos,sc->lsidebearing,sc->countermask_cnt,
+ sc->countermasks);
+ if ( pos==2 ) /* => no counters, one byte to say 0 h counters, one byte for 0 v counters */
+return;
+ for ( i=pos; i>22; i-=22 ) {
+ for ( j=i-22; j<i; ++j )
+ AddNumber(gb,hints[j],round);
+ AddNumber(gb,22,round);
+ AddNumber(gb,12,round);
+ if ( gb->pt+2>=gb->end )
+ GrowBuffer(gb);
+ *(gb->pt)++ = 12;
+ *(gb->pt)++ = 16; /* CallOtherSubr */
+ }
+ for ( j=0; j<i; ++j )
+ AddNumber(gb,hints[j],round);
+ AddNumber(gb,i,round);
+ AddNumber(gb,13,round);
+ if ( gb->pt+2>=gb->end )
+ GrowBuffer(gb);
+ *(gb->pt)++ = 12;
+ *(gb->pt)++ = 16; /* CallOtherSubr */
+}
+
+static void SubrsCheck(struct pschars *subrs) {
+ /* <subr number presumed to be on stack> 1 3 callother pop callsubr */
+
+ if ( subrs->next>=subrs->cnt ) {
+ subrs->cnt += 100;
+ subrs->values = grealloc(subrs->values,subrs->cnt*sizeof(uint8 *));
+ subrs->lens = grealloc(subrs->lens,subrs->cnt*sizeof(int));
+ if ( subrs->keys!=NULL ) {
+ int i;
+ subrs->keys = grealloc(subrs->keys,subrs->cnt*sizeof(char *));
+ for ( i=subrs->cnt-100; i<subrs->cnt; ++i )
+ subrs->keys[i] = NULL;
+ }
+ }
+}
+
+/* Does the hintmask we need already exist in a subroutine? if so return that */
+/* subr. Else build a new subr with the hints we need. Note we can only use */
+/* *stem3 commands if there are no conflicts in that coordinate, it isn't cjk*/
+/* and all the other conditions are met */
+static int FindOrBuildHintSubr(struct hintdb *hdb, uint8 mask[12], int round) {
+ struct mhlist *mh;
+ GrowBuf gb;
+
+ for ( mh=hdb->sublist; mh!=NULL; mh=mh->next ) {
+ if ( memcmp(mask,mh->mask,sizeof(mask))==0 )
+return( mh->subr );
+#if 0
+ /* If we find a subr for which we have all the bits set (with extras */
+ /* since we didn't match) then it is safe to replace the old subr */
+ /* with ours. This will save use one subr entry, and maybe a call */
+
+ /* Hmm. Adobe doesn't do this in their code. Doubtless they know more */
+ /* about what hints imply about counters than I do */
+ for ( i=0; i<12; ++i )
+ if ( (mh->mask[i]&mask[i])!=mh->mask[i] )
+ break;
+ if ( i==12 )
+ break;
+#endif
+ }
+ SubrsCheck(hdb->subrs);
+
+ memset(&gb,0,sizeof(gb));
+ if ( !hdb->scs[0]->hconflicts )
+ CvtPsHints(&gb,hdb->scs,hdb->instance_count,true,round,hdb->iscjk,NULL);
+ else
+ CvtPsMasked(&gb,hdb->scs,hdb->instance_count,true,round,mask);
+ if ( !hdb->scs[0]->vconflicts )
+ CvtPsHints(&gb,hdb->scs,hdb->instance_count,false,round,hdb->iscjk,NULL);
+ else
+ CvtPsMasked(&gb,hdb->scs,hdb->instance_count,false,round,mask);
+ if ( gb.pt+1 >= gb.end )
+ GrowBuffer(&gb);
+ *gb.pt++ = 11; /* return */
+
+ /* Replace an old subroutine */
+ if ( mh!=NULL ) {
+ free( hdb->subrs->values[mh->subr]);
+ hdb->subrs->values[mh->subr] = (uint8 *) copyn((char *) gb.base,gb.pt-gb.base);
+ hdb->subrs->lens[mh->subr] = gb.pt-gb.base;
+ memcpy(mh->mask,mask,sizeof(mh->mask));
+ } else {
+ hdb->subrs->values[hdb->subrs->next] = (uint8 *) copyn((char *) gb.base,gb.pt-gb.base);
+ hdb->subrs->lens[hdb->subrs->next] = gb.pt-gb.base;
+
+ mh = gcalloc(1,sizeof(struct mhlist));
+ memcpy(mh->mask,mask,sizeof(mh->mask));
+ mh->subr = hdb->subrs->next++;
+ mh->next = hdb->sublist;
+ hdb->sublist = mh;
+ }
+ free(gb.base);
+
+return( mh->subr );
+}
+
+static void CallTransformedHintSubr(GrowBuf *gb,struct hintdb *hdb,
+ SplineChar *scs[MmMax], RefChar *refs[MmMax], BasePoint trans[MmMax],
+ int instance_count, int round) {
+ HintMask hm;
+ int s;
+
+ if ( HintMaskFromTransformedRef(refs[0],&trans[0],scs[0],&hm)==NULL )
+return;
+ s = FindOrBuildHintSubr(hdb, hm, round);
+ AddNumber(gb,s,round);
+ AddNumber(gb,4,round); /* subr 4 is (my) magic subr that does the hint subs call */
+ if ( gb->pt+1 >= gb->end )
+ GrowBuffer(gb);
+ *gb->pt++ = 10; /* callsubr */
+}
+
+static void HintSetup(GrowBuf *gb,struct hintdb *hdb, SplinePoint *to,
+ int round, int break_subr ) {
+ int s;
+ int i;
+
+ if ( to->hintmask==NULL || hdb->noconflicts )
+return;
+ if ( hdb->scs[0]->hstem==NULL && hdb->scs[0]->vstem==NULL ) /* Hints are turned off. Hint mask still remains though */
+return;
+ for ( i=0; i<HntMax/8; ++i )
+ if ( to->hintmask[i]!=0 )
+ break;
+ if ( i==HntMax/8 ) /* Empty mask */
+return;
+
+ s = FindOrBuildHintSubr(hdb,*to->hintmask,round);
+ memcpy(hdb->mask,*to->hintmask,sizeof(HintMask));
+ if ( hdb->cursub == s ) { /* If we were able to redefine */
+return; /* the subroutine currently */
+ } /* active then we are done */
+
+ if ( break_subr )
+ BreakSubroutine(gb,hdb);
+
+ AddNumber(gb,s,round);
+ AddNumber(gb,4,round); /* subr 4 is (my) magic subr that does the hint subs call */
+ if ( gb->pt+1 >= gb->end )
+ GrowBuffer(gb);
+ *gb->pt++ = 10; /* callsubr */
+ hdb->cursub = s;
+ if ( break_subr )
+ StartNextSubroutine(gb,hdb);
+}
+
+static void _moveto(GrowBuf *gb,BasePoint *current,BasePoint *to,int instance_count,
+ int line, int round, struct hintdb *hdb) {
+ BasePoint temp[MmMax];
+ int i, samex, samey;
+ real data[MmMax][6];
+
+ if ( gb->pt+18 >= gb->end )
+ GrowBuffer(gb);
+
+#if 0
+ if ( current->x==to->x && current->y==to->y ) {
+ /* we're already here */ /* Yes, but sometimes a move is required anyway */
+ } else
+#endif
+ for ( i=0; i<instance_count; ++i ) {
+ temp[i].x = myround(to[i].x,round);
+ temp[i].y = myround(to[i].y,round);
+ }
+ to = temp;
+ samex = samey = true;
+ for ( i=0; i<instance_count; ++i ) {
+ if ( current[i].x!=to[i].x ) samex = false;
+ if ( current[i].y!=to[i].y ) samey = false;
+ }
+ if ( samex ) {
+ for ( i=0; i<instance_count; ++i )
+ data[i][0] = to[i].y-current[i].y;
+ AddData(gb,data,instance_count,1,round);
+ *(gb->pt)++ = line ? 7 : 4; /* v move/line to */
+ } else if ( samey ) {
+ for ( i=0; i<instance_count; ++i )
+ data[i][0] = to[i].x-current[i].x;
+ AddData(gb,data,instance_count,1,round);
+ *(gb->pt)++ = line ? 6 : 22; /* h move/line to */
+ } else {
+ for ( i=0; i<instance_count; ++i ) {
+ data[i][0] = to[i].x-current[i].x;
+ data[i][1] = to[i].y-current[i].y;
+ }
+ AddData(gb,data,instance_count,2,round);
+ *(gb->pt)++ = line ? 5 : 21; /* r move/line to */
+ }
+ for ( i=0; i<instance_count; ++i )
+ current[i] = to[i];
+ if ( !line )
+ StartNextSubroutine(gb,hdb);
+}
+
+static void moveto(GrowBuf *gb,BasePoint *current,Spline *splines[MmMax],
+ int instance_count, int line, int round, struct hintdb *hdb) {
+ BasePoint to[MmMax];
+ int i;
+
+ if ( !line) BreakSubroutine(gb,hdb);
+ if ( hdb!=NULL ) HintSetup(gb,hdb,splines[0]->to,round,line);
+ for ( i=0; i<instance_count; ++i )
+ to[i] = splines[i]->to->me;
+ _moveto(gb,current,to,instance_count,line,round,hdb);
+}
+
+static void splmoveto(GrowBuf *gb,BasePoint *current,SplineSet *spl[MmMax],
+ int instance_count, int line, int round, struct hintdb *hdb) {
+ BasePoint to[MmMax];
+ int i;
+
+ if ( !line) BreakSubroutine(gb,hdb);
+ if ( hdb!=NULL ) HintSetup(gb,hdb,spl[0]->first,round,line);
+ for ( i=0; i<instance_count; ++i )
+ to[i] = spl[i]->first->me;
+ _moveto(gb,current,to,instance_count,line,round,hdb);
+}
+
+static int NeverConflicts(RefChar *refs[MmMax], int instance_count) {
+ int i;
+ for ( i=0; i<instance_count; ++i )
+ if ( refs[i]->sc->hconflicts || refs[i]->sc->vconflicts )
+return( false );
+
+return( true );
+}
+
+static int AllStationary(RefChar *refs[MmMax], BasePoint trans[MmMax], int instance_count) {
+ int i;
+ for ( i=0; i<instance_count; ++i )
+ if ( !refs[i]->justtranslated ||
+ refs[i]->transform[4]+trans[i].x!=0 ||
+ refs[i]->transform[5]+trans[i].y!=0 )
+return( false );
+
+return( true );
+}
+
+static int AnyRefs(SplineChar *sc) {
+ int i;
+
+ for ( i=ly_fore; i<sc->layer_cnt; ++i )
+ if ( sc->layers[i].refs!=NULL )
+return( true );
+
+return( false );
+}
+
+static void refmoveto(GrowBuf *gb,BasePoint *current,BasePoint rpos[MmMax],
+ int instance_count, int line, int round, struct hintdb *hdb, RefChar *refs[MmMax]) {
+ BasePoint to[MmMax];
+ int i;
+
+ if ( !line) BreakSubroutine(gb,hdb);
+ for ( i=0; i<instance_count; ++i ) {
+ to[i] = rpos[i];
+ if ( refs!=NULL ) {
+ to[i].x += refs[i]->transform[4];
+ to[i].y += refs[i]->transform[5];
+ }
+ }
+ _moveto(gb,current,to,instance_count,line,round,hdb);
+}
+
+static void curveto(GrowBuf *gb,BasePoint *current,Spline *splines[MmMax],int instance_count,
+ int round, struct hintdb *hdb) {
+ BasePoint temp1[MmMax], temp2[MmMax], temp3[MmMax], *c0[MmMax], *c1[MmMax], *s1[MmMax];
+ real data[MmMax][6];
+ int i, op, opcnt;
+ int vh, hv;
+
+ if ( hdb!=NULL ) HintSetup(gb,hdb,splines[0]->to,round,true);
+
+ if ( gb->pt+50 >= gb->end )
+ GrowBuffer(gb);
+
+ vh = hv = true;
+ for ( i=0; i<instance_count; ++i ) {
+ c0[i] = &splines[i]->from->nextcp;
+ c1[i] = &splines[i]->to->prevcp;
+ s1[i] = &splines[i]->to->me;
+ temp1[i].x = myround(c0[i]->x,round);
+ temp1[i].y = myround(c0[i]->y,round);
+ c0[i] = &temp1[i];
+ temp2[i].x = myround(c1[i]->x,round);
+ temp2[i].y = myround(c1[i]->y,round);
+ c1[i] = &temp2[i];
+ temp3[i].x = myround(s1[i]->x,round);
+ temp3[i].y = myround(s1[i]->y,round);
+ s1[i] = &temp3[i];
+ if ( current[i].x != c0[i]->x || c1[i]->y!=s1[i]->y ) vh = false;
+ if ( current[i].y != c0[i]->y || c1[i]->x!=s1[i]->x ) hv = false;
+ }
+ if ( vh ) {
+ for ( i=0; i<instance_count; ++i ) {
+ data[i][0] = c0[i]->y-current[i].y;
+ data[i][1] = c1[i]->x-c0[i]->x;
+ data[i][2] = c1[i]->y-c0[i]->y;
+ data[i][3] = s1[i]->x-c1[i]->x;
+ }
+ op = 30; /* vhcurveto */
+ opcnt = 4;
+ } else if ( hv ) {
+ for ( i=0; i<instance_count; ++i ) {
+ data[i][0] = c0[i]->x-current[i].x;
+ data[i][1] = c1[i]->x-c0[i]->x;
+ data[i][2] = c1[i]->y-c0[i]->y;
+ data[i][3] = s1[i]->y-c1[i]->y;
+ }
+ op = 31; /* hvcurveto */
+ opcnt = 4;
+ } else {
+ for ( i=0; i<instance_count; ++i ) {
+ data[i][0] = c0[i]->x-current[i].x;
+ data[i][1] = c0[i]->y-current[i].y;
+ data[i][2] = c1[i]->x-c0[i]->x;
+ data[i][3] = c1[i]->y-c0[i]->y;
+ data[i][4] = s1[i]->x-c1[i]->x;
+ data[i][5] = s1[i]->y-c1[i]->y;
+ }
+ op = 8; /* rrcurveto */
+ opcnt=6;
+ }
+ AddData(gb,data,instance_count,opcnt,false);
+ if ( gb->pt+1 >= gb->end )
+ GrowBuffer(gb);
+ *(gb->pt)++ = op;
+
+ for ( i=0; i<instance_count; ++i )
+ current[i] = *s1[i];
+}
+
+static int SplinesAreFlexible(Spline *splines[MmMax], int instance_count) {
+ int i, x=false, y=false;
+
+ for ( i=0; i<instance_count; ++i ) {
+ if ( !splines[i]->to->flexx && !splines[i]->to->flexy )
+return( false );
+ if (( x && splines[i]->to->flexy ) || ( y && splines[i]->to->flexx ))
+return( false );
+ x = splines[i]->to->flexx;
+ y = splines[i]->to->flexy;
+ }
+return( true );
+}
+
+static void flexto(GrowBuf *gb,BasePoint current[MmMax],Spline *pspline[MmMax],
+ int instance_count,int round, struct hintdb *hdb) {
+ BasePoint *c0, *c1, *mid, *end=NULL;
+ Spline *nspline;
+ BasePoint offsets[MmMax][8];
+ int i,j;
+ BasePoint temp1, temp2, temp3, temp;
+ real data[MmMax][6];
+
+ for ( j=0; j<instance_count; ++j ) {
+ c0 = &pspline[j]->from->nextcp;
+ c1 = &pspline[j]->to->prevcp;
+ mid = &pspline[j]->to->me;
+
+ temp1.x = myround(c0->x,round);
+ temp1.y = myround(c0->y,round);
+ c0 = &temp1;
+ temp2.x = myround(c1->x,round);
+ temp2.y = myround(c1->y,round);
+ c1 = &temp2;
+ temp.x = myround(mid->x,round);
+ temp.y = myround(mid->y,round);
+ mid = &temp;
+/* reference point is same level as current point */
+ if ( current[j].y==pspline[j]->to->next->to->me.y ) {
+ offsets[j][0].x = mid->x-current[j].x; offsets[j][0].y = 0;
+ offsets[j][1].x = c0->x-mid->x; offsets[j][1].y = c0->y-current[j].y;
+ } else {
+ offsets[j][0].x = 0; offsets[j][0].y = mid->y-current[j].y;
+ offsets[j][1].x = c0->x-current[j].x; offsets[j][1].y = c0->y-mid->y;
+ }
+ offsets[j][2].x = c1->x-c0->x; offsets[j][2].y = c1->y-c0->y;
+ offsets[j][3].x = mid->x-c1->x; offsets[j][3].y = mid->y-c1->y;
+ nspline = pspline[j]->to->next;
+ c0 = &nspline->from->nextcp;
+ c1 = &nspline->to->prevcp;
+ end = &nspline->to->me;
+
+ temp1.x = myround(c0->x,round);
+ temp1.y = myround(c0->y,round);
+ c0 = &temp1;
+ temp2.x = myround(c1->x,round);
+ temp2.y = myround(c1->y,round);
+ c1 = &temp2;
+ temp3.x = myround(end->x,round);
+ temp3.y = myround(end->y,round);
+ end = &temp3;
+
+ offsets[j][4].x = c0->x-mid->x; offsets[j][4].y = c0->y-mid->y;
+ offsets[j][5].x = c1->x-c0->x; offsets[j][5].y = c1->y-c0->y;
+ offsets[j][6].x = end->x-c1->x; offsets[j][6].y = end->y-c1->y;
+ offsets[j][7].x = end->x; offsets[j][7].y = end->y;
+ current[j] = *end;
+ }
+
+ if ( hdb!=NULL )
+ HintSetup(gb,hdb,pspline[0]->to->next->to,round,false);
+
+ if ( gb->pt+2 >= gb->end )
+ GrowBuffer(gb);
+
+ *(gb->pt)++ = 1+139; /* 1 */
+ *(gb->pt)++ = 10; /* callsubr */
+ for ( i=0; i<7; ++i ) {
+ if ( gb->pt+20 >= gb->end )
+ GrowBuffer(gb);
+ for ( j=0; j<instance_count; ++j ) {
+ data[j][0] = offsets[j][i].x;
+ data[j][1] = offsets[j][i].y;
+ }
+ AddData(gb,data,instance_count,2,round);
+ *(gb->pt)++ = 21; /* rmoveto */
+ *(gb->pt)++ = 2+139; /* 2 */
+ *(gb->pt)++ = 10; /* callsubr */
+ }
+ if ( gb->pt+20 >= gb->end )
+ GrowBuffer(gb);
+ *(gb->pt)++ = 50+139; /* 50, .50 pixels */
+ for ( j=0; j<instance_count; ++j ) {
+ data[j][0] = offsets[j][7].x;
+ data[j][1] = offsets[j][7].y;
+ }
+ AddData(gb,data,instance_count,2,round);
+ *(gb->pt)++ = 0+139; /* 0 */
+ *(gb->pt)++ = 10; /* callsubr */
+
+ *current = *end;
+}
+
+static void _CvtPsSplineSet(GrowBuf *gb, SplinePointList *spl[MmMax], int instance_count,
+ BasePoint current[MmMax],
+ int round, struct hintdb *hdb, int is_order2, int stroked ) {
+ Spline *spline[MmMax], *first;
+ SplinePointList temp[MmMax], *freeme=NULL;
+ int i;
+
+ if ( is_order2 ) {
+ freeme = spl[0] = SplineSetsPSApprox(spl[0]);
+ instance_count = 1;
+ }
+ while ( spl[0]!=NULL ) {
+ first = NULL;
+ for ( i=0; i<instance_count; ++i )
+ SplineSetReverse(spl[i]);
+ /* For some reason fontographer reads its spline in in the reverse */
+ /* order from that I use. I'm not sure how they do that. The result */
+ /* being that what I call clockwise they call counter. Oh well. */
+ /* If I reverse the splinesets after reading them in, and then again*/
+ /* when saving them out, all should be well */
+ if ( spl[0]->first->flexy || spl[0]->first->flexx ) {
+ /* can't handle a flex (mid) point as the first point. rotate the */
+ /* list by one, this is possible because only closed paths have */
+ /* points marked as flex, and because we can't have two flex mid- */
+ /* points in a row */
+ for ( i = 0; i<instance_count; ++i ) {
+ temp[i] = *spl[i];
+ temp[i].first = temp[i].last = spl[i]->first->next->to;
+ spl[i] = &temp[i];
+ }
+ if ( spl[0]->first->flexy || spl[0]->first->flexx ) {
+ /* well, well, well. We did have two flexes in a row */
+ for ( i = 0; i<instance_count; ++i ) {
+ spl[i]->first->flexx = spl[i]->first->flexy = false;
+ }
+ }
+ }
+ splmoveto(gb,current,spl,instance_count,false,round,hdb);
+ for ( i=0; i<instance_count; ++i )
+ spline[i] = spl[i]->first->next;
+ while ( spline[0]!=NULL && spline[0]!=first ) {
+ if ( first==NULL ) first = spline[0];
+ if ( SplinesAreFlexible(spline,instance_count) &&
+ (hdb->noconflicts || spline[0]->to->hintmask==NULL)) {
+ flexto(gb,current,spline,instance_count,round,hdb); /* does two adjacent splines */
+ for ( i=0; i<instance_count; ++i )
+ spline[i] = spline[i]->to->next;
+ } else if ( spline[0]->knownlinear && spline[0]->to==spl[0]->first ) {
+ /* We can finish this off with the closepath */
+ break;
+ } else if ( spline[0]->knownlinear )
+ moveto(gb,current,spline,instance_count,true,round,hdb);
+ else
+ curveto(gb,current,spline,instance_count,round,hdb);
+ for ( i=0; i<instance_count; ++i )
+ spline[i] = spline[i]->to->next;
+ }
+ if ( !stroked || spl[0]->first->prev!=NULL ) {
+ if ( gb->pt+1 >= gb->end )
+ GrowBuffer(gb);
+ *(gb->pt)++ = 9; /* closepath */
+ }
+ for ( i=0; i<instance_count; ++i ) {
+ SplineSetReverse(spl[i]);
+ /* Of course, I have to Reverse again to get back to my convention after*/
+ /* saving */
+ spl[i] = spl[i]->next;
+ }
+ }
+ SplinePointListsFree(freeme);
+}
+
+static RefChar *IsRefable(RefChar *ref, int isps, real transform[6], RefChar *sofar) {
+ real trans[6];
+ RefChar *sub;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ struct reflayer *rl;
+#endif
+
+ trans[0] = ref->transform[0]*transform[0] +
+ ref->transform[1]*transform[2];
+ trans[1] = ref->transform[0]*transform[1] +
+ ref->transform[1]*transform[3];
+ trans[2] = ref->transform[2]*transform[0] +
+ ref->transform[3]*transform[2];
+ trans[3] = ref->transform[2]*transform[1] +
+ ref->transform[3]*transform[3];
+ trans[4] = ref->transform[4]*transform[0] +
+ ref->transform[5]*transform[2] +
+ transform[4];
+ trans[5] = ref->transform[4]*transform[1] +
+ ref->transform[5]*transform[3] +
+ transform[5];
+
+ if (( isps==1 && ref->adobe_enc!=-1 ) ||
+ (/*isps!=1 &&*/ (ref->sc->layers[ly_fore].splines!=NULL || ref->sc->layers[ly_fore].refs==NULL))) {
+ /* If we're in postscript mode and the character we are refering to */
+ /* has an adobe encoding then we are done. */
+ /* In TrueType mode, if the character has no refs itself then we are */
+ /* done, but if it has splines as well as refs we are also done */
+ /* because it will have to be dumped out as splines */
+ /* Type2 PS (opentype) is the same as truetype here */
+ /* Now that I allow refs to be subrs in type1, it also uses the ttf test */
+ sub = RefCharCreate();
+#ifdef FONTFORGE_CONFIG_TYPE3
+ rl = sub->layers;
+ *sub = *ref;
+ sub->layers = rl;
+ *rl = ref->layers[0];
+#else
+ *sub = *ref;
+#endif
+ sub->next = sofar;
+ /*sub->layers[0].splines = NULL;*/
+ memcpy(sub->transform,trans,sizeof(trans));
+return( sub );
+ } else if ( /* isps &&*/ ( ref->sc->layers[ly_fore].refs==NULL || ref->sc->layers[ly_fore].splines!=NULL) ) {
+ RefCharsFreeRef(sofar);
+return( NULL );
+ }
+ for ( sub=ref->sc->layers[ly_fore].refs; sub!=NULL; sub=sub->next ) {
+ sofar = IsRefable(sub,isps,trans, sofar);
+ if ( sofar==NULL )
+return( NULL );
+ }
+return( sofar );
+}
+
+static int IsPSSeacable(SplineChar *sc) {
+ RefChar *ref;
+
+ if ( sc->layers[ly_fore].refs==NULL || sc->layers[ly_fore].splines!=NULL )
+return( false );
+
+ for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
+ if ( !ref->justtranslated )
+return( false );
+ }
+return( true );
+}
+
+static RefChar *RefFindAdobe(RefChar *r, RefChar *t) {
+ *t = *r;
+ while ( t->adobe_enc==-1 && t->sc->layers[ly_fore].refs!=NULL &&
+ t->sc->layers[ly_fore].refs->next==NULL &&
+ t->sc->layers[ly_fore].splines==NULL &&
+ t->sc->layers[ly_fore].refs->justtranslated ) {
+ t->transform[4] += t->sc->layers[ly_fore].refs->transform[4];
+ t->transform[5] += t->sc->layers[ly_fore].refs->transform[5];
+ t->adobe_enc = t->sc->layers[ly_fore].refs->adobe_enc;
+ t->orig_pos = t->sc->layers[ly_fore].refs->orig_pos;
+ t->sc = t->sc->layers[ly_fore].refs->sc;
+ }
+return( t );
+}
+
+static int IsSeacable(GrowBuf *gb, SplineChar *scs[MmMax],
+ int instance_count, int round) {
+ /* can be at most two chars in a seac (actually must be exactly 2, but */
+ /* I'll put in a space if there's only one (and if splace is blank) */
+ RefChar *r1, *r2, *rt, *refs;
+ RefChar space, t1, t2;
+ DBounds b;
+ int i, j, swap;
+ real data[MmMax][6];
+
+ for ( j=0 ; j<instance_count; ++j )
+ if ( !IsPSSeacable(scs[j]))
+return( false );
+
+ refs = scs[0]->layers[ly_fore].refs;
+ if ( refs==NULL )
+return( false );
+
+ r1 = refs;
+ if ((r2 = r1->next)==NULL ) {
+ RefChar *refs = r1->sc->layers[ly_fore].refs;
+ if ( refs!=NULL && refs->next!=NULL && refs->next->next==NULL &&
+ r1->sc->layers[ly_fore].splines==NULL &&
+ refs->adobe_enc!=-1 && refs->next->adobe_enc!=-1 ) {
+ r2 = refs->next;
+ r1 = refs;
+ }
+ }
+ if ( r2==NULL ) {
+ r2 = &space;
+ memset(r2,'\0',sizeof(space));
+ space.adobe_enc = ' ';
+ space.transform[0] = space.transform[3] = 1.0;
+ for ( i=0; i<scs[0]->parent->glyphcnt; ++i )
+ if ( scs[0]->parent->glyphs[i]!=NULL &&
+ strcmp(scs[0]->parent->glyphs[i]->name,"space")==0 )
+ break;
+ if ( i==scs[0]->parent->glyphcnt )
+ r2 = NULL; /* No space???? */
+ else {
+ space.sc = scs[0]->parent->glyphs[i];
+ if ( space.sc->layers[ly_fore].splines!=NULL || space.sc->layers[ly_fore].refs!=NULL )
+ r2 = NULL;
+ }
+ } else if ( r2->next!=NULL )
+ r2 = NULL;
+
+ /* check for something like "AcyrillicBreve" which has a ref to Acyril */
+ /* (which doesn't have an adobe enc) which in turn has a ref to A (which */
+ /* does) */
+ if ( r2!=NULL ) {
+ if ( r1->adobe_enc==-1 )
+ r1 = RefFindAdobe(r1,&t1);
+ if ( r2->adobe_enc==-1 )
+ r2 = RefFindAdobe(r2,&t2);
+ }
+
+/* CID fonts have no encodings. So we can't use seac to reference characters */
+/* in them. The other requirements are just those of seac */
+ if ( r2==NULL ||
+ r1->adobe_enc==-1 ||
+ r2->adobe_enc==-1 ||
+ ((r1->transform[4]!=0 || r1->transform[5]!=0 || r1->sc->width!=scs[0]->width ) &&
+ (r2->transform[4]!=0 || r2->transform[5]!=0 || r2->sc->width!=scs[0]->width)) )
+return( false );
+
+ swap = false;
+ if ( r1->transform[4]!=0 || r1->transform[5]!=0 ) {
+ rt = r1; r1 = r2; r2 = rt;
+ swap = !swap;
+ }
+
+ SplineCharFindBounds(r1->sc,&b);
+ r1->sc->lsidebearing = round?rint(b.minx):b.minx;
+ SplineCharFindBounds(r2->sc,&b);
+ r2->sc->lsidebearing = round?rint(b.minx):b.minx;
+
+ if ( (r1->sc->width!=scs[0]->width || r1->sc->lsidebearing!=scs[0]->lsidebearing) &&
+ r2->sc->width==scs[0]->width && r2->sc->lsidebearing==scs[0]->lsidebearing &&
+ r2->transform[4]==0 && r2->transform[5]==0 ) {
+ rt = r1; r1 = r2; r2 = rt;
+ swap = !swap;
+ }
+ if ( r1->sc->width!=scs[0]->width || r1->sc->lsidebearing!=scs[0]->lsidebearing ||
+ r1->transform[4]!=0 || r1->transform[5]!=0 )
+return( false );
+
+ for ( j=0; j<instance_count; ++j ) {
+ SplineChar *r2sc = scs[j]->parent->glyphs[r2->sc->orig_pos];
+ RefChar *r3, t3;
+
+ SplineCharFindBounds(r2sc,&b);
+ if ( scs[j]->layers[ly_fore].refs!=NULL && scs[j]->layers[ly_fore].refs->next==NULL )
+ r3 = r2; /* Space, not offset */
+ else if ( swap )
+ r3 = RefFindAdobe(scs[j]->layers[ly_fore].refs,&t3);
+ else
+ r3 = RefFindAdobe(scs[j]->layers[ly_fore].refs->next,&t3);
+
+ b.minx = myround(b.minx,round);
+ data[j][0] = b.minx;
+ data[j][1] = r3->transform[4] + b.minx-scs[j]->lsidebearing;
+ data[j][2] = r3->transform[5];
+ }
+ AddData(gb,data,instance_count,3,round);
+ AddNumber(gb,r1->adobe_enc,round);
+ AddNumber(gb,r2->adobe_enc,round);
+ if ( gb->pt+2>gb->end )
+ GrowBuffer(gb);
+ *(gb->pt)++ = 12;
+ *(gb->pt)++ = 6; /* seac 12,6 */
+
+return( true );
+}
+
+static int _SCNeedsSubsPts(SplineChar *sc) {
+ RefChar *ref;
+
+ if ( sc->hstem==NULL && sc->vstem==NULL )
+return( false );
+
+ if ( sc->layers[ly_fore].splines!=NULL )
+return( sc->layers[ly_fore].splines->first->hintmask==NULL );
+
+ for ( ref = sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next )
+ if ( ref->layers[0].splines!=NULL )
+return( ref->layers[0].splines->first->hintmask==NULL );
+
+return( false ); /* It's empty. that's easy. */
+}
+
+static int SCNeedsSubsPts(SplineChar *sc,enum fontformat format) {
+ if ( (format!=ff_mma && format!=ff_mmb) || sc->parent->mm==NULL ) {
+ if ( !sc->hconflicts && !sc->vconflicts )
+return( false ); /* No conflicts, no swap-over points needed */
+return( _SCNeedsSubsPts(sc));
+ } else {
+ MMSet *mm = sc->parent->mm;
+ int i;
+ for ( i=0; i<mm->instance_count; ++i ) if ( sc->orig_pos<mm->instances[i]->glyphcnt ) {
+ if ( _SCNeedsSubsPts(mm->instances[i]->glyphs[sc->orig_pos]) )
+return( true );
+ }
+return( false );
+ }
+}
+
+static void ExpandRef1(GrowBuf *gb, SplineChar *scs[MmMax], int instance_count,
+ struct hintdb *hdb, RefChar *r[MmMax], BasePoint trans[MmMax],
+ BasePoint current[MmMax],
+ struct pschars *subrs, int round, int iscjk) {
+ BasePoint *bpt;
+ BasePoint rtrans[MmMax], rpos[MmMax];
+ int i;
+
+ for ( i=0; i<instance_count; ++i ) {
+ rtrans[i].x = r[i]->transform[4]+trans[i].x;
+ rtrans[i].y = r[i]->transform[5]+trans[i].y;
+ if ( round ) {
+ rtrans[i].x = rint(rtrans[i].x);
+ rtrans[i].y = rint(rtrans[i].y);
+ }
+ }
+
+ BreakSubroutine(gb,hdb);
+ if ( r[0]->sc == scs[0] ) {
+ /* Hints for self */
+ if ( hdb->cnt>0 && !hdb->noconflicts && NeverConflicts(r,instance_count)) {
+ CvtPsHints(gb,scs,instance_count,true,round,iscjk,NULL);
+ CvtPsHints(gb,scs,instance_count,false,round,iscjk,NULL);
+ }
+ } else {
+ /* Hints for a real reference */
+ if ( !NeverConflicts(r,instance_count) || r[0]->sc->anyflexes || AnyRefs(r[0]->sc) )
+ /* Hints already done */;
+ else if ( hdb->noconflicts )
+ /* Hints already done */;
+ else if ( r[0]->sc->hstem!=NULL || r[0]->sc->vstem!=NULL )
+ CallTransformedHintSubr(gb,hdb,scs,r,trans,instance_count,round);
+ }
+
+ if ( hdb!=NULL && hdb->gi!=NULL )
+ bpt = hdb->gi->psubrs[r[0]->sc->ttf_glyph].startstop;
+ else
+ bpt = (BasePoint *) (subrs->keys[r[0]->sc->ttf_glyph]);
+ for ( i=0; i<instance_count; ++i ) {
+ rpos[i].x = bpt[2*i].x + rtrans[i].x;
+ rpos[i].y = bpt[2*i].y + rtrans[i].y;
+ }
+ refmoveto(gb,current,rpos, instance_count,false,round,hdb,NULL);
+ hdb->startset = true;
+
+ if ( hdb!=NULL && hdb->gi!=NULL ) {
+ GlyphInfo *gi = hdb->gi;
+ StartNextSubroutine(gb,hdb);
+ gi->bits[gi->bcnt].psub_index = r[0]->sc->ttf_glyph;
+ ++gi->bcnt;
+ gi->justbroken = true;
+ } else {
+ AddNumber(gb,r[0]->sc->ttf_glyph,round);
+ if ( gb->pt+1>=gb->end )
+ GrowBuffer(gb);
+ *gb->pt++ = 10;
+ }
+
+ for ( i=0; i<instance_count; ++i ) {
+ current[i].x = bpt[2*i+1].x + rtrans[i].x;
+ current[i].y = bpt[2*i+1].y + rtrans[i].y;
+ }
+}
+
+static void RSC2PS1(GrowBuf *gb, SplineChar *base[MmMax],SplineChar *rsc[MmMax],
+ struct hintdb *hdb, BasePoint *trans, struct pschars *subrs,
+ BasePoint current[MmMax], int flags, int iscjk,
+ int instance_count ) {
+ BasePoint subtrans[MmMax];
+ SplineChar *rscs[MmMax];
+ int round = (flags&ps_flag_round)? true : false;
+ RefChar *refs[MmMax];
+ SplineSet *spls[MmMax], *freeme[MmMax];
+ int i;
+ int wasntconflicted = hdb->noconflicts;
+
+ for ( i=0; i<instance_count; ++i ) {
+ spls[i] = rsc[i]->layers[ly_fore].splines;
+ if ( base[0]!=rsc[0] )
+ spls[i] = freeme[i] = SPLCopyTranslatedHintMasks(spls[i],base[i],rsc[i],&trans[i]);
+ }
+ _CvtPsSplineSet(gb,spls,instance_count,current,round,hdb,
+ base[0]->parent->order2,base[0]->parent->strokedfont);
+ if ( base[0]!=rsc[0] )
+ for ( i=0; i<instance_count; ++i )
+ SplinePointListsFree(freeme[i]);
+
+ for ( i=0; i<instance_count; ++i )
+ refs[i] = rsc[i]->layers[ly_fore].refs;
+ while ( refs[0]!=NULL ) {
+ for ( i=0; i<instance_count; ++i )
+ spls[i] = refs[i]->layers[0].splines;
+ if ( !refs[0]->justtranslated ) {
+ for ( i=0; i<instance_count; ++i )
+ spls[i] = freeme[i] = SPLCopyTransformedHintMasks(refs[i],base[i],&trans[i]);
+ if ( NeverConflicts(refs,instance_count) && !hdb->noconflicts &&
+ refs[0]->transform[1]==0 && refs[0]->transform[2]==0 )
+ CallTransformedHintSubr(gb,hdb,base,refs,trans,instance_count,round);
+ _CvtPsSplineSet(gb,spls,instance_count,current,round,hdb,
+ base[0]->parent->order2,base[0]->parent->strokedfont);
+ for ( i=0; i<instance_count; ++i )
+ SplinePointListsFree(freeme[i]);
+ } else if ( refs[0]->sc->ttf_glyph!=0x7fff &&
+ ((flags&ps_flag_nohints) ||
+ !refs[0]->sc->anyflexes ||
+ (refs[0]->transform[4]+trans[0].x==0 && refs[0]->transform[5]+trans[0].y==0)) &&
+ ((flags&ps_flag_nohints) ||
+ NeverConflicts(refs,instance_count) ||
+ AllStationary(refs,trans,instance_count)) ) {
+ ExpandRef1(gb,base,instance_count,hdb,refs,trans,
+ current,subrs,round,iscjk);
+ } else {
+ for ( i=0; i<instance_count; ++i ) {
+ subtrans[i].x = trans[i].x + refs[i]->transform[4];
+ subtrans[i].y = trans[i].y + refs[i]->transform[5];
+ rscs[i] = refs[i]->sc;
+ }
+ if ( !hdb->noconflicts && NeverConflicts(refs,instance_count)) {
+ CallTransformedHintSubr(gb,hdb,base,refs,trans,instance_count,round);
+ hdb->noconflicts = true;
+ }
+ RSC2PS1(gb,base,rscs,hdb,subtrans,subrs,current,flags,iscjk,
+ instance_count);
+ hdb->noconflicts = wasntconflicted;
+ }
+ for ( i=0; i<instance_count; ++i )
+ refs[i] = refs[i]->next;
+ }
+}
+
+static unsigned char *SplineChar2PS(SplineChar *sc,int *len,int round,int iscjk,
+ struct pschars *subrs,int flags,enum fontformat format,
+ GlyphInfo *gi) {
+ DBounds b;
+ GrowBuf gb;
+ BasePoint current[MmMax];
+ unsigned char *ret;
+ struct hintdb hintdb, *hdb=NULL;
+ StemInfo *oldh[MmMax], *oldv[MmMax];
+ int hc[MmMax], vc[MmMax];
+ BasePoint trans[MmMax];
+ int instance_count, i;
+ SplineChar *scs[MmMax];
+ real data[MmMax][6];
+ MMSet *mm = sc->parent->mm;
+ HintMask *hm[MmMax];
+ int fixuphm = false;
+
+ if ( !(flags&ps_flag_nohints) && SCNeedsSubsPts(sc,format))
+ SCFigureHintMasks(sc);
+
+ if ( (format==ff_mma || format==ff_mmb) && mm!=NULL ) {
+ instance_count = mm->instance_count;
+ if ( instance_count>16 )
+ instance_count = 16;
+ for ( i=0; i<instance_count; ++i )
+ scs[i] = mm->instances[i]->glyphs[sc->orig_pos];
+ } else {
+ instance_count = 1;
+ scs[0] = sc;
+ mm = NULL;
+ }
+
+ if ( flags&ps_flag_nohints ) {
+ for ( i=0; i<instance_count; ++i ) {
+ oldh[i] = scs[i]->hstem; oldv[i] = scs[i]->vstem;
+ hc[i] = scs[i]->hconflicts; vc[i] = scs[i]->vconflicts;
+ scs[i]->hstem = NULL; scs[i]->vstem = NULL;
+ scs[i]->hconflicts = false; scs[i]->vconflicts = false;
+ }
+ } else {
+ for ( i=0; i<instance_count; ++i )
+ if ( scs[i]->vconflicts || scs[i]->hconflicts )
+ break;
+ if ( scs[0]->layers[ly_fore].splines!=NULL && i==instance_count ) { /* No conflicts */
+ fixuphm = true;
+ for ( i=0; i<instance_count; ++i ) {
+ hm[i] = scs[i]->layers[ly_fore].splines->first->hintmask;
+ scs[i]->layers[ly_fore].splines->first->hintmask = NULL;
+ }
+ }
+ }
+
+ memset(&gb,'\0',sizeof(gb));
+ memset(current,'\0',sizeof(current));
+ for ( i=0; i<instance_count; ++i ) {
+ SplineCharFindBounds(scs[i],&b);
+ scs[i]->lsidebearing = current[i].x = round?rint(b.minx):b.minx;
+ data[i][0] = b.minx;
+ data[i][1] = scs[i]->width;
+ }
+ AddData(&gb,data,instance_count,2,round);
+ *gb.pt++ = 13; /* hsbw, lbearing & width */
+
+ memset(&hintdb,0,sizeof(hintdb));
+ hintdb.subrs = subrs; hintdb.iscjk = iscjk&~0x100; hintdb.scs = scs;
+ hintdb.instance_count = instance_count;
+ hintdb.cnt = NumberHints(scs,instance_count);
+ hintdb.noconflicts = true;
+ hintdb.gi = gi;
+ for ( i=0; i<instance_count; ++i )
+ if ( scs[i]->hconflicts || scs[i]->vconflicts )
+ hintdb.noconflicts = false;
+ hdb = &hintdb;
+ if ( gi!=NULL )
+ gi->bcnt = -1;
+
+ /* If this char is being placed in a subroutine, then we don't want to */
+ /* use seac because somebody is going to call that subroutine and */
+ /* add another reference to it later. CID keyed fonts also can't use */
+ /* seac (they have no encoding so it doesn't work), that's what iscjk&0x100 */
+ /* tests for */
+ if ( scs[0]->ttf_glyph==0x7fff && !(iscjk&0x100) && !(flags&ps_flag_noseac) &&
+ IsSeacable(&gb,scs,instance_count,round)) {
+ if ( gi )
+ gi->active->wasseac = true;
+ /* in MM fonts, all should share the same refs, so all should be */
+ /* seac-able if one is */
+ } else {
+ iscjk &= ~0x100;
+ if ( iscjk && instance_count==1 )
+ CounterHints1(&gb,sc,round); /* Must come immediately after hsbw */
+ if ( hintdb.noconflicts ) {
+ CvtPsHints(&gb,scs,instance_count,true,round,iscjk,NULL);
+ CvtPsHints(&gb,scs,instance_count,false,round,iscjk,NULL);
+ }
+ memset(&trans,0,sizeof(trans));
+ RSC2PS1(&gb,scs,scs,hdb,trans,subrs,current,flags,iscjk,
+ instance_count);
+ }
+ if ( gi->bcnt==-1 ) { /* If it's whitespace */
+ gi->bcnt = 0;
+ StartNextSubroutine(&gb,hdb);
+ }
+ BreakSubroutine(&gb,hdb);
+ MoveSubrsToChar(gi);
+ ret = NULL;
+
+ if ( hdb!=NULL ) {
+ struct mhlist *mh, *mhnext;
+ for ( mh=hdb->sublist; mh!=NULL; mh=mhnext ) {
+ mhnext = mh->next;
+ free(mh);
+ }
+ }
+ free(gb.base);
+ if ( flags&ps_flag_nohints ) {
+ for ( i=0; i<instance_count; ++i ) {
+ scs[i]->hstem = oldh[i]; scs[i]->vstem = oldv[i];
+ scs[i]->hconflicts = hc[i]; scs[i]->vconflicts = vc[i];
+ }
+ } else if ( fixuphm ) {
+ for ( i=0; i<instance_count; ++i )
+ scs[i]->layers[ly_fore].splines->first->hintmask = hm[i];
+ }
+return( ret );
+}
+
+#ifdef FONTFORGE_CONFIG_PS_REFS_GET_SUBRS
+static int AlwaysSeacable(SplineChar *sc,int flags) {
+ struct splinecharlist *d;
+ RefChar *r;
+
+ if ( sc->parent->cidmaster!=NULL ) /* Can't use seac in CID fonts, no encoding */
+return( false );
+ if ( flags&ps_flag_noseac )
+return( false );
+
+ for ( d=sc->dependents; d!=NULL; d = d->next ) {
+ if ( d->sc->layers[ly_fore].splines!=NULL ) /* I won't deal with things with both splines and refs. */
+ continue; /* skip it */
+ for ( r=d->sc->layers[ly_fore].refs; r!=NULL; r=r->next ) {
+ if ( !r->justtranslated )
+ break; /* Can't deal with it either way */
+ }
+ if ( r!=NULL ) /* Bad transform matrix */
+ continue; /* Can't handle either way, skip */
+
+ for ( r=d->sc->layers[ly_fore].refs; r!=NULL; r=r->next ) {
+ if ( r->adobe_enc==-1 )
+return( false ); /* not seacable, but could go in subr */
+ }
+ r = d->sc->layers[ly_fore].refs;
+ if ( r->next!=NULL && r->next->next!=NULL )
+return( false ); /* seac only takes 2 glyphs */
+ if ( r->next!=NULL &&
+ ((r->transform[4]!=0 || r->transform[5]!=0 || r->sc->width!=d->sc->width) &&
+ (r->next->transform[4]!=0 || r->next->transform[5]!=0 || r->next->sc->width!=d->sc->width)))
+return( false ); /* seac only allows one to be translated, and the untranslated one must have the right width */
+ if ( r->next==NULL &&
+ (r->transform[4]!=0 || r->transform[5]!=0 || r->sc->width!=d->sc->width))
+return( false );
+ }
+ /* Either always can be represented by seac, or sometimes by neither */
+return( true );
+}
+
+/* normally we can't put a character with hint conflicts into a subroutine */
+/* (because when we would have to invoke the hints within the subr and */
+/* hints are expressed as absolute positions, so if the char has been */
+/* translated we can't do the hints right). BUT if the character is not */
+/* translated, and if it has the right lbearing, then the hints in the */
+/* ref will match those in the character and we can use a subroutine for */
+/* both */
+/* If at least one ref fits our requirements then return true */
+/* The same reasoning applies to flex hints. There are absolute expressions */
+/* in them too. */
+static int SpecialCaseConflicts(SplineChar *sc) {
+ struct splinecharlist *d;
+ RefChar *r;
+ DBounds sb, db;
+
+ SplineCharFindBounds(sc,&sb);
+ for ( d=sc->dependents; d!=NULL; d = d->next ) {
+ SplineCharFindBounds(d->sc,&db);
+ if ( db.minx != sb.minx )
+ continue;
+ for ( r=d->sc->layers[ly_fore].refs; r!=NULL; r=r->next )
+ if ( r->sc == sc && r->justtranslated &&
+ r->transform[4]==0 && r->transform[5]==0 )
+return( true );
+ }
+return( false );
+}
+
+static BasePoint *FigureStartStop(SplineChar *sc, GlyphInfo *gi ) {
+ int m, didfirst;
+ SplineChar *msc;
+ SplineSet *spl;
+ RefChar *r;
+ BasePoint *startstop;
+
+ /* We need to know the location of the first point on the */
+ /* first path (need to rmoveto it, and the location of the */
+ /* last point on the last path (will need to move from it */
+ /* for the next component) */
+
+ startstop = gcalloc(2*gi->instance_count,sizeof(BasePoint));
+ for ( m=0; m<gi->instance_count; ++m ) {
+ if ( gi->instance_count==1 || sc->parent->mm==NULL )
+ msc = sc;
+ else
+ msc = sc->parent->mm->instances[m]->glyphs[sc->orig_pos];
+ didfirst = false;
+ spl = msc->layers[ly_fore].splines;
+ if ( spl!=NULL ) {
+ startstop[0] = spl->first->me;
+ didfirst = true;
+ while ( spl!=NULL ) {
+ /* Closepath does NOT set the current point */
+ /* Remember we reverse PostScript */
+ if ( spl->last==spl->first && spl->first->next!=NULL &&
+ spl->first->next->knownlinear )
+ startstop[1] = spl->first->next->to->me;
+ else
+ startstop[1] = spl->last->me;
+ spl = spl->next;
+ }
+ }
+ for ( r=msc->layers[ly_fore].refs; r!=NULL; r=r->next ) {
+ spl = r->layers[0].splines;
+ if ( spl!=NULL ) {
+ if ( !didfirst )
+ startstop[0] = spl->first->me;
+ didfirst = true;
+ }
+ while ( spl!=NULL ) {
+ /* Closepath does NOT set the current point */
+ /* Remember we reverse PostScript */
+ if ( spl->last==spl->first && spl->first->next!=NULL &&
+ spl->first->next->knownlinear )
+ startstop[1] = spl->first->next->to->me;
+ else
+ startstop[1] = spl->last->me;
+ spl = spl->next;
+ }
+ }
+ }
+return( startstop );
+}
+#endif /* FONTFORGE_CONFIG_PS_REFS_GET_SUBRS */
+
+/* Mark those glyphs which can live totally in subrs */
+static void SplineFont2FullSubrs1(int flags,GlyphInfo *gi) {
+ int i;
+ SplineChar *sc;
+#ifdef FONTFORGE_CONFIG_PS_REFS_GET_SUBRS
+ int anydone, cc;
+ struct potentialsubrs *ps;
+ SplineSet *spl;
+ RefChar *r;
+#endif /* FONTFORGE_CONFIG_PS_REFS_GET_SUBRS */
+
+ if ( !autohint_before_generate && !(flags&ps_flag_nohints))
+ SplineFontAutoHintRefs(gi->sf);
+ for ( i=0; i<gi->glyphcnt; ++i ) if ( (sc=gi->gb[i].sc)!=NULL )
+ sc->ttf_glyph = 0x7fff;
+
+#ifdef FONTFORGE_CONFIG_PS_REFS_GET_SUBRS
+ anydone = true;
+ while ( anydone ) {
+ anydone = false;
+ for ( i=0; i<gi->glyphcnt; ++i ) if ( (sc=gi->gb[i].sc)!=NULL ) {
+ if ( !SCWorthOutputting(sc) || sc->ttf_glyph!=0x7fff )
+ continue;
+ /* if the glyph is a single contour with no hintmasks then */
+ /* our single contour code will find it. If we do it here too */
+ /* we'll get a subr which points to another subr. Very dull and */
+ /* a waste of space */
+ cc = 0;
+ for ( spl=sc->layers[ly_fore].splines; spl!=NULL; spl=spl->next )
+ ++cc;
+ for ( r= sc->layers[ly_fore].refs; r!=NULL && cc<2 ; r=r->next ) {
+ for ( spl=r->layers[0].splines; spl!=NULL; spl=spl->next )
+ ++cc;
+ }
+ if ( cc<2 )
+ continue;
+ /* Put the */
+ /* character into a subr if it is referenced by other characters */
+ if ( (sc->dependents!=NULL &&
+ ((!sc->hconflicts && !sc->vconflicts && !sc->anyflexes) ||
+ SpecialCaseConflicts(sc)) &&
+ !AlwaysSeacable(sc,flags))) {
+ RefChar *r;
+
+ for ( r=sc->layers[ly_fore].refs; r!=NULL; r=r->next )
+ if ( r->sc->ttf_glyph==0x7fff )
+ break;
+ if ( r!=NULL ) /* Contains a reference to something which is */
+ continue; /* not in a sub itself. Skip it for now, we'll*/
+ /* come back to it next pass when perhaps the */
+ /* reference will be nicely ensconsed itself */
+ if ( gi->pcnt>=gi->pmax )
+ gi->psubrs = grealloc(gi->psubrs,(gi->pmax+=gi->glyphcnt)*sizeof(struct potentialsubrs));
+ ps = &gi->psubrs[gi->pcnt];
+ memset(ps,0,sizeof(*ps)); /* set cnt to 0 */
+ ps->idx = gi->pcnt++;
+ ps->full_glyph_index = i;
+ sc->ttf_glyph = gi->pcnt-1;
+ ps->startstop = FigureStartStop(sc,gi);
+ anydone = true;
+ }
+ }
+ }
+#endif /* FONTFORGE_CONFIG_PS_REFS_GET_SUBRS */
+}
+
+int SFOneWidth(SplineFont *sf) {
+ int width, i;
+
+ width = -2;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sf->glyphs[i]) &&
+ (strcmp(sf->glyphs[i]->name,".notdef")!=0 || sf->glyphs[i]->layers[ly_fore].splines!=NULL)) {
+ /* Only trust the width of notdef if it's got some content */
+ /* (at least as far as fixed pitch determination goes) */
+ if ( width==-2 ) width = sf->glyphs[i]->width;
+ else if ( width!=sf->glyphs[i]->width ) {
+ width = -1;
+ break;
+ }
+ }
+return(width);
+}
+
+int CIDOneWidth(SplineFont *_sf) {
+ int width, i;
+ int k;
+ SplineFont *sf;
+
+ if ( _sf->cidmaster!=NULL ) _sf = _sf->cidmaster;
+ width = -2;
+ k=0;
+ do {
+ sf = _sf->subfonts==NULL? _sf : _sf->subfonts[k];
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sf->glyphs[i]) &&
+ (strcmp(sf->glyphs[i]->name,".notdef")!=0 || sf->glyphs[i]->layers[ly_fore].splines!=NULL)) {
+ /* Only trust the width of notdef if it's got some content */
+ /* (at least as far as fixed pitch determination goes) */
+ if ( width==-2 ) width = sf->glyphs[i]->width;
+ else if ( width!=sf->glyphs[i]->width ) {
+ width = -1;
+ break;
+ }
+ }
+ ++k;
+ } while ( k<_sf->subfontcnt );
+return(width);
+}
+
+int SFOneHeight(SplineFont *sf) {
+ int width, i;
+
+ if ( !sf->hasvmetrics )
+return( sf->ascent+sf->descent );
+
+ width = -2;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sf->glyphs[i]) &&
+ (strcmp(sf->glyphs[i]->name,".notdef")!=0 || sf->glyphs[i]->layers[ly_fore].splines!=NULL)) {
+ /* Only trust the width of notdef if it's got some content */
+ /* (at least as far as fixed pitch determination goes) */
+ if ( width==-2 ) width = sf->glyphs[i]->vwidth;
+ else if ( width!=sf->glyphs[i]->vwidth ) {
+ width = -1;
+ break;
+ }
+ }
+return(width);
+}
+
+int SFIsCJK(SplineFont *sf,EncMap *map) {
+ char *val;
+
+ if ( (val = PSDictHasEntry(sf->private,"LanguageGroup"))!=NULL )
+return( strtol(val,NULL,10));
+
+ if ( map->enc->is_japanese || map->enc->is_korean ||
+ map->enc->is_tradchinese || map->enc->is_simplechinese )
+return( true );
+ if ( (map->enc->is_unicodebmp || map->enc->is_unicodefull) &&
+ sf->glyphcnt>0x3000 &&
+ SCWorthOutputting(sf->glyphs[0x3000]) &&
+ !SCWorthOutputting(sf->glyphs['A']) )
+return( true );
+ if ( map->enc==&custom ) {
+ /* If it's in a CID font and it doesn't contain alphabetics, then */
+ /* it's assumed to be CJK */
+ if ( sf->cidmaster!=NULL )
+return( !SCWorthOutputting(SFGetChar(sf,'A',NULL)) &&
+ !SCWorthOutputting(SFGetChar(sf,0x391,NULL)) && /* Alpha */
+ !SCWorthOutputting(SFGetChar(sf,0x410,NULL)) && /* Cyrillic A */
+ !SCWorthOutputting(SFGetChar(sf,-1,"uni0041.hw")) ); /* Halfwidth A, non standard name, from my cidmap */
+ }
+
+return( false );
+}
+
+static void SetupType1Subrs(struct pschars *subrs,GlyphInfo *gi) {
+ int scnt, call_size;
+ int i;
+
+ scnt = subrs->next;
+ call_size = gi->pcnt+scnt<1131 ? 3 : 6;
+ for ( i=0; i<gi->pcnt; ++i ) {
+ /* A subroutine call takes somewhere between 2 and 6 bytes itself. */
+ /* and we must add a return statement to the end. We don't want to */
+ /* make things bigger */
+ if ( gi->psubrs[i].full_glyph_index!=-1 )
+ gi->psubrs[i].idx = scnt++;
+ else if ( gi->psubrs[i].cnt*gi->psubrs[i].len>(gi->psubrs[i].cnt*call_size)+gi->psubrs[i].len+1 )
+ gi->psubrs[i].idx = scnt++;
+ else
+ gi->psubrs[i].idx = -1;
+ }
+
+ subrs->cnt = scnt;
+ subrs->next = scnt;
+ subrs->lens = grealloc(subrs->lens,scnt*sizeof(int));
+ subrs->values = grealloc(subrs->values,scnt*sizeof(unsigned char *));
+
+ for ( i=0; i<gi->pcnt; ++i ) {
+ scnt = gi->psubrs[i].idx;
+ if ( scnt==-1 || gi->psubrs[i].full_glyph_index != -1 )
+ continue;
+ subrs->lens[scnt] = gi->psubrs[i].len+1;
+ subrs->values[scnt] = galloc(subrs->lens[scnt]);
+ memcpy(subrs->values[scnt],gi->psubrs[i].data,gi->psubrs[i].len);
+ subrs->values[scnt][gi->psubrs[i].len] = 11; /* Add a return to end of subr */
+ }
+}
+
+static void SetupType1Chrs(struct pschars *chrs,struct pschars *subrs,GlyphInfo *gi, int iscid) {
+ int i,k,j;
+
+ /* If a glyph lives entirely in a subroutine then we need to create both */
+ /* the subroutine entry, and the char entry which calls the subr. */
+ /* The subroutine entry will be everything EXCEPT the glyph header */
+ /* the char entry will be the glyph header and a subroutine call */
+ /* If the glyph does not go into a subr then everything goes into the char */
+ for ( i=0; i<gi->glyphcnt; ++i ) {
+ int len=0;
+ struct glyphbits *gb = &gi->gb[i];
+ if ( gb->sc==NULL )
+ continue;
+ if ( !iscid )
+ chrs->keys[i] = copy(gb->sc->name);
+ for ( k=0; k<2; ++k ) if ( k!=0 || gb->sc->ttf_glyph!=0x7fff ) {
+ uint8 *vals;
+ for ( j=0; j<gb->bcnt; ++j ) {
+ if ( k!=0 || j!=0 )
+ len += gb->bits[j].dlen;
+ if ( k==1 && gb->sc->ttf_glyph!=0x7fff ) {
+ int si = gi->psubrs[ gb->sc->ttf_glyph ].idx;
+ len += 1 + (si<=107?1:si<=1131?2:5);
+ break;
+ }
+ if ( gi->psubrs[ gb->bits[j].psub_index ].idx==-1 )
+ len += gi->psubrs[ gb->bits[j].psub_index ].len;
+ else {
+ int si = gi->psubrs[ gb->bits[j].psub_index ].idx;
+ len += 1 + (si<=107?1:si<=1131?2:5);
+ /* Space for a subr call & the sub number to call */
+ }
+ }
+ if ( k==0 ) {
+ int si = gi->psubrs[ gb->sc->ttf_glyph ].idx;
+ subrs->lens[si] = len+1;
+ vals = subrs->values[si] = galloc(len+2);
+ } else {
+ /* Don't need or want and endchar if we are using seac */
+ chrs->lens[i] = len + !gb->wasseac;
+ vals = chrs->values[i] = galloc(len+2); /* space for endchar and a final NUL (which is really meaningless, but makes me feel better) */
+ }
+
+ len = 0;
+ for ( j=0; j<gb->bcnt; ++j ) {
+ int si;
+ if ( k!=0 || j!=0 ) {
+ memcpy(vals+len,gb->bits[j].data,gb->bits[j].dlen);
+ len += gb->bits[j].dlen;
+ }
+ si = -1;
+ if ( k==1 && gb->sc->ttf_glyph!=0x7fff )
+ si = gi->psubrs[ gb->sc->ttf_glyph ].idx;
+ else if ( gi->psubrs[ gb->bits[j].psub_index ].idx==-1 ) {
+ memcpy(vals+len,gi->psubrs[ gb->bits[j].psub_index ].data,
+ gi->psubrs[ gb->bits[j].psub_index ].len);
+ len += gi->psubrs[ gb->bits[j].psub_index ].len;
+ } else
+ si = gi->psubrs[ gb->bits[j].psub_index ].idx;
+ if ( si!=-1 ) {
+ /* space for the number (subroutine index) */
+ if ( si<=107 )
+ vals[len++] = si+139;
+ else if ( si>0 && si<=1131 ) {
+ si-=108;
+ vals[len++] = (si>>8)+247;
+ vals[len++] = si&0xff;
+ } else {
+ vals[len++] = '\377';
+ vals[len++] = (si>>24)&0xff;
+ vals[len++] = (si>>16)&0xff;
+ vals[len++] = (si>>8)&0xff;
+ vals[len++] = si&0xff;
+ }
+ /* space for the subroutine operator */
+ vals[len++] = 10;
+ }
+ if ( k==1 && gb->sc->ttf_glyph!=0x7fff )
+ break;
+ }
+ if ( k==0 ) {
+ vals[len++] = 11; /* return */
+ vals[len] = '\0';
+ } else if ( gb->wasseac ) {
+ /* Don't want an endchar */
+ vals[len] = '\0';
+ } else {
+ vals[len++] = 14; /* endchar */
+ vals[len] = '\0';
+ }
+ }
+ }
+}
+
+struct pschars *SplineFont2ChrsSubrs(SplineFont *sf, int iscjk,
+ struct pschars *subrs,int flags, enum fontformat format) {
+ struct pschars *chrs = gcalloc(1,sizeof(struct pschars));
+ int i, cnt, instance_count;
+ int fixed;
+ int notdef_pos;
+ MMSet *mm = sf->mm;
+ int round = (flags&ps_flag_round)? true : false;
+ GlyphInfo gi;
+ SplineChar dummynotdef, *sc;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ Layer dummylayers[2];
+#endif
+
+ if ( (format==ff_mma || format==ff_mmb) && mm!=NULL ) {
+ instance_count = mm->instance_count;
+ sf = mm->instances[0];
+ fixed = 0;
+ for ( i=0; i<instance_count; ++i ) {
+ MarkTranslationRefs(mm->instances[i]);
+ fixed = SFOneWidth(mm->instances[i]);
+ if ( fixed==-1 )
+ break;
+ }
+ } else {
+ MarkTranslationRefs(sf);
+ fixed = SFOneWidth(sf);
+ instance_count = 1;
+ }
+
+ notdef_pos = SFFindNotdef(sf,fixed);
+ cnt = 0;
+ for ( i=0; i<sf->glyphcnt; ++i )
+#if HANYANG
+ if ( sf->glyphs[i]!=NULL && sf->glyphs[i]->compositionunit )
+ /* Don't count it */;
+ else
+#endif
+ if ( SCWorthOutputting(sf->glyphs[i]) &&
+ ( i==notdef_pos || strcmp(sf->glyphs[i]->name,".notdef")!=0))
+ ++cnt;
+/* only honor the width on .notdef in non-fixed pitch fonts (or ones where there is an actual outline in notdef) */
+ if ( notdef_pos==-1 )
+ ++cnt; /* one notdef entry */
+
+ memset(&gi,0,sizeof(gi));
+ memset(&gi.hashed,-1,sizeof(gi.hashed));
+ gi.instance_count = 1;
+ gi.sf = sf;
+ gi.glyphcnt = cnt;
+ gi.gb = gcalloc(cnt,sizeof(struct glyphbits));
+ gi.pmax = 3*cnt;
+ gi.psubrs = galloc(gi.pmax*sizeof(struct potentialsubrs));
+ gi.instance_count = instance_count;
+
+ if ( notdef_pos==-1 ) {
+ memset(&dummynotdef,0,sizeof(dummynotdef));
+ dummynotdef.name = ".notdef";
+ dummynotdef.parent = sf;
+ dummynotdef.layer_cnt = 2;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ dummynotdef.layers = dummylayers;
+ memset(dummylayers,0,sizeof(dummylayers));
+#endif
+ dummynotdef.width = SFOneWidth(sf);
+ if ( dummynotdef.width==-1 )
+ dummynotdef.width = (sf->ascent+sf->descent)/2;
+ gi.gb[0].sc = &dummynotdef;
+ } else
+ gi.gb[0].sc = sf->glyphs[notdef_pos];
+ cnt = 1;
+ for ( i=0 ; i<sf->glyphcnt; ++i ) {
+#if HANYANG
+ if ( sf->glyphs[i]!=NULL && sf->glyphs[i]->compositionunit )
+ /* don't output it, should be in a subroutine */;
+ else
+#endif
+ if ( SCWorthOutputting(sf->glyphs[i]) &&
+ strcmp(sf->glyphs[i]->name,".notdef")!=0) /* We've already added .notdef */
+ gi.gb[cnt++].sc = sf->glyphs[i];
+ }
+
+ SplineFont2FullSubrs1(flags,&gi);
+
+ for ( i=0; i<cnt; ++i ) {
+ if ( (sc = gi.gb[i].sc)==NULL )
+ continue;
+ gi.active = &gi.gb[i];
+ SplineChar2PS(sc,NULL, round,iscjk,subrs,flags,format,&gi);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next()) {
+ PSCharsFree(chrs);
+ GIFree(&gi,&dummynotdef);
+return( NULL );
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+
+ SetupType1Subrs(subrs,&gi);
+
+ chrs->cnt = cnt;
+ chrs->keys = galloc(cnt*sizeof(char *));
+ chrs->lens = galloc(cnt*sizeof(int));
+ chrs->values = galloc(cnt*sizeof(unsigned char *));
+
+ SetupType1Chrs(chrs,subrs,&gi,false);
+
+ GIFree(&gi,&dummynotdef);
+
+ chrs->next = cnt;
+ if ( chrs->next>chrs->cnt )
+ IError("Character estimate failed, about to die..." );
+return( chrs );
+}
+
+struct pschars *CID2ChrsSubrs(SplineFont *cidmaster,struct cidbytes *cidbytes,int flags) {
+ struct pschars *chrs = gcalloc(1,sizeof(struct pschars));
+ int i, cnt, cid;
+ SplineFont *sf = NULL;
+ struct fddata *fd;
+ int round = (flags&ps_flag_round)? true : false;
+ /* I don't support mm cid files. I don't think adobe does either */
+ GlyphInfo gi;
+ int notdef_subfont;
+ SplineChar dummynotdef, *sc;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ Layer dummylayers[2];
+#endif
+
+ cnt = 0; notdef_subfont = -1;
+ for ( i=0; i<cidmaster->subfontcnt; ++i ) {
+ if ( cnt<cidmaster->subfonts[i]->glyphcnt )
+ cnt = cidmaster->subfonts[i]->glyphcnt;
+ if ( cidmaster->subfonts[i]->glyphcnt>0 &&
+ SCWorthOutputting(cidmaster->subfonts[i]->glyphs[0]) )
+ notdef_subfont = i;
+ }
+ cidbytes->cidcnt = cnt;
+
+ if ( notdef_subfont==-1 ) {
+ memset(&dummynotdef,0,sizeof(dummynotdef));
+ dummynotdef.name = ".notdef";
+ dummynotdef.parent = cidmaster->subfonts[0];
+ dummynotdef.layer_cnt = 2;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ dummynotdef.layers = dummylayers;
+ memset(dummylayers,0,sizeof(dummylayers));
+#endif
+ dummynotdef.width = SFOneWidth(dummynotdef.parent);
+ if ( dummynotdef.width==-1 )
+ dummynotdef.width = (dummynotdef.parent->ascent+dummynotdef.parent->descent);
+ }
+
+ memset(&gi,0,sizeof(gi));
+ gi.instance_count = 1;
+ gi.glyphcnt = cnt;
+ gi.gb = galloc(cnt*sizeof(struct glyphbits));
+ gi.pmax = 3*cnt;
+ gi.psubrs = galloc(gi.pmax*sizeof(struct potentialsubrs));
+
+ chrs->cnt = cnt;
+ chrs->lens = gcalloc(cnt,sizeof(int));
+ chrs->values = gcalloc(cnt,sizeof(unsigned char *));
+ cidbytes->fdind = galloc(cnt*sizeof(unsigned char *));
+ memset(cidbytes->fdind,-1,cnt*sizeof(unsigned char *));
+
+ /* In a type1 CID-keyed font we must handle subroutines subfont by subfont*/
+ /* as there are no global subrs */
+ for ( i=0; i<cidmaster->subfontcnt; ++i ) {
+ gi.sf = sf = cidmaster->subfonts[i];
+ MarkTranslationRefs(sf);
+ fd = &cidbytes->fds[i];
+ memset(&gi.hashed,-1,sizeof(gi.hashed));
+ gi.instance_count = 1;
+ gi.glyphcnt = sf->glyphcnt;
+ memset(gi.gb,0,sf->glyphcnt*sizeof(struct glyphbits));
+ for ( cid=0; cid<cnt && cid<sf->glyphcnt; ++cid ) {
+ if ( cid==0 && notdef_subfont==-1 && i==cidmaster->subfontcnt-1 )
+ gi.gb[0].sc = &dummynotdef;
+ else if ( SCWorthOutputting(sf->glyphs[cid]) &&
+ strcmp(sf->glyphs[cid]->name,".notdef")!=0) /* We've already added .notdef */
+ gi.gb[cid].sc = sf->glyphs[cid];
+ if ( gi.gb[cid].sc!=NULL )
+ cidbytes->fdind[cid] = i;
+ }
+ SplineFont2FullSubrs1(flags,&gi);
+
+ for ( cid=0; cid<cnt && cid<sf->glyphcnt; ++cid ) {
+ if ( (sc = gi.gb[cid].sc)==NULL )
+ continue;
+ gi.active = &gi.gb[cid];
+ SplineChar2PS(sc,NULL, round,fd->iscjk|0x100,fd->subrs,
+ flags,ff_cid,&gi);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next()) {
+ PSCharsFree(chrs);
+ GIFree(&gi,&dummynotdef);
+return( NULL );
+ }
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+ }
+
+ SetupType1Subrs(fd->subrs,&gi);
+ SetupType1Chrs(chrs,fd->subrs,&gi,true);
+ GIContentsFree(&gi,&dummynotdef);
+ }
+ GIFree(&gi,&dummynotdef);
+ chrs->next = cnt;
+return( chrs );
+}
+
+/* ************************************************************************** */
+/* ********************** Type2 PostScript CharStrings ********************** */
+/* ************************************************************************** */
+
+#if 0
+static int real_warn = false;
+#endif
+
+static real myround2(real pos, int round) {
+ if ( round )
+return( rint(pos));
+
+return( rint(65536*pos)/65536 );
+}
+
+static void AddNumber2(GrowBuf *gb, real pos, int round) {
+ int val, factor;
+ unsigned char *str;
+
+ if ( gb->pt+5>=gb->end )
+ GrowBuffer(gb);
+
+ pos = rint(65536*pos)/65536;
+ if ( round )
+ pos = rint(pos);
+
+ str = gb->pt;
+ if ( pos>32767.99 || pos<-32768 ) {
+ /* same logic for big ints and reals */
+ if ( pos>0x3fffffff || pos<-0x40000000 ) {
+ LogError( _("Number out of range: %g in type2 output (must be [-65536,65535])\n"),
+ pos );
+ if ( pos>0 ) pos = 0x3fffffff; else pos = -0x40000000;
+ }
+ for ( factor=2; factor<32768; factor<<=2 )
+ if ( pos/factor<32767.99 && pos/factor>-32768 )
+ break;
+ AddNumber2(gb,pos/factor,false);
+ AddNumber2(gb,factor,false);
+ if ( gb->pt+2>=gb->end )
+ GrowBuffer(gb);
+ *(gb->pt++) = 0x0c; /* Multiply operator */
+ *(gb->pt++) = 0x18;
+ } else if ( pos!=floor(pos )) {
+ val = pos*65536;
+ *str++ = '\377';
+ *str++ = (val>>24)&0xff;
+ *str++ = (val>>16)&0xff;
+ *str++ = (val>>8)&0xff;
+ *str++ = val&0xff;
+ } else {
+ val = rint(pos);
+ if ( pos>=-107 && pos<=107 )
+ *str++ = val+139;
+ else if ( pos>=108 && pos<=1131 ) {
+ val -= 108;
+ *str++ = (val>>8)+247;
+ *str++ = val&0xff;
+ } else if ( pos>=-1131 && pos<=-108 ) {
+ val = -val;
+ val -= 108;
+ *str++ = (val>>8)+251;
+ *str++ = val&0xff;
+ } else {
+ *str++ = 28;
+ *str++ = (val>>8)&0xff;
+ *str++ = val&0xff;
+ }
+ }
+ gb->pt = str;
+}
+
+static void AddMask2(GrowBuf *gb,uint8 mask[12],int cnt, int oper) {
+ int i;
+
+ if ( gb->pt+1+((cnt+7)>>3)>=gb->end )
+ GrowBuffer(gb);
+ *gb->pt++ = oper; /* hintmask,cntrmask */
+ for ( i=0; i< ((cnt+7)>>3); ++i )
+ *gb->pt++ = mask[i];
+}
+
+static void CounterHints2(GrowBuf *gb, SplineChar *sc, int hcnt) {
+ int i;
+
+ for ( i=0; i<sc->countermask_cnt; ++i )
+ AddMask2(gb,sc->countermasks[i],hcnt,20); /* cntrmask */
+}
+
+static int HintSetup2(GrowBuf *gb,struct hintdb *hdb, SplinePoint *to, int break_subr ) {
+
+ /* We might get a point with a hintmask in a glyph with no conflicts */
+ /* (ie. the initial point when we return to it at the end of the splineset*/
+ /* in that case hdb->cnt will be 0 and we should ignore it */
+ /* components in subroutines depend on not having any hintmasks */
+ if ( to->hintmask==NULL || hdb->cnt==0 || hdb->noconflicts || hdb->skiphm )
+return( false );
+
+ if ( memcmp(hdb->mask,*to->hintmask,(hdb->cnt+7)/8)==0 )
+return( false );
+
+ if ( break_subr )
+ BreakSubroutine(gb,hdb);
+
+ AddMask2(gb,*to->hintmask,hdb->cnt,19); /* hintmask */
+ memcpy(hdb->mask,*to->hintmask,sizeof(HintMask));
+ hdb->donefirsthm = true;
+ if ( break_subr )
+ StartNextSubroutine(gb,hdb);
+return( true );
+}
+
+static void moveto2(GrowBuf *gb,struct hintdb *hdb,SplinePoint *to, int round) {
+ BasePoint temp, *tom;
+
+ if ( gb->pt+18 >= gb->end )
+ GrowBuffer(gb);
+
+ BreakSubroutine(gb,hdb);
+ HintSetup2(gb,hdb,to,false);
+ tom = &to->me;
+ if ( round ) {
+ temp.x = rint(tom->x);
+ temp.y = rint(tom->y);
+ tom = &temp;
+ }
+#if 0
+ if ( hdb->current.x==tom->x && hdb->current.y==tom->y ) {
+ /* we're already here */
+ /* Yes, but a move is required anyway at char start */
+ } else
+#endif
+ if ( hdb->current.x==tom->x ) {
+ AddNumber2(gb,tom->y-hdb->current.y,round);
+ *(gb->pt)++ = 4; /* v move to */
+ } else if ( hdb->current.y==tom->y ) {
+ AddNumber2(gb,tom->x-hdb->current.x,round);
+ *(gb->pt)++ = 22; /* h move to */
+ } else {
+ AddNumber2(gb,tom->x-hdb->current.x,round);
+ AddNumber2(gb,tom->y-hdb->current.y,round);
+ *(gb->pt)++ = 21; /* r move to */
+ }
+ hdb->current = *tom;
+ StartNextSubroutine(gb,hdb);
+}
+
+static Spline *lineto2(GrowBuf *gb,struct hintdb *hdb,Spline *spline, Spline *done, int round) {
+ int cnt, hv, hvcnt;
+ Spline *test, *lastgood, *lasthvgood;
+ BasePoint temp1, temp2, *tom, *fromm;
+ int donehm;
+
+ lastgood = NULL;
+ for ( test=spline, cnt=0; test->knownlinear && cnt<15; ) {
+ ++cnt;
+ lastgood = test;
+ test = test->to->next;
+ /* it will be smaller to use a closepath operator so ignore the */
+ /* ultimate spline */
+ if ( test==done || test==NULL || test->to->next==done )
+ break;
+ }
+
+ HintSetup2(gb,hdb,spline->to,true);
+
+ hv = -1; hvcnt=1; lasthvgood = NULL;
+ if ( spline->from->me.x==spline->to->me.x )
+ hv = 1; /* Vertical */
+ else if ( spline->from->me.y==spline->to->me.y )
+ hv = 0; /* Horizontal */
+ donehm = true;
+ if ( hv!=-1 ) {
+ lasthvgood = spline; hvcnt = 1;
+ if ( cnt!=1 ) {
+ for ( test=spline->to->next; test!=NULL ; test = test->to->next ) {
+ fromm = &test->from->me;
+ if ( round ) {
+ temp2.x = rint(fromm->x);
+ temp2.y = rint(fromm->y);
+ fromm = &temp2;
+ }
+ tom = &test->to->me;
+ if ( round ) {
+ temp1.x = rint(tom->x);
+ temp1.y = rint(tom->y);
+ tom = &temp1;
+ }
+ if ( hv==1 && tom->y==fromm->y )
+ hv = 0;
+ else if ( hv==0 && tom->x==fromm->x )
+ hv = 1;
+ else
+ break;
+ lasthvgood = test;
+ ++hvcnt;
+ if ( test==lastgood )
+ break;
+ }
+ }
+ donehm = true;
+ if ( hvcnt==cnt || hvcnt>=2 ) {
+ /* It's more efficient to do some h/v linetos */
+ for ( test=spline; ; test = test->to->next ) {
+ if ( !donehm && test->to->hintmask!=NULL )
+ break;
+ donehm = false;
+ fromm = &test->from->me;
+ if ( round ) {
+ temp2.x = rint(fromm->x);
+ temp2.y = rint(fromm->y);
+ fromm = &temp2;
+ }
+ tom = &test->to->me;
+ if ( round ) {
+ temp1.x = rint(tom->x);
+ temp1.y = rint(tom->y);
+ tom = &temp1;
+ }
+ if ( fromm->x==tom->x )
+ AddNumber2(gb,tom->y-fromm->y,round);
+ else
+ AddNumber2(gb,tom->x-fromm->x,round);
+ hdb->current = *tom;
+ if ( test==lasthvgood ) {
+ test = test->to->next;
+ break;
+ }
+ }
+ if ( gb->pt+1 >= gb->end )
+ GrowBuffer(gb);
+ *(gb->pt)++ = spline->from->me.x==spline->to->me.x? 7 : 6;
+return( test );
+ }
+ }
+
+ for ( test=spline; test!=NULL; test = test->to->next ) {
+ if ( !donehm && test->to->hintmask!=NULL )
+ break;
+ donehm = false;
+ fromm = &test->from->me;
+ if ( round ) {
+ temp2.x = rint(fromm->x);
+ temp2.y = rint(fromm->y);
+ fromm = &temp2;
+ }
+ tom = &test->to->me;
+ if ( round ) {
+ temp1.x = rint(tom->x);
+ temp1.y = rint(tom->y);
+ tom = &temp1;
+ }
+ AddNumber2(gb,tom->x-fromm->x,round);
+ AddNumber2(gb,tom->y-fromm->y,round);
+ hdb->current = *tom;
+ if ( test==lastgood ) {
+ test = test->to->next;
+ break;
+ }
+ }
+ if ( gb->pt+1 >= gb->end )
+ GrowBuffer(gb);
+ *(gb->pt)++ = 5; /* r line to */
+return( test );
+}
+
+static Spline *curveto2(GrowBuf *gb,struct hintdb *hdb,Spline *spline, Spline *done, int round) {
+ int cnt=0, hv;
+ Spline *first;
+ BasePoint start;
+ int donehm;
+
+ HintSetup2(gb,hdb,spline->to,true);
+
+ hv = -1;
+ if ( hdb->current.x==myround2(spline->from->nextcp.x,round) &&
+ myround2(spline->to->prevcp.y,round)==myround2(spline->to->me.y,round) )
+ hv = 1;
+ else if ( hdb->current.y==myround2(spline->from->nextcp.y,round) &&
+ myround2(spline->to->prevcp.x,round)==myround2(spline->to->me.x,round) )
+ hv = 0;
+ donehm = true;
+ if ( hv!=-1 ) {
+ first = spline; start = hdb->current;
+ while (
+ (hv==1 && hdb->current.x==myround2(spline->from->nextcp.x,round) &&
+ myround2(spline->to->prevcp.y,round)==myround2(spline->to->me.y,round) ) ||
+ (hv==0 && hdb->current.y==myround2(spline->from->nextcp.y,round) &&
+ myround2(spline->to->prevcp.x,round)==myround2(spline->to->me.x,round) ) ) {
+ if ( !donehm && spline->to->hintmask!=NULL )
+ break;
+ donehm = false;
+ if ( hv==1 ) {
+ AddNumber2(gb,myround2(spline->from->nextcp.y,round)-hdb->current.y,round);
+ AddNumber2(gb,myround2(spline->to->prevcp.x,round)-myround2(spline->from->nextcp.x,round),round);
+ AddNumber2(gb,myround2(spline->to->prevcp.y,round)-myround2(spline->from->nextcp.y,round),round);
+ AddNumber2(gb,myround2(spline->to->me.x,round)-myround2(spline->to->prevcp.x,round),round);
+ hv = 0;
+ } else {
+ AddNumber2(gb,myround2(spline->from->nextcp.x,round)-hdb->current.x,round);
+ AddNumber2(gb,myround2(spline->to->prevcp.x,round)-myround2(spline->from->nextcp.x,round),round);
+ AddNumber2(gb,myround2(spline->to->prevcp.y,round)-myround2(spline->from->nextcp.y,round),round);
+ AddNumber2(gb,myround2(spline->to->me.y,round)-myround2(spline->to->prevcp.y,round),round);
+ hv = 1;
+ }
+ hdb->current.x = myround2(spline->to->me.x,round);
+ hdb->current.y = myround2(spline->to->me.y,round);
+ ++cnt;
+ spline = spline->to->next;
+ if ( spline==done || spline==NULL || cnt>9 || spline->knownlinear )
+ break;
+ }
+ if ( gb->pt+1 >= gb->end )
+ GrowBuffer(gb);
+ *(gb->pt)++ = ( start.x==myround2(first->from->nextcp.x,round) && myround2(first->to->prevcp.y,round)==myround2(first->to->me.y,round) )?
+ 30:31; /* vhcurveto:hvcurveto */
+return( spline );
+ }
+ while ( cnt<6 ) {
+ if ( !donehm && spline->to->hintmask!=NULL )
+ break;
+ donehm = false;
+ hv = -1;
+ if ( hdb->current.x==myround2(spline->from->nextcp.x,round) &&
+ myround2(spline->to->prevcp.y,round)==myround2(spline->to->me.y,round) &&
+ spline->to->next!=NULL &&
+ myround2(spline->to->me.y,round)==myround2(spline->to->nextcp.y,round) &&
+ myround2(spline->to->next->to->prevcp.x,round)==myround2(spline->to->next->to->me.x,round) )
+ break;
+ else if ( hdb->current.y==myround2(spline->from->nextcp.y,round) &&
+ myround2(spline->to->prevcp.x,round)==myround2(spline->to->me.x,round) &&
+ spline->to->next!=NULL &&
+ myround2(spline->to->me.x,round)==myround2(spline->to->nextcp.x,round) &&
+ myround2(spline->to->next->to->prevcp.y,round)==myround2(spline->to->next->to->me.y,round) )
+ break;
+ AddNumber2(gb,myround2(spline->from->nextcp.x,round)-hdb->current.x,round);
+ AddNumber2(gb,myround2(spline->from->nextcp.y,round)-hdb->current.y,round);
+ AddNumber2(gb,myround2(spline->to->prevcp.x,round)-myround2(spline->from->nextcp.x,round),round);
+ AddNumber2(gb,myround2(spline->to->prevcp.y,round)-myround2(spline->from->nextcp.y,round),round);
+ AddNumber2(gb,myround2(spline->to->me.x,round)-myround2(spline->to->prevcp.x,round),round);
+ AddNumber2(gb,myround2(spline->to->me.y,round)-myround2(spline->to->prevcp.y,round),round);
+ hdb->current.x = myround2(spline->to->me.x,round);
+ hdb->current.y = myround2(spline->to->me.y,round);
+ ++cnt;
+ spline = spline->to->next;
+ if ( spline==done || spline==NULL || spline->knownlinear )
+ break;
+ }
+ if ( gb->pt+1 >= gb->end )
+ GrowBuffer(gb);
+ *(gb->pt)++ = 8; /* rrcurveto */
+return( spline );
+}
+
+static void flexto2(GrowBuf *gb,struct hintdb *hdb,Spline *pspline,int round) {
+ BasePoint *c0, *c1, *mid, *end, *nc0, *nc1;
+ Spline *nspline;
+
+ c0 = &pspline->from->nextcp;
+ c1 = &pspline->to->prevcp;
+ mid = &pspline->to->me;
+ nspline = pspline->to->next;
+ nc0 = &nspline->from->nextcp;
+ nc1 = &nspline->to->prevcp;
+ end = &nspline->to->me;
+
+ HintSetup2(gb,hdb,nspline->to,true);
+
+ if ( myround2(c0->y,round)==hdb->current.y && myround2(nc1->y,round)==hdb->current.y &&
+ myround2(end->y,round)==hdb->current.y &&
+ myround2(c1->y,round)==myround2(mid->y,round) && myround2(nc0->y,round)==myround2(mid->y,round) ) {
+ if ( gb->pt+7*6+2 >= gb->end )
+ GrowBuffer(gb);
+ AddNumber2(gb,myround2(c0->x,round)-hdb->current.x,round);
+ AddNumber2(gb,myround2(c1->x,round)-myround2(c0->x,round),round);
+ AddNumber2(gb,myround2(c1->y,round)-myround2(c0->y,round),round);
+ AddNumber2(gb,myround2(mid->x,round)-myround2(c1->x,round),round);
+ AddNumber2(gb,myround2(nc0->x,round)-myround2(mid->x,round),round);
+ AddNumber2(gb,myround2(nc1->x,round)-myround2(nc0->x,round),round);
+ AddNumber2(gb,myround2(end->x,round)-myround2(nc1->x,round),round);
+ *gb->pt++ = 12; *gb->pt++ = 34; /* hflex */
+ } else {
+ if ( gb->pt+11*6+2 >= gb->end )
+ GrowBuffer(gb);
+ AddNumber2(gb,myround2(c0->x,round)-hdb->current.x,round);
+ AddNumber2(gb,myround2(c0->y,round)-hdb->current.y,round);
+ AddNumber2(gb,myround2(c1->x,round)-myround2(c0->x,round),round);
+ AddNumber2(gb,myround2(c1->y,round)-myround2(c0->y,round),round);
+ AddNumber2(gb,myround2(mid->x,round)-myround2(c1->x,round),round);
+ AddNumber2(gb,myround2(mid->y,round)-myround2(c1->y,round),round);
+ AddNumber2(gb,myround2(nc0->x,round)-myround2(mid->x,round),round);
+ AddNumber2(gb,myround2(nc0->y,round)-myround2(mid->y,round),round);
+ AddNumber2(gb,myround2(nc1->x,round)-myround2(nc0->x,round),round);
+ AddNumber2(gb,myround2(nc1->y,round)-myround2(nc0->y,round),round);
+ if ( hdb->current.y==myround2(end->y,round) )
+ AddNumber2(gb,myround2(end->x,round)-myround2(nc1->x,round),round);
+ else
+ AddNumber2(gb,myround2(end->y,round)-myround2(nc1->y,round),round);
+ *gb->pt++ = 12; *gb->pt++ = 37; /* flex1 */
+ }
+
+ hdb->current = *end;
+}
+
+static void CvtPsSplineSet2(GrowBuf *gb, SplinePointList *spl,
+ struct hintdb *hdb, int is_order2,int round ) {
+ Spline *spline, *first;
+ SplinePointList temp, *freeme = NULL;
+ int unhinted = true;;
+
+ if ( is_order2 )
+ freeme = spl = SplineSetsPSApprox(spl);
+
+ for ( ; spl!=NULL; spl = spl->next ) {
+ first = NULL;
+ SplineSetReverse(spl);
+ /* PostScript and TrueType store their splines in in reverse */
+ /* orientations. Annoying. Oh well. I shall adopt TrueType and */
+ /* If I reverse the PS splinesets after reading them in, and then */
+ /* again when saving them out, all should be well */
+ if ( spl->first->flexy || spl->first->flexx ) {
+ /* can't handle a flex (mid) point as the first point. rotate the */
+ /* list by one, this is possible because only closed paths have */
+ /* points marked as flex, and because we can't have two flex mid- */
+ /* points in a row */
+ if ( spl->first->hintmask==NULL || spl->first->next->to->hintmask!=NULL ) {
+ /* But we can't rotate it if we expect it to provide us with */
+ /* a hintmask. */
+ temp = *spl;
+ temp.first = temp.last = spl->first->next->to;
+ spl = &temp;
+ }
+ if ( spl->first->flexy || spl->first->flexx ) {
+ /* If we couldn't rotate, or if we rotated to something that */
+ /* also is flexible, then just turn off flex. That's safe */
+ spl->first->flexx = spl->first->flexy = false;
+ }
+ }
+ if ( unhinted && hdb->cnt>0 && spl->first->hintmask!=NULL ) {
+ hdb->mask[0] = ~(*spl->first->hintmask)[0]; /* Make it different */
+ unhinted = false;
+ }
+ moveto2(gb,hdb,spl->first,round);
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; ) {
+ if ( first==NULL ) first = spline;
+ else if ( first->from==spline->to )
+ hdb->skiphm = true;
+ if ( spline->to->flexx || spline->to->flexy ) {
+ flexto2(gb,hdb,spline,round); /* does two adjacent splines */
+ spline = spline->to->next->to->next;
+ } else if ( spline->knownlinear && spline->to == spl->first )
+ /* In Type2 we don't even need a closepath to finish this off */
+ /* (which is good, because there isn't a close path) */
+ break;
+ else if ( spline->knownlinear )
+ spline = lineto2(gb,hdb,spline,first,round);
+ else
+ spline = curveto2(gb,hdb,spline,first,round);
+ }
+ hdb->skiphm = false;
+ /* No closepath oper in type2 fonts, it's implied */
+ SplineSetReverse(spl);
+ /* Of course, I have to Reverse again to get back to my convention after*/
+ /* saving */
+ }
+ SplinePointListsFree(freeme);
+}
+
+static void DumpHints(GrowBuf *gb,StemInfo *h,int oper,int midoper,int round) {
+ real last = 0, cur;
+ int cnt;
+
+ if ( h==NULL )
+return;
+ cnt = 0;
+ while ( h!=NULL && h->hintnumber!=-1 ) {
+ /* Type2 hints do not support negative widths except in the case of */
+ /* ghost (now called edge) hints */
+ if ( cnt>24-1 ) { /* stack max = 48 numbers, => 24 hints, leave a bit of slop for the width */
+ if ( gb->pt+1>=gb->end )
+ GrowBuffer(gb);
+ *gb->pt++ = midoper;
+ cnt = 0;
+ }
+ cur = myround2(h->start,round) + myround2(h->width,round);
+ if ( h->width<0 ) {
+ AddNumber2(gb,cur-last,round);
+ AddNumber2(gb,-myround2(h->width,round),round);
+ cur -= myround2(h->width,round);
+ } else if ( h->ghost ) {
+ if ( h->width==20 ) {
+ AddNumber2(gb,myround2(h->start,round)-last+20,round);
+ AddNumber2(gb,-20,round);
+ cur = myround2(h->start,round);
+ } else {
+ AddNumber2(gb,myround2(h->start+21,round)-last,round);
+ AddNumber2(gb,-21,round);
+ cur = myround2(h->start+21,round)-21;
+ }
+ } else {
+ AddNumber2(gb,myround2(h->start,round)-last,round);
+ AddNumber2(gb,myround2(h->width,round),round);
+ }
+ last = cur;
+ h = h->next;
+ ++cnt;
+ }
+ if ( oper!=-1 ) {
+ if ( gb->pt+1>=gb->end )
+ GrowBuffer(gb);
+ *gb->pt++ = oper;
+ }
+}
+
+static void DumpRefsHints(GrowBuf *gb, struct hintdb *hdb,RefChar *cur,StemInfo *h,StemInfo *v,
+ BasePoint *trans, int round) {
+ uint8 masks[12];
+ int cnt, sets=0;
+ StemInfo *rs;
+
+ /* trans has already been rounded (whole char is translated by an integral amount) */
+
+ /* If we have a subroutine containing conflicts, then its hints will match*/
+ /* ours exactly, and we can use its hintmasks directly */
+ if (( cur->sc->hconflicts || cur->sc->vconflicts ) &&
+ cur->sc->layers[ly_fore].splines!=NULL &&
+ cur->sc->layers[ly_fore].splines->first->hintmask!=NULL ) {
+ AddMask2(gb,*cur->sc->layers[ly_fore].splines->first->hintmask,hdb->cnt,19); /* hintmask */
+ hdb->donefirsthm = true;
+ memcpy(hdb->mask,*cur->sc->layers[ly_fore].splines->first->hintmask,sizeof(HintMask));
+return;
+ }
+
+ if ( h==NULL && v==NULL )
+ IError("hintmask invoked when there are no hints");
+ memset(masks,'\0',sizeof(masks));
+ cnt = 0;
+ while ( h!=NULL && h->hintnumber>=0 ) {
+ /* Horizontal stems are defined by vertical bounds */
+ real pos = (round ? rint(h->start) : h->start) - trans->y;
+ for ( rs = cur->sc->hstem; rs!=NULL; rs=rs->next ) {
+ real rpos = round ? rint(rs->start) : rs->start;
+ if ( rpos==pos && (round ? (rint(rs->width)==rint(h->width)) : (rs->width==h->width)) ) {
+ masks[h->hintnumber>>3] |= 0x80>>(h->hintnumber&7);
+ ++sets;
+ break;
+ } else if ( rpos>pos )
+ break;
+ }
+ h = h->next; ++cnt;
+ }
+ while ( v!=NULL && v->hintnumber>=0 ) {
+ real pos = (round ? rint(v->start) : v->start) - trans->x;
+ for ( rs = cur->sc->vstem; rs!=NULL; rs=rs->next ) {
+ real rpos = round ? rint(rs->start) : rs->start;
+ if ( rpos==pos && (round ? (rint(rs->width)==rint(v->width)) : (rs->width==v->width)) ) {
+ masks[v->hintnumber>>3] |= 0x80>>(v->hintnumber&7);
+ ++sets;
+ break;
+ } else if ( rpos>pos )
+ break;
+ }
+ v = v->next; ++cnt;
+ }
+ BreakSubroutine(gb,hdb);
+ hdb->donefirsthm = true;
+ /* if ( sets!=0 ) */ /* First ref will need a hintmask even if it has no hints (if there are conflicts) */
+ AddMask2(gb,masks,cnt,19); /* hintmask */
+}
+
+static void DummyHintmask(GrowBuf *gb,struct hintdb *hdb) {
+ HintMask hm;
+
+ memset(hm,0,sizeof(hm));
+ if ( hdb->cnt!=0 ) {
+ BreakSubroutine(gb,hdb);
+ hdb->donefirsthm = true;
+ AddMask2(gb,hm,hdb->cnt,19); /* hintmask */
+ }
+}
+
+static void SetTransformedHintMask(GrowBuf *gb,struct hintdb *hdb,
+ SplineChar *sc, RefChar *ref, BasePoint *trans, int round) {
+ HintMask hm;
+
+ if ( HintMaskFromTransformedRef(ref,trans,sc,&hm)!=NULL ) {
+ BreakSubroutine(gb,hdb);
+ hdb->donefirsthm = true;
+ AddMask2(gb,hm,hdb->cnt,19); /* hintmask */
+ } else if ( !hdb->donefirsthm )
+ DummyHintmask(gb,hdb);
+}
+
+static void ExpandRef2(GrowBuf *gb, SplineChar *sc, struct hintdb *hdb,
+ RefChar *r, BasePoint *trans,
+ struct pschars *subrs, int round) {
+ BasePoint *bpt;
+ BasePoint temp, rtrans;
+ GlyphInfo *gi;
+ /* The only refs I deal with here have no hint conflicts within them */
+
+ rtrans.x = r->transform[4]+trans->x;
+ rtrans.y = r->transform[5]+trans->y;
+ if ( round ) {
+ rtrans.x = rint(rtrans.x);
+ rtrans.y = rint(rtrans.y);
+ }
+
+ BreakSubroutine(gb,hdb);
+ if ( hdb->cnt>0 && !hdb->noconflicts )
+ DumpRefsHints(gb,hdb,r,sc->hstem,sc->vstem,&rtrans,round);
+
+ /* Translate from end of last character to where this one should */
+ /* start (we must have one moveto operator to start off, none */
+ /* in the subr) */
+ bpt = hdb->gi->psubrs[r->sc->lsidebearing].startstop;
+ temp.x = bpt[0].x+rtrans.x;
+ temp.y = bpt[0].y+rtrans.y;
+ if ( hdb->current.x!=temp.x )
+ AddNumber2(gb,temp.x-hdb->current.x,round);
+ if ( hdb->current.y!=temp.y || hdb->current.x==temp.x )
+ AddNumber2(gb,temp.y-hdb->current.y,round);
+ if ( gb->pt+1>=gb->end )
+ GrowBuffer(gb);
+ *gb->pt++ = hdb->current.x==temp.x?4: /* vmoveto */
+ hdb->current.y==temp.y?22: /* hmoveto */
+ 21; /* rmoveto */
+ if ( r->sc->lsidebearing==0x7fff )
+ IError("Attempt to reference an unreferenceable glyph %s", r->sc->name );
+
+ gi = hdb->gi;
+ StartNextSubroutine(gb,hdb);
+ gi->bits[gi->bcnt].psub_index = r->sc->lsidebearing;
+ ++gi->bcnt;
+ gi->justbroken = true;
+ hdb->current.x = bpt[1].x+rtrans.x;
+ hdb->current.y = bpt[1].y+rtrans.y;
+}
+
+static void RSC2PS2(GrowBuf *gb, SplineChar *base,SplineChar *rsc,
+ struct hintdb *hdb, BasePoint *trans, struct pschars *subrs,
+ int flags ) {
+ BasePoint subtrans;
+ int stationary = trans->x==0 && trans->y==0;
+ RefChar *r, *unsafe=NULL;
+ int unsafecnt=0, allwithouthints=true;
+ int round = (flags&ps_flag_round)? true : false;
+ StemInfo *oldh, *oldv;
+ int hc, vc;
+ SplineSet *freeme, *temp;
+ int wasntconflicted = hdb->noconflicts;
+ oldh = NULL; oldv = NULL; hc = 0; vc = 0; /* for -Wall */
+ if ( flags&ps_flag_nohints ) {
+ oldh = rsc->hstem; oldv = rsc->vstem;
+ hc = rsc->hconflicts; vc = rsc->vconflicts;
+ rsc->hstem = NULL; rsc->vstem = NULL;
+ rsc->hconflicts = false; rsc->vconflicts = false;
+ } else {
+ for ( r=rsc->layers[ly_fore].refs; r!=NULL; r=r->next ) {
+ if ( !r->justtranslated )
+ continue;
+ if ( r->sc->hconflicts || r->sc->vconflicts ) {
+ ++unsafecnt;
+ unsafe = r;
+ } else if ( r->sc->hstem!=NULL || r->sc->vstem!=NULL )
+ allwithouthints = false;
+ }
+ if ( !stationary )
+ allwithouthints = false;
+ if ( allwithouthints && unsafe!=NULL && hdb->cnt!=NumberHints(&unsafe->sc,1))
+ allwithouthints = false; /* There are other hints elsewhere in the base glyph */
+ }
+
+ if ( unsafe && allwithouthints ) {
+ if ( unsafe->sc->lsidebearing!=0x7fff ) {
+ ExpandRef2(gb,base,hdb,unsafe,trans,subrs,round);
+ } else if ( unsafe->transform[4]==0 && unsafe->transform[5]==0 )
+ RSC2PS2(gb,base,unsafe->sc,hdb,trans,subrs,flags);
+ else
+ unsafe = NULL;
+ } else
+ unsafe = NULL;
+
+ /* What is the hintmask state here? It should not matter */
+ freeme = NULL; temp = rsc->layers[ly_fore].splines;
+ if ( base!=rsc )
+ temp = freeme = SPLCopyTranslatedHintMasks(temp,base,rsc,trans);
+ CvtPsSplineSet2(gb,temp,hdb,rsc->parent->order2,round);
+ SplinePointListsFree(freeme);
+
+ for ( r = rsc->layers[ly_fore].refs; r!=NULL; r = r->next ) if ( r!=unsafe ) {
+ if ( !r->justtranslated ) {
+ if ( !r->sc->hconflicts && !r->sc->vconflicts && !hdb->noconflicts &&
+ r->transform[1]==0 && r->transform[2]==0 &&
+ r->transform[0]>0 && r->transform[3]>0 )
+ SetTransformedHintMask(gb,hdb,base,r,trans,round);
+ if ( !hdb->donefirsthm )
+ DummyHintmask(gb,hdb);
+ temp = SPLCopyTransformedHintMasks(r,base,trans);
+ CvtPsSplineSet2(gb,temp,hdb,rsc->parent->order2,round);
+ SplinePointListsFree(temp);
+ } else if ( r->sc->lsidebearing!=0x7fff &&
+ ((flags&ps_flag_nohints) ||
+ (!r->sc->hconflicts && !r->sc->vconflicts)) ) {
+ ExpandRef2(gb,base,hdb,r,trans,subrs,round);
+ } else {
+ subtrans.x = trans->x + r->transform[4];
+ subtrans.y = trans->y + r->transform[5];
+ if ( !hdb->noconflicts && !r->sc->hconflicts && !r->sc->vconflicts) {
+ SetTransformedHintMask(gb,hdb,base,r,trans,round);
+ hdb->noconflicts = true;
+ }
+ RSC2PS2(gb,base,r->sc,hdb,&subtrans,subrs,flags);
+ hdb->noconflicts = wasntconflicted;
+ }
+ }
+
+ if ( flags&ps_flag_nohints ) {
+ rsc->hstem = oldh; rsc->vstem = oldv;
+ rsc->hconflicts = hc; rsc->vconflicts = vc;
+ }
+}
+
+static unsigned char *SplineChar2PS2(SplineChar *sc,int *len, int nomwid,
+ int defwid, struct pschars *subrs, int flags,
+ GlyphInfo *gi) {
+ GrowBuf gb;
+ unsigned char *ret;
+ struct hintdb hdb;
+ StemInfo *oldh, *oldv;
+ int hc, vc;
+ SplineChar *scs[MmMax];
+ int round = (flags&ps_flag_round)? true : false;
+ HintMask *hm = NULL;
+ BasePoint trans;
+ oldh = NULL; oldv = NULL; hc = 0; vc = 0; /* for -Wall */
+ if ( autohint_before_generate && sc->changedsincelasthinted &&
+ !sc->manualhints && !(flags&ps_flag_nohints))
+ SplineCharAutoHint(sc,NULL);
+ if ( !(flags&ps_flag_nohints) && SCNeedsSubsPts(sc,ff_otf))
+ SCFigureHintMasks(sc);
+
+ if ( flags&ps_flag_nohints ) {
+ oldh = sc->hstem; oldv = sc->vstem;
+ hc = sc->hconflicts; vc = sc->vconflicts;
+ sc->hstem = NULL; sc->vstem = NULL;
+ sc->hconflicts = false; sc->vconflicts = false;
+ } else if ( sc->layers[ly_fore].splines!=NULL && !sc->vconflicts &&
+ !sc->hconflicts ) {
+ hm = sc->layers[ly_fore].splines->first->hintmask;
+ sc->layers[ly_fore].splines->first->hintmask = NULL;
+ }
+
+ memset(&gb,'\0',sizeof(gb));
+
+ GrowBuffer(&gb);
+
+ /* store the width on the stack */
+ if ( sc->width==defwid )
+ /* Don't need to do anything for the width */;
+ else
+ AddNumber2(&gb,sc->width-nomwid,round);
+
+ memset(&trans,'\0',sizeof(trans));
+ memset(&hdb,'\0',sizeof(hdb));
+ hdb.scs = scs;
+ hdb.gi = gi;
+ if ( gi!=NULL )
+ gi->bcnt = -1;
+ scs[0] = sc;
+ hdb.noconflicts = !sc->hconflicts && !sc->vconflicts;
+ hdb.cnt = NumberHints(hdb.scs,1);
+ DumpHints(&gb,sc->hstem,sc->hconflicts || sc->vconflicts?18:1,
+ sc->hconflicts || sc->vconflicts?18:1,round);
+ DumpHints(&gb,sc->vstem,sc->hconflicts || sc->vconflicts?-1:3,
+ sc->hconflicts || sc->vconflicts?23:3,round);
+ CounterHints2(&gb, sc, hdb.cnt );
+ RSC2PS2(&gb,sc,sc,&hdb,&trans,subrs,flags);
+
+ if ( gi->bcnt==-1 ) { /* If it's whitespace */
+ gi->bcnt = 0;
+ StartNextSubroutine(&gb,&hdb);
+ }
+ BreakSubroutine(&gb,&hdb);
+ MoveSubrsToChar(gi);
+ ret = NULL;
+
+ free(gb.base);
+ if ( flags&ps_flag_nohints ) {
+ sc->hstem = oldh; sc->vstem = oldv;
+ sc->hconflicts = hc; sc->vconflicts = vc;
+ } else if ( hm!=NULL )
+ sc->layers[ly_fore].splines->first->hintmask = hm;
+return( ret );
+}
+
+static SplinePoint *LineTo(SplinePoint *last, int x, int y) {
+ SplinePoint *sp = SplinePointCreate(x,y);
+ SplineMake3(last,sp);
+return( sp );
+}
+
+static void Type2NotDefSplines(SplineFont *sf,SplineChar *sc) {
+ /* I'd always assumed that Type2 notdefs would look like type1 notdefs */
+ /* but they don't, they look like truetype notdefs. And Ralf Stubner */
+ /* points out that the spec says they should. So make a box here */
+ int stem, ymax;
+ SplineSet *inner, *ss;
+ StemInfo *h, *hints;
+
+ stem = (sf->ascent+sf->descent)/20;
+ ymax = 2*sf->ascent/3;
+
+ ss = chunkalloc(sizeof(SplineSet));
+ ss->first = ss->last = SplinePointCreate(stem,0);
+ ss->last = LineTo(ss->last,stem,ymax);
+ ss->last = LineTo(ss->last,sc->width-stem,ymax);
+ ss->last = LineTo(ss->last,sc->width-stem,0);
+ SplineMake3(ss->last,ss->first);
+ ss->last = ss->first;
+
+ ss->next = inner = chunkalloc(sizeof(SplineSet));
+ inner->first = inner->last = SplinePointCreate(2*stem,stem);
+ inner->last = LineTo(inner->last,sc->width-2*stem,stem);
+ inner->last = LineTo(inner->last,sc->width-2*stem,ymax-stem);
+ inner->last = LineTo(inner->last,2*stem,ymax-stem);
+ SplineMake3(inner->last,inner->first);
+ inner->last = inner->first;
+
+ sc->layers[ly_fore].splines = ss;
+
+ hints = chunkalloc(sizeof(StemInfo));
+ hints->start = stem;
+ hints->width = stem;
+ hints->next = h = chunkalloc(sizeof(StemInfo));
+ h->start = sc->width-2*stem;
+ h->width = stem;
+ sc->vstem = hints;
+
+ hints = chunkalloc(sizeof(StemInfo));
+ hints->start = 0;
+ hints->width = stem;
+ hints->next = h = chunkalloc(sizeof(StemInfo));
+ h->start = ymax-stem;
+ h->width = stem;
+ sc->hstem = hints;
+}
+
+#ifdef FONTFORGE_CONFIG_PS_REFS_GET_SUBRS
+/* This char has hint conflicts. Check to see if we can put it into a subr */
+/* in spite of that. If there is at least one dependent character which: */
+/* refers to us without translating us */
+/* and all its other refs contain no hints at all */
+static int Type2SpecialCase(SplineChar *sc) {
+ struct splinecharlist *d;
+ RefChar *r;
+
+ for ( d=sc->dependents; d!=NULL; d=d->next ) {
+ for ( r=d->sc->layers[ly_fore].refs; r!=NULL; r = r->next ) {
+ if ( autohint_before_generate && r->sc!=NULL &&
+ r->sc->changedsincelasthinted && !r->sc->manualhints )
+ SplineCharAutoHint(r->sc,NULL);
+ if ( r->transform[0]!=1 || r->transform[1]!=0 ||
+ r->transform[2]!=0 || r->transform[3]!=1 )
+ break;
+ if ( r->sc!=sc && (r->sc->hstem!=NULL || r->sc->vstem!=NULL))
+ break;
+ if ( r->sc==sc && (r->transform[4]!=0 || r->transform[5]!=0))
+ break;
+ }
+ if ( r==NULL )
+return( true );
+ }
+return( false );
+}
+#endif /* FONTFORGE_CONFIG_PS_REFS_GET_SUBRS */
+
+/* Mark those glyphs which can live totally in subrs */
+static void SplineFont2FullSubrs2(int flags,GlyphInfo *gi) {
+ int i;
+ SplineChar *sc;
+#ifdef FONTFORGE_CONFIG_PS_REFS_GET_SUBRS
+ int cc;
+ RefChar *r;
+ struct potentialsubrs *ps;
+ SplineSet *spl;
+#endif /* FONTFORGE_CONFIG_PS_REFS_GET_SUBRS */
+
+ if ( !autohint_before_generate && !(flags&ps_flag_nohints))
+ SplineFontAutoHintRefs(gi->sf);
+
+ for ( i=0; i<gi->glyphcnt; ++i ) if ( (sc=gi->gb[i].sc)!=NULL )
+ sc->lsidebearing = 0x7fff;
+
+/* This code allows us to put whole glyphs into subroutines */
+/* I found slight improvements in space on some fonts, and large increases */
+/* in others. So I'm disabling it for now */
+#ifdef FONTFORGE_CONFIG_PS_REFS_GET_SUBRS
+ /* We don't allow refs to refs. It's too complex */
+ for ( i=0; i<gi->glyphcnt; ++i ) if ( (sc=gi->gb[i].sc)!=NULL ) {
+ if ( SCWorthOutputting(sc) &&
+ (( sc->layers[ly_fore].refs==NULL && sc->dependents!=NULL &&
+ ( (!sc->hconflicts && !sc->vconflicts) ||
+ Type2SpecialCase(sc)) ) )) {
+ /* if the glyph is a single contour with no hintmasks then */
+ /* our single contour code will find it. If we do it here too */
+ /* we'll get a subr which points to another subr. Very dull and */
+ /* a waste of space */
+ cc = 0;
+ for ( spl=sc->layers[ly_fore].splines; spl!=NULL; spl=spl->next )
+ ++cc;
+ for ( r= sc->layers[ly_fore].refs; r!=NULL && cc<2 ; r=r->next ) {
+ for ( spl=r->layers[0].splines; spl!=NULL; spl=spl->next )
+ ++cc;
+ }
+ if ( cc<2 )
+ continue;
+ /* Put the */
+ /* character into a subr if it is referenced by other characters */
+ if ( gi->pcnt>=gi->pmax )
+ gi->psubrs = grealloc(gi->psubrs,(gi->pmax+=gi->glyphcnt)*sizeof(struct potentialsubrs));
+ ps = &gi->psubrs[gi->pcnt];
+ memset(ps,0,sizeof(*ps)); /* set cnt to 0 */
+ ps->idx = gi->pcnt++;
+ ps->full_glyph_index = i;
+ sc->lsidebearing = gi->pcnt-1;
+ ps->startstop = FigureStartStop(sc,gi);
+ }
+ }
+#endif /* FONTFORGE_CONFIG_PS_REFS_GET_SUBRS */
+}
+
+struct pschars *SplineFont2ChrsSubrs2(SplineFont *sf, int nomwid, int defwid,
+ const int *bygid, int cnt, int flags, struct pschars **_subrs) {
+ struct pschars *subrs, *chrs;
+ int i,j,k,scnt;
+ SplineChar *sc;
+ GlyphInfo gi;
+ SplineChar dummynotdef;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ Layer dummylayers[2];
+#endif
+
+ if ( !autohint_before_generate && !(flags&ps_flag_nohints))
+ SplineFontAutoHintRefs(sf);
+
+ memset(&gi,0,sizeof(gi));
+ memset(&gi.hashed,-1,sizeof(gi.hashed));
+ gi.instance_count = 1;
+ gi.sf = sf;
+ gi.glyphcnt = cnt;
+ gi.bygid = bygid;
+ gi.gb = gcalloc(cnt,sizeof(struct glyphbits));
+ gi.pmax = 3*cnt;
+ gi.psubrs = galloc(gi.pmax*sizeof(struct potentialsubrs));
+ for ( i=0; i<cnt; ++i ) {
+ int gid = bygid[i];
+ if ( i==0 && gid==-1 ) {
+ sc = &dummynotdef;
+ memset(sc,0,sizeof(dummynotdef));
+ dummynotdef.name = ".notdef";
+ dummynotdef.parent = sf;
+ dummynotdef.layer_cnt = 2;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ dummynotdef.layers = dummylayers;
+ memset(dummylayers,0,sizeof(dummylayers));
+#endif
+ dummynotdef.width = SFOneWidth(sf);
+ if ( dummynotdef.width==-1 )
+ dummynotdef.width = (sf->ascent+sf->descent)/2;
+ Type2NotDefSplines(sf,&dummynotdef);
+ } else if ( gid!=-1 )
+ sc = sf->glyphs[gid];
+ else
+ continue;
+ gi.gb[i].sc = sc;
+ if ( autohint_before_generate && sc!=NULL &&
+ sc->changedsincelasthinted && !sc->manualhints &&
+ !(flags&ps_flag_nohints))
+ SplineCharAutoHint(sc,NULL);
+ sc->lsidebearing = 0x7fff;
+ }
+ MarkTranslationRefs(sf);
+ SplineFont2FullSubrs2(flags,&gi);
+
+ for ( i=0; i<cnt; ++i ) {
+ if ( (sc = gi.gb[i].sc)==NULL )
+ continue;
+ gi.active = &gi.gb[i];
+ SplineChar2PS2(sc,NULL,nomwid,defwid,NULL,flags,&gi);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_next();
+#endif
+ }
+
+ for ( i=scnt=0; i<gi.pcnt; ++i ) {
+ /* A subroutine call takes somewhere between 2 and 4 bytes itself. */
+ /* and we must add a return statement to the end. We don't want to */
+ /* make things bigger */
+ /* if we have more than 65535 subrs a subr call can take 9 bytes */
+ if ( gi.psubrs[i].full_glyph_index!=-1 )
+ gi.psubrs[i].idx = scnt++;
+ else if ( gi.psubrs[i].cnt*gi.psubrs[i].len>(gi.psubrs[i].cnt*4)+gi.psubrs[i].len+1 )
+ gi.psubrs[i].idx = scnt++;
+ else
+ gi.psubrs[i].idx = -1;
+ }
+ subrs = gcalloc(1,sizeof(struct pschars));
+ subrs->cnt = scnt;
+ subrs->next = scnt;
+ subrs->lens = galloc(scnt*sizeof(int));
+ subrs->values = galloc(scnt*sizeof(unsigned char *));
+ subrs->bias = scnt<1240 ? 107 :
+ scnt<33900 ? 1131 : 32768;
+ for ( i=0; i<gi.pcnt; ++i ) {
+ if ( gi.psubrs[i].idx != -1 ) {
+ scnt = gi.psubrs[i].idx;
+ subrs->lens[scnt] = gi.psubrs[i].len+1;
+ subrs->values[scnt] = galloc(subrs->lens[scnt]);
+ memcpy(subrs->values[scnt],gi.psubrs[i].data,gi.psubrs[i].len);
+ subrs->values[scnt][gi.psubrs[i].len] = 11; /* Add a return to end of subr */
+ }
+ }
+
+ chrs = gcalloc(1,sizeof(struct pschars));
+ chrs->cnt = cnt;
+ chrs->next = cnt;
+ chrs->lens = galloc(cnt*sizeof(int));
+ chrs->values = galloc(cnt*sizeof(unsigned char *));
+ chrs->keys = galloc(cnt*sizeof(char *));
+ for ( i=0; i<cnt; ++i ) {
+ int len=0;
+ uint8 *vals;
+ struct glyphbits *gb = &gi.gb[i];
+ if ( gb->sc==NULL )
+ continue;
+ chrs->keys[i] = copy(gb->sc->name);
+ for ( k=0; k<2; ++k ) if ( k!=0 || gb->sc->lsidebearing!=0x7fff ) {
+ for ( j=0; j<gb->bcnt; ++j ) {
+ if ( k!=0 || j!=0 )
+ len += gb->bits[j].dlen;
+ if ( k==1 && gb->sc->lsidebearing!=0x7fff ) {
+ int si = gi.psubrs[ gb->sc->lsidebearing ].idx;
+ len += 1 + (si<=107 && si>=-107?1:si<=1131 && si>=-1131?2:si>=-32768 && si<32767?3:8);
+ break;
+ }
+ if ( gi.psubrs[ gb->bits[j].psub_index ].idx==-1 )
+ len += gi.psubrs[ gb->bits[j].psub_index ].len;
+ else {
+ int si = gi.psubrs[ gb->bits[j].psub_index ].idx - subrs->bias;
+ /* space for the number (subroutine index) */
+ if ( si>=-107 && si<=107 )
+ ++len;
+ else if ( si>=-1131 && si<=1131 )
+ len += 2;
+ else if ( si>=-32768 && si<=32767 )
+ len += 3;
+ else
+ len += 8;
+ /* space for the subroutine operator */
+ ++len;
+ }
+ }
+ if ( k==0 ) {
+ int si = gi.psubrs[ gb->sc->lsidebearing ].idx;
+ subrs->lens[si] = len+1;
+ vals = subrs->values[si] = galloc(len+2);
+ } else {
+ chrs->lens[i] = len+1;
+ vals = chrs->values[i] = galloc(len+2); /* space for endchar and a final NUL (which is really meaningless, but makes me feel better) */
+ }
+
+ len = 0;
+ for ( j=0; j<gb->bcnt; ++j ) {
+ int si;
+ if ( k!=0 || j!=0 ) {
+ memcpy(vals+len,gb->bits[j].data,gb->bits[j].dlen);
+ len += gb->bits[j].dlen;
+ }
+ si = 0x80000000;
+ if ( k==1 && gb->sc->lsidebearing!=0x7fff )
+ si = gi.psubrs[ gb->sc->lsidebearing ].idx - subrs->bias;
+ else if ( gi.psubrs[ gb->bits[j].psub_index ].idx==-1 ) {
+ memcpy(vals+len,gi.psubrs[ gb->bits[j].psub_index ].data,
+ gi.psubrs[ gb->bits[j].psub_index ].len);
+ len += gi.psubrs[ gb->bits[j].psub_index ].len;
+ } else
+ si = gi.psubrs[ gb->bits[j].psub_index ].idx - subrs->bias;
+ if ( si!=0x80000000 ) {
+ /* space for the number (subroutine index) */
+ if ( si>=-107 && si<=107 )
+ vals[len++] = si+139;
+ else if ( si>0 && si<=1131 ) {
+ si-=108;
+ vals[len++] = (si>>8)+247;
+ vals[len++] = si&0xff;
+ } else if ( si>=-1131 && si<0 ) {
+ si=(-si)-108;
+ vals[len++] = (si>>8)+251;
+ vals[len++] = si&0xff;
+ } else if ( si>=-32768 && si<=32767 ) {
+ vals[len++] = 28;
+ vals[len++] = (si>>8)&0xff;
+ vals[len++] = si&0xff;
+ } else {
+ /* store as fixed point, then multiply by 64. Takes 8 bytes */
+ si *= (65536/64);
+ vals[len++] = '\377';
+ vals[len++] = (si>>24)&0xff;
+ vals[len++] = (si>>16)&0xff;
+ vals[len++] = (si>>8)&0xff;
+ vals[len++] = si&0xff;
+ vals[len++] = 64 + 139;
+ vals[len++] = 0xc; vals[len++] = 0x18; /* Multiply */
+ }
+
+ /* space for the subroutine operator */
+ vals[len++] = 10;
+ }
+ if ( k==1 && gb->sc->lsidebearing!=0x7fff )
+ break;
+ }
+ if ( k==0 ) {
+ vals[len++] = 11; /* return */
+ vals[len] = '\0';
+ } else {
+ vals[len++] = 14; /* endchar */
+ vals[len] = '\0';
+ }
+ }
+ }
+
+ GIFree(&gi,&dummynotdef);
+ *_subrs = subrs;
+return( chrs );
+}
+
+struct pschars *CID2ChrsSubrs2(SplineFont *cidmaster,struct fd2data *fds,
+ int flags, struct pschars **_glbls) {
+ struct pschars *chrs, *glbls;
+ int i, j, cnt, cid, max, fd;
+ int *scnts;
+ SplineChar *sc;
+ SplineFont *sf = NULL;
+ /* In a cid-keyed font, cid 0 is defined to be .notdef so there are no */
+ /* special worries. If it is defined we use it. If it is not defined */
+ /* we add it. */
+ GlyphInfo gi;
+ SplineChar dummynotdef;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ Layer dummylayers[2];
+#endif
+
+ max = 0;
+ for ( i=0; i<cidmaster->subfontcnt; ++i ) {
+ if ( max<cidmaster->subfonts[i]->glyphcnt )
+ max = cidmaster->subfonts[i]->glyphcnt;
+ MarkTranslationRefs(cidmaster->subfonts[i]);
+ }
+ cnt = 1; /* for .notdef */
+ for ( cid = 1; cid<max; ++cid ) {
+ for ( i=0; i<cidmaster->subfontcnt; ++i ) {
+ sf = cidmaster->subfonts[i];
+ if ( cid<sf->glyphcnt && (sc=sf->glyphs[cid])!=NULL ) {
+ sc->ttf_glyph = -1;
+ sc->lsidebearing = 0x7fff;
+ if ( SCWorthOutputting(sc))
+ ++cnt;
+ break;
+ }
+ }
+ }
+
+ memset(&gi,0,sizeof(gi));
+ memset(&gi.hashed,-1,sizeof(gi.hashed));
+ gi.instance_count = 1;
+ gi.sf = sf;
+ gi.glyphcnt = cnt;
+ gi.bygid = NULL;
+ gi.gb = gcalloc(cnt,sizeof(struct glyphbits));
+ gi.pmax = 3*cnt;
+ gi.psubrs = galloc(gi.pmax*sizeof(struct potentialsubrs));
+
+ for ( cid = cnt = 0; cid<max; ++cid ) {
+ sf = NULL;
+ for ( i=0; i<cidmaster->subfontcnt; ++i ) {
+ sf = cidmaster->subfonts[i];
+ if ( cid<sf->glyphcnt && SCWorthOutputting(sf->glyphs[cid]) )
+ break;
+ }
+ if ( cid!=0 && i==cidmaster->subfontcnt ) {
+ sc=NULL;
+ } else if ( i==cidmaster->subfontcnt ) {
+ /* They didn't define CID 0 */
+ sc = &dummynotdef;
+ /* Place it in the final subfont (which is what sf points to) */
+ memset(sc,0,sizeof(dummynotdef));
+ dummynotdef.name = ".notdef";
+ dummynotdef.parent = sf;
+ dummynotdef.layer_cnt = 2;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ dummynotdef.layers = dummylayers;
+ memset(dummylayers,0,sizeof(dummylayers));
+#endif
+ dummynotdef.width = SFOneWidth(sf);
+ if ( dummynotdef.width==-1 )
+ dummynotdef.width = (sf->ascent+sf->descent);
+ Type2NotDefSplines(sf,&dummynotdef);
+ gi.gb[cnt].sc = sc;
+ gi.gb[cnt].fd = i = cidmaster->subfontcnt-1;
+#if 0 && HANYANG /* Too much stuff knows the glyph cnt, can't refigure it here at the end */
+ } else if ( sf->glyphs[cid]->compositionunit ) {
+ sc=NULL; /* don't output it, should be in a subroutine */;
+#endif
+ } else {
+ gi.gb[cnt].sc = sc = sf->glyphs[cid];
+ gi.gb[cnt].fd = i;
+ }
+ if ( sc!=NULL ) {
+ sc->lsidebearing = 0x7fff;
+ gi.active = &gi.gb[cnt];
+ sc->ttf_glyph = cnt++;
+ SplineChar2PS2(sc,NULL,fds[i].nomwid,fds[i].defwid,NULL,flags,&gi);
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_next();
+#endif
+ }
+
+ scnts = gcalloc( cidmaster->subfontcnt+1,sizeof(int));
+ for ( i=0; i<gi.pcnt; ++i ) {
+ gi.psubrs[i].idx = -1;
+ if ( gi.psubrs[i].cnt*gi.psubrs[i].len>(gi.psubrs[i].cnt*4)+gi.psubrs[i].len+1 )
+ gi.psubrs[i].idx = scnts[gi.psubrs[i].fd+1]++;
+ }
+
+ glbls = gcalloc(1,sizeof(struct pschars));
+ glbls->cnt = scnts[0];
+ glbls->next = scnts[0];
+ glbls->lens = galloc(scnts[0]*sizeof(int));
+ glbls->values = galloc(scnts[0]*sizeof(unsigned char *));
+ glbls->bias = scnts[0]<1240 ? 107 :
+ scnts[0]<33900 ? 1131 : 32768;
+ for ( fd=0; fd<cidmaster->subfontcnt; ++fd ) {
+ fds[fd].subrs = gcalloc(1,sizeof(struct pschars));
+ fds[fd].subrs->cnt = scnts[fd+1];
+ fds[fd].subrs->next = scnts[fd+1];
+ fds[fd].subrs->lens = galloc(scnts[fd+1]*sizeof(int));
+ fds[fd].subrs->values = galloc(scnts[fd+1]*sizeof(unsigned char *));
+ fds[fd].subrs->bias = scnts[fd+1]<1240 ? 107 :
+ scnts[fd+1]<33900 ? 1131 : 32768;
+ }
+ free( scnts);
+
+ for ( i=0; i<gi.pcnt; ++i ) {
+ if ( gi.psubrs[i].idx != -1 ) {
+ struct pschars *subrs = gi.psubrs[i].fd==-1 ? glbls : fds[gi.psubrs[i].fd].subrs;
+ int scnt = gi.psubrs[i].idx;
+ subrs->lens[scnt] = gi.psubrs[i].len+1;
+ subrs->values[scnt] = galloc(subrs->lens[scnt]);
+ memcpy(subrs->values[scnt],gi.psubrs[i].data,gi.psubrs[i].len);
+ subrs->values[scnt][gi.psubrs[i].len] = 11; /* Add a return to end of subr */
+ }
+ }
+
+
+ chrs = gcalloc(1,sizeof(struct pschars));
+ chrs->cnt = cnt;
+ chrs->next = cnt;
+ chrs->lens = galloc(cnt*sizeof(int));
+ chrs->values = galloc(cnt*sizeof(unsigned char *));
+ chrs->keys = galloc(cnt*sizeof(char *));
+ for ( i=0; i<cnt; ++i ) {
+ int len=0;
+ struct glyphbits *gb = &gi.gb[i];
+ chrs->keys[i] = copy(gb->sc->name);
+ for ( j=0; j<gb->bcnt; ++j ) {
+ len += gb->bits[j].dlen;
+ if ( gi.psubrs[ gb->bits[j].psub_index ].idx==-1 )
+ len += gi.psubrs[ gb->bits[j].psub_index ].len;
+ else {
+ struct pschars *subrs = gi.psubrs[gb->bits[j].psub_index].fd==-1 ? glbls : fds[gi.psubrs[gb->bits[j].psub_index].fd].subrs;
+ int si = gi.psubrs[ gb->bits[j].psub_index ].idx - subrs->bias;
+ /* space for the number (subroutine index) */
+ if ( si>=-107 && si<=107 )
+ ++len;
+ else if ( si>=-1131 && si<=1131 )
+ len += 2;
+ else if ( si>=-32768 && si<=32767 )
+ len += 3;
+ else
+ len += 8;
+ /* space for the subroutine operator */
+ ++len;
+ }
+ }
+ chrs->lens[i] = len+1;
+ chrs->values[i] = galloc(len+2); /* space for endchar and a final NUL (which is really meaningless, but makes me feel better) */
+
+ len = 0;
+ for ( j=0; j<gb->bcnt; ++j ) {
+ memcpy(chrs->values[i]+len,gb->bits[j].data,gb->bits[j].dlen);
+ len += gb->bits[j].dlen;
+ if ( gi.psubrs[ gb->bits[j].psub_index ].idx==-1 ) {
+ memcpy(chrs->values[i]+len,gi.psubrs[ gb->bits[j].psub_index ].data,
+ gi.psubrs[ gb->bits[j].psub_index ].len);
+ len += gi.psubrs[ gb->bits[j].psub_index ].len;
+ } else {
+ struct pschars *subrs = gi.psubrs[gb->bits[j].psub_index].fd==-1 ? glbls : fds[gi.psubrs[gb->bits[j].psub_index].fd].subrs;
+ int si = gi.psubrs[ gb->bits[j].psub_index ].idx - subrs->bias;
+ /* space for the number (subroutine index) */
+ if ( si>=-107 && si<=107 )
+ chrs->values[i][len++] = si+139;
+ else if ( si>0 && si<=1131 ) {
+ si-=108;
+ chrs->values[i][len++] = (si>>8)+247;
+ chrs->values[i][len++] = si&0xff;
+ } else if ( si>=-1131 && si<0 ) {
+ si=(-si)-108;
+ chrs->values[i][len++] = (si>>8)+251;
+ chrs->values[i][len++] = si&0xff;
+ } else if ( si>=-32768 && si<=32767 ) {
+ chrs->values[i][len++] = 28;
+ chrs->values[i][len++] = (si>>8)&0xff;
+ chrs->values[i][len++] = si&0xff;
+ } else {
+ /* store as fixed point, then multiply by 64. Takes 8 bytes */
+ si *= (65536/64);
+ chrs->values[i][len++] = '\377';
+ chrs->values[i][len++] = (si>>24)&0xff;
+ chrs->values[i][len++] = (si>>16)&0xff;
+ chrs->values[i][len++] = (si>>8)&0xff;
+ chrs->values[i][len++] = si&0xff;
+ chrs->values[i][len++] = 64 + 139;
+ chrs->values[i][len++] = 0xc; chrs->values[i][len++] = 0x18; /* Multiply */
+ }
+ /* space for the subroutine operator */
+ if ( gi.psubrs[ gb->bits[j].psub_index ].fd==-1 ) {
+ chrs->values[i][len++] = 29;
+ } else
+ chrs->values[i][len++] = 10;
+ }
+ }
+ chrs->values[i][len++] = 14; /* endchar */
+ chrs->values[i][len] = '\0';
+ }
+ GIFree(&gi,&dummynotdef);
+ *_glbls = glbls;
+return( chrs );
+}
+
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/splinestroke.c b/Build/source/libs/luafontforge/fontforge/fontforge/splinestroke.c
new file mode 100644
index 00000000000..468c50d790a
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/splinestroke.c
@@ -0,0 +1,1987 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include "splinefont.h"
+#include <math.h>
+#if defined(FONTFORGE_CONFIG_GTK)
+#else
+#include <gwidget.h>
+#endif
+
+#define PI 3.1415926535897932
+
+typedef struct joininfo {
+ SplinePoint *from, *to;
+ real tprev;
+ real tnext;
+ BasePoint inter;
+} JointPoint;
+
+
+static real SplineAngle(Spline *spline,real t) {
+ Spline1D *xsp = &spline->splines[0], *ysp = &spline->splines[1];
+ real xslope = (3*xsp->a*t+2*xsp->b)*t + xsp->c;
+ real yslope = (3*ysp->a*t+2*ysp->b)*t + ysp->c;
+
+ if ( xslope==0 && yslope==0 ) {
+ real faket = (t>.5) ? t-.01 : t+.01;
+ xslope = (3*xsp->a*faket+2*xsp->b)*faket + xsp->c;
+ yslope = (3*ysp->a*faket+2*ysp->b)*faket + ysp->c;
+ }
+ if ( spline->knownlinear || ( xslope==0 && yslope==0 )) {
+ xslope = spline->to->me.x-spline->from->me.x;
+ yslope = spline->to->me.y-spline->from->me.y;
+ }
+return( atan2(yslope,xslope) );
+}
+
+static int PenCorner(double lineangle,StrokeInfo *si) {
+
+ if ( ( lineangle>=si->penangle && lineangle<=si->penangle+PI/2 ) ||
+ ( lineangle+2*PI>=si->penangle && lineangle+2*PI<=si->penangle+PI/2 ) ||
+ ( lineangle-2*PI>=si->penangle && lineangle-2*PI<=si->penangle+PI/2 ) ) {
+return( 0 );
+ } else if ( ( lineangle>=si->penangle+PI/2 && lineangle<=si->penangle+PI ) ||
+ ( lineangle+2*PI>=si->penangle+PI/2 && lineangle+2*PI<=si->penangle+PI ) ||
+ ( lineangle-2*PI>=si->penangle+PI/2 && lineangle-2*PI<=si->penangle+PI ) ) {
+return( 1 );
+ } else if ( ( lineangle>=si->penangle+PI && lineangle<=si->penangle+3*PI/2 ) ||
+ ( lineangle+2*PI>=si->penangle+PI && lineangle+2*PI<=si->penangle+3*PI/2 ) ||
+ ( lineangle-2*PI>=si->penangle+PI && lineangle-2*PI<=si->penangle+3*PI/2 ) ) {
+return( 2 );
+ } else {
+return( 3 );
+ }
+}
+
+/* the plus point is where we go when we rotate the line's direction by +90degrees */
+/* and then move radius in that direction. minus is when we rotate -90 and */
+/* then move */ /* counter-clockwise */
+static double SplineExpand(Spline *spline,real t,real toff, StrokeInfo *si,
+ BasePoint *plus, BasePoint *minus) {
+ Spline1D *xsp = &spline->splines[0], *ysp = &spline->splines[1];
+ BasePoint base;
+ double lineangle, c,s, factor = 1.0;
+
+ if ( si->factor!=NULL )
+ factor = (si->factor)(si->data,spline,t);
+
+ base.x = ((xsp->a*t+xsp->b)*t+xsp->c)*t + xsp->d;
+ base.y = ((ysp->a*t+ysp->b)*t+ysp->c)*t + ysp->d;
+
+ lineangle = SplineAngle(spline,t+toff);
+ if ( si->stroke_type != si_caligraphic ) {
+ c = si->radius*factor*cos(lineangle+PI/2);
+ s = si->radius*factor*sin(lineangle+PI/2);
+ plus->y = base.y+s;
+ plus->x = base.x+c;
+ minus->y = base.y-s;
+ minus->x = base.x-c;
+ } else {
+ int corner = PenCorner(lineangle,si);
+ plus->x = base.x + factor*si->xoff[corner];
+ plus->y = base.y + factor*si->yoff[corner];
+ corner += 2;
+ minus->x = base.x + factor*si->xoff[corner];
+ minus->y = base.y + factor*si->yoff[corner];
+ }
+return( lineangle );
+}
+
+static SplinePoint *makequartercircle(real x, real y, real radius,
+ real xmul, real ymul,SplinePoint *prev) {
+ SplinePoint *here = SplinePointCreate(x,y);
+
+ if ( xmul==0 ) {
+ here->nextcp.x = here->prevcp.x = x;
+ here->nextcp.y = y + .552*ymul*radius;
+ here->prevcp.y = y - .552*ymul*radius;
+ } else {
+ here->nextcp.y = here->prevcp.y = y;
+ here->nextcp.x = x + .552*xmul*radius;
+ here->prevcp.x = x - .552*xmul*radius;
+ }
+ here->nonextcp = here->noprevcp = false;
+ if ( prev!=NULL )
+ SplineMake3(prev,here);
+return( here );
+}
+
+static SplinePoint *makeline(SplinePoint *prev, real x, real y) {
+ SplinePoint *here = SplinePointCreate(x,y);
+ here->pointtype = pt_corner;
+ if ( prev!=NULL )
+ SplineMake3(prev,here);
+return( here );
+}
+
+static void SinglePointStroke(SplinePoint *base, StrokeInfo *si, SplinePoint **_plus, SplinePoint **_minus) {
+ SplinePoint *plus, *cur;
+
+ /* A single point, is kind of dull.
+ For a caligraphic pen, it's just a copy of the pen
+ For a linecap of lc_butt it's still a point
+ For a linecap of lc_round it's a circle
+ For a linecap of lc_square it should be a square...
+ but how does one orient that square? probably a circle is best
+ here too
+ */
+ /* We don't have a spline, so don't try guessing factor */
+ if ( si->stroke_type == si_caligraphic ) {
+ plus = SplinePointCreate(base->me.x+si->xoff[0],base->me.y+si->yoff[0]);
+ plus->pointtype = pt_corner;
+ cur = makeline(plus,base->me.x+si->xoff[1],base->me.y+si->yoff[1]);
+ cur = makeline(cur,base->me.x+si->xoff[2],base->me.y+si->yoff[2]);
+ cur = makeline(cur,base->me.x+si->xoff[3],base->me.y+si->yoff[3]);
+ SplineMake3(cur,plus);
+ *_plus = *_minus = plus;
+ } else if ( si->cap!=lc_butt ) {
+ plus = makequartercircle(base->me.x-si->radius,base->me.y,si->radius,0,1,NULL);
+ cur = makequartercircle(base->me.x,base->me.y+si->radius,si->radius,1,0,plus);
+ cur = makequartercircle(base->me.x+si->radius,base->me.y,si->radius,0,-1,cur);
+ cur = makequartercircle(base->me.x,base->me.y-si->radius,si->radius,-1,0,cur);
+ SplineMake3(cur,plus);
+ *_plus = *_minus = plus;
+ } else {
+ *_plus = *_minus = cur = chunkalloc(sizeof(SplinePoint));
+ *cur = *base;
+ cur->next = cur->prev = NULL;
+ cur->hintmask = NULL;
+ }
+}
+
+static SplinePoint *StrokeEnd(SplinePoint *base, StrokeInfo *si, int isstart,
+ SplinePoint **_to) {
+ BasePoint junk;
+ SplinePoint *mid1, *mid2, *cur, *from, *to;
+ real len;
+ real c,s;
+ real angle;
+ real sign;
+ real factor = si->factor==NULL ? 1.0 :
+ base->next!=NULL ? (si->factor)(si->data,base->next,0) :
+ base->prev!=NULL ? (si->factor)(si->data,base->prev,1) :
+ 1.0;
+
+ from = chunkalloc(sizeof(SplinePoint));
+ to = chunkalloc(sizeof(SplinePoint));
+ from->nonextcp = to->nonextcp = from->noprevcp = to->noprevcp = true;
+ from->pointtype = pt_corner; to->pointtype = pt_corner;
+
+ if ( isstart )
+ angle = SplineExpand(base->next,0,0,si,&from->me,&to->me)+ PI;
+ else
+ angle = SplineExpand(base->prev,1,0,si,&to->me,&from->me);
+
+ if ( (len = to->me.x-from->me.x)<0 )
+ len = -len;
+ len += ( to->me.y > from->me.y ) ? (to->me.y - from->me.y) : (from->me.y - to->me.y);
+
+ if ( si->stroke_type == si_caligraphic ) {
+ int corner;
+ corner = PenCorner(angle,si);
+ cur = makeline(from,base->me.x+factor*si->xoff[corner+1],base->me.y+factor*si->yoff[corner+1]);
+ SplineMake3(cur,to);
+ } else {
+ if ( isstart ) {
+ SplineIsLinearMake(base->next);
+ angle = SplineExpand(base->next,0,0,si,&junk,&junk)+ PI;
+ sign = -1;
+ } else {
+ SplineIsLinearMake(base->prev);
+ angle = SplineExpand(base->prev,1,0,si,&junk,&junk);
+ sign = -1;
+ }
+ if ( si->cap==lc_butt ) {
+ SplineMake3(from,to); /* draw a line between */
+ } else if ( si->cap==lc_square ) {
+ mid1 = SplinePointCreate(
+ from->me.x+ sign*(from->me.y-base->me.y),
+ from->me.y- sign*(from->me.x-base->me.x));
+ mid2 = SplinePointCreate(
+ to->me.x+ sign*(from->me.y-base->me.y),
+ to->me.y- sign*(from->me.x-base->me.x));
+ mid1->pointtype = pt_corner; mid2->pointtype = pt_corner;
+ SplineMake3(from,mid1);
+ SplineMake3(mid1,mid2);
+ SplineMake3(mid2,to);
+ } else if ( si->cap==lc_round ) {
+ mid1 = chunkalloc(sizeof(SplinePoint));
+ mid1->me.x = base->me.x+ sign*(from->me.y-base->me.y);
+ mid1->me.y = base->me.y- sign*(from->me.x-base->me.x);
+ mid1->pointtype = pt_curve;
+ c = .552*si->radius*factor*cos(angle);
+ s = .552*si->radius*factor*sin(angle);
+ from->nextcp.x = from->me.x + c;
+ from->nextcp.y = from->me.y + s;
+ from->nonextcp = false;
+ to->prevcp.x = to->me.x +c;
+ to->prevcp.y = to->me.y +s;
+ to->noprevcp = false;
+ mid1->prevcp.x = mid1->me.x - sign*s;
+ mid1->prevcp.y = mid1->me.y + sign*c;
+ mid1->nextcp.x = mid1->me.x + sign*s;
+ mid1->nextcp.y = mid1->me.y - sign*c;
+ SplineMake3(from,mid1);
+ SplineMake3(mid1,to);
+ }
+ }
+ SplinePointCatagorize(to);
+ SplinePointCatagorize(from);
+ *_to = to;
+return( from );
+}
+
+/* Is this the inner intersection or the outer one (the inner one is on both splines) */
+/* the outer one is beyond both */
+static int Intersect_Lines(BasePoint *inter,BasePoint *p1,real sx1, real sy1,
+ BasePoint *p2, real sx2, real sy2, real radius) {
+ real t1/*,t2*/;
+ real denom;
+
+ denom = (sx1*sy2-sx2*sy1);
+ if ( denom>-.0001 && denom<.0001 ) {
+ /* Lines are parallel. Might be coincident, might not */
+ t1 = 10000;
+ } else {
+ /* t2 = (sy1*(p2->x-p1->x)-sx1*(p2->y-p1->y))/denom;*/
+ t1 = (sy2*(p2->x-p1->x)-sx2*(p2->y-p1->y))/denom;
+ }
+ if ( t1>1000 || t1<-1000 ) {
+ denom = sqrt(sx1*sx1 + sy1*sy1)/radius;
+ if ( denom==0 ) {
+ inter->x = (p1->x+p2->x)/2;
+ inter->y = (p1->y+p2->y)/2;
+ } else {
+ inter->x = (p1->x+p2->x)/2 + sx1/denom;
+ inter->y = (p1->y+p2->y)/2 + sy1/denom;
+ }
+return( -1 );
+ } else {
+ inter->x = p1->x + t1*sx1;
+ inter->y = p1->y + t1*sy1;
+return( t1<=0 ); /* if t1 < 0 then the intersection point is actually */
+ /* on both of the spline segments. if it isn't then */
+ /* it will be on the continuation of the spline */
+ /* but beyond its endpoint... */
+ }
+}
+
+static double CircleCpDist(double angle) {
+ /* To draw an arc of length angle on a unit circle, the control points */
+ /* should be this far from their base points. Determined empirically, */
+ /* fit by least squares */
+
+ if ( angle<0 ) angle = -angle;
+ while ( angle>2*PI ) angle -= 2*PI;
+ if ( angle>PI ) angle = 2*PI-angle;
+return( ((0.0115445*angle - 0.0111987)*angle + 0.357114)*angle );
+}
+
+static SplinePoint *ChordMid(double angle,BasePoint *center,BasePoint *from,
+ double *_cpratio) {
+ BasePoint off, new;
+ double s,c,cpratio;
+ SplinePoint *sp;
+
+ if ( angle<0 ) angle = -angle;
+ while ( angle>2*PI ) angle -= 2*PI;
+ if ( angle>PI ) angle = 2*PI-angle;
+ angle /= 2;
+
+ off.x = from->x-center->x;
+ off.y = from->y-center->y;
+ s = sin(angle); c = cos(angle);
+ new.x = c*off.x - s*off.y;
+ new.y = s*off.x + c*off.y;
+ sp = SplinePointCreate(new.x+center->x,new.y+center->y);
+
+ *_cpratio = cpratio = CircleCpDist(angle);
+ new.x *= cpratio; new.y *= cpratio; /* new is a vector of length radius pointing perp to the direction of the cps */
+ /* We need to multiply by cp ratio and rotate 90 degrees */
+ sp->prevcp.x = sp->me.x + new.y;
+ sp->prevcp.y = sp->me.y - new.x;
+ sp->nextcp.x = sp->me.x - new.y;
+ sp->nextcp.y = sp->me.y + new.x;
+ sp->nonextcp = sp->noprevcp = false;
+return( sp );
+}
+
+static void MakeJoints(SplinePoint *from,SplinePoint *to,StrokeInfo *si,
+ BasePoint *inter, BasePoint *center,
+ int incr,double pangle, double nangle, real factor) {
+ SplinePoint *mid;
+ int cstart, cend, i;
+
+ if ( si->stroke_type == si_caligraphic ) {
+ cstart = PenCorner(pangle,si);
+ cend = PenCorner(nangle,si);
+ if ( cstart==cend ) {
+ /* same as a miter join */
+ mid = SplinePointCreate(inter->x,inter->y);
+ mid->pointtype = pt_corner;
+ SplineMake3(from,mid);
+ SplineMake3(mid,to);
+ } else {
+ if ( incr<0 ) {
+ if ((cstart += 2)>=4 ) cstart -= 4;
+ if ((cend += 2)>=4 ) cend -= 4;
+ incr = 1; /* Why??? */
+ }
+ if ( incr>0 && cstart>cend )
+ cend += 4;
+ else if ( incr<0 && cstart<cend )
+ cstart += 4;
+ i = cstart + incr; /* First one is from */
+ mid = from;
+ while ( i!=cend ) {
+ mid = makeline(mid,center->x+factor*si->xoff[i],center->y+factor*si->yoff[i]);
+ i += incr;
+ }
+ SplineMake3(mid,to);
+ }
+ } else if ( si->join==lj_bevel ) {
+ SplineMake3(from,to);
+ } else if ( si->join == lj_miter ) {
+ mid = SplinePointCreate(inter->x,inter->y);
+ mid->pointtype = pt_corner;
+ SplineMake3(from,mid);
+ SplineMake3(mid,to);
+ } else {
+ double cplen = CircleCpDist(nangle-pangle);
+ mid = NULL;
+ if ( cplen>.6 ) {
+ /* If angle of the arc is more than about 90 degrees a cubic */
+ /* spline is noticeably different from a circle's arc */
+ /* So add an extra point to help things out */
+ mid = ChordMid(nangle-pangle,center,&from->me,&cplen);
+ }
+ cplen *= si->radius*factor;
+ from->pointtype = to->pointtype = pt_curve;
+ from->nextcp.x = from->me.x-cplen*cos(nangle);
+ from->nextcp.y = from->me.y-cplen*sin(nangle);
+ to->prevcp.x = to->me.x+cplen*cos(pangle);
+ to->prevcp.y = to->me.y+cplen*sin(pangle);
+ from->nonextcp = false; to->noprevcp = false;
+ if ( mid==NULL )
+ SplineMake3(from,to);
+ else {
+ SplineMake3(from,mid);
+ SplineMake3(mid,to);
+ }
+ }
+}
+
+static int OnEdge(BasePoint *plus,BasePoint *minus,Spline *sp, double t,
+ double heret, Spline *hsp,
+ StrokeInfo *si, double *_ppt, double *_pmt, double *_mpt, double *_mmt) {
+ double rsq = si->radius*si->radius;
+ double tt, xdiff, ydiff, loopdiff;
+ double pptval= -1, pmtval= -1, mptval= -1, mmtval = -1;
+ BasePoint here, test;
+
+ here.x = ((hsp->splines[0].a*heret+hsp->splines[0].b)*heret+hsp->splines[0].c)*heret+hsp->splines[0].d;
+ here.y = ((hsp->splines[1].a*heret+hsp->splines[1].b)*heret+hsp->splines[1].c)*heret+hsp->splines[1].d;
+
+ if ( (xdiff = sp->to->me.x-sp->from->me.x)<0 ) xdiff = -xdiff;
+ if ( (ydiff = sp->to->me.y-sp->from->me.y)<0 ) ydiff = -ydiff;
+ loopdiff = (xdiff+ydiff==0) ? 2 : 1.0/(4*(xdiff+ydiff)/si->radius);
+
+ if ( _ppt!=NULL ) {
+ for ( tt = t+loopdiff; tt<=1 ; tt += loopdiff ) {
+ test.x = ((sp->splines[0].a*tt+sp->splines[0].b)*tt+sp->splines[0].c)*tt+sp->splines[0].d;
+ test.y = ((sp->splines[1].a*tt+sp->splines[1].b)*tt+sp->splines[1].c)*tt+sp->splines[1].d;
+ if ( (test.x-here.x)*(test.x-here.x)+(test.y-here.y)*(test.y-here.y)> 2*rsq )
+ break;
+ if ( (plus->x-test.x)*(plus->x-test.x)+(plus->y-test.y)*(plus->y-test.y)<= rsq )
+ pptval = tt;
+ if ( (minus->x-test.x)*(minus->x-test.x)+(minus->y-test.y)*(minus->y-test.y)<= rsq )
+ pmtval = tt;
+ }
+ *_ppt = pptval; *_pmt = pmtval;
+ }
+
+ if ( _mmt!=NULL ) {
+ for ( tt = t-loopdiff; tt>=0 ; tt -= loopdiff ) {
+ test.x = ((sp->splines[0].a*tt+sp->splines[0].b)*tt+sp->splines[0].c)*tt+sp->splines[0].d;
+ test.y = ((sp->splines[1].a*tt+sp->splines[1].b)*tt+sp->splines[1].c)*tt+sp->splines[1].d;
+ if ( (test.x-here.x)*(test.x-here.x)+(test.y-here.y)*(test.y-here.y)> 2*rsq )
+ break;
+ if ( (plus->x-test.x)*(plus->x-test.x)+(plus->y-test.y)*(plus->y-test.y)< rsq )
+ mptval = tt;
+ if ( (minus->x-test.x)*(minus->x-test.x)+(minus->y-test.y)*(minus->y-test.y)< rsq )
+ mmtval = tt;
+ }
+ *_mmt = mmtval; *_mpt = mptval;
+ }
+
+return( pptval!=-1 || mmtval!=-1 || pmtval!=-1 || mptval==-1 );
+}
+
+#define BasePtDistance(pt1, pt2) sqrt(((pt1)->x-(pt2)->x)*((pt1)->x-(pt2)->x) + ((pt1)->y-(pt2)->y)*((pt1)->y-(pt2)->y))
+
+#if 0
+static int PointToSplineLessThan(BasePoint *test,Spline *against,real radius) {
+ BasePoint here;
+ double t;
+ double xdiff,ydiff, delta;
+
+ if ( BasePtDistance(test,&against->from->me)<=radius+.01 )
+return( true );
+ if ( BasePtDistance(test,&against->to->me)<=radius+.01 )
+return( true );
+ if ( (xdiff = against->from->me.x-against->to->me.x)<0 ) xdiff = -xdiff;
+ if ( (ydiff = against->from->me.y-against->to->me.y)<0 ) ydiff = -ydiff;
+ delta = radius/(2*(xdiff+ydiff));
+ if ( delta<.0625 ) delta = .0625;
+ for ( t=delta; t<.99999 ; t+=delta ) {
+ here.x = ((against->splines[0].a*t+against->splines[0].b)*t+against->splines[0].c)*t+against->splines[0].d;
+ here.y = ((against->splines[1].a*t+against->splines[1].b)*t+against->splines[1].c)*t+against->splines[1].d;
+ if ( BasePtDistance(test,&here)<=radius )
+return( true );
+ }
+return( false );
+}
+
+static int EntirelyWithin(SplinePoint *start,Spline *s,int dir,real radius) {
+ /* Return whether every point along the splines starting at start is */
+ /* within radius of some point along the spline s */
+ Spline *test = dir ? start->next : start->prev;
+ BasePoint here;
+ double t;
+
+ while ( test!=NULL ) {
+ if ( !PointToSplineLessThan(&test->from->me,s,radius) ||
+ !PointToSplineLessThan(&test->to->me,s,radius))
+return( false );
+ for ( t=.125; t<.99999 ; t+=.125 ) {
+ here.x = ((test->splines[0].a*t+test->splines[0].b)*t+test->splines[0].c)*t+test->splines[0].d;
+ here.y = ((test->splines[1].a*t+test->splines[1].b)*t+test->splines[1].c)*t+test->splines[1].d;
+ if ( !PointToSplineLessThan(&test->to->me,s,radius))
+return( false );
+ }
+ if ( dir ) test = test->to->next;
+ else test = test->from->prev;
+ }
+return( true );
+}
+#endif
+
+static SplinePoint *MergeSplinePoint(SplinePoint *sp1,SplinePoint *sp2) {
+ /* sp1 and sp2 should be close together, use their average for the */
+ /* new position, get rid of one, and add its spline to the other */
+ /* sp1->next==NULL, sp2->prev==NULL */
+ double offx, offy;
+
+ offx = (sp1->me.x-sp2->me.x)/2;
+ offy = (sp1->me.y-sp2->me.y)/2;
+ sp1->me.x -= offx; sp1->prevcp.x -= offx;
+ sp1->me.y -= offy; sp1->prevcp.y -= offy;
+ sp1->nextcp.x = sp2->nextcp.x + offx;
+ sp1->nextcp.y = sp2->nextcp.y + offy;
+ sp1->nonextcp = sp2->nonextcp;
+ sp1->next = sp2->next;
+ SplinePointFree(sp2);
+ if ( sp1->next!=NULL )
+ sp1->next->from = sp1;
+ SplinePointCatagorize(sp1);
+ if ( sp1->prev!=NULL )
+ SplineRefigure(sp1->prev);
+ if ( sp1->next!=NULL )
+ SplineRefigure(sp1->next);
+return( sp1 );
+}
+
+static void MSP(SplinePoint *sp1,SplinePoint **sp2, SplinePoint **sp2alt) {
+ int same2 = *sp2==*sp2alt;
+
+ *sp2 = MergeSplinePoint(sp1,*sp2);
+ if ( same2 )
+ *sp2alt = *sp2;
+}
+
+static SplinePoint *SplineMaybeBisect(Spline *s,double t) {
+ /* Things get very confused if I have a splineset with just a single point */
+ SplinePoint *temp, *sp;
+
+ if ( t<.0001 ) {
+ temp = chunkalloc(sizeof(SplinePoint));
+ sp = s->from;
+ *temp = *sp;
+ temp->hintmask = NULL;
+ temp->next->from = temp;
+ sp->next = NULL;
+ sp->nextcp = sp->me;
+ sp->nonextcp = true;
+ temp->prevcp = temp->me;
+ temp->noprevcp = true;
+ SplineMake3(sp,temp);
+return( temp );
+ } else if ( t>.9999 ) {
+ temp = chunkalloc(sizeof(SplinePoint));
+ sp = s->to;
+ *temp = *sp;
+ temp->hintmask = NULL;
+ temp->prev->to = temp;
+ sp->prev = NULL;
+ sp->prevcp = sp->me;
+ sp->noprevcp = true;
+ temp->nextcp = temp->me;
+ temp->nonextcp = true;
+ SplineMake3(temp,sp);
+return( temp );
+ }
+
+return( SplineBisect(s,t));
+}
+
+static void SplineFreeBetween(SplinePoint *from,SplinePoint *to,int freefrom,int freeto) {
+ Spline *s;
+
+ if ( from==to ) {
+ if ( freefrom && freeto )
+ SplinePointFree(from);
+return;
+ }
+
+ while ( from!=to && from!=NULL ) {
+ s = from->next;
+ if ( freefrom )
+ SplinePointFree(from);
+ else
+ from->next = NULL;
+ if ( s==NULL )
+return;
+ freefrom = true;
+ from = s->to;
+ SplineFree(s);
+ }
+ if ( freeto )
+ SplinePointFree(to);
+ else
+ to->prev = NULL;
+}
+
+static void SplineFreeForeward(SplinePoint *from) {
+ Spline *s;
+
+ while ( from!=NULL ) {
+ s = from->next;
+ SplinePointFree(from);
+ if ( s==NULL )
+return;
+ from = s->to;
+ SplineFree(s);
+ }
+}
+
+static void SplineFreeBackward(SplinePoint *to) {
+ Spline *s;
+
+ while ( to!=NULL ) {
+ s = to->prev;
+ SplinePointFree(to);
+ if ( s==NULL )
+return;
+ to = s->from;
+ SplineFree(s);
+ }
+}
+
+static SplinePoint *SplineCopyAfter(SplinePoint *from,SplinePoint **end) {
+ SplinePoint *head, *last;
+
+ last = head = chunkalloc(sizeof(SplinePoint));
+ *head = *from;
+ head->hintmask = NULL;
+ head->prev = NULL;
+ while ( from->next!=NULL ) {
+ last->next = chunkalloc(sizeof(Spline));
+ *last->next = *from->next;
+ last->next->from = last;
+ last->next->to = chunkalloc(sizeof(SplinePoint));
+ *last->next->to = *from->next->to;
+ last->next->to->hintmask = NULL;
+ last->next->to->prev = last->next;
+ last = last->next->to;
+ from = from->next->to;
+ }
+ *end = last;
+return( head );
+}
+
+static SplinePoint *SplineCopyBefore(SplinePoint *to,SplinePoint **end) {
+ SplinePoint *head, *last;
+
+ last = head = chunkalloc(sizeof(SplinePoint));
+ *head = *to;
+ head->hintmask = NULL;
+ head->next = NULL;
+ while ( to->prev!=NULL ) {
+ last->prev = chunkalloc(sizeof(Spline));
+ *last->prev = *to->prev;
+ last->prev->to = last;
+ last->prev->from = chunkalloc(sizeof(SplinePoint));
+ *last->prev->from = *to->prev->from;
+ last->prev->from->hintmask = NULL;
+ last->prev->from->next = last->prev;
+ last = last->prev->from;
+ to = to->prev->from;
+ }
+ *end = last;
+return( head );
+}
+
+static SplinePoint *Intersect_Splines(SplinePoint *from,SplinePoint *to,
+ SplinePoint **ret) {
+ Spline *test1, *test2;
+ BasePoint pts[9];
+ extended t1s[9], t2s[9];
+
+ for ( test1=from->next; test1!=NULL; test1=test1->to->next ) {
+ for ( test2=to->prev; test2!=NULL; test2=test2->from->prev ) {
+ if ( SplinesIntersect(test1,test2,pts,t1s,t2s)>0 ) {
+ *ret = SplineMaybeBisect(test2,t2s[0]);
+return( SplineMaybeBisect(test1,t1s[0]));
+ }
+ }
+ }
+ *ret = NULL;
+return( NULL );
+}
+
+struct strokedspline {
+ Spline *s;
+ SplinePoint *plusfrom, *plusto, *origplusfrom;
+ SplinePoint *minusfrom, *minusto, *origminusto;
+ int8 plusskip, minusskip; /* If this spline is so small that it is totally within the region stroked by an adjacent spline */
+ int8 pinnerto, minnerto; /* to and from as defined on original spline s */
+ BasePoint minterto, pinterto;
+ double nangle, pangle;
+ struct strokedspline *next, *prev;
+};
+
+static void StrokeEndComplete(struct strokedspline *cur,StrokeInfo *si,int isstart) {
+ SplinePoint *edgestart, *edgeend, *curat, *edgeat;
+ struct strokedspline *lastp, *lastm;
+
+ if ( isstart ) {
+ edgestart = StrokeEnd(cur->s->from,si,true,&edgeend);
+ for ( lastp=cur; lastp!=NULL && lastp->plusskip ; lastp=lastp->next );
+ for ( lastm=cur; lastm!=NULL && lastm->minusskip ; lastm=lastm->next );
+ if ( lastm==cur )
+ MSP(edgeend,&cur->minusfrom,&cur->minusto);
+ else {
+ curat = Intersect_Splines(lastm->minusfrom,edgeend,&edgeat);
+ if ( curat!=NULL ) {
+ SplineFreeBetween(lastm->minusfrom,curat,true,false);
+ SplineFreeBetween(edgeat,edgeend,false,true);
+ } else
+ MSP(edgeend,&lastm->minusfrom,&lastm->minusto);
+ }
+ if ( lastp==cur )
+ MergeSplinePoint(cur->plusto,edgestart);
+ else {
+ edgeat = Intersect_Splines(edgestart,lastp->plusto,&curat);
+ if ( curat!=NULL ) {
+ SplineFreeBetween(curat,lastp->plusto,false,true);
+ SplineFreeBetween(edgestart,edgeat,true,false);
+ } else
+ MergeSplinePoint(lastp->plusto,edgestart);
+ }
+ } else {
+ edgestart = StrokeEnd(cur->s->to,si,false,&edgeend);
+ for ( lastp=cur; lastp!=NULL && lastp->plusskip ; lastp=lastp->prev );
+ for ( lastm=cur; lastm!=NULL && lastm->minusskip ; lastm=lastm->prev );
+ if ( lastp==cur )
+ MSP(edgeend,&cur->plusfrom,&cur->plusto);
+ else {
+ curat = Intersect_Splines(lastp->plusfrom,edgeend,&edgeat);
+ if ( curat!=NULL ) {
+ SplineFreeBetween(lastp->plusfrom,curat,true,false);
+ lastp->plusfrom = curat;
+ SplineFreeBetween(edgeat,edgeend,false,true);
+ lastp->plusfrom = MergeSplinePoint(edgeat,curat);
+ } else
+ MSP(edgeend,&lastp->plusfrom,&lastp->plusto);
+ }
+ if ( lastm==cur )
+ MergeSplinePoint(cur->minusto,edgestart);
+ else {
+ edgeat = Intersect_Splines(edgestart,lastm->minusto,&curat);
+ if ( curat!=NULL ) {
+ SplineFreeBetween(curat,lastm->minusto,false,true);
+ lastm->minusto = curat;
+ SplineFreeBetween(edgestart,edgeat,true,false);
+ MergeSplinePoint(lastm->minusto,edgeat);
+ } else
+ MergeSplinePoint(lastm->minusto,edgestart);
+ }
+ }
+}
+
+static void StrokedSplineFree(struct strokedspline *head) {
+ struct strokedspline *next, *cur=head;
+
+ while ( cur!=NULL ) {
+ next = cur->next;
+ chunkfree(cur,sizeof(*cur));
+ cur = next;
+ if ( cur==head )
+ break;
+ }
+}
+
+static void FreeOrigStuff(struct strokedspline *before) {
+
+ if ( before->origminusto!=NULL )
+ SplineFreeBackward(before->origminusto);
+ before->origminusto = NULL;
+ if ( before->origplusfrom!=NULL )
+ SplineFreeForeward(before->origplusfrom);
+ before->origplusfrom = NULL;
+}
+
+static void SplineMakeRound(SplinePoint *from,SplinePoint *to, real radius) {
+ /* I believe this only gets called when we have a line join where the */
+ /* contour makes a U-Turn (opposite of being colinear) */
+ BasePoint dir;
+ SplinePoint *center;
+
+ dir.x = (to->me.y-from->me.y)/2;
+ dir.y = -(to->me.x-from->me.x)/2;
+ center = SplinePointCreate((to->me.x+from->me.x)/2+dir.x,
+ (to->me.y+from->me.y)/2+dir.y);
+ from->nextcp.x = from->me.x + .552*dir.x;
+ from->nextcp.y = from->me.y + .552*dir.y;
+ to->prevcp.x = to->me.x + .552*dir.x;
+ to->prevcp.y = to->me.y + .552*dir.y;
+ from->nonextcp = to->noprevcp = false;
+ center->prevcp.x = center->me.x + .552*dir.y;
+ center->nextcp.x = center->me.x - .552*dir.y;
+ center->prevcp.y = center->me.y - .552*dir.x;
+ center->nextcp.y = center->me.y + .552*dir.x;
+ center->nonextcp = center->noprevcp = false;
+ SplineMake3(from,center);
+ SplineMake3(center,to);
+}
+
+static int DoIntersect_Splines(struct strokedspline *before,
+ struct strokedspline *after, int doplus,StrokeInfo *si,SplineChar *sc,
+ int force_connect ) {
+ SplinePoint *beforeat, *afterat;
+ int ret = true;
+ int toobig = false;
+
+ if ( doplus ) {
+ beforeat = Intersect_Splines(before->plusfrom,after->plusto,&afterat);
+ if ( beforeat!=NULL ) {
+ after->origplusfrom = after->plusfrom;
+ after->plusto = SplineCopyBefore(afterat,&after->plusfrom);
+ SplineFreeBetween(before->plusfrom,beforeat,true/*free before->plusfrom*/,false/* keep beforeat */);
+ before->plusfrom = beforeat;
+ } else if ( before->origplusfrom!=NULL &&
+ (beforeat = Intersect_Splines(before->origplusfrom,after->plusto,&afterat))!=NULL ) {
+ toobig = true;
+ after->origplusfrom = after->plusfrom;
+ after->plusto = SplineCopyBefore(afterat,&after->plusfrom);
+ SplineFreeBetween(before->plusfrom,before->plusto,true/*free plusfrom*/,false);
+ before->plusfrom = SplinePointCreate(afterat->me.x,afterat->me.y);
+ before->plusfrom->nextcp = before->plusfrom->me;
+ before->plusfrom->nonextcp = true;
+ SplineMake3(before->plusfrom,before->plusto); /* This line goes backwards */
+#if 0 /* This introduces lots of bugs, it gets invoked when it */
+ /* shouldn't, and I can't figure out how to distinguish */
+ } else if ( EntirelyWithin(before->plusfrom,after->s,true,si->radius) ) {
+ /* the splines at before are all within radius units of the original */
+ /* after spline. This means that they will make no contribution */
+ /* to the outline. */
+ if ( before->prev!=NULL && before->prev!=after )
+ ret = DoIntersect_Splines(before->prev,after,doplus,si,sc);
+ before->plusskip = true;
+ toobig = ret;
+ } else if ( EntirelyWithin(after->plusto,before->s,false,si->radius) ) {
+ /* the splines at after are entirely within radius units of the original */
+ if ( after->next!=NULL && after->next!=before )
+ ret = DoIntersect_Splines(before,after->next,doplus,si,sc);
+ after->plusskip = true;
+ toobig = ret;
+#endif
+ } else {
+ /* No intersection everything can stay as it is */
+ if ( force_connect && BasePtDistance(&after->plusto->me,&before->plusfrom->me)>3 ) {
+ beforeat = SplinePointCreate(after->plusto->me.x,after->plusto->me.y);
+ if ( si->join==lj_round )
+ SplineMakeRound(beforeat,before->plusfrom,si->radius);
+ else
+ SplineMake3(beforeat,before->plusfrom);
+ before->plusfrom = beforeat;
+ toobig = true;
+ }
+ ret = false;
+ }
+ } else {
+ afterat = Intersect_Splines(after->minusfrom,before->minusto,&beforeat);
+ if ( afterat!=NULL ) {
+ after->origminusto = after->minusto;
+ after->minusfrom = SplineCopyAfter(afterat,&after->minusto);
+ SplineFreeBetween(beforeat,before->minusto,false/*keep beforeat*/,true);
+ before->minusto = beforeat;
+ } else if ( before->origminusto!=NULL &&
+ (afterat = Intersect_Splines(after->minusfrom,before->origminusto,&beforeat))!=NULL ) {
+ toobig = true;
+ after->origminusto = after->minusto;
+ after->minusfrom = SplineCopyAfter(afterat,&after->minusto);
+ SplineFreeBetween(before->minusfrom,before->minusto,false/*keep minusfrom*/,true);
+ before->minusto = SplinePointCreate(afterat->me.x,afterat->me.y);
+ before->minusfrom->nextcp = before->minusfrom->me;
+ before->minusfrom->nonextcp = true;
+ SplineMake3(before->minusfrom,before->minusto); /* This line goes backwards */
+#if 0 /* This introduces lots of bugs, it gets invoked when it */
+ /* shouldn't, and I can't figure out how to distinguish */
+ } else if ( EntirelyWithin(before->minusto,after->s,false,si->radius) ) {
+ /* the splines at before are all within radius units of the original */
+ /* after spline. This means that they will make no contribution */
+ /* to the outline. */
+ ret = false;
+ if ( before->prev!=NULL && before->prev!=after && before->prev!=after->next )
+ ret = DoIntersect_Splines(before->prev,after,doplus,si,sc);
+ before->minusskip = true;
+ toobig = ret;
+ } else if ( EntirelyWithin(after->minusfrom,before->s,true,si->radius) ) {
+ /* the splines at after are entirely within radius units of the original */
+ ret = false;
+ if ( after->next!=NULL && after->next!=before && before->prev!=after->next )
+ ret = DoIntersect_Splines(before,after->next,doplus,si,sc);
+ after->minusskip = true;
+ toobig = ret;
+#endif
+ } else {
+ /* No intersection everything can stay as it is */
+ if ( force_connect && BasePtDistance(&after->minusfrom->me,&before->minusto->me)>3 ) {
+ beforeat = SplinePointCreate(after->minusfrom->me.x,after->minusfrom->me.y);
+ if ( si->join==lj_round )
+ SplineMakeRound(before->minusto,beforeat,si->radius);
+ else
+ SplineMake3(before->minusto,beforeat);
+ before->minusto = beforeat;
+ toobig = true;
+ }
+ ret = false;
+ }
+ }
+
+ if ( toobig ) {
+ si->gottoobig = si->gottoobiglocal = true;
+ if ( !si->toobigwarn ) {
+ si->toobigwarn = true;
+ gwwv_post_error( _("Bad Stroke"), _("The stroke width is so big that the generated path\nmay intersect itself in %.100s"),
+ sc==NULL?"<nameless char>": sc->name );
+ }
+ }
+return( ret );
+}
+
+/* Plus joins run from prev to next, minus joins run from next to prev */
+/* This makes plus joins clockwise and minus joins counter */
+static void StrokeJoint(SplinePoint *base,StrokeInfo *si,
+ struct strokedspline *before,struct strokedspline *after,
+ SplineChar *sc) {
+ BasePoint nplus, nminus, pplus,pminus;
+ double nangle, pangle;
+ int pinner, minner;
+#if 0
+ double pt, mt;
+ double tt, xdiff, ydiff;
+#endif
+
+ before->pangle = pangle = SplineExpand(base->prev,1,0,si,&pplus,&pminus);
+ before->nangle = nangle = SplineExpand(base->next,0,0,si,&nplus,&nminus);
+
+ if ( RealWithin(pangle,nangle,.1) || RealWithin(pangle+2*PI,nangle,.1) ||
+ RealWithin(pangle,nangle+2*PI,.1)) {
+ /* If the two splines are tangent at the base, then everything is */
+ /* simple, there is no join, things match up perfectly */
+ /* Um. No. If there is a sharp bend or a corner nearby then it may */
+ /* have the same effect as a corner, in extreme cases the entire */
+ /* spline may be eaten up */
+ /* Actually, that's probably done best in Remove Overlap. If we try */
+ /* to do it here, we unlease lots of potentials for bugs in other */
+ /* cases */
+
+#if 0
+ if ( (xdiff = base->me.x-base->prev->from->me.x)<0 ) xdiff = -xdiff;
+ if ( (ydiff = base->me.y-base->prev->from->me.y)<0 ) ydiff = -ydiff;
+ if ( xdiff+ydiff==0 ) xdiff = 1;
+ tt = si->radius/(2*(xdiff+ydiff));
+ if ( tt>.2 ) tt = .2;
+ OnEdge(&pplus,&pminus,base->next,0,1.0-tt,base->prev,
+ si,&pt,&mt,NULL,NULL);
+ if ( pt!=-1 )
+ DoIntersect_Splines(before,after,true,si,sc,true);
+ else {
+ if ( (xdiff = base->me.x-base->next->to->me.x)<0 ) xdiff = -xdiff;
+ if ( (ydiff = base->me.y-base->next->to->me.y)<0 ) ydiff = -ydiff;
+ tt = si->radius/(2*(xdiff+ydiff));
+ if ( tt>.2 ) tt = .2;
+ OnEdge(&nplus,&nminus,base->prev,1.,tt,base->next,
+ si,NULL,NULL,&pt,&mt);
+ if ( mt!=-1 )
+ DoIntersect_Splines(before,after,false,si,sc,true);
+ }
+#endif
+ before->pinnerto = before->minnerto = -1;
+ } else {
+ pinner = Intersect_Lines(&before->pinterto,&pplus,
+ 3*base->prev->splines[0].a+2*base->prev->splines[0].b+base->prev->splines[0].c,
+ 3*base->prev->splines[1].a+2*base->prev->splines[1].b+base->prev->splines[1].c,
+ &nplus,
+ base->next->splines[0].c,
+ base->next->splines[1].c,si->radius);
+ minner = Intersect_Lines(&before->minterto,&pminus,
+ 3*base->prev->splines[0].a+2*base->prev->splines[0].b+base->prev->splines[0].c,
+ 3*base->prev->splines[1].a+2*base->prev->splines[1].b+base->prev->splines[1].c,
+ &nminus,
+ base->next->splines[0].c,
+ base->next->splines[1].c,si->radius);
+ if ( pinner==-1 && minner!=-1 )
+ pinner = !minner;
+ before->pinnerto = pinner; before->minnerto = (pinner!=-1?!pinner:-1);
+ if ( pinner==1 ) {
+ DoIntersect_Splines(before,after,true,si,sc,true);
+ } else if ( pinner==0 ) {
+ DoIntersect_Splines(before,after,false,si,sc,true);
+ } else { /* splines are parallel, but moving in same dir */
+ if ( DoIntersect_Splines(before,after,true,si,sc,false)) {
+ before->pinnerto = 1;
+ before->minnerto = 0;
+ } else {
+ if ( DoIntersect_Splines(before,after,false,si,sc,true)) {
+ before->pinnerto = 0;
+ before->minnerto = 1;
+ } else
+ DoIntersect_Splines(before,after,true,si,sc,true);
+ }
+ }
+ }
+}
+
+static int SplineSolveForPen(Spline *s,StrokeInfo *si,double *ts,int *pinners,
+ double tstart,double tend) {
+ /* Find all the places at which the spline has the same slope as one of the */
+ /* edges of the pen. There can be at most 8 (we get four quadratics) */
+ double a, b, c, sq, t1, t2;
+ int i, cnt=0, j;
+ Spline1D *xsp = &s->splines[0], *ysp = &s->splines[1];
+ BasePoint pp, pm, np, nm, testp, testm;
+
+ a =0;b =0;c =0;
+ ts[cnt++] = tstart;
+ for ( i=0; i<2; ++i ) {
+ if ( i==0 ) {
+ a = 3*(ysp->a*si->c-xsp->a*si->s);
+ b = 2*(ysp->b*si->c-xsp->b*si->s);
+ c = ysp->c*si->c-xsp->c*si->s;
+ } else if ( i==1 ) {
+ a = 3*(-ysp->a*si->c-xsp->a*si->s);
+ b = 2*(-ysp->b*si->c-xsp->b*si->s);
+ c = -ysp->c*si->c-xsp->c*si->s;
+#if 0 /* These two are just the negatives of the first two and as such have the same roots */
+ } else if ( i==2 ) {
+ a = 3*(-ysp->a*si->c+xsp->a*si->s);
+ b = 2*(-ysp->b*si->c+xsp->b*si->s);
+ c = -ysp->c*si->c+xsp->c*si->s;
+ } else {
+ a = 3*(ysp->a*si->c+xsp->a*si->s);
+ b = 2*(ysp->b*si->c+xsp->b*si->s);
+ c = ysp->c*si->c+xsp->c*si->s;
+#endif
+ }
+ sq = b*b-4*a*c;
+ if ( sq==0 ) {
+ t1 = -b/(2*a);
+ t2 = -1;
+ } else if ( sq>0 ) {
+ sq = sqrt(sq);
+ t1 = (-b+sq)/(2*a);
+ t2 = (-b-sq)/(2*a);
+ } else
+ t1 = t2 = -1;
+ if ( t1>tstart && t1<tend )
+ ts[cnt++] = t1;
+ if ( t2>tstart && t2<tend )
+ ts[cnt++] = t2;
+ }
+ ts[cnt++] = tend;
+ if ( cnt<=2 )
+return(cnt);
+ /* Order them */
+ for ( i=1; i<cnt-1; ++i ) for ( j=i+1; j<cnt; ++j )
+ if ( ts[i]>ts[j] ) {
+ double temp = ts[i];
+ ts[i] = ts[j];
+ ts[j] = temp;
+ }
+ /* Figure which side is inner */
+ for ( i=1; i<cnt-1; ++i ) {
+ SplineExpand(s,ts[i],-(ts[i]-ts[i-1])/20.,si,&pp,&pm);
+ SplineExpand(s,ts[i],(ts[i+1]-ts[i])/20.,si,&np,&nm);
+ SplineExpand(s,ts[i]+(ts[i+1]-ts[i])/20.,0,si,&testp,&testm);
+ pinners[i] = ( (testp.x-np.x)*(pp.x-np.x)+(testp.y-np.y)*(pp.y-np.y)> 0 );
+ }
+return( cnt );
+}
+
+#if 0
+static void SplineSetFixRidiculous(SplineSet *ss) {
+ /* Make sure we don't have any splines with ridiculous control points */
+ /* No control point, when projected onto the vector between the two */
+ /* end points should be far beyond either of the end points... */
+ Spline *s, *first;
+ double vx, vy, test, end;
+ int unreasonable;
+
+ first = NULL;
+ for ( s=ss->first->next; s!=NULL && s!=first; s = s->to->next ) {
+ if ( first==NULL ) first = s;
+ vx = s->to->me.x-s->from->me.x; vy = s->to->me.y-s->from->me.y;
+ end = vx*vx + vy*vy;
+ unreasonable = false;
+ test = vx*(s->from->nextcp.x-s->from->me.x) +
+ vy*(s->from->nextcp.y-s->from->me.y);
+ if ( test<-2*end || test>2*end ) {
+ s->from->nextcp = s->from->me;
+ s->from->nonextcp = true;
+ unreasonable = true;
+ }
+ test = vx*(s->to->prevcp.x-s->from->me.x) +
+ vy*(s->to->prevcp.y-s->from->me.y);
+ if ( test<-2*end || test>2*end ) {
+ s->to->prevcp = s->to->me;
+ s->to->noprevcp = true;
+ unreasonable = true;
+ }
+ if ( unreasonable )
+ SplineRefigure(s);
+ }
+}
+#endif
+
+static void SplineSetFixCPs(SplineSet *ss) {
+ SplinePoint *sp;
+
+ for ( sp=ss->first; ; ) {
+ SPWeightedAverageCps(sp);
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ SPLCatagorizePoints(ss);
+}
+
+static SplineSet *SSFixupOverlap(StrokeInfo *si,SplineChar *sc,
+ SplineSet *ssplus,SplineSet *ssminus, int reversed) {
+ ssplus->next = ssminus;
+ ssplus = SplineSetRemoveOverlap(sc,ssplus,over_remove);
+ if ( si->removeinternal || si->removeexternal ) {
+ SplineSet *prev, *spl, *next;
+ prev = NULL;
+ for ( spl=ssplus; spl!=NULL; spl = next ) {
+ int clock = SplinePointListIsClockwise(spl) ^ reversed;
+ next = spl->next;
+ if (( !clock && si->removeinternal ) || ( clock && si->removeexternal )) {
+ SplinePointListFree(spl);
+ if ( prev==NULL )
+ ssplus = next;
+ else
+ prev->next = next;
+ } else
+ prev = spl;
+ }
+ }
+return( ssplus );
+}
+
+static SplinePoint *SPNew(SplinePoint *base,BasePoint *pos,BasePoint *cp,int isnext) {
+ SplinePoint *sp = SplinePointCreate(pos->x,pos->y);
+
+ sp->pointtype = base->pointtype;
+ if ( isnext ) {
+ sp->nextcp.x = pos->x + (cp->x-base->me.x);
+ sp->nextcp.y = pos->y + (cp->y-base->me.y);
+ sp->nonextcp = (sp->nextcp.x==pos->x) && (sp->nextcp.y==pos->y);
+ } else {
+ sp->prevcp.x = pos->x + (cp->x-base->me.x);
+ sp->prevcp.y = pos->y + (cp->y-base->me.y);
+ sp->noprevcp = (sp->prevcp.x==pos->x) && (sp->prevcp.y==pos->y);
+ }
+return( sp );
+}
+
+static void NormalizeT(TPoint *mids,int cnt,double tbase,double tend) {
+ int i;
+
+ for ( i=0; i<cnt; ++i )
+ mids[i].t = (mids[i].t - tbase)/(tend - tbase);
+}
+
+static void SPFigureCP(SplinePoint *sp,double t,Spline *spline,int isnext) {
+ Spline temp;
+ double tn;
+ Spline1D *s1;
+ BasePoint off;
+
+ s1 = &spline->splines[0];
+ off.x = sp->me.x - ( ((s1->a*t+s1->b)*t+s1->c)*t+s1->d );
+ s1 = &spline->splines[1];
+ off.y = sp->me.y - ( ((s1->a*t+s1->b)*t+s1->c)*t+s1->d );
+
+ if ( isnext ) {
+ double s = (1.0-t);
+ /* We want to renormalize the spline so that it runs from [t,1] and */
+ /* then figure what the control point at t should be */
+ s1 = &spline->splines[0];
+ temp.splines[0].d = s1->d + t*(s1->c + t*(s1->b + t*s1->a));
+ temp.splines[0].c = s*(s1->c + t*(2*s1->b + 3*s1->a*t));
+ temp.splines[0].b = s*s*(s1->b+3*s1->a*t);
+#if 0
+ temp.splines[0].a = s*s*s*s1->a;
+#endif
+ s1 = &spline->splines[1];
+ temp.splines[1].d = s1->d + t*(s1->c + t*(s1->b + t*s1->a));
+ temp.splines[1].c = s*(s1->c + t*(2*s1->b + 3*s1->a*t));
+ temp.splines[1].b = s*s*(s1->b+3*s1->a*t);
+#if 0
+ temp.splines[1].a = s*s*s*s1->a;
+#endif
+ if ( spline->order2 ) {
+ sp->nextcp.x = temp.splines[0].d + temp.splines[0].c/2 + off.x;
+ sp->nextcp.y = temp.splines[1].d + temp.splines[1].c/2 + off.y;
+ } else {
+ sp->nextcp.x = temp.splines[0].d + temp.splines[0].c/3 + off.x;
+ sp->nextcp.y = temp.splines[1].d + temp.splines[1].c/3 + off.y;
+ }
+ sp->nonextcp = false;
+ } else {
+ /* We want to renormalize the spline so that it runs from [0,t] and */
+ /* then figure what the control point at t should be */
+ temp = *spline;
+ temp.splines[0].c *= t; temp.splines[1].c *= t;
+ tn = t*t;
+ temp.splines[0].b *= tn; temp.splines[1].b *= tn;
+#if 0
+ tn *= t;
+ temp.splines[0].a *= tn; temp.splines[1].a *= tn;
+#endif
+ if ( spline->order2 ) {
+ sp->prevcp.x = temp.splines[0].d + temp.splines[0].c/2 + off.x;
+ sp->prevcp.y = temp.splines[1].d + temp.splines[1].c/2 + off.y;
+ } else {
+ sp->prevcp.x = temp.splines[0].d + (2*temp.splines[0].c+temp.splines[0].b)/3 + off.x;
+ sp->prevcp.y = temp.splines[1].d + (2*temp.splines[1].c+temp.splines[1].b)/3 + off.y;
+ }
+ sp->noprevcp = false;
+ }
+}
+
+static void SPFigurePlusCP(SplinePoint *sp,double t,Spline *spline,int isnext) {
+ SplinePoint dummy;
+
+ /* Plus splines run in the oposite direction */
+ dummy = *sp;
+ SPFigureCP(&dummy,t,spline,!isnext);
+ if ( isnext ) {
+ sp->nextcp = dummy.prevcp;
+ sp->nonextcp = false;
+ } else {
+ sp->prevcp = dummy.nextcp;
+ sp->noprevcp = false;
+ }
+}
+
+static int Overlaps(TPoint *expanded,TPoint *inner,double rsq) {
+ double len;
+ BasePoint dir;
+
+ dir.x = (expanded->x-inner->x); dir.y = (expanded->y-inner->y);
+ len = (dir.x*dir.x) + (dir.y*dir.y);
+ if ( len>=rsq )
+return( false );
+ len = sqrt(rsq/len);
+ expanded->x = inner->x + len*dir.x;
+ expanded->y = inner->y + len*dir.y;
+return( true );
+}
+
+#define Approx 10
+
+static struct strokedspline *_SplineSetApprox(SplineSet *spl,StrokeInfo *si,SplineChar *sc) {
+ struct strokedspline *head=NULL, *last=NULL, *cur;
+ int max=Approx;
+ TPoint *pmids=galloc(max*sizeof(TPoint)),
+ *mmids=galloc(max*sizeof(TPoint)),
+ *mids=galloc(max*sizeof(TPoint));
+ uint8 *knots=galloc(max);
+ BasePoint pto, mto, pfrom, mfrom;
+ double approx, xdiff, ydiff, loopdiff;
+ Spline *spline, *first;
+ int i,j,k;
+ SplinePoint *p_to, *m_to, *p_from, *m_from;
+ int cnt, anyknots;
+ double ts[9];
+ BasePoint m,p,temp;
+ double mt1, pt1, mt2, pt2, rsq;
+ int pinners[10];
+ int mwascovered, pwascovered;
+ enum knot_type { kt_knot=1, kt_pgood=2, kt_mgood=4 };
+ int toobig;
+
+ first = NULL;
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; spline = spline->to->next ) {
+ cur = chunkalloc(sizeof(struct strokedspline));
+ if ( last==NULL )
+ head = cur;
+ else {
+ last->next = cur;
+ cur->prev = last;
+ }
+ last = cur;
+ cur->s = spline;
+ SplineIsLinearMake(spline);
+ SplineExpand(spline,0,0,si,&pto,&mfrom);
+ SplineExpand(spline,1,0,si,&pfrom,&mto);
+ cur->minusfrom = SPNew(spline->from,&mfrom,&spline->from->nextcp,true);
+ cur->plusto = SPNew(spline->from,&pto,&spline->from->nextcp,false);
+ cur->minusto = SPNew(spline->to,&mto,&spline->to->prevcp,false);
+ cur->plusfrom = SPNew(spline->to,&pfrom,&spline->to->prevcp,true);
+
+ if ( si->stroke_type == si_caligraphic ) {
+ /* At each t where the spline is tangent to one of the pen-angles */
+ /* we need to figure out which side is inner and which is outer */
+ /* the outer side gets a copy of the appropriate pen side (with corner points tangent) */
+ /* the inner side is going to be a single corner point at the */
+ /* intersection of the splines from the two corners */
+ /* And if (god help us) we've got a point of inflection here then */
+ /* we get half the pen on each side */
+ /* I ignore the case of a point of inflection, and I don't */
+ /* find the real intersection point, I just guess that it is */
+ /* near the mid point of the pen */
+ cnt = SplineSolveForPen(spline,si,ts,pinners+1,0,1);
+ p_to = m_to = NULL;
+ p_from = NULL; /* Make gcc happy */
+ for ( j=1; j<cnt; ++j ) {
+ for ( i=0; i<Approx; ++i ) {
+ real t = ts[j-1] + (i+1)*(ts[j]-ts[j-1])/(Approx+1);
+ mmids[i].t = (i+1)/(double) (Approx+1); pmids[i].t = 1-mmids[i].t;
+ SplineExpand(spline,t,0,si,&p,&m);
+ pmids[i].x = p.x; pmids[i].y = p.y;
+ mmids[i].x = m.x; mmids[i].y = m.y;
+ }
+ if ( j==1 ) {
+ p_to = cur->plusto; m_from = cur->minusfrom;
+ } else if ( pinners[j-1] ) {
+ p_to = p_from;
+ SplineExpand(spline,ts[j-1],(ts[j-1]-ts[j-2])/20.,si,&p,&m);
+ m_from = SplinePointCreate(m.x,m.y);
+ m_from->pointtype = pt_tangent;
+ SplineMake3(m_to,m_from);
+ } else {
+ m_from = m_to;
+ SplineExpand(spline,ts[j-1],(ts[j-1]-ts[j-2])/20.,si,&p,&m);
+ p_to = SplinePointCreate(p.x,p.y);
+ p_to->pointtype = pt_tangent;
+ SplineMake3(p_to,p_from);
+ }
+ if ( j==cnt-1 ) {
+ p_from = cur->plusfrom;
+ m_to = cur->minusto;
+ } else if ( pinners[j] ) {
+ SplineExpand(spline,ts[j],(ts[j+1]-ts[j-1])/20.,si,&p,&m);
+ SplineExpand(spline,ts[j],-(ts[j+1]-ts[j-1])/20.,si,&temp,&m);
+ p_from = SplinePointCreate((p.x+temp.x)/2,(p.y+temp.y)/2);
+ p_from->pointtype = pt_corner;
+ m_to = SplinePointCreate(m.x,m.y);
+ m_to->pointtype = pt_tangent;
+ } else {
+ SplineExpand(spline,ts[j],(ts[j+1]-ts[j-1])/20.,si,&p,&m);
+ SplineExpand(spline,ts[j],-(ts[j+1]-ts[j-1])/20.,si,&p,&temp);
+ p_from = SplinePointCreate(p.x,p.y);
+ p_from->pointtype = pt_tangent;
+ m_to = SplinePointCreate((m.x+temp.x)/2,(m.y+temp.y)/2);
+ m_to->pointtype = pt_corner;
+ }
+ ApproximateSplineFromPoints(p_from,p_to,pmids,Approx,false);
+ ApproximateSplineFromPoints(m_from,m_to,mmids,Approx,false);
+ if ( m_from!=cur->minusfrom && m_from->pointtype!=pt_corner )
+ m_from->pointtype = pt_tangent;
+ }
+ } else {
+ /* Figure out where the curve starts to bend sharply, and add */
+ /* New points there. I used to strip out the curve where it */
+ /* overlapped itself, but I think that's better done by remove */
+ /* overlap rather than here */
+ if ( (xdiff = spline->to->me.x-spline->from->me.x)<0 ) xdiff = -xdiff;
+ if ( (ydiff = spline->to->me.y-spline->from->me.y)<0 ) ydiff = -ydiff;
+ loopdiff = (xdiff+ydiff==0) ? .1 : 1.0/(4*(xdiff+ydiff)/si->radius);
+ approx = rint(1.0/loopdiff);
+ if ( approx<0 || approx>3000 ) approx=3000;
+ if ( approx>max ) {
+ max = approx+10;
+ pmids = grealloc(pmids,max*sizeof(TPoint));
+ mmids = grealloc(mmids,max*sizeof(TPoint));
+ mids = grealloc(mids,max*sizeof(TPoint));
+ knots = grealloc(knots,max);
+ }
+
+ mwascovered = pwascovered = false;
+ toobig = false;
+ for ( i=0; i<approx; ++i ) {
+ real t = (i+1)/(approx+1);
+ SplineExpand(spline,t,0,si,&p,&m);
+ OnEdge(&p,&m,spline,t,t,spline,si,&pt1,&mt1,&pt2,&mt2);
+ knots[i] = 0;
+ if ( ((pt1!=-1 || pt2!=-1) && !pwascovered && i!=0) ||
+ ((mt1!=-1 || mt2!=-1) && !mwascovered && i!=0))
+ knots[i] = kt_knot;
+ if ( ((pt1==-1 && pt2==-1) && pwascovered && i!=0 ) ||
+ ((mt1==-1 && mt2==-1) && mwascovered && i!=0 )) {
+ if ( knots[i-1]&kt_knot )
+ knots[i] = kt_knot;
+ else
+ knots[i-1] |= kt_knot;
+ }
+ pwascovered = pt1!=-1 || pt2!=-1;
+ mwascovered = mt1!=-1 || mt2!=-1;
+ pmids[i].t = 1-(i+1)/(approx+1);
+ pmids[i].x = p.x; pmids[i].y = p.y;
+ mmids[i].t = (i+1)/(approx+1);
+ mmids[i].x = m.x; mmids[i].y = m.y;
+ mids[i].x = (m.x+p.x)/2; mids[i].y = (m.y+p.y)/2;
+ /*if ( !pwascovered )*/ knots[i] |= kt_pgood;
+ /*if ( !mwascovered )*/ knots[i] |= kt_mgood;
+ if ( pwascovered || mwascovered )
+ toobig = true;
+ }
+ rsq = si->radius*si->radius;
+ for ( i=0; i<approx; ++i ) {
+ for ( j=1; j<approx/2; ++j ) {
+ if ( i+j<approx ) {
+ Overlaps(&mmids[i],&mids[i+j],rsq);
+ Overlaps(&pmids[i],&mids[i+j],rsq);
+ }
+ if ( i-j>0 ) {
+ Overlaps(&mmids[i],&mids[i-j],rsq);
+ Overlaps(&pmids[i],&mids[i-j],rsq);
+ }
+ }
+ }
+ anyknots = false;
+ for ( i=0; i<approx; ++i ) if ( knots[i]&kt_knot ) { anyknots=true; break; }
+ if ( toobig ) {
+ si->gottoobig = si->gottoobiglocal = true;
+ if ( !si->toobigwarn ) {
+ si->toobigwarn = true;
+ gwwv_post_error( _("Bad Stroke"), _("The stroke width is so big that the generated path\nmay intersect itself in %.100s"),
+ sc==NULL?"<nameless char>": sc->name );
+ }
+ }
+
+ /* Look for any sharp bends, they give us problems which are */
+ /* eased by creating a new point. */
+ if ( !anyknots ) {
+ double radius = si->radius;
+ si->radius *= 2;
+ mwascovered = pwascovered = false;
+ for ( i=0; i<approx; ++i ) {
+ real t = (i+1)/(approx+1);
+ SplineExpand(spline,t,0,si,&p,&m);
+ OnEdge(&p,&m,spline,t,t,spline,si,&pt1,&mt1,&pt2,&mt2);
+ if ( ((pt1!=-1 || pt2!=-1) && !pwascovered && i!=0) ||
+ ((mt1!=-1 || mt2!=-1) && !mwascovered && i!=0))
+ knots[i] |= kt_knot;
+ if ( ((pt1==-1 && pt2==-1) && pwascovered && i!=0 ) ||
+ ((mt1==-1 && mt2==-1) && mwascovered && i!=0 )) {
+ if ( knots[i-1]&kt_knot )
+ knots[i] |= kt_knot;
+ else
+ knots[i-1] |= kt_knot;
+ }
+ pwascovered = pt1!=-1 || pt2!=-1;
+ mwascovered = mt1!=-1 || mt2!=-1;
+ }
+ si->radius = radius;
+ }
+
+ p_to = cur->plusto;
+ m_from = cur->minusfrom;
+ for ( i=0, j=1; i<approx; ++i ) {
+ if ( knots[i]&kt_knot ) {
+ for ( k=i+1; k<approx && !(knots[k]&kt_knot); ++k );
+ if ( i>0 && (knots[i-1]&kt_mgood) ) {
+ if ( i+1<approx && !(knots[i+1]&kt_mgood) && k<approx )
+ m_to = SplinePointCreate((mmids[i].x+mmids[k].x)/2,(mmids[i].y+mmids[k].y)/2);
+ else
+ m_to = SplinePointCreate(mmids[i].x,mmids[i].y);
+ m_to->pointtype = pt_corner;
+ SPFigureCP(m_from,(j)/(approx+1),spline,true);
+ SPFigureCP(m_to,(i+1)/(approx+1),spline,false);
+ NormalizeT(mmids+j,i-j,mmids[j-1].t,mmids[i].t);
+ ApproximateSplineFromPointsSlopes(m_from,m_to,mmids+j,i-j,false);
+ m_from = m_to;
+ }
+
+ if ( i>0 && (knots[i-1]&kt_pgood) ) {
+ if ( i+1<approx && !(knots[i+1]&kt_pgood) && k<approx )
+ p_from = SplinePointCreate((pmids[i].x+pmids[k].x)/2,(pmids[i].y+pmids[k].y)/2);
+ else
+ p_from = SplinePointCreate(pmids[i].x,pmids[i].y);
+ p_from->pointtype = pt_corner;
+ SPFigurePlusCP(p_to,j/(approx+1),spline,false);
+ SPFigurePlusCP(p_from,(i+1)/(approx+1),spline,true);
+ NormalizeT(pmids+j,i-j,pmids[i].t,pmids[j-1].t);
+ ApproximateSplineFromPointsSlopes(p_from,p_to,pmids+j,i-j,false);
+ p_to = p_from;
+ }
+
+ j=i+1;
+ }
+ }
+
+ if ( j!=1 ) {
+ NormalizeT(pmids+j,i-j,0.0,pmids[j-1].t);
+ NormalizeT(mmids+j,i-j,mmids[j-1].t,1.0);
+ SPFigureCP(m_from,(j)/(approx+1),spline,true);
+ SPFigurePlusCP(p_to,(j)/(approx+1),spline,false);
+ }
+ ApproximateSplineFromPointsSlopes(cur->plusfrom,p_to,pmids+j,i-j,false);
+ ApproximateSplineFromPointsSlopes(m_from,cur->minusto,mmids+j,i-j,false);
+ }
+ if ( spline->to->next==NULL ) {
+ /* Done */
+ break;
+ }
+ if ( first==NULL ) first = spline;
+ }
+ if ( spline==first ) {
+ head->prev = last;
+ last->next = head;
+ }
+ free(mmids); free(pmids); free(knots); free(mids);
+return( head );
+}
+
+static void SPLCheckValidity(SplineSet *ss) {
+ SplinePoint *sp, *nsp;
+
+ for ( sp=ss->first; ; sp = nsp ) {
+ if ( sp->next==NULL )
+ break;
+ nsp = sp->next->to;
+ if ( nsp->prev != sp->next || sp->next->from!=sp )
+ IError("Bad SPL");
+ if ( nsp==ss->first )
+ break;
+ }
+
+ for ( sp=ss->last; ; sp = nsp ) {
+ if ( sp->prev==NULL )
+ break;
+ nsp = sp->prev->from;
+ if ( nsp->next != sp->prev || sp->prev->to!=sp )
+ IError("Bad SPL");
+ if ( nsp==ss->last )
+ break;
+ }
+}
+
+static SplineSet *_SplineSetStroke(SplineSet *spl,StrokeInfo *si,SplineChar *sc) {
+ SplineSet *ssplus, *ssminus;
+ int reversed = false;
+ struct strokedspline *head, *cur, *first, *lastp, *lastm;
+
+ si->gottoobiglocal = false;
+
+ if ( spl->first->next==NULL || spl->first->next->to==spl->first ) {
+ /* Only one point in the SplineSet. */
+ ssplus = chunkalloc(sizeof(SplineSet));
+ SinglePointStroke(spl->first,si,&ssplus->first,&ssplus->last);
+return( ssplus );
+ }
+
+ SplineSetAddExtrema(NULL,spl,ae_all,1000/* Not used*/);
+
+ if ( spl->first==spl->last && spl->first->next!=NULL ) {
+ /* My routine gets screwed up by counter-clockwise triangles */
+ if ( !SplinePointListIsClockwise(spl)) {
+ reversed = true;
+ SplineSetReverse(spl);
+ }
+ }
+
+ head = cur = _SplineSetApprox(spl,si,sc);
+
+ first = NULL;
+ for ( cur=head; cur!=NULL && cur!=first; cur=cur->next ) {
+ if ( first==NULL ) first = cur;
+ if ( cur->s->to->next!=NULL )
+ StrokeJoint(cur->s->to,si,cur,cur->next,sc);
+ FreeOrigStuff(cur);
+ }
+ FreeOrigStuff(head); /* normally gets freed when we look at the next item on list. But we did that for head first */
+
+ /* Finish off intersections, before doing joins */
+ if ( spl->first->prev==NULL ) {
+ StrokeEndComplete(head,si,true);
+ for ( cur=head; cur->next!=NULL; cur=cur->next );
+ StrokeEndComplete(cur,si,false);
+ }
+
+ lastp = lastm = head;
+ if ( lastp->plusskip ) lastp = NULL;
+ if ( lastm->minusskip ) lastm = NULL;
+
+ first = NULL;
+ for ( cur=head; cur!=NULL && cur!=first; cur=cur->next ) {
+ real factor = si->factor==NULL ? 1.0 : (si->factor)(si->data,cur->s,1.0);
+ if ( first==NULL ) first = cur;
+
+ if ( cur->s->to->next!=NULL ) {
+ if ( !cur->plusskip ) lastp = cur;
+ if ( lastp!=NULL && !cur->next->plusskip ) {
+ if ( cur->pinnerto==-1 )
+ MSP(cur->next->plusto,&lastp->plusfrom,&lastp->plusto);
+ else if ( cur->pinnerto )
+ MSP(cur->next->plusto,&lastp->plusfrom,&lastp->plusto);
+ else if ( cur==lastp )
+ MakeJoints(cur->next->plusto,cur->plusfrom,si,&cur->pinterto,
+ &cur->s->to->me,-1,cur->pangle,cur->nangle,factor);
+ else
+ IError("Lastp not cur" );
+ }
+ if ( !cur->minusskip ) lastm = cur;
+ if ( lastm!=NULL && !cur->next->minusskip ) {
+ if ( cur->minnerto==-1 )
+ MSP(lastm->minusto,&cur->next->minusfrom,&cur->next->minusto);
+ else if ( cur->minnerto )
+ MSP(lastm->minusto,&cur->next->minusfrom,&cur->next->minusto);
+ else if ( cur==lastm )
+ MakeJoints(lastm->minusto,cur->next->minusfrom,si,&cur->minterto,
+ &cur->s->to->me,1,PI+cur->nangle,PI+cur->pangle,factor);
+ else
+ IError("Lastm not cur");
+ }
+ }
+ }
+
+ for ( cur=head; cur!=NULL && cur->plusskip; ) { cur=cur->next; if ( cur==head ) cur=NULL; }
+ if ( cur!=NULL ) {
+ ssplus = chunkalloc(sizeof(SplineSet));
+ ssplus->first = ssplus->last = cur->plusfrom;
+ SplineSetFixCPs(ssplus);
+ SPLCheckValidity(ssplus);
+ } else
+ /* It is possible to have a contour completely swallowed by the pen */
+ ssplus = NULL;
+ for ( cur=head; cur!=NULL && cur->minusskip; ) { cur=cur->next; if ( cur==head ) cur=NULL; }
+ if ( spl->first==spl->last && cur!=NULL ) {
+ ssminus = chunkalloc(sizeof(SplineSet));
+ ssminus->first = ssminus->last = cur->minusfrom;
+ SPLCheckValidity(ssminus);
+ /*SplineSetFixRidiculous(ssplus); SplineSetFixRidiculous(ssminus);*/
+ SplineSetFixCPs(ssminus);
+ if ( reversed ) {
+ SplineSet *temp = ssplus;
+ ssplus = ssminus;
+ ssminus = temp;
+ }
+ /* I can't always detect an overlap, so let's always do the remove */
+ /* Sigh, no. That is still too dangerous */
+ /* Note: SSFixupOverlap will remove internal/external as needed */
+ SplineSetReverse(ssminus);
+ if ( ssplus != NULL )
+ SplineSetReverse(ssplus);
+ if ( si->removeoverlapifneeded && si->gottoobiglocal && ssplus!=NULL )
+ ssplus = SSFixupOverlap(si,sc,ssplus,ssminus,reversed);
+ else if ( si->removeinternal && ssplus!=NULL ) {
+ SplinePointListFree(ssminus);
+ } else if ( si->removeexternal ) {
+ SplinePointListFree(ssplus);
+ SplineSetReverse(ssminus);
+ ssplus = ssminus;
+ } else {
+ if ( ssplus != NULL )
+ ssplus->next = ssminus;
+ else
+ ssplus = ssminus;
+ /* I used to do a splineset correct dir here on both, but */
+ /* that doesn't work always if a contour self intersects */
+ /* I think it should always be correct */
+ }
+ if ( reversed ) /* restore original, just in case we want it */
+ SplineSetReverse(spl);
+ } else if ( si->stroke_type==si_std || si->stroke_type==si_elipse )
+ SplineSetReverse(ssplus);
+ StrokedSplineFree(head);
+return( ssplus );
+}
+
+#if 0
+static void BisectTurners(SplineSet *spl) {
+ Spline *first, *s, *next;
+ double len,lenf,lent, dott,dotf;
+
+ /* Also if we have a spline which turns through about 180 degrees */
+ /* our approximations degrade. So bisect any such splines */
+ first = NULL;
+ for ( s = spl->first->next; s!=NULL && s!=first; s=next ) {
+ next = s->to->next;
+ if ( first==NULL ) first = s;
+ len = sqrt( (s->from->me.x-s->to->me.x)*(s->from->me.x-s->to->me.x) +
+ (s->from->me.y-s->to->me.y)*(s->from->me.y-s->to->me.y) );
+ lenf= sqrt( (s->from->me.x-s->from->nextcp.x)*(s->from->me.x-s->from->nextcp.x) +
+ (s->from->me.y-s->from->nextcp.y)*(s->from->me.y-s->from->nextcp.y) );
+ dotf = ((s->from->me.x-s->to->me.x)*(s->from->me.x-s->from->nextcp.x) +
+ (s->from->me.y-s->to->me.y)*(s->from->me.y-s->from->nextcp.y))/
+ (len*lenf);
+ lent= sqrt( (s->to->prevcp.x-s->to->me.x)*(s->to->prevcp.x-s->to->me.x) +
+ (s->to->prevcp.y-s->to->me.y)*(s->to->prevcp.y-s->to->me.y) );
+ dott = ((s->from->me.x-s->to->me.x)*(s->to->prevcp.x-s->to->me.x) +
+ (s->from->me.y-s->to->me.y)*(s->to->prevcp.y-s->to->me.y))/
+ (len*lent);
+ dotf = acos(dotf); dott = acos(dott);
+ if ( dotf+dott > PI/2 )
+ SplineBisect(s,.5);
+ }
+}
+
+void SSBisectTurners(SplineSet *spl) {
+ while ( spl!=NULL ) {
+ BisectTurners(spl);
+ spl = spl->next;
+ }
+}
+#endif
+
+#ifdef LOCAL_DEBUG
+static void touchall(SplineSet *spl) {
+ SplinePoint *sp;
+
+ for ( sp=spl->last; sp!=NULL; ) {
+ if ( sp->prev==NULL )
+ break;
+ sp = sp->prev->from;
+ if ( sp==spl->last )
+ break;
+ }
+ for ( sp=spl->first; sp!=NULL; ) {
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+}
+
+/* I know there's no prototype. It's just a useful routine to make valgrind */
+/* check consistency */
+void splstouchall(SplineSet *ss) {
+ while ( ss!=NULL ) {
+ touchall(ss);
+ ss = ss->next;
+ }
+}
+#endif
+
+static SplineSet *SSRemoveUTurns(SplineSet *base, StrokeInfo *si) {
+ /* All too often in MetaPost output splines have tiny cps which */
+ /* make the slope at the end-points irrelevant when looking at */
+ /* the curve. Since we assume the slope at the end-points is */
+ /* similar to the slope at t=.01 this confuses us greatly and */
+ /* produces nasty results. In this case try to approximate a new */
+ /* spline with very different cps. Note: We break continuity! */
+ /* A special case of this is the following: */
+ /* My stroking algorithem gets confused by sharp turns. For example */
+ /* if we have a spline which is all in a line, but the control points */
+ /* are such that it doubles back on itself ( "* + * +", ie. cps */
+ /* outside of the points) then things get very unhappy */
+ SplineSet *spl= base;
+ Spline *first, *s, *next, *snew;
+ double dx,dy, offx,offy, diff, n,l, slen, len, bound;
+ int linear, bad, i, cnt;
+ SplinePoint fakefrom, faketo;
+ TPoint *tps;
+
+ bound = si->radius*si->radius;
+ first = NULL;
+ if ( spl->first->next!=NULL && !spl->first->next->order2 )
+ for ( s = spl->first->next; s!=NULL && s!=first; s=s->to->next ) {
+ if ( first==NULL ) first = s;
+
+ bad = false;
+ dx = s->to->me.x-s->from->me.x;
+ dy = s->to->me.y-s->from->me.y;
+ slen = dx*dx + dy*dy;
+
+ offx = s->from->nextcp.x-s->from->me.x;
+ offy = s->from->nextcp.y-s->from->me.y;
+ l= offx*dx + offy*dy;
+ if ( l<0 ) {
+ l = -l;
+ if ( (n= offx*dy - offy*dx)<0 ) n = -n;
+ len = offx*offx + offy*offy;
+ if ( (n/l>2*len/si->radius || (n>l/3 && s->from->prev==NULL )) && len<bound && len< slen/4 )
+ bad = 1;
+ }
+
+ offx = s->to->me.x-s->to->prevcp.x;
+ offy = s->to->me.y-s->to->prevcp.y;
+ l= offx*dx + offy*dy;
+ if ( l<0 ) {
+ l = -l;
+ if ( (n= offx*dy - offy*dx)<0 ) n = -n;
+ len = offx*offx + offy*offy;
+ if ( (n/l>2*len/si->radius || (n>l/3 && s->to->next==NULL)) && len<bound && len< slen/4 )
+ bad |= 2;
+ }
+
+ if ( bad ) {
+ fakefrom = *s->from; fakefrom.next = fakefrom.prev = NULL;
+ faketo = *s->to; faketo.next = faketo.prev = NULL;
+
+ slen = sqrt(slen);
+ dx /= slen; dy/=slen;
+
+ if ( bad&1 ) { /* from->nextcp is nasty */
+ offx = s->from->nextcp.x-s->from->me.x;
+ offy = s->from->nextcp.y-s->from->me.y;
+ len = sqrt(offx*offx + offy*offy);
+ offx /= len; offy/=len;
+
+ n = offx*dy - offy*dx;
+ fakefrom.nextcp.x = fakefrom.me.x + slen*dx + 3*len*dy;
+ fakefrom.nextcp.y = fakefrom.me.y + slen*dy - 3*len*dx;
+ }
+
+ if ( bad&2 ) { /* from->nextcp is nasty */
+ offx = s->to->prevcp.x-s->to->me.x;
+ offy = s->to->prevcp.y-s->to->me.y;
+ len = sqrt(offx*offx + offy*offy);
+ offx /= len; offy/=len;
+
+ n = offx*dy - offy*dx;
+ faketo.prevcp.x = faketo.me.x - slen*dx + 3*len*dy;
+ faketo.prevcp.y = faketo.me.y - slen*dy - 3*len*dx;
+ }
+
+ if (( cnt = slen/2)<10 ) cnt = 10;
+ tps = galloc(cnt*sizeof(TPoint));
+ for ( i=0; i<cnt; ++i ) {
+ double t = ((double) (i+1))/(cnt+1);
+ tps[i].t = t;
+ tps[i].x = ((s->splines[0].a*t + s->splines[0].b)*t + s->splines[0].c)*t + s->splines[0].d;
+ tps[i].y = ((s->splines[1].a*t + s->splines[1].b)*t + s->splines[1].c)*t + s->splines[1].d;
+ }
+ snew = ApproximateSplineFromPointsSlopes(&fakefrom,&faketo,tps,cnt,false);
+ snew->from = s->from;
+ snew->to = s->to;
+ snew->from->next = snew;
+ snew->to->prev = snew;
+ snew->from->nextcp = fakefrom.nextcp;
+ snew->from->nonextcp = fakefrom.nonextcp;
+ if ( bad&1 ) snew->from->pointtype = pt_corner;
+ snew->to->prevcp = faketo.prevcp;
+ snew->to->noprevcp = faketo.noprevcp;
+ if ( bad&2 ) snew->to->pointtype = pt_corner;
+ if ( first==s ) first=snew;
+ SplineFree(s);
+ free(tps);
+ s = snew;
+ }
+ }
+
+ first = NULL;
+ for ( s = spl->first->next; s!=NULL && s!=first; s=s->to->next ) {
+ if ( first==NULL ) first = s;
+ dx = s->to->me.x-s->from->me.x;
+ dy = s->to->me.y-s->from->me.y;
+ offx = s->from->nextcp.x-s->from->me.x;
+ offy = s->from->nextcp.y-s->from->me.y;
+ if ( offx*dx + offy*dy<0 ) {
+ diff = offx*dy-offy*dx;
+ linear = ( diff<1 && diff>-1 );
+ if ( offx<0 ) offx = -offx;
+ if ( offy<0 ) offy = -offy;
+ if ( offx+offy<1 || linear ) {
+ s->from->nextcp = s->from->me;
+ s->from->nonextcp = true;
+ if ( s->from->pointtype == pt_curve )
+ s->from->pointtype = pt_corner;
+ if ( s->order2 ) {
+ s->to->prevcp = s->to->me;
+ s->to->noprevcp = true;
+ if ( s->to->pointtype==pt_curve )
+ s->to->pointtype = pt_corner;
+ }
+ SplineRefigure(s);
+ }
+ }
+ offx = s->to->me.x-s->to->prevcp.x;
+ offy = s->to->me.y-s->to->prevcp.y;
+ if ( offx*dx + offy*dy<0 ) {
+ diff = offx*dy-offy*dx;
+ linear = ( diff<1 && diff>-1 );
+ if ( offx<0 ) offx = -offx;
+ if ( offy<0 ) offy = -offy;
+ if ( offx+offy<1 || linear ) {
+ s->to->prevcp = s->to->me;
+ s->to->noprevcp = true;
+ if ( s->to->pointtype==pt_curve )
+ s->to->pointtype = pt_corner;
+ if ( s->order2 ) {
+ s->from->nextcp = s->from->me;
+ s->from->nonextcp = true;
+ if ( s->from->pointtype == pt_curve )
+ s->from->pointtype = pt_corner;
+ }
+ SplineRefigure(s);
+ }
+ }
+ }
+
+ /* Zero length splines are bad too */
+ /* As are splines of length .000003 */
+ first = NULL;
+ for ( s = spl->first->next; s!=NULL && s!=first; s=next ) {
+ if ( first==NULL ) first = s;
+ next = s->to->next;
+ if ( s->from->nonextcp && s->to->noprevcp && s!=next &&
+ s->from->me.x >= s->to->me.x-.1 && s->from->me.x <= s->to->me.x+.1 &&
+ s->from->me.y >= s->to->me.y-.1 && s->from->me.y <= s->to->me.y+.1 ) {
+ s->from->next = next;
+ if ( next!=NULL ) {
+ s->from->nextcp = next->from->nextcp;
+ s->from->nonextcp = next->from->nonextcp;
+ s->from->nextcpdef = next->from->nextcpdef;
+ next->from = s->from;
+ }
+ SplinePointCatagorize(s->from);
+ if ( spl->last == s->to ) {
+ if ( next==NULL )
+ spl->last = s->from;
+ else
+ spl->first = spl->last = s->from;
+ }
+ if ( spl->first==s->to ) spl->first = s->from;
+ if ( spl->last==s->to ) spl->last = s->from;
+ SplinePointFree(s->to);
+ SplineFree(s);
+ if ( first==s ) first = NULL;
+ }
+ }
+
+#if 0
+ BisectTurners(spl);
+#endif
+return( base );
+}
+
+SplineSet *SplineSetStroke(SplineSet *spl,StrokeInfo *si,SplineChar *sc) {
+ SplineSet *ret, *temp, *temp2;
+ SplineSet *order3 = NULL;
+
+ if ( spl->first->next!=NULL && spl->first->next->order2 )
+ order3 = spl = SSPSApprox(spl);
+ if ( si->radius==0 )
+ si->radius=1;
+ temp2 = SSRemoveUTurns(SplinePointListCopy(spl),si);
+ if ( si->stroke_type == si_elipse ) {
+ real trans[6], factor;
+ StrokeInfo si2;
+ trans[0] = trans[3] = si->c;
+ trans[1] = -si->s;
+ trans[2] = si->s;
+ trans[4] = trans[5] = 0;
+ factor = si->radius/si->minorradius;
+ trans[0] *= factor; trans[2] *= factor;
+ temp = SplinePointListCopy(temp2);
+#if 0
+ BisectTurners(temp);
+#endif
+ temp = SplinePointListTransform(temp,trans,true);
+ si2 = *si;
+ si2.stroke_type = si_std;
+ ret = SplineSetStroke(temp,&si2,sc);
+ SplinePointListFree(temp);
+ trans[0] = trans[3] = si->c;
+ trans[1] = si->s;
+ trans[2] = -si->s;
+ trans[4] = trans[5] = 0;
+ factor = si->minorradius/si->radius;
+ trans[0] *= factor; trans[1] *= factor;
+ ret = SplinePointListTransform(ret,trans,true);
+ } else
+ ret = _SplineSetStroke(temp2,si,sc);
+ SplinePointListFree(temp2);
+ if ( order3!=NULL ) {
+ temp = SplineSetsTTFApprox(ret);
+ SplinePointListsFree(ret);
+ SplinePointListFree(order3);
+ ret = temp;
+ }
+return( ret );
+}
+
+ /* for angles between [penangle,penangle+90] use (-r,t/2) rotated by penangle */
+ /* [penangle+90,penangle+180] use (-r,-t/2) */
+ /* [penangle+180,penangle+270] use (r,-t/2) */
+ /* [penangle+270,penangle] use (r,t/2) */
+
+SplineSet *SSStroke(SplineSet *spl,StrokeInfo *si,SplineChar *sc) {
+ SplineSet *head=NULL, *last=NULL, *cur;
+ /*int was_clock = true;*/
+
+ for ( ; spl!=NULL; spl = spl->next ) {
+#if 0
+ if ( si->removeinternal || si->removeexternal )
+ was_clock = SplinePointListIsClockwise(spl);
+#endif
+ cur = SplineSetStroke(spl,si,sc);
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+#if 0
+ if ( was_clock==0 ) /* there'd better be only one spl in cur */
+ SplineSetReverse(cur);
+#endif
+ while ( cur->next!=NULL ) cur = cur->next;
+ last = cur;
+ }
+return( head );
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/splineutil.c b/Build/source/libs/luafontforge/fontforge/fontforge/splineutil.c
new file mode 100644
index 00000000000..173d2d4ad68
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/splineutil.c
@@ -0,0 +1,5776 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaeditui.h"
+#include <math.h>
+#include "psfont.h"
+#include "ustring.h"
+#include "utype.h"
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+#include "views.h" /* for FindSel structure */
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+#ifdef HAVE_IEEEFP_H
+# include <ieeefp.h> /* Solaris defines isnan in ieeefp rather than math.h */
+#endif
+
+/*#define DEBUG 1*/
+
+typedef struct quartic {
+ double a,b,c,d,e;
+} Quartic;
+
+/* In an attempt to make allocation more efficient I just keep preallocated */
+/* lists of certain common sizes. It doesn't seem to make much difference */
+/* when allocating stuff, but does when freeing. If the extra complexity */
+/* is bad then put: */
+/* #define chunkalloc(size) gcalloc(1,size) */
+/* #define chunkfree(item,size) free(item) */
+/* into splinefont.h after (or instead of) the definition of chunkalloc()*/
+
+#ifndef chunkalloc
+#define ALLOC_CHUNK 100 /* Number of small chunks to malloc at a time */
+#if !defined(FONTFORGE_CONFIG_USE_LONGDOUBLE) && !defined(FONTFORGE_CONFIG_USE_DOUBLE)
+# define CHUNK_MAX 100 /* Maximum size (in chunk units) that we are prepared to allocate */
+ /* The size of our data structures */
+#else
+# define CHUNK_MAX 129
+#endif
+# define CHUNK_UNIT sizeof(void *) /* will vary with the word size of */
+ /* the machine. if pointers are 64 bits*/
+ /* we may need twice as much space as for 32 bits */
+
+#ifdef FLAG
+#undef FLAG
+#define FLAG 0xbadcafe
+#endif
+
+#ifdef CHUNKDEBUG
+static int chunkdebug = 0; /* When this is set we never free anything, insuring that each chunk is unique */
+#endif
+
+#if ALLOC_CHUNK>1
+struct chunk { struct chunk *next; };
+struct chunk2 { struct chunk2 *next; int flag; };
+static struct chunk *chunklists[CHUNK_MAX] = { 0 };
+#endif
+
+#if defined(FLAG) && ALLOC_CHUNK>1
+void chunktest(void) {
+ int i;
+ struct chunk2 *c;
+
+ for ( i=2; i<CHUNK_MAX; ++i )
+ for ( c=(struct chunk2 *) chunklists[i]; c!=NULL; c=c->next )
+ if ( c->flag!=FLAG ) {
+ fprintf( stderr, "Chunk memory list has been corrupted\n" );
+ abort();
+ }
+}
+#endif
+
+void *chunkalloc(int size) {
+# if ALLOC_CHUNK<=1
+return( gcalloc(1,size));
+# else
+ struct chunk *item;
+ int index;
+
+ if ( size&(CHUNK_UNIT-1) )
+ size = (size+CHUNK_UNIT-1)&~(CHUNK_UNIT-1);
+
+ if ( (size&(CHUNK_UNIT-1)) || size>=CHUNK_MAX*CHUNK_UNIT || size<=sizeof(struct chunk)) {
+ fprintf( stderr, "Attempt to allocate something of size %d\n", size );
+return( gcalloc(1,size));
+ }
+#ifdef FLAG
+ chunktest();
+#endif
+ index = (size+CHUNK_UNIT-1)/CHUNK_UNIT;
+ if ( chunklists[index]==NULL ) {
+ char *pt, *end;
+ pt = galloc(ALLOC_CHUNK*size);
+ chunklists[index] = (struct chunk *) pt;
+ end = pt+(ALLOC_CHUNK-1)*size;
+ while ( pt<end ) {
+ ((struct chunk *) pt)->next = (struct chunk *) (pt + size);
+#ifdef FLAG
+ ((struct chunk2 *) pt)->flag = FLAG;
+#endif
+ pt += size;
+ }
+ ((struct chunk *) pt)->next = NULL;
+#ifdef FLAG
+ ((struct chunk2 *) pt)->flag = FLAG;
+#endif
+ }
+ item = chunklists[index];
+ chunklists[index] = item->next;
+ memset(item,'\0',size);
+return( item );
+# endif
+}
+
+void chunkfree(void *item,int size) {
+ int index = (size+CHUNK_UNIT-1)/CHUNK_UNIT;
+#ifdef CHUNKDEBUG
+ if ( chunkdebug )
+return;
+#endif
+# if ALLOC_CHUNK<=1
+ free(item);
+# else
+ if ( item==NULL )
+return;
+
+ if ( size&(CHUNK_UNIT-1) )
+ size = (size+CHUNK_UNIT-1)&~(CHUNK_UNIT-1);
+
+ if ( (size&(CHUNK_UNIT-1)) || size>=CHUNK_MAX*CHUNK_UNIT || size<=sizeof(struct chunk)) {
+ fprintf( stderr, "Attempt to free something of size %d\n", size );
+ free(item);
+ } else {
+#ifdef LOCAL_DEBUG
+ if ( (char *) (chunklists[index]) == (char *) item ||
+ ( ((char *) (chunklists[index]))<(char *) item &&
+ ((char *) (chunklists[index]))+size>(char *) item) ||
+ ( ((char *) (chunklists[index]))>(char *) item &&
+ ((char *) (chunklists[index]))<((char *) item)+size))
+ IError( "Memory mixup. Chunk list is wrong!!!" );
+#endif
+ ((struct chunk *) item)->next = chunklists[index];
+# ifdef FLAG
+ if ( size>=sizeof(struct chunk2))
+ ((struct chunk2 *) item)->flag = FLAG;
+# endif
+ chunklists[index] = (struct chunk *) item;
+ }
+# ifdef FLAG
+ chunktest();
+# endif
+# endif
+}
+#endif
+
+char *strconcat(const char *str1,const char *str2) {
+ int len1 = strlen(str1);
+ char *ret = galloc(len1+strlen(str2)+1);
+ strcpy(ret,str1);
+ strcpy(ret+len1,str2);
+return( ret );
+}
+
+char *strconcat3(const char *str1,const char *str2, const char *str3) {
+ int len1 = strlen(str1), len2 = strlen(str2);
+ char *ret = galloc(len1+len2+strlen(str3)+1);
+ strcpy(ret,str1);
+ strcpy(ret+len1,str2);
+ strcpy(ret+len1+len2,str2);
+return( ret );
+}
+
+void LineListFree(LineList *ll) {
+ LineList *next;
+
+ while ( ll!=NULL ) {
+ next = ll->next;
+ chunkfree(ll,sizeof(LineList));
+ ll = next;
+ }
+}
+
+void LinearApproxFree(LinearApprox *la) {
+ LinearApprox *next;
+
+ while ( la!=NULL ) {
+ next = la->next;
+ LineListFree(la->lines);
+ chunkfree(la,sizeof(LinearApprox));
+ la = next;
+ }
+}
+
+void SplineFree(Spline *spline) {
+ LinearApproxFree(spline->approx);
+ chunkfree(spline,sizeof(Spline));
+}
+
+SplinePoint *SplinePointCreate(real x, real y) {
+ SplinePoint *sp = chunkalloc(sizeof(SplinePoint));
+ sp->me.x = x; sp->me.y = y;
+ sp->nextcp = sp->prevcp = sp->me;
+ sp->nonextcp = sp->noprevcp = true;
+ sp->nextcpdef = sp->prevcpdef = false;
+ sp->ttfindex = sp->nextcpindex = 0xfffe;
+return( sp );
+}
+
+Spline *SplineMake3(SplinePoint *from, SplinePoint *to) {
+ Spline *spline = chunkalloc(sizeof(Spline));
+
+ spline->from = from; spline->to = to;
+ from->next = to->prev = spline;
+ SplineRefigure3(spline);
+return( spline );
+}
+
+void SplinePointFree(SplinePoint *sp) {
+ chunkfree(sp->hintmask,sizeof(HintMask));
+ chunkfree(sp,sizeof(SplinePoint));
+}
+
+void SplinePointMDFree(SplineChar *sc, SplinePoint *sp) {
+ MinimumDistance *md, *prev, *next;
+
+ if ( sc!=NULL ) {
+ prev = NULL;
+ for ( md = sc->md; md!=NULL; md = next ) {
+ next = md->next;
+ if ( md->sp1==sp || md->sp2==sp ) {
+ if ( prev==NULL )
+ sc->md = next;
+ else
+ prev->next = next;
+ chunkfree(md,sizeof(MinimumDistance));
+ } else
+ prev = md;
+ }
+ }
+
+ chunkfree(sp->hintmask,sizeof(HintMask));
+ chunkfree(sp,sizeof(SplinePoint));
+}
+
+void SplinePointsFree(SplinePointList *spl) {
+ Spline *first, *spline, *next;
+ int nonext;
+
+ if ( spl==NULL )
+return;
+ nonext = spl->first->next==NULL;
+ if ( spl->first!=NULL ) {
+ first = NULL;
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; spline = next ) {
+ next = spline->to->next;
+ SplinePointFree(spline->to);
+ SplineFree(spline);
+ if ( first==NULL ) first = spline;
+ }
+ if ( spl->last!=spl->first || nonext )
+ SplinePointFree(spl->first);
+ }
+}
+
+void SplinePointListFree(SplinePointList *spl) {
+ Spline *first, *spline, *next;
+ int nonext;
+
+ if ( spl==NULL )
+return;
+ if ( spl->first!=NULL ) {
+ nonext = spl->first->next==NULL;
+ first = NULL;
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; spline = next ) {
+ next = spline->to->next;
+ SplinePointFree(spline->to);
+ SplineFree(spline);
+ if ( first==NULL ) first = spline;
+ }
+ if ( spl->last!=spl->first || nonext )
+ SplinePointFree(spl->first);
+ }
+ chunkfree(spl,sizeof(SplinePointList));
+}
+
+void SplinePointListMDFree(SplineChar *sc,SplinePointList *spl) {
+ Spline *first, *spline, *next;
+ int freefirst;
+
+ if ( spl==NULL )
+return;
+ if ( spl->first!=NULL ) {
+ first = NULL;
+ freefirst = ( spl->last!=spl->first || spl->first->next==NULL );
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; spline = next ) {
+ next = spline->to->next;
+ SplinePointMDFree(sc,spline->to);
+ SplineFree(spline);
+ if ( first==NULL ) first = spline;
+ }
+ if ( freefirst )
+ SplinePointMDFree(sc,spl->first);
+ }
+ chunkfree(spl,sizeof(SplinePointList));
+}
+
+void SplinePointListsMDFree(SplineChar *sc,SplinePointList *spl) {
+ SplinePointList *next;
+
+ while ( spl!=NULL ) {
+ next = spl->next;
+ SplinePointListMDFree(sc,spl);
+ spl = next;
+ }
+}
+
+void SplinePointListsFree(SplinePointList *head) {
+ SplinePointList *spl, *next;
+
+ for ( spl=head; spl!=NULL; spl=next ) {
+ next = spl->next;
+ SplinePointListFree(spl);
+ }
+}
+
+void ImageListsFree(ImageList *imgs) {
+ ImageList *inext;
+
+ while ( imgs!=NULL ) {
+ inext = imgs->next;
+ chunkfree(imgs,sizeof(ImageList));
+ imgs = inext;
+ }
+}
+
+void RefCharFree(RefChar *ref) {
+#ifdef FONTFORGE_CONFIG_TYPE3
+ int i;
+
+ if ( ref==NULL )
+return;
+ for ( i=0; i<ref->layer_cnt; ++i ) {
+ SplinePointListsFree(ref->layers[i].splines);
+ ImageListsFree(ref->layers[i].images);
+ }
+ free(ref->layers);
+#else
+ if ( ref==NULL )
+return;
+ SplinePointListsFree(ref->layers[0].splines);
+#endif
+ chunkfree(ref,sizeof(RefChar));
+}
+
+RefChar *RefCharCreate(void) {
+ RefChar *ref = chunkalloc(sizeof(RefChar));
+#ifdef FONTFORGE_CONFIG_TYPE3
+ ref->layers = gcalloc(1,sizeof(struct reflayer));
+ ref->layers[0].fill_brush.opacity = ref->layers[0].stroke_pen.brush.opacity = 1.0;
+ ref->layers[0].fill_brush.col = ref->layers[0].stroke_pen.brush.col = COLOR_INHERITED;
+ ref->layers[0].stroke_pen.width = WIDTH_INHERITED;
+ ref->layers[0].stroke_pen.linecap = lc_inherited;
+ ref->layers[0].stroke_pen.linejoin = lj_inherited;
+ ref->layers[0].dofill = true;
+#endif
+ ref->layer_cnt = 1;
+ ref->round_translation_to_grid = true;
+return( ref );
+}
+
+void RefCharsFree(RefChar *ref) {
+ RefChar *rnext;
+
+ while ( ref!=NULL ) {
+ rnext = ref->next;
+ RefCharFree(ref);
+ ref = rnext;
+ }
+}
+
+static extended SolveCubic(extended a, extended b, extended c, extended d, double err, extended t0) {
+ /* find t between t0 and .5 where at^3+bt^2+ct+d == +/- err */
+ extended t, val, offset;
+ int first;
+
+ offset=a;
+ if ( a<0 ) offset = -a;
+ if ( b<0 ) offset -= b; else offset += b;
+ if ( c<0 ) offset -= c; else offset += c;
+ offset += 1; /* Make sure it isn't 0 */
+ offset = err/(10.*offset);
+ if ( offset<.00001 ) offset = .00001; else if ( offset>.01 ) offset = .01;
+
+ first = 1;
+ for ( t=t0+offset; t<.5; t += offset ) {
+ val = ((a*t+b)*t+c)*t+d;
+ if ( val>=err || val<=-err )
+ break;
+ first = 0;
+ }
+ if ( !first )
+ t -= offset;
+ if ( t>.5 ) t=.5;
+
+return( t );
+}
+
+static extended SolveCubicBack(extended a, extended b, extended c, extended d, double err, extended t0) {
+ /* find t between .5 and t0 where at^3+bt^2+ct+d == +/- err */
+ extended t, val, offset;
+ int first;
+
+ offset=a;
+ if ( a<0 ) offset = -a;
+ if ( b<0 ) offset -= b; else offset += b;
+ if ( c<0 ) offset -= c; else offset += c;
+ offset += 1; /* Make sure it isn't 0 */
+ offset = err/(10.*offset);
+ if ( offset<.00001 ) offset = .00001; else if ( offset>.01 ) offset = .01;
+
+ first = 1;
+ for ( t=t0-offset; t>.5; t -= offset ) {
+ val = ((a*t+b)*t+c)*t+d;
+ if ( val>=err || val<=-err )
+ break;
+ first = 0;
+ }
+ if ( !first )
+ t -= offset;
+ if ( t<.5 ) t=.5;
+
+return( t );
+}
+
+/* Remove line segments which are just one point long */
+/* Merge colinear line segments */
+/* Merge two segments each of which involves a single pixel change in one dimension (cut corners) */
+static void SimplifyLineList(LineList *prev) {
+ LineList *next, *lines;
+
+ if ( prev->next==NULL )
+return;
+ lines = prev->next;
+ while ( (next = lines->next)!=NULL ) {
+ if ( (prev->here.x==lines->here.x && prev->here.y == lines->here.y ) ||
+ ( prev->here.x==lines->here.x && lines->here.x==next->here.x ) ||
+ ( prev->here.y==lines->here.y && lines->here.y==next->here.y ) ||
+ (( prev->here.x==next->here.x+1 || prev->here.x==next->here.x-1 ) &&
+ ( prev->here.y==next->here.y+1 || prev->here.y==next->here.y-1 )) ) {
+ lines->here = next->here;
+ lines->next = next->next;
+ chunkfree(next,sizeof(*next));
+ } else {
+ prev = lines;
+ lines = next;
+ }
+ }
+ if ( prev!=NULL &&
+ prev->here.x==lines->here.x && prev->here.y == lines->here.y ) {
+ prev->next = lines->next;
+ chunkfree(lines,sizeof(*lines));
+ lines = prev->next;
+ }
+
+ if ( lines!=NULL ) while ( (next = lines->next)!=NULL ) {
+ if ( prev->here.x!=next->here.x ) {
+ double slope = (next->here.y-prev->here.y) / (double) (next->here.x-prev->here.x);
+ double inter = prev->here.y - slope*prev->here.x;
+ int y = rint(lines->here.x*slope + inter);
+ if ( y == lines->here.y ) {
+ lines->here = next->here;
+ lines->next = next->next;
+ chunkfree(next,sizeof(*next));
+ } else
+ lines = next;
+ } else
+ lines = next;
+ }
+}
+
+LinearApprox *SplineApproximate(Spline *spline, real scale) {
+ LinearApprox *test;
+ LineList *cur, *last=NULL, *prev;
+ double tx,ty,t;
+ double slpx, slpy;
+ double intx, inty;
+
+ for ( test = spline->approx; test!=NULL && test->scale!=scale; test = test->next );
+ if ( test!=NULL )
+return( test );
+
+ test = chunkalloc(sizeof(LinearApprox));
+ test->scale = scale;
+ test->next = spline->approx;
+ spline->approx = test;
+
+ cur = chunkalloc(sizeof(LineList) );
+ cur->here.x = rint(spline->from->me.x*scale);
+ cur->here.y = rint(spline->from->me.y*scale);
+ test->lines = last = cur;
+ if ( spline->knownlinear ) {
+ cur = chunkalloc(sizeof(LineList) );
+ cur->here.x = rint(spline->to->me.x*scale);
+ cur->here.y = rint(spline->to->me.y*scale);
+ last->next = cur;
+ } else {
+ /* find t so that (xt,yt) is a half pixel off from (cx*t+dx,cy*t+dy) */
+ /* min t of scale*(ax*t^3+bx*t^2)==.5, scale*(ay*t^3+by*t^2)==.5 */
+ /* I do this from both ends in. this is because I miss essential */
+ /* symmetry if I go from one end to the other. */
+ /* first start at 0 and go to .5, the first linear approximation is easy */
+ /* it's just the function itself ignoring higher orders, so the error*/
+ /* is just the higher orders */
+ tx = SolveCubic(spline->splines[0].a,spline->splines[0].b,0,0,.5/scale,0);
+ ty = SolveCubic(spline->splines[1].a,spline->splines[1].b,0,0,.5/scale,0);
+ t = (tx<ty)?tx:ty;
+ cur = chunkalloc(sizeof(LineList) );
+ cur->here.x = rint( (((spline->splines[0].a*t+spline->splines[0].b)*t+spline->splines[0].c)*t + spline->splines[0].d)*scale );
+ cur->here.y = rint( (((spline->splines[1].a*t+spline->splines[1].b)*t+spline->splines[1].c)*t + spline->splines[1].d)*scale );
+ last->next = cur;
+ last = cur;
+ while ( t<.5 ) {
+ slpx = (3*spline->splines[0].a*t+2*spline->splines[0].b)*t+spline->splines[0].c;
+ slpy = (3*spline->splines[1].a*t+2*spline->splines[1].b)*t+spline->splines[1].c;
+ intx = ((spline->splines[0].a*t+spline->splines[0].b)*t+spline->splines[0].c-slpx)*t + spline->splines[0].d;
+ inty = ((spline->splines[1].a*t+spline->splines[1].b)*t+spline->splines[1].c-slpy)*t + spline->splines[1].d;
+ tx = SolveCubic(spline->splines[0].a,spline->splines[0].b,spline->splines[0].c-slpx,spline->splines[0].d-intx,.5/scale,t);
+ ty = SolveCubic(spline->splines[1].a,spline->splines[1].b,spline->splines[1].c-slpy,spline->splines[1].d-inty,.5/scale,t);
+ t = (tx<ty)?tx:ty;
+ cur = chunkalloc(sizeof(LineList));
+ cur->here.x = rint( (((spline->splines[0].a*t+spline->splines[0].b)*t+spline->splines[0].c)*t + spline->splines[0].d)*scale );
+ cur->here.y = rint( (((spline->splines[1].a*t+spline->splines[1].b)*t+spline->splines[1].c)*t + spline->splines[1].d)*scale );
+ last->next = cur;
+ last = cur;
+ }
+
+ /* Now start at t=1 and work back to t=.5 */
+ prev = NULL;
+ cur = chunkalloc(sizeof(LineList) );
+ cur->here.x = rint(spline->to->me.x*scale);
+ cur->here.y = rint(spline->to->me.y*scale);
+ prev = cur;
+ t=1.0;
+ while ( 1 ) {
+ slpx = (3*spline->splines[0].a*t+2*spline->splines[0].b)*t+spline->splines[0].c;
+ slpy = (3*spline->splines[1].a*t+2*spline->splines[1].b)*t+spline->splines[1].c;
+ intx = ((spline->splines[0].a*t+spline->splines[0].b)*t+spline->splines[0].c-slpx)*t + spline->splines[0].d;
+ inty = ((spline->splines[1].a*t+spline->splines[1].b)*t+spline->splines[1].c-slpy)*t + spline->splines[1].d;
+ tx = SolveCubicBack(spline->splines[0].a,spline->splines[0].b,spline->splines[0].c-slpx,spline->splines[0].d-intx,.5/scale,t);
+ ty = SolveCubicBack(spline->splines[1].a,spline->splines[1].b,spline->splines[1].c-slpy,spline->splines[1].d-inty,.5/scale,t);
+ t = (tx>ty)?tx:ty;
+ cur = chunkalloc(sizeof(LineList) );
+ cur->here.x = rint( (((spline->splines[0].a*t+spline->splines[0].b)*t+spline->splines[0].c)*t + spline->splines[0].d)*scale );
+ cur->here.y = rint( (((spline->splines[1].a*t+spline->splines[1].b)*t+spline->splines[1].c)*t + spline->splines[1].d)*scale );
+ cur->next = prev;
+ prev = cur;
+ if ( t<=.5 )
+ break;
+ }
+ last->next = cur;
+ SimplifyLineList(test->lines);
+ }
+ if ( test->lines->next==NULL ) {
+ test->oneline = 1;
+ test->onepoint = 1;
+ } else if ( test->lines->next->next == NULL ) {
+ test->oneline = 1;
+ }
+return( test );
+}
+
+static void SplineFindBounds(const Spline *sp, DBounds *bounds) {
+ real t, b2_fourac, v;
+ real min, max;
+ const Spline1D *sp1;
+ int i;
+
+ /* first try the end points */
+ for ( i=0; i<2; ++i ) {
+ sp1 = &sp->splines[i];
+ if ( i==0 ) {
+ if ( sp->to->me.x<bounds->minx ) bounds->minx = sp->to->me.x;
+ if ( sp->to->me.x>bounds->maxx ) bounds->maxx = sp->to->me.x;
+ min = bounds->minx; max = bounds->maxx;
+ } else {
+ if ( sp->to->me.y<bounds->miny ) bounds->miny = sp->to->me.y;
+ if ( sp->to->me.y>bounds->maxy ) bounds->maxy = sp->to->me.y;
+ min = bounds->miny; max = bounds->maxy;
+ }
+
+ /* then try the extrema of the spline (assuming they are between t=(0,1) */
+ /* (I don't bother fixing up for tiny rounding errors here. they don't matter */
+ /* But we could call CheckExtremaForSingleBitErrors */
+ if ( sp1->a!=0 ) {
+ b2_fourac = 4*sp1->b*sp1->b - 12*sp1->a*sp1->c;
+ if ( b2_fourac>=0 ) {
+ b2_fourac = sqrt(b2_fourac);
+ t = (-2*sp1->b + b2_fourac) / (6*sp1->a);
+ if ( t>0 && t<1 ) {
+ v = ((sp1->a*t+sp1->b)*t+sp1->c)*t + sp1->d;
+ if ( v<min ) min = v;
+ if ( v>max ) max = v;
+ }
+ t = (-2*sp1->b - b2_fourac) / (6*sp1->a);
+ if ( t>0 && t<1 ) {
+ v = ((sp1->a*t+sp1->b)*t+sp1->c)*t + sp1->d;
+ if ( v<min ) min = v;
+ if ( v>max ) max = v;
+ }
+ }
+ } else if ( sp1->b!=0 ) {
+ t = -sp1->c/(2.0*sp1->b);
+ if ( t>0 && t<1 ) {
+ v = (sp1->b*t+sp1->c)*t + sp1->d;
+ if ( v<min ) min = v;
+ if ( v>max ) max = v;
+ }
+ }
+ if ( i==0 ) {
+ bounds->minx = min; bounds->maxx = max;
+ } else {
+ bounds->miny = min; bounds->maxy = max;
+ }
+ }
+}
+
+static void _SplineSetFindBounds(const SplinePointList *spl, DBounds *bounds) {
+ Spline *spline, *first;
+ /* Ignore contours consisting of a single point (used for hinting, anchors */
+ /* for mark to base, etc. */
+
+ for ( ; spl!=NULL; spl = spl->next ) if ( spl->first->next!=NULL && spl->first->next->to != spl->first ) {
+ first = NULL;
+ if ( bounds->minx==0 && bounds->maxx==0 && bounds->miny==0 && bounds->maxy == 0 ) {
+ bounds->minx = bounds->maxx = spl->first->me.x;
+ bounds->miny = bounds->maxy = spl->first->me.y;
+ } else {
+ if ( spl->first->me.x<bounds->minx ) bounds->minx = spl->first->me.x;
+ if ( spl->first->me.x>bounds->maxx ) bounds->maxx = spl->first->me.x;
+ if ( spl->first->me.y<bounds->miny ) bounds->miny = spl->first->me.y;
+ if ( spl->first->me.y>bounds->maxy ) bounds->maxy = spl->first->me.y;
+ }
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) {
+ SplineFindBounds(spline,bounds);
+ if ( first==NULL ) first = spline;
+ }
+ }
+}
+
+void SplineSetFindBounds(const SplinePointList *spl, DBounds *bounds) {
+ memset(bounds,'\0',sizeof(*bounds));
+ _SplineSetFindBounds(spl,bounds);
+}
+
+#ifdef FONTFORGE_CONFIG_TYPE3
+static void _ImageFindBounds(ImageList *img,DBounds *bounds) {
+ if ( bounds->minx==0 && bounds->maxx==0 && bounds->miny==0 && bounds->maxy == 0 )
+ *bounds = img->bb;
+ else if ( img->bb.minx!=0 || img->bb.maxx != 0 || img->bb.maxy != 0 || img->bb.miny!=0 ) {
+ if ( img->bb.minx < bounds->minx ) bounds->minx = img->bb.minx;
+ if ( img->bb.miny < bounds->miny ) bounds->miny = img->bb.miny;
+ if ( img->bb.maxx > bounds->maxx ) bounds->maxx = img->bb.maxx;
+ if ( img->bb.maxy > bounds->maxy ) bounds->maxy = img->bb.maxy;
+ }
+}
+#endif
+
+void SplineCharFindBounds(SplineChar *sc,DBounds *bounds) {
+ RefChar *rf;
+ int i;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ ImageList *img;
+ real e;
+ DBounds b;
+#endif
+
+ /* a char with no splines (ie. a space) must have an lbearing of 0 */
+ bounds->minx = bounds->maxx = 0;
+ bounds->miny = bounds->maxy = 0;
+
+ for ( i=ly_fore; i<sc->layer_cnt; ++i ) {
+ for ( rf=sc->layers[i].refs; rf!=NULL; rf = rf->next ) {
+ if ( bounds->minx==0 && bounds->maxx==0 && bounds->miny==0 && bounds->maxy == 0 )
+ *bounds = rf->bb;
+ else if ( rf->bb.minx!=0 || rf->bb.maxx != 0 || rf->bb.maxy != 0 || rf->bb.miny!=0 ) {
+ if ( rf->bb.minx < bounds->minx ) bounds->minx = rf->bb.minx;
+ if ( rf->bb.miny < bounds->miny ) bounds->miny = rf->bb.miny;
+ if ( rf->bb.maxx > bounds->maxx ) bounds->maxx = rf->bb.maxx;
+ if ( rf->bb.maxy > bounds->maxy ) bounds->maxy = rf->bb.maxy;
+ }
+ }
+#ifdef FONTFORGE_CONFIG_TYPE3
+ memset(&b,0,sizeof(b));
+ _SplineSetFindBounds(sc->layers[i].splines,&b);
+ for ( img=sc->layers[i].images; img!=NULL; img=img->next )
+ _ImageFindBounds(img,bounds);
+ if ( sc->layers[i].dostroke ) {
+ if ( sc->layers[i].stroke_pen.width!=WIDTH_INHERITED )
+ e = sc->layers[i].stroke_pen.width*sc->layers[i].stroke_pen.trans[0];
+ else
+ e = sc->layers[i].stroke_pen.trans[0];
+ b.minx -= e; b.maxx += e;
+ b.miny -= e; b.maxy += e;
+ }
+ if ( bounds->minx==0 && bounds->maxx==0 && bounds->miny==0 && bounds->maxy == 0 )
+ *bounds = b;
+ else if ( b.minx!=0 || b.maxx != 0 || b.maxy != 0 || b.miny!=0 ) {
+ if ( b.minx < bounds->minx ) bounds->minx = b.minx;
+ if ( b.miny < bounds->miny ) bounds->miny = b.miny;
+ if ( b.maxx > bounds->maxx ) bounds->maxx = b.maxx;
+ if ( b.maxy > bounds->maxy ) bounds->maxy = b.maxy;
+ }
+#else
+ _SplineSetFindBounds(sc->layers[i].splines,bounds);
+#endif
+ }
+ if ( sc->parent!=NULL && sc->parent->strokedfont &&
+ (bounds->minx!=bounds->maxx || bounds->miny!=bounds->maxy)) {
+ real sw = sc->parent->strokewidth;
+ bounds->minx -= sw; bounds->miny -= sw;
+ bounds->maxx += sw; bounds->maxy += sw;
+ }
+}
+
+void SplineFontFindBounds(SplineFont *sf,DBounds *bounds) {
+ RefChar *rf;
+ int i, k;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ real extra=0,e;
+ ImageList *img;
+#endif
+
+ bounds->minx = bounds->maxx = 0;
+ bounds->miny = bounds->maxy = 0;
+
+ for ( i = 0; i<sf->glyphcnt; ++i ) {
+ SplineChar *sc = sf->glyphs[i];
+ if ( sc!=NULL ) {
+ for ( k=ly_fore; k<sc->layer_cnt; ++k ) {
+ for ( rf=sc->layers[k].refs; rf!=NULL; rf = rf->next ) {
+ if ( bounds->minx==0 && bounds->maxx==0 && bounds->miny==0 && bounds->maxy == 0 )
+ *bounds = rf->bb;
+ else if ( rf->bb.minx!=0 || rf->bb.maxx != 0 || rf->bb.maxy != 0 || rf->bb.miny!=0 ) {
+ if ( rf->bb.minx < bounds->minx ) bounds->minx = rf->bb.minx;
+ if ( rf->bb.miny < bounds->miny ) bounds->miny = rf->bb.miny;
+ if ( rf->bb.maxx > bounds->maxx ) bounds->maxx = rf->bb.maxx;
+ if ( rf->bb.maxy > bounds->maxy ) bounds->maxy = rf->bb.maxy;
+ }
+ }
+
+ _SplineSetFindBounds(sc->layers[k].splines,bounds);
+#ifdef FONTFORGE_CONFIG_TYPE3
+ for ( img=sc->layers[k].images; img!=NULL; img=img->next )
+ _ImageFindBounds(img,bounds);
+ if ( sc->layers[k].dostroke ) {
+ if ( sc->layers[k].stroke_pen.width!=WIDTH_INHERITED )
+ e = sc->layers[k].stroke_pen.width*sc->layers[k].stroke_pen.trans[0];
+ else
+ e = sc->layers[k].stroke_pen.trans[0];
+ if ( e>extra ) extra = e;
+ }
+#endif
+ }
+ }
+ }
+#ifdef FONTFORGE_CONFIG_TYPE3
+ bounds->minx -= extra; bounds->miny -= extra;
+ bounds->maxx += extra; bounds->maxy += extra;
+#endif
+}
+
+void CIDFindBounds(SplineFont *cidmaster,DBounds *bounds) {
+ SplineFont *sf;
+ int i;
+ DBounds b;
+ real factor;
+
+ if ( cidmaster->cidmaster )
+ cidmaster = cidmaster->cidmaster;
+ if ( cidmaster->subfonts==NULL ) {
+ SplineFontFindBounds(cidmaster,bounds);
+return;
+ }
+
+ sf = cidmaster->subfonts[0];
+ SplineFontFindBounds(sf,bounds);
+ factor = 1000.0/(sf->ascent+sf->descent);
+ bounds->maxx *= factor; bounds->minx *= factor; bounds->miny *= factor; bounds->maxy *= factor;
+ for ( i=1; i<cidmaster->subfontcnt; ++i ) {
+ sf = cidmaster->subfonts[i];
+ SplineFontFindBounds(sf,&b);
+ factor = 1000.0/(sf->ascent+sf->descent);
+ b.maxx *= factor; b.minx *= factor; b.miny *= factor; b.maxy *= factor;
+ if ( b.maxx>bounds->maxx ) bounds->maxx = b.maxx;
+ if ( b.maxy>bounds->maxy ) bounds->maxy = b.maxy;
+ if ( b.miny<bounds->miny ) bounds->miny = b.miny;
+ if ( b.minx<bounds->minx ) bounds->minx = b.minx;
+ }
+}
+
+static void _SplineSetFindTop(SplineSet *ss,BasePoint *top) {
+ SplinePoint *sp;
+
+ for ( ; ss!=NULL; ss=ss->next ) {
+ for ( sp=ss->first; ; ) {
+ if ( sp->me.y > top->y ) *top = sp->me;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ }
+}
+
+#ifndef FONTFORGE_CONFIG_TYPE3
+static void SplineSetFindTop(SplineSet *ss,BasePoint *top) {
+
+ top->y = -1e10;
+ _SplineSetFindTop(ss,top);
+ if ( top->y < -65536 ) top->y = top->x = 0;
+}
+#endif
+
+void SplineSetQuickBounds(SplineSet *ss,DBounds *b) {
+ SplinePoint *sp;
+
+ b->minx = b->miny = 1e10;
+ b->maxx = b->maxy = -1e10;
+ for ( ; ss!=NULL; ss=ss->next ) {
+ for ( sp=ss->first; ; ) {
+ if ( sp->me.y < b->miny ) b->miny = sp->me.y;
+ if ( sp->me.x < b->minx ) b->minx = sp->me.x;
+ if ( sp->me.y > b->maxy ) b->maxy = sp->me.y;
+ if ( sp->me.x > b->maxx ) b->maxx = sp->me.x;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ }
+ if ( b->minx>65536 ) b->minx = 0;
+ if ( b->miny>65536 ) b->miny = 0;
+ if ( b->maxx<-65536 ) b->maxx = 0;
+ if ( b->maxy<-65536 ) b->maxy = 0;
+}
+
+void SplineCharQuickBounds(SplineChar *sc, DBounds *b) {
+ RefChar *ref;
+ int i;
+ DBounds temp;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ real e;
+ ImageList *img;
+#endif
+
+ memset(b,0,sizeof(*b));
+ for ( i=ly_fore; i<sc->layer_cnt; ++i ) {
+ SplineSetQuickBounds(sc->layers[i].splines,&temp);
+#ifdef FONTFORGE_CONFIG_TYPE3
+ for ( img=sc->layers[i].images; img!=NULL; img=img->next )
+ _ImageFindBounds(img,b);
+ if ( sc->layers[i].dostroke && sc->layers[i].splines!=NULL ) {
+ if ( sc->layers[i].stroke_pen.width!=WIDTH_INHERITED )
+ e = sc->layers[i].stroke_pen.width*sc->layers[i].stroke_pen.trans[0];
+ else
+ e = sc->layers[i].stroke_pen.trans[0];
+ temp.minx -= e; temp.maxx += e;
+ temp.miny -= e; temp.maxy += e;
+ }
+#endif
+ if ( temp.minx!=0 || temp.maxx != 0 || temp.maxy != 0 || temp.miny!=0 ) {
+ if ( temp.minx < b->minx ) b->minx = temp.minx;
+ if ( temp.miny < b->miny ) b->miny = temp.miny;
+ if ( temp.maxx > b->maxx ) b->maxx = temp.maxx;
+ if ( temp.maxy > b->maxy ) b->maxy = temp.maxy;
+ }
+ for ( ref = sc->layers[i].refs; ref!=NULL; ref = ref->next ) {
+ /*SplineSetQuickBounds(ref->layers[0].splines,&temp);*/
+ if ( b->minx==0 && b->maxx==0 && b->miny==0 && b->maxy == 0 )
+ *b = ref->bb;
+ else if ( ref->bb.minx!=0 || ref->bb.maxx != 0 || ref->bb.maxy != 0 || ref->bb.miny!=0 ) {
+ if ( ref->bb.minx < b->minx ) b->minx = ref->bb.minx;
+ if ( ref->bb.miny < b->miny ) b->miny = ref->bb.miny;
+ if ( ref->bb.maxx > b->maxx ) b->maxx = ref->bb.maxx;
+ if ( ref->bb.maxy > b->maxy ) b->maxy = ref->bb.maxy;
+ }
+ }
+ }
+ if ( sc->parent->strokedfont && (b->minx!=b->maxx || b->miny!=b->maxy)) {
+ real sw = sc->parent->strokewidth;
+ b->minx -= sw; b->miny -= sw;
+ b->maxx += sw; b->maxy += sw;
+ }
+}
+
+void SplineSetQuickConservativeBounds(SplineSet *ss,DBounds *b) {
+ SplinePoint *sp;
+
+ b->minx = b->miny = 1e10;
+ b->maxx = b->maxy = -1e10;
+ for ( ; ss!=NULL; ss=ss->next ) {
+ for ( sp=ss->first; ; ) {
+ if ( sp->me.y < b->miny ) b->miny = sp->me.y;
+ if ( sp->me.x < b->minx ) b->minx = sp->me.x;
+ if ( sp->me.y > b->maxy ) b->maxy = sp->me.y;
+ if ( sp->me.x > b->maxx ) b->maxx = sp->me.x;
+ if ( sp->nextcp.y < b->miny ) b->miny = sp->nextcp.y;
+ if ( sp->nextcp.x < b->minx ) b->minx = sp->nextcp.x;
+ if ( sp->nextcp.y > b->maxy ) b->maxy = sp->nextcp.y;
+ if ( sp->nextcp.x > b->maxx ) b->maxx = sp->nextcp.x;
+ if ( sp->prevcp.y < b->miny ) b->miny = sp->prevcp.y;
+ if ( sp->prevcp.x < b->minx ) b->minx = sp->prevcp.x;
+ if ( sp->prevcp.y > b->maxy ) b->maxy = sp->prevcp.y;
+ if ( sp->prevcp.x > b->maxx ) b->maxx = sp->prevcp.x;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ }
+ if ( b->minx>65536 ) b->minx = 0;
+ if ( b->miny>65536 ) b->miny = 0;
+ if ( b->maxx<-65536 ) b->maxx = 0;
+ if ( b->maxy<-65536 ) b->maxy = 0;
+}
+
+void SplineCharQuickConservativeBounds(SplineChar *sc, DBounds *b) {
+ RefChar *ref;
+ int i;
+ DBounds temp;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ real e;
+ ImageList *img;
+#endif
+
+ memset(b,0,sizeof(*b));
+ for ( i=ly_fore; i<sc->layer_cnt; ++i ) {
+ SplineSetQuickConservativeBounds(sc->layers[i].splines,&temp);
+#ifdef FONTFORGE_CONFIG_TYPE3
+ for ( img=sc->layers[i].images; img!=NULL; img=img->next )
+ _ImageFindBounds(img,b);
+ if ( sc->layers[i].dostroke && sc->layers[i].splines!=NULL ) {
+ if ( sc->layers[i].stroke_pen.width!=WIDTH_INHERITED )
+ e = sc->layers[i].stroke_pen.width*sc->layers[i].stroke_pen.trans[0];
+ else
+ e = sc->layers[i].stroke_pen.trans[0];
+ temp.minx -= e; temp.maxx += e;
+ temp.miny -= e; temp.maxy += e;
+ }
+#endif
+ if ( temp.minx!=0 || temp.maxx != 0 || temp.maxy != 0 || temp.miny!=0 ) {
+ if ( temp.minx < b->minx ) b->minx = temp.minx;
+ if ( temp.miny < b->miny ) b->miny = temp.miny;
+ if ( temp.maxx > b->maxx ) b->maxx = temp.maxx;
+ if ( temp.maxy > b->maxy ) b->maxy = temp.maxy;
+ }
+ for ( ref = sc->layers[i].refs; ref!=NULL; ref = ref->next ) {
+ /*SplineSetQuickConservativeBounds(ref->layers[0].splines,&temp);*/
+ if ( b->minx==0 && b->maxx==0 && b->miny==0 && b->maxy == 0 )
+ *b = ref->bb;
+ else if ( ref->bb.minx!=0 || ref->bb.maxx != 0 || ref->bb.maxy != 0 || ref->bb.miny!=0 ) {
+ if ( ref->bb.minx < b->minx ) b->minx = ref->bb.minx;
+ if ( ref->bb.miny < b->miny ) b->miny = ref->bb.miny;
+ if ( ref->bb.maxx > b->maxx ) b->maxx = ref->bb.maxx;
+ if ( ref->bb.maxy > b->maxy ) b->maxy = ref->bb.maxy;
+ }
+ }
+ }
+ if ( sc->parent->strokedfont && (b->minx!=b->maxx || b->miny!=b->maxy)) {
+ real sw = sc->parent->strokewidth;
+ b->minx -= sw; b->miny -= sw;
+ b->maxx += sw; b->maxy += sw;
+ }
+}
+
+void SplineFontQuickConservativeBounds(SplineFont *sf,DBounds *b) {
+ DBounds bb;
+ int i;
+
+ b->minx = b->miny = 1e10;
+ b->maxx = b->maxy = -1e10;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ SplineCharQuickConservativeBounds(sf->glyphs[i],&bb);
+ if ( bb.minx < b->minx ) b->minx = bb.minx;
+ if ( bb.miny < b->miny ) b->miny = bb.miny;
+ if ( bb.maxx > b->maxx ) b->maxx = bb.maxx;
+ if ( bb.maxy > b->maxy ) b->maxy = bb.maxy;
+ }
+ if ( b->minx>65536 ) b->minx = 0;
+ if ( b->miny>65536 ) b->miny = 0;
+ if ( b->maxx<-65536 ) b->maxx = 0;
+ if ( b->maxy<-65536 ) b->maxy = 0;
+}
+
+void SplinePointCatagorize(SplinePoint *sp) {
+
+ sp->pointtype = pt_corner;
+ if ( sp->next==NULL && sp->prev==NULL )
+ ;
+ else if ( (sp->next!=NULL && sp->next->to->me.x==sp->me.x && sp->next->to->me.y==sp->me.y) ||
+ (sp->prev!=NULL && sp->prev->from->me.x==sp->me.x && sp->prev->from->me.y==sp->me.y ))
+ ;
+ else if ( sp->next==NULL ) {
+ sp->pointtype = sp->noprevcp ? pt_corner : pt_curve;
+ } else if ( sp->prev==NULL ) {
+ sp->pointtype = sp->nonextcp ? pt_corner : pt_curve;
+ } else if ( sp->nonextcp && sp->noprevcp ) {
+ ;
+ } else {
+ BasePoint ndir, ncdir, pdir, pcdir;
+ double nlen, nclen, plen, pclen;
+ double slop;
+ double minlen;
+
+ ncdir.x = sp->nextcp.x - sp->me.x; ncdir.y = sp->nextcp.y - sp->me.y;
+ pcdir.x = sp->prevcp.x - sp->me.x; pcdir.y = sp->prevcp.y - sp->me.y;
+ ndir.x = ndir.y = pdir.x = pdir.y = 0;
+ if ( sp->next!=NULL ) {
+ ndir.x = sp->next->to->me.x - sp->me.x; ndir.y = sp->next->to->me.y - sp->me.y;
+ }
+ if ( sp->prev!=NULL ) {
+ pdir.x = sp->prev->from->me.x - sp->me.x; pdir.y = sp->prev->from->me.y - sp->me.y;
+ }
+ nclen = sqrt(ncdir.x*ncdir.x + ncdir.y*ncdir.y);
+ pclen = sqrt(pcdir.x*pcdir.x + pcdir.y*pcdir.y);
+ nlen = sqrt(ndir.x*ndir.x + ndir.y*ndir.y);
+ plen = sqrt(pdir.x*pdir.x + pdir.y*pdir.y);
+ if ( nclen!=0 ) { ncdir.x /= nclen; ncdir.y /= nclen; }
+ if ( pclen!=0 ) { pcdir.x /= pclen; pcdir.y /= pclen; }
+ if ( nlen!=0 ) { ndir.x /= nlen; ndir.y /= nlen; }
+ if ( plen!=0 ) { pdir.x /= plen; pdir.y /= plen; }
+ /* as the cp gets closer to the base point (being bound to integer */
+ /* coordinates in many cases) we need to be less precise in our defn */
+ /* of colinear. */
+ if ( pclen>=1 && nclen>=1 )
+ minlen = pclen<nclen ? pclen : nclen;
+ else if ( pclen>=1 )
+ minlen = pclen;
+ else
+ minlen = nclen;
+ if ( minlen<2 )
+ slop = -.95;
+ else if ( minlen<5 )
+ slop = -.98;
+ else
+ slop = -.99;
+ if ( nclen!=0 && pclen!=0 && ncdir.x*pcdir.x+ncdir.y*pcdir.y<slop )
+ sp->pointtype = pt_curve;
+ else if (( nclen!=0 || plen!=0 ) &&
+ (nclen==0 || ncdir.x*pdir.x+ncdir.y*pdir.y<slop ) &&
+ (pclen==0 || ndir.x*pcdir.x+ndir.y*pcdir.y<slop ))
+ sp->pointtype = pt_tangent;
+ }
+}
+
+int SplinePointIsACorner(SplinePoint *sp) {
+ enum pointtype old = sp->pointtype, new;
+
+ SplinePointCatagorize(sp);
+ new = sp->pointtype;
+ sp->pointtype = old;
+return( new==pt_corner );
+}
+
+void SPLCatagorizePoints(SplinePointList *spl) {
+ Spline *spline, *first, *last=NULL;
+
+ for ( ; spl!=NULL; spl = spl->next ) {
+ first = NULL;
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) {
+ SplinePointCatagorize(spline->from);
+ last = spline;
+ if ( first==NULL ) first = spline;
+ }
+ if ( spline==NULL && last!=NULL )
+ SplinePointCatagorize(last->to);
+ }
+}
+
+void SCCatagorizePoints(SplineChar *sc) {
+#ifdef FONTFORGE_CONFIG_TYPE3
+ int i;
+ for ( i=ly_fore; i<sc->layer_cnt; ++i )
+ SPLCatagorizePoints(sc->layers[i].splines);
+#else
+ SPLCatagorizePoints(sc->layers[ly_fore].splines);
+#endif
+}
+
+static int CharsNotInEncoding(FontDict *fd) {
+ int i, cnt, j;
+
+ for ( i=cnt=0; i<fd->chars->cnt; ++i ) {
+ if ( fd->chars->keys[i]!=NULL ) {
+ for ( j=0; j<256; ++j )
+ if ( fd->encoding[j]!=NULL &&
+ strcmp(fd->encoding[j],fd->chars->keys[i])==0 )
+ break;
+ if ( j==256 )
+ ++cnt;
+ }
+ }
+ /* And for type 3 fonts... */
+ if ( fd->charprocs!=NULL ) for ( i=0; i<fd->charprocs->cnt; ++i ) {
+ if ( fd->charprocs->keys[i]!=NULL ) {
+ for ( j=0; j<256; ++j )
+ if ( fd->encoding[j]!=NULL &&
+ strcmp(fd->encoding[j],fd->charprocs->keys[i])==0 )
+ break;
+ if ( j==256 )
+ ++cnt;
+ }
+ }
+return( cnt );
+}
+
+static int LookupCharString(char *encname,struct pschars *chars) {
+ int k;
+
+ if ( encname==NULL ) encname = ".notdef"; /* In case of an incomplete encoding array */
+
+ for ( k=0; k<chars->cnt; ++k ) {
+ if ( chars->keys[k]!=NULL )
+ if ( strcmp(encname,chars->keys[k])==0 )
+return( k );
+ }
+return( -1 );
+}
+
+SplinePointList *SplinePointListCopy1(const SplinePointList *spl) {
+ SplinePointList *cur;
+ const SplinePoint *pt; SplinePoint *cpt;
+ Spline *spline;
+
+ cur = chunkalloc(sizeof(SplinePointList));
+
+ for ( pt=spl->first; ; ) {
+ cpt = chunkalloc(sizeof(SplinePoint));
+ *cpt = *pt;
+ if ( pt->hintmask!=NULL ) {
+ cpt->hintmask = chunkalloc(sizeof(HintMask));
+ memcpy(cpt->hintmask,pt->hintmask,sizeof(HintMask));
+ }
+ cpt->next = cpt->prev = NULL;
+ if ( cur->first==NULL )
+ cur->first = cur->last = cpt;
+ else {
+ spline = chunkalloc(sizeof(Spline));
+ *spline = *pt->prev;
+ spline->from = cur->last;
+ cur->last->next = spline;
+ cpt->prev = spline;
+ spline->to = cpt;
+ spline->approx = NULL;
+ cur->last = cpt;
+ }
+ if ( pt->next==NULL )
+ break;
+ pt = pt->next->to;
+ if ( pt==spl->first )
+ break;
+ }
+ if ( spl->first->prev!=NULL ) {
+ cpt = cur->first;
+ spline = chunkalloc(sizeof(Spline));
+ *spline = *pt->prev;
+ spline->from = cur->last;
+ cur->last->next = spline;
+ cpt->prev = spline;
+ spline->to = cpt;
+ spline->approx = NULL;
+ cur->last = cpt;
+ }
+return( cur );
+}
+
+/* If this routine is called we are guarenteed that:
+ at least one point on the splineset is selected
+ not all points on the splineset are selected
+*/
+static SplinePointList *SplinePointListCopySelected1(SplinePointList *spl) {
+ SplinePointList *head=NULL, *last=NULL, *cur;
+ SplinePoint *cpt, *first, *start;
+ Spline *spline;
+
+ start = spl->first;
+ if ( spl->first==spl->last ) {
+ /* If it's a circle and the start point is selected then we don't know*/
+ /* where that selection began (and we have to keep it with the things*/
+ /* that precede it when we make the new splinesets), so loop until we*/
+ /* find something unselected */
+ while ( start->selected )
+ start = start->next->to;
+ }
+ first = NULL;
+ while ( start != NULL && start!=first ) {
+ while ( start!=NULL && start!=first && !start->selected ) {
+ if ( first==NULL ) first = start;
+ if ( start->next==NULL ) {
+ start = NULL;
+ break;
+ }
+ start = start->next->to;
+ }
+ if ( start==NULL || start==first )
+ break;
+ cur = chunkalloc(sizeof(SplinePointList));
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+
+ while ( start!=NULL && start->selected && start!=first ) {
+ cpt = chunkalloc(sizeof(SplinePoint));
+ *cpt = *start;
+ cpt->hintmask = NULL;
+ cpt->next = cpt->prev = NULL;
+ if ( cur->first==NULL )
+ cur->first = cur->last = cpt;
+ else {
+ spline = chunkalloc(sizeof(Spline));
+ *spline = *start->prev;
+ spline->from = cur->last;
+ cur->last->next = spline;
+ cpt->prev = spline;
+ spline->to = cpt;
+ spline->approx = NULL;
+ cur->last = cpt;
+ }
+ if ( first==NULL ) first = start;
+ if ( start->next==NULL ) {
+ start = NULL;
+ break;
+ }
+ start = start->next->to;
+ }
+ }
+return( head );
+}
+
+SplinePointList *SplinePointListCopy(const SplinePointList *base) {
+ SplinePointList *head=NULL, *last=NULL, *cur;
+
+ for ( ; base!=NULL; base = base->next ) {
+ cur = SplinePointListCopy1(base);
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ }
+return( head );
+}
+
+SplinePointList *SplinePointListCopySelected(SplinePointList *base) {
+ SplinePointList *head=NULL, *last=NULL, *cur=NULL;
+ SplinePoint *pt, *first;
+ int anysel, allsel;
+
+ for ( ; base!=NULL; base = base->next ) {
+ anysel = false; allsel = true;
+ first = NULL;
+ for ( pt=base->first; pt!=NULL && pt!=first; pt = pt->next->to ) {
+ if ( pt->selected ) anysel = true;
+ else allsel = false;
+ if ( first==NULL ) first = pt;
+ if ( pt->next==NULL )
+ break;
+ }
+ if ( allsel )
+ cur = SplinePointListCopy1(base);
+ else if ( anysel )
+ cur = SplinePointListCopySelected1(base);
+ if ( anysel ) {
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ for ( last = cur; last->next ; last = last->next );
+ }
+ }
+return( head );
+}
+
+static SplinePointList *SplinePointListSplit(SplineChar *sc,SplinePointList *spl) {
+ SplinePointList *head=NULL, *last=NULL, *cur;
+ SplinePoint *first, *start, *next;
+
+ start = spl->first;
+ if ( spl->first==spl->last ) {
+ /* If it's a circle and the start point isnt selected then we don't know*/
+ /* where that selection began (and we have to keep it with the things*/
+ /* that precede it when we make the new splinesets), so loop until we*/
+ /* find something selected */
+ while ( !start->selected )
+ start = start->next->to;
+ }
+ first = NULL;
+ while ( start != NULL && start!=first ) {
+ while ( start!=NULL && start!=first && start->selected ) {
+ if ( first==NULL ) first = start;
+ if ( start->prev!=NULL ) {
+ start->prev->from->next = NULL;
+ SplineFree(start->prev);
+ }
+ if ( start->next!=NULL ) {
+ next = start->next->to;
+ next->prev = NULL;
+ SplineFree(start->next);
+ } else
+ next = NULL;
+ SplinePointMDFree(sc,start);
+ start = next;
+ }
+ if ( start==NULL || start==first )
+ break;
+ if ( head==NULL ) {
+ head = cur = spl;
+ spl->first = spl->last = NULL;
+ } else {
+ cur = chunkalloc(sizeof(SplinePointList));
+ last->next = cur;
+ }
+ last = cur;
+
+ while ( start!=NULL && !start->selected && start!=first ) {
+ if ( cur->first==NULL )
+ cur->first = start;
+ cur->last = start;
+ if ( start->next!=NULL ) {
+ next = start->next->to;
+ if ( next->selected ) {
+ SplineFree(start->next);
+ start->next = NULL;
+ next->prev = NULL;
+ }
+ } else
+ next = NULL;
+ if ( first==NULL ) first = start;
+ start = next;
+ }
+ }
+return( last );
+}
+
+SplinePointList *SplinePointListRemoveSelected(SplineChar *sc,SplinePointList *base) {
+ SplinePointList *head=NULL, *last=NULL, *next;
+ SplinePoint *pt, *first;
+ int anysel, allsel;
+
+ for ( ; base!=NULL; base = next ) {
+ next = base->next;
+ anysel = false; allsel = true;
+ first = NULL;
+ for ( pt=base->first; pt!=NULL && pt!=first; pt = pt->next->to ) {
+ if ( pt->selected ) anysel = true;
+ else allsel = false;
+ if ( first==NULL ) first = pt;
+ if ( pt->next==NULL )
+ break;
+ }
+ if ( allsel ) {
+ SplinePointListMDFree(sc,base);
+ continue;
+ }
+ if ( head==NULL )
+ head = base;
+ else
+ last->next = base;
+ last = base;
+ if ( anysel )
+ last = SplinePointListSplit(sc,base);
+ }
+ if ( last!=NULL ) last->next = NULL;
+return( head );
+}
+
+ImageList *ImageListCopy(ImageList *cimg) {
+ ImageList *head=NULL, *last=NULL, *new;
+
+ for ( ; cimg!=NULL; cimg=cimg->next ) {
+ new = chunkalloc(sizeof(ImageList));
+ *new = *cimg;
+ new->next = NULL;
+ if ( last==NULL )
+ head = last = new;
+ else {
+ last->next = new;
+ last = new;
+ }
+ }
+return( head );
+}
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ImageList *ImageListTransform(ImageList *img, real transform[6]) {
+ ImageList *head = img;
+
+ /* Don't support rotating, flipping or skewing images */;
+ if ( transform[0]!=0 && transform[3]!=0 ) {
+ while ( img!=NULL ) {
+ double x = img->xoff;
+ img->xoff = transform[0]*x + transform[2]*img->yoff + transform[4];
+ img->yoff = transform[1]*x + transform[3]*img->yoff + transform[5];
+ if (( img->xscale *= transform[0])<0 ) {
+ img->xoff += img->xscale *
+ (img->image->list_len==0?img->image->u.image:img->image->u.images[0])->width;
+ img->xscale = -img->xscale;
+ }
+ if (( img->yscale *= transform[3])<0 ) {
+ img->yoff += img->yscale *
+ (img->image->list_len==0?img->image->u.image:img->image->u.images[0])->height;
+ img->yscale = -img->yscale;
+ }
+ img->bb.minx = img->xoff; img->bb.maxy = img->yoff;
+ img->bb.maxx = img->xoff + GImageGetWidth(img->image)*img->xscale;
+ img->bb.miny = img->yoff - GImageGetHeight(img->image)*img->yscale;
+ img = img->next;
+ }
+ }
+return( head );
+}
+#endif
+
+void ApTransform(AnchorPoint *ap, real transform[6]) {
+ BasePoint p;
+ p.x = transform[0]*ap->me.x + transform[2]*ap->me.y + transform[4];
+ p.y = transform[1]*ap->me.x + transform[3]*ap->me.y + transform[5];
+ ap->me.x = rint(1024*p.x)/1024;
+ ap->me.y = rint(1024*p.y)/1024;
+}
+
+static void TransformPoint(SplinePoint *sp, real transform[6]) {
+ BasePoint p;
+ p.x = transform[0]*sp->me.x + transform[2]*sp->me.y + transform[4];
+ p.y = transform[1]*sp->me.x + transform[3]*sp->me.y + transform[5];
+ p.x = rint(1024*p.x)/1024;
+ p.y = rint(1024*p.y)/1024;
+ sp->me = p;
+ if ( !sp->nonextcp ) {
+ p.x = transform[0]*sp->nextcp.x + transform[2]*sp->nextcp.y + transform[4];
+ p.y = transform[1]*sp->nextcp.x + transform[3]*sp->nextcp.y + transform[5];
+ p.x = rint(1024*p.x)/1024;
+ p.y = rint(1024*p.y)/1024;
+ sp->nextcp = p;
+ } else
+ sp->nextcp = sp->me;
+ if ( !sp->noprevcp ) {
+ p.x = transform[0]*sp->prevcp.x + transform[2]*sp->prevcp.y + transform[4];
+ p.y = transform[1]*sp->prevcp.x + transform[3]*sp->prevcp.y + transform[5];
+ p.x = rint(1024*p.x)/1024;
+ p.y = rint(1024*p.y)/1024;
+ sp->prevcp = p;
+ } else
+ sp->prevcp = sp->me;
+}
+
+SplinePointList *SplinePointListTransform(SplinePointList *base, real transform[6], int allpoints ) {
+ Spline *spline, *first;
+ SplinePointList *spl;
+ SplinePoint *spt, *pfirst;
+ int allsel, anysel, alldone=true;
+
+ for ( spl = base; spl!=NULL; spl = spl->next ) {
+ pfirst = NULL;
+ allsel = true; anysel=false;
+ for ( spt = spl->first ; spt!=pfirst; spt = spt->next->to ) {
+ if ( pfirst==NULL ) pfirst = spt;
+ if ( allpoints || spt->selected ) {
+ TransformPoint(spt,transform);
+ anysel = true;
+ } else
+ allsel = alldone = false;
+ if ( spt->next==NULL )
+ break;
+ }
+ if ( !anysel ) /* This splineset had no selected points it's unchanged */
+ continue;
+ /* if we changed all the points then the control points are right */
+ /* otherwise those near the edges may be wonky, fix 'em up */
+ /* Figuring out where the edges of the selection are is difficult */
+ /* so let's just tweak all points, it shouldn't matter */
+ /* It does matter. Let's tweak all default points */
+ if ( !allpoints && !allsel && spl->first->next!=NULL && !spl->first->next->order2 ) {
+ pfirst = NULL;
+ for ( spt = spl->first ; spt!=pfirst; spt = spt->next->to ) {
+ if ( pfirst==NULL ) pfirst = spt;
+ if ( spt->prev!=NULL && spt->prevcpdef )
+ SplineCharDefaultPrevCP(spt);
+ if ( spt->next==NULL )
+ break;
+ if ( spt->nextcpdef )
+ SplineCharDefaultNextCP(spt);
+ }
+ }
+ first = NULL;
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) {
+ if ( !alldone ) SplineRefigureFixup(spline); else SplineRefigure(spline);
+ if ( first==NULL ) first = spline;
+ }
+ }
+return( base );
+}
+
+SplinePointList *SplinePointListShift(SplinePointList *base,real xoff,int allpoints ) {
+ real transform[6];
+ if ( xoff==0 )
+return( base );
+ transform[0] = transform[3] = 1;
+ transform[1] = transform[2] = transform[5] = 0;
+ transform[4] = xoff;
+return( SplinePointListTransform(base,transform,allpoints));
+}
+
+HintMask *HintMaskFromTransformedRef(RefChar *ref,BasePoint *trans,
+ SplineChar *basesc,HintMask *hm) {
+ StemInfo *st, *st2;
+ int hst_cnt, bcnt;
+ real start, width;
+ int i;
+
+ if ( ref->transform[1]!=0 || ref->transform[2]!=0 )
+return(NULL);
+
+ memset(hm,0,sizeof(HintMask));
+ for ( st = ref->sc->hstem; st!=NULL; st=st->next ) {
+ start = st->start*ref->transform[3] + ref->transform[5] + trans->y;
+ width = st->width*ref->transform[3];
+ for ( st2=basesc->hstem,bcnt=0; st2!=NULL; st2=st2->next, bcnt++ )
+ if ( st2->start == start && st2->width == width )
+ break;
+ if ( st2!=NULL )
+ (*hm)[bcnt>>3] |= (0x80>>(bcnt&7));
+ }
+ for ( st2=basesc->hstem,hst_cnt=0; st2!=NULL; st2=st2->next, hst_cnt++ );
+
+ for ( st = ref->sc->vstem; st!=NULL; st=st->next ) {
+ start = st->start*ref->transform[0] + ref->transform[4] + trans->x;
+ width = st->width*ref->transform[0];
+ for ( st2=basesc->vstem,bcnt=hst_cnt; st2!=NULL; st2=st2->next, bcnt++ )
+ if ( st2->start == start && st2->width == width )
+ break;
+ if ( st2!=NULL )
+ (*hm)[bcnt>>3] |= (0x80>>(bcnt&7));
+ }
+ for ( i=0; i<HntMax/8; ++i )
+ if ( (*hm)[i]!=0 )
+return( hm );
+
+return( NULL );
+}
+
+static HintMask *HintMaskTransform(HintMask *oldhm,real transform[6],
+ SplineChar *basesc,SplineChar *subsc) {
+ HintMask *newhm;
+ StemInfo *st, *st2;
+ int cnt, hst_cnt, bcnt;
+ real start, width;
+
+ if ( transform[1]!=0 || transform[2]!=0 )
+return( NULL );
+
+ newhm = chunkalloc(sizeof(HintMask));
+ for ( st = subsc->hstem,cnt = 0; st!=NULL; st=st->next, cnt++ ) {
+ if ( (*oldhm)[cnt>>3]&(0x80>>(cnt&7)) ) {
+ start = st->start*transform[3] + transform[5];
+ width = st->width*transform[3];
+ for ( st2=basesc->hstem,bcnt=0; st2!=NULL; st2=st2->next, bcnt++ )
+ if ( st2->start == start && st2->width == width )
+ break;
+ if ( st2!=NULL )
+ (*newhm)[bcnt>>3] |= (0x80>>(bcnt&7));
+ }
+ }
+ for ( st2=basesc->hstem,hst_cnt=0; st2!=NULL; st2=st2->next, hst_cnt++ );
+
+ for ( st = subsc->vstem; st!=NULL; st=st->next, cnt++ ) {
+ if ( (*oldhm)[cnt>>3]&(0x80>>(cnt&7)) ) {
+ start = st->start*transform[0] + transform[4];
+ width = st->width*transform[0];
+ for ( st2=basesc->vstem,bcnt=hst_cnt; st2!=NULL; st2=st2->next, bcnt++ )
+ if ( st2->start == start && st2->width == width )
+ break;
+ if ( st2!=NULL )
+ (*newhm)[bcnt>>3] |= (0x80>>(bcnt&7));
+ }
+ }
+return( newhm );
+}
+
+SplinePointList *SPLCopyTranslatedHintMasks(SplinePointList *base,
+ SplineChar *basesc, SplineChar *subsc, BasePoint *trans ) {
+ SplinePointList *spl, *spl2, *head;
+ SplinePoint *spt, *spt2, *pfirst;
+ real transform[6];
+ Spline *s, *first;
+
+ head = SplinePointListCopy(base);
+
+ transform[0] = transform[3] = 1; transform[1] = transform[2] = 0;
+ transform[4] = trans->x; transform[5] = trans->y;
+
+ for ( spl = head, spl2=base; spl!=NULL; spl = spl->next, spl2 = spl2->next ) {
+ pfirst = NULL;
+ for ( spt = spl->first, spt2 = spl2->first ; spt!=pfirst; spt = spt->next->to, spt2 = spt2->next->to ) {
+ if ( pfirst==NULL ) pfirst = spt;
+ TransformPoint(spt,transform);
+ if ( spt2->hintmask ) {
+ chunkfree(spt->hintmask,sizeof(HintMask));
+ spt->hintmask = HintMaskTransform(spt2->hintmask,transform,basesc,subsc);
+ }
+ if ( spt->next==NULL )
+ break;
+ }
+ first = NULL;
+ for ( s = spl->first->next; s!=NULL && s!=first; s=s->to->next ) {
+ SplineRefigure(s);
+ if ( first==NULL ) first = s;
+ }
+ }
+return( head );
+}
+
+static SplinePointList *_SPLCopyTransformedHintMasks(SplineChar *subsc,real transform[6],
+ SplineChar *basesc ) {
+ SplinePointList *spl, *spl2, *head, *last=NULL, *cur, *base;
+ SplinePoint *spt, *spt2, *pfirst;
+ Spline *s, *first;
+ real trans[6];
+ RefChar *rf;
+
+ base = subsc->layers[ly_fore].splines;
+ head = SplinePointListCopy(base);
+ if ( head!=NULL )
+ for ( last = head; last->next!=NULL; last=last->next );
+
+ for ( spl = head, spl2=base; spl!=NULL; spl = spl->next, spl2=spl2->next ) {
+ pfirst = NULL;
+ for ( spt = spl->first, spt2 = spl2->first ; spt!=pfirst; spt = spt->next->to, spt2 = spt2->next->to ) {
+ if ( pfirst==NULL ) pfirst = spt;
+ TransformPoint(spt,transform);
+ if ( spt2->hintmask ) {
+ chunkfree(spt->hintmask,sizeof(HintMask));
+ spt->hintmask = HintMaskTransform(spt2->hintmask,transform,basesc,subsc);
+ }
+ if ( spt->next==NULL )
+ break;
+ }
+ first = NULL;
+ for ( s = spl->first->next; s!=NULL && s!=first; s=s->to->next ) {
+ SplineRefigure(s);
+ if ( first==NULL ) first = s;
+ }
+ }
+ for ( rf=subsc->layers[ly_fore].refs; rf!=NULL; rf=rf->next ) {
+ trans[0] = rf->transform[0]*transform[0] +
+ rf->transform[1]*transform[2];
+ trans[1] = rf->transform[0]*transform[1] +
+ rf->transform[1]*transform[3];
+ trans[2] = rf->transform[2]*transform[0] +
+ rf->transform[3]*transform[2];
+ trans[3] = rf->transform[2]*transform[1] +
+ rf->transform[3]*transform[3];
+ trans[4] = rf->transform[4]*transform[0] +
+ rf->transform[5]*transform[2] +
+ transform[4];
+ trans[5] = rf->transform[4]*transform[1] +
+ rf->transform[5]*transform[3] +
+ transform[5];
+ cur = _SPLCopyTransformedHintMasks(rf->sc,trans,basesc);
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ if ( cur!=NULL ) {
+ while ( cur->next!=NULL ) cur = cur->next;
+ last = cur;
+ }
+ }
+return( head );
+}
+
+SplinePointList *SPLCopyTransformedHintMasks(RefChar *r,
+ SplineChar *basesc, BasePoint *trans ) {
+ real transform[6];
+
+ memcpy(transform,r->transform,sizeof(transform));
+ transform[4] += trans->x; transform[5] += trans->y;
+return( _SPLCopyTransformedHintMasks(r->sc,transform,basesc));
+}
+
+void SplinePointListSelect(SplinePointList *spl,int sel) {
+ Spline *spline, *first;
+
+ for ( ; spl!=NULL; spl = spl->next ) {
+ first = NULL;
+ spl->first->selected = sel;
+ for ( spline = spl->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) {
+ spline->to->selected = sel;
+ if ( first==NULL ) first = spline;
+ }
+ }
+}
+
+void SCMakeDependent(SplineChar *dependent,SplineChar *base) {
+ struct splinecharlist *dlist;
+
+ if ( dependent->searcherdummy )
+return;
+
+ for ( dlist=base->dependents; dlist!=NULL && dlist->sc!=dependent; dlist = dlist->next);
+ if ( dlist==NULL ) {
+ dlist = chunkalloc(sizeof(struct splinecharlist));
+ dlist->sc = dependent;
+ dlist->next = base->dependents;
+ base->dependents = dlist;
+ }
+}
+
+static void InstanciateReference(SplineFont *sf, RefChar *topref, RefChar *refs,
+ real transform[6], SplineChar *dsc) {
+ real trans[6];
+ RefChar *rf;
+ SplineChar *rsc;
+ SplinePointList *spl, *new;
+ int i;
+
+ if ( !refs->checked ) {
+ if ( refs->sc!=NULL )
+ i = refs->sc->orig_pos; /* Can happen in type3 fonts */
+ else for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ if ( strcmp(sf->glyphs[i]->name,AdobeStandardEncoding[refs->adobe_enc])==0 )
+ break;
+ if ( i!=sf->glyphcnt && !sf->glyphs[i]->ticked ) {
+ refs->checked = true;
+ refs->sc = rsc = sf->glyphs[i];
+ refs->orig_pos = rsc->orig_pos;
+ refs->unicode_enc = rsc->unicodeenc;
+ SCMakeDependent(dsc,rsc);
+ } else {
+ LogError( _("Couldn't find referenced character \"%s\" in %s\n"),
+ AdobeStandardEncoding[refs->adobe_enc], dsc->name);
+return;
+ }
+ } else if ( refs->sc->ticked )
+return;
+
+ rsc = refs->sc;
+ rsc->ticked = true;
+
+ for ( rf=rsc->layers[ly_fore].refs; rf!=NULL; rf = rf->next ) {
+ trans[0] = rf->transform[0]*transform[0] +
+ rf->transform[1]*transform[2];
+ trans[1] = rf->transform[0]*transform[1] +
+ rf->transform[1]*transform[3];
+ trans[2] = rf->transform[2]*transform[0] +
+ rf->transform[3]*transform[2];
+ trans[3] = rf->transform[2]*transform[1] +
+ rf->transform[3]*transform[3];
+ trans[4] = rf->transform[4]*transform[0] +
+ rf->transform[5]*transform[2] +
+ transform[4];
+ trans[5] = rf->transform[4]*transform[1] +
+ rf->transform[5]*transform[3] +
+ transform[5];
+ InstanciateReference(sf,topref,rf,trans,rsc);
+ }
+ rsc->ticked = false;
+
+#ifdef FONTFORGE_CONFIG_TYPE3
+ if ( sf->multilayer ) {
+ int lbase = topref->layer_cnt;
+ if ( topref->layer_cnt==0 ) {
+ topref->layers = gcalloc(rsc->layer_cnt-1,sizeof(struct reflayer));
+ topref->layer_cnt = rsc->layer_cnt-1;
+ } else {
+ topref->layer_cnt += rsc->layer_cnt-1;
+ topref->layers = grealloc(topref->layers,topref->layer_cnt*sizeof(struct reflayer));
+ memset(topref->layers+lbase,0,(rsc->layer_cnt-1)*sizeof(struct reflayer));
+ }
+ for ( i=ly_fore; i<rsc->layer_cnt; ++i ) {
+ topref->layers[i-ly_fore+lbase].splines = SplinePointListTransform(SplinePointListCopy(rsc->layers[i].splines),transform,true);
+ topref->layers[i-ly_fore+lbase].fill_brush = rsc->layers[i].fill_brush;
+ topref->layers[i-ly_fore+lbase].stroke_pen = rsc->layers[i].stroke_pen;
+ topref->layers[i-ly_fore+lbase].dofill = rsc->layers[i].dofill;
+ topref->layers[i-ly_fore+lbase].dostroke = rsc->layers[i].dostroke;
+ topref->layers[i-ly_fore+lbase].fillfirst = rsc->layers[i].fillfirst;
+ /* ??? and images? Can't read images yet, so not a problem yet */
+ }
+ } else {
+ if ( topref->layer_cnt==0 ) {
+ topref->layers = gcalloc(1,sizeof(struct reflayer));
+ topref->layer_cnt = 1;
+ }
+#else
+ {
+#endif
+ new = SplinePointListTransform(SplinePointListCopy(rsc->layers[ly_fore].splines),transform,true);
+ if ( new!=NULL ) {
+ for ( spl = new; spl->next!=NULL; spl = spl->next );
+ spl->next = topref->layers[0].splines;
+ topref->layers[0].splines = new;
+ }
+ }
+}
+
+static char *copyparse(char *str) {
+ char *ret, *rpt;
+ int ch,i;
+
+ if ( str==NULL )
+return( str );
+
+ rpt=ret=galloc(strlen(str)+1);
+ while ( *str ) {
+ if ( *str=='\\' ) {
+ ++str;
+ if ( *str=='n' ) ch = '\n';
+ else if ( *str=='r' ) ch = '\r';
+ else if ( *str=='t' ) ch = '\t';
+ else if ( *str=='b' ) ch = '\b';
+ else if ( *str=='f' ) ch = '\f';
+ else if ( *str=='\\' ) ch = '\\';
+ else if ( *str=='(' ) ch = '(';
+ else if ( *str==')' ) ch = ')';
+ else if ( *str>='0' && *str<='7' ) {
+ for ( i=ch = 0; i<3 && *str>='0' && *str<='7'; ++i )
+ ch = (ch<<3) + *str++-'0';
+ --str;
+ } else
+ ch = *str;
+ ++str;
+ *rpt++ = ch;
+ } else
+ *rpt++ = *str++;
+ }
+ *rpt = '\0';
+ if ( !utf8_valid(ret)) {
+ /* Assume latin1, convert to utf8 */
+ rpt = latin1_2_utf8_copy(ret);
+ free(ret);
+ ret = rpt;
+ }
+return(ret);
+}
+
+char *XUIDFromFD(int xuid[20]) {
+ int i;
+ char *ret=NULL;
+
+ for ( i=19; i>=0 && xuid[i]==0; --i );
+ if ( i>=0 ) {
+ int j; char *pt;
+ ret = galloc(2+20*(i+1));
+ pt = ret;
+ *pt++ = '[';
+ for ( j=0; j<=i; ++j ) {
+ sprintf(pt,"%d ", xuid[j]);
+ pt += strlen(pt);
+ }
+ pt[-1] = ']';
+ }
+return( ret );
+}
+
+void SplineFontMetaData(SplineFont *sf,struct fontdict *fd) {
+ int em;
+
+ sf->fontname = utf8_verify_copy(fd->cidfontname?fd->cidfontname:fd->fontname);
+ sf->display_size = -default_fv_font_size;
+ sf->display_antialias = default_fv_antialias;
+ if ( fd->fontinfo!=NULL ) {
+ if ( sf->fontname==NULL && fd->fontinfo->fullname!=NULL ) {
+ sf->fontname = EnforcePostScriptName(fd->fontinfo->fullname);
+ }
+ if ( sf->fontname==NULL ) sf->fontname = EnforcePostScriptName(fd->fontinfo->familyname);
+ sf->fullname = copyparse(fd->fontinfo->fullname);
+ sf->familyname = copyparse(fd->fontinfo->familyname);
+ sf->weight = copyparse(fd->fontinfo->weight);
+ sf->version = copyparse(fd->fontinfo->version);
+ sf->copyright = copyparse(fd->fontinfo->notice);
+ sf->italicangle = fd->fontinfo->italicangle;
+ sf->upos = fd->fontinfo->underlineposition;
+ sf->uwidth = fd->fontinfo->underlinethickness;
+ sf->strokedfont = fd->painttype==2;
+ sf->strokewidth = fd->strokewidth;
+ sf->ascent = fd->fontinfo->ascent;
+ sf->descent = fd->fontinfo->descent;
+ }
+ if ( sf->uniqueid==0 ) sf->uniqueid = fd->uniqueid;
+ if ( sf->fontname==NULL ) sf->fontname = GetNextUntitledName();
+ if ( sf->fullname==NULL ) sf->fullname = copy(sf->fontname);
+ if ( sf->familyname==NULL ) sf->familyname = copy(sf->fontname);
+ if ( sf->weight==NULL ) sf->weight = copy("");
+ if ( fd->modificationtime!=0 ) {
+ sf->modificationtime = fd->modificationtime;
+ sf->creationtime = fd->creationtime;
+ }
+ sf->cidversion = fd->cidversion;
+ sf->xuid = XUIDFromFD(fd->xuid);
+ /*sf->wasbinary = fd->wasbinary;*/
+ if ( fd->fontmatrix[0]==0 )
+ em = 1000;
+ else
+ em = rint(1/fd->fontmatrix[0]);
+ if ( sf->ascent==0 && sf->descent!=0 )
+ sf->ascent = em-sf->descent;
+ else if ( fd->fontbb[3]-fd->fontbb[1]==em ) {
+ if ( sf->ascent==0 ) sf->ascent = fd->fontbb[3];
+ if ( sf->descent==0 ) sf->descent = fd->fontbb[1];
+ } else if ( sf->ascent==0 )
+ sf->ascent = 8*em/10;
+ sf->descent = em-sf->ascent;
+
+ sf->private = fd->private->private; fd->private->private = NULL;
+ PSDictRemoveEntry(sf->private, "OtherSubrs");
+
+ sf->cidregistry = copy(fd->registry);
+ sf->ordering = copy(fd->ordering);
+ sf->supplement = fd->supplement;
+ sf->pfminfo.fstype = fd->fontinfo->fstype;
+ if ( sf->ordering!=NULL ) {
+ if ( strnmatch(sf->ordering,"Japan",5)==0 )
+ sf->uni_interp = ui_japanese;
+ else if ( strnmatch(sf->ordering,"Korea",5)==0 )
+ sf->uni_interp = ui_korean;
+ else if ( strnmatch(sf->ordering,"CNS",3)==0 )
+ sf->uni_interp = ui_trad_chinese;
+ else if ( strnmatch(sf->ordering,"GB",2)==0 )
+ sf->uni_interp = ui_simp_chinese;
+ }
+}
+
+static void TransByFontMatrix(SplineFont *sf,real fontmatrix[6]) {
+ real trans[6];
+ int em = sf->ascent+sf->descent, i;
+ SplineChar *sc;
+ RefChar *refs;
+
+ if ( fontmatrix[0]==fontmatrix[3] &&
+ fontmatrix[1]==0 && fontmatrix[2]==0 &&
+ fontmatrix[4]==0 && fontmatrix[5]==0 )
+return; /* It's just the expected matrix */
+
+ trans[0] = 1;
+ if ( fontmatrix[0]==fontmatrix[3] ) trans[3] = 1;
+ else trans[3] = rint(fontmatrix[3]*em);
+ trans[1] = fontmatrix[1]*em;
+ trans[2] = fontmatrix[2]*em;
+ trans[4] = rint(fontmatrix[4]*em);
+ trans[5] = rint(fontmatrix[5]*em);
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL ) {
+ SplinePointListTransform(sc->layers[ly_fore].splines,trans,true);
+ for ( refs=sc->layers[ly_fore].refs; refs!=NULL; refs=refs->next ) {
+ /* Just scale the offsets. we'll do all the base characters */
+ real temp = refs->transform[4]*trans[0] +
+ refs->transform[5]*trans[2] +
+ /*transform[4]*/0;
+ refs->transform[5] = refs->transform[4]*trans[1] +
+ refs->transform[5]*trans[3] +
+ /*transform[5]*/0;
+ refs->transform[4] = temp;
+ }
+ sc->changedsincelasthinted = true;
+ sc->manualhints = false;
+ }
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL ) {
+ for ( refs=sc->layers[ly_fore].refs; refs!=NULL; refs=refs->next )
+ SCReinstanciateRefChar(sc,refs);
+ }
+}
+
+void SFInstanciateRefs(SplineFont *sf) {
+ int i, layer;
+ RefChar *refs, *next, *pr;
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ sf->glyphs[i]->ticked = false;
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ SplineChar *sc = sf->glyphs[i];
+
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ for ( pr=NULL, refs = sc->layers[layer].refs; refs!=NULL; refs=next ) {
+ next = refs->next;
+ sc->ticked = true;
+ InstanciateReference(sf, refs, refs, refs->transform,sc);
+ if ( refs->sc!=NULL ) {
+ SplineSetFindBounds(refs->layers[0].splines,&refs->bb);
+ sc->ticked = false;
+ pr = refs;
+ } else {
+ /* In some mal-formed postscript fonts we can have a reference */
+ /* to a character that is not actually in the font. I even */
+ /* generated one by mistake once... */
+ if ( pr==NULL )
+ sc->layers[layer].refs = next;
+ else
+ pr->next = next;
+ refs->next = NULL;
+ RefCharsFree(refs);
+ }
+ }
+ }
+ }
+}
+
+/* Also handles type3s */
+static void _SplineFontFromType1(SplineFont *sf, FontDict *fd, struct pscontext *pscontext) {
+ int i, j, notdefpos;
+ RefChar *refs, *next;
+ int istype2 = fd->fonttype==2; /* Easy enough to deal with even though it will never happen... */
+ int istype3 = fd->charprocs->next!=0;
+ EncMap *map;
+
+ if ( istype2 )
+ fd->private->subrs->bias = fd->private->subrs->cnt<1240 ? 107 :
+ fd->private->subrs->cnt<33900 ? 1131 : 32768;
+ sf->glyphmax = sf->glyphcnt = istype3 ? fd->charprocs->next : fd->chars->next;
+ if ( sf->map==NULL ) {
+ sf->map = map = EncMapNew(256+CharsNotInEncoding(fd),sf->glyphcnt,fd->encoding_name);
+ } else
+ map = sf->map;
+ sf->glyphs = gcalloc(map->backmax,sizeof(SplineChar *));
+#ifdef FONTFORGE_CONFIG_TYPE3
+ if ( istype3 ) /* We read a type3 */
+ sf->multilayer = true;
+#endif
+ if ( istype3 )
+ notdefpos = LookupCharString(".notdef",(struct pschars *) (fd->charprocs));
+ else
+ notdefpos = LookupCharString(".notdef",fd->chars);
+ for ( i=0; i<256; ++i ) {
+ int k;
+ if ( istype3 ) {
+ k = LookupCharString(fd->encoding[i],(struct pschars *) (fd->charprocs));
+ } else {
+ k = LookupCharString(fd->encoding[i],fd->chars);
+ }
+ if ( k==-1 ) k = notdefpos;
+ map->map[i] = k;
+ if ( k!=-1 && map->backmap[k]==-1 )
+ map->backmap[k] = i;
+ }
+ if ( map->enccount>256 ) {
+ int k, j;
+ for ( k=0; k<fd->chars->cnt; ++k ) {
+ if ( fd->chars->keys[k]!=NULL ) {
+ for ( j=0; j<256; ++j )
+ if ( fd->encoding[j]!=NULL &&
+ strcmp(fd->encoding[j],fd->chars->keys[k])==0 )
+ break;
+ if ( j==256 ) {
+ map->map[i] = k;
+ if ( map->backmap[k]==-1 )
+ map->backmap[k] = i;
+ ++i;
+ }
+ }
+ }
+ /* And for type3s */
+ for ( k=0; k<fd->charprocs->cnt; ++k ) {
+ if ( fd->charprocs->keys[k]!=NULL ) {
+ for ( j=0; j<256; ++j )
+ if ( fd->encoding[j]!=NULL &&
+ strcmp(fd->encoding[j],fd->charprocs->keys[k])==0 )
+ break;
+ if ( j==256 ) {
+ map->map[i] = k;
+ if ( map->backmap[k]==-1 )
+ map->backmap[k] = i;
+ ++i;
+ }
+ }
+ }
+ }
+ for ( i=0; i<map->enccount; ++i ) if ( map->map[i]==-1 )
+ map->map[i] = notdefpos;
+
+ for ( i=0; i<sf->glyphcnt; ++i ) {
+ if ( !istype3 )
+ sf->glyphs[i] = PSCharStringToSplines(fd->chars->values[i],fd->chars->lens[i],
+ pscontext,fd->private->subrs,NULL,fd->chars->keys[i]);
+ else
+ sf->glyphs[i] = fd->charprocs->values[i];
+ if ( sf->glyphs[i]!=NULL ) {
+ sf->glyphs[i]->orig_pos = i;
+ sf->glyphs[i]->vwidth = sf->ascent+sf->descent;
+ sf->glyphs[i]->unicodeenc = UniFromName(sf->glyphs[i]->name,sf->uni_interp,map->enc);
+ sf->glyphs[i]->parent = sf;
+ /* SCLigDefault(sf->glyphs[i]);*/ /* Also reads from AFM file, but it probably doesn't exist */
+ }
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ gwwv_progress_next();
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_progress_next();
+#endif
+ }
+ SFInstanciateRefs(sf);
+ if ( fd->metrics!=NULL ) {
+ for ( i=0; i<fd->metrics->next; ++i ) {
+ int width = strtol(fd->metrics->values[i],NULL,10);
+ for ( j=sf->glyphcnt-1; j>=0; --j ) {
+ if ( sf->glyphs[j]!=NULL && sf->glyphs[j]->name!=NULL &&
+ strcmp(fd->metrics->keys[i],sf->glyphs[j]->name)==0 ) {
+ sf->glyphs[j]->width = width;
+ break;
+ }
+ }
+ }
+ }
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ for ( refs = sf->glyphs[i]->layers[ly_fore].refs; refs!=NULL; refs=next ) {
+ next = refs->next;
+ if ( refs->adobe_enc==' ' && refs->layers[0].splines==NULL ) {
+ /* When I have a link to a single character I will save out a */
+ /* seac to that character and a space (since I can only make */
+ /* real char links), so if we find a space link, get rid of*/
+ /* it. It's an artifact */
+ SCRefToSplines(sf->glyphs[i],refs);
+ }
+ }
+ /* sometimes (some apple oblique fonts) the fontmatrix is not just a */
+ /* formality, it acutally contains a skew. So be ready */
+ if ( fd->fontmatrix[0]!=0 )
+ TransByFontMatrix(sf,fd->fontmatrix);
+ AltUniFigure(sf,sf->map);
+}
+
+static void SplineFontFromType1(SplineFont *sf, FontDict *fd, struct pscontext *pscontext) {
+ int i;
+ SplineChar *sc;
+
+ _SplineFontFromType1(sf,fd,pscontext);
+
+ /* Clean up the hint masks, We create an initial hintmask whether we need */
+ /* it or not */
+ for ( i=0; i<sf->glyphcnt; ++i ) {
+ if ( (sc = sf->glyphs[i])!=NULL && !sc->hconflicts && !sc->vconflicts &&
+ sc->layers[ly_fore].splines!=NULL ) {
+ chunkfree( sc->layers[ly_fore].splines->first->hintmask,sizeof(HintMask) );
+ sc->layers[ly_fore].splines->first->hintmask = NULL;
+ }
+ }
+}
+
+#ifndef LUA_FF_LIB
+static SplineFont *SplineFontFromMMType1(SplineFont *sf, FontDict *fd, struct pscontext *pscontext) {
+ char *pt, *end, *origweight;
+ MMSet *mm;
+ int ipos, apos, ppos, item, i;
+ real blends[12]; /* At most twelve points/axis in a blenddesignmap */
+ real designs[12];
+ EncMap *map;
+
+ if ( fd->weightvector==NULL || fd->fontinfo->blenddesignpositions==NULL ||
+ fd->fontinfo->blenddesignmap==NULL || fd->fontinfo->blendaxistypes==NULL ) {
+#if defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("Bad Multiple Master Font"),_("Bad Multiple Master Font"));
+#else
+ gwwv_post_error(_("Bad Multiple Master Font"),_("Bad Multiple Master Font"));
+#endif
+ SplineFontFree(sf);
+return( NULL );
+ }
+
+ mm = chunkalloc(sizeof(MMSet));
+
+ pt = fd->weightvector;
+ while ( *pt==' ' || *pt=='[' ) ++pt;
+ while ( *pt!=']' && *pt!='\0' ) {
+ pscontext->blend_values[ pscontext->instance_count ] =
+ strtod(pt,&end);
+ if ( pt==end )
+ break;
+ ++(pscontext->instance_count);
+ if ( pscontext->instance_count>=sizeof(pscontext->blend_values)/sizeof(pscontext->blend_values[0])) {
+ LogError( _("Multiple master font with more than 16 instances\n") );
+ break;
+ }
+ for ( pt = end; *pt==' '; ++pt );
+ }
+
+ mm->instance_count = pscontext->instance_count;
+ mm->instances = galloc(pscontext->instance_count*sizeof(SplineFont *));
+ mm->defweights = galloc(mm->instance_count*sizeof(real));
+ memcpy(mm->defweights,pscontext->blend_values,mm->instance_count*sizeof(real));
+ mm->normal = sf;
+ _SplineFontFromType1(mm->normal,fd,pscontext);
+ map = sf->map;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ sf->glyphs[i]->blended = true;
+ sf->mm = mm;
+
+ pt = fd->fontinfo->blendaxistypes;
+ while ( *pt==' ' || *pt=='[' ) ++pt;
+ while ( *pt!=']' && *pt!='\0' ) {
+ if ( *pt=='/' ) ++pt;
+ for ( end=pt; *end!=' ' && *end!=']' && *end!='\0'; ++end );
+ if ( pt==end )
+ break;
+ if ( mm->axis_count>=sizeof(mm->axes)/sizeof(mm->axes[0])) {
+ LogError( _("Multiple master font with more than 4 axes\n") );
+ break;
+ }
+ mm->axes[ mm->axis_count++ ] = copyn( pt,end-pt );
+ for ( pt = end; *pt==' '; ++pt );
+ }
+
+ if ( mm->instance_count < (1<<mm->axis_count) )
+#if defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("Bad Multiple Master Font"),_("This multiple master font has %1$d instance fonts, but it needs at least %2$d master fonts for %3$d axes. FontForge will not be able to edit this correctly"),mm->instance_count,1<<mm->axis_count,mm->axis_count);
+#else
+ gwwv_post_error(_("Bad Multiple Master Font"),_("This multiple master font has %1$d instance fonts, but it needs at least %2$d master fonts for %3$d axes. FontForge will not be able to edit this correctly"),mm->instance_count,1<<mm->axis_count,mm->axis_count);
+#endif
+ else if ( mm->instance_count > (1<<mm->axis_count) )
+#if defined(FONTFORGE_CONFIG_GTK)
+ gwwv_post_error(_("Bad Multiple Master Font"),_("This multiple master font has %1$d instance fonts, but FontForge can only handle %2$d master fonts for %3$d axes. FontForge will not be able to edit this correctly"),mm->instance_count,1<<mm->axis_count,mm->axis_count);
+#else
+ gwwv_post_error(_("Bad Multiple Master Font"),_("This multiple master font has %1$d instance fonts, but FontForge can only handle %2$d master fonts for %3$d axes. FontForge will not be able to edit this correctly"),mm->instance_count,1<<mm->axis_count,mm->axis_count);
+#endif
+ mm->positions = gcalloc(mm->axis_count*mm->instance_count,sizeof(real));
+ pt = fd->fontinfo->blenddesignpositions;
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='[' ) ++pt;
+ ipos = 0;
+ while ( *pt!=']' && *pt!='\0' ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt==']' || *pt=='\0' )
+ break;
+ if ( ipos>=mm->instance_count )
+ break;
+ if ( *pt=='[' ) {
+ ++pt;
+ apos=0;
+ while ( *pt!=']' && *pt!='\0' ) {
+ if ( apos>=mm->axis_count ) {
+ LogError( _("Too many axis positions specified in /BlendDesignPositions.\n") );
+ break;
+ }
+ mm->positions[ipos*mm->axis_count+apos] =
+ strtod(pt,&end);
+ if ( pt==end )
+ break;
+ ++apos;
+ for ( pt = end; *pt==' '; ++pt );
+ }
+ if ( *pt==']' ) ++pt;
+ ++ipos;
+ } else
+ ++pt;
+ }
+
+ mm->axismaps = gcalloc(mm->axis_count,sizeof(struct axismap));
+ pt = fd->fontinfo->blenddesignmap;
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='[' ) ++pt;
+ apos = 0;
+ while ( *pt!=']' && *pt!='\0' ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt==']' || *pt=='\0' )
+ break;
+ if ( apos>=mm->axis_count )
+ break;
+ if ( *pt=='[' ) {
+ ++pt;
+ ppos=0;
+ while ( *pt!=']' && *pt!='\0' ) {
+ if ( ppos>=12 ) {
+ LogError( _("Too many mapping data points specified in /BlendDesignMap for axis %s.\n"), mm->axes[apos] );
+ break;
+ }
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='[' ) {
+ ++pt;
+ designs[ppos] = strtod(pt,&end);
+ blends[ppos] = strtod(end,&end);
+ if ( blends[ppos]<0 || blends[ppos]>1 ) {
+ LogError( _("Bad value for blend in /BlendDesignMap for axis %s.\n"), mm->axes[apos] );
+ if ( blends[ppos]<0 ) blends[ppos] = 0;
+ if ( blends[ppos]>1 ) blends[ppos] = 1;
+ }
+ pt = end;
+ while ( *pt!=']' && *pt!='\0' ) ++pt;
+ ppos ++;
+ }
+ ++pt;
+ while ( *pt==' ' ) ++pt;
+ }
+ if ( *pt==']' ) ++pt;
+ if ( ppos<2 )
+ LogError( _("Bad few values in /BlendDesignMap for axis %s.\n"), mm->axes[apos] );
+ mm->axismaps[apos].points = ppos;
+ mm->axismaps[apos].blends = galloc(ppos*sizeof(real));
+ mm->axismaps[apos].designs = galloc(ppos*sizeof(real));
+ memcpy(mm->axismaps[apos].blends,blends,ppos*sizeof(real));
+ memcpy(mm->axismaps[apos].designs,designs,ppos*sizeof(real));
+ ++apos;
+ } else
+ ++pt;
+ }
+
+ mm->cdv = copy(fd->cdv);
+ mm->ndv = copy(fd->ndv);
+
+ origweight = fd->fontinfo->weight;
+
+ /* Now figure out the master designs, being careful to interpolate */
+ /* BlueValues, ForceBold, UnderlinePosition etc. We need to copy private */
+ /* generate a font name */
+ for ( ipos = 0; ipos<mm->instance_count; ++ipos ) {
+ free(fd->fontname);
+ free(fd->fontinfo->fullname);
+ fd->fontname = MMMakeMasterFontname(mm,ipos,&fd->fontinfo->fullname);
+ fd->fontinfo->weight = MMGuessWeight(mm,ipos,copy(origweight));
+ if ( fd->blendfontinfo!=NULL ) {
+ for ( item=0; item<3; ++item ) {
+ static char *names[] = { "ItalicAngle", "UnderlinePosition", "UnderlineThickness" };
+ pt = PSDictHasEntry(fd->blendfontinfo,names[item]);
+ if ( pt!=NULL ) {
+ pt = MMExtractNth(pt,ipos);
+ if ( pt!=NULL ) {
+ double val = strtod(pt,NULL);
+ free(pt);
+ switch ( item ) {
+ case 0: fd->fontinfo->italicangle = val; break;
+ case 1: fd->fontinfo->underlineposition = val; break;
+ case 2: fd->fontinfo->underlinethickness = val; break;
+ }
+ }
+ }
+ }
+ }
+ fd->private->private = PSDictCopy(sf->private);
+ if ( fd->blendprivate!=NULL ) {
+ static char *arrnames[] = { "BlueValues", "OtherBlues", "FamilyBlues", "FamilyOtherBlues", "StdHW", "StdVW", "StemSnapH", "StemSnapV", NULL };
+ static char *scalarnames[] = { "ForceBold", "BlueFuzz", "BlueScale", "BlueShift", NULL };
+ for ( item=0; scalarnames[item]!=NULL; ++item ) {
+ pt = PSDictHasEntry(fd->blendprivate,scalarnames[item]);
+ if ( pt!=NULL ) {
+ pt = MMExtractNth(pt,ipos);
+ PSDictChangeEntry(fd->private->private,scalarnames[item],pt);
+ free(pt);
+ }
+ }
+ for ( item=0; arrnames[item]!=NULL; ++item ) {
+ pt = PSDictHasEntry(fd->blendprivate,arrnames[item]);
+ if ( pt!=NULL ) {
+ pt = MMExtractArrayNth(pt,ipos);
+ PSDictChangeEntry(fd->private->private,arrnames[item],pt);
+ free(pt);
+ }
+ }
+ }
+ for ( item=0; item<mm->instance_count; ++item )
+ pscontext->blend_values[item] = 0;
+ pscontext->blend_values[ipos] = 1;
+
+ mm->instances[ipos] = SplineFontEmpty();
+ SplineFontMetaData(mm->instances[ipos],fd);
+ free(fd->fontinfo->weight);
+ mm->instances[ipos]->map = map;
+ _SplineFontFromType1(mm->instances[ipos],fd,pscontext);
+ mm->instances[ipos]->mm = mm;
+ }
+ fd->fontinfo->weight = origweight;
+
+ /* Clean up hintmasks. We always create a hintmask on the first point */
+ /* only keep them if we actually have conflicts. */
+ for ( i=0; i<mm->normal->glyphcnt; ++i )
+ if ( mm->normal->glyphs[i]!=NULL &&
+ mm->normal->glyphs[i]->layers[ly_fore].splines != NULL ) {
+ for ( item=0; item<mm->instance_count; ++item )
+ if ( mm->instances[item]->glyphs[i]->vconflicts ||
+ mm->instances[item]->glyphs[i]->hconflicts )
+ break;
+ if ( item==mm->instance_count ) { /* No conflicts */
+ for ( item=0; item<mm->instance_count; ++item ) {
+ chunkfree( mm->instances[item]->glyphs[i]->layers[ly_fore].splines->first->hintmask, sizeof(HintMask) );
+ mm->instances[item]->glyphs[i]->layers[ly_fore].splines->first->hintmask = NULL;
+ }
+ chunkfree( mm->normal->glyphs[i]->layers[ly_fore].splines->first->hintmask, sizeof(HintMask) );
+ mm->normal->glyphs[i]->layers[ly_fore].splines->first->hintmask = NULL;
+ }
+ }
+
+return( sf );
+}
+#endif
+
+static SplineFont *SplineFontFromCIDType1(SplineFont *sf, FontDict *fd,
+ struct pscontext *pscontext) {
+ int i,j,k, bad, uni;
+ SplineChar **chars;
+ char buffer[100];
+ struct cidmap *map;
+ SplineFont *_sf;
+ SplineChar *sc;
+ EncMap *encmap;
+
+ bad = 0x80000000;
+ for ( i=0; i<fd->fdcnt; ++i )
+ if ( fd->fds[i]->fonttype!=1 && fd->fds[i]->fonttype!=2 )
+ bad = fd->fds[i]->fonttype;
+ if ( bad!=0x80000000 || fd->cidfonttype!=0 ) {
+ LogError( _("Could not parse a CID font, %sCIDFontType %d, %sfonttype %d\n"),
+ ( fd->cidfonttype!=0 ) ? "unexpected " : "",
+ ( bad!=0x80000000 ) ? "unexpected " : "",
+ fd->cidfonttype, bad );
+ SplineFontFree(sf);
+return( NULL );
+ }
+ if ( fd->cidstrs==NULL || fd->cidcnt==0 ) {
+ LogError( _("CID format doesn't contain what we expected it to.\n") );
+ SplineFontFree(sf);
+return( NULL );
+ }
+
+ encmap = EncMap1to1(fd->cidcnt);
+
+ sf->subfontcnt = fd->fdcnt;
+ sf->subfonts = galloc((sf->subfontcnt+1)*sizeof(SplineFont *));
+ for ( i=0; i<fd->fdcnt; ++i ) {
+ sf->subfonts[i] = SplineFontEmpty();
+ SplineFontMetaData(sf->subfonts[i],fd->fds[i]);
+ sf->subfonts[i]->cidmaster = sf;
+ sf->subfonts[i]->uni_interp = sf->uni_interp;
+ sf->subfonts[i]->map = encmap;
+ if ( fd->fds[i]->fonttype==2 )
+ fd->fds[i]->private->subrs->bias =
+ fd->fds[i]->private->subrs->cnt<1240 ? 107 :
+ fd->fds[i]->private->subrs->cnt<33900 ? 1131 : 32768;
+ }
+
+ map = FindCidMap(sf->cidregistry,sf->ordering,sf->supplement,sf);
+
+ chars = gcalloc(fd->cidcnt,sizeof(SplineChar *));
+ for ( i=0; i<fd->cidcnt; ++i ) if ( fd->cidlens[i]>0 ) {
+ j = fd->cidfds[i]; /* We get font indexes of 255 for non-existant chars */
+ uni = CID2NameUni(map,i,buffer,sizeof(buffer));
+ pscontext->is_type2 = fd->fds[j]->fonttype==2;
+ chars[i] = PSCharStringToSplines(fd->cidstrs[i],fd->cidlens[i],
+ pscontext,fd->fds[j]->private->subrs,
+ NULL,buffer);
+ chars[i]->vwidth = sf->subfonts[j]->ascent+sf->subfonts[j]->descent;
+ chars[i]->unicodeenc = uni;
+ chars[i]->orig_pos = i;
+ /* There better not be any references (seac's) because we have no */
+ /* encoding on which to base any fixups */
+ if ( chars[i]->layers[ly_fore].refs!=NULL )
+ IError( "Reference found in CID font. Can't fix it up");
+ sf->subfonts[j]->glyphcnt = sf->subfonts[j]->glyphmax = i+1;
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ gwwv_progress_next();
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_progress_next();
+#endif
+ }
+ for ( i=0; i<fd->fdcnt; ++i )
+ sf->subfonts[i]->glyphs = gcalloc(sf->subfonts[i]->glyphcnt,sizeof(SplineChar *));
+ for ( i=0; i<fd->cidcnt; ++i ) if ( chars[i]!=NULL ) {
+ j = fd->cidfds[i];
+ if ( j<sf->subfontcnt ) {
+ sf->subfonts[j]->glyphs[i] = chars[i];
+ chars[i]->parent = sf->subfonts[j];
+ }
+ }
+ free(chars);
+
+ /* Clean up the hint masks, We create an initial hintmask whether we */
+ /* need it or not */
+ k=0;
+ do {
+ _sf = k<sf->subfontcnt?sf->subfonts[k]:sf;
+ for ( i=0; i<_sf->glyphcnt; ++i ) {
+ if ( (sc = _sf->glyphs[i])!=NULL && !sc->hconflicts && !sc->vconflicts &&
+ sc->layers[ly_fore].splines!=NULL ) {
+ chunkfree( sc->layers[ly_fore].splines->first->hintmask,sizeof(HintMask) );
+ sc->layers[ly_fore].splines->first->hintmask = NULL;
+ }
+ }
+ ++k;
+ } while ( k<sf->subfontcnt );
+return( sf );
+}
+
+SplineFont *SplineFontFromPSFont(FontDict *fd) {
+ SplineFont *sf;
+ struct pscontext pscontext;
+
+ if ( fd->sf!=NULL )
+ sf = fd->sf;
+ else {
+ memset(&pscontext,0,sizeof(pscontext));
+ pscontext.is_type2 = fd->fonttype==2;
+ pscontext.painttype = fd->painttype;
+
+ sf = SplineFontEmpty();
+ SplineFontMetaData(sf,fd);
+ if ( fd->wascff ) {
+ SplineFontFree(sf);
+ sf = fd->sf;
+ } else if ( fd->fdcnt!=0 )
+ sf = SplineFontFromCIDType1(sf,fd,&pscontext);
+#ifndef LUA_FF_LIB
+ else if ( fd->weightvector!=NULL )
+ SplineFontFromMMType1(sf,fd,&pscontext);
+#endif
+ else
+ SplineFontFromType1(sf,fd,&pscontext);
+ if ( loaded_fonts_same_as_new && new_fonts_are_order2 &&
+ fd->weightvector==NULL )
+ SFConvertToOrder2(sf);
+ }
+ if ( sf->multilayer )
+ SFCheckPSBitmap(sf);
+return( sf );
+}
+
+#ifdef FONTFORGE_CONFIG_TYPE3
+static void LayerToRefLayer(struct reflayer *rl,Layer *layer) {
+ rl->fill_brush = layer->fill_brush;
+ rl->stroke_pen = layer->stroke_pen;
+ rl->dofill = layer->dofill;
+ rl->dostroke = layer->dostroke;
+ rl->fillfirst = layer->fillfirst;
+}
+#endif
+
+void RefCharFindBounds(RefChar *rf) {
+#ifdef FONTFORGE_CONFIG_TYPE3
+ int i;
+ SplineChar *rsc = rf->sc;
+ real extra=0,e;
+
+ memset(&rf->bb,'\0',sizeof(rf->bb));
+ rf->top.y = -1e10;
+ for ( i=0; i<rf->layer_cnt; ++i ) {
+ _SplineSetFindBounds(rf->layers[i].splines,&rf->bb);
+ _SplineSetFindTop(rf->layers[i].splines,&rf->top);
+ if ( rsc->layers[i].dostroke ) {
+ if ( rf->layers[i].stroke_pen.width!=WIDTH_INHERITED )
+ e = rf->layers[i].stroke_pen.width*rf->layers[i].stroke_pen.trans[0];
+ else
+ e = rf->layers[i].stroke_pen.trans[0];
+ if ( e>extra ) extra = e;
+ }
+ }
+ if ( rf->top.y < -65536 ) rf->top.y = rf->top.x = 0;
+ rf->bb.minx -= extra; rf->bb.miny -= extra;
+ rf->bb.maxx += extra; rf->bb.maxy += extra;
+#else
+ SplineSetFindBounds(rf->layers[0].splines,&rf->bb);
+ SplineSetFindTop(rf->layers[0].splines,&rf->top);
+#endif
+}
+
+void SCReinstanciateRefChar(SplineChar *sc,RefChar *rf) {
+ SplinePointList *spl, *new;
+ RefChar *refs;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ int i,j;
+ SplineChar *rsc = rf->sc;
+ real extra=0,e;
+
+ for ( i=0; i<rf->layer_cnt; ++i )
+ SplinePointListsFree(rf->layers[i].splines);
+ free( rf->layers );
+ rf->layers = NULL;
+ rf->layer_cnt = 0;
+ if ( rsc==NULL )
+return;
+ /* Can be called before sc->parent is set, but only when reading a ttf */
+ /* file which won't be multilayer */
+ if ( sc->parent!=NULL && sc->parent->multilayer ) {
+ int cnt = 0;
+ RefChar *subref;
+ for ( i=ly_fore; i<rsc->layer_cnt; ++i ) {
+ if ( rsc->layers[i].splines!=NULL || rsc->layers[i].images!=NULL )
+ ++cnt;
+ for ( subref=rsc->layers[i].refs; subref!=NULL; subref=subref->next )
+ cnt += subref->layer_cnt;
+ }
+
+ rf->layer_cnt = cnt;
+ rf->layers = gcalloc(cnt,sizeof(struct reflayer));
+ cnt = 0;
+ for ( i=ly_fore; i<rsc->layer_cnt; ++i ) {
+ if ( rsc->layers[i].splines!=NULL || rsc->layers[i].images!=NULL ) {
+ rf->layers[cnt].splines =
+ SplinePointListTransform(
+ SplinePointListCopy(rsc->layers[i].splines),rf->transform,true);
+ rf->layers[cnt].images =
+ ImageListTransform(
+ ImageListCopy(rsc->layers[i].images),rf->transform);
+ LayerToRefLayer(&rf->layers[cnt],&rsc->layers[i]);
+ ++cnt;
+ }
+ for ( subref=rsc->layers[i].refs; subref!=NULL; subref=subref->next ) {
+ for ( j=0; j<subref->layer_cnt; ++j ) if ( subref->layers[j].images!=NULL || subref->layers[j].splines!=NULL ) {
+ rf->layers[cnt] = subref->layers[j];
+ rf->layers[cnt].splines =
+ SplinePointListTransform(
+ SplinePointListCopy(subref->layers[j].splines),rf->transform,true);
+ rf->layers[cnt].images =
+ ImageListTransform(
+ ImageListCopy(subref->layers[j].images),rf->transform);
+ ++cnt;
+ }
+ }
+ }
+
+ memset(&rf->bb,'\0',sizeof(rf->bb));
+ rf->top.y = -1e10;
+ for ( i=0; i<rf->layer_cnt; ++i ) {
+ _SplineSetFindBounds(rf->layers[i].splines,&rf->bb);
+ _SplineSetFindTop(rf->layers[i].splines,&rf->top);
+ if ( rsc->layers[i].dostroke ) {
+ if ( rf->layers[i].stroke_pen.width!=WIDTH_INHERITED )
+ e = rf->layers[i].stroke_pen.width*rf->layers[i].stroke_pen.trans[0];
+ else
+ e = rf->layers[i].stroke_pen.trans[0];
+ if ( e>extra ) extra = e;
+ }
+ }
+ if ( rf->top.y < -65536 ) rf->top.y = rf->top.x = 0;
+ rf->bb.minx -= extra; rf->bb.miny -= extra;
+ rf->bb.maxx += extra; rf->bb.maxy += extra;
+ } else {
+ rf->layers = gcalloc(1,sizeof(struct reflayer));
+ rf->layer_cnt = 1;
+ rf->layers[0].dofill = true;
+#else
+ SplinePointListsFree(rf->layers[0].splines);
+ rf->layers[0].splines = NULL;
+ if ( rf->sc==NULL )
+return;
+ {
+#endif
+ new = SplinePointListTransform(SplinePointListCopy(rf->sc->layers[ly_fore].splines),rf->transform,true);
+ if ( new!=NULL ) {
+ for ( spl = new; spl->next!=NULL; spl = spl->next );
+ spl->next = rf->layers[0].splines;
+ rf->layers[0].splines = new;
+ }
+ for ( refs = rf->sc->layers[ly_fore].refs; refs!=NULL; refs = refs->next ) {
+ new = SplinePointListTransform(SplinePointListCopy(refs->layers[0].splines),rf->transform,true);
+ if ( new!=NULL ) {
+ for ( spl = new; spl->next!=NULL; spl = spl->next );
+ spl->next = rf->layers[0].splines;
+ rf->layers[0].splines = new;
+ }
+ }
+ }
+ RefCharFindBounds(rf);
+}
+
+static void _SFReinstanciateRefs(SplineFont *sf) {
+ int i, undone, undoable, j, cnt;
+ RefChar *ref;
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ sf->glyphs[i]->ticked = false;
+
+ undone = true;
+ cnt = 0;
+ while ( undone && cnt<200) {
+ undone = false;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ undoable = false;
+ for ( j=0; j<sf->glyphs[i]->layer_cnt; ++j ) {
+ for ( ref=sf->glyphs[i]->layers[j].refs; ref!=NULL; ref=ref->next ) {
+ if ( !ref->sc->ticked )
+ undoable = true;
+ }
+ }
+ if ( undoable )
+ undone = true;
+ else {
+ for ( j=0; j<sf->glyphs[i]->layer_cnt; ++j ) {
+ for ( ref=sf->glyphs[i]->layers[j].refs; ref!=NULL; ref=ref->next )
+ SCReinstanciateRefChar(sf->glyphs[i],ref);
+ }
+ sf->glyphs[i]->ticked = true;
+ }
+ }
+ ++cnt;
+ }
+}
+
+void SFReinstanciateRefs(SplineFont *sf) {
+ int i;
+
+ if ( sf->cidmaster!=NULL || sf->subfontcnt!=0 ) {
+ if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
+ for ( i=0; i<sf->subfontcnt; ++i )
+ _SFReinstanciateRefs(sf->subfonts[i]);
+ } else
+ _SFReinstanciateRefs(sf);
+}
+
+void SCReinstanciateRef(SplineChar *sc,SplineChar *rsc) {
+ RefChar *rf;
+
+ for ( rf=sc->layers[ly_fore].refs; rf!=NULL; rf=rf->next ) if ( rf->sc==rsc ) {
+ SCReinstanciateRefChar(sc,rf);
+ }
+}
+
+void SCRemoveDependent(SplineChar *dependent,RefChar *rf) {
+ struct splinecharlist *dlist, *pd;
+ RefChar *prev;
+
+ if ( dependent->layers[ly_fore].refs==rf )
+ dependent->layers[ly_fore].refs = rf->next;
+ else {
+ for ( prev = dependent->layers[ly_fore].refs; prev->next!=rf; prev=prev->next );
+ prev->next = rf->next;
+ }
+ /* Check for multiple dependencies (colon has two refs to period) */
+ /* if there are none, then remove dependent from ref->sc's dependents list */
+ for ( prev = dependent->layers[ly_fore].refs; prev!=NULL && (prev==rf || prev->sc!=rf->sc); prev = prev->next );
+ if ( prev==NULL ) {
+ dlist = rf->sc->dependents;
+ if ( dlist==NULL )
+ /* Do nothing */;
+ else if ( dlist->sc==dependent ) {
+ rf->sc->dependents = dlist->next;
+ } else {
+ for ( pd=dlist, dlist = pd->next; dlist!=NULL && dlist->sc!=dependent; pd=dlist, dlist = pd->next );
+ if ( dlist!=NULL )
+ pd->next = dlist->next;
+ }
+ chunkfree(dlist,sizeof(struct splinecharlist));
+ }
+ RefCharFree(rf);
+}
+
+void SCRemoveLayerDependents(SplineChar *dependent,int layer) {
+ RefChar *rf, *next;
+
+ for ( rf=dependent->layers[layer].refs; rf!=NULL; rf=next ) {
+ next = rf->next;
+ SCRemoveDependent(dependent,rf);
+ }
+ dependent->layers[layer].refs = NULL;
+}
+
+void SCRemoveDependents(SplineChar *dependent) {
+ int layer;
+
+ for ( layer=ly_fore; layer<dependent->layer_cnt; ++layer )
+ SCRemoveLayerDependents(dependent,layer);
+}
+
+void SCRefToSplines(SplineChar *sc,RefChar *rf) {
+ SplineSet *spl;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ int layer;
+
+ if ( sc->parent->multilayer ) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ Layer *old = sc->layers;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ sc->layers = grealloc(sc->layers,(sc->layer_cnt+rf->layer_cnt)*sizeof(Layer));
+ for ( layer = 0; layer<rf->layer_cnt; ++layer ) {
+ LayerDefault(&sc->layers[sc->layer_cnt+layer]);
+ sc->layers[sc->layer_cnt+layer].splines = rf->layers[layer].splines;
+ rf->layers[layer].splines = NULL;
+ sc->layers[sc->layer_cnt+layer].images = rf->layers[layer].images;
+ rf->layers[layer].images = NULL;
+ sc->layers[sc->layer_cnt+layer].refs = NULL;
+ sc->layers[sc->layer_cnt+layer].undoes = NULL;
+ sc->layers[sc->layer_cnt+layer].redoes = NULL;
+ sc->layers[sc->layer_cnt+layer].fill_brush = rf->layers[layer].fill_brush;
+ sc->layers[sc->layer_cnt+layer].stroke_pen = rf->layers[layer].stroke_pen;
+ sc->layers[sc->layer_cnt+layer].dofill = rf->layers[layer].dofill;
+ sc->layers[sc->layer_cnt+layer].dostroke = rf->layers[layer].dostroke;
+ sc->layers[sc->layer_cnt+layer].fillfirst = rf->layers[layer].fillfirst;
+ }
+ sc->layer_cnt += rf->layer_cnt;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ SCMoreLayers(sc,old);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ } else {
+#else
+ {
+#endif
+ if ( (spl = rf->layers[0].splines)!=NULL ) {
+ while ( spl->next!=NULL )
+ spl = spl->next;
+ spl->next = sc->layers[ly_fore].splines;
+ sc->layers[ly_fore].splines = rf->layers[0].splines;
+ rf->layers[0].splines = NULL;
+ }
+ }
+ SCRemoveDependent(sc,rf);
+}
+
+/* This returns all real solutions, even those out of bounds */
+/* I use -999999 as an error flag, since we're really only interested in */
+/* solns near 0 and 1 that should be ok. -1 is perhaps a little too close */
+static int _CubicSolve(const Spline1D *sp,extended ts[3]) {
+ extended d, xN, yN, delta2, temp, delta, h, t2, t3, theta;
+ int i=0;
+
+ ts[0] = ts[1] = ts[2] = -999999;
+ if ( sp->d==0 && sp->a!=0 ) {
+ /* one of the roots is 0, the other two are the soln of a quadratic */
+ ts[0] = 0;
+ if ( sp->c==0 ) {
+ ts[1] = -sp->b/(extended) sp->a; /* two zero roots */
+ } else {
+ temp = sp->b*(extended) sp->b-4*(extended) sp->a*sp->c;
+ if ( RealNear(temp,0))
+ ts[1] = -sp->b/(2*(extended) sp->a);
+ else if ( temp>=0 ) {
+ temp = sqrt(temp);
+ ts[1] = (-sp->b+temp)/(2*(extended) sp->a);
+ ts[2] = (-sp->b-temp)/(2*(extended) sp->a);
+ }
+ }
+ } else if ( sp->a!=0 ) {
+ /* http://www.m-a.org.uk/eb/mg/mg077ch.pdf */
+ /* this nifty solution to the cubic neatly avoids complex arithmatic */
+ xN = -sp->b/(3*(extended) sp->a);
+ yN = ((sp->a*xN + sp->b)*xN+sp->c)*xN + sp->d;
+
+ delta2 = (sp->b*(extended) sp->b-3*(extended) sp->a*sp->c)/(9*(extended) sp->a*sp->a);
+ if ( RealNear(delta2,0) ) delta2 = 0;
+
+ /* the descriminant is yN^2-h^2, but delta might be <0 so avoid using h */
+ d = yN*yN - 4*sp->a*sp->a*delta2*delta2*delta2;
+ if ( ((yN>.01 || yN<-.01) && RealNear(d/yN,0)) || ((yN<=.01 && yN>=-.01) && RealNear(d,0)) )
+ d = 0;
+ if ( d>0 ) {
+ temp = sqrt(d);
+ t2 = (-yN-temp)/(2*sp->a);
+ t2 = (t2==0) ? 0 : (t2<0) ? -pow(-t2,1./3.) : pow(t2,1./3.);
+ t3 = (-yN+temp)/(2*sp->a);
+ t3 = t3==0 ? 0 : (t3<0) ? -pow(-t3,1./3.) : pow(t3,1./3.);
+ ts[0] = xN + t2 + t3;
+ } else if ( d<0 ) {
+ if ( delta2>=0 ) {
+ delta = sqrt(delta2);
+ h = 2*sp->a*delta2*delta;
+ temp = -yN/h;
+ if ( temp>=-1.0001 && temp<=1.0001 ) {
+ if ( temp<-1 ) temp = -1; else if ( temp>1 ) temp = 1;
+ theta = acos(temp)/3;
+ ts[i++] = xN+2*delta*cos(theta);
+ ts[i++] = xN+2*delta*cos(2.0943951+theta);
+ ts[i++] = xN+2*delta*cos(4.1887902+theta);
+ }
+ }
+ } else if ( /* d==0 && */ delta2!=0 ) {
+ delta = yN/(2*sp->a);
+ delta = delta==0 ? 0 : delta>0 ? pow(delta,1./3.) : -pow(-delta,1./3.);
+ ts[i++] = xN + delta; /* this root twice, but that's irrelevant to me */
+ ts[i++] = xN - 2*delta;
+ } else if ( /* d==0 && */ delta2==0 ) {
+ if ( xN>=-0.0001 && xN<=1.0001 ) ts[0] = xN;
+ }
+ } else if ( sp->b!=0 ) {
+ extended d = sp->c*(extended) sp->c-4*(extended) sp->b*sp->d;
+ if ( RealNear(d,0)) d=0;
+ if ( d<0 )
+return(false); /* All roots imaginary */
+ d = sqrt(d);
+ ts[0] = (-sp->c-d)/(2*(extended) sp->b);
+ ts[1] = (-sp->c+d)/(2*(extended) sp->b);
+ } else if ( sp->c!=0 ) {
+ ts[0] = -sp->d/(extended) sp->c;
+ } else {
+ /* If it's a point then either everything is a solution, or nothing */
+ }
+return( ts[0]!=-999999 );
+}
+
+int CubicSolve(const Spline1D *sp,extended ts[3]) {
+ extended t;
+ int i;
+ /* This routine gives us all solutions between [0,1] with -1 as an error flag */
+ /* http://mathforum.org/dr.math/faq/faq.cubic.equations.html */
+
+ if ( !_CubicSolve(sp,ts)) {
+ ts[0] = ts[1] = ts[2] = -1;
+return( false );
+ }
+
+ for ( i=0; i<3; ++i )
+ if ( ts[i]==-999999 ) ts[i] = -1;
+ if (ts[0]>1.0001 || ts[0]<-.0001 ) ts[0] = -1;
+ else if ( ts[0]<0 ) ts[0] = 0; else if ( ts[0]>1 ) ts[0] = 1;
+ if (ts[1]>1.0001 || ts[1]<-.0001 ) ts[1] = -1;
+ else if ( ts[1]<0 ) ts[1] = 0; else if ( ts[1]>1 ) ts[1] = 1;
+ if (ts[2]>1.0001 || ts[2]<-.0001 ) ts[2] = -1;
+ else if ( ts[2]<0 ) ts[2] = 0; else if ( ts[2]>1 ) ts[2] = 1;
+ if ( ts[1]==-1 ) { ts[1] = ts[2]; ts[2] = -1;}
+ if ( ts[0]==-1 ) { ts[0] = ts[1]; ts[1] = ts[2]; ts[2] = -1; }
+ if ( ts[0]==-1 )
+return( false );
+ if ( ts[0]>ts[2] && ts[2]!=-1 ) {
+ t = ts[0]; ts[0] = ts[2]; ts[2] = t;
+ }
+ if ( ts[0]>ts[1] && ts[1]!=-1 ) {
+ t = ts[0]; ts[0] = ts[1]; ts[1] = t;
+ }
+ if ( ts[1]>ts[2] && ts[2]!=-1 ) {
+ t = ts[1]; ts[1] = ts[2]; ts[2] = t;
+ }
+return( true );
+}
+
+#if 0
+/* These methods purport to solve all quartics. But they don't solve mine */
+/* so I may have miscopied or something, but I'll give up on algebraic solns*/
+static int QuarticAlternate(Quartic *q,double ts[4],double offset) {
+ Spline1D sp;
+ double zs[3], h, j, temp;
+ int i;
+
+ sp.a = 1; sp.b = 2*q->c; sp.c = q->c*q->c-4*q->e;
+ sp.d = q->d*q->d;
+ if ( !_CubicSolve(&sp,zs))
+return(-1);
+ for ( i=0; i<3; ++i )
+ if ( zs[i]>0 )
+ break;
+ if ( i>=3 )
+return( -1 );
+ h = sqrt(zs[i]);
+ j = (q->c+zs[i]-q->d/h)/2;
+
+ /* Now the roots of q are the roots of y^2+hy+j and y^2-hy+(q->e)/j */
+ i = 0;
+ temp = h*h-4*j;
+ if ( temp>=0 ) {
+ temp = sqrt(temp);
+ ts[i++] = (-h+temp)/2 - offset;
+ ts[i++] = (-h-temp)/2 - offset;
+ }
+ temp = h*h-4*q->e/j;
+ if ( temp>=0 ) {
+ temp = sqrt(temp);
+ ts[i++] = (h+temp)/2 - offset;
+ ts[i++] = (h-temp)/2 - offset;
+ }
+return( i );
+}
+
+static int _QuarticSolve(Quartic *q,double ts[4]) {
+ Quartic work;
+ double zs[3], pq[2], r;
+ double f,offset;
+ Spline1D sp;
+ int i,j;
+
+ ts[0] = ts[1] = ts[2] = ts[3] = -1;
+ if ( RealNear(q->a,0) ) {
+ /* I got a quadratic here once so this can happen ... */
+ i = 0;
+ if ( RealNear(q->b,0)) {
+ if ( RealNear(q->c,0)) {
+ if ( !RealNear(q->d,0))
+ ts[i++] = -q->e/q->d;
+ } else {
+ f = q->d*q->d - 4*q->c*q->e;
+ if ( f>=0 ) {
+ f=sqrt(f);
+ ts[i++] = (-q->d + f)/(2*q->c);
+ ts[i++] = (-q->d - f)/(2*q->c);
+ }
+ }
+ } else {
+ sp.a = q->b; sp.b = q->c; sp.c = q->d; sp.d = q->e;
+ ts[3] = -1;
+ if ( !CubicSolve(&sp,ts))
+return( -1 );
+ for ( i=0; i<3 && ts[i]!=-1; ++i );
+ }
+ } else if ( RealNear(q->e,0)) {
+ sp.a = q->a; sp.b = q->b; sp.c = q->c; sp.d = q->d;
+ CubicSolve(&sp,ts);
+ for ( i=0; i<3 && ts[i]!=-1; ++i );
+ ts[i++] = 0;
+ } else {
+ /* http://mathforum.org/dr.math/faq/faq.cubic.equations.html */
+ /* divide by q->a, substitute t=s - q->b/4 */
+ offset = q->b/(4*q->a);
+
+ work.a = 1;
+ work.b = 0;
+ work.c = (q->c-3*q->b*q->b/(8*q->a))/q->a;
+ work.d = (q->b*q->b*q->b/(8*q->a*q->a) - q->b*q->c/(2*q->a) + q->d)/q->a;
+ work.e = (-3*q->b*q->b*q->b*q->b/(256*q->a*q->a*q->a) + (q->b*q->b*q->c)/(16*q->a*q->a) -
+ q->b*q->d/(4*q->a) + q->e)/q->a;
+
+ if ( RealNear(work.e,0)) {
+ sp.a = work.a; sp.b = work.b; sp.c = work.c; sp.d = work.d;
+ CubicSolve(&sp,ts);
+ for ( i=0; i<3 && ts[i]!=-1; ++i );
+ ts[i++] = 0;
+ for ( j=0; j<i; ++j )
+ ts[j] -= offset;
+ } else if ( RealNear(work.d,0)) {
+ /* now we have a quadratic in s^2 */
+ double b24ac = work.c*work.c - 4*work.e, t1, t2;
+ if ( b24ac<0 && b24ac>-.0001 ) b24ac = 0;
+ if ( b24ac < 0 ) /* All roots imaginary */
+return( -1 );
+ b24ac = sqrt(b24ac);
+ t1 = (-work.c + b24ac)/2;
+ t2 = (-work.c - b24ac)/2;
+ i = 0;
+ if ( t1>0 ) {
+ ts[0] = sqrt(t1);
+ ts[1] = -ts[0];
+ i=2;
+ } else if ( t1>-.0001 )
+ ts[i++] = 0;
+ if ( t2>0 ) {
+ ts[i++] = sqrt(t2);
+ ts[i] = -ts[i-1];
+ ++i;
+ } else if ( t2>-.0001 )
+ ts[i++] = 0;
+ for ( j=0; j<i ; ++j )
+ ts[j] -= offset;
+ if ( i==0 )
+return( -1 );
+ } else {
+ sp.a = 1;
+ sp.b = work.c/2;
+ sp.c = (work.c*work.c-4*work.e)/16;
+ sp.d = work.d*work.d/64;
+ if ( !_CubicSolve(&sp,zs) )
+return( QuarticAlternate(&work,ts,offset));
+
+ j = 0;
+ for ( i=0; zs[i]!=-999999; ++i )
+ if ( zs[i]>0 ) {
+ pq[j++] = zs[i];
+ if ( j==2 )
+ break;
+ }
+ if ( j!=2 )
+return( QuarticAlternate(&work,ts,offset));
+ pq[0] = sqrt(pq[0]);
+ pq[1] = sqrt(pq[1]);
+ r = -work.d/(8 * pq[0] *pq[1]);
+ ts[0] = pq[0]+pq[1]+r - offset;
+ ts[1] = pq[0]-pq[1]-r - offset;
+ ts[2] = -pq[0]+pq[1]-r - offset;
+ ts[3] = -pq[0]-pq[1]+r - offset;
+ i = 4;
+ }
+ }
+return( i );
+}
+#else
+static int _QuarticSolve(Quartic *q,extended ts[4]) {
+ extended extrema[5];
+ Spline1D sp;
+ int ecnt = 0, i, zcnt;
+
+ /* Two special cases */
+ if ( q->a==0 ) { /* It's really a cubic */
+ sp.a = q->b;
+ sp.b = q->c;
+ sp.c = q->d;
+ sp.d = q->e;
+ ts[4] = -999999;
+return( _CubicSolve(&sp,ts));
+ } else if ( q->e==0 ) { /* we can factor out a zero root */
+ sp.a = q->a;
+ sp.b = q->b;
+ sp.c = q->c;
+ sp.d = q->d;
+ ts[0] = 0;
+return( _CubicSolve(&sp,ts+1)+1);
+ }
+
+ sp.a = 4*q->a;
+ sp.b = 3*q->b;
+ sp.c = 2*q->c;
+ sp.d = q->d;
+ if ( _CubicSolve(&sp,extrema)) {
+ ecnt = 1;
+ if ( extrema[1]!=-999999 ) {
+ ecnt = 2;
+ if ( extrema[1]<extrema[0] ) {
+ extended temp = extrema[1]; extrema[1] = extrema[0]; extrema[0]=temp;
+ }
+ if ( extrema[2]!=-999999 ) {
+ ecnt = 3;
+ if ( extrema[2]<extrema[0] ) {
+ extended temp = extrema[2]; extrema[2] = extrema[0]; extrema[0]=temp;
+ }
+ if ( extrema[2]<extrema[1] ) {
+ extended temp = extrema[2]; extrema[2] = extrema[1]; extrema[1]=temp;
+ }
+ }
+ }
+ }
+ for ( i=ecnt-1; i>=0 ; --i )
+ extrema[i+1] = extrema[i];
+ /* Upper and lower bounds within which we'll search */
+ extrema[0] = -999;
+ extrema[ecnt+1] = 999;
+ ecnt += 2;
+ /* divide into monotonic sections & use binary search to find zeroes */
+ for ( i=zcnt=0; i<ecnt-1; ++i ) {
+ extended top, bottom, val;
+ extended topt, bottomt, t;
+ topt = extrema[i+1];
+ bottomt = extrema[i];
+ top = (((q->a*topt+q->b)*topt+q->c)*topt+q->d)*topt+q->e;
+ bottom = (((q->a*bottomt+q->b)*bottomt+q->c)*bottomt+q->d)*bottomt+q->e;
+ if ( top<bottom ) {
+ extended temp = top; top = bottom; bottom = temp;
+ temp = topt; topt = bottomt; bottomt = temp;
+ }
+ if ( bottom>.001 ) /* this monotonic is all above 0 */
+ continue;
+ if ( top<-.001 ) /* this monotonic is all below 0 */
+ continue;
+ if ( bottom>0 ) {
+ ts[zcnt++] = bottomt;
+ continue;
+ }
+ if ( top<0 ) {
+ ts[zcnt++] = topt;
+ continue;
+ }
+ forever {
+ t = (topt+bottomt)/2;
+ if ( t==topt || t==bottomt ) {
+ ts[zcnt++] = t;
+ break;
+ }
+
+ val = (((q->a*t+q->b)*t+q->c)*t+q->d)*t+q->e;
+ if ( val>-.0001 && val<.0001 ) {
+ ts[zcnt++] = t;
+ break;
+ } else if ( val>0 ) {
+ top = val;
+ topt = t;
+ } else {
+ bottom = val;
+ bottomt = t;
+ }
+ }
+ }
+ for ( i=zcnt; i<4; ++i )
+ ts[i] = -999999;
+return( zcnt );
+}
+#endif
+
+static int QuarticSolve(Quartic *q,extended ts[4]) {
+ int i,j,k;
+
+ if ( _QuarticSolve(q,ts)==-1 )
+return( -1 );
+
+ for ( i=0; i<4 && ts[i]!=-999999; ++i ) {
+ if ( ts[i]>-.0001 && ts[i]<0 ) ts[i] = 0;
+ if ( ts[i]>1.0 && ts[i]<1.0001 ) ts[i] = 1;
+ if ( ts[i]>1.0 || ts[i]<0 ) ts[i] = -999999;
+ }
+ for ( i=3; i>=0 && ts[i]==-999999; --i );
+ if ( i==-1 )
+return( -1 );
+ for ( j=i ; j>=0 ; --j ) {
+ if ( ts[j]<0 ) {
+ for ( k=j+1; k<=i; ++k )
+ ts[k-1] = ts[k];
+ ts[i--] = -999999;
+ }
+ }
+return(i+1);
+}
+
+extended SplineSolve(const Spline1D *sp, real tmin, real tmax, extended sought,real err) {
+ /* We want to find t so that spline(t) = sought */
+ /* the curve must be monotonic */
+ /* returns t which is near sought or -1 */
+ Spline1D temp;
+ extended ts[3];
+ int i;
+ extended t;
+
+ temp = *sp;
+ temp.d -= sought;
+ CubicSolve(&temp,ts);
+ if ( tmax<tmin ) { t = tmax; tmax = tmin; tmin = t; }
+ for ( i=0; i<3; ++i )
+ if ( ts[i]>=tmin && ts[i]<=tmax )
+return( ts[i] );
+
+return( -1 );
+}
+
+#ifndef EXTENDED_IS_LONG_DOUBLE
+double CheckExtremaForSingleBitErrors(const Spline1D *sp, double t) {
+ union { double dval; int32 ival[2]; } u1, um1, temp;
+ double slope, slope1, slopem1;
+#ifdef WORDS_BIGENDIAN
+ const int index = 1;
+#else
+ const int index = 0;
+#endif
+
+ slope = (3*(double) sp->a*t+2*sp->b)*t+sp->c;
+
+ u1.dval = t;
+ u1.ival[index] += 1;
+ slope1 = (3*(double) sp->a*u1.dval+2*sp->b)*u1.dval+sp->c;
+
+ um1.dval = t;
+ um1.ival[index] -= 1;
+ slopem1 = (3*(double) sp->a*um1.dval+2*sp->b)*um1.dval+sp->c;
+
+ if ( slope<0 ) slope = -slope;
+ if ( slope1<0 ) slope1 = -slope1;
+ if ( slopem1<0 ) slopem1 = -slopem1;
+
+ if ( slope1<slope && slope1<=slopem1 ) {
+ /* Ok, things got better when we added 1. */
+ /* Do they improve further if we add 1 more? */
+ temp = u1;
+ temp.ival[index] += 1;
+ slope = (3*(double) sp->a*temp.dval+2*sp->b)*temp.dval+sp->c;
+ if ( slope<0 ) slope = -slope;
+ if ( slope<slope1 )
+return( temp.dval );
+ else
+return( u1.dval );
+ } else if ( slopem1<slope && slopem1<=slope ) {
+ /* Ok, things got better when we subtracted 1. */
+ /* Do they improve further if we subtract 1 more? */
+ temp = um1;
+ temp.ival[index] -= 1;
+ slope = (3*(double) sp->a*temp.dval+2*sp->b)*temp.dval+sp->c;
+ if ( slope<0 ) slope = -slope;
+ if ( slope<slopem1 )
+return( temp.dval );
+ else
+return( um1.dval );
+ }
+ /* that seems as good as it gets */
+
+return( t );
+}
+#else
+extended esqrt(extended e) {
+ extended rt, temp;
+
+ rt = sqrt( (double) e );
+ if ( e<=0 )
+return( rt );
+
+ temp = e/rt;
+ rt = (rt+temp)/2;
+ temp = e/rt;
+ rt = (rt+temp)/2;
+return( rt );
+}
+#endif
+
+static void _SplineFindExtrema(const Spline1D *sp, extended *_t1, extended *_t2 ) {
+ extended t1= -1, t2= -1;
+ extended b2_fourac;
+
+ /* Find the extreme points on the curve */
+ /* Set to -1 if there are none or if they are outside the range [0,1] */
+ /* Order them so that t1<t2 */
+ /* If only one valid extremum it will be t1 */
+ /* (Does not check the end points unless they have derivative==0) */
+ /* (Does not check to see if d/dt==0 points are inflection points (rather than extrema) */
+ if ( sp->a!=0 ) {
+ /* cubic, possibly 2 extrema (possibly none) */
+ b2_fourac = 4*(extended)sp->b*sp->b - 12*(extended)sp->a*sp->c;
+ if ( b2_fourac>=0 ) {
+ b2_fourac = esqrt(b2_fourac);
+ t1 = (-2*sp->b - b2_fourac) / (6*sp->a);
+ t2 = (-2*sp->b + b2_fourac) / (6*sp->a);
+ t1 = CheckExtremaForSingleBitErrors(sp,t1);
+ t2 = CheckExtremaForSingleBitErrors(sp,t2);
+ if ( t1>t2 ) { extended temp = t1; t1 = t2; t2 = temp; }
+ else if ( t1==t2 ) t2 = -1;
+ if ( RealNear(t1,0)) t1=0; else if ( RealNear(t1,1)) t1=1;
+ if ( RealNear(t2,0)) t2=0; else if ( RealNear(t2,1)) t2=1;
+ }
+ } else if ( sp->b!=0 ) {
+ /* Quadratic, at most one extremum */
+ t1 = -sp->c/(2.0*(extended) sp->b);
+ } else /*if ( sp->c!=0 )*/ {
+ /* linear, no extrema */
+ }
+ *_t1 = t1; *_t2 = t2;
+}
+
+void SplineFindExtrema(const Spline1D *sp, extended *_t1, extended *_t2 ) {
+ extended t1= -1, t2= -1;
+ extended b2_fourac;
+
+ /* Find the extreme points on the curve */
+ /* Set to -1 if there are none or if they are outside the range [0,1] */
+ /* Order them so that t1<t2 */
+ /* If only one valid extremum it will be t1 */
+ /* (Does not check the end points unless they have derivative==0) */
+ /* (Does not check to see if d/dt==0 points are inflection points (rather than extrema) */
+ if ( sp->a!=0 ) {
+ /* cubic, possibly 2 extrema (possibly none) */
+ b2_fourac = 4*(extended) sp->b*sp->b - 12*(extended) sp->a*sp->c;
+ if ( b2_fourac>=0 ) {
+ b2_fourac = esqrt(b2_fourac);
+ t1 = (-2*sp->b - b2_fourac) / (6*sp->a);
+ t2 = (-2*sp->b + b2_fourac) / (6*sp->a);
+ t1 = CheckExtremaForSingleBitErrors(sp,t1);
+ t2 = CheckExtremaForSingleBitErrors(sp,t2);
+ if ( t1>t2 ) { extended temp = t1; t1 = t2; t2 = temp; }
+ else if ( t1==t2 ) t2 = -1;
+ if ( RealNear(t1,0)) t1=0; else if ( RealNear(t1,1)) t1=1;
+ if ( RealNear(t2,0)) t2=0; else if ( RealNear(t2,1)) t2=1;
+ if ( t2<=0 || t2>=1 ) t2 = -1;
+ if ( t1<=0 || t1>=1 ) { t1 = t2; t2 = -1; }
+ }
+ } else if ( sp->b!=0 ) {
+ /* Quadratic, at most one extremum */
+ t1 = -sp->c/(2.0*(extended) sp->b);
+ if ( t1<=0 || t1>=1 ) t1 = -1;
+ } else /*if ( sp->c!=0 )*/ {
+ /* linear, no extrema */
+ }
+ *_t1 = t1; *_t2 = t2;
+}
+
+double SplineCurvature(Spline *s, double t) {
+ /* Kappa = (x'y'' - y'x'') / (x'^2 + y'^2)^(3/2) */
+ double dxdt, dydt, d2xdt2, d2ydt2, denom, numer;
+
+ if ( s==NULL )
+return( CURVATURE_ERROR );
+
+ dxdt = (3*s->splines[0].a*t+2*s->splines[0].b)*t+s->splines[0].c;
+ dydt = (3*s->splines[1].a*t+2*s->splines[1].b)*t+s->splines[1].c;
+ d2xdt2 = 6*s->splines[0].a*t + 2*s->splines[0].b;
+ d2ydt2 = 6*s->splines[1].a*t + 2*s->splines[1].b;
+ denom = pow( dxdt*dxdt + dydt*dydt, 3.0/2.0 );
+ numer = dxdt*d2ydt2 - dydt*d2xdt2;
+
+ if ( numer==0 )
+return( 0 );
+ if ( denom==0 )
+return( CURVATURE_ERROR );
+
+return( numer/denom );
+}
+
+int SplineAtInflection(Spline1D *sp, double t ) {
+ /* It's a point of inflection if d sp/dt==0 and d2 sp/dt^2==0 */
+return ( RealNear( (3*sp->a*t + 2*sp->b)*t + sp->c,0) &&
+ RealNear( 6*sp->a*t + 2*sp->b, 0));
+}
+
+int SplineAtMinMax(Spline1D *sp, double t ) {
+ /* It's a point of inflection if d sp/dt==0 and d2 sp/dt^2!=0 */
+return ( RealNear( (3*sp->a*t + 2*sp->b)*t + sp->c,0) &&
+ !RealNear( 6*sp->a*t + 2*sp->b, 0));
+}
+
+int Spline2DFindExtrema(const Spline *sp, extended extrema[4] ) {
+ int i,j;
+ BasePoint last, cur, mid;
+
+ SplineFindExtrema(&sp->splines[0],&extrema[0],&extrema[1]);
+ SplineFindExtrema(&sp->splines[1],&extrema[2],&extrema[3]);
+
+ for ( i=0; i<3; ++i ) for ( j=i+1; j<4; ++j ) {
+ if ( (extrema[i]==-1 && extrema[j]!=-1) || (extrema[i]>extrema[j] && extrema[j]!=-1) ) {
+ extended temp = extrema[i];
+ extrema[i] = extrema[j];
+ extrema[j] = temp;
+ }
+ }
+ for ( i=j=0; i<3 && extrema[i]!=-1; ++i ) {
+ if ( extrema[i]==extrema[i+1] ) {
+ for ( j=i+1; j<3; ++j )
+ extrema[j] = extrema[j+1];
+ extrema[3] = -1;
+ }
+ }
+
+ /* Extrema which are too close together are not interesting */
+ last = sp->from->me;
+ for ( i=0; i<4 && extrema[i]!=-1; ++i ) {
+ cur.x = ((sp->splines[0].a*extrema[i]+sp->splines[0].b)*extrema[i]+
+ sp->splines[0].c)*extrema[i]+sp->splines[0].d;
+ cur.y = ((sp->splines[1].a*extrema[i]+sp->splines[1].b)*extrema[i]+
+ sp->splines[1].c)*extrema[i]+sp->splines[1].d;
+ mid.x = (last.x+cur.x)/2; mid.y = (last.y+cur.y)/2;
+ if ( (mid.x==last.x || mid.x==cur.x) &&
+ (mid.y==last.y || mid.y==cur.y)) {
+ for ( j=i+1; j<3; ++j )
+ extrema[j] = extrema[j+1];
+ } else
+ last = cur;
+ }
+ for ( i=0; i<4 && extrema[i]!=-1; ++i );
+ if ( i!=0 ) {
+ cur = sp->to->me;
+ mid.x = (last.x+cur.x)/2; mid.y = (last.y+cur.y)/2;
+ if ( (mid.x==last.x || mid.x==cur.x) &&
+ (mid.y==last.y || mid.y==cur.y))
+ extrema[--i] = -1;
+ }
+
+return( i );
+}
+
+int Spline2DFindPointsOfInflection(const Spline *sp, extended poi[2] ) {
+ int cnt=0;
+ extended a, b, c, b2_fourac, t;
+ /* A POI happens when d2 y/dx2 is zero. This is not the same as d2y/dt2 / d2x/dt2 */
+ /* d2 y/dx^2 = d/dt ( dy/dt / dx/dt ) / dx/dt */
+ /* = ( (dx/dt) * d2 y/dt2 - ((dy/dt) * d2 x/dt2) )/ (dx/dt)^3 */
+ /* (3ax*t^2+2bx*t+cx) * (6ay*t+2by) - (3ay*t^2+2by*t+cy) * (6ax*t+2bx) == 0 */
+ /* (3ax*t^2+2bx*t+cx) * (3ay*t+by) - (3ay*t^2+2by*t+cy) * (3ax*t+bx) == 0 */
+ /* 9*ax*ay*t^3 + (3ax*by+6bx*ay)*t^2 + (2bx*by+3cx*ay)*t + cx*by */
+ /* -(9*ax*ay*t^3 + (3ay*bx+6by*ax)*t^2 + (2by*bx+3cy*ax)*t + cy*bx)==0 */
+ /* 3*(ax*by-ay*bx)*t^2 + 3*(cx*ay-cy*ax)*t+ (cx*by-cy*bx) == 0 */
+
+ a = 3*((extended) sp->splines[1].a*sp->splines[0].b-(extended) sp->splines[0].a*sp->splines[1].b);
+ b = 3*((extended) sp->splines[0].c*sp->splines[1].a - (extended) sp->splines[1].c*sp->splines[0].a);
+ c = (extended) sp->splines[0].c*sp->splines[1].b-(extended) sp->splines[1].c*sp->splines[0].b;
+ if ( !RealNear(a,0) ) {
+ b2_fourac = b*b - 4*a*c;
+ poi[0] = poi[1] = -1;
+ if ( b2_fourac<0 )
+return( 0 );
+ b2_fourac = esqrt( b2_fourac );
+ t = (-b+b2_fourac)/(2*a);
+ if ( t>=0 && t<=1.0 )
+ poi[cnt++] = t;
+ t = (-b-b2_fourac)/(2*a);
+ if ( t>=0 && t<=1.0 ) {
+ if ( cnt==1 && poi[0]>t ) {
+ poi[1] = poi[0];
+ poi[0] = t;
+ ++cnt;
+ } else
+ poi[cnt++] = t;
+ }
+ } else if ( !RealNear(b,0) ) {
+ t = -c/b;
+ if ( t>=0 && t<=1.0 )
+ poi[cnt++] = t;
+ }
+
+return( cnt );
+}
+
+/* Ok, if the above routine finds an extremum that less than 1 unit */
+/* from an endpoint or another extremum, then many things are */
+/* just going to skip over it, and other things will be confused by this */
+/* so just remove it. It should be so close the difference won't matter */
+void SplineRemoveExtremaTooClose(Spline1D *sp, extended *_t1, extended *_t2 ) {
+ extended last, test;
+ extended t1= *_t1, t2 = *_t2;
+
+ if ( t1>t2 && t2!=-1 ) {
+ t1 = t2;
+ t2 = *_t1;
+ }
+ last = sp->d;
+ if ( t1!=-1 ) {
+ test = ((sp->a*t1+sp->b)*t1+sp->c)*t1+sp->d;
+ if ( (test-last)*(test-last)<1 )
+ t1 = -1;
+ else
+ last = test;
+ }
+ if ( t2!=-1 ) {
+ test = ((sp->a*t2+sp->b)*t2+sp->c)*t2+sp->d;
+ if ( (test-last)*(test-last)<1 )
+ t2 = -1;
+ else
+ last = test;
+ }
+ test = sp->a+sp->b+sp->c+sp->d;
+ if ( (test-last)*(test-last)<1 ) {
+ if ( t2!=-1 )
+ t2 = -1;
+ else if ( t1!=-1 )
+ t1 = -1;
+ else
+ /* Well we should just remove the whole spline? */;
+ }
+ *_t1 = t1; *_t2 = t2;
+}
+
+int SplineSolveFull(const Spline1D *sp,extended val, extended ts[3]) {
+ Spline1D temp;
+
+ temp = *sp;
+ temp.d -= val;
+ CubicSolve(&temp,ts);
+return( ts[0]!=-1 );
+}
+
+#if 0
+static int CheckEndpoint(BasePoint *end,Spline *s,int te,BasePoint *pts,
+ real *tarray,real *ts,int soln) {
+ double t;
+ int i;
+
+ for ( i=0; i<soln; ++i )
+ if ( end->x==pts[i].x && end->y==pts[i].y )
+return( soln );
+
+ t = SplineNearPoint(s,end,.01);
+ if ( t<=0 || t>=1 ) /* If both splines are at end points then it's a join not an intersection */
+return( soln );
+ tarray[soln] = te;
+ ts[soln] = t;
+ pts[soln] = *end;
+return( soln+1 );
+}
+#endif
+
+static int AddPoint(extended x,extended y,extended t,extended s,BasePoint *pts,
+ extended t1s[3],extended t2s[3], int soln) {
+ int i;
+
+ for ( i=0; i<soln; ++i )
+ if ( x==pts[i].x && y==pts[i].y )
+return( soln );
+ t1s[soln] = t;
+ t2s[soln] = s;
+ pts[soln].x = x;
+ pts[soln].y = y;
+return( soln+1 );
+}
+
+static int AddQuadraticSoln(extended s,const Spline *s1, const Spline *s2, BasePoint pts[3],
+ extended t1s[3], extended t2s[3], int soln ) {
+ extended t, x, y, d;
+ int i;
+
+ if ( s<-.0001 || s>1.0001 )
+return( soln );
+ if ( s<0 ) s=0; else if ( s>1 ) s=1;
+
+ x = (s2->splines[0].b*s+s2->splines[0].c)*s+s2->splines[0].d;
+ y = (s2->splines[1].b*s+s2->splines[1].c)*s+s2->splines[1].d;
+
+ for ( i=0; i<soln; ++i )
+ if ( x==pts[i].x && y==pts[i].y )
+return( soln );
+
+ d = s1->splines[0].c*(extended) s1->splines[0].c-4*(extended) s1->splines[0].a*(s1->splines[0].d-x);
+ if ( RealNear(d,0)) d = 0;
+ if ( d<0 )
+return( soln );
+ t = (-s1->splines[0].c-d)/(2*s1->splines[0].b);
+ if ( t>-.0001 && t<1.0001 ) {
+ if ( t<=0 ) {t=0; x=s1->from->me.x; y = s1->from->me.y; }
+ else if ( t>=1 ) { t=1; x=s1->to->me.x; y = s1->to->me.y; }
+ if ( RealNear(y, (s1->splines[1].b*t+s1->splines[1].c)*t+s1->splines[1].d ) )
+return( AddPoint(x,y,t,s,pts,t1s,t2s,soln));
+ }
+ t = (-s1->splines[0].c+d)/(2*s1->splines[0].b);
+ if ( t>-.0001 && t<1.0001 ) {
+ if ( t<=0 ) {t=0; x=s1->from->me.x; y = s1->from->me.y; }
+ else if ( t>=1 ) { t=1; x=s1->to->me.x; y = s1->to->me.y; }
+ if ( RealNear(y, (s1->splines[1].b*t+s1->splines[1].c)*t+s1->splines[1].d) )
+return( AddPoint(x,y,t,s,pts,t1s,t2s,soln));
+ }
+return( soln );
+}
+
+static void IterateSolve(const Spline1D *sp,extended ts[3]) {
+ /* The closed form solution has too many rounding errors for my taste... */
+ int i,j;
+
+ ts[0] = ts[1] = ts[2] = -1;
+
+ if ( sp->a!=0 ) {
+ extended e[4];
+ e[0] = 0; e[1] = e[2] = e[3] = 1.0;
+ SplineFindExtrema(sp,&e[1],&e[2]);
+ if ( e[1]==-1 ) e[1] = 1;
+ if ( e[2]==-1 ) e[2] = 1;
+ for ( i=j=0; i<3; ++i ) {
+ ts[j] = IterateSplineSolve(sp,e[i],e[i+1],0,.0001);
+ if ( ts[j]!=-1 ) ++j;
+ if ( e[i+1]==1.0 )
+ break;
+ }
+ } else if ( sp->b!=0 ) {
+ extended b2_4ac = sp->c*(extended) sp->c - 4*sp->b*(extended) sp->d;
+ if ( b2_4ac>=0 ) {
+ b2_4ac = esqrt(b2_4ac);
+ ts[0] = (-sp->c-b2_4ac)/(2*sp->b);
+ ts[1] = (-sp->c+b2_4ac)/(2*sp->b);
+ if ( ts[0]>ts[1] ) { bigreal t = ts[0]; ts[0] = ts[1]; ts[1] = t; }
+ }
+ } else if ( sp->c!=0 ) {
+ ts[0] = -sp->d/(extended) sp->c;
+ } else
+ /* No solutions, or all solutions */;
+
+ for ( i=j=0; i<3; ++i )
+ if ( ts[i]>=0 && ts[i]<=1 )
+ ts[j++] = ts[i];
+ for ( i=0; i<j-1; ++i )
+ if ( ts[i]+.0000001>ts[i+1]) {
+ ts[i] = (ts[i]+ts[i+1])/2;
+ --j;
+ for ( ++i; i<j; ++i )
+ ts[i] = ts[i+1];
+ }
+ if ( j!=0 ) {
+ if ( ts[0]!=0 ) {
+ extended d0 = sp->d;
+ extended dt = ((sp->a*ts[0]+sp->b)*ts[0]+sp->c)*ts[0]+sp->d;
+ if ( d0<0 ) d0=-d0;
+ if ( dt<0 ) dt=-dt;
+ if ( d0<dt )
+ ts[0] = 0;
+ }
+ if ( ts[j-1]!=1.0 ) {
+ extended d1 = sp->a+(extended) sp->b+sp->c+sp->d;
+ extended dt = ((sp->a*ts[j-1]+sp->b)*ts[j-1]+sp->c)*ts[j-1]+sp->d;
+ if ( d1<0 ) d1=-d1;
+ if ( dt<0 ) dt=-dt;
+ if ( d1<dt )
+ ts[j-1] = 1;
+ }
+ }
+ for ( ; j<3; ++j )
+ ts[j] = -1;
+}
+
+static extended ISolveWithin(const Spline1D *sp,extended val,extended tlow, extended thigh) {
+ Spline1D temp;
+ extended ts[3];
+ int i;
+
+ temp = *sp;
+ temp.d -= val;
+ IterateSolve(&temp,ts);
+ if ( tlow<thigh ) {
+ for ( i=0; i<3; ++i )
+ if ( ts[i]>=tlow && ts[i]<=thigh )
+return( ts[i] );
+ for ( i=0; i<3; ++i ) {
+ if ( ts[i]>=tlow-1./1024. && ts[i]<=tlow )
+return( tlow );
+ if ( ts[i]>=thigh && ts[i]<=thigh+1./1024 )
+return( thigh );
+ }
+ } else {
+ for ( i=0; i<3; ++i )
+ if ( ts[i]>=thigh && ts[i]<=tlow )
+return( ts[i] );
+ for ( i=0; i<3; ++i ) {
+ if ( ts[i]>=thigh-1./1024. && ts[i]<=thigh )
+return( thigh );
+ if ( ts[i]>=tlow && ts[i]<=tlow+1./1024 )
+return( tlow );
+ }
+ }
+return( -1 );
+}
+
+static int ICAddInter(int cnt,BasePoint *foundpos,extended *foundt1,extended *foundt2,
+ const Spline *s1,const Spline *s2,extended t1,extended t2) {
+ foundt1[cnt] = t1;
+ foundt2[cnt] = t2;
+ foundpos[cnt].x = ((s1->splines[0].a*t1+s1->splines[0].b)*t1+
+ s1->splines[0].c)*t1+s1->splines[0].d;
+ foundpos[cnt].y = ((s1->splines[1].a*t1+s1->splines[1].b)*t1+
+ s1->splines[1].c)*t1+s1->splines[1].d;
+return( cnt+1 );
+}
+
+static int ICBinarySearch(int cnt,BasePoint *foundpos,extended *foundt1,extended *foundt2,
+ int other,
+ const Spline *s1,const Spline *s2,extended t1low,extended t1high,extended t2low,extended t2high) {
+ int major;
+ extended t1, t2;
+ extended o1o, o2o, o1n, o2n, m;
+
+ major = !other;
+ o1o = ((s1->splines[other].a*t1low+s1->splines[other].b)*t1low+
+ s1->splines[other].c)*t1low+s1->splines[other].d;
+ o2o = ((s2->splines[other].a*t2low+s2->splines[other].b)*t2low+
+ s2->splines[other].c)*t2low+s2->splines[other].d;
+ forever {
+ t1 = (t1low+t1high)/2;
+ m = ((s1->splines[major].a*t1+s1->splines[major].b)*t1+
+ s1->splines[major].c)*t1+s1->splines[major].d;
+ t2 = ISolveWithin(&s2->splines[major],m,t2low,t2high);
+ if ( t2==-1 )
+return( cnt );
+
+ o1n = ((s1->splines[other].a*t1+s1->splines[other].b)*t1+
+ s1->splines[other].c)*t1+s1->splines[other].d;
+ o2n = ((s2->splines[other].a*t2+s2->splines[other].b)*t2+
+ s2->splines[other].c)*t2+s2->splines[other].d;
+ if (( o1n-o2n<.001 && o1n-o2n>-.001) ||
+ (t1-t1low<.0001 && t1-t1low>-.0001))
+return( ICAddInter(cnt,foundpos,foundt1,foundt2,s1,s2,t1,t2));
+ if ( (o1o>o2o && o1n<o2n) || (o1o<o2o && o1n>o2n)) {
+ t1high = t1;
+ t2high = t2;
+ } else {
+ t1low = t1;
+ t2low = t2;
+ }
+ }
+}
+
+static int CubicsIntersect(const Spline *s1,extended lowt1,extended hight1,BasePoint *min1,BasePoint *max1,
+ const Spline *s2,extended lowt2,extended hight2,BasePoint *min2,BasePoint *max2,
+ BasePoint *foundpos,extended *foundt1,extended *foundt2) {
+ int major, other;
+ BasePoint max, min;
+ extended t1max, t1min, t2max, t2min, t1, t2, t1diff, oldt2;
+ extended o1o, o2o, o1n, o2n, m;
+ int cnt=0;
+
+ if ( (min.x = min1->x)<min2->x ) min.x = min2->x;
+ if ( (min.y = min1->y)<min2->y ) min.y = min2->y;
+ if ( (max.x = max1->x)>max2->x ) max.x = max2->x;
+ if ( (max.y = max1->y)>max2->y ) max.y = max2->y;
+ if ( max.x<min.x || max.y<min.y )
+return( 0 );
+ if ( max.x-min.x > max.y-min.y )
+ major = 0;
+ else
+ major = 1;
+ other = 1-major;
+
+ t1max = ISolveWithin(&s1->splines[major],(&max.x)[major],lowt1,hight1);
+ t1min = ISolveWithin(&s1->splines[major],(&min.x)[major],lowt1,hight1);
+ t2max = ISolveWithin(&s2->splines[major],(&max.x)[major],lowt2,hight2);
+ t2min = ISolveWithin(&s2->splines[major],(&min.x)[major],lowt2,hight2);
+ if ( t1max==-1 || t1min==-1 || t2max==-1 || t1min==-1 )
+return( 0 );
+ t1diff = (t1max-t1min)/64.0;
+ if ( t1diff==0 )
+return( 0 );
+
+ t1 = t1min; t2 = t2min;
+ o1o = ((s1->splines[other].a*t1+s1->splines[other].b)*t1+
+ s1->splines[other].c)*t1+s1->splines[other].d;
+ o2o = ((s2->splines[other].a*t2+s2->splines[other].b)*t2+
+ s2->splines[other].c)*t2+s2->splines[other].d;
+ if ( o1o==o2o )
+ cnt = ICAddInter(cnt,foundpos,foundt1,foundt2,s1,s2,t1,t2);
+ forever {
+ t1 += t1diff;
+ if (( t1max>t1min && t1>t1max ) || (t1max<t1min && t1<t1max) || cnt>3 )
+ break;
+ m = ((s1->splines[major].a*t1+s1->splines[major].b)*t1+
+ s1->splines[major].c)*t1+s1->splines[major].d;
+ oldt2 = t2;
+ t2 = ISolveWithin(&s2->splines[major],m,lowt2,hight2);
+ if ( t2==-1 )
+ continue;
+
+ o1n = ((s1->splines[other].a*t1+s1->splines[other].b)*t1+
+ s1->splines[other].c)*t1+s1->splines[other].d;
+ o2n = ((s2->splines[other].a*t2+s2->splines[other].b)*t2+
+ s2->splines[other].c)*t2+s2->splines[other].d;
+ if ( o1n==o2n )
+ cnt = ICAddInter(cnt,foundpos,foundt1,foundt2,s1,s2,t1,t2);
+ if ( (o1o>o2o && o1n<o2n) || (o1o<o2o && o1n>o2n))
+ cnt = ICBinarySearch(cnt,foundpos,foundt1,foundt2,other,
+ s1,s2,t1-t1diff,t1,oldt2,t2);
+ o1o = o1n; o2o = o2n;
+ }
+return( cnt );
+}
+
+static int Closer(const Spline *s1,const Spline *s2,extended t1,extended t2,extended t1p,extended t2p) {
+ double x1 = ((s1->splines[0].a*t1+s1->splines[0].b)*t1+s1->splines[0].c)*t1+s1->splines[0].c;
+ double y1 = ((s1->splines[1].a*t1+s1->splines[1].b)*t1+s1->splines[1].c)*t1+s1->splines[1].c;
+ double x2 = ((s2->splines[0].a*t2+s2->splines[0].b)*t2+s2->splines[0].c)*t2+s2->splines[0].c;
+ double y2 = ((s2->splines[1].a*t2+s2->splines[1].b)*t2+s2->splines[1].c)*t2+s2->splines[1].c;
+ double diff = abs(x1-x2) + abs(y1-y2);
+ double x1p = ((s1->splines[0].a*t1p+s1->splines[0].b)*t1p+s1->splines[0].c)*t1p+s1->splines[0].c;
+ double y1p = ((s1->splines[1].a*t1p+s1->splines[1].b)*t1p+s1->splines[1].c)*t1p+s1->splines[1].c;
+ double x2p = ((s2->splines[0].a*t2p+s2->splines[0].b)*t2p+s2->splines[0].c)*t2p+s2->splines[0].c;
+ double y2p = ((s2->splines[1].a*t2p+s2->splines[1].b)*t2p+s2->splines[1].c)*t2p+s2->splines[1].c;
+ double diffp = abs(x1p-x2p) + abs(y1p-y2p);
+
+ if ( diff<diffp )
+return( false );
+
+return( true );
+}
+
+/* returns 0=>no intersection, 1=>at least one, location in pts, t1s, t2s */
+/* -1 => We couldn't figure it out in a closed form, have to do a numerical */
+/* approximation */
+int SplinesIntersect(const Spline *s1, const Spline *s2, BasePoint pts[9],
+ extended t1s[10], extended t2s[10]) { /* One extra for a trailing -1 */
+ BasePoint min1, max1, min2, max2;
+ int soln = 0;
+ extended x,y,s,t, ac0, ac1;
+ extended d;
+ int i,j,found;
+ Spline1D spline, temp;
+ Quartic quad;
+ extended tempts[4]; /* 3 solns for cubics, 4 for quartics */
+ extended extrema1[6], extrema2[6];
+ int ecnt1, ecnt2;
+
+ t1s[0] = t1s[1] = t1s[2] = t1s[3] = -1;
+ t2s[0] = t2s[1] = t2s[2] = t2s[3] = -1;
+
+ if ( s1==s2 && !s1->knownlinear && !s1->isquadratic )
+ /* Special case see if it doubles back on itself anywhere */;
+ else if ( s1==s2 )
+return( 0 ); /* Linear and quadratics can't double back, can't self-intersect */
+ else if ( s1->splines[0].a == s2->splines[0].a &&
+ s1->splines[0].b == s2->splines[0].b &&
+ s1->splines[0].c == s2->splines[0].c &&
+ s1->splines[0].d == s2->splines[0].d &&
+ s1->splines[1].a == s2->splines[1].a &&
+ s1->splines[1].b == s2->splines[1].b &&
+ s1->splines[1].c == s2->splines[1].c &&
+ s1->splines[1].d == s2->splines[1].d )
+return( -1 ); /* Same spline. Intersects everywhere */
+
+ /* Ignore splines which are just a point */
+ if ( s1->knownlinear && s1->splines[0].c==0 && s1->splines[1].c==0 )
+return( 0 );
+ if ( s2->knownlinear && s2->splines[0].c==0 && s2->splines[1].c==0 )
+return( 0 );
+
+ if ( s1->knownlinear )
+ /* Do Nothing */;
+ else if ( s2->knownlinear || (!s1->isquadratic && s2->isquadratic)) {
+ const Spline *stemp = s1;
+ extended *ts = t1s;
+ t1s = t2s; t2s = ts;
+ s1 = s2; s2 = stemp;
+ }
+
+ min1 = s1->from->me; max1 = min1;
+ min2 = s2->from->me; max2 = min2;
+ if ( s1->from->nextcp.x>max1.x ) max1.x = s1->from->nextcp.x;
+ else if ( s1->from->nextcp.x<min1.x ) min1.x = s1->from->nextcp.x;
+ if ( s1->from->nextcp.y>max1.y ) max1.y = s1->from->nextcp.y;
+ else if ( s1->from->nextcp.y<min1.y ) min1.y = s1->from->nextcp.y;
+ if ( s1->to->prevcp.x>max1.x ) max1.x = s1->to->prevcp.x;
+ else if ( s1->to->prevcp.x<min1.x ) min1.x = s1->to->prevcp.x;
+ if ( s1->to->prevcp.y>max1.y ) max1.y = s1->to->prevcp.y;
+ else if ( s1->to->prevcp.y<min1.y ) min1.y = s1->to->prevcp.y;
+ if ( s1->to->me.x>max1.x ) max1.x = s1->to->me.x;
+ else if ( s1->to->me.x<min1.x ) min1.x = s1->to->me.x;
+ if ( s1->to->me.y>max1.y ) max1.y = s1->to->me.y;
+ else if ( s1->to->me.y<min1.y ) min1.y = s1->to->me.y;
+
+ if ( s2->from->nextcp.x>max2.x ) max2.x = s2->from->nextcp.x;
+ else if ( s2->from->nextcp.x<min2.x ) min2.x = s2->from->nextcp.x;
+ if ( s2->from->nextcp.y>max2.y ) max2.y = s2->from->nextcp.y;
+ else if ( s2->from->nextcp.y<min2.y ) min2.y = s2->from->nextcp.y;
+ if ( s2->to->prevcp.x>max2.x ) max2.x = s2->to->prevcp.x;
+ else if ( s2->to->prevcp.x<min2.x ) min2.x = s2->to->prevcp.x;
+ if ( s2->to->prevcp.y>max2.y ) max2.y = s2->to->prevcp.y;
+ else if ( s2->to->prevcp.y<min2.y ) min2.y = s2->to->prevcp.y;
+ if ( s2->to->me.x>max2.x ) max2.x = s2->to->me.x;
+ else if ( s2->to->me.x<min2.x ) min2.x = s2->to->me.x;
+ if ( s2->to->me.y>max2.y ) max2.y = s2->to->me.y;
+ else if ( s2->to->me.y<min2.y ) min2.y = s2->to->me.y;
+ if ( min1.x>max2.x || min2.x>max1.x || min1.y>max2.y || min2.y>max1.y )
+return( false ); /* no intersection of bounding boxes */
+
+#if 0
+ soln = CheckEndpoint(&s1->from->me,s2,0,pts,t1s,t2s,soln);
+ soln = CheckEndpoint(&s1->to->me,s2,1,pts,t1s,t2s,soln);
+ soln = CheckEndpoint(&s2->from->me,s1,0,pts,t2s,t1s,soln);
+ soln = CheckEndpoint(&s2->to->me,s1,1,pts,t2s,t1s,soln);
+#endif
+
+ if ( s1->knownlinear ) {
+ spline.d = s1->splines[1].c*(s2->splines[0].d-s1->splines[0].d)-
+ s1->splines[0].c*(s2->splines[1].d-s1->splines[1].d);
+ spline.c = s1->splines[1].c*s2->splines[0].c - s1->splines[0].c*s2->splines[1].c;
+ spline.b = s1->splines[1].c*s2->splines[0].b - s1->splines[0].c*s2->splines[1].b;
+ spline.a = s1->splines[1].c*s2->splines[0].a - s1->splines[0].c*s2->splines[1].a;
+ IterateSolve(&spline,tempts);
+ if ( tempts[0]==-1 )
+return( false );
+ for ( i = 0; i<3 && tempts[i]!=-1; ++i ) {
+ x = ((s2->splines[0].a*tempts[i]+s2->splines[0].b)*tempts[i]+
+ s2->splines[0].c)*tempts[i]+s2->splines[0].d;
+ y = ((s2->splines[1].a*tempts[i]+s2->splines[1].b)*tempts[i]+
+ s2->splines[1].c)*tempts[i]+s2->splines[1].d;
+ if ( (ac0 = s1->splines[0].c)<0 ) ac0 = -ac0;
+ if ( (ac1 = s1->splines[1].c)<0 ) ac1 = -ac1;
+ if ( ac0>ac1 )
+ t = (x-s1->splines[0].d)/s1->splines[0].c;
+ else
+ t = (y-s1->splines[1].d)/s1->splines[1].c;
+ if ( tempts[i]>.999 && Closer(s1,s2,tempts[i],t,1,t))
+ tempts[i] = 1;
+ else if ( tempts[i]<.001 && Closer(s1,s2,tempts[i],t,0,t))
+ tempts[i] = 0;
+ if ( t>.999 && Closer(s1,s2,tempts[i],t,tempts[i],1))
+ t = 1;
+ else if ( t<.001 && Closer(s1,s2,tempts[i],t,tempts[i],0))
+ t = 0;
+ if ( t<-.001 || t>1.001 || x<min1.x-.01 || y<min1.y-.01 || x>max1.x+.01 || y>max1.y+.01 )
+ continue;
+ if ( t<=0 ) {t=0; x=s1->from->me.x; y = s1->from->me.y; }
+ else if ( t>=1 ) { t=1; x=s1->to->me.x; y = s1->to->me.y; }
+ if ( s1->from->me.x==s1->to->me.x ) /* Avoid rounding errors */
+ x = s1->from->me.x; /* on hor/vert lines */
+ else if ( s1->from->me.y==s1->to->me.y )
+ y = s1->from->me.y;
+ if ( s2->knownlinear ) {
+ if ( s2->from->me.x==s2->to->me.x )
+ x = s2->from->me.x;
+ else if ( s2->from->me.y==s2->to->me.y )
+ y = s2->from->me.y;
+ }
+ soln = AddPoint(x,y,t,tempts[i],pts,t1s,t2s,soln);
+ }
+return( soln!=0 );
+ } else if ( s1->isquadratic && s2->isquadratic ) {
+ temp.a = 0;
+ temp.b = s1->splines[1].b*s2->splines[0].b - s1->splines[0].b*s2->splines[1].b;
+ temp.c = s1->splines[1].b*s2->splines[0].c - s1->splines[0].b*s2->splines[1].c;
+ temp.d = s1->splines[1].b*(s2->splines[0].d-s1->splines[0].d) -
+ s1->splines[0].b*(s2->splines[1].d-s1->splines[1].d);
+ d = s1->splines[1].b*s1->splines[0].c - s1->splines[0].b*s1->splines[1].c;
+ if ( RealNear(d,0)) d=0;
+ if ( d!=0 ) {
+ temp.b /= d; temp.c /= d; temp.d /= d;
+ /* At this point t= temp.b*s^2 + temp.c*s + temp.d */
+ /* We substitute this back into one of our equations and get a */
+ /* quartic in s */
+ quad.a = s1->splines[0].b*temp.b*temp.b;
+ quad.b = s1->splines[0].b*2*temp.b*temp.c;
+ quad.c = s1->splines[0].b*(2*temp.b*temp.d+temp.c*temp.c);
+ quad.d = s1->splines[0].b*2*temp.d*temp.c;
+ quad.e = s1->splines[0].b*temp.d*temp.d;
+ quad.b+= s1->splines[0].c*temp.b;
+ quad.c+= s1->splines[0].c*temp.c;
+ quad.d+= s1->splines[0].c*temp.d;
+ quad.e+= s1->splines[0].d;
+ quad.e-= s2->splines[0].d;
+ quad.d-= s2->splines[0].c;
+ quad.c-= s2->splines[0].b;
+ if ( QuarticSolve(&quad,tempts)==-1 )
+return( -1 );
+ for ( i=0; i<4 && tempts[i]!=-999999; ++i )
+ soln = AddQuadraticSoln(tempts[i],s1,s2,pts,t1s,t2s,soln);
+ } else {
+ d = temp.c*temp.c-4*temp.b*temp.c;
+ if ( RealNear(d,0)) d = 0;
+ if ( d<0 )
+return( soln!=0 );
+ d = sqrt(d);
+ s = (-temp.c-d)/(2*temp.b);
+ soln = AddQuadraticSoln(s,s1,s2,pts,t1s,t2s,soln);
+ s = (-temp.c+d)/(2*temp.b);
+ soln = AddQuadraticSoln(s,s1,s2,pts,t1s,t2s,soln);
+ }
+return( soln!=0 );
+ }
+ /* if one of the splines is quadratic then we can get an expression */
+ /* relating c*t+d to poly(s^3), and substituting this back we get */
+ /* a poly of degree 6 in s which could be solved iteratively */
+ /* however mixed quadratics and cubics are unlikely */
+
+ /* but if both splines are degree 3, the t is expressed as the sqrt of */
+ /* a third degree poly, which must be substituted into a cubic, and */
+ /* then squared to get rid of the sqrts leaving us with an ?18? degree */
+ /* poly. Ick. */
+
+ /* So let's do it the hard way... we break the splines into little bits */
+ /* where they are monotonic in both dimensions, then check these for */
+ /* possible intersections */
+ extrema1[0] = extrema2[0] = 0;
+ ecnt1 = Spline2DFindExtrema(s1,extrema1+1);
+ ecnt2 = Spline2DFindExtrema(s2,extrema2+1);
+ extrema1[++ecnt1] = 1.0;
+ extrema2[++ecnt2] = 1.0;
+ found=0;
+ for ( i=0; i<ecnt1; ++i ) {
+ min1.x = ((s1->splines[0].a*extrema1[i]+s1->splines[0].b)*extrema1[i]+
+ s1->splines[0].c)*extrema1[i]+s1->splines[0].d;
+ min1.y = ((s1->splines[1].a*extrema1[i]+s1->splines[1].b)*extrema1[i]+
+ s1->splines[1].c)*extrema1[i]+s1->splines[1].d;
+ max1.x = ((s1->splines[0].a*extrema1[i+1]+s1->splines[0].b)*extrema1[i+1]+
+ s1->splines[0].c)*extrema1[i+1]+s1->splines[0].d;
+ max1.y = ((s1->splines[1].a*extrema1[i+1]+s1->splines[1].b)*extrema1[i+1]+
+ s1->splines[1].c)*extrema1[i+1]+s1->splines[1].d;
+ if ( max1.x<min1.x ) { extended temp = max1.x; max1.x = min1.x; min1.x = temp; }
+ if ( max1.y<min1.y ) { extended temp = max1.y; max1.y = min1.y; min1.y = temp; }
+ for ( j=(s1==s2)?i+1:0; j<ecnt2; ++j ) {
+ min2.x = ((s2->splines[0].a*extrema2[j]+s2->splines[0].b)*extrema2[j]+
+ s2->splines[0].c)*extrema2[j]+s2->splines[0].d;
+ min2.y = ((s2->splines[1].a*extrema2[j]+s2->splines[1].b)*extrema2[j]+
+ s2->splines[1].c)*extrema2[j]+s2->splines[1].d;
+ max2.x = ((s2->splines[0].a*extrema2[j+1]+s2->splines[0].b)*extrema2[j+1]+
+ s2->splines[0].c)*extrema2[j+1]+s2->splines[0].d;
+ max2.y = ((s2->splines[1].a*extrema2[j+1]+s2->splines[1].b)*extrema2[j+1]+
+ s2->splines[1].c)*extrema2[j+1]+s2->splines[1].d;
+ if ( max2.x<min2.x ) { extended temp = max2.x; max2.x = min2.x; min2.x = temp; }
+ if ( max2.y<min2.y ) { extended temp = max2.y; max2.y = min2.y; min2.y = temp; }
+ if ( min1.x>max2.x || min2.x>max1.x || min1.y>max2.y || min2.y>max1.y )
+ /* No possible intersection */;
+ else if ( s1!=s2 )
+ found += CubicsIntersect(s1,extrema1[i],extrema1[i+1],&min1,&max1,
+ s2,extrema2[j],extrema2[j+1],&min2,&max2,
+ &pts[found],&t1s[found],&t2s[found]);
+ else {
+ int k,l;
+ int cnt = CubicsIntersect(s1,extrema1[i],extrema1[i+1],&min1,&max1,
+ s2,extrema2[j],extrema2[j+1],&min2,&max2,
+ &pts[found],&t1s[found],&t2s[found]);
+ for ( k=0; k<cnt; ++k ) {
+ if ( RealNear(t1s[found+k],t2s[found+k]) ) {
+ for ( l=k+1; l<cnt; ++l ) {
+ pts[found+l-1] = pts[found+l];
+ t1s[found+l-1] = t1s[found+l];
+ t2s[found+l-1] = t2s[found+l];
+ }
+ --cnt; --k;
+ }
+ }
+ found += cnt;
+ }
+ }
+ }
+ t1s[found] = t2s[found] = -1;
+return( found!=0 );
+}
+
+/* Puts all the contours of the glyph together. Next routine undoes this */
+SplineSet *LayerAllSplines(Layer *layer) {
+ SplineSet *head=NULL, *last=NULL;
+ RefChar *r;
+
+ head = layer->splines;
+ if ( head!=NULL )
+ for ( last=head; last->next!=NULL; last = last->next );
+ for ( r=layer->refs; r!=NULL; r=r->next ) {
+ if ( last!=NULL ) {
+ last->next = r->layers[0].splines;
+ for ( ; last->next!=NULL; last=last->next );
+ } else {
+ head = r->layers[0].splines;
+ if ( head!=NULL )
+ for ( last=head; last->next!=NULL; last = last->next );
+ }
+ }
+return( head );
+}
+
+SplineSet *LayerUnAllSplines(Layer *layer) {
+ SplineSet *spl = layer->splines;
+ RefChar *r = layer->refs;
+
+ if ( spl==NULL ) {
+ while ( r!=NULL && r->layers[0].splines==NULL )
+ r = r->next;
+ if ( r==NULL )
+return( NULL );
+ spl = r->layers[0].splines;
+ r = r->next;
+ }
+ while ( r!=NULL ) {
+ while ( spl!=NULL && spl->next!=r->layers[0].splines )
+ spl = spl->next;
+ spl->next = NULL;
+ spl = r->layers[0].splines;
+ r = r->next;
+ }
+return( layer->splines );
+}
+
+int SplineSetIntersect(SplineSet *spl, Spline **_spline, Spline **_spline2) {
+ BasePoint pts[9];
+ extended t1s[10], t2s[10];
+ int found = false,i;
+ SplineSet *test, *test2;
+ Spline *spline, *spline2, *first, *first2;
+
+ for ( test=spl; test!=NULL ; test=test->next ) {
+ first = NULL;
+ for ( spline = test->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) {
+ if ( first==NULL ) first = spline;
+ for ( test2=test; test2!=NULL; test2=test2->next ) {
+ first2 = test2==test && first!=spline ? first : NULL;
+ for ( spline2=(test2==test)?spline : test2->first->next;
+ spline2!=NULL && spline2!=first2; spline2 = spline2->to->next ) {
+ if ( first2==NULL ) first2 = spline2;
+ if ( SplinesIntersect(spline,spline2,pts,t1s,t2s)) {
+ if ( spline->to->next!=spline2 && spline->from->prev!=spline2 )
+ found = true;
+ else for ( i=0; i<10 && t1s[i]!=-1; ++i ) {
+ if ( (t1s[i]<.9 && t1s[i]>.1) || (t2s[i]<.9 && t2s[i]>.1)) {
+ found = true;
+ break;
+ }
+ }
+ if ( found )
+ break;
+ }
+ }
+ if ( found )
+ break;
+ }
+ if ( found )
+ break;
+ }
+ if ( found )
+ break;
+ }
+ if ( found ) {
+ *_spline = spline;
+ *_spline2 = spline2;
+ }
+return( found );
+}
+
+int LineTangentToSplineThroughPt(Spline *s, BasePoint *pt, extended ts[4],
+ extended tmin, extended tmax) {
+ /* attempt to find a line though the point pt which is tangent to the spline */
+ /* we return t of the tangent point on the spline (if any) */
+ /* So the slope of the line through pt&tangent point must match slope */
+ /* at the tangent point on the spline. Or... */
+ /* (pt.x-xt)/(pt.y-yt) = (dx/dt)/(dy/dt) */
+ /* (pt.x-xt)*(dy/dt) = (pt.y-yt)*(dx/dt) */
+ /* (pt.x - ax*t^3 - bx*t^2 - cx*t - dx)(3ay*t^2 + 2by*t + cy) = */
+ /* (pt.y - ay*t^3 - by*t^2 - cy*t^2 - dy)(3ax*t^2 + 2bx*t + cx) */
+ /* (-ax*3ay + ay*3ax) * t^5 + */
+ /* (-ax*2by - bx*3ay + ay*2bx + by*3ax) * t^4 + */
+ /* (-ax*cy - bx*2by - cx*3ay + ay*cx + by*2bx + cy*3ax) * t^3 + */
+ /* (pt.x*3ay - bx*cy - cx*2by - dx*3ay - pt.y*3ax + by*cx + cy*2bx + dy*3ax) * t^2 + */
+ /* (pt.x*2by - cx*cy - dx*2by - pt.y*2bx + cy*cx + dy*2bx) * t + */
+ /* (pt.x*cy - dx*cy - pt.y*cx + dy*cx) = 0 */
+ /* Yeah! The order 5 terms cancel out */
+ /* (ax*by - bx*ay) * t^4 + */
+ /* (2*ax*cy - 2*cx*ay) * t^3 + */
+ /* (3*pt.x*ay + bx*cy - cx*by - 3*dx*ay - 3*pt.y*ax + 3*dy*ax) * t^2 + */
+ /* (2*pt.x*by - 2*dx*by - 2*pt.y*bx + 2*dy*bx) * t + */
+ /* (pt.x*cy - dx*cy - pt.y*cx + dy*cx) = 0 */
+ Quartic quad;
+ int i,j,k;
+
+ if ( !finite(pt->x) || !finite(pt->y) ) {
+ IError( "Non-finite arguments passed to LineTangentToSplineThroughPt");
+return( -1 );
+ }
+
+ quad.a = s->splines[0].a*s->splines[1].b - s->splines[0].b*s->splines[1].a;
+ quad.b = 2*s->splines[0].a*s->splines[1].c - 2*s->splines[0].c*s->splines[1].a;
+ quad.c = 3*pt->x*s->splines[1].a + s->splines[0].b*s->splines[1].c - s->splines[0].c*s->splines[1].b - 3*s->splines[0].d*s->splines[1].a - 3*pt->y*s->splines[0].a + 3*s->splines[1].d*s->splines[0].a;
+ quad.d = 2*pt->x*s->splines[1].b - 2*s->splines[0].d*s->splines[1].b - 2*pt->y*s->splines[0].b + 2*s->splines[1].d*s->splines[0].b;
+ quad.e = pt->x*s->splines[1].c - s->splines[0].d*s->splines[1].c - pt->y*s->splines[0].c + s->splines[1].d*s->splines[0].c;
+
+ if ( _QuarticSolve(&quad,ts)==-1 )
+return( -1 );
+
+ for ( i=0; i<4 && ts[i]!=-999999; ++i ) {
+ if ( ts[i]>tmin-.0001 && ts[i]<tmin ) ts[i] = tmin;
+ if ( ts[i]>tmax && ts[i]<tmax+.001 ) ts[i] = tmax;
+ if ( ts[i]>tmax || ts[i]<tmin ) ts[i] = -999999;
+ }
+ for ( i=3; i>=0 && ts[i]==-999999; --i );
+ if ( i==-1 )
+return( -1 );
+ for ( j=i ; j>=0 ; --j ) {
+ if ( ts[j]<0 ) {
+ for ( k=j+1; k<=i; ++k )
+ ts[k-1] = ts[k];
+ ts[i--] = -999999;
+ }
+ }
+return(i+1);
+}
+
+static int XSolve(Spline *spline,real tmin, real tmax,FindSel *fs) {
+ Spline1D *yspline = &spline->splines[1], *xspline = &spline->splines[0];
+ bigreal t,x,y;
+
+ fs->p->t = t = SplineSolve(xspline,tmin,tmax,fs->p->cx,.001);
+ if ( t>=0 && t<=1 ) {
+ y = ((yspline->a*t+yspline->b)*t+yspline->c)*t + yspline->d;
+ if ( fs->yl<y && fs->yh>y )
+return( true );
+ }
+ /* Although we know that globaly there's more x change, locally there */
+ /* maybe more y change */
+ fs->p->t = t = SplineSolve(yspline,tmin,tmax,fs->p->cy,.001);
+ if ( t>=0 && t<=1 ) {
+ x = ((xspline->a*t+xspline->b)*t+xspline->c)*t + xspline->d;
+ if ( fs->xl<x && fs->xh>x )
+return( true );
+ }
+return( false );
+}
+
+static int YSolve(Spline *spline,real tmin, real tmax,FindSel *fs) {
+ Spline1D *yspline = &spline->splines[1], *xspline = &spline->splines[0];
+ bigreal t,x,y;
+
+ fs->p->t = t = SplineSolve(yspline,tmin,tmax,fs->p->cy,.001);
+ if ( t>=0 && t<=1 ) {
+ x = ((xspline->a*t+xspline->b)*t+xspline->c)*t + xspline->d;
+ if ( fs->xl<x && fs->xh>x )
+return( true );
+ }
+ /* Although we know that globaly there's more y change, locally there */
+ /* maybe more x change */
+ fs->p->t = t = SplineSolve(xspline,tmin,tmax,fs->p->cx,.001);
+ if ( t>=0 && t<=1 ) {
+ y = ((yspline->a*t+yspline->b)*t+yspline->c)*t + yspline->d;
+ if ( fs->yl<y && fs->yh>y )
+return( true );
+ }
+return( false );
+}
+
+static int NearXSpline(FindSel *fs, Spline *spline) {
+ /* If we get here we've checked the bounding box and we're in it */
+ /* the y spline is a horizontal line */
+ /* the x spline is not linear */
+ bigreal t,y;
+ Spline1D *yspline = &spline->splines[1], *xspline = &spline->splines[0];
+
+ if ( xspline->a!=0 ) {
+ extended t1, t2, tbase;
+ SplineFindExtrema(xspline,&t1,&t2);
+ tbase = 0;
+ if ( t1!=-1 ) {
+ if ( XSolve(spline,0,t1,fs))
+return( true );
+ tbase = t1;
+ }
+ if ( t2!=-1 ) {
+ if ( XSolve(spline,tbase,t2,fs))
+return( true );
+ tbase = t2;
+ }
+ if ( XSolve(spline,tbase,1.0,fs))
+return( true );
+ } else if ( xspline->b!=0 ) {
+ bigreal root = xspline->c*xspline->c - 4*xspline->b*(xspline->d-fs->p->cx);
+ if ( root < 0 )
+return( false );
+ root = sqrt(root);
+ fs->p->t = t = (-xspline->c + root)/(2*xspline->b);
+ if ( t>=0 && t<=1 ) {
+ y = ((yspline->a*t+yspline->b)*t+yspline->c)*t + yspline->d;
+ if ( fs->yl<y && fs->yh>y )
+return( true );
+ }
+ fs->p->t = t = (-xspline->c - root)/(2*xspline->b);
+ if ( t>=0 && t<=1 ) {
+ y = ((yspline->a*t+yspline->b)*t+yspline->c)*t + yspline->d;
+ if ( fs->yl<y && fs->yh>y )
+return( true );
+ }
+ } else /* xspline->c can't be 0 because dx>dy => dx!=0 => xspline->c!=0 */ {
+ fs->p->t = t = (fs->p->cx-xspline->d)/xspline->c;
+ y = ((yspline->a*t+yspline->b)*t+yspline->c)*t + yspline->d;
+ if ( fs->yl<y && fs->yh>y )
+return( true );
+ }
+return( false );
+}
+
+int NearSpline(FindSel *fs, Spline *spline) {
+ bigreal t,x,y;
+ Spline1D *yspline = &spline->splines[1], *xspline = &spline->splines[0];
+ bigreal dx, dy;
+
+ if (( dx = spline->to->me.x-spline->from->me.x)<0 ) dx = -dx;
+ if (( dy = spline->to->me.y-spline->from->me.y)<0 ) dy = -dy;
+
+ if ( spline->knownlinear ) {
+ if ( fs->xl > spline->from->me.x && fs->xl > spline->to->me.x )
+return( false );
+ if ( fs->xh < spline->from->me.x && fs->xh < spline->to->me.x )
+return( false );
+ if ( fs->yl > spline->from->me.y && fs->yl > spline->to->me.y )
+return( false );
+ if ( fs->yh < spline->from->me.y && fs->yh < spline->to->me.y )
+return( false );
+ if ( xspline->c==0 && yspline->c==0 ) /* It's a point. */
+return( true );
+ if ( dy>dx ) {
+ t = (fs->p->cy-yspline->d)/yspline->c;
+ fs->p->t = t;
+ x = xspline->c*t + xspline->d;
+ if ( fs->xl<x && fs->xh>x && t>=0 && t<=1 )
+return( true );
+ } else {
+ t = (fs->p->cx-xspline->d)/xspline->c;
+ fs->p->t = t;
+ y = yspline->c*t + yspline->d;
+ if ( fs->yl<y && fs->yh>y && t>=0 && t<=1 )
+return( true );
+ }
+return( false );
+ } else {
+ if ( fs->xl > spline->from->me.x && fs->xl > spline->to->me.x &&
+ fs->xl > spline->from->nextcp.x && fs->xl > spline->to->prevcp.x )
+return( false );
+ if ( fs->xh < spline->from->me.x && fs->xh < spline->to->me.x &&
+ fs->xh < spline->from->nextcp.x && fs->xh < spline->to->prevcp.x )
+return( false );
+ if ( fs->yl > spline->from->me.y && fs->yl > spline->to->me.y &&
+ fs->yl > spline->from->nextcp.y && fs->yl > spline->to->prevcp.y )
+return( false );
+ if ( fs->yh < spline->from->me.y && fs->yh < spline->to->me.y &&
+ fs->yh < spline->from->nextcp.y && fs->yh < spline->to->prevcp.y )
+return( false );
+
+ if ( dx>dy )
+return( NearXSpline(fs,spline));
+ else if ( yspline->a == 0 && yspline->b == 0 ) {
+ fs->p->t = t = (fs->p->cy-yspline->d)/yspline->c;
+ x = ((xspline->a*t+xspline->b)*t+xspline->c)*t + xspline->d;
+ if ( fs->xl<x && fs->xh>x && t>=0 && t<=1 )
+return( true );
+ } else if ( yspline->a==0 ) {
+ bigreal root = yspline->c*yspline->c - 4*yspline->b*(yspline->d-fs->p->cy);
+ if ( root < 0 )
+return( false );
+ root = sqrt(root);
+ fs->p->t = t = (-yspline->c + root)/(2*yspline->b);
+ x = ((xspline->a*t+xspline->b)*t+xspline->c)*t + xspline->d;
+ if ( fs->xl<x && fs->xh>x && t>0 && t<1 )
+return( true );
+ fs->p->t = t = (-yspline->c - root)/(2*yspline->b);
+ x = ((xspline->a*t+xspline->b)*t+xspline->c)*t + xspline->d;
+ if ( fs->xl<x && fs->xh>x && t>=0 && t<=1 )
+return( true );
+ } else {
+ extended t1, t2, tbase;
+ SplineFindExtrema(yspline,&t1,&t2);
+ tbase = 0;
+ if ( t1!=-1 ) {
+ if ( YSolve(spline,0,t1,fs))
+return( true );
+ tbase = t1;
+ }
+ if ( t2!=-1 ) {
+ if ( YSolve(spline,tbase,t2,fs))
+return( true );
+ tbase = t2;
+ }
+ if ( YSolve(spline,tbase,1.0,fs))
+return( true );
+ }
+ }
+return( false );
+}
+
+real SplineNearPoint(Spline *spline, BasePoint *bp, real fudge) {
+ PressedOn p;
+ FindSel fs;
+
+ memset(&fs,'\0',sizeof(fs));
+ memset(&p,'\0',sizeof(p));
+ fs.p = &p;
+ p.cx = bp->x;
+ p.cy = bp->y;
+ fs.fudge = fudge;
+ fs.xl = p.cx-fudge;
+ fs.xh = p.cx+fudge;
+ fs.yl = p.cy-fudge;
+ fs.yh = p.cy+fudge;
+ if ( !NearSpline(&fs,spline))
+return( -1 );
+
+return( p.t );
+}
+
+static int SplinePrevMinMax(Spline *s,int up) {
+ const double t = .9999;
+ double y;
+ int pup;
+
+ s = s->from->prev;
+ while ( s->from->me.y==s->to->me.y && s->islinear )
+ s = s->from->prev;
+ y = ((s->splines[1].a*t + s->splines[1].b)*t + s->splines[1].c)*t + s->splines[1].d;
+ pup = s->to->me.y > y;
+return( pup!=up );
+}
+
+static int SplineNextMinMax(Spline *s,int up) {
+ const double t = .0001;
+ double y;
+ int nup;
+
+ s = s->to->next;
+ while ( s->from->me.y==s->to->me.y && s->islinear )
+ s = s->to->next;
+ y = ((s->splines[1].a*t + s->splines[1].b)*t + s->splines[1].c)*t + s->splines[1].d;
+ nup = y > s->from->me.y;
+return( nup!=up );
+}
+
+static int Crossings(Spline *s,BasePoint *pt) {
+ extended ext[4];
+ int i, cnt=0;
+ bigreal yi, yi1, t, x;
+
+ ext[0] = 0; ext[3] = 1.0;
+ SplineFindExtrema(&s->splines[1],&ext[1],&ext[2]);
+ if ( ext[2]!=-1 && SplineAtInflection(&s->splines[1],ext[2])) ext[2]=-1;
+ if ( ext[1]!=-1 && SplineAtInflection(&s->splines[1],ext[1])) {ext[1] = ext[2]; ext[2]=-1;}
+ if ( ext[1]==-1 ) ext[1] = 1.0;
+ else if ( ext[2]==-1 ) ext[2] = 1.0;
+ yi = s->splines[1].d;
+ for ( i=0; ext[i]!=1.0; ++i, yi=yi1 ) {
+ yi1 = ((s->splines[1].a*ext[i+1]+s->splines[1].b)*ext[i+1]+s->splines[1].c)*ext[i+1]+s->splines[1].d;
+ if ( yi==yi1 )
+ continue; /* Ignore horizontal lines */
+ if ( (yi>yi1 && (pt->y<yi1 || pt->y>yi)) ||
+ (yi<yi1 && (pt->y<yi || pt->y>yi1)) )
+ continue;
+ t = IterateSplineSolve(&s->splines[1],ext[i],ext[i+1],pt->y,.0001);
+ if ( t==-1 )
+ continue;
+ x = ((s->splines[0].a*t+s->splines[0].b)*t+s->splines[0].c)*t+s->splines[0].d;
+ if ( x>=pt->x ) /* Things on the edge are not inside */
+ continue;
+ if (( ext[i]!=0 && RealApprox(t,ext[i]) && SplineAtMinMax(&s->splines[1],ext[i]) ) ||
+ ( ext[i+1]!=1 && RealApprox(t,ext[i+1]) && SplineAtMinMax(&s->splines[1],ext[i+1]) ))
+ continue; /* Min/Max points don't add to count */
+ if (( RealApprox(t,0) && SplinePrevMinMax(s,yi1>yi) ) ||
+ ( RealApprox(t,1) && SplineNextMinMax(s,yi1>yi) ))
+ continue; /* ditto */
+ if ( pt->y==yi1 ) /* Not a min/max. prev/next spline continues same direction */
+ continue; /* If it's at an endpoint we don't want to count it twice */
+ /* So only add to count at start endpoint, never at final */
+ if ( yi1>yi )
+ ++cnt;
+ else
+ --cnt;
+ }
+return( cnt );
+}
+
+/* Return whether this point is within the set of contours in spl */
+/* Draw a line from [-infinity,pt.y] to [pt.x,pt.y] and count contour crossings */
+int SSPointWithin(SplineSet *spl,BasePoint *pt) {
+ int cnt=0;
+ Spline *s, *first;
+
+ while ( spl!=NULL ) {
+ if ( spl->first->prev!=NULL ) {
+ first = NULL;
+ for ( s = spl->first->next; s!=first; s=s->to->next ) {
+ if ( first==NULL ) first = s;
+ if (( s->from->me.x>pt->x && s->from->nextcp.x>pt->x &&
+ s->to->me.x>pt->x && s->to->prevcp.x>pt->x) ||
+ ( s->from->me.y>pt->y && s->from->nextcp.y>pt->y &&
+ s->to->me.y>pt->y && s->to->prevcp.y>pt->y) ||
+ ( s->from->me.y<pt->y && s->from->nextcp.y<pt->y &&
+ s->to->me.y<pt->y && s->to->prevcp.y<pt->y))
+ continue;
+ cnt += Crossings(s,pt);
+ }
+ }
+ spl = spl->next;
+ }
+return( cnt!=0 );
+}
+
+void StemInfoFree(StemInfo *h) {
+ HintInstance *hi, *n;
+
+ for ( hi=h->where; hi!=NULL; hi=n ) {
+ n = hi->next;
+ chunkfree(hi,sizeof(HintInstance));
+ }
+ chunkfree(h,sizeof(StemInfo));
+}
+
+void StemInfosFree(StemInfo *h) {
+ StemInfo *hnext;
+ HintInstance *hi, *n;
+
+ for ( ; h!=NULL; h = hnext ) {
+ for ( hi=h->where; hi!=NULL; hi=n ) {
+ n = hi->next;
+ chunkfree(hi,sizeof(HintInstance));
+ }
+ hnext = h->next;
+ chunkfree(h,sizeof(StemInfo));
+ }
+}
+
+void DStemInfoFree(DStemInfo *h) {
+
+ chunkfree(h,sizeof(DStemInfo));
+}
+
+void DStemInfosFree(DStemInfo *h) {
+ DStemInfo *hnext;
+
+ for ( ; h!=NULL; h = hnext ) {
+ hnext = h->next;
+ chunkfree(h,sizeof(DStemInfo));
+ }
+}
+
+StemInfo *StemInfoCopy(StemInfo *h) {
+ StemInfo *head=NULL, *last=NULL, *cur;
+ HintInstance *hilast, *hicur, *hi;
+
+ for ( ; h!=NULL; h = h->next ) {
+ cur = chunkalloc(sizeof(StemInfo));
+ *cur = *h;
+ cur->next = NULL;
+ if ( head==NULL )
+ head = last = cur;
+ else {
+ last->next = cur;
+ last = cur;
+ }
+ cur->where = hilast = NULL;
+ for ( hi=h->where; hi!=NULL; hi=hi->next ) {
+ hicur = chunkalloc(sizeof(StemInfo));
+ *hicur = *hi;
+ hicur->next = NULL;
+ if ( hilast==NULL )
+ cur->where = hilast = hicur;
+ else {
+ hilast->next = hicur;
+ hilast = hicur;
+ }
+ }
+ }
+return( head );
+}
+
+DStemInfo *DStemInfoCopy(DStemInfo *h) {
+ DStemInfo *head=NULL, *last=NULL, *cur;
+
+ for ( ; h!=NULL; h = h->next ) {
+ cur = chunkalloc(sizeof(DStemInfo));
+ *cur = *h;
+ cur->next = NULL;
+ if ( head==NULL )
+ head = last = cur;
+ else {
+ last->next = cur;
+ last = cur;
+ }
+ }
+return( head );
+}
+
+MinimumDistance *MinimumDistanceCopy(MinimumDistance *md) {
+ MinimumDistance *head=NULL, *last=NULL, *cur;
+
+ for ( ; md!=NULL; md = md->next ) {
+ cur = chunkalloc(sizeof(DStemInfo));
+ *cur = *md;
+ cur->next = NULL;
+ if ( head==NULL )
+ head = last = cur;
+ else {
+ last->next = cur;
+ last = cur;
+ }
+ }
+return( head );
+}
+
+void KernPairsFree(KernPair *kp) {
+ KernPair *knext;
+ for ( ; kp!=NULL; kp = knext ) {
+ knext = kp->next;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( kp->adjust!=NULL ) {
+ free(kp->adjust->corrections);
+ chunkfree(kp->adjust,sizeof(DeviceTable));
+ }
+#endif
+ chunkfree(kp,sizeof(KernPair));
+ }
+}
+
+static AnchorPoint *AnchorPointsRemoveName(AnchorPoint *alist,AnchorClass *an) {
+ AnchorPoint *prev=NULL, *ap, *next;
+
+ for ( ap=alist; ap!=NULL; ap=next ) {
+ next = ap->next;
+ if ( ap->anchor == an ) {
+ if ( prev==NULL )
+ alist = next;
+ else
+ prev->next = next;
+ ap->next = NULL;
+ AnchorPointsFree(ap);
+ if ( ap->type==at_mark || ap->type==at_basechar || ap->type==at_basemark )
+ next = NULL; /* Names only occur once, unless it's a ligature or cursive */
+ } else
+ prev = ap;
+ }
+return( alist );
+}
+
+static void SCRemoveAnchorClass(SplineChar *sc,AnchorClass *an) {
+ Undoes *test;
+
+ if ( sc==NULL )
+return;
+ sc->anchor = AnchorPointsRemoveName(sc->anchor,an);
+ for ( test = sc->layers[ly_fore].undoes; test!=NULL; test=test->next )
+ if ( test->undotype==ut_state || test->undotype==ut_tstate ||
+ test->undotype==ut_statehint || test->undotype==ut_statename )
+ test->u.state.anchor = AnchorPointsRemoveName(test->u.state.anchor,an);
+ for ( test = sc->layers[ly_fore].redoes; test!=NULL; test=test->next )
+ if ( test->undotype==ut_state || test->undotype==ut_tstate ||
+ test->undotype==ut_statehint || test->undotype==ut_statename )
+ test->u.state.anchor = AnchorPointsRemoveName(test->u.state.anchor,an);
+}
+
+void SFRemoveAnchorClass(SplineFont *sf,AnchorClass *an) {
+ int i;
+ AnchorClass *prev, *test;
+
+ PasteRemoveAnchorClass(sf,an);
+
+ for ( i=0; i<sf->glyphcnt; ++i )
+ SCRemoveAnchorClass(sf->glyphs[i],an);
+ prev = NULL;
+ for ( test=sf->anchor; test!=NULL; test=test->next ) {
+ if ( test==an ) {
+ if ( prev==NULL )
+ sf->anchor = test->next;
+ else
+ prev->next = test->next;
+ chunkfree(test,sizeof(AnchorClass));
+ break;
+ } else
+ prev = test;
+ }
+}
+
+AnchorPoint *APAnchorClassMerge(AnchorPoint *anchors,AnchorClass *into,AnchorClass *from) {
+ AnchorPoint *api=NULL, *prev, *ap, *next;
+
+ prev = NULL;
+ for ( ap=anchors; ap!=NULL; ap=next ) {
+ next = ap->next;
+ if ( ap->anchor==from ) {
+ for ( api=anchors; api!=NULL; api=api->next ) {
+ if ( api->anchor==into &&
+ (api->type!=at_baselig || ap->type!=at_baselig || api->lig_index==ap->lig_index))
+ break;
+ }
+ if ( api==NULL && into!=NULL ) {
+ ap->anchor = into;
+ prev = ap;
+ } else {
+ if ( prev==NULL )
+ anchors = next;
+ else
+ prev->next = next;
+ ap->next = NULL;
+ AnchorPointsFree(ap);
+ }
+ } else
+ prev = ap;
+ }
+return( anchors );
+}
+
+void AnchorClassMerge(SplineFont *sf,AnchorClass *into,AnchorClass *from) {
+ int i;
+
+ if ( into==from )
+return;
+ PasteAnchorClassMerge(sf,into,from);
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ SplineChar *sc = sf->glyphs[i];
+
+ sc->anchor = APAnchorClassMerge(sc->anchor,into,from);
+ }
+}
+
+AnchorPoint *AnchorPointsCopy(AnchorPoint *alist) {
+ AnchorPoint *head=NULL, *last=NULL, *ap;
+
+ while ( alist!=NULL ) {
+ ap = chunkalloc(sizeof(AnchorPoint));
+ *ap = *alist;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( ap->xadjust.corrections!=NULL ) {
+ int len = ap->xadjust.last_pixel_size-ap->xadjust.first_pixel_size+1;
+ ap->xadjust.corrections = galloc(len);
+ memcpy(ap->xadjust.corrections,alist->xadjust.corrections,len);
+ }
+ if ( ap->yadjust.corrections!=NULL ) {
+ int len = ap->yadjust.last_pixel_size-ap->yadjust.first_pixel_size+1;
+ ap->yadjust.corrections = galloc(len);
+ memcpy(ap->yadjust.corrections,alist->yadjust.corrections,len);
+ }
+#endif
+ if ( head==NULL )
+ head = ap;
+ else
+ last->next = ap;
+ last = ap;
+ alist = alist->next;
+ }
+return( head );
+}
+
+void AnchorPointsFree(AnchorPoint *ap) {
+ AnchorPoint *anext;
+ for ( ; ap!=NULL; ap = anext ) {
+ anext = ap->next;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ free(ap->xadjust.corrections);
+ free(ap->yadjust.corrections);
+#endif
+ chunkfree(ap,sizeof(AnchorPoint));
+ }
+}
+
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+void ValDevFree(ValDevTab *adjust) {
+ if ( adjust==NULL )
+return;
+ free( adjust->xadjust.corrections );
+ free( adjust->yadjust.corrections );
+ free( adjust->xadv.corrections );
+ free( adjust->yadv.corrections );
+ chunkfree(adjust,sizeof(ValDevTab));
+}
+
+ValDevTab *ValDevTabCopy(ValDevTab *orig) {
+ ValDevTab *new;
+ int i;
+
+ if ( orig==NULL )
+return( NULL );
+ new = chunkalloc(sizeof(ValDevTab));
+ for ( i=0; i<4; ++i ) {
+ if ( (&orig->xadjust)[i].corrections!=NULL ) {
+ int len = (&orig->xadjust)[i].last_pixel_size - (&orig->xadjust)[i].first_pixel_size + 1;
+ (&new->xadjust)[i] = (&orig->xadjust)[i];
+ (&new->xadjust)[i].corrections = galloc(len);
+ memcpy((&new->xadjust)[i].corrections,(&orig->xadjust)[i].corrections,len);
+ }
+ }
+return( new );
+}
+
+void DeviceTableFree(DeviceTable *dt) {
+
+ if ( dt==NULL )
+return;
+
+ free(dt->corrections);
+ chunkfree(dt,sizeof(DeviceTable));
+}
+
+DeviceTable *DeviceTableCopy(DeviceTable *orig) {
+ DeviceTable *new;
+ int len;
+
+ if ( orig==NULL )
+return( NULL );
+ new = chunkalloc(sizeof(DeviceTable));
+ *new = *orig;
+ len = orig->last_pixel_size - orig->first_pixel_size + 1;
+ new->corrections = galloc(len);
+ memcpy(new->corrections,orig->corrections,len);
+return( new );
+}
+
+void DeviceTableSet(DeviceTable *adjust, int size, int correction) {
+ int len, i, j;
+
+ len = adjust->last_pixel_size-adjust->first_pixel_size + 1;
+ if ( correction==0 ) {
+ if ( adjust->corrections==NULL ||
+ size<adjust->first_pixel_size ||
+ size>adjust->last_pixel_size )
+return;
+ adjust->corrections[size-adjust->first_pixel_size] = 0;
+ for ( i=0; i<len; ++i )
+ if ( adjust->corrections[i]!=0 )
+ break;
+ if ( i==len ) {
+ free(adjust->corrections);
+ memset(adjust,0,sizeof(DeviceTable));
+ } else {
+ if ( i!=0 ) {
+ for ( j=0; j<len-i; ++j )
+ adjust->corrections[j] = adjust->corrections[j+i];
+ adjust->first_pixel_size += i;
+ len -= i;
+ }
+ for ( i=len-1; i>=0; --i )
+ if ( adjust->corrections[i]!=0 )
+ break;
+ adjust->last_pixel_size = adjust->first_pixel_size+i;
+ }
+ } else {
+ if ( adjust->corrections==NULL ) {
+ adjust->first_pixel_size = adjust->last_pixel_size = size;
+ adjust->corrections = galloc(1);
+ } else if ( size>=adjust->first_pixel_size &&
+ size<=adjust->last_pixel_size ) {
+ } else if ( size>adjust->last_pixel_size ) {
+ adjust->corrections = grealloc(adjust->corrections,
+ size-adjust->first_pixel_size);
+ for ( i=len; i<size-adjust->first_pixel_size; ++i )
+ adjust->corrections[i] = 0;
+ adjust->last_pixel_size = size;
+ } else {
+ int8 *new = galloc(adjust->last_pixel_size-size+1);
+ memset(new,0,adjust->first_pixel_size-size);
+ memcpy(new+adjust->first_pixel_size-size,
+ adjust->corrections, len);
+ adjust->first_pixel_size = size;
+ free(adjust->corrections);
+ adjust->corrections = new;
+ }
+ adjust->corrections[size-adjust->first_pixel_size] = correction;
+ }
+}
+#endif
+
+void PSTFree(PST *pst) {
+ PST *pnext;
+ for ( ; pst!=NULL; pst = pnext ) {
+ pnext = pst->next;
+ if ( pst->type==pst_lcaret )
+ free(pst->u.lcaret.carets);
+ else if ( pst->type==pst_pair ) {
+ free(pst->u.pair.paired);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ ValDevFree(pst->u.pair.vr[0].adjust);
+ ValDevFree(pst->u.pair.vr[1].adjust);
+#endif
+ chunkfree(pst->u.pair.vr,sizeof(struct vr [2]));
+ } else if ( pst->type!=pst_position ) {
+ free(pst->u.subs.variant);
+ } else if ( pst->type==pst_position ) {
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ ValDevFree(pst->u.pos.adjust);
+#endif
+ }
+ chunkfree(pst,sizeof(PST));
+ }
+}
+
+void MinimumDistancesFree(MinimumDistance *md) {
+ MinimumDistance *next;
+
+ while ( md!=NULL ) {
+ next = md->next;
+ chunkfree(md,sizeof(MinimumDistance));
+ md = next;
+ }
+}
+
+void TTFLangNamesFree(struct ttflangname *l) {
+ struct ttflangname *next;
+ int i;
+
+ while ( l!=NULL ) {
+ next = l->next;
+ for ( i=0; i<ttf_namemax; ++i )
+ free(l->names[i]);
+ chunkfree(l,sizeof(*l));
+ l = next;
+ }
+}
+
+void AltUniFree(struct altuni *altuni) {
+ struct altuni *next;
+
+ while ( altuni ) {
+ next = altuni->next;
+ chunkfree(altuni,sizeof(struct altuni));
+ altuni = next;
+ }
+}
+
+void LayerDefault(Layer *layer) {
+ memset(layer,0,sizeof(Layer));
+#ifdef FONTFORGE_CONFIG_TYPE3
+ layer->fill_brush.opacity = layer->stroke_pen.brush.opacity = 1.0;
+ layer->fill_brush.col = layer->stroke_pen.brush.col = COLOR_INHERITED;
+ layer->stroke_pen.width = 10;
+ layer->stroke_pen.linecap = lc_round;
+ layer->stroke_pen.linejoin = lj_round;
+ layer->dofill = true;
+ layer->fillfirst = true;
+ layer->stroke_pen.trans[0] = layer->stroke_pen.trans[3] = 1.0;
+ layer->stroke_pen.trans[1] = layer->stroke_pen.trans[2] = 0.0;
+ /* Dashes default to an unbroken line */
+#endif
+}
+
+SplineChar *SplineCharCreate(void) {
+ SplineChar *sc = chunkalloc(sizeof(SplineChar));
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ sc->color = COLOR_DEFAULT;
+#endif
+ sc->orig_pos = 0xffff;
+ sc->unicodeenc = -1;
+ sc->layer_cnt = 2;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ sc->layers = gcalloc(2,sizeof(Layer));
+ LayerDefault(&sc->layers[0]);
+ LayerDefault(&sc->layers[1]);
+#endif
+ sc->tex_height = sc->tex_depth = sc->tex_sub_pos = sc->tex_super_pos =
+ TEX_UNDEF;
+return( sc );
+}
+
+void SplineCharListsFree(struct splinecharlist *dlist) {
+ struct splinecharlist *dnext;
+ for ( ; dlist!=NULL; dlist = dnext ) {
+ dnext = dlist->next;
+ chunkfree(dlist,sizeof(struct splinecharlist));
+ }
+}
+
+void SplineCharFreeContents(SplineChar *sc) {
+ int i;
+
+ if ( sc==NULL )
+return;
+ free(sc->name);
+ free(sc->comment);
+ for ( i=0; i<sc->layer_cnt; ++i ) {
+ SplinePointListsFree(sc->layers[i].splines);
+ RefCharsFree(sc->layers[i].refs);
+ ImageListsFree(sc->layers[i].images);
+ /* image garbage collection????!!!! */
+ UndoesFree(sc->layers[i].undoes);
+ UndoesFree(sc->layers[i].redoes);
+ }
+ StemInfosFree(sc->hstem);
+ StemInfosFree(sc->vstem);
+ DStemInfosFree(sc->dstem);
+ MinimumDistancesFree(sc->md);
+ KernPairsFree(sc->kerns);
+ KernPairsFree(sc->vkerns);
+ AnchorPointsFree(sc->anchor);
+ SplineCharListsFree(sc->dependents);
+ PSTFree(sc->possub);
+ free(sc->ttf_instrs);
+ free(sc->countermasks);
+#ifdef FONTFORGE_CONFIG_TYPE3
+ free(sc->layers);
+#endif
+ AltUniFree(sc->altuni);
+#ifndef _NO_PYTHON
+ PyFF_FreeSC(sc);
+#endif
+}
+
+void SplineCharFree(SplineChar *sc) {
+
+ if ( sc==NULL )
+return;
+ SplineCharFreeContents(sc);
+ chunkfree(sc,sizeof(SplineChar));
+}
+
+void AnchorClassesFree(AnchorClass *an) {
+ AnchorClass *anext;
+ for ( ; an!=NULL; an = anext ) {
+ anext = an->next;
+ free(an->name);
+ chunkfree(an,sizeof(AnchorClass));
+ }
+}
+
+void TtfTablesFree(struct ttf_table *tab) {
+ struct ttf_table *next;
+
+ for ( ; tab!=NULL; tab = next ) {
+ next = tab->next;
+ free(tab->data);
+ chunkfree(tab,sizeof(struct ttf_table));
+ }
+}
+
+void ScriptLangListFree(struct scriptlanglist *sl) {
+ struct scriptlanglist *next;
+
+ while ( sl!=NULL ) {
+ next = sl->next;
+ free(sl->morelangs);
+ chunkfree(sl,sizeof(*sl));
+ sl = next;
+ }
+}
+
+void FeatureScriptLangListFree(FeatureScriptLangList *fl) {
+ FeatureScriptLangList *next;
+
+ while ( fl!=NULL ) {
+ next = fl->next;
+ ScriptLangListFree(fl->scripts);
+ chunkfree(fl,sizeof(*fl));
+ fl = next;
+ }
+}
+
+void OTLookupFree(OTLookup *lookup) {
+ struct lookup_subtable *st, *stnext;
+
+ free(lookup->lookup_name);
+ FeatureScriptLangListFree(lookup->features);
+ for ( st=lookup->subtables; st!=NULL; st=stnext ) {
+ stnext = st->next;
+ free(st->subtable_name);
+ free(st->suffix);
+ chunkfree(st,sizeof(struct lookup_subtable));
+ }
+ chunkfree( lookup,sizeof(OTLookup) );
+}
+
+void OTLookupListFree(OTLookup *lookup ) {
+ OTLookup *next;
+
+ for ( ; lookup!=NULL; lookup = next ) {
+ next = lookup->next;
+ OTLookupFree(lookup);
+ }
+}
+
+KernClass *KernClassCopy(KernClass *kc) {
+ KernClass *new;
+ int i;
+
+ if ( kc==NULL )
+return( NULL );
+ new = chunkalloc(sizeof(KernClass));
+ *new = *kc;
+ new->firsts = galloc(new->first_cnt*sizeof(char *));
+ new->seconds = galloc(new->second_cnt*sizeof(char *));
+ new->offsets = galloc(new->first_cnt*new->second_cnt*sizeof(int16));
+ memcpy(new->offsets,kc->offsets, new->first_cnt*new->second_cnt*sizeof(int16));
+ for ( i=0; i<new->first_cnt; ++i )
+ new->firsts[i] = copy(kc->firsts[i]);
+ for ( i=0; i<new->second_cnt; ++i )
+ new->seconds[i] = copy(kc->seconds[i]);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ new->adjusts = gcalloc(new->first_cnt*new->second_cnt,sizeof(DeviceTable));
+ memcpy(new->adjusts,kc->adjusts, new->first_cnt*new->second_cnt*sizeof(DeviceTable));
+ for ( i=new->first_cnt*new->second_cnt-1; i>=0 ; --i ) {
+ if ( new->adjusts[i].corrections!=NULL ) {
+ int8 *old = new->adjusts[i].corrections;
+ int len = new->adjusts[i].last_pixel_size - new->adjusts[i].first_pixel_size + 1;
+ new->adjusts[i].corrections = galloc(len);
+ memcpy(new->adjusts[i].corrections,old,len);
+ }
+ }
+#endif
+ new->next = NULL;
+return( new );
+}
+
+void KernClassFreeContents(KernClass *kc) {
+ int i;
+
+ for ( i=1; i<kc->first_cnt; ++i )
+ free(kc->firsts[i]);
+ for ( i=1; i<kc->second_cnt; ++i )
+ free(kc->seconds[i]);
+ free(kc->firsts);
+ free(kc->seconds);
+ free(kc->offsets);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ for ( i=kc->first_cnt*kc->second_cnt-1; i>=0 ; --i )
+ free(kc->adjusts[i].corrections);
+ free(kc->adjusts);
+#endif
+}
+
+void KernClassListFree(KernClass *kc) {
+ KernClass *n;
+
+ while ( kc ) {
+ KernClassFreeContents(kc);
+ n = kc->next;
+ chunkfree(kc,sizeof(KernClass));
+ kc = n;
+ }
+}
+
+void MacNameListFree(struct macname *mn) {
+ struct macname *next;
+
+ while ( mn!=NULL ) {
+ next = mn->next;
+ free(mn->name);
+ chunkfree(mn,sizeof(struct macname));
+ mn = next;
+ }
+}
+
+void MacSettingListFree(struct macsetting *ms) {
+ struct macsetting *next;
+
+ while ( ms!=NULL ) {
+ next = ms->next;
+ MacNameListFree(ms->setname);
+ chunkfree(ms,sizeof(struct macsetting));
+ ms = next;
+ }
+}
+
+void MacFeatListFree(MacFeat *mf) {
+ MacFeat *next;
+
+ while ( mf!=NULL ) {
+ next = mf->next;
+ MacNameListFree(mf->featname);
+ MacSettingListFree(mf->settings);
+ chunkfree(mf,sizeof(MacFeat));
+ mf = next;
+ }
+}
+
+void ASMFree(ASM *sm) {
+ ASM *next;
+ int i;
+
+ while ( sm!=NULL ) {
+ next = sm->next;
+ if ( sm->type==asm_insert ) {
+ for ( i=0; i<sm->class_cnt*sm->state_cnt; ++i ) {
+ free( sm->state[i].u.insert.mark_ins );
+ free( sm->state[i].u.insert.cur_ins );
+ }
+ } else if ( sm->type==asm_kern ) {
+ for ( i=0; i<sm->class_cnt*sm->state_cnt; ++i ) {
+ free( sm->state[i].u.kern.kerns );
+ }
+ }
+ for ( i=4; i<sm->class_cnt; ++i )
+ free(sm->classes[i]);
+ free(sm->state);
+ free(sm->classes);
+ chunkfree(sm,sizeof(ASM));
+ sm = next;
+ }
+}
+
+void OtfNameListFree(struct otfname *on) {
+ struct otfname *on_next;
+
+ for ( ; on!=NULL; on = on_next ) {
+ on_next = on->next;
+ free(on->name);
+ chunkfree(on,sizeof(*on));
+ }
+}
+
+EncMap *EncMapNew(int enccount,int backmax,Encoding *enc) {
+ EncMap *map = chunkalloc(sizeof(EncMap));
+
+ map->enccount = map->encmax = enccount;
+ map->backmax = backmax;
+ map->map = galloc(enccount*sizeof(int));
+ memset(map->map,-1,enccount*sizeof(int));
+ map->backmap = galloc(backmax*sizeof(int));
+ memset(map->backmap,-1,backmax*sizeof(int));
+ map->enc = enc;
+return(map);
+}
+
+EncMap *EncMap1to1(int enccount) {
+ EncMap *map = chunkalloc(sizeof(EncMap));
+ /* Used for CID fonts where CID is same as orig_pos */
+ int i;
+
+ map->enccount = map->encmax = map->backmax = enccount;
+ map->map = galloc(enccount*sizeof(int));
+ map->backmap = galloc(enccount*sizeof(int));
+ for ( i=0; i<enccount; ++i )
+ map->map[i] = map->backmap[i] = i;
+ map->enc = &custom;
+return(map);
+}
+
+static void EncodingFree(Encoding *enc) {
+ int i;
+
+ if ( enc==NULL )
+return;
+ free(enc->enc_name);
+ free(enc->unicode);
+ if ( enc->psnames!=NULL ) {
+ for ( i=0; i<enc->char_cnt; ++i )
+ free(enc->psnames[i]);
+ free(enc->psnames);
+ }
+ free(enc);
+}
+
+void EncMapFree(EncMap *map) {
+ if ( map==NULL )
+return;
+
+ if ( map->enc->is_temporary )
+ EncodingFree(map->enc);
+ free(map->map);
+ free(map->backmap);
+ free(map->remap);
+ chunkfree(map,sizeof(EncMap));
+}
+
+EncMap *EncMapCopy(EncMap *map) {
+ EncMap *new;
+
+ new = chunkalloc(sizeof(EncMap));
+ *new = *map;
+ new->map = galloc(new->encmax*sizeof(int));
+ new->backmap = galloc(new->backmax*sizeof(int));
+ memcpy(new->map,map->map,new->enccount*sizeof(int));
+ memcpy(new->backmap,map->backmap,new->backmax*sizeof(int));
+ if ( map->remap ) {
+ int n;
+ for ( n=0; map->remap[n].infont!=-1; ++n );
+ new->remap = galloc(n*sizeof(struct remap));
+ memcpy(new->remap,map->remap,n*sizeof(struct remap));
+ }
+return( new );
+}
+
+void MarkClassFree(int cnt,char **classes,char **names) {
+ int i;
+
+ for ( i=1; i<cnt; ++i ) {
+ free( classes[i] );
+ free( names[i] );
+ }
+ free( classes );
+ free( names );
+}
+
+void SplineFontFree(SplineFont *sf) {
+ int i;
+ BDFFont *bdf, *bnext;
+
+ if ( sf==NULL )
+return;
+ if ( sf->mm!=NULL ) {
+ MMSetFree(sf->mm);
+return;
+ }
+ CopyBufferClearCopiedFrom(sf);
+ PasteRemoveSFAnchors(sf);
+ for ( bdf = sf->bitmaps; bdf!=NULL; bdf = bnext ) {
+ bnext = bdf->next;
+ BDFFontFree(bdf);
+ }
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ SplineCharFree(sf->glyphs[i]);
+ free(sf->glyphs);
+ free(sf->fontname);
+ free(sf->fullname);
+ free(sf->familyname);
+ free(sf->weight);
+ free(sf->copyright);
+ free(sf->comments);
+ free(sf->filename);
+ free(sf->origname);
+ free(sf->autosavename);
+ free(sf->version);
+ free(sf->xuid);
+ free(sf->cidregistry);
+ free(sf->ordering);
+ MacFeatListFree(sf->features);
+ /* We don't free the EncMap. That field is only a temporary pointer. Let the FontView free it, that's where it really lives */
+ SplinePointListsFree(sf->grid.splines);
+ AnchorClassesFree(sf->anchor);
+ TtfTablesFree(sf->ttf_tables);
+ UndoesFree(sf->grid.undoes);
+ UndoesFree(sf->grid.redoes);
+ PSDictFree(sf->private);
+ TTFLangNamesFree(sf->names);
+ for ( i=0; i<sf->subfontcnt; ++i )
+ SplineFontFree(sf->subfonts[i]);
+ free(sf->subfonts);
+ GlyphHashFree(sf);
+ OTLookupListFree(sf->gpos_lookups);
+ OTLookupListFree(sf->gsub_lookups);
+ KernClassListFree(sf->kerns);
+ KernClassListFree(sf->vkerns);
+ FPSTFree(sf->possub);
+ ASMFree(sf->sm);
+ OtfNameListFree(sf->fontstyle_name);
+ MarkClassFree(sf->mark_class_cnt,sf->mark_classes,sf->mark_class_names);
+ free( sf->gasp );
+ free(sf);
+}
+
+void MMSetFreeContents(MMSet *mm) {
+ int i;
+
+ free(mm->instances);
+
+ free(mm->positions);
+ free(mm->defweights);
+
+ for ( i=0; i<mm->axis_count; ++i ) {
+ free(mm->axes[i]);
+ free(mm->axismaps[i].blends);
+ free(mm->axismaps[i].designs);
+ MacNameListFree(mm->axismaps[i].axisnames);
+ }
+ free(mm->axismaps);
+ free(mm->cdv);
+ free(mm->ndv);
+ for ( i=0; i<mm->named_instance_count; ++i ) {
+ free(mm->named_instances[i].coords);
+ MacNameListFree(mm->named_instances[i].names);
+ }
+ free(mm->named_instances);
+}
+
+void MMSetFree(MMSet *mm) {
+ int i;
+
+ for ( i=0; i<mm->instance_count; ++i ) {
+ mm->instances[i]->mm = NULL;
+ mm->instances[i]->map = NULL;
+ SplineFontFree(mm->instances[i]);
+ }
+ mm->normal->mm = NULL;
+ SplineFontFree(mm->normal); /* EncMap gets freed here */
+ MMSetFreeContents(mm);
+
+ chunkfree(mm,sizeof(*mm));
+}
+
+static int xcmp(const void *_p1, const void *_p2) {
+ const SplinePoint * const *_spt1 = _p1, * const *_spt2 = _p2;
+ const SplinePoint *sp1 = *_spt1, *sp2 = *_spt2;
+
+ if ( sp1->me.x>sp2->me.x )
+return( 1 );
+ else if ( sp1->me.x<sp2->me.x )
+return( -1 );
+
+return( 0 );
+}
+
+static int ycmp(const void *_p1, const void *_p2) {
+ const SplinePoint * const *_spt1 = _p1, * const *_spt2 = _p2;
+ const SplinePoint *sp1 = *_spt1, *sp2 = *_spt2;
+
+ if ( sp1->me.y>sp2->me.y )
+return( 1 );
+ else if ( sp1->me.y<sp2->me.y )
+return( -1 );
+
+return( 0 );
+}
+
+struct cluster {
+ int cnt;
+ int first, last;
+};
+
+static void countcluster(SplinePoint **ptspace, struct cluster *cspace,
+ int ptcnt, int is_y, int i, double within, double max) {
+ int j;
+
+ cspace[i].cnt = 1; /* current point is always within its own cluster */
+ cspace[i].first = cspace[i].last = i;
+ for ( j=i-1; j>=0; --j ) {
+ if ( cspace[j].cnt==0 ) /* Already allocated to a different cluster */
+ break;
+ if ( (&ptspace[j+1]->me.x)[is_y]-(&ptspace[j]->me.x)[is_y]<within &&
+ (&ptspace[i]->me.x)[is_y]-(&ptspace[j]->me.x)[is_y]<max ) {
+ ++cspace[i].cnt;
+ cspace[i].first = j;
+ } else
+ break;
+ }
+ for ( j=i+1; j<ptcnt; ++j ) {
+ if ( cspace[j].cnt==0 ) /* Already allocated to a different cluster */
+ break;
+ if ( (&ptspace[j]->me.x)[is_y]-(&ptspace[j-1]->me.x)[is_y]<within &&
+ (&ptspace[j]->me.x)[is_y]-(&ptspace[i]->me.x)[is_y]<max ) {
+ ++cspace[i].cnt;
+ cspace[i].last = j;
+ } else
+ break;
+ }
+}
+
+static int _SplineCharRoundToCluster(SplineChar *sc,SplinePoint **ptspace,
+ struct cluster *cspace,int ptcnt,int is_y,int dohints,
+ int layer, int changed,
+ double within, double max ) {
+ int i,j,best;
+ double low,high,cur;
+
+ for ( i=0; i<ptcnt; ++i )
+ cspace[i].cnt = 1; /* Initialize to non-zero */
+ for ( i=0; i<ptcnt; ++i )
+ countcluster(ptspace,cspace,ptcnt,is_y,i,within,max);
+
+ forever {
+ j=0; best = cspace[0].cnt;
+ for ( i=1; i<ptcnt; ++i ) {
+ if ( cspace[i].cnt>best ) {
+ j=i;
+ best = cspace[i].cnt;
+ }
+ }
+ if ( best<=1 ) /* No more clusters */
+return( changed );
+ for ( i=j+1; i<=cspace[j].last && cspace[i].cnt==cspace[j].cnt; ++i );
+ j = (j+i-1)/2; /* There are probably several points with the */
+ /* same values for cspace. Pick one in the */
+ /* middle, so that when round we round to the */
+ /* middle rather than to an edge */
+ low = (&ptspace[cspace[j].first]->me.x)[is_y];
+ high = (&ptspace[cspace[j].last]->me.x)[is_y];
+ cur = (&ptspace[j]->me.x)[is_y];
+ if ( low==high ) {
+ for ( i=cspace[j].first; i<=cspace[j].last; ++i )
+ cspace[i].cnt = 0;
+ continue;
+ }
+ if ( !changed ) {
+ if ( layer==-2 )
+ SCPreserveState(sc,dohints);
+ else if ( layer!=-1 )
+ SCPreserveLayer(sc,layer,dohints);
+ changed = true;
+ }
+ for ( i=cspace[j].first; i<=cspace[j].last; ++i ) {
+ double off = (&ptspace[i]->me.x)[is_y] - cur;
+ (&ptspace[i]->nextcp.x)[is_y] -= off;
+ (&ptspace[i]->prevcp.x)[is_y] -= off;
+ (&ptspace[i]->me.x)[is_y] -= off;
+ if ( (&ptspace[i]->prevcp.x)[is_y]-cur>-within &&
+ (&ptspace[i]->prevcp.x)[is_y]-cur<within ) {
+ (&ptspace[i]->prevcp.x)[is_y] = cur;
+ if ( (&ptspace[i]->prevcp.x)[!is_y]==(&ptspace[i]->me.x)[!is_y] )
+ ptspace[i]->noprevcp = true;
+ }
+ if ( (&ptspace[i]->nextcp.x)[is_y]-cur>-within &&
+ (&ptspace[i]->nextcp.x)[is_y]-cur<within ) {
+ (&ptspace[i]->nextcp.x)[is_y] = cur;
+ if ( (&ptspace[i]->nextcp.x)[!is_y]==(&ptspace[i]->me.x)[!is_y] )
+ ptspace[i]->nonextcp = true;
+ }
+ cspace[i].cnt = 0;
+ }
+ if ( dohints ) {
+ StemInfo *h = is_y ? sc->hstem : sc->vstem;
+ while ( h!=NULL && h->start<=high ) {
+ if ( h->start>=low ) {
+ h->width -= (h->start-cur);
+ h->start = cur;
+ }
+ if ( h->start+h->width>=low && h->start+h->width<=high )
+ h->width = cur-h->start;
+ h = h->next;
+ }
+ }
+ /* Ok, surrounding points can no longer use the ones allocated to */
+ /* this cluster. So refigure them */
+ for ( i=cspace[j].first-1; i>=0 &&
+ ( (&ptspace[i]->me.x)[is_y]-cur>-max && (&ptspace[i]->me.x)[is_y]-cur<max ); --i )
+ countcluster(ptspace,cspace,ptcnt,is_y,i,within,max);
+ for ( i=cspace[j].last+1; i<ptcnt &&
+ ( (&ptspace[i]->me.x)[is_y]-cur>-max && (&ptspace[i]->me.x)[is_y]-cur<max ); ++i )
+ countcluster(ptspace,cspace,ptcnt,is_y,i,within,max);
+ }
+}
+
+int SCRoundToCluster(SplineChar *sc,int layer,int sel,double within,double max) {
+ /* Do a cluster analysis on the points in this character. Look at each */
+ /* axis in turn. Order all points in char along this axis. For each pt: */
+ /* look at the two points before & after it. If those to pts are within */
+ /* the error bound (within) then continue until we reach a point that */
+ /* is further from its nearest point than "within" or is further from */
+ /* the center point than "max". Count all the points we have found. */
+ /* These points make up the cluster centered on this point. */
+ /* Then find the largest cluster & round everything to the center point */
+ /* (shift each point & its cps to center point. Then if cps are "within" */
+ /* set the cps to the center point too) */
+ /* Refigure all clusters within "max" of this one, Find the next largest */
+ /* cluster, and continue. We stop when the largest cluster has only one */
+ /* point in it */
+ /* if "sel" is true then we are only interested in selected points */
+ /* (if there are no selected points then all points in the current layer) */
+ /* if "layer"==-1 then use sf->grid. if layer==-2 then all foreground layers*/
+ /* if "layer"==ly_fore or -2 then round hints that fall in our clusters too*/
+ int ptcnt, selcnt;
+ int l,k,changed;
+ SplineSet *spl;
+ SplinePoint *sp;
+ SplinePoint **ptspace;
+ struct cluster *cspace;
+ Spline *s, *first;
+
+ ptspace = NULL;
+ /* First figure out what points we will need */
+ for ( k=0; k<2; ++k ) {
+ ptcnt = selcnt = 0;
+ if ( layer==-2 ) {
+ for ( l=ly_fore; l<sc->layer_cnt; ++l ) {
+ for ( spl = sc->layers[l].splines; spl!=NULL; spl=spl->next ) {
+ for ( sp = spl->first; ; ) {
+ if ( k && (!sel || (sel && sp->selected)) )
+ ptspace[ptcnt++] = sp;
+ else if ( !k )
+ ++ptcnt;
+ if ( sp->selected ) ++selcnt;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ }
+ }
+ } else {
+ if ( layer==-1 )
+ spl = sc->parent->grid.splines;
+ else
+ spl = sc->layers[layer].splines;
+ for ( ; spl!=NULL; spl=spl->next ) {
+ for ( sp = spl->first; ; ) {
+ if ( k && (!sel || (sel && sp->selected)) )
+ ptspace[ptcnt++] = sp;
+ else if ( !k )
+ ++ptcnt;
+ if ( sp->selected ) ++selcnt;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ }
+ }
+ if ( sel && selcnt==0 )
+ sel = false;
+ if ( sel ) ptcnt = selcnt;
+ if ( ptcnt<=1 )
+return(false); /* Can't be any clusters */
+ if ( k==0 )
+ ptspace = galloc((ptcnt+1)*sizeof(SplinePoint *));
+ else
+ ptspace[ptcnt] = NULL;
+ }
+
+ cspace = galloc(ptcnt*sizeof(struct cluster));
+
+ qsort(ptspace,ptcnt,sizeof(SplinePoint *),xcmp);
+ changed = _SplineCharRoundToCluster(sc,ptspace,cspace,ptcnt,false,
+ (layer==-2 || layer==ly_fore) && !sel,layer,false,within,max);
+
+ qsort(ptspace,ptcnt,sizeof(SplinePoint *),ycmp);
+ changed = _SplineCharRoundToCluster(sc,ptspace,cspace,ptcnt,true,
+ (layer==-2 || layer==ly_fore) && !sel,layer,changed,within,max);
+
+ free(ptspace);
+ free(cspace);
+
+ if ( changed ) {
+ if ( layer==-2 ) {
+ for ( l=ly_fore; l<sc->layer_cnt; ++l ) {
+ for ( spl = sc->layers[l].splines; spl!=NULL; spl=spl->next ) {
+ first = NULL;
+ for ( s=spl->first->next; s!=NULL && s!=first; s=s->to->next ) {
+ SplineRefigure(s);
+ if ( first==NULL ) first = s;
+ }
+ }
+ }
+ } else {
+ if ( layer==-1 )
+ spl = sc->parent->grid.splines;
+ else
+ spl = sc->layers[layer].splines;
+ for ( ; spl!=NULL; spl=spl->next ) {
+ first = NULL;
+ for ( s=spl->first->next; s!=NULL && s!=first; s=s->to->next ) {
+ SplineRefigure(s);
+ if ( first==NULL ) first = s;
+ }
+ }
+ }
+ SCCharChangedUpdate(sc);
+ }
+return( changed );
+}
+
+static int SplineRemoveAnnoyingExtrema1(Spline *s,int which,double err_sq) {
+ /* Remove extrema which are very close to one of the spline end-points */
+ /* and which are in the oposite direction (along the normal of the */
+ /* close end-point's cp) from the other end-point */
+ extended ts[2], t1, t2;
+ bigreal df, dt;
+ bigreal dp, d_o;
+ int i;
+ BasePoint pos, norm;
+ SplinePoint *close, *other;
+ BasePoint *ccp;
+ bigreal c_, b_, nextcp, prevcp, prop;
+ int changed = false;
+
+ SplineFindExtrema(&s->splines[which],&ts[0],&ts[1]);
+
+ for ( i=0; i<2; ++i ) if ( ts[i]!=-1 && ts[i]!=0 && ts[i]!=1 ) {
+ pos.x = ((s->splines[0].a*ts[i]+s->splines[0].b)*ts[i]+s->splines[0].c)*ts[i]+s->splines[0].d;
+ pos.y = ((s->splines[1].a*ts[i]+s->splines[1].b)*ts[i]+s->splines[1].c)*ts[i]+s->splines[1].d;
+ df = (pos.x-s->from->me.x)*(pos.x-s->from->me.x) + (pos.y-s->from->me.y)*(pos.y-s->from->me.y);
+ dt = (pos.x-s->to->me.x)*(pos.x-s->to->me.x) + (pos.y-s->to->me.y)*(pos.y-s->to->me.y);
+ if ( df<dt && df<err_sq ) {
+ close = s->from;
+ ccp = &s->from->nextcp;
+ other = s->to;
+ } else if ( dt<df && dt<err_sq ) {
+ close = s->to;
+ ccp = &s->to->prevcp;
+ other = s->from;
+ } else
+ continue;
+ if ( ccp->x==close->me.x && ccp->y==close->me.y )
+ continue;
+
+ norm.x = (ccp->y-close->me.y);
+ norm.y = -(ccp->x-close->me.x);
+ dp = (pos.x-close->me.x)*norm.x + (pos.y-close->me.y)*norm.y;
+ d_o = (other->me.x-close->me.x)*norm.x + (other->me.y-close->me.y)*norm.y;
+ if ( dp!=0 && dp*d_o>=0 )
+ continue;
+
+ _SplineFindExtrema(&s->splines[which],&t1,&t2);
+ if ( t1==ts[i] ) {
+ if ( close==s->from ) t1=0;
+ else t1 = 1;
+ } else if ( t2==ts[i] ) {
+ if ( close==s->from ) t2=0;
+ else t2 = 1;
+ } else
+ continue;
+
+ if ( t2==-1 ) /* quadratic */
+ continue; /* Can't happen in a quadratic */
+
+ /* The roots of the "slope" quadratic were t1, t2. We have shifted one*/
+ /* root so that that extremum is exactly on an end point */
+ /* Figure out the new slope quadratic, from that what the cubic must */
+ /* be, and from that what the control points must be */
+ /* Quad = 3at^2 + 2bt + c */
+ /* New quad = 3a * (t^2 -(t1+t2)t + t1*t2) */
+ /* a' = a, b' = -(t1+t2)/6a, c' = t1*t2/3a, d' = d */
+ /* nextcp = from + c'/3, prevcp = nextcp + (b' + c')/3 */
+ /* Then for each cp figure what percentage of the original cp vector */
+ /* (or at least this one dimension of that vector) this represents */
+ /* and scale both dimens by this amount */
+ b_ = -(t1+t2)*3*s->splines[which].a/2;
+ c_ = (t1*t2)*3*s->splines[which].a;
+ nextcp = (&s->from->me.x)[which] + c_/3;
+ prevcp = nextcp + (b_ + c_)/3;
+
+ if ( (&s->from->nextcp.x)[which] != (&s->from->me.x)[which] ) {
+ prop = (c_/3) / ( (&s->from->nextcp.x)[which] - (&s->from->me.x)[which] );
+ if ( prop<0 && (c_/3 < .1 && c_/3 > -.1))
+ (&s->to->prevcp.x)[which] = nextcp;
+ else if ( prop>=0 && prop<=10 ) {
+ s->from->nextcp.x = s->from->me.x + prop*(s->from->nextcp.x-s->from->me.x);
+ s->from->nextcp.y = s->from->me.y + prop*(s->from->nextcp.y-s->from->me.y);
+ s->from->nonextcp = (prop == 0);
+ }
+ }
+
+ if ( (&s->to->prevcp.x)[which] != (&s->to->me.x)[which] ) {
+ prop = ( prevcp - (&s->to->me.x)[which]) /
+ ( (&s->to->prevcp.x)[which] - (&s->to->me.x)[which] );
+ if ( prop<0 && (prevcp - (&s->to->me.x)[which] < .1 && prevcp - (&s->to->me.x)[which] > -.1))
+ (&s->to->prevcp.x)[which] = prevcp;
+ else if ( prop>=0 && prop<=10 ) {
+ s->to->prevcp.x = s->to->me.x + prop*(s->to->prevcp.x-s->to->me.x);
+ s->to->prevcp.y = s->to->me.y + prop*(s->to->prevcp.y-s->to->me.y);
+ s->to->noprevcp = (prop == 0);
+ }
+ }
+ SplineRefigure(s);
+ changed = true;
+ }
+return( changed );
+}
+
+static int SplineRemoveAnnoyingExtrema(Spline *s,double err_sq) {
+ int changed;
+
+ changed = SplineRemoveAnnoyingExtrema1(s,0,err_sq);
+ if ( SplineRemoveAnnoyingExtrema1(s,1,err_sq) )
+ changed = true;
+return( changed );
+}
+
+int SplineSetsRemoveAnnoyingExtrema(SplineSet *ss,double err) {
+ int changed = false;
+ double err_sq = err*err;
+ Spline *s, *first;
+
+
+ while ( ss!=NULL ) {
+ first = NULL;
+ for ( s = ss->first->next; s!=NULL && s!=first; s = s->to->next ) {
+ if ( first == NULL ) first = s;
+ if ( SplineRemoveAnnoyingExtrema(s,err_sq))
+ changed = true;
+ }
+ ss = ss->next;
+ }
+return( changed );
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/splineutil2.c b/Build/source/libs/luafontforge/fontforge/fontforge/splineutil2.c
new file mode 100644
index 00000000000..036446f02a7
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/splineutil2.c
@@ -0,0 +1,4069 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include <math.h>
+#include "ustring.h"
+#include "chardata.h"
+#include <unistd.h>
+#include <time.h>
+#include <stdlib.h>
+#include "views.h" /* For SCCharChangedUpdate */
+
+/*#define DEBUG 1*/
+
+int RealNear(real a,real b) {
+ real d;
+
+#if 0 /* def FONTFORGE_CONFIG_USE_DOUBLE*/
+ if ( a==0 )
+return( b>-1e-8 && b<1e-8 );
+ if ( b==0 )
+return( a>-1e-8 && a<1e-8 );
+
+ d = a/(1024*1024.);
+ if ( d<0 ) d = -d;
+return( b>a-d && b<a+d );
+#else /* For floats */
+ if ( a==0 )
+return( b>-1e-5 && b<1e-5 );
+ if ( b==0 )
+return( a>-1e-5 && a<1e-5 );
+
+ d = a/(1024*64.);
+ if ( d<0 ) d = -d;
+return( b>a-d && b<a+d );
+#endif
+}
+
+int RealNearish(real a,real b) {
+
+ if ( a-b<.001 && a-b>-.001 )
+return( true );
+return( false );
+}
+
+int RealApprox(real a,real b) {
+
+ if ( a==0 ) {
+ if ( b<.0001 && b>-.0001 )
+return( true );
+ } else if ( b==0 ) {
+ if ( a<.0001 && a>-.0001 )
+return( true );
+ } else {
+ a /= b;
+ if ( a>=.95 && a<=1.05 )
+return( true );
+ }
+return( false );
+}
+
+int RealWithin(real a,real b,real fudge) {
+
+return( b>=a-fudge && b<=a+fudge );
+}
+
+int RealRatio(real a,real b,real fudge) {
+
+ if ( b==0 )
+return( RealWithin(a,b,fudge));
+
+return( RealWithin(a/b,1.0,fudge));
+}
+
+static int MinMaxWithin(Spline *spline) {
+ extended dx, dy;
+ int which;
+ extended t1, t2;
+ extended w;
+ /* We know that this "spline" is basically one dimensional. As long as its*/
+ /* extrema are between the start and end points on that line then we can */
+ /* treat it as a line. If the extrema are way outside the line segment */
+ /* then it's a line that backtracks on itself */
+
+ if ( (dx = spline->to->me.x - spline->from->me.x)<0 ) dx = -dx;
+ if ( (dy = spline->to->me.y - spline->from->me.y)<0 ) dy = -dy;
+ which = dx<dy;
+ SplineFindExtrema(&spline->splines[which],&t1,&t2);
+ if ( t1==-1 )
+return( true );
+ w = ((spline->splines[which].a*t1 + spline->splines[which].b)*t1
+ + spline->splines[which].c)*t1 + spline->splines[which].d;
+ if ( RealNear(w, (&spline->to->me.x)[which]) || RealNear(w, (&spline->from->me.x)[which]) )
+ /* Close enough */;
+ else if ( (w<(&spline->to->me.x)[which] && w<(&spline->from->me.x)[which]) ||
+ (w>(&spline->to->me.x)[which] && w>(&spline->from->me.x)[which]) )
+return( false ); /* Outside */
+
+ w = ((spline->splines[which].a*t2 + spline->splines[which].b)*t2
+ + spline->splines[which].c)*t2 + spline->splines[which].d;
+ if ( RealNear(w, (&spline->to->me.x)[which]) || RealNear(w, (&spline->from->me.x)[which]) )
+ /* Close enough */;
+ else if ( (w<(&spline->to->me.x)[which] && w<(&spline->from->me.x)[which]) ||
+ (w>(&spline->to->me.x)[which] && w>(&spline->from->me.x)[which]) )
+return( false ); /* Outside */
+
+return( true );
+}
+
+int SplineIsLinear(Spline *spline) {
+ double t1,t2, t3,t4;
+ int ret;
+
+ if ( spline->knownlinear )
+return( true );
+ if ( spline->knowncurved )
+return( false );
+
+ if ( spline->splines[0].a==0 && spline->splines[0].b==0 &&
+ spline->splines[1].a==0 && spline->splines[1].b==0 )
+return( true );
+
+ /* Something is linear if the control points lie on the line between the */
+ /* two base points */
+
+ /* Vertical lines */
+ if ( RealNear(spline->from->me.x,spline->to->me.x) ) {
+ ret = RealNear(spline->from->me.x,spline->from->nextcp.x) &&
+ RealNear(spline->from->me.x,spline->to->prevcp.x);
+ if ( ! ((spline->from->nextcp.y >= spline->from->me.y &&
+ spline->from->nextcp.y <= spline->to->me.y &&
+ spline->to->prevcp.y >= spline->from->me.y &&
+ spline->to->prevcp.y <= spline->to->me.y ) ||
+ (spline->from->nextcp.y <= spline->from->me.y &&
+ spline->from->nextcp.y >= spline->to->me.y &&
+ spline->to->prevcp.y <= spline->from->me.y &&
+ spline->to->prevcp.y >= spline->to->me.y )) )
+ ret = MinMaxWithin(spline);
+ /* Horizontal lines */
+ } else if ( RealNear(spline->from->me.y,spline->to->me.y) ) {
+ ret = RealNear(spline->from->me.y,spline->from->nextcp.y) &&
+ RealNear(spline->from->me.y,spline->to->prevcp.y);
+ if ( ! ((spline->from->nextcp.x >= spline->from->me.x &&
+ spline->from->nextcp.x <= spline->to->me.x &&
+ spline->to->prevcp.x >= spline->from->me.x &&
+ spline->to->prevcp.x <= spline->to->me.x) ||
+ (spline->from->nextcp.x <= spline->from->me.x &&
+ spline->from->nextcp.x >= spline->to->me.x &&
+ spline->to->prevcp.x <= spline->from->me.x &&
+ spline->to->prevcp.x >= spline->to->me.x)) )
+ ret = MinMaxWithin(spline);
+ } else {
+ ret = true;
+ t1 = (spline->from->nextcp.y-spline->from->me.y)/(spline->to->me.y-spline->from->me.y);
+ t2 = (spline->from->nextcp.x-spline->from->me.x)/(spline->to->me.x-spline->from->me.x);
+ t3 = (spline->to->me.y-spline->to->prevcp.y)/(spline->to->me.y-spline->from->me.y);
+ t4 = (spline->to->me.x-spline->to->prevcp.x)/(spline->to->me.x-spline->from->me.x);
+ ret = (RealApprox(t1,t2) || (RealApprox(t1,0) && RealApprox(t2,0))) &&
+ (RealApprox(t3,t4) || (RealApprox(t3,0) && RealApprox(t4,0)));
+ if ( ret ) {
+ if ( t1<0 || t2<0 || t3<0 || t4<0 ||
+ t1>1 || t2>1 || t3>1 || t4>1 )
+ ret = MinMaxWithin(spline);
+ }
+ }
+ spline->knowncurved = !ret;
+ spline->knownlinear = ret;
+ if ( ret ) {
+ /* A few places that if the spline is knownlinear then its splines[?] */
+ /* are linear. So give the linear version and not that suggested by */
+ /* the control points */
+ spline->splines[0].a = spline->splines[0].b = 0;
+ spline->splines[0].d = spline->from->me.x;
+ spline->splines[0].c = spline->to->me.x-spline->from->me.x;
+ spline->splines[1].a = spline->splines[1].b = 0;
+ spline->splines[1].d = spline->from->me.y;
+ spline->splines[1].c = spline->to->me.y-spline->from->me.y;
+ }
+return( ret );
+}
+
+int SplineIsLinearMake(Spline *spline) {
+
+ if ( spline->islinear )
+return( true );
+ if ( SplineIsLinear(spline)) {
+ spline->islinear = spline->from->nonextcp = spline->to->noprevcp = true;
+ spline->from->nextcp = spline->from->me;
+ if ( spline->from->nonextcp && spline->from->noprevcp )
+ spline->from->pointtype = pt_corner;
+ else if ( spline->from->pointtype == pt_curve )
+ spline->from->pointtype = pt_tangent;
+ spline->to->prevcp = spline->to->me;
+ if ( spline->to->nonextcp && spline->to->noprevcp )
+ spline->to->pointtype = pt_corner;
+ else if ( spline->to->pointtype == pt_curve )
+ spline->to->pointtype = pt_tangent;
+ SplineRefigure(spline);
+ }
+return( spline->islinear );
+}
+
+typedef struct spline1 {
+ Spline1D sp;
+ real s0, s1;
+ real c0, c1;
+} Spline1;
+
+static void FigureSpline1(Spline1 *sp1,bigreal t0, bigreal t1, Spline1D *sp ) {
+ bigreal s = (t1-t0);
+ if ( sp->a==0 && sp->b==0 ) {
+ sp1->sp.d = sp->d + t0*sp->c;
+ sp1->sp.c = s*sp->c;
+ sp1->sp.b = sp1->sp.a = 0;
+ } else {
+ sp1->sp.d = sp->d + t0*(sp->c + t0*(sp->b + t0*sp->a));
+ sp1->sp.c = s*(sp->c + t0*(2*sp->b + 3*sp->a*t0));
+ sp1->sp.b = s*s*(sp->b+3*sp->a*t0);
+ sp1->sp.a = s*s*s*sp->a;
+#if 0 /* Got invoked once on a perfectly good spline */
+ sp1->s1 = sp1->sp.a+sp1->sp.b+sp1->sp.c+sp1->sp.d;
+ if ( ((sp1->s1>.001 || sp1->s1<-.001) && !RealNear((double) sp1->sp.a+sp1->sp.b+sp1->sp.c+sp1->sp.d,sp1->s1)) ||
+ !RealNear(sp1->sp.d,sp1->s0))
+ IError( "Created spline does not work in FigureSpline1");
+#endif
+ }
+ sp1->c0 = sp1->sp.c/3 + sp1->sp.d;
+ sp1->c1 = sp1->c0 + (sp1->sp.b+sp1->sp.c)/3;
+}
+
+SplinePoint *SplineBisect(Spline *spline, extended t) {
+ Spline1 xstart, xend;
+ Spline1 ystart, yend;
+ Spline *spline1, *spline2;
+ SplinePoint *mid;
+ SplinePoint *old0, *old1;
+ Spline1D *xsp = &spline->splines[0], *ysp = &spline->splines[1];
+ int order2 = spline->order2;
+
+#ifdef DEBUG
+ if ( t<=1e-3 || t>=1-1e-3 )
+ IError("Bisection to create a zero length spline");
+#endif
+ xstart.s0 = xsp->d; ystart.s0 = ysp->d;
+ xend.s1 = (extended) xsp->a+xsp->b+xsp->c+xsp->d;
+ yend.s1 = (extended) ysp->a+ysp->b+ysp->c+ysp->d;
+ xstart.s1 = xend.s0 = ((xsp->a*t+xsp->b)*t+xsp->c)*t + xsp->d;
+ ystart.s1 = yend.s0 = ((ysp->a*t+ysp->b)*t+ysp->c)*t + ysp->d;
+ FigureSpline1(&xstart,0,t,xsp);
+ FigureSpline1(&xend,t,1,xsp);
+ FigureSpline1(&ystart,0,t,ysp);
+ FigureSpline1(&yend,t,1,ysp);
+
+ mid = chunkalloc(sizeof(SplinePoint));
+ mid->me.x = xstart.s1; mid->me.y = ystart.s1;
+ if ( order2 ) {
+ mid->nextcp.x = xend.sp.d + xend.sp.c/2;
+ mid->nextcp.y = yend.sp.d + yend.sp.c/2;
+ mid->prevcp.x = xstart.sp.d + xstart.sp.c/2;
+ mid->prevcp.y = ystart.sp.d + ystart.sp.c/2;
+ } else {
+ mid->nextcp.x = xend.c0; mid->nextcp.y = yend.c0;
+ mid->prevcp.x = xstart.c1; mid->prevcp.y = ystart.c1;
+ }
+ if ( mid->me.x==mid->nextcp.x && mid->me.y==mid->nextcp.y )
+ mid->nonextcp = true;
+ if ( mid->me.x==mid->prevcp.x && mid->me.y==mid->prevcp.y )
+ mid->noprevcp = true;
+
+ old0 = spline->from; old1 = spline->to;
+ if ( order2 ) {
+ old0->nextcp = mid->prevcp;
+ old1->prevcp = mid->nextcp;
+ } else {
+ old0->nextcp.x = xstart.c0; old0->nextcp.y = ystart.c0;
+ old1->prevcp.x = xend.c1; old1->prevcp.y = yend.c1;
+ }
+ old0->nonextcp = (old0->nextcp.x==old0->me.x && old0->nextcp.y==old0->me.y);
+ old1->noprevcp = (old1->prevcp.x==old1->me.x && old1->prevcp.y==old1->me.y);
+ old0->nextcpdef = false;
+ old1->prevcpdef = false;
+ SplineFree(spline);
+
+ spline1 = chunkalloc(sizeof(Spline));
+ spline1->splines[0] = xstart.sp; spline1->splines[1] = ystart.sp;
+ spline1->from = old0;
+ spline1->to = mid;
+ spline1->order2 = order2;
+ old0->next = spline1;
+ mid->prev = spline1;
+ if ( SplineIsLinear(spline1)) {
+ spline1->islinear = spline1->from->nonextcp = spline1->to->noprevcp = true;
+ spline1->from->nextcp = spline1->from->me;
+ spline1->to->prevcp = spline1->to->me;
+ }
+ SplineRefigure(spline1);
+
+ spline2 = chunkalloc(sizeof(Spline));
+ spline2->splines[0] = xend.sp; spline2->splines[1] = xend.sp;
+ spline2->from = mid;
+ spline2->to = old1;
+ spline2->order2 = order2;
+ mid->next = spline2;
+ old1->prev = spline2;
+ if ( SplineIsLinear(spline2)) {
+ spline2->islinear = spline2->from->nonextcp = spline2->to->noprevcp = true;
+ spline2->from->nextcp = spline2->from->me;
+ spline2->to->prevcp = spline2->to->me;
+ }
+ SplineRefigure(spline2);
+return( mid );
+}
+
+Spline *SplineSplit(Spline *spline, extended ts[3]) {
+ /* Split the current spline in up to 3 places */
+ Spline1 splines[2][4];
+ int i,cnt;
+ bigreal base;
+ SplinePoint *last, *sp;
+ Spline *new;
+ int order2 = spline->order2;
+
+ memset(splines,0,sizeof(splines));
+ base=0;
+ for ( i=cnt=0; i<3 && ts[i]!=-1; ++i ) {
+ if ( base>1-1e-3 ) /* Avoid tiny splines */
+ break;
+ else if ( base<ts[i]-1e-3 ) {
+ FigureSpline1(&splines[0][cnt],base,ts[i],&spline->splines[0]);
+ FigureSpline1(&splines[1][cnt++],base,ts[i],&spline->splines[1]);
+ base = ts[i];
+ }
+ }
+ if ( base==0 )
+return( spline );
+
+ FigureSpline1(&splines[0][cnt],base,1.0,&spline->splines[0]);
+ FigureSpline1(&splines[1][cnt],base,1.0,&spline->splines[1]);
+
+ last = spline->from;
+ for ( i=0; i<=cnt; ++i ) {
+ if ( order2 ) {
+ last->nextcp.x = splines[0][i].sp.d+splines[0][i].sp.c/2;
+ last->nextcp.y = splines[1][i].sp.d+splines[1][i].sp.c/2;
+ } else {
+ last->nextcp.x = splines[0][i].c0;
+ last->nextcp.y = splines[1][i].c0;
+ }
+ if ( i==cnt )
+ sp = spline->to;
+ else {
+ sp = chunkalloc(sizeof(SplinePoint));
+ sp->me.x = splines[0][i+1].sp.d;
+ sp->me.y = splines[1][i+1].sp.d;
+ }
+ if ( order2 ) {
+ sp->prevcp = last->nextcp;
+ SplineMake2(last,sp);
+ } else {
+ sp->prevcp.x = splines[0][i].c1;
+ sp->prevcp.y = splines[1][i].c1;
+ SplineMake3(last,sp);
+ }
+ last = sp;
+ }
+
+ new = spline->from->next;
+ SplineFree(spline);
+return( new );
+}
+
+static Spline *IsLinearApprox(SplinePoint *from, SplinePoint *to,
+ TPoint *mid, int cnt, int order2) {
+ double vx, vy, slope;
+ int i;
+
+ vx = to->me.x-from->me.x; vy = to->me.y-from->me.y;
+ if ( vx==0 && vy==0 ) {
+ for ( i=0; i<cnt; ++i )
+ if ( mid[i].x != from->me.x || mid[i].y != from->me.y )
+return( NULL );
+ } else if ( fabs(vx)>fabs(vy) ) {
+ slope = vy/vx;
+ for ( i=0; i<cnt; ++i )
+ if ( !RealWithin(mid[i].y,from->me.y+slope*(mid[i].x-from->me.x),.7) )
+return( NULL );
+ } else {
+ slope = vx/vy;
+ for ( i=0; i<cnt; ++i )
+ if ( !RealWithin(mid[i].x,from->me.x+slope*(mid[i].y-from->me.y),.7) )
+return( NULL );
+ }
+ from->nonextcp = to->noprevcp = true;
+return( SplineMake(from,to,order2) );
+}
+
+#if 0
+static void CleanupDir(BasePoint *newcp,BasePoint *oldcp,BasePoint *base) {
+ double orig, new;
+ orig = atan2(oldcp->y-base->y,oldcp->x-base->x);
+ new = atan2(newcp->y-base->y,newcp->x-base->x);
+ if ( !RealNearish(orig,new)) {
+ double c = cos(orig), s = sin(orig);
+ /*double len = sqrt((newcp->x-base->x)*(newcp->x-base->x) + (newcp->y-base->y)*(newcp->y-base->y));*/
+ /* use dot product rather than length */
+ double len;
+ if ( c<1e-6 && c>-1e-6 ) { c=0; if ( s<0 ) s=-1; else s=1; }
+ if ( s<1e-6 && s>-1e-6 ) { s=0; if ( c<0 ) c=-1; else c=1; }
+ len = (newcp->x-base->x)*c + (newcp->y-base->y)*s;
+ newcp->x = len*c; newcp->y = len*s;
+ if ( newcp->x*(oldcp->x-base->x) + newcp->y*(oldcp->y-base->y)<0 ) {
+ IError( "Control points in wrong direction" );
+ newcp->x = -newcp->x; newcp->y = -newcp->y;
+ }
+ newcp->x += base->x; newcp->y += base->y;
+ }
+}
+#endif
+
+/* Least squares tells us that:
+ | S(xi*ti^3) | | S(ti^6) S(ti^5) S(ti^4) S(ti^3) | | a |
+ | S(xi*ti^2) | = | S(ti^5) S(ti^4) S(ti^3) S(ti^2) | * | b |
+ | S(xi*ti) | | S(ti^4) S(ti^3) S(ti^2) S(ti) | | c |
+ | S(xi) | | S(ti^3) S(ti^2) S(ti) n | | d |
+ and the definition of a spline tells us:
+ | x1 | = | 1 1 1 1 | * (a b c d)
+ | x0 | = | 0 0 0 1 | * (a b c d)
+So we're a bit over specified. Let's use the last two lines of least squares
+and the 2 from the spline defn. So d==x0. Now we've got three unknowns
+and only three equations...
+
+For order2 splines we've got
+ | S(xi*ti^2) | | S(ti^4) S(ti^3) S(ti^2) | | b |
+ | S(xi*ti) | = | S(ti^3) S(ti^2) S(ti) | * | c |
+ | S(xi) | | S(ti^2) S(ti) n | | d |
+ and the definition of a spline tells us:
+ | x1 | = | 1 1 1 | * (b c d)
+ | x0 | = | 0 0 1 | * (b c d)
+=>
+ d = x0
+ b+c = x1-x0
+ S(ti^2)*b + S(ti)*c = S(xi)-n*x0
+ S(ti^2)*b + S(ti)*(x1-x0-b) = S(xi)-n*x0
+ [ S(ti^2)-S(ti) ]*b = S(xi)-S(ti)*(x1-x0) - n*x0
+*/
+static int _ApproximateSplineFromPoints(SplinePoint *from, SplinePoint *to,
+ TPoint *mid, int cnt, BasePoint *nextcp, BasePoint *prevcp,
+ int order2) {
+ double tt, ttn;
+ int i, j, ret;
+ double vx[3], vy[3], m[3][3];
+ double ts[7], xts[4], yts[4];
+ BasePoint nres, pres;
+ int nrescnt=0, prescnt=0;
+ double nmin, nmax, pmin, pmax, test, ptest;
+ double bx, by, cx, cy;
+
+ memset(&nres,0,sizeof(nres)); memset(&pres,0,sizeof(pres));
+
+ /* Add the initial and end points */
+ ts[0] = 2; for ( i=1; i<7; ++i ) ts[i] = 1;
+ xts[0] = from->me.x+to->me.x; yts[0] = from->me.y+to->me.y;
+ xts[3] = xts[2] = xts[1] = to->me.x; yts[3] = yts[2] = yts[1] = to->me.y;
+ nmin = pmin = 0; nmax = pmax = (to->me.x-from->me.x)*(to->me.x-from->me.x)+(to->me.y-from->me.y)*(to->me.y-from->me.y);
+ for ( i=0; i<cnt; ++i ) {
+ xts[0] += mid[i].x;
+ yts[0] += mid[i].y;
+ ++ts[0];
+ tt = mid[i].t;
+ xts[1] += tt*mid[i].x;
+ yts[1] += tt*mid[i].y;
+ ts[1] += tt;
+ ts[2] += (ttn=tt*tt);
+ xts[2] += ttn*mid[i].x;
+ yts[2] += ttn*mid[i].y;
+ ts[3] += (ttn*=tt);
+ xts[3] += ttn*mid[i].x;
+ yts[3] += ttn*mid[i].y;
+ ts[4] += (ttn*=tt);
+ ts[5] += (ttn*=tt);
+ ts[6] += (ttn*=tt);
+
+ test = (mid[i].x-from->me.x)*(to->me.x-from->me.x) + (mid[i].y-from->me.y)*(to->me.y-from->me.y);
+ if ( test<nmin ) nmin=test;
+ if ( test>nmax ) nmax=test;
+ test = (mid[i].x-to->me.x)*(from->me.x-to->me.x) + (mid[i].y-to->me.y)*(from->me.y-to->me.y);
+ if ( test<pmin ) pmin=test;
+ if ( test>pmax ) pmax=test;
+ }
+ pmin *= 1.2; pmax *= 1.2; nmin *= 1.2; nmax *= 1.2;
+
+ for ( j=0; j<3; ++j ) {
+ if ( order2 ) {
+ if ( RealNear(ts[j+2],ts[j+1]) )
+ continue;
+ /* This produces really bad results!!!! But I don't see what I can do to improve it */
+ bx = (xts[j]-ts[j+1]*(to->me.x-from->me.x) - ts[j]*from->me.x) / (ts[j+2]-ts[j+1]);
+ by = (yts[j]-ts[j+1]*(to->me.y-from->me.y) - ts[j]*from->me.y) / (ts[j+2]-ts[j+1]);
+ cx = to->me.x-from->me.x-bx;
+ cy = to->me.y-from->me.y-by;
+
+ nextcp->x = from->me.x + cx/2;
+ nextcp->y = from->me.y + cy/2;
+ *prevcp = *nextcp;
+ } else {
+ vx[0] = xts[j+1]-ts[j+1]*from->me.x;
+ vx[1] = xts[j]-ts[j]*from->me.x;
+ vx[2] = to->me.x-from->me.x; /* always use the defn of spline */
+
+ vy[0] = yts[j+1]-ts[j+1]*from->me.y;
+ vy[1] = yts[j]-ts[j]*from->me.y;
+ vy[2] = to->me.y-from->me.y;
+
+ m[0][0] = ts[j+4]; m[0][1] = ts[j+3]; m[0][2] = ts[j+2];
+ m[1][0] = ts[j+3]; m[1][1] = ts[j+2]; m[1][2] = ts[j+1];
+ m[2][0] = 1; m[2][1] = 1; m[2][2] = 1;
+
+ /* Remove a terms from rows 0 and 1 */
+ vx[0] -= ts[j+4]*vx[2];
+ vy[0] -= ts[j+4]*vy[2];
+ m[0][0] = 0; m[0][1] -= ts[j+4]; m[0][2] -= ts[j+4];
+ vx[1] -= ts[j+3]*vx[2];
+ vy[1] -= ts[j+3]*vy[2];
+ m[1][0] = 0; m[1][1] -= ts[j+3]; m[1][2] -= ts[j+3];
+
+ if ( fabs(m[1][1])<fabs(m[0][1]) ) {
+ double temp;
+ temp = vx[1]; vx[1] = vx[0]; vx[0] = temp;
+ temp = vy[1]; vy[1] = vy[0]; vy[0] = temp;
+ temp = m[1][1]; m[1][1] = m[0][1]; m[0][1] = temp;
+ temp = m[1][2]; m[1][2] = m[0][2]; m[0][2] = temp;
+ }
+ /* remove b terms from rows 0 and 2 (first normalize row 1 so m[1][1] is 1*/
+ vx[1] /= m[1][1];
+ vy[1] /= m[1][1];
+ m[1][2] /= m[1][1];
+ m[1][1] = 1;
+ vx[0] -= m[0][1]*vx[1];
+ vy[0] -= m[0][1]*vy[1];
+ m[0][2] -= m[0][1]*m[1][2]; m[0][1] = 0;
+ vx[2] -= m[2][1]*vx[1];
+ vy[2] -= m[2][1]*vy[1];
+ m[2][2] -= m[2][1]*m[1][2]; m[2][1] = 0;
+
+ vx[0] /= m[0][2]; /* This is cx */
+ vy[0] /= m[0][2]; /* This is cy */
+ /*m[0][2] = 1;*/
+
+ vx[1] -= m[1][2]*vx[0]; /* This is bx */
+ vy[1] -= m[1][2]*vy[0]; /* This is by */
+ /* m[1][2] = 0; */
+ vx[2] -= m[2][2]*vx[0]; /* This is ax */
+ vy[2] -= m[2][2]*vy[0]; /* This is ay */
+ /* m[2][2] = 0; */
+
+ nextcp->x = from->me.x + vx[0]/3;
+ nextcp->y = from->me.y + vy[0]/3;
+ prevcp->x = nextcp->x + (vx[0]+vx[1])/3;
+ prevcp->y = nextcp->y + (vy[0]+vy[1])/3;
+ }
+
+ test = (nextcp->x-from->me.x)*(to->me.x-from->me.x) +
+ (nextcp->y-from->me.y)*(to->me.y-from->me.y);
+ ptest = (prevcp->x-to->me.x)*(from->me.x-to->me.x) +
+ (prevcp->y-to->me.y)*(from->me.y-to->me.y);
+ if ( order2 &&
+ (test<nmin || test>nmax || ptest<pmin || ptest>pmax))
+ continue;
+ if ( test>=nmin && test<=nmax ) {
+ nres.x += nextcp->x; nres.y += nextcp->y;
+ ++nrescnt;
+ }
+ if ( test>=pmin && test<=pmax ) {
+ pres.x += prevcp->x; pres.y += prevcp->y;
+ ++prescnt;
+ }
+ if ( nrescnt==1 && prescnt==1 )
+ break;
+ }
+
+ ret = 0;
+ if ( nrescnt>0 ) {
+ ret |= 1;
+ nextcp->x = nres.x/nrescnt;
+ nextcp->y = nres.y/nrescnt;
+ } else
+ *nextcp = from->nextcp;
+ if ( prescnt>0 ) {
+ ret |= 2;
+ prevcp->x = pres.x/prescnt;
+ prevcp->y = pres.y/prescnt;
+ } else
+ *prevcp = to->prevcp;
+ if ( order2 && ret!=3 ) {
+ nextcp->x = (nextcp->x + prevcp->x)/2;
+ nextcp->y = (nextcp->y + prevcp->y)/2;
+ }
+ if ( order2 )
+ *prevcp = *nextcp;
+return( ret );
+}
+
+static void TestForLinear(SplinePoint *from,SplinePoint *to) {
+ BasePoint off, cpoff, cpoff2;
+ double len, co, co2;
+
+ /* Did we make a line? */
+ off.x = to->me.x-from->me.x; off.y = to->me.y-from->me.y;
+ len = sqrt(off.x*off.x + off.y*off.y);
+ if ( len!=0 ) {
+ off.x /= len; off.y /= len;
+ cpoff.x = from->nextcp.x-from->me.x; cpoff.y = from->nextcp.y-from->me.y;
+ len = sqrt(cpoff.x*cpoff.x + cpoff.y*cpoff.y);
+ if ( len!=0 ) {
+ cpoff.x /= len; cpoff.y /= len;
+ }
+ cpoff2.x = to->prevcp.x-from->me.x; cpoff2.y = to->prevcp.y-from->me.y;
+ len = sqrt(cpoff2.x*cpoff2.x + cpoff2.y*cpoff2.y);
+ if ( len!=0 ) {
+ cpoff2.x /= len; cpoff2.y /= len;
+ }
+ co = cpoff.x*off.y - cpoff.y*off.x; co2 = cpoff2.x*off.y - cpoff2.y*off.x;
+ if ( co<.05 && co>-.05 && co2<.05 && co2>-.05 ) {
+ from->nextcp = from->me; from->nonextcp = true;
+ to->prevcp = to->me; to->noprevcp = true;
+ } else {
+ Spline temp;
+ memset(&temp,0,sizeof(temp));
+ temp.from = from; temp.to = to;
+ SplineRefigure(&temp);
+ if ( SplineIsLinear(&temp)) {
+ from->nextcp = from->me; from->nonextcp = true;
+ to->prevcp = to->me; to->noprevcp = true;
+ }
+ }
+ }
+}
+
+/* Find a spline which best approximates the list of intermediate points we */
+/* are given. No attempt is made to fix the slopes */
+Spline *ApproximateSplineFromPoints(SplinePoint *from, SplinePoint *to,
+ TPoint *mid, int cnt, int order2) {
+ int ret;
+ Spline *spline;
+ BasePoint nextcp, prevcp;
+
+ if ( (spline = IsLinearApprox(from,to,mid,cnt,order2))!=NULL )
+return( spline );
+
+ ret = _ApproximateSplineFromPoints(from,to,mid,cnt,&nextcp,&prevcp,order2);
+
+ if ( ret&1 ) {
+ from->nextcp = nextcp;
+ from->nonextcp = false;
+ } else {
+ from->nextcp = from->me;
+ from->nonextcp = true;
+ }
+ if ( ret&2 ) {
+ to->prevcp = prevcp;
+ to->noprevcp = false;
+ } else {
+ to->prevcp = to->me;
+ to->noprevcp = true;
+ }
+ TestForLinear(from,to);
+ spline = SplineMake(from,to,order2);
+return( spline );
+}
+
+static double ClosestSplineSolve(Spline1D *sp,double sought,double close_to_t) {
+ /* We want to find t so that spline(t) = sought */
+ /* find the value which is closest to close_to_t */
+ /* on error return closetot */
+ Spline1D temp;
+ extended ts[3];
+ int i;
+ double t, best, test;
+
+ temp = *sp;
+ temp.d -= sought;
+ CubicSolve(&temp,ts);
+ best = 9e20; t= close_to_t;
+ for ( i=0; i<3; ++i ) if ( ts[i]!=-1 ) {
+ if ( (test=ts[i]-close_to_t)<0 ) test = -test;
+ if ( test<best ) {
+ best = test;
+ t = ts[i];
+ }
+ }
+
+return( t );
+}
+
+struct dotbounds {
+ BasePoint unit;
+ BasePoint base;
+ double len;
+ double min,max; /* If min<0 || max>len the spline extends beyond its endpoints */
+};
+
+static double SigmaDeltas(Spline *spline,TPoint *mid, int cnt, DBounds *b, struct dotbounds *db) {
+ int i, lasti;
+ double xdiff, ydiff, sum, temp, t, lastt;
+ SplinePoint *to = spline->to, *from = spline->from;
+ extended ts[2], x,y;
+ struct dotbounds db2;
+ double dot;
+
+ if ( (xdiff = to->me.x-from->me.x)<0 ) xdiff = -xdiff;
+ if ( (ydiff = to->me.y-from->me.y)<0 ) ydiff = -ydiff;
+
+ sum = 0; lastt = -1; lasti = -1;
+ for ( i=0; i<cnt; ++i ) {
+ if ( ydiff>2*xdiff ) {
+ t = ClosestSplineSolve(&spline->splines[1],mid[i].y,mid[i].t);
+ } else if ( xdiff>2*ydiff ) {
+ t = ClosestSplineSolve(&spline->splines[0],mid[i].x,mid[i].t);
+ } else {
+ t = (ClosestSplineSolve(&spline->splines[1],mid[i].y,mid[i].t) +
+ ClosestSplineSolve(&spline->splines[0],mid[i].x,mid[i].t))/2;
+ }
+ if ( t==lastt ) /* These last* values appear to be debugging */
+ t = lastt + (mid[i].t - mid[lasti].t);
+ else {
+ lastt = t;
+ lasti = i;
+ }
+ temp = mid[i].x - ( ((spline->splines[0].a*t+spline->splines[0].b)*t+spline->splines[0].c)*t + spline->splines[0].d );
+ sum += temp*temp;
+ temp = mid[i].y - ( ((spline->splines[1].a*t+spline->splines[1].b)*t+spline->splines[1].c)*t + spline->splines[1].d );
+ sum += temp*temp;
+ }
+
+ /* Ok, we've got distances from a set of points on the old spline to the */
+ /* new one. Let's do the reverse: find the extrema of the new and see how*/
+ /* close they get to the bounding box of the old */
+ /* And get really unhappy if the spline extends beyond the end-points */
+ db2.min = 0; db2.max = db->len;
+ SplineFindExtrema(&spline->splines[0],&ts[0],&ts[1]);
+ for ( i=0; i<2; ++i ) {
+ if ( ts[i]!=-1 ) {
+ x = ((spline->splines[0].a*ts[i]+spline->splines[0].b)*ts[i]+spline->splines[0].c)*ts[i] + spline->splines[0].d;
+ y = ((spline->splines[1].a*ts[i]+spline->splines[1].b)*ts[i]+spline->splines[1].c)*ts[i] + spline->splines[1].d;
+ if ( x<b->minx )
+ sum += (x-b->minx)*(x-b->minx);
+ else if ( x>b->maxx )
+ sum += (x-b->maxx)*(x-b->maxx);
+ dot = (x-db->base.x)*db->unit.x + (y-db->base.y)*db->unit.y;
+ if ( dot<db2.min ) db2.min = dot;
+ if ( dot>db2.max ) db2.max = dot;
+ }
+ }
+ SplineFindExtrema(&spline->splines[1],&ts[0],&ts[1]);
+ for ( i=0; i<2; ++i ) {
+ if ( ts[i]!=-1 ) {
+ x = ((spline->splines[0].a*ts[i]+spline->splines[0].b)*ts[i]+spline->splines[0].c)*ts[i] + spline->splines[0].d;
+ y = ((spline->splines[1].a*ts[i]+spline->splines[1].b)*ts[i]+spline->splines[1].c)*ts[i] + spline->splines[1].d;
+ if ( y<b->miny )
+ sum += (y-b->miny)*(y-b->miny);
+ else if ( y>b->maxy )
+ sum += (y-b->maxy)*(y-b->maxy);
+ dot = (x-db->base.x)*db->unit.x + (y-db->base.y)*db->unit.y;
+ if ( dot<db2.min ) db2.min = dot;
+ if ( dot>db2.max ) db2.max = dot;
+ }
+ }
+
+ /* Big penalty for going beyond the range of the desired spline */
+ if ( db->min==0 && db2.min<0 )
+ sum += 10000 + db2.min*db2.min;
+ else if ( db2.min<db->min )
+ sum += 100 + (db2.min-db->min)*(db2.min-db->min);
+ if ( db->max==db->len && db2.max>db->len )
+ sum += 10000 + (db2.max-db->max)*(db2.max-db->max);
+ else if ( db2.max>db->max )
+ sum += 100 + (db2.max-db->max)*(db2.max-db->max);
+
+return( sum );
+}
+
+static void ApproxBounds(DBounds *b,TPoint *mid, int cnt, struct dotbounds *db) {
+ int i;
+ double dot;
+
+ b->minx = b->maxx = mid[0].x;
+ b->miny = b->maxy = mid[0].y;
+ db->min = 0; db->max = db->len;
+ for ( i=1; i<cnt; ++i ) {
+ if ( mid[i].x>b->maxx ) b->maxx = mid[i].x;
+ if ( mid[i].x<b->minx ) b->minx = mid[i].x;
+ if ( mid[i].y>b->maxy ) b->maxy = mid[i].y;
+ if ( mid[i].y<b->miny ) b->miny = mid[i].y;
+ dot = (mid[i].x-db->base.x)*db->unit.x + (mid[i].y-db->base.y)*db->unit.y;
+ if ( dot<db->min ) db->min = dot;
+ if ( dot>db->max ) db->max = dot;
+ }
+}
+
+static int GoodCurve(SplinePoint *sp, int check_prev ) {
+ double dx, dy, lenx, leny;
+
+ if ( sp->pointtype!=pt_curve )
+return( false );
+ if ( check_prev ) {
+ dx = sp->me.x - sp->prevcp.x;
+ dy = sp->me.y - sp->prevcp.y;
+ } else {
+ dx = sp->me.x - sp->nextcp.x;
+ dy = sp->me.y - sp->nextcp.y;
+ }
+ /* If the cp is very close to the base point the point might as well be a corner */
+ if ( dx<0 ) dx = -dx;
+ if ( dy<0 ) dy = -dy;
+ if ( dx+dy<1 )
+return( false );
+
+ if ( check_prev ) {
+ if ( sp->prev==NULL )
+return( true );
+ lenx = sp->me.x - sp->prev->from->me.x;
+ leny = sp->me.y - sp->prev->from->me.y;
+ } else {
+ if ( sp->next==NULL )
+return( true );
+ lenx = sp->me.x - sp->next->to->me.x;
+ leny = sp->me.y - sp->next->to->me.y;
+ }
+ if ( lenx<0 ) lenx = -lenx;
+ if ( leny<0 ) leny = -leny;
+ if ( 50*(dx+dy) < lenx+leny )
+return( false );
+
+return( true );
+}
+
+#if 0
+static int totcnt_cnt, nocnt_cnt, incr_cnt, curdiff_cnt;
+#endif
+
+/* I used to do a least squares aproach adding two more to the above set of equations */
+/* which held the slopes constant. But that didn't work very well. So instead*/
+/* Then I tried doing the approximation, and then forcing the control points */
+/* to be in line (witht the original slopes), getting a better approximation */
+/* to "t" for each data point and then calculating an error array, approximating*/
+/* it, and using that to fix up the final result */
+/* Then I tried checking various possible cp lengths in the desired directions*/
+/* finding the best one or two, and doing a 2D binary search using that as a */
+/* starting point. */
+/* And sometimes a least squares approach will give us the right answer, so */
+/* try that too. */
+/* This still isn't as good as I'd like it... But I haven't been able to */
+/* improve it further yet */
+#define TRY_CNT 2
+#define DECIMATION 5
+Spline *ApproximateSplineFromPointsSlopes(SplinePoint *from, SplinePoint *to,
+ TPoint *mid, int cnt, int order2) {
+ BasePoint tounit, fromunit, ftunit;
+ double flen,tlen,ftlen;
+ Spline *spline, temp;
+ BasePoint nextcp;
+ int bettern, betterp;
+ double offn, offp, incrn, incrp, trylen;
+ int nocnt = 0, totcnt;
+ double curdiff, bestdiff[TRY_CNT];
+ int i,j,besti[TRY_CNT],bestj[TRY_CNT],k,l;
+ double fdiff, tdiff, fmax, tmax, fdotft, tdotft;
+ DBounds b;
+ struct dotbounds db;
+ double offn_, offp_, finaldiff;
+
+ /* If all the selected points are at the same spot, and one of the */
+ /* end-points is also at that spot, then just copy the control point */
+ /* But our caller seems to have done that for us */
+
+ /* If the two end-points are corner points then allow the slope to vary */
+ /* Or if one end-point is a tangent but the point defining the tangent's */
+ /* slope is being removed then allow the slope to vary */
+ /* Except if the slope is horizontal or vertical then keep it fixed */
+ if ( ( !from->nonextcp && ( from->nextcp.x==from->me.x || from->nextcp.y==from->me.y)) ||
+ (!to->noprevcp && ( to->prevcp.x==to->me.x || to->prevcp.y==to->me.y)) )
+ /* Preserve the slope */;
+ else if ( ((from->pointtype == pt_corner && from->nonextcp) ||
+ (from->pointtype == pt_tangent &&
+ ((from->nonextcp && from->noprevcp) || !from->noprevcp))) &&
+ ((to->pointtype == pt_corner && to->noprevcp) ||
+ (to->pointtype == pt_tangent &&
+ ((to->nonextcp && to->noprevcp) || !to->nonextcp))) ) {
+ from->pointtype = to->pointtype = pt_corner;
+return( ApproximateSplineFromPoints(from,to,mid,cnt,order2) );
+ }
+
+ /* If we are going to honour the slopes of a quadratic spline, there is */
+ /* only one possibility */
+ if ( order2 ) {
+ if ( from->nonextcp || to->noprevcp )
+return( ApproximateSplineFromPoints(from,to,mid,cnt,order2) );
+ else if ( !IntersectLines(&nextcp,&from->nextcp,&from->me,&to->prevcp,&to->me) ) {
+ /* If the slopes don't intersect then use a line */
+ /* (or if the intersection is patently absurd) */
+ from->nonextcp = to->noprevcp = true;
+ from->nextcp = from->me;
+ to->prevcp = to->me;
+ TestForLinear(from,to);
+ } else {
+ from->nextcp = to->prevcp = nextcp;
+ from->nonextcp = to->noprevcp = false;
+ }
+return( SplineMake2(from,to));
+ }
+ /* From here down we are only working with cubic splines */
+
+ if ( !to->noprevcp || to->pointtype == pt_corner ) {
+ tounit.x = to->prevcp.x-to->me.x; tounit.y = to->prevcp.y-to->me.y;
+ } else {
+ tounit.x = to->me.x-to->nextcp.x; tounit.y = to->me.y-to->nextcp.y;
+ }
+ tlen = sqrt(tounit.x*tounit.x + tounit.y*tounit.y);
+ if ( !from->nonextcp || from->pointtype == pt_corner ) {
+ fromunit.x = from->nextcp.x-from->me.x; fromunit.y = from->nextcp.y-from->me.y;
+ } else {
+ fromunit.x = from->me.x-from->prevcp.x; fromunit.y = from->me.y-from->prevcp.y;
+ }
+ flen = sqrt(fromunit.x*fromunit.x + fromunit.y*fromunit.y);
+ if ( tlen==0 || flen==0 ) {
+ if ( from->next!=NULL )
+ temp = *from->next;
+ else {
+ memset(&temp,0,sizeof(temp));
+ temp.from = from; temp.to = to;
+ SplineRefigure(&temp);
+ from->next = to->prev = NULL;
+ }
+ }
+ if ( tlen==0 ) {
+ if ( to->pointtype==pt_curve && to->next && !to->nonextcp ) {
+ tounit.x = to->me.x-to->nextcp.x; tounit.y = to->me.y-to->nextcp.y;
+/* Doesn't work
+ } else if ( to->pointtype==pt_tangent && to->next ) {
+ tounit.x = to->me.x-to->next->to->me.x; tounit.y = to->me.y-to->next->to->me.y;
+*/
+ } else {
+ tounit.x = -( (3*temp.splines[0].a*.9999+2*temp.splines[0].b)*.9999+temp.splines[0].c );
+ tounit.y = -( (3*temp.splines[1].a*.9999+2*temp.splines[1].b)*.9999+temp.splines[1].c );
+ }
+ tlen = sqrt(tounit.x*tounit.x + tounit.y*tounit.y);
+ }
+ tounit.x /= tlen; tounit.y /= tlen;
+
+ if ( flen==0 ) {
+ if ( from->pointtype==pt_curve && from->prev && !from->noprevcp ) {
+ fromunit.x = from->me.x-from->prevcp.x; fromunit.y = from->me.y-from->prevcp.y;
+/*
+ } else if ( from->pointtype==pt_tangent && from->prev ) {
+ fromunit.x = from->me.x-from->prev->from->me.x; fromunit.y = from->me.y-from->prev->from->me.y;
+*/
+ } else {
+ fromunit.x = ( (3*temp.splines[0].a*.0001+2*temp.splines[0].b)*.0001+temp.splines[0].c );
+ fromunit.y = ( (3*temp.splines[1].a*.0001+2*temp.splines[1].b)*.0001+temp.splines[1].c );
+ }
+ flen = sqrt(fromunit.x*fromunit.x + fromunit.y*fromunit.y);
+ }
+ fromunit.x /= flen; fromunit.y /= flen;
+
+ trylen = (to->me.x-from->me.x)*fromunit.x + (to->me.y-from->me.y)*fromunit.y;
+ if ( trylen>flen ) flen = trylen;
+
+ trylen = (from->me.x-to->me.x)*tounit.x + (from->me.y-to->me.y)*tounit.y;
+ if ( trylen>tlen ) tlen = trylen;
+
+ ftunit.x = (to->me.x-from->me.x); ftunit.y = (to->me.y-from->me.y);
+ ftlen = sqrt(ftunit.x*ftunit.x + ftunit.y*ftunit.y);
+ if ( ftlen!=0 ) {
+ ftunit.x /= ftlen; ftunit.y /= ftlen;
+ }
+ fdotft = fromunit.x*ftunit.x + fromunit.y*ftunit.y;
+ fmax = fdotft>0 ? ftlen/fdotft : 1e10;
+ tdotft = -tounit.x*ftunit.x - tounit.y*ftunit.y;
+ tmax = tdotft>0 ? ftlen/tdotft : 1e10;
+ /* At fmax, tmax the control points will stretch beyond the other endpoint*/
+ /* when projected along the line between the two endpoints */
+
+ db.base = from->me;
+ db.unit.x = (to->me.x-from->me.x); db.unit.y = (to->me.y-from->me.y);
+ db.len = sqrt(db.unit.x*db.unit.x + db.unit.y*db.unit.y);
+ if ( db.len!=0 ) {
+ db.unit.x /= db.len;
+ db.unit.y /= db.len;
+ }
+ ApproxBounds(&b,mid,cnt,&db);
+
+ for ( k=0; k<TRY_CNT; ++k ) {
+ bestdiff[k] = 1e20;
+ besti[k] = -1; bestj[k] = -1;
+ }
+ fdiff = flen/DECIMATION;
+ tdiff = tlen/DECIMATION;
+ from->nextcp = from->me;
+ from->nonextcp = false;
+ to->noprevcp = false;
+ memset(&temp,0,sizeof(Spline));
+ temp.from = from; temp.to = to;
+ for ( i=1; i<DECIMATION; ++i ) {
+ from->nextcp.x += fdiff*fromunit.x; from->nextcp.y += fdiff*fromunit.y;
+ to->prevcp = to->me;
+ for ( j=1; j<DECIMATION; ++j ) {
+ to->prevcp.x += tdiff*tounit.x; to->prevcp.y += tdiff*tounit.y;
+ SplineRefigure(&temp);
+ curdiff = SigmaDeltas(&temp,mid,cnt,&b,&db);
+ for ( k=0; k<TRY_CNT; ++k ) {
+ if ( curdiff<bestdiff[k] ) {
+ for ( l=TRY_CNT-1; l>k; --l ) {
+ bestdiff[l] = bestdiff[l-1];
+ besti[l] = besti[l-1];
+ bestj[l] = bestj[l-1];
+ }
+ bestdiff[k] = curdiff;
+ besti[k] = i; bestj[k]=j;
+ break;
+ }
+ }
+ }
+ }
+
+ finaldiff = 1e20;
+ offn_ = offp_ = -1;
+ spline = SplineMake(from,to,false);
+ for ( k=-1; k<TRY_CNT; ++k ) {
+ if ( k<0 ) {
+ BasePoint nextcp, prevcp;
+ double temp1, temp2;
+ int ret = _ApproximateSplineFromPoints(from,to,mid,cnt,&nextcp,&prevcp,false);
+ /* sometimes least squares gives us the right answer */
+ if ( !(ret&1) || !(ret&2))
+ continue;
+ temp1 = (prevcp.x-to->me.x)*tounit.x + (prevcp.y-to->me.y)*tounit.y;
+ temp2 = (nextcp.x-from->me.x)*fromunit.x + (nextcp.y-from->me.y)*fromunit.y;
+ if ( temp1<=0 || temp2<=0 ) /* A nice solution... but the control points are diametrically opposed to what they should be */
+ continue;
+ tlen = temp1; flen = temp2;
+ } else {
+ if ( bestj[k]<0 || besti[k]<0 )
+ continue;
+ tlen = bestj[k]*tdiff; flen = besti[k]*fdiff;
+ }
+ to->prevcp.x = to->me.x + tlen*tounit.x; to->prevcp.y = to->me.y + tlen*tounit.y;
+ from->nextcp.x = from->me.x + flen*fromunit.x; from->nextcp.y = from->me.y + flen*fromunit.y;
+ SplineRefigure(spline);
+
+ bettern = betterp = false;
+ incrn = tdiff/2.0; incrp = fdiff/2.0;
+ offn = flen; offp = tlen;
+ nocnt = 0;
+ curdiff = SigmaDeltas(spline,mid,cnt,&b,&db);
+ totcnt = 0;
+ forever {
+ double fadiff, fsdiff;
+ double tadiff, tsdiff;
+
+ from->nextcp.x = from->me.x + (offn+incrn)*fromunit.x; from->nextcp.y = from->me.y + (offn+incrn)*fromunit.y;
+ to->prevcp.x = to->me.x + offp*tounit.x; to->prevcp.y = to->me.y + offp*tounit.y;
+ SplineRefigure(spline);
+ fadiff = SigmaDeltas(spline,mid,cnt,&b,&db);
+ from->nextcp.x = from->me.x + (offn-incrn)*fromunit.x; from->nextcp.y = from->me.y + (offn-incrn)*fromunit.y;
+ SplineRefigure(spline);
+ fsdiff = SigmaDeltas(spline,mid,cnt,&b,&db);
+ from->nextcp.x = from->me.x + offn*fromunit.x; from->nextcp.y = from->me.y + offn*fromunit.y;
+ if ( offn-incrn<=0 )
+ fsdiff += 1e10;
+
+ to->prevcp.x = to->me.x + (offp+incrp)*tounit.x; to->prevcp.y = to->me.y + (offp+incrp)*tounit.y;
+ SplineRefigure(spline);
+ tadiff = SigmaDeltas(spline,mid,cnt,&b,&db);
+ to->prevcp.x = to->me.x + (offp-incrp)*tounit.x; to->prevcp.y = to->me.y + (offp-incrp)*tounit.y;
+ SplineRefigure(spline);
+ tsdiff = SigmaDeltas(spline,mid,cnt,&b,&db);
+ to->prevcp.x = to->me.x + offp*tounit.x; to->prevcp.y = to->me.y + offp*tounit.y;
+ if ( offp-incrp<=0 )
+ tsdiff += 1e10;
+
+ if ( offn>=incrn && fsdiff<curdiff &&
+ (fsdiff<fadiff && fsdiff<tsdiff && fsdiff<tadiff)) {
+ offn -= incrn;
+ if ( bettern>0 )
+ incrn /= 2;
+ bettern = -1;
+ nocnt = 0;
+ curdiff = fsdiff;
+ } else if ( offn+incrn<fmax && fadiff<curdiff &&
+ (fadiff<=fsdiff && fadiff<tsdiff && fadiff<tadiff)) {
+ offn += incrn;
+ if ( bettern<0 )
+ incrn /= 2;
+ bettern = 1;
+ nocnt = 0;
+ curdiff = fadiff;
+ } else if ( offp>=incrp && tsdiff<curdiff &&
+ (tsdiff<=fsdiff && tsdiff<=fadiff && tsdiff<tadiff)) {
+ offp -= incrp;
+ if ( betterp>0 )
+ incrp /= 2;
+ betterp = -1;
+ nocnt = 0;
+ curdiff = tsdiff;
+ } else if ( offp+incrp<tmax && tadiff<curdiff &&
+ (tadiff<=fsdiff && tadiff<=fadiff && tadiff<=tsdiff)) {
+ offp += incrp;
+ if ( betterp>0 )
+ incrp /= 2;
+ betterp = 1;
+ nocnt = 0;
+ curdiff = tadiff;
+ } else {
+ if ( ++nocnt > 6 )
+ break;
+ incrn /= 2;
+ incrp /= 2;
+ }
+ if ( curdiff<1 )
+ break;
+ if ( incrp<tdiff/1024 || incrn<fdiff/1024 )
+ break;
+ if ( ++totcnt>200 )
+ break;
+ if ( offn<0 || offp<0 ) {
+ IError("Approximation got inverse control points");
+ break;
+ }
+ }
+#if 0
+ if ( nocnt>6 )
+ nocnt_cnt++;
+ else if ( curdiff<1 )
+ curdiff_cnt++;
+ else if ( totcnt>200 )
+ totcnt_cnt++;
+ else
+ incr_cnt++;
+#endif
+ if ( curdiff<finaldiff ) {
+ finaldiff = curdiff;
+ offn_ = offn;
+ offp_ = offp;
+ }
+ }
+
+ to->noprevcp = offp_==0;
+ from->nonextcp = offn_==0;
+ to->prevcp.x = to->me.x + offp_*tounit.x; to->prevcp.y = to->me.y + offp_*tounit.y;
+ from->nextcp.x = from->me.x + offn_*fromunit.x; from->nextcp.y = from->me.y + offn_*fromunit.y;
+ /* I used to check for a spline very close to linear (and if so, make it */
+ /* linear). But in when stroking a path with an eliptical pen we transform*/
+ /* the coordinate system and our normal definitions of "close to linear" */
+ /* don't apply */
+ /*TestForLinear(from,to);*/
+ SplineRefigure(spline);
+
+return( spline );
+}
+#undef TRY_CNT
+#undef DECIMATION
+
+ /* calculating the actual length of a spline is hard, this gives a very */
+ /* rough (but quick) approximation */
+static double SplineLenApprox(Spline *spline) {
+ double len, slen, temp;
+
+ if ( (temp = spline->to->me.x-spline->from->me.x)<0 ) temp = -temp;
+ len = temp;
+ if ( (temp = spline->to->me.y-spline->from->me.y)<0 ) temp = -temp;
+ len += temp;
+ if ( !spline->to->noprevcp || !spline->from->nonextcp ) {
+ if ( (temp = spline->from->nextcp.x-spline->from->me.x)<0 ) temp = -temp;
+ slen = temp;
+ if ( (temp = spline->from->nextcp.y-spline->from->me.y)<0 ) temp = -temp;
+ slen += temp;
+ if ( (temp = spline->to->prevcp.x-spline->from->nextcp.x)<0 ) temp = -temp;
+ slen += temp;
+ if ( (temp = spline->to->prevcp.y-spline->from->nextcp.y)<0 ) temp = -temp;
+ slen += temp;
+ if ( (temp = spline->to->me.x-spline->to->prevcp.x)<0 ) temp = -temp;
+ slen += temp;
+ if ( (temp = spline->to->me.y-spline->to->prevcp.y)<0 ) temp = -temp;
+ slen += temp;
+ len = (len + slen)/2;
+ }
+return( len );
+}
+
+double SplineLength(Spline *spline) {
+ /* I ignore the constant term. It's just an unneeded addition */
+ double len, t;
+ double lastx = 0, lasty = 0;
+ double curx, cury;
+
+ len = 0;
+ for ( t=1.0/128; t<=1.0001 ; t+=1.0/128 ) {
+ curx = ((spline->splines[0].a*t+spline->splines[0].b)*t+spline->splines[0].c)*t;
+ cury = ((spline->splines[1].a*t+spline->splines[1].b)*t+spline->splines[1].c)*t;
+ len += sqrt( (curx-lastx)*(curx-lastx) + (cury-lasty)*(cury-lasty) );
+ lastx = curx; lasty = cury;
+ }
+return( len );
+}
+
+static TPoint *SplinesFigureTPsBetween(SplinePoint *from, SplinePoint *to,
+ int *tot) {
+ int cnt, i, j, pcnt;
+ double len, slen, lbase;
+ SplinePoint *np;
+ TPoint *tp;
+ double _lens[10], *lens = _lens;
+ int _cnts[10], *cnts = _cnts;
+ /* I used just to give every spline 10 points. But that gave much more */
+ /* weight to small splines than to big ones */
+
+ cnt = 0;
+ for ( np = from->next->to; ; np = np->next->to ) {
+ ++cnt;
+ if ( np==to )
+ break;
+ }
+ if ( cnt>10 ) {
+ lens = galloc(cnt*sizeof(double));
+ cnts = galloc(cnt*sizeof(int));
+ }
+ cnt = 0; len = 0;
+ for ( np = from->next->to; ; np = np->next->to ) {
+ lens[cnt] = SplineLenApprox(np->prev);
+ len += lens[cnt];
+ ++cnt;
+ if ( np==to )
+ break;
+ }
+ if ( len!=0 ) {
+ pcnt = 0;
+ for ( i=0; i<cnt; ++i ) {
+ int pnts = rint( (10*cnt*lens[i])/len );
+ if ( pnts<2 ) pnts = 2;
+ cnts[i] = pnts;
+ pcnt += pnts;
+ }
+ } else
+ pcnt = 2*cnt;
+
+ tp = galloc((pcnt+1)*sizeof(TPoint)); i = 0;
+ if ( len==0 ) {
+ for ( i=0; i<=pcnt; ++i ) {
+ tp[i].t = i/(pcnt);
+ tp[i].x = from->me.x;
+ tp[i].y = from->me.y;
+ }
+ } else {
+ lbase = 0;
+ for ( i=cnt=0, np = from->next->to; ; np = np->next->to, ++cnt ) {
+ slen = SplineLenApprox(np->prev);
+ for ( j=0; j<cnts[cnt]; ++j ) {
+ double t = j/(double) cnts[cnt];
+ tp[i].t = (lbase+ t*slen)/len;
+ tp[i].x = ((np->prev->splines[0].a*t+np->prev->splines[0].b)*t+np->prev->splines[0].c)*t + np->prev->splines[0].d;
+ tp[i++].y = ((np->prev->splines[1].a*t+np->prev->splines[1].b)*t+np->prev->splines[1].c)*t + np->prev->splines[1].d;
+ }
+ lbase += slen;
+ if ( np==to )
+ break;
+ }
+ }
+ if ( cnts!=_cnts ) free(cnts);
+ if ( lens!=_lens ) free(lens);
+
+ *tot = i;
+
+return( tp );
+}
+
+void SplinesRemoveBetween(SplineChar *sc, SplinePoint *from, SplinePoint *to,int type) {
+ int tot;
+ TPoint *tp;
+ SplinePoint *np, oldfrom;
+ Spline *sp;
+ int order2 = from->next->order2;
+
+ oldfrom = *from;
+ tp = SplinesFigureTPsBetween(from,to,&tot);
+
+ if ( type==1 )
+ ApproximateSplineFromPointsSlopes(from,to,tp,tot-1,order2);
+ else
+ ApproximateSplineFromPoints(from,to,tp,tot-1,order2);
+
+ /* Have to do the frees after the approximation because the approx */
+ /* uses the splines to determine slopes */
+ for ( sp = oldfrom.next; ; ) {
+ np = sp->to;
+ SplineFree(sp);
+ if ( np==to )
+ break;
+ sp = np->next;
+ SplinePointMDFree(sc,np);
+ }
+
+ free(tp);
+
+ SplinePointCatagorize(from);
+ SplinePointCatagorize(to);
+}
+
+static void RemoveZeroLengthSplines(SplineSet *spl, int onlyselected, double bound) {
+ SplinePoint *curp, *next, *prev;
+ double plen, nlen;
+
+ bound *= bound;
+
+ for ( curp = spl->first, prev=NULL; curp!=NULL ; curp=next ) {
+ next = NULL;
+ if ( curp->next!=NULL )
+ next = curp->next->to;
+ if ( curp==next ) /* Once we've worked a contour down to a single point we can't do anything more here. Someone else will have to free the contour */
+return;
+ /* Zero length splines give us NaNs */
+ if ( curp!=NULL && (curp->selected || !onlyselected) ) {
+ plen = nlen = 1e10;
+ if ( curp->prev!=NULL )
+ plen = (curp->me.x-curp->prev->from->me.x)*(curp->me.x-curp->prev->from->me.x) +
+ (curp->me.y-curp->prev->from->me.y)*(curp->me.y-curp->prev->from->me.y);
+ if ( curp->next!=NULL )
+ nlen = (curp->me.x-next->me.x)*(curp->me.x-next->me.x) +
+ (curp->me.y-next->me.y)*(curp->me.y-next->me.y);
+ if (( curp->prev!=NULL && plen<=bound && plen<nlen ) ||
+ (curp->next!=NULL && nlen<bound && nlen<plen )) {
+ if ( curp->prev!=NULL && plen<=bound && plen<nlen ) {
+ SplinePoint *other = curp->prev->from;
+ other->nextcp = curp->nextcp;
+ other->nonextcp = curp->nonextcp;
+ other->nextcpdef = curp->nextcpdef;
+ other->next = curp->next;
+ if ( curp->next!=NULL ) other->next->from = other;
+ SplineFree(curp->prev);
+ } else {
+ SplinePoint *other = next;
+ other->prevcp = curp->prevcp;
+ other->noprevcp = curp->noprevcp;
+ other->prevcpdef = curp->prevcpdef;
+ other->prev = curp->prev;
+ if ( curp->prev!=NULL ) other->prev->to = other;
+ SplineFree(curp->next);
+ }
+ SplinePointFree(curp);
+ if ( spl->first==curp ) {
+ spl->first = next;
+ if ( spl->last==curp )
+ spl->last = next;
+ } else if ( spl->last==curp )
+ spl->last = prev;
+ } else
+ prev = curp;
+ } else
+ prev = curp;
+ if ( next==spl->first )
+ break;
+ }
+}
+
+SplineSet *SSRemoveZeroLengthSplines(SplineSet *base) {
+ SplineSet *spl, *prev, *next;
+
+ for ( prev = NULL, spl=base; spl!=NULL; spl=next ) {
+ next = spl->next;
+ if ( spl->first->next!=NULL && spl->first->next->to==spl->first &&
+ spl->first->nonextcp && spl->first->noprevcp ) {
+ if ( prev==NULL )
+ base = next;
+ else
+ prev->next = next;
+ spl->next = NULL;
+ SplinePointListFree(spl);
+ } else {
+ RemoveZeroLengthSplines(spl,false,0);
+ prev = spl;
+ }
+ }
+return( base );
+}
+
+static void RemoveStupidControlPoints(SplineSet *spl) {
+ double len, normal, dir;
+ Spline *s, *first;
+ BasePoint unit, off;
+
+ /* Also remove really stupid control points: Tiny offsets pointing in */
+ /* totally the wrong direction. Some of the TeX fonts we get have these */
+ /* We get equally bad results with a control point that points beyond the */
+ /* other end point */
+ first = NULL;
+ for ( s = spl->first->next; s!=NULL && s!=first; s=s->to->next ) {
+ unit.x = s->to->me.x-s->from->me.x;
+ unit.y = s->to->me.y-s->from->me.y;
+ len = sqrt(unit.x*unit.x+unit.y*unit.y);
+ if ( len!=0 ) {
+ int refigure = false;
+ unit.x /= len; unit.y /= len;
+ if ( !s->from->nonextcp ) {
+ off.x = s->from->nextcp.x-s->from->me.x;
+ off.y = s->from->nextcp.y-s->from->me.y;
+ if ((normal = off.x*unit.y - off.y*unit.x)<0 ) normal = -normal;
+ dir = off.x*unit.x + off.y*unit.y;
+ if (( normal<dir && normal<1 && dir<0 ) || (normal<.5 && dir<-.5) ||
+ (normal<.1 && dir>len)) {
+ s->from->nextcp = s->from->me;
+ s->from->nonextcp = true;
+ refigure = true;
+ }
+ }
+ if ( !s->to->noprevcp ) {
+ off.x = s->to->me.x - s->to->prevcp.x;
+ off.y = s->to->me.y - s->to->prevcp.y;
+ if ((normal = off.x*unit.y - off.y*unit.x)<0 ) normal = -normal;
+ dir = off.x*unit.x + off.y*unit.y;
+ if (( normal<-dir && normal<1 && dir<0 ) || (normal<.5 && dir>-.5 && dir<0) ||
+ (normal<.1 && dir>len)) {
+ s->to->prevcp = s->to->me;
+ s->to->noprevcp = true;
+ refigure = true;
+ }
+ }
+ if ( refigure )
+ SplineRefigure(s);
+ }
+ if ( first==NULL ) first = s;
+ }
+}
+
+void SSRemoveStupidControlPoints(SplineSet *base) {
+ SplineSet *spl;
+
+ for (spl=base; spl!=NULL; spl=spl->next )
+ RemoveStupidControlPoints(spl);
+}
+
+static void OverlapClusterCpAngles(SplineSet *spl,double within) {
+ double len, nlen, plen;
+ double startoff, endoff;
+ SplinePoint *sp, *nsp, *psp;
+ BasePoint *nbp, *pbp;
+ BasePoint pdir, ndir, fpdir, fndir;
+ int nbad, pbad;
+
+ /* If we have a junction point (right mid of 3) where the two splines */
+ /* are almost, but not quite moving in the same direction as they go */
+ /* away from the point, and if there is a tiny overlap because of this */
+ /* "almost" same, then we will probably get a bit confused in remove */
+ /* overlap */
+
+ for ( sp = spl->first; ; ) {
+ if ( sp->next==NULL )
+ break;
+ nsp = sp->next->to;
+ if (( !sp->nonextcp || !sp->noprevcp ) && sp->prev!=NULL ) {
+ psp = sp->prev->from;
+ nbp = !sp->nonextcp ? &sp->nextcp : !nsp->noprevcp ? &nsp->prevcp : &nsp->me;
+ pbp = !sp->noprevcp ? &sp->prevcp : !psp->nonextcp ? &psp->nextcp : &psp->me;
+
+ pdir.x = pbp->x-sp->me.x; pdir.y = pbp->y-sp->me.y;
+ ndir.x = nbp->x-sp->me.x; ndir.y = nbp->y-sp->me.y;
+ fpdir.x = psp->me.x-sp->me.x; fpdir.y = psp->me.y-sp->me.y;
+ fndir.x = nsp->me.x-sp->me.x; fndir.y = nsp->me.y-sp->me.y;
+
+ plen = sqrt(pdir.x*pdir.x+pdir.y*pdir.y);
+ if ( plen!=0 ) {
+ pdir.x /= plen; pdir.y /= plen;
+ }
+
+ nlen = sqrt(ndir.x*ndir.x+ndir.y*ndir.y);
+ if ( nlen!=0 ) {
+ ndir.x /= nlen; ndir.y /= nlen;
+ }
+
+ nbad = pbad = false;
+ if ( !sp->nonextcp && plen!=0 && nlen!=0 ) {
+ len = sqrt(fndir.x*fndir.x+fndir.y*fndir.y);
+ if ( len!=0 ) {
+ fndir.x /= len; fndir.y /= len;
+ startoff = ndir.x*pdir.y - ndir.y*pdir.x;
+ endoff = fndir.x*pdir.y - fndir.y*pdir.x;
+ if (( (startoff<0 && endoff>0) || (startoff>0 && endoff<0)) &&
+ startoff > -within && startoff < within )
+ nbad = true;
+ }
+ }
+ if ( !sp->noprevcp && plen!=0 && nlen!=0 ) {
+ len = sqrt(fpdir.x*fpdir.x+fpdir.y*fpdir.y);
+ if ( len!=0 ) {
+ fpdir.x /= len; fpdir.y /= len;
+ startoff = pdir.x*ndir.y - pdir.y*ndir.x;
+ endoff = fpdir.x*ndir.y - fpdir.y*ndir.x;
+ if (( (startoff<0 && endoff>0) || (startoff>0 && endoff<0)) &&
+ startoff > -within && startoff < within )
+ pbad = true;
+ }
+ }
+ if ( nbad && pbad ) {
+ if ( ndir.x==0 || ndir.y==0 )
+ nbad = false;
+ else if ( pdir.x==0 || pdir.y==0 )
+ pbad = false;
+ }
+ if ( nbad && pbad ) {
+ if ( ndir.x*pdir.x + ndir.y*pdir.y > 0 ) {
+ ndir.x = pdir.x = (ndir.x + pdir.x)/2;
+ ndir.y = pdir.y = (ndir.x + pdir.x)/2;
+ } else {
+ ndir.x = (ndir.x - pdir.x)/2;
+ ndir.y = (ndir.y - pdir.y)/2;
+ pdir.x = -ndir.x; pdir.y = -ndir.y;
+ }
+ sp->nextcp.x = sp->me.x + nlen*ndir.x;
+ sp->nextcp.y = sp->me.y + nlen*ndir.y;
+ sp->prevcp.x = sp->me.x + plen*pdir.x;
+ sp->prevcp.y = sp->me.y + plen*pdir.y;
+ SplineRefigure(sp->next); SplineRefigure(sp->prev);
+ } else if ( nbad ) {
+ if ( ndir.x*pdir.x + ndir.y*pdir.y < 0 ) {
+ pdir.x = -pdir.x;
+ pdir.y = -pdir.y;
+ }
+ sp->nextcp.x = sp->me.x + nlen*pdir.x;
+ sp->nextcp.y = sp->me.y + nlen*pdir.y;
+ SplineRefigure(sp->next);
+ } else if ( pbad ) {
+ if ( ndir.x*pdir.x + ndir.y*pdir.y < 0 ) {
+ ndir.x = -ndir.x;
+ ndir.y = -ndir.y;
+ }
+ sp->prevcp.x = sp->me.x + plen*ndir.x;
+ sp->prevcp.y = sp->me.y + plen*ndir.y;
+ SplineRefigure(sp->prev);
+ }
+ }
+ if ( nsp==spl->first )
+ break;
+ sp = nsp;
+ }
+}
+
+void SSOverlapClusterCpAngles(SplineSet *base,double within) {
+ SplineSet *spl;
+
+ for (spl=base; spl!=NULL; spl=spl->next )
+ OverlapClusterCpAngles(spl,within);
+}
+
+static SplinePointList *SplinePointListMerge(SplineChar *sc, SplinePointList *spl,int type) {
+ Spline *spline, *first;
+ SplinePoint *nextp, *curp, *selectme;
+ int all;
+
+ /* If the entire splineset is selected, it should merge into oblivion */
+ first = NULL;
+ all = spl->first->selected;
+ for ( spline = spl->first->next; spline!=NULL && spline!=first && all; spline=spline->to->next ) {
+ if ( !spline->to->selected ) all = false;
+ if ( first==NULL ) first = spline;
+ }
+ if ( spl->first->next!=NULL && spl->first->next->to==spl->first &&
+ spl->first->nonextcp && spl->first->noprevcp )
+ all = true; /* Merge away any splines which are just dots */
+ if ( all )
+return( NULL ); /* Some one else should free it and reorder the spline set list */
+ RemoveZeroLengthSplines(spl,true,.3);
+
+ if ( spl->first!=spl->last ) {
+ /* If the spline isn't closed, then any selected points at the ends */
+ /* get deleted */
+ while ( spl->first->selected ) {
+ nextp = spl->first->next->to;
+ SplineFree(spl->first->next);
+ SplinePointMDFree(sc,spl->first);
+ spl->first = nextp;
+ nextp->prev = NULL;
+ }
+ while ( spl->last->selected ) {
+ nextp = spl->last->prev->from;
+ SplineFree(spl->last->prev);
+ SplinePointMDFree(sc,spl->last);
+ spl->last = nextp;
+ nextp->next = NULL;
+ }
+ } else {
+ while ( spl->first->selected ) {
+ spl->first = spl->first->next->to;
+ spl->last = spl->first;
+ }
+ }
+
+ /* when we get here spl->first is not selected */
+ if ( spl->first->selected ) IError( "spl->first is selected in SplinePointListMerge");
+ curp = spl->first;
+ selectme = NULL;
+ while ( 1 ) {
+ while ( !curp->selected ) {
+ if ( curp->next==NULL )
+ curp = NULL;
+ else
+ curp = curp->next->to;
+ if ( curp==spl->first || curp==NULL )
+ break;
+ }
+ if ( curp==NULL || !curp->selected )
+ break;
+ for ( nextp=curp->next->to; nextp->selected; nextp = nextp->next->to );
+ /* we don't need to check for the end of the splineset here because */
+ /* we know that spl->last is not selected */
+ SplinesRemoveBetween(sc,curp->prev->from,nextp,type);
+ curp = nextp;
+ selectme = nextp;
+ }
+ if ( selectme!=NULL ) selectme->selected = true;
+return( spl );
+}
+
+void SplineCharMerge(SplineChar *sc,SplineSet **head,int type) {
+ SplineSet *spl, *prev=NULL, *next;
+
+ for ( spl = *head; spl!=NULL; spl = next ) {
+ next = spl->next;
+ if ( SplinePointListMerge(sc,spl,type)==NULL ) {
+ if ( prev==NULL )
+ *head = next;
+ else
+ prev->next = next;
+ chunkfree(spl,sizeof(*spl));
+ } else
+ prev = spl;
+ }
+}
+
+static int SPisExtremum(SplinePoint *sp) {
+ BasePoint *prev, *next;
+ SplinePoint *psp, *nsp;
+
+ if ( sp->prev==NULL || sp->next==NULL )
+return( true );
+
+ nsp = sp->next->to;
+ psp = sp->prev->from;
+
+ /* A point that changes from curved to straight horizontal/vertical should*/
+ /* be treated as an extremum */
+ if (( !sp->next->knownlinear && sp->prev->knownlinear &&
+ (RealWithin(sp->me.x,sp->prev->from->me.x,.02) ||
+ RealWithin(sp->me.y,sp->prev->from->me.y,.02))) ||
+ ( !sp->prev->knownlinear && sp->next->knownlinear &&
+ (RealWithin(sp->me.x,sp->next->to->me.x,.02) ||
+ RealWithin(sp->me.y,sp->next->to->me.y,.02))))
+return( true );
+
+ if ( sp->prev->knownlinear )
+ prev = &psp->me;
+ else if ( !sp->noprevcp )
+ prev = &sp->prevcp;
+ else
+ prev = &psp->nextcp;
+ if ( sp->next->knownlinear )
+ next = &nsp->me;
+ else if ( !sp->nonextcp )
+ next = &sp->nextcp;
+ else
+ next = &nsp->prevcp;
+
+ if ( sp->next->knownlinear && sp->prev->knownlinear &&
+ ((sp->me.x==nsp->me.x && sp->me.x==psp->me.x &&
+ ((sp->me.y<=nsp->me.y && psp->me.y<=sp->me.y) ||
+ (sp->me.y>=nsp->me.y && psp->me.y>=sp->me.y))) ||
+ (sp->me.y==nsp->me.y && sp->me.y==psp->me.y &&
+ ((sp->me.x<=nsp->me.x && psp->me.x<=sp->me.x) ||
+ (sp->me.x>=nsp->me.x && psp->me.x>=sp->me.x)))) )
+return( false ); /* A point in the middle of a horizontal/vertical line */
+ /* is not an extrema and can be removed */
+
+ if ( prev->x==sp->me.x && next->x==sp->me.x ) {
+ if ( prev->y==sp->me.y && next->y==sp->me.y )
+return( false ); /* this should be caught above */
+#if 0 /* no matter what the control points look like this guy is either an */
+ /* an extremum or a point of inflection, so we don't need to check */
+ if (( prev->y<=sp->me.y && sp->me.y <= next->y ) ||
+ (prev->y>=sp->me.y && sp->me.y >= next->y ))
+#endif
+return( true );
+ } else if ( prev->y==sp->me.y && next->y==sp->me.y ) {
+return( true );
+ } else if (( prev->x<=sp->me.x && next->x<=sp->me.x ) ||
+ (prev->x>=sp->me.x && next->x>=sp->me.x ))
+return( true );
+ else if (( prev->y<=sp->me.y && next->y<=sp->me.y ) ||
+ (prev->y>=sp->me.y && next->y>=sp->me.y ))
+return( true );
+
+return( false );
+}
+
+/* Almost exactly the same as SplinesRemoveBetween, but this one is conditional */
+/* the intermediate points/splines are removed only if we have a good match */
+/* used for simplify */
+static int SplinesRemoveBetweenMaybe(SplineChar *sc,
+ SplinePoint *from, SplinePoint *to, int flags, double err) {
+ int i,tot;
+ SplinePoint *afterfrom, *sp, *next;
+ TPoint *tp, *tp2;
+ BasePoint test;
+ int good;
+ BasePoint fncp, tpcp;
+ int fpt, tpt;
+ int order2 = from->next->order2;
+
+ afterfrom = from->next->to;
+ fncp = from->nextcp; tpcp = to->prevcp;
+ fpt = from->pointtype; tpt = to->pointtype;
+
+ if ( afterfrom==to || from==to )
+return( false );
+
+ tp = SplinesFigureTPsBetween(from,to,&tot);
+ tp2 = galloc((tot+1)*sizeof(TPoint));
+ memcpy(tp2,tp,tot*sizeof(TPoint));
+
+ if ( !(flags&sf_ignoreslopes) )
+ ApproximateSplineFromPointsSlopes(from,to,tp,tot-1,order2);
+ else {
+ ApproximateSplineFromPoints(from,to,tp,tot-1,order2);
+ }
+
+ i = tot;
+
+ good = true;
+ while ( --i>0 && good ) {
+ /* tp[0] is the same as from (easier to include it), but the SplineNear*/
+ /* routine will sometimes reject the end-points of the spline */
+ /* so just don't check it */
+ test.x = tp2[i].x; test.y = tp2[i].y;
+ good = SplineNearPoint(from->next,&test,err)!= -1;
+ }
+
+ free(tp);
+ free(tp2);
+ if ( good ) {
+ SplineFree(afterfrom->prev);
+ for ( sp=afterfrom; sp!=to; sp=next ) {
+ next = sp->next->to;
+ SplineFree(sp->next);
+ SplinePointMDFree(sc,sp);
+ }
+ SplinePointCatagorize(from);
+ SplinePointCatagorize(to);
+ } else {
+ SplineFree(from->next);
+ from->next = afterfrom->prev;
+ from->nextcp = fncp;
+ from->nonextcp = ( fncp.x==from->me.x && fncp.y==from->me.y);
+ from->pointtype = fpt;
+ for ( sp=afterfrom; sp->next->to!=to; sp=sp->next->to );
+ to->prev = sp->next;
+ to->prevcp = tpcp;
+ to->noprevcp = ( tpcp.x==to->me.x && tpcp.y==to->me.y);
+ to->pointtype = tpt;
+ }
+return( good );
+}
+
+/* In truetype we can interpolate away an on curve point. Try this */
+static int Spline2Interpolate(SplinePoint *mid, double err) {
+ SplinePoint *from, *to;
+ BasePoint midme, test;
+ int i,tot, good;
+ TPoint *tp;
+
+ midme = mid->me;
+ from = mid->prev->from; to = mid->next->to;
+ tp = SplinesFigureTPsBetween(from,to,&tot);
+
+ mid->me.x = (mid->prevcp.x + mid->nextcp.x)/2;
+ mid->me.y = (mid->prevcp.y + mid->nextcp.y)/2;
+ SplineRefigure(mid->next);
+ SplineRefigure(mid->prev);
+
+ i = tot;
+ good = true;
+ while ( --i>0 && good ) {
+ /* tp[0] is the same as from (easier to include it), but the SplineNear*/
+ /* routine will sometimes reject the end-points of the spline */
+ /* so just don't check it */
+ test.x = tp[i].x; test.y = tp[i].y;
+ if ( i>tot/2 )
+ good = SplineNearPoint(mid->next,&test,err)!= -1 ||
+ SplineNearPoint(mid->prev,&test,err)!= -1;
+ else
+ good = SplineNearPoint(mid->prev,&test,err)!= -1 ||
+ SplineNearPoint(mid->next,&test,err)!= -1;
+ }
+ if ( !good ) {
+ mid->me = midme;
+ SplineRefigure(mid->next);
+ SplineRefigure(mid->prev);
+ }
+ free(tp);
+return( good );
+}
+
+int SPInterpolate(SplinePoint *sp) {
+ /* Using truetype rules, can we interpolate this point? */
+return( !sp->dontinterpolate && !sp->nonextcp && !sp->noprevcp &&
+ !sp->roundx && !sp->roundy &&
+ (RealWithin(sp->me.x,(sp->nextcp.x+sp->prevcp.x)/2,.1) &&
+ RealWithin(sp->me.y,(sp->nextcp.y+sp->prevcp.y)/2,.1)) );
+}
+
+static int _SplinesRemoveMidMaybe(SplineChar *sc,SplinePoint *mid, int flags,
+ double err, double lenmax2) {
+ SplinePoint *from, *to;
+#if 0 /* See comment below */
+ BasePoint fncp, tpcp, fncp2, tpcp2;
+ int fpt, tpt;
+#endif
+
+ if ( mid->prev==NULL || mid->next==NULL )
+return( false );
+
+ from = mid->prev->from; to = mid->next->to;
+
+ /* Retain points which are horizontal or vertical, because postscript says*/
+ /* type1 fonts should always have a point at the extrema (except for small*/
+ /* things like serifs), and the extrema occur at horizontal/vertical points*/
+ /* tt says something similar */
+ if ( !(flags&sf_ignoreextremum) && SPisExtremum(mid) )
+return( false );
+
+ if ( !(flags&sf_mergelines) && (mid->pointtype==pt_corner ||
+ mid->prev->knownlinear || mid->next->knownlinear) ) {
+ /* Be very careful about merging straight lines. Generally they should*/
+ /* remain straight... */
+ /* Actually it's not that the lines are straight, the significant thing */
+ /* is that if there is a abrupt change in direction at this point */
+ /* (a corner) we don't want to get rid of it */
+ BasePoint prevu, nextu;
+ double plen, nlen;
+
+ if ( mid->next->knownlinear || mid->nonextcp ) {
+ nextu.x = to->me.x-mid->me.x;
+ nextu.y = to->me.y-mid->me.y;
+ } else {
+ nextu.x = mid->nextcp.x-mid->me.x;
+ nextu.y = mid->nextcp.y-mid->me.y;
+ }
+ if ( mid->prev->knownlinear || mid->noprevcp ) {
+ prevu.x = from->me.x-mid->me.x;
+ prevu.y = from->me.y-mid->me.y;
+ } else {
+ prevu.x = mid->prevcp.x-mid->me.x;
+ prevu.y = mid->prevcp.y-mid->me.y;
+ }
+ nlen = sqrt(nextu.x*nextu.x + nextu.y*nextu.y);
+ plen = sqrt(prevu.x*prevu.x + prevu.y*prevu.y);
+ if ( nlen==0 || plen==0 )
+ /* Not a real corner */;
+ else if ( (nextu.x*prevu.x + nextu.y*prevu.y)/(nlen*plen)>((nlen+plen>20)?-.98:-.95) ) {
+ /* If the cos if the angle between the two segments is too far */
+ /* from parallel then don't try to smooth the point into oblivion */
+ double flen, tlen;
+ flen = (from->me.x-mid->me.x)*(from->me.x-mid->me.x) +
+ (from->me.y-mid->me.y)*(from->me.y-mid->me.y);
+ tlen = (to->me.x-mid->me.x)*(to->me.x-mid->me.x) +
+ (to->me.y-mid->me.y)*(to->me.y-mid->me.y);
+ if ( (flen<.7 && tlen<.7) || flen<.25 || tlen<.25 )
+ /* Too short to matter */;
+ else
+return( false );
+ }
+
+ if ( mid->prev->knownlinear && mid->next->knownlinear ) {
+ /* Special checks for horizontal/vertical lines */
+ /* don't let the smoothing distort them */
+ if ( from->me.x==to->me.x ) {
+ if ( mid->me.x!=to->me.x )
+return( false );
+ } else if ( from->me.y==to->me.y ) {
+ if ( mid->me.y!=to->me.y )
+return( false );
+ } else if ( !RealRatio((from->me.y-to->me.y)/(from->me.x-to->me.x),
+ (mid->me.y-to->me.y)/(mid->me.x-to->me.x),
+ .05) ) {
+return( false );
+ }
+ } else if ( mid->prev->knownlinear ) {
+ if ( (mid->me.x-from->me.x)*(mid->me.x-from->me.x) + (mid->me.y-from->me.y)*(mid->me.y-from->me.y)
+ > lenmax2 )
+return( false );
+ } else {
+ if ( (mid->me.x-to->me.x)*(mid->me.x-to->me.x) + (mid->me.y-to->me.y)*(mid->me.y-to->me.y)
+ > lenmax2 )
+return( false );
+ }
+ }
+
+#if 0 /* Used to try to enforce tangentness of a point */
+ /* I now think it's better to change the point to a curve */
+ fncp2 = fncp = from->nextcp; tpcp2 = tpcp = to->prevcp;
+ fpt = from->pointtype; tpt = to->pointtype;
+
+ /* if from or to is a tangent then we can only remove mid if it's on the */
+ /* line between them */
+ if (( from->pointtype==pt_tangent && !from->noprevcp) ||
+ ( to->pointtype==pt_tangent && !to->nonextcp)) {
+ if ( from->me.x==to->me.x ) {
+ if ( mid->me.x!=to->me.x )
+return( false );
+ } else if ( !RealNear((from->me.y-to->me.y)/(from->me.x-to->me.x),
+ (mid->me.y-to->me.y)/(mid->me.x-to->me.x)) )
+return( false );
+ }
+#endif
+
+ if ( mid->next->order2 ) {
+ if ( SPInterpolate(from) && SPInterpolate(to) && SPInterpolate(mid))
+return( false );
+ }
+
+return ( SplinesRemoveBetweenMaybe(sc,from,to,flags,err));
+}
+
+/* A wrapper to SplinesRemoveBetweenMaybe to handle some extra checking for a */
+/* common case */
+static int SplinesRemoveMidMaybe(SplineChar *sc,SplinePoint *mid, int flags,
+ double err, double lenmax2) {
+ int changed1 = false;
+ if ( mid->next->order2 ) {
+ if ( !mid->dontinterpolate && !mid->nonextcp && !mid->noprevcp &&
+ !(RealWithin(mid->me.x,(mid->nextcp.x+mid->prevcp.x)/2,.1) &&
+ RealWithin(mid->me.y,(mid->nextcp.y+mid->prevcp.y)/2,.1)) )
+ changed1 = Spline2Interpolate(mid,err);
+ }
+return( _SplinesRemoveMidMaybe(sc,mid,flags,err,lenmax2) || changed1 );
+}
+
+#ifndef LUA_FF_LIB
+void SPLNearlyHvCps(SplineChar *sc,SplineSet *ss,double err) {
+ Spline *s, *first=NULL;
+ int refresh;
+ SplinePoint *from, *to;
+
+ for ( s = ss->first->next; s!=NULL && s!=first; s=s->to->next ) {
+ if ( first==NULL ) first = s;
+ refresh = false;
+ from = s->from; to = s->to;
+ if ( !from->nonextcp && from->nextcp.x-from->me.x<err && from->nextcp.x-from->me.x>-err ) {
+ from->nextcp.x = from->me.x;
+ if ( s->order2 ) to->prevcp = from->nextcp;
+ if ( from->nextcp.y==from->me.y ) from->nonextcp = true;
+ refresh = true;
+ } else if ( !from->nonextcp && from->nextcp.y-from->me.y<err && from->nextcp.y-from->me.y>-err ) {
+ from->nextcp.y = from->me.y;
+ if ( s->order2 ) to->prevcp = from->nextcp;
+ if ( from->nextcp.x==from->me.x ) from->nonextcp = true;
+ refresh = true;
+ }
+ if ( !to->noprevcp && to->prevcp.x-to->me.x<err && to->prevcp.x-to->me.x>-err ) {
+ to->prevcp.x = to->me.x;
+ if ( s->order2 ) from->nextcp = to->prevcp;
+ if ( to->prevcp.y==to->me.y ) to->noprevcp = true;
+ refresh = true;
+ } else if ( !to->noprevcp && to->prevcp.y-to->me.y<err && to->prevcp.y-to->me.y>-err ) {
+ to->prevcp.y = to->me.y;
+ if ( s->order2 ) from->nextcp = to->prevcp;
+ if ( to->prevcp.x==to->me.x ) to->noprevcp = true;
+ refresh = true;
+ }
+ if ( refresh )
+ SplineRefigure(s);
+ }
+}
+#endif
+
+void SPLNearlyHvLines(SplineChar *sc,SplineSet *ss,double err) {
+ Spline *s, *first=NULL;
+
+ for ( s = ss->first->next; s!=NULL && s!=first; s=s->to->next ) {
+ if ( first==NULL ) first = s;
+ if ( s->knownlinear ) {
+ if ( s->to->me.x-s->from->me.x<err && s->to->me.x-s->from->me.x>-err ) {
+ s->to->nextcp.x += (s->from->me.x-s->to->me.x);
+ s->to->me.x = s->from->me.x;
+ s->to->prevcp = s->to->me;
+ s->from->nextcp = s->from->me;
+ SplineRefigure(s);
+ if ( s->to->next != NULL )
+ SplineRefigure(s->to->next);
+ } else if ( s->to->me.y-s->from->me.y<err && s->to->me.y-s->from->me.y>-err ) {
+ s->to->nextcp.y += (s->from->me.y-s->to->me.y);
+ s->to->me.y = s->from->me.y;
+ s->to->prevcp = s->to->me;
+ s->from->nextcp = s->from->me;
+ SplineRefigure(s);
+ if ( s->to->next != NULL )
+ SplineRefigure(s->to->next);
+ }
+ }
+ }
+}
+
+#ifndef LUA_FF_LIB
+/* Does this spline deviate from a straight line between its endpoints by more*/
+/* than err? */
+/* Rotate the spline so that the line between the endpoints is horizontal, */
+/* then find the maxima/minima of the y spline (this is the deviation) */
+/* check that that is less than err */
+static int SplineCloseToLinear(Spline *s, double err) {
+ double angle;
+ extended co,si, t1, t2, y;
+ SplinePoint from, to;
+ Spline sp;
+ BasePoint bp;
+
+ from = *s->from; to = *s->to;
+ to.me.x -= from.me.x; to.me.y -= from.me.y;
+ to.prevcp.x -= from.me.x; to.prevcp.y -= from.me.y;
+ from.nextcp.x -= from.me.x ; from.nextcp.y -= from.me.y;
+ from.me.x = from.me.y = 0;
+ angle = atan2(to.me.y, to.me.x);
+
+ si = sin(angle); co = cos(angle);
+ bp.x = to.me.x*co + to.me.y*si;
+ bp.y = -to.me.x*si + to.me.y*co;
+ to.me = bp;
+
+ bp.x = to.prevcp.x*co + to.prevcp.y*si;
+ bp.y = -to.prevcp.x*si + to.prevcp.y*co;
+ to.prevcp = bp;
+
+ bp.x = from.nextcp.x*co + from.nextcp.y*si;
+ bp.y = -from.nextcp.x*si + from.nextcp.y*co;
+ from.nextcp = bp;
+
+ memset(&sp,0,sizeof(Spline));
+ sp.from = &from; sp.to = &to;
+ sp.order2 = s->order2;
+ SplineRefigure(&sp);
+ SplineFindExtrema(&sp.splines[1],&t1,&t2);
+
+ if ( t1==-1 )
+return( true );
+
+ y = ((sp.splines[1].a*t1 + sp.splines[1].b)*t1 + sp.splines[1].c)*t1 + sp.splines[1].d;
+ if ( y>err || y<-err )
+return( false );
+
+ if ( t2==-1 )
+return( true );
+ y = ((sp.splines[1].a*t2 + sp.splines[1].b)*t2 + sp.splines[1].c)*t2 + sp.splines[1].d;
+return( y<=err && y>=-err );
+}
+
+int SPLNearlyLines(SplineChar *sc,SplineSet *ss,double err) {
+ Spline *s, *first=NULL;
+ int changed = false;
+
+ for ( s = ss->first->next; s!=NULL && s!=first; s=s->to->next ) {
+ if ( first==NULL ) first = s;
+ if ( s->islinear )
+ /* Nothing to be done */;
+ else if ( s->knownlinear || SplineCloseToLinear(s,err)) {
+ s->from->nextcp = s->from->me;
+ s->from->nonextcp = true;
+ s->to->prevcp = s->to->me;
+ s->to->noprevcp = true;
+ SplineRefigure(s);
+ changed = true;
+ }
+ }
+return( changed );
+}
+#endif
+
+static void SPLForceLines(SplineChar *sc,SplineSet *ss,double bump_size) {
+ Spline *s, *first=NULL;
+ SplinePoint *sp;
+ int any;
+ BasePoint unit;
+ double len, minlen = (sc->parent->ascent+sc->parent->descent)/20.0;
+ double diff, xoff, yoff, len2;
+
+ for ( s = ss->first->next; s!=NULL && s!=first; s=s->to->next ) {
+ if ( first==NULL ) first = s;
+ if ( s->knownlinear ) {
+ unit.x = s->to->me.x-s->from->me.x;
+ unit.y = s->to->me.y-s->from->me.y;
+ len = sqrt(unit.x*unit.x + unit.y*unit.y);
+ if ( len<minlen )
+ continue;
+ unit.x /= len; unit.y /= len;
+ do {
+ any = false;
+ if ( s->from->prev!=NULL && s->from->prev!=s ) {
+ sp = s->from->prev->from;
+ len2 = sqrt((sp->me.x-s->from->me.x)*(sp->me.x-s->from->me.x) + (sp->me.y-s->from->me.y)*(sp->me.y-s->from->me.y));
+ diff = (sp->me.x-s->from->me.x)*unit.y - (sp->me.y-s->from->me.y)*unit.x;
+ if ( len2<len && fabs(diff)<=bump_size ) {
+ xoff = diff*unit.y; yoff = -diff*unit.x;
+ sp->me.x -= xoff; sp->me.y -= yoff;
+ sp->prevcp.x -= xoff; sp->prevcp.y -= yoff;
+ sp->nextcp = sp->me; sp->nonextcp = true;
+ if ( sp->next==first ) first = NULL;
+ SplineFree(sp->next);
+ if ( s->from==ss->first ) {
+ if ( ss->first==ss->last ) ss->last = sp;
+ ss->first = sp;
+ }
+ SplinePointMDFree(sc,s->from);
+ sp->next = s; s->from = sp;
+ SplineRefigure(s);
+ if ( sp->prev!=NULL )
+ SplineRefigure(sp->prev);
+ sp->pointtype = pt_corner;
+ any = true;
+
+ /* We must recalculate the length each time, we */
+ /* might have shortened it. */
+ unit.x = s->to->me.x-s->from->me.x;
+ unit.y = s->to->me.y-s->from->me.y;
+ len = sqrt(unit.x*unit.x + unit.y*unit.y);
+ if ( len<minlen )
+ break;
+ unit.x /= len; unit.y /= len;
+ }
+ }
+ if ( s->to->next!=NULL && s->to->next!=s ) {
+ sp = s->to->next->to;
+ /* If the next spline is a longer line than we are, then don't */
+ /* merge it to us, rather merge us into it next time through the loop */
+ /* Hmm. Don't merge out the bump in general if the "bump" is longer than we are */
+ len2 = sqrt((sp->me.x-s->to->me.x)*(sp->me.x-s->to->me.x) + (sp->me.y-s->to->me.y)*(sp->me.y-s->to->me.y));
+ diff = (sp->me.x-s->to->me.x)*unit.y - (sp->me.y-s->to->me.y)*unit.x;
+ if ( len2<len && fabs(diff)<=bump_size ) {
+ xoff = diff*unit.y; yoff = -diff*unit.x;
+ sp->me.x -= xoff; sp->me.y -= yoff;
+ sp->nextcp.x -= xoff; sp->nextcp.y -= yoff;
+ sp->prevcp = sp->me; sp->noprevcp = true;
+ if ( sp->prev==first ) first = NULL;
+ SplineFree(sp->prev);
+ if ( s->to==ss->last ) {
+ if ( ss->first==ss->last ) ss->first = sp;
+ ss->last = sp;
+ }
+ SplinePointMDFree(sc,s->to);
+ sp->prev = s; s->to = sp;
+ SplineRefigure(s);
+ if ( sp->next!=NULL )
+ SplineRefigure(sp->next);
+ sp->pointtype = pt_corner;
+ any = true;
+
+ unit.x = s->to->me.x-s->from->me.x;
+ unit.y = s->to->me.y-s->from->me.y;
+ len = sqrt(unit.x*unit.x + unit.y*unit.y);
+ if ( len<minlen )
+ break;
+ unit.x /= len; unit.y /= len;
+ }
+ }
+ } while ( any );
+ }
+ }
+}
+
+static int SPLSmoothControlPoints(SplineSet *ss,double tan_bounds,int vert_check) {
+ SplinePoint *sp;
+ /* If a point has control points, and if those cps are in nearly the same */
+ /* direction (within tan_bounds) then adjust them so that they are in the*/
+ /* same direction */
+ BasePoint unit, unit2;
+ double len, len2, para, norm, tn;
+ int changed=false, found;
+
+ for ( sp = ss->first; ; ) {
+ if (( !sp->nonextcp && !sp->noprevcp && sp->pointtype==pt_corner ) ||
+ ((sp->pointtype==pt_corner || sp->pointtype==pt_curve) &&
+ (( !sp->nonextcp && sp->noprevcp && sp->prev!=NULL && sp->prev->knownlinear ) ||
+ ( !sp->noprevcp && sp->nonextcp && sp->next!=NULL && sp->next->knownlinear )))) {
+ BasePoint *next = sp->nonextcp ? &sp->next->to->me : &sp->nextcp;
+ BasePoint *prev = sp->noprevcp ? &sp->prev->to->me : &sp->prevcp;
+ unit.x = next->x-sp->me.x;
+ unit.y = next->y-sp->me.y;
+ len = sqrt(unit.x*unit.x + unit.y*unit.y);
+ unit.x /= len; unit.y /= len;
+ para = (sp->me.x-prev->x)*unit.x + (sp->me.y-prev->y)*unit.y;
+ norm = (sp->me.x-prev->x)*unit.y - (sp->me.y-prev->y)*unit.x;
+ if ( para==0 )
+ tn = 1000;
+ else
+ tn = norm/para;
+ if ( tn<0 ) tn = -tn;
+ if ( tn<tan_bounds && para>0 ) {
+ found = 0;
+ unit2.x = sp->me.x-sp->prevcp.x;
+ unit2.y = sp->me.y-sp->prevcp.y;
+ len2 = sqrt(unit2.x*unit2.x + unit2.y*unit2.y);
+ unit2.x /= len2; unit2.y /= len2;
+ if ( vert_check ) {
+ if ( fabs(unit.x)>fabs(unit.y) ) {
+ /* Closer to horizontal */
+ if ( (unit.y<=0 && unit2.y>=0) || (unit.y>=0 && unit2.y<=0) ) {
+ unit2.x = unit2.x<0 ? -1 : 1; unit2.y = 0;
+ found = 1;
+ }
+ } else {
+ if ( (unit.x<=0 && unit2.x>=0) || (unit.x>=0 && unit2.x<=0) ) {
+ unit2.y = unit2.y<0 ? -1 : 1; unit2.x = 0;
+ found = 1;
+ }
+ }
+ }
+ /* If we're next to a line, we must extend the line. No choice */
+ if ( sp->nonextcp ) {
+ if ( len<len2 )
+ goto nextpt;
+ found = true;
+ unit2 = unit;
+ } else if ( sp->noprevcp ) {
+ if ( len2<len )
+ goto nextpt;
+ found = true;
+ } else if ( !found ) {
+ unit2.x = (unit.x*len + unit2.x*len2)/(len+len2);
+ unit2.y = (unit.y*len + unit2.y*len2)/(len+len2);
+ }
+ sp->nextcp.x = sp->me.x + len*unit2.x;
+ sp->nextcp.y = sp->me.y + len*unit2.y;
+ sp->prevcp.x = sp->me.x - len2*unit2.x;
+ sp->prevcp.y = sp->me.y - len2*unit2.y;
+ sp->pointtype = pt_curve;
+ if ( sp->prev )
+ SplineRefigure(sp->prev);
+ if ( sp->next )
+ SplineRefigure(sp->next);
+ changed = true;
+ }
+ }
+ nextpt:
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+return( changed );
+}
+
+static void GetNextUnitVector(SplinePoint *sp,BasePoint *uv) {
+ double len;
+
+ if ( sp->next==NULL ) {
+ uv->x = uv->y = 0;
+ } else if ( sp->next->knownlinear ) {
+ uv->x = sp->next->to->me.x - sp->me.x;
+ uv->y = sp->next->to->me.y - sp->me.y;
+ } else if ( sp->nonextcp ) {
+ uv->x = sp->next->to->prevcp.x - sp->me.x;
+ uv->y = sp->next->to->prevcp.y - sp->me.y;
+ } else {
+ uv->x = sp->nextcp.x - sp->me.x;
+ uv->y = sp->nextcp.y - sp->me.y;
+ }
+ len = sqrt(uv->x*uv->x + uv->y*uv->y );
+ if ( len!= 0 ) {
+ uv->x /= len;
+ uv->y /= len;
+ }
+}
+
+static int isExtreme(SplinePoint *sp) {
+ if ( sp->next==NULL || sp->prev==NULL )
+return( 2 ); /* End point. Always extreme */
+ if ( sp->nonextcp ) {
+ if ( !sp->next->knownlinear )
+return( false );
+ if ( sp->next->to->me.x == sp->me.x || sp->next->to->me.y == sp->me.y )
+ /* Ok, horizontal or vertical line, that'll do */;
+ else
+return( false );
+ } else {
+ if ( sp->nextcp.x != sp->me.x && sp->nextcp.y != sp->me.y )
+return( false );
+ }
+ if ( sp->noprevcp ) {
+ if ( !sp->prev->knownlinear )
+return( false );
+ if ( sp->prev->from->me.x == sp->me.x || sp->prev->from->me.y == sp->me.y )
+ /* Ok, horizontal or vertical line, that'll do */;
+ else
+return( false );
+ } else {
+ if ( sp->prevcp.x != sp->me.x && sp->prevcp.y != sp->me.y )
+return( false );
+ }
+return( true );
+}
+
+/* If the start point of a contour is not at an extremum, and the contour has */
+/* a point which is at an extremum, then make the start point be that point */
+/* leave it unchanged if start point is already extreme, or no extreme point */
+/* could be found */
+static void SPLStartToExtremum(SplineChar *sc,SplinePointList *spl) {
+ SplinePoint *sp;
+
+ while ( spl!=NULL ) {
+ if ( spl->first==spl->last ) { /* It's closed */
+ for ( sp=spl->first; !isExtreme(sp); ) {
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ if ( sp!=spl->first )
+ spl->first = spl->last = sp;
+ }
+ spl = spl->next;
+ }
+}
+
+/* Cleanup just turns splines with control points which happen to trace out */
+/* lines into simple lines */
+/* it also checks for really nasty control points which point in the wrong */
+/* direction but are very close to the base point. We get these from some */
+/* TeX fonts. I assume they are due to rounding errors (or just errors) in*/
+/* some autotracer */
+void SplinePointListSimplify(SplineChar *sc,SplinePointList *spl,
+ struct simplifyinfo *smpl) {
+ SplinePoint *first, *next, *sp, *nsp;
+ BasePoint suv, nuv;
+ double lenmax2 = smpl->linelenmax*smpl->linelenmax;
+
+ if ( spl==NULL )
+return;
+
+ RemoveZeroLengthSplines(spl,false,0.1);
+ RemoveStupidControlPoints(spl);
+ SSRemoveBacktracks(spl);
+ if ( smpl->flags!=sf_cleanup && (smpl->flags&sf_setstart2extremum))
+ SPLStartToExtremum(sc,spl);
+ if ( spl->first->next!=NULL && spl->first->next->to==spl->first &&
+ spl->first->nonextcp && spl->first->noprevcp )
+return; /* Ignore any splines which are just dots */
+
+ if ( smpl->flags!=sf_cleanup && (smpl->flags&sf_forcelines)) {
+ SPLNearlyHvLines(sc,spl,smpl->linefixup);
+ SPLForceLines(sc,spl,smpl->linefixup);
+ }
+
+ if ( smpl->flags!=sf_cleanup && spl->first->prev!=NULL && spl->first->prev!=spl->first->next ) {
+ /* first thing to try is to remove everything between two extrema */
+ /* We do this even if they checked ignore extrema. After this pass */
+ /* we'll come back and check every point individually */
+ /* However, if we turn through more than 90 degrees we can't approximate */
+ /* a good match, and it takes us forever to make the attempt and fail*/
+ /* We take a dot product to prevent that */
+ for ( sp = spl->first; ; ) {
+ if ( sp->next==NULL )
+ break;
+ if ( SPisExtremum(sp) ) {
+ GetNextUnitVector(sp,&suv);
+ for ( nsp=sp->next->to; nsp!=sp; nsp = nsp->next->to ) {
+ if ( nsp->next==NULL )
+ break;
+ if ( nsp->prev->knownlinear &&
+ (nsp->me.x-nsp->prev->from->me.x)*(nsp->me.x-nsp->prev->from->me.x) +
+ (nsp->me.y-nsp->prev->from->me.y)*(nsp->me.y-nsp->prev->from->me.y)
+ >= lenmax2 )
+ goto nogood;
+ GetNextUnitVector(nsp,&nuv);
+ if ( suv.x*nuv.x + suv.y*nuv.y < 0 ) {
+ if ( suv.x*nuv.x + suv.y*nuv.y > -.1 )
+ break;
+ goto nogood;
+ }
+ if ( SPisExtremum(nsp) || nsp==spl->first)
+ break;
+ }
+ /* nsp is something we don't want to remove */
+ if ( nsp==sp )
+ break;
+ else if ( sp->next->to == nsp )
+ goto nogood; /* Nothing to remove */
+ if ( SplinesRemoveBetweenMaybe(sc,sp,nsp,smpl->flags,smpl->err)) {
+ if ( spl->last==spl->first )
+ spl->last = spl->first = sp; /* We know this point didn't get removed */
+ }
+ nogood:
+ sp = nsp;
+ } else
+ sp = sp->next->to;
+ if ( sp == spl->first )
+ break;
+ }
+
+ while ( 1 ) {
+ first = spl->first->prev->from;
+ if ( first->prev == first->next )
+return;
+ if ( !SplinesRemoveMidMaybe(sc,spl->first,smpl->flags,smpl->err,lenmax2))
+ break;
+ if ( spl->first==spl->last )
+ spl->last = first;
+ spl->first = first;
+ }
+ }
+
+ /* Special case checks for paths containing only one point */
+ /* else we get lots of nans (or only two points) */
+ if ( spl->first->next == NULL )
+return;
+ for ( sp = spl->first->next->to; sp->next!=NULL; sp = next ) {
+ SplineIsLinearMake(sp->prev); /* First see if we can turn it*/
+ /* into a line, then try to merge two splines */
+ next = sp->next->to;
+ if ( sp->prev == sp->next ||
+ (sp->next!=NULL && sp->next->to->next!=NULL &&
+ sp->next->to->next->to == sp ))
+return;
+ if ( smpl->flags!=sf_cleanup ) {
+ if ( SplinesRemoveMidMaybe(sc,sp,smpl->flags,smpl->err,lenmax2) ) {
+ if ( spl->first==sp )
+ spl->first = next;
+ if ( spl->last==sp )
+ spl->last = next;
+ }
+ } else {
+ while ( sp->me.x==next->me.x && sp->me.y==next->me.y &&
+ sp->nextcp.x>sp->me.x-1 && sp->nextcp.x<sp->me.x+1 &&
+ sp->nextcp.y>sp->me.y-1 && sp->nextcp.y<sp->me.y+1 &&
+ next->prevcp.x>next->me.x-1 && next->prevcp.x<next->me.x+1 &&
+ next->prevcp.y>next->me.y-1 && next->prevcp.y<next->me.y+1 ) {
+ SplineFree(sp->next);
+ sp->next = next->next;
+ if ( sp->next!=NULL )
+ sp->next->from = sp;
+ sp->nextcp = next->nextcp;
+ sp->nonextcp = next->nonextcp;
+ sp->nextcpdef = next->nextcpdef;
+ SplinePointMDFree(sc,next);
+ if ( sp->next!=NULL )
+ next = sp->next->to;
+ else {
+ next = NULL;
+ break;
+ }
+ }
+ if ( next==NULL )
+ break;
+ }
+ if ( next->prev!=NULL && next->prev->from==spl->last )
+ break;
+ }
+ if ( smpl->flags!=sf_cleanup && (smpl->flags&sf_smoothcurves))
+ SPLSmoothControlPoints(spl,smpl->tan_bounds,smpl->flags&sf_choosehv);
+}
+
+/* cleanup may be: -1 => lines become lines, 0 => simplify & retain slopes, 1=> simplify and discard slopes, 2=>discard extrema */
+SplineSet *SplineCharSimplify(SplineChar *sc,SplineSet *head,
+ struct simplifyinfo *smpl) {
+ SplineSet *spl, *prev, *snext;
+ int anysel=0, wassingleton;
+
+ if ( smpl->check_selected_contours ) {
+ for ( spl = head; spl!=NULL && !anysel; spl = spl->next ) {
+ anysel = PointListIsSelected(spl);
+ }
+ }
+
+ prev = NULL;
+ for ( spl = head; spl!=NULL; spl = snext ) {
+ snext = spl->next;
+ if ( !anysel || PointListIsSelected(spl)) {
+ wassingleton = spl->first->prev==spl->first->next &&
+ (spl->first->prev==NULL ||
+ (spl->first->noprevcp && spl->first->nonextcp));
+ SplinePointListSimplify(sc,spl,smpl);
+ /* remove any singleton points */
+ if (( !wassingleton ||
+ (smpl->flags!=sf_cleanup && (smpl->flags&sf_rmsingletonpoints))) &&
+ spl->first->prev==spl->first->next &&
+ (spl->first->prev==NULL ||
+ (spl->first->noprevcp && spl->first->nonextcp))) {
+ if ( prev==NULL )
+ head = snext;
+ else
+ prev->next = snext;
+ spl->next = NULL;
+ SplinePointListMDFree(sc,spl);
+ } else
+ prev = spl;
+ }
+ }
+ SplineSetsRemoveAnnoyingExtrema(head,.3);
+ SPLCatagorizePoints(head);
+#if 0
+ printf( "nocnt=%d totcnt=%d curdif=%d incr=%d\n", nocnt_cnt, totcnt_cnt, curdiff_cnt, incr_cnt );
+#endif
+return( head );
+}
+
+#ifndef LUA_FF_LIB
+/* If the start point of a contour to be the left most point on it. If there */
+/* are several points with that same value, use the one closest to the base */
+/* line */
+void SPLStartToLeftmost(SplineChar *sc,SplinePointList *spl, int *changed) {
+ SplinePoint *sp;
+ SplinePoint *best;
+
+ if ( spl->first==spl->last ) { /* It's closed */
+ best = spl->first;
+ for ( sp=spl->first; ; ) {
+ if ( sp->me.x < best->me.x ||
+ (sp->me.x==best->me.x && (fabs(sp->me.y)<fabs(best->me.y))) )
+ best = sp;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ if ( best!=spl->first ) {
+ if ( !*changed ) {
+ SCPreserveState(sc,false);
+ *changed = true;
+ }
+ spl->first = spl->last = best;
+ }
+ }
+}
+
+void SPLsStartToLeftmost(SplineChar *sc) {
+ int changed = 0;
+ int layer;
+ SplineSet *ss;
+
+ if ( sc==NULL )
+return;
+
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ for ( ss = sc->layers[layer].splines; ss!=NULL; ss=ss->next )
+ SPLStartToLeftmost(sc,ss,&changed);
+ }
+ if ( changed )
+ SCCharChangedUpdate(sc);
+}
+
+struct contourinfo {
+ SplineSet *ss;
+ BasePoint *min;
+};
+
+static int order_contours(const void *_c1, const void *_c2) {
+ const struct contourinfo *c1 = _c1, *c2 = _c2;
+
+ if ( c1->min->x<c2->min->x )
+return( -1 );
+ else if ( c1->min->x>c2->min->x )
+return( 1 );
+ else if ( fabs(c1->min->y)<fabs(c2->min->y) )
+return( -1 );
+ else if ( fabs(c1->min->y)>fabs(c2->min->y) )
+return( 1 );
+ else
+return( 0 );
+}
+
+void CanonicalContours(SplineChar *sc) {
+ int changed;
+ int layer;
+ SplineSet *ss;
+ SplinePoint *sp, *best;
+ int contour_cnt, contour_max=0, i, diff;
+ struct contourinfo *ci;
+
+ if ( sc==NULL )
+return;
+
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ contour_cnt = 0;
+ for ( ss = sc->layers[layer].splines; ss!=NULL; ss=ss->next )
+ ++contour_cnt;
+ if ( contour_cnt>contour_max )
+ contour_max = contour_cnt;
+ }
+
+ if ( contour_max<=1 ) /* Can't be out of order */
+return;
+
+ changed = 0;
+ ci = gcalloc(contour_max,sizeof(struct contourinfo));
+ for ( layer=ly_fore; layer<sc->layer_cnt; ++layer ) {
+ contour_cnt = 0;
+ for ( ss = sc->layers[layer].splines; ss!=NULL; ss=ss->next ) {
+ best = ss->first;
+ for ( sp=ss->first; ; ) {
+ if ( sp->me.x < best->me.x ||
+ (sp->me.x==best->me.x && (fabs(sp->me.y)<fabs(best->me.y))) )
+ best = sp;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ ci[contour_cnt].ss = ss;
+ ci[contour_cnt++].min = &best->me;
+ }
+ qsort(ci,contour_cnt,sizeof(struct contourinfo),order_contours);
+ diff = 0;
+ for ( i=0, ss = sc->layers[layer].splines; ss!=NULL; ss=ss->next ) {
+ if ( ci[i].ss != ss ) {
+ diff = true;
+ break;
+ }
+ }
+ if ( diff && !changed ) {
+ SCPreserveState(sc,false);
+ changed = true;
+ }
+ if ( diff ) {
+ sc->layers[layer].splines = ci[0].ss;
+ for ( i=1; i<contour_cnt; ++i )
+ ci[i-1].ss->next = ci[i].ss;
+ ci[contour_cnt-1].ss->next = NULL;
+ }
+ }
+ free(ci);
+ if ( changed )
+ SCCharChangedUpdate(sc);
+}
+#endif
+
+static int SplineSetMakeLoop(SplineSet *spl,real fudge) {
+ if ( spl->first!=spl->last &&
+ (spl->first->me.x >= spl->last->me.x-fudge &&
+ spl->first->me.x <= spl->last->me.x+fudge &&
+ spl->first->me.y >= spl->last->me.y-fudge &&
+ spl->first->me.y <= spl->last->me.y+fudge )) {
+ spl->first->prev = spl->last->prev;
+ spl->first->prev->to = spl->first;
+ spl->first->prevcp = spl->last->prevcp;
+ spl->first->noprevcp = spl->last->noprevcp;
+ spl->first->prevcpdef = spl->last->prevcpdef;
+ SplinePointFree(spl->last);
+ spl->last = spl->first;
+return( true );
+ }
+return( false );
+}
+
+SplineSet *SplineSetJoin(SplineSet *start,int doall,real fudge,int *changed) {
+ SplineSet *spl, *spl2, *prev;
+
+ *changed = false;
+ for ( spl=start; spl!=NULL; spl=spl->next ) {
+ if ( spl->first->prev==NULL &&
+ (doall || PointListIsSelected(spl)) ) {
+ if ( SplineSetMakeLoop(spl,fudge) ) {
+ *changed = true;
+ } else {
+ prev = NULL;
+ for ( spl2=start ; spl2!=NULL; prev = spl2, spl2=spl2->next ) if ( spl2!=spl ) {
+ if (!( spl->first->me.x >= spl2->last->me.x-fudge &&
+ spl->first->me.x <= spl2->last->me.x+fudge &&
+ spl->first->me.y >= spl2->last->me.y-fudge &&
+ spl->first->me.y <= spl2->last->me.y+fudge )) {
+ if (( spl->last->me.x >= spl2->last->me.x-fudge &&
+ spl->last->me.x <= spl2->last->me.x+fudge &&
+ spl->last->me.y >= spl2->last->me.y-fudge &&
+ spl->last->me.y <= spl2->last->me.y+fudge ) ||
+ ( spl->last->me.x >= spl2->first->me.x-fudge &&
+ spl->last->me.x <= spl2->first->me.x+fudge &&
+ spl->last->me.y >= spl2->first->me.y-fudge &&
+ spl->last->me.y <= spl2->first->me.y+fudge ))
+ SplineSetReverse(spl);
+ }
+ if ( spl->first->me.x >= spl2->first->me.x-fudge &&
+ spl->first->me.x <= spl2->first->me.x+fudge &&
+ spl->first->me.y >= spl2->first->me.y-fudge &&
+ spl->first->me.y <= spl2->first->me.y+fudge )
+ SplineSetReverse(spl2);
+ if ( spl->first->me.x >= spl2->last->me.x-fudge &&
+ spl->first->me.x <= spl2->last->me.x+fudge &&
+ spl->first->me.y >= spl2->last->me.y-fudge &&
+ spl->first->me.y <= spl2->last->me.y+fudge ) {
+ spl->first->prev = spl2->last->prev;
+ spl->first->prev->to = spl->first;
+ spl->first->prevcp = spl2->last->prevcp;
+ spl->first->noprevcp = spl2->last->noprevcp;
+ spl->first->prevcpdef = spl2->last->prevcpdef;
+ SplinePointFree(spl2->last);
+ spl->first = spl2->first;
+ spl2->first = spl2->last = NULL;
+ if ( prev!=NULL )
+ prev->next = spl2->next;
+ else
+ start = spl2->next;
+ chunkfree(spl2,sizeof(SplineSet));
+ SplineSetMakeLoop(spl,fudge);
+ *changed = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+return(start);
+}
+
+#ifndef LUA_FF_LIB
+SplineSet *SplineCharRemoveTiny(SplineChar *sc,SplineSet *head) {
+ SplineSet *spl, *snext, *pr;
+ Spline *spline, *next, *first;
+ const double err = 1.0/64.0;
+
+ for ( spl = head, pr=NULL; spl!=NULL; spl = snext ) {
+ first = NULL;
+ for ( spline=spl->first->next; spline!=NULL && spline!=first; spline=next ) {
+ next = spline->to->next;
+ if ( spline->from->me.x-spline->to->me.x>-err && spline->from->me.x-spline->to->me.x<err &&
+ spline->from->me.y-spline->to->me.y>-err && spline->from->me.y-spline->to->me.y<err &&
+ (spline->from->nonextcp || spline->to->noprevcp) &&
+ spline->from->prev!=NULL ) {
+ if ( spline->from==spline->to )
+ break;
+ if ( spl->last==spline->from ) spl->last = NULL;
+ if ( spl->first==spline->from ) spl->first = NULL;
+ if ( first==spline->from->prev ) first=NULL;
+ /*SplinesRemoveBetween(sc,spline->from->prev->from,spline->to);*/
+ spline->to->prevcp = spline->from->prevcp;
+ spline->to->noprevcp = spline->from->noprevcp;
+ spline->to->prevcpdef = spline->from->prevcpdef;
+ spline->from->prev->to = spline->to;
+ spline->to->prev = spline->from->prev;
+ SplineRefigure(spline->from->prev);
+ SplinePointFree(spline->from);
+ SplineFree(spline);
+ if ( first==NULL ) first = next->from->prev;
+ if ( spl->first==NULL ) spl->first = next->from;
+ if ( spl->last==NULL ) spl->last = next->from;
+ } else {
+ if ( first==NULL ) first = spline;
+ }
+ }
+ snext = spl->next;
+ if ( spl->first->next==spl->first->prev ) {
+ spl->next = NULL;
+ SplinePointListMDFree(sc,spl);
+ if ( pr==NULL )
+ head = snext;
+ else
+ pr->next = snext;
+ } else
+ pr = spl;
+ }
+return( head );
+}
+#endif
+
+#if 0
+Spline *SplineAddPointsOfInflection(Spline *s) {
+ double ts[2];
+ int cnt;
+ SplinePoint *sp;
+
+ forever {
+ if ( s->knownlinear )
+return( s );
+ cnt = Spline2DFindPointsOfInflection(s,ts);
+ if ( cnt==0 )
+return( s );
+ if ( cnt==2 && ts[0]>ts[1] )
+ ts[0] = ts[1];
+ sp = SplineBisect(s,ts[0]);
+ s = sp->next;
+ if ( cnt==1 )
+return( s );
+ /* As with add extrema, if we had more than one, loop back to look */
+ /* at any others. The spline is different now, easier to compute the */
+ /* new value than to fix up the old */
+ }
+}
+
+void SplineSetAddPointsOfInflection(SplineChar *sc, SplineSet *ss) {
+ Spline *s, *first;
+
+ first = NULL;
+ for ( s = ss->first->next; s!=NULL && s!=first; s = s->to->next ) {
+ s = SplineAddPointsOfInflection(s);
+ if ( first==NULL ) first = s;
+ }
+}
+
+void SplineCharAddPointsOfInflection(SplineChar *sc, SplineSet *head) {
+ SplineSet *ss;
+
+ for ( ss=head; ss!=NULL; ss=ss->next ) {
+ SplineSetAddPointsOfInflection(sc,ss,between_selected,sf);
+ }
+}
+#endif
+
+Spline *SplineAddExtrema(Spline *s,int always,real lenbound, real offsetbound,
+ DBounds *b) {
+ /* First find the extrema, if any */
+ bigreal t[4], min;
+ uint8 rmfrom[4], rmto[4];
+ int p, i,j, p_s, mini;
+ SplinePoint *sp;
+ real len = 0;
+
+ if ( !always ) {
+ real xlen, ylen;
+ xlen = (s->from->me.x-s->to->me.x);
+ ylen = (s->from->me.y-s->to->me.y);
+ len = xlen*xlen + ylen*ylen;
+ lenbound *= lenbound;
+ if ( len < lenbound ) {
+ len = SplineLength(s);
+ len *= len;
+ }
+ }
+
+ memset(rmfrom,0,sizeof(rmfrom));
+ memset(rmto,0,sizeof(rmto));
+
+ forever {
+ if ( s->knownlinear )
+return(s);
+ p = 0;
+ if ( s->splines[0].a!=0 ) {
+ double d = 4*s->splines[0].b*s->splines[0].b-4*3*s->splines[0].a*s->splines[0].c;
+ if ( d>0 ) {
+ d = sqrt(d);
+ t[p++] = CheckExtremaForSingleBitErrors(&s->splines[0],(-2*s->splines[0].b+d)/(2*3*s->splines[0].a));
+ t[p++] = CheckExtremaForSingleBitErrors(&s->splines[0],(-2*s->splines[0].b-d)/(2*3*s->splines[0].a));
+ }
+ } else if ( s->splines[0].b!=0 )
+ t[p++] = -s->splines[0].c/(2*s->splines[0].b);
+ if ( !always ) {
+ /* Generally we are only interested in extrema on long splines, or */
+ /* extrema which are extrema for the entire contour, not just this */
+ /* spline */
+ /* Also extrema which are very close to one of the end-points can */
+ /* be ignored. */
+ /* No they can't. But we need to remove the original point in this*/
+ /* case */
+ for ( i=0; i<p; ++i ) {
+ real x = ((s->splines[0].a*t[i]+s->splines[0].b)*t[i]+s->splines[0].c)*t[i]+s->splines[0].d;
+ real y = ((s->splines[1].a*t[i]+s->splines[1].b)*t[i]+s->splines[1].c)*t[i]+s->splines[1].d;
+ int close_from = ( x-s->from->me.x<offsetbound && x-s->from->me.x>-offsetbound) &&
+ ( y-s->from->me.y<10*offsetbound && y-s->from->me.y>-10*offsetbound );
+ int close_to = ( x-s->to->me.x<offsetbound && x-s->to->me.x>-offsetbound) &&
+ ( y-s->to->me.y<10*offsetbound && y-s->to->me.y>-10*offsetbound );
+ int remove_from = close_from && GoodCurve(s->from,true);
+ int remove_to = close_to && GoodCurve(s->to,false);
+ if (( x>b->minx && x<b->maxx && len<lenbound ) ||
+ (close_from && !remove_from) || (close_to && !remove_to) ) {
+ --p;
+ for ( j=i; j<p; ++j )
+ t[j] = t[j+1];
+ --i;
+ } else {
+ rmfrom[i] = remove_from;
+ rmto[i] = remove_to;
+ }
+ }
+ }
+
+ p_s = p;
+ if ( s->splines[1].a!=0 ) {
+ double d = 4*s->splines[1].b*s->splines[1].b-4*3*s->splines[1].a*s->splines[1].c;
+ if ( d>0 ) {
+ d = sqrt(d);
+ t[p++] = CheckExtremaForSingleBitErrors(&s->splines[1],(-2*s->splines[1].b+d)/(2*3*s->splines[1].a));
+ t[p++] = CheckExtremaForSingleBitErrors(&s->splines[1],(-2*s->splines[1].b-d)/(2*3*s->splines[1].a));
+ }
+ } else if ( s->splines[1].b!=0 )
+ t[p++] = -s->splines[1].c/(2*s->splines[1].b);
+ if ( !always ) {
+ for ( i=p_s; i<p; ++i ) {
+ real x = ((s->splines[0].a*t[i]+s->splines[0].b)*t[i]+s->splines[0].c)*t[i]+s->splines[0].d;
+ real y = ((s->splines[1].a*t[i]+s->splines[1].b)*t[i]+s->splines[1].c)*t[i]+s->splines[1].d;
+ int close_from =( y-s->from->me.y<offsetbound && y-s->from->me.y>-offsetbound ) &&
+ ( x-s->from->me.x<offsetbound && x-s->from->me.x>-offsetbound);
+ int close_to = ( y-s->to->me.y<offsetbound && y-s->to->me.y>-offsetbound ) &&
+ ( x-s->to->me.x<offsetbound && x-s->to->me.x>-offsetbound);
+ int remove_from = close_from && GoodCurve(s->from,true);
+ int remove_to = close_to && GoodCurve(s->to,false);
+ if (( y>b->miny && y<b->maxy && len<lenbound ) ||
+ (close_from && !remove_from) || (close_to && !remove_to) ) {
+ --p;
+ for ( j=i; j<p; ++j )
+ t[j] = t[j+1];
+ --i;
+ } else {
+ rmfrom[i] = remove_from;
+ rmto[i] = remove_to;
+ }
+ }
+ }
+
+ /* Throw out any t values which are not between 0 and 1 */
+ /* (we do a little fudging near the endpoints so we don't get confused */
+ /* by rounding errors) */
+ for ( i=0; i<p; ++i ) {
+ if ( t[i]>0 && t[i]<.05 ) {
+ BasePoint test;
+ /* Expand strong gets very confused on zero-length splines so */
+ /* don't let that happen */
+ test.x = ((s->splines[0].a*t[i]+s->splines[0].b)*t[i]+s->splines[0].c)*t[i]+s->splines[0].d;
+ test.y = ((s->splines[1].a*t[i]+s->splines[1].b)*t[i]+s->splines[1].c)*t[i]+s->splines[1].d;
+ if ( test.x== s->from->me.x && test.y==s->from->me.y )
+ t[i] = 0; /* Throw it out */
+ }
+ if ( t[i]<1 && t[i]>.95 ) {
+ BasePoint test;
+ test.x = ((s->splines[0].a*t[i]+s->splines[0].b)*t[i]+s->splines[0].c)*t[i]+s->splines[0].d;
+ test.y = ((s->splines[1].a*t[i]+s->splines[1].b)*t[i]+s->splines[1].c)*t[i]+s->splines[1].d;
+ if ( test.x== s->to->me.x && test.y==s->to->me.y )
+ t[i] = 1.0; /* Throw it out */
+ }
+
+ if ( t[i]<.0001 || t[i]>.9999 ) {
+ --p;
+ for ( j=i; j<p; ++j ) {
+ t[j] = t[j+1];
+ rmfrom[j] = rmfrom[j+1];
+ rmto[j] = rmto[j+1];
+ }
+ --i;
+ }
+ }
+
+ if ( p==0 )
+return(s);
+
+ /* Find the smallest of all the interesting points */
+ min = t[0]; mini = 0;
+ for ( i=1; i<p; ++i ) {
+ if ( t[i]<min ) {
+ min=t[i];
+ mini = i;
+ }
+ }
+ sp = SplineBisect(s,min);
+/* On the mac we get rounding errors in the bisect routine */
+ { double dx, dy;
+ if ( (dx = sp->me.x - sp->prevcp.x)<0 ) dx=-dx;
+ if ( (dy = sp->me.y - sp->prevcp.y)<0 ) dy=-dy;
+ if ( dx!=0 && dy!=0 ) {
+ if ( dx<dy )
+ sp->prevcp.x = sp->me.x;
+ else
+ sp->prevcp.y = sp->me.y;
+ }
+ if ( (dx = sp->me.x - sp->nextcp.x)<0 ) dx=-dx;
+ if ( (dy = sp->me.y - sp->nextcp.y)<0 ) dy=-dy;
+ if ( dx!=0 && dy!=0 ) {
+ if ( dx<dy )
+ sp->nextcp.x = sp->me.x;
+ else
+ sp->nextcp.y = sp->me.y;
+ }
+ }
+
+ if ( rmfrom[mini] ) sp->prev->from->ticked = true;
+ if ( rmto[mini] ) sp->next->to->ticked = true;
+ s = sp->next;
+ if ( p==1 )
+return( s );
+ /* Don't try to use any other computed t values, it is easier to */
+ /* recompute them than to try and figure out what they map to on the */
+ /* new spline */
+ }
+}
+
+void SplineSetAddExtrema(SplineChar *sc, SplineSet *ss,enum ae_type between_selected, int emsize) {
+ Spline *s, *first;
+ DBounds b;
+ int always = true;
+ real lenbound = 0;
+ real offsetbound=0;
+ SplinePoint *sp, *nextp;
+
+ if ( between_selected==ae_only_good ) {
+ SplineSetQuickBounds(ss,&b);
+ lenbound = (emsize)/32.0;
+ always = false;
+ offsetbound = .5;
+ between_selected = ae_only_good_rm_later;
+ for ( sp = ss->first; ; ) {
+ sp->ticked = false;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ }
+
+ first = NULL;
+ for ( s = ss->first->next; s!=NULL && s!=first; s = s->to->next ) {
+ if ( between_selected!=ae_between_selected ||
+ (s->from->selected && s->to->selected))
+ s = SplineAddExtrema(s,always,lenbound,offsetbound,&b);
+ if ( first==NULL ) first = s;
+ }
+ if ( between_selected == ae_only_good_rm_later ) {
+ for ( sp = ss->first; ; ) {
+ if ( sp->next==NULL )
+ break;
+ nextp = sp->next->to;
+ if ( sp->ticked ) {
+ if ( sp==ss->first )
+ ss->first = ss->last = nextp;
+ SplinesRemoveBetween(sc,sp->prev->from,nextp,1);
+ }
+ sp = nextp;
+ if ( sp==ss->first )
+ break;
+ }
+ }
+}
+
+void SplineCharAddExtrema(SplineChar *sc, SplineSet *head,enum ae_type between_selected,int emsize) {
+ SplineSet *ss;
+
+ for ( ss=head; ss!=NULL; ss=ss->next ) {
+ SplineSetAddExtrema(sc,ss,between_selected,emsize);
+ }
+}
+
+char *GetNextUntitledName(void) {
+ static int untitled_cnt=1;
+ char buffer[80];
+
+ sprintf( buffer, "Untitled%d", untitled_cnt++ );
+return( copy(buffer));
+}
+
+SplineFont *SplineFontEmpty(void) {
+ extern int default_fv_row_count, default_fv_col_count;
+ time_t now;
+ SplineFont *sf;
+
+ sf = gcalloc(1,sizeof(SplineFont));
+ sf->pfminfo.fstype = -1;
+ sf->top_enc = -1;
+ sf->macstyle = -1;
+ sf->desired_row_cnt = default_fv_row_count; sf->desired_col_cnt = default_fv_col_count;
+ sf->display_antialias = default_fv_antialias;
+ sf->display_bbsized = default_fv_bbsized;
+ sf->display_size = -default_fv_font_size;
+ sf->pfminfo.winascent_add = sf->pfminfo.windescent_add = true;
+ sf->pfminfo.hheadascent_add = sf->pfminfo.hheaddescent_add = true;
+ sf->pfminfo.typoascent_add = sf->pfminfo.typodescent_add = true;
+ if ( TTFFoundry!=NULL )
+ strncpy(sf->pfminfo.os2_vendor,TTFFoundry,4);
+ else
+ memcpy(sf->pfminfo.os2_vendor,"PfEd",4);
+ sf->for_new_glyphs = DefaultNameListForNewFonts();
+ time(&now);
+ sf->creationtime = sf->modificationtime = now;
+return( sf );
+}
+
+SplineFont *SplineFontBlank(int charcnt) {
+ SplineFont *sf;
+ char buffer[200];
+ time_t now;
+ struct tm *tm;
+ const char *author = GetAuthor();
+
+ sf = SplineFontEmpty();
+ sf->fontname = GetNextUntitledName();
+ sf->fullname = copy(sf->fontname);
+ sf->familyname = copy(sf->fontname);
+ sprintf( buffer, "%s.sfd", sf->fontname);
+ sf->origname = copy(buffer);
+ sf->weight = copy("Medium");
+ if ( author!=NULL )
+ sprintf( buffer, "Created by %.50s with FontForge 2.0 (http://fontforge.sf.net)", author );
+ else
+ strcpy( buffer, "Created with FontForge 2.0 (http://fontforge.sf.net)" );
+ sf->copyright = copy(buffer);
+ if ( xuid!=NULL ) {
+ sf->xuid = galloc(strlen(xuid)+20);
+ sprintf(sf->xuid,"[%s %d]", xuid, (rand()&0xffffff));
+ }
+ time(&now);
+ tm = localtime(&now);
+ sprintf( buffer, "%d-%d-%d: Created.", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday );
+ sf->comments = copy(buffer);
+ sf->version = copy("001.000");
+ sf->ascent = rint(new_em_size*.8); sf->descent = new_em_size-sf->ascent;
+ sf->upos = -rint(new_em_size*.1); sf->uwidth = rint(new_em_size*.05); /* defaults for cff */
+ sf->glyphcnt = 0;
+ sf->glyphmax = charcnt;
+ sf->glyphs = gcalloc(charcnt,sizeof(SplineChar *));
+ sf->pfminfo.fstype = -1;
+ sf->order2 = false;
+ sf->use_typo_metrics = true;
+return( sf );
+}
+
+SplineFont *SplineFontNew(void) {
+ SplineFont *sf;
+ int enclen = default_encoding->char_cnt;
+
+ sf = SplineFontBlank(enclen);
+ sf->onlybitmaps = true;
+ sf->new = true;
+ sf->order2 = new_fonts_are_order2;
+
+ sf->map = EncMapNew(enclen,enclen,default_encoding);
+#ifdef LUA_FF_LIB
+ sf->next = NULL;
+#endif
+return( sf );
+}
+
+static void SFChangeXUID(SplineFont *sf, int random) {
+ char *pt, *new, *npt;
+ int val;
+
+ if ( sf->xuid==NULL )
+return;
+ pt = strrchr(sf->xuid,' ');
+ if ( pt==NULL )
+ pt = strchr(sf->xuid,'[');
+ if ( pt==NULL )
+ pt = sf->xuid;
+ else
+ ++pt;
+ if ( random )
+ val = rand()&0xffffff;
+ else {
+ val = strtol(pt,NULL,10);
+ val = (val+1)&0xffffff;
+ }
+
+ new = galloc(pt-sf->xuid+12);
+ strncpy(new,sf->xuid,pt-sf->xuid);
+ npt = new + (pt-sf->xuid);
+ if ( npt==new ) *npt++ = '[';
+ sprintf(npt, "%d]", val );
+ free(sf->xuid); sf->xuid = new;
+ sf->changed = true;
+ sf->changed_since_xuidchanged = false;
+}
+
+void SFIncrementXUID(SplineFont *sf) {
+ SFChangeXUID(sf,false);
+}
+
+void SFRandomChangeXUID(SplineFont *sf) {
+ SFChangeXUID(sf,true);
+}
+
+void SPWeightedAverageCps(SplinePoint *sp) {
+ double pangle, nangle, angle, plen, nlen, c, s;
+ if ( sp->noprevcp || sp->nonextcp )
+ /*SPAverageCps(sp)*/; /* Expand Stroke wants this case to hold still */
+ else if ( sp->pointtype==pt_curve && sp->prev && sp->next ) {
+ pangle = atan2(sp->me.y-sp->prevcp.y,sp->me.x-sp->prevcp.x);
+ nangle = atan2(sp->nextcp.y-sp->me.y,sp->nextcp.x-sp->me.x);
+ if ( pangle<0 && nangle>0 && nangle-pangle>=3.1415926 )
+ pangle += 2*3.1415926535897932;
+ else if ( pangle>0 && nangle<0 && pangle-nangle>=3.1415926 )
+ nangle += 2*3.1415926535897932;
+ plen = sqrt((sp->me.y-sp->prevcp.y)*(sp->me.y-sp->prevcp.y) +
+ (sp->me.x-sp->prevcp.x)*(sp->me.x-sp->prevcp.x));
+ nlen = sqrt((sp->nextcp.y-sp->me.y)*(sp->nextcp.y-sp->me.y) +
+ (sp->nextcp.x-sp->me.x)*(sp->nextcp.x-sp->me.x));
+ if ( plen+nlen==0 )
+ angle = (nangle+pangle)/2;
+ else
+ angle = (plen*pangle + nlen*nangle)/(plen+nlen);
+ plen = -plen;
+ c = cos(angle); s=sin(angle);
+ sp->nextcp.x = c*nlen + sp->me.x;
+ sp->nextcp.y = s*nlen + sp->me.y;
+ sp->prevcp.x = c*plen + sp->me.x;
+ sp->prevcp.y = s*plen + sp->me.y;
+ SplineRefigure(sp->prev);
+ SplineRefigure(sp->next);
+ } else
+ SPAverageCps(sp);
+}
+
+void SPAverageCps(SplinePoint *sp) {
+ double pangle, nangle, angle, plen, nlen, c, s;
+ if ( sp->pointtype==pt_curve && sp->prev && sp->next ) {
+ if ( sp->noprevcp )
+ pangle = atan2(sp->me.y-sp->prev->from->me.y,sp->me.x-sp->prev->from->me.x);
+ else
+ pangle = atan2(sp->me.y-sp->prevcp.y,sp->me.x-sp->prevcp.x);
+ if ( sp->nonextcp )
+ nangle = atan2(sp->next->to->me.y-sp->me.y,sp->next->to->me.x-sp->me.x);
+ else
+ nangle = atan2(sp->nextcp.y-sp->me.y,sp->nextcp.x-sp->me.x);
+ if ( pangle<0 && nangle>0 && nangle-pangle>=3.1415926 )
+ pangle += 2*3.1415926535897932;
+ else if ( pangle>0 && nangle<0 && pangle-nangle>=3.1415926 )
+ nangle += 2*3.1415926535897932;
+ angle = (nangle+pangle)/2;
+ plen = -sqrt((sp->me.y-sp->prevcp.y)*(sp->me.y-sp->prevcp.y) +
+ (sp->me.x-sp->prevcp.x)*(sp->me.x-sp->prevcp.x));
+ nlen = sqrt((sp->nextcp.y-sp->me.y)*(sp->nextcp.y-sp->me.y) +
+ (sp->nextcp.x-sp->me.x)*(sp->nextcp.x-sp->me.x));
+ c = cos(angle); s=sin(angle);
+ sp->nextcp.x = c*nlen + sp->me.x;
+ sp->nextcp.y = s*nlen + sp->me.y;
+ sp->prevcp.x = c*plen + sp->me.x;
+ sp->prevcp.y = s*plen + sp->me.y;
+ SplineRefigure(sp->prev);
+ SplineRefigure(sp->next);
+ } else if ( sp->pointtype==pt_tangent && sp->prev && sp->next ) {
+ if ( !sp->noprevcp ) {
+ nangle = atan2(sp->next->to->me.y-sp->me.y,sp->next->to->me.x-sp->me.x);
+ plen = -sqrt((sp->me.y-sp->prevcp.y)*(sp->me.y-sp->prevcp.y) +
+ (sp->me.x-sp->prevcp.x)*(sp->me.x-sp->prevcp.x));
+ c = cos(nangle); s=sin(nangle);
+ sp->prevcp.x = c*plen + sp->me.x;
+ sp->prevcp.y = s*plen + sp->me.y;
+ SplineRefigure(sp->prev);
+ }
+ if ( !sp->nonextcp ) {
+ pangle = atan2(sp->me.y-sp->prev->from->me.y,sp->me.x-sp->prev->from->me.x);
+ nlen = sqrt((sp->nextcp.y-sp->me.y)*(sp->nextcp.y-sp->me.y) +
+ (sp->nextcp.x-sp->me.x)*(sp->nextcp.x-sp->me.x));
+ c = cos(pangle); s=sin(pangle);
+ sp->nextcp.x = c*nlen + sp->me.x;
+ sp->nextcp.y = s*nlen + sp->me.y;
+ SplineRefigure(sp->next);
+ }
+ }
+}
+
+void SPLAverageCps(SplinePointList *spl) {
+ SplinePoint *sp;
+
+ while ( spl!=NULL ) {
+ for ( sp=spl->first ; ; ) {
+ SPAverageCps(sp);
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==spl->first )
+ break;
+ }
+ spl = spl->next;
+ }
+}
+
+void SplineCharTangentNextCP(SplinePoint *sp) {
+ double len;
+ BasePoint *bp, unit;
+
+ if ( sp->prev==NULL )
+return;
+ bp = &sp->prev->from->me;
+
+ unit.y = sp->me.y-bp->y; unit.x = sp->me.x-bp->x;
+ len = sqrt( unit.x*unit.x + unit.y*unit.y );
+ if ( len!=0 ) {
+ unit.x /= len;
+ unit.y /= len;
+ }
+ len = sqrt((sp->nextcp.y-sp->me.y)*(sp->nextcp.y-sp->me.y) + (sp->nextcp.x-sp->me.x)*(sp->nextcp.x-sp->me.x));
+ sp->nextcp.x = sp->me.x + len*unit.x;
+ sp->nextcp.y = sp->me.y + len*unit.y;
+ sp->nextcp.x = rint(sp->nextcp.x*1024)/1024;
+ sp->nextcp.y = rint(sp->nextcp.y*1024)/1024;
+ if ( sp->next!=NULL && sp->next->order2 )
+ sp->next->to->prevcp = sp->nextcp;
+}
+
+void SplineCharTangentPrevCP(SplinePoint *sp) {
+ double len;
+ BasePoint *bp, unit;
+
+ if ( sp->next==NULL )
+return;
+ bp = &sp->next->to->me;
+
+ unit.y = sp->me.y-bp->y; unit.x = sp->me.x-bp->x;
+ len = sqrt( unit.x*unit.x + unit.y*unit.y );
+ if ( len!=0 ) {
+ unit.x /= len;
+ unit.y /= len;
+ }
+ len = sqrt((sp->prevcp.y-sp->me.y)*(sp->prevcp.y-sp->me.y) + (sp->prevcp.x-sp->me.x)*(sp->prevcp.x-sp->me.x));
+ sp->prevcp.x = sp->me.x + len*unit.x;
+ sp->prevcp.y = sp->me.y + len*unit.y;
+ sp->prevcp.x = rint(sp->prevcp.x*1024)/1024;
+ sp->prevcp.y = rint(sp->prevcp.y*1024)/1024;
+ if ( sp->prev!=NULL && sp->prev->order2 )
+ sp->prev->from->nextcp = sp->prevcp;
+}
+
+#define NICE_PROPORTION .39
+void SplineCharDefaultNextCP(SplinePoint *base) {
+ SplinePoint *prev=NULL, *next;
+ double len, plen, ulen;
+ BasePoint unit;
+
+ if ( base->next==NULL )
+return;
+ if ( base->next->order2 ) {
+ SplineRefigureFixup(base->next);
+return;
+ }
+ if ( !base->nextcpdef ) {
+ if ( base->pointtype==pt_tangent )
+ SplineCharTangentNextCP(base);
+return;
+ }
+ next = base->next->to;
+ if ( base->prev!=NULL )
+ prev = base->prev->from;
+
+ len = NICE_PROPORTION * sqrt((base->me.x-next->me.x)*(base->me.x-next->me.x) +
+ (base->me.y-next->me.y)*(base->me.y-next->me.y));
+ unit.x = next->me.x - base->me.x;
+ unit.y = next->me.y - base->me.y;
+ ulen = sqrt(unit.x*unit.x + unit.y*unit.y);
+ if ( ulen!=0 )
+ unit.x /= ulen, unit.y /= ulen;
+ base->nonextcp = false;
+
+ if ( base->pointtype == pt_curve ) {
+ if ( prev!=NULL && (base->prevcpdef || base->noprevcp)) {
+ unit.x = next->me.x - prev->me.x;
+ unit.y = next->me.y - prev->me.y;
+ ulen = sqrt(unit.x*unit.x + unit.y*unit.y);
+ if ( ulen!=0 )
+ unit.x /= ulen, unit.y /= ulen;
+ plen = sqrt((base->prevcp.x-base->me.x)*(base->prevcp.x-base->me.x) +
+ (base->prevcp.y-base->me.y)*(base->prevcp.y-base->me.y));
+ base->prevcp.x = base->me.x - plen*unit.x;
+ base->prevcp.y = base->me.y - plen*unit.y;
+ SplineRefigureFixup(base->prev);
+ } else if ( prev!=NULL ) {
+ /* The prev control point is fixed. So we've got to use the same */
+ /* angle it uses */
+ unit.x = base->me.x-base->prevcp.x;
+ unit.y = base->me.y-base->prevcp.y;
+ ulen = sqrt(unit.x*unit.x + unit.y*unit.y);
+ if ( ulen!=0 )
+ unit.x /= ulen, unit.y /= ulen;
+ } else {
+ base->prevcp = base->me;
+ base->noprevcp = true;
+ base->prevcpdef = true;
+ }
+ } else if ( base->pointtype == pt_corner ) {
+ if ( next->pointtype != pt_curve ) {
+ base->nonextcp = true;
+ }
+ } else /* tangent */ {
+ if ( next->pointtype != pt_curve ) {
+ base->nonextcp = true;
+ } else {
+ if ( prev!=NULL ) {
+ if ( !base->noprevcp ) {
+ plen = sqrt((base->prevcp.x-base->me.x)*(base->prevcp.x-base->me.x) +
+ (base->prevcp.y-base->me.y)*(base->prevcp.y-base->me.y));
+ base->prevcp.x = base->me.x - plen*unit.x;
+ base->prevcp.y = base->me.y - plen*unit.y;
+ SplineRefigureFixup(base->prev);
+ }
+ unit.x = base->me.x-prev->me.x;
+ unit.y = base->me.y-prev->me.y;
+ ulen = sqrt(unit.x*unit.x + unit.y*unit.y);
+ if ( ulen!=0 )
+ unit.x /= ulen, unit.y /= ulen;
+ }
+ }
+ }
+ if ( base->nonextcp )
+ base->nextcp = base->me;
+ else {
+ base->nextcp.x = base->me.x + len*unit.x;
+ base->nextcp.y = base->me.y + len*unit.y;
+ base->nextcp.x = rint(base->nextcp.x*1024)/1024;
+ base->nextcp.y = rint(base->nextcp.y*1024)/1024;
+ if ( base->next != NULL )
+ SplineRefigureFixup(base->next);
+ }
+}
+
+void SplineCharDefaultPrevCP(SplinePoint *base) {
+ SplinePoint *next=NULL, *prev;
+ double len, nlen, ulen;
+ BasePoint unit;
+
+ if ( base->prev==NULL )
+return;
+ if ( base->prev->order2 ) {
+ SplineRefigureFixup(base->prev);
+return;
+ }
+ if ( !base->prevcpdef ) {
+ if ( base->pointtype==pt_tangent )
+ SplineCharTangentPrevCP(base);
+return;
+ }
+ prev = base->prev->from;
+ if ( base->next!=NULL )
+ next = base->next->to;
+
+ len = NICE_PROPORTION * sqrt((base->me.x-prev->me.x)*(base->me.x-prev->me.x) +
+ (base->me.y-prev->me.y)*(base->me.y-prev->me.y));
+ unit.x = prev->me.x - base->me.x;
+ unit.y = prev->me.y - base->me.y;
+ ulen = sqrt(unit.x*unit.x + unit.y*unit.y);
+ if ( ulen!=0 )
+ unit.x /= ulen, unit.y /= ulen;
+ base->noprevcp = false;
+
+ if ( base->pointtype == pt_curve ) {
+ if ( next!=NULL && (base->nextcpdef || base->nonextcp)) {
+ unit.x = prev->me.x - next->me.x;
+ unit.y = prev->me.y - next->me.y;
+ ulen = sqrt(unit.x*unit.x + unit.y*unit.y);
+ if ( ulen!=0 )
+ unit.x /= ulen, unit.y /= ulen;
+ nlen = sqrt((base->nextcp.x-base->me.x)*(base->nextcp.x-base->me.x) +
+ (base->nextcp.y-base->me.y)*(base->nextcp.y-base->me.y));
+ base->nextcp.x = base->me.x - nlen*unit.x;
+ base->nextcp.y = base->me.y - nlen*unit.y;
+ SplineRefigureFixup(base->next);
+ } else if ( next!=NULL ) {
+ /* The next control point is fixed. So we got to use the same */
+ /* angle it uses */
+ unit.x = base->me.x-base->nextcp.x;
+ unit.y = base->me.y-base->nextcp.y;
+ ulen = sqrt(unit.x*unit.x + unit.y*unit.y);
+ if ( ulen!=0 )
+ unit.x /= ulen, unit.y /= ulen;
+ } else {
+ base->nextcp = base->me;
+ base->nonextcp = true;
+ base->nextcpdef = true;
+ }
+ } else if ( base->pointtype == pt_corner ) {
+ if ( prev->pointtype != pt_curve ) {
+ base->noprevcp = true;
+ }
+ } else /* tangent */ {
+ if ( prev->pointtype != pt_curve ) {
+ base->noprevcp = true;
+ } else {
+ if ( next!=NULL ) {
+ if ( !base->nonextcp ) {
+ nlen = sqrt((base->nextcp.x-base->me.x)*(base->nextcp.x-base->me.x) +
+ (base->nextcp.y-base->me.y)*(base->nextcp.y-base->me.y));
+ base->nextcp.x = base->me.x - nlen*unit.x;
+ base->nextcp.y = base->me.y - nlen*unit.y;
+ SplineRefigureFixup(base->next);
+ }
+ unit.x = base->me.x-next->me.x;
+ unit.y = base->me.y-next->me.y;
+ ulen = sqrt(unit.x*unit.x + unit.y*unit.y);
+ if ( ulen!=0 )
+ unit.x /= ulen, unit.y /= ulen;
+ }
+ }
+ }
+ if ( base->noprevcp )
+ base->prevcp = base->me;
+ else {
+ base->prevcp.x = base->me.x + len*unit.x;
+ base->prevcp.y = base->me.y + len*unit.y;
+ base->prevcp.x = rint(base->prevcp.x*1024)/1024;
+ base->prevcp.y = rint(base->prevcp.y*1024)/1024;
+ if ( base->prev!=NULL )
+ SplineRefigureFixup(base->prev);
+ }
+}
+
+void SPSmoothJoint(SplinePoint *sp) {
+ BasePoint unitn, unitp;
+ double len, dot, dotn, dotp;
+ if ( sp->prev==NULL || sp->next==NULL || sp->pointtype==pt_corner )
+return;
+
+ if ( sp->pointtype==pt_curve && !sp->nonextcp && !sp->noprevcp ) {
+ unitn.x = sp->nextcp.x-sp->me.x;
+ unitn.y = sp->nextcp.y-sp->me.y;
+ len = sqrt(unitn.x*unitn.x + unitn.y*unitn.y);
+ if ( len==0 )
+return;
+ unitn.x /= len; unitn.y /= len;
+ unitp.x = sp->me.x - sp->prevcp.x;
+ unitp.y = sp->me.y - sp->prevcp.y;
+ len = sqrt(unitp.x*unitp.x + unitp.y*unitp.y);
+ if ( len==0 )
+return;
+ unitp.x /= len; unitp.y /= len;
+ dotn = unitp.y*(sp->nextcp.x-sp->me.x) - unitp.x*(sp->nextcp.y-sp->me.y);
+ dotp = unitn.y*(sp->me.x - sp->prevcp.x) - unitn.x*(sp->me.y - sp->prevcp.y);
+ sp->nextcp.x -= dotn*unitp.y/2;
+ sp->nextcp.y -= -dotn*unitp.x/2;
+ sp->prevcp.x += dotp*unitn.y/2;
+ sp->prevcp.y += -dotp*unitn.x/2;
+ SplineRefigure(sp->prev); SplineRefigure(sp->next);
+ }
+ if ( sp->pointtype==pt_tangent && !sp->nonextcp ) {
+ unitp.x = sp->me.x - sp->prev->from->me.x;
+ unitp.y = sp->me.y - sp->prev->from->me.y;
+ len = sqrt(unitp.x*unitp.x + unitp.y*unitp.y);
+ if ( len!=0 ) {
+ unitp.x /= len; unitp.y /= len;
+ dot = unitp.y*(sp->nextcp.x-sp->me.x) - unitp.x*(sp->nextcp.y-sp->me.y);
+ sp->nextcp.x -= dot*unitp.y;
+ sp->nextcp.y -= -dot*unitp.x;
+ SplineRefigure(sp->next);
+ }
+ }
+ if ( sp->pointtype==pt_tangent && !sp->noprevcp ) {
+ unitn.x = sp->nextcp.x-sp->me.x;
+ unitn.y = sp->nextcp.y-sp->me.y;
+ len = sqrt(unitn.x*unitn.x + unitn.y*unitn.y);
+ if ( len!=0 ) {
+ unitn.x /= len; unitn.y /= len;
+ dot = unitn.y*(sp->me.x-sp->prevcp.x) - unitn.x*(sp->me.y-sp->prevcp.y);
+ sp->prevcp.x += dot*unitn.y;
+ sp->prevcp.y += -dot*unitn.x;
+ SplineRefigure(sp->prev);
+ }
+ }
+}
+
+void SplinePointListSet(SplinePointList *tobase, SplinePointList *frombase) {
+ SplinePoint *tsp, *first, *fsp;
+ Spline *tspline, *firstsp, *fspline;
+
+ for ( ; tobase!=NULL && frombase!=NULL; tobase = tobase->next , frombase=frombase->next ) {
+ first = NULL;
+ for ( tsp = tobase->first, fsp=frombase->first; tsp!=first; tsp=tsp->next->to, fsp=fsp->next->to ) {
+ tsp->me = fsp->me;
+ tsp->nextcp = fsp->nextcp;
+ tsp->prevcp = fsp->prevcp;
+ tsp->noprevcp = fsp->noprevcp;
+ tsp->nonextcp = fsp->nonextcp;
+ if ( first==NULL ) first = tsp;
+ if ( tsp->next==NULL )
+ break;
+ }
+ firstsp = NULL;
+ for ( tspline = tobase->first->next, fspline=frombase->first->next;
+ tspline!=NULL && tspline!=firstsp;
+ tspline=tspline->to->next, fspline=fspline->to->next ) {
+ tspline->splines[0] = fspline->splines[0];
+ tspline->splines[1] = fspline->splines[1];
+ LinearApproxFree(tspline->approx);
+ tspline->approx = NULL;
+ if ( firstsp==NULL ) firstsp = tspline;
+ }
+ }
+}
+
+int PointListIsSelected(SplinePointList *spl) {
+ int anypoints = 0;
+ Spline *spline, *first;
+
+ first = NULL;
+ if ( spl->first->selected ) anypoints = true;
+ for ( spline=spl->first->next; spline!=NULL && spline!=first && !anypoints; spline = spline->to->next ) {
+ if ( spline->to->selected ) anypoints = true;
+ if ( first == NULL ) first = spline;
+ }
+return( anypoints );
+}
+
+SplineSet *SplineSetReverse(SplineSet *spl) {
+ Spline *spline, *first, *next;
+ BasePoint tp;
+ SplinePoint *temp;
+ int bool;
+ /* reverse the splineset so that what was the start point becomes the end */
+ /* and vice versa. This entails reversing every individual spline, and */
+ /* each point */
+
+ first = NULL;
+ spline = spl->first->next;
+ if ( spline==NULL )
+return( spl ); /* Only one point, reversal is meaningless */
+
+ tp = spline->from->nextcp;
+ spline->from->nextcp = spline->from->prevcp;
+ spline->from->prevcp = tp;
+ bool = spline->from->nonextcp;
+ spline->from->nonextcp = spline->from->noprevcp;
+ spline->from->noprevcp = bool;
+ bool = spline->from->nextcpdef;
+ spline->from->nextcpdef = spline->from->prevcpdef;
+ spline->from->prevcpdef = bool;
+
+ for ( ; spline!=NULL && spline!=first; spline=next ) {
+ next = spline->to->next;
+
+ if ( spline->to!=spl->first ) { /* On a closed spline don't want to reverse the first point twice */
+ tp = spline->to->nextcp;
+ spline->to->nextcp = spline->to->prevcp;
+ spline->to->prevcp = tp;
+ bool = spline->to->nonextcp;
+ spline->to->nonextcp = spline->to->noprevcp;
+ spline->to->noprevcp = bool;
+ bool = spline->to->nextcpdef;
+ spline->to->nextcpdef = spline->to->prevcpdef;
+ spline->to->prevcpdef = bool;
+ }
+
+ temp = spline->to;
+ spline->to = spline->from;
+ spline->from = temp;
+ spline->from->next = spline;
+ spline->to->prev = spline;
+ SplineRefigure(spline);
+ if ( first==NULL ) first = spline;
+ }
+
+ if ( spl->first!=spl->last ) {
+ temp = spl->first;
+ spl->first = spl->last;
+ spl->last = temp;
+ spl->first->prev = NULL;
+ spl->last->next = NULL;
+ }
+return( spl );
+}
+
+void SplineSetsUntick(SplineSet *spl) {
+ Spline *spline, *first;
+
+ while ( spl!=NULL ) {
+ first = NULL;
+ spl->first->isintersection = false;
+ for ( spline=spl->first->next; spline!=first && spline!=NULL; spline = spline->to->next ) {
+ spline->isticked = false;
+ spline->isneeded = false;
+ spline->isunneeded = false;
+ spline->ishorvert = false;
+ spline->to->isintersection = false;
+ if ( first==NULL ) first = spline;
+ }
+ spl = spl->next;
+ }
+}
+
+static void SplineSetTick(SplineSet *spl) {
+ Spline *spline, *first;
+
+ first = NULL;
+ for ( spline=spl->first->next; spline!=first && spline!=NULL; spline = spline->to->next ) {
+ spline->isticked = true;
+ if ( first==NULL ) first = spline;
+ }
+}
+
+static SplineSet *SplineSetOfSpline(SplineSet *spl,Spline *search) {
+ Spline *spline, *first;
+
+ while ( spl!=NULL ) {
+ first = NULL;
+ for ( spline=spl->first->next; spline!=first && spline!=NULL; spline = spline->to->next ) {
+ if ( spline==search )
+return( spl );
+ if ( first==NULL ) first = spline;
+ }
+ spl = spl->next;
+ }
+return( NULL );
+}
+
+int SplineInSplineSet(Spline *spline, SplineSet *spl) {
+ Spline *first, *s;
+
+ first = NULL;
+ for ( s = spl->first->next; s!=NULL && s!=first; s = s->to->next ) {
+ if ( s==spline )
+return( true );
+ if ( first==NULL ) first = s;
+ }
+return( false );
+}
+
+#include "edgelist.h"
+
+static void EdgeListReverse(EdgeList *es, SplineSet *spl) {
+ int i;
+
+ if ( es->edges!=NULL ) {
+ for ( i=0; i<es->cnt; ++i ) {
+ Edge *e;
+ for ( e = es->edges[i]; e!=NULL; e = e->esnext ) {
+ if ( SplineInSplineSet(e->spline,spl)) {
+ e->up = !e->up;
+ e->t_mmin = 1-e->t_mmin;
+ e->t_mmax = 1-e->t_mmax;
+ e->t_cur = 1-e->t_cur;
+ }
+ }
+ }
+ }
+}
+
+static int SSCheck(SplineSet *base,Edge *active, int up, EdgeList *es,int *changed) {
+ SplineSet *spl;
+ if ( active->spline->isticked )
+return( 0 );
+ spl = SplineSetOfSpline(base,active->spline);
+ if ( active->up!=up ) {
+ SplineSetReverse(spl);
+ *changed = true;
+ EdgeListReverse(es,spl);
+ }
+ SplineSetTick(spl);
+return( 1 );
+}
+
+SplineSet *SplineSetsExtractOpen(SplineSet **tbase) {
+ SplineSet *spl, *openhead=NULL, *openlast=NULL, *prev=NULL, *snext;
+
+ for ( spl= *tbase; spl!=NULL; spl = snext ) {
+ snext = spl->next;
+ if ( spl->first->prev==NULL ) {
+ if ( prev==NULL )
+ *tbase = snext;
+ else
+ prev->next = snext;
+ if ( openhead==NULL )
+ openhead = spl;
+ else
+ openlast->next = spl;
+ openlast = spl;
+ spl->next = NULL;
+ } else
+ prev = spl;
+ }
+return( openhead );
+}
+
+void SplineSetsInsertOpen(SplineSet **tbase,SplineSet *open) {
+ SplineSet *e, *p, *spl, *next;
+
+ for ( p=NULL, spl=*tbase, e=open; e!=NULL; e = next ) {
+ next = e->next;
+ while ( spl!=NULL && spl->first->ttfindex<e->first->ttfindex ) {
+ p = spl;
+ spl = spl->next;
+ }
+ if ( p==NULL )
+ *tbase = e;
+ else
+ p->next = e;
+ e->next = spl;
+ p = e;
+ }
+}
+
+/* The idea behind SplineSetsCorrect is simple. However there are many splinesets */
+/* where it is impossible, so bear in mind that this only works for nice */
+/* splines. Figure 8's, interesecting splines all cause problems */
+/* The outermost spline should be clockwise (up), the next splineset we find */
+/* should be down, if it isn't reverse it (if it's already been dealt with */
+/* then ignore it) */
+SplineSet *SplineSetsCorrect(SplineSet *base,int *changed) {
+ SplineSet *spl;
+ int sscnt, check_cnt;
+ EdgeList es;
+ DBounds b;
+ Edge *active=NULL, *apt, *pr, *e;
+ int i, winding;
+
+ *changed = false;
+
+ SplineSetsUntick(base);
+ for (sscnt=0,spl=base; spl!=NULL; spl=spl->next, ++sscnt );
+
+ SplineSetFindBounds(base,&b);
+ memset(&es,'\0',sizeof(es));
+ es.scale = 1.0;
+ es.mmin = floor(b.miny*es.scale);
+ es.mmax = ceil(b.maxy*es.scale);
+ es.omin = b.minx*es.scale;
+ es.omax = b.maxx*es.scale;
+
+/* Give up if we are given unreasonable values (ie. if rounding errors might screw us up) */
+ if ( es.mmin<1e5 && es.mmax>-1e5 && es.omin<1e5 && es.omax>-1e5 ) {
+ es.cnt = (int) (es.mmax-es.mmin) + 1;
+ es.edges = gcalloc(es.cnt,sizeof(Edge *));
+ es.interesting = gcalloc(es.cnt,sizeof(char));
+ es.sc = NULL;
+ es.major = 1; es.other = 0;
+ FindEdgesSplineSet(base,&es);
+
+ check_cnt = 0;
+ for ( i=0; i<es.cnt && check_cnt<sscnt; ++i ) {
+ active = ActiveEdgesRefigure(&es,active,i);
+ if ( es.edges[i]!=NULL )
+ continue; /* Just too hard to get the edges sorted when we are at a start vertex */
+ if ( /*es.edges[i]==NULL &&*/ !es.interesting[i] &&
+ !(i>0 && es.interesting[i-1]) && !(i>0 && es.edges[i-1]!=NULL) &&
+ !(i<es.cnt-1 && es.edges[i+1]!=NULL) &&
+ !(i<es.cnt-1 && es.interesting[i+1])) /* interesting things happen when we add (or remove) entries */
+ continue; /* and where we have extrema */
+ for ( apt=active; apt!=NULL; apt = e) {
+ check_cnt += SSCheck(base,apt,true,&es,changed);
+ winding = apt->up?1:-1;
+ for ( pr=apt, e=apt->aenext; e!=NULL && winding!=0; pr=e, e=e->aenext ) {
+ if ( !e->spline->isticked )
+ check_cnt += SSCheck(base,e,winding<0,&es,changed);
+ if ( pr->up!=e->up )
+ winding += (e->up?1:-1);
+ else if ( (pr->before==e || pr->after==e ) &&
+ (( pr->mmax==i && e->mmin==i ) ||
+ ( pr->mmin==i && e->mmax==i )) )
+ /* This just continues the line and doesn't change count */;
+ else
+ winding += (e->up?1:-1);
+ }
+ /* color a horizontal line that comes out of the last vertex */
+ if ( e!=NULL && (e->before==pr || e->after==pr) &&
+ (( pr->mmax==i && e->mmin==i ) ||
+ ( pr->mmin==i && e->mmax==i )) ) {
+ pr = e;
+ e = e->aenext;
+ }
+ }
+ }
+ FreeEdges(&es);
+ }
+return( base );
+}
+
+SplineSet *SplineSetsAntiCorrect(SplineSet *base) {
+ int changed;
+ SplineSet *spl;
+
+ SplineSetsCorrect(base,&changed);
+ for ( spl = base; spl!=NULL; spl = spl->next )
+ SplineSetReverse(spl);
+return( base );
+}
+
+/* This is exactly the same as SplineSetsCorrect, but instead of correcting */
+/* problems we merely search for them and if we find any return the first */
+SplineSet *SplineSetsDetectDir(SplineSet **_base,int *_lastscan) {
+ SplineSet *ret, *base;
+ EIList el;
+ EI *active=NULL, *apt, *pr, *e;
+ int i, winding,change,waschange;
+ int lastscan = *_lastscan;
+ SplineChar dummy;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ Layer layers[2];
+#endif
+
+ base = *_base;
+
+ memset(&el,'\0',sizeof(el));
+ memset(&dummy,'\0',sizeof(dummy));
+#ifdef FONTFORGE_CONFIG_TYPE3
+ memset(layers,0,sizeof(layers));
+ dummy.layers = layers;
+#endif
+ dummy.layer_cnt = 2;
+ dummy.layers[ly_fore].splines = base;
+ ELFindEdges(&dummy,&el);
+ if ( el.coordmax[1]-el.coordmin[1] > 1.e6 ) {
+ LogError( _("Warning: Unreasonably big splines. They will be ignored.\n") );
+return( NULL );
+ }
+ el.major = 1;
+ ELOrder(&el,el.major);
+
+ ret = NULL;
+ waschange = false;
+ for ( i=0; i<el.cnt && ret==NULL; ++i ) {
+ active = EIActiveEdgesRefigure(&el,active,i,1,&change);
+ if ( i<=lastscan )
+ continue;
+ if ( el.ordered[i]!=NULL || el.ends[i] ) {
+ waschange = change;
+ continue; /* Just too hard to get the edges sorted when we are at a start vertex */
+ }
+ if ( !( waschange || change || el.ends[i] || el.ordered[i]!=NULL ||
+ (i!=el.cnt-1 && (el.ends[i+1] || el.ordered[i+1]!=NULL)) ))
+ continue;
+ waschange = change;
+ for ( apt=active; apt!=NULL && ret==NULL; apt = e) {
+ if ( EISkipExtremum(apt,i+el.low,1)) {
+ e = apt->aenext->aenext;
+ continue;
+ }
+ if ( !apt->up ) {
+ ret = SplineSetOfSpline(base,active->spline);
+ break;
+ }
+ winding = apt->up?1:-1;
+ for ( pr=apt, e=apt->aenext; e!=NULL && winding!=0; pr=e, e=e->aenext ) {
+ if ( EISkipExtremum(e,i+el.low,1)) {
+ e = e->aenext;
+ continue;
+ }
+ if ( pr->up!=e->up ) {
+ if ( (winding<=0 && !e->up) || (winding>0 && e->up )) {
+ ret = SplineSetOfSpline(base,active->spline);
+ break;
+ }
+ winding += (e->up?1:-1);
+ } else if ( EISameLine(pr,e,i+el.low,1) )
+ /* This just continues the line and doesn't change count */;
+ else {
+ if ( (winding<=0 && !e->up) || (winding>0 && e->up )) {
+ ret = SplineSetOfSpline(base,active->spline);
+ break;
+ }
+ winding += (e->up?1:-1);
+ }
+ }
+ }
+ }
+ free(el.ordered);
+ free(el.ends);
+ ElFreeEI(&el);
+ *_base = base;
+ *_lastscan = i;
+return( ret );
+}
+
+int SplinePointListIsClockwise(const SplineSet *spl) {
+ EIList el;
+ EI *active=NULL, *apt, *e;
+ int i, change,waschange;
+ SplineChar dummy;
+ SplineSet *next;
+ int ret = -1, maybe=-1;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ Layer layers[2];
+#endif
+
+ if ( spl->first!=spl->last || spl->first->next == NULL )
+return( -1 ); /* Open paths, (open paths with only one point are a special case) */
+
+ memset(&el,'\0',sizeof(el));
+ memset(&dummy,'\0',sizeof(dummy));
+#ifdef FONTFORGE_CONFIG_TYPE3
+ memset(layers,0,sizeof(layers));
+ dummy.layers = layers;
+#endif
+ dummy.layer_cnt = 2;
+ dummy.layers[ly_fore].splines = (SplineSet *) spl;
+ next = spl->next; ((SplineSet *) spl)->next = NULL;
+ ELFindEdges(&dummy,&el);
+ if ( el.coordmax[1]-el.coordmin[1] > 1.e6 ) {
+ LogError( _("Warning: Unreasonably big splines. They will be ignored.\n") );
+return( -1 );
+ }
+ el.major = 1;
+ ELOrder(&el,el.major);
+
+ waschange = false;
+ for ( i=0; i<el.cnt && ret==-1; ++i ) {
+ active = EIActiveEdgesRefigure(&el,active,i,1,&change);
+ if ( el.ordered[i]!=NULL || el.ends[i] || waschange || change ) {
+ waschange = change;
+ if ( active!=NULL )
+ maybe = active->up;
+ continue; /* Just too hard to get the edges sorted when we are at a start vertex */
+ }
+ waschange = change;
+ for ( apt=active; apt!=NULL && ret==-1; apt = e) {
+ if ( EISkipExtremum(apt,i+el.low,1)) {
+ e = apt->aenext->aenext;
+ continue;
+ }
+ ret = apt->up;
+ break;
+ }
+ }
+ free(el.ordered);
+ free(el.ends);
+ ElFreeEI(&el);
+ ((SplineSet *) spl)->next = next;
+ if ( ret==-1 )
+ ret = maybe;
+return( ret );
+}
+
+#if 0
+void SFFigureGrid(SplineFont *sf) {
+ /* Look for any horizontal/vertical lines in the grid splineset */
+ int hsnaps[40], hcnt=0, vsnaps[40], vcnt=0, i;
+ SplineSet *ss;
+ Spline *s, *first;
+
+ for ( ss = sf->gridsplines; ss!=NULL; ss=ss->next ) {
+ first = NULL;
+ for ( s=ss->first->next; s!=NULL && s!=first; s=s->to->next ) {
+ if ( s->knownlinear ) {
+ if ( s->from->me.x==s->to->me.x && hcnt<40 )
+ hsnaps[hcnt++] = s->from->me.x;
+ if ( s->from->me.y==s->to->me.y && vcnt<40 )
+ vsnaps[vcnt++] = s->from->me.y;
+ }
+ if ( first==NULL ) first = s;
+ }
+ }
+
+ if ( sf->hsnaps!=NULL ) {
+ for ( i=0; i<hcnt && sf->hsnaps[i]==hsnaps[i]; ++i );
+ if ( i!=hcnt || sf->hsnaps[i]!=0x80000000 ) {
+ free( sf->hsnaps );
+ sf->hsnaps = NULL;
+ }
+ }
+ if ( sf->vsnaps!=NULL ) {
+ for ( i=0; i<vcnt && sf->vsnaps[i]==vsnaps[i]; ++i );
+ if ( i!=vcnt || sf->vsnaps[i]!=0x80000000 ) {
+ free( sf->vsnaps );
+ sf->vsnaps = NULL;
+ }
+ }
+
+ if ( hcnt!=0 && sf->hsnaps==NULL ) {
+ sf->hsnaps = galloc((hcnt+1)*sizeof(int));
+ memcpy(sf->hsnaps,hsnaps,hcnt*sizeof(int));
+ sf->hsnaps[hcnt] = 0x80000000;
+ }
+ if ( vcnt!=0 && sf->vsnaps==NULL ) {
+ sf->vsnaps = galloc((vcnt+1)*sizeof(int));
+ memcpy(sf->vsnaps,vsnaps,vcnt*sizeof(int));
+ sf->vsnaps[vcnt] = 0x80000000;
+ }
+}
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/stamp.c b/Build/source/libs/luafontforge/fontforge/fontforge/stamp.c
new file mode 100644
index 00000000000..b34fc8db12b
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/stamp.c
@@ -0,0 +1,5 @@
+#include <time.h>
+
+const time_t source_modtime = 1181260092;
+const char *source_modtime_str = "16:48 7-Jun-2007";
+const char *source_version_str = "20070607";
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/stamper.c b/Build/source/libs/luafontforge/fontforge/fontforge/stamper.c
new file mode 100644
index 00000000000..a476bb837bc
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/stamper.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <time.h>
+
+static const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
+ "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
+int main() {
+ time_t now;
+ struct tm *tm;
+
+ time(&now);
+ tm = localtime(&now);
+ printf( "#include <time.h>\n\n" );
+ printf( "const time_t source_modtime = %ld;\n", now);
+ printf( "const char *source_modtime_str = \"%02d:%02d %d-%s-%d\";\n",
+ tm->tm_hour, tm->tm_min,
+ tm->tm_mday, months[tm->tm_mon], tm->tm_year+1900 );
+ printf( "const char *source_version_str = \"%04d%02d%02d\";\n",
+ tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday );
+return( 0 );
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/start.c b/Build/source/libs/luafontforge/fontforge/fontforge/start.c
new file mode 100644
index 00000000000..97e1c948661
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/start.c
@@ -0,0 +1,935 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaeditui.h"
+#include <gfile.h>
+#ifdef FONTFORGE_CONFIG_GDRAW
+# include <gresource.h>
+# include <ustring.h>
+#elif defined( FONTFORGE_CONFIG_GTK )
+# include "interface.h"
+# include "callbacks.h"
+# include "support.h"
+#endif
+#include <time.h>
+#include <sys/time.h>
+#include <locale.h>
+#include <unistd.h>
+#if !defined(_NO_LIBUNINAMESLIST) && !defined(_STATIC_LIBUNINAMESLIST) && !defined(NODYNAMIC)
+# include <dynamic.h>
+#endif
+#ifdef __Mac
+# include <stdlib.h> /* getenv,setenv */
+#endif
+
+int32 unicode_from_adobestd[256] = {0}; /* fix 64bit aligns */
+
+struct lconv localeinfo;
+char *coord_sep = ","; /* Not part of locale data */
+const struct unicode_nameannot * const *const *_UnicodeNameAnnot = NULL;
+
+#ifndef LUA_FF_LIB
+static void initadobeenc(void) {
+ int i,j;
+
+ for ( i=0; i<0x100; ++i ) {
+ if ( strcmp(AdobeStandardEncoding[i],".notdef")==0 )
+ unicode_from_adobestd[i] = 0xfffd;
+ else {
+ j = UniFromName(AdobeStandardEncoding[i],ui_none,&custom);
+ if ( j==-1 ) j = 0xfffd;
+ unicode_from_adobestd[i] = j;
+ }
+ }
+}
+
+static void inituninameannot(void) {
+#if 1 || _NO_LIBUNINAMESLIST
+ _UnicodeNameAnnot = NULL;
+#elif defined(_STATIC_LIBUNINAMESLIST) || defined(NODYNAMIC)
+ extern const struct unicode_nameannot * const * const UnicodeNameAnnot[];
+ _UnicodeNameAnnot = UnicodeNameAnnot;
+#else
+ DL_CONST void *libuninames=NULL;
+ const char *loc = getenv("LC_ALL");
+# ifdef LIBDIR
+ char full[1024], buf[100];
+# else
+ char buf[100];
+#endif
+ int i;
+
+ if ( loc==NULL ) loc = getenv("LC_MESSAGES");
+ if ( loc==NULL ) loc = getenv("LANG");
+ for ( i=0; i<4; ++i ) {
+ strcpy(buf,"libuninameslist-");
+ if ( i==3 )
+ buf[strlen(buf)-1] = '\0';
+ /* Use the default name */
+ else if ( i==2 ) {
+ if ( loc==NULL || strlen( loc )<2 )
+ continue;
+ strncat(buf,loc,2);
+ } else if ( i==1 ) {
+ if ( loc==NULL || strlen( loc )<5 )
+ continue;
+ strncat(buf,loc,5);
+ } else if ( i==0 ) {
+ if ( loc==NULL || strlen( loc )<6 )
+ continue;
+ strcat(buf,loc);
+ }
+ strcat(buf, SO_EXT );
+
+# ifdef LIBDIR
+# if !defined(_NO_SNPRINTF) && !defined(VMS)
+ snprintf( full, sizeof(full), "%s/%s", LIBDIR, buf );
+# else
+ sprintf( full, "%s/%s", LIBDIR, buf );
+# endif
+ libuninames = dlopen( full,RTLD_LAZY);
+# endif
+ if ( libuninames==NULL )
+ libuninames = dlopen( buf,RTLD_LAZY);
+ if ( libuninames!=NULL ) {
+ _UnicodeNameAnnot = dlsym(libuninames,"UnicodeNameAnnot");
+return;
+ }
+ }
+#endif
+}
+#endif
+
+void doversion(void) {
+ extern const char *source_version_str;
+#ifdef FONTFORGE_CONFIG_TYPE3
+ printf( "fontforge %s-ML\n", source_version_str );
+#else
+ printf( "fontforge %s\n", source_version_str );
+#endif
+exit(0);
+}
+
+#ifndef LUA_FF_LIB
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static void _dousage(void) {
+ printf( "fontforge [options] [fontfiles]\n" );
+ printf( "\t-new\t\t\t (creates a new font)\n" );
+#if HANYANG
+ printf( "\t-newkorean\t\t (creates a new korean font)\n" );
+#endif
+ printf( "\t-recover none|auto|clean (control error recovery)\n" );
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ printf( "\t-nosplash\t\t (no splash screen)\n" );
+#endif
+ printf( "\t-display display-name\t (sets the X display)\n" );
+#ifdef FONTFORGE_CONFIG_GDRAW
+ printf( "\t-depth val\t\t (sets the display depth if possible)\n" );
+ printf( "\t-vc val\t\t\t (sets the visual class if possible)\n" );
+ printf( "\t-cmap current|copy|private\t (sets the type of colormap)\n" );
+ printf( "\t-dontopenxdevices\t (in case that fails)\n" );
+ printf( "\t-sync\t\t\t (syncs the display, debugging)\n" );
+ printf( "\t-keyboard ibm|mac|sun|ppc (generates appropriate hotkeys in menus)\n" );
+#endif
+#if MyMemory
+ printf( "\t-memory\t\t\t (turns on memory checks, debugging)\n" );
+#endif
+ printf( "\t-usage\t\t\t (displays this message, and exits)\n" );
+ printf( "\t-help\t\t\t (displays this message, invokes a browser)\n\t\t\t\t (Using the BROWSER environment variable)\n" );
+ printf( "\t-version\t\t (prints the version of fontforge and exits)\n" );
+ printf( "\t-lang=py\t\t use python for scripts\n" );
+ printf( "\t-lang=ff\t\t use fontforge's legacy scripting language\n" );
+ printf( "\t-script scriptfile\t (executes scriptfile)\n" );
+ printf( "\t\tmust be the first option (or follow -lang).\n" );
+ printf( "\t\tAll others passed to scriptfile.\n" );
+ printf( "\t-dry scriptfile\t (syntax checks scriptfile)\n" );
+ printf( "\t\tmust be the first option. All others passed to scriptfile.\n" );
+ printf( "\t-c script-string\t (executes argument as scripting cmds)\n" );
+ printf( "\t\tmust be the first option. All others passed to the script.\n" );
+ printf( "\n" );
+ printf( "FontForge will read postscript (pfa, pfb, ps, cid), opentype (otf),\n" );
+ printf( "\ttruetype (ttf,ttc), macintosh resource fonts (dfont,bin,hqx),\n" );
+ printf( "\tand bdf and pcf fonts. It will also read it's own format --\n" );
+ printf( "\tsfd files.\n" );
+ printf( "If no fontfiles are specified (and -new is not either and there's nothing\n" );
+ printf( "\tto recover) then fontforge will produce an open font dlg.\n" );
+ printf( "If a scriptfile is specified then FontForge will not open the X display\n" );
+ printf( "\tnor will it process any additional arguments. It will execute the\n" );
+ printf( "\tscriptfile and give it any remaining arguments\n" );
+ printf( "If the first argument is an executable filename, and that file's first\n" );
+ printf( "\tline contains \"fontforge\" then it will be treated as a scriptfile.\n\n" );
+ printf( "For more information see:\n\thttp://fontforge.sourceforge.net/\n" );
+ printf( "Send bug reports to:\tfontforge-devel@lists.sourceforge.net\n" );
+}
+
+static void dousage(void) {
+ _dousage();
+exit(0);
+}
+
+static void dohelp(void) {
+ _dousage();
+ help("overview.html");
+exit(0);
+}
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+#endif
+
+/* TH oddly ,the crosscompiler gets errors from gettimeofday() */
+
+#ifndef LUA_FF_LIB
+static void initrand(void) {
+ struct timeval tv;
+
+ gettimeofday(&tv,NULL);
+ srand(tv.tv_usec);
+}
+
+static void initlibrarysearchpath(void) {
+#ifdef __Mac
+ /* If the user has not set library path, then point it at fink */
+ /* otherwise leave alone. On the mac people often use fink to */
+ /* install image libs. For some reason fink installs in a place */
+ /* the dynamic loader doesn't find */
+ /* (And fink's attempts to set the PATH variables generally don't work */
+ setenv("DYLD_LIBRARY_PATH","/sw/lib",0);
+#endif
+}
+#endif
+
+struct delayed_event {
+ void *data;
+ void (*func)(void *);
+};
+
+#ifdef FONTFORGE_CONFIG_GTK
+
+static void splash_window_tooltip_fun( GtkWidget *splashw ) {
+ static char *foolishness[] = {
+/* GT: These strings are for fun. If they are offensive of incomprehensible */
+/* GT: simply translate them as something dull like: "FontForge" */
+/* GT: Someone said this first quote was a political slogan. If anything, it */
+/* GT: is intended as a satire */
+ N_("A free press discriminates\nagainst the illiterate."),
+ N_("A free press discriminates\nagainst the illiterate."),
+/* GT: The following are mostly misquotations of fairly well-known bits of */
+/* GT: English literature. Trying to translate them literally may miss the */
+/* GT: point. Finding something appropriate in the literature of your own */
+/* GT: language and then twisting it might be closer to the original intent. */
+/* GT: Or just translate them all as "FontForge" and don't worry about them. */
+/* GT: Misquotation of an old latin drinking song */
+ N_("Gaudeamus Ligature!"),
+ N_("Gaudeamus Ligature!"),
+/* GT: Misquotation of the Gospel of John */
+ N_("In the beginning was the letter...")
+/* GT: Misquotation of As You Like It, II, vii, 139-143 */
+ N_("All the world's a page,\n"
+ "And all the men and women merely letters;\n"
+ "They have their ligatures and hyphenations,\n"
+ "And one man in his time forms many words."),
+/* GT: Misquotation of The Wind in the Willows */
+ N_("There is nothing, absolutely nothing,\n"
+ "half so much worth doing\n"
+ "as simply messing about with fonts"),
+/* GT: The New Hacker's Dictionary attributes this to XEROX PARC */
+/* GT: A misquotation of "Ontogeny recapitulates phylogeny" */
+ N_("fontology recapitulates file-ogeny")
+ };
+ GtkTooltips *tips;
+
+ tips = gtk_tooltips_new();
+ gtk_tooltips_set_tip( tips, splashw, _(foolishness[rand()%(sizeof(foolishness)/sizeof(foolishness[0]))]), NULL );
+}
+
+void ShowAboutScreen(void) {
+ GtkWidget *splashw, *version;
+ char buffer[200];
+ extern const char *source_modtime_str;
+ extern const char *source_version_str;
+
+ splashw = create_FontForgeSplash ();
+ splash_window_tooltip_fun( splashw );
+ version = lookup_widget(splashw,"Version");
+ if ( version!=NULL ) {
+#ifdef FONTFORGE_CONFIG_TYPE3
+ sprintf( buffer, "Version: %s (%s-ML)", source_modtime_str, source_version_str);
+#else
+ sprintf( buffer, "Version: %s (%s)", source_modtime_str, source_version_str);
+#endif
+ gtk_label_set_text(GTK_LABEL( version ),buffer);
+ }
+ gtk_widget_show (splashw);
+}
+
+static int DoDelayedEvents(gpointer data) {
+ struct delayed_event *info = (struct delayed_event *) data;
+
+ if ( info!=NULL ) {
+ (info->func)(info->data);
+ chunkfree(info,sizeof(struct delayed_event));
+ }
+return( FALSE ); /* cancel timer */
+}
+
+void DelayEvent(void (*func)(void *), void *data) {
+ struct delayed_event *info = chunkalloc(sizeof(struct delayed_event));
+
+ info->data = data;
+ info->func = func;
+
+ gtk_timeout_add(100,DoDelayedEvents,info);
+}
+
+static int _DoAutoSaves( gpointer ignored ) {
+ DoAutoSaves();
+return( TRUE ); /* Continue timer */
+}
+
+struct argcontext {
+ int argc;
+ char **argv;
+ int recover;
+};
+
+static int ParseArgs( gpointer data ) {
+ struct argcontext *args = data;
+ int argc = args->argc;
+ char **argv = args->argv;
+ int recover = args->recover;
+ int any, i;
+ int next_recent = 0;
+
+ any = 0;
+ if ( recover==-1 )
+ CleanAutoRecovery();
+ else if ( recover )
+ any = DoAutoRecovery();
+
+ for ( i=1; i<argc; ++i ) {
+ char buffer[1025];
+ char *pt = argv[i];
+
+ if ( pt[0]=='-' && pt[1]=='-' )
+ ++pt;
+ if ( strcmp(pt,"-new")==0 ) {
+ FontNew();
+ any = 1;
+#if HANYANG
+ } else if ( strcmp(pt,"-newkorean")==0 ) {
+ MenuNewComposition(NULL,NULL,NULL);
+ any = 1;
+#endif
+ } else if ( strcmp(pt,"-last")==0 ) {
+ if ( next_recent<RECENT_MAX && RecentFiles[next_recent]!=NULL )
+ if ( ViewPostscriptFont(RecentFiles[next_recent++]))
+ any = 1;
+ } else if ( strcmp(pt,"-sync")==0 || strcmp(pt,"-memory")==0 ||
+ strcmp(pt,"-nosplash")==0 || strcmp(pt,"-recover=none")==0 ||
+ strcmp(pt,"-recover=clean")==0 || strcmp(pt,"-recover=auto")==0 ||
+ strcmp(pt,"-dontopenxdevices")==0 )
+ /* Already done, needed to be before display opened */;
+ else if ( (strcmp(pt,"-depth")==0 || strcmp(pt,"-vc")==0 ||
+ strcmp(pt,"-cmap")==0 || strcmp(pt,"-colormap")==0 ||
+ strcmp(pt,"-keyboard")==0 ||
+ strcmp(pt,"-display")==0 || strcmp(pt,"-recover")==0 ) &&
+ i<argc-1 )
+ ++i; /* Already done, needed to be before display opened */
+ else {
+ GFileGetAbsoluteName(argv[i],buffer,sizeof(buffer));
+ if ( GFileIsDir(buffer)) {
+ char *fname;
+ fname = galloc(strlen(buffer)+strlen("glyphs/contents.plist")+1);
+ strcpy(fname,buffer); strcat(fname,"glyphs/contents.plist");
+ if ( GFileExists(fname)) {
+ /* It's probably a Unified Font Object directory */
+ free(fname);
+ if ( ViewPostscriptFont(buffer) )
+ any = 1;
+ } else {
+ strcpy(fname,buffer); strcat(fname,"/font.props");
+ if ( GFileExists(fname)) {
+ /* It's probably a sf dir collection */
+ free(fname);
+ if ( ViewPostscriptFont(buffer) )
+ any = 1;
+ } else {
+ free(fname);
+ if ( buffer[strlen(buffer)-1]!='/' ) {
+ /* If dirname doesn't end in "/" we'll be looking in parent dir */
+ buffer[strlen(buffer)+1]='\0';
+ buffer[strlen(buffer)] = '/';
+ }
+ fname = GetPostscriptFontName(buffer,false);
+ if ( fname!=NULL )
+ ViewPostscriptFont(fname);
+ any = 1; /* Even if we didn't get a font, don't bring up dlg again */
+ free(fname);
+ }
+ }
+ } else if ( ViewPostscriptFont(buffer)!=0 )
+ any = 1;
+ }
+ }
+ if ( !any )
+ Menu_Open(NULL,NULL);
+return( FALSE ); /* Cancel timer */
+}
+
+#elif defined( FONTFORGE_CONFIG_GDRAW )
+static void BuildCharHook(GDisplay *gd) {
+ GWidgetCreateInsChar();
+}
+
+static void InsCharHook(GDisplay *gd,unichar_t ch) {
+ GInsCharSetChar(ch);
+}
+
+extern GImage splashimage;
+static GWindow splashw;
+static GTimer *autosave_timer, *splasht;
+static GFont *splash_font, *splash_italic;
+static int as,fh, linecnt;
+static unichar_t msg[350];
+static unichar_t *lines[20], *is, *ie;
+
+void ShowAboutScreen(void) {
+ static int first=1;
+
+ if ( first ) {
+ GDrawResize(splashw,splashimage.u.image->width,splashimage.u.image->height+linecnt*fh);
+ first = false;
+ }
+ if ( splasht!=NULL )
+ GDrawCancelTimer(splasht);
+ splasht=NULL;
+ GDrawSetVisible(splashw,true);
+}
+
+static void SplashLayout() {
+ unichar_t *start, *pt, *lastspace;
+ extern const char *source_modtime_str;
+ extern const char *source_version_str;
+
+ uc_strcpy(msg, "When my father finished his book on Renaissance printing (The Craft of Printing and the Publication of Shakespeare's Works) he told me that I would have to write the chapter on computer typography. This is my attempt to do so.");
+
+ GDrawSetFont(splashw,splash_font);
+ linecnt = 0;
+ lines[linecnt++] = msg-1;
+ for ( start = msg; *start!='\0'; start = pt ) {
+ lastspace = NULL;
+ for ( pt=start; ; ++pt ) {
+ if ( *pt==' ' || *pt=='\0' ) {
+ if ( GDrawGetTextWidth(splashw,start,pt-start,NULL)<splashimage.u.image->width-10 )
+ lastspace = pt;
+ else
+ break;
+ if ( *pt=='\0' )
+ break;
+ }
+ }
+ if ( lastspace!=NULL )
+ pt = lastspace;
+ lines[linecnt++] = pt;
+ if ( *pt ) ++pt;
+ }
+ uc_strcpy(pt, " FontForge used to be named PfaEdit.");
+ pt += u_strlen(pt);
+ lines[linecnt++] = pt;
+ uc_strcpy(pt," Version: ");;
+ uc_strcat(pt,source_modtime_str);
+ uc_strcat(pt," (");
+ uc_strcat(pt,source_version_str);
+#ifdef FONTFORGE_CONFIG_TYPE3
+ uc_strcat(pt,"-ML");
+#endif
+ uc_strcat(pt,")");
+ lines[linecnt++] = pt+u_strlen(pt);
+ lines[linecnt] = NULL;
+ is = u_strchr(msg,'(');
+ ie = u_strchr(msg,')');
+}
+
+void DelayEvent(void (*func)(void *), void *data) {
+ struct delayed_event *info = gcalloc(1,sizeof(struct delayed_event));
+
+ info->data = data;
+ info->func = func;
+ GDrawRequestTimer(splashw,100,0,info);
+}
+
+static void DoDelayedEvents(GEvent *event) {
+ GTimer *t = event->u.timer.timer;
+ struct delayed_event *info = (struct delayed_event *) (event->u.timer.userdata);
+
+ if ( info!=NULL ) {
+ (info->func)(info->data);
+ free(info);
+ }
+ GDrawCancelTimer(t);
+}
+
+static int splash_e_h(GWindow gw, GEvent *event) {
+ static int splash_cnt;
+ GRect old;
+ int i, y, x;
+ static char *foolishness[] = {
+/* GT: These strings are for fun. If they are offensive of incomprehensible */
+/* GT: simply translate them as something dull like: "FontForge" */
+ N_("A free press discriminates\nagainst the illiterate."),
+ N_("A free press discriminates\nagainst the illiterate."),
+ N_("Gaudeamus Ligature!"),
+ N_("Gaudeamus Ligature!"),
+ N_("In the beginning was the letter..."),
+ };
+
+ if ( event->type == et_expose ) {
+ GDrawPushClip(gw,&event->u.expose.rect,&old);
+ GDrawDrawImage(gw,&splashimage,NULL,0,0);
+ GDrawSetFont(gw,splash_font);
+ y = splashimage.u.image->height + as + fh/2;
+ for ( i=1; i<linecnt; ++i ) {
+ if ( is>=lines[i-1]+1 && is<lines[i] ) {
+ x = 8+GDrawDrawText(gw,8,y,lines[i-1]+1,is-lines[i-1]-1,NULL,0x000000);
+ GDrawSetFont(gw,splash_italic);
+ GDrawDrawText(gw,x,y,is,lines[i]-is,NULL,0x000000);
+ } else if ( ie>=lines[i-1]+1 && ie<lines[i] ) {
+ x = 8+GDrawDrawText(gw,8,y,lines[i-1]+1,ie-lines[i-1]-1,NULL,0x000000);
+ GDrawSetFont(gw,splash_font);
+ GDrawDrawText(gw,x,y,ie,lines[i]-ie,NULL,0x000000);
+ } else
+ GDrawDrawText(gw,8,y,lines[i-1]+1,lines[i]-lines[i-1]-1,NULL,0x000000);
+ y += fh;
+ }
+ GDrawPopClip(gw,&old);
+ } else if ( event->type == et_map ) {
+ splash_cnt = 0;
+ } else if ( event->type == et_timer && event->u.timer.timer==autosave_timer ) {
+ DoAutoSaves();
+ } else if ( event->type == et_timer && event->u.timer.timer==splasht ) {
+ if ( ++splash_cnt==1 )
+ GDrawResize(gw,splashimage.u.image->width,splashimage.u.image->height-24);
+ else if ( splash_cnt==2 )
+ GDrawResize(gw,splashimage.u.image->width,splashimage.u.image->height);
+ else if ( splash_cnt>=7 ) {
+ GGadgetEndPopup();
+ GDrawSetVisible(gw,false);
+ GDrawCancelTimer(splasht);
+ splasht = NULL;
+ }
+ } else if ( event->type == et_timer ) {
+ DoDelayedEvents(event);
+ } else if ( event->type==et_char || event->type==et_mousedown ||
+ event->type==et_close ) {
+ GGadgetEndPopup();
+ GDrawSetVisible(gw,false);
+ } else if ( event->type==et_mousemove ) {
+ GGadgetPreparePopup8(gw,_(foolishness[rand()%(sizeof(foolishness)/sizeof(foolishness[0]))]) );
+ }
+return( true );
+}
+
+static void AddR(char *prog, char *name, char *val ) {
+ char *full = galloc(strlen(name)+strlen(val)+4);
+ strcpy(full,name);
+ strcat(full,": ");
+ strcat(full,val);
+ GResourceAddResourceString(full,prog);
+}
+#endif
+
+#ifndef LUA_FF_LIB
+#ifdef FONTFORGE_CONFIG_NO_WINDOWING_UI
+static char * GResourceProgramDir=NULL;
+#endif
+
+static char *getLocaleDir(void) {
+ static char *sharedir=NULL;
+ static int set=false;
+ char *pt;
+ int len;
+
+ if ( set )
+return( sharedir );
+
+ set = true;
+ pt = strstr(GResourceProgramDir,"/bin");
+ if ( pt==NULL ) {
+#ifdef PREFIX
+return( PREFIX "/share/locale" );
+#else
+ pt = GResourceProgramDir + strlen(GResourceProgramDir);
+#endif
+ }
+ len = (pt-GResourceProgramDir)+strlen("/share/locale")+1;
+ sharedir = galloc(len);
+ strncpy(sharedir,GResourceProgramDir,pt-GResourceProgramDir);
+ strcpy(sharedir+(pt-GResourceProgramDir),"/share/locale");
+return( sharedir );
+}
+#endif
+
+#if defined(__Mac) && !(defined(FONTFORGE_CONFIG_NO_WINDOWING_UI) || defined( X_DISPLAY_MISSING ))
+static int uses_local_x(int argc,char **argv) {
+ int i;
+ char *arg;
+
+ for ( i=1; i<argc; ++i ) {
+ arg = argv[i];
+ if ( *arg=='-' ) {
+ if ( arg[0]=='-' && arg[1]=='-' )
+ ++arg;
+ if ( strcmp(arg,"-display")==0 )
+return( false ); /* we use a different display */
+ if ( strcmp(arg,"-c")==0 )
+return( false ); /* we use a script string, no x display at all */
+ if ( strcmp(arg,"-script")==0 )
+return( false ); /* we use a script, no x display at all */
+ if ( strcmp(arg,"-")==0 )
+return( false ); /* script on stdin */
+ } else {
+ /* Is this argument a script file ? */
+ FILE *temp = fopen(argv[i],"r");
+ char buffer[200];
+ if ( temp==NULL )
+return( true ); /* not a script file, so need local local X */
+ buffer[0] = '\0';
+ fgets(buffer,sizeof(buffer),temp);
+ fclose(temp);
+ if ( buffer[0]=='#' && buffer[1]=='!' &&
+ (strstr(buffer,"pfaedit")!=NULL || strstr(buffer,"fontforge")!=NULL )) {
+return( false ); /* is a script file, so no need for X */
+
+return( true ); /* not a script, so needs X */
+ }
+ }
+ }
+return( true );
+}
+#endif
+
+#ifndef LUA_FF_LIB
+int FontForgeMain( int argc, char **argv ) {
+ extern const char *source_modtime_str;
+ const char *load_prefs = getenv("FONTFORGE_LOADPREFS");
+#if !defined( FONTFORGE_CONFIG_NO_WINDOWING_UI )
+ int i;
+ extern int splash;
+ int recover=1;
+#endif
+#ifdef FONTFORGE_CONFIG_GDRAW
+ int any;
+ int next_recent=0;
+ GRect pos;
+ GWindowAttrs wattrs;
+ char *display = NULL;
+ FontRequest rq;
+ static unichar_t times[] = { 't', 'i', 'm', 'e', 's',',','c','l','e','a','r','l','y','u',',','u','n','i','f','o','n','t', '\0' };
+ int ds, ld;
+#elif defined( FONTFORGE_CONFIG_GTK )
+ GtkWidget *splashw;
+ GtkWidget *notices;
+ gchar *home_dir, *rc_path;
+ struct argcontext args;
+#elif defined( FONTFORGE_CONFIG_NO_WINDOWING_UI )
+#else
+# error FontForge has not been properly configured.
+/* One of FONTFORGE_CONFIG_GDRAW, FONTFORGE_CONFIG_GTK, FONTFORGE_CONFIG_NO_WINDOWING_UI */
+/* must be set */
+#endif
+
+#ifdef FONTFORGE_CONFIG_TYPE3
+ fprintf( stderr, "Copyright (c) 2000-2007 by George Williams.\n Executable based on sources from %s-ML.\n",
+ source_modtime_str );
+#else
+ fprintf( stderr, "Copyright (c) 2000-2007 by George Williams.\n Executable based on sources from %s.\n",
+ source_modtime_str );
+#endif
+ setlocale(LC_ALL,"");
+ localeinfo = *localeconv();
+ coord_sep = ",";
+ if ( *localeinfo.decimal_point=='.' ) coord_sep=",";
+ else if ( *localeinfo.decimal_point!='.' ) coord_sep=" ";
+ if ( getenv("FF_SCRIPT_IN_LATIN1") ) use_utf8_in_script=false;
+
+#if !defined( FONTFORGE_CONFIG_NO_WINDOWING_UI )
+ GResourceSetProg(argv[0]);
+#endif
+#if defined( FONTFORGE_CONFIG_GTK )
+ gtk_set_locale ();
+
+ home_dir = (gchar*) g_get_home_dir();
+ rc_path = g_strdup_printf("%s/.fontforgerc", home_dir);
+ gtk_rc_add_default_file(rc_path);
+ g_free(rc_path);
+
+ gtk_init (&argc, &argv);
+
+ add_pixmap_directory (PIXMAP_DIR);
+#endif
+
+#if !defined( FONTFORGE_CONFIG_NO_WINDOWING_UI )
+ GMenuSetShortcutDomain("FontForge-MenuShortCuts");
+#endif
+ bind_textdomain_codeset("FontForge-MenuShortCuts","UTF-8");
+ bindtextdomain("FontForge-MenuShortCuts", getLocaleDir());
+ bind_textdomain_codeset("FontForge","UTF-8");
+ bindtextdomain("FontForge", getLocaleDir());
+ textdomain("FontForge");
+#if !defined( FONTFORGE_CONFIG_GTK )
+#if !defined( FONTFORGE_CONFIG_NO_WINDOWING_UI )
+ GResourceUseGetText();
+#endif
+#endif
+
+#if defined(__Mac) && !(defined(FONTFORGE_CONFIG_NO_WINDOWING_UI) || defined( X_DISPLAY_MISSING ))
+ /* Start X if they haven't already done so. Well... try anyway */
+ /* Must be before we change DYLD_LIBRARY_PATH or X won't start */
+ if ( uses_local_x(argc,argv) && getenv("DISPLAY")==NULL ) {
+ system( "open /Applications/Utilities/X11.app/" );
+ setenv("DISPLAY",":0.0",0);
+ }
+#endif
+
+ SetDefaults();
+ if ( load_prefs!=NULL && strcasecmp(load_prefs,"Always")==0 )
+ LoadPrefs();
+ else
+ PrefDefaultEncoding();
+ if ( default_encoding==NULL )
+ default_encoding=FindOrMakeEncoding("ISO8859-1");
+ if ( default_encoding==NULL )
+ default_encoding=&custom; /* In case iconv is broken */
+ initlibrarysearchpath();
+ initrand();
+ initadobeenc();
+ inituninameannot();
+ CheckIsScript(argc,argv); /* Will run the script and exit if it is a script */
+ /* If there is no UI, there is always a script */
+ /* and we will never return from the above */
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( load_prefs==NULL ||
+ (strcasecmp(load_prefs,"Always")!=0 && /* Already loaded */
+ strcasecmp(load_prefs,"Never")!=0 ))
+ LoadPrefs();
+ for ( i=1; i<argc; ++i ) {
+ char *pt = argv[i];
+ if ( pt[0]=='-' && pt[1]=='-' )
+ ++pt;
+# if defined( FONTFORGE_CONFIG_GTK )
+ if ( strcmp(pt,"-sync")==0 )
+ gwwv_x11_synchronize();
+# else
+ if ( strcmp(pt,"-sync")==0 )
+ GResourceAddResourceString("Gdraw.Synchronize: true",argv[0]);
+ else if ( strcmp(pt,"-depth")==0 && i<argc-1 )
+ AddR(argv[0],"Gdraw.Depth", argv[++i]);
+ else if ( strcmp(pt,"-vc")==0 && i<argc-1 )
+ AddR(argv[0],"Gdraw.VisualClass", argv[++i]);
+ else if ( (strcmp(pt,"-cmap")==0 || strcmp(pt,"-colormap")==0) && i<argc-1 )
+ AddR(argv[0],"Gdraw.Colormap", argv[++i]);
+ else if ( (strcmp(pt,"-dontopenxdevices")==0) )
+ AddR(argv[0],"Gdraw.DontOpenXDevices", "true");
+ else if ( strcmp(pt,"-keyboard")==0 && i<argc-1 )
+ AddR(argv[0],"Gdraw.Keyboard", argv[++i]);
+ else if ( strcmp(pt,"-display")==0 && i<argc-1 )
+ display = argv[++i];
+# endif
+# if MyMemory
+ else if ( strcmp(pt,"-memory")==0 )
+ __malloc_debug(5);
+# endif
+ else if ( strcmp(pt,"-nosplash")==0 )
+ splash = 0;
+ else if ( strcmp(pt,"-recover")==0 && i<argc-1 ) {
+ ++i;
+ if ( strcmp(argv[i],"none")==0 )
+ recover=0;
+ else if ( strcmp(argv[i],"clean")==0 )
+ recover= -1;
+ else if ( strcmp(argv[i],"auto")==0 )
+ recover= 1;
+ else {
+ fprintf( stderr, "Invalid argument to -recover, must be none, auto or clean\n" );
+ dousage();
+ }
+ } else if ( strcmp(pt,"-recover=none")==0 ) {
+ recover = 0;
+ } else if ( strcmp(pt,"-recover=clean")==0 ) {
+ recover = -1;
+ }
+ else if ( strcmp(pt,"-help")==0 )
+ dohelp();
+ else if ( strcmp(pt,"-usage")==0 )
+ dousage();
+ else if ( strcmp(pt,"-version")==0 )
+ doversion();
+ }
+
+# ifdef FONTFORGE_CONFIG_GDRAW
+ GDrawCreateDisplays(display,argv[0]);
+ default_background = GDrawGetDefaultBackground(screen_display);
+ InitToolIconClut(default_background);
+# endif
+ InitCursors();
+
+# ifdef FONTFORGE_CONFIG_GTK
+ if ( splash ) {
+ splashw = create_FontForgeSplash ();
+ splash_window_tooltip_fun( splashw );
+ notices = lookup_widget(splashw,"Notices");
+ if ( notices!=NULL )
+ gtk_widget_hide(notices);
+ gtk_widget_show (splashw);
+ }
+
+ gtk_timeout_add(30*1000,_DoAutoSaves,NULL); /* Check for autosave every 30 seconds */
+
+ args.argc = argc; args.argv = argv; args.recover = recover;
+ gtk_timeout_add(100,ParseArgs,&args);
+ /* Parse arguments within the main loop */
+
+ gtk_main ();
+# else /* Gdraw */
+ /* the splash screen used not to have a title bar (wam_nodecor) */
+ /* but I found I needed to know how much the window manager moved */
+ /* the window around, which I can determine if I have a positioned */
+ /* decorated window created at the begining */
+ /* Actually I don't care any more */
+ wattrs.mask = wam_events|wam_cursor|wam_bordwidth|wam_backcol|wam_positioned|wam_utf8_wtitle|wam_isdlg;
+ wattrs.event_masks = ~(1<<et_charup);
+ wattrs.positioned = 1;
+ wattrs.cursor = ct_pointer;
+ wattrs.utf8_window_title = "FontForge";
+ wattrs.border_width = 2;
+ wattrs.background_color = 0xffffff;
+ wattrs.is_dlg = true;
+ pos.x = pos.y = 200;
+ pos.width = splashimage.u.image->width;
+ pos.height = splashimage.u.image->height-56; /* 54 */
+ splashw = GDrawCreateTopWindow(NULL,&pos,splash_e_h,NULL,&wattrs);
+ memset(&rq,0,sizeof(rq));
+ rq.family_name = times;
+ rq.point_size = 12;
+ rq.weight = 400;
+ splash_font = GDrawInstanciateFont(NULL,&rq);
+ rq.style = fs_italic;
+ splash_italic = GDrawInstanciateFont(NULL,&rq);
+ GDrawSetFont(splashw,splash_font);
+ GDrawFontMetrics(splash_font,&as,&ds,&ld);
+ fh = as+ds+ld;
+ SplashLayout();
+ if ( splash ) {
+ GDrawSetVisible(splashw,true);
+ GDrawSync(NULL);
+ GDrawProcessPendingEvents(NULL);
+ GDrawProcessPendingEvents(NULL);
+ splasht = GDrawRequestTimer(splashw,1000,1000,NULL);
+ }
+ autosave_timer=GDrawRequestTimer(splashw,60*1000,30*1000,NULL);
+
+ GDrawProcessPendingEvents(NULL);
+ GDrawSetBuildCharHooks(BuildCharHook,InsCharHook);
+
+ any = 0;
+ if ( recover==-1 )
+ CleanAutoRecovery();
+ else if ( recover )
+ any = DoAutoRecovery();
+
+ for ( i=1; i<argc; ++i ) {
+ char buffer[1025];
+ char *pt = argv[i];
+
+ GDrawProcessPendingEvents(NULL);
+ if ( pt[0]=='-' && pt[1]=='-' )
+ ++pt;
+ if ( strcmp(pt,"-new")==0 ) {
+ FontNew();
+ any = 1;
+# if HANYANG
+ } else if ( strcmp(pt,"-newkorean")==0 ) {
+ MenuNewComposition(NULL,NULL,NULL);
+ any = 1;
+# endif
+ } else if ( strcmp(pt,"-last")==0 ) {
+ if ( next_recent<RECENT_MAX && RecentFiles[next_recent]!=NULL )
+ if ( ViewPostscriptFont(RecentFiles[next_recent++]))
+ any = 1;
+ } else if ( strcmp(pt,"-sync")==0 || strcmp(pt,"-memory")==0 ||
+ strcmp(pt,"-nosplash")==0 || strcmp(pt,"-recover=none")==0 ||
+ strcmp(pt,"-recover=clean")==0 || strcmp(pt,"-recover=auto")==0 ||
+ strcmp(pt,"-dontopenxdevices")==0 )
+ /* Already done, needed to be before display opened */;
+ else if ( (strcmp(pt,"-depth")==0 || strcmp(pt,"-vc")==0 ||
+ strcmp(pt,"-cmap")==0 || strcmp(pt,"-colormap")==0 ||
+ strcmp(pt,"-keyboard")==0 ||
+ strcmp(pt,"-display")==0 || strcmp(pt,"-recover")==0 ) &&
+ i<argc-1 )
+ ++i; /* Already done, needed to be before display opened */
+ else {
+ GFileGetAbsoluteName(argv[i],buffer,sizeof(buffer));
+ if ( GFileIsDir(buffer)) {
+ char *fname;
+ fname = galloc(strlen(buffer)+strlen("/glyphs/contents.plist")+1);
+ strcpy(fname,buffer); strcat(fname,"/glyphs/contents.plist");
+ if ( GFileExists(fname)) {
+ /* It's probably a Unified Font Object directory */
+ free(fname);
+ if ( ViewPostscriptFont(buffer) )
+ any = 1;
+ } else {
+ strcpy(fname,buffer); strcat(fname,"/font.props");
+ if ( GFileExists(fname)) {
+ /* It's probably a sf dir collection */
+ free(fname);
+ if ( ViewPostscriptFont(buffer) )
+ any = 1;
+ } else {
+ free(fname);
+ if ( buffer[strlen(buffer)-1]!='/' ) {
+ /* If dirname doesn't end in "/" we'll be looking in parent dir */
+ buffer[strlen(buffer)+1]='\0';
+ buffer[strlen(buffer)] = '/';
+ }
+ fname = GetPostscriptFontName(buffer,false);
+ if ( fname!=NULL )
+ ViewPostscriptFont(fname);
+ any = 1; /* Even if we didn't get a font, don't bring up dlg again */
+ free(fname);
+ }
+ }
+ } else if ( ViewPostscriptFont(buffer)!=0 )
+ any = 1;
+ }
+ }
+ if ( !any )
+ MenuOpen(NULL,NULL,NULL);
+ GDrawEventLoop(NULL);
+# endif
+#endif
+return( 0 );
+}
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/stemdb.c b/Build/source/libs/luafontforge/fontforge/fontforge/stemdb.c
new file mode 100644
index 00000000000..2e608c71703
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/stemdb.c
@@ -0,0 +1,2428 @@
+/* Copyright (C) 2005-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include "edgelist2.h"
+#include "stemdb.h"
+#include <math.h>
+
+/* A diagonal end is like the top or bottom of a slash. Should we add a vertical stem at the end? */
+/* A diagonal corner is like the bottom of circumflex. Should we add a horizontal stem */
+int hint_diagonal_ends = 0,
+ hint_diagonal_intersections = 0,
+ hint_bounding_boxes = 1;
+
+static const double slope_error = .05;
+ /* If the dot vector of a slope and the normal of another slope is less */
+ /* than this error, then we say they are close enough to be colinear */
+static double dist_error_hv = 3;
+static double dist_error_diag = 6;
+ /* It's easy to get horizontal/vertical lines aligned properly */
+ /* it is more difficult to get diagonal ones done */
+ /* The "A" glyph in Apple's Times.dfont(Roman) is off by 6 in one spot */
+
+struct st {
+ Spline *s;
+ double st, lt;
+};
+
+static int SplineFigureOpticalSlope(Spline *s,int start_at_from,BasePoint *dir) {
+ /* Sometimes splines have tiny control points, and to the eye the slope */
+ /* of the spline has nothing to do with that specified by the cps. */
+ /* So see if the spline is straightish and figure the slope based on */
+ /* some average direction */
+ /* dir is a input output parameter. */
+ /* it should be initialized to the unit vector determined by the appropriate cp */
+ /* if the function returns true, it will be set to a unit vector in the average direction */
+ BasePoint pos, *base, average_dir, normal;
+ double t, len, incr, off;
+
+ if ( start_at_from ) {
+ incr = -.1;
+ base = &s->from->me;
+ } else {
+ incr = .1;
+ base = &s->to->me;
+ }
+
+ t = .5-incr;
+ memset(&average_dir,0,sizeof(average_dir));
+ while ( t>0 && t<1.0 ) {
+ pos.x = ((s->splines[0].a*t+s->splines[0].b)*t+s->splines[0].c)*t+s->splines[0].d;
+ pos.y = ((s->splines[1].a*t+s->splines[1].b)*t+s->splines[1].c)*t+s->splines[1].d;
+
+ average_dir.x += (pos.x-base->x); average_dir.y += (pos.y-base->y);
+ t += incr;
+ }
+
+ len = sqrt(average_dir.x*average_dir.x + average_dir.y*average_dir.y);
+ if ( len==0 )
+return( false );
+ average_dir.x /= len; average_dir.y /= len;
+ normal.x = average_dir.y; normal.y = - average_dir.x;
+
+ t = .5-incr;
+ while ( t>0 && t<1.0 ) {
+ pos.x = ((s->splines[0].a*t+s->splines[0].b)*t+s->splines[0].c)*t+s->splines[0].d;
+ pos.y = ((s->splines[1].a*t+s->splines[1].b)*t+s->splines[1].c)*t+s->splines[1].d;
+ off = (pos.x-base->x)*normal.x + (pos.y-base->y)*normal.y;
+ if ( off<-dist_error_hv || off>dist_error_hv )
+return( false );
+ t += incr;
+ }
+
+ off = dir->x*normal.x + dir->y*normal.y;
+ if ( off<slope_error ) {
+ /* prefer the direction which is closer to horizontal/vertical */
+ double dx, dy, ax, ay, d, a;
+ if ( (dx=dir->x)<0 ) dx = -dx;
+ if ( (dy=dir->y)<0 ) dy = -dy;
+ d = (dx<dy) ? dx : dy;
+ if ( (ax=average_dir.x)<0 ) ax = -ax;
+ if ( (ay=average_dir.y)<0 ) ay = -ay;
+ a = (ax<ay) ? ax : ay;
+ if ( d<a )
+return( false );
+ }
+
+ *dir = average_dir;
+return( true );
+}
+
+static void PointInit(struct glyphdata *gd,SplinePoint *sp, SplineSet *ss) {
+ struct pointdata *pd;
+ double len;
+
+ if ( sp->ttfindex==0xffff || sp->ttfindex==0xfffe )
+return;
+ pd = &gd->points[sp->ttfindex];
+ pd->sp = sp;
+ pd->ss = ss;
+
+ if ( sp->next==NULL ) {
+ pd->nextunit.x = ss->first->me.x - sp->me.x;
+ pd->nextunit.y = ss->first->me.y - sp->me.y;
+ pd->nextlinear = true;
+ } else if ( sp->next->knownlinear ) {
+ pd->nextunit.x = sp->next->to->me.x - sp->me.x;
+ pd->nextunit.y = sp->next->to->me.y - sp->me.y;
+ pd->nextlinear = true;
+ } else if ( sp->nonextcp ) {
+ pd->nextunit.x = sp->next->to->prevcp.x - sp->me.x;
+ pd->nextunit.y = sp->next->to->prevcp.y - sp->me.y;
+ } else {
+ pd->nextunit.x = sp->nextcp.x - sp->me.x;
+ pd->nextunit.y = sp->nextcp.y - sp->me.y;
+ }
+ len = sqrt(pd->nextunit.x*pd->nextunit.x + pd->nextunit.y*pd->nextunit.y);
+ if ( len==0 )
+ pd->nextzero = true;
+ else {
+ pd->nextlen = len;
+ pd->nextunit.x /= len;
+ pd->nextunit.y /= len;
+ if ( sp->next!=NULL && !sp->next->knownlinear )
+ SplineFigureOpticalSlope(sp->next,true,&pd->nextunit);
+ if ( pd->nextunit.x<slope_error && pd->nextunit.x>-slope_error ) {
+ pd->nextunit.x = 0; pd->nextunit.y = pd->nextunit.y>0 ? 1 : -1;
+ } else if ( pd->nextunit.y<slope_error && pd->nextunit.y>-slope_error ) {
+ pd->nextunit.y = 0; pd->nextunit.x = pd->nextunit.x>0 ? 1 : -1;
+ }
+ if ( pd->nextunit.y==0 ) pd->next_hor = true;
+ else if ( pd->nextunit.x==0 ) pd->next_ver = true;
+ }
+
+ if ( sp->prev==NULL ) {
+ pd->prevunit.x = ss->last->me.x - sp->me.x;
+ pd->prevunit.y = ss->last->me.y - sp->me.y;
+ pd->prevlinear = true;
+ } else if ( sp->prev->knownlinear ) {
+ pd->prevunit.x = sp->prev->from->me.x - sp->me.x;
+ pd->prevunit.y = sp->prev->from->me.y - sp->me.y;
+ pd->prevlinear = true;
+ } else if ( sp->noprevcp ) {
+ pd->prevunit.x = sp->prev->from->nextcp.x - sp->me.x;
+ pd->prevunit.y = sp->prev->from->nextcp.y - sp->me.y;
+ } else {
+ pd->prevunit.x = sp->prevcp.x - sp->me.x;
+ pd->prevunit.y = sp->prevcp.y - sp->me.y;
+ }
+ len = sqrt(pd->prevunit.x*pd->prevunit.x + pd->prevunit.y*pd->prevunit.y);
+ if ( len==0 )
+ pd->prevzero = true;
+ else {
+ pd->prevlen = len;
+ pd->prevunit.x /= len;
+ pd->prevunit.y /= len;
+ if ( sp->prev!=NULL && !sp->prev->knownlinear )
+ SplineFigureOpticalSlope(sp->prev,false,&pd->prevunit);
+ if ( pd->prevunit.x<slope_error && pd->prevunit.x>-slope_error ) {
+ pd->prevunit.x = 0; pd->prevunit.y = pd->prevunit.y>0 ? 1 : -1;
+ } else if ( pd->prevunit.y<slope_error && pd->prevunit.y>-slope_error ) {
+ pd->prevunit.y = 0; pd->prevunit.x = pd->prevunit.x>0 ? 1 : -1;
+ }
+ if ( pd->prevunit.y==0 ) pd->prev_hor = true;
+ else if ( pd->prevunit.x==0 ) pd->prev_ver = true;
+ }
+ {
+ double same = pd->prevunit.x*pd->nextunit.x + pd->prevunit.y*pd->nextunit.y;
+ if ( same<-.95 )
+ pd->colinear = true;
+ }
+ if ( hint_diagonal_intersections ) {
+ if ( pd->prev_hor || pd->prev_ver )
+ /* It IS horizontal or vertical. No need to fake it */;
+ else if ( RealNear(pd->nextunit.x,-pd->prevunit.x) &&
+ RealNear(pd->nextunit.y,pd->prevunit.y) && !pd->nextzero)
+ pd->symetrical_h = true;
+ else if ( RealNear(pd->nextunit.y,-pd->prevunit.y) &&
+ RealNear(pd->nextunit.x,pd->prevunit.x) && !pd->nextzero)
+ pd->symetrical_v = true;
+ }
+}
+
+static int BBoxIntersectsLine(Spline *s,Spline *line) {
+ double t,x,y;
+ DBounds b;
+
+ b.minx = b.maxx = s->from->me.x;
+ b.miny = b.maxy = s->from->me.y;
+ if ( s->to->me.x<b.minx ) b.minx = s->to->me.x;
+ else if ( s->to->me.x>b.maxx ) b.maxx = s->to->me.x;
+ if ( s->to->me.y<b.miny ) b.miny = s->to->me.y;
+ else if ( s->to->me.y>b.maxy ) b.maxy = s->to->me.y;
+ if ( s->to->prevcp.x<b.minx ) b.minx = s->to->prevcp.x;
+ else if ( s->to->prevcp.x>b.maxx ) b.maxx = s->to->prevcp.x;
+ if ( s->to->prevcp.y<b.miny ) b.miny = s->to->prevcp.y;
+ else if ( s->to->prevcp.y>b.maxy ) b.maxy = s->to->prevcp.y;
+ if ( s->from->nextcp.x<b.minx ) b.minx = s->from->nextcp.x;
+ else if ( s->from->nextcp.x>b.maxx ) b.maxx = s->from->nextcp.x;
+ if ( s->from->nextcp.y<b.miny ) b.miny = s->from->nextcp.y;
+ else if ( s->from->nextcp.y>b.maxy ) b.maxy = s->from->nextcp.y;
+
+ if ( line->splines[0].c!=0 ) {
+ t = (b.minx-line->splines[0].d)/line->splines[0].c;
+ y = line->splines[1].c*t+line->splines[1].d;
+ if ( y>=b.miny && y<=b.maxy )
+return( true );
+ t = (b.maxx-line->splines[0].d)/line->splines[0].c;
+ y = line->splines[1].c*t+line->splines[1].d;
+ if ( y>=b.miny && y<=b.maxy )
+return( true );
+ }
+ if ( line->splines[1].c!=0 ) {
+ t = (b.miny-line->splines[1].d)/line->splines[1].c;
+ x = line->splines[0].c*t+line->splines[0].d;
+ if ( x>=b.minx && x<=b.maxx )
+return( true );
+ t = (b.maxy-line->splines[1].d)/line->splines[1].c;
+ x = line->splines[0].c*t+line->splines[0].d;
+ if ( x>=b.minx && x<=b.maxx )
+return( true );
+ }
+return( false );
+}
+
+static int stcmp(const void *_p1, const void *_p2) {
+ const struct st *stpt1 = _p1, *stpt2 = _p2;
+ if ( stpt1->lt>stpt2->lt )
+return( 1 );
+ else if ( stpt1->lt<stpt2->lt )
+return( -1 );
+
+return( 0 );
+}
+
+static int LineType(struct st *st,int i, int cnt,Spline *line) {
+ SplinePoint *sp;
+ BasePoint nextcp, prevcp, here;
+ double dn, dp;
+
+ if ( st[i].st>.01 && st[i].st<.99 )
+return( 0 ); /* Not near an end-point, just a normal line */
+ if ( i+1>=cnt )
+return( 0 ); /* No following spline */
+ if ( st[i+1].st>.01 && st[i+1].st<.99 )
+return( 0 ); /* Following spline not near an end-point, can't */
+ /* match to this one, just a normal line */
+ if ( st[i].st<.5 && st[i+1].st>.5 ) {
+ if ( st[i+1].s->to->next!=st[i].s )
+return( 0 );
+ sp = st[i].s->from;
+ } else if ( st[i].st>.5 && st[i+1].st<.5 ) {
+ if ( st[i].s->to->next!=st[i+1].s )
+return( 0 );
+ sp = st[i].s->to;
+ } else
+return( 0 );
+
+ if ( !sp->nonextcp )
+ nextcp = sp->nextcp;
+ else
+ nextcp = sp->next->to->me;
+ if ( !sp->noprevcp )
+ prevcp = sp->prevcp;
+ else
+ prevcp = sp->prev->from->me;
+ here.x = line->splines[0].c*(st[i].st+st[i+1].st)/2 + line->splines[0].d;
+ here.y = line->splines[1].c*(st[i].st+st[i+1].st)/2 + line->splines[1].d;
+
+ nextcp.x -= here.x; nextcp.y -= here.y;
+ prevcp.x -= here.x; prevcp.y -= here.y;
+
+ dn = nextcp.x*line->splines[1].c - nextcp.y*line->splines[0].c;
+ dp = prevcp.x*line->splines[1].c - prevcp.y*line->splines[0].c;
+ if ( dn*dp<0 ) /* splines away move on opposite sides of the line */
+return( 1 ); /* Treat this line and the next as one */
+ /* We assume that a rounding error gave us one erroneous intersection (or we went directly through the endpoint) */
+ else
+return( 2 ); /* Ignore both this line and the next */
+ /* Intersects both in a normal fashion */
+}
+
+static int MonotonicOrder(Spline **sspace,Spline *line,struct st *stspace) {
+ Spline *s;
+ int i,j,k,cnt;
+ BasePoint pts[9];
+ extended lts[10], sts[10];
+
+ for ( i=j=0; (s=sspace[j])!=NULL; ++j ) {
+ if ( BBoxIntersectsLine(s,line) ) {
+ /* Lines parallel to the direction we are testing just get in the */
+ /* way and don't add any useful info */
+ if ( s->islinear &&
+ RealNear(line->splines[0].c*s->splines[1].c,
+ line->splines[1].c*s->splines[0].c))
+ continue;
+ if ( SplinesIntersect(line,s,pts,lts,sts)<=0 )
+ continue;
+ for ( k=0; sts[k]!=-1; ++k ) {
+ if ( sts[k]>=0 && sts[k]<=1 ) {
+ stspace[i].s = s;
+ stspace[i].lt = lts[k];
+ stspace[i++].st = sts[k];
+ }
+ }
+ }
+ }
+ stspace[i].s = NULL;
+ cnt = i;
+ qsort(stspace,cnt,sizeof(struct st),stcmp);
+return( cnt );
+}
+
+static Spline *MonotonicFindAlong(Spline *line,struct st *stspace,int cnt,
+ Spline *findme, double *other_t) {
+ Spline *s;
+ int i;
+ int eo; /* I do horizontal/vertical by winding number */
+ /* But figuring winding number with respect to a */
+ /* diagonal line is hard. So I use even-odd */
+ /* instead. */
+
+ eo = 0;
+ for ( i=0; i<cnt; ++i ) {
+ s = stspace[i].s;
+ if ( s==findme ) {
+ if ( (eo&1) && i>0 ) {
+ *other_t = stspace[i-1].st;
+return( stspace[i-1].s );
+ } else if ( !(eo&1) && i+1<cnt ) {
+ *other_t = stspace[i+1].st;
+return( stspace[i+1].s );
+ }
+ fprintf( stderr, "MonotonicFindAlong: Ran out of intersections.\n" );
+return( NULL );
+ }
+ if ( i+1<cnt && stspace[i+1].s==findme )
+ ++eo;
+ else switch ( LineType(stspace,i,cnt,line) ) {
+ case 0: /* Normal spline */
+ ++eo;
+ break;
+ case 1: /* Intersects at end-point & next entry is other side */
+ ++eo; /* And the two sides continue in approximately the */
+ ++i; /* same direction */
+ break;
+ case 2: /* Intersects at end-point & next entry is other side */
+ ++i; /* And the two sides go in opposite directions */
+ break;
+ }
+ }
+ fprintf( stderr, "MonotonicFindAlong: Never found our spline.\n" );
+return( NULL );
+}
+
+static int MonotonicFindStemBounds(Spline *line,struct st *stspace,int cnt,
+ struct stemdata *stem ) {
+ int i,j;
+ int eo; /* I do horizontal/vertical by winding number */
+ /* But figuring winding number with respect to a */
+ /* diagonal line is hard. So I use even-odd */
+ /* instead. */
+ double pos, npos;
+
+ eo = 0;
+ for ( i=0; i<cnt; ++i ) {
+ pos = (line->splines[0].c*stspace[i].lt + line->splines[0].d - stem->left.x)*stem->l_to_r.x +
+ (line->splines[1].c*stspace[i].lt + line->splines[1].d - stem->left.y)*stem->l_to_r.y;
+ npos = 99999999;
+ if ( i+1<cnt )
+ npos = (line->splines[0].c*stspace[i+1].lt + line->splines[0].d - stem->left.x)*stem->l_to_r.x +
+ (line->splines[1].c*stspace[i+1].lt + line->splines[1].d - stem->left.y)*stem->l_to_r.y;
+
+ if ( fabs(npos)<fabs(pos) )
+ /* Then npos is closer to the base of the stem and is what we want*/;
+ else if ( pos>-dist_error_diag && pos<dist_error_diag ) {
+ if ( (eo&1) && i>0 )
+ j = i-1;
+ else if ( !(eo&1) && i+1<cnt )
+ j = i+1;
+ else
+return( false );
+ pos = (line->splines[0].c*stspace[j].lt + line->splines[0].d - stem->left.x)*stem->l_to_r.x +
+ (line->splines[1].c*stspace[j].lt + line->splines[1].d - stem->left.y)*stem->l_to_r.y;
+return( pos>=stem->width-dist_error_diag && pos<=stem->width+dist_error_diag );
+ }
+ if ( i+1<cnt && npos>-dist_error_diag && npos<dist_error_diag )
+ ++eo;
+ else switch ( LineType(stspace,i,cnt,line) ) {
+ case 0: /* Normal spline */
+ ++eo;
+ break;
+ case 1: /* Intersects at end-point & next entry is other side */
+ ++eo; /* And the two sides continue in approximately the */
+ ++i; /* same direction */
+ break;
+ case 2: /* Intersects at end-point & next entry is other side */
+ ++i; /* And the two sides go in opposite directions */
+ break;
+ }
+ }
+return( false );
+}
+
+static int MatchWinding(struct monotonic ** space,int i,int nw,int winding,int which) {
+ struct monotonic *m;
+ int j;
+
+ if (( nw<0 && winding>0 ) || (nw>0 && winding<0)) {
+ winding = nw;
+ for ( j=i-1; j>=0; --j ) {
+ m = space[j];
+ winding += ((&m->xup)[which] ? 1 : -1 );
+ if ( winding==0 )
+return( j );
+ }
+ } else {
+ winding = nw;
+ for ( j=i+1; space[j]!=NULL; ++j ) {
+ m = space[j];
+ winding += ((&m->xup)[which] ? 1 : -1 );
+ if ( winding==0 )
+return( j );
+ }
+ }
+return( -1 );
+}
+
+static Spline *FindMatchingHVEdge(struct glyphdata *gd, struct pointdata *pd,
+ int is_next, double *other_t ) {
+ double test, t;
+ int which;
+ Spline *s;
+ Monotonic *m;
+ int winding, nw, i,j;
+ struct monotonic **space;
+ BasePoint *dir, d, hv;
+ nw = 0;
+ /* Things are difficult if we go exactly through the point. Move off */
+ /* to the side a tiny bit and hope that doesn't matter */
+ if ( is_next==2 ) {
+ /* Consider the case of the bottom of the circumflex (or a chevron) */
+ /* Think of it as a flattend breve. It is symetrical and we want to */
+ /* note the vertical distance between the two points that define */
+ /* the bottom, so treat them as a funky stem */
+ /* \ \ / / */
+ /* \ \ / / */
+ /* \ \ / / */
+ /* \ + / */
+ /* \ / */
+ /* + */
+ hv.x = pd->symetrical_h ? 1.0 : 0.0;
+ hv.y = pd->symetrical_v ? 1.0 : 0.0;
+ dir = &hv;
+ t = .001;
+ s = pd->sp->next; /* Could just as easily be prev */
+ } else if ( is_next ) {
+ s = pd->sp->next;
+ t = .001;
+ dir = &pd->nextunit;
+ } else {
+ s = pd->sp->prev;
+ t = .999;
+ dir = &pd->prevunit;
+ }
+ if ( (d.x = dir->x)<0 ) d.x = -d.x;
+ if ( (d.y = dir->y)<0 ) d.y = -d.y;
+ which = d.x<d.y; /* closer to vertical */
+
+ if ( s==NULL ) /* Somehow we got an open contour? */
+return( NULL );
+
+ test = ((s->splines[which].a*t+s->splines[which].b)*t+s->splines[which].c)*t+s->splines[which].d;
+ MonotonicFindAt(gd->ms,which,test,space = gd->space);
+
+ winding = 0;
+ for ( i=0; space[i]!=NULL; ++i ) {
+ m = space[i];
+ nw = ((&m->xup)[which] ? 1 : -1 );
+ if ( m->s == s && t>=m->tstart && t<=m->tend )
+ break;
+ winding += nw;
+ }
+ if ( space[i]==NULL ) {
+ fprintf( stderr, "FindMatchinHVEdge didn't\n" );
+return( NULL );
+ }
+
+ j = MatchWinding(space,i,nw,winding,which);
+ if ( j!=-1 ) {
+ *other_t = space[j]->t;
+return( space[j]->s );
+ }
+
+ fprintf( stderr, "FindMatchingHVEdge fell into an impossible position\n" );
+return( NULL );
+}
+
+static void MakeVirtualLine(struct glyphdata *gd,BasePoint *perturbed,
+ BasePoint *dir,Spline *myline,SplinePoint *end1, SplinePoint *end2) {
+ BasePoint norm, absnorm;
+ double t1, t2;
+
+ if ( gd->stspace==NULL ) {
+ int i, cnt;
+ SplineSet *spl;
+ Spline *s, *first;
+ for ( i=0; i<2; ++i ) {
+ cnt = 0;
+ for ( spl=gd->sc->layers[ly_fore].splines; spl!=NULL; spl=spl->next ) {
+ first = NULL;
+ if ( spl->first->prev!=NULL ) {
+ for ( s=spl->first->next; s!=first; s=s->to->next ) {
+ if ( first==NULL ) first = s;
+ if ( i )
+ gd->sspace[cnt] = s;
+ ++cnt;
+ }
+ }
+ }
+ if ( !i ) {
+ gd->scnt = cnt;
+ gd->sspace = galloc((cnt+1)*sizeof(Spline *));
+ } else
+ gd->sspace[cnt] = NULL;
+ }
+ gd->stspace = galloc((3*cnt+2)*sizeof(struct st));
+ SplineCharFindBounds(gd->sc,&gd->size);
+ gd->size.minx -= 10; gd->size.miny -= 10;
+ gd->size.maxx += 10; gd->size.maxy += 10;
+ }
+
+ norm.x = -dir->y;
+ norm.y = dir->x;
+ absnorm = norm;
+ if ( absnorm.x<0 ) absnorm.x = -absnorm.x;
+ if ( absnorm.y<0 ) absnorm.y = -absnorm.y;
+
+ memset(myline,0,sizeof(*myline));
+ memset(end1,0,sizeof(*end1));
+ memset(end2,0,sizeof(*end2));
+ myline->knownlinear = myline->islinear = true;
+
+ if ( absnorm.x > absnorm.y ) {
+ /* Greater change in x than in y */
+ t1 = (gd->size.minx-perturbed->x)/norm.x;
+ t2 = (gd->size.maxx-perturbed->x)/norm.x;
+ myline->splines[0].d = gd->size.minx;
+ myline->splines[0].c = gd->size.maxx-gd->size.minx;
+ myline->splines[1].d = perturbed->y+t1*norm.y;
+ myline->splines[1].c = (t2-t1)*norm.y;
+ } else {
+ t1 = (gd->size.miny-perturbed->y)/norm.y;
+ t2 = (gd->size.maxy-perturbed->y)/norm.y;
+ myline->splines[1].d = gd->size.miny;
+ myline->splines[1].c = gd->size.maxy-gd->size.miny;
+ myline->splines[0].d = perturbed->x+t1*norm.x;
+ myline->splines[0].c = (t2-t1)*norm.x;
+ }
+ end1->me.x = myline->splines[0].d;
+ end2->me.x = myline->splines[0].d + myline->splines[0].c;
+ end1->me.y = myline->splines[1].d;
+ end2->me.y = myline->splines[1].d + myline->splines[1].c;
+ end1->nextcp = end1->prevcp = end1->me;
+ end2->nextcp = end2->prevcp = end2->me;
+ end1->nonextcp = end1->noprevcp = end2->nonextcp = end2->noprevcp = true;
+ end1->next = myline; end2->prev = myline;
+ myline->from = end1; myline->to = end2;
+}
+
+static Spline *FindMatchingEdge(struct glyphdata *gd, struct pointdata *pd,
+ int is_next, int only_hv ) {
+ BasePoint *dir, perturbed, diff;
+ Spline myline;
+ SplinePoint end1, end2;
+ double *other_t = is_next==2 ? &pd->both_e_t : is_next ? &pd->next_e_t : &pd->prev_e_t;
+ double t;
+ Spline *s;
+ int cnt;
+
+ if ( ( is_next && (pd->next_hor || pd->next_ver)) ||
+ ( !is_next && ( pd->prev_hor || pd->prev_ver )) ||
+ is_next == 2 )
+return( FindMatchingHVEdge(gd,pd,is_next,other_t));
+ if ( only_hv ) {
+ if (( is_next && ((pd->nextunit.y>-3*slope_error && pd->nextunit.y<3*slope_error) || (pd->nextunit.x>-3*slope_error && pd->nextunit.x<3*slope_error))) ||
+ ( !is_next && ((pd->prevunit.y>-3*slope_error && pd->prevunit.y<3*slope_error) || (pd->prevunit.x>-3*slope_error && pd->prevunit.x<3*slope_error))))
+ /* Close to vertical/horizontal */;
+ else
+return( NULL );
+ }
+
+ if ( is_next ) {
+ dir = &pd->nextunit;
+ t = .001;
+ s = pd->sp->next;
+ } else {
+ dir = &pd->prevunit;
+ t = .999;
+ s = pd->sp->prev;
+ }
+ if ( s==NULL )
+return( NULL );
+ diff.x = s->to->me.x-s->from->me.x; diff.y = s->to->me.y-s->from->me.y;
+ if ( diff.x<.03 && diff.x>-.03 && diff.y<.03 && diff.y>-.03 )
+return( NULL );
+
+ /* Don't base the line on the current point, we run into rounding errors */
+ /* where lines that should intersect it don't. Instead perturb it a tiny*/
+ /* bit in the direction along the spline */
+ forever {
+ perturbed.x = ((s->splines[0].a*t+s->splines[0].b)*t+s->splines[0].c)*t+s->splines[0].d;
+ perturbed.y = ((s->splines[1].a*t+s->splines[1].b)*t+s->splines[1].c)*t+s->splines[1].d;
+ if ( !RealWithin(perturbed.x,pd->sp->me.x,.01) ||
+ !RealWithin(perturbed.y,pd->sp->me.y,.01) )
+ break;
+ if ( t<.5 ) {
+ t *= 2;
+ if ( t>.5 )
+ break;
+ } else {
+ t = 1- 2*(1-t);
+ if ( t<.5 )
+ break;
+ }
+ }
+
+ MakeVirtualLine(gd,&perturbed,dir,&myline,&end1,&end2);
+ /* prev_e_t = next_e_t = both_e_t =. This is where these guys are set */
+ cnt = MonotonicOrder(gd->sspace,&myline,gd->stspace);
+return( MonotonicFindAlong(&myline,gd->stspace,cnt,s,other_t));
+}
+
+static int StillStem(struct glyphdata *gd, double t, int isnext,
+ BasePoint *pos, struct stemdata *stem ) {
+ Spline myline;
+ SplinePoint end1, end2;
+ int cnt, ret, neg;
+
+ neg = 0;
+ if ( stem->width<0 ) {
+ neg = 1;
+ stem->width = -stem->width;
+ }
+ MakeVirtualLine(gd,pos,&stem->unit,&myline,&end1,&end2);
+ cnt = MonotonicOrder(gd->sspace,&myline,gd->stspace);
+ ret = MonotonicFindStemBounds(&myline,gd->stspace,cnt,stem);
+ if ( neg )
+ stem->width = -stem->width;
+return( ret );
+}
+
+/* In TrueType I want to make sure that everything on a diagonal line remains */
+/* on the same line. Hence we compute the line. Also we are interested in */
+/* points that are on the intersection of two lines */
+static struct linedata *BuildLine(struct glyphdata *gd,struct pointdata *pd,int is_next ) {
+ int i;
+ BasePoint *dir, *base;
+ struct pointdata **pspace = gd->pspace;
+ int pcnt=0;
+ double dist_error;
+ struct linedata *line;
+ double n_s_err, p_s_err, off;
+
+ dir = is_next ? &pd->nextunit : &pd->prevunit;
+ dist_error = ( dir->x==0 || dir->y==0 ) ? dist_error_hv : dist_error_diag ; /* Diagonals are harder to align */
+ if ( dir->x==0 && dir->y==0 )
+return( NULL );
+ base = &pd->sp->me;
+
+ for ( i= (pd - gd->points)+1; i<gd->pcnt; ++i ) if ( gd->points[i].sp!=NULL ) {
+ struct pointdata *pd2 = &gd->points[i];
+ off = (pd2->sp->me.x-base->x)*dir->y - (pd2->sp->me.y-base->y)*dir->x;
+ if ( off>dist_error || off<-dist_error )
+ continue;
+ n_s_err = dir->x*pd2->nextunit.y - dir->y*pd2->nextunit.x;
+ p_s_err = dir->x*pd2->prevunit.y - dir->y*pd2->prevunit.x;
+ if ( (n_s_err<slope_error && n_s_err>-slope_error && pd2->nextline==NULL ) ||
+ (p_s_err<slope_error && p_s_err>-slope_error && pd2->prevline==NULL ))
+ pspace[pcnt++] = pd2;
+ }
+
+ if ( pcnt==0 )
+return( NULL );
+ if ( pcnt==1 ) {
+ /* if the line consists of just these two points, only count it as */
+ /* a true line if the two form a line */
+ if ( (pd->sp->next->to!=pspace[0]->sp || !pd->sp->next->knownlinear) &&
+ ( pd->sp->prev->from!=pspace[0]->sp || !pd->sp->prev->knownlinear ))
+return( NULL );
+ }
+
+ line = &gd->lines[gd->linecnt++];
+ line->pcnt = pcnt+1;
+ line->points = galloc((pcnt+1)*sizeof(struct pointdata *));
+ line->points[0] = pd;
+ line->unitvector = *dir;
+ line->online = *base;
+ for ( i=0; i<pcnt; ++i ) {
+ n_s_err = dir->x*pspace[i]->nextunit.y - dir->y*pspace[i]->nextunit.x;
+ p_s_err = dir->x*pspace[i]->prevunit.y - dir->y*pspace[i]->prevunit.x;
+ if ( n_s_err<slope_error && n_s_err>-slope_error && pspace[i]->nextline==NULL ) {
+ pspace[i]->nextline = line;
+ if ( pspace[i]->colinear )
+ pspace[i]->prevline = line;
+ }
+ if ( p_s_err<slope_error && p_s_err>-slope_error && pspace[i]->prevline==NULL ) {
+ pspace[i]->prevline = line;
+ if ( pspace[i]->colinear )
+ pspace[i]->nextline = line;
+ }
+ line->points[i+1] = pspace[i];
+ }
+return( line );
+}
+
+static struct stem_chunk *AddToStem(struct stemdata *stem,struct pointdata *pd1,struct pointdata *pd2,
+ int is_next1, int is_next2, struct pointdata *pd2potential ) {
+ struct stem_chunk *chunk;
+ BasePoint *dir = &stem->unit;
+ BasePoint *test = &pd1->sp->me;
+ double off, dist_error;
+ int j;
+ struct pointdata *pd1potential = pd1;
+
+ dist_error = ( dir->x==0 || dir->y==0 ) ? dist_error_hv : dist_error_diag; /* Diagonals are harder to align */
+
+ off = (test->x-stem->left.x)*dir->y - (test->y-stem->left.y)*dir->x;
+ if ( off>dist_error || off<-dist_error ) {
+ struct pointdata *pd = pd1;
+ int in = is_next1;
+ pd1 = pd2; is_next1 = is_next2;
+ pd2 = pd; is_next2 = in;
+ pd1potential = pd2potential; pd2potential = NULL;
+ }
+
+ chunk = NULL;
+ for ( j=stem->chunk_cnt-1; j>=0; --j ) {
+ chunk = &stem->chunks[j];
+ if ( chunk->l==pd1 && chunk->r==pd2 )
+ break;
+ }
+
+ if ( j<0 ) {
+ stem->chunks = grealloc(stem->chunks,(stem->chunk_cnt+1)*sizeof(struct stem_chunk));
+ chunk = &stem->chunks[stem->chunk_cnt++];
+ chunk->l = pd1;
+ chunk->r = pd2;
+ chunk->lpotential = pd1potential;
+ chunk->rpotential = pd2potential;
+ chunk->lnext = is_next1;
+ chunk->rnext = is_next2;
+ chunk->stemcheat = false;
+ }
+ if ( pd1!=NULL ) {
+ if ( is_next1 ) {
+ if ( pd1->nextstem == NULL ) {
+ pd1->nextstem = stem;
+ pd1->next_is_l = true;
+#if 0 /* They can be different, if so we need to figure which is better */
+ if ( pd1->colinear )
+ pd1->prevstem = stem;
+#endif
+ }
+ } else {
+ if ( pd1->prevstem == NULL ) {
+ pd1->prevstem = stem;
+ pd1->prev_is_l = true;
+ }
+ }
+ }
+ if ( pd2!=NULL ) {
+ if ( is_next2 ) {
+ if ( pd2->nextstem == NULL ) {
+ pd2->nextstem = stem;
+ pd2->next_is_l = false; /* It's r */
+ }
+ } else {
+ if ( pd2->prevstem == NULL ) {
+ pd2->prevstem = stem;
+ pd2->prev_is_l = false;
+ }
+ }
+ }
+return( chunk );
+}
+
+static int OnStem(struct stemdata *stem,BasePoint *test) {
+ double dist_error, off;
+ BasePoint *dir = &stem->unit;
+
+ dist_error = ( dir->x==0 || dir->y==0 ) ? dist_error_hv : dist_error_diag; /* Diagonals are harder to align */
+
+ off = (test->x-stem->left.x)*dir->y - (test->y-stem->left.y)*dir->x;
+ if ( off<dist_error && off>-dist_error )
+return( true );
+
+ off = (test->x-stem->right.x)*dir->y - (test->y-stem->right.y)*dir->x;
+ if ( off<=dist_error && off>=-dist_error )
+return( true );
+
+return( false );
+}
+
+static struct stemdata *FindStem(struct glyphdata *gd,struct pointdata *pd,
+ BasePoint *dir,SplinePoint *match, int is_next2) {
+ int j;
+ BasePoint *mdir;
+ struct pointdata *pd2;
+ struct stemdata *stem;
+ double err;
+
+ if ( match->ttfindex==0xffff )
+return( NULL ); /* Point doesn't really exist */
+
+ if ( gd->only_hv &&
+ (dir->x<-slope_error || dir->x>slope_error) &&
+ (dir->y<-slope_error || dir->y>slope_error)) {
+ /* Not close enough to hor/vert, unless it's a serif */
+ if ( pd->sp->next->to!=match && pd->sp->prev->from!=match )
+return( NULL );
+ }
+
+ pd2 = &gd->points[match->ttfindex];
+
+ mdir = is_next2 ? &pd2->nextunit : &pd2->prevunit;
+ if ( mdir->x==0 && mdir->y==0 )
+return( NULL );
+ err = mdir->x*dir->y - mdir->y*dir->x;
+ if (( err<slope_error && err>-slope_error ) ||
+ (( dir->x>.99 || dir->x<-.99 || dir->y>.99 || dir->y<-.99 ) &&
+ (pd->sp->next->to==match || pd->sp->prev->from==match) &&
+ err<3*slope_error && err>-3*slope_error )) {
+ /* Special check for cm serifs */
+ stem = is_next2 ? pd2->nextstem : pd2->prevstem;
+ if ( stem!=NULL && OnStem(stem,&pd->sp->me))
+return( stem );
+
+ for ( j=0; j<gd->stemcnt; ++j ) {
+ err = gd->stems[j].unit.x*dir->y - gd->stems[j].unit.y*dir->x;
+ if ( err<slope_error && err>-slope_error &&
+ OnStem(&gd->stems[j],&pd->sp->me) && OnStem(&gd->stems[j],&pd2->sp->me)) {
+return( &gd->stems[j] );
+ }
+ }
+ if ( dir->y>.99 || dir->y<-.99 ) {
+ for ( j=0; j<gd->stemcnt; ++j ) {
+ if ( (gd->stems[j].unit.y>.99 || gd->stems[j].unit.y<-.99) &&
+ ((match->me.x==gd->stems[j].left.x && pd->sp->me.x==gd->stems[j].right.x) ||
+ (match->me.x==gd->stems[j].right.x && pd->sp->me.x==gd->stems[j].left.x))) {
+ gd->stems[j].unit.x = gd->stems[j].l_to_r.y = 0;
+ gd->stems[j].unit.y = ( gd->stems[j].unit.y*dir->y<0 ) ? -1 : 1;
+ gd->stems[j].l_to_r.x = gd->stems[j].unit.y;
+return( &gd->stems[j] );
+ }
+ }
+ } else if ( dir->x>.99 || dir->x<-.99 ) {
+ for ( j=0; j<gd->stemcnt; ++j ) {
+ if (( gd->stems[j].unit.x>.99 || gd->stems[j].unit.x<-.99 ) &&
+ ((match->me.y==gd->stems[j].left.y && pd->sp->me.y==gd->stems[j].right.y) ||
+ (match->me.y==gd->stems[j].right.y && pd->sp->me.y==gd->stems[j].left.y))) {
+ gd->stems[j].unit.y = gd->stems[j].l_to_r.x = 0;
+ gd->stems[j].unit.x = ( gd->stems[j].unit.x*dir->x<0 ) ? -1 : 1;
+ gd->stems[j].l_to_r.y = gd->stems[j].unit.x;
+return( &gd->stems[j] );
+ }
+ }
+ }
+return( (struct stemdata *) (-1) );
+ }
+return( NULL );
+}
+
+static struct stemdata *NewStem(struct glyphdata *gd,BasePoint *dir,
+ BasePoint *pos1, BasePoint *pos2) {
+ struct stemdata * stem = &gd->stems[gd->stemcnt++];
+
+ stem->unit = *dir;
+ if ( dir->x+dir->y<0 ) {
+ stem->unit.x = -stem->unit.x;
+ stem->unit.y = -stem->unit.y;
+ }
+ if (( stem->unit.x>stem->unit.y && pos1->y<pos2->y ) ||
+ (stem->unit.y>=stem->unit.x && pos1->x<pos2->x )) {
+ stem->left = *pos1;
+ stem->right = *pos2;
+ } else {
+ stem->left = *pos2;
+ stem->right = *pos1;
+ }
+ /* Guess at which normal we want */
+ stem->l_to_r.x = dir->y; stem->l_to_r.y = -dir->x;
+ /* If we guessed wrong, use the other */
+ if ( (stem->right.x-stem->left.x)*stem->l_to_r.x +
+ (stem->right.y-stem->left.y)*stem->l_to_r.y < 0 ) {
+ stem->l_to_r.x = -stem->l_to_r.x;
+ stem->l_to_r.y = -stem->l_to_r.y;
+ }
+ stem->chunks = NULL;
+ stem->chunk_cnt = 0;
+return( stem );
+}
+
+static int ParallelToDir(SplinePoint *sp,int checknext, BasePoint *dir,
+ BasePoint *opposite,SplinePoint *basesp) {
+ BasePoint n, o, *base = &basesp->me;
+ double len, err;
+
+ if ( checknext ) {
+ if ( sp->next!=NULL && sp->next->knownlinear ) {
+ n.x = sp->next->to->me.x - sp->me.x;
+ n.y = sp->next->to->me.y - sp->me.y;
+ } else {
+ n.x = sp->nextcp.x - sp->me.x;
+ n.y = sp->nextcp.y - sp->me.y;
+ }
+ len = n.x*n.x + n.y*n.y;
+ if ( len == 0 )
+return( false );
+ len = sqrt(len);
+ n.x /= len;
+ n.y /= len;
+ } else {
+ if ( sp->prev!=NULL && sp->prev->knownlinear ) {
+ n.x = sp->prev->from->me.x - sp->me.x;
+ n.y = sp->prev->from->me.y - sp->me.y;
+ } else {
+ n.x = sp->prevcp.x - sp->me.x;
+ n.y = sp->prevcp.y - sp->me.y;
+ }
+ len = n.x*n.x + n.y*n.y;
+ if ( len == 0 )
+return( false );
+ len = sqrt(len);
+ n.x /= len;
+ n.y /= len;
+ }
+ err = n.x*dir->y - n.y*dir->x;
+ if (( dir->x>.99 || dir->x<-.99 || dir->y>.99 || dir->y<-.99 ) &&
+ (sp->next->to==basesp || sp->prev->from==basesp) ) {
+ /* special check for serifs */
+ if ( err>3*slope_error || err<-3*slope_error )
+return( false );
+ } else {
+ if ( err>slope_error || err<-slope_error )
+return( false );
+ }
+
+ /* Now sp must be on the same side of the spline as opposite */
+ o.x = opposite->x-base->x; o.y = opposite->y-base->y;
+ n.x = sp->me.x-base->x; n.y = sp->me.y-base->y;
+ if ( ( o.x*dir->y - o.y*dir->x )*( n.x*dir->y - n.y*dir->x ) < 0 )
+return( false );
+
+return( true );
+}
+
+static int NearlyParallel(BasePoint *dir,Spline *other, double t) {
+ BasePoint odir;
+ double olen, dot;
+
+ odir.x = (3*other->splines[0].a*t+2*other->splines[0].b)*t+other->splines[0].c;
+ odir.y = (3*other->splines[1].a*t+2*other->splines[1].b)*t+other->splines[1].c;
+ olen = sqrt(odir.x*odir.x + odir.y*odir.y);
+ if ( olen==0 )
+return( false );
+ odir.x /= olen; odir.y /= olen;
+ dot = dir->x*odir.x + dir->y*odir.y;
+ if ( dot>.95 || dot<-.95 ) /* cos(18) = .95 */
+return( true );
+
+return( false );
+}
+
+static double NormalDist(BasePoint *to, BasePoint *from, BasePoint *perp) {
+ double len = (to->x-from->x)*perp->y - (to->y-from->y)*perp->x;
+ if ( len<0 ) len = -len;
+return( len );
+}
+
+static int NewIsBetter(struct stemdata *stem,struct pointdata *pd,
+ struct pointdata *newcomer, double width) {
+ double stemwidth;
+ int i, cnt;
+ double newd, oldd;
+ struct pointdata *former;
+
+ stemwidth = (stem->left.x-stem->right.x)*stem->unit.y -
+ (stem->left.y-stem->right.y)*stem->unit.x;
+ if ( stemwidth<0 ) stemwidth = -stemwidth;
+
+ if ( width>= stemwidth )
+return( false );
+
+ for ( i=cnt=0; i<stem->chunk_cnt; ++i ) {
+ former = NULL;
+ if ( stem->chunks[i].r==pd || stem->chunks[i].rpotential==pd )
+ former = stem->chunks[i].l==NULL ? stem->chunks[i].lpotential : stem->chunks[i].l;
+ else if ( stem->chunks[i].l==pd || stem->chunks[i].lpotential==pd )
+ former = stem->chunks[i].r==NULL ? stem->chunks[i].rpotential : stem->chunks[i].r;
+ if ( former!=NULL ) {
+ oldd = (former->sp->me.x-pd->sp->me.x)*stem->unit.x +
+ (former->sp->me.y-pd->sp->me.y)*stem->unit.y;
+ newd = (newcomer->sp->me.x-pd->sp->me.x)*stem->unit.x +
+ (newcomer->sp->me.y-pd->sp->me.y)*stem->unit.y;
+ if ( oldd<0 ) oldd = -oldd;
+ if ( newd<0 ) newd = -newd;
+ if ( newd>oldd ) {
+ /* The old stem is wider, but the points are closer */
+ /* if they are much further appart than the improvement we get from making the width smaller... */
+ if ( (newd-oldd) > 4*(stemwidth-width) )
+return( false );
+ }
+ }
+ if ( stem->chunks[i].r==pd || stem->chunks[i].l==pd )
+ ++cnt;
+ }
+
+ if ( cnt>=2 )
+return( false );
+return( true );
+}
+
+static void MakePDPotential(struct stemdata *stem,struct pointdata *pd) {
+ int i;
+
+ for ( i=0; i<stem->chunk_cnt; ++i ) {
+ if ( stem->chunks[i].l==pd ) {
+ stem->chunks[i].lpotential = pd;
+ stem->chunks[i].l=NULL;
+ }
+ if ( stem->chunks[i].r==pd ) {
+ stem->chunks[i].rpotential=pd;
+ stem->chunks[i].r=NULL;
+ }
+ }
+}
+
+static struct stemdata *TestStem(struct glyphdata *gd,struct pointdata *pd,
+ BasePoint *dir,SplinePoint *match, int is_next, int is_next2) {
+ struct pointdata *pd2, *pd2potential;
+ struct stemdata *stem, *stem2 = (struct stemdata *) (-2);
+ double width;
+
+ if ( match->ttfindex==0xffff )
+return( NULL );
+ width = (match->me.x-pd->sp->me.x)*dir->y - (match->me.y-pd->sp->me.y)*dir->x;
+ if ( width<0 ) width = -width;
+ if ( width<.5 )
+return( NULL ); /* Zero width stems aren't interesting */
+ if ( (is_next && pd->sp->next->to==match) || (!is_next && pd->sp->prev->from==match) )
+return( NULL ); /* Don't want a stem between two splines that intersect */
+
+ stem = FindStem(gd,pd,dir,match,is_next2);
+ if ( stem==NULL )
+return( NULL );
+
+ pd2 = &gd->points[match->ttfindex];
+ stem2 = NULL;
+ /* OK, we've got a valid stem between us and pd2. Now see if we get the */
+ /* same stem when we look at pd2. If we do, then all is happy and nice */
+ /* and we can add both points to the stem. If not, then we're sort of */
+ /* happy, but we can only add pd to the stem */
+ if ( pd2->nextstem==stem )
+ stem2 = stem;
+ else if ( pd2->prevstem==stem )
+ stem2 = stem;
+ else if ( is_next2 && pd2->nextstem!=NULL && NewIsBetter(pd2->nextstem,pd2,pd,width) ) {
+ MakePDPotential(pd2->nextstem,pd2);
+ pd2->nextstem = NULL;
+ stem2 = stem;
+ } else if ( !is_next2 && pd2->prevstem!=NULL && NewIsBetter(pd2->prevstem,pd2,pd,width) ) {
+ MakePDPotential(pd2->prevstem,pd2);
+ pd2->prevstem = NULL;
+ stem2 = stem;
+ } else if ( (is_next2 && pd2->nextstem==NULL) || (!is_next2 && pd2->prevstem==NULL) ) {
+ stem2 = stem;
+ } else
+ stem2 = NULL;
+
+ pd2potential = pd2;
+ if ( stem2==NULL )
+ pd2 = NULL;
+
+ if ( stem==(struct stemdata *) (-1) )
+ stem = NewStem(gd,dir,&pd->sp->me,&match->me);
+
+ AddToStem(stem,pd,pd2,is_next,is_next2,pd2potential);
+return( stem );
+}
+
+static double FindSameSlope(Spline *s,BasePoint *dir,double close_to) {
+ double a,b,c, desc;
+ double t1,t2;
+ double d1, d2;
+
+ if ( s==NULL )
+return( -1e4 );
+
+ a = dir->x*s->splines[1].a*3 - dir->y*s->splines[0].a*3;
+ b = dir->x*s->splines[1].b*2 - dir->y*s->splines[0].b*2;
+ c = dir->x*s->splines[1].c - dir->y*s->splines[0].c ;
+ if ( a!=0 ) {
+ desc = b*b - 4*a*c;
+ if ( desc<0 )
+return( -1e4 );
+ desc = sqrt(desc);
+ t1 = (-b+desc)/(2*a);
+ t2 = (-b-desc)/(2*a);
+ if ( (d1=t1-close_to)<0 ) d1 = -d1;
+ if ( (d2=t2-close_to)<0 ) d2 = -d2;
+ if ( d2<d1 && t2>=-.001 && t2<=1.001 )
+ t1 = t2;
+ } else if ( b!=0 )
+ t1 = -c/b;
+ else
+return( -1e4 );
+
+return( t1 );
+}
+
+static struct stemdata *HalfStem(struct glyphdata *gd,struct pointdata *pd,
+ BasePoint *dir,Spline *other,double other_t,int is_next) {
+ /* Find the spot on other where the slope is the same as dir */
+ double t1;
+ double width, err;
+ BasePoint match;
+ struct stemdata *stem = NULL;
+ int j;
+
+ t1 = FindSameSlope(other,dir,other_t);
+ if ( t1==-1e4 )
+return( NULL );
+ if ( t1<0 && other->from->prev!=NULL && gd->points[other->from->ttfindex].colinear ) {
+ other = other->from->prev;
+ t1 = FindSameSlope(other,dir,1.0);
+ } else if ( t1>1 && other->to->next!=NULL && gd->points[other->to->ttfindex].colinear ) {
+ other = other->to->next;
+ t1 = FindSameSlope(other,dir,0.0);
+ }
+
+ if ( t1<-.001 || t1>1.001 )
+return( NULL );
+
+ /* Ok. the opposite edge has the right slope at t1 */
+ /* Now see if we can make a one sided stem out of these two */
+ match.x = ((other->splines[0].a*t1+other->splines[0].b)*t1+other->splines[0].c)*t1+other->splines[0].d;
+ match.y = ((other->splines[1].a*t1+other->splines[1].b)*t1+other->splines[1].c)*t1+other->splines[1].d;
+
+ width = (match.x-pd->sp->me.x)*dir->y - (match.y-pd->sp->me.y)*dir->x;
+ /* offset = (match.x-pd->sp->me.x)*dir->x + (match.y-pd->sp->me.y)*dir->y;*/
+ if ( width<.5 && width>-.5 )
+return( NULL ); /* Zero width stems aren't interesting */
+
+ if ( isnan(t1))
+ IError( "NaN value in HalfStem" );
+
+ if ( is_next ) {
+ pd->nextedge = other;
+ pd->next_e_t = t1;
+ } else {
+ pd->prevedge = other;
+ pd->prev_e_t = t1;
+ }
+
+ stem = NULL;
+ for ( j=0; j<gd->stemcnt; ++j ) {
+ err = gd->stems[j].unit.x*dir->y - gd->stems[j].unit.y*dir->x;
+ if ( err<slope_error && err>-slope_error &&
+ OnStem(&gd->stems[j],&pd->sp->me) && OnStem(&gd->stems[j],&match)) {
+ stem = &gd->stems[j];
+ break;
+ }
+ }
+ if ( stem==NULL )
+ stem = NewStem(gd,dir,&pd->sp->me,&match);
+ AddToStem(stem,pd,NULL,is_next,false,NULL);
+return( stem );
+}
+
+static struct stemdata *FindOrMakeHVStem(struct glyphdata *gd,
+ struct pointdata *pd, struct pointdata *pd2, int is_h) {
+ int i;
+ struct stemdata *stem;
+ BasePoint dir;
+
+ stem = NULL;
+ memset(&dir,0,sizeof(dir));
+ if ( is_h ) {
+ dir.x = 1;
+ for ( i=0; i<gd->stemcnt; ++i ) {
+ stem = &gd->stems[i];
+ if ( stem->unit.x==1 &&
+ ((stem->left.y==pd->sp->me.y && stem->right.y==pd2->sp->me.y) ||
+ (stem->left.y==pd2->sp->me.y && stem->right.y==pd->sp->me.y)))
+ break;
+ }
+ if ( i==gd->stemcnt ) stem=NULL;
+ } else {
+ dir.y = 1;
+ for ( i=0; i<gd->stemcnt; ++i ) {
+ stem = &gd->stems[i];
+ if ( stem->unit.y==1 &&
+ ((stem->left.x==pd->sp->me.x && stem->right.x==pd2->sp->me.x) ||
+ (stem->left.x==pd2->sp->me.x && stem->right.x==pd->sp->me.x)))
+ break;
+ }
+ if ( i==gd->stemcnt ) stem=NULL;
+ }
+ if ( stem==NULL )
+ stem = NewStem(gd,&dir,&pd->sp->me,&pd2->sp->me);
+return( stem );
+}
+
+static struct stemdata *EdgeStem(struct glyphdata *gd,struct pointdata *pd) {
+ struct pointdata *pd2;
+ /* suppose we have something like */
+ /* *--* */
+ /* \ \ */
+ /* \ \ */
+ /* Then let's create a vertical stem between the two points */
+ /* (and a horizontal stem if the thing is rotated 90 degrees) */
+ struct stemdata *stem = NULL;
+ struct stem_chunk *chunk;
+ double width, length1, length2;
+
+ if ( !hint_diagonal_ends )
+return( NULL );
+
+ if ( !gd->only_hv ||
+ pd->sp->next==NULL || pd->sp->next->to->next==NULL )
+return( NULL );
+ pd2 = &gd->points[pd->sp->next->to->ttfindex];
+ if ( (pd->sp->me.x!=pd2->sp->me.x && pd->sp->me.y!=pd2->sp->me.y ) ||
+ pd->sp->prev==NULL || !pd->sp->prev->knownlinear ||
+ pd2->sp->next==NULL || !pd2->sp->next->knownlinear )
+return( NULL );
+ if ( !UnitsParallel(&pd2->nextunit,&pd->prevunit ) )
+return( NULL );
+ if ( pd->prevunit.x==0 || pd->prevunit.y==0 ) /* Must be diagonal */
+return( NULL );
+
+ length1 = (pd->sp->prev->from->me.x-pd->sp->me.x)*(pd->sp->prev->from->me.x-pd->sp->me.x) +
+ (pd->sp->prev->from->me.y-pd->sp->me.y)*(pd->sp->prev->from->me.y-pd->sp->me.y);
+ length2 = (pd2->sp->next->to->me.x-pd2->sp->me.x)*(pd2->sp->next->to->me.x-pd2->sp->me.x) +
+ (pd2->sp->next->to->me.y-pd2->sp->me.y)*(pd2->sp->next->to->me.y-pd2->sp->me.y);
+ if ( length2<length1 )
+ length1 = length2;
+
+ if ( pd->sp->me.x==pd2->sp->me.x )
+ width = pd->sp->me.y-pd2->sp->me.y;
+ else
+ width = pd->sp->me.x-pd2->sp->me.x;
+
+ if ( width*width>length1 )
+return( NULL );
+
+ stem = FindOrMakeHVStem(gd,pd,pd2,pd->sp->me.x==pd2->sp->me.x);
+ chunk = AddToStem(stem,pd,pd2,false,true,NULL);
+ chunk->stemcheat = true;
+return( stem );
+}
+
+static int ConnectsAcross(struct glyphdata *gd,SplinePoint *sp,int is_next,Spline *findme) {
+ struct pointdata *pd = &gd->points[sp->ttfindex];
+ Spline *other, *test;
+ BasePoint *dir;
+
+ if ( is_next )
+ other = pd->nextedge;
+ else
+ other = pd->prevedge;
+
+ if ( other==findme )
+return( true );
+ if ( other==NULL )
+return( false );
+
+ dir = &gd->points[other->to->ttfindex].nextunit;
+ test = other->to->next;
+ while ( test!=NULL &&
+ gd->points[test->from->ttfindex].nextunit.x * dir->x +
+ gd->points[test->from->ttfindex].nextunit.y * dir->y >= 0 ) {
+ if ( test==findme )
+return( true );
+ test = test->to->next;
+ if ( test==other )
+ break;
+ }
+
+ dir = &gd->points[other->from->ttfindex].prevunit;
+ test = other->from->prev;
+ while ( test!=NULL &&
+ gd->points[test->to->ttfindex].prevunit.x * dir->x +
+ gd->points[test->to->ttfindex].prevunit.y * dir->y >= 0 ) {
+ if ( test==findme )
+return( true );
+ test = test->from->prev;
+ if ( test==other )
+ break;
+ }
+
+return( false );
+}
+
+static void BuildStem(struct glyphdata *gd,struct pointdata *pd,int is_next ) {
+ BasePoint *dir;
+ Spline *other, *cur;
+ double t;
+ double tod, fromd;
+ struct stemdata *stem;
+ int tp, fp;
+ BasePoint opposite;
+
+ if ( is_next ) {
+ dir = &pd->nextunit;
+ other = pd->nextedge;
+ cur = pd->sp->next;
+ t = pd->next_e_t;
+ } else {
+ dir = &pd->prevunit;
+ other = pd->prevedge;
+ cur = pd->sp->prev;
+ t = pd->prev_e_t;
+ }
+ if ( other==NULL )
+return;
+
+ opposite.x = ((other->splines[0].a*t+other->splines[0].b)*t+other->splines[0].c)*t+other->splines[0].d;
+ opposite.y = ((other->splines[1].a*t+other->splines[1].b)*t+other->splines[1].c)*t+other->splines[1].d;
+
+ tp = ParallelToDir(other->to,false,dir,&opposite,pd->sp);
+ fp = ParallelToDir(other->from,true,dir,&opposite,pd->sp);
+ stem = NULL;
+ if ( is_next )
+ stem = EdgeStem(gd,pd);
+ if ( !tp && !fp )
+return;
+
+ /* We have several conflicting metrics for getting the "better" stem */
+ /* Generally we prefer the stem with the smaller width (but not always. See tilde) */
+ /* Generally we prefer the stem formed by the point closer to the intersection */
+ tod = (1-t)*NormalDist(&other->to->me,&pd->sp->me,dir);
+ fromd = t*NormalDist(&other->from->me,&pd->sp->me,dir);
+ stem = NULL;
+ if ( (tp && (tod<fromd)) ||
+ (tp && !fp && (tod<2*fromd)) ||
+ (tp && !fp && (ConnectsAcross(gd,other->to,false,cur) ||
+ NearlyParallel(dir,other,t))))
+ stem = TestStem(gd,pd,dir, other->to, is_next, false);
+ if ( stem==NULL && ((fp && (fromd<tod)) ||
+ (fp && !tp && (fromd<2*tod)) ||
+ (fp && !tp && (ConnectsAcross(gd,other->from,true,cur) ||
+ NearlyParallel(dir,other,t)))))
+ stem = TestStem(gd,pd,dir, other->from, is_next,true);
+ if ( stem==NULL && cur!=NULL && !other->knownlinear && !cur->knownlinear )
+ stem = HalfStem(gd,pd,dir,other,t,is_next);
+}
+
+static void DiagonalCornerStem(struct glyphdata *gd,struct pointdata *pd) {
+ Spline *other = pd->bothedge;
+ struct pointdata *pfrom = &gd->points[other->from->ttfindex],
+ *pto = &gd->points[other->to->ttfindex],
+ *pd2 = NULL, *pd3=NULL;
+ double width, length;
+ struct stemdata *stem;
+ struct stem_chunk *chunk;
+
+ if ( pd->symetrical_h && pto->symetrical_h && pd->both_e_t>.9 )
+ pd2 = pto;
+ else if ( pd->symetrical_h && pfrom->symetrical_h && pd->both_e_t<.1 )
+ pd2 = pfrom;
+ else if ( pd->symetrical_v && pto->symetrical_v && pd->both_e_t>.9 )
+ pd2 = pto;
+ else if ( pd->symetrical_v && pfrom->symetrical_v && pd->both_e_t<.1 )
+ pd2 = pfrom;
+ else if ( pd->symetrical_h && other->islinear && other->splines[1].c==0 ) {
+ pd2 = pfrom;
+ pd3 = pto;
+ } else if ( pd->symetrical_v && other->islinear && other->splines[0].c==0 ) {
+ pd2 = pfrom;
+ pd3 = pto;
+ } else
+return;
+
+ if ( pd->symetrical_v )
+ width = (pd->sp->me.x-pd2->sp->me.x);
+ else
+ width = (pd->sp->me.y-pd2->sp->me.y);
+ length = (pd->sp->next->to->me.x-pd->sp->me.x)*(pd->sp->next->to->me.x-pd->sp->me.x) +
+ (pd->sp->next->to->me.y-pd->sp->me.y)*(pd->sp->next->to->me.y-pd->sp->me.y);
+ if ( width*width>length )
+return;
+
+ stem = FindOrMakeHVStem(gd,pd,pd2,pd->symetrical_h);
+ chunk = AddToStem(stem,pd,pd2,false,true,NULL);
+ if ( pd3==NULL )
+ chunk->stemcheat = 2;
+ else {
+ chunk->stemcheat = 3;
+ chunk = AddToStem(stem,pd,pd3,false,true,NULL);
+ chunk->stemcheat = 3;
+ }
+}
+
+static int swidth_cmp(const void *_p1, const void *_p2) {
+ const struct stemdata * const *stpt1 = _p1, * const *stpt2 = _p2;
+ const struct stemdata *s1 = *stpt1, *s2 = *stpt2;
+ if ( s1->width>s2->width )
+return( 1 );
+ else if ( s1->width<s2->width )
+return( -1 );
+
+return( 0 );
+}
+
+static int IsL(BasePoint *bp,struct stemdata *stem) {
+ double offl, offr;
+
+ offl = (bp->x-stem->left.x)*stem->l_to_r.x + (bp->y-stem->left.y)*stem->l_to_r.y;
+ if ( offl<0 ) offl = -offl;
+ offr = (bp->x-stem->right.x)*stem->l_to_r.x + (bp->y-stem->right.y)*stem->l_to_r.y;
+ if ( offr<0 ) offr = -offr;
+return( offl < offr );
+}
+
+static struct pointdata *PotentialAdd(struct glyphdata *gd,struct stemdata *stem,
+ struct pointdata *pd, int is_next ) {
+
+ if ( is_next && (pd->nextstem==NULL || pd->nextstem->toobig )) {
+ pd->nextstem = stem;
+ pd->next_is_l = IsL(&pd->sp->me,stem);
+return( pd );
+ } else if ( !is_next && (pd->prevstem==NULL || pd->prevstem->toobig )) {
+ pd->prevstem = stem;
+ pd->prev_is_l = IsL(&pd->sp->me,stem);
+return( pd );
+ }
+return( NULL );
+}
+
+static int IsClosestPotential(struct stemdata **sspace,int cur,int goodcnt,
+ int is_l,struct stem_chunk *chunk) {
+ struct pointdata *search;
+ double mydist, dist;
+ SplinePoint *sp1, *sp2;
+ int i,j;
+
+ if ( is_l ) {
+ if ( chunk->r==NULL )
+return( false );
+ search = chunk->lpotential;
+ sp1 = search->sp; sp2 = chunk->r->sp;
+ mydist = (sp1->me.x-sp2->me.x)*(sp1->me.x-sp2->me.x) +
+ (sp1->me.y-sp2->me.y)*(sp1->me.y-sp2->me.y);
+ } else {
+ if ( chunk->l==NULL )
+return( false );
+ search = chunk->rpotential;
+ sp1 = search->sp; sp2 = chunk->l->sp;
+ mydist = (sp1->me.x-sp2->me.x)*(sp1->me.x-sp2->me.x) +
+ (sp1->me.y-sp2->me.y)*(sp1->me.y-sp2->me.y);
+ }
+ for ( i=cur+1; i<goodcnt; ++i ) {
+ struct stemdata *stem = sspace[i];
+ for ( j=0; j<stem->chunk_cnt; ++j ) {
+ struct stem_chunk *chunk = &stem->chunks[j];
+ if ( is_l && chunk->r!=NULL && chunk->l==NULL && chunk->lpotential==search ) {
+ sp2 = chunk->r->sp;
+ dist = (sp1->me.x-sp2->me.x)*(sp1->me.x-sp2->me.x) +
+ (sp1->me.y-sp2->me.y)*(sp1->me.y-sp2->me.y);
+ if ( dist<mydist )
+return( false );
+ } else if ( !is_l && chunk->l!=NULL && chunk->r==NULL && chunk->rpotential==search ) {
+ sp2 = chunk->l->sp;
+ dist = (sp1->me.x-sp2->me.x)*(sp1->me.x-sp2->me.x) +
+ (sp1->me.y-sp2->me.y)*(sp1->me.y-sp2->me.y);
+ if ( dist<mydist )
+return( false );
+ }
+ }
+ }
+return( true );
+}
+
+int UnitsParallel(BasePoint *u1,BasePoint *u2) {
+ double dot = u1->x*u2->x + u1->y*u2->y;
+return( dot>.95 || dot < -.95 );
+}
+
+static void FixupT(struct stemdata *stem,struct pointdata *pd,int isnext) {
+ /* When we calculated "next/prev_e_t" we deliberately did not use pd1->me */
+ /* (because things get hard at intersections) so our t is only an approx-*/
+ /* imation. We can do a lot better now */
+ Spline *s;
+ Spline myline;
+ SplinePoint end1, end2;
+ double width,t,sign, len, dot;
+ BasePoint pts[9];
+ extended lts[10], sts[10];
+ BasePoint diff;
+
+ width = (stem->right.x-stem->left.x)*stem->unit.y - (stem->right.y-stem->left.y)*stem->unit.x;
+ s = isnext ? pd->nextedge : pd->prevedge;
+ if ( s==NULL )
+return;
+ diff.x = s->to->me.x-s->from->me.x; diff.y = s->to->me.y-s->from->me.y;
+ if ( diff.x<.001 && diff.x>-.001 && diff.y<.001 && diff.y>-.001 )
+return; /* Zero length splines give us NaNs */
+ len = sqrt( diff.x*diff.x + diff.y*diff.y );
+ dot = (diff.x*stem->unit.x + diff.y*stem->unit.y)/len;
+ if ( dot < .0004 && dot > -.0004 )
+return; /* It's orthogonal to our stem */
+
+ if (( stem->unit.x==1 || stem->unit.x==-1 ) && s->knownlinear )
+ t = (pd->sp->me.x-s->from->me.x)/(s->to->me.x-s->from->me.x);
+ else if (( stem->unit.y==1 || stem->unit.y==-1 ) && s->knownlinear )
+ t = (pd->sp->me.y-s->from->me.y)/(s->to->me.y-s->from->me.y);
+ else {
+ memset(&myline,0,sizeof(myline));
+ memset(&end1,0,sizeof(end1));
+ memset(&end2,0,sizeof(end2));
+ sign = ( (isnext && pd->next_is_l) || (!isnext && pd->prev_is_l)) ? 1 : -1;
+ myline.knownlinear = myline.islinear = true;
+ end1.me = pd->sp->me;
+ end2.me.x = pd->sp->me.x+1.1*sign*width*stem->l_to_r.x;
+ end2.me.y = pd->sp->me.y+1.1*sign*width*stem->l_to_r.y;
+ end1.nextcp = end1.prevcp = end1.me;
+ end2.nextcp = end2.prevcp = end2.me;
+ end1.nonextcp = end1.noprevcp = end2.nonextcp = end2.noprevcp = true;
+ end1.next = &myline; end2.prev = &myline;
+ myline.from = &end1; myline.to = &end2;
+ myline.splines[0].d = end1.me.x;
+ myline.splines[0].c = end2.me.x-end1.me.x;
+ myline.splines[1].d = end1.me.y;
+ myline.splines[1].c = end2.me.y-end1.me.y;
+ if ( SplinesIntersect(&myline,s,pts,lts,sts)<=0 )
+return;
+ t = sts[0];
+ }
+ if ( isnan(t))
+ IError( "NaN value in FixupT" );
+ if ( isnext )
+ pd->next_e_t = t;
+ else
+ pd->prev_e_t = t;
+}
+
+static int StemIsActiveAt(struct glyphdata *gd,struct stemdata *stem,double stempos ) {
+ BasePoint pos;
+ int which;
+ double test;
+ struct monotonic **space, *m;
+ int winding, nw, i,j;
+ m = NULL; nw = 0;
+ pos.x = stem->left.x + stempos*stem->unit.x;
+ pos.y = stem->left.y + stempos*stem->unit.y;
+
+ if ( stem->unit.x==0 || stem->unit.y==0 ) {
+ which = stem->unit.x==0;
+ MonotonicFindAt(gd->ms,which,((real *) &pos.x)[which],space = gd->space);
+ test = ((real *) &pos.x)[!which] - dist_error_hv;
+
+ winding = 0;
+ for ( i=0; space[i]!=NULL; ++i ) {
+ m = space[i];
+ nw = ((&m->xup)[which] ? 1 : -1 );
+ if ( m->other>=test )
+ break;
+ winding += nw;
+ }
+ if ( space[i]==NULL || m->other>test+2*dist_error_hv )
+return( false );
+ j = MatchWinding(space,i,nw,winding,which);
+ if ( j==-1 )
+return( false );
+ m = space[j];
+ if ( m->other>=((real *) &stem->right.x)[!which]-dist_error_hv &&
+ m->other<=((real *) &stem->right.x)[!which]+dist_error_hv )
+return( true );
+return( false );
+ } else {
+ Spline myline;
+ SplinePoint end1, end2;
+ int cnt;
+ MakeVirtualLine(gd,&pos,&stem->unit,&myline,&end1,&end2);
+ cnt = MonotonicOrder(gd->sspace,&myline,gd->stspace);
+return( MonotonicFindStemBounds(&myline,gd->stspace,cnt,stem));
+ }
+}
+
+static int WalkSpline(struct glyphdata *gd, SplinePoint *sp,int gonext,struct stemdata *stem,BasePoint *res) {
+ int i;
+ double off,diff;
+ double incr;
+ double t=.5;
+ Spline *s;
+ BasePoint pos, good;
+ /* Some splines have tiny control points and are almost flat */
+ /* think of them as lines then rather than treating them as curves */
+ /* figure out how long they remain within a few orthoganal units of */
+ /* the point */
+
+ if ( gonext ) {
+ s = sp->next;
+ incr = .25;
+ *res = sp->nextcp;
+ } else {
+ s = sp->prev;
+ incr = -.25;
+ *res = sp->prevcp;
+ }
+ good = *res;
+ for ( i=0; i<6; ++i ) {
+ pos.x = ((s->splines[0].a*t+s->splines[0].b)*t+s->splines[0].c)*t+s->splines[0].d;
+ pos.y = ((s->splines[1].a*t+s->splines[1].b)*t+s->splines[1].c)*t+s->splines[1].d;
+ diff = (pos.x-sp->me.x)*stem->l_to_r.x +
+ (pos.y-sp->me.y)*stem->l_to_r.y;
+ if ( diff>=-dist_error_hv && diff<dist_error_hv && StillStem(gd,t,gonext,&pos,stem)) {
+ good = pos;
+ t += incr;
+ } else
+ t -= incr;
+ incr/=2;
+ }
+ off = (res->x-sp->me.x)*stem->unit.x + (res->y-sp->me.y)*stem->unit.y;
+ diff = (good.x-sp->me.x)*stem->unit.x + (good.y-sp->me.y)*stem->unit.y;
+ if (( off>0 && diff>off ) || ( off<0 && diff<off )) {
+ *res = good;
+return( false ); /* Treat as a funny line */
+ }
+return( true ); /* Treat as curved */
+}
+
+static BasePoint *AdjustForImperfectSlopeMatch(SplinePoint *sp,BasePoint *pos,
+ struct stemdata *stem,BasePoint *temp) {
+ double off;
+
+ off = (pos->x-sp->me.x)*stem->l_to_r.x +
+ (pos->y-sp->me.y)*stem->l_to_r.y;
+ if ( off<0 ) off=-off;
+ if ( off<=dist_error_hv )
+return( pos );
+
+ temp->x = sp->me.x + dist_error_hv*(pos->x-sp->me.x)/off;
+ temp->y = sp->me.y + dist_error_hv*(pos->y-sp->me.y)/off;
+return( temp );
+}
+
+static int AddLineSegment(struct stemdata *stem, struct segment *space, int cnt,
+ struct pointdata *pd, struct glyphdata *gd ) {
+ double s, e;
+ BasePoint stemp, etemp, stemp2, etemp2;
+ BasePoint *start, *end;
+ int scurved = false, ecurved = false;
+ SplinePoint *sp, *psp, *nsp;
+ double b;
+
+ if ( pd==NULL || (sp = pd->sp)==NULL || sp->ticked ||
+ sp->next==NULL || sp->prev==NULL )
+return( cnt );
+ end = &sp->me;
+ start = &sp->me;
+ if ( UnitsParallel(&pd->nextunit,&stem->unit)) {
+ if ( sp->next->knownlinear ) {
+ nsp = sp->next->to;
+ end = &nsp->me;
+ if ( nsp->next!=NULL && !nsp->next->knownlinear && !nsp->ticked &&
+ UnitsParallel(&gd->points[nsp->ttfindex].nextunit,&stem->unit)) {
+ WalkSpline(gd,nsp,true,stem,&etemp);
+ end = &etemp;
+ nsp->ticked = true;
+ }
+ } else {
+ WalkSpline(gd,sp,true,stem,&etemp);
+ ecurved = true;
+ end = &etemp;
+ }
+ } else {
+ if ( !WalkSpline(gd,sp,true,stem,&etemp))
+ end = &etemp;
+ }
+ if ( UnitsParallel(&pd->prevunit,&stem->unit)) {
+ if ( sp->prev->knownlinear ) {
+ psp = sp->prev->from;
+ start = &psp->me;
+ if ( psp->prev!=NULL && !psp->prev->knownlinear && !psp->ticked &&
+ UnitsParallel(&gd->points[psp->ttfindex].prevunit,&stem->unit)) {
+ WalkSpline(gd,psp,false,stem,&stemp);
+ start = &stemp;
+ psp->ticked = true;
+ }
+ } else {
+ WalkSpline(gd,sp,false,stem,&stemp);
+ scurved = true;
+ start = &stemp;
+ }
+ } else {
+ if ( !WalkSpline(gd,sp,false,stem,&stemp))
+ start = &stemp;
+ }
+
+ sp->ticked = true;
+
+ /* Now if the segment sp-start doesn't have exactly the right slope, then */
+ /* we can only use that bit of it which is less than a standard error */
+ start = AdjustForImperfectSlopeMatch(sp,start,stem,&stemp2);
+ end = AdjustForImperfectSlopeMatch(sp,end,stem,&etemp2);
+
+ s = (start->x-stem->left.x)*stem->unit.x +
+ (start->y-stem->left.y)*stem->unit.y;
+ e = ( end->x-stem->left.x)*stem->unit.x +
+ ( end->y-stem->left.y)*stem->unit.y;
+ b = 0;
+ if ( scurved || ecurved ) {
+ b = (sp->me.x-stem->left.x)*stem->unit.x +
+ (sp->me.y-stem->left.y)*stem->unit.y;
+ if ( scurved )
+ s = b + (s-b)*1.3;
+ if ( ecurved )
+ e = b + (e-b)*1.3;
+ }
+ if ( s==e )
+return( cnt );
+ if ( s>e ) {
+ double t = s;
+ int c = scurved;
+ s = e;
+ e = t;
+ scurved = ecurved;
+ ecurved = c;
+ }
+ space[cnt].start = s;
+ space[cnt].end = e;
+ space[cnt].base = b;
+ space[cnt].curved= scurved | (ecurved?2:0);
+return( cnt+1 );
+}
+
+static int segment_cmp(const void *_s1, const void *_s2) {
+ const struct segment *s1 = _s1, *s2 = _s2;
+ if ( s1->start<s2->start )
+return( -1 );
+ else if ( s1->start>s2->start )
+return( 1 );
+
+return( 0 );
+}
+
+static int proj_cmp(const void *_p1, const void *_p2) {
+ struct pointdata * const *p1 = _p1, * const *p2 = _p2;
+ if ( (*p1)->projection<(*p2)->projection )
+return( -1 );
+ else if ( (*p1)->projection>(*p2)->projection )
+return( 1 );
+
+return( 0 );
+}
+
+static int InActive(double projection,struct segment *segments, int cnt) {
+ int i;
+
+ for ( i=0; i<cnt; ++i ) {
+ if ( projection<=segments[i].end )
+return( projection>=segments[i].start );
+ }
+return( false );
+}
+
+static int MergeSegments(struct segment *space, int cnt) {
+ int i,j;
+
+ for ( i=j=0; i<cnt; ++i, ++j ) {
+ if ( i!=j )
+ space[j] = space[i];
+ while ( i+1<cnt && space[i+1].start<space[j].end ) {
+ if ( space[i+1].end>space[j].end ) {
+ space[j].end = space[i+1].end;
+ space[j].curved = (space[j].curved&1) | (space[i+1].curved&2);
+ }
+ ++i;
+ }
+ }
+return( j );
+}
+
+static void FigureStemActive(struct glyphdata *gd, struct stemdata *stem) {
+ int i, j, pcnt=0;
+ struct pointdata *pd, **pspace = gd->pspace;
+ struct segment *lspace = gd->lspace, *rspace = gd->rspace;
+ struct segment *bothspace = gd->bothspace, *activespace = gd->activespace;
+ int lcnt, rcnt, bcnt, bpos, acnt;
+ double width, last, len, clen;
+
+ width = (stem->left.x-stem->right.x)*stem->unit.y -
+ (stem->left.y-stem->right.y)*stem->unit.x;
+ stem->width=width;
+
+ for ( i=0; i<gd->pcnt; ++i ) if ( gd->points[i].sp!=NULL )
+ gd->points[i].sp->ticked = false;
+
+ lcnt = rcnt = 0;
+ for ( i=0; i<stem->chunk_cnt; ++i ) {
+ lcnt = AddLineSegment(stem,lspace,lcnt,stem->chunks[i].l, gd );
+ if ( stem->chunks[i].lpotential!=stem->chunks[i].l )
+ lcnt = AddLineSegment(stem,lspace,lcnt,stem->chunks[i].lpotential, gd );
+ rcnt = AddLineSegment(stem,rspace,rcnt,stem->chunks[i].r, gd );
+ if ( stem->chunks[i].rpotential!=stem->chunks[i].r )
+ rcnt = AddLineSegment(stem,rspace,rcnt,stem->chunks[i].rpotential, gd );
+ }
+ bcnt = 0;
+ if ( lcnt!=0 && rcnt!=0 ) {
+ if ( lcnt==1 && rcnt==1 && lspace[0].curved && rspace[0].curved ) {
+ double gap;
+ if ( lspace[0].start>rspace[0].end )
+ gap = lspace[0].start-rspace[0].end;
+ else if ( rspace[0].start>lspace[0].end )
+ gap = rspace[0].start-lspace[0].end;
+ else
+ gap = 0;
+ if ( gap < (lspace[0].end-lspace[0].start + rspace[0].end-rspace[0].start)/2 ) {
+ if ( lspace[0].base<rspace[0].start )
+ rspace[0].start = lspace[0].base;
+ else if ( lspace[0].base>rspace[0].end )
+ rspace[0].end = lspace[0].base;
+ if ( rspace[0].base<lspace[0].start )
+ lspace[0].start = rspace[0].base;
+ else if ( rspace[0].base>lspace[0].end )
+ lspace[0].end = rspace[0].base;
+ }
+ }
+ qsort(lspace,lcnt,sizeof(struct segment),segment_cmp);
+ qsort(rspace,rcnt,sizeof(struct segment),segment_cmp);
+ lcnt = MergeSegments(lspace,lcnt);
+ rcnt = MergeSegments(rspace,rcnt);
+ for ( i=j=bcnt=0; i<lcnt && j<rcnt; ++i ) {
+ while ( j<rcnt && rspace[j].end<=lspace[i].start )
+ ++j;
+ while ( j<rcnt && rspace[j].start<=lspace[i].end ) {
+ double s = lspace[i].start;
+ double e = lspace[i].end;
+ if ( rspace[j].start>s )
+ s = rspace[j].start;
+ if ( rspace[j].end<e )
+ e = rspace[j].end;
+ bothspace[bcnt ].curved= rspace[j].curved || lspace[i].curved;
+ bothspace[bcnt ].start = s;
+ bothspace[bcnt++].end = e;
+ if ( rspace[j].end>lspace[i].end )
+ break;
+ ++j;
+ }
+ }
+ }
+
+ acnt = 0;
+ if ( bcnt!=0 ) {
+ for ( i=0; i<gd->pcnt; ++i ) if ( (pd = &gd->points[i])->sp!=NULL ) {
+ /* Let's say we have a stem. And then inside that stem we have */
+ /* another rectangle. So our first stem isn't really a stem any */
+ /* more (because we hit another edge first), yet it's still reasonable*/
+ /* to align the original stem */
+ /* Now suppose the rectangle is rotated a bit so we can't make */
+ /* a stem from it. What do we do here? */
+ double inverseproj = (pd->sp->me.x-stem->right.x)*stem->unit.y -
+ (pd->sp->me.y-stem->right.y)*stem->unit.x;
+ if ( (width>0 && inverseproj>=0 && inverseproj<=width) ||
+ (width<0 && inverseproj<=0 && inverseproj>=-width)) {
+ pd->projection = (pd->sp->me.x - stem->left.x)*stem->unit.x +
+ (pd->sp->me.y - stem->left.y)*stem->unit.y;
+ if ( InActive(pd->projection,bothspace,bcnt) )
+ pspace[pcnt++] = pd;
+ }
+ }
+ qsort(pspace,pcnt,sizeof(struct pointdata *),proj_cmp);
+
+ bpos = i = 0;
+ while ( bpos<bcnt ) {
+ if ( bothspace[bpos].curved ) {
+ activespace[acnt++] = bothspace[bpos++];
+ } else {
+ last = bothspace[bpos].start;
+ while ( i<pcnt && pspace[i]->projection<bothspace[bpos].end ) {
+ if ( last<pspace[i]->projection ) {
+ if ( StemIsActiveAt(gd,stem,(1.001*last+pspace[i]->projection)/2.001) ) {
+ if ( acnt==0 || activespace[acnt-1].end!=last ) {
+ activespace[acnt ].curved = bothspace[bpos].curved;
+ activespace[acnt++].start = last;
+ }
+ activespace[acnt-1].end = pspace[i]->projection;
+ }
+ last = pspace[i]->projection;
+ }
+ ++i;
+ }
+ if ( StemIsActiveAt(gd,stem,(1.001*last+bothspace[bpos].end)/2.001) ) {
+ if ( acnt==0 || activespace[acnt-1].end!=last ) {
+ activespace[acnt ].curved = bothspace[bpos].curved;
+ activespace[acnt++].start = last;
+ }
+ activespace[acnt-1].end = bothspace[bpos].end;
+ }
+ ++bpos;
+ }
+ }
+ }
+
+ for ( i=0; i<stem->chunk_cnt; ++i ) {
+ struct stem_chunk *chunk = &stem->chunks[i];
+ if ( chunk->stemcheat==3 && chunk->l!=NULL && chunk->r!=NULL &&
+ i+1<stem->chunk_cnt &&
+ stem->chunks[i+1].stemcheat==3 && chunk->l==stem->chunks[i+1].l ) {
+ SplinePoint *sp = chunk->l->sp;
+ double proj = (sp->me.x - stem->left.x) *stem->unit.x +
+ (sp->me.y - stem->left.y) *stem->unit.y;
+ SplinePoint *sp2 = chunk->r->sp, *sp3 = stem->chunks[i+1].r->sp;
+ double proj2 = (sp2->me.x - stem->left.x) *stem->unit.x +
+ (sp2->me.y - stem->left.y) *stem->unit.y;
+ double proj3 = (sp3->me.x - stem->left.x) *stem->unit.x +
+ (sp3->me.y - stem->left.y) *stem->unit.y;
+ activespace[acnt ].curved = false;
+ if ( proj2<proj3 ) {
+ activespace[acnt ].start = proj2;
+ activespace[acnt ].end = proj3;
+ } else {
+ activespace[acnt ].start = proj3;
+ activespace[acnt ].end = proj2;
+ }
+ activespace[acnt++].base = proj;
+ ++i;
+ } else if ( chunk->stemcheat==4 && chunk->l!=NULL && chunk->r!=NULL ) {
+ SplinePoint *sp = chunk->l->sp;
+ SplinePoint *sp2 = chunk->r->sp;
+ double proj = (sp->me.x - stem->left.x) *stem->unit.x +
+ (sp->me.y - stem->left.y) *stem->unit.y;
+ double proj2 = (sp2->me.x - stem->left.x) *stem->unit.x +
+ (sp2->me.y - stem->left.y) *stem->unit.y;
+ activespace[acnt ].curved = false;
+ if ( proj2<proj ) {
+ activespace[acnt ].start = proj2;
+ activespace[acnt ].end = proj;
+ } else {
+ activespace[acnt ].start = proj;
+ activespace[acnt ].end = proj2;
+ }
+ activespace[acnt++].base = proj;
+ ++i;
+ } else if ( chunk->stemcheat && chunk->l!=NULL && chunk->r!=NULL ) {
+ SplinePoint *sp = chunk->l->sp;
+ double proj = (sp->me.x - stem->left.x) *stem->unit.x +
+ (sp->me.y - stem->left.y) *stem->unit.y, orig_proj=proj;
+ SplinePoint *other = chunk->lnext ? sp->next->to : sp->prev->from;
+ double len = (other->me.x-sp->me.x) * stem->unit.x +
+ (other->me.y-sp->me.y) * stem->unit.y;
+ double width = (stem->width<0) ? -stem->width : stem->width;
+ if ( chunk->stemcheat==2 )
+ proj -= width/2;
+ else if ( len<0 )
+ proj -= width;
+ activespace[acnt ].curved = true;
+ activespace[acnt ].start = proj;
+ activespace[acnt ].end = proj+width;
+ activespace[acnt++].base = orig_proj;
+ }
+ }
+
+ stem->activecnt = acnt;
+ if ( acnt!=0 ) {
+ stem->active = galloc(acnt*sizeof(struct segment));
+ memcpy(stem->active,activespace,acnt*sizeof(struct segment));
+ }
+ if ( stem->width<0 )
+ stem->width = -stem->width;
+
+ len = clen = 0;
+ for ( i=0; i<acnt; ++i ) {
+ if ( stem->active[i].curved )
+ clen += stem->active[i].end-stem->active[i].start;
+ else
+ len += stem->active[i].end-stem->active[i].start;
+ }
+ stem->len = len; stem->clen = len+clen;
+}
+
+static void GDStemsFixupIntersects(struct glyphdata *gd) {
+ int i,j;
+
+ for ( i=0; i<gd->stemcnt; ++i ) {
+ struct stemdata *stem = &gd->stems[i];
+ for ( j=0; j<stem->chunk_cnt; ++j ) {
+ struct stem_chunk *chunk = &stem->chunks[j];
+ if ( chunk->l!=NULL && stem==chunk->l->nextstem )
+ FixupT(stem,chunk->l,true);
+ if ( chunk->l!=NULL && stem==chunk->l->prevstem )
+ FixupT(stem,chunk->l,false);
+ if ( chunk->r!=NULL && stem==chunk->r->nextstem )
+ FixupT(stem,chunk->r,true);
+ if ( chunk->r!=NULL && stem==chunk->r->prevstem )
+ FixupT(stem,chunk->r,false);
+ }
+ }
+}
+
+static void GDFindMismatchedParallelStems(struct glyphdata *gd) {
+ int i;
+ struct pointdata *pd;
+ double width;
+
+ for ( i=0; i<gd->stemcnt; ++i ) {
+ struct stemdata *stem = &gd->stems[i];
+
+ width = (stem->left.x-stem->right.x)*stem->unit.y -
+ (stem->left.y-stem->right.y)*stem->unit.x;
+ if ( width<0 ) width = -width;
+ stem->width = width;
+ }
+
+ for ( i=0; i<gd->pcnt; ++i ) if ( (pd = &gd->points[i])->sp!=NULL && pd->colinear ) {
+ if ( pd->nextstem!=NULL && pd->prevstem!=NULL &&
+ pd->nextstem != pd->prevstem ) {
+ if ( pd->nextstem->width<pd->prevstem->width ) {
+ MakePDPotential(pd->prevstem,pd);
+ pd->prevstem = pd->nextstem;
+ } else {
+ MakePDPotential(pd->nextstem,pd);
+ pd->nextstem = pd->prevstem;
+ }
+ }
+ }
+}
+
+static void GDFindUnlikelyStems(struct glyphdata *gd) {
+ double width;
+ int i;
+ double em = (gd->sc->parent->ascent+gd->sc->parent->descent);
+
+ GDStemsFixupIntersects(gd);
+
+ GDFindMismatchedParallelStems(gd);
+
+ /* If a stem has straight edges, and it is wider than tall */
+ /* then it is unlikely to be a real stem */
+ for ( i=0; i<gd->stemcnt; ++i ) {
+ struct stemdata *stem = &gd->stems[i];
+
+ width = stem->width;
+ stem->toobig = ( width<=em/8 && 2.0*stem->clen < width ) ||
+ ( width>em/8 && width<=em/4 && 1.5*stem->clen < width ) ||
+ ( width>em/4 && stem->clen < width );
+ }
+}
+
+static void AddOpposite(struct glyphdata *gd,struct stem_chunk *chunk,
+ struct stemdata *stem) {
+ Spline *s;
+ double t;
+ struct pointdata **other;
+
+ if ( chunk->l!=NULL ) {
+ if ( chunk->l->nextstem == stem ) {
+ s = chunk->l->nextedge;
+ t = chunk->l->next_e_t;
+ } else {
+ s = chunk->l->prevedge;
+ t = chunk->l->prev_e_t;
+ }
+ other = &chunk->r;
+ } else {
+ if ( chunk->r->nextstem == stem ) {
+ s = chunk->r->nextedge;
+ t = chunk->r->next_e_t;
+ } else {
+ s = chunk->r->prevedge;
+ t = chunk->r->prev_e_t;
+ }
+ other = &chunk->l;
+ }
+ if ( s!=NULL && s->knownlinear ) {
+ struct pointdata *fpd = &gd->points[s->from->ttfindex];
+ struct pointdata *tpd = &gd->points[s->to->ttfindex];
+ if ( fpd->nextstem==NULL && OnStem(stem,&fpd->sp->me)) {
+ fpd->nextstem = stem;
+ fpd->next_is_l = chunk->l==NULL;
+ if ( t<.5 )
+ *other = fpd;
+ }
+ if ( tpd->prevstem == NULL && OnStem(stem,&tpd->sp->me)) {
+ tpd->prevstem = stem;
+ tpd->prev_is_l = chunk->l==NULL;
+ if ( t>.5 )
+ *other = tpd;
+ }
+ }
+}
+
+static void CheckForBoundingBoxHints(struct glyphdata *gd) {
+ /* Adobe seems to add hints at the bounding boxes of glyphs with no hints */
+ int hcnt=0, vcnt=0, i;
+ struct stemdata *stem;
+ SplinePoint *minx, *maxx, *miny, *maxy;
+ SplineFont *sf;
+ int emsize;
+ struct stem_chunk *chunk;
+
+ for ( i=0; i<gd->stemcnt; ++i ) {
+ stem = &gd->stems[i];
+ if ( stem->toobig )
+ break;
+ if ( stem->unit.x > .9 || stem->unit.x < -.9 )
+ ++hcnt;
+ else
+ ++vcnt;
+ }
+ if ( hcnt!=0 && vcnt!=0 )
+return;
+
+ minx = maxx = miny = maxy = NULL;
+ for ( i=0; i<gd->pcnt; ++i ) if ( gd->points[i].sp!=NULL ) {
+ SplinePoint *sp = gd->points[i].sp;
+ if ( minx==NULL )
+ minx = maxx = miny = maxy = sp;
+ else {
+ if ( minx->me.x>sp->me.x )
+ minx = sp;
+ else if ( maxx->me.x<sp->me.x )
+ maxx = sp;
+ if ( miny->me.y>sp->me.y )
+ miny = sp;
+ else if ( maxy->me.y<sp->me.y )
+ maxy = sp;
+ }
+ }
+
+ if ( minx==NULL ) /* No contours */
+return;
+
+ sf = gd->sc->parent;
+ emsize = sf->ascent+sf->descent;
+
+ if ( hcnt==0 && maxy->me.y!=miny->me.y && maxy->me.y-miny->me.y<emsize/2 ) {
+ struct pointdata *pd = &gd->points[maxy->ttfindex],
+ *pd2 = &gd->points[miny->ttfindex];
+ stem = FindOrMakeHVStem(gd,pd,pd2,true);
+ chunk = AddToStem(stem,pd,pd2,false,true,NULL);
+ chunk->stemcheat = 4;
+ FigureStemActive(gd,stem);
+ stem->toobig = false;
+ stem->clen += stem->width;
+ }
+
+ if ( vcnt==0 && maxx->me.x!=minx->me.x && maxx->me.x-minx->me.x<emsize/2 ) {
+ struct pointdata *pd = &gd->points[maxx->ttfindex],
+ *pd2 = &gd->points[minx->ttfindex];
+ stem = FindOrMakeHVStem(gd,pd,pd2,false);
+ chunk = AddToStem(stem,pd,pd2,false,true,NULL);
+ chunk->stemcheat = 4;
+ FigureStemActive(gd,stem);
+ stem->toobig = false;
+ stem->clen += stem->width;
+ }
+}
+
+struct glyphdata *GlyphDataBuild(SplineChar *sc, int only_hv) {
+ struct glyphdata *gd;
+ int i,j;
+ SplineSet *ss;
+ SplinePoint *sp;
+ Monotonic *m;
+ int cnt, goodcnt;
+ struct stemdata **sspace;
+ int em = sc->parent!=NULL ? sc->parent->ascent+sc->parent->descent : 1000;
+
+ /* We can't hint type3 fonts, so the only layer we care about is ly_fore */
+ /* We shan't try to hint references yet */
+ if ( sc->layers[ly_fore].splines==NULL )
+return( NULL );
+
+ dist_error_hv = .003*em;
+ dist_error_diag = .006*em;
+
+ gd = gcalloc(1,sizeof(struct glyphdata));
+ gd->only_hv = only_hv;
+
+ /* SSToMContours can clean up the splinesets (remove 0 length splines) */
+ /* so it must be called BEFORE everything else (even though logically */
+ /* that doesn't make much sense). Otherwise we might have a pointer */
+ /* to something since freed */
+ gd->ms = SSsToMContours(sc->layers[ly_fore].splines,over_remove); /* second argument is meaningless here */
+
+ gd->realcnt = gd->pcnt = SCNumberPoints(sc);
+ for ( i=0, ss=sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next, ++i );
+ gd->ccnt = i;
+ gd->contourends = galloc((i+1)*sizeof(int));
+ for ( i=0, ss=sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next, ++i ) {
+ SplinePoint *last;
+ if ( ss->first->prev!=NULL )
+ last = ss->first->prev->from;
+ else
+ last = ss->last;
+ if ( last->ttfindex==0xffff )
+ gd->contourends[i] = last->nextcpindex;
+ else
+ gd->contourends[i] = last->ttfindex;
+ }
+ gd->contourends[i] = -1;
+ gd->sc = sc;
+ gd->sf = sc->parent;
+ gd->fudge = (sc->parent->ascent+sc->parent->descent)/500;
+
+ /* Create temporary point numbers for the implied points. We need this */
+ /* for metafont if nothing else */
+ for ( ss= sc->layers[ly_fore].splines; ss!=NULL; ss = ss->next ) {
+ for ( sp = ss->first; ; ) {
+ if ( sp->ttfindex == 0xffff )
+ sp->ttfindex = gd->pcnt++;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ }
+ gd->norefpcnt = gd->pcnt;
+ /* And for 0xfffe points such as those used in glyphs with order2 glyphs */
+ /* with references. */
+ for ( ss= sc->layers[ly_fore].splines; ss!=NULL; ss = ss->next ) {
+ for ( sp = ss->first; ; ) {
+ if ( sp->ttfindex == 0xfffe )
+ sp->ttfindex = gd->pcnt++;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ }
+
+ gd->points = gcalloc(gd->pcnt,sizeof(struct pointdata));
+ for ( ss=sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) if ( ss->first->prev!=NULL ) {
+ for ( sp=ss->first; ; ) {
+ PointInit(gd,sp,ss);
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ }
+
+ /*gd->ms = SSsToMContours(sc->layers[ly_fore].splines,over_remove);*/ /* second argument is meaningless here */
+ for ( m=gd->ms, cnt=0; m!=NULL; m=m->linked, ++cnt );
+ gd->space = galloc((cnt+2)*sizeof(Monotonic*));
+ gd->mcnt = cnt;
+
+ for ( i=0; i<gd->pcnt; ++i ) if ( gd->points[i].sp!=NULL ) {
+ struct pointdata *pd = &gd->points[i];
+ if ( !pd->nextzero )
+ pd->nextedge = FindMatchingEdge(gd,pd,true,only_hv);
+ if ( !pd->prevzero )
+ pd->prevedge = FindMatchingEdge(gd,pd,false,only_hv);
+ if ( only_hv && (pd->symetrical_h || pd->symetrical_v ))
+ pd->bothedge = FindMatchingEdge(gd,pd,2,only_hv);
+
+ }
+
+#if 0
+ /* Consider the slash character. We have a diagonal stem capped with two */
+ /* horizontal lines. From the upper right corner, a line drawn normal to*/
+ /* the right diagonal stem will intersect the top cap, very close to the*/
+ /* upper right corner. That isn't interesting information */
+ for ( i=0; i<gd->pcnt; ++i ) if ( gd->points[i].sp!=NULL ) {
+ struct pointdata *pd = &gd->points[i];
+ if ( pd->nextedge == pd->sp->prev && pd->next_e_t>.9 &&
+ gd->points[pd->sp->prev->from->ttfindex].prevedge == pd->sp->next ) {
+ pd->nextedge = pd->sp->prev->from->prev;
+ pd->next_e_t = 1;
+ }
+ if ( pd->prevedge == pd->sp->next && pd->prev_e_t<.1 &&
+ gd->points[pd->sp->next->to->ttfindex].nextedge == pd->sp->prev ) {
+ pd->prevedge = pd->sp->next->to->next;
+ pd->prev_e_t = 0;
+ }
+ }
+#endif
+
+ /* There will never be more lines than there are points (counting next/prev as separate) */
+ gd->lines = galloc(2*gd->pcnt*sizeof(struct linedata));
+ gd->linecnt = 0;
+ gd->pspace = galloc(gd->pcnt*sizeof(struct pointdata *));
+ for ( i=0; i<gd->pcnt; ++i ) if ( gd->points[i].sp!=NULL ) {
+ struct pointdata *pd = &gd->points[i];
+ if (( !only_hv || pd->next_hor || pd->next_ver ) && pd->nextline==NULL ) {
+ pd->nextline = BuildLine(gd,pd,true);
+ if ( pd->colinear )
+ pd->prevline = pd->nextline;
+ }
+ if (( !only_hv || pd->prev_hor || pd->prev_ver ) && pd->prevline==NULL ) {
+ pd->prevline = BuildLine(gd,pd,false);
+ if ( pd->colinear && pd->nextline == NULL )
+ pd->nextline = pd->prevline;
+ }
+ }
+
+ /* There will never be more stems than there are points (counting next/prev as separate) */
+ gd->stems = gcalloc(2*gd->pcnt,sizeof(struct stemdata));
+ gd->stemcnt = 0; /* None used so far */
+ for ( i=0; i<gd->pcnt; ++i ) if ( gd->points[i].sp!=NULL ) {
+ struct pointdata *pd = &gd->points[i];
+ if ( pd->nextedge!=NULL /*&& pd->nextstem==NULL*/ )
+ BuildStem(gd,pd,true);
+ if ( pd->prevedge!=NULL /*&& pd->prevstem==NULL*/ )
+ BuildStem(gd,pd,false);
+ if ( pd->bothedge!=NULL )
+ DiagonalCornerStem(gd,pd);
+ }
+ for ( i=0; i<gd->pcnt; ++i ) if ( gd->points[i].sp!=NULL ) {
+ struct pointdata *pd = &gd->points[i];
+ if ( pd->nextstem==NULL && pd->colinear ) {
+ pd->nextstem = pd->prevstem;
+ pd->next_is_l = pd->prev_is_l;
+ } else if ( pd->prevstem==NULL && pd->colinear ) {
+ pd->prevstem = pd->nextstem;
+ pd->prev_is_l = pd->next_is_l;
+ }
+ }
+
+ sspace = galloc(gd->stemcnt*sizeof(struct stemdata *));
+ for ( i=j=0; i<gd->stemcnt; ++i ) /*if ( !gd->stems[i].toobig )*/
+ sspace[j++] = &gd->stems[i];
+ goodcnt = j;
+ qsort(sspace,goodcnt,sizeof(struct stemdata *),swidth_cmp);
+
+ /* we were cautious about assigning points to stems, go back now and see */
+ /* if there are any low-quality matches which remain unassigned, and if */
+ /* so then assign them to the stem they almost fit on. */
+ /* If there are multiple stems, find the one which is closest to this point */
+ for ( i=0; i<goodcnt; ++i ) {
+ struct stemdata *stem = sspace[i];
+ for ( j=0; j<stem->chunk_cnt; ++j ) {
+ struct stem_chunk *chunk = &stem->chunks[j];
+ if ( chunk->l==NULL && chunk->lpotential!=NULL &&
+ IsClosestPotential(sspace,i,goodcnt,true,chunk))
+ chunk->l = PotentialAdd(gd,stem,chunk->lpotential,chunk->lnext);
+ if ( chunk->r==NULL && chunk->rpotential!=NULL &&
+ IsClosestPotential(sspace,i,goodcnt,false,chunk))
+ chunk->r = PotentialAdd(gd,stem,chunk->rpotential,chunk->rnext);
+ }
+ }
+ for ( i=0; i<goodcnt; ++i ) {
+ struct stemdata *stem = sspace[i];
+ for ( j=0; j<stem->chunk_cnt; ++j ) {
+ struct stem_chunk *chunk = &stem->chunks[j];
+ if (( chunk->l!=NULL && chunk->r==NULL ) ||
+ ( chunk->l==NULL && chunk->r!=NULL ))
+ AddOpposite(gd,chunk,stem);
+ }
+ }
+ free(sspace);
+
+ gd->lspace = galloc(gd->pcnt*sizeof(struct segment));
+ gd->rspace = galloc(gd->pcnt*sizeof(struct segment));
+ gd->bothspace = galloc(3*gd->pcnt*sizeof(struct segment));
+ gd->activespace = galloc(3*gd->pcnt*sizeof(struct segment));
+ for ( i=j=0; i<gd->stemcnt; ++i )
+ FigureStemActive(gd,&gd->stems[i]);
+
+ if ( only_hv && hint_bounding_boxes )
+ CheckForBoundingBoxHints(gd);
+
+ FreeMonotonics(gd->ms); gd->ms = NULL;
+ free(gd->space); gd->space = NULL;
+ free(gd->sspace); gd->sspace = NULL;
+ free(gd->stspace); gd->stspace = NULL;
+ free(gd->pspace); gd->pspace = NULL;
+ free(gd->lspace); gd->lspace = NULL;
+ free(gd->rspace); gd->rspace = NULL;
+ free(gd->bothspace); gd->bothspace = NULL;
+ free(gd->activespace); gd->activespace = NULL;
+
+ GDFindUnlikelyStems(gd);
+
+return( gd );
+}
+
+void GlyphDataFree(struct glyphdata *gd) {
+ int i;
+
+ /* Restore implicit points */
+ for ( i=gd->realcnt; i<gd->norefpcnt; ++i )
+ gd->points[i].sp->ttfindex = 0xffff;
+ for ( i=gd->norefpcnt; i<gd->pcnt; ++i )
+ gd->points[i].sp->ttfindex = 0xfffe;
+
+ for ( i=0; i<gd->linecnt; ++i )
+ free(gd->lines[i].points);
+ for ( i=0; i<gd->stemcnt; ++i ) {
+ free(gd->stems[i].chunks);
+ free(gd->stems[i].active);
+ }
+ free(gd->lines);
+ free(gd->stems);
+ free(gd->contourends);
+ free(gd->points);
+ free(gd);
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/stemdb.h b/Build/source/libs/luafontforge/fontforge/fontforge/stemdb.h
new file mode 100644
index 00000000000..149792a65f3
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/stemdb.h
@@ -0,0 +1,153 @@
+/* Copyright (C) 2005-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _STEMDB_H_
+# define _STEMDB_H_
+
+# include "pfaedit.h"
+
+struct glyphdata {
+ SplineFont *sf;
+ BlueData bd;
+ SplineChar *sc;
+ int fudge;
+ int ccnt;
+ int *contourends;
+ int realcnt; /* Includes control points, excludes implied points */
+ int norefpcnt; /* Does not include points in glyphs with references */
+ int pcnt; /* Includes control points, includes implied points */
+ struct pointdata *points; /* Entries corresponding to control points are empty */
+ int stemcnt;
+ struct stemdata *stems;
+ int linecnt;
+ struct linedata *lines;
+
+ /* Temporary values, quickly freed */
+ int mcnt;
+ struct monotonic *ms;
+ struct monotonic **space;
+ int scnt;
+ Spline **sspace;
+ struct st *stspace;
+ DBounds size;
+ struct pointdata **pspace;
+ struct stembundle *bundles;
+ struct segment { double start, end, base; int curved; } *lspace, *rspace, *bothspace, *activespace;
+
+ int only_hv;
+};
+
+struct pointdata {
+ SplinePoint *sp;
+ SplineSet *ss;
+ BasePoint nextunit, prevunit; /* unit vectors pointing in the next/prev directions */
+ struct linedata *nextline, *prevline; /* any other points lying on approximately the same line */
+ Spline *nextedge, *prevedge; /* There should always be a matching spline, which may end up as part of a stem, and may not */
+ Spline *bothedge;
+ double next_e_t, prev_e_t; /* Location on other edge where our normal hits it */
+ double both_e_t;
+ struct stemdata *nextstem, *prevstem;
+ struct stemdata *bothstem;
+ double nextlen, prevlen;
+ unsigned int nextlinear: 1;
+ unsigned int nextzero: 1;
+ unsigned int prevlinear: 1;
+ unsigned int prevzero: 1;
+ unsigned int colinear: 1;
+ unsigned int symetrical_h: 1; /* Are next & prev symetrical? */
+ unsigned int symetrical_v: 1; /* Are next & prev symetrical? */
+ unsigned int next_hor: 1;
+ unsigned int next_ver: 1;
+ unsigned int prev_hor: 1;
+ unsigned int prev_ver: 1;
+ unsigned int newpos_set: 2; /* Holds three values: 0 (not), 1 (positioned by 1 stem), 2 (2 stems) */
+ unsigned int next_is_l: 1;
+ unsigned int prev_is_l: 1;
+ BasePoint newpos;
+ BasePoint newnext, newprev;
+ BasePoint posdir; /* If point has been positioned in 1 direction, this is that direction */
+ double projection; /* temporary value */
+};
+
+struct linedata {
+ BasePoint unitvector;
+ BasePoint online;
+ int pcnt;
+ struct pointdata **points;
+};
+
+struct stemdata {
+ BasePoint unit; /* Unit vector pointing in direction of stem */
+ BasePoint l_to_r; /* Unit vector pointing from left to right (across stem) */
+ BasePoint left; /* a point on one side of the stem (not necissarily left, even for vertical stems) */
+ BasePoint right; /* and one on the other */
+ double width;
+ int chunk_cnt; /* number of separate point-pairs on this stem */
+ struct stem_chunk {
+ struct pointdata *l;
+ struct pointdata *r;
+ struct pointdata *lpotential, *rpotential;
+ uint8 lnext, rnext; /* are we using the next/prev side of the left/right points */
+ uint8 ltick, rtick;
+ uint8 stemcheat; /* It's not a real stem, but it's something we'd like PostScript to hint for us */
+ } *chunks;
+ int activecnt;
+ struct segment *active;
+ uint8 toobig; /* Stem is fatter than tall, unlikely to be a real stem */
+ uint8 positioned;
+ uint8 ticked;
+ double len, clen; /* Length of linear segments. clen adds "length" of curved bits */
+ struct stembundle *bundle;
+ double lpos, rpos; /* When placed in a bundle, relative to the bundle's basepoint in l_to_r */
+ double lnew, rnew; /* New position of left, right edges relative to bp,l_to_r */
+};
+
+struct stembounds {
+ struct stembounds *next;
+ struct stemdata *stem;
+ double tstart, tend;
+ uint8 isr;
+};
+
+struct splinesteminfo {
+ Spline *s;
+ struct stembounds *sb;
+};
+
+struct stembundle {
+ BasePoint *unit; /* All these stems are parallel, pointing in unit direction */
+ BasePoint *l_to_r; /* Axis along which these stems are ordered (normal to unit) */
+ BasePoint *bp; /* Base point for measuring by l_to_r (stem->lpos,rpos) */
+ int cnt; /* Number of stems in the bundle */
+ struct stemdata **stemlist;
+ struct stembundle *next;
+};
+
+
+extern struct glyphdata *GlyphDataBuild(SplineChar *sc, int only_hv);
+extern void GlyphDataFree(struct glyphdata *gd);
+
+#endif /* _STEMDB_H_ */
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/tottf.c b/Build/source/libs/luafontforge/fontforge/fontforge/tottf.c
new file mode 100644
index 00000000000..d132be86f6f
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/tottf.c
@@ -0,0 +1,5768 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+#include <locale.h>
+#include <utype.h>
+#include <ustring.h>
+#include <chardata.h>
+#include <gwidget.h>
+
+#ifdef __CygWin
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
+#endif
+
+#ifdef LUA_FF_LIB
+extern int unic_islefttoright(int);
+extern int unic_isdigit(int);
+#define islefttoright unic_islefttoright
+#define isdigit unic_isdigit
+#endif
+
+
+#include "ttf.h"
+
+/* This file produces a ttf file given a splinefont. */
+
+/* ************************************************************************** */
+
+/* Required tables:
+ cmap encoding
+ head header data
+ hhea horizontal metrics header data
+ hmtx horizontal metrics (widths, lsidebearing)
+ maxp various maxima in the font
+ name various names associated with the font
+ post postscript names and other stuff
+Required by windows but not mac
+ OS/2 bleah.
+Required for TrueType
+ loca pointers to the glyphs
+ glyf character shapes
+Required for OpenType (Postscript)
+ CFF A complete postscript CFF font here with all its internal tables
+Required for bitmaps
+ bdat/EBDT bitmap data
+ bloc/EBLC pointers to bitmaps
+ bhed for apple bitmap only fonts, replaces head
+Optional for bitmaps
+ EBSC bitmap scaling table (used in windows "bitmap-only" fonts)
+"Advanced Typograpy"
+ Apple
+ feat (mapping between morx features and 'name' names)
+ kern (if data are present)
+ lcar (ligature caret, if data present)
+ morx (substitutions, if data present)
+ prop (glyph properties, if data present)
+ opbd (optical bounds, if data present)
+ OpenType
+ GPOS (opentype, if kern,anchor data are present)
+ GSUB (opentype, if ligature (other subs) data are present)
+ GDEF (opentype, if anchor data are present)
+Apple variation tables (for distortable (multiple master type) fonts)
+ fvar (font variations)
+ gvar (glyph variations)
+ cvar (cvt variations)
+ avar (axis variations)
+additional tables
+ cvt for hinting
+ gasp to control when things should be hinted
+ fpgm for hinting (currently only copied and dumped verbatim)
+ prep for hinting (currently only copied and dumped verbatim)
+FontForge
+ PfEd My own table
+TeX
+ TeX TeX specific info (stuff that used to live in tfm files)
+*/
+
+const char *ttfstandardnames[258] = {
+".notdef",
+".null",
+"nonmarkingreturn",
+"space",
+"exclam",
+"quotedbl",
+"numbersign",
+"dollar",
+"percent",
+"ampersand",
+"quotesingle",
+"parenleft",
+"parenright",
+"asterisk",
+"plus",
+"comma",
+"hyphen",
+"period",
+"slash",
+"zero",
+"one",
+"two",
+"three",
+"four",
+"five",
+"six",
+"seven",
+"eight",
+"nine",
+"colon",
+"semicolon",
+"less",
+"equal",
+"greater",
+"question",
+"at",
+"A",
+"B",
+"C",
+"D",
+"E",
+"F",
+"G",
+"H",
+"I",
+"J",
+"K",
+"L",
+"M",
+"N",
+"O",
+"P",
+"Q",
+"R",
+"S",
+"T",
+"U",
+"V",
+"W",
+"X",
+"Y",
+"Z",
+"bracketleft",
+"backslash",
+"bracketright",
+"asciicircum",
+"underscore",
+"grave",
+"a",
+"b",
+"c",
+"d",
+"e",
+"f",
+"g",
+"h",
+"i",
+"j",
+"k",
+"l",
+"m",
+"n",
+"o",
+"p",
+"q",
+"r",
+"s",
+"t",
+"u",
+"v",
+"w",
+"x",
+"y",
+"z",
+"braceleft",
+"bar",
+"braceright",
+"asciitilde",
+"Adieresis",
+"Aring",
+"Ccedilla",
+"Eacute",
+"Ntilde",
+"Odieresis",
+"Udieresis",
+"aacute",
+"agrave",
+"acircumflex",
+"adieresis",
+"atilde",
+"aring",
+"ccedilla",
+"eacute",
+"egrave",
+"ecircumflex",
+"edieresis",
+"iacute",
+"igrave",
+"icircumflex",
+"idieresis",
+"ntilde",
+"oacute",
+"ograve",
+"ocircumflex",
+"odieresis",
+"otilde",
+"uacute",
+"ugrave",
+"ucircumflex",
+"udieresis",
+"dagger",
+"degree",
+"cent",
+"sterling",
+"section",
+"bullet",
+"paragraph",
+"germandbls",
+"registered",
+"copyright",
+"trademark",
+"acute",
+"dieresis",
+"notequal",
+"AE",
+"Oslash",
+"infinity",
+"plusminus",
+"lessequal",
+"greaterequal",
+"yen",
+"mu",
+"partialdiff",
+"summation",
+"product",
+"pi",
+"integral",
+"ordfeminine",
+"ordmasculine",
+"Omega",
+"ae",
+"oslash",
+"questiondown",
+"exclamdown",
+"logicalnot",
+"radical",
+"florin",
+"approxequal",
+"Delta",
+"guillemotleft",
+"guillemotright",
+"ellipsis",
+"nonbreakingspace",
+"Agrave",
+"Atilde",
+"Otilde",
+"OE",
+"oe",
+"endash",
+"emdash",
+"quotedblleft",
+"quotedblright",
+"quoteleft",
+"quoteright",
+"divide",
+"lozenge",
+"ydieresis",
+"Ydieresis",
+"fraction",
+"currency",
+"guilsinglleft",
+"guilsinglright",
+"fi",
+"fl",
+"daggerdbl",
+"periodcentered",
+"quotesinglbase",
+"quotedblbase",
+"perthousand",
+"Acircumflex",
+"Ecircumflex",
+"Aacute",
+"Edieresis",
+"Egrave",
+"Iacute",
+"Icircumflex",
+"Idieresis",
+"Igrave",
+"Oacute",
+"Ocircumflex",
+"apple",
+"Ograve",
+"Uacute",
+"Ucircumflex",
+"Ugrave",
+"dotlessi",
+"circumflex",
+"tilde",
+"macron",
+"breve",
+"dotaccent",
+"ring",
+"cedilla",
+"hungarumlaut",
+"ogonek",
+"caron",
+"Lslash",
+"lslash",
+"Scaron",
+"scaron",
+"Zcaron",
+"zcaron",
+"brokenbar",
+"Eth",
+"eth",
+"Yacute",
+"yacute",
+"Thorn",
+"thorn",
+"minus",
+"multiply",
+"onesuperior",
+"twosuperior",
+"threesuperior",
+"onehalf",
+"onequarter",
+"threequarters",
+"franc",
+"Gbreve",
+"gbreve",
+"Idotaccent",
+"Scedilla",
+"scedilla",
+"Cacute",
+"cacute",
+"Ccaron",
+"ccaron",
+"dcroat"
+};
+
+static int uniranges[][3] = {
+ { 0x20, 0x7e, 0 }, /* Basic Latin */
+ { 0xa0, 0xff, 1 }, /* Latin-1 Supplement */
+ { 0x100, 0x17f, 2 }, /* Latin Extended-A */
+ { 0x180, 0x24f, 3 }, /* Latin Extended-B */
+ { 0x250, 0x2af, 4 }, /* IPA Extensions */
+ { 0x2b0, 0x2ff, 5 }, /* Spacing Modifier Letters */
+ { 0x300, 0x36f, 6 }, /* Combining Diacritical Marks */
+ { 0x370, 0x3ff, 7 }, /* Greek */
+ { 0x400, 0x52f, 9 }, /* Cyrillic / Cyrillic Supplement */
+ { 0x530, 0x58f, 10 }, /* Armenian */
+ { 0x590, 0x5ff, 11 }, /* Hebrew */
+ { 0x600, 0x6ff, 13 }, /* Arabic */
+ { 0x700, 0x74f, 71 }, /* Syriac */
+ { 0x780, 0x7bf, 72 }, /* Thaana */
+ { 0x900, 0x97f, 15 }, /* Devanagari */
+ { 0x980, 0x9ff, 16 }, /* Bengali */
+ { 0xa00, 0xa7f, 17 }, /* Gurmukhi */
+ { 0xa80, 0xaff, 18 }, /* Gujarati */
+ { 0xb00, 0xb7f, 19 }, /* Oriya */
+ { 0xb80, 0xbff, 20 }, /* Tamil */
+ { 0xc00, 0xc7f, 21 }, /* Telugu */
+ { 0xc80, 0xcff, 22 }, /* Kannada */
+ { 0xd00, 0xd7f, 23 }, /* Malayalam */
+ { 0xd80, 0xdff, 73 }, /* Sinhala */
+ { 0xe00, 0xe7f, 24 }, /* Thai */
+ { 0xe80, 0xeff, 25 }, /* Lao */
+ { 0xf00, 0xfbf, 70 }, /* Tibetan */
+ { 0x1000, 0x109f, 74 }, /* Myanmar */
+ { 0x10a0, 0x10ff, 26 }, /* Georgian */
+ { 0x1100, 0x11ff, 28 }, /* Hangul Jamo */
+ { 0x1200, 0x137f, 75 }, /* Ethiopic */
+ { 0x13a0, 0x13ff, 76 }, /* Cherokee */
+ { 0x1400, 0x167f, 77 }, /* Unified Canadian Aboriginal Symbols */
+ { 0x1680, 0x169f, 78 }, /* Ogham */
+ { 0x16a0, 0x16ff, 79 }, /* Runic */
+ { 0x1700, 0x177f, 84 }, /* Tagalog / Harunoo / Buhid / Tagbanwa */
+ { 0x1780, 0x17ff, 80 }, /* Khmer */
+ { 0x1800, 0x18af, 81 }, /* Mongolian */
+ /* { 0x1900, 0x194f, }, Limbu */
+ /* { 0x1950, 0x197f, }, Tai le */
+ /* { 0x19e0, 0x19ff, }, Khmer Symbols */
+ /* { 0x1d00, 0x1d7f, }, Phonetic Extensions */
+ { 0x1e00, 0x1eff, 29 }, /* Latin Extended Additional */
+ { 0x1f00, 0x1fff, 30 }, /* Greek Extended */
+ { 0x2000, 0x206f, 31 }, /* General Punctuation */
+ { 0x2070, 0x209f, 32 }, /* Superscripts and Subscripts */
+ { 0x20a0, 0x20cf, 33 }, /* Currency Symbols */
+ { 0x20d0, 0x20ff, 34 }, /* Combining Marks for Symbols */
+ { 0x2100, 0x214f, 35 }, /* Letterlike Symbols */
+ { 0x2150, 0x218f, 36 }, /* Number Forms */
+ { 0x2190, 0x21ff, 37 }, /* Arrows */
+ { 0x2200, 0x22ff, 38 }, /* Mathematical Operators */
+ { 0x2300, 0x237f, 39 }, /* Miscellaneous Technical */
+ { 0x2400, 0x243f, 40 }, /* Control Pictures */
+ { 0x2440, 0x245f, 41 }, /* Optical Character Recognition */
+ { 0x2460, 0x24ff, 42 }, /* Enclosed Alphanumerics */
+ { 0x2500, 0x257f, 43 }, /* Box Drawing */
+ { 0x2580, 0x259f, 44 }, /* Block Elements */
+ { 0x25a0, 0x25ff, 45 }, /* Geometric Shapes */
+ { 0x2600, 0x267f, 46 }, /* Miscellaneous Symbols */
+ { 0x2700, 0x27bf, 47 }, /* Dingbats */
+ { 0x27c0, 0x27ef, 38 }, /* Miscellaneous Mathematical Symbols-A */
+ { 0x27f0, 0x27ff, 37 }, /* Supplementary Arrows-A */
+ { 0x2800, 0x28ff, 82 }, /* Braille Patterns */
+ { 0x2900, 0x297f, 37 }, /* Supplementary Arrows-B */
+ { 0x2980, 0x2aff, 38 }, /* Miscellaneous Mathematical Symbols-B /
+ Supplemental Mathematical Operators */
+ { 0x2e80, 0x2fff, 59 }, /* CJK Radicals Supplement / Kangxi Radicals /
+ Ideographic Description Characters */
+ { 0x3000, 0x303f, 48 }, /* CJK Symbols and Punctuation */
+ { 0x3040, 0x309f, 49 }, /* Hiragana */
+ { 0x30a0, 0x30ff, 50 }, /* Katakana */
+ { 0x3100, 0x312f, 51 }, /* Bopomofo */
+ { 0x3130, 0x318f, 52 }, /* Hangul Compatibility Jamo */
+ { 0x3190, 0x319f, 59 }, /* Kanbun */
+ { 0x31a0, 0x31bf, 51 }, /* Bopomofo Extended */
+ { 0x31f0, 0x31ff, 50 }, /* Katakana Phonetic Extensions */
+ { 0x3200, 0x32ff, 54 }, /* Enclosed CJK Letters and Months */
+ { 0x3300, 0x33ff, 55 }, /* CJK compatability */
+ { 0x3400, 0x4dbf, 59 }, /* CJK Unified Ideographs Extension A */
+ /* { 0x4dc0, 0x4dff, }, Yijing Hexagram Symbols */
+ { 0x4e00, 0x9fff, 59 }, /* CJK Unified Ideographs */
+ { 0xa000, 0xa4cf, 81 }, /* Yi Syllables / Yi Radicals */
+ { 0xac00, 0xd7af, 56 }, /* Hangul */
+ { 0xe000, 0xf8ff, 60 }, /* Private Use Area */
+
+ { 0xf900, 0xfaff, 61 }, /* CJK Compatibility Ideographs */
+ /* 12 ideographs in The IBM 32 Compatibility Additions are CJK unified
+ ideographs despite their names: see The Unicode Standard 4.0, p.475 */
+ { 0xfa0e, 0xfa0f, 59 },
+ { 0xfa10, 0xfa10, 61 },
+ { 0xfa11, 0xfa11, 59 },
+ { 0xfa12, 0xfa12, 61 },
+ { 0xfa13, 0xfa14, 59 },
+ { 0xfa15, 0xfa1e, 61 },
+ { 0xfa1f, 0xfa1f, 59 },
+ { 0xfa20, 0xfa20, 61 },
+ { 0xfa21, 0xfa21, 59 },
+ { 0xfa22, 0xfa22, 61 },
+ { 0xfa23, 0xfa24, 59 },
+ { 0xfa25, 0xfa26, 61 },
+ { 0xfa27, 0xfa29, 59 },
+ { 0xfa2a, 0xfaff, 61 }, /* CJK Compatibility Ideographs */
+
+ { 0xfb00, 0xfb4f, 62 }, /* Alphabetic Presentation Forms */
+ { 0xfb50, 0xfdff, 63 }, /* Arabic Presentation Forms-A */
+ { 0xfe00, 0xfe0f, 91 }, /* Variation Selectors */
+ { 0xfe20, 0xfe2f, 64 }, /* Combining Half Marks */
+ { 0xfe30, 0xfe4f, 65 }, /* CJK Compatibility Forms */
+ { 0xfe50, 0xfe6f, 66 }, /* Small Form Variants */
+ { 0xfe70, 0xfeef, 67 }, /* Arabic Presentation Forms-B */
+ { 0xff00, 0xffef, 68 }, /* Halfwidth and Fullwidth Forms */
+ { 0xfff0, 0xffff, 69 }, /* Specials */
+
+ /* { 0x10000, 0x1007f, }, Linear B Syllabary */
+ /* { 0x10080, 0x100ff, }, Linear B Ideograms */
+ /* { 0x10100, 0x1013f, }, Aegean Numbers */
+ { 0x10300, 0x1032f, 85 }, /* Old Italic */
+ { 0x10330, 0x1034f, 86 }, /* Gothic */
+ { 0x10400, 0x1044f, 87 }, /* Deseret */
+ /* { 0x10450, 0x1047f, }, Shavian */
+ /* { 0x10480, 0x104af, }, Osmanya */
+ /* { 0x10800, 0x1083f, }, Cypriot Syllabary */
+ { 0x1d000, 0x1d1ff, 88 }, /* Byzantine Musical Symbols / Musical Symbols */
+ /* { 0x1d300, 0x1d35f, }, Tai Xuan Jing Symbols */
+ { 0x1d400, 0x1d7ff, 89 }, /* Mathematical Alphanumeric Symbols */
+ { 0x20000, 0x2a6df, 59 }, /* CJK Unified Ideographs Extension B */
+ { 0x2f800, 0x2fa1f, 61 }, /* CJK Compatibility Ideographs Supplement */
+ { 0xe0000, 0xe007f, 92 }, /* Tags */
+ { 0xe0100, 0xe01ef, 91 }, /* Variation Selectors Supplement */
+ { 0xf0000, 0xffffd, 90 }, /* Supplementary Private Use Area-A */
+ { 0x100000, 0x10fffd, 90 }, /* Supplementary Private Use Area-B */
+};
+
+static int32 getuint32(FILE *ttf) {
+ int ch1 = getc(ttf);
+ int ch2 = getc(ttf);
+ int ch3 = getc(ttf);
+ int ch4 = getc(ttf);
+ if ( ch4==EOF )
+return( EOF );
+return( (ch1<<24)|(ch2<<16)|(ch3<<8)|ch4 );
+}
+
+void putshort(FILE *file,int sval) {
+ putc((sval>>8)&0xff,file);
+ putc(sval&0xff,file);
+}
+
+void putlong(FILE *file,int val) {
+ putc((val>>24)&0xff,file);
+ putc((val>>16)&0xff,file);
+ putc((val>>8)&0xff,file);
+ putc(val&0xff,file);
+}
+#define dumpabsoffset putlong
+
+static void dumpoffset(FILE *file,int offsize,int val) {
+ if ( offsize==1 )
+ putc(val,file);
+ else if ( offsize==2 )
+ putshort(file,val);
+ else if ( offsize==3 ) {
+ putc((val>>16)&0xff,file);
+ putc((val>>8)&0xff,file);
+ putc(val&0xff,file);
+ } else
+ putlong(file,val);
+}
+
+static void put2d14(FILE *file,real dval) {
+ int val;
+ int mant;
+
+ val = floor(dval);
+ mant = floor(16384.*(dval-val));
+ val = (val<<14) | mant;
+ putshort(file,val);
+}
+
+void putfixed(FILE *file,real dval) {
+ int val;
+ int mant;
+
+ val = floor(dval);
+ mant = floor(65536.*(dval-val));
+ val = (val<<16) | mant;
+ putlong(file,val);
+}
+
+int ttfcopyfile(FILE *ttf, FILE *other, int pos, char *tab_name) {
+ int ch;
+ int ret = 1;
+
+ if ( ferror(ttf) || ferror(other)) {
+ IError("Disk error of some nature. Perhaps no space on device?\nGenerated font will be unusable" );
+ } else if ( pos!=ftell(ttf)) {
+ IError("File Offset wrong for ttf table (%s), %d expected %d", tab_name, ftell(ttf), pos );
+ }
+ rewind(other);
+ while (( ch = getc(other))!=EOF )
+ putc(ch,ttf);
+ if ( ferror(other)) ret = 0;
+ if ( fclose(other)) ret = 0;
+return( ret );
+}
+
+static void FigureFullMetricsEnd(SplineFont *sf,struct glyphinfo *gi, int istt ) {
+ /* We can reduce the size of the width array by removing a run at the end */
+ /* of the same width. So start at the end, find the width of the last */
+ /* character we'll output, then run backwards as long as we've got the */
+ /* same width */
+ /* (do same thing for vertical metrics too */
+ int i, lasti, lastv, lastdefault = istt ? 3 : 1;
+ int width, vwidth;
+
+ lasti = lastv = gi->gcnt-1;
+ for ( i=gi->gcnt-1; i>lastdefault && gi->bygid[i]==-1; --i );
+ if ( i>=lastdefault ) {
+ width = sf->glyphs[gi->bygid[i]]->width;
+ vwidth = sf->glyphs[gi->bygid[i]]->vwidth;
+ lasti = lastv = i;
+ for ( i=lasti-1; i>=lastdefault; --i ) {
+ if ( SCWorthOutputting(sf->glyphs[gi->bygid[i]]) ) {
+ if ( sf->glyphs[gi->bygid[i]]->width!=width )
+ break;
+ else
+ lasti = i;
+ }
+ }
+ gi->lasthwidth = lasti;
+ if ( sf->hasvmetrics ) {
+ for ( i=lastv-1; i>=lastdefault; --i ) {
+ if ( SCWorthOutputting(sf->glyphs[gi->bygid[i]]) ) {
+ if ( sf->glyphs[gi->bygid[i]]->vwidth!=vwidth )
+ break;
+ else
+ lastv = i;
+ }
+ }
+ gi->lastvwidth = lastv;
+ }
+ } else {
+ gi->lasthwidth = 0;
+ gi->lastvwidth = 0;
+ }
+}
+
+static void dumpghstruct(struct glyphinfo *gi,struct glyphhead *gh) {
+
+ putshort(gi->glyphs,gh->numContours);
+ putshort(gi->glyphs,gh->xmin);
+ putshort(gi->glyphs,gh->ymin);
+ putshort(gi->glyphs,gh->xmax);
+ putshort(gi->glyphs,gh->ymax);
+ if ( gh->xmin<gi->xmin ) gi->xmin = gh->xmin;
+ if ( gh->ymin<gi->ymin ) gi->ymin = gh->ymin;
+ if ( gh->xmax>gi->xmax ) gi->xmax = gh->xmax;
+ if ( gh->ymax>gi->ymax ) gi->ymax = gh->ymax;
+}
+
+static void ttfdumpmetrics(SplineChar *sc,struct glyphinfo *gi,DBounds *b) {
+
+ if ( sc->ttf_glyph<=gi->lasthwidth )
+ putshort(gi->hmtx,sc->width);
+ putshort(gi->hmtx,b->minx);
+ if ( sc->parent->hasvmetrics ) {
+ if ( sc->ttf_glyph<=gi->lastvwidth )
+ putshort(gi->vmtx,sc->vwidth);
+ putshort(gi->vmtx,sc->parent->vertical_origin-b->maxy);
+ }
+ if ( sc->ttf_glyph==gi->lasthwidth )
+ gi->hfullcnt = sc->ttf_glyph+1;
+ if ( sc->ttf_glyph==gi->lastvwidth )
+ gi->vfullcnt = sc->ttf_glyph+1;
+}
+
+static SplineSet *SCttfApprox(SplineChar *sc) {
+ SplineSet *head=NULL, *last=NULL, *ss, *tss;
+ RefChar *ref;
+
+ for ( ss=sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) {
+ tss = sc->parent->order2 ? SplinePointListCopy1(ss) : SSttfApprox(ss);
+ if ( head==NULL ) head = tss;
+ else last->next = tss;
+ last = tss;
+ }
+ for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
+ for ( ss=ref->layers[0].splines; ss!=NULL; ss=ss->next ) {
+ tss = sc->parent->order2 ? SplinePointListCopy1(ss) : SSttfApprox(ss);
+ if ( head==NULL ) head = tss;
+ else last->next = tss;
+ last = tss;
+ }
+ }
+return( head );
+}
+
+#define _On_Curve 1
+#define _X_Short 2
+#define _Y_Short 4
+#define _Repeat 8
+#define _X_Same 0x10
+#define _Y_Same 0x20
+
+int SSAddPoints(SplineSet *ss,int ptcnt,BasePoint *bp, char *flags) {
+ SplinePoint *sp, *first, *nextsp;
+ int startcnt = ptcnt;
+
+ if ( ss->first->prev!=NULL &&
+ ss->first->prev->from->nextcpindex==startcnt ) {
+ if ( flags!=NULL ) flags[ptcnt] = 0;
+ bp[ptcnt].x = rint(ss->first->prevcp.x);
+ bp[ptcnt++].y = rint(ss->first->prevcp.y);
+ } else if ( ss->first->ttfindex!=ptcnt && ss->first->ttfindex!=0xfffe )
+ IError("Unexpected point count in SSAddPoints" );
+
+ first = NULL;
+ for ( sp=ss->first; sp!=first ; ) {
+ if ( sp->ttfindex!=0xffff ) {
+ if ( flags!=NULL ) flags[ptcnt] = _On_Curve;
+ bp[ptcnt].x = rint(sp->me.x);
+ bp[ptcnt].y = rint(sp->me.y);
+ sp->ttfindex = ptcnt++;
+ } else if ( !SPInterpolate( sp ) ) {
+ /* If an on curve point is midway between two off curve points*/
+ /* it may be omitted and will be interpolated on read in */
+ if ( flags!=NULL ) flags[ptcnt] = _On_Curve;
+ bp[ptcnt].x = rint(sp->me.x);
+ bp[ptcnt].y = rint(sp->me.y);
+ sp->ttfindex = ptcnt++;
+ }
+ nextsp = sp->next!=NULL ? sp->next->to : NULL;
+ if ( sp->nextcpindex == startcnt )
+ /* This control point is actually our first point, not our last */
+ break;
+ if ( (sp->nextcpindex !=0xffff && sp->nextcpindex!=0xfffe ) ||
+ !sp->nonextcp ) {
+ if ( flags!=NULL ) flags[ptcnt] = 0;
+ bp[ptcnt].x = rint(sp->nextcp.x);
+ bp[ptcnt++].y = rint(sp->nextcp.y);
+ }
+ if ( nextsp==NULL )
+ break;
+ if ( first==NULL ) first = sp;
+ sp = nextsp;
+ }
+return( ptcnt );
+}
+
+static void dumppointarrays(struct glyphinfo *gi,BasePoint *bp, char *fs, int pc) {
+ BasePoint last;
+ int i,flags;
+ int lastflag, flagcnt;
+
+ if ( gi->maxp->maxPoints<pc )
+ gi->maxp->maxPoints = pc;
+
+ /* flags */
+ last.x = last.y = 0;
+ lastflag = -1; flagcnt = 0;
+ for ( i=0; i<pc; ++i ) {
+ flags = 0;
+ if ( fs==NULL || fs[i] )
+ flags = _On_Curve; /* points are on curve */
+ if ( last.x==bp[i].x )
+ flags |= _X_Same;
+ else if ( bp[i].x-last.x>-256 && bp[i].x-last.x<255 ) {
+ flags |= _X_Short;
+ if ( bp[i].x>=last.x )
+ flags |= _X_Same; /* In this context it means positive */
+ }
+ if ( last.y==bp[i].y )
+ flags |= _Y_Same;
+ else if ( bp[i].y-last.y>-256 && bp[i].y-last.y<255 ) {
+ flags |= _Y_Short;
+ if ( bp[i].y>=last.y )
+ flags |= _Y_Same; /* In this context it means positive */
+ }
+ last = bp[i];
+ if ( lastflag==-1 ) {
+ lastflag = flags;
+ flagcnt = 0;
+ } else if ( flags!=lastflag ) {
+ if ( flagcnt!=0 )
+ lastflag |= _Repeat;
+ putc(lastflag,gi->glyphs);
+ if ( flagcnt!=0 )
+ putc(flagcnt,gi->glyphs);
+ lastflag = flags;
+ flagcnt = 0;
+ } else {
+ if ( ++flagcnt == 255 ) {
+ putc(lastflag|_Repeat,gi->glyphs);
+ putc(255,gi->glyphs);
+ lastflag = -1;
+ flagcnt = 0;
+ }
+ }
+ }
+ if ( lastflag!=-1 ) {
+ if ( flagcnt!=0 )
+ lastflag |= _Repeat;
+ putc(lastflag,gi->glyphs);
+ if ( flagcnt!=0 )
+ putc(flagcnt,gi->glyphs);
+ }
+
+ /* xcoords */
+ last.x = 0;
+ for ( i=0; i<pc; ++i ) {
+ if ( last.x==bp[i].x )
+ /* Do Nothing */;
+ else if ( bp[i].x-last.x>-256 && bp[i].x-last.x<255 ) {
+ if ( bp[i].x>=last.x )
+ putc(bp[i].x-last.x,gi->glyphs);
+ else
+ putc(last.x-bp[i].x,gi->glyphs);
+ } else
+ putshort(gi->glyphs,bp[i].x-last.x);
+ last.x = bp[i].x;
+ }
+ /* ycoords */
+ last.y = 0;
+ for ( i=0; i<pc; ++i ) {
+ if ( last.y==bp[i].y )
+ /* Do Nothing */;
+ else if ( bp[i].y-last.y>-256 && bp[i].y-last.y<255 ) {
+ if ( bp[i].y>=last.y )
+ putc(bp[i].y-last.y,gi->glyphs);
+ else
+ putc(last.y-bp[i].y,gi->glyphs);
+ } else
+ putshort(gi->glyphs,bp[i].y-last.y);
+ last.y = bp[i].y;
+ }
+ if ( ftell(gi->glyphs)&1 ) /* Pad the file so that the next glyph */
+ putc('\0',gi->glyphs); /* on a word boundary */
+}
+
+static void dumpinstrs(struct glyphinfo *gi,uint8 *instrs,int cnt) {
+ int i;
+
+ if ( (gi->flags&ttf_flag_nohints) ) {
+ putshort(gi->glyphs,0);
+return;
+ }
+ /* Do we ever want to call AutoHint and AutoInst here? I think not. */
+
+ if ( gi->maxp->maxglyphInstr<cnt ) gi->maxp->maxglyphInstr=cnt;
+ putshort(gi->glyphs,cnt);
+ for ( i=0; i<cnt; ++i )
+ putc( instrs[i],gi->glyphs );
+}
+
+static void dumpmissingglyph(SplineFont *sf,struct glyphinfo *gi,int fixedwidth) {
+ /* Or .notdef */
+ struct glyphhead gh;
+ BasePoint bp[10];
+ uint8 instrs[50];
+ int stemcvt, stem;
+
+ gi->pointcounts[gi->next_glyph] = 8;
+ gi->loca[gi->next_glyph++] = ftell(gi->glyphs);
+ gi->maxp->maxContours = 2;
+
+ gh.numContours = 2;
+ gh.ymin = 0;
+ gh.ymax = 2*(sf->ascent+sf->descent)/3;
+ gh.xmax = (sf->ascent+sf->descent)/3;
+ gh.xmin = stem = gh.xmax/10;
+ gh.xmax += stem;
+ if ( gh.ymax>sf->ascent ) gh.ymax = sf->ascent;
+ dumpghstruct(gi,&gh);
+
+ stemcvt = TTF_getcvtval(gi->sf,stem);
+
+ bp[0].x = stem; bp[0].y = 0;
+ bp[1].x = stem; bp[1].y = gh.ymax;
+ bp[2].x = gh.xmax; bp[2].y = gh.ymax;
+ bp[3].x = gh.xmax; bp[3].y = 0;
+
+ bp[4].x = 2*stem; bp[4].y = stem;
+ bp[5].x = gh.xmax-stem; bp[5].y = stem;
+ bp[6].x = gh.xmax-stem; bp[6].y = gh.ymax-stem;
+ bp[7].x = 2*stem; bp[7].y = gh.ymax-stem;
+
+ instrs[0] = 0xb1; /* Pushb, 2byte */
+ instrs[1] = 1; /* Point 1 */
+ instrs[2] = 0; /* Point 0 */
+ instrs[3] = 0x2f; /* MDAP, rounded (pt0) */
+ instrs[4] = 0x3c; /* ALIGNRP, (pt1 same pos as pt0)*/
+ instrs[5] = 0xb2; /* Pushb, 3byte */
+ instrs[6] = 7; /* Point 7 */
+ instrs[7] = 4; /* Point 4 */
+ instrs[8] = stemcvt; /* CVT entry for our stem width */
+ instrs[9] = 0xe0+0x0d; /* MIRP, don't set rp0, minimum, rounded, black */
+ instrs[10] = 0x32; /* SHP[rp2] (pt7 same pos as pt4) */
+ instrs[11] = 0xb1; /* Pushb, 2byte */
+ instrs[12] = 6; /* Point 6 */
+ instrs[13] = 5; /* Point 5 */
+ instrs[14] = 0xc0+0x1c; /* MDRP, set rp0, minimum, rounded, grey */
+ instrs[15] = 0x3c; /* ALIGNRP, (pt6 same pos as pt5)*/
+ instrs[16] = 0xb2; /* Pushb, 3byte */
+ instrs[17] = 3; /* Point 3 */
+ instrs[18] = 2; /* Point 2 */
+ instrs[19] = stemcvt; /* CVT entry for our stem width */
+ instrs[20] = 0xe0+0x0d; /* MIRP, dont set rp0, minimum, rounded, black */
+ instrs[21] = 0x32; /* SHP[rp2] (pt3 same pos as pt2) */
+
+ instrs[22] = 0x00; /* SVTCA, y axis */
+
+ instrs[23] = 0xb1; /* Pushb, 2byte */
+ instrs[24] = 3; /* Point 3 */
+ instrs[25] = 0; /* Point 0 */
+ instrs[26] = 0x2f; /* MDAP, rounded */
+ instrs[27] = 0x3c; /* ALIGNRP, (pt3 same height as pt0)*/
+ instrs[28] = 0xb2; /* Pushb, 3byte */
+ instrs[29] = 5; /* Point 5 */
+ instrs[30] = 4; /* Point 4 */
+ instrs[31] = stemcvt; /* CVT entry for our stem width */
+ instrs[32] = 0xe0+0x0d; /* MIRP, don't set rp0, minimum, rounded, black */
+ instrs[33] = 0x32; /* SHP[rp2] (pt5 same height as pt4) */
+ instrs[34] = 0xb2; /* Pushb, 3byte */
+ instrs[35] = 7; /* Point 7 */
+ instrs[36] = 6; /* Point 6 */
+ instrs[37] = TTF_getcvtval(gi->sf,bp[6].y); /* CVT entry for top height */
+ instrs[38] = 0xe0+0x1c; /* MIRP, set rp0, minimum, rounded, grey */
+ instrs[39] = 0x3c; /* ALIGNRP (pt7 same height as pt6) */
+ instrs[40] = 0xb2; /* Pushb, 3byte */
+ instrs[41] = 1; /* Point 1 */
+ instrs[42] = 2; /* Point 2 */
+ instrs[43] = stemcvt; /* CVT entry for our stem width */
+ instrs[44] = 0xe0+0x0d; /* MIRP, dont set rp0, minimum, rounded, black */
+ instrs[45] = 0x32; /* SHP[rp2] (pt1 same height as pt2) */
+
+ /* We've touched all points in all dimensions */
+ /* Don't need any IUP */
+
+ /* end contours array */
+ putshort(gi->glyphs,4-1);
+ putshort(gi->glyphs,8-1);
+ /* instruction length&instructions */
+ dumpinstrs(gi,instrs,46);
+
+ dumppointarrays(gi,bp,NULL,8);
+
+ if ( fixedwidth==-1 )
+ putshort(gi->hmtx,gh.xmax + 2*stem);
+ else
+ putshort(gi->hmtx,fixedwidth);
+ putshort(gi->hmtx,stem);
+ if ( sf->hasvmetrics ) {
+ putshort(gi->vmtx,sf->ascent+sf->descent);
+ putshort(gi->vmtx,sf->vertical_origin-gh.ymax);
+ }
+}
+
+static void dumpblankglyph(struct glyphinfo *gi,SplineFont *sf,int fixedwidth) {
+ int advance = gi->next_glyph==1?0:fixedwidth==-1?(sf->ascent+sf->descent)/3:
+ fixedwidth;
+ /* For reasons quite obscure to me, glyph 1 has an advance width of 0 */
+ /* even in a mono-spaced font like CourierNew.ttf */
+
+ /* These don't get a glyph header, because there are no contours */
+ gi->pointcounts[gi->next_glyph] = 0;
+ gi->loca[gi->next_glyph++] = ftell(gi->glyphs);
+ putshort(gi->hmtx,advance);
+ putshort(gi->hmtx,0);
+ if ( sf->hasvmetrics ) {
+ putshort(gi->vmtx,gi->next_glyph==2?0:(sf->ascent+sf->descent));
+ putshort(gi->vmtx,0);
+ }
+}
+
+static void dumpspace(SplineChar *sc, struct glyphinfo *gi) {
+ /* These don't get a glyph header, because there are no contours */
+ DBounds b;
+ gi->pointcounts[gi->next_glyph] = 0;
+ gi->loca[gi->next_glyph++] = ftell(gi->glyphs);
+ memset(&b,0,sizeof(b));
+ ttfdumpmetrics(sc,gi,&b);
+}
+
+static int IsTTFRefable(SplineChar *sc) {
+ RefChar *ref;
+
+ if ( sc->layers[ly_fore].refs==NULL || sc->layers[ly_fore].splines!=NULL )
+return( false );
+
+ for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
+ if ( ref->transform[0]<-2 || ref->transform[0]>1.999939 ||
+ ref->transform[1]<-2 || ref->transform[1]>1.999939 ||
+ ref->transform[2]<-2 || ref->transform[2]>1.999939 ||
+ ref->transform[3]<-2 || ref->transform[3]>1.999939 )
+return( false );
+ }
+return( true );
+}
+
+static int RefDepth(RefChar *ref) {
+ int rd, temp;
+ SplineChar *sc = ref->sc;
+
+ if ( sc->layers[ly_fore].refs==NULL || sc->layers[ly_fore].splines!=NULL )
+return( 1 );
+ rd = 0;
+ for ( ref = sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
+ if ( ref->transform[0]>=-2 || ref->transform[0]<=1.999939 ||
+ ref->transform[1]>=-2 || ref->transform[1]<=1.999939 ||
+ ref->transform[2]>=-2 || ref->transform[2]<=1.999939 ||
+ ref->transform[3]>=-2 || ref->transform[3]<=1.999939 ) {
+ temp = RefDepth(ref);
+ if ( temp>rd ) rd = temp;
+ }
+ }
+return( rd+1 );
+}
+
+static void CountCompositeMaxPts(SplineChar *sc,struct glyphinfo *gi) {
+ RefChar *ref;
+ int ptcnt = 0, index;
+
+ for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
+ if ( ref->sc->ttf_glyph==-1 )
+ continue;
+ index = ref->sc->ttf_glyph;
+ if ( gi->pointcounts[index]==-1 )
+ CountCompositeMaxPts(ref->sc,gi);
+ ptcnt += gi->pointcounts[index];
+ }
+ gi->pointcounts[sc->ttf_glyph] = ptcnt;
+ if ( gi->maxp->maxCompositPts<ptcnt ) gi->maxp->maxCompositPts=ptcnt;
+}
+
+/* In order3 fonts we figure out the composite point counts at the end */
+/* when we know how many points are in each sub-glyph */
+static void RefigureCompositeMaxPts(SplineFont *sf,struct glyphinfo *gi) {
+ int i;
+
+ for ( i=0; i<gi->gcnt; ++i ) if ( gi->bygid[i]!=-1 && sf->glyphs[gi->bygid[i]]->ttf_glyph!=-1 ) {
+ if ( sf->glyphs[gi->bygid[i]]->layers[ly_fore].splines==NULL &&
+ sf->glyphs[gi->bygid[i]]->layers[ly_fore].refs!=NULL &&
+ gi->pointcounts[i]== -1 )
+ CountCompositeMaxPts(sf->glyphs[gi->bygid[i]],gi);
+ }
+}
+
+static void dumpcomposite(SplineChar *sc, struct glyphinfo *gi) {
+ struct glyphhead gh;
+ DBounds bb;
+ int i, ptcnt, ctcnt, flags, sptcnt, rd;
+ SplineSet *ss;
+ RefChar *ref;
+ SplineChar *isc = sc->ttf_instrs==NULL && sc->parent->mm!=NULL && sc->parent->mm->apple ?
+ sc->parent->mm->normal->glyphs[sc->orig_pos] : sc;
+ int arg1, arg2;
+
+#if 0
+ if ( autohint_before_generate && sc->changedsincelasthinted &&
+ !sc->manualhints )
+ if ( !(gi->flags&ttf_flag_nohints) )
+ SplineCharAutoHint(sc,NULL);
+#endif
+
+ gi->loca[gi->next_glyph] = ftell(gi->glyphs);
+
+ SplineCharFindBounds(sc,&bb);
+ gh.numContours = -1;
+ gh.xmin = floor(bb.minx); gh.ymin = floor(bb.miny);
+ gh.xmax = ceil(bb.maxx); gh.ymax = ceil(bb.maxy);
+ dumpghstruct(gi,&gh);
+
+ i=ptcnt=ctcnt=0;
+ for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next, ++i ) {
+ if ( ref->sc->ttf_glyph==-1 ) {
+ /*if ( sc->layers[ly_fore].refs->next==NULL || any )*/
+ continue;
+ }
+ flags = 0;
+ if ( ref->round_translation_to_grid )
+ flags |= _ROUND;
+ if ( ref->use_my_metrics )
+ flags |= _USE_MY_METRICS;
+ if ( ref->next!=NULL )
+ flags |= _MORE; /* More components */
+ else if ( isc->ttf_instrs_len!=0 ) /* Composits also inherit instructions */
+ flags |= _INSTR; /* Instructions appear after last ref */
+ if ( ref->transform[1]!=0 || ref->transform[2]!=0 )
+ flags |= _MATRIX; /* Need a full matrix */
+ else if ( ref->transform[0]!=ref->transform[3] )
+ flags |= _XY_SCALE; /* different xy scales */
+ else if ( ref->transform[0]!=1. )
+ flags |= _SCALE; /* xy scale is same */
+ if ( ref->point_match ) {
+ arg1 = ref->match_pt_base;
+ arg2 = ref->match_pt_ref;
+ } else {
+ arg1 = rint(ref->transform[4]);
+ arg2 = rint(ref->transform[5]);
+ flags |= _ARGS_ARE_XY|_UNSCALED_OFFSETS;
+ /* The values I output are the values I want to see */
+ /* There is some very strange stuff wrongly-documented on the apple*/
+ /* site about how these should be interpretted when there are */
+ /* scale factors, or rotations */
+ /* That description does not match the behavior of their rasterizer*/
+ /* I've reverse engineered something else (see parsettf.c) */
+ /* http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html */
+ /* Adobe says that setting bit 12 means that this will not happen */
+ /* Apple doesn't mention bit 12 though...(but they do support it) */
+ }
+ if ( arg1<-128 || arg1>127 ||
+ arg2<-128 || arg2>127 )
+ flags |= _ARGS_ARE_WORDS;
+ putshort(gi->glyphs,flags);
+ putshort(gi->glyphs,ref->sc->ttf_glyph==-1?0:ref->sc->ttf_glyph);
+ if ( flags&_ARGS_ARE_WORDS ) {
+ putshort(gi->glyphs,(short)arg1);
+ putshort(gi->glyphs,(short)arg2);
+ } else {
+ putc((char) arg1,gi->glyphs);
+ putc((char) arg2,gi->glyphs);
+ }
+ if ( flags&_MATRIX ) {
+ put2d14(gi->glyphs,ref->transform[0]);
+ put2d14(gi->glyphs,ref->transform[1]);
+ put2d14(gi->glyphs,ref->transform[2]);
+ put2d14(gi->glyphs,ref->transform[3]);
+ } else if ( flags&_XY_SCALE ) {
+ put2d14(gi->glyphs,ref->transform[0]);
+ put2d14(gi->glyphs,ref->transform[3]);
+ } else if ( flags&_SCALE ) {
+ put2d14(gi->glyphs,ref->transform[0]);
+ }
+ sptcnt = SSTtfNumberPoints(ref->layers[0].splines);
+ for ( ss=ref->layers[0].splines; ss!=NULL ; ss=ss->next ) {
+ ++ctcnt;
+ }
+ if ( sc->parent->order2 )
+ ptcnt += sptcnt;
+ else if ( ptcnt>=0 && gi->pointcounts[ref->sc->ttf_glyph==-1?0:ref->sc->ttf_glyph]>=0 )
+ ptcnt += gi->pointcounts[ref->sc->ttf_glyph==-1?0:ref->sc->ttf_glyph];
+ else
+ ptcnt = -1;
+ rd = RefDepth(ref);
+ if ( rd>gi->maxp->maxcomponentdepth )
+ gi->maxp->maxcomponentdepth = rd;
+ }
+
+ if ( isc->ttf_instrs_len!=0 )
+ dumpinstrs(gi,isc->ttf_instrs,isc->ttf_instrs_len);
+
+ gi->pointcounts[gi->next_glyph++] = ptcnt;
+ if ( gi->maxp->maxnumcomponents<i ) gi->maxp->maxnumcomponents = i;
+ if ( gi->maxp->maxCompositPts<ptcnt ) gi->maxp->maxCompositPts=ptcnt;
+ if ( gi->maxp->maxCompositCtrs<ctcnt ) gi->maxp->maxCompositCtrs=ctcnt;
+
+ ttfdumpmetrics(sc,gi,&bb);
+ if ( ftell(gi->glyphs)&1 ) /* Pad the file so that the next glyph */
+ putc('\0',gi->glyphs); /* on a word boundary, can only happen if odd number of instrs */
+}
+
+static void dumpglyph(SplineChar *sc, struct glyphinfo *gi) {
+ struct glyphhead gh;
+ DBounds bb;
+ SplineSet *ss, *ttfss;
+ int contourcnt, ptcnt, origptcnt;
+ BasePoint *bp;
+ char *fs;
+ SplineChar *isc = sc->ttf_instrs==NULL && sc->parent->mm!=NULL && sc->parent->mm->apple ?
+ sc->parent->mm->normal->glyphs[sc->orig_pos] : sc;
+
+/* I haven't seen this documented, but ttf rasterizers are unhappy with a */
+/* glyph that consists of a single point. Glyphs containing two single points*/
+/* are ok, glyphs with a single point and anything else are ok, glyphs with */
+/* a line are ok. But a single point is not ok. Dunno why */
+ if (( sc->layers[ly_fore].splines==NULL && sc->layers[ly_fore].refs==NULL ) ||
+ ( sc->layers[ly_fore].refs==NULL &&
+ (sc->layers[ly_fore].splines->first->next==NULL ||
+ sc->layers[ly_fore].splines->first->next->to == sc->layers[ly_fore].splines->first) &&
+ sc->layers[ly_fore].splines->next==NULL) ) {
+ dumpspace(sc,gi);
+return;
+ }
+
+ gi->loca[gi->next_glyph] = ftell(gi->glyphs);
+
+ if ( isc->ttf_instrs!=NULL )
+ initforinstrs(sc);
+
+ ttfss = SCttfApprox(sc);
+ ptcnt = SSTtfNumberPoints(ttfss);
+ for ( ss=ttfss, contourcnt=0; ss!=NULL; ss=ss->next ) {
+ ++contourcnt;
+ }
+ origptcnt = ptcnt;
+
+ SplineCharFindBounds(sc,&bb);
+ /* MicroSoft's font validator has a bug. It only looks at the points */
+ /* when calculating the bounding box, and complains when I look at */
+ /* the splines for internal extrema. I presume it does this because */
+ /* all the extrema are supposed to be points (and it complains about */
+ /* that error too), but it would lead to rasterization problems if */
+ /* we did what they want */
+ gh.numContours = contourcnt;
+ gh.xmin = floor(bb.minx); gh.ymin = floor(bb.miny);
+ gh.xmax = ceil(bb.maxx); gh.ymax = ceil(bb.maxy);
+ dumpghstruct(gi,&gh);
+ if ( contourcnt>gi->maxp->maxContours ) gi->maxp->maxContours = contourcnt;
+ if ( ptcnt>gi->maxp->maxPoints ) gi->maxp->maxPoints = ptcnt;
+
+ bp = galloc(ptcnt*sizeof(BasePoint));
+ fs = galloc(ptcnt);
+ ptcnt = contourcnt = 0;
+ for ( ss=ttfss; ss!=NULL; ss=ss->next ) {
+ ptcnt = SSAddPoints(ss,ptcnt,bp,fs);
+ putshort(gi->glyphs,ptcnt-1);
+ }
+ if ( ptcnt!=origptcnt )
+ IError( "Point count wrong calculated=%d, actual=%d in %.20s", origptcnt, ptcnt, sc->name );
+ gi->pointcounts[gi->next_glyph++] = ptcnt;
+
+ dumpinstrs(gi,isc->ttf_instrs,isc->ttf_instrs_len);
+
+ dumppointarrays(gi,bp,fs,ptcnt);
+ SplinePointListsFree(ttfss);
+ free(bp);
+ free(fs);
+
+ ttfdumpmetrics(sc,gi,&bb);
+}
+
+void SFDummyUpCIDs(struct glyphinfo *gi,SplineFont *sf) {
+ int i,j,k,max;
+ int *bygid;
+
+ max = 0;
+ for ( k=0; k<sf->subfontcnt; ++k )
+ if ( sf->subfonts[k]->glyphcnt>max ) max = sf->subfonts[k]->glyphcnt;
+ if ( max == 0 )
+return;
+
+ sf->glyphs = gcalloc(max,sizeof(SplineChar *));
+ sf->glyphcnt = sf->glyphmax = max;
+ for ( k=0; k<sf->subfontcnt; ++k )
+ for ( i=0; i<sf->subfonts[k]->glyphcnt; ++i ) if ( sf->subfonts[k]->glyphs[i]!=NULL )
+ sf->glyphs[i] = sf->subfonts[k]->glyphs[i];
+
+ if ( gi==NULL )
+return;
+
+ bygid = galloc((sf->glyphcnt+3)*sizeof(int));
+ memset(bygid,0xff, (sf->glyphcnt+3)*sizeof(int));
+
+ j=1;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ if ( bygid[0]== -1 && strcmp(sf->glyphs[i]->name,".notdef")==0 ) {
+ sf->glyphs[i]->ttf_glyph = 0;
+ bygid[0] = i;
+ } else if ( SCWorthOutputting(sf->glyphs[i])) {
+ sf->glyphs[i]->ttf_glyph = j;
+ bygid[j++] = i;
+ }
+ }
+ gi->bygid = bygid;
+ gi->gcnt = j;
+}
+
+static void AssignNotdefNull(SplineFont *sf,int *bygid, int iscff) {
+ int i;
+
+ /* The first three glyphs are magic, glyph 0 is .notdef */
+ /* glyph 1 is .null and glyph 2 is nonmarking return */
+ /* We may generate them automagically */
+
+ bygid[0] = bygid[1] = bygid[2] = -1;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ if ( bygid[0]== -1 && strcmp(sf->glyphs[i]->name,".notdef")==0 ) {
+ sf->glyphs[i]->ttf_glyph = 0;
+ bygid[0] = i;
+ } else if ( !iscff && bygid[1]== -1 &&
+ (strcmp(sf->glyphs[i]->name,".null")==0 ||
+ (i==1 && strcmp(sf->glyphs[1]->name,"glyph1")==0)) ) {
+ sf->glyphs[i]->ttf_glyph = 1;
+ bygid[1] = i;
+ } else if ( !iscff && bygid[2]== -1 &&
+ (strcmp(sf->glyphs[i]->name,"nonmarkingreturn")==0 ||
+ (i==2 && strcmp(sf->glyphs[2]->name,"glyph2")==0)) ) {
+ sf->glyphs[i]->ttf_glyph = 2;
+ bygid[2] = i;
+ }
+ }
+}
+
+static int AssignTTFGlyph(struct glyphinfo *gi,SplineFont *sf,EncMap *map,int iscff) {
+ int *bygid = galloc((sf->glyphcnt+3)*sizeof(int));
+ int i,j;
+
+ memset(bygid,0xff, (sf->glyphcnt+3)*sizeof(int));
+
+ AssignNotdefNull(sf,bygid,iscff);
+
+ j = iscff ? 1 : 3;
+ for ( i=0; i<map->enccount; ++i ) if ( map->map[i]!=-1 ) {
+ SplineChar *sc = sf->glyphs[map->map[i]];
+ if ( SCWorthOutputting(sc) && sc->ttf_glyph==-1
+#if HANYANG
+ && (!iscff || !sc->compositionunit)
+#endif
+ ) {
+ sc->ttf_glyph = j;
+ bygid[j++] = sc->orig_pos;
+ }
+ }
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ SplineChar *sc = sf->glyphs[i];
+ if ( SCWorthOutputting(sc) && sc->ttf_glyph==-1
+#if HANYANG
+ && (!iscff || !sc->compositionunit)
+#endif
+ ) {
+ sc->ttf_glyph = j;
+ bygid[j++] = i;
+ }
+ }
+ gi->bygid = bygid;
+ gi->gcnt = j;
+return j;
+}
+
+static int AssignTTFBitGlyph(struct glyphinfo *gi,SplineFont *sf,EncMap *map,int32 *bsizes) {
+ int i, j;
+ BDFFont *bdf;
+ int *bygid = galloc((sf->glyphcnt+3)*sizeof(int));
+
+ memset(bygid,0xff, (sf->glyphcnt+3)*sizeof(int));
+
+ AssignNotdefNull(sf,bygid,false);
+
+ for ( bdf = sf->bitmaps; bdf!=NULL; bdf=bdf->next ) {
+ for ( j=0; bsizes[j]!=0 && ((bsizes[j]&0xffff)!=bdf->pixelsize || (bsizes[j]>>16)!=BDFDepth(bdf)); ++j );
+ if ( bsizes[j]==0 )
+ continue;
+ for ( i=0; i<bdf->glyphcnt; ++i ) if ( !IsntBDFChar(bdf->glyphs[i]) )
+ sf->glyphs[i]->ttf_glyph = -2;
+ }
+
+ j = 3;
+ for ( i=0; i<map->enccount; ++i ) if ( map->map[i]!=-1 ) {
+ SplineChar *sc = sf->glyphs[map->map[i]];
+ if ( sc->ttf_glyph==-2 ) {
+ sc->ttf_glyph = j;
+ bygid[j++] = sc->orig_pos;
+ }
+ }
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ SplineChar *sc = sf->glyphs[i];
+ if ( sc->ttf_glyph==-2 ) {
+ sc->ttf_glyph = j;
+ bygid[j++] = i;
+ }
+ }
+
+ gi->bygid = bygid;
+ gi->gcnt = j;
+return j;
+}
+
+static int dumpglyphs(SplineFont *sf,struct glyphinfo *gi) {
+ int i;
+ int fixed = gi->fixed_width;
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_change_stages(2+gi->strikecnt);
+#endif
+ QuickBlues(sf,&gi->bd);
+ /*FindBlues(sf,gi->blues,NULL);*/
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_next_stage();
+#endif
+
+ if ( !gi->onlybitmaps ) {
+ if ( sf->order2 )
+ for ( i=0; i<sf->glyphcnt; ++i ) {
+ SplineChar *sc = sf->glyphs[i];
+ if ( SCWorthOutputting(sc) )
+ if ( !SCPointsNumberedProperly(sc)) {
+ free(sc->ttf_instrs); sc->ttf_instrs = NULL;
+ sc->ttf_instrs_len = 0;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ SCMarkInstrDlgAsChanged(sc);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ SCNumberPoints(sc);
+ }
+ }
+ }
+
+ gi->maxp->numGlyphs = gi->gcnt;
+ gi->loca = galloc((gi->maxp->numGlyphs+1)*sizeof(uint32));
+ gi->pointcounts = galloc((gi->maxp->numGlyphs+1)*sizeof(int32));
+ memset(gi->pointcounts,-1,(gi->maxp->numGlyphs+1)*sizeof(int32));
+ gi->next_glyph = 0;
+ gi->glyphs = tmpfile();
+ gi->hmtx = tmpfile();
+ if ( sf->hasvmetrics )
+ gi->vmtx = tmpfile();
+ FigureFullMetricsEnd(sf,gi,true);
+
+ if ( fixed!=-1 ) {
+ gi->lasthwidth = 3;
+ gi->hfullcnt = 3;
+ }
+ for ( i=0; i<gi->gcnt; ++i ) {
+ if ( i==0 ) {
+ if ( gi->bygid[0]!=-1 && (fixed==-1 || sf->glyphs[gi->bygid[0]]->width==fixed))
+ dumpglyph(sf->glyphs[gi->bygid[0]],gi);
+ else
+ dumpmissingglyph(sf,gi,fixed);
+ } else if ( i<=2 && gi->bygid[i]==-1 )
+ dumpblankglyph(gi,sf,fixed);
+ else if ( gi->onlybitmaps ) {
+ if ( gi->bygid[i]!=-1 && sf->glyphs[gi->bygid[i]]->ttf_glyph>0 )
+ dumpspace(sf->glyphs[gi->bygid[i]],gi);
+ } else {
+ if ( gi->bygid[i]!=-1 && sf->glyphs[gi->bygid[i]]->ttf_glyph>0 ) {
+ if ( IsTTFRefable(sf->glyphs[gi->bygid[i]]) )
+ dumpcomposite(sf->glyphs[gi->bygid[i]],gi);
+ else
+ dumpglyph(sf->glyphs[gi->bygid[i]],gi);
+ }
+ }
+ if ( (ftell(gi->glyphs)&3) != 0 ) {
+ /* Apple says glyphs must be 16bit aligned */
+ if ( ftell(gi->glyphs)&1 )
+ putc('\0',gi->glyphs);
+ /* MS says glyphs should be 32bit aligned */
+ if ( ftell(gi->glyphs)&2 )
+ putshort(gi->glyphs,0);
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( !gwwv_progress_next())
+return( false );
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+
+ /* extra location entry points to end of last glyph */
+ gi->loca[gi->next_glyph] = ftell(gi->glyphs);
+ /* Microsoft's Font Validator wants the last loca entry to point into the */
+ /* glyph table. I think that's an error on their part, but it's so easy */
+ /* to fix, I might as well (instead of pointing to right after the table)*/
+ /* Sigh. But if I do that, it complains that there's extra stuff in the */
+ /* glyph table. There's just no pleasing them */
+ /* putlong(gi->glyphs,0);*/
+ gi->glyph_len = ftell(gi->glyphs);
+ gi->hmtxlen = ftell(gi->hmtx);
+ /* pad out to four bytes */
+ if ( gi->hmtxlen&2 ) putshort(gi->hmtx,0);
+ if ( gi->loca[gi->next_glyph]&3 ) {
+ for ( i=4-(gi->loca[gi->next_glyph]&3); i>0; --i )
+ putc('\0',gi->glyphs);
+ }
+ if ( sf->hasvmetrics ) {
+ gi->vmtxlen = ftell(gi->vmtx);
+ if ( gi->vmtxlen&2 ) putshort(gi->vmtx,0);
+ }
+ if ( !sf->order2 )
+ RefigureCompositeMaxPts(sf,gi);
+ free(gi->pointcounts);
+
+return( true );
+}
+
+/* Generate a null glyf and loca table for X opentype bitmaps */
+static int dumpnoglyphs(SplineFont *sf,struct glyphinfo *gi) {
+
+ gi->glyphs = tmpfile();
+ gi->glyph_len = 0;
+ /* loca gets built in dummyloca */
+return( true );
+}
+
+/* Standard names for cff */
+extern const char *cffnames[];
+extern const int nStdStrings;
+
+static int storesid(struct alltabs *at,char *str) {
+ int i;
+ FILE *news;
+ char *pt;
+ long pos;
+
+ if ( str!=NULL ) { /* NULL is the magic string at end of array */
+ for ( i=0; cffnames[i]!=NULL; ++i ) {
+ if ( strcmp(cffnames[i],str)==0 )
+return( i );
+ }
+ }
+
+ pos = ftell(at->sidf)+1;
+ if ( pos>=65536 && !at->sidlongoffset ) {
+ at->sidlongoffset = true;
+ news = tmpfile();
+ rewind(at->sidh);
+ for ( i=0; i<at->sidcnt; ++i )
+ putlong(news,getushort(at->sidh));
+ fclose(at->sidh);
+ at->sidh = news;
+ }
+ if ( at->sidlongoffset )
+ putlong(at->sidh,pos);
+ else
+ putshort(at->sidh,pos);
+
+ if ( str!=NULL ) {
+ for ( pt=str; *pt; ++pt )
+ putc(*pt,at->sidf);
+ }
+return( at->sidcnt++ + nStdStrings );
+}
+
+static void dumpint(FILE *cfff,int num) {
+
+ if ( num>=-107 && num<=107 )
+ putc(num+139,cfff);
+ else if ( num>=108 && num<=1131 ) {
+ num -= 108;
+ putc((num>>8)+247,cfff);
+ putc(num&0xff,cfff);
+ } else if ( num>=-1131 && num<=-108 ) {
+ num = -num;
+ num -= 108;
+ putc((num>>8)+251,cfff);
+ putc(num&0xff,cfff);
+ } else if ( num>=-32768 && num<32768 ) {
+ putc(28,cfff);
+ putc(num>>8,cfff);
+ putc(num&0xff,cfff);
+ } else { /* In dict data we have 4 byte ints, in type2 strings we don't */
+ putc(29,cfff);
+ putc((num>>24)&0xff,cfff);
+ putc((num>>16)&0xff,cfff);
+ putc((num>>8)&0xff,cfff);
+ putc(num&0xff,cfff);
+ }
+}
+
+static void dumpdbl(FILE *cfff,double d) {
+ if ( d-rint(d)>-.00001 && d-rint(d)<.00001 )
+ dumpint(cfff,(int) d);
+ else {
+ /* The type2 strings have a fixed format, but the dict data does not */
+ char buffer[20], *pt;
+ int sofar,n,odd;
+ sprintf( buffer, "%g", d);
+ sofar = 0; odd=true;
+ putc(30,cfff); /* Start a double */
+ for ( pt=buffer; *pt; ++pt ) {
+ if ( isdigit(*pt) )
+ n = *pt-'0';
+ else if ( *pt=='.' )
+ n = 0xa;
+ else if ( *pt=='-' )
+ n = 0xe;
+ else if (( *pt=='E' || *pt=='e') && pt[1]=='-' ) {
+ n = 0xc;
+ ++pt;
+ } else if ( *pt=='E' || *pt=='e')
+ n = 0xb;
+ else
+ n = 0; /* Should never happen */
+ if ( odd ) {
+ sofar = n<<4;
+ odd = false;
+ } else {
+ putc(sofar|n,cfff);
+ sofar=0;
+ odd = true;
+ }
+ }
+ if ( sofar==0 )
+ putc(0xff,cfff);
+ else
+ putc(sofar|0xf,cfff);
+ }
+}
+
+static void dumpoper(FILE *cfff,int oper ) {
+ if ( oper!=-1 ) {
+ if ( oper>=256 )
+ putc(oper>>8,cfff);
+ putc(oper&0xff,cfff);
+ }
+}
+
+static void dumpdbloper(FILE *cfff,double d, int oper ) {
+ dumpdbl(cfff,d);
+ dumpoper(cfff,oper);
+}
+
+static void dumpintoper(FILE *cfff,int v, int oper ) {
+ dumpint(cfff,v);
+ dumpoper(cfff,oper);
+}
+
+static void dumpsizedint(FILE *cfff,int big,int num, int oper ) {
+ if ( big ) {
+ putc(29,cfff);
+ putc((num>>24)&0xff,cfff);
+ putc((num>>16)&0xff,cfff);
+ putc((num>>8)&0xff,cfff);
+ putc(num&0xff,cfff);
+ } else {
+ putc(28,cfff);
+ putc(num>>8,cfff);
+ putc(num&0xff,cfff);
+ }
+ dumpoper(cfff,oper);
+}
+
+static void dumpsid(FILE *cfff,struct alltabs *at,char *str,int oper) {
+ if ( str==NULL )
+return;
+ dumpint(cfff,storesid(at,str));
+ dumpoper(cfff,oper);
+}
+
+static void DumpStrDouble(char *pt,FILE *cfff,int oper) {
+ real d;
+ if ( *pt=='[' ) ++pt; /* For StdHW, StdVW */
+ d = strtod(pt,NULL);
+ dumpdbloper(cfff,d,oper);
+}
+
+static void DumpDblArray(real *arr,int n,FILE *cfff, int oper) {
+ int mi,i;
+
+ for ( mi=n-1; mi>=0 && arr[mi]==0; --mi );
+ if ( mi<0 )
+return;
+ dumpdbl(cfff,arr[0]);
+ for ( i=1; i<=mi; ++i )
+ dumpdbl(cfff,arr[i]-arr[i-1]);
+ dumpoper(cfff,oper);
+}
+
+static void DumpStrArray(char *pt,FILE *cfff,int oper) {
+ real d, last=0;
+ char *end;
+
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+return;
+ if ( *pt=='[' ) ++pt;
+ while ( *pt==' ' ) ++pt;
+ while ( *pt!=']' && *pt!='\0' ) {
+ d = strtod(pt,&end);
+ if ( pt==end ) /* User screwed up. Should be a number */
+ break;
+ dumpdbl(cfff,d-last);
+ last = d;
+ pt = end;
+ while ( *pt==' ' ) ++pt;
+ }
+ dumpoper(cfff,oper);
+}
+
+static void dumpcffheader(SplineFont *sf,FILE *cfff) {
+ putc('\1',cfff); /* Major version: 1 */
+ putc('\0',cfff); /* Minor version: 0 */
+ putc('\4',cfff); /* Header size in bytes */
+ putc('\4',cfff); /* Absolute Offset size. */
+ /* I don't think there are any absolute offsets that aren't encoded */
+ /* in a dict as numbers (ie. inherently variable sized items) */
+}
+
+static void dumpcffnames(SplineFont *sf,FILE *cfff) {
+ char *pt;
+
+ putshort(cfff,1); /* One font name */
+ putc('\1',cfff); /* Offset size */
+ putc('\1',cfff); /* Offset to first name */
+ putc('\1'+strlen(sf->fontname),cfff);
+ for ( pt=sf->fontname; *pt; ++pt )
+ putc(*pt,cfff);
+}
+
+static void dumpcffcharset(SplineFont *sf,struct alltabs *at) {
+ int i;
+
+ at->gn_sid = gcalloc(at->gi.gcnt,sizeof(uint32));
+ putc(0,at->charset);
+ /* I always use a format 0 charset. ie. an array of SIDs in random order */
+
+ /* First element must be ".notdef" and is omitted */
+
+ for ( i=1; i<at->gi.gcnt; ++i )
+ if ( at->gi.bygid[i]!=-1 && SCWorthOutputting(sf->glyphs[at->gi.bygid[i]])) {
+ at->gn_sid[i] = storesid(at,sf->glyphs[at->gi.bygid[i]]->name);
+ putshort(at->charset,at->gn_sid[i]);
+ }
+}
+
+static void dumpcffcidset(SplineFont *sf,struct alltabs *at) {
+ int gid, start;
+
+ putc(2,at->charset);
+
+ start = -1; /* Glyph 0 always maps to CID 0, and is omitted */
+ for ( gid = 1; gid<at->gi.gcnt; ++gid ) {
+ if ( start==-1 )
+ start = gid;
+ else if ( at->gi.bygid[gid]-at->gi.bygid[start]!=gid-start ) {
+ putshort(at->charset,at->gi.bygid[start]);
+ putshort(at->charset,at->gi.bygid[gid-1]-at->gi.bygid[start]);
+ start = gid;
+ }
+ }
+ if ( start!=-1 ) {
+ putshort(at->charset,at->gi.bygid[start]);
+ putshort(at->charset,at->gi.bygid[gid-1]-at->gi.bygid[start]);
+ }
+}
+
+static void dumpcfffdselect(SplineFont *sf,struct alltabs *at) {
+ int cid, k, lastfd, cnt;
+ int gid;
+
+ putc(3,at->fdselect);
+ putshort(at->fdselect,0); /* number of ranges, fill in later */
+
+ for ( k=0; k<sf->subfontcnt; ++k )
+ if ( SCWorthOutputting(sf->subfonts[k]->glyphs[0]))
+ break;
+ if ( k==sf->subfontcnt ) --k; /* If CID 0 not defined, put it in last font */
+ putshort(at->fdselect,0);
+ putc(k,at->fdselect);
+ lastfd = k;
+ cnt = 1;
+ for ( gid = 1; gid<at->gi.gcnt; ++gid ) {
+ cid = at->gi.bygid[gid];
+ for ( k=0; k<sf->subfontcnt; ++k ) {
+ if ( cid<sf->subfonts[k]->glyphcnt &&
+ SCWorthOutputting(sf->subfonts[k]->glyphs[cid]) )
+ break;
+ }
+ if ( k==sf->subfontcnt )
+ /* Doesn't map to a glyph, irrelevant */;
+ else {
+ if ( k!=lastfd ) {
+ putshort(at->fdselect,gid);
+ putc(k,at->fdselect);
+ lastfd = k;
+ ++cnt;
+ }
+ }
+ }
+ putshort(at->fdselect,gid);
+ fseek(at->fdselect,1,SEEK_SET);
+ putshort(at->fdselect,cnt);
+ fseek(at->fdselect,0,SEEK_END);
+}
+
+static void dumpcffencoding(SplineFont *sf,struct alltabs *at) {
+ int i, cnt, anydups;
+ uint32 start_pos = ftell(at->encoding);
+ SplineChar *sc;
+ EncMap *map = at->map;
+
+ putc(0,at->encoding);
+ /* I always use a format 0 encoding. ie. an array of glyph indexes */
+ putc(0xff,at->encoding); /* fixup later */
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ sf->glyphs[i]->ticked = false;
+
+ cnt = 0;
+ anydups = 0;
+ for ( i=0; i<256 && i<map->enccount; ++i ) if ( map->map[i]!=-1 && (sc=sf->glyphs[map->map[i]])!=NULL ) {
+ if ( sc->ttf_glyph>255 )
+ continue;
+ if ( sc->ticked ) {
+ ++anydups;
+ } else if ( sc->ttf_glyph>0 ) {
+ if ( cnt>=255 )
+ break;
+ putc(i,at->encoding);
+ ++cnt;
+ sc->ticked = true;
+ }
+ }
+ if ( anydups ) {
+ fseek(at->encoding,start_pos,SEEK_SET);
+ putc(0x80,at->encoding);
+ putc(cnt,at->encoding);
+ fseek(at->encoding,0,SEEK_END);
+ putc(anydups,at->encoding);
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ sf->glyphs[i]->ticked = false;
+ for ( i=0; i<256 && i<map->enccount; ++i ) if ( map->map[i]!=-1 && (sc=sf->glyphs[map->map[i]])!=NULL ) {
+ if ( sc->ttf_glyph>255 )
+ continue;
+ if ( sc->ticked ) {
+ putc(i,at->encoding);
+ putshort(at->encoding,at->gn_sid[sc->ttf_glyph]);
+ }
+ sc->ticked = true;
+ }
+ } else {
+ fseek(at->encoding,start_pos+1,SEEK_SET);
+ putc(cnt,at->encoding);
+ fseek(at->encoding,0,SEEK_END);
+ }
+ free( at->gn_sid );
+ at->gn_sid = NULL;
+}
+
+static void _dumpcffstrings(FILE *file, struct pschars *strs) {
+ int i, len, offsize;
+
+ /* First figure out the offset size */
+ len = 1;
+ for ( i=0; i<strs->next; ++i )
+ len += strs->lens[i];
+
+ /* Then output the index size and offsets */
+ putshort( file, strs->next );
+ if ( strs->next!=0 ) {
+ /* presumably offsets are unsigned. But the docs don't state this in the obvious place */
+ offsize = len<=255?1:len<=65535?2:len<=0xffffff?3:4;
+ putc(offsize,file);
+ len = 1;
+ for ( i=0; i<strs->next; ++i ) {
+ dumpoffset(file,offsize,len);
+ len += strs->lens[i];
+ }
+ dumpoffset(file,offsize,len);
+
+ /* last of all the strings */
+ for ( i=0; i<strs->next; ++i ) {
+ uint8 *pt = strs->values[i], *end = pt+strs->lens[i];
+ while ( pt<end )
+ putc( *pt++, file );
+ }
+ }
+}
+
+static FILE *dumpcffstrings(struct pschars *strs) {
+ FILE *file = tmpfile();
+ _dumpcffstrings(file,strs);
+ PSCharsFree(strs);
+return( file );
+}
+
+int SFFigureDefWidth(SplineFont *sf, int *_nomwid) {
+ uint16 *widths; uint32 *cumwid;
+ int nomwid, defwid, i, sameval=(int) 0x80000000, maxw=0, allsame=true;
+ int cnt,j;
+
+ for ( i=0; i<sf->glyphcnt; ++i )
+ if ( SCWorthOutputting(sf->glyphs[i]) ) {
+ if ( maxw<sf->glyphs[i]->width ) maxw = sf->glyphs[i]->width;
+ if ( sameval == 0x8000000 )
+ sameval = sf->glyphs[i]->width;
+ else if ( sameval!=sf->glyphs[i]->width )
+ allsame = false;
+ }
+ if ( allsame ) {
+ nomwid = defwid = sameval;
+ } else {
+ ++maxw;
+ if ( maxw>65535 ) maxw = 3*(sf->ascent+sf->descent);
+ widths = gcalloc(maxw,sizeof(uint16));
+ cumwid = gcalloc(maxw,sizeof(uint32));
+ defwid = 0; cnt=0;
+ for ( i=0; i<sf->glyphcnt; ++i )
+ if ( SCWorthOutputting(sf->glyphs[i]) &&
+ sf->glyphs[i]->width>=0 &&
+ sf->glyphs[i]->width<maxw )
+ if ( ++widths[sf->glyphs[i]->width] > cnt ) {
+ defwid = sf->glyphs[i]->width;
+ cnt = widths[defwid];
+ }
+ widths[defwid] = 0;
+ for ( i=0; i<maxw; ++i )
+ for ( j=-107; j<=107; ++j )
+ if ( i+j>=0 && i+j<maxw )
+ cumwid[i] += widths[i+j];
+ cnt = 0; nomwid = 0;
+ for ( i=0; i<maxw; ++i )
+ if ( cnt<cumwid[i] ) {
+ cnt = cumwid[i];
+ nomwid = i;
+ }
+ free(widths); free(cumwid);
+ }
+ if ( _nomwid!=NULL )
+ *_nomwid = nomwid;
+return( defwid );
+}
+
+static void ATFigureDefWidth(SplineFont *sf, struct alltabs *at, int subfont) {
+ int nomwid, defwid;
+
+ defwid = SFFigureDefWidth(sf,&nomwid);
+ if ( subfont==-1 )
+ at->defwid = defwid;
+ else
+ at->fds[subfont].defwid = defwid;
+ if ( subfont==-1 )
+ at->nomwid = nomwid;
+ else
+ at->fds[subfont].nomwid = nomwid;
+}
+
+static void dumpcffprivate(SplineFont *sf,struct alltabs *at,int subfont,
+ int subrcnt) {
+ char *pt;
+ FILE *private = subfont==-1?at->private:at->fds[subfont].private;
+ int mi,i;
+ real bluevalues[14], otherblues[10];
+ real snapcnt[12];
+ real stemsnaph[12], stemsnapv[12];
+ real stdhw[1], stdvw[1];
+ int hasblue=0, hash=0, hasv=0, bs;
+ int nomwid, defwid;
+ EncMap *map = at->map;
+ double bluescale;
+
+ /* The private dict is not in an index, so no index header. Just the data */
+
+ if ( subfont==-1 )
+ defwid = at->defwid;
+ else
+ defwid = at->fds[subfont].defwid;
+ dumpintoper(private,defwid,20); /* Default Width */
+ if ( subfont==-1 )
+ nomwid = at->nomwid;
+ else
+ nomwid = at->fds[subfont].nomwid;
+ dumpintoper(private,nomwid,21); /* Nominative Width */
+
+ bs = SplineFontIsFlexible(sf,at->gi.flags);
+ hasblue = PSDictHasEntry(sf->private,"BlueValues")!=NULL;
+ hash = PSDictHasEntry(sf->private,"StdHW")!=NULL;
+ hasv = PSDictHasEntry(sf->private,"StdVW")!=NULL;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_change_stages(2+autohint_before_generate+!hasblue);
+#endif
+ if ( autohint_before_generate ) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_change_line1(_("Auto Hinting Font..."));
+#endif
+ SplineFontAutoHint(sf);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_next_stage();
+#endif
+ }
+
+ otherblues[0] = otherblues[1] = bluevalues[0] = bluevalues[1] = 0;
+ if ( !hasblue ) {
+ FindBlues(sf,bluevalues,otherblues);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_next_stage();
+#endif
+ }
+
+ stdhw[0] = stdvw[0] = 0;
+ if ( !hash ) {
+ FindHStems(sf,stemsnaph,snapcnt);
+ mi = -1;
+ for ( i=0; stemsnaph[i]!=0 && i<12; ++i )
+ if ( mi==-1 ) mi = i;
+ else if ( snapcnt[i]>snapcnt[mi] ) mi = i;
+ if ( mi!=-1 ) stdhw[0] = stemsnaph[mi];
+ }
+
+ if ( !hasv ) {
+ FindVStems(sf,stemsnapv,snapcnt);
+ mi = -1;
+ for ( i=0; stemsnapv[i]!=0 && i<12; ++i )
+ if ( mi==-1 ) mi = i;
+ else if ( snapcnt[i]>snapcnt[mi] ) mi = i;
+ if ( mi!=-1 ) stdvw[0] = stemsnapv[mi];
+ }
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_change_line1(_("Saving OpenType Font"));
+#endif
+
+ if ( hasblue )
+ DumpStrArray(PSDictHasEntry(sf->private,"BlueValues"),private,6);
+ else
+ DumpDblArray(bluevalues,sizeof(bluevalues)/sizeof(bluevalues[0]),private,6);
+ if ( (pt=PSDictHasEntry(sf->private,"OtherBlues"))!=NULL )
+ DumpStrArray(pt,private,7);
+ else if ( !hasblue )
+ DumpDblArray(otherblues,sizeof(otherblues)/sizeof(otherblues[0]),private,7);
+ if ( (pt=PSDictHasEntry(sf->private,"FamilyBlues"))!=NULL )
+ DumpStrArray(pt,private,8);
+ bluescale = BlueScaleFigure(sf->private,bluevalues,otherblues);
+ if ( (pt=PSDictHasEntry(sf->private,"FamilyOtherBlues"))!=NULL )
+ DumpStrArray(pt,private,9);
+ if ( (pt=PSDictHasEntry(sf->private,"BlueScale"))!=NULL )
+ DumpStrDouble(pt,private,(12<<8)+9);
+ else if ( bluescale!=-1 )
+ dumpdbloper(private,bluescale,(12<<8)+9);
+ if ( (pt=PSDictHasEntry(sf->private,"BlueShift"))!=NULL )
+ DumpStrDouble(pt,private,(12<<8)+10);
+ else
+ dumpintoper(private,bs,(12<<8)+10);
+ if ( (pt=PSDictHasEntry(sf->private,"BlueFuzz"))!=NULL )
+ DumpStrDouble(pt,private,(12<<8)+11);
+ if ( hash ) {
+ DumpStrDouble(PSDictHasEntry(sf->private,"StdHW"),private,10);
+ if ( (pt=PSDictHasEntry(sf->private,"StemSnapH"))!=NULL )
+ DumpStrArray(pt,private,(12<<8)|12);
+ } else {
+ if ( stdhw[0]!=0 )
+ dumpdbloper(private,stdhw[0],10);
+ DumpDblArray(stemsnaph,sizeof(stemsnaph)/sizeof(stemsnaph[0]),private,(12<<8)|12);
+ }
+ if ( hasv ) {
+ DumpStrDouble(PSDictHasEntry(sf->private,"StdVW"),private,11);
+ if ( (pt=PSDictHasEntry(sf->private,"StemSnapV"))!=NULL )
+ DumpStrArray(pt,private,(12<<8)|13);
+ } else {
+ if ( stdvw[0]!=0 )
+ dumpdbloper(private,stdvw[0],11);
+ DumpDblArray(stemsnapv,sizeof(stemsnapv)/sizeof(stemsnapv[0]),private,(12<<8)|13);
+ }
+ if ( (pt=PSDictHasEntry(sf->private,"ForceBold"))!=NULL ) {
+ dumpintoper(private,*pt=='t'||*pt=='T',(12<<8)|14);
+ } else if ( sf->weight!=NULL &&
+ (strstrmatch(sf->weight,"Bold")!=NULL ||
+ strstrmatch(sf->weight,"Demi")!=NULL ||
+ strstrmatch(sf->weight,"Fett")!=NULL ||
+ strstrmatch(sf->weight,"Gras")!=NULL ||
+ strstrmatch(sf->weight,"Heavy")!=NULL ||
+ strstrmatch(sf->weight,"Black")!=NULL))
+ dumpintoper(private,1,(12<<8)|14);
+ if ( (pt=PSDictHasEntry(sf->private,"LanguageGroup"))!=NULL )
+ DumpStrDouble(pt,private,(12<<8)+17);
+ else if ( map->enc->is_japanese ||
+ map->enc->is_korean ||
+ map->enc->is_tradchinese ||
+ map->enc->is_simplechinese )
+ dumpintoper(private,1,(12<<8)|17);
+ if ( (pt=PSDictHasEntry(sf->private,"ExpansionFactor"))!=NULL )
+ DumpStrDouble(pt,private,(12<<8)+18);
+ if ( subrcnt!=0 )
+ dumpsizedint(private,false,ftell(private)+3+1,19); /* Subrs */
+
+ if ( subfont==-1 )
+ at->privatelen = ftell(private);
+ else
+ at->fds[subfont].privatelen = ftell(private);
+}
+
+/* When we exit this the topdict is not complete, we still need to fill in */
+/* values for charset,encoding,charstrings and private. Then we need to go */
+/* back and fill in the table length (at lenpos) */
+static void dumpcfftopdict(SplineFont *sf,struct alltabs *at) {
+ char *pt, *end;
+ FILE *cfff = at->cfff;
+ DBounds b;
+
+ putshort(cfff,1); /* One top dict */
+ putc('\2',cfff); /* Offset size */
+ putshort(cfff,1); /* Offset to topdict */
+ at->lenpos = ftell(cfff);
+ putshort(cfff,0); /* placeholder for final position (final offset in index points beyond last element) */
+ dumpsid(cfff,at,sf->version,0);
+ dumpsid(cfff,at,sf->copyright,1);
+ dumpsid(cfff,at,sf->fullname?sf->fullname:sf->fontname,2);
+ dumpsid(cfff,at,sf->familyname,3);
+ dumpsid(cfff,at,sf->weight,4);
+ if ( at->gi.fixed_width!=-1 ) dumpintoper(cfff,1,(12<<8)|1);
+ if ( sf->italicangle!=0 ) dumpdbloper(cfff,sf->italicangle,(12<<8)|2);
+ if ( sf->upos!=-100 ) dumpdbloper(cfff,sf->upos,(12<<8)|3);
+ if ( sf->uwidth!=50 ) dumpdbloper(cfff,sf->uwidth,(12<<8)|4);
+ if ( sf->strokedfont ) {
+ dumpintoper(cfff,2,(12<<8)|5);
+ dumpdbloper(cfff,sf->strokewidth,(12<<8)|8);
+ }
+ /* We'll never set CharstringType */
+ if ( sf->ascent+sf->descent!=1000 ) {
+ dumpdbl(cfff,1.0/(sf->ascent+sf->descent));
+ dumpint(cfff,0);
+ dumpint(cfff,0);
+ dumpdbl(cfff,1.0/(sf->ascent+sf->descent));
+ dumpint(cfff,0);
+ dumpintoper(cfff,0,(12<<8)|7);
+ }
+ if ( sf->uniqueid!=-1 )
+ dumpintoper(cfff, sf->uniqueid?sf->uniqueid:4000000 + (rand()&0x3ffff), 13 );
+ SplineFontFindBounds(sf,&b);
+ at->gi.xmin = b.minx;
+ at->gi.ymin = b.miny;
+ at->gi.xmax = b.maxx;
+ at->gi.ymax = b.maxy;
+ dumpdbl(cfff,floor(b.minx));
+ dumpdbl(cfff,floor(b.miny));
+ dumpdbl(cfff,ceil(b.maxx));
+ dumpdbloper(cfff,ceil(b.maxy),5);
+ /* We'll never set StrokeWidth */
+ if ( sf->xuid!=NULL ) {
+ pt = sf->xuid; if ( *pt=='[' ) ++pt;
+ while ( *pt && *pt!=']' ) {
+ dumpint(cfff,strtol(pt,&end,10));
+ if ( pt==end ) /* garbage in XUID */
+ break;
+ for ( pt = end; *pt==' '; ++pt );
+ }
+ putc(14,cfff);
+ if ( sf->changed_since_xuidchanged )
+ SFIncrementXUID(sf);
+ }
+ /* Offset to charset (oper=15) needed here */
+ /* Offset to encoding (oper=16) needed here (not for CID )*/
+ /* Offset to charstrings (oper=17) needed here */
+ /* Length of, and Offset to private (oper=18) needed here (not for CID )*/
+}
+
+static int dumpcffdict(SplineFont *sf,struct alltabs *at) {
+ FILE *fdarray = at->fdarray;
+ int pstart;
+ /* according to the PSRef Man v3, only fontname, fontmatrix and private */
+ /* appear in this dictionary */
+
+ dumpsid(fdarray,at,sf->fontname,(12<<8)|38);
+ if ( sf->ascent+sf->descent!=1000 ) {
+ dumpdbl(fdarray,1.0/(sf->ascent+sf->descent));
+ dumpint(fdarray,0);
+ dumpint(fdarray,0);
+ dumpdbl(fdarray,1.0/(sf->ascent+sf->descent));
+ dumpint(fdarray,0);
+ dumpintoper(fdarray,0,(12<<8)|7);
+ }
+ pstart = ftell(fdarray);
+ dumpsizedint(fdarray,false,0,-1); /* private length */
+ dumpsizedint(fdarray,true,0,18); /* private offset */
+return( pstart );
+}
+
+static void dumpcffdictindex(SplineFont *sf,struct alltabs *at) {
+ int i;
+ int pos;
+
+ putshort(at->fdarray,sf->subfontcnt);
+ putc('\2',at->fdarray); /* DICTs aren't very big, and there are at most 255 */
+ putshort(at->fdarray,1); /* Offset to first dict */
+ for ( i=0; i<sf->subfontcnt; ++i )
+ putshort(at->fdarray,0); /* Dump offset placeholders (note there's one extra to mark the end) */
+ pos = ftell(at->fdarray)-1;
+ for ( i=0; i<sf->subfontcnt; ++i ) {
+ at->fds[i].fillindictmark = dumpcffdict(sf->subfonts[i],at);
+ at->fds[i].eodictmark = ftell(at->fdarray);
+ if ( at->fds[i].eodictmark>65536 )
+ IError("The DICT INDEX got too big, result won't work");
+ }
+ fseek(at->fdarray,2*sizeof(short)+sizeof(char),SEEK_SET);
+ for ( i=0; i<sf->subfontcnt; ++i )
+ putshort(at->fdarray,at->fds[i].eodictmark-pos);
+ fseek(at->fdarray,0,SEEK_END);
+}
+
+static void dumpcffcidtopdict(SplineFont *sf,struct alltabs *at) {
+ char *pt, *end;
+ FILE *cfff = at->cfff;
+ DBounds b;
+ int cidcnt=0, k;
+
+ for ( k=0; k<sf->subfontcnt; ++k )
+ if ( sf->subfonts[k]->glyphcnt>cidcnt ) cidcnt = sf->subfonts[k]->glyphcnt;
+
+ putshort(cfff,1); /* One top dict */
+ putc('\2',cfff); /* Offset size */
+ putshort(cfff,1); /* Offset to topdict */
+ at->lenpos = ftell(cfff);
+ putshort(cfff,0); /* placeholder for final position */
+ dumpsid(cfff,at,sf->cidregistry,-1);
+ dumpsid(cfff,at,sf->ordering,-1);
+ dumpintoper(cfff,sf->supplement,(12<<8)|30); /* ROS operator must be first */
+ dumpdbloper(cfff,sf->cidversion,(12<<8)|31);
+ dumpintoper(cfff,cidcnt,(12<<8)|34);
+ dumpintoper(cfff, sf->uniqueid?sf->uniqueid:4000000 + (rand()&0x3ffff), (12<<8)|35 );
+
+ dumpsid(cfff,at,sf->copyright,1);
+ dumpsid(cfff,at,sf->fullname?sf->fullname:sf->fontname,2);
+ dumpsid(cfff,at,sf->familyname,3);
+ dumpsid(cfff,at,sf->weight,4);
+ /* FontMatrix (identity here, real ones in sub fonts)*/
+ /* Actually there is no fontmatrix in the adobe cid font I'm looking at */
+ /* which means it should default to [.001...] but it doesn't so the */
+ /* docs aren't completely accurate */
+ /* I now see I've no idea what the FontMatrix means in a CID keyed font */
+ /* it seems to be ignored everywhere */
+#if 0
+ dumpdbl(cfff,1.0);
+ dumpint(cfff,0);
+ dumpint(cfff,0);
+ dumpdbl(cfff,1.0);
+ dumpint(cfff,0);
+ dumpintoper(cfff,0,(12<<8)|7);
+#endif
+
+ CIDFindBounds(sf,&b);
+ at->gi.xmin = b.minx;
+ at->gi.ymin = b.miny;
+ at->gi.xmax = b.maxx;
+ at->gi.ymax = b.maxy;
+ dumpdbl(cfff,floor(b.minx));
+ dumpdbl(cfff,floor(b.miny));
+ dumpdbl(cfff,ceil(b.maxx));
+ dumpdbloper(cfff,ceil(b.maxy),5);
+ /* We'll never set StrokeWidth */
+ if ( sf->xuid!=NULL ) {
+ pt = sf->xuid; if ( *pt=='[' ) ++pt;
+ while ( *pt && *pt!=']' ) {
+ dumpint(cfff,strtol(pt,&end,10));
+ for ( pt = end; *pt==' '; ++pt );
+ }
+ putc(14,cfff);
+ if ( sf->changed_since_xuidchanged )
+ SFIncrementXUID(sf);
+ }
+#if 0
+ /* Acrobat doesn't seem to care about a private dict here. Ghostscript */
+ /* dies. Tech Note: 5176.CFF.PDF, top of page 23 says: */
+ /* A Private DICT is required, but may be specified as having */
+ /* a length of 0 if there are no non-default values to be stored*/
+ /* No indication >where< it is required. I assumed everywhere. Perhaps */
+ /* just in basefonts? */
+ dumpint(cfff,0); /* Docs say a private dict is required and they don't specifically omit CID top dicts */
+ dumpintoper(cfff,0,18); /* But they do say it can be zero */
+#endif
+ /* Offset to charset (oper=15) needed here */
+ /* Offset to charstrings (oper=17) needed here */
+ /* Offset to FDArray (oper=12,36) needed here */
+ /* Offset to FDSelect (oper=12,37) needed here */
+}
+
+static int isStdEncoding(SplineFont *sf,EncMap *map) {
+ int i;
+
+ for ( i=0; i<256 && i<map->enccount; ++i ) if ( map->map[i]!=-1 && sf->glyphs[map->map[i]]!=NULL )
+ if ( sf->glyphs[map->map[i]]->unicodeenc!=-1 )
+ if ( sf->glyphs[map->map[i]]->unicodeenc!=unicode_from_adobestd[i] )
+return( 0 );
+
+return( 1 );
+}
+
+static void finishup(SplineFont *sf,struct alltabs *at) {
+ int strlen, shlen, glen,enclen,csetlen,cstrlen,prvlen;
+ int base, eotop, strhead;
+ int output_enc = ( at->format==ff_cff && !isStdEncoding(sf,at->map));
+
+ storesid(at,NULL); /* end the strings index */
+ strlen = ftell(at->sidf) + (shlen = ftell(at->sidh));
+ glen = sizeof(short); /* Single entry: 0, no globals */
+ enclen = ftell(at->encoding);
+ csetlen = ftell(at->charset);
+ cstrlen = ftell(at->charstrings);
+ prvlen = ftell(at->private);
+ base = ftell(at->cfff);
+ if ( base+6*3+strlen+glen+enclen+csetlen+cstrlen+prvlen > 32767 ) {
+ at->cfflongoffset = true;
+ base += 5*5+4;
+ } else
+ base += 5*3+4;
+ strhead = 2+(at->sidcnt>1);
+ base += strhead;
+
+ dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen,15); /* Charset */
+ if ( output_enc ) /* encoding offset */
+ dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen,16); /* encoding offset */
+ else {
+ dumpsizedint(at->cfff,at->cfflongoffset,0,16);
+ enclen = 0;
+ }
+ dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen+enclen,17);/* charstrings */
+ dumpsizedint(at->cfff,at->cfflongoffset,at->privatelen,-1);
+ dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen+enclen+cstrlen,18); /* private size */
+ eotop = base-strhead-at->lenpos-1;
+ if ( at->cfflongoffset ) {
+ fseek(at->cfff,3,SEEK_SET);
+ putc(4,at->cfff);
+ }
+ fseek(at->cfff,at->lenpos,SEEK_SET);
+ putshort(at->cfff,eotop);
+ fseek(at->cfff,0,SEEK_END);
+
+ /* String Index */
+ putshort(at->cfff,at->sidcnt-1);
+ if ( at->sidcnt!=1 ) { /* Everybody gets an added NULL */
+ putc(at->sidlongoffset?4:2,at->cfff);
+ if ( !ttfcopyfile(at->cfff,at->sidh,base,"CFF-StringBase")) at->error = true;
+ if ( !ttfcopyfile(at->cfff,at->sidf,base+shlen,"CFF-StringData")) at->error = true;
+ }
+
+ /* Global Subrs */
+ putshort(at->cfff,0);
+
+ /* Charset */
+ if ( !ttfcopyfile(at->cfff,at->charset,base+strlen+glen,"CFF-Charset")) at->error = true;
+
+ /* Encoding */
+ if ( !ttfcopyfile(at->cfff,at->encoding,base+strlen+glen+csetlen,"CFF-Encoding")) at->error = true;
+
+ /* Char Strings */
+ if ( !ttfcopyfile(at->cfff,at->charstrings,base+strlen+glen+csetlen+enclen,"CFF-CharStrings")) at->error = true;
+
+ /* Private & Subrs */
+ if ( !ttfcopyfile(at->cfff,at->private,base+strlen+glen+csetlen+enclen+cstrlen,"CFF-Private")) at->error = true;
+}
+
+static void finishupcid(SplineFont *sf,struct alltabs *at) {
+ int strlen, shlen, glen,csetlen,cstrlen,fdsellen,fdarrlen,prvlen;
+ int base, eotop, strhead;
+ int i;
+
+ storesid(at,NULL); /* end the strings index */
+ strlen = ftell(at->sidf) + (shlen = ftell(at->sidh));
+ glen = ftell(at->globalsubrs);
+ /* No encodings */
+ csetlen = ftell(at->charset);
+ fdsellen = ftell(at->fdselect);
+ cstrlen = ftell(at->charstrings);
+ fdarrlen = ftell(at->fdarray);
+ base = ftell(at->cfff);
+
+ at->cfflongoffset = true;
+ base += 5*4+4+2; /* two of the opers below are two byte opers */
+ strhead = 2+(at->sidcnt>1);
+ base += strhead;
+
+ prvlen = 0;
+ for ( i=0; i<sf->subfontcnt; ++i ) {
+ fseek(at->fdarray,at->fds[i].fillindictmark,SEEK_SET);
+ dumpsizedint(at->fdarray,false,at->fds[i].privatelen,-1); /* Private len */
+ dumpsizedint(at->fdarray,true,base+strlen+glen+csetlen+fdsellen+cstrlen+fdarrlen+prvlen,18); /* Private offset */
+ prvlen += ftell(at->fds[i].private); /* private & subrs */
+ }
+
+ dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen,15); /* charset */
+ dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen,(12<<8)|37); /* fdselect */
+ dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen+fdsellen,17); /* charstrings */
+ dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen+fdsellen+cstrlen,(12<<8)|36); /* fdarray */
+ eotop = base-strhead-at->lenpos-1;
+ fseek(at->cfff,at->lenpos,SEEK_SET);
+ putshort(at->cfff,eotop);
+ fseek(at->cfff,0,SEEK_END);
+
+ /* String Index */
+ putshort(at->cfff,at->sidcnt-1);
+ if ( at->sidcnt!=1 ) { /* Everybody gets an added NULL */
+ putc(at->sidlongoffset?4:2,at->cfff);
+ if ( !ttfcopyfile(at->cfff,at->sidh,base,"CFF-StringBase")) at->error = true;
+ if ( !ttfcopyfile(at->cfff,at->sidf,base+shlen,"CFF-StringData")) at->error = true;
+ }
+
+ /* Global Subrs */
+ if ( !ttfcopyfile(at->cfff,at->globalsubrs,base+strlen,"CFF-GlobalSubrs")) at->error = true;
+
+ /* Charset */
+ if ( !ttfcopyfile(at->cfff,at->charset,base+strlen+glen,"CFF-Charset")) at->error = true;
+
+ /* FDSelect */
+ if ( !ttfcopyfile(at->cfff,at->fdselect,base+strlen+glen+csetlen,"CFF-FDSelect")) at->error = true;
+
+ /* Char Strings */
+ if ( !ttfcopyfile(at->cfff,at->charstrings,base+strlen+glen+csetlen+fdsellen,"CFF-CharStrings")) at->error = true;
+
+ /* FDArray (DICT Index) */
+ if ( !ttfcopyfile(at->cfff,at->fdarray,base+strlen+glen+csetlen+fdsellen+cstrlen,"CFF-FDArray")) at->error = true;
+
+ /* Private & Subrs */
+ prvlen = 0;
+ for ( i=0; i<sf->subfontcnt; ++i ) {
+ int temp = ftell(at->fds[i].private);
+ if ( !ttfcopyfile(at->cfff,at->fds[i].private,
+ base+strlen+glen+csetlen+fdsellen+cstrlen+fdarrlen+prvlen,"CFF-PrivateSubrs")) at->error = true;
+ prvlen += temp;
+ }
+
+ free(at->fds);
+}
+
+static int dumpcffhmtx(struct alltabs *at,SplineFont *sf,int bitmaps) {
+ DBounds b;
+ SplineChar *sc;
+ int i,cnt;
+ int dovmetrics = sf->hasvmetrics;
+ int width = at->gi.fixed_width;
+
+ at->gi.hmtx = tmpfile();
+ if ( dovmetrics )
+ at->gi.vmtx = tmpfile();
+ FigureFullMetricsEnd(sf,&at->gi,bitmaps); /* Bitmap fonts use ttf convention of 3 magic glyphs */
+ if ( at->gi.bygid[0]!=-1 && (sf->glyphs[at->gi.bygid[0]]->width==width || width==-1 )) {
+ putshort(at->gi.hmtx,sf->glyphs[at->gi.bygid[0]]->width);
+ SplineCharFindBounds(sf->glyphs[at->gi.bygid[0]],&b);
+ putshort(at->gi.hmtx,b.minx);
+ if ( dovmetrics ) {
+ putshort(at->gi.vmtx,sf->glyphs[at->gi.bygid[0]]->vwidth);
+ putshort(at->gi.vmtx,sf->vertical_origin-b.miny);
+ }
+ } else {
+ putshort(at->gi.hmtx,width==-1?(sf->ascent+sf->descent)/2:width);
+ putshort(at->gi.hmtx,0);
+ if ( dovmetrics ) {
+ putshort(at->gi.vmtx,sf->ascent+sf->descent);
+ putshort(at->gi.vmtx,0);
+ }
+ }
+ cnt = 1;
+ if ( bitmaps ) {
+ if ( width==-1 ) width = (sf->ascent+sf->descent)/3;
+ putshort(at->gi.hmtx,width);
+ putshort(at->gi.hmtx,0);
+ if ( dovmetrics ) {
+ putshort(at->gi.vmtx,sf->ascent+sf->descent);
+ putshort(at->gi.vmtx,0);
+ }
+ putshort(at->gi.hmtx,width);
+ putshort(at->gi.hmtx,0);
+ if ( dovmetrics ) {
+ putshort(at->gi.vmtx,sf->ascent+sf->descent);
+ putshort(at->gi.vmtx,0);
+ }
+ cnt = 3;
+ }
+
+ for ( i=cnt; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
+ sc = sf->glyphs[at->gi.bygid[i]];
+ if ( SCWorthOutputting(sc) ) {
+ if ( i<=at->gi.lasthwidth )
+ putshort(at->gi.hmtx,sc->width);
+ SplineCharFindBounds(sc,&b);
+ putshort(at->gi.hmtx,b.minx);
+ if ( dovmetrics ) {
+ if ( i<=at->gi.lastvwidth )
+ putshort(at->gi.vmtx,sc->vwidth);
+ putshort(at->gi.vmtx,sf->vertical_origin-b.maxy);
+ }
+ ++cnt;
+ if ( i==at->gi.lasthwidth )
+ at->gi.hfullcnt = cnt;
+ if ( i==at->gi.lastvwidth )
+ at->gi.vfullcnt = cnt;
+ }
+ }
+ at->gi.hmtxlen = ftell(at->gi.hmtx);
+ if ( at->gi.hmtxlen&2 ) putshort(at->gi.hmtx,0);
+ if ( dovmetrics ) {
+ at->gi.vmtxlen = ftell(at->gi.vmtx);
+ if ( at->gi.vmtxlen&2 ) putshort(at->gi.vmtx,0);
+ }
+
+ at->gi.maxp->numGlyphs = cnt;
+return( true );
+}
+
+static void dumpcffcidhmtx(struct alltabs *at,SplineFont *_sf) {
+ DBounds b;
+ SplineChar *sc;
+ int cid,i,cnt=0,max;
+ SplineFont *sf = NULL;
+ int dovmetrics = _sf->hasvmetrics;
+
+ at->gi.hmtx = tmpfile();
+ if ( dovmetrics )
+ at->gi.vmtx = tmpfile();
+ FigureFullMetricsEnd(_sf,&at->gi,false);
+
+ max = 0;
+ for ( i=0; i<_sf->subfontcnt; ++i )
+ if ( max<_sf->subfonts[i]->glyphcnt )
+ max = _sf->subfonts[i]->glyphcnt;
+ for ( cid = 0; cid<max; ++cid ) {
+ for ( i=0; i<_sf->subfontcnt; ++i ) {
+ sf = _sf->subfonts[i];
+ if ( cid<sf->glyphcnt && SCWorthOutputting(sf->glyphs[cid]))
+ break;
+ }
+ if ( i!=_sf->subfontcnt ) {
+ sc = sf->glyphs[cid];
+ if ( sc->ttf_glyph<=at->gi.lasthwidth )
+ putshort(at->gi.hmtx,sc->width);
+ SplineCharFindBounds(sc,&b);
+ putshort(at->gi.hmtx,b.minx);
+ if ( dovmetrics ) {
+ if ( sc->ttf_glyph<=at->gi.lastvwidth )
+ putshort(at->gi.vmtx,sc->vwidth);
+ putshort(at->gi.vmtx,sf->vertical_origin-b.maxy);
+ }
+ ++cnt;
+ if ( sc->ttf_glyph==at->gi.lasthwidth )
+ at->gi.hfullcnt = cnt;
+ if ( sc->ttf_glyph==at->gi.lastvwidth )
+ at->gi.vfullcnt = cnt;
+ } else if ( cid==0 ) {
+ /* Create a dummy entry for .notdef */
+ sf = _sf->subfonts[0];
+ putshort(at->gi.hmtx,sf->ascent+sf->descent);
+ putshort(at->gi.hmtx,0);
+ ++cnt;
+ if ( dovmetrics ) {
+ putshort(at->gi.vmtx,sf->ascent+sf->descent);
+ putshort(at->gi.vmtx,0);
+ }
+ }
+ }
+ at->gi.hmtxlen = ftell(at->gi.hmtx);
+ if ( at->gi.hmtxlen&2 ) putshort(at->gi.hmtx,0);
+ if ( dovmetrics ) {
+ at->gi.vmtxlen = ftell(at->gi.vmtx);
+ if ( at->gi.vmtxlen&2 ) putshort(at->gi.vmtx,0);
+ }
+
+ at->gi.maxp->numGlyphs = cnt;
+}
+
+static int dumptype2glyphs(SplineFont *sf,struct alltabs *at) {
+ int i;
+ struct pschars *subrs, *chrs;
+
+ at->cfff = tmpfile();
+ at->sidf = tmpfile();
+ at->sidh = tmpfile();
+ at->charset = tmpfile();
+ at->encoding = tmpfile();
+ at->private = tmpfile();
+
+ dumpcffheader(sf,at->cfff);
+ dumpcffnames(sf,at->cfff);
+ dumpcffcharset(sf,at);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_change_stages(2+at->gi.strikecnt);
+#endif
+
+ ATFigureDefWidth(sf,at,-1);
+ if ((chrs =SplineFont2ChrsSubrs2(sf,at->nomwid,at->defwid,at->gi.bygid,at->gi.gcnt,at->gi.flags,&subrs))==NULL )
+return( false );
+ dumpcffprivate(sf,at,-1,subrs->next);
+ if ( subrs->next!=0 )
+ _dumpcffstrings(at->private,subrs);
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ gwwv_progress_next_stage();
+#endif
+ at->charstrings = dumpcffstrings(chrs);
+ PSCharsFree(subrs);
+ if ( at->charstrings == NULL )
+return( false );
+ if ( at->format==ff_cff && !isStdEncoding(sf,at->map))
+ dumpcffencoding(sf,at); /* Do this after we've assigned glyph ids */
+ dumpcfftopdict(sf,at);
+ finishup(sf,at);
+
+ at->cfflen = ftell(at->cfff);
+ if ( at->cfflen&3 ) {
+ for ( i=4-(at->cfflen&3); i>0; --i )
+ putc('\0',at->cfff);
+ }
+
+ if ( at->format!=ff_cff )
+ dumpcffhmtx(at,sf,false);
+ free(at->gn_sid); at->gn_sid=NULL;
+return( true );
+}
+
+static int dumpcidglyphs(SplineFont *sf,struct alltabs *at) {
+ int i;
+ struct pschars *glbls = NULL, *chrs;
+
+ at->cfff = tmpfile();
+ at->sidf = tmpfile();
+ at->sidh = tmpfile();
+ at->charset = tmpfile();
+ at->fdselect = tmpfile();
+ at->fdarray = tmpfile();
+ at->globalsubrs = tmpfile();
+
+ at->fds = gcalloc(sf->subfontcnt,sizeof(struct fd2data));
+ for ( i=0; i<sf->subfontcnt; ++i ) {
+ at->fds[i].private = tmpfile();
+ ATFigureDefWidth(sf->subfonts[i],at,i);
+ }
+ if ( (chrs = CID2ChrsSubrs2(sf,at->fds,at->gi.flags,&glbls))==NULL )
+return( false );
+ for ( i=0; i<sf->subfontcnt; ++i ) {
+ dumpcffprivate(sf->subfonts[i],at,i,at->fds[i].subrs->next);
+ if ( at->fds[i].subrs->next!=0 )
+ _dumpcffstrings(at->fds[i].private,at->fds[i].subrs);
+ PSCharsFree(at->fds[i].subrs);
+ }
+ _dumpcffstrings(at->globalsubrs,glbls);
+ PSCharsFree(glbls);
+
+ dumpcffheader(sf,at->cfff);
+ dumpcffnames(sf,at->cfff);
+ dumpcffcidset(sf,at);
+ dumpcfffdselect(sf,at);
+ dumpcffdictindex(sf,at);
+ if ( (at->charstrings = dumpcffstrings(chrs))==NULL )
+return( false );
+ dumpcffcidtopdict(sf,at);
+ finishupcid(sf,at);
+
+ at->cfflen = ftell(at->cfff);
+ if ( at->cfflen&3 ) {
+ for ( i=4-(at->cfflen&3); i>0; --i )
+ putc('\0',at->cfff);
+ }
+
+ if ( at->format!=ff_cffcid )
+ dumpcffcidhmtx(at,sf);
+return( true );
+}
+
+static int AnyInstructions(SplineFont *sf) {
+ int i;
+
+ if ( sf->subfontcnt!=0 ) {
+ for ( i=0; i<sf->subfontcnt; ++i )
+ if ( AnyInstructions(sf->subfonts[i]))
+return( true );
+ } else {
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ if ( sf->glyphs[i]->ttf_instrs_len!=0 )
+return( true );
+ }
+ }
+return( false );
+}
+
+#ifdef _HAS_LONGLONG
+void cvt_unix_to_1904( long long time, int32 result[2]) {
+ uint32 date1970[4], tm[4];
+ uint32 year[2];
+ int i;
+
+ tm[0] = time &0xffff;
+ tm[1] = (time>>16)&0xffff;
+ tm[2] = (time>>32)&0xffff;
+ tm[3] = (time>>48)&0xffff;
+#else
+void cvt_unix_to_1904( long time, int32 result[2]) {
+ int32 date1970[4], tm[4];
+ uint32 year[2];
+ int i;
+
+ tm[0] = time &0xffff;
+ tm[1] = (time>>16)&0xffff;
+ tm[2] = 0;
+ tm[3] = 0;
+#endif
+ memset(date1970,0,sizeof(date1970));
+ year[0] = (60*60*24*365L)&0xffff;
+ year[1] = (60*60*24*365L)>>16;
+ for ( i=1904; i<1970; ++i ) {
+ date1970[0] += year[0];
+ date1970[1] += year[1];
+ if ( (i&3)==0 && (i%100!=0 || i%400==0))
+ date1970[0] += 24*60*60L; /* Leap year */
+ date1970[1] += (date1970[0]>>16);
+ date1970[0] &= 0xffff;
+ date1970[2] += date1970[1]>>16;
+ date1970[1] &= 0xffff;
+ date1970[3] += date1970[2]>>16;
+ date1970[2] &= 0xffff;
+ }
+
+ for ( i=0; i<3; ++i ) {
+ tm[i] += date1970[i];
+ tm[i+1] += tm[i]>>16;
+ tm[i] &= 0xffff;
+ }
+ tm[3] -= date1970[3];
+
+ result[0] = (tm[1]<<16) | tm[0];
+ result[1] = (tm[3]<<16) | tm[2];
+}
+
+static void sethead(struct head *head,SplineFont *sf,struct alltabs *at) {
+ time_t now;
+ int i, lr, rl, indic_rearrange, arabic;
+ ASM *sm;
+
+ lr = rl = arabic = 0;
+ for ( i=0; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
+ SplineChar *sc = sf->glyphs[at->gi.bygid[i]];
+ int uni = sc->unicodeenc ;
+ if ( SCRightToLeft(sc) )
+ rl = 1;
+ else if (( uni!=-1 && uni<0x10000 && islefttoright(uni)) ||
+ (uni>=0x10300 && uni<0x107ff))
+ lr = 1;
+ if ( SCScriptFromUnicode(sc)==CHR('a','r','a','b') )
+ arabic = 1;
+ }
+
+ head->version = 0x00010000;
+ if ( sf->subfontcnt!=0 ) {
+ int val, mant;
+ val = floor(sf->cidversion);
+ mant = floor(65536.*(sf->cidversion-val));
+ head->revision = (val<<16) | mant;
+ } else if ( sf->version!=NULL ) {
+ char *pt=sf->version;
+ double dval;
+ int val, mant;
+ while ( *pt && !isdigit(*pt) && *pt!='.' ) ++pt;
+ if ( *pt ) {
+ dval = strtod(pt,NULL);
+ val = floor(dval);
+ mant = floor(65536.*(dval-val));
+ head->revision = (val<<16) | mant;
+ }
+ }
+ head->checksumAdj = 0;
+ head->magicNum = 0x5f0f3cf5;
+ head->flags = 8|2|1; /* baseline at 0, lsbline at 0, round ppem */
+ if ( AnyInstructions(sf))
+ head->flags = 0x10|8|4|2|1; /* baseline at 0, lsbline at 0, round ppem, instructions may depend on point size, instructions change metrics */
+/* Apple flags */
+ if ( sf->hasvmetrics )
+ head->flags |= (1<<5); /* designed to be layed out vertically */
+ /* Bit 6 must be zero */
+ if ( arabic )
+ head->flags |= (1<<7);
+ if ( sf->sm )
+ head->flags |= (1<<8); /* has metamorphesis effects */
+ if ( rl )
+ head->flags |= (1<<9);
+ indic_rearrange = 0;
+ for ( sm = sf->sm; sm!=NULL; sm=sm->next )
+ if ( sm->type == asm_indic )
+ indic_rearrange = true;
+ if ( indic_rearrange )
+ head->flags |= (1<<10);
+/* End apple flags */
+ if ( sf->head_optimized_for_cleartype )
+ head->flags |= (1<<13);
+ head->emunits = sf->ascent+sf->descent;
+ head->macstyle = MacStyleCode(sf,NULL);
+ head->lowestreadable = 8;
+ head->locais32 = 1;
+
+ /* I assume we've always got some neutrals (spaces, punctuation) */
+ if ( lr && rl )
+ head->dirhint = 0;
+ else if ( rl )
+ head->dirhint = -2;
+ else
+ head->dirhint = 2;
+ if ( rl )
+ head->flags |= (1<<9); /* Apple documents this */
+ /* if there are any indic characters, set bit 10 */
+
+ time(&now); /* seconds since 1970, need to convert to seconds since 1904 */
+ cvt_unix_to_1904(now,head->modtime);
+ memcpy(head->createtime,head->modtime,sizeof(head->modtime));
+}
+
+static void sethhead(struct hhead *hhead,struct hhead *vhead,struct alltabs *at, SplineFont *sf) {
+ int i, width, rbearing, height, bbearing;
+ int ymax, ymin, xmax, xmin, off;
+ DBounds bb;
+ /* Might as well fill in the vhead even if we don't use it */
+ /* we just won't dump it out if we don't want it */
+
+ width = 0x80000000; rbearing = 0x7fffffff; height = 0x80000000; bbearing=0x7fffffff;
+ xmax = ymax = 0x80000000; xmin = ymin = 0x7fffffff;
+ for ( i=0; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
+ SplineChar *sc = sf->glyphs[at->gi.bygid[i]];
+ SplineCharFindBounds(sc,&bb);
+ if ( sc->width>width ) width = sc->width;
+ if ( sc->vwidth>height ) height = sc->vwidth;
+ if ( sc->width-bb.maxx < rbearing ) rbearing = sc->width-bb.maxx;
+ if ( sc->vwidth-bb.maxy < bbearing ) bbearing = sc->vwidth-bb.maxy;
+ if ( bb.maxy > ymax ) ymax = bb.maxy;
+ if ( bb.miny < ymin ) ymin = bb.miny;
+ if ( bb.maxx > xmax ) xmax = bb.maxx;
+ if ( bb.minx < xmin ) xmin = bb.minx;
+ }
+
+ if ( at->head.ymax>ymax ) ymax = at->head.ymax; /* If generated .notdef glyph is bigger than real glyphs */
+ if ( at->head.ymin<ymin ) ymin = at->head.ymin;
+
+ if ( ymax==0 && ymin==0 ) {
+ /* this can happen in a bitmap only font */
+ ymax = sf->ascent;
+ ymin = -sf->descent;
+ }
+ hhead->version = 0x00010000;
+ if ( sf->pfminfo.hheadascent_add )
+ hhead->ascender = ymax + sf->pfminfo.hhead_ascent;
+ else
+ hhead->ascender = sf->pfminfo.hhead_ascent;
+ if ( sf->pfminfo.hheadascent_add )
+ hhead->descender = ymin + sf->pfminfo.hhead_descent;
+ else
+ hhead->descender = sf->pfminfo.hhead_descent;
+ hhead->linegap = sf->pfminfo.linegap;
+
+ vhead->version = 0x00011000;
+ off = (sf->ascent+sf->descent)/2;
+ vhead->ascender = xmax-off;
+ vhead->descender = xmin-off;
+ vhead->linegap = sf->pfminfo.linegap;
+
+ at->isfixed = at->gi.fixed_width!=-1;
+ hhead->maxwidth = width;
+ hhead->minlsb = at->head.xmin;
+ hhead->minrsb = rbearing;
+ /* Apple's ftxvalidator says the the min sidebearing should be 0 even if it isn't */
+ if ( hhead->minlsb>0 ) hhead->minlsb = 0;
+ if ( hhead->minrsb>0 ) hhead->minrsb = 0;
+ hhead->maxextent = at->head.xmax;
+ if ( sf->italicangle==0 )
+ hhead->caretSlopeRise = 1;
+ else {
+ hhead->caretSlopeRise = 100;
+ hhead->caretSlopeRun = (int) rint(100*tan(-sf->italicangle*3.1415926535897/180.));
+ }
+
+ vhead->maxwidth = height;
+ vhead->minlsb = at->head.ymin;
+ vhead->minrsb = bbearing;
+ vhead->maxextent = at->head.ymax;
+ vhead->caretSlopeRise = 0;
+ vhead->caretSlopeRun = 1;
+ /* Are there vertical oblique fonts? */
+
+ hhead->numMetrics = at->gi.hfullcnt;
+ vhead->numMetrics = at->gi.vfullcnt;
+}
+
+static void setvorg(struct vorg *vorg, SplineFont *sf) {
+ vorg->majorVersion = 1;
+ vorg->minorVersion = 0;
+ vorg->defaultVertOriginY = sf->vertical_origin;
+ vorg->numVertOriginYMetrics = 0;
+}
+
+static void OS2WeightCheck(struct pfminfo *pfminfo,char *weight) {
+ if ( weight==NULL ) {
+ /* default it */
+ } else if ( strstrmatch(weight,"medi")!=NULL ) {
+ pfminfo->weight = 500;
+ pfminfo->panose[2] = 6;
+ } else if ( strstrmatch(weight,"demi")!=NULL ||
+ strstrmatch(weight,"halb")!=NULL ||
+ (strstrmatch(weight,"semi")!=NULL &&
+ strstrmatch(weight,"bold")!=NULL) ) {
+ pfminfo->weight = 600;
+ pfminfo->panose[2] = 7;
+ } else if ( strstrmatch(weight,"bold")!=NULL ||
+ strstrmatch(weight,"fett")!=NULL ||
+ strstrmatch(weight,"gras")!=NULL ) {
+ pfminfo->weight = 700;
+ pfminfo->panose[2] = 8;
+ } else if ( strstrmatch(weight,"heavy")!=NULL ) {
+ pfminfo->weight = 800;
+ pfminfo->panose[2] = 9;
+ } else if ( strstrmatch(weight,"black")!=NULL ) {
+ pfminfo->weight = 900;
+ pfminfo->panose[2] = 10;
+ } else if ( strstrmatch(weight,"nord")!=NULL ) {
+ pfminfo->weight = 950;
+ pfminfo->panose[2] = 11;
+ } else if ( strstrmatch(weight,"thin")!=NULL ) {
+ pfminfo->weight = 100;
+ pfminfo->panose[2] = 2;
+ } else if ( strstrmatch(weight,"extra")!=NULL ||
+ strstrmatch(weight,"light")!=NULL ) {
+ pfminfo->weight = 200;
+ pfminfo->panose[2] = 3;
+ } else if ( strstrmatch(weight,"light")!=NULL ) {
+ pfminfo->weight = 300;
+ pfminfo->panose[2] = 4;
+ }
+}
+
+void SFDefaultOS2Simple(struct pfminfo *pfminfo,SplineFont *sf) {
+ pfminfo->pfmfamily = 0x11;
+ pfminfo->panose[0] = 2;
+ pfminfo->weight = 400;
+ pfminfo->panose[2] = 5;
+ pfminfo->width = 5;
+ pfminfo->panose[3] = 3;
+ pfminfo->winascent_add = pfminfo->windescent_add = true;
+ pfminfo->hheadascent_add = pfminfo->hheaddescent_add = true;
+ pfminfo->typoascent_add = pfminfo->typodescent_add = true;
+ pfminfo->os2_winascent = pfminfo->os2_windescent = 0;
+
+ if ( sf->subfonts!=NULL ) sf = sf->subfonts[0];
+ pfminfo->linegap = pfminfo->vlinegap = pfminfo->os2_typolinegap =
+ rint(.09*(sf->ascent+sf->descent));
+}
+
+void SFDefaultOS2SubSuper(struct pfminfo *pfminfo,int emsize,double italic_angle) {
+ double s = sin(italic_angle*3.1415926535897932/180.0);
+ pfminfo->os2_supysize = pfminfo->os2_subysize = .7*emsize;
+ pfminfo->os2_supxsize = pfminfo->os2_subxsize = .65*emsize;
+ pfminfo->os2_subyoff = .14*emsize;
+ pfminfo->os2_supyoff = .48*emsize;
+ pfminfo->os2_supxoff = s*pfminfo->os2_supyoff;
+ pfminfo->os2_subxoff = -s*pfminfo->os2_subyoff;
+ pfminfo->os2_strikeysize = 102*emsize/2048;
+ pfminfo->os2_strikeypos = 530*emsize/2048;
+}
+
+void SFDefaultOS2Info(struct pfminfo *pfminfo,SplineFont *sf,char *fontname) {
+ int samewid= -1;
+ char *weight = sf->cidmaster==NULL ? sf->weight : sf->cidmaster->weight;
+
+ if ( sf->pfminfo.pfmset ) {
+ if ( pfminfo!=&sf->pfminfo )
+ *pfminfo = sf->pfminfo;
+ if ( !pfminfo->panose_set ) {
+ struct pfminfo info;
+ memset(&info,0,sizeof(info));
+ sf->pfminfo.pfmset = false;
+ SFDefaultOS2Info(&info,sf,fontname);
+ sf->pfminfo.pfmset = true;
+ memcpy(pfminfo->panose,info.panose,sizeof(info.panose));
+ }
+ } else {
+ struct pfminfo hold;
+ if ( pfminfo->hheadset || pfminfo->vheadset )
+ hold = *pfminfo;
+ else
+ hold.hheadset = hold.vheadset = false;
+ memset(pfminfo,'\0',sizeof(*pfminfo));
+ SFDefaultOS2Simple(pfminfo,sf);
+ samewid = CIDOneWidth(sf);
+
+ pfminfo->pfmfamily = 0x10;
+ if ( samewid>0 ) {
+ pfminfo->pfmfamily = 0x30;
+ /* pfminfo->panose[3] = 9; */ /* This is done later */
+ } else if ( strstrmatch(fontname,"sans")!=NULL )
+ pfminfo->pfmfamily = 0x20;
+ else if ( strstrmatch(fontname,"script")!=NULL ) {
+ pfminfo->pfmfamily = 0x40;
+ pfminfo->panose[0] = 3;
+ }
+ if ( samewid==-1 )
+ pfminfo->pfmfamily |= 0x1; /* Else it assumes monospace */
+
+/* urw uses 4 character abreviations */
+ if ( weight!=NULL )
+ OS2WeightCheck(pfminfo,weight);
+ OS2WeightCheck(pfminfo,fontname);
+
+ if ( strstrmatch(fontname,"ultra")!=NULL &&
+ strstrmatch(fontname,"condensed")!=NULL ) {
+ pfminfo->width = 1;
+ pfminfo->panose[3] = 8;
+ } else if ( strstrmatch(fontname,"extra")!=NULL &&
+ strstrmatch(fontname,"condensed")!=NULL ) {
+ pfminfo->width = 2;
+ pfminfo->panose[3] = 8;
+ } else if ( strstrmatch(fontname,"semi")!=NULL &&
+ strstrmatch(fontname,"condensed")!=NULL ) {
+ pfminfo->width = 4;
+ pfminfo->panose[3] = 6;
+ } else if ( strstrmatch(fontname,"condensed")!=NULL ||
+ strstrmatch(fontname,"narrow")!=NULL ) {
+ pfminfo->width = 3;
+ pfminfo->panose[3] = 6;
+ } else if ( strstrmatch(fontname,"ultra")!=NULL &&
+ strstrmatch(fontname,"expanded")!=NULL ) {
+ pfminfo->width = 9;
+ pfminfo->panose[3] = 7;
+ } else if ( strstrmatch(fontname,"extra")!=NULL &&
+ strstrmatch(fontname,"expanded")!=NULL ) {
+ pfminfo->width = 8;
+ pfminfo->panose[3] = 7;
+ } else if ( strstrmatch(fontname,"semi")!=NULL &&
+ strstrmatch(fontname,"expanded")!=NULL ) {
+ pfminfo->width = 6;
+ pfminfo->panose[3] = 5;
+ } else if ( strstrmatch(fontname,"expanded")!=NULL ) {
+ pfminfo->width = 7;
+ pfminfo->panose[3] = 5;
+ }
+ if ( samewid>0 )
+ pfminfo->panose[3] = 9;
+ if ( hold.hheadset ) {
+ pfminfo->hheadset = true;
+ pfminfo->hheadascent_add = hold.hheadascent_add;
+ pfminfo->hheaddescent_add = hold.hheaddescent_add;
+ pfminfo->hhead_ascent = hold.hhead_ascent;
+ pfminfo->hhead_descent = hold.hhead_descent;
+ pfminfo->linegap = hold.linegap;
+ }
+ if ( hold.vheadset ) {
+ pfminfo->vheadset = true;
+ pfminfo->vlinegap = hold.vlinegap;
+ }
+ }
+ if ( !pfminfo->subsuper_set )
+ SFDefaultOS2SubSuper(pfminfo,sf->ascent+sf->descent,sf->italicangle);
+}
+
+void OS2FigureCodePages(SplineFont *sf, uint32 CodePage[2]) {
+ int i;
+ uint32 latin1[8];
+ int has_ascii, has_latin1;
+
+ memset(latin1,0,sizeof(latin1));
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ if ( sf->glyphs[i]->unicodeenc<256 && sf->glyphs[i]->unicodeenc>=0 )
+ latin1[(sf->glyphs[i]->unicodeenc>>5)] |= 1<<(sf->glyphs[i]->unicodeenc&31);
+ }
+
+ has_ascii = latin1[1]==0xffffffff && latin1[2]==0xffffffff &&
+ (latin1[3]&0x7fffffff)==0x7fffffff; /* DEL is not a char */
+ has_latin1 = has_ascii && (latin1[5]&~1&~(1<<0xd))== (~1&~(1<<0xd)) && /* Ignore nobreak space, softhyphen */
+ latin1[6]==0xffffffff && latin1[7] == 0xffffffff;
+ CodePage[0] = CodePage[1] = 0;
+ if ( has_ascii ) CodePage[1] |= 1U<<31; /* US (Ascii I assume) */
+ if ( has_latin1 ) CodePage[0] |= 1U<<30; /* WE/latin1 */
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ if ( sf->glyphs[i]->unicodeenc==0xde && has_ascii )
+ CodePage[0] |= 1<<0; /* (ANSI) Latin1 */
+ else if ( sf->glyphs[i]->unicodeenc==0x13d && has_ascii ) {
+ CodePage[0] |= 1<<1; /* latin2 */
+ CodePage[1] |= 1<<26; /* latin2 */
+ } else if ( sf->glyphs[i]->unicodeenc==0x411 ) {
+ CodePage[0] |= 1<<2; /* cyrillic */
+ CodePage[1] |= 1<<17; /* MS DOS Russian */
+ CodePage[1] |= 1<<25; /* IBM Cyrillic */
+ } else if ( sf->glyphs[i]->unicodeenc==0x386 ) {
+ CodePage[0] |= 1<<3; /* greek */
+ CodePage[1] |= 1<<16; /* IBM Greek */
+ CodePage[1] |= 1<<28; /* Greek, former 437 G */
+ } else if ( sf->glyphs[i]->unicodeenc==0x130 && has_ascii ) {
+ CodePage[0] |= 1<<4; /* turkish */
+ CodePage[1] |= 1<<24; /* IBM turkish */
+ } else if ( sf->glyphs[i]->unicodeenc==0x5d0 ) {
+ CodePage[0] |= 1<<5; /* hebrew */
+ CodePage[1] |= 1<<21; /* hebrew */
+ } else if ( sf->glyphs[i]->unicodeenc==0x631 ) {
+ CodePage[0] |= 1<<6; /* arabic */
+ CodePage[1] |= 1<<19; /* arabic */
+ CodePage[1] |= 1<<29; /* arabic; ASMO 708 */
+ } else if ( sf->glyphs[i]->unicodeenc==0x157 && has_ascii ) {
+ CodePage[0] |= 1<<7; /* baltic */
+ CodePage[1] |= 1<<27; /* baltic */
+ } else if ( sf->glyphs[i]->unicodeenc==0x20AB && has_ascii ) {
+ CodePage[0] |= 1<<8; /* vietnamese */
+ } else if ( sf->glyphs[i]->unicodeenc==0xe45 )
+ CodePage[0] |= 1<<16; /* thai */
+ else if ( sf->glyphs[i]->unicodeenc==0x30a8 )
+ CodePage[0] |= 1<<17; /* japanese */
+ else if ( sf->glyphs[i]->unicodeenc==0x3105 )
+ CodePage[0] |= 1<<18; /* simplified chinese */
+ else if ( sf->glyphs[i]->unicodeenc==0x3131 )
+ CodePage[0] |= 1<<19; /* korean wansung */
+ else if ( sf->glyphs[i]->unicodeenc==0x592E )
+ CodePage[0] |= 1<<20; /* traditional chinese */
+ else if ( sf->glyphs[i]->unicodeenc==0xacf4 )
+ CodePage[0] |= 1<<21; /* korean Johab */
+ else if ( sf->glyphs[i]->unicodeenc==0x2030 && has_ascii )
+ CodePage[0] |= 1U<<29; /* mac roman */
+ else if ( sf->glyphs[i]->unicodeenc==0x2665 && has_ascii )
+ CodePage[0] |= 1U<<30; /* OEM */
+#if 0 /* the symbol bit doesn't mean it contains the glyphs in symbol */
+ /* rather that one is using a symbol encoding. Or that there are */
+ /* glyphs with unicode encoding between 0xf000 and 0xf0ff, in which */
+ /* case those guys should be given a symbol encoding */
+ /* There's a bug in the way otf fonts handle this (but not ttf) and */
+ /* they only seem to list the symbol glyphs */
+ else if ( sf->glyphs[i]->unicodeenc==0x21d4 )
+ CodePage[0] |= 1U<<31; /* symbol */
+#else
+ /* This doesn't work well either. In ttf fonts the bit is ignored */
+ /* in otf fonts the bit means "ignore all other bits" */
+ else if ( sf->glyphs[i]->unicodeenc>=0xf000 && sf->glyphs[i]->unicodeenc<=0xf0ff )
+ CodePage[0] |= 1U<<31; /* symbol */
+#endif
+ else if ( sf->glyphs[i]->unicodeenc==0xc3 && has_ascii )
+ CodePage[1] |= 1<<18; /* MS-DOS Nordic */
+ else if ( sf->glyphs[i]->unicodeenc==0xe9 && has_ascii )
+ CodePage[1] |= 1<<20; /* MS-DOS Canadian French */
+ else if ( sf->glyphs[i]->unicodeenc==0xf5 && has_ascii )
+ CodePage[1] |= 1<<23; /* MS-DOS Portuguese */
+ else if ( sf->glyphs[i]->unicodeenc==0xfe && has_ascii )
+ CodePage[1] |= 1<<22; /* MS-DOS Icelandic */
+ }
+}
+
+static void WinBB(SplineFont *sf,uint16 *winascent,uint16 *windescent,struct alltabs *at) {
+ /* The windows ascent/descent is calculated on the ymin/max of the */
+ /* glyphs in the so called ANSI character set. I'm going to pretend */
+ /* that's Latin1 with a few additions */
+ /* Well, that's what is documented, but the documentation says contradictory */
+ /* things. I believe that winAscent should be the same as hhea.ascent */
+
+ *winascent = at->head.ymax;
+ *windescent = -at->head.ymin; /* Should be positive */
+ if ( sf->cidmaster!=NULL )
+ sf = sf->cidmaster;
+
+ if ( sf->pfminfo.winascent_add )
+ *winascent += sf->pfminfo.os2_winascent;
+ else
+ *winascent = sf->pfminfo.os2_winascent;
+ if ( sf->pfminfo.windescent_add )
+ *windescent += sf->pfminfo.os2_windescent;
+ else
+ *windescent = sf->pfminfo.os2_windescent;
+}
+
+static void setos2(struct os2 *os2,struct alltabs *at, SplineFont *sf,
+ enum fontformat format) {
+ int i,j,cnt1,cnt2,first,last,avg1,avg2,gid;
+ char *pt;
+ static int const weightFactors[26] = { 64, 14, 27, 35, 100, 20, 14, 42, 63,
+ 3, 6, 35, 20, 56, 56, 17, 4, 49, 56, 71, 31, 10, 18, 3, 18, 2 };
+ EncMap *map;
+
+ os2->version = 1;
+ if ( format==ff_otf || format==ff_otfcid )
+ os2->version = 3;
+ if ( sf->os2_version!=0 )
+ os2->version = sf->os2_version;
+
+ os2->weightClass = sf->pfminfo.weight;
+ os2->widthClass = sf->pfminfo.width;
+ os2->fstype = 0x8;
+ if ( sf->pfminfo.fstype!=-1 )
+ os2->fstype = sf->pfminfo.fstype;
+ if ( !sf->pfminfo.subsuper_set )
+ SFDefaultOS2SubSuper(&sf->pfminfo,sf->ascent+sf->descent,sf->italicangle);
+ os2->ysupYSize = sf->pfminfo.os2_supysize;
+ os2->ysubXSize = sf->pfminfo.os2_subxsize;
+ os2->ysubYSize = sf->pfminfo.os2_subysize;
+ os2->ysupXSize = sf->pfminfo.os2_supxsize;
+ os2->ysubYOff = sf->pfminfo.os2_subyoff;
+ os2->ysubXOff = sf->pfminfo.os2_subxoff;
+ os2->ysupXOff = sf->pfminfo.os2_supxoff;
+ os2->ysupYOff = sf->pfminfo.os2_supyoff;
+ os2->yStrikeoutSize = sf->pfminfo.os2_strikeysize;
+ os2->yStrikeoutPos = sf->pfminfo.os2_strikeypos;
+ os2->fsSel = (at->head.macstyle&1?32:0)|(at->head.macstyle&2?1:0);
+ if ( sf->fullname!=NULL && strstrmatch(sf->fullname,"outline")!=NULL )
+ os2->fsSel |= 8;
+ if ( os2->fsSel==0 && sf->pfminfo.weight==400 )
+ os2->fsSel = 64; /* Regular */
+ if ( os2->version>=4 ) {
+ if ( strstrmatch(sf->fontname,"Obli")==0 ) {
+ os2->fsSel &= ~1; /* Turn off Italic */
+ os2->fsSel |= 512; /* Turn on Oblique */
+ }
+ if ( sf->use_typo_metrics )
+ os2->fsSel |= 128; /* Don't use win ascent/descent for line spacing */
+ if ( sf->weight_width_slope_only )
+ os2->fsSel |= 256;
+ }
+/* David Lemon @Adobe.COM
+1) The sTypoAscender and sTypoDescender values should sum to 2048 in
+a 2048-unit font. They indicate the position of the em square
+relative to the baseline.
+GWW: Almost, sTypoAscender-sTypoDescender == EmSize
+
+2) The usWinAscent and usWinDescent values represent the maximum
+height and depth of specific glyphs within the font, and some
+applications will treat them as the top and bottom of the font
+bounding box. (the "ANSI" glyphs)
+GWW: That's what's documented. But it means non-ANSI glyphs get clipped. So the
+docs are wrong.
+*/
+ if ( sf->pfminfo.typoascent_add )
+ os2->ascender = sf->ascent + sf->pfminfo.os2_typoascent;
+ else
+ os2->ascender = sf->pfminfo.os2_typoascent;
+ if ( sf->pfminfo.typodescent_add )
+ os2->descender = -sf->descent + sf->pfminfo.os2_typodescent; /* Should be neg */
+ else
+ os2->descender = sf->pfminfo.os2_typodescent;
+ WinBB(sf,&os2->winascent,&os2->windescent,at);
+ os2->linegap = sf->pfminfo.os2_typolinegap;
+ os2->sFamilyClass = sf->pfminfo.os2_family_class;
+
+ avg1 = avg2 = last = 0; first = 0xffff;
+ cnt1 = cnt2 = 0;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ if ( SCWorthOutputting(sf->glyphs[i]) &&
+ sf->glyphs[i]->unicodeenc!=-1 ) {
+ if ( sf->glyphs[i]->unicodeenc > 0xffff )
+ os2->unicoderange[57>>5] |= (1<<(57&31));
+ for ( j=0; j<sizeof(uniranges)/sizeof(uniranges[0]); ++j )
+ if ( sf->glyphs[i]->unicodeenc>=uniranges[j][0] &&
+ sf->glyphs[i]->unicodeenc<=uniranges[j][1] ) {
+ int bit = uniranges[j][2];
+ os2->unicoderange[bit>>5] |= (1<<(bit&31));
+ break;
+ }
+ /* Don't include the dummy glyphs (.notdef, .null, etc.) they aren't */
+ /* really encoded. Don't include glyphs out of BMP, OS/2 uses shorts */
+ /* for the first/last char and can't represent them. */
+ /* If no BMP glyphs, then first should be 0xffff. If any outside */
+ /* BMP then last is 0xffff */
+ if ( sf->glyphs[i]->ttf_glyph>2 ) {
+ if ( sf->glyphs[i]->unicodeenc<=0xffff ) {
+ if ( sf->glyphs[i]->unicodeenc<first ) first = sf->glyphs[i]->unicodeenc;
+ if ( sf->glyphs[i]->unicodeenc>last ) last = sf->glyphs[i]->unicodeenc;
+ } else {
+ last = 0xffff;
+ }
+ }
+ if ( sf->glyphs[i]->width!=0 ) {
+ avg2 += sf->glyphs[i]->width; ++cnt2;
+ }
+ if ( sf->glyphs[i]->unicodeenc==' ') {
+ avg1 += sf->glyphs[i]->width * 166; ++cnt1;
+ } else if (sf->glyphs[i]->unicodeenc>='a' && sf->glyphs[i]->unicodeenc<='z') {
+ avg1 += sf->glyphs[i]->width * weightFactors[sf->glyphs[i]->unicodeenc-'a']; ++cnt1;
+ }
+ }
+ }
+ if ( format==ff_ttfsym ) /* MS Symbol font has this set to zero. Does it matter? */
+ memset(os2->unicoderange,0,sizeof(os2->unicoderange));
+
+ if ( sf->pfminfo.pfmset )
+ strncpy(os2->achVendID,sf->pfminfo.os2_vendor,4);
+ else if ( TTFFoundry!=NULL )
+ strncpy(os2->achVendID,TTFFoundry,4);
+ else
+ memcpy(os2->achVendID,"PfEd",4);
+ for ( pt=os2->achVendID; pt<os2->achVendID && *pt!='\0'; ++pt );
+ while ( pt<os2->achVendID ) *pt++ = ' '; /* Pad with spaces not NUL */
+
+ /* v1,2 & v3,4 have different ways of calculating avgCharWid. */
+ /* but I'm told that using the v3 way breaks display of CJK fonts in windows */
+ os2->avgCharWid = 500;
+ os2->v1_avgCharWid = os2->v3_avgCharWid = 0;
+ if ( cnt1==27 )
+ os2->v1_avgCharWid = avg1/1000;
+ if ( cnt2!=0 )
+ os2->v3_avgCharWid = avg2/cnt2;
+ memcpy(os2->panose,sf->pfminfo.panose,sizeof(os2->panose));
+ map = at->map;
+ if ( format==ff_ttfsym ) {
+ os2->ulCodePage[0] = 0x80000000;
+ os2->ulCodePage[1] = 0;
+ first = 255; last = 0;
+ for ( i=0; i<map->enccount && i<255; ++i )
+ if ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
+ sf->glyphs[gid]->ttf_glyph!=-1 ) {
+ if ( i<first ) first = i;
+ if ( i>last ) last = i;
+ }
+ os2->firstcharindex = 0xf000 + first; /* This gets mapped to space */
+ os2->lastcharindex = 0xf000 + last;
+ } else {
+ os2->firstcharindex = first;
+ os2->lastcharindex = last;
+ OS2FigureCodePages(sf, os2->ulCodePage);
+ /* Herbert Duerr: */
+ /* Some old versions of Windows do not provide access to all */
+ /* glyphs in a font if the fonts contains non-PUA symbols */
+ /* and thus only has sets the codepage flag for symbol */
+ /* => a workaround for this problem on Windows legacy versions */
+ /* is to use an OS2-table version without codepage flags */
+ /* GWW: */
+ /* This sounds to me like a windows bug rather than one in ff */
+ /* and this is a work-around for windows. As far as I can tell */
+ /* ff is setting the codepage field properly, it's just that */
+ /* windows doesn't interpret that bit correctly */
+ /* GWW: Things get worse. Windows no longer accepts a version 0 */
+ /* for OS/2. FontLab simply lies and says we have a latin1 */
+ /* code page when we don't. */
+ if( format!=ff_ttfsym )
+ if( (os2->ulCodePage[0]&~(1U<<31))==0 && os2->ulCodePage[1]==0 )
+ os2->ulCodePage[0] |= 1;
+ }
+
+ if ( os2->version>=2 ) {
+ BlueData bd;
+
+ QuickBlues(sf,&bd); /* This handles cid fonts properly */
+ os2->xHeight = (bd.xheight >= 0.0 ? bd.xheight : 0);
+ os2->capHeight = (bd.caph >= 0.0 ? bd.caph : 0);
+ os2->defChar = 0;
+ if ( format==ff_otf || format==ff_otfcid )
+ os2->defChar = ' ';
+ os2->breakChar = ' ';
+ os2->maxContext = 1; /* Kerning will set this to 2, ligature to whatever */
+ }
+
+ if ( os2->version>=3 && os2->v3_avgCharWid!=0 )
+ os2->avgCharWid = os2->v3_avgCharWid;
+ else if ( os2->v1_avgCharWid!=0 )
+ os2->avgCharWid = os2->v1_avgCharWid;
+ else if ( os2->v3_avgCharWid!=0 )
+ os2->avgCharWid = os2->v3_avgCharWid;
+}
+
+static void redoloca(struct alltabs *at) {
+ int i;
+
+ at->loca = tmpfile();
+ if ( at->head.locais32 ) {
+ for ( i=0; i<=at->maxp.numGlyphs; ++i )
+ putlong(at->loca,at->gi.loca[i]);
+ at->localen = sizeof(int32)*(at->maxp.numGlyphs+1);
+ } else {
+ for ( i=0; i<=at->maxp.numGlyphs; ++i )
+ putshort(at->loca,at->gi.loca[i]/2);
+ at->localen = sizeof(int16)*(at->maxp.numGlyphs+1);
+ if ( ftell(at->loca)&2 )
+ putshort(at->loca,0);
+ }
+ if ( at->format!=ff_type42 && at->format!=ff_type42cid ) {
+ free(at->gi.loca);
+ at->gi.loca = NULL;
+ }
+}
+
+static void dummyloca(struct alltabs *at) {
+
+ at->loca = tmpfile();
+ if ( at->head.locais32 ) {
+ putlong(at->loca,0);
+ at->localen = sizeof(int32);
+ } else {
+ putshort(at->loca,0);
+ at->localen = sizeof(int16);
+ putshort(at->loca,0); /* pad it */
+ }
+}
+
+static void redohead(struct alltabs *at) {
+ at->headf = tmpfile();
+
+ putlong(at->headf,at->head.version);
+ putlong(at->headf,at->head.revision);
+ putlong(at->headf,at->head.checksumAdj);
+ putlong(at->headf,at->head.magicNum);
+ putshort(at->headf,at->head.flags);
+ putshort(at->headf,at->head.emunits);
+ putlong(at->headf,at->head.createtime[1]);
+ putlong(at->headf,at->head.createtime[0]);
+ putlong(at->headf,at->head.modtime[1]);
+ putlong(at->headf,at->head.modtime[0]);
+ putshort(at->headf,at->head.xmin);
+ putshort(at->headf,at->head.ymin);
+ putshort(at->headf,at->head.xmax);
+ putshort(at->headf,at->head.ymax);
+ putshort(at->headf,at->head.macstyle);
+ putshort(at->headf,at->head.lowestreadable);
+ putshort(at->headf,at->head.dirhint);
+ putshort(at->headf,at->head.locais32);
+ putshort(at->headf,at->head.glyphformat);
+
+ at->headlen = ftell(at->headf);
+ if ( (at->headlen&2)!=0 )
+ putshort(at->headf,0);
+}
+
+static void redohhead(struct alltabs *at,int isv) {
+ int i;
+ struct hhead *head;
+ FILE *f;
+
+ if ( !isv ) {
+ f = at->hheadf = tmpfile();
+ head = &at->hhead;
+ } else {
+ f = at->vheadf = tmpfile();
+ head = &at->vhead;
+ }
+
+ putlong(f,head->version);
+ putshort(f,head->ascender);
+ putshort(f,head->descender);
+ putshort(f,head->linegap);
+ putshort(f,head->maxwidth);
+ putshort(f,head->minlsb);
+ putshort(f,head->minrsb);
+ putshort(f,head->maxextent);
+ putshort(f,head->caretSlopeRise);
+ putshort(f,head->caretSlopeRun);
+ for ( i=0; i<5; ++i )
+ putshort(f,head->mbz[i]);
+ putshort(f,head->metricformat);
+ putshort(f,head->numMetrics);
+
+ if ( !isv ) {
+ at->hheadlen = ftell(f);
+ if ( (at->hheadlen&2)!=0 )
+ putshort(f,0);
+ } else {
+ at->vheadlen = ftell(f);
+ if ( (at->vheadlen&2)!=0 )
+ putshort(f,0);
+ }
+}
+
+static void redovorg(struct alltabs *at) {
+
+ at->vorgf = tmpfile();
+ putshort(at->vorgf,at->vorg.majorVersion);
+ putshort(at->vorgf,at->vorg.minorVersion);
+ putshort(at->vorgf,at->vorg.defaultVertOriginY);
+ putshort(at->vorgf,at->vorg.numVertOriginYMetrics);
+
+ at->vorglen = ftell(at->vorgf);
+ if ( (at->vorglen&2)!=0 )
+ putshort(at->vorgf,0);
+}
+
+static void redomaxp(struct alltabs *at,enum fontformat format) {
+ at->maxpf = tmpfile();
+
+ putlong(at->maxpf,at->maxp.version);
+ putshort(at->maxpf,at->maxp.numGlyphs);
+ if ( format!=ff_otf && format!=ff_otfcid ) {
+ putshort(at->maxpf,at->maxp.maxPoints);
+ putshort(at->maxpf,at->maxp.maxContours);
+ putshort(at->maxpf,at->maxp.maxCompositPts);
+ putshort(at->maxpf,at->maxp.maxCompositCtrs);
+ putshort(at->maxpf,at->maxp.maxZones);
+ putshort(at->maxpf,at->maxp.maxTwilightPts);
+ putshort(at->maxpf,at->maxp.maxStorage);
+ putshort(at->maxpf,at->maxp.maxFDEFs);
+ putshort(at->maxpf,at->maxp.maxIDEFs);
+ putshort(at->maxpf,at->maxp.maxStack);
+ putshort(at->maxpf,at->maxp.maxglyphInstr);
+ putshort(at->maxpf,at->maxp.maxnumcomponents);
+ putshort(at->maxpf,at->maxp.maxcomponentdepth);
+ }
+
+ at->maxplen = ftell(at->maxpf);
+ if ( (at->maxplen&2)!=0 )
+ putshort(at->maxpf,0);
+}
+
+static void redoos2(struct alltabs *at) {
+ int i;
+ at->os2f = tmpfile();
+
+ putshort(at->os2f,at->os2.version);
+ putshort(at->os2f,at->os2.avgCharWid);
+ putshort(at->os2f,at->os2.weightClass);
+ putshort(at->os2f,at->os2.widthClass);
+ putshort(at->os2f,at->os2.fstype);
+ putshort(at->os2f,at->os2.ysubXSize);
+ putshort(at->os2f,at->os2.ysubYSize);
+ putshort(at->os2f,at->os2.ysubXOff);
+ putshort(at->os2f,at->os2.ysubYOff);
+ putshort(at->os2f,at->os2.ysupXSize);
+ putshort(at->os2f,at->os2.ysupYSize);
+ putshort(at->os2f,at->os2.ysupXOff);
+ putshort(at->os2f,at->os2.ysupYOff);
+ putshort(at->os2f,at->os2.yStrikeoutSize);
+ putshort(at->os2f,at->os2.yStrikeoutPos);
+ putshort(at->os2f,at->os2.sFamilyClass);
+ for ( i=0; i<10; ++i )
+ putc(at->os2.panose[i],at->os2f);
+ for ( i=0; i<4; ++i )
+ putlong(at->os2f,at->os2.unicoderange[i]);
+ for ( i=0; i<4; ++i )
+ putc(at->os2.achVendID[i],at->os2f);
+ putshort(at->os2f,at->os2.fsSel);
+ putshort(at->os2f,at->os2.firstcharindex);
+ putshort(at->os2f,at->os2.lastcharindex);
+ putshort(at->os2f,at->os2.ascender);
+ putshort(at->os2f,at->os2.descender);
+ putshort(at->os2f,at->os2.linegap);
+ putshort(at->os2f,at->os2.winascent);
+ putshort(at->os2f,at->os2.windescent);
+ if ( at->os2.version>=1 ) {
+ putlong(at->os2f,at->os2.ulCodePage[0]);
+ putlong(at->os2f,at->os2.ulCodePage[1]);
+ }
+
+ if ( at->os2.version>=2 ) {
+ putshort(at->os2f,at->os2.xHeight);
+ putshort(at->os2f,at->os2.capHeight);
+ putshort(at->os2f,at->os2.defChar);
+ putshort(at->os2f,at->os2.breakChar);
+ putshort(at->os2f,at->os2.maxContext);
+ }
+
+ at->os2len = ftell(at->os2f);
+ if ( (at->os2len&2)!=0 )
+ putshort(at->os2f,0);
+}
+
+#if 0
+static int icomp(const void *a, const void *b) {
+ return *(int *)a - *(int *)b;
+}
+#endif
+
+static void dumpgasp(struct alltabs *at, SplineFont *sf) {
+ int i;
+
+ at->gaspf = tmpfile();
+ if ( sf->gasp_cnt==0 ) {
+ putshort(at->gaspf,0); /* Old version number */
+ /* For fonts with no instructions always dump a gasp table which */
+ /* asks for grey and no grid fit */
+ putshort(at->gaspf,1);
+ putshort(at->gaspf,0xffff); /* Upper bound on pixels/em for this range */
+ putshort(at->gaspf,0x2); /* Grey scale, no gridfitting */
+ /* No hints, so no grids to fit */
+ } else {
+ putshort(at->gaspf,sf->gasp_version); /* New version number, with clear type info */
+ putshort(at->gaspf,sf->gasp_cnt);
+ for ( i=0; i<sf->gasp_cnt; ++i ) {
+ putshort(at->gaspf,sf->gasp[i].ppem);
+ putshort(at->gaspf,sf->gasp[i].flags);
+ }
+ }
+ at->gasplen = ftell(at->gaspf);
+ /* This table is always 32 bit aligned */
+}
+
+#if 0
+static void dumpmacstr(FILE *file,unichar_t *str) {
+ int ch;
+ unsigned char *table;
+
+ do {
+ ch = *str++;
+ if ( ch==0 )
+ putc('\0',file);
+ else if ( (ch>>8)>=mac_from_unicode.first && (ch>>8)<=mac_from_unicode.last &&
+ (table = mac_from_unicode.table[(ch>>8)-mac_from_unicode.first])!=NULL &&
+ table[ch&0xff]!=0 )
+ putc(table[ch&0xff],file);
+ else
+ putc('?',file); /* if we were to omit an unencoded char all our position calculations would be off */
+ } while ( ch!='\0' );
+}
+#endif
+
+static void dumpstr(FILE *file,char *str) {
+ do {
+ putc(*str,file);
+ } while ( *str++!='\0' );
+}
+
+#if 0
+static void dumpc2ustr(FILE *file,char *str) {
+ do {
+ putc('\0',file);
+ putc(*str,file);
+ } while ( *str++!='\0' );
+}
+#endif
+
+static void dumpustr(FILE *file,char *utf8_str) {
+ unichar_t *ustr = utf82u_copy(utf8_str), *pt=ustr;
+ do {
+ putc(*pt>>8,file);
+ putc(*pt&0xff,file);
+ } while ( *pt++!='\0' );
+ free(ustr);
+}
+
+static void dumppstr(FILE *file,char *str) {
+ putc(strlen(str),file);
+ fwrite(str,sizeof(char),strlen(str),file);
+}
+
+char *utf8_verify_copy(const char *str) {
+ /* When given a postscript string it SHOULD be in ASCII. But it will often*/
+ /* contain a copyright symbol (sometimes in latin1, sometimes in macroman)*/
+ /* unfortunately both encodings use 0xa9 for copyright so we can't distinguish */
+ /* guess that it's latin1 (or that copyright is the only odd char which */
+ /* means a latin1 conversion will work for macs too). */
+
+ if ( str==NULL )
+return( NULL );
+
+ if ( utf8_valid(str))
+return( copy(str)); /* Either in ASCII (good) or appears to be utf8*/
+return( latin1_2_utf8_copy(str));
+}
+
+/* Oh. If the encoding is symbol (platform=3, specific=0) then Windows won't */
+/* accept the font unless the name table also has entries for (3,0). I'm not */
+/* sure if this is the case for the CJK encodings (docs don't mention that) */
+/* but let's do it just in case */
+void DefaultTTFEnglishNames(struct ttflangname *dummy, SplineFont *sf) {
+ time_t now;
+ struct tm *tm;
+ char buffer[200];
+
+ if ( dummy->names[ttf_copyright]==NULL || *dummy->names[ttf_copyright]=='\0' )
+ dummy->names[ttf_copyright] = utf8_verify_copy(sf->copyright);
+ if ( dummy->names[ttf_family]==NULL || *dummy->names[ttf_family]=='\0' )
+ dummy->names[ttf_family] = utf8_verify_copy(sf->familyname);
+ if ( dummy->names[ttf_subfamily]==NULL || *dummy->names[ttf_subfamily]=='\0' )
+ dummy->names[ttf_subfamily] = utf8_verify_copy(SFGetModifiers(sf));
+ if ( dummy->names[ttf_uniqueid]==NULL || *dummy->names[ttf_uniqueid]=='\0' ) {
+ time(&now);
+ tm = localtime(&now);
+ sprintf( buffer, "%s : %s : %d-%d-%d",
+ BDFFoundry?BDFFoundry:TTFFoundry?TTFFoundry:"FontForge 2.0",
+ sf->fullname!=NULL?sf->fullname:sf->fontname,
+ tm->tm_mday, tm->tm_mon+1, tm->tm_year+1900 );
+ dummy->names[ttf_uniqueid] = copy(buffer);
+ }
+ if ( dummy->names[ttf_fullname]==NULL || *dummy->names[ttf_fullname]=='\0' )
+ dummy->names[ttf_fullname] = utf8_verify_copy(sf->fullname);
+ if ( dummy->names[ttf_version]==NULL || *dummy->names[ttf_version]=='\0' ) {
+ if ( sf->subfontcnt!=0 )
+ sprintf( buffer, "Version %f ", sf->cidversion );
+ else if ( sf->version!=NULL )
+ sprintf(buffer,"Version %.20s ", sf->version);
+ else
+ strcpy(buffer,"Version 1.0" );
+ dummy->names[ttf_version] = copy(buffer);
+ }
+ if ( dummy->names[ttf_postscriptname]==NULL || *dummy->names[ttf_postscriptname]=='\0' )
+ dummy->names[ttf_postscriptname] = utf8_verify_copy(sf->fontname);
+}
+
+typedef struct {
+ uint16 platform;
+ uint16 specific;
+ uint16 lang;
+ uint16 strid;
+ uint16 len;
+ uint16 offset;
+} NameEntry;
+
+typedef struct {
+ FILE *strings;
+ int cur, max;
+ enum fontformat format;
+ Encoding *encoding_name;
+ NameEntry *entries;
+ int applemode;
+} NamTab;
+
+static int compare_entry(const void *_mn1, const void *_mn2) {
+ const NameEntry *mn1 = _mn1, *mn2 = _mn2;
+
+ if ( mn1->platform!=mn2->platform )
+return( mn1->platform - mn2->platform );
+ if ( mn1->specific!=mn2->specific )
+return( mn1->specific - mn2->specific );
+ if ( mn1->lang!=mn2->lang )
+return( mn1->lang - mn2->lang );
+
+return( mn1->strid-mn2->strid );
+}
+
+static void AddEncodedName(NamTab *nt,char *utf8name,uint16 lang,uint16 strid) {
+ NameEntry *ne;
+ int maclang, macenc= -1, specific;
+ char *macname = NULL;
+
+ if ( strid==ttf_postscriptname && lang!=0x409 )
+return; /* Should not happen, but it did */
+
+ if ( nt->cur+6>=nt->max ) {
+ if ( nt->cur==0 )
+ nt->entries = galloc((nt->max=100)*sizeof(NameEntry));
+ else
+ nt->entries = grealloc(nt->entries,(nt->max+=100)*sizeof(NameEntry));
+ }
+
+ ne = nt->entries + nt->cur;
+
+ ne->platform = 3; /* Windows */
+ ne->specific = 1; /* unicode */
+ ne->lang = lang;
+ ne->strid = strid;
+ ne->offset = ftell(nt->strings);
+ ne->len = 2*utf82u_strlen(utf8name);
+ dumpustr(nt->strings,utf8name);
+ ++ne;
+
+ if ( nt->format==ff_ttfsym ) {
+ *ne = ne[-1];
+ ne->specific = 0; /* Windows "symbol" */
+ ++ne;
+ }
+
+ maclang = WinLangToMac(lang);
+ if ( !nt->applemode && lang!=0x409 )
+ maclang = 0xffff;
+ if ( maclang!=0xffff ) {
+#ifdef FONTFORGE_CONFIG_APPLE_UNICODE_NAMES
+ if ( strid!=ttf_postscriptname ) {
+ *ne = ne[-1];
+ ne->platform = 0; /* Mac unicode */
+ ne->specific = 0; /* 3 => Unicode 2.0 semantics */ /* 0 ("default") is also a reasonable value */
+ ne->lang = maclang;
+ ++ne;
+ }
+#endif
+
+ macenc = MacEncFromMacLang(maclang);
+ macname = Utf8ToMacStr(utf8name,macenc,maclang);
+ if ( macname!=NULL ) {
+ ne->platform = 1; /* apple non-unicode encoding */
+ ne->specific = macenc; /* whatever */
+ ne->lang = maclang;
+ ne->strid = strid;
+ ne->offset = ftell(nt->strings);
+ ne->len = strlen(macname);
+ dumpstr(nt->strings,macname);
+ ++ne;
+ free(macname);
+ }
+ }
+
+ specific = nt->encoding_name->is_korean ? 5 : /* Wansung, korean */
+ nt->encoding_name->is_japanese ? 2 : /* SJIS */
+ nt->encoding_name->is_simplechinese ? 3 :/* packed gb2312, don't know the real name */
+ strmatch(nt->encoding_name->enc_name,"EUC-GB12345")==0 ? 3 :/* Lie */
+ nt->encoding_name->is_tradchinese ? 4 : /* Big5, traditional Chinese */
+ -1;
+ if ( specific != -1 ) {
+ ne->platform = 3; /* windows */
+ ne->specific = specific; /* whatever */
+ ne->lang = lang;
+ ne->strid = strid;
+ if ( macname!=NULL &&
+ (( specific== 2 && macenc==1 ) || /* Japanese */
+ ( specific== 3 && macenc==25 ) || /* simplified chinese */
+ ( specific== 4 && macenc==2 ) || /* traditional chinese */
+ ( specific== 5 && macenc==3 )) ) { /* wansung korean */
+ ne->offset = ne[-1].offset;
+ ne->len = ne[-1].len;
+ } else {
+ char *space, *encname, *out;
+ ICONV_CONST char *in;
+ Encoding *enc;
+ size_t inlen, outlen;
+ ne->offset = ftell(nt->strings);
+ encname = nt->encoding_name->is_japanese ? "SJIS" :
+ strmatch(nt->encoding_name->enc_name,"JOHAB")==0 ? "JOHAB" :
+ nt->encoding_name->is_korean ? "EUC-KR" :
+ nt->encoding_name->is_simplechinese ? "EUC-CN" :
+ nt->encoding_name->enc_name;
+ enc = FindOrMakeEncoding(encname);
+ if ( enc==NULL )
+ --ne;
+ else {
+ unichar_t *uin = utf82u_copy(utf8name);
+ outlen = 3*strlen(utf8name)+10;
+ out = space = galloc(outlen+2);
+ in = (char *) uin; inlen = 2*u_strlen(uin);
+ iconv(enc->fromunicode,NULL,NULL,NULL,NULL); /* should not be needed, but just in case */
+ iconv(enc->fromunicode,&in,&inlen,&out,&outlen);
+ out[0] = '\0'; out[1] = '\0';
+ ne->offset = ftell(nt->strings);
+ ne->len = strlen(space);
+ dumpstr(nt->strings,space);
+ free(space); free(uin);
+ }
+ }
+ ++ne;
+ }
+ nt->cur = ne - nt->entries;
+}
+
+static void AddMacName(NamTab *nt,struct macname *mn, int strid) {
+ NameEntry *ne;
+
+ if ( nt->cur+1>=nt->max ) {
+ if ( nt->cur==0 )
+ nt->entries = galloc((nt->max=100)*sizeof(NameEntry));
+ else
+ nt->entries = grealloc(nt->entries,(nt->max+=100)*sizeof(NameEntry));
+ }
+
+ ne = nt->entries + nt->cur;
+
+ ne->platform = 1; /* apple non-unicode encoding */
+ ne->specific = mn->enc; /* whatever */
+ ne->lang = mn->lang;
+ ne->strid = strid;
+ ne->offset = ftell(nt->strings);
+ ne->len = strlen(mn->name);
+ dumpstr(nt->strings,mn->name);
+
+ ++nt->cur;
+}
+
+/* There's an inconsistancy here. Apple's docs say there most be only one */
+/* nameid==6 and that name must be ascii (presumably plat=1, spec=0, lang=0) */
+/* The opentype docs say there must be two (psl=1,0,0 & psl=3,1,0x409) any */
+/* others are to be ignored */
+/* A representative from Apple says they will change their spec to accept */
+/* the opentype version, and tells me that they don't currently care */
+/* So ignore this */
+/* Undocumented fact: Windows insists on having a UniqueID string 3,1 */
+static void dumpnames(struct alltabs *at, SplineFont *sf,enum fontformat format) {
+ int i,j;
+ struct ttflangname dummy, *cur, *useng = NULL;
+ struct macname *mn;
+ struct other_names *on, *onn;
+ NamTab nt;
+ struct otfname *otfn;
+
+ memset(&nt,0,sizeof(nt));
+ nt.encoding_name = at->map->enc;
+ nt.format = format;
+ nt.applemode = at->applemode;
+ nt.strings = tmpfile();
+
+ memset(&dummy,0,sizeof(dummy));
+ for ( cur=sf->names; cur!=NULL; cur=cur->next ) {
+ if ( cur->lang==0x409 ) {
+ dummy = *cur;
+ useng = cur;
+ break;
+ }
+ }
+ DefaultTTFEnglishNames(&dummy, sf);
+
+ for ( i=0; i<ttf_namemax; ++i ) if ( dummy.names[i]!=NULL )
+ AddEncodedName(&nt,dummy.names[i],0x409,i);
+ for ( cur=sf->names; cur!=NULL; cur=cur->next ) {
+ if ( cur->lang!=0x409 )
+ for ( i=0; i<ttf_namemax; ++i )
+ if ( cur->names[i]!=NULL )
+ AddEncodedName(&nt,cur->names[i],cur->lang,i);
+ }
+
+ /* The examples I've seen of the feature table only contain platform==mac */
+ /* so I'm not including apple unicode */
+ if ( at->feat_name!=NULL ) {
+ for ( i=0; at->feat_name[i].strid!=0; ++i ) {
+ for ( mn=at->feat_name[i].mn; mn!=NULL; mn=mn->next )
+ AddMacName(&nt,mn,at->feat_name[i].strid);
+#if 0 /* I'm not sure why I keep track of these alternates */
+ /* Dumping them out like this is a bad idea. It might be worth */
+ /* something if we searched through the alternate sets for languages */
+ /* not found in the main set, but at the moment I don't think so */
+ /* What happens now is that I get duplicate names output */
+ for ( mn=at->feat_name[i].smn; mn!=NULL; mn=mn->next )
+ AddMacName(&nt,mn,at->feat_name[i].strid);
+#endif
+ }
+ }
+ /* And the names used by the fvar table aren't mac unicode either */
+ for ( on = at->other_names; on!=NULL; on=onn ) {
+ for ( mn = on->mn; mn!=NULL ; mn = mn->next )
+ AddMacName(&nt,mn,on->strid);
+ onn = on->next;
+ chunkfree(on,sizeof(*on));
+ }
+ /* Wow, the GPOS 'size' feature uses the name table in a very mac-like way*/
+ if ( at->fontstyle_name_strid!=0 && sf->fontstyle_name!=NULL ) {
+ for ( otfn = sf->fontstyle_name; otfn!=NULL; otfn = otfn->next )
+ AddEncodedName(&nt,otfn->name,otfn->lang,at->fontstyle_name_strid);
+ }
+
+ qsort(nt.entries,nt.cur,sizeof(NameEntry),compare_entry);
+
+ at->name = tmpfile();
+ putshort(at->name,0); /* format */
+ putshort(at->name,nt.cur); /* numrec */
+ putshort(at->name,(3+nt.cur*6)*sizeof(int16)); /* offset to strings */
+
+ for ( i=0; i<nt.cur; ++i ) {
+ putshort(at->name,nt.entries[i].platform);
+ putshort(at->name,nt.entries[i].specific);
+ putshort(at->name,nt.entries[i].lang);
+ putshort(at->name,nt.entries[i].strid);
+ putshort(at->name,nt.entries[i].len);
+ putshort(at->name,nt.entries[i].offset);
+ }
+ if ( !ttfcopyfile(at->name,nt.strings,(3+nt.cur*6)*sizeof(int16),"name-data"))
+ at->error = true;
+
+ at->namelen = ftell(at->name);
+ if ( (at->namelen&3)!=0 )
+ for ( j= 4-(at->namelen&3); j>0; --j )
+ putc('\0',at->name);
+
+ for ( i=0; i<ttf_namemax; ++i )
+ if ( useng==NULL || dummy.names[i]!=useng->names[i] )
+ free( dummy.names[i]);
+ free( nt.entries );
+ free( at->feat_name );
+}
+
+static void dumppost(struct alltabs *at, SplineFont *sf, enum fontformat format) {
+ int pos, i,j, shouldbe;
+ int shorttable = (format==ff_otf || format==ff_otfcid ||
+ (at->gi.flags&ttf_flag_shortps));
+ uint32 here;
+
+ at->post = tmpfile();
+
+ putlong(at->post,shorttable?0x00030000:0x00020000); /* formattype */
+ putfixed(at->post,sf->italicangle);
+ putshort(at->post,sf->upos);
+ putshort(at->post,sf->uwidth);
+ putlong(at->post,at->isfixed);
+ putlong(at->post,0); /* no idea about memory */
+ putlong(at->post,0); /* no idea about memory */
+ putlong(at->post,0); /* no idea about memory */
+ putlong(at->post,0); /* no idea about memory */
+ if ( !shorttable ) {
+ here = ftell(at->post);
+ putshort(at->post,at->maxp.numGlyphs);
+
+ shouldbe = 0;
+ for ( i=0, pos=0; i<at->gi.gcnt; ++i ) {
+ if ( at->gi.bygid[i]!=-1 && sf->glyphs[at->gi.bygid[i]]!=NULL ) {
+ SplineChar *sc = sf->glyphs[at->gi.bygid[i]];
+ while ( i>shouldbe ) {
+ if ( shouldbe==0 )
+ putshort(at->post,0); /* glyph 0 is named .notdef */
+ else if ( shouldbe==1 )
+ putshort(at->post,1); /* glyphs 1&2 are .null and cr */
+ else if ( shouldbe==2 )
+ putshort(at->post,2); /* or something */
+ else
+ putshort(at->post,0);
+ ++shouldbe;
+ }
+ if ( strcmp(sc->name,".notdef")==0 )
+ putshort(at->post,0);
+ else {
+ for ( j=0; j<258; ++j )
+ if ( strcmp(sc->name,ttfstandardnames[j])==0 )
+ break;
+ if ( j!=258 )
+ putshort(at->post,j);
+ else {
+ putshort(at->post,pos+258);
+ ++pos;
+ }
+ }
+ ++shouldbe;
+ }
+ }
+
+ if ( shouldbe!=at->maxp.numGlyphs ) {
+ fseek(at->post,here,SEEK_SET);
+ putshort(at->post,shouldbe);
+ fseek(at->post,0,SEEK_END);
+ }
+ if ( pos!=0 ) {
+ for ( i=0; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
+ SplineChar *sc = sf->glyphs[at->gi.bygid[i]];
+ if ( strcmp(sc->name,".notdef")==0 )
+ /* Do Nothing */;
+ else {
+ for ( j=0; j<258; ++j )
+ if ( strcmp(sc->name,ttfstandardnames[j])==0 )
+ break;
+ if ( j!=258 )
+ /* Do Nothing */;
+ else
+ dumppstr(at->post,sc->name);
+ }
+ }
+ }
+ }
+ at->postlen = ftell(at->post);
+ if ( (at->postlen&3)!=0 )
+ for ( j= 4-(at->postlen&3); j>0; --j )
+ putc('\0',at->post);
+}
+
+static FILE *_Gen816Enc(SplineFont *sf,int *tlen,EncMap *map) {
+ int i, j, complained, pos, k, subheadindex, jj, isbig5=false;
+ uint16 table[256];
+ struct subhead subheads[128];
+ uint16 *glyphs;
+ uint16 tempglyphs[256];
+ int base, lbase, basebound, subheadcnt, planesize, plane0size;
+ int base2, base2bound;
+ FILE *sub;
+ char *encname = map->enc->iconv_name!=NULL ? map->enc->iconv_name : map->enc->enc_name;
+
+ *tlen = 0;
+
+ base2 = -1; base2bound = -2;
+ if ( map->enc->is_tradchinese && strstrmatch(encname,"hkscs")!=NULL ) {
+ base = 0x81;
+ basebound = 0xfe;
+ subheadcnt = basebound-base+1;
+ lbase = 0x40;
+ planesize = 191;
+ } else if ( map->enc->is_tradchinese || sf->uni_interp==ui_trad_chinese) {
+ base = 0xa1;
+ basebound = 0xf9; /* wcl-02.ttf's cmap claims to go up to fc, but everything after f9 is invalid (according to what I know of big5, f9 should be the end) */
+ subheadcnt = basebound-base+1;
+ lbase = 0x40;
+ planesize = 191;
+ isbig5 = true;
+ } else if ( strstrmatch(encname,"euc")!=NULL ) {
+ base = 0xa1;
+ basebound = 0xfd;
+ lbase = 0xa1;
+ subheadcnt = basebound-base+1;
+ planesize = 0xfe - lbase +1;
+ } else if ( strstrmatch(encname,"johab")!=NULL ) {
+ base = 0x84;
+ basebound = 0xf9;
+ lbase = 0x31;
+ subheadcnt = basebound-base+1;
+ planesize = 0xfe -0x31+1; /* Stupid gcc bug, thinks 0xfe- is ambiguous (exponant) */
+ } else if ( strstrmatch(encname,"sjis")!=NULL || strstrmatch(encname,"cp932")!=NULL ) {
+ base = 129;
+ basebound = 159;
+ lbase = 64;
+ planesize = 252 - lbase +1;
+ base2 = 0xe0;
+ /* SJIS supports "user defined characters" between 0xf040 and 0xfcfc */
+ /* there probably won't be any, but allow space for them if there are*/
+ for ( base2bound=0xfc00; base2bound>0xefff; --base2bound )
+ if ( base2bound<map->enccount && map->map[base2bound]!=-1 &&
+ SCWorthOutputting(sf->glyphs[map->map[base2bound]]))
+ break;
+ base2bound >>= 8;
+ subheadcnt = basebound-base + 1 + base2bound-base2 + 1;
+ } else {
+ IError( "Unsupported 8/16 encoding %s\n", map->enc->enc_name );
+return( NULL );
+ }
+ plane0size = base2==-1? base : base2;
+ i=0;
+ if ( base2!=-1 ) {
+ for ( i=basebound; i<base2 && i<map->enccount; ++i )
+ if ( map->map[i]==-1 )
+ continue;
+ else if ( SCWorthOutputting(sf->glyphs[map->map[i]]))
+ break;
+ if ( i==base2 || i==map->enccount )
+ i = 0;
+ }
+ if ( i==0 ) {
+ for ( i=0; i<base && i<map->enccount; ++i )
+ if ( map->map[i]==-1 )
+ continue;
+ else if ( SCWorthOutputting(sf->glyphs[map->map[i]]))
+ break;
+ }
+#if 0
+ if ( i==base || i==sf->glyphcnt )
+return( NULL ); /* Doesn't have the single byte entries */
+ /* Can use the normal 16 bit encoding scheme */
+ /* Always do an 8/16, and we'll do a unicode table too now... */
+#endif
+
+ if ( base2!=-1 ) {
+ for ( i=base; i<=basebound && i<map->enccount; ++i )
+ if ( map->map[i]!=-1 && SCWorthOutputting(sf->glyphs[map->map[i]])) {
+ gwwv_post_error(_("Bad Encoding"),_("There is a single byte character (%d) using one of the slots needed for double byte characters"),i);
+ break;
+ }
+ if ( i==basebound+1 )
+ for ( i=base2; i<256 && i<map->enccount; ++i )
+ if ( map->map[i]!=-1 && SCWorthOutputting(sf->glyphs[map->map[i]])) {
+ gwwv_post_error(_("Bad Encoding"),_("There is a single byte character (%d) using one of the slots needed for double byte characters"),i);
+ break;
+ }
+ } else {
+ for ( i=base; i<=256 && i<map->enccount; ++i )
+ if ( map->map[i]!=-1 && SCWorthOutputting(sf->glyphs[map->map[i]])) {
+ gwwv_post_error(_("Bad Encoding"),_("There is a single byte character (%d) using one of the slots needed for double byte characters"),i);
+ break;
+ }
+ }
+ for ( i=256; i<(base<<8) && i<map->enccount; ++i )
+ if ( map->map[i]!=-1 && SCWorthOutputting(sf->glyphs[map->map[i]])) {
+ gwwv_post_error(_("Bad Encoding"),_("There is a character (%d) which cannot be encoded"),i);
+ break;
+ }
+ if ( i==(base<<8) && base2==-1 )
+ for ( i=((basebound+1)<<8); i<0x10000 && i<map->enccount; ++i )
+ if ( map->map[i]!=-1 && SCWorthOutputting(sf->glyphs[map->map[i]])) {
+ gwwv_post_error(_("Bad Encoding"),_("There is a character (%d) which cannot be encoded"),i);
+ break;
+ }
+
+ memset(table,'\0',sizeof(table));
+ for ( i=base; i<=basebound; ++i )
+ table[i] = 8*(i-base+1);
+ for ( i=base2; i<=base2bound; ++i )
+ table[i] = 8*(i-base2+basebound-base+1+1);
+ memset(subheads,'\0',sizeof(subheads));
+ subheads[0].first = 0; subheads[0].cnt = plane0size;
+ for ( i=1; i<subheadcnt+1; ++i ) {
+ subheads[i].first = lbase;
+ subheads[i].cnt = planesize;
+ }
+ glyphs = gcalloc(subheadcnt*planesize+plane0size,sizeof(uint16));
+ subheads[0].rangeoff = 0;
+ for ( i=0; i<plane0size && i<map->enccount; ++i )
+ if ( map->map[i]!=-1 && sf->glyphs[map->map[i]]!=NULL &&
+ sf->glyphs[map->map[i]]->ttf_glyph!=-1 )
+ glyphs[i] = sf->glyphs[map->map[i]]->ttf_glyph;
+
+ pos = 1;
+
+ complained = false;
+ subheadindex = 1;
+ for ( jj=0; jj<2 || (base2==-1 && jj<1); ++jj )
+ for ( j=((jj==0?base:base2)<<8); j<=((jj==0?basebound:base2bound)<<8); j+= 0x100 ) {
+ for ( i=0; i<lbase; ++i )
+ if ( !complained && map->map[i+j]!=-1 &&
+ SCWorthOutputting(sf->glyphs[map->map[i+j]])) {
+ gwwv_post_error(_("Bad Encoding"),_("There is a character (%d) which is not normally in the encoding"),i+j);
+ complained = true;
+ }
+ if ( isbig5 ) {
+ /* big5 has a gap here. Does johab? */
+ for ( i=0x7f; i<0xa1; ++i )
+ if ( !complained && map->map[i+j]!=-1 &&
+ SCWorthOutputting(sf->glyphs[map->map[i+j]])) {
+ gwwv_post_error(_("Bad Encoding"),_("There is a character (%d) which is not normally in the encoding"),i+j);
+ complained = true;
+ }
+ }
+ memset(tempglyphs,0,sizeof(tempglyphs));
+ for ( i=0; i<planesize; ++i )
+ if ( map->map[j+lbase+i]!=-1 && sf->glyphs[map->map[j+lbase+i]]!=NULL &&
+ sf->glyphs[map->map[j+lbase+i]]->ttf_glyph!=-1 )
+ tempglyphs[i] = sf->glyphs[map->map[j+lbase+i]]->ttf_glyph;
+ for ( i=1; i<pos; ++i ) {
+ int delta = 0;
+ for ( k=0; k<planesize; ++k )
+ if ( tempglyphs[k]==0 && glyphs[plane0size+(i-1)*planesize+k]==0 )
+ /* Still matches */;
+ else if ( tempglyphs[k]==0 || glyphs[plane0size+(i-1)*planesize+k]==0 )
+ break; /* Doesn't match */
+ else if ( delta==0 )
+ delta = (uint16) (tempglyphs[k]-glyphs[plane0size+(i-1)*planesize+k]);
+ else if ( tempglyphs[k]==(uint16) (glyphs[plane0size+(i-1)*planesize+k]+delta) )
+ /* Still matches */;
+ else
+ break;
+ if ( k==planesize ) {
+ subheads[subheadindex].delta = delta;
+ subheads[subheadindex].rangeoff = plane0size+(i-1)*planesize;
+ break;
+ }
+ }
+ if ( subheads[subheadindex].rangeoff==0 ) {
+ memcpy(glyphs+(pos-1)*planesize+plane0size,tempglyphs,planesize*sizeof(uint16));
+ subheads[subheadindex].rangeoff = plane0size+(pos++-1)*planesize ;
+ }
+ ++subheadindex;
+ }
+
+ /* fixup offsets */
+ /* my rangeoffsets are indexes into the glyph array. That's nice and */
+ /* simple. Unfortunately ttf says they are offsets from the current */
+ /* location in the file (sort of) so we now fix them up. */
+ for ( i=0; i<subheadcnt+1; ++i )
+ subheads[i].rangeoff = subheads[i].rangeoff*sizeof(uint16) +
+ (subheadcnt-i)*sizeof(struct subhead) + sizeof(uint16);
+
+ sub = tmpfile();
+ if ( sub==NULL )
+return( NULL );
+
+ putshort(sub,2); /* 8/16 format */
+ putshort(sub,0); /* Subtable length, we'll come back and fix this */
+ putshort(sub,0); /* version/language, not meaningful in ms systems */
+ for ( i=0; i<256; ++i )
+ putshort(sub,table[i]);
+ for ( i=0; i<subheadcnt+1; ++i ) {
+ putshort(sub,subheads[i].first);
+ putshort(sub,subheads[i].cnt);
+ putshort(sub,subheads[i].delta);
+ putshort(sub,subheads[i].rangeoff);
+ }
+ for ( i=0; i<(pos-1)*planesize+plane0size; ++i )
+ putshort(sub,glyphs[i]);
+ free(glyphs);
+
+ *tlen = ftell(sub);
+ fseek(sub,2,SEEK_SET);
+ putshort(sub,*tlen); /* Length, I said we'd come back to it */
+ rewind( sub );
+return( sub );
+}
+
+static FILE *Needs816Enc(SplineFont *sf,int *tlen,EncMap *map, FILE **apple, int *appletlen) {
+ FILE *sub;
+ char *encname = map->enc->iconv_name!=NULL ? map->enc->iconv_name : map->enc->enc_name;
+ EncMap *oldmap = map;
+ EncMap *applemap = NULL;
+ Encoding *enc;
+
+ *tlen = 0;
+ if ( apple!=NULL ) {
+ *apple = NULL;
+ *appletlen = 0;
+ }
+ if ( sf->cidmaster!=NULL || sf->subfontcnt!=0 )
+return( NULL );
+ if ( (strstrmatch(encname,"big")!=NULL && strchr(encname,'5')!=NULL) ||
+ strstrmatch(encname,"johab")!=NULL ||
+ strstrmatch(encname,"sjis")!=NULL ||
+ strstrmatch(encname,"cp932")!=NULL ||
+ strstrmatch(encname,"euc-kr")!=NULL ||
+ strstrmatch(encname,"euc-cn")!=NULL )
+ /* Already properly encoded */;
+ else if ( strstrmatch(encname,"2022")!=NULL &&
+ (strstrmatch(encname,"JP2")!=NULL ||
+ strstrmatch(encname,"JP-2")!=NULL ||
+ strstrmatch(encname,"JP-3")!=NULL ))
+return( NULL ); /* No 8/16 encoding for JP2 nor JP3 */
+ else if ( sf->uni_interp>=ui_japanese && sf->uni_interp<=ui_korean ) {
+ enc = FindOrMakeEncoding(
+ sf->uni_interp==ui_japanese ? "sjis" :
+ sf->uni_interp==ui_trad_chinese ? "big5" :
+ sf->uni_interp==ui_simp_chinese ? "euc-cn" :
+ "euc-kr");
+ if ( map->enc!=enc ) {
+ map = EncMapFromEncoding(sf,enc);
+ encname = map->enc->iconv_name!=NULL ? map->enc->iconv_name : map->enc->enc_name;
+ }
+ } else
+return( NULL );
+
+ /* Both MS and Apple extend sjis. I don't know how to get iconv to give me*/
+ /* apple's encoding though. So I generate one 8/16 table for MS based on */
+ /* their extension (cp932), and another table based on plain sjis for Apple*/
+ /* Don't know if this is true of other cjk encodings... for the moment I */
+ /* will just use standard encodings for them */
+ if ( strstrmatch(encname,"sjis")!=NULL ) {
+ enc = FindOrMakeEncoding("cp932");
+ if ( enc!=NULL ) {
+ applemap = map;
+ map = EncMapFromEncoding(sf,enc);
+ }
+ } else if ( strstrmatch(encname,"cp932")!=NULL )
+ applemap = EncMapFromEncoding(sf,FindOrMakeEncoding("sjis"));
+
+ if ( applemap!=NULL )
+ *apple = _Gen816Enc(sf,appletlen,applemap);
+ sub = _Gen816Enc(sf,tlen,map);
+
+ if ( applemap!=NULL && applemap!=oldmap )
+ EncMapFree(applemap);
+ if ( map!=oldmap )
+ EncMapFree(map);
+return( sub );
+}
+
+static FILE *NeedsUCS4Table(SplineFont *sf,int *ucs4len,EncMap *map) {
+ int i=0,j,group;
+ FILE *format12;
+ SplineChar *sc;
+ EncMap *freeme = NULL;
+ struct altuni *altuni;
+
+ if ( map->enc->is_unicodefull )
+ i=0x10000;
+ else if ( map->enc->is_custom )
+ i = 0;
+ else
+ i = map->enc->char_cnt;
+ for ( ; i<map->enccount; ++i ) {
+ if ( map->map[i]!=-1 && SCWorthOutputting(sf->glyphs[map->map[i]]) ) {
+ if ( sf->glyphs[map->map[i]]->unicodeenc>=0x10000 )
+ break;
+ for ( altuni=sf->glyphs[map->map[i]]->altuni; altuni!=NULL && altuni->unienc<0x10000;
+ altuni=altuni->next );
+ if ( altuni!=NULL )
+ break;
+ }
+ }
+
+ if ( i>=map->enccount )
+return(NULL);
+
+ if ( !map->enc->is_unicodefull )
+ map = freeme = EncMapFromEncoding(sf,FindOrMakeEncoding("ucs4"));
+
+ format12 = tmpfile();
+ if ( format12==NULL )
+return( NULL );
+
+ putshort(format12,12); /* Subtable format */
+ putshort(format12,0); /* padding */
+ putlong(format12,0); /* Length, we'll come back to this */
+ putlong(format12,0); /* language */
+ putlong(format12,0); /* Number of groups, we'll come back to this */
+
+ group = 0;
+ for ( i=0; i<map->enccount; ++i ) if ( map->map[i]!=-1 && SCWorthOutputting(sf->glyphs[map->map[i]]) && sf->glyphs[map->map[i]]->unicodeenc!=-1 ) {
+ sc = sf->glyphs[map->map[i]];
+ for ( j=i+1; j<map->enccount && map->map[j]!=-1 &&
+ SCWorthOutputting(sf->glyphs[map->map[j]]) &&
+ sf->glyphs[map->map[j]]->unicodeenc!=-1 &&
+ sf->glyphs[map->map[j]]->ttf_glyph==sc->ttf_glyph+j-i; ++j );
+ --j;
+ putlong(format12,i); /* start char code */
+ putlong(format12,j); /* end char code */
+ putlong(format12,sc->ttf_glyph);
+ ++group;
+ i=j; /* move to the start of the next group */
+ }
+ *ucs4len = ftell(format12);
+ fseek(format12,4,SEEK_SET);
+ putlong(format12,*ucs4len); /* Length, I said we'd come back to it */
+ putlong(format12,0); /* language */
+ putlong(format12,group); /* Number of groups */
+ rewind( format12 );
+
+ if ( freeme!=NULL )
+ EncMapFree(freeme);
+return( format12 );
+}
+
+static FILE *NeedsUCS2Table(SplineFont *sf,int *ucs2len,EncMap *map) {
+ /* We always want a format 4 2byte unicode encoding map */
+ uint32 *avail = galloc(65536*sizeof(uint32));
+ int i,j,l;
+ int segcnt, cnt=0, delta, rpos;
+ struct cmapseg { uint16 start, end; uint16 delta; uint16 rangeoff; } *cmapseg;
+ uint16 *ranges;
+ SplineChar *sc;
+ FILE *format4 = tmpfile();
+
+ memset(avail,0xff,65536*sizeof(uint32));
+ if ( map->enc->is_unicodebmp || map->enc->is_unicodefull ) { int gid;
+ for ( i=0; i<65536 && i<map->enccount; ++i ) if ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL && sf->glyphs[gid]->ttf_glyph!=-1 ) {
+ avail[i] = gid;
+ ++cnt;
+ }
+ } else {
+ struct altuni *altuni;
+ for ( i=0; i<sf->glyphcnt; ++i ) {
+ if ( (sc=sf->glyphs[i])!=NULL && sc->ttf_glyph!=-1 ) {
+ if ( sc->unicodeenc>=0 && sc->unicodeenc<=0xffff ) {
+ avail[sc->unicodeenc] = i;
+ ++cnt;
+ }
+ for ( altuni=sc->altuni; altuni!=NULL; altuni = altuni->next ) {
+ if ( altuni->unienc>=0 && altuni->unienc<=0xffff ) {
+ avail[altuni->unienc] = i;
+ ++cnt;
+ }
+ }
+ }
+ }
+ }
+
+ j = -1;
+ for ( i=segcnt=0; i<65536; ++i ) {
+ if ( avail[i]!=0xffffffff && j==-1 ) {
+ j=i;
+ ++segcnt;
+ } else if ( j!=-1 && avail[i]==0xffffffff )
+ j = -1;
+ }
+ cmapseg = gcalloc(segcnt+1,sizeof(struct cmapseg));
+ ranges = galloc(cnt*sizeof(int16));
+ j = -1;
+ for ( i=segcnt=0; i<65536; ++i ) {
+ if ( avail[i]!=0xffffffff && j==-1 ) {
+ j=i;
+ cmapseg[segcnt].start = j;
+ ++segcnt;
+ } else if ( j!=-1 && avail[i]==0xffffffff ) {
+ cmapseg[segcnt-1].end = i-1;
+ j = -1;
+ }
+ }
+ if ( j!=-1 )
+ cmapseg[segcnt-1].end = i-1;
+ /* create a dummy segment to mark the end of the table */
+ cmapseg[segcnt].start = cmapseg[segcnt].end = 0xffff;
+ cmapseg[segcnt++].delta = 1;
+ rpos = 0;
+ for ( i=0; i<segcnt-1; ++i ) {
+ l = avail[cmapseg[i].start];
+ sc = sf->glyphs[l];
+ delta = sc->ttf_glyph-cmapseg[i].start;
+ for ( j=cmapseg[i].start; j<=cmapseg[i].end; ++j ) {
+ l = avail[j];
+ sc = sf->glyphs[l];
+ if ( delta != sc->ttf_glyph-j )
+ break;
+ }
+ if ( j>cmapseg[i].end )
+ cmapseg[i].delta = delta;
+ else {
+ cmapseg[i].rangeoff = (rpos + (segcnt-i)) * sizeof(int16);
+ for ( j=cmapseg[i].start; j<=cmapseg[i].end; ++j ) {
+ l = avail[j];
+ sc = sf->glyphs[l];
+ ranges[rpos++] = sc->ttf_glyph;
+ }
+ }
+ }
+ free(avail);
+
+
+ putshort(format4,4); /* format */
+ putshort(format4,(8+4*segcnt+rpos)*sizeof(int16));
+ putshort(format4,0); /* language/version */
+ putshort(format4,2*segcnt); /* segcnt */
+ for ( j=0,i=1; i<=segcnt; i<<=1, ++j );
+ putshort(format4,i); /* 2*2^floor(log2(segcnt)) */
+ putshort(format4,j-1);
+ putshort(format4,2*segcnt-i);
+ for ( i=0; i<segcnt; ++i )
+ putshort(format4,cmapseg[i].end);
+ putshort(format4,0);
+ for ( i=0; i<segcnt; ++i )
+ putshort(format4,cmapseg[i].start);
+ for ( i=0; i<segcnt; ++i )
+ putshort(format4,cmapseg[i].delta);
+ for ( i=0; i<segcnt; ++i )
+ putshort(format4,cmapseg[i].rangeoff);
+ for ( i=0; i<rpos; ++i )
+ putshort(format4,ranges[i]);
+ free(ranges);
+ free(cmapseg);
+ *ucs2len = ftell(format4);
+return( format4 );
+}
+
+static void dumpcmap(struct alltabs *at, SplineFont *sf,enum fontformat format) {
+ int i,enccnt, issmall, hasmac;
+ uint16 table[256];
+ SplineChar *sc;
+ int alreadyprivate = false;
+ int anyglyphs = 0;
+ int wasotf = format==ff_otf || format==ff_otfcid;
+ EncMap *map = at->map;
+ int ucs4len=0, ucs2len=0, cjklen=0, applecjklen=0;
+ FILE *format12, *format4, *format2, *apple2;
+ int mspos, ucs4pos, cjkpos, applecjkpos;
+
+ for ( i=at->gi.gcnt-1; i>0 ; --i ) if ( at->gi.bygid[i]!=-1 ) {
+ if ( SCWorthOutputting(sf->glyphs[at->gi.bygid[i]])) {
+ anyglyphs = true;
+ if ( sf->glyphs[at->gi.bygid[i]]->unicodeenc!=-1 )
+ break;
+ }
+ }
+ if ( sf->subfontcnt==0 && !anyglyphs ) {
+ gwwv_post_error(_("No Encoded Glyphs"),_("Warning: Font contained no glyphs"));
+ }
+ if ( sf->subfontcnt==0 && format!=ff_ttfsym) {
+ if ( i==0 && anyglyphs ) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ if ( map->enccount<=256 ) {
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buts[3];
+ buts[0] = _("_Yes"); buts[1] = _("_No"); buts[2] = NULL;
+#else
+ static char *buts[] = { GTK_STOCK_YES, GTK_STOCK_NO, NULL };
+#endif
+ if ( gwwv_ask(_("No Encoded Glyphs"),(const char **) buts,0,1,_("This font contains no glyphs with unicode encodings.\nWould you like to use a \"Symbol\" encoding instead of Unicode?"))==0 )
+ format = ff_ttfsym;
+ } else
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ gwwv_post_error(_("No Encoded Glyphs"),_("This font contains no glyphs with unicode encodings.\nYou will probably not be able to use the output."));
+ }
+ }
+
+ at->cmap = tmpfile();
+
+ /* MacRoman encoding table */ /* Not going to bother with making this work for cid fonts */
+ /* I now see that Apple doesn't restrict us to format 0 sub-tables (as */
+ /* the docs imply) but instead also uses format 6 tables. Wildly in- */
+ /* appropriate as they are for 2byte encodings, but Apple uses them */
+ /* for one byte ones too */
+ memset(table,'\0',sizeof(table));
+ if ( !wasotf ) {
+ table[29] = table[8] = table[0] = 1;
+ table[9] = table[13] = 2;
+ }
+ for ( i=0; i<256 ; ++i ) {
+ extern unichar_t MacRomanEnc[];
+ /* sc = SFFindExistingCharMac(sf,map,MacRomanEnc[i]); */
+ sc = SFGetChar(sf,MacRomanEnc[i],NULL);
+ if ( sc!=NULL && sc->ttf_glyph!=-1 )
+ table[i] = sc->ttf_glyph;
+ }
+ if ( table[0]==0 ) table[0] = 1;
+
+ if ( format==ff_ttfsym ) {
+ int acnt=0, pcnt=0;
+ for ( i=0; i<map->enccount && i<0xffff; ++i ) {
+ if ( map->map[i]!=-1 && sf->glyphs[map->map[i]]!=NULL &&
+ sf->glyphs[map->map[i]]->ttf_glyph!=-1 ) {
+ if ( i>=0xf000 && i<=0xf0ff )
+ ++acnt;
+ else if ( i>=0x20 && i<=0xff )
+ ++pcnt;
+ }
+ }
+ alreadyprivate = acnt>pcnt;
+ memset(table,'\0',sizeof(table));
+ if ( !wasotf ) {
+ table[29] = table[8] = table[0] = 1;
+ table[9] = table[13] = 2;
+ }
+ if ( !alreadyprivate ) {
+ for ( i=0; i<map->enccount && i<256; ++i ) {
+ if ( map->map[i]!=-1 && (sc = sf->glyphs[map->map[i]])!=NULL &&
+ sc->ttf_glyph!=-1 )
+ table[i] = sc->ttf_glyph;
+ }
+ } else {
+ for ( i=0xf000; i<=0xf0ff && i<sf->glyphcnt; ++i ) {
+ if ( map->map[i]!=-1 && (sc = sf->glyphs[map->map[i]])!=NULL &&
+ sc->ttf_glyph!=-1 )
+ table[i-0xf000] = sc->ttf_glyph;
+ }
+ }
+ /* if the user has read in a ttf symbol file then it will already have */
+ /* the right private use encoding, and we don't want to mess it up. */
+ /* The alreadyprivate flag should detect this case */
+ if ( !alreadyprivate ) {
+ for ( i=0; i<map->enccount && i<256; ++i ) {
+ if ( map->map[i]!=-1 && (sc = sf->glyphs[map->map[i]])!=NULL ) {
+ sc->orig_pos = sc->unicodeenc;
+ sc->unicodeenc = 0xf000 + i;
+ }
+ }
+ for ( ; i<map->enccount; ++i ) {
+ if ( map->map[i]!=-1 && (sc = sf->glyphs[map->map[i]])!=NULL ) {
+ sc->orig_pos = sc->unicodeenc;
+ sc->unicodeenc = -1;
+ }
+ }
+ }
+ }
+
+ format4 = NeedsUCS2Table(sf,&ucs2len,map);
+ format12 = NeedsUCS4Table(sf,&ucs4len,map);
+ format2 = Needs816Enc(sf,&cjklen,map,&apple2,&applecjklen);
+
+ /* Two/Three/Four encoding table pointers, one for ms, one for mac */
+ /* usually one for mac big, just a copy of ms */
+ /* plus we may have a format12 encoding for ucs4, mac doesn't support */
+ /* plus we may have a format2 encoding for cjk, sometimes I know the codes for the mac... */
+ /* sometimes the mac will have a slightly different cjk table */
+ if ( format==ff_ttfsym ) {
+ enccnt = 2;
+ hasmac = 0;
+ } else {
+ hasmac = 1;
+ enccnt = 3;
+ if ( format12!=NULL )
+ enccnt = 5;
+ if ( format2!=NULL ) {
+ if ( strstrmatch(map->enc->enc_name,"johab")!=NULL ) {
+ ++enccnt;
+ } else {
+ enccnt+=2;
+ hasmac=3;
+ }
+ }
+ }
+
+ putshort(at->cmap,0); /* version */
+ putshort(at->cmap,enccnt); /* num tables */
+
+ mspos = 2*sizeof(uint16)+enccnt*(2*sizeof(uint16)+sizeof(uint32));
+ ucs4pos = mspos+ucs2len;
+ cjkpos = ucs4pos+ucs4len;
+ if ( apple2==NULL ) {
+ applecjkpos = cjkpos;
+ applecjklen = cjklen;
+ } else
+ applecjkpos = cjkpos + cjklen;
+ /* applecjklen set above */
+ if ( hasmac&1 ) {
+ /* big mac table, just a copy of the ms table */
+ putshort(at->cmap,0); /* mac unicode platform */
+ putshort(at->cmap,3); /* Unicode 2.0 */
+ putlong(at->cmap,mspos);
+ }
+ if ( format12!=NULL ) {
+ /* full unicode mac table, just a copy of the ms table */
+ putshort(at->cmap,0); /* mac unicode platform */
+ putshort(at->cmap,4); /* Unicode 2.0, full unicode */
+ putlong(at->cmap,ucs4pos);
+ }
+ putshort(at->cmap,1); /* mac platform */
+ putshort(at->cmap,0); /* plat specific enc, script=roman */
+ /* Even the symbol font on the mac claims a mac roman encoding */
+ /* although it actually contains a symbol encoding. There is an*/
+ /* "RSymbol" language listed for Mac (specific=8) but it isn't used*/
+ putlong(at->cmap,applecjkpos+applecjklen); /* offset from tab start to sub tab start */
+ if ( format2!=NULL && (hasmac&2) ) {
+ /* mac cjk table, often a copy of the ms table */
+ putshort(at->cmap,1); /* mac platform */
+ putshort(at->cmap,
+ map->enc->is_japanese || sf->uni_interp==ui_japanese ? 1 : /* SJIS */
+ map->enc->is_korean || sf->uni_interp==ui_korean ? 3 : /* Korean */
+ map->enc->is_simplechinese || sf->uni_interp==ui_simp_chinese ? 25 :/* Simplified Chinese */
+ 2 ); /* Big5 */
+ putlong(at->cmap,applecjkpos);
+ }
+
+ putshort(at->cmap,3); /* ms platform */
+ putshort(at->cmap, /* plat specific enc */
+ format==ff_ttfsym ? 0 : /* Symbol */
+ 1 ); /* Unicode */
+ putlong(at->cmap,mspos); /* offset from tab start to sub tab start */
+
+ if ( format2!=NULL ) {
+ putshort(at->cmap,3); /* ms platform */
+ putshort(at->cmap, /* plat specific enc */
+ strstrmatch(map->enc->enc_name,"johab")!=NULL ? 6 :
+ map->enc->is_korean || sf->uni_interp==ui_korean ? 5 :
+ map->enc->is_japanese || sf->uni_interp==ui_japanese ? 2 :
+ map->enc->is_simplechinese || sf->uni_interp==ui_simp_chinese ? 3 :
+ 4); /* Big5 */
+ putlong(at->cmap,cjkpos); /* offset from tab start to sub tab start */
+ }
+
+ if ( format12!=NULL ) {
+ putshort(at->cmap,3); /* ms platform */
+ putshort(at->cmap,10); /* plat specific enc, ucs4 */
+ putlong(at->cmap,ucs4pos); /* offset from tab start to sub tab start */
+ }
+ if ( format4!=NULL ) {
+ if ( !ttfcopyfile(at->cmap,format4,mspos,"cmap-Unicode16")) at->error = true;
+ }
+ if ( format12!=NULL ) {
+ if ( !ttfcopyfile(at->cmap,format12,ucs4pos,"cmap-Unicode32")) at->error = true;
+ }
+ if ( format2!=NULL ) {
+ if ( !ttfcopyfile(at->cmap,format2,cjkpos,"cmap-cjk")) at->error = true;
+ }
+ if ( apple2!=NULL ) {
+ if ( !ttfcopyfile(at->cmap,apple2,applecjkpos,"cmap-applecjk")) at->error = true;
+ }
+
+ /* Mac table */
+ issmall = true;
+ for ( i=0; i<256; ++i )
+ if ( table[i]>=256 ) {
+ issmall = false;
+ break;
+ }
+ if ( issmall ) {
+ putshort(at->cmap,0); /* format */
+ putshort(at->cmap,262); /* length = 256bytes + 6 header bytes */
+ putshort(at->cmap,0); /* language = english */
+ for ( i=0; i<256; ++i )
+ putc(table[i],at->cmap);
+ } else {
+ putshort(at->cmap,6); /* format 6 */
+ putshort(at->cmap,522); /* length = 256short +10 header bytes */
+ putshort(at->cmap,0); /* language = english */
+ putshort(at->cmap,0); /* first code */
+ putshort(at->cmap,256); /* entry count */
+ for ( i=0; i<256; ++i )
+ putshort(at->cmap,table[i]);
+ }
+
+ at->cmaplen = ftell(at->cmap);
+ if ( (at->cmaplen&2)!=0 )
+ putshort(at->cmap,0);
+
+ if ( format==ff_ttfsym ) {
+ if ( !alreadyprivate ) {
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ sf->glyphs[i]->unicodeenc = sf->glyphs[i]->orig_pos;
+ sf->glyphs[i]->orig_pos = i;
+ }
+ }
+ }
+}
+
+static int32 filecheck(FILE *file) {
+ uint32 sum = 0, chunk;
+
+ rewind(file);
+ while ( 1 ) {
+ chunk = getuint32(file);
+ if ( feof(file))
+ break;
+ sum += chunk;
+ }
+return( sum );
+}
+
+static void AbortTTF(struct alltabs *at, SplineFont *sf) {
+ int i;
+
+ if ( at->loca!=NULL )
+ fclose(at->loca);
+ if ( at->name!=NULL )
+ fclose(at->name);
+ if ( at->post!=NULL )
+ fclose(at->post);
+ if ( at->gpos!=NULL )
+ fclose(at->gpos);
+ if ( at->gsub!=NULL )
+ fclose(at->gsub);
+ if ( at->gdef!=NULL )
+ fclose(at->gdef);
+ if ( at->kern!=NULL )
+ fclose(at->kern);
+ if ( at->cmap!=NULL )
+ fclose(at->cmap);
+ if ( at->headf!=NULL )
+ fclose(at->headf);
+ if ( at->hheadf!=NULL )
+ fclose(at->hheadf);
+ if ( at->maxpf!=NULL )
+ fclose(at->maxpf);
+ if ( at->os2f!=NULL )
+ fclose(at->os2f);
+ if ( at->cvtf!=NULL )
+ fclose(at->cvtf);
+ if ( at->vheadf!=NULL )
+ fclose(at->vheadf);
+ if ( at->vorgf!=NULL )
+ fclose(at->vorgf);
+ if ( at->cfff!=NULL )
+ fclose(at->cfff);
+
+ if ( at->gi.glyphs!=NULL )
+ fclose(at->gi.glyphs);
+ if ( at->gi.hmtx!=NULL )
+ fclose(at->gi.hmtx);
+ if ( at->gi.vmtx!=NULL )
+ fclose(at->gi.vmtx);
+ if ( at->fpgmf!=NULL )
+ fclose(at->fpgmf);
+ if ( at->prepf!=NULL )
+ fclose(at->prepf);
+ if ( at->gaspf!=NULL )
+ fclose(at->gaspf);
+
+ if ( at->sidf!=NULL )
+ fclose(at->sidf);
+ if ( at->sidh!=NULL )
+ fclose(at->sidh);
+ if ( at->charset!=NULL )
+ fclose(at->charset);
+ if ( at->encoding!=NULL )
+ fclose(at->encoding);
+ if ( at->private!=NULL )
+ fclose(at->private);
+ if ( at->charstrings!=NULL )
+ fclose(at->charstrings);
+ if ( at->fdselect!=NULL )
+ fclose(at->fdselect);
+ if ( at->fdarray!=NULL )
+ fclose(at->fdarray);
+ if ( at->bdat!=NULL )
+ fclose(at->bdat);
+ if ( at->bloc!=NULL )
+ fclose(at->bloc);
+ if ( at->ebsc!=NULL )
+ fclose(at->ebsc);
+
+ if ( at->prop!=NULL )
+ fclose(at->prop);
+ if ( at->opbd!=NULL )
+ fclose(at->opbd);
+ if ( at->acnt!=NULL )
+ fclose(at->acnt);
+ if ( at->lcar!=NULL )
+ fclose(at->lcar);
+ if ( at->feat!=NULL )
+ fclose(at->feat);
+ if ( at->morx!=NULL )
+ fclose(at->morx);
+
+ if ( at->pfed!=NULL )
+ fclose(at->pfed);
+ if ( at->tex!=NULL )
+ fclose(at->tex);
+
+ if ( at->gvar!=NULL )
+ fclose(at->gvar);
+ if ( at->fvar!=NULL )
+ fclose(at->fvar);
+ if ( at->cvar!=NULL )
+ fclose(at->cvar);
+ if ( at->avar!=NULL )
+ fclose(at->avar);
+
+ for ( i=0; i<sf->subfontcnt; ++i ) {
+ if ( at->fds[i].private!=NULL )
+ fclose(at->fds[i].private);
+ }
+ if ( sf->subfontcnt!=0 ) {
+ free(sf->glyphs);
+ sf->glyphs = NULL;
+ sf->glyphcnt = sf->glyphmax = 0;
+ }
+ if ( at->fds!=NULL )
+ free( at->fds );
+ free( at->gi.bygid );
+}
+
+int SFHasInstructions(SplineFont *sf) {
+ int i;
+
+ if ( sf->mm!=NULL && sf->mm->apple )
+ sf = sf->mm->normal;
+
+ if ( sf->subfontcnt!=0 )
+return( false ); /* Truetype doesn't support cid keyed fonts */
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ if ( strcmp(sf->glyphs[i]->name,".notdef")==0 )
+ continue; /* ff produces fonts with instructions in .notdef & not elsewhere. Ignore these */
+ if ( sf->glyphs[i]->ttf_instrs!=NULL )
+return( true );
+ }
+return( false );
+}
+
+static void MaxpFromTable(struct alltabs *at,SplineFont *sf) {
+ struct ttf_table *maxp;
+
+ maxp = SFFindTable(sf,CHR('m','a','x','p'));
+ if ( maxp==NULL && sf->mm!=NULL && sf->mm->apple )
+ maxp = SFFindTable(sf->mm->normal,CHR('m','a','x','p'));
+ if ( maxp==NULL || maxp->len<13*sizeof(uint16) )
+return;
+ /* We can figure out the others ourselves, but these depend on the contents */
+ /* of uninterpretted tables */
+ at->maxp.maxZones = memushort(maxp->data,maxp->len, 7*sizeof(uint16));
+ at->maxp.maxTwilightPts = memushort(maxp->data,maxp->len, 8*sizeof(uint16));
+ at->maxp.maxStorage = memushort(maxp->data,maxp->len, 9*sizeof(uint16));
+ at->maxp.maxFDEFs = memushort(maxp->data,maxp->len, 10*sizeof(uint16));
+ at->maxp.maxIDEFs = memushort(maxp->data,maxp->len, 11*sizeof(uint16));
+ at->maxp.maxStack = memushort(maxp->data,maxp->len, 12*sizeof(uint16));
+}
+
+static FILE *dumpstoredtable(SplineFont *sf,uint32 tag,int *len) {
+ struct ttf_table *tab = SFFindTable(sf,tag);
+ FILE *out;
+
+ if ( tab==NULL && sf->mm!=NULL && sf->mm->apple )
+ tab = SFFindTable(sf->mm->normal,tag);
+ if ( tab==NULL ) {
+ *len = 0;
+return( NULL );
+ }
+
+ out = tmpfile();
+ fwrite(tab->data,1,tab->len,out);
+ if ( (tab->len&1))
+ putc('\0',out);
+ if ( (tab->len+1)&2 )
+ putshort(out,0);
+ *len = tab->len;
+return( out );
+}
+
+static FILE *dumpsavedtable(struct ttf_table *tab) {
+ FILE *out;
+
+ if ( tab==NULL )
+return( NULL );
+
+ out = tmpfile();
+ fwrite(tab->data,1,tab->len,out);
+ if ( (tab->len&1))
+ putc('\0',out);
+ if ( (tab->len+1)&2 )
+ putshort(out,0);
+return( out );
+}
+
+static int tagcomp(const void *_t1, const void *_t2) {
+ struct taboff *t1 = (struct taboff *) _t1, *t2 = (struct taboff *) _t2;
+return( (int) (t1->tag - t2->tag) );
+}
+
+static int tcomp(const void *_t1, const void *_t2) {
+ struct taboff *t1 = *((struct taboff **) _t1), *t2 = *((struct taboff **) _t2);
+return( t1->orderingval - t2->orderingval );
+}
+
+static int tcomp2(const void *_t1, const void *_t2) {
+ struct taboff *t1 = *((struct taboff **) _t1), *t2 = *((struct taboff **) _t2);
+ if ( t1->offset>t2->offset )
+return( 1 );
+ else if ( t1->offset < t2->offset )
+return( -1 );
+return( 0 );
+}
+
+static int initTables(struct alltabs *at, SplineFont *sf,enum fontformat format,
+ int32 *bsizes, enum bitmapformat bf,int flags) {
+ int i, j, aborted, ebdtpos=0, eblcpos=0, offset;
+ BDFFont *bdf;
+ struct ttf_table *tab;
+
+ if ( strmatch(at->map->enc->enc_name,"symbol")==0 && format==ff_ttf )
+ format = ff_ttfsym;
+
+ SFDefaultOS2Info(&sf->pfminfo,sf,sf->fontname);
+
+ at->gi.xmin = at->gi.ymin = 15000;
+ at->gi.sf = sf;
+ if ( bf!=bf_ttf && bf!=bf_sfnt_dfont && bf!=bf_otb && bf!=bf_sfnt_ms )
+ bsizes = NULL;
+ if ( bsizes!=NULL ) {
+ for ( i=j=0; bsizes[i]!=0; ++i ) {
+ for ( bdf=sf->bitmaps; bdf!=NULL && (bdf->pixelsize!=(bsizes[i]&0xffff) || BDFDepth(bdf)!=(bsizes[i]>>16)); bdf=bdf->next );
+ if ( bdf!=NULL )
+ bsizes[j++] = bsizes[i];
+ else
+ gwwv_post_error(_("Missing bitmap strike"), _("The font database does not contain a bitmap of size %d and depth %d"), bsizes[i]&0xffff, bsizes[i]>>16 );
+ }
+ bsizes[j] = 0;
+ for ( i=0; bsizes[i]!=0; ++i );
+ at->gi.strikecnt = i;
+ if ( i==0 ) bsizes=NULL;
+ }
+
+ if ( sf->subfonts!=NULL ) {
+ SFDummyUpCIDs(&at->gi,sf); /* life is easier if we ignore the seperate fonts of a cid keyed fonts and treat it as flat */
+ } else if ( format!=ff_none )
+ AssignTTFGlyph(&at->gi,sf,at->map,format==ff_otf);
+ else {
+ if ( bsizes==NULL ) {
+ gwwv_post_error(_("No bitmap strikes"), _("No bitmap strikes"));
+ AbortTTF(at,sf);
+return( false );
+ }
+ AssignTTFBitGlyph(&at->gi,sf,at->map,bsizes);
+ }
+
+ at->maxp.version = 0x00010000;
+ if ( format==ff_otf || format==ff_otfcid || (format==ff_none && at->applemode) )
+ at->maxp.version = 0x00005000;
+ at->maxp.maxnumcomponents = 0;
+ at->maxp.maxcomponentdepth = 0;
+ at->maxp.maxZones = 2; /* 1 would probably do, don't use twilight */
+ at->maxp.maxFDEFs = 1; /* Not even 1 */
+ at->maxp.maxStorage = 1; /* Not even 1 */
+ at->maxp.maxStack = 64; /* A guess, it's probably more like 8 */
+ if ( format==ff_otf || format==ff_otfcid || (format==ff_none && at->applemode) )
+ at->maxp.version = 0x00005000;
+ else
+ MaxpFromTable(at,sf);
+ at->gi.maxp = &at->maxp;
+ if ( format==ff_otf )
+ aborted = !dumptype2glyphs(sf,at);
+ else if ( format==ff_otfcid )
+ aborted = !dumpcidglyphs(sf,at);
+ else if ( format==ff_none && at->applebitmaps ) {
+ aborted = !dumpcffhmtx(at,sf,true); /* There is no 'hmtx' table for apple bitmap only fonts */
+ /* But we need some of the side effects of this */
+ } else if ( format==ff_none && at->otbbitmaps ) {
+ aborted = !dumpcffhmtx(at,sf,true);
+ dumpnoglyphs(sf,&at->gi);
+ } else if ( format==ff_none && at->msbitmaps ) {
+ aborted = !dumpglyphs(sf,&at->gi);
+ } else {
+ struct ttf_table *tab;
+ /* There's a typo in Adobe's docs, and the instructions in these tables*/
+ /* need to be included in the max glyph instruction length */
+ if ( (tab = SFFindTable(sf,CHR('f','p','g','m'))) != NULL ) {
+ at->maxp.maxglyphInstr = tab->len;
+ at->gi.has_instrs = true;
+ }
+ if ( (tab = SFFindTable(sf,CHR('p','r','e','p'))) != NULL ) {
+ if ( at->maxp.maxglyphInstr < tab->len )
+ at->maxp.maxglyphInstr = tab->len;
+ at->gi.has_instrs = true;
+ }
+ at->gi.has_instrs = (SFFindTable(sf,CHR('f','p','g','m')) != NULL ||
+ SFFindTable(sf,CHR('p','r','e','p')) != NULL);
+ /* if format==ff_none the following will put out lots of space glyphs */
+ aborted = !dumpglyphs(sf,&at->gi);
+ }
+ if ( format!=ff_type42 && format!=ff_type42cid ) {
+#ifndef LUA_FF_LIB
+ if ( bsizes!=NULL && !aborted )
+ ttfdumpbitmap(sf,at,bsizes);
+ if ( bsizes!=NULL && format==ff_none && at->msbitmaps )
+ ttfdumpbitmapscaling(sf,at,bsizes);
+#endif
+ }
+ if ( aborted ) {
+ AbortTTF(at,sf);
+return( false );
+ }
+
+ if ( at->gi.xmin==15000 ) at->gi.xmin = 0;
+ if ( at->gi.ymin==15000 ) at->gi.ymin = 0;
+ if ( bsizes!=NULL && format==ff_none ) {
+ if ( sf->ascent >at->gi.ymax ) at->gi.ymax = sf->ascent;
+ if ( -sf->descent<at->gi.ymin ) at->gi.ymin = -sf->descent;
+ }
+ at->head.xmin = at->gi.xmin;
+ at->head.ymin = at->gi.ymin;
+ at->head.xmax = at->gi.xmax;
+ at->head.ymax = at->gi.ymax;
+
+ sethead(&at->head,sf,at);
+ sethhead(&at->hhead,&at->vhead,at,sf);
+ setvorg(&at->vorg,sf);
+ setos2(&at->os2,at,sf,format); /* should precede kern/ligature output */
+ if ( at->gi.glyph_len<0x20000 )
+ at->head.locais32 = 0;
+ if ( format==ff_none && at->otbbitmaps )
+ dummyloca(at);
+ else if ( format!=ff_otf && format!=ff_otfcid && bf!=bf_sfnt_dfont &&
+ (format!=ff_none || (bsizes!=NULL && !at->applemode && at->opentypemode)) )
+ redoloca(at);
+ redohead(at);
+ if ( format!=ff_none || !at->applemode ) /* No 'hhea' table for apple bitmap-only fonts */
+ redohhead(at,false);
+ if ( sf->hasvmetrics ) {
+ redohhead(at,true);
+ redovorg(at); /* I know, VORG is only meaningful in a otf font and I dump it out in ttf too. Well, it will help ME read the font back in, and it won't bother anyone else. So there. */
+ }
+ redomaxp(at,format);
+ ttf_fftm_dump(sf,at);
+
+ if ( format!=ff_type42 && format!=ff_type42cid ) {
+ if ( at->opentypemode ) {
+ SFFindUnusedLookups(sf);
+ otf_dumpgpos(at,sf);
+ otf_dumpgsub(at,sf);
+ otf_dumpgdef(at,sf);
+ }
+ if ( at->dovariations )
+ ttf_dumpvariations(at,sf);
+#ifndef LUA_FF_LIB
+ if ( at->applemode ) {
+ if ( !at->opentypemode )
+ SFFindUnusedLookups(sf);
+ ttf_dumpkerns(at,sf);
+ aat_dumplcar(at,sf);
+ aat_dumpmorx(at,sf); /* Sets the feat table too */
+ aat_dumpopbd(at,sf);
+ aat_dumpprop(at,sf);
+ }
+#endif
+ if ( !at->applemode && (!at->opentypemode || (at->gi.flags&ttf_flag_oldkern)) )
+ ttf_dumpkerns(at,sf); /* everybody supports a mimimal kern table */
+
+ dumpnames(at,sf,format); /* Must be after dumpmorx which may create extra names */
+ /* GPOS 'size' can also create names */
+ redoos2(at);
+ }
+ if ( format!=ff_otf && format!=ff_otfcid && format!=ff_none ) {
+ if (( sf->gasp_cnt!=0 || !SFHasInstructions(sf))
+ && format!=ff_type42 && format!=ff_type42cid )
+ dumpgasp(at, sf);
+ at->fpgmf = dumpstoredtable(sf,CHR('f','p','g','m'),&at->fpgmlen);
+ at->prepf = dumpstoredtable(sf,CHR('p','r','e','p'),&at->preplen);
+ at->cvtf = dumpstoredtable(sf,CHR('c','v','t',' '),&at->cvtlen);
+ }
+ for ( tab=sf->ttf_tab_saved; tab!=NULL; tab=tab->next )
+ tab->temp = dumpsavedtable(tab);
+ if ( format!=ff_type42 && format!=ff_type42cid ) {
+ dumppost(at,sf,format);
+ dumpcmap(at,sf,format);
+
+ pfed_dump(at,sf);
+ tex_dump(at,sf);
+ }
+ if ( sf->subfonts!=NULL ) {
+ free(sf->glyphs); sf->glyphs = NULL;
+ sf->glyphcnt = sf->glyphmax = 0;
+ }
+ free( at->gi.bygid );
+ at->gi.gcnt = 0;
+
+ if ( format==ff_otf || format==ff_otfcid ) {
+ at->tabdir.version = CHR('O','T','T','O');
+#ifdef FONTFORGE_CONFIG_APPLE_ONLY_TTF /* This means that Windows will reject the font. In general not a good idea */
+ } else if ( at->applemode && !at->opentypemode ) {
+ at->tabdir.version = CHR('t','r','u','e');
+#endif
+ } else {
+ at->tabdir.version = 0x00010000;
+ }
+
+ i = 0;
+
+ if ( format==ff_otf || format==ff_otfcid ) {
+ at->tabdir.tabs[i].tag = CHR('C','F','F',' ');
+ at->tabdir.tabs[i].length = at->cfflen;
+ at->tabdir.tabs[i++].data = at->cfff;
+ }
+
+ if ( at->bdat!=NULL && (at->msbitmaps || at->otbbitmaps)) {
+ ebdtpos = i;
+ at->tabdir.tabs[i].tag = CHR('E','B','D','T');
+ at->tabdir.tabs[i].length = at->bdatlen;
+ at->tabdir.tabs[i++].data = at->bdat;
+ }
+
+ if ( at->bloc!=NULL && (at->msbitmaps || at->otbbitmaps)) {
+ eblcpos = i;
+ at->tabdir.tabs[i].tag = CHR('E','B','L','C');
+ at->tabdir.tabs[i].data = at->bloc;
+ at->tabdir.tabs[i++].length = at->bloclen;
+ }
+
+ if ( at->ebsc!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('E','B','S','C');
+ at->tabdir.tabs[i].data = at->ebsc;
+ at->tabdir.tabs[i++].length = at->ebsclen;
+ }
+
+ if ( at->fftmf!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('F','F','T','M');
+ at->tabdir.tabs[i].data = at->fftmf;
+ at->tabdir.tabs[i++].length = at->fftmlen;
+ }
+
+ if ( at->gdef!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('G','D','E','F');
+ at->tabdir.tabs[i].data = at->gdef;
+ at->tabdir.tabs[i++].length = at->gdeflen;
+ }
+
+ if ( at->gpos!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('G','P','O','S');
+ at->tabdir.tabs[i].data = at->gpos;
+ at->tabdir.tabs[i++].length = at->gposlen;
+ }
+
+ if ( at->gsub!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('G','S','U','B');
+ at->tabdir.tabs[i].data = at->gsub;
+ at->tabdir.tabs[i++].length = at->gsublen;
+ }
+
+ if ( at->os2f!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('O','S','/','2');
+ at->tabdir.tabs[i].data = at->os2f;
+ at->tabdir.tabs[i++].length = at->os2len;
+ }
+
+ if ( at->pfed!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('P','f','E','d');
+ at->tabdir.tabs[i].data = at->pfed;
+ at->tabdir.tabs[i++].length = at->pfedlen;
+ }
+
+ if ( at->tex!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('T','e','X',' ');
+ at->tabdir.tabs[i].data = at->tex;
+ at->tabdir.tabs[i++].length = at->texlen;
+ }
+
+ if ( at->bdf!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('B','D','F',' ');
+ at->tabdir.tabs[i].data = at->bdf;
+ at->tabdir.tabs[i++].length = at->bdflen;
+ }
+
+ if ( at->vorgf!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('V','O','R','G');
+ at->tabdir.tabs[i].data = at->vorgf;
+ at->tabdir.tabs[i++].length = at->vorglen;
+ }
+
+ if ( at->acnt!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('a','c','n','t');
+ at->tabdir.tabs[i].data = at->acnt;
+ at->tabdir.tabs[i++].length = at->acntlen;
+ }
+
+ if ( at->bdat!=NULL && at->applebitmaps ) {
+ at->tabdir.tabs[i].tag = CHR('b','d','a','t');
+ if ( !at->msbitmaps ) {
+ at->tabdir.tabs[i].data = at->bdat;
+ at->tabdir.tabs[i++].length = at->bdatlen;
+ } else {
+ at->tabdir.tabs[i].data = NULL;
+ at->tabdir.tabs[i].dup_of = ebdtpos;
+ at->tabdir.tabs[i++].length = at->tabdir.tabs[ebdtpos].length;
+ }
+ }
+
+ if ( format==ff_none && at->applebitmaps ) {
+ /* Bitmap only fonts get a bhed table rather than a head */
+ at->tabdir.tabs[i].tag = CHR('b','h','e','d');
+ at->tabdir.tabs[i].data = at->headf;
+ at->tabdir.tabs[i++].length = at->headlen;
+ }
+
+ if ( at->bloc!=NULL && at->applebitmaps ) {
+ at->tabdir.tabs[i].tag = CHR('b','l','o','c');
+ if ( !at->msbitmaps ) {
+ at->tabdir.tabs[i].data = at->bloc;
+ at->tabdir.tabs[i++].length = at->bloclen;
+ } else {
+ at->tabdir.tabs[i].data = NULL;
+ at->tabdir.tabs[i].dup_of = eblcpos;
+ at->tabdir.tabs[i++].length = at->tabdir.tabs[eblcpos].length;
+ }
+ }
+
+ if ( at->cmap!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('c','m','a','p');
+ at->tabdir.tabs[i].data = at->cmap;
+ at->tabdir.tabs[i++].length = at->cmaplen;
+ }
+
+ if ( format!=ff_otf && format!=ff_otfcid && format!=ff_none ) {
+ if ( at->cvtf!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('c','v','t',' ');
+ at->tabdir.tabs[i].data = at->cvtf;
+ at->tabdir.tabs[i++].length = at->cvtlen;
+ }
+ }
+
+ if ( at->feat!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('f','e','a','t');
+ at->tabdir.tabs[i].data = at->feat;
+ at->tabdir.tabs[i++].length = at->featlen;
+ }
+
+ if ( at->fpgmf!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('f','p','g','m');
+ at->tabdir.tabs[i].data = at->fpgmf;
+ at->tabdir.tabs[i++].length = at->fpgmlen;
+ }
+
+ if ( at->gaspf!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('g','a','s','p');
+ at->tabdir.tabs[i].data = at->gaspf;
+ at->tabdir.tabs[i++].length = at->gasplen;
+ }
+
+ if ( at->gi.glyphs!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('g','l','y','f');
+ at->tabdir.tabs[i].data = at->gi.glyphs;
+ at->tabdir.tabs[i++].length = at->gi.glyph_len;
+ }
+
+ if ( format!=ff_none || !at->applebitmaps ) {
+ at->tabdir.tabs[i].tag = CHR('h','e','a','d');
+ at->tabdir.tabs[i].data = at->headf;
+ at->tabdir.tabs[i++].length = at->headlen;
+ }
+
+ if ( format!=ff_none || !at->applemode ) {
+ at->tabdir.tabs[i].tag = CHR('h','h','e','a');
+ at->tabdir.tabs[i].data = at->hheadf;
+ at->tabdir.tabs[i++].length = at->hheadlen;
+ } else if ( at->hheadf!=NULL ) {
+ fclose(at->hheadf);
+ at->hheadf = NULL;
+ }
+
+ if ( format!=ff_none || !at->applemode ) {
+ at->tabdir.tabs[i].tag = CHR('h','m','t','x');
+ at->tabdir.tabs[i].data = at->gi.hmtx;
+ at->tabdir.tabs[i++].length = at->gi.hmtxlen;
+ }
+
+ if ( at->kern!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('k','e','r','n');
+ at->tabdir.tabs[i].data = at->kern;
+ at->tabdir.tabs[i++].length = at->kernlen;
+ }
+
+ if ( at->lcar!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('l','c','a','r');
+ at->tabdir.tabs[i].data = at->lcar;
+ at->tabdir.tabs[i++].length = at->lcarlen;
+ }
+
+ if ( at->loca!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('l','o','c','a');
+ at->tabdir.tabs[i].data = at->loca;
+ at->tabdir.tabs[i++].length = at->localen;
+ }
+
+ at->tabdir.tabs[i].tag = CHR('m','a','x','p');
+ at->tabdir.tabs[i].data = at->maxpf;
+ at->tabdir.tabs[i++].length = at->maxplen;
+
+ if ( at->morx!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('m','o','r','x');
+ at->tabdir.tabs[i].data = at->morx;
+ at->tabdir.tabs[i++].length = at->morxlen;
+ }
+
+ if ( at->name!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('n','a','m','e');
+ at->tabdir.tabs[i].data = at->name;
+ at->tabdir.tabs[i++].length = at->namelen;
+ }
+
+ if ( at->opbd!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('o','p','b','d');
+ at->tabdir.tabs[i].data = at->opbd;
+ at->tabdir.tabs[i++].length = at->opbdlen;
+ }
+
+ if ( at->post!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('p','o','s','t');
+ at->tabdir.tabs[i].data = at->post;
+ at->tabdir.tabs[i++].length = at->postlen;
+ }
+
+ if ( format!=ff_otf && format!=ff_otfcid && format!=ff_none ) {
+ if ( at->prepf!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('p','r','e','p');
+ at->tabdir.tabs[i].data = at->prepf;
+ at->tabdir.tabs[i++].length = at->preplen;
+ }
+ }
+
+ if ( at->prop!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('p','r','o','p');
+ at->tabdir.tabs[i].data = at->prop;
+ at->tabdir.tabs[i++].length = at->proplen;
+ }
+
+ if ( at->vheadf!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('v','h','e','a');
+ at->tabdir.tabs[i].data = at->vheadf;
+ at->tabdir.tabs[i++].length = at->vheadlen;
+
+ at->tabdir.tabs[i].tag = CHR('v','m','t','x');
+ at->tabdir.tabs[i].data = at->gi.vmtx;
+ at->tabdir.tabs[i++].length = at->gi.vmtxlen;
+ }
+
+ if ( at->fvar!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('f','v','a','r');
+ at->tabdir.tabs[i].data = at->fvar;
+ at->tabdir.tabs[i++].length = at->fvarlen;
+ }
+ if ( at->gvar!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('g','v','a','r');
+ at->tabdir.tabs[i].data = at->gvar;
+ at->tabdir.tabs[i++].length = at->gvarlen;
+ }
+ if ( at->cvar!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('c','v','a','r');
+ at->tabdir.tabs[i].data = at->cvar;
+ at->tabdir.tabs[i++].length = at->cvarlen;
+ }
+ if ( at->avar!=NULL ) {
+ at->tabdir.tabs[i].tag = CHR('a','v','a','r');
+ at->tabdir.tabs[i].data = at->avar;
+ at->tabdir.tabs[i++].length = at->avarlen;
+ }
+
+ if ( i>=MAX_TAB )
+ IError("Miscalculation of number of tables needed. Up sizeof tabs array in struct tabdir in ttf.h" );
+
+ for ( tab=sf->ttf_tab_saved; tab!=NULL && i<MAX_TAB; tab=tab->next ) {
+ at->tabdir.tabs[i].tag = tab->tag;
+ at->tabdir.tabs[i].data = tab->temp;
+ at->tabdir.tabs[i++].length = tab->len;
+ }
+ if ( tab!=NULL )
+ IError("Some user supplied tables omitted. Up sizeof tabs array in struct tabdir in ttf.h" );
+
+ qsort(at->tabdir.tabs,i,sizeof(struct taboff),tagcomp);
+
+ at->tabdir.numtab = i;
+ at->tabdir.searchRange = (i<16?8:i<32?16:i<64?32:64)*16;
+ at->tabdir.entrySel = (i<16?3:i<32?4:i<64?5:6);
+ at->tabdir.rangeShift = at->tabdir.numtab*16-at->tabdir.searchRange;
+ for ( i=0; i<at->tabdir.numtab; ++i ) {
+ struct taboff *tab = &at->tabdir.tabs[i];
+ at->tabdir.ordered[i] = tab;
+/* This is the ordering of tables in ARIAL. I've no idea why it makes a */
+/* difference to order them, time to do a seek seems likely to be small, but */
+/* other people make a big thing about ordering them so I'll do it. */
+/* I got bored after glyph. Adobe follows the same scheme for their otf fonts */
+/* so at least the world is consistant */
+/* On the other hand, MS Font validator has a different idea. Oh well */
+/* From: http://partners.adobe.com/asn/tech/type/opentype/recom.jsp */
+/* TrueType Ordering */
+/* head, hhea, maxp, OS/2, hmtx, LTSH, VDMX, hdmx, cmap, fpgm, prep, cvt, */
+/* loca, glyf, kern, name, post, gasp, PCLT, DSIG */
+/* CFF in OpenType Ordering */
+/* head, hhea, maxp, OS/2, name, cmap, post, CFF, (other tables, as convenient) */
+ if ( format==ff_otf || format==ff_otfcid ) {
+ tab->orderingval = tab->tag==CHR('h','e','a','d')? 1 :
+ tab->tag==CHR('h','h','e','a')? 2 :
+ tab->tag==CHR('m','a','x','p')? 3 :
+ tab->tag==CHR('O','S','/','2')? 4 :
+ tab->tag==CHR('n','a','m','e')? 5 :
+ tab->tag==CHR('c','m','a','p')? 6 :
+ tab->tag==CHR('p','o','s','t')? 7 :
+ tab->tag==CHR('C','F','F',' ')? 8 :
+ tab->tag==CHR('G','D','E','F')? 17 :
+ tab->tag==CHR('G','S','U','B')? 18 :
+ tab->tag==CHR('G','P','O','S')? 19 :
+ 20;
+ } else {
+ tab->orderingval = tab->tag==CHR('h','e','a','d')? 1 :
+ tab->tag==CHR('h','h','e','a')? 2 :
+ tab->tag==CHR('m','a','x','p')? 3 :
+ tab->tag==CHR('O','S','/','2')? 4 :
+ tab->tag==CHR('h','m','t','x')? 5 :
+ tab->tag==CHR('L','T','S','H')? 6 :
+ tab->tag==CHR('V','D','M','X')? 7 :
+ tab->tag==CHR('h','d','m','x')? 8 :
+ tab->tag==CHR('c','m','a','p')? 9 :
+ tab->tag==CHR('f','p','g','m')? 10 :
+ tab->tag==CHR('p','r','e','p')? 11 :
+ tab->tag==CHR('c','v','t',' ')? 12 :
+ tab->tag==CHR('l','o','c','a')? 13 :
+ tab->tag==CHR('g','l','y','f')? 14 :
+ tab->tag==CHR('k','e','r','n')? 15 :
+ tab->tag==CHR('n','a','m','e')? 16 :
+ tab->tag==CHR('p','o','s','t')? 17 :
+ tab->tag==CHR('g','a','s','p')? 18 :
+ tab->tag==CHR('P','C','L','T')? 19 :
+ tab->tag==CHR('D','S','I','G')? 20 :
+ tab->tag==CHR('G','D','E','F')? 21 :
+ tab->tag==CHR('G','S','U','B')? 22 :
+ tab->tag==CHR('G','P','O','S')? 23 :
+ 24;
+ }
+ }
+
+ qsort(at->tabdir.ordered,at->tabdir.numtab,sizeof(struct taboff *),tcomp);
+
+ offset = sizeof(int32)+4*sizeof(int16) + at->tabdir.numtab*4*sizeof(int32);
+ for ( i=0; i<at->tabdir.numtab; ++i ) if ( at->tabdir.ordered[i]->data!=NULL ) {
+ at->tabdir.ordered[i]->offset = offset;
+ offset += ((at->tabdir.ordered[i]->length+3)>>2)<<2;
+ at->tabdir.ordered[i]->checksum = filecheck(at->tabdir.ordered[i]->data);
+ }
+ for ( i=0; i<at->tabdir.numtab; ++i ) if ( at->tabdir.ordered[i]->data==NULL ) {
+ struct taboff *tab = &at->tabdir.tabs[at->tabdir.ordered[i]->dup_of];
+ at->tabdir.ordered[i]->offset = tab->offset;
+ at->tabdir.ordered[i]->checksum = tab->checksum;
+ }
+return( true );
+}
+
+static char *Tag2String(uint32 tag) {
+ static char buffer[8];
+
+ buffer[0] = tag>>24;
+ buffer[1] = tag>>16;
+ buffer[2] = tag>>8;
+ buffer[3] = tag;
+ buffer[4] = 0;
+return( buffer );
+}
+
+static void dumpttf(FILE *ttf,struct alltabs *at, enum fontformat format) {
+ int32 checksum;
+ int i, head_index=-1;
+ /* I can't use fwrite because I (may) have to byte swap everything */
+
+ putlong(ttf,at->tabdir.version);
+ putshort(ttf,at->tabdir.numtab);
+ putshort(ttf,at->tabdir.searchRange);
+ putshort(ttf,at->tabdir.entrySel);
+ putshort(ttf,at->tabdir.rangeShift);
+ for ( i=0; i<at->tabdir.numtab; ++i ) {
+ if ( at->tabdir.tabs[i].tag==CHR('h','e','a','d') || at->tabdir.tabs[i].tag==CHR('b','h','e','d') )
+ head_index = i;
+ putlong(ttf,at->tabdir.tabs[i].tag);
+ putlong(ttf,at->tabdir.tabs[i].checksum);
+ putlong(ttf,at->tabdir.tabs[i].offset);
+ putlong(ttf,at->tabdir.tabs[i].length);
+ }
+
+ for ( i=0; i<at->tabdir.numtab; ++i ) if ( at->tabdir.ordered[i]->data!=NULL )
+ if ( !ttfcopyfile(ttf,at->tabdir.ordered[i]->data,
+ at->tabdir.ordered[i]->offset,Tag2String(at->tabdir.tabs[i].tag)))
+ at->error = true;
+
+ checksum = filecheck(ttf);
+ checksum = 0xb1b0afba-checksum;
+ if ( head_index!=-1 )
+ fseek(ttf,at->tabdir.tabs[head_index].offset+2*sizeof(int32),SEEK_SET);
+ putlong(ttf,checksum);
+
+ /* ttfcopyfile closed all the files (except ttf) */
+}
+
+static void DumpGlyphToNameMap(char *fontname,SplineFont *sf) {
+ char *d, *e;
+ char *newname = galloc(strlen(fontname)+10);
+ FILE *file;
+ int i,k,max;
+ SplineChar *sc;
+
+ strcpy(newname,fontname);
+ d = strrchr(newname,'/');
+ if ( d==NULL ) d=newname;
+ e = strrchr(d,'.');
+ if ( e==NULL ) e = newname+strlen(newname);
+ strcpy(e,".g2n");
+
+ file = fopen(newname,"wb");
+ if ( file==NULL ) {
+ LogError( _("Failed to open glyph to name map file for writing: %s\n"), newname );
+ free(newname);
+return;
+ }
+
+ if ( sf->subfontcnt==0 )
+ max = sf->glyphcnt;
+ else {
+ for ( k=max=0; k<sf->subfontcnt; ++k )
+ if ( sf->subfonts[k]->glyphcnt > max )
+ max = sf->subfonts[k]->glyphcnt;
+ }
+ for ( i=0; i<max; ++i ) {
+ sc = NULL;
+ if ( sf->subfontcnt==0 )
+ sc = sf->glyphs[i];
+ else {
+ for ( k=0; k<sf->subfontcnt; ++k ) if ( i<sf->subfonts[k]->glyphcnt )
+ if ( (sc=sf->subfonts[k]->glyphs[i])!=NULL )
+ break;
+ }
+ if ( sc!=NULL && sc->ttf_glyph!=-1 ) {
+ fprintf( file, "GLYPHID %d\tPSNAME %s", sc->ttf_glyph, sc->name );
+ if ( sc->unicodeenc!=-1 )
+ fprintf( file, "\tUNICODE %04X", sc->unicodeenc );
+ putc('\n',file);
+ }
+ }
+ fclose(file);
+ free(newname);
+}
+
+static int dumpcff(struct alltabs *at,SplineFont *sf,enum fontformat format,
+ FILE *cff) {
+ int ret;
+
+ if ( format==ff_cff ) {
+ AssignTTFGlyph(&at->gi,sf,at->map,true);
+ ret = dumptype2glyphs(sf,at);
+ } else {
+ SFDummyUpCIDs(&at->gi,sf); /* life is easier if we ignore the seperate fonts of a cid keyed fonts and treat it as flat */
+ ret = dumpcidglyphs(sf,at);
+ free(sf->glyphs); sf->glyphs = NULL;
+ sf->glyphcnt = sf->glyphmax = 0;
+ }
+ free( at->gi.bygid );
+
+ if ( !ret )
+ at->error = true;
+ else if ( at->gi.flags & ps_flag_nocffsugar ) {
+ if ( !ttfcopyfile(cff,at->cfff,0,"CFF"))
+ at->error = true;
+ } else {
+ long len;
+ char buffer[80];
+ fprintf(cff,"%%!PS-Adobe-3.0 Resource-FontSet\n");
+ fprintf(cff,"%%%%DocumentNeedResources:ProcSet (FontSetInit)\n");
+ fprintf(cff,"%%%%Title: (FontSet/%s)\n", sf->fontname);
+ fprintf(cff,"%%%%EndComments\n" );
+ fprintf(cff,"%%%%IncludeResource: ProcSet(FontSetInit)\n" );
+ fprintf(cff,"%%%%BeginResource: FontSet(%s)\n", sf->fontname );
+ fprintf(cff,"/FontSetInit /ProcSet findresource begin\n" );
+ fseek(at->cfff,0,SEEK_END);
+ len = ftell(at->cfff);
+ rewind(at->cfff);
+ sprintf( buffer, "/%s %ld StartData\n", sf->fontname, len );
+ fprintf(cff,"%%%%BeginData: %ld Binary Bytes\n", (long) (len+strlen(buffer)) );
+ fputs(buffer,cff);
+ if ( !ttfcopyfile(cff,at->cfff,ftell(cff),"CFF"))
+ at->error = true;
+ fprintf(cff,"\n%%%%EndData\n" );
+ fprintf(cff,"%%%%EndResource\n" );
+ fprintf(cff,"%%%%EOF\n" );
+ }
+return( !at->error );
+}
+
+int _WriteTTFFont(FILE *ttf,SplineFont *sf,enum fontformat format,
+ int32 *bsizes, enum bitmapformat bf,int flags,EncMap *map) {
+ struct alltabs at;
+ char *oldloc;
+ int i;
+
+ oldloc = setlocale(LC_NUMERIC,"C"); /* TrueType probably doesn't need this, but OpenType does for floats in dictionaries */
+ if ( format==ff_otfcid || format== ff_cffcid ) {
+ if ( sf->cidmaster ) sf = sf->cidmaster;
+ } else {
+ if ( sf->subfontcnt!=0 ) sf = sf->subfonts[0];
+ }
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ sf->glyphs[i]->ttf_glyph = -1;
+
+ memset(&at,'\0',sizeof(struct alltabs));
+ at.gi.flags = flags;
+ at.gi.is_ttf = format == ff_ttf || format==ff_ttfsym || format==ff_ttfmacbin || format==ff_ttfdfont;
+ at.applemode = (flags&ttf_flag_applemode)?1:0;
+ at.opentypemode = (flags&ttf_flag_otmode)?1:0;
+ at.msbitmaps = bsizes!=NULL && at.opentypemode;
+ at.applebitmaps = bsizes!=NULL && at.applemode;
+ at.gi.onlybitmaps = format==ff_none;
+
+ if ( bf==bf_sfnt_dfont ) { at.msbitmaps = false; at.applebitmaps=true; at.opentypemode=false; at.gi.onlybitmaps=true;}
+ if ( bf==bf_sfnt_ms ) { at.msbitmaps = true; at.applebitmaps=false; at.applemode=false; at.gi.onlybitmaps=true;}
+ if ( bf==bf_otb ) { at.otbbitmaps = true; at.applebitmaps=at.msbitmaps=false; at.applemode=false; at.gi.onlybitmaps=true;}
+
+ if ( bsizes!=NULL && !at.applebitmaps && !at.otbbitmaps && !at.msbitmaps )
+ at.msbitmaps = true; /* They asked for bitmaps, but no bitmap type selected */
+ at.gi.bsizes = bsizes;
+ at.gi.fixed_width = CIDOneWidth(sf);
+ at.isotf = format==ff_otf || format==ff_otfcid;
+ at.format = format;
+ at.next_strid = 256;
+#ifndef LUA_FF_LIB
+ if ( at.applemode && sf->mm!=NULL && sf->mm->apple &&
+ (format==ff_ttf || format==ff_ttfsym || format==ff_ttfmacbin ||
+ format==ff_ttfdfont) &&
+ MMValid(sf->mm,false)) {
+ at.dovariations = true;
+ at.gi.dovariations = true;
+ sf = sf->mm->normal;
+ }
+#endif
+ at.sf = sf;
+ at.map = map;
+
+ if ( format==ff_cff || format==ff_cffcid ) {
+ dumpcff(&at,sf,format,ttf);
+ } else {
+ if ( initTables(&at,sf,format,bsizes,bf,flags))
+ dumpttf(ttf,&at,format);
+ }
+ setlocale(LC_NUMERIC,oldloc);
+ if ( at.error || ferror(ttf))
+return( 0 );
+
+#ifdef __CygWin
+ /* Modern versions of windows want the execute bit set on a ttf file */
+ /* I've no idea what this corresponds to in windows, nor any idea on */
+ /* how to set it from the windows UI, but this seems to work */
+ {
+ struct stat buf;
+ fstat(fileno(ttf),&buf);
+ fchmod(fileno(ttf),S_IXUSR | buf.st_mode );
+ }
+#endif
+
+return( 1 );
+}
+
+int WriteTTFFont(char *fontname,SplineFont *sf,enum fontformat format,
+ int32 *bsizes, enum bitmapformat bf,int flags,EncMap *map) {
+ FILE *ttf;
+ int ret;
+
+ if (( ttf=fopen(fontname,"wb+"))==NULL )
+return( 0 );
+ ret = _WriteTTFFont(ttf,sf,format,bsizes,bf,flags,map);
+ if ( ret && (flags&ttf_flag_glyphmap) )
+ DumpGlyphToNameMap(fontname,sf);
+ if ( fclose(ttf)==-1 )
+return( 0 );
+return( ret );
+}
+
+struct hexout {
+ FILE *type42;
+ int bytesout;
+};
+
+static void dumphex(struct hexout *hexout,FILE *temp,int length) {
+ int i, ch, ch1;
+
+ if ( length&1 )
+ LogError( _("Table length should not be odd\n") );
+
+ while ( length>65534 ) {
+ dumphex(hexout,temp,65534);
+ length -= 65534;
+ }
+
+ fprintf( hexout->type42, " <\n " );
+ hexout->bytesout = 0;
+ for ( i=0; i<length; ++i ) {
+ ch = getc(temp);
+ if ( ch==EOF )
+ break;
+ if ( hexout->bytesout>=31 ) {
+ fprintf( hexout->type42, "\n " );
+ hexout->bytesout = 0;
+ }
+ ch1 = ch>>4;
+ if ( ch1>=10 )
+ ch1 += 'A'-10;
+ else
+ ch1 += '0';
+ putc(ch1,hexout->type42);
+ ch1 = ch&0xf;
+ if ( ch1>=10 )
+ ch1 += 'A'-10;
+ else
+ ch1 += '0';
+ putc(ch1,hexout->type42);
+ ++hexout->bytesout;
+ }
+ fprintf( hexout->type42, "\n 00\n >\n" );
+}
+
+static void dumptype42(FILE *type42,struct alltabs *at, enum fontformat format) {
+ FILE *temp = tmpfile();
+ struct hexout hexout;
+ int i, length;
+
+ dumpttf(temp,at,format);
+ rewind(temp);
+
+ hexout.type42 = type42;
+ hexout.bytesout = 0;
+
+ /* Resort the tables into file order */
+ qsort(at->tabdir.ordered,at->tabdir.numtab,sizeof(struct taboff *),tcomp2);
+
+ dumphex(&hexout,temp,at->tabdir.ordered[0]->offset);
+
+ for ( i=0; i<at->tabdir.numtab; ++i ) {
+ if ( at->tabdir.ordered[i]->length>65534 && at->tabdir.ordered[i]->tag==CHR('g','l','y','f')) {
+ uint32 last = 0;
+ int j;
+ fseek(temp,at->tabdir.ordered[i]->offset,SEEK_SET);
+ for ( j=0; j<at->maxp.numGlyphs; ++j ) {
+ if ( at->gi.loca[j+1]-last > 65534 ) {
+ dumphex(&hexout,temp,at->gi.loca[j]-last);
+ last = at->gi.loca[j];
+ }
+ }
+ dumphex(&hexout,temp,at->gi.loca[j]-last);
+ } else {
+ if ( i<at->tabdir.numtab-1 )
+ length = at->tabdir.ordered[i+1]->offset-at->tabdir.ordered[i]->offset;
+ else {
+ fseek(temp,0,SEEK_END);
+ length = ftell(temp)-at->tabdir.ordered[i]->offset;
+ }
+ fseek(temp,at->tabdir.ordered[i]->offset,SEEK_SET);
+ dumphex(&hexout,temp,length);
+ }
+ }
+
+ fclose( temp );
+}
+
+int _WriteType42SFNTS(FILE *type42,SplineFont *sf,enum fontformat format,
+ int flags,EncMap *map) {
+ struct alltabs at;
+ char *oldloc;
+ int i;
+
+ oldloc = setlocale(LC_NUMERIC,"C"); /* TrueType probably doesn't need this, but OpenType does for floats in dictionaries */
+ if ( sf->subfontcnt!=0 ) sf = sf->subfonts[0];
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
+ sf->glyphs[i]->ttf_glyph = -1;
+
+ memset(&at,'\0',sizeof(struct alltabs));
+ at.gi.flags = flags;
+ at.applemode = false;
+ at.opentypemode = false;
+ at.msbitmaps = false;
+ at.otbbitmaps = false;
+ at.gi.onlybitmaps = false;
+ at.gi.bsizes = NULL;
+ at.gi.fixed_width = CIDOneWidth(sf);
+ at.isotf = false;
+ at.format = format;
+ at.next_strid = 256;
+ at.sf = sf;
+ at.map = map;
+
+ if ( initTables(&at,sf,format,NULL,bf_none,flags))
+ dumptype42(type42,&at,format);
+ free(at.gi.loca);
+
+ setlocale(LC_NUMERIC,oldloc);
+ if ( at.error || ferror(type42))
+return( 0 );
+
+return( 1 );
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/tottfgpos.c b/Build/source/libs/luafontforge/fontforge/fontforge/tottfgpos.c
new file mode 100644
index 00000000000..8601514db81
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/tottfgpos.c
@@ -0,0 +1,3444 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaeditui.h"
+#include <utype.h>
+#include <ustring.h>
+
+int coverageformatsallowed=3;
+
+#include "ttf.h"
+
+#ifdef LUA_FF_LIB
+extern void gwwv_post_error(char *a, ...);
+extern int unic_isrighttoleft (int);
+#define isrighttoleft unic_isrighttoleft
+#endif
+
+/* This file contains routines to create the otf gpos and gsub tables and their */
+/* attendant subtables */
+
+/* Undocumented fact: ATM (which does kerning for otf fonts in Word) can't handle features with multiple lookups */
+
+/* Undocumented fact: Only one feature with a given tag allowed per script/lang */
+/* So if we have multiple lookups with the same tag they must be merged into */
+/* one feature with many lookups */
+
+/* scripts (for opentype) that I understand */
+ /* see also list in lookups.c mapping script tags to friendly names */
+
+static uint32 scripts[][15] = {
+/* Arabic */ { CHR('a','r','a','b'), 0x0600, 0x06ff, 0xfb50, 0xfdff, 0xfe70, 0xfeff },
+/* Aramaic */ { CHR('a','r','a','m'), 0x820, 0x83f },
+/* Armenian */ { CHR('a','r','m','n'), 0x0530, 0x058f, 0xfb13, 0xfb17 },
+/* Balinese */ { CHR('b','a','l','i'), 0x1b00, 0x1b7f },
+/* Bengali */ { CHR('b','e','n','g'), 0x0980, 0x09ff },
+/* Bliss symb */{ CHR('b','l','i','s'), 0x12200, 0x124ff },
+/* Bopomofo */ { CHR('b','o','p','o'), 0x3100, 0x312f, 0x31a0, 0x31bf },
+/* Braille */ { CHR('b','r','a','i'), 0x2800, 0x28ff },
+/* Buginese */ { CHR('b','u','g','i'), 0x1a00, 0x1a1f },
+/* Buhid */ { CHR('b','u','h','d'), 0x1740, 0x1753 },
+/* Byzantine M*/{ CHR('b','y','z','m'), 0x1d000, 0x1d0ff },
+/* Canadian Syl*/{CHR('c','a','n','s'), 0x1400, 0x167f },
+/* Cherokee */ { CHR('c','h','e','r'), 0x13a0, 0x13ff },
+/* Cirth */ { CHR('c','i','r','t'), 0x12080, 0x120ff },
+/* CJKIdeogra */{ CHR('h','a','n','i'), 0x3300, 0x9fff, 0xf900, 0xfaff, 0x020000, 0x02ffff },
+/* Coptic */ { CHR('c','o','p','t'), 0x2c80, 0x2cff },
+/* Cypriot */ { CHR('c','p','m','n'), 0x10800, 0x1083f },
+/* Cyrillic */ { CHR('c','y','r','l'), 0x0400, 0x052f },
+/* Deseret */ { CHR('d','s','r','t'), 0x10400, 0x1044f },
+/* Devanagari */{ CHR('d','e','v','a'), 0x0900, 0x097f },
+/* Ethiopic */ { CHR('e','t','h','i'), 0x1200, 0x139f },
+/* Georgian */ { CHR('g','e','o','r'), 0x1080, 0x10ff },
+/* Glagolitic */{ CHR('g','l','a','g'), 0x1080, 0x10ff },
+/* Gothic */ { CHR('g','o','t','h'), 0x10330, 0x1034a },
+/* Greek */ { CHR('g','r','e','k'), 0x0370, 0x03ff, 0x1f00, 0x1fff },
+/* Gujarati */ { CHR('g','u','j','r'), 0x0a80, 0x0aff },
+/* Gurmukhi */ { CHR('g','u','r','u'), 0x0a00, 0x0a7f },
+/* Hangul */ { CHR('h','a','n','g'), 0xac00, 0xd7af, 0x3130, 0x319f, 0xffa0, 0xff9f },
+/* Hanunoo */ { CHR('h','a','n','o'), 0x1720, 0x1734 },
+ /* I'm not sure what the difference is between the 'hang' tag and the 'jamo' */
+ /* tag. 'Jamo' is said to be the precomposed forms, but what's 'hang'? */
+/* Hebrew */ { CHR('h','e','b','r'), 0x0590, 0x05ff, 0xfb1e, 0xfb4f },
+#if 0 /* Hiragana used to have its own tag, but has since been merged with katakana */
+/* Hiragana */ { CHR('h','i','r','a'), 0x3040, 0x309f },
+#endif
+/* Hangul Jamo*/{ CHR('j','a','m','o'), 0x1100, 0x11ff, 0x3130, 0x319f, 0xffa0, 0xffdf },
+/* Katakana */ { CHR('k','a','n','a'), 0x3040, 0x30ff, 0xff60, 0xff9f },
+/* Javanese */ { CHR('j','a','v','a'), 0 }, /* MS has a tag, but there is no unicode range */
+/* Khmer */ { CHR('k','h','m','r'), 0x1780, 0x17ff },
+/* Kannada */ { CHR('k','n','d','a'), 0x0c80, 0x0cff },
+/* Kharosthi */ { CHR('k','h','a','r'), 0x10a00, 0x10a5f },
+/* Latin */ { CHR('l','a','t','n'), 0x0041, 0x005a, 0x0061, 0x007a,
+ 0x00c0, 0x02af, 0x1d00, 0x1eff, 0xfb00, 0xfb0f, 0xff00, 0xff5f, 0, 0 },
+/* Lao */ { CHR('l','a','o',' '), 0x0e80, 0x0eff },
+/* Limbu */ { CHR('l','i','m','b'), 0x1900, 0x194f },
+/* Linear A */ { CHR('l','i','n','a'), 0x10180, 0x102cf },
+/* Linear B */ { CHR('l','i','n','b'), 0x10000, 0x100fa },
+/* Malayalam */ { CHR('m','l','y','m'), 0x0d00, 0x0d7f },
+/* Mathematical Alphanumeric Symbols */
+ { CHR('m','a','t','h'), 0x1d400, 0x1d7ff },
+/* Mongolian */ { CHR('m','o','n','g'), 0x1800, 0x18af },
+/* Musical */ { CHR('m','u','s','i'), 0x1d100, 0x1d1ff },
+/* Myanmar */ { CHR('m','y','m','r'), 0x1000, 0x107f },
+/* N'Ko */ { CHR('n','k','o',' '), 0x07c0, 0x07fa },
+/* Ogham */ { CHR('o','g','a','m'), 0x1680, 0x169f },
+/* Old Italic */{ CHR('i','t','a','l'), 0x10300, 0x1031e },
+/* Old Permic */{ CHR('p','e','r','m'), 0x10350, 0x1037f },
+/* Old Persian cuneiform */
+ { CHR('x','p','e','o'), 0x103a0, 0x103df },
+/* Oriya */ { CHR('o','r','y','a'), 0x0b00, 0x0b7f },
+/* Osmanya */ { CHR('o','s','m','a'), 0x10480, 0x104a9 },
+/* Phags-pa */ { CHR('p','h','a','g'), 0xa840, 0xa87f },
+/* Phoenician */{ CHR('p','h','n','x'), 0x10900, 0x1091f },
+/* Pollard */ { CHR('p','l','r','d'), 0x104b0, 0x104d9 },
+/* Runic */ { CHR('r','u','n','r'), 0x16a0, 0x16ff },
+/* Shavian */ { CHR('s','h','a','w'), 0x10450, 0x1047f },
+/* Sinhala */ { CHR('s','i','n','h'), 0x0d80, 0x0dff },
+/* Sumero-Akkadian Cuneiform */
+ { CHR('x','s','u','x'), 0x12000, 0x1236e },
+/* Syloti Nagri */
+ { CHR('s','y','l','o'), 0xa800, 0xa82f },
+/* Syriac */ { CHR('s','y','r','c'), 0x0700, 0x074f },
+/* Tagalog */ { CHR('t','a','g','l'), 0x1700, 0x1714 },
+/* Tagbanwa */ { CHR('t','a','g','b'), 0x1760, 0x1773 },
+/* Tai Le */ { CHR('t','a','l','e'), 0x1950, 0x1974 },
+/* Tai Lu */ { CHR('t','a','l','u'), 0x1980, 0x19df },
+/* Tamil */ { CHR('t','a','m','l'), 0x0b80, 0x0bff },
+/* Telugu */ { CHR('t','e','l','u'), 0x0c00, 0x0c7f },
+/* Tengwar */ { CHR('t','e','n','g'), 0x12000, 0x1207f },
+/* Thaana */ { CHR('t','h','a','a'), 0x0780, 0x07bf },
+/* Thai */ { CHR('t','h','a','i'), 0x0e00, 0x0e7f },
+/* Tibetan */ { CHR('t','i','b','t'), 0x0f00, 0x0fff },
+/* Tifinagh */ { CHR('t','f','n','g'), 0x2d30, 0x2d7f },
+/* Ugaritic */ { CHR('u','g','a','r'), 0x10380, 0x1039d },
+/* Yi */ { CHR('y','i',' ',' '), 0xa000, 0xa4c6 },
+ { 0 }
+};
+
+int ScriptIsRightToLeft(uint32 script) {
+ if ( script==CHR('a','r','a','b') || script==CHR('h','e','b','r') ||
+ script==CHR('c','p','m','n') || script==CHR('k','h','a','r') ||
+ script==CHR('s','y','r','c') || script==CHR('t','h','a','a') ||
+ script==CHR('n','k','o',' '))
+return( true );
+
+return( false );
+}
+
+uint32 ScriptFromUnicode(int u,SplineFont *sf) {
+ int s, k;
+
+ if ( u!=-1 ) {
+ for ( s=0; scripts[s][0]!=0; ++s ) {
+ for ( k=1; scripts[s][k+1]!=0; k += 2 )
+ if ( u>=scripts[s][k] && u<=scripts[s][k+1] )
+ break;
+ if ( scripts[s][k+1]!=0 )
+ break;
+ }
+ if ( scripts[s][0]!=0 ) {
+ extern int use_second_indic_scripts;
+ uint32 script = scripts[s][0];
+ if ( use_second_indic_scripts ) {
+ /* MS has a parallel set of script tags for their new */
+ /* Indic font shaper */
+ if ( script == CHR('b','e','n','g' )) script = CHR('b','n','g','2');
+ else if ( script == CHR('d','e','v','a' )) script = CHR('d','e','v','2');
+ else if ( script == CHR('g','u','j','r' )) script = CHR('g','j','r','2');
+ else if ( script == CHR('g','u','r','u' )) script = CHR('g','u','r','2');
+ else if ( script == CHR('k','n','d','a' )) script = CHR('k','n','d','2');
+ else if ( script == CHR('m','l','y','m' )) script = CHR('m','l','y','2');
+ else if ( script == CHR('o','r','y','a' )) script = CHR('o','r','y','2');
+ else if ( script == CHR('t','a','m','l' )) script = CHR('t','m','l','2');
+ else if ( script == CHR('t','e','l','u' )) script = CHR('t','e','l','2');
+ }
+return( script );
+ }
+ } else if ( sf!=NULL ) {
+ if ( sf->cidmaster!=NULL || sf->subfontcnt!=0 ) {
+ if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
+ if ( strmatch(sf->ordering,"Identity")==0 )
+return( DEFAULT_SCRIPT );
+ else if ( strmatch(sf->ordering,"Korean")==0 )
+return( CHR('h','a','n','g'));
+ else
+return( CHR('h','a','n','i') );
+ }
+ }
+
+return( DEFAULT_SCRIPT );
+}
+
+uint32 SCScriptFromUnicode(SplineChar *sc) {
+ char *pt;
+ PST *pst;
+ SplineFont *sf;
+ int i; unsigned uni;
+ FeatureScriptLangList *features;
+
+ if ( sc==NULL )
+return( DEFAULT_SCRIPT );
+
+ sf = sc->parent;
+ if ( sc->unicodeenc!=-1 )
+return( ScriptFromUnicode( sc->unicodeenc,sf ));
+
+ pt = sc->name;
+ if ( *pt ) for ( ++pt; *pt!='\0' && *pt!='_' && *pt!='.'; ++pt );
+ if ( *pt!='\0' ) {
+ char *str = copyn(sc->name,pt-sc->name);
+ int uni = sf==NULL || sf->fv==NULL ? UniFromName(str,ui_none,&custom) :
+ UniFromName(str,sf->uni_interp,sf->fv->map->enc);
+ free(str);
+ if ( uni!=-1 )
+return( ScriptFromUnicode( uni,sf ));
+ }
+ /* Adobe ligature uniXXXXXXXX */
+ if ( strncmp(sc->name,"uni",3)==0 && sscanf(sc->name+3,"%4x", &uni)==1 )
+return( ScriptFromUnicode( uni,sf ));
+
+ if ( sf==NULL )
+return( DEFAULT_SCRIPT );
+
+ if ( sf->cidmaster ) sf=sf->cidmaster;
+ else if ( sf->mm!=NULL ) sf=sf->mm->normal;
+ for ( i=0; i<2; ++i ) {
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->type == pst_lcaret )
+ continue;
+ for ( features = pst->subtable->lookup->features; features!=NULL; features=features->next ) {
+ if ( features->scripts!=NULL )
+return( features->scripts->script );
+ }
+ }
+ }
+return( ScriptFromUnicode( sc->unicodeenc,sf ));
+}
+
+int SCRightToLeft(SplineChar *sc) {
+
+ if ( sc->unicodeenc>=0x10800 && sc->unicodeenc<=0x10fff )
+return( true ); /* Supplemental Multilingual Plane, RTL scripts */
+ if ( sc->unicodeenc!=-1 && sc->unicodeenc<0x10000 )
+return( isrighttoleft(sc->unicodeenc ));
+
+return( ScriptIsRightToLeft(SCScriptFromUnicode(sc)));
+}
+
+static void GlyphMapFree(SplineChar ***map) {
+ int i;
+
+ if ( map==NULL )
+return;
+ for ( i=0; map[i]!=NULL; ++i )
+ free(map[i]);
+ free(map);
+}
+
+static SplineChar **FindSubs(SplineChar *sc,struct lookup_subtable *sub) {
+ SplineChar *spc[30], **space = spc;
+ int max = sizeof(spc)/sizeof(spc[0]);
+ int cnt=0;
+ char *pt, *start;
+ SplineChar *subssc, **ret;
+ PST *pst;
+
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable==sub ) {
+ pt = pst->u.subs.variant;
+ while ( 1 ) {
+ while ( *pt==' ' ) ++pt;
+ start = pt;
+ pt = strchr(start,' ');
+ if ( pt!=NULL )
+ *pt = '\0';
+ subssc = SFGetChar(sc->parent,-1,start);
+ if ( subssc!=NULL && subssc->ttf_glyph!=-1 ) {
+ if ( cnt>=max ) {
+ if ( spc==space ) {
+ space = galloc((max+=30)*sizeof(SplineChar *));
+ memcpy(space,spc,(max-30)*sizeof(SplineChar *));
+ } else
+ space = grealloc(space,(max+=30)*sizeof(SplineChar *));
+ }
+ space[cnt++] = subssc;
+ }
+ if ( pt==NULL )
+ break;
+ *pt=' ';
+ }
+ }
+ }
+ if ( cnt==0 ) /* Might happen if the substitution names weren't in the font */
+return( NULL );
+ ret = galloc((cnt+1)*sizeof(SplineChar *));
+ memcpy(ret,space,cnt*sizeof(SplineChar *));
+ ret[cnt] = NULL;
+ if ( space!=spc )
+ free(space);
+return( ret );
+}
+
+static SplineChar ***generateMapList(SplineChar **glyphs, struct lookup_subtable *sub) {
+ int cnt;
+ SplineChar *sc;
+ int i;
+ SplineChar ***maps=NULL;
+
+ for ( cnt=0; glyphs[cnt]!=NULL; ++cnt );
+ maps = galloc((cnt+1)*sizeof(SplineChar **));
+ for ( i=0; i<cnt; ++i ) {
+ sc = glyphs[i];
+ maps[i] = FindSubs(sc,sub);
+ }
+ maps[cnt] = NULL;
+return( maps );
+}
+
+void AnchorClassDecompose(SplineFont *sf,AnchorClass *_ac, int classcnt, int *subcnts,
+ SplineChar ***marks,SplineChar ***base,
+ SplineChar ***lig,SplineChar ***mkmk,
+ struct glyphinfo *gi) {
+ /* Run through the font finding all characters with this anchor class */
+ /* (and the cnt-1 classes after it) */
+ /* and distributing in the four possible anchor types */
+ int i,j,k,gid, gmax;
+ struct sclist { int cnt; SplineChar **glyphs; } heads[at_max];
+ AnchorPoint *test;
+ AnchorClass *ac;
+
+ memset(heads,0,sizeof(heads));
+ memset(subcnts,0,classcnt*sizeof(int));
+ memset(marks,0,classcnt*sizeof(SplineChar **));
+ gmax = gi==NULL ? sf->glyphcnt : gi->gcnt;
+ for ( j=0; j<2; ++j ) {
+ for ( i=0; i<gmax; ++i ) if ( (gid = gi==NULL ? i : gi->bygid[i])!=-1 && sf->glyphs[gid]!=NULL ) {
+ for ( ac = _ac, k=0; k<classcnt; ac=ac->next ) if ( ac->matches ) {
+ for ( test=sf->glyphs[gid]->anchor; test!=NULL ; test=test->next ) {
+ if ( test->anchor==ac ) {
+ if ( test->type==at_mark ) {
+ if ( j )
+ marks[k][subcnts[k]] = sf->glyphs[gid];
+ ++subcnts[k];
+ if ( ac->type!=act_mkmk )
+ break;
+ } else if ( test->type!=at_centry && test->type!=at_cexit ) {
+ if ( heads[test->type].glyphs!=NULL ) {
+ /* If we have multiple mark classes, we may use the same base glyph */
+ /* with more than one mark class. But it should only appear once in */
+ /* the output */
+ if ( heads[test->type].cnt==0 ||
+ heads[test->type].glyphs[heads[test->type].cnt-1]!=sf->glyphs[gid] ) {
+ heads[test->type].glyphs[heads[test->type].cnt] = sf->glyphs[gid];
+ ++heads[test->type].cnt;
+ }
+ } else
+ ++heads[test->type].cnt;
+ if ( ac->type!=act_mkmk )
+ break;
+ }
+ }
+ }
+ ++k;
+ }
+ }
+ if ( j==1 )
+ break;
+ for ( i=0; i<4; ++i )
+ if ( heads[i].cnt!=0 ) {
+ heads[i].glyphs = galloc((heads[i].cnt+1)*sizeof(SplineChar *));
+ /* I used to set glyphs[cnt] to NULL here. But it turns out */
+ /* cnt may be an overestimate on the first pass. So we can */
+ /* only set it at the end of the second pass */
+ heads[i].cnt = 0;
+ }
+ for ( k=0; k<classcnt; ++k ) if ( subcnts[k]!=0 ) {
+ marks[k] = galloc((subcnts[k]+1)*sizeof(SplineChar *));
+ marks[k][subcnts[k]] = NULL;
+ subcnts[k] = 0;
+ }
+ }
+ for ( i=0; i<4; ++i )
+ if ( heads[i].glyphs!=NULL )
+ heads[i].glyphs[heads[i].cnt] = NULL;
+
+ *base = heads[at_basechar].glyphs;
+ *lig = heads[at_baselig].glyphs;
+ *mkmk = heads[at_basemark].glyphs;
+}
+
+SplineChar **EntryExitDecompose(SplineFont *sf,AnchorClass *ac,struct glyphinfo *gi) {
+ /* Run through the font finding all characters with this anchor class */
+ int i,j, cnt, gmax, gid;
+ SplineChar **array;
+ AnchorPoint *test;
+
+ array=NULL;
+ gmax = gi==NULL ? sf->glyphcnt : gi->gcnt;
+ for ( j=0; j<2; ++j ) {
+ cnt = 0;
+ for ( i=0; i<gmax; ++i ) if ( (gid = gi==NULL ? i : gi->bygid[i])!=-1 && sf->glyphs[gid]!=NULL ) {
+ for ( test=sf->glyphs[gid]->anchor; test!=NULL && test->anchor!=ac; test=test->next );
+ if ( test!=NULL && (test->type==at_centry || test->type==at_cexit )) {
+ if ( array!=NULL )
+ array[cnt] = sf->glyphs[gid];
+ ++cnt;
+ }
+ }
+ if ( cnt==0 )
+return( NULL );
+ if ( j==1 )
+ break;
+ array = galloc((cnt+1)*sizeof(SplineChar *));
+ array[cnt] = NULL;
+ }
+return( array );
+}
+
+static void AnchorGuessContext(SplineFont *sf,struct alltabs *at) {
+ int i;
+ int maxbase=0, maxmark=0, basec, markc;
+ AnchorPoint *ap;
+ int hascursive = 0;
+
+ /* the order in which we examine the glyphs does not matter here, so */
+ /* we needn't add the complexity running though in gid order */
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i] ) {
+ basec = markc = 0;
+ for ( ap = sf->glyphs[i]->anchor; ap!=NULL; ap=ap->next )
+ if ( ap->type==at_basemark )
+ ++markc;
+ else if ( ap->type==at_basechar || ap->type==at_baselig )
+ ++basec;
+ else if ( ap->type==at_centry )
+ hascursive = true;
+ if ( basec>maxbase ) maxbase = basec;
+ if ( markc>maxmark ) maxmark = markc;
+ }
+
+ if ( maxbase*(maxmark+1)>at->os2.maxContext )
+ at->os2.maxContext = maxbase*(maxmark+1);
+ if ( hascursive && at->os2.maxContext<2 )
+ at->os2.maxContext=2;
+}
+
+static void dumpcoveragetable(FILE *gpos,SplineChar **glyphs) {
+ int i, last = -2, range_cnt=0, start;
+ /* the glyph list should already be sorted */
+ /* figure out whether it is better (smaller) to use an array of glyph ids */
+ /* or a set of glyph id ranges */
+
+ for ( i=0; glyphs[i]!=NULL; ++i ) {
+ if ( glyphs[i]->ttf_glyph<=last )
+ IError("Glyphs must be ordered when creating coverage table");
+ if ( glyphs[i]->ttf_glyph!=last+1 )
+ ++range_cnt;
+ last = glyphs[i]->ttf_glyph;
+ }
+ /* I think Windows will only accept format 2 coverage tables? */
+ if ( !(coverageformatsallowed&2) || ((coverageformatsallowed&1) && i<=3*range_cnt )) {
+ /* We use less space with a list of glyphs than with a set of ranges */
+ putshort(gpos,1); /* Coverage format=1 => glyph list */
+ putshort(gpos,i); /* count of glyphs */
+ for ( i=0; glyphs[i]!=NULL; ++i )
+ putshort(gpos,glyphs[i]->ttf_glyph); /* array of glyph IDs */
+ } else {
+ putshort(gpos,2); /* Coverage format=2 => range list */
+ putshort(gpos,range_cnt); /* count of ranges */
+ last = -2; start = -2; /* start is a index in our glyph array, last is ttf_glyph */
+ for ( i=0; glyphs[i]!=NULL; ++i ) {
+ if ( glyphs[i]->ttf_glyph!=last+1 ) {
+ if ( last!=-2 ) {
+ putshort(gpos,glyphs[start]->ttf_glyph); /* start glyph ID */
+ putshort(gpos,last); /* end glyph ID */
+ putshort(gpos,start); /* coverage index of start glyph */
+ }
+ start = i;
+ }
+ last = glyphs[i]->ttf_glyph;
+ }
+ if ( last!=-2 ) {
+ putshort(gpos,glyphs[start]->ttf_glyph); /* start glyph ID */
+ putshort(gpos,last); /* end glyph ID */
+ putshort(gpos,start); /* coverage index of start glyph */
+ }
+ }
+}
+
+static int sc_ttf_order( const void *_sc1, const void *_sc2) {
+ const SplineChar *sc1 = *(const SplineChar **) _sc1, *sc2 = *(const SplineChar **) _sc2;
+return( sc1->ttf_glyph - sc2->ttf_glyph );
+}
+
+static SplineChar **SFOrderedGlyphsWithPSTinSubtable(SplineFont *sf,struct lookup_subtable *sub) {
+ SplineChar **glyphs = SFGlyphsWithPSTinSubtable(sf,sub);
+ int cnt, i, k;
+ if ( glyphs==NULL )
+return( NULL );
+ for ( cnt=0; glyphs[cnt]!=NULL; ++cnt);
+ qsort(glyphs,cnt,sizeof(SplineChar *),sc_ttf_order);
+ if ( glyphs[0]->ttf_glyph==-1 ) {
+ /* Not sure if this can happen, but it's easy to fix */
+ for ( k=0; k<cnt && glyphs[k]->ttf_glyph==-1; ++k);
+ for ( i=0; i<=cnt-k; ++i )
+ glyphs[i] = glyphs[i+k];
+ }
+return( glyphs );
+}
+
+SplineChar **SFGlyphsFromNames(SplineFont *sf,char *names) {
+ int cnt, ch;
+ char *pt, *end;
+ SplineChar *sc, **glyphs;
+
+ cnt = 0;
+ for ( pt = names; *pt; pt = end+1 ) {
+ ++cnt;
+ end = strchr(pt,' ');
+ if ( end==NULL )
+ break;
+ }
+
+ glyphs = galloc((cnt+1)*sizeof(SplineChar *));
+ cnt = 0;
+ for ( pt = names; *pt; pt = end+1 ) {
+ end = strchr(pt,' ');
+ if ( end==NULL )
+ end = pt+strlen(pt);
+ ch = *end;
+ *end = '\0';
+ sc = SFGetChar(sf,-1,pt);
+ if ( sc!=NULL && sc->ttf_glyph!=-1 )
+ glyphs[cnt++] = sc;
+ *end = ch;
+ if ( ch=='\0' )
+ break;
+ }
+ glyphs[cnt] = NULL;
+return( glyphs );
+}
+
+static SplineChar **OrderedGlyphsFromNames(SplineFont *sf,char *names) {
+ SplineChar **glyphs = SFGlyphsFromNames(sf,names);
+ int i,j;
+
+ if ( glyphs==NULL || glyphs[0]==NULL )
+return( glyphs );
+
+ for ( i=0; glyphs[i+1]!=NULL; ++i ) for ( j=i+1; glyphs[j]!=NULL; ++j ) {
+ if ( glyphs[i]->ttf_glyph > glyphs[j]->ttf_glyph ) {
+ SplineChar *sc = glyphs[i];
+ glyphs[i] = glyphs[j];
+ glyphs[j] = sc;
+ }
+ }
+ if ( glyphs[0]!=NULL ) { /* Glyphs should not appear twice in the name list, just just in case they do... */
+ for ( i=0; glyphs[i+1]!=NULL; ++i ) {
+ if ( glyphs[i]==glyphs[i+1] ) {
+ for ( j=i+1; glyphs[j]!=NULL; ++j )
+ glyphs[j] = glyphs[j+1];
+ }
+ }
+ }
+return( glyphs );
+}
+
+static void gposvrmaskeddump(FILE *gpos,int vf1,int mask,int offset) {
+ if ( vf1&1 ) putshort(gpos,mask&1 ? offset : 0 );
+ if ( vf1&2 ) putshort(gpos,mask&2 ? offset : 0 );
+ if ( vf1&4 ) putshort(gpos,mask&4 ? offset : 0 );
+ if ( vf1&8 ) putshort(gpos,mask&8 ? offset : 0 );
+}
+
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+static int devtaboffsetsize(DeviceTable *dt) {
+ int type = 1, i;
+
+ for ( i=dt->last_pixel_size-dt->first_pixel_size; i>=0; --i ) {
+ if ( dt->corrections[i]>=8 || dt->corrections[i]<-8 )
+return( 3 );
+ else if ( dt->corrections[i]>=2 || dt->corrections[i]<-2 )
+ type = 2;
+ }
+return( type );
+}
+
+static void dumpgposdevicetable(FILE *gpos,DeviceTable *dt) {
+ int type;
+ int i,cnt,b;
+
+ if ( dt==NULL || dt->corrections==NULL )
+return;
+ type = devtaboffsetsize(dt);
+ putshort(gpos,dt->first_pixel_size);
+ putshort(gpos,dt->last_pixel_size );
+ putshort(gpos,type);
+ cnt = dt->last_pixel_size - dt->first_pixel_size + 1;
+ if ( type==3 ) {
+ for ( i=0; i<cnt; ++i )
+ putc(dt->corrections[i],gpos);
+ if ( cnt&1 )
+ putc(0,gpos);
+ } else if ( type==2 ) {
+ for ( i=0; i<cnt; i+=4 ) {
+ int val = 0;
+ for ( b=0; b<4 && i+b<cnt; ++b )
+ val |= (dt->corrections[i+b]&0x000f)<<(12-b*4);
+ putshort(gpos,val);
+ }
+ } else {
+ for ( i=0; i<cnt; i+=8 ) {
+ int val = 0;
+ for ( b=0; b<8 && i+b<cnt; ++b )
+ val |= (dt->corrections[i+b]&0x0003)<<(14-b*2);
+ putshort(gpos,val);
+ }
+ }
+}
+
+static int DevTabLen(DeviceTable *dt) {
+ int type;
+ int cnt;
+
+ if ( dt==NULL || dt->corrections==NULL )
+return( 0 );
+ cnt = dt->last_pixel_size - dt->first_pixel_size + 1;
+ type = devtaboffsetsize(dt);
+ if ( type==3 )
+ cnt = (cnt+1)/2;
+ else if ( type==2 )
+ cnt = (cnt+3)/4;
+ else
+ cnt = (cnt+7)/8;
+ cnt += 3; /* first, last, type */
+return( sizeof(uint16)*cnt );
+}
+
+static int ValDevTabLen(ValDevTab *vdt) {
+
+ if ( vdt==NULL )
+return( 0 );
+
+return( DevTabLen(&vdt->xadjust) + DevTabLen(&vdt->yadjust) +
+ DevTabLen(&vdt->xadv) + DevTabLen(&vdt->yadv) );
+}
+
+static int gposdumpvaldevtab(FILE *gpos,ValDevTab *vdt,int bits,int next_dev_tab ) {
+
+ if ( bits&0x10 ) {
+ if ( vdt==NULL || vdt->xadjust.corrections==NULL )
+ putshort(gpos,0);
+ else {
+ putshort(gpos,next_dev_tab);
+ next_dev_tab += DevTabLen(&vdt->xadjust);
+ }
+ }
+ if ( bits&0x20 ) {
+ if ( vdt==NULL || vdt->yadjust.corrections==NULL )
+ putshort(gpos,0);
+ else {
+ putshort(gpos,next_dev_tab);
+ next_dev_tab += DevTabLen(&vdt->yadjust);
+ }
+ }
+ if ( bits&0x40 ) {
+ if ( vdt==NULL || vdt->xadv.corrections==NULL )
+ putshort(gpos,0);
+ else {
+ putshort(gpos,next_dev_tab);
+ next_dev_tab += DevTabLen(&vdt->xadv);
+ }
+ }
+ if ( bits&0x80 ) {
+ if ( vdt==NULL || vdt->yadv.corrections==NULL )
+ putshort(gpos,0);
+ else {
+ putshort(gpos,next_dev_tab);
+ next_dev_tab += DevTabLen(&vdt->yadv);
+ }
+ }
+return( next_dev_tab );
+}
+
+static int gposmaskeddumpdevtab(FILE *gpos,DeviceTable *dt,int bits,int mask,
+ int next_dev_tab ) {
+
+ if ( bits&0x10 ) {
+ if ( !(mask&0x10) || dt==NULL )
+ putshort(gpos,0);
+ else {
+ putshort(gpos,next_dev_tab);
+ next_dev_tab += DevTabLen(dt);
+ }
+ }
+ if ( bits&0x20 ) {
+ if ( !(mask&0x20) || dt==NULL )
+ putshort(gpos,0);
+ else {
+ putshort(gpos,next_dev_tab);
+ next_dev_tab += DevTabLen(dt);
+ }
+ }
+ if ( bits&0x40 ) {
+ if ( !(mask&0x40) || dt==NULL )
+ putshort(gpos,0);
+ else {
+ putshort(gpos,next_dev_tab);
+ next_dev_tab += DevTabLen(dt);
+ }
+ }
+ if ( bits&0x80 ) {
+ if ( !(mask&0x80) || dt==NULL )
+ putshort(gpos,0);
+ else {
+ putshort(gpos,next_dev_tab);
+ next_dev_tab += DevTabLen(dt);
+ }
+ }
+return( next_dev_tab );
+}
+
+static int DevTabsSame(DeviceTable *dt1, DeviceTable *dt2) {
+ DeviceTable _dt;
+ int i;
+
+ if ( dt1==NULL && dt2==NULL )
+return( true );
+ if ( dt1==NULL ) {
+ memset(&_dt,0,sizeof(_dt));
+ dt1 = &_dt;
+ }
+ if ( dt2==NULL ) {
+ memset(&_dt,0,sizeof(_dt));
+ dt2 = &_dt;
+ }
+ if ( dt1->corrections==NULL && dt2->corrections==NULL )
+return( true );
+ if ( dt1->corrections==NULL || dt2->corrections==NULL )
+return( false );
+ if ( dt1->first_pixel_size!=dt2->first_pixel_size ||
+ dt1->last_pixel_size!=dt2->last_pixel_size )
+return( false );
+ for ( i=dt2->last_pixel_size-dt1->first_pixel_size; i>=0; --i )
+ if ( dt1->corrections[i]!=dt2->corrections[i] )
+return( false );
+
+return( true );
+}
+
+static int ValDevTabsSame(ValDevTab *vdt1, ValDevTab *vdt2) {
+ ValDevTab _vdt;
+
+ if ( vdt1==NULL && vdt2==NULL )
+return( true );
+ if ( vdt1==NULL ) {
+ memset(&_vdt,0,sizeof(_vdt));
+ vdt1 = &_vdt;
+ }
+ if ( vdt2==NULL ) {
+ memset(&_vdt,0,sizeof(_vdt));
+ vdt2 = &_vdt;
+ }
+return( DevTabsSame(&vdt1->xadjust,&vdt2->xadjust) &&
+ DevTabsSame(&vdt1->yadjust,&vdt2->yadjust) &&
+ DevTabsSame(&vdt1->xadv,&vdt2->xadv) &&
+ DevTabsSame(&vdt1->yadv,&vdt2->yadv) );
+}
+#endif
+
+static void dumpGPOSsimplepos(FILE *gpos,SplineFont *sf,struct lookup_subtable *sub ) {
+ int cnt, cnt2;
+ int32 coverage_pos, end;
+ PST *pst, *first=NULL;
+ int bits = 0, same=true;
+ SplineChar **glyphs;
+
+ glyphs = SFOrderedGlyphsWithPSTinSubtable(sf,sub);
+ for ( cnt=cnt2=0; glyphs[cnt]!=NULL; ++cnt) {
+ for ( pst=glyphs[cnt]->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable==sub && pst->type==pst_position ) {
+ if ( first==NULL ) first = pst;
+ else if ( same ) {
+ if ( first->u.pos.xoff!=pst->u.pos.xoff ||
+ first->u.pos.yoff!=pst->u.pos.yoff ||
+ first->u.pos.h_adv_off!=pst->u.pos.h_adv_off ||
+ first->u.pos.v_adv_off!=pst->u.pos.v_adv_off )
+ same = false;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( !ValDevTabsSame(pst->u.pos.adjust,first->u.pos.adjust))
+ same = false;
+#endif
+ }
+ if ( pst->u.pos.xoff!=0 ) bits |= 1;
+ if ( pst->u.pos.yoff!=0 ) bits |= 2;
+ if ( pst->u.pos.h_adv_off!=0 ) bits |= 4;
+ if ( pst->u.pos.v_adv_off!=0 ) bits |= 8;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( pst->u.pos.adjust!=NULL ) {
+ if ( pst->u.pos.adjust->xadjust.corrections!=NULL ) bits |= 0x10;
+ if ( pst->u.pos.adjust->yadjust.corrections!=NULL ) bits |= 0x20;
+ if ( pst->u.pos.adjust->xadv.corrections!=NULL ) bits |= 0x40;
+ if ( pst->u.pos.adjust->yadv.corrections!=NULL ) bits |= 0x80;
+ }
+#endif
+ ++cnt2;
+ break;
+ }
+ }
+ }
+ if ( bits==0 ) bits=1;
+ if ( cnt!=cnt2 )
+ IError( "Count mismatch in dumpGPOSsimplepos#1 %d vs %d\n", cnt, cnt2 );
+
+ putshort(gpos,same?1:2); /* 1 means all value records same */
+ coverage_pos = ftell(gpos);
+ putshort(gpos,0); /* offset to coverage table */
+ putshort(gpos,bits);
+ if ( same ) {
+ if ( bits&1 ) putshort(gpos,first->u.pos.xoff);
+ if ( bits&2 ) putshort(gpos,first->u.pos.yoff);
+ if ( bits&4 ) putshort(gpos,first->u.pos.h_adv_off);
+ if ( bits&8 ) putshort(gpos,first->u.pos.v_adv_off);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( bits&0xf0 ) {
+ int next_dev_tab = ftell(gpos)-coverage_pos+2+
+ sizeof(int16)*((bits&0x10?1:0) + (bits&0x20?1:0) + (bits&0x40?1:0) + (bits&0x80?1:0));
+ if ( bits&0x10 ) { putshort(gpos,next_dev_tab); next_dev_tab += DevTabLen(&first->u.pos.adjust->xadjust); }
+ if ( bits&0x20 ) { putshort(gpos,next_dev_tab); next_dev_tab += DevTabLen(&first->u.pos.adjust->yadjust); }
+ if ( bits&0x40 ) { putshort(gpos,next_dev_tab); next_dev_tab += DevTabLen(&first->u.pos.adjust->xadv); }
+ if ( bits&0x80 ) { putshort(gpos,next_dev_tab); next_dev_tab += DevTabLen(&first->u.pos.adjust->yadv); }
+ if ( bits&0x10 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->xadjust);
+ if ( bits&0x20 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->yadjust);
+ if ( bits&0x40 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->xadv);
+ if ( bits&0x80 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->yadv);
+ if ( next_dev_tab!=ftell(gpos)-coverage_pos+2 )
+ IError( "Device Table offsets wrong in simple positioning 2");
+ }
+#endif
+ } else {
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ int vr_size =
+ sizeof(int16)*((bits&0x1?1:0) + (bits&0x2?1:0) + (bits&0x4?1:0) + (bits&0x8?1:0) +
+ (bits&0x10?1:0) + (bits&0x20?1:0) + (bits&0x40?1:0) + (bits&0x80?1:0));
+ int next_dev_tab = ftell(gpos)-coverage_pos+2+2+vr_size*cnt;
+#endif
+ putshort(gpos,cnt);
+ for ( cnt2 = 0; glyphs[cnt2]!=NULL; ++cnt2 ) {
+ for ( pst=glyphs[cnt2]->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable==sub && pst->type==pst_position ) {
+ if ( bits&1 ) putshort(gpos,pst->u.pos.xoff);
+ if ( bits&2 ) putshort(gpos,pst->u.pos.yoff);
+ if ( bits&4 ) putshort(gpos,pst->u.pos.h_adv_off);
+ if ( bits&8 ) putshort(gpos,pst->u.pos.v_adv_off);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ next_dev_tab = gposdumpvaldevtab(gpos,pst->u.pos.adjust,bits,
+ next_dev_tab);
+#endif
+ break;
+ }
+ }
+ }
+ if ( cnt!=cnt2 )
+ IError( "Count mismatch in dumpGPOSsimplepos#3 %d vs %d\n", cnt, cnt2 );
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( bits&0xf0 ) {
+ for ( cnt2 = 0; glyphs[cnt2]!=NULL; ++cnt2 ) {
+ for ( pst=glyphs[cnt2]->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable==sub && pst->type==pst_position ) {
+ if ( bits&0x10 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->xadjust);
+ if ( bits&0x20 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->yadjust);
+ if ( bits&0x40 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->xadv);
+ if ( bits&0x80 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->yadv);
+ }
+ }
+ }
+ }
+ if ( next_dev_tab!=ftell(gpos)-coverage_pos+2 )
+ IError( "Device Table offsets wrong in simple positioning 2");
+#endif
+ }
+ end = ftell(gpos);
+ fseek(gpos,coverage_pos,SEEK_SET);
+ putshort(gpos,end-coverage_pos+2);
+ fseek(gpos,end,SEEK_SET);
+ dumpcoveragetable(gpos,glyphs);
+ fseek(gpos,0,SEEK_END);
+ free(glyphs);
+}
+
+struct sckppst {
+ uint16 samewas;
+ uint16 devtablen;
+ uint16 tot;
+ uint8 isv;
+ uint8 subtable_too_big;
+/* The first few fields are only meaningful in the first structure in the array*/
+/* and provide information about the entire rest of the array */
+ uint16 other_gid;
+ SplineChar *sc;
+ KernPair *kp;
+ PST *pst;
+};
+
+static int cmp_gid( const void *_s1, const void *_s2 ) {
+ const struct sckppst *s1 = _s1, *s2 = _s2;
+return( ((int) s1->other_gid) - ((int) s2->other_gid) );
+}
+
+static void dumpGPOSpairpos(FILE *gpos,SplineFont *sf,struct lookup_subtable *sub) {
+ int cnt;
+ int32 coverage_pos, offset_pos, end, start, pos;
+ PST *pst;
+ KernPair *kp;
+ int vf1 = 0, vf2=0, i, j, k, tot, bit_cnt, v;
+ int start_cnt, end_cnt;
+ int chunk_cnt, chunk_max;
+ SplineChar *sc, **glyphs, *gtemp;
+ int isr2l = -1;
+ struct sckppst **seconds;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ int devtablen;
+#endif
+
+ /* Figure out all the data we need. First the glyphs with kerning info */
+ /* then the glyphs to which they kern, and by how much */
+ glyphs = SFOrderedGlyphsWithPSTinSubtable(sf,sub);
+ for ( cnt=0; glyphs[cnt]!=NULL; ++cnt);
+ seconds = galloc(cnt*sizeof(struct sckppst));
+ for ( cnt=0; glyphs[cnt]!=NULL; ++cnt) {
+ for ( k=0; k<2; ++k ) {
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ devtablen = 0;
+#endif
+ tot = 0;
+ for ( pst=glyphs[cnt]->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->subtable==sub && pst->type==pst_pair &&
+ (sc = SFGetChar(sf,-1,pst->u.pair.paired))!=NULL &&
+ sc->ttf_glyph!=-1 ) {
+ if ( k ) {
+ seconds[cnt][tot].sc = sc;
+ seconds[cnt][tot].other_gid = sc->ttf_glyph;
+ seconds[cnt][tot].pst = pst;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ devtablen += ValDevTabLen(pst->u.pair.vr[0].adjust) +
+ ValDevTabLen(pst->u.pair.vr[1].adjust);
+#endif
+ }
+ ++tot;
+ }
+ }
+ for ( v=0; v<2; ++v ) {
+ for ( kp = v ? glyphs[cnt]->vkerns : glyphs[cnt]->kerns; kp!=NULL; kp=kp->next ) {
+ if ( kp->sc->ttf_glyph!=-1 ) {
+ if ( k ) {
+ seconds[cnt][tot].other_gid = kp->sc->ttf_glyph;
+ seconds[cnt][tot].sc = kp->sc;
+ seconds[cnt][tot].kp = kp;
+ seconds[cnt][tot].isv = v;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ devtablen += DevTabLen(kp->adjust);
+#endif
+ }
+ ++tot;
+ }
+ }
+ }
+ if ( k==0 ) {
+ seconds[cnt] = gcalloc(tot+1,sizeof(struct sckppst));
+ } else {
+ qsort(seconds[cnt],tot,sizeof(struct sckppst),cmp_gid);
+ seconds[cnt][0].tot = tot;
+ /* Devtablen is 0 unless we are configured for device tables */
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ seconds[cnt][0].devtablen = devtablen;
+#endif
+ seconds[cnt][0].samewas = 0xffff;
+ }
+ }
+ }
+
+ /* Some fonts do a primitive form of class based kerning, several glyphs */
+ /* can share the same list of second glyphs & offsets */
+ for ( cnt=0; glyphs[cnt]!=NULL; ++cnt) {
+ struct sckppst *test = seconds[cnt], *test2;
+ for ( i=cnt-1; i>=0; --i ) {
+ test2 = seconds[i];
+ if ( test[0].tot != test2[0].tot )
+ continue;
+ for ( j=test[0].tot-1; j>=0; --j ) {
+ if ( test[j].other_gid != test2[j].other_gid )
+ break;
+ if ( test[j].kp!=NULL && test2[j].kp!=NULL &&
+ test[j].kp->off == test2[j].kp->off
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ && DevTabsSame(test[j].kp->adjust,test2[j].kp->adjust)
+#endif
+ )
+ /* So far, so good */;
+ else if ( test[j].pst!=NULL && test2[j].pst!=NULL &&
+ test[j].pst->u.pair.vr[0].xoff == test2[j].pst->u.pair.vr[0].xoff &&
+ test[j].pst->u.pair.vr[0].yoff == test2[j].pst->u.pair.vr[0].yoff &&
+ test[j].pst->u.pair.vr[0].h_adv_off == test2[j].pst->u.pair.vr[0].h_adv_off &&
+ test[j].pst->u.pair.vr[0].v_adv_off == test2[j].pst->u.pair.vr[0].v_adv_off &&
+ test[j].pst->u.pair.vr[1].xoff == test2[j].pst->u.pair.vr[1].xoff &&
+ test[j].pst->u.pair.vr[1].yoff == test2[j].pst->u.pair.vr[1].yoff &&
+ test[j].pst->u.pair.vr[1].h_adv_off == test2[j].pst->u.pair.vr[1].h_adv_off &&
+ test[j].pst->u.pair.vr[1].v_adv_off == test2[j].pst->u.pair.vr[1].v_adv_off
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ && ValDevTabsSame(test[j].pst->u.pair.vr[0].adjust,test2[j].pst->u.pair.vr[0].adjust)
+ && ValDevTabsSame(test[j].pst->u.pair.vr[1].adjust,test2[j].pst->u.pair.vr[1].adjust)
+#endif
+ )
+ /* That's ok too. */;
+ else
+ break;
+ }
+ if ( j>=0 )
+ continue;
+ test2[0].samewas = j;
+ break;
+ }
+ }
+
+ /* Ok, how many offsets must we output? Normall kerning will just use */
+ /* one offset (with perhaps a device table), but the standard allows */
+ /* us to adjust 8 different values (with 8 different device tables) */
+ /* Find out which we need */
+ for ( cnt=0; glyphs[cnt]!=NULL; ++cnt) {
+ for ( tot=0 ; tot<seconds[cnt][0].tot; ++tot ) {
+ if ( (pst=seconds[cnt][tot].pst)!=NULL ) {
+ if ( pst->subtable==sub && pst->type==pst_pair ) {
+ if ( pst->u.pair.vr[0].xoff!=0 ) vf1 |= 1;
+ if ( pst->u.pair.vr[0].yoff!=0 ) vf1 |= 2;
+ if ( pst->u.pair.vr[0].h_adv_off!=0 ) vf1 |= 4;
+ if ( pst->u.pair.vr[0].v_adv_off!=0 ) vf1 |= 8;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( pst->u.pair.vr[0].adjust!=NULL ) {
+ if ( pst->u.pair.vr[0].adjust->xadjust.corrections!=NULL ) vf1 |= 0x10;
+ if ( pst->u.pair.vr[0].adjust->yadjust.corrections!=NULL ) vf1 |= 0x20;
+ if ( pst->u.pair.vr[0].adjust->xadv.corrections!=NULL ) vf1 |= 0x40;
+ if ( pst->u.pair.vr[0].adjust->yadv.corrections!=NULL ) vf1 |= 0x80;
+ }
+#endif
+ if ( pst->u.pair.vr[1].xoff!=0 ) vf2 |= 1;
+ if ( pst->u.pair.vr[1].yoff!=0 ) vf2 |= 2;
+ if ( pst->u.pair.vr[1].h_adv_off!=0 ) vf2 |= 4;
+ if ( pst->u.pair.vr[1].v_adv_off!=0 ) vf2 |= 8;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( pst->u.pair.vr[1].adjust!=NULL ) {
+ if ( pst->u.pair.vr[1].adjust->xadjust.corrections!=NULL ) vf2 |= 0x10;
+ if ( pst->u.pair.vr[1].adjust->yadjust.corrections!=NULL ) vf2 |= 0x20;
+ if ( pst->u.pair.vr[1].adjust->xadv.corrections!=NULL ) vf2 |= 0x40;
+ if ( pst->u.pair.vr[1].adjust->yadv.corrections!=NULL ) vf2 |= 0x80;
+ }
+#endif
+ }
+ }
+ if ( (kp = seconds[cnt][tot].kp)!=NULL ) {
+ int mask = 0, mask2=0;
+ if ( !seconds[cnt][tot].isv && isr2l==-1 ) {
+ SplineChar *sc = seconds[cnt][tot].sc;
+ int known_r2l = SCRightToLeft(sc);
+ if ( known_r2l )
+ isr2l = true;
+ else if ( SCScriptFromUnicode(sc)== DEFAULT_SCRIPT )
+ continue;
+ else
+ isr2l = false;
+ }
+ if ( seconds[cnt][tot].isv )
+ mask = 0x0008;
+ else if ( isr2l )
+ mask2 = 0x0004;
+ else
+ mask = 0x0004;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( kp->adjust!=NULL ) {
+ mask |= mask<<4;
+ mask2 |= mask2<<4;
+ }
+#endif
+ vf1 |= mask;
+ vf2 |= mask2;
+ }
+ }
+ }
+ if ( isr2l==-1 ) isr2l = 0;
+ if ( vf1==0 && vf2==0 ) vf1=1;
+ bit_cnt = 0;
+ for ( i=0; i<8; ++i ) {
+ if ( vf1&(1<<i) ) ++bit_cnt;
+ if ( vf2&(1<<i) ) ++bit_cnt;
+ }
+
+ chunk_max = chunk_cnt = 0;
+ for ( start_cnt=0; start_cnt<cnt; start_cnt=end_cnt ) {
+ int len = 5*2;
+ for ( end_cnt=start_cnt; end_cnt<cnt; ++end_cnt ) {
+ int glyph_len = 2; /* For the glyph's offset */
+ if ( seconds[end_cnt][0].samewas==0xffff || seconds[end_cnt][0].samewas<start_cnt )
+ glyph_len += (bit_cnt*2+2)*seconds[end_cnt][0].tot +
+ seconds[end_cnt][0].devtablen;
+ if ( glyph_len>65535 && end_cnt==start_cnt ) {
+ LogError(_("Lookup subtable %s contains a glyph %s whose kerning information takes up more than 64k bytes\n"),
+ sub->subtable_name, glyphs[start_cnt]->name );
+ len += glyph_len;
+ } else if ( len+glyph_len>65535 ) {
+ if( start_cnt==0 )
+ LogError(_("Lookup subtable %s had to be split into several subtables\nbecause it was too big.\n"),
+ sub->subtable_name );
+ break;
+ } else
+ len += glyph_len;
+ }
+ if ( start_cnt!=0 || end_cnt!=cnt ) {
+ if ( chunk_cnt>=chunk_max )
+ sub->extra_subtables = grealloc(sub->extra_subtables,((chunk_max+=10)+1)*sizeof(uint32));
+ sub->extra_subtables[chunk_cnt++] = ftell(gpos);
+ sub->extra_subtables[chunk_cnt] = -1;
+ }
+
+ start = ftell(gpos);
+ putshort(gpos,1); /* 1 means char pairs (ie. not classes) */
+ coverage_pos = ftell(gpos);
+ putshort(gpos,0); /* offset to coverage table */
+ putshort(gpos,vf1);
+ putshort(gpos,vf2);
+ putshort(gpos,end_cnt-start_cnt);
+ offset_pos = ftell(gpos);
+ for ( i=start_cnt; i<end_cnt; ++i )
+ putshort(gpos,0); /* Fill in later */
+ for ( i=start_cnt; i<end_cnt; ++i ) {
+ if ( seconds[i][0].samewas>= start_cnt && seconds[i][0].samewas!=0xffff ) {
+ /* It's the same as the glyph at samewas, so just copy the */
+ /* offset from there. We don't need to do anything else */
+ int offset;
+ fseek(gpos,offset_pos+(seconds[i][0].samewas-start_cnt)*sizeof(uint16),SEEK_SET);
+ offset = getushort(gpos);
+ fseek(gpos,offset_pos+(i-start_cnt)*sizeof(uint16),SEEK_SET);
+ putshort(gpos,offset);
+ fseek(gpos,0,SEEK_END);
+ continue;
+ }
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ int next_dev_tab = ftell(gpos)-start;
+ if ( (vf1&0xf0) || (vf2&0xf0) ) {
+ for ( tot=0 ; tot<seconds[i][0].tot; ++tot ) {
+ if ( (pst=seconds[i][tot].pst)!=NULL ) {
+ if ( pst->u.pair.vr[0].adjust!=NULL ) {
+ dumpgposdevicetable(gpos,&pst->u.pair.vr[0].adjust->xadjust);
+ dumpgposdevicetable(gpos,&pst->u.pair.vr[0].adjust->yadjust);
+ dumpgposdevicetable(gpos,&pst->u.pair.vr[0].adjust->xadv);
+ dumpgposdevicetable(gpos,&pst->u.pair.vr[0].adjust->yadv);
+ }
+ if ( pst->u.pair.vr[1].adjust!=NULL ) {
+ dumpgposdevicetable(gpos,&pst->u.pair.vr[1].adjust->xadjust);
+ dumpgposdevicetable(gpos,&pst->u.pair.vr[1].adjust->yadjust);
+ dumpgposdevicetable(gpos,&pst->u.pair.vr[1].adjust->xadv);
+ dumpgposdevicetable(gpos,&pst->u.pair.vr[1].adjust->yadv);
+ }
+ }
+ if ( (kp=seconds[i][tot].kp)!=NULL && kp->adjust!=NULL )
+ dumpgposdevicetable(gpos,kp->adjust);
+ }
+ }
+#endif
+ pos = ftell(gpos);
+ fseek(gpos,offset_pos+(i-start_cnt)*sizeof(uint16),SEEK_SET);
+ putshort(gpos,pos-start);
+ fseek(gpos,pos,SEEK_SET);
+
+ putshort(gpos,seconds[i][0].tot);
+ for ( tot=0 ; tot<seconds[i][0].tot; ++tot ) {
+ putshort(gpos,seconds[i][tot].other_gid);
+ if ( (pst=seconds[i][tot].pst)!=NULL ) {
+ if ( vf1&1 ) putshort(gpos,pst->u.pair.vr[0].xoff);
+ if ( vf1&2 ) putshort(gpos,pst->u.pair.vr[0].yoff);
+ if ( vf1&4 ) putshort(gpos,pst->u.pair.vr[0].h_adv_off);
+ if ( vf1&8 ) putshort(gpos,pst->u.pair.vr[0].v_adv_off);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ next_dev_tab = gposdumpvaldevtab(gpos,pst->u.pair.vr[0].adjust,vf1,
+ next_dev_tab);
+#endif
+ if ( vf2&1 ) putshort(gpos,pst->u.pair.vr[1].xoff);
+ if ( vf2&2 ) putshort(gpos,pst->u.pair.vr[1].yoff);
+ if ( vf2&4 ) putshort(gpos,pst->u.pair.vr[1].h_adv_off);
+ if ( vf2&8 ) putshort(gpos,pst->u.pair.vr[1].v_adv_off);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ next_dev_tab = gposdumpvaldevtab(gpos,pst->u.pair.vr[1].adjust,vf2,
+ next_dev_tab);
+#endif
+ } else if ( (kp=seconds[i][tot].kp)!=NULL ) {
+ int mask=0, mask2=0;
+ if ( seconds[i][tot].isv )
+ mask = 0x8;
+ else if ( isr2l )
+ mask2 = 0x4;
+ else
+ mask = 0x4;
+ gposvrmaskeddump(gpos,vf1,mask,kp->off);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ next_dev_tab = gposmaskeddumpdevtab(gpos,kp->adjust,vf1,mask<<4,
+ next_dev_tab);
+#endif
+ gposvrmaskeddump(gpos,vf2,mask2,kp->off);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ next_dev_tab = gposmaskeddumpdevtab(gpos,kp->adjust,vf2,mask2<<4,
+ next_dev_tab);
+#endif
+ }
+ }
+ }
+ end = ftell(gpos);
+ fseek(gpos,coverage_pos,SEEK_SET);
+ putshort(gpos,end-start);
+ fseek(gpos,end,SEEK_SET);
+ gtemp = glyphs[end_cnt]; glyphs[end_cnt] = NULL;
+ dumpcoveragetable(gpos,glyphs+start_cnt);
+ glyphs[end_cnt] = gtemp;
+ }
+ for ( i=0; i<cnt; ++i )
+ free(seconds[i]);
+ free(seconds);
+ free(glyphs);
+}
+
+uint16 *ClassesFromNames(SplineFont *sf,char **classnames,int class_cnt,
+ int numGlyphs, SplineChar ***glyphs, int apple_kc) {
+ uint16 *class;
+ int i;
+ char *pt, *end, ch;
+ SplineChar *sc, **gs=NULL;
+ int offset = (apple_kc && classnames[0]!=NULL);
+
+ class = gcalloc(numGlyphs,sizeof(uint16));
+ if ( glyphs ) *glyphs = gs = gcalloc(numGlyphs,sizeof(SplineChar *));
+ for ( i=0; i<class_cnt; ++i ) {
+ if ( i==0 && classnames[0]==NULL )
+ continue;
+ for ( pt = classnames[i]; *pt; pt = end+1 ) {
+ while ( *pt==' ' ) ++pt;
+ if ( *pt=='\0' )
+ break;
+ end = strchr(pt,' ');
+ if ( end==NULL )
+ end = pt+strlen(pt);
+ ch = *end;
+ *end = '\0';
+ sc = SFGetChar(sf,-1,pt);
+ if ( sc!=NULL && sc->ttf_glyph!=-1 ) {
+ class[sc->ttf_glyph] = i+offset;
+ if ( gs!=NULL )
+ gs[sc->ttf_glyph] = sc;
+ }
+ *end = ch;
+ if ( ch=='\0' )
+ break;
+ }
+ }
+return( class );
+}
+
+static SplineChar **GlyphsFromClasses(SplineChar **gs, int numGlyphs) {
+ int i, cnt;
+ SplineChar **glyphs;
+
+ for ( i=cnt=0; i<numGlyphs; ++i )
+ if ( gs[i]!=NULL ) ++cnt;
+ glyphs = galloc((cnt+1)*sizeof(SplineChar *));
+ for ( i=cnt=0; i<numGlyphs; ++i )
+ if ( gs[i]!=NULL )
+ glyphs[cnt++] = gs[i];
+ glyphs[cnt++] = NULL;
+ free(gs);
+return( glyphs );
+}
+
+static SplineChar **GlyphsFromInitialClasses(SplineChar **gs, int numGlyphs, uint16 *classes, uint16 *initial) {
+ int i, j, cnt;
+ SplineChar **glyphs;
+
+ for ( i=cnt=0; i<numGlyphs; ++i ) {
+ for ( j=0; initial[j]!=0xffff; ++j )
+ if ( initial[j]==classes[i])
+ break;
+ if ( initial[j]!=0xffff && gs[i]!=NULL ) ++cnt;
+ }
+ glyphs = galloc((cnt+1)*sizeof(SplineChar *));
+ for ( i=cnt=0; i<numGlyphs; ++i ) {
+ for ( j=0; initial[j]!=0xffff; ++j )
+ if ( initial[j]==classes[i])
+ break;
+ if ( initial[j]!=0xffff && gs[i]!=NULL )
+ glyphs[cnt++] = gs[i];
+ }
+ glyphs[cnt++] = NULL;
+return( glyphs );
+}
+
+static void DumpClass(FILE *gpos,uint16 *class,int numGlyphs) {
+ int ranges, i, cur, first= -1, last=-1, istart;
+
+ for ( i=ranges=0; i<numGlyphs; ) {
+ istart = i;
+ cur = class[i];
+ while ( i<numGlyphs && class[i]==cur )
+ ++i;
+ if ( cur!=0 ) {
+ ++ranges;
+ if ( first==-1 ) first = istart;
+ last = i-1;
+ }
+ }
+ if ( ranges*3+1>last-first+1+2 || first==-1 ) {
+ if ( first==-1 ) first = last = 0;
+ putshort(gpos,1); /* Format 1, list of all posibilities */
+ putshort(gpos,first);
+ putshort(gpos,last-first+1);
+ for ( i=first; i<=last ; ++i )
+ putshort(gpos,class[i]);
+ } else {
+ putshort(gpos,2); /* Format 2, series of ranges */
+ putshort(gpos,ranges);
+ for ( i=0; i<numGlyphs; ) {
+ istart = i;
+ cur = class[i];
+ while ( i<numGlyphs && class[i]==cur )
+ ++i;
+ if ( cur!=0 ) {
+ putshort(gpos,istart);
+ putshort(gpos,i-1);
+ putshort(gpos,cur);
+ }
+ }
+ }
+}
+
+static int KernClassR2L(SplineFont *sf, KernClass *kc) {
+ int i, ch, known_r2l ;
+ char *pt, *start;
+ SplineChar *sc;
+
+ for ( i=1; i<kc->first_cnt; ++i ) {
+ for ( start = kc->firsts[i]; *start ; ) {
+ for ( pt=start; *pt!=' ' && *pt!='\0'; ++pt );
+ ch = *pt; *pt = '\0';
+ sc = SFGetChar(sf,-1,start);
+ *pt = ch;
+ if ( sc!=NULL ) {
+ known_r2l = SCRightToLeft(sc);
+ if ( known_r2l )
+return( true );
+ else if ( SCScriptFromUnicode(sc)== DEFAULT_SCRIPT )
+ /* Do Nothing */;
+ else
+return( false );
+ }
+ while ( ch==' ' )
+ ch = *++pt;
+ start = pt;
+ }
+ }
+
+ /* Eh? All the data were non-commital? Well, try the second set of classes*/
+ for ( i=1; i<kc->second_cnt; ++i ) {
+ for ( start = kc->seconds[i]; *start ; ) {
+ for ( pt=start; *pt!=' ' && *pt!='\0'; ++pt );
+ ch = *pt; *pt = '\0';
+ sc = SFGetChar(sf,-1,start);
+ *pt = ch;
+ if ( sc!=NULL ) {
+ known_r2l = SCRightToLeft(sc);
+ if ( known_r2l )
+return( true );
+ else if ( SCScriptFromUnicode(sc)== DEFAULT_SCRIPT )
+ /* Do Nothing */;
+ else
+return( false );
+ }
+ while ( ch==' ' )
+ ch = *++pt;
+ start = pt;
+ }
+ }
+
+ /* We still don't have any idea? Well, lets just say it's l2r */
+return( false );
+}
+
+static void dumpgposkernclass(FILE *gpos,SplineFont *sf,
+ struct lookup_subtable *sub, struct alltabs *at) {
+ uint32 begin_off = ftell(gpos), pos;
+ uint16 *class1, *class2;
+ KernClass *kc = sub->kc, *test;
+ SplineChar **glyphs;
+ int i, isv, isr2l;
+ int anydevtab = false;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ int next_devtab;
+#endif
+
+ putshort(gpos,2); /* format 2 of the pair adjustment subtable */
+ putshort(gpos,0); /* offset to coverage table */
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ for ( i=0; i<kc->first_cnt*kc->second_cnt; ++i ) {
+ if ( kc->adjusts[i].corrections!=NULL ) {
+ anydevtab = true;
+ break;
+ }
+ }
+#endif
+
+ for ( test=sf->vkerns; test!=NULL && test!=kc; test=test->next );
+ isv = test==kc;
+ isr2l = KernClassR2L(sf,kc);
+
+ if ( isv ) {
+ /* As far as I know there is no "bottom to top" writing direction */
+ /* Oh. There is. Ogham, Runic */
+ putshort(gpos,anydevtab?0x0088:0x0008); /* Alter YAdvance of first character */
+ putshort(gpos,0x0000); /* leave second char alone */
+ } else if ( isr2l ) {
+ /* Right to left kerns modify the second character's width */
+ /* this doesn't make sense to me, but who am I to argue */
+ putshort(gpos,0x0000); /* leave first char alone */
+ putshort(gpos,anydevtab?0x0044:0x0004); /* Alter XAdvance of second character */
+ } else {
+ putshort(gpos,anydevtab?0x0044:0x0004); /* Alter XAdvance of first character */
+ putshort(gpos,0x0000); /* leave second char alone */
+ }
+ class1 = ClassesFromNames(sf,kc->firsts,kc->first_cnt,at->maxp.numGlyphs,&glyphs,false);
+ glyphs = GlyphsFromClasses(glyphs,at->maxp.numGlyphs);
+ class2 = ClassesFromNames(sf,kc->seconds,kc->second_cnt,at->maxp.numGlyphs,NULL,false);
+ putshort(gpos,0); /* offset to first glyph classes */
+ putshort(gpos,0); /* offset to second glyph classes */
+ putshort(gpos,kc->first_cnt);
+ putshort(gpos,kc->second_cnt);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ next_devtab = ftell(gpos)-begin_off + kc->first_cnt*kc->second_cnt*2*sizeof(uint16);
+#endif
+ for ( i=0; i<kc->first_cnt*kc->second_cnt; ++i ) {
+ putshort(gpos,kc->offsets[i]);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( anydevtab && kc->adjusts[i].corrections!=NULL ) {
+ putshort(gpos,next_devtab);
+ next_devtab += DevTabLen(&kc->adjusts[i]);
+ } else if ( anydevtab )
+ putshort(gpos,0);
+#endif
+ }
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( anydevtab ) {
+ for ( i=0; i<kc->first_cnt*kc->second_cnt; ++i ) {
+ if ( kc->adjusts[i].corrections!=NULL )
+ dumpgposdevicetable(gpos,&kc->adjusts[i]);
+ }
+ if ( next_devtab!=ftell(gpos)-begin_off )
+ IError("Device table offsets screwed up in kerning class");
+ }
+#endif
+ pos = ftell(gpos);
+ fseek(gpos,begin_off+4*sizeof(uint16),SEEK_SET);
+ putshort(gpos,pos-begin_off);
+ fseek(gpos,pos,SEEK_SET);
+ DumpClass(gpos,class1,at->maxp.numGlyphs);
+
+ pos = ftell(gpos);
+ fseek(gpos,begin_off+5*sizeof(uint16),SEEK_SET);
+ putshort(gpos,pos-begin_off);
+ fseek(gpos,pos,SEEK_SET);
+ DumpClass(gpos,class2,at->maxp.numGlyphs);
+
+ pos = ftell(gpos);
+ fseek(gpos,begin_off+sizeof(uint16),SEEK_SET);
+ putshort(gpos,pos-begin_off);
+ fseek(gpos,pos,SEEK_SET);
+ dumpcoveragetable(gpos,glyphs);
+
+ free(glyphs);
+ free(class1);
+ free(class2);
+}
+
+static void dumpanchor(FILE *gpos,AnchorPoint *ap, int is_ttf ) {
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ int base = ftell(gpos);
+#endif
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( ap->xadjust.corrections!=NULL || ap->yadjust.corrections!=NULL )
+ putshort(gpos,3); /* format 3 w/ device tables */
+ else
+#endif
+ if ( ap->has_ttf_pt && is_ttf )
+ putshort(gpos,2); /* format 2 w/ a matching ttf point index */
+ else
+ putshort(gpos,1); /* Anchor format 1 just location*/
+ putshort(gpos,ap->me.x); /* X coord of attachment */
+ putshort(gpos,ap->me.y); /* Y coord of attachment */
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( ap->xadjust.corrections!=NULL || ap->yadjust.corrections!=NULL ) {
+ putshort(gpos,ap->xadjust.corrections==NULL?0:
+ ftell(gpos)-base+4);
+ putshort(gpos,ap->yadjust.corrections==NULL?0:
+ ftell(gpos)-base+2+DevTabLen(&ap->xadjust));
+ dumpgposdevicetable(gpos,&ap->xadjust);
+ dumpgposdevicetable(gpos,&ap->yadjust);
+ } else
+#endif
+ if ( ap->has_ttf_pt && is_ttf )
+ putshort(gpos,ap->ttf_pt_index);
+}
+
+static void dumpgposCursiveAttach(FILE *gpos, SplineFont *sf,
+ struct lookup_subtable *sub,struct glyphinfo *gi) {
+ AnchorClass *ac, *testac;
+ SplineChar **entryexit;
+ int cnt, offset,j;
+ AnchorPoint *ap, *entry, *exit;
+ uint32 coverage_offset, start;
+
+ ac = NULL;
+ for ( testac=sf->anchor; testac!=NULL; testac = testac->next ) {
+ if ( testac->subtable == sub ) {
+ if ( ac==NULL )
+ ac = testac;
+ else {
+ gwwv_post_error(_("Two cursive anchor classes"),_("Two cursive anchor classes in the same subtable, %s"),
+ sub->subtable_name);
+ break;
+ }
+ }
+ }
+ if ( ac==NULL ) {
+ IError( "Missing anchor class for %s", sub->subtable_name );
+return;
+ }
+ entryexit = EntryExitDecompose(sf,ac,gi);
+ if ( entryexit==NULL )
+return;
+
+ for ( cnt=0; entryexit[cnt]!=NULL; ++cnt );
+
+ start = ftell(gpos);
+ putshort(gpos,1); /* format 1 for this subtable */
+ putshort(gpos,0); /* Fill in later, offset to coverage table */
+ putshort(gpos,cnt); /* number of glyphs */
+
+ offset = 6+2*2*cnt;
+ for ( j=0; j<cnt; ++j ) {
+ entry = exit = NULL;
+ for ( ap=entryexit[j]->anchor; ap!=NULL; ap=ap->next ) {
+ if ( ap->anchor==ac && ap->type==at_centry ) entry = ap;
+ if ( ap->anchor==ac && ap->type==at_cexit ) exit = ap;
+ }
+ if ( entry!=NULL ) {
+ putshort(gpos,offset);
+ offset += 6;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( entry->xadjust.corrections!=NULL || entry->yadjust.corrections!=NULL )
+ offset += 4 + DevTabLen(&entry->xadjust) + DevTabLen(&entry->yadjust);
+#endif
+ } else
+ putshort(gpos,0);
+ if ( exit!=NULL ) {
+ putshort(gpos,offset);
+ offset += 6;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( exit->xadjust.corrections!=NULL || exit->yadjust.corrections!=NULL )
+ offset += 4 + DevTabLen(&exit->xadjust) + DevTabLen(&exit->yadjust);
+ else
+#endif
+ if ( gi->is_ttf && ap->has_ttf_pt )
+ offset += 2;
+ } else
+ putshort(gpos,0);
+ }
+ for ( j=0; j<cnt; ++j ) {
+ entry = exit = NULL;
+ for ( ap=entryexit[j]->anchor; ap!=NULL; ap=ap->next ) {
+ if ( ap->anchor==ac && ap->type==at_centry ) entry = ap;
+ if ( ap->anchor==ac && ap->type==at_cexit ) exit = ap;
+ }
+ if ( entry!=NULL )
+ dumpanchor(gpos,entry,gi->is_ttf);
+ if ( exit!=NULL )
+ dumpanchor(gpos,exit,gi->is_ttf);
+ }
+ coverage_offset = ftell(gpos);
+ dumpcoveragetable(gpos,entryexit);
+ fseek(gpos,start+2,SEEK_SET);
+ putshort(gpos,coverage_offset-start);
+ fseek(gpos,0,SEEK_END);
+
+ free(entryexit);
+}
+
+static int orderglyph(const void *_sc1,const void *_sc2) {
+ SplineChar * const *sc1 = _sc1, * const *sc2 = _sc2;
+
+return( (*sc1)->ttf_glyph - (*sc2)->ttf_glyph );
+}
+
+static SplineChar **allmarkglyphs(SplineChar ***glyphlist, int classcnt) {
+ SplineChar **glyphs;
+ int i, tot, k;
+
+ if ( classcnt==1 )
+return( glyphlist[0]);
+
+ for ( i=tot=0; i<classcnt; ++i ) {
+ for ( k=0; glyphlist[i][k]!=NULL; ++k );
+ tot += k;
+ }
+ glyphs = galloc((tot+1)*sizeof(SplineChar *));
+ for ( i=tot=0; i<classcnt; ++i ) {
+ for ( k=0; glyphlist[i][k]!=NULL; ++k )
+ glyphs[tot++] = glyphlist[i][k];
+ }
+ qsort(glyphs,tot,sizeof(SplineChar *),orderglyph);
+ for ( i=k=0; i<tot; ++i ) {
+ while ( i+1<tot && glyphs[i]==glyphs[i+1]) ++i;
+ glyphs[k++] = glyphs[i];
+ }
+ glyphs[k] = NULL;
+return( glyphs );
+}
+
+static void dumpgposAnchorData(FILE *gpos,AnchorClass *_ac,
+ enum anchor_type at,
+ SplineChar ***marks,SplineChar **base,
+ int classcnt, struct glyphinfo *gi) {
+ AnchorClass *ac=NULL;
+ int j,cnt,k,l, pos, offset, tot, max;
+ uint32 coverage_offset, markarray_offset, subtable_start;
+ AnchorPoint *ap = NULL, **aps;
+ SplineChar **markglyphs;
+
+ for ( cnt=0; base[cnt]!=NULL; ++cnt );
+
+ subtable_start = ftell(gpos);
+ putshort(gpos,1); /* format 1 for this subtable */
+ putshort(gpos,0); /* Fill in later, offset to mark coverage table */
+ putshort(gpos,0); /* Fill in later, offset to base coverage table */
+ putshort(gpos,classcnt);
+ putshort(gpos,0); /* Fill in later, offset to mark array */
+ putshort(gpos,12); /* Offset to base array */
+ /* Base array */
+ putshort(gpos,cnt); /* Number of entries in array */
+ if ( at==at_basechar || at==at_basemark ) {
+ offset = 2;
+ for ( l=0; l<3; ++l ) {
+ for ( j=0; j<cnt; ++j ) {
+ for ( k=0, ac=_ac; k<classcnt; ++k, ac=ac->next ) {
+ for ( ap=base[j]->anchor; ap!=NULL && (ap->anchor!=ac || ap->type!=at);
+ ap=ap->next );
+ switch ( l ) {
+ case 0:
+ offset += 2;
+ break;
+ case 1:
+ if ( ap==NULL )
+ putshort(gpos,0);
+ else {
+ putshort(gpos,offset);
+ offset += 6;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( ap->xadjust.corrections!=NULL || ap->yadjust.corrections!=NULL )
+ offset += 4 + DevTabLen(&ap->xadjust) + DevTabLen(&ap->yadjust);
+ else
+#endif
+ if ( gi->is_ttf && ap->has_ttf_pt )
+ offset += 2;
+ }
+ break;
+ case 2:
+ if ( ap!=NULL )
+ dumpanchor(gpos,ap,gi->is_ttf);
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ offset = 2+2*cnt;
+ max = 0;
+ for ( j=0; j<cnt; ++j ) {
+ putshort(gpos,offset);
+ pos = tot = 0;
+ for ( ap=base[j]->anchor; ap!=NULL ; ap=ap->next )
+ for ( k=0, ac=_ac; k<classcnt; ++k, ac=ac->next ) {
+ if ( ap->anchor==ac ) {
+ if ( ap->lig_index>pos ) pos = ap->lig_index;
+ ++tot;
+ }
+ }
+ if ( pos>max ) max = pos;
+ offset += 2+(pos+1)*classcnt*2+tot*6;
+ /* 2 for component count, for each component an offset to an offset to an anchor record */
+ }
+ ++max;
+ aps = galloc((classcnt*max)*sizeof(AnchorPoint *));
+ for ( j=0; j<cnt; ++j ) {
+ memset(aps,0,(classcnt*max)*sizeof(AnchorPoint *));
+ pos = 0;
+ for ( ap=base[j]->anchor; ap!=NULL ; ap=ap->next )
+ for ( k=0, ac=_ac; k<classcnt; ++k, ac=ac->next ) {
+ if ( ap->anchor==ac ) {
+ if ( ap->lig_index>pos ) pos = ap->lig_index;
+ aps[k*max+ap->lig_index] = ap;
+ }
+ }
+ ++pos;
+ putshort(gpos,pos);
+ offset = 2+2*pos*classcnt;
+ for ( l=0; l<pos; ++l ) {
+ for ( k=0; k<classcnt; ++k ) {
+ if ( aps[k*max+l]==NULL )
+ putshort(gpos,0);
+ else {
+ putshort(gpos,offset);
+ offset += 6;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( aps[k*max+l]->xadjust.corrections!=NULL || aps[k*max+l]->yadjust.corrections!=NULL )
+ offset += 4 + DevTabLen(&aps[k*max+l]->xadjust) +
+ DevTabLen(&aps[k*max+l]->yadjust);
+ else
+#endif
+ if ( gi->is_ttf && aps[k*max+l]->has_ttf_pt )
+ offset += 2;
+ }
+ }
+ }
+ for ( l=0; l<pos; ++l ) {
+ for ( k=0; k<classcnt; ++k ) {
+ if ( aps[k*max+l]!=NULL ) {
+ dumpanchor(gpos,aps[k*max+l],gi->is_ttf);
+ }
+ }
+ }
+ }
+ free(aps);
+ }
+ coverage_offset = ftell(gpos);
+ fseek(gpos,subtable_start+4,SEEK_SET);
+ putshort(gpos,coverage_offset-subtable_start);
+ fseek(gpos,0,SEEK_END);
+ dumpcoveragetable(gpos,base);
+
+ /* We tried sharing the mark table, (among all these sub-tables) but */
+ /* that doesn't work because we need to be able to reorder the sub-tables */
+ markglyphs = allmarkglyphs(marks,classcnt);
+ coverage_offset = ftell(gpos);
+ dumpcoveragetable(gpos,markglyphs);
+ markarray_offset = ftell(gpos);
+ for ( cnt=0; markglyphs[cnt]!=NULL; ++cnt );
+ putshort(gpos,cnt);
+ offset = 2+4*cnt;
+ for ( j=0; j<cnt; ++j ) {
+ if ( classcnt==0 ) {
+ putshort(gpos,0); /* Only one class */
+ ap = NULL;
+ } else {
+ for ( k=0, ac=_ac; k<classcnt; ac=ac->next ) {
+ if ( ac->matches ) {
+ for ( ap = markglyphs[j]->anchor; ap!=NULL && (ap->anchor!=ac || ap->type!=at_mark);
+ ap=ap->next );
+ if ( ap!=NULL )
+ break;
+ ++k;
+ }
+ }
+ putshort(gpos,k);
+ }
+ putshort(gpos,offset);
+ offset += 6;
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+ if ( ap!=NULL && (ap->xadjust.corrections!=NULL || ap->yadjust.corrections!=NULL ))
+ offset += 4 + DevTabLen(&ap->xadjust) + DevTabLen(&ap->yadjust);
+ else
+#endif
+ if ( gi->is_ttf && ap->has_ttf_pt )
+ offset += 2;
+ }
+ for ( j=0; j<cnt; ++j ) {
+ for ( k=0, ac=_ac; k<classcnt; ac=ac->next ) {
+ if ( ac->matches ) {
+ for ( ap = markglyphs[j]->anchor; ap!=NULL && (ap->anchor!=ac || ap->type!=at_mark);
+ ap=ap->next );
+ if ( ap!=NULL )
+ break;
+ ++k;
+ }
+ }
+ dumpanchor(gpos,ap,gi->is_ttf);
+ }
+ if ( markglyphs!=marks[0] )
+ free(markglyphs);
+
+ fseek(gpos,subtable_start+2,SEEK_SET); /* mark coverage table offset */
+ putshort(gpos,coverage_offset-subtable_start);
+ fseek(gpos,4,SEEK_CUR);
+ putshort(gpos,markarray_offset-subtable_start);
+
+ fseek(gpos,0,SEEK_END);
+}
+
+static void dumpGSUBsimplesubs(FILE *gsub,SplineFont *sf,struct lookup_subtable *sub) {
+ int cnt, diff, ok = true;
+ int32 coverage_pos, end;
+ SplineChar **glyphs, ***maps;
+
+ glyphs = SFOrderedGlyphsWithPSTinSubtable(sf,sub);
+ maps = generateMapList(glyphs,sub);
+
+ diff = (*maps[0])->ttf_glyph - glyphs[0]->ttf_glyph;
+ for ( cnt=0; glyphs[cnt]!=NULL; ++cnt)
+ if ( diff!= maps[cnt][0]->ttf_glyph-glyphs[cnt]->ttf_glyph ) ok = false;
+
+ if ( ok ) {
+ putshort(gsub,1); /* delta format */
+ coverage_pos = ftell(gsub);
+ putshort(gsub,0); /* offset to coverage table */
+ putshort(gsub,diff);
+ } else {
+ putshort(gsub,2); /* glyph list format */
+ coverage_pos = ftell(gsub);
+ putshort(gsub,0); /* offset to coverage table */
+ putshort(gsub,cnt);
+ for ( cnt = 0; glyphs[cnt]!=NULL; ++cnt )
+ putshort(gsub,(*maps[cnt])->ttf_glyph);
+ }
+ end = ftell(gsub);
+ fseek(gsub,coverage_pos,SEEK_SET);
+ putshort(gsub,end-coverage_pos+2);
+ fseek(gsub,end,SEEK_SET);
+ dumpcoveragetable(gsub,glyphs);
+
+ free(glyphs);
+ GlyphMapFree(maps);
+}
+
+static void dumpGSUBmultiplesubs(FILE *gsub,SplineFont *sf,struct lookup_subtable *sub) {
+ int cnt, offset;
+ int32 coverage_pos, end;
+ int gc;
+ SplineChar **glyphs, ***maps;
+
+ glyphs = SFOrderedGlyphsWithPSTinSubtable(sf,sub);
+ maps = generateMapList(glyphs,sub);
+ for ( cnt=0; glyphs[cnt]!=NULL; ++cnt);
+
+ putshort(gsub,1); /* glyph list format */
+ coverage_pos = ftell(gsub);
+ putshort(gsub,0); /* offset to coverage table */
+ putshort(gsub,cnt);
+ offset = 6+2*cnt;
+ for ( cnt = 0; glyphs[cnt]!=NULL; ++cnt ) {
+ putshort(gsub,offset);
+ for ( gc=0; maps[cnt][gc]!=NULL; ++gc );
+ offset += 2+2*gc;
+ }
+ for ( cnt = 0; glyphs[cnt]!=NULL; ++cnt ) {
+ for ( gc=0; maps[cnt][gc]!=NULL; ++gc );
+ putshort(gsub,gc);
+ for ( gc=0; maps[cnt][gc]!=NULL; ++gc )
+ putshort(gsub,maps[cnt][gc]->ttf_glyph);
+ }
+ end = ftell(gsub);
+ fseek(gsub,coverage_pos,SEEK_SET);
+ putshort(gsub,end-coverage_pos+2);
+ fseek(gsub,end,SEEK_SET);
+ dumpcoveragetable(gsub,glyphs);
+
+ free(glyphs);
+ GlyphMapFree(maps);
+}
+
+static int AllToBeOutput(LigList *lig) {
+ struct splinecharlist *cmp;
+
+ if ( lig->lig->u.lig.lig->ttf_glyph==-1 ||
+ lig->first->ttf_glyph==-1 )
+return( 0 );
+ for ( cmp=lig->components; cmp!=NULL; cmp=cmp->next )
+ if ( cmp->sc->ttf_glyph==-1 )
+return( 0 );
+return( true );
+}
+
+static void dumpGSUBligdata(FILE *gsub,SplineFont *sf,
+ struct lookup_subtable *sub, struct alltabs *at) {
+ int32 coverage_pos, next_val_pos, here, lig_list_start;
+ int cnt, i, pcnt, lcnt, max=100, j;
+ uint16 *offsets=NULL, *ligoffsets=galloc(max*sizeof(uint16));
+ SplineChar **glyphs;
+ LigList *ll;
+ struct splinecharlist *scl;
+
+ glyphs = SFOrderedGlyphsWithPSTinSubtable(sf,sub);
+ cnt=0;
+ if ( glyphs!=NULL ) for ( ; glyphs[cnt]!=NULL; ++cnt );
+
+ putshort(gsub,1); /* only one format for ligatures */
+ coverage_pos = ftell(gsub);
+ putshort(gsub,0); /* offset to coverage table */
+ putshort(gsub,cnt);
+ next_val_pos = ftell(gsub);
+ if ( glyphs!=NULL )
+ offsets = galloc(cnt*sizeof(int16));
+ for ( i=0; i<cnt; ++i )
+ putshort(gsub,0);
+ for ( i=0; i<cnt; ++i ) {
+ offsets[i] = ftell(gsub)-coverage_pos+2;
+ for ( pcnt = 0, ll = glyphs[i]->ligofme; ll!=NULL; ll=ll->next )
+ if ( ll->lig->subtable==sub && AllToBeOutput(ll))
+ ++pcnt;
+ putshort(gsub,pcnt);
+ if ( pcnt>=max ) {
+ max = pcnt+100;
+ ligoffsets = grealloc(ligoffsets,max*sizeof(int));
+ }
+ lig_list_start = ftell(gsub);
+ for ( j=0; j<pcnt; ++j )
+ putshort(gsub,0); /* Place holders */
+ for ( pcnt=0, ll = glyphs[i]->ligofme; ll!=NULL; ll=ll->next ) {
+ if ( ll->lig->subtable==sub && AllToBeOutput(ll)) {
+ ligoffsets[pcnt] = ftell(gsub)-lig_list_start+2;
+ putshort(gsub,ll->lig->u.lig.lig->ttf_glyph);
+ for ( lcnt=0, scl=ll->components; scl!=NULL; scl=scl->next ) ++lcnt;
+ putshort(gsub, lcnt+1);
+ if ( lcnt+1>at->os2.maxContext )
+ at->os2.maxContext = lcnt+1;
+ for ( scl=ll->components; scl!=NULL; scl=scl->next )
+ putshort(gsub, scl->sc->ttf_glyph );
+ ++pcnt;
+ }
+ }
+ fseek(gsub,lig_list_start,SEEK_SET);
+ for ( j=0; j<pcnt; ++j )
+ putshort(gsub,ligoffsets[j]);
+ fseek(gsub,0,SEEK_END);
+ }
+ free(ligoffsets);
+ if ( glyphs!=NULL ) {
+ here = ftell(gsub);
+ fseek(gsub,coverage_pos,SEEK_SET);
+ putshort(gsub,here-coverage_pos+2);
+ fseek(gsub,next_val_pos,SEEK_SET);
+ for ( i=0; i<cnt; ++i )
+ putshort(gsub,offsets[i]);
+ fseek(gsub,here,SEEK_SET);
+ dumpcoveragetable(gsub,glyphs);
+ free(glyphs);
+ free(offsets);
+ }
+}
+
+static int ui16cmp(const void *_i1, const void *_i2) {
+ if ( *(const uint16 *) _i1 > *(const uint16 *) _i2 )
+return( 1 );
+ if ( *(const uint16 *) _i1 < *(const uint16 *) _i2 )
+return( -1 );
+
+return( 0 );
+}
+
+static uint16 *FigureInitialClasses(FPST *fpst) {
+ uint16 *initial = galloc((fpst->nccnt+1)*sizeof(uint16));
+ int i, cnt, j;
+
+ for ( i=cnt=0; i<fpst->rule_cnt; ++i ) {
+ for ( j=0; j<cnt ; ++j )
+ if ( initial[j] == fpst->rules[i].u.class.nclasses[0] )
+ break;
+ if ( j==cnt )
+ initial[cnt++] = fpst->rules[i].u.class.nclasses[0];
+ }
+ qsort(initial,cnt,sizeof(uint16),ui16cmp);
+ initial[cnt] = 0xffff;
+return( initial );
+}
+
+static SplineChar **OrderedInitialGlyphs(SplineFont *sf,FPST *fpst) {
+ SplineChar **glyphs, *sc;
+ int i, j, cnt, ch;
+ char *pt, *names;
+
+ glyphs = galloc((fpst->rule_cnt+1)*sizeof(SplineChar *));
+ for ( i=cnt=0; i<fpst->rule_cnt; ++i ) {
+ names = fpst->rules[i].u.glyph.names;
+ pt = strchr(names,' ');
+ if ( pt==NULL ) pt = names+strlen(names);
+ ch = *pt; *pt = '\0';
+ sc = SFGetChar(sf,-1,names);
+ *pt = ch;
+ for ( j=0; j<cnt; ++j )
+ if ( glyphs[j]==sc )
+ break;
+ if ( j==cnt && sc!=NULL )
+ glyphs[cnt++] = sc;
+ }
+ glyphs[cnt] = NULL;
+ if ( cnt==0 )
+return( glyphs );
+
+ for ( i=0; glyphs[i+1]!=NULL; ++i ) for ( j=i+1; glyphs[j]!=NULL; ++j ) {
+ if ( glyphs[i]->ttf_glyph > glyphs[j]->ttf_glyph ) {
+ sc = glyphs[i];
+ glyphs[i] = glyphs[j];
+ glyphs[j] = sc;
+ }
+ }
+return( glyphs );
+}
+
+static int NamesStartWith(SplineChar *sc,char *names ) {
+ char *pt;
+
+ pt = strchr(names,' ');
+ if ( pt==NULL ) pt = names+strlen(names);
+ if ( pt-names!=strlen(sc->name))
+return( false );
+
+return( strncmp(sc->name,names,pt-names)==0 );
+}
+
+static int CntRulesStartingWith(FPST *fpst,SplineChar *sc) {
+ int i, cnt;
+
+ for ( i=cnt=0; i<fpst->rule_cnt; ++i ) {
+ if ( NamesStartWith(sc,fpst->rules[i].u.glyph.names))
+ ++cnt;
+ }
+return( cnt );
+}
+
+static int CntRulesStartingWithClass(FPST *fpst,uint16 cval) {
+ int i, cnt;
+
+ for ( i=cnt=0; i<fpst->rule_cnt; ++i ) {
+ if ( fpst->rules[i].u.class.nclasses[0]==cval )
+ ++cnt;
+ }
+return( cnt );
+}
+
+static void dumpg___ContextChainGlyphs(FILE *lfile,SplineFont *sf,
+ struct lookup_subtable *sub, struct alltabs *at) {
+ FPST *fpst = sub->fpst;
+ int iscontext = fpst->type==pst_contextpos || fpst->type==pst_contextsub;
+ uint32 base = ftell(lfile);
+ int i,cnt, subcnt, j,k,l, maxcontext,curcontext;
+ SplineChar **glyphs, **subglyphs;
+ int lc;
+
+ glyphs = OrderedInitialGlyphs(sf,fpst);
+ for ( cnt=0; glyphs[cnt]!=NULL; ++cnt );
+
+ putshort(lfile,1); /* Sub format 1 => glyph lists */
+ putshort(lfile,(3+cnt)*sizeof(short)); /* offset to coverage */
+ putshort(lfile,cnt);
+ for ( i=0; i<cnt; ++i )
+ putshort(lfile,0); /* Offset to rule */
+ dumpcoveragetable(lfile,glyphs);
+
+ maxcontext = 0;
+
+ for ( i=0; i<cnt; ++i ) {
+ uint32 pos = ftell(lfile);
+ fseek(lfile,base+(3+i)*sizeof(short),SEEK_SET);
+ putshort(lfile,pos-base);
+ fseek(lfile,pos,SEEK_SET);
+ subcnt = CntRulesStartingWith(fpst,glyphs[i]);
+ putshort(lfile,subcnt);
+ for ( j=0; j<subcnt; ++j )
+ putshort(lfile,0);
+ for ( j=k=0; k<fpst->rule_cnt; ++k ) if ( NamesStartWith(glyphs[i],fpst->rules[k].u.glyph.names )) {
+ uint32 subpos = ftell(lfile);
+ fseek(lfile,pos+(1+j)*sizeof(short),SEEK_SET);
+ putshort(lfile,subpos-pos);
+ fseek(lfile,subpos,SEEK_SET);
+
+ for ( l=lc=0; l<fpst->rules[k].lookup_cnt; ++l )
+ if ( fpst->rules[k].lookups[l].lookup->lookup_index!=-1 )
+ ++lc;
+ if ( iscontext ) {
+ subglyphs = SFGlyphsFromNames(sf,fpst->rules[k].u.glyph.names);
+ for ( l=0; subglyphs[l]!=NULL; ++l );
+ putshort(lfile,l);
+ curcontext = l;
+ putshort(lfile,lc);
+ for ( l=1; subglyphs[l]!=NULL; ++l )
+ putshort(lfile,subglyphs[l]->ttf_glyph);
+ free(subglyphs);
+ } else {
+ subglyphs = SFGlyphsFromNames(sf,fpst->rules[k].u.glyph.back);
+ for ( l=0; subglyphs[l]!=NULL; ++l );
+ putshort(lfile,l);
+ curcontext = l;
+ for ( l=0; subglyphs[l]!=NULL; ++l )
+ putshort(lfile,subglyphs[l]->ttf_glyph);
+ free(subglyphs);
+ subglyphs = SFGlyphsFromNames(sf,fpst->rules[k].u.glyph.names);
+ for ( l=0; subglyphs[l]!=NULL; ++l );
+ putshort(lfile,l);
+ curcontext += l;
+ for ( l=1; subglyphs[l]!=NULL; ++l )
+ putshort(lfile,subglyphs[l]->ttf_glyph);
+ free(subglyphs);
+ subglyphs = SFGlyphsFromNames(sf,fpst->rules[k].u.glyph.fore);
+ for ( l=0; subglyphs[l]!=NULL; ++l );
+ putshort(lfile,l);
+ curcontext += l;
+ for ( l=0; subglyphs[l]!=NULL; ++l )
+ putshort(lfile,subglyphs[l]->ttf_glyph);
+ free(subglyphs);
+ putshort(lfile,lc);
+ }
+ for ( l=0; l<fpst->rules[k].lookup_cnt; ++l )
+ if ( fpst->rules[k].lookups[l].lookup->lookup_index!=-1 ) {
+ putshort(lfile,fpst->rules[k].lookups[l].seq);
+ putshort(lfile,fpst->rules[k].lookups[l].lookup->lookup_index);
+ }
+ ++j;
+ if ( curcontext>maxcontext ) maxcontext = curcontext;
+ }
+ }
+ free(glyphs);
+
+ if ( maxcontext>at->os2.maxContext )
+ at->os2.maxContext = maxcontext;
+}
+
+static void dumpg___ContextChainClass(FILE *lfile,SplineFont *sf,
+ struct lookup_subtable *sub, struct alltabs *at) {
+ FPST *fpst = sub->fpst;
+ int iscontext = fpst->type==pst_contextpos || fpst->type==pst_contextsub;
+ uint32 base = ftell(lfile), rulebase, pos, subpos, npos;
+ uint16 *initialclasses, *iclass, *bclass, *lclass;
+ SplineChar **iglyphs, **bglyphs, **lglyphs, **glyphs;
+ int i,ii,cnt, subcnt, j,k,l , maxcontext,curcontext;
+ int lc;
+
+ putshort(lfile,2); /* Sub format 2 => class */
+ putshort(lfile,0); /* offset to coverage table */
+ if ( iscontext )
+ putshort(lfile,0); /* offset to input classdef */
+ else {
+ putshort(lfile,0); /* offset to backtrack classdef */
+ putshort(lfile,0); /* offset to input classdef */
+ putshort(lfile,0); /* offset to lookahead classdef */
+ }
+ initialclasses = FigureInitialClasses(fpst);
+ putshort(lfile,fpst->nccnt);
+ rulebase = ftell(lfile);
+ for ( cnt=0; cnt<fpst->nccnt; ++cnt )
+ putshort(lfile,0);
+
+ iclass = ClassesFromNames(sf,fpst->nclass,fpst->nccnt,at->maxp.numGlyphs,&iglyphs,false);
+ lglyphs = bglyphs = NULL; bclass = lclass = NULL;
+ if ( !iscontext ) {
+ bclass = ClassesFromNames(sf,fpst->bclass,fpst->bccnt,at->maxp.numGlyphs,&bglyphs,false);
+ lclass = ClassesFromNames(sf,fpst->fclass,fpst->fccnt,at->maxp.numGlyphs,&lglyphs,false);
+ }
+ pos = ftell(lfile);
+ fseek(lfile,base+sizeof(uint16),SEEK_SET);
+ putshort(lfile,pos-base);
+ fseek(lfile,pos,SEEK_SET);
+ glyphs = GlyphsFromInitialClasses(iglyphs,at->maxp.numGlyphs,iclass,initialclasses);
+ dumpcoveragetable(lfile,glyphs);
+ free(glyphs);
+ free(iglyphs); free(bglyphs); free(lglyphs);
+
+ if ( iscontext ) {
+ pos = ftell(lfile);
+ fseek(lfile,base+2*sizeof(uint16),SEEK_SET);
+ putshort(lfile,pos-base);
+ fseek(lfile,pos,SEEK_SET);
+ DumpClass(lfile,iclass,at->maxp.numGlyphs);
+ free(iclass);
+ } else {
+ pos = ftell(lfile);
+ fseek(lfile,base+2*sizeof(uint16),SEEK_SET);
+ putshort(lfile,pos-base);
+ fseek(lfile,pos,SEEK_SET);
+ DumpClass(lfile,bclass,at->maxp.numGlyphs);
+ if ( ClassesMatch(fpst->bccnt,fpst->bclass,fpst->nccnt,fpst->nclass)) {
+ npos = pos;
+ fseek(lfile,base+3*sizeof(uint16),SEEK_SET);
+ putshort(lfile,npos-base);
+ fseek(lfile,0,SEEK_END);
+ } else {
+ npos = ftell(lfile);
+ fseek(lfile,base+3*sizeof(uint16),SEEK_SET);
+ putshort(lfile,npos-base);
+ fseek(lfile,npos,SEEK_SET);
+ DumpClass(lfile,iclass,at->maxp.numGlyphs);
+ }
+ if ( ClassesMatch(fpst->fccnt,fpst->fclass,fpst->bccnt,fpst->bclass)) {
+ fseek(lfile,base+4*sizeof(uint16),SEEK_SET);
+ putshort(lfile,pos-base);
+ fseek(lfile,0,SEEK_END);
+ } else if ( ClassesMatch(fpst->fccnt,fpst->fclass,fpst->nccnt,fpst->nclass)) {
+ fseek(lfile,base+4*sizeof(uint16),SEEK_SET);
+ putshort(lfile,npos-base);
+ fseek(lfile,0,SEEK_END);
+ } else {
+ pos = ftell(lfile);
+ fseek(lfile,base+4*sizeof(uint16),SEEK_SET);
+ putshort(lfile,pos-base);
+ fseek(lfile,pos,SEEK_SET);
+ DumpClass(lfile,lclass,at->maxp.numGlyphs);
+ }
+ free(iclass); free(bclass); free(lclass);
+ }
+
+ ii=0;
+ for ( i=0; i<fpst->nccnt; ++i ) {
+ if ( initialclasses[ii]!=i ) {
+ /* This class isn't an initial one, so leave it's rule pointer NULL */
+ } else {
+ ++ii;
+ pos = ftell(lfile);
+ fseek(lfile,rulebase+i*sizeof(short),SEEK_SET);
+ putshort(lfile,pos-base);
+ fseek(lfile,pos,SEEK_SET);
+ subcnt = CntRulesStartingWithClass(fpst,i);
+ putshort(lfile,subcnt);
+ for ( j=0; j<subcnt; ++j )
+ putshort(lfile,0);
+ for ( j=k=0; k<fpst->rule_cnt; ++k ) if ( i==fpst->rules[k].u.class.nclasses[0] ) {
+ subpos = ftell(lfile);
+ fseek(lfile,pos+(1+j)*sizeof(short),SEEK_SET);
+ putshort(lfile,subpos-pos);
+ fseek(lfile,subpos,SEEK_SET);
+
+ for ( l=lc=0; l<fpst->rules[k].lookup_cnt; ++l )
+ if ( fpst->rules[k].lookups[l].lookup->lookup_index!=-1 )
+ ++lc;
+ if ( iscontext ) {
+ putshort(lfile,fpst->rules[k].u.class.ncnt);
+ putshort(lfile,lc);
+ for ( l=1; l<fpst->rules[k].u.class.ncnt; ++l )
+ putshort(lfile,fpst->rules[k].u.class.nclasses[l]);
+ } else {
+ putshort(lfile,fpst->rules[k].u.class.bcnt);
+ for ( l=0; l<fpst->rules[k].u.class.bcnt; ++l )
+ putshort(lfile,fpst->rules[k].u.class.bclasses[l]);
+ putshort(lfile,fpst->rules[k].u.class.ncnt);
+ for ( l=1; l<fpst->rules[k].u.class.ncnt; ++l )
+ putshort(lfile,fpst->rules[k].u.class.nclasses[l]);
+ putshort(lfile,fpst->rules[k].u.class.fcnt);
+ for ( l=0; l<fpst->rules[k].u.class.fcnt; ++l )
+ putshort(lfile,fpst->rules[k].u.class.fclasses[l]);
+ putshort(lfile,lc);
+ }
+ for ( l=0; l<fpst->rules[k].lookup_cnt; ++l )
+ if ( fpst->rules[k].lookups[l].lookup->lookup_index!=-1 ) {
+ putshort(lfile,fpst->rules[k].lookups[l].seq);
+ putshort(lfile,fpst->rules[k].lookups[l].lookup->lookup_index);
+ }
+ ++j;
+ }
+ }
+ }
+ free(initialclasses);
+
+ maxcontext = 0;
+ for ( i=0; i<fpst->rule_cnt; ++i ) {
+ curcontext = fpst->rules[i].u.class.ncnt+fpst->rules[i].u.class.bcnt+fpst->rules[i].u.class.fcnt;
+ if ( curcontext>maxcontext ) maxcontext = curcontext;
+ }
+ if ( maxcontext>at->os2.maxContext )
+ at->os2.maxContext = maxcontext;
+}
+
+static void dumpg___ContextChainCoverage(FILE *lfile,SplineFont *sf,
+ struct lookup_subtable *sub, struct alltabs *at) {
+ FPST *fpst = sub->fpst;
+ int iscontext = fpst->type==pst_contextpos || fpst->type==pst_contextsub;
+ uint32 base = ftell(lfile), ibase=0, lbase, bbase;
+ int i, l;
+ SplineChar **glyphs;
+ int curcontext;
+ int lc;
+
+ if ( fpst->rule_cnt!=1 )
+ IError("Bad rule cnt in coverage context lookup");
+ if ( fpst->format==pst_reversecoverage && fpst->rules[0].u.rcoverage.always1!=1 )
+ IError("Bad input count in reverse coverage lookup" );
+
+ putshort(lfile,3); /* Sub format 3 => coverage */
+ for ( l=lc=0; l<fpst->rules[0].lookup_cnt; ++l )
+ if ( fpst->rules[0].lookups[l].lookup->lookup_index!=-1 )
+ ++lc;
+ if ( iscontext ) {
+ putshort(lfile,fpst->rules[0].u.coverage.ncnt);
+ putshort(lfile,lc);
+ for ( i=0; i<fpst->rules[0].u.coverage.ncnt; ++i )
+ putshort(lfile,0);
+ for ( i=0; i<fpst->rules[0].lookup_cnt; ++i )
+ if ( fpst->rules[0].lookups[i].lookup->lookup_index!=-1 ) {
+ putshort(lfile,fpst->rules[0].lookups[i].seq);
+ putshort(lfile,fpst->rules[0].lookups[i].lookup->lookup_index);
+ }
+ for ( i=0; i<fpst->rules[0].u.coverage.ncnt; ++i ) {
+ uint32 pos = ftell(lfile);
+ fseek(lfile,base+6+2*i,SEEK_SET);
+ putshort(lfile,pos-base);
+ fseek(lfile,pos,SEEK_SET);
+ glyphs = OrderedGlyphsFromNames(sf,fpst->rules[0].u.coverage.ncovers[i]);
+ dumpcoveragetable(lfile,glyphs);
+ free(glyphs);
+ }
+ } else {
+ if ( fpst->format==pst_reversecoverage ) {
+ ibase = ftell(lfile);
+ putshort(lfile,0);
+ }
+ putshort(lfile,fpst->rules[0].u.coverage.bcnt);
+ bbase = ftell(lfile);
+ for ( i=0; i<fpst->rules[0].u.coverage.bcnt; ++i )
+ putshort(lfile,0);
+ if ( fpst->format==pst_coverage ) {
+ putshort(lfile,fpst->rules[0].u.coverage.ncnt);
+ ibase = ftell(lfile);
+ for ( i=0; i<fpst->rules[0].u.coverage.ncnt; ++i )
+ putshort(lfile,0);
+ }
+ putshort(lfile,fpst->rules[0].u.coverage.fcnt);
+ lbase = ftell(lfile);
+ for ( i=0; i<fpst->rules[0].u.coverage.fcnt; ++i )
+ putshort(lfile,0);
+ if ( fpst->format==pst_coverage ) {
+ putshort(lfile,lc);
+ for ( i=0; i<fpst->rules[0].lookup_cnt; ++i )
+ if ( fpst->rules[0].lookups[i].lookup->lookup_index!=-1 ) {
+ putshort(lfile,fpst->rules[0].lookups[i].seq);
+ putshort(lfile,fpst->rules[0].lookups[i].lookup->lookup_index);
+ }
+ } else { /* reverse coverage */
+ glyphs = SFGlyphsFromNames(sf,fpst->rules[0].u.rcoverage.replacements);
+ for ( i=0; glyphs[i]!=0; ++i );
+ putshort(lfile,i);
+ for ( i=0; glyphs[i]!=0; ++i )
+ putshort(lfile,glyphs[i]->ttf_glyph);
+ }
+ for ( i=0; i<fpst->rules[0].u.coverage.ncnt; ++i ) {
+ uint32 pos = ftell(lfile);
+ fseek(lfile,ibase+2*i,SEEK_SET);
+ putshort(lfile,pos-base);
+ fseek(lfile,pos,SEEK_SET);
+ glyphs = OrderedGlyphsFromNames(sf,fpst->rules[0].u.coverage.ncovers[i]);
+ dumpcoveragetable(lfile,glyphs);
+ free(glyphs);
+ }
+ for ( i=0; i<fpst->rules[0].u.coverage.bcnt; ++i ) {
+ uint32 pos = ftell(lfile);
+ fseek(lfile,bbase+2*i,SEEK_SET);
+ putshort(lfile,pos-base);
+ fseek(lfile,pos,SEEK_SET);
+ glyphs = OrderedGlyphsFromNames(sf,fpst->rules[0].u.coverage.bcovers[i]);
+ dumpcoveragetable(lfile,glyphs);
+ free(glyphs);
+ }
+ for ( i=0; i<fpst->rules[0].u.coverage.fcnt; ++i ) {
+ uint32 pos = ftell(lfile);
+ fseek(lfile,lbase+2*i,SEEK_SET);
+ putshort(lfile,pos-base);
+ fseek(lfile,pos,SEEK_SET);
+ glyphs = OrderedGlyphsFromNames(sf,fpst->rules[0].u.coverage.fcovers[i]);
+ dumpcoveragetable(lfile,glyphs);
+ free(glyphs);
+ }
+ }
+
+ curcontext = fpst->rules[0].u.coverage.ncnt+fpst->rules[0].u.coverage.bcnt+fpst->rules[0].u.coverage.fcnt;
+ if ( curcontext>at->os2.maxContext )
+ at->os2.maxContext = curcontext;
+}
+
+static void dumpg___ContextChain(FILE *lfile,SplineFont *sf,
+ struct lookup_subtable *sub, struct alltabs *at) {
+ FPST *fpst = sub->fpst;
+
+ switch ( fpst->format ) {
+ case pst_glyphs:
+ dumpg___ContextChainGlyphs(lfile,sf,sub,at);
+ break;
+ case pst_class:
+ dumpg___ContextChainClass(lfile,sf,sub,at);
+ break;
+ case pst_coverage:
+ case pst_reversecoverage:
+ dumpg___ContextChainCoverage(lfile,sf,sub,at);
+ break;
+ }
+
+ fseek(lfile,0,SEEK_END);
+
+}
+
+static void AnchorsAway(FILE *lfile,SplineFont *sf,
+ struct lookup_subtable *sub, struct glyphinfo *gi ) {
+ SplineChar **base, **lig, **mkmk;
+ AnchorClass *ac, *acfirst;
+ SplineChar ***marks;
+ int *subcnts;
+ int cmax, classcnt;
+ int i;
+
+ marks = galloc((cmax=20)*sizeof(SplineChar **));
+ subcnts = galloc(cmax*sizeof(int));
+
+ classcnt = 0;
+ acfirst = NULL;
+ for ( ac=sf->anchor; ac!=NULL; ac = ac->next ) {
+ ac->matches = false;
+ if ( ac->subtable==sub && !ac->processed ) {
+ if ( acfirst == NULL )
+ acfirst = ac;
+ if ( ac->type==act_curs )
+ continue;
+ else if ( ac->has_mark && ac->has_base ) {
+ ac->matches = ac->processed = true;
+ ++classcnt;
+ }
+ }
+ }
+ if ( classcnt>cmax ) {
+ marks = grealloc(marks,(cmax=classcnt+10)*sizeof(SplineChar **));
+ subcnts = grealloc(subcnts,cmax*sizeof(int));
+ }
+ AnchorClassDecompose(sf,acfirst,classcnt,subcnts,marks,&base,&lig,&mkmk,gi);
+ switch ( sub->lookup->lookup_type ) {
+ case gpos_mark2base:
+ if ( marks[0]!=NULL && base!=NULL )
+ dumpgposAnchorData(lfile,acfirst,at_basechar,marks,base,classcnt,gi);
+ break;
+ case gpos_mark2ligature:
+ if ( marks[0]!=NULL && lig!=NULL )
+ dumpgposAnchorData(lfile,acfirst,at_baselig,marks,lig,classcnt,gi);
+ break;
+ case gpos_mark2mark:
+ if ( marks[0]!=NULL && mkmk!=NULL )
+ dumpgposAnchorData(lfile,acfirst,at_basemark,marks,mkmk,classcnt,gi);
+ break;
+ default:
+ break;
+ }
+ for ( i=0; i<classcnt; ++i )
+ free(marks[i]);
+ free(base);
+ free(lig);
+ free(mkmk);
+ free(marks);
+ free(subcnts);
+}
+
+static int lookup_size_cmp(const void *_l1, const void *_l2) {
+ const OTLookup *l1 = _l1, *l2 = _l2;
+return( l1->lookup_length-l2->lookup_length );
+}
+
+static int FPSTRefersToOTL(FPST *fpst,OTLookup *otl) {
+ int i, j;
+
+ if ( fpst==NULL || fpst->type == pst_reversesub )
+return( false );
+ for ( i=0; i<fpst->rule_cnt; ++i ) {
+ for ( j=0; j< fpst->rules[i].lookup_cnt; ++j )
+ if ( fpst->rules[i].lookups[j].lookup == otl )
+return( true );
+ }
+return( false );
+}
+
+static int OnlyMac(OTLookup *otl, OTLookup *all) {
+ FeatureScriptLangList *features = otl->features;
+ int anymac = 0;
+ struct lookup_subtable *sub;
+
+ switch ( otl->lookup_type ) {
+ /* These two lookup types are mac only */
+ case kern_statemachine: case morx_indic: case morx_context: case morx_insert:
+return( true );
+ /* These lookup types are OpenType only */
+ case gsub_multiple: case gsub_alternate: case gsub_context:
+ case gsub_contextchain: case gsub_reversecchain:
+ case gpos_single: case gpos_cursive: case gpos_mark2base:
+ case gpos_mark2ligature: case gpos_mark2mark:
+ case gpos_context: case gpos_contextchain:
+return( false );
+ /* These two can be expressed in both, and might be either */
+ case gpos_pair: case gsub_single: case gsub_ligature:
+ for ( features = otl->features; features!=NULL; features = features->next ) {
+ if ( !features->ismac )
+return( false );
+ else
+ anymac = true;
+ }
+ /* Either it has no features at all (nested), or all its features */
+ /* are mac feature settings. Even if all are mac feature settings it */
+ /* might still be used as under control of a contextual feature */
+ /* so in both cases check for nested */
+ while ( all!=NULL ) {
+ if ( all!=otl && !all->unused &&
+ (all->lookup_type==gpos_context ||
+ all->lookup_type==gpos_contextchain ||
+ all->lookup_type==gsub_context ||
+ all->lookup_type==gsub_contextchain /*||
+ all->lookup_type==gsub_reversecchain*/ )) {
+ for ( sub=all->subtables; sub!=NULL; sub=sub->next ) if ( !sub->unused && sub->fpst!=NULL ) {
+ if ( FPSTRefersToOTL(sub->fpst,otl) )
+return( false );
+ }
+ }
+ all = all->next;
+ default:
+ break;
+ }
+ if ( anymac )
+return( true );
+ /* As far as I can tell, this lookup isn't used at all */
+ /* Let's output it anyway, just in case we ever support some other */
+ /* table that uses GPOS/GSUB lookups (I think JUST) */
+return( false );
+ }
+ /* Should never get here, but gcc probably thinks we might */
+return( true );
+}
+
+static FILE *G___figureLookups(SplineFont *sf,int is_gpos,
+ struct alltabs *at) {
+ OTLookup *otl;
+ struct lookup_subtable *sub;
+ int index, i;
+ FILE *final;
+ FILE *lfile = tmpfile();
+ OTLookup **sizeordered;
+ OTLookup *all = is_gpos ? sf->gpos_lookups : sf->gsub_lookups;
+ char *buffer;
+ int len;
+
+ index = 0;
+ for ( otl=all; otl!=NULL; otl=otl->next ) {
+ if ( otl->unused || OnlyMac(otl,all))
+ otl->lookup_index = -1;
+ else
+ otl->lookup_index = index++;
+ }
+ for ( otl=all; otl!=NULL; otl=otl->next ) {
+ if ( otl->lookup_index!=-1 ) {
+ otl->lookup_offset = ftell(lfile);
+ for ( sub = otl->subtables; sub!=NULL; sub=sub->next ) {
+ sub->extra_subtables = NULL;
+ if ( sub->unused )
+ sub->subtable_offset = -1;
+ else {
+ sub->subtable_offset = ftell(lfile);
+ switch ( otl->lookup_type ) {
+ /* GPOS lookup types */
+ case gpos_single:
+ dumpGPOSsimplepos(lfile,sf,sub);
+ break;
+
+ case gpos_pair:
+ if ( at->os2.maxContext<2 )
+ at->os2.maxContext = 2;
+ if ( sub->kc!=NULL )
+ dumpgposkernclass(lfile,sf,sub,at);
+ else
+ dumpGPOSpairpos(lfile,sf,sub);
+ break;
+
+ case gpos_cursive:
+ dumpgposCursiveAttach(lfile,sf,sub,&at->gi);
+ break;
+
+ case gpos_mark2base:
+ case gpos_mark2ligature:
+ case gpos_mark2mark:
+ AnchorsAway(lfile,sf,sub,&at->gi);
+ break;
+
+ case gpos_contextchain:
+ case gpos_context:
+ dumpg___ContextChain(lfile,sf,sub,at);
+ break;
+
+ /* GSUB lookup types */
+ case gsub_single:
+ dumpGSUBsimplesubs(lfile,sf,sub);
+ break;
+
+ case gsub_multiple:
+ case gsub_alternate:
+ dumpGSUBmultiplesubs(lfile,sf,sub);
+ break;
+
+ case gsub_ligature:
+ dumpGSUBligdata(lfile,sf,sub,at);
+ break;
+
+ case gsub_contextchain:
+ case gsub_context:
+ case gsub_reversecchain:
+ dumpg___ContextChain(lfile,sf,sub,at);
+ break;
+ default:
+ break;
+ }
+ if ( ftell(lfile)-sub->subtable_offset==0 ) {
+ IError( "Lookup sub table, %s in %s, contains no data.\n",
+ sub->subtable_name, sub->lookup->lookup_name );
+ sub->unused = true;
+ sub->subtable_offset = -1;
+ } else if ( sub->extra_subtables==NULL &&
+ ftell(lfile)-sub->subtable_offset>65535 )
+ IError( "Lookup sub table, %s in %s, is too big. Will not be useable.\n",
+ sub->subtable_name, sub->lookup->lookup_name );
+ }
+ }
+ otl->lookup_length = ftell(lfile)-otl->lookup_offset;
+ }
+ }
+ if ( is_gpos )
+ AnchorGuessContext(sf,at);
+
+ /* We don't need to reorder short files */
+ if ( ftell(lfile)<65536 )
+return( lfile );
+
+ /* Order the lookups so that the smallest ones come first */
+ /* thus we are less likely to need extension tables */
+ /* I think it's better to order the entire lookup rather than ordering the*/
+ /* subtables -- since the extension subtable would be required for all */
+ /* subtables in the lookup, so might as well keep them all together */
+ sizeordered = galloc(index*sizeof(OTLookup *));
+ for ( otl=is_gpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl=otl->next )
+ if ( otl->lookup_index!=-1 )
+ sizeordered[ otl->lookup_index ] = otl;
+ qsort(sizeordered,index,sizeof(OTLookup *),lookup_size_cmp);
+
+ final = tmpfile();
+ buffer = galloc(32768);
+ for ( i=0; i<index; ++i ) {
+ otl = sizeordered[i];
+ fseek(lfile,otl->lookup_offset,SEEK_SET);
+ otl->lookup_offset = ftell(final);
+ len = otl->lookup_length;
+ while ( len>=32768 ) {
+ int done = fread(buffer,1,32768,lfile);
+ if ( done==EOF )
+ break;
+ fwrite(buffer,1,done,final);
+ len -= done;
+ }
+ if ( len>0 && len<=32768 ) {
+ int done = fread(buffer,1,len,lfile);
+ if ( done==EOF )
+ break;
+ fwrite(buffer,1,done,final);
+ }
+ }
+ free(buffer);
+ free(sizeordered);
+ fclose(lfile);
+return( final );
+}
+
+struct ginfo {
+ int fmax, fcnt;
+ struct feat_lookups {
+ uint32 tag;
+ int lcnt;
+ OTLookup **lookups;
+ int feature_id; /* Initially consecutive, but may be rearranged by sorting */
+ } *feat_lookups;
+ int sc;
+ struct scriptset {
+ uint32 script;
+ int lc;
+ struct langsys {
+ uint32 lang;
+ int fc;
+ int *feature_id;
+ int same_as;
+ int32 offset;
+ } *langsys;
+ } *scripts;
+};
+
+static int FindOrMakeNewFeatureLookup(struct ginfo *ginfo,OTLookup **lookups,
+ uint32 tag) {
+ int i, j;
+
+ for ( i=0; i<ginfo->fcnt; ++i ) {
+ if ( ginfo->feat_lookups[i].tag!= tag )
+ continue;
+ if ( lookups==NULL && ginfo->feat_lookups[i].lookups==NULL ) /* 'size' feature */
+return( i );
+ if ( lookups==NULL || ginfo->feat_lookups[i].lookups==NULL )
+ continue;
+ for ( j=0; lookups[j]!=NULL && ginfo->feat_lookups[i].lookups[j]!=NULL; ++j )
+ if ( ginfo->feat_lookups[i].lookups[j]!=lookups[j] )
+ break;
+ if ( ginfo->feat_lookups[i].lookups[j]==lookups[j] ) {
+ free(lookups);
+return( i );
+ }
+ }
+ if ( ginfo->fcnt>=ginfo->fmax )
+ ginfo->feat_lookups = grealloc(ginfo->feat_lookups,(ginfo->fmax+=20)*sizeof(struct feat_lookups));
+ ginfo->feat_lookups[i].feature_id = i;
+ ginfo->feat_lookups[i].tag = tag;
+ ginfo->feat_lookups[i].lookups = lookups;
+ j=0;
+ if ( lookups!=NULL ) for ( ; lookups[j]!=NULL; ++j );
+ ginfo->feat_lookups[i].lcnt = j;
+ ++ginfo->fcnt;
+return( i );
+}
+
+static int feat_alphabetize(const void *_fl1, const void *_fl2) {
+ const struct feat_lookups *fl1 = _fl1, *fl2 = _fl2;
+
+ if ( fl1->tag<fl2->tag )
+return( -1 );
+ if ( fl1->tag>fl2->tag )
+return( 1 );
+
+return( 0 );
+}
+
+static int numeric_order(const void *_i1, const void *_i2) {
+ int i1 = *(const int *) _i1, i2 = *(const int *) _i2;
+
+ if ( i1<i2 )
+return( -1 );
+ if ( i1>i2 )
+return( 1 );
+
+return( 0 );
+}
+
+static int LangSysMatch(struct scriptset *s,int ils1, int ils2 ) {
+ struct langsys *ls1 = &s->langsys[ils1], *ls2 = &s->langsys[ils2];
+ int i;
+
+ if ( ls1->fc!=ls2->fc )
+return( false );
+ for ( i=0; i<ls1->fc; ++i )
+ if ( ls1->feature_id[i]!=ls2->feature_id[i] )
+return( false );
+
+return( true );
+}
+
+static void FindFeatures(SplineFont *sf,int is_gpos,struct ginfo *ginfo) {
+ uint32 *scripts, *langs, *features;
+ OTLookup **lookups;
+ int sc, lc, fc, j;
+
+ memset(ginfo,0,sizeof(struct ginfo));
+
+ scripts = SFScriptsInLookups(sf,is_gpos);
+ if ( scripts==NULL ) /* All lookups unused */
+return;
+ for ( sc=0; scripts[sc]!=0; ++sc );
+ ginfo->scripts = galloc(sc*sizeof(struct scriptset));
+ ginfo->sc = sc;
+ for ( sc=0; scripts[sc]!=0; ++sc ) {
+ langs = SFLangsInScript(sf,is_gpos,scripts[sc]);
+ for ( lc=0; langs[lc]!=0; ++lc );
+ ginfo->scripts[sc].script = scripts[sc];
+ ginfo->scripts[sc].lc = lc;
+ ginfo->scripts[sc].langsys = galloc(lc*sizeof(struct langsys));
+ for ( lc=0; langs[lc]!=0; ++lc ) {
+ features = SFFeaturesInScriptLang(sf,is_gpos,scripts[sc],langs[lc]);
+ for ( fc=0; features[fc]!=0; ++fc );
+ ginfo->scripts[sc].langsys[lc].lang = langs[lc];
+ ginfo->scripts[sc].langsys[lc].fc = fc;
+ ginfo->scripts[sc].langsys[lc].feature_id = galloc(fc*sizeof(int));
+ ginfo->scripts[sc].langsys[lc].same_as = -1;
+ for ( fc=0; features[fc]!=0; ++fc ) {
+ lookups = SFLookupsInScriptLangFeature(sf,is_gpos,scripts[sc],langs[lc],features[fc]);
+ ginfo->scripts[sc].langsys[lc].feature_id[fc] =
+ FindOrMakeNewFeatureLookup(ginfo,lookups,features[fc]);
+ /* lookups is freed or used by FindOrMakeNewFeatureLookup */
+ }
+ free(features);
+ }
+ free(langs);
+ }
+ free(scripts);
+
+ qsort(ginfo->feat_lookups,ginfo->fcnt,sizeof(struct feat_lookups),feat_alphabetize);
+
+ /* Now we've disordered the features. Find each feature_id and turn it back*/
+ /* into a feature number */
+ for ( sc=0; sc<ginfo->sc; ++sc ) {
+ for ( lc=0; lc<ginfo->scripts[sc].lc; ++lc ) {
+ int fcmax = ginfo->scripts[sc].langsys[lc].fc;
+ int *feature_id = ginfo->scripts[sc].langsys[lc].feature_id;
+ for ( fc=0; fc<fcmax; ++fc ) {
+ int id = feature_id[fc];
+ for ( j=0; j<ginfo->fcnt; ++j )
+ if ( id==ginfo->feat_lookups[j].feature_id )
+ break;
+ feature_id[fc] = j;
+ }
+ qsort(feature_id,fcmax,sizeof(int),numeric_order);
+ }
+ /* See if there are langsys tables which use exactly the same features*/
+ /* They can use the same entry in the file. This optimization seems */
+ /* to be required for Japanese vertical writing to work in Uniscribe.*/
+ for ( lc=0; lc<ginfo->scripts[sc].lc; ++lc ) {
+ for ( j=0; j<lc; ++j )
+ if ( LangSysMatch(&ginfo->scripts[sc],j,lc) ) {
+ ginfo->scripts[sc].langsys[lc].same_as = j;
+ break;
+ }
+ }
+ }
+}
+
+
+static void dump_script_table(FILE *g___,struct scriptset *ss,struct ginfo *ginfo) {
+ int i, lcnt, dflt_lang = -1;
+ uint32 base;
+ int j, req_index;
+ uint32 offset;
+
+ /* Count the languages, and find default */
+ for ( lcnt=0; lcnt<ss->lc; ++lcnt )
+ if ( ss->langsys[lcnt].lang==DEFAULT_LANG )
+ dflt_lang = lcnt;
+ if ( dflt_lang != -1 )
+ --lcnt;
+
+ base = ftell(g___);
+ putshort(g___, 0 ); /* fill in later, Default Lang Sys */
+ putshort(g___,lcnt);
+ for ( i=0; i<ss->lc; ++i ) if ( i!=dflt_lang ) {
+ putlong(g___,ss->langsys[i].lang); /* Language tag */
+ putshort(g___,0); /* Fill in later, offset to langsys */
+ }
+
+ for ( lcnt=0; lcnt<ss->lc; ++lcnt ) {
+ if ( ss->langsys[lcnt].same_as!=-1 )
+ offset = ss->langsys[ ss->langsys[lcnt].same_as ].offset;
+ else {
+ offset = ftell(g___);
+ ss->langsys[lcnt].offset = offset;
+ }
+ fseek(g___,lcnt==dflt_lang ? base :
+ lcnt<dflt_lang ? base + 4 + lcnt*6 +4 :
+ base + 4 + (lcnt-1)*6 +4 , SEEK_SET );
+ putshort(g___,offset-base);
+ fseek(g___,0,SEEK_END);
+ if ( ss->langsys[lcnt].same_as==-1 ) {
+ req_index = -1;
+ for ( j=0; j<ss->langsys[lcnt].fc; ++j ) {
+ if ( ginfo->feat_lookups[ ss->langsys[lcnt].feature_id[j] ].tag == REQUIRED_FEATURE ) {
+ req_index = ss->langsys[lcnt].feature_id[j];
+ break;
+ }
+ }
+ putshort(g___,0); /* LookupOrder, always NULL */
+ putshort(g___,req_index); /* index of required feature, if any */
+ putshort(g___,ss->langsys[lcnt].fc - (req_index!=-1));
+ /* count of non-required features */
+ for ( j=0; j<ss->langsys[lcnt].fc; ++j ) if ( j!=req_index )
+ putshort(g___,ss->langsys[lcnt].feature_id[j]);
+ }
+ }
+}
+
+static FILE *g___FigureExtensionSubTables(OTLookup *all,int startoffset,int is_gpos) {
+ OTLookup *otf;
+ struct lookup_subtable *sub;
+ int len, len2, gotmore;
+ FILE *efile;
+ int i, offset, cnt;
+ int any= false;
+
+ if ( all==NULL )
+return( NULL );
+ gotmore = true; cnt=len=0;
+ while ( gotmore ) {
+ gotmore = false;
+ offset = startoffset + 8*cnt;
+ for ( otf=all; otf!=NULL; otf=otf->next ) if ( otf->lookup_index!=-1 ) {
+ if ( otf->needs_extension )
+ continue;
+ for ( sub = otf->subtables; sub!=NULL; sub=sub->next ) {
+ if ( sub->subtable_offset==-1 )
+ continue;
+ if ( sub->extra_subtables!=NULL ) {
+ for ( i=0; sub->extra_subtables[i]!=-1; ++i ) {
+ if ( sub->extra_subtables[i]+offset>65535 )
+ break;
+ }
+ if ( sub->extra_subtables[i]!=-1 )
+ break;
+ } else if ( sub->subtable_offset+offset>65535 )
+ break;
+ }
+ if ( sub!=NULL ) {
+ if ( !any ) {
+ ff_post_notice(_("Lookup potentially too big"),
+ _("Lookup %s has an\noffset bigger than 65535 bytes. This means\nFontForge must use an extension lookup to output it.\nNot all applications support extension lookups."),
+ otf->lookup_name );
+ any = true;
+ }
+ otf->needs_extension = true;
+ gotmore = true;
+ len += 8*otf->subcnt;
+ ++cnt;
+ }
+ offset -= 6+2*otf->subcnt;
+ }
+ }
+
+ if ( cnt==0 ) /* No offset overflows */
+return( NULL );
+
+ /* Now we've worked out which lookups need extension tables and marked them*/
+ /* Generate the extension tables, and update the offsets to reflect the size */
+ /* of the extensions */
+ efile = tmpfile();
+
+ len2 = 0;
+ for ( otf=all; otf!=NULL; otf=otf->next ) if ( otf->lookup_index!=-1 ) {
+ if ( otf->needs_extension ) {
+ putshort(efile,1); /* exten subtable format (there's only one) */
+ putshort(efile,otf->lookup_type&0xff);
+ }
+ for ( sub = otf->subtables; sub!=NULL; sub=sub->next ) {
+ if ( sub->subtable_offset==-1 )
+ continue;
+ if ( sub->extra_subtables!=NULL ) {
+ for ( i=0; sub->extra_subtables[i]!=-1; ++i ) {
+ sub->extra_subtables[i] += len;
+ if ( otf->needs_extension ) {
+ int off = ftell(efile);
+ putshort(efile,1); /* exten subtable format (there's only one) */
+ putshort(efile,otf->lookup_type&0xff);
+ putlong(efile,sub->extra_subtables[i]-len2);
+ sub->extra_subtables[i] = off;
+ len2+=8;
+ }
+ }
+ } else {
+ sub->subtable_offset += len;
+ if ( otf->needs_extension ) {
+ int off = ftell(efile);
+ putshort(efile,1); /* exten subtable format (there's only one) */
+ putshort(efile,otf->lookup_type&0xff);
+ putlong(efile,sub->subtable_offset-len2);
+ sub->subtable_offset = off;
+ len2+=8;
+ }
+ }
+ }
+ }
+
+return( efile );
+}
+
+static FILE *dumpg___info(struct alltabs *at, SplineFont *sf,int is_gpos) {
+ /* Dump out either a gpos or a gsub table. gpos handles kerns, gsub ligs */
+ /* we assume that SFFindUnusedLookups has been called */
+ FILE *lfile, *g___, *efile;
+ uint32 lookup_list_table_start, feature_list_table_start, here, scripts_start_offset;
+ struct ginfo ginfo;
+ int32 size_params_loc, size_params_ptr;
+ int i,j, cnt, scnt, offset;
+ OTLookup *otf, *all;
+ struct lookup_subtable *sub;
+ char *buf;
+
+ FindFeatures(sf,is_gpos,&ginfo);
+ if ( ginfo.sc==0 )
+return( NULL );
+ lfile = G___figureLookups(sf,is_gpos,at);
+
+ if ( ginfo.sc==0 && ftell(lfile)==0 ) {
+ /* ftell(lfile)==0 => There are no lookups for this table */
+ /* ginfo.sc==0 => There are no scripts. */
+ /* If both are true then we don't need to output the table */
+ /* It is perfectly possible to have lookups without scripts */
+ /* (if some other table refered to them -- we don't currently */
+ /* support this, but we might some day). */
+ /* It is also possible to have scripts without lookups (to get */
+ /* around a bug in Uniscribe which only processes some scripts */
+ /* if both GPOS and GSUB entries are present. So we share scripts */
+ /* between the two tables */
+ fclose(lfile);
+ /* if ginfo.sc==0 then there will be nothing to free in the ginfo struct*/
+return( NULL );
+ }
+
+ g___ = tmpfile();
+
+ putlong(g___,0x10000); /* version number */
+ putshort(g___,10); /* offset to script table */
+ putshort(g___,0); /* offset to features. Come back for this */
+ putshort(g___,0); /* offset to lookups. Come back for this */
+/* Now the scripts */
+ scripts_start_offset = ftell(g___);
+ putshort(g___,ginfo.sc);
+ for ( i=0; i<ginfo.sc; ++i ) {
+ putlong(g___,ginfo.scripts[i].script);
+ putshort(g___,0); /* fix up later */
+ }
+
+ /* Ok, that was the script_list_table which gives each script an offset */
+ /* Now for each script we provide a Script table which contains an */
+ /* offset to a bunch of features for the default language, and a */
+ /* a more complex situation for non-default languages. */
+ offset=2+4; /* To the script pointer at the start of table */
+ for ( i=0; i<ginfo.sc; ++i ) {
+ here = ftell(g___);
+ fseek(g___,scripts_start_offset+offset,SEEK_SET);
+ putshort(g___,here-scripts_start_offset);
+ offset+=6;
+ fseek(g___,here,SEEK_SET);
+ dump_script_table(g___,&ginfo.scripts[i],&ginfo);
+ }
+ /* And that should finish all the scripts/languages */
+
+ /* so free the ginfo script/lang data */
+ for ( i=0; i<ginfo.sc; ++i ) {
+ for ( j=0; j<ginfo.scripts[i].lc; ++j ) {
+ free( ginfo.scripts[i].langsys[j].feature_id );
+ }
+ free( ginfo.scripts[i].langsys );
+ }
+ free( ginfo.scripts );
+
+/* Now the features */
+ feature_list_table_start = ftell(g___);
+ fseek(g___,6,SEEK_SET);
+ putshort(g___,feature_list_table_start);
+ fseek(g___,0,SEEK_END);
+ putshort(g___,ginfo.fcnt); /* Number of features */
+ offset = 2+6*ginfo.fcnt; /* Offset to start of first feature table from beginning of feature_list */
+ for ( i=0; i<ginfo.fcnt; ++i ) {
+ putlong(g___,ginfo.feat_lookups[i].tag);
+ putshort(g___,offset);
+ offset += 4+2*ginfo.feat_lookups[i].lcnt;
+ }
+ /* for each feature, one feature table */
+ size_params_ptr = 0;
+ for ( i=0; i<ginfo.fcnt; ++i ) {
+ if ( ginfo.feat_lookups[i].tag==CHR('s','i','z','e') )
+ size_params_ptr = ftell(g___);
+ putshort(g___,0); /* No feature params (we'll come back for 'size') */
+ putshort(g___,ginfo.feat_lookups[i].lcnt);/* this many lookups */
+ for ( j=0; j<ginfo.feat_lookups[i].lcnt; ++j )
+ putshort(g___,ginfo.feat_lookups[i].lookups[j]->lookup_index );
+ /* index of each lookup */
+ }
+ if ( size_params_ptr!=0 ) {
+ size_params_loc = ftell(g___);
+ fseek(g___,size_params_ptr,SEEK_SET);
+ /* When Adobe first released fonts containing the 'size' feature */
+ /* they did not follow the spec, and the offset to the size parameters */
+ /* was relative to the wrong location. They claim (Aug 2006) that */
+ /* this has been fixed. FF used to do what Adobe did. Many programs */
+ /* expect broken sizes tables now. Therefore allow the user to chose */
+ /* which kind to output */
+#if 0
+ putshort(g___,size_params_loc-((at->gi.flags&ttf_flag_brokensize)?feature_list_table_start:size_params_ptr));
+#else
+ putshort(g___,size_params_loc-size_params_ptr);
+#endif
+ fseek(g___,size_params_loc,SEEK_SET);
+ putshort(g___,sf->design_size);
+ if ( sf->fontstyle_id!=0 || sf->fontstyle_name!=NULL ||
+ sf->design_range_bottom!=0 || sf->design_range_top!=0 ) {
+ putshort(g___,sf->fontstyle_id);
+ at->fontstyle_name_strid = at->next_strid++;
+ putshort(g___,at->fontstyle_name_strid);
+ putshort(g___,sf->design_range_bottom);
+ putshort(g___,sf->design_range_top);
+ } else {
+ putshort(g___,0);
+ putshort(g___,0);
+ putshort(g___,0);
+ putshort(g___,0);
+ }
+ }
+ /* And that should finish all the features */
+
+ /* so free the ginfo feature data */
+ for ( i=0; i<ginfo.fcnt; ++i )
+ free( ginfo.feat_lookups[i].lookups );
+ free( ginfo.feat_lookups );
+
+/* Now the lookups */
+ all = is_gpos ? sf->gpos_lookups : sf->gsub_lookups;
+ for ( cnt=0, otf = all; otf!=NULL; otf=otf->next ) {
+ if ( otf->lookup_index!=-1 )
+ ++cnt;
+ }
+ lookup_list_table_start = ftell(g___);
+ fseek(g___,8,SEEK_SET);
+ putshort(g___,lookup_list_table_start);
+ fseek(g___,0,SEEK_END);
+ putshort(g___,cnt);
+ offset = 2+2*cnt; /* Offset to start of first lookup table from beginning of lookup list */
+ for ( otf = all; otf!=NULL; otf=otf->next ) if ( otf->lookup_index!=-1 ) {
+ putshort(g___,offset);
+ for ( scnt=0, sub = otf->subtables; sub!=NULL; sub=sub->next ) {
+ if ( sub->subtable_offset==-1 )
+ continue;
+ else if ( sub->extra_subtables!=NULL ) {
+ for ( i=0; sub->extra_subtables[i]!=-1; ++i )
+ ++scnt;
+ } else
+ ++scnt;
+ }
+ otf->subcnt = scnt;
+ offset += 6+2*scnt; /* 6 bytes header +2 per lookup */
+ }
+ offset -= 2+2*cnt;
+ /* now the lookup tables */
+ /* do we need any extension sub-tables? */
+ efile=g___FigureExtensionSubTables(all,offset,is_gpos);
+ for ( otf = all; otf!=NULL; otf=otf->next ) if ( otf->lookup_index!=-1 ) {
+ putshort(g___,!otf->needs_extension ? (otf->lookup_type&0xff)
+ : is_gpos ? 9 : 7);
+ putshort(g___,otf->lookup_flags);
+ putshort(g___,otf->subcnt);
+ for ( sub = otf->subtables; sub!=NULL; sub=sub->next ) {
+ if ( sub->subtable_offset==-1 )
+ continue;
+ else if ( sub->extra_subtables!=NULL ) {
+ for ( i=0; sub->extra_subtables[i]!=-1; ++i )
+ putshort(g___,offset+sub->extra_subtables[i]);
+ } else
+ putshort(g___,offset+sub->subtable_offset);
+
+ /* Offset to lookup data which is in the temp file */
+ /* we keep adjusting offset so it reflects the distance between */
+ /* here and the place where the temp file will start, and then */
+ /* we need to skip l->offset bytes in the temp file */
+ /* If it's a big GPOS/SUB table we may also need some extension */
+ /* pointers, but FigureExtension will adjust for that */
+ }
+ offset -= 6+2*otf->subcnt;
+ }
+
+ buf = galloc(8096);
+ if ( efile!=NULL ) {
+ rewind(efile);
+ while ( (i=fread(buf,1,8096,efile))>0 )
+ fwrite(buf,1,i,g___);
+ fclose(efile);
+ }
+ rewind(lfile);
+ while ( (i=fread(buf,1,8096,lfile))>0 )
+ fwrite(buf,1,i,g___);
+ fclose(lfile);
+ free(buf);
+ for ( otf = all; otf!=NULL; otf=otf->next ) if ( otf->lookup_index!=-1 ) {
+ for ( sub = otf->subtables; sub!=NULL; sub=sub->next ) {
+ free(sub->extra_subtables);
+ sub->extra_subtables = NULL;
+ }
+ }
+return( g___ );
+}
+
+void otf_dumpgpos(struct alltabs *at, SplineFont *sf) {
+ /* Open Type, bless its annoying little heart, doesn't store kern info */
+ /* in the kern table. Of course not, how silly of me to think it might */
+ /* be consistent. It stores it in the much more complicated gpos table */
+ AnchorClass *ac;
+
+ for ( ac=sf->anchor; ac!=NULL; ac=ac->next )
+ ac->processed = false;
+
+ at->gpos = dumpg___info(at, sf,true);
+ if ( at->gpos!=NULL ) {
+ at->gposlen = ftell(at->gpos);
+ if ( at->gposlen&1 ) putc('\0',at->gpos);
+ if ( (at->gposlen+1)&2 ) putshort(at->gpos,0);
+ }
+}
+
+void otf_dumpgsub(struct alltabs *at, SplineFont *sf) {
+ /* substitutions such as: Ligatures, cjk vertical rotation replacement, */
+ /* arabic forms, small caps, ... */
+ SFLigaturePrepare(sf);
+ at->gsub = dumpg___info(at, sf, false);
+ if ( at->gsub!=NULL ) {
+ at->gsublen = ftell(at->gsub);
+ if ( at->gsublen&1 ) putc('\0',at->gsub);
+ if ( (at->gsublen+1)&2 ) putshort(at->gsub,0);
+ }
+ SFLigatureCleanup(sf);
+}
+
+static int LigCaretCnt(SplineChar *sc) {
+ PST *pst;
+
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->type == pst_lcaret )
+return( pst->u.lcaret.cnt );
+ }
+return( 0 );
+}
+
+static void DumpLigCarets(FILE *gdef,SplineChar *sc) {
+ PST *pst;
+ int i, j, offset;
+
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->type == pst_lcaret )
+ break;
+ }
+ if ( pst==NULL )
+return;
+
+ if ( SCRightToLeft(sc) ) {
+ for ( i=0; i<pst->u.lcaret.cnt-1; ++i )
+ for ( j=i+1; j<pst->u.lcaret.cnt; ++j )
+ if ( pst->u.lcaret.carets[i]<pst->u.lcaret.carets[j] ) {
+ int16 temp = pst->u.lcaret.carets[i];
+ pst->u.lcaret.carets[i] = pst->u.lcaret.carets[j];
+ pst->u.lcaret.carets[j] = temp;
+ }
+ } else {
+ for ( i=0; i<pst->u.lcaret.cnt-1; ++i )
+ for ( j=i+1; j<pst->u.lcaret.cnt; ++j )
+ if ( pst->u.lcaret.carets[i]>pst->u.lcaret.carets[j] ) {
+ int16 temp = pst->u.lcaret.carets[i];
+ pst->u.lcaret.carets[i] = pst->u.lcaret.carets[j];
+ pst->u.lcaret.carets[j] = temp;
+ }
+ }
+
+ putshort(gdef,pst->u.lcaret.cnt); /* this many carets */
+ offset = sizeof(uint16) + sizeof(uint16)*pst->u.lcaret.cnt;
+ for ( i=0; i<pst->u.lcaret.cnt; ++i ) {
+ putshort(gdef,offset);
+ offset+=4;
+ }
+ for ( i=0; i<pst->u.lcaret.cnt; ++i ) {
+ putshort(gdef,1); /* Format 1 */
+ putshort(gdef,pst->u.lcaret.carets[i]);
+ }
+}
+
+int gdefclass(SplineChar *sc) {
+ PST *pst;
+ AnchorPoint *ap;
+
+ if ( sc->glyph_class!=0 )
+return( sc->glyph_class-1 );
+
+ if ( strcmp(sc->name,".notdef")==0 )
+return( 0 );
+
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->type == pst_ligature )
+return( 2 ); /* Ligature */
+ }
+
+ ap=sc->anchor;
+ while ( ap!=NULL && (ap->type==at_centry || ap->type==at_cexit) )
+ ap = ap->next;
+ if ( ap!=NULL && (ap->type==at_mark || ap->type==at_basemark) )
+return( 3 );
+ else
+return( 1 );
+ /* I not quite sure what a componant glyph is. Probably something that */
+ /* is not in the cmap table and is referenced in other glyphs */
+ /* Anyway I never return class 4 */ /* (I've never seen it used by others) */
+}
+
+void otf_dumpgdef(struct alltabs *at, SplineFont *sf) {
+ /* In spite of what the open type docs say, this table does appear to be */
+ /* required (at least the glyph class def table) if we do mark to base */
+ /* positioning */
+ /* I was wondering at the apperant contradiction: something can be both a */
+ /* base glyph and a ligature component, but it appears that the component*/
+ /* class is unused and everything is a base unless it is a ligature or */
+ /* mark */
+ /* All my example fonts ignore the attachment list subtable and the mark */
+ /* attach class def subtable, so I shall too */
+ /* Ah. Some indic fonts need the mark attach class subtable for greater */
+ /* control of lookup flags */
+ /* All my example fonts contain a ligature caret list subtable, which is */
+ /* empty. Odd, but perhaps important */
+ PST *pst;
+ int i,j,k, lcnt, needsclass;
+ int pos, offset;
+ int cnt, start, last, lastval;
+ SplineChar **glyphs, *sc;
+
+ /* Don't look in the cidmaster if we are only dumping one subfont */
+ if ( sf->cidmaster && sf->cidmaster->glyphs!=NULL ) sf = sf->cidmaster;
+ else if ( sf->mm!=NULL ) sf=sf->mm->normal;
+
+ glyphs = NULL;
+ for ( k=0; k<2; ++k ) {
+ lcnt = 0;
+ needsclass = false;
+ for ( i=0; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
+ SplineChar *sc = sf->glyphs[at->gi.bygid[i]];
+ if ( sc->glyph_class!=0 || gdefclass(sc)!=1 )
+ needsclass = true;
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->type == pst_lcaret ) {
+ for ( j=pst->u.lcaret.cnt-1; j>=0; --j )
+ if ( pst->u.lcaret.carets[j]!=0 )
+ break;
+ if ( j!=-1 )
+ break;
+ }
+ }
+ if ( pst!=NULL ) {
+ if ( glyphs!=NULL ) glyphs[lcnt] = sc;
+ ++lcnt;
+ }
+ }
+ if ( lcnt==0 )
+ break;
+ if ( glyphs!=NULL )
+ break;
+ glyphs = galloc((lcnt+1)*sizeof(SplineChar *));
+ glyphs[lcnt] = NULL;
+ }
+ if ( !needsclass && lcnt==0 && sf->mark_class_cnt==0 )
+return; /* No anchor positioning, no ligature carets */
+
+ at->gdef = tmpfile();
+ putlong(at->gdef,0x00010000); /* Version */
+ putshort(at->gdef, needsclass ? 12 : 0 ); /* glyph class defn table */
+ putshort(at->gdef, 0 ); /* attachment list table */
+ putshort(at->gdef, 0 ); /* ligature caret table (come back and fix up later) */
+ putshort(at->gdef, 0 ); /* mark attachment class table */
+
+ /* Glyph class subtable */
+ if ( needsclass ) {
+ /* Mark shouldn't conflict with anything */
+ /* Ligature is more important than Base */
+ /* Component is not used */
+#if 1 /* ttx can't seem to support class format type 1 so let's output type 2 */
+ for ( j=0; j<2; ++j ) {
+ cnt = 0;
+ for ( i=0; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
+ sc = sf->glyphs[at->gi.bygid[i]];
+ if ( sc!=NULL && sc->ttf_glyph!=-1 ) {
+ lastval = gdefclass(sc);
+ start = last = i;
+ for ( ; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
+ sc = sf->glyphs[at->gi.bygid[i]];
+ if ( gdefclass(sc)!=lastval )
+ break;
+ last = i;
+ }
+ --i;
+ if ( lastval!=0 ) {
+ if ( j==1 ) {
+ putshort(at->gdef,start);
+ putshort(at->gdef,last);
+ putshort(at->gdef,lastval);
+ }
+ ++cnt;
+ }
+ }
+ }
+ if ( j==0 ) {
+ putshort(at->gdef,2); /* class format 2, range list by class */
+ putshort(at->gdef,cnt);
+ }
+ }
+#else
+ putshort(at->gdef,1); /* class format 1 complete list of glyphs */
+ putshort(at->gdef,0); /* First glyph */
+ putshort(at->gdef,at->maxp.numGlyphs );
+ j=0;
+ for ( i=0; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
+ for ( ; j<i; ++j )
+ putshort(at->gdef,1); /* Any hidden characters (like notdef) default to base */
+ putshort(at->gdef,gdefclass(sf->glyphs[at->gi.bygid[i]]));
+ ++j;
+ }
+#endif
+ }
+
+ /* Ligature caret subtable. Always include this if we have a GDEF */
+ pos = ftell(at->gdef);
+ fseek(at->gdef,8,SEEK_SET); /* location of lig caret table offset */
+ putshort(at->gdef,pos);
+ fseek(at->gdef,0,SEEK_END);
+ if ( lcnt==0 ) {
+ /* It always seems to be present, even if empty */
+ putshort(at->gdef,4); /* Offset to (empty) coverage table */
+ putshort(at->gdef,0); /* no ligatures */
+ putshort(at->gdef,2); /* coverage table format 2 */
+ putshort(at->gdef,0); /* no ranges in coverage table */
+ } else {
+ pos = ftell(at->gdef); /* coverage location */
+ putshort(at->gdef,0); /* Offset to coverage table (fix up later) */
+ putshort(at->gdef,lcnt);
+ offset = 2*lcnt+4;
+ for ( i=0; i<lcnt; ++i ) {
+ putshort(at->gdef,offset);
+ offset+=2+6*LigCaretCnt(glyphs[i]);
+ }
+ for ( i=0; i<lcnt; ++i )
+ DumpLigCarets(at->gdef,glyphs[i]);
+ offset = ftell(at->gdef);
+ fseek(at->gdef,pos,SEEK_SET);
+ putshort(at->gdef,offset-pos);
+ fseek(at->gdef,0,SEEK_END);
+ dumpcoveragetable(at->gdef,glyphs);
+ }
+
+ /* Mark Attachment Class Subtable */
+ if ( sf->mark_class_cnt>0 ) {
+ uint16 *mclasses = ClassesFromNames(sf,sf->mark_classes,sf->mark_class_cnt,at->maxp.numGlyphs,NULL,false);
+ pos = ftell(at->gdef);
+ fseek(at->gdef,10,SEEK_SET); /* location of mark attach table offset */
+ putshort(at->gdef,pos);
+ fseek(at->gdef,0,SEEK_END);
+ DumpClass(at->gdef,mclasses,at->maxp.numGlyphs);
+ free(mclasses);
+ }
+
+ at->gdeflen = ftell(at->gdef);
+ if ( at->gdeflen&1 ) putc('\0',at->gdef);
+ if ( (at->gdeflen+1)&2 ) putshort(at->gdef,0);
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/tottfvar.c b/Build/source/libs/luafontforge/fontforge/fontforge/tottfvar.c
new file mode 100644
index 00000000000..ccc614693e0
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/tottfvar.c
@@ -0,0 +1,814 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include "ttf.h"
+#include <math.h>
+#include <ustring.h>
+
+static int PtNumbersAreSet(SplineChar *sc) {
+ struct splinecharlist *dep;
+
+ if ( sc==NULL )
+return( false );
+
+ if ( sc->ttf_instrs!=NULL )
+return( true );
+ for ( dep= sc->dependents; dep!=NULL ; dep=dep->next )
+ if ( dep->sc->ttf_instrs!=NULL )
+return( true );
+
+return( false );
+}
+
+static int AssignPtNumbers(MMSet *mm,int gid) {
+ /* None of the instances has fixed point numbers. Make them match */
+ int cnt=0;
+ SplineSet **ss;
+ SplinePoint **sp;
+ int i;
+ int allavg, alllines, stillmore, ret=true;
+
+ ss = galloc((mm->instance_count+1)*sizeof(SplineSet *));
+ sp = galloc((mm->instance_count+1)*sizeof(SplinePoint *));
+ for ( i=0; i<mm->instance_count; ++i )
+ ss[i] = mm->instances[i]->glyphs[gid]->layers[ly_fore].splines;
+ ss[i] = mm->normal->glyphs[gid]->layers[ly_fore].splines;
+
+ if ( ss[0]==NULL ) {
+ stillmore = false;
+ for ( i=0; i<=mm->instance_count; ++i )
+ if ( ss[i]!=NULL ) stillmore = true;
+ if ( stillmore )
+return( false );
+return( true );
+ } else {
+ stillmore = true;
+ for ( i=0; i<=mm->instance_count; ++i )
+ if ( ss[i]==NULL ) stillmore = false;
+ if ( !stillmore )
+return( false );
+ }
+
+ forever {
+ for ( i=0; i<=mm->instance_count; ++i )
+ sp[i] = ss[i]->first;
+ forever {
+ allavg = alllines = true;
+ for ( i=0; i<=mm->instance_count; ++i ) {
+ if ( !RealNear(sp[i]->me.x,(sp[i]->nextcp.x+sp[i]->prevcp.x)/2) ||
+ !RealNear(sp[i]->me.y,(sp[i]->nextcp.y+sp[i]->prevcp.y)/2) )
+ allavg = false;
+ if ( !sp[i]->nonextcp )
+ alllines = false;
+ }
+ if ( sp[0] == ss[0]->first )
+ allavg = false;
+ for ( i=0; i<=mm->instance_count; ++i ) {
+ if ( allavg )
+ sp[i]->ttfindex = 0xffff;
+ else
+ sp[i]->ttfindex = cnt;
+ }
+ if ( !allavg )
+ ++cnt;
+ for ( i=0; i<=mm->instance_count; ++i ) {
+ if ( alllines )
+ sp[i]->nextcpindex = 0xffff;
+ else
+ sp[i]->nextcpindex = cnt;
+ }
+ if ( !alllines )
+ ++cnt;
+
+ if ( sp[0]->next==NULL ) {
+ stillmore = false;
+ for ( i=1; i<=mm->instance_count; ++i )
+ if ( sp[i]->next!=NULL )
+ stillmore = true;
+ if ( stillmore )
+ ret = false;
+ break;
+ }
+ for ( i=1; i<=mm->instance_count; ++i )
+ if ( sp[i]->next==NULL )
+ stillmore = false;
+ if ( !stillmore ) {
+ ret = false;
+ break;
+ }
+ sp[0] = sp[0]->next->to;
+ for ( i=1; i<=mm->instance_count; ++i )
+ sp[i] = sp[i]->next->to;
+ if ( sp[0]==ss[0]->first ) {
+ stillmore = false;
+ for ( i=1; i<=mm->instance_count; ++i )
+ if ( sp[i]!=ss[i]->first )
+ stillmore = true;
+ if ( stillmore )
+ ret = false;
+ break;
+ }
+ for ( i=1; i<=mm->instance_count; ++i ) {
+ if ( sp[i]==ss[i]->first )
+ stillmore = false;
+ }
+ if ( !stillmore ) {
+ ret = false;
+ break;
+ }
+ }
+ if ( !ret )
+ break;
+ stillmore = true;
+ for ( i=0; i<=mm->instance_count; ++i )
+ ss[i] = ss[i]->next;
+ if ( ss[0]==NULL ) {
+ stillmore=false;
+ for ( i=1; i<=mm->instance_count; ++i )
+ if ( ss[i]!=NULL )
+ stillmore = true;
+ if ( stillmore )
+ ret = true;
+ break;
+ }
+ for ( i=1; i<=mm->instance_count; ++i )
+ if ( ss[i]==NULL )
+ stillmore = false;
+ if ( !stillmore ) {
+ ret = true;
+ break;
+ }
+ }
+ free(ss);
+ free(sp);
+return( ret );
+}
+
+static int MatchPoints(SplineFont *sffixed, SplineFont *sfother, int gid) {
+ SplineChar *fixed, *other;
+ SplineSet *ss1, *ss2;
+ SplinePoint *sp1, *sp2;
+
+ fixed = sffixed->glyphs[gid]; other = sfother->glyphs[gid];
+
+ if ( PtNumbersAreSet(other)) {
+ /* Point numbers must match exactly, both are fixed */
+ for ( ss1=fixed->layers[ly_fore].splines,
+ ss2=other->layers[ly_fore].splines;
+ ss1!=NULL && ss2!=NULL ;
+ ss1 = ss1->next, ss2=ss2->next ) {
+ for ( sp1=ss1->first, sp2=ss2->first; ; ) {
+ if ( sp1->ttfindex!=sp2->ttfindex ||
+ sp1->nextcpindex!=sp2->nextcpindex )
+return( false );
+ if ( sp1->next==NULL || sp2->next==NULL ) {
+ if ( sp1->next!=NULL || sp2->next!=NULL )
+return( false );
+ break;
+ }
+ sp1 = sp1->next->to; sp2=sp2->next->to;
+ if ( sp1==ss1->first || sp2==ss2->first ) {
+ if ( sp1!=ss1->first || sp2!=ss2->first )
+return( false );
+ break;
+ }
+ }
+ }
+return( ss1==NULL && ss2==NULL );
+ } else {
+ for ( ss1=fixed->layers[ly_fore].splines,
+ ss2=other->layers[ly_fore].splines;
+ ss1!=NULL && ss2!=NULL ;
+ ss1 = ss1->next, ss2=ss2->next ) {
+ for ( sp1=ss1->first, sp2=ss2->first; ; ) {
+ if ( sp1->ttfindex!=0xffff )
+ sp2->ttfindex = sp1->ttfindex;
+ else if ( !RealNear(sp2->me.x,(sp2->nextcp.x+sp2->prevcp.x)/2) ||
+ !RealNear(sp2->me.y,(sp2->nextcp.y+sp2->prevcp.y)/2) )
+return( false );
+ else
+ sp2->ttfindex = 0xffff;
+ if ( sp1->nextcpindex!=0xffff )
+ sp2->nextcpindex = sp1->nextcpindex;
+ else if ( !sp2->nonextcp )
+return( false );
+ else
+ sp2->nextcpindex = 0xffff;
+ if ( sp1->next==NULL || sp2->next==NULL ) {
+ if ( sp1->next!=NULL || sp2->next!=NULL )
+return( false );
+ break;
+ }
+ sp1 = sp1->next->to; sp2=sp2->next->to;
+ if ( sp1==ss1->first || sp2==ss2->first ) {
+ if ( sp1!=ss1->first || sp2!=ss2->first )
+return( false );
+ break;
+ }
+ }
+ }
+return( ss1==NULL && ss2==NULL );
+ }
+}
+
+int ContourPtNumMatch(MMSet *mm, int gid) {
+ SplineFont *sf;
+ int i;
+
+ if ( !mm->apple )
+return( false );
+
+ if ( gid>=mm->normal->glyphcnt )
+return( false );
+ if ( !SCWorthOutputting(mm->normal->glyphs[gid] ) ) {
+ for ( i=0; i<mm->instance_count; ++i ) {
+ if ( gid>=mm->instances[i]->glyphcnt )
+return( false );
+ if ( SCWorthOutputting(mm->instances[i]->glyphs[gid]))
+return( false );
+ }
+return( true ); /* None is not worth outputting, and that's ok, they match */
+ } else {
+ for ( i=0; i<mm->instance_count; ++i ) {
+ if ( gid>=mm->instances[i]->glyphcnt )
+return( false );
+ if ( !SCWorthOutputting(mm->instances[i]->glyphs[gid]))
+return( false );
+ }
+ /* All are worth outputting */
+ }
+
+ if ( mm->normal->glyphs[gid]->layers[ly_fore].refs!=NULL && mm->normal->glyphs[gid]->layers[ly_fore].splines!=NULL )
+return( false );
+ for ( i=0; i<mm->instance_count; ++i ) {
+ if ( mm->instances[i]->glyphs[gid]->layers[ly_fore].refs!=NULL && mm->instances[i]->glyphs[gid]->layers[ly_fore].splines!=NULL )
+return( false );
+ }
+ if ( mm->normal->glyphs[gid]->layers[ly_fore].refs!=NULL ) {
+ RefChar *r;
+ int cnt, c;
+ for ( r=mm->normal->glyphs[gid]->layers[ly_fore].refs, cnt=0; r!=NULL; r=r->next )
+ ++cnt;
+ for ( i=0; i<mm->instance_count; ++i ) {
+ for ( r=mm->instances[i]->glyphs[gid]->layers[ly_fore].refs, c=0; r!=NULL; r=r->next )
+ ++c;
+ if ( c!=cnt )
+return( false );
+ }
+ }
+
+ sf = NULL;
+ if ( PtNumbersAreSet(mm->normal->glyphs[gid]) )
+ sf = mm->normal;
+ else {
+ for ( i=0; i<mm->instance_count; ++i ) {
+ if ( PtNumbersAreSet(mm->instances[i]->glyphs[gid])) {
+ sf = mm->instances[i];
+ break;
+ }
+ }
+ }
+ if ( sf==NULL )
+ /* No instance has fixed points. Make sure all fonts are consistent */
+return( AssignPtNumbers(mm,gid));
+
+ if ( sf!=mm->normal && !MatchPoints(sf,mm->normal,gid))
+return( false );
+ for ( i=0; i<mm->instance_count; ++i ) if ( sf!=mm->instances[i] ) {
+ if ( !MatchPoints(sf, mm->instances[i],gid) )
+return( false );
+ }
+return( true );
+}
+
+static int SCPointCount(SplineChar *sc) {
+ int ptcnt=0;
+ RefChar *r;
+
+ ptcnt = SSTtfNumberPoints(sc->layers[ly_fore].splines);
+ for ( r=sc->layers[ly_fore].refs; r!=NULL ; r=r->next )
+ ++ptcnt;
+return( ptcnt );
+}
+
+int16 **SCFindDeltas(MMSet *mm, int gid, int *_ptcnt) {
+ /* When figuring out the deltas the first thing we must do is figure */
+ /* out each point's number */
+ int i, j, k, l, cnt, ptcnt;
+ int16 **deltas;
+ SplineSet *ss1, *ss2;
+ SplinePoint *sp1, *sp2;
+ RefChar *r1, *r2;
+
+ if ( !ContourPtNumMatch(mm,gid))
+return( NULL );
+ if ( !SCWorthOutputting(mm->normal->glyphs[gid]))
+return( NULL );
+
+ *_ptcnt = ptcnt = SCPointCount(mm->normal->glyphs[gid])+4;
+ deltas = galloc(2*mm->instance_count*sizeof(int16 *));
+ for ( i=0; i<2*mm->instance_count; ++i )
+ deltas[i] = gcalloc(ptcnt,sizeof(int16));
+ for ( i=0; i<mm->instance_count; ++i ) {
+ for ( ss1=mm->normal->glyphs[gid]->layers[ly_fore].splines,
+ ss2=mm->instances[i]->glyphs[gid]->layers[ly_fore].splines;
+ ss1!=NULL && ss2!=NULL ;
+ ss1 = ss1->next, ss2=ss2->next ) {
+ for ( sp1=ss1->first, sp2=ss2->first; ; ) {
+ if ( sp1->ttfindex!=0xffff ) {
+ deltas[2*i][sp1->ttfindex] = rint(sp2->me.x)-rint(sp1->me.x);
+ deltas[2*i+1][sp1->ttfindex] = rint(sp2->me.y)-rint(sp1->me.y);
+ }
+ if ( sp1->nextcpindex != 0xffff ) {
+ deltas[2*i][sp1->nextcpindex] = rint(sp2->nextcp.x)-rint(sp1->nextcp.x);
+ deltas[2*i+1][sp1->nextcpindex] = rint(sp2->nextcp.y)-rint(sp1->nextcp.y);
+ }
+ if ( sp1->next==NULL )
+ break;
+ sp1 = sp1->next->to; sp2 = sp2->next->to;
+ if ( sp1==ss1->first )
+ break;
+ }
+ }
+ for ( cnt=0,
+ r1=mm->normal->glyphs[gid]->layers[ly_fore].refs,
+ r2=mm->instances[i]->glyphs[gid]->layers[ly_fore].refs;
+ r1!=NULL && r2!=NULL;
+ r1=r1->next, r2=r2->next, ++cnt ) {
+ deltas[2*i][cnt] = r2->transform[4]-r1->transform[4];
+ deltas[2*i+1][cnt] = r2->transform[5]-r1->transform[5];
+ }
+ /* Phantom points */
+ deltas[2*i][ptcnt-4] = 0; deltas[2*i+1][ptcnt-4] = 0; /* lbearing */
+ deltas[2*i][ptcnt-3] = mm->instances[i]->glyphs[gid]->width -mm->normal->glyphs[gid]->width;
+ deltas[2*i+1][ptcnt-3] = 0; /* horizontal advance */
+ deltas[2*i][ptcnt-2] = 0; deltas[2*i+1][ptcnt-2] = 0; /* top bearing */
+ deltas[2*i][ptcnt-1] = 0; /* vertical advance */
+ deltas[2*i+1][ptcnt-1] = mm->instances[i]->glyphs[gid]->vwidth -mm->normal->glyphs[gid]->vwidth; /* horizontal advance */
+ }
+
+ /* Ok, each delta now contains the difference between the instance[i] points */
+ /* and the base points. But that isn't good enough. We must subtract */
+ /* [0,1] and [1,0] from [1,1], and then subtract [1,1,0] [1,0,1] [0,1,1] */
+ /* from [1,1,1] and so on (also [-1,0] from [-1,1], etc.) */
+ for ( j=1; j<mm->axis_count; ++j ) {
+ for ( i=0; i<mm->instance_count; ++i ) {
+ for ( k=cnt=0; k<mm->axis_count; ++k )
+ if ( mm->positions[i*mm->axis_count+k]!=0 )
+ ++cnt;
+ if ( cnt==j ) {
+ for ( l = 0; l<mm->instance_count; ++l ) if ( l!=i ) {
+ for ( k=0; k<mm->axis_count; ++k )
+ if ( mm->positions[i*mm->axis_count+k]!=0 &&
+ mm->positions[l*mm->axis_count+k]!=mm->positions[i*mm->axis_count+k])
+ break;
+ if ( k==mm->axis_count ) {
+ for ( k=0; k<ptcnt; ++k ) {
+ deltas[2*l][k] -= deltas[2*i][k];
+ deltas[2*l+1][k] -= deltas[2*i+1][k];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* If all variants of the glyph are the same, no point in having a gvar */
+ /* entry for it */
+ for ( i=0 ; i<mm->instance_count; ++i ) {
+ for ( j=0; j<ptcnt; ++j )
+ if ( deltas[i][j]!=0 )
+ break;
+ if ( j!=ptcnt )
+ break;
+ }
+ if ( i==mm->instance_count ) {
+ /* All zeros */
+ for ( i=0 ; i<mm->instance_count; ++i )
+ free(deltas[i]);
+ free(deltas);
+return( NULL );
+ }
+
+return( deltas );
+}
+
+int16 **CvtFindDeltas(MMSet *mm, int *_ptcnt) {
+ int i, j, k, l, cnt, ptcnt;
+ int16 **deltas;
+ struct ttf_table *cvt, *icvt;
+ for ( cvt = mm->normal->ttf_tables; cvt!=NULL && cvt->tag!=CHR('c','v','t',' '); cvt=cvt->next );
+
+ if ( cvt==NULL )
+return( NULL );
+
+ icvt = NULL;
+ for ( i=0; i<mm->instance_count; ++i )
+ if ( (icvt=mm->instances[i]->ttf_tables)!=NULL )
+ break;
+ if ( icvt==NULL ) /* No other cvt tables => no variation */
+return( NULL );
+
+ *_ptcnt = ptcnt = cvt->len/2;
+ deltas = gcalloc(mm->instance_count,sizeof(int16 *));
+ for ( i=0; i<mm->instance_count; ++i ) if ( (icvt=mm->instances[i]->ttf_tables)!=NULL ) {
+ deltas[i] = gcalloc(ptcnt,sizeof(int16));
+ for ( j=0; j<ptcnt; ++j )
+ deltas[i][j] = memushort(icvt->data,icvt->len, sizeof(uint16)*j)-
+ memushort(cvt->data,cvt->len, sizeof(uint16)*j);
+ }
+
+ /* Ok, each delta now contains the difference between the instance[i] points */
+ /* and the base points. But that isn't good enough. We must subtract */
+ /* [0,1] and [1,0] from [1,1], and then subtract [1,1,0] [1,0,1] [0,1,1] */
+ /* from [1,1,1] and so on (also [-1,0] from [-1,1], etc.) */
+ for ( j=1; j<mm->axis_count; ++j ) {
+ for ( i=0; i<mm->instance_count; ++i ) if ( deltas[i]!=NULL ) {
+ for ( k=cnt=0; k<mm->axis_count; ++k )
+ if ( mm->positions[i*mm->axis_count+k]!=0 )
+ ++cnt;
+ if ( cnt==j ) {
+ for ( l = 0; l<mm->instance_count; ++l ) if ( l!=i && deltas[l]!=NULL ) {
+ for ( k=0; k<mm->axis_count; ++k )
+ if ( mm->positions[i*mm->axis_count+k]!=0 &&
+ mm->positions[l*mm->axis_count+k]!=mm->positions[i*mm->axis_count+k])
+ break;
+ if ( k==mm->axis_count ) {
+ for ( k=0; k<ptcnt; ++k )
+ deltas[l][k] -= deltas[i][k];
+ }
+ }
+ }
+ }
+ }
+
+ /* If all variants of the cvt are the same, no point in having a gvar */
+ /* entry for it */
+ for ( i=0 ; i<mm->instance_count; ++i ) if ( deltas[i]!=NULL ) {
+ for ( j=0; j<ptcnt; ++j )
+ if ( deltas[i][j]!=0 )
+ break;
+ if ( j==ptcnt ) {
+ free(deltas[i]);
+ deltas[i] = NULL;
+ }
+ }
+ for ( i=0 ; i<mm->instance_count; ++i )
+ if ( deltas[i]!=NULL )
+ break;
+ if ( i==mm->instance_count ) {
+ /* All zeros */
+ free(deltas);
+return( NULL );
+ }
+
+return( deltas );
+}
+
+static void ttf_dumpcvar(struct alltabs *at, MMSet *mm) {
+ int16 **deltas;
+ int ptcnt, cnt, pcnt;
+ int i,j,rj,big;
+ int tuple_size;
+ uint32 start, end;
+ uint16 *pts;
+
+ deltas = CvtFindDeltas(mm,&ptcnt);
+ for ( i=cnt=0; i<mm->instance_count; ++i )
+ if ( deltas[i]!=NULL )
+ ++cnt;
+ if ( cnt==0 ) {
+ free(deltas);
+return;
+ }
+
+ tuple_size = 4+2*mm->axis_count;
+ at->cvar = tmpfile();
+ putlong( at->cvar, 0x00010000 ); /* Format */
+ putshort( at->cvar, cnt ); /* Number of instances with cvt tables (tuple count of interesting tuples) */
+ putshort( at->cvar, 8+cnt*tuple_size ); /* Offset to data */
+
+ for ( i=0; i<mm->instance_count; ++i ) if ( deltas[i]!=NULL ) {
+ putshort( at->cvar, 0 ); /* tuple data size, figure out later */
+ putshort( at->cvar, 0xa000 ); /* tuple coords follow, private points in data */
+ for ( j=0; j<mm->axis_count; ++j )
+ putshort( at->cvar, rint(16384*mm->positions[i*mm->axis_count+j]) );
+ }
+ if ( ftell( at->cvar )!=8+cnt*tuple_size )
+ IError( "Data offset wrong" );
+
+ for ( i=cnt=0; i<mm->instance_count; ++i ) if ( deltas[i]!=NULL ) {
+ start = ftell(at->cvar);
+ for ( j=pcnt=0; j<ptcnt; ++j )
+ if ( deltas[i][j]!=0 )
+ ++pcnt;
+ pts = galloc(pcnt*sizeof(uint16));
+ for ( j=pcnt=0; j<ptcnt; ++j )
+ if ( deltas[i][j]!=0 )
+ pts[pcnt++]=j;
+
+ if ( pcnt>0x7f ) {
+ putc(0x80|(pcnt>>8), at->cvar );
+ putc(pcnt&0xff, at->cvar);
+ } else
+ putc(pcnt, at->cvar);
+ for ( j=0; j<pcnt; ) {
+ big = pts[j]>=0x80 ? 0x80 : 0;
+ for ( rj=j+1 ; rj<j+0x80 && rj<pcnt && !big; ++rj )
+ if ( pts[rj]-pts[rj-1]>=0x80 )
+ big = 0x80;
+
+ putc((rj-j-1)|big,at->cvar);
+ if ( big ) {
+ putshort(at->cvar,pts[j]);
+ for ( ++j; j<rj; ++j )
+ putshort(at->cvar,pts[j]-pts[j-1]);
+ } else {
+ putc(pts[j],at->cvar);
+ for ( ++j; j<rj; ++j )
+ putc(pts[j]-pts[j-1],at->cvar);
+ }
+ }
+ /* Now output the corresponding deltas for those points */
+ for ( j=0; j<pcnt; ) {
+ if ( deltas[i][j]>0x7f || deltas[i][j]<0x80 ) {
+ for ( rj=j+1; rj<j+0x40 && rj<pcnt; ++rj ) {
+ if ( deltas[i][pts[rj]]>0x7f || deltas[i][pts[rj]]<0x80 ||
+ (rj+1<j+0x40 && rj+1<pcnt && (deltas[i][pts[rj+1]]>0x7f || deltas[i][pts[rj+1]]<0x80)) )
+ /* Keep going with a big run */;
+ else
+ break;
+ }
+ putc( (rj-j-1)|0x40,at->cvar );
+ for ( ; j<rj ; ++j )
+ putshort( at->cvar, deltas[i][pts[j]] );
+ } else {
+ for ( rj=j+1; rj<j+0x40 && rj<pcnt; ++rj ) {
+ if ( deltas[i][pts[rj]]>0x7f || deltas[i][pts[rj]]<0x80 )
+ break;
+ }
+ putc( rj-j-1,at->cvar );
+ for ( ; j<rj ; ++j )
+ putc( deltas[i][pts[j]], at->cvar );
+ }
+ }
+ free(pts);
+ end = ftell(at->cvar);
+ fseek(at->cvar, 8+cnt*tuple_size, SEEK_SET);
+ putshort(at->cvar,end-start);
+ fseek(at->cvar, end, SEEK_SET);
+ ++cnt;
+ }
+
+ for ( i=0; i<mm->instance_count; ++i )
+ free( deltas[i] );
+ free(deltas);
+
+ at->cvarlen = ftell(at->cvar);
+ if ( at->cvarlen&1 )
+ putc('\0',at->cvar );
+ if ( ftell(at->cvar)&2 )
+ putshort(at->cvar,0);
+}
+
+static void dumpdeltas(struct alltabs *at,int16 *deltas,int ptcnt) {
+ int j,rj;
+
+ for ( j=0; j<ptcnt; ) {
+ for ( rj=j; rj<ptcnt && rj<j+0x40 && deltas[rj]==0; ++rj );
+ if ( rj!=j ) {
+ putc((rj-j-1)|0x80,at->gvar);
+ j = rj;
+ continue;
+ }
+ if ( deltas[j]>0x7f || deltas[j]<0x80 ) {
+ for ( rj=j+1; rj<j+0x40 && rj<ptcnt; ++rj ) {
+ if ( deltas[rj]>0x7f || deltas[rj]<0x80 ||
+ (rj+1<j+0x40 && rj+1<ptcnt && (deltas[rj+1]>0x7f || deltas[rj+1]<0x80)) )
+ /* Keep going with a big run */;
+ else
+ break;
+ }
+ putc( (rj-j-1)|0x40,at->gvar );
+ for ( ; j<rj ; ++j )
+ putshort( at->gvar, deltas[j] );
+ } else {
+ for ( rj=j+1; rj<j+0x40 && rj<ptcnt; ++rj ) {
+ if ( deltas[rj]>0x7f || deltas[rj]<0x80 ||
+ (deltas[rj]==0 && rj+1<j+0x40 && rj+1<ptcnt &&
+ deltas[rj+1]<=0x7f && deltas[rj+1]>=0x80 && deltas[rj+1]!=0 ))
+ break;
+ }
+ putc( rj-j-1,at->gvar );
+ for ( ; j<rj ; ++j )
+ putc( deltas[j], at->gvar );
+ }
+ }
+}
+
+static void ttf_dumpgvar(struct alltabs *at, MMSet *mm) {
+ int i,j, last;
+ uint32 gcoordoff, glyphoffs, start, here, tupledataend, tupledatastart;
+ int16 **deltas;
+ int ptcnt;
+
+ at->gvar = tmpfile();
+ putlong( at->gvar, 0x00010000 ); /* Format */
+ putshort( at->gvar, mm->axis_count );
+ putshort( at->gvar, mm->instance_count ); /* Number of global tuples */
+ gcoordoff = ftell(at->gvar);
+ putlong( at->gvar, 0 ); /* Offset to global tuples, fix later */
+ putshort( at->gvar,at->maxp.numGlyphs );
+ putshort( at->gvar, 1 ); /* always output 32bit offsets */
+ putlong( at->gvar, ftell(at->gvar)+4 + (at->maxp.numGlyphs+1)*4);
+ glyphoffs = ftell(at->gvar);
+ for ( i=0; i<=at->maxp.numGlyphs; ++i )
+ putlong( at->gvar,0 );
+
+ start = ftell( at->gvar );
+ last = -1;
+ for ( i=0; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
+ deltas = SCFindDeltas(mm,at->gi.bygid[i],&ptcnt);
+ if ( deltas==NULL )
+ continue;
+ here = ftell(at->gvar);
+ fseek(at->gvar,glyphoffs+(last+1)*4,SEEK_SET);
+ for ( ; last< i; ++last )
+ putlong(at->gvar,here-start);
+ fseek(at->gvar,here,SEEK_SET);
+ putshort(at->gvar,mm->instance_count);
+ putshort(at->gvar,4+4*mm->instance_count); /* offset to data */
+ for ( j=0; j<mm->instance_count; ++j ) {
+ putshort(at->gvar,0); /* tuple data size, fix later */
+ putshort(at->gvar,0x2000|j); /* private points, tuple i */
+ }
+ for ( j=0; j<mm->instance_count; ++j ) {
+ tupledatastart = ftell(at->gvar);
+ putc('\0',at->gvar); /* Point list, all points */
+ dumpdeltas(at,deltas[2*j],ptcnt);
+ dumpdeltas(at,deltas[2*j+1],ptcnt);
+ tupledataend = ftell(at->gvar);
+ fseek(at->gvar,here+4+4*j,SEEK_SET);
+ putshort( at->gvar,tupledataend-tupledatastart);
+ fseek(at->gvar,tupledataend,SEEK_SET);
+ free(deltas[2*j]); free(deltas[2*j+1]);
+ }
+ free(deltas);
+ }
+ here = ftell(at->gvar);
+ fseek(at->gvar,glyphoffs+(last+1)*4,SEEK_SET);
+ for ( ; last< at->maxp.numGlyphs; ++last )
+ putlong(at->gvar,here-start);
+ fseek(at->gvar,gcoordoff,SEEK_SET);
+ putlong(at->gvar,here);
+ fseek(at->gvar,here,SEEK_SET);
+ for ( j=0; j<mm->instance_count; ++j ) {
+ for ( i=0; i<mm->axis_count; ++i )
+ putshort(at->gvar,rint(16384*mm->positions[j*mm->axis_count+i]));
+ }
+
+ at->gvarlen = ftell(at->gvar);
+ if ( at->gvarlen&1 )
+ putc('\0',at->gvar );
+ if ( ftell(at->gvar)&2 )
+ putshort(at->gvar,0);
+}
+
+
+static void ttf_dumpavar(struct alltabs *at, MMSet *mm) {
+ int i,j;
+
+ for ( i=0; i<mm->axis_count; ++i ) {
+ if ( mm->axismaps[i].points>3 )
+ break;
+ }
+ if ( i==mm->axis_count ) /* We only have simple axes */
+return; /* No need for a variation table */
+
+ at->avar = tmpfile();
+ putlong( at->avar, 0x00010000 ); /* Format */
+ putlong( at->avar, mm->axis_count );
+ for ( i=0; i<mm->axis_count; ++i ) {
+ putshort( at->avar, mm->axismaps[i].points );
+ for ( j=0; j<mm->axismaps[i].points; ++j ) {
+ if ( mm->axismaps[i].designs[j]<mm->axismaps[i].def )
+ putshort( at->avar, (mm->axismaps[i].designs[j]-mm->axismaps[i].def)*16384/
+ (mm->axismaps[i].def-mm->axismaps[i].min));
+ else
+ putshort( at->avar, (mm->axismaps[i].designs[j]-mm->axismaps[i].def)*16384/
+ (mm->axismaps[i].max-mm->axismaps[i].def));
+ putshort( at->avar, mm->axismaps[i].blends[j]*16384);
+ }
+ }
+
+ at->avarlen = ftell(at->avar);
+ if ( at->avarlen&2 )
+ putshort(at->avar,0);
+}
+
+static uint32 AxisNameToTag(char *name) {
+ char buf[4];
+ int i;
+
+ if ( strmatch(name,"Weight")==0 )
+return( CHR('w','g','h','t'));
+ if ( strmatch(name,"Width")==0 )
+return( CHR('w','d','t','h'));
+ if ( strmatch(name,"OpticalSize")==0 )
+return( CHR('o','p','s','z'));
+ if ( strmatch(name,"Slant")==0 )
+return( CHR('s','l','n','t'));
+
+ memset(buf,0,sizeof(buf));
+ for ( i=0; i<4 && name[i]!='\0'; ++i )
+ buf[i] = name[i];
+return( CHR(buf[0],buf[1],buf[2],buf[3]));
+}
+
+static int AllocateStrId(struct alltabs *at,struct macname *mn) {
+ struct other_names *on;
+
+ if ( mn==NULL )
+return( 0 );
+
+ on = chunkalloc(sizeof(struct other_names));
+ on->strid = at->next_strid++;
+ on->mn = mn;
+ on->next = at->other_names;
+ at->other_names = on;
+return( on->strid );
+}
+
+static void ttf_dumpfvar(struct alltabs *at, MMSet *mm) {
+ int i,j;
+
+ at->fvar = tmpfile();
+ putlong( at->fvar, 0x00010000 ); /* Format */
+ putshort( at->fvar, 16 ); /* Offset to first axis data */
+ putshort( at->fvar, 2 ); /* Size count pairs */
+ putshort( at->fvar, mm->axis_count );
+ putshort( at->fvar, 20 ); /* Size of each axis record */
+ putshort( at->fvar, mm->named_instance_count );
+ putshort( at->fvar, 4+4*mm->axis_count );
+
+ /* For each axis ... */
+ for ( i=0; i<mm->axis_count; ++i ) {
+ putlong( at->fvar, AxisNameToTag(mm->axes[i]) );
+ putlong( at->fvar, rint(mm->axismaps[i].min*65536));
+ putlong( at->fvar, rint(mm->axismaps[i].def*65536));
+ putlong( at->fvar, rint(mm->axismaps[i].max*65536));
+ putshort(at->fvar, 0 ); /* No flags defined for axes */
+ putshort(at->fvar, AllocateStrId(at,mm->axismaps[i].axisnames));
+ }
+
+ /* For each named font ... */
+ for ( i=0; i<mm->named_instance_count; ++i ) {
+ putshort(at->fvar, AllocateStrId(at,mm->named_instances[i].names));
+ putshort(at->fvar, 0 ); /* No flags here either */
+ for ( j=0; j<mm->axis_count; ++j )
+ putlong(at->fvar, rint(65536*mm->named_instances[i].coords[j]));
+ }
+
+ at->fvarlen = ftell(at->fvar);
+ if ( at->fvarlen&2 ) /* I don't think this is ever hit */
+ putshort(at->fvar,0);
+}
+
+void ttf_dumpvariations(struct alltabs *at, SplineFont *sf) {
+ MMSet *mm = sf->mm;
+ int i,j;
+
+ for ( j=0; j<sf->glyphcnt; ++j ) if ( sf->glyphs[j]!=NULL ) {
+ for ( i=0; i<mm->instance_count; ++i ) if ( mm->instances[i]->glyphs[j]!=NULL )
+ mm->instances[i]->glyphs[j]->ttf_glyph = sf->glyphs[j]->ttf_glyph;
+ }
+
+ ttf_dumpfvar(at,mm);
+ ttf_dumpgvar(at,mm);
+ ttf_dumpcvar(at,mm);
+ ttf_dumpavar(at,mm);
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/ttf.h b/Build/source/libs/luafontforge/fontforge/fontforge/ttf.h
new file mode 100644
index 00000000000..a88bf3ecf21
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/ttf.h
@@ -0,0 +1,831 @@
+/* Copyright (C) 2001-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "psfont.h" /* for struct fddata */
+
+#define MAC_DELETED_GLYPH_NAME "<Delete>"
+
+/* Some glyphs have multiple encodings ("A" might be used for Alpha and Cyrillic A) */
+struct dup {
+ SplineChar *sc;
+ int enc;
+ int uni;
+ struct dup *prev;
+};
+
+struct variations {
+ int axis_count;
+ struct taxis {
+ uint32 tag;
+ real min, def, max; /* in user design space */
+ int nameid;
+ int paircount;
+ real *mapfrom; /* after conversion from [-1,1] */
+ real *mapto; /* secondary conversiont to [-1,1] */
+ } *axes; /* Array of axis_count entries */
+ int instance_count; /* Not master designs, but named interpolations in design space */
+ struct tinstance {
+ int nameid;
+ real *coords; /* Location along axes array[axis_count] */
+ } *instances;
+ int tuple_count;
+ struct tuples {
+ real *coords; /* Location along axes array[axis_count] */
+ SplineChar **chars; /* Varied glyphs, array parallels one in info */
+ struct ttf_table *cvt;
+ KernClass *khead, *klast, *vkhead, *vklast;
+ /* Varied kern classes */
+ } *tuples;
+};
+
+struct ttfinfo {
+ int emsize; /* ascent + descent? from the head table */
+ int ascent, descent; /* from the hhea table */
+ /* not the usWinAscent from the OS/2 table */
+ int vertical_origin; /* if vmetrics are present */
+ int width_cnt; /* from the hhea table, in the hmtx table */
+ int glyph_cnt; /* from maxp table (or cff table) */
+ unsigned int index_to_loc_is_long:1; /* in head table */
+ unsigned int is_ttc:1; /* Is it a font collection? */
+ unsigned int is_onebyte:1; /* Is it a one byte encoding? */
+ unsigned int twobytesymbol:1; /* it had a symbol encoding which we converted to unicode */
+ unsigned int complainedbeyondglyfend:1; /* Don't complain about this more than once */
+ unsigned int extensionrequested:1; /* Only ask once for a copy of a font containing extension subtables */
+ unsigned int to_order2:1; /* We are to leave the font as truetype (order2) splines, else convert to ps */
+ unsigned int complainedmultname:1; /* Don't complain about this more than once */
+ unsigned int strokedfont: 1; /* painttype==2 for otf */
+ unsigned int use_typo_metrics: 1;
+ unsigned int weight_width_slope_only: 1;
+ unsigned int optimized_for_cleartype: 1;
+ enum openflags openflags;
+ /* Mac fonts platform=0/1, platform specific enc id, roman=0, english is lang code 0 */
+ /* iso platform=2, platform specific enc id, latin1=0/2, no language */
+ /* microsoft platform=3, platform specific enc id, 1, english is lang code 0x??09 */
+ char *copyright; /* from the name table, nameid=0 */
+ char *familyname; /* nameid=1 */
+ char *fullname; /* nameid=4 */
+ char *weight;
+ char *version; /* nameid=5 */
+ char *fontname; /* postscript font name, nameid=6 */
+ char *xuid; /* Only for open type cff fonts */
+ int uniqueid;
+ real italicAngle; /* from post table */
+ int upos, uwidth; /* underline pos, width from post table */
+ real strokewidth;
+ int fstype;
+ struct psdict *private; /* Only for open type cff fonts */
+ EncMap *map;
+ enum uni_interp uni_interp;
+ struct pfminfo pfminfo;
+ short os2_version;
+ short gasp_version;
+ int dupnamestate;
+ struct ttflangname *names;
+ char *fontcomments;
+ SplineChar **chars; /* from all over, glyf table for contours */
+ /* cmap table for encodings */
+ /* hmtx table for widths */
+ /* post table for names */
+ /* Or from CFF table for everything in opentype */
+ BDFFont *bitmaps;
+ char *cidregistry, *ordering;
+ int supplement;
+ real cidfontversion;
+ int subfontcnt;
+ SplineFont **subfonts;
+ char *inuse; /* What glyphs are used by this font in the ttc */
+
+ int numtables;
+ /* CFF */
+ uint32 cff_start; /* Offset from sof to start of postscript compact font format */
+ uint32 cff_length;
+ /* cmap */
+ uint32 encoding_start; /* Offset from sof to start of encoding table */
+ /* gasp */
+ uint32 gasp_start;
+ /* glyf */
+ uint32 glyph_start; /* Offset from sof to start of glyph table */
+ uint32 glyph_length;
+ /* GDEF */
+ uint32 gdef_start; /* Offset from sof to start of GDEF table (glyph class defn, ligature carets) */
+ uint32 gdef_length;
+ /* GPOS */
+ uint32 gpos_start; /* Offset from sof to start of GPOS table */
+ uint32 gpos_length;
+ /* GSUB */
+ uint32 gsub_start; /* Offset from sof to start of GSUB table */
+ uint32 gsub_length;
+ uint32 g_bounds; /* Filled in with g???_start+g???_length */
+ /* EBDT, bdat */
+ uint32 bitmapdata_start; /* Offset to start of bitmap data */
+ uint32 bitmapdata_length;
+ /* EBLT, bloc */
+ uint32 bitmaploc_start; /* Offset to start of bitmap locator data */
+ uint32 bitmaploc_length;
+ /* gvar, etc. */
+ uint32 gvar_start, gvar_len;
+ uint32 fvar_start, fvar_len;
+ uint32 avar_start, avar_len;
+ uint32 cvar_start, cvar_len;
+ /* head */
+ uint32 head_start;
+ /* hhea */
+ uint32 hhea_start;
+ /* hmtx */
+ uint32 hmetrics_start;
+ /* kern */
+ uint32 kern_start;
+ /* loca */
+ uint32 glyphlocations_start;/* there are glyph_cnt of these, from maxp tab */
+ uint32 loca_length; /* actually glypn_cnt is wrong. Use the table length (divided by size) instead */
+ /* maxp */
+ uint32 maxp_start; /* maximum number of glyphs */
+ uint32 maxp_len;
+ /* name */
+ uint32 copyright_start; /* copyright and fontname */
+ /* post */
+ uint32 postscript_start; /* names for the glyphs, italic angle, etc. */
+ /* OS/2 */
+ uint32 os2_start;
+ /* TYP1 */
+ uint32 typ1_start; /* For Adobe's? Apple's? attempt to stuff a type1 font into an sfnt wrapper */
+ uint32 typ1_length;
+ /* vhea */
+ uint32 vhea_start;
+ /* vmtx */
+ uint32 vmetrics_start;
+ /* VORG */
+ uint32 vorg_start;
+
+ /* PfEd -- FontForge/PfaEdit specific info */
+ uint32 pfed_start;
+ /* TeX -- TeX table, also non-standard */
+ uint32 tex_start;
+ /* BDF -- BDF properties, also non-standard */
+ uint32 bdf_start;
+ /* FFTM -- FontForge timestamps */
+ uint32 fftm_start;
+
+ /* Apple Advanced Typography Tables */
+ uint32 prop_start;
+ uint32 lcar_start;
+ uint32 opbd_start;
+ uint32 acnt_start;
+ uint32 feat_start;
+ uint32 mort_start;
+ uint32 morx_start;
+
+ /* Info for instructions */
+ uint32 cvt_start, cvt_len;
+ uint32 prep_start, prep_len;
+ uint32 fpgm_start, fpgm_len;
+
+ unsigned int one_of_many: 1; /* A TTCF file, or a opentype font with multiple fonts */
+ unsigned int obscomplain: 1; /* We've complained about obsolete format 3 in EBDT table */
+ unsigned int cmpcomplain: 1; /* We've complained about compressed format 4 in EBDT */
+ unsigned int unkcomplain: 1; /* We've complained about unknown formats in EBDT */
+ unsigned int comcomplain: 1; /* We've complained about composit formats in EBDT */
+ unsigned int onlystrikes: 1; /* Only read in the bitmaps, not the outlines */
+ unsigned int onlyonestrike: 1; /* Only read in one bitmap (strike) */
+ unsigned int barecff: 1; /* pay attention to the encoding in the cff file, we won't have a cmap */
+
+ int platform, specific; /* values of the encoding we chose to use */
+
+ int anchor_class_cnt; /* For GPOS */
+ int anchor_merge_cnt;
+ AnchorClass *ahead, *alast;
+
+ KernClass *khead, *klast, *vkhead, *vklast;
+
+ OTLookup *gpos_lookups, *gsub_lookups, *cur_lookups;
+
+ OTLookup *mort_subs_lookup, *mort_pos_lookup2;
+ int mort_r2l, mort_tag_mac, mort_feat, mort_setting, mort_is_nested;
+ uint16 *morx_classes;
+
+ int mort_max;
+
+ struct ttf_table *tabs;
+ FPST *possub;
+ ASM *sm;
+ MacFeat *features;
+ char *chosenname;
+ int macstyle;
+ int lookup_cnt; /* Max lookup in current GPOS/GSUB table */
+ int feature_cnt; /* Max feature in current GPOS/GSUB table */
+ struct variations *variations;
+ struct macidname {
+ int id;
+ struct macname *head, *last;
+ struct macidname *next;
+ } *macstrids;
+ struct fontdict *fd; /* For reading in Type42 fonts. Glyph names in postscript section must be associated with glyphs in TTF section */
+ int savecnt;
+ struct savetab {
+ uint32 tag;
+ uint32 offset;
+ int len;
+ } *savetab;
+ int32 last_size_pos;
+ uint16 design_size;
+ uint16 fontstyle_id;
+ struct otfname *fontstyle_name;
+ uint16 design_range_bottom, design_range_top;
+ struct texdata texdata;
+ int mark_class_cnt;
+ char **mark_classes; /* glyph name list */
+ char **mark_class_names; /* used within ff (utf8) */
+ uint8 warned_morx_out_of_bounds_glyph;
+ int badgid_cnt, badgid_max; /* Used when parsing apple morx tables*/
+ SplineChar **badgids; /* which use out of range glyph IDs as temporary flags */
+#ifdef _HAS_LONGLONG
+ long long creationtime; /* seconds since 1970 */
+ long long modificationtime;
+#else
+ long creationtime;
+ long modificationtime;
+#endif
+ int gasp_cnt;
+ struct gasp *gasp;
+};
+
+#define MAX_TAB 48
+struct tabdir {
+ int32 version; /* 0x00010000 */
+ uint16 numtab;
+ uint16 searchRange; /* (Max power of 2 <= numtab) *16 */
+ uint16 entrySel; /* Log2(Max power of 2 <= numtab ) */
+ uint16 rangeShift; /* numtab*16 - searchRange */
+ struct taboff {
+ uint32 tag; /* Table name */
+ uint32 checksum;/* for table */
+ uint32 offset; /* to start of table in file */
+ uint32 length;
+ FILE *data;
+ uint16 dup_of;
+ uint16 orderingval;
+ } tabs[MAX_TAB]; /* room for all the above tables */
+ struct taboff *ordered[MAX_TAB];
+};
+
+struct glyphhead {
+ int16 numContours;
+ int16 xmin;
+ int16 ymin;
+ int16 xmax;
+ int16 ymax;
+};
+
+struct head {
+ int32 version; /* 0x00010000 */
+ int32 revision; /* 0 */
+ uint32 checksumAdj; /* set to 0, sum entire font, store 0xb1b0afba-sum */
+ uint32 magicNum; /* 0x5f0f3cf5 */
+ uint16 flags; /* 1 */
+ uint16 emunits; /* sf->ascent+sf->descent */
+ int32 createtime[2];/* number of seconds since 1904 */
+ int32 modtime[2];
+ int16 xmin; /* min for entire font */
+ int16 ymin;
+ int16 xmax;
+ int16 ymax;
+ uint16 macstyle; /* 1=>Bold, 2=>Italic */
+ uint16 lowestreadable; /* size in pixels. Say about 10? */
+ int16 dirhint; /* 0=>mixed directional characters, */
+ int16 locais32; /* is the location table 32bits or 16, 0=>16, 1=>32 */
+ int16 glyphformat; /* 0 */
+ uint16 mbz; /* padding */
+};
+
+struct hhead {
+ int32 version; /* 0x00010000 */
+ int16 ascender; /* sf->ascender */
+ int16 descender; /* -sf->descender */
+ int16 linegap; /* 0 */
+ int16 maxwidth; /* of all characters */
+ int16 minlsb; /* How is this different from xmin above? */
+ int16 minrsb;
+ int16 maxextent; /* How is this different from xmax above? */
+ int16 caretSlopeRise;/* Uh... let's say 1? */
+ int16 caretSlopeRun;/* Uh... let's say 0 */
+ /* not exactly specified, but FontValidator wants this to match italicangle */
+ int16 mbz[5];
+ int16 metricformat; /* 0 */
+ uint16 numMetrics; /* just set to glyph count */
+};
+
+struct hmtx {
+ uint16 width; /* NOTE: TTF only allows positive widths!!! */
+ int16 lsb;
+};
+
+struct kern {
+ uint16 version; /* 0 */
+ uint16 ntab; /* 1, number of subtables */
+ /* first (and only) subtable */
+ uint16 stversion; /* 0 */
+ uint16 length; /* length of subtable beginning at &stversion */
+ uint16 coverage; /* 1, (set of flags&format) */
+ uint16 nPairs; /* number of kern pairs */
+ uint16 searchRange; /* (Max power of 2 <= nPairs) *6 */
+ uint16 entrySel; /* Log2(Max power of 2 <= nPairs ) */
+ uint16 rangeShift; /* numtab*6 - searchRange */
+ struct kp {
+ uint16 left; /* left glyph num */
+ uint16 right; /* right glyph num */
+ /* table is ordered by these two above treated as uint32 */
+ int16 offset; /* kern amount */
+ } *kerns; /* Array should be nPairs big */
+};
+
+struct maxp {
+ int32 version; /* 0x00010000 */
+ uint16 numGlyphs;
+ uint16 maxPoints; /* max number of points in a simple glyph */
+ uint16 maxContours; /* max number of paths in a simple glyph */
+ uint16 maxCompositPts;
+ uint16 maxCompositCtrs;
+ uint16 maxZones; /* 1 */
+ uint16 maxTwilightPts; /* 0 */
+ uint16 maxStorage; /* 0 */
+ uint16 maxFDEFs; /* 0 */
+ uint16 maxIDEFs; /* 0 */
+ uint16 maxStack; /* 0 */
+ uint16 maxglyphInstr;/* 0 */
+ uint16 maxnumcomponents; /* Maximum number of refs in any composit */
+ uint16 maxcomponentdepth;
+ /* Apple docs say: 0 (if no composits), maximum value 1 (one level of composit) */
+ /* OpenType docs say: 1 (if no composits), any depth allowed */
+ uint16 mbz; /* pad out to a 4byte boundary */
+};
+
+struct nametab {
+ uint16 format; /* 0 */
+ uint16 numrec; /* 1 */
+ uint16 startOfStrings; /* offset from start of table to start of strings */
+ struct namerec {
+ uint16 platform; /* 3 => MS */
+ uint16 specific; /* 1 */
+ uint16 language; /* 0x0409 */
+ uint16 nameid; /* 0=>copyright, 1=>family, 2=>weight, 4=>fullname */
+ /* 5=>version, 6=>postscript name */
+ uint16 strlen;
+ uint16 stroff;
+ } nr[6];
+};
+
+struct os2 {
+ uint16 version; /* 1 */
+ int16 avgCharWid; /* average all chars (v3) see v2 definition below */
+ uint16 weightClass; /* 100=>thin, 200=>extra-light, 300=>light, 400=>normal, */
+ /* 500=>Medium, 600=>semi-bold, 700=>bold, 800=>extra-bold, */
+ /* 900=>black */
+ uint16 widthClass; /* 75=>condensed, 100, 125=>expanded */
+ int16 fstype; /* 0x0008 => allow embedded editing */
+ int16 ysubXSize; /* emsize/5 */
+ int16 ysubYSize; /* emsize/5 */
+ int16 ysubXOff; /* 0 */
+ int16 ysubYOff; /* emsize/5 */
+ int16 ysupXSize; /* emsize/5 */
+ int16 ysupYSize; /* emsize/5 */
+ int16 ysupXOff; /* 0 */
+ int16 ysupYOff; /* emsize/5 */
+ int16 yStrikeoutSize; /* 102/2048 *emsize */
+ int16 yStrikeoutPos; /* 530/2048 *emsize */
+ int16 sFamilyClass; /* ??? 0 */
+ /* high order byte is the "class", low order byte the sub class */
+ /* class = 0 => no classification */
+ /* class = 1 => old style serifs */
+ /* subclass 0, no class; 1 ibm rounded; 2 garalde; 3 venetian; 4 mod venitian; 5 dutch modern; 6 dutch trad; 7 contemporary; 8 caligraphic; 15 misc */
+ /* class = 2 => transitional serifs */
+ /* subclass 0, no class; 1 drect line; 2 script; 15 misc */
+ /* class = 3 => modern serifs */
+ /* subclass: 1, italian; 2, script */
+ /* class = 4 => clarendon serifs */
+ /* subclass: 1, clarendon; 2, modern; 3 trad; 4 newspaper; 5 stub; 6 monotone; 7 typewriter */
+ /* class = 5 => slab serifs */
+ /* subclass: 1, monotone; 2, humanist; 3 geometric; 4 swiss; 5 typewriter */
+ /* class = 7 => freeform serifs */
+ /* subclass: 1, modern */
+ /* class = 8 => sans serif */
+ /* subclass: 1, ibm neogrotesque; 2 humanist; 3 low-x rounded; 4 high-x rounded; 5 neo-grotesque; 6 mod neo-grot; 9 typewriter; 10 matrix */
+ /* class = 9 => ornamentals */
+ /* subclass: 1, engraver; 2 black letter; 3 decorative; 4 3D */
+ /* class = 10 => scripts */
+ /* subclass: 1, uncial; 2 brush joined; 3 formal joined; 4 monotone joined; 5 calligraphic; 6 brush unjoined; 7 formal unjoined; 8 monotone unjoined */
+ /* class = 12 => symbolic */
+ /* subclass: 3 mixed serif; 6 old style serif; 7 neo-grotesque sans; */
+ char panose[10]; /* can be set to zero */
+ uint32 unicoderange[4];
+ /* 1<<0=>ascii, 1<<1 => latin1, 2=>100-17f, 3=>180-24f, 4=>250-2af */
+ /* 5=> 2b0-2ff, 6=>300-36f, ... */
+ char achVendID[4]; /* can be zero */
+ uint16 fsSel; /* 1=> italic, 32=>bold, 64 => regular */
+ /* 2=>underscore, 4=>negative, 8->outlined, 16=>strikeout */
+ /* version 4 of OS/2 */
+ /* 128->don't use win_ascent/descent for line spacing */
+ /* 256=>family varies on weight width slope only */
+ /* 512=>oblique (as opposed to italic) */
+ uint16 firstcharindex; /* minimum unicode encoding */
+ uint16 lastcharindex; /* maximum unicode encoding */
+ uint16 ascender; /* font ascender height (not ascent) */
+ uint16 descender; /* font descender height */
+ uint16 linegap; /* 0 */
+ uint16 winascent; /* ymax */
+ uint16 windescent; /* ymin */
+ uint32 ulCodePage[2];
+ /* 1<<0 => latin1, 1<<1=>latin2, cyrillic, greek, turkish, hebrew, arabic */
+ /* 1<<30 => mac, 1<<31 => symbol */
+ /* OTF stuff (version 2 of OS/2) */
+ short xHeight;
+ short capHeight;
+ short defChar;
+ short breakChar;
+ short maxContext;
+ /* V3 of OS/2 has no additional data */
+ /* V4 of OS/2 has no additional data */
+
+ int v1_avgCharWid; /* 1&2 Weighted average of the lower case letters and space */
+ int v3_avgCharWid; /* 3&4 average over all non-zero width glyphs */
+};
+
+struct post {
+ int32 formattype; /* 0x00020000 */
+ int32 italicAngle; /* in fixed format */
+ int16 upos;
+ int16 uwidth;
+ uint32 isfixed;
+ uint32 minmem42;
+ uint32 maxmem42;
+ uint32 minmem1;
+ uint32 maxmem1;
+ uint16 numglyphs;
+ uint16 glyphnameindex[1];
+};
+
+struct glyphinfo {
+ struct maxp *maxp; /* this one is given to dumpglyphs, rest blank */
+ uint32 *loca;
+ FILE *glyphs;
+ FILE *hmtx;
+ int hmtxlen;
+ FILE *vmtx;
+ int vmtxlen;
+ int next_glyph;
+ int glyph_len;
+ int xmin, ymin, xmax, ymax;
+ BlueData bd;
+ int strikecnt; /* number of bitmaps to dump */
+ int lasthwidth, lastvwidth; /* encoding of last glyph for which we generate a full metrics entry */
+ int hfullcnt, vfullcnt;
+ int flags;
+ int fixed_width;
+ int32 *bsizes;
+ unsigned int dovariations: 1;
+ unsigned int onlybitmaps: 1;
+ unsigned int has_instrs: 1;
+ unsigned int is_ttf: 1;
+ SplineFont *sf;
+ int32 *pointcounts;
+ int *bygid; /* glyph list */
+ int gcnt;
+};
+
+struct vorg {
+ uint16 majorVersion; /* 1 */
+ uint16 minorVersion; /* 0 */
+ short defaultVertOriginY; /* Y coord of default vertical origin in the design coordinate system */
+ uint16 numVertOriginYMetrics; /* exceptions to the above, elements in following array */
+#if 0
+ struct {
+ uint16 glyphindex; /* ordered */
+ short vertOrigin;
+ } origins[];
+#endif
+};
+
+struct alltabs {
+ struct tabdir tabdir;
+ struct head head;
+ struct hhead hhead;
+ struct hhead vhead;
+ struct maxp maxp;
+ struct os2 os2;
+ struct vorg vorg;
+ FILE *loca;
+ int localen;
+ FILE *name;
+ int namelen;
+ FILE *post;
+ int postlen;
+ FILE *gpos; /* Used instead of kern for opentype (and other glyph positioning) */
+ int gposlen;
+ FILE *gsub; /* Used for ligatures and other substitutions */
+ int gsublen;
+ FILE *gdef; /* If we use mark to base we need this to tell the text processor what things are marks (the opentype docs say it is optional. They are wrong) */
+ int gdeflen;
+ FILE *kern;
+ int kernlen;
+ FILE *cmap;
+ int cmaplen;
+ FILE *headf;
+ int headlen;
+ FILE *hheadf;
+ int hheadlen;
+ FILE *maxpf;
+ int maxplen;
+ FILE *os2f;
+ int os2len;
+ FILE *cvtf;
+ int cvtlen;
+ FILE *fpgmf; /* Copied from an original ttf file and dumped out. Never generated */
+ int fpgmlen;
+ FILE *prepf; /* Copied from an original ttf file and dumped out. Never generated */
+ int preplen;
+ FILE *vheadf;
+ int vheadlen;
+ FILE *vorgf;
+ int vorglen;
+ FILE *gaspf;
+ int gasplen;
+ FILE *cfff;
+ int cfflen;
+ FILE *sidf;
+ FILE *sidh;
+ FILE *charset;
+ FILE *encoding;
+ FILE *globalsubrs;
+ FILE *private;
+ FILE *charstrings;
+ FILE *fdselect;
+ FILE *fdarray;
+ FILE *bdat; /* might be EBDT */
+ int bdatlen;
+ FILE *bloc; /* might be EBLC */
+ int bloclen;
+ FILE *ebsc;
+ int ebsclen;
+ FILE *prop;
+ int proplen;
+ FILE *opbd;
+ int opbdlen;
+ FILE *acnt;
+ int acntlen;
+ FILE *lcar;
+ int lcarlen;
+ FILE *feat;
+ int featlen;
+ FILE *morx;
+ int morxlen;
+ FILE *pfed;
+ int pfedlen;
+ FILE *tex;
+ int texlen;
+ FILE *bdf;
+ int bdflen;
+ FILE *gvar;
+ int gvarlen;
+ FILE *fvar;
+ int fvarlen;
+ FILE *cvar;
+ int cvarlen;
+ FILE *avar;
+ int avarlen;
+ FILE *fftmf;
+ int fftmlen;
+ int defwid, nomwid;
+ int sidcnt;
+ int lenpos;
+ int privatelen;
+ unsigned int sidlongoffset: 1;
+ unsigned int cfflongoffset: 1;
+ unsigned int applemode: 1; /* Where apple & ms differ do things apple's way (bitmaps, name table PostScript) */
+ unsigned int opentypemode: 1; /* Where apple & ms differ do things opentype's way (bitmaps, name table PostScript) */
+ /* If both are set then try to generate both types of tables. Some things can't be fudged though (name table postscript) */
+ unsigned int msbitmaps: 1;
+ unsigned int applebitmaps: 1;
+ unsigned int otbbitmaps: 1;
+ unsigned int isotf: 1;
+ unsigned int dovariations: 1; /* Output Apple *var tables (for mm fonts) */
+ unsigned int error: 1;
+ struct glyphinfo gi;
+ int isfixed;
+ struct fd2data *fds;
+ int next_strid;
+
+ struct feat_name { int strid; struct macname *mn, *smn; } *feat_name;
+ struct other_names { int strid; struct macname *mn; struct other_names *next; } *other_names;
+ struct macname2 *ordered_feat;
+
+ int next_lookup; /* for doing nested lookups in contextual features */
+ short *gn_sid;
+ enum fontformat format;
+ int fontstyle_name_strid; /* For GPOS 'size' */
+ SplineFont *sf;
+ EncMap *map;
+};
+
+struct subhead { uint16 first, cnt, delta, rangeoff; }; /* a sub header in 8/16 cmap table */
+
+enum touchflags { tf_x=1, tf_y=2, tf_d=4, tf_endcontour=0x80, tf_startcontour=0x40 };
+
+struct contexttree {
+ int depth;
+ int branch_cnt; /* count of subbranches of this node */
+ struct ct_branch {
+ uint16 classnum;
+ struct contexttree *branch;
+ } *branches;
+ struct fpst_rule *ends_here;
+ int rule_cnt; /* count of rules which are active here */
+ struct ct_subs {
+ struct fpst_rule *rule;
+ struct contexttree *branch;/* if the rule ends here this will be null */
+ uint16 thisclassnum;
+ } *rules;
+ int pending_pos;
+ OTLookup *applymarkedsubs;
+ OTLookup *applycursubs;
+ uint16 marked_index, cur_index;
+ uint8 markme;
+ int state, next_state;
+ struct contexttree *parent;
+};
+
+ /* TrueType Composite glyph flags */
+#define _ARGS_ARE_WORDS 1
+#define _ARGS_ARE_XY 2
+#define _ROUND 4 /* round offsets so componant is on grid */
+#define _SCALE 8
+/* 0x10 is reserved */
+#define _MORE 0x20
+#define _XY_SCALE 0x40
+#define _MATRIX 0x80
+#define _INSTR 0x100
+#define _USE_MY_METRICS 0x200
+#define _OVERLAP_COMPOUND 0x400 /* Used in Apple GX fonts */
+ /* Means the components overlap (which? this one and what other?) */
+/* Described in OpenType specs, not by Apple */
+/* amusingly, Apple supports but MS does not */
+/* MS says they support this after Win 2000 */
+#define _SCALED_OFFSETS 0x800 /* Use Apple definition of offset interpretation */
+#define _UNSCALED_OFFSETS 0x1000 /* Use MS definition */
+
+extern int ttfFixupRef(SplineChar **chars,int i);
+
+ /* Open type Advanced Typography Tables */
+extern void otf_dumpgpos(struct alltabs *at, SplineFont *sf);
+extern void otf_dumpgsub(struct alltabs *at, SplineFont *sf);
+extern void otf_dumpgdef(struct alltabs *at, SplineFont *sf);
+extern int gdefclass(SplineChar *sc);
+
+ /* Apple Advanced Typography Tables */
+extern void aat_dumpacnt(struct alltabs *at, SplineFont *sf);
+extern void ttf_dumpkerns(struct alltabs *at, SplineFont *sf);
+extern void aat_dumplcar(struct alltabs *at, SplineFont *sf);
+extern void aat_dumpmorx(struct alltabs *at, SplineFont *sf);
+extern void aat_dumpopbd(struct alltabs *at, SplineFont *sf);
+extern void aat_dumpprop(struct alltabs *at, SplineFont *sf);
+extern int LookupHasDefault(OTLookup *otl);
+extern int scriptsHaveDefault(struct scriptlanglist *sl);
+extern int FPSTisMacable(SplineFont *sf, FPST *fpst);
+extern uint32 MacFeatureToOTTag(int featureType,int featureSetting);
+extern int OTTagToMacFeature(uint32 tag, int *featureType,int *featureSetting);
+extern uint16 *props_array(SplineFont *sf,struct glyphinfo *gi);
+extern int haslrbounds(SplineChar *sc, PST **left, PST **right);
+
+ /* Apple variation tables */
+extern int ContourPtNumMatch(MMSet *mm, int gid);
+extern int16 **SCFindDeltas(MMSet *mm, int gid, int *_ptcnt);
+extern int16 **CvtFindDeltas(MMSet *mm, int *_ptcnt);
+extern void ttf_dumpvariations(struct alltabs *at, SplineFont *sf);
+
+extern struct macsettingname {
+ int mac_feature_type;
+ int mac_feature_setting;
+ uint32 otf_tag;
+} macfeat_otftag[], *user_macfeat_otftag;
+
+ /* TrueType instructions */
+extern struct ttf_table *SFFindTable(SplineFont *sf,uint32 tag);
+extern int32 memlong(uint8 *data,int table_len, int offset);
+extern int memushort(uint8 *data,int table_len, int offset);
+extern void memputshort(uint8 *data,int offset,uint16 val);
+extern int TTF__getcvtval(SplineFont *sf,int val);
+extern int TTF_getcvtval(SplineFont *sf,int val);
+extern void initforinstrs(SplineChar *sc);
+extern int SSAddPoints(SplineSet *ss,int ptcnt,BasePoint *bp, char *flags);
+
+ /* Used by both otf and apple */
+extern uint16 *ClassesFromNames(SplineFont *sf,char **classnames,int class_cnt,
+ int numGlyphs, SplineChar ***glyphs, int apple_kc);
+extern SplineChar **SFGlyphsFromNames(SplineFont *sf,char *names);
+
+
+extern void AnchorClassOrder(SplineFont *sf);
+extern SplineChar **EntryExitDecompose(SplineFont *sf,AnchorClass *ac,
+ struct glyphinfo *gi);
+extern void AnchorClassDecompose(SplineFont *sf,AnchorClass *_ac, int classcnt, int *subcnts,
+ SplineChar ***marks,SplineChar ***base,
+ SplineChar ***lig,SplineChar ***mkmk,
+ struct glyphinfo *gi);
+
+#ifdef _HAS_LONGLONG
+extern void cvt_unix_to_1904( long long time, int32 result[2]);
+#else
+extern void cvt_unix_to_1904( long time, int32 result[2]);
+#endif
+
+
+ /* Non-standard tables */
+ /* My PfEd table for FontForge/PfaEdit specific info */
+extern void pfed_dump(struct alltabs *at, SplineFont *sf);
+extern void pfed_read(FILE *ttf,struct ttfinfo *info);
+ /* The TeX table, to contain stuff the TeX people want */
+extern void tex_dump(struct alltabs *at, SplineFont *sf);
+extern void tex_read(FILE *ttf,struct ttfinfo *info);
+ /* The BDF table, to contain bdf properties the X people want */
+extern int ttf_bdf_dump(SplineFont *sf,struct alltabs *at,int32 *sizes);
+extern void ttf_bdf_read(FILE *ttf,struct ttfinfo *info);
+ /* The FFTM table, to some timestamps I'd like */
+extern int ttf_fftm_dump(SplineFont *sf,struct alltabs *at);
+
+
+ /* Parsing advanced typography */
+extern void readmacfeaturemap(FILE *ttf,struct ttfinfo *info);
+extern void readttfkerns(FILE *ttf,struct ttfinfo *info);
+extern void readttfmort(FILE *ttf,struct ttfinfo *info);
+extern void readttfopbd(FILE *ttf,struct ttfinfo *info);
+extern void readttflcar(FILE *ttf,struct ttfinfo *info);
+extern void readttfprop(FILE *ttf,struct ttfinfo *info);
+extern void readttfgsubUsed(FILE *ttf,struct ttfinfo *info);
+extern void GuessNamesFromGSUB(FILE *ttf,struct ttfinfo *info);
+extern void readttfgpossub(FILE *ttf,struct ttfinfo *info,int gpos);
+extern void readttfgdef(FILE *ttf,struct ttfinfo *info);
+
+extern void VariationFree(struct ttfinfo *info);
+extern void readttfvariations(struct ttfinfo *info, FILE *ttf);
+
+extern struct otfname *FindAllLangEntries(FILE *ttf, struct ttfinfo *info, int id );
+
+/* Known font parameters for 'TeX ' table (fontdims, spacing params, whatever you want to call them) */
+ /* Used by all fonts */
+#define TeX_Slant CHR('S','l','n','t')
+#define TeX_Space CHR('S','p','a','c')
+#define TeX_Stretch CHR('S','t','r','e')
+#define TeX_Shrink CHR('S','h','n','k')
+#define TeX_XHeight CHR('X','H','g','t')
+#define TeX_Quad CHR('Q','u','a','d')
+ /* Used by text fonts */
+#define TeX_ExtraSp CHR('E','x','S','p')
+ /* Used by all math fonts */
+#define TeX_MathSp CHR('M','t','S','p')
+ /* Used by math fonts */
+#define TeX_Num1 CHR('N','u','m','1')
+#define TeX_Num2 CHR('N','u','m','2')
+#define TeX_Num3 CHR('N','u','m','3')
+#define TeX_Denom1 CHR('D','n','m','1')
+#define TeX_Denom2 CHR('D','n','m','2')
+#define TeX_Sup1 CHR('S','u','p','1')
+#define TeX_Sup2 CHR('S','u','p','2')
+#define TeX_Sup3 CHR('S','u','p','3')
+#define TeX_Sub1 CHR('S','u','b','1')
+#define TeX_Sub2 CHR('S','u','b','2')
+#define TeX_SupDrop CHR('S','p','D','p')
+#define TeX_SubDrop CHR('S','b','D','p')
+#define TeX_Delim1 CHR('D','l','m','1')
+#define TeX_Delim2 CHR('D','l','m','2')
+#define TeX_AxisHeight CHR('A','x','H','t')
+ /* Used by math extension fonts */
+#define TeX_DefRuleThick CHR('R','l','T','k')
+#define TeX_BigOpSpace1 CHR('B','O','S','1')
+#define TeX_BigOpSpace2 CHR('B','O','S','2')
+#define TeX_BigOpSpace3 CHR('B','O','S','3')
+#define TeX_BigOpSpace4 CHR('B','O','S','4')
+#define TeX_BigOpSpace5 CHR('B','O','S','5')
+
+extern void SFDummyUpCIDs(struct glyphinfo *gi,SplineFont *sf);
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/ttfspecial.c b/Build/source/libs/luafontforge/fontforge/fontforge/ttfspecial.c
new file mode 100644
index 00000000000..5ff917ba3ef
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/ttfspecial.c
@@ -0,0 +1,1067 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pfaedit.h"
+#include <time.h>
+#include <utype.h>
+#include <ustring.h>
+#include <gdraw.h> /* For COLOR_DEFAULT */
+
+#include "ttf.h"
+
+/* This file contains routines to generate non-standard true/opentype tables */
+/* The first is the 'PfEd' table containing PfaEdit specific information */
+/* glyph comments & colours ... perhaps other info later */
+
+/* ************************************************************************** */
+/* ************************* The 'PfEd' table ************************* */
+/* ************************* Output ************************* */
+/* ************************************************************************** */
+
+/* 'PfEd' table format is as follows... */
+/* uint32 version number 0x00010000 */
+/* uint32 subtable count */
+/* struct { uint32 tab, offset } tag/offset for first subtable */
+/* struct { uint32 tab, offset } tag/offset for second subtable */
+/* ... */
+
+/* 'PfEd' 'fcmt' font comment subtable format */
+/* short version number 0 */
+/* short string length */
+/* String in latin1 (ASCII is better) */
+
+/* 'PfEd' 'cmnt' glyph comment subtable format */
+/* short version number 0 */
+/* short count-of-ranges */
+/* struct { short start-glyph, end-glyph, short offset } */
+/* ... */
+/* foreach glyph >=start-glyph, <=end-glyph(+1) */
+/* uint32 offset to glyph comment string (in UCS2) */
+/* ... */
+/* And one last offset pointing beyong the end of the last string to enable length calculations */
+/* String table in UCS2 (NUL terminated). All offsets from start*/
+/* of subtable */
+
+/* 'PfEd' 'colr' glyph colour subtable */
+/* short version number 0 */
+/* short count-of-ranges */
+/* struct { short start-glyph, end-glyph, uint32 colour (rgb) } */
+
+#define MAX_SUBTABLE_TYPES 3
+
+struct PfEd_subtabs {
+ int next;
+ struct {
+ FILE *data;
+ uint32 tag;
+ uint32 offset;
+ } subtabs[MAX_SUBTABLE_TYPES];
+};
+
+static void PfEd_FontComment(SplineFont *sf, struct PfEd_subtabs *pfed ) {
+ FILE *fcmt;
+ char *pt;
+
+ if ( sf->comments==NULL || *sf->comments=='\0' )
+return;
+ pfed->subtabs[pfed->next].tag = CHR('f','c','m','t');
+ pfed->subtabs[pfed->next++].data = fcmt = tmpfile();
+
+ putshort(fcmt,0); /* sub-table version number */
+ putshort(fcmt,strlen(sf->comments));
+ for ( pt = sf->comments; *pt; ++pt )
+ putshort(fcmt,*pt);
+ putshort(fcmt,0);
+ if ( ftell(fcmt)&2 ) putshort(fcmt,0);
+}
+
+static void PfEd_GlyphComments(SplineFont *sf, struct PfEd_subtabs *pfed,
+ struct glyphinfo *gi ) {
+ int i, j, k, any, cnt, last, skipped;
+ uint32 offset;
+ SplineChar *sc, *sc2;
+ FILE *cmnt;
+ char *upt;
+ uint32 uch;
+
+ sc2 = NULL;
+ any = 0;
+ /* We don't need to check in bygid order. We just want to know existance */
+ for ( i=0; i<sf->glyphcnt; ++i ) {
+ if ( sf->glyphs[i]!=NULL && sf->glyphs[i]->ttf_glyph!=-1 &&
+ sf->glyphs[i]->comment!=NULL ) {
+ any = true;
+ break;
+ }
+ }
+
+ if ( !any )
+return;
+
+ pfed->subtabs[pfed->next].tag = CHR('c','m','n','t');
+ pfed->subtabs[pfed->next++].data = cmnt = tmpfile();
+
+ putshort(cmnt,0); /* sub-table version number */
+
+ offset = 0;
+ for ( j=0; j<4; ++j ) {
+ cnt = 0;
+ for ( i=0; i<gi->gcnt; ++i ) if ( gi->bygid[i]!=-1 ) {
+ sc=sf->glyphs[gi->bygid[i]];
+ if ( sc!=NULL && sc->comment!=NULL ) {
+ last = i; skipped = false;
+ for ( k=i+1; k<gi->gcnt; ++k ) {
+ if ( gi->bygid[k]!=-1 )
+ sc2 = sf->glyphs[gi->bygid[k]];
+ if ( (gi->bygid[k]==-1 || sc2->comment==NULL) && skipped )
+ break;
+ if ( gi->bygid[k]!=-1 && sc2->comment!=NULL ) {
+ last = k;
+ skipped = false;
+ } else
+ skipped = true;
+ }
+ ++cnt;
+ if ( j==1 ) {
+ putshort(cmnt,i);
+ putshort(cmnt,last);
+ putlong(cmnt,offset);
+ offset += sizeof(uint32)*(last-i+2);
+ } else if ( j==2 ) {
+ for ( ; i<=last; ++i ) {
+ if ( gi->bygid[i]==-1 || (sc=sf->glyphs[gi->bygid[i]])->comment==NULL )
+ putlong(cmnt,0);
+ else {
+ putlong(cmnt,offset);
+ offset += sizeof(unichar_t)*(utf82u_strlen(sc->comment)+1);
+ }
+ }
+ putlong(cmnt,offset); /* Guard data, to let us calculate the string lengths */
+ } else if ( j==3 ) {
+ for ( ; i<=last; ++i ) {
+ if ( gi->bygid[i]==-1 || (sc=sf->glyphs[gi->bygid[i]])->comment==NULL )
+ continue;
+ for ( upt = sc->comment; (uch = utf8_ildb((const char **) &upt))!='\0'; ) {
+ if ( uch<0x10000 )
+ putshort(cmnt,uch);
+ else {
+ putshort(cmnt,0xd800|(uch/0x400));
+ putshort(cmnt,0xdc00|(uch&0x3ff));
+ }
+ }
+ putshort(cmnt,0);
+ }
+ }
+ i = last;
+ }
+ }
+ if ( j==0 ) {
+ putshort(cmnt,cnt);
+ offset = 2*sizeof(short) + cnt*(2*sizeof(short)+sizeof(uint32));
+ }
+ }
+ if ( ftell(cmnt) & 2 )
+ putshort(cmnt,0);
+}
+
+static void PfEd_Colours(SplineFont *sf, struct PfEd_subtabs *pfed, struct glyphinfo *gi ) {
+ int i, j, k, any, cnt, last;
+ SplineChar *sc, *sc2;
+ FILE *colr;
+
+ any = 0;
+ for ( i=0; i<sf->glyphcnt; ++i ) {
+ if ( sf->glyphs[i]!=NULL && sf->glyphs[i]->ttf_glyph!=-1 &&
+ sf->glyphs[i]->color!=COLOR_DEFAULT ) {
+ any = true;
+ break;
+ }
+ }
+
+ if ( !any )
+return;
+
+ pfed->subtabs[pfed->next].tag = CHR('c','o','l','r');
+ pfed->subtabs[pfed->next++].data = colr = tmpfile();
+
+ putshort(colr,0); /* sub-table version number */
+ for ( j=0; j<2; ++j ) {
+ cnt = 0;
+ for ( i=0; i<gi->gcnt; ++i ) if ( gi->bygid[i]!=-1 ) {
+ sc = sf->glyphs[gi->bygid[i]];
+ if ( sc!=NULL && sc->color!=COLOR_DEFAULT ) {
+ last = i;
+ for ( k=i+1; k<gi->gcnt; ++k ) {
+ if ( gi->bygid[k]==-1 )
+ break;
+ sc2 = sf->glyphs[gi->bygid[k]];
+ if ( sc2->color != sc->color )
+ break;
+ last = k;
+ }
+ ++cnt;
+ if ( j==1 ) {
+ putshort(colr,i);
+ putshort(colr,last);
+ putlong(colr,sc->color);
+ }
+ i = last;
+ }
+ }
+ if ( j==0 )
+ putshort(colr,cnt);
+ }
+ if ( ftell(colr) & 2 )
+ putshort(colr,0);
+}
+
+void pfed_dump(struct alltabs *at, SplineFont *sf) {
+ struct PfEd_subtabs pfed;
+ FILE *file;
+ int i;
+ uint32 offset;
+
+ memset(&pfed,0,sizeof(pfed));
+ if ( at->gi.flags & ttf_flag_pfed_comments ) {
+ PfEd_FontComment(sf, &pfed );
+ PfEd_GlyphComments(sf, &pfed, &at->gi );
+ }
+ if ( at->gi.flags & ttf_flag_pfed_colors )
+ PfEd_Colours(sf, &pfed, &at->gi );
+
+ if ( pfed.next==0 )
+return; /* No subtables */
+
+ at->pfed = file = tmpfile();
+ putlong(file, 0x00010000); /* Version number */
+ putlong(file, pfed.next); /* sub-table count */
+ offset = 2*sizeof(uint32) + 2*pfed.next*sizeof(uint32);
+ for ( i=0; i<pfed.next; ++i ) {
+ putlong(file,pfed.subtabs[i].tag);
+ putlong(file,offset);
+ fseek(pfed.subtabs[i].data,0,SEEK_END);
+ pfed.subtabs[i].offset = offset;
+ offset += ftell(pfed.subtabs[i].data);
+ }
+ for ( i=0; i<pfed.next; ++i ) {
+ fseek(pfed.subtabs[i].data,0,SEEK_SET);
+ ttfcopyfile(file,pfed.subtabs[i].data,pfed.subtabs[i].offset,"PfEd-subtable");
+ }
+ if ( ftell(file)&3 )
+ IError("'PfEd' table not properly aligned");
+ at->pfedlen = ftell(file);
+}
+
+/* ************************* The 'PfEd' table ************************* */
+/* ************************* Input ************************* */
+
+static void pfed_readfontcomment(FILE *ttf,struct ttfinfo *info,uint32 base) {
+ int len;
+ char *pt, *end;
+
+ fseek(ttf,base,SEEK_SET);
+ if ( getushort(ttf)!=0 )
+return; /* Bad version number */
+ len = getushort(ttf);
+ pt = galloc(len+1); /* data are stored as UCS2, but currently are ASCII */
+ info->fontcomments = pt;
+ end = pt+len;
+ while ( pt<end )
+ *pt++ = getushort(ttf);
+ *pt = '\0';
+}
+
+static char *ReadUnicodeStr(FILE *ttf,uint32 offset,int len) {
+ char *pt, *str;
+ uint32 uch, uch2;
+ int i;
+
+ if ( len<0 )
+return( NULL );
+
+ len>>=1;
+ pt = str = galloc(3*len);
+ fseek(ttf,offset,SEEK_SET);
+ for ( i=0; i<len; ++i ) {
+ uch = getushort(ttf);
+ if ( uch>=0xd800 && uch<0xdc00 ) {
+ uch2 = getushort(ttf);
+ if ( uch2>=0xdc00 && uch2<0xe000 )
+ uch = ((uch-0xd800)<<10) | (uch2&0x3ff);
+ else {
+ pt = utf8_idpb(pt,uch);
+ uch = uch2;
+ }
+ }
+ pt = utf8_idpb(pt,uch);
+ }
+ *pt++ = 0;
+return( grealloc(str,pt-str) );
+}
+
+static void pfed_readglyphcomments(FILE *ttf,struct ttfinfo *info,uint32 base) {
+ int n, i, j;
+ struct grange { int start, end; uint32 offset; } *grange;
+ uint32 offset, next;
+
+ fseek(ttf,base,SEEK_SET);
+ if ( getushort(ttf)!=0 )
+return; /* Bad version number */
+ n = getushort(ttf);
+ grange = galloc(n*sizeof(struct grange));
+ for ( i=0; i<n; ++i ) {
+ grange[i].start = getushort(ttf);
+ grange[i].end = getushort(ttf);
+ grange[i].offset = getlong(ttf);
+ if ( grange[i].start>grange[i].end || grange[i].end>info->glyph_cnt ) {
+ LogError( _("Bad glyph range specified in glyph comment subtable of PfEd table\n") );
+ grange[i].start = 1; grange[i].end = 0;
+ }
+ }
+ for ( i=0; i<n; ++i ) {
+ for ( j=grange[i].start; j<=grange[i].end; ++j ) {
+ fseek( ttf,base+grange[i].offset+(j-grange[i].start)*sizeof(uint32),SEEK_SET);
+ offset = getlong(ttf);
+ next = getlong(ttf);
+ info->chars[j]->comment = ReadUnicodeStr(ttf,base+offset,next-offset);
+ if ( info->chars[j]->comment == NULL )
+ LogError("Invalid comment string (negative length?) in 'PfEd' table for glyph %s.",
+ info->chars[j]->name );
+ }
+ }
+ free(grange);
+}
+
+static void pfed_readcolours(FILE *ttf,struct ttfinfo *info,uint32 base) {
+ int n, i, j, start, end;
+ uint32 col;
+
+ fseek(ttf,base,SEEK_SET);
+ if ( getushort(ttf)!=0 )
+return; /* Bad version number */
+ n = getushort(ttf);
+ for ( i=0; i<n; ++i ) {
+ start = getushort(ttf);
+ end = getushort(ttf);
+ col = getlong(ttf);
+ if ( start>end || end>info->glyph_cnt )
+ LogError( _("Bad glyph range specified in colour subtable of PfEd table\n") );
+ else {
+ for ( j=start; j<=end; ++j )
+ info->chars[j]->color = col;
+ }
+ }
+}
+
+void pfed_read(FILE *ttf,struct ttfinfo *info) {
+ int n,i;
+ struct tagoff { uint32 tag, offset; } tagoff[MAX_SUBTABLE_TYPES+30];
+
+ fseek(ttf,info->pfed_start,SEEK_SET);
+
+ if ( getlong(ttf)!=0x00010000 )
+return;
+ n = getlong(ttf);
+ if ( n>=MAX_SUBTABLE_TYPES+30 )
+ n = MAX_SUBTABLE_TYPES+30;
+ for ( i=0; i<n; ++i ) {
+ tagoff[i].tag = getlong(ttf);
+ tagoff[i].offset = getlong(ttf);
+ }
+ for ( i=0; i<n; ++i ) switch ( tagoff[i].tag ) {
+ case CHR('f','c','m','t'):
+ pfed_readfontcomment(ttf,info,info->pfed_start+tagoff[i].offset);
+ break;
+ case CHR('c','m','n','t'):
+ pfed_readglyphcomments(ttf,info,info->pfed_start+tagoff[i].offset);
+ break;
+ case CHR('c','o','l','r'):
+ pfed_readcolours(ttf,info,info->pfed_start+tagoff[i].offset);
+ break;
+ default:
+ LogError( _("Unknown subtable '%c%c%c%c' in 'PfEd' table, ignored\n"),
+ tagoff[i].tag>>24, (tagoff[i].tag>>16)&0xff, (tagoff[i].tag>>8)&0xff, tagoff[i].tag&0xff );
+ break;
+ }
+}
+
+/* 'TeX ' table format is as follows... */
+/* uint32 version number 0x00010000 */
+/* uint32 subtable count */
+/* struct { uint32 tab, offset } tag/offset for first subtable */
+/* struct { uint32 tab, offset } tag/offset for second subtable */
+/* ... */
+
+/* 'TeX ' 'ftpm' font parameter subtable format */
+/* short version number 0 */
+/* parameter count */
+/* array of { 4chr tag, value } */
+
+/* 'TeX ' 'htdp' per-glyph height/depth subtable format */
+/* short version number 0 */
+/* short glyph-count */
+/* array[glyph-count] of { int16 height,depth } */
+
+/* 'TeX ' 'sbsp' per-glyph sub/super script positioning subtable */
+/* short version number 0 */
+/* short glyph-count */
+/* array[glyph-count] of { int16 sub,super } */
+
+#undef MAX_SUBTABLE_TYPES
+#define MAX_SUBTABLE_TYPES 3
+
+struct TeX_subtabs {
+ int next;
+ struct {
+ FILE *data;
+ uint32 tag;
+ uint32 offset;
+ } subtabs[MAX_SUBTABLE_TYPES];
+};
+
+static uint32 tex_text_params[] = {
+ TeX_Slant,
+ TeX_Space,
+ TeX_Stretch,
+ TeX_Shrink,
+ TeX_XHeight,
+ TeX_Quad,
+ TeX_ExtraSp,
+ 0
+};
+static uint32 tex_math_params[] = {
+ TeX_Slant,
+ TeX_Space,
+ TeX_Stretch,
+ TeX_Shrink,
+ TeX_XHeight,
+ TeX_Quad,
+ TeX_MathSp,
+ TeX_Num1,
+ TeX_Num2,
+ TeX_Num3,
+ TeX_Denom1,
+ TeX_Denom2,
+ TeX_Sup1,
+ TeX_Sup2,
+ TeX_Sup3,
+ TeX_Sub1,
+ TeX_Sub2,
+ TeX_SupDrop,
+ TeX_SubDrop,
+ TeX_Delim1,
+ TeX_Delim2,
+ TeX_AxisHeight,
+ 0};
+static uint32 tex_mathext_params[] = {
+ TeX_Slant,
+ TeX_Space,
+ TeX_Stretch,
+ TeX_Shrink,
+ TeX_XHeight,
+ TeX_Quad,
+ TeX_MathSp,
+ TeX_DefRuleThick,
+ TeX_BigOpSpace1,
+ TeX_BigOpSpace2,
+ TeX_BigOpSpace3,
+ TeX_BigOpSpace4,
+ TeX_BigOpSpace5,
+ 0};
+
+/* ************************************************************************** */
+/* ************************* The 'TeX ' table ************************* */
+/* ************************* Output ************************* */
+/* ************************************************************************** */
+
+static void TeX_dumpFontParams(SplineFont *sf, struct TeX_subtabs *tex, struct alltabs *at ) {
+ FILE *fprm;
+ int i,pcnt;
+ uint32 *tags;
+
+ if ( sf->texdata.type==tex_unset )
+return;
+ tex->subtabs[tex->next].tag = CHR('f','t','p','m');
+ tex->subtabs[tex->next++].data = fprm = tmpfile();
+
+ putshort(fprm,0); /* sub-table version number */
+ pcnt = sf->texdata.type==tex_math ? 22 : sf->texdata.type==tex_mathext ? 13 : 7;
+ tags = sf->texdata.type==tex_math ? tex_math_params :
+ sf->texdata.type==tex_mathext ? tex_mathext_params :
+ tex_text_params;
+ putshort(fprm,pcnt);
+ for ( i=0; i<pcnt; ++i ) {
+ putlong(fprm,tags[i]);
+ putlong(fprm,sf->texdata.params[i]);
+ }
+ /* always aligned */
+}
+
+static void TeX_dumpHeightDepth(SplineFont *sf, struct TeX_subtabs *tex, struct alltabs *at ) {
+ FILE *htdp;
+ int i,j,k,last_g, gid;
+ DBounds b;
+
+ for ( i=at->gi.gcnt-1; i>=0; --i ) {
+ gid = at->gi.bygid[i];
+ if ( gid!=-1 && sf->glyphs[gid]!=NULL &&
+ (sf->glyphs[gid]->tex_height!=TEX_UNDEF || sf->glyphs[gid]->tex_depth!=TEX_UNDEF))
+ break;
+ }
+ if ( i<0 ) /* No height/depth info */
+return;
+
+ tex->subtabs[tex->next].tag = CHR('h','t','d','p');
+ tex->subtabs[tex->next++].data = htdp = tmpfile();
+
+ putshort(htdp,0); /* sub-table version number */
+ putshort(htdp,sf->glyphs[gid]->ttf_glyph+1);/* data for this many glyphs */
+
+ last_g = -1;
+ for ( j=0; j<=i; ++j ) {
+ gid = at->gi.bygid[j];
+ if ( gid!=-1 && sf->glyphs[gid]!=NULL ) {
+ SplineChar *sc = sf->glyphs[gid];
+ for ( k=last_g+1; k<sc->ttf_glyph; ++k ) {
+ putshort(htdp,0);
+ putshort(htdp,0);
+ }
+ if ( sc->tex_depth==TEX_UNDEF || sc->tex_height==TEX_UNDEF )
+ SplineCharFindBounds(sc,&b);
+ putshort( htdp, sc->tex_height==TEX_UNDEF ? b.maxy : sc->tex_height );
+ putshort( htdp, sc->tex_depth==TEX_UNDEF ? -b.miny : sc->tex_depth );
+ last_g = sc->ttf_glyph;
+ }
+ }
+ /* always aligned */
+}
+
+static void TeX_dumpSubSuper(SplineFont *sf, struct TeX_subtabs *tex, struct alltabs *at ) {
+ FILE *sbsp;
+ int i,j,k,last_g, gid;
+
+ for ( i=at->gi.gcnt-1; i>=0; --i ) {
+ gid = at->gi.bygid[i];
+ if ( gid!=-1 && sf->glyphs[gid]!=NULL &&
+ (sf->glyphs[gid]->tex_sub_pos!=TEX_UNDEF || sf->glyphs[gid]->tex_super_pos!=TEX_UNDEF))
+ break;
+ }
+ if ( i<0 ) /* No sub/super info */
+return;
+
+ tex->subtabs[tex->next].tag = CHR('s','b','s','p');
+ tex->subtabs[tex->next++].data = sbsp = tmpfile();
+
+ putshort(sbsp,0); /* sub-table version number */
+ putshort(sbsp,sf->glyphs[gid]->ttf_glyph+1);/* data for this many glyphs */
+
+ last_g = -1;
+ for ( j=0; j<=i; ++j ) {
+ gid = at->gi.bygid[j];
+ if ( gid!=-1 && sf->glyphs[gid]!=NULL ) {
+ SplineChar *sc = sf->glyphs[gid];
+ for ( k=last_g+1; k<sc->ttf_glyph; ++k ) {
+ putshort(sbsp,0);
+ putshort(sbsp,0);
+ }
+ putshort( sbsp, sc->tex_sub_pos==TEX_UNDEF ? sc->width : sc->tex_sub_pos );
+ putshort( sbsp, sc->tex_super_pos!=TEX_UNDEF ? sc->tex_super_pos :
+ sc->tex_sub_pos!=TEX_UNDEF ? sc->width - sc->tex_sub_pos :
+ 0 );
+ last_g = sc->ttf_glyph;
+ }
+ }
+ /* always aligned */
+}
+
+void tex_dump(struct alltabs *at, SplineFont *sf) {
+ struct TeX_subtabs tex;
+ FILE *file;
+ int i;
+ uint32 offset;
+
+ if ( !(at->gi.flags & ttf_flag_TeXtable ))
+return;
+
+ memset(&tex,0,sizeof(tex));
+ TeX_dumpFontParams(sf,&tex,at);
+ TeX_dumpHeightDepth(sf,&tex,at);
+ TeX_dumpSubSuper(sf,&tex,at);
+
+ if ( tex.next==0 )
+return; /* No subtables */
+
+ at->tex = file = tmpfile();
+ putlong(file, 0x00010000); /* Version number */
+ putlong(file, tex.next); /* sub-table count */
+ offset = 2*sizeof(uint32) + 2*tex.next*sizeof(uint32);
+ for ( i=0; i<tex.next; ++i ) {
+ putlong(file,tex.subtabs[i].tag);
+ putlong(file,offset);
+ fseek(tex.subtabs[i].data,0,SEEK_END);
+ tex.subtabs[i].offset = offset;
+ offset += ftell(tex.subtabs[i].data);
+ }
+ for ( i=0; i<tex.next; ++i ) {
+ fseek(tex.subtabs[i].data,0,SEEK_SET);
+ ttfcopyfile(file,tex.subtabs[i].data,tex.subtabs[i].offset,"TeX-subtable");
+ }
+ if ( ftell(file)&3 )
+ IError("'TeX ' table not properly aligned");
+ at->texlen = ftell(file);
+}
+
+/* ************************* The 'TeX ' table ************************* */
+/* ************************* Input ************************* */
+
+static void TeX_readFontParams(FILE *ttf,struct ttfinfo *info,uint32 base) {
+ int i,pcnt;
+ static uint32 *alltags[] = { tex_text_params, tex_math_params, tex_mathext_params };
+ int j,k;
+ uint32 tag;
+ int32 val;
+
+ fseek(ttf,base,SEEK_SET);
+ if ( getushort(ttf)!=0 ) /* Don't know how to read this version of the subtable */
+return;
+ pcnt = getushort(ttf);
+ if ( pcnt==22 ) info->texdata.type = tex_math;
+ else if ( pcnt==13 ) info->texdata.type = tex_mathext;
+ else if ( pcnt>=7 ) info->texdata.type = tex_text;
+ for ( i=0; i<pcnt; ++i ) {
+ tag = getlong(ttf);
+ val = getlong(ttf);
+ for ( j=0; j<3; ++j ) {
+ for ( k=0; alltags[j][k]!=0; ++k )
+ if ( alltags[j][k]==tag )
+ break;
+ if ( alltags[j][k]==tag )
+ break;
+ }
+ if ( j<3 )
+ info->texdata.params[k] = val;
+ }
+}
+
+static void TeX_readHeightDepth(FILE *ttf,struct ttfinfo *info,uint32 base) {
+ int i,gcnt;
+
+ fseek(ttf,base,SEEK_SET);
+ if ( getushort(ttf)!=0 ) /* Don't know how to read this version of the subtable */
+return;
+ gcnt = getushort(ttf);
+ for ( i=0; i<gcnt && i<info->glyph_cnt; ++i ) {
+ int h, d;
+ h = getushort(ttf);
+ d = getushort(ttf);
+ if ( info->chars[i]!=NULL ) {
+ info->chars[i]->tex_height = h;
+ info->chars[i]->tex_depth = d;
+ }
+ }
+}
+
+static void TeX_readSubSuper(FILE *ttf,struct ttfinfo *info,uint32 base) {
+ int i,gcnt;
+
+ fseek(ttf,base,SEEK_SET);
+ if ( getushort(ttf)!=0 ) /* Don't know how to read this version of the subtable */
+return;
+ gcnt = getushort(ttf);
+ for ( i=0; i<gcnt && i<info->glyph_cnt; ++i ) {
+ int super, sub;
+ sub = getushort(ttf);
+ super = getushort(ttf);
+ if ( info->chars[i]!=NULL ) {
+ info->chars[i]->tex_sub_pos = sub;
+ info->chars[i]->tex_super_pos = super;
+ }
+ }
+}
+
+void tex_read(FILE *ttf,struct ttfinfo *info) {
+ int n,i;
+ struct tagoff { uint32 tag, offset; } tagoff[MAX_SUBTABLE_TYPES+30];
+
+ fseek(ttf,info->tex_start,SEEK_SET);
+
+ if ( getlong(ttf)!=0x00010000 )
+return;
+ n = getlong(ttf);
+ if ( n>=MAX_SUBTABLE_TYPES+30 )
+ n = MAX_SUBTABLE_TYPES+30;
+ for ( i=0; i<n; ++i ) {
+ tagoff[i].tag = getlong(ttf);
+ tagoff[i].offset = getlong(ttf);
+ }
+ for ( i=0; i<n; ++i ) switch ( tagoff[i].tag ) {
+ case CHR('f','t','p','m'):
+ TeX_readFontParams(ttf,info,info->tex_start+tagoff[i].offset);
+ break;
+ case CHR('h','t','d','p'):
+ TeX_readHeightDepth(ttf,info,info->tex_start+tagoff[i].offset);
+ break;
+ case CHR('s','b','s','p'):
+ TeX_readSubSuper(ttf,info,info->tex_start+tagoff[i].offset);
+ break;
+ default:
+ LogError( _("Unknown subtable '%c%c%c%c' in 'TeX ' table, ignored\n"),
+ tagoff[i].tag>>24, (tagoff[i].tag>>16)&0xff, (tagoff[i].tag>>8)&0xff, tagoff[i].tag&0xff );
+ break;
+ }
+}
+
+/* ************************************************************************** */
+/* ************************* The 'BDF ' table ************************* */
+/* ************************* Output ************************* */
+/* ************************************************************************** */
+
+/* the BDF table is used to store BDF properties so that we can do round trip */
+/* conversion from BDF->otb->BDF without losing anything. */
+/* Format:
+ USHORT version : 'BDF' table version number, must be 0x0001
+ USHORT strikeCount : number of strikes in table
+ ULONG stringTable : offset (from start of BDF table) to string table
+
+followed by an array of 'strikeCount' descriptors that look like:
+ USHORT ppem : vertical pixels-per-EM for this strike
+ USHORT num_items : number of items (properties and atoms), max is 255
+
+this array is followed by 'strikeCount' value sets. Each "value set" is
+an array of (num_items) items that look like:
+ ULONG item_name : offset in string table to item name
+ USHORT item_type : item type: 0 => non-property string (e.g. COMMENT)
+ 1 => non-property atom (e.g. FONT)
+ 2 => non-property int32
+ 3 => non-property uint32
+ 0x10 => flag for a property, ored
+ with above value types)
+ ULONG item_value : item value.
+ strings => an offset into the string table
+ to the corresponding string,
+ without the surrending double-quotes
+
+ atoms => an offset into the string table
+
+ integers => the corresponding 32-bit value
+Then the string table of null terminated strings. These strings should be in
+ASCII.
+*/
+
+/* Internally FF stores BDF comments as one psuedo property per line. As you */
+/* might expect. But FreeType merges them into one large lump with newlines */
+/* between lines. Which means that BDF tables created by FreeType will be in*/
+/* that format. So we might as well be compatible. We will pack & unpack */
+/* comment lines */
+
+static int BDFPropCntMergedComments(BDFFont *bdf) {
+ int i, cnt;
+
+ cnt = 0;
+ for ( i=0; i<bdf->prop_cnt; ++i ) {
+ ++cnt;
+ if ( strmatch(bdf->props[i].name,"COMMENT")==0 )
+ break;
+ }
+ for ( ; i<bdf->prop_cnt; ++i ) {
+ if ( strmatch(bdf->props[i].name,"COMMENT")==0 )
+ continue;
+ ++cnt;
+ }
+return( cnt );
+}
+
+static char *MergeComments(BDFFont *bdf) {
+ int len, i;
+ char *str;
+
+ len = 0;
+ for ( i=0; i<bdf->prop_cnt; ++i ) {
+ if ( strmatch(bdf->props[i].name,"COMMENT")==0 &&
+ ((bdf->props[i].type & ~prt_property)==prt_string ||
+ (bdf->props[i].type & ~prt_property)==prt_atom ))
+ len += strlen( bdf->props[i].u.atom ) + 1;
+ }
+ if ( len==0 )
+return( copy( "" ));
+
+ str = galloc( len+1 );
+ len = 0;
+ for ( i=0; i<bdf->prop_cnt; ++i ) {
+ if ( strmatch(bdf->props[i].name,"COMMENT")==0 &&
+ ((bdf->props[i].type & ~prt_property)==prt_string ||
+ (bdf->props[i].type & ~prt_property)==prt_atom )) {
+ strcpy(str+len,bdf->props[i].u.atom );
+ len += strlen( bdf->props[i].u.atom ) + 1;
+ str[len-1] = '\n';
+ }
+ }
+ str[len-1] = '\0';
+return( str );
+}
+
+#define AMAX 50
+
+int ttf_bdf_dump(SplineFont *sf,struct alltabs *at,int32 *sizes) {
+ FILE *strings;
+ struct atomoff { char *name; int pos; } atomoff[AMAX];
+ int acnt=0;
+ int spcnt = 0;
+ int i,j,k;
+ BDFFont *bdf;
+ long pos;
+
+ for ( i=0; sizes[i]!=0; ++i ) {
+ for ( bdf=sf->bitmaps; bdf!=NULL && (bdf->pixelsize!=(sizes[i]&0xffff) || BDFDepth(bdf)!=(sizes[i]>>16)); bdf=bdf->next );
+ if ( bdf!=NULL && bdf->prop_cnt!=0 )
+ ++spcnt;
+ }
+ if ( spcnt==0 ) /* No strikes with properties */
+return(true);
+
+ at->bdf = tmpfile();
+ strings = tmpfile();
+
+ putshort(at->bdf,0x0001);
+ putshort(at->bdf,spcnt);
+ putlong(at->bdf,0); /* offset to string table */
+
+ for ( i=0; sizes[i]!=0; ++i ) {
+ for ( bdf=sf->bitmaps; bdf!=NULL && (bdf->pixelsize!=(sizes[i]&0xffff) || BDFDepth(bdf)!=(sizes[i]>>16)); bdf=bdf->next );
+ if ( bdf!=NULL && bdf->prop_cnt!=0 ) {
+ putshort(at->bdf,bdf->pixelsize);
+ putshort(at->bdf,BDFPropCntMergedComments(bdf));
+ }
+ }
+
+ for ( i=0; sizes[i]!=0; ++i ) {
+ for ( bdf=sf->bitmaps; bdf!=NULL && (bdf->pixelsize!=(sizes[i]&0xffff) || BDFDepth(bdf)!=(sizes[i]>>16)); bdf=bdf->next );
+ if ( bdf!=NULL && bdf->prop_cnt!=0 ) {
+ int saw_comment=0;
+ char *str;
+ for ( j=0; j<bdf->prop_cnt; ++j ) {
+ if ( strmatch(bdf->props[j].name,"COMMENT")==0 && saw_comment )
+ continue;
+ /* Try to reuse keyword names in string space */
+ for ( k=0 ; k<acnt; ++k ) {
+ if ( strcmp(atomoff[k].name,bdf->props[j].name)==0 )
+ break;
+ }
+ if ( k>=acnt && k<AMAX ) {
+ atomoff[k].name = bdf->props[j].name;
+ atomoff[k].pos = ftell(strings);
+ ++acnt;
+ fwrite(atomoff[k].name,1,strlen(atomoff[k].name)+1,strings);
+ }
+ if ( k<acnt )
+ putlong(at->bdf,atomoff[k].pos);
+ else {
+ putlong(at->bdf,ftell(strings));
+ fwrite(bdf->props[j].name,1,strlen(bdf->props[j].name)+1,strings);
+ }
+ str = bdf->props[j].u.str;
+ if ( strmatch(bdf->props[j].name,"COMMENT")==0 ) {
+ str = MergeComments(bdf);
+ saw_comment = true;
+ }
+ putshort(at->bdf,bdf->props[j].type);
+ if ( (bdf->props[j].type & ~prt_property)==prt_string ||
+ (bdf->props[j].type & ~prt_property)==prt_atom ) {
+ putlong(at->bdf,ftell(strings));
+ fwrite(str,1,strlen(str)+1,strings);
+ if ( str!=bdf->props[j].u.str )
+ free(str);
+ } else {
+ putlong(at->bdf,bdf->props[j].u.val);
+ }
+ }
+ }
+ }
+
+ pos = ftell(at->bdf);
+ fseek(at->bdf,4,SEEK_SET);
+ putlong(at->bdf,pos);
+ fseek(at->bdf,0,SEEK_END);
+
+ if ( !ttfcopyfile(at->bdf,strings,pos,"BDF string table"))
+return( false );
+
+ at->bdflen = ftell( at->bdf );
+
+ /* Align table */
+ if ( at->bdflen&1 )
+ putc('\0',at->bdf);
+ if ( (at->bdflen+1)&2 )
+ putshort(at->bdf,0);
+
+return( true );
+}
+
+/* ************************* The 'BDF ' table ************************* */
+/* ************************* Input ************************* */
+
+static char *getstring(FILE *ttf,long start) {
+ long here = ftell(ttf);
+ int len, ch;
+ char *str, *pt;
+
+ fseek(ttf,start,SEEK_SET);
+ for ( len=1; (ch=getc(ttf))>0 ; ++len );
+ fseek(ttf,start,SEEK_SET);
+ pt = str = galloc(len);
+ while ( (ch=getc(ttf))>0 )
+ *pt++ = ch;
+ *pt = '\0';
+ fseek(ttf,here,SEEK_SET);
+return( str );
+}
+
+/* COMMENTS get stored all in one lump by freetype. De-lump them */
+static int CheckForNewlines(BDFFont *bdf,int k) {
+ char *pt, *start;
+ int cnt, i;
+
+ for ( cnt=0, pt = bdf->props[k].u.atom; *pt; ++pt )
+ if ( *pt=='\n' )
+ ++cnt;
+ if ( cnt==0 )
+return( k );
+
+ bdf->prop_cnt += cnt;
+ bdf->props = grealloc(bdf->props, bdf->prop_cnt*sizeof( BDFProperties ));
+
+ pt = strchr(bdf->props[k].u.atom,'\n');
+ *pt = '\0'; ++pt;
+ for ( i=1; i<=cnt; ++i ) {
+ start = pt;
+ while ( *pt!='\n' && *pt!='\0' ) ++pt;
+ bdf->props[k+i].name = copy(bdf->props[k].name);
+ bdf->props[k+i].type = bdf->props[k].type;
+ bdf->props[k+i].u.atom = copyn(start,pt-start);
+ if ( *pt=='\n' ) ++pt;
+ }
+ pt = copy( bdf->props[k].u.atom );
+ free( bdf->props[k].u.atom );
+ bdf->props[k].u.atom = pt;
+return( k+cnt );
+}
+
+void ttf_bdf_read(FILE *ttf,struct ttfinfo *info) {
+ int strike_cnt, i,j,k;
+ long string_start;
+ struct bdfinfo { BDFFont *bdf; int cnt; } *bdfinfo;
+ BDFFont *bdf;
+
+ if ( info->bdf_start==0 )
+return;
+ fseek(ttf,info->bdf_start,SEEK_SET);
+ if ( getushort(ttf)!=1 )
+return;
+ strike_cnt = getushort(ttf);
+ string_start = getlong(ttf) + info->bdf_start;
+
+ bdfinfo = galloc(strike_cnt*sizeof(struct bdfinfo));
+ for ( i=0; i<strike_cnt; ++i ) {
+ int ppem, num_items;
+ ppem = getushort(ttf);
+ num_items = getushort(ttf);
+ for ( bdf=info->bitmaps; bdf!=NULL; bdf=bdf->next )
+ if ( bdf->pixelsize==ppem )
+ break;
+ bdfinfo[i].bdf = bdf;
+ bdfinfo[i].cnt = num_items;
+ }
+
+ for ( i=0; i<strike_cnt; ++i ) {
+ if ( (bdf = bdfinfo[i].bdf) ==NULL )
+ fseek(ttf,10*bdfinfo[i].cnt,SEEK_CUR);
+ else {
+ bdf->prop_cnt = bdfinfo[i].cnt;
+ bdf->props = galloc(bdf->prop_cnt*sizeof(BDFProperties));
+ for ( j=k=0; j<bdfinfo[i].cnt; ++j, ++k ) {
+ long name = getlong(ttf);
+ int type = getushort(ttf);
+ long value = getlong(ttf);
+ bdf->props[k].type = type;
+ bdf->props[k].name = getstring(ttf,string_start+name);
+ switch ( type&~prt_property ) {
+ case prt_int: case prt_uint:
+ bdf->props[k].u.val = value;
+ if ( strcmp(bdf->props[k].name,"FONT_ASCENT")==0 &&
+ value<=bdf->pixelsize ) {
+ bdf->ascent = value;
+ bdf->descent = bdf->pixelsize-value;
+ }
+ break;
+ case prt_string: case prt_atom:
+ bdf->props[k].u.str = getstring(ttf,string_start+value);
+ k = CheckForNewlines(bdf,k);
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+/* ************************************************************************** */
+/* ************************* The 'FFTM' table ************************* */
+/* ************************* Output ************************* */
+/* ************************************************************************** */
+
+/* FontForge timestamp table */
+/* Contains: */
+/* date of fontforge sources */
+/* date of font's (not file's) creation */
+/* date of font's modification */
+int ttf_fftm_dump(SplineFont *sf,struct alltabs *at) {
+ int32 results[2];
+ extern const time_t source_modtime;
+
+ at->fftmf = tmpfile();
+
+ putlong(at->fftmf,0x00000001); /* Version */
+
+ cvt_unix_to_1904(source_modtime,results);
+ putlong(at->fftmf,results[1]);
+ putlong(at->fftmf,results[0]);
+
+ cvt_unix_to_1904(sf->creationtime,results);
+ putlong(at->fftmf,results[1]);
+ putlong(at->fftmf,results[0]);
+
+ cvt_unix_to_1904(sf->modificationtime,results);
+ putlong(at->fftmf,results[1]);
+ putlong(at->fftmf,results[0]);
+
+ at->fftmlen = ftell(at->fftmf); /* had better be 7*4 */
+ /* It will never be misaligned */
+ if ( (at->fftmlen&1)!=0 )
+ putc(0,at->fftmf);
+ if ( ((at->fftmlen+1)&2)!=0 )
+ putshort(at->fftmf,0);
+return( true );
+}
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/unicoderange.h b/Build/source/libs/luafontforge/fontforge/fontforge/unicoderange.h
new file mode 100644
index 00000000000..48df4b7b1c7
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/unicoderange.h
@@ -0,0 +1,47 @@
+/* Copyright (C) 2006,2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+extern struct unicoderange {
+ char *name; /* The range's name */
+ int32 first, last, defined;
+ /* The first codepoint, last codepoint in the range */
+ /* and a codepoint which actually has a character */
+ /* associated with it */
+ uint8 display;
+ uint8 unassigned; /* No characters in this range are assigned */
+ int actual; /* Count of assigned codepoints in this range */
+} unicoderange[];
+
+struct rangeinfo {
+ struct unicoderange *range;
+ int cnt;
+ int actual;
+};
+
+enum ur_flags { ur_includeempty = 1, ur_sortbyname = 2, ur_sortbyunicode = 4 };
+extern struct rangeinfo *SFUnicodeRanges(SplineFont *sf, enum ur_flags flags);
+int unicoderange_cnt;
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/views.h b/Build/source/libs/luafontforge/fontforge/fontforge/views.h
new file mode 100644
index 00000000000..1b50d36de63
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/views.h
@@ -0,0 +1,1420 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _VIEWS_H
+#define _VIEWS_H
+
+#include "splinefont.h"
+
+#if defined(FONTFORGE_CONFIG_GTK)
+# include <gtk/gtk.h>
+# include <gdk/gdk.h>
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+# include <ggadget.h>
+#else
+# include <ggadget.h> /* Need GImage, gettext, etc. even if no UI */
+#endif
+
+struct gfi_data;
+struct contextchaindlg;
+struct statemachinedlg;
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+extern struct cvshows {
+ int showfore, showback, showgrids, showhhints, showvhints, showdhints;
+ int showpoints, showfilled;
+ int showrulers;
+ int showrounds; /* 0=>no, 1=>auto, 2=>always */
+ int showmdx, showmdy; /* minimum distances x,y */
+ int showhmetrics, showvmetrics; /* show advance width, baseline, etc. */
+ int markextrema;
+ int markpoi; /* Points of inflection */
+ int showblues, showfamilyblues;
+ int showanchor;
+ int showcpinfo;
+ int showtabs; /* with the names of former glyphs */
+ int showsidebearings;
+} CVShows;
+
+extern struct bvshows {
+ int showfore, showoutline, showgrid;
+ int lastpixelsize;
+} BVShows;
+#endif
+
+typedef struct drect {
+ real x, y;
+ real width, height;
+} DRect;
+
+typedef struct pressedOn {
+ int x,y; /* screen location of the press */
+ real cx, cy; /* Translated into character space */
+ SplinePoint *sp;
+ unsigned int nextcp: 1; /* Is the cursor on the "next" control point of */
+ unsigned int prevcp: 1; /* the spline point, or the "prev" control point */
+ unsigned int anysel: 1; /* did we hit anything? */
+/* unsigned int width: 1; / * we're moving the width rather than a spline */
+/* unsigned int vwidth: 1; / * we're moving the width rather than a spline */
+ unsigned int pressed: 1;
+ unsigned int rubberbanding: 1;
+ unsigned int rubberlining: 1;
+ unsigned int transany: 1;
+ unsigned int transanyrefs: 1;
+ Spline *spline;
+ real t; /* location on the spline where we pressed */
+ RefChar *ref;
+ SplinePointList *spl; /* containing spline or point */
+ ImageList *img;
+ AnchorPoint *ap;
+ float ex, ey; /* end of last rubber band rectangle */
+ BasePoint constrain; /* Point to which we constrain movement */
+ BasePoint cp; /* Original control point position */
+} PressedOn;
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+/* Note: These are ordered as they are displayed in the tools palette */
+enum cvtools { cvt_pointer, cvt_magnify,
+ cvt_freehand, cvt_hand,
+ cvt_curve, cvt_corner, cvt_tangent, cvt_pen,
+ cvt_knife, cvt_ruler,
+ cvt_scale, cvt_flip,
+ cvt_rotate, cvt_skew,
+ cvt_3d_rotate, cvt_perspective,
+ cvt_rect, cvt_poly,
+ cvt_elipse, cvt_star,
+ cvt_minify, cvt_max=cvt_minify,
+ cvt_none = -1};
+#endif
+enum bvtools { bvt_pointer, bvt_magnify,
+ bvt_pencil, bvt_line,
+ bvt_shift, bvt_hand,
+ bvt_minify, bvt_eyedropper, bvt_max=bvt_eyedropper,
+ bvt_setwidth, bvt_setvwidth,
+ bvt_rect, bvt_filledrect,
+ bvt_elipse, bvt_filledelipse,
+ bvt_max2 = bvt_filledelipse,
+ bvt_none = -1,
+ bvt_fliph=0, bvt_flipv, bvt_rotate90cw, bvt_rotate90ccw, bvt_rotate180, bvt_skew, bvt_transmove };
+enum drawmode { dm_grid, dm_back, dm_fore, dm_max };
+
+typedef struct bvtfunc {
+ enum bvtools func;
+ int x,y; /* used by skew and move */
+} BVTFunc;
+
+struct freetype_raster {
+ int16 rows, cols;
+ int16 as, lb;
+ int16 bytes_per_row;
+ int16 num_greys;
+ uint8 *bitmap;
+};
+
+enum byte_types { bt_instr, bt_cnt, bt_byte, bt_wordhi, bt_wordlo, bt_impliedreturn };
+struct instrdata {
+ uint8 *instrs;
+ int instr_cnt, max;
+ uint8 *bts;
+ unsigned int changed: 1;
+ unsigned int in_composit: 1;
+ SplineFont *sf;
+ SplineChar *sc;
+ uint32 tag;
+ struct instrdlg *id;
+ struct instrdata *next;
+};
+
+struct instrinfo {
+#if defined(FONTFORGE_CONFIG_GTK)
+ GtkWidget *v;
+ GtkWidget *vsb;
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+ GWindow v;
+ GGadget *vsb;
+#else
+ int v;
+#endif
+ int16 sbw;
+ int16 vheight, vwidth;
+ int16 lheight,lpos;
+ int16 lstopped;
+ int16 as, fh;
+ struct instrdata *instrdata;
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ GFont *gfont;
+#endif
+ int isel_pos;
+ unsigned int showaddr: 1;
+ unsigned int showhex: 1;
+ unsigned int mousedown: 1;
+ void *userdata;
+ void (*selection_callback)(struct instrinfo *,int ip);
+ int (*bpcheck)(struct instrinfo *,int ip);
+#if defined(FONTFORGE_CONFIG_GTK)
+ int (*handle_char)(struct instrinfo *,GdkEvent *e);
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+ int (*handle_char)(struct instrinfo *,GEvent *e);
+#endif
+};
+
+enum debug_wins { dw_registers=0x1, dw_stack=0x2, dw_storage=0x4, dw_points=0x8,
+ dw_cvt=0x10, dw_raster=0x20, dw_gloss=0x40 };
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+typedef struct debugview {
+ struct debugger_context *dc; /* Local to freetype.c */
+#if defined(FONTFORGE_CONFIG_GTK)
+ GtkWidget *dv, *v;
+ GtkWidget *regs, *stack, *storage, *points, *cvt, *raster, *gloss; /* Order matters */
+ GtkWidget *points_v;
+ GtkWidget *cvtsb, *pts_vsb, *glosssb, *storagesb, *regsb, *stacksb;
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+ GWindow dv, v;
+ /* Windows for twilight points, cvt, registers, stack, storage, stack gloss */
+ GWindow regs, stack, storage, points, cvt, raster, gloss; /* order matters */
+ GWindow points_v;
+ GGadget *cvtsb;
+ GGadget *pts_vsb;
+ GGadget *glosssb;
+ GGadget *storagesb;
+ GGadget *regsb;
+ GGadget *stacksb;
+#endif
+ struct instrdata id;
+ struct instrinfo ii;
+ int dwidth, toph;
+ struct charview *cv;
+ double scale;
+ int pts_head, cvt_offtop, gloss_offtop, storage_offtop, stack_offtop, reg_offtop;
+ int points_offtop;
+
+ int codeSize;
+ uint8 initialbytes[4];
+ struct reflist { RefChar *ref; struct reflist *parent; } *active_refs;
+ int last_npoints;
+} DebugView;
+
+enum dv_coderange { cr_none=0, cr_fpgm, cr_prep, cr_glyph }; /* cleverly chosen to match ttobjs.h */
+#endif
+
+#if !defined( FONTFORGE_CONFIG_NO_WINDOWING_UI ) || defined(_DEFINE_SEARCHVIEW_)
+#define FORMER_MAX 10
+
+typedef struct charview {
+ SplineChar *sc;
+ unsigned int showback:1;
+ unsigned int showfore:1;
+ unsigned int showgrids:1;
+ unsigned int showhhints:1;
+ unsigned int showvhints:1;
+ unsigned int showdhints:1;
+ unsigned int showpoints:1;
+ unsigned int showfilled:1;
+ unsigned int showrulers:1;
+ unsigned int showrounds:2; /* 0=>no, 1=>auto, 2=>always */
+ unsigned int showmdx:1;
+ unsigned int showmdy:1;
+ unsigned int showhmetrics:1;
+ unsigned int showvmetrics:1;
+ unsigned int showblues:1; /* 16 */
+ unsigned int showfamilyblues:1;
+ unsigned int showanchor:1;
+ unsigned int showpointnumbers:1;
+ unsigned int markextrema:1;
+ unsigned int markpoi:1;
+ unsigned int needsrasterize:1; /* Rasterization (of fill or fontview) needed on mouse up */
+ unsigned int recentchange:1; /* a change happened in the grids or background. don't need to rasterize */
+ unsigned int drawmode:2;
+ unsigned int info_within: 1; /* cursor is within main window */
+ unsigned int back_img_out_of_date: 1; /* Force redraw of back image pixmap */
+ unsigned int cntrldown:1;
+ unsigned int joinvalid:1;
+ unsigned int widthsel:1;
+ unsigned int vwidthsel:1;
+ unsigned int inactive:1; /* When in a search view */
+ unsigned int show_ft_results: 1; /* 32 */
+ unsigned int coderange: 2; /* For the debugger */
+ unsigned int autonomous_ruler_w: 1;
+ unsigned int showcpinfo: 1;
+ unsigned int showtabs: 1;
+ unsigned int showsidebearings: 1;
+ Layer *layerheads[dm_max];
+ real scale;
+#if defined(FONTFORGE_CONFIG_GTK)
+ GtkWidget *gw, *v;
+ GtkWidget *vsb, *hsb, *mb, *tabs;
+ PangoFont *small, *normal;
+ GtkWindow *icon; /* Pixmap? */
+ guint pressed; /* glib timer id */
+ GtkWindow backimgs; /* Pixmap? */
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+ GWindow gw, v;
+ GGadget *vsb, *hsb, *mb, *tabs;
+ GFont *small, *normal;
+ GWindow icon;
+ GWindow ruler_w;
+ GFont *rfont;
+ GTimer *pressed;
+ GWindow backimgs;
+ GIC *gic;
+#else
+ void *gw, *v;
+#endif
+ int width, height;
+ int xoff, yoff;
+ int mbh, infoh, rulerh;
+ int16 sas, sfh, nas, nfh;
+ BasePoint info;
+ SplinePoint *info_sp;
+#if defined(FONTFORGE_CONFIG_GTK)
+ GdkPoint e; /* mouse location */
+ GdkPoint olde;
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+ GPoint e; /* mouse location */
+ GPoint olde;
+#endif
+ BasePoint last_c;
+ BDFChar *filled;
+#ifdef FONTFORGE_CONFIG_GDRAW
+ GImage gi;
+#endif
+ struct charview *next;
+ struct fontview *fv;
+ int enc;
+ EncMap *map_of_enc; /* Only use for comparison against fontview's map to see if our enc be valid */
+ /* Will not be updated when fontview is reencoded */
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ PressedOn p;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ SplinePoint *lastselpt;
+ /*GWindow tools, layers;*/
+ int8 b1_tool, cb1_tool, b2_tool, cb2_tool; /* Button 3 does a popup */
+ int8 s1_tool, s2_tool, er_tool; /* Bindings for wacom stylus and eraser */
+ int8 showing_tool, pressed_tool, pressed_display, had_control, active_tool;
+ SplinePointList *active_spl;
+ SplinePoint *active_sp;
+ IPoint handscroll_base;
+ uint16 rfh, ras;
+ BasePoint lastknife;
+ struct freehand {
+ struct tracedata *head, *last; /* for the freehand tool */
+ SplinePointList *current_trace;
+ int ignore_wobble; /* Ignore wiggles smaller than this */
+ int skip_cnt;
+ } freehand;
+ enum expandedge { ee_none, ee_nw, ee_up, ee_ne, ee_right, ee_se, ee_down,
+ ee_sw, ee_left, ee_max } expandedge;
+ BasePoint expandorigin;
+ real expandwidth, expandheight;
+ SplinePointList *active_shape;
+ SplinePoint joinpos;
+ SplineChar *template1, *template2;
+#if HANYANG
+ struct jamodisplay *jamodisplay;
+#endif
+ real oldwidth, oldvwidth;
+#if _ModKeysAutoRepeat
+# if defined(FONTFORGE_CONFIG_GTK)
+# elif defined(FONTFORGE_CONFIG_GDRAW)
+ GTimer *autorpt;
+ int keysym, oldstate;
+ int oldkeyx, oldkeyy;
+ GWindow oldkeyw;
+# endif
+#endif
+ struct searchview *searcher; /* The sv within which this view is embedded (if it is) */
+ PST *lcarets;
+ int16 nearcaret;
+ /* freetype results display */
+ int16 ft_dpi, ft_ppem, ft_gridfitwidth, ft_depth;
+ real ft_pointsize;
+ SplineSet *gridfit;
+ struct freetype_raster *raster, *oldraster;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ DebugView *dv;
+#endif
+ uint32 mmvisible;
+ char *former_names[FORMER_MAX];
+ int former_cnt;
+ AnchorPoint *apmine, *apmatch;
+ SplineChar *apsc;
+} CharView;
+#endif
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+typedef struct bitmapview {
+ BDFChar *bc;
+ BDFFont *bdf;
+ struct fontview *fv;
+ EncMap *map_of_enc;
+ int enc;
+#if defined(FONTFORGE_CONFIG_GTK)
+ GtkWidget *v;
+ GtkWidget *gw;
+ GtkWidget *vsb, *hsb, *mb;
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+ GWindow gw, v;
+ GGadget *vsb, *hsb, *mb;
+ GGadget *recalc;
+ GFont *small;
+#endif
+ int xoff, yoff;
+ int width, height;
+ int infoh, mbh;
+ int scale;
+ real scscale;
+ struct bitmapview *next;
+ unsigned int showfore:1;
+ unsigned int showoutline:1;
+ unsigned int showgrid:1;
+ unsigned int cntrldown:1;
+ unsigned int recentchange:1;
+ unsigned int clearing:1;
+ unsigned int shades_hidden:1;
+ unsigned int shades_down:1;
+ /*GWindow tools, layers;*/
+ int8 b1_tool, cb1_tool, b2_tool, cb2_tool; /* Button 3 does a popup */
+ int8 s1_tool, s2_tool, er_tool; /* Bindings for wacom stylus and eraser */
+ int8 showing_tool, pressed_tool, pressed_display, had_control, active_tool;
+ int pressed_x, pressed_y;
+ int info_x, info_y;
+ int event_x, event_y;
+ int16 sas, sfh;
+#if _ModKeysAutoRepeat
+# if defined(FONTFORGE_CONFIG_GTK)
+# elif defined(FONTFORGE_CONFIG_GDRAW)
+ GTimer *autorpt;
+ int keysym, oldstate;
+# endif
+#endif
+ int color; /* for greyscale fonts (between 0,255) */
+ int color_under_cursor;
+} BitmapView;
+
+struct aplist { AnchorPoint *ap; int connected_to, selected; struct aplist *next; };
+
+typedef struct metricsview {
+ struct fontview *fv;
+ SplineFont *sf;
+ int pixelsize;
+ BDFFont *bdf; /* We can also see metric info on a bitmap font */
+ BDFFont *show; /* Or the rasterized version of the outline font */
+#if defined(FONTFORGE_CONFIG_GTK)
+ GtkWidget *gw;
+ PangoFont *font;
+ GtkWidget *hsb, *vsb, *mb, *text, *subtable_list;
+ GtkWidget *namelab, *widthlab, *lbearinglab, *rbearinglab, *kernlab;
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+ GWindow gw;
+ GFont *font;
+ GGadget *hsb, *vsb, *mb, *text, *script, *features, *subtable_list;
+ GGadget *namelab, *widthlab, *lbearinglab, *rbearinglab, *kernlab;
+#endif
+ int16 xstart;
+ int16 width, height, dwidth;
+ int16 mbh,sbh;
+ int16 topend; /* y value of the end of the region containing the text field */
+ int16 displayend; /* y value of the end of the region showing filled characters */
+ int16 fh, as;
+ int16 cmax, clen;
+ SplineChar **chars; /* Character input stream */
+ struct opentype_str *glyphs;/* after going through the various gsub/gpos transformations */
+ struct metricchar { /* One for each glyph above */
+ int16 dx, dwidth; /* position and width of the displayed char */
+ int16 dy, dheight; /* displayed info for vertical metrics */
+ int xoff, yoff;
+ int16 mx, mwidth; /* position and width of the text underneath */
+ int16 kernafter;
+ unsigned int selected: 1;
+#if defined(FONTFORGE_CONFIG_GTK)
+ GtkWidget *width, *lbearing, *rbearing, *kern, *name;
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+ GGadget *width, *lbearing, *rbearing, *kern, *name;
+#endif
+ } *perchar;
+ SplineChar **sstr; /* Character input stream */
+ int16 mwidth, mbase;
+ int16 glyphcnt, max;
+ int16 pressed_x, pressed_y;
+ int16 activeoff;
+ int xoff, coff, yoff;
+ struct metricsview *next;
+ unsigned int right_to_left: 1;
+ unsigned int pressed: 1;
+ unsigned int pressedwidth: 1;
+ unsigned int pressedkern: 1;
+ unsigned int showgrid: 1;
+ unsigned int antialias: 1;
+ unsigned int vertical: 1;
+ struct aplist *pressed_apl;
+ int xp, yp, ap_owner;
+ BasePoint ap_start;
+ int cursor;
+ int scale_index;
+ struct lookup_subtable *cur_subtable;
+ GTextInfo *scriptlangs;
+} MetricsView;
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+enum fv_metrics { fvm_baseline=1, fvm_origin=2, fvm_advanceat=4, fvm_advanceto=8 };
+typedef struct fontview {
+ EncMap *map;
+ EncMap *normal; /* If this is not NULL then we have a compacted encoding in map, and this is the original */
+ SplineFont *sf;
+ BDFFont *show, *filled;
+#if defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
+ void *gw, *v;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ GtkWidget *gw, *v;
+ PangoFont **fontset;
+ GtkWidget *vsb, *mb;
+ guint pressed; /* gtk timer id */
+ GdkGC *gc;
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+ GWindow gw, v;
+ GFont **fontset;
+ GGadget *vsb, *mb;
+ GTimer *pressed;
+ GTimer *resize;
+ GEvent resize_event;
+ GIC *gic;
+#endif
+ int width, height; /* of v */
+ int16 infoh,mbh;
+ int16 lab_height, lab_as;
+ int16 colcnt, rowcnt; /* of display window */
+ int32 rowoff, rowltot; /* Can be really big in full unicode */
+ int16 cbw,cbh; /* width/height of a character box */
+ struct fontview *next; /* Next on list of open fontviews */
+ struct fontview *nextsame; /* Next fv looking at this font */
+ int pressed_pos, end_pos;
+ uint8 *selected;
+ unsigned int antialias:1;
+ unsigned int bbsized:1; /* displayed bitmap should be scaled by bounding box rather than emsize */
+ unsigned int wasonlybitmaps:1;
+ unsigned int refstate: 3; /* 0x1 => paste orig of all non exist refs, 0x2=>don't, 0x3 => don't warn about non-exist refs with no source font */
+ unsigned int touched: 1;
+ unsigned int showhmetrics: 4;
+ unsigned int showvmetrics: 4;
+ unsigned int drag_and_drop: 1;
+ unsigned int has_dd_no_cursor: 1;
+ unsigned int any_dd_events_sent: 1;
+ unsigned int resize_expected: 1;
+ /* Some window managers do not honour my resize requests (if window is*/
+ /* maximized for example), but we depend on the resize request to */
+ /* fix up the window. We do get a configure notify, but the window */
+ /* stays the same size, so kludge things */
+ unsigned int glyphlabel: 2;
+ int16 magnify;
+ int16 user_requested_magnify;
+ SplineFont *cidmaster;
+ int32 *mapping; /* an array mapping grid cells (0=upper left) to font indeces (enc, 0=NUL) */
+ /* So the default array would contain NUL, ^A, ^B, ... */
+ int mapcnt; /* Number of chars in the current group (mapping) */
+ struct dictionary *fontvars; /* Scripting */
+ struct searchview *sv;
+ SplineChar *sc_near_top;
+ int sel_index;
+ struct lookup_subtable *cur_subtable;
+#ifndef _NO_PYTHON
+ void *python_fv_object;
+ void *python_data;
+#endif
+} FontView;
+
+typedef struct findsel {
+#if defined(FONTFORGE_CONFIG_GTK)
+ GdkEvent *e;
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+ GEvent *e;
+#endif
+ real fudge; /* One pixel fudge factor */
+ real xl,xh, yl, yh; /* One pixel fudge factor */
+ unsigned int select_controls: 1; /* notice control points */
+ unsigned int seek_controls: 1; /* notice control points before base points */
+ unsigned int all_controls: 1; /* notice control points even if the base points aren't selected (in truetype point numbering mode where all cps are visible) */
+ real scale;
+ PressedOn *p;
+} FindSel;
+
+#if !defined( FONTFORGE_CONFIG_NO_WINDOWING_UI ) || defined(_DEFINE_SEARCHVIEW_)
+typedef struct searchview {
+ FontView dummy_fv;
+ SplineFont dummy_sf;
+ SplineChar sc_srch, sc_rpl;
+ SplineChar *chars[2];
+ EncMap dummy_map;
+ int32 map[2], backmap[2];
+ uint8 sel[2];
+ CharView cv_srch, cv_rpl;
+ CharView *lastcv;
+/* ****** */
+#if defined(FONTFORGE_CONFIG_GTK)
+ GtkWidget *gw;
+ GtkWidget *mb;
+ PangoFont *plain, *bold;
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+ GWindow gw;
+ GGadget *mb;
+ GFont *plain, *bold;
+#else
+ void *gw;
+#endif
+ int mbh;
+ int fh, as;
+ int rpl_x, cv_y;
+ int cv_width, cv_height;
+ short button_height, button_width;
+/* ****** */
+ FontView *fv;
+ SplineChar *curchar;
+ SplineSet *path, *revpath, *replacepath, *revreplace;
+ int pointcnt, rpointcnt;
+ real fudge;
+ real fudge_percent; /* a value of .05 here represents 5% (we don't store the integer) */
+ unsigned int tryreverse: 1;
+ unsigned int tryflips: 1;
+ unsigned int tryrotate: 1;
+ unsigned int tryscale: 1;
+ unsigned int onlyselected: 1;
+ unsigned int subpatternsearch: 1;
+ unsigned int doreplace: 1;
+ unsigned int replaceall: 1;
+ unsigned int findall: 1;
+ unsigned int searchback: 1;
+ unsigned int wrap: 1;
+ unsigned int wasreversed: 1;
+ unsigned int isvisible: 1;
+ unsigned int findenabled: 1;
+ unsigned int rplallenabled: 1;
+ unsigned int rplenabled: 1;
+ unsigned int showsfindnext: 1;
+ unsigned int replacewithref: 1;
+ SplineSet *matched_spl;
+ SplinePoint *matched_sp, *last_sp;
+ real matched_rot, matched_scale;
+ real matched_x, matched_y;
+ double matched_co, matched_si; /* Precomputed sin, cos */
+ enum flipset { flip_none = 0, flip_x, flip_y, flip_xy } matched_flip;
+#ifdef _HAS_LONGLONG
+ unsigned long long matched_refs; /* Bit map of which refs in the char were matched */
+ unsigned long long matched_ss; /* Bit map of which splines in the char were matched */
+ /* In multi-path mode */
+ unsigned long long matched_ss_start;/* Bit map of which splines we tried to start matches with */
+#else
+ unsigned long matched_refs;
+ unsigned long matched_ss;
+ unsigned long matched_ss_start;
+#endif
+} SearchView;
+#endif
+
+struct lkdata {
+ int cnt, max;
+ int off_top, off_left;
+ struct lkinfo {
+ OTLookup *lookup;
+ unsigned int open: 1;
+ unsigned int deleted: 1;
+ unsigned int new: 1;
+ unsigned int selected: 1;
+ int16 subtable_cnt, subtable_max;
+ struct lksubinfo {
+ struct lookup_subtable *subtable;
+ unsigned int deleted: 1;
+ unsigned int new: 1;
+ unsigned int selected: 1;
+ } *subtables;
+ } *all;
+};
+
+struct gfi_data {
+ SplineFont *sf;
+ GWindow gw;
+ int tn_active;
+ int private_aspect, ttfv_aspect, tn_aspect, tx_aspect, unicode_aspect;
+ int old_sel, old_aspect, old_lang, old_strid;
+ int ttf_set, names_set, tex_set;
+ struct psdict *private;
+ int langlocalecode; /* MS code for the current locale */
+ unsigned int family_untitled: 1;
+ unsigned int human_untitled: 1;
+ unsigned int done: 1;
+ unsigned int mpdone: 1;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ struct anchor_shows { CharView *cv; SplineChar *sc; int restart; } anchor_shows[2];
+#endif
+ struct texdata texdata;
+ struct contextchaindlg *ccd;
+ struct statemachinedlg *smd;
+/* For GDEF Mark Attachment Class -- used in lookup flags */
+/* As usual, class 0 is unused */
+ int mark_class_cnt;
+ char **mark_classes; /* glyph name list */
+ char **mark_class_names; /* used within ff */
+ struct markclassdlg *mcd;
+ GFont *font;
+ int as, fh;
+ struct lkdata tables[2];
+ int lkwidth, lkheight;
+};
+
+enum widthtype { wt_width, wt_lbearing, wt_rbearing, wt_vwidth };
+
+enum fvtrans_flags { fvt_dobackground=1, fvt_round_to_int=2,
+ fvt_dontsetwidth=4, fvt_dontmovewidth=8, fvt_scalekernclasses=0x10,
+ fvt_scalepstpos=0x20, fvt_dogrid=0x40, fvt_partialreftrans=0x80 };
+
+enum origins { or_zero, or_center, or_lastpress, or_value, or_undefined };
+struct pov_data {
+ enum origins xorigin, yorigin;
+ double x, y, z;
+ double direction; /* Direction of gaze projected into xy plane */
+ double tilt; /* Angle which drawing plane is tilted with respect to projection plane */
+ double d; /* Distance to projection plane */
+ double sintilt; /* Used internally */
+};
+
+extern FontView *_FontViewCreate(SplineFont *sf);
+extern FontView *FontViewCreate(SplineFont *sf);
+extern void SplineFontSetUnChanged(SplineFont *sf);
+extern void FontViewFree(FontView *fv);
+extern void FVToggleCharChanged(SplineChar *sc);
+extern void FVMarkHintsOutOfDate(SplineChar *sc);
+extern void FVRefreshChar(FontView *fv,int gid);
+extern int _FVMenuSave(FontView *fv);
+extern int _FVMenuSaveAs(FontView *fv);
+extern int _FVMenuGenerate(FontView *fv,int family);
+extern void _FVCloseWindows(FontView *fv);
+extern void SCClearBackground(SplineChar *sc);
+extern char *GetPostscriptFontName(char *defdir,int mult);
+extern void MergeKernInfo(SplineFont *sf,EncMap *map);
+extern void _FVSimplify(FontView *fv,struct simplifyinfo *smpl);
+#ifdef FONTFORGE_CONFIG_WRITE_PFM
+extern int WritePfmFile(char *filename,SplineFont *sf, int type0, EncMap *map);
+#endif
+extern int GenerateScript(SplineFont *sf,char *filename,char *bitmaptype,
+ int fmflags,int res, char *subfontdirectory,struct sflist *sfs,
+ EncMap *map,NameList *rename_to);
+extern int SFGenerateFont(SplineFont *sf,int family,EncMap *map);
+
+extern int SFScaleToEm(SplineFont *sf, int ascent, int descent);
+extern void TransHints(StemInfo *stem,real mul1, real off1, real mul2, real off2, int round_to_int );
+extern void VrTrans(struct vr *vr,real transform[6]);
+extern void FVTransFunc(void *_fv,real transform[6],int otype, BVTFunc *bvts,
+ enum fvtrans_flags );
+extern void FVTrans(FontView *fv,SplineChar *sc,real transform[6],uint8 *sel,
+ enum fvtrans_flags);
+extern int SFNLTrans(FontView *fv,char *x_expr,char *y_expr);
+extern void NonLinearDlg(FontView *fv,struct charview *cv);
+extern void FVPointOfView(FontView *fv,struct pov_data *);
+extern void FVBuildAccent(FontView *fv,int onlyaccents);
+extern void FVBuildDuplicate(FontView *fv);
+extern void FVChangeChar(FontView *fv,int encoding);
+extern void SCClearContents(SplineChar *sc);
+extern void SCClearAll(SplineChar *sc);
+extern void BCClearAll(BDFChar *bc);
+extern void UnlinkThisReference(FontView *fv,SplineChar *sc);
+extern void FVFakeMenus(FontView *fv,int cmd);
+extern void FVMetricsCenter(FontView *fv,int docenter);
+extern void MergeFont(FontView *fv,SplineFont *other);
+extern void FVMergeFonts(FontView *fv);
+extern SplineFont *InterpolateFont(SplineFont *base, SplineFont *other, real amount, Encoding *enc);
+extern void FVInterpolateFonts(FontView *fv);
+extern void FVRevert(FontView *fv);
+extern void FVRevertBackup(FontView *fv);
+
+extern void FVDeselectAll(FontView *fv);
+
+extern void FVAutoKern(FontView *fv);
+extern void FVAutoWidth(FontView *fv);
+extern void FVRemoveKerns(FontView *fv);
+extern void FVRemoveVKerns(FontView *fv);
+extern void FVVKernFromHKern(FontView *fv);
+extern int AutoWidthScript(FontView *fv,int spacing);
+extern int AutoKernScript(FontView *fv,int spacing, int threshold,
+ struct lookup_subtable *sub, char *kernfile);
+
+enum fvformats { fv_bdf, fv_ttf, fv_pk, fv_pcf, fv_mac, fv_win, fv_palm,
+ fv_image, fv_imgtemplate, fv_eps, fv_epstemplate,
+ fv_svg, fv_svgtemplate,
+ fv_glif, fv_gliftemplate,
+ fv_fig };
+extern int HasSVG(void);
+extern void SCImportSVG(SplineChar *sc,int layer,char *path,char *memory, int memlen,int doclear);
+extern int HasUFO(void);
+extern void SCImportGlif(SplineChar *sc,int layer,char *path,char *memory, int memlen,int doclear);
+extern void SCImportPS(SplineChar *sc,int layer,char *path,int doclear, int flags);
+extern void SCImportPSFile(SplineChar *sc,int layer,FILE *ps,int doclear,int flags);
+extern void SCAddScaleImage(SplineChar *sc,GImage *image,int doclear,int layer);
+extern void SCInsertImage(SplineChar *sc,GImage *image,real scale,real yoff, real xoff, int layer);
+extern int FVImportImages(FontView *fv,char *path,int isimage,int toback,int flags);
+extern int FVImportImageTemplate(FontView *fv,char *path,int isimage,int toback,int flags);
+
+extern int _ExportPDF(FILE *pdf,SplineChar *sc);
+extern int _ExportEPS(FILE *eps,SplineChar *sc,int gen_preview);
+extern int _ExportSVG(FILE *svg,SplineChar *sc);
+extern int _ExportGlif(FILE *glif,SplineChar *sc);
+extern int ExportImage(char *filename,SplineChar *sc, int format, int pixelsize, int bitsperpixel);
+extern void ScriptExport(SplineFont *sf, BDFFont *bdf, int format, int gid,
+ char *format_spec, EncMap *map);
+
+extern void BCFlattenFloat(BDFChar *bc);
+extern void BCTrans(BDFFont *bdf,BDFChar *bc,BVTFunc *bvts,FontView *fv );
+
+extern enum undotype CopyUndoType(void);
+extern int CopyContainsSomething(void);
+extern int CopyContainsBitmap(void);
+extern const Undoes *CopyBufferGet(void);
+extern RefChar *CopyContainsRef(SplineFont *);
+extern char **CopyGetPosSubData(enum possub_type *type,SplineFont **copied_from,
+ int pst_depth);
+extern void CopyReference(SplineChar *sc);
+extern void SCCopyLookupData(SplineChar *sc);
+extern void PasteRemoveSFAnchors(SplineFont *);
+extern void PasteAnchorClassMerge(SplineFont *sf,AnchorClass *into,AnchorClass *from);
+extern void PasteRemoveAnchorClass(SplineFont *sf,AnchorClass *dying);
+extern void ClipboardClear(void);
+extern SplineSet *ClipBoardToSplineSet(void);
+extern void BCCopySelected(BDFChar *bc,int pixelsize,int depth);
+extern void PasteToBC(BDFChar *bc,int pixelsize,int depth,FontView *fv);
+extern void FVCopyWidth(FontView *fv,enum undotype ut);
+extern void FVCopyAnchors(FontView *fv);
+enum fvcopy_type { ct_fullcopy, ct_reference, ct_lookups, ct_unlinkrefs };
+extern void FVCopy(FontView *fv, enum fvcopy_type copytype);
+extern void PasteIntoFV(FontView *fv, int pasteinto, real trans[6]);
+
+extern void SCUpdateAll(SplineChar *sc);
+extern void SCOutOfDateBackground(SplineChar *sc);
+extern void SCClearSelPt(SplineChar *sc);
+extern void _SCCharChangedUpdate(SplineChar *sc,int changed);
+extern void SCCharChangedUpdate(SplineChar *sc);
+extern void SCHintsChanged(SplineChar *sc);
+extern void SCSynchronizeWidth(SplineChar *sc,real newwidth, real oldwidth,FontView *fv);
+extern RefChar *HasUseMyMetrics(SplineChar *sc);
+extern void SCSynchronizeLBearing(SplineChar *sc,real off);
+extern void BackgroundImageTransform(SplineChar *sc, ImageList *img,real transform[6]);
+extern void SCClearRounds(SplineChar *sc);
+extern void SCMoreLayers(SplineChar *,Layer *old);
+extern void SCLayersChange(SplineChar *sc);
+extern void SFLayerChange(SplineFont *sf);
+extern void SCTile(SplineChar *sc);
+
+extern void ExecuteScriptFile(FontView *fv, char *filename);
+extern void DictionaryFree(struct dictionary *dica);
+
+extern void BCCharChangedUpdate(BDFChar *bc);
+extern BDFFloat *BDFFloatCreate(BDFChar *bc,int xmin,int xmax,int ymin,int ymax, int clear);
+extern BDFFloat *BDFFloatCopy(BDFFloat *sel);
+extern BDFFloat *BDFFloatConvert(BDFFloat *sel,int newdepth, int olddepth);
+extern void BDFFloatFree(BDFFloat *sel);
+
+extern void SCDoRedo(SplineChar *sc,int layer);
+extern void SCDoUndo(SplineChar *sc,int layer);
+extern void SCCopyWidth(SplineChar *sc,enum undotype);
+extern void SCAppendPosSub(SplineChar *sc,enum possub_type type, char **d,SplineFont *copied_from);
+#if !defined( FONTFORGE_CONFIG_NO_WINDOWING_UI ) || defined(_DEFINE_SEARCHVIEW_)
+extern void PasteToCV(CharView *cv);
+#endif
+
+extern void MDReplace(MinimumDistance *md,SplineSet *old,SplineSet *rpl);
+
+extern void _SCAutoTrace(SplineChar *sc, char **args);
+extern char **AutoTraceArgs(int ask);
+extern void FVAutoTrace(FontView *fv,int ask);
+extern char *FindAutoTraceName(void);
+extern char *FindMFName(void);
+extern char *ProgramExists(char *prog,char *buffer);
+extern void *GetAutoTraceArgs(void);
+extern void SetAutoTraceArgs(void *a);
+extern void MfArgsInit(void);
+
+extern void DumpPfaEditEncodings(void);
+extern void ParseEncodingFile(char *filename);
+extern void LoadPfaEditEncodings(void);
+
+extern void SCStroke(SplineChar *sc);
+extern void FVOutline(FontView *fv, real width);
+extern void FVInline(FontView *fv, real width, real inset);
+extern void FVShadow(FontView *fv,real angle, real outline_width,
+ real shadow_length,int wireframe);
+
+extern void SetDefaults(void);
+extern char *getPfaEditShareDir(void);
+extern void LoadPrefs(void);
+extern void PrefDefaultEncoding(void);
+extern void _SavePrefs(void);
+extern void SavePrefs(void);
+extern void PfaEditSetFallback(void);
+extern void RecentFilesRemember(char *filename);
+extern int GetPrefs(char *name,Val *val); /* for scripting */
+extern int SetPrefs(char *name,Val *val1, Val *val2); /* for scripting */
+
+extern int FVImportBDF(FontView *fv, char *filename,int ispk, int toback);
+extern int FVImportMult(FontView *fv, char *filename,int toback,int bf);
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+struct debugger_context;
+extern void DebuggerTerminate(struct debugger_context *dc);
+extern void DebuggerReset(struct debugger_context *dc,real pointsize,int dpi,int dbg_fpgm, int is_bitmap);
+extern struct debugger_context *DebuggerCreate(SplineChar *sc,real pointsize,int dpi,int dbg_fpgm, int is_bitmap);
+enum debug_gotype { dgt_continue, dgt_step, dgt_next, dgt_stepout };
+extern void DebuggerGo(struct debugger_context *dc,enum debug_gotype,DebugView *dv);
+extern struct TT_ExecContextRec_ *DebuggerGetEContext(struct debugger_context *dc);
+extern void DebuggerToggleBp(struct debugger_context *dc,int range,int ip);
+extern int DebuggerBpCheck(struct debugger_context *dc,int range,int ip);
+extern void DebuggerSetWatches(struct debugger_context *dc,int n, uint8 *w);
+extern uint8 *DebuggerGetWatches(struct debugger_context *dc, int *n);
+extern void DebuggerSetWatchStores(struct debugger_context *dc,int n, uint8 *w);
+extern uint8 *DebuggerGetWatchStores(struct debugger_context *dc, int *n);
+extern int DebuggerIsStorageSet(struct debugger_context *dc, int index);
+extern void DebuggerSetWatchCvts(struct debugger_context *dc,int n, uint8 *w);
+extern uint8 *DebuggerGetWatchCvts(struct debugger_context *dc, int *n);
+extern int DebuggingFpgm(struct debugger_context *dc);
+#endif
+
+extern int BitmapControl(FontView *fv,int32 *sizes,int isavail,int rasterize);
+
+#if defined(FONTFORGE_CONFIG_GTK)
+extern void ScriptPrint(FontView *fv,int type,int32 *pointsizes,char *samplefile,
+ char *sample, char *outputfile);
+extern char *PrtBuildDef( SplineFont *sf, int istwobyte );
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+extern void ScriptPrint(FontView *fv,int type,int32 *pointsizes,char *samplefile,
+ unichar_t *sample, char *outputfile);
+extern unichar_t *PrtBuildDef( SplineFont *sf, int istwobyte );
+#endif
+
+extern char *Kern2Text(SplineChar *other,KernPair *kp,int isv);
+extern char *PST2Text(PST *pst,SplineFont *sf);
+
+
+extern void FVStrokeItScript(FontView *fv, StrokeInfo *si);
+
+extern int FVParseSelectByPST(FontView *fv,struct lookup_subtable *sub,
+ int search_type);
+#if defined(FONTFORGE_CONFIG_GTK)
+extern void DropChars2Text(GdkWindow gw, GtkWidget *glyphs,GdkEvent *event);
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+extern void DropChars2Text(GWindow gw, GGadget *glyphs,GEvent *event);
+#endif
+
+extern void FVSetWidthScript(FontView *fv,enum widthtype wtype,int val,int incr);
+
+extern void FVReplaceOutlineWithReference( FontView *fv, double fudge );
+
+extern void skewselect(BVTFunc *bvtf,real t);
+
+extern int UserFeaturesDiffer(void);
+
+extern int SLICount(SplineFont *sf);
+#if defined(FONTFORGE_CONFIG_GTK)
+extern char *ClassName(const char *name,uint32 feature_tag,
+ uint16 flags, int script_lang_index, int merge_with, int act_type,
+ int macfeature,SplineFont *sf);
+extern char *DecomposeClassName(const char *clsnm, char **name,
+ uint32 *feature_tag, int *macfeature,
+ uint16 *flags, uint16 *script_lang_index,int *merge_with,int *act_type,
+ SplineFont *sf);
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+extern unichar_t *ClassName(const char *name,uint32 feature_tag,
+ uint16 flags, int script_lang_index, int merge_with, int act_type,
+ int macfeature,SplineFont *sf);
+extern unichar_t *DecomposeClassName(const unichar_t *clsnm, unichar_t **name,
+ uint32 *feature_tag, int *macfeature,
+ uint16 *flags, uint16 *script_lang_index,int *merge_with,int *act_type,
+ SplineFont *sf);
+#endif
+extern PST *AddSubs(PST *last,uint32 tag,char *name,uint16 flags,
+ uint16 sli,SplineChar *sc);
+
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+extern void FVSetTitle(FontView *fv);
+extern void FVScrollToChar(FontView *fv,int i);
+extern void FVRegenChar(FontView *fv,SplineChar *sc);
+extern FontView *FontNew(void);
+extern FontView *ViewPostscriptFont(char *filename);
+#if defined(FONTFORGE_CONFIG_GTK)
+ /* Many of these are defined in interface.h */
+extern char *AskNameTag(char *title,char *def,uint32 def_tag,uint16 flags,
+ int script_lang_index, enum possub_type type, SplineFont *sf, SplineChar *default_script,
+ int merge_with,int act_type);
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+extern void _MenuWarnings(GWindow gw,struct gmenuitem *mi,GEvent *e);
+extern void MenuPrefs(GWindow base,struct gmenuitem *mi,GEvent *e);
+extern void MenuSaveAll(GWindow base,struct gmenuitem *mi,GEvent *e);
+extern void MenuExit(GWindow base,struct gmenuitem *mi,GEvent *e);
+extern void MenuOpen(GWindow base,struct gmenuitem *mi,GEvent *e);
+extern void MenuHelp(GWindow base,struct gmenuitem *mi,GEvent *e);
+extern void MenuIndex(GWindow base,struct gmenuitem *mi,GEvent *e);
+extern void MenuAbout(GWindow base,struct gmenuitem *mi,GEvent *e);
+extern void MenuLicense(GWindow base,struct gmenuitem *mi,GEvent *e);
+extern void MenuNew(GWindow gw,struct gmenuitem *mi,GEvent *e);
+extern void WindowMenuBuild(GWindow base,struct gmenuitem *mi,GEvent *);
+extern void MenuRecentBuild(GWindow base,struct gmenuitem *mi,GEvent *);
+extern void MenuScriptsBuild(GWindow base,struct gmenuitem *mi,GEvent *);
+extern void mb2DoGetText(GMenuItem2 *mb);
+extern void mbDoGetText(GMenuItem *mb);
+extern int RecentFilesAny(void);
+extern void _aplistbuild(struct gmenuitem *mi,SplineFont *sf,
+ void (*func)(GWindow,struct gmenuitem *,GEvent *));
+extern int32 *ParseBitmapSizes(GGadget *g,char *msg,int *err);
+extern GTextInfo *AddMacFeatures(GTextInfo *opentype,enum possub_type type,SplineFont *sf);
+extern unichar_t *AskNameTag(char *title,unichar_t *def,uint32 def_tag,uint16 flags,
+ int script_lang_index, enum possub_type type, SplineFont *sf, SplineChar *default_script,
+ int merge_with,int act_type);
+extern unichar_t *ShowScripts(unichar_t *usedef);
+extern GTextInfo *SFLangList(SplineFont *sf,int addfinal,SplineChar *default_script);
+extern GTextInfo **SFLangArray(SplineFont *sf,int addfinal);
+extern int ScriptLangList(SplineFont *sf,GGadget *list,int sli);
+extern void GListDelSelected(GGadget *list);
+extern void GListMoveSelected(GGadget *list,int offset);
+extern GTextInfo *GListChangeLine(GGadget *list,int pos, const unichar_t *line);
+extern GTextInfo *GListAppendLine(GGadget *list,const unichar_t *line,int select);
+extern GTextInfo *GListChangeLine8(GGadget *list,int pos, const char *line);
+extern GTextInfo *GListAppendLine8(GGadget *list,const char *line,int select);
+#endif
+extern void CharInfoInit(void);
+#ifdef FONTFORGE_CONFIG_DEVICETABLES
+extern int DeviceTableOK(char *dvstr, int *_low, int *_high);
+extern DeviceTable *DeviceTableParse(DeviceTable *dv,char *dvstr);
+extern void VRDevTabParse(struct vr *vr,struct matrix_data *md);
+extern void DevTabToString(char **str,DeviceTable *adjust);
+extern void ValDevTabToStrings(struct matrix_data *mds,int first_offset,ValDevTab *adjust);
+#endif
+extern void KpMDParse(SplineFont *sf,SplineChar *sc,struct lookup_subtable *sub,
+ struct matrix_data *possub,int rows,int cols,int i);
+extern void GFI_LookupEnableButtons(struct gfi_data *gfi, int isgpos);
+extern void GFI_LookupScrollbars(struct gfi_data *gfi, int isgpos, int refresh);
+extern void FontInfo(SplineFont *sf,int aspect,int sync);
+extern void FontInfoDestroy(SplineFont *sf);
+extern void FontMenuFontInfo(void *fv);
+extern void GFI_CCDEnd(struct gfi_data *d);
+extern struct enc *MakeEncoding(SplineFont *sf, EncMap *map);
+extern void LoadEncodingFile(void);
+extern void RemoveEncoding(void);
+extern void SFPrivateInfo(SplineFont *sf);
+extern void FontViewReformatAll(SplineFont *sf);
+extern void FontViewReformatOne(FontView *fv);
+extern void FVShowFilled(FontView *fv);
+extern void FVChangeDisplayBitmap(FontView *fv,BDFFont *bdf);
+extern void FVDelay(FontView *fv,void (*func)(FontView *));
+#if defined(FONTFORGE_CONFIG_GTK)
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+extern void GFI_FinishContextNew(struct gfi_data *d,FPST *fpst, int success);
+extern void SCPreparePopup(GWindow gw,SplineChar *sc, struct remap *remap, int enc, int actualuni);
+extern void CVDrawSplineSet(CharView *cv, GWindow pixmap, SplinePointList *set,
+ Color fg, int dopoints, DRect *clip );
+extern GWindow CVMakeTools(CharView *cv);
+extern GWindow CVMakeLayers(CharView *cv);
+extern GWindow BVMakeTools(BitmapView *bv);
+extern GWindow BVMakeLayers(BitmapView *bv);
+extern int CVPaletteMnemonicCheck(GEvent *event);
+extern int TrueCharState(GEvent *event);
+extern void CVToolsPopup(CharView *cv, GEvent *event);
+extern void BVToolsPopup(BitmapView *bv, GEvent *event);
+#endif
+extern real CVRoundRectRadius(void);
+extern int CVRectElipseCenter(void);
+extern void CVRectEllipsePosDlg(CharView *cv);
+extern real CVStarRatio(void);
+extern int CVPolyStarPoints(void);
+extern StrokeInfo *CVFreeHandInfo(void);
+extern void BVToolsSetCursor(BitmapView *bv, int state,char *device);
+extern void CVToolsSetCursor(CharView *cv, int state,char *device);
+extern int CVPaletteIsVisible(CharView *cv,int which);
+extern void CVPaletteSetVisible(CharView *cv,int which,int visible);
+extern void CVPalettesRaise(CharView *cv);
+extern void CVLayersSet(CharView *cv);
+extern void _CVPaletteActivate(CharView *cv,int force);
+extern void CVPaletteActivate(CharView *cv);
+extern void CVPalettesHideIfMine(CharView *cv);
+extern int BVPaletteIsVisible(BitmapView *bv,int which);
+extern void BVPaletteSetVisible(BitmapView *bv,int which,int visible);
+extern void BVPaletteActivate(BitmapView *bv);
+extern void BVPalettesHideIfMine(BitmapView *bv);
+extern void BVPaletteColorChange(BitmapView *bv);
+extern void BVPaletteColorUnderChange(BitmapView *bv,int color);
+extern void BVPaletteChangedChar(BitmapView *bv);
+extern void CVPaletteDeactivate(void);
+extern void PalettesChangeDocking(void);
+extern int CVPalettesWidth(void);
+extern int BVPalettesWidth(void);
+
+extern void CVDoTransform(CharView *cv, enum cvtools cvt );
+extern void CVTransFunc(CharView *cv,real transform[6],enum fvtrans_flags);
+extern void TransformDlgCreate(void *data,void (*transfunc)(void *,real *,int,BVTFunc *,enum fvtrans_flags),
+ int (*getorigin)(void *,BasePoint *,int), int enableback,
+ enum cvtools cvt);
+extern void BitmapDlg(FontView *fv,SplineChar *sc, int isavail);
+extern int SimplifyDlg(SplineFont *sf,struct simplifyinfo *smpl);
+extern void CVReviewHints(CharView *cv);
+extern void CVCreateHint(CharView *cv,int ishstem,int preserveundoes);
+extern void SCRemoveSelectedMinimumDistances(SplineChar *sc,int inx);
+extern int CVExport(CharView *cv);
+extern int BVExport(BitmapView *bv);
+
+#if defined(FONTFORGE_CONFIG_GTK)
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+extern void DrawAnchorPoint(GWindow pixmap,int x, int y,int selected);
+extern void DefaultY(GRect *pos);
+extern void CVDrawRubberRect(GWindow pixmap, CharView *cv);
+extern void CVInfoDraw(CharView *cv, GWindow pixmap );
+extern void CVChar(CharView *cv, GEvent *event );
+extern void PI_ShowHints(SplineChar *sc, GGadget *list, int set);
+extern GTextInfo *SCHintList(SplineChar *sc,HintMask *);
+#endif
+extern void CVResize(CharView *cv );
+extern CharView *CharViewCreate(SplineChar *sc,FontView *fv,int enc);
+extern void CharViewFree(CharView *cv);
+extern int CVValid(SplineFont *sf, SplineChar *sc, CharView *cv);
+extern void CVSetCharChanged(CharView *cv,int changed);
+extern void _CVCharChangedUpdate(CharView *cv,int changed);
+extern void CVCharChangedUpdate(CharView *cv);
+extern int CVAnySel(CharView *cv, int *anyp, int *anyr, int *anyi, int *anya);
+extern SplinePoint *CVAnySelPoints(CharView *cv);
+extern void CVSelectPointAt(CharView *cv);
+extern int CVTwoForePointsSelected(CharView *cv, SplinePoint **sp1, SplinePoint **sp2);
+extern int CVIsDiagonalable(SplinePoint *sp1, SplinePoint *sp2, SplinePoint **sp3, SplinePoint **sp4);
+extern int CVClearSel(CharView *cv);
+extern int CVSetSel(CharView *cv,int mask);
+extern void CVInvertSel(CharView *cv);
+extern int CVAllSelected(CharView *cv);
+extern SplinePointList *CVAnySelPointList(CharView *cv);
+extern SplinePoint *CVAnySelPoint(CharView *cv);
+extern int CVOneThingSel(CharView *cv, SplinePoint **sp, SplinePointList **spl,
+ RefChar **ref, ImageList **img, AnchorPoint **ap);
+extern int CVOneContourSel(CharView *cv, SplinePointList **_spl,
+ RefChar **ref, ImageList **img);
+extern void RevertedGlyphReferenceFixup(SplineChar *sc, SplineFont *sf);
+extern void CVImport(CharView *cv);
+extern void BVImport(BitmapView *bv);
+extern void FVImport(FontView *bv);
+extern void CVFindCenter(CharView *cv, BasePoint *bp, int nosel);
+extern void CVStroke(CharView *cv);
+extern void FVStroke(FontView *fv);
+extern void FreeHandStrokeDlg(StrokeInfo *si);
+extern void OutlineDlg(FontView *fv, CharView *cv,MetricsView *mv,int isinline);
+extern void ShadowDlg(FontView *fv, CharView *cv,MetricsView *mv,int wireframe);
+extern void CVTile(CharView *cv);
+extern void FVTile(FontView *fv);
+extern void SCCharInfo(SplineChar *sc,EncMap *map,int enc);
+extern void CharInfoDestroy(struct charinfo *ci);
+extern SplineChar *SuffixCheck(SplineChar *sc,char *suffix);
+extern void SCSubtableDefaultSubsCheck(SplineChar *sc, struct lookup_subtable *sub, struct matrix_data *possub, int col_cnt, int r);
+extern void CVGetInfo(CharView *cv);
+extern void CVPGetInfo(CharView *cv);
+extern int SCUsedBySubs(SplineChar *sc);
+extern void SCSubBy(SplineChar *sc);
+extern void SCRefBy(SplineChar *sc);
+extern void ApGetInfo(CharView *cv, AnchorPoint *ap);
+extern void CVAddAnchor(CharView *cv);
+extern AnchorClass *AnchorClassUnused(SplineChar *sc,int *waslig);
+extern void FVSetWidth(FontView *fv,enum widthtype wtype);
+extern void CVSetWidth(CharView *cv,enum widthtype wtype);
+extern void CVChangeSC(CharView *cv, SplineChar *sc );
+extern void SCRefreshTitles(SplineChar *sc);
+extern void SPChangePointType(SplinePoint *sp, int pointtype);
+
+extern void CVAdjustPoint(CharView *cv, SplinePoint *sp);
+extern void CVMergeSplineSets(CharView *cv, SplinePoint *active, SplineSet *activess,
+ SplinePoint *merge, SplineSet *mergess);
+extern void CVAdjustControl(CharView *cv,BasePoint *cp, BasePoint *to);
+extern int CVMoveSelection(CharView *cv, real dx, real dy, uint32 input_state);
+#if defined(FONTFORGE_CONFIG_GDRAW)
+extern int CVTestSelectFromEvent(CharView *cv,GEvent *event);
+extern void CVMouseMovePen(CharView *cv, PressedOn *p, GEvent *event);
+extern void CVMouseUpPoint(CharView *cv,GEvent *event);
+extern int CVMouseMovePointer(CharView *cv, GEvent *event);
+extern void CVMouseDownPointer(CharView *cv, FindSel *fs, GEvent *event);
+extern void CVMouseDownRuler(CharView *cv, GEvent *event);
+extern void CVMouseMoveRuler(CharView *cv, GEvent *event);
+extern int CVMouseAtSpline(CharView *cv,GEvent *event);
+extern void CVMouseUpRuler(CharView *cv, GEvent *event);
+extern void CVMouseMoveHand(CharView *cv, GEvent *event);
+extern void CVMouseDownFreeHand(CharView *cv, GEvent *event);
+extern void CVMouseMoveFreeHand(CharView *cv, GEvent *event);
+extern void CVMouseUpFreeHand(CharView *cv, GEvent *event);
+extern void CVMouseDownShape(CharView *cv,GEvent *event);
+extern void CPStartInfo(CharView *cv, GEvent *event);
+extern void CPUpdateInfo(CharView *cv, GEvent *event);
+extern void CPEndInfo(CharView *cv);
+extern void BVChar(BitmapView *cv, GEvent *event );
+#endif
+extern void CVMouseDownPoint(CharView *cv,GEvent *event);
+extern void CVMouseMovePoint(CharView *cv,PressedOn *);
+extern void CVMouseUpPointer(CharView *cv );
+extern void CVCheckResizeCursors(CharView *cv);
+extern void CVMouseDownHand(CharView *cv);
+extern void CVMouseUpHand(CharView *cv);
+extern void CVMouseDownTransform(CharView *cv);
+extern void CVMouseMoveTransform(CharView *cv);
+extern void CVMouseUpTransform(CharView *cv);
+extern void CVMouseDownKnife(CharView *cv);
+extern void CVMouseMoveKnife(CharView *cv,PressedOn *);
+extern void CVMouseUpKnife(CharView *cv,GEvent *event);
+extern void CVMouseMoveShape(CharView *cv);
+extern void CVMouseUpShape(CharView *cv);
+#ifdef FONTFORGE_CONFIG_GDRAW
+extern void LogoExpose(GWindow pixmap,GEvent *event, GRect *r,enum drawmode dm);
+#endif
+extern void CVDebugPointPopup(CharView *cv);
+
+extern int GotoChar(SplineFont *sf,EncMap *map);
+
+extern int CVLayer(CharView *cv);
+extern Undoes *CVPreserveStateHints(CharView *cv);
+extern Undoes *CVPreserveState(CharView *cv);
+extern Undoes *CVPreserveTState(CharView *cv);
+extern Undoes *CVPreserveWidth(CharView *cv,int width);
+extern Undoes *CVPreserveVWidth(CharView *cv,int vwidth);
+extern void CVDoRedo(CharView *cv);
+extern void CVDoUndo(CharView *cv);
+extern void CVRestoreTOriginalState(CharView *cv);
+extern void CVUndoCleanup(CharView *cv);
+extern void CVRemoveTopUndo(CharView *cv);
+extern void CopySelected(CharView *cv);
+extern void CVCopyGridFit(CharView *cv);
+extern void CopyWidth(CharView *cv,enum undotype);
+extern void MVCopyChar(MetricsView *mv, SplineChar *sc, enum fvcopy_type fullcopy);
+extern void PasteIntoMV(MetricsView *mv,SplineChar *sc, int doclear);
+
+extern void CVShowPoint(CharView *cv, BasePoint *me);
+
+extern BitmapView *BitmapViewCreate(BDFChar *bc, BDFFont *bdf, FontView *fv,int enc);
+extern BitmapView *BitmapViewCreatePick(int enc, FontView *fv);
+extern void BitmapViewFree(BitmapView *bv);
+#ifdef FONTFORGE_CONFIG_GDRAW
+extern void BVMenuRotateInvoked(GWindow gw,struct gmenuitem *mi, GEvent *e);
+#endif
+extern void BVRotateBitmap(BitmapView *bv,enum bvtools type );
+extern int BVColor(BitmapView *bv);
+extern void BCSetPoint(BDFChar *bc, int x, int y, int color);
+extern void BCGeneralFunction(BitmapView *bv,
+ void (*SetPoint)(BitmapView *,int x, int y, void *data),void *data);
+extern char *BVFlipNames[];
+extern void BVChangeBC(BitmapView *bv, BDFChar *bc, int fitit );
+
+extern void MVSetSCs(MetricsView *mv, SplineChar **scs);
+extern void MVRefreshChar(MetricsView *mv, SplineChar *sc);
+extern void MVRegenChar(MetricsView *mv, SplineChar *sc);
+extern void MVReKern(MetricsView *mv);
+extern MetricsView *MetricsViewCreate(FontView *fv,SplineChar *sc,BDFFont *bdf);
+extern void MetricsViewFree(MetricsView *mv);
+extern void MVRefreshAll(MetricsView *mv);
+
+extern void DoPrefs(void);
+#if defined(FONTFORGE_CONFIG_GTK)
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+extern void GListAddStr(GGadget *list,unichar_t *str, void *ud);
+extern void GListReplaceStr(GGadget *list,int index, unichar_t *str, void *ud);
+extern struct macname *NameGadgetsGetNames( GWindow gw );
+extern void NameGadgetsSetEnabled( GWindow gw, int enable );
+extern int GCDBuildNames(GGadgetCreateData *gcd,GTextInfo *label,int pos,struct macname *names);
+extern void GCDFillMacFeat(GGadgetCreateData *mfgcd,GTextInfo *mflabels, int width,
+ MacFeat *all, int fromprefs, GGadgetCreateData *boxes,
+ GGadgetCreateData **array);
+extern void Prefs_ReplaceMacFeatures(GGadget *list);
+#endif
+
+#if defined(FONTFORGE_CONFIG_GTK)
+extern char *FVOpenFont(char *title, const char *defaultfile,
+ const char *initial_filter,int mult);
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+extern void SCAutoTrace(SplineChar *sc,GWindow v,int ask);
+extern unichar_t *FVOpenFont(char *title, const char *defaultfile, int mult);
+#endif
+
+
+extern void PrintDlg(FontView *fv,SplineChar *sc,MetricsView *mv);
+
+#if defined(FONTFORGE_CONFIG_GTK)
+#elif defined(FONTFORGE_CONFIG_GDRAW)
+enum sftf_fonttype { sftf_pfb, sftf_ttf, sftf_otf, sftf_bitmap, sftf_pfaedit };
+extern int SFTFSetFont(GGadget *g, int start, int end, SplineFont *sf,
+ enum sftf_fonttype, int size, int antialias);
+extern void SFTFRegisterCallback(GGadget *g, void *cbcontext,
+ void (*changefontcallback)(void *,SplineFont *,enum sftf_fonttype,int size,int aa));
+extern GGadget *SFTextAreaCreate(struct gwindow *base, GGadgetData *gd,void *data);
+#endif
+extern void DisplayDlg(SplineFont *sf);
+
+extern void ShowAboutScreen(void);
+extern void DelayEvent(void (*func)(void *), void *data);
+
+extern void FindProblems(FontView *fv,CharView *cv,SplineChar *sc);
+extern void MetaFont(FontView *fv,CharView *cv,SplineChar *sc);
+extern void CVConstrainSelection(CharView *cv,int type);
+extern void CVMakeParallel(CharView *cv);
+
+extern void ScriptDlg(FontView *fv);
+
+# if HANYANG
+extern void MenuNewComposition(GWindow gw, struct gmenuitem *, GEvent *);
+extern void CVDisplayCompositions(GWindow gw, struct gmenuitem *, GEvent *);
+extern void Disp_DoFinish(struct jamodisplay *d, int cancel);
+extern void Disp_RefreshChar(SplineFont *sf,SplineChar *sc);
+extern void Disp_DefaultTemplate(CharView *cv);
+# endif
+
+extern SearchView *SVCreate(FontView *fv);
+extern void SVCharViewInits(SearchView *sv);
+#ifdef FONTFORGE_CONFIG_GDRAW
+extern void SVMenuClose(GWindow gw,struct gmenuitem *mi,GEvent *e);
+extern void SVChar(SearchView *sv, GEvent *event);
+#endif
+extern void SVMakeActive(SearchView *sv,CharView *cv);
+extern int SVAttachFV(FontView *fv,int ask_if_difficult);
+extern void SVDetachFV(FontView *fv);
+
+extern void ShowAtt(SplineFont *sf);
+extern void FontCompareDlg(FontView *fv);
+extern void SFShowKernPairs(SplineFont *sf,SplineChar *sc,AnchorClass *ac);
+extern void SFShowLigatures(SplineFont *sf,SplineChar *sc);
+
+extern void SCEditInstructions(SplineChar *sc);
+extern void SFEditTable(SplineFont *sf, uint32 tag);
+extern void IIScrollTo(struct instrinfo *ii,int ip,int mark_stop);
+extern void IIReinit(struct instrinfo *ii,int ip);
+#ifdef FONTFORGE_CONFIG_GDRAW
+extern int ii_v_e_h(GWindow gw, GEvent *event);
+extern void instr_scroll(struct instrinfo *ii,struct sbevent *sb);
+#endif
+
+extern void CVGridFitChar(CharView *cv);
+extern void CVFtPpemDlg(CharView *cv,int debug);
+extern void SCDeGridFit(SplineChar *sc);
+
+extern void CVDebugReInit(CharView *cv,int restart_debug,int dbg_fpgm);
+extern void CVDebugFree(DebugView *dv);
+#if defined(FONTFORGE_CONFIG_GDRAW)
+extern int DVChar(DebugView *dv, GEvent *e);
+#endif
+
+extern void KernClassD(KernClass *kc, SplineFont *sf, int isv);
+extern void ShowKernClasses(SplineFont *sf,MetricsView *mv,int isv);
+extern void KCLD_End(struct kernclasslistdlg *kcld);
+extern void KCLD_MvDetach(struct kernclasslistdlg *kcld,MetricsView *mv);
+extern void KernPairD(SplineFont *sf,SplineChar *sc1,SplineChar *sc2,int isv);
+#if defined(FONTFORGE_CONFIG_GDRAW)
+extern void KCD_DrawGlyph(GWindow pixmap,int x,int baseline,BDFChar *bdfc,int mag);
+#endif
+extern GTextInfo *BuildFontList(FontView *except);
+extern void TFFree(GTextInfo *tf);
+
+extern void AnchorControl(SplineChar *sc,AnchorPoint *ap);
+extern void AnchorControlClass(SplineFont *_sf,AnchorClass *ac);
+
+extern void FVSelectByPST(FontView *fv);
+extern void SFUntickAll(SplineFont *sf);
+
+enum hist_type { hist_hstem, hist_vstem, hist_blues };
+struct psdict;
+extern void SFHistogram(SplineFont *sf,struct psdict *private,uint8 *selected,
+ EncMap *map, enum hist_type which);
+
+extern void CCD_Close(struct contextchaindlg *ccd);
+extern int CCD_NameListCheck(SplineFont *sf,const char *ret,int empty_bad,char *title);
+#if defined(FONTFORGE_CONFIG_GDRAW)
+extern struct contextchaindlg *ContextChainEdit(SplineFont *sf,FPST *fpst,
+ struct gfi_data *gfi,unichar_t *newname);
+extern int CCD_InvalidClassList(char *ret,GGadget *list,int wasedit);
+extern char *cu_copybetween(const unichar_t *start, const unichar_t *end);
+#endif
+
+extern struct statemachinedlg *StateMachineEdit(SplineFont *sf,ASM *sm,struct gfi_data *d);
+extern void SMD_Close(struct statemachinedlg *smd);
+extern void GFI_FinishSMNew(struct gfi_data *d,ASM *sm, int success,int isnew);
+extern void GFI_SMDEnd(struct gfi_data *d);
+
+extern void MMChangeBlend(MMSet *mm,FontView *fv,int tonew);
+extern void MMWizard(MMSet *mm);
+
+extern int LayerDialog(Layer *layer);
+extern void CVLayerChange(CharView *cv);
+
+extern void CVPointOfView(CharView *cv,struct pov_data *);
+extern int PointOfViewDlg(struct pov_data *pov,SplineFont *sf,int flags);
+
+extern SplineChar *FVMakeChar(FontView *fv,int i);
+
+extern void CVYPerspective(CharView *cv,double x_vanish, double y_vanish);
+
+extern void DVCreateGloss(DebugView *dv);
+extern int CVXPos(DebugView *dv,int offset,int width);
+
+extern EncMap *EncMapFromEncoding(SplineFont *sf,Encoding *enc);
+extern void SFRemoveGlyph(SplineFont *sf,SplineChar *sc, int *flags);
+extern void FVAddEncodingSlot(FontView *fv,int gid);
+extern void SFAddEncodingSlot(SplineFont *sf,int gid);
+extern void SFAddGlyphAndEncode(SplineFont *sf,SplineChar *sc,EncMap *basemap, int baseenc);
+#if defined(FONTFORGE_CONFIG_GDRAW)
+extern GMenuItem *GetEncodingMenu(void (*func)(GWindow,GMenuItem *,GEvent *),
+ Encoding *current);
+
+extern GTextInfo *TIFromName(const char *name);
+#endif
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+
+enum subtable_data_flags {
+ /* I have flags for each alternative because I want "unspecified" to be */
+ /* an option */
+ sdf_kernclass = 0x01,
+ sdf_kernpair = 0x02,
+ sdf_verticalkern = 0x04,
+ sdf_horizontalkern = 0x08,
+ sdf_dontedit = 0x10
+};
+struct subtable_data {
+ int flags;
+ SplineChar *sc;
+};
+
+extern GTextInfo **SFLookupListFromType(SplineFont *sf, int lookup_type );
+extern GTextInfo **SFSubtablesOfType(SplineFont *sf, int lookup_type, int kernclass);
+extern GTextInfo *SFSubtableListOfType(SplineFont *sf, int lookup_type, int kernclass);
+extern struct lookup_subtable *SFNewLookupSubtableOfType(SplineFont *sf, int lookup_type, struct subtable_data *sd );
+extern int EditLookup(OTLookup *otl,int isgpos,SplineFont *sf);
+extern int EditSubtable(struct lookup_subtable *sub,int isgpos,SplineFont *sf,
+ struct subtable_data *sd);
+extern void _LookupSubtableContents(SplineFont *sf, struct lookup_subtable *sub,
+ struct subtable_data *sd);
+
+extern void SFBdfProperties(SplineFont *sf, EncMap *map, BDFFont *thisone);
+
+
+struct instrdlg;
+uint8 *_IVParse(struct instrdlg *iv, char *text, int *len);
+char *_IVUnParseInstrs(uint8 *instrs,int instr_cnt);
+
+#ifdef FONTFORGE_CONFIG_GDRAW
+extern GMenuItem2 helplist[];
+#endif
+extern BasePoint last_ruler_offset[];
+
+#endif /* _VIEWS_H */
diff --git a/Build/source/libs/luafontforge/fontforge/fontforge/xlib.opt b/Build/source/libs/luafontforge/fontforge/fontforge/xlib.opt
new file mode 100644
index 00000000000..8014a9e3977
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/fontforge/xlib.opt
@@ -0,0 +1,13 @@
+sys$library:libungif/lib
+sys$library:freetype/lib
+sys$library:tiff/lib
+sys$library:libjpeg/lib
+sys$library:libpng/lib
+sys$library:libz/lib
+sys$library:libuninameslist/lib
+sys$library:libxml/lib
+sys$library:intl/lib
+sys$library:iconv/lib
+sys$library:decw$xlibshr.exe/share
+sys$library:decw$xextlibshr.exe/share
+sys$share:vms_jackets.exe/share
diff --git a/Build/source/libs/luafontforge/fontforge/inc/basics.h b/Build/source/libs/luafontforge/fontforge/inc/basics.h
new file mode 100644
index 00000000000..04c2fcf54a2
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/basics.h
@@ -0,0 +1,75 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _BASICS_H
+#define _BASICS_H
+
+#ifdef VMS /* these three lines from Jacob Jansen, Open VMS port */
+# include <vms_jackets.h>
+#endif
+
+#include <stdio.h> /* for NULL */
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#else
+# include <inttypes.h>
+#endif
+#include <stdlib.h> /* for free */
+#include <limits.h>
+
+#define true 1
+#define false 0
+
+#define forever for (;;)
+
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef int16_t int16;
+typedef uint16_t uint16;
+typedef int8_t int8;
+typedef uint8_t uint8;
+
+ /* An integral type which can hold a pointer */
+typedef intptr_t intpt;
+
+#ifdef UNICHAR_16
+typedef uint16 unichar_t;
+#else
+typedef uint32 unichar_t;
+#endif
+
+
+#define gfree ff_gree
+#define galloc ff_galloc
+#define grealloc ff_grealloc
+#define gcalloc ff_gcalloc
+
+extern void *galloc(long size);
+extern void *gcalloc(int cnt, long size);
+extern void *grealloc(void *,long size);
+extern void gfree(void *);
+extern void galloc_set_trap(void (*)(void));
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/inc/chardata.h b/Build/source/libs/luafontforge/fontforge/inc/chardata.h
new file mode 100644
index 00000000000..fd2247f7e1b
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/chardata.h
@@ -0,0 +1,78 @@
+#include "basics.h"
+
+struct charmap {
+ int first, last;
+ unsigned char **table;
+ unichar_t *totable;
+};
+struct charmap2 {
+ int first, last;
+ unsigned short **table;
+ unichar_t *totable;
+};
+
+extern const unichar_t unicode_from_i8859_1[];
+extern struct charmap i8859_1_from_unicode;
+extern const unichar_t unicode_from_i8859_2[];
+extern struct charmap i8859_2_from_unicode;
+extern const unichar_t unicode_from_i8859_3[];
+extern struct charmap i8859_3_from_unicode;
+extern const unichar_t unicode_from_i8859_4[];
+extern struct charmap i8859_4_from_unicode;
+extern const unichar_t unicode_from_i8859_5[];
+extern struct charmap i8859_5_from_unicode;
+extern const unichar_t unicode_from_i8859_6[];
+extern struct charmap i8859_6_from_unicode;
+extern const unichar_t unicode_from_i8859_7[];
+extern struct charmap i8859_7_from_unicode;
+extern const unichar_t unicode_from_i8859_8[];
+extern struct charmap i8859_8_from_unicode;
+extern const unichar_t unicode_from_i8859_9[];
+extern struct charmap i8859_9_from_unicode;
+extern const unichar_t unicode_from_i8859_10[];
+extern struct charmap i8859_10_from_unicode;
+extern const unichar_t unicode_from_i8859_11[];
+extern struct charmap i8859_11_from_unicode;
+extern const unichar_t unicode_from_i8859_13[];
+extern struct charmap i8859_13_from_unicode;
+extern const unichar_t unicode_from_i8859_14[];
+extern struct charmap i8859_14_from_unicode;
+extern const unichar_t unicode_from_i8859_15[];
+extern struct charmap i8859_15_from_unicode;
+extern const unichar_t unicode_from_koi8_r[];
+extern struct charmap koi8_r_from_unicode;
+extern const unichar_t unicode_from_jis201[];
+extern struct charmap jis201_from_unicode;
+extern const unichar_t unicode_from_win[];
+extern struct charmap win_from_unicode;
+extern const unichar_t unicode_from_mac[];
+extern struct charmap mac_from_unicode;
+extern const unichar_t unicode_from_MacSymbol[];
+extern struct charmap MacSymbol_from_unicode;
+extern const unichar_t unicode_from_ZapfDingbats[];
+extern struct charmap ZapfDingbats_from_unicode;
+
+extern unichar_t *unicode_from_alphabets[];
+extern struct charmap *alphabets_from_unicode[];
+
+extern const unichar_t unicode_from_jis208[];
+extern const unichar_t unicode_from_jis212[];
+extern struct charmap2 jis_from_unicode;
+/* Subtract 0xa100 before indexing this array */
+extern const unichar_t unicode_from_big5[];
+extern struct charmap2 big5_from_unicode;
+/* Subtract 0x8100 before indexing this array */
+extern const unichar_t unicode_from_big5hkscs[];
+extern struct charmap2 big5hkscs_from_unicode;
+extern const unichar_t unicode_from_ksc5601[];
+extern struct charmap2 ksc5601_from_unicode;
+/* Subtract 0x8400 before indexing this array */
+extern const unichar_t unicode_from_johab[];
+extern struct charmap2 johab_from_unicode;
+extern const unichar_t unicode_from_gb2312[];
+extern struct charmap2 gb2312_from_unicode;
+
+/* a mask for each character saying what charset(s) it may be found in */
+extern const unsigned long * const unicode_backtrans[];
+
+extern const unichar_t *const * const unicode_alternates[];
diff --git a/Build/source/libs/luafontforge/fontforge/inc/charset.h b/Build/source/libs/luafontforge/fontforge/inc/charset.h
new file mode 100644
index 00000000000..f893c2f0ec4
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/charset.h
@@ -0,0 +1,71 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _CHARSET_H
+#define _CHARSET_H
+/* ASCII is ISO 646, except the ISO version admits national alternatives */
+enum encoding { e_usascii, e_iso646_no, e_iso646_se, e_iso8859_1,
+ e_iso8859_2, e_iso8859_3, e_iso8859_4, e_iso8859_5, e_iso8859_6,
+ e_iso8859_7, e_iso8859_8, e_iso8859_9, e_iso8859_10,
+ e_iso8859_11/* same as TIS */, e_iso8859_13, e_iso8859_14, e_iso8859_15,
+ e_koi8_r, /* RFC 1489 */
+ e_jis201, /* 8 bit, ascii & katakana */
+ e_win, e_mac,
+ e_user,
+/* korean appears to fit into the jis/euc encoding schemes */
+/* the difference between jis & jis2 is what the output encoding should be (presence of '(') */
+ e_jis, e_jis2, e_jiskorean, e_jisgb, e_sjis, /* multi-byte */
+ e_euc, e_euckorean, e_eucgb,
+ e_wansung, e_johab,
+ e_big5,
+ e_big5hkscs,
+ e_unicode, e_unicode_backwards, /* wide chars */
+ e_utf7, e_utf8, /* unicode encodings */
+ e_ucs4, /* 4 byte chars */
+ e_notrans, /* _inch returns 16bits */
+ e_encodingmax, e_unknown=-1, e_first2byte=e_jis };
+
+enum charset { em_none = -1,
+ em_iso8859_1, em_iso8859_2, em_iso8859_3, em_iso8859_4, em_iso8859_5,
+ em_iso8859_6, em_iso8859_7, em_iso8859_8, em_iso8859_9, em_iso8859_10,
+ em_iso8859_11/* same as TIS */, em_iso8859_13, em_iso8859_14, em_iso8859_15,
+ em_koi8_r,
+ em_jis201,
+ em_win, em_mac, em_symbol, em_zapfding, em_user, em_adobestandard=em_user,
+ em_jis208, em_jis212, em_ksc5601, em_gb2312, em_big5, em_big5hkscs,
+ em_johab /* Korean*/,
+/* 28 */
+ em_unicode, em_unicode4, em_gb18030 , em_max, em_first2byte=em_jis208, em_last94x94=em_gb2312 };
+
+extern int /*enum charset*/ local_encoding;
+#if HAVE_ICONV_H
+# include <iconv.h>
+extern char *iconv_local_encoding_name;
+#else
+# include <gwwiconv.h> /* My fake iconv based on encodings in gdraw/gunicode */
+#endif
+extern struct namemap { char *name; int map; } encodingnames[];
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/inc/dynamic.h b/Build/source/libs/luafontforge/fontforge/inc/dynamic.h
new file mode 100644
index 00000000000..fce7746f20f
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/dynamic.h
@@ -0,0 +1,35 @@
+/* Vague support for several different shared library formats */
+/* Everyone but the mac uses a varient of dlopen, while the mac uses NSAddImage */
+/* Under cygwin the shared libs have very strange names which bare little */
+/* resemblance to what we expect. GNU creates a .la file that tells us what */
+/* the name should be, so indirect through that */
+#ifndef __DYNAMIC_H
+# define __DYNAMIC_H
+
+# ifdef __Mac
+# include <mach-o/dyld.h>
+extern const void *gwwv_NSAddImage(char *name,uint32_t options);
+# define SO_EXT ".dylib"
+/* man NSModule */
+# define dlopen(name,foo) gwwv_NSAddImage(name,NSADDIMAGE_OPTION_WITH_SEARCHING|NSADDIMAGE_OPTION_RETURN_ON_ERROR)
+/* It would have been nice if the Mac's docs had mentioned that the linker adds*/
+/* an underscore to symbol names.... */
+# define dlsym(image,symname) NSAddressOfSymbol(NSLookupSymbolInImage(image,"_" symname,NSLOOKUPSYMBOLINIMAGE_OPTION_BIND|NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR))
+# define DL_CONST const
+# define dlclose(image_ptr) /* Don't know how to do this on mac */
+# define dlerror() "Error when loading dynamic library"
+# else
+# include <dlfcn.h>
+# ifdef __CygWin
+# define dlopen(name,foo) libtool_laopen(name,foo)
+void *libtool_laopen(const char *filename, int flags);
+# endif
+#ifdef __VMS
+# define SO_EXT ".exe"
+#else
+# define SO_EXT ".so"
+#endif
+#define DL_CONST
+# endif
+
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/inc/fileutil.h b/Build/source/libs/luafontforge/fontforge/inc/fileutil.h
new file mode 100644
index 00000000000..5c9be3a2af3
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/fileutil.h
@@ -0,0 +1,43 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _FILEUTIL_H
+#define _FILEUTIL_H
+
+extern char *GFileGetAbsoluteName(char *name, char *result, int rsiz);
+extern char *GFileBuildName(char *dir,char *fname,char *buffer,int size);
+extern char *GFileReplaceName(char *oldname,char *fname,char *buffer,int size);
+extern char *GFileNameTail(const char *oldname);
+extern int GFileIsDir(const char *file);
+extern int GFileExists(const char *file);
+extern int GFileModifyable(const char *file);
+extern int GFileModifyableDir(const char *file);
+extern int GFileReadable(char *file);
+extern int GFileMkDir(char *name);
+extern int GFileRmDir(char *name);
+extern int GFileUnlink(char *name);
+
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/inc/gdraw.h b/Build/source/libs/luafontforge/fontforge/inc/gdraw.h
new file mode 100644
index 00000000000..9d273ad63f8
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/gdraw.h
@@ -0,0 +1,593 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _GDRAW_H
+#define _GDRAW_H
+#include "basics.h"
+#include "charset.h"
+
+typedef uint32 Color;
+
+#define COLOR_UNKNOWN ((Color) 0xffffffff)
+#define COLOR_TRANSPARENT ((Color) 0xffffffff)
+#define COLOR_DEFAULT ((Color) 0xfffffffe)
+#define COLOR_CREATE(r,g,b) (((r)<<16) | ((g)<<8) | (b))
+#define COLOR_RED(col) ((col)>>16)
+#define COLOR_GREEN(col) (((col)>>8) & 0xff)
+#define COLOR_BLUE(col) ((col)&0xff)
+
+typedef struct clut {
+ int16 clut_len;
+ unsigned int is_grey: 1;
+ uint32 trans_index; /* will be ignored for cluts in images, use base->trans instead */
+ Color clut[256];
+} GClut;
+
+typedef struct revcmap RevCMap;
+
+enum image_type { it_mono, it_bitmap=it_mono, it_index, it_true };
+
+struct _GImage {
+/* Format: bitmaps are stored with the most significant bit first in byte units
+ indexed images are stored in byte units
+ true color images are stored in 4 byte units, 0,red,green,blue
+*/
+ unsigned int image_type: 2;
+ int16 delay; /* for animated GIFs, delay to next frame */
+ int32 width, height;
+ int32 bytes_per_line;
+ uint8 *data;
+ GClut *clut;
+ Color trans; /* PNG supports more than one transparent color, we don't */
+ /* for non-true color images this is the index, not a color */
+};
+
+/* We deal with 1 bit, 8 bit and 32 bit images internal. 1 bit images may have*/
+/* a clut (if they don't assume bw, 0==black, 1==white), 8 bit must have a */
+/* clut, 32bit are actually 24 bit RGB images, but we pad them for easy */
+/* accessing. it_screen means that we've got an image that can be drawn */
+/* directly on the screen */
+typedef struct gimage {
+ short list_len; /* length of list */
+ union { /* depends on whether has_list is set */
+ struct _GImage *image;
+ struct _GImage **images;
+ } u;
+ void *userdata;
+} GImage;
+
+enum pastetrans_type { ptt_paste_trans_to_trans, ptt_old_shines_through};
+
+typedef struct grect {
+ int32 x,y,width,height;
+} GRect;
+
+typedef struct gpoint {
+ int16 x,y;
+} GPoint;
+
+enum font_style { fs_none, fs_italic=1, fs_smallcaps=2, fs_condensed=4, fs_extended=8 };
+enum font_type { ft_unknown, ft_serif, ft_sans, ft_mono, ft_cursive, ft_max };
+enum text_mods { tm_none, tm_upper=1, tm_lower=2, tm_initialcaps=4, tm_showsofthyphen=8 };
+enum text_lines { tl_none, tl_under=1, tl_strike=2, tl_over=4, tl_dash=8 };
+
+typedef struct {
+ const unichar_t *family_name; /* may be more than one */
+ int16 point_size; /* negative values are in pixels */
+ int16 weight;
+ enum font_style style;
+ char *utf8_family_name;
+} FontRequest;
+
+typedef struct {
+ int16 letter_spacing; /* in point tenths */
+ unsigned int starts_word: 1;
+ unsigned int has_charset: 1;
+ enum text_mods mods;
+ enum text_lines lines;
+ enum charset charset;
+} FontMods;
+
+typedef struct gbidata {
+ unichar_t *text;
+ uint8 *level;
+ uint8 *override;
+ uint16 *type;
+ unichar_t **original;
+ int32 len;
+ unsigned int base_right_to_left: 1;
+ unsigned int interpret_arabic: 1;
+} GBiText;
+
+typedef struct font_instance FontInstance, GFont;
+enum gic_style { gic_overspot=2, gic_root=1, gic_hidden=0, gic_orlesser=4, gic_type=3 };
+typedef struct ginput_context GIC;
+
+typedef struct ggc {
+ struct gwindow *w;
+ int32 xor_base;
+ Color fg;
+ Color bg;
+ GRect clip;
+ enum draw_func { df_copy, df_xor } func;
+ unsigned int copy_through_sub_windows: 1;
+ unsigned int bitmap_col: 1; /* window is mapped for bitmap */
+ int16 skip_len, dash_len;
+ int16 line_width;
+ int16 ts;
+ int32 ts_xoff, ts_yoff;
+ int dash_offset;
+ GFont *fi;
+} GGC;
+
+typedef struct gtextbounds {
+ int16 lbearing; /* of first character */
+ /* origin to left edge of first char's raster */
+ int32 rbearing; /* origin to right edge of last char's raster */
+ int16 as,ds; /* maximum ascent and maximum descent */
+ /* (both numbers will be positive for "g" */
+ /* so total height = as+ds */
+ int16 fas, fds; /* font ascent and descent */
+ /* total width = rbearing-lbearing */
+ int32 width; /* above are for the bounding rect, not the text */
+ /* "width" which may be totally different */
+} GTextBounds;
+
+enum selnames { sn_primary, sn_clipboard, sn_drag_and_drop, sn_max };
+typedef struct gwindow *GWindow;
+typedef struct gdisplay GDisplay;
+typedef struct gtimer GTimer;
+
+enum keystate_mask { ksm_shift=1, ksm_capslock=2, ksm_control=4, ksm_meta=8,
+ ksm_cmdsuse=0x8,
+/* Suse X on a Mac maps command to meta. As of Mac 10.2, the command key is 0x10 */
+/* In 10.0 the command key was 0x20 */
+ ksm_cmdmacosx=0x10, /* But not the command key under suse ppc linux*/
+ ksm_numlock=0x10, /* It's numlock on my 386 system */
+ ksm_super=0x40, /* RedHat mask for the key with the windows flag on it */
+ ksm_hyper=0x80,
+/* Both Suse and Mac OS/X now map option to 0x2000, but under 10.0 it was meta */
+ ksm_option=0x2000,
+ ksm_button1=(1<<8), ksm_button2=(1<<9), ksm_button3=(1<<10),
+ ksm_button4=(1<<11), ksm_button5=(1<<12),
+ ksm_buttons=(ksm_button1|ksm_button2|ksm_button3|ksm_button4|ksm_button5)};
+enum mnemonic_focus { mf_normal, mf_tab, mf_mnemonic, mf_shortcut };
+typedef struct gevent {
+ enum event_type { et_noevent = -1, et_char, et_charup,
+ et_mousemove, et_mousedown, et_mouseup,
+ et_crossing, /* these four are assumed to be consecutive */
+ et_focus,
+ et_expose, et_visibility, et_resize, et_timer,
+ et_close/*request by user*/, et_create,
+ et_map, et_destroy/*window being freed*/,
+ et_selclear,
+ et_drag, et_dragout, et_drop,
+ et_lastnativeevent=et_drop,
+ et_controlevent, et_user } type;
+#define _GD_EVT_CHRLEN 10
+ GWindow w;
+ union {
+ struct {
+ char *device; /* for wacom devices */
+ uint32 time;
+ uint16 state;
+ int16 x,y;
+ uint16 keysym;
+ unichar_t chars[_GD_EVT_CHRLEN];
+ } chr;
+ struct {
+ char *device; /* for wacom devices */
+ uint32 time;
+ int16 state;
+ int16 x,y;
+ int16 button;
+ int16 clicks;
+ int32 pressure, xtilt, ytilt, separation;
+ } mouse;
+ struct {
+ GRect rect;
+ } expose;
+ struct {
+ enum visibility_state { vs_unobscured, vs_partially, vs_obscured } state;
+ } visibility;
+ struct {
+ GRect size;
+ int16 dx, dy, dwidth, dheight;
+ unsigned int moved: 1;
+ unsigned int sized: 1;
+ } resize;
+ struct {
+ char *device; /* for wacom devices */
+ uint32 time;
+ int16 state;
+ int16 x,y;
+ unsigned int entered: 1;
+ } crossing;
+ struct {
+ unsigned int gained_focus: 1;
+ unsigned int mnemonic_focus: 2;
+ } focus;
+ struct {
+ unsigned int is_visible: 1;
+ } map;
+ struct {
+ enum selnames sel;
+ } selclear;
+ struct {
+ int32 x,y;
+ } drag_drop;
+ struct {
+ GTimer *timer;
+ void *userdata;
+ } timer;
+ struct {
+ enum { et_buttonpress, et_buttonactivate, et_radiochanged,
+ et_listselected, et_listdoubleclick,
+ et_scrollbarchange,
+ et_textchanged, et_textfocuschanged,
+ et_lastsubtype } subtype;
+ struct ggadget *g;
+ union {
+ struct sbevent {
+ enum sb { et_sb_top, et_sb_uppage, et_sb_up, et_sb_left=et_sb_up,
+ et_sb_down, et_sb_right=et_sb_down, et_sb_downpage,
+ et_sb_bottom,
+ et_sb_thumb, et_sb_thumbrelease } type;
+ int32 pos;
+ } sb;
+ struct {
+ int gained_focus;
+ } tf_focus;
+ struct {
+ int from_pulldown; /* -1 normally, else index into pulldown list */
+ } tf_changed;
+ struct {
+ int clicks;
+ int16 button, state;
+ } button;
+ struct {
+ int from_mouse, changed_index;
+ } list;
+ } u;
+ } control;
+ struct {
+ long subtype;
+ void *userdata;
+ } user;
+ } u;
+ void *native_window;
+} GEvent;
+
+typedef enum cursor_types { ct_default, ct_pointer, ct_backpointer, ct_hand,
+ ct_question, ct_cross, ct_4way, ct_text, ct_watch, ct_draganddrop,
+ ct_invisible,
+ ct_user, ct_user2 /* and so on */ } GCursor;
+
+typedef struct gwindow_attrs {
+ enum window_attr_mask { wam_events=0x2, wam_bordwidth=0x4,
+ wam_bordcol=0x8, wam_backcol=0x10, wam_cursor=0x20, wam_wtitle=0x40,
+ wam_ititle=0x80, wam_icon=0x100, wam_nodecor=0x200,
+ wam_positioned=0x400, wam_centered=0x800, wam_undercursor=0x1000,
+ wam_noresize=0x2000, wam_restrict=0x4000, wam_redirect=0x8000,
+ wam_isdlg=0x10000, wam_notrestricted=0x20000,
+ wam_transient=0x40000,
+ wam_utf8_wtitle=0x80000, wam_utf8_ititle=0x100000 } mask;
+ uint32 event_masks; /* (1<<et_char) | (1<<et_mouseup) etc */
+ int16 border_width;
+ Color border_color; /* Color_UNKNOWN if unspecified */
+ Color background_color;
+ GCursor cursor;
+ /* Remainder is only for top level windows */
+ const unichar_t *window_title;
+ const unichar_t *icon_title;
+ struct gwindow *icon; /* A bitmap pixmap, or NULL */
+ unsigned int nodecoration: 1; /* no wm decoration */
+ unsigned int positioned: 1; /* position information is important */
+ unsigned int centered: 2; /* center the window on the screen. pos.width&pos.height are used */
+ unsigned int undercursor: 1; /* center the window under the cursor. */
+ unsigned int noresize: 1; /* set min and max sizes to current size */
+ unsigned int restrict_input_to_me: 1;/* for dialogs, no input outside of dlg */
+ unsigned int redirect_chars_to_me: 1;/* ditto, we get any input outside of us */
+ unsigned int is_dlg: 1; /* 1 for dlg, 0 for main window */
+ unsigned int not_restricted: 1; /* gets events if if a restricted (modal) dlg is up */
+ GWindow redirect_from; /* only redirect input from this window and its children */
+ GWindow transient; /* the Transient_FOR hint */
+ const char *utf8_window_title;
+ const char *utf8_icon_title;
+} GWindowAttrs;
+
+typedef struct gprinter_attrs {
+ enum printer_attr_mask { pam_pagesize=1, pam_margins=2, pam_scale=4,
+ pam_res=8, pam_copies=0x10, pam_thumbnails=0x20, pam_printername=0x40,
+ pam_filename=0x80, pam_args=0x100, pam_color=0x200, pam_transparent=0x400,
+ pam_lpr=0x800, pam_queue=0x1000, pam_eps=0x2000, pam_landscape=0x4000,
+ pam_title=0x8000 } mask;
+ float width, height; /* paper size */
+ float lmargin, rmargin, tmargin, bmargin;
+ float scale; /* 1.0 implies no scaling */
+ enum printer_units { pu_inches, pu_points, pu_mm } units;
+ int32 res; /* printer resolution */
+ int16 num_copies;
+ int16 thumbnails; /* linear count of number of thumbnail*/
+ /* pages per edge of real page */
+ unsigned int do_color: 1;
+ unsigned int do_transparent: 1; /* try to get transparent images to work*/
+ unsigned int use_lpr: 1;
+ unsigned int donot_queue: 1; /* ie. print to file */
+ unsigned int landscape: 1;
+ unsigned int eps: 1; /* generate an eps file, not a full doc */
+ char *printer_name; /* only if things are queued */
+ char *file_name; /* only if things aren't queued */
+ char *extra_lpr_args;
+ unichar_t *title;
+ uint16 start_page, end_page; /* Ignored by printer routines, for programmer */
+} GPrinterAttrs;
+
+typedef struct gdeveventmask {
+ int event_mask;
+ char *device_name;
+} GDevEventMask;
+
+enum gzoom_flags { gzf_pos=1, gzf_size=2 };
+
+typedef int (*GDrawEH)(GWindow,GEvent *);
+
+extern unichar_t *GDrawKeysyms[];
+extern GDisplay *screen_display, *printer_display;
+
+extern void GDrawCreateDisplays(char *displayname,char *programname);
+extern void *GDrawNativeDisplay(GDisplay *);
+extern void GDrawTerm(GDisplay *disp);
+
+extern int GDrawGetRes(GWindow gw);
+extern int GDrawPointsToPixels(GWindow gw,int points);
+extern int GDrawPixelsToPoints(GWindow gw,int pixels);
+
+extern void GDrawSetDefaultIcon(GWindow icon);
+extern GWindow GDrawCreateTopWindow(GDisplay *gdisp, GRect *pos, int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs);
+extern GWindow GDrawCreateSubWindow(GWindow w, GRect *pos, int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs);
+extern GWindow GDrawCreatePixmap(GDisplay *gdisp, uint16 width, uint16 height);
+extern GWindow GDrawCreateBitmap(GDisplay *gdisp, uint16 width, uint16 height, uint8 *data);
+extern GCursor GDrawCreateCursor(GWindow src,GWindow mask,Color fg,Color bg,
+ int16 x, int16 y );
+extern void GDrawDestroyWindow(GWindow w);
+extern void GDrawDestroyCursor(GDisplay *gdisp, GCursor ct);
+extern int GDrawNativeWindowExists(GDisplay *gdisp, void *native);
+extern void GDrawSetZoom(GWindow w, GRect *zoomsize, enum gzoom_flags);
+extern void GDrawSetWindowBorder(GWindow w, int width, Color color);
+extern int GDrawSetDither(GDisplay *gdisp, int dither);
+extern void GDrawReparentWindow(GWindow child,GWindow newparent, int x,int y);
+extern void GDrawSetVisible(GWindow w, int visible);
+extern int GDrawIsVisible(GWindow w);
+extern void GDrawTrueMove(GWindow w, int32 x, int32 y);
+extern void GDrawMove(GWindow w, int32 x, int32 y);
+extern void GDrawResize(GWindow w, int32 width, int32 height);
+extern void GDrawMoveResize(GWindow w, int32 x, int32 y, int32 width, int32 height);
+extern GWindow GDrawGetRoot(GDisplay *);
+extern Color GDrawGetDefaultBackground(GDisplay *);
+extern Color GDrawGetDefaultForeground(GDisplay *);
+extern GRect *GDrawGetSize(GWindow w, GRect *ret);
+extern GDrawEH GDrawGetEH(GWindow w);
+extern void GDrawSetEH(GWindow w,GDrawEH e_h);
+extern void GDrawGetPointerPosition(GWindow w, GEvent *mouse);
+extern void GDrawRaise(GWindow w);
+extern void GDrawRaiseAbove(GWindow w,GWindow below);
+extern int GDrawIsAbove(GWindow w,GWindow other);
+extern void GDrawLower(GWindow w);
+extern void GDrawSetWindowTitles(GWindow w, const unichar_t *title, const unichar_t *icontit);
+extern void GDrawSetWindowTitles8(GWindow w, const char *title, const char *icontit);
+extern unichar_t *GDrawGetWindowTitle(GWindow w);
+extern char *GDrawGetWindowTitle8(GWindow w);
+extern void GDrawSetCursor(GWindow w, GCursor ct);
+extern GCursor GDrawGetCursor(GWindow w);
+extern GWindow GDrawGetRedirectWindow(GDisplay *gd);
+extern GWindow GDrawGetParentWindow(GWindow gw);
+extern int GDrawWindowIsAncestor(GWindow ancester, GWindow descendent);
+extern void GDrawSetUserData(GWindow gw, void *ud);
+extern void *GDrawGetUserData(GWindow gw);
+extern GDisplay *GDrawGetDisplayOfWindow(GWindow);
+extern void GDrawTranslateCoordinates(GWindow from,GWindow to, GPoint *pt);
+extern int32 GDrawEventInWindow(GWindow inme,GEvent *event);
+extern void GDrawBeep(GDisplay *gdisp);
+extern void GDrawFlush(GDisplay *gdisp);
+
+extern void GDrawGetClip(GWindow w, GRect *ret);
+extern void GDrawSetClip(GWindow w, GRect *rct);
+extern void GDrawPushClip(GWindow w, GRect *rct, GRect *old);
+extern void GDrawPopClip(GWindow w, GRect *old);
+extern GGC *GDrawGetWindowGGC(GWindow w);
+extern void GDrawSetXORBase(GWindow w,Color col);
+extern void GDrawSetXORMode(GWindow w);
+extern void GDrawSetCopyMode(GWindow w);
+extern void GDrawSetCopyThroughSubWindows(GWindow w,int16 through);
+extern void GDrawSetDashedLine(GWindow w,int16 dash_len, int16 skip_len, int16 off);
+extern void GDrawSetStippled(GWindow w,int16 ts, int32 yoff,int32 xoff);
+extern void GDrawSetLineWidth(GWindow w,int16 width);
+extern void GDrawSetForeground(GWindow w,Color col);
+extern void GDrawSetBackground(GWindow w,Color col);
+
+extern GFont *GDrawSetFont(GWindow gw, GFont *fi);
+extern GFont *GDrawInstanciateFont(GDisplay *disp, FontRequest *rq);
+extern GFont *GDrawAttachFont(GWindow gw, FontRequest *rq);
+extern FontRequest *GDrawDecomposeFont(GFont *fi, FontRequest *rq);
+extern enum charset GDrawFindEncoding(unichar_t *text, int32 len,
+ GFont *fi, unichar_t **next, int *ulevel);
+extern void GDrawFontMetrics(GFont *fi,int *as, int *ds, int *ld);
+extern int32 GDrawGetTextPtAfterPos(GWindow gw,unichar_t *text, int32 cnt, FontMods *mods,
+ int32 maxwidth, unichar_t **end);
+extern int32 GDrawGetTextPtBeforePos(GWindow gw,unichar_t *text, int32 cnt, FontMods *mods,
+ int32 maxwidth, unichar_t **end);
+extern int32 GDrawGetTextPtFromPos(GWindow gw,unichar_t *text, int32 cnt, FontMods *mods,
+ int32 maxwidth, unichar_t **end);
+int32 GDrawGetTextBounds(GWindow gw,unichar_t *text, int32 cnt, FontMods *mods,
+ GTextBounds *size);
+extern int32 GDrawGetTextWidth(GWindow gw, const unichar_t *text, int32 cnt, FontMods *mods);
+extern int32 GDrawDrawText(GWindow gw, int32 x, int32 y, const unichar_t *txt, int32 cnt, FontMods *mods, Color col);
+/* Routines that handle bidirectional text */
+/* (slower than the equivalent left to right routines) */
+extern int32 GDrawDrawBiText(GWindow gw, int32 x, int32 y, unichar_t *txt, int32 cnt, FontMods *mods, Color col);
+extern int32 GDrawGetBiTextWidth(GWindow gw,unichar_t *text, int len, int32 cnt, FontMods *mods);
+extern int32 GDrawGetBiTextPtAfterPos(GWindow gw,unichar_t *text, int32 cnt, FontMods *mods,
+ int32 maxwidth, unichar_t **end);
+extern int32 GDrawGetBiTextPtBeforePos(GWindow gw,unichar_t *text, int32 cnt, FontMods *mods,
+ int32 maxwidth, unichar_t **end);
+extern int32 GDrawGetBiTextPtFromPos(GWindow gw,unichar_t *text, int32 cnt, FontMods *mods,
+ int32 maxwidth, unichar_t **end);
+extern int GDrawFontHasCharset(FontInstance *fi,/*enum charset*/int charset);
+extern int32 GDrawIsAllLeftToRight(unichar_t *text, int32 cnt);
+extern void GDrawBiText1(GBiText *bd, const unichar_t *text, int32 cnt);
+extern void GDrawArabicForms(GBiText *bd, int32 start, int32 end);
+extern void _GDrawBiText2(GBiText *bd, int32 start, int32 end);
+extern void GDrawBiText2(GBiText *bd, int32 start, int32 end);
+/* UTF8 routines */
+extern int32 GDrawGetText8PtAfterPos(GWindow gw,char *text, int32 cnt, FontMods *mods,
+ int32 maxwidth, char **end);
+extern int32 GDrawGetText8PtBeforePos(GWindow gw,char *text, int32 cnt, FontMods *mods,
+ int32 maxwidth, char **end);
+extern int32 GDrawGetText8PtFromPos(GWindow gw,char *text, int32 cnt, FontMods *mods,
+ int32 maxwidth, char **end);
+int32 GDrawGetText8Bounds(GWindow gw,char *text, int32 cnt, FontMods *mods,
+ GTextBounds *size);
+extern int32 GDrawGetText8Width(GWindow gw, const char *text, int32 cnt, FontMods *mods);
+extern int32 GDrawDrawText8(GWindow gw, int32 x, int32 y, const char *txt, int32 cnt, FontMods *mods, Color col);
+
+extern GIC *GDrawCreateInputContext(GWindow w,enum gic_style def_style);
+extern void GDrawSetGIC(GWindow w,GIC *gic,int x, int y);
+
+extern void GDrawClear(GWindow w, GRect *rect);
+extern void GDrawDrawLine(GWindow w, int32 x,int32 y, int32 xend,int32 yend, Color col);
+extern void GDrawDrawArrow(GWindow w, int32 x,int32 y, int32 xend,int32 yend, int arrows, Color col);
+extern void GDrawDrawRect(GWindow w, GRect *rect, Color col);
+extern void GDrawFillRect(GWindow w, GRect *rect, Color col);
+extern void GDrawDrawElipse(GWindow w, GRect *rect, Color col);
+extern void GDrawFillElipse(GWindow w, GRect *rect, Color col);
+extern void GDrawDrawArc(GWindow w, GRect *rect, int32 sangle, int32 tangle, Color col);
+extern void GDrawDrawPoly(GWindow w, GPoint *pts, int16 cnt, Color col);
+extern void GDrawFillPoly(GWindow w, GPoint *pts, int16 cnt, Color col);
+extern void GDrawScroll(GWindow w, GRect *rect, int32 hor, int32 vert);
+extern void GDrawDrawImage(GWindow w, GImage *img, GRect *src, int32 x, int32 y);
+extern void GDrawDrawScaledImage(GWindow w, GImage *img, int32 x, int32 y);
+extern void GDrawDrawImageMagnified(GWindow w, GImage *img, GRect *src, int32 x, int32 y,
+ int32 width, int32 height);
+extern void GDrawTileImage(GWindow w, GImage *img, GRect *src, int32 x, int32 y);
+extern void GDrawDrawPixmap(GWindow w, GWindow pixmap, GRect *src, int32 x, int32 y);
+extern void GDrawTilePixmap(GWindow w, GWindow pixmap, GRect *src, int32 x, int32 y);
+extern GImage *GDrawCopyScreenToImage(GWindow w, GRect *rect);
+
+extern void GDrawGrabSelection(GWindow w,enum selnames sel);
+extern void GDrawAddSelectionType(GWindow w,enum selnames sel,char *type,
+ void *data,int32 cnt,int32 unitsize,void *(*gendata)(void *,int32 *len),
+ void (*freedata)(void *));
+extern void *GDrawRequestSelection(GWindow w,enum selnames sn, char *typename, int32 *len);
+extern int GDrawSelectionHasType(GWindow w,enum selnames sn, char *typename);
+
+extern void GDrawPointerUngrab(GDisplay *disp);
+extern void GDrawPointerGrab(GWindow w);
+extern int GDrawEnableExposeRequests(GWindow w,int enabled);
+extern void GDrawRequestExpose(GWindow w, GRect *rect, int doclear);
+extern void GDrawSync(GDisplay *gdisp);
+extern void GDrawForceUpdate(GWindow w);
+extern void GDrawProcessOneEvent(GDisplay *disp);
+extern void GDrawProcessPendingEvents(GDisplay *disp);
+extern void GDrawProcessWindowEvents(GWindow w);
+extern void GDrawSkipMouseMoveEvents(GWindow w,GEvent *last);
+extern void GDrawEventLoop(GDisplay *disp);
+extern void GDrawPostEvent(GEvent *e);
+extern void GDrawPostDragEvent(GWindow gw,GEvent *e,enum event_type);
+
+extern GTimer *GDrawRequestTimer(GWindow w,int32 time_from_now,int32 frequency,
+ void *userdata);
+extern void GDrawCancelTimer(GTimer *timer);
+
+extern void GDrawSyncThread(GDisplay *gd, void (*func)(void *), void *data);
+
+extern GWindow GPrinterStartJob(GDisplay *gdisp,void *user_data,GPrinterAttrs *attrs);
+extern void GPrinterNextPage(GWindow w);
+extern int GPrinterEndJob(GWindow w,int cancel);
+
+extern void GDrawSetBuildCharHooks(void (*hook)(GDisplay *), void (*inshook)(GDisplay *,unichar_t));
+
+extern int GDrawRequestDeviceEvents(GWindow w,int devcnt,struct gdeveventmask *de);
+
+extern void GDrawFatalError(const char *fmt,...);
+extern void GDrawIError(const char *fmt,...);
+extern void GDrawError(const char *fmt,...);
+
+extern GImage *GImageCreate(enum image_type type, int32 width, int32 height);
+extern GImage *_GImage_Create(enum image_type type, int32 width, int32 height);
+extern void GImageDestroy(GImage *gi);
+extern GImage *GImageCreateAnimation(GImage **images, int n);
+extern GImage *GImageAddImageBefore(GImage *dest, GImage *src, int pos);
+
+extern GImage *GImageBaseGetSub(struct _GImage *base, enum image_type it, GRect *src, GClut *nclut, RevCMap *rev);
+extern GImage *GImageGetSub(GImage *image,enum image_type it, GRect *src, GClut *nclut, RevCMap *rev);
+extern int GImageInsertToBase(struct _GImage *tobase, GImage *from, GRect *src, RevCMap *rev,
+ int to_x, int to_y, enum pastetrans_type ptt );
+extern int GImageInsert(GImage *to, GImage *from, GRect *src, RevCMap *rev,
+ int to_x, int to_y, enum pastetrans_type ptt );
+extern Color GImageGetPixelColor(GImage *base,int x, int y);
+extern int GImageGetWidth(GImage *);
+extern int GImageGetHeight(GImage *);
+extern int GImageGetScaledWidth(GWindow gw, GImage *img);
+extern int GImageGetScaledHeight(GWindow gw, GImage *img);
+extern void *GImageGetUserData(GImage *img);
+extern void GImageSetUserData(GImage *img,void *userdata);
+extern void GImageResize(struct _GImage *tobase, struct _GImage *fbase,
+ GRect *src, RevCMap *rev);
+extern GImage *GImageResize32(GImage *from, GRect *src, int width, int height, Color trans);
+extern GImage *GImageResizeSame(GImage *from, GRect *src, int width, int height, RevCMap *rev);
+extern RevCMap *GClutReverse(GClut *clut,int side_size);
+void GClut_RevCMapFree(RevCMap *rev);
+extern GClut *GImageFindCLUT(GImage *image,GClut *clut,int clutmax);
+extern int GImageSameClut(GClut *clut,GClut *nclut);
+extern int GImageGreyClut(GClut *clut);
+extern Color GImageColourFName(unichar_t *name);
+extern Color _GImage_ColourFName(char *name);
+extern char *GImageNameFColour(Color col);
+extern Color GDrawColorDarken(Color col, int by);
+extern Color GDrawColorBrighten(Color col, int by);
+
+extern int GImageWriteGImage(GImage *gi, char *filename);
+extern int GImageWriteBmp(GImage *gi, char *filename);
+extern GImage *GImageRead_Bmp(FILE *file);
+extern GImage *GImageReadBmp(char *filename);
+extern int GImageWriteXbm(GImage *gi, char *filename);
+extern GImage *GImageReadXbm(char *filename);
+extern int GImageWriteXpm(GImage *gi, char *filename);
+extern GImage *GImageReadXpm(char *filename);
+extern int GImageWriteEps(GImage *gi, char *filename);
+extern GImage *GImageReadTiff(char *filename);
+extern GImage *GImageReadJpeg(char *filename);
+extern int GImageWriteJpeg(GImage *gi, char *filename, int quality, int progressive);
+extern GImage *GImageRead_Png(FILE *fp);
+extern GImage *GImageReadPng(char *filename);
+extern int GImageWritePng(GImage *gi, char *filename, int progressive);
+extern GImage *GImageReadGif(char *filename);
+extern int GImageWriteGif(GImage *gi,char *filename,int progressive);
+extern GImage *GImageReadRas(char *filename); /* Sun Raster */
+extern GImage *GImageReadRgb(char *filename); /* SGI */
+extern GImage *GImageRead(char *filename);
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/inc/gfile.h b/Build/source/libs/luafontforge/fontforge/inc/gfile.h
new file mode 100644
index 00000000000..8a8ee5bcaca
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/gfile.h
@@ -0,0 +1,62 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _GFILE_H
+#define _GFILE_H
+
+extern char *GFileGetAbsoluteName(char *name, char *result, int rsiz);
+extern char *GFileMakeAbsoluteName(char *name);
+extern char *GFileBuildName(char *dir,char *fname,char *buffer,int size);
+extern char *GFileReplaceName(char *oldname,char *fname,char *buffer,int size);
+extern char *GFileNameTail(const char *oldname);
+extern char *GFileAppendFile(char *dir,char *name,int isdir);
+extern int GFileIsAbsolute(const char *file);
+extern int GFileIsDir(const char *file);
+extern int GFileExists(const char *file);
+extern int GFileModifyable(const char *file);
+extern int GFileModifyableDir(const char *file);
+extern int GFileReadable(char *file);
+extern int GFileMkDir(char *name);
+extern int GFileRmDir(char *name);
+extern int GFileUnlink(char *name);
+extern char *_GFile_find_program_dir(char *prog);
+extern unichar_t *u_GFileGetAbsoluteName(unichar_t *name, unichar_t *result, int rsiz);
+extern unichar_t *u_GFileBuildName(unichar_t *dir,unichar_t *fname,unichar_t *buffer,int size);
+extern unichar_t *u_GFileReplaceName(unichar_t *oldname,unichar_t *fname,unichar_t *buffer,int size);
+extern unichar_t *u_GFileNameTail(const unichar_t *oldname);
+extern unichar_t *u_GFileNormalize(unichar_t *name);
+extern unichar_t *u_GFileAppendFile(unichar_t *dir,unichar_t *name,int isdir);
+extern int u_GFileIsAbsolute(const unichar_t *file);
+extern int u_GFileIsDir(const unichar_t *file);
+extern int u_GFileExists(const unichar_t *file);
+extern int u_GFileModifyable(const unichar_t *file);
+extern int u_GFileModifyableDir(const unichar_t *file);
+extern int u_GFileReadable(unichar_t *file);
+extern int u_GFileMkDir(unichar_t *name);
+extern int u_GFileRmDir(unichar_t *name);
+extern int u_GFileUnlink(unichar_t *name);
+
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/inc/ggadget.h b/Build/source/libs/luafontforge/fontforge/inc/ggadget.h
new file mode 100644
index 00000000000..90e69ddb5a2
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/ggadget.h
@@ -0,0 +1,484 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _GGADGET_H
+#define _GGADGET_H
+
+#include "gdraw.h"
+#include "intl.h"
+struct giocontrol;
+
+typedef struct gtextinfo {
+ unichar_t *text;
+ GImage *image;
+ Color fg;
+ Color bg;
+ void *userdata;
+ GFont *font;
+ unsigned int disabled: 1;
+ unsigned int image_precedes: 1;
+ unsigned int checkable: 1; /* Only for menus */
+ unsigned int checked: 1; /* Only for menus */
+ unsigned int selected: 1; /* Only for lists (used internally for menu(bar)s, when cursor is on the line) */
+ unsigned int line: 1; /* Only for menus */
+ unsigned int text_is_1byte: 1; /* If passed in as 1byte (ie. iso-8859-1) text, will be converted */
+ unsigned int text_in_resource: 1; /* the text field is actually an index into the string resource table */
+ unsigned int changed: 1; /* If a row/column widget changed this */
+ unichar_t mnemonic; /* Only for menus and menubars */
+ /* should really be in menuitem, but that wastes space and complicates GTextInfoDraw */
+} GTextInfo;
+
+typedef struct gmenuitem {
+ GTextInfo ti;
+ unichar_t shortcut;
+ short short_mask;
+ struct gmenuitem *sub;
+ void (*moveto)(struct gwindow *base,struct gmenuitem *mi,GEvent *); /* called before creating submenu */
+ void (*invoke)(struct gwindow *base,struct gmenuitem *mi,GEvent *); /* called on mouse release */
+ int mid;
+} GMenuItem;
+
+typedef struct gmenuitem2 {
+ GTextInfo ti;
+ char *shortcut;
+ struct gmenuitem2 *sub;
+ void (*moveto)(struct gwindow *base,struct gmenuitem *mi,GEvent *); /* called before creating submenu */
+ void (*invoke)(struct gwindow *base,struct gmenuitem *mi,GEvent *); /* called on mouse release */
+ int mid;
+} GMenuItem2;
+
+typedef struct tabinfo {
+ unichar_t *text;
+ struct ggadgetcreatedata *gcd;
+ unsigned int disabled: 1;
+ unsigned int selected: 1;
+ unsigned int text_is_1byte: 1; /* If passed in as 1byte (ie. iso-8859-1) text, will be converted */
+ unsigned int text_in_resource: 1; /* the text field is actually an index into the string resource table */
+ unsigned char nesting;
+} GTabInfo;
+
+enum border_type { bt_none, bt_box, bt_raised, bt_lowered, bt_engraved,
+ bt_embossed, bt_double };
+enum border_shape { bs_rect, bs_roundrect, bs_elipse, bs_diamond };
+enum box_flags {
+ box_foreground_border_inner = 1, /* 1 point line */
+ box_foreground_border_outer = 2, /* 1 point line */
+ box_active_border_inner = 4, /* 1 point line */
+ box_foreground_shadow_outer = 8, /* 1 point line, bottom&right */
+ box_do_depressed_background = 0x10,
+ box_draw_default = 0x20, /* if a default button draw a depressed rect around button */
+ box_generate_colors = 0x40 /* use border_brightest to compute other border cols */
+ };
+typedef struct gbox {
+ unsigned char border_type;
+ unsigned char border_shape;
+ unsigned char border_width; /* In points */
+ unsigned char padding; /* In points */
+ unsigned char rr_radius; /* In points */
+ unsigned char flags;
+ Color border_brightest; /* used for left upper part of elipse */
+ Color border_brighter;
+ Color border_darkest; /* used for right lower part of elipse */
+ Color border_darker;
+ Color main_background;
+ Color main_foreground;
+ Color disabled_background;
+ Color disabled_foreground;
+ Color active_border;
+ Color depressed_background;
+} GBox;
+
+typedef struct ggadget GGadget;
+typedef struct ggadget *GGadgetSet;
+
+enum sb_type { sb_upline, sb_downline, sb_uppage, sb_downpage, sb_track, sb_trackrelease };
+
+typedef int (*GGadgetHandler)(GGadget *,GEvent *);
+
+typedef struct ggadgetdata {
+ GRect pos;
+ GBox *box;
+ unichar_t mnemonic;
+ unichar_t shortcut;
+ uint8 short_mask;
+ uint8 cols; /* for rowcol */
+ short cid;
+ GTextInfo *label; /* Overloaded with a GGadgetCreateData * for hvboxes (their label is a gadget) */
+ union {
+ GTextInfo *list; /* for List Widgets (and ListButtons, RowCols etc) */
+ GTabInfo *tabs; /* for Tab Widgets */
+ GMenuItem *menu; /* for menus */
+ GMenuItem2 *menu2; /* for menus (alternate) */
+ struct ggadgetcreatedata **boxelements; /* An array of things to go in the box */
+ struct matrixinit *matrix;
+ GDrawEH drawable_e_h; /* Drawable event handler */
+ } u;
+ enum gg_flags { gg_visible=1, gg_enabled=2, gg_pos_in_pixels=4,
+ gg_sb_vert=8, gg_line_vert=gg_sb_vert,
+ gg_but_default=0x10, gg_but_cancel=0x20,
+ gg_cb_on=0x40, gg_rad_startnew=0x80,
+ gg_rad_continueold=0x100, /* even if not previous */
+ gg_list_alphabetic=0x100, gg_list_multiplesel=0x200,
+ gg_list_exactlyone=0x400, gg_list_internal=0x800,
+ gg_group_prevlabel=0x1000, gg_group_end=0x2000,
+ gg_textarea_wrap=0x4000,
+ gg_tabset_scroll=0x8000, gg_tabset_filllines=0x10000, gg_tabset_fill1line = 0x20000,
+ gg_tabset_nowindow=gg_textarea_wrap,
+ gg_rowcol_alphabetic=gg_list_alphabetic,
+ gg_rowcol_vrules=0x40000, gg_rowcol_hrules=0x800000,
+ gg_rowcol_displayonly=0x1000000,
+ gg_dontcopybox=0x10000000,
+ gg_pos_use0=0x20000000, gg_pos_under=0x40000000,
+ gg_pos_newline = (int) 0x80000000,
+ /* Reuse some flag values for different widgets */
+ gg_file_pulldown=gg_sb_vert, gg_file_multiple = gg_list_multiplesel,
+ gg_text_xim = gg_tabset_scroll,
+ gg_tabset_vert = gg_sb_vert,
+ gg_utf8_popup = gg_rowcol_displayonly
+ } flags;
+ const unichar_t *popup_msg; /* Brief help message */
+ GGadgetHandler handle_controlevent;
+} GGadgetData;
+
+typedef struct ggadgetcreatedata {
+ GGadget *(*creator)(struct gwindow *base, GGadgetData *gd,void *data);
+ GGadgetData gd;
+ void *data;
+ GGadget *ret;
+} GGadgetCreateData;
+
+#define GCD_Glue ((GGadgetCreateData *) -1) /* Special entries */
+#define GCD_ColSpan ((GGadgetCreateData *) -2) /* for box elements */
+#define GCD_RowSpan ((GGadgetCreateData *) -3)
+#define GCD_HPad10 ((GGadgetCreateData *) -4)
+
+enum ghvbox_expand { gb_expandglue=-4, gb_expandgluesame=-3, gb_samesize=-2,
+ gb_expandall=-1 };
+enum editor_commands { ec_cut, ec_clear, ec_copy, ec_paste, ec_undo, ec_redo,
+ ec_selectall, ec_search, ec_backsearch, ec_backword, ec_deleteword,
+ ec_max };
+
+ /* return values from file chooser filter functions */
+enum fchooserret { fc_hide, fc_show, fc_showdisabled };
+
+struct matrixinit {
+ int col_cnt;
+ struct col_init {
+ enum me_type { me_int, me_enum, me_real, me_string, me_bigstr, me_func,
+ me_funcedit,
+ me_stringchoice, me_stringchoicetrans, me_stringchoicetag } me_type;
+ char *(*func)(GGadget *,int r,int c);
+ GTextInfo *enum_vals;
+ void (*enable_enum)(GGadget *,GMenuItem *, int r, int c);
+ char *title;
+ } *col_init;
+ int initial_row_cnt;
+ struct matrix_data {
+ union {
+ intpt md_ival;
+ double md_real;
+ char *md_str;
+ } u;
+ uint8 frozen;
+ uint8 user_bits;
+ uint8 current;
+ } *matrix_data;
+ void (*initrow)(GGadget *g,int row);
+ int (*candelete)(GGadget *g,int row);
+ void (*finishedit)(GGadget *g,int r, int c, int wasnew);
+ void (*popupmenu)(GGadget *g,GEvent *e,int row,int col);
+ int (*handle_key)(GGadget *g,GEvent *e);
+ char *(*bigedittitle)(GGadget *g,int r, int c);
+};
+
+#define GME_NoChange 0x80000000
+
+struct gdirentry;
+typedef enum fchooserret (*GFileChooserFilterType)(GGadget *g,struct gdirentry *ent,
+ const unichar_t *dir);
+
+#define _STR_NULL (-1) /* Null string resource */
+#define _STR_Language 0
+#define _STR_OK 1
+#define _STR_Cancel 2
+#define _STR_Open 3
+#define _STR_Save 4
+#define _STR_Filter 5
+#define _STR_New 6
+#define _STR_Replace 7
+#define _STR_Fileexists 8
+#define _STR_Fileexistspre 9
+#define _STR_Fileexistspost 10
+#define _STR_Createdir 11
+#define _STR_Dirname 12
+#define _STR_Couldntcreatedir 13
+#define _STR_SelectAll 14
+#define _STR_None 15
+#define __STR_LastStd 15
+
+#define _NUM_Buttonsize 0
+#define _NUM_ScaleFactor 1
+#define __NUM_LastStd 1
+
+extern void GTextInfoFree(GTextInfo *ti);
+extern void GTextInfoListFree(GTextInfo *ti);
+extern void GTextInfoArrayFree(GTextInfo **ti);
+extern GTextInfo **GTextInfoFromChars(char **array, int len);
+extern const unichar_t *GStringGetResource(int index,unichar_t *mnemonic);
+extern int GGadgetScale(int xpos);
+extern int GIntGetResource(int index);
+extern int GStringSetResourceFileV(char *filename,uint32 checksum);
+extern int GStringSetResourceFile(char *filename); /* returns 1 for success, 0 for failure */
+/* fallback string arrays are null terminated. mnemonics is same length as string */
+/* fallback integer arrays are terminated by 0x80000000 (negative infinity) */
+extern void GStringSetFallbackArray(const unichar_t **array,const unichar_t *mn,
+ const int *ires);
+unichar_t *GStringFileGetResource(char *filename, int index,unichar_t *mnemonic);
+extern void GResourceUseGetText(void);
+
+void GGadgetDestroy(GGadget *g);
+void GGadgetSetVisible(GGadget *g,int visible);
+int GGadgetIsVisible(GGadget *g);
+void GGadgetSetEnabled(GGadget *g,int enabled);
+int GGadgetIsEnabled(GGadget *g);
+GWindow GGadgetGetWindow(GGadget *g);
+void *GGadgetGetUserData(GGadget *g);
+void GGadgetSetUserData(GGadget *g, void *d);
+void GGadgetSetPopupMsg(GGadget *g, const unichar_t *msg);
+GRect *GGadgetGetInnerSize(GGadget *g,GRect *rct);
+GRect *GGadgetGetSize(GGadget *g,GRect *rct);
+void GGadgetGetDesiredSize(GGadget *g,GRect *outer, GRect *inner);
+void GGadgetSetDesiredSize(GGadget *g,GRect *outer, GRect *inner);
+int GGadgetGetCid(GGadget *g);
+void GGadgetResize(GGadget *g,int32 width, int32 height );
+void GGadgetMove(GGadget *g,int32 x, int32 y );
+void GGadgetRedraw(GGadget *g);
+void GGadgetsCreate(GWindow base, GGadgetCreateData *gcd);
+int GGadgetFillsWindow(GGadget *g);
+int GGadgetIsDefault(GGadget *g);
+
+void GGadgetSetTitle(GGadget *g,const unichar_t *title);
+void GGadgetSetTitle8(GGadget *g,const char *title);
+const unichar_t *_GGadgetGetTitle(GGadget *g); /* Do not free!!! */
+unichar_t *GGadgetGetTitle(GGadget *g); /* Free the return */
+char *GGadgetGetTitle8(GGadget *g); /* Free the return (utf8) */
+void GGadgetSetFont(GGadget *g,GFont *font);
+GFont *GGadgetGetFont(GGadget *g);
+int GGadgetEditCmd(GGadget *g,enum editor_commands cmd);
+int GGadgetActiveGadgetEditCmd(GWindow gw,enum editor_commands cmd);
+void GGadgetSetHandler(GGadget *g, GGadgetHandler handler);
+GGadgetHandler GGadgetGetHandler(GGadget *g);
+
+void GTextFieldSelect(GGadget *g,int sel_start, int sel_end);
+void GTextFieldShow(GGadget *g,int pos);
+void GTextFieldReplace(GGadget *g,const unichar_t *txt);
+void GGadgetClearList(GGadget *g);
+void GGadgetSetList(GGadget *g, GTextInfo **ti, int32 copyit);
+GTextInfo **GGadgetGetList(GGadget *g,int32 *len); /* Do not free!!! */
+GTextInfo *GGadgetGetListItem(GGadget *g,int32 pos);
+GTextInfo *GGadgetGetListItemSelected(GGadget *g);
+void GGadgetSelectListItem(GGadget *g,int32 pos,int32 sel);
+void GGadgetSelectOneListItem(GGadget *g,int32 pos);
+int32 GGadgetIsListItemSelected(GGadget *g,int32 pos);
+int32 GGadgetGetFirstListSelectedItem(GGadget *g);
+void GGadgetScrollListToPos(GGadget *g,int32 pos);
+void GGadgetScrollListToText(GGadget *g,const unichar_t *lab,int32 sel);
+void GGadgetSetListOrderer(GGadget *g,int (*orderer)(const void *, const void *));
+
+void GGadgetSetChecked(GGadget *g, int ison);
+int GGadgetIsChecked(GGadget *g);
+
+int GListIndexFromY(GGadget *g,int y);
+void GListSetSBAlwaysVisible(GGadget *g,int always);
+void GListSetPopupCallback(GGadget *g,void (*callback)(GGadget *,int));
+
+int GTabSetGetSel(GGadget *g);
+void GTabSetSetSel(GGadget *g,int sel);
+void GTabSetSetEnabled(GGadget *g,int pos, int enabled);
+GWindow GTabSetGetSubwindow(GGadget *g,int pos);
+int GTabSetGetTabLines(GGadget *g);
+void GTabSetSetNestedExpose(GGadget *g, void (*)(GWindow,GGadget *,GEvent *));
+void GTabSetSetNestedMouse(GGadget *g, int (*)(GGadget *,GEvent *));
+void GTabSetChangeTabName(GGadget *g, char *name, int pos);
+void GTabSetRemetric(GGadget *g);
+
+int32 GScrollBarGetPos(GGadget *g);
+int32 GScrollBarSetPos(GGadget *g,int32 pos);
+void GScrollBarSetMustShow(GGadget *g, int32 sb_min, int32 sb_max, int32 sb_pagesize,
+ int32 sb_mustshow);
+void GScrollBarSetBounds(GGadget *g, int32 sb_min, int32 sb_max, int32 sb_pagesize );
+void GScrollBarGetBounds(GGadget *g, int32 *sb_min, int32 *sb_max, int32 *sb_pagesize );
+
+void GMenuBarSetItemChecked(GGadget *g, int mid, int check);
+void GMenuBarSetItemEnabled(GGadget *g, int mid, int enabled);
+void GMenuBarSetItemName(GGadget *g, int mid, const unichar_t *name);
+void GMenuSetShortcutDomain(char *domain);
+const char *GMenuGetShortcutDomain(void);
+
+
+void GFileChooserPopupCheck(GGadget *g,GEvent *e);
+void GFileChooserFilterIt(GGadget *g);
+void GFileChooserRefreshList(GGadget *g);
+int GFileChooserFilterEh(GGadget *g,GEvent *e);
+void GFileChooserConnectButtons(GGadget *g,GGadget *ok, GGadget *filter);
+void GFileChooserSetFilterText(GGadget *g,const unichar_t *filter);
+void GFileChooserSetFilterFunc(GGadget *g,GFileChooserFilterType filter);
+void GFileChooserSetDir(GGadget *g,unichar_t *dir);
+struct giocontrol *GFileChooserReplaceIO(GGadget *g,struct giocontrol *gc);
+unichar_t *GFileChooserGetDir(GGadget *g);
+unichar_t *GFileChooserGetFilterText(GGadget *g);
+GFileChooserFilterType GFileChooserGetFilterFunc(GGadget *g);
+void GFileChooserSetMimetypes(GGadget *g,unichar_t **mimetypes);
+unichar_t **GFileChooserGetMimetypes(GGadget *g);
+void GFileChooserGetChildren(GGadget *g,GGadget **pulldown, GGadget **list, GGadget **tf);
+int GFileChooserPosIsDir(GGadget *g, int pos);
+unichar_t *GFileChooserFileNameOfPos(GGadget *g, int pos);
+
+void GHVBoxSetExpandableCol(GGadget *g,int col);
+void GHVBoxSetExpandableRow(GGadget *g,int row);
+void GHVBoxSetPadding(GGadget *g,int hpad, int vpad);
+void GHVBoxFitWindow(GGadget *g);
+
+void GMatrixEditSet(GGadget *g,struct matrix_data *data, int rows, int copy_it);
+struct matrix_data *GMatrixEditGet(GGadget *g, int *rows);
+struct matrix_data *_GMatrixEditGet(GGadget *g, int *rows);
+GGadget *_GMatrixEditGetActiveTextField(GGadget *g);
+int GMatrixEditGetColCnt(GGadget *g);
+int GMatrixEditGetActiveRow(GGadget *g);
+int GMatrixEditGetActiveCol(GGadget *g);
+void GMatrixEditDeleteRow(GGadget *g,int row);
+int GMatrixEditStringDlg(GGadget *g,int row,int col);
+void GMatrixEditSetNewText(GGadget *g, char *text);
+void GMatrixEditSetOtherButtonEnable(GGadget *g, void (*sob)(GGadget *g, int r, int c));
+void GMatrixEditSetMouseMoveReporter(GGadget *g, void (*rmm)(GGadget *g, int r, int c));
+void GMatrixEditSetTextChangeReporter(GGadget *g, void (*tcr)(GGadget *g, int r, int c, GGadget *text));
+void GMatrixEditSetValidateStr(GGadget *g, char *(*validate)(GGadget *g, int r, int c, int wasnew, char *str));
+void GMatrixEditUp(GGadget *g);
+void GMatrixEditDown(GGadget *g);
+void GMatrixEditSetUpDownVisible(GGadget *g, int enabled);
+void GMatrixEditAddButtons(GGadget *g, GGadgetCreateData *gcd);
+void GMatrixEditEnableColumn(GGadget *g, int col, int enabled);
+void GMatrixEditShowColumn(GGadget *g, int col, int visible);
+void GMatrixEditSetColumnChoices(GGadget *g, int col, GTextInfo *ti);
+
+GWindow GDrawableGetWindow(GGadget *g);
+
+
+extern void GGadgetPreparePopupImage(GWindow base,const unichar_t *msg,
+ const void *data,
+ GImage *(*get_image)(const void *data),
+ void (*free_image)(const void *data,GImage *img));
+extern void GGadgetPreparePopup(GWindow base,const unichar_t *msg);
+extern void GGadgetPreparePopupR(GWindow base,int msg);
+extern void GGadgetPreparePopup8(GWindow base,char *msg);
+extern void GGadgetEndPopup(void);
+extern void GGadgetPopupExternalEvent(GEvent *e);
+
+extern int GGadgetDispatchEvent(GGadget *g,GEvent *e);
+extern void GGadgetTakesKeyboard(GGadget *g, int takes_keyboard);
+
+/* Handles *?{}[] wildcards */
+int GGadgetWildMatch(unichar_t *pattern, unichar_t *name,int ignorecase);
+enum fchooserret GFileChooserDefFilter(GGadget *g,struct gdirentry *ent,
+ const unichar_t *dir);
+
+GWindow GMenuCreatePopupMenu(GWindow owner,GEvent *event, GMenuItem *mi);
+GWindow _GMenuCreatePopupMenu(GWindow owner,GEvent *event, GMenuItem *mi,
+ void (*donecallback)(GWindow owner));
+
+GGadget *GLineCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GGroupCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GSpacerCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GLabelCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GButtonCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GImageButtonCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GListButtonCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GRadioCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GCheckBoxCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GScrollBarCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GListCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GTextFieldCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GPasswordCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GNumericFieldCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GTextAreaCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GListFieldCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GMenuBarCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GMenu2BarCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GTabSetCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GFileChooserCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GHBoxCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GVBoxCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GHVBoxCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GHVGroupCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GMatrixEditCreate(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *GDrawableCreate(struct gwindow *base, GGadgetData *gd,void *data);
+
+GGadget *CreateSlider(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *CreateFileChooser(struct gwindow *base, GGadgetData *gd,void *data);
+GGadget *CreateGadgets(struct gwindow *base, GGadgetCreateData *gcd);
+
+GTextInfo **GTextInfoArrayFromList(GTextInfo *ti, uint16 *cnt);
+
+extern unichar_t *utf82u_mncopy(const char *utf8buf,unichar_t *mn);
+
+#if 0
+void GadgetRedraw(Gadget *g);
+void GadgetSetBox(Gadget *g,Box *b);
+Box *GadgetGetBox(Gadget *g);
+Rect *GadgetGetPos(Gadget *g);
+void GadgetMove(Gadget *g, int x, int y);
+void GadgetResize(Gadget *g, int width, int height);
+void GadgetReposition(Gadget *g, Rect *r);
+void GadgetSetVisible(Gadget *g, int visible);
+int GadgetIsVisible(Gadget *g);
+void GadgetSetEnabled(Gadget *g, int enabled);
+int GadgetIsEnabled(Gadget *g);
+void GadgetSetFocus(Gadget *g);
+int GadgetHasFocus(Gadget *g);
+void GadgetSetMnemonic(Gadget *g, int ch);
+int GadgetGetMnemonic(Gadget *g);
+void GadgetSetAccel(Gadget *g, int ch, short mask);
+int GadgetGetAccelChar(Gadget *g);
+short GadgetGetAccelMask(Gadget *g);
+
+void GadgetSetTitle(Gadget *g,const unichar_t *title);
+unichar_t *GadgetGetTitle(Gadget *g);
+void GadgetSetFont(Gadget *g,GFont *font);
+GFont *GadgetGetFont(Gadget *g);
+
+void GadgetSetCheck(Gadget *g,int checked);
+int GadgetGetChecked(Gadget *g);
+
+void GadgetClearList(Gadget *g);
+void GadgetSetListTI(Gadget *g,GTextInfo *ti);
+void GadgetSetList(Gadget *g,unichar_t **list);
+void GadgetPrependToList(Gadget *g,unichar_t *
+
+void GadgetSetMenuItem(Gadget *,MenuItem *m);
+MenuItem *GadgetGetMenuItem(Gadget *);
+#endif
+
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/inc/gicons.h b/Build/source/libs/luafontforge/fontforge/inc/gicons.h
new file mode 100644
index 00000000000..ecf7d027c92
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/gicons.h
@@ -0,0 +1,52 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+extern GImage _GIcon_unknown;
+extern GImage _GIcon_object;
+extern GImage _GIcon_updir;
+extern GImage _GIcon_dir;
+extern GImage _GIcon_core;
+extern GImage _GIcon_image;
+extern GImage _GIcon_video;
+extern GImage _GIcon_audio;
+extern GImage _GIcon_texthtml;
+extern GImage _GIcon_textxml;
+extern GImage _GIcon_textjava;
+extern GImage _GIcon_textcss;
+extern GImage _GIcon_textplain;
+extern GImage _GIcon_textc;
+extern GImage _GIcon_textmake;
+extern GImage _GIcon_textfontbdf;
+extern GImage _GIcon_textfontps;
+extern GImage _GIcon_textfontsfd;
+extern GImage _GIcon_textps;
+extern GImage _GIcon_ttf;
+extern GImage _GIcon_cid;
+extern GImage _GIcon_mac;
+extern GImage _GIcon_macttf;
+extern GImage _GIcon_compressed;
+extern GImage _GIcon_tar;
+extern GImage _GIcon_homefolder;
diff --git a/Build/source/libs/luafontforge/fontforge/inc/gio.h b/Build/source/libs/luafontforge/fontforge/inc/gio.h
new file mode 100644
index 00000000000..b49ab8ddc87
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/gio.h
@@ -0,0 +1,109 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _GIO_H
+#define _GIO_H
+
+#include "basics.h"
+#include <time.h>
+
+typedef struct gauth {
+ unichar_t *username;
+ unichar_t *password;
+} GAuth;
+
+enum giofuncs { gf_dir, gf_statfile, gf_getfile, gf_putfile,
+ gf_mkdir, gf_delfile, gf_deldir, gf_renamefile,
+ /*gf_lockfile, gf_unlockfile,*/
+ gf_max };
+
+typedef struct giocontrol {
+ unichar_t *path;
+ unichar_t *origpath; /* what the user asked for (before any redirects), NULL if path doesn't change */
+ unichar_t *topath; /* for renames and copies */
+ GAuth auth;
+ void *userdata;
+ struct gio_connectiondata *connectiondata;
+ struct gio_threaddata *threaddata;
+ void *iodata;
+ void (*receivedata)(struct giocontrol *);
+ void (*receiveintermediate)(struct giocontrol *);
+ void (*receiveerror)(struct giocontrol *);
+ unsigned int done: 1;
+ unsigned int direntrydata: 1;
+ unsigned int abort: 1;
+ enum giofuncs gf;
+ int protocol_index;
+ struct giocontrol *next;
+ int return_code;
+ unichar_t *error;
+ unichar_t status[80];
+} GIOControl;
+
+typedef struct gdirentry {
+ unichar_t *name;
+ unichar_t *mimetype;
+ unsigned int isdir: 1;
+ unsigned int isexe: 1;
+ unsigned int islnk: 1;
+ unsigned int hasdir: 1;
+ unsigned int hasexe: 1;
+ unsigned int haslnk: 1;
+ unsigned int hasmode: 1;
+ unsigned int hassize: 1;
+ unsigned int hastime: 1;
+ unsigned int timezoneknown: 1; /* We got a time, but we don't know the timezone. might be off by 24 hours either way */
+ unsigned int fcdata: 2;
+ short mode;
+ uint32 size;
+ time_t modtime;
+ struct gdirentry *next;
+} GDirEntry;
+
+extern void GIOdir(GIOControl *gc);
+extern void GIOstatFile(GIOControl *gc);
+extern void GIOfileExists(GIOControl *gc);
+extern void GIOgetFile(GIOControl *gc);
+extern void GIOputFile(GIOControl *gc);
+extern void GIOmkDir(GIOControl *gc);
+extern void GIOdelFile(GIOControl *gc);
+extern void GIOdelDir(GIOControl *gc);
+extern void GIOrenameFile(GIOControl *gc);
+extern GDirEntry *GIOgetDirData(GIOControl *gc);
+extern int32 GIOread(GIOControl *gc,void *buffer,int32 len);
+extern int32 GIOwrite(GIOControl *gc,void *buffer,int32 len);
+extern void GIOFreeDirEntries(GDirEntry *lst);
+extern void GIOcancel(GIOControl *gc);
+extern void GIOclose(GIOControl *gc);
+extern GIOControl *GIOCreate(unichar_t *path,void *userdata,
+ void (*receivedata)(struct giocontrol *),
+ void (*receiveerror)(struct giocontrol *));
+extern void GIOSetDefAuthorizer(int32 (*getauth)(struct giocontrol *));
+extern void GIOSetUserAgent(unichar_t *agent);
+
+extern unichar_t *GIOguessMimeType(const unichar_t *path,int isdir);
+extern unichar_t *_GioMacMime(const char *path);
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/inc/gkeysym.h b/Build/source/libs/luafontforge/fontforge/inc/gkeysym.h
new file mode 100644
index 00000000000..7d4d2e59f5b
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/gkeysym.h
@@ -0,0 +1,298 @@
+#ifndef _GKEYSYM_H_
+#define _GKEYSYM_H_
+
+#ifndef X_DISPLAY_MISSING
+#include <X11/keysym.h>
+/* Based on the X keysymdef file */
+/***********************************************************
+Copyright 1987, 1994, 1998 The Open Group
+
+All Rights Reserved.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+#define GK_Special 0xfe00 /* keysyms above this value aren't unicode */
+#define GK_TypeAhead 0x0000 /* no single keysym, unicode value in event string */
+
+#define GK_BackSpace XK_BackSpace
+#define GK_Tab XK_Tab
+#ifndef XK_ISO_Left_Tab
+# define GK_BackTab XK_Tab
+#else
+# define GK_BackTab XK_ISO_Left_Tab
+#endif
+#define GK_Linefeed XK_Linefeed
+#define GK_Clear XK_Clear
+#define GK_Return XK_Return
+#define GK_Pause XK_Pause
+#define GK_Scroll_Lock XK_Scroll_Lock
+#define GK_Sys_Req XK_Sys_Req
+#define GK_Escape XK_Escape
+#define GK_Delete XK_Delete
+
+#define GK_Home XK_Home
+#define GK_Left XK_Left
+#define GK_Up XK_Up
+#define GK_Right XK_Right
+#define GK_Down XK_Down
+#define GK_Prior XK_Prior
+#define GK_Page_Up XK_Page_Up
+#define GK_Next XK_Next
+#define GK_Page_Down XK_Page_Down
+#define GK_End XK_End
+#define GK_Begin XK_Begin
+
+#define GK_Menu XK_Menu
+#define GK_Help XK_Help
+
+#define GK_KP_Enter XK_KP_Enter
+#define GK_KP_Home XK_KP_Home
+#define GK_KP_Left XK_KP_Left
+#define GK_KP_Up XK_KP_Up
+#define GK_KP_Right XK_KP_Right
+#define GK_KP_Down XK_KP_Down
+#define GK_KP_Prior XK_KP_Prior
+#define GK_KP_Page_Up XK_KP_Page_Up
+#define GK_KP_Next XK_KP_Next
+#define GK_KP_Page_Down XK_KP_Page_Down
+#define GK_KP_End XK_KP_End
+#define GK_KP_Begin XK_KP_Begin
+
+#define GK_F1 XK_F1
+#define GK_F2 XK_F2
+#define GK_F3 XK_F3
+#define GK_F4 XK_F4
+#define GK_F5 XK_F5
+#define GK_F6 XK_F6
+#define GK_F7 XK_F7
+#define GK_F8 XK_F8
+#define GK_F9 XK_F9
+#define GK_F10 XK_F10
+#define GK_F11 XK_F11
+#define GK_L1 XK_L1
+#define GK_F12 XK_F12
+#define GK_L2 XK_L2
+#define GK_F13 XK_F13
+#define GK_L3 XK_L3
+#define GK_F14 XK_F14
+#define GK_L4 XK_L4
+#define GK_F15 XK_F15
+#define GK_L5 XK_L5
+#define GK_F16 XK_F16
+#define GK_L6 XK_L6
+#define GK_F17 XK_F17
+#define GK_L7 XK_L7
+#define GK_F18 XK_F18
+#define GK_L8 XK_L8
+#define GK_F19 XK_F19
+#define GK_L9 XK_L9
+#define GK_F20 XK_F20
+#define GK_L10 XK_L10
+#define GK_F21 XK_F21
+#define GK_R1 XK_R1
+#define GK_F22 XK_F22
+#define GK_R2 XK_R2
+#define GK_F23 XK_F23
+#define GK_R3 XK_R3
+#define GK_F24 XK_F24
+#define GK_R4 XK_R4
+#define GK_F25 XK_F25
+#define GK_R5 XK_R5
+#define GK_F26 XK_F26
+#define GK_R6 XK_R6
+#define GK_F27 XK_F27
+#define GK_R7 XK_R7
+#define GK_F28 XK_F28
+#define GK_R8 XK_R8
+#define GK_F29 XK_F29
+#define GK_R9 XK_R9
+#define GK_F30 XK_F30
+#define GK_R10 XK_R10
+#define GK_F31 XK_F31
+#define GK_R11 XK_R11
+#define GK_F32 XK_F32
+#define GK_R12 XK_R12
+#define GK_F33 XK_F33
+#define GK_R13 XK_R13
+#define GK_F34 XK_F34
+#define GK_R14 XK_R14
+#define GK_F35 XK_F35
+#define GK_R15 XK_R15
+
+#define GK_Shift_L XK_Shift_L
+#define GK_Shift_R XK_Shift_R
+#define GK_Control_L XK_Control_L
+#define GK_Control_R XK_Control_R
+#define GK_Caps_Lock XK_Caps_Lock
+#define GK_Shift_Lock XK_Shift_Lock
+
+#define GK_Meta_L XK_Meta_L
+#define GK_Meta_R XK_Meta_R
+#define GK_Alt_L XK_Alt_L
+#define GK_Alt_R XK_Alt_R
+#define GK_Super_L XK_Super_L
+#define GK_Super_R XK_Super_R
+#define GK_Hyper_L XK_Hyper_L
+#define GK_Hyper_R XK_Hyper_R
+
+#else /* No X */
+
+#define GK_Special 0xfe00 /* keysyms above this value aren't unicode */
+#define GK_TypeAhead 0x0000 /* no single keysym, unicode value in event string */
+
+#define GK_BackSpace 0xff01
+#define GK_Tab 0xff02
+#define GK_BackTab 0xff03
+#define GK_Linefeed 0xff04
+#define GK_Clear 0xff05
+#define GK_Return 0xff06
+#define GK_Pause 0xff07
+#define GK_Scroll_Lock 0xff08
+#define GK_Sys_Req 0xff09
+#define GK_Escape 0xff0a
+#define GK_Delete 0xff0b
+
+#define GK_Home 0xff0c
+#define GK_Left 0xff0d
+#define GK_Up 0xff0e
+#define GK_Right 0xff0f
+#define GK_Down 0xff10
+#define GK_Prior 0xff11
+#define GK_Page_Up 0xff12
+#define GK_Next 0xff13
+#define GK_Page_Down 0xff14
+#define GK_End 0xff15
+#define GK_Begin 0xff16
+
+#define GK_Menu 0xff17
+#define GK_Help 0xff18
+
+#define GK_KP_Enter 0xFF8D
+#define GK_KP_Home 0xff19
+#define GK_KP_Left 0xff1a
+#define GK_KP_Up 0xff1b
+#define GK_KP_Right 0xff1c
+#define GK_KP_Down 0xff1d
+#define GK_KP_Prior 0xff1e
+#define GK_KP_Page_Up 0xff1f
+#define GK_KP_Next 0xff20
+#define GK_KP_Page_Down 0xff21
+#define GK_KP_End 0xff22
+#define GK_KP_Begin 0xff23
+
+#define GK_F1 0
+#define GK_F2 0
+#define GK_F3 0
+#define GK_F4 0
+#define GK_F5 0
+#define GK_F6 0
+#define GK_F7 0
+#define GK_F8 0
+#define GK_F9 0
+#define GK_F10 0
+#define GK_F11 0
+#define GK_L1 0
+#define GK_F12 0
+#define GK_L2 0
+#define GK_F13 0
+#define GK_L3 0
+#define GK_F14 0
+#define GK_L4 0
+#define GK_F15 0
+#define GK_L5 0
+#define GK_F16 0
+#define GK_L6 0
+#define GK_F17 0
+#define GK_L7 0
+#define GK_F18 0
+#define GK_L8 0
+#define GK_F19 0
+#define GK_L9 0
+#define GK_F20 0
+#define GK_L10 0
+#define GK_F21 0
+#define GK_R1 0
+#define GK_F22 0
+#define GK_R2 0
+#define GK_F23 0
+#define GK_R3 0
+#define GK_F24 0
+#define GK_R4 0
+#define GK_F25 0
+#define GK_R5 0
+#define GK_F26 0
+#define GK_R6 0
+#define GK_F27 0
+#define GK_R7 0
+#define GK_F28 0
+#define GK_R8 0
+#define GK_F29 0
+#define GK_R9 0
+#define GK_F30 0
+#define GK_R10 0
+#define GK_F31 0
+#define GK_R11 0
+#define GK_F32 0
+#define GK_R12 0
+#define GK_F33 0
+#define GK_R13 0
+#define GK_F34 0
+#define GK_R14 0
+#define GK_F35 0
+#define GK_R15 0
+
+#define GK_Shift_L 0
+#define GK_Shift_R 0
+#define GK_Control_L 0
+#define GK_Control_R 0
+#define GK_Caps_Lock 0
+#define GK_Shift_Lock 0
+
+#define GK_Meta_L 0
+#define GK_Meta_R 0
+#define GK_Alt_L 0
+#define GK_Alt_R 0
+#define GK_Super_L 0
+#define GK_Super_R 0
+#define GK_Hyper_L 0
+#define GK_Hyper_R 0
+#endif /* No X */
+
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/inc/gprogress.h b/Build/source/libs/luafontforge/fontforge/inc/gprogress.h
new file mode 100644
index 00000000000..d0d26581b70
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/gprogress.h
@@ -0,0 +1,77 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _GPROGRESS_H
+#define _GPROGRESS_H
+#include "basics.h"
+#include "intl.h"
+
+extern void GProgressStartIndicator(
+ int delay, /* in tenths of seconds */
+ const unichar_t *win_title, /* for the window decoration */
+ const unichar_t *line1, /* First line of description */
+ const unichar_t *line2, /* Second line */
+ int tot, /* Number of sub-entities in the operation */
+ int stages /* Number of stages, each processing tot sub-entities */
+);
+extern void GProgressStartIndicatorR(int delay, int win_titler, int line1r,
+ int line2r, int tot, int stages);
+extern void GProgressEndIndicator(void); /* Ends the topmost indicator */
+extern void GProgressChangeLine1(const unichar_t *line1); /* Changes the text in the topmost */
+extern void GProgressChangeLine2(const unichar_t *line2); /* Changes the text in the topmost */
+extern void GProgressChangeLine1R(int line1r); /* Changes the text in the topmost */
+extern void GProgressChangeLine2R(int line2r); /* Changes the text in the topmost */
+extern void GProgressChangeTotal(int tot); /* Changes the expected length in the topmost */
+extern void GProgressChangeStages(int stages); /* Changes the expected number of stages in the topmost */
+extern void GProgressEnableStop(int enabled); /* Allows you to disable and enable the stop button if it can't be used in a section of code */
+ /* if any of the next routines returns false, then abort processing */
+extern int GProgressNextStage(void); /* Move to the next stage in the topmost indicator */
+extern int GProgressNext(void); /* Increment progress by one sub-entity */
+extern int GProgressIncrementBy(int cnt); /* Increment progress by cnt sub-entities */
+extern void GProgressPauseTimer(void); /* Don't bring up the progress dlg because of */
+extern void GProgressResumeTimer(void); /* time spent between a pause and resume */
+extern void GProgressShow(void); /* Display the damn thing whether we should or not */
+
+extern void GProgressStartIndicator8(int delay, const char *title, const char *line1,
+ const char *line2, int tot, int stages);
+extern void GProgressChangeLine1_8(const char *line1); /* Changes the text in the topmost */
+extern void GProgressChangeLine2_8(const char *line2); /* Changes the text in the topmost */
+
+#define gwwv_progress_start_indicator GProgressStartIndicator8
+#define gwwv_progress_next GProgressNext
+#define gwwv_progress_next_stage GProgressNextStage
+#define gwwv_progress_end_indicator GProgressEndIndicator
+#define gwwv_progress_show GProgressShow
+#define gwwv_progress_change_line1 GProgressChangeLine1_8
+#define gwwv_progress_change_line2 GProgressChangeLine2_8
+#define gwwv_progress_change_total GProgressChangeTotal
+#define gwwv_progress_change_stages GProgressChangeStages
+#define gwwv_progress_increment GProgressIncrementBy
+#define gwwv_progress_pause_timer GProgressPauseTimer
+#define gwwv_progress_resume_timer GProgressResumeTimer
+#define gwwv_progress_enable_stop GProgressEnableStop
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/inc/gresource.h b/Build/source/libs/luafontforge/fontforge/inc/gresource.h
new file mode 100644
index 00000000000..11e6274bbc1
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/gresource.h
@@ -0,0 +1,58 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _GRESOURCE_H
+#define _GRESOURCE_H
+
+#include "gdraw.h"
+
+enum res_type { rt_int, rt_double, rt_bool/* int */, rt_color, rt_string };
+
+typedef struct gresstruct {
+ char *resname;
+ enum res_type type;
+ void *val;
+ void *(*cvt)(char *,void *); /* converts a string into a whatever */
+ int found;
+} GResStruct;
+
+extern char *GResourceProgramName, *GResourceFullProgram, *GResourceProgramDir;
+extern int local_encoding;
+#if HAVE_ICONV_H
+# include <iconv.h>
+extern char *iconv_local_encoding_name;
+#endif
+
+void GResourceSetProg(char *prog);
+void GResourceAddResourceFile(char *filename,char *prog);
+void GResourceAddResourceString(char *string,char *prog);
+void GResourceFind( GResStruct *info, char *prefix);
+char *GResourceFindString(char *name);
+int GResourceFindBool(char *name, int def);
+long GResourceFindInt(char *name, long def);
+Color GResourceFindColor(char *name, Color def);
+GImage *GResourceFindImage(char *name, GImage *def);
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/inc/gwidget.h b/Build/source/libs/luafontforge/fontforge/inc/gwidget.h
new file mode 100644
index 00000000000..da470eab786
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/gwidget.h
@@ -0,0 +1,215 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _GWIDGET_H
+#define _GWIDGET_H
+
+#include <stdarg.h>
+#include "gdraw.h"
+#include "gprogress.h"
+#include "ggadget.h"
+
+struct ggadget;
+struct ggadgetcreatedata;
+struct gtimer;
+
+typedef GWindow GWidget;
+
+typedef struct gwidgetcreatedata {
+ GRect r;
+ struct ggadgetcreatedata *gcd;
+ struct gwidgetcreatedata *wcd;
+ unichar_t *title;
+ unsigned int trap_input: 1;
+ unsigned int tab_navigation: 1;
+ unsigned int arrow_navigation: 1;
+ unsigned int do_default: 1;
+ unsigned int do_cancel: 1;
+ Color fore, back;
+ void (*e_h)(GWindow, GEvent *); /* User's event function for window, our eh will call it */
+#if 0 /* should expect these events: */
+ void (*create)(Widget *);
+ void (*close)(Widget *);
+ void (*expose)(Widget *,XEvent *);
+ void (*mouse)(Widget *,XEvent *,int count);
+ void (*key)(Widget *,XEvent *);
+ void (*resize)(Widget *,XEvent *);
+ void (*map)(Widget *,XEvent *);
+ void (*time)(Widget *,struct timer *timer);
+ void (*paste)(Widget *,void *data, long length);
+#endif
+} GWidgetData;
+
+typedef struct gwidgetcreatordata {
+ GWidget *(*creator)(GWidget *parent, GWidgetData *, void *data);
+ GWidgetData wd;
+ void *data;
+} GWidgetCreateData;
+
+extern GWindow GWidgetCreateTopWindow(GDisplay *gdisp, GRect *pos, int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs);
+extern GWindow GWidgetCreateSubWindow(GWindow w, GRect *pos, int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs);
+extern GWindow GWidgetCreatePalette(GWindow w, GRect *pos, int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs);
+
+GWindow GWindowGetCurrentFocusTopWindow(void);
+GWindow GWidgetGetCurrentFocusWindow(void);
+GWindow GWidgetGetPreviousFocusTopWindow(void);
+struct ggadget *GWindowGetCurrentFocusGadget(void);
+struct ggadget *GWindowGetFocusGadgetOfWindow(GWindow gw);
+void GWindowClearFocusGadgetOfWindow(GWindow gw);
+void GWidgetIndicateFocusGadget(struct ggadget *g);
+void GWidgetNextFocus(GWindow);
+void GWidgetPrevFocus(GWindow);
+void GWidgetRequestVisiblePalette(GWindow palette,int visible);
+void GWidgetHidePalettes(void);
+void GPaletteDock(GWindow palette,int x, int y);
+void GPaletteUndock(GWindow palette,int x, int y);
+int GPaletteIsDocked(GWindow palette);
+void GWidgetReparentWindow(GWindow child,GWindow newparent, int x,int y);
+
+struct ggadget *GWidgetGetControl(GWindow gw, int cid);
+struct ggadget *_GWidgetGetGadgets(GWindow gw);
+GWindow GWidgetGetParent(GWindow gw);
+GWindow GWidgetGetTopWidget(GWindow gw);
+extern GDrawEH GWidgetGetEH(GWindow w);
+extern void GWidgetSetEH(GWindow w,GDrawEH e_h);
+extern void GWidgetFlowGadgets(GWindow gw);
+extern void GWidgetToDesiredSize(GWindow gw);
+
+ /* Built in dialogs */
+unichar_t *GWidgetOpenFile(const unichar_t *title, const unichar_t *defaultfile,
+ const unichar_t *initial_filter, unichar_t **mimetypes,GFileChooserFilterType filter);
+unichar_t *GWidgetSaveAsFile(const unichar_t *title, const unichar_t *defaultfile,
+ const unichar_t *initial_filter, unichar_t **mimetypes,GFileChooserFilterType filter );
+unichar_t *GWidgetSaveAsFileWithGadget(const unichar_t *title, const unichar_t *defaultfile,
+ const unichar_t *initial_filter, unichar_t **mimetypes,
+ GFileChooserFilterType filter, GGadgetCreateData *optional_gcd);
+char *GWidgetOpenFile8(const char *title, const char *defaultfile,
+ const char *initial_filter, char **mimetypes,GFileChooserFilterType filter);
+char *GWidgetSaveAsFileWithGadget8(const char *title, const char *defaultfile,
+ const char *initial_filter, char **mimetypes,
+ GFileChooserFilterType filter, GGadgetCreateData *optional_gcd);
+char *GWidgetSaveAsFile8(const char *title, const char *defaultfile,
+ const char *initial_filter, char **mimetypes,GFileChooserFilterType filter );
+int GWidgetAsk(const unichar_t *title, const unichar_t **answers, const unichar_t *mn,
+ int def, int cancel,const unichar_t *question,...);
+int GWidgetAskCentered(const unichar_t *title,
+ const unichar_t ** answers, const unichar_t *mn, int def, int cancel,const unichar_t *question,...);
+unichar_t *GWidgetAskString(const unichar_t *title,
+ const unichar_t *def,const unichar_t *question,...);
+void GWidgetPostNotice(const unichar_t *title,const unichar_t *statement,...);
+void GWidgetError(const unichar_t *title,const unichar_t *statement,...);
+void GWidgetErrorR(int title,int statement,...);
+int GWidgetAskR(int title, int *answers, int def, int cancel,int question,...);
+int GWidgetAskR_(int title, int *answers, int def, int cancel,const unichar_t *question,...);
+int GWidgetAskCenteredR(int title, int *answers, int def, int cancel,int question,...);
+int GWidgetAskCenteredR_(int title, int *answers, int def, int cancel,const unichar_t *question,...);
+unichar_t *GWidgetAskStringR(int title, const unichar_t *def,int question,...);
+void GWidgetPostNoticeR(int title,int statement,...);
+int GWidgetAsk8(const char *title, const char **answers,
+ int def, int cancel,const char *question,...);
+int GWidgetAskCentered8(const char *title,
+ const char ** answers, int def, int cancel,const char *question,...);
+char *GWidgetAskString8(const char *title,
+ const char *def,const char *question,...);
+void GWidgetPostNotice8(const char *title,const char *statement,...);
+void _GWidgetPostNotice8(const char *title,const char *statement,va_list ap);
+int GWidgetPostNoticeActive8(const char *title);
+void GWidgetError8(const char *title,const char *statement,...);
+
+int GWidgetChoicesR(int title, const unichar_t **choices,int cnt, int def,int question,...);
+int GWidgetChoicesBR(int title, const unichar_t **choices, int cnt, int def,
+ int buts[2],int question,...);
+int GWidgetChoicesBRM(int title, const unichar_t **choices,char *sel,
+ int cnt, int buts[2], int question,...);
+int GWidgetChoices8(const char *title, const char **choices,int cnt, int def,
+ const char *question,...);
+int GWidgetChoicesB8(char *title, const char **choices, int cnt, int def,
+ char *buts[2], const char *question,...);
+int GWidgetChoicesBM8(char *title, const char **choices,char *sel,
+ int cnt, char *buts[2], const char *question,...);
+
+#define gwwv_choose_multiple GWidgetChoicesBM8
+#define gwwv_choose_with_buttons GWidgetChoicesB8
+#define gwwv_choose GWidgetChoices8
+#define gwwv_ask_string GWidgetAskString8
+#define gwwv_ask GWidgetAsk8
+#define gwwv_ask_centered GWidgetAskCentered8
+#define gwwv_post_error GWidgetError8
+#define gwwv_post_notice GWidgetPostNotice8
+#define gwwv_open_filename(tit,def,filter,filtfunc) GWidgetOpenFile8(tit,def,filter,NULL,filtfunc)
+#define gwwv_save_filename(tit,def,filter) GWidgetSaveAsFile8(tit,def,filter,NULL,NULL)
+#define gwwv_save_filename_with_gadget(tit,def,filter,gcd) GWidgetSaveAsFileWithGadget8(tit,def,filter,NULL,NULL,gcd)
+
+void GWidgetCreateInsChar(void); /* takes input even when a modal dlg is active */
+ /* but is not modal itself */
+void GInsCharSetChar(unichar_t ch); /* Sets current selection in ins char dlg */
+
+extern GIC *GWidgetCreateInputContext(GWindow w,enum gic_style def_style);
+extern GIC *GWidgetGetInputContext(GWindow w);
+
+
+#if 0
+Widget *CreateCenteredDialog(Widget *parent, WidgetData *wd,void *data);
+Widget *CreateDialog(Widget *parent, WidgetData *wd,void *data);
+Widget *CreateTopWindow(Widget *parent, WidgetData *wd,void *data);
+Widget *CreateCanvas(Widget *parent, WidgetData *wd,void *data);
+Widget *CreateWidgets(Widget *parent, WidgetCreateData *wcd);
+
+unichar_t *CreateFileDialog(unichar_t *title,unichar_t *dir,unichar_t *file,unichar_t *mimetypes, unichar_t *wildcard, unichar_t *open, unichar_t *cancel);
+int CreateQuestionDialog(unichar_t *title, unichar_t *question,unichar_t *but1, unichar_t *but2, unichar_t *but3, unichar_t *but4, unichar_t *but5);
+unichar_t *CreateStringDialog(unichar_t *title, unichar_t *question, unichar_t *def, unichar_t *ok, unichar_t *cancel);
+TextInfo *CreateListDialog(unichar_t *title, unichar_t *question, TextInfo *list, unichar_t *ok, unichar_t *cancel);
+void CreateNoteDlg(unichar_t *title,unichar_t *text,unichar_t *ok); /* does not take focus, vanishes if ignored */
+void CreateWarningDlg(unichar_t *title,unichar_t *text,unichar_t *ok); /* does not take focus, vanishes if ignored */
+void CreateErrorDlg(unichar_t *title,unichar_t *text,unichar_t *ok); /* does take focus */
+void CreateFatalDlg(unichar_t *title,unichar_t *text,unichar_t *ok); /* does not return, preallocated */
+void CreateCharDialog(); /* takes input even when a modal dlg is active */
+ /* but is not modal itself */
+void CreatePrefsDialog();
+
+void WidgetSetTitle(Widget *widg,unichar_t *title);
+unichar_t_t WidgetGetTitle(Widget *widg);
+
+void WidgetChangeMenu(Widget *widg,MenuItem *bar);
+void WidgetChangeInvisibleCommands(Widget *widg,MenuItem *invisible);
+MenuItem *WidgetGetMenu(Widget *widg);
+MenuItem *WidgetGetInvisibleCommands(Widget *widg);
+
+enum handler_mask { hm_close=1, hm_expose=2, hm_mouse=4, hm_key=8, hm_resize=16, hm_map=32, hm_time=64, hm_paste=128 };
+void WidgetSetHandlers(Widget *widg,enum handler_mask hm, WidgetData *wd);
+
+void WidgetMove(Widget *widg, int x, int y);
+void WidgetResize(Widget *widg, int width, int height);
+void WidgetReposition(Widget *widg, Rect *r);
+Rect *WidgetGetPos(Widget *widg);
+
+void WidgetRaise(Widget *widg);
+void WidgetLower(Widget *widg);
+
+void WidgetSetIconName(Widget *widg,unichar_t *name);
+void WidgetSetIconPixmap(Widget *widg,Pixmap p);
+#endif
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/inc/gwwiconv.h b/Build/source/libs/luafontforge/fontforge/inc/gwwiconv.h
new file mode 100644
index 00000000000..914056c9227
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/gwwiconv.h
@@ -0,0 +1,55 @@
+/* Copyright (C) 2004-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _GWWICONV_H
+#define _GWWICONV_H
+
+# ifndef HAVE_ICONV_H
+# define __need_size_t
+# include <stdlib.h> /* For size_t */
+
+typedef void *gww_iconv_t;
+
+extern gww_iconv_t gww_iconv_open(const char *toenc,const char *fromenc);
+extern void gww_iconv_close( gww_iconv_t cd);
+extern size_t gww_iconv( gww_iconv_t cd,
+ char **inbuf, size_t *inlen,
+ char **outbuf, size_t *outlen);
+
+#define iconv_t gww_iconv_t
+#define iconv_open gww_iconv_open
+#define iconv_close gww_iconv_close
+#define iconv gww_iconv
+
+# define iconv_arg2_t char **
+# else /* HAVE_ICONV_H */
+# ifdef iconv /* libiconv has a different calling convention */
+# define iconv_arg2_t const char **
+# else
+# define iconv_arg2_t char **
+# endif /* iconv */
+# endif /* HAVE_ICONV_H */
+#endif /* _GWWICONV_H */
diff --git a/Build/source/libs/luafontforge/fontforge/inc/intl.h b/Build/source/libs/luafontforge/fontforge/inc/intl.h
new file mode 100644
index 00000000000..69c778c357e
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/intl.h
@@ -0,0 +1,85 @@
+/* Copyright (C) 2005-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _INTL_H
+#define _INTL_H
+
+#if !defined( HAVE_LIBINTL_H )
+# define _(str) (str)
+# define P_(str1,str_non1,n) ((n)==1?str1:str_non1)
+# define U_(str) (str)
+
+#ifndef __sun__
+# define bindtextdomain(domain,dir)
+# define bind_textdomain_codeset(domain,enc)
+# define textdomain(domain)
+
+# define dgettext(domain,str) (str)
+#endif
+
+#elif defined( NODYNAMIC ) || defined ( _STATIC_LIBINTL )
+
+# include <libintl.h>
+# define _(str) gettext(str)
+# define P_(str1,str_non1,n) ngettext(str1,str_non1,n)
+/* For messages including utf8 characters. old xgettexts won't handle them */
+/* so we must do something special. */
+# define U_(str) gettext(str)
+
+#else
+
+# include <libintl.h>
+# define _(str) gwwv_gettext(str)
+# define P_(str1,str_non1,n) gwwv_ngettext(str1,str_non1,n)
+# define U_(str) gwwv_gettext(str)
+
+# define bindtextdomain(domain,dir) gwwv_bindtextdomain(domain,dir)
+# define bind_textdomain_codeset(domain,enc) gwwv_bind_textdomain_codeset(domain,enc)
+# define textdomain(domain) gwwv_textdomain(domain)
+
+# ifdef dgettext
+# undef dgettext
+# endif
+# define dgettext(domain,str) gwwv_dgettext(domain,str)
+
+char *gwwv_bindtextdomain(const char *, const char *);
+char *gwwv_bind_textdomain_codeset(const char *, const char *);
+char *gwwv_textdomain(const char *);
+char *gwwv_gettext(const char *);
+char *gwwv_ngettext(const char *,const char *, unsigned long int);
+char *gwwv_dgettext(const char *,const char *);
+#endif
+/* For messages including utf8 sequences that need gettext_noop treatment */
+#define NU_(str) (str)
+#define N_(str) (str)
+#define S_(str) sgettext(str)
+/* For messages in the shortcuts domain */
+#define H_(str) (str)
+
+extern void GResourceUseGetText(void);
+char *sgettext(const char *msgid);
+
+#endif /* _INTL_H */
diff --git a/Build/source/libs/luafontforge/fontforge/inc/ustring.h b/Build/source/libs/luafontforge/fontforge/inc/ustring.h
new file mode 100644
index 00000000000..14d01c89377
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/ustring.h
@@ -0,0 +1,128 @@
+/* Copyright (C) 2000-2007 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _UCHAR_H
+# define _UCHAR_H
+#include <stdarg.h>
+#include <string.h>
+#include <memory.h>
+#include "basics.h"
+#include "charset.h"
+
+extern char *copy(const char *);
+extern char *copyn(const char *,long);
+extern unichar_t *u_copy(const unichar_t*);
+extern unichar_t *u_copyn(const unichar_t*, long);
+extern unichar_t *uc_copyn(const char *, int);
+extern unichar_t *uc_copy(const char*);
+extern unichar_t *u_concat(const unichar_t*,const unichar_t*);
+extern char *cu_copyn(const unichar_t *pt,int len);
+extern char *cu_copy(const unichar_t*);
+
+extern long uc_strcmp(const unichar_t *,const char *);
+extern long u_strcmp(const unichar_t *, const unichar_t *);
+extern long uc_strncmp(const unichar_t *,const char *,int);
+extern long u_strncmp(const unichar_t *, const unichar_t *,int);
+extern long uc_strmatch(const unichar_t *,const char *);
+extern long uc_strnmatch(const unichar_t *,const char *,int);
+extern long u_strnmatch(const unichar_t *str1, const unichar_t *str2, int len);
+extern long u_strmatch(const unichar_t *, const unichar_t *);
+extern int strmatch(const char *,const char *);
+extern int strnmatch(const char *str1, const char *str2, int n);
+extern void uc_strcpy(unichar_t *, const char *);
+extern void cu_strcpy(char *, const unichar_t *);
+extern void u_strcpy(unichar_t *, const unichar_t *);
+extern void u_strncpy(unichar_t *, const unichar_t *,int);
+extern void cu_strncpy(char *to, const unichar_t *from, int len);
+extern void uc_strncpy(unichar_t *to, const char *from, int len);
+extern void uc_strcat(unichar_t *, const char *);
+extern void uc_strncat(unichar_t *, const char *,int len);
+extern void cu_strcat(char *, const unichar_t *);
+extern void cu_strncat(char *, const unichar_t *,int len);
+extern void u_strcat(unichar_t *, const unichar_t *);
+extern void u_strncat(unichar_t *, const unichar_t *, int len);
+extern int u_strlen(const unichar_t *);
+extern unichar_t *u_strchr(const unichar_t *,unichar_t);
+extern unichar_t *u_strrchr(const unichar_t *,unichar_t);
+extern unichar_t *uc_strstr(const unichar_t *,const char *);
+extern unichar_t *u_strstr(const unichar_t *,const unichar_t *);
+extern unichar_t *uc_strstrmatch(const unichar_t *,const char *);
+extern unichar_t *u_strstrmatch(const unichar_t *,const unichar_t *);
+extern char * strstrmatch(const char *,const char *);
+
+extern char *u_to_c(const unichar_t *);
+extern unichar_t *c_to_u(const char *);
+
+extern unsigned long u_strtoul(const unichar_t *,unichar_t **,int);
+extern long u_strtol(const unichar_t *,unichar_t **,int);
+extern double u_strtod(const unichar_t *,unichar_t **);
+
+extern char *strstart(const char *initial,const char *full);
+extern char *strstartmatch(const char *initial,const char *full);
+extern unichar_t *u_strstartmatch(const unichar_t *initial, const unichar_t *full);
+extern unichar_t *cu_strstartmatch(const char *initial, const unichar_t *full);
+
+#ifdef UNICHAR_16
+extern uint32 *utf82u32_strncpy(int32 *ubuf,const char *utf8buf,int len);
+extern uint32 *utf82u32_copy(const char *utf8buf);
+extern char *u322utf8_copy(const uint32 *ubuf);
+extern char *u322utf8_strncpy(char *utf8buf, const uint32 *ubuf,int len);
+#else
+/* Make sure we have different entry points in the library */
+#define utf82u_strncpy utf82U_strncpy
+#endif
+extern int32 utf8_ildb(const char **utf8_text);
+extern char *utf8_idpb(char *utf8_text,uint32 ch);
+extern char *utf8_db(char *utf8_text);
+extern char *utf8_ib(char *utf8_text);
+extern int utf8_valid(const char *str);
+extern char *latin1_2_utf8_strcpy(char *utf8buf,const char *lbuf);
+extern char *latin1_2_utf8_copy(const char *lbuf);
+extern char *utf8_2_latin1_copy(const char *utf8buf);
+extern int utf8_strlen(const char *utf8_str); /* how many characters in the string */
+extern int utf82u_strlen(const char *utf8_str); /* how many long would this be in shorts (UCS2) */
+extern char *def2utf8_copy(const char *from);
+extern char *utf82def_copy(const char *ufrom);
+
+extern unichar_t *utf82u_strncpy(unichar_t *ubuf,const char *utf8buf,int len);
+extern unichar_t *utf82u_strcpy(unichar_t *ubuf,const char *utf8buf);
+extern void utf82u_strcat(unichar_t *ubuf,const char *utf8buf);
+extern unichar_t *utf82u_copyn(const char *utf8buf,int len);
+extern unichar_t *utf82u_copy(const char *utf8buf);
+extern char *u2utf8_strcpy(char *utf8buf,const unichar_t *ubuf);
+extern char *u2utf8_copy(const unichar_t *ubuf);
+extern char *u2utf8_copyn(const unichar_t *ubuf,int len);
+extern unichar_t *encoding2u_strncpy(unichar_t *uto, const char *from, int n, enum encoding cs);
+extern char *u2encoding_strncpy(char *to, const unichar_t *ufrom, int n, enum encoding cs);
+extern unichar_t *def2u_strncpy(unichar_t *uto, const char *from, int n);
+extern char *u2def_strncpy(char *to, const unichar_t *ufrom, int n);
+extern unichar_t *def2u_copy(const char *from);
+extern char *u2def_copy(const unichar_t *ufrom);
+
+extern int u_sprintf(unichar_t *str, const unichar_t *format, ... );
+extern int u_snprintf(unichar_t *str, int len, const unichar_t *format, ... );
+extern int u_vsnprintf(unichar_t *str, int len, const unichar_t *format, va_list ap );
+#endif
diff --git a/Build/source/libs/luafontforge/fontforge/inc/utype.h b/Build/source/libs/luafontforge/fontforge/inc/utype.h
new file mode 100644
index 00000000000..e99f4d2b286
--- /dev/null
+++ b/Build/source/libs/luafontforge/fontforge/inc/utype.h
@@ -0,0 +1,115 @@
+#ifndef _UTYPE_H
+
+#define _UTYPE_H
+
+#ifndef LUA_FF_LIB
+
+#define ____L 0x1
+#define ____U 0x2
+#define ____TITLE 0x4
+#define ____D 0x8
+#define ____S 0x10
+#define ____P 0x20
+#define ____X 0x40
+#define ____ZW 0x80
+#define ____L2R 0x100
+#define ____R2L 0x200
+#define ____ENUM 0x400
+#define ____ANUM 0x800
+#define ____ENS 0x1000
+#define ____CS 0x2000
+#define ____ENT 0x4000
+#define ____COMBINE 0x8000
+#define ____BB 0x10000
+#define ____BA 0x20000
+#define ____NS 0x40000
+#define ____NE 0x80000
+#define ____UB 0x100000
+#define ____NB 0x8000000
+#define ____AL 0x200000
+#define ____ID 0x400000
+#define ____INITIAL 0x800000
+#define ____MEDIAL 0x1000000
+#define ____FINAL 0x2000000
+#define ____ISOLATED 0x4000000
+#define ____DECOMPNORM 0x10000000
+
+#define ____COMBININGCLASS 0xff
+#define ____ABOVE 0x100
+#define ____BELOW 0x200
+#define ____OVERSTRIKE 0x400
+#define ____LEFT 0x800
+#define ____RIGHT 0x1000
+#define ____JOINS2 0x2000
+#define ____CENTERLEFT 0x4000
+#define ____CENTERRIGHT 0x8000
+#define ____CENTEREDOUTSIDE 0x10000
+#define ____OUTSIDE 0x20000
+#define ____LEFTEDGE 0x80000
+#define ____RIGHTEDGE 0x40000
+#define ____TOUCHING 0x100000
+#define ____COMBININGPOSMASK 0x1fff00
+
+extern const unsigned int ____utype[];
+extern const unsigned short ____tolower[];
+extern const unsigned short ____toupper[];
+extern const unsigned short ____totitle[];
+extern const unsigned short ____tomirror[];
+extern const unsigned char ____digitval[];
+
+extern const unsigned int ____utype2[];
+
+extern const unsigned int ____codepointassigned[];
+
+#define tolower(ch) (____tolower[(ch)+1])
+#define toupper(ch) (____toupper[(ch)+1])
+#define totitle(ch) (____totitle[(ch)+1])
+#define tomirror(ch) (____tomirror[(ch)+1])
+#define tovalue(ch) (____digitval[(ch)+1])
+#define islower(ch) (____utype[(ch)+1]&____L)
+#define isupper(ch) (____utype[(ch)+1]&____U)
+#define istitle(ch) (____utype[(ch)+1]&____TITLE)
+#define isalpha(ch) (____utype[(ch)+1]&(____L|____U|____TITLE|____AL))
+#define isdigit(ch) (____utype[(ch)+1]&____D)
+#define isalnum(ch) (____utype[(ch)+1]&(____L|____U|____TITLE|____AL|____D))
+#define isideographic(ch) (____utype[(ch)+1]&____ID)
+#define isspace(ch) (____utype[(ch)+1]&____S)
+#define ispunct(ch) (____utype[(ch)+1]&_____P)
+#define ishexdigit(ch) (____utype[(ch)+1]&____X)
+#define iszerowidth(ch) (____utype[(ch)+1]&____ZW)
+#define islefttoright(ch) (____utype[(ch)+1]&____L2R)
+#define isrighttoleft(ch) (____utype[(ch)+1]&____R2L)
+#define iseuronumeric(ch) (____utype[(ch)+1]&____ENUM)
+#define isarabnumeric(ch) (____utype[(ch)+1]&____ANUM)
+#define iseuronumsep(ch) (____utype[(ch)+1]&____ENS)
+#define iscommonsep(ch) (____utype[(ch)+1]&____CS)
+#define iseuronumterm(ch) (____utype[(ch)+1]&____ENT)
+#define iscombining(ch) (____utype[(ch)+1]&____COMBINE)
+#define isbreakbetweenok(ch1,ch2) (((____utype[(ch1)+1]&____BA) && !(____utype[(ch2)+1]&____NS)) || ((____utype[(ch2)+1]&____BB) && !(____utype[(ch1)+1]&____NE)) || (!(____utype[(ch2)+1]&____D) && ch1=='/'))
+#define isnobreak(ch) (____utype[(ch)+1]&____NB)
+#define isarabinitial(ch) (____utype[(ch)+1]&____INITIAL)
+#define isarabmedial(ch) (____utype[(ch)+1]&____MEDIAL)
+#define isarabfinal(ch) (____utype[(ch)+1]&____FINAL)
+#define isarabisolated(ch) (____utype[(ch)+1]&____ISOLATED)
+
+#define isdecompositionnormative(ch) (____utype[(ch)+1]&____DECOMPNORM)
+
+#define combiningclass(ch) (____utype2[(ch)+1]&____COMBININGCLASS)
+#define combiningposmask(ch) (____utype2[(ch)+1]&____COMBININGPOSMASK)
+
+#define isunicodepointassigned(ch) (____codepointassigned[(ch)/32]&(1<<((ch)%32)))
+
+
+extern struct arabicforms {
+ unsigned short initial, medial, final, isolated;
+ unsigned int isletter: 1;
+ unsigned int joindual: 1;
+ unsigned int required_lig_with_alef: 1;
+} ArabicForms[256]; /* for chars 0x600-0x6ff, subtract 0x600 to use array */
+
+#define _SOFT_HYPHEN 0xad
+
+#define _DOUBLE_S 0xdf
+
+#endif /* LUA_FF_LIB */
+#endif
diff --git a/Build/source/libs/luafontforge/src/ffdummies.c b/Build/source/libs/luafontforge/src/ffdummies.c
new file mode 100644
index 00000000000..dce8c116c0f
--- /dev/null
+++ b/Build/source/libs/luafontforge/src/ffdummies.c
@@ -0,0 +1,5552 @@
+
+/* some dummy functions and variables so that a few ff source files can be ignored */
+
+#define FONTFORGE_CONFIG_NO_WINDOWING_UI 1
+
+#include "pfaeditui.h"
+#include <unistd.h>
+#include <math.h>
+#include <time.h>
+#include <locale.h>
+#include <utype.h>
+#include <chardata.h>
+#include <ustring.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "sd.h"
+
+#include "ttf.h" /* for macsettingname */
+
+void _gwwv_post_error(const char *fmt, va_list ap) ;
+
+/* some Gdraw routines for filesystem access */
+
+
+int GFileIsDir(const char *file) {
+ char buffer[1000];
+ sprintf(buffer,"%s/.",file);
+return( access(buffer,0)==0 );
+}
+
+int GFileExists(const char *file) {
+return( access(file,0)==0 );
+}
+
+char *GFileNameTail(const char *oldname) {
+ char *pt;
+
+ pt = strrchr(oldname,'/');
+ if ( pt !=NULL )
+return( pt+1);
+ else
+return( (char *)oldname );
+}
+
+
+char *GFileAppendFile(char *dir,char *name,int isdir) {
+ char *ret, *pt;
+
+ ret = galloc((strlen(dir)+strlen(name)+3));
+ strcpy(ret,dir);
+ pt = ret+strlen(ret);
+ if ( pt>ret && pt[-1]!='/' )
+ *pt++ = '/';
+ strcpy(pt,name);
+ if ( isdir ) {
+ pt += strlen(pt);
+ if ( pt>ret && pt[-1]!='/' ) {
+ *pt++ = '/';
+ *pt = '\0';
+ }
+ }
+return(ret);
+}
+
+int GFileReadable(char *file) {
+return( access(file,04)==0 );
+}
+
+static char dirname_[1024];
+
+
+char *GFileGetAbsoluteName(char *name, char *result, int rsiz) {
+ /* result may be the same as name */
+ char buffer[1000];
+
+ if ( *name!='/' ) {
+ char *pt, *spt, *rpt, *bpt;
+
+ if ( dirname_[0]=='\0' ) {
+ getcwd(dirname_,sizeof(dirname_));
+ }
+ strcpy(buffer,dirname_);
+ if ( buffer[strlen(buffer)-1]!='/' )
+ strcat(buffer,"/");
+ strcat(buffer,name);
+
+ /* Normalize out any .. */
+ spt = rpt = buffer;
+ while ( *spt!='\0' ) {
+ if ( *spt=='/' ) ++spt;
+ for ( pt = spt; *pt!='\0' && *pt!='/'; ++pt );
+ if ( pt==spt ) /* Found // in a path spec, reduce to / (we've*/
+ strcpy(spt,pt); /* skipped past the :// of the machine name) */
+ else if ( pt==spt+1 && spt[0]=='.' ) /* Noop */
+ strcpy(spt,pt);
+ else if ( pt==spt+2 && spt[0]=='.' && spt[1]=='.' ) {
+ for ( bpt=spt-2 ; bpt>rpt && *bpt!='/'; --bpt );
+ if ( bpt>=rpt && *bpt=='/' ) {
+ strcpy(bpt,pt);
+ spt = bpt;
+ } else {
+ rpt = pt;
+ spt = pt;
+ }
+ } else
+ spt = pt;
+ }
+ name = buffer;
+ if ( rsiz>sizeof(buffer)) rsiz = sizeof(buffer); /* Else valgrind gets unhappy */
+ }
+ if (result!=name) {
+ strncpy(result,name,rsiz);
+ result[rsiz-1]='\0';
+ }
+return(result);
+}
+
+
+
+/* a gettext miss */
+
+char *sgettext(const char *msgid) {
+ const char *msgval = msgid;
+ char *found;
+ if ( (found = strrchr (msgid, '|'))!=NULL )
+ msgval = found+1;
+ return (char *) msgval;
+}
+
+/* some utype.c macros, in function from */
+
+int unic_isrighttoleft (int c) {
+ /* most of the holes are combining chars */
+ if ((c==0x05be) || (c==0x05c0) || (c==0x05c3) || (c==0x05c6) ||
+ (c>=0x05d0 && c<=0x05ea) ||
+ (c>=0x05f0 && c<=0x05f4) ||
+ (c>=0x0600 && c<=0x0603) ||
+ (c==0x060b) || (c==0x060d) || (c==0x061b) ||
+ (c>=0x061e && c<=0x061f) ||
+ (c>=0x0621 && c<=0x063a) ||
+ (c>=0x0640 && c<=0x064a) ||
+ (c>=0x066d && c<=0x066f) ||
+ (c>=0x0671 && c<=0x06d5) ||
+ (c==0x06dd) ||
+ (c>=0x06e5 && c<=0x06e6) ||
+ (c>=0x06ee && c<=0x06ef) ||
+ (c>=0x06fa && c<=0x070d) ||
+ (c==0x0710) ||
+ (c>=0x0712 && c<=0x072f) ||
+ (c>=0x074d && c<=0x076d) ||
+ (c>=0x0780 && c<=0x07a5) ||
+ (c==0x07b1) ||
+ (c>=0x07c0 && c<=0x07ea) ||
+ (c>=0x07f4 && c<=0x07f5) ||
+ (c==0x07fa) ||
+ (c==0x200f) || (c==0x202b) || (c==0x202e) ||
+ (c>=0xfb1d && c<=0xfb3c) ||
+ (c==0xfb3e) ||
+ (c>=0xfb40 && c<=0xfbb1) ||
+ (c>=0xfbd3 && c<=0xfd3d) ||
+ (c>=0xfd50 && c<=0xfd8f) ||
+ (c>=0xfd92 && c<=0xfdc7) ||
+ (c>=0xfdf0 && c<=0xfdfc) ||
+ (c>=0xfe70 && c<=0xfefc)) {
+ if ((c==0xfe75) || (c==0xfb42) ||
+ (c==0xfb45) || (c==0xfb29) ||
+ (c==0xfb37) || (c==0xfb1e)) {
+ return 0;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+int unic_islefttoright (int c) {
+ if((c>=0x0041 && c<=0x005a) ||
+ (c>=0x0061 && c<=0x007a) ||
+ (c==0x00aa) || (c==0x00b5) || (c==0x00ba) ||
+ (c>=0x00c0 && c<=0x00d6) ||
+ (c>=0x00d8 && c<=0x00f6) ||
+ (c>=0x00f8 && c<=0x02b8) ||
+ (c>=0x02bb && c<=0x02c1) ||
+ (c>=0x02d0 && c<=0x02d1) ||
+ (c>=0x02e0 && c<=0x02e4) ||
+ (c==0x02ee) ||
+ (c>=0x037a && c<=0x037d) ||
+ (c==0x0386) ||
+ (c>=0x0388 && c<=0x038a) ||
+ (c==0x038c) ||
+ (c>=0x038e && c<=0x03a1) ||
+ (c>=0x03a3 && c<=0x03ce) ||
+ (c>=0x03d0 && c<=0x03f5) ||
+ (c>=0x03f7 && c<=0x0482) ||
+ (c>=0x048a && c<=0x0513) ||
+ (c>=0x0531 && c<=0x0556) ||
+ (c>=0x0559 && c<=0x055f) ||
+ (c>=0x0561 && c<=0x0587) ||
+ (c==0x0589) ||
+ (c>=0x0903 && c<=0x0939) ||
+ (c>=0x093d && c<=0x0940) ||
+ (c>=0x0949 && c<=0x094c) ||
+ (c==0x0950) ||
+ (c>=0x0958 && c<=0x0961) ||
+ (c>=0x0964 && c<=0x0970) ||
+ (c>=0x097b && c<=0x097f) ||
+ (c>=0x0982 && c<=0x0983) ||
+ (c>=0x0985 && c<=0x098c) ||
+ (c>=0x098f && c<=0x0990) ||
+ (c>=0x0993 && c<=0x09a8) ||
+ (c>=0x09aa && c<=0x09b0) ||
+ (c==0x09b2) ||
+ (c>=0x09b6 && c<=0x09b9) ||
+ (c>=0x09bd && c<=0x09c0) ||
+ (c>=0x09c7 && c<=0x09c8) ||
+ (c>=0x09cb && c<=0x09cc) ||
+ (c==0x09ce) ||
+ (c==0x09d7) ||
+ (c>=0x09dc && c<=0x09dd) ||
+ (c>=0x09df && c<=0x09e1) ||
+ (c>=0x09e6 && c<=0x09f1) ||
+ (c>=0x09f4 && c<=0x09fa) ||
+ (c==0x0a03) ||
+ (c>=0x0a05 && c<=0x0a0a) ||
+ (c>=0x0a0f && c<=0x0a10) ||
+ (c>=0x0a13 && c<=0x0a28) ||
+ (c>=0x0a2a && c<=0x0a30) ||
+ (c>=0x0a32 && c<=0x0a33) ||
+ (c>=0x0a35 && c<=0x0a36) ||
+ (c>=0x0a38 && c<=0x0a39) ||
+ (c>=0x0a3e && c<=0x0a40) ||
+ (c>=0x0a59 && c<=0x0a5c) ||
+ (c==0x0a5e) ||
+ (c>=0x0a66 && c<=0x0a6f) ||
+ (c>=0x0a72 && c<=0x0a74) ||
+ (c==0x0a83) ||
+ (c>=0x0a85 && c<=0x0a8d) ||
+ (c>=0x0a8f && c<=0x0a91) ||
+ (c>=0x0a93 && c<=0x0aa8) ||
+ (c>=0x0aaa && c<=0x0ab0) ||
+ (c>=0x0ab2 && c<=0x0ab3) ||
+ (c>=0x0ab5 && c<=0x0ab9) ||
+ (c>=0x0abd && c<=0x0ac0) ||
+ (c==0x0ac9) ||
+ (c>=0x0acb && c<=0x0acc) ||
+ (c==0x0ad0) ||
+ (c>=0x0ae0 && c<=0x0ae1) ||
+ (c>=0x0ae6 && c<=0x0aef) ||
+ (c>=0x0b02 && c<=0x0b03) ||
+ (c>=0x0b05 && c<=0x0b0c) ||
+ (c>=0x0b0f && c<=0x0b10) ||
+ (c>=0x0b13 && c<=0x0b28) ||
+ (c>=0x0b2a && c<=0x0b30) ||
+ (c>=0x0b32 && c<=0x0b33) ||
+ (c>=0x0b35 && c<=0x0b39) ||
+ (c>=0x0b3d && c<=0x0b3e) ||
+ (c==0x0b40) ||
+ (c>=0x0b47 && c<=0x0b48) ||
+ (c>=0x0b4b && c<=0x0b4c) ||
+ (c==0x0b57) ||
+ (c>=0x0b5c && c<=0x0b5d) ||
+ (c>=0x0b5f && c<=0x0b61) ||
+ (c>=0x0b66 && c<=0x0b71) ||
+ (c==0x0b83) ||
+ (c>=0x0b85 && c<=0x0b8a) ||
+ (c>=0x0b8e && c<=0x0b90) ||
+ (c>=0x0b92 && c<=0x0b95) ||
+ (c>=0x0b99 && c<=0x0b9a) ||
+ (c==0x0b9c) ||
+ (c>=0x0b9e && c<=0x0b9f) ||
+ (c>=0x0ba3 && c<=0x0ba4) ||
+ (c>=0x0ba8 && c<=0x0baa) ||
+ (c>=0x0bae && c<=0x0bb9) ||
+ (c>=0x0bbe && c<=0x0bbf) ||
+ (c>=0x0bc1 && c<=0x0bc2) ||
+ (c>=0x0bc6 && c<=0x0bc8) ||
+ (c>=0x0bca && c<=0x0bcc) ||
+ (c==0x0bd7) ||
+ (c>=0x0be6 && c<=0x0bf2) ||
+ (c>=0x0c01 && c<=0x0c03) ||
+ (c>=0x0c05 && c<=0x0c0c) ||
+ (c>=0x0c0e && c<=0x0c10) ||
+ (c>=0x0c12 && c<=0x0c28) ||
+ (c>=0x0c2a && c<=0x0c33) ||
+ (c>=0x0c35 && c<=0x0c39) ||
+ (c>=0x0c41 && c<=0x0c44) ||
+ (c>=0x0c60 && c<=0x0c61) ||
+ (c>=0x0c66 && c<=0x0c6f) ||
+ (c>=0x0c82 && c<=0x0c83) ||
+ (c>=0x0c85 && c<=0x0c8c) ||
+ (c>=0x0c8e && c<=0x0c90) ||
+ (c>=0x0c92 && c<=0x0ca8) ||
+ (c>=0x0caa && c<=0x0cb3) ||
+ (c>=0x0cb5 && c<=0x0cb9) ||
+ (c>=0x0cbd && c<=0x0cc4) ||
+ (c>=0x0cc6 && c<=0x0cc8) ||
+ (c>=0x0cca && c<=0x0ccb) ||
+ (c>=0x0cd5 && c<=0x0cd6) ||
+ (c==0x0cde) ||
+ (c>=0x0ce0 && c<=0x0ce1) ||
+ (c>=0x0ce6 && c<=0x0cef) ||
+ (c>=0x0d02 && c<=0x0d03) ||
+ (c>=0x0d05 && c<=0x0d0c) ||
+ (c>=0x0d0e && c<=0x0d10) ||
+ (c>=0x0d12 && c<=0x0d28) ||
+ (c>=0x0d2a && c<=0x0d39) ||
+ (c>=0x0d3e && c<=0x0d40) ||
+ (c>=0x0d46 && c<=0x0d48) ||
+ (c>=0x0d4a && c<=0x0d4c) ||
+ (c==0x0d57) ||
+ (c>=0x0d60 && c<=0x0d61) ||
+ (c>=0x0d66 && c<=0x0d6f) ||
+ (c>=0x0d82 && c<=0x0d83) ||
+ (c>=0x0d85 && c<=0x0d96) ||
+ (c>=0x0d9a && c<=0x0db1) ||
+ (c>=0x0db3 && c<=0x0dbb) ||
+ (c==0x0dbd) ||
+ (c>=0x0dc0 && c<=0x0dc6) ||
+ (c>=0x0dcf && c<=0x0dd1) ||
+ (c>=0x0dd8 && c<=0x0ddf) ||
+ (c>=0x0df2 && c<=0x0df4) ||
+ (c>=0x0e01 && c<=0x0e30) ||
+ (c>=0x0e32 && c<=0x0e33) ||
+ (c>=0x0e40 && c<=0x0e46) ||
+ (c>=0x0e4f && c<=0x0e5b) ||
+ (c>=0x0e81 && c<=0x0e82) ||
+ (c==0x0e84) ||
+ (c>=0x0e87 && c<=0x0e88) ||
+ (c==0x0e8a) ||
+ (c==0x0e8d) ||
+ (c>=0x0e94 && c<=0x0e97) ||
+ (c>=0x0e99 && c<=0x0e9f) ||
+ (c>=0x0ea1 && c<=0x0ea3) ||
+ (c==0x0ea5) ||
+ (c==0x0ea7) ||
+ (c>=0x0eaa && c<=0x0eab) ||
+ (c>=0x0ead && c<=0x0eb0) ||
+ (c>=0x0eb2 && c<=0x0eb3) ||
+ (c==0x0ebd) ||
+ (c>=0x0ec0 && c<=0x0ec4) ||
+ (c==0x0ec6) ||
+ (c>=0x0ed0 && c<=0x0ed9) ||
+ (c>=0x0edc && c<=0x0edd) ||
+ (c>=0x0f00 && c<=0x0f17) ||
+ (c>=0x0f1a && c<=0x0f34) ||
+ (c==0x0f36) ||
+ (c==0x0f38) ||
+ (c>=0x0f3e && c<=0x0f47) ||
+ (c>=0x0f49 && c<=0x0f6a) ||
+ (c==0x0f7f) ||
+ (c==0x0f85) ||
+ (c>=0x0f88 && c<=0x0f8b) ||
+ (c>=0x0fbe && c<=0x0fc5) ||
+ (c>=0x0fc7 && c<=0x0fcc) ||
+ (c>=0x0fcf && c<=0x0fd1) ||
+ (c>=0x1000 && c<=0x1021) ||
+ (c>=0x1023 && c<=0x1027) ||
+ (c>=0x1029 && c<=0x102a) ||
+ (c==0x102c) ||
+ (c==0x1031) ||
+ (c==0x1038) ||
+ (c>=0x1040 && c<=0x1057) ||
+ (c>=0x10a0 && c<=0x10c5) ||
+ (c>=0x10d0 && c<=0x10fc) ||
+ (c>=0x1100 && c<=0x1159) ||
+ (c>=0x115f && c<=0x11a2) ||
+ (c>=0x11a8 && c<=0x11f9) ||
+ (c>=0x1200 && c<=0x1248) ||
+ (c>=0x124a && c<=0x124d) ||
+ (c>=0x1250 && c<=0x1256) ||
+ (c==0x1258) ||
+ (c>=0x125a && c<=0x125d) ||
+ (c>=0x1260 && c<=0x1288) ||
+ (c>=0x128a && c<=0x128d) ||
+ (c>=0x1290 && c<=0x12b0) ||
+ (c>=0x12b2 && c<=0x12b5) ||
+ (c>=0x12b8 && c<=0x12be) ||
+ (c==0x12c0) ||
+ (c>=0x12c2 && c<=0x12c5) ||
+ (c>=0x12c8 && c<=0x12d6) ||
+ (c>=0x12d8 && c<=0x1310) ||
+ (c>=0x1312 && c<=0x1315) ||
+ (c>=0x1318 && c<=0x135a) ||
+ (c>=0x1360 && c<=0x137c) ||
+ (c>=0x1380 && c<=0x138f) ||
+ (c>=0x13a0 && c<=0x13f4) ||
+ (c>=0x1401 && c<=0x1676) ||
+ (c>=0x1681 && c<=0x169a) ||
+ (c>=0x16a0 && c<=0x16f0) ||
+ (c>=0x1700 && c<=0x170c) ||
+ (c>=0x170e && c<=0x1711) ||
+ (c>=0x1720 && c<=0x1731) ||
+ (c>=0x1735 && c<=0x1736) ||
+ (c>=0x1740 && c<=0x1751) ||
+ (c>=0x1760 && c<=0x176c) ||
+ (c>=0x176e && c<=0x1770) ||
+ (c>=0x1780 && c<=0x17b6) ||
+ (c>=0x17be && c<=0x17c5) ||
+ (c>=0x17c7 && c<=0x17c8) ||
+ (c>=0x17d4 && c<=0x17da) ||
+ (c==0x17dc) ||
+ (c>=0x17e0 && c<=0x17e9) ||
+ (c>=0x1810 && c<=0x1819) ||
+ (c>=0x1820 && c<=0x1877) ||
+ (c>=0x1880 && c<=0x18a8) ||
+ (c>=0x1900 && c<=0x191c) ||
+ (c>=0x1923 && c<=0x1926) ||
+ (c>=0x1930 && c<=0x1931) ||
+ (c>=0x1933 && c<=0x1938) ||
+ (c>=0x1946 && c<=0x196d) ||
+ (c>=0x1970 && c<=0x1974) ||
+ (c>=0x1980 && c<=0x19a9) ||
+ (c>=0x19b0 && c<=0x19c9) ||
+ (c>=0x19d0 && c<=0x19d9) ||
+ (c>=0x1a00 && c<=0x1a16) ||
+ (c>=0x1a19 && c<=0x1a1b) ||
+ (c>=0x1a1e && c<=0x1a1f) ||
+ (c>=0x1b04 && c<=0x1b33) ||
+ (c==0x1b35) ||
+ (c==0x1b3b) ||
+ (c>=0x1b3d && c<=0x1b41) ||
+ (c>=0x1b43 && c<=0x1b4b) ||
+ (c>=0x1b50 && c<=0x1b6a) ||
+ (c>=0x1b74 && c<=0x1b7c) ||
+ (c>=0x1d00 && c<=0x1dbf) ||
+ (c>=0x1e00 && c<=0x1e9b) ||
+ (c>=0x1ea0 && c<=0x1ef9) ||
+ (c>=0x1f00 && c<=0x1f15) ||
+ (c>=0x1f18 && c<=0x1f1d) ||
+ (c>=0x1f20 && c<=0x1f45) ||
+ (c>=0x1f48 && c<=0x1f4d) ||
+ (c>=0x1f50 && c<=0x1f57) ||
+ (c==0x1f59) ||
+ (c==0x1f5b) ||
+ (c==0x1f5d) ||
+ (c>=0x1f5f && c<=0x1f7d) ||
+ (c>=0x1f80 && c<=0x1fb4) ||
+ (c>=0x1fb6 && c<=0x1fbc) ||
+ (c==0x1fbe) ||
+ (c>=0x1fc2 && c<=0x1fc4) ||
+ (c>=0x1fc6 && c<=0x1fcc) ||
+ (c>=0x1fd0 && c<=0x1fd3) ||
+ (c>=0x1fd6 && c<=0x1fdb) ||
+ (c>=0x1fe0 && c<=0x1fec) ||
+ (c>=0x1ff2 && c<=0x1ff4) ||
+ (c>=0x1ff6 && c<=0x1ffc) ||
+ (c==0x200e) ||
+ (c==0x202a) ||
+ (c==0x202d) ||
+ (c==0x2071) ||
+ (c==0x207f) ||
+ (c>=0x2090 && c<=0x2094) ||
+ (c==0x2102) ||
+ (c==0x2107) ||
+ (c>=0x210a && c<=0x2113) ||
+ (c==0x2115) ||
+ (c>=0x2119 && c<=0x211d) ||
+ (c==0x2124) ||
+ (c==0x2126) ||
+ (c==0x2128) ||
+ (c>=0x212a && c<=0x212d) ||
+ (c>=0x212f && c<=0x2139) ||
+ (c>=0x213c && c<=0x213f) ||
+ (c>=0x2145 && c<=0x2149) ||
+ (c==0x214e) ||
+ (c>=0x2160 && c<=0x2184) ||
+ (c>=0x2336 && c<=0x237a) ||
+ (c==0x2395) ||
+ (c>=0x249c && c<=0x24e9) ||
+ (c==0x26ac) ||
+ (c>=0x2800 && c<=0x28ff) ||
+ (c>=0x2c00 && c<=0x2c2e) ||
+ (c>=0x2c30 && c<=0x2c5e) ||
+ (c>=0x2c60 && c<=0x2c6c) ||
+ (c>=0x2c74 && c<=0x2c77) ||
+ (c>=0x2c80 && c<=0x2ce4) ||
+ (c>=0x2d00 && c<=0x2d25) ||
+ (c>=0x2d30 && c<=0x2d65) ||
+ (c==0x2d6f) ||
+ (c>=0x2d80 && c<=0x2d96) ||
+ (c>=0x2da0 && c<=0x2da6) ||
+ (c>=0x2da8 && c<=0x2dae) ||
+ (c>=0x2db0 && c<=0x2db6) ||
+ (c>=0x2db8 && c<=0x2dbe) ||
+ (c>=0x2dc0 && c<=0x2dc6) ||
+ (c>=0x2dc8 && c<=0x2dce) ||
+ (c>=0x2dd0 && c<=0x2dd6) ||
+ (c>=0x2dd8 && c<=0x2dde) ||
+ (c>=0x3005 && c<=0x3007) ||
+ (c>=0x3021 && c<=0x3029) ||
+ (c>=0x3031 && c<=0x3035) ||
+ (c>=0x3038 && c<=0x303c) ||
+ (c>=0x3041 && c<=0x3096) ||
+ (c>=0x309d && c<=0x309f) ||
+ (c>=0x30a1 && c<=0x30fa) ||
+ (c>=0x30fc && c<=0x30ff) ||
+ (c>=0x3105 && c<=0x312c) ||
+ (c>=0x3131 && c<=0x318e) ||
+ (c>=0x3190 && c<=0x31b7) ||
+ (c>=0x31f0 && c<=0x321c) ||
+ (c>=0x3220 && c<=0x3243) ||
+ (c>=0x3260 && c<=0x327b) ||
+ (c>=0x327f && c<=0x32b0) ||
+ (c>=0x32c0 && c<=0x32cb) ||
+ (c>=0x32d0 && c<=0x32fe) ||
+ (c>=0x3300 && c<=0x3376) ||
+ (c>=0x337b && c<=0x33dd) ||
+ (c>=0x33e0 && c<=0x33fe) ||
+ (c>=0x3400 && c<=0x4db5) ||
+ (c>=0x4e00 && c<=0x9fbb) ||
+ (c>=0xa000 && c<=0xa48c) ||
+ (c>=0xa800 && c<=0xa801) ||
+ (c>=0xa803 && c<=0xa805) ||
+ (c>=0xa807 && c<=0xa80a) ||
+ (c>=0xa80c && c<=0xa824) ||
+ (c==0xa827) ||
+ (c>=0xa840 && c<=0xa873) ||
+ (c>=0xac00 && c<=0xd7a3) ||
+ (c>=0xd800 && c<=0xfa2d) ||
+ (c>=0xfa30 && c<=0xfa6a) ||
+ (c>=0xfa70 && c<=0xfad9) ||
+ (c>=0xfb00 && c<=0xfb06) ||
+ (c>=0xfb13 && c<=0xfb17) ||
+ (c>=0xff21 && c<=0xff3a) ||
+ (c>=0xff41 && c<=0xff5a) ||
+ (c>=0xff66 && c<=0xffbe) ||
+ (c>=0xffc2 && c<=0xffc7) ||
+ (c>=0xffca && c<=0xffcf) ||
+ (c>=0xffd2 && c<=0xffd7) ||
+ (c>=0xffda && c<=0xffdc)) {
+ return 1;
+ }
+ return 0;
+}
+
+int unic_isdigit (int c) {
+ if ((c>=0x0030 && c<=0x0039) ||
+ (c>=0x0660 && c<=0x0669) ||
+ (c>=0x06f0 && c<=0x06f9) ||
+ (c>=0x07c0 && c<=0x07c9) ||
+ (c>=0x0966 && c<=0x096f) ||
+ (c>=0x09e6 && c<=0x09ef) ||
+ (c>=0x0a66 && c<=0x0a6f) ||
+ (c>=0x0ae6 && c<=0x0aef) ||
+ (c>=0x0b66 && c<=0x0b6f) ||
+ (c>=0x0be6 && c<=0x0bef) ||
+ (c>=0x0c66 && c<=0x0c6f) ||
+ (c>=0x0ce6 && c<=0x0cef) ||
+ (c>=0x0d66 && c<=0x0d6f) ||
+ (c>=0x0e50 && c<=0x0e59) ||
+ (c>=0x0ed0 && c<=0x0ed9) ||
+ (c>=0x0f20 && c<=0x0f29) ||
+ (c>=0x1040 && c<=0x1049) ||
+ (c>=0x17e0 && c<=0x17e9) ||
+ (c>=0x1810 && c<=0x1819) ||
+ (c>=0x1946 && c<=0x194f) ||
+ (c>=0x19d0 && c<=0x19d9) ||
+ (c>=0x1b50 && c<=0x1b59) ||
+ (c>=0xff10 && c<=0xff19))
+ return 1;
+ return 0;
+}
+
+
+int unic_iscombining (int c) {
+ if ((c>=0x0300 && c<=0x0357) ||
+ (c>=0x035d && c<=0x0362) ||
+ (c>=0x0483 && c<=0x0486) ||
+ (c>=0x07eb && c<=0x07f3) ||
+ (c>=0x1b6b && c<=0x1b73) ||
+ (c>=0x1dc4 && c<=0x1dca) ||
+ (c>=0x1dfe && c<=0x1dff) ||
+ (c==0x202a) ||
+ (c>=0x20d0 && c<=0x20dc) ||
+ (c==0x20e1) ||
+ (c>=0x20e5 && c<=0x20e6) ||
+ (c>=0x20ec && c<=0x20ef) ||
+ (c>=0x3099 && c<=0x309a) ||
+ (c>=0xfe20 && c<=0xfe23) )
+ return 1;
+ return 0;
+}
+
+/* cleaned out some of the incidental holes in ranges already, but
+ there are more */
+
+int unic_isalpha (int c) {
+ if((c>=0x0041&&c<=0x005a) ||
+ (c>=0x0061&&c<=0x007a) ||
+ (c==0x00aa) ||
+ (c==0x00b5) ||
+ (c==0x00ba) ||
+ (c>=0x00c0&&c<=0x01bf) ||
+ (c>=0x01c4&&c<=0x02af) ||
+ (c==0x0345) ||
+ (c>=0x037b&&c<=0x037d) ||
+ (c==0x0386) ||
+ (c>=0x0388&&c<=0x038a) ||
+ (c==0x038c) ||
+ (c>=0x038e&&c<=0x0481) ||
+ (c>=0x048a&&c<=0x0513) ||
+ (c>=0x0531&&c<=0x0556) ||
+ (c>=0x0561&&c<=0x0587) ||
+ (c>=0x05b0&&c<=0x05bd) ||
+ (c==0x05bf) ||
+ (c>=0x05c1&&c<=0x05c2) ||
+ (c>=0x05c4&&c<=0x05c5) ||
+ (c==0x05c7) ||
+ (c>=0x0610&&c<=0x0615) ||
+ (c>=0x064b&&c<=0x0657) ||
+ (c>=0x0659&&c<=0x065e) ||
+ (c==0x0670) ||
+ (c>=0x06d6&&c<=0x06dc) ||
+ (c>=0x06e1&&c<=0x06e4) ||
+ (c>=0x06e7&&c<=0x06e8) ||
+ (c==0x06ed) ||
+ (c==0x0711) ||
+ (c>=0x0730&&c<=0x073f) ||
+ (c>=0x07a6&&c<=0x07b0) ||
+ (c>=0x0901&&c<=0x0903) ||
+ (c>=0x093e&&c<=0x094c) ||
+ (c>=0x0962&&c<=0x0963) ||
+ (c>=0x0981&&c<=0x0983) ||
+ (c>=0x09be&&c<=0x09c4) ||
+ (c>=0x09c7&&c<=0x09c8) ||
+ (c>=0x09cb&&c<=0x09cc) ||
+ (c==0x09d7) ||
+ (c>=0x09e2&&c<=0x09e3) ||
+ (c>=0x0a01&&c<=0x0a03) ||
+ (c>=0x0a3e&&c<=0x0a42) ||
+ (c>=0x0a47&&c<=0x0a48) ||
+ (c>=0x0a4b&&c<=0x0a4c) ||
+ (c>=0x0a70&&c<=0x0a71) ||
+ (c>=0x0a81&&c<=0x0a83) ||
+ (c>=0x0abe&&c<=0x0ac5) ||
+ (c>=0x0ac7&&c<=0x0ac9) ||
+ (c>=0x0acb&&c<=0x0acc) ||
+ (c>=0x0ae2&&c<=0x0ae3) ||
+ (c>=0x0b01&&c<=0x0b03) ||
+ (c>=0x0b3e&&c<=0x0b43) ||
+ (c>=0x0b47&&c<=0x0b48) ||
+ (c>=0x0b4b&&c<=0x0b4c) ||
+ (c>=0x0b56&&c<=0x0b57) ||
+ (c==0x0b82) ||
+ (c>=0x0bbe&&c<=0x0bc2) ||
+ (c>=0x0bc6&&c<=0x0bc8) ||
+ (c>=0x0bca&&c<=0x0bcc) ||
+ (c==0x0bd7) ||
+ (c>=0x0c01&&c<=0x0c03) ||
+ (c>=0x0c3e&&c<=0x0c44) ||
+ (c>=0x0c46&&c<=0x0c48) ||
+ (c>=0x0c4a&&c<=0x0c4c) ||
+ (c>=0x0c55&&c<=0x0c56) ||
+ (c>=0x0c82&&c<=0x0c83) ||
+ (c>=0x0cbe&&c<=0x0cc4) ||
+ (c>=0x0cc6&&c<=0x0cc8) ||
+ (c>=0x0cca&&c<=0x0ccc) ||
+ (c>=0x0cd5&&c<=0x0cd6) ||
+ (c>=0x0ce2&&c<=0x0ce3) ||
+ (c>=0x0d02&&c<=0x0d03) ||
+ (c>=0x0d3e&&c<=0x0d43) ||
+ (c>=0x0d46&&c<=0x0d48) ||
+ (c>=0x0d4a&&c<=0x0d4c) ||
+ (c==0x0d57) ||
+ (c>=0x0d82&&c<=0x0d83) ||
+ (c>=0x0dcf&&c<=0x0dd4) ||
+ (c==0x0dd6) ||
+ (c>=0x0dd8&&c<=0x0ddf) ||
+ (c>=0x0df2&&c<=0x0df3) ||
+ (c==0x0e31) ||
+ (c>=0x0e34&&c<=0x0e3a) ||
+ (c==0x0e4d) ||
+ (c==0x0eb1) ||
+ (c>=0x0eb4&&c<=0x0eb9) ||
+ (c>=0x0ebb&&c<=0x0ebc) ||
+ (c==0x0ecd) ||
+ (c>=0x0f71&&c<=0x0f81) ||
+ (c>=0x0f90&&c<=0x0f97) ||
+ (c>=0x0f99&&c<=0x0fbc) ||
+ (c>=0x102c&&c<=0x1032) ||
+ (c==0x1036) ||
+ (c==0x1038) ||
+ (c>=0x1056&&c<=0x1059) ||
+ (c>=0x10a0&&c<=0x10c5) ||
+ (c==0x135f) ||
+ (c>=0x1712&&c<=0x1713) ||
+ (c>=0x1732&&c<=0x1733) ||
+ (c>=0x1752&&c<=0x1753) ||
+ (c>=0x1772&&c<=0x1773) ||
+ (c>=0x17b6&&c<=0x17c8) ||
+ (c==0x18a9) ||
+ (c>=0x1920&&c<=0x192b) ||
+ (c>=0x1930&&c<=0x1938) ||
+ (c>=0x19b0&&c<=0x19c0) ||
+ (c>=0x19c8&&c<=0x19c9) ||
+ (c>=0x1a17&&c<=0x1a1b) ||
+ (c>=0x1b00&&c<=0x1b04) ||
+ (c>=0x1b35&&c<=0x1b43) ||
+ (c>=0x1d00&&c<=0x1d2b) ||
+ (c>=0x1d62&&c<=0x1d77) ||
+ (c>=0x1d79&&c<=0x1d9a) ||
+ (c>=0x1e00&&c<=0x1e9b) ||
+ (c>=0x1ea0&&c<=0x1ef9) ||
+ (c>=0x1f00&&c<=0x1f15) ||
+ (c>=0x1f18&&c<=0x1f1d) ||
+ (c>=0x1f20&&c<=0x1f45) ||
+ (c>=0x1f48&&c<=0x1f4d) ||
+ (c>=0x1f50&&c<=0x1f57) ||
+ (c==0x1f59) ||
+ (c==0x1f5b) ||
+ (c==0x1f5d) ||
+ (c>=0x1f5f&&c<=0x1f7d) ||
+ (c>=0x1f80&&c<=0x1fb4) ||
+ (c>=0x1fb6&&c<=0x1fbc) ||
+ (c==0x1fbe) ||
+ (c>=0x1fc2&&c<=0x1fc4) ||
+ (c>=0x1fc6&&c<=0x1fcc) ||
+ (c>=0x1fd0&&c<=0x1fd3) ||
+ (c>=0x1fd6&&c<=0x1fdb) ||
+ (c>=0x1fe0&&c<=0x1fec) ||
+ (c>=0x1ff2&&c<=0x1ff4) ||
+ (c>=0x1ff6&&c<=0x1ffc) ||
+ (c==0x2071) ||
+ (c==0x207f) ||
+ (c==0x2102) ||
+ (c==0x2107) ||
+ (c>=0x210a&&c<=0x2113) ||
+ (c==0x2115) ||
+ (c>=0x2119&&c<=0x211d) ||
+ (c==0x2124) ||
+ (c==0x2126) ||
+ (c==0x2128) ||
+ (c>=0x212a&&c<=0x212d) ||
+ (c>=0x212f&&c<=0x2134) ||
+ (c==0x2139) ||
+ (c>=0x213c&&c<=0x213f) ||
+ (c>=0x2145&&c<=0x2149) ||
+ (c==0x214e) ||
+ (c>=0x2183&&c<=0x2184) ||
+ (c>=0x24b6&&c<=0x24e9) ||
+ (c>=0x2c00&&c<=0x2c2e) ||
+ (c>=0x2c30&&c<=0x2c5e) ||
+ (c>=0x2c60&&c<=0x2c6c) ||
+ (c>=0x2c74&&c<=0x2c77) ||
+ (c>=0x2c80&&c<=0x2ce4) ||
+ (c>=0x2d00&&c<=0x2d25) ||
+ (c>=0xa823&&c<=0xa827) ||
+ (c>=0xfb00&&c<=0xfb06) ||
+ (c>=0xfb13&&c<=0xfb17) ||
+ (c==0xfb1e) ||
+ (c>=0xff21&&c<=0xff3a) ||
+ (c>=0xff41&&c<=0xff5a)) {
+ if (c==0x00d7||c==0x00f7||c==0x01bb||c==0x0294||c==0x03a2||c==0x03cf||c==0x03f6)
+ return 0;
+ else
+ return 1;
+ }
+ return 0;
+}
+
+const unsigned short ____tolower[]= { 0,
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
+ 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
+ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
+ 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
+ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
+ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00d7,
+ 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00df,
+ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
+ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
+ 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff,
+ 0x0101, 0x0101, 0x0103, 0x0103, 0x0105, 0x0105, 0x0107, 0x0107,
+ 0x0109, 0x0109, 0x010b, 0x010b, 0x010d, 0x010d, 0x010f, 0x010f,
+ 0x0111, 0x0111, 0x0113, 0x0113, 0x0115, 0x0115, 0x0117, 0x0117,
+ 0x0119, 0x0119, 0x011b, 0x011b, 0x011d, 0x011d, 0x011f, 0x011f,
+ 0x0121, 0x0121, 0x0123, 0x0123, 0x0125, 0x0125, 0x0127, 0x0127,
+ 0x0129, 0x0129, 0x012b, 0x012b, 0x012d, 0x012d, 0x012f, 0x012f,
+ 0x0069, 0x0131, 0x0133, 0x0133, 0x0135, 0x0135, 0x0137, 0x0137,
+ 0x0138, 0x013a, 0x013a, 0x013c, 0x013c, 0x013e, 0x013e, 0x0140,
+ 0x0140, 0x0142, 0x0142, 0x0144, 0x0144, 0x0146, 0x0146, 0x0148,
+ 0x0148, 0x0149, 0x014b, 0x014b, 0x014d, 0x014d, 0x014f, 0x014f,
+ 0x0151, 0x0151, 0x0153, 0x0153, 0x0155, 0x0155, 0x0157, 0x0157,
+ 0x0159, 0x0159, 0x015b, 0x015b, 0x015d, 0x015d, 0x015f, 0x015f,
+ 0x0161, 0x0161, 0x0163, 0x0163, 0x0165, 0x0165, 0x0167, 0x0167,
+ 0x0169, 0x0169, 0x016b, 0x016b, 0x016d, 0x016d, 0x016f, 0x016f,
+ 0x0171, 0x0171, 0x0173, 0x0173, 0x0175, 0x0175, 0x0177, 0x0177,
+ 0x00ff, 0x017a, 0x017a, 0x017c, 0x017c, 0x017e, 0x017e, 0x017f,
+ 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
+ 0x0188, 0x0256, 0x0257, 0x018c, 0x018c, 0x018d, 0x01dd, 0x0259,
+ 0x025b, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
+ 0x0199, 0x0199, 0x019a, 0x019b, 0x026f, 0x0272, 0x019e, 0x0275,
+ 0x01a1, 0x01a1, 0x01a3, 0x01a3, 0x01a5, 0x01a5, 0x0280, 0x01a8,
+ 0x01a8, 0x0283, 0x01aa, 0x01ab, 0x01ad, 0x01ad, 0x0288, 0x01b0,
+ 0x01b0, 0x028a, 0x028b, 0x01b4, 0x01b4, 0x01b6, 0x01b6, 0x0292,
+ 0x01b9, 0x01b9, 0x01ba, 0x01bb, 0x01bd, 0x01bd, 0x01be, 0x01bf,
+ 0x01c0, 0x01c1, 0x01c2, 0x01c3, 0x01c6, 0x01c6, 0x01c6, 0x01c9,
+ 0x01c9, 0x01c9, 0x01cc, 0x01cc, 0x01cc, 0x01ce, 0x01ce, 0x01d0,
+ 0x01d0, 0x01d2, 0x01d2, 0x01d4, 0x01d4, 0x01d6, 0x01d6, 0x01d8,
+ 0x01d8, 0x01da, 0x01da, 0x01dc, 0x01dc, 0x01dd, 0x01df, 0x01df,
+ 0x01e1, 0x01e1, 0x01e3, 0x01e3, 0x01e5, 0x01e5, 0x01e7, 0x01e7,
+ 0x01e9, 0x01e9, 0x01eb, 0x01eb, 0x01ed, 0x01ed, 0x01ef, 0x01ef,
+ 0x01f0, 0x01f3, 0x01f3, 0x01f3, 0x01f5, 0x01f5, 0x0195, 0x01bf,
+ 0x01f9, 0x01f9, 0x01fb, 0x01fb, 0x01fd, 0x01fd, 0x01ff, 0x01ff,
+ 0x0201, 0x0201, 0x0203, 0x0203, 0x0205, 0x0205, 0x0207, 0x0207,
+ 0x0209, 0x0209, 0x020b, 0x020b, 0x020d, 0x020d, 0x020f, 0x020f,
+ 0x0211, 0x0211, 0x0213, 0x0213, 0x0215, 0x0215, 0x0217, 0x0217,
+ 0x0219, 0x0219, 0x021b, 0x021b, 0x021d, 0x021d, 0x021f, 0x021f,
+ 0x019e, 0x0221, 0x0223, 0x0223, 0x0225, 0x0225, 0x0227, 0x0227,
+ 0x0229, 0x0229, 0x022b, 0x022b, 0x022d, 0x022d, 0x022f, 0x022f,
+ 0x0231, 0x0231, 0x0233, 0x0233, 0x0234, 0x0235, 0x0236, 0x0237,
+ 0x0238, 0x0239, 0x2c65, 0x023c, 0x023c, 0x019a, 0x2c66, 0x023f,
+ 0x0240, 0x0242, 0x0242, 0x0180, 0x0289, 0x028c, 0x0247, 0x0247,
+ 0x0249, 0x0249, 0x024b, 0x024b, 0x024d, 0x024d, 0x024f, 0x024f,
+ 0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0257,
+ 0x0258, 0x0259, 0x025a, 0x025b, 0x025c, 0x025d, 0x025e, 0x025f,
+ 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, 0x0265, 0x0266, 0x0267,
+ 0x0268, 0x0269, 0x026a, 0x026b, 0x026c, 0x026d, 0x026e, 0x026f,
+ 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277,
+ 0x0278, 0x0279, 0x027a, 0x027b, 0x027c, 0x027d, 0x027e, 0x027f,
+ 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287,
+ 0x0288, 0x0289, 0x028a, 0x028b, 0x028c, 0x028d, 0x028e, 0x028f,
+ 0x0290, 0x0291, 0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297,
+ 0x0298, 0x0299, 0x029a, 0x029b, 0x029c, 0x029d, 0x029e, 0x029f,
+ 0x02a0, 0x02a1, 0x02a2, 0x02a3, 0x02a4, 0x02a5, 0x02a6, 0x02a7,
+ 0x02a8, 0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ad, 0x02ae, 0x02af,
+ 0x02b0, 0x02b1, 0x02b2, 0x02b3, 0x02b4, 0x02b5, 0x02b6, 0x02b7,
+ 0x02b8, 0x02b9, 0x02ba, 0x02bb, 0x02bc, 0x02bd, 0x02be, 0x02bf,
+ 0x02c0, 0x02c1, 0x02c2, 0x02c3, 0x02c4, 0x02c5, 0x02c6, 0x02c7,
+ 0x02c8, 0x02c9, 0x02ca, 0x02cb, 0x02cc, 0x02cd, 0x02ce, 0x02cf,
+ 0x02d0, 0x02d1, 0x02d2, 0x02d3, 0x02d4, 0x02d5, 0x02d6, 0x02d7,
+ 0x02d8, 0x02d9, 0x02da, 0x02db, 0x02dc, 0x02dd, 0x02de, 0x02df,
+ 0x02e0, 0x02e1, 0x02e2, 0x02e3, 0x02e4, 0x02e5, 0x02e6, 0x02e7,
+ 0x02e8, 0x02e9, 0x02ea, 0x02eb, 0x02ec, 0x02ed, 0x02ee, 0x02ef,
+ 0x02f0, 0x02f1, 0x02f2, 0x02f3, 0x02f4, 0x02f5, 0x02f6, 0x02f7,
+ 0x02f8, 0x02f9, 0x02fa, 0x02fb, 0x02fc, 0x02fd, 0x02fe, 0x02ff,
+ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
+ 0x0308, 0x0309, 0x030a, 0x030b, 0x030c, 0x030d, 0x030e, 0x030f,
+ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
+ 0x0318, 0x0319, 0x031a, 0x031b, 0x031c, 0x031d, 0x031e, 0x031f,
+ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
+ 0x0328, 0x0329, 0x032a, 0x032b, 0x032c, 0x032d, 0x032e, 0x032f,
+ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
+ 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, 0x033d, 0x033e, 0x033f,
+ 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347,
+ 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, 0x034d, 0x034e, 0x034f,
+ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
+ 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, 0x035d, 0x035e, 0x035f,
+ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
+ 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x037a, 0x037b, 0x037c, 0x037d, 0x037e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x03ac, 0x0387,
+ 0x03ad, 0x03ae, 0x03af, 0x0000, 0x03cc, 0x0000, 0x03cd, 0x03ce,
+ 0x0390, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
+ 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
+ 0x03c0, 0x03c1, 0x0000, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7,
+ 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03ac, 0x03ad, 0x03ae, 0x03af,
+ 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
+ 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
+ 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7,
+ 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0000,
+ 0x03d0, 0x03d1, 0x03d2, 0x03d3, 0x03d4, 0x03d5, 0x03d6, 0x03d7,
+ 0x03d9, 0x03d9, 0x03db, 0x03db, 0x03dd, 0x03dd, 0x03df, 0x03df,
+ 0x03e1, 0x03e1, 0x03e3, 0x03e3, 0x03e5, 0x03e5, 0x03e7, 0x03e7,
+ 0x03e9, 0x03e9, 0x03eb, 0x03eb, 0x03ed, 0x03ed, 0x03ef, 0x03ef,
+ 0x03f0, 0x03f1, 0x03f2, 0x03f3, 0x03b8, 0x03f5, 0x03f6, 0x03f8,
+ 0x03f8, 0x03f2, 0x03fb, 0x03fb, 0x03fc, 0x037b, 0x037c, 0x037d,
+ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
+ 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045d, 0x045e, 0x045f,
+ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+ 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
+ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+ 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
+ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
+ 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045d, 0x045e, 0x045f,
+ 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467,
+ 0x0469, 0x0469, 0x046b, 0x046b, 0x046d, 0x046d, 0x046f, 0x046f,
+ 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0477, 0x0477,
+ 0x0479, 0x0479, 0x047b, 0x047b, 0x047d, 0x047d, 0x047f, 0x047f,
+ 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0000,
+ 0x0488, 0x0489, 0x048b, 0x048b, 0x048d, 0x048d, 0x048f, 0x048f,
+ 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497,
+ 0x0499, 0x0499, 0x049b, 0x049b, 0x049d, 0x049d, 0x049f, 0x049f,
+ 0x04a1, 0x04a1, 0x04a3, 0x04a3, 0x04a5, 0x04a5, 0x04a7, 0x04a7,
+ 0x04a9, 0x04a9, 0x04ab, 0x04ab, 0x04ad, 0x04ad, 0x04af, 0x04af,
+ 0x04b1, 0x04b1, 0x04b3, 0x04b3, 0x04b5, 0x04b5, 0x04b7, 0x04b7,
+ 0x04b9, 0x04b9, 0x04bb, 0x04bb, 0x04bd, 0x04bd, 0x04bf, 0x04bf,
+ 0x04cf, 0x04c2, 0x04c2, 0x04c4, 0x04c4, 0x04c6, 0x04c6, 0x04c8,
+ 0x04c8, 0x04ca, 0x04ca, 0x04cc, 0x04cc, 0x04ce, 0x04ce, 0x04cf,
+ 0x04d1, 0x04d1, 0x04d3, 0x04d3, 0x04d5, 0x04d5, 0x04d7, 0x04d7,
+ 0x04d9, 0x04d9, 0x04db, 0x04db, 0x04dd, 0x04dd, 0x04df, 0x04df,
+ 0x04e1, 0x04e1, 0x04e3, 0x04e3, 0x04e5, 0x04e5, 0x04e7, 0x04e7,
+ 0x04e9, 0x04e9, 0x04eb, 0x04eb, 0x04ed, 0x04ed, 0x04ef, 0x04ef,
+ 0x04f1, 0x04f1, 0x04f3, 0x04f3, 0x04f5, 0x04f5, 0x04f7, 0x04f7,
+ 0x04f9, 0x04f9, 0x04fb, 0x04fb, 0x04fd, 0x04fd, 0x04ff, 0x04ff,
+ 0x0501, 0x0501, 0x0503, 0x0503, 0x0505, 0x0505, 0x0507, 0x0507,
+ 0x0509, 0x0509, 0x050b, 0x050b, 0x050d, 0x050d, 0x050f, 0x050f,
+ 0x0511, 0x0511, 0x0513, 0x0513, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
+ 0x0568, 0x0569, 0x056a, 0x056b, 0x056c, 0x056d, 0x056e, 0x056f,
+ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
+ 0x0578, 0x0579, 0x057a, 0x057b, 0x057c, 0x057d, 0x057e, 0x057f,
+ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0000,
+ 0x0000, 0x0559, 0x055a, 0x055b, 0x055c, 0x055d, 0x055e, 0x055f,
+ 0x0000, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
+ 0x0568, 0x0569, 0x056a, 0x056b, 0x056c, 0x056d, 0x056e, 0x056f,
+ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
+ 0x0578, 0x0579, 0x057a, 0x057b, 0x057c, 0x057d, 0x057e, 0x057f,
+ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587,
+ 0x0000, 0x0589, 0x058a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597,
+ 0x0598, 0x0599, 0x059a, 0x059b, 0x059c, 0x059d, 0x059e, 0x059f,
+ 0x05a0, 0x05a1, 0x05a2, 0x05a3, 0x05a4, 0x05a5, 0x05a6, 0x05a7,
+ 0x05a8, 0x05a9, 0x05aa, 0x05ab, 0x05ac, 0x05ad, 0x05ae, 0x05af,
+ 0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7,
+ 0x05b8, 0x05b9, 0x05ba, 0x05bb, 0x05bc, 0x05bd, 0x05be, 0x05bf,
+ 0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05c4, 0x05c5, 0x05c6, 0x05c7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7,
+ 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df,
+ 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7,
+ 0x05e8, 0x05e9, 0x05ea, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x05f0, 0x05f1, 0x05f2, 0x05f3, 0x05f4, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0600, 0x0601, 0x0602, 0x0603, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x060b, 0x060c, 0x060d, 0x060e, 0x060f,
+ 0x0610, 0x0611, 0x0612, 0x0613, 0x0614, 0x0615, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x061b, 0x0000, 0x0000, 0x061e, 0x061f,
+ 0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
+ 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f,
+ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637,
+ 0x0638, 0x0639, 0x063a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647,
+ 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f,
+ 0x0650, 0x0651, 0x0652, 0x0653, 0x0654, 0x0655, 0x0656, 0x0657,
+ 0x0658, 0x0659, 0x065a, 0x065b, 0x065c, 0x065d, 0x065e, 0x0000,
+ 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667,
+ 0x0668, 0x0669, 0x066a, 0x066b, 0x066c, 0x066d, 0x066e, 0x066f,
+ 0x0670, 0x0671, 0x0672, 0x0673, 0x0674, 0x0675, 0x0676, 0x0677,
+ 0x0678, 0x0679, 0x067a, 0x067b, 0x067c, 0x067d, 0x067e, 0x067f,
+ 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0686, 0x0687,
+ 0x0688, 0x0689, 0x068a, 0x068b, 0x068c, 0x068d, 0x068e, 0x068f,
+ 0x0690, 0x0691, 0x0692, 0x0693, 0x0694, 0x0695, 0x0696, 0x0697,
+ 0x0698, 0x0699, 0x069a, 0x069b, 0x069c, 0x069d, 0x069e, 0x069f,
+ 0x06a0, 0x06a1, 0x06a2, 0x06a3, 0x06a4, 0x06a5, 0x06a6, 0x06a7,
+ 0x06a8, 0x06a9, 0x06aa, 0x06ab, 0x06ac, 0x06ad, 0x06ae, 0x06af,
+ 0x06b0, 0x06b1, 0x06b2, 0x06b3, 0x06b4, 0x06b5, 0x06b6, 0x06b7,
+ 0x06b8, 0x06b9, 0x06ba, 0x06bb, 0x06bc, 0x06bd, 0x06be, 0x06bf,
+ 0x06c0, 0x06c1, 0x06c2, 0x06c3, 0x06c4, 0x06c5, 0x06c6, 0x06c7,
+ 0x06c8, 0x06c9, 0x06ca, 0x06cb, 0x06cc, 0x06cd, 0x06ce, 0x06cf,
+ 0x06d0, 0x06d1, 0x06d2, 0x06d3, 0x06d4, 0x06d5, 0x06d6, 0x06d7,
+ 0x06d8, 0x06d9, 0x06da, 0x06db, 0x06dc, 0x06dd, 0x06de, 0x06df,
+ 0x06e0, 0x06e1, 0x06e2, 0x06e3, 0x06e4, 0x06e5, 0x06e6, 0x06e7,
+ 0x06e8, 0x06e9, 0x06ea, 0x06eb, 0x06ec, 0x06ed, 0x06ee, 0x06ef,
+ 0x06f0, 0x06f1, 0x06f2, 0x06f3, 0x06f4, 0x06f5, 0x06f6, 0x06f7,
+ 0x06f8, 0x06f9, 0x06fa, 0x06fb, 0x06fc, 0x06fd, 0x06fe, 0x06ff,
+ 0x0700, 0x0701, 0x0702, 0x0703, 0x0704, 0x0705, 0x0706, 0x0707,
+ 0x0708, 0x0709, 0x070a, 0x070b, 0x070c, 0x070d, 0x0000, 0x070f,
+ 0x0710, 0x0711, 0x0712, 0x0713, 0x0714, 0x0715, 0x0716, 0x0717,
+ 0x0718, 0x0719, 0x071a, 0x071b, 0x071c, 0x071d, 0x071e, 0x071f,
+ 0x0720, 0x0721, 0x0722, 0x0723, 0x0724, 0x0725, 0x0726, 0x0727,
+ 0x0728, 0x0729, 0x072a, 0x072b, 0x072c, 0x072d, 0x072e, 0x072f,
+ 0x0730, 0x0731, 0x0732, 0x0733, 0x0734, 0x0735, 0x0736, 0x0737,
+ 0x0738, 0x0739, 0x073a, 0x073b, 0x073c, 0x073d, 0x073e, 0x073f,
+ 0x0740, 0x0741, 0x0742, 0x0743, 0x0744, 0x0745, 0x0746, 0x0747,
+ 0x0748, 0x0749, 0x074a, 0x0000, 0x0000, 0x074d, 0x074e, 0x074f,
+ 0x0750, 0x0751, 0x0752, 0x0753, 0x0754, 0x0755, 0x0756, 0x0757,
+ 0x0758, 0x0759, 0x075a, 0x075b, 0x075c, 0x075d, 0x075e, 0x075f,
+ 0x0760, 0x0761, 0x0762, 0x0763, 0x0764, 0x0765, 0x0766, 0x0767,
+ 0x0768, 0x0769, 0x076a, 0x076b, 0x076c, 0x076d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0786, 0x0787,
+ 0x0788, 0x0789, 0x078a, 0x078b, 0x078c, 0x078d, 0x078e, 0x078f,
+ 0x0790, 0x0791, 0x0792, 0x0793, 0x0794, 0x0795, 0x0796, 0x0797,
+ 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, 0x079e, 0x079f,
+ 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a6, 0x07a7,
+ 0x07a8, 0x07a9, 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07ae, 0x07af,
+ 0x07b0, 0x07b1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x07c0, 0x07c1, 0x07c2, 0x07c3, 0x07c4, 0x07c5, 0x07c6, 0x07c7,
+ 0x07c8, 0x07c9, 0x07ca, 0x07cb, 0x07cc, 0x07cd, 0x07ce, 0x07cf,
+ 0x07d0, 0x07d1, 0x07d2, 0x07d3, 0x07d4, 0x07d5, 0x07d6, 0x07d7,
+ 0x07d8, 0x07d9, 0x07da, 0x07db, 0x07dc, 0x07dd, 0x07de, 0x07df,
+ 0x07e0, 0x07e1, 0x07e2, 0x07e3, 0x07e4, 0x07e5, 0x07e6, 0x07e7,
+ 0x07e8, 0x07e9, 0x07ea, 0x07eb, 0x07ec, 0x07ed, 0x07ee, 0x07ef,
+ 0x07f0, 0x07f1, 0x07f2, 0x07f3, 0x07f4, 0x07f5, 0x07f6, 0x07f7,
+ 0x07f8, 0x07f9, 0x07fa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0901, 0x0902, 0x0903, 0x0904, 0x0905, 0x0906, 0x0907,
+ 0x0908, 0x0909, 0x090a, 0x090b, 0x090c, 0x090d, 0x090e, 0x090f,
+ 0x0910, 0x0911, 0x0912, 0x0913, 0x0914, 0x0915, 0x0916, 0x0917,
+ 0x0918, 0x0919, 0x091a, 0x091b, 0x091c, 0x091d, 0x091e, 0x091f,
+ 0x0920, 0x0921, 0x0922, 0x0923, 0x0924, 0x0925, 0x0926, 0x0927,
+ 0x0928, 0x0929, 0x092a, 0x092b, 0x092c, 0x092d, 0x092e, 0x092f,
+ 0x0930, 0x0931, 0x0932, 0x0933, 0x0934, 0x0935, 0x0936, 0x0937,
+ 0x0938, 0x0939, 0x0000, 0x0000, 0x093c, 0x093d, 0x093e, 0x093f,
+ 0x0940, 0x0941, 0x0942, 0x0943, 0x0944, 0x0945, 0x0946, 0x0947,
+ 0x0948, 0x0949, 0x094a, 0x094b, 0x094c, 0x094d, 0x0000, 0x0000,
+ 0x0950, 0x0951, 0x0952, 0x0953, 0x0954, 0x0000, 0x0000, 0x0000,
+ 0x0958, 0x0959, 0x095a, 0x095b, 0x095c, 0x095d, 0x095e, 0x095f,
+ 0x0960, 0x0961, 0x0962, 0x0963, 0x0964, 0x0965, 0x0966, 0x0967,
+ 0x0968, 0x0969, 0x096a, 0x096b, 0x096c, 0x096d, 0x096e, 0x096f,
+ 0x0970, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x097b, 0x097c, 0x097d, 0x097e, 0x097f,
+ 0x0000, 0x0981, 0x0982, 0x0983, 0x0000, 0x0985, 0x0986, 0x0987,
+ 0x0988, 0x0989, 0x098a, 0x098b, 0x098c, 0x0000, 0x0000, 0x098f,
+ 0x0990, 0x0000, 0x0000, 0x0993, 0x0994, 0x0995, 0x0996, 0x0997,
+ 0x0998, 0x0999, 0x099a, 0x099b, 0x099c, 0x099d, 0x099e, 0x099f,
+ 0x09a0, 0x09a1, 0x09a2, 0x09a3, 0x09a4, 0x09a5, 0x09a6, 0x09a7,
+ 0x09a8, 0x0000, 0x09aa, 0x09ab, 0x09ac, 0x09ad, 0x09ae, 0x09af,
+ 0x09b0, 0x0000, 0x09b2, 0x0000, 0x0000, 0x0000, 0x09b6, 0x09b7,
+ 0x09b8, 0x09b9, 0x0000, 0x0000, 0x09bc, 0x09bd, 0x09be, 0x09bf,
+ 0x09c0, 0x09c1, 0x09c2, 0x09c3, 0x09c4, 0x0000, 0x0000, 0x09c7,
+ 0x09c8, 0x0000, 0x0000, 0x09cb, 0x09cc, 0x09cd, 0x09ce, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x09d7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x09dc, 0x09dd, 0x0000, 0x09df,
+ 0x09e0, 0x09e1, 0x09e2, 0x09e3, 0x0000, 0x0000, 0x09e6, 0x09e7,
+ 0x09e8, 0x09e9, 0x09ea, 0x09eb, 0x09ec, 0x09ed, 0x09ee, 0x09ef,
+ 0x09f0, 0x09f1, 0x09f2, 0x09f3, 0x09f4, 0x09f5, 0x09f6, 0x09f7,
+ 0x09f8, 0x09f9, 0x09fa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0a01, 0x0a02, 0x0a03, 0x0000, 0x0a05, 0x0a06, 0x0a07,
+ 0x0a08, 0x0a09, 0x0a0a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0a0f,
+ 0x0a10, 0x0000, 0x0000, 0x0a13, 0x0a14, 0x0a15, 0x0a16, 0x0a17,
+ 0x0a18, 0x0a19, 0x0a1a, 0x0a1b, 0x0a1c, 0x0a1d, 0x0a1e, 0x0a1f,
+ 0x0a20, 0x0a21, 0x0a22, 0x0a23, 0x0a24, 0x0a25, 0x0a26, 0x0a27,
+ 0x0a28, 0x0000, 0x0a2a, 0x0a2b, 0x0a2c, 0x0a2d, 0x0a2e, 0x0a2f,
+ 0x0a30, 0x0000, 0x0a32, 0x0a33, 0x0000, 0x0a35, 0x0a36, 0x0000,
+ 0x0a38, 0x0a39, 0x0000, 0x0000, 0x0a3c, 0x0000, 0x0a3e, 0x0a3f,
+ 0x0a40, 0x0a41, 0x0a42, 0x0000, 0x0000, 0x0000, 0x0000, 0x0a47,
+ 0x0a48, 0x0000, 0x0000, 0x0a4b, 0x0a4c, 0x0a4d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0a59, 0x0a5a, 0x0a5b, 0x0a5c, 0x0000, 0x0a5e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0a66, 0x0a67,
+ 0x0a68, 0x0a69, 0x0a6a, 0x0a6b, 0x0a6c, 0x0a6d, 0x0a6e, 0x0a6f,
+ 0x0a70, 0x0a71, 0x0a72, 0x0a73, 0x0a74, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0a81, 0x0a82, 0x0a83, 0x0000, 0x0a85, 0x0a86, 0x0a87,
+ 0x0a88, 0x0a89, 0x0a8a, 0x0a8b, 0x0a8c, 0x0a8d, 0x0000, 0x0a8f,
+ 0x0a90, 0x0a91, 0x0000, 0x0a93, 0x0a94, 0x0a95, 0x0a96, 0x0a97,
+ 0x0a98, 0x0a99, 0x0a9a, 0x0a9b, 0x0a9c, 0x0a9d, 0x0a9e, 0x0a9f,
+ 0x0aa0, 0x0aa1, 0x0aa2, 0x0aa3, 0x0aa4, 0x0aa5, 0x0aa6, 0x0aa7,
+ 0x0aa8, 0x0000, 0x0aaa, 0x0aab, 0x0aac, 0x0aad, 0x0aae, 0x0aaf,
+ 0x0ab0, 0x0000, 0x0ab2, 0x0ab3, 0x0000, 0x0ab5, 0x0ab6, 0x0ab7,
+ 0x0ab8, 0x0ab9, 0x0000, 0x0000, 0x0abc, 0x0abd, 0x0abe, 0x0abf,
+ 0x0ac0, 0x0ac1, 0x0ac2, 0x0ac3, 0x0ac4, 0x0ac5, 0x0000, 0x0ac7,
+ 0x0ac8, 0x0ac9, 0x0000, 0x0acb, 0x0acc, 0x0acd, 0x0000, 0x0000,
+ 0x0ad0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0ae0, 0x0ae1, 0x0ae2, 0x0ae3, 0x0000, 0x0000, 0x0ae6, 0x0ae7,
+ 0x0ae8, 0x0ae9, 0x0aea, 0x0aeb, 0x0aec, 0x0aed, 0x0aee, 0x0aef,
+ 0x0000, 0x0af1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0b01, 0x0b02, 0x0b03, 0x0000, 0x0b05, 0x0b06, 0x0b07,
+ 0x0b08, 0x0b09, 0x0b0a, 0x0b0b, 0x0b0c, 0x0000, 0x0000, 0x0b0f,
+ 0x0b10, 0x0000, 0x0000, 0x0b13, 0x0b14, 0x0b15, 0x0b16, 0x0b17,
+ 0x0b18, 0x0b19, 0x0b1a, 0x0b1b, 0x0b1c, 0x0b1d, 0x0b1e, 0x0b1f,
+ 0x0b20, 0x0b21, 0x0b22, 0x0b23, 0x0b24, 0x0b25, 0x0b26, 0x0b27,
+ 0x0b28, 0x0000, 0x0b2a, 0x0b2b, 0x0b2c, 0x0b2d, 0x0b2e, 0x0b2f,
+ 0x0b30, 0x0000, 0x0b32, 0x0b33, 0x0000, 0x0b35, 0x0b36, 0x0b37,
+ 0x0b38, 0x0b39, 0x0000, 0x0000, 0x0b3c, 0x0b3d, 0x0b3e, 0x0b3f,
+ 0x0b40, 0x0b41, 0x0b42, 0x0b43, 0x0000, 0x0000, 0x0000, 0x0b47,
+ 0x0b48, 0x0000, 0x0000, 0x0b4b, 0x0b4c, 0x0b4d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b56, 0x0b57,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0b5c, 0x0b5d, 0x0000, 0x0b5f,
+ 0x0b60, 0x0b61, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b66, 0x0b67,
+ 0x0b68, 0x0b69, 0x0b6a, 0x0b6b, 0x0b6c, 0x0b6d, 0x0b6e, 0x0b6f,
+ 0x0b70, 0x0b71, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0b82, 0x0b83, 0x0000, 0x0b85, 0x0b86, 0x0b87,
+ 0x0b88, 0x0b89, 0x0b8a, 0x0000, 0x0000, 0x0000, 0x0b8e, 0x0b8f,
+ 0x0b90, 0x0000, 0x0b92, 0x0b93, 0x0b94, 0x0b95, 0x0000, 0x0000,
+ 0x0000, 0x0b99, 0x0b9a, 0x0000, 0x0b9c, 0x0000, 0x0b9e, 0x0b9f,
+ 0x0000, 0x0000, 0x0000, 0x0ba3, 0x0ba4, 0x0000, 0x0000, 0x0000,
+ 0x0ba8, 0x0ba9, 0x0baa, 0x0000, 0x0000, 0x0000, 0x0bae, 0x0baf,
+ 0x0bb0, 0x0bb1, 0x0bb2, 0x0bb3, 0x0bb4, 0x0bb5, 0x0bb6, 0x0bb7,
+ 0x0bb8, 0x0bb9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0bbe, 0x0bbf,
+ 0x0bc0, 0x0bc1, 0x0bc2, 0x0000, 0x0000, 0x0000, 0x0bc6, 0x0bc7,
+ 0x0bc8, 0x0000, 0x0bca, 0x0bcb, 0x0bcc, 0x0bcd, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0bd7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0be6, 0x0be7,
+ 0x0be8, 0x0be9, 0x0bea, 0x0beb, 0x0bec, 0x0bed, 0x0bee, 0x0bef,
+ 0x0bf0, 0x0bf1, 0x0bf2, 0x0bf3, 0x0bf4, 0x0bf5, 0x0bf6, 0x0bf7,
+ 0x0bf8, 0x0bf9, 0x0bfa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0c01, 0x0c02, 0x0c03, 0x0000, 0x0c05, 0x0c06, 0x0c07,
+ 0x0c08, 0x0c09, 0x0c0a, 0x0c0b, 0x0c0c, 0x0000, 0x0c0e, 0x0c0f,
+ 0x0c10, 0x0000, 0x0c12, 0x0c13, 0x0c14, 0x0c15, 0x0c16, 0x0c17,
+ 0x0c18, 0x0c19, 0x0c1a, 0x0c1b, 0x0c1c, 0x0c1d, 0x0c1e, 0x0c1f,
+ 0x0c20, 0x0c21, 0x0c22, 0x0c23, 0x0c24, 0x0c25, 0x0c26, 0x0c27,
+ 0x0c28, 0x0000, 0x0c2a, 0x0c2b, 0x0c2c, 0x0c2d, 0x0c2e, 0x0c2f,
+ 0x0c30, 0x0c31, 0x0c32, 0x0c33, 0x0000, 0x0c35, 0x0c36, 0x0c37,
+ 0x0c38, 0x0c39, 0x0000, 0x0000, 0x0000, 0x0000, 0x0c3e, 0x0c3f,
+ 0x0c40, 0x0c41, 0x0c42, 0x0c43, 0x0c44, 0x0000, 0x0c46, 0x0c47,
+ 0x0c48, 0x0000, 0x0c4a, 0x0c4b, 0x0c4c, 0x0c4d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0c55, 0x0c56, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0c60, 0x0c61, 0x0000, 0x0000, 0x0000, 0x0000, 0x0c66, 0x0c67,
+ 0x0c68, 0x0c69, 0x0c6a, 0x0c6b, 0x0c6c, 0x0c6d, 0x0c6e, 0x0c6f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0c82, 0x0c83, 0x0000, 0x0c85, 0x0c86, 0x0c87,
+ 0x0c88, 0x0c89, 0x0c8a, 0x0c8b, 0x0c8c, 0x0000, 0x0c8e, 0x0c8f,
+ 0x0c90, 0x0000, 0x0c92, 0x0c93, 0x0c94, 0x0c95, 0x0c96, 0x0c97,
+ 0x0c98, 0x0c99, 0x0c9a, 0x0c9b, 0x0c9c, 0x0c9d, 0x0c9e, 0x0c9f,
+ 0x0ca0, 0x0ca1, 0x0ca2, 0x0ca3, 0x0ca4, 0x0ca5, 0x0ca6, 0x0ca7,
+ 0x0ca8, 0x0000, 0x0caa, 0x0cab, 0x0cac, 0x0cad, 0x0cae, 0x0caf,
+ 0x0cb0, 0x0cb1, 0x0cb2, 0x0cb3, 0x0000, 0x0cb5, 0x0cb6, 0x0cb7,
+ 0x0cb8, 0x0cb9, 0x0000, 0x0000, 0x0cbc, 0x0cbd, 0x0cbe, 0x0cbf,
+ 0x0cc0, 0x0cc1, 0x0cc2, 0x0cc3, 0x0cc4, 0x0000, 0x0cc6, 0x0cc7,
+ 0x0cc8, 0x0000, 0x0cca, 0x0ccb, 0x0ccc, 0x0ccd, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0cd5, 0x0cd6, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0cde, 0x0000,
+ 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0000, 0x0000, 0x0ce6, 0x0ce7,
+ 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x0cef,
+ 0x0000, 0x0cf1, 0x0cf2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0d02, 0x0d03, 0x0000, 0x0d05, 0x0d06, 0x0d07,
+ 0x0d08, 0x0d09, 0x0d0a, 0x0d0b, 0x0d0c, 0x0000, 0x0d0e, 0x0d0f,
+ 0x0d10, 0x0000, 0x0d12, 0x0d13, 0x0d14, 0x0d15, 0x0d16, 0x0d17,
+ 0x0d18, 0x0d19, 0x0d1a, 0x0d1b, 0x0d1c, 0x0d1d, 0x0d1e, 0x0d1f,
+ 0x0d20, 0x0d21, 0x0d22, 0x0d23, 0x0d24, 0x0d25, 0x0d26, 0x0d27,
+ 0x0d28, 0x0000, 0x0d2a, 0x0d2b, 0x0d2c, 0x0d2d, 0x0d2e, 0x0d2f,
+ 0x0d30, 0x0d31, 0x0d32, 0x0d33, 0x0d34, 0x0d35, 0x0d36, 0x0d37,
+ 0x0d38, 0x0d39, 0x0000, 0x0000, 0x0000, 0x0000, 0x0d3e, 0x0d3f,
+ 0x0d40, 0x0d41, 0x0d42, 0x0d43, 0x0000, 0x0000, 0x0d46, 0x0d47,
+ 0x0d48, 0x0000, 0x0d4a, 0x0d4b, 0x0d4c, 0x0d4d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0d57,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0d60, 0x0d61, 0x0000, 0x0000, 0x0000, 0x0000, 0x0d66, 0x0d67,
+ 0x0d68, 0x0d69, 0x0d6a, 0x0d6b, 0x0d6c, 0x0d6d, 0x0d6e, 0x0d6f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0d82, 0x0d83, 0x0000, 0x0d85, 0x0d86, 0x0d87,
+ 0x0d88, 0x0d89, 0x0d8a, 0x0d8b, 0x0d8c, 0x0d8d, 0x0d8e, 0x0d8f,
+ 0x0d90, 0x0d91, 0x0d92, 0x0d93, 0x0d94, 0x0d95, 0x0d96, 0x0000,
+ 0x0000, 0x0000, 0x0d9a, 0x0d9b, 0x0d9c, 0x0d9d, 0x0d9e, 0x0d9f,
+ 0x0da0, 0x0da1, 0x0da2, 0x0da3, 0x0da4, 0x0da5, 0x0da6, 0x0da7,
+ 0x0da8, 0x0da9, 0x0daa, 0x0dab, 0x0dac, 0x0dad, 0x0dae, 0x0daf,
+ 0x0db0, 0x0db1, 0x0000, 0x0db3, 0x0db4, 0x0db5, 0x0db6, 0x0db7,
+ 0x0db8, 0x0db9, 0x0dba, 0x0dbb, 0x0000, 0x0dbd, 0x0000, 0x0000,
+ 0x0dc0, 0x0dc1, 0x0dc2, 0x0dc3, 0x0dc4, 0x0dc5, 0x0dc6, 0x0000,
+ 0x0000, 0x0000, 0x0dca, 0x0000, 0x0000, 0x0000, 0x0000, 0x0dcf,
+ 0x0dd0, 0x0dd1, 0x0dd2, 0x0dd3, 0x0dd4, 0x0000, 0x0dd6, 0x0000,
+ 0x0dd8, 0x0dd9, 0x0dda, 0x0ddb, 0x0ddc, 0x0ddd, 0x0dde, 0x0ddf,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0df2, 0x0df3, 0x0df4, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
+ 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
+ 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
+ 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
+ 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
+ 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
+ 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
+ 0x0e38, 0x0e39, 0x0e3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0e3f,
+ 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
+ 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
+ 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
+ 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0e81, 0x0e82, 0x0000, 0x0e84, 0x0000, 0x0000, 0x0e87,
+ 0x0e88, 0x0000, 0x0e8a, 0x0000, 0x0000, 0x0e8d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0e94, 0x0e95, 0x0e96, 0x0e97,
+ 0x0000, 0x0e99, 0x0e9a, 0x0e9b, 0x0e9c, 0x0e9d, 0x0e9e, 0x0e9f,
+ 0x0000, 0x0ea1, 0x0ea2, 0x0ea3, 0x0000, 0x0ea5, 0x0000, 0x0ea7,
+ 0x0000, 0x0000, 0x0eaa, 0x0eab, 0x0000, 0x0ead, 0x0eae, 0x0eaf,
+ 0x0eb0, 0x0eb1, 0x0eb2, 0x0eb3, 0x0eb4, 0x0eb5, 0x0eb6, 0x0eb7,
+ 0x0eb8, 0x0eb9, 0x0000, 0x0ebb, 0x0ebc, 0x0ebd, 0x0000, 0x0000,
+ 0x0ec0, 0x0ec1, 0x0ec2, 0x0ec3, 0x0ec4, 0x0000, 0x0ec6, 0x0000,
+ 0x0ec8, 0x0ec9, 0x0eca, 0x0ecb, 0x0ecc, 0x0ecd, 0x0000, 0x0000,
+ 0x0ed0, 0x0ed1, 0x0ed2, 0x0ed3, 0x0ed4, 0x0ed5, 0x0ed6, 0x0ed7,
+ 0x0ed8, 0x0ed9, 0x0000, 0x0000, 0x0edc, 0x0edd, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0f00, 0x0f01, 0x0f02, 0x0f03, 0x0f04, 0x0f05, 0x0f06, 0x0f07,
+ 0x0f08, 0x0f09, 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0d, 0x0f0e, 0x0f0f,
+ 0x0f10, 0x0f11, 0x0f12, 0x0f13, 0x0f14, 0x0f15, 0x0f16, 0x0f17,
+ 0x0f18, 0x0f19, 0x0f1a, 0x0f1b, 0x0f1c, 0x0f1d, 0x0f1e, 0x0f1f,
+ 0x0f20, 0x0f21, 0x0f22, 0x0f23, 0x0f24, 0x0f25, 0x0f26, 0x0f27,
+ 0x0f28, 0x0f29, 0x0f2a, 0x0f2b, 0x0f2c, 0x0f2d, 0x0f2e, 0x0f2f,
+ 0x0f30, 0x0f31, 0x0f32, 0x0f33, 0x0f34, 0x0f35, 0x0f36, 0x0f37,
+ 0x0f38, 0x0f39, 0x0f3a, 0x0f3b, 0x0f3c, 0x0f3d, 0x0f3e, 0x0f3f,
+ 0x0f40, 0x0f41, 0x0f42, 0x0f43, 0x0f44, 0x0f45, 0x0f46, 0x0f47,
+ 0x0000, 0x0f49, 0x0f4a, 0x0f4b, 0x0f4c, 0x0f4d, 0x0f4e, 0x0f4f,
+ 0x0f50, 0x0f51, 0x0f52, 0x0f53, 0x0f54, 0x0f55, 0x0f56, 0x0f57,
+ 0x0f58, 0x0f59, 0x0f5a, 0x0f5b, 0x0f5c, 0x0f5d, 0x0f5e, 0x0f5f,
+ 0x0f60, 0x0f61, 0x0f62, 0x0f63, 0x0f64, 0x0f65, 0x0f66, 0x0f67,
+ 0x0f68, 0x0f69, 0x0f6a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0f71, 0x0f72, 0x0f73, 0x0f74, 0x0f75, 0x0f76, 0x0f77,
+ 0x0f78, 0x0f79, 0x0f7a, 0x0f7b, 0x0f7c, 0x0f7d, 0x0f7e, 0x0f7f,
+ 0x0f80, 0x0f81, 0x0f82, 0x0f83, 0x0f84, 0x0f85, 0x0f86, 0x0f87,
+ 0x0f88, 0x0f89, 0x0f8a, 0x0f8b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0f90, 0x0f91, 0x0f92, 0x0f93, 0x0f94, 0x0f95, 0x0f96, 0x0f97,
+ 0x0000, 0x0f99, 0x0f9a, 0x0f9b, 0x0f9c, 0x0f9d, 0x0f9e, 0x0f9f,
+ 0x0fa0, 0x0fa1, 0x0fa2, 0x0fa3, 0x0fa4, 0x0fa5, 0x0fa6, 0x0fa7,
+ 0x0fa8, 0x0fa9, 0x0faa, 0x0fab, 0x0fac, 0x0fad, 0x0fae, 0x0faf,
+ 0x0fb0, 0x0fb1, 0x0fb2, 0x0fb3, 0x0fb4, 0x0fb5, 0x0fb6, 0x0fb7,
+ 0x0fb8, 0x0fb9, 0x0fba, 0x0fbb, 0x0fbc, 0x0000, 0x0fbe, 0x0fbf,
+ 0x0fc0, 0x0fc1, 0x0fc2, 0x0fc3, 0x0fc4, 0x0fc5, 0x0fc6, 0x0fc7,
+ 0x0fc8, 0x0fc9, 0x0fca, 0x0fcb, 0x0fcc, 0x0000, 0x0000, 0x0fcf,
+ 0x0fd0, 0x0fd1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
+ 0x1008, 0x1009, 0x100a, 0x100b, 0x100c, 0x100d, 0x100e, 0x100f,
+ 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017,
+ 0x1018, 0x1019, 0x101a, 0x101b, 0x101c, 0x101d, 0x101e, 0x101f,
+ 0x1020, 0x1021, 0x0000, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
+ 0x0000, 0x1029, 0x102a, 0x0000, 0x102c, 0x102d, 0x102e, 0x102f,
+ 0x1030, 0x1031, 0x1032, 0x0000, 0x0000, 0x0000, 0x1036, 0x1037,
+ 0x1038, 0x1039, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047,
+ 0x1048, 0x1049, 0x104a, 0x104b, 0x104c, 0x104d, 0x104e, 0x104f,
+ 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057,
+ 0x1058, 0x1059, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2d00, 0x2d01, 0x2d02, 0x2d03, 0x2d04, 0x2d05, 0x2d06, 0x2d07,
+ 0x2d08, 0x2d09, 0x2d0a, 0x2d0b, 0x2d0c, 0x2d0d, 0x2d0e, 0x2d0f,
+ 0x2d10, 0x2d11, 0x2d12, 0x2d13, 0x2d14, 0x2d15, 0x2d16, 0x2d17,
+ 0x2d18, 0x2d19, 0x2d1a, 0x2d1b, 0x2d1c, 0x2d1d, 0x2d1e, 0x2d1f,
+ 0x2d20, 0x2d21, 0x2d22, 0x2d23, 0x2d24, 0x2d25, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10d7,
+ 0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc, 0x10dd, 0x10de, 0x10df,
+ 0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10e4, 0x10e5, 0x10e6, 0x10e7,
+ 0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x10ee, 0x10ef,
+ 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7,
+ 0x10f8, 0x10f9, 0x10fa, 0x10fb, 0x10fc, 0x0000, 0x0000, 0x0000,
+ 0x1100, 0x1101, 0x1102, 0x1103, 0x1104, 0x1105, 0x1106, 0x1107,
+ 0x1108, 0x1109, 0x110a, 0x110b, 0x110c, 0x110d, 0x110e, 0x110f,
+ 0x1110, 0x1111, 0x1112, 0x1113, 0x1114, 0x1115, 0x1116, 0x1117,
+ 0x1118, 0x1119, 0x111a, 0x111b, 0x111c, 0x111d, 0x111e, 0x111f,
+ 0x1120, 0x1121, 0x1122, 0x1123, 0x1124, 0x1125, 0x1126, 0x1127,
+ 0x1128, 0x1129, 0x112a, 0x112b, 0x112c, 0x112d, 0x112e, 0x112f,
+ 0x1130, 0x1131, 0x1132, 0x1133, 0x1134, 0x1135, 0x1136, 0x1137,
+ 0x1138, 0x1139, 0x113a, 0x113b, 0x113c, 0x113d, 0x113e, 0x113f,
+ 0x1140, 0x1141, 0x1142, 0x1143, 0x1144, 0x1145, 0x1146, 0x1147,
+ 0x1148, 0x1149, 0x114a, 0x114b, 0x114c, 0x114d, 0x114e, 0x114f,
+ 0x1150, 0x1151, 0x1152, 0x1153, 0x1154, 0x1155, 0x1156, 0x1157,
+ 0x1158, 0x1159, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x115f,
+ 0x1160, 0x1161, 0x1162, 0x1163, 0x1164, 0x1165, 0x1166, 0x1167,
+ 0x1168, 0x1169, 0x116a, 0x116b, 0x116c, 0x116d, 0x116e, 0x116f,
+ 0x1170, 0x1171, 0x1172, 0x1173, 0x1174, 0x1175, 0x1176, 0x1177,
+ 0x1178, 0x1179, 0x117a, 0x117b, 0x117c, 0x117d, 0x117e, 0x117f,
+ 0x1180, 0x1181, 0x1182, 0x1183, 0x1184, 0x1185, 0x1186, 0x1187,
+ 0x1188, 0x1189, 0x118a, 0x118b, 0x118c, 0x118d, 0x118e, 0x118f,
+ 0x1190, 0x1191, 0x1192, 0x1193, 0x1194, 0x1195, 0x1196, 0x1197,
+ 0x1198, 0x1199, 0x119a, 0x119b, 0x119c, 0x119d, 0x119e, 0x119f,
+ 0x11a0, 0x11a1, 0x11a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x11a8, 0x11a9, 0x11aa, 0x11ab, 0x11ac, 0x11ad, 0x11ae, 0x11af,
+ 0x11b0, 0x11b1, 0x11b2, 0x11b3, 0x11b4, 0x11b5, 0x11b6, 0x11b7,
+ 0x11b8, 0x11b9, 0x11ba, 0x11bb, 0x11bc, 0x11bd, 0x11be, 0x11bf,
+ 0x11c0, 0x11c1, 0x11c2, 0x11c3, 0x11c4, 0x11c5, 0x11c6, 0x11c7,
+ 0x11c8, 0x11c9, 0x11ca, 0x11cb, 0x11cc, 0x11cd, 0x11ce, 0x11cf,
+ 0x11d0, 0x11d1, 0x11d2, 0x11d3, 0x11d4, 0x11d5, 0x11d6, 0x11d7,
+ 0x11d8, 0x11d9, 0x11da, 0x11db, 0x11dc, 0x11dd, 0x11de, 0x11df,
+ 0x11e0, 0x11e1, 0x11e2, 0x11e3, 0x11e4, 0x11e5, 0x11e6, 0x11e7,
+ 0x11e8, 0x11e9, 0x11ea, 0x11eb, 0x11ec, 0x11ed, 0x11ee, 0x11ef,
+ 0x11f0, 0x11f1, 0x11f2, 0x11f3, 0x11f4, 0x11f5, 0x11f6, 0x11f7,
+ 0x11f8, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1200, 0x1201, 0x1202, 0x1203, 0x1204, 0x1205, 0x1206, 0x1207,
+ 0x1208, 0x1209, 0x120a, 0x120b, 0x120c, 0x120d, 0x120e, 0x120f,
+ 0x1210, 0x1211, 0x1212, 0x1213, 0x1214, 0x1215, 0x1216, 0x1217,
+ 0x1218, 0x1219, 0x121a, 0x121b, 0x121c, 0x121d, 0x121e, 0x121f,
+ 0x1220, 0x1221, 0x1222, 0x1223, 0x1224, 0x1225, 0x1226, 0x1227,
+ 0x1228, 0x1229, 0x122a, 0x122b, 0x122c, 0x122d, 0x122e, 0x122f,
+ 0x1230, 0x1231, 0x1232, 0x1233, 0x1234, 0x1235, 0x1236, 0x1237,
+ 0x1238, 0x1239, 0x123a, 0x123b, 0x123c, 0x123d, 0x123e, 0x123f,
+ 0x1240, 0x1241, 0x1242, 0x1243, 0x1244, 0x1245, 0x1246, 0x1247,
+ 0x1248, 0x0000, 0x124a, 0x124b, 0x124c, 0x124d, 0x0000, 0x0000,
+ 0x1250, 0x1251, 0x1252, 0x1253, 0x1254, 0x1255, 0x1256, 0x0000,
+ 0x1258, 0x0000, 0x125a, 0x125b, 0x125c, 0x125d, 0x0000, 0x0000,
+ 0x1260, 0x1261, 0x1262, 0x1263, 0x1264, 0x1265, 0x1266, 0x1267,
+ 0x1268, 0x1269, 0x126a, 0x126b, 0x126c, 0x126d, 0x126e, 0x126f,
+ 0x1270, 0x1271, 0x1272, 0x1273, 0x1274, 0x1275, 0x1276, 0x1277,
+ 0x1278, 0x1279, 0x127a, 0x127b, 0x127c, 0x127d, 0x127e, 0x127f,
+ 0x1280, 0x1281, 0x1282, 0x1283, 0x1284, 0x1285, 0x1286, 0x1287,
+ 0x1288, 0x0000, 0x128a, 0x128b, 0x128c, 0x128d, 0x0000, 0x0000,
+ 0x1290, 0x1291, 0x1292, 0x1293, 0x1294, 0x1295, 0x1296, 0x1297,
+ 0x1298, 0x1299, 0x129a, 0x129b, 0x129c, 0x129d, 0x129e, 0x129f,
+ 0x12a0, 0x12a1, 0x12a2, 0x12a3, 0x12a4, 0x12a5, 0x12a6, 0x12a7,
+ 0x12a8, 0x12a9, 0x12aa, 0x12ab, 0x12ac, 0x12ad, 0x12ae, 0x12af,
+ 0x12b0, 0x0000, 0x12b2, 0x12b3, 0x12b4, 0x12b5, 0x0000, 0x0000,
+ 0x12b8, 0x12b9, 0x12ba, 0x12bb, 0x12bc, 0x12bd, 0x12be, 0x0000,
+ 0x12c0, 0x0000, 0x12c2, 0x12c3, 0x12c4, 0x12c5, 0x0000, 0x0000,
+ 0x12c8, 0x12c9, 0x12ca, 0x12cb, 0x12cc, 0x12cd, 0x12ce, 0x12cf,
+ 0x12d0, 0x12d1, 0x12d2, 0x12d3, 0x12d4, 0x12d5, 0x12d6, 0x0000,
+ 0x12d8, 0x12d9, 0x12da, 0x12db, 0x12dc, 0x12dd, 0x12de, 0x12df,
+ 0x12e0, 0x12e1, 0x12e2, 0x12e3, 0x12e4, 0x12e5, 0x12e6, 0x12e7,
+ 0x12e8, 0x12e9, 0x12ea, 0x12eb, 0x12ec, 0x12ed, 0x12ee, 0x12ef,
+ 0x12f0, 0x12f1, 0x12f2, 0x12f3, 0x12f4, 0x12f5, 0x12f6, 0x12f7,
+ 0x12f8, 0x12f9, 0x12fa, 0x12fb, 0x12fc, 0x12fd, 0x12fe, 0x12ff,
+ 0x1300, 0x1301, 0x1302, 0x1303, 0x1304, 0x1305, 0x1306, 0x1307,
+ 0x1308, 0x1309, 0x130a, 0x130b, 0x130c, 0x130d, 0x130e, 0x130f,
+ 0x1310, 0x0000, 0x1312, 0x1313, 0x1314, 0x1315, 0x0000, 0x0000,
+ 0x1318, 0x1319, 0x131a, 0x131b, 0x131c, 0x131d, 0x131e, 0x131f,
+ 0x1320, 0x1321, 0x1322, 0x1323, 0x1324, 0x1325, 0x1326, 0x1327,
+ 0x1328, 0x1329, 0x132a, 0x132b, 0x132c, 0x132d, 0x132e, 0x132f,
+ 0x1330, 0x1331, 0x1332, 0x1333, 0x1334, 0x1335, 0x1336, 0x1337,
+ 0x1338, 0x1339, 0x133a, 0x133b, 0x133c, 0x133d, 0x133e, 0x133f,
+ 0x1340, 0x1341, 0x1342, 0x1343, 0x1344, 0x1345, 0x1346, 0x1347,
+ 0x1348, 0x1349, 0x134a, 0x134b, 0x134c, 0x134d, 0x134e, 0x134f,
+ 0x1350, 0x1351, 0x1352, 0x1353, 0x1354, 0x1355, 0x1356, 0x1357,
+ 0x1358, 0x1359, 0x135a, 0x0000, 0x0000, 0x0000, 0x0000, 0x135f,
+ 0x1360, 0x1361, 0x1362, 0x1363, 0x1364, 0x1365, 0x1366, 0x1367,
+ 0x1368, 0x1369, 0x136a, 0x136b, 0x136c, 0x136d, 0x136e, 0x136f,
+ 0x1370, 0x1371, 0x1372, 0x1373, 0x1374, 0x1375, 0x1376, 0x1377,
+ 0x1378, 0x1379, 0x137a, 0x137b, 0x137c, 0x0000, 0x0000, 0x0000,
+ 0x1380, 0x1381, 0x1382, 0x1383, 0x1384, 0x1385, 0x1386, 0x1387,
+ 0x1388, 0x1389, 0x138a, 0x138b, 0x138c, 0x138d, 0x138e, 0x138f,
+ 0x1390, 0x1391, 0x1392, 0x1393, 0x1394, 0x1395, 0x1396, 0x1397,
+ 0x1398, 0x1399, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x13a0, 0x13a1, 0x13a2, 0x13a3, 0x13a4, 0x13a5, 0x13a6, 0x13a7,
+ 0x13a8, 0x13a9, 0x13aa, 0x13ab, 0x13ac, 0x13ad, 0x13ae, 0x13af,
+ 0x13b0, 0x13b1, 0x13b2, 0x13b3, 0x13b4, 0x13b5, 0x13b6, 0x13b7,
+ 0x13b8, 0x13b9, 0x13ba, 0x13bb, 0x13bc, 0x13bd, 0x13be, 0x13bf,
+ 0x13c0, 0x13c1, 0x13c2, 0x13c3, 0x13c4, 0x13c5, 0x13c6, 0x13c7,
+ 0x13c8, 0x13c9, 0x13ca, 0x13cb, 0x13cc, 0x13cd, 0x13ce, 0x13cf,
+ 0x13d0, 0x13d1, 0x13d2, 0x13d3, 0x13d4, 0x13d5, 0x13d6, 0x13d7,
+ 0x13d8, 0x13d9, 0x13da, 0x13db, 0x13dc, 0x13dd, 0x13de, 0x13df,
+ 0x13e0, 0x13e1, 0x13e2, 0x13e3, 0x13e4, 0x13e5, 0x13e6, 0x13e7,
+ 0x13e8, 0x13e9, 0x13ea, 0x13eb, 0x13ec, 0x13ed, 0x13ee, 0x13ef,
+ 0x13f0, 0x13f1, 0x13f2, 0x13f3, 0x13f4, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x1401, 0x1402, 0x1403, 0x1404, 0x1405, 0x1406, 0x1407,
+ 0x1408, 0x1409, 0x140a, 0x140b, 0x140c, 0x140d, 0x140e, 0x140f,
+ 0x1410, 0x1411, 0x1412, 0x1413, 0x1414, 0x1415, 0x1416, 0x1417,
+ 0x1418, 0x1419, 0x141a, 0x141b, 0x141c, 0x141d, 0x141e, 0x141f,
+ 0x1420, 0x1421, 0x1422, 0x1423, 0x1424, 0x1425, 0x1426, 0x1427,
+ 0x1428, 0x1429, 0x142a, 0x142b, 0x142c, 0x142d, 0x142e, 0x142f,
+ 0x1430, 0x1431, 0x1432, 0x1433, 0x1434, 0x1435, 0x1436, 0x1437,
+ 0x1438, 0x1439, 0x143a, 0x143b, 0x143c, 0x143d, 0x143e, 0x143f,
+ 0x1440, 0x1441, 0x1442, 0x1443, 0x1444, 0x1445, 0x1446, 0x1447,
+ 0x1448, 0x1449, 0x144a, 0x144b, 0x144c, 0x144d, 0x144e, 0x144f,
+ 0x1450, 0x1451, 0x1452, 0x1453, 0x1454, 0x1455, 0x1456, 0x1457,
+ 0x1458, 0x1459, 0x145a, 0x145b, 0x145c, 0x145d, 0x145e, 0x145f,
+ 0x1460, 0x1461, 0x1462, 0x1463, 0x1464, 0x1465, 0x1466, 0x1467,
+ 0x1468, 0x1469, 0x146a, 0x146b, 0x146c, 0x146d, 0x146e, 0x146f,
+ 0x1470, 0x1471, 0x1472, 0x1473, 0x1474, 0x1475, 0x1476, 0x1477,
+ 0x1478, 0x1479, 0x147a, 0x147b, 0x147c, 0x147d, 0x147e, 0x147f,
+ 0x1480, 0x1481, 0x1482, 0x1483, 0x1484, 0x1485, 0x1486, 0x1487,
+ 0x1488, 0x1489, 0x148a, 0x148b, 0x148c, 0x148d, 0x148e, 0x148f,
+ 0x1490, 0x1491, 0x1492, 0x1493, 0x1494, 0x1495, 0x1496, 0x1497,
+ 0x1498, 0x1499, 0x149a, 0x149b, 0x149c, 0x149d, 0x149e, 0x149f,
+ 0x14a0, 0x14a1, 0x14a2, 0x14a3, 0x14a4, 0x14a5, 0x14a6, 0x14a7,
+ 0x14a8, 0x14a9, 0x14aa, 0x14ab, 0x14ac, 0x14ad, 0x14ae, 0x14af,
+ 0x14b0, 0x14b1, 0x14b2, 0x14b3, 0x14b4, 0x14b5, 0x14b6, 0x14b7,
+ 0x14b8, 0x14b9, 0x14ba, 0x14bb, 0x14bc, 0x14bd, 0x14be, 0x14bf,
+ 0x14c0, 0x14c1, 0x14c2, 0x14c3, 0x14c4, 0x14c5, 0x14c6, 0x14c7,
+ 0x14c8, 0x14c9, 0x14ca, 0x14cb, 0x14cc, 0x14cd, 0x14ce, 0x14cf,
+ 0x14d0, 0x14d1, 0x14d2, 0x14d3, 0x14d4, 0x14d5, 0x14d6, 0x14d7,
+ 0x14d8, 0x14d9, 0x14da, 0x14db, 0x14dc, 0x14dd, 0x14de, 0x14df,
+ 0x14e0, 0x14e1, 0x14e2, 0x14e3, 0x14e4, 0x14e5, 0x14e6, 0x14e7,
+ 0x14e8, 0x14e9, 0x14ea, 0x14eb, 0x14ec, 0x14ed, 0x14ee, 0x14ef,
+ 0x14f0, 0x14f1, 0x14f2, 0x14f3, 0x14f4, 0x14f5, 0x14f6, 0x14f7,
+ 0x14f8, 0x14f9, 0x14fa, 0x14fb, 0x14fc, 0x14fd, 0x14fe, 0x14ff,
+ 0x1500, 0x1501, 0x1502, 0x1503, 0x1504, 0x1505, 0x1506, 0x1507,
+ 0x1508, 0x1509, 0x150a, 0x150b, 0x150c, 0x150d, 0x150e, 0x150f,
+ 0x1510, 0x1511, 0x1512, 0x1513, 0x1514, 0x1515, 0x1516, 0x1517,
+ 0x1518, 0x1519, 0x151a, 0x151b, 0x151c, 0x151d, 0x151e, 0x151f,
+ 0x1520, 0x1521, 0x1522, 0x1523, 0x1524, 0x1525, 0x1526, 0x1527,
+ 0x1528, 0x1529, 0x152a, 0x152b, 0x152c, 0x152d, 0x152e, 0x152f,
+ 0x1530, 0x1531, 0x1532, 0x1533, 0x1534, 0x1535, 0x1536, 0x1537,
+ 0x1538, 0x1539, 0x153a, 0x153b, 0x153c, 0x153d, 0x153e, 0x153f,
+ 0x1540, 0x1541, 0x1542, 0x1543, 0x1544, 0x1545, 0x1546, 0x1547,
+ 0x1548, 0x1549, 0x154a, 0x154b, 0x154c, 0x154d, 0x154e, 0x154f,
+ 0x1550, 0x1551, 0x1552, 0x1553, 0x1554, 0x1555, 0x1556, 0x1557,
+ 0x1558, 0x1559, 0x155a, 0x155b, 0x155c, 0x155d, 0x155e, 0x155f,
+ 0x1560, 0x1561, 0x1562, 0x1563, 0x1564, 0x1565, 0x1566, 0x1567,
+ 0x1568, 0x1569, 0x156a, 0x156b, 0x156c, 0x156d, 0x156e, 0x156f,
+ 0x1570, 0x1571, 0x1572, 0x1573, 0x1574, 0x1575, 0x1576, 0x1577,
+ 0x1578, 0x1579, 0x157a, 0x157b, 0x157c, 0x157d, 0x157e, 0x157f,
+ 0x1580, 0x1581, 0x1582, 0x1583, 0x1584, 0x1585, 0x1586, 0x1587,
+ 0x1588, 0x1589, 0x158a, 0x158b, 0x158c, 0x158d, 0x158e, 0x158f,
+ 0x1590, 0x1591, 0x1592, 0x1593, 0x1594, 0x1595, 0x1596, 0x1597,
+ 0x1598, 0x1599, 0x159a, 0x159b, 0x159c, 0x159d, 0x159e, 0x159f,
+ 0x15a0, 0x15a1, 0x15a2, 0x15a3, 0x15a4, 0x15a5, 0x15a6, 0x15a7,
+ 0x15a8, 0x15a9, 0x15aa, 0x15ab, 0x15ac, 0x15ad, 0x15ae, 0x15af,
+ 0x15b0, 0x15b1, 0x15b2, 0x15b3, 0x15b4, 0x15b5, 0x15b6, 0x15b7,
+ 0x15b8, 0x15b9, 0x15ba, 0x15bb, 0x15bc, 0x15bd, 0x15be, 0x15bf,
+ 0x15c0, 0x15c1, 0x15c2, 0x15c3, 0x15c4, 0x15c5, 0x15c6, 0x15c7,
+ 0x15c8, 0x15c9, 0x15ca, 0x15cb, 0x15cc, 0x15cd, 0x15ce, 0x15cf,
+ 0x15d0, 0x15d1, 0x15d2, 0x15d3, 0x15d4, 0x15d5, 0x15d6, 0x15d7,
+ 0x15d8, 0x15d9, 0x15da, 0x15db, 0x15dc, 0x15dd, 0x15de, 0x15df,
+ 0x15e0, 0x15e1, 0x15e2, 0x15e3, 0x15e4, 0x15e5, 0x15e6, 0x15e7,
+ 0x15e8, 0x15e9, 0x15ea, 0x15eb, 0x15ec, 0x15ed, 0x15ee, 0x15ef,
+ 0x15f0, 0x15f1, 0x15f2, 0x15f3, 0x15f4, 0x15f5, 0x15f6, 0x15f7,
+ 0x15f8, 0x15f9, 0x15fa, 0x15fb, 0x15fc, 0x15fd, 0x15fe, 0x15ff,
+ 0x1600, 0x1601, 0x1602, 0x1603, 0x1604, 0x1605, 0x1606, 0x1607,
+ 0x1608, 0x1609, 0x160a, 0x160b, 0x160c, 0x160d, 0x160e, 0x160f,
+ 0x1610, 0x1611, 0x1612, 0x1613, 0x1614, 0x1615, 0x1616, 0x1617,
+ 0x1618, 0x1619, 0x161a, 0x161b, 0x161c, 0x161d, 0x161e, 0x161f,
+ 0x1620, 0x1621, 0x1622, 0x1623, 0x1624, 0x1625, 0x1626, 0x1627,
+ 0x1628, 0x1629, 0x162a, 0x162b, 0x162c, 0x162d, 0x162e, 0x162f,
+ 0x1630, 0x1631, 0x1632, 0x1633, 0x1634, 0x1635, 0x1636, 0x1637,
+ 0x1638, 0x1639, 0x163a, 0x163b, 0x163c, 0x163d, 0x163e, 0x163f,
+ 0x1640, 0x1641, 0x1642, 0x1643, 0x1644, 0x1645, 0x1646, 0x1647,
+ 0x1648, 0x1649, 0x164a, 0x164b, 0x164c, 0x164d, 0x164e, 0x164f,
+ 0x1650, 0x1651, 0x1652, 0x1653, 0x1654, 0x1655, 0x1656, 0x1657,
+ 0x1658, 0x1659, 0x165a, 0x165b, 0x165c, 0x165d, 0x165e, 0x165f,
+ 0x1660, 0x1661, 0x1662, 0x1663, 0x1664, 0x1665, 0x1666, 0x1667,
+ 0x1668, 0x1669, 0x166a, 0x166b, 0x166c, 0x166d, 0x166e, 0x166f,
+ 0x1670, 0x1671, 0x1672, 0x1673, 0x1674, 0x1675, 0x1676, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1680, 0x1681, 0x1682, 0x1683, 0x1684, 0x1685, 0x1686, 0x1687,
+ 0x1688, 0x1689, 0x168a, 0x168b, 0x168c, 0x168d, 0x168e, 0x168f,
+ 0x1690, 0x1691, 0x1692, 0x1693, 0x1694, 0x1695, 0x1696, 0x1697,
+ 0x1698, 0x1699, 0x169a, 0x169b, 0x169c, 0x0000, 0x0000, 0x0000,
+ 0x16a0, 0x16a1, 0x16a2, 0x16a3, 0x16a4, 0x16a5, 0x16a6, 0x16a7,
+ 0x16a8, 0x16a9, 0x16aa, 0x16ab, 0x16ac, 0x16ad, 0x16ae, 0x16af,
+ 0x16b0, 0x16b1, 0x16b2, 0x16b3, 0x16b4, 0x16b5, 0x16b6, 0x16b7,
+ 0x16b8, 0x16b9, 0x16ba, 0x16bb, 0x16bc, 0x16bd, 0x16be, 0x16bf,
+ 0x16c0, 0x16c1, 0x16c2, 0x16c3, 0x16c4, 0x16c5, 0x16c6, 0x16c7,
+ 0x16c8, 0x16c9, 0x16ca, 0x16cb, 0x16cc, 0x16cd, 0x16ce, 0x16cf,
+ 0x16d0, 0x16d1, 0x16d2, 0x16d3, 0x16d4, 0x16d5, 0x16d6, 0x16d7,
+ 0x16d8, 0x16d9, 0x16da, 0x16db, 0x16dc, 0x16dd, 0x16de, 0x16df,
+ 0x16e0, 0x16e1, 0x16e2, 0x16e3, 0x16e4, 0x16e5, 0x16e6, 0x16e7,
+ 0x16e8, 0x16e9, 0x16ea, 0x16eb, 0x16ec, 0x16ed, 0x16ee, 0x16ef,
+ 0x16f0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1700, 0x1701, 0x1702, 0x1703, 0x1704, 0x1705, 0x1706, 0x1707,
+ 0x1708, 0x1709, 0x170a, 0x170b, 0x170c, 0x0000, 0x170e, 0x170f,
+ 0x1710, 0x1711, 0x1712, 0x1713, 0x1714, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1720, 0x1721, 0x1722, 0x1723, 0x1724, 0x1725, 0x1726, 0x1727,
+ 0x1728, 0x1729, 0x172a, 0x172b, 0x172c, 0x172d, 0x172e, 0x172f,
+ 0x1730, 0x1731, 0x1732, 0x1733, 0x1734, 0x1735, 0x1736, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1740, 0x1741, 0x1742, 0x1743, 0x1744, 0x1745, 0x1746, 0x1747,
+ 0x1748, 0x1749, 0x174a, 0x174b, 0x174c, 0x174d, 0x174e, 0x174f,
+ 0x1750, 0x1751, 0x1752, 0x1753, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1760, 0x1761, 0x1762, 0x1763, 0x1764, 0x1765, 0x1766, 0x1767,
+ 0x1768, 0x1769, 0x176a, 0x176b, 0x176c, 0x0000, 0x176e, 0x176f,
+ 0x1770, 0x0000, 0x1772, 0x1773, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1780, 0x1781, 0x1782, 0x1783, 0x1784, 0x1785, 0x1786, 0x1787,
+ 0x1788, 0x1789, 0x178a, 0x178b, 0x178c, 0x178d, 0x178e, 0x178f,
+ 0x1790, 0x1791, 0x1792, 0x1793, 0x1794, 0x1795, 0x1796, 0x1797,
+ 0x1798, 0x1799, 0x179a, 0x179b, 0x179c, 0x179d, 0x179e, 0x179f,
+ 0x17a0, 0x17a1, 0x17a2, 0x17a3, 0x17a4, 0x17a5, 0x17a6, 0x17a7,
+ 0x17a8, 0x17a9, 0x17aa, 0x17ab, 0x17ac, 0x17ad, 0x17ae, 0x17af,
+ 0x17b0, 0x17b1, 0x17b2, 0x17b3, 0x17b4, 0x17b5, 0x17b6, 0x17b7,
+ 0x17b8, 0x17b9, 0x17ba, 0x17bb, 0x17bc, 0x17bd, 0x17be, 0x17bf,
+ 0x17c0, 0x17c1, 0x17c2, 0x17c3, 0x17c4, 0x17c5, 0x17c6, 0x17c7,
+ 0x17c8, 0x17c9, 0x17ca, 0x17cb, 0x17cc, 0x17cd, 0x17ce, 0x17cf,
+ 0x17d0, 0x17d1, 0x17d2, 0x17d3, 0x17d4, 0x17d5, 0x17d6, 0x17d7,
+ 0x17d8, 0x17d9, 0x17da, 0x17db, 0x17dc, 0x17dd, 0x0000, 0x0000,
+ 0x17e0, 0x17e1, 0x17e2, 0x17e3, 0x17e4, 0x17e5, 0x17e6, 0x17e7,
+ 0x17e8, 0x17e9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x17f0, 0x17f1, 0x17f2, 0x17f3, 0x17f4, 0x17f5, 0x17f6, 0x17f7,
+ 0x17f8, 0x17f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1800, 0x1801, 0x1802, 0x1803, 0x1804, 0x1805, 0x1806, 0x1807,
+ 0x1808, 0x1809, 0x180a, 0x180b, 0x180c, 0x180d, 0x180e, 0x0000,
+ 0x1810, 0x1811, 0x1812, 0x1813, 0x1814, 0x1815, 0x1816, 0x1817,
+ 0x1818, 0x1819, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827,
+ 0x1828, 0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f,
+ 0x1830, 0x1831, 0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837,
+ 0x1838, 0x1839, 0x183a, 0x183b, 0x183c, 0x183d, 0x183e, 0x183f,
+ 0x1840, 0x1841, 0x1842, 0x1843, 0x1844, 0x1845, 0x1846, 0x1847,
+ 0x1848, 0x1849, 0x184a, 0x184b, 0x184c, 0x184d, 0x184e, 0x184f,
+ 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855, 0x1856, 0x1857,
+ 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e, 0x185f,
+ 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
+ 0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f,
+ 0x1870, 0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1880, 0x1881, 0x1882, 0x1883, 0x1884, 0x1885, 0x1886, 0x1887,
+ 0x1888, 0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f,
+ 0x1890, 0x1891, 0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897,
+ 0x1898, 0x1899, 0x189a, 0x189b, 0x189c, 0x189d, 0x189e, 0x189f,
+ 0x18a0, 0x18a1, 0x18a2, 0x18a3, 0x18a4, 0x18a5, 0x18a6, 0x18a7,
+ 0x18a8, 0x18a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1900, 0x1901, 0x1902, 0x1903, 0x1904, 0x1905, 0x1906, 0x1907,
+ 0x1908, 0x1909, 0x190a, 0x190b, 0x190c, 0x190d, 0x190e, 0x190f,
+ 0x1910, 0x1911, 0x1912, 0x1913, 0x1914, 0x1915, 0x1916, 0x1917,
+ 0x1918, 0x1919, 0x191a, 0x191b, 0x191c, 0x0000, 0x0000, 0x0000,
+ 0x1920, 0x1921, 0x1922, 0x1923, 0x1924, 0x1925, 0x1926, 0x1927,
+ 0x1928, 0x1929, 0x192a, 0x192b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1930, 0x1931, 0x1932, 0x1933, 0x1934, 0x1935, 0x1936, 0x1937,
+ 0x1938, 0x1939, 0x193a, 0x193b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1940, 0x0000, 0x0000, 0x0000, 0x1944, 0x1945, 0x1946, 0x1947,
+ 0x1948, 0x1949, 0x194a, 0x194b, 0x194c, 0x194d, 0x194e, 0x194f,
+ 0x1950, 0x1951, 0x1952, 0x1953, 0x1954, 0x1955, 0x1956, 0x1957,
+ 0x1958, 0x1959, 0x195a, 0x195b, 0x195c, 0x195d, 0x195e, 0x195f,
+ 0x1960, 0x1961, 0x1962, 0x1963, 0x1964, 0x1965, 0x1966, 0x1967,
+ 0x1968, 0x1969, 0x196a, 0x196b, 0x196c, 0x196d, 0x0000, 0x0000,
+ 0x1970, 0x1971, 0x1972, 0x1973, 0x1974, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1980, 0x1981, 0x1982, 0x1983, 0x1984, 0x1985, 0x1986, 0x1987,
+ 0x1988, 0x1989, 0x198a, 0x198b, 0x198c, 0x198d, 0x198e, 0x198f,
+ 0x1990, 0x1991, 0x1992, 0x1993, 0x1994, 0x1995, 0x1996, 0x1997,
+ 0x1998, 0x1999, 0x199a, 0x199b, 0x199c, 0x199d, 0x199e, 0x199f,
+ 0x19a0, 0x19a1, 0x19a2, 0x19a3, 0x19a4, 0x19a5, 0x19a6, 0x19a7,
+ 0x19a8, 0x19a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x19b0, 0x19b1, 0x19b2, 0x19b3, 0x19b4, 0x19b5, 0x19b6, 0x19b7,
+ 0x19b8, 0x19b9, 0x19ba, 0x19bb, 0x19bc, 0x19bd, 0x19be, 0x19bf,
+ 0x19c0, 0x19c1, 0x19c2, 0x19c3, 0x19c4, 0x19c5, 0x19c6, 0x19c7,
+ 0x19c8, 0x19c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x19d0, 0x19d1, 0x19d2, 0x19d3, 0x19d4, 0x19d5, 0x19d6, 0x19d7,
+ 0x19d8, 0x19d9, 0x0000, 0x0000, 0x0000, 0x0000, 0x19de, 0x19df,
+ 0x19e0, 0x19e1, 0x19e2, 0x19e3, 0x19e4, 0x19e5, 0x19e6, 0x19e7,
+ 0x19e8, 0x19e9, 0x19ea, 0x19eb, 0x19ec, 0x19ed, 0x19ee, 0x19ef,
+ 0x19f0, 0x19f1, 0x19f2, 0x19f3, 0x19f4, 0x19f5, 0x19f6, 0x19f7,
+ 0x19f8, 0x19f9, 0x19fa, 0x19fb, 0x19fc, 0x19fd, 0x19fe, 0x19ff,
+ 0x1a00, 0x1a01, 0x1a02, 0x1a03, 0x1a04, 0x1a05, 0x1a06, 0x1a07,
+ 0x1a08, 0x1a09, 0x1a0a, 0x1a0b, 0x1a0c, 0x1a0d, 0x1a0e, 0x1a0f,
+ 0x1a10, 0x1a11, 0x1a12, 0x1a13, 0x1a14, 0x1a15, 0x1a16, 0x1a17,
+ 0x1a18, 0x1a19, 0x1a1a, 0x1a1b, 0x0000, 0x0000, 0x1a1e, 0x1a1f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1b00, 0x1b01, 0x1b02, 0x1b03, 0x1b04, 0x1b05, 0x1b06, 0x1b07,
+ 0x1b08, 0x1b09, 0x1b0a, 0x1b0b, 0x1b0c, 0x1b0d, 0x1b0e, 0x1b0f,
+ 0x1b10, 0x1b11, 0x1b12, 0x1b13, 0x1b14, 0x1b15, 0x1b16, 0x1b17,
+ 0x1b18, 0x1b19, 0x1b1a, 0x1b1b, 0x1b1c, 0x1b1d, 0x1b1e, 0x1b1f,
+ 0x1b20, 0x1b21, 0x1b22, 0x1b23, 0x1b24, 0x1b25, 0x1b26, 0x1b27,
+ 0x1b28, 0x1b29, 0x1b2a, 0x1b2b, 0x1b2c, 0x1b2d, 0x1b2e, 0x1b2f,
+ 0x1b30, 0x1b31, 0x1b32, 0x1b33, 0x1b34, 0x1b35, 0x1b36, 0x1b37,
+ 0x1b38, 0x1b39, 0x1b3a, 0x1b3b, 0x1b3c, 0x1b3d, 0x1b3e, 0x1b3f,
+ 0x1b40, 0x1b41, 0x1b42, 0x1b43, 0x1b44, 0x1b45, 0x1b46, 0x1b47,
+ 0x1b48, 0x1b49, 0x1b4a, 0x1b4b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1b50, 0x1b51, 0x1b52, 0x1b53, 0x1b54, 0x1b55, 0x1b56, 0x1b57,
+ 0x1b58, 0x1b59, 0x1b5a, 0x1b5b, 0x1b5c, 0x1b5d, 0x1b5e, 0x1b5f,
+ 0x1b60, 0x1b61, 0x1b62, 0x1b63, 0x1b64, 0x1b65, 0x1b66, 0x1b67,
+ 0x1b68, 0x1b69, 0x1b6a, 0x1b6b, 0x1b6c, 0x1b6d, 0x1b6e, 0x1b6f,
+ 0x1b70, 0x1b71, 0x1b72, 0x1b73, 0x1b74, 0x1b75, 0x1b76, 0x1b77,
+ 0x1b78, 0x1b79, 0x1b7a, 0x1b7b, 0x1b7c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1d00, 0x1d01, 0x1d02, 0x1d03, 0x1d04, 0x1d05, 0x1d06, 0x1d07,
+ 0x1d08, 0x1d09, 0x1d0a, 0x1d0b, 0x1d0c, 0x1d0d, 0x1d0e, 0x1d0f,
+ 0x1d10, 0x1d11, 0x1d12, 0x1d13, 0x1d14, 0x1d15, 0x1d16, 0x1d17,
+ 0x1d18, 0x1d19, 0x1d1a, 0x1d1b, 0x1d1c, 0x1d1d, 0x1d1e, 0x1d1f,
+ 0x1d20, 0x1d21, 0x1d22, 0x1d23, 0x1d24, 0x1d25, 0x1d26, 0x1d27,
+ 0x1d28, 0x1d29, 0x1d2a, 0x1d2b, 0x1d2c, 0x1d2d, 0x1d2e, 0x1d2f,
+ 0x1d30, 0x1d31, 0x1d32, 0x1d33, 0x1d34, 0x1d35, 0x1d36, 0x1d37,
+ 0x1d38, 0x1d39, 0x1d3a, 0x1d3b, 0x1d3c, 0x1d3d, 0x1d3e, 0x1d3f,
+ 0x1d40, 0x1d41, 0x1d42, 0x1d43, 0x1d44, 0x1d45, 0x1d46, 0x1d47,
+ 0x1d48, 0x1d49, 0x1d4a, 0x1d4b, 0x1d4c, 0x1d4d, 0x1d4e, 0x1d4f,
+ 0x1d50, 0x1d51, 0x1d52, 0x1d53, 0x1d54, 0x1d55, 0x1d56, 0x1d57,
+ 0x1d58, 0x1d59, 0x1d5a, 0x1d5b, 0x1d5c, 0x1d5d, 0x1d5e, 0x1d5f,
+ 0x1d60, 0x1d61, 0x1d62, 0x1d63, 0x1d64, 0x1d65, 0x1d66, 0x1d67,
+ 0x1d68, 0x1d69, 0x1d6a, 0x1d6b, 0x1d6c, 0x1d6d, 0x1d6e, 0x1d6f,
+ 0x1d70, 0x1d71, 0x1d72, 0x1d73, 0x1d74, 0x1d75, 0x1d76, 0x1d77,
+ 0x1d78, 0x1d79, 0x1d7a, 0x1d7b, 0x1d7c, 0x1d7d, 0x1d7e, 0x1d7f,
+ 0x1d80, 0x1d81, 0x1d82, 0x1d83, 0x1d84, 0x1d85, 0x1d86, 0x1d87,
+ 0x1d88, 0x1d89, 0x1d8a, 0x1d8b, 0x1d8c, 0x1d8d, 0x1d8e, 0x1d8f,
+ 0x1d90, 0x1d91, 0x1d92, 0x1d93, 0x1d94, 0x1d95, 0x1d96, 0x1d97,
+ 0x1d98, 0x1d99, 0x1d9a, 0x1d9b, 0x1d9c, 0x1d9d, 0x1d9e, 0x1d9f,
+ 0x1da0, 0x1da1, 0x1da2, 0x1da3, 0x1da4, 0x1da5, 0x1da6, 0x1da7,
+ 0x1da8, 0x1da9, 0x1daa, 0x1dab, 0x1dac, 0x1dad, 0x1dae, 0x1daf,
+ 0x1db0, 0x1db1, 0x1db2, 0x1db3, 0x1db4, 0x1db5, 0x1db6, 0x1db7,
+ 0x1db8, 0x1db9, 0x1dba, 0x1dbb, 0x1dbc, 0x1dbd, 0x1dbe, 0x1dbf,
+ 0x1dc0, 0x1dc1, 0x1dc2, 0x1dc3, 0x1dc4, 0x1dc5, 0x1dc6, 0x1dc7,
+ 0x1dc8, 0x1dc9, 0x1dca, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1dfe, 0x1dff,
+ 0x1e01, 0x1e01, 0x1e03, 0x1e03, 0x1e05, 0x1e05, 0x1e07, 0x1e07,
+ 0x1e09, 0x1e09, 0x1e0b, 0x1e0b, 0x1e0d, 0x1e0d, 0x1e0f, 0x1e0f,
+ 0x1e11, 0x1e11, 0x1e13, 0x1e13, 0x1e15, 0x1e15, 0x1e17, 0x1e17,
+ 0x1e19, 0x1e19, 0x1e1b, 0x1e1b, 0x1e1d, 0x1e1d, 0x1e1f, 0x1e1f,
+ 0x1e21, 0x1e21, 0x1e23, 0x1e23, 0x1e25, 0x1e25, 0x1e27, 0x1e27,
+ 0x1e29, 0x1e29, 0x1e2b, 0x1e2b, 0x1e2d, 0x1e2d, 0x1e2f, 0x1e2f,
+ 0x1e31, 0x1e31, 0x1e33, 0x1e33, 0x1e35, 0x1e35, 0x1e37, 0x1e37,
+ 0x1e39, 0x1e39, 0x1e3b, 0x1e3b, 0x1e3d, 0x1e3d, 0x1e3f, 0x1e3f,
+ 0x1e41, 0x1e41, 0x1e43, 0x1e43, 0x1e45, 0x1e45, 0x1e47, 0x1e47,
+ 0x1e49, 0x1e49, 0x1e4b, 0x1e4b, 0x1e4d, 0x1e4d, 0x1e4f, 0x1e4f,
+ 0x1e51, 0x1e51, 0x1e53, 0x1e53, 0x1e55, 0x1e55, 0x1e57, 0x1e57,
+ 0x1e59, 0x1e59, 0x1e5b, 0x1e5b, 0x1e5d, 0x1e5d, 0x1e5f, 0x1e5f,
+ 0x1e61, 0x1e61, 0x1e63, 0x1e63, 0x1e65, 0x1e65, 0x1e67, 0x1e67,
+ 0x1e69, 0x1e69, 0x1e6b, 0x1e6b, 0x1e6d, 0x1e6d, 0x1e6f, 0x1e6f,
+ 0x1e71, 0x1e71, 0x1e73, 0x1e73, 0x1e75, 0x1e75, 0x1e77, 0x1e77,
+ 0x1e79, 0x1e79, 0x1e7b, 0x1e7b, 0x1e7d, 0x1e7d, 0x1e7f, 0x1e7f,
+ 0x1e81, 0x1e81, 0x1e83, 0x1e83, 0x1e85, 0x1e85, 0x1e87, 0x1e87,
+ 0x1e89, 0x1e89, 0x1e8b, 0x1e8b, 0x1e8d, 0x1e8d, 0x1e8f, 0x1e8f,
+ 0x1e91, 0x1e91, 0x1e93, 0x1e93, 0x1e95, 0x1e95, 0x1e96, 0x1e97,
+ 0x1e98, 0x1e99, 0x1e9a, 0x1e9b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1ea1, 0x1ea1, 0x1ea3, 0x1ea3, 0x1ea5, 0x1ea5, 0x1ea7, 0x1ea7,
+ 0x1ea9, 0x1ea9, 0x1eab, 0x1eab, 0x1ead, 0x1ead, 0x1eaf, 0x1eaf,
+ 0x1eb1, 0x1eb1, 0x1eb3, 0x1eb3, 0x1eb5, 0x1eb5, 0x1eb7, 0x1eb7,
+ 0x1eb9, 0x1eb9, 0x1ebb, 0x1ebb, 0x1ebd, 0x1ebd, 0x1ebf, 0x1ebf,
+ 0x1ec1, 0x1ec1, 0x1ec3, 0x1ec3, 0x1ec5, 0x1ec5, 0x1ec7, 0x1ec7,
+ 0x1ec9, 0x1ec9, 0x1ecb, 0x1ecb, 0x1ecd, 0x1ecd, 0x1ecf, 0x1ecf,
+ 0x1ed1, 0x1ed1, 0x1ed3, 0x1ed3, 0x1ed5, 0x1ed5, 0x1ed7, 0x1ed7,
+ 0x1ed9, 0x1ed9, 0x1edb, 0x1edb, 0x1edd, 0x1edd, 0x1edf, 0x1edf,
+ 0x1ee1, 0x1ee1, 0x1ee3, 0x1ee3, 0x1ee5, 0x1ee5, 0x1ee7, 0x1ee7,
+ 0x1ee9, 0x1ee9, 0x1eeb, 0x1eeb, 0x1eed, 0x1eed, 0x1eef, 0x1eef,
+ 0x1ef1, 0x1ef1, 0x1ef3, 0x1ef3, 0x1ef5, 0x1ef5, 0x1ef7, 0x1ef7,
+ 0x1ef9, 0x1ef9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1f00, 0x1f01, 0x1f02, 0x1f03, 0x1f04, 0x1f05, 0x1f06, 0x1f07,
+ 0x1f00, 0x1f01, 0x1f02, 0x1f03, 0x1f04, 0x1f05, 0x1f06, 0x1f07,
+ 0x1f10, 0x1f11, 0x1f12, 0x1f13, 0x1f14, 0x1f15, 0x0000, 0x0000,
+ 0x1f10, 0x1f11, 0x1f12, 0x1f13, 0x1f14, 0x1f15, 0x0000, 0x0000,
+ 0x1f20, 0x1f21, 0x1f22, 0x1f23, 0x1f24, 0x1f25, 0x1f26, 0x1f27,
+ 0x1f20, 0x1f21, 0x1f22, 0x1f23, 0x1f24, 0x1f25, 0x1f26, 0x1f27,
+ 0x1f30, 0x1f31, 0x1f32, 0x1f33, 0x1f34, 0x1f35, 0x1f36, 0x1f37,
+ 0x1f30, 0x1f31, 0x1f32, 0x1f33, 0x1f34, 0x1f35, 0x1f36, 0x1f37,
+ 0x1f40, 0x1f41, 0x1f42, 0x1f43, 0x1f44, 0x1f45, 0x0000, 0x0000,
+ 0x1f40, 0x1f41, 0x1f42, 0x1f43, 0x1f44, 0x1f45, 0x0000, 0x0000,
+ 0x1f50, 0x1f51, 0x1f52, 0x1f53, 0x1f54, 0x1f55, 0x1f56, 0x1f57,
+ 0x0000, 0x1f51, 0x0000, 0x1f53, 0x0000, 0x1f55, 0x0000, 0x1f57,
+ 0x1f60, 0x1f61, 0x1f62, 0x1f63, 0x1f64, 0x1f65, 0x1f66, 0x1f67,
+ 0x1f60, 0x1f61, 0x1f62, 0x1f63, 0x1f64, 0x1f65, 0x1f66, 0x1f67,
+ 0x1f70, 0x1f71, 0x1f72, 0x1f73, 0x1f74, 0x1f75, 0x1f76, 0x1f77,
+ 0x1f78, 0x1f79, 0x1f7a, 0x1f7b, 0x1f7c, 0x1f7d, 0x0000, 0x0000,
+ 0x1f80, 0x1f81, 0x1f82, 0x1f83, 0x1f84, 0x1f85, 0x1f86, 0x1f87,
+ 0x1f80, 0x1f81, 0x1f82, 0x1f83, 0x1f84, 0x1f85, 0x1f86, 0x1f87,
+ 0x1f90, 0x1f91, 0x1f92, 0x1f93, 0x1f94, 0x1f95, 0x1f96, 0x1f97,
+ 0x1f90, 0x1f91, 0x1f92, 0x1f93, 0x1f94, 0x1f95, 0x1f96, 0x1f97,
+ 0x1fa0, 0x1fa1, 0x1fa2, 0x1fa3, 0x1fa4, 0x1fa5, 0x1fa6, 0x1fa7,
+ 0x1fa0, 0x1fa1, 0x1fa2, 0x1fa3, 0x1fa4, 0x1fa5, 0x1fa6, 0x1fa7,
+ 0x1fb0, 0x1fb1, 0x1fb2, 0x1fb3, 0x1fb4, 0x0000, 0x1fb6, 0x1fb7,
+ 0x1fb0, 0x1fb1, 0x1f70, 0x1f71, 0x1fb3, 0x1fbd, 0x1fbe, 0x1fbf,
+ 0x1fc0, 0x1fc1, 0x1fc2, 0x1fc3, 0x1fc4, 0x0000, 0x1fc6, 0x1fc7,
+ 0x1f72, 0x1f73, 0x1f74, 0x1f75, 0x1fc3, 0x1fcd, 0x1fce, 0x1fcf,
+ 0x1fd0, 0x1fd1, 0x1fd2, 0x1fd3, 0x0000, 0x0000, 0x1fd6, 0x1fd7,
+ 0x1fd0, 0x1fd1, 0x1f76, 0x1f77, 0x0000, 0x1fdd, 0x1fde, 0x1fdf,
+ 0x1fe0, 0x1fe1, 0x1fe2, 0x1fe3, 0x1fe4, 0x1fe5, 0x1fe6, 0x1fe7,
+ 0x1fe0, 0x1fe1, 0x1f7a, 0x1f7b, 0x1fe5, 0x1fed, 0x1fee, 0x1fef,
+ 0x0000, 0x0000, 0x1ff2, 0x1ff3, 0x1ff4, 0x0000, 0x1ff6, 0x1ff7,
+ 0x1f78, 0x1f79, 0x1f7c, 0x1f7d, 0x1ff3, 0x1ffd, 0x1ffe, 0x0000,
+ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
+ 0x2008, 0x2009, 0x200a, 0x200b, 0x200c, 0x200d, 0x200e, 0x200f,
+ 0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017,
+ 0x2018, 0x2019, 0x201a, 0x201b, 0x201c, 0x201d, 0x201e, 0x201f,
+ 0x2020, 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027,
+ 0x2028, 0x2029, 0x202a, 0x202b, 0x202c, 0x202d, 0x202e, 0x202f,
+ 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037,
+ 0x2038, 0x2039, 0x203a, 0x203b, 0x203c, 0x203d, 0x203e, 0x203f,
+ 0x2040, 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047,
+ 0x2048, 0x2049, 0x204a, 0x204b, 0x204c, 0x204d, 0x204e, 0x204f,
+ 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057,
+ 0x2058, 0x2059, 0x205a, 0x205b, 0x205c, 0x205d, 0x205e, 0x205f,
+ 0x2060, 0x2061, 0x2062, 0x2063, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x206a, 0x206b, 0x206c, 0x206d, 0x206e, 0x206f,
+ 0x2070, 0x2071, 0x0000, 0x0000, 0x2074, 0x2075, 0x2076, 0x2077,
+ 0x2078, 0x2079, 0x207a, 0x207b, 0x207c, 0x207d, 0x207e, 0x207f,
+ 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087,
+ 0x2088, 0x2089, 0x208a, 0x208b, 0x208c, 0x208d, 0x208e, 0x0000,
+ 0x2090, 0x2091, 0x2092, 0x2093, 0x2094, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x20a0, 0x20a1, 0x20a2, 0x20a3, 0x20a4, 0x20a5, 0x20a6, 0x20a7,
+ 0x20a8, 0x20a9, 0x20aa, 0x20ab, 0x20ac, 0x20ad, 0x20ae, 0x20af,
+ 0x20b0, 0x20b1, 0x20b2, 0x20b3, 0x20b4, 0x20b5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x20d0, 0x20d1, 0x20d2, 0x20d3, 0x20d4, 0x20d5, 0x20d6, 0x20d7,
+ 0x20d8, 0x20d9, 0x20da, 0x20db, 0x20dc, 0x20dd, 0x20de, 0x20df,
+ 0x20e0, 0x20e1, 0x20e2, 0x20e3, 0x20e4, 0x20e5, 0x20e6, 0x20e7,
+ 0x20e8, 0x20e9, 0x20ea, 0x20eb, 0x20ec, 0x20ed, 0x20ee, 0x20ef,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107,
+ 0x2108, 0x2109, 0x210a, 0x210b, 0x210c, 0x210d, 0x210e, 0x210f,
+ 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117,
+ 0x2118, 0x2119, 0x211a, 0x211b, 0x211c, 0x211d, 0x211e, 0x211f,
+ 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x03c9, 0x2127,
+ 0x2128, 0x2129, 0x006b, 0x00e5, 0x212c, 0x212d, 0x212e, 0x212f,
+ 0x2130, 0x2131, 0x214e, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137,
+ 0x2138, 0x2139, 0x213a, 0x213b, 0x213c, 0x213d, 0x213e, 0x213f,
+ 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147,
+ 0x2148, 0x2149, 0x214a, 0x214b, 0x214c, 0x214d, 0x214e, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157,
+ 0x2158, 0x2159, 0x215a, 0x215b, 0x215c, 0x215d, 0x215e, 0x215f,
+ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
+ 0x2178, 0x2179, 0x217a, 0x217b, 0x217c, 0x217d, 0x217e, 0x217f,
+ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
+ 0x2178, 0x2179, 0x217a, 0x217b, 0x217c, 0x217d, 0x217e, 0x217f,
+ 0x2180, 0x2181, 0x2182, 0x2184, 0x2184, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197,
+ 0x2198, 0x2199, 0x219a, 0x219b, 0x219c, 0x219d, 0x219e, 0x219f,
+ 0x21a0, 0x21a1, 0x21a2, 0x21a3, 0x21a4, 0x21a5, 0x21a6, 0x21a7,
+ 0x21a8, 0x21a9, 0x21aa, 0x21ab, 0x21ac, 0x21ad, 0x21ae, 0x21af,
+ 0x21b0, 0x21b1, 0x21b2, 0x21b3, 0x21b4, 0x21b5, 0x21b6, 0x21b7,
+ 0x21b8, 0x21b9, 0x21ba, 0x21bb, 0x21bc, 0x21bd, 0x21be, 0x21bf,
+ 0x21c0, 0x21c1, 0x21c2, 0x21c3, 0x21c4, 0x21c5, 0x21c6, 0x21c7,
+ 0x21c8, 0x21c9, 0x21ca, 0x21cb, 0x21cc, 0x21cd, 0x21ce, 0x21cf,
+ 0x21d0, 0x21d1, 0x21d2, 0x21d3, 0x21d4, 0x21d5, 0x21d6, 0x21d7,
+ 0x21d8, 0x21d9, 0x21da, 0x21db, 0x21dc, 0x21dd, 0x21de, 0x21df,
+ 0x21e0, 0x21e1, 0x21e2, 0x21e3, 0x21e4, 0x21e5, 0x21e6, 0x21e7,
+ 0x21e8, 0x21e9, 0x21ea, 0x21eb, 0x21ec, 0x21ed, 0x21ee, 0x21ef,
+ 0x21f0, 0x21f1, 0x21f2, 0x21f3, 0x21f4, 0x21f5, 0x21f6, 0x21f7,
+ 0x21f8, 0x21f9, 0x21fa, 0x21fb, 0x21fc, 0x21fd, 0x21fe, 0x21ff,
+ 0x2200, 0x2201, 0x2202, 0x2203, 0x2204, 0x2205, 0x2206, 0x2207,
+ 0x2208, 0x2209, 0x220a, 0x220b, 0x220c, 0x220d, 0x220e, 0x220f,
+ 0x2210, 0x2211, 0x2212, 0x2213, 0x2214, 0x2215, 0x2216, 0x2217,
+ 0x2218, 0x2219, 0x221a, 0x221b, 0x221c, 0x221d, 0x221e, 0x221f,
+ 0x2220, 0x2221, 0x2222, 0x2223, 0x2224, 0x2225, 0x2226, 0x2227,
+ 0x2228, 0x2229, 0x222a, 0x222b, 0x222c, 0x222d, 0x222e, 0x222f,
+ 0x2230, 0x2231, 0x2232, 0x2233, 0x2234, 0x2235, 0x2236, 0x2237,
+ 0x2238, 0x2239, 0x223a, 0x223b, 0x223c, 0x223d, 0x223e, 0x223f,
+ 0x2240, 0x2241, 0x2242, 0x2243, 0x2244, 0x2245, 0x2246, 0x2247,
+ 0x2248, 0x2249, 0x224a, 0x224b, 0x224c, 0x224d, 0x224e, 0x224f,
+ 0x2250, 0x2251, 0x2252, 0x2253, 0x2254, 0x2255, 0x2256, 0x2257,
+ 0x2258, 0x2259, 0x225a, 0x225b, 0x225c, 0x225d, 0x225e, 0x225f,
+ 0x2260, 0x2261, 0x2262, 0x2263, 0x2264, 0x2265, 0x2266, 0x2267,
+ 0x2268, 0x2269, 0x226a, 0x226b, 0x226c, 0x226d, 0x226e, 0x226f,
+ 0x2270, 0x2271, 0x2272, 0x2273, 0x2274, 0x2275, 0x2276, 0x2277,
+ 0x2278, 0x2279, 0x227a, 0x227b, 0x227c, 0x227d, 0x227e, 0x227f,
+ 0x2280, 0x2281, 0x2282, 0x2283, 0x2284, 0x2285, 0x2286, 0x2287,
+ 0x2288, 0x2289, 0x228a, 0x228b, 0x228c, 0x228d, 0x228e, 0x228f,
+ 0x2290, 0x2291, 0x2292, 0x2293, 0x2294, 0x2295, 0x2296, 0x2297,
+ 0x2298, 0x2299, 0x229a, 0x229b, 0x229c, 0x229d, 0x229e, 0x229f,
+ 0x22a0, 0x22a1, 0x22a2, 0x22a3, 0x22a4, 0x22a5, 0x22a6, 0x22a7,
+ 0x22a8, 0x22a9, 0x22aa, 0x22ab, 0x22ac, 0x22ad, 0x22ae, 0x22af,
+ 0x22b0, 0x22b1, 0x22b2, 0x22b3, 0x22b4, 0x22b5, 0x22b6, 0x22b7,
+ 0x22b8, 0x22b9, 0x22ba, 0x22bb, 0x22bc, 0x22bd, 0x22be, 0x22bf,
+ 0x22c0, 0x22c1, 0x22c2, 0x22c3, 0x22c4, 0x22c5, 0x22c6, 0x22c7,
+ 0x22c8, 0x22c9, 0x22ca, 0x22cb, 0x22cc, 0x22cd, 0x22ce, 0x22cf,
+ 0x22d0, 0x22d1, 0x22d2, 0x22d3, 0x22d4, 0x22d5, 0x22d6, 0x22d7,
+ 0x22d8, 0x22d9, 0x22da, 0x22db, 0x22dc, 0x22dd, 0x22de, 0x22df,
+ 0x22e0, 0x22e1, 0x22e2, 0x22e3, 0x22e4, 0x22e5, 0x22e6, 0x22e7,
+ 0x22e8, 0x22e9, 0x22ea, 0x22eb, 0x22ec, 0x22ed, 0x22ee, 0x22ef,
+ 0x22f0, 0x22f1, 0x22f2, 0x22f3, 0x22f4, 0x22f5, 0x22f6, 0x22f7,
+ 0x22f8, 0x22f9, 0x22fa, 0x22fb, 0x22fc, 0x22fd, 0x22fe, 0x22ff,
+ 0x2300, 0x2301, 0x2302, 0x2303, 0x2304, 0x2305, 0x2306, 0x2307,
+ 0x2308, 0x2309, 0x230a, 0x230b, 0x230c, 0x230d, 0x230e, 0x230f,
+ 0x2310, 0x2311, 0x2312, 0x2313, 0x2314, 0x2315, 0x2316, 0x2317,
+ 0x2318, 0x2319, 0x231a, 0x231b, 0x231c, 0x231d, 0x231e, 0x231f,
+ 0x2320, 0x2321, 0x2322, 0x2323, 0x2324, 0x2325, 0x2326, 0x2327,
+ 0x2328, 0x2329, 0x232a, 0x232b, 0x232c, 0x232d, 0x232e, 0x232f,
+ 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337,
+ 0x2338, 0x2339, 0x233a, 0x233b, 0x233c, 0x233d, 0x233e, 0x233f,
+ 0x2340, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347,
+ 0x2348, 0x2349, 0x234a, 0x234b, 0x234c, 0x234d, 0x234e, 0x234f,
+ 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357,
+ 0x2358, 0x2359, 0x235a, 0x235b, 0x235c, 0x235d, 0x235e, 0x235f,
+ 0x2360, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367,
+ 0x2368, 0x2369, 0x236a, 0x236b, 0x236c, 0x236d, 0x236e, 0x236f,
+ 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377,
+ 0x2378, 0x2379, 0x237a, 0x237b, 0x237c, 0x237d, 0x237e, 0x237f,
+ 0x2380, 0x2381, 0x2382, 0x2383, 0x2384, 0x2385, 0x2386, 0x2387,
+ 0x2388, 0x2389, 0x238a, 0x238b, 0x238c, 0x238d, 0x238e, 0x238f,
+ 0x2390, 0x2391, 0x2392, 0x2393, 0x2394, 0x2395, 0x2396, 0x2397,
+ 0x2398, 0x2399, 0x239a, 0x239b, 0x239c, 0x239d, 0x239e, 0x239f,
+ 0x23a0, 0x23a1, 0x23a2, 0x23a3, 0x23a4, 0x23a5, 0x23a6, 0x23a7,
+ 0x23a8, 0x23a9, 0x23aa, 0x23ab, 0x23ac, 0x23ad, 0x23ae, 0x23af,
+ 0x23b0, 0x23b1, 0x23b2, 0x23b3, 0x23b4, 0x23b5, 0x23b6, 0x23b7,
+ 0x23b8, 0x23b9, 0x23ba, 0x23bb, 0x23bc, 0x23bd, 0x23be, 0x23bf,
+ 0x23c0, 0x23c1, 0x23c2, 0x23c3, 0x23c4, 0x23c5, 0x23c6, 0x23c7,
+ 0x23c8, 0x23c9, 0x23ca, 0x23cb, 0x23cc, 0x23cd, 0x23ce, 0x23cf,
+ 0x23d0, 0x23d1, 0x23d2, 0x23d3, 0x23d4, 0x23d5, 0x23d6, 0x23d7,
+ 0x23d8, 0x23d9, 0x23da, 0x23db, 0x23dc, 0x23dd, 0x23de, 0x23df,
+ 0x23e0, 0x23e1, 0x23e2, 0x23e3, 0x23e4, 0x23e5, 0x23e6, 0x23e7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2400, 0x2401, 0x2402, 0x2403, 0x2404, 0x2405, 0x2406, 0x2407,
+ 0x2408, 0x2409, 0x240a, 0x240b, 0x240c, 0x240d, 0x240e, 0x240f,
+ 0x2410, 0x2411, 0x2412, 0x2413, 0x2414, 0x2415, 0x2416, 0x2417,
+ 0x2418, 0x2419, 0x241a, 0x241b, 0x241c, 0x241d, 0x241e, 0x241f,
+ 0x2420, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447,
+ 0x2448, 0x2449, 0x244a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467,
+ 0x2468, 0x2469, 0x246a, 0x246b, 0x246c, 0x246d, 0x246e, 0x246f,
+ 0x2470, 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, 0x2477,
+ 0x2478, 0x2479, 0x247a, 0x247b, 0x247c, 0x247d, 0x247e, 0x247f,
+ 0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487,
+ 0x2488, 0x2489, 0x248a, 0x248b, 0x248c, 0x248d, 0x248e, 0x248f,
+ 0x2490, 0x2491, 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, 0x2497,
+ 0x2498, 0x2499, 0x249a, 0x249b, 0x249c, 0x249d, 0x249e, 0x249f,
+ 0x24a0, 0x24a1, 0x24a2, 0x24a3, 0x24a4, 0x24a5, 0x24a6, 0x24a7,
+ 0x24a8, 0x24a9, 0x24aa, 0x24ab, 0x24ac, 0x24ad, 0x24ae, 0x24af,
+ 0x24b0, 0x24b1, 0x24b2, 0x24b3, 0x24b4, 0x24b5, 0x24d0, 0x24d1,
+ 0x24d2, 0x24d3, 0x24d4, 0x24d5, 0x24d6, 0x24d7, 0x24d8, 0x24d9,
+ 0x24da, 0x24db, 0x24dc, 0x24dd, 0x24de, 0x24df, 0x24e0, 0x24e1,
+ 0x24e2, 0x24e3, 0x24e4, 0x24e5, 0x24e6, 0x24e7, 0x24e8, 0x24e9,
+ 0x24d0, 0x24d1, 0x24d2, 0x24d3, 0x24d4, 0x24d5, 0x24d6, 0x24d7,
+ 0x24d8, 0x24d9, 0x24da, 0x24db, 0x24dc, 0x24dd, 0x24de, 0x24df,
+ 0x24e0, 0x24e1, 0x24e2, 0x24e3, 0x24e4, 0x24e5, 0x24e6, 0x24e7,
+ 0x24e8, 0x24e9, 0x24ea, 0x24eb, 0x24ec, 0x24ed, 0x24ee, 0x24ef,
+ 0x24f0, 0x24f1, 0x24f2, 0x24f3, 0x24f4, 0x24f5, 0x24f6, 0x24f7,
+ 0x24f8, 0x24f9, 0x24fa, 0x24fb, 0x24fc, 0x24fd, 0x24fe, 0x24ff,
+ 0x2500, 0x2501, 0x2502, 0x2503, 0x2504, 0x2505, 0x2506, 0x2507,
+ 0x2508, 0x2509, 0x250a, 0x250b, 0x250c, 0x250d, 0x250e, 0x250f,
+ 0x2510, 0x2511, 0x2512, 0x2513, 0x2514, 0x2515, 0x2516, 0x2517,
+ 0x2518, 0x2519, 0x251a, 0x251b, 0x251c, 0x251d, 0x251e, 0x251f,
+ 0x2520, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527,
+ 0x2528, 0x2529, 0x252a, 0x252b, 0x252c, 0x252d, 0x252e, 0x252f,
+ 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537,
+ 0x2538, 0x2539, 0x253a, 0x253b, 0x253c, 0x253d, 0x253e, 0x253f,
+ 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547,
+ 0x2548, 0x2549, 0x254a, 0x254b, 0x254c, 0x254d, 0x254e, 0x254f,
+ 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557,
+ 0x2558, 0x2559, 0x255a, 0x255b, 0x255c, 0x255d, 0x255e, 0x255f,
+ 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567,
+ 0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x256d, 0x256e, 0x256f,
+ 0x2570, 0x2571, 0x2572, 0x2573, 0x2574, 0x2575, 0x2576, 0x2577,
+ 0x2578, 0x2579, 0x257a, 0x257b, 0x257c, 0x257d, 0x257e, 0x257f,
+ 0x2580, 0x2581, 0x2582, 0x2583, 0x2584, 0x2585, 0x2586, 0x2587,
+ 0x2588, 0x2589, 0x258a, 0x258b, 0x258c, 0x258d, 0x258e, 0x258f,
+ 0x2590, 0x2591, 0x2592, 0x2593, 0x2594, 0x2595, 0x2596, 0x2597,
+ 0x2598, 0x2599, 0x259a, 0x259b, 0x259c, 0x259d, 0x259e, 0x259f,
+ 0x25a0, 0x25a1, 0x25a2, 0x25a3, 0x25a4, 0x25a5, 0x25a6, 0x25a7,
+ 0x25a8, 0x25a9, 0x25aa, 0x25ab, 0x25ac, 0x25ad, 0x25ae, 0x25af,
+ 0x25b0, 0x25b1, 0x25b2, 0x25b3, 0x25b4, 0x25b5, 0x25b6, 0x25b7,
+ 0x25b8, 0x25b9, 0x25ba, 0x25bb, 0x25bc, 0x25bd, 0x25be, 0x25bf,
+ 0x25c0, 0x25c1, 0x25c2, 0x25c3, 0x25c4, 0x25c5, 0x25c6, 0x25c7,
+ 0x25c8, 0x25c9, 0x25ca, 0x25cb, 0x25cc, 0x25cd, 0x25ce, 0x25cf,
+ 0x25d0, 0x25d1, 0x25d2, 0x25d3, 0x25d4, 0x25d5, 0x25d6, 0x25d7,
+ 0x25d8, 0x25d9, 0x25da, 0x25db, 0x25dc, 0x25dd, 0x25de, 0x25df,
+ 0x25e0, 0x25e1, 0x25e2, 0x25e3, 0x25e4, 0x25e5, 0x25e6, 0x25e7,
+ 0x25e8, 0x25e9, 0x25ea, 0x25eb, 0x25ec, 0x25ed, 0x25ee, 0x25ef,
+ 0x25f0, 0x25f1, 0x25f2, 0x25f3, 0x25f4, 0x25f5, 0x25f6, 0x25f7,
+ 0x25f8, 0x25f9, 0x25fa, 0x25fb, 0x25fc, 0x25fd, 0x25fe, 0x25ff,
+ 0x2600, 0x2601, 0x2602, 0x2603, 0x2604, 0x2605, 0x2606, 0x2607,
+ 0x2608, 0x2609, 0x260a, 0x260b, 0x260c, 0x260d, 0x260e, 0x260f,
+ 0x2610, 0x2611, 0x2612, 0x2613, 0x2614, 0x2615, 0x2616, 0x2617,
+ 0x2618, 0x2619, 0x261a, 0x261b, 0x261c, 0x261d, 0x261e, 0x261f,
+ 0x2620, 0x2621, 0x2622, 0x2623, 0x2624, 0x2625, 0x2626, 0x2627,
+ 0x2628, 0x2629, 0x262a, 0x262b, 0x262c, 0x262d, 0x262e, 0x262f,
+ 0x2630, 0x2631, 0x2632, 0x2633, 0x2634, 0x2635, 0x2636, 0x2637,
+ 0x2638, 0x2639, 0x263a, 0x263b, 0x263c, 0x263d, 0x263e, 0x263f,
+ 0x2640, 0x2641, 0x2642, 0x2643, 0x2644, 0x2645, 0x2646, 0x2647,
+ 0x2648, 0x2649, 0x264a, 0x264b, 0x264c, 0x264d, 0x264e, 0x264f,
+ 0x2650, 0x2651, 0x2652, 0x2653, 0x2654, 0x2655, 0x2656, 0x2657,
+ 0x2658, 0x2659, 0x265a, 0x265b, 0x265c, 0x265d, 0x265e, 0x265f,
+ 0x2660, 0x2661, 0x2662, 0x2663, 0x2664, 0x2665, 0x2666, 0x2667,
+ 0x2668, 0x2669, 0x266a, 0x266b, 0x266c, 0x266d, 0x266e, 0x266f,
+ 0x2670, 0x2671, 0x2672, 0x2673, 0x2674, 0x2675, 0x2676, 0x2677,
+ 0x2678, 0x2679, 0x267a, 0x267b, 0x267c, 0x267d, 0x267e, 0x267f,
+ 0x2680, 0x2681, 0x2682, 0x2683, 0x2684, 0x2685, 0x2686, 0x2687,
+ 0x2688, 0x2689, 0x268a, 0x268b, 0x268c, 0x268d, 0x268e, 0x268f,
+ 0x2690, 0x2691, 0x2692, 0x2693, 0x2694, 0x2695, 0x2696, 0x2697,
+ 0x2698, 0x2699, 0x269a, 0x269b, 0x269c, 0x0000, 0x0000, 0x0000,
+ 0x26a0, 0x26a1, 0x26a2, 0x26a3, 0x26a4, 0x26a5, 0x26a6, 0x26a7,
+ 0x26a8, 0x26a9, 0x26aa, 0x26ab, 0x26ac, 0x26ad, 0x26ae, 0x26af,
+ 0x26b0, 0x26b1, 0x26b2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2701, 0x2702, 0x2703, 0x2704, 0x0000, 0x2706, 0x2707,
+ 0x2708, 0x2709, 0x0000, 0x0000, 0x270c, 0x270d, 0x270e, 0x270f,
+ 0x2710, 0x2711, 0x2712, 0x2713, 0x2714, 0x2715, 0x2716, 0x2717,
+ 0x2718, 0x2719, 0x271a, 0x271b, 0x271c, 0x271d, 0x271e, 0x271f,
+ 0x2720, 0x2721, 0x2722, 0x2723, 0x2724, 0x2725, 0x2726, 0x2727,
+ 0x0000, 0x2729, 0x272a, 0x272b, 0x272c, 0x272d, 0x272e, 0x272f,
+ 0x2730, 0x2731, 0x2732, 0x2733, 0x2734, 0x2735, 0x2736, 0x2737,
+ 0x2738, 0x2739, 0x273a, 0x273b, 0x273c, 0x273d, 0x273e, 0x273f,
+ 0x2740, 0x2741, 0x2742, 0x2743, 0x2744, 0x2745, 0x2746, 0x2747,
+ 0x2748, 0x2749, 0x274a, 0x274b, 0x0000, 0x274d, 0x0000, 0x274f,
+ 0x2750, 0x2751, 0x2752, 0x0000, 0x0000, 0x0000, 0x2756, 0x0000,
+ 0x2758, 0x2759, 0x275a, 0x275b, 0x275c, 0x275d, 0x275e, 0x0000,
+ 0x0000, 0x2761, 0x2762, 0x2763, 0x2764, 0x2765, 0x2766, 0x2767,
+ 0x2768, 0x2769, 0x276a, 0x276b, 0x276c, 0x276d, 0x276e, 0x276f,
+ 0x2770, 0x2771, 0x2772, 0x2773, 0x2774, 0x2775, 0x2776, 0x2777,
+ 0x2778, 0x2779, 0x277a, 0x277b, 0x277c, 0x277d, 0x277e, 0x277f,
+ 0x2780, 0x2781, 0x2782, 0x2783, 0x2784, 0x2785, 0x2786, 0x2787,
+ 0x2788, 0x2789, 0x278a, 0x278b, 0x278c, 0x278d, 0x278e, 0x278f,
+ 0x2790, 0x2791, 0x2792, 0x2793, 0x2794, 0x0000, 0x0000, 0x0000,
+ 0x2798, 0x2799, 0x279a, 0x279b, 0x279c, 0x279d, 0x279e, 0x279f,
+ 0x27a0, 0x27a1, 0x27a2, 0x27a3, 0x27a4, 0x27a5, 0x27a6, 0x27a7,
+ 0x27a8, 0x27a9, 0x27aa, 0x27ab, 0x27ac, 0x27ad, 0x27ae, 0x27af,
+ 0x0000, 0x27b1, 0x27b2, 0x27b3, 0x27b4, 0x27b5, 0x27b6, 0x27b7,
+ 0x27b8, 0x27b9, 0x27ba, 0x27bb, 0x27bc, 0x27bd, 0x27be, 0x0000,
+ 0x27c0, 0x27c1, 0x27c2, 0x27c3, 0x27c4, 0x27c5, 0x27c6, 0x27c7,
+ 0x27c8, 0x27c9, 0x27ca, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x27d0, 0x27d1, 0x27d2, 0x27d3, 0x27d4, 0x27d5, 0x27d6, 0x27d7,
+ 0x27d8, 0x27d9, 0x27da, 0x27db, 0x27dc, 0x27dd, 0x27de, 0x27df,
+ 0x27e0, 0x27e1, 0x27e2, 0x27e3, 0x27e4, 0x27e5, 0x27e6, 0x27e7,
+ 0x27e8, 0x27e9, 0x27ea, 0x27eb, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x27f0, 0x27f1, 0x27f2, 0x27f3, 0x27f4, 0x27f5, 0x27f6, 0x27f7,
+ 0x27f8, 0x27f9, 0x27fa, 0x27fb, 0x27fc, 0x27fd, 0x27fe, 0x27ff,
+ 0x2800, 0x2801, 0x2802, 0x2803, 0x2804, 0x2805, 0x2806, 0x2807,
+ 0x2808, 0x2809, 0x280a, 0x280b, 0x280c, 0x280d, 0x280e, 0x280f,
+ 0x2810, 0x2811, 0x2812, 0x2813, 0x2814, 0x2815, 0x2816, 0x2817,
+ 0x2818, 0x2819, 0x281a, 0x281b, 0x281c, 0x281d, 0x281e, 0x281f,
+ 0x2820, 0x2821, 0x2822, 0x2823, 0x2824, 0x2825, 0x2826, 0x2827,
+ 0x2828, 0x2829, 0x282a, 0x282b, 0x282c, 0x282d, 0x282e, 0x282f,
+ 0x2830, 0x2831, 0x2832, 0x2833, 0x2834, 0x2835, 0x2836, 0x2837,
+ 0x2838, 0x2839, 0x283a, 0x283b, 0x283c, 0x283d, 0x283e, 0x283f,
+ 0x2840, 0x2841, 0x2842, 0x2843, 0x2844, 0x2845, 0x2846, 0x2847,
+ 0x2848, 0x2849, 0x284a, 0x284b, 0x284c, 0x284d, 0x284e, 0x284f,
+ 0x2850, 0x2851, 0x2852, 0x2853, 0x2854, 0x2855, 0x2856, 0x2857,
+ 0x2858, 0x2859, 0x285a, 0x285b, 0x285c, 0x285d, 0x285e, 0x285f,
+ 0x2860, 0x2861, 0x2862, 0x2863, 0x2864, 0x2865, 0x2866, 0x2867,
+ 0x2868, 0x2869, 0x286a, 0x286b, 0x286c, 0x286d, 0x286e, 0x286f,
+ 0x2870, 0x2871, 0x2872, 0x2873, 0x2874, 0x2875, 0x2876, 0x2877,
+ 0x2878, 0x2879, 0x287a, 0x287b, 0x287c, 0x287d, 0x287e, 0x287f,
+ 0x2880, 0x2881, 0x2882, 0x2883, 0x2884, 0x2885, 0x2886, 0x2887,
+ 0x2888, 0x2889, 0x288a, 0x288b, 0x288c, 0x288d, 0x288e, 0x288f,
+ 0x2890, 0x2891, 0x2892, 0x2893, 0x2894, 0x2895, 0x2896, 0x2897,
+ 0x2898, 0x2899, 0x289a, 0x289b, 0x289c, 0x289d, 0x289e, 0x289f,
+ 0x28a0, 0x28a1, 0x28a2, 0x28a3, 0x28a4, 0x28a5, 0x28a6, 0x28a7,
+ 0x28a8, 0x28a9, 0x28aa, 0x28ab, 0x28ac, 0x28ad, 0x28ae, 0x28af,
+ 0x28b0, 0x28b1, 0x28b2, 0x28b3, 0x28b4, 0x28b5, 0x28b6, 0x28b7,
+ 0x28b8, 0x28b9, 0x28ba, 0x28bb, 0x28bc, 0x28bd, 0x28be, 0x28bf,
+ 0x28c0, 0x28c1, 0x28c2, 0x28c3, 0x28c4, 0x28c5, 0x28c6, 0x28c7,
+ 0x28c8, 0x28c9, 0x28ca, 0x28cb, 0x28cc, 0x28cd, 0x28ce, 0x28cf,
+ 0x28d0, 0x28d1, 0x28d2, 0x28d3, 0x28d4, 0x28d5, 0x28d6, 0x28d7,
+ 0x28d8, 0x28d9, 0x28da, 0x28db, 0x28dc, 0x28dd, 0x28de, 0x28df,
+ 0x28e0, 0x28e1, 0x28e2, 0x28e3, 0x28e4, 0x28e5, 0x28e6, 0x28e7,
+ 0x28e8, 0x28e9, 0x28ea, 0x28eb, 0x28ec, 0x28ed, 0x28ee, 0x28ef,
+ 0x28f0, 0x28f1, 0x28f2, 0x28f3, 0x28f4, 0x28f5, 0x28f6, 0x28f7,
+ 0x28f8, 0x28f9, 0x28fa, 0x28fb, 0x28fc, 0x28fd, 0x28fe, 0x28ff,
+ 0x2900, 0x2901, 0x2902, 0x2903, 0x2904, 0x2905, 0x2906, 0x2907,
+ 0x2908, 0x2909, 0x290a, 0x290b, 0x290c, 0x290d, 0x290e, 0x290f,
+ 0x2910, 0x2911, 0x2912, 0x2913, 0x2914, 0x2915, 0x2916, 0x2917,
+ 0x2918, 0x2919, 0x291a, 0x291b, 0x291c, 0x291d, 0x291e, 0x291f,
+ 0x2920, 0x2921, 0x2922, 0x2923, 0x2924, 0x2925, 0x2926, 0x2927,
+ 0x2928, 0x2929, 0x292a, 0x292b, 0x292c, 0x292d, 0x292e, 0x292f,
+ 0x2930, 0x2931, 0x2932, 0x2933, 0x2934, 0x2935, 0x2936, 0x2937,
+ 0x2938, 0x2939, 0x293a, 0x293b, 0x293c, 0x293d, 0x293e, 0x293f,
+ 0x2940, 0x2941, 0x2942, 0x2943, 0x2944, 0x2945, 0x2946, 0x2947,
+ 0x2948, 0x2949, 0x294a, 0x294b, 0x294c, 0x294d, 0x294e, 0x294f,
+ 0x2950, 0x2951, 0x2952, 0x2953, 0x2954, 0x2955, 0x2956, 0x2957,
+ 0x2958, 0x2959, 0x295a, 0x295b, 0x295c, 0x295d, 0x295e, 0x295f,
+ 0x2960, 0x2961, 0x2962, 0x2963, 0x2964, 0x2965, 0x2966, 0x2967,
+ 0x2968, 0x2969, 0x296a, 0x296b, 0x296c, 0x296d, 0x296e, 0x296f,
+ 0x2970, 0x2971, 0x2972, 0x2973, 0x2974, 0x2975, 0x2976, 0x2977,
+ 0x2978, 0x2979, 0x297a, 0x297b, 0x297c, 0x297d, 0x297e, 0x297f,
+ 0x2980, 0x2981, 0x2982, 0x2983, 0x2984, 0x2985, 0x2986, 0x2987,
+ 0x2988, 0x2989, 0x298a, 0x298b, 0x298c, 0x298d, 0x298e, 0x298f,
+ 0x2990, 0x2991, 0x2992, 0x2993, 0x2994, 0x2995, 0x2996, 0x2997,
+ 0x2998, 0x2999, 0x299a, 0x299b, 0x299c, 0x299d, 0x299e, 0x299f,
+ 0x29a0, 0x29a1, 0x29a2, 0x29a3, 0x29a4, 0x29a5, 0x29a6, 0x29a7,
+ 0x29a8, 0x29a9, 0x29aa, 0x29ab, 0x29ac, 0x29ad, 0x29ae, 0x29af,
+ 0x29b0, 0x29b1, 0x29b2, 0x29b3, 0x29b4, 0x29b5, 0x29b6, 0x29b7,
+ 0x29b8, 0x29b9, 0x29ba, 0x29bb, 0x29bc, 0x29bd, 0x29be, 0x29bf,
+ 0x29c0, 0x29c1, 0x29c2, 0x29c3, 0x29c4, 0x29c5, 0x29c6, 0x29c7,
+ 0x29c8, 0x29c9, 0x29ca, 0x29cb, 0x29cc, 0x29cd, 0x29ce, 0x29cf,
+ 0x29d0, 0x29d1, 0x29d2, 0x29d3, 0x29d4, 0x29d5, 0x29d6, 0x29d7,
+ 0x29d8, 0x29d9, 0x29da, 0x29db, 0x29dc, 0x29dd, 0x29de, 0x29df,
+ 0x29e0, 0x29e1, 0x29e2, 0x29e3, 0x29e4, 0x29e5, 0x29e6, 0x29e7,
+ 0x29e8, 0x29e9, 0x29ea, 0x29eb, 0x29ec, 0x29ed, 0x29ee, 0x29ef,
+ 0x29f0, 0x29f1, 0x29f2, 0x29f3, 0x29f4, 0x29f5, 0x29f6, 0x29f7,
+ 0x29f8, 0x29f9, 0x29fa, 0x29fb, 0x29fc, 0x29fd, 0x29fe, 0x29ff,
+ 0x2a00, 0x2a01, 0x2a02, 0x2a03, 0x2a04, 0x2a05, 0x2a06, 0x2a07,
+ 0x2a08, 0x2a09, 0x2a0a, 0x2a0b, 0x2a0c, 0x2a0d, 0x2a0e, 0x2a0f,
+ 0x2a10, 0x2a11, 0x2a12, 0x2a13, 0x2a14, 0x2a15, 0x2a16, 0x2a17,
+ 0x2a18, 0x2a19, 0x2a1a, 0x2a1b, 0x2a1c, 0x2a1d, 0x2a1e, 0x2a1f,
+ 0x2a20, 0x2a21, 0x2a22, 0x2a23, 0x2a24, 0x2a25, 0x2a26, 0x2a27,
+ 0x2a28, 0x2a29, 0x2a2a, 0x2a2b, 0x2a2c, 0x2a2d, 0x2a2e, 0x2a2f,
+ 0x2a30, 0x2a31, 0x2a32, 0x2a33, 0x2a34, 0x2a35, 0x2a36, 0x2a37,
+ 0x2a38, 0x2a39, 0x2a3a, 0x2a3b, 0x2a3c, 0x2a3d, 0x2a3e, 0x2a3f,
+ 0x2a40, 0x2a41, 0x2a42, 0x2a43, 0x2a44, 0x2a45, 0x2a46, 0x2a47,
+ 0x2a48, 0x2a49, 0x2a4a, 0x2a4b, 0x2a4c, 0x2a4d, 0x2a4e, 0x2a4f,
+ 0x2a50, 0x2a51, 0x2a52, 0x2a53, 0x2a54, 0x2a55, 0x2a56, 0x2a57,
+ 0x2a58, 0x2a59, 0x2a5a, 0x2a5b, 0x2a5c, 0x2a5d, 0x2a5e, 0x2a5f,
+ 0x2a60, 0x2a61, 0x2a62, 0x2a63, 0x2a64, 0x2a65, 0x2a66, 0x2a67,
+ 0x2a68, 0x2a69, 0x2a6a, 0x2a6b, 0x2a6c, 0x2a6d, 0x2a6e, 0x2a6f,
+ 0x2a70, 0x2a71, 0x2a72, 0x2a73, 0x2a74, 0x2a75, 0x2a76, 0x2a77,
+ 0x2a78, 0x2a79, 0x2a7a, 0x2a7b, 0x2a7c, 0x2a7d, 0x2a7e, 0x2a7f,
+ 0x2a80, 0x2a81, 0x2a82, 0x2a83, 0x2a84, 0x2a85, 0x2a86, 0x2a87,
+ 0x2a88, 0x2a89, 0x2a8a, 0x2a8b, 0x2a8c, 0x2a8d, 0x2a8e, 0x2a8f,
+ 0x2a90, 0x2a91, 0x2a92, 0x2a93, 0x2a94, 0x2a95, 0x2a96, 0x2a97,
+ 0x2a98, 0x2a99, 0x2a9a, 0x2a9b, 0x2a9c, 0x2a9d, 0x2a9e, 0x2a9f,
+ 0x2aa0, 0x2aa1, 0x2aa2, 0x2aa3, 0x2aa4, 0x2aa5, 0x2aa6, 0x2aa7,
+ 0x2aa8, 0x2aa9, 0x2aaa, 0x2aab, 0x2aac, 0x2aad, 0x2aae, 0x2aaf,
+ 0x2ab0, 0x2ab1, 0x2ab2, 0x2ab3, 0x2ab4, 0x2ab5, 0x2ab6, 0x2ab7,
+ 0x2ab8, 0x2ab9, 0x2aba, 0x2abb, 0x2abc, 0x2abd, 0x2abe, 0x2abf,
+ 0x2ac0, 0x2ac1, 0x2ac2, 0x2ac3, 0x2ac4, 0x2ac5, 0x2ac6, 0x2ac7,
+ 0x2ac8, 0x2ac9, 0x2aca, 0x2acb, 0x2acc, 0x2acd, 0x2ace, 0x2acf,
+ 0x2ad0, 0x2ad1, 0x2ad2, 0x2ad3, 0x2ad4, 0x2ad5, 0x2ad6, 0x2ad7,
+ 0x2ad8, 0x2ad9, 0x2ada, 0x2adb, 0x2adc, 0x2add, 0x2ade, 0x2adf,
+ 0x2ae0, 0x2ae1, 0x2ae2, 0x2ae3, 0x2ae4, 0x2ae5, 0x2ae6, 0x2ae7,
+ 0x2ae8, 0x2ae9, 0x2aea, 0x2aeb, 0x2aec, 0x2aed, 0x2aee, 0x2aef,
+ 0x2af0, 0x2af1, 0x2af2, 0x2af3, 0x2af4, 0x2af5, 0x2af6, 0x2af7,
+ 0x2af8, 0x2af9, 0x2afa, 0x2afb, 0x2afc, 0x2afd, 0x2afe, 0x2aff,
+ 0x2b00, 0x2b01, 0x2b02, 0x2b03, 0x2b04, 0x2b05, 0x2b06, 0x2b07,
+ 0x2b08, 0x2b09, 0x2b0a, 0x2b0b, 0x2b0c, 0x2b0d, 0x2b0e, 0x2b0f,
+ 0x2b10, 0x2b11, 0x2b12, 0x2b13, 0x2b14, 0x2b15, 0x2b16, 0x2b17,
+ 0x2b18, 0x2b19, 0x2b1a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2b20, 0x2b21, 0x2b22, 0x2b23, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2c30, 0x2c31, 0x2c32, 0x2c33, 0x2c34, 0x2c35, 0x2c36, 0x2c37,
+ 0x2c38, 0x2c39, 0x2c3a, 0x2c3b, 0x2c3c, 0x2c3d, 0x2c3e, 0x2c3f,
+ 0x2c40, 0x2c41, 0x2c42, 0x2c43, 0x2c44, 0x2c45, 0x2c46, 0x2c47,
+ 0x2c48, 0x2c49, 0x2c4a, 0x2c4b, 0x2c4c, 0x2c4d, 0x2c4e, 0x2c4f,
+ 0x2c50, 0x2c51, 0x2c52, 0x2c53, 0x2c54, 0x2c55, 0x2c56, 0x2c57,
+ 0x2c58, 0x2c59, 0x2c5a, 0x2c5b, 0x2c5c, 0x2c5d, 0x2c5e, 0x0000,
+ 0x2c30, 0x2c31, 0x2c32, 0x2c33, 0x2c34, 0x2c35, 0x2c36, 0x2c37,
+ 0x2c38, 0x2c39, 0x2c3a, 0x2c3b, 0x2c3c, 0x2c3d, 0x2c3e, 0x2c3f,
+ 0x2c40, 0x2c41, 0x2c42, 0x2c43, 0x2c44, 0x2c45, 0x2c46, 0x2c47,
+ 0x2c48, 0x2c49, 0x2c4a, 0x2c4b, 0x2c4c, 0x2c4d, 0x2c4e, 0x2c4f,
+ 0x2c50, 0x2c51, 0x2c52, 0x2c53, 0x2c54, 0x2c55, 0x2c56, 0x2c57,
+ 0x2c58, 0x2c59, 0x2c5a, 0x2c5b, 0x2c5c, 0x2c5d, 0x2c5e, 0x0000,
+ 0x2c61, 0x2c61, 0x026b, 0x1d7d, 0x027d, 0x2c65, 0x2c66, 0x2c68,
+ 0x2c68, 0x2c6a, 0x2c6a, 0x2c6c, 0x2c6c, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2c74, 0x2c76, 0x2c76, 0x2c77,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2c81, 0x2c81, 0x2c83, 0x2c83, 0x2c85, 0x2c85, 0x2c87, 0x2c87,
+ 0x2c89, 0x2c89, 0x2c8b, 0x2c8b, 0x2c8d, 0x2c8d, 0x2c8f, 0x2c8f,
+ 0x2c91, 0x2c91, 0x2c93, 0x2c93, 0x2c95, 0x2c95, 0x2c97, 0x2c97,
+ 0x2c99, 0x2c99, 0x2c9b, 0x2c9b, 0x2c9d, 0x2c9d, 0x2c9f, 0x2c9f,
+ 0x2ca1, 0x2ca1, 0x2ca3, 0x2ca3, 0x2ca5, 0x2ca5, 0x2ca7, 0x2ca7,
+ 0x2ca9, 0x2ca9, 0x2cab, 0x2cab, 0x2cad, 0x2cad, 0x2caf, 0x2caf,
+ 0x2cb1, 0x2cb1, 0x2cb3, 0x2cb3, 0x2cb5, 0x2cb5, 0x2cb7, 0x2cb7,
+ 0x2cb9, 0x2cb9, 0x2cbb, 0x2cbb, 0x2cbd, 0x2cbd, 0x2cbf, 0x2cbf,
+ 0x2cc1, 0x2cc1, 0x2cc3, 0x2cc3, 0x2cc5, 0x2cc5, 0x2cc7, 0x2cc7,
+ 0x2cc9, 0x2cc9, 0x2ccb, 0x2ccb, 0x2ccd, 0x2ccd, 0x2ccf, 0x2ccf,
+ 0x2cd1, 0x2cd1, 0x2cd3, 0x2cd3, 0x2cd5, 0x2cd5, 0x2cd7, 0x2cd7,
+ 0x2cd9, 0x2cd9, 0x2cdb, 0x2cdb, 0x2cdd, 0x2cdd, 0x2cdf, 0x2cdf,
+ 0x2ce1, 0x2ce1, 0x2ce3, 0x2ce3, 0x2ce4, 0x2ce5, 0x2ce6, 0x2ce7,
+ 0x2ce8, 0x2ce9, 0x2cea, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2cf9, 0x2cfa, 0x2cfb, 0x2cfc, 0x2cfd, 0x2cfe, 0x2cff,
+ 0x2d00, 0x2d01, 0x2d02, 0x2d03, 0x2d04, 0x2d05, 0x2d06, 0x2d07,
+ 0x2d08, 0x2d09, 0x2d0a, 0x2d0b, 0x2d0c, 0x2d0d, 0x2d0e, 0x2d0f,
+ 0x2d10, 0x2d11, 0x2d12, 0x2d13, 0x2d14, 0x2d15, 0x2d16, 0x2d17,
+ 0x2d18, 0x2d19, 0x2d1a, 0x2d1b, 0x2d1c, 0x2d1d, 0x2d1e, 0x2d1f,
+ 0x2d20, 0x2d21, 0x2d22, 0x2d23, 0x2d24, 0x2d25, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2d30, 0x2d31, 0x2d32, 0x2d33, 0x2d34, 0x2d35, 0x2d36, 0x2d37,
+ 0x2d38, 0x2d39, 0x2d3a, 0x2d3b, 0x2d3c, 0x2d3d, 0x2d3e, 0x2d3f,
+ 0x2d40, 0x2d41, 0x2d42, 0x2d43, 0x2d44, 0x2d45, 0x2d46, 0x2d47,
+ 0x2d48, 0x2d49, 0x2d4a, 0x2d4b, 0x2d4c, 0x2d4d, 0x2d4e, 0x2d4f,
+ 0x2d50, 0x2d51, 0x2d52, 0x2d53, 0x2d54, 0x2d55, 0x2d56, 0x2d57,
+ 0x2d58, 0x2d59, 0x2d5a, 0x2d5b, 0x2d5c, 0x2d5d, 0x2d5e, 0x2d5f,
+ 0x2d60, 0x2d61, 0x2d62, 0x2d63, 0x2d64, 0x2d65, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2d6f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2d80, 0x2d81, 0x2d82, 0x2d83, 0x2d84, 0x2d85, 0x2d86, 0x2d87,
+ 0x2d88, 0x2d89, 0x2d8a, 0x2d8b, 0x2d8c, 0x2d8d, 0x2d8e, 0x2d8f,
+ 0x2d90, 0x2d91, 0x2d92, 0x2d93, 0x2d94, 0x2d95, 0x2d96, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2da0, 0x2da1, 0x2da2, 0x2da3, 0x2da4, 0x2da5, 0x2da6, 0x0000,
+ 0x2da8, 0x2da9, 0x2daa, 0x2dab, 0x2dac, 0x2dad, 0x2dae, 0x0000,
+ 0x2db0, 0x2db1, 0x2db2, 0x2db3, 0x2db4, 0x2db5, 0x2db6, 0x0000,
+ 0x2db8, 0x2db9, 0x2dba, 0x2dbb, 0x2dbc, 0x2dbd, 0x2dbe, 0x0000,
+ 0x2dc0, 0x2dc1, 0x2dc2, 0x2dc3, 0x2dc4, 0x2dc5, 0x2dc6, 0x0000,
+ 0x2dc8, 0x2dc9, 0x2dca, 0x2dcb, 0x2dcc, 0x2dcd, 0x2dce, 0x0000,
+ 0x2dd0, 0x2dd1, 0x2dd2, 0x2dd3, 0x2dd4, 0x2dd5, 0x2dd6, 0x0000,
+ 0x2dd8, 0x2dd9, 0x2dda, 0x2ddb, 0x2ddc, 0x2ddd, 0x2dde, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2e00, 0x2e01, 0x2e02, 0x2e03, 0x2e04, 0x2e05, 0x2e06, 0x2e07,
+ 0x2e08, 0x2e09, 0x2e0a, 0x2e0b, 0x2e0c, 0x2e0d, 0x2e0e, 0x2e0f,
+ 0x2e10, 0x2e11, 0x2e12, 0x2e13, 0x2e14, 0x2e15, 0x2e16, 0x2e17,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2e1c, 0x2e1d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2e80, 0x2e81, 0x2e82, 0x2e83, 0x2e84, 0x2e85, 0x2e86, 0x2e87,
+ 0x2e88, 0x2e89, 0x2e8a, 0x2e8b, 0x2e8c, 0x2e8d, 0x2e8e, 0x2e8f,
+ 0x2e90, 0x2e91, 0x2e92, 0x2e93, 0x2e94, 0x2e95, 0x2e96, 0x2e97,
+ 0x2e98, 0x2e99, 0x0000, 0x2e9b, 0x2e9c, 0x2e9d, 0x2e9e, 0x2e9f,
+ 0x2ea0, 0x2ea1, 0x2ea2, 0x2ea3, 0x2ea4, 0x2ea5, 0x2ea6, 0x2ea7,
+ 0x2ea8, 0x2ea9, 0x2eaa, 0x2eab, 0x2eac, 0x2ead, 0x2eae, 0x2eaf,
+ 0x2eb0, 0x2eb1, 0x2eb2, 0x2eb3, 0x2eb4, 0x2eb5, 0x2eb6, 0x2eb7,
+ 0x2eb8, 0x2eb9, 0x2eba, 0x2ebb, 0x2ebc, 0x2ebd, 0x2ebe, 0x2ebf,
+ 0x2ec0, 0x2ec1, 0x2ec2, 0x2ec3, 0x2ec4, 0x2ec5, 0x2ec6, 0x2ec7,
+ 0x2ec8, 0x2ec9, 0x2eca, 0x2ecb, 0x2ecc, 0x2ecd, 0x2ece, 0x2ecf,
+ 0x2ed0, 0x2ed1, 0x2ed2, 0x2ed3, 0x2ed4, 0x2ed5, 0x2ed6, 0x2ed7,
+ 0x2ed8, 0x2ed9, 0x2eda, 0x2edb, 0x2edc, 0x2edd, 0x2ede, 0x2edf,
+ 0x2ee0, 0x2ee1, 0x2ee2, 0x2ee3, 0x2ee4, 0x2ee5, 0x2ee6, 0x2ee7,
+ 0x2ee8, 0x2ee9, 0x2eea, 0x2eeb, 0x2eec, 0x2eed, 0x2eee, 0x2eef,
+ 0x2ef0, 0x2ef1, 0x2ef2, 0x2ef3, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2f00, 0x2f01, 0x2f02, 0x2f03, 0x2f04, 0x2f05, 0x2f06, 0x2f07,
+ 0x2f08, 0x2f09, 0x2f0a, 0x2f0b, 0x2f0c, 0x2f0d, 0x2f0e, 0x2f0f,
+ 0x2f10, 0x2f11, 0x2f12, 0x2f13, 0x2f14, 0x2f15, 0x2f16, 0x2f17,
+ 0x2f18, 0x2f19, 0x2f1a, 0x2f1b, 0x2f1c, 0x2f1d, 0x2f1e, 0x2f1f,
+ 0x2f20, 0x2f21, 0x2f22, 0x2f23, 0x2f24, 0x2f25, 0x2f26, 0x2f27,
+ 0x2f28, 0x2f29, 0x2f2a, 0x2f2b, 0x2f2c, 0x2f2d, 0x2f2e, 0x2f2f,
+ 0x2f30, 0x2f31, 0x2f32, 0x2f33, 0x2f34, 0x2f35, 0x2f36, 0x2f37,
+ 0x2f38, 0x2f39, 0x2f3a, 0x2f3b, 0x2f3c, 0x2f3d, 0x2f3e, 0x2f3f,
+ 0x2f40, 0x2f41, 0x2f42, 0x2f43, 0x2f44, 0x2f45, 0x2f46, 0x2f47,
+ 0x2f48, 0x2f49, 0x2f4a, 0x2f4b, 0x2f4c, 0x2f4d, 0x2f4e, 0x2f4f,
+ 0x2f50, 0x2f51, 0x2f52, 0x2f53, 0x2f54, 0x2f55, 0x2f56, 0x2f57,
+ 0x2f58, 0x2f59, 0x2f5a, 0x2f5b, 0x2f5c, 0x2f5d, 0x2f5e, 0x2f5f,
+ 0x2f60, 0x2f61, 0x2f62, 0x2f63, 0x2f64, 0x2f65, 0x2f66, 0x2f67,
+ 0x2f68, 0x2f69, 0x2f6a, 0x2f6b, 0x2f6c, 0x2f6d, 0x2f6e, 0x2f6f,
+ 0x2f70, 0x2f71, 0x2f72, 0x2f73, 0x2f74, 0x2f75, 0x2f76, 0x2f77,
+ 0x2f78, 0x2f79, 0x2f7a, 0x2f7b, 0x2f7c, 0x2f7d, 0x2f7e, 0x2f7f,
+ 0x2f80, 0x2f81, 0x2f82, 0x2f83, 0x2f84, 0x2f85, 0x2f86, 0x2f87,
+ 0x2f88, 0x2f89, 0x2f8a, 0x2f8b, 0x2f8c, 0x2f8d, 0x2f8e, 0x2f8f,
+ 0x2f90, 0x2f91, 0x2f92, 0x2f93, 0x2f94, 0x2f95, 0x2f96, 0x2f97,
+ 0x2f98, 0x2f99, 0x2f9a, 0x2f9b, 0x2f9c, 0x2f9d, 0x2f9e, 0x2f9f,
+ 0x2fa0, 0x2fa1, 0x2fa2, 0x2fa3, 0x2fa4, 0x2fa5, 0x2fa6, 0x2fa7,
+ 0x2fa8, 0x2fa9, 0x2faa, 0x2fab, 0x2fac, 0x2fad, 0x2fae, 0x2faf,
+ 0x2fb0, 0x2fb1, 0x2fb2, 0x2fb3, 0x2fb4, 0x2fb5, 0x2fb6, 0x2fb7,
+ 0x2fb8, 0x2fb9, 0x2fba, 0x2fbb, 0x2fbc, 0x2fbd, 0x2fbe, 0x2fbf,
+ 0x2fc0, 0x2fc1, 0x2fc2, 0x2fc3, 0x2fc4, 0x2fc5, 0x2fc6, 0x2fc7,
+ 0x2fc8, 0x2fc9, 0x2fca, 0x2fcb, 0x2fcc, 0x2fcd, 0x2fce, 0x2fcf,
+ 0x2fd0, 0x2fd1, 0x2fd2, 0x2fd3, 0x2fd4, 0x2fd5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+int unic_tolower (int c) {
+ if (c<0x3000) {
+ return ____tolower[(c)+1];
+ } else {
+ if (c>=0xff21&&c<=0xff3a) {
+ return c+ 32;
+ } else if ((c>=0x3000 && c<=0x303f) || (c>=0x3041 && c<=0x3096) ||
+ (c>=0x3099 && c<=0x30ff) || (c>=0x3105 && c<=0x312c) ||
+ (c>=0x3131 && c<=0x318e) || (c>=0x3190 && c<=0x31b7) ||
+ (c>=0x31c0 && c<=0x31cf) || (c>=0x31f0 && c<=0x321e) ||
+ (c>=0x3220 && c<=0x3243) || (c>=0x3250 && c<=0x32fe) ||
+ (c>=0x3300 && c<=0x4db5) || (c>=0x4dc0 && c<=0x9fbb) ||
+ (c>=0xa000 && c<=0xa48c) || (c>=0xa490 && c<=0xa4c6) ||
+ (c>=0xa700 && c<=0xa71a) || (c>=0xa720 && c<=0xa721) ||
+ (c>=0xa800 && c<=0xa82b) || (c>=0xa840 && c<=0xa877) ||
+ (c>=0xac00 && c<=0xd7a3) || (c>=0xd800 && c<=0xfa2d) ||
+ (c>=0xfa30 && c<=0xfa6a) || (c>=0xfa70 && c<=0xfad9) ||
+ (c>=0xfb00 && c<=0xfb06) || (c>=0xfb13 && c<=0xfb17) ||
+ (c>=0xfb1d && c<=0xfb36) || (c>=0xfb38 && c<=0xfb3c) ||
+ c==0xfb3e ||
+ (c>=0xfb40 && c<=0xfb41) || (c>=0xfb43 && c<=0xfb44) ||
+ (c>=0xfb46 && c<=0xfbb1) || (c>=0xfbd3 && c<=0xfd3f) ||
+ (c>=0xfd50 && c<=0xfd8f) || (c>=0xfd92 && c<=0xfdc7) ||
+ (c>=0xfdf0 && c<=0xfdfd) || (c>=0xfe00 && c<=0xfe19) ||
+ (c>=0xfe20 && c<=0xfe23) || (c>=0xfe30 && c<=0xfe52) ||
+ (c>=0xfe54 && c<=0xfe66) || (c>=0xfe68 && c<=0xfe6b) ||
+ (c>=0xfe70 && c<=0xfe74) || (c>=0xfe76 && c<=0xfefc) ||
+ c==0xfeff ||
+ (c>=0xff01 && c<=0xff20) || (c>=0xff3b && c<=0xffbe) ||
+ (c>=0xffc2 && c<=0xffc7) || (c>=0xffca && c<=0xffcf) ||
+ (c>=0xffd2 && c<=0xffd7) || (c>=0xffda && c<=0xffdc) ||
+ (c>=0xffe0 && c<=0xffe6) || (c>=0xffe8 && c<=0xffee) ||
+ (c>=0xfff9 && c<=0xfffd)){
+ return c;
+ } else {
+ return 0;
+ }
+ }
+}
+
+/* some error and process reporting stuff */
+
+char **gww_errors = NULL;
+int gww_error_count = 0;
+
+void _gwwv_post_error(const char *fmt, va_list args) {
+ char *buf;
+ buf = malloc(1024);
+ if (buf==NULL) {
+ perror("memory allocation failed");
+ exit(EXIT_FAILURE);
+ }
+ vsnprintf(buf,1024,fmt,args);
+ gww_errors = realloc(gww_errors, (gww_error_count+2)*sizeof(char *));
+ if (gww_errors==NULL) {
+ perror("memory allocation failed");
+ exit(EXIT_FAILURE);
+ }
+ gww_errors[gww_error_count ] = buf ;
+ gww_error_count ++;
+ gww_errors[gww_error_count ] = NULL;
+
+}
+
+void gwwv_post_error(const char *fmt, ...) {
+ va_list args;
+ va_start (args, fmt);
+ _gwwv_post_error(fmt,args);
+ va_end (args);
+}
+
+
+void gwwv_errors_free (void) {
+ int i;
+ if (gww_error_count>0) {
+ for (i=0;i<gww_error_count;i++) {
+ free(gww_errors[i]);
+ }
+ free(gww_errors);
+ gww_error_count = 0;
+ gww_errors = NULL;
+ }
+}
+
+void gwwv_post_notice (char *fmt, ...) { }
+void gwwv_ask (char *a) { }
+void gwwv_progress_change_line1 (char *a) { }
+void gwwv_progress_change_line2 (char *b) { }
+void gwwv_progress_next (void){ }
+void gwwv_progress_start_indicator (void) { }
+void gwwv_progress_end_indicator (void) { }
+void gwwv_progress_enable_stop (void) { }
+void gwwv_progress_resume_timer (void) { }
+void gwwv_progress_pause_timer (void) { }
+void gwwv_progress_next_stage (void) { }
+void gwwv_progress_change_stages (void) { }
+void gwwv_progress_change_total (void) { }
+void gwwv_progress_increment (void) { }
+
+void GWidgetError8(char *a, char *b) { }
+
+void GProgressChangeLine1_8 (char *a) { }
+void GProgressChangeLine2_8 (char *b) { }
+void GProgressChangeTotal (void) { }
+void GProgressNext (void){ }
+void GProgressStartIndicator (void) { }
+void GProgressEndIndicator (void) { }
+void GProgressEnableStop (void) { }
+void GProgressResumeTimer (void) { }
+void GProgressPauseTimer (void) { }
+void GProgressNextStage (void) { }
+void GProgressChangeStages (void) { }
+void GProgressIncrement (void) { }
+
+/* from plugins.c */
+
+void LoadPluginDir(void *a) { }
+
+/* from scripting.c */
+
+int no_windowing_ui = 1;
+int running_script = 1;
+int use_utf8_in_script = 1;
+
+void ScriptError( void *c, const char *msg ) { }
+
+void ScriptErrorString( void *c, const char *msg, const char *name) { }
+
+void ScriptErrorF( void *c, const char *format, ... ) { }
+
+void CheckIsScript(int argc, char *argv[]) { }
+
+void ExecuteScriptFile(FontView *fv, char *filename) { }
+
+void ScriptDlg(FontView *fv) { }
+
+struct dictentry {
+ char *name;
+ Val val;
+};
+
+struct dictionary {
+ struct dictentry *entries;
+ int cnt, max;
+};
+
+
+typedef struct array {
+ int argc;
+ Val *vals;
+} Array;
+
+static void arrayfree(Array *a) {
+ int i;
+
+ for ( i=0; i<a->argc; ++i ) {
+ if ( a->vals[i].type==v_str )
+ free(a->vals[i].u.sval);
+ else if ( a->vals[i].type==v_arr )
+ arrayfree(a->vals[i].u.aval);
+ }
+ free(a->vals);
+ free(a);
+}
+
+
+void DictionaryFree(struct dictionary *dica) {
+ int i;
+
+ if ( dica==NULL )
+return;
+
+ for ( i=0; i<dica->cnt; ++i ) {
+ free(dica->entries[i].name );
+ if ( dica->entries[i].val.type == v_str )
+ free( dica->entries[i].val.u.sval );
+ if ( dica->entries[i].val.type == v_arr )
+ arrayfree( dica->entries[i].val.u.aval );
+ }
+ free( dica->entries );
+}
+
+
+char **GetFontNames(char *filename) {
+ FILE *foo;
+ char **ret = NULL;
+
+ if ( GFileIsDir(filename)) {
+#if 0
+ char *temp = galloc(strlen(filename)+strlen("/glyphs/contents.plist")+1);
+ strcpy(temp,filename);
+ strcat(temp,"/glyphs/contents.plist");
+ if ( GFileExists(temp))
+ ret = NamesReadUFO(filename);
+ else
+ {
+ strcpy(temp,filename);
+ strcat(temp,"/font.props");
+ if ( GFileExists(temp))
+ ret = NamesReadSFD(temp);
+ /* The fonts.prop file will look just like an sfd file as far */
+ /* as fontnames are concerned, we don't need a separate routine*/
+ }
+ free(temp);
+#endif
+ } else {
+ foo = fopen(filename,"rb");
+ if ( foo!=NULL ) {
+ /* Try to guess the file type from the first few characters... */
+ int ch1 = getc(foo);
+ int ch2 = getc(foo);
+ int ch3 = getc(foo);
+ int ch4 = getc(foo);
+ int ch5, ch6;
+ fseek(foo, 98, SEEK_SET);
+ ch5 = getc(foo);
+ ch6 = getc(foo);
+ fclose(foo);
+ if (( ch1==0 && ch2==1 && ch3==0 && ch4==0 ) ||
+ (ch1=='O' && ch2=='T' && ch3=='T' && ch4=='O') ||
+ (ch1=='t' && ch2=='r' && ch3=='u' && ch4=='e') ||
+ (ch1=='t' && ch2=='t' && ch3=='c' && ch4=='f') ) {
+ ret = NamesReadTTF(filename);
+ } else if (( ch1=='%' && ch2=='!' ) ||
+ ( ch1==0x80 && ch2=='\01' ) ) { /* PFB header */
+ ret = NamesReadPostscript(filename);
+#if 0
+ } else if ( ch1=='<' && ch2=='?' && (ch3=='x'||ch3=='X') && (ch4=='m'||ch4=='M') ) {
+ ret = NamesReadSVG(filename);
+ } else if ( ch1=='S' && ch2=='p' && ch3=='l' && ch4=='i' ) {
+ ret = NamesReadSFD(filename);
+#endif
+ } else if ( ch1==1 && ch2==0 && ch3==4 ) {
+ ret = NamesReadCFF(filename);
+ } else /* Too hard to figure out a valid mark for a mac resource file */
+ ret = NamesReadMacBinary(filename);
+ }
+ }
+return( ret );
+}
+
+
+/* from svg.c */
+
+SplineChar *SCHasSubs(SplineChar *sc, uint32 tag) {
+ PST *pst;
+
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->type==pst_substitution &&
+ FeatureTagInFeatureScriptList(tag,pst->subtable->lookup->features) )
+return( SFGetChar(sc->parent,-1,pst->u.subs.variant));
+ }
+return( NULL );
+}
+
+int _ExportSVG(FILE *svg,SplineChar *sc) {
+ return 0;
+}
+
+int WriteSVGFont(char *fontname,SplineFont *sf,enum fontformat format,int flags,
+ EncMap *map) {
+ return 1;
+}
+
+int HasSVG(void) { return 0; }
+
+
+SplineFont *SFReadSVG(char *filename, int flags) {
+return( NULL );
+}
+
+SplineSet *SplinePointListInterpretSVG(char *filename,char *memory, int memlen,
+ int em_size,int ascent,int is_stroked) {
+return( NULL );
+}
+
+/* from ufo.c */
+
+int HasUFO(void) {
+return( false );
+}
+
+SplineFont *SFReadUFO(char *filename, int flags) {
+return( NULL );
+}
+
+SplineSet *SplinePointListInterpretGlif(char *filename,char *memory, int memlen,
+ int em_size,int ascent,int is_stroked) {
+return( NULL );
+}
+
+int WriteUFOFont(char *basedir,SplineFont *sf,enum fontformat ff,int flags,
+ EncMap *map) {
+ return 1;
+}
+
+int _ExportGlif(FILE *glif,SplineChar *sc) {
+return 0;
+}
+
+/* from autosave.c, but much shortened */
+
+char *getPfaEditDir(char *buffer) {
+ return( NULL );
+}
+
+void DoAutoSaves (void ) {}
+
+/* from dumppfa.c, but much shortened */
+
+const char *GetAuthor(void) {
+ static char author[200] = { '\0' };
+ const char *ret = NULL, *pt;
+
+ if ((pt=getenv("USER"))!=NULL ) {
+ strncpy(author,pt,sizeof(author));
+ author[sizeof(author)-1] = '\0';
+ ret = author;
+ }
+ return ret;
+}
+
+double BlueScaleFigure(struct psdict *private,real bluevalues[], real otherblues[]) {
+ double max_diff=0, p1, p2;
+ char *pt, *end;
+ int i;
+
+ if ( PSDictHasEntry(private,"BlueScale")!=NULL )
+return( -1 );
+
+ pt = PSDictHasEntry(private,"BlueValues");
+ if ( pt!=NULL ) {
+ while ( *pt==' ' || *pt=='[' ) ++pt;
+ forever {
+ p1 = strtod(pt,&end);
+ if ( end==pt )
+ break;
+ pt = end;
+ p2 = strtod(pt,&end);
+ if ( end==pt )
+ break;
+ if ( p2-p1 >max_diff ) max_diff = p2-p1;
+ pt = end;
+ }
+ } else {
+ for ( i=0; i<14 && (bluevalues[i]!=0 || bluevalues[i+1])!=0; i+=2 ) {
+ if ( bluevalues[i+1] - bluevalues[i]>=max_diff )
+ max_diff = bluevalues[i+1] - bluevalues[i];
+ }
+ }
+
+ pt = PSDictHasEntry(private,"OtherBlues");
+ if ( pt!=NULL ) {
+ while ( *pt==' ' || *pt=='[' ) ++pt;
+ forever {
+ p1 = strtod(pt,&end);
+ if ( end==pt )
+ break;
+ pt = end;
+ p2 = strtod(pt,&end);
+ if ( end==pt )
+ break;
+ if ( p2-p1 >max_diff ) max_diff = p2-p1;
+ pt = end;
+ }
+ } else {
+ for ( i=0; i<10 && (otherblues[i]!=0 || otherblues[i+1]!=0); i+=2 ) {
+ if ( otherblues[i+1] - otherblues[i]>=max_diff )
+ max_diff = otherblues[i+1] - otherblues[i];
+ }
+ }
+ if ( max_diff<=0 )
+return( -1 );
+ if ( 1/max_diff > .039625 )
+return( -1 );
+
+return( .99/max_diff );
+}
+
+/* from dumpbdf.c */
+
+int IsntBDFChar(BDFChar *bdfc) {
+ if ( bdfc==NULL )
+return( true );
+
+return( !SCWorthOutputting(bdfc->sc));
+}
+
+/* form bitmapdlg.c (stubbed) */
+
+void SFOrderBitmapList(SplineFont *sf) {
+}
+
+/* from metafont.c, whole */
+
+void SCCopyFgToBg(SplineChar *sc, int show) {
+ SplinePointList *fore, *end;
+
+ SCPreserveBackground(sc);
+ fore = SplinePointListCopy(sc->layers[ly_fore].splines);
+ if ( fore!=NULL ) {
+ SplinePointListsFree(sc->layers[ly_back].splines);
+ sc->layers[ly_back].splines = NULL;
+ for ( end = fore; end->next!=NULL; end = end->next );
+ end->next = sc->layers[ly_back].splines;
+ sc->layers[ly_back].splines = fore;
+ if ( show )
+ SCCharChangedUpdate(sc);
+ }
+}
+
+
+/* from tottf.c, whole */
+#if 0
+
+void putshort(FILE *file,int sval) {
+ putc((sval>>8)&0xff,file);
+ putc(sval&0xff,file);
+}
+
+void putlong(FILE *file,int val) {
+ putc((val>>24)&0xff,file);
+ putc((val>>16)&0xff,file);
+ putc((val>>8)&0xff,file);
+ putc(val&0xff,file);
+}
+
+char *utf8_verify_copy(const char *str) {
+ /* When given a postscript string it SHOULD be in ASCII. But it will often*/
+ /* contain a copyright symbol (sometimes in latin1, sometimes in macroman)*/
+ /* unfortunately both encodings use 0xa9 for copyright so we can't distinguish */
+ /* guess that it's latin1 (or that copyright is the only odd char which */
+ /* means a latin1 conversion will work for macs too). */
+
+ if ( str==NULL )
+return( NULL );
+
+ if ( utf8_valid(str))
+return( copy(str)); /* Either in ASCII (good) or appears to be utf8*/
+return( latin1_2_utf8_copy(str));
+}
+
+const char *ttfstandardnames[258] = {
+".notdef",
+".null",
+"nonmarkingreturn",
+"space",
+"exclam",
+"quotedbl",
+"numbersign",
+"dollar",
+"percent",
+"ampersand",
+"quotesingle",
+"parenleft",
+"parenright",
+"asterisk",
+"plus",
+"comma",
+"hyphen",
+"period",
+"slash",
+"zero",
+"one",
+"two",
+"three",
+"four",
+"five",
+"six",
+"seven",
+"eight",
+"nine",
+"colon",
+"semicolon",
+"less",
+"equal",
+"greater",
+"question",
+"at",
+"A",
+"B",
+"C",
+"D",
+"E",
+"F",
+"G",
+"H",
+"I",
+"J",
+"K",
+"L",
+"M",
+"N",
+"O",
+"P",
+"Q",
+"R",
+"S",
+"T",
+"U",
+"V",
+"W",
+"X",
+"Y",
+"Z",
+"bracketleft",
+"backslash",
+"bracketright",
+"asciicircum",
+"underscore",
+"grave",
+"a",
+"b",
+"c",
+"d",
+"e",
+"f",
+"g",
+"h",
+"i",
+"j",
+"k",
+"l",
+"m",
+"n",
+"o",
+"p",
+"q",
+"r",
+"s",
+"t",
+"u",
+"v",
+"w",
+"x",
+"y",
+"z",
+"braceleft",
+"bar",
+"braceright",
+"asciitilde",
+"Adieresis",
+"Aring",
+"Ccedilla",
+"Eacute",
+"Ntilde",
+"Odieresis",
+"Udieresis",
+"aacute",
+"agrave",
+"acircumflex",
+"adieresis",
+"atilde",
+"aring",
+"ccedilla",
+"eacute",
+"egrave",
+"ecircumflex",
+"edieresis",
+"iacute",
+"igrave",
+"icircumflex",
+"idieresis",
+"ntilde",
+"oacute",
+"ograve",
+"ocircumflex",
+"odieresis",
+"otilde",
+"uacute",
+"ugrave",
+"ucircumflex",
+"udieresis",
+"dagger",
+"degree",
+"cent",
+"sterling",
+"section",
+"bullet",
+"paragraph",
+"germandbls",
+"registered",
+"copyright",
+"trademark",
+"acute",
+"dieresis",
+"notequal",
+"AE",
+"Oslash",
+"infinity",
+"plusminus",
+"lessequal",
+"greaterequal",
+"yen",
+"mu",
+"partialdiff",
+"summation",
+"product",
+"pi",
+"integral",
+"ordfeminine",
+"ordmasculine",
+"Omega",
+"ae",
+"oslash",
+"questiondown",
+"exclamdown",
+"logicalnot",
+"radical",
+"florin",
+"approxequal",
+"Delta",
+"guillemotleft",
+"guillemotright",
+"ellipsis",
+"nonbreakingspace",
+"Agrave",
+"Atilde",
+"Otilde",
+"OE",
+"oe",
+"endash",
+"emdash",
+"quotedblleft",
+"quotedblright",
+"quoteleft",
+"quoteright",
+"divide",
+"lozenge",
+"ydieresis",
+"Ydieresis",
+"fraction",
+"currency",
+"guilsinglleft",
+"guilsinglright",
+"fi",
+"fl",
+"daggerdbl",
+"periodcentered",
+"quotesinglbase",
+"quotedblbase",
+"perthousand",
+"Acircumflex",
+"Ecircumflex",
+"Aacute",
+"Edieresis",
+"Egrave",
+"Iacute",
+"Icircumflex",
+"Idieresis",
+"Igrave",
+"Oacute",
+"Ocircumflex",
+"apple",
+"Ograve",
+"Uacute",
+"Ucircumflex",
+"Ugrave",
+"dotlessi",
+"circumflex",
+"tilde",
+"macron",
+"breve",
+"dotaccent",
+"ring",
+"cedilla",
+"hungarumlaut",
+"ogonek",
+"caron",
+"Lslash",
+"lslash",
+"Scaron",
+"scaron",
+"Zcaron",
+"zcaron",
+"brokenbar",
+"Eth",
+"eth",
+"Yacute",
+"yacute",
+"Thorn",
+"thorn",
+"minus",
+"multiply",
+"onesuperior",
+"twosuperior",
+"threesuperior",
+"onehalf",
+"onequarter",
+"threequarters",
+"franc",
+"Gbreve",
+"gbreve",
+"Idotaccent",
+"Scedilla",
+"scedilla",
+"Cacute",
+"cacute",
+"Ccaron",
+"ccaron",
+"dcroat"
+};
+
+int ttfcopyfile(FILE *ttf, FILE *other, int pos, char *tab_name) {
+ int ch;
+ int ret = 1;
+
+ if ( ferror(ttf) || ferror(other)) {
+ IError("Disk error of some nature. Perhaps no space on device?\nGenerated font will be unusable" );
+ } else if ( pos!=ftell(ttf)) {
+ IError("File Offset wrong for ttf table (%s), %d expected %d", tab_name, ftell(ttf), pos );
+ }
+ rewind(other);
+ while (( ch = getc(other))!=EOF )
+ putc(ch,ttf);
+ if ( ferror(other)) ret = 0;
+ if ( fclose(other)) ret = 0;
+return( ret );
+}
+
+
+
+static void OS2WeightCheck(struct pfminfo *pfminfo,char *weight) {
+ if ( weight==NULL ) {
+ /* default it */
+ } else if ( strstrmatch(weight,"medi")!=NULL ) {
+ pfminfo->weight = 500;
+ pfminfo->panose[2] = 6;
+ } else if ( strstrmatch(weight,"demi")!=NULL ||
+ strstrmatch(weight,"halb")!=NULL ||
+ (strstrmatch(weight,"semi")!=NULL &&
+ strstrmatch(weight,"bold")!=NULL) ) {
+ pfminfo->weight = 600;
+ pfminfo->panose[2] = 7;
+ } else if ( strstrmatch(weight,"bold")!=NULL ||
+ strstrmatch(weight,"fett")!=NULL ||
+ strstrmatch(weight,"gras")!=NULL ) {
+ pfminfo->weight = 700;
+ pfminfo->panose[2] = 8;
+ } else if ( strstrmatch(weight,"heavy")!=NULL ) {
+ pfminfo->weight = 800;
+ pfminfo->panose[2] = 9;
+ } else if ( strstrmatch(weight,"black")!=NULL ) {
+ pfminfo->weight = 900;
+ pfminfo->panose[2] = 10;
+ } else if ( strstrmatch(weight,"nord")!=NULL ) {
+ pfminfo->weight = 950;
+ pfminfo->panose[2] = 11;
+ } else if ( strstrmatch(weight,"thin")!=NULL ) {
+ pfminfo->weight = 100;
+ pfminfo->panose[2] = 2;
+ } else if ( strstrmatch(weight,"extra")!=NULL ||
+ strstrmatch(weight,"light")!=NULL ) {
+ pfminfo->weight = 200;
+ pfminfo->panose[2] = 3;
+ } else if ( strstrmatch(weight,"light")!=NULL ) {
+ pfminfo->weight = 300;
+ pfminfo->panose[2] = 4;
+ }
+}
+
+void SFDefaultOS2Simple(struct pfminfo *pfminfo,SplineFont *sf) {
+ pfminfo->pfmfamily = 0x11;
+ pfminfo->panose[0] = 2;
+ pfminfo->weight = 400;
+ pfminfo->panose[2] = 5;
+ pfminfo->width = 5;
+ pfminfo->panose[3] = 3;
+ pfminfo->winascent_add = pfminfo->windescent_add = true;
+ pfminfo->hheadascent_add = pfminfo->hheaddescent_add = true;
+ pfminfo->typoascent_add = pfminfo->typodescent_add = true;
+ pfminfo->os2_winascent = pfminfo->os2_windescent = 0;
+
+ if ( sf->subfonts!=NULL ) sf = sf->subfonts[0];
+ pfminfo->linegap = pfminfo->vlinegap = pfminfo->os2_typolinegap =
+ rint(.09*(sf->ascent+sf->descent));
+}
+
+void SFDefaultOS2SubSuper(struct pfminfo *pfminfo,int emsize,double italic_angle) {
+ double s = sin(italic_angle*3.1415926535897932/180.0);
+ pfminfo->os2_supysize = pfminfo->os2_subysize = .7*emsize;
+ pfminfo->os2_supxsize = pfminfo->os2_subxsize = .65*emsize;
+ pfminfo->os2_subyoff = .14*emsize;
+ pfminfo->os2_supyoff = .48*emsize;
+ pfminfo->os2_supxoff = s*pfminfo->os2_supyoff;
+ pfminfo->os2_subxoff = -s*pfminfo->os2_subyoff;
+ pfminfo->os2_strikeysize = 102*emsize/2048;
+ pfminfo->os2_strikeypos = 530*emsize/2048;
+}
+
+void SFDefaultOS2Info(struct pfminfo *pfminfo,SplineFont *sf,char *fontname) {
+ int samewid= -1;
+ char *weight = sf->cidmaster==NULL ? sf->weight : sf->cidmaster->weight;
+
+ if ( sf->pfminfo.pfmset ) {
+ if ( pfminfo!=&sf->pfminfo )
+ *pfminfo = sf->pfminfo;
+ if ( !pfminfo->panose_set ) {
+ struct pfminfo info;
+ memset(&info,0,sizeof(info));
+ sf->pfminfo.pfmset = false;
+ SFDefaultOS2Info(&info,sf,fontname);
+ sf->pfminfo.pfmset = true;
+ memcpy(pfminfo->panose,info.panose,sizeof(info.panose));
+ }
+ } else {
+ struct pfminfo hold;
+ if ( pfminfo->hheadset || pfminfo->vheadset )
+ hold = *pfminfo;
+ else
+ hold.hheadset = hold.vheadset = false;
+ memset(pfminfo,'\0',sizeof(*pfminfo));
+ SFDefaultOS2Simple(pfminfo,sf);
+ samewid = CIDOneWidth(sf);
+
+ pfminfo->pfmfamily = 0x10;
+ if ( samewid>0 ) {
+ pfminfo->pfmfamily = 0x30;
+ /* pfminfo->panose[3] = 9; */ /* This is done later */
+ } else if ( strstrmatch(fontname,"sans")!=NULL )
+ pfminfo->pfmfamily = 0x20;
+ else if ( strstrmatch(fontname,"script")!=NULL ) {
+ pfminfo->pfmfamily = 0x40;
+ pfminfo->panose[0] = 3;
+ }
+ if ( samewid==-1 )
+ pfminfo->pfmfamily |= 0x1; /* Else it assumes monospace */
+
+/* urw uses 4 character abreviations */
+ if ( weight!=NULL )
+ OS2WeightCheck(pfminfo,weight);
+ OS2WeightCheck(pfminfo,fontname);
+
+ if ( strstrmatch(fontname,"ultra")!=NULL &&
+ strstrmatch(fontname,"condensed")!=NULL ) {
+ pfminfo->width = 1;
+ pfminfo->panose[3] = 8;
+ } else if ( strstrmatch(fontname,"extra")!=NULL &&
+ strstrmatch(fontname,"condensed")!=NULL ) {
+ pfminfo->width = 2;
+ pfminfo->panose[3] = 8;
+ } else if ( strstrmatch(fontname,"semi")!=NULL &&
+ strstrmatch(fontname,"condensed")!=NULL ) {
+ pfminfo->width = 4;
+ pfminfo->panose[3] = 6;
+ } else if ( strstrmatch(fontname,"condensed")!=NULL ||
+ strstrmatch(fontname,"narrow")!=NULL ) {
+ pfminfo->width = 3;
+ pfminfo->panose[3] = 6;
+ } else if ( strstrmatch(fontname,"ultra")!=NULL &&
+ strstrmatch(fontname,"expanded")!=NULL ) {
+ pfminfo->width = 9;
+ pfminfo->panose[3] = 7;
+ } else if ( strstrmatch(fontname,"extra")!=NULL &&
+ strstrmatch(fontname,"expanded")!=NULL ) {
+ pfminfo->width = 8;
+ pfminfo->panose[3] = 7;
+ } else if ( strstrmatch(fontname,"semi")!=NULL &&
+ strstrmatch(fontname,"expanded")!=NULL ) {
+ pfminfo->width = 6;
+ pfminfo->panose[3] = 5;
+ } else if ( strstrmatch(fontname,"expanded")!=NULL ) {
+ pfminfo->width = 7;
+ pfminfo->panose[3] = 5;
+ }
+ if ( samewid>0 )
+ pfminfo->panose[3] = 9;
+ if ( hold.hheadset ) {
+ pfminfo->hheadset = true;
+ pfminfo->hheadascent_add = hold.hheadascent_add;
+ pfminfo->hheaddescent_add = hold.hheaddescent_add;
+ pfminfo->hhead_ascent = hold.hhead_ascent;
+ pfminfo->hhead_descent = hold.hhead_descent;
+ pfminfo->linegap = hold.linegap;
+ }
+ if ( hold.vheadset ) {
+ pfminfo->vheadset = true;
+ pfminfo->vlinegap = hold.vlinegap;
+ }
+ }
+ if ( !pfminfo->subsuper_set )
+ SFDefaultOS2SubSuper(pfminfo,sf->ascent+sf->descent,sf->italicangle);
+}
+
+void OS2FigureCodePages(SplineFont *sf, uint32 CodePage[2]) {
+ int i;
+ uint32 latin1[8];
+ int has_ascii, has_latin1;
+
+ memset(latin1,0,sizeof(latin1));
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ if ( sf->glyphs[i]->unicodeenc<256 && sf->glyphs[i]->unicodeenc>=0 )
+ latin1[(sf->glyphs[i]->unicodeenc>>5)] |= 1<<(sf->glyphs[i]->unicodeenc&31);
+ }
+
+ has_ascii = latin1[1]==0xffffffff && latin1[2]==0xffffffff &&
+ (latin1[3]&0x7fffffff)==0x7fffffff; /* DEL is not a char */
+ has_latin1 = has_ascii && (latin1[5]&~1&~(1<<0xd))== (~1&~(1<<0xd)) && /* Ignore nobreak space, softhyphen */
+ latin1[6]==0xffffffff && latin1[7] == 0xffffffff;
+ CodePage[0] = CodePage[1] = 0;
+ if ( has_ascii ) CodePage[1] |= 1U<<31; /* US (Ascii I assume) */
+ if ( has_latin1 ) CodePage[0] |= 1U<<30; /* WE/latin1 */
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ if ( sf->glyphs[i]->unicodeenc==0xde && has_ascii )
+ CodePage[0] |= 1<<0; /* (ANSI) Latin1 */
+ else if ( sf->glyphs[i]->unicodeenc==0x13d && has_ascii ) {
+ CodePage[0] |= 1<<1; /* latin2 */
+ CodePage[1] |= 1<<26; /* latin2 */
+ } else if ( sf->glyphs[i]->unicodeenc==0x411 ) {
+ CodePage[0] |= 1<<2; /* cyrillic */
+ CodePage[1] |= 1<<17; /* MS DOS Russian */
+ CodePage[1] |= 1<<25; /* IBM Cyrillic */
+ } else if ( sf->glyphs[i]->unicodeenc==0x386 ) {
+ CodePage[0] |= 1<<3; /* greek */
+ CodePage[1] |= 1<<16; /* IBM Greek */
+ CodePage[1] |= 1<<28; /* Greek, former 437 G */
+ } else if ( sf->glyphs[i]->unicodeenc==0x130 && has_ascii ) {
+ CodePage[0] |= 1<<4; /* turkish */
+ CodePage[1] |= 1<<24; /* IBM turkish */
+ } else if ( sf->glyphs[i]->unicodeenc==0x5d0 ) {
+ CodePage[0] |= 1<<5; /* hebrew */
+ CodePage[1] |= 1<<21; /* hebrew */
+ } else if ( sf->glyphs[i]->unicodeenc==0x631 ) {
+ CodePage[0] |= 1<<6; /* arabic */
+ CodePage[1] |= 1<<19; /* arabic */
+ CodePage[1] |= 1<<29; /* arabic; ASMO 708 */
+ } else if ( sf->glyphs[i]->unicodeenc==0x157 && has_ascii ) {
+ CodePage[0] |= 1<<7; /* baltic */
+ CodePage[1] |= 1<<27; /* baltic */
+ } else if ( sf->glyphs[i]->unicodeenc==0x20AB && has_ascii ) {
+ CodePage[0] |= 1<<8; /* vietnamese */
+ } else if ( sf->glyphs[i]->unicodeenc==0xe45 )
+ CodePage[0] |= 1<<16; /* thai */
+ else if ( sf->glyphs[i]->unicodeenc==0x30a8 )
+ CodePage[0] |= 1<<17; /* japanese */
+ else if ( sf->glyphs[i]->unicodeenc==0x3105 )
+ CodePage[0] |= 1<<18; /* simplified chinese */
+ else if ( sf->glyphs[i]->unicodeenc==0x3131 )
+ CodePage[0] |= 1<<19; /* korean wansung */
+ else if ( sf->glyphs[i]->unicodeenc==0x592E )
+ CodePage[0] |= 1<<20; /* traditional chinese */
+ else if ( sf->glyphs[i]->unicodeenc==0xacf4 )
+ CodePage[0] |= 1<<21; /* korean Johab */
+ else if ( sf->glyphs[i]->unicodeenc==0x2030 && has_ascii )
+ CodePage[0] |= 1U<<29; /* mac roman */
+ else if ( sf->glyphs[i]->unicodeenc==0x2665 && has_ascii )
+ CodePage[0] |= 1U<<30; /* OEM */
+#if 0 /* the symbol bit doesn't mean it contains the glyphs in symbol */
+ /* rather that one is using a symbol encoding. Or that there are */
+ /* glyphs with unicode encoding between 0xf000 and 0xf0ff, in which */
+ /* case those guys should be given a symbol encoding */
+ /* There's a bug in the way otf fonts handle this (but not ttf) and */
+ /* they only seem to list the symbol glyphs */
+ else if ( sf->glyphs[i]->unicodeenc==0x21d4 )
+ CodePage[0] |= 1U<<31; /* symbol */
+#else
+ /* This doesn't work well either. In ttf fonts the bit is ignored */
+ /* in otf fonts the bit means "ignore all other bits" */
+ else if ( sf->glyphs[i]->unicodeenc>=0xf000 && sf->glyphs[i]->unicodeenc<=0xf0ff )
+ CodePage[0] |= 1U<<31; /* symbol */
+#endif
+ else if ( sf->glyphs[i]->unicodeenc==0xc3 && has_ascii )
+ CodePage[1] |= 1<<18; /* MS-DOS Nordic */
+ else if ( sf->glyphs[i]->unicodeenc==0xe9 && has_ascii )
+ CodePage[1] |= 1<<20; /* MS-DOS Canadian French */
+ else if ( sf->glyphs[i]->unicodeenc==0xf5 && has_ascii )
+ CodePage[1] |= 1<<23; /* MS-DOS Portuguese */
+ else if ( sf->glyphs[i]->unicodeenc==0xfe && has_ascii )
+ CodePage[1] |= 1<<22; /* MS-DOS Icelandic */
+ }
+}
+
+#define _On_Curve 1
+#define _X_Short 2
+#define _Y_Short 4
+#define _Repeat 8
+#define _X_Same 0x10
+#define _Y_Same 0x20
+
+int SSAddPoints(SplineSet *ss,int ptcnt,BasePoint *bp, char *flags) {
+ SplinePoint *sp, *first, *nextsp;
+ int startcnt = ptcnt;
+
+ if ( ss->first->prev!=NULL &&
+ ss->first->prev->from->nextcpindex==startcnt ) {
+ if ( flags!=NULL ) flags[ptcnt] = 0;
+ bp[ptcnt].x = rint(ss->first->prevcp.x);
+ bp[ptcnt++].y = rint(ss->first->prevcp.y);
+ } else if ( ss->first->ttfindex!=ptcnt && ss->first->ttfindex!=0xfffe )
+ IError("Unexpected point count in SSAddPoints" );
+
+ first = NULL;
+ for ( sp=ss->first; sp!=first ; ) {
+ if ( sp->ttfindex!=0xffff ) {
+ if ( flags!=NULL ) flags[ptcnt] = _On_Curve;
+ bp[ptcnt].x = rint(sp->me.x);
+ bp[ptcnt].y = rint(sp->me.y);
+ sp->ttfindex = ptcnt++;
+ } else if ( !SPInterpolate( sp ) ) {
+ /* If an on curve point is midway between two off curve points*/
+ /* it may be omitted and will be interpolated on read in */
+ if ( flags!=NULL ) flags[ptcnt] = _On_Curve;
+ bp[ptcnt].x = rint(sp->me.x);
+ bp[ptcnt].y = rint(sp->me.y);
+ sp->ttfindex = ptcnt++;
+ }
+ nextsp = sp->next!=NULL ? sp->next->to : NULL;
+ if ( sp->nextcpindex == startcnt )
+ /* This control point is actually our first point, not our last */
+ break;
+ if ( (sp->nextcpindex !=0xffff && sp->nextcpindex!=0xfffe ) ||
+ !sp->nonextcp ) {
+ if ( flags!=NULL ) flags[ptcnt] = 0;
+ bp[ptcnt].x = rint(sp->nextcp.x);
+ bp[ptcnt++].y = rint(sp->nextcp.y);
+ }
+ if ( nextsp==NULL )
+ break;
+ if ( first==NULL ) first = sp;
+ sp = nextsp;
+ }
+return( ptcnt );
+}
+
+
+#ifdef _HAS_LONGLONG
+void cvt_unix_to_1904( long long time, int32 result[2]) {
+ uint32 date1970[4], tm[4];
+ uint32 year[2];
+ int i;
+
+ tm[0] = time &0xffff;
+ tm[1] = (time>>16)&0xffff;
+ tm[2] = (time>>32)&0xffff;
+ tm[3] = (time>>48)&0xffff;
+#else
+void cvt_unix_to_1904( long time, int32 result[2]) {
+ int32 date1970[4], tm[4];
+ uint32 year[2];
+ int i;
+
+ tm[0] = time &0xffff;
+ tm[1] = (time>>16)&0xffff;
+ tm[2] = 0;
+ tm[3] = 0;
+#endif
+ memset(date1970,0,sizeof(date1970));
+ year[0] = (60*60*24*365L)&0xffff;
+ year[1] = (60*60*24*365L)>>16;
+ for ( i=1904; i<1970; ++i ) {
+ date1970[0] += year[0];
+ date1970[1] += year[1];
+ if ( (i&3)==0 && (i%100!=0 || i%400==0))
+ date1970[0] += 24*60*60L; /* Leap year */
+ date1970[1] += (date1970[0]>>16);
+ date1970[0] &= 0xffff;
+ date1970[2] += date1970[1]>>16;
+ date1970[1] &= 0xffff;
+ date1970[3] += date1970[2]>>16;
+ date1970[2] &= 0xffff;
+ }
+
+ for ( i=0; i<3; ++i ) {
+ tm[i] += date1970[i];
+ tm[i+1] += tm[i]>>16;
+ tm[i] &= 0xffff;
+ }
+ tm[3] -= date1970[3];
+
+ result[0] = (tm[1]<<16) | tm[0];
+ result[1] = (tm[3]<<16) | tm[2];
+}
+
+#endif /* for tottf.c */
+
+/* from fvimportbdf.c */
+
+void SFCheckPSBitmap(SplineFont *sf) {
+ /* full, was empty */
+}
+
+ void SFDefaultAscent(SplineFont *sf) {
+ /* stubbed */
+}
+
+
+/* from bdfinfo.c */
+
+int BdfPropHasInt(BDFFont *font,const char *key, int def ) {
+ int i;
+
+ for ( i=0; i<font->prop_cnt; ++i ) if ( strcmp(font->props[i].name,key)==0 ) {
+ switch ( font->props[i].type&~prt_property ) {
+ case prt_int: case prt_uint:
+return( font->props[i].u.val );
+ break;
+ }
+ }
+return( def );
+}
+
+/* from tottfaat.c */
+
+int scriptsHaveDefault(struct scriptlanglist *sl) {
+ int i;
+
+ for ( ; sl!=NULL; sl=sl->next ) {
+ for ( i=0; i<sl->lang_cnt; ++i ) {
+ if ( (i<MAX_LANG && sl->langs[i]==DEFAULT_LANG) ||
+ (i>=MAX_LANG && sl->morelangs[i-MAX_LANG]==DEFAULT_LANG)) {
+return( true );
+ }
+ }
+ }
+return( false );
+}
+
+uint32 MacFeatureToOTTag(int featureType,int featureSetting) {
+ int i;
+ struct macsettingname *msn = user_macfeat_otftag ? user_macfeat_otftag : macfeat_otftag;
+
+ for ( i=0; msn[i].otf_tag!=0; ++i )
+ if ( msn[i].mac_feature_type == featureType &&
+ msn[i].mac_feature_setting == featureSetting )
+return( msn[i].otf_tag );
+
+return( 0 );
+}
+
+int OTTagToMacFeature(uint32 tag, int *featureType,int *featureSetting) {
+ int i;
+ struct macsettingname *msn = user_macfeat_otftag ? user_macfeat_otftag : macfeat_otftag;
+
+ for ( i=0; msn[i].otf_tag!=0; ++i )
+ if ( msn[i].otf_tag == tag ) {
+ *featureType = msn[i].mac_feature_type;
+ *featureSetting = msn[i].mac_feature_setting;
+return( true );
+ }
+
+ *featureType = 0;
+ *featureSetting = 0;
+return( false );
+}
+
+static void DumpKernClass(FILE *file, uint16 *class,int cnt,int add,int mul) {
+ int i, first=-1, last=-1;
+
+ for ( i=0; i<cnt; ++i ) {
+ if ( class[i] ) last = i;
+ if ( class[i] && first==-1 ) first = i;
+ }
+ putshort(file,first);
+ putshort(file,last-first+1);
+ for ( i=first; i<=last; ++i )
+ putshort(file,class[i]*mul+add);
+}
+
+struct kerncounts {
+ int cnt;
+ int vcnt;
+ int mh, mv;
+ int kccnt;
+ int vkccnt;
+ int ksm;
+ int hsubs;
+ int *hbreaks;
+ int vsubs;
+ int *vbreaks;
+};
+
+static int CountKerns(struct alltabs *at, SplineFont *sf, struct kerncounts *kcnt) {
+ int i, cnt, vcnt, j, kccnt=0, vkccnt=0, ksm=0, mh, mv;
+ KernPair *kp;
+ KernClass *kc;
+ ASM *sm;
+
+ cnt = mh = vcnt = mv = 0;
+ for ( i=0; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
+ j = 0;
+ for ( kp = sf->glyphs[at->gi.bygid[i]]->kerns; kp!=NULL; kp=kp->next )
+ if ( kp->off!=0 && LookupHasDefault(kp->subtable->lookup ))
+ ++cnt, ++j;
+ if ( j>mh ) mh=j;
+ j=0;
+ for ( kp = sf->glyphs[at->gi.bygid[i]]->vkerns; kp!=NULL; kp=kp->next )
+ if ( kp->off!=0 && LookupHasDefault(kp->subtable->lookup ))
+ ++vcnt, ++j;
+ if ( j>mv ) mv=j;
+ }
+ kcnt->cnt = cnt;
+ kcnt->vcnt = vcnt;
+ kcnt->mh = mh;
+ kcnt->mv = mv;
+ kcnt->hbreaks = kcnt->vbreaks = NULL;
+ if ( cnt>=10000 ) {
+ /* the sub-table size is 6*cnt+14 or so and needs to be less 65535 */
+ /* so break it up into little bits */
+ /* We might not need this when applemode is set because the subtable */
+ /* length is a long. BUT... there's a damn binsearch header with */
+ /* shorts in it still */
+ int b=0;
+ kcnt->hbreaks = galloc((at->gi.gcnt+1)*sizeof(int));
+ cnt = 0;
+ for ( i=0; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
+ j = 0;
+ for ( kp = sf->glyphs[at->gi.bygid[i]]->kerns; kp!=NULL; kp=kp->next )
+ if ( kp->off!=0 && LookupHasDefault(kp->subtable->lookup ))
+ ++j;
+ if ( (cnt+j)*6>64000L && cnt!=0 ) {
+ kcnt->hbreaks[b++] = cnt;
+ cnt = 0;
+ }
+ cnt += j;
+ }
+ kcnt->hbreaks[b++] = cnt;
+ kcnt->hsubs = b;
+ } else if ( cnt!=0 )
+ kcnt->hsubs = 1;
+ else
+ kcnt->hsubs = 0;
+ if ( vcnt>=10000 ) {
+ int b=0;
+ kcnt->vbreaks = galloc((at->gi.gcnt+1)*sizeof(int));
+ vcnt = 0;
+ for ( i=0; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
+ j = 0;
+ for ( kp = sf->glyphs[at->gi.bygid[i]]->vkerns; kp!=NULL; kp=kp->next )
+ if ( kp->off!=0 && LookupHasDefault(kp->subtable->lookup))
+ ++j;
+ if ( (vcnt+j)*6>64000L && vcnt!=0 ) {
+ kcnt->vbreaks[b++] = vcnt;
+ vcnt = 0;
+ }
+ vcnt += j;
+ }
+ kcnt->vbreaks[b++] = vcnt;
+ kcnt->vsubs = b;
+ } else if ( vcnt!=0 )
+ kcnt->vsubs = 1;
+ else
+ kcnt->vsubs = 0;
+
+ if ( at->applemode ) { /* if we aren't outputting Apple's extensions to kerning (by classes, and by state machine) then don't check for those extensions */
+ for ( kc=sf->kerns; kc!=NULL; kc = kc->next ) if ( LookupHasDefault(kc->subtable->lookup) )
+ ++kccnt;
+ for ( kc=sf->vkerns; kc!=NULL; kc = kc->next ) if ( LookupHasDefault(kc->subtable->lookup) )
+ ++vkccnt;
+ for ( sm=sf->sm; sm!=NULL; sm=sm->next )
+ if ( sm->type == asm_kern )
+ ++ksm;
+ }
+ kcnt->kccnt = kccnt;
+ kcnt->vkccnt = vkccnt;
+ kcnt->ksm = ksm;
+return( kcnt->hsubs + kcnt->vsubs + kccnt + vkccnt + ksm );
+}
+
+static void ttf_dumpsfkerns(struct alltabs *at, SplineFont *sf, int tupleIndex, int version) {
+ struct kerncounts kcnt;
+ int i, j, k, m, c, gid, tot, km;
+ KernPair *kp;
+ KernClass *kc;
+ /*ASM *sm;*/
+ uint16 *glnum, *offsets;
+ int isv;
+ int tupleMask = tupleIndex==-1 ? 0 : 0x2000;
+ int b, bmax;
+ int *breaks;
+
+ if ( CountKerns(at,sf,&kcnt)==0 )
+return;
+
+ if ( tupleIndex==-1 ) tupleIndex = 0;
+
+ for ( isv=0; isv<2; ++isv ) {
+ c = isv ? kcnt.vcnt : kcnt.cnt;
+ bmax = isv ? kcnt.vsubs : kcnt.hsubs;
+ breaks = isv ? kcnt.vbreaks : kcnt.hbreaks;
+ if ( c!=0 ) {
+ km = isv ? kcnt.mv : kcnt.mh;
+ glnum = galloc(km*sizeof(uint16));
+ offsets = galloc(km*sizeof(uint16));
+ gid = 0;
+ for ( b=0; b<bmax; ++b ) {
+ c = bmax==1 ? c : breaks[b];
+ if ( version==0 ) {
+ putshort(at->kern,0); /* subtable version */
+ putshort(at->kern,(7+3*c)*sizeof(uint16)); /* subtable length */
+ putshort(at->kern,!isv); /* coverage, flags=hor/vert&format=0 */
+ } else {
+ putlong(at->kern,(8+3*c)*sizeof(uint16)); /* subtable length */
+ /* Apple's new format has a completely different coverage format */
+ putshort(at->kern,(isv?0x8000:0)| /* format 0, horizontal/vertical flags (coverage) */
+ tupleMask);
+ putshort(at->kern,tupleIndex);
+ }
+ putshort(at->kern,c);
+ for ( i=1,j=0; i<=c; i<<=1, ++j );
+ i>>=1; --j;
+ putshort(at->kern,i*6); /* binary search headers */
+ putshort(at->kern,j);
+ putshort(at->kern,6*(c-i));
+
+ for ( tot = 0; gid<at->gi.gcnt && tot<c; ++gid ) if ( at->gi.bygid[gid]!=-1 ) {
+ SplineChar *sc = sf->glyphs[at->gi.bygid[gid]];
+ m = 0;
+ for ( kp = isv ? sc->vkerns : sc->kerns; kp!=NULL; kp=kp->next ) {
+ if ( kp->off!=0 && LookupHasDefault(kp->subtable->lookup)) {
+ /* order the pairs */
+ for ( j=0; j<m; ++j )
+ if ( kp->sc->ttf_glyph<glnum[j] )
+ break;
+ for ( k=m; k>j; --k ) {
+ glnum[k] = glnum[k-1];
+ offsets[k] = offsets[k-1];
+ }
+ glnum[j] = kp->sc->ttf_glyph;
+ offsets[j] = kp->off;
+ ++m;
+ }
+ }
+ for ( j=0; j<m; ++j ) {
+ putshort(at->kern,gid);
+ putshort(at->kern,glnum[j]);
+ putshort(at->kern,offsets[j]);
+ }
+ tot += m;
+ }
+ }
+ free(offsets);
+ free(glnum);
+ }
+ }
+ free(kcnt.hbreaks); free(kcnt.vbreaks);
+
+ if ( at->applemode ) for ( isv=0; isv<2; ++isv ) {
+ for ( kc=isv ? sf->vkerns : sf->kerns; kc!=NULL; kc=kc->next ) if ( LookupHasDefault(kc->subtable->lookup) ) {
+ /* If we are here, we must be using version 1 */
+ uint32 len_pos = ftell(at->kern), pos;
+ uint16 *class1, *class2;
+ int first_cnt = kc->first_cnt;
+
+ /* OpenType fonts can actually have a set of glyphs in class[0] of*/
+ /* the first class. This happens when there are glyphs in the */
+ /* coverage table which are not in any of the classes. Otherwise */
+ /* class 0 is sort of useless in opentype */
+ if ( kc->firsts[0]!=NULL )
+ ++first_cnt;
+
+ putlong(at->kern,0); /* subtable length */
+ putshort(at->kern,(isv?0x8002:2)| /* format 2, horizontal/vertical flags (coverage) */
+ tupleMask);
+ putshort(at->kern,tupleIndex);
+
+ putshort(at->kern,sizeof(uint16)*kc->second_cnt);
+ putshort(at->kern,0); /* left classes */
+ putshort(at->kern,0); /* right classes */
+ putshort(at->kern,16); /* Offset to array, next byte */
+
+ if ( kc->firsts[0]!=NULL ) {
+ /* Create a dummy class to correspond to the mac's class 0 */
+ /* all entries will be 0 */
+ for ( i=0 ; i<kc->second_cnt; ++i )
+ putshort(at->kern,0);
+ }
+ for ( i=0; i<kc->first_cnt*kc->second_cnt; ++i )
+ putshort(at->kern,kc->offsets[i]);
+
+ pos = ftell(at->kern);
+ fseek(at->kern,len_pos+10,SEEK_SET);
+ putshort(at->kern,pos-len_pos);
+ fseek(at->kern,pos,SEEK_SET);
+ class1 = ClassesFromNames(sf,kc->firsts,kc->first_cnt,at->maxp.numGlyphs,NULL,true);
+ DumpKernClass(at->kern,class1,at->maxp.numGlyphs,16,sizeof(uint16)*kc->second_cnt);
+ free(class1);
+
+ pos = ftell(at->kern);
+ fseek(at->kern,len_pos+12,SEEK_SET);
+ putshort(at->kern,pos-len_pos);
+ fseek(at->kern,pos,SEEK_SET);
+ class2 = ClassesFromNames(sf,kc->seconds,kc->second_cnt,at->maxp.numGlyphs,NULL,true);
+ DumpKernClass(at->kern,class2,at->maxp.numGlyphs,0,sizeof(uint16));
+ free(class2);
+
+ pos = ftell(at->kern);
+ fseek(at->kern,len_pos,SEEK_SET);
+ putlong(at->kern,pos-len_pos);
+ fseek(at->kern,pos,SEEK_SET);
+ }
+ }
+
+ if ( at->applemode ) if ( kcnt.ksm!=0 ) {
+#ifndef LUA_FF_LIB
+ for ( sm=sf->sm; sm!=NULL; sm=sm->next ) if ( sm->type == asm_kern ) {
+ uint32 len_pos = ftell(at->kern), pos;
+
+ putlong(at->kern,0); /* subtable length */
+ putshort(at->kern,((sm->flags&0x8000)?0x8001:1)| /* format 1, horizontal/vertical flags (coverage) */
+ tupleMask);
+ putshort(at->kern,tupleIndex);
+ morx_dumpASM(at->kern,sm,at,sf);
+
+ pos = ftell(at->kern);
+ fseek(at->kern,len_pos,SEEK_SET);
+ putlong(at->kern,pos-len_pos);
+ fseek(at->kern,pos,SEEK_SET);
+ }
+#endif
+ }
+}
+
+void ttf_dumpkerns(struct alltabs *at, SplineFont *sf) {
+ int i, mmcnt=0, sum;
+ int version;
+ MMSet *mm = at->dovariations ? sf->mm : NULL;
+ struct kerncounts kcnt;
+ int must_use_old_style = 0;
+
+ if ( !at->applemode && (!at->opentypemode || (at->gi.flags&ttf_flag_oldkern)) ) {
+ must_use_old_style = true;
+ SFKernClassTempDecompose(sf,false);
+ mm = NULL;
+ } else {
+ if ( mm!=NULL ) {
+ for ( i=0; i<mm->instance_count; ++i ) {
+ mmcnt += CountKerns(at,mm->instances[i],&kcnt);
+ free(kcnt.hbreaks); free(kcnt.vbreaks);
+ }
+ sf = mm->normal;
+ }
+ }
+
+ sum = CountKerns(at,sf,&kcnt);
+ free(kcnt.hbreaks); free(kcnt.vbreaks);
+ if ( sum==0 && mmcnt==0 ) {
+ if ( must_use_old_style )
+ SFKernCleanup(sf,false);
+return;
+ }
+
+ /* Old kerning format (version 0) uses 16 bit quantities */
+ /* Apple's new format (version 0x00010000) uses 32 bit quantities */
+ at->kern = tmpfile();
+ if ( must_use_old_style ||
+ ( kcnt.kccnt==0 && kcnt.vkccnt==0 && kcnt.ksm==0 && mmcnt==0 )) {
+ /* MS does not support format 1,2,3 kern sub-tables so if we have them */
+ /* we might as well admit that this table is for apple only and use */
+ /* the new format apple recommends. Otherwise, use the old format */
+ /* If we might need to store tuple data, use the new format */
+ putshort(at->kern,0); /* version */
+ putshort(at->kern,sum); /* number of subtables */
+ version = 0;
+ } else {
+ putlong(at->kern,0x00010000); /* version */
+ putlong(at->kern,sum+mmcnt); /* number of subtables */
+ version = 1;
+ }
+
+ ttf_dumpsfkerns(at, sf, -1, version);
+ if ( mm!=NULL ) {
+ for ( i=0; i<mm->instance_count; ++i )
+ ttf_dumpsfkerns(at, mm->instances[i], i, version);
+ }
+ if ( must_use_old_style )
+ SFKernCleanup(sf,false);
+
+ at->kernlen = ftell(at->kern);
+ if ( at->kernlen&2 )
+ putshort(at->kern,0); /* pad it */
+}
+
+
+int LookupHasDefault(OTLookup *otl) {
+ FeatureScriptLangList *feats;
+
+ if ( otl->def_lang_checked )
+return( otl->def_lang_found );
+
+ otl->def_lang_checked = true;
+ for ( feats=otl->features; feats!=NULL; feats = feats->next ) {
+ if ( scriptsHaveDefault(feats->scripts) ) {
+ otl->def_lang_found = true;
+return( true );
+ }
+ }
+ otl->def_lang_found = false;
+return( false );
+}
+
+
+/* from sfd1.c, full */
+
+enum uni_interp interp_from_encoding(Encoding *enc,enum uni_interp interp) {
+
+ if ( enc==NULL )
+return( interp );
+
+ if ( enc->is_japanese )
+ interp = ui_japanese;
+ else if ( enc->is_korean )
+ interp = ui_korean;
+ else if ( enc->is_tradchinese )
+ interp = ui_trad_chinese;
+ else if ( enc->is_simplechinese )
+ interp = ui_simp_chinese;
+return( interp );
+}
+
+/* from bitmapview.c */
+
+void BCCharChangedUpdate(BDFChar *bc) {
+ /* full */
+ bc->changed = true;
+}
+
+BDFChar *BDFMakeGID(BDFFont *bdf,int gid) {
+ SplineFont *sf=bdf->sf;
+ SplineChar *sc;
+ BDFChar *bc;
+ int i;
+
+ if ( gid==-1 )
+return( NULL );
+
+ if ( sf->cidmaster!=NULL || sf->subfonts!=NULL ) {
+ int j = SFHasCID(sf,gid);
+ if ( sf->cidmaster ) sf = sf->cidmaster;
+ if ( j==-1 ) {
+ for ( j=0; j<sf->subfontcnt; ++j )
+ if ( gid<sf->subfonts[j]->glyphcnt )
+ break;
+ if ( j==sf->subfontcnt )
+return( NULL );
+ }
+ sf = sf->subfonts[j];
+ }
+ if ( (sc = sf->glyphs[gid])==NULL )
+return( NULL );
+
+ if ( gid>=bdf->glyphcnt ) {
+ if ( gid>=bdf->glyphmax )
+ bdf->glyphs = grealloc(bdf->glyphs,(bdf->glyphmax=sf->glyphmax)*sizeof(BDFChar *));
+ for ( i=bdf->glyphcnt; i<=gid; ++i )
+ bdf->glyphs[i] = NULL;
+ bdf->glyphcnt = sf->glyphcnt;
+ }
+ if ( (bc = bdf->glyphs[gid])==NULL ) {
+#ifndef LUA_FF_LIB
+ if ( bc!=NULL )
+ /* Done */;
+ else if ( bdf->clut==NULL )
+ bc = SplineCharRasterize(sc,bdf->pixelsize);
+ else
+ bc = SplineCharAntiAlias(sc,bdf->pixelsize,BDFDepth(bdf));
+#endif
+ bdf->glyphs[gid] = bc;
+ bc->orig_pos = gid;
+ BCCharChangedUpdate(bc);
+ }
+return( bc );
+}
+
+BDFChar *BDFMakeChar(BDFFont *bdf,EncMap *map,int enc) {
+ SplineFont *sf=bdf->sf;
+
+ if ( enc==-1 )
+return( NULL );
+
+ if ( sf->cidmaster!=NULL ) {
+ int j = SFHasCID(sf,enc);
+ sf = sf->cidmaster;
+ if ( j==-1 ) {
+ for ( j=0; j<sf->subfontcnt; ++j )
+ if ( enc<sf->subfonts[j]->glyphcnt )
+ break;
+ if ( j==sf->subfontcnt )
+return( NULL );
+ }
+ sf = sf->subfonts[j];
+ }
+ SFMakeChar(sf,map,enc);
+return( BDFMakeGID(bdf,map->map[enc]));
+}
+
+/* splinesaveafm.c */
+
+int SCDrawsSomething(SplineChar *sc) {
+ int layer,l;
+ RefChar *ref;
+
+ if ( sc==NULL )
+return( false );
+ for ( layer = ly_fore; layer<sc->layer_cnt; ++layer ) {
+ if ( sc->layers[layer].splines!=NULL || sc->layers[layer].images!=NULL )
+return( true );
+ for ( ref = sc->layers[layer].refs; ref!=NULL; ref=ref->next )
+ for ( l=0; l<ref->layer_cnt; ++l )
+ if ( ref->layers[l].splines!=NULL )
+return( true );
+ }
+return( false );
+}
+
+int SCWorthOutputting(SplineChar *sc) {
+return( sc!=NULL &&
+ ( SCDrawsSomething(sc) || sc->widthset || sc->anchor!=NULL ||
+#if HANYANG
+ sc->compositionunit ||
+#endif
+ sc->dependents!=NULL /*||
+ sc->width!=sc->parent->ascent+sc->parent->descent*/ ) );
+}
+
+void SFKernCleanup(SplineFont *sf,int isv) {
+ int i;
+ KernPair *kp, *p, *n;
+ OTLookup *otl, *otlp, *otln;
+
+ if ( (!isv && sf->kerns==NULL) || (isv && sf->vkerns==NULL) ) /* can't have gotten messed up */
+return;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
+ for ( kp = isv ? sf->glyphs[i]->vkerns : sf->glyphs[i]->kerns, p=NULL; kp!=NULL; kp = n ) {
+ n = kp->next;
+ if ( kp->kcid!=0 ) {
+ if ( p!=NULL )
+ p->next = n;
+ else if ( isv )
+ sf->glyphs[i]->vkerns = n;
+ else
+ sf->glyphs[i]->kerns = n;
+ chunkfree(kp,sizeof(*kp));
+ } else
+ p = kp;
+ }
+ }
+ for ( otl=sf->gpos_lookups, otlp = NULL; otl!=NULL; otl = otln ) {
+ otln = otl->next;
+ if ( otl->temporary_kern ) {
+ if ( otlp!=NULL )
+ otlp->next = otln;
+ else
+ sf->gpos_lookups = otln;
+ OTLookupFree(otl);
+ } else
+ otlp = otl;
+ }
+}
+
+
+static void KCSfree(SplineChar ***scs,int cnt) {
+ int i;
+ for ( i=1; i<cnt; ++i )
+ free( scs[i]);
+ free(scs);
+}
+
+static SplineChar ***KernClassToSC(SplineFont *sf, char **classnames, int cnt) {
+ SplineChar ***scs, *sc;
+ int i,j;
+ char *pt, *end, ch;
+
+ scs = galloc(cnt*sizeof(SplineChar **));
+ for ( i=1; i<cnt; ++i ) {
+ for ( pt=classnames[i]-1, j=0; pt!=NULL; pt=strchr(pt+1,' ') )
+ ++j;
+ scs[i] = galloc((j+1)*sizeof(SplineChar *));
+ for ( pt=classnames[i], j=0; *pt!='\0'; pt=end+1 ) {
+ end = strchr(pt,' ');
+ if ( end==NULL )
+ end = pt+strlen(pt);
+ ch = *end;
+ *end = '\0';
+ sc = SFGetChar(sf,-1,pt);
+ if ( sc!=NULL )
+ scs[i][j++] = sc;
+ if ( ch=='\0' )
+ break;
+ *end = ch;
+ }
+ scs[i][j] = NULL;
+ }
+return( scs );
+}
+
+static void AddTempKP(SplineChar *first,SplineChar *second,
+ int16 offset, struct lookup_subtable *sub,uint16 kcid,int isv) {
+ KernPair *kp;
+
+ for ( kp=first->kerns; kp!=NULL; kp=kp->next )
+ if ( kp->sc == second )
+ break;
+ if ( kp==NULL ) {
+ kp = chunkalloc(sizeof(KernPair));
+ kp->sc = second;
+ kp->off = offset;
+ kp->subtable = sub;
+ kp->kcid = kcid;
+ if ( isv ) {
+ kp->next = first->vkerns;
+ first->vkerns = kp;
+ } else {
+ kp->next = first->kerns;
+ first->kerns = kp;
+ }
+ }
+}
+
+
+void SFKernClassTempDecompose(SplineFont *sf,int isv) {
+ KernClass *kc, *head= isv ? sf->vkerns : sf->kerns;
+ SplineChar ***first, ***last;
+ int i, j, k, l;
+ OTLookup *otl;
+
+ for ( kc = head, i=0; kc!=NULL; kc = kc->next )
+ kc->kcid = ++i;
+ for ( kc = head; kc!=NULL; kc = kc->next ) {
+
+ otl = chunkalloc(sizeof(OTLookup));
+ otl->next = sf->gpos_lookups;
+ sf->gpos_lookups = otl;
+ otl->lookup_type = gpos_pair;
+ otl->lookup_flags = kc->subtable->lookup->lookup_flags;
+ otl->features = FeatureListCopy(kc->subtable->lookup->features);
+ otl->lookup_name = copy(_("<Temporary kerning>"));
+ otl->temporary_kern = otl->store_in_afm = true;
+ otl->subtables = chunkalloc(sizeof(struct lookup_subtable));
+ otl->subtables->lookup = otl;
+ otl->subtables->per_glyph_pst_or_kern = true;
+ otl->subtables->subtable_name = copy(_("<Temporary kerning>"));
+
+ first = KernClassToSC(sf,kc->firsts,kc->first_cnt);
+ last = KernClassToSC(sf,kc->seconds,kc->second_cnt);
+ for ( i=1; i<kc->first_cnt; ++i ) for ( j=1; j<kc->second_cnt; ++j ) {
+ if ( kc->offsets[i*kc->second_cnt+j]!=0 ) {
+ for ( k=0; first[i][k]!=NULL; ++k )
+ for ( l=0; last[j][l]!=NULL; ++l )
+ AddTempKP(first[i][k],last[j][l],
+ kc->offsets[i*kc->second_cnt+j],
+ otl->subtables,kc->kcid,isv);
+ }
+ }
+ KCSfree(first,kc->first_cnt);
+ KCSfree(last,kc->second_cnt);
+ }
+}
+
+int SFFindNotdef(SplineFont *sf, int fixed) {
+ int notdefpos = -1, i, width=-1;
+ /* If all glyphs have the same known width set fixed to it */
+ /* If glyphs are proportional set fixed to -1 */
+ /* If we don't know yet, set fixed to -2 */
+
+ if ( fixed==-2 ) { /* Unknown */
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sf->glyphs[i]) ) {
+ if ( strcmp(sf->glyphs[i]->name,".notdef")==0 ) {
+ if ( notdefpos==-1 ) notdefpos = i;
+ } else if ( width==-1 )
+ width = sf->glyphs[i]->width;
+ else if ( width!=sf->glyphs[i]->width )
+ width = -2;
+ }
+ if ( width>=0 && sf->glyphcnt>2 && notdefpos>=0) {
+ if ( width!=sf->glyphs[notdefpos]->width ) {
+ notdefpos = -1;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sf->glyphs[i]) ) {
+ if ( strcmp(sf->glyphs[i]->name,".notdef")==0 &&
+ sf->glyphs[i]->width == width ) {
+ notdefpos = i;
+ break;
+ }
+ }
+ }
+ }
+ } else if ( fixed>=0 ) { /* Known, fixed width */
+
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sf->glyphs[i]) ) {
+ if ( strcmp(sf->glyphs[i]->name,".notdef")==0 &&
+ sf->glyphs[i]->width == fixed )
+return( i );
+ }
+ } else { /* Known, variable width */
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sf->glyphs[i]) ) {
+ if ( strcmp(sf->glyphs[i]->name,".notdef")==0 )
+return( i );
+ }
+ }
+
+return( notdefpos );
+}
+
+
+#ifdef LUA_FF_LIB
+/* no need for iconv here, since PS is 8-bit legacy */
+#define Isspace(a) ((a)==' '|| ((a) >= '\t' && (a) <= '\r'))
+#define Isdigit(a) ((a)>='0' && (a)<='9')
+#define Isalpha(a) (((a)>='a' && (a)<='z') || ((a)>='A' && (a)<='Z'))
+#define Isupper(a) ((a)>='A' && (a)<='Z')
+#define Isalnum(a) (Isalpha(a)||Isdigit(a))
+#define Ishexdigit(a) (((a)>='0' && (a)<='9')||((a)>='a' && (a)<='f')||((a)>='A' && (a)<='F'))
+#else
+#define Isspace isspace
+#define Isdigit isdigit
+#define Isalpha isalpha
+#define Isupper isupper
+#define Isalnum isalnum
+#define Ishexdigit ishexdigit
+#endif
+
+
+
+
+int CheckAfmOfPostscript(SplineFont *sf,char *psname, EncMap *map) {
+ char *new, *pt;
+ int ret;
+ int wasuc=false;
+
+ new = galloc(strlen(psname)+6);
+ strcpy(new,psname);
+ pt = strrchr(new,'.');
+ if ( pt==NULL ) pt = new+strlen(new);
+ else wasuc = Isupper(pt[1]);
+
+ if ( sf->mm!=NULL ) {
+ strcpy(pt,wasuc?".AMFM":".amfm");
+ if ( !LoadKerningDataFromAmfm(sf,new,map)) {
+ strcpy(pt,wasuc?".amfm":".AMFM");
+ ret = LoadKerningDataFromAmfm(sf,new,map);
+ } else
+ ret = true;
+ /* The above routine reads from the afm file if one exist */
+ } else {
+ strcpy(pt,wasuc?".AFM":".afm");
+ if ( !LoadKerningDataFromAfm(sf,new,map)) {
+ strcpy(pt,wasuc?".afm":".AFM");
+ ret = LoadKerningDataFromAfm(sf,new,map);
+ } else
+ ret = true;
+ }
+ free(new);
+return( ret );
+}
+
+static void *mygets(FILE *file,char *buffer,int size) {
+ char *end = buffer+size-1;
+ char *pt = buffer;
+ int ch;
+
+ while ( (ch=getc(file))!=EOF && ch!='\r' && ch!='\n' && pt<end )
+ *pt++ = ch;
+ *pt = '\0';
+ if ( ch==EOF && pt==buffer )
+return( NULL );
+ if ( ch=='\r' ) {
+ ch = getc(file);
+ if ( ch!='\n' )
+ ungetc(ch,file);
+ }
+return( buffer );
+}
+
+
+/* ************************************************************************** */
+/* **************************** Reading AFM files *************************** */
+/* ************************************************************************** */
+static void KPInsert( SplineChar *sc1, SplineChar *sc2, int off, int isv ) {
+ KernPair *kp;
+ int32 script;
+
+ if ( sc1!=NULL && sc2!=NULL ) {
+ for ( kp=sc1->kerns; kp!=NULL && kp->sc!=sc2; kp = kp->next );
+ if ( kp!=NULL )
+ kp->off = off;
+ else if ( off!=0 ) {
+ kp = chunkalloc(sizeof(KernPair));
+ kp->sc = sc2;
+ kp->off = off;
+ script = SCScriptFromUnicode(sc1);
+ if ( script==DEFAULT_SCRIPT )
+ script = SCScriptFromUnicode(sc2);
+ kp->subtable = SFSubTableFindOrMake(sc1->parent,
+ isv?CHR('v','k','r','n'):CHR('k','e','r','n'),
+ script, gpos_pair);
+ if ( isv ) {
+ kp->next = sc1->vkerns;
+ sc1->vkerns = kp;
+ } else {
+ kp->next = sc1->kerns;
+ sc1->kerns = kp;
+ }
+ }
+ }
+}
+
+int LoadKerningDataFromAfm(SplineFont *sf, char *filename,EncMap *map) {
+ FILE *file = fopen(filename,"r");
+ char buffer[200], *pt, *ept, ch;
+ SplineChar *sc1, *sc2;
+ int off, lx, ly, rx, ry;
+ char name[44], second[44], lig[44], buf2[100];
+ PST *liga;
+ double scale = (sf->ascent+sf->descent)/1000.0;
+
+ if ( file==NULL )
+return( 0 );
+ gwwv_progress_change_line2(_("Reading AFM file"));
+ while ( mygets(file,buffer,sizeof(buffer))!=NULL ) {
+ if ( strncmp(buffer,"KPX",3)==0 || strncmp(buffer,"KPY",3)==0 ) {
+ int isv = strncmp(buffer,"KPY",3)==0;
+ for ( pt=buffer+3; Isspace(*pt); ++pt);
+ for ( ept = pt; *ept!='\0' && !Isspace(*ept); ++ept );
+ ch = *ept; *ept = '\0';
+ sc1 = SFGetChar(sf,-1,pt);
+ *ept = ch;
+ for ( pt=ept; Isspace(*pt); ++pt);
+ for ( ept = pt; *ept!='\0' && !Isspace(*ept); ++ept );
+ ch = *ept; *ept = '\0';
+ sc2 = SFGetChar(sf,-1,pt);
+ *ept = ch;
+ off = strtol(ept,NULL,10);
+ KPInsert(sc1,sc2,rint(off*scale),isv);
+ } else if ( buffer[0]=='C' && Isspace(buffer[1])) {
+ char *pt;
+ sc2 = NULL;
+ for ( pt= strchr(buffer,';'); pt!=NULL; pt=strchr(pt+1,';') ) {
+ if ( sscanf( pt, "; N %40s", name )==1 )
+ sc2 = SFGetChar(sf,-1,name);
+ else if ( sc2!=NULL &&
+ sscanf( pt, "; B %d %d %d %d", &lx, &ly, &rx, &ry)==4 ) {
+ sc2->xmin = lx;
+ sc2->ymin = ly;
+ sc2->xmax = rx;
+ sc2->ymax = ry;
+
+ }
+ else if ( sc2!=NULL &&
+ sscanf( pt, "; L %40s %40s", second, lig)==2 ) {
+ sc1 = SFGetChar(sf,-1,lig);
+ if ( sc1!=NULL ) {
+ sprintf( buf2, "%s %s", name, second);
+ for ( liga=sc1->possub; liga!=NULL; liga=liga->next ) {
+ if ( liga->type == pst_ligature && strcmp(liga->u.lig.components,buf2)==0 )
+ break;
+ }
+ if ( liga==NULL ) {
+ liga = chunkalloc(sizeof(PST));
+ liga->subtable = SFSubTableFindOrMake(sf,
+ CHR('l','i','g','a'),SCScriptFromUnicode(sc2),
+ gsub_ligature);
+ liga->subtable->lookup->store_in_afm = true;
+ liga->type = pst_ligature;
+ liga->next = sc1->possub;
+ sc1->possub = liga;
+ liga->u.lig.lig = sc1;
+ liga->u.lig.components = copy( buf2 );
+ }
+ }
+ }
+ }
+ }
+ }
+ fclose(file);
+return( 1 );
+}
+
+static void CheckMMAfmFile(SplineFont *sf,char *amfm_filename,char *fontname,EncMap *map) {
+ /* the afm file should be in the same directory as the amfm file */
+ /* with the fontname as the filename */
+ char *temp, *pt;
+
+ free(sf->fontname);
+ sf->fontname = copy(fontname);
+
+ temp = galloc(strlen(amfm_filename)+strlen(fontname)+strlen(".afm")+1);
+ strcpy(temp, amfm_filename);
+ pt = strrchr(temp,'/');
+ if ( pt==NULL ) pt = temp;
+ else ++pt;
+ strcpy(pt,fontname);
+ pt += strlen(pt);
+ strcpy(pt,".afm");
+ if ( !LoadKerningDataFromAfm(sf,temp,map) ) {
+ strcpy(pt,".AFM");
+ LoadKerningDataFromAfm(sf,temp,map);
+ }
+ free(temp);
+}
+
+int LoadKerningDataFromAmfm(SplineFont *sf, char *filename,EncMap *map) {
+ FILE *file=NULL;
+ char buffer[280], *pt, lastname[257];
+ int index, i;
+ MMSet *mm = sf->mm;
+
+ if ( mm!=NULL )
+ file = fopen(filename,"r");
+ pt = strstrmatch(filename,".amfm");
+ if ( pt!=NULL ) {
+ char *afmname = copy(filename);
+ strcpy(afmname+(pt-filename),Isupper(pt[1])?".AFM":".afm");
+ LoadKerningDataFromAfm(mm->normal,afmname,map);
+ free(afmname);
+ }
+ if ( file==NULL )
+return( 0 );
+
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ gwwv_progress_change_line2(_("Reading AFM file"));
+#elif defined(FONTFORGE_CONFIG_GTK)
+ gwwv_progress_change_line2(_("Reading AFM file"));
+#endif
+ while ( fgets(buffer,sizeof(buffer),file)!=NULL ) {
+ if ( strstrmatch(buffer,"StartMaster")!=NULL )
+ break;
+ }
+ index = -1; lastname[0] = '\0';
+ while ( fgets(buffer,sizeof(buffer),file)!=NULL ) {
+ if ( strstrmatch(buffer,"EndMaster")!=NULL ) {
+ if ( lastname[0]!='\0' && index!=-1 && index<mm->instance_count )
+ CheckMMAfmFile(mm->instances[index],filename,lastname,map);
+ index = -1; lastname[0] = '\0';
+ } else if ( sscanf(buffer,"FontName %256s", lastname )== 1 ) {
+ /* Do Nothing, all done */
+ } else if ( (pt = strstr(buffer,"WeightVector"))!=NULL ) {
+ pt += strlen("WeightVector");
+ while ( *pt==' ' || *pt=='[' ) ++pt;
+ i = 0;
+ while ( *pt!=']' && *pt!='\0' ) {
+ if ( *pt=='0' )
+ ++i;
+ else if ( *pt=='1' ) {
+ index = i;
+ break;
+ }
+ ++pt;
+ }
+ }
+ }
+ fclose(file);
+return( true );
+}
+
+
+/* from tottfgpos.c */
+
+#if 0
+static uint32 scripts[][15] = {
+/* Arabic */ { CHR('a','r','a','b'), 0x0600, 0x06ff, 0xfb50, 0xfdff, 0xfe70, 0xfeff },
+/* Aramaic */ { CHR('a','r','a','m'), 0x820, 0x83f },
+/* Armenian */ { CHR('a','r','m','n'), 0x0530, 0x058f, 0xfb13, 0xfb17 },
+/* Balinese */ { CHR('b','a','l','i'), 0x1b00, 0x1b7f },
+/* Bengali */ { CHR('b','e','n','g'), 0x0980, 0x09ff },
+/* Bliss symb */{ CHR('b','l','i','s'), 0x12200, 0x124ff },
+/* Bopomofo */ { CHR('b','o','p','o'), 0x3100, 0x312f, 0x31a0, 0x31bf },
+/* Braille */ { CHR('b','r','a','i'), 0x2800, 0x28ff },
+/* Buginese */ { CHR('b','u','g','i'), 0x1a00, 0x1a1f },
+/* Buhid */ { CHR('b','u','h','d'), 0x1740, 0x1753 },
+/* Byzantine M*/{ CHR('b','y','z','m'), 0x1d000, 0x1d0ff },
+/* Canadian Syl*/{CHR('c','a','n','s'), 0x1400, 0x167f },
+/* Cherokee */ { CHR('c','h','e','r'), 0x13a0, 0x13ff },
+/* Cirth */ { CHR('c','i','r','t'), 0x12080, 0x120ff },
+/* CJKIdeogra */{ CHR('h','a','n','i'), 0x3300, 0x9fff, 0xf900, 0xfaff, 0x020000, 0x02ffff },
+/* Coptic */ { CHR('c','o','p','t'), 0x2c80, 0x2cff },
+/* Cypriot */ { CHR('c','p','m','n'), 0x10800, 0x1083f },
+/* Cyrillic */ { CHR('c','y','r','l'), 0x0400, 0x052f },
+/* Deseret */ { CHR('d','s','r','t'), 0x10400, 0x1044f },
+/* Devanagari */{ CHR('d','e','v','a'), 0x0900, 0x097f },
+/* Ethiopic */ { CHR('e','t','h','i'), 0x1200, 0x139f },
+/* Georgian */ { CHR('g','e','o','r'), 0x1080, 0x10ff },
+/* Glagolitic */{ CHR('g','l','a','g'), 0x1080, 0x10ff },
+/* Gothic */ { CHR('g','o','t','h'), 0x10330, 0x1034a },
+/* Greek */ { CHR('g','r','e','k'), 0x0370, 0x03ff, 0x1f00, 0x1fff },
+/* Gujarati */ { CHR('g','u','j','r'), 0x0a80, 0x0aff },
+/* Gurmukhi */ { CHR('g','u','r','u'), 0x0a00, 0x0a7f },
+/* Hangul */ { CHR('h','a','n','g'), 0xac00, 0xd7af, 0x3130, 0x319f, 0xffa0, 0xff9f },
+/* Hanunoo */ { CHR('h','a','n','o'), 0x1720, 0x1734 },
+ /* I'm not sure what the difference is between the 'hang' tag and the 'jamo' */
+ /* tag. 'Jamo' is said to be the precomposed forms, but what's 'hang'? */
+/* Hebrew */ { CHR('h','e','b','r'), 0x0590, 0x05ff, 0xfb1e, 0xfb4f },
+#if 0 /* Hiragana used to have its own tag, but has since been merged with katakana */
+/* Hiragana */ { CHR('h','i','r','a'), 0x3040, 0x309f },
+#endif
+/* Hangul Jamo*/{ CHR('j','a','m','o'), 0x1100, 0x11ff, 0x3130, 0x319f, 0xffa0, 0xffdf },
+/* Katakana */ { CHR('k','a','n','a'), 0x3040, 0x30ff, 0xff60, 0xff9f },
+/* Javanese */ { CHR('j','a','v','a'), 0 }, /* MS has a tag, but there is no unicode range */
+/* Khmer */ { CHR('k','h','m','r'), 0x1780, 0x17ff },
+/* Kannada */ { CHR('k','n','d','a'), 0x0c80, 0x0cff },
+/* Kharosthi */ { CHR('k','h','a','r'), 0x10a00, 0x10a5f },
+/* Latin */ { CHR('l','a','t','n'), 0x0041, 0x005a, 0x0061, 0x007a,
+ 0x00c0, 0x02af, 0x1d00, 0x1eff, 0xfb00, 0xfb0f, 0xff00, 0xff5f, 0, 0 },
+/* Lao */ { CHR('l','a','o',' '), 0x0e80, 0x0eff },
+/* Limbu */ { CHR('l','i','m','b'), 0x1900, 0x194f },
+/* Linear A */ { CHR('l','i','n','a'), 0x10180, 0x102cf },
+/* Linear B */ { CHR('l','i','n','b'), 0x10000, 0x100fa },
+/* Malayalam */ { CHR('m','l','y','m'), 0x0d00, 0x0d7f },
+/* Mathematical Alphanumeric Symbols */
+ { CHR('m','a','t','h'), 0x1d400, 0x1d7ff },
+/* Mongolian */ { CHR('m','o','n','g'), 0x1800, 0x18af },
+/* Musical */ { CHR('m','u','s','i'), 0x1d100, 0x1d1ff },
+/* Myanmar */ { CHR('m','y','m','r'), 0x1000, 0x107f },
+/* N'Ko */ { CHR('n','k','o',' '), 0x07c0, 0x07fa },
+/* Ogham */ { CHR('o','g','a','m'), 0x1680, 0x169f },
+/* Old Italic */{ CHR('i','t','a','l'), 0x10300, 0x1031e },
+/* Old Permic */{ CHR('p','e','r','m'), 0x10350, 0x1037f },
+/* Old Persian cuneiform */
+ { CHR('x','p','e','o'), 0x103a0, 0x103df },
+/* Oriya */ { CHR('o','r','y','a'), 0x0b00, 0x0b7f },
+/* Osmanya */ { CHR('o','s','m','a'), 0x10480, 0x104a9 },
+/* Phags-pa */ { CHR('p','h','a','g'), 0xa840, 0xa87f },
+/* Phoenician */{ CHR('p','h','n','x'), 0x10900, 0x1091f },
+/* Pollard */ { CHR('p','l','r','d'), 0x104b0, 0x104d9 },
+/* Runic */ { CHR('r','u','n','r'), 0x16a0, 0x16ff },
+/* Shavian */ { CHR('s','h','a','w'), 0x10450, 0x1047f },
+/* Sinhala */ { CHR('s','i','n','h'), 0x0d80, 0x0dff },
+/* Sumero-Akkadian Cuneiform */
+ { CHR('x','s','u','x'), 0x12000, 0x1236e },
+/* Syloti Nagri */
+ { CHR('s','y','l','o'), 0xa800, 0xa82f },
+/* Syriac */ { CHR('s','y','r','c'), 0x0700, 0x074f },
+/* Tagalog */ { CHR('t','a','g','l'), 0x1700, 0x1714 },
+/* Tagbanwa */ { CHR('t','a','g','b'), 0x1760, 0x1773 },
+/* Tai Le */ { CHR('t','a','l','e'), 0x1950, 0x1974 },
+/* Tai Lu */ { CHR('t','a','l','u'), 0x1980, 0x19df },
+/* Tamil */ { CHR('t','a','m','l'), 0x0b80, 0x0bff },
+/* Telugu */ { CHR('t','e','l','u'), 0x0c00, 0x0c7f },
+/* Tengwar */ { CHR('t','e','n','g'), 0x12000, 0x1207f },
+/* Thaana */ { CHR('t','h','a','a'), 0x0780, 0x07bf },
+/* Thai */ { CHR('t','h','a','i'), 0x0e00, 0x0e7f },
+/* Tibetan */ { CHR('t','i','b','t'), 0x0f00, 0x0fff },
+/* Tifinagh */ { CHR('t','f','n','g'), 0x2d30, 0x2d7f },
+/* Ugaritic */ { CHR('u','g','a','r'), 0x10380, 0x1039d },
+/* Yi */ { CHR('y','i',' ',' '), 0xa000, 0xa4c6 },
+ { 0 }
+};
+
+int ScriptIsRightToLeft(uint32 script) {
+ if ( script==CHR('a','r','a','b') || script==CHR('h','e','b','r') ||
+ script==CHR('c','p','m','n') || script==CHR('k','h','a','r') ||
+ script==CHR('s','y','r','c') || script==CHR('t','h','a','a') ||
+ script==CHR('n','k','o',' '))
+return( true );
+
+return( false );
+}
+
+uint32 ScriptFromUnicode(int u,SplineFont *sf) {
+ int s, k;
+
+ if ( u!=-1 ) {
+ for ( s=0; scripts[s][0]!=0; ++s ) {
+ for ( k=1; scripts[s][k+1]!=0; k += 2 )
+ if ( u>=scripts[s][k] && u<=scripts[s][k+1] )
+ break;
+ if ( scripts[s][k+1]!=0 )
+ break;
+ }
+ if ( scripts[s][0]!=0 ) {
+ extern int use_second_indic_scripts;
+ uint32 script = scripts[s][0];
+ if ( use_second_indic_scripts ) {
+ /* MS has a parallel set of script tags for their new */
+ /* Indic font shaper */
+ if ( script == CHR('b','e','n','g' )) script = CHR('b','n','g','2');
+ else if ( script == CHR('d','e','v','a' )) script = CHR('d','e','v','2');
+ else if ( script == CHR('g','u','j','r' )) script = CHR('g','j','r','2');
+ else if ( script == CHR('g','u','r','u' )) script = CHR('g','u','r','2');
+ else if ( script == CHR('k','n','d','a' )) script = CHR('k','n','d','2');
+ else if ( script == CHR('m','l','y','m' )) script = CHR('m','l','y','2');
+ else if ( script == CHR('o','r','y','a' )) script = CHR('o','r','y','2');
+ else if ( script == CHR('t','a','m','l' )) script = CHR('t','m','l','2');
+ else if ( script == CHR('t','e','l','u' )) script = CHR('t','e','l','2');
+ }
+return( script );
+ }
+ } else if ( sf!=NULL ) {
+ if ( sf->cidmaster!=NULL || sf->subfontcnt!=0 ) {
+ if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
+ if ( strmatch(sf->ordering,"Identity")==0 )
+return( DEFAULT_SCRIPT );
+ else if ( strmatch(sf->ordering,"Korean")==0 )
+return( CHR('h','a','n','g'));
+ else
+return( CHR('h','a','n','i') );
+ }
+ }
+
+return( DEFAULT_SCRIPT );
+}
+
+uint32 SCScriptFromUnicode(SplineChar *sc) {
+ char *pt;
+ PST *pst;
+ SplineFont *sf;
+ int i; unsigned uni;
+ FeatureScriptLangList *features;
+
+ if ( sc==NULL )
+return( DEFAULT_SCRIPT );
+
+ sf = sc->parent;
+ if ( sc->unicodeenc!=-1 )
+return( ScriptFromUnicode( sc->unicodeenc,sf ));
+
+ pt = sc->name;
+ if ( *pt ) for ( ++pt; *pt!='\0' && *pt!='_' && *pt!='.'; ++pt );
+ if ( *pt!='\0' ) {
+ char *str = copyn(sc->name,pt-sc->name);
+ int uni = sf==NULL || sf->fv==NULL ? UniFromName(str,ui_none,&custom) :
+ UniFromName(str,sf->uni_interp,sf->fv->map->enc);
+ free(str);
+ if ( uni!=-1 )
+return( ScriptFromUnicode( uni,sf ));
+ }
+ /* Adobe ligature uniXXXXXXXX */
+ if ( strncmp(sc->name,"uni",3)==0 && sscanf(sc->name+3,"%4x", &uni)==1 )
+return( ScriptFromUnicode( uni,sf ));
+
+ if ( sf==NULL )
+return( DEFAULT_SCRIPT );
+
+ if ( sf->cidmaster ) sf=sf->cidmaster;
+ else if ( sf->mm!=NULL ) sf=sf->mm->normal;
+ for ( i=0; i<2; ++i ) {
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->type == pst_lcaret )
+ continue;
+ for ( features = pst->subtable->lookup->features; features!=NULL; features=features->next ) {
+ if ( features->scripts!=NULL )
+return( features->scripts->script );
+ }
+ }
+ }
+return( ScriptFromUnicode( sc->unicodeenc,sf ));
+}
+
+SplineChar **SFGlyphsFromNames(SplineFont *sf,char *names) {
+ int cnt, ch;
+ char *pt, *end;
+ SplineChar *sc, **glyphs;
+
+ cnt = 0;
+ for ( pt = names; *pt; pt = end+1 ) {
+ ++cnt;
+ end = strchr(pt,' ');
+ if ( end==NULL )
+ break;
+ }
+
+ glyphs = galloc((cnt+1)*sizeof(SplineChar *));
+ cnt = 0;
+ for ( pt = names; *pt; pt = end+1 ) {
+ end = strchr(pt,' ');
+ if ( end==NULL )
+ end = pt+strlen(pt);
+ ch = *end;
+ *end = '\0';
+ sc = SFGetChar(sf,-1,pt);
+ if ( sc!=NULL && sc->ttf_glyph!=-1 )
+ glyphs[cnt++] = sc;
+ *end = ch;
+ if ( ch=='\0' )
+ break;
+ }
+ glyphs[cnt] = NULL;
+return( glyphs );
+}
+int gdefclass(SplineChar *sc) {
+ PST *pst;
+ AnchorPoint *ap;
+
+ if ( sc->glyph_class!=0 )
+return( sc->glyph_class-1 );
+
+ if ( strcmp(sc->name,".notdef")==0 )
+return( 0 );
+
+ for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
+ if ( pst->type == pst_ligature )
+return( 2 ); /* Ligature */
+ }
+
+ ap=sc->anchor;
+ while ( ap!=NULL && (ap->type==at_centry || ap->type==at_cexit) )
+ ap = ap->next;
+ if ( ap!=NULL && (ap->type==at_mark || ap->type==at_basemark) )
+return( 3 );
+ else
+return( 1 );
+ /* I not quite sure what a componant glyph is. Probably something that */
+ /* is not in the cmap table and is referenced in other glyphs */
+ /* Anyway I never return class 4 */ /* (I've never seen it used by others) */
+}
+
+#endif /* tottfgpos.c */
+
+/* from charinfo.c */
+
+
+static int MultipleValues(char *name, int local) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buts[3];
+ buts[0] = _("_Yes"); buts[1]=_("_No"); buts[2] = NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buts[] = { GTK_STOCK_YES, GTK_STOCK_CANCEL, NULL };
+#endif
+ if ( gwwv_ask(_("Multiple"),(const char **) buts,0,1,_("There is already a glyph with this Unicode encoding\n(named %1$.40s, at local encoding %2$d).\nIs that what you want?"),name,local)==0 )
+return( true );
+#endif
+return( false );
+}
+
+static int MultipleNames(void) {
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+#if defined(FONTFORGE_CONFIG_GDRAW)
+ char *buts[3];
+ buts[0] = _("_Yes"); buts[1]=_("_Cancel"); buts[2] = NULL;
+#elif defined(FONTFORGE_CONFIG_GTK)
+ static char *buts[] = { GTK_STOCK_YES, GTK_STOCK_CANCEL, NULL };
+#endif
+ if ( gwwv_ask(_("Multiple"),(const char **) buts,0,1,_("There is already a glyph with this name,\ndo you want to swap names?"))==0 )
+return( true );
+#endif
+return( false );
+}
+
+int SCSetMetaData(SplineChar *sc,char *name,int unienc,const char *comment) {
+ SplineFont *sf = sc->parent;
+ int i, mv=0;
+ int isnotdef, samename=false;
+ struct altuni *alt;
+
+ for ( alt=sc->altuni; alt!=NULL && alt->unienc!=unienc; alt=alt->next );
+ if ( (sc->unicodeenc == unienc || alt!=NULL ) && strcmp(name,sc->name)==0 ) {
+ samename = true; /* No change, it must be good */
+ }
+ if ( alt!=NULL || !samename ) {
+ isnotdef = strcmp(name,".notdef")==0;
+ for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL && sf->glyphs[i]!=sc ) {
+ if ( unienc!=-1 && sf->glyphs[i]->unicodeenc==unienc ) {
+ if ( !mv && !MultipleValues(sf->glyphs[i]->name,i)) {
+return( false );
+ }
+ mv = 1;
+ } else if ( !isnotdef && strcmp(name,sf->glyphs[i]->name)==0 ) {
+ if ( !MultipleNames()) {
+return( false );
+ }
+ free(sf->glyphs[i]->name);
+ sf->glyphs[i]->namechanged = true;
+ if ( strncmp(sc->name,"uni",3)==0 && sf->glyphs[i]->unicodeenc!=-1) {
+ char buffer[12];
+ if ( sf->glyphs[i]->unicodeenc<0x10000 )
+ sprintf( buffer,"uni%04X", sf->glyphs[i]->unicodeenc);
+ else
+ sprintf( buffer,"u%04X", sf->glyphs[i]->unicodeenc);
+ sf->glyphs[i]->name = copy(buffer);
+ } else {
+ sf->glyphs[i]->name = sc->name;
+ sc->name = NULL;
+ }
+ break;
+ }
+ }
+ if ( sc->unicodeenc!=unienc ) {
+ struct splinecharlist *scl;
+ int layer;
+ RefChar *ref;
+
+ for ( scl=sc->dependents; scl!=NULL; scl=scl->next ) {
+ for ( layer=ly_fore; layer<scl->sc->layer_cnt; ++layer )
+ for ( ref = scl->sc->layers[layer].refs; ref!=NULL; ref=ref->next )
+ if ( ref->sc==sc )
+ ref->unicode_enc = unienc;
+ }
+ }
+ }
+ if ( alt!=NULL )
+ alt->unienc = sc->unicodeenc;
+ sc->unicodeenc = unienc;
+ if ( sc->name==NULL || strcmp(name,sc->name)!=0 ) {
+ free(sc->name);
+ sc->name = copy(name);
+ sc->namechanged = true;
+ GlyphHashFree(sf);
+ }
+ sf->changed = true;
+ if ( unienc>=0xe000 && unienc<=0xf8ff )
+ /* Ok to name things in the private use area */;
+ else if ( samename )
+ /* Ok to name it itself */;
+ else {
+ FontView *fvs;
+ for ( fvs=sf->fv; fvs!=NULL; fvs=fvs->nextsame ) {
+ int enc = fvs->map->backmap[sc->orig_pos];
+ if ( enc!=-1 && ((fvs->map->enc->only_1byte && enc<256) ||
+ (fvs->map->enc->has_2byte && enc<65535 ))) {
+ fvs->map->enc = &custom;
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ FVSetTitle(fvs);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+ }
+ }
+ }
+ free(sc->comment); sc->comment = NULL;
+ if ( comment!=NULL && *comment!='\0' )
+ sc->comment = copy(comment);
+
+#ifndef FONTFORGE_CONFIG_NO_WINDOWING_UI
+ SCRefreshTitles(sc);
+#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
+return( true );
+}
+
+/* from cvhints.c */
+
+void SCClearRounds(SplineChar *sc) {
+ SplineSet *ss;
+ SplinePoint *sp;
+
+ for ( ss=sc->layers[ly_fore].splines; ss!=NULL; ss=ss->next ) {
+ for ( sp=ss->first; ; ) {
+ sp->roundx = sp->roundy = false;
+ if ( sp->next==NULL )
+ break;
+ sp = sp->next->to;
+ if ( sp==ss->first )
+ break;
+ }
+ }
+}
+
+
+/* from cvpointer.c */
+
+RefChar *HasUseMyMetrics(SplineChar *sc) {
+ RefChar *r;
+
+ for ( r=sc->layers[ly_fore].refs; r!=NULL; r=r->next )
+ if ( r->use_my_metrics )
+return( r );
+
+return( NULL );
+}
+
+/* if they changed the width, then change the width on all bitmap chars of */
+/* ours, and if we are a letter, then change the width on all chars linked */
+/* to us which had the same width that we used to have (so if we change the */
+/* width of A, we'll also change that of À and Ä and ... */
+void SCSynchronizeWidth(SplineChar *sc,real newwidth, real oldwidth, FontView *flagfv) {
+ BDFFont *bdf;
+ struct splinecharlist *dlist;
+ FontView *fv = sc->parent->fv;
+ RefChar *r = HasUseMyMetrics(sc);
+ int isprobablybase;
+
+ sc->widthset = true;
+ if( r!=NULL ) {
+ if ( oldwidth==r->sc->width ) {
+ sc->width = r->sc->width;
+return;
+ }
+ newwidth = r->sc->width;
+ }
+ if ( newwidth==oldwidth )
+return;
+ sc->width = newwidth;
+ for ( bdf=sc->parent->bitmaps; bdf!=NULL; bdf=bdf->next ) {
+ BDFChar *bc = bdf->glyphs[sc->orig_pos];
+ if ( bc!=NULL ) {
+ int width = rint(sc->width*bdf->pixelsize / (real) (sc->parent->ascent+sc->parent->descent));
+ if ( bc->width!=width ) {
+ /*BCPreserveWidth(bc);*/ /* Bitmaps can't set width, so no undo for it */
+ bc->width = width;
+ BCCharChangedUpdate(bc);
+ }
+ }
+ }
+
+ if ( !adjustwidth )
+return;
+
+ isprobablybase = true;
+ if ( sc->unicodeenc==-1 || sc->unicodeenc>=0x10000 ||
+ !unic_isalpha(sc->unicodeenc) || unic_iscombining(sc->unicodeenc))
+ isprobablybase = false;
+
+ for ( dlist=sc->dependents; dlist!=NULL; dlist=dlist->next ) {
+ RefChar *metrics = HasUseMyMetrics(dlist->sc);
+ if ( metrics!=NULL && metrics->sc!=sc )
+ continue;
+ else if ( metrics==NULL && !isprobablybase )
+ continue;
+ if ( dlist->sc->width==oldwidth &&
+ (flagfv==NULL || !flagfv->selected[flagfv->map->backmap[dlist->sc->orig_pos]])) {
+ SCSynchronizeWidth(dlist->sc,newwidth,oldwidth,fv);
+ if ( !dlist->sc->changed ) {
+ dlist->sc->changed = true;
+ if ( fv!=NULL )
+ FVToggleCharChanged(dlist->sc);
+ }
+ SCUpdateAll(dlist->sc);
+ }
+ }
+}
+
+
+/* If they change the left bearing of a character, then in all chars */
+/* that depend on it should be adjusted too. */
+/* Also all vstem hints */
+/* I deliberately don't set undoes in the dependants. The change is not */
+/* in them, after all */
+void SCSynchronizeLBearing(SplineChar *sc,real off) {
+ struct splinecharlist *dlist;
+ RefChar *ref;
+ DStemInfo *d;
+ StemInfo *h;
+ HintInstance *hi;
+ int isprobablybase;
+
+ for ( h=sc->vstem; h !=NULL; h=h->next )
+ h->start += off;
+ for ( h=sc->hstem; h !=NULL; h=h->next )
+ for ( hi = h->where; hi!=NULL; hi=hi->next ) {
+ hi->begin += off;
+ hi->end += off;
+ }
+ for ( d=sc->dstem; d !=NULL; d=d->next ) {
+ d->leftedgetop.x += off;
+ d->rightedgetop.x += off;
+ d->leftedgebottom.x += off;
+ d->rightedgebottom.x += off;
+ }
+
+ if ( !adjustlbearing )
+return;
+
+ isprobablybase = true;
+ if ( sc->unicodeenc==-1 || sc->unicodeenc>=0x10000 ||
+ !unic_isalpha(sc->unicodeenc) || unic_iscombining(sc->unicodeenc))
+ isprobablybase = false;
+
+ for ( dlist=sc->dependents; dlist!=NULL; dlist=dlist->next ) {
+ RefChar *metrics = HasUseMyMetrics(dlist->sc);
+ if ( metrics!=NULL && metrics->sc!=sc )
+ continue;
+ else if ( metrics==NULL && !isprobablybase )
+ continue;
+ else if ( metrics==NULL && sc->width!=dlist->sc->width )
+ continue;
+ SCPreserveState(dlist->sc,false);
+ SplinePointListShift(dlist->sc->layers[ly_fore].splines,off,true);
+ for ( ref = dlist->sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next )
+ if ( ref->sc!=sc ) {
+ SplinePointListShift(ref->layers[0].splines,off,true);
+ ref->transform[4] += off;
+ ref->bb.minx += off; ref->bb.maxx += off;
+ }
+ SCUpdateAll(dlist->sc);
+ SCSynchronizeLBearing(dlist->sc,off);
+ }
+}
+
+
+/* from cvgetinfo.c */
+
+void MDReplace(MinimumDistance *md,SplineSet *old,SplineSet *rpl) {
+ /* Replace all the old points with the ones in rpl in the minimum distance hints */
+ SplinePoint *osp, *rsp;
+ MinimumDistance *test;
+
+ if ( md==NULL )
+return;
+
+ while ( old!=NULL && rpl!=NULL ) {
+ osp = old->first; rsp = rpl->first;
+ while ( 1 ) {
+ for ( test=md; test!=NULL ; test=test->next ) {
+ if ( test->sp1==osp )
+ test->sp1 = rsp;
+ if ( test->sp2==osp )
+ test->sp2 = rsp;
+ }
+ if ( osp->next==NULL || rsp->next==NULL )
+ break;
+ osp = osp->next->to;
+ rsp = rsp->next->to;
+ if ( osp==old->first )
+ break;
+ }
+ old = old->next;
+ rpl = rpl->next;
+ }
+}
+
+void SCOrderAP(SplineChar *sc) {
+ int lc=0, cnt=0, out=false, i,j;
+ AnchorPoint *ap, **array;
+ /* Order so that first ligature index comes first */
+
+ for ( ap=sc->anchor; ap!=NULL; ap=ap->next ) {
+ if ( ap->lig_index<lc ) out = true;
+ if ( ap->lig_index>lc ) lc = ap->lig_index;
+ ++cnt;
+ }
+ if ( !out )
+return;
+
+ array = galloc(cnt*sizeof(AnchorPoint *));
+ for ( i=0, ap=sc->anchor; ap!=NULL; ++i, ap=ap->next )
+ array[i] = ap;
+ for ( i=0; i<cnt-1; ++i ) {
+ for ( j=i+1; j<cnt; ++j ) {
+ if ( array[i]->lig_index>array[j]->lig_index ) {
+ ap = array[i];
+ array[i] = array[j];
+ array[j] = ap;
+ }
+ }
+ }
+ sc->anchor = array[0];
+ for ( i=0; i<cnt-1; ++i )
+ array[i]->next = array[i+1];
+ array[cnt-1]->next = NULL;
+ free( array );
+}
+
+/* autowidth.c */
+
+#define NOTREACHED -9999.0
+
+static real SplineFindMinXAtY(Spline *spline,real y,real min) {
+ extended t,t1,t2,tbase,val;
+ Spline1D *xsp;
+
+ if ( y>spline->from->me.y && y>spline->from->nextcp.y &&
+ y>spline->to->me.y && y>spline->to->prevcp.y )
+return( min );
+ if ( y<spline->from->me.y && y<spline->from->nextcp.y &&
+ y<spline->to->me.y && y<spline->to->prevcp.y )
+return( min );
+ if ( min!=NOTREACHED ) {
+ if ( min<=spline->from->me.x && min<=spline->from->nextcp.x &&
+ min<=spline->to->me.x && min<=spline->to->prevcp.x )
+return( min );
+ }
+
+ xsp = &spline->splines[0];
+ SplineFindExtrema(&spline->splines[1], &t1, &t2 );
+ tbase = 0;
+ if ( t1!=-1 ) {
+ t = SplineSolve(&spline->splines[1],0,t1,y,.01);
+ if ( t>=0 && t<=1 ) {
+ val = ((xsp->a*t+xsp->b)*t+xsp->c)*t + xsp->d;
+ if ( min==NOTREACHED || val<min )
+ min = val;
+ }
+ tbase = t1;
+ }
+ if ( t2!=-1 ) {
+ t = SplineSolve(&spline->splines[1],tbase,t2,y,.01);
+ if ( t>=0 && t<=1 ) {
+ val = ((xsp->a*t+xsp->b)*t+xsp->c)*t + xsp->d;
+ if ( min==NOTREACHED || val<min )
+ min = val;
+ }
+ tbase = t2;
+ }
+ t = SplineSolve(&spline->splines[1],tbase,1.0,y,.01);
+ if ( t>=0 && t<=1 ) {
+ val = ((xsp->a*t+xsp->b)*t+xsp->c)*t + xsp->d;
+ if ( min==NOTREACHED || val<min )
+ min = val;
+ }
+return( min );
+}
+
+
+static real SSFindMinXAtY(SplineSet *spl,real y,real min) {
+ Spline *sp, *first;
+
+ while ( spl!=NULL ) {
+ first = NULL;
+ for ( sp = spl->first->next; sp!=NULL && sp!=first; sp = sp->to->next ) {
+ min = SplineFindMinXAtY(sp,y,min);
+ if ( first==NULL ) first = sp;
+ }
+ spl = spl->next;
+ }
+return( min );
+}
+
+static real SCFindMinXAtY(SplineChar *sc,real y) {
+ real min = NOTREACHED;
+ RefChar *ref;
+
+ min = SSFindMinXAtY(sc->layers[ly_fore].splines,y,NOTREACHED);
+ for ( ref=sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next )
+ min = SSFindMinXAtY(ref->layers[0].splines,y,min);
+return( min );
+}
+
+
+real SFGuessItalicAngle(SplineFont *sf) {
+ static char *easyserif = "IBDEFHKLNPR";
+ int i,si;
+ real as, topx, bottomx;
+ DBounds bb;
+ double angle;
+
+ for ( i=0; easyserif[i]!='\0'; ++i )
+ if ( (si=SFFindExistingSlot(sf,easyserif[i],NULL))!=-1 && sf->glyphs[si]!=NULL )
+ break;
+ if ( easyserif[i]=='\0' ) /* can't guess */
+return( 0 );
+
+ SplineCharFindBounds(sf->glyphs[si],&bb);
+ as = bb.maxy-bb.miny;
+
+ topx = SCFindMinXAtY(sf->glyphs[si],2*as/3+bb.miny);
+ bottomx = SCFindMinXAtY(sf->glyphs[si],as/3+bb.miny);
+ if ( topx==bottomx )
+return( 0 );
+
+ angle = atan2(as/3,topx-bottomx)*180/3.1415926535897932-90;
+ if ( angle<1 && angle>-1 ) angle = 0;
+return( angle );
+}
+
+
+/* from uiutil.c */
+
+void IError(const char *format,...) {
+ char *newf;
+ va_list ap;
+ const char *ierr = "Internal Error: ";
+ va_start(ap,format);
+ newf = malloc(strlen(format)+strlen(ierr)+1);
+ if (newf==NULL) {
+ perror("memory allocation failed");
+ exit(EXIT_FAILURE);
+ }
+ sprintf(newf,"%s%s",ierr,format);
+ _gwwv_post_error(newf,ap);
+ va_end(ap);
+}
+
+void LogError(const char *format,...) {
+ va_list ap;
+ va_start(ap,format);
+ _gwwv_post_error(format,ap);
+ va_end(ap);
+}
+
+void ff_post_notice(const char *title,const char *statement,...) {
+ char *newf;
+ va_list ap;
+ va_start(ap,statement);
+ newf = malloc(strlen(statement)+strlen(title)+3);
+ if (newf==NULL) {
+ perror("memory allocation failed");
+ exit(EXIT_FAILURE);
+ }
+ sprintf(newf,"%s: %s",title,statement);
+ _gwwv_post_error(newf,ap);
+ va_end(ap);
+}
+
+
+/* from statemachine.c */
+
+
+typedef struct statemachinedlg {
+ int state_cnt, class_cnt, index;
+ struct asm_state *states;
+ ASM *sm;
+ SplineFont *sf;
+ struct gfi_data *d;
+ int isnew;
+ int fh, as;
+ int stateh, statew;
+ int xstart, ystart; /* This is where the headers start */
+ int xstart2, ystart2; /* This is where the data start */
+ int width, height;
+ int offleft, offtop;
+ int canceldrop, sbdrop;
+ int isedit;
+ int st_pos;
+ int edit_done, edit_ok;
+} SMD;
+
+
+SMD *StateMachineEdit(SplineFont *sf,ASM *sm,struct gfi_data *d) {
+ /* complete. but prepocessed */
+ SMD *smd = gcalloc(1,sizeof(SMD));
+return( smd );
+}
+
+/* from fvcomposite.c */
+
+#define BottomAccent 0x300
+#define TopAccent 0x345
+
+
+/* for accents between 0x300 and 345 these are some synonyms */
+/* type1 wants accented chars built with accents in the 0x2c? range */
+/* except for grave and acute which live in iso8859-1 range */
+/* this table is ordered on a best try basis */
+static const unichar_t accents[][4] = {
+ { 0x2cb, 0x300, 0x60 }, /* grave */
+ { 0x2ca, 0x301, 0xb4 }, /* acute */
+ { 0x2c6, 0x302, 0x5e }, /* circumflex */
+ { 0x2dc, 0x303, 0x7e }, /* tilde */
+ { 0x2c9, 0x304, 0xaf }, /* macron */
+ { 0x305, 0xaf }, /* overline, (macron is suggested as a syn, but it's not quite right) */
+ { 0x2d8, 0x306 }, /* breve */
+ { 0x2d9, 0x307, '.' }, /* dot above */
+ { 0xa8, 0x308 }, /* diaeresis */
+ { 0x2c0 }, /* hook above */
+ { 0x2da, 0xb0 }, /* ring above */
+ { 0x2dd }, /* real acute */
+ { 0x2c7 }, /* caron */
+ { 0x2c8, 0x384, 0x30d, '\'' }, /* vertical line, tonos */
+ { 0x30e, '"' }, /* real vertical line */
+ { 0 }, /* real grave */
+ { 0 }, /* cand... */ /* 310 */
+ { 0 }, /* inverted breve */
+ { 0x2bb }, /* turned comma */
+ { 0x2bc, 0x313, ',' }, /* comma above */
+ { 0x2bd }, /* reversed comma */
+ { 0x2bc, 0x315, ',' }, /* comma above right */
+ { 0x316, 0x60, 0x2cb }, /* grave below */
+ { 0x317, 0xb4, 0x2ca }, /* acute below */
+ { 0 }, /* left tack */
+ { 0 }, /* right tack */
+ { 0 }, /* left angle */
+ { 0 }, /* horn, sometimes comma but only if nothing better */
+ { 0 }, /* half ring */
+ { 0x2d4 }, /* up tack */
+ { 0x2d5 }, /* down tack */
+ { 0x2d6, 0x31f, '+' }, /* plus below */
+ { 0x2d7, 0x320, '-' }, /* minus below */ /* 320 */
+ { 0x2b2 }, /* hook */
+ { 0 }, /* back hook */
+ { 0x323, 0x2d9, '.' }, /* dot below */
+ { 0x324, 0xa8 }, /* diaeresis below */
+ { 0x325, 0x2da, 0xb0 }, /* ring below */
+ { 0x326, 0x2bc, ',' }, /* comma below */
+ { 0xb8 }, /* cedilla */
+ { 0x2db }, /* ogonek */ /* 0x328 */
+ { 0x329, 0x2c8, 0x384, '\'' }, /* vertical line below */
+ { 0 }, /* bridge below */
+ { 0 }, /* real arch below */
+ { 0x32c, 0x2c7 }, /* caron below */
+ { 0x32d, 0x2c6, 0x52 }, /* circumflex below */
+ { 0x32e, 0x2d8 }, /* breve below */
+ { 0 }, /* inverted breve below */
+ { 0x330, 0x2dc, 0x7e }, /* tilde below */ /* 0x330 */
+ { 0x331, 0xaf, 0x2c9 }, /* macron below */
+ { 0x332, '_' }, /* low line */
+ { 0 }, /* real low line */
+ { 0x334, 0x2dc, 0x7e }, /* tilde overstrike */
+ { 0x335, '-' }, /* line overstrike */
+ { 0x336, '_' }, /* long line overstrike */
+ { 0x337, '/' }, /* short solidus overstrike */
+ { 0x338, '/' }, /* long solidus overstrike */ /* 0x338 */
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0x340, 0x60, 0x2cb }, /* tone mark, left of circumflex */ /* 0x340 */
+ { 0x341, 0xb4, 0x2ca }, /* tone mark, right of circumflex */
+ { 0x342, 0x2dc, 0x7e }, /* perispomeni (tilde) */
+ { 0x343, 0x2bc, ',' }, /* koronis */
+ { 0 }, /* dialytika tonos (two accents) */
+ { 0x37a }, /* ypogegrammeni */
+ { 0xffff }
+};
+
+int CanonicalCombiner(int uni) {
+ /* Translate spacing accents to combiners */
+ int j,k;
+
+ /* The above table will use these occasionally, but we don't want to */
+ /* translate them. They aren't accents */
+ if ( uni==',' || uni=='\'' || uni=='"' || uni=='~' || uni=='^' || uni=='-' ||
+ uni=='+' || uni=='.' )
+return( uni );
+
+ for ( j=0; accents[j][0]!=0xffff; ++j ) {
+ for ( k=0; k<4; ++k ) {
+ if ( uni==accents[j][k] ) {
+ uni = 0x300+j;
+ break;
+ }
+ }
+ if ( uni>=0x300 && uni<0x370 )
+ break;
+ }
+return( uni );
+}
+
+/* from cvundoes.c */
+
+int maxundoes=0;
+
+void UndoesFree(Undoes *undo) { }
+
+Undoes *SCPreserveState(SplineChar *sc,int dohints) { return NULL; }
+Undoes *BCPreserveState(BDFChar *bc) { return NULL; }
+Undoes *SCPreserveBackground(SplineChar *sc) { return NULL;}
+Undoes *SFPreserveGuide(SplineFont *sf) { return NULL; }
+Undoes *SCPreserveLayer(SplineChar *sc,int layer, int dohints) { return NULL; }
+
+void SCUndoSetLBearingChange(SplineChar *sc,int lbc) {}
+void PasteAnchorClassMerge(SplineFont *sf,AnchorClass *into,AnchorClass *from) {}
+void PasteRemoveSFAnchors(SplineFont *sf) {}
+void PasteRemoveAnchorClass(SplineFont *sf,AnchorClass *dying) {}
+void CopyBufferClearCopiedFrom(SplineFont *dying) { }
+void PasteIntoFV(FontView *fv,int pasteinto,real trans[6]) { }
+
+RefChar *CopyContainsRef(SplineFont *sf) { return NULL; }
+
+int getAdobeEnc(char *name) {
+ extern char *AdobeStandardEncoding[256];
+ int i;
+
+ for ( i=0; i<256; ++i )
+ if ( strcmp(name,AdobeStandardEncoding[i])==0 )
+ break;
+ if ( i==256 ) i = -1;
+return( i );
+}
+
+
+/* stubs from bvedit.c */
+
+void BCTrans(BDFFont *bdf,BDFChar *bc,BVTFunc *bvts,FontView *fv ) {
+}
+void BDFCharFindBounds(BDFChar *bc,IBounds *bb) {
+}
+void BCFlattenFloat(BDFChar *bc ) {
+}
+
+/* from combinations.c */
+
+
+int PSTContains(const char *components,const char *name) {
+ const char *pt;
+ int len = strlen(name);
+
+ for ( pt = strstr(components,name); pt!=NULL; pt = strstr(pt+len,name)) {
+ if (( pt==components || pt[-1]==' ') && (pt[len]==' ' || pt[len]=='\0'))
+return( true );
+ }
+return( false );
+}
+
+
+/* from mm.c (the stuff needed for Apple MM support) */
+
+
+char *MMAxisAbrev(char *axis_name) {
+ if ( strcmp(axis_name,"Weight")==0 )
+return( "wt" );
+ if ( strcmp(axis_name,"Width")==0 )
+return( "wd" );
+ if ( strcmp(axis_name,"OpticalSize")==0 )
+return( "op" );
+ if ( strcmp(axis_name,"Slant")==0 )
+return( "sl" );
+
+return( axis_name );
+}
+
+static double MMAxisUnmap(MMSet *mm,int axis,double ncv) {
+ struct axismap *axismap = &mm->axismaps[axis];
+ int j;
+
+ if ( ncv<=axismap->blends[0] )
+return(axismap->designs[0]);
+
+ for ( j=1; j<axismap->points; ++j ) {
+ if ( ncv<=axismap->blends[j]) {
+ double t = (ncv-axismap->blends[j-1])/(axismap->blends[j]-axismap->blends[j-1]);
+return( axismap->designs[j-1]+ t*(axismap->designs[j]-axismap->designs[j-1]) );
+ }
+ }
+
+return(axismap->designs[axismap->points-1]);
+}
+
+
+
+static char *_MMMakeFontname(MMSet *mm,real *normalized,char **fullname) {
+ char *pt, *pt2, *hyphen=NULL;
+ char *ret = NULL;
+ int i,j;
+
+ if ( mm->apple ) {
+ for ( i=0; i<mm->named_instance_count; ++i ) {
+ for ( j=0; j<mm->axis_count; ++j ) {
+ if (( normalized[j] == -1 &&
+ RealApprox(mm->named_instances[i].coords[j],mm->axismaps[j].min) ) ||
+ ( normalized[j] == 0 &&
+ RealApprox(mm->named_instances[i].coords[j],mm->axismaps[j].def) ) ||
+ ( normalized[j] == 1 &&
+ RealApprox(mm->named_instances[i].coords[j],mm->axismaps[j].max) ))
+ /* A match so far */;
+ else
+ break;
+ }
+ if ( j==mm->axis_count )
+ break;
+ }
+ if ( i!=mm->named_instance_count ) {
+ char *styles = PickNameFromMacName(mm->named_instances[i].names);
+ if ( styles==NULL )
+ styles = FindEnglishNameInMacName(mm->named_instances[i].names);
+ if ( styles!=NULL ) {
+ ret = galloc(strlen(mm->normal->familyname)+ strlen(styles)+3 );
+ strcpy(ret,mm->normal->familyname);
+ hyphen = ret+strlen(ret);
+ strcpy(hyphen," ");
+ strcpy(hyphen+1,styles);
+ free(styles);
+ }
+ }
+ }
+
+ if ( ret==NULL ) {
+ pt = ret = galloc(strlen(mm->normal->familyname)+ mm->axis_count*15 + 1);
+ strcpy(pt,mm->normal->familyname);
+ pt += strlen(pt);
+ *pt++ = '_';
+ for ( i=0; i<mm->axis_count; ++i ) {
+ if ( !mm->apple )
+ sprintf( pt, " %d%s", (int) rint(MMAxisUnmap(mm,i,normalized[i])),
+ MMAxisAbrev(mm->axes[i]));
+ else
+ sprintf( pt, " %.1f%s", MMAxisUnmap(mm,i,normalized[i]),
+ MMAxisAbrev(mm->axes[i]));
+ pt += strlen(pt);
+ }
+ if ( pt>ret && pt[-1]==' ' )
+ --pt;
+ *pt = '\0';
+ }
+
+ *fullname = ret;
+
+ ret = copy(ret);
+ for ( pt=*fullname, pt2=ret; *pt!='\0'; ++pt )
+ if ( pt==hyphen )
+ *pt2++ = '-';
+ else if ( *pt!=' ' )
+ *pt2++ = *pt;
+ *pt2 = '\0';
+return( ret );
+}
+
+char *MMMakeMasterFontname(MMSet *mm,int ipos,char **fullname) {
+return( _MMMakeFontname(mm,&mm->positions[ipos*mm->axis_count],fullname));
+}
+
+/* from splinesaveafm.c */
+
+
+void SFLigatureCleanup(SplineFont *sf) {
+ LigList *l, *next;
+ struct splinecharlist *scl, *sclnext;
+ int j;
+
+ for ( j=0; j<sf->glyphcnt; ++j ) if ( sf->glyphs[j]!=NULL ) {
+ for ( l = sf->glyphs[j]->ligofme; l!=NULL; l = next ) {
+ next = l->next;
+ for ( scl = l->components; scl!=NULL; scl = sclnext ) {
+ sclnext = scl->next;
+ chunkfree(scl,sizeof(struct splinecharlist));
+ }
+ if ( l->lig->temporary ) {
+ free(l->lig->u.lig.components);
+ chunkfree(l->lig,sizeof(PST));
+ }
+ free( l );
+ }
+ sf->glyphs[j]->ligofme = NULL;
+ }
+}
+
+
+void SFLigaturePrepare(SplineFont *sf) {
+ PST *lig;
+ LigList *ll;
+ int i,j,k,ch;
+ char *pt, *ligstart;
+ SplineChar *sc, *tsc;
+ struct splinecharlist *head, *last;
+ int ccnt, lcnt, lmax=20;
+ LigList **all = galloc(lmax*sizeof(LigList *));
+ ccnt = 0; /* for -Wall */
+ /* First clear out any old stuff */
+ for ( j=0; j<sf->glyphcnt; ++j ) if ( sf->glyphs[j]!=NULL )
+ sf->glyphs[j]->ligofme = NULL;
+
+ /* Attach all the ligatures to the first character of their components */
+ /* Figure out what the components are, and if they all exist */
+ /* we're only interested in the lig if all components are worth outputting */
+ for ( i=0 ; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sf->glyphs[i]) && sf->glyphs[i]->possub!=NULL ) {
+ for ( lig = sf->glyphs[i]->possub; lig!=NULL; lig=lig->next ) if ( lig->type==pst_ligature ) {
+ ligstart = lig->u.lig.components;
+ last = head = NULL; sc = NULL;
+ for ( pt = ligstart; *pt!='\0'; ) {
+ char *start = pt;
+ for ( ; *pt!='\0' && *pt!=' '; ++pt );
+ ch = *pt; *pt = '\0';
+ tsc = SFGetChar(sf,-1,start);
+ *pt = ch;
+ if ( tsc!=NULL ) {
+ if ( !SCWorthOutputting(tsc)) {
+ sc = NULL;
+ break;
+ }
+ if ( sc==NULL ) {
+ sc = tsc;
+ ccnt = 1;
+ } else {
+ struct splinecharlist *cur = chunkalloc(sizeof(struct splinecharlist));
+ if ( head==NULL )
+ head = cur;
+ else
+ last->next = cur;
+ last = cur;
+ cur->sc = tsc;
+ cur->next = NULL;
+ ++ccnt;
+ }
+ } else {
+ sc = NULL;
+ break;
+ }
+ while ( *pt==' ' ) ++pt;
+ }
+ if ( sc!=NULL ) {
+ ll = galloc(sizeof(LigList));
+ ll->lig = lig;
+ ll->next = sc->ligofme;
+ ll->first = sc;
+ ll->components = head;
+ ll->ccnt = ccnt;
+ sc->ligofme = ll;
+ } else {
+ while ( head!=NULL ) {
+ last = head->next;
+ chunkfree(head,sizeof(*head));
+ head = last;
+ }
+ }
+ }
+ }
+ for ( i=0 ; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL && sc->ligofme!=NULL ) {
+ for ( ll=sc->ligofme, lcnt=0; ll!=NULL; ll=ll->next, ++lcnt );
+ /* Finally, order the list so that the longest ligatures are first */
+ if ( lcnt>1 ) {
+ if ( lcnt>=lmax )
+ all = grealloc(all,(lmax=lcnt+30)*sizeof(LigList *));
+ for ( ll=sc->ligofme, k=0; ll!=NULL; ll=ll->next, ++k )
+ all[k] = ll;
+ for ( k=0; k<lcnt-1; ++k ) for ( j=k+1; j<lcnt; ++j )
+ if ( all[k]->ccnt<all[j]->ccnt ) {
+ ll = all[k];
+ all[k] = all[j];
+ all[j] = ll;
+ }
+ sc->ligofme = all[0];
+ for ( k=0; k<lcnt-1; ++k )
+ all[k]->next = all[k+1];
+ all[k]->next = NULL;
+ }
+ }
+ free( all );
+}
+
+/* from autohint.c, stubs for now */
+
+void FindBlues( SplineFont *sf, real blues[14], real otherblues[10]) {
+}
+
+void QuickBlues(SplineFont *_sf, BlueData *bd) {
+}
+
+void SplineFontAutoHint( SplineFont *sf) {
+}
+
+void SplineFontAutoHintRefs( SplineFont *_sf) {
+}
+
+void SplineCharAutoHint( SplineChar *sc, BlueData *bd ) {
+}
+
+
+/* from genttfinstrs.c */
+
+int TTF__getcvtval(SplineFont *sf,int val) {
+ int i;
+ struct ttf_table *cvt_tab = SFFindTable(sf,CHR('c','v','t',' '));
+
+ if ( cvt_tab==NULL ) {
+ cvt_tab = chunkalloc(sizeof(struct ttf_table));
+ cvt_tab->tag = CHR('c','v','t',' ');
+ cvt_tab->maxlen = 200;
+ cvt_tab->data = galloc(100*sizeof(short));
+ cvt_tab->next = sf->ttf_tables;
+ sf->ttf_tables = cvt_tab;
+ }
+ for ( i=0; sizeof(uint16)*i<cvt_tab->len; ++i ) {
+ int tval = (int16) memushort(cvt_tab->data,cvt_tab->len, sizeof(uint16)*i);
+ if ( val>=tval-1 && val<=tval+1 )
+return( i );
+ }
+ if ( sizeof(uint16)*i>=cvt_tab->maxlen ) {
+ if ( cvt_tab->maxlen==0 ) cvt_tab->maxlen = cvt_tab->len;
+ cvt_tab->maxlen += 200;
+ cvt_tab->data = grealloc(cvt_tab->data,cvt_tab->maxlen);
+ }
+ memputshort(cvt_tab->data,sizeof(uint16)*i,val);
+ cvt_tab->len += sizeof(uint16);
+return( i );
+}
+
+int TTF_getcvtval(SplineFont *sf,int val) {
+
+ /* by default sign is unimportant in the cvt */
+ /* For some instructions anyway, but not for MIAP so this routine has */
+ /* been broken in two. */
+ if ( val<0 ) val = -val;
+return( TTF__getcvtval(sf,val));
+}
+
+
+
+struct ttf_table *SFFindTable(SplineFont *sf,uint32 tag) {
+ struct ttf_table *tab;
+
+ for ( tab=sf->ttf_tables; tab!=NULL && tab->tag!=tag; tab=tab->next );
+return( tab );
+}
+
+void initforinstrs(SplineChar *sc) {
+}
diff --git a/Build/source/libs/luafontforge/src/luafflib.c b/Build/source/libs/luafontforge/src/luafflib.c
new file mode 100644
index 00000000000..cf252e682ea
--- /dev/null
+++ b/Build/source/libs/luafontforge/src/luafflib.c
@@ -0,0 +1,1769 @@
+/**
+* $Id $
+* @desc Support interface for fontforge 20070607
+* @version 1.0
+* @author Taco Hoekwater
+*/
+
+#include <stdio.h>
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "pfaedit.h"
+
+extern void LoadPrefs(void);
+
+extern char **gww_errors;
+extern int gww_error_count;
+extern void gwwv_errors_free (void);
+
+#define FONT_METATABLE "fontforge.splinefont"
+
+#define LUA_OTF_VERSION "0.2"
+
+char *possub_type_enum[] = {
+ "null", "position", "pair", "substitution",
+ "alternate", "multiple", "ligature", "lcaret",
+ "kerning", "vkerning", "anchors", "contextpos",
+ "contextsub", "chainpos", "chainsub","reversesub",
+ "max", "kernback", "vkernback"};
+
+#define LAST_POSSUB_TYPE_ENUM 18
+
+#define eight_nulls() NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+
+char *otf_lookup_type_enum[] = {
+ "gsub_start", "gsub_single", "gsub_multiple", "gsub_alternate",
+ "gsub_ligature", "gsub_context", "gsub_contextchain", NULL,
+ "gsub_reversecontextchain", NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*0x00F */
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(), NULL, NULL, NULL, NULL, NULL, "morx_indic", "morx_context", "morx_insert", /* 0x0FF*/
+ "gpos_start", "gpos_single", "gpos_pair", "gpos_cursive",
+ "gpos_mark2base", "gpos_mark2ligature", "gpos_mark2mark", "gpos_context",
+ "gpos_contextchain", NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x10F */
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, "kern_statemachine", /* 0x1FF*/
+};
+
+
+char *anchor_type_enum[] = { "mark", "basechar", "baselig", "basemark", "centry", "cexit", "max", NULL };
+#define MAX_ANCHOR_TYPE 7
+char *anchorclass_type_enum[] = { "mark", "mkmk", "curs", "mklg", NULL };
+char *glyph_class_enum[] = { "automatic", "none" ,"base", "ligature","mark", "component", NULL };
+
+
+#define check_isfont(L,b) (SplineFont **)luaL_checkudata(L,b,FONT_METATABLE)
+
+void handle_generic_pst (lua_State *L, struct generic_pst *pst); /* forward */
+void handle_generic_fpst (lua_State *L, struct generic_fpst *fpst); /* forward */
+void handle_kernclass (lua_State *L, struct kernclass *kerns);
+void handle_anchorclass (lua_State *L, struct anchorclass *anchor);
+
+
+void
+lua_ff_pushfont(lua_State *L, SplineFont *sf) {
+ SplineFont **a;
+ if (sf==NULL) {
+ lua_pushnil(L);
+ } else {
+ a = lua_newuserdata(L,sizeof(SplineFont *));
+ *a = sf;
+ luaL_getmetatable(L,FONT_METATABLE);
+ lua_setmetatable(L,-2);
+ }
+ return;
+}
+
+
+static int
+ff_open (lua_State *L) {
+ SplineFont *sf;
+ const char *fontname;
+ FILE *l;
+ char s[511];
+ size_t len;
+ int args,i ;
+ int openflags = 1;
+ fontname = luaL_checkstring(L,1);
+ /* test fontname for existance */
+ if ((l = fopen(fontname,"r"))) {
+ fclose(l);
+ } else {
+ lua_pushfstring(L,"font loading failed for %s (read error)\n", fontname);
+ lua_error(L);
+ }
+ args = lua_gettop(L);
+ if (args>=2) {
+ if (lua_isstring(L,2)) {
+ if (*(fontname+strlen(fontname))!=')') {
+ /* possibly fails for embedded parens in the font name */
+ snprintf(s,511,"%s(%s)", fontname, lua_tolstring(L,2,&len));
+ if (len==0) {
+ snprintf(s,511,"%s", fontname);
+ }
+ }
+ }
+ } else {
+ snprintf(s,511,"%s", fontname);
+ }
+ if (strlen(s)>0) {
+ sf = ReadSplineFont((char *)s,openflags);
+ if (sf==NULL) {
+ lua_pushfstring(L,"font loading failed for %s\n", fontname);
+ lua_error(L);
+ } else {
+ lua_ff_pushfont(L,sf);
+ if (gww_error_count>0) {
+ lua_newtable(L);
+ for (i=0;i<gww_error_count;i++) {
+ lua_pushstring(L,gww_errors[i]);
+ lua_rawseti(L,-2,(i+1));
+ }
+ gwwv_errors_free();
+ } else {
+ lua_pushnil(L);
+ }
+ }
+ } else {
+ lua_pushfstring(L,"font loading failed: empty string given\n", fontname);
+ lua_error(L);
+ }
+ return 2;
+}
+
+
+static int
+ff_close (lua_State *L) {
+ SplineFont **sf;
+ /*fputs("ff_close called",stderr);*/
+ sf = check_isfont(L,1);
+ if (*sf!=NULL) {
+ SplineFontFree(*sf);
+ *sf = NULL;
+ }
+ return 0;
+}
+
+static int
+ff_apply_featurefile (lua_State *L) {
+ SplineFont **sf;
+ char *fname;
+ sf = check_isfont(L,1);
+ fname = (char *)luaL_checkstring(L,2);
+ SFApplyFeatureFilename(*sf,fname);
+ return 0;
+}
+
+static int
+ff_apply_afmfile (lua_State *L) {
+ SplineFont **sf;
+ char *fname;
+ sf = check_isfont(L,1);
+ fname = (char *)luaL_checkstring(L,2);
+ CheckAfmOfPostscript(*sf,fname,(*sf)->map);
+
+ return 0;
+}
+
+
+
+static void
+dump_intfield (lua_State *L, char *name, long int field) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,name);
+ lua_pushnumber(L,field);
+ lua_rawset(L,-3);
+}
+
+#define dump_cond_intfield(a,b,c) if ((c)!=0) { dump_intfield ((a),(b),(c)); }
+
+
+static void
+dump_stringfield (lua_State *L, char *name, char *field) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,name);
+ lua_pushstring(L,field);
+ lua_rawset(L,-3);
+}
+
+static void
+dump_char_ref (lua_State *L, struct splinechar *spchar) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,"char");
+ lua_pushstring(L,spchar->name);
+ lua_rawset(L,-3);
+}
+
+
+static void
+dump_lstringfield (lua_State *L, char *name, char *field, int len) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,name);
+ lua_pushlstring(L,field,len);
+ lua_rawset(L,-3);
+}
+
+static void
+dump_enumfield (lua_State *L, char *name, int fid, char **fields) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,name);
+ lua_pushstring(L,fields[fid]);
+ lua_rawset(L,-3);
+}
+
+static void
+dump_floatfield (lua_State *L, char *name, double field) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,name);
+ lua_pushnumber(L,field);
+ lua_rawset(L,-3);
+}
+
+static char tag_string [5] = {0};
+
+static char *make_tag_string (unsigned int field) {
+ tag_string[0] = (field&0xFF000000) >> 24;
+ tag_string[1] = (field&0x00FF0000) >> 16;
+ tag_string[2] = (field&0x0000FF00) >> 8;
+ tag_string[3] = (field&0x000000FF);
+ return (char *)tag_string;
+}
+
+static void
+dump_tag (lua_State *L, char *name, unsigned int field) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,name);
+ lua_pushlstring(L,make_tag_string(field),4);
+ lua_rawset(L,-3);
+}
+
+#define NESTED_TABLE(a,b,c) { \
+ int k = 1; \
+ next = b; \
+ while (next != NULL) { \
+ lua_checkstack(L,2); \
+ lua_pushnumber(L,k); k++; \
+ lua_createtable(L,0,c); \
+ a(L, next); \
+ lua_rawset(L,-3); \
+ next = next->next; \
+ } }
+
+void
+do_handle_scriptlanglist (lua_State *L, struct scriptlanglist *sl) {
+ int k;
+ dump_tag(L,"script", sl->script);
+
+ lua_checkstack(L,3);
+ lua_newtable(L);
+ for (k=0;k<MAX_LANG;k++) {
+ if (sl->langs[k] != 0) {
+ lua_pushnumber(L,(k+1));
+ lua_pushstring(L,make_tag_string(sl->langs[k]));
+ lua_rawset(L,-3);
+ }
+ }
+
+ if (sl->lang_cnt>=MAX_LANG) {
+ for (k=MAX_LANG;k<sl->lang_cnt;k++) {
+ lua_pushnumber(L,(k+1));
+ lua_pushstring(L,make_tag_string(sl->morelangs[k-MAX_LANG]));
+ lua_rawset(L,-3);
+ }
+ }
+ lua_setfield(L,-2,"langs");
+}
+
+void
+handle_scriptlanglist (lua_State *L, struct scriptlanglist *sll) {
+ struct scriptlanglist *next;
+ NESTED_TABLE(do_handle_scriptlanglist,sll,4);
+}
+
+void
+do_handle_featurescriptlanglist (lua_State *L, struct featurescriptlanglist *features) {
+ dump_tag (L,"tag",features->featuretag);
+ lua_newtable(L);
+ handle_scriptlanglist(L, features->scripts);
+ lua_setfield(L,-2,"scripts");
+ dump_cond_intfield (L,"ismac",features->ismac);
+}
+
+void
+handle_featurescriptlanglist (lua_State *L, struct featurescriptlanglist *features) {
+ struct featurescriptlanglist *next;
+ NESTED_TABLE(do_handle_featurescriptlanglist,features,3);
+}
+
+void
+do_handle_lookup_subtable (lua_State *L, struct lookup_subtable *subtable) {
+
+ dump_stringfield(L,"name", subtable->subtable_name);
+ dump_stringfield(L,"suffix", subtable->suffix);
+
+ /* struct otlookup *lookup; */ /* this is the parent */
+
+ /* dump_intfield (L,"unused", subtable->unused); */
+ /* The next one is true if there is no fpst, false otherwise */
+ /*
+ dump_intfield (L,"per_glyph_pst_or_kern",subtable->per_glyph_pst_or_kern);
+ */
+ dump_cond_intfield (L,"anchor_classes", subtable->anchor_classes);
+ dump_cond_intfield (L,"vertical_kerning", subtable->vertical_kerning);
+
+ if (subtable->kc != NULL) {
+ lua_newtable(L);
+ handle_kernclass(L, subtable->kc);
+ lua_setfield(L,-2, "kernclass");
+ }
+
+ /* generic_asm *sm; */ /* TODO, Apple state machine */
+
+ /* int subtable_offset; */ /* used by OTF file generation */
+ /* int32 *extra_subtables; */ /* used by OTF file generation */
+}
+
+/* subtables have to be dumped as an array because the ordering
+ * has to be preserved
+ */
+
+void
+handle_lookup_subtable (lua_State *L, struct lookup_subtable *subtable) {
+ struct lookup_subtable *next;
+ NESTED_TABLE(do_handle_lookup_subtable,subtable,2);
+}
+
+void
+do_handle_lookup (lua_State *L, struct otlookup *lookup ) {
+
+ dump_enumfield (L,"type", lookup->lookup_type, otf_lookup_type_enum);
+
+ lua_newtable(L);
+ if (lookup->lookup_flags & pst_r2l) {
+ lua_pushstring(L,"r2l"); lua_pushboolean(L,1); lua_rawset(L,-3);
+ }
+ if (lookup->lookup_flags & pst_ignorebaseglyphs) {
+ lua_pushstring(L,"ignorebaseglyphs"); lua_pushboolean(L,1); lua_rawset(L,-3);
+ }
+ if (lookup->lookup_flags & pst_ignoreligatures) {
+ lua_pushstring(L,"ignoreligatures"); lua_pushboolean(L,1); lua_rawset(L,-3);
+ }
+ if (lookup->lookup_flags & pst_ignorecombiningmarks) {
+ lua_pushstring(L,"ignorecombiningmarks"); lua_pushboolean(L,1); lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"flags");
+
+
+ dump_stringfield (L,"name", lookup->lookup_name);
+
+ if (lookup->features != NULL) {
+ lua_newtable(L);
+ handle_featurescriptlanglist(L,lookup->features);
+ lua_setfield(L,-2,"features");
+ }
+
+ if (lookup->subtables != NULL) {
+ lua_newtable(L);
+ handle_lookup_subtable(L,lookup->subtables);
+ lua_setfield(L,-2,"subtables");
+ }
+
+ /* dump_intfield (L,"unused", lookup->unused); */
+ /* dump_intfield (L,"empty", lookup->empty); */
+ /* dump_intfield (L,"def_lang_checked", lookup->def_lang_checked); */
+ /* dump_intfield (L,"def_lang_found", lookup->def_lang_found); */
+ /* dump_intfield (L,"subcnt", lookup->subcnt); */
+ /* dump_intfield (L,"index", lookup->lookup_index); */ /* identical to array index */
+ /* dump_intfield (L,"lookup_offset", lookup->lookup_offset); */
+ /* dump_intfield (L,"lookup_length", lookup->lookup_length); */
+ /* dump_stringfield(L,"tempname", lookup->tempname); */
+
+}
+
+void
+handle_lookup (lua_State *L, struct otlookup *lookup ) {
+ struct otlookup *next;
+ NESTED_TABLE(do_handle_lookup,lookup,18); /* 18 is a guess */
+}
+
+void
+do_handle_kernpair (lua_State *L, struct kernpair *kp) {
+
+ if (kp->sc != NULL)
+ dump_char_ref(L, kp->sc);
+ dump_intfield(L,"off", kp->off);
+ if (kp->subtable!=NULL) {
+ dump_stringfield(L,"lookup",kp->subtable->subtable_name);
+ }
+}
+
+void
+handle_kernpair (lua_State *L, struct kernpair *kp) {
+ struct kernpair *next;
+ NESTED_TABLE(do_handle_kernpair,kp,4);
+}
+
+void
+handle_splinecharlist (lua_State *L, struct splinecharlist *scl) {
+
+ struct splinecharlist *next = scl;
+ int k = 1;
+ lua_checkstack(L,10);
+ while( next != NULL) {
+ if (next->sc != NULL) {
+ lua_pushnumber(L,k); k++;
+ lua_pushstring(L,next->sc->name);
+ lua_rawset(L,-3);
+ }
+ next = next->next;
+ }
+}
+
+
+#define interesting_vr(a) (((a)->xoff!=0) || ((a)->yoff!=0) || ((a)->h_adv_off!=0) || ((a)->v_adv_off!=0))
+
+void handle_vr (lua_State *L, struct vr *pos) {
+
+ dump_cond_intfield(L,"x", pos->xoff);
+ dump_cond_intfield(L,"y", pos->yoff);
+ dump_cond_intfield(L,"h", pos->h_adv_off);
+ dump_cond_intfield(L,"v", pos->v_adv_off);
+
+}
+
+void
+do_handle_generic_pst (lua_State *L, struct generic_pst *pst) {
+ int k;
+ if (pst->type>LAST_POSSUB_TYPE_ENUM) {
+ dump_tag(L,"type", pst->type);
+ } else {
+ dump_enumfield(L,"type", pst->type, possub_type_enum);
+ }
+
+ /*dump_intfield(L,"macfeature", pst->macfeature); */
+
+ lua_checkstack(L,4);
+ lua_pushstring(L,"specification");
+ lua_createtable(L,0,4);
+ if (pst->type == pst_position) {
+ handle_vr (L, &pst->u.pos);
+ } else if (pst->type == pst_pair) {
+ dump_stringfield(L,"paired",pst->u.pair.paired);
+ if (pst->u.pair.vr != NULL) {
+ lua_pushstring(L,"offsets");
+ lua_createtable(L,2,0);
+ if (interesting_vr(pst->u.pair.vr)) {
+ lua_createtable(L,0,4);
+ handle_vr (L, pst->u.pair.vr);
+ lua_rawseti(L,-2,1);
+ }
+ if (interesting_vr(pst->u.pair.vr+1)) {
+ lua_createtable(L,0,4);
+ handle_vr (L, pst->u.pair.vr+1);
+ lua_rawseti(L,-2,2);
+ }
+ lua_rawset(L,-3);
+ }
+ } else if (pst->type == pst_substitution) {
+ dump_stringfield(L,"variant",pst->u.subs.variant);
+ } else if (pst->type == pst_alternate) {
+ dump_stringfield(L,"components",pst->u.mult.components);
+ } else if (pst->type == pst_multiple) {
+ dump_stringfield(L,"components",pst->u.alt.components);
+ } else if (pst->type == pst_ligature) {
+ dump_stringfield(L,"components",pst->u.lig.components);
+ if (pst->u.lig.lig != NULL) {
+ dump_char_ref(L,pst->u.lig.lig);
+ }
+ } else if (pst->type == pst_lcaret) {
+ for (k=0;k<pst->u.lcaret.cnt;k++) {
+ lua_pushnumber(L,(k+1));
+ lua_pushnumber(L,pst->u.lcaret.carets[k]);
+ lua_rawset(L,-3);
+ }
+ }
+ lua_rawset(L,-3);
+}
+
+
+void
+handle_generic_pst (lua_State *L, struct generic_pst *pst) {
+ struct generic_pst *next;
+ int k;
+ int l = 1;
+ next = pst;
+ /* most likely everything arrives in proper order. But to prevent
+ * surprises, better do this is the proper way
+ */
+ while (next != NULL) {
+ if (next->subtable !=NULL &&
+ next->subtable->subtable_name !=NULL) {
+ lua_checkstack(L,3); /* just in case */
+ lua_getfield(L,-1,next->subtable->subtable_name);
+ if (!lua_istable(L,-1)) {
+ lua_pop(L,1);
+ lua_newtable(L);
+ lua_setfield(L,-2,next->subtable->subtable_name);
+ lua_getfield(L,-1,next->subtable->subtable_name);
+ }
+ k = lua_objlen(L,-1) + 1;
+ lua_pushnumber(L,k);
+ lua_createtable(L,0,4);
+ do_handle_generic_pst(L, next);
+ lua_rawset(L,-3);
+ next = next->next;
+ lua_pop(L,1); /* pop the subtable */
+ } else {
+ /* Found a pst without subtable, or without subtable name */
+ lua_pushnumber(L,l); l++;
+ lua_createtable(L,0,4);
+ do_handle_generic_pst(L, next);
+ lua_rawset(L,-3);
+ next = next->next;
+ }
+ }
+}
+
+void
+do_handle_liglist (lua_State *L, struct liglist *ligofme) {
+ lua_checkstack(L,2);
+ if(ligofme->lig != NULL) {
+ lua_createtable(L,0,6);
+ handle_generic_pst (L,ligofme->lig);
+ lua_setfield(L,-2,"lig");
+ }
+ dump_char_ref(L,ligofme->first);
+ if (ligofme->components != NULL) {
+ lua_newtable(L);
+ handle_splinecharlist (L,ligofme->components);
+ lua_setfield(L,-2,"components");
+ }
+ dump_intfield(L,"ccnt",ligofme->ccnt);
+}
+
+void
+handle_liglist (lua_State *L, struct liglist *ligofme) {
+ struct liglist *next;
+ NESTED_TABLE(do_handle_liglist,ligofme,3);
+}
+
+/*
+if glyph.anchor then
+ local t = { }
+ for k,v in ipairs(glyph.anchor) do
+ if not t[v.type] then t[v.type] = { } end
+ t[v.type][v.anchor] = v
+ v.anchor = nil
+ v.type = nil
+ end
+ glyph.anchor = t
+ end
+*/
+
+void
+do_handle_anchorpoint (lua_State *L, struct anchorpoint *anchor) {
+
+ if (anchor->anchor==NULL) {
+ return;
+ }
+ if (anchor->type>=0 && anchor->type <= MAX_ANCHOR_TYPE ) {
+ lua_pushstring(L,anchor_type_enum[anchor->type]);
+ } else {
+ lua_pushstring(L,"Anchorpoint has an unknown type!");
+ lua_error(L);
+ }
+
+ lua_rawget(L,-2);
+ if (!lua_istable(L,-1)) {
+ /* create the table first */
+ lua_pop(L,1);
+ lua_pushstring(L,anchor_type_enum[anchor->type]);
+ lua_pushvalue(L,-1);
+ lua_newtable(L);
+ lua_rawset(L,-4);
+ lua_rawget(L,-2);
+ }
+ /* now the 'type' table is top of stack */
+ if (anchor->type==at_baselig) {
+ lua_pushstring(L,anchor->anchor->name);
+ lua_rawget(L,-2);
+ if (!lua_istable(L,-1)) {
+ /* create the table first */
+ lua_pop(L,1);
+ lua_pushstring(L,anchor->anchor->name);
+ lua_pushvalue(L,-1);
+ lua_newtable(L);
+ lua_rawset(L,-4);
+ lua_rawget(L,-2);
+ }
+ lua_newtable(L);
+ dump_intfield(L,"x", anchor->me.x);
+ dump_intfield(L,"y", anchor->me.y);
+
+ if (anchor->has_ttf_pt)
+ dump_intfield(L,"ttf_pt_index", anchor->ttf_pt_index);
+ /* dump_intfield(L,"lig_index", anchor->lig_index); */
+ lua_rawseti(L,-2,(anchor->lig_index+1));
+ lua_pop(L,1);
+ } else {
+ lua_pushstring(L,anchor->anchor->name);
+ lua_newtable(L);
+ dump_intfield(L,"x", anchor->me.x);
+ dump_intfield(L,"y", anchor->me.y);
+
+ if (anchor->has_ttf_pt)
+ dump_intfield(L,"ttf_pt_index", anchor->ttf_pt_index);
+ lua_rawset(L,-3);
+ }
+ lua_pop(L,1);
+}
+
+void
+handle_anchorpoint (lua_State *L, struct anchorpoint *anchor) {
+ struct anchorpoint *next;
+ next = anchor;
+ while (next != NULL) {
+ do_handle_anchorpoint(L, next);
+ next = next->next;
+ }
+}
+
+void
+handle_splinechar (lua_State *L,struct splinechar *glyph, int hasvmetrics) {
+
+ dump_stringfield(L,"name", glyph->name);
+ dump_intfield(L,"unicode", glyph->unicodeenc);
+ lua_createtable(L,4,0);
+ lua_pushnumber(L,1); lua_pushnumber(L,glyph->xmin); lua_rawset(L,-3);
+ lua_pushnumber(L,2); lua_pushnumber(L,glyph->ymin); lua_rawset(L,-3);
+ lua_pushnumber(L,3); lua_pushnumber(L,glyph->xmax); lua_rawset(L,-3);
+ lua_pushnumber(L,4); lua_pushnumber(L,glyph->ymax); lua_rawset(L,-3);
+ lua_setfield(L,-2,"boundingbox");
+
+ /*dump_intfield(L,"orig_pos", glyph->orig_pos);*/
+ if (hasvmetrics)
+ dump_intfield(L,"vwidth", glyph->vwidth);
+ dump_intfield(L,"width", glyph->width);
+
+ dump_cond_intfield(L,"lsidebearing", glyph->lsidebearing);
+
+ /* Layer layers[2]; */ /* TH Not used */
+ /* int layer_cnt; */ /* TH Not used */
+ /* StemInfo *hstem; */ /* TH Not used */
+ /* StemInfo *vstem; */ /* TH Not used */
+ /* DStemInfo *dstem; */ /* TH Not used */
+
+ /* MinimumDistance *md; */ /* TH Not used */
+ /* struct charview *views; */ /* TH Not used */
+ /* struct charinfo *charinfo; */ /* TH ? (charinfo.c) */
+
+ /* struct splinefont *parent; */ /* TH Not used */
+
+ /*
+
+ */
+ if (glyph->glyph_class>0) {
+ dump_enumfield(L,"class", glyph->glyph_class, glyph_class_enum);
+ }
+ /* TH: internal fontforge stuff
+ dump_intfield(L,"ticked", glyph->ticked);
+ dump_intfield(L,"widthset", glyph->widthset);
+ dump_intfield(L,"ttf_glyph", glyph->ttf_glyph);
+ dump_intfield(L,"changed", glyph->changed);
+ dump_intfield(L,"changedsincelasthinted", glyph->changedsincelasthinted);
+ dump_intfield(L,"manualhints", glyph->manualhints);
+ dump_intfield(L,"changed_since_autosave", glyph->changed_since_autosave);
+ dump_intfield(L,"vconflicts", glyph->vconflicts);
+ dump_intfield(L,"hconflicts", glyph->hconflicts);
+ dump_intfield(L,"anyflexes", glyph->anyflexes);
+ dump_intfield(L,"searcherdummy", glyph->searcherdummy);
+ dump_intfield(L,"changed_since_search", glyph->changed_since_search);
+ dump_intfield(L,"wasopen", glyph->wasopen);
+ dump_intfield(L,"namechanged", glyph->namechanged);
+ dump_intfield(L,"blended", glyph->blended);
+ dump_intfield(L,"unused_so_far", glyph->unused_so_far);
+ dump_intfield(L,"numberpointsbackards", glyph->numberpointsbackards);
+ dump_intfield(L,"instructions_out_of_date", glyph->instructions_out_of_date);
+ dump_intfield(L,"complained_about_ptnums", glyph->complained_about_ptnums);
+
+ uint8 *ttf_instrs;
+ int16 ttf_instrs_len;
+ int16 countermask_cnt;
+ HintMask *countermasks;
+ */
+
+ if (glyph->kerns != NULL) {
+ lua_newtable(L);
+ handle_kernpair(L,glyph->kerns);
+ lua_setfield(L,-2,"kerns");
+ }
+ if (glyph->vkerns != NULL) {
+ lua_newtable(L);
+ handle_kernpair(L,glyph->vkerns);
+ lua_setfield(L,-2,"vkerns");
+ }
+
+ if (glyph->dependents != NULL) {
+ lua_newtable(L);
+ handle_splinecharlist(L,glyph->dependents);
+ lua_setfield(L,-2,"dependents");
+
+ }
+ if (glyph->possub != NULL) {
+ lua_newtable(L);
+ handle_generic_pst(L,glyph->possub);
+ lua_setfield(L,-2,"lookups");
+ }
+
+ if (glyph->ligofme != NULL) {
+ lua_newtable(L);
+ handle_liglist(L,glyph->ligofme);
+ lua_setfield(L,-2,"ligatures");
+ }
+
+ if (glyph->comment != NULL)
+ dump_stringfield(L,"comment", glyph->comment);
+
+ /* Color color; */ /* dont care */
+
+ if (glyph->anchor != NULL) {
+ lua_newtable(L);
+ handle_anchorpoint(L,glyph->anchor);
+ lua_setfield(L,-2,"anchors");
+ }
+
+ if (glyph->tex_height != TEX_UNDEF)
+ dump_intfield(L,"tex_height", glyph->tex_height);
+ if (glyph->tex_depth != TEX_UNDEF)
+ dump_intfield(L,"tex_depth", glyph->tex_depth);
+ if (glyph->tex_sub_pos != TEX_UNDEF)
+ dump_intfield(L,"tex_sub_pos", glyph->tex_sub_pos);
+ if (glyph->tex_super_pos != TEX_UNDEF)
+ dump_intfield(L,"tex_super_pos", glyph->tex_super_pos);
+
+ /* struct altuni { struct altuni *next; int unienc; } *altuni; */
+}
+
+char *panose_values_0[] = { "Any", "No Fit", "Text and Display", "Script", "Decorative", "Pictorial" };
+
+char *panose_values_1[] = { "Any", "No Fit", "Cove", "Obtuse Cove", "Square Cove", "Obtuse Square Cove",
+ "Square", "Thin", "Bone", "Exaggerated", "Triangle", "Normal Sans",
+ "Obtuse Sans", "Perp Sans", "Flared", "Rounded" } ;
+
+char *panose_values_2[] = { "Any", "No Fit", "Very Light", "Light", "Thin", "Book",
+ "Medium", "Demi", "Bold", "Heavy", "Black", "Nord" } ;
+
+char *panose_values_3[] = { "Any", "No Fit", "Old Style", "Modern", "Even Width",
+ "Expanded", "Condensed", "Very Expanded", "Very Condensed", "Monospaced" };
+
+char *panose_values_4[] = { "Any", "No Fit", "None", "Very Low", "Low", "Medium Low",
+ "Medium", "Medium High", "High", "Very High" };
+
+char *panose_values_5[] = { "Any", "No Fit", "Gradual/Diagonal", "Gradual/Transitional","Gradual/Vertical",
+ "Gradual/Horizontal", "Rapid/Vertical", "Rapid/Horizontal", "Instant/Vertical" };
+
+char *panose_values_6[] = {"Any","No Fit","Straight Arms/Horizontal","Straight Arms/Wedge","Straight Arms/Vertical",
+ "Straight Arms/Single Serif","Straight Arms/Double Serif","Non-Straight Arms/Horizontal",
+ "Non-Straight Arms/Wedge","Non-Straight Arms/Vertical","Non-Straight Arms/Single Serif",
+ "Non-Straight Arms/Double Serif" };
+
+char *panose_values_7[] = { "Any", "No Fit","Normal/Contact","Normal/Weighted","Normal/Boxed","Normal/Flattened",
+ "Normal/Rounded","Normal/Off Center","Normal/Square","Oblique/Contact","Oblique/Weighted",
+ "Oblique/Boxed","Oblique/Flattened","Oblique/Rounded","Oblique/Off Center","Oblique/Square" };
+
+char *panose_values_8[] = { "Any","No Fit","Standard/Trimmed","Standard/Pointed","Standard/Serifed","High/Trimmed",
+ "High/Pointed","High/Serifed","Constant/Trimmed","Constant/Pointed","Constant/Serifed",
+ "Low/Trimmed","Low/Pointed","Low/Serifed"};
+
+char *panose_values_9[] = { "Any","No Fit", "Constant/Small", "Constant/Standard",
+ "Constant/Large", "Ducking/Small", "Ducking/Standard", "Ducking/Large" };
+
+
+void
+handle_pfminfo (lua_State *L, struct pfminfo pfm) {
+
+ dump_intfield (L, "pfmset", pfm.pfmset);
+ dump_intfield (L, "winascent_add", pfm.winascent_add);
+ dump_intfield (L, "windescent_add", pfm.windescent_add);
+ dump_intfield (L, "hheadascent_add", pfm.hheadascent_add);
+ dump_intfield (L, "hheaddescent_add", pfm.hheaddescent_add);
+ dump_intfield (L, "typoascent_add", pfm.typoascent_add);
+ dump_intfield (L, "typodescent_add", pfm.typodescent_add);
+ dump_intfield (L, "subsuper_set", pfm.subsuper_set);
+ dump_intfield (L, "panose_set", pfm.panose_set);
+ dump_intfield (L, "hheadset", pfm.hheadset);
+ dump_intfield (L, "vheadset", pfm.vheadset);
+ dump_intfield (L, "pfmfamily", pfm.pfmfamily);
+ dump_intfield (L, "weight", pfm.weight);
+ dump_intfield (L, "width", pfm.width);
+ dump_intfield (L, "avgwidth", pfm.avgwidth);
+ dump_intfield (L, "firstchar", pfm.firstchar);
+ dump_intfield (L, "lastchar", pfm.lastchar);
+ lua_createtable(L,0,10);
+ dump_enumfield(L,"familytype", pfm.panose[0], panose_values_0);
+ dump_enumfield(L,"serifstyle", pfm.panose[1], panose_values_1);
+ dump_enumfield(L,"weight", pfm.panose[2], panose_values_2);
+ dump_enumfield(L,"proportion", pfm.panose[3], panose_values_3);
+ dump_enumfield(L,"contrast", pfm.panose[4], panose_values_4);
+ dump_enumfield(L,"strokevariation", pfm.panose[5], panose_values_5);
+ dump_enumfield(L,"armstyle", pfm.panose[6], panose_values_6);
+ dump_enumfield(L,"letterform", pfm.panose[7], panose_values_7);
+ dump_enumfield(L,"midline", pfm.panose[8], panose_values_8);
+ dump_enumfield(L,"xheight", pfm.panose[9], panose_values_9);
+ lua_setfield (L,-2,"panose");
+
+ dump_intfield (L, "fstype", pfm.fstype);
+ dump_intfield (L, "linegap", pfm.linegap);
+ dump_intfield (L, "vlinegap", pfm.vlinegap);
+ dump_intfield (L, "hhead_ascent", pfm.hhead_ascent);
+ dump_intfield (L, "hhead_descent", pfm.hhead_descent);
+ dump_intfield (L, "hhead_descent", pfm.hhead_descent);
+ dump_intfield (L, "os2_typoascent", pfm.os2_typoascent );
+ dump_intfield (L, "os2_typodescent", pfm.os2_typodescent );
+ dump_intfield (L, "os2_typolinegap", pfm.os2_typolinegap );
+ dump_intfield (L, "os2_winascent", pfm.os2_winascent );
+ dump_intfield (L, "os2_windescent", pfm.os2_windescent );
+ dump_intfield (L, "os2_subxsize", pfm.os2_subxsize );
+ dump_intfield (L, "os2_subysize", pfm.os2_subysize );
+ dump_intfield (L, "os2_subxoff", pfm.os2_subxoff );
+ dump_intfield (L, "os2_subyoff", pfm.os2_subyoff );
+ dump_intfield (L, "os2_supxsize", pfm.os2_supxsize );
+ dump_intfield (L, "os2_supysize", pfm.os2_supysize );
+ dump_intfield (L, "os2_supxoff", pfm.os2_supxoff );
+ dump_intfield (L, "os2_supyoff", pfm.os2_supyoff );
+ dump_intfield (L, "os2_strikeysize", pfm.os2_strikeysize );
+ dump_intfield (L, "os2_strikeypos", pfm.os2_strikeypos );
+ dump_lstringfield (L, "os2_vendor", pfm.os2_vendor, 4);
+ dump_intfield (L, "os2_family_class", pfm.os2_family_class);
+ dump_intfield (L, "os2_xheight", pfm.os2_xheight);
+ dump_intfield (L, "os2_capheight", pfm.os2_capheight);
+ dump_intfield (L, "os2_defaultchar", pfm.os2_defaultchar);
+ dump_intfield (L, "os2_breakchar", pfm.os2_breakchar);
+}
+
+
+void
+do_handle_enc (lua_State *L, struct enc *enc) {
+ int i;
+
+ dump_stringfield(L,"enc_name", enc->enc_name);
+ dump_intfield (L,"char_cnt", enc->char_cnt);
+
+ lua_checkstack(L,4);
+ if (enc->char_cnt && enc->unicode != NULL) {
+ lua_createtable(L,enc->char_cnt,1);
+ for (i=0;i<enc->char_cnt;i++) {
+ lua_pushnumber(L,i);
+ lua_pushnumber(L,enc->unicode[i]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"unicode");
+ }
+
+ if (enc->char_cnt && enc->psnames != NULL) {
+ lua_createtable(L,enc->char_cnt,1);
+ for (i=0;i<enc->char_cnt;i++) {
+ lua_pushnumber(L,i);
+ lua_pushstring(L,enc->psnames[i]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"psnames");
+ }
+ dump_intfield (L,"builtin", enc->builtin );
+ dump_intfield (L,"hidden", enc->hidden );
+ dump_intfield (L,"only_1byte", enc->only_1byte );
+ dump_intfield (L,"has_1byte", enc->has_1byte );
+ dump_intfield (L,"has_2byte", enc->has_2byte );
+ dump_cond_intfield (L,"is_unicodebmp", enc->is_unicodebmp );
+ dump_cond_intfield (L,"is_unicodefull", enc->is_unicodefull );
+ dump_cond_intfield (L,"is_custom", enc->is_custom );
+ dump_cond_intfield (L,"is_original", enc->is_original );
+ dump_cond_intfield (L,"is_compact", enc->is_compact );
+ dump_cond_intfield (L,"is_japanese", enc->is_japanese );
+ dump_cond_intfield (L,"is_korean", enc->is_korean );
+ dump_cond_intfield (L,"is_tradchinese", enc->is_tradchinese );
+ dump_cond_intfield (L,"is_simplechinese", enc->is_simplechinese);
+
+ if (enc->iso_2022_escape_len > 0) {
+ dump_lstringfield (L,"iso_2022_escape", enc->iso_2022_escape, enc->iso_2022_escape_len);
+ }
+ dump_intfield (L,"low_page", enc->low_page);
+ dump_intfield(L,"high_page", enc->high_page);
+
+ dump_stringfield(L,"iconv_name", enc->iconv_name);
+
+ /* TH: iconv internal information, ignorable */
+ /* iconv_t *tounicode; */
+ /* iconv_t *fromunicode; */
+ /* int (*tounicode_func)(int); */
+ /* int (*fromunicode_func)(int); */
+
+ /*dump_intfield (L,"is_temporary", enc->is_temporary);*/
+ dump_intfield (L,"char_max", enc->char_max);
+
+}
+
+void
+handle_enc (lua_State *L, struct enc *enc) {
+ struct enc *next;
+ NESTED_TABLE(do_handle_enc,enc,24);
+}
+
+void
+handle_encmap (lua_State *L, struct encmap *map) {
+ int i;
+ dump_intfield(L,"enccount", map->enccount) ;
+ dump_intfield(L,"encmax", map->encmax) ;
+ dump_intfield(L,"backmax", map->backmax) ;
+ /*dump_intfield(L,"ticked", map->ticked) ;*/
+ if (map->remap != NULL) {
+ lua_newtable(L);
+ dump_intfield(L,"firstenc", map->remap->firstenc) ;
+ dump_intfield(L,"lastenc", map->remap->lastenc) ;
+ dump_intfield(L,"infont", map->remap->infont) ;
+ lua_setfield(L,-2,"remap");
+ }
+ lua_checkstack(L,4);
+ if (map->encmax > 0 && map->map != NULL) {
+ lua_createtable(L,map->encmax,1);
+ for (i=0;i<map->encmax;i++) {
+ if (map->map[i]!=-1) {
+ lua_pushnumber(L,i);
+ lua_pushnumber(L,map->map[i]);
+ lua_rawset(L,-3);
+ }
+ }
+ lua_setfield(L,-2,"map");
+ }
+
+ if (map->backmax > 0 && map->backmap != NULL) {
+ lua_newtable(L);
+ for (i=0;i<map->backmax;i++) {
+ if (map->backmap[i]!=-1) {
+ lua_pushnumber(L,i);
+ lua_pushnumber(L,map->backmap[i]);
+ lua_rawset(L,-3);
+ }
+ }
+ lua_setfield(L,-2,"backmap");
+ }
+
+ if (map->enc != NULL) {
+ lua_newtable(L);
+ handle_enc(L,map->enc);
+ lua_setfield(L,-2,"enc");
+ }
+}
+
+static void
+handle_psdict (lua_State *L, struct psdict *private) {
+ int k;
+ if (private->keys != NULL && private->values != NULL) {
+ for (k=0;k<private->next;k++) {
+ lua_pushstring(L,private->keys[k]);
+ lua_pushstring(L,private->values[k]);
+ lua_rawset(L,-3);
+ }
+ }
+}
+
+char *ttfnames_enum[ttf_namemax] = { "copyright", "family", "subfamily", "uniqueid",
+ "fullname", "version", "postscriptname", "trademark",
+ "manufacturer", "designer", "descriptor", "venderurl",
+ "designerurl", "license", "licenseurl", "idontknow",
+ "preffamilyname", "prefmodifiers", "compatfull", "sampletext",
+ "cidfindfontname"};
+
+void
+do_handle_ttflangname (lua_State *L, struct ttflangname *names) {
+ int k;
+ dump_stringfield(L,"lang", (char *)MSLangString(names->lang)) ;
+ lua_checkstack(L,4);
+ lua_createtable(L,0,ttf_namemax);
+ for (k=0;k<ttf_namemax;k++) {
+ lua_pushstring(L,ttfnames_enum[k]);
+ lua_pushstring(L,names->names[k]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L, -2 , "names");
+}
+
+
+void
+handle_ttflangname (lua_State *L, struct ttflangname *names) {
+ struct ttflangname *next;
+ NESTED_TABLE(do_handle_ttflangname,names,2);
+}
+
+
+void
+do_handle_anchorclass (lua_State *L, struct anchorclass *anchor) {
+
+ dump_stringfield(L,"name", anchor->name);
+ if (anchor->subtable!=NULL) {
+ dump_stringfield(L,"lookup",anchor->subtable->subtable_name);
+ }
+ dump_enumfield(L,"type", anchor->type, anchorclass_type_enum);
+}
+
+void
+handle_anchorclass (lua_State *L, struct anchorclass *anchor) {
+ struct anchorclass *next;
+ NESTED_TABLE(do_handle_anchorclass,anchor,10);
+}
+
+void
+do_handle_ttf_table (lua_State *L, struct ttf_table *ttf_tab) {
+
+ dump_tag(L,"tag", ttf_tab->tag);
+ dump_intfield(L,"len", ttf_tab->len);
+ dump_intfield(L,"maxlen", ttf_tab->maxlen);
+ dump_lstringfield(L,"data", (char *)ttf_tab->data, ttf_tab->len);
+}
+
+void
+handle_ttf_table (lua_State *L, struct ttf_table *ttf_tab) {
+ struct ttf_table *next;
+ NESTED_TABLE(do_handle_ttf_table,ttf_tab,4);
+}
+
+void
+do_handle_kernclass (lua_State *L, struct kernclass *kerns) {
+ int k;
+
+ /*
+ * dump_intfield(L,"first_cnt", kerns->first_cnt);
+ * dump_intfield(L,"second_cnt", kerns->second_cnt);
+ */
+ lua_checkstack(L,4);
+ lua_createtable(L,kerns->first_cnt,1);
+ for (k=0;k<kerns->first_cnt;k++) {
+ lua_pushnumber(L,(k+1));
+ lua_pushstring(L,kerns->firsts[k]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"firsts");
+
+ lua_createtable(L,kerns->second_cnt,1);
+ for (k=0;k<kerns->second_cnt;k++) {
+ lua_pushnumber(L,(k+1));
+ lua_pushstring(L,kerns->seconds[k]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"seconds");
+
+ if (kerns->subtable != NULL) {
+ dump_stringfield(L,"lookup", kerns->subtable->subtable_name);
+ }
+ /*dump_intfield(L,"kcid", kerns->kcid); *//* probably not needed */
+
+ lua_createtable(L,kerns->second_cnt*kerns->first_cnt,1);
+ for (k=0;k<(kerns->second_cnt*kerns->first_cnt);k++) {
+ if (kerns->offsets[k]!=0) {
+ lua_pushnumber(L,(k+1));
+ lua_pushnumber(L,kerns->offsets[k]);
+ lua_rawset(L,-3);
+ }
+ }
+ lua_setfield(L,-2,"offsets");
+
+}
+
+void
+handle_kernclass (lua_State *L, struct kernclass *kerns) {
+ struct kernclass *next;
+ NESTED_TABLE(do_handle_kernclass,kerns,8);
+}
+
+
+#define DUMP_NUMBER_ARRAY(s,cnt,item) { \
+ if (cnt>0 && item != NULL) { \
+ int kk; \
+ lua_newtable(L); \
+ for (kk=0;kk<cnt;kk++) { \
+ lua_pushnumber(L,(kk+1)); \
+ lua_pushnumber(L,item[kk]); \
+ lua_rawset(L,-3); } \
+ lua_setfield(L,-2,s); } }
+
+
+#define DUMP_STRING_ARRAY(s,cnt,item) { \
+ if (cnt>0 && item!=NULL) { \
+ int kk; \
+ lua_newtable(L); \
+ for (kk=0;kk<cnt;kk++) { \
+ lua_pushnumber(L,(kk+1)); \
+ lua_pushstring(L,item[kk]); \
+ lua_rawset(L,-3); } \
+ lua_setfield(L,-2,s); } }
+
+#define DUMP_EXACT_STRING_ARRAY(s,cnt,item) { \
+ if (cnt>0 && item!=NULL) { \
+ int kk; \
+ lua_newtable(L); \
+ for (kk=0;kk<cnt;kk++) { \
+ lua_pushnumber(L,(kk)); \
+ lua_pushstring(L,item[kk]); \
+ lua_rawset(L,-3); } \
+ lua_setfield(L,-2,s); } }
+
+
+
+static char *fpossub_format_enum [] = { "glyphs", "class","coverage","reversecoverage"};
+
+void handle_fpst_rule (lua_State *L, struct fpst_rule *rule, int format) {
+ int k;
+
+
+ if (format == pst_glyphs) {
+
+ lua_newtable(L);
+ dump_stringfield(L,"names",rule->u.glyph.names);
+ dump_stringfield(L,"back",rule->u.glyph.back);
+ dump_stringfield(L,"fore",rule->u.glyph.fore);
+ lua_setfield(L,-2,fpossub_format_enum[format]);
+
+ } else if (format == pst_class) {
+
+ lua_newtable(L);
+ DUMP_NUMBER_ARRAY("current", rule->u.class.ncnt,rule->u.class.nclasses);
+ DUMP_NUMBER_ARRAY("before", rule->u.class.bcnt,rule->u.class.bclasses);
+ DUMP_NUMBER_ARRAY("after", rule->u.class.fcnt,rule->u.class.fclasses);
+#if 0
+ DUMP_NUMBER_ARRAY("allclasses", 0,rule->u.class.allclasses);
+#endif
+ lua_setfield(L,-2,fpossub_format_enum[format]);
+
+ } else if (format == pst_coverage) {
+
+ lua_newtable(L);
+ DUMP_STRING_ARRAY("current", rule->u.coverage.ncnt,rule->u.coverage.ncovers);
+ DUMP_STRING_ARRAY("before", rule->u.coverage.bcnt,rule->u.coverage.bcovers);
+ DUMP_STRING_ARRAY("after", rule->u.coverage.fcnt,rule->u.coverage.fcovers);
+ lua_setfield(L,-2,fpossub_format_enum[format]);
+
+ } else if (format == pst_reversecoverage) {
+
+ lua_newtable(L);
+ DUMP_STRING_ARRAY("current", rule->u.rcoverage.always1,rule->u.rcoverage.ncovers);
+ DUMP_STRING_ARRAY("before", rule->u.rcoverage.bcnt,rule->u.rcoverage.bcovers);
+ DUMP_STRING_ARRAY("after", rule->u.rcoverage.fcnt,rule->u.rcoverage.fcovers);
+ dump_stringfield(L,"replacements", rule->u.rcoverage.replacements);
+ lua_setfield(L,-2,fpossub_format_enum[format]);
+ } else {
+ fprintf(stderr,"handle_fpst_rule(): Unknown rule format: %d\n",format);
+ }
+
+ if (rule->lookup_cnt>0) {
+ lua_newtable(L);
+ for (k=0;k<rule->lookup_cnt;k++) {
+ lua_pushnumber(L,(rule->lookups[k].seq+1));
+ if (rule->lookups[k].lookup!=NULL) {
+ lua_pushstring(L,rule->lookups[k].lookup->lookup_name);
+ } else {
+ lua_pushnil(L);
+ }
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"lookups");
+ } else {
+ /*fprintf(stderr,"handle_fpst_rule(): No lookups?\n");*/
+ }
+}
+
+void
+do_handle_generic_fpst(lua_State *L, struct generic_fpst *fpst) {
+ int k;
+
+ if (fpst->type>LAST_POSSUB_TYPE_ENUM) {
+ dump_intfield(L,"type", fpst->type);
+ } else {
+ dump_enumfield(L,"type", fpst->type, possub_type_enum);
+ }
+ dump_enumfield(L,"format", fpst->format, fpossub_format_enum);
+
+ if (fpst->format==pst_class) {
+ DUMP_EXACT_STRING_ARRAY("current_class",fpst->nccnt,fpst->nclass);
+ DUMP_EXACT_STRING_ARRAY("before_class",fpst->bccnt,fpst->bclass);
+ DUMP_EXACT_STRING_ARRAY("after_class",fpst->fccnt,fpst->fclass);
+ } else {
+ DUMP_STRING_ARRAY("current_class",fpst->nccnt,fpst->nclass);
+ DUMP_STRING_ARRAY("before_class",fpst->bccnt,fpst->bclass);
+ DUMP_STRING_ARRAY("after_class",fpst->fccnt,fpst->fclass);
+ }
+
+ lua_checkstack(L,4);
+ if (fpst->rule_cnt>0) {
+ lua_createtable(L,fpst->rule_cnt,1);
+ for (k=0;k<fpst->rule_cnt;k++) {
+ lua_pushnumber(L,(k+1));
+ lua_newtable(L);
+ handle_fpst_rule(L,&(fpst->rules[k]),fpst->format);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"rules");
+ }
+ /*dump_intfield (L,"ticked", fpst->ticked);*/
+}
+
+void
+handle_generic_fpst(lua_State *L, struct generic_fpst *fpst) {
+ struct generic_fpst *next;
+ int k = 1;
+ lua_checkstack(L,3);
+ if (fpst->subtable != NULL &&
+ fpst->subtable->subtable_name != NULL) {
+ lua_pushstring(L,fpst->subtable->subtable_name);
+ } else {
+ lua_pushnumber(L,k); k++;
+ }
+ lua_createtable(L,0,10);
+ do_handle_generic_fpst(L,fpst);
+ lua_rawset(L,-3);
+ next = fpst->next;
+ while (next != NULL) {
+ lua_checkstack(L,3);
+ if (next->subtable != NULL &&
+ next->subtable->subtable_name != NULL) {
+ lua_pushstring(L,next->subtable->subtable_name);
+ } else {
+ lua_pushnumber(L,k); k++;
+ }
+ lua_createtable(L,0,10);
+ do_handle_generic_fpst(L, next);
+ lua_rawset(L,-3);
+ next = next->next;
+ }
+}
+
+void
+do_handle_otfname (lua_State *L, struct otfname *oname) {
+ dump_intfield(L,"lang", oname->lang);
+ dump_stringfield(L,"name", oname->name);
+}
+
+void
+handle_otfname (lua_State *L, struct otfname *oname) {
+ struct otfname *next;
+ NESTED_TABLE(do_handle_otfname,oname,2);
+}
+
+void
+do_handle_macname (lua_State *L, struct macname *featname) {
+ dump_intfield(L,"enc", featname->enc);
+ dump_intfield(L,"lang", featname->lang);
+ dump_stringfield(L,"name", featname->name);
+}
+
+void
+handle_macname (lua_State *L, struct macname *featname) {
+ struct macname *next;
+ NESTED_TABLE(do_handle_macname,featname,3);
+}
+
+void
+do_handle_macsetting (lua_State *L, struct macsetting *settings) {
+ dump_intfield(L,"setting", settings->setting);
+ dump_intfield(L,"strid", settings->strid);
+ dump_intfield(L,"initially_enabled", settings->initially_enabled);
+ if (settings->setname != NULL) {
+ lua_newtable(L);
+ handle_macname(L,settings->setname);
+ lua_setfield(L,-2,"setname");
+ }
+}
+
+void
+handle_macsetting (lua_State *L, struct macsetting *settings) {
+ struct macsetting *next;
+ NESTED_TABLE(do_handle_macsetting,settings,4);
+}
+
+
+void
+do_handle_macfeat (lua_State *L, struct macfeat *features) {
+
+ dump_intfield(L,"feature", features->feature);
+ dump_intfield(L,"ismutex", features->ismutex);
+ dump_intfield(L,"default_setting", features->default_setting);
+ dump_intfield(L,"strid", features->strid);
+
+ if (features->featname != NULL) {
+ lua_newtable(L);
+ handle_macname(L,features->featname);
+ lua_setfield(L,-2,"featname");
+ }
+
+ if (features->settings != NULL) {
+ lua_newtable(L);
+ handle_macsetting(L,features->settings);
+ lua_setfield(L,-2,"settings");
+ }
+}
+
+void
+handle_macfeat (lua_State *L, struct macfeat *features) {
+ struct macfeat *next;
+ NESTED_TABLE(do_handle_macfeat,features,6);
+}
+
+char *tex_type_enum[4] = { "unset", "text", "math", "mathext"};
+
+/* has an offset of 1, ui_none = 0. */
+char *uni_interp_enum[9] = {
+ "unset", "none", "adobe", "greek", "japanese",
+ "trad_chinese", "simp_chinese", "korean", "ams" };
+
+
+void
+handle_splinefont(lua_State *L, struct splinefont *sf) {
+ int k,l;
+
+ dump_stringfield(L,"table_version", LUA_OTF_VERSION);
+ dump_stringfield(L,"fontname", sf->fontname);
+ dump_stringfield(L,"fullname", sf->fullname);
+ dump_stringfield(L,"familyname", sf->familyname);
+ dump_stringfield(L,"weight", sf->weight);
+ dump_stringfield(L,"copyright", sf->copyright);
+ dump_stringfield(L,"filename", sf->filename);
+ dump_stringfield(L,"defbasefilename", sf->defbasefilename);
+ dump_stringfield(L,"version", sf->version);
+ dump_floatfield (L,"italicangle", sf->italicangle);
+ dump_floatfield (L,"upos", sf->upos);
+ dump_floatfield (L,"uwidth", sf->uwidth);
+ dump_intfield (L,"units_per_em", sf->units_per_em);
+ dump_intfield (L,"ascent", sf->ascent);
+ dump_intfield (L,"descent", sf->descent);
+ dump_intfield (L,"vertical_origin", sf->vertical_origin);
+ dump_intfield (L,"uniqueid", sf->uniqueid);
+ dump_intfield (L,"glyphcnt", sf->glyphcnt);
+ dump_intfield (L,"glyphmax", sf->glyphmax);
+
+ if (sf->possub != NULL) {
+ lua_newtable(L);
+ handle_generic_fpst(L,sf->possub);
+ lua_setfield(L,-2,"lookups");
+ }
+
+ lua_checkstack(L,4);
+ lua_createtable(L,sf->glyphcnt,0);
+ /* here is a bit of hackery for .notdef's that appear in the middle
+ of a type1 font. This situation should be handled nicer, because the
+ trick assumes a specific way of handling cff fonts, and that will
+ fail. The current code will at least make sure that the intended use
+ works, for now. */
+ l = 0;
+ for (k=0;k<sf->glyphcnt;k++,l++) {
+ lua_pushnumber(L,l);
+ lua_createtable(L,0,12);
+ if (sf->glyphs[k]) {
+ if (k>0 && strcmp(sf->glyphs[k]->name,".notdef") == 0) {
+ l--;
+ } else {
+ handle_splinechar(L,sf->glyphs[k], sf->hasvmetrics);
+ }
+ }
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"glyphs");
+
+ dump_intfield(L,"changed", sf->changed);
+ dump_intfield(L,"hasvmetrics", sf->hasvmetrics);
+ dump_intfield(L,"order2", sf->order2);
+ dump_intfield(L,"strokedfont", sf->strokedfont);
+ dump_intfield(L,"weight_width_slope_only", sf->weight_width_slope_only);
+ dump_intfield(L,"head_optimized_for_cleartype",sf->head_optimized_for_cleartype);
+ dump_enumfield(L,"uni_interp", (sf->uni_interp+1), uni_interp_enum);
+
+ if (sf->map != NULL ) {
+ lua_newtable(L);
+ handle_encmap(L,sf->map);
+ lua_setfield(L,-2,"map");
+ }
+
+ dump_stringfield(L,"origname", sf->origname); /* new */
+
+ if (sf->private != NULL) {
+ lua_newtable(L);
+ handle_psdict(L, sf->private);
+ lua_setfield(L,-2,"private");
+ }
+
+ dump_stringfield(L,"xuid", sf->xuid);
+
+ lua_createtable(L,0,40);
+ handle_pfminfo(L,sf->pfminfo);
+ lua_setfield(L,-2,"pfminfo");
+
+ if (sf->names != NULL) {
+ lua_newtable(L);
+ handle_ttflangname(L,sf->names);
+ lua_setfield(L,-2,"names");
+ }
+
+ lua_createtable(L,0,4);
+ dump_stringfield(L,"registry", sf->cidregistry);
+ dump_stringfield(L,"ordering", sf->ordering);
+ dump_intfield (L,"version", sf->cidversion);
+ dump_intfield (L,"supplement", sf->supplement);
+ lua_setfield(L,-2,"cidinfo");
+
+ if (sf->subfontcnt>0) {
+ lua_createtable(L,sf->subfontcnt,0);
+ for (k=0;k<sf->subfontcnt;k++) {
+ lua_checkstack(L,10);
+ lua_newtable(L);
+ handle_splinefont(L,sf->subfonts[k]);
+ lua_rawseti(L,-2,(k+1));
+ }
+ lua_setfield(L,-2,"subfonts");
+ }
+
+ /* always the parent of a subfont, so why bother? */
+ /*
+ if (sf->cidmaster != NULL) {
+ lua_pushstring(L, sf->cidmaster->origname);
+ lua_setfield(L,-2,"cidmaster");
+ }
+ */
+
+ dump_stringfield(L,"comments", sf->comments);
+
+ if (sf->ttf_tables != NULL) {
+ lua_newtable(L);
+ handle_ttf_table(L,sf->ttf_tables);
+ lua_setfield(L,-2,"ttf_tables");
+ }
+
+ if (sf->texdata.type != tex_unset) {
+ lua_newtable(L);
+ dump_enumfield(L,"type", sf->texdata.type, tex_type_enum);
+ lua_newtable(L);
+ for (k=0;k<22;k++) {
+ lua_pushnumber(L,k);
+ lua_pushnumber(L,sf->texdata.params[k]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"params");
+ lua_setfield(L,-2,"texdata");
+ }
+ if (sf->anchor != NULL) {
+ lua_newtable(L);
+ handle_anchorclass(L,sf->anchor);
+ lua_setfield(L,-2,"anchor_classes");
+ }
+ if (sf->kerns != NULL) {
+ lua_newtable(L);
+ handle_kernclass(L,sf->kerns);
+ lua_setfield(L,-2,"kerns");
+ }
+ if (sf->vkerns != NULL) {
+ lua_newtable(L);
+ handle_kernclass(L,sf->vkerns);
+ lua_setfield(L,-2,"vkerns");
+ }
+ if (sf->gsub_lookups != NULL) {
+ lua_newtable(L);
+ handle_lookup(L,sf->gsub_lookups);
+ lua_setfield(L,-2,"gsub");
+ }
+ if (sf->gpos_lookups != NULL) {
+ lua_newtable(L);
+ handle_lookup(L,sf->gpos_lookups);
+ lua_setfield(L,-2,"gpos");
+ }
+
+ /* Todo: a set of Apple-related items */
+ /*
+ ASM *sm;
+ if (sf->features != NULL) {
+ lua_newtable(L);
+ handle_macfeat(L,sf->features);
+ lua_setfield(L,-2,"features");
+ }
+ struct mmset *mm;
+ */
+
+ dump_stringfield(L,"chosenname", sf->chosenname);
+
+ dump_intfield(L,"macstyle", sf->macstyle);
+ dump_stringfield(L,"fondname", sf->fondname);
+
+ dump_intfield(L,"design_size", sf->design_size);
+ dump_intfield(L,"fontstyle_id", sf->fontstyle_id);
+
+ if (sf->fontstyle_name != NULL) {
+ lua_newtable(L);
+ handle_otfname(L,sf->fontstyle_name);
+ lua_setfield(L,-2,"fontstyle_name");
+ }
+
+ dump_intfield(L,"design_range_bottom",sf->design_range_bottom);
+ dump_intfield(L,"design_range_top", sf->design_range_top);
+ dump_floatfield(L,"strokewidth", sf->strokewidth);
+ /*dump_intfield(L,"mark_class_cnt", sf->mark_class_cnt);*/
+
+ if (sf->mark_class_cnt>0) {
+ lua_newtable(L);
+ for ( k=0; k<sf->mark_class_cnt; ++k ) {
+ lua_pushnumber(L,(k+1));
+ lua_pushstring(L,sf->mark_classes[k]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-1,"mark_classes");
+
+ lua_newtable(L);
+ for ( k=0; k<sf->mark_class_cnt; ++k ) {
+ lua_pushnumber(L,(k+1));
+ lua_pushstring(L,sf->mark_class_names[k]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-1,"mark_class_names");
+ }
+
+ dump_intfield(L,"creationtime", sf->creationtime);
+ dump_intfield(L,"modificationtime", sf->modificationtime);
+
+ dump_intfield(L,"os2_version", sf->os2_version);
+ /* Grid-fitting And Scan-conversion Procedures: not needed */
+
+ /*
+ dump_intfield(L,"gasp_version", sf->gasp_version);
+ dump_intfield(L,"gasp_cnt", sf->gasp_cnt);
+ dump_intfield(L,"gasp", (int)sf->gasp);
+ */
+
+ /* uint8 sfd_version; */ /* Used only when reading in an sfd file */
+ /* struct gfi_data *fontinfo; */ /* TH: looks like this is screen-related */
+}
+
+int
+ff_make_table (lua_State *L) {
+ SplineFont *sf;
+ sf = *(check_isfont(L,1));
+ if (sf == NULL) {
+ lua_pushboolean(L,0);
+ } else {
+ lua_createtable(L,0,60);
+ handle_splinefont(L,sf);
+ }
+ return 1;
+}
+
+void do_ff_info (lua_State *L, SplineFont *sf) {
+ lua_newtable(L);
+ dump_stringfield(L,"familyname", sf->familyname);
+ dump_stringfield(L,"fontname", sf->fontname);
+ dump_stringfield(L,"fullname", sf->fullname);
+ dump_intfield (L,"italicangle", sf->italicangle);
+ dump_stringfield(L,"version", sf->version);
+ dump_stringfield(L,"weight", sf->weight);
+
+}
+
+static int
+ff_info (lua_State *L) {
+ SplineFont *sf;
+ FILE *l;
+ int i;
+ const char *fontname;
+ int openflags = 1;
+ fontname = luaL_checkstring(L,1);
+ if (!strlen(fontname)) {
+ lua_pushfstring(L,"font loading failed: empty string given\n", fontname);
+ lua_error(L);
+ return 1;
+ }
+ /* test fontname for existance */
+ if ((l = fopen(fontname,"r"))) {
+ fclose(l);
+ } else {
+ lua_pushfstring(L,"font loading failed for %s (read error)\n", fontname);
+ lua_error(L);
+ }
+ sf = ReadSplineFontInfo((char *)fontname,openflags);
+ if (sf==NULL) {
+ lua_pushfstring(L,"font loading failed for %s\n", fontname);
+ lua_error(L);
+ } else {
+ if (sf->next != NULL) {
+ i = 1;
+ lua_newtable(L);
+ while (sf) {
+ do_ff_info(L, sf);
+ lua_rawseti(L,-2,i);
+ i++;
+ SplineFontFree(sf);
+ sf = sf->next;
+ }
+ } else {
+ do_ff_info(L, sf);
+ SplineFontFree(sf);
+ }
+ }
+ return 1;
+}
+
+/* possible flags:
+
+ ttf_flag_shortps = 1,
+ ttf_flag_nohints = 2,
+ ttf_flag_applemode=4,
+ ttf_flag_pfed_comments=8,
+ ttf_flag_pfed_colors=0x10,
+ ttf_flag_otmode=0x20,
+ ttf_flag_glyphmap=0x40,
+ ttf_flag_TeXtable=0x80,
+ ttf_flag_ofm=0x100,
+ ttf_flag_oldkern=0x200,
+ ttf_flag_brokensize=0x400
+
+ ps_flag_nohintsubs = 0x10000,
+ ps_flag_noflex=0x20000,
+ ps_flag_nohints = 0x40000,
+ ps_flag_restrict256=0x80000,
+ ps_flag_afm = 0x100000,
+ ps_flag_pfm = 0x200000,
+ ps_flag_tfm = 0x400000,
+ ps_flag_round = 0x800000,
+ ps_flag_nocffsugar = 0x1000000,
+ ps_flag_identitycidmap = 0x2000000,
+ ps_flag_afmwithmarks = 0x4000000,
+ ps_flag_noseac = 0x8000000,
+
+
+*/
+
+extern int readbinfile(FILE *f, unsigned char **b, int *s);
+
+static void ff_do_cff (SplineFont *sf, char *filename, unsigned char **buf, int *bufsiz) {
+ FILE *f;
+ int32 *bsizes = NULL;
+ int flags = ps_flag_nocffsugar + ps_flag_nohints;
+ EncMap *map;
+
+ map = EncMap1to1(sf->glyphcnt);
+
+ if(WriteTTFFont(filename, sf, ff_cff, bsizes, bf_none, flags, map)) {
+ /* success */
+ f = fopen(filename,"rb");
+ readbinfile(f , buf, bufsiz);
+ /*fprintf(stdout,"\n%s => CFF, size: %d\n", sf->filename, *bufsiz);*/
+ fclose(f);
+ return;
+ }
+ /* errors */
+ /*fprintf(stdout,"\n%s => CFF, failed\n", sf->filename);*/
+
+}
+
+/* exported for writecff.c */
+
+int ff_createcff (char *file, unsigned char **buf, int *bufsiz) {
+ SplineFont *sf;
+ int k ;
+ char s[] = "tempfile.cff";
+ int openflags = 1;
+ int notdefpos = 0;
+ sf = ReadSplineFont(file,openflags);
+ if (sf) {
+ /* this is not the best way. nicer to have no temp file at all */
+ ff_do_cff(sf, s, buf,bufsiz);
+ for (k=0;k<sf->glyphcnt;k++) {
+ if (sf->glyphs[k] && strcmp(sf->glyphs[k]->name,".notdef")==0) {
+ notdefpos=k;
+ break;
+ }
+ }
+ remove(s);
+ SplineFontFree(sf);
+ }
+ return notdefpos;
+}
+
+int ff_get_ttc_index(char *ffname, char*psname) {
+ SplineFont *sf;
+ int i = 0;
+ int openflags = 1;
+ int index = 0;
+
+ sf = ReadSplineFontInfo((char *)ffname,openflags);
+ if (sf==NULL) {
+ perror("font loading failed unexpectedly\n");
+ exit(EXIT_FAILURE);
+ }
+ while (sf != NULL) {
+ if (strcmp(sf->fontname,psname)==0) {
+ index = i;
+ break;
+ }
+ i++;
+ sf = sf->next;
+ }
+ return index;
+}
+
+
+static int ff_make_cff (lua_State *L) {
+ SplineFont **sf;
+ char *s;
+ unsigned char *buf = NULL;
+ int bufsiz = 0;
+ sf = check_isfont(L,1);
+ s = (char *)luaL_checkstring(L,2);
+ ff_do_cff (*sf, s, &buf, &bufsiz);
+ return 0;
+}
+
+
+static struct luaL_reg fflib[] = {
+ {"open", ff_open},
+ {"info", ff_info},
+ {"close", ff_close},
+ {"apply_afmfile", ff_apply_afmfile},
+ {"apply_featurefile", ff_apply_featurefile},
+ {"to_table", ff_make_table},
+ {"to_cff", ff_make_cff},
+ {NULL, NULL}
+};
+
+static const struct luaL_reg fflib_m [] = {
+ {"__gc", ff_close }, /* doesnt work yet! */
+ {NULL, NULL} /* sentinel */
+};
+
+
+int luaopen_ff (lua_State *L) {
+ LoadPrefs();
+ luaL_newmetatable(L,FONT_METATABLE);
+ luaL_register(L, NULL, fflib_m);
+ luaL_openlib(L, "fontforge", fflib, 0);
+ return 1;
+}
+
diff --git a/Build/source/libs/luamd5/makefile b/Build/source/libs/luamd5/makefile
new file mode 100644
index 00000000000..78ea7b7cb60
--- /dev/null
+++ b/Build/source/libs/luamd5/makefile
@@ -0,0 +1,23 @@
+# Location of Lua header files
+LUA_DIR = /usr/local/include/
+
+# Compilation parameters
+CC = gcc
+CWARNS = -Wall -Wmissing-prototypes -Wshadow -pedantic -Wpointer-arith -Wcast-align -Waggregate-return
+CFLAGS = $(CONFIG) $(CWARNS) -ansi -O2 -I$(LUA_DIR)
+
+
+# Files in this distribution
+FILES = makefile \
+ md5.c \
+ md5lib.c \
+ md5.h \
+ md5.lua \
+ md5.html \
+ md5tests.lua
+
+# Rule to create shared library, to be used with `loadlib' (see also
+# file `md5.lua')
+md5 : md5.o md5lib.o
+ ld -o libmd5.so -shared md5.o md5lib.o
+
diff --git a/Build/source/libs/luamd5/md5.c b/Build/source/libs/luamd5/md5.c
new file mode 100644
index 00000000000..7e630bfc46b
--- /dev/null
+++ b/Build/source/libs/luamd5/md5.c
@@ -0,0 +1,209 @@
+/**
+* $Id: md5.c,v 1.1 2000/11/09 19:19:59 roberto Exp $
+* Hash function MD5
+* @author Marcela Ozorio Suarez, Roberto I.
+*/
+
+
+#include <string.h>
+
+#include "md5.h"
+
+
+#define WORD 32
+#define MASK 0xFFFFFFFF
+typedef unsigned long WORD32;
+
+
+/**
+* md5 hash function.
+* @param message: aribtary string.
+* @param len: message length.
+* @param output: buffer to receive the hash value. Its size must be
+* (at least) HASHSIZE.
+*/
+void md5 (const char *message, long len, char *output);
+
+
+
+/*
+** Realiza a rotacao no sentido horario dos bits da variavel 'D' do tipo WORD32.
+** Os bits sao deslocados de 'num' posicoes
+*/
+#define rotate(D, num) (D<<num) | (D>>(WORD-num))
+
+/*Macros que definem operacoes relizadas pelo algoritmo md5 */
+#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~(z))))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~(z))))
+
+
+/*vetor de numeros utilizados pelo algoritmo md5 para embaralhar bits */
+static const WORD32 T[64]={
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+ 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+};
+
+
+static void word32tobytes (const WORD32 *input, char *output) {
+ int j = 0;
+ while (j<4*4) {
+ WORD32 v = *input++;
+ output[j++] = (char)(v & 0xff); v >>= 8;
+ output[j++] = (char)(v & 0xff); v >>= 8;
+ output[j++] = (char)(v & 0xff); v >>= 8;
+ output[j++] = (char)(v & 0xff);
+ }
+}
+
+
+static void inic_digest(WORD32 *d) {
+ d[0] = 0x67452301;
+ d[1] = 0xEFCDAB89;
+ d[2] = 0x98BADCFE;
+ d[3] = 0x10325476;
+}
+
+
+/*funcao que implemeta os quatro passos principais do algoritmo MD5 */
+static void digest(const WORD32 *m, WORD32 *d) {
+ int j;
+ /*MD5 PASSO1 */
+ for (j=0; j<4*4; j+=4) {
+ d[0] = d[0]+ F(d[1], d[2], d[3])+ m[j] + T[j]; d[0]=rotate(d[0], 7);
+ d[0]+=d[1];
+ d[3] = d[3]+ F(d[0], d[1], d[2])+ m[(j)+1] + T[j+1]; d[3]=rotate(d[3], 12);
+ d[3]+=d[0];
+ d[2] = d[2]+ F(d[3], d[0], d[1])+ m[(j)+2] + T[j+2]; d[2]=rotate(d[2], 17);
+ d[2]+=d[3];
+ d[1] = d[1]+ F(d[2], d[3], d[0])+ m[(j)+3] + T[j+3]; d[1]=rotate(d[1], 22);
+ d[1]+=d[2];
+ }
+ /*MD5 PASSO2 */
+ for (j=0; j<4*4; j+=4) {
+ d[0] = d[0]+ G(d[1], d[2], d[3])+ m[(5*j+1)&0x0f] + T[(j-1)+17];
+ d[0] = rotate(d[0],5);
+ d[0]+=d[1];
+ d[3] = d[3]+ G(d[0], d[1], d[2])+ m[((5*(j+1)+1)&0x0f)] + T[(j+0)+17];
+ d[3] = rotate(d[3], 9);
+ d[3]+=d[0];
+ d[2] = d[2]+ G(d[3], d[0], d[1])+ m[((5*(j+2)+1)&0x0f)] + T[(j+1)+17];
+ d[2] = rotate(d[2], 14);
+ d[2]+=d[3];
+ d[1] = d[1]+ G(d[2], d[3], d[0])+ m[((5*(j+3)+1)&0x0f)] + T[(j+2)+17];
+ d[1] = rotate(d[1], 20);
+ d[1]+=d[2];
+ }
+ /*MD5 PASSO3 */
+ for (j=0; j<4*4; j+=4) {
+ d[0] = d[0]+ H(d[1], d[2], d[3])+ m[(3*j+5)&0x0f] + T[(j-1)+33];
+ d[0] = rotate(d[0], 4);
+ d[0]+=d[1];
+ d[3] = d[3]+ H(d[0], d[1], d[2])+ m[(3*(j+1)+5)&0x0f] + T[(j+0)+33];
+ d[3] = rotate(d[3], 11);
+ d[3]+=d[0];
+ d[2] = d[2]+ H(d[3], d[0], d[1])+ m[(3*(j+2)+5)&0x0f] + T[(j+1)+33];
+ d[2] = rotate(d[2], 16);
+ d[2]+=d[3];
+ d[1] = d[1]+ H(d[2], d[3], d[0])+ m[(3*(j+3)+5)&0x0f] + T[(j+2)+33];
+ d[1] = rotate(d[1], 23);
+ d[1]+=d[2];
+ }
+ /*MD5 PASSO4 */
+ for (j=0; j<4*4; j+=4) {
+ d[0] = d[0]+ I(d[1], d[2], d[3])+ m[(7*j)&0x0f] + T[(j-1)+49];
+ d[0] = rotate(d[0], 6);
+ d[0]+=d[1];
+ d[3] = d[3]+ I(d[0], d[1], d[2])+ m[(7*(j+1))&0x0f] + T[(j+0)+49];
+ d[3] = rotate(d[3], 10);
+ d[3]+=d[0];
+ d[2] = d[2]+ I(d[3], d[0], d[1])+ m[(7*(j+2))&0x0f] + T[(j+1)+49];
+ d[2] = rotate(d[2], 15);
+ d[2]+=d[3];
+ d[1] = d[1]+ I(d[2], d[3], d[0])+ m[(7*(j+3))&0x0f] + T[(j+2)+49];
+ d[1] = rotate(d[1], 21);
+ d[1]+=d[2];
+ }
+}
+
+
+static void bytestoword32 (WORD32 *x, const char *pt) {
+ int i;
+ for (i=0; i<16; i++) {
+ int j=i*4;
+ x[i] = (((WORD32)(unsigned char)pt[j+3] << 8 |
+ (WORD32)(unsigned char)pt[j+2]) << 8 |
+ (WORD32)(unsigned char)pt[j+1]) << 8 |
+ (WORD32)(unsigned char)pt[j];
+ }
+
+}
+
+
+static void put_length(WORD32 *x, long len) {
+ /* in bits! */
+ x[14] = (WORD32)((len<<3) & MASK);
+ x[15] = (WORD32)(len>>(32-3) & 0x7);
+}
+
+
+/*
+** returned status:
+* 0 - normal message (full 64 bytes)
+* 1 - enough room for 0x80, but not for message length (two 4-byte words)
+* 2 - enough room for 0x80 plus message length (at least 9 bytes free)
+*/
+static int converte (WORD32 *x, const char *pt, int num, int old_status) {
+ int new_status = 0;
+ char buff[64];
+ if (num<64) {
+ memcpy(buff, pt, num); /* to avoid changing original string */
+ memset(buff+num, 0, 64-num);
+ if (old_status == 0)
+ buff[num] = '\200';
+ new_status = 1;
+ pt = buff;
+ }
+ bytestoword32(x, pt);
+ if (num <= (64 - 9))
+ new_status = 2;
+ return new_status;
+}
+
+
+
+void md5 (const char *message, long len, char *output) {
+ WORD32 d[4];
+ int status = 0;
+ long i = 0;
+ inic_digest(d);
+ while (status != 2) {
+ WORD32 d_old[4];
+ WORD32 wbuff[16];
+ int numbytes = (len-i >= 64) ? 64 : len-i;
+ /*salva os valores do vetor digest*/
+ d_old[0]=d[0]; d_old[1]=d[1]; d_old[2]=d[2]; d_old[3]=d[3];
+ status = converte(wbuff, message+i, numbytes, status);
+ if (status == 2) put_length(wbuff, len);
+ digest(wbuff, d);
+ d[0]+=d_old[0]; d[1]+=d_old[1]; d[2]+=d_old[2]; d[3]+=d_old[3];
+ i += numbytes;
+ }
+ word32tobytes(d, output);
+}
+
diff --git a/Build/source/libs/luamd5/md5.h b/Build/source/libs/luamd5/md5.h
new file mode 100644
index 00000000000..80d43f72687
--- /dev/null
+++ b/Build/source/libs/luamd5/md5.h
@@ -0,0 +1,20 @@
+/**
+* $Id: md5.h,v 1.2 2003/04/28 16:25:44 roberto Exp $
+* Cryptographic module for Lua.
+* @author Roberto Ierusalimschy
+*/
+
+
+#ifndef md5_h
+#define md5_h
+
+#include <lua.h>
+
+
+#define HASHSIZE 16
+
+void md5 (const char *message, long len, char *output);
+int luaopen_md5 (lua_State *L);
+
+
+#endif
diff --git a/Build/source/libs/luamd5/md5.html b/Build/source/libs/luamd5/md5.html
new file mode 100644
index 00000000000..1f47c971286
--- /dev/null
+++ b/Build/source/libs/luamd5/md5.html
@@ -0,0 +1,122 @@
+<html><body>
+<h1>Cryptographic Library for Lua 5.0</h1>
+
+<p>
+This library offers basic cryptographic facilities for Lua 5.0:
+a hash (digest) function, an a pair crypt/decrypt.
+(<a href=md5.tar.gz>download</a>)
+
+
+<h2>Lua API</h2>
+
+All functions are registered inside a table <code>md5</code>.
+
+<ul>
+
+<li><code>md5.sum (message)</code>
+<p>
+Computes the MD5 message-digest of the string <code>message</code>.
+This function takes as input a message of arbitrary length and content
+and returns as output a 128-bit "fingerprint" (or "message digest")
+of the input.
+The output is formated as a binary string with 16 characters.
+It is conjectured that it is computationally infeasible to produce
+two messages having the same message digest, or to produce any
+message having a given pre-specified target message digest.
+(see <a href="ftp://ftp.isi.edu/in-notes/rfc1321.txt">
+RFC 1321</a>)
+<p>
+
+<li><code>md5.sumhexa (message)</code>
+<p>
+Similar to <code>md5.sum</code>,
+but returns its value as a string of 32 hexadecimal digits.
+
+<li><code>md5.crypt (message, key [,seed])</code>
+<p>
+Encrypts a string, using MD5 in CFB (Cipher-feedback mode).
+<code>message</code> is an arbitrary binary string to be encrypted.
+<code>key</code> is an arbitrary binary string to be used as a key.
+<code>seed</code> is an arbitrary binary string to be used as a seed;
+Returns the cyphertext (as a binary string).
+
+<p>
+If no seed is provided,
+the function uses the result of <code>os.time()</code> as a seed.
+It is recommended that you use different seeds for each message;
+the seed itself is not private, and should contain no private data,
+because it goes plain in the beginning of the encrypted message.
+
+<p>
+The length of the cyphertext is the length of the message plus the
+length of the seed plus one.
+<p>
+
+<li><code>md5.decrypt (message, key)</code>
+<p>
+Decrypts a string.
+The input <code>message</code> must be the result of a previous call
+to <code>crypt</code>.
+For any <code>msg</code>, <code>key</code>,
+and <code>seed</code>, we have that
+<pre>
+ md5.decrypt(md5.crypt(msg, key, seed), key) == msg
+</pre>
+<p>
+
+<li><code>md5.exor (s1, s2)</code>
+<p>
+Does a bit-a-bit exclusive or of strings <code>s1</code> and <code>s2</code>.
+Both strings must have the same length,
+which will be also the length of the resulting string.
+<p>
+
+</ul>
+
+
+<h2>C API</h2>
+
+The following functions are declared in <code>md5.h</code>
+<ul>
+
+<li><code>int luaopen_md5 (lua_State *L);</code>
+<p>
+Opens the library:
+Registers the above Lua functions in the given state.
+<p>
+
+<li><code>void md5 (const char *message, long len, char *output);</code>
+<p>
+Computes the MD5 message-digest of <code>message</code>.
+<code>len</code> is the length of <code>message</code>.
+<code>output</code> is a buffer that receives the result;
+it must have at least 16 bytes (128 bits).
+<p>
+
+</ul>
+
+<h2>INSTALL</h2>
+
+The following instructions assume that your Lua installation has a dynamic
+linking facility (function <code>loadlib</code>):
+
+<ul>
+
+<li>Build a shared library (<code>.so</code>, <code>.dll</code>, etc.)
+with files <code>md5.c</code> and <code>md5lib.c</code>.
+(There is a <code>makefile</code> for Linux and similar systems.)
+
+<li>Put the shared library somewhere,
+and edit file <code>md5.lua</code> to point to it.
+
+<li>Put the file <code>md5.lua</code> in a directory of your
+<code>LUA_PATH</code>.
+
+</ul>
+
+<p><br><small><em>
+$Id: md5.html,v 1.4 2003/04/28 16:40:42 roberto Exp $
+</em></small>
+
+</body></html>
+
diff --git a/Build/source/libs/luamd5/md5.lua b/Build/source/libs/luamd5/md5.lua
new file mode 100644
index 00000000000..0e0c4912dd9
--- /dev/null
+++ b/Build/source/libs/luamd5/md5.lua
@@ -0,0 +1,22 @@
+-- md5.lua
+-- (you should put this file in any directory of your LUA_PATH)
+
+
+-- change the next line to point to the md5 dynamic library
+
+-- local path = "/usr/local/lua/lib/libmd5.so"
+--local path = "./libmd5.so"
+
+--assert(loadlib(path, "luaopen_md5"))()
+
+
+-- Returns the md5 hash value as a string of hexadecimal digits
+
+function md5.sumhexa (k)
+ k = md5.sum(k)
+ return (string.gsub(k, ".", function (c)
+ return string.format("%02x", string.byte(c))
+ end))
+end
+
+return md5
diff --git a/Build/source/libs/luamd5/md5lib.c b/Build/source/libs/luamd5/md5lib.c
new file mode 100644
index 00000000000..7c72a16fcb6
--- /dev/null
+++ b/Build/source/libs/luamd5/md5lib.c
@@ -0,0 +1,183 @@
+/**
+* $Id: md5lib.c,v 1.2 2003/04/28 16:25:44 roberto Exp $
+* Cryptographic and Hash functions for Lua
+* @version 1.0
+* @author Roberto Ierusalimschy
+*/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "md5.h"
+
+
+/**
+* Hash function. Returns a hash for a given string.
+* @param message: arbitrary binary string.
+* @return A 128-bit hash string.
+*/
+static int lmd5 (lua_State *L) {
+ char buff[16];
+ size_t l;
+ const char *message = luaL_checklstring(L, 1, &l);
+ md5(message, l, buff);
+ lua_pushlstring(L, buff, 16L);
+ return 1;
+}
+
+
+/**
+* X-Or. Does a bit-a-bit exclusive-or of two strings.
+* @param s1: arbitrary binary string.
+* @param s2: arbitrary binary string with same length as s1.
+* @return a binary string with same length as s1 and s2,
+* where each bit is the exclusive-or of the corresponding bits in s1-s2.
+*/
+static int ex_or (lua_State *L) {
+ size_t l1, l2;
+ const char *s1 = luaL_checklstring(L, 1, &l1);
+ const char *s2 = luaL_checklstring(L, 2, &l2);
+ luaL_Buffer b;
+ luaL_argcheck( L, l1 == l2, 2, "lengths must be equal" );
+ luaL_buffinit(L, &b);
+ while (l1--) luaL_putchar(&b, (*s1++)^(*s2++));
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static void checkseed (lua_State *L) {
+ if (lua_isnone(L, 3)) { /* no seed? */
+ time_t tm = time(NULL); /* for `random' seed */
+ lua_pushlstring(L, (char *)&tm, sizeof(tm));
+ }
+}
+
+
+#define MAXKEY 256
+#define BLOCKSIZE 16
+
+
+
+static int initblock (lua_State *L, const char *seed, int lseed, char *block) {
+ size_t lkey;
+ const char *key = luaL_checklstring(L, 2, &lkey);
+ if (lkey > MAXKEY)
+ luaL_error(L, "key too long (> %d)", MAXKEY);
+ memset(block, 0, BLOCKSIZE);
+ memcpy(block, seed, lseed);
+ memcpy(block+BLOCKSIZE, key, lkey);
+ return (int)lkey+BLOCKSIZE;
+}
+
+
+static void codestream (lua_State *L, const char *msg, size_t lmsg,
+ char *block, int lblock) {
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ while (lmsg > 0) {
+ char code[BLOCKSIZE];
+ int i;
+ md5(block, lblock, code);
+ for (i=0; i<BLOCKSIZE && lmsg > 0; i++, lmsg--)
+ code[i] ^= *msg++;
+ luaL_addlstring(&b, code, i);
+ memcpy(block, code, i); /* update seed */
+ }
+ luaL_pushresult(&b);
+}
+
+
+static void decodestream (lua_State *L, const char *cypher, size_t lcypher,
+ char *block, int lblock) {
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ while (lcypher > 0) {
+ char code[BLOCKSIZE];
+ int i;
+ md5(block, lblock, code); /* update seed */
+ for (i=0; i<BLOCKSIZE && lcypher > 0; i++, lcypher--)
+ code[i] ^= *cypher++;
+ luaL_addlstring(&b, code, i);
+ memcpy(block, cypher-i, i);
+ }
+ luaL_pushresult(&b);
+}
+
+
+/**
+* Encrypts a string. Uses the hash function md5 in CFB (Cipher-feedback
+* mode).
+* @param message: arbitrary binary string to be encrypted.
+* @param key: arbitrary binary string to be used as a key.
+* @param [seed]: optional arbitrary binary string to be used as a seed.
+* if no seed is provided, the function uses the result of
+* <code>time()</code> as a seed.
+* @return The cyphertext (as a binary string).
+*/
+static int crypt (lua_State *L) {
+ size_t lmsg;
+ const char *msg = luaL_checklstring(L, 1, &lmsg);
+ size_t lseed;
+ const char *seed;
+ int lblock;
+ char block[BLOCKSIZE+MAXKEY];
+ checkseed(L);
+ seed = luaL_checklstring(L, 3, &lseed);
+ if (lseed > BLOCKSIZE)
+ luaL_error(L, "seed too long (> %d)", BLOCKSIZE);
+ /* put seed and seed length at the beginning of result */
+ block[0] = (char)lseed;
+ memcpy(block+1, seed, lseed);
+ lua_pushlstring(L, block, lseed+1); /* to concat with result */
+ lblock = initblock(L, seed, lseed, block);
+ codestream(L, msg, lmsg, block, lblock);
+ lua_concat(L, 2);
+ return 1;
+}
+
+
+/**
+* Decrypts a string. For any message, key, and seed, we have that
+* <code>decrypt(crypt(msg, key, seed), key) == msg</code>.
+* @param cyphertext: message to be decrypted (this must be the result of
+ a previous call to <code>crypt</code>.
+* @param key: arbitrary binary string to be used as a key.
+* @return The plaintext.
+*/
+static int decrypt (lua_State *L) {
+ size_t lcyphertext;
+ const char *cyphertext = luaL_checklstring(L, 1, &lcyphertext);
+ size_t lseed = cyphertext[0];
+ const char *seed = cyphertext+1;
+ int lblock;
+ char block[BLOCKSIZE+MAXKEY];
+ luaL_argcheck(L, lcyphertext >= lseed+1 && lseed <= BLOCKSIZE, 1,
+ "invalid cyphered string");
+ cyphertext += lseed+1;
+ lcyphertext -= lseed+1;
+ lblock = initblock(L, seed, lseed, block);
+ decodestream(L, cyphertext, lcyphertext, block, lblock);
+ return 1;
+}
+
+
+static struct luaL_reg md5lib[] = {
+ {"sum", lmd5},
+ {"exor", ex_or},
+ {"crypt", crypt},
+ {"decrypt", decrypt},
+ {NULL, NULL}
+};
+
+
+int luaopen_md5 (lua_State *L) {
+ luaL_openlib(L, "md5", md5lib, 0);
+ return 1;
+}
+
diff --git a/Build/source/libs/luamd5/md5tests.lua b/Build/source/libs/luamd5/md5tests.lua
new file mode 100644
index 00000000000..4a6092bf34c
--- /dev/null
+++ b/Build/source/libs/luamd5/md5tests.lua
@@ -0,0 +1,78 @@
+#!/usr/bin/env lua5.0
+
+dofile "md5.lua"
+
+
+assert(md5.exor('', '') == '')
+assert(md5.exor('alo alo', '\0\0\0\0\0\0\0') == 'alo alo')
+
+local function invert (s)
+ return md5.exor(s, string.rep('\255', string.len(s)))
+end
+
+x = string.rep('0123456789', 1000)
+assert(md5.exor(x,x) == string.rep('\0', 10000))
+assert(md5.exor(x,invert(x)) == string.rep('\255', 10000))
+
+assert(invert(invert('alo alo')) == 'alo alo')
+
+assert(invert(invert(invert('alo\0\255alo'))) == invert('alo\0\255alo'))
+
+-- test some known sums
+assert(md5.sumhexa("") == "d41d8cd98f00b204e9800998ecf8427e")
+assert(md5.sumhexa("a") == "0cc175b9c0f1b6a831c399e269772661")
+assert(md5.sumhexa("abc") == "900150983cd24fb0d6963f7d28e17f72")
+assert(md5.sumhexa("message digest") == "f96b697d7cb7938d525a2f31aaf161d0")
+assert(md5.sumhexa("abcdefghijklmnopqrstuvwxyz") == "c3fcd3d76192e4007dfb496cca67e13b")
+assert(md5.sumhexa("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
+ == "d174ab98d277d9f5a5611c2c9f419d9f")
+
+
+-- test padding borders
+assert(md5.sumhexa(string.rep('a',53)) == "e9e7e260dce84ffa6e0e7eb5fd9d37fc")
+assert(md5.sumhexa(string.rep('a',54)) == "eced9e0b81ef2bba605cbc5e2e76a1d0")
+assert(md5.sumhexa(string.rep('a',55)) == "ef1772b6dff9a122358552954ad0df65")
+assert(md5.sumhexa(string.rep('a',56)) == "3b0c8ac703f828b04c6c197006d17218")
+assert(md5.sumhexa(string.rep('a',57)) == "652b906d60af96844ebd21b674f35e93")
+assert(md5.sumhexa(string.rep('a',63)) == "b06521f39153d618550606be297466d5")
+assert(md5.sumhexa(string.rep('a',64)) == "014842d480b571495a4a0363793f7367")
+assert(md5.sumhexa(string.rep('a',65)) == "c743a45e0d2e6a95cb859adae0248435")
+assert(md5.sumhexa(string.rep('a',255)) == "46bc249a5a8fc5d622cf12c42c463ae0")
+assert(md5.sumhexa(string.rep('a',256)) == "81109eec5aa1a284fb5327b10e9c16b9")
+
+assert(md5.sumhexa(
+"12345678901234567890123456789012345678901234567890123456789012345678901234567890")
+ == "57edf4a22be3c955ac49da2e2107b67a")
+
+print '+'
+
+
+
+local tolerance = 1.12
+
+local function contchars (s)
+ local a = {}
+ for i=0,255 do a[string.char(i)] = 0 end
+ for c in string.gfind(s, '.') do
+ a[c] = a[c] + 1
+ end
+ local av = string.len(s)/256
+ for i=0,255 do
+ local c = string.char(i)
+ assert(a[c] < av*tolerance and a[c] > av/tolerance, i)
+ end
+end
+
+
+local key = 'xuxu bacana'
+assert(md5.decrypt(md5.crypt('', key), key) == '')
+assert(md5.decrypt(md5.crypt('', key, '\0\0seed\0'), key) == '')
+assert(md5.decrypt(md5.crypt('a', key), key) == 'a')
+local msg = string.rep("1233456789\0\1\2\3\0\255", 10000)
+local code = md5.crypt(msg, key, "seed")
+assert(md5.decrypt(code, key) == msg)
+contchars(code)
+
+assert(md5.crypt('a', 'a') ~= md5.crypt('a', 'b'))
+
+print"OK"
diff --git a/Build/source/libs/luapeg/lpeg.c b/Build/source/libs/luapeg/lpeg.c
new file mode 100644
index 00000000000..2f2bbb706be
--- /dev/null
+++ b/Build/source/libs/luapeg/lpeg.c
@@ -0,0 +1,1989 @@
+/*
+** $Id: lpeg.c,v 1.75 2007/10/08 14:10:53 roberto Exp $
+** LPeg - PEG pattern matching for Lua
+** Copyright 2007, Lua.org & PUC-Rio (see documentation for license)
+** written by Roberto Ierusalimschy
+*/
+
+/*
+ PEG rules:
+
+ e1 | e2 -> choice L1; e1; commit L2; L1: e2; L2:
+ e* -> L2: choice L1; e; commit L2; L1:
+ or e* -> choice L1; L2: e; partialcommit L2; L1:
+ e? -> choice L1; e; commit L1; L1:
+ !e -> choice L1; e; commit L2; L2: fail; L1:
+ or !e -> choice L1; e; failtwice; L1:
+ &e -> choice L1; choice L2; e; L2: commit L3; L3: fail; L1:
+ or &e -> choice L1; e; backcommit L2; L1: fail; L2:
+*/
+
+
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "lua.h"
+#include "lauxlib.h"
+
+
+/* maximum call/backtrack levels */
+#define MAXBACK 400
+
+/* initial size for capture's list */
+#define IMAXCAPTURES 600
+
+
+/* index, on Lua stack, for subject */
+#define SUBJIDX 2
+
+/* index, on Lua stack, for substitution value cache */
+#define SUBSCACHE 3
+
+/* index, on Lua stack, for capture list */
+#define CAPLISTIDX (SUBSCACHE + 1)
+
+/* index, on Lua stack, for pattern's fenv */
+#define PENVIDX (CAPLISTIDX + 1)
+
+
+
+typedef unsigned char byte;
+
+
+#define CHARSETSIZE ((UCHAR_MAX/CHAR_BIT) + 1)
+
+
+typedef byte Charset[CHARSETSIZE];
+
+
+typedef const char *(*PattFunc) (const void *ud,
+ const char *o, /* string start */
+ const char *s, /* current position */
+ const char *e); /* string end */
+
+
+/* Virtual Machine's instructions */
+typedef enum Opcode {
+ IAny, IChar, ISet, IZSet,
+ ITestAny, ITestChar, ITestSet, ITestZSet,
+ ISpan, ISpanZ,
+ IRet, IEnd,
+ IChoice, IJmp, ICall, IOpenCall,
+ ICommit, IPartialCommit, IBackCommit, IFailTwice, IFail, IGiveup,
+ IFunc, ILFunc,
+ IFullCapture, IEmptyCapture, IOpenCapture, ICloseCapture
+} Opcode;
+
+
+#define ISJMP 1
+#define ISCHECK 2
+#define ISTEST 4
+#define ISNOFAIL 8
+#define ISCAPTURE 16
+#define ISMOVABLE 32
+#define ISFENVOFF 64
+#define HASCHARSET 128
+
+static const byte opproperties[] = {
+ /* IAny */ ISCHECK,
+ /* IChar */ ISCHECK,
+ /* ISet */ ISCHECK | HASCHARSET,
+ /* IZSet */ ISCHECK | HASCHARSET,
+ /* ITestAny */ ISJMP | ISTEST | ISNOFAIL,
+ /* ITestChar */ ISJMP | ISTEST | ISNOFAIL,
+ /* ITestSet */ ISJMP | ISTEST | ISNOFAIL | HASCHARSET,
+ /* ITestZSet */ ISJMP | ISTEST | ISNOFAIL | HASCHARSET,
+ /* ISpan */ ISNOFAIL | HASCHARSET,
+ /* ISpanZ */ ISNOFAIL | HASCHARSET,
+ /* IRet */ 0,
+ /* IEnd */ 0,
+ /* IChoice */ ISJMP,
+ /* IJmp */ ISJMP | ISNOFAIL,
+ /* ICall */ ISJMP,
+ /* IOpenCall */ ISFENVOFF,
+ /* ICommit */ ISJMP,
+ /* IPartialCommit */ ISJMP,
+ /* IBackCommit */ ISJMP,
+ /* IFailTwice */ 0,
+ /* IFail */ 0,
+ /* IGiveup */ 0,
+ /* IFunc */ 0,
+ /* ILFunc */ ISFENVOFF,
+ /* IFullCapture */ ISCAPTURE | ISNOFAIL | ISFENVOFF,
+ /* IEmptyCapture */ ISCAPTURE | ISNOFAIL | ISMOVABLE | ISFENVOFF,
+ /* IOpenCapture */ ISCAPTURE | ISNOFAIL | ISMOVABLE | ISFENVOFF,
+ /* ICloseCapture */ ISCAPTURE | ISNOFAIL | ISMOVABLE | ISFENVOFF
+};
+
+
+typedef union Instruction {
+ struct Inst {
+ byte code;
+ byte aux;
+ short offset;
+ } i;
+ PattFunc f;
+ byte buff[1];
+} Instruction;
+
+static const Instruction giveup = {{IGiveup, 0, 0}};
+
+#define getkind(op) ((op)->i.aux & 0xF)
+#define getoff(op) (((op)->i.aux >> 4) & 0xF)
+
+#define dest(p,x) ((x) + ((p)+(x))->i.offset)
+
+#define MAXOFF 0xF
+
+#define isprop(op,p) (opproperties[(op)->i.code] & (p))
+#define isjmp(op) isprop(op, ISJMP)
+#define iscapture(op) isprop(op, ISCAPTURE)
+#define ischeck(op) isprop(op, ISCHECK)
+#define istest(op) isprop(op, ISTEST)
+#define isnofail(op) isprop(op, ISNOFAIL)
+#define ismovable(op) isprop(op, ISMOVABLE)
+#define isfenvoff(op) isprop(op, ISFENVOFF)
+#define hascharset(op) isprop(op, HASCHARSET)
+
+
+/* kinds of captures */
+typedef enum CapKind {
+ Cclose, Cposition, Cconst, Csimple, Ctable, Cfunction,
+ Cquery, Cstring, Csubst, Caccum
+} CapKind;
+
+#define iscapnosize(k) ((k) == Cposition || (k) == Cconst)
+
+
+typedef struct Capture {
+ const char *s; /* position */
+ short idx;
+ byte kind;
+ byte siz;
+} Capture;
+
+
+/* maximum size (in elements) for a pattern */
+#define MAXPATTSIZE (SHRT_MAX - 10)
+
+
+/* size (in elements) for an instruction plus extra l bytes */
+#define instsize(l) (((l) - 1)/sizeof(Instruction) + 2)
+
+
+/* size (in elements) for a ISet instruction */
+#define CHARSETINSTSIZE instsize(CHARSETSIZE)
+
+
+
+#define loopset(v,b) { int v; for (v = 0; v < CHARSETSIZE; v++) b; }
+
+
+#define testchar(st,c) (((int)(st)[((c) >> 3)] & (1 << ((c) & 7))))
+#define setchar(st,c) ((st)[(c) >> 3] |= (1 << ((c) & 7)))
+
+
+
+static int sizei (const Instruction *i) {
+ if (hascharset(i)) return CHARSETINSTSIZE;
+ else if (i->i.code == IFunc) return i->i.offset;
+ else return 1;
+}
+
+
+static const char *val2str (lua_State *L, int idx) {
+ const char *k = lua_tostring(L, idx);
+ if (k != NULL)
+ return lua_pushfstring(L, "rule '%s'", k);
+ else
+ return lua_pushfstring(L, "rule <a %s>", luaL_typename(L, -1));
+}
+
+
+static int getposition (lua_State *L, int t, int i) {
+ int res;
+ lua_getfenv(L, -1);
+ lua_rawgeti(L, -1, i); /* get key from pattern's environment */
+ lua_gettable(L, t); /* get position from positions table */
+ res = lua_tointeger(L, -1);
+ if (res == 0) { /* key has no registered position? */
+ lua_rawgeti(L, -2, i); /* get key again */
+ luaL_error(L, "%s is not defined in given grammar", val2str(L, -1));
+ }
+ lua_pop(L, 2); /* remove environment and position */
+ return res;
+}
+
+
+
+/*
+** {======================================================
+** Printing patterns
+** =======================================================
+*/
+
+
+static void printcharset (const Charset st) {
+ int i;
+ printf("[");
+ for (i = 0; i <= UCHAR_MAX; i++) {
+ int first = i;
+ while (testchar(st, i) && i <= UCHAR_MAX) i++;
+ if (i - 1 == first) /* unary range? */
+ printf("(%02x)", first);
+ else if (i - 1 > first) /* non-empty range? */
+ printf("(%02x-%02x)", first, i - 1);
+ }
+ printf("]");
+}
+
+
+static void printcapkind (int kind) {
+ const char *const modes[] = {
+ "close", "position", "constant", "simple", "table", "function",
+ "query", "string", "substitution", "accumulator"};
+ printf("%s", modes[kind]);
+}
+
+
+static void printinst (const Instruction *op, const Instruction *p) {
+ const char *const names[] = {
+ "any", "char", "set", "zset",
+ "testany", "testchar", "testset", "testzset",
+ "span", "spanz",
+ "ret", "end",
+ "choice", "jmp", "call", "open_call",
+ "commit", "partial_commit", "back_commit", "failtwice", "fail", "giveup",
+ "func", "Luafunc",
+ "fullcapture", "emptycapture", "opencapture", "closecapture"
+ };
+ printf("%02d: %s ", p - op, names[p->i.code]);
+ switch ((Opcode)p->i.code) {
+ case IChar: {
+ printf("'%c'", p->i.aux);
+ break;
+ }
+ case ITestChar: {
+ printf("'%c'", p->i.aux);
+ printf("-> %d", dest(0, p) - op);
+ break;
+ }
+ case IAny: {
+ printf("* %d", p->i.aux);
+ break;
+ }
+ case ITestAny: {
+ printf("* %d", p->i.aux);
+ printf("-> %d", dest(0, p) - op);
+ break;
+ }
+ case IFullCapture: case IOpenCapture:
+ case IEmptyCapture: case ICloseCapture: {
+ printcapkind(getkind(p));
+ printf("(n = %d)", getoff(p));
+ /* go through */
+ }
+ case ILFunc: {
+ printf(" (%d)", p->i.offset);
+ break;
+ }
+ case ISet: case IZSet: case ISpan: case ISpanZ: {
+ printcharset((p+1)->buff);
+ break;
+ }
+ case ITestSet: case ITestZSet: {
+ printcharset((p+1)->buff);
+ printf("-> %d", dest(0, p) - op);
+ break;
+ }
+ case IOpenCall: {
+ printf("-> %d", p->i.offset);
+ break;
+ }
+ case IChoice: {
+ printf("-> %d (%d)", dest(0, p) - op, p->i.aux);
+ break;
+ }
+ case IJmp: case ICall: case ICommit:
+ case IPartialCommit: case IBackCommit: {
+ printf("-> %d", dest(0, p) - op);
+ break;
+ }
+ default: break;
+ }
+ printf("\n");
+}
+
+
+static void printpatt (Instruction *p) {
+ Instruction *op = p;
+ for (;;) {
+ printinst(op, p);
+ if (p->i.code == IEnd) break;
+ p += sizei(p);
+ }
+}
+
+
+static void printcap (Capture *cap) {
+ for (; cap->s; cap++) {
+ printcapkind(cap->kind);
+ printf(" (idx: %d - size: %d) -> %p\n", cap->idx, cap->siz, cap->s);
+ }
+}
+
+/* }====================================================== */
+
+
+
+
+/*
+** {======================================================
+** Virtual Machine
+** =======================================================
+*/
+
+
+typedef struct Stack {
+ const char *s;
+ const Instruction *p;
+ int caplevel;
+} Stack;
+
+
+static Capture *doublecap (lua_State *L, Capture *cap, int captop) {
+ Capture *newc;
+ if (captop >= INT_MAX/((int)sizeof(Capture) * 2))
+ luaL_error(L, "too many captures");
+ newc = (Capture *)lua_newuserdata(L, captop * 2 * sizeof(Capture));
+ memcpy(newc, cap, captop * sizeof(Capture));
+ lua_replace(L, CAPLISTIDX);
+ return newc;
+}
+
+
+static const char *match (lua_State *L, const char *o, const char *s,
+ const char *e, Instruction *op, Capture *capture) {
+ Stack stackbase[MAXBACK];
+ Stack *stacklimit = stackbase + MAXBACK;
+ Stack *stack = stackbase; /* point to first empty slot in stack */
+ int capsize = IMAXCAPTURES;
+ int captop = 0; /* point to first empty slot in captures */
+ const Instruction *p = op;
+ stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack++;
+ for (;;) {
+#if defined(DEBUG)
+ printf("s: |%s| stck: %d c: %d ", s, stack - stackbase, captop);
+ printinst(op, p);
+#endif
+ switch ((Opcode)p->i.code) {
+ case IEnd: {
+ assert(stack == stackbase + 1);
+ capture[captop].kind = Cclose;
+ capture[captop].s = NULL;
+ return s;
+ }
+ case IGiveup: {
+ assert(stack == stackbase);
+ return NULL;
+ }
+ case IRet: {
+ assert(stack > stackbase && (stack - 1)->s == NULL);
+ p = (--stack)->p;
+ continue;
+ }
+ case IAny: {
+ int n = p->i.aux;
+ if (n > e - s) goto fail;
+ else { p++; s += n; }
+ continue;
+ }
+ case ITestAny: {
+ int n = p->i.aux;
+ if (n > e - s) p += p->i.offset;
+ else { p++; s += n; }
+ continue;
+ }
+ case IChar: {
+ if ((byte)*s != p->i.aux || s >= e) goto fail;
+ else { p++; s++; }
+ continue;
+ }
+ case ITestChar: {
+ if ((byte)*s != p->i.aux || s >= e) p += p->i.offset;
+ else { p++; s++; }
+ continue;
+ }
+ case ISet: {
+ int c = (unsigned char)*s;
+ if (!testchar((p+1)->buff, c)) goto fail;
+ else { p += CHARSETINSTSIZE; s++; }
+ continue;
+ }
+ case ITestSet: {
+ int c = (unsigned char)*s;
+ if (!testchar((p+1)->buff, c)) p += p->i.offset;
+ else { p += CHARSETINSTSIZE; s++; }
+ continue;
+ }
+ case IZSet: {
+ int c = (unsigned char)*s;
+ if (!testchar((p+1)->buff, c) || s >= e) goto fail;
+ else { p += CHARSETINSTSIZE; s++; }
+ continue;
+ }
+ case ITestZSet: {
+ int c = (unsigned char)*s;
+ if (!testchar((p+1)->buff, c) || s >= e) p += p->i.offset;
+ else { p += CHARSETINSTSIZE; s++; }
+ continue;
+ }
+ case ISpan: {
+ for (;; s++) {
+ int c = (unsigned char)*s;
+ if (!testchar((p+1)->buff, c)) break;
+ }
+ p += CHARSETINSTSIZE;
+ continue;
+ }
+ case ISpanZ: {
+ for (; s < e; s++) {
+ int c = (unsigned char)*s;
+ if (!testchar((p+1)->buff, c)) break;
+ }
+ p += CHARSETINSTSIZE;
+ continue;
+ }
+ case IFunc: {
+ const char *r = (p+1)->f((p+2)->buff, o, s, e);
+ if (r == NULL) goto fail;
+ s = r;
+ p += p->i.offset;
+ continue;
+ }
+ case ILFunc: {
+ lua_Integer res;
+ lua_rawgeti(L, PENVIDX, p->i.offset); /* push function */
+ lua_pushvalue(L, SUBJIDX); /* push original subject */
+ lua_pushinteger(L, s - o + 1); /* current position */
+ lua_call(L, 2, 1);
+ res = lua_tointeger(L, -1) - 1;
+ lua_pop(L, 1);
+ if (res < s - o || res > e - o) goto fail;
+ s = o + res;
+ p++;
+ continue;
+ }
+ case IJmp: {
+ p += p->i.offset;
+ continue;
+ }
+ case IChoice: {
+ if (stack >= stacklimit)
+ return (luaL_error(L, "too many pending calls/choices"), (char *)0);
+ stack->p = dest(0, p);
+ stack->s = s - p->i.aux;
+ stack->caplevel = captop;
+ stack++;
+ p++;
+ continue;
+ }
+ case ICall: {
+ if (stack >= stacklimit)
+ return (luaL_error(L, "too many pending calls/choices"), (char *)0);
+ stack->s = NULL;
+ stack->p = p + 1; /* save return address */
+ stack++;
+ p += p->i.offset;
+ continue;
+ }
+ case ICommit: {
+ assert(stack > stackbase && (stack - 1)->s != NULL);
+ stack--;
+ p += p->i.offset;
+ continue;
+ }
+ case IPartialCommit: {
+ assert(stack > stackbase && (stack - 1)->s != NULL);
+ (stack - 1)->s = s;
+ (stack - 1)->caplevel = captop;
+ p += p->i.offset;
+ continue;
+ }
+ case IBackCommit: {
+ assert(stack > stackbase && (stack - 1)->s != NULL);
+ s = (--stack)->s;
+ captop = stack->caplevel;
+ p += p->i.offset;
+ continue;
+ }
+ case IFailTwice:
+ assert(stack > stackbase);
+ stack--;
+ /* go through */
+ case IFail:
+ fail: { /* pattern failed: try to backtrack */
+ do { /* remove pending calls */
+ assert(stack > stackbase);
+ s = (--stack)->s;
+ } while (s == NULL);
+ captop = stack->caplevel;
+ p = stack->p;
+ continue;
+ }
+ case ICloseCapture: {
+ const char *s1 = s - getoff(p);
+ assert(captop > 0);
+ if (capture[captop - 1].siz == 0 &&
+ s1 - capture[captop - 1].s < UCHAR_MAX) {
+ capture[captop - 1].siz = s1 - capture[captop - 1].s + 1;
+ p++;
+ continue;
+ }
+ else {
+ capture[captop].siz = 1; /* mark entry as closed */
+ goto capture;
+ }
+ }
+ case IEmptyCapture:
+ capture[captop].siz = 1; /* mark entry as closed */
+ goto capture;
+ case IOpenCapture:
+ capture[captop].siz = 0; /* mark entry as open */
+ goto capture;
+ case IFullCapture:
+ capture[captop].siz = getoff(p) + 1; /* save capture size */
+ capture: {
+ capture[captop].s = s - getoff(p);
+ capture[captop].idx = p->i.offset;
+ capture[captop].kind = getkind(p);
+ if (++captop >= capsize) {
+ capture = doublecap(L, capture, captop);
+ capsize = 2 * captop;
+ }
+ p++;
+ continue;
+ }
+ case IOpenCall:
+ luaL_error(L, "reference to unknown rule #%d", p->i.offset);
+ default: assert(0); return NULL;
+ }
+ }
+}
+
+/* }====================================================== */
+
+
+/*
+** {======================================================
+** Verifier
+** =======================================================
+*/
+
+
+static int verify (lua_State *L, Instruction *op, const Instruction *p,
+ Instruction *e, int postable, int rule) {
+ static const char dummy[] = "";
+ Stack back[MAXBACK];
+ int backtop = 0; /* point to first empty slot in back */
+ while (p != e) {
+ switch ((Opcode)p->i.code) {
+ case IRet: {
+ p = back[--backtop].p;
+ continue;
+ }
+ case IChoice: {
+ if (backtop >= MAXBACK)
+ return luaL_error(L, "too many pending calls/choices");
+ back[backtop].p = dest(0, p);
+ back[backtop++].s = dummy;
+ p++;
+ continue;
+ }
+ case ICall: {
+ assert((p + 1)->i.code != IRet); /* no tail call */
+ if (backtop >= MAXBACK)
+ return luaL_error(L, "too many pending calls/choices");
+ back[backtop].s = NULL;
+ back[backtop++].p = p + 1;
+ goto dojmp;
+ }
+ case IOpenCall: {
+ int i;
+ if (postable == 0) /* grammar still not fixed? */
+ goto fail; /* to be verified later */
+ for (i = 0; i < backtop; i++) {
+ if (back[i].s == NULL && back[i].p == p + 1)
+ return luaL_error(L, "%s is left recursive", val2str(L, rule));
+ }
+ if (backtop >= MAXBACK)
+ return luaL_error(L, "too many pending calls/choices");
+ back[backtop].s = NULL;
+ back[backtop++].p = p + 1;
+ p = op + getposition(L, postable, p->i.offset);
+ continue;
+ }
+ case IBackCommit:
+ case ICommit: {
+ assert(backtop > 0 && p->i.offset > 0);
+ backtop--;
+ goto dojmp;
+ }
+ case IPartialCommit: {
+ assert(backtop > 0);
+ if (p->i.offset > 0) goto dojmp; /* forward jump */
+ else { /* loop will be detected when checking corresponding rule */
+ assert(postable != 0);
+ backtop--;
+ p++; /* just go on now */
+ continue;
+ }
+ }
+ case ITestAny:
+ case ITestChar: /* all these cases jump for empty subject */
+ case ITestSet:
+ case ITestZSet:
+ case IJmp:
+ dojmp: {
+ p += p->i.offset;
+ continue;
+ }
+ case IAny:
+ case IChar:
+ case ISet:
+ case IZSet:
+ case IFailTwice: /* assume that first level failed; try to backtrack */
+ goto fail;
+ case IFail: {
+ if (p->i.aux) { /* is an 'and' predicate? */
+ assert((p - 1)->i.code == IBackCommit && (p - 1)->i.offset == 2);
+ p++; /* pretend it succeeded and go ahead */
+ continue;
+ }
+ /* else go through */
+ }
+ fail: { /* pattern failed: try to backtrack */
+ do {
+ if (backtop-- == 0)
+ return 1; /* no more backtracking */
+ } while (back[backtop].s == NULL);
+ p = back[backtop].p;
+ continue;
+ }
+ case ISpan: case ISpanZ:
+ case IOpenCapture:
+ case ICloseCapture:
+ case IEmptyCapture:
+ case IFullCapture: {
+ p += sizei(p);
+ continue;
+ }
+ case IFunc: {
+ const char *r = (p+1)->f((p+2)->buff, dummy, dummy, dummy);
+ if (r == NULL) goto fail;
+ p += p->i.offset;
+ continue;
+ }
+ case ILFunc: {
+ goto fail; /* be liberal in this case */
+ }
+ case IEnd: /* cannot happen (should stop before it) */
+ default: assert(0); return 0;
+ }
+ }
+ assert(backtop == 0);
+ return 0;
+}
+
+
+static void checkrule (lua_State *L, Instruction *op, int from, int to,
+ int postable, int rule) {
+ int i;
+ int lastopen = 0; /* more recent OpenCall seen in the code */
+ for (i = from; i < to; i += sizei(op + i)) {
+ if (op[i].i.code == IPartialCommit && op[i].i.offset < 0) { /* loop? */
+ int start = dest(op, i);
+ assert(op[start - 1].i.code == IChoice && dest(op, start - 1) == i + 1);
+ if (start <= lastopen) { /* loop does contain an open call? */
+ if (!verify(L, op, op + start, op + i, postable, rule)) /* check body */
+ luaL_error(L, "possible infinite loop in %s", val2str(L, rule));
+ }
+ }
+ else if (op[i].i.code == IOpenCall)
+ lastopen = i;
+ }
+ assert(op[i - 1].i.code == IRet);
+ verify(L, op, op + from, op + to - 1, postable, rule);
+}
+
+
+
+
+/* }====================================================== */
+
+
+
+
+/*
+** {======================================================
+** Building Patterns
+** =======================================================
+*/
+
+enum charsetanswer { NOINFO, ISCHARSET, VALIDSTARTS };
+
+typedef struct CharsetTag {
+ enum charsetanswer tag;
+ Charset cs;
+} CharsetTag;
+
+
+static Instruction *getpatt (lua_State *L, int idx, int *size);
+
+
+static void check2test (Instruction *p, int n) {
+ assert(ischeck(p));
+ p->i.code += ITestAny - IAny;
+ p->i.offset = n;
+}
+
+
+/*
+** invert array slice p[0]-p[e] (both inclusive)
+*/
+static void invert (Instruction *p, int e) {
+ int i;
+ for (i = 0; i < e; i++, e--) {
+ Instruction temp = p[i];
+ p[i] = p[e];
+ p[e] = temp;
+ }
+}
+
+
+/*
+** rotate array slice p[0]-p[e] (both inclusive) 'n' steps
+** to the 'left'
+*/
+static void rotate (Instruction *p, int e, int n) {
+ invert(p, n - 1);
+ invert(p + n, e - n);
+ invert(p, e);
+}
+
+
+#define op_step(p) ((p)->i.code == IAny ? (p)->i.aux : 1)
+
+
+static int skipchecks (Instruction *p, int up, int *pn) {
+ int i, n = 0;
+ for (i = 0; ischeck(p + i); i += sizei(p + i)) {
+ int st = op_step(p + i);
+ if (n + st > MAXOFF - up) break;
+ n += st;
+ }
+ *pn = n;
+ return i;
+}
+
+
+#define ismovablecap(op) (ismovable(op) && getoff(op) < MAXOFF)
+
+static void optimizecaptures (Instruction *p) {
+ int i;
+ int limit = 0;
+ for (i = 0; p[i].i.code != IEnd; i += sizei(p + i)) {
+ if (isjmp(p + i) && dest(p, i) >= limit)
+ limit = dest(p, i) + 1; /* do not optimize jump targets */
+ else if (i >= limit && ismovablecap(p + i) && ischeck(p + i + 1)) {
+ int end, n, j; /* found a border capture|check */
+ int maxoff = getoff(p + i);
+ int start = i;
+ /* find first capture in the group */
+ while (start > limit && ismovablecap(p + start - 1)) {
+ start--;
+ if (getoff(p + start) > maxoff) maxoff = getoff(p + start);
+ }
+ end = skipchecks(p + i + 1, maxoff, &n) + i; /* find last check */
+ if (n == 0) continue; /* first check is too big to move across */
+ assert(n <= MAXOFF && start <= i && i < end);
+ for (j = start; j <= i; j++)
+ p[j].i.aux += (n << 4); /* correct offset of captures to be moved */
+ rotate(p + start, end - start, i - start + 1); /* move them up */
+ i = end;
+ assert(ischeck(p + start) && iscapture(p + i));
+ }
+ }
+}
+
+
+static int target (Instruction *p, int i) {
+ while (p[i].i.code == IJmp) i += p[i].i.offset;
+ return i;
+}
+
+
+static void optimizejumps (Instruction *p) {
+ int i;
+ for (i = 0; p[i].i.code != IEnd; i += sizei(p + i)) {
+ if (isjmp(p + i))
+ p[i].i.offset = target(p, dest(p, i)) - i;
+ }
+}
+
+
+static void optimizechoice (Instruction *p) {
+ assert(p->i.code == IChoice);
+ if (ischeck(p + 1)) {
+ int lc = sizei(p + 1);
+ rotate(p, lc, 1);
+ assert(ischeck(p) && (p + lc)->i.code == IChoice);
+ (p + lc)->i.aux = op_step(p);
+ check2test(p, (p + lc)->i.offset);
+ (p + lc)->i.offset -= lc;
+ }
+}
+
+
+/*
+** A 'headfail' pattern is a pattern that can only fails in its first
+** instruction, which must be a check.
+*/
+static int isheadfail (Instruction *p) {
+ if (!ischeck(p)) return 0;
+ /* check that other operations cannot fail */
+ for (p += sizei(p); p->i.code != IEnd; p += sizei(p))
+ if (!isnofail(p)) return 0;
+ return 1;
+}
+
+
+#define checkpattern(L, idx) ((Instruction *)luaL_checkudata(L, idx, "pattern"))
+
+
+static int jointable (lua_State *L, int p1) {
+ int n, n1, i;
+ lua_getfenv(L, p1);
+ n1 = lua_objlen(L, -1); /* number of elements in p1's env */
+ lua_getfenv(L, -2);
+ if (n1 == 0 || lua_equal(L, -2, -1)) {
+ lua_pop(L, 2);
+ return 0; /* no need to change anything */
+ }
+ n = lua_objlen(L, -1); /* number of elements in p's env */
+ if (n == 0) {
+ lua_pop(L, 1); /* removes p env */
+ lua_setfenv(L, -2); /* p now shares p1's env */
+ return 0; /* no need to correct anything */
+ }
+ lua_createtable(L, n + n1, 0);
+ /* stack: p; p1 env; p env; new p env */
+ for (i = 1; i <= n; i++) {
+ lua_rawgeti(L, -2, i);
+ lua_rawseti(L, -2, i);
+ }
+ for (i = 1; i <= n1; i++) {
+ lua_rawgeti(L, -3, i);
+ lua_rawseti(L, -2, n + i);
+ }
+ lua_setfenv(L, -4); /* new table becomes p env */
+ lua_pop(L, 2); /* remove p1 env and old p env */
+ return n;
+}
+
+
+#define copypatt(p1,p2,sz) memcpy(p1, p2, (sz) * sizeof(Instruction));
+
+#define pattsize(L,idx) (lua_objlen(L, idx)/sizeof(Instruction) - 1)
+
+
+static int addpatt (lua_State *L, Instruction *p, int p1idx) {
+ Instruction *p1 = (Instruction *)lua_touserdata(L, p1idx);
+ int sz = pattsize(L, p1idx);
+ int corr = jointable(L, p1idx);
+ copypatt(p, p1, sz + 1);
+ if (corr != 0) {
+ Instruction *px;
+ for (px = p; px < p + sz; px += sizei(px)) {
+ if (isfenvoff(px) && px->i.offset != 0)
+ px->i.offset += corr;
+ }
+ }
+ return sz;
+}
+
+
+static void setinstaux (Instruction *i, Opcode op, int offset, int aux) {
+ i->i.code = op;
+ i->i.offset = offset;
+ i->i.aux = aux;
+}
+
+#define setinst(i,op,off) setinstaux(i,op,off,0)
+
+static int value2fenv (lua_State *L, int vidx) {
+ lua_createtable(L, 1, 0);
+ lua_pushvalue(L, vidx);
+ lua_rawseti(L, -2, 1);
+ lua_setfenv(L, -2);
+ return 1;
+}
+
+
+static Instruction *newpatt (lua_State *L, size_t n) {
+ Instruction *p;
+ if (n >= MAXPATTSIZE - 1)
+ luaL_error(L, "pattern too big");
+ p = (Instruction *)lua_newuserdata(L, (n + 1) * sizeof(Instruction));
+ luaL_getmetatable(L, "pattern");
+ lua_setmetatable(L, -2);
+ setinst(p + n, IEnd, 0);
+ return p;
+}
+
+
+static void fillcharset (Instruction *p, Charset cs) {
+ switch (p[0].i.code) {
+ case IZSet: case ITestZSet:
+ assert(testchar(p[1].buff, '\0'));
+ /* go through */
+ case ISet: case ITestSet: {
+ loopset(i, cs[i] = p[1].buff[i]);
+ break;
+ }
+ case IChar: case ITestChar: {
+ loopset(i, cs[i] = 0);
+ setchar(cs, p[0].i.aux);
+ break;
+ }
+ default: { /* any char may start unhandled instructions */
+ loopset(i, cs[i] = 0xff);
+ break;
+ }
+ }
+}
+
+
+/*
+** Function 'tocharset' gets information about which chars may be a
+** valid start for a pattern.
+*/
+
+static enum charsetanswer tocharset (Instruction *p, CharsetTag *c) {
+ if (ischeck(p)) {
+ fillcharset(p, c->cs);
+ if ((p + sizei(p))->i.code == IEnd && op_step(p) == 1)
+ c->tag = ISCHARSET;
+ else
+ c->tag = VALIDSTARTS;
+ }
+ else
+ c->tag = NOINFO;
+ return c->tag;
+}
+
+
+static int exclusiveset (Charset c1, Charset c2) {
+ /* non-empty intersection? */
+ loopset(i, {if ((c1[i] & c2[i]) != 0) return 0;});
+ return 1; /* no intersection */
+}
+
+
+static int exclusive (CharsetTag *c1, CharsetTag *c2) {
+ if (c1->tag == NOINFO || c2->tag == NOINFO)
+ return 0; /* one of them is not filled */
+ else return exclusiveset(c1->cs, c2->cs);
+}
+
+
+#define correctset(p) { if (testchar(p[1].buff, '\0')) p->i.code++; }
+
+
+static Instruction *newcharset (lua_State *L) {
+ Instruction *p = newpatt(L, CHARSETINSTSIZE);
+ p[0].i.code = ISet;
+ loopset(i, p[1].buff[i] = 0);
+ return p;
+}
+
+
+static int set_l (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+ if (l == 1)
+ getpatt(L, 1, NULL); /* a unit set is equivalent to a literal */
+ else {
+ Instruction *p = newcharset(L);
+ while (l--) {
+ setchar(p[1].buff, (unsigned char)(*s));
+ s++;
+ }
+ correctset(p);
+ }
+ return 1;
+}
+
+
+static int range_l (lua_State *L) {
+ int arg;
+ int top = lua_gettop(L);
+ Instruction *p = newcharset(L);
+ for (arg = 1; arg <= top; arg++) {
+ int c;
+ size_t l;
+ const char *r = luaL_checklstring(L, arg, &l);
+ luaL_argcheck(L, l == 2, arg, "range must have two characters");
+ for (c = (byte)r[0]; c <= (byte)r[1]; c++)
+ setchar(p[1].buff, c);
+ }
+ correctset(p);
+ return 1;
+}
+
+
+static int nter_l (lua_State *L) {
+ Instruction *p;
+ luaL_argcheck(L, !lua_isnoneornil(L, 1), 1, "non-nil value expected");
+ p = newpatt(L, 1);
+ setinst(p, IOpenCall, value2fenv(L, 1));
+ return 1;
+}
+
+
+
+static void checkfield (lua_State *L) {
+ Instruction *p = (Instruction *)lua_touserdata(L, -1);
+ if (p != NULL) { /* value is a userdata? */
+ if (lua_getmetatable(L, -1)) { /* does it have a metatable? */
+ lua_getfield(L, LUA_REGISTRYINDEX, "pattern");
+ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
+ lua_pop(L, 2); /* remove both metatables */
+ return;
+ }
+ }
+ }
+ luaL_error(L, "invalid field in grammar");
+}
+
+
+static Instruction *fix_l (lua_State *L, int t) {
+ Instruction *p;
+ int i;
+ int totalsize = 2; /* include initial call and jump */
+ int n = 0; /* number of rules */
+ int base = lua_gettop(L);
+ lua_newtable(L); /* to store relative positions of each rule */
+ lua_pushinteger(L, 1); /* default initial rule */
+ /* collect patterns and compute sizes */
+ lua_pushnil(L);
+ while (lua_next(L, t) != 0) {
+ int l;
+ if (lua_tonumber(L, -2) == 1 && lua_isstring(L, -1)) {
+ lua_replace(L, base + 2); /* use this value as initial rule */
+ continue;
+ }
+ checkfield(L);
+ l = pattsize(L, -1) + 1; /* space for pattern + ret */
+ if (totalsize >= MAXPATTSIZE - l)
+ luaL_error(L, "grammar too large");
+ luaL_checkstack(L, LUA_MINSTACK, "grammar has too many rules");
+ lua_insert(L, -2); /* put key on top */
+ lua_pushvalue(L, -1); /* duplicate key (for lua_next) */
+ lua_pushvalue(L, -1); /* duplicate key (to index positions table)) */
+ lua_pushinteger(L, totalsize); /* position for this rule */
+ lua_settable(L, base + 1); /* store key=>position in positions table */
+ totalsize += l;
+ n++;
+ }
+ luaL_argcheck(L, n > 0, t, "empty grammar");
+ p = newpatt(L, totalsize); /* create new pattern */
+ p++; /* save space for call */
+ setinst(p++, IJmp, totalsize - 1); /* after call, jumps to the end */
+ for (i = 1; i <= n; i++) { /* copy all rules into new pattern */
+ p += addpatt(L, p, base + 1 + i*2);
+ setinst(p++, IRet, 0);
+ }
+ p -= totalsize; /* back to first position */
+ totalsize = 2; /* go through each rule's position */
+ for (i = 1; i <= n; i++) { /* check all rules */
+ int l = pattsize(L, base + 1 + i*2) + 1;
+ checkrule(L, p, totalsize, totalsize + l, base + 1, base + 2 + i*2);
+ totalsize += l;
+ }
+ lua_pushvalue(L, base + 2); /* get initial rule */
+ lua_gettable(L, base + 1); /* get its position in postions table */
+ i = lua_tonumber(L, -1); /* convert to number */
+ lua_pop(L, 1);
+ if (i == 0) /* is it defined? */
+ luaL_error(L, "initial rule not defined in given grammar");
+ setinst(p, ICall, i); /* first instruction calls initial rule */
+ /* correct calls */
+ for (i = 0; i < totalsize; i += sizei(p + i)) {
+ if (p[i].i.code == IOpenCall) {
+ int pos = getposition(L, base + 1, p[i].i.offset);
+ p[i].i.code = (p[target(p, i + 1)].i.code == IRet) ? IJmp : ICall;
+ p[i].i.offset = pos - i;
+ }
+ }
+ optimizejumps(p);
+ lua_replace(L, t); /* put new pattern in old's position */
+ lua_settop(L, base); /* remove rules and positions table */
+ return p;
+}
+
+
+static Instruction *any (lua_State *L, int n, int extra, int *offsetp) {
+ int offset = offsetp ? *offsetp : 0;
+ Instruction *p = newpatt(L, (n - 1)/UCHAR_MAX + extra + 1);
+ Instruction *p1 = p + offset;
+ for (; n > UCHAR_MAX; n -= UCHAR_MAX)
+ setinstaux(p1++, IAny, 0, UCHAR_MAX);
+ setinstaux(p1++, IAny, 0, n);
+ if (offsetp) *offsetp = p1 - p;
+ return p;
+}
+
+
+static Instruction *getpatt (lua_State *L, int idx, int *size) {
+ Instruction *p;
+ switch (lua_type(L, idx)) {
+ case LUA_TSTRING: {
+ size_t i, len;
+ const char *s = lua_tolstring(L, idx, &len);
+ p = newpatt(L, len);
+ for (i = 0; i < len; i++)
+ setinstaux(p + i, IChar, 0, (unsigned char)s[i]);
+ lua_replace(L, idx);
+ break;
+ }
+ case LUA_TNUMBER: {
+ int n = lua_tointeger(L, idx);
+ if (n == 0) /* empty pattern? */
+ p = newpatt(L, 0);
+ else if (n > 0)
+ p = any(L, n, 0, NULL);
+ else if (-n <= UCHAR_MAX) {
+ p = newpatt(L, 2);
+ setinstaux(p, ITestAny, 2, -n);
+ setinst(p + 1, IFail, 0);
+ }
+ else {
+ int offset = 2; /* space for ITestAny & IChoice */
+ p = any(L, -n - UCHAR_MAX, 3, &offset);
+ setinstaux(p, ITestAny, offset + 1, UCHAR_MAX);
+ setinstaux(p + 1, IChoice, offset, UCHAR_MAX);
+ setinst(p + offset, IFailTwice, 0);
+ }
+ lua_replace(L, idx);
+ break;
+ }
+ case LUA_TBOOLEAN: {
+ if (lua_toboolean(L, idx)) /* true? */
+ p = newpatt(L, 0); /* empty pattern (always succeeds) */
+ else {
+ p = newpatt(L, 1);
+ setinst(p, IFail, 0);
+ }
+ lua_replace(L, idx);
+ break;
+ }
+ case LUA_TTABLE: {
+ p = fix_l(L, idx);
+ break;
+ }
+ case LUA_TFUNCTION: {
+ p = newpatt(L, 1);
+ setinst(p, ILFunc, value2fenv(L, idx));
+ lua_replace(L, idx);
+ break;
+ }
+ default: {
+ p = checkpattern(L, idx);
+ break;
+ }
+ }
+ if (size) *size = pattsize(L, idx);
+ return p;
+}
+
+
+static int getpattl (lua_State *L, int idx) {
+ int size;
+ getpatt(L, idx, &size);
+ return size;
+}
+
+
+static int pattern_l (lua_State *L) {
+ lua_settop(L, 1);
+ getpatt(L, 1, NULL);
+ return 1;
+}
+
+
+#define isany(p) ((p)->i.code == IAny && ((p) + 1)->i.code == IEnd)
+
+
+static int concat_l (lua_State *L) {
+ /* p1; p2; */
+ int l1, l2;
+ Instruction *p1 = getpatt(L, 1, &l1);
+ Instruction *p2 = getpatt(L, 2, &l2);
+ if (isany(p1) && isany(p2))
+ any(L, p1->i.aux + p2->i.aux, 0, NULL);
+ else {
+ Instruction *op = newpatt(L, l1 + l2);
+ Instruction *p = op + addpatt(L, op, 1);
+ addpatt(L, p, 2);
+ optimizecaptures(op);
+ }
+ return 1;
+}
+
+
+static int diff_l (lua_State *L) {
+ int l1, l2;
+ Instruction *p1 = getpatt(L, 1, &l1);
+ Instruction *p2 = getpatt(L, 2, &l2);
+ CharsetTag st1, st2;
+ if (tocharset(p1, &st1) == ISCHARSET && tocharset(p2, &st2) == ISCHARSET) {
+ Instruction *p = newcharset(L);
+ loopset(i, p[1].buff[i] = st1.cs[i] & ~st2.cs[i]);
+ correctset(p);
+ }
+ else if (isheadfail(p2)) {
+ Instruction *p = newpatt(L, l2 + 1 + l1);
+ p += addpatt(L, p, 2);
+ check2test(p - l2, l2 + 1);
+ setinst(p++, IFail, 0);
+ addpatt(L, p, 1);
+ }
+ else { /* !e2 . e1 */
+ /* !e -> choice L1; e; failtwice; L1: ... */
+ Instruction *p = newpatt(L, 1 + l2 + 1 + l1);
+ Instruction *pi = p;
+ setinst(p++, IChoice, 1 + l2 + 1);
+ p += addpatt(L, p, 2);
+ setinst(p++, IFailTwice, 0);
+ addpatt(L, p, 1);
+ optimizechoice(pi);
+ }
+ return 1;
+}
+
+
+static int unm_l (lua_State *L) {
+ lua_pushliteral(L, "");
+ lua_insert(L, 1);
+ return diff_l(L);
+}
+
+
+static int pattand_l (lua_State *L) {
+ /* &e -> choice L1; e; backcommit L2; L1: fail; L2: ... */
+ int l1 = getpattl(L, 1);
+ Instruction *p = newpatt(L, 1 + l1 + 2);
+ setinst(p++, IChoice, 1 + l1 + 1);
+ p += addpatt(L, p, 1);
+ setinst(p++, IBackCommit, 2);
+ setinstaux(p, IFail, 0, 1);
+ return 1;
+}
+
+
+static int firstpart (Instruction *p, int l) {
+ if (istest(p)) {
+ int e = p[0].i.offset - 1;
+ if ((p[e].i.code == IJmp || p[e].i.code == ICommit) &&
+ e + p[e].i.offset == l)
+ return e + 1;
+ }
+ else if (p[0].i.code == IChoice) {
+ int e = p[0].i.offset - 1;
+ if (p[e].i.code == ICommit && e + p[e].i.offset == l)
+ return e + 1;
+ }
+ return 0;
+}
+
+
+static Instruction *auxnew (lua_State *L, Instruction **op, int *size,
+ int extra) {
+ *op = newpatt(L, *size + extra);
+ jointable(L, 1);
+ *size += extra;
+ return *op + *size - extra;
+}
+
+
+static int nofail (Instruction *p, int l) {
+ int i;
+ for (i = 0; i < l; i += sizei(p + i)) {
+ if (!isnofail(p + i)) return 0;
+ }
+ return 1;
+}
+
+
+static int interfere (Instruction *p1, int l1, CharsetTag *st2) {
+ if (nofail(p1, l1)) /* p1 cannot fail? */
+ return 0; /* nothing can intefere with it */
+ if (st2->tag == NOINFO) return 1;
+ switch (p1->i.code) {
+ case ITestChar: return testchar(st2->cs, p1->i.aux);
+ case ITestSet: return !exclusiveset(st2->cs, (p1 + 1)->buff);
+ default: assert(p1->i.code == ITestAny); return 1;
+ }
+}
+
+
+static Instruction *basicUnion (lua_State *L, Instruction *p1, int l1,
+ int l2, int *size, CharsetTag *st2) {
+ Instruction *op;
+ CharsetTag st1;
+ tocharset(p1, &st1);
+ if (st1.tag == ISCHARSET && st2->tag == ISCHARSET) {
+ Instruction *p = auxnew(L, &op, size, CHARSETINSTSIZE);
+ setinst(p, ISet, 0);
+ loopset(i, p[1].buff[i] = st1.cs[i] | st2->cs[i]);
+ correctset(p);
+ }
+ else if (exclusive(&st1, st2) || isheadfail(p1)) {
+ Instruction *p = auxnew(L, &op, size, l1 + 1 + l2);
+ copypatt(p, p1, l1);
+ check2test(p, l1 + 1);
+ p += l1;
+ setinst(p++, IJmp, l2 + 1);
+ addpatt(L, p, 2);
+ }
+ else {
+ /* choice L1; e1; commit L2; L1: e2; L2: ... */
+ Instruction *p = auxnew(L, &op, size, 1 + l1 + 1 + l2);
+ setinst(p++, IChoice, 1 + l1 + 1);
+ copypatt(p, p1, l1); p += l1;
+ setinst(p++, ICommit, 1 + l2);
+ addpatt(L, p, 2);
+ optimizechoice(p - (1 + l1 + 1));
+ }
+ return op;
+}
+
+
+static Instruction *separateparts (lua_State *L, Instruction *p1, int l1,
+ int l2, int *size, CharsetTag *st2) {
+ int sp = firstpart(p1, l1);
+ if (sp == 0) /* first part is entire p1? */
+ return basicUnion(L, p1, l1, l2, size, st2);
+ else if ((p1 + sp - 1)->i.code == ICommit || !interfere(p1, sp, st2)) {
+ Instruction *p;
+ int init = *size;
+ int end = init + sp;
+ *size = end;
+ p = separateparts(L, p1 + sp, l1 - sp, l2, size, st2);
+ copypatt(p + init, p1, sp);
+ (p + end - 1)->i.offset = *size - (end - 1);
+ return p;
+ }
+ else { /* must change back to non-optimized choice */
+ Instruction *p;
+ int init = *size;
+ int end = init + sp + 1; /* needs one extra instruction (choice) */
+ int sizefirst = sizei(p1); /* size of p1's first instruction (the test) */
+ *size = end;
+ p = separateparts(L, p1 + sp, l1 - sp, l2, size, st2);
+ copypatt(p + init, p1, sizefirst); /* copy the test */
+ (p + init)->i.offset++; /* correct jump (because of new instruction) */
+ init += sizefirst;
+ setinstaux(p + init, IChoice, sp - sizefirst + 1, 1); init++;
+ copypatt(p + init, p1 + sizefirst, sp - sizefirst - 1);
+ init += sp - sizefirst - 1;
+ setinst(p + init, ICommit, *size - (end - 1));
+ return p;
+ }
+}
+
+
+static int union_l (lua_State *L) {
+ int l1, l2;
+ int size = 0;
+ Instruction *p1 = getpatt(L, 1, &l1);
+ Instruction *p2 = getpatt(L, 2, &l2);
+ CharsetTag st2;
+ if (p1->i.code == IFail) /* check for identity element */
+ lua_pushvalue(L, 2);
+ else if (p2->i.code == IFail)
+ lua_pushvalue(L, 1);
+ else {
+ tocharset(p2, &st2);
+ separateparts(L, p1, l1, l2, &size, &st2);
+ }
+ return 1;
+}
+
+
+static int repeatcharset (lua_State *L, Charset cs, int l1, int n) {
+ /* e; ...; e; span; */
+ int i;
+ Instruction *p = newpatt(L, n*l1 + CHARSETINSTSIZE);
+ for (i = 0; i < n; i++) {
+ p += addpatt(L, p, 1);
+ }
+ setinst(p, ISpan, 0);
+ loopset(k, p[1].buff[k] = cs[k]);
+ correctset(p);
+ return 1;
+}
+
+
+static Instruction *repeatheadfail (lua_State *L, int l1, int n) {
+ /* e; ...; e; L2: e'(L1); jump L2; L1: ... */
+ int i;
+ Instruction *p = newpatt(L, (n + 1)*l1 + 1);
+ Instruction *op = p;
+ for (i = 0; i < n; i++) {
+ p += addpatt(L, p, 1);
+ }
+ p += addpatt(L, p, 1);
+ check2test(p - l1, l1 + 1);
+ setinst(p, IJmp, -l1);
+ return op;
+}
+
+
+static Instruction *repeats (lua_State *L, Instruction *p1, int l1, int n) {
+ /* e; ...; e; choice L1; L2: e; partialcommit L2; L1: ... */
+ int i;
+ Instruction *op = newpatt(L, (n + 1)*l1 + 2);
+ Instruction *p = op;
+ if (!verify(L, p1, p1, p1 + l1, 0, 0))
+ luaL_error(L, "loop body may accept empty string");
+ for (i = 0; i < n; i++) {
+ p += addpatt(L, p, 1);
+ }
+ setinst(p++, IChoice, 1 + l1 + 1);
+ p += addpatt(L, p, 1);
+ setinst(p, IPartialCommit, -l1);
+ return op;
+}
+
+
+static void optionalheadfail (lua_State *L, int l1, int n) {
+ Instruction *op = newpatt(L, n * l1);
+ Instruction *p = op;
+ int i;
+ for (i = 0; i < n; i++) {
+ p += addpatt(L, p, 1);
+ check2test(p - l1, (n - i)*l1);
+ }
+}
+
+
+static void optionals (lua_State *L, int l1, int n) {
+ /* choice L1; e; partialcommit L2; L2: ... e; L1: commit L3; L3: ... */
+ int i;
+ Instruction *op = newpatt(L, n*(l1 + 1) + 1);
+ Instruction *p = op;
+ setinst(p++, IChoice, 1 + n*(l1 + 1));
+ for (i = 0; i < n; i++) {
+ p += addpatt(L, p, 1);
+ setinst(p++, IPartialCommit, 1);
+ }
+ setinst(p - 1, ICommit, 1); /* correct last commit */
+ optimizechoice(op);
+}
+
+
+static int star_l (lua_State *L) {
+ int l1;
+ int n = luaL_checkint(L, 2);
+ Instruction *p1 = getpatt(L, 1, &l1);
+ if (n >= 0) {
+ CharsetTag st;
+ Instruction *op;
+ if (tocharset(p1, &st) == ISCHARSET)
+ return repeatcharset(L, st.cs, l1, n);
+ if (isheadfail(p1))
+ op = repeatheadfail(L, l1, n);
+ else
+ op = repeats(L, p1, l1, n);
+ optimizecaptures(op);
+ optimizejumps(op);
+ }
+ else {
+ if (isheadfail(p1))
+ optionalheadfail(L, l1, -n);
+ else
+ optionals(L, l1, -n);
+ }
+ return 1;
+}
+
+
+static int getlabel (lua_State *L, int labelidx) {
+ if (labelidx == 0) return 0;
+ else return value2fenv(L, labelidx);
+}
+
+
+#define setinstcap(i,op,idx,k,n) setinstaux(i,op,idx,((k) | ((n) << 4)))
+
+
+static int capture_aux (lua_State *L, int kind, int labelidx) {
+ int l1, n;
+ Instruction *p1 = getpatt(L, 1, &l1);
+ int lc = skipchecks(p1, 0, &n);
+ if (lc == l1) { /* got whole pattern? */
+ /* may use a IFullCapture instruction at its end */
+ Instruction *p = newpatt(L, l1 + 1);
+ int label = getlabel(L, labelidx);
+ p += addpatt(L, p, 1);
+ setinstcap(p, IFullCapture, label, kind, n);
+ }
+ else { /* must use open-close pair */
+ Instruction *op = newpatt(L, 1 + l1 + 1);
+ Instruction *p = op;
+ setinstcap(p++, IOpenCapture, getlabel(L, labelidx), kind, 0);
+ p += addpatt(L, p, 1);
+ setinstcap(p, ICloseCapture, 0, Cclose, 0);
+ optimizecaptures(op);
+ }
+ return 1;
+}
+
+
+static int capture_l (lua_State *L) { return capture_aux(L, Csimple, 0); }
+static int tcapture_l (lua_State *L) { return capture_aux(L, Ctable, 0); }
+static int capsubst_l (lua_State *L) { return capture_aux(L, Csubst, 0); }
+static int capaccum_l (lua_State *L) { return capture_aux(L, Caccum, 0); }
+
+static int rcapture_l (lua_State *L) {
+ switch (lua_type(L, 2)) {
+ case LUA_TFUNCTION: return capture_aux(L, Cfunction, 2);
+ case LUA_TTABLE: return capture_aux(L, Cquery, 2);
+ case LUA_TSTRING: return capture_aux(L, Cstring, 2);
+ default: return luaL_argerror(L, 2, "invalid replacement value");
+ }
+}
+
+
+static int position_l (lua_State *L) {
+ Instruction *p = newpatt(L, 1);
+ setinstcap(p, IEmptyCapture, 0, Cposition, 0);
+ return 1;
+}
+
+
+static int capconst_l (lua_State *L) {
+ int i, j;
+ int n = lua_gettop(L);
+ Instruction *p = newpatt(L, n);
+ lua_createtable(L, n, 0); /* new environment for the new pattern */
+ for (i = j = 1; i <= n; i++) {
+ if (lua_isnil(L, i))
+ setinstcap(p++, IEmptyCapture, 0, Cconst, 0);
+ else {
+ setinstcap(p++, IEmptyCapture, j, Cconst, 0);
+ lua_pushvalue(L, i);
+ lua_rawseti(L, -2, j++);
+ }
+ }
+ lua_setfenv(L, -2); /* set environment */
+ return 1;
+}
+
+
+/* }====================================================== */
+
+
+
+/*
+** {======================================================
+** User-Defined Patterns
+** =======================================================
+*/
+
+static void newpattfunc (lua_State *L, PattFunc f, const void *ud, size_t l) {
+ int n = instsize(l) + 1;
+ Instruction *p = newpatt(L, n);
+ p[0].i.code = IFunc;
+ p[0].i.offset = n;
+ p[1].f = f;
+ memcpy(p[2].buff, ud, l);
+}
+
+
+#include <ctype.h>
+
+static const char *span (const void *ud, const char *o,
+ const char *s,
+ const char *e) {
+ const char *u = (const char *)ud;
+ (void)o; (void)e;
+ return s + strspn(s, u);
+}
+
+
+static int span_l (lua_State *L) {
+ const char *s = luaL_checkstring(L, 1);
+ newpattfunc(L, span, s, strlen(s) + 1);
+ return 1;
+}
+
+/* }====================================================== */
+
+
+
+/*
+** {======================================================
+** Captures
+** =======================================================
+*/
+
+
+typedef struct CapState {
+ Capture *cap; /* current capture */
+ lua_State *L;
+ const char *s; /* original string */
+ int valuecached; /* value stored in cache slot */
+} CapState;
+
+
+#define captype(cap) ((cap)->kind)
+
+#define isclosecap(cap) (captype(cap) == Cclose)
+
+#define closeaddr(c) ((c)->s + (c)->siz - 1)
+
+#define isfullcap(cap) ((cap)->siz != 0)
+
+#define pushluaval(cs) lua_rawgeti((cs)->L, PENVIDX, (cs)->cap->idx)
+
+#define pushsubject(cs, c) lua_pushlstring((cs)->L, (c)->s, (c)->siz - 1)
+
+
+#define updatecache(cs,v) { if ((v) != (cs)->valuecached) updatecache_(cs,v); }
+
+
+static void updatecache_ (CapState *cs, int v) {
+ lua_rawgeti(cs->L, PENVIDX, v);
+ lua_replace(cs->L, SUBSCACHE);
+ cs->valuecached = v;
+}
+
+
+static int pushcapture (CapState *cs);
+
+
+static int pushallcaptures (CapState *cs, int addextra) {
+ Capture *co = cs->cap;
+ int n = 0;
+ if (isfullcap(cs->cap++)) {
+ pushsubject(cs, co); /* push whole match */
+ return 1;
+ }
+ while (!isclosecap(cs->cap))
+ n += pushcapture(cs);
+ if (addextra || n == 0) { /* need extra? */
+ lua_pushlstring(cs->L, co->s, cs->cap->s - co->s); /* push whole match */
+ n++;
+ }
+ cs->cap++; /* skip close entry */
+ return n;
+}
+
+
+static int simplecap (CapState *cs) {
+ int n;
+ lua_pushnil(cs->L); /* open space */
+ n = pushallcaptures(cs, 1);
+ lua_replace(cs->L, -(n + 1)); /* put extra in previously opened slot */
+ return n;
+}
+
+
+static int tablecap (CapState *cs) {
+ int n = 0;
+ lua_newtable(cs->L);
+ if (isfullcap(cs->cap++))
+ return 1; /* table is empty */
+ while (!isclosecap(cs->cap)) {
+ int i;
+ int k = pushcapture(cs);
+ for (i = k; i > 0; i--)
+ lua_rawseti(cs->L, -(i + 1), n + i);
+ n += k;
+ }
+ cs->cap++; /* skip close entry */
+ return 1;
+}
+
+
+static int querycap (CapState *cs) {
+ int idx = cs->cap->idx;
+ int n = pushallcaptures(cs, 0);
+ if (n > 1) /* extra captures? */
+ lua_pop(cs->L, n - 1); /* throw them away */
+ updatecache(cs, idx);
+ lua_gettable(cs->L, SUBSCACHE);
+ if (!lua_isnil(cs->L, -1))
+ return 1;
+ else {
+ lua_pop(cs->L, 1); /* remove value */
+ return 0;
+ }
+}
+
+
+static int accumcap (CapState *cs) {
+ lua_State *L = cs->L;
+ if (isfullcap(cs->cap++) || isclosecap(cs->cap) || pushcapture(cs) != 1)
+ luaL_error(L, "no initial value for accumulator capture");
+ while (!isclosecap(cs->cap)) {
+ int n;
+ if (captype(cs->cap) != Cfunction)
+ luaL_error(L, "invalid (non function) capture to accumulate");
+ pushluaval(cs);
+ lua_insert(L, -2); /* put function before previous capture */
+ n = pushallcaptures(cs, 0);
+ lua_call(L, n + 1, 1);
+ }
+ cs->cap++;
+ return 1;
+}
+
+
+static int functioncap (CapState *cs) {
+ int n;
+ int top = lua_gettop(cs->L);
+ pushluaval(cs);
+ n = pushallcaptures(cs, 0);
+ lua_call(cs->L, n, LUA_MULTRET);
+ return lua_gettop(cs->L) - top;
+}
+
+
+typedef struct StrAux {
+ const char *s;
+ const char *e;
+} StrAux;
+
+#define MAXSTRCAPS 10
+
+static int getstrcaps (CapState *cs, StrAux *cps, int n) {
+ int k = n++;
+ if (k < MAXSTRCAPS) cps[k].s = cs->cap->s;
+ if (!isfullcap(cs->cap++)) {
+ while (!isclosecap(cs->cap)) {
+ if (captype(cs->cap) != Csimple)
+ luaL_error(cs->L, "invalid capture #%d in replacement pattern", n);
+ n = getstrcaps(cs, cps, n);
+ }
+ cs->cap++; /* skip close */
+ }
+ if (k < MAXSTRCAPS) cps[k].e = closeaddr(cs->cap - 1);
+ return n;
+}
+
+
+static void stringcap (luaL_Buffer *b, CapState *cs) {
+ StrAux cps[MAXSTRCAPS];
+ int n;
+ size_t len, i;
+ const char *c;
+ updatecache(cs, cs->cap->idx);
+ c = lua_tolstring(cs->L, SUBSCACHE, &len);
+ n = getstrcaps(cs, cps, 0) - 1;
+ for (i = 0; i < len; i++) {
+ if (c[i] != '%' || c[++i] < '0' || c[i] > '9')
+ luaL_addchar(b, c[i]);
+ else {
+ int l = c[i] - '0';
+ if (l > n)
+ luaL_error(cs->L, "invalid capture index (%c)", c[i]);
+ luaL_addlstring(b, cps[l].s, cps[l].e - cps[l].s);
+ }
+ }
+}
+
+
+static void substcap (CapState *cs) {
+ luaL_Buffer b;
+ const char *curr = (cs->cap - 1)->s;
+ luaL_buffinit(cs->L, &b);
+ while (!isclosecap(cs->cap)) {
+ int n;
+ const char *next = cs->cap->s;
+ luaL_addlstring(&b, curr, next - curr);
+ if (captype(cs->cap) == Cstring)
+ stringcap(&b, cs); /* add capture directly to buffer */
+ else if ((n = pushcapture(cs)) == 0) { /* no capture? */
+ curr = next; /* result keeps the original text */
+ continue;
+ }
+ else {
+ if (n > 1) lua_pop(cs->L, n - 1); /* ignore extra values */
+ if (!lua_isstring(cs->L, -1))
+ luaL_error(cs->L, "invalid replacement value (a %s)",
+ luaL_typename(cs->L, -1));
+ luaL_addvalue(&b); /* add result to accumulator */
+ }
+ /* continue after match */
+ curr = closeaddr(cs->cap - 1);
+ }
+ luaL_addlstring(&b, curr, cs->cap->s - curr);
+ luaL_pushresult(&b);
+ cs->cap++;
+}
+
+
+static int pushcapture (CapState *cs) {
+ luaL_checkstack(cs->L, 4, "too many unstored captures");
+ switch (captype(cs->cap)) {
+ case Cposition: {
+ lua_pushinteger(cs->L, cs->cap->s - cs->s + 1);
+ cs->cap++;
+ return 1;
+ }
+ case Cconst: {
+ pushluaval(cs);
+ cs->cap++;
+ return 1;
+ }
+ case Csimple: {
+ if (isfullcap(cs->cap)) {
+ pushsubject(cs, cs->cap);
+ cs->cap++;
+ return 1;
+ }
+ else return simplecap(cs);
+ }
+ case Cstring: {
+ luaL_Buffer b;
+ luaL_buffinit(cs->L, &b);
+ stringcap(&b, cs);
+ luaL_pushresult(&b);
+ return 1;
+ }
+ case Csubst: {
+ if (isfullcap(cs->cap++)) /* no changes? */
+ pushsubject(cs, cs->cap - 1); /* push original subject */
+ else
+ substcap(cs);
+ return 1;
+ }
+ case Ctable: return tablecap(cs);
+ case Cfunction: return functioncap(cs);
+ case Cquery: return querycap(cs);
+ case Caccum: return accumcap(cs);
+ default: assert(0); return 0;
+ }
+}
+
+
+static int getcaptures (lua_State *L, const char *s, const char *r) {
+ Capture *capture = (Capture *)lua_touserdata(L, CAPLISTIDX);
+ CapState cs;
+ int n = 0;
+ cs.cap = capture; cs.L = L; cs.s = s; cs.valuecached = 0;
+ while (!isclosecap(cs.cap))
+ n += pushcapture(&cs);
+ if (n == 0) { /* no captures? */
+ lua_pushinteger(L, r - s + 1); /* return only end position */
+ n = 1;
+ }
+ return n;
+}
+
+/* }====================================================== */
+
+
+static int printpat_l (lua_State *L) {
+ Instruction *p = getpatt(L, 1, NULL);
+ int n, i;
+ lua_getfenv(L, 1);
+ n = lua_objlen(L, -1);
+ printf("[");
+ for (i = 1; i <= n; i++) {
+ printf("%d = ", i);
+ lua_rawgeti(L, -1, i);
+ if (lua_isstring(L, -1))
+ printf("%s ", lua_tostring(L, -1));
+ else
+ printf("%s ", lua_typename(L, lua_type(L, -1)));
+ lua_pop(L, 1);
+ }
+ printf("]\n");
+ printpatt(p);
+ return 0;
+}
+
+
+static int matchl (lua_State *L) {
+ Capture capture[IMAXCAPTURES];
+ const char *r;
+ size_t l;
+ Instruction *p = getpatt(L, 1, NULL);
+ const char *s = luaL_checklstring(L, SUBJIDX, &l);
+ lua_Integer i = luaL_optinteger(L, 3, 1);
+ i = (i > 0) ?
+ ((i <= (lua_Integer)l) ? i - 1 : (lua_Integer)l) :
+ (((lua_Integer)l + i >= 0) ? (lua_Integer)l + i : 0);
+ lua_settop(L, CAPLISTIDX - 1);
+ lua_pushlightuserdata(L, capture);
+ lua_getfenv(L, 1);
+ r = match(L, s, s + i, s + l, p, capture);
+ if (r == NULL) {
+ lua_pushnil(L);
+ return 1;
+ }
+ assert(lua_gettop(L) == PENVIDX);
+ return getcaptures(L, s, r);
+}
+
+
+static struct luaL_reg pattreg[] = {
+ {"match", matchl},
+ {"print", printpat_l},
+ {"C", capture_l},
+ {"Ca", capaccum_l},
+ {"Cc", capconst_l},
+ {"Cp", position_l},
+ {"Cs", capsubst_l},
+ {"Ct", tcapture_l},
+ {"P", pattern_l},
+ {"R", range_l},
+ {"S", set_l},
+ {"V", nter_l},
+ {"span", span_l},
+ {NULL, NULL}
+};
+
+
+static struct luaL_reg metapattreg[] = {
+ {"__add", union_l},
+ {"__pow", star_l},
+ {"__sub", diff_l},
+ {"__mul", concat_l},
+ {"__div", rcapture_l},
+ {"__unm", unm_l},
+ {"__len", pattand_l},
+ {NULL, NULL}
+};
+
+
+int luaopen_lpeg (lua_State *L);
+int luaopen_lpeg (lua_State *L) {
+ lua_newtable(L);
+ lua_replace(L, LUA_ENVIRONINDEX); /* empty env for new patterns */
+ luaL_newmetatable(L, "pattern");
+ luaL_register(L, NULL, metapattreg);
+ luaL_register(L, "lpeg", pattreg);
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, -2);
+ lua_settable(L, -4);
+ return 1;
+}
+
diff --git a/Build/source/libs/luazip/Makefile b/Build/source/libs/luazip/Makefile
new file mode 100644
index 00000000000..ea1980db71c
--- /dev/null
+++ b/Build/source/libs/luazip/Makefile
@@ -0,0 +1,24 @@
+# $Id: Makefile,v 1.9 2005/06/27 17:43:19 tomas Exp $
+
+T= zip
+V= 1.2.1
+CONFIG= ./config
+
+include $(CONFIG)
+
+SRCS= src/lua$T.c
+OBJS= src/lua$T.o
+
+
+lib: src/$(LIBNAME)
+
+src/$(LIBNAME): $(OBJS)
+ $(CC) $(CFLAGS) $(LIB_OPTION) -o src/$(LIBNAME) $(OBJS) -lzzip
+
+install: src/$(LIBNAME)
+ mkdir -p $(LUA_LIBDIR)
+ cp src/$(LIBNAME) $(LUA_LIBDIR)
+ cd $(LUA_LIBDIR); ln -f -s $(LIBNAME) $T.so
+
+clean:
+ rm -f $L src/$(LIBNAME) $(OBJS)
diff --git a/Build/source/libs/luazip/README b/Build/source/libs/luazip/README
new file mode 100644
index 00000000000..5c3e36dc198
--- /dev/null
+++ b/Build/source/libs/luazip/README
@@ -0,0 +1,3 @@
+
+LuaZip is a Lua extension library used to read files stored inside zip files.
+Please see docs at doc/index.html or http://www.keplerproject.org/luazip
diff --git a/Build/source/libs/luazip/config b/Build/source/libs/luazip/config
new file mode 100644
index 00000000000..83f4b958101
--- /dev/null
+++ b/Build/source/libs/luazip/config
@@ -0,0 +1,23 @@
+# Installation directories
+# System's libraries directory (where binary libraries are installed)
+LUA_LIBDIR= /usr/local/lib/lua/5.0
+# System's lua directory (where Lua libraries are installed)
+LUA_DIR= /usr/local/share/lua/5.0
+# Lua includes directory
+LUA_INC= /home/taco/luatex-dev/luatex/src/libs/lua51
+# Zziplib includes directory
+ZZLIB_INC= /usr/include
+
+# OS dependent
+LIB_OPTION= -shared #for Linux
+#LIB_OPTION= -bundle -undefined dynamic_lookup #for MacOS X
+
+LIBNAME= $T.so.$V
+
+# Compilation directives
+WARN= -O2 -Wall -fPIC -W -Waggregate-return -Wcast-align -Wmissing-prototypes -Wnested-externs -Wshadow -Wwrite-strings
+INCS= -I$(LUA_INC) -I$(ZZLIB_INC)
+CFLAGS= $(WARN) $(INCS)
+CC= gcc
+
+# $Id: config,v 1.5 2005/06/24 02:00:38 tomas Exp $
diff --git a/Build/source/libs/luazip/doc/us/examples.html b/Build/source/libs/luazip/doc/us/examples.html
new file mode 100644
index 00000000000..cc55405315a
--- /dev/null
+++ b/Build/source/libs/luazip/doc/us/examples.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+ <title>LuaZip: Reading files inside zip files</title>
+ <link rel="stylesheet" href="http://www.keplerproject.org/doc.css" type="text/css"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo">
+ <a href="http://www.keplerproject.org"><img alt="LuaZip logo" src="luazip-128.png"/></a>
+ </div>
+ <div id="product_name"><big><strong>LuaZip</strong></big></div>
+ <div id="product_description">Reading files inside zip files</div>
+</div> <!-- id="product" -->
+
+<div id="main">
+
+<div id="navigation">
+<h1>LuaZip</h1>
+ <ul>
+ <li><a href="index.html">Home</a>
+ <ul>
+ <li><a href="index.html#overview">Overview</a></li>
+ <li><a href="index.html#status">Status</a></li>
+ <li><a href="index.html#download">Download</a></li>
+ <li><a href="index.html#history">History</a></li>
+ <li><a href="index.html#credits">Credits</a></li>
+ <li><a href="index.html#contact">Contact</a></li>
+ </ul>
+ </li>
+ <li><a href="manual.html">Manual</a>
+ <ul>
+ <li><a href="manual.html#introduction">Introduction</a></li>
+ <li><a href="manual.html#installation">Installation</a></li>
+ <li><a href="manual.html#reference">Reference</a></li>
+ </ul>
+ </li>
+ <li><strong>Examples</strong></li>
+ <li><a href="http://luaforge.net/projects/luazip/">Project</a>
+ <ul>
+ <li><a href="http://luaforge.net/tracker/?group_id=8">Bug Tracker</a></li>
+ <li><a href="http://luaforge.net/scm/?group_id=8">CVS</a></li>
+ </ul>
+ </li>
+ <li><a href="license.html">License</a></li>
+ </ul>
+</div> <!-- id="navigation" -->
+
+<div id="content">
+
+
+<h2><a name="examples"></a>Example</h2>
+
+<p>
+Suppose we have the following file hierarchy:
+</p>
+
+<pre class="example">
+/a
+ /b
+ c.zip
+/a2
+ b2.ext2
+/a3.ext3
+/luazip.zip
+</pre>
+
+<ul>
+<li>c.zip contains the file 'd.txt'</li>
+<li>b2.ext2 is a zip file containing the file 'c2/d2.txt'</li>
+<li>a3.ext3 is a zip file containing the file 'b3/c3/d3.txt'</li>
+<li>luazip.zip contains the files 'luazip.h', 'luazip.c', 'Makefile', 'README'</li>
+</ul>
+
+Below is a small sample code displaying the basic use of the library.
+
+<pre class="example">
+require "zip"
+
+local zfile, err = zip.open('luazip.zip')
+
+-- print the filenames of the files inside the zip
+for file in zfile:files() do
+ print(file.filename)
+end
+
+-- open README and print it
+local f1, err = zfile:open('README')
+local s1 = f1:read("*a")
+print(s1)
+
+f1:close()
+zfile:close()
+
+-- open d.txt inside c.zip
+local d, err = zip.openfile('a/b/c/d.txt')
+assert(d, err)
+d:close()
+
+-- open d2.txt inside b2.ext2
+local d2, err = zip.openfile('a2/b2/c2/d2.txt', "ext2")
+assert(d2, err)
+d2:close()
+
+-- open d3.txt inside a3.ext3
+local d3, err = zip.openfile('a3/b3/c3/d3.txt', {"ext2", "ext3"})
+assert(d3, err)
+d3:close()
+</pre>
+
+</div> <!-- id="content" -->
+
+</div> <!-- id="main" -->
+
+<div id="about">
+ <p><a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
+ <p><small>
+ $Id: examples.html,v 1.4 2006/03/23 20:45:21 carregal Exp $
+ </small></p>
+</div> <!-- id="about" -->
+
+</div> <!-- id="container" -->
+
+</body>
+</html>
diff --git a/Build/source/libs/luazip/doc/us/index.html b/Build/source/libs/luazip/doc/us/index.html
new file mode 100644
index 00000000000..ca5aad3f412
--- /dev/null
+++ b/Build/source/libs/luazip/doc/us/index.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+ <title>LuaZip: Reading files inside zip files</title>
+ <link rel="stylesheet" href="http://www.keplerproject.org/doc.css" type="text/css"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo">
+ <a href="http://www.keplerproject.org"><img alt="LuaZip logo" src="luazip-128.png"/></a>
+ </div>
+ <div id="product_name"><big><strong>LuaZip</strong></big></div>
+ <div id="product_description">Reading files inside zip files</div>
+</div> <!-- id="product" -->
+
+<div id="main">
+
+<div id="navigation">
+<h1>LuaZip</h1>
+ <ul>
+ <li><strong>Home</strong>
+ <ul>
+ <li><a href="index.html#overview">Overview</a></li>
+ <li><a href="index.html#status">Status</a></li>
+ <li><a href="index.html#download">Download</a></li>
+ <li><a href="index.html#history">History</a></li>
+ <li><a href="index.html#credits">Credits</a></li>
+ <li><a href="index.html#contact">Contact</a></li>
+ </ul>
+ </li>
+ <li><a href="manual.html">Manual</a>
+ <ul>
+ <li><a href="manual.html#introduction">Introduction</a></li>
+ <li><a href="manual.html#installation">Installation</a></li>
+ <li><a href="manual.html#reference">Reference</a></li>
+ </ul>
+ </li>
+ <li><a href="examples.html">Examples</a></li>
+ <li><a href="http://luaforge.net/projects/luazip/">Project</a>
+ <ul>
+ <li><a href="http://luaforge.net/tracker/?group_id=8">Bug Tracker</a></li>
+ <li><a href="http://luaforge.net/scm/?group_id=8">CVS</a></li>
+ </ul>
+ </li>
+ <li><a href="license.html">License</a></li>
+ </ul>
+</div> <!-- id="navigation" -->
+
+<div id="content">
+
+<h2><a name="overview"></a>Overview</h2>
+
+<p>LuaZip is a lightweight <a href="http://www.lua.org">Lua</a> 5.0 extension library
+used to read files stored inside zip files. The API is very similar to the standard
+Lua I/O library API.</p>
+
+<p>LuaZip is free software and uses the same <a href="license.html">license</a> as Lua 5.0.</p>
+
+<h2><a name="status"></a>Status</h2>
+
+<p>Current version is 1.2.2. It was developed for Lua 5.0.</p>
+
+<p>Version 1.2.2 follows the
+<a href="http://www.keplerproject.org/compat">package model</a>
+for Lua 5.1 (see section <a href="manual.html#installation">Installation</a>
+for more details).</p>
+
+<h2><a name="download"></a>Download</h2>
+
+<p>LuaZip source can be downloaded from its
+<a href="http://luaforge.net/projects/luazip/files">Lua Forge</a>
+page. If you are using
+<a href="http://luabinaries.luaforge.net">LuaBinaries</a> Release 2
+a Windows binary version of LuaZip can be found at the same
+LuaForge page.</p>
+
+<h2><a name="history"></a>History</h2>
+
+<dl class="history">
+ <dt><strong>Version 1.2.2</strong> [24/Mar/2006]</dt>
+ <dd>Minor fixes on makefile and config</dd>
+
+ <dt><strong>Version 1.2.1</strong> [08/Jun/2005]</dt>
+ <dd>Minor bug fixes</dd>
+
+ <dt><strong>Version 1.2.0</strong> [01/Dec/2004]</dt>
+ <dd></dd>
+
+ <dt><strong><a href="http://www.keplerproject.org/luazip/1.1">Version 1.1.3</a></strong> [25/Jun/2004]</dt>
+ <dd>First Public Release</dd>
+</dl>
+
+<h2><a name="credits"></a>Credits</h2>
+
+<p>LuaZip was designed and coded by Danilo Tuler as part of the
+<a href="http://www.keplerproject.org">Kepler Project</a>.</p>
+
+<h2><a name="contact"></a>Contact</h2>
+
+<p>For more information please
+<a href="mailto:info-NO-SPAM-THANKS@keplerproject.org">contact</a> us.
+Comments are welcome!</p>
+
+<p>You can also reach other Kepler developers and users on the Kepler Project
+<a href="http://luaforge.net/mail/?group_id=104">mailing list</a>.</p>
+
+</div> <!-- id="content" -->
+
+</div> <!-- id="main" -->
+
+<div id="about">
+ <p><a href="http://validator.w3.org/check?uri=referer">
+ <img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
+ <p><small>$Id: index.html,v 1.7 2006/03/23 20:45:21 carregal Exp $</small></p>
+</div> <!-- id="about" -->
+
+</div> <!-- id="container" -->
+
+</body>
+</html>
diff --git a/Build/source/libs/luazip/doc/us/license.html b/Build/source/libs/luazip/doc/us/license.html
new file mode 100644
index 00000000000..f9fd47f9cfe
--- /dev/null
+++ b/Build/source/libs/luazip/doc/us/license.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+ <title>LuaZip: Reading files inside zip files</title>
+ <link rel="stylesheet" href="http://www.keplerproject.org/doc.css" type="text/css"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo">
+ <a href="http://www.keplerproject.org"><img alt="LuaZip logo" src="luazip-128.png"/></a>
+ </div>
+ <div id="product_name"><big><strong>LuaZip</strong></big></div>
+ <div id="product_description">Reading files inside zip files</div>
+</div> <!-- id="product" -->
+
+<div id="main">
+
+<div id="navigation">
+<h1>LuaZip</h1>
+ <ul>
+ <li><a href="index.html">Home</a>
+ <ul>
+ <li><a href="index.html#overview">Overview</a></li>
+ <li><a href="index.html#status">Status</a></li>
+ <li><a href="index.html#download">Download</a></li>
+ <li><a href="index.html#history">History</a></li>
+ <li><a href="index.html#credits">Credits</a></li>
+ <li><a href="index.html#contact">Contact</a></li>
+ </ul>
+ </li>
+ <li><a href="manual.html">Manual</a>
+ <ul>
+ <li><a href="manual.html#introduction">Introduction</a></li>
+ <li><a href="manual.html#installation">Installation</a></li>
+ <li><a href="manual.html#reference">Reference</a></li>
+ </ul>
+ </li>
+ <li><a href="examples.html">Examples</a></li>
+ <li><a href="http://luaforge.net/projects/luazip/">Project</a>
+ <ul>
+ <li><a href="http://luaforge.net/tracker/?group_id=8">Bug Tracker</a></li>
+ <li><a href="http://luaforge.net/scm/?group_id=8">CVS</a></li>
+ </ul>
+ </li>
+ <li><strong>License</strong></li>
+ </ul>
+</div> <!-- id="navigation" -->
+
+<div id="content">
+
+<h2>License</h2>
+
+<p>
+LuaZip is free software: it can be used for both academic and commercial purposes at absolutely no cost.
+There are no royalties or GNU-like "copyleft" restrictions.
+LuaZip qualifies as <a href="http://www.opensource.org/docs/definition.html">Open Source</a>
+software.
+Its licenses are compatible with <a href="http://www.gnu.org/licenses/gpl.html">GPL</a>.
+LuaZip is not in the public domain and the <a href="http://www.keplerproject.org">Kepler Project</a>
+keep its copyright. The legal details are below.
+</p>
+
+<p>
+The spirit of the license is that
+you are free to use LuaZip for any purpose at no cost without having to ask us.
+The only requirement is that
+if you do use LuaZip,
+then you should give us credit by including the appropriate copyright notice
+somewhere in your product or its documentation.
+</p>
+
+<p>
+The LuaZip library was designed and implemented by Danilo Tuler.
+Part of the code is a derived work from the Lua standard I/O library, copyrighted by Tecgraf, PUC-Rio.
+</p>
+
+<hr/>
+<p>
+Copyright &copy; 2003-2006 The Kepler Project.
+</p>
+
+<p>
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+</p>
+
+<p>
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+</p>
+
+<p>
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+</p>
+
+</div> <!-- id="content" -->
+
+</div> <!-- id="main" -->
+
+<div id="about">
+ <p><a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
+ <p><small>
+ $Id: license.html,v 1.5 2006/03/25 14:59:02 carregal Exp $
+ </small></p>
+</div> <!-- id="about" -->
+
+</div> <!-- id="container" -->
+
+</body>
+</html>
diff --git a/Build/source/libs/luazip/doc/us/luazip-128.png b/Build/source/libs/luazip/doc/us/luazip-128.png
new file mode 100644
index 00000000000..03b2e379b59
--- /dev/null
+++ b/Build/source/libs/luazip/doc/us/luazip-128.png
Binary files differ
diff --git a/Build/source/libs/luazip/doc/us/manual.html b/Build/source/libs/luazip/doc/us/manual.html
new file mode 100644
index 00000000000..d9103af5539
--- /dev/null
+++ b/Build/source/libs/luazip/doc/us/manual.html
@@ -0,0 +1,181 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+ <title>LuaZip: Reading files inside zip files</title>
+ <link rel="stylesheet" href="http://www.keplerproject.org/doc.css" type="text/css"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo">
+ <a href="http://www.keplerproject.org"><img alt="LuaZip logo" src="luazip-128.png"/></a>
+ </div>
+ <div id="product_name"><big><strong>LuaZip</strong></big></div>
+ <div id="product_description">Reading files inside zip files</div>
+</div> <!-- id="product" -->
+
+<div id="main">
+
+<div id="navigation">
+<h1>LuaZip</h1>
+ <ul>
+ <li><a href="index.html">Home</a>
+ <ul>
+ <li><a href="index.html#overview">Overview</a></li>
+ <li><a href="index.html#status">Status</a></li>
+ <li><a href="index.html#download">Download</a></li>
+ <li><a href="index.html#history">History</a></li>
+ <li><a href="index.html#credits">Credits</a></li>
+ <li><a href="index.html#contact">Contact</a></li>
+ </ul>
+ </li>
+ <li><strong>Manual</strong>
+ <ul>
+ <li><a href="manual.html#introduction">Introduction</a></li>
+ <li><a href="manual.html#installation">Installation</a></li>
+ <li><a href="manual.html#reference">Reference</a></li>
+ </ul>
+ </li>
+ <li><a href="examples.html">Examples</a></li>
+ <li><a href="http://luaforge.net/projects/luazip/">Project</a>
+ <ul>
+ <li><a href="http://luaforge.net/tracker/?group_id=8">Bug Tracker</a></li>
+ <li><a href="http://luaforge.net/scm/?group_id=8">CVS</a></li>
+ </ul>
+ </li>
+ <li><a href="license.html">License</a></li>
+ </ul>
+</div> <!-- id="navigation" -->
+
+<div id="content">
+
+
+<h2><a name="introduction"></a>Introduction</h2>
+
+<p>LuaZip is a lightweight <a href="http://www.lua.org">Lua</a> 5.0 extension library
+that can be used to read files stored inside zip files. It uses
+<a href="http://zziplib.sourceforge.net">zziplib</a> to do all the hard work.</p>
+
+<p>The API exposed to Lua is very simple and very similiar to the usual file handling
+functions provided by the
+<a href="http://www.lua.org/manual/5.0/manual.html#5.6">I/O Lua standard library</a>.
+In fact, the API is so similar that parts of this manual are extracted from the Lua manual,
+copyrighted by Tecgraf, PUC-Rio.</p>
+
+<h2><a name="installation"></a>Installation</h2>
+
+<p>LuaZip follows the
+<a href="http://www.keplerproject.org/compat/">package model</a>
+for Lua 5.1, therefore it should be "installed". Refer to
+<a href="http://www.keplerproject.org/compat/manual.html#configuration">
+Compat-5.1 configuration</a> section about how to install the compiled
+binary properly.</p>
+
+<p>If you are using Unix you may need to download
+<a href="http://zziplib.sourceforge.net">zziplib 0.13.36</a></p>
+
+<p>If you are using Windows, the binary version of LuaZip includes zziplib
+(<code>zlib1.dll</code>). </p>
+
+<h2><a name="reference"></a>Reference</h2>
+
+<dl>
+ <dt><strong>zip.open (filename)</strong></dt>
+ <dd>This function opens a zip file and returns a new zip file handle. In case of
+ error it returns nil and an error message. Unlike <code>io.open</code>, there is no
+ <code>mode</code> parameter, as the only supported mode is "read".</dd>
+
+ <dt><strong>zip.openfile (filename [, extensions]])</strong></dt>
+ <dd>This function opens a file and returns a file handle. In case of
+ error it returns nil and an error message. Unlike <code>io.open</code>, there is no
+ <code>mode</code> parameter, as the only supported mode is "read".<br/>
+ This function implements a virtual file system based on optionally compressed files.
+ Instead of simply looking for a file at a given path, this function goes recursively up
+ through all path separators ("/") looking for zip files there. If it finds a zip file,
+ this function use the remaining path to open the requested file.<br/>
+ The optional parameter <em>extensions</em> allows the use of file extensions other than .zip
+ during the lookup. It can be a string corresponding to the extension or an indexed table
+ with the lookup extensions sequence.</dd>
+
+ <dt><strong>zfile:close ()</strong></dt>
+ <dd>This function closes a zfile opened by <code>zip.open</code></dd>
+
+ <dt><strong>zfile:files ()</strong></dt>
+ <dd>Returns an iterator function that returns a new table containing the
+ following information each time it is called:
+ <ul>
+ <li><code>filename</code>: the full path of a file</li>
+ <li><code>compressed_size</code>: the compressed size of the file in bytes</li>
+ <li><code>uncompressed_size</code>: the uncompressed size of the file in bytes</li>
+ </ul>
+ </dd>
+
+ <dt><strong>zfile:open (filename)</strong></dt>
+ <dd>This function opens a file that is stored inside the zip file opened by <code>zip.open</code>.<br/>
+ The filename may contain the full path of the file contained inside the zip. The
+ directory separator must be '/'.<br/>
+ Unlike <code>f:open</code>, there is no <code>mode</code> parameter, as the only
+ supported mode is "read".</dd>
+
+ <dt><strong>file:read (format1, ...)</strong></dt>
+ <dd>Reads a <code>file</code> according to the given formats, which specify what to read.<br/>
+ For each format, the function returns a string with the characters read, or nil if it cannot read
+ data with the specified format. When called without formats, it uses a default format that reads
+ the entire next line (see below).<br/>
+ The available formats are:
+ <ul>
+ <li><code>"*a"</code>: reads the whole file, starting at the current position. On end of file, it
+ returns the empty string.</li>
+ <li><code>"*l"</code>: reads the next line (skipping the end of line), returns nil on end of file.
+ This is the default format.</li>
+ <li><code><i>number</i></code>: reads a string with up to that number of characters, returning nil
+ on end of file.</li>
+ </ul>
+ <br/>
+ Unlike the standard I/O read, the format <code>"*n"</code> is not supported.</dd>
+
+ <dt><strong>file:seek ([whence] [, offset])</strong></dt>
+ <dd>Sets and gets the file position, measured from the beginning of the file, to the position given
+ by <code>offset</code> plus a base specified by the string <code>whence</code>, as follows:
+ <ul>
+ <li><code>set</code>: base is position 0 (beginning of the file);</li>
+ <li><code>cur</code>: base is current position;</li>
+ <li><code>end</code>: base is end of file;</li>
+ </ul>
+ In case of success, function <code>seek</code> returns the final file position, measured in bytes
+ from the beginning of the file. If this function fails, it returns nil, plus an error string.
+ The default value for <code>whence</code> is <code>"cur"</code>, and for <code>offset</code> is 0.
+ Therefore, the call <code>file:seek()</code> returns the current file position, without changing
+ it; the call <code>file:seek("set")</code> sets the position to the beginning of the file (and returns 0);
+ and the call <code>file:seek("end")</code> sets the position to the end of the file, and returns its
+ size.</dd>
+
+ <dt><strong>file:close ()</strong></dt>
+ <dd>This function closes a file opened by <code>zfile:open</code>.</dd>
+
+ <dt><strong>file:lines ()</strong></dt>
+ <dd>Returns an iterator function that returns a new line from the file each time it is called.
+ Therefore, the construction<br/>
+ <pre class="example">for line in file:lines() do ... end</pre>
+ will iterate over all lines of the file.</dd>
+</dl>
+
+</div> <!-- id="content" -->
+
+</div> <!-- id="main" -->
+
+<div id="about">
+ <p><a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
+ <p><small>
+ $Id: manual.html,v 1.10 2006/03/25 14:59:02 carregal Exp $
+ </small></p>
+</div> <!-- id="about" -->
+
+</div> <!-- id="container" -->
+
+</body>
+</html>
diff --git a/Build/source/libs/luazip/src/luazip.c b/Build/source/libs/luazip/src/luazip.c
new file mode 100644
index 00000000000..2aaca6d3a6e
--- /dev/null
+++ b/Build/source/libs/luazip/src/luazip.c
@@ -0,0 +1,533 @@
+/*
+ LuaZip - Reading files inside zip files.
+ http://www.keplerproject.org/luazip/
+
+ Author: Danilo Tuler
+ Copyright (c) 2003-2006 Kepler Project
+
+ $Id: luazip.c,v 1.9 2006/03/23 20:44:53 carregal Exp $
+*/
+
+#include <string.h>
+#include <stdlib.h>
+#include "zzip/zzip.h"
+#include "luazip.h"
+#include "lauxlib.h"
+
+#define ZIPFILEHANDLE "lzipFile"
+#define ZIPINTERNALFILEHANDLE "lzipInternalFile"
+#define LUAZIP_MAX_EXTENSIONS 32
+
+static int pushresult (lua_State *L, int i, const char *filename) {
+ if (i) {
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+ else {
+ lua_pushnil(L);
+ if (filename)
+ lua_pushfstring(L, "%s: %s", filename, zzip_strerror(zzip_errno(errno)));
+ else
+ lua_pushfstring(L, "%s", zzip_strerror(zzip_errno(errno)));
+ lua_pushnumber(L, zzip_errno(errno));
+ return 3;
+ }
+}
+
+static ZZIP_DIR** topfile (lua_State *L, int findex) {
+ ZZIP_DIR** f = (ZZIP_DIR**)luaL_checkudata(L, findex, ZIPFILEHANDLE);
+ if (f == NULL) luaL_argerror(L, findex, "bad zip file");
+ return f;
+}
+
+static ZZIP_DIR* tofile (lua_State *L, int findex) {
+ ZZIP_DIR** f = topfile(L, findex);
+ if (*f == NULL)
+ luaL_error(L, "attempt to use a closed zip file");
+ return *f;
+}
+
+static ZZIP_FILE** topinternalfile (lua_State *L, int findex) {
+ ZZIP_FILE** f = (ZZIP_FILE**)luaL_checkudata(L, findex, ZIPINTERNALFILEHANDLE);
+ if (f == NULL) luaL_argerror(L, findex, "bad zip file");
+ return f;
+}
+
+static ZZIP_FILE* tointernalfile (lua_State *L, int findex) {
+ ZZIP_FILE** f = topinternalfile(L, findex);
+ if (*f == NULL)
+ luaL_error(L, "attempt to use a closed zip file");
+ return *f;
+}
+
+/*
+** When creating file handles, always creates a `closed' file handle
+** before opening the actual file; so, if there is a memory error, the
+** file is not left opened.
+*/
+static ZZIP_DIR** newfile (lua_State *L) {
+ ZZIP_DIR** pf = (ZZIP_DIR**)lua_newuserdata(L, sizeof(ZZIP_DIR*));
+ *pf = NULL; /* file handle is currently `closed' */
+ luaL_getmetatable(L, ZIPFILEHANDLE);
+ lua_setmetatable(L, -2);
+ return pf;
+}
+
+static ZZIP_FILE** newinternalfile (lua_State *L) {
+ ZZIP_FILE** pf = (ZZIP_FILE**)lua_newuserdata(L, sizeof(ZZIP_FILE*));
+ *pf = NULL; /* file handle is currently `closed' */
+ luaL_getmetatable(L, ZIPINTERNALFILEHANDLE);
+ lua_setmetatable(L, -2);
+ return pf;
+}
+
+
+static int zip_open (lua_State *L) {
+ const char *zipfilename = luaL_checkstring(L, 1);
+ /*const char *mode = luaL_optstring(L, 2, "r");*/
+
+ ZZIP_DIR** pf = newfile(L);
+ *pf = zzip_dir_open(zipfilename, 0);
+ if (*pf == NULL)
+ {
+ lua_pushnil(L);
+ lua_pushfstring(L, "could not open file `%s'", zipfilename);
+ return 2;
+ }
+ return 1;
+}
+
+static int zip_close (lua_State *L) {
+ ZZIP_DIR* f = tofile(L, 1);
+ if (zzip_dir_close(f) == 0)
+ {
+ *(ZZIP_DIR**)lua_touserdata(L, 1) = NULL; /* mark file as close */
+ lua_pushboolean(L, 1);
+ }
+ else
+ lua_pushboolean(L, 0);
+ return 1;
+}
+
+static int f_open (lua_State *L) {
+ ZZIP_DIR* uf = tofile(L, 1);
+ const char *filename = luaL_checkstring(L, 2);
+ /*const char *mode = luaL_optstring(L, 3, "r");*/
+ ZZIP_FILE** inf = newinternalfile(L);
+
+ *inf = zzip_file_open(uf, filename, 0);
+ if (*inf)
+ return 1;
+
+ lua_pushnil(L);
+ lua_pushfstring(L, "could not open file `%s'", filename);
+ return 2;
+}
+
+/*
+
+*/
+static int zip_openfile (lua_State *L) {
+ ZZIP_FILE** inf;
+
+ const char * ext2[LUAZIP_MAX_EXTENSIONS+1];
+ zzip_strings_t *ext = ext2;
+
+ const char *filename = luaL_checkstring(L, 1);
+ /*const char *mode = luaL_optstring(L, 2, "r");*/
+
+ inf = newinternalfile(L);
+
+ if (lua_isstring(L, 2))
+ {
+ /* creates a table with the string as the first and only (numerical) element */
+ lua_newtable(L);
+ lua_pushvalue(L, 2);
+ lua_rawseti(L, -2, 1);
+
+ /* replaces the string by the table with the string inside */
+ lua_replace(L, 2);
+ }
+
+ if (lua_istable(L, 2))
+ {
+ int i, m, n;
+
+ /* how many extension were specified? */
+ n = luaL_getn(L, 2);
+
+ if (n > LUAZIP_MAX_EXTENSIONS)
+ {
+ luaL_error(L, "too many extensions specified");
+ }
+
+ for (i = 0, m = 0; i < n; i++)
+ {
+ lua_rawgeti(L, 2, i+1);
+ if (lua_isstring(L, -1))
+ {
+ /* luazip specifies "zip" as the extension, but zziplib expects ".zip" */
+ lua_pushstring(L, ".");
+ lua_insert(L, -2);
+ lua_concat(L, 2);
+
+ ext2[m] = lua_tostring(L, -1);
+ m++;
+ }
+ lua_pop(L, 1);
+ }
+ ext2[m] = 0;
+
+ *inf = zzip_open_ext_io(filename, 0, 0664, ext, 0);
+ }
+ else
+ {
+ *inf = zzip_open(filename, 0);
+ }
+
+ if (*inf)
+ return 1;
+
+ lua_pushnil(L);
+ lua_pushfstring(L, "could not open file `%s'", filename);
+ return 2;
+}
+
+static int zip_type (lua_State *L) {
+ ZZIP_DIR** f = (ZZIP_DIR**)luaL_checkudata(L, 1, ZIPFILEHANDLE);
+ if (f == NULL) lua_pushnil(L);
+ else if (*f == NULL)
+ lua_pushliteral(L, "closed zip file");
+ else
+ lua_pushliteral(L, "zip file");
+ return 1;
+}
+
+static int zip_tostring (lua_State *L) {
+ char buff[32];
+ ZZIP_DIR** f = topfile(L, 1);
+ if (*f == NULL)
+ strcpy(buff, "closed");
+ else
+ sprintf(buff, "%p", lua_touserdata(L, 1));
+ lua_pushfstring(L, "zip file (%s)", buff);
+ return 1;
+}
+
+static int ff_tostring (lua_State *L) {
+ char buff[32];
+ ZZIP_FILE** f = topinternalfile(L, 1);
+ if (*f == NULL)
+ strcpy(buff, "closed");
+ else
+ sprintf(buff, "%p", lua_touserdata(L, 1));
+ lua_pushfstring(L, "file in zip file (%s)", buff);
+ return 1;
+}
+
+static int zip_gc (lua_State *L) {
+ ZZIP_DIR**f = topfile(L, 1);
+ if (*f != NULL) /* ignore closed files */
+ zip_close(L);
+ return 0;
+}
+
+static int zip_readfile (lua_State *L) {
+ ZZIP_DIRENT* ent = NULL;
+ ZZIP_DIR* uf = NULL;
+
+ uf = *(ZZIP_DIR**)lua_touserdata(L, lua_upvalueindex(1));
+ if (uf == NULL) /* file is already closed? */
+ luaL_error(L, "file is already closed");
+
+ ent = zzip_readdir(uf);
+
+ if (ent == NULL)
+ return 0;
+
+ lua_newtable(L);
+ lua_pushstring(L, "compressed_size"); lua_pushnumber(L, ent->d_csize); lua_settable(L, -3);
+ lua_pushstring(L, "compression_method"); lua_pushnumber(L, ent->d_compr); lua_settable(L, -3);
+ lua_pushstring(L, "uncompressed_size"); lua_pushnumber(L, ent->st_size); lua_settable(L, -3);
+ lua_pushstring(L, "filename"); lua_pushstring(L, ent->d_name); lua_settable(L, -3);
+
+ return 1;
+}
+
+static int f_files (lua_State *L) {
+ ZZIP_DIR *f = tofile(L, 1);
+ zzip_rewinddir(f);
+ lua_pushliteral(L, ZIPFILEHANDLE);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_pushcclosure(L, zip_readfile, 2);
+ return 1;
+}
+
+static int aux_close (lua_State *L) {
+ ZZIP_FILE *f = tointernalfile(L, 1);
+ int ok = (zzip_fclose(f) == 0);
+ if (ok)
+ *(ZZIP_FILE **)lua_touserdata(L, 1) = NULL; /* mark file as closed */
+ return ok;
+}
+
+static int ff_close (lua_State *L) {
+ return pushresult(L, aux_close(L), NULL);
+}
+
+static int ff_gc (lua_State *L) {
+ ZZIP_FILE**f = topinternalfile(L, 1);
+ if (*f != NULL) /* ignore closed files */
+ aux_close(L);
+ return 0;
+}
+
+static int zzip_getc (ZZIP_FILE *f)
+{
+ char c;
+ return (zzip_fread(&c, sizeof(char), 1, f) == 0) ? EOF : (int)c;
+}
+
+static char* zzip_fgets(char *str, int size, ZZIP_FILE *stream)
+{
+ int c, i;
+
+ for (i = 0; i < size-1; i++)
+ {
+ c = zzip_getc(stream);
+ if (EOF == c)
+ return NULL;
+ str[i]=c;
+ if (('\n' == c)/* || ('\r' == c)*/)
+ {
+ str[i++]='\n';
+ break;
+ }
+ }
+ str[i] = '\0';
+
+ return str;
+}
+
+/* no support to read numbers
+static int zzip_fscanf (ZZIP_FILE *f, const char *format, ...)
+{
+ // TODO
+ return 0;
+}
+
+static int read_number (lua_State *L, ZZIP_FILE *f) {
+ lua_Number d;
+ if (zzip_fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
+ lua_pushnumber(L, d);
+ return 1;
+ }
+ else return 0; // read fails
+}
+*/
+
+static int test_eof (lua_State *L, ZZIP_FILE *f) {
+ /* TODO */
+ (void) L;
+ (void) f;
+ return 1;
+}
+
+static int read_line (lua_State *L, ZZIP_FILE *f) {
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ for (;;) {
+ size_t l;
+ char *p = luaL_prepbuffer(&b);
+ if (zzip_fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */
+ luaL_pushresult(&b); /* close buffer */
+ return (lua_strlen(L, -1) > 0); /* check whether read something */
+ }
+ l = strlen(p);
+ if (p[l-1] != '\n')
+ luaL_addsize(&b, l);
+ else {
+ luaL_addsize(&b, l - 1); /* do not include `eol' */
+ luaL_pushresult(&b); /* close buffer */
+ return 1; /* read at least an `eol' */
+ }
+ }
+}
+
+static int read_chars (lua_State *L, ZZIP_FILE *f, size_t n) {
+ size_t rlen; /* how much to read */
+ size_t nr; /* number of chars actually read */
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ rlen = LUAL_BUFFERSIZE; /* try to read that much each time */
+ do {
+ char *p = luaL_prepbuffer(&b);
+ if (rlen > n) rlen = n; /* cannot read more than asked */
+ nr = zzip_fread(p, sizeof(char), rlen, f);
+ luaL_addsize(&b, nr);
+ n -= nr; /* still have to read `n' chars */
+ } while (n > 0 && nr == rlen); /* until end of count or eof */
+ luaL_pushresult(&b); /* close buffer */
+ return (n == 0 || lua_strlen(L, -1) > 0);
+}
+
+static int g_read (lua_State *L, ZZIP_FILE *f, int first) {
+ int nargs = lua_gettop(L) - 1;
+ int success;
+ int n;
+ if (nargs == 0) { /* no arguments? */
+ success = read_line(L, f);
+ n = first+1; /* to return 1 result */
+ }
+ else { /* ensure stack space for all results and for auxlib's buffer */
+ luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
+ success = 1;
+ for (n = first; nargs-- && success; n++) {
+ if (lua_type(L, n) == LUA_TNUMBER) {
+ size_t l = (size_t)lua_tonumber(L, n);
+ success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
+ }
+ else {
+ const char *p = lua_tostring(L, n);
+ luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
+ switch (p[1]) {
+ case 'l': /* line */
+ success = read_line(L, f);
+ break;
+ case 'a': /* file */
+ read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */
+ success = 1; /* always success */
+ break;
+ default:
+ return luaL_argerror(L, n, "invalid format");
+ }
+ }
+ }
+ }
+ if (!success) {
+ lua_pop(L, 1); /* remove last result */
+ lua_pushnil(L); /* push nil instead */
+ }
+ return n - first;
+}
+
+static int ff_read (lua_State *L) {
+ return g_read(L, tointernalfile(L, 1), 2);
+}
+
+static int zip_readline (lua_State *L);
+
+static void aux_lines (lua_State *L, int idx, int close) {
+ lua_pushliteral(L, ZIPINTERNALFILEHANDLE);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_pushvalue(L, idx);
+ lua_pushboolean(L, close); /* close/not close file when finished */
+ lua_pushcclosure(L, zip_readline, 3);
+}
+
+static int ff_lines (lua_State *L) {
+ tointernalfile(L, 1); /* check that it's a valid file handle */
+ aux_lines(L, 1, 0);
+ return 1;
+}
+
+static int zip_readline (lua_State *L) {
+ ZZIP_FILE *f = *(ZZIP_FILE **)lua_touserdata(L, lua_upvalueindex(2));
+ if (f == NULL) /* file is already closed? */
+ luaL_error(L, "file is already closed");
+ if (read_line(L, f)) return 1;
+ else { /* EOF */
+ if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
+ lua_settop(L, 0);
+ lua_pushvalue(L, lua_upvalueindex(2));
+ aux_close(L); /* close it */
+ }
+ return 0;
+ }
+}
+
+static int ff_seek (lua_State *L) {
+ static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
+ static const char *const modenames[] = {"set", "cur", "end", NULL};
+ ZZIP_FILE *f = tointernalfile(L, 1);
+ int op = luaL_checkoption(L, 2, "cur", modenames);
+ long offset = luaL_optlong(L, 3, 0);
+ luaL_argcheck(L, op != -1, 2, "invalid mode");
+ op = zzip_seek(f, offset, mode[op]);
+ if (op < 0)
+ return pushresult(L, 0, NULL); /* error */
+ else {
+ lua_pushnumber(L, zzip_tell(f));
+ return 1;
+ }
+}
+
+static const luaL_reg ziplib[] = {
+ {"open", zip_open},
+ {"close", zip_close},
+ {"type", zip_type},
+ /* {"files", io_files},*/
+ {"openfile", zip_openfile},
+ {NULL, NULL}
+};
+
+static const luaL_reg flib[] = {
+ {"open", f_open},
+ {"close", zip_close},
+ {"files", f_files},
+ {"__gc", zip_gc},
+ {"__tostring", zip_tostring},
+ {NULL, NULL}
+};
+
+static const luaL_reg fflib[] = {
+ {"read", ff_read},
+ {"close", ff_close},
+ {"seek", ff_seek},
+ {"lines", ff_lines},
+ {"__gc", ff_gc},
+ {"__tostring", ff_tostring},
+/* {"flush", ff_flush},
+ {"write", ff_write},*/
+ {NULL, NULL}
+};
+
+
+/*
+** Assumes the table is on top of the stack.
+*/
+static void set_info (lua_State *L) {
+ lua_pushliteral (L, "_COPYRIGHT");
+ lua_pushliteral (L, "Copyright (C) 2003-2006 Kepler Project");
+ lua_settable (L, -3);
+ lua_pushliteral (L, "_DESCRIPTION");
+ lua_pushliteral (L, "Reading files inside zip files");
+ lua_settable (L, -3);
+ lua_pushliteral (L, "_VERSION");
+ lua_pushliteral (L, "LuaZip 1.2.2");
+ lua_settable (L, -3);
+}
+
+static void createmeta (lua_State *L) {
+ luaL_newmetatable(L, ZIPFILEHANDLE); /* create new metatable for file handles */
+ /* file methods */
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, -2); /* push metatable */
+ lua_rawset(L, -3); /* metatable.__index = metatable */
+ luaL_openlib(L, NULL, flib, 0);
+
+ luaL_newmetatable(L, ZIPINTERNALFILEHANDLE); /* create new metatable for internal file handles */
+ /* internal file methods */
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, -2); /* push metatable */
+ lua_rawset(L, -3); /* metatable.__index = metatable */
+ luaL_openlib(L, NULL, fflib, 0);
+}
+
+LUAZIP_API int luaopen_zip (lua_State *L) {
+ createmeta(L);
+ lua_pushvalue(L, -1);
+ luaL_openlib(L, LUA_ZIPLIBNAME, ziplib, 1);
+ set_info(L);
+ return 1;
+}
diff --git a/Build/source/libs/luazip/src/luazip.h b/Build/source/libs/luazip/src/luazip.h
new file mode 100644
index 00000000000..84bfd40b458
--- /dev/null
+++ b/Build/source/libs/luazip/src/luazip.h
@@ -0,0 +1,23 @@
+/*
+ LuaZip - Reading files inside zip files.
+ http://www.keplerproject.org/luazip/
+
+ Author: Danilo Tuler
+ Copyright (c) 2003-2006 Kepler Project
+
+ $Id: luazip.h,v 1.4 2006/03/23 20:44:53 carregal Exp $
+*/
+
+#ifndef luazip_h
+#define luazip_h
+
+#include "lua.h"
+
+#ifndef LUAZIP_API
+#define LUAZIP_API LUA_API
+#endif
+
+#define LUA_ZIPLIBNAME "zip"
+LUAZIP_API int luaopen_zip (lua_State *L);
+
+#endif
diff --git a/Build/source/libs/luazip/tests/a/b/c.zip b/Build/source/libs/luazip/tests/a/b/c.zip
new file mode 100644
index 00000000000..6e432b41c56
--- /dev/null
+++ b/Build/source/libs/luazip/tests/a/b/c.zip
Binary files differ
diff --git a/Build/source/libs/luazip/tests/a2/b2.ext2 b/Build/source/libs/luazip/tests/a2/b2.ext2
new file mode 100644
index 00000000000..cbc96481469
--- /dev/null
+++ b/Build/source/libs/luazip/tests/a2/b2.ext2
Binary files differ
diff --git a/Build/source/libs/luazip/tests/a2/b2.zip b/Build/source/libs/luazip/tests/a2/b2.zip
new file mode 100644
index 00000000000..4635580d657
--- /dev/null
+++ b/Build/source/libs/luazip/tests/a2/b2.zip
Binary files differ
diff --git a/Build/source/libs/luazip/tests/a3.ext3 b/Build/source/libs/luazip/tests/a3.ext3
new file mode 100644
index 00000000000..f02ba2cf97e
--- /dev/null
+++ b/Build/source/libs/luazip/tests/a3.ext3
Binary files differ
diff --git a/Build/source/libs/luazip/tests/a3.zip b/Build/source/libs/luazip/tests/a3.zip
new file mode 100644
index 00000000000..6f6c291f3d4
--- /dev/null
+++ b/Build/source/libs/luazip/tests/a3.zip
Binary files differ
diff --git a/Build/source/libs/luazip/tests/luazip.zip b/Build/source/libs/luazip/tests/luazip.zip
new file mode 100644
index 00000000000..bf498e2a0eb
--- /dev/null
+++ b/Build/source/libs/luazip/tests/luazip.zip
Binary files differ
diff --git a/Build/source/libs/luazip/tests/test_zip.lua b/Build/source/libs/luazip/tests/test_zip.lua
new file mode 100644
index 00000000000..84e2cae4ec0
--- /dev/null
+++ b/Build/source/libs/luazip/tests/test_zip.lua
@@ -0,0 +1,76 @@
+--[[------------------------------------------------------------------------
+test_zip.lua
+test code for luazip
+--]]------------------------------------------------------------------------
+
+-- compatibility code for Lua version 5.0 providing 5.1 behavior
+if string.find (_VERSION, "Lua 5.0") and not package then
+ if not LUA_PATH then
+ LUA_PATH = os.getenv("LUA_PATH") or "./?.lua;"
+ end
+ require"compat-5.1"
+ package.cpath = os.getenv("LUA_CPATH") or "./?.so;./?.dll;./?.dylib"
+end
+
+require('zip')
+
+function test_open ()
+ local zfile, err = zip.open('luazip.zip')
+
+ assert(zfile, err)
+
+ print("File list begin")
+ for file in zfile:files() do
+ print(file.filename)
+ end
+ print("File list ended OK!")
+ print()
+
+ print("Testing zfile:open")
+ local f1, err = zfile:open('README')
+ assert(f1, err)
+
+ local f2, err = zfile:open('luazip.h')
+ assert(f2, err)
+ print("zfile:open OK!")
+ print()
+
+ print("Testing reading by number")
+ local c = f1:read(1)
+ while c ~= nil do
+ io.write(c)
+ c = f1:read(1)
+ end
+
+ print()
+ print("OK")
+ print()
+end
+
+function test_openfile ()
+ print("Testing the openfile magic")
+
+ local d, err = zip.openfile('a/b/c/d.txt')
+ assert(d, err)
+
+ local e, err = zip.openfile('a/b/c/e.txt')
+ assert(e == nil, err)
+
+ local d2, err = zip.openfile('a2/b2/c2/d2.txt', "ext2")
+ assert(d2, err)
+
+ local e2, err = zip.openfile('a2/b2/c2/e2.txt', "ext2")
+ assert(e2 == nil, err)
+
+ local d3, err = zip.openfile('a3/b3/c3/d3.txt', {"ext2", "ext3"})
+ assert(d3, err)
+
+ local e3, err = zip.openfile('a3/b3/c3/e3.txt', {"ext2", "ext3"})
+ assert(e3 == nil, err)
+
+ print("Smooth magic!")
+ print()
+end
+
+test_open()
+test_openfile()
diff --git a/Build/source/libs/luazip/vc6/README b/Build/source/libs/luazip/vc6/README
new file mode 100644
index 00000000000..b059dc4bc55
--- /dev/null
+++ b/Build/source/libs/luazip/vc6/README
@@ -0,0 +1,28 @@
+These are the Visual Studio 6 projects provided by the Kepler Project
+
+Files:
+
+ luazip_dll.dsp
+ luazip_static.dsp
+ luazip.dsw
+ README
+
+Generated files:
+
+ luazip.ncb
+ luazip.opt
+
+ ../lib/vc6/libzip.lib
+ ../lib/vc6/libzipd.lib
+ ../lib/vc6/zip.exp
+ ../lib/vc6/zip.lib
+ ../lib/vc6/zipd.exp
+ ../lib/vc6/zipd.lib
+ ../lib/vc6/zipd.pdb
+
+ ../bin/vc6/zip.dll
+ ../bin/vc6/zipd.dll
+ ../bin/vc6/zipd.ilk
+
+Download source from:
+ http://prdownloads.sourceforge.net/zziplib/zziplib-0.12.83.tar.bz2?download \ No newline at end of file
diff --git a/Build/source/libs/luazip/vc6/luazip.dsw b/Build/source/libs/luazip/vc6/luazip.dsw
new file mode 100644
index 00000000000..1b9e29be03f
--- /dev/null
+++ b/Build/source/libs/luazip/vc6/luazip.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "luazip_dll"=.\luazip_dll.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/Build/source/libs/luazip/vc6/luazip.rc b/Build/source/libs/luazip/vc6/luazip.rc
new file mode 100644
index 00000000000..e493fc02f41
--- /dev/null
+++ b/Build/source/libs/luazip/vc6/luazip.rc
@@ -0,0 +1,109 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Portuguese (Brazil) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PTB)
+#ifdef _WIN32
+LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,2,1,0
+ PRODUCTVERSION 1,2,1,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x21L
+#else
+ FILEFLAGS 0x20L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Comments", "\0"
+ VALUE "CompanyName", "Ideais\0"
+ VALUE "FileDescription", "LuaZip\0"
+ VALUE "FileVersion", "1, 2, 1, 0\0"
+ VALUE "InternalName", "luazip\0"
+ VALUE "LegalCopyright", "Kepler Project © 2005\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "luazip.dll\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "LuaZip\0"
+ VALUE "ProductVersion", "1, 2, 1, 0\0"
+ VALUE "SpecialBuild", "lua-5.0.2, zziplib-0.12.83\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Portuguese (Brazil) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Build/source/libs/luazip/vc6/luazip_dll.dsp b/Build/source/libs/luazip/vc6/luazip_dll.dsp
new file mode 100644
index 00000000000..128cccf0d8e
--- /dev/null
+++ b/Build/source/libs/luazip/vc6/luazip_dll.dsp
@@ -0,0 +1,163 @@
+# Microsoft Developer Studio Project File - Name="luazip_dll" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=luazip_dll - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "luazip_dll.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "luazip_dll.mak" CFG="luazip_dll - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "luazip_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "luazip_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "luazip_dll - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../lib/vc6"
+# PROP Intermediate_Dir "luazip_dll/Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUAZIP_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../external-src/lua50/include" /I "../../external-src/zlib/include" /I "../../external-src/zziplib-0.12.83" /I "../../compat/src" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUAZIP_EXPORTS" /D LUAZIP_API=__declspec(dllexport) /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x416 /d "NDEBUG"
+# ADD RSC /l 0x416 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 lua50.lib zdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../bin/vc6/zip.dll" /libpath:"../../external-src/lua50/lib/dll" /libpath:"../../external-src/zlib/lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=cd ../bin/vc6 zip.exe luazip-1.2.1-win32.zip zip.dll
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "luazip_dll - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../lib/vc6"
+# PROP Intermediate_Dir "luazip_dll/Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUAZIP_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../external-src/lua50/include" /I "../../external-src/zlib/include" /I "../../external-src/zziplib-0.12.83" /I "../../compat/src" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUAZIP_EXPORTS" /D LUAZIP_API=__declspec(dllexport) /FR /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x416 /d "_DEBUG"
+# ADD RSC /l 0x416 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 lua50.lib zdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"../bin/vc6/zipd.dll" /pdbtype:sept /libpath:"../../external-src/lua50/lib/dll" /libpath:"../../external-src/zlib/lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "luazip_dll - Win32 Release"
+# Name "luazip_dll - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\..\compat\src\compat-5.1.c"
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\luazip.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\luazip.rc
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE="..\..\compat\src\compat-5.1.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\luazip.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "zziplib Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE="..\..\external-src\zziplib-0.12.83\zzip\dir.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\external-src\zziplib-0.12.83\zzip\err.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\external-src\zziplib-0.12.83\zzip\file.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\external-src\zziplib-0.12.83\zzip\info.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\external-src\zziplib-0.12.83\zzip\plugin.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\external-src\zziplib-0.12.83\zzip\stat.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\external-src\zziplib-0.12.83\zzip\write.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\external-src\zziplib-0.12.83\zzip\zip.c"
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/Build/source/libs/luazip/vc6/luazip_static.dsp b/Build/source/libs/luazip/vc6/luazip_static.dsp
new file mode 100644
index 00000000000..8558e9291c4
--- /dev/null
+++ b/Build/source/libs/luazip/vc6/luazip_static.dsp
@@ -0,0 +1,144 @@
+# Microsoft Developer Studio Project File - Name="luazip_static" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=luazip_static - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "luazip_static.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "luazip_static.mak" CFG="luazip_static - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "luazip_static - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "luazip_static - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "luazip_static - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../lib/vc6"
+# PROP Intermediate_Dir "luazip_static/Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../lua/include" /I "../../zlib/include" /I "../zziplib-0.12.83" /I "../../compat" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x416 /d "NDEBUG"
+# ADD RSC /l 0x416 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"../lib/vc6/libzip.lib"
+
+!ELSEIF "$(CFG)" == "luazip_static - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../lib/vc6"
+# PROP Intermediate_Dir "luazip_static/Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../lua/include" /I "../../zlib/include" /I "../zziplib-0.12.83" /I "../../compat" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x416 /d "_DEBUG"
+# ADD RSC /l 0x416 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"../lib/vc6/libzipd.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "luazip_static - Win32 Release"
+# Name "luazip_static - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\..\compat\compat-5.1.c"
+# End Source File
+# Begin Source File
+
+SOURCE=..\luazip.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE="..\..\compat\compat-5.1.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\luazip.h
+# End Source File
+# End Group
+# Begin Group "zziplib Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE="..\zziplib-0.12.83\zzip\dir.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zziplib-0.12.83\zzip\err.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zziplib-0.12.83\zzip\file.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zziplib-0.12.83\zzip\info.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zziplib-0.12.83\zzip\plugin.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zziplib-0.12.83\zzip\stat.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zziplib-0.12.83\zzip\write.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zziplib-0.12.83\zzip\zip.c"
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/Build/source/libs/luazip/vc6/resource.h b/Build/source/libs/luazip/vc6/resource.h
new file mode 100644
index 00000000000..53a3f933359
--- /dev/null
+++ b/Build/source/libs/luazip/vc6/resource.h
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by luazip.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Build/source/libs/luazip/vc7/README b/Build/source/libs/luazip/vc7/README
new file mode 100644
index 00000000000..aa091358dce
--- /dev/null
+++ b/Build/source/libs/luazip/vc7/README
@@ -0,0 +1,27 @@
+These are the Visual Studio 7 projects provided by the Kepler Project
+
+Files:
+
+ luazip_dll.vcproj
+ luazip_static.vcproj
+ luazip.sln
+ README
+
+Generated files:
+
+ lzip.suo
+
+ ../lib/vc7/libzip.lib
+ ../lib/vc7/libzipd.lib
+ ../lib/vc7/zip.exp
+ ../lib/vc7/zip.lib
+ ../lib/vc7/zipd.exp
+ ../lib/vc7/zipd.lib
+ ../lib/vc7/zipd.pdb
+
+ ../bin/vc7/zip.dll
+ ../bin/vc7/zipd.dll
+ ../bin/vc7/zipd.ilk
+
+Download source from:
+ http://prdownloads.sourceforge.net/zziplib/zziplib-0.12.83.tar.bz2?download \ No newline at end of file
diff --git a/Build/source/libs/luazip/vc7/luazip.rc b/Build/source/libs/luazip/vc7/luazip.rc
new file mode 100644
index 00000000000..b40e6ba04ea
--- /dev/null
+++ b/Build/source/libs/luazip/vc7/luazip.rc
@@ -0,0 +1,103 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Portuguese (Brazil) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PTB)
+#ifdef _WIN32
+LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,2,0,0
+ PRODUCTVERSION 1,2,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x21L
+#else
+ FILEFLAGS 0x20L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "CompanyName", "Ideais"
+ VALUE "FileDescription", "LuaZip"
+ VALUE "FileVersion", "1, 2, 0, 0"
+ VALUE "InternalName", "luazip"
+ VALUE "LegalCopyright", "Kepler Project © 2004"
+ VALUE "OriginalFilename", "luazip.dll"
+ VALUE "ProductName", "LuaZip"
+ VALUE "ProductVersion", "1, 2, 0, 0"
+ VALUE "SpecialBuild", "lua-5.0.2, zziplib-0.12.83, compat-5.1 release 1"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Portuguese (Brazil) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Build/source/libs/luazip/vc7/luazip.sln b/Build/source/libs/luazip/vc7/luazip.sln
new file mode 100644
index 00000000000..23a65cb6b93
--- /dev/null
+++ b/Build/source/libs/luazip/vc7/luazip.sln
@@ -0,0 +1,29 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "luazip_dll", "luazip_dll.vcproj", "{F7323180-F4E8-4994-9DE4-DB985CF23033}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "luazip_static", "luazip_static.vcproj", "{F4571BC6-4181-4D7C-BA2A-4398140445D0}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {F7323180-F4E8-4994-9DE4-DB985CF23033}.Debug.ActiveCfg = Debug|Win32
+ {F7323180-F4E8-4994-9DE4-DB985CF23033}.Debug.Build.0 = Debug|Win32
+ {F7323180-F4E8-4994-9DE4-DB985CF23033}.Release.ActiveCfg = Release|Win32
+ {F7323180-F4E8-4994-9DE4-DB985CF23033}.Release.Build.0 = Release|Win32
+ {F4571BC6-4181-4D7C-BA2A-4398140445D0}.Debug.ActiveCfg = Debug|Win32
+ {F4571BC6-4181-4D7C-BA2A-4398140445D0}.Debug.Build.0 = Debug|Win32
+ {F4571BC6-4181-4D7C-BA2A-4398140445D0}.Release.ActiveCfg = Release|Win32
+ {F4571BC6-4181-4D7C-BA2A-4398140445D0}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/luazip/vc7/luazip_dll.vcproj b/Build/source/libs/luazip/vc7/luazip_dll.vcproj
new file mode 100644
index 00000000000..480e556f41c
--- /dev/null
+++ b/Build/source/libs/luazip/vc7/luazip_dll.vcproj
@@ -0,0 +1,374 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="luazip_dll"
+ ProjectGUID="{29D4A74F-B425-4DD4-8CE4-419A244E89A6}"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\../lib/vc7"
+ IntermediateDirectory=".\luazip_dll/Release"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../../lua/include,../../zlib/include,../zziplib-0.12.83,../../compat"
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport)"
+ StringPooling="TRUE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\luazip_dll/Release/luazip_dll.pch"
+ AssemblerListingLocation=".\luazip_dll/Release/"
+ ObjectFile=".\luazip_dll/Release/"
+ ProgramDataBaseFileName=".\luazip_dll/Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="lua.lib lualib.lib zdll.lib odbc32.lib odbccp32.lib"
+ OutputFile="../bin/vc7/zip.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories="../../lua/lib/vc7,../../zlib/lib"
+ ProgramDatabaseFile=".\../lib/vc7/zip.pdb"
+ ImportLibrary=".\../lib/vc7/zip.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\../lib/vc7/luazip_dll.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\../lib/vc7"
+ IntermediateDirectory=".\luazip_dll/Debug"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../lua/include,../../zlib/include,../zziplib-0.12.83,../../compat"
+ PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport)"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\luazip_dll/Debug/luazip_dll.pch"
+ AssemblerListingLocation=".\luazip_dll/Debug/"
+ ObjectFile=".\luazip_dll/Debug/"
+ ProgramDataBaseFileName=".\luazip_dll/Debug/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="luad.lib lualibd.lib zdll.lib odbc32.lib odbccp32.lib"
+ OutputFile="../bin/vc7/zipd.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories="../../lua/lib/vc7,../../zlib/lib"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\../lib/vc7/zipd.pdb"
+ ImportLibrary=".\../lib/vc7/zipd.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\../lib/vc7/luazip_dll.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\..\compat\compat-5.1.c">
+ </File>
+ <File
+ RelativePath="..\luazip.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="luazip.rc">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="..\..\compat\compat-5.1.h">
+ </File>
+ <File
+ RelativePath="..\luazip.h">
+ </File>
+ <File
+ RelativePath=".\resource.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="zziplib Files"
+ Filter="">
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\dir.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\err.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\file.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\info.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\plugin.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\stat.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\write.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\zip.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_MBCS;_USRDLL;LUAZIP_EXPORTS;LUAZIP_API=__declspec(dllexport);$(NoInherit)"
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/luazip/vc7/luazip_static.vcproj b/Build/source/libs/luazip/vc7/luazip_static.vcproj
new file mode 100644
index 00000000000..37642467175
--- /dev/null
+++ b/Build/source/libs/luazip/vc7/luazip_static.vcproj
@@ -0,0 +1,324 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="luazip_static"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\../lib/vc7"
+ IntermediateDirectory=".\luazip_static/Release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../../lua/include,../../zlib/include,../zziplib-0.12.83,../../compat"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\luazip_static/Release/luazip_static.pch"
+ AssemblerListingLocation=".\luazip_static/Release/"
+ ObjectFile=".\luazip_static/Release/"
+ ProgramDataBaseFileName=".\luazip_static/Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="../lib/vc7/libzip.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\../lib/vc7"
+ IntermediateDirectory=".\luazip_static/Debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../lua/include,../../zlib/include,../zziplib-0.12.83,../../compat"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\luazip_static/Debug/luazip_static.pch"
+ AssemblerListingLocation=".\luazip_static/Debug/"
+ ObjectFile=".\luazip_static/Debug/"
+ ProgramDataBaseFileName=".\luazip_static/Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="../lib/vc7/libzipd.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\..\compat\compat-5.1.c">
+ </File>
+ <File
+ RelativePath="..\luazip.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="..\..\compat\compat-5.1.h">
+ </File>
+ <File
+ RelativePath="..\luazip.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="zziplib Files"
+ Filter="">
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\dir.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\err.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\file.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\info.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\plugin.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\stat.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\write.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\zziplib-0.12.83\zzip\zip.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/luazip/vc7/resource.h b/Build/source/libs/luazip/vc7/resource.h
new file mode 100644
index 00000000000..54116ac80fb
--- /dev/null
+++ b/Build/source/libs/luazip/vc7/resource.h
@@ -0,0 +1,27 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by luazip.rc
+//
+#define IDS_PROJNAME 100
+#define IDR_WMDMLOGGER 101
+#define IDS_LOG_SEV_INFO 201
+#define IDS_LOG_SEV_WARN 202
+#define IDS_LOG_SEV_ERROR 203
+#define IDS_LOG_DATETIME 204
+#define IDS_LOG_SRCNAME 205
+#define IDS_DEF_LOGFILE 301
+#define IDS_DEF_MAXSIZE 302
+#define IDS_DEF_SHRINKTOSIZE 303
+#define IDS_DEF_LOGENABLED 304
+#define IDS_MUTEX_TIMEOUT 401
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 201
+#define _APS_NEXT_COMMAND_VALUE 32768
+#define _APS_NEXT_CONTROL_VALUE 201
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Build/source/libs/luazlib/Makefile b/Build/source/libs/luazlib/Makefile
new file mode 100644
index 00000000000..a4bc3d9a82a
--- /dev/null
+++ b/Build/source/libs/luazlib/Makefile
@@ -0,0 +1,57 @@
+# $Id: Makefile,v 1.8 2004/07/22 19:10:47 tngd Exp $
+# makefile for zlib library for Lua
+
+# dist location
+DISTDIR=$(HOME)/dist
+TMP=/tmp
+
+# change these to reflect your Lua installation
+LUA= $(HOME)/lua
+LUAINC= $(LUA)/include
+LUALIB= $(LUA)/lib
+LUABIN= $(LUA)/bin
+
+ZLIB=../zlib-1.2.1
+
+# no need to change anything below here
+CFLAGS= $(INCS) $(DEFS) $(WARN) -O2
+WARN= -g -Werror -Wall #-ansi -pedantic -Wall
+INCS= -I$(LUAINC) -I$(ZLIB)
+LIBS= -L$(ZLIB) -lz
+
+MYNAME= zlib
+MYLIB= l$(MYNAME)
+
+OBJS= lzlib.o lgzip.o
+
+T= $(MYLIB).so
+
+VER=0.2
+TARFILE = $(DISTDIR)/$(MYLIB)-$(VER).tar.gz
+TARFILES = Makefile README \
+ lzlib.c lgzip.c \
+ zlib.lua gzip.lua \
+ test_zlib.lua test_gzip.lua
+
+all: $T
+
+#lua: lzlib.o lua.o lauxlib.o
+# gcc -g -o lua lua.o $(OBJS) -I. $(LIBS) -lm -ldl -llualib -llua
+
+test: $T
+ $(LUABIN)/lua -lzlib test_zlib.lua
+ $(LUABIN)/lua -lgzip test_gzip.lua
+
+$T: $(OBJS)
+ $(CC) -o $@ -shared $(OBJS) $(LIBS)
+
+clean:
+ rm -f $(OBJS) $T core core.* a.out
+
+dist: $(TARFILE)
+
+$(TARFILE): $(TARFILES)
+ @ln -sf `pwd` $(TMP)/$(MYLIB)-$(VER)
+ tar -zcvf $(TARFILE) -C $(TMP) $(addprefix $(MYLIB)-$(VER)/,$(TARFILES))
+ @rm -f $(TMP)/$(MYLIB)-$(VER)
+ @lsum $(TARFILE) $(DISTDIR)/md5sums.txt
diff --git a/Build/source/libs/luazlib/README b/Build/source/libs/luazlib/README
new file mode 100644
index 00000000000..35aa883838e
--- /dev/null
+++ b/Build/source/libs/luazlib/README
@@ -0,0 +1,30 @@
+*************************************************************************
+* Author : Tiago Dionizio (tngd@mega.ist.utl.pt) *
+* Library : lzlib - Lua 5 interface to access zlib library functions *
+* *
+* Permission is hereby granted, free of charge, to any person obtaining *
+* a copy of this software and associated documentation files (the *
+* "Software"), to deal in the Software without restriction, including *
+* without limitation the rights to use, copy, modify, merge, publish, *
+* distribute, sublicense, and/or sell copies of the Software, and to *
+* permit persons to whom the Software is furnished to do so, subject to *
+* the following conditions: *
+* *
+* The above copyright notice and this permission notice shall be *
+* included in all copies or substantial portions of the Software. *
+* *
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY *
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, *
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE *
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+*************************************************************************
+
+To use this library you need zlib library.
+You can get it from http://www.gzip.org/zlib/
+
+
+Read description in zlib.lua and lzlib.c for details on how to use this
+library.
diff --git a/Build/source/libs/luazlib/gzip.lua b/Build/source/libs/luazlib/gzip.lua
new file mode 100644
index 00000000000..d7b0db4a0e0
--- /dev/null
+++ b/Build/source/libs/luazlib/gzip.lua
@@ -0,0 +1,102 @@
+--[[------------------------------------------------------------------------
+gzip.lua
+support code for zlib library version 1.2.1 - gzip extentions
+usage lua -lgzip ...
+
+Author: Tiago Dionizio (tngd@mega.ist.utl.pt)
+$Id: gzip.lua,v 1.3 2004/07/22 19:11:55 tngd Exp $
+--]]------------------------------------------------------------------------
+
+
+--[[------------------------------------------------------------------------
+
+After loading the module a table with the following interface should be
+available:
+
+gzip.open(filename [, mode])
+
+ Opens a file name using "gzopen". Behaviour is identical to the description
+ given in the zlib library. If mode is not given a default mode "rb" will be
+ used. Mode is the same as interpreted by gzopen function, ie, it can
+ include special modes such as characters 1 to 9 that will be treated as the
+ compression level when opening a file for writing.
+
+ It returns a new file handle, or, in case of errors, nil plus an error
+ message
+
+gzip.lines(filename)
+
+ Same behaviour as io.lines in the io standard library provided by lua
+ with the aditional feature of working with gzip files. If a normal text
+ file is read it will read it normaly (normal gzopen behaviour).
+
+gzip.close(file)
+
+ Same as file:close, use file:close instead.
+
+file:flush()
+
+ This function takes no parameters and flushes all output to working file.
+ The same as calling 'gzflush(file, Z_FINISH)' so writing to the file will
+ most likely not work as expected. This is subject to change in the future
+ if there is a strong reason for it to happen.
+
+file:read(format1, ...)
+ Reads the file file, according to the given formats, which specify what
+ to read. For each format, the function returns a string with the characters
+ read, or nil if it cannot read data with the specified format. When called
+ without formats, it uses a default format that reads the entire next line
+ (see below).
+
+ The available formats are
+
+ "*a" reads the whole file, starting at the current position. On end of
+ file, it returns the empty string.
+ "*l" reads the next line (skipping the end of line), returning nil on
+ end of file. This is the default format.
+ number reads a string with up to that number of characters, returning
+ nil on end of file. If number is zero, it reads nothing and
+ returns an empty string, or nil on end of file.
+
+ Unlink io.read, the "*n" format will not be available.
+
+
+file:lines()
+
+ Returns an iterator function that, each time it is called, returns a new
+ line from the file. Therefore, the construction
+ for line in file:lines() do ... end
+ will iterate over all lines of the file. (Unlike gzip.lines, this function
+ does not close the file when the loop ends.)
+
+file:seek([whence] [, offset])
+
+ Sets and gets the file position, measured from the beginning of the file,
+ to the position given by offset plus a base specified by the string whence,
+ as follows:
+
+ "set" base is position 0 (beginning of the file);
+ "cur" base is current position;
+
+ In case of success, function seek returns the final file position, measured in bytes from the beginning of the file. If this function fails, it returns nil, plus a string describing the error.
+ The default value for whence is "cur", and for offset is 0. Therefore, the call file:seek() returns the current file position, without changing it; the call file:seek("set") sets the position to the beginning of the file (and returns 0); and the call file:seek("end") sets the position to the end of the file, and returns its size.
+
+ This function is subject to limitations imposed by gzseek function from
+ zlib library, such as the inability to use "end" as the base for seeking
+ and the inability to seek backwards when writing.
+
+file:write(value1, ...)
+
+ Writes the value of each of its arguments to the filehandle file. The
+ arguments must be strings or numbers. To write other values, use tostring
+ or string.format before write
+
+file:close()
+
+ Closes the file.
+
+--]]------------------------------------------------------------------------
+
+require("requirelib")
+
+requirelib("lzlib", "luaopen_gzip", true)
diff --git a/Build/source/libs/luazlib/lgzip.c b/Build/source/libs/luazlib/lgzip.c
new file mode 100644
index 00000000000..603b0f71877
--- /dev/null
+++ b/Build/source/libs/luazlib/lgzip.c
@@ -0,0 +1,373 @@
+/************************************************************************
+* Author : Tiago Dionizio (tngd@mega.ist.utl.pt) *
+* Library : lgzip - a gzip file access binding for Lua 5 *
+* based on liolib.c from Lua 5.0 library *
+* *
+* Permission is hereby granted, free of charge, to any person obtaining *
+* a copy of this software and associated documentation files (the *
+* "Software"), to deal in the Software without restriction, including *
+* without limitation the rights to use, copy, modify, merge, publish, *
+* distribute, sublicense, and/or sell copies of the Software, and to *
+* permit persons to whom the Software is furnished to do so, subject to *
+* the following conditions: *
+* *
+* The above copyright notice and this permission notice shall be *
+* included in all copies or substantial portions of the Software. *
+* *
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY *
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, *
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE *
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+************************************************************************/
+
+/************************************************************************
+$Id: lgzip.c,v 1.2 2003/12/28 01:26:16 tngd Exp $
+Changes:
+************************************************************************/
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "zlib.h"
+
+#include "lua.h"
+#include "lauxlib.h"
+
+
+
+/*
+** {======================================================
+** FILE Operations
+** =======================================================
+*/
+
+
+#define FILEHANDLE "zlib:gzFile"
+
+
+static int pushresult (lua_State *L, int i, const char *filename) {
+ if (i) {
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+ else {
+ lua_pushnil(L);
+ if (filename)
+ lua_pushfstring(L, "%s: %s", filename, strerror(errno));
+ else
+ lua_pushfstring(L, "%s", strerror(errno));
+ lua_pushnumber(L, errno);
+ return 3;
+ }
+}
+
+
+static gzFile *topfile (lua_State *L, int findex) {
+ gzFile*f = (gzFile*)luaL_checkudata(L, findex, FILEHANDLE);
+ if (f == NULL) luaL_argerror(L, findex, "bad file");
+ return f;
+}
+
+
+static gzFile tofile (lua_State *L, int findex) {
+ gzFile*f = topfile(L, findex);
+ if (*f == NULL)
+ luaL_error(L, "attempt to use a closed file");
+ return *f;
+}
+
+
+
+/*
+** When creating file handles, always creates a `closed' file handle
+** before opening the actual file; so, if there is a memory error, the
+** file is not left opened.
+*/
+static gzFile *newfile (lua_State *L) {
+ gzFile *pf = (gzFile*)lua_newuserdata(L, sizeof(gzFile));
+ *pf = NULL; /* file handle is currently `closed' */
+ luaL_getmetatable(L, FILEHANDLE);
+ lua_setmetatable(L, -2);
+ return pf;
+}
+
+
+static int aux_close (lua_State *L) {
+ gzFile f = tofile(L, 1);
+ int ok = (gzclose(f) == Z_OK);
+ if (ok)
+ *(gzFile*)lua_touserdata(L, 1) = NULL; /* mark file as closed */
+ return ok;
+}
+
+
+static int io_close (lua_State *L) {
+ return pushresult(L, aux_close(L), NULL);
+}
+
+
+static int io_gc (lua_State *L) {
+ gzFile *f = topfile(L, 1);
+ if (*f != NULL) /* ignore closed files */
+ aux_close(L);
+ return 0;
+}
+
+
+static int io_tostring (lua_State *L) {
+ char buff[128];
+ gzFile *f = topfile(L, 1);
+ if (*f == NULL)
+ strcpy(buff, "closed");
+ else
+ sprintf(buff, "%p", lua_touserdata(L, 1));
+ lua_pushfstring(L, "gzip file (%s)", buff);
+ return 1;
+}
+
+
+static int io_open (lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ const char *mode = luaL_optstring(L, 2, "rb");
+ gzFile *pf = newfile(L);
+ *pf = gzopen(filename, mode);
+ return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
+}
+
+
+static int io_readline (lua_State *L);
+
+static void aux_lines (lua_State *L, int idx, int close) {
+ lua_pushliteral(L, FILEHANDLE);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_pushvalue(L, idx);
+ lua_pushboolean(L, close); /* close/not close file when finished */
+ lua_pushcclosure(L, io_readline, 3);
+}
+
+
+static int f_lines (lua_State *L) {
+ tofile(L, 1); /* check that it's a valid file handle */
+ aux_lines(L, 1, 0);
+ return 1;
+}
+
+
+static int io_lines (lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ gzFile *pf = newfile(L);
+ *pf = gzopen(filename, "rb");
+ luaL_argcheck(L, *pf, 1, strerror(errno));
+ aux_lines(L, lua_gettop(L), 1);
+ return 1;
+}
+
+
+/*
+** {======================================================
+** READ
+** =======================================================
+*/
+
+
+static int test_eof (lua_State *L, gzFile f) {
+ lua_pushlstring(L, NULL, 0);
+ return (gzeof(f) != 1);
+}
+
+
+static int read_line (lua_State *L, gzFile f) {
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ for (;;) {
+ size_t l;
+ char *p = luaL_prepbuffer(&b);
+ if (gzgets(f, p, LUAL_BUFFERSIZE) == NULL) { /* eof? */
+ luaL_pushresult(&b); /* close buffer */
+ return (lua_strlen(L, -1) > 0); /* check whether read something */
+ }
+ l = strlen(p);
+ if (p[l-1] != '\n')
+ luaL_addsize(&b, l);
+ else {
+ luaL_addsize(&b, l - 1); /* do not include `eol' */
+ luaL_pushresult(&b); /* close buffer */
+ return 1; /* read at least an `eol' */
+ }
+ }
+}
+
+
+static int read_chars (lua_State *L, gzFile f, size_t n) {
+ size_t rlen; /* how much to read */
+ size_t nr; /* number of chars actually read */
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ rlen = LUAL_BUFFERSIZE; /* try to read that much each time */
+ do {
+ char *p = luaL_prepbuffer(&b);
+ if (rlen > n) rlen = n; /* cannot read more than asked */
+ nr = gzread(f, p, rlen);
+ luaL_addsize(&b, nr);
+ n -= nr; /* still have to read `n' chars */
+ } while (n > 0 && nr == rlen); /* until end of count or eof */
+ luaL_pushresult(&b); /* close buffer */
+ return (n == 0 || lua_strlen(L, -1) > 0);
+}
+
+
+static int g_read (lua_State *L, gzFile f, int first) {
+ int nargs = lua_gettop(L) - 1;
+ int success;
+ int n;
+ if (nargs == 0) { /* no arguments? */
+ success = read_line(L, f);
+ n = first+1; /* to return 1 result */
+ }
+ else { /* ensure stack space for all results and for auxlib's buffer */
+ luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
+ success = 1;
+ for (n = first; nargs-- && success; n++) {
+ if (lua_type(L, n) == LUA_TNUMBER) {
+ size_t l = (size_t)lua_tonumber(L, n);
+ success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
+ }
+ else {
+ const char *p = lua_tostring(L, n);
+ luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
+ switch (p[1]) {
+ case 'l': /* line */
+ success = read_line(L, f);
+ break;
+ case 'a': /* file */
+ read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */
+ success = 1; /* always success */
+ break;
+ default:
+ return luaL_argerror(L, n, "invalid format");
+ }
+ }
+ }
+ }
+ if (!success) {
+ lua_pop(L, 1); /* remove last result */
+ lua_pushnil(L); /* push nil instead */
+ }
+ return n - first;
+}
+
+
+static int f_read (lua_State *L) {
+ return g_read(L, tofile(L, 1), 2);
+}
+
+
+static int io_readline (lua_State *L) {
+ gzFile f = *(gzFile*)lua_touserdata(L, lua_upvalueindex(2));
+ if (f == NULL) /* file is already closed? */
+ luaL_error(L, "file is already closed");
+ if (read_line(L, f)) return 1;
+ else { /* EOF */
+ if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
+ lua_settop(L, 0);
+ lua_pushvalue(L, lua_upvalueindex(2));
+ aux_close(L); /* close it */
+ }
+ return 0;
+ }
+}
+
+/* }====================================================== */
+
+
+static int g_write (lua_State *L, gzFile f, int arg) {
+ int nargs = lua_gettop(L) - 1;
+ int status = 1;
+ for (; nargs--; arg++) {
+ if (lua_type(L, arg) == LUA_TNUMBER) {
+ /* optimization: could be done exactly as for strings */
+ status = status &&
+ gzprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+ }
+ else {
+ size_t l;
+ const char *s = luaL_checklstring(L, arg, &l);
+ status = status && (gzwrite(f, (char*)s, l) == l);
+ }
+ }
+ return pushresult(L, status, NULL);
+}
+
+
+static int f_write (lua_State *L) {
+ return g_write(L, tofile(L, 1), 2);
+}
+
+
+static int f_seek (lua_State *L) {
+ static const int mode[] = {SEEK_SET, SEEK_CUR};
+ static const char *const modenames[] = {"set", "cur", NULL};
+ gzFile f = tofile(L, 1);
+ int op = luaL_checkoption(L, 2, "cur", modenames);
+ long offset = luaL_optlong(L, 3, 0);
+ luaL_argcheck(L, op != -1, 2, "invalid mode");
+ op = gzseek(f, offset, mode[op]);
+ if (op == -1)
+ return pushresult(L, 0, NULL); /* error */
+ else {
+ lua_pushnumber(L, op);
+ return 1;
+ }
+}
+
+
+static int f_flush (lua_State *L) {
+ return pushresult(L, gzflush(tofile(L, 1), Z_FINISH) == Z_OK, NULL);
+}
+
+
+static const luaL_reg iolib[] = {
+ {"lines", io_lines},
+ {"close", io_close},
+ {"open", io_open},
+ {NULL, NULL}
+};
+
+
+static const luaL_reg flib[] = {
+ {"flush", f_flush},
+ {"read", f_read},
+ {"lines", f_lines},
+ {"seek", f_seek},
+ {"write", f_write},
+ {"close", io_close},
+ {"__gc", io_gc},
+ {"__tostring", io_tostring},
+ {NULL, NULL}
+};
+
+
+static void createmeta (lua_State *L) {
+ luaL_newmetatable(L, FILEHANDLE); /* create new metatable for file handles */
+ /* file methods */
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, -2); /* push metatable */
+ lua_rawset(L, -3); /* metatable.__index = metatable */
+ luaL_openlib(L, NULL, flib, 0);
+}
+
+
+/* }====================================================== */
+
+
+
+LUALIB_API int luaopen_gzip (lua_State *L) {
+ createmeta(L);
+ lua_pushvalue(L, -1);
+ luaL_openlib(L, "gzip", iolib, 1);
+ return 1;
+}
+
diff --git a/Build/source/libs/luazlib/lzlib.c b/Build/source/libs/luazlib/lzlib.c
new file mode 100644
index 00000000000..ebc72d97664
--- /dev/null
+++ b/Build/source/libs/luazlib/lzlib.c
@@ -0,0 +1,584 @@
+/************************************************************************
+* Author : Tiago Dionizio (tngd@mega.ist.utl.pt) *
+* Library : lzlib - Lua 5 interface to access zlib library functions *
+* *
+* Permission is hereby granted, free of charge, to any person obtaining *
+* a copy of this software and associated documentation files (the *
+* "Software"), to deal in the Software without restriction, including *
+* without limitation the rights to use, copy, modify, merge, publish, *
+* distribute, sublicense, and/or sell copies of the Software, and to *
+* permit persons to whom the Software is furnished to do so, subject to *
+* the following conditions: *
+* *
+* The above copyright notice and this permission notice shall be *
+* included in all copies or substantial portions of the Software. *
+* *
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY *
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, *
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE *
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+************************************************************************/
+
+/************************************************************************
+$Id: lzlib.c,v 1.3 2004/07/22 19:10:47 tngd Exp $
+Changes:
+************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include "lua.h"
+#include "lauxlib.h"
+
+#include "zlib.h"
+
+
+/*
+** =========================================================================
+** compile time options wich determine available functionality
+** =========================================================================
+*/
+
+
+/*
+** =========================================================================
+** zlib stream metamethods
+** =========================================================================
+*/
+#define ZSTREAMMETA "zlib:zstream"
+
+#define LZANY (void*)-1
+#define LZNONE (void*)0
+#define LZDEFLATE (void*)1
+#define LZINFLATE (void*)2
+
+static z_stream *lzstream_new(lua_State *L)
+{
+ z_stream *s = (z_stream*)lua_newuserdata(L, sizeof(z_stream));
+
+ luaL_getmetatable(L, ZSTREAMMETA);
+ lua_setmetatable(L, -2); /* set metatable */
+
+ s->zalloc = Z_NULL;
+ s->zfree = Z_NULL;
+
+ s->next_out = Z_NULL;
+ s->avail_out = 0;
+ s->next_in = Z_NULL;
+ s->avail_in = 0;
+
+ s->opaque = LZNONE;
+
+ return s;
+}
+
+static void lzstream_cleanup(lua_State *L, z_stream *s)
+{
+ if (s && s->opaque != LZNONE)
+ {
+ if (s->opaque == LZINFLATE)
+ inflateEnd(s);
+ if (s->opaque == LZDEFLATE)
+ deflateEnd(s);
+ s->opaque = LZNONE;
+ }
+}
+
+/* ====================================================================== */
+
+static z_stream *lzstream_get(lua_State *L, int index)
+{
+ z_stream *s = (z_stream*)luaL_checkudata(L, index, ZSTREAMMETA);
+ if (s == NULL) luaL_argerror(L, index, "bad zlib stream");
+ return s;
+}
+
+static z_stream *lzstream_check(lua_State *L, int index, void *state)
+{
+ z_stream *s = lzstream_get(L, index);
+ if ((state != LZANY && s->opaque != state) || s->opaque == LZNONE)
+ luaL_argerror(L, index, "attempt to use invalid zlib stream");
+ return s;
+}
+
+/* ====================================================================== */
+
+static int lzstream_tostring(lua_State *L)
+{
+ char buf[100];
+ z_stream *s = (z_stream*)luaL_checkudata(L, 1, ZSTREAMMETA);
+ if (s == NULL) luaL_argerror(L, 1, "bad zlib stream");
+
+ if (s->opaque == LZNONE)
+ strncpy(buf, "zlib stream (closed)", 100);
+ else if (s->opaque == LZDEFLATE)
+ snprintf(buf, 100, "zlib deflate stream (%p)", s);
+ else if (s->opaque == LZINFLATE)
+ snprintf(buf, 100, "zlib inflate stream (%p)", s);
+ else
+ snprintf(buf, 100, "%p", s);
+
+ lua_pushstring(L, buf);
+ return 1;
+}
+
+/* ====================================================================== */
+
+static int lzstream_gc(lua_State *L)
+{
+ z_stream *s = lzstream_get(L, 1);
+ lzstream_cleanup(L, s);
+ return 0;
+}
+
+/* ====================================================================== */
+
+static int lzstream_close(lua_State *L)
+{
+ z_stream *s = lzstream_check(L, 1, LZANY);
+ lzstream_cleanup(L, s);
+ return 0;
+}
+
+/* ====================================================================== */
+
+static int lzstream_adler(lua_State *L)
+{
+ z_stream *s = lzstream_check(L, 1, LZANY);
+ lua_pushnumber(L, s->adler);
+ return 1;
+}
+
+/* ====================================================================== */
+
+static int lzlib_deflate(lua_State *L)
+{
+ int level = luaL_optint(L, 1, Z_DEFAULT_COMPRESSION);
+ int method = luaL_optint(L, 2, Z_DEFLATED);
+ int windowBits = luaL_optint(L, 3, 15);
+ int memLevel = luaL_optint(L, 4, 8);
+ int strategy = luaL_optint(L, 5, Z_DEFAULT_STRATEGY);
+
+ z_stream *s = lzstream_new(L);
+
+ if (deflateInit2(s, level, method, windowBits, memLevel, strategy) != Z_OK)
+ {
+ lua_pushliteral(L, "failed to start decompressing");
+ lua_error(L);
+ }
+ s->opaque = LZDEFLATE;
+ return 1;
+}
+
+/* ====================================================================== */
+
+static int lzlib_inflate(lua_State *L)
+{
+ int windowBits = luaL_optint(L, 1, 15);
+
+ z_stream *s = lzstream_new(L);
+
+ if (inflateInit2(s, windowBits) != Z_OK)
+ {
+ lua_pushliteral(L, "failed to start compressing");
+ lua_error(L);
+ }
+
+ s->opaque = LZINFLATE;
+ return 1;
+}
+
+/* ====================================================================== */
+
+static int lzstream_decompress(lua_State *L)
+{
+ z_stream *s = lzstream_check(L, 1, LZINFLATE);
+ s->next_in = (char*)luaL_checkstring(L, 2);
+ s->avail_in = lua_strlen(L, 2);
+
+ {
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ int r;
+
+ do {
+ s->next_out = luaL_prepbuffer(&b);
+ s->avail_out = LUAL_BUFFERSIZE;
+
+ /* munch some more */
+ r = inflate(s, Z_SYNC_FLUSH);
+ if (r != Z_OK && r != Z_STREAM_END) {
+ lua_pushfstring(L, "failed to decompress [%d]", r);
+ lua_error(L);
+ }
+
+ /* push gathered data */
+ luaL_addsize(&b, LUAL_BUFFERSIZE - s->avail_out);
+
+ /* until we have free space in the output buffer - meaning we are done */
+ } while (s->avail_in > 0 || s->avail_out == 0);
+
+ /* send gathered data if any */
+ luaL_pushresult(&b);
+ }
+ return 1;
+}
+
+/* ====================================================================== */
+
+static int lzstream_compress(lua_State *L)
+{
+ z_stream *s = lzstream_check(L, 1, LZDEFLATE);
+ s->next_in = (char*)luaL_checkstring(L, 2);
+ s->avail_in = lua_strlen(L, 2);
+
+ {
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ int r;
+
+ do {
+ s->next_out = luaL_prepbuffer(&b);
+ s->avail_out = LUAL_BUFFERSIZE;
+
+ /* bake some more */
+ if ((r = deflate(s, Z_NO_FLUSH)) != Z_OK)
+ {
+ lua_pushfstring(L, "failed to compress [%d]", r);
+ lua_error(L);
+ }
+
+ /* push gathered data */
+ luaL_addsize(&b, LUAL_BUFFERSIZE - s->avail_out);
+
+ /* until we have free space in the output buffer - meaning we are done */
+ } while (s->avail_out == 0);
+
+ /* send gathered data if any */
+ luaL_pushresult(&b);
+ }
+ return 1;
+}
+
+/* ====================================================================== */
+
+static int lzstream_flush(lua_State *L)
+{
+ z_stream *s = lzstream_check(L, 1, LZANY);
+
+ if (s->opaque == LZINFLATE) {
+ lua_pushliteral(L, "");
+ return 1;
+ }
+
+ s->next_in = "";
+ s->avail_in = 0;
+
+ {
+ int r = 0;
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+
+ do {
+ s->next_out = luaL_prepbuffer(&b);
+ s->avail_out = LUAL_BUFFERSIZE;
+
+ r = deflate(s, Z_FINISH);
+
+ if (r != Z_OK && r != Z_STREAM_END) {
+ lua_pushfstring(L, "failed to flush [%d]", r);
+ lua_error(L);
+ }
+
+ /* push gathered data */
+ luaL_addsize(&b, LUAL_BUFFERSIZE - s->avail_out);
+ } while (r != Z_STREAM_END);
+
+ /* send gathered data if any */
+ luaL_pushresult(&b);
+ }
+ return 1;
+}
+
+/* ====================================================================== */
+
+static int lzstream_reset(lua_State *L)
+{
+ z_stream *s = lzstream_check(L, 1, LZANY);
+
+ if (s->state == LZDEFLATE)
+ lua_pushnumber(L, deflateReset(s));
+ else if (s->opaque == LZINFLATE)
+ lua_pushnumber(L, inflateReset(s));
+ else
+ {
+ lua_pushliteral(L, "invalid zlib stream state");
+ lua_error(L);
+ }
+
+ return 1;
+}
+
+
+/*
+** =========================================================================
+** zlib functions
+** =========================================================================
+*/
+
+static int lzlib_version(lua_State *L)
+{
+ lua_pushstring(L, zlibVersion());
+ return 1;
+}
+
+/* ====================================================================== */
+static int lzlib_adler32(lua_State *L)
+{
+ if (lua_gettop(L) == 0)
+ {
+ /* adler32 initial value */
+ lua_pushnumber(L, adler32(0L, Z_NULL, 0));
+ }
+ else
+ {
+ /* update adler32 checksum */
+ int adler = luaL_checkint(L, 1);
+ const char* buf = luaL_checkstring(L, 2);
+ int len = lua_strlen(L, 2);
+
+ lua_pushnumber(L, adler32(adler, buf, len));
+ }
+ return 1;
+}
+
+/* ====================================================================== */
+static int lzlib_crc32(lua_State *L)
+{
+ if (lua_gettop(L) == 0)
+ {
+ /* crc32 initial value */
+ lua_pushnumber(L, crc32(0L, Z_NULL, 0));
+ }
+ else
+ {
+ /* update crc32 checksum */
+ int crc = luaL_checkint(L, 1);
+ const char* buf = luaL_checkstring(L, 2);
+ int len = lua_strlen(L, 2);
+
+ lua_pushnumber(L, crc32(crc, buf, len));
+ }
+ return 1;
+}
+
+/* ====================================================================== */
+
+
+static int lzlib_compress(lua_State *L)
+{
+ const char *next_in = luaL_checkstring(L, 1);
+ int avail_in = lua_strlen(L, 1);
+ int level = luaL_optint(L, 2, Z_DEFAULT_COMPRESSION);
+ int method = luaL_optint(L, 3, Z_DEFLATED);
+ int windowBits = luaL_optint(L, 4, 15);
+ int memLevel = luaL_optint(L, 5, 8);
+ int strategy = luaL_optint(L, 6, Z_DEFAULT_STRATEGY);
+
+ int ret;
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+
+ z_stream zs;
+
+ zs.zalloc = Z_NULL;
+ zs.zfree = Z_NULL;
+
+ zs.next_out = Z_NULL;
+ zs.avail_out = 0;
+ zs.next_in = Z_NULL;
+ zs.avail_in = 0;
+
+ ret = deflateInit2(&zs, level, method, windowBits, memLevel, strategy);
+
+ if (ret != Z_OK)
+ {
+ lua_pushnil(L);
+ lua_pushnumber(L, ret);
+ return 2;
+ }
+
+ zs.next_in = (char*)next_in;
+ zs.avail_in = avail_in;
+
+ for(;;)
+ {
+ zs.next_out = luaL_prepbuffer(&b);
+ zs.avail_out = LUAL_BUFFERSIZE;
+
+ /* munch some more */
+ ret = deflate(&zs, Z_FINISH);
+
+ /* push gathered data */
+ luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out);
+
+ /* done processing? */
+ if (ret == Z_STREAM_END)
+ break;
+
+ /* error condition? */
+ if (ret != Z_OK)
+ break;
+ }
+
+ /* cleanup */
+ deflateEnd(&zs);
+
+ luaL_pushresult(&b);
+ lua_pushnumber(L, ret);
+ return 2;
+}
+
+/* ====================================================================== */
+
+static int lzlib_decompress(lua_State *L)
+{
+ const char *next_in = luaL_checkstring(L, 1);
+ int avail_in = lua_strlen(L, 1);
+ int windowBits = luaL_optint(L, 2, 15);
+
+ int ret;
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+
+ z_stream zs;
+
+ zs.zalloc = Z_NULL;
+ zs.zfree = Z_NULL;
+
+ zs.next_out = Z_NULL;
+ zs.avail_out = 0;
+ zs.next_in = Z_NULL;
+ zs.avail_in = 0;
+
+ ret = inflateInit2(&zs, windowBits);
+
+ if (ret != Z_OK)
+ {
+ lua_pushnil(L);
+ lua_pushnumber(L, ret);
+ return 2;
+ }
+
+ zs.next_in = (char*)next_in;
+ zs.avail_in = avail_in;
+
+ for(;;)
+ {
+ zs.next_out = luaL_prepbuffer(&b);
+ zs.avail_out = LUAL_BUFFERSIZE;
+
+ /* bake some more */
+ ret = inflate(&zs, Z_FINISH);
+
+ /* push gathered data */
+ luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out);
+
+ /* need dictionary? - no dictionary support here, so just quit */
+ if (ret == Z_NEED_DICT)
+ break;
+
+ /* done processing? */
+ if (ret == Z_STREAM_END)
+ break;
+
+ /* error condition? */
+ if (ret != Z_BUF_ERROR)
+ break;
+ }
+
+ /* cleanup */
+ inflateEnd(&zs);
+
+ luaL_pushresult(&b);
+ lua_pushnumber(L, ret);
+ return 2;
+}
+
+
+/*
+** =========================================================================
+** Register functions
+** =========================================================================
+*/
+
+
+LUALIB_API int luaopen_zlib(lua_State *L)
+{
+ const luaL_reg zstreamm[] =
+ {
+ {"reset", lzstream_reset },
+
+ {"compress", lzstream_compress },
+ {"decompress", lzstream_decompress },
+ {"flush", lzstream_flush },
+ {"close", lzstream_close },
+
+ {"adler", lzstream_adler },
+
+ {"__tostring", lzstream_tostring },
+ {"__gc", lzstream_gc },
+ {NULL, NULL}
+ };
+
+ const luaL_reg zlib[] =
+ {
+ {"version", lzlib_version },
+ {"adler32", lzlib_adler32 },
+ {"crc32", lzlib_crc32 },
+
+ {"compressobj", lzlib_deflate },
+ {"decompressobj", lzlib_inflate },
+
+ {"compress", lzlib_compress },
+ {"decompress", lzlib_decompress },
+
+ {NULL, NULL}
+ };
+
+ /* ====================================================================== */
+
+ /* make sure header and library version are consistent */
+ const char* version = zlibVersion();
+ if (strncmp(version, ZLIB_VERSION, 5))
+ {
+ lua_pushfstring(L, "zlib library version does not match - header: %s, library: %s", ZLIB_VERSION, version);
+ lua_error(L);
+ }
+
+ /* create new metatable for zlib compression structures */
+ luaL_newmetatable(L, ZSTREAMMETA);
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, -2); /* push metatable */
+ lua_rawset(L, -3); /* metatable.__index = metatable */
+
+ /*
+ ** Stack: metatable
+ */
+ luaL_openlib(L, NULL, zstreamm, 0);
+
+ lua_pop(L, 1); /* remove metatable from stack */
+
+ /*
+ ** Stack:
+ */
+ lua_newtable(L);
+ luaL_openlib(L, NULL, zlib, 0);
+
+ /*
+ ** Stack: zlib table
+ */
+ return 1;
+}
diff --git a/Build/source/libs/luazlib/test_gzip.lua b/Build/source/libs/luazlib/test_gzip.lua
new file mode 100644
index 00000000000..96041f11357
--- /dev/null
+++ b/Build/source/libs/luazlib/test_gzip.lua
@@ -0,0 +1,96 @@
+-- $Id: test_gzip.lua,v 1.2 2003/12/28 01:26:16 tngd Exp $
+
+local function line(header, c)
+ header = header or ''
+ c = c or '-'
+ print(string.rep(string.sub(c, 1, 1), 78 - string.len(header))..header)
+end
+
+
+line(' gzip', '=')
+
+line(' gzip writing')
+local loops = 1000
+local testfile = "test.gz"
+
+local of = gzip.open(testfile, "wb9")
+
+if (not of) then
+ error("Failed to open file test.gz for writing")
+end
+
+for i = 1, loops do
+ of:write(i, "\n")
+end
+
+of:close()
+
+local i = 0
+for l in gzip.lines(testfile) do
+ i = i + 1
+ if (tostring(i) ~= l) then
+ error(tostring(i))
+ end
+end
+
+assert(i == loops)
+print('Ok.')
+line(' gzip reading')
+
+local inf = gzip.open(testfile)
+
+if (not inf) then
+ error("Failed to open file test.gz for reading")
+end
+
+for i = 1, loops do
+ if (tostring(i) ~= inf:read("*l")) then
+ error(tostring(i))
+ end
+end
+
+inf:close()
+
+print('Ok.')
+line(' compress seek')
+
+of = gzip.open(testfile, "wb1")
+
+if (not of) then
+ error("Failed to open file test.gz for writing")
+end
+
+assert(of:seek("cur", 5) == 5)
+assert(of:seek("set", 10) == 10)
+
+of:write("1")
+
+of:close()
+
+print('Ok.')
+line(' uncompress seek')
+
+inf = gzip.open(testfile)
+
+if (not inf) then
+ error("Failed to open file test.gz for reading")
+end
+
+assert(inf:seek("set", 6) == 6)
+assert(inf:seek("set", 4) == 4)
+assert(inf:seek("cur", 1) == 5)
+assert(inf:seek("cur", -1) == 4)
+assert(inf:seek("cur", 1) == 5)
+assert(inf:seek("set", 6) == 6)
+
+inf:read(4)
+
+assert(inf:read(1) == "1")
+
+inf:close()
+
+os.remove(testfile)
+
+print('Ok.')
+
+line(' gzip', '=')
diff --git a/Build/source/libs/luazlib/test_zlib.lua b/Build/source/libs/luazlib/test_zlib.lua
new file mode 100644
index 00000000000..9368b6aef8e
--- /dev/null
+++ b/Build/source/libs/luazlib/test_zlib.lua
@@ -0,0 +1,106 @@
+-- $Id: test_zlib.lua,v 1.3 2004/07/22 19:10:47 tngd Exp $
+-- zlib = loadlib("./lzlib.so", "luaopen_zlib")()
+
+
+local function line(header, c)
+ header = header or ''
+ c = c or '-'
+ print(string.rep(string.sub(c, 1, 1), 78 - string.len(header))..header)
+end
+
+local function ipart(value)
+ return value - math.mod(value, 1)
+end
+
+local function bitvalues(value, bstart, num)
+ value = ipart(value / 2^bstart)
+ return math.mod(value, 2^num)
+end
+
+line(' zlib '..zlib.version(), '=')
+
+line(' adler32')
+local adler = zlib.adler32()
+print('adler32 init : '..adler)
+adler = zlib.adler32(adler, 'some text')
+print('updated adler: '..adler)
+adler = zlib.adler32(adler, 'some text')
+print('updated adler: '..adler)
+adler = zlib.adler32(adler, 'some text')
+print('updated adler: '..adler)
+adler = zlib.adler32(adler, 'some text')
+print('updated adler: '..adler)
+adler = zlib.adler32(adler, 'some text')
+print('updated adler: '..adler)
+adler = zlib.adler32(adler, 'some textd')
+print('updated adler: '..adler)
+
+line(' crc32')
+local crc = zlib.crc32()
+print('crc32 init : '..crc)
+crc = zlib.crc32(crc, 'some text')
+print('updated crc: '..crc)
+crc = zlib.crc32(crc, 'some text')
+print('updated crc: '..crc)
+crc = zlib.crc32(crc, 'some text')
+print('updated crc: '..crc)
+crc = zlib.crc32(crc, 'some text')
+print('updated crc: '..crc)
+crc = zlib.crc32(crc, 'some text')
+print('updated crc: '..crc)
+crc = zlib.crc32(crc, 'some textd')
+print('updated crc: '..crc)
+
+
+line(' deflate/inflate')
+local us
+f = io.open('lzlib.c') -- f = io.open('../all.tar')
+us = f:read('*a')
+f:close()
+
+do -- local block
+
+local f, cs, zd, zi, aux_res, res, ret, count
+
+print('file length : '..string.len(us))
+
+cs = ''
+zd = zlib.compressobj(1)
+print('deflate stream : '..tostring(zd))
+
+cs = cs .. zd:compress(string.sub(us, 1, string.len(us)/2))
+cs = cs .. zd:compress(string.sub(us, string.len(us)/2+1))
+cs = cs .. zd:flush()
+
+print('compressed length : '..string.len(cs))
+print('compressed adler : '..tostring(zd:adler()))
+zd:close()
+
+zi = zlib.decompressobj()
+print('inflate stream : '..tostring(zi))
+res = ''
+res = res .. zi:decompress(string.sub(cs, 1, 10))
+res = res .. zi:decompress(string.sub(cs, 11))
+res = res .. zi:flush()
+print('uncompressed length : '..string.len(res))
+print('uncompressed adler : '..tostring(zi:adler()))
+zi:close()
+print('result == uncompressed : '..tostring(res == us))
+print('compression ratio : '..tostring(string.len(us)/string.len(cs)))
+
+end -- local block
+collectgarbage()
+
+line(' compress/uncompress')
+do -- local block
+local cs, res
+print('file length : '..string.len(us))
+cs = zlib.compress(us,1)
+print('compressed length : '..string.len(cs))
+res = zlib.decompress(cs)
+print('compressed length : '..string.len(res))
+print('result == uncompressed : '..tostring(res == us))
+print('compression ratio : '..tostring(string.len(us)/string.len(cs)))
+end -- local block
+
+line(' zlib '..zlib.version(), '=')
diff --git a/Build/source/libs/luazlib/zlib.lua b/Build/source/libs/luazlib/zlib.lua
new file mode 100644
index 00000000000..d50db24fe79
--- /dev/null
+++ b/Build/source/libs/luazlib/zlib.lua
@@ -0,0 +1,105 @@
+--[[------------------------------------------------------------------------
+zlib.lua
+support code for zlib library version 1.2.1
+usage lua -lzlib ...
+
+Author: Tiago Dionizio (tngd@mega.ist.utl.pt)
+$Id: zlib.lua,v 1.3 2004/07/22 19:11:55 tngd Exp $
+--]]------------------------------------------------------------------------
+
+--[[ Exports ---------------------------------------------------------------
+
+ds = deflate stream
+is = inflate stream
+int = number (integer)
+* = (any type)
+
+[...] represent optional parameters that may be omited or nil, in wich case
+will be replaced by their default values
+
+-- zlib constants --
+
+int zlib.XXXX
+
+-- zlib functions --
+
+string zlib.version()
+int zlib.compile_flags()
+int zlib.adler32(int adler, string buf)
+int zlib.crc32(int crc, string buf)
+
+string zlib.compress(string buf [, int level] [, int method] [, int windowBits] [, int memLevel] [, int strategy])
+string zlib.uncompress(string buf [, int windowBits])
+
+ds zlib.deflate_init([int level] [, int method] [, int windowBits] [, int memLevel] [, int strategy])
+is zlib.inflate_init([int windowBits])
+
+-- deflate stream methods --
+
+int ds:adler()
+int ds:data_type()
+int ds:total_in()
+int ds:total_out()
+int, int df:process(string [, int flush])
+void ds:done()
+void ds:callback(function callback, * userdata)
+int ds:set_dictionary(string dictionary)
+ds [,int] ds:clone()
+int ds:reset()
+int ds:params(int level, int strategy)
+int ds:prime(int bits, int value)
+
+-- inflate stream methods --
+
+int is:adler()
+int is:data_type()
+int is:total_in()
+int is:total_out()
+int, int if:process(string [, int flush])
+void if:done()
+void is:callback([function callback] [, * userdata])
+void is:dictionary([function callback] [, * userdata])
+int is:set_dictionary(string dictionary)
+is [,int] is:clone()
+int is:reset()
+int, int is:sync(string buf)
+
+-- callbacks --
+void callback(string buf, * userdata)
+void dictionary(* userdata)
+
+-- general description --
+most functions/methods correspond to the original function in the zlib
+library, the main differences are:
+
+zlib.XXXX constants correspond to the Z_XXXX constants defined in the
+zlib library
+
+when (de)compressing blocks, the generated output is sent to the callback
+function, this is done to prevent passing too much meaningful result values
+from the process method
+
+deflate/inflate zlib functions are interfaced through the process method
+
+ds:params may invoke the output callback
+
+process method returns the error value and the number of input bytes
+processed
+
+clone method returns a copy of the stream (also copies callbacks) and
+returns a new stream object or nil plus an error code
+
+dictionary callback is not strictly necessary, but may avoid extra process
+calls if used, only needed when compressed stream also used a custom
+dictionary. when using it you must call is:set_dictionary as needed, if not
+you will have to watch the return code for zlib.
+
+is:sync returns an error code and the number of input bytes processed
+
+
+** for more information please refer to zlib.h **
+--]]------------------------------------------------------------------------
+
+require('requirelib')
+
+requirelib('lzlib', 'luaopen_zlib', true)
diff --git a/Build/source/libs/slnunicode/slnudata.c b/Build/source/libs/slnunicode/slnudata.c
new file mode 100644
index 00000000000..f98df22848c
--- /dev/null
+++ b/Build/source/libs/slnunicode/slnudata.c
@@ -0,0 +1,946 @@
+/* license.terms
+This software is copyrighted by the Regents of the University of
+California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
+Corporation and other parties. The following terms apply to all files
+associated with the software unless explicitly disclaimed in
+individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
+are acquiring the software on behalf of the Department of Defense, the
+software shall be classified as "Commercial Computer Software" and the
+Government shall have only "Restricted Rights" as defined in Clause
+252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
+authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license.
+*/
+/*
+ * tclUniData.c --
+ *
+ * Declarations of Unicode character information tables. This file is
+ * automatically generated by the tools/uniParse.tcl script. Do not
+ * modify this file by hand.
+ *
+ * Copyright (c) 1998 by Scriptics Corporation.
+ * All rights reserved.
+ *
+ * RCS: @(#) $Id: slnudata.c,v 1.1.1.1 2006/04/19 15:03:33 erik Exp $
+ */
+
+/*
+ * A 16-bit Unicode character is split into two parts in order to index
+ * into the following tables. The lower OFFSET_BITS comprise an offset
+ * into a page of characters. The upper bits comprise the page number.
+ */
+
+#define OFFSET_BITS 5
+
+/*
+ * The pageMap is indexed by page number and returns an alternate page number
+ * that identifies a unique page of characters. Many Unicode characters map
+ * to the same alternate page number.
+ */
+
+static unsigned char pageMap[] = {
+ 0, 1, 2, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, 15, 16, 17,
+ 18, 19, 20, 21, 22, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 7, 32,
+ 7, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 47,
+ 48, 49, 50, 51, 52, 35, 47, 53, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 58, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 80, 81,
+ 84, 85, 80, 86, 87, 88, 89, 90, 91, 92, 35, 93, 94, 95, 35, 96, 97,
+ 98, 99, 100, 101, 102, 35, 47, 103, 104, 35, 35, 105, 106, 107, 47,
+ 47, 108, 47, 47, 109, 47, 110, 111, 47, 112, 47, 113, 114, 115, 116,
+ 114, 47, 117, 118, 35, 47, 47, 119, 90, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 120, 121, 47, 47, 122,
+ 35, 35, 35, 35, 47, 123, 124, 125, 126, 47, 127, 128, 47, 129, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 7, 7, 7, 7, 130, 7, 7, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 150, 151, 152, 153, 154, 155, 156, 156, 156, 156, 156, 156, 156,
+ 157, 158, 159, 160, 161, 162, 35, 35, 35, 160, 163, 164, 165, 166,
+ 167, 168, 169, 160, 160, 160, 160, 170, 171, 172, 173, 174, 160, 160,
+ 175, 35, 35, 35, 35, 176, 177, 178, 179, 180, 181, 35, 35, 160, 160,
+ 160, 160, 160, 160, 160, 160, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 182, 160, 160, 155, 160, 160, 160, 160, 160, 160, 170, 183, 184, 185,
+ 90, 47, 186, 90, 47, 187, 188, 189, 47, 47, 190, 128, 35, 35, 191,
+ 192, 193, 194, 192, 195, 196, 197, 160, 160, 160, 198, 160, 160, 199,
+ 197, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 200, 35, 35, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 201, 35, 35, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 202, 203, 204, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 205, 35, 35, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
+ 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
+ 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
+ 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
+ 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 47, 47, 47, 47, 47, 47, 47, 47, 47, 208, 35, 35, 35, 35,
+ 35, 35, 209, 210, 211, 47, 47, 212, 213, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 214, 215, 47, 216, 47, 217, 218, 35, 219, 220, 221, 47,
+ 47, 47, 222, 223, 2, 224, 225, 226, 227, 228, 229, 230, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 231, 35, 232, 233,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 208, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 47, 234, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 235, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 236, 207, 207, 207, 207, 207, 207, 207, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35
+};
+
+/*
+ * The groupMap is indexed by combining the alternate page number with
+ * the page offset and returns a group number that identifies a unique
+ * set of character attributes.
+ */
+
+static unsigned char groupMap[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 4, 3, 3, 3, 5, 6, 3, 7, 3, 8,
+ 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 7, 7, 7, 3, 3, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 5, 3, 6, 11, 12, 11, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 5, 7, 6, 7, 1, 2, 3, 4, 4, 4, 4, 14, 14, 11, 14, 15, 16,
+ 7, 8, 14, 11, 14, 7, 17, 17, 11, 18, 14, 3, 11, 17, 15, 19, 17, 17,
+ 17, 3, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 7, 10, 10, 10, 10, 10, 10, 10, 15,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 7, 13, 13, 13, 13, 13, 13, 13, 20, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21,
+ 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 23, 24, 21, 22, 21,
+ 22, 21, 22, 15, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21,
+ 22, 21, 22, 15, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21,
+ 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 25,
+ 21, 22, 21, 22, 21, 22, 26, 15, 27, 21, 22, 21, 22, 28, 21, 22, 29,
+ 29, 21, 22, 15, 30, 31, 32, 21, 22, 29, 33, 34, 35, 36, 21, 22, 15,
+ 15, 35, 37, 15, 38, 21, 22, 21, 22, 21, 22, 39, 21, 22, 39, 15, 15,
+ 21, 22, 39, 21, 22, 40, 40, 21, 22, 21, 22, 41, 21, 22, 15, 42, 21,
+ 22, 15, 43, 42, 42, 42, 42, 44, 45, 46, 44, 45, 46, 44, 45, 46, 21,
+ 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 47, 21,
+ 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 15, 44, 45, 46, 21, 22, 48, 49, 21, 22, 21, 22, 21, 22, 21, 22, 0,
+ 0, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 50, 51, 15, 52, 52, 15, 53, 15,
+ 54, 15, 15, 15, 15, 52, 15, 15, 55, 15, 15, 15, 15, 56, 57, 15, 15,
+ 15, 15, 15, 57, 15, 15, 58, 15, 15, 59, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 60, 15, 15, 60, 15, 15, 15, 15, 60, 15, 61, 61, 15, 15,
+ 15, 15, 15, 15, 62, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 11, 11, 63, 63, 63, 63, 63, 63, 63,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 63, 63, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 63, 63, 63, 63,
+ 63, 11, 11, 11, 11, 11, 11, 11, 11, 11, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,
+ 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11,
+ 0, 0, 0, 0, 63, 0, 0, 0, 3, 0, 0, 0, 0, 0, 11, 11, 66, 3, 67, 67, 67,
+ 0, 68, 0, 69, 69, 15, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 70, 71,
+ 71, 71, 15, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 72, 13, 13, 13, 13, 13, 13, 13, 13, 13, 73, 74, 74, 0,
+ 75, 76, 77, 77, 77, 78, 79, 15, 0, 0, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 80, 81, 47,
+ 15, 82, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 84, 84, 84, 84, 84, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 21, 22, 14, 64, 64, 64, 64, 0, 85, 85, 0, 0, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21,
+ 22, 77, 21, 22, 21, 22, 0, 0, 21, 22, 0, 0, 21, 22, 0, 0, 0, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21,
+ 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 0, 0, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 0, 0, 63, 3, 3, 3, 3, 3, 3, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 15, 0, 3, 8, 0, 0,
+ 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 64, 64, 3, 64, 3, 64,
+ 64, 3, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 0, 0, 0, 0, 0, 42, 42, 42, 3, 3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 0, 0, 0, 0, 0, 63, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 0, 0, 64, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 3, 42, 64,
+ 64, 64, 64, 64, 64, 64, 85, 85, 64, 64, 64, 64, 64, 64, 63, 63, 64,
+ 64, 14, 64, 64, 64, 64, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 42, 42,
+ 42, 14, 14, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 88, 42,
+ 64, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,
+ 64, 89, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 0, 0, 64, 42, 89, 89, 89, 64, 64, 64, 64, 64, 64,
+ 64, 64, 89, 89, 89, 89, 64, 0, 0, 42, 64, 64, 64, 64, 0, 0, 0, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 64, 64, 3, 3, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,
+ 89, 89, 0, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 42, 42, 0, 0, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 0, 42, 0, 0, 0, 42,
+ 42, 42, 42, 0, 0, 64, 0, 89, 89, 89, 64, 64, 64, 64, 0, 0, 89, 89,
+ 0, 0, 89, 89, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, 42, 42,
+ 0, 42, 42, 42, 64, 64, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 42, 42,
+ 4, 4, 17, 17, 17, 17, 17, 17, 14, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 42,
+ 42, 42, 42, 42, 42, 0, 0, 0, 0, 42, 42, 0, 0, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0,
+ 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 0, 42, 42, 0, 42, 42, 0, 0,
+ 64, 0, 89, 89, 89, 64, 64, 0, 0, 0, 0, 64, 64, 0, 0, 64, 64, 64, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 0, 42, 0, 0, 0, 0, 0,
+ 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 64, 64, 42, 42, 42, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 64, 64, 89, 0, 42, 42, 42, 42, 42, 42, 42,
+ 0, 42, 0, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 42, 42,
+ 42, 42, 0, 42, 42, 0, 42, 42, 42, 42, 42, 0, 0, 64, 42, 89, 89, 89,
+ 64, 64, 64, 64, 64, 0, 64, 64, 89, 0, 89, 89, 64, 0, 0, 42, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 0, 42,
+ 42, 0, 0, 42, 42, 42, 42, 0, 0, 64, 42, 89, 64, 89, 64, 64, 64, 0,
+ 0, 0, 89, 89, 0, 0, 89, 89, 64, 0, 0, 0, 0, 0, 0, 0, 0, 64, 89, 0,
+ 0, 0, 0, 42, 42, 0, 42, 42, 42, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 89,
+ 0, 42, 42, 42, 42, 42, 42, 0, 0, 0, 42, 42, 42, 0, 42, 42, 42, 42,
+ 0, 0, 0, 42, 42, 0, 42, 0, 42, 42, 0, 0, 0, 42, 42, 0, 0, 0, 42, 42,
+ 42, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 0, 0, 0,
+ 0, 89, 89, 64, 89, 89, 0, 0, 0, 89, 89, 89, 0, 89, 89, 89, 64, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 89, 89, 89, 0, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42,
+ 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 0, 42, 42, 42, 42, 42, 0, 0, 0, 0, 64, 64, 64, 89, 89,
+ 89, 89, 0, 64, 64, 64, 0, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 64,
+ 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89,
+ 89, 0, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 0, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42,
+ 42, 42, 0, 0, 0, 0, 89, 64, 89, 89, 89, 89, 89, 0, 64, 89, 89, 0, 89,
+ 89, 64, 64, 0, 0, 0, 0, 0, 0, 0, 89, 89, 0, 0, 0, 0, 0, 0, 0, 42, 0,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 89, 89, 89, 64, 64,
+ 64, 0, 0, 89, 89, 89, 0, 89, 89, 89, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 89, 0, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 0, 0,
+ 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 64, 0, 0, 0, 0, 89, 89, 89, 64,
+ 64, 64, 0, 64, 0, 89, 89, 89, 89, 89, 89, 89, 89, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 89, 3, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 64, 42, 42, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0, 0, 4, 42, 42,
+ 42, 42, 42, 42, 63, 64, 64, 64, 64, 64, 64, 64, 64, 3, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 3, 3, 0, 0, 0, 0, 0, 42, 42, 0, 42, 0, 0, 42, 42,
+ 0, 42, 0, 0, 42, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 0, 42, 42, 42, 42,
+ 42, 42, 42, 0, 42, 42, 42, 0, 42, 0, 42, 0, 0, 42, 42, 0, 42, 42, 42,
+ 42, 64, 42, 42, 64, 64, 64, 64, 64, 64, 0, 64, 64, 42, 0, 0, 42, 42,
+ 42, 42, 42, 0, 63, 0, 64, 64, 64, 64, 64, 64, 0, 0, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 0, 0, 42, 42, 0, 0, 42, 14, 14, 14, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 14, 14, 14, 14, 14, 64, 64, 14, 14, 14,
+ 14, 14, 14, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 14, 64, 14, 64, 14, 64, 5, 6, 5, 6, 89, 89, 42, 42, 42,
+ 42, 42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 89, 64, 64, 64, 64, 64, 3, 64, 64, 42,
+ 42, 42, 42, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 0, 14, 14, 14, 14, 14, 14, 14, 14, 64, 14, 14, 14, 14, 14, 14, 0, 0,
+ 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 0, 42,
+ 42, 42, 42, 42, 0, 42, 42, 0, 89, 64, 64, 64, 64, 89, 64, 0, 0, 0,
+ 64, 64, 89, 64, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3,
+ 3, 3, 3, 3, 3, 42, 42, 42, 42, 42, 42, 89, 89, 64, 64, 0, 0, 0, 0,
+ 0, 0, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+ 77, 77, 77, 77, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0,
+ 0, 0, 0, 0, 42, 42, 42, 42, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 42, 42, 42,
+ 42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 0, 42, 0, 42, 42, 42, 42, 0, 0, 42, 42, 42, 42, 42, 42, 42,
+ 0, 42, 0, 42, 42, 42, 42, 0, 0, 42, 42, 42, 42, 42, 42, 42, 0, 42,
+ 0, 42, 42, 42, 42, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 0, 42, 0, 42, 42, 42, 42, 0, 0, 42, 42, 42, 42, 42, 42,
+ 42, 0, 42, 0, 42, 42, 42, 42, 0, 0, 42, 42, 42, 42, 42, 42, 42, 0,
+ 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3,
+ 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 3, 3, 42, 42, 42, 42, 42,
+ 42, 42, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 5, 6, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 3, 3, 3, 90, 90, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 89, 89, 89, 64, 64, 64, 64, 64, 64, 64, 89, 89, 89, 89, 89,
+ 89, 89, 89, 64, 89, 89, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 3, 3, 3, 3, 3, 3, 3, 4, 3, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3,
+ 3, 3, 3, 3, 8, 3, 3, 3, 3, 88, 88, 88, 88, 0, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 0, 0, 0, 0, 0, 0, 42, 42, 42, 63, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 0,
+ 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 22, 21, 22, 21, 22, 21,
+ 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 15, 15,
+ 15, 15, 15, 91, 0, 0, 0, 0, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 0,
+ 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93,
+ 93, 93, 93, 92, 92, 92, 92, 92, 92, 0, 0, 93, 93, 93, 93, 93, 93, 0,
+ 0, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93,
+ 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 92,
+ 92, 92, 92, 92, 92, 0, 0, 93, 93, 93, 93, 93, 93, 0, 0, 15, 92, 15,
+ 92, 15, 92, 15, 92, 0, 93, 0, 93, 0, 93, 0, 93, 92, 92, 92, 92, 92,
+ 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 94, 94, 95, 95, 95, 95,
+ 96, 96, 97, 97, 98, 98, 99, 99, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92,
+ 100, 100, 100, 100, 100, 100, 100, 100, 92, 92, 92, 92, 92, 92, 92,
+ 92, 100, 100, 100, 100, 100, 100, 100, 100, 92, 92, 92, 92, 92, 92,
+ 92, 92, 100, 100, 100, 100, 100, 100, 100, 100, 92, 92, 15, 101, 15,
+ 0, 15, 15, 93, 93, 102, 102, 103, 11, 104, 11, 11, 11, 15, 101, 15,
+ 0, 15, 15, 105, 105, 105, 105, 103, 11, 11, 11, 92, 92, 15, 15, 0,
+ 0, 15, 15, 93, 93, 106, 106, 0, 11, 11, 11, 92, 92, 15, 15, 15, 107,
+ 15, 15, 93, 93, 108, 108, 109, 11, 11, 11, 0, 0, 15, 101, 15, 0, 15,
+ 15, 110, 110, 111, 111, 103, 11, 11, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 88, 88, 88, 88, 8, 8, 8, 8, 8, 8, 3, 3, 16, 19, 5, 16, 16,
+ 19, 5, 16, 3, 3, 3, 3, 3, 3, 3, 3, 112, 113, 88, 88, 88, 88, 88, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 16, 19, 3, 3, 3, 3, 12, 12, 3, 3, 3, 7,
+ 5, 6, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 88, 88, 88, 88, 88, 17,
+ 0, 0, 0, 17, 17, 17, 17, 17, 17, 7, 7, 7, 5, 6, 15, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 7, 7, 7, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 85, 85, 85, 85, 64, 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 77,
+ 14, 14, 14, 14, 77, 14, 14, 15, 77, 77, 77, 15, 15, 77, 77, 77, 15,
+ 14, 77, 14, 14, 14, 77, 77, 77, 77, 77, 14, 14, 14, 14, 14, 14, 77,
+ 14, 114, 14, 77, 14, 115, 116, 77, 77, 14, 15, 77, 77, 14, 77, 15,
+ 42, 42, 42, 42, 15, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117,
+ 117, 117, 117, 117, 117, 118, 118, 118, 118, 118, 118, 118, 118, 118,
+ 118, 118, 118, 118, 118, 118, 118, 90, 90, 90, 90, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 7, 7, 14, 14,
+ 14, 14, 7, 14, 14, 7, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 7, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 14, 14, 7,
+ 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 7, 7, 14, 14, 14, 14, 14, 14, 14, 5, 6, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 7, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,
+ 14, 14, 14, 0, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 0, 14, 0, 14, 14, 14, 14, 0, 0, 0, 14, 0, 14, 14,
+ 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 14, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0,
+ 0, 0, 0, 2, 3, 3, 3, 14, 63, 42, 90, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6,
+ 14, 14, 5, 6, 5, 6, 5, 6, 5, 6, 8, 5, 6, 6, 14, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 64, 64, 64, 64, 64, 64, 8, 63, 63, 63, 63, 63, 14,
+ 14, 90, 90, 90, 0, 0, 0, 14, 14, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 64, 64,
+ 11, 11, 63, 63, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 12, 63,
+ 63, 63, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 14, 14, 17, 17, 17,
+ 17, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 0, 14, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 121, 121, 121, 121, 121, 121,
+ 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121,
+ 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,
+ 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 0,
+ 0, 0, 0, 0, 42, 64, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 7, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 42,
+ 42, 0, 42, 0, 42, 42, 0, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 64, 64, 64, 64,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 8, 8, 12, 12, 5, 6, 5, 6, 5,
+ 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 0, 0, 0, 0, 3, 3, 3, 3, 12, 12, 12,
+ 3, 3, 3, 0, 3, 3, 3, 3, 8, 5, 6, 5, 6, 5, 6, 3, 3, 3, 7, 8, 7, 7, 7,
+ 0, 3, 4, 3, 3, 0, 0, 0, 0, 42, 42, 42, 0, 42, 0, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 0, 0, 88, 0, 3, 3, 3, 4, 3, 3, 3, 5, 6, 3, 7, 3, 8, 3, 3, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 3, 3, 7, 7, 7, 3, 11, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 5, 7, 6, 7, 0, 0, 3, 5, 6, 3, 12, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 63, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 63,
+ 63, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0,
+ 42, 42, 42, 42, 42, 42, 0, 0, 42, 42, 42, 42, 42, 42, 0, 0, 42, 42,
+ 42, 42, 42, 42, 0, 0, 42, 42, 42, 0, 0, 0, 4, 4, 7, 11, 14, 4, 4, 0,
+ 14, 7, 7, 7, 7, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 88, 88, 14,
+ 14, 42, 17, 42, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 123, 123,
+ 126, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 89, 64, 14, 14, 14,
+ 14, 14, 0, 0, 77, 77, 15, 15, 77, 15, 15, 77, 77, 15, 77, 77, 15, 77,
+ 77, 15, 15, 77, 15, 15, 77, 77, 15, 77, 77, 15, 77, 77, 15, 15, 77,
+ 15, 15, 77, 77, 15, 77, 77, 15, 77, 77, 15, 15, 77, 77, 15, 15, 77,
+ 15, 15, 77, 77, 15, 15, 77, 15, 15, 77, 77, 15, 15, 9, 9, 9, 42, 42,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 88, 0, 88, 88, 88, 88, 88, 88, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122
+};
+
+/*
+ * Each group represents a unique set of character attributes. The attributes
+ * are encoded into a 32-bit value as follows:
+ *
+ * Bits 0-4 Character category: see the constants listed below.
+ *
+ * Bits 5-7 Case delta type: 000 = identity
+ * 010 = add delta for lower
+ * 011 = add delta for lower, add 1 for title
+ * 100 = sutract delta for title/upper
+ * 101 = sub delta for upper, sub 1 for title
+ * 110 = sub delta for upper, add delta for lower
+ *
+ * Bits 8-21 Reserved for future use.
+ *
+ * Bits 22-31 Case delta: delta for case conversions. This should be the
+ * highest field so we can easily sign extend.
+ */
+
+static int groups[] = {
+ 0, 15, 12, 25, 27, 21, 22, 26, 20, 9, 134217793, 28, 19, 134217858,
+ 29, 2, 23, 11, 1178599554, 24, -507510654, 4194369, 4194434, -834666431,
+ 973078658, -507510719, 1258291330, 880803905, 864026689, 859832385,
+ 331350081, 847249473, 851443777, 868220993, -406847358, 884998209,
+ 876609601, 893386817, 897581121, 914358337, 910164033, 918552641,
+ 5, -234880894, 8388705, 4194499, 8388770, 331350146, -406847423,
+ -234880959, 880803970, 864026754, 859832450, 847249538, 851443842,
+ 868221058, 876609666, 884998274, 893386882, 897581186, 914358402,
+ 910164098, 918552706, 4, 6, -352321402, 159383617, 155189313,
+ 268435521, 264241217, 159383682, 155189378, 130023554, 268435586,
+ 264241282, 260046978, 239075458, 1, 197132418, 226492546, 360710274,
+ 335544450, -251658175, 402653314, 335544385, 7, 201326657, 201326722,
+ 16, 8, 10, 247464066, -33554302, -33554367, -310378366, -360710014,
+ -419430270, -536870782, -469761918, -528482174, -33554365, -37748606,
+ -310378431, -37748669, 155189378, -360710079, -419430335, -29359998,
+ -469761983, -29360063, -536870847, -528482239, 13, 14, -1463812031,
+ -801111999, -293601215, 67108938, 67109002, 109051997, 109052061,
+ 18, 17, 8388673, 12582977, 8388738, 12583042
+};
+
+/*
+ * The following constants are used to determine the category of a
+ * Unicode character.
+ */
+
+#define UNICODE_CATEGORY_MASK 0X1F
+
+enum {
+ UNASSIGNED,
+ UPPERCASE_LETTER,
+ LOWERCASE_LETTER,
+ TITLECASE_LETTER,
+ MODIFIER_LETTER,
+ OTHER_LETTER,
+ NON_SPACING_MARK,
+ ENCLOSING_MARK,
+ COMBINING_SPACING_MARK,
+ DECIMAL_DIGIT_NUMBER,
+ LETTER_NUMBER,
+ OTHER_NUMBER,
+ SPACE_SEPARATOR,
+ LINE_SEPARATOR,
+ PARAGRAPH_SEPARATOR,
+ CONTROL,
+ FORMAT,
+ PRIVATE_USE,
+ SURROGATE,
+ CONNECTOR_PUNCTUATION,
+ DASH_PUNCTUATION,
+ OPEN_PUNCTUATION,
+ CLOSE_PUNCTUATION,
+ INITIAL_QUOTE_PUNCTUATION,
+ FINAL_QUOTE_PUNCTUATION,
+ OTHER_PUNCTUATION,
+ MATH_SYMBOL,
+ CURRENCY_SYMBOL,
+ MODIFIER_SYMBOL,
+ OTHER_SYMBOL
+};
+
+/*
+ * The following macros extract the fields of the character info. The
+ * GetDelta() macro is complicated because we can't rely on the C compiler
+ * to do sign extension on right shifts.
+ */
+
+#define GetCaseType(info) (((info) & 0xE0) >> 5)
+#define GetCategory(info) ((info) & 0x1F)
+#define GetDelta(info) (((info) > 0) ? ((info) >> 22) : (~(~((info)) >> 22)))
+
+/*
+ * This macro extracts the information about a character from the
+ * Unicode character tables.
+ */
+
+#define GetUniCharInfo(ch) (groups[groupMap[(pageMap[(((int)(ch)) & 0xffff) >> OFFSET_BITS] << OFFSET_BITS) | ((ch) & ((1 << OFFSET_BITS)-1))]])
+
diff --git a/Build/source/libs/slnunicode/slnunico.c b/Build/source/libs/slnunicode/slnunico.c
new file mode 100644
index 00000000000..c40c4f7b539
--- /dev/null
+++ b/Build/source/libs/slnunicode/slnunico.c
@@ -0,0 +1,1368 @@
+/*
+* Selene Unicode/UTF-8
+* This additions
+* Copyright (c) 2005 Malete Partner, Berlin, partner@malete.org
+* Available under "Lua 5.0 license", see http://www.lua.org/license.html#5
+* $Id: slnunico.c,v 1.5 2006/07/26 17:20:04 paul Exp $
+*
+* contains code from
+** lstrlib.c,v 1.109 2004/12/01 15:46:06 roberto Exp
+** Standard library for string operations and pattern-matching
+** See Copyright Notice in lua.h
+*
+* uses the udata table and a couple of expressions from Tcl 8.4.x UTF-8
+* which comes with the following license.terms:
+
+This software is copyrighted by the Regents of the University of
+California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
+Corporation and other parties. The following terms apply to all files
+associated with the software unless explicitly disclaimed in
+individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
+are acquiring the software on behalf of the Department of Defense, the
+software shall be classified as "Commercial Computer Software" and the
+Government shall have only "Restricted Rights" as defined in Clause
+252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
+authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license.
+
+(end of Tcl license terms)
+*/
+
+/*
+According to http://ietf.org/rfc/rfc3629.txt we support up to 4-byte
+(21 bit) sequences encoding the UTF-16 reachable 0-0x10FFFF.
+Any byte not part of a 2-4 byte sequence in that range decodes to itself.
+Ill formed (non-shortest) "C0 80" will be decoded as two code points C0 and 80,
+not code point 0; see security considerations in the RFC.
+However, UTF-16 surrogates (D800-DFFF) are accepted.
+
+See http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
+for default grapheme clusters.
+Lazy westerners we are (and lacking the Hangul_Syllable_Type data),
+we care for base char + Grapheme_Extend, but not for Hangul syllable sequences.
+
+For http://unicode.org/Public/UNIDATA/UCD.html#Grapheme_Extend
+we use Mn (NON_SPACING_MARK) + Me (ENCLOSING_MARK),
+ignoring the 18 mostly south asian Other_Grapheme_Extend (16 Mc, 2 Cf) from
+http://www.unicode.org/Public/UNIDATA/PropList.txt
+*/
+
+#include <ctype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lstrlib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+#ifndef SLN_UNICODENAME /* unless set it luaconf */
+# define SLN_UNICODENAME "unicode"
+#endif
+
+
+#include "slnudata.c"
+#define charinfo(c) (~0xFFFF&(c) ? 0 : GetUniCharInfo(c)) /* BMP only */
+#define charcat(c) (UNICODE_CATEGORY_MASK & charinfo(c))
+#define Grapheme_Extend(code) \
+ (1 & (((1<<NON_SPACING_MARK)|(1<<ENCLOSING_MARK)) >> charcat(code)))
+
+enum { /* operation modes */
+ MODE_ASCII, /* single byte 7bit */
+ MODE_LATIN, /* single byte 8859-1 */
+ MODE_UTF8, /* UTF-8 by code points */
+ MODE_GRAPH /* UTF-8 by grapheme clusters */
+#define MODE_MBYTE(mode) (~1&(mode))
+};
+
+
+/* macro to `unsign' a character */
+#define uchar(c) ((unsigned char)(c))
+
+typedef const unsigned char cuc; /* it's just toooo long :) */
+
+
+static void utf8_enco (luaL_Buffer *b, unsigned c)
+{
+ if (0x80 > c) {
+ luaL_addchar(b, c);
+ return;
+ }
+ if (0x800 > c)
+ luaL_addchar(b, 0xC0|(c>>6));
+ else {
+ if (0x10000 > c)
+ luaL_addchar(b, 0xE0|(c>>12));
+ else {
+ luaL_addchar(b, 0xF0|(c>>18));
+ luaL_addchar(b, 0x80|(0x3F&(c>>12)));
+ }
+ luaL_addchar(b, 0x80|(0x3F&(c>>6)));
+ }
+ luaL_addchar(b, 0x80|(0x3F&c));
+} /* utf8_enco */
+
+
+/* end must be > *pp */
+static unsigned utf8_deco (const char **pp, const char *end)
+{
+ register cuc *p = (cuc*)*pp, * const e = (cuc*)end;
+ unsigned first = *p, code;
+
+ *pp = (const char*)++p; /* eat one */
+ /* check ASCII, dangling cont., non-shortest or not continued */
+ if (0xC2 > first || e == p || 0x80 != (0xC0&*p)) return first;
+ code = 0x3F&*p++; /* save 1st cont. */
+ /* check 2 byte (5+6 = 11 bit) sequence up to 0x7FF */
+ if (0xE0 > first) { /* any >= C2 is valid */
+ code |= (0x1F&first)<<6;
+ goto seq;
+ }
+ if (e != p && 0x80 == (0xC0&*p)) { /* is continued */
+ code = code<<6 | (0x3F&*p++); /* save 2nd */
+ if (0xF0 > first) { /* 3 byte (4+6+6 = 16 bit) seq -- want 2nd cont. */
+ if ( 0xF800&(code |= (0x0F&first)<<12) /* >0x7FF: not non-shortest */
+ /* && 0xD800 != (0xD800 & code) -- nah, let surrogates pass */
+ )
+ goto seq;
+ } else if (e != p && 0x80 == (0xC0&*p) /* check 3rd */
+ /* catch 0xF4 < first and other out-of-bounds */
+ /* TH: add the 256 out-of-range glyphs in 'plane 18' */
+ && 0x110100 > (code = (0x0F&first)<<18 | code<<6 | (0x3F&*p++))
+ && 0xFFFF < code /* not a 16 bitty */
+ )
+ goto seq;
+ }
+ return first;
+seq:
+ *pp = (const char*)p;
+ return code;
+} /* utf8_deco */
+
+
+/* reverse decode before pp > start */
+static unsigned utf8_oced (const char **pp, const char *start)
+{
+ register cuc *p = (cuc*)*pp, * const s = (cuc*)start;
+ unsigned last = *--p, code;
+
+ *pp = (const char*)p; /* eat one */
+ /* check non-continuer or at the edge */
+ if (0x80 != (0xC0&last) || s == p) return last;
+ code = 0x3F&last; /* save last cont. */
+ if (0xC0 == (0xE0&*--p)) { /* preceeded by 2 byte seq starter */
+ if (0xC2 <= *p) { code |= (0x1F&*p)<<6; goto seq; }
+ } else if (0x80 == (0xC0&*p) && s<p) {
+ code |= (0x3F&*p)<<6;
+ if (0xE0 == (0xF0&*--p)) { /* 3 byte starter */
+ if (0xF800&(code |= (0x0F&*p)<<12)) goto seq;
+ } else if (0x80 == (0xC0&*p) && s<=--p /* valid 4 byte ? */
+ /* TH: add the 256 out-of-range glyphs in 'plane 18' */
+ && 0x110100 > (code |= (0x0F&*p)<<18 | (0x3F&p[1])<<12)
+ && 0xFFFF < code
+ )
+ goto seq;
+ }
+ return last;
+seq:
+ *pp = (const char*)p;
+ return code;
+} /* utf8_oced */
+
+
+/* skip over Grapheme_Extend codes */
+static void utf8_graphext (const char **pp, const char *end)
+{
+ const char *p = *pp;
+ for (; p < end; *pp=p) {
+ unsigned code = utf8_deco(&p, end);
+ if (!Grapheme_Extend(code)) break;
+ }
+} /* utf8_graphext */
+
+
+static int utf8_count (const char **pp, int bytes, int graph, int max)
+{
+ const char *const end = *pp+bytes;
+ int count = 0;
+ while (*pp < end && count != max) {
+ unsigned code = utf8_deco(pp, end);
+ count++;
+ if (!graph) continue;
+ if (Grapheme_Extend(code) && 1<count) count--; /* uncount */
+ }
+ if (graph && count == max) /* gather more extending */
+ utf8_graphext(pp, end);
+ return count;
+} /* utf8_count */
+
+
+
+static int unic_len (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+ int mode = lua_tointeger(L, lua_upvalueindex(1));
+ if (MODE_MBYTE(mode)) l = (size_t)utf8_count(&s, l, mode-2, -1);
+ lua_pushinteger(L, l);
+ return 1;
+}
+
+
+static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {
+ /* relative string position: negative means back from end */
+ return (pos>=0) ? pos : (ptrdiff_t)len+pos+1;
+}
+
+
+static int unic_sub (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l), *p, *e=s+l;
+ ptrdiff_t start = luaL_checkinteger(L, 2);
+ ptrdiff_t end = luaL_optinteger(L, 3, -1);
+ int mode = lua_tointeger(L, lua_upvalueindex(1));
+
+ if (MODE_MBYTE(mode)) { p=s; l = (size_t)utf8_count(&p, l, mode-2, -1); }
+ start = posrelat(start, l);
+ end = posrelat(end, l);
+ if (start < 1) start = 1;
+ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
+ if (start > end)
+ lua_pushliteral(L, "");
+ else {
+ l = end - --start; /* #units */
+ if (!(MODE_MBYTE(mode))) /* single byte */
+ s += start;
+ else {
+ if (start) utf8_count(&s, e-s, mode-2, start); /* skip */
+ p = s;
+ utf8_count(&p, e-p, mode-2, l);
+ l = p-s;
+ }
+ lua_pushlstring(L, s, l);
+ }
+ return 1;
+}
+
+
+static int str_reverse (lua_State *L) { /* TODO? whatfor? */
+ size_t l;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l), *p = s+l, *q;
+ int mode = lua_tointeger(L, lua_upvalueindex(1)), mb = MODE_MBYTE(mode);
+
+ luaL_buffinit(L, &b);
+ if (!mb)
+ while (s < p--) luaL_addchar(&b, *p);
+ else {
+ unsigned code;
+ while (s < p) {
+ q = p;
+ code = utf8_oced(&p, s);
+ if (MODE_GRAPH == mode)
+ while (Grapheme_Extend(code) && p>s) code = utf8_oced(&p, s);
+ luaL_addlstring(&b, p, q-p);
+ }
+ }
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+
+static int unic_lower (lua_State *L) {
+ size_t l;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l), * const e=s+l;
+ int mode = lua_tointeger(L, lua_upvalueindex(1)), mb = MODE_MBYTE(mode);
+ luaL_buffinit(L, &b);
+ while (s < e) {
+ unsigned c = mb ? utf8_deco(&s, e) : uchar(*s++);
+ int info = charinfo(c);
+ if (GetCaseType(info)&0x02 && (mode || !(0x80&c))) c += GetDelta(info);
+ if (mb) utf8_enco(&b, c); else luaL_addchar(&b, c);
+ }
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int unic_upper (lua_State *L) {
+ size_t l;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l), * const e=s+l;
+ int mode = lua_tointeger(L, lua_upvalueindex(1)), mb = MODE_MBYTE(mode);
+ luaL_buffinit(L, &b);
+ while (s < e) {
+ unsigned c = mb ? utf8_deco(&s, e) : uchar(*s++);
+ int info = charinfo(c);
+ if (GetCaseType(info)&0x04 && (mode || !(0x80&c))) c -= GetDelta(info);
+ if (mb) utf8_enco(&b, c); else luaL_addchar(&b, c);
+ }
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int str_rep (lua_State *L) {
+ size_t l;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l);
+ int n = luaL_checkint(L, 2);
+ luaL_buffinit(L, &b);
+ while (n-- > 0)
+ luaL_addlstring(&b, s, l);
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int unic_byte (lua_State *L) {
+ size_t l;
+ ptrdiff_t posi, pose;
+ const char *s = luaL_checklstring(L, 1, &l), *p, *e=s+l;
+ int n, mode = lua_tointeger(L, lua_upvalueindex(1)), mb = MODE_MBYTE(mode);
+
+ if (mb) { p=s; l = (size_t)utf8_count(&p, l, mode-2, -1); }
+ posi = posrelat(luaL_optinteger(L, 2, 1), l);
+ pose = posrelat(luaL_optinteger(L, 3, posi), l);
+ if (posi <= 0) posi = 1;
+ if ((size_t)pose > l) pose = l;
+ if (0 >= (n = pose - --posi)) return 0; /* empty interval */
+ if (!mb)
+ e = (s += posi) + n;
+ else {
+ if (posi) utf8_count(&s, e-s, mode-2, posi); /* skip */
+ p=s;
+ utf8_count(&p, e-s, mode-2, n);
+ e=p;
+ }
+ /* byte count is upper bound on #elements */
+ luaL_checkstack(L, e-s, "string slice too long");
+ for (n=0; s<e; n++)
+ lua_pushinteger(L, mb ? utf8_deco(&s, e) : uchar(*s++));
+ return n;
+}
+
+
+static int unic_char (lua_State *L) {
+ int i, n = lua_gettop(L); /* number of arguments */
+ int mode = lua_tointeger(L, lua_upvalueindex(1)), mb = MODE_MBYTE(mode);
+ /* TH: add the 256 out-of-range glyphs in 'plane 18' */
+ unsigned lim = mb ? 0x110100 : 0x100;
+
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ for (i=1; i<=n; i++) {
+ unsigned c = luaL_checkint(L, i);
+ luaL_argcheck(L, lim > c, i, "invalid value");
+ if (mb) utf8_enco(&b, c); else luaL_addchar(&b, c);
+ }
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int writer (lua_State *L, const void* b, size_t size, void* B) {
+ (void)L;
+ luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
+ return 0;
+}
+
+
+static int str_dump (lua_State *L) {
+ luaL_Buffer b;
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ lua_settop(L, 1);
+ luaL_buffinit(L,&b);
+ if (lua_dump(L, writer, &b) != 0)
+ luaL_error(L, "unable to dump given function");
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+
+/*
+** {======================================================
+** PATTERN MATCHING
+** =======================================================
+* find/gfind(_aux) -> match, push_captures
+* gsub -> match, add_s (-> push_captures)
+* push_captures, add_s -> push_onecapture
+* match ->
+* start/end_capture -> match,
+* match_capture, matchbalance, classend -> -,
+* min/max_expand -> match, singlematch
+* singlematch -> matchbracketclass, match_class,
+* matchbracketclass -> match_class -> -,
+*/
+
+
+#define CAP_UNFINISHED (-1)
+#define CAP_POSITION (-2)
+
+typedef struct MatchState {
+ const char *src_init; /* init of source string */
+ const char *src_end; /* end (`\0') of source string */
+ lua_State *L;
+ int level; /* total number of captures (finished or unfinished) */
+ int mode;
+ int mb;
+ struct {
+ const char *init;
+ ptrdiff_t len;
+ } capture[LUA_MAXCAPTURES];
+} MatchState;
+
+
+#define L_ESC '%'
+#define SPECIALS "^$*+?.([%-"
+
+
+static int check_capture (MatchState *ms, int l) {
+ l -= '1';
+ if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
+ return luaL_error(ms->L, "invalid capture index");
+ return l;
+}
+
+
+static int capture_to_close (MatchState *ms)
+{
+ int level = ms->level;
+ for (level--; level>=0; level--)
+ if (ms->capture[level].len == CAP_UNFINISHED) return level;
+ return luaL_error(ms->L, "invalid pattern capture");
+}
+
+
+static const char *classend (MatchState *ms, const char *p)
+{
+ switch (*p) {
+ case L_ESC:
+ if (!*++p) luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")");
+ break;
+ case '[':
+ /* if (*p == '^') p++; -- no effect */
+ do { /* look for a `]' */
+ if (!*p) luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");
+ if (L_ESC == *(p++) && *p) p++; /* skip escapes (e.g. `%]') */
+ } while (']' != *p);
+ break;
+ default:
+ if (!ms->mb) break;
+ utf8_deco(&p, p+4);
+ return p;
+ }
+ return p+1;
+} /* classend */
+
+
+/*
+ * The following macros are used for fast character category tests. The
+ * x_BITS values are shifted right by the category value to determine whether
+ * the given category is included in the set.
+ */
+
+#define LETTER_BITS ((1 << UPPERCASE_LETTER) | (1 << LOWERCASE_LETTER) \
+ | (1 << TITLECASE_LETTER) | (1 << MODIFIER_LETTER) | (1 << OTHER_LETTER))
+
+#define DIGIT_BITS (1 << DECIMAL_DIGIT_NUMBER)
+
+#define NUMBER_BITS (1 << DECIMAL_DIGIT_NUMBER) \
+ | (1 << LETTER_NUMBER) | (1 << OTHER_NUMBER)
+
+#define SPACE_BITS ((1 << SPACE_SEPARATOR) | (1 << LINE_SEPARATOR) \
+ | (1 << PARAGRAPH_SEPARATOR))
+
+#define CONNECTOR_BITS (1 << CONNECTOR_PUNCTUATION)
+
+#define PUNCT_BITS ((1 << CONNECTOR_PUNCTUATION) | \
+ (1 << DASH_PUNCTUATION) | (1 << OPEN_PUNCTUATION) | \
+ (1 << CLOSE_PUNCTUATION) | (1 << INITIAL_QUOTE_PUNCTUATION) | \
+ (1 << FINAL_QUOTE_PUNCTUATION) | (1 << OTHER_PUNCTUATION))
+
+
+/* character c matches class cl. undefined for cl not ascii */
+static int match_class (int c, int cl, int mode)
+{
+ int msk, res;
+
+ switch (0x20|cl /*tolower*/) {
+ case 'a' : msk = LETTER_BITS; break;
+ case 'c' : msk = 1<<CONTROL; break;
+ case 'x' : /* hexdigits */
+ if (0x40==(~0x3f&c)/*64-127*/ && 1&(0x7e/*a-f*/>>(0x1f&c))) goto matched;
+ case 'd' : msk = 1<<DECIMAL_DIGIT_NUMBER; mode=0;/* ASCII only */ break;
+ case 'l' : msk = 1<<LOWERCASE_LETTER; break;
+ case 'n' : msk = NUMBER_BITS; break; /* new */
+ case 'p' : msk = PUNCT_BITS; break;
+ case 's' :
+#define STDSPACE /* standard "space" controls 9-13 */ \
+ (1<<9/*TAB*/|1<<10/*LF*/|1<<11/*VT*/|1<<12/*FF*/|1<<13/*CR*/)
+ if (!(~0x1f & c) && 1&(STDSPACE >> c)) goto matched;
+ msk = SPACE_BITS;
+ break;
+ case 'u' : msk = 1<<UPPERCASE_LETTER; break;
+ /*
+ this is not compatible to lua 5.1, where %w is just a letter or a digit
+ case 'w' : msk = LETTER_BITS|NUMBER_BITS|CONNECTOR_BITS; break;
+ */
+ case 'w' : msk = LETTER_BITS|NUMBER_BITS; break;
+ case 'z' : if (!c) goto matched; msk = 0; break;
+ default: return cl == c;
+ }
+ res = 1 & (msk >> charcat(c));
+ if (!mode && 0x80&c) res = 0;
+ if (0) {
+matched:
+ res = 1;
+ }
+ return 0x20&cl /*islower*/ ? res : !res;
+} /* match_class */
+
+
+/* decode single byte or UTF-8 seq; advance *s */
+static unsigned deco (const MatchState *ms, const char **s, const char *e)
+{
+ return ms->mb ? utf8_deco(s, e) : *(unsigned char*)(*s)++;
+}
+
+/* s must be < ms->src_end, p < ep */
+static const char *singlematch (const MatchState *ms,
+ const char *s, const char *p, const char *ep)
+{
+ int neg = 0;
+ unsigned c1, c2;
+ unsigned c;
+#ifdef OPTIMIZE_SIZE
+ c = deco(ms, &s, ms->src_end);
+#else
+ if (!ms->mb || !(0x80&*s))
+ c = *(unsigned char*)s++;
+ else
+ c = utf8_deco(&s, ms->src_end);
+#endif
+
+ switch (*p) {
+ case L_ESC:
+ if (match_class(c, uchar(p[1]), ms->mode)) {
+ case '.': /* the all class */
+#ifndef OPTIMIZE_SIZE
+ if (MODE_GRAPH != ms->mode) return s; /* common fast path */
+#endif
+ goto matched_class;
+ }
+ s = 0;
+ break;
+ default:
+#ifdef OPTIMIZE_SIZE
+ c1 = deco(ms, &p, ep);
+#else
+ if (!ms->mb || !(0x80&*p))
+ c1 = *(unsigned char*)p++;
+ else
+ c1 = utf8_deco(&p, ep);
+#endif
+ if (c != c1) s = 0;
+ break;
+ case '[': /* matchbracketclass */
+ ep--; /* now on the ']' */
+ if ((neg = '^' == *++p)) p++; /* skip the `^' */
+ while (p < ep) {
+ if (*p == L_ESC) {
+ if (match_class(c, uchar(*++p), ms->mode)) goto matched_class_in_brack;
+ p++;
+ continue;
+ }
+ c1 = deco(ms, &p, ep);
+ /* in lua-5.1 and 5.1.1 a trailing '-' is allowed
+ dynasm.lua relies on this
+ */
+ if ( ep <= p + 1 || '-' != *p ) {
+ const char *op = p, *es;
+ if (MODE_GRAPH == ms->mode) utf8_graphext(&p, ep);
+ if (c != c1) continue;
+ if (MODE_GRAPH != ms->mode) goto matched;
+ /* comp grapheme extension */
+ es = s;
+ utf8_graphext(&es, ms->src_end);
+ if (es-s == p-op && (es==s || !memcmp(s, op, es-s))) goto matched;
+ continue;
+
+ }
+ ++p;
+ /* range c1-c2 -- no extend support in range bounds... */
+ /* if (ep == ++p) break; see above */ /* bugger - trailing dash */
+ c2 = deco(ms, &p, ep);
+ if (c2 < c1) { unsigned swap=c1; c1=c2; c2=swap; }
+ if (c1 <= c && c <= c2) goto matched_class_in_brack; /* ...but extend match */
+ }
+ /* not matched */
+ neg = !neg;
+ matched:
+ if (neg) s = 0;
+ /* matchbracketclass */
+ }
+ return s;
+matched_class_in_brack: /* matched %something or range in [] */
+ if (neg)
+ s = 0;
+ else {
+matched_class: /* matched %something or . */
+ if (MODE_GRAPH == ms->mode) utf8_graphext(&s, ms->src_end);
+ }
+ return s;
+}
+
+
+static const char *match (MatchState *ms, const char *s, const char *p);
+
+
+static const char *matchbalance (MatchState *ms, const char *s,
+ const char *p) {
+ if (*p == 0 || *(p+1) == 0)
+ luaL_error(ms->L, "unbalanced pattern");
+ if (*s != *p) return NULL;
+ else {
+ int b = *p;
+ int e = *(p+1);
+ int cont = 1;
+ while (++s < ms->src_end) {
+ if (*s == e) {
+ if (--cont == 0) return s+1;
+ }
+ else if (*s == b) cont++;
+ }
+ }
+ return NULL; /* string ends out of balance */
+}
+
+
+static const char *max_expand (MatchState *ms,
+ const char *s, const char *p, const char *ep)
+{
+ const char *sp = s, *es;
+ while (sp<ms->src_end && (es = singlematch(ms, sp, p, ep)))
+ sp = es;
+ /* keeps trying to match with the maximum repetitions */
+ while (sp>=s) {
+ const char *res = match(ms, sp, ep+1);
+ if (res || sp==s) return res;
+ if (!ms->mb)
+ sp--; /* else didn't match; reduce 1 repetition to try again */
+ else {
+ unsigned code = utf8_oced(&sp, s);
+ if (MODE_GRAPH == ms->mode)
+ while (Grapheme_Extend(code) && sp>s) code = utf8_oced(&sp, s);
+ }
+ }
+ return NULL;
+}
+
+
+static const char *min_expand (MatchState *ms,
+ const char *s, const char *p, const char *ep)
+{
+ do {
+ const char *res = match(ms, s, ep+1);
+ if (res) return res;
+ if (s >= ms->src_end) break;
+ } while ((s = singlematch(ms, s, p, ep))); /* try with one more repetition */
+ return NULL;
+}
+
+
+static const char *start_capture (MatchState *ms, const char *s,
+ const char *p, int what) {
+ const char *res;
+ int level = ms->level;
+ if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");
+ ms->capture[level].init = s;
+ ms->capture[level].len = what;
+ ms->level = level+1;
+ if ((res=match(ms, s, p)) == NULL) /* match failed? */
+ ms->level--; /* undo capture */
+ return res;
+}
+
+
+static const char *end_capture (MatchState *ms, const char *s,
+ const char *p) {
+ int l = capture_to_close(ms);
+ const char *res;
+ ms->capture[l].len = s - ms->capture[l].init; /* close capture */
+ if ((res = match(ms, s, p)) == NULL) /* match failed? */
+ ms->capture[l].len = CAP_UNFINISHED; /* undo capture */
+ return res;
+}
+
+
+static const char *match_capture (MatchState *ms, const char *s, int l) {
+ size_t len;
+ l = check_capture(ms, l);
+ len = ms->capture[l].len;
+ if ((size_t)(ms->src_end-s) >= len &&
+ memcmp(ms->capture[l].init, s, len) == 0)
+ return s+len;
+ else return NULL;
+}
+
+
+static const char *match (MatchState *ms, const char *s, const char *p) {
+ init: /* using goto's to optimize tail recursion */
+ switch (*p) {
+ case '(': { /* start capture */
+ if (*(p+1) == ')') /* position capture? */
+ return start_capture(ms, s, p+2, CAP_POSITION);
+ else
+ return start_capture(ms, s, p+1, CAP_UNFINISHED);
+ }
+ case ')': { /* end capture */
+ return end_capture(ms, s, p+1);
+ }
+ case L_ESC: {
+ switch (*(p+1)) {
+ case 'b': { /* balanced string? */
+ s = matchbalance(ms, s, p+2);
+ if (s == NULL) return NULL;
+ p+=4; goto init; /* else return match(ms, s, p+4); */
+ }
+#if 0 /* TODO */
+ case 'f': { /* frontier? */
+ const char *ep; char previous;
+ p += 2;
+ if (*p != '[')
+ luaL_error(ms->L, "missing " LUA_QL("[") " after "
+ LUA_QL("%%f") " in pattern" );
+ luaL_error(ms->L, "missing `[' after `%%f' in pattern");
+ ep = classend(ms, p); /* points to what is next */
+ /* with UTF-8, getting the previous is more complicated */
+ previous = (s == ms->src_init) ? '\0' : *(s-1);
+ /* use singlematch to apply all necessary magic */
+ if (singlematch(uchar(previous), p, ep-1) ||
+ !singlematch(uchar(*s), p, ep-1)) return NULL;
+ p=ep; goto init; /* else return match(ms, s, ep); */
+ }
+#endif
+ default: {
+ if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */
+ s = match_capture(ms, s, uchar(*(p+1)));
+ if (s == NULL) return NULL;
+ p+=2; goto init; /* else return match(ms, s, p+2) */
+ }
+ goto dflt; /* case default */
+ }
+ }
+ }
+ case '\0': { /* end of pattern */
+ return s; /* match succeeded */
+ }
+ case '$': {
+ if (*(p+1) == '\0') /* is the `$' the last char in pattern? */
+ return (s == ms->src_end) ? s : NULL; /* check end of string */
+ else goto dflt; /* ??? */
+ }
+ default: dflt: { /* it is a pattern item */
+ const char *ep = classend(ms, p); /* points to what is next */
+ const char *es = 0;
+ if (s < ms->src_end) es = singlematch(ms, s, p, ep);
+ switch (*ep) {
+ case '?': { /* optional */
+ const char *res;
+ if (es && (res=match(ms, es, ep+1))) return res;
+ p=ep+1; goto init; /* else return match(ms, s, ep+1); */
+ }
+ case '*': { /* 0 or more repetitions */
+ return max_expand(ms, s, p, ep);
+ }
+ case '+': { /* 1 or more repetitions */
+ return (es ? max_expand(ms, es, p, ep) : NULL);
+ }
+ case '-': { /* 0 or more repetitions (minimum) */
+ return min_expand(ms, s, p, ep);
+ }
+ default: {
+ if (!es) return NULL;
+ s=es; p=ep; goto init; /* else return match(ms, s+1, ep); */
+ }
+ }
+ }
+ }
+}
+
+
+
+static const char *lmemfind (const char *s1, size_t l1,
+ const char *s2, size_t l2) {
+ if (l2 == 0) return s1; /* empty strings are everywhere */
+ else if (l2 > l1) return NULL; /* avoids a negative `l1' */
+ else {
+ const char *init; /* to search for a `*s2' inside `s1' */
+ l2--; /* 1st char will be checked by `memchr' */
+ l1 = l1-l2; /* `s2' cannot be found after that */
+ while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
+ init++; /* 1st char is already checked */
+ if (memcmp(init, s2+1, l2) == 0)
+ return init-1;
+ else { /* correct `l1' and `s1' to try again */
+ l1 -= init-s1;
+ s1 = init;
+ }
+ }
+ return NULL; /* not found */
+ }
+}
+
+
+static void push_onecapture (MatchState *ms, int i, const char *s,
+ const char *e )
+{
+ if (i >= ms->level) {
+ if (i == 0) /* ms->level == 0, too */
+ lua_pushlstring(ms->L, s, e - s); /* add whole match */
+ else
+ luaL_error(ms->L, "invalid capture index");
+ }
+ else {
+ ptrdiff_t l = ms->capture[i].len;
+ if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
+ if (l == CAP_POSITION)
+ lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);
+ else
+ lua_pushlstring(ms->L, ms->capture[i].init, l);
+ }
+}
+
+
+static int push_captures (MatchState *ms, const char *s, const char *e) {
+ int i;
+ int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
+ luaL_checkstack(ms->L, nlevels, "too many captures");
+ for ( i = 0; i < nlevels; i++ )
+ push_onecapture( ms, i, s, e );
+ return nlevels; /* number of strings pushed */
+}
+
+
+static int unic_find_aux (lua_State *L, int find) {
+ size_t l1, l2;
+ const char *s = luaL_checklstring(L, 1, &l1);
+ const char *p = luaL_checklstring(L, 2, &l2);
+ ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
+ if (init < 0) init = 0;
+ else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;
+ if (find && (lua_toboolean(L, 4) || /* explicit request? */
+ strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */
+ /* do a plain search */
+ const char *s2 = lmemfind(s+init, l1-init, p, l2);
+ if (s2) {
+ lua_pushinteger(L, s2-s+1);
+ lua_pushinteger(L, s2-s+l2);
+ return 2;
+ }
+ }
+ else {
+ MatchState ms;
+ int anchor = (*p == '^') ? (p++, 1) : 0;
+ const char *s1=s+init;
+ ms.L = L;
+ ms.src_init = s;
+ ms.src_end = s+l1;
+ ms.mode = lua_tointeger(L, lua_upvalueindex(1));
+ ms.mb = MODE_MBYTE(ms.mode);
+ do {
+ const char *res;
+ ms.level = 0;
+ if ((res=match(&ms, s1, p)) != NULL) {
+ if (find) {
+ lua_pushinteger(L, s1-s+1); /* start */
+ lua_pushinteger(L, res-s); /* end */
+ return push_captures(&ms, NULL, 0) + 2;
+ } else
+ return push_captures(&ms, s1, res);
+ }
+ } while (s1++ < ms.src_end && !anchor);
+ }
+ lua_pushnil(L); /* not found */
+ return 1;
+}
+
+static int unic_find (lua_State *L) {
+ return unic_find_aux(L, 1);
+}
+
+
+static int unic_match (lua_State *L) {
+ return unic_find_aux(L, 0);
+}
+
+
+
+static int gmatch_aux (lua_State *L) {
+ MatchState ms;
+ size_t ls;
+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
+ const char *p = lua_tostring(L, lua_upvalueindex(2));
+ const char *src;
+ ms.L = L;
+ ms.src_init = s;
+ ms.src_end = s+ls;
+ for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
+ src <= ms.src_end;
+ src++)
+ {
+ const char *e;
+ ms.level = 0;
+ if ((e = match(&ms, src, p)) != NULL) {
+ lua_Integer newstart = e-s;
+ if (e == src) newstart++; /* empty match? go at least one position */
+ lua_pushinteger(L, newstart);
+ lua_replace(L, lua_upvalueindex(3));
+ return push_captures(&ms, src, e);
+ }
+ }
+ return 0; /* not found */
+}
+
+
+
+static int gmatch (lua_State *L) {
+ luaL_checkstring(L, 1);
+ luaL_checkstring(L, 2);
+ lua_settop(L, 2);
+ lua_pushinteger(L, 0);
+ lua_pushcclosure(L, gmatch_aux, 3);
+ return 1;
+}
+
+static int gfind_nodef (lua_State *L) {
+ return luaL_error(L, LUA_QL("string.gfind") " was renamed to "
+ LUA_QL("string.gmatch"));
+}
+
+
+static void add_s (MatchState *ms, luaL_Buffer *b,
+ const char *s, const char *e)
+{
+ size_t l, i;
+ const char *news = lua_tolstring(ms->L, 3, &l);
+ for (i = 0; i < l; i++) {
+ if (news[i] != L_ESC)
+ luaL_addchar(b, news[i]);
+ else {
+ i++; /* skip ESC */
+ if (!isdigit(uchar(news[i])))
+ luaL_addchar(b, news[i]);
+ else if (news[i] == '0')
+ luaL_addlstring(b, s, e - s);
+ else {
+ push_onecapture(ms, news[i] - '1', s, e);
+ luaL_addvalue(b); /* add capture to accumulated result */
+ }
+ }
+ }
+}
+
+static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
+ const char *e)
+{
+ lua_State *L = ms->L;
+ switch (lua_type(L, 3)) {
+ case LUA_TNUMBER:
+ case LUA_TSTRING: {
+ add_s(ms, b, s, e);
+ return;
+ }
+ case LUA_TFUNCTION: {
+ int n;
+ lua_pushvalue(L, 3);
+ n = push_captures(ms, s, e);
+ lua_call(L, n, 1);
+ break;
+ }
+ case LUA_TTABLE: {
+ push_onecapture(ms, 0, s, e);
+ lua_gettable(L, 3);
+ break;
+ }
+ default: {
+ luaL_argerror(L, 3, "string/function/table expected");
+ return;
+ }
+ }
+ if (!lua_toboolean(L, -1)) { /* nil or false? */
+ lua_pop(L, 1);
+ lua_pushlstring(L, s, e - s); /* keep original text */
+ }
+ else if (!lua_isstring(L, -1))
+ luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
+ luaL_addvalue(b); /* add result to accumulator */
+}
+
+static int unic_gsub (lua_State *L) {
+ size_t srcl;
+ const char *src = luaL_checklstring(L, 1, &srcl);
+ const char *p = luaL_checkstring(L, 2);
+ int max_s = luaL_optint(L, 4, srcl+1);
+ int anchor = (*p == '^') ? (p++, 1) : 0;
+ int n = 0;
+ MatchState ms;
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ ms.L = L;
+ ms.src_init = src;
+ ms.src_end = src+srcl;
+ ms.mode = lua_tointeger(L, lua_upvalueindex(1));
+ ms.mb = MODE_MBYTE(ms.mode);
+ while (n < max_s) {
+ const char *e;
+ ms.level = 0;
+ e = match(&ms, src, p);
+ if (e) {
+ n++;
+ add_value(&ms, &b, src, e);
+ }
+ if (e && e>src) /* non empty match? */
+ src = e; /* skip it */
+ else if (src < ms.src_end)
+ luaL_addchar(&b, *src++);
+ else break;
+ if (anchor) break;
+ }
+ luaL_addlstring(&b, src, ms.src_end-src);
+ luaL_pushresult(&b);
+ lua_pushinteger(L, n); /* number of substitutions */
+ return 2;
+}
+
+/* }====================================================== */
+
+
+/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
+#define MAX_ITEM 512
+/* valid flags in a format specification */
+#define FLAGS "-+ #0"
+/*
+** maximum size of each format specification (such as '%-099.99d')
+** (+10 accounts for %99.99x plus margin of error)
+*/
+#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
+
+
+static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
+ size_t l;
+ const char *s = luaL_checklstring(L, arg, &l);
+ luaL_addchar(b, '"');
+ while (l--) {
+ switch (*s) {
+ case '"': case '\\': case '\n': {
+ luaL_addchar(b, '\\');
+ luaL_addchar(b, *s);
+ break;
+ }
+ case '\r': {
+ luaL_addlstring(b, "\\r", 2);
+ break;
+ }
+ case '\0': {
+ luaL_addlstring(b, "\\000", 4);
+ break;
+ }
+ default: {
+ luaL_addchar(b, *s);
+ break;
+ }
+ }
+ s++;
+ }
+ luaL_addchar(b, '"');
+}
+
+
+static const char *scanformat (lua_State *L, const char *strfrmt, char *form,
+ int *hasprecision)
+{
+ const char *p = strfrmt;
+ while (strchr(FLAGS, *p)) p++; /* skip flags */
+ if ((size_t)(p - strfrmt) >= sizeof(FLAGS))
+ luaL_error(L, "invalid format (repeated flags)");
+ if (isdigit(uchar(*p))) p++; /* skip width */
+ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
+ if (*p == '.') {
+ p++;
+ *hasprecision = 1;
+ if (isdigit(uchar(*p))) p++; /* skip precision */
+ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
+ }
+ if (isdigit(uchar(*p)))
+ luaL_error(L, "invalid format (width or precision too long)");
+ form[0] = L_ESC;
+ strncpy(form+1, strfrmt, p-strfrmt+1);
+ form[p-strfrmt+2] = 0;
+ return p;
+}
+
+static void addintlen (char *form) {
+ size_t l = strlen(form);
+ char spec = form[l - 1];
+ strcpy(form + l - 1, LUA_INTFRMLEN);
+ form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
+ form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
+}
+
+static int str_format (lua_State *L) {
+ int arg = 1;
+ size_t sfl;
+ const char *strfrmt = luaL_checklstring(L, arg, &sfl);
+ const char *strfrmt_end = strfrmt+sfl;
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ while (strfrmt < strfrmt_end) {
+ if (*strfrmt != L_ESC)
+ luaL_addchar(&b, *strfrmt++);
+ else if (*++strfrmt == L_ESC)
+ luaL_addchar(&b, *strfrmt++); /* %% */
+ else { /* format item */
+ char form[MAX_FORMAT]; /* to store the format (`%...') */
+ char buff[MAX_ITEM]; /* to store the formatted item */
+ int hasprecision = 0;
+ arg++;
+ strfrmt = scanformat(L, strfrmt, form, &hasprecision);
+ switch (*strfrmt++) {
+ case 'c': {
+#ifdef LUA_USE_SNPRINTF
+ snprintf( buff, MAX_ITEM, form,
+ (int) luaL_checknumber( L, arg ) );
+#else
+ sprintf(buff, form, (int) luaL_checknumber( L, arg ) );
+#endif
+ break;
+ }
+ case 'd': case 'i': {
+ addintlen( form );
+#ifdef LUA_USE_SNPRINTF
+ snprintf( buff, MAX_ITEM, form,
+ (LUA_INTFRM_T) luaL_checknumber(L, arg) );
+#else
+ sprintf(buff, form,
+ (LUA_INTFRM_T) luaL_checknumber(L, arg) );
+#endif
+ break;
+ }
+ case 'o': case 'u': case 'x': case 'X': {
+ addintlen( form );
+#ifdef LUA_USE_SNPRINTF
+ snprintf(buff, MAX_ITEM, form,
+ (unsigned LUA_INTFRM_T) luaL_checknumber(L, arg) );
+#else
+ sprintf(buff, form,
+ (unsigned LUA_INTFRM_T) luaL_checknumber(L, arg) );
+#endif
+ break;
+ }
+ case 'e': case 'E': case 'f':
+ case 'g': case 'G': {
+#ifndef LUA_NUMBER_DOUBLE
+ luaL_argerror( L, 1, "double formatting not supported" );
+#else
+# ifdef __dietlibc__
+# warning "double formatting is broken in dietlibc"
+# endif
+# ifdef LUA_USE_SNPRINTF
+ snprintf(buff, MAX_ITEM, form,
+ (double) luaL_checknumber(L, arg) );
+# else
+ sprintf(buff, form, (double) luaL_checknumber(L, arg) );
+# endif
+#endif
+ break;
+ }
+ case 'q': {
+ addquoted(L, &b, arg);
+ continue; /* skip the `addsize' at the end */
+ }
+ case 's': {
+ size_t l;
+ const char *s = luaL_checklstring(L, arg, &l);
+ if (!hasprecision && l >= 100) {
+ /* no precision and string is too long to be formatted;
+ keep original string */
+ lua_pushvalue(L, arg);
+ luaL_addvalue(&b);
+ continue; /* skip the `addsize' at the end */
+ }
+ else {
+#ifdef LUA_USE_SNPRINTF
+ snprintf(buff, MAX_ITEM, form, s);
+#else
+ sprintf(buff, form, s);
+#endif
+ break;
+ }
+ }
+ default: { /* also treat cases `pnLlh' */
+ return luaL_error(L, "invalid option " LUA_QL("%%%c") " to "
+ LUA_QL("format"), *(strfrmt - 1));
+ }
+ }
+ luaL_addlstring(&b, buff, strlen(buff));
+ }
+ }
+ luaL_pushresult(&b);
+ return 1;
+}
+
+#ifdef WANT_EXT_MATCH
+static struct { const char *k; int v; } unicflags[] = {
+ { "ASCII", MODE_ASCII }
+ ,{ "LATIN", MODE_LATIN }
+ ,{ "UTF8", MODE_UTF8 }
+ ,{ "GRAPH", MODE_GRAPH }
+};
+#define unicflags_sz ( sizeof( unicflags ) / sizeof( unicflags[0] ) )
+
+/*
+ allow direkt match calls from c
+*/
+int ext_uni_match ( void *state, const char *s, size_t n,
+ const char *p, int init, int mode )
+{
+ lua_State *L = state;
+ MatchState ms;
+ int anchor = (*p == '^') ? (p++, 1) : 0;
+ const char *s1;
+ int i = posrelat( init, n ) - 1;
+ if (i < 0) i = 0;
+ else if ((size_t)(i) > n) i = (ptrdiff_t)n;
+ s1 = s + i;
+ ms.L = L;
+ ms.src_init = s;
+ ms.src_end = s + n;
+ ms.mode = mode;
+ ms.mb = MODE_MBYTE(mode);
+ do {
+ const char *res;
+ ms.level = 0;
+ if ( ( res=match(&ms, s1, p)) != NULL )
+ return 1;
+ } while ( s1++ < ms.src_end && !anchor );
+ return 0;
+}
+#endif
+
+static const luaL_reg uniclib[] = {
+ {"byte", unic_byte}, /* no cluster ! */
+ {"char", unic_char},
+ {"dump", str_dump},
+ {"find", unic_find}, /* cluster */
+ {"format", str_format},
+ {"gfind", gfind_nodef},
+ {"gmatch", gmatch}, /* cluster */
+ {"gsub", unic_gsub}, /* cluster */
+ {"len", unic_len}, /* cluster/byte opt. */
+ {"lower", unic_lower},
+ {"match", unic_match}, /* cluster */
+ {"rep", str_rep},
+ {"reverse", str_reverse},
+ {"sub", unic_sub}, /* cluster/byte opt. */
+ {"upper", unic_upper},
+ {NULL, NULL}
+};
+
+#if defined( SLNUNICODE_AS_STRING ) && defined( STRING_WITH_METAT )
+static void createmetatable (lua_State *L) {
+ lua_newtable(L); /* create metatable for strings */
+ lua_pushliteral(L, ""); /* dummy string */
+ lua_pushvalue(L, -2);
+ lua_setmetatable(L, -2); /* set string metatable */
+ lua_pop(L, 1); /* pop dummy string */
+ lua_pushvalue(L, -2); /* string library... */
+ lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */
+ lua_pop(L, 1); /* pop metatable */
+}
+#endif
+
+/*
+** Open string library
+*/
+LUALIB_API int luaopen_unicode (lua_State *L) {
+ /* register unicode itself so require("unicode") works */
+ luaL_register(L, SLN_UNICODENAME,
+ uniclib + (sizeof uniclib/sizeof uniclib[0] - 1)); /* empty func list */
+ lua_pop(L, 1);
+ lua_pushinteger(L, MODE_ASCII);
+ luaI_openlib(L, SLN_UNICODENAME ".ascii", uniclib, 1);
+#ifdef SLNUNICODE_AS_STRING
+#if defined(LUA_COMPAT_GFIND)
+ lua_getfield(L, -1, "gmatch");
+ lua_setfield(L, -2, "gfind");
+#endif
+#ifdef STRING_WITH_METAT
+ createmetatable(L);
+#endif
+ lua_setfield(L, LUA_GLOBALSINDEX, "string");
+#endif
+ lua_pushinteger(L, MODE_LATIN);
+ luaI_openlib(L, SLN_UNICODENAME ".latin1", uniclib, 1);
+ lua_pushinteger(L, MODE_GRAPH);
+ luaI_openlib(L, SLN_UNICODENAME ".grapheme", uniclib, 1);
+ lua_pushinteger(L, MODE_UTF8);
+ luaI_openlib(L, SLN_UNICODENAME ".utf8", uniclib, 1);
+#ifdef WANT_EXT_MATCH
+ {
+ unsigned i;
+ const char *ln = SLN_UNICODENAME ".mode";
+ luaL_findtable( L, LUA_REGISTRYINDEX, "_LOADED", 1 );
+ lua_getfield( L, -1, ln );
+ if ( !lua_istable(L, -1 ) ) {
+ lua_pop( L, 1 );
+ if ( luaL_findtable( L, LUA_GLOBALSINDEX, ln, unicflags_sz ) )
+ luaL_error( L, "name conflict for module " LUA_QS, ln );
+ lua_pushvalue( L, -1 );
+ lua_setfield( L, -3, ln );
+ }
+ lua_remove( L, -2 );
+ for( i = 0; unicflags_sz > i; ++i ) {
+ lua_pushnumber( L, unicflags[i].v );
+ lua_setfield( L, -2, unicflags[i].k );
+ }
+ }
+#endif
+ return 1;
+}
+
diff --git a/Build/source/libs/slnunicode/unitest b/Build/source/libs/slnunicode/unitest
new file mode 100755
index 00000000000..5473e08636b
--- /dev/null
+++ b/Build/source/libs/slnunicode/unitest
@@ -0,0 +1,215 @@
+#!/opt/lua-5.0.2/bin/lua
+-- there are four string-like ctype closures:
+-- unicode.ascii, latin1, utf8 and grapheme
+--
+-- ascii and latin1 are single-byte like string,
+-- but use the unicode table for upper/lower and character classes
+-- ascii does not touch bytes > 127 on upper/lower
+--
+-- ascii or latin1 can be used as locale-independent string replacement.
+-- (There is a compile switch to do this automatically for ascii).
+--
+-- UTF-8 operates on UTF-8 sequences as of RFC 3629:
+-- 1 byte 0-7F, 2 byte 80-7FF, 3 byte 800-FFFF, 4 byte 1000-10FFFF
+-- (not exclusing UTF-16 surrogate characters)
+-- Any byte not part of such a sequence is treated as it's (Latin-1) value.
+--
+-- Grapheme takes care of grapheme clusters, which are characters followed by
+-- "grapheme extension" characters (Mn+Me) like combining diacritical marks.
+--
+-- calls are:
+-- len(str)
+-- sub(str, start [,end=-1])
+-- byte(str, start [,end=-1])
+-- lower(str)
+-- upper(str)
+-- char(i [,j...])
+-- reverse(str)
+--
+-- same as in string: rep, format, dump
+-- TODO: use char count with %s in format? (sub does the job)
+-- TODO: grapheme.byte: only first code of any cluster?
+--
+-- find, gfind, gsub: done, but need thorough testing ...:
+-- ascii does not match them on any %class (but on ., literals and ranges)
+-- behaviour of %class with class not ASCII is undefined
+-- frontier %f currently disabled -- should we?
+--
+-- character classes are:
+-- %a L* (Lu+Ll+Lt+Lm+Lo)
+-- %c Cc
+-- %d 0-9
+-- %l Ll
+-- %n N* (Nd+Nl+No, new)
+-- %p P* (Pc+Pd+Ps+Pe+Pi+Pf+Po)
+-- %s Z* (Zs+Zl+Zp) plus the controls 9-13 (HT,LF,VT,FF,CR)
+-- %u Lu (also Lt ?)
+-- %w %a+%n+Pc (e.g. '_')
+-- %x 0-9A-Za-z
+-- %z the 0 byte
+-- c.f. http://unicode.org/Public/UNIDATA/UCD.html#General_Category_Values
+-- http://unicode.org/Public/UNIDATA/UnicodeData.txt
+--
+-- NOTE: find positions are in bytes for all ctypes!
+-- use ascii.sub to cut found ranges!
+-- this is a) faster b) more reliable
+--
+-- UTF-8 behaviour: match is by codes, code ranges are supported
+--
+-- grapheme behaviour: any %class, '.' and range match includes
+-- any following grapheme extensions.
+-- Ranges apply to single code points only.
+-- If a [] enumeration contains a grapheme cluster,
+-- this matches only the exact same cluster.
+-- However, a literal single 'o' standalone or in an [] enumeration
+-- will match just that 'o', even if it has a extension in the string.
+-- Consequently, grapheme match positions are not always cluster positions.
+--
+
+local unicode = require("unicode")
+local utf8 = unicode.utf8
+unicode.string = string -- for tests unicode[ctype]
+local sprintf = string.format
+local function printf (fmt, ...) return print(sprintf(fmt, ...)) end
+
+local function check (test, ok, got)
+ if ok == got then return printf("ok %s = %s",test,ok) end
+ return printf("NOK %s = %s GOT '%s'",test, ok, got or "<nil>")
+end
+local function checka (test, ok, ...)
+ local arg = {...}
+ arg[1] = arg[1] or ""
+ return check(test, ok, table.concat(arg, ","))
+end
+
+
+local function testlen (str,bytes,codes,chars)
+ codes = codes or bytes
+ chars = chars or codes
+ return check(sprintf("len '%s'", str),
+ sprintf("%d/%d/%d", bytes, codes, chars),
+sprintf("%d/%d/%d", string.len(str), utf8.len(str), unicode.grapheme.len(str)))
+end
+
+-- 176 = 00B0;DEGREE SIGN -- UTF-8: C2,B0 = \194\176
+-- 196 = 00C4;LATIN CAPITAL LETTER A WITH DIAERESIS
+-- 214 = 00D6;LATIN CAPITAL LETTER O WITH DIAERESIS
+-- 776 = 0308;COMBINING DIAERESIS -- UTF-8: CC,88 = \204\136
+testlen("A\tB",3) -- plain Latin-1
+testlen("\176\196\214",3) -- plain Latin-1
+testlen("\196\176\214",3,2) -- C4,B0 is valid seq 0130 I WITH DOT ABOVE
+testlen("\192\178",2) -- C0,B2 is bad seq for 2
+testlen("°ÄÖ",6,3) -- simple Latin-1 chars in UTF-8
+testlen("\204\136A\204\136O\204\136",8,5,3) -- decomposed (with broken lead)
+
+
+local function testsub (ctype,ok,str,start,e)
+ return check(sprintf("%s.sub('%s',%d,%d)", ctype, str, start, e), ok,
+ unicode[ctype].sub(str,start,e))
+end
+testsub("ascii","BCD","ABCDE",2,4)
+testsub("utf8","BCD","ABCDE",2,4)
+testsub("latin1","Ä","°ÄÖ",3,4)
+testsub("utf8","Ä","°ÄÖ",2,2)
+testsub("utf8","ÄÖ","°ÄÖ",2,-1)
+testsub("utf8","\204\136","A\204\136O\204\136",2,2) -- decomposed
+testsub("grapheme","O\204\136","A\204\136O\204\136",2,2) -- decomposed
+
+
+local function testbyte (ctype, ok, str, ...)
+ return checka(sprintf("%s.byte('%s',%s)",ctype,str,table.concat({...}, ",")),
+ ok, unicode[ctype].byte(str, ...))
+end
+testbyte("string","194,176","Ä°Ö",3,4) -- the UTF-8 seq for °
+testbyte("ascii","194,176","Ä°Ö",3,4)
+testbyte("utf8","176,214","Ä°Ö",2,3) -- code points for °,Ö
+testbyte("utf8","65,776","\204\136A\204\136O\204\136",2,3) -- decomposed
+testbyte("grapheme","65,776","\204\136A\204\136O\204\136",2) -- decomposed
+
+
+local function testchar (ctype, ok, ...)
+ return check(sprintf("%s.char(%s)",ctype,table.concat({...}, ",")),
+ ok, unicode[ctype].char(...))
+end
+testchar("ascii", "AB", 65,66)
+testchar("ascii", "\176", 176)
+testchar("utf8", "\194\176", 176)
+
+
+local function testcase (ctype,str,up,lo)
+ check(sprintf("%s.lower('%s')", ctype, str), lo, unicode[ctype].lower(str))
+ check(sprintf("%s.upper('%s')", ctype, str), up, unicode[ctype].upper(str))
+end
+-- upper/lower also fixes plain Latin
+testcase("utf8","Ab\196üo\204\136","ABÄÜO\204\136","abäüo\204\136")
+testcase("ascii","Ab\196üo\204\136","AB\196üO\204\136","ab\196üo\204\136")
+testcase("latin1","Ab\196","AB\196","ab\228")
+
+
+local function testrev (ctype,ok,str)
+ return check(sprintf("%s.reverse('%s')",ctype,str),
+ ok, unicode[ctype].reverse(str))
+end
+testrev("ascii","b\136\204oa\176\194ba","ab°ao\204\136b");
+testrev("utf8","b\204\136oa°ba","ab°ao\204\136b");
+testrev("grapheme","bo\204\136a°ba","ab°ao\204\136b");
+
+
+
+local function testfind (ctype,ok,str,pat)
+ return checka(sprintf("%s.find('%s','%s')",ctype,str,pat),
+ ok, unicode[ctype].find(str, pat))
+end
+testfind("ascii","1,1","e=mc2","%a")
+testfind("ascii","3,4","e=mc2","%a%a")
+testfind("ascii","5,5","e=mc2","%d")
+testfind("ascii","","Ä","%a")
+testfind("ascii","1,2","Ä","%A*")
+testfind("latin1","1,1","Ä","%a")
+testfind("utf8","1,2","Ä","%a")
+testfind("utf8","1,1","o\204\136","%a*")
+testfind("utf8","2,3","o\204\136","%A")
+testfind("utf8","1,1","o\204\136",".")
+testfind("grapheme","1,3","o\204\136","%a*")
+testfind("grapheme","2,3","o\204\136","%A") -- didn't expect this?
+testfind("grapheme","1,3","o\204\136",".")
+testfind("utf8","4,5","ÜHÄPPY","[À-Ö]")
+testfind("utf8","4,5","ÜHÄPPY","[Ä-]")
+testfind("utf8","7,7","ÜHÄP-PY","[ä-]")
+testfind("ascii","1,4","abcdef","%a*d")
+testfind("utf8","1,10","äöüßü","%a*ü")
+testfind("utf8","1,6","äöüß","%a*ü")
+testfind("utf8","4,5,Ä","ÜHÄPPY","([À-Ö])")
+testfind("utf8","1,5,ÜHÄ","ÜHÄ_PPY","([%w]+)")
+testfind("utf8","1,9,ÜHÄ_PPY","ÜHÄ_PPY","([%w_]+)")
+
+
+local function testgsub (ctype,ok,str,pat,repl)
+ return check(sprintf("%s.gsub('%s','%s','%s')",ctype,str,pat,repl),
+ ok, unicode[ctype].gsub(str,pat,repl))
+end
+testgsub("ascii","hello hello world world","hello world", "(%w+)", "%1 %1")
+testgsub("ascii","world hello Lua from",
+ "hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
+testgsub("ascii","l helö wöfr rldöL müä",
+ "hellö wörld fröm Lüä", "(%w+)%s*(%w+)", "%2 %1")
+testgsub("utf8","wörld hellö Lüä fröm",
+ "hellö wörld fröm Lüä", "(%w+)%s*(%w+)", "%2 %1")
+testgsub("utf8","HÜppÄ","HÄppÜ","([À-Ö])(%l*)(%u)","%3%2%1")
+
+
+fail = 0
+for i=0,65535 do if i ~= utf8.byte(utf8.char(i)) then fail=fail+1 end end
+check("code-decode failures", 0, fail)
+
+--[[ print the table
+for i=192,65535,64 do
+ local k = i/64
+ io.write(sprintf("%04x\\%3d\\%3d ",i, 224+k/64, 128+math.mod(k,64)))
+ for j=i,i+63 do
+ io.write(utf8.char(j))
+ end
+ io.write("\n")
+end
+]]
+
diff --git a/Build/source/libs/zziplib/COPYING.LIB b/Build/source/libs/zziplib/COPYING.LIB
new file mode 100644
index 00000000000..eb685a5ec98
--- /dev/null
+++ b/Build/source/libs/zziplib/COPYING.LIB
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/Build/source/libs/zziplib/ChangeLog b/Build/source/libs/zziplib/ChangeLog
new file mode 100644
index 00000000000..bf2e62b35cf
--- /dev/null
+++ b/Build/source/libs/zziplib/ChangeLog
@@ -0,0 +1,1194 @@
+2006-08-08
+ * rephrase build system, automated tests, some doc parts
+
+2006-04-28
+ * bsd/mac needs sys/types.h for size_t
+
+2005-12-11
+ * there have been reports about multithreading problems
+ * one source of problems: access to the dir->cache members.
+ fixed by using an explicit semaphore variable, otherwise
+ just allocate/deallocate the buffer / filehandle
+ * second source of problems: the zip file is opened _and_ read
+ with only one filehandle for multiple threads that
+ share the same "dir" handle. Look for "->currentfp".
+ * that is not fixed away - while access to the cache variables
+ can continue in the case of a "locked" state that is not
+ possible for open/reads. In the "locked" case the thread
+ must be blocked but that is a system-specific call.
+ * there are two ways to fix it - (a) push down the sysfile to
+ each zzip_file by "dup(2)"licating the sysfile handle.
+ However zzip looses a feature that was helping a lot on
+ system with a low number of sysfile hands (e.g. dos and
+ some embedded operating systems that I did work with).
+ and (b) provide an indirect ->lock() call that can be
+ filled by the caller application upon zzip invokation,
+ perhaps add it to the io-plugin structure. Well (c) is
+ it possible to support both styles? Dynamically?
+
+2005-12-10
+ * testing on sourceforge compilefarm - including "make check"
+ * there was an error on bsd'ish systems (implicit 64on32)
+ which was caused by archaic CORRECT_ROOTSEEK code
+ being still present. Remove it?
+
+2005-12-09
+ * testing with Microsoft Visual Studio 2005 (msvc8) Express Edition
+ * fixing some compilation problems related to zip64 support in win32
+
+2005-12-08
+ * cut acinclude.m4 into seperated aclocal macros in m4/ subdirectory
+
+2005-10-14
+ * testing on sourceforge compilefarm, cleaning away any compiler warnings
+ i386-debian2.2 i386-freebsd4.8
+ amd64-fedora3 alpha-debian3.0
+ sparc-solaris8 powerpc-macos10.2
+ * note, the build system has some quirks but not yet renovated to the
+ newest autoconf/automake stuff anyway - TBD before final release
+
+2005-10-13
+ * MSVC7 knows the following __declspec attributes:
+ align(#), allocate("seg"), deprecated, dllexport, dllimport,
+ naked{for asm}, noinline, noreturn, nothrow, novtable,
+ property{MngC++}, selectany{common}, thread{tls}, uuid("name")
+ * introduce zzip__new__ for a restrict'ed return item
+ * introduce zzip_byte_t to help silence down compiler warnings
+ about signedness mismatch in assigning data buffer variables.
+ Especially the zlib data_in happens to be of unsigned char type.
+ * note that zzip/format.h does now use zzip_byte_t for layout definition
+
+2005-02-17
+ * adding that _GNU_SOURCE on __linux__ to get the strndup prototype
+ * cleaning a few warning messages on different platforms as well
+ as a bug for 64bit platforms
+ * updating docs/mksite.sh and adding docs/mksite.pl and going to
+ let VERSION be pasted directly instead of a makefile snippet
+ * adding docs/memdisk.htm documentation to the series which is
+ currently quite shallow.
+ * note: no tests for actual zip64 support are made, neither for a
+ large central directory (more than 64K files) nor for large
+ files (more than 2GB). This is all theoretic but I am quite
+ confident that it will work.
+
+2005-02-16
+ * change zzip/zip disk_trailer implementation
+ * we do not anymore pass a copy of the file block around
+ * we do use a local helper structure now with off_t fields
+ * the parse_root_directory is now using off_t for all computatations
+ * make check succeeds - beware, this is a new implementation
+ * RANT: glibc bastards make for additinal warning messages, the fseeko
+ prototype is not exported by default, but as soon as we add some
+ define to make it available, some other prototypes are disabled,
+ including one of the most widespread: strndup(). The documentation
+ even says we have to say GNU to get prototype - if you have ever heard
+ of unix to diverge into something not quite but be alike, here it is,
+ what compiles on most platforms gives a warning on linux even that it
+ works fine afterwards because the libc does export all we need and
+ autoconf does find it - it is just not prototyped and that's all.
+
+2005-02-15
+ * adding zzip/memdisk.* as cache variant for libzzipfseeko
+ * add macro support for zip64 extensions
+ * extend trailer routines with zip64 detection (and return 0)
+ * add memdisk bins
+
+2005-01-04
+ * remember TODO multithreading tests and hardening the code.
+ http://www.idefense.com/application/poi/display?id=153&type=vulnerabilities
+
+2004-12-27
+ * updating to latest autoconf/automake/libtool stuff in Suse92
+ * required a rewrite of ax_enable_builddir.m4 in ac-archive
+ * adding two macros to silence down bogus depracation warnings
+ from the latest gcc 3.3.5
+
+2004-11-27
+ * harveyandsu:yahoo:com reported an api mismatch for SDL rwops
+ usage and the implementation in the SDL_rwops_zzip example.
+ *
+
+2004-05-11
+ * documenting zzip-cryptoid handling
+ * update mksite.sh
+
+2004-05-09
+ * documenting zzipmmapped and zzipfseeko parser libraries
+
+2004-05-08
+ * remove bogus zzip_file_open_ext_io from zzip.h
+ * change to use mksite.sh for documentation builds
+
+2004-03-08
+ * add link in docs/history.htm to the new appnote.txt whitepaper
+ on zip file format specification.
+
+2004-02-19
+ * a test run on solaris did show that fetch.* needs to be linked
+ to the new lib*.la stuff - to convert endianess-dependent
+ values from zip to main memory
+ * there seems to be an automake problem with hpux10 that I can not
+ yet define on what grounds it is - to get away with it I am
+ not defining automake 1.7 as the version to be used, plus
+ autoconf 2.57 - these are pretty new.
+
+2004-01-24
+ * zzip/fseeko.c and bins/zzip.c had some issued with non-C99 compilers
+ which do not like variable declarations in the middle of a block
+
+2004-01-16
+ * zzip_rewind again - the deflateReset does not reset the
+ input buffer variables (oops) so we have to do it
+ explicitly. Here we adopt to set crestlen to full
+ csize and the current z-buffer fillstate avail_in
+ to null to trigger a new read() on next zzip_read.
+ * the zlib headers do not tell whether next_in/avail_in
+ is used in deflateReset as is done in deflateInit.
+ A question to zlib@gzip.org brought no answer (as
+ is always the case) and after some thinking I did
+ decide to reset avail_in *after* the zReset call.
+ * based on this decision, I have made up a patch and I was
+ sending it over to zlib@gzip.org. Same consequence
+ again, the message is bluntly ignored (while there is
+ traffic on zlib devel mailinglist). There seems to be
+ a major problem about it, either a technical problem
+ (mail-adress disfunctional) or a social problem (no
+ one cares or perhaps some minor racism).
+
+2003-12-29
+ * added libzzipfseeko.la with another simplified interface
+ * rename the other one to libzzipmmapped.la
+ * fix bugs for decompression on the latter as well
+ it seems the one has to use inflateInit2 (..., -MAX_WBITS)
+ * added bins/unzzipshow for an example binary
+ * added "--help" and "--version" to all bins examples
+
+2003-12-24
+ * added libzzipmmap.la with a simplified interface to zip archives
+ * added bins unzzipdir and unzzipcat to show usage of libzzipmmap.la
+ * introduce zzip/types.h to allow easier inclusion to zzip/mmapped.*
+
+2003-12-22
+ * add AC_C_BIGENDIAN and
+ * move out ZZIP_GET to zzip/fetch.h where we also specify access
+ wrappers to items in the zzip/format.h structures, portably.
+ * add byteswap.h ac_check and put a new file autoconf.h to carry
+ compiletime overrides for the autoconf definitions.
+ * start changing over to use zzip/fetch.h definitions everywhere
+ thereby replacing original ZZIP_GET16/32 usages completely.
+ This is localized to zzip/zip.c
+ * rename struct zzip_root_dirent to struct zzip_disk_entry but
+ retain a compatibility declaration.
+ * introduce zzip_version_t and zzip_dostime_t along with an optional
+ ZZIP_NEED_PACKED def that helps with weird compiler struct packing
+ * struct zzip_file_trailer did not use the char[x] variant, it does now
+ * place even more zzip/fetch.h declarations
+ * place even more defs into zzip/format.h
+ * noting CVS area on webpages
+
+2003-12-21
+ * Nigel Stewart hints on some MSVC 6 issues, thanks.
+
+2003-12-20
+ * implant *Reset instead of Deinit/Init in zzip_rewind - the latter
+ is supposed to make for a memory leak (see problem report).
+
+2003-12-10
+ * add zzip_rewind fix by glenn = Glenn Maynard (www.stepmania.com)
+ * fix dirsep_casecmp buglet noted by glenn
+ * glenn did ask for zzip_fstat, and here it is.
+ * but glenn's file_dup is not as easy and skipped here.
+ * otherwise, glenn noted that zziplib is not fully ready for multithreading,
+ the reason seems to be mostly in the reshared 32k buffer where the
+ access is not synchronized completely :-( ... effectivly, in MT
+ all ZZIP_FILE*s need to have a dedicated ZZIP_DIR*buffer.
+ * update make-doc.py with newest version
+
+2003-08-18
+ * changing license to dual MPL / LGPL
+ * bumping version code 12.83 = 13.23 which are actually the very
+ same inside the code
+ * remove a few compatibility headers at install time.
+ * add install-exec-hook to add ln -s aliases for sharedlibs
+ they are being tried again in .spec but that does not
+ matter as long as it is "|| true"
+ * adapt all source to carry the MPL alternative license
+ instead of the old cruft.
+ * remove staticlinking.txt - it should be covered by copying.htm now
+ * remove "compats" disthook as well as the complete subdirectory
+ i.e. rm -r "zziplib/" at top directory (actually, I store it
+ in a distant place for now.)
+ * remove _htmpages.ar and _manpages.are from dist tarball
+ * add toplevel COPYING.LIB
+ * adapt README and TODO
+ * remove ac_output(zziplib and bins/zzip-config)
+ * remove bins/zzip-config.in
+ * adapt m4 macro and call zzip-config to be archaic
+ * remove maintainer-mode for "test.zip"
+ * turn zzip_plugin_io_t into a union reference, the old struct is
+ still of the same name but a member in there called "fd"
+ the typedef is no a "union _zzip_plugin_io" instead.
+ * the member "use_mmap" is renamed to "sys" - we add a #define
+ in plugin.h to let some software compile with all versions
+ * in zzip/zip.c, try now with making maplen and pagesize of type
+ zzip_ssize_t - as it was newly introduce it might help and
+ perhaps be a little conservative in execution. Before that,
+ we did use size_t and it was provoking warnings like
+ comparing/computing signed+unsigned pairs of values.
+ * add "type" and "write" members to zzip_plugin_io, keep it
+ backward compatible as much as possible.
+ * add _zzip_write to zzip/conf.h
+ * remove ZZIP_WRAPWRAP code in plugin.c
+ * remove --with-wrapwrap
+ * introduce a #define _zzip_plugin_io_handlers and
+ typedefs zzip_plugin_io_handlers and zzip_plugin_io_handlers_t
+ * oops toplevel PHONY does not work, an automake restriction
+ * oops, "cat body.htm" should be "cat $(srcdir)/body.htm"
+ * adding manpages.ar again, just to be sure
+
+2003-08-14
+ * remove _not_implemend macro definitions for shallow-write api
+ from header zzip.h
+ * introduce symbol _ZZIP_WRITE_SOURCE that all files should
+ carry that want to have the declarations of the
+ shallow-write api
+ * use that symbol for zzip/write.c and bins/zzip.c
+ * adding docs/64on32.htm
+
+2003-08-14
+ * for the shallow-write api to compile on win32, we need to
+ test for direct.h which only exists on win'sh system
+ or so we assume
+ * add bins/unzzip
+ * add bins/zzip
+ * ooops, zzip_strerror_of should check dir != 0
+
+2003-08-13
+ * complete zip-write API - no actual implementation so far
+ * tested shallow-write implementation on solaris+linux+win32
+ * and now, call it zzip-12 always
+
+2003-08-12
+ * `make docs` does not always work, so we add `make docu` now
+ * update make-doc.py
+ * fix call for make-doc.py
+ * fix zzip_get16 bad refer that gets detected by make-doc.py
+
+
+2003-08-07
+ * implement zzip/write to a degree that it forwards calls to real
+ files and directories in the system. No zip archives here,
+ but the accession API has been setup so that applications
+ can start to pick it up even for versions of zziplib that
+ have been compiled without zip archive support.
+
+2003-08-07
+ * add doc lines in zzip/zzip.h
+ * add write-defines including flag-marker ZZIP_NO_CREAT
+ * add file write.c with empty definitions for write-support
+ * add the make-doc.py script in its last version - and make its output
+ the default master files for both html and docbook
+ * remove all other doc-maker scripts but make-doc.pl and make-doc.py
+ plus the make-dbk.pl of course
+ * twist configure.ac to set PYTHON instead of PHP
+
+2003-08-03
+ * make compatibility-headers to issue a warning upon include
+
+2003-07-31
+ * fix a segfault with corrupted central directory - just some checks
+ for field boundaries
+ * add a hack to support the fixup-rootdir thing with some simple(r) code
+ that abuses a few fields in the trailer-structure
+ * cvs checkout savannah.gnu.org:config into ../savannah.config and,
+ * add a rule `make configsub` in Makefile.mk to update the two files
+ uses/config.sub and uses/config.guess to the latest versions.
+
+2003-07-30
+ * creating a 0.12.82 out of the source for 0.10.82 and make up a rpm
+ spec which does alias the .so files for these generations
+
+2003-07-29
+ * the include of _LARGEFILE_SOURCE to do ZZIP_LARGEFILE_RENAME is
+ actually a bad idea - the respective symbol does not provoke
+ 64bit off_t on newer platforms. Only _LARGE_FILES seems to
+ be correct here for older aix platform to get them define
+ off_t = 64bit where others are using _FILE_OFFSET_BITS=64 now.
+ * after changes to README, remember to package updated test.zip !!
+ otherwise `make check` will fail.
+ * modify _msvc.sed to include "define ssize_t int"
+ * use ZZIP_EXPORTS instead of ZZIP_DLL for DLL export, that's the
+ automatic way of MSVC 6 saying that "zzip" is a DLL project.
+ * create new msvc6/zzip.dsp and delete msvc6/zziplib_DLL.dsp
+ * all examples shall import from zzip.dll by linking with zzip.lib
+ whereas that other zziplib.lib is just the static library
+ * do a looong and detailed information in README.MSVC6
+ * create a rule to pack the *.dll,*.exe,*lib files into a zip
+
+2003-07-28
+ * doc bug in zzip-zip reported by j.scrott.frank
+ * remind me: unzip from memory seems to be more of a task lately...
+ * forgot to modify RELASEINFO in rpm for zzip64 variant
+ * also do not just use -D_LARGEFILE_SOURCE, it does not have the
+ desired effect on all systems. Instead invent a new name
+ -D_ZZIP_LARGEFILE to make it happen magically.
+ * invent a rule to create zziplib64.pc from zziplib.pc for the
+ renamed libzzip.so -> libzzip64.so
+ * invent a rule to create zziplib64.la from zziplib.la for the
+ renamed libzzip.so -> libzzip64.so
+ * do also rename default libzzip.so to libzzip32.so and then create
+ a symlink to it under the old name libzzip.so
+ * create zziplib32.pc and zziplib32.la files accordingly. Following
+ an application may choose explicitly between 32 or 64bit off_t
+ version. This allows us to claim now that the default libzzip.so
+ library may be either of them and not anymore strict 32bit off_t
+ * aaahm, note that all of these account for rules in the linux rpm spec!
+ other system do not get this packaging support from vanilla tarfile
+ * well, better make it lib01 instead of lib0.10 for the rpm name
+ * already roll out visualc7.zip and msvc6 files in subdirectories,
+ do not ship them as .zip files
+ * already adapt msvc6 .dsp files but not yet tested
+ * rename main "rpm" target into "rpm2" to get rid of the warning message
+ * use (cd zzip64 && make install) instead of (... make install-ltLIBRARIES)
+ since otherwise we do not get any .pc file installed (oops)
+ * while modifying *.la into *64.la, take care to fixup reference to the
+ "old archive" *.a as well making it *64.a - same for *32.la file.
+ * some file.c reports there was not previous declaration of some of
+ its functions, but _only_ in 64bit compile step.
+ Reason: looks like a gcc 3.2.2 bug, no fix here.
+ * convert a few "ln -s" into "ln -s -f" in "make install" parts
+ * update README to point out staticlink model
+ in a separated LICENSE section.
+
+2003-07-28
+ * add three extra gcc options: -Wpointer-arith, -Wsign-compare, and
+ -Wmissing-declarations which will help about portability to
+ platforms where that is enabled by default in -Wall
+ * sign-compare fix in, zzobfuscated (zzip_size_t -> zzip_ssize_t),
+ * make 5 functions in zzipwrap/wrap.c global=>to=>static
+ * add pre-delcare headers for 2 functions in zzip/zip.c
+ __zzip_find_disk_trailer(), __zzip_parse_root_directory()
+ * rewording of "ends/tail" in find-disk-trailer which does also find
+ a little bug (ends-1 or not) in there, It should not have shown any
+ practical problem so far, also corrected by anotgher little bug
+ in there (ends-tail > sizeof or ends-tail >= sizeof)
+ * adding a parts of a patch from Martin Schitter to harden zziplib
+ for corrupted zip files.
+ * remove a few duplicates in Makefile.mk, still need to keep "rpm"
+ * add declaration for zzip_dir_alloc_ext_io into zzip/lib.h
+
+2003-07-27
+ * redefine size_t maplen -> off_t maplen and for each of the calls to
+ mmap()/munmap()/read()/getpagesize() we cast to size_t - this might
+ get us rid of a few warnings about signed/unsigned comparisons.
+ * introduce AC_TYPE_SIZE_T and use the prefixed variant _zzip_size_t
+ within plugin.h for io->read() calls. That makes for a little
+ bit of portability - it seems some platforms (dot-net f.e.)
+ do not `typedef unsigned int size_t;`, perhaps because int is 16bit
+ and a 32bit or even 64bit entitity is needed.
+ * now we do not need to AC_COMPILE_CHECK_SIZEOF(size_t) anymore, perhaps
+ even stand io-wrap is not needed anymore. Let's see.
+ * both changes need update of zzip/conf.h for _zzip_size_t plus
+ - plugin.h for io->read(,,size_t)
+ - zzip.h for zzip_file_read (,,size_t)
+ - zzip.h for zzip_read(,,size_t)
+ - zzip.h for zzip_fread(,size_t,size_t,)
+ - zzip.h for zzip_seek(,off_t,)
+ - zzip.h for zzip_tell(,off_t,)
+ - file.h int => size_t for zzip_file's restlen crestlen usize csize
+ * the io->seeks(,off_t,) has not been respected so far sometimes.
+ and like lseek(2), we define the returntype of zzip_seek as off_t
+ * introduce zzip_ssize_t as well, and modify
+ - zzip.h for zzip_read and zzip_fread and zzip_file_read
+ - plugin.h for io->read() return type
+ * dot-net bug in aligned4() - sizeof(long) < sizeof(void*) !!
+ better use off_t in the hope that it does fix it
+ * tested on ia32-linux, alpha64-linux, sparc32-solaris
+ * ooops, we need to update io-plugin examples and documentation as well,
+ since we define a custom _read() routine righ there.
+
+2003-07-26
+ * updating to AX_SPEC_DEFAULTS macro
+ * zzshowme does not work with no libzzip installed in the system
+ * add automake option dist-bzip2
+ * use tar.bz2 for rpm build
+ * add dist-bzip for the latter
+ * use zziplib-lib0.10 package which provides zziplib and libzzip0
+ * forgot to add *.la files into the rpm devel package
+ * AC_SET_RELEASEINFO_VERSIONINFO => AX_SET_VERSION_INFO
+ * adjust all RELEASEINFO -> RELEASE_INFO accordingly
+ * and choose 0.10.82.pre1 as a vesion number for testing
+ which is possible now as the new macro does it right.
+ * forgot override of default_includes in test/*.am
+ * somehow ax_prefix gets the wrong input, i.e. _config.h instead of config.h
+ so we make that one explicit now
+
+2003-05-13
+ * the off64_t mode renaming for 64on32 was done incorrectly and
+ it lead to problems on solaris8 - fix it.
+ * fixup `make check` to work on subdir build
+
+2003-05-11
+ * adapt README file to clarify LICENSE details as suggested by
+ a discussion with ACE/TAO developers that want to use the
+ library for some compressed xml archives.
+ * fix a few zzip_char_t bugs that got visible in MSVC mode as
+ reported by Olge Ryabukha
+ * kill sfnet strand of the rpm build, the docs are installed
+ into the share/groups part and the omf file points to that
+ place. The index.html file is the one at sourceforge while
+ the other one is the entry point of the local documentation.
+
+2003-04-21
+ * quite a few updates are need to --enable-builddir by default
+ * watch out: subdir build is the default now!
+
+2003-04-20
+ * pick up AX_ENABLE_BUILDDIR
+ * throw out ac_subst CONFIG_ARGS
+ * use AX_SPEC_PACKAGE_VERSION
+
+2003-04-20
+ * memory leak in zzip/file.c - adding free(dir->realname) zzip/zip.c
+ in function zzip_dir_close called via zzip_file_close
+ (bug reported by Olge Ryabukha, thanks!)
+ * "/" is hardcoded for finding subpaths but on windows that could be
+ a backslash as well. That should be handled better, we add some
+ alternative implementations for dirsep_strrchr and dirsep_casecmp
+ but the default is OFF!! even on WINDOWS !!
+ * thereby seen another problem: we did deliberatly use strcasecmp but
+ this symbol is not available on all unix systems - the manual
+ says its a BSD4.3 addition. Some other systems call it strcmpi
+ or stricmp instead, or they do not have it at all. Here we add
+ a configure rule to check for that symbol, and when we do not
+ have it then we _enable_ dirsep_casecmp automatically.
+
+2003-01-16
+ * change extension of intermediate docbookfiles to ".xml"
+ * throw out attempts to compile docs with php
+
+2003-01-15
+ * lots of doc updates in between. (forgot to document them).
+ * a zzip-config update, and installing an aclocal macro now.
+
+2003-01-06
+ * defattr(root,root) !! - why that had been forgotten? hmmm...
+ * allowing for --disable-debug to clean cflags from -g entries
+ but it has not effect on callframe generation... actually.
+
+2003-01-05
+ * we need to stop the manpages.ar bloat - now!
+
+2003-01-05
+ * add largefile tests in configure.ac
+ * add largefile detection in zzip/conf.h
+ * add renamings for zzip_telldir/seekdir in zzip/zzip.h
+ * add extra exports in zzip/dir.c to have both 32bit and 64bit names exported
+ i.e. zzip_telldir _and_ zzip_telldir64
+ * add renamings in zzip/plugin.h to ensure that 64bit-off_t-compiled zziplib
+ is not given io-callbacks being from another program that is actually
+ compiled as 32bit-off_t and where therefore arguments do not match.
+ * detected a dubious export of "aligned4()" - rename this export now.
+ * also rename everything having "_io" in the name - just to guard ourselves
+ from the case where two -lzzip are in the libpath and one is
+ compiled 64bit-off_t while the other is not.
+ * rename the younger function s/zzip_open_shared/zzip_open_shared_io/
+ * make up functions for zzip_open_ext_io and zzip_opendir_ext_io for the
+ case of 32/64bit dual systems where lib is compiled in largefile mode.
+ Let the call succeed unless an "io" structure was given - return
+ the EOVERFLOW errno as specified in the large.file WG documents.
+ * make all parallel defines for 32/64 bit dual off_t dependent on
+ defined EOVERFLOW and defined PIC - i.e. only for dynamic linkage.
+ * adding LARGEFILE_CFLAGS into zziplib.pc and bins/zzip-config.in
+ * NOTE: the default for --with-largefile is still OFF !!
+ * NOTE: our zzip_readdir is not depenent on off_t size
+ * adding -64 into the --release info for the sharedlibrary build
+ it should have been a --variant but such does not exist so far
+ in libtool, sorry.
+ * extract AC_SYS_LARGEFILE_SENSITIVE and put it into an extra ac-macro
+ * clean zzip/file.h from compatibility-install as zzip-file.h
+ the structure in there contains zzip_off_t items and they
+ should be internal always anyway - so disallow access for
+ old programs now just to be sure.
+ * adding zzip64 compilation into zziplib.spec - an rpm package will now
+ install both 32bit off_t and 64bit off_t variants of the sharedlib
+ * note: we do not copy 64bit zzcat into the rpm, perhaps we should?
+
+2002-12-31
+ * add make check-sfx
+ * add zzipself.c and zzipsetstub.c for the sfx test
+ * zzip_file_open takes o_modes flags, clarify in zzip.h
+
+2002-12-27
+ * adding scrollkeeper omf file generation in docs/
+ * adding omf file installation in docs/make-install-doc
+ * replace %post-doc message in zziplib.spec with scrollkeeper-update call.
+ * need *.pc *.omf in CLEANFILES now
+ * mingw32 crossgcc tests for win32 dirent emulation - did need some fixing
+
+2002-12-23
+ * adding generation/installation of pkgconfig files
+ * making SDL a build-requirement for rpm packaging
+
+2002-12-22
+ * add compatibility subdirectory "zziplib"
+ * zzipback.sed to create zziplib/* files from current release files
+ * include into distribution tarball
+ * IMPORTANT: flashback - 12.24 is now called 10.74 -
+ the old source line will cease to exist, only the compatibility
+ directory will survive a while - that should put some pressure
+ on developers to update to the new source tree. And it saves me
+ some work to keep two trees in sync.
+
+2002-12-20
+ * fix some problems of make-doc.pl with the current project
+ * make a standard inlude info referring to zziplib.h as well
+ * unpack htmpages.ar on SFNET and register it on the frontpage
+ * dont forget to modify includes of internal headers
+ * ...
+ * fixed an annoying bug in make-doc.pl
+ * include htmpages.ar into the tarball
+
+2002-12-19 Guido Drhaeim <guidod@gmx.de>
+ * completed new directory structure - the library is called 0.12.22 as
+ to match 0.10.72, it's the same C source in its content
+ * install-headers modified - the new structure is now compatible both
+ as a shared libary (binary compatible) and for the include headers
+ too - source compatible not only for function names but also for
+ the #include lines
+ * 0.12.23 fixes a bug in make doc: the xmlto html was never done.
+ * and we implant make-doc.pl which was founded on the base of the local
+ zzip-doc.pl but has since gone a lot further. It's currently just
+ a third variant but it is now used as the primary master default.
+
+2002-12-18 Guido Draheim <guidod@gmx.de>
+ * man page update for zzip_open_shared (it turns out to be a good name).
+ * let frontpage point to http://www.gzip.org/zlib for primary zlib site.
+
+2002-12-17 Guido Draheim <guidod@gmx.de>
+ * introduce zzip_open_file that may have an extra argument of a factory
+ file to share the zzip internal directory if that is possible.
+ * introduce zzip_freopen to take an extra argument. The supplied handle
+ is freed unless of course one puts ZZIP_FACTORY into o_modes so
+ that it becomes a wrapper around zzip_open_file
+ * the zzip_open_file, in that case, is the old zzip_open_ext_io call
+ but extended with checking the factory stream for a matching
+ basename.
+ * while being there: introduce ZZIP_ALLOWREAL o_mode that will make it
+ that a real file is open/read/close with the standard posixish
+ routines. This is most useful when having an obfuscated zip
+ file around but during development one wants to sometimes check
+ with a real file - so the call mode is something in the middle
+ of ZZIP_ALLOWREAL - ZZIP_PREFERZIP|ZZIP_ALLOWREAL - ZZIP_ONLYZIP
+ where the middle is for "yet another file not yet included",
+ hmm, perhaps a cheat file? ;-)=)
+ * cleaning rwops example: fix the mode check, it's not needful to start
+ with "r" to be a readfile mode, it may be somewhere in between.
+ * introduced __zzip_dir_parse as a cut off from zzip_dir_fdopen_ext_io,
+ but it did turn out to be not necessary, so it is made static in
+ the end. Still, it works as documenting the control flow better.
+
+2002-12-17 Guido Draheim <guidod@gmx.de>
+ * win32 mmap removing extra braces
+ * win32 dirent implementation added - new file __dirent.h
+ and modified zzip-dir.c
+ * a couple of arg[n] -> argv[argn] cleanups.
+ * a missing argc > 1 check added.
+ * all changes due tests / bug reports by Thomas-dot-Eder-at-nmi-AT
+
+2002-12-16 Guido Draheim <guidod@gmx.de>
+ * the infozip `zip` tool puts out messages per default on some machines
+ fix by adding >/dev/null in some places of Makefile.am
+ * the hpux10.20 platform has sys/mman.h but no MAP_FAILED
+ the `man mmap` says it returnes "-1" as done on all other unix
+ compatible platforms, so we add a default define ((void*)(-1))
+ * update TODO file with some hints on test runs.
+ * add --with-zlib configure call to make it easier to specify a path
+ * make zlib error messages to point to this configure option.
+ * beautify error output on all other options as well.
+ * create `make brute` to make a bruteforce test
+ * solaris8 make has a problem with $< ... change sometimes into $?
+ * freebsd/darwin have 64bit off_t by default - and that reveals a problem
+ in the zzip_telldir/zzip_seekdir code. Let's change the code to make
+ it return/receive a byte-offset of "dir->hdr" to "dir->hdr0".
+ This makes printing of those values also more intelligible (if ever).
+ * ia64-linux reveals a problem in "default_io" since size_t is 64bit.
+ We modify --with-wrapwrap to autodetect this case. This is okay
+ since zip-files can not get bigger than 32bit offsets anyway.
+
+2002-12-16 Guido Draheim <guidod@gmx.de>
+ * merging corrected README.SDL and __hints.h
+ courtesy of Thomas-dot-Eder-at-nmi-AT
+ * update CFLAGS ac-macros to the new generation as shipped with
+ latest ac-archive-0.5.39 (did upload just yesterday...)
+
+2002-12-14 Guido Draheim <guidod@gmx.de>
+ * many hours of debugging - I don't remember which flaw came in through
+ the latest changes or which others were there before *sigh*
+ * e.g. the error-code mappings were refined on linux errno codes
+ * fix "caseless" bugs reported by Thomas-dot-Eder-at-nmi-AT
+ * fix MSVC related flaw when taking a casted value as an lvalue
+ * replace AC_CREATE_PREFIX_CONFIG_H with new style AX_PREFIX_CONFIG_H
+ * invent zzip-msvc.sed to turn config.h.in into zzip-msvc.in and
+ finalize a fresh zzip-msvc.h via AX_PREFIX_CONFIG_H
+
+2002-12-13 Guido Draheim <guidod@gmx.de>
+ * shown by Mike Nordell tamlin-at-algonet-SE we can support win32 mmap
+ * modify configure.ac : if have:winbase.h then auto -enable-mmap
+ * refactor mmap'ing - it goes into __mmap.h and uses the io->use_mmap value
+ and that include file contains both posix and win32 mmap variants
+ * rewrite pagesize/mapoff calculations - this should be faster in itself
+ and also easier to maintain in the future for being more obvious.
+ * rewrite read/write defines and wrapwrap's. The zzip-conf.h does now
+ contain defines for _zzip_read/_zzip_lseek - and it should us get
+ rid of the nasty win32 problems with redefining _read/read
+ * refactor DBG defines - put them into __debug.h - oops, xbuf() was
+ an exported symbol, better be not. Use only newer NOTE/WARN macros!
+ * implant __hints.h include - that's taken from another project but it
+ is so damn useful ;-)
+
+2002-12-12 Guido Draheim <guidod@gmx.de>
+ * modifizied zzip-zip.c to include a sanity check on getpagesize ()
+ for mmap () functionality and ZZIP_BUFSIZ (the default is good).
+ * modify configure.ac : const char strings
+ * modify configure.ac : strict prototypes
+ * modify configure.ac : all warnings
+ * ... and so it reveals something missed along ;-)
+
+2002-08-27 Guido Draheim <guidod@gmx.de>
+ * modified zzip-stdint.h along the example patch for FreeBSD done
+ by wjpalentstijn at sourceforge in projet uwadv.
+
+2002-07-24 Guido Draheim <guidod@gmx.de>
+ * did teach myself php over converting zzip-doc.pl into zzip-doc.php
+ * added php-test and another way to create the docbook file, with php
+
+2002-07-20 Guido Draheim <guidod@gmx.de>
+ * lots of fixes around docbook/manpage - and generate a zziplib.3
+ overview page. Fixes also lots of comments in the sources.
+ * modified fopen-mode interpration nicely.
+ * added zzip-api for full overview of the zzip's API
+
+2002-07-19 Guido Draheim <guidod@gmx.de>
+ * greatly enhanced docbook/manpage generation - including to attach
+ author and license info from the respective source file header
+
+2002-07-18 Guido Draheim <guidod@gmx.de>
+ * extended the perlscript to generate zziplib.docbook
+ * use xmlto to generated manpages.ar
+ * install-man3 target and push into rpm-devel package
+
+2002-07-17 Guido Draheim <guidod@gmx.de>
+ * no new code, just doc updates. The perl-script is now capable to
+ combine _ext_io functions with their non-ext/io cousin, and the
+ sources have been modified to honour this new mode.
+ * the perl-script is now ready to spit out other data like docbook
+ files that we can generate man-pages from later.
+
+2002-07-16 Guido Draheim <guidod@gmx.de>
+ * extern-C in SDL_rwops_zzip.h ... and ifdef'able DECLSPEC for staticlinking
+ * zzip_fopen allows to greatly simplify SDL_rwops_zzip.c
+ * zzxordir.c zzxorcat.c zzxorcopy.c invented
+ * lots of new documentation added
+ zzip-extio.html zzip-xor.html zzip-refs.html
+ * new checks that test the zzxor examples
+ * and found an zzxor bug in the course
+
+2002-07-15 Guido Draheim <guidod@gmx.de>
+ * Michael-dot-Fink-at-asamnet-dot-de did some code review while
+ going after a specialty he wanted to do with the libs, and therefore..
+ * PREFERZIP did never test real file - stupid bug, inverted logic....
+ * add ZIPONLY zzipmode - we have plenty of options availabe... on 32bit
+ platforms however, since I want to keep with the access-bits in
+ the lower parts.
+
+2002-07-12 Guido Draheim <guidod@gmx.de>
+ * watcom-c-10.5 project file added
+ * used my old watcom compiler to debug the win32 problems, and it turned
+ out to be a mismatch in proccall for zlib - while the default in
+ zlib.h inferred WINAPI, it turned out that zlib114dll.zip had in
+ fact been compiled with __syscall procframe callmethod. Duh!!!
+ * some things had to be rearranged in header files - most classically it
+ seems that this compiler does not support __inline in C mode.
+
+2002-07-11 Guido Draheim <guidod@gmx.de>
+ * convert all API const types into those with _zzip_const and use new
+ types like zzip_char_t and zzip_strings_t throughout the sources.
+ * add ZZIP_RDONLY and friends. Do not use fcntl bits anymore, and limit
+ use routines to convert them into O_DEFs later one in the next
+ version of this lib - here we just declare them to be their O_DEFs
+ but code should start to pick up ZZIP_DEFs in the meantime.
+ * add zzip_fopen and friends as another type of magic wrappers.
+ * modify open_ext_io to use receive separate arguments for the two
+ zzip extraflags - use these from now on, the others are just
+ for limited backward compatibility.
+ * modify all _close functions to return "int".
+
+2002-07-10 Guido Draheim <guidod@gmx.de>
+ * Marlin Prowell mbp-at-cadalog-inc-dot-com did hit a problem on FreeBSD
+ showing off a config problem - the configure.ac macro for off_t is
+ written to be _undefined_ if off_t existed in the system. Instead we
+ chose to defined zzip_off_t into a "long" as it is needed on win32,
+ and since FreeBSD on LFP32 uses OFF64 it did fall flat on calls to
+ lseek - without io-wrap the gcc did cast them correctly, so it worked.
+ * the fix: use off_t if zzip_off_t undefined. Add a define zzip_off_t into
+ long in conf-msvc.h. Add a configure-option to have wrappers for the
+ default lowlevel calls as suggested by Marlin but I choose to have
+ them off by default - a bsd ports package may start using it.
+ * there have not been reported problems in the last three months where only
+ developers knew about the new version. Guess it's time to push this
+ tarball and announce it on freshmeat.
+
+2002-04-30 Guido Draheim <guidod@gmx.de>
+ * fix typo in zzip-zip.c: __USE_MMAP -> _USE_MMAP
+ * if zlib.h not found, make it a fatal exit
+
+2002-04-25 Guido Draheim <guidod@gmx.de>
+ * adding a few more `make check` rules for bigger zip files
+ * add even negative tests
+ * add some spaces in error-messaging in zzdir.c and let return
+ an exitcode when some argument files could not be read
+
+2002-04-24 Guido Draheim <guidod@gmx.de>
+ * apply patch from Mike Nordell
+ changes all "const char * *" into the intended "const char * const *"
+ changes some typecasts
+ corrects comment and adds some
+ and two fixes
+ * put the updated MSVC6 files into the project, again Mike Nordell
+ * me, add new zzwrap.dsp to DIST in Makefile.am, following Mike's addition
+ * me, modify some typecasts to use off_t/size_t where apropriate
+ * modified COPYING.ZZIP to be a bit more general than just for ZZIPLIB
+ as noted by Tomi Olilla
+ * zzipwrap demo_callback, how can we do void* and char* at the same time...
+
+2002-04-23 Guido Draheim <guidod@gmx.de>
+ * changed ssize_t into int in zzipwrap-mem for portability reasons
+ * fix zzip_dir_fdopen_ext for access to uninitialized io-vtable
+ (thanks to Lutz Sammer johns98-at-web-dot-de for testing)
+
+2002-04-22 Guido Draheim <guidod@gmx.de>
+ * add MSVC6 project files contributed by Mike Nordell tamlin-at-algonet-dot-SE
+ * add plugin_io-patch from Mike Nordell
+ and dump the iowrap-patch from Andreas Shiffler from earlier release
+ * append the Mike Nordell's zzobfuscated.c to Makefile.am
+ * add a new file COPYING for new less-strictly license
+ after Tomi Ollila has transferred full copyright to me
+ * remove Tomi Ollila from all copyright entries in the sources
+ but honour his name where apropriate
+ * modify LGPL hints in sources and point to COPYING.ZZIP as well
+ and change copyright year info
+ * create COPYING.ZZIP with some general LGPL exceptions.
+ * use newer AC_CREATE_CONFIG_H macro and start using acinclude.m4
+ to allow retooling of the project.
+ * and use zzip_off_t instead of ZZIP_off_t (but keep backward compatibility)
+ * apply patch for the problem detected and corrected by
+ Steve Dillon steved-at-phone-IVR-dot-com
+ * try with an updated ac_create_prefix_config_h due to a bug report by
+ John W. O'Brien john-at-jugglers-dot.com
+ where his shell-and-echo combination did interpret \\1 twice.
+ * add use_mmap flag to plugin_io_t, so the feature can be used
+ along USE_MMAP configured setups
+ * change USE_MMAP #ifdefs to use if()s and to rely on the
+ compiler to do code removal for unreachable code
+ * remove tell() part of plugin_io and rename seek()-indirection
+ to seeks()-indirection using a tells()-macro in zzip-file
+ * also rename s/seek/seeks/ in zzip-zip and kill the (*function)(x)
+ for the indirection functions into just function(x)-calls
+ * fix zzobfuscated example code - there's no read() without unistd.h
+ in unix, and global zzip_install_io had been removed lately.
+ * add zzipwrap-io.c and zzipwrap.c from Andreas Schiffler's patch
+ on the new ground of Mike Nordell's plugin_io
+ * modify zzipwrap sources to work with plugin-io
+ * add io pointer to dir-structure, and use it as the default for file-structs
+ * __zzip_open_zip is called __zzip_try_open now and takes two arguments
+ * typedef struct zzip_plugin_io * zzip_plugin_io_t;
+ * zzip_opendir_ext_io .. for magic convenience
+ * create new zzipwrap.la in Makefile.am
+ * move plugin_io struct from zziplib.h to zzip-io.h
+ along with its helper functions
+ * change all filesize into zzip_off_t
+ * s/zzip_find_disk_trailer/__zzip_find_disk_trailer/ (additional io arg)
+ * s/zzip_parse_root_directory/__zzip_parse_root_directory/ (ditto)
+
+2001-10-11 Guido Draheim <guidod@gmx.de>
+ * added zzipwrap feature contributed by Andreas Schiffler
+
+2001-09-18 Guido Draheim <guidod@gmx.de>
+ * fix bug for `zzip-config --cflags`
+ which did print /xx/include instead of -I/xx/include
+ (thanks to Roger Ostrander <denor(at)yahoo.com>)
+ * change the for-loop in zzip-config - the "for i ; do" is not portable
+ because I had problems on solaris-sh. Use "$@" which expands
+ to a list (!!) of argv entries for this for-loop even for
+ arguments that contain spaces. fascinating.
+ * use AC_HELP_STRING ... the `configure --help` screen got a bit
+ misformatted lately.
+ * add a `make check` rule.
+
+2001-08-19 Guido Draheim <guidod@gmx.de>
+ * add that /programs magic to the $prefix check in configure.ac
+ * add that /usr/share magic to the $prefix check in configure.ac
+ * fix zzip-sdl-rwops.html layout (and copying.zlib link).
+ * fix some flaws in sdl-rwops example source (just by code review).
+ * add unistd.h include to zziptest.c to silence off the warning about sleep
+ * add non-dll compile to extern in zzip-conf.h - does that fix anything?
+
+2001-08-18 Guido Draheim <guidod@gmx.de>
+ * SDL_rwops_zzip.c/SDL_rwops_zzip.h SDL-example file.
+ * change all filename args to be const
+ * add ZZIP_const to zzip-conf.h, but do not use it for now.
+ It seems that all current lib-users have a modern compiler...
+
+2001-08-16 Guido Draheim <guidod@gmx.de>
+ * export zzip_dir_free / zzip_dir_alloc
+ * bring in fileext field to check for multiple fileextensions.
+ * make zzip_open check for multiple (default) fileextensions.
+ * add ifdef USE_ZZIPLIKES to implement feature proposed by
+ Julien Cayzac <deepmind(at)jessica.brainlex.com>
+ * make zzip_open check along the dirpath for a zip-file
+ a feature proposed by Lutz Sammer <Johns98(at)web.de>
+
+2001-08-15 Guido Draheim <guidod@gmx.de>
+ * add "stroustrup" style to all c files to ensure that casual
+ developers do not trash the layout unintentionally.
+ * modify examples a bit with more newlines / comments.
+ * re-license examples to ZLIB license
+ * include COPYING.ZLIB into doc_FILES
+
+2001-08-10 Guido Draheim <guidod@gmx.de>
+ * change frontpage of webpages - including a few crosslinks to
+ other projects
+
+2001-08-07 Guido Draheim <guidod@gmx.de>
+ * split version X.Y.Z into -relese X -version-info Y:Z
+ * adding --disable-thread-safe, and add -thread-safe linkage by default
+ * modify releaseinfo for with-debug
+ * install-zip target to make a windows package
+ * change serial to _vendor - rpm has never been used for other than linux
+
+2001-08-06 Guido Draheim <guidod@gmx.de>
+ * reorganize docs, update docs to new style
+ * split version X.Y.Z into -release X.Y -version-info Z
+
+2001-08-05 Guido Draheim <guidod@gmx.de>
+ * add zzip-msvc.h, a header file that will be included when
+ a windows compiler is detected in zzip-conf.h, e.g.
+ _MSC_VER or __BORLANDC__
+ * mv index.html zzip-index.html and add makerule that patches
+ the VERSION in before installing it as index.html
+ * add a makerule to build sourceforge htdocs and add it
+ to the rpm build.
+ * add generic patches for libtool into configure.ac
+
+2001-07-18 Guido Draheim <guidod@gmx.de>
+ * check up bugs in automake 1.4beef, now using a rule to
+ override AUTO* in non-maintainer-mode. we also set
+ libtool to silent in non-maintainer-mode
+ * docs are installed to $datadir/doc/$package as default
+ * rpms can now be built.
+ * create --with-docdir and let it be filled in rpm-configure
+ so that docs will end up where rpmopt says it should.
+ * ChangeLog goes into %doc of rpms.
+ * uhmm, forgot to install the test*.c files into the docdir
+ * the bin rpms had not been built
+ * compress into base and devel package
+ * errnolist should be static
+
+2001-07-17 Guido Draheim <guidod@gmx.de>
+ * nuke Makerule system, use plain autotools style including
+ configure && make install to rebuild
+ * update Makefile.am (which is new now)
+ * use next-generation autotools as a basis, update configure.ac
+ to newer style, update configscreen at the end of file
+ * check perl in configure and let it default to "echo"
+ * check HAVE_ defines coming from config.h - it is not anymore
+ included by zzip-config.h, so each config-def usage
+ must now use the prefix'd version
+ * provide a zziplib.spec file
+
+2001-01-05 Guido Draheim <guidod@gmx.de>
+ * apply zzip_seek-patch from Ted [sourceforge.net/users/tam4]
+ * -> 0.10.12
+
+2001-01-02 Guido Draheim <guidod@gmx.de>
+ * gone through a couple of trial and error versions until
+ I finally arrived at a mingw32msvc zzip.dll - basically
+ I had to update the included libtool files to 1.3.5
+ and the zzip.dll source-files have a ZZIP_DLL define
+ before the first include that points to zzip-conf.h -
+ and there is the magic about dllexport and dllimport.
+ Hopefully the same can run under MSVC without further
+ changes to the sources.
+ * try to package a zip-file that contains the relevant files
+ from the mingw32msvc install, so that windows user
+ get a clean dll without the need to compile it.
+ * -> 0.10.11
+
+2001-01-01 Guido Draheim <guidod@gmx.de>
+ * received a patch for MSVC compatibility from Ted A. (@lehigh.edu)
+ which made me to look after the project again. There
+ were two support requrest during summer that asked for
+ MSVC support, especially a prebuilt dll and headers.
+ * added AC_PREFIX_CONFIG_H that I made originally for
+ another project. It enables me to push the configure
+ detections into a global include/-dir. Ted's patch
+ used an `IFDEF MSVC DEFINE HAVE_SYS_TYPES_H` which
+ is a symptom of using config.h&HAVE_CONFIG_H and
+ zzip-file.h&IFDEF HAVE_xx. Change all header-IFDEF-HAVE
+ to use IFDEF-ZZIP_HAVE, and install zzip-config.h
+ along with the other headers, change the original
+ include"config.h" in zzip-stdint.h and make it rely
+ on zzip-conf.h - where zzip-conf.h includes zzip-config.h
+ and lists the detected features to be used, along with most
+ important extra defs for MSVC compatibility. (!!!)
+ * added AC_COMPILE_CHECK_SIZEOF (cross-compile clean!)
+ to always use the correct STDINT defines. Delete
+ use of glib.h if present, it's not needed anymore.
+ * use ZZIP_off_t instead of off_t
+ * prepare for a MSVC' ZZIP.DLL with _zzip_export defines..
+ -DZZIP_DLL -> declspec(dllexport)
+ -DHAVE_LIBZZIP -> declspec(dllimport)
+ * make sure, __attribute__ is okay with non-gcc compilers
+ and attache packed-attribute to *all* zipformat-structs. The
+ whole of zzipformat.h is also enclosed in pack-pragmas.
+ * -> 0.10.7
+ * create zzip-config.in and install it.
+ * mingw32msvc has shown that we need -lz on the command-line
+ to resolve a few symbols
+ * go automake
+ * install zzip-config along
+ * mingw32msvc does not build with cross-make.sh as seen on
+ http://libsdl.org/Xmingw32 - it needs the cross-tool/lib
+ just as well. There we have LDLIBADD in Makefile.mk now.
+ Now everything works for making win32 target with cross-tools.
+ * The rest of the make-struture should ensure to be able to
+ create an MSVC nmake Makefile - the Makerule.am is clean and
+ can be directly included... hopefully.
+ * -> 0.10.8
+
+
+2000-06-03 Guido Draheim <guidod@gmx.de>
+ * Tomi did a final test round for solaris, oh well,
+ configure needs some fixes...
+ * checking for myself at the university's solaris2.6 with
+ gcc-2.95.2, hmm... there's an sys/int_types.h that
+ seems to define some of C9X int-types, put it into
+ the configure.in and know about it in zzip-stdint.h
+ (btw, glibc seems to have include/inttypes.h that
+ includes stdint.h).
+ * tomi did report a problem with gcc 2.7.2... probably
+ sth. about -rpath
+ * release 0.10.6 and going to announce it...
+
+2000-05-31 Guido Draheim <guidod@gmx.de>
+ * created the main doc html files, index.html, zzip-zip.html
+ and zzip-file.html. the README and README.API is deleted,
+ and the TODO is a bit updated.
+ * This version is meant to be announced very soon now.
+ * release 0.10.5 and contact Tomi for his final nod.
+
+2000-05-31 Guido Draheim <guidod@gmx.de>
+ * ifdef HAVE_SYS_STAT_H where stat is used. Removed
+ the stats from zzip-file.h - it will now just try
+ to open the file or zip-file and assume that
+ open(2) will fail if the file is not there. I do
+ hereby assume that the returned fd is seekable..
+ * two new functions, zzip_dir_real and zzip_file_real
+ to check if the ZZIP_XX structures are wrapping a
+ real file or directory. Otherwise it is a zip-archive
+ or a zip-contained file respectivly.
+ * zzip_compr_str does now know about stat-types and
+ will return names for S_ISTYPE bits.
+ * remove zzip_fd. It was identical to zzip_dirfd
+ whose name is consistent with dirent.h
+ * zzip_stat -> zzip_dir_stat since it does not neither
+ return a stat structure nor does it use stat(2)
+ * Checking the doc-comments
+
+2000-05-30 Guido Draheim <guidod@gmx.de>
+ * zzip_fp -> zzip_file and _fp_ functions to _file_
+ * zzip-stdint.h to ensure iso c9x typedefs
+ * ZZIP_GET16/32 macros in zzip.h header.
+ * minor updates in cosmetics and documentation
+ * have full replacements for dirent.h functions,
+ the zip-specific functions are now called
+ zip_dir_open (and more alike). The zzdir can
+ now show a list of files in a real directory,
+ or magically the files contained in a zip-arch.
+ * release 0.10.4
+
+2000-05-29 Guido Draheim <guidod@gmx.de>
+ * zzipmain -> zziptest and some cleanups
+ in the Makefile. zziptest is now just
+ another test program, so it gets compiled
+ in full similarity with zzcat and zzdir.
+ * removed zziptest from install-bin
+ * the long forgotten simplicistic dependency
+ rule is now in here too.
+ * cosmetics to pointer declar' stars in
+ zziplib.h
+ * ZZIP_FP -> ZZIP_FILE and
+ zzip-fp.h -> zzip-file.h
+ * removed the use of zzip.h where suggested
+ by Tomi. (use public zziplib.h instead)
+ * removed errno.h from zziplib.h
+ * printing configuration at end of configure.
+ * add install-includeHEADERS rule, so that
+ zziplib.h does now get installed.
+
+
+2000-05-27 Guido Draheim <guidod@gmx.de>
+ * zzipformat.h carries information about the
+ zip-file structure. The typedefs are now
+ used to access members of the zip-archive
+ (instead of using the offsets directly).
+ * notice that the members are declared
+ bytewise due to compiler semantics that is
+ making a structure packed&aligned to the
+ greatest common size (which would be 4).
+ setting as attribute(packed) is not very
+ portable.
+ * reworked the files, esp. zzip-zip.c and
+ zzip-ar.c
+ * _USE_MMAP in autoconf, including option
+ and CFLAGS setting. instead of open/read
+ to a scan buffer the zip-file is mmapped
+ and scanned directly.
+ * _LOWSTK in autoconf, including option and
+ a CFLAGS setting. Still need a scan buffer
+ and this flag tells us not to carve the
+ scan buffer from the auto-stack and use
+ instead some malloc for the scan buffer.
+ * DEBUG in autoconf, including option and
+ a CFLAGS setting. The macros should now
+ be able to be found everyone and only.
+ * revamped EDH find routine, dumped old-style.
+ * revamped read-EDH to use mmap and to use
+ copy/read only for the parts we need. The
+ read-EDH buffer is not limited to 32K
+ anymore and can have any length. No realloc
+ need anymore.
+ * opendir does not allocate the cache.buf32k
+ anymore - it does have no need for it. the
+ buffer is still cached for subsequent Open
+ calls. May want to setvbuf later.
+ * a few renamings to be more bits/dirent.h-like,
+ so many things are now called d_name and
+ d_reclen instead of name or next as before.
+ * renamed the package to "zziplib" as being
+ suggested by Tomi.
+ * release 0.10.3
+
+2000-05-26 Guido Draheim <guidod@gmx.de>
+ * -release at link-line for the lib
+ * zzcat.c as a test program, which uncovered
+ a few flaws.
+ * a flaw w/_fd_opendir when being given a
+ non-inited err-return-variable and no
+ error did occur.
+ * the error to errno table was incomplete,
+ and the ZZIP_INFLATE error is superfluous.
+ * zzdir.c as a test program, needs still to
+ be given the full zip-arch name.
+ * changed member names of zzip_dirent to
+ match similar names in dirent and stat,
+ (ie. d_name and st_size) and added furthermore
+ a z_size that returns the compressed size.
+ * little updates to names and comments.
+ * release 0.10.2
+
+2000-05-22 Guido Draheim <guidod@gmx.de>
+ * merge with zip08x-0.9.6 - actually just
+ a bugfix for zzip_fp_open IGNOREPATH -
+ I even applied it in a different way than
+ Tomi did.
+ * bugfixes for zzip_open, it did not always
+ set errno(2) to the value of zzip_errno.
+ * The zzip_read is now seperate from
+ zzip_fp_read, so that setting errno(2) is
+ only done in zzip_read, not in the zzip-touching
+ function.
+ * zzip-doc.pl to generate libzzip.html
+ * release 0.10.1
+
+2000-05-21 Guido Draheim <guidod@gmx.de>
+ * drop-in replacements ready for daily use,
+ just use zzip_open with a normal path to
+ a fs file. If that file is not found in
+ a normal fs directory, then the path is
+ splitted into a basepath and a filename,
+ a ".zip" is appended to the basepath to
+ form a zip-arch name, and the filename
+ is then searched inside the zip-arch if
+ that one exists. Very nice for distribution
+ of a subdirectory full of scripts and that
+ is what it is meant for - the PFE will be
+ able to use this one for Forth-files.
+ * have a VERSION file containing "0.10.0" and
+ add some rules to Mk-rules
+ * start with in-source docs that will be used
+ for documenting the lib calls. A jdoc like
+ doc extractor should be able to grok these,
+ I'll see to release docs with the next
+ release, but this time...
+ * make it release 0.10.0 and upload it to
+ pfe.sourceforge.net/pub where it will lurk
+ around until I contacted Tomi. He seems to
+ be currently working on zip08x
+
+2000-05-17 Guido Draheim <guidod@gmx.de>
+ * decided to have it actually called zzip_ and so
+ all of the stuff is going to get renamed again.
+
+2000-05-16 Guido Draheim <guidod@gmx.de>
+ * obtained Tomi's code and made changes so that the
+ resulting library is more portable, esp. the glib
+ usage is being abolished. The name of the library
+ (and package) has been renamed to libunzip and
+ all types, consts and funcs to now carry the unzip_
+ prefix.
+ * autoconf !!!!
+ * drop-in functions that can be made to easily replace
+ dirent and filefd functions.
+
+
+Mon Apr 5 11:23:46 2000 Tomi Ollila (too@iki.fi)
+
+ * Release 0.9.5
+
+ * Made some tiny modifications after Matthew's code.
+
+Sun Apr 4 8:30:00 2000 Matthew D. Campbell (matt@campbellhome.dhs.org)
+
+ * Cleaned up compile warnings in SuSE Linux
+
+ * Cleaned up code for cross-compilation with Xmingw32
+
+ * Modified zipx.h to support linking to C++ apps
+
+Wed Jul 28 11:23:46 1999 Tomi Ollila (too@iki.fi)
+
+ * Release 0.9.4
+
+ * Fixed support for simultaneous open files with each
+ open `ZipFile'.
+
+Thu Jul 22 11:57:46 1999 Tomi Ollila (too@iki.fi)
+
+ * Release 0.9.3
+
+ * Added premilinary README.API.
+
+Sat Jul 10 11:49:58 1999 Tomi Ollila (too@iki.fi)
+
+ * Release 0.9.2
+
+ * Fixed code to read start-of-file offset from local header
+ instead relying directory info is sufficient (were TOO naive
+ about that, the first user reported this library won't work
+ with his archives).
+
+Sun Jun 13 20:40:11 1999 Tomi Ollila (too@iki.fi)
+
+ * Initial release (0.9.1).
diff --git a/Build/source/libs/zziplib/Makefile.am b/Build/source/libs/zziplib/Makefile.am
new file mode 100644
index 00000000000..f95935f30d9
--- /dev/null
+++ b/Build/source/libs/zziplib/Makefile.am
@@ -0,0 +1,78 @@
+AUTOMAKE_OPTIONS = 1.4 foreign dist-bzip2
+ACLOCAL_AMFLAGS = -I m4
+WANT_AUTOMAKE = 1.7
+WANT_AUTOCONF = 2.57
+
+DIST_SUBDIRS = zzip zzipwrap bins test docs SDL
+SUBDIRS = zzip zzipwrap bins test docs @SDL@
+
+# see Makefile.mk for the "make rpm" target
+rpm2: dist-bzip2 $(PACKAGE).spec
+ rpmbuild -ta $(PACKAGE)-$(VERSION).tar.bz2
+
+zzip.html zzip.xml zzip.pdf \
+doc docu clean-doc clean-docs clean-docu \
+man manpages htmpages unpack clean-unpack \
+omf install-omf install-doc install-sfnet install-man3 x :
+ (cd docs && $(MAKE) `basename $@`)
+
+sdl testsdl test-sdl install-sdl :
+ (cd SDL && $(MAKE) `basename $@`)
+
+check-test0 check-test1 check-zzdir check-zzcat \
+check-zzxor check-zzxordir check-zzxorcat \
+check-sfx check-readme : \
+ (cd test && $(MAKE) `basename $@`)
+
+MSVC8 = msvc8/README.TXT msvc8/zip.exe msvc8/test1.zip msvc8/test.zip \
+msvc8/zzdir.vcproj msvc8/zzipself.vcproj msvc8/zzip.vcproj \
+msvc8/zziplib.sln msvc8/zzipsetstub.sln msvc8/zzobfuscated.sln \
+msvc8/zziplib.vcproj msvc8/zzipsetstub.vcproj msvc8/zzobfuscated.vcproj \
+msvc8/zzcat.sln msvc8/zzipself.bat msvc8/zzip.sln \
+msvc8/zzcat.vcproj msvc8/zzipself.sln msvc8/zziptest.sln \
+msvc8/zzdir.sln msvc8/zzipself.txt msvc8/zziptest.vcproj
+
+MSVC7 = msvc7/pkzip.exe msvc7/test1.zip msvc7/test.zip \
+msvc7/zzdir.vcproj msvc7/zzipself.vcproj msvc7/zzip.vcproj \
+msvc7/zziplib.sln msvc7/zzipsetstub.sln msvc7/zzobfuscated.sln \
+msvc7/zziplib.vcproj msvc7/zzipsetstub.vcproj msvc7/zzobfuscated.vcproj \
+msvc7/zzcat.sln msvc7/zzipself.bat msvc7/zzip.sln \
+msvc7/zzcat.vcproj msvc7/zzipself.sln msvc7/zziptest.sln \
+msvc7/zzdir.sln msvc7/zzipself.txt msvc7/zziptest.vcproj
+
+MSVC6 = \
+msvc6/zzcat.dsp msvc6/zziplib.dsp msvc6/zzipwrap.dsp \
+msvc6/zzdir.dsp msvc6/zziplib.dsw msvc6/zzobfuscated.dsp \
+msvc6/zziptest.dsp msvc6/zzip.dsp
+
+EXTRA_DIST = zziplib.spec zzipback.sed Makefile.mk \
+ $(MSVC8) $(MSVC7) $(MSVC6) $(am__aclocal_m4_deps)
+
+PHONY = auto boottrap rpm doc docs man manpages htmpages sdl testsdl \
+ comp compats msvc6 msvc7
+docs : docu
+# ------------------------------------------------------------------------
+
+test-comp:
+ test ! -d testing || rm -r testing
+ mkdir testing
+ (cd testing && tar xzvf ../$(PACKAGE)-$(VERSION).tar.gz)
+ (cd "testing/$(PACKAGE)-$(VERSION)/zziplib" && sh configure)
+ $(MAKE) -C "testing/$(PACKAGE)-$(VERSION)/zziplib"
+ $(MAKE) -C "testing/$(PACKAGE)-$(VERSION)/zziplib" check
+
+clean-comp:
+ test ! -d testing || rm -r testing
+
+msvc :
+ mkdir bin
+ mkdir lib
+ mkdir include
+ mkdir include/zzip
+ cp $(srcdir)/msvc6/Release/*.exe bin/
+ cp $(srcdir)/msvc6/Release/*.dll bin/
+ cp $(srcdir)/msvc6/Release/*.lib lib/
+ cp $(srcdir)/zzip/*.h include/zzip/
+ zip -9r $(srcdir)/$(PACKAGE)-$(VERSION)-msvc6-bin.zip bin/
+ zip -9r $(srcdir)/$(PACKAGE)-$(VERSION)-msvc6-lib.zip lib/ include/
+ rm -r bin lib include
diff --git a/Build/source/libs/zziplib/Makefile.in b/Build/source/libs/zziplib/Makefile.in
new file mode 100644
index 00000000000..39702df9cef
--- /dev/null
+++ b/Build/source/libs/zziplib/Makefile.in
@@ -0,0 +1,743 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = .
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/config.h.in \
+ $(top_srcdir)/configure COPYING.LIB ChangeLog TODO \
+ uses/config.guess uses/config.sub uses/depcomp uses/install-sh \
+ uses/ltmain.sh uses/missing uses/mkinstalldirs
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_compile_check_sizeof.m4 \
+ $(top_srcdir)/m4/ac_set_default_paths_system.m4 \
+ $(top_srcdir)/m4/ac_sys_largefile_sensitive.m4 \
+ $(top_srcdir)/m4/acx_restrict.m4 \
+ $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \
+ $(top_srcdir)/m4/ax_cflags_no_writable_strings.m4 \
+ $(top_srcdir)/m4/ax_cflags_strict_prototypes.m4 \
+ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \
+ $(top_srcdir)/m4/ax_create_pkgconfig_info.m4 \
+ $(top_srcdir)/m4/ax_enable_builddir_uname.m4 \
+ $(top_srcdir)/m4/ax_expand_prefix.m4 \
+ $(top_srcdir)/m4/ax_maintainer_mode_auto_silent.m4 \
+ $(top_srcdir)/m4/ax_not_enable_frame_pointer.m4 \
+ $(top_srcdir)/m4/ax_prefix_config_h.m4 \
+ $(top_srcdir)/m4/ax_set_version_info.m4 \
+ $(top_srcdir)/m4/ax_spec_file.m4 \
+ $(top_srcdir)/m4/ax_spec_package_version.m4 \
+ $(top_srcdir)/m4/ax_warning_default_aclocaldir.m4 \
+ $(top_srcdir)/m4/ax_warning_default_pkgconfig.m4 \
+ $(top_srcdir)/m4/patch_libtool_on_darwin_zsh_overquoting.m4 \
+ $(top_srcdir)/m4/patch_libtool_sys_lib_search_path_spec.m4 \
+ $(top_srcdir)/m4/patch_libtool_to_add_host_cc.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno configure.status.lineno
+mkinstalldirs = $(SHELL) $(top_srcdir)/uses/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-exec-recursive install-info-recursive \
+ install-recursive installcheck-recursive installdirs-recursive \
+ pdf-recursive ps-recursive uninstall-info-recursive \
+ uninstall-recursive
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d $(distdir) \
+ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONFIG_FILES = @CONFIG_FILES@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LARGEFILE_CFLAGS = @LARGEFILE_CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+MKZIP = @MKZIP@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RELEASE_INFO = @RELEASE_INFO@
+RESOLVES = @RESOLVES@
+SDL = @SDL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+THREAD_SAFE = @THREAD_SAFE@
+VERSION = @VERSION@
+VERSION_INFO = @VERSION_INFO@
+XMLTO = @XMLTO@
+ZIPTESTS = @ZIPTESTS@
+ZLIB_INCL = @ZLIB_INCL@
+ZLIB_LDIR = @ZLIB_LDIR@
+ZLIB_VERSION = @ZLIB_VERSION@
+ZZIPLIB_LDFLAGS = @ZZIPLIB_LDFLAGS@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_AS = @ac_ct_AS@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DLLTOOL = @ac_ct_DLLTOOL@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_OBJDUMP = @ac_ct_OBJDUMP@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+aclocaldir = @aclocaldir@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_enable_builddir_sed = @ax_enable_builddir_sed@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+docdir = @docdir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pkgconfig_libdir = @pkgconfig_libdir@
+pkgconfig_libfile = @pkgconfig_libfile@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+AUTOMAKE_OPTIONS = 1.4 foreign dist-bzip2
+ACLOCAL_AMFLAGS = -I m4
+WANT_AUTOMAKE = 1.7
+WANT_AUTOCONF = 2.57
+DIST_SUBDIRS = zzip zzipwrap bins test docs SDL
+SUBDIRS = zzip zzipwrap bins test docs @SDL@
+MSVC8 = msvc8/README.TXT msvc8/zip.exe msvc8/test1.zip msvc8/test.zip \
+msvc8/zzdir.vcproj msvc8/zzipself.vcproj msvc8/zzip.vcproj \
+msvc8/zziplib.sln msvc8/zzipsetstub.sln msvc8/zzobfuscated.sln \
+msvc8/zziplib.vcproj msvc8/zzipsetstub.vcproj msvc8/zzobfuscated.vcproj \
+msvc8/zzcat.sln msvc8/zzipself.bat msvc8/zzip.sln \
+msvc8/zzcat.vcproj msvc8/zzipself.sln msvc8/zziptest.sln \
+msvc8/zzdir.sln msvc8/zzipself.txt msvc8/zziptest.vcproj
+
+MSVC7 = msvc7/pkzip.exe msvc7/test1.zip msvc7/test.zip \
+msvc7/zzdir.vcproj msvc7/zzipself.vcproj msvc7/zzip.vcproj \
+msvc7/zziplib.sln msvc7/zzipsetstub.sln msvc7/zzobfuscated.sln \
+msvc7/zziplib.vcproj msvc7/zzipsetstub.vcproj msvc7/zzobfuscated.vcproj \
+msvc7/zzcat.sln msvc7/zzipself.bat msvc7/zzip.sln \
+msvc7/zzcat.vcproj msvc7/zzipself.sln msvc7/zziptest.sln \
+msvc7/zzdir.sln msvc7/zzipself.txt msvc7/zziptest.vcproj
+
+MSVC6 = \
+msvc6/zzcat.dsp msvc6/zziplib.dsp msvc6/zzipwrap.dsp \
+msvc6/zzdir.dsp msvc6/zziplib.dsw msvc6/zzobfuscated.dsp \
+msvc6/zziptest.dsp msvc6/zzip.dsp
+
+EXTRA_DIST = zziplib.spec zzipback.sed Makefile.mk \
+ $(MSVC8) $(MSVC7) $(MSVC6) $(am__aclocal_m4_deps)
+
+PHONY = auto boottrap rpm doc docs man manpages htmpages sdl testsdl \
+ comp compats msvc6 msvc7
+
+all: config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
+ cd $(srcdir) && $(AUTOMAKE) --foreign \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+config.h: stamp-h1
+ @if test ! -f $@; then \
+ rm -f stamp-h1; \
+ $(MAKE) stamp-h1; \
+ else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+ @rm -f stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_srcdir) && $(AUTOHEADER)
+ rm -f stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f config.h stamp-h1
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ mkdir $(distdir)
+ $(mkdir_p) $(distdir)/$(top_srcdir) $(distdir)/$(top_srcdir)/m4 $(distdir)/m4 $(distdir)/msvc6 $(distdir)/msvc7 $(distdir)/msvc8 $(distdir)/uses
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(mkdir_p) "$(distdir)/$$subdir" \
+ || exit 1; \
+ distdir=`$(am__cd) $(distdir) && pwd`; \
+ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+ (cd $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$top_distdir" \
+ distdir="$$distdir/$$subdir" \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+ -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r $(distdir)
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && cd $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}'
+distuninstallcheck:
+ @cd $(distuninstallcheck_dir) \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile config.h
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr \
+ distclean-libtool distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \
+ check-am clean clean-generic clean-libtool clean-recursive \
+ ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \
+ dist-shar dist-tarZ dist-zip distcheck distclean \
+ distclean-generic distclean-hdr distclean-libtool \
+ distclean-recursive distclean-tags distcleancheck distdir \
+ distuninstallcheck dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-exec \
+ install-exec-am install-info install-info-am install-man \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ maintainer-clean-recursive mostlyclean mostlyclean-generic \
+ mostlyclean-libtool mostlyclean-recursive pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am uninstall-info-am
+
+
+# see Makefile.mk for the "make rpm" target
+rpm2: dist-bzip2 $(PACKAGE).spec
+ rpmbuild -ta $(PACKAGE)-$(VERSION).tar.bz2
+
+zzip.html zzip.xml zzip.pdf \
+doc docu clean-doc clean-docs clean-docu \
+man manpages htmpages unpack clean-unpack \
+omf install-omf install-doc install-sfnet install-man3 x :
+ (cd docs && $(MAKE) `basename $@`)
+
+sdl testsdl test-sdl install-sdl :
+ (cd SDL && $(MAKE) `basename $@`)
+
+check-test0 check-test1 check-zzdir check-zzcat \
+check-zzxor check-zzxordir check-zzxorcat \
+check-sfx check-readme : \
+ (cd test && $(MAKE) `basename $@`)
+docs : docu
+# ------------------------------------------------------------------------
+
+test-comp:
+ test ! -d testing || rm -r testing
+ mkdir testing
+ (cd testing && tar xzvf ../$(PACKAGE)-$(VERSION).tar.gz)
+ (cd "testing/$(PACKAGE)-$(VERSION)/zziplib" && sh configure)
+ $(MAKE) -C "testing/$(PACKAGE)-$(VERSION)/zziplib"
+ $(MAKE) -C "testing/$(PACKAGE)-$(VERSION)/zziplib" check
+
+clean-comp:
+ test ! -d testing || rm -r testing
+
+msvc :
+ mkdir bin
+ mkdir lib
+ mkdir include
+ mkdir include/zzip
+ cp $(srcdir)/msvc6/Release/*.exe bin/
+ cp $(srcdir)/msvc6/Release/*.dll bin/
+ cp $(srcdir)/msvc6/Release/*.lib lib/
+ cp $(srcdir)/zzip/*.h include/zzip/
+ zip -9r $(srcdir)/$(PACKAGE)-$(VERSION)-msvc6-bin.zip bin/
+ zip -9r $(srcdir)/$(PACKAGE)-$(VERSION)-msvc6-lib.zip lib/ include/
+ rm -r bin lib include
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Build/source/libs/zziplib/Makefile.mk b/Build/source/libs/zziplib/Makefile.mk
new file mode 100644
index 00000000000..084c042a64d
--- /dev/null
+++ b/Build/source/libs/zziplib/Makefile.mk
@@ -0,0 +1,73 @@
+PUB=pub/
+
+auto:
+ aclocal && autoconf && autoheader && automake
+
+boottrap:
+ rm -rf .deps .libs
+ rm -f config.guess config.sub stamp-h.in
+ rm -f install-sh ltconfig ltmain.sh depcomp mkinstalldirs
+ rm -f config.h config.h.in config.log config.cache configure
+ rm -f aclocal.m4 Makefile Makefile.in
+ aclocal
+ autoconf
+ autoheader
+ automake -a -c
+
+rpm: dist-bzip $(PACKAGE).spec
+ rpmbuild -ta $(PACKAGE)-$(VERSION).tar.bz2
+
+dist-bzip : dist-bzip2
+ $(MAKE) dist-bzip2-done
+dist-bzip2-done dist-done :
+ test -d $(PUB) || mkdir $(PUB)
+ @ echo cp $(BUILD)/$(PACKAGE)-$(VERSION).tar.bz2 $(PUB). \
+ ; cp $(BUILD)/$(PACKAGE)-$(VERSION).tar.bz2 $(PUB).
+snapshot:
+ $(MAKE) dist-bzip2 VERSION=`date +%Y.%m%d`
+distclean-done:
+ - rm -r *.d
+
+configsub :
+ cp ../savannah.config/config.guess uses/config.guess
+ cp ../savannah.config/config.sub uses/config.sub
+
+cf = $(cf_fedora)
+cf_debian = x86-linux1
+cf_fedora = x86-linux2
+cf_freebsd = x86-freebsd1
+cf_netbsd = x86-netbsd1
+cf_openbsd = x86-openbsd1
+cf_amd64 = amd64-linux1
+cf_alpha = usf-cf-alpha-linux-1
+cf_powermac = ppc-osx3
+cf_powerpc = openpower-linux1
+cf_sparc = sparc-solaris1
+cf_solaris = x86-solaris1
+cf_all = $(cf_debian) $(cf_fedora) $(cf_freebsd) $(cf_netbsd) $(cf_openbsd) \
+ $(cf_amd64) $(cf_alpha) $(cf_powerpc) $(cf_sparc) $(cf_solaris) \
+ $(cf_powermac)
+cf : cf-upload cf-system-all
+cf-upload: ; scp $(PUB)$(PACKAGE)-$(VERSION).tar.bz2 cf-shell.sf.net:
+cf-unpack: ; ssh cf-shell.sf.net \
+ "ssh $(cf) 'tar xjvf $(PACKAGE)-$(VERSION).tar.bz2'"
+cf-configure: ; ssh cf-shell.sf.net \
+ "ssh $(cf) 'uname -msr; cd $(PACKAGE)-$(VERSION) && sh configure'"
+cf-build: ; ssh cf-shell.sf.net \
+ "ssh $(cf) 'uname -msr; cd $(PACKAGE)-$(VERSION) && make'"
+cf-check: ; ssh cf-shell.sf.net \
+ "ssh $(cf) 'uname -msr; cd $(PACKAGE)-$(VERSION) && make check'"
+cf-system: ; ssh cf-shell.sf.net \
+ "ssh $(cf) 'uname -msr | sed s,^,====$(cf)====,'"
+cf-configure-all:
+ @ for cf in $(cf_all) ; do echo $(MAKE) cf-configure cf=$$cf \
+ ; sleep 1; $(MAKE) cf-configure cf=$$cf ; done
+cf-build-all:
+ @ for cf in $(cf_all) ; do echo $(MAKE) cf-build cf=$$cf \
+ ; sleep 1; $(MAKE) cf-build cf=$$cf ; done
+cf-check-all:
+ @ for cf in $(cf_all) ; do echo $(MAKE) cf-check cf=$$cf \
+ ; sleep 1; $(MAKE) cf-check cf=$$cf ; done
+cf-system-all:
+ @ for cf in $(cf_all) ; do echo $(MAKE) cf-configure cf=$$cf \
+ ; sleep 1 ; $(MAKE) cf-system cf=$$cf ; done
diff --git a/Build/source/libs/zziplib/README b/Build/source/libs/zziplib/README
new file mode 100644
index 00000000000..5668eda043a
--- /dev/null
+++ b/Build/source/libs/zziplib/README
@@ -0,0 +1,47 @@
+PROJECT
+ The zziplib provides read access to zipped files in a zip-archive,
+ using compression based solely on free algorithms provided by zlib.
+ It also provides a functionality to overlay the archive filesystem
+ with the filesystem of the operating system environment.
+
+AUTHOR
+ The project was originally written by Tomi Ollila, later largely
+ rewritten by Guido Draheim, and extended with contributions in
+ the years to follow. Guido Draheim <guidod@gmx.de> holds the full
+ copyright to the zziplib sources.
+
+COPYING
+ The zziplib may be used freely under the restrictions of the
+ GNU Lesser General Public License version 2 or later. Alternativly
+ the Mozilla Public license can be chosen. The sources are under
+ a dual license, as long as the MPL hint is not removed, the modified
+ files will be again under a dual license for the final recipient.
+
+LICENSING
+ If you can not use a dynalinked library according to LGPL rules,
+ then look at docs/copying.htm for a few hints. Generally the LGPL
+ has a way for staticlinking as well as the MPL has a way. Anyway,
+ special (paid) licenses can be negotiated with the copyright holder.
+
+HOMEPAGE
+ The zziplib project is hosted at SourceForge, the complete
+ documentation can be found at http://zziplib.sf.net - the
+ SourceForge servers are also used to distribute the sources
+ of the zziplib project. Releases are announced via the
+ freshmeat services on http://freshmeat.net/projects/zziplib
+
+INSTALLATION
+ The zziplib sources are built with gnu autotools and they should
+ be easy to install on unixish systems via the usual sequence of
+ `configure && make && make check && make install`. Many distributors
+ ship prebuilt packages e.g. in rpm format. Additionally there are
+ MSVC project files shipped along for usage with the Microsoft
+ VisualC series of compilers. There should be no problem either
+ when crosscompiling the zziplib for a third host platform.
+
+MAINTAINANCE
+ The zziplib library is intentionally a lightweight interface to
+ zip files. The author take patches but please consider to put
+ complex extensions into separate modules rather than implanting them
+ right into the core of the library engine. All Patches and Bug Reports
+ should be sent to Guido Draheim <guidod@gmx.de>.
diff --git a/Build/source/libs/zziplib/SDL/.deps/SDL_rwops_zzcat.Po b/Build/source/libs/zziplib/SDL/.deps/SDL_rwops_zzcat.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/SDL/.deps/SDL_rwops_zzcat.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/SDL/Makefile.am b/Build/source/libs/zziplib/SDL/Makefile.am
new file mode 100644
index 00000000000..9cd9db15802
--- /dev/null
+++ b/Build/source/libs/zziplib/SDL/Makefile.am
@@ -0,0 +1,68 @@
+AUTOMAKE_OPTIONS = 1.4 foreign
+AUTOTOOL_VERSION=autoconf-2.52 automake-1.5 libtool-1.4.2
+
+sdldir = ${pkgdatadir}/SDL
+sdl_DATA = SDL_rwops_zzip.c SDL_rwops_zzip.h
+
+EXTRA_DIST = $(sdl_DATA)
+check_PROGRAMS = zzcatsdl
+
+zzcatsdl_SOURCES = SDL_rwops_zzcat.c
+zzcatsdl_LDFLAGS = `sdl-config --libs` `./zzip-config --libs`
+zzcatsdl_cflags = `sdl-config --cflags` `./zzip-config --cflags`
+
+SDL_rwops_zzip.$(OBJEXT) : zzip-config @srcdir@/SDL_rwops_zzip.c
+ $(COMPILE) $(zzcatsdl_cflags) -c @srcdir@/SDL_rwops_zzip.c -o $@
+SDL_rwops_zzcat.$(OBJEXT) : zzip-config @srcdir@/SDL_rwops_zzcat.c
+ $(COMPILE) $(zzcatsdl_cflags) -c @srcdir@/SDL_rwops_zzcat.c -o $@
+zzcatsdl$(EXEEXT): SDL_rwops_zzip.$(OBJEXT) SDL_rwops_zzcat.$(OBJEXT)
+ $(LINK) SDL_rwops_zzip.$(OBJEXT) SDL_rwops_zzcat.$(OBJEXT) \
+ $(zzcatsdl_LDFLAGS) -o $@
+
+zzip-config : ../bins/zzip-config
+ sed -e 's:includedir=.*:includedir=..:' \
+ -e 's:libdir=.*:libdir=../zzip:' $? > $@
+ chmod +x $@
+
+test.zip : @top_srcdir@/test/test.zip
+ $(LN_S) $? $@
+testsdl test-sdl : test.zip zzcatsdl$(EXEEXT)
+ ./zzcatsdl$(EXEEXT) test/README > test.out
+ diff -q @top_srcdir@/README test.out && rm test.out
+
+sdl : all
+install-sdl : install-data # and not the binary
+
+### if it wouldn't be for the zzip-config then we could write it like this
+# zzcatsdl_SOURCES = SDL_rwops_zzcat.c SDL_rwops_zzip.c
+# zzcatsdl_LDADD = `sdl-config --libs` `zzip-config --libs`
+# CFLAGS = `sdl-config --cflags` `zzip-config --cflags`
+###
+
+CLEANFILES = *.pc *.omf
+# ----------------------------------------------------------------------
+# we do not install a library, so this about equivalent to some SDL.pc
+pkgconfigdir=$(libdir)/pkgconfig
+pkgconfig_HEADERS= zzip-sdl-config.pc zzip-sdl-rwops.pc
+ERRNULL= 2>/dev/null
+zzip-sdl-config.pc : Makefile
+ @ echo "prefix="`sdl-config --prefix $(ERRNULL)` >$@
+ @ echo "sdl_static_libs="`sdl-config --static-libs $(ERRNULL)` >>$@
+ @ echo "sdl_libs="`sdl-config --libs $(ERRNULL)` >>$@
+ @ echo "sdl_cflags="`sdl-config --cflags $(ERRNULL)` >>$@
+ @ echo " " >>$@
+ @ echo "Name: zzip-sdl-config" >>$@
+ @ echo "Version: "`sdl-config --version $(ERRNULL)` >>$@
+ @ echo "Description: SDL Config (for ZZipLib)" >>$@
+ echo 'Libs: $${sdl_libs}' >>$@
+ echo 'Cflags: $${sdl_cflags}' >>$@
+
+zzip-sdl-rwops.pc : Makefile
+ @ echo 'zzipdatadir=$(pkgdatadir)' >$@
+ @ echo 'zzipsdlrwops=$${zzipdatadir}/SDL' >>$@
+ @ echo " " >>$@
+ @ echo "Name: zzip-sdl-rwops" >>$@
+ @ echo "Version: $(VERSION)" >>$@
+ @ echo "Description: SDL_rwops for ZZipLib" >>$@
+ echo 'Requires: zzip-sdl-config, zziplib' >>$@
+ echo 'Cflags: -I$${zzipsdlrwops}' >>$@
diff --git a/Build/source/libs/zziplib/SDL/Makefile.in b/Build/source/libs/zziplib/SDL/Makefile.in
new file mode 100644
index 00000000000..7bbad54f184
--- /dev/null
+++ b/Build/source/libs/zziplib/SDL/Makefile.in
@@ -0,0 +1,588 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+check_PROGRAMS = zzcatsdl$(EXEEXT)
+subdir = SDL
+DIST_COMMON = $(pkgconfig_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_compile_check_sizeof.m4 \
+ $(top_srcdir)/m4/ac_set_default_paths_system.m4 \
+ $(top_srcdir)/m4/ac_sys_largefile_sensitive.m4 \
+ $(top_srcdir)/m4/acx_restrict.m4 \
+ $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \
+ $(top_srcdir)/m4/ax_cflags_no_writable_strings.m4 \
+ $(top_srcdir)/m4/ax_cflags_strict_prototypes.m4 \
+ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \
+ $(top_srcdir)/m4/ax_create_pkgconfig_info.m4 \
+ $(top_srcdir)/m4/ax_enable_builddir_uname.m4 \
+ $(top_srcdir)/m4/ax_expand_prefix.m4 \
+ $(top_srcdir)/m4/ax_maintainer_mode_auto_silent.m4 \
+ $(top_srcdir)/m4/ax_not_enable_frame_pointer.m4 \
+ $(top_srcdir)/m4/ax_prefix_config_h.m4 \
+ $(top_srcdir)/m4/ax_set_version_info.m4 \
+ $(top_srcdir)/m4/ax_spec_file.m4 \
+ $(top_srcdir)/m4/ax_spec_package_version.m4 \
+ $(top_srcdir)/m4/ax_warning_default_aclocaldir.m4 \
+ $(top_srcdir)/m4/ax_warning_default_pkgconfig.m4 \
+ $(top_srcdir)/m4/patch_libtool_on_darwin_zsh_overquoting.m4 \
+ $(top_srcdir)/m4/patch_libtool_sys_lib_search_path_spec.m4 \
+ $(top_srcdir)/m4/patch_libtool_to_add_host_cc.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/uses/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am_zzcatsdl_OBJECTS = SDL_rwops_zzcat.$(OBJEXT)
+zzcatsdl_OBJECTS = $(am_zzcatsdl_OBJECTS)
+zzcatsdl_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/uses/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(zzcatsdl_SOURCES)
+DIST_SOURCES = $(zzcatsdl_SOURCES)
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(sdldir)" "$(DESTDIR)$(pkgconfigdir)"
+sdlDATA_INSTALL = $(INSTALL_DATA)
+DATA = $(sdl_DATA)
+pkgconfigHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(pkgconfig_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONFIG_FILES = @CONFIG_FILES@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LARGEFILE_CFLAGS = @LARGEFILE_CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+MKZIP = @MKZIP@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RELEASE_INFO = @RELEASE_INFO@
+RESOLVES = @RESOLVES@
+SDL = @SDL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+THREAD_SAFE = @THREAD_SAFE@
+VERSION = @VERSION@
+VERSION_INFO = @VERSION_INFO@
+XMLTO = @XMLTO@
+ZIPTESTS = @ZIPTESTS@
+ZLIB_INCL = @ZLIB_INCL@
+ZLIB_LDIR = @ZLIB_LDIR@
+ZLIB_VERSION = @ZLIB_VERSION@
+ZZIPLIB_LDFLAGS = @ZZIPLIB_LDFLAGS@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_AS = @ac_ct_AS@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DLLTOOL = @ac_ct_DLLTOOL@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_OBJDUMP = @ac_ct_OBJDUMP@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+aclocaldir = @aclocaldir@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_enable_builddir_sed = @ax_enable_builddir_sed@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+docdir = @docdir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pkgconfig_libdir = @pkgconfig_libdir@
+pkgconfig_libfile = @pkgconfig_libfile@
+# ----------------------------------------------------------------------
+# we do not install a library, so this about equivalent to some SDL.pc
+pkgconfigdir = $(libdir)/pkgconfig
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+AUTOMAKE_OPTIONS = 1.4 foreign
+AUTOTOOL_VERSION = autoconf-2.52 automake-1.5 libtool-1.4.2
+sdldir = ${pkgdatadir}/SDL
+sdl_DATA = SDL_rwops_zzip.c SDL_rwops_zzip.h
+EXTRA_DIST = $(sdl_DATA)
+zzcatsdl_SOURCES = SDL_rwops_zzcat.c
+zzcatsdl_LDFLAGS = `sdl-config --libs` `./zzip-config --libs`
+zzcatsdl_cflags = `sdl-config --cflags` `./zzip-config --cflags`
+
+### if it wouldn't be for the zzip-config then we could write it like this
+# zzcatsdl_SOURCES = SDL_rwops_zzcat.c SDL_rwops_zzip.c
+# zzcatsdl_LDADD = `sdl-config --libs` `zzip-config --libs`
+# CFLAGS = `sdl-config --cflags` `zzip-config --cflags`
+###
+CLEANFILES = *.pc *.omf
+pkgconfig_HEADERS = zzip-sdl-config.pc zzip-sdl-rwops.pc
+ERRNULL = 2>/dev/null
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign SDL/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign SDL/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SDL_rwops_zzcat.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+install-sdlDATA: $(sdl_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(sdldir)" || $(mkdir_p) "$(DESTDIR)$(sdldir)"
+ @list='$(sdl_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(sdlDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(sdldir)/$$f'"; \
+ $(sdlDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(sdldir)/$$f"; \
+ done
+
+uninstall-sdlDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sdl_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(sdldir)/$$f'"; \
+ rm -f "$(DESTDIR)$(sdldir)/$$f"; \
+ done
+install-pkgconfigHEADERS: $(pkgconfig_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgconfigdir)" || $(mkdir_p) "$(DESTDIR)$(pkgconfigdir)"
+ @list='$(pkgconfig_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(pkgconfigHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ $(pkgconfigHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+
+uninstall-pkgconfigHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgconfig_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+check: check-am
+all-am: Makefile $(DATA) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(sdldir)" "$(DESTDIR)$(pkgconfigdir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pkgconfigHEADERS install-sdlDATA
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-pkgconfigHEADERS \
+ uninstall-sdlDATA
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean \
+ clean-checkPROGRAMS clean-generic clean-libtool ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-exec install-exec-am install-info \
+ install-info-am install-man install-pkgconfigHEADERS \
+ install-sdlDATA install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-info-am uninstall-pkgconfigHEADERS \
+ uninstall-sdlDATA
+
+
+SDL_rwops_zzip.$(OBJEXT) : zzip-config @srcdir@/SDL_rwops_zzip.c
+ $(COMPILE) $(zzcatsdl_cflags) -c @srcdir@/SDL_rwops_zzip.c -o $@
+SDL_rwops_zzcat.$(OBJEXT) : zzip-config @srcdir@/SDL_rwops_zzcat.c
+ $(COMPILE) $(zzcatsdl_cflags) -c @srcdir@/SDL_rwops_zzcat.c -o $@
+zzcatsdl$(EXEEXT): SDL_rwops_zzip.$(OBJEXT) SDL_rwops_zzcat.$(OBJEXT)
+ $(LINK) SDL_rwops_zzip.$(OBJEXT) SDL_rwops_zzcat.$(OBJEXT) \
+ $(zzcatsdl_LDFLAGS) -o $@
+
+zzip-config : ../bins/zzip-config
+ sed -e 's:includedir=.*:includedir=..:' \
+ -e 's:libdir=.*:libdir=../zzip:' $? > $@
+ chmod +x $@
+
+test.zip : @top_srcdir@/test/test.zip
+ $(LN_S) $? $@
+testsdl test-sdl : test.zip zzcatsdl$(EXEEXT)
+ ./zzcatsdl$(EXEEXT) test/README > test.out
+ diff -q @top_srcdir@/README test.out && rm test.out
+
+sdl : all
+install-sdl : install-data # and not the binary
+zzip-sdl-config.pc : Makefile
+ @ echo "prefix="`sdl-config --prefix $(ERRNULL)` >$@
+ @ echo "sdl_static_libs="`sdl-config --static-libs $(ERRNULL)` >>$@
+ @ echo "sdl_libs="`sdl-config --libs $(ERRNULL)` >>$@
+ @ echo "sdl_cflags="`sdl-config --cflags $(ERRNULL)` >>$@
+ @ echo " " >>$@
+ @ echo "Name: zzip-sdl-config" >>$@
+ @ echo "Version: "`sdl-config --version $(ERRNULL)` >>$@
+ @ echo "Description: SDL Config (for ZZipLib)" >>$@
+ echo 'Libs: $${sdl_libs}' >>$@
+ echo 'Cflags: $${sdl_cflags}' >>$@
+
+zzip-sdl-rwops.pc : Makefile
+ @ echo 'zzipdatadir=$(pkgdatadir)' >$@
+ @ echo 'zzipsdlrwops=$${zzipdatadir}/SDL' >>$@
+ @ echo " " >>$@
+ @ echo "Name: zzip-sdl-rwops" >>$@
+ @ echo "Version: $(VERSION)" >>$@
+ @ echo "Description: SDL_rwops for ZZipLib" >>$@
+ echo 'Requires: zzip-sdl-config, zziplib' >>$@
+ echo 'Cflags: -I$${zzipsdlrwops}' >>$@
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Build/source/libs/zziplib/SDL/SDL_rwops_zzcat.c b/Build/source/libs/zziplib/SDL/SDL_rwops_zzcat.c
new file mode 100644
index 00000000000..8df2685a289
--- /dev/null
+++ b/Build/source/libs/zziplib/SDL/SDL_rwops_zzcat.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2001 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB License
+ *
+ * (this example uses errno which might not be multithreaded everywhere)
+ */
+
+#include <SDL_rwops_zzip.h>
+#include <stdlib.h> /* exit */
+
+/* mostly a copy from zzcat.c */
+
+int main (int argc, char** argv)
+{
+ static const char usage[] =
+ " zzcat <file>... \n"
+ " - prints the file to stdout. the file can be a normal file\n"
+ " or an inflated part of a zip-archive \n"
+ ;
+
+ int argn;
+ if (argc <= 1)
+ {
+ printf (usage);
+ exit (0);
+ }
+
+ for (argn=1; argn < argc; argn++)
+ {
+ SDL_RWops* rwops;
+
+ rwops = SDL_RWFromZZIP (argv[argn], "rb");
+ if (! rwops)
+ {
+ perror (argv[argn]);
+ continue;
+ }else{
+ char buf[17];
+ int n;
+
+ /* read chunks of 16 bytes into buf and print them to stdout */
+ while (0 < (n = SDL_RWread(rwops, buf, 16, 1)))
+ {
+ buf[n] = '\0';
+# ifdef STDOUT_FILENO
+ write (STDOUT_FILENO, buf, n);
+# else
+ fwrite (buf, 1, n, stdout);
+# endif
+ }
+
+ if (n == -1)
+ perror (argv[argn]);
+
+ SDL_RWclose (rwops);
+ }
+ }
+
+ return 0;
+}
+
+
+
diff --git a/Build/source/libs/zziplib/SDL/SDL_rwops_zzip.c b/Build/source/libs/zziplib/SDL/SDL_rwops_zzip.c
new file mode 100644
index 00000000000..b273a811470
--- /dev/null
+++ b/Build/source/libs/zziplib/SDL/SDL_rwops_zzip.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2001 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB License
+ *
+ * (this example uses errno which might not be multithreaded everywhere)
+ */
+
+#include <SDL_rwops_zzip.h>
+#include <zzip/zzip.h>
+#include <string.h> /* strchr */
+
+/* MSVC can not take a casted variable as an lvalue ! */
+#define SDL_RWOPS_ZZIP_DATA(_context) \
+ ((_context)->hidden.unknown.data1)
+#define SDL_RWOPS_ZZIP_FILE(_context) (ZZIP_FILE*) \
+ ((_context)->hidden.unknown.data1)
+
+static int _zzip_seek(SDL_RWops *context, int offset, int whence)
+{
+ return zzip_seek(SDL_RWOPS_ZZIP_FILE(context), offset, whence);
+}
+
+static int _zzip_read(SDL_RWops *context, void *ptr, int size, int maxnum)
+{
+ return zzip_read(SDL_RWOPS_ZZIP_FILE(context), ptr, size*maxnum) / size;
+}
+
+static int _zzip_write(SDL_RWops *context, const void *ptr, int size, int num)
+{
+ return 0; /* ignored */
+}
+
+static int _zzip_close(SDL_RWops *context)
+{
+ if (! context) return 0; /* may be SDL_RWclose is called by atexit */
+
+ zzip_close (SDL_RWOPS_ZZIP_FILE(context));
+ SDL_FreeRW (context);
+ return 0;
+}
+
+SDL_RWops *SDL_RWFromZZIP(const char* file, const char* mode)
+{
+ register SDL_RWops* rwops;
+ register ZZIP_FILE* zzip_file;
+
+ if (! strchr (mode, 'r'))
+ return SDL_RWFromFile(file, mode);
+
+ zzip_file = zzip_fopen (file, mode);
+ if (! zzip_file) return 0;
+
+ rwops = SDL_AllocRW ();
+ if (! rwops) { errno=ENOMEM; zzip_close (zzip_file); return 0; }
+
+ SDL_RWOPS_ZZIP_DATA(rwops) = zzip_file;
+ rwops->read = _zzip_read;
+ rwops->write = _zzip_write;
+ rwops->seek = _zzip_seek;
+ rwops->close = _zzip_close;
+ return rwops;
+}
diff --git a/Build/source/libs/zziplib/SDL/SDL_rwops_zzip.h b/Build/source/libs/zziplib/SDL/SDL_rwops_zzip.h
new file mode 100644
index 00000000000..1a2d188de83
--- /dev/null
+++ b/Build/source/libs/zziplib/SDL/SDL_rwops_zzip.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2001 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB License
+ *
+ * You should be able to drop it in the place of a SDL_RWFromFile. Then
+ * go to X/share/myapp and do `cd graphics && zip -9r ../graphics.zip .`
+ * and rename the graphics/ subfolder - and still all your files
+ * are found: a filepath like X/shared/graphics/game/greetings.bmp
+ * will open X/shared/graphics.zip and return the zipped file
+ * game/greetings.bmp in the zip-archive (for reading that is).
+ *
+ */
+
+#ifndef _SDL_RWops_ZZIP_h
+#define _SDL_RWops_ZZIP_h
+
+#include <SDL_rwops.h>
+
+#ifndef ZZIP_NO_DECLSPEC
+#define ZZIP_DECLSPEC
+#else /* use DECLSPEC from SDL/begin_code.h */
+#define ZZIP_DECLSPEC DECLSPEC
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern ZZIP_DECLSPEC
+SDL_RWops *SDL_RWFromZZIP(const char* file, const char* mode);
+
+#ifdef __cplusplus
+} /* extern C */
+#endif
+
+#endif
diff --git a/Build/source/libs/zziplib/SDL/zzip-sdl-config.pc b/Build/source/libs/zziplib/SDL/zzip-sdl-config.pc
new file mode 100644
index 00000000000..7e54d7ec1dd
--- /dev/null
+++ b/Build/source/libs/zziplib/SDL/zzip-sdl-config.pc
@@ -0,0 +1,10 @@
+prefix=/usr
+sdl_static_libs=-L/usr/lib -lSDL -lpthread -lm -ldl -L/usr/X11R6/lib -lX11 -lXext -laa
+sdl_libs=-L/usr/lib -lSDL -lpthread
+sdl_cflags=-I/usr/include/SDL -D_REENTRANT
+
+Name: zzip-sdl-config
+Version: 1.2.9
+Description: SDL Config (for ZZipLib)
+Libs: ${sdl_libs}
+Cflags: ${sdl_cflags}
diff --git a/Build/source/libs/zziplib/SDL/zzip-sdl-rwops.pc b/Build/source/libs/zziplib/SDL/zzip-sdl-rwops.pc
new file mode 100644
index 00000000000..8d7858def0c
--- /dev/null
+++ b/Build/source/libs/zziplib/SDL/zzip-sdl-rwops.pc
@@ -0,0 +1,8 @@
+zzipdatadir=/usr/local/share/zziplib
+zzipsdlrwops=${zzipdatadir}/SDL
+
+Name: zzip-sdl-rwops
+Version: 2006.0807
+Description: SDL_rwops for ZZipLib
+Requires: zzip-sdl-config, zziplib
+Cflags: -I${zzipsdlrwops}
diff --git a/Build/source/libs/zziplib/TODO b/Build/source/libs/zziplib/TODO
new file mode 100644
index 00000000000..2bc5edfd6ea
--- /dev/null
+++ b/Build/source/libs/zziplib/TODO
@@ -0,0 +1,54 @@
+
+- Check the CRC value at the end of read... and add more error codes.
+
+- Do more test. Currently use only with tested "friendly" archives.
+ This is also related to usages of zziplib in virus detection
+ code which should better have a hardened library code. That does
+ also include inflate interface code to need the most testing.
+
+- the buffer reusage code was not strictly multithreading. It should
+ be fixed by now but it would be better to have an automatic test
+ routine to check reentrancy/multithreaded functionality.
+
+- Sligthly More documentation. With the generation of man pages and
+ multiple pages for the website, it does already look acceptable.
+ It should still get better of course - kinda newbie friendly *g*
+
+KNOWN PROBLEMS
+
+The win32 compilers need each a different config.h derivate that
+matches both the headers shipped with the compiler and installed
+with updates of the SDK. There is no autoconfigure on win32 as
+that - unless you install some unix tools along.
+
+The sparc-sun-solaris2.* will utter warnings for "char subscript"
+which is caused by isdigit() from ctype.h - this will NOT FIX as
+it is only in the example source code and we want to keep those
+lean and mean to make them easy to adopt by developers.
+
+The hppa1.1-hp-hpux10.20 did show spurious problems of making
+shared libraries - this may well fix with an update of the
+libtool package, the libtool 1.4 is dated 2001/04/24
+
+There are spurious reports of users on win32 platforms that tell
+of some problems with a specific zip file they have but it was
+not possible so far to recreate an environment abroad to show
+the problem too. One can not say if that is due some general
+instability out of DLL hell, or if there is a bug hiding somewhere.
+Please send all those zip files to the maintainer, perhaps it
+can help to find the real cause (I doubt it is in zziplib, but..)
+
+TESTED PLATFORMS
+sparc-sun-solaris2.6/gcc2.95.3
+sparc-sun-solaris2.8/gcc2.95.3
+hppa1.1-hp-hpux10.20
+i686-mandrake-linux-9.0/gcc3.2
+i686-mandrake-linux-9.1/gcc3.2.2
+i686-debian-linux-2.2/gcc2.95.2
+i386-unknown-freebsd4.7/gcc2.95.4 (formerly with wrapwrap)
+powerpc-apple-darwin5.5 (formerly with wrapwrap)
+alphaev67-unknown-linux-gnu/gcc2.95.4 (that's a 64bit platform)
+i386-ms-win32/msvc6
+i386-ms-win32/msvc7
+i386-ms-win32/mingw+msys
+... and probably a lot of others not known to the maintainer.
diff --git a/Build/source/libs/zziplib/aclocal.m4 b/Build/source/libs/zziplib/aclocal.m4
new file mode 100644
index 00000000000..39b8e7d8b68
--- /dev/null
+++ b/Build/source/libs/zziplib/aclocal.m4
@@ -0,0 +1,7278 @@
+# generated automatically by aclocal 1.9.6 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+
+# serial 48 AC_PROG_LIBTOOL
+
+
+# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)
+# -----------------------------------------------------------
+# If this macro is not defined by Autoconf, define it here.
+m4_ifdef([AC_PROVIDE_IFELSE],
+ [],
+ [m4_define([AC_PROVIDE_IFELSE],
+ [m4_ifdef([AC_PROVIDE_$1],
+ [$2], [$3])])])
+
+
+# AC_PROG_LIBTOOL
+# ---------------
+AC_DEFUN([AC_PROG_LIBTOOL],
+[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl
+dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX
+dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX.
+ AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [AC_LIBTOOL_CXX],
+ [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX
+ ])])
+dnl And a similar setup for Fortran 77 support
+ AC_PROVIDE_IFELSE([AC_PROG_F77],
+ [AC_LIBTOOL_F77],
+ [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77
+])])
+
+dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly.
+dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run
+dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both.
+ AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+ [AC_LIBTOOL_GCJ],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+ [AC_LIBTOOL_GCJ],
+ [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],
+ [AC_LIBTOOL_GCJ],
+ [ifdef([AC_PROG_GCJ],
+ [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+ ifdef([A][M_PROG_GCJ],
+ [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+ ifdef([LT_AC_PROG_GCJ],
+ [define([LT_AC_PROG_GCJ],
+ defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])])
+])])# AC_PROG_LIBTOOL
+
+
+# _AC_PROG_LIBTOOL
+# ----------------
+AC_DEFUN([_AC_PROG_LIBTOOL],
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Prevent multiple expansion
+define([AC_PROG_LIBTOOL], [])
+])# _AC_PROG_LIBTOOL
+
+
+# AC_LIBTOOL_SETUP
+# ----------------
+AC_DEFUN([AC_LIBTOOL_SETUP],
+[AC_PREREQ(2.50)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+
+AC_REQUIRE([AC_PROG_LN_S])dnl
+AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+AC_REQUIRE([AC_OBJEXT])dnl
+AC_REQUIRE([AC_EXEEXT])dnl
+dnl
+
+AC_LIBTOOL_SYS_MAX_CMD_LEN
+AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+AC_LIBTOOL_OBJDIR
+
+AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+_LT_AC_PROG_ECHO_BACKSLASH
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g']
+
+# Same as above, but do not quote variable references.
+[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g']
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+AC_CHECK_TOOL(AR, ar, false)
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(STRIP, strip, :)
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ AC_PATH_MAGIC
+ fi
+ ;;
+esac
+
+AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+enable_win32_dll=yes, enable_win32_dll=no)
+
+AC_ARG_ENABLE([libtool-lock],
+ [AC_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+AC_ARG_WITH([pic],
+ [AC_HELP_STRING([--with-pic],
+ [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+ [pic_mode="$withval"],
+ [pic_mode=default])
+test -z "$pic_mode" && pic_mode=default
+
+# Use C for the default configuration in the libtool script
+tagname=
+AC_LIBTOOL_LANG_C_CONFIG
+_LT_AC_TAGCONFIG
+])# AC_LIBTOOL_SETUP
+
+
+# _LT_AC_SYS_COMPILER
+# -------------------
+AC_DEFUN([_LT_AC_SYS_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_AC_SYS_COMPILER
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+AC_DEFUN([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+ case $cc_temp in
+ compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+ distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+])
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+AC_DEFUN([_LT_COMPILER_BOILERPLATE],
+[ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+AC_DEFUN([_LT_LINKER_BOILERPLATE],
+[ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+])# _LT_LINKER_BOILERPLATE
+
+
+# _LT_AC_SYS_LIBPATH_AIX
+# ----------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX],
+[AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_AC_SYS_LIBPATH_AIX
+
+
+# _LT_AC_SHELL_INIT(ARG)
+# ----------------------
+AC_DEFUN([_LT_AC_SHELL_INIT],
+[ifdef([AC_DIVERSION_NOTICE],
+ [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+ [AC_DIVERT_PUSH(NOTICE)])
+$1
+AC_DIVERT_POP
+])# _LT_AC_SHELL_INIT
+
+
+# _LT_AC_PROG_ECHO_BACKSLASH
+# --------------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
+[_LT_AC_SHELL_INIT([
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+ ;;
+esac
+
+echo=${ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X[$]1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+[$]*
+EOF
+ exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if (echo_test_string=`eval $cmd`) 2>/dev/null &&
+ echo_test_string=`eval $cmd` &&
+ (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+ then
+ break
+ fi
+ done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ if test "X$echo" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ echo='print -r'
+ elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+ else
+ # Try using printf.
+ echo='printf %s\n'
+ if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ echo="$CONFIG_SHELL [$]0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$CONFIG_SHELL [$]0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+ if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "[$]0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ echo=echo
+ fi
+ fi
+ fi
+ fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+ ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(ECHO)
+])])# _LT_AC_PROG_ECHO_BACKSLASH
+
+
+# _LT_AC_LOCK
+# -----------
+AC_DEFUN([_LT_AC_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+ [AC_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE="32"
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE="64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ ppc*-*linux*|powerpc*-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+ [AC_LANG_PUSH(C)
+ AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+ AC_LANG_POP])
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+sparc*-*solaris*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*) LD="${LD-ld} -m elf64_sparc" ;;
+ *) LD="${LD-ld} -64" ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+ AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+ AC_CHECK_TOOL(AS, as, false)
+ AC_CHECK_TOOL(OBJDUMP, objdump, false)
+ ;;
+ ])
+esac
+
+need_locks="$enable_libtool_lock"
+
+])# _LT_AC_LOCK
+
+
+# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION],
+[AC_REQUIRE([LT_AC_PROG_SED])
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$3"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ fi
+ $rm conftest*
+])
+
+if test x"[$]$2" = xyes; then
+ ifelse([$5], , :, [$5])
+else
+ ifelse([$6], , :, [$6])
+fi
+])# AC_LIBTOOL_COMPILER_OPTION
+
+
+# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [ACTION-SUCCESS], [ACTION-FAILURE])
+# ------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_LINKER_OPTION],
+[AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $3"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&AS_MESSAGE_LOG_FD
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ else
+ $2=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+ ifelse([$4], , :, [$4])
+else
+ ifelse([$5], , :, [$5])
+fi
+])# AC_LIBTOOL_LINKER_OPTION
+
+
+# AC_LIBTOOL_SYS_MAX_CMD_LEN
+# --------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN],
+[# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+ i=0
+ teststring="ABCD"
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \
+ = "XX$teststring") >/dev/null 2>&1 &&
+ new_result=`expr "X$teststring" : ".*" 2>&1` &&
+ lt_cv_sys_max_cmd_len=$new_result &&
+ test $i != 17 # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on massive
+ # amounts of additional arguments before passing them to the linker.
+ # It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ ;;
+ esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+ AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+ AC_MSG_RESULT(none)
+fi
+])# AC_LIBTOOL_SYS_MAX_CMD_LEN
+
+
+# _LT_AC_CHECK_DLFCN
+# ------------------
+AC_DEFUN([_LT_AC_CHECK_DLFCN],
+[AC_CHECK_HEADERS(dlfcn.h)dnl
+])# _LT_AC_CHECK_DLFCN
+
+
+# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ---------------------------------------------------------------------
+AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+ [$4]
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ exit (status);
+}]
+EOF
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) $1 ;;
+ x$lt_dlneed_uscore) $2 ;;
+ x$lt_dlunknown|x*) $3 ;;
+ esac
+ else :
+ # compilation failed
+ $3
+ fi
+fi
+rm -fr conftest*
+])# _LT_AC_TRY_DLOPEN_SELF
+
+
+# AC_LIBTOOL_DLOPEN_SELF
+# ----------------------
+AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ])
+ ;;
+
+ *)
+ AC_CHECK_FUNC([shl_load],
+ [lt_cv_dlopen="shl_load"],
+ [AC_CHECK_LIB([dld], [shl_load],
+ [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
+ [AC_CHECK_FUNC([dlopen],
+ [lt_cv_dlopen="dlopen"],
+ [AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+ [AC_CHECK_LIB([svld], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+ [AC_CHECK_LIB([dld], [dld_link],
+ [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
+ ])
+ ])
+ ])
+ ])
+ ])
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ AC_CACHE_CHECK([whether a program can dlopen itself],
+ lt_cv_dlopen_self, [dnl
+ _LT_AC_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+ lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+ ])
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+ lt_cv_dlopen_self_static, [dnl
+ _LT_AC_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+ lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
+ ])
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+])# AC_LIBTOOL_DLOPEN_SELF
+
+
+# AC_LIBTOOL_PROG_CC_C_O([TAGNAME])
+# ---------------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler
+AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O],
+[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+ [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+ [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+ fi
+ fi
+ chmod u+w . 2>&AS_MESSAGE_LOG_FD
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+])
+])# AC_LIBTOOL_PROG_CC_C_O
+
+
+# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME])
+# -----------------------------------------
+# Check to see if we can do hard links to lock some files if needed
+AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS],
+[AC_REQUIRE([_LT_AC_LOCK])dnl
+
+hard_links="nottested"
+if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ AC_MSG_CHECKING([if we can lock with hard links])
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ AC_MSG_RESULT([$hard_links])
+ if test "$hard_links" = no; then
+ AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS
+
+
+# AC_LIBTOOL_OBJDIR
+# -----------------
+AC_DEFUN([AC_LIBTOOL_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+])# AC_LIBTOOL_OBJDIR
+
+
+# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME])
+# ----------------------------------------------
+# Check hardcoding attributes.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_AC_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \
+ test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \
+ test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+ test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then
+ # Linking always hardcodes the temporary library directory.
+ _LT_AC_TAGVAR(hardcode_action, $1)=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ _LT_AC_TAGVAR(hardcode_action, $1)=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ _LT_AC_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH
+
+
+# AC_LIBTOOL_SYS_LIB_STRIP
+# ------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP],
+[striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+fi
+ ;;
+ *)
+ AC_MSG_RESULT([no])
+ ;;
+ esac
+fi
+])# AC_LIBTOOL_SYS_LIB_STRIP
+
+
+# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER],
+[AC_MSG_CHECKING([dynamic linker characteristics])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[[01]] | aix4.[[01]].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[[45]]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[[123]]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[[89]] | openbsd2.[[89]].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+])# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+
+
+# _LT_AC_TAGCONFIG
+# ----------------
+AC_DEFUN([_LT_AC_TAGCONFIG],
+[AC_ARG_WITH([tags],
+ [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@],
+ [include additional configurations @<:@automatic@:>@])],
+ [tagnames="$withval"])
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+ if test ! -f "${ofile}"; then
+ AC_MSG_WARN([output file `$ofile' does not exist])
+ fi
+
+ if test -z "$LTCC"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+ if test -z "$LTCC"; then
+ AC_MSG_WARN([output file `$ofile' does not look like a libtool script])
+ else
+ AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile'])
+ fi
+ fi
+ if test -z "$LTCFLAGS"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`"
+ fi
+
+ # Extract list of available tagged configurations in $ofile.
+ # Note that this assumes the entire list is on one line.
+ available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for tagname in $tagnames; do
+ IFS="$lt_save_ifs"
+ # Check whether tagname contains only valid characters
+ case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in
+ "") ;;
+ *) AC_MSG_ERROR([invalid tag name: $tagname])
+ ;;
+ esac
+
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+ then
+ AC_MSG_ERROR([tag name \"$tagname\" already exists])
+ fi
+
+ # Update the list of available tags.
+ if test -n "$tagname"; then
+ echo appending configuration tag \"$tagname\" to $ofile
+
+ case $tagname in
+ CXX)
+ if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ AC_LIBTOOL_LANG_CXX_CONFIG
+ else
+ tagname=""
+ fi
+ ;;
+
+ F77)
+ if test -n "$F77" && test "X$F77" != "Xno"; then
+ AC_LIBTOOL_LANG_F77_CONFIG
+ else
+ tagname=""
+ fi
+ ;;
+
+ GCJ)
+ if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+ AC_LIBTOOL_LANG_GCJ_CONFIG
+ else
+ tagname=""
+ fi
+ ;;
+
+ RC)
+ AC_LIBTOOL_LANG_RC_CONFIG
+ ;;
+
+ *)
+ AC_MSG_ERROR([Unsupported tag name: $tagname])
+ ;;
+ esac
+
+ # Append the new tag name to the list of available tags.
+ if test -n "$tagname" ; then
+ available_tags="$available_tags $tagname"
+ fi
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ # Now substitute the updated list of available tags.
+ if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+ mv "${ofile}T" "$ofile"
+ chmod +x "$ofile"
+ else
+ rm -f "${ofile}T"
+ AC_MSG_ERROR([unable to update list of available tagged configurations.])
+ fi
+fi
+])# _LT_AC_TAGCONFIG
+
+
+# AC_LIBTOOL_DLOPEN
+# -----------------
+# enable checks for dlopen support
+AC_DEFUN([AC_LIBTOOL_DLOPEN],
+ [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_DLOPEN
+
+
+# AC_LIBTOOL_WIN32_DLL
+# --------------------
+# declare package support for building win32 DLLs
+AC_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_BEFORE([$0], [AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_WIN32_DLL
+
+
+# AC_ENABLE_SHARED([DEFAULT])
+# ---------------------------
+# implement the --enable-shared flag
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_SHARED],
+[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([shared],
+ [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+ [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_shared=]AC_ENABLE_SHARED_DEFAULT)
+])# AC_ENABLE_SHARED
+
+
+# AC_DISABLE_SHARED
+# -----------------
+# set the default shared flag to --disable-shared
+AC_DEFUN([AC_DISABLE_SHARED],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_SHARED(no)
+])# AC_DISABLE_SHARED
+
+
+# AC_ENABLE_STATIC([DEFAULT])
+# ---------------------------
+# implement the --enable-static flag
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_STATIC],
+[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([static],
+ [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+ [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_static=]AC_ENABLE_STATIC_DEFAULT)
+])# AC_ENABLE_STATIC
+
+
+# AC_DISABLE_STATIC
+# -----------------
+# set the default static flag to --disable-static
+AC_DEFUN([AC_DISABLE_STATIC],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_STATIC(no)
+])# AC_DISABLE_STATIC
+
+
+# AC_ENABLE_FAST_INSTALL([DEFAULT])
+# ---------------------------------
+# implement the --enable-fast-install flag
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_FAST_INSTALL],
+[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([fast-install],
+ [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+ [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT)
+])# AC_ENABLE_FAST_INSTALL
+
+
+# AC_DISABLE_FAST_INSTALL
+# -----------------------
+# set the default to --disable-fast-install
+AC_DEFUN([AC_DISABLE_FAST_INSTALL],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_FAST_INSTALL(no)
+])# AC_DISABLE_FAST_INSTALL
+
+
+# AC_LIBTOOL_PICMODE([MODE])
+# --------------------------
+# implement the --with-pic flag
+# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
+AC_DEFUN([AC_LIBTOOL_PICMODE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+pic_mode=ifelse($#,1,$1,default)
+])# AC_LIBTOOL_PICMODE
+
+
+# AC_PROG_EGREP
+# -------------
+# This is predefined starting with Autoconf 2.54, so this conditional
+# definition can be removed once we require Autoconf 2.54 or later.
+m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP],
+[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep],
+ [if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi])
+ EGREP=$ac_cv_prog_egrep
+ AC_SUBST([EGREP])
+])])
+
+
+# AC_PATH_TOOL_PREFIX
+# -------------------
+# find a file program which can recognise shared library
+AC_DEFUN([AC_PATH_TOOL_PREFIX],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] | ?:[\\/]*])
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word. This closes a longstanding sh security hole.
+ ac_dummy="ifelse([$2], , $PATH, [$2])"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$1; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ AC_MSG_RESULT($MAGIC_CMD)
+else
+ AC_MSG_RESULT(no)
+fi
+])# AC_PATH_TOOL_PREFIX
+
+
+# AC_PATH_MAGIC
+# -------------
+# find a file program which can recognise a shared library
+AC_DEFUN([AC_PATH_MAGIC],
+[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+ else
+ MAGIC_CMD=:
+ fi
+fi
+])# AC_PATH_MAGIC
+
+
+# AC_PROG_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([AC_PROG_LD],
+[AC_ARG_WITH([gnu-ld],
+ [AC_HELP_STRING([--with-gnu-ld],
+ [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+ [test "$withval" = no || with_gnu_ld=yes],
+ [with_gnu_ld=no])
+AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by $CC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]]* | ?:[[\\/]]*)
+ re_direlt='/[[^/]][[^/]]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_PROG_LD_GNU
+])# AC_PROG_LD
+
+
+# AC_PROG_LD_GNU
+# --------------
+AC_DEFUN([AC_PROG_LD_GNU],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# AC_PROG_LD_GNU
+
+
+# AC_PROG_LD_RELOAD_FLAG
+# ----------------------
+# find reload flag for linker
+# -- PORTME Some linkers may need a different reload flag.
+AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+ lt_cv_ld_reload_flag,
+ [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+])# AC_PROG_LD_RELOAD_FLAG
+
+
+# AC_DEPLIBS_CHECK_METHOD
+# -----------------------
+# how to check for library dependencies
+# -- PORTME fill in with the dynamic library characteristics
+AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
+[AC_CACHE_CHECK([how to recognise dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[[45]]*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump'.
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | kfreebsd*-gnu | dragonfly*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix3*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+nto-qnx*)
+ lt_cv_deplibs_check_method=unknown
+ ;;
+
+openbsd*)
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+])# AC_DEPLIBS_CHECK_METHOD
+
+
+# AC_PROG_NM
+# ----------
+# find the pathname to a BSD-compatible name lister
+AC_DEFUN([AC_PROG_NM],
+[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM,
+[if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ lt_nm_to_check="${ac_tool_prefix}nm"
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm="$ac_dir/$lt_tmp_nm"
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+ done
+ test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi])
+NM="$lt_cv_path_NM"
+])# AC_PROG_NM
+
+
+# AC_CHECK_LIBM
+# -------------
+# check for math library
+AC_DEFUN([AC_CHECK_LIBM],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
+ # These system don't have libm, or don't need it
+ ;;
+*-ncr-sysv4.3*)
+ AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+ AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+ ;;
+*)
+ AC_CHECK_LIB(m, cos, LIBM="-lm")
+ ;;
+esac
+])# AC_CHECK_LIBM
+
+
+# AC_LIBLTDL_CONVENIENCE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl convenience library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-convenience to the configure arguments. Note that
+# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided,
+# it is assumed to be `libltdl'. LIBLTDL will be prefixed with
+# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/'
+# (note the single quotes!). If your package is not flat and you're not
+# using automake, define top_builddir and top_srcdir appropriately in
+# the Makefiles.
+AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+ case $enable_ltdl_convenience in
+ no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+ "") enable_ltdl_convenience=yes
+ ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+ esac
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+ LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+ # For backwards non-gettext consistent compatibility...
+ INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_CONVENIENCE
+
+
+# AC_LIBLTDL_INSTALLABLE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl installable library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-install to the configure arguments. Note that
+# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided,
+# and an installed libltdl is not found, it is assumed to be `libltdl'.
+# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with
+# '${top_srcdir}/' (note the single quotes!). If your package is not
+# flat and you're not using automake, define top_builddir and top_srcdir
+# appropriately in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+ AC_CHECK_LIB(ltdl, lt_dlinit,
+ [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+ [if test x"$enable_ltdl_install" = xno; then
+ AC_MSG_WARN([libltdl not installed, but installation disabled])
+ else
+ enable_ltdl_install=yes
+ fi
+ ])
+ if test x"$enable_ltdl_install" = x"yes"; then
+ ac_configure_args="$ac_configure_args --enable-ltdl-install"
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+ LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+ else
+ ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+ LIBLTDL="-lltdl"
+ LTDLINCL=
+ fi
+ # For backwards non-gettext consistent compatibility...
+ INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_INSTALLABLE
+
+
+# AC_LIBTOOL_CXX
+# --------------
+# enable support for C++ libraries
+AC_DEFUN([AC_LIBTOOL_CXX],
+[AC_REQUIRE([_LT_AC_LANG_CXX])
+])# AC_LIBTOOL_CXX
+
+
+# _LT_AC_LANG_CXX
+# ---------------
+AC_DEFUN([_LT_AC_LANG_CXX],
+[AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([_LT_AC_PROG_CXXCPP])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX])
+])# _LT_AC_LANG_CXX
+
+# _LT_AC_PROG_CXXCPP
+# ------------------
+AC_DEFUN([_LT_AC_PROG_CXXCPP],
+[
+AC_REQUIRE([AC_PROG_CXX])
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ AC_PROG_CXXCPP
+fi
+])# _LT_AC_PROG_CXXCPP
+
+# AC_LIBTOOL_F77
+# --------------
+# enable support for Fortran 77 libraries
+AC_DEFUN([AC_LIBTOOL_F77],
+[AC_REQUIRE([_LT_AC_LANG_F77])
+])# AC_LIBTOOL_F77
+
+
+# _LT_AC_LANG_F77
+# ---------------
+AC_DEFUN([_LT_AC_LANG_F77],
+[AC_REQUIRE([AC_PROG_F77])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77])
+])# _LT_AC_LANG_F77
+
+
+# AC_LIBTOOL_GCJ
+# --------------
+# enable support for GCJ libraries
+AC_DEFUN([AC_LIBTOOL_GCJ],
+[AC_REQUIRE([_LT_AC_LANG_GCJ])
+])# AC_LIBTOOL_GCJ
+
+
+# _LT_AC_LANG_GCJ
+# ---------------
+AC_DEFUN([_LT_AC_LANG_GCJ],
+[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[],
+ [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[],
+ [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])],
+ [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])],
+ [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ])
+])# _LT_AC_LANG_GCJ
+
+
+# AC_LIBTOOL_RC
+# -------------
+# enable support for Windows resource files
+AC_DEFUN([AC_LIBTOOL_RC],
+[AC_REQUIRE([LT_AC_PROG_RC])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC])
+])# AC_LIBTOOL_RC
+
+
+# AC_LIBTOOL_LANG_C_CONFIG
+# ------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG])
+AC_DEFUN([_LT_AC_LANG_C_CONFIG],
+[lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}\n'
+
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+AC_LIBTOOL_DLOPEN_SELF
+
+# Report which library types will actually be built
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_C_CONFIG
+
+
+# AC_LIBTOOL_LANG_CXX_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)])
+AC_DEFUN([_LT_AC_LANG_CXX_CONFIG],
+[AC_LANG_PUSH(C++)
+AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([_LT_AC_PROG_CXXCPP])
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Dependencies to place before and after the object being linked:
+_LT_AC_TAGVAR(predep_objects, $1)=
+_LT_AC_TAGVAR(postdep_objects, $1)=
+_LT_AC_TAGVAR(predeps, $1)=
+_LT_AC_TAGVAR(postdeps, $1)=
+_LT_AC_TAGVAR(compiler_lib_search_path, $1)=
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+ $as_unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+ $as_unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+else
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+fi
+
+if test "$GXX" = yes; then
+ # Set up default GNU C++ configuration
+
+ AC_PROG_LD
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test "$with_gnu_ld" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='${wl}'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+ grep 'no-whole-archive' > /dev/null; then
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+_LT_AC_TAGVAR(ld_shlibs, $1)=yes
+case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_AC_TAGVAR(archive_cmds, $1)=''
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ if test "$GXX" = yes; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ else
+ # We have old collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(always_export_symbols, $1)=no
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ if test "$GXX" = yes ; then
+ lt_int_apple_cc_single_mod=no
+ output_verbose_link_cmd='echo'
+ if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
+ lt_int_apple_cc_single_mod=yes
+ fi
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ fi
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ fi
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ freebsd[[12]]*)
+ # C++ shared libraries reported to be fairly broken before switch to ELF
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ freebsd-elf*)
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ ;;
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+ gnu*)
+ ;;
+ hpux9*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+ ;;
+ *)
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ interix3*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+ fi
+ fi
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+ esac
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc*)
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ ;;
+ pgCC*)
+ # Portland Group C++ compiler
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ esac
+ ;;
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ m88k*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ openbsd*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ fi
+ output_verbose_link_cmd='echo'
+ ;;
+ osf3*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~
+ $rm $lib.exp'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ psos*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The C++ compiler is used as linker so we must use $wl
+ # flag to pass the commands to the underlying system
+ # linker. We must also pass each convience library through
+ # to the system linker between allextract/defaultextract.
+ # The C++ compiler will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract'
+ ;;
+ esac
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ output_verbose_link_cmd='echo'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+ if $CC --version | grep -v '^2\.7' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ fi
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+ fi
+ ;;
+ esac
+ ;;
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ # So that behaviour is only enabled if SCOABSPATH is set to a
+ # non-empty value in the environment. Most likely only useful for
+ # creating official distributions of packages.
+ # This is a hack until libtool officially supports absolute path
+ # names for shared libraries.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+esac
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_AC_TAGVAR(GCC, $1)="$GXX"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+AC_LIBTOOL_POSTDEP_PREDEP($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+])# AC_LIBTOOL_LANG_CXX_CONFIG
+
+# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME])
+# ------------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library. It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+ifelse([$1],[],[cat > conftest.$ac_ext <<EOF
+int a;
+void foo (void) { a = 0; }
+EOF
+],[$1],[CXX],[cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+EOF
+],[$1],[F77],[cat > conftest.$ac_ext <<EOF
+ subroutine foo
+ implicit none
+ integer*4 a
+ a=0
+ return
+ end
+EOF
+],[$1],[GCJ],[cat > conftest.$ac_ext <<EOF
+public class foo {
+ private int a;
+ public void bar (void) {
+ a = 0;
+ }
+};
+EOF
+])
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ # The `*' in the case matches for architectures that use `case' in
+ # $output_verbose_cmd can trigger glob expansion during the loop
+ # eval without this substitution.
+ output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
+
+ for p in `eval $output_verbose_link_cmd`; do
+ case $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" \
+ || test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p in
+ -L* | -R*)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then
+ _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+ else
+ _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$_LT_AC_TAGVAR(postdeps, $1)"; then
+ _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}"
+ else
+ _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${prev}${p}"
+ fi
+ fi
+ ;;
+
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ if test -z "$_LT_AC_TAGVAR(predep_objects, $1)"; then
+ _LT_AC_TAGVAR(predep_objects, $1)="$p"
+ else
+ _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p"
+ fi
+ else
+ if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then
+ _LT_AC_TAGVAR(postdep_objects, $1)="$p"
+ else
+ _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$rm -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+ifelse([$1],[CXX],
+[case $host_os in
+interix3*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ _LT_AC_TAGVAR(predep_objects,$1)=
+ _LT_AC_TAGVAR(postdep_objects,$1)=
+ _LT_AC_TAGVAR(postdeps,$1)=
+ ;;
+
+solaris*)
+ case $cc_basename in
+ CC*)
+ # Adding this requires a known-good setup of shared libraries for
+ # Sun compiler versions before 5.6, else PIC objects from an old
+ # archive will be linked into the output, leading to subtle bugs.
+ _LT_AC_TAGVAR(postdeps,$1)='-lCstd -lCrun'
+ ;;
+ esac
+ ;;
+esac
+])
+
+case " $_LT_AC_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+])# AC_LIBTOOL_POSTDEP_PREDEP
+
+# AC_LIBTOOL_LANG_F77_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)])
+AC_DEFUN([_LT_AC_LANG_F77_CONFIG],
+[AC_REQUIRE([AC_PROG_F77])
+AC_LANG_PUSH(Fortran 77)
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code=" subroutine t\n return\n end\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code=" program t\n end\n"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+_LT_AC_TAGVAR(GCC, $1)="$G77"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_F77_CONFIG
+
+
+# AC_LIBTOOL_LANG_GCJ_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)])
+AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_GCJ_CONFIG
+
+
+# AC_LIBTOOL_LANG_RC_CONFIG
+# -------------------------
+# Ensure that the configuration vars for the Windows resource compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)])
+AC_DEFUN([_LT_AC_LANG_RC_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_RC_CONFIG
+
+
+# AC_LIBTOOL_CONFIG([TAGNAME])
+# ----------------------------
+# If TAGNAME is not passed, then create an initial libtool script
+# with a default configuration from the untagged config vars. Otherwise
+# add code to config.status for appending the configuration named by
+# TAGNAME from the matching tagged config vars.
+AC_DEFUN([AC_LIBTOOL_CONFIG],
+[# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ _LT_AC_TAGVAR(compiler, $1) \
+ _LT_AC_TAGVAR(CC, $1) \
+ _LT_AC_TAGVAR(LD, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \
+ _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \
+ _LT_AC_TAGVAR(old_archive_cmds, $1) \
+ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \
+ _LT_AC_TAGVAR(predep_objects, $1) \
+ _LT_AC_TAGVAR(postdep_objects, $1) \
+ _LT_AC_TAGVAR(predeps, $1) \
+ _LT_AC_TAGVAR(postdeps, $1) \
+ _LT_AC_TAGVAR(compiler_lib_search_path, $1) \
+ _LT_AC_TAGVAR(archive_cmds, $1) \
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1) \
+ _LT_AC_TAGVAR(postinstall_cmds, $1) \
+ _LT_AC_TAGVAR(postuninstall_cmds, $1) \
+ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \
+ _LT_AC_TAGVAR(allow_undefined_flag, $1) \
+ _LT_AC_TAGVAR(no_undefined_flag, $1) \
+ _LT_AC_TAGVAR(export_symbols_cmds, $1) \
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \
+ _LT_AC_TAGVAR(hardcode_automatic, $1) \
+ _LT_AC_TAGVAR(module_cmds, $1) \
+ _LT_AC_TAGVAR(module_expsym_cmds, $1) \
+ _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \
+ _LT_AC_TAGVAR(exclude_expsyms, $1) \
+ _LT_AC_TAGVAR(include_expsyms, $1); do
+
+ case $var in
+ _LT_AC_TAGVAR(old_archive_cmds, $1) | \
+ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \
+ _LT_AC_TAGVAR(archive_cmds, $1) | \
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \
+ _LT_AC_TAGVAR(module_cmds, $1) | \
+ _LT_AC_TAGVAR(module_expsym_cmds, $1) | \
+ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \
+ _LT_AC_TAGVAR(export_symbols_cmds, $1) | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\[$]0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'`
+ ;;
+ esac
+
+ifelse([$1], [],
+ [cfgfile="${ofile}T"
+ trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+ $rm -f "$cfgfile"
+ AC_MSG_NOTICE([creating $ofile])],
+ [cfgfile="$ofile"])
+
+ cat <<__EOF__ >> "$cfgfile"
+ifelse([$1], [],
+[#! $SHELL
+
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e 1s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG],
+[# ### BEGIN LIBTOOL TAG CONFIG: $tagname])
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_[]_LT_AC_TAGVAR(compiler, $1)
+
+# Is the compiler the GNU C compiler?
+with_gcc=$_LT_AC_TAGVAR(GCC, $1)
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_[]_LT_AC_TAGVAR(LD, $1)
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1)
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1)
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1)
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1)
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1)
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1)
+archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1)
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1)
+module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1)
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1)
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1)
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1)
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1)
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1)
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1)
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1)
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1)
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1)
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1)
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1)
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1)
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1)
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1)
+
+# Symbols that must always be exported.
+include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1)
+
+ifelse([$1],[],
+[# ### END LIBTOOL CONFIG],
+[# ### END LIBTOOL TAG CONFIG: $tagname])
+
+__EOF__
+
+ifelse([$1],[], [
+ case $host_os in
+ aix3*)
+ cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+EOF
+ ;;
+ esac
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" || \
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+])
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+])# AC_LIBTOOL_CONFIG
+
+
+# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI],
+[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+
+_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+
+ AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+ lt_cv_prog_compiler_rtti_exceptions,
+ [-fno-rtti -fno-exceptions], [],
+ [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI
+
+
+# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+# ---------------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_NM])
+AC_REQUIRE([AC_OBJEXT])
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[[BCDT]]'
+ ;;
+cygwin* | mingw* | pw32*)
+ symcode='[[ABCDGISTW]]'
+ ;;
+hpux*) # Its linker distinguishes data from code symbols
+ if test "$host_cpu" = ia64; then
+ symcode='[[ABCDEGRST]]'
+ fi
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ ;;
+linux*)
+ if test "$host_cpu" = ia64; then
+ symcode='[[ABCDGIRSTW]]'
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[[BCDEGRST]]'
+ ;;
+osf*)
+ symcode='[[BCDEGQRST]]'
+ ;;
+solaris*)
+ symcode='[[BDRT]]'
+ ;;
+sco3.2v5*)
+ symcode='[[DT]]'
+ ;;
+sysv4.2uw2*)
+ symcode='[[DT]]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[[ABDT]]'
+ ;;
+sysv4)
+ symcode='[[DFNSTU]]'
+ ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+ if AC_TRY_EVAL(ac_compile); then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if grep ' nm_test_var$' "$nlist" >/dev/null; then
+ if grep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+ cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[[]] =
+{
+EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+ cat <<\EOF >> conftest.$ac_ext
+ {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_save_LIBS="$LIBS"
+ lt_save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+ pipe_works=yes
+ fi
+ LIBS="$lt_save_LIBS"
+ CFLAGS="$lt_save_CFLAGS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+ cat conftest.$ac_ext >&5
+ fi
+ rm -f conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ AC_MSG_RESULT(failed)
+else
+ AC_MSG_RESULT(ok)
+fi
+]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+
+
+# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME])
+# ---------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC],
+[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=
+
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+ ifelse([$1],[CXX],[
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | os2* | pw32*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix4* | aix5*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ esac
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ if test "$host_cpu" != ia64; then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ fi
+ ;;
+ aCC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ icpc* | ecpc*)
+ # Intel C++
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgCC*)
+ # Portland Group C++ compiler.
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd*)
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+],
+[
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC (with -KPIC) is the default.
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ newsos6)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ linux*)
+ case $cc_basename in
+ icc* | ecc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ ccc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All Alpha code is PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All OSF/1 code is PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ solaris*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ unicos*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+
+ uts4*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)])
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then
+ AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works],
+ _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1),
+ [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [],
+ [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in
+ "" | " "*) ;;
+ *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+ esac],
+ [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\"
+AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+ _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1),
+ $lt_tmp_static_flag,
+ [],
+ [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=])
+])
+
+
+# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME])
+# ------------------------------------
+# See if the linker supports building shared libraries.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS],
+[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ifelse([$1],[CXX],[
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ case $host_os in
+ aix4* | aix5*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+ ;;
+ cygwin* | mingw*)
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ *)
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+],[
+ runpath_var=
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+ _LT_AC_TAGVAR(archive_cmds, $1)=
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)=
+ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ _LT_AC_TAGVAR(thread_safe_flag_spec, $1)=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+ _LT_AC_TAGVAR(hardcode_automatic, $1)=no
+ _LT_AC_TAGVAR(module_cmds, $1)=
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)=
+ _LT_AC_TAGVAR(always_export_symbols, $1)=no
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ _LT_AC_TAGVAR(include_expsyms, $1)=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ _LT_CC_BASENAME([$compiler])
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(always_export_symbols, $1)=no
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ interix3*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+
+ if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then
+ runpath_var=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_AC_TAGVAR(archive_cmds, $1)=''
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ else
+ # We have old collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ # see comment about different semantics on the GNU ld section
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ bsdi[[45]]*)
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true'
+ # FIXME: Should let the user specify the lib program.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ freebsd1*)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ newsos6)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ openbsd*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ else
+ case $host_os in
+ openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ else
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ solaris*)
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl, iff we do not link with $LD.
+ # Luckily, gcc supports the same syntax we need for Sun Studio.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ case $wlarc in
+ '')
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;;
+ *)
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
+ esac ;;
+ esac
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ ;;
+ motorola)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4.3*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*)
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+ # Assume -lc should be added
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $_LT_AC_TAGVAR(archive_cmds, $1) in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+ pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+ if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
+ then
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ else
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+ fi
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)])
+ ;;
+ esac
+ fi
+ ;;
+esac
+])# AC_LIBTOOL_PROG_LD_SHLIBS
+
+
+# _LT_AC_FILE_LTDLL_C
+# -------------------
+# Be careful that the start marker always follows a newline.
+AC_DEFUN([_LT_AC_FILE_LTDLL_C], [
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# # ifdef __CYGWIN32__
+# # define __CYGWIN__ __CYGWIN32__
+# # endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+# __hDllInstance_base = hInst;
+# return TRUE;
+# }
+# /* ltdll.c ends here */
+])# _LT_AC_FILE_LTDLL_C
+
+
+# _LT_AC_TAGVAR(VARNAME, [TAGNAME])
+# ---------------------------------
+AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])])
+
+
+# old names
+AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL])
+AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+AC_DEFUN([AM_PROG_LD], [AC_PROG_LD])
+AC_DEFUN([AM_PROG_NM], [AC_PROG_NM])
+
+# This is just to silence aclocal about the macro not being used
+ifelse([AC_DISABLE_FAST_INSTALL])
+
+AC_DEFUN([LT_AC_PROG_GCJ],
+[AC_CHECK_TOOL(GCJ, gcj, no)
+ test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+ AC_SUBST(GCJFLAGS)
+])
+
+AC_DEFUN([LT_AC_PROG_RC],
+[AC_CHECK_TOOL(RC, windres, no)
+])
+
+# NOTE: This macro has been submitted for inclusion into #
+# GNU Autoconf as AC_PROG_SED. When it is available in #
+# a released version of Autoconf we should remove this #
+# macro and use it instead. #
+# LT_AC_PROG_SED
+# --------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible. Prefer GNU sed if found.
+AC_DEFUN([LT_AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f $lt_ac_sed && continue
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test $lt_ac_count -gt 10 && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test $lt_ac_count -gt $lt_ac_max; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+])
+SED=$lt_cv_path_SED
+AC_MSG_RESULT([$SED])
+])
+
+# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION so it can be traced.
+# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+ [AM_AUTOMAKE_VERSION([1.9.6])])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 7
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])
+AC_SUBST([$1_FALSE])
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
+ [$1], CXX, [depcc="$CXX" am_compiler_list=],
+ [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 3
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # So let's grep whole file.
+ if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. FIXME. This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 12
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.58])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+# test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" &&
+ test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES(CC)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+])
+])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $1 | $1:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+AC_DEFUN([AM_MAINTAINER_MODE],
+[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+ dnl maintainer-mode is disabled by default
+ AC_ARG_ENABLE(maintainer-mode,
+[ --enable-maintainer-mode enable make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer],
+ USE_MAINTAINER_MODE=$enableval,
+ USE_MAINTAINER_MODE=no)
+ AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+ AM_CONDITIONAL(MAINTAINER_MODE, [test $USE_MAINTAINER_MODE = yes])
+ MAINT=$MAINTAINER_MODE_TRUE
+ AC_SUBST(MAINT)dnl
+]
+)
+
+AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+ am__include=include
+ am__quote=
+ _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ fi
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise.
+#
+# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories
+# created by `make install' are always world readable, even if the
+# installer happens to have an overly restrictive umask (e.g. 077).
+# This was a mistake. There are at least two reasons why we must not
+# use `-m 0755':
+# - it causes special bits like SGID to be ignored,
+# - it may be too restrictive (some setups expect 775 directories).
+#
+# Do not use -m 0755 and let people choose whatever they expect by
+# setting umask.
+#
+# We cannot accept any implementation of `mkdir' that recognizes `-p'.
+# Some implementations (such as Solaris 8's) are not thread-safe: if a
+# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c'
+# concurrently, both version can detect that a/ is missing, but only
+# one can create it and the other will error out. Consequently we
+# restrict ourselves to GNU make (using the --version option ensures
+# this.)
+AC_DEFUN([AM_PROG_MKDIR_P],
+[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+ # We used to keeping the `.' as first argument, in order to
+ # allow $(mkdir_p) to be used without argument. As in
+ # $(mkdir_p) $(somedir)
+ # where $(somedir) is conditionally defined. However this is wrong
+ # for two reasons:
+ # 1. if the package is installed by a user who cannot write `.'
+ # make install will fail,
+ # 2. the above comment should most certainly read
+ # $(mkdir_p) $(DESTDIR)$(somedir)
+ # so it does not work when $(somedir) is undefined and
+ # $(DESTDIR) is not.
+ # To support the latter case, we have to write
+ # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
+ # so the `.' trick is pointless.
+ mkdir_p='mkdir -p --'
+else
+ # On NextStep and OpenStep, the `mkdir' command does not
+ # recognize any option. It will interpret all options as
+ # directories to create, and then abort because `.' already
+ # exists.
+ for d in ./-p ./--version;
+ do
+ test -d $d && rmdir $d
+ done
+ # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
+ if test -f "$ac_aux_dir/mkinstalldirs"; then
+ mkdir_p='$(mkinstalldirs)'
+ else
+ mkdir_p='$(install_sh) -d'
+ fi
+fi
+AC_SUBST([mkdir_p])])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [m4_case([$1], [ustar],, [pax],,
+ [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar;
+ do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([m4/ac_compile_check_sizeof.m4])
+m4_include([m4/ac_set_default_paths_system.m4])
+m4_include([m4/ac_sys_largefile_sensitive.m4])
+m4_include([m4/acx_restrict.m4])
+m4_include([m4/ax_cflags_gcc_option.m4])
+m4_include([m4/ax_cflags_no_writable_strings.m4])
+m4_include([m4/ax_cflags_strict_prototypes.m4])
+m4_include([m4/ax_cflags_warn_all.m4])
+m4_include([m4/ax_create_pkgconfig_info.m4])
+m4_include([m4/ax_enable_builddir_uname.m4])
+m4_include([m4/ax_expand_prefix.m4])
+m4_include([m4/ax_maintainer_mode_auto_silent.m4])
+m4_include([m4/ax_not_enable_frame_pointer.m4])
+m4_include([m4/ax_prefix_config_h.m4])
+m4_include([m4/ax_set_version_info.m4])
+m4_include([m4/ax_spec_file.m4])
+m4_include([m4/ax_spec_package_version.m4])
+m4_include([m4/ax_warning_default_aclocaldir.m4])
+m4_include([m4/ax_warning_default_pkgconfig.m4])
+m4_include([m4/patch_libtool_on_darwin_zsh_overquoting.m4])
+m4_include([m4/patch_libtool_sys_lib_search_path_spec.m4])
+m4_include([m4/patch_libtool_to_add_host_cc.m4])
diff --git a/Build/source/libs/zziplib/bins/.deps/unzip-mem.Po b/Build/source/libs/zziplib/bins/.deps/unzip-mem.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/.deps/unzip-mem.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/bins/.deps/unzzip.Po b/Build/source/libs/zziplib/bins/.deps/unzzip.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/.deps/unzzip.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/bins/.deps/unzzipcat-mem.Po b/Build/source/libs/zziplib/bins/.deps/unzzipcat-mem.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/.deps/unzzipcat-mem.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/bins/.deps/unzzipcat-seeko.Po b/Build/source/libs/zziplib/bins/.deps/unzzipcat-seeko.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/.deps/unzzipcat-seeko.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/bins/.deps/unzzipcat.Po b/Build/source/libs/zziplib/bins/.deps/unzzipcat.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/.deps/unzzipcat.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/bins/.deps/unzzipdir-mem.Po b/Build/source/libs/zziplib/bins/.deps/unzzipdir-mem.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/.deps/unzzipdir-mem.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/bins/.deps/unzzipdir.Po b/Build/source/libs/zziplib/bins/.deps/unzzipdir.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/.deps/unzzipdir.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/bins/.deps/zzcat.Po b/Build/source/libs/zziplib/bins/.deps/zzcat.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/.deps/zzcat.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/bins/.deps/zzdir.Po b/Build/source/libs/zziplib/bins/.deps/zzdir.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/.deps/zzdir.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/bins/.deps/zzip.Po b/Build/source/libs/zziplib/bins/.deps/zzip.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/.deps/zzip.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/bins/.deps/zziptest.Po b/Build/source/libs/zziplib/bins/.deps/zziptest.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/.deps/zziptest.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/bins/.deps/zzobfuscated.Po b/Build/source/libs/zziplib/bins/.deps/zzobfuscated.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/.deps/zzobfuscated.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/bins/.deps/zzxorcat.Po b/Build/source/libs/zziplib/bins/.deps/zzxorcat.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/.deps/zzxorcat.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/bins/.deps/zzxorcopy.Po b/Build/source/libs/zziplib/bins/.deps/zzxorcopy.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/.deps/zzxorcopy.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/bins/.deps/zzxordir.Po b/Build/source/libs/zziplib/bins/.deps/zzxordir.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/.deps/zzxordir.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/bins/Makefile.am b/Build/source/libs/zziplib/bins/Makefile.am
new file mode 100644
index 00000000000..ed9429d35df
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/Makefile.am
@@ -0,0 +1,56 @@
+AUTOMAKE_OPTIONS = 1.4 foreign
+AUTOTOOL_VERSION=autoconf-2.52 automake-1.5 libtool-1.4.2
+DEFAULT_INCLUDES = # nothing - no default of -I. -I$(srcdir)
+DEFS = @DEFS@ -I$(top_builddir) -I$(top_srcdir) # also for automake 1.4
+
+bin_PROGRAMS = zzcat zzdir zzxorcat zzxordir zzxorcopy \
+ unzzip unzzipdir unzzipcat unzzipcat-seeko \
+ unzzipdir-mem unzzipcat-mem unzip-mem
+noinst_PROGRAMS = zziptest zzobfuscated zzip
+aclocaldir = $(datadir)/aclocal
+aclocal_DATA = zziplib.m4
+#
+VERSION_INFO=@VERSION_INFO@
+RELEASE_INFO=@RELEASE_INFO@
+THREAD_SAFE=@THREAD_SAFE@
+#
+
+WCC10_CLEAN = *.obj *.lk1 *.mk1 *.mk *.sym *.tgt
+
+EXTRA_DIST = $(aclocal_DATA)
+CLEANFILES = $(WCC10_CLEAN)
+
+unzzip_LDFLAGS = @ZZIPLIB_LDFLAGS@
+unzzip_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+zzip_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzip_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+zziptest_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zziptest_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+zzcat_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzcat_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+zzdir_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzdir_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+zzxorcat_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzxorcat_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+zzxordir_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzxordir_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+zzobfuscated_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzobfuscated_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+
+# these use the simplified mmapped disk version
+unzzipdir_LDFLAGS = @ZZIPLIB_LDFLAGS@
+unzzipdir_LDADD = ../zzip/libzzipmmapped.la @RESOLVES@ -lz
+unzzipcat_LDFLAGS = @ZZIPLIB_LDFLAGS@
+unzzipcat_LDADD = ../zzip/libzzipmmapped.la @RESOLVES@ -lz
+unzzipdir_mem_LDFLAGS = @ZZIPLIB_LDFLAGS@
+unzzipdir_mem_LDADD = ../zzip/libzzipmmapped.la @RESOLVES@ -lz
+unzzipcat_mem_LDFLAGS = @ZZIPLIB_LDFLAGS@
+unzzipcat_mem_LDADD = ../zzip/libzzipmmapped.la @RESOLVES@ -lz
+unzip_mem_LDFLAGS = @ZZIPLIB_LDFLAGS@
+unzip_mem_LDADD = ../zzip/libzzipmmapped.la @RESOLVES@ -lz
+# and this uses the simplified fseeko stdio version
+unzzipcat_seeko_LDFLAGS = @ZZIPLIB_LDFLAGS@
+unzzipcat_seeko_LDADD = ../zzip/libzzipfseeko.la @RESOLVES@ -lz
+
+../zzip/libzzip.la : @top_srcdir@/zzip/*.c
+ (cd ../zzip && $(MAKE) `basename $@`)
diff --git a/Build/source/libs/zziplib/bins/Makefile.in b/Build/source/libs/zziplib/bins/Makefile.in
new file mode 100644
index 00000000000..42380ca40b7
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/Makefile.in
@@ -0,0 +1,689 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+bin_PROGRAMS = zzcat$(EXEEXT) zzdir$(EXEEXT) zzxorcat$(EXEEXT) \
+ zzxordir$(EXEEXT) zzxorcopy$(EXEEXT) unzzip$(EXEEXT) \
+ unzzipdir$(EXEEXT) unzzipcat$(EXEEXT) unzzipcat-seeko$(EXEEXT) \
+ unzzipdir-mem$(EXEEXT) unzzipcat-mem$(EXEEXT) \
+ unzip-mem$(EXEEXT)
+noinst_PROGRAMS = zziptest$(EXEEXT) zzobfuscated$(EXEEXT) \
+ zzip$(EXEEXT)
+subdir = bins
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_compile_check_sizeof.m4 \
+ $(top_srcdir)/m4/ac_set_default_paths_system.m4 \
+ $(top_srcdir)/m4/ac_sys_largefile_sensitive.m4 \
+ $(top_srcdir)/m4/acx_restrict.m4 \
+ $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \
+ $(top_srcdir)/m4/ax_cflags_no_writable_strings.m4 \
+ $(top_srcdir)/m4/ax_cflags_strict_prototypes.m4 \
+ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \
+ $(top_srcdir)/m4/ax_create_pkgconfig_info.m4 \
+ $(top_srcdir)/m4/ax_enable_builddir_uname.m4 \
+ $(top_srcdir)/m4/ax_expand_prefix.m4 \
+ $(top_srcdir)/m4/ax_maintainer_mode_auto_silent.m4 \
+ $(top_srcdir)/m4/ax_not_enable_frame_pointer.m4 \
+ $(top_srcdir)/m4/ax_prefix_config_h.m4 \
+ $(top_srcdir)/m4/ax_set_version_info.m4 \
+ $(top_srcdir)/m4/ax_spec_file.m4 \
+ $(top_srcdir)/m4/ax_spec_package_version.m4 \
+ $(top_srcdir)/m4/ax_warning_default_aclocaldir.m4 \
+ $(top_srcdir)/m4/ax_warning_default_pkgconfig.m4 \
+ $(top_srcdir)/m4/patch_libtool_on_darwin_zsh_overquoting.m4 \
+ $(top_srcdir)/m4/patch_libtool_sys_lib_search_path_spec.m4 \
+ $(top_srcdir)/m4/patch_libtool_to_add_host_cc.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/uses/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(aclocaldir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
+unzip_mem_SOURCES = unzip-mem.c
+unzip_mem_OBJECTS = unzip-mem.$(OBJEXT)
+unzip_mem_DEPENDENCIES = ../zzip/libzzipmmapped.la
+unzzip_SOURCES = unzzip.c
+unzzip_OBJECTS = unzzip.$(OBJEXT)
+unzzip_DEPENDENCIES = ../zzip/libzzip.la
+unzzipcat_SOURCES = unzzipcat.c
+unzzipcat_OBJECTS = unzzipcat.$(OBJEXT)
+unzzipcat_DEPENDENCIES = ../zzip/libzzipmmapped.la
+unzzipcat_mem_SOURCES = unzzipcat-mem.c
+unzzipcat_mem_OBJECTS = unzzipcat-mem.$(OBJEXT)
+unzzipcat_mem_DEPENDENCIES = ../zzip/libzzipmmapped.la
+unzzipcat_seeko_SOURCES = unzzipcat-seeko.c
+unzzipcat_seeko_OBJECTS = unzzipcat-seeko.$(OBJEXT)
+unzzipcat_seeko_DEPENDENCIES = ../zzip/libzzipfseeko.la
+unzzipdir_SOURCES = unzzipdir.c
+unzzipdir_OBJECTS = unzzipdir.$(OBJEXT)
+unzzipdir_DEPENDENCIES = ../zzip/libzzipmmapped.la
+unzzipdir_mem_SOURCES = unzzipdir-mem.c
+unzzipdir_mem_OBJECTS = unzzipdir-mem.$(OBJEXT)
+unzzipdir_mem_DEPENDENCIES = ../zzip/libzzipmmapped.la
+zzcat_SOURCES = zzcat.c
+zzcat_OBJECTS = zzcat.$(OBJEXT)
+zzcat_DEPENDENCIES = ../zzip/libzzip.la
+zzdir_SOURCES = zzdir.c
+zzdir_OBJECTS = zzdir.$(OBJEXT)
+zzdir_DEPENDENCIES = ../zzip/libzzip.la
+zzip_SOURCES = zzip.c
+zzip_OBJECTS = zzip.$(OBJEXT)
+zzip_DEPENDENCIES = ../zzip/libzzip.la
+zziptest_SOURCES = zziptest.c
+zziptest_OBJECTS = zziptest.$(OBJEXT)
+zziptest_DEPENDENCIES = ../zzip/libzzip.la
+zzobfuscated_SOURCES = zzobfuscated.c
+zzobfuscated_OBJECTS = zzobfuscated.$(OBJEXT)
+zzobfuscated_DEPENDENCIES = ../zzip/libzzip.la
+zzxorcat_SOURCES = zzxorcat.c
+zzxorcat_OBJECTS = zzxorcat.$(OBJEXT)
+zzxorcat_DEPENDENCIES = ../zzip/libzzip.la
+zzxorcopy_SOURCES = zzxorcopy.c
+zzxorcopy_OBJECTS = zzxorcopy.$(OBJEXT)
+zzxorcopy_LDADD = $(LDADD)
+zzxordir_SOURCES = zzxordir.c
+zzxordir_OBJECTS = zzxordir.$(OBJEXT)
+zzxordir_DEPENDENCIES = ../zzip/libzzip.la
+depcomp = $(SHELL) $(top_srcdir)/uses/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = unzip-mem.c unzzip.c unzzipcat.c unzzipcat-mem.c \
+ unzzipcat-seeko.c unzzipdir.c unzzipdir-mem.c zzcat.c zzdir.c \
+ zzip.c zziptest.c zzobfuscated.c zzxorcat.c zzxorcopy.c \
+ zzxordir.c
+DIST_SOURCES = unzip-mem.c unzzip.c unzzipcat.c unzzipcat-mem.c \
+ unzzipcat-seeko.c unzzipdir.c unzzipdir-mem.c zzcat.c zzdir.c \
+ zzip.c zziptest.c zzobfuscated.c zzxorcat.c zzxorcopy.c \
+ zzxordir.c
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+aclocalDATA_INSTALL = $(INSTALL_DATA)
+DATA = $(aclocal_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONFIG_FILES = @CONFIG_FILES@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@ -I$(top_builddir) -I$(top_srcdir) # also for automake 1.4
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LARGEFILE_CFLAGS = @LARGEFILE_CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+MKZIP = @MKZIP@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RELEASE_INFO = @RELEASE_INFO@
+RESOLVES = @RESOLVES@
+SDL = @SDL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+THREAD_SAFE = @THREAD_SAFE@
+VERSION = @VERSION@
+#
+VERSION_INFO = @VERSION_INFO@
+XMLTO = @XMLTO@
+ZIPTESTS = @ZIPTESTS@
+ZLIB_INCL = @ZLIB_INCL@
+ZLIB_LDIR = @ZLIB_LDIR@
+ZLIB_VERSION = @ZLIB_VERSION@
+ZZIPLIB_LDFLAGS = @ZZIPLIB_LDFLAGS@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_AS = @ac_ct_AS@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DLLTOOL = @ac_ct_DLLTOOL@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_OBJDUMP = @ac_ct_OBJDUMP@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+aclocaldir = $(datadir)/aclocal
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_enable_builddir_sed = @ax_enable_builddir_sed@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+docdir = @docdir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pkgconfig_libdir = @pkgconfig_libdir@
+pkgconfig_libfile = @pkgconfig_libfile@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+AUTOMAKE_OPTIONS = 1.4 foreign
+AUTOTOOL_VERSION = autoconf-2.52 automake-1.5 libtool-1.4.2
+DEFAULT_INCLUDES = # nothing - no default of -I. -I$(srcdir)
+aclocal_DATA = zziplib.m4
+#
+WCC10_CLEAN = *.obj *.lk1 *.mk1 *.mk *.sym *.tgt
+EXTRA_DIST = $(aclocal_DATA)
+CLEANFILES = $(WCC10_CLEAN)
+unzzip_LDFLAGS = @ZZIPLIB_LDFLAGS@
+unzzip_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+zzip_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzip_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+zziptest_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zziptest_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+zzcat_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzcat_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+zzdir_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzdir_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+zzxorcat_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzxorcat_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+zzxordir_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzxordir_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+zzobfuscated_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzobfuscated_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+
+# these use the simplified mmapped disk version
+unzzipdir_LDFLAGS = @ZZIPLIB_LDFLAGS@
+unzzipdir_LDADD = ../zzip/libzzipmmapped.la @RESOLVES@ -lz
+unzzipcat_LDFLAGS = @ZZIPLIB_LDFLAGS@
+unzzipcat_LDADD = ../zzip/libzzipmmapped.la @RESOLVES@ -lz
+unzzipdir_mem_LDFLAGS = @ZZIPLIB_LDFLAGS@
+unzzipdir_mem_LDADD = ../zzip/libzzipmmapped.la @RESOLVES@ -lz
+unzzipcat_mem_LDFLAGS = @ZZIPLIB_LDFLAGS@
+unzzipcat_mem_LDADD = ../zzip/libzzipmmapped.la @RESOLVES@ -lz
+unzip_mem_LDFLAGS = @ZZIPLIB_LDFLAGS@
+unzip_mem_LDADD = ../zzip/libzzipmmapped.la @RESOLVES@ -lz
+# and this uses the simplified fseeko stdio version
+unzzipcat_seeko_LDFLAGS = @ZZIPLIB_LDFLAGS@
+unzzipcat_seeko_LDADD = ../zzip/libzzipfseeko.la @RESOLVES@ -lz
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bins/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bins/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ || test -f $$p1 \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+unzip-mem$(EXEEXT): $(unzip_mem_OBJECTS) $(unzip_mem_DEPENDENCIES)
+ @rm -f unzip-mem$(EXEEXT)
+ $(LINK) $(unzip_mem_LDFLAGS) $(unzip_mem_OBJECTS) $(unzip_mem_LDADD) $(LIBS)
+unzzip$(EXEEXT): $(unzzip_OBJECTS) $(unzzip_DEPENDENCIES)
+ @rm -f unzzip$(EXEEXT)
+ $(LINK) $(unzzip_LDFLAGS) $(unzzip_OBJECTS) $(unzzip_LDADD) $(LIBS)
+unzzipcat$(EXEEXT): $(unzzipcat_OBJECTS) $(unzzipcat_DEPENDENCIES)
+ @rm -f unzzipcat$(EXEEXT)
+ $(LINK) $(unzzipcat_LDFLAGS) $(unzzipcat_OBJECTS) $(unzzipcat_LDADD) $(LIBS)
+unzzipcat-mem$(EXEEXT): $(unzzipcat_mem_OBJECTS) $(unzzipcat_mem_DEPENDENCIES)
+ @rm -f unzzipcat-mem$(EXEEXT)
+ $(LINK) $(unzzipcat_mem_LDFLAGS) $(unzzipcat_mem_OBJECTS) $(unzzipcat_mem_LDADD) $(LIBS)
+unzzipcat-seeko$(EXEEXT): $(unzzipcat_seeko_OBJECTS) $(unzzipcat_seeko_DEPENDENCIES)
+ @rm -f unzzipcat-seeko$(EXEEXT)
+ $(LINK) $(unzzipcat_seeko_LDFLAGS) $(unzzipcat_seeko_OBJECTS) $(unzzipcat_seeko_LDADD) $(LIBS)
+unzzipdir$(EXEEXT): $(unzzipdir_OBJECTS) $(unzzipdir_DEPENDENCIES)
+ @rm -f unzzipdir$(EXEEXT)
+ $(LINK) $(unzzipdir_LDFLAGS) $(unzzipdir_OBJECTS) $(unzzipdir_LDADD) $(LIBS)
+unzzipdir-mem$(EXEEXT): $(unzzipdir_mem_OBJECTS) $(unzzipdir_mem_DEPENDENCIES)
+ @rm -f unzzipdir-mem$(EXEEXT)
+ $(LINK) $(unzzipdir_mem_LDFLAGS) $(unzzipdir_mem_OBJECTS) $(unzzipdir_mem_LDADD) $(LIBS)
+zzcat$(EXEEXT): $(zzcat_OBJECTS) $(zzcat_DEPENDENCIES)
+ @rm -f zzcat$(EXEEXT)
+ $(LINK) $(zzcat_LDFLAGS) $(zzcat_OBJECTS) $(zzcat_LDADD) $(LIBS)
+zzdir$(EXEEXT): $(zzdir_OBJECTS) $(zzdir_DEPENDENCIES)
+ @rm -f zzdir$(EXEEXT)
+ $(LINK) $(zzdir_LDFLAGS) $(zzdir_OBJECTS) $(zzdir_LDADD) $(LIBS)
+zzip$(EXEEXT): $(zzip_OBJECTS) $(zzip_DEPENDENCIES)
+ @rm -f zzip$(EXEEXT)
+ $(LINK) $(zzip_LDFLAGS) $(zzip_OBJECTS) $(zzip_LDADD) $(LIBS)
+zziptest$(EXEEXT): $(zziptest_OBJECTS) $(zziptest_DEPENDENCIES)
+ @rm -f zziptest$(EXEEXT)
+ $(LINK) $(zziptest_LDFLAGS) $(zziptest_OBJECTS) $(zziptest_LDADD) $(LIBS)
+zzobfuscated$(EXEEXT): $(zzobfuscated_OBJECTS) $(zzobfuscated_DEPENDENCIES)
+ @rm -f zzobfuscated$(EXEEXT)
+ $(LINK) $(zzobfuscated_LDFLAGS) $(zzobfuscated_OBJECTS) $(zzobfuscated_LDADD) $(LIBS)
+zzxorcat$(EXEEXT): $(zzxorcat_OBJECTS) $(zzxorcat_DEPENDENCIES)
+ @rm -f zzxorcat$(EXEEXT)
+ $(LINK) $(zzxorcat_LDFLAGS) $(zzxorcat_OBJECTS) $(zzxorcat_LDADD) $(LIBS)
+zzxorcopy$(EXEEXT): $(zzxorcopy_OBJECTS) $(zzxorcopy_DEPENDENCIES)
+ @rm -f zzxorcopy$(EXEEXT)
+ $(LINK) $(zzxorcopy_LDFLAGS) $(zzxorcopy_OBJECTS) $(zzxorcopy_LDADD) $(LIBS)
+zzxordir$(EXEEXT): $(zzxordir_OBJECTS) $(zzxordir_DEPENDENCIES)
+ @rm -f zzxordir$(EXEEXT)
+ $(LINK) $(zzxordir_LDFLAGS) $(zzxordir_OBJECTS) $(zzxordir_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unzip-mem.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unzzip.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unzzipcat-mem.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unzzipcat-seeko.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unzzipcat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unzzipdir-mem.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unzzipdir.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzcat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzdir.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzip.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zziptest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzobfuscated.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzxorcat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzxorcopy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzxordir.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+install-aclocalDATA: $(aclocal_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(aclocaldir)" || $(mkdir_p) "$(DESTDIR)$(aclocaldir)"
+ @list='$(aclocal_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(aclocalDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(aclocaldir)/$$f'"; \
+ $(aclocalDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(aclocaldir)/$$f"; \
+ done
+
+uninstall-aclocalDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(aclocal_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(aclocaldir)/$$f'"; \
+ rm -f "$(DESTDIR)$(aclocaldir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(aclocaldir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+ clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-aclocalDATA
+
+install-exec-am: install-binPROGRAMS
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-aclocalDATA uninstall-binPROGRAMS \
+ uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic clean-libtool clean-noinstPROGRAMS ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-aclocalDATA install-am \
+ install-binPROGRAMS install-data install-data-am install-exec \
+ install-exec-am install-info install-info-am install-man \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-aclocalDATA \
+ uninstall-am uninstall-binPROGRAMS uninstall-info-am
+
+
+../zzip/libzzip.la : @top_srcdir@/zzip/*.c
+ (cd ../zzip && $(MAKE) `basename $@`)
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Build/source/libs/zziplib/bins/unzip-mem.c b/Build/source/libs/zziplib/bins/unzip-mem.c
new file mode 100644
index 00000000000..3f7d7f0631e
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/unzip-mem.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2003 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB license.
+ *
+ * This file is used as an example to clarify zzipmmap api usage.
+ */
+
+#include <zlib.h> /* crc32 */
+
+#include <zzip/memdisk.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef ZZIP_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef ZZIP_HAVE_IO_H
+#include <io.h>
+#endif
+
+#include <time.h>
+
+#ifdef ZZIP_HAVE_FNMATCH_H
+#include <fnmatch.h>
+#else
+#define fnmatch(x,y,z) strcmp(x,y)
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#define ___ {
+#define ____ }
+
+#define EXIT_SUCCESS 0
+#define EXIT_WARNINGS 1
+#define EXIT_ERRORS 2
+#define EXIT_EFORMAT 3
+#define EXIT_ENOMEM 4
+#define EXIT_ENOTTY 5
+#define EXIT_EINFLATE 6
+#define EXIT_ENOARCH 9
+#define EXIT_EOPTION 10
+#define EXIT_ENOFILE 11
+#define EXIT_EDISKFULL 50
+#define EXIT_EPREMATURE 51
+#define EXIT_USERABORT 80
+#define EXIT_BADCOMPRESSION 81
+#define EXIT_BADPASSWORD 82
+
+static int status = EXIT_SUCCESS;
+static int option_list = 0; /* "-l" */
+static int option_pipe = 0; /* "-p" */
+static int option_verbose = 0; /* "-v" */
+static int option_testcrc = 0; /* "-t" */
+static int option_binary = 0; /* "-b" */
+static int option_nocase = 0; /* "-C" */
+static int option_junkpaths = 0; /* "-j" */
+static int option_dosfiles = 0; /* "-L" */
+static int option_keepold = 0; /* "-n" */
+static int option_overwrite = 0; /* "-o" */
+static int option_quiet = 0; /* "-q" */
+static int option_permbits = 0; /* "-X" */
+
+static const char usage[] =
+{
+ "unzzip-mem <zip> [names].. \n"
+ " - unzzip a zip archive.\n"
+ "options:\n"
+ " -l list archive files (name, usize, mtime, comments)\n" /* +totals */
+ " -p extract archive files to pipe, i.e. stdout (binary mode)\n"
+ " -t test archive files (check the crc values)\n"
+ " -v verbose list of archive files\n"
+ " -b accept and ignore (force binary extract)\n"
+ " -C match filenames case-insensitively\n"
+ " -j junk paths (do not recreate directory structure)\n"
+ " -L convert dos filenames to lowercase upon extract\n"
+ " -n never overwrite existing files\n"
+ " -o always overwrite existing files\n"
+ " -q quite operation\n"
+ " -X restore user/owner attributes of files\n"
+};
+
+static void zzip_mem_entry_pipe(ZZIP_MEM_DISK* disk,
+ ZZIP_MEM_ENTRY* entry, FILE* out)
+{
+ ZZIP_DISK_FILE* file = zzip_mem_entry_fopen (disk, entry);
+ if (file)
+ {
+ char buffer[1024]; int len;
+ while ((len = zzip_mem_disk_fread (buffer, 1024, 1, file)))
+ fwrite (buffer, len, 1, out);
+
+ zzip_mem_disk_fclose (file);
+ }
+}
+
+static void zzip_mem_entry_make(ZZIP_MEM_DISK* disk,
+ ZZIP_MEM_ENTRY* entry)
+{
+ FILE* file = fopen (entry->zz_name, "w");
+ if (file) { zzip_mem_entry_pipe (disk, entry, file); fclose (file); }
+ perror (entry->zz_name);
+ if (status < EXIT_WARNINGS) status = EXIT_WARNINGS;
+}
+
+/* ------------------------- test ------------------------------------ */
+
+static char* archive = 0;
+static int test_errors = 0;
+
+static void zzip_mem_entry_test(ZZIP_MEM_DISK* disk,
+ ZZIP_MEM_ENTRY* entry)
+{
+ ZZIP_DISK_FILE* file = zzip_mem_entry_fopen (disk, entry);
+ printf (" testing: %s ", entry->zz_name);
+ if (strlen (entry->zz_name) < 24) {
+ printf ("%.*s", 24 - (int) strlen (entry->zz_name),
+ " ");
+ }
+ if (file)
+ {
+ unsigned long crc = crc32 (0L, NULL, 0);
+ unsigned char buffer[1024]; int len;
+ while ((len = zzip_mem_disk_fread (buffer, 1024, 1, file))) {
+ crc = crc32 (crc, buffer, len);
+ }
+
+ zzip_mem_disk_fclose (file);
+ if (crc == (unsigned long) entry->zz_crc32) {
+ printf ("OK\n");
+ } else {
+ printf ("BAD %lx (should be %lx)\n", crc, entry->zz_crc32);
+ test_errors ++;
+ }
+ } else {
+ printf ("ERROR (no such file)\n");
+ test_errors ++;
+ }
+}
+
+static void zzip_mem_entry_test_start(void)
+{
+ test_errors = 0;
+ printf ("Archive: %s\n", archive);
+}
+
+static void zzip_mem_entry_test_done(void)
+{
+ if (test_errors == 0) {
+ printf ("No errors detected in compressed data of %s\n", archive);
+ } else {
+ printf ("%i errors detected in compressed data of %s\n",
+ test_errors, archive);
+ }
+}
+
+/* ------------------------- list ------------------------------------ */
+
+static char _zzip_time_[30];
+static char* _zzip_ctime (const time_t* timeval)
+{
+ struct tm* date = localtime (timeval);
+ sprintf (_zzip_time_, "%02i-%02i-%02i %02i:%02i",
+ date->tm_mon, date->tm_mday, date->tm_year%100,
+ date->tm_hour, date->tm_min);
+ return _zzip_time_;
+}
+
+static const char* comprlevel[] = {
+ "stored", "shrunk", "redu:1", "redu:2", "redu:3", "redu:4",
+ "impl:N", "toknze", "defl:N", "defl:B", "impl:B" };
+
+zzip_off_t sum_usize = 0;
+zzip_off_t sum_csize = 0;
+zzip_off_t sum_files = 0;
+#define L (long)
+
+static void zzip_mem_entry_direntry_start (void)
+{
+ sum_usize = 0;
+ sum_csize = 0;
+ sum_files = 0;
+ if (option_verbose) goto verbose;
+ printf(" Length Date & Time Name\n");
+ printf(" -------- ---- ---- ----\n");
+ return;
+ verbose:
+ printf(" Length Method Size Ratio Date Time CRC-32 Name\n");
+ printf("-------- ------ ------- ----- ---- ---- ------ ----\n");
+}
+
+static void zzip_mem_entry_direntry_done (void)
+{
+ char exp = ' ';
+ if (sum_usize / 1024 > 1024*1024*1024) { exp = 'G';
+ sum_usize /= 1024*1024*1024; sum_usize /= 1024*1024*1024; }
+ if (sum_usize > 1024*1024*1024) { exp = 'M';
+ sum_usize /= 1024*1024; sum_csize /= 1024*1024; }
+ if (sum_usize > 1024*1024) { exp = 'K';
+ sum_usize /= 1024; sum_csize /= 1024; }
+ if (option_verbose) goto verbose;
+ printf(" -------- ----\n");
+ printf(" %8li%c %8li %s\n", L sum_usize, exp, L sum_files,
+ sum_files == 1 ? "file" : "files");
+ return;
+ verbose:
+ printf("-------- ------ ------- ----- ----\n");
+ printf("%8li%c %8li%c %3li%% %8li %s\n",
+ L sum_usize, exp, L sum_csize, exp,
+ L (100 - (sum_csize*100/sum_usize)), L sum_files,
+ sum_files == 1 ? "file" : "files");
+}
+
+static void zzip_mem_entry_direntry(ZZIP_MEM_ENTRY* entry)
+{
+ char* name = zzip_mem_entry_to_name (entry);
+ zzip_off_t usize = zzip_mem_entry_usize (entry);
+ zzip_off_t csize = zzip_mem_entry_csize (entry);
+ int compr = zzip_mem_entry_data_comprlevel (entry);
+ time_t mtime = entry->zz_mktime;
+ long crc32 = entry->zz_crc32;
+ const char* comment = zzip_mem_entry_to_comment (entry);
+ char exp = ' ';
+
+ sum_usize += usize;
+ sum_csize += csize;
+ sum_files += 1;
+
+ if (usize / 1024 > 1024*1024*1024) { exp = 'G';
+ usize /= 1024*1024*1024; usize /= 1024*1024*1024; }
+ if (usize > 1024*1024*1024) { exp = 'M';
+ usize /= 1024*1024; csize /= 1024*1024; }
+ if (usize > 1024*1024) { exp = 'K';
+ usize /= 1024; csize /= 1024; }
+
+ if (! comment) comment = "";
+ if (*name == '\n') name++;
+
+ if (option_verbose) {
+ printf("%8li%c %s %8li%c%3li%% %s %8lx %s %s\n",
+ L usize, exp, comprlevel[compr], L csize, exp,
+ L (100 - (csize*100/usize)),
+ _zzip_ctime(&mtime), crc32, name, comment);
+ } else {
+ printf(" %8li%c %s %s %s\n",
+ L usize, exp, _zzip_ctime(&mtime), name, comment);
+ }
+}
+
+static void zzip_mem_entry_listfiles(ZZIP_MEM_DISK* disk, char* filespec)
+{
+ zzip_mem_entry_direntry_start ();
+ ___ ZZIP_MEM_ENTRY* entry = 0;
+ while ((entry = zzip_mem_disk_findmatch(disk, filespec, entry, 0, 0)))
+ zzip_mem_entry_direntry (entry); ____;
+ zzip_mem_entry_direntry_done ();
+}
+
+static void zzip_mem_entry_listall(ZZIP_MEM_DISK* disk)
+{
+ zzip_mem_entry_direntry_start ();
+ ___ ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
+ for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
+ zzip_mem_entry_direntry (entry); ____;
+ zzip_mem_entry_direntry_done ();
+}
+
+static void zzip_mem_entry_testfiles(ZZIP_MEM_DISK* disk, char* filespec)
+{
+ zzip_mem_entry_test_start ();
+ ___ ZZIP_MEM_ENTRY* entry = 0;
+ while ((entry = zzip_mem_disk_findmatch(disk, filespec, entry, 0, 0)))
+ zzip_mem_entry_test (disk, entry); ____;
+ zzip_mem_entry_test_done ();
+}
+
+static void zzip_mem_entry_testall(ZZIP_MEM_DISK* disk)
+{
+ zzip_mem_entry_test_start ();
+ ___ ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
+ for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
+ zzip_mem_entry_test (disk, entry); ____;
+ zzip_mem_entry_test_done ();
+}
+
+static void zzip_mem_entry_pipefiles(ZZIP_MEM_DISK* disk, char* filespec)
+{
+ ZZIP_MEM_ENTRY* entry = 0;
+ while ((entry = zzip_mem_disk_findmatch(disk, filespec, entry, 0, 0)))
+ zzip_mem_entry_pipe (disk, entry, stdout);
+}
+
+static void zzip_mem_entry_pipeall(ZZIP_MEM_DISK* disk)
+{
+ ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
+ for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
+ zzip_mem_entry_pipe (disk, entry, stdout);
+}
+
+static void zzip_mem_entry_makefiles(ZZIP_MEM_DISK* disk, char* filespec)
+{
+ ZZIP_MEM_ENTRY* entry = 0;
+ while ((entry = zzip_mem_disk_findmatch(disk, filespec, entry, 0, 0)))
+ zzip_mem_entry_make (disk, entry);
+}
+
+static void zzip_mem_entry_makeall(ZZIP_MEM_DISK* disk)
+{
+ ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
+ for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
+ zzip_mem_entry_make (disk, entry);
+}
+
+int
+main (int argc, char ** argv)
+{
+ int argn; int archname = 0; int filespec = 0;
+ ZZIP_MEM_DISK* disk;
+ if (argc <= 1 || ! strcmp (argv[1], "--help"))
+ {
+ printf (usage);
+ return 0;
+ }
+ if (! strcmp (argv[1], "--version"))
+ {
+ printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
+ return 0;
+ }
+
+ for (argn=1; argn < argc; argn++) {
+ if ((argv[argn])[0] == '-') {
+ int x = 1;
+ while ((argv[argn])[x]) {
+ switch (argv[argn][x]) {
+ case 'l': option_list++; break;
+ case 'p': option_pipe++; break;
+ case 't': option_testcrc++; break;
+ case 'v': option_verbose++; break;
+ case 'b': option_binary++; break;
+ case 'C': option_nocase++; break;
+ case 'j': option_junkpaths++; break;
+ case 'L': option_dosfiles++; break;
+ case 'n': option_keepold++; break;
+ case 'o': option_overwrite++; break;
+ case 'q': option_quiet++; break;
+ case 'X': option_permbits++; break;
+ }
+ x++;
+ }
+ (argv[argn])[0] = 0;
+ } else {
+ if (! archname) { archname = argn; continue; }
+ if (! filespec) { filespec = argn; continue; }
+ }
+ }
+
+ if (! archname) {
+ printf (usage);
+ return 0;
+ } else archive = argv[archname];
+
+ disk = zzip_mem_disk_open (argv[archname]);
+ if (! disk) {
+ perror(argv[archname]);
+ return -1;
+ }
+
+ if (option_list || option_verbose) {
+ if (! filespec) {
+ zzip_mem_entry_listall (disk);
+ } else {
+ for (argn=filespec; argn < argc; argn++) {
+ if (argv[argn][0]) {
+ zzip_mem_entry_listfiles (disk, argv[argn]);
+ }
+ }
+ }
+ } else if (option_pipe) {
+ if (! filespec) {
+ zzip_mem_entry_pipeall (disk);
+ } else {
+ for (argn=filespec; argn < argc; argn++) {
+ if (argv[argn][0]) {
+ zzip_mem_entry_pipefiles (disk, argv[argn]);
+ }
+ }
+ }
+ } else if (option_testcrc) {
+ if (! filespec) {
+ zzip_mem_entry_testall (disk);
+ } else {
+ for (argn=filespec; argn < argc; argn++) {
+ if (argv[argn][0]) {
+ zzip_mem_entry_testfiles (disk, argv[argn]);
+ }
+ }
+ }
+ } else {
+ if (! filespec) {
+ zzip_mem_entry_makeall (disk);
+ } else {
+ for (argn=filespec; argn < argc; argn++) {
+ if (argv[argn][0]) {
+ zzip_mem_entry_makefiles (disk, argv[argn]);
+ }
+ }
+ }
+ }
+
+ return status;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/bins/unzzip.c b/Build/source/libs/zziplib/bins/unzzip.c
new file mode 100644
index 00000000000..ae8b3b97969
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/unzzip.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2003 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB license.
+ *
+ * This file is used as an example to clarify zzip api usage.
+ */
+
+#include <zzip/zzip.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef ZZIP_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef ZZIP_HAVE_IO_H
+#include <io.h>
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static const char usage[] =
+{
+ "unzzip <dir>.. \n"
+ " - unzzip the files contained in a zip archive.\n"
+};
+
+int
+main (int argc, char ** argv)
+{
+ int argn;
+ int exitcode = 0;
+ zzip_error_t error;
+
+ if (argc <= 1 || ! strcmp (argv[1], "--help"))
+ {
+ printf (usage);
+ return 0;
+ }
+ if (! strcmp (argv[1], "--version"))
+ {
+ printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
+ return 0;
+ }
+
+ for (argn=1; argn < argc; argn++)
+ {
+ ZZIP_DIR * dir;
+ ZZIP_DIRENT d;
+
+ dir = zzip_dir_open(argv[argn], &error);
+ if (! dir)
+ {
+ fprintf (stderr, "did not open %s: \n", argv[argn]);
+ fprintf (stderr, "%s: %s\n", argv[argn], zzip_strerror(error));
+ exitcode++;
+ continue;
+ }
+
+ if (argc > 2) printf ("%s: \n", argv[argn]);
+
+ /* read each dir entry and show one line of info per file */
+ while (zzip_dir_read (dir, &d))
+ {
+ int output;
+ ZZIP_FILE* input = zzip_file_open (dir, d.d_name, O_RDONLY);
+ if (! input)
+ {
+ fprintf (stderr, "|did not open %s: \n", d.d_name);
+ fprintf (stderr, "|%s: %s\n", d.d_name, zzip_strerror_of(dir));
+ continue;
+ }
+
+ output = creat (d.d_name, 0664);
+ if (output == -1)
+ {
+ fprintf (stderr, "|output file %s: \n", d.d_name);
+ perror(d.d_name);
+ zzip_file_close (input);
+ continue;
+ }
+
+ printf("%s\n", d.d_name);
+
+ {
+ char buf[17]; zzip_ssize_t n;
+ /* read chunks of 16 bytes into buf */
+ while (0 < (n = zzip_read (input, buf, 16)))
+ {
+ write (output, buf, n);
+ }
+
+ if (n == -1)
+ perror (d.d_name);
+ }
+ close (output);
+ zzip_file_close (input);
+ }
+
+ zzip_dir_close(dir);
+ }
+
+ return exitcode;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/bins/unzzipcat-mem.c b/Build/source/libs/zziplib/bins/unzzipcat-mem.c
new file mode 100644
index 00000000000..7474854187e
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/unzzipcat-mem.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2003 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB license.
+ *
+ * This file is used as an example to clarify zzipmmap api usage.
+ */
+
+#include <zzip/memdisk.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef ZZIP_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef ZZIP_HAVE_IO_H
+#include <io.h>
+#endif
+
+#ifdef ZZIP_HAVE_FNMATCH_H
+#include <fnmatch.h>
+#else
+#define fnmatch(x,y,z) strcmp(x,y)
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static const char usage[] =
+{
+ "unzzipdir-mem <zip> [names].. \n"
+ " - unzzip data content of files contained in a zip archive.\n"
+};
+
+static void zzip_mem_entry_fprint(ZZIP_MEM_DISK* disk,
+ ZZIP_MEM_ENTRY* entry, FILE* out)
+{
+ ZZIP_DISK_FILE* file = zzip_mem_entry_fopen (disk, entry);
+ if (file)
+ {
+ char buffer[1024]; int len;
+ while ((len = zzip_mem_disk_fread (buffer, 1024, 1, file)))
+ fwrite (buffer, len, 1, out);
+
+ zzip_mem_disk_fclose (file);
+ }
+}
+
+static void zzip_mem_disk_cat_file(ZZIP_MEM_DISK* disk, char* name, FILE* out)
+{
+ ZZIP_DISK_FILE* file = zzip_mem_disk_fopen (disk, name);
+ if (file)
+ {
+ char buffer[1024]; int len;
+ while ((len = zzip_mem_disk_fread (buffer, 1, 1024, file)))
+ {
+ fwrite (buffer, 1, len, out);
+ }
+
+ zzip_mem_disk_fclose (file);
+ }
+}
+
+int
+main (int argc, char ** argv)
+{
+ int argn;
+ ZZIP_MEM_DISK* disk;
+
+ if (argc <= 1 || ! strcmp (argv[1], "--help"))
+ {
+ printf (usage);
+ return 0;
+ }
+ if (! strcmp (argv[1], "--version"))
+ {
+ printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
+ return 0;
+ }
+
+ disk = zzip_mem_disk_open (argv[1]);
+ if (! disk) {
+ perror(argv[1]);
+ return -1;
+ }
+
+ if (argc == 2)
+ { /* print directory list */
+ ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
+ for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
+ {
+ char* name = zzip_mem_entry_to_name (entry);
+ printf ("%s\n", name);
+ }
+ return 0;
+ }
+
+ if (argc == 3)
+ { /* list from one spec */
+ ZZIP_MEM_ENTRY* entry = 0;
+ while ((entry = zzip_mem_disk_findmatch(disk, argv[2], entry, 0, 0)))
+ {
+ zzip_mem_entry_fprint (disk, entry, stdout);
+ }
+
+ return 0;
+ }
+
+ for (argn=1; argn < argc; argn++)
+ { /* list only the matching entries - each in order of commandline */
+ ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
+ for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
+ {
+ char* name = zzip_mem_entry_to_name (entry);
+ if (! fnmatch (argv[argn], name,
+ FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD))
+ zzip_mem_disk_cat_file (disk, name, stdout);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/bins/unzzipcat-seeko.c b/Build/source/libs/zziplib/bins/unzzipcat-seeko.c
new file mode 100644
index 00000000000..f16f0b96566
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/unzzipcat-seeko.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2003 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB license.
+ *
+ * This file is used as an example to clarify zzipfseeko api usage.
+ */
+
+#include <zzip/fseeko.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef ZZIP_HAVE_FNMATCH_H
+#include <fnmatch.h>
+#else
+#define fnmatch(x,y,z) strcmp(x,y)
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static const char usage[] =
+{
+ "unzzipcat-seeko <zip> [names].. \n"
+ " - unzzip data content of files contained in a zip archive.\n"
+};
+
+static void zzip_entry_fprint(ZZIP_ENTRY* entry, FILE* out)
+{
+ ZZIP_ENTRY_FILE* file = zzip_entry_fopen (entry, 0);
+ if (file)
+ {
+ char buffer[1024]; int len;
+ while ((len = zzip_entry_fread (buffer, 1024, 1, file)))
+ fwrite (buffer, len, 1, out);
+
+ zzip_entry_fclose (file);
+ }
+}
+
+static void zzip_cat_file(FILE* disk, char* name, FILE* out)
+{
+ ZZIP_ENTRY_FILE* file = zzip_entry_ffile (disk, name);
+ if (file)
+ {
+ char buffer[1024]; int len;
+ while ((len = zzip_entry_fread (buffer, 1024, 1, file)))
+ fwrite (buffer, len, 1, out);
+
+ zzip_entry_fclose (file);
+ }
+}
+
+int
+main (int argc, char ** argv)
+{
+ int argn;
+ FILE* disk;
+
+ if (argc <= 1 || ! strcmp (argv[1], "--help"))
+ {
+ printf (usage);
+ return 0;
+ }
+ if (! strcmp (argv[1], "--version"))
+ {
+ printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
+ return 0;
+ }
+
+ disk = fopen (argv[1], "r");
+ if (! disk) {
+ perror(argv[1]);
+ return -1;
+ }
+
+ if (argc == 2)
+ { /* print directory list */
+ ZZIP_ENTRY* entry = zzip_entry_findfirst(disk);
+ if (! entry) puts("no first entry!\n");
+ for (; entry ; entry = zzip_entry_findnext(entry))
+ {
+ char* name = zzip_entry_strdup_name (entry);
+ printf ("%s\n", name);
+ free (name);
+ }
+ return 0;
+ }
+
+ if (argc == 3)
+ { /* list from one spec */
+ ZZIP_ENTRY* entry = 0;
+ while ((entry = zzip_entry_findmatch(disk, argv[2], entry, 0, 0)))
+ zzip_entry_fprint (entry, stdout);
+
+ return 0;
+ }
+
+ for (argn=1; argn < argc; argn++)
+ { /* list only the matching entries - each in order of commandline */
+ ZZIP_ENTRY* entry = zzip_entry_findfirst(disk);
+ for (; entry ; entry = zzip_entry_findnext(entry))
+ {
+ char* name = zzip_entry_strdup_name (entry);
+ if (! fnmatch (argv[argn], name,
+ FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD))
+ zzip_cat_file (disk, name, stdout);
+ free (name);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/bins/unzzipcat.c b/Build/source/libs/zziplib/bins/unzzipcat.c
new file mode 100644
index 00000000000..4282cb36be9
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/unzzipcat.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2003 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB license.
+ *
+ * This file is used as an example to clarify zzipmmap api usage.
+ */
+
+#include <zzip/mmapped.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef ZZIP_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef ZZIP_HAVE_IO_H
+#include <io.h>
+#endif
+
+#ifdef ZZIP_HAVE_FNMATCH_H
+#include <fnmatch.h>
+#else
+#define fnmatch(x,y,z) strcmp(x,y)
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static const char usage[] =
+{
+ "unzzipdir <zip> [names].. \n"
+ " - unzzip data content of files contained in a zip archive.\n"
+};
+
+static void zzip_disk_entry_fprint(ZZIP_DISK* disk,
+ ZZIP_DISK_ENTRY* entry, FILE* out)
+{
+ ZZIP_DISK_FILE* file = zzip_disk_entry_fopen (disk, entry);
+ if (file)
+ {
+ char buffer[1024]; int len;
+ while ((len = zzip_disk_fread (buffer, 1024, 1, file)))
+ fwrite (buffer, len, 1, out);
+
+ zzip_disk_fclose (file);
+ }
+}
+
+static void zzip_disk_cat_file(ZZIP_DISK* disk, char* name, FILE* out)
+{
+ ZZIP_DISK_FILE* file = zzip_disk_fopen (disk, name);
+ if (file)
+ {
+ char buffer[1024]; int len;
+ while ((len = zzip_disk_fread (buffer, 1, 1024, file)))
+ {
+ fwrite (buffer, 1, len, out);
+ }
+
+ zzip_disk_fclose (file);
+ }
+}
+
+int
+main (int argc, char ** argv)
+{
+ int argn;
+ ZZIP_DISK* disk;
+
+ if (argc <= 1 || ! strcmp (argv[1], "--help"))
+ {
+ printf (usage);
+ return 0;
+ }
+ if (! strcmp (argv[1], "--version"))
+ {
+ printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
+ return 0;
+ }
+
+ disk = zzip_disk_open (argv[1]);
+ if (! disk) {
+ perror(argv[1]);
+ return -1;
+ }
+
+ if (argc == 2)
+ { /* print directory list */
+ ZZIP_DISK_ENTRY* entry = zzip_disk_findfirst(disk);
+ for (; entry ; entry = zzip_disk_findnext(disk, entry))
+ {
+ char* name = zzip_disk_entry_strdup_name (disk, entry);
+ printf ("%s\n", name);
+ free (name);
+ }
+ return 0;
+ }
+
+ if (argc == 3)
+ { /* list from one spec */
+ ZZIP_DISK_ENTRY* entry = 0;
+ while ((entry = zzip_disk_findmatch(disk, argv[2], entry, 0, 0)))
+ zzip_disk_entry_fprint (disk, entry, stdout);
+
+ return 0;
+ }
+
+ for (argn=1; argn < argc; argn++)
+ { /* list only the matching entries - each in order of commandline */
+ ZZIP_DISK_ENTRY* entry = zzip_disk_findfirst(disk);
+ for (; entry ; entry = zzip_disk_findnext(disk, entry))
+ {
+ char* name = zzip_disk_entry_strdup_name (disk, entry);
+ if (! fnmatch (argv[argn], name,
+ FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD))
+ zzip_disk_cat_file (disk, name, stdout);
+ free (name);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/bins/unzzipdir-mem.c b/Build/source/libs/zziplib/bins/unzzipdir-mem.c
new file mode 100644
index 00000000000..dc020772309
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/unzzipdir-mem.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2003 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB license.
+ *
+ * This file is used as an example to clarify zzipmmap api usage.
+ */
+
+#include <zzip/memdisk.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef ZZIP_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef ZZIP_HAVE_IO_H
+#include <io.h>
+#endif
+
+#ifdef ZZIP_HAVE_FNMATCH_H
+#include <fnmatch.h>
+#else
+#define fnmatch(x,y,z) strcmp(x,y)
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static const char usage[] =
+{
+ "unzzipdir <zip> [names].. \n"
+ " - unzzip a listing of files contained in a zip archive.\n"
+};
+
+int
+main (int argc, char ** argv)
+{
+ int argn;
+ ZZIP_MEM_DISK* disk;
+
+ if (argc <= 1 || ! strcmp (argv[1], "--help"))
+ {
+ printf (usage);
+ return 0;
+ }
+ if (! strcmp (argv[1], "--version"))
+ {
+ printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
+ return 0;
+ }
+
+ disk = zzip_mem_disk_open (argv[1]);
+ if (! disk) {
+ perror(argv[1]);
+ return -1;
+ }
+
+ if (argc == 2)
+ { /* list all */
+ ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
+ for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
+ {
+ char* name = zzip_mem_entry_to_name (entry);
+ printf ("%s\n", name);
+ }
+ return 0;
+ }
+
+ if (argc == 3)
+ { /* list from one spec */
+ ZZIP_MEM_ENTRY* entry = 0;
+ while ((entry = zzip_mem_disk_findmatch(disk, argv[2], entry, 0, 0)))
+ {
+ char* name = zzip_mem_entry_to_name (entry);
+ printf ("%s\n", name);
+ }
+ return 0;
+ }
+
+ { /* list only the matching entries - in order of zip directory */
+ ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
+ for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
+ {
+ char* name = zzip_mem_entry_to_name (entry);
+ for (argn=1; argn < argc; argn++)
+ {
+ if (! fnmatch (argv[argn], name,
+ FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD))
+ printf ("%s\n", name);
+ }
+ }
+ return 0;
+ }
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/bins/unzzipdir.c b/Build/source/libs/zziplib/bins/unzzipdir.c
new file mode 100644
index 00000000000..3c570c5548f
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/unzzipdir.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2003 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB license.
+ *
+ * This file is used as an example to clarify zzipmmap api usage.
+ */
+
+#include <zzip/mmapped.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef ZZIP_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef ZZIP_HAVE_IO_H
+#include <io.h>
+#endif
+
+#ifdef ZZIP_HAVE_FNMATCH_H
+#include <fnmatch.h>
+#else
+#define fnmatch(x,y,z) strcmp(x,y)
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static const char usage[] =
+{
+ "unzzipdir <zip> [names].. \n"
+ " - unzzip a listing of files contained in a zip archive.\n"
+};
+
+int
+main (int argc, char ** argv)
+{
+ int argn;
+ ZZIP_DISK* disk;
+
+ if (argc <= 1 || ! strcmp (argv[1], "--help"))
+ {
+ printf (usage);
+ return 0;
+ }
+ if (! strcmp (argv[1], "--version"))
+ {
+ printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
+ return 0;
+ }
+
+ disk = zzip_disk_open (argv[1]);
+ if (! disk) {
+ perror(argv[1]);
+ return -1;
+ }
+
+ if (argc == 2)
+ { /* list all */
+ ZZIP_DISK_ENTRY* entry = zzip_disk_findfirst(disk);
+ for (; entry ; entry = zzip_disk_findnext(disk, entry))
+ {
+ char* name = zzip_disk_entry_strdup_name (disk, entry);
+ printf ("%s\n", name);
+ free (name);
+ }
+ return 0;
+ }
+
+ if (argc == 3)
+ { /* list from one spec */
+ ZZIP_DISK_ENTRY* entry = 0;
+ while ((entry = zzip_disk_findmatch(disk, argv[2], entry, 0, 0)))
+ {
+ char* name = zzip_disk_entry_strdup_name (disk, entry);
+ printf ("%s\n", name);
+ free (name);
+ }
+ return 0;
+ }
+
+ { /* list only the matching entries - in order of zip directory */
+ ZZIP_DISK_ENTRY* entry = zzip_disk_findfirst(disk);
+ for (; entry ; entry = zzip_disk_findnext(disk, entry))
+ {
+ char* name = zzip_disk_entry_strdup_name (disk, entry);
+ for (argn=1; argn < argc; argn++)
+ {
+ if (! fnmatch (argv[argn], name,
+ FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD))
+ printf ("%s\n", name);
+ }
+ free (name);
+ }
+ return 0;
+ }
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/bins/zzcat.c b/Build/source/libs/zziplib/bins/zzcat.c
new file mode 100644
index 00000000000..27225820784
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/zzcat.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2000,2001,2002 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB License
+ */
+
+#include <zzip/zzip.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static const char usage[] =
+{
+ " zzcat <file>... \n"
+ " - prints the file to stdout, so you may want to redirect the output; \n"
+ " the file can be a normal file or an inflated part of a zip-archive, \n"
+ " to get 'README' from dist.zip you may write \n"
+ " zzcat dist/README \n"
+};
+
+int
+main (int argc, char ** argv)
+{
+ int argn;
+
+ if (argc <= 1 || ! strcmp (argv[1], "--help"))
+ {
+ printf (usage);
+ return 0;
+ }
+ if (! strcmp (argv[1], "--version"))
+ {
+ printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
+ return 0;
+ }
+
+ for (argn=1; argn < argc; argn++)
+ {
+ ZZIP_FILE* fp = zzip_open (argv[argn], O_RDONLY|O_BINARY);
+
+ if (! fp)
+ {
+ perror (argv[argn]);
+ continue;
+ }else{
+ char buf[17];
+ int n;
+
+ /* read chunks of 16 bytes into buf and print them to stdout */
+ while (0 < (n = zzip_read(fp, buf, 16)))
+ {
+ buf[n] = '\0';
+# ifdef STDOUT_FILENO
+ write (STDOUT_FILENO, buf, n);
+# else
+ fwrite (buf, 1, n, stdout);
+# endif
+ }
+
+ if (n == -1)
+ perror (argv[argn]);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/bins/zzdir.c b/Build/source/libs/zziplib/bins/zzdir.c
new file mode 100644
index 00000000000..5345f0852da
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/zzdir.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2000,2001,2002 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB license.
+ */
+
+#include <zzip/zzip.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static const char usage[] =
+{
+ "zzdir <dir>.. \n"
+ " - prints a content table to stdout, but the dir can also be a zip-arch."
+ "\n"
+ " To show the contents of a zip-archive named 'test.zip', you may write \n"
+ " zzdir test \n"
+};
+
+int
+main (int argc, char ** argv)
+{
+ int argn;
+ int exitcode = 0;
+
+ if (argc <= 1 || ! strcmp (argv[1], "--help"))
+ {
+ printf (usage);
+ return 0;
+ }
+ if (! strcmp (argv[1], "--version"))
+ {
+ printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
+ return 0;
+ }
+
+ for (argn=1; argn < argc; argn++)
+ {
+ ZZIP_DIR * dir;
+ ZZIP_DIRENT * d;
+
+ dir = zzip_opendir(argv[argn]);
+ if (! dir)
+ {
+ fprintf (stderr, "did not open %s: ", argv[argn]);
+ perror(argv[argn]);
+ exitcode++;
+ continue;
+ }
+
+ if (argc > 2) printf ("%s: \n", argv[argn]);
+
+ /* read each dir entry and show one line of info per file */
+ while ((d = zzip_readdir (dir)))
+ {
+ /* orignalsize / compression-type / compression-ratio / filename */
+ if (d->st_size > 999999)
+ {
+ printf ("%5dK %-9s %2d%% %s \n",
+ d->st_size>>10,
+ zzip_compr_str(d->d_compr),
+ 100 - (d->d_csize|1)/((d->st_size/100)|1),
+ d->d_name);
+ }else{
+ printf ("%6d %-9s %2d%% %s \n",
+ d->st_size,
+ zzip_compr_str(d->d_compr),
+ 100 - (d->d_csize|1)*100/(d->st_size|1),
+ d->d_name);
+ }
+ }
+
+ zzip_closedir(dir);
+ }
+
+ return exitcode;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/bins/zzip.c b/Build/source/libs/zziplib/bins/zzip.c
new file mode 100644
index 00000000000..52237235698
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/zzip.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2003 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB license.
+ *
+ * This file is used as an example to clarify zzip api usage.
+ * (the write-api is work in progress, beware)
+ */
+
+#define _ZZIP_WRITE_SOURCE
+
+#include <zzip/zzip.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef ZZIP_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef ZZIP_HAVE_IO_H
+#include <io.h>
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static const char usage[] =
+{
+ "zzip <dir> files... \n"
+ " - zzip the files into a zip area."
+};
+
+int
+main (int argc, char ** argv)
+{
+ int argn;
+ int exitcode = 0;
+ ZZIP_DIR * dir;
+
+ if (argc <= 1 || ! strcmp (argv[1], "--help"))
+ {
+ printf (usage);
+ return 0;
+ }
+ if (! strcmp (argv[1], "--version"))
+ {
+ printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
+ return 0;
+ }
+
+ dir = zzip_dir_creat(argv[1], 0755);
+ if (! dir)
+ {
+ fprintf (stderr, "did not creat %s: \n", argv[1]);
+ perror(argv[1]);
+ if (1)
+ return 1;
+ else
+ fprintf (stderr, "(ignored)\n");
+ }
+
+ for (argn=2; argn < argc; argn++)
+ {
+ int input = open (argv[argn], O_RDONLY);
+ if (input == -1)
+ {
+ perror (argv[argn]);
+ continue;
+ }
+ else
+ {
+ char buf[17]; zzip_ssize_t n;
+ ZZIP_FILE* output = zzip_file_creat (dir, argv[argn], 0755);
+ if (! output)
+ {
+ fprintf (stderr, "|did not open %s: \n", argv[argn]);
+ fprintf (stderr, "|%s: %s\n", argv[argn],
+ zzip_strerror_of(dir));
+ continue;
+ }
+
+ while ((n = read (input, buf, 16)))
+ {
+ zzip_write (output, buf, n);
+ }
+ zzip_close (output);
+ }
+ close (input);
+ }
+ zzip_closedir(dir);
+
+ return exitcode;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/bins/zziplib.m4 b/Build/source/libs/zziplib/bins/zziplib.m4
new file mode 100644
index 00000000000..4029ca546e3
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/zziplib.m4
@@ -0,0 +1,105 @@
+dnl this macro has been copied from /usr/share/aclocal/pkg.m4
+dnl modified to check only for zziplib. You are advised to use
+dnl pgkconfig macro directly instead. It is only installed to
+dnl the convenience of software makers who do not want to have
+dnl yet another package dependency when building zziplib-based
+dnl projects. In general, you can include in your configure.ac
+dnl some line like
+dnl PKG_CHECK_ZZIPLIB([ZZIP],[0.10.75])
+dnl in order to get the two autoconf/automake subst variables
+dnl named ZZIP_CFLAGS and ZZIP_LIBS respectivly.
+
+dnl PKG_CHECK_ZZIPLIB(ZZIP, minversion, action-if, action-not)
+dnl defines ZZIP_LIBS, ZZIP_CFLAGS, see pkg-config man page
+dnl also defines ZZIP_PKG_ERRORS on error
+AC_DEFUN([PKG_CHECK_ZZIPLIB], [# checking for zziplib cflags/libs $2
+ succeeded=no
+
+ if test -z "$PKG_CONFIG"; then
+ AC_PATH_PROG([PKG_CONFIG],[pkg-config],[no])
+ fi
+
+ if test "$PKG_CONFIG" = "no" ; then
+ dnl we stick in an extra section that takes advantage of `zzip-config`
+ dnl script that might be there and carry cflags/libs info as well.
+ AC_PATH_PROG([ZZIP_CONFIG], [zzip-config], [no])
+ if test "$ZZIP_CONFIG" = "no" ; then
+ echo "*** Neither config spec could be found - there was no archaic"
+ echo "*** zzip-config script around and no pkg-config script in the"
+ echo "*** PATH. Make sure that either one is in your path, or set"
+ echo "*** set the PKG_CONFIG environment variable to the full"
+ echo "*** path to pkg-config. See http://zziplib.sf.net - or see"
+ echo "*** http://www.freedesktop.org/software/pkgconfig for more."
+ else
+ AC_MSG_CHECKING($1_LIBS)
+ $1_LIBS=`$ZZIP_CONFIG --libs 2>/dev/null`
+ AC_MSG_RESULT($[]$1_LIBS)
+
+ if test ".$[]$1_LIBS" != "." ; then
+ AC_MSG_CHECKING($1_CFLAGS)
+ $1_CFLAGS=`$ZZIP_CONFIG --cflags 2>/dev/null`
+ AC_MSG_RESULT($[]$1_CFLAGS)
+ succeeded="yes"
+ else
+ AC_MSG_CHECKING($1_CFLAGS)
+ $1_CFLAGS=`$ZZIP_CONFIG --cflags 2>&1`
+ AC_MSG_RESULT([(detecting errors...)])
+ AC_MSG_WARN([... there is a problem with zzip-config])
+ AC_MSG_WARN([... $[]$1_CFLAGS])
+ AC_MSG_WARN([... inference of library requirements from prefix])
+ succeeded=`echo $ZZIP_CONFIG | sed -e 's,/[^/]*,,'` # dirname
+ $1_CFLAGS=""
+ $1_LIBS=""
+ if test "/$succeeded" != "//usr" ; then
+ test -d "$succeeded/include" && $1_CFLAGS="-I$succeeded/include "
+ test -d "$succeeded/lib" && $1_LIBS="-L$succeeded/lib "
+ fi
+ $1_LIBS="$[]$1_LIBS -lzzip -lz"
+ succeeded="yes"
+ AC_MSG_CHECKING($1_CFLAGS... guessed)
+ AC_MSG_RESULT($[]$1_CFLAGS)
+ AC_MSG_CHECKING($1_LIBS... guessed)
+ AC_MSG_RESULT($[]$1_LIBS)
+ fi
+ fi
+ else
+ PKG_CONFIG_MIN_VERSION=0.9.0
+ if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
+ AC_MSG_CHECKING(for zziplib[]ifelse([$2],,,[ >= $2]))
+
+ if $PKG_CONFIG --exists "zziplib[]ifelse([$2],,,[ >= $2])" ; then
+ AC_MSG_RESULT(yes)
+ succeeded=yes
+
+ AC_MSG_CHECKING($1_CFLAGS)
+ $1_CFLAGS=`$PKG_CONFIG --cflags "zziplib[]ifelse([$2],,,[ >= $2])"`
+ AC_MSG_RESULT($$1_CFLAGS)
+
+ AC_MSG_CHECKING($1_LIBS)
+ $1_LIBS=`$PKG_CONFIG --libs "zziplib[]ifelse([$2],,,[ >= $2])"`
+ AC_MSG_RESULT($$1_LIBS)
+ else
+ $1_CFLAGS=""
+ $1_LIBS=""
+ ## If we have a custom action on failure, don't print errors, but
+ ## do set a variable so people can do so.
+ $1_PKG_ERRORS=`$PKG_CONFIG dnl
+ --errors-to-stdout --print-errors "zziplib[]ifelse([$2],,,[ >= $2])"`
+ ifelse([$4], ,echo $$1_PKG_ERRORS,)
+ fi
+
+ AC_SUBST($1_CFLAGS)
+ AC_SUBST($1_LIBS)
+ else
+ echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
+ echo "*** See http://www.freedesktop.org/software/pkgconfig"
+ fi
+ fi
+
+ if test $succeeded = yes; then
+ ifelse([$3], , :, [$3])
+ else
+ succeeded="zziplib[]ifelse([$2],,,[ >= $2])"
+ ifelse([$4], ,[AC_MSG_ERROR([Library requirements ($succeeded) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.])], [$4])
+ fi
+])
diff --git a/Build/source/libs/zziplib/bins/zziptest.c b/Build/source/libs/zziplib/bins/zziptest.c
new file mode 100644
index 00000000000..eb82afe7682
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/zziptest.c
@@ -0,0 +1,153 @@
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ * Tomi Ollila <Tomi.Ollila@iki.fi>
+ *
+ * Copyright (c) 1999,2000,2001,2002,2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined _MSC_VER /* Win32*/
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#define sleep Sleep
+#endif
+
+#include <zzip/lib.h>
+
+#ifdef ZZIP_HAVE_UNISTD_H
+#include <unistd.h> /* sleep */
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#if __GNUC__+0 >= 3 && __GNUC_MINOR__+0 >= 3
+# ifdef DEBUG
+# warning suppress a warning where the compiler should have optimized instead.
+# endif
+#define I_(_T,_L,_R) do { _T _l = (_T) _L; \
+ _l _R; _L = (typeof(_L)) _l; } while(0)
+#else
+#define I_(_T,_L,_R) _L _R
+#endif
+
+int main(int argc, char ** argv)
+{
+ ZZIP_DIR * dir;
+ const char * name = "test.zip";
+ zzip_error_t rv;
+ int i;
+
+ if (argc > 1 && argv[1] != NULL)
+ {
+ if (! strcmp (argv[1], "--help")) {
+ printf ("zziptest [testfile]\n - selftest defaults to 'test.zip'");
+ return 0;
+ }else if (! strcmp (argv[1], "--version")) {
+ printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
+ return 0;
+ }else{
+ name = argv[1];
+ argv++; argc--;
+ }
+ }
+
+ printf("Opening zip file `%s'... ", name);
+ { int fd = open (name, O_RDONLY|O_BINARY);
+ if (fd == -1) { perror ("could not open input file"); return 0; }
+ if (! (dir = zzip_dir_fdopen(fd, &rv)))
+ {
+ printf("error %d.\n", rv);
+ return 0;
+ }
+ } printf("OK.\n");
+
+#if 1
+ printf("{check...\n");
+ { struct zzip_dir_hdr * hdr = dir->hdr0;
+
+ if (hdr == NULL)
+ { printf ("could not find first header in dir_hdr"); }
+ else
+ {
+ while (1)
+ {
+ printf("\ncompression method: %d", hdr->d_compr);
+ if (hdr->d_compr == 0) printf(" (stored)");
+ else if (hdr->d_compr == 8) printf(" (deflated)");
+ else printf(" (unknown)");
+ printf("\ncrc32: %x\n", hdr->d_crc32);
+ printf("compressed size: %d\n", hdr->d_csize);
+ printf("uncompressed size: %d\n", hdr->d_usize);
+ printf("offset of file in archive: %d\n", hdr->d_off);
+ printf("filename: %s\n\n", hdr->d_name);
+
+ if (hdr->d_reclen == 0) break;
+ I_(char *, hdr, += hdr->d_reclen);
+ sleep(1);
+ }
+ }
+ } printf ("\n}\n");
+#endif
+#if 1
+ { printf("{contents...\n");
+ for (i = 0; i < 2; i++)
+ {
+ ZZIP_DIRENT* d;
+
+ while((d=zzip_readdir(dir)))
+ {
+ printf(" name \"%s\", compr %d, size %d, ratio %2d\n",
+ d->d_name, d->d_compr, d->st_size,
+ 100 - (d->d_csize|1)*100/(d->st_size|1));
+ }
+ printf(" %d. time ---------------\n", i + 1);
+ zzip_rewinddir(dir);
+ }
+ printf("}...OK\n");
+ }
+#endif
+
+ { ZZIP_FILE * fp;
+ char buf[17];
+ const char * name = argv[1]? argv[1]: "README";
+
+
+ printf("Opening file `%s' in zip archive... ", name);
+ fp = zzip_file_open(dir, (char *)name, ZZIP_CASEINSENSITIVE);
+
+ if (! fp)
+ { printf("error %d: %s\n", zzip_error(dir), zzip_strerror_of(dir)); }
+ else
+ {
+ printf("OK.\n");
+ printf("Contents of the file:\n");
+
+ while (0 < (i = zzip_file_read(fp, buf, 16)))
+ {
+ buf[i] = '\0';
+ /*printf("\n*** read %d ***\n", i); fflush(stdout); */
+ printf("%s", buf);
+ /*write(1, buf, i);*/ /* Windows does not have write !!! */
+ }
+ if (i < 0) printf("error %d\n", zzip_error(dir));
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/bins/zzobfuscated.c b/Build/source/libs/zziplib/bins/zzobfuscated.c
new file mode 100644
index 00000000000..352afc29a13
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/zzobfuscated.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2002 Mike Nordell
+ * portions Copyright (c) 2000,2001,2002 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB License
+ *
+ * A small example that displays how the plugin I/O functions can be used
+ * to read "encrypted" zip archives.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <zzip/zzip.h>
+#include <zzip/plugin.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#if defined ZZIP_HAVE_UNISTD_H
+#include <unistd.h> /* read */
+#elif defined ZZIP_HAVE_IO_H
+#include <io.h> /* win32 */
+#else
+#endif
+
+#ifdef _MSC_VER
+#define _MSC_VER_NULL NULL
+#else
+#define _MSC_VER_NULL
+#endif
+
+/*
+ * Only override our the read handler. Let the system take care
+ * the rest.
+ */
+
+static zzip_ssize_t our_read(int fd, void* buf, zzip_size_t len)
+{
+ const zzip_ssize_t bytes = read(fd, buf, len);
+ zzip_ssize_t i;
+ char* pch = (char*)buf;
+ for (i=0; i<bytes; ++i) {
+ pch[i] ^= 0x55;
+ }
+ return bytes;
+}
+
+static zzip_plugin_io_handlers our_handlers = { _MSC_VER_NULL };
+static const char* const our_fileext [] = { ".dat", ".sav", 0 };
+
+
+static const char usage[] =
+{
+ " zzobfuscated <file> [in-zip filename]\n"
+ " - Demonstrates the use of installable file I/O handlers.\n"
+ " Copies <file> to \"obfuscated[.dat]\" while \"encrypting\" it by xor'ing\n"
+ " every byte with 0x55, installs file I/O handlers, and then uses the\n"
+ " zzip_open_ext_io function to read and print the file to stdout.\n"
+ " The file can be a normal file or an inflated part of a zip-archive,\n"
+ " to get 'README' from test.zip you may write \n"
+ " zzobfuscated test.zip README \n"
+};
+
+int
+main (int argc, char* argv[])
+{
+ if (argc <= 1 || argc > 3 || ! strcmp (argv[1], "--help"))
+ {
+ printf (usage);
+ return 0;
+ }
+ if (! strcmp (argv[1], "--version"))
+ {
+ printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
+ return 0;
+ }
+
+ if (strlen(argv[1]) > 128) {
+ fprintf(stderr, "Please provide a filename shorter than 128 chars.\n");
+ exit(1);
+ }
+
+ /* obfuscate the file */
+ {
+ int ch;
+ FILE* fin;
+ FILE* fout;
+ fin = fopen(argv[1], "rb");
+ if (!fin) {
+ fprintf(stderr, "Can't open input file \"%s\"\n", argv[1]);
+ exit(1);
+ }
+ fout = fopen((argc == 2) ? "obfuscated" : "obfuscated.dat", "wb");
+ if (!fout) {
+ fprintf(stderr, "Can't open output file \"obfuscated\"\n");
+ exit(1);
+ }
+ while ((ch = fgetc(fin)) != EOF) {
+ ch ^= 0x55;
+ fputc(ch, fout);
+ }
+ fclose(fout);
+ fclose(fin);
+ }
+
+ /* install our I/O hander */
+ zzip_init_io(&our_handlers, 0);
+ our_handlers.fd.read = &our_read;
+
+ {
+# define argn 2
+ ZZIP_FILE* fp;
+ char name[256];
+ if (argc == 3) {
+ sprintf(name, "obfuscated/%s", argv[argn]);
+ } else {
+ sprintf(name, "obfuscated");
+ }
+ fp = zzip_open_ext_io (name, O_RDONLY|O_BINARY, ZZIP_PREFERZIP,
+ our_fileext, &our_handlers);
+
+ if (! fp)
+ {
+ perror (name);
+ exit(1);
+ }else{
+ char buf[17];
+ int n;
+
+ /* read chunks of 16 bytes into buf and print them to stdout */
+ while (0 < (n = zzip_read(fp, buf, 16)))
+ {
+ buf[n] = '\0';
+# ifdef STDOUT_FILENO
+ write (STDOUT_FILENO, buf, n);
+# else
+ fwrite (buf, 1, n, stdout);
+# endif
+ }
+
+ if (n == -1)
+ perror (argv[argn]);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/bins/zzxorcat.c b/Build/source/libs/zziplib/bins/zzxorcat.c
new file mode 100644
index 00000000000..97fcd51fd32
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/zzxorcat.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2000,2001,2002 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB License
+ *
+ * show zip-reading with xor-obfuscation.
+ * Note that the difference to the standard zzcat.c is quite small.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <zzip/zzip.h>
+#include <zzip/plugin.h>
+
+#if defined ZZIP_HAVE_UNISTD_H
+#include <unistd.h>
+#elif defined ZZIP_HAVE_IO_H
+#include <io.h>
+#else
+#error need posix io for this example
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static const char usage[] =
+{
+ " zzxorcat [-#] <file>... \n"
+ " - prints the file to stdout, so you may want to redirect the output; \n"
+ " the file is part of an inflated zip-archive obfuscated with xor value,\n"
+ " given by the numeric option (default is 0x55). \n"
+ " to get 'README' from dist.dat you may write \n"
+ " zzcat dist/README \n"
+};
+
+static int xor_value;
+
+static zzip_ssize_t xor_read (int f, void* p, zzip_size_t l)
+{
+ zzip_ssize_t r = read(f, p, l);
+ zzip_ssize_t x; char* q; for (x=0, q=p; x < r; x++) q[x] ^= xor_value;
+ return r;
+}
+
+static zzip_plugin_io_handlers xor_handlers;
+static zzip_strings_t xor_fileext[] = { ".dat", "", 0 };
+
+int
+main (int argc, char ** argv)
+{
+ int argn;
+ xor_value = 0x55;
+
+ if (argc <= 1 || ! strcmp (argv[1], "--help"))
+ {
+ printf (usage);
+ return 0;
+ }
+ if (! strcmp (argv[1], "--version"))
+ {
+ printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
+ return 0;
+ }
+
+ zzip_init_io (&xor_handlers, 0); xor_handlers.fd.read = &xor_read;
+
+ for (argn=1; argn < argc; argn++)
+ {
+ ZZIP_FILE* fp;
+
+ if (argv[argn][0] == '-')
+ {
+ if (isdigit(argv[argn][1])) xor_value = atoi (argv[argn]+1);
+ continue;
+ }
+
+ fp = zzip_open_ext_io (argv[argn], O_RDONLY|O_BINARY,
+ ZZIP_CASELESS|ZZIP_ONLYZIP,
+ xor_fileext, &xor_handlers);
+ if (! fp)
+ {
+ perror (argv[argn]);
+ continue;
+ }else{
+ char buf[17];
+ zzip_ssize_t n;
+
+ /* read chunks of 16 bytes into buf and print them to stdout */
+ while (0 < (n = zzip_read(fp, buf, 16)))
+ {
+ buf[n] = '\0';
+# ifdef STDOUT_FILENO
+ write (STDOUT_FILENO, buf, n);
+# else
+ fwrite (buf, 1, n, stdout);
+# endif
+ }
+
+ if (n == -1)
+ perror (argv[n]);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/bins/zzxorcopy.c b/Build/source/libs/zziplib/bins/zzxorcopy.c
new file mode 100644
index 00000000000..1c06e534126
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/zzxorcopy.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2000,2001,2002 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB License
+ *
+ * show a simple program to add xor-obfuscation.
+ * look at the resulting file with zzxordir an zzxorcat
+ * Remember that xor'ing data twice will result in the original data.
+ * This file has no dependency with zziplib - it's freestanding.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <zzip/_config.h> /* for ZZIP_VERSION */
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#if __STDC_VERSION__+0 < 199901
+#define _ssize_t int
+#define _size_t unsigned
+#else
+#define _ssize_t ssize_t
+#define _size_t size_t
+#endif
+
+static const char usage[] =
+{
+ " zzxopy [-#] <input-file> <output-file> \n"
+ " copies data from input-file to output-file adding simple \n"
+ " obfuscation by xor-ing each byte with the numeric value given. \n"
+ " the default xor-value is 0x55. Remember that copying data twice \n"
+ " with the same xor-value will result in the original file data. \n"
+};
+
+static int xor_value;
+
+static _ssize_t xor_read (FILE* f, void* p, _size_t l)
+{
+ _ssize_t r = fread(p, 1, l, f);
+ _ssize_t x; char* q; for (x=0, q=p; x < r; x++) q[x] ^= xor_value;
+ return r;
+}
+
+int
+main (int argc, char ** argv)
+{
+ int argn;
+ xor_value = 0x55;
+
+ if (argc <= 1 || ! strcmp (argv[1], "--help"))
+ {
+ printf (usage);
+ return 0;
+ }
+ if (! strcmp (argv[1], "--version"))
+ {
+ printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
+ return 0;
+ }
+
+ for (argn=1; argn < argc; argn++)
+ {
+ FILE* iF = 0;
+ FILE* oF = 0;
+
+ if (argv[argn][0] == '-')
+ {
+ if (isdigit(argv[argn][1])) xor_value = atoi (argv[argn]+1);
+ continue;
+ }
+
+ if (argn + 1 >= argc)
+ {
+ printf (usage);
+ exit (1);
+ }
+
+ iF = fopen (argv[argn], "rb");
+ if (! iF) { perror (argv[argn]); exit (2); }
+ argn++;
+ oF = fopen (argv[argn], "wb");
+ if (! oF) { perror (argv[argn]); fclose(iF); exit (3); }
+
+ {
+ char buf[17];
+ _ssize_t n;
+
+ /* read chunks of 16 bytes into buf and print them to stdout */
+ while (0 < (n = xor_read(iF, buf, 16)))
+ {
+ buf[n] = '\0';
+ n = fwrite (buf, 1, n, oF);
+ if (n < 0) break;
+ }
+
+ if (n < 0 && ferror (iF))
+ perror (argv[argn]);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/bins/zzxordir.c b/Build/source/libs/zziplib/bins/zzxordir.c
new file mode 100644
index 00000000000..c1e1f141446
--- /dev/null
+++ b/Build/source/libs/zziplib/bins/zzxordir.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2000,2001,2002 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB license.
+ *
+ * show zip-reading with xor-obfuscation.
+ * Note that the difference to the standard zzdir.c is quite small.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <zzip/zzip.h>
+#include <zzip/plugin.h>
+
+#if defined ZZIP_HAVE_UNISTD_H
+#include <unistd.h>
+#elif defined ZZIP_HAVE_IO_H
+#include <io.h>
+#else
+#error need posix io for this example
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static const char usage[] =
+{
+ "zzdir <dir>.. \n"
+ " - prints a content table to stdout, but the dir can also be a zip-arch."
+ "\n"
+ " the file is part of an inflated zip-archive obfuscated with xor value,\n"
+ " given by the numeric option (default is 0x55). \n"
+ "\n"
+ " To show the contents of a zip-archive named 'test.zip', you may write \n"
+ " zzdir test \n"
+};
+
+static int xor_value;
+
+static zzip_ssize_t xor_read (int f, void* p, zzip_size_t l)
+{
+ zzip_ssize_t r = read(f, p, l);
+ zzip_ssize_t x; char* q; for (x=0, q=p; x < r; x++) q[x] ^= xor_value;
+ return r;
+}
+
+static zzip_plugin_io_handlers xor_handlers = { };
+static zzip_strings_t xor_fileext[] = { ".dat", "", 0 };
+
+int
+main (int argc, char ** argv)
+{
+ int argn;
+ int exitcode = 0;
+ xor_value = 0x55;
+
+ if (argc <= 1 || ! strcmp (argv[1], "--help"))
+ {
+ printf (usage);
+ return 0;
+ }
+ if (! strcmp (argv[1], "--version"))
+ {
+ printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
+ return 0;
+ }
+
+ zzip_init_io (&xor_handlers, 0); xor_handlers.fd.read = &xor_read;
+
+ for (argn=1; argn < argc; argn++)
+ {
+ ZZIP_DIR * dir;
+ ZZIP_DIRENT * d;
+
+ if (argv[argn][0] == '-')
+ {
+ if (isdigit(argv[argn][1])) xor_value = atoi (argv[argn]+1);
+ continue;
+ }
+
+ dir = zzip_opendir_ext_io(argv[argn],
+ ZZIP_ONLYZIP, xor_fileext, &xor_handlers);
+ if (! dir)
+ {
+ fprintf (stderr, "did not open %s: ", argv[argn]);
+ perror(argv[argn]);
+ exitcode++;
+ continue;
+ }
+
+ if (argc > 2) printf ("%s: \n", argv[argn]);
+
+ /* read each dir entry and show one line of info per file */
+ while ((d = zzip_readdir (dir)))
+ {
+ /* orignalsize / compression-type / compression-ratio / filename */
+ if (d->st_size > 999999)
+ {
+ printf ("%5dK %-9s %2d%% %s \n",
+ d->st_size>>10,
+ zzip_compr_str(d->d_compr),
+ 100 - (d->d_csize|1)/((d->st_size/100)|1),
+ d->d_name);
+ }else{
+ printf ("%6d %-9s %2d%% %s \n",
+ d->st_size,
+ zzip_compr_str(d->d_compr),
+ 100 - (d->d_csize|1)*100/(d->st_size|1),
+ d->d_name);
+ }
+ }
+
+ zzip_closedir(dir);
+ }
+
+ return exitcode;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/config.h.in b/Build/source/libs/zziplib/config.h.in
new file mode 100644
index 00000000000..ef1f9971edc
--- /dev/null
+++ b/Build/source/libs/zziplib/config.h.in
@@ -0,0 +1,160 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the <byteswap.h> header file. */
+#undef HAVE_BYTESWAP_H
+
+/* Define to 1 if you have the <direct.h> header file. */
+#undef HAVE_DIRECT_H
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_DIRENT_H
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <fnmatch.h> header file. */
+#undef HAVE_FNMATCH_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <io.h> header file. */
+#undef HAVE_IO_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strndup' function. */
+#undef HAVE_STRNDUP
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_DIR_H
+
+/* Define to 1 if you have the <sys/int_types.h> header file. */
+#undef HAVE_SYS_INT_TYPES_H
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <winbase.h> header file. */
+#undef HAVE_WINBASE_H
+
+/* Define to 1 if you have the <windows.h> header file. */
+#undef HAVE_WINDOWS_H
+
+/* Define to 1 if you have the <winnt.h> header file. */
+#undef HAVE_WINNT_H
+
+/* Define to 1 if you have the <zlib.h> header file. */
+#undef HAVE_ZLIB_H
+
+/* whether the system defaults to 32bit off_t but can do 64bit when requested
+ */
+#undef LARGEFILE_SENSITIVE
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The number of bytes in type int */
+#undef SIZEOF_INT
+
+/* The number of bytes in type long */
+#undef SIZEOF_LONG
+
+/* The number of bytes in type short */
+#undef SIZEOF_SHORT
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to `long long' if <sys/types.h> does not define. */
+#undef __int64
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to `_zzip_off_t' if <sys/types.h> does not define. */
+#undef off64_t
+
+/* Define to `long' if <sys/types.h> does not define. */
+#undef off_t
+
+/* Define to equivalent of C99 restrict keyword, or to nothing if this is not
+ supported. Do not define if restrict is supported directly. */
+#undef restrict
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef ssize_t
diff --git a/Build/source/libs/zziplib/configure b/Build/source/libs/zziplib/configure
new file mode 100755
index 00000000000..a31235f4abf
--- /dev/null
+++ b/Build/source/libs/zziplib/configure
@@ -0,0 +1,25785 @@
+#! /bin/sh
+# From configure.ac Revision: 1.6 .
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+#
+# Guido Draheim <guido@gmx.de> for ZZipLib.SF.net
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','`
+ ;;
+esac
+
+echo=${ECHO-echo}
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if (echo_test_string=`eval $cmd`) 2>/dev/null &&
+ echo_test_string=`eval $cmd` &&
+ (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+ then
+ break
+ fi
+ done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ if test "X$echo" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ echo='print -r'
+ elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
+ else
+ # Try using printf.
+ echo='printf %s\n'
+ if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+ if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "$0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ echo=echo
+ fi
+ fi
+ fi
+ fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+ ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
+fi
+
+
+
+
+tagnames=${tagnames+${tagnames},}CXX
+
+tagnames=${tagnames+${tagnames},}F77
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete. It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="zziplib.spec"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os ax_enable_builddir_sed THREAD_SAFE ZLIB_INCL ZLIB_LDIR INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB DLLTOOL ac_ct_DLLTOOL AS ac_ct_AS OBJDUMP ac_ct_OBJDUMP CPP CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL RELEASE_INFO VERSION_INFO MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT pkgconfig_libdir pkgconfig_libfile PERL PYTHON MKZIP XMLTO LARGEFILE_CFLAGS ZLIB_VERSION docdir SDL ZIPTESTS ZZIPLIB_LDFLAGS RESOLVES PKG_CONFIG pkgconfigdir aclocaldir CONFIG_FILES LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_option in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ eval "enable_$ac_feature=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_$ac_feature='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_$ac_package='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/-/_/g'`
+ eval "with_$ac_package=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ eval "$ac_envvar='$ac_optarg'"
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+ localstatedir libdir includedir oldincludedir infodir mandir
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+ { (exit 1); exit 1; }; }
+ else
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+ fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+ { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+ac_env_CXX_set=${CXX+set}
+ac_env_CXX_value=$CXX
+ac_cv_env_CXX_set=${CXX+set}
+ac_cv_env_CXX_value=$CXX
+ac_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_env_CXXFLAGS_value=$CXXFLAGS
+ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_cv_env_CXXFLAGS_value=$CXXFLAGS
+ac_env_CXXCPP_set=${CXXCPP+set}
+ac_env_CXXCPP_value=$CXXCPP
+ac_cv_env_CXXCPP_set=${CXXCPP+set}
+ac_cv_env_CXXCPP_value=$CXXCPP
+ac_env_F77_set=${F77+set}
+ac_env_F77_value=$F77
+ac_cv_env_F77_set=${F77+set}
+ac_cv_env_F77_value=$F77
+ac_env_FFLAGS_set=${FFLAGS+set}
+ac_env_FFLAGS_value=$FFLAGS
+ac_cv_env_FFLAGS_set=${FFLAGS+set}
+ac_cv_env_FFLAGS_value=$FFLAGS
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+ cat <<_ACEOF
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --infodir=DIR info documentation [PREFIX/info]
+ --mandir=DIR man documentation [PREFIX/man]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-builddir disable automatic build in subdir of sources
+
+ --disable-thread-safe disable thread-safe libtool option
+
+ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors
+ --enable-shared[=PKGS]
+ build shared libraries [default=yes]
+ --enable-static[=PKGS]
+ build static libraries [default=yes]
+ --enable-fast-install[=PKGS]
+ optimize for fast installation [default=yes]
+ --disable-libtool-lock avoid locking (might break parallel builds)
+ --enable-maintainer-mode enable make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer
+ --disable-largefile omit support for large files
+ --disable-mmap disable mmap usage
+
+ --enable-sdl enable SDL usage (if present)
+
+ --enable-frame-pointer enable callframe generation for debugging
+ --enable-default-pkgconfigdir(=PATH) override the libdir/pkgconfig default
+ --enable-default-aclocaldir(=PATH) override the datadir/aclocal default
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-zlib zlib prefix (e.g. '$HOME/software')
+
+ --with-gnu-ld assume the C compiler uses GNU ld [default=no]
+ --with-pic try to use only PIC/non-PIC objects [default=use
+ both]
+ --with-tags[=TAGS]
+ include additional configurations [automatic]
+ --with-largefile compile as off64_t instead of 32bit off_t
+
+ --with-docdir docdir prefix (prefix/share/doc)
+
+ --with-debug debug messages in library
+
+ --with-lowstk limited thread stack
+
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
+ headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ CXXCPP C++ preprocessor
+ F77 Fortran 77 compiler command
+ FFLAGS Fortran 77 compiler flags
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ ac_popdir=`pwd`
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d $ac_dir || continue
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+ cd $ac_dir
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_srcdir/configure.gnu; then
+ echo
+ $SHELL $ac_srcdir/configure.gnu --help=recursive
+ elif test -f $ac_srcdir/configure; then
+ echo
+ $SHELL $ac_srcdir/configure --help=recursive
+ elif test -f $ac_srcdir/configure.ac ||
+ test -f $ac_srcdir/configure.in; then
+ echo
+ $ac_configure --help
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi
+ cd $ac_popdir
+ done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+ cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+
+Guido Draheim <guido@gmx.de> for ZZipLib.SF.net
+_ACEOF
+ exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+ # Get rid of the leading space.
+ ac_sep=" "
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+{
+ (set) 2>&1 |
+ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ sed -n \
+ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+ ;;
+ *)
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+}
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ sed "/^$/d" confdefs.h | sort
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core &&
+ rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+ ' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . $cache_file;;
+ *) . ./$cache_file;;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+ eval ac_new_val="\$ac_env_${ac_var}_value"
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_aux_dir=
+for ac_dir in uses $srcdir/uses; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f $ac_dir/shtool; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in uses $srcdir/uses" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in uses $srcdir/uses" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# =======================================================================
+# Make sure we can run config.sub.
+$ac_config_sub sun4 >/dev/null 2>&1 ||
+ { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5
+echo "$as_me: error: cannot run $ac_config_sub" >&2;}
+ { (exit 1); exit 1; }; }
+
+echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6
+if test "${ac_cv_build+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_build_alias=$build_alias
+test -z "$ac_cv_build_alias" &&
+ ac_cv_build_alias=`$ac_config_guess`
+test -z "$ac_cv_build_alias" &&
+ { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+ { (exit 1); exit 1; }; }
+ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
+ { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6
+build=$ac_cv_build
+build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6
+if test "${ac_cv_host+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_host_alias=$host_alias
+test -z "$ac_cv_host_alias" &&
+ ac_cv_host_alias=$ac_cv_build_alias
+ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
+ { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6
+host=$ac_cv_host
+host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking target system type" >&5
+echo $ECHO_N "checking target system type... $ECHO_C" >&6
+if test "${ac_cv_target+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_target_alias=$target_alias
+test "x$ac_cv_target_alias" = "x" &&
+ ac_cv_target_alias=$ac_cv_host_alias
+ac_cv_target=`$ac_config_sub $ac_cv_target_alias` ||
+ { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_target_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_target_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_target" >&5
+echo "${ECHO_T}$ac_cv_target" >&6
+target=$ac_cv_target
+target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+ax_enable_builddir="."
+# Check whether --enable-builddir or --disable-builddir was given.
+if test "${enable_builddir+set}" = set; then
+ enableval="$enable_builddir"
+ ax_enable_builddir="$enableval"
+else
+ ax_enable_builddir="yes"
+fi;
+if test ".$ac_srcdir_defaulted" != ".no" ; then
+if test ".$srcdir" = ".." ; then
+ if test -f config.status ; then
+ { echo "$as_me:$LINENO: toplevel srcdir already configured... skipping subdir build" >&5
+echo "$as_me: toplevel srcdir already configured... skipping subdir build" >&6;}
+ else
+ test ".$ax_enable_builddir" = "." && ax_enable_builddir="."
+ test ".$ax_enable_builddir" = ".no" && ax_enable_builddir="."
+ test ".$BUILD" = "." && BUILD=`uname -msr | tr " /" "__"`.d
+ test ".$ax_enable_builddir" = ".yes" && ax_enable_builddir="$BUILD"
+ if test ".$ax_enable_builddir" != ".." ; then # we know where to go and
+ { if $as_mkdir_p; then
+ mkdir -p $ax_enable_builddir
+ else
+ as_dir=$ax_enable_builddir
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory $ax_enable_builddir" >&5
+echo "$as_me: error: cannot create directory $ax_enable_builddir" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ echo __.$ax_enable_builddir.__ > $ax_enable_builddir/conftest.tmp
+ cd $ax_enable_builddir
+ if grep __.$ax_enable_builddir.__ conftest.tmp >/dev/null 2>/dev/null ; then
+ rm conftest.tmp
+ echo "$as_me:$LINENO: result: continue configure in default builddir \"./$ax_enable_builddir\"" >&5
+echo "${ECHO_T}continue configure in default builddir \"./$ax_enable_builddir\"" >&6
+ else
+ { { echo "$as_me:$LINENO: error: could not change to default builddir \"./$ax_enable_builddir\"" >&5
+echo "$as_me: error: could not change to default builddir \"./$ax_enable_builddir\"" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ srcdir=`echo "$ax_enable_builddir" |
+ sed -e 's,^\./,,;s,[^/]$,&/,;s,[^/]*/,../,g;s,[/]$,,;'`
+ # going to restart from subdirectory location
+ test -f $srcdir/config.log && mv $srcdir/config.log .
+ test -f $srcdir/confdefs.h && mv $srcdir/confdefs.h .
+ test -f $srcdir/conftest.log && mv $srcdir/conftest.log .
+ test -f $srcdir/$cache_file && mv $srcdir/$cache_file .
+ echo "$as_me:$LINENO: result: ....exec $SHELL $srcdir/$0 \"--srcdir=$srcdir\" \"--enable-builddir=$ax_enable_builddir\" ${1+\"$@\"}" >&5
+echo "${ECHO_T}....exec $SHELL $srcdir/$0 \"--srcdir=$srcdir\" \"--enable-builddir=$ax_enable_builddir\" ${1+\"$@\"}" >&6
+ case "$0" in # restart
+ /\\) exec $SHELL $0 "--srcdir=$srcdir" "--enable-builddir=$ax_enable_builddir" ${1+"$@"} ;;
+ *) exec $SHELL $srcdir/$0 "--srcdir=$srcdir" "--enable-builddir=$ax_enable_builddir" ${1+"$@"} ;;
+ esac
+ fi
+ fi
+fi fi
+# Extract the first word of "gsed sed", so it can be a program name with args.
+set dummy gsed sed; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_ax_enable_builddir_sed+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $ax_enable_builddir_sed in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ax_enable_builddir_sed="$ax_enable_builddir_sed" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_ax_enable_builddir_sed="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_path_ax_enable_builddir_sed" && ac_cv_path_ax_enable_builddir_sed="sed"
+ ;;
+esac
+fi
+ax_enable_builddir_sed=$ac_cv_path_ax_enable_builddir_sed
+
+if test -n "$ax_enable_builddir_sed"; then
+ echo "$as_me:$LINENO: result: $ax_enable_builddir_sed" >&5
+echo "${ECHO_T}$ax_enable_builddir_sed" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ ac_config_commands="$ac_config_commands buildir"
+
+ # --------------------------------------------
+case "$prefix:$ac_default_prefix" in
+ NONE:/usr/local)
+ result=""
+ echo "$as_me:$LINENO: checking default prefix path" >&5
+echo $ECHO_N "checking default prefix path... $ECHO_C" >&6
+ case "${target_os}" in
+ *cygwin* | *mingw* | *uwin* | *djgpp | *emx* )
+ if test "${host_os}" = "${target_os}" ; then
+ ac_default_prefix="/programs"
+ result="(win/dos target)"
+ else
+ case "$PATH" in
+ *:/usr/local/cross-tools/$target_alias/bin:*)
+ ac_default_prefix="/usr/local/cross-tools/$target_alias" ;;
+ *:/usr/local/$target_alias/bin:*)
+ ac_default_prefix="/usr/local/$target_alias" ;;
+ *:/usr/local/$target_cpu-$target_os/bin:*)
+ ac_default_prefix="/usr/local/$target_cpu-$target_os" ;;
+ *)
+ ac_default_prefix="/programs" ;;
+ esac
+ result="(win/dos cross-compiler)"
+ fi
+ ;;
+ esac
+ echo "$as_me:$LINENO: result: $ac_default_prefix $result" >&5
+echo "${ECHO_T}$ac_default_prefix $result" >&6
+ ;;
+esac
+echo "$as_me:$LINENO: checking default prefix system" >&5
+echo $ECHO_N "checking default prefix system... $ECHO_C" >&6
+result="$prefix" ; test "$result" = "NONE" && result="$ac_default_prefix"
+case ${result} in
+ /programs | /programs/*) result="is win-/programs"
+ # on win/dos, .exe .dll and .cfg live in the same directory
+ libdir=`echo $libdir |sed -e 's:^..exec_prefix./lib$:${bindir}:'`
+ sbindir=`echo $sbindir |sed -e 's:^..exec_prefix./sbin$:${libdir}:'`
+ sysconfdir=`echo $sysconfdir |sed -e 's:^..prefix./etc$:${sbindir}:'`
+ libexecdir=`echo $libexecdir |sed -e 's:/libexec$:/system:'`
+ # help-files shall be set with --infodir, docprefix is datadir
+ docprefix="${datadir}"
+ mandir=`echo $mandir \
+ |sed -e 's:^..prefix./man$:${datadir}/info:'`
+ includedir=`echo $includedir \
+ |sed -e 's:^..prefix./include$:${datadir}/include:'`
+ # other state files (but /etc) are moved to datadir
+ sharedstatedir=`echo $sharedstatedir \
+ |sed -e 's:^..prefix./com$:${datadir}/default:'`
+ localstatedir=`echo $localstatedir \
+ |sed -e 's:^..prefix./var$:${datadir}/current:'`
+ ;;
+ /usr) result="is /usr-shipped"
+ # doc files are left at prefix
+ docprefix="${prefix}"
+ # state files go under /top
+ sysconfdir=`echo $sysconfdir |sed -e 's:^..prefix./etc$:/etc:'`
+ sharedstatedir=`echo $sharedstatedir \
+ |sed -e 's:^..prefix./com$:/etc/default:'`
+ # $prefix/var is going to end up in /var/lib
+ localstatedir=`echo $localstatedir \
+ |sed -e 's:^..prefix./var$:/var/lib:'`
+ ;;
+ /opt | /opt/*) result="is /opt-package"
+ # state files go under /top/prefix
+ sysconfdir=`echo $sysconfdir \
+ |sed -e 's:^..prefix./etc$:/etc${prefix}:'`
+ sharedstatedir=`echo $sharedstatedir \
+ |sed -e 's:^..prefix./com$:/etc/default${prefix}:'`
+ # $prefix/var is going to to be /var$prefix... once again
+ localstatedir=`echo $localstatedir \
+ |sed -e 's:^..prefix./var$:/var${prefix}:'`
+ # doc files are left at prefix
+ docprefix="${prefix}"
+ ;;
+ *) result="is /local-package"
+ # doc files are moved from prefix down to datadir
+ docprefix="${datadir}"
+ mandir=`echo $mandir \
+ |sed -e 's:^..prefix./man$:${datadir}/man:'`
+ infodir=`echo $infodir \
+ |sed -e 's:^..prefix./infodir$:${datadir}/info:'`
+ # never use $prefix/com - that is no good idea
+ sharedstatedir=`echo $sharedstatedir \
+ |sed -e 's:^..prefix./com$:${sysconfdir}/default:'`
+ ;;
+esac
+echo "$as_me:$LINENO: result: $result" >&5
+echo "${ECHO_T}$result" >&6
+# --------------------------------------------------------
+
+# -----------------------------------------------------------------------
+# Check whether --enable-thread-safe or --disable-thread-safe was given.
+if test "${enable_thread_safe+set}" = set; then
+ enableval="$enable_thread_safe"
+
+else
+ enable_thread_safe="yes"
+fi;
+THREAD_SAFE=""
+test "$enable_thread_safe" = "yes" && THREAD_SAFE="-thread-safe"
+test "$enable_thread_safe" = "$host_os" && THREAD_SAFE="-thread-safe"
+
+if test -n "$THREAD_SAFE" ; then
+ echo "$as_me:$LINENO: result: ...using thread-safe linkage" >&5
+echo "${ECHO_T}...using thread-safe linkage" >&6
+else
+ echo "$as_me:$LINENO: result: disabled thread-safe linkage" >&5
+echo "${ECHO_T}disabled thread-safe linkage" >&6
+fi
+# ----------------------------------------------------------------
+echo "$as_me:$LINENO: checking zlib install prefix" >&5
+echo $ECHO_N "checking zlib install prefix... $ECHO_C" >&6
+
+# Check whether --with-zlib or --without-zlib was given.
+if test "${with_zlib+set}" = set; then
+ withval="$with_zlib"
+
+else
+ with_zlib="no"
+fi;
+if test "${with_zlib}" = yes ; then # choose --prefix paths
+ if test "${prefix}" = NONE ; then
+ echo "$as_me:$LINENO: result: oops" >&5
+echo "${ECHO_T}oops" >&6
+ { { echo "$as_me:$LINENO: error: --with-zlib requires a path argument or a --prefix path set" >&5
+echo "$as_me: error: --with-zlib requires a path argument or a --prefix path set" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ with_zlib="$prefix"
+fi
+
+case ".$with_zlib" in
+ .no|.no,*)
+ echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
+ with_zlib="no, not configured" ;;
+ ./usr)
+ echo "$as_me:$LINENO: result: oops, ignored (may try --with-zlib=/usr/.)" >&5
+echo "${ECHO_T}oops, ignored (may try --with-zlib=/usr/.)" >&6
+ with_zlib="no, /usr ignored" ;;
+ *) if test ! -d "$with_zlib/include" ; then
+ echo "$as_me:$LINENO: result: oops" >&5
+echo "${ECHO_T}oops" >&6
+ { { echo "$as_me:$LINENO: error: \"$with_zlib/include\" is not a directory" >&5
+echo "$as_me: error: \"$with_zlib/include\" is not a directory" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ if test ! -d "$with_zlib/lib" ; then
+ echo "$as_me:$LINENO: result: oops" >&5
+echo "${ECHO_T}oops" >&6
+ { { echo "$as_me:$LINENO: error: \"$with_zlib/lib\" is not a directory" >&5
+echo "$as_me: error: \"$with_zlib/lib\" is not a directory" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ echo "$as_me:$LINENO: result: $with_zlib" >&5
+echo "${ECHO_T}$with_zlib" >&6
+ ZLIB_INCL="-I$with_zlib/include"
+ ZLIB_LDIR="-L$with_zlib/lib"
+ echo "$as_me:$LINENO: result: ..adding CPPFLAGS $ZLIB_INCL" >&5
+echo "${ECHO_T}..adding CPPFLAGS $ZLIB_INCL" >&6
+ echo "$as_me:$LINENO: result: ..adding LDFLAGS $ZLIB_LDIR" >&5
+echo "${ECHO_T}..adding LDFLAGS $ZLIB_LDIR" >&6
+ CPPFLAGS="$CPPFLAGS $ZLIB_INCL"
+ LDFLAGS="$LDFLAGS $ZLIB_LDIR"
+ ;;
+esac
+
+
+# -----------------------------------------------------------------------
+
+ echo "$as_me:$LINENO: checking rpm spec file" >&5
+echo $ECHO_N "checking rpm spec file... $ECHO_C" >&6
+ if test "." != "." ; then
+ ax_spec_file_=""
+ ax_spec_file=`basename `
+ else
+ case ".$ac_unique_file" in
+ *.spec) ax_spec_file="$ac_unique_file"
+ ax_spec_file_="$ac_unique_file" ;;
+ *) ax_spec_file="TODO"
+ if test ".$PACKAGE" != "."
+ then ax_spec_file_="$PACKAGE.spec"
+ else ax_spec_file_="README"
+ fi
+ cat >&5 <<EOF
+ no ax_spec_file argument has been given, using defaults of
+ (1) $ax_spec_file_
+ (2) $ax_spec_file
+EOF
+ ;;
+ esac
+ fi
+ # find specfile
+ for i in . $srcdir $srcdir/.. .. ; do
+ if test -f "$i/$ax_spec_file_" ; then
+ ax_spec_dir="$i"
+ ax_spec_file="$ax_spec_dir/$ax_spec_file_"
+ break
+ fi
+ if test -f "$i/$ax_spec_file" ; then
+ ax_spec_dir="$i"
+ ax_spec_file="$ax_spec_dir/$ax_spec_file"
+ break
+ fi
+ done
+ case "$ax_spec_file" in
+ ./*) if test "$ax_spec_file" = "./$ax_spec_file_" ; then
+ ax_spec_file="$ax_spec_file_"
+ fi
+ echo "$as_me:$LINENO: result: $ax_spec_file" >&5
+echo "${ECHO_T}$ax_spec_file" >&6 ;;
+ */*) echo "$as_me:$LINENO: result: $ax_spec_file" >&5
+echo "${ECHO_T}$ax_spec_file" >&6 ;;
+ *) { { echo "$as_me:$LINENO: error: no rpm spec file found" >&5
+echo "$as_me: error: no rpm spec file found" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+
+
+ echo "$as_me:$LINENO: checking for spec package" >&5
+echo $ECHO_N "checking for spec package... $ECHO_C" >&6
+ if test ".$PACKAGE_NAME" = "." ; then if test ! -f $ax_spec_file
+ then k="(w/o spec)"
+ else k=""
+
+ if test ".$PACKAGE_NAME" = "." ; then
+ PACKAGE_NAME=`grep -i '^[ ]*name[ ]*:' "$ax_spec_file" | sed -e 's/.*:[ ]*//' -e 's/[ ][ ]*/ /g' -e 's/^ //' -e 's/ $//' -e 'q'`
+ if test ".$PACKAGE_NAME" = "." ; then
+ for PACKAGE_NAME in name PACKAGE_NAME package_name ; do
+ PACKAGE_NAME=`echo "$PACKAGE_NAME" | sed -e 's/^%//g'`
+ PACKAGE_NAME=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_NAME[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_NAME[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file`
+ test ".PACKAGE_NAME" != "." && break
+ done
+ fi
+ case ".$PACKAGE_NAME" in
+ .%{*)
+ PACKAGE_NAME=`echo "$PACKAGE_NAME" | sed -e 's/%{//' -e 's/}$//'`
+ PACKAGE_NAME=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_NAME[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_NAME[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file` ;;
+ .%*)
+ PACKAGE_NAME=`echo "$PACKAGE_NAME" | sed -e 's/%//'`
+ PACKAGE_NAME=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_NAME[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_NAME[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file` ;;
+ esac
+
+ fi # test ".$[]PACKAGE_NAME" = "."
+
+ PACKAGE_NAME=`echo $PACKAGE_NAME | sed -e 's/ /-/g'`
+ fi fi
+ test ".$PACKAGE_NAME" = "." && k="(fallback)"
+ test ".$PACKAGE_NAME" = "." && PACKAGE_NAME=`basename $ax_spec_file .spec`
+ test ".$PACKAGE_NAME" = ".README" && PACKAGE_NAME="TODO"
+ test ".$PACKAGE_NAME" = ".TODO" && PACKAGE_NAME="foo"
+
+ test "PACKAGE_NAME" = "PACKAGE_NAME" && test ".$PACKAGE" = "." && PACKAGE="$PACKAGE_NAME"
+ echo "$as_me:$LINENO: result: $PACKAGE_NAME $k" >&5
+echo "${ECHO_T}$PACKAGE_NAME $k" >&6
+
+ echo "$as_me:$LINENO: checking for spec version" >&5
+echo $ECHO_N "checking for spec version... $ECHO_C" >&6
+ if test ".$PACKAGE_VERSION" = "." ; then if test ! -f $ax_spec_file
+ then k="(w/o spec)"
+ else k=""
+
+ if test ".$PACKAGE_VERSION" = "." ; then
+ PACKAGE_VERSION=`grep -i '^[ ]*version[ ]*:' "$ax_spec_file" | sed -e 's/.*:[ ]*//' -e 's/[ ][ ]*/ /g' -e 's/^ //' -e 's/ $//' -e 'q'`
+ if test ".$PACKAGE_VERSION" = "." ; then
+ for PACKAGE_VERSION in version PACKAGE_VERSION package_version ; do
+ PACKAGE_VERSION=`echo "$PACKAGE_VERSION" | sed -e 's/^%//g'`
+ PACKAGE_VERSION=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_VERSION[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_VERSION[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file`
+ test ".PACKAGE_VERSION" != "." && break
+ done
+ fi
+ case ".$PACKAGE_VERSION" in
+ .%{*)
+ PACKAGE_VERSION=`echo "$PACKAGE_VERSION" | sed -e 's/%{//' -e 's/}$//'`
+ PACKAGE_VERSION=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_VERSION[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_VERSION[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file` ;;
+ .%*)
+ PACKAGE_VERSION=`echo "$PACKAGE_VERSION" | sed -e 's/%//'`
+ PACKAGE_VERSION=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_VERSION[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_VERSION[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file` ;;
+ esac
+
+ fi # test ".$[]PACKAGE_VERSION" = "."
+
+ PACKAGE_VERSION=`echo $PACKAGE_VERSION | sed -e 's/ /-/g'`
+ fi fi
+ test ".$PACKAGE_VERSION" = "." && k="(fallback)"
+ test ".$PACKAGE_VERSION" = "." && PACKAGE_VERSION=`date +0.%y.%W%w`
+
+ test "PACKAGE_VERSION" = "PACKAGE_VERSION" && test ".$VERSION" = "." && VERSION="$PACKAGE_VERSION"
+ case "$PACKAGE_VERSION" in # note we set traditional VERSION before cleaning things up
+ *.*.) PACKAGE_VERSION="$PACKAGE_VERSION"`date +%W%w` ;;
+ *.*.*) ;;
+ *.) PACKAGE_VERSION="$PACKAGE_VERSION"`date +%y.%W%w` ;;
+ *.*) PACKAGE_VERSION="$PACKAGE_VERSION.0" ;;
+ *) PACKAGE_VERSION=`echo "$PACKAGE_VERSION" | $as_tr_sh` ; PACKAGE_VERSION="$PACKAGE_VERSION.`date +%y.%W%w`" ;;
+ esac
+ PACKAGE_VERSION=`echo $PACKAGE_VERSION | sed -e "s/[.]0\\(0-9\\)/.\\1/g"`
+ echo "$as_me:$LINENO: result: $PACKAGE_VERSION $k" >&5
+echo "${ECHO_T}$PACKAGE_VERSION $k" >&6
+
+ echo "$as_me:$LINENO: checking for spec license type" >&5
+echo $ECHO_N "checking for spec license type... $ECHO_C" >&6
+ if test ".$PACKAGE_LICENSE" = "." ; then if test ! -f $ax_spec_file
+ then k="(w/o spec)"
+ else k=""
+
+ if test ".$PACKAGE_LICENSE" = "." ; then
+ PACKAGE_LICENSE=`grep -i '^[ ]*license[ ]*:' "$ax_spec_file" | sed -e 's/.*:[ ]*//' -e 's/[ ][ ]*/ /g' -e 's/^ //' -e 's/ $//' -e 'q'`
+ if test ".$PACKAGE_LICENSE" = "." ; then
+ for PACKAGE_LICENSE in license PACKAGE_LICENSE package_license ; do
+ PACKAGE_LICENSE=`echo "$PACKAGE_LICENSE" | sed -e 's/^%//g'`
+ PACKAGE_LICENSE=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_LICENSE[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_LICENSE[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file`
+ test ".PACKAGE_LICENSE" != "." && break
+ done
+ fi
+ case ".$PACKAGE_LICENSE" in
+ .%{*)
+ PACKAGE_LICENSE=`echo "$PACKAGE_LICENSE" | sed -e 's/%{//' -e 's/}$//'`
+ PACKAGE_LICENSE=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_LICENSE[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_LICENSE[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file` ;;
+ .%*)
+ PACKAGE_LICENSE=`echo "$PACKAGE_LICENSE" | sed -e 's/%//'`
+ PACKAGE_LICENSE=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_LICENSE[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_LICENSE[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file` ;;
+ esac
+
+ fi # test ".$[]PACKAGE_LICENSE" = "."
+
+ PACKAGE_LICENSE=`echo $PACKAGE_LICENSE | sed -e 's/ *License//g'`
+ fi fi
+ test ".$PACKAGE_LICENSE" = "." && k="(fallback)"
+ if test ".$PACKAGE_LICENSE" = "." ; then
+ for ac_file in "$srcdir/COPYING" "$srcdir/COPYING" "$srcdir/LICENSE" ; do
+ test -f "$ac_file" || continue
+ if grep "GNU LESSER GENERAL PUBLIC LICENSE" "$ac_file" >/dev/null
+ then PACKAGE_LICENSE="GNU LGPL" ; break
+ elif grep "GNU GENERAL PUBLIC LICENSE" "$ac_file" >/dev/null
+ then PACKAGE_LICENSE="GNU GPL" ; break
+ elif grep "MOZILLA PUBLIC LICENSE" "$ac_file" >/dev/null
+ then PACKAGE_LICENSE="MPL" ; break
+ elif grep "Mozilla Public License" "$ac_file" >/dev/null
+ then PACKAGE_LICENSE="MPL" ; break
+ elif grep -i "artistic license" "$ac_file" >/dev/null
+ then PACKAGE_LICENSE="Artistic" ; break
+ elif grep -i "artistic control" "$ac_file" >/dev/null
+ then PACKAGE_LICENSE="Artistic" ; break
+ elif grep -i "semblance of artistic" "$ac_file" >/dev/null
+ then PACKAGE_LICENSE="Artistic" ; break
+ elif grep -i "above copyright notice" "$ac_file" >/dev/null
+ then PACKAGE_LICENSE="BSD" ; break
+ fi
+ done
+ if test ".$PACKAGE_LICENSE" = "." ; then
+ if test "$srcdir/COPYING.LIB" ; then PACKAGE_LICENSE="GNU LGPL"
+ elif test ".$ltmain" != "." ; then PACKAGE_LICENSE="GNU LGPL"
+ else PACKAGE_LICENSE="GNU GPL"
+ fi
+ fi
+ fi
+
+ test "$PACKAGE_LICENSE" = "GPL" && PACKAGE_LICENSE="GNU GPL"
+ test "$PACKAGE_LICENSE" = "LGPL" && PACKAGE_LICENSE="GNU LGPL"
+ echo "$as_me:$LINENO: result: $PACKAGE_LICENSE $k" >&5
+echo "${ECHO_T}$PACKAGE_LICENSE $k" >&6
+
+ echo "$as_me:$LINENO: checking for spec summary" >&5
+echo $ECHO_N "checking for spec summary... $ECHO_C" >&6
+ if test ".$PACKAGE_SUMMARY" = "." ; then if test ! -f $ax_spec_file
+ then k="(w/o spec)"
+ else k=""
+
+ if test ".$PACKAGE_SUMMARY" = "." ; then
+ PACKAGE_SUMMARY=`grep -i '^[ ]*summary[ ]*:' "$ax_spec_file" | sed -e 's/.*:[ ]*//' -e 's/[ ][ ]*/ /g' -e 's/^ //' -e 's/ $//' -e 'q'`
+ if test ".$PACKAGE_SUMMARY" = "." ; then
+ for PACKAGE_SUMMARY in summary PACKAGE_SUMMARY package_summary ; do
+ PACKAGE_SUMMARY=`echo "$PACKAGE_SUMMARY" | sed -e 's/^%//g'`
+ PACKAGE_SUMMARY=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_SUMMARY[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_SUMMARY[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file`
+ test ".PACKAGE_SUMMARY" != "." && break
+ done
+ fi
+ case ".$PACKAGE_SUMMARY" in
+ .%{*)
+ PACKAGE_SUMMARY=`echo "$PACKAGE_SUMMARY" | sed -e 's/%{//' -e 's/}$//'`
+ PACKAGE_SUMMARY=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_SUMMARY[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_SUMMARY[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file` ;;
+ .%*)
+ PACKAGE_SUMMARY=`echo "$PACKAGE_SUMMARY" | sed -e 's/%//'`
+ PACKAGE_SUMMARY=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_SUMMARY[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_SUMMARY[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file` ;;
+ esac
+
+ fi # test ".$[]PACKAGE_SUMMARY" = "."
+
+ fi fi
+ test ".$PACKAGE_SUMMARY" = "." && k="(fallback)"
+ if test ".$PACKAGE_SUMMARY" = "." ; then PACKAGE_SUMMARY="$PACKAGE"
+ test ".$PACKAGE_SUMMARY" = "." && PACKAGE_SUMMARY="foo"
+ test ".$ltmain" != "." && PACKAGE_SUMMARY="$PACKAGE_SUMMARY library"
+ fi
+
+ echo "$as_me:$LINENO: result: $PACKAGE_SUMMARY $k" >&5
+echo "${ECHO_T}$PACKAGE_SUMMARY $k" >&6
+
+ echo "$as_me:$LINENO: checking for spec category" >&5
+echo $ECHO_N "checking for spec category... $ECHO_C" >&6
+ if test ".$PACKAGE_CATEGORY" = "." ; then if test ! -f $ax_spec_file
+ then k="(w/o spec)"
+ else k=""
+
+ if test ".$PACKAGE_CATEGORY" = "." ; then
+ PACKAGE_CATEGORY=`grep -i '^[ ]*group[ ]*:' "$ax_spec_file" | sed -e 's/.*:[ ]*//' -e 's/[ ][ ]*/ /g' -e 's/^ //' -e 's/ $//' -e 'q'`
+ if test ".$PACKAGE_CATEGORY" = "." ; then
+ for PACKAGE_CATEGORY in group PACKAGE_CATEGORY package_category ; do
+ PACKAGE_CATEGORY=`echo "$PACKAGE_CATEGORY" | sed -e 's/^%//g'`
+ PACKAGE_CATEGORY=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_CATEGORY[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_CATEGORY[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file`
+ test ".PACKAGE_CATEGORY" != "." && break
+ done
+ fi
+ case ".$PACKAGE_CATEGORY" in
+ .%{*)
+ PACKAGE_CATEGORY=`echo "$PACKAGE_CATEGORY" | sed -e 's/%{//' -e 's/}$//'`
+ PACKAGE_CATEGORY=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_CATEGORY[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_CATEGORY[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file` ;;
+ .%*)
+ PACKAGE_CATEGORY=`echo "$PACKAGE_CATEGORY" | sed -e 's/%//'`
+ PACKAGE_CATEGORY=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_CATEGORY[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_CATEGORY[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file` ;;
+ esac
+
+ fi # test ".$[]PACKAGE_CATEGORY" = "."
+
+ PACKAGE_CATEGORY=`echo $PACKAGE_CATEGORY | sed -e 's/ /-/g'`
+ fi fi
+ test ".$PACKAGE_CATEGORY" = "." && k="(fallback)"
+ if test ".$PACKAGE_CATEGORY" = "." ; then if test ".$ltmain" != "."
+ then PACKAGE_CATEGORY="Development/Library"
+ else PACKAGE_CATEGORY="Development/Other"
+ fi fi
+
+ echo "$as_me:$LINENO: result: $PACKAGE_CATEGORY $k" >&5
+echo "${ECHO_T}$PACKAGE_CATEGORY $k" >&6
+
+ echo "$as_me:$LINENO: checking for spec icon" >&5
+echo $ECHO_N "checking for spec icon... $ECHO_C" >&6
+ if test ".$PACKAGE_ICON" = "." ; then if test ! -f $ax_spec_file
+ then k="(w/o spec)"
+ else k=""
+
+ if test ".$PACKAGE_ICON" = "." ; then
+ PACKAGE_ICON=`grep -i '^[ ]*icon[ ]*:' "$ax_spec_file" | sed -e 's/.*:[ ]*//' -e 's/[ ][ ]*/ /g' -e 's/^ //' -e 's/ $//' -e 'q'`
+ if test ".$PACKAGE_ICON" = "." ; then
+ for PACKAGE_ICON in icon PACKAGE_ICON package_icon ; do
+ PACKAGE_ICON=`echo "$PACKAGE_ICON" | sed -e 's/^%//g'`
+ PACKAGE_ICON=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_ICON[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_ICON[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file`
+ test ".PACKAGE_ICON" != "." && break
+ done
+ fi
+ case ".$PACKAGE_ICON" in
+ .%{*)
+ PACKAGE_ICON=`echo "$PACKAGE_ICON" | sed -e 's/%{//' -e 's/}$//'`
+ PACKAGE_ICON=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_ICON[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_ICON[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file` ;;
+ .%*)
+ PACKAGE_ICON=`echo "$PACKAGE_ICON" | sed -e 's/%//'`
+ PACKAGE_ICON=`sed -e "/^%[ ]*define[ ][ ]*$PACKAGE_ICON[ ]/!d" -e "s/^%[ ]*define[ ][ ]*$PACKAGE_ICON[ ]*//" -e 's/[ ][ ]*/ /' -e 's/ $//' -e 'q' $ax_spec_file` ;;
+ esac
+
+ fi # test ".$[]PACKAGE_ICON" = "."
+
+ fi fi
+ test ".$PACKAGE_ICON" = "." && k="(fallback)"
+ if test ".$PACKAGE_ICON" = "." ; then PACKAGE_ICON="$PACKAGE-icon.png" ; fi
+
+ echo "$as_me:$LINENO: result: $PACKAGE_ICON $k" >&5
+echo "${ECHO_T}$PACKAGE_ICON $k" >&6
+
+
+am__api_version="1.9"
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL=$ac_install_sh
+ fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,$program_prefix,;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$,$program_suffix,;$program_transform_name"
+# Double any \ or $. echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm conftest.sed
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+ # We used to keeping the `.' as first argument, in order to
+ # allow $(mkdir_p) to be used without argument. As in
+ # $(mkdir_p) $(somedir)
+ # where $(somedir) is conditionally defined. However this is wrong
+ # for two reasons:
+ # 1. if the package is installed by a user who cannot write `.'
+ # make install will fail,
+ # 2. the above comment should most certainly read
+ # $(mkdir_p) $(DESTDIR)$(somedir)
+ # so it does not work when $(somedir) is undefined and
+ # $(DESTDIR) is not.
+ # To support the latter case, we have to write
+ # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
+ # so the `.' trick is pointless.
+ mkdir_p='mkdir -p --'
+else
+ # On NextStep and OpenStep, the `mkdir' command does not
+ # recognize any option. It will interpret all options as
+ # directories to create, and then abort because `.' already
+ # exists.
+ for d in ./-p ./--version;
+ do
+ test -d $d && rmdir $d
+ done
+ # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
+ if test -f "$ac_aux_dir/mkinstalldirs"; then
+ mkdir_p='$(mkinstalldirs)'
+ else
+ mkdir_p='$(install_sh) -d'
+ fi
+fi
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AWK+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AWK="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$AWK" && break
+done
+
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.make <<\_ACEOF
+all:
+ @echo 'ac_maketemp="$(MAKE)"'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftest.make
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ SET_MAKE=
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+# test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" &&
+ test -f $srcdir/config.status; then
+ { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE=$PACKAGE
+ VERSION=$VERSION
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":"
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ STRIP=$ac_ct_STRIP
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_CC" && break
+done
+
+ CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+ "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+ (eval $ac_link_default) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Find the output, starting from the most likely. This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+ ;;
+ conftest.$ac_ext )
+ # This is the source file.
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ # FIXME: I believe we export ac_cv_exeext for Libtool,
+ # but it would be cool to find out if it's true. Does anybody
+ # maintain Libtool? --akim.
+ export ac_cv_exeext
+ break;;
+ * )
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ export ac_cv_exeext
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std1 is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std1. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX 10.20 and later -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+ x|xno)
+ echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+ *)
+ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+ CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C. Since we use `exit',
+# in C++ we need to declare it. In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+ choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ for ac_declaration in \
+ '' \
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);'
+do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+DEPDIR="${am__leading_dot}deps"
+
+ ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
+echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+ am__include=include
+ am__quote=
+ _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ fi
+fi
+
+
+echo "$as_me:$LINENO: result: $_am_result" >&5
+echo "${ECHO_T}$_am_result" >&6
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+ enableval="$enable_dependency_tracking"
+
+fi;
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+
+
+if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+
+
+depcc="$CC" am_compiler_list=
+
+echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+
+
+if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL=$ac_install_sh
+ fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+ p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_shared=yes
+fi;
+
+# Check whether --enable-static or --disable-static was given.
+if test "${enable_static+set}" = set; then
+ enableval="$enable_static"
+ p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_static=yes
+fi;
+
+# Check whether --enable-fast-install or --disable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+ enableval="$enable_fast_install"
+ p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_fast_install=yes
+fi;
+
+echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5
+echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6
+if test "${lt_cv_path_SED+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f $lt_ac_sed && continue
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test $lt_ac_count -gt 10 && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test $lt_ac_count -gt $lt_ac_max; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+
+fi
+
+SED=$lt_cv_path_SED
+echo "$as_me:$LINENO: result: $SED" >&5
+echo "${ECHO_T}$SED" >&6
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval="$with_gnu_ld"
+ test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi;
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
+else
+ echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+ { (exit 1); exit 1; }; }
+echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5
+echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6
+if test "${lt_cv_ld_reload_flag+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_ld_reload_flag='-r'
+fi
+echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5
+echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
+echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6
+if test "${lt_cv_path_NM+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ lt_nm_to_check="${ac_tool_prefix}nm"
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm="$ac_dir/$lt_tmp_nm"
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+ done
+ test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi
+fi
+echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5
+echo "${ECHO_T}$lt_cv_path_NM" >&6
+NM="$lt_cv_path_NM"
+
+echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+ echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6
+fi
+
+echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5
+echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6
+if test "${lt_cv_deplibs_check_method+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[45]*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump'.
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | kfreebsd*-gnu | dragonfly*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix3*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+nto-qnx*)
+ lt_cv_deplibs_check_method=unknown
+ ;;
+
+openbsd*)
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5
+echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+ enableval="$enable_libtool_lock"
+
+fi;
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE="32"
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE="64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '#line 4384 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ ppc*-*linux*|powerpc*-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
+echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6
+if test "${lt_cv_cc_needs_belf+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ lt_cv_cc_needs_belf=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+lt_cv_cc_needs_belf=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
+echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+sparc*-*solaris*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*) LD="${LD-ld} -m elf64_sparc" ;;
+ *) LD="${LD-ld} -64" ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_DLLTOOL+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$DLLTOOL"; then
+ ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+DLLTOOL=$ac_cv_prog_DLLTOOL
+if test -n "$DLLTOOL"; then
+ echo "$as_me:$LINENO: result: $DLLTOOL" >&5
+echo "${ECHO_T}$DLLTOOL" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_DLLTOOL"; then
+ ac_ct_DLLTOOL=$DLLTOOL
+ # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_DLLTOOL+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_DLLTOOL"; then
+ ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_DLLTOOL="dlltool"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_DLLTOOL" && ac_cv_prog_ac_ct_DLLTOOL="false"
+fi
+fi
+ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+if test -n "$ac_ct_DLLTOOL"; then
+ echo "$as_me:$LINENO: result: $ac_ct_DLLTOOL" >&5
+echo "${ECHO_T}$ac_ct_DLLTOOL" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ DLLTOOL=$ac_ct_DLLTOOL
+else
+ DLLTOOL="$ac_cv_prog_DLLTOOL"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
+set dummy ${ac_tool_prefix}as; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AS+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AS"; then
+ ac_cv_prog_AS="$AS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AS="${ac_tool_prefix}as"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+AS=$ac_cv_prog_AS
+if test -n "$AS"; then
+ echo "$as_me:$LINENO: result: $AS" >&5
+echo "${ECHO_T}$AS" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_AS"; then
+ ac_ct_AS=$AS
+ # Extract the first word of "as", so it can be a program name with args.
+set dummy as; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_AS+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_AS"; then
+ ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AS="as"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_AS" && ac_cv_prog_ac_ct_AS="false"
+fi
+fi
+ac_ct_AS=$ac_cv_prog_ac_ct_AS
+if test -n "$ac_ct_AS"; then
+ echo "$as_me:$LINENO: result: $ac_ct_AS" >&5
+echo "${ECHO_T}$ac_ct_AS" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ AS=$ac_ct_AS
+else
+ AS="$ac_cv_prog_AS"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_OBJDUMP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$OBJDUMP"; then
+ ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+ echo "$as_me:$LINENO: result: $OBJDUMP" >&5
+echo "${ECHO_T}$OBJDUMP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+ ac_ct_OBJDUMP=$OBJDUMP
+ # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_OBJDUMP"; then
+ ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OBJDUMP="objdump"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_OBJDUMP" && ac_cv_prog_ac_ct_OBJDUMP="false"
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+ echo "$as_me:$LINENO: result: $ac_ct_OBJDUMP" >&5
+echo "${ECHO_T}$ac_ct_OBJDUMP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ OBJDUMP=$ac_ct_OBJDUMP
+else
+ OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+ ;;
+
+esac
+
+need_locks="$enable_libtool_lock"
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ exit(2);
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in dlfcn.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_CXX" && break
+done
+test -n "$ac_ct_CXX" || ac_ct_CXX="g++"
+
+ CXX=$ac_ct_CXX
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+ "checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cxx_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+for ac_declaration in \
+ '' \
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);'
+do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+depcc="$CXX" am_compiler_list=
+
+echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6
+if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CXX_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CXX_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+
+
+if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+ am__fastdepCXX_TRUE=
+ am__fastdepCXX_FALSE='#'
+else
+ am__fastdepCXX_TRUE='#'
+ am__fastdepCXX_FALSE=
+fi
+
+
+
+
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
+echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6
+if test -z "$CXXCPP"; then
+ if test "${ac_cv_prog_CXXCPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CXXCPP needs to be expanded
+ for CXXCPP in "$CXX -E" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+ CXXCPP=$ac_cv_prog_CXXCPP
+else
+ ac_cv_prog_CXXCPP=$CXXCPP
+fi
+echo "$as_me:$LINENO: result: $CXXCPP" >&5
+echo "${ECHO_T}$CXXCPP" >&6
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+fi
+
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$F77"; then
+ ac_cv_prog_F77="$F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_F77="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+F77=$ac_cv_prog_F77
+if test -n "$F77"; then
+ echo "$as_me:$LINENO: result: $F77" >&5
+echo "${ECHO_T}$F77" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$F77" && break
+ done
+fi
+if test -z "$F77"; then
+ ac_ct_F77=$F77
+ for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_F77"; then
+ ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_F77="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_F77=$ac_cv_prog_ac_ct_F77
+if test -n "$ac_ct_F77"; then
+ echo "$as_me:$LINENO: result: $ac_ct_F77" >&5
+echo "${ECHO_T}$ac_ct_F77" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_F77" && break
+done
+
+ F77=$ac_ct_F77
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:6225:" \
+ "checking for Fortran 77 compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+rm -f a.out
+
+# If we don't use `.F' as extension, the preprocessor is not run on the
+# input file. (Note that this only needs to work for GNU compilers.)
+ac_save_ext=$ac_ext
+ac_ext=F
+echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6
+if test "${ac_cv_f77_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+#ifndef __GNUC__
+ choke me
+#endif
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_f77_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6
+ac_ext=$ac_save_ext
+ac_test_FFLAGS=${FFLAGS+set}
+ac_save_FFLAGS=$FFLAGS
+FFLAGS=
+echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5
+echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_f77_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ FFLAGS=-g
+cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_f77_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_f77_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5
+echo "${ECHO_T}$ac_cv_prog_f77_g" >&6
+if test "$ac_test_FFLAGS" = set; then
+ FFLAGS=$ac_save_FFLAGS
+elif test $ac_cv_prog_f77_g = yes; then
+ if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+ FFLAGS="-g -O2"
+ else
+ FFLAGS="-g"
+ fi
+else
+ if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+ FFLAGS="-O2"
+ else
+ FFLAGS=
+ fi
+fi
+
+G77=`test $ac_compiler_gnu = yes && echo yes`
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+
+# find the maximum length of command line arguments
+echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5
+echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6
+if test "${lt_cv_sys_max_cmd_len+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ i=0
+ teststring="ABCD"
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \
+ = "XX$teststring") >/dev/null 2>&1 &&
+ new_result=`expr "X$teststring" : ".*" 2>&1` &&
+ lt_cv_sys_max_cmd_len=$new_result &&
+ test $i != 17 # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on massive
+ # amounts of additional arguments before passing them to the linker.
+ # It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ ;;
+ esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+ echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5
+echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6
+else
+ echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
+fi
+
+
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5
+echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6
+if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[BCDT]'
+ ;;
+cygwin* | mingw* | pw32*)
+ symcode='[ABCDGISTW]'
+ ;;
+hpux*) # Its linker distinguishes data from code symbols
+ if test "$host_cpu" = ia64; then
+ symcode='[ABCDEGRST]'
+ fi
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ ;;
+linux*)
+ if test "$host_cpu" = ia64; then
+ symcode='[ABCDGIRSTW]'
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[BCDEGRST]'
+ ;;
+osf*)
+ symcode='[BCDEGQRST]'
+ ;;
+solaris*)
+ symcode='[BDRT]'
+ ;;
+sco3.2v5*)
+ symcode='[DT]'
+ ;;
+sysv4.2uw2*)
+ symcode='[DT]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[ABDT]'
+ ;;
+sysv4)
+ symcode='[DFNSTU]'
+ ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5
+ (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if grep ' nm_test_var$' "$nlist" >/dev/null; then
+ if grep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+ cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+ cat <<\EOF >> conftest.$ac_ext
+ {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_save_LIBS="$LIBS"
+ lt_save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext}; then
+ pipe_works=yes
+ fi
+ LIBS="$lt_save_LIBS"
+ CFLAGS="$lt_save_CFLAGS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&5
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&5
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+ fi
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ fi
+ rm -f conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ echo "$as_me:$LINENO: result: failed" >&5
+echo "${ECHO_T}failed" >&6
+else
+ echo "$as_me:$LINENO: result: ok" >&5
+echo "${ECHO_T}ok" >&6
+fi
+
+echo "$as_me:$LINENO: checking for objdir" >&5
+echo $ECHO_N "checking for objdir... $ECHO_C" >&6
+if test "${lt_cv_objdir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5
+echo "${ECHO_T}$lt_cv_objdir" >&6
+objdir=$lt_cv_objdir
+
+
+
+
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_AR" && ac_cv_prog_ac_ct_AR="false"
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
+echo "${ECHO_T}$ac_ct_AR" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ AR=$ac_ct_AR
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ RANLIB=$ac_ct_RANLIB
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":"
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ STRIP=$ac_ct_STRIP
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5
+echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/${ac_tool_prefix}file; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ echo "$as_me:$LINENO: checking for file" >&5
+echo $ECHO_N "checking for file... $ECHO_C" >&6
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/file; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ else
+ MAGIC_CMD=:
+ fi
+fi
+
+ fi
+ ;;
+esac
+
+enable_dlopen=no
+enable_win32_dll=yes
+
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+ enableval="$enable_libtool_lock"
+
+fi;
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+
+# Check whether --with-pic or --without-pic was given.
+if test "${with_pic+set}" = set; then
+ withval="$with_pic"
+ pic_mode="$withval"
+else
+ pic_mode=default
+fi;
+test -z "$pic_mode" && pic_mode=default
+
+# Use C for the default configuration in the libtool script
+tagname=
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}\n'
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+ lt_prog_compiler_no_builtin_flag=' -fno-builtin'
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_rtti_exceptions=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="-fno-rtti -fno-exceptions"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:7288: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:7292: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_rtti_exceptions=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+ lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+ :
+fi
+
+fi
+
+lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_static='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic='-fno-common'
+ ;;
+
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ else
+ lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic='-qnocommon'
+ lt_prog_compiler_wl='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ linux*)
+ case $cc_basename in
+ icc* | ecc*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fpic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ lt_prog_compiler_wl='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl='-Qoption ld '
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic='-Kconform_pic'
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_can_build_shared=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic='-pic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic" >&6
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6
+if test "${lt_prog_compiler_pic_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:7556: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:7560: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6
+
+if test x"$lt_prog_compiler_pic_works" = xyes; then
+ case $lt_prog_compiler_pic in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+ esac
+else
+ lt_prog_compiler_pic=
+ lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic=
+ ;;
+ *)
+ lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
+if test "${lt_prog_compiler_static_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works=yes
+ fi
+ else
+ lt_prog_compiler_static_works=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works" >&6
+
+if test x"$lt_prog_compiler_static_works" = xyes; then
+ :
+else
+ lt_prog_compiler_static=
+fi
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:7660: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:7664: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
+
+ runpath_var=
+ allow_undefined_flag=
+ enable_shared_with_static_runtimes=no
+ archive_cmds=
+ archive_expsym_cmds=
+ old_archive_From_new_cmds=
+ old_archive_from_expsyms_cmds=
+ export_dynamic_flag_spec=
+ whole_archive_flag_spec=
+ thread_safe_flag_spec=
+ hardcode_libdir_flag_spec=
+ hardcode_libdir_flag_spec_ld=
+ hardcode_libdir_separator=
+ hardcode_direct=no
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=unsupported
+ link_all_deplibs=unknown
+ hardcode_automatic=no
+ module_cmds=
+ module_expsym_cmds=
+ always_export_symbols=no
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ ld_shlibs=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ allow_undefined_flag=unsupported
+ always_export_symbols=no
+ enable_shared_with_static_runtimes=yes
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ interix3*)
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ archive_cmds='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs" = no; then
+ runpath_var=
+ hardcode_libdir_flag_spec=
+ export_dynamic_flag_spec=
+ whole_archive_flag_spec=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds=''
+ hardcode_direct=yes
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct=yes
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag="-z nodefs"
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag=' ${wl}-bernotok'
+ allow_undefined_flag=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec='$convenience'
+ archive_cmds_need_lc=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs=no
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_From_new_cmds='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc=no
+ hardcode_direct=no
+ hardcode_automatic=yes
+ hardcode_shlibpath_var=unsupported
+ whole_archive_flag_spec=''
+ link_all_deplibs=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ export_dynamic_flag_spec='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+
+ hardcode_direct=yes
+ export_dynamic_flag_spec='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld='+b $libdir'
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ ;;
+ *)
+ hardcode_direct=yes
+ export_dynamic_flag_spec='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_ld='-rpath $libdir'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ link_all_deplibs=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ newsos6)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_shlibpath_var=no
+ ;;
+
+ openbsd*)
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ *)
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ hardcode_libdir_separator=:
+ ;;
+
+ solaris*)
+ no_undefined_flag=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl, iff we do not link with $LD.
+ # Luckily, gcc supports the same syntax we need for Sun Studio.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ case $wlarc in
+ '')
+ whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+ *)
+ whole_archive_flag_spec='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
+ esac ;;
+ esac
+ link_all_deplibs=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds='$CC -r -o $output$reload_objs'
+ hardcode_direct=no
+ ;;
+ motorola)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ export_dynamic_flag_spec='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
+ no_undefined_flag='${wl}-z,text'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag='${wl}-z,text'
+ allow_undefined_flag='${wl}-z,nodefs'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+ export_dynamic_flag_spec='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $ld_shlibs" >&5
+echo "${ECHO_T}$ld_shlibs" >&6
+test "$ld_shlibs" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl
+ pic_flag=$lt_prog_compiler_pic
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag
+ allow_undefined_flag=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc=no
+ else
+ archive_cmds_need_lc=yes
+ fi
+ allow_undefined_flag=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5
+echo "${ECHO_T}$archive_cmds_need_lc" >&6
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+ test -n "$runpath_var" || \
+ test "X$hardcode_automatic" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no &&
+ test "$hardcode_minus_L" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action=unsupported
+fi
+echo "$as_me:$LINENO: result: $hardcode_action" >&5
+echo "${ECHO_T}$hardcode_action" >&6
+
+if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+striplib=
+old_striplib=
+echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
+echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+ ;;
+ *)
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ ;;
+ esac
+fi
+
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+int
+main ()
+{
+dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dl_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
+if test $ac_cv_lib_dl_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+
+fi
+
+ ;;
+
+ *)
+ echo "$as_me:$LINENO: checking for shl_load" >&5
+echo $ECHO_N "checking for shl_load... $ECHO_C" >&6
+if test "${ac_cv_func_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define shl_load innocuous_shl_load
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shl_load (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef shl_load
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char shl_load ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_shl_load) || defined (__stub___shl_load)
+choke me
+#else
+char (*f) () = shl_load;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != shl_load;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_shl_load=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
+echo "${ECHO_T}$ac_cv_func_shl_load" >&6
+if test $ac_cv_func_shl_load = yes; then
+ lt_cv_dlopen="shl_load"
+else
+ echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char shl_load ();
+int
+main ()
+{
+shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dld_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dld_shl_load=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6
+if test $ac_cv_lib_dld_shl_load = yes; then
+ lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"
+else
+ echo "$as_me:$LINENO: checking for dlopen" >&5
+echo $ECHO_N "checking for dlopen... $ECHO_C" >&6
+if test "${ac_cv_func_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define dlopen innocuous_dlopen
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char dlopen (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef dlopen
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_dlopen) || defined (__stub___dlopen)
+choke me
+#else
+char (*f) () = dlopen;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != dlopen;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
+echo "${ECHO_T}$ac_cv_func_dlopen" >&6
+if test $ac_cv_func_dlopen = yes; then
+ lt_cv_dlopen="dlopen"
+else
+ echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+int
+main ()
+{
+dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dl_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
+if test $ac_cv_lib_dl_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+ echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
+echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+int
+main ()
+{
+dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_svld_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_svld_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6
+if test $ac_cv_lib_svld_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+ echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
+echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dld_link ();
+int
+main ()
+{
+dld_link ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dld_dld_link=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dld_dld_link=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6
+if test $ac_cv_lib_dld_dld_link = yes; then
+ lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
+echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6
+if test "${lt_cv_dlopen_self+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+#line 10005 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ exit (status);
+}
+EOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self" >&6
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
+echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self_static=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+#line 10105 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ exit (status);
+}
+EOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self_static=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+
+
+# Report which library types will actually be built
+echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6
+
+echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6
+
+echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler \
+ CC \
+ LD \
+ lt_prog_compiler_wl \
+ lt_prog_compiler_pic \
+ lt_prog_compiler_static \
+ lt_prog_compiler_no_builtin_flag \
+ export_dynamic_flag_spec \
+ thread_safe_flag_spec \
+ whole_archive_flag_spec \
+ enable_shared_with_static_runtimes \
+ old_archive_cmds \
+ old_archive_from_new_cmds \
+ predep_objects \
+ postdep_objects \
+ predeps \
+ postdeps \
+ compiler_lib_search_path \
+ archive_cmds \
+ archive_expsym_cmds \
+ postinstall_cmds \
+ postuninstall_cmds \
+ old_archive_from_expsyms_cmds \
+ allow_undefined_flag \
+ no_undefined_flag \
+ export_symbols_cmds \
+ hardcode_libdir_flag_spec \
+ hardcode_libdir_flag_spec_ld \
+ hardcode_libdir_separator \
+ hardcode_automatic \
+ module_cmds \
+ module_expsym_cmds \
+ lt_cv_prog_compiler_c_o \
+ exclude_expsyms \
+ include_expsyms; do
+
+ case $var in
+ old_archive_cmds | \
+ old_archive_from_new_cmds | \
+ archive_cmds | \
+ archive_expsym_cmds | \
+ module_cmds | \
+ module_expsym_cmds | \
+ old_archive_from_expsyms_cmds | \
+ export_symbols_cmds | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="${ofile}T"
+ trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+ $rm -f "$cfgfile"
+ { echo "$as_me:$LINENO: creating $ofile" >&5
+echo "$as_me: creating $ofile" >&6;}
+
+ cat <<__EOF__ >> "$cfgfile"
+#! $SHELL
+
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e 1s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# ### END LIBTOOL CONFIG
+
+__EOF__
+
+
+ case $host_os in
+ aix3*)
+ cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+EOF
+ ;;
+ esac
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" || \
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+# Check whether --with-tags or --without-tags was given.
+if test "${with_tags+set}" = set; then
+ withval="$with_tags"
+ tagnames="$withval"
+fi;
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+ if test ! -f "${ofile}"; then
+ { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5
+echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;}
+ fi
+
+ if test -z "$LTCC"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+ if test -z "$LTCC"; then
+ { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5
+echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;}
+ else
+ { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5
+echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;}
+ fi
+ fi
+ if test -z "$LTCFLAGS"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`"
+ fi
+
+ # Extract list of available tagged configurations in $ofile.
+ # Note that this assumes the entire list is on one line.
+ available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for tagname in $tagnames; do
+ IFS="$lt_save_ifs"
+ # Check whether tagname contains only valid characters
+ case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in
+ "") ;;
+ *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5
+echo "$as_me: error: invalid tag name: $tagname" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+ then
+ { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5
+echo "$as_me: error: tag name \"$tagname\" already exists" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ # Update the list of available tags.
+ if test -n "$tagname"; then
+ echo appending configuration tag \"$tagname\" to $ofile
+
+ case $tagname in
+ CXX)
+ if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+
+archive_cmds_need_lc_CXX=no
+allow_undefined_flag_CXX=
+always_export_symbols_CXX=no
+archive_expsym_cmds_CXX=
+export_dynamic_flag_spec_CXX=
+hardcode_direct_CXX=no
+hardcode_libdir_flag_spec_CXX=
+hardcode_libdir_flag_spec_ld_CXX=
+hardcode_libdir_separator_CXX=
+hardcode_minus_L_CXX=no
+hardcode_shlibpath_var_CXX=unsupported
+hardcode_automatic_CXX=no
+module_cmds_CXX=
+module_expsym_cmds_CXX=
+link_all_deplibs_CXX=unknown
+old_archive_cmds_CXX=$old_archive_cmds
+no_undefined_flag_CXX=
+whole_archive_flag_spec_CXX=
+enable_shared_with_static_runtimes_CXX=no
+
+# Dependencies to place before and after the object being linked:
+predep_objects_CXX=
+postdep_objects_CXX=
+predeps_CXX=
+postdeps_CXX=
+compiler_lib_search_path_CXX=
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+objext_CXX=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+ $as_unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+ $as_unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+compiler_CXX=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+ lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
+else
+ lt_prog_compiler_no_builtin_flag_CXX=
+fi
+
+if test "$GXX" = yes; then
+ # Set up default GNU C++ configuration
+
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval="$with_gnu_ld"
+ test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi;
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
+else
+ echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+ { (exit 1); exit 1; }; }
+echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test "$with_gnu_ld" = yes; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='${wl}'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+ grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_CXX=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
+ld_shlibs_CXX=yes
+case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_CXX=''
+ hardcode_direct_CXX=yes
+ hardcode_libdir_separator_CXX=':'
+ link_all_deplibs_CXX=yes
+
+ if test "$GXX" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct_CXX=yes
+ else
+ # We have old collect2
+ hardcode_direct_CXX=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_CXX=yes
+ hardcode_libdir_flag_spec_CXX='-L$libdir'
+ hardcode_libdir_separator_CXX=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols_CXX=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_CXX='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+ archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_CXX="-z nodefs"
+ archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_CXX=' ${wl}-bernotok'
+ allow_undefined_flag_CXX=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_CXX='$convenience'
+ archive_cmds_need_lc_CXX=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_CXX=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_CXX=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_CXX='-L$libdir'
+ allow_undefined_flag_CXX=unsupported
+ always_export_symbols_CXX=no
+ enable_shared_with_static_runtimes_CXX=yes
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc_CXX=no
+ hardcode_direct_CXX=no
+ hardcode_automatic_CXX=yes
+ hardcode_shlibpath_var_CXX=unsupported
+ whole_archive_flag_spec_CXX=''
+ link_all_deplibs_CXX=yes
+
+ if test "$GXX" = yes ; then
+ lt_int_apple_cc_single_mod=no
+ output_verbose_link_cmd='echo'
+ if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
+ lt_int_apple_cc_single_mod=yes
+ fi
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ else
+ archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ fi
+ module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ fi
+ module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ freebsd[12]*)
+ # C++ shared libraries reported to be fairly broken before switch to ELF
+ ld_shlibs_CXX=no
+ ;;
+ freebsd-elf*)
+ archive_cmds_need_lc_CXX=no
+ ;;
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ ld_shlibs_CXX=yes
+ ;;
+ gnu*)
+ ;;
+ hpux9*)
+ hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ hardcode_direct_CXX=yes
+ hardcode_minus_L_CXX=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aCC*)
+ archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; then
+ hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld_CXX='+b $libdir'
+ ;;
+ *)
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ ;;
+ *)
+ hardcode_direct_CXX=yes
+ hardcode_minus_L_CXX=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ interix3*)
+ hardcode_direct_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+ fi
+ fi
+ link_all_deplibs_CXX=yes
+ ;;
+ esac
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc*)
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ archive_cmds_need_lc_CXX=no
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ ;;
+ pgCC*)
+ # Portland Group C++ compiler
+ archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ esac
+ ;;
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ m88k*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ hardcode_direct_CXX=yes
+ hardcode_shlibpath_var_CXX=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ ld_shlibs_CXX=no
+ ;;
+ openbsd*)
+ hardcode_direct_CXX=yes
+ hardcode_shlibpath_var_CXX=no
+ archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ fi
+ output_verbose_link_cmd='echo'
+ ;;
+ osf3*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ cxx*)
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -o $oldlib $oldobjs'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ cxx*)
+ allow_undefined_flag_CXX=' -expect_unresolved \*'
+ archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~
+ $rm $lib.exp'
+
+ hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ psos*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ archive_cmds_need_lc_CXX=yes
+ no_undefined_flag_CXX=' -zdefs'
+ archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ hardcode_shlibpath_var_CXX=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The C++ compiler is used as linker so we must use $wl
+ # flag to pass the commands to the underlying system
+ # linker. We must also pass each convience library through
+ # to the system linker between allextract/defaultextract.
+ # The C++ compiler will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract'
+ ;;
+ esac
+ link_all_deplibs_CXX=yes
+
+ output_verbose_link_cmd='echo'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ no_undefined_flag_CXX=' ${wl}-z ${wl}defs'
+ if $CC --version | grep -v '^2\.7' > /dev/null; then
+ archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir'
+ fi
+ ;;
+ esac
+ ;;
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ no_undefined_flag_CXX='${wl}-z,text'
+ archive_cmds_need_lc_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ # So that behaviour is only enabled if SCOABSPATH is set to a
+ # non-empty value in the environment. Most likely only useful for
+ # creating official distributions of packages.
+ # This is a hack until libtool officially supports absolute path
+ # names for shared libraries.
+ no_undefined_flag_CXX='${wl}-z,text'
+ allow_undefined_flag_CXX='${wl}-z,nodefs'
+ archive_cmds_need_lc_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator_CXX=':'
+ link_all_deplibs_CXX=yes
+ export_dynamic_flag_spec_CXX='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+esac
+echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+GCC_CXX="$GXX"
+LD_CXX="$LD"
+
+
+cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+EOF
+
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ # The `*' in the case matches for architectures that use `case' in
+ # $output_verbose_cmd can trigger glob expansion during the loop
+ # eval without this substitution.
+ output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
+
+ for p in `eval $output_verbose_link_cmd`; do
+ case $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" \
+ || test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p in
+ -L* | -R*)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$compiler_lib_search_path_CXX"; then
+ compiler_lib_search_path_CXX="${prev}${p}"
+ else
+ compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$postdeps_CXX"; then
+ postdeps_CXX="${prev}${p}"
+ else
+ postdeps_CXX="${postdeps_CXX} ${prev}${p}"
+ fi
+ fi
+ ;;
+
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ if test -z "$predep_objects_CXX"; then
+ predep_objects_CXX="$p"
+ else
+ predep_objects_CXX="$predep_objects_CXX $p"
+ fi
+ else
+ if test -z "$postdep_objects_CXX"; then
+ postdep_objects_CXX="$p"
+ else
+ postdep_objects_CXX="$postdep_objects_CXX $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling CXX test program"
+fi
+
+$rm -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+case $host_os in
+interix3*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ predep_objects_CXX=
+ postdep_objects_CXX=
+ postdeps_CXX=
+ ;;
+
+solaris*)
+ case $cc_basename in
+ CC*)
+ # Adding this requires a known-good setup of shared libraries for
+ # Sun compiler versions before 5.6, else PIC objects from an old
+ # archive will be linked into the output, leading to subtle bugs.
+ postdeps_CXX='-lCstd -lCrun'
+ ;;
+ esac
+ ;;
+esac
+
+
+case " $postdeps_CXX " in
+*" -lc "*) archive_cmds_need_lc_CXX=no ;;
+esac
+
+lt_prog_compiler_wl_CXX=
+lt_prog_compiler_pic_CXX=
+lt_prog_compiler_static_CXX=
+
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
+
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; then
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_CXX='-Bstatic'
+ fi
+ ;;
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | os2* | pw32*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_CXX='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ lt_prog_compiler_pic_CXX=
+ ;;
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_CXX=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ esac
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix4* | aix5*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_CXX='-Bstatic'
+ else
+ lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic_CXX='-qnocommon'
+ lt_prog_compiler_wl_CXX='-Wl,'
+ ;;
+ esac
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ lt_prog_compiler_pic_CXX='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+ if test "$host_cpu" != ia64; then
+ lt_prog_compiler_pic_CXX='+Z'
+ fi
+ ;;
+ aCC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ lt_prog_compiler_wl_CXX='--backend -Wl,'
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ icpc* | ecpc*)
+ # Intel C++
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-static'
+ ;;
+ pgCC*)
+ # Portland Group C++ compiler.
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-fpic'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_static_CXX='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ lt_prog_compiler_pic_CXX='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd*)
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ lt_prog_compiler_wl_CXX='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ lt_prog_compiler_wl_CXX='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_static_CXX='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ lt_prog_compiler_wl_CXX='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ lt_prog_compiler_pic_CXX='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ lt_prog_compiler_pic_CXX='-pic'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ lt_prog_compiler_pic_CXX='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ lt_prog_compiler_can_build_shared_CXX=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_CXX"; then
+
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6
+if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works_CXX=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:12445: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:12449: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works_CXX=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6
+
+if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then
+ case $lt_prog_compiler_pic_CXX in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;;
+ esac
+else
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_can_build_shared_CXX=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_CXX=
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
+if test "${lt_prog_compiler_static_works_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works_CXX=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works_CXX=yes
+ fi
+ else
+ lt_prog_compiler_static_works_CXX=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6
+
+if test x"$lt_prog_compiler_static_works_CXX" = xyes; then
+ :
+else
+ lt_prog_compiler_static_CXX=
+fi
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o_CXX=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:12549: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:12553: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_CXX=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
+
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ case $host_os in
+ aix4* | aix5*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ export_symbols_cmds_CXX="$ltdll_cmds"
+ ;;
+ cygwin* | mingw*)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([^ ]*\) [^ ]*/\1 DATA/;/^I /d;/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ *)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+
+echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_CXX" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_CXX=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_CXX in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_CXX
+ pic_flag=$lt_prog_compiler_pic_CXX
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
+ allow_undefined_flag_CXX=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc_CXX=no
+ else
+ archive_cmds_need_lc_CXX=yes
+ fi
+ allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
+hardcode_action_CXX=
+if test -n "$hardcode_libdir_flag_spec_CXX" || \
+ test -n "$runpath_var_CXX" || \
+ test "X$hardcode_automatic_CXX" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct_CXX" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no &&
+ test "$hardcode_minus_L_CXX" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_CXX=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_CXX=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_CXX=unsupported
+fi
+echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5
+echo "${ECHO_T}$hardcode_action_CXX" >&6
+
+if test "$hardcode_action_CXX" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_CXX \
+ CC_CXX \
+ LD_CXX \
+ lt_prog_compiler_wl_CXX \
+ lt_prog_compiler_pic_CXX \
+ lt_prog_compiler_static_CXX \
+ lt_prog_compiler_no_builtin_flag_CXX \
+ export_dynamic_flag_spec_CXX \
+ thread_safe_flag_spec_CXX \
+ whole_archive_flag_spec_CXX \
+ enable_shared_with_static_runtimes_CXX \
+ old_archive_cmds_CXX \
+ old_archive_from_new_cmds_CXX \
+ predep_objects_CXX \
+ postdep_objects_CXX \
+ predeps_CXX \
+ postdeps_CXX \
+ compiler_lib_search_path_CXX \
+ archive_cmds_CXX \
+ archive_expsym_cmds_CXX \
+ postinstall_cmds_CXX \
+ postuninstall_cmds_CXX \
+ old_archive_from_expsyms_cmds_CXX \
+ allow_undefined_flag_CXX \
+ no_undefined_flag_CXX \
+ export_symbols_cmds_CXX \
+ hardcode_libdir_flag_spec_CXX \
+ hardcode_libdir_flag_spec_ld_CXX \
+ hardcode_libdir_separator_CXX \
+ hardcode_automatic_CXX \
+ module_cmds_CXX \
+ module_expsym_cmds_CXX \
+ lt_cv_prog_compiler_c_o_CXX \
+ exclude_expsyms_CXX \
+ include_expsyms_CXX; do
+
+ case $var in
+ old_archive_cmds_CXX | \
+ old_archive_from_new_cmds_CXX | \
+ archive_cmds_CXX | \
+ archive_expsym_cmds_CXX | \
+ module_cmds_CXX | \
+ module_expsym_cmds_CXX | \
+ old_archive_from_expsyms_cmds_CXX | \
+ export_symbols_cmds_CXX | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_CXX
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_CXX
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_CXX
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_CXX
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_CXX
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_CXX
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_CXX
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_CXX
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_CXX
+archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_CXX
+module_expsym_cmds=$lt_module_expsym_cmds_CXX
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_CXX
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_CXX
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_CXX
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_CXX
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_CXX
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_CXX
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_CXX
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_CXX
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_CXX
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_CXX
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_CXX
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_CXX"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_CXX
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_CXX
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_CXX
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_CXX
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+
+ else
+ tagname=""
+ fi
+ ;;
+
+ F77)
+ if test -n "$F77" && test "X$F77" != "Xno"; then
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+archive_cmds_need_lc_F77=no
+allow_undefined_flag_F77=
+always_export_symbols_F77=no
+archive_expsym_cmds_F77=
+export_dynamic_flag_spec_F77=
+hardcode_direct_F77=no
+hardcode_libdir_flag_spec_F77=
+hardcode_libdir_flag_spec_ld_F77=
+hardcode_libdir_separator_F77=
+hardcode_minus_L_F77=no
+hardcode_automatic_F77=no
+module_cmds_F77=
+module_expsym_cmds_F77=
+link_all_deplibs_F77=unknown
+old_archive_cmds_F77=$old_archive_cmds
+no_undefined_flag_F77=
+whole_archive_flag_spec_F77=
+enable_shared_with_static_runtimes_F77=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+objext_F77=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code=" subroutine t\n return\n end\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code=" program t\n end\n"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+compiler_F77=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6
+
+echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6
+
+echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6
+
+GCC_F77="$G77"
+LD_F77="$LD"
+
+lt_prog_compiler_wl_F77=
+lt_prog_compiler_pic_F77=
+lt_prog_compiler_static_F77=
+
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_static_F77='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_F77='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_F77='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_F77='-fno-common'
+ ;;
+
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared_F77=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_F77=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_F77='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ lt_prog_compiler_pic_F77='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_F77='-Bstatic'
+ else
+ lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic_F77='-qnocommon'
+ lt_prog_compiler_wl_F77='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_F77='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_F77='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static_F77='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static_F77='-non_shared'
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ linux*)
+ case $cc_basename in
+ icc* | ecc*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-fpic'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static_F77='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static_F77='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ lt_prog_compiler_wl_F77='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl_F77='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl_F77='-Qoption ld '
+ lt_prog_compiler_pic_F77='-PIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic_F77='-Kconform_pic'
+ lt_prog_compiler_static_F77='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_can_build_shared_F77=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic_F77='-pic'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared_F77=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_F77"; then
+
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6
+if test "${lt_prog_compiler_pic_works_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works_F77=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_F77"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:14119: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:14123: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works_F77=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6
+
+if test x"$lt_prog_compiler_pic_works_F77" = xyes; then
+ case $lt_prog_compiler_pic_F77 in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;;
+ esac
+else
+ lt_prog_compiler_pic_F77=
+ lt_prog_compiler_can_build_shared_F77=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_F77=
+ ;;
+ *)
+ lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\"
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
+if test "${lt_prog_compiler_static_works_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works_F77=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works_F77=yes
+ fi
+ else
+ lt_prog_compiler_static_works_F77=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6
+
+if test x"$lt_prog_compiler_static_works_F77" = xyes; then
+ :
+else
+ lt_prog_compiler_static_F77=
+fi
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o_F77=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:14223: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:14227: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_F77=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
+
+ runpath_var=
+ allow_undefined_flag_F77=
+ enable_shared_with_static_runtimes_F77=no
+ archive_cmds_F77=
+ archive_expsym_cmds_F77=
+ old_archive_From_new_cmds_F77=
+ old_archive_from_expsyms_cmds_F77=
+ export_dynamic_flag_spec_F77=
+ whole_archive_flag_spec_F77=
+ thread_safe_flag_spec_F77=
+ hardcode_libdir_flag_spec_F77=
+ hardcode_libdir_flag_spec_ld_F77=
+ hardcode_libdir_separator_F77=
+ hardcode_direct_F77=no
+ hardcode_minus_L_F77=no
+ hardcode_shlibpath_var_F77=unsupported
+ link_all_deplibs_F77=unknown
+ hardcode_automatic_F77=no
+ module_cmds_F77=
+ module_expsym_cmds_F77=
+ always_export_symbols_F77=no
+ export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms_F77=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs_F77=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_F77='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_F77=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs_F77=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_minus_L_F77=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ ld_shlibs_F77=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_F77=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ allow_undefined_flag_F77=unsupported
+ always_export_symbols_F77=no
+ enable_shared_with_static_runtimes_F77=yes
+ export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ interix3*)
+ hardcode_direct_F77=no
+ hardcode_shlibpath_var_F77=no
+ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_F77='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ archive_cmds_F77='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs_F77=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs_F77=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs_F77" = no; then
+ runpath_var=
+ hardcode_libdir_flag_spec_F77=
+ export_dynamic_flag_spec_F77=
+ whole_archive_flag_spec_F77=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag_F77=unsupported
+ always_export_symbols_F77=yes
+ archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L_F77=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct_F77=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_F77=''
+ hardcode_direct_F77=yes
+ hardcode_libdir_separator_F77=':'
+ link_all_deplibs_F77=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct_F77=yes
+ else
+ # We have old collect2
+ hardcode_direct_F77=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_F77=yes
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_libdir_separator_F77=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols_F77=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_F77='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_F77="-z nodefs"
+ archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_F77=' ${wl}-bernotok'
+ allow_undefined_flag_F77=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_F77='$convenience'
+ archive_cmds_need_lc_F77=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_minus_L_F77=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs_F77=no
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec_F77=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec_F77=' '
+ allow_undefined_flag_F77=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_From_new_cmds_F77='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path_F77='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes_F77=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag_F77='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc_F77=no
+ hardcode_direct_F77=no
+ hardcode_automatic_F77=yes
+ hardcode_shlibpath_var_F77=unsupported
+ whole_archive_flag_spec_F77=''
+ link_all_deplibs_F77=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs_F77=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs_F77=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes
+ hardcode_minus_L_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ hardcode_direct_F77=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+
+ hardcode_direct_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_F77=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld_F77='+b $libdir'
+ hardcode_direct_F77=no
+ hardcode_shlibpath_var_F77=no
+ ;;
+ *)
+ hardcode_direct_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_F77=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_ld_F77='-rpath $libdir'
+ fi
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ link_all_deplibs_F77=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ newsos6)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ openbsd*)
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_F77='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ ;;
+ *)
+ archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_minus_L_F77=yes
+ allow_undefined_flag_F77=unsupported
+ archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag_F77=' -expect_unresolved \*'
+ archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag_F77=' -expect_unresolved \*'
+ archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec_F77='-rpath $libdir'
+ fi
+ hardcode_libdir_separator_F77=:
+ ;;
+
+ solaris*)
+ no_undefined_flag_F77=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_shlibpath_var_F77=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl, iff we do not link with $LD.
+ # Luckily, gcc supports the same syntax we need for Sun Studio.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ case $wlarc in
+ '')
+ whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;;
+ *)
+ whole_archive_flag_spec_F77='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
+ esac ;;
+ esac
+ link_all_deplibs_F77=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_direct_F77=yes
+ hardcode_minus_L_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds_F77='$CC -r -o $output$reload_objs'
+ hardcode_direct_F77=no
+ ;;
+ motorola)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_F77=no
+ export_dynamic_flag_spec_F77='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_F77=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs_F77=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
+ no_undefined_flag_F77='${wl}-z,text'
+ archive_cmds_need_lc_F77=no
+ hardcode_shlibpath_var_F77=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag_F77='${wl}-z,text'
+ allow_undefined_flag_F77='${wl}-z,nodefs'
+ archive_cmds_need_lc_F77=no
+ hardcode_shlibpath_var_F77=no
+ hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator_F77=':'
+ link_all_deplibs_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ *)
+ ld_shlibs_F77=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5
+echo "${ECHO_T}$ld_shlibs_F77" >&6
+test "$ld_shlibs_F77" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_F77" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_F77=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_F77 in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_F77
+ pic_flag=$lt_prog_compiler_pic_F77
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_F77
+ allow_undefined_flag_F77=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc_F77=no
+ else
+ archive_cmds_need_lc_F77=yes
+ fi
+ allow_undefined_flag_F77=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
+hardcode_action_F77=
+if test -n "$hardcode_libdir_flag_spec_F77" || \
+ test -n "$runpath_var_F77" || \
+ test "X$hardcode_automatic_F77" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct_F77" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no &&
+ test "$hardcode_minus_L_F77" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_F77=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_F77=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_F77=unsupported
+fi
+echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5
+echo "${ECHO_T}$hardcode_action_F77" >&6
+
+if test "$hardcode_action_F77" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_F77 \
+ CC_F77 \
+ LD_F77 \
+ lt_prog_compiler_wl_F77 \
+ lt_prog_compiler_pic_F77 \
+ lt_prog_compiler_static_F77 \
+ lt_prog_compiler_no_builtin_flag_F77 \
+ export_dynamic_flag_spec_F77 \
+ thread_safe_flag_spec_F77 \
+ whole_archive_flag_spec_F77 \
+ enable_shared_with_static_runtimes_F77 \
+ old_archive_cmds_F77 \
+ old_archive_from_new_cmds_F77 \
+ predep_objects_F77 \
+ postdep_objects_F77 \
+ predeps_F77 \
+ postdeps_F77 \
+ compiler_lib_search_path_F77 \
+ archive_cmds_F77 \
+ archive_expsym_cmds_F77 \
+ postinstall_cmds_F77 \
+ postuninstall_cmds_F77 \
+ old_archive_from_expsyms_cmds_F77 \
+ allow_undefined_flag_F77 \
+ no_undefined_flag_F77 \
+ export_symbols_cmds_F77 \
+ hardcode_libdir_flag_spec_F77 \
+ hardcode_libdir_flag_spec_ld_F77 \
+ hardcode_libdir_separator_F77 \
+ hardcode_automatic_F77 \
+ module_cmds_F77 \
+ module_expsym_cmds_F77 \
+ lt_cv_prog_compiler_c_o_F77 \
+ exclude_expsyms_F77 \
+ include_expsyms_F77; do
+
+ case $var in
+ old_archive_cmds_F77 | \
+ old_archive_from_new_cmds_F77 | \
+ archive_cmds_F77 | \
+ archive_expsym_cmds_F77 | \
+ module_cmds_F77 | \
+ module_expsym_cmds_F77 | \
+ old_archive_from_expsyms_cmds_F77 | \
+ export_symbols_cmds_F77 | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_F77
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_F77
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_F77
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_F77
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_F77
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_F77
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_F77
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_F77
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_F77
+archive_expsym_cmds=$lt_archive_expsym_cmds_F77
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_F77
+module_expsym_cmds=$lt_module_expsym_cmds_F77
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_F77
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_F77
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_F77
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_F77
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_F77
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_F77
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_F77
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_F77
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_F77
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_F77
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_F77
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_F77
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_F77
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_F77"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_F77
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_F77
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_F77
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_F77
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+ else
+ tagname=""
+ fi
+ ;;
+
+ GCJ)
+ if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+
+
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+objext_GCJ=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+compiler_GCJ=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+archive_cmds_need_lc_GCJ=no
+
+old_archive_cmds_GCJ=$old_archive_cmds
+
+
+lt_prog_compiler_no_builtin_flag_GCJ=
+
+if test "$GCC" = yes; then
+ lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin'
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_rtti_exceptions=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="-fno-rtti -fno-exceptions"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:16426: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:16430: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_rtti_exceptions=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+ lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions"
+else
+ :
+fi
+
+fi
+
+lt_prog_compiler_wl_GCJ=
+lt_prog_compiler_pic_GCJ=
+lt_prog_compiler_static_GCJ=
+
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_static_GCJ='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_GCJ='-fno-common'
+ ;;
+
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared_GCJ=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_GCJ=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_GCJ='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ lt_prog_compiler_pic_GCJ='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ else
+ lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic_GCJ='-qnocommon'
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_GCJ='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static_GCJ='-non_shared'
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ linux*)
+ case $cc_basename in
+ icc* | ecc*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-fpic'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static_GCJ='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static_GCJ='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ lt_prog_compiler_wl_GCJ='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl_GCJ='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl_GCJ='-Qoption ld '
+ lt_prog_compiler_pic_GCJ='-PIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic_GCJ='-Kconform_pic'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_can_build_shared_GCJ=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic_GCJ='-pic'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared_GCJ=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_GCJ"; then
+
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6
+if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works_GCJ=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_GCJ"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:16694: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:16698: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works_GCJ=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6
+
+if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then
+ case $lt_prog_compiler_pic_GCJ in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;;
+ esac
+else
+ lt_prog_compiler_pic_GCJ=
+ lt_prog_compiler_can_build_shared_GCJ=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_GCJ=
+ ;;
+ *)
+ lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\"
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
+if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works_GCJ=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works_GCJ=yes
+ fi
+ else
+ lt_prog_compiler_static_works_GCJ=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6
+
+if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then
+ :
+else
+ lt_prog_compiler_static_GCJ=
+fi
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o_GCJ=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:16798: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:16802: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_GCJ=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
+
+ runpath_var=
+ allow_undefined_flag_GCJ=
+ enable_shared_with_static_runtimes_GCJ=no
+ archive_cmds_GCJ=
+ archive_expsym_cmds_GCJ=
+ old_archive_From_new_cmds_GCJ=
+ old_archive_from_expsyms_cmds_GCJ=
+ export_dynamic_flag_spec_GCJ=
+ whole_archive_flag_spec_GCJ=
+ thread_safe_flag_spec_GCJ=
+ hardcode_libdir_flag_spec_GCJ=
+ hardcode_libdir_flag_spec_ld_GCJ=
+ hardcode_libdir_separator_GCJ=
+ hardcode_direct_GCJ=no
+ hardcode_minus_L_GCJ=no
+ hardcode_shlibpath_var_GCJ=unsupported
+ link_all_deplibs_GCJ=unknown
+ hardcode_automatic_GCJ=no
+ module_cmds_GCJ=
+ module_expsym_cmds_GCJ=
+ always_export_symbols_GCJ=no
+ export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms_GCJ=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs_GCJ=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_GCJ='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_GCJ=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs_GCJ=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_minus_L_GCJ=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ ld_shlibs_GCJ=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_GCJ=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ allow_undefined_flag_GCJ=unsupported
+ always_export_symbols_GCJ=no
+ enable_shared_with_static_runtimes_GCJ=yes
+ export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ interix3*)
+ hardcode_direct_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ archive_cmds_GCJ='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs_GCJ=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs_GCJ=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs_GCJ" = no; then
+ runpath_var=
+ hardcode_libdir_flag_spec_GCJ=
+ export_dynamic_flag_spec_GCJ=
+ whole_archive_flag_spec_GCJ=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag_GCJ=unsupported
+ always_export_symbols_GCJ=yes
+ archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L_GCJ=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct_GCJ=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_GCJ=''
+ hardcode_direct_GCJ=yes
+ hardcode_libdir_separator_GCJ=':'
+ link_all_deplibs_GCJ=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct_GCJ=yes
+ else
+ # We have old collect2
+ hardcode_direct_GCJ=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_GCJ=yes
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_libdir_separator_GCJ=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols_GCJ=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_GCJ='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_GCJ="-z nodefs"
+ archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_GCJ=' ${wl}-bernotok'
+ allow_undefined_flag_GCJ=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_GCJ='$convenience'
+ archive_cmds_need_lc_GCJ=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_minus_L_GCJ=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs_GCJ=no
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec_GCJ=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec_GCJ=' '
+ allow_undefined_flag_GCJ=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_From_new_cmds_GCJ='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes_GCJ=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc_GCJ=no
+ hardcode_direct_GCJ=no
+ hardcode_automatic_GCJ=yes
+ hardcode_shlibpath_var_GCJ=unsupported
+ whole_archive_flag_spec_GCJ=''
+ link_all_deplibs_GCJ=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs_GCJ=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs_GCJ=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes
+ hardcode_minus_L_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ hardcode_direct_GCJ=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+
+ hardcode_direct_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_GCJ=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld_GCJ='+b $libdir'
+ hardcode_direct_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+ *)
+ hardcode_direct_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_GCJ=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir'
+ fi
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ link_all_deplibs_GCJ=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ newsos6)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ openbsd*)
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ ;;
+ *)
+ archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_minus_L_GCJ=yes
+ allow_undefined_flag_GCJ=unsupported
+ archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag_GCJ=' -expect_unresolved \*'
+ archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag_GCJ=' -expect_unresolved \*'
+ archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec_GCJ='-rpath $libdir'
+ fi
+ hardcode_libdir_separator_GCJ=:
+ ;;
+
+ solaris*)
+ no_undefined_flag_GCJ=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_shlibpath_var_GCJ=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl, iff we do not link with $LD.
+ # Luckily, gcc supports the same syntax we need for Sun Studio.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ case $wlarc in
+ '')
+ whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;;
+ *)
+ whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
+ esac ;;
+ esac
+ link_all_deplibs_GCJ=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_minus_L_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds_GCJ='$CC -r -o $output$reload_objs'
+ hardcode_direct_GCJ=no
+ ;;
+ motorola)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_GCJ=no
+ export_dynamic_flag_spec_GCJ='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_GCJ=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs_GCJ=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
+ no_undefined_flag_GCJ='${wl}-z,text'
+ archive_cmds_need_lc_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag_GCJ='${wl}-z,text'
+ allow_undefined_flag_GCJ='${wl}-z,nodefs'
+ archive_cmds_need_lc_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator_GCJ=':'
+ link_all_deplibs_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ *)
+ ld_shlibs_GCJ=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5
+echo "${ECHO_T}$ld_shlibs_GCJ" >&6
+test "$ld_shlibs_GCJ" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_GCJ" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_GCJ=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_GCJ in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_GCJ
+ pic_flag=$lt_prog_compiler_pic_GCJ
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ
+ allow_undefined_flag_GCJ=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc_GCJ=no
+ else
+ archive_cmds_need_lc_GCJ=yes
+ fi
+ allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
+hardcode_action_GCJ=
+if test -n "$hardcode_libdir_flag_spec_GCJ" || \
+ test -n "$runpath_var_GCJ" || \
+ test "X$hardcode_automatic_GCJ" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct_GCJ" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no &&
+ test "$hardcode_minus_L_GCJ" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_GCJ=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_GCJ=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_GCJ=unsupported
+fi
+echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5
+echo "${ECHO_T}$hardcode_action_GCJ" >&6
+
+if test "$hardcode_action_GCJ" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_GCJ \
+ CC_GCJ \
+ LD_GCJ \
+ lt_prog_compiler_wl_GCJ \
+ lt_prog_compiler_pic_GCJ \
+ lt_prog_compiler_static_GCJ \
+ lt_prog_compiler_no_builtin_flag_GCJ \
+ export_dynamic_flag_spec_GCJ \
+ thread_safe_flag_spec_GCJ \
+ whole_archive_flag_spec_GCJ \
+ enable_shared_with_static_runtimes_GCJ \
+ old_archive_cmds_GCJ \
+ old_archive_from_new_cmds_GCJ \
+ predep_objects_GCJ \
+ postdep_objects_GCJ \
+ predeps_GCJ \
+ postdeps_GCJ \
+ compiler_lib_search_path_GCJ \
+ archive_cmds_GCJ \
+ archive_expsym_cmds_GCJ \
+ postinstall_cmds_GCJ \
+ postuninstall_cmds_GCJ \
+ old_archive_from_expsyms_cmds_GCJ \
+ allow_undefined_flag_GCJ \
+ no_undefined_flag_GCJ \
+ export_symbols_cmds_GCJ \
+ hardcode_libdir_flag_spec_GCJ \
+ hardcode_libdir_flag_spec_ld_GCJ \
+ hardcode_libdir_separator_GCJ \
+ hardcode_automatic_GCJ \
+ module_cmds_GCJ \
+ module_expsym_cmds_GCJ \
+ lt_cv_prog_compiler_c_o_GCJ \
+ exclude_expsyms_GCJ \
+ include_expsyms_GCJ; do
+
+ case $var in
+ old_archive_cmds_GCJ | \
+ old_archive_from_new_cmds_GCJ | \
+ archive_cmds_GCJ | \
+ archive_expsym_cmds_GCJ | \
+ module_cmds_GCJ | \
+ module_expsym_cmds_GCJ | \
+ old_archive_from_expsyms_cmds_GCJ | \
+ export_symbols_cmds_GCJ | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_GCJ
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_GCJ
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_GCJ
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_GCJ
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_GCJ
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_GCJ
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_GCJ
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_GCJ
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_GCJ
+archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_GCJ
+module_expsym_cmds=$lt_module_expsym_cmds_GCJ
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_GCJ
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_GCJ
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_GCJ
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_GCJ
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_GCJ
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_GCJ
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_GCJ
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_GCJ
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_GCJ
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_GCJ
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_GCJ
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_GCJ"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_GCJ
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_GCJ
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_GCJ
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_GCJ
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+ else
+ tagname=""
+ fi
+ ;;
+
+ RC)
+
+
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+objext_RC=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+compiler_RC=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+lt_cv_prog_compiler_c_o_RC=yes
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_RC \
+ CC_RC \
+ LD_RC \
+ lt_prog_compiler_wl_RC \
+ lt_prog_compiler_pic_RC \
+ lt_prog_compiler_static_RC \
+ lt_prog_compiler_no_builtin_flag_RC \
+ export_dynamic_flag_spec_RC \
+ thread_safe_flag_spec_RC \
+ whole_archive_flag_spec_RC \
+ enable_shared_with_static_runtimes_RC \
+ old_archive_cmds_RC \
+ old_archive_from_new_cmds_RC \
+ predep_objects_RC \
+ postdep_objects_RC \
+ predeps_RC \
+ postdeps_RC \
+ compiler_lib_search_path_RC \
+ archive_cmds_RC \
+ archive_expsym_cmds_RC \
+ postinstall_cmds_RC \
+ postuninstall_cmds_RC \
+ old_archive_from_expsyms_cmds_RC \
+ allow_undefined_flag_RC \
+ no_undefined_flag_RC \
+ export_symbols_cmds_RC \
+ hardcode_libdir_flag_spec_RC \
+ hardcode_libdir_flag_spec_ld_RC \
+ hardcode_libdir_separator_RC \
+ hardcode_automatic_RC \
+ module_cmds_RC \
+ module_expsym_cmds_RC \
+ lt_cv_prog_compiler_c_o_RC \
+ exclude_expsyms_RC \
+ include_expsyms_RC; do
+
+ case $var in
+ old_archive_cmds_RC | \
+ old_archive_from_new_cmds_RC | \
+ archive_cmds_RC | \
+ archive_expsym_cmds_RC | \
+ module_cmds_RC | \
+ module_expsym_cmds_RC | \
+ old_archive_from_expsyms_cmds_RC | \
+ export_symbols_cmds_RC | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_RC
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_RC
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_RC
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_RC
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_RC
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_RC
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_RC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_RC
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_RC
+archive_expsym_cmds=$lt_archive_expsym_cmds_RC
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_RC
+module_expsym_cmds=$lt_module_expsym_cmds_RC
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_RC
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_RC
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_RC
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_RC
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_RC
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_RC
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_RC
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_RC
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_RC
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_RC
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_RC
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_RC
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_RC
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_RC"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_RC
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_RC
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_RC
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_RC
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+ ;;
+
+ *)
+ { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5
+echo "$as_me: error: Unsupported tag name: $tagname" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+
+ # Append the new tag name to the list of available tags.
+ if test -n "$tagname" ; then
+ available_tags="$available_tags $tagname"
+ fi
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ # Now substitute the updated list of available tags.
+ if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+ mv "${ofile}T" "$ofile"
+ chmod +x "$ofile"
+ else
+ rm -f "${ofile}T"
+ { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5
+echo "$as_me: error: unable to update list of available tagged configurations." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+fi
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Prevent multiple expansion
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test ".$PACKAGE_VERSION" = "." && PACKAGE_VERSION="$VERSION"
+echo "$as_me:$LINENO: checking out linker version info $PACKAGE_VERSION " >&5
+echo $ECHO_N "checking out linker version info $PACKAGE_VERSION ... $ECHO_C" >&6
+ MINOR_VERSION=`echo $PACKAGE_VERSION`
+ MAJOR_VERSION=`echo "$MINOR_VERSION" | sed -e 's/[.].*//'`
+ MINOR_VERSION=`echo "$MINOR_VERSION" | sed -e "s/^$MAJOR_VERSION//" -e 's/^.//'`
+ MICRO_VERSION="$MINOR_VERSION"
+ MINOR_VERSION=`echo "$MICRO_VERSION" | sed -e 's/[.].*//'`
+ MICRO_VERSION=`echo "$MICRO_VERSION" | sed -e "s/^$MINOR_VERSION//" -e 's/^.//'`
+ PATCH_VERSION="$MICRO_VERSION"
+ MICRO_VERSION=`echo "$PATCH_VERSION" | sed -e 's/[^0-9].*//'`
+ PATCH_VERSION=`echo "$PATCH_VERSION" | sed -e "s/^$MICRO_VERSION//" -e 's/[-.]//'`
+ if test "_$MICRO_VERSION" = "_" ; then MICRO_VERSION="0" ; fi
+ if test "_$MINOR_VERSION" = "_" ; then MINOR_VERSION="$MAJOR_VERSION" ; MAJOR_VERSION="0" ; fi
+ MINOR_VERSION=`echo "$MINOR_VERSION" | sed -e 's/[^0-9].*//'`
+ RELEASE_INFO="-release $MAJOR_VERSION"
+ VERSION_INFO="-version-info $MINOR_VERSION:$MICRO_VERSION"
+echo "$as_me:$LINENO: result: /$MAJOR_VERSION/$MINOR_VERSION:$MICRO_VERSION (-$MAJOR_VERSION.so.$MINOR_VERSION.0.$MICRO_VERSION)" >&5
+echo "${ECHO_T}/$MAJOR_VERSION/$MINOR_VERSION:$MICRO_VERSION (-$MAJOR_VERSION.so.$MINOR_VERSION.0.$MICRO_VERSION)" >&6
+
+
+
+
+# -----------------------------------------------------------------------
+echo "$as_me:$LINENO: result: creating zzip/_msvc.in via zzip/_msvc.sed of config.h.in" >&5
+echo "${ECHO_T}creating zzip/_msvc.in via zzip/_msvc.sed of config.h.in" >&6
+test -d zzip || mkdir zzip
+sed -f $srcdir/zzip/_msvc.sed $srcdir/config.h.in >zzip/_msvc.in
+ ac_config_headers="$ac_config_headers config.h"
+
+
+ ac_config_commands="$ac_config_commands zzip/_config.h"
+
+
+ ac_config_commands="$ac_config_commands zzip/_msvc.h"
+
+echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5
+echo $ECHO_N "checking whether to enable maintainer-specific portions of Makefiles... $ECHO_C" >&6
+ # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then
+ enableval="$enable_maintainer_mode"
+ USE_MAINTAINER_MODE=$enableval
+else
+ USE_MAINTAINER_MODE=no
+fi;
+ echo "$as_me:$LINENO: result: $USE_MAINTAINER_MODE" >&5
+echo "${ECHO_T}$USE_MAINTAINER_MODE" >&6
+
+
+if test $USE_MAINTAINER_MODE = yes; then
+ MAINTAINER_MODE_TRUE=
+ MAINTAINER_MODE_FALSE='#'
+else
+ MAINTAINER_MODE_TRUE='#'
+ MAINTAINER_MODE_FALSE=
+fi
+
+ MAINT=$MAINTAINER_MODE_TRUE
+
+
+
+
+# we need the expanded forms...
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+echo "$as_me:$LINENO: checking our pkgconfig libname" >&5
+echo $ECHO_N "checking our pkgconfig libname... $ECHO_C" >&6
+test ".$ax_create_pkgconfig_libname" != "." || \
+ax_create_pkgconfig_libname="`basename zzip/zziplib.pc .pc`"
+test ".$ax_create_pkgconfig_libname" != "." || \
+ax_create_pkgconfig_libname="$PACKAGE"
+ax_create_pkgconfig_libname=`eval echo "$ax_create_pkgconfig_libname"`
+ax_create_pkgconfig_libname=`eval echo "$ax_create_pkgconfig_libname"`
+echo "$as_me:$LINENO: result: $ax_create_pkgconfig_libname" >&5
+echo "${ECHO_T}$ax_create_pkgconfig_libname" >&6
+
+echo "$as_me:$LINENO: checking our pkgconfig version" >&5
+echo $ECHO_N "checking our pkgconfig version... $ECHO_C" >&6
+test ".$ax_create_pkgconfig_version" != "." || \
+ax_create_pkgconfig_version="${PACKAGE_VERSION}"
+test ".$ax_create_pkgconfig_version" != "." || \
+ax_create_pkgconfig_version="$VERSION"
+ax_create_pkgconfig_version=`eval echo "$ax_create_pkgconfig_version"`
+ax_create_pkgconfig_version=`eval echo "$ax_create_pkgconfig_version"`
+echo "$as_me:$LINENO: result: $ax_create_pkgconfig_version" >&5
+echo "${ECHO_T}$ax_create_pkgconfig_version" >&6
+
+echo "$as_me:$LINENO: checking our pkgconfig_libdir" >&5
+echo $ECHO_N "checking our pkgconfig_libdir... $ECHO_C" >&6
+test ".$pkgconfig_libdir" = "." && \
+pkgconfig_libdir='${libdir}/pkgconfig'
+ax_create_pkgconfig_libdir=`eval echo "$pkgconfig_libdir"`
+ax_create_pkgconfig_libdir=`eval echo "$ax_create_pkgconfig_libdir"`
+ax_create_pkgconfig_libdir=`eval echo "$ax_create_pkgconfig_libdir"`
+echo "$as_me:$LINENO: result: $pkgconfig_libdir" >&5
+echo "${ECHO_T}$pkgconfig_libdir" >&6
+test "$pkgconfig_libdir" != "$ax_create_pkgconfig_libdir" && (
+echo "$as_me:$LINENO: result: expanded our pkgconfig_libdir... $ax_create_pkgconfig_libdir" >&5
+echo "${ECHO_T}expanded our pkgconfig_libdir... $ax_create_pkgconfig_libdir" >&6)
+
+
+echo "$as_me:$LINENO: checking our pkgconfig_libfile" >&5
+echo $ECHO_N "checking our pkgconfig_libfile... $ECHO_C" >&6
+test ".$pkgconfig_libfile" != "." || \
+pkgconfig_libfile="`basename zzip/zziplib.pc`"
+ax_create_pkgconfig_libfile=`eval echo "$pkgconfig_libfile"`
+ax_create_pkgconfig_libfile=`eval echo "$ax_create_pkgconfig_libfile"`
+echo "$as_me:$LINENO: result: $pkgconfig_libfile" >&5
+echo "${ECHO_T}$pkgconfig_libfile" >&6
+test "$pkgconfig_libfile" != "$ax_create_pkgconfig_libfile" && (
+echo "$as_me:$LINENO: result: expanded our pkgconfig_libfile... $ax_create_pkgconfig_libfile" >&5
+echo "${ECHO_T}expanded our pkgconfig_libfile... $ax_create_pkgconfig_libfile" >&6)
+
+
+echo "$as_me:$LINENO: checking our package / suffix" >&5
+echo $ECHO_N "checking our package / suffix... $ECHO_C" >&6
+ax_create_pkgconfig_suffix="$program_suffix"
+test ".$ax_create_pkgconfig_suffix" != .NONE || ax_create_pkgconfig_suffix=""
+echo "$as_me:$LINENO: result: ${PACKAGE_NAME} / ${ax_create_pkgconfig_suffix}" >&5
+echo "${ECHO_T}${PACKAGE_NAME} / ${ax_create_pkgconfig_suffix}" >&6
+
+echo "$as_me:$LINENO: checking our pkgconfig description" >&5
+echo $ECHO_N "checking our pkgconfig description... $ECHO_C" >&6
+ax_create_pkgconfig_description="$PACKAGE_SUMMARY"
+test ".$ax_create_pkgconfig_description" != "." || \
+ax_create_pkgconfig_description="$ax_create_pkgconfig_libname Library"
+ax_create_pkgconfig_description=`eval echo "$ax_create_pkgconfig_description"`
+ax_create_pkgconfig_description=`eval echo "$ax_create_pkgconfig_description"`
+echo "$as_me:$LINENO: result: $ax_create_pkgconfig_description" >&5
+echo "${ECHO_T}$ax_create_pkgconfig_description" >&6
+
+echo "$as_me:$LINENO: checking our pkgconfig requires" >&5
+echo $ECHO_N "checking our pkgconfig requires... $ECHO_C" >&6
+ax_create_pkgconfig_requires="zzip-zlib-config"
+ax_create_pkgconfig_requires=`eval echo "$ax_create_pkgconfig_requires"`
+ax_create_pkgconfig_requires=`eval echo "$ax_create_pkgconfig_requires"`
+echo "$as_me:$LINENO: result: $ax_create_pkgconfig_requires" >&5
+echo "${ECHO_T}$ax_create_pkgconfig_requires" >&6
+
+echo "$as_me:$LINENO: checking our pkgconfig ext libs" >&5
+echo $ECHO_N "checking our pkgconfig ext libs... $ECHO_C" >&6
+ax_create_pkgconfig_pkglibs="$PACKAGE_LIBS"
+test ".$ax_create_pkgconfig_pkglibs" != "." || ax_create_pkgconfig_pkglibs="-l$ax_create_pkgconfig_libname"
+ax_create_pkgconfig_libs="-lzzip"
+ax_create_pkgconfig_libs=`eval echo "$ax_create_pkgconfig_libs"`
+ax_create_pkgconfig_libs=`eval echo "$ax_create_pkgconfig_libs"`
+echo "$as_me:$LINENO: result: $ax_create_pkgconfig_libs" >&5
+echo "${ECHO_T}$ax_create_pkgconfig_libs" >&6
+
+echo "$as_me:$LINENO: checking our pkgconfig cppflags" >&5
+echo $ECHO_N "checking our pkgconfig cppflags... $ECHO_C" >&6
+ax_create_pkgconfig_cppflags="$CPPFLAGS $PACKAGE_CFLAGS"
+ax_create_pkgconfig_cppflags=`eval echo "$ax_create_pkgconfig_cppflags"`
+ax_create_pkgconfig_cppflags=`eval echo "$ax_create_pkgconfig_cppflags"`
+echo "$as_me:$LINENO: result: $ax_create_pkgconfig_cppflags" >&5
+echo "${ECHO_T}$ax_create_pkgconfig_cppflags" >&6
+
+echo "$as_me:$LINENO: checking our pkgconfig ldflags" >&5
+echo $ECHO_N "checking our pkgconfig ldflags... $ECHO_C" >&6
+ax_create_pkgconfig_ldflags="$LDFLAGS $PACKAGE_LDFLAGS"
+ax_create_pkgconfig_ldflags=`eval echo "$ax_create_pkgconfig_ldflags"`
+ax_create_pkgconfig_ldflags=`eval echo "$ax_create_pkgconfig_ldflags"`
+echo "$as_me:$LINENO: result: $ax_create_pkgconfig_ldflags" >&5
+echo "${ECHO_T}$ax_create_pkgconfig_ldflags" >&6
+
+test ".$ax_create_pkgconfig_generate" != "." || \
+ax_create_pkgconfig_generate="zzip/zziplib.pc"
+ax_create_pkgconfig_generate=`eval echo "$ax_create_pkgconfig_generate"`
+ax_create_pkgconfig_generate=`eval echo "$ax_create_pkgconfig_generate"`
+test "$pkgconfig_libfile" != "$ax_create_pkgconfig_generate" && (
+echo "$as_me:$LINENO: result: generate the pkgconfig later... $ax_create_pkgconfig_generate" >&5
+echo "${ECHO_T}generate the pkgconfig later... $ax_create_pkgconfig_generate" >&6)
+
+if test ".$ax_create_pkgconfig_src_libdir" = "." ; then
+ax_create_pkgconfig_src_libdir=`pwd`
+ax_create_pkgconfig_src_libdir=`(dirname "$ax_create_pkgconfig_src_libdir/$ax_create_pkgconfig_generate") 2>/dev/null ||
+$as_expr X"$ax_create_pkgconfig_src_libdir/$ax_create_pkgconfig_generate" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ax_create_pkgconfig_src_libdir/$ax_create_pkgconfig_generate" : 'X\(//\)[^/]' \| \
+ X"$ax_create_pkgconfig_src_libdir/$ax_create_pkgconfig_generate" : 'X\(//\)$' \| \
+ X"$ax_create_pkgconfig_src_libdir/$ax_create_pkgconfig_generate" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ax_create_pkgconfig_src_libdir/$ax_create_pkgconfig_generate" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+test ! -d $ax_create_pkgconfig_src_libdir/src || \
+ax_create_pkgconfig_src_libdir="$ax_create_pkgconfig_src_libdir/src"
+case ".$objdir" in
+*libs) ax_create_pkgconfig_src_libdir="$ax_create_pkgconfig_src_libdir/$objdir" ;; esac
+echo "$as_me:$LINENO: result: noninstalled pkgconfig -L $ax_create_pkgconfig_src_libdir" >&5
+echo "${ECHO_T}noninstalled pkgconfig -L $ax_create_pkgconfig_src_libdir" >&6
+fi
+
+if test ".$ax_create_pkgconfig_src_headers" = "." ; then
+ax_create_pkgconfig_src_headers=`pwd`
+v="$ac_top_srcdir" ;
+test ".$v" != "." || v="$ax_spec_dir"
+test ".$v" != "." || v="$srcdir"
+case "$v" in /*) PKG_CONFIG_src_headers="" ;; esac
+ax_create_pkgconfig_src_headers=`(dirname "$ax_create_pkgconfig_src_headers/$v/x") 2>/dev/null ||
+$as_expr X"$ax_create_pkgconfig_src_headers/$v/x" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ax_create_pkgconfig_src_headers/$v/x" : 'X\(//\)[^/]' \| \
+ X"$ax_create_pkgconfig_src_headers/$v/x" : 'X\(//\)$' \| \
+ X"$ax_create_pkgconfig_src_headers/$v/x" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ax_create_pkgconfig_src_headers/$v/x" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+test ! -d $ax_create_pkgconfig_src_headers/include || \
+ax_create_pkgconfig_src_headers="$ax_create_pkgconfig_src_headers/include"
+echo "$as_me:$LINENO: result: noninstalled pkgconfig -I $ax_create_pkgconfig_src_headers" >&5
+echo "${ECHO_T}noninstalled pkgconfig -I $ax_create_pkgconfig_src_headers" >&6
+fi
+
+
+ ac_config_commands="$ac_config_commands $ax_create_pkgconfig_generate"
+
+# -----------------------------------------------------------------------
+for ac_prog in perl5 perl
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_PERL+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $PERL in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ ;;
+esac
+fi
+PERL=$ac_cv_path_PERL
+
+if test -n "$PERL"; then
+ echo "$as_me:$LINENO: result: $PERL" >&5
+echo "${ECHO_T}$PERL" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$PERL" && break
+done
+test -n "$PERL" || PERL="echo no perl found for"
+
+for ac_prog in python2.2 python2.3 python
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_PYTHON+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $PYTHON in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ ;;
+esac
+fi
+PYTHON=$ac_cv_path_PYTHON
+
+if test -n "$PYTHON"; then
+ echo "$as_me:$LINENO: result: $PYTHON" >&5
+echo "${ECHO_T}$PYTHON" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$PYTHON" && break
+done
+test -n "$PYTHON" || PYTHON="echo no python found for"
+
+for ac_prog in zip pkzip
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_MKZIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $MKZIP in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_MKZIP="$MKZIP" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_MKZIP="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ ;;
+esac
+fi
+MKZIP=$ac_cv_path_MKZIP
+
+if test -n "$MKZIP"; then
+ echo "$as_me:$LINENO: result: $MKZIP" >&5
+echo "${ECHO_T}$MKZIP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$MKZIP" && break
+done
+test -n "$MKZIP" || MKZIP=":"
+
+for ac_prog in xmlto
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_XMLTO+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $XMLTO in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_XMLTO="$XMLTO" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_XMLTO="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ ;;
+esac
+fi
+XMLTO=$ac_cv_path_XMLTO
+
+if test -n "$XMLTO"; then
+ echo "$as_me:$LINENO: result: $XMLTO" >&5
+echo "${ECHO_T}$XMLTO" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$XMLTO" && break
+done
+test -n "$XMLTO" || XMLTO=":"
+
+
+echo "$as_me:$LINENO: checking for inline" >&5
+echo $ECHO_N "checking for inline... $ECHO_C" >&6
+if test "${ac_cv_c_inline+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_inline=$ac_kw; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
+echo "${ECHO_T}$ac_cv_c_inline" >&6
+
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
+if test "${ac_cv_c_const+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this. */
+ typedef int charset[2];
+ const charset x;
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *ccp;
+ char **p;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ ccp = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++ccp;
+ p = (char**) ccp;
+ ccp = (char const *const *) p;
+ { /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ }
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_const=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_const=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for C restrict keyword" >&5
+echo $ECHO_N "checking for C restrict keyword... $ECHO_C" >&6
+if test "${acx_cv_c_restrict+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ acx_cv_c_restrict=unsupported
+
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ # Try the official restrict keyword, then gcc's __restrict__, then
+ # SGI's __restrict. __restrict has slightly different semantics than
+ # restrict (it's a bit stronger, in that __restrict pointers can't
+ # overlap even with non __restrict pointers), but I think it should be
+ # okay under the circumstances where restrict is normally used.
+ for acx_kw in restrict __restrict__ __restrict; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+float * $acx_kw x;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ acx_cv_c_restrict=$acx_kw; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+echo "$as_me:$LINENO: result: $acx_cv_c_restrict" >&5
+echo "${ECHO_T}$acx_cv_c_restrict" >&6
+ if test "$acx_cv_c_restrict" != "restrict"; then
+ acx_kw="$acx_cv_c_restrict"
+ if test "$acx_kw" = unsupported; then acx_kw=""; fi
+
+cat >>confdefs.h <<_ACEOF
+#define restrict $acx_kw
+_ACEOF
+
+ fi
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ exit(2);
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+
+
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+ as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5
+echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main ()
+{
+if ((DIR *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+ echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir ();
+int
+main ()
+{
+opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_opendir="none required"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+ for ac_lib in dir; do
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir ();
+int
+main ()
+{
+opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_opendir="-l$ac_lib"
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+ test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+else
+ echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir ();
+int
+main ()
+{
+opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_opendir="none required"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+ for ac_lib in x; do
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir ();
+int
+main ()
+{
+opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_opendir="-l$ac_lib"
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+ test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+fi
+
+
+
+
+
+
+
+for ac_header in stdint.h unistd.h windows.h winnt.h winbase.h sys/int_types.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+for ac_header in sys/types.h sys/mman.h sys/stat.h sys/param.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+for ac_header in io.h direct.h zlib.h byteswap.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in fnmatch.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_func in strcasecmp strndup
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+echo "$as_me:$LINENO: checking for off_t" >&5
+echo $ECHO_N "checking for off_t... $ECHO_C" >&6
+if test "${ac_cv_type_off_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((off_t *) 0)
+ return 0;
+if (sizeof (off_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_off_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_off_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
+echo "${ECHO_T}$ac_cv_type_off_t" >&6
+if test $ac_cv_type_off_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off_t long
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6
+if test "${ac_cv_type_size_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((size_t *) 0)
+ return 0;
+if (sizeof (size_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_size_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_size_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6
+if test $ac_cv_type_size_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for ssize_t" >&5
+echo $ECHO_N "checking for ssize_t... $ECHO_C" >&6
+if test "${ac_cv_type_ssize_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((ssize_t *) 0)
+ return 0;
+if (sizeof (ssize_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_ssize_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_ssize_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_ssize_t" >&5
+echo "${ECHO_T}$ac_cv_type_ssize_t" >&6
+if test $ac_cv_type_ssize_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define ssize_t int
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for off64_t" >&5
+echo $ECHO_N "checking for off64_t... $ECHO_C" >&6
+if test "${ac_cv_type_off64_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((off64_t *) 0)
+ return 0;
+if (sizeof (off64_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_off64_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_off64_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_off64_t" >&5
+echo "${ECHO_T}$ac_cv_type_off64_t" >&6
+if test $ac_cv_type_off64_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off64_t _zzip_off_t
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for __int64" >&5
+echo $ECHO_N "checking for __int64... $ECHO_C" >&6
+if test "${ac_cv_type___int64+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((__int64 *) 0)
+ return 0;
+if (sizeof (__int64))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type___int64=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type___int64=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type___int64" >&5
+echo "${ECHO_T}$ac_cv_type___int64" >&6
+if test $ac_cv_type___int64 = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define __int64 long long
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking size of short" >&5
+echo $ECHO_N "checking size of short... $ECHO_C" >&6
+if test "${ac_cv_sizeof_short+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include "confdefs.h"
+#include <sys/types.h>
+
+
+int
+main ()
+{
+switch (0) case 0: case (sizeof (short) == $ac_size):;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_short=$ac_size
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test x$ac_cv_sizeof_short != x ; then break; fi
+done
+
+fi
+
+if test x$ac_cv_sizeof_short = x ; then
+ { { echo "$as_me:$LINENO: error: cannot determine a size for short" >&5
+echo "$as_me: error: cannot determine a size for short" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_short" >&5
+echo "${ECHO_T}$ac_cv_sizeof_short" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_SHORT $ac_cv_sizeof_short
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking size of int" >&5
+echo $ECHO_N "checking size of int... $ECHO_C" >&6
+if test "${ac_cv_sizeof_int+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include "confdefs.h"
+#include <sys/types.h>
+
+
+int
+main ()
+{
+switch (0) case 0: case (sizeof (int) == $ac_size):;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_int=$ac_size
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test x$ac_cv_sizeof_int != x ; then break; fi
+done
+
+fi
+
+if test x$ac_cv_sizeof_int = x ; then
+ { { echo "$as_me:$LINENO: error: cannot determine a size for int" >&5
+echo "$as_me: error: cannot determine a size for int" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5
+echo "${ECHO_T}$ac_cv_sizeof_int" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking size of long" >&5
+echo $ECHO_N "checking size of long... $ECHO_C" >&6
+if test "${ac_cv_sizeof_long+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include "confdefs.h"
+#include <sys/types.h>
+
+
+int
+main ()
+{
+switch (0) case 0: case (sizeof (long) == $ac_size):;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_long=$ac_size
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test x$ac_cv_sizeof_long != x ; then break; fi
+done
+
+fi
+
+if test x$ac_cv_sizeof_long = x ; then
+ { { echo "$as_me:$LINENO: error: cannot determine a size for long" >&5
+echo "$as_me: error: cannot determine a size for long" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6
+if test "${ac_cv_c_bigendian+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_bigendian=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_bigendian=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+# It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+ # try to guess the endianness by grepping values into an object file
+ ac_cv_c_bigendian=unknown
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+ ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+int
+main ()
+{
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long l;
+ char c[sizeof (long)];
+ } u;
+ u.l = 1;
+ exit (u.c[sizeof (long) - 1] == 1);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_bigendian=no
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_bigendian=yes
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6
+case $ac_cv_c_bigendian in
+ yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define WORDS_BIGENDIAN 1
+_ACEOF
+ ;;
+ no)
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+
+# the default is _disabled_!! anyway, result is prefixed in zzip/_config.h!!
+# Check whether --enable-largefile or --disable-largefile was given.
+if test "${enable_largefile+set}" = set; then
+ enableval="$enable_largefile"
+
+fi;
+if test "$enable_largefile" != no; then
+
+ echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5
+echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6
+if test "${ac_cv_sys_largefile_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_sys_largefile_CC=no
+ if test "$GCC" != yes; then
+ ac_save_CC=$CC
+ while :; do
+ # IRIX 6.2 and later do not support large files by default,
+ # so use the C compiler's -n32 option if that helps.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+ CC="$CC -n32"
+ rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sys_largefile_CC=' -n32'; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+ break
+ done
+ CC=$ac_save_CC
+ rm -f conftest.$ac_ext
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5
+echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6
+ if test "$ac_cv_sys_largefile_CC" != no; then
+ CC=$CC$ac_cv_sys_largefile_CC
+ fi
+
+ echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6
+if test "${ac_cv_sys_file_offset_bits+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ while :; do
+ ac_cv_sys_file_offset_bits=no
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sys_file_offset_bits=64; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ break
+done
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5
+echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6
+if test "$ac_cv_sys_file_offset_bits" != no; then
+
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+
+fi
+rm -f conftest*
+ echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5
+echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6
+if test "${ac_cv_sys_large_files+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ while :; do
+ ac_cv_sys_large_files=no
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sys_large_files=1; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ break
+done
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5
+echo "${ECHO_T}$ac_cv_sys_large_files" >&6
+if test "$ac_cv_sys_large_files" != no; then
+
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+
+fi
+rm -f conftest*
+fi
+
+# we know about some internals of ac_sys_largefile here...
+echo "$as_me:$LINENO: checking whether system differentiates 64bit off_t by defines" >&5
+echo $ECHO_N "checking whether system differentiates 64bit off_t by defines... $ECHO_C" >&6
+ac_cv_sys_largefile_sensitive="no"
+if test ".$ac_cv_sys_file_offset_bits$ac_cv_sys_large_files" != ".nono"
+then ac_cv_sys_largefile_sensitive="yes"
+
+cat >>confdefs.h <<\_ACEOF
+#define LARGEFILE_SENSITIVE 1
+_ACEOF
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_sensitive" >&5
+echo "${ECHO_T}$ac_cv_sys_largefile_sensitive" >&6
+
+test ".$LARGEFILE_CFLAGS" = "." && LARGEFILE_CFLAGS=""
+
+# Check whether --with-largefile or --without-largefile was given.
+if test "${with_largefile+set}" = set; then
+ withval="$with_largefile"
+
+else
+ with_largefile="no"
+fi;
+if test ".$ac_cv_sys_largefile_sensitive" = ".no" ; then
+ echo "$as_me:$LINENO: result: compiles library with the only off_t seen" >&5
+echo "${ECHO_T}compiles library with the only off_t seen" >&6
+elif test ".$with_largefile" != ".no" ; then
+ echo "$as_me:$LINENO: result: compiles library as 64bit off_t variant - and renaming some function names" >&5
+echo "${ECHO_T}compiles library as 64bit off_t variant - and renaming some function names" >&6
+ LARGEFILE_CFLAGS="$LARGEFILE_CFLAGS -D_LARGEFILE_SOURCE"
+ echo "$as_me:$LINENO: result: ..adding CFLAGS $LARGEFILE_CFLAGS" >&5
+echo "${ECHO_T}..adding CFLAGS $LARGEFILE_CFLAGS" >&6
+ CFLAGS="$CFLAGS $LARGEFILE_CFLAGS"
+ echo "$as_me:$LINENO: result: ..adding 64 into RELEASE_INFO for the libraries" >&5
+echo "${ECHO_T}..adding 64 into RELEASE_INFO for the libraries" >&6
+ RELEASE_INFO="$RELEASE_INFO-64"
+else
+ echo "$as_me:$LINENO: result: compiles library as 32bit off_t variant - largefile is not the default here" >&5
+echo "${ECHO_T}compiles library as 32bit off_t variant - largefile is not the default here" >&6
+fi
+
+echo "$as_me:$LINENO: checking for zlib being found" >&5
+echo $ECHO_N "checking for zlib being found... $ECHO_C" >&6
+if test "_$ac_cv_header_zlib_h" != "_yes" ; then
+ echo "$as_me:$LINENO: result: ...oops: zlib.h not found - try adding some CPPFLAGS to configure call" >&5
+echo "${ECHO_T}...oops: zlib.h not found - try adding some CPPFLAGS to configure call" >&6
+ echo "$as_me:$LINENO: result: ...note: and when linkage fails you might also need to set some LDFLAGS" >&5
+echo "${ECHO_T}...note: and when linkage fails you might also need to set some LDFLAGS" >&6
+ case "$prefix" in
+ NONE|/usr)
+ echo "$as_me:$LINENO: result: ...note: both can be set by specifying the install prefix of the zlib library" >&5
+echo "${ECHO_T}...note: both can be set by specifying the install prefix of the zlib library" >&6
+ echo "$as_me:$LINENO: result: ...note: via --with-zlib=path ... it will test for -Ipath/include -Lpath/lib" >&5
+echo "${ECHO_T}...note: via --with-zlib=path ... it will test for -Ipath/include -Lpath/lib" >&6
+ ;;
+ *) if test -d $prefix/include ; then
+ echo "$as_me:$LINENO: result: ...note: -I$prefix/include is not added to CPPFLAGS automatically and" >&5
+echo "${ECHO_T}...note: -I$prefix/include is not added to CPPFLAGS automatically and" >&6
+ echo "$as_me:$LINENO: result: ...note: neither is -L$prefix/lib for LDFLAGS .. both will be if you specify" >&5
+echo "${ECHO_T}...note: neither is -L$prefix/lib for LDFLAGS .. both will be if you specify" >&6
+ echo "$as_me:$LINENO: result: ...note: --with-zlib to configure call" >&5
+echo "${ECHO_T}...note: --with-zlib to configure call" >&6
+ fi
+ ;;
+ esac
+ { { echo "$as_me:$LINENO: error: zlib.h not found: \"zlib\" is required to build \"$PACKAGE\"" >&5
+echo "$as_me: error: zlib.h not found: \"zlib\" is required to build \"$PACKAGE\"" >&2;}
+ { (exit 1); exit 1; }; }
+ exit 1
+fi
+cat >conftest.c <<EOF
+#include <zlib.h>
+const char* zlib_VeRsIoN = ZLIB_VERSION "dEtEcT";
+EOF
+ZLIB_VERSION=`(eval "$ac_cpp conftest.c") 2>/dev/null \
+| grep zlib_VeRsIoN | sed -e 's,.*= *.,,' -e 's,. *.dEtEcT.*,,'`
+rm conftest.c
+
+echo "$as_me:$LINENO: result: yes - $ZLIB_VERSION" >&5
+echo "${ECHO_T}yes - $ZLIB_VERSION" >&6
+# ----------------------------------------------------------------
+echo "$as_me:$LINENO: checking docdir default" >&5
+echo $ECHO_N "checking docdir default... $ECHO_C" >&6
+
+# Check whether --with-docdir or --without-docdir was given.
+if test "${with_docdir+set}" = set; then
+ withval="$with_docdir"
+
+else
+ with_docdir="no"
+fi;
+case "${with_docdir}" in
+ prefix/*) docdir=` echo "$withval" | sed 's/^prefix/${prefix}'` ;;
+ datadir/*) docdir=` echo "$withval" | sed 's/^datadir/${datadir}'` ;;
+ yes) docdir='${prefix}/doc' ;;
+ no) docdir='${datadir}/doc' ;;
+ /*|\\*|a-zA-Z:*) docdir="$with_docdir" ;;
+ *) echo "$as_me:$LINENO: result: oops" >&5
+echo "${ECHO_T}oops" >&6
+ { { echo "$as_me:$LINENO: error: bad value ${withval} for --with-docdir" >&5
+echo "$as_me: error: bad value ${withval} for --with-docdir" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+esac
+
+echo "$as_me:$LINENO: result: $docdir" >&5
+echo "${ECHO_T}$docdir" >&6
+# ----------------------------------------------------------------
+echo "$as_me:$LINENO: checking whether using debugging messages in libraries" >&5
+echo $ECHO_N "checking whether using debugging messages in libraries... $ECHO_C" >&6
+
+# Check whether --with-debug or --without-debug was given.
+if test "${with_debug+set}" = set; then
+ withval="$with_debug"
+ case "${withval}" in
+ yes|no) with_debug="$withval" ;;
+ *) echo "$as_me:$LINENO: result: oops" >&5
+echo "${ECHO_T}oops" >&6
+ { { echo "$as_me:$LINENO: error: bad value ${withval} for --with-debug" >&5
+echo "$as_me: error: bad value ${withval} for --with-debug" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+else
+ with_debug="no"
+fi;
+test "$with_debug" != "yes" && with_debug="no" # yes or no
+test "$with_debug" = "yes" && export CFLAGS="$CFLAGS -DDEBUG"
+result="$with_debug" ; test "$result" = "yes" && result="yes, added -DDEBUG"
+echo "$as_me:$LINENO: result: $result" >&5
+echo "${ECHO_T}$result" >&6
+if test "$with_debug" = "yes" ; then if test -n "$RELEASE_INFO" ; then
+ RELEASE_INFO="$RELEASE_INFO-dbg"
+ echo "$as_me:$LINENO: result: modified release" >&5
+echo "${ECHO_T}modified release" >&6
+fi fi
+# ----------------------------------------------------------------
+echo "$as_me:$LINENO: checking whether thread stack is too small for bufsiz buffers" >&5
+echo $ECHO_N "checking whether thread stack is too small for bufsiz buffers... $ECHO_C" >&6
+ # many embedded platforms, superthreaded systems and kernel usage
+ # will severely limit the stackspace for its threads. Use _LOWSTK
+ # compile-define on those platforms.
+
+# Check whether --with-lowstk or --without-lowstk was given.
+if test "${with_lowstk+set}" = set; then
+ withval="$with_lowstk"
+ case "${withval}" in
+ yes|no|auto) with_lowstk="$withval" ;;
+ *) { { echo "$as_me:$LINENO: error: bad value ${withval} for --with-lowstk" >&5
+echo "$as_me: error: bad value ${withval} for --with-lowstk" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+else
+ with_lowstk="auto"
+fi;
+if test "$with_lowstk" = "auto"; then
+ case $target in
+ *-palmos-*) $with_lowstk="yes" ;;
+ esac
+fi
+test "$with_lowstk" != "yes" && with_lowstk="no" # yes or no
+test "$with_lowstk" = "yes" && CFLAGS="$CFLAGS -D_LOWSTK"
+result="$with_lowstk" ; test "$result" = "yes" && result="yes, added -D_LOWSTK"
+echo "$as_me:$LINENO: result: $with_lowstk" >&5
+echo "${ECHO_T}$with_lowstk" >&6
+# ---------------------------------------------------------------
+echo "$as_me:$LINENO: checking whether can use mmap for file scanning" >&5
+echo $ECHO_N "checking whether can use mmap for file scanning... $ECHO_C" >&6
+ # system with mmap are probably better performing an searching
+ # and parsing - atleast memory consumption is far better
+# Check whether --enable-mmap or --disable-mmap was given.
+if test "${enable_mmap+set}" = set; then
+ enableval="$enable_mmap"
+ case "${enableval}" in
+ yes|no|auto) enable_mmap="${enableval}" ;;
+ *) echo "$as_me:$LINENO: result: oops" >&5
+echo "${ECHO_T}oops" >&6
+ { { echo "$as_me:$LINENO: error: bad value ${enableval} for --disable-mmap" >&5
+echo "$as_me: error: bad value ${enableval} for --disable-mmap" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+else
+ enable_mmap="auto"
+fi;
+if test "$enable_mmap" = "auto"
+then
+ test "$ac_cv_header_winbase_h" && enable_mmap="yes, winbase.h"
+ test "$ac_cv_header_sys_mman_h" && enable_mmap="yes, sys/mman.h"
+fi
+case "$enable_mmap" in
+ yes|yes,*) CFLAGS="$CFLAGS -D_USE_MMAP"
+ echo "$as_me:$LINENO: result: $enable_mmap" >&5
+echo "${ECHO_T}$enable_mmap" >&6 ;;
+ *) enable_mmap="no"
+ echo "$as_me:$LINENO: result: no (just a bit slower)" >&5
+echo "${ECHO_T}no (just a bit slower)" >&6 ;;
+esac
+# ---------------------------------------------------------------
+echo "$as_me:$LINENO: checking whether making SDL parts" >&5
+echo $ECHO_N "checking whether making SDL parts... $ECHO_C" >&6
+SDL=""
+# Check whether --enable-sdl or --disable-sdl was given.
+if test "${enable_sdl+set}" = set; then
+ enableval="$enable_sdl"
+
+else
+ enable_sdl="no"
+fi;
+if test "$enable_sdl" = "no" ; then
+ echo "$as_me:$LINENO: result: no, disabled" >&5
+echo "${ECHO_T}no, disabled" >&6
+else
+ enable_sdl=`sdl-config --version 2>/dev/null`
+ case ".$enable_sdl" in
+ .1.*) echo "$as_me:$LINENO: result: yes, for SDL $enable_sdl" >&5
+echo "${ECHO_T}yes, for SDL $enable_sdl" >&6
+ SDL="SDL" ;;
+ .2.*) echo "$as_me:$LINENO: result: yes, untested $enable_sdl" >&5
+echo "${ECHO_T}yes, untested $enable_sdl" >&6
+ SDL="SDL" ;;
+ *) echo "$as_me:$LINENO: result: no, $enable_sdl" >&5
+echo "${ECHO_T}no, $enable_sdl" >&6 ;;
+ esac
+fi
+
+# ---------------------------------------------------------------
+echo "$as_me:$LINENO: checking running extra tests on make check" >&5
+echo $ECHO_N "checking running extra tests on make check... $ECHO_C" >&6
+if test "MKZIP" != ":" ; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ ZIPTESTS=""
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ ZIPTESTS="#"
+fi
+
+# ---------------------------------------------------------------
+echo "$as_me:$LINENO: checking link options" >&5
+echo $ECHO_N "checking link options... $ECHO_C" >&6
+case "$host_os" in
+ mingw*)
+ ZZIPLIB_LDFLAGS="-no-undefined -export-all-symbols -mconsole"
+ RESOLVES=' '
+ ;;
+ *)
+ ZZIPLIB_LDFLAGS="--export-dynamic"
+ RESOLVES=' # '
+ ;;
+esac
+echo "$as_me:$LINENO: result: $ZZIPLIB_LDFLAGS $RESOLVES" >&5
+echo "${ECHO_T}$ZZIPLIB_LDFLAGS $RESOLVES" >&6
+
+
+# ---------------------------------------------------------------
+echo "$as_me:$LINENO: checking auto silent in maintainer mode" >&5
+echo $ECHO_N "checking auto silent in maintainer mode... $ECHO_C" >&6
+if test "$USE_MAINTAINER_MODE" = "no" ; then
+ test ".$TIMEOUT" = "." && TIMEOUT="9"
+ AUTOHEADER="sleep $TIMEOUT ; true || autoheader || skipped"
+ AUTOMAKE="sleep $TIMEOUT ; true || automake || skipped"
+ AUTOCONF="sleep $TIMEOUT ; true || autoconf || skipped"
+ if test ".$LIBTOOL" != "." ; then
+ LIBTOOL="$LIBTOOL --silent"
+ echo "$as_me:$LINENO: result: libtool-silent, auto-sleep-9" >&5
+echo "${ECHO_T}libtool-silent, auto-sleep-9" >&6
+ else
+ echo "$as_me:$LINENO: result: auto-sleep-9" >&5
+echo "${ECHO_T}auto-sleep-9" >&6
+ fi
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+echo "$as_me:$LINENO: checking CFLAGS frame-pointer" >&5
+echo $ECHO_N "checking CFLAGS frame-pointer... $ECHO_C" >&6
+# Check whether --enable-frame-pointer or --disable-frame-pointer was given.
+if test "${enable_frame_pointer+set}" = set; then
+ enableval="$enable_frame_pointer"
+
+fi;
+case ".$enable_frame_pointer" in
+ .|.no|.no,*) test ".$enable_frame_pointer" = "." && enable_frame_pointer="no"
+ CFLAGS=`echo " $CFLAGS " | sed -e 's/ -g / /'`
+ if test ".$GCC" = ".yes" ; then
+ CFLAGS="$CFLAGS -fomit-frame-pointer"
+ echo "$as_me:$LINENO: result: $enable_frame_pointer, -fomit-frame-pointer added" >&5
+echo "${ECHO_T}$enable_frame_pointer, -fomit-frame-pointer added" >&6
+ else
+ echo "$as_me:$LINENO: result: $enable_frame_pointer, -g removed" >&5
+echo "${ECHO_T}$enable_frame_pointer, -g removed" >&6
+ fi ;;
+ *) echo "$as_me:$LINENO: result: $enable_frame_pointer, kept" >&5
+echo "${ECHO_T}$enable_frame_pointer, kept" >&6 ;;
+esac
+
+echo "$as_me:$LINENO: checking CFLAGS for maximum warnings" >&5
+echo $ECHO_N "checking CFLAGS for maximum warnings... $ECHO_C" >&6
+if test "${ac_cv_cflags_warn_all+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_cflags_warn_all="no, unknown"
+
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ ac_save_CFLAGS="$CFLAGS"
+for ac_arg in "-pedantic % -Wall" "-xstrconst % -v" "-std1 % -verbose -w0 -warnprotos" "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" "-ansi -ansiE % -fullwarn" "+ESlit % +w1" "-Xc % -pvctl,fullmsg" "-h conform % -h msglevel 2" #
+do CFLAGS="$ac_save_CFLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_cflags_warn_all=`echo $ac_arg | sed -e 's,.*% *,,'` ; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+ CFLAGS="$ac_save_CFLAGS"
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cflags_warn_all" >&5
+echo "${ECHO_T}$ac_cv_cflags_warn_all" >&6
+case ".$ac_cv_cflags_warn_all" in
+ .ok|.ok,*) ;;
+ .|.no|.no,*)
+ ;;
+ *)
+ if echo " $CFLAGS " | grep " $ac_cv_cflags_warn_all " 2>&1 >/dev/null
+ then { (echo "$as_me:$LINENO: : CFLAGS does contain \$ac_cv_cflags_warn_all") >&5
+ (: CFLAGS does contain $ac_cv_cflags_warn_all) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ else { (echo "$as_me:$LINENO: : CFLAGS=\"\$CFLAGS \$ac_cv_cflags_warn_all\"") >&5
+ (: CFLAGS="$CFLAGS $ac_cv_cflags_warn_all") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ CFLAGS="$CFLAGS $ac_cv_cflags_warn_all"
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking CFLAGS making strings readonly" >&5
+echo $ECHO_N "checking CFLAGS making strings readonly... $ECHO_C" >&6
+if test "${ac_cv_cflags_no_writable_strings+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_cflags_no_writable_strings="no, unknown"
+
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ ac_save_CFLAGS="$CFLAGS"
+# IRIX C compiler:
+# -use_readonly_const is the default for IRIX C,
+# puts them into .rodata, but they are copied later.
+# need to be "-G0 -rdatashared" for strictmode but
+# I am not sure what effect that has really. - guidod
+for ac_arg in "-Wall % -fno-writable-strings -Wwrite-strings" "-v -Xc % -xstrconst" "+w1 -Aa % +ESlit" "-w0 -std1 % -readonly_strings" "-fullwarn -use_readonly_const %% ok, its the default" #
+do CFLAGS="$ac_save_CFLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_cflags_no_writable_strings=`echo $ac_arg | sed -e 's,.*% *,,'` ; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case ".$ac_cv_cflags_no_writable_strings" in
+ .|.no|.no,*) ;;
+ *) # sanity check - testing strcpy() from string.h
+ cp config.log config.tmp
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+int
+main ()
+{
+
+ char test[16];
+ if (strcpy (test, "test")) return 1;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ if test `diff config.log config.tmp | grep -i warning | wc -l` != 0
+ then ac_cv_cflags_no_writable_strings="no, suppressed, string.h," ; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_cflags_no_writable_strings="no, suppressed, string.h"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ rm config.tmp
+ ;;
+esac
+ CFLAGS="$ac_save_CFLAGS"
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cflags_no_writable_strings" >&5
+echo "${ECHO_T}$ac_cv_cflags_no_writable_strings" >&6
+case ".$ac_cv_cflags_no_writable_strings" in
+ .ok|.ok,*) ;;
+ .|.no|.no,*)
+ ;;
+ *)
+ if echo " $CFLAGS " | grep " $ac_cv_cflags_no_writable_strings " 2>&1 >/dev/null
+ then { (echo "$as_me:$LINENO: : CFLAGS does contain \$ac_cv_cflags_no_writable_strings") >&5
+ (: CFLAGS does contain $ac_cv_cflags_no_writable_strings) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ else { (echo "$as_me:$LINENO: : CFLAGS=\"\$CFLAGS \$ac_cv_cflags_no_writable_strings\"") >&5
+ (: CFLAGS="$CFLAGS $ac_cv_cflags_no_writable_strings") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ CFLAGS="$CFLAGS $ac_cv_cflags_no_writable_strings"
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking CFLAGS for strict prototypes" >&5
+echo $ECHO_N "checking CFLAGS for strict prototypes... $ECHO_C" >&6
+if test "${ac_cv_cflags_strict_prototypes+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_cflags_strict_prototypes="no, unknown"
+
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ ac_save_CFLAGS="$CFLAGS"
+for ac_arg in "-Wall % -fstrict-prototypes -Wstrict-prototypes" "-Wall % -Wstrict-prototypes" #
+do CFLAGS="$ac_save_CFLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_cflags_strict_prototypes=`echo $ac_arg | sed -e 's,.*% *,,'` ; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case ".$ac_cv_cflags_strict_prototypes" in
+ .|.no|.no,*) ;;
+ *) # sanity check with signal() from sys/signal.h
+ cp config.log config.tmp
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <signal.h>
+int
+main ()
+{
+
+ if (signal (SIGINT, SIG_IGN) == SIG_DFL) return 1;
+ if (signal (SIGINT, SIG_IGN) != SIG_DFL) return 2;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ if test `diff config.log config.tmp | grep -i warning | wc -l` != 0
+then if test `diff config.log config.tmp | grep -i warning | wc -l` != 1
+then ac_cv_cflags_strict_prototypes="no, suppressed, signal.h," ; fi ; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_cflags_strict_prototypes="no, suppressed, signal.h"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ rm config.tmp
+ ;;
+esac
+ CFLAGS="$ac_save_CFLAGS"
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cflags_strict_prototypes" >&5
+echo "${ECHO_T}$ac_cv_cflags_strict_prototypes" >&6
+case ".$ac_cv_cflags_strict_prototypes" in
+ .ok|.ok,*) ;;
+ .|.no|.no,*)
+ ;;
+ *)
+ if echo " $CFLAGS " | grep " $ac_cv_cflags_strict_prototypes " 2>&1 >/dev/null
+ then { (echo "$as_me:$LINENO: : CFLAGS does contain \$ac_cv_cflags_strict_prototypes") >&5
+ (: CFLAGS does contain $ac_cv_cflags_strict_prototypes) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ else { (echo "$as_me:$LINENO: : CFLAGS=\"\$CFLAGS \$ac_cv_cflags_strict_prototypes\"") >&5
+ (: CFLAGS="$CFLAGS $ac_cv_cflags_strict_prototypes") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ CFLAGS="$CFLAGS $ac_cv_cflags_strict_prototypes"
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking CFLAGS for gcc -Wpointer-arith" >&5
+echo $ECHO_N "checking CFLAGS for gcc -Wpointer-arith... $ECHO_C" >&6
+if test "${ac_cv_cflags_gcc_option__Wpointer_arith+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_cflags_gcc_option__Wpointer_arith="no, unknown"
+
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ ac_save_CFLAGS="$CFLAGS"
+for ac_arg in "-pedantic % -Wpointer-arith" #
+do CFLAGS="$ac_save_CFLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_cflags_gcc_option__Wpointer_arith=`echo $ac_arg | sed -e 's,.*% *,,'` ; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+ CFLAGS="$ac_save_CFLAGS"
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cflags_gcc_option__Wpointer_arith" >&5
+echo "${ECHO_T}$ac_cv_cflags_gcc_option__Wpointer_arith" >&6
+case ".$ac_cv_cflags_gcc_option__Wpointer_arith" in
+ .ok|.ok,*) ;;
+ .|.no|.no,*) ;;
+ *)
+ if echo " $CFLAGS " | grep " $ac_cv_cflags_gcc_option__Wpointer_arith " 2>&1 >/dev/null
+ then { (echo "$as_me:$LINENO: : CFLAGS does contain \$ac_cv_cflags_gcc_option__Wpointer_arith") >&5
+ (: CFLAGS does contain $ac_cv_cflags_gcc_option__Wpointer_arith) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ else { (echo "$as_me:$LINENO: : CFLAGS=\"\$CFLAGS \$ac_cv_cflags_gcc_option__Wpointer_arith\"") >&5
+ (: CFLAGS="$CFLAGS $ac_cv_cflags_gcc_option__Wpointer_arith") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ CFLAGS="$CFLAGS $ac_cv_cflags_gcc_option__Wpointer_arith"
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking CFLAGS for gcc -Wsign-compare" >&5
+echo $ECHO_N "checking CFLAGS for gcc -Wsign-compare... $ECHO_C" >&6
+if test "${ac_cv_cflags_gcc_option__Wsign_compare+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_cflags_gcc_option__Wsign_compare="no, unknown"
+
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ ac_save_CFLAGS="$CFLAGS"
+for ac_arg in "-pedantic % -Wsign-compare" #
+do CFLAGS="$ac_save_CFLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_cflags_gcc_option__Wsign_compare=`echo $ac_arg | sed -e 's,.*% *,,'` ; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+ CFLAGS="$ac_save_CFLAGS"
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cflags_gcc_option__Wsign_compare" >&5
+echo "${ECHO_T}$ac_cv_cflags_gcc_option__Wsign_compare" >&6
+case ".$ac_cv_cflags_gcc_option__Wsign_compare" in
+ .ok|.ok,*) ;;
+ .|.no|.no,*) ;;
+ *)
+ if echo " $CFLAGS " | grep " $ac_cv_cflags_gcc_option__Wsign_compare " 2>&1 >/dev/null
+ then { (echo "$as_me:$LINENO: : CFLAGS does contain \$ac_cv_cflags_gcc_option__Wsign_compare") >&5
+ (: CFLAGS does contain $ac_cv_cflags_gcc_option__Wsign_compare) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ else { (echo "$as_me:$LINENO: : CFLAGS=\"\$CFLAGS \$ac_cv_cflags_gcc_option__Wsign_compare\"") >&5
+ (: CFLAGS="$CFLAGS $ac_cv_cflags_gcc_option__Wsign_compare") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ CFLAGS="$CFLAGS $ac_cv_cflags_gcc_option__Wsign_compare"
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking CFLAGS for gcc -Wmissing-declarations" >&5
+echo $ECHO_N "checking CFLAGS for gcc -Wmissing-declarations... $ECHO_C" >&6
+if test "${ac_cv_cflags_gcc_option__Wmissing_declarations+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_cflags_gcc_option__Wmissing_declarations="no, unknown"
+
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ ac_save_CFLAGS="$CFLAGS"
+for ac_arg in "-pedantic % -Wmissing-declarations" #
+do CFLAGS="$ac_save_CFLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_cflags_gcc_option__Wmissing_declarations=`echo $ac_arg | sed -e 's,.*% *,,'` ; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+ CFLAGS="$ac_save_CFLAGS"
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cflags_gcc_option__Wmissing_declarations" >&5
+echo "${ECHO_T}$ac_cv_cflags_gcc_option__Wmissing_declarations" >&6
+case ".$ac_cv_cflags_gcc_option__Wmissing_declarations" in
+ .ok|.ok,*) ;;
+ .|.no|.no,*) ;;
+ *)
+ if echo " $CFLAGS " | grep " $ac_cv_cflags_gcc_option__Wmissing_declarations " 2>&1 >/dev/null
+ then { (echo "$as_me:$LINENO: : CFLAGS does contain \$ac_cv_cflags_gcc_option__Wmissing_declarations") >&5
+ (: CFLAGS does contain $ac_cv_cflags_gcc_option__Wmissing_declarations) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ else { (echo "$as_me:$LINENO: : CFLAGS=\"\$CFLAGS \$ac_cv_cflags_gcc_option__Wmissing_declarations\"") >&5
+ (: CFLAGS="$CFLAGS $ac_cv_cflags_gcc_option__Wmissing_declarations") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ CFLAGS="$CFLAGS $ac_cv_cflags_gcc_option__Wmissing_declarations"
+ fi
+ ;;
+esac
+
+# ---------------------------------------------------------------
+ # The prefix default can be set in configure.ac (otherwise it is /usr/local)
+ test "x$prefix" = xNONE && prefix=$ac_default_prefix
+ # Let make expand exec_prefix. Allows to override the makevar 'prefix' later
+ test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Check whether --enable-enable-default-pkgconfigdir or --disable-enable-default-pkgconfigdir was given.
+if test "${enable_enable_default_pkgconfigdir+set}" = set; then
+ enableval="$enable_enable_default_pkgconfigdir"
+
+fi;
+test ".$enable_default_pkgconfigdir" = "." && enable_default_pkgconfigdir="no"
+case ".$enable_default_pkgconfigdir" in
+ .no) ax_warning_default_pkgconfig_def='${libdir}/pkgconfig' ;;
+ .yes) # autodetect
+ if test ".$PKG_CONFIG" = "." ; then # we use the same default as in pkg.m4
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_PKG_CONFIG+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
+ ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+
+if test -n "$PKG_CONFIG"; then
+ echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5
+echo "${ECHO_T}$PKG_CONFIG" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ fi
+ if test "$PKG_CONFIG" = "no"
+ then ax_warning_default_pkgconfig_def="/tmp" ; test -d "/usr/lib/pkgconfig" && ax_warning_default_pkgconfig_def="/usr/lib/pkgconfig"
+ else ax_warning_default_pkgconfig_bin=`(dirname "$ax_warning_default_pkgconfig_def") 2>/dev/null ||
+$as_expr X"$ax_warning_default_pkgconfig_def" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ax_warning_default_pkgconfig_def" : 'X\(//\)[^/]' \| \
+ X"$ax_warning_default_pkgconfig_def" : 'X\(//\)$' \| \
+ X"$ax_warning_default_pkgconfig_def" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ax_warning_default_pkgconfig_def" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'` ;
+ if test -d "$ax_warning_default_pkgconfig_bin/lib/pkgconfig" ; then
+ ax_warning_default_pkgconfig_def="$ax_warning_default_pkgconfig_bin/lib/pkgconfig"
+ else ax_warning_default_pkgconfig_bin=`(dirname "$ax_warning_default_pkgconfig_def") 2>/dev/null ||
+$as_expr X"$ax_warning_default_pkgconfig_def" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ax_warning_default_pkgconfig_def" : 'X\(//\)[^/]' \| \
+ X"$ax_warning_default_pkgconfig_def" : 'X\(//\)$' \| \
+ X"$ax_warning_default_pkgconfig_def" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ax_warning_default_pkgconfig_def" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ if test -d "$ax_warning_default_pkgconfig_bin/lib/pkgconfig" ; then
+ ax_warning_default_pkgconfig_def="$ax_warning_default_pkgconfig_bin/lib/pkgconfig"
+ else
+ if test -d "/usr/lib/pkgconfig" ; then
+ ax_warning_default_pkgconfig_def="/usr/lib/pkgconfig"
+ else
+ ax_warning_default_pkgconfig_def="/tmp"
+ fi fi fi
+ fi ;;
+ *) ax_warning_default_pkgconfig_def="$enable_default_pkgconfigdir" ;;
+esac
+ax_warning_default_pkgconfig_loc='$ax_warning_default_pkgconfig_def'
+
+ if test ".$PKG_CONFIG" = "." ; then # we use the same default as in pkg.m4
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_PKG_CONFIG+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
+ ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+
+if test -n "$PKG_CONFIG"; then
+ echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5
+echo "${ECHO_T}$PKG_CONFIG" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ fi
+ if test "$PKG_CONFIG" = "no"
+ then ax_warning_default_pkgconfig_dir="/" ; test -d "/usr/lib/pkgconfig" && ax_warning_default_pkgconfig_dir="/usr/lib/pkgconfig"
+ else ax_warning_default_pkgconfig_bin=`(dirname "$ax_warning_default_pkgconfig_dir") 2>/dev/null ||
+$as_expr X"$ax_warning_default_pkgconfig_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ax_warning_default_pkgconfig_dir" : 'X\(//\)[^/]' \| \
+ X"$ax_warning_default_pkgconfig_dir" : 'X\(//\)$' \| \
+ X"$ax_warning_default_pkgconfig_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ax_warning_default_pkgconfig_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'` ;
+ if test -d "$ax_warning_default_pkgconfig_bin/lib/pkgconfig" ; then
+ ax_warning_default_pkgconfig_dir="$ax_warning_default_pkgconfig_bin/lib/pkgconfig"
+ else ax_warning_default_pkgconfig_bin=`(dirname "$ax_warning_default_pkgconfig_dir") 2>/dev/null ||
+$as_expr X"$ax_warning_default_pkgconfig_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ax_warning_default_pkgconfig_dir" : 'X\(//\)[^/]' \| \
+ X"$ax_warning_default_pkgconfig_dir" : 'X\(//\)$' \| \
+ X"$ax_warning_default_pkgconfig_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ax_warning_default_pkgconfig_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ if test -d "$ax_warning_default_pkgconfig_bin/lib/pkgconfig" ; then
+ ax_warning_default_pkgconfig_dir="$ax_warning_default_pkgconfig_bin/lib/pkgconfig"
+ else
+ if test -d "/usr/lib/pkgconfig" ; then
+ ax_warning_default_pkgconfig_dir="/usr/lib/pkgconfig"
+ else
+ ax_warning_default_pkgconfig_dir="/"
+ fi fi fi
+ fi
+{ (echo "$as_me:$LINENO: : last pkgconfig dir is assumed as \"\$ax_warning_default_pkgconfig_dir\"") >&5
+ (: last pkgconfig dir is assumed as "$ax_warning_default_pkgconfig_dir") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ax_warning_default_pkgconfig_dir=`eval "echo $ax_warning_default_pkgconfig_dir"`
+ax_warning_default_pkgconfig_dir=`eval "echo $ax_warning_default_pkgconfig_dir"`
+ax_warning_default_pkgconfig_loc=`eval "echo $ax_warning_default_pkgconfig_loc"`
+ax_warning_default_pkgconfig_loc=`eval "echo $ax_warning_default_pkgconfig_loc"`
+ax_warning_default_pkgconfig_loc=`eval "echo $ax_warning_default_pkgconfig_loc"`
+ax_warning_default_pkgconfig_loc=`eval "echo $ax_warning_default_pkgconfig_loc"`
+for ax_warning_default_pkgconfig_dir in `echo "$PKG_CONFIG_PATH:$ax_warning_default_pkgconfig_dir" | sed -e 's,:, ,g'` ; do
+ { (echo "$as_me:$LINENO: : test \".\$ax_warning_default_pkgconfig_loc\" = \".\$ax_warning_default_pkgconfig_dir\"") >&5
+ (: test ".$ax_warning_default_pkgconfig_loc" = ".$ax_warning_default_pkgconfig_dir") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ test ".$ax_warning_default_pkgconfig_loc" = ".$ax_warning_default_pkgconfig_dir" && break
+done
+if test "$ax_warning_default_pkgconfig_loc" != "$ax_warning_default_pkgconfig_dir" ; then
+ { echo "$as_me:$LINENO: warning: pkgconfigdir=$ax_warning_default_pkgconfig_loc (see config.log)" >&5
+echo "$as_me: warning: pkgconfigdir=$ax_warning_default_pkgconfig_loc (see config.log)" >&6;}
+ { echo "$as_me:$LINENO: perhaps: make install pkgconfigdir=$ax_warning_default_pkgconfig_dir" >&5
+echo "$as_me: perhaps: make install pkgconfigdir=$ax_warning_default_pkgconfig_dir" >&6;}
+ cat >&5 <<EOF
+ pkgconfigdir: the default pkgconfigdir of $ax_warning_default_pkgconfig_loc
+ pkgconfigdir: is not listed in the dirlist where pkg-config will look for
+ pkgconfigdir: package-configs - you can override the install-path using
+ pkgconfigdir: make install pkgconfigdir=$ax_warning_default_pkgconfig_dir
+ pkgconfigdir: or set/append the directory to the environment variable
+ pkgconfigdir: PKG_CONFIG_PATH="$ax_warning_default_pkgconfig_loc"
+EOF
+ fi
+
+pkgconfigdir="$ax_warning_default_pkgconfig_dir"
+
+
+# Check whether --enable-enable-default-aclocaldir or --disable-enable-default-aclocaldir was given.
+if test "${enable_enable_default_aclocaldir+set}" = set; then
+ enableval="$enable_enable_default_aclocaldir"
+
+fi;
+test ".$enable_default_aclocaldir" = "." && enable_default_aclocaldir="no"
+case ".$enable_default_aclocaldir" in
+ .no) ax_warning_default_aclocal_def='${datadir}/aclocal' ;;
+ .yes) # autodetect
+ if test ".$ACLOCAL" = "." ; then
+ # Extract the first word of "aclocal", so it can be a program name with args.
+set dummy aclocal; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_ACLOCAL+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $ACLOCAL in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ACLOCAL="$ACLOCAL" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_ACLOCAL="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_path_ACLOCAL" && ac_cv_path_ACLOCAL=":"
+ ;;
+esac
+fi
+ACLOCAL=$ac_cv_path_ACLOCAL
+
+if test -n "$ACLOCAL"; then
+ echo "$as_me:$LINENO: result: $ACLOCAL" >&5
+echo "${ECHO_T}$ACLOCAL" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ fi
+ ax_warning_default_aclocal_bin="$ACLOCAL"
+ test ".$ax_warning_default_aclocal_bin" = "." && ax_warning_default_aclocal_bin="aclocal"
+ ax_warning_default_aclocal_def=`test ".$SHELL" = "." && SHELL="'sh'" ; eval "$ax_warning_default_aclocal_bin --print-ac-dir"`
+ test ".$ax_warning_default_aclocal_def" = "." && test -d "/usr/share/aclocal" && ax_warning_default_aclocal_def="/usr/share/aclocal"
+ test ".$ax_warning_default_aclocal_def" = "." && ax_warning_default_aclocal_def="/tmp" ;;
+ *) ax_warning_default_aclocal_def="$enable_default_aclocaldir" ;;
+esac
+ax_warning_default_aclocal_loc='$ax_warning_default_aclocal_def'
+
+ if test ".$ACLOCAL" = "." ; then
+ # Extract the first word of "aclocal", so it can be a program name with args.
+set dummy aclocal; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_ACLOCAL+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $ACLOCAL in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ACLOCAL="$ACLOCAL" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_ACLOCAL="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_path_ACLOCAL" && ac_cv_path_ACLOCAL=":"
+ ;;
+esac
+fi
+ACLOCAL=$ac_cv_path_ACLOCAL
+
+if test -n "$ACLOCAL"; then
+ echo "$as_me:$LINENO: result: $ACLOCAL" >&5
+echo "${ECHO_T}$ACLOCAL" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ fi
+ ax_warning_default_aclocal_bin="$ACLOCAL"
+ test ".$ax_warning_default_aclocal_bin" = "." && ax_warning_default_aclocal_bin="aclocal"
+ ax_warning_default_aclocal_dir=`test ".$SHELL" = "." && SHELL="'sh'" ; eval "$ax_warning_default_aclocal_bin --print-ac-dir"`
+ test ".$ax_warning_default_aclocal_dir" = "." && test -d "/usr/share/aclocal" && ax_warning_default_aclocal_dir="/usr/share/aclocal"
+ test ".$ax_warning_default_aclocal_dir" = "." && ax_warning_default_aclocal_dir="/tmp"
+ax_warning_default_aclocal_dir=`eval "echo $ax_warning_default_aclocal_dir"` # we need to expand
+ax_warning_default_aclocal_dir=`eval "echo $ax_warning_default_aclocal_dir"`
+ax_warning_default_aclocal_loc=`eval "echo $ax_warning_default_aclocal_loc"`
+ax_warning_default_aclocal_loc=`eval "echo $ax_warning_default_aclocal_loc"`
+ax_warning_default_aclocal_loc=`eval "echo $ax_warning_default_aclocal_loc"`
+ax_warning_default_aclocal_loc=`eval "echo $ax_warning_default_aclocal_loc"`
+{ (echo "$as_me:$LINENO: : test \"\$ax_warning_default_aclocal_loc\" = \"\$ax_warning_default_aclocal_dir\"") >&5
+ (: test "$ax_warning_default_aclocal_loc" = "$ax_warning_default_aclocal_dir") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+if test "$ax_warning_default_aclocal_loc" != "$ax_warning_default_aclocal_dir" ; then
+ if test -f "$ax_warning_default_aclocal_dir/dirlist" ; then
+ for ax_warning_default_aclocal_dir in `cat $ax_warning_default_aclocal_dir/dirlist` $ax_warning_default_aclocal_dir ; do
+ { (echo "$as_me:$LINENO: : test \"\$ax_warning_default_aclocal_loc\" = \"\$ax_warning_default_aclocal_dir\"") >&5
+ (: test "$ax_warning_default_aclocal_loc" = "$ax_warning_default_aclocal_dir") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ test "$ax_warning_default_aclocal_loc" = "$ax_warning_default_aclocal_dir" && break
+ done
+ fi
+ if test "$ax_warning_default_aclocal_loc" != "$ax_warning_default_aclocal_dir" ; then
+ { echo "$as_me:$LINENO: warning: aclocaldir=$ax_warning_default_aclocal_loc (see config.log)" >&5
+echo "$as_me: warning: aclocaldir=$ax_warning_default_aclocal_loc (see config.log)" >&6;}
+ { echo "$as_me:$LINENO: perhaps: make install aclocaldir=$ax_warning_default_aclocal_dir" >&5
+echo "$as_me: perhaps: make install aclocaldir=$ax_warning_default_aclocal_dir" >&6;}
+ cat >&5 <<EOF
+ aclocaldir: the default aclocaldir of $ax_warning_default_aclocal_loc
+ aclocaldir: is not listed in the dirlist where aclocal will look
+ aclocaldir: for macros - you can override the install-path using
+ aclocaldir: make install aclocaldir=$ax_warning_default_aclocal_dir
+ aclocaldir: or append the directory to aclocal reconfigures later as
+ aclocaldir: aclocal -I $ax_warning_default_aclocal_loc
+ aclocaldir: when an autoconf macro is needed from that directory
+EOF
+ fi
+fi
+
+aclocaldir="$ax_warning_default_aclocal_dir"
+
+
+
+ ac_config_files="$ac_config_files Makefile zzip/Makefile zzipwrap/Makefile SDL/Makefile docs/Makefile test/Makefile bins/Makefile"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+ (set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+} |
+ sed '
+ t clear
+ : clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+ if test -w $cache_file; then
+ test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+ cat confcache >$cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_i=`echo "$ac_i" |
+ sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+ # 2. Add them.
+ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling. Logging --version etc. is OK.
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+ echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+ echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+ echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+ echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "x$1" : 'x\([^=]*\)='`
+ ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ -*)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ *) # This is not an option, so the user has probably given explicit
+ # arguments.
+ ac_option=$1
+ ac_need_defaults=false;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --vers* | -V )
+ echo "$ac_cs_version"; exit 0 ;;
+ --he | --h)
+ # Conflict between --help and --header
+ { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1" ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS section.
+#
+
+ax_enable_builddir_srcdir="$srcdir" # $srcdir
+ax_enable_builddir_host="$HOST" # $HOST / $host
+ax_enable_builddir_version="$VERSION" # $VERSION
+ax_enable_builddir_package="$PACKAGE" # $PACKAGE
+ax_enable_builddir_sed="$ax_enable_builddir_sed" # $SED
+ax_enable_builddir="$ax_enable_builddir" # $SUB
+
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+PACKAGE="$PACKAGE"
+PACKAGE="$PACKAGE"
+
+ax_create_pkgconfig_generate="$ax_create_pkgconfig_generate"
+pkgconfig_prefix='$prefix'
+pkgconfig_execprefix='$exec_prefix'
+pkgconfig_bindir='$bindir'
+pkgconfig_libdir='$libdir'
+pkgconfig_includedir='$includedir'
+pkgconfig_datadir='$datadir'
+pkgconfig_sysconfdir='$sysconfdir'
+pkgconfig_suffix='$ax_create_pkgconfig_suffix'
+pkgconfig_package='$PACKAGE_NAME'
+pkgconfig_libname='$ax_create_pkgconfig_libname'
+pkgconfig_description='$ax_create_pkgconfig_description'
+pkgconfig_version='$ax_create_pkgconfig_version'
+pkgconfig_requires='$ax_create_pkgconfig_requires'
+pkgconfig_libs='$ax_create_pkgconfig_libs'
+pkgconfig_ldflags='$ax_create_pkgconfig_ldflags'
+pkgconfig_cppflags='$ax_create_pkgconfig_cppflags'
+pkgconfig_src_libdir='$ax_create_pkgconfig_src_libdir'
+pkgconfig_src_headers='$ax_create_pkgconfig_src_headers'
+
+
+_ACEOF
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+ case "$ac_config_target" in
+ # Handling of arguments.
+ "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "zzip/Makefile" ) CONFIG_FILES="$CONFIG_FILES zzip/Makefile" ;;
+ "zzipwrap/Makefile" ) CONFIG_FILES="$CONFIG_FILES zzipwrap/Makefile" ;;
+ "SDL/Makefile" ) CONFIG_FILES="$CONFIG_FILES SDL/Makefile" ;;
+ "docs/Makefile" ) CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;;
+ "test/Makefile" ) CONFIG_FILES="$CONFIG_FILES test/Makefile" ;;
+ "bins/Makefile" ) CONFIG_FILES="$CONFIG_FILES bins/Makefile" ;;
+ "buildir" ) CONFIG_COMMANDS="$CONFIG_COMMANDS buildir" ;;
+ "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "zzip/_config.h" ) CONFIG_COMMANDS="$CONFIG_COMMANDS zzip/_config.h" ;;
+ "zzip/_msvc.h" ) CONFIG_COMMANDS="$CONFIG_COMMANDS zzip/_msvc.h" ;;
+ "$ax_create_pkgconfig_generate" ) CONFIG_COMMANDS="$CONFIG_COMMANDS $ax_create_pkgconfig_generate" ;;
+ "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./confstat$$-$RANDOM
+ (umask 077 && mkdir $tmp)
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+ # Protect against being on the right side of a sed subst in config.status.
+ sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+ s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@build@,$build,;t t
+s,@build_cpu@,$build_cpu,;t t
+s,@build_vendor@,$build_vendor,;t t
+s,@build_os@,$build_os,;t t
+s,@host@,$host,;t t
+s,@host_cpu@,$host_cpu,;t t
+s,@host_vendor@,$host_vendor,;t t
+s,@host_os@,$host_os,;t t
+s,@target@,$target,;t t
+s,@target_cpu@,$target_cpu,;t t
+s,@target_vendor@,$target_vendor,;t t
+s,@target_os@,$target_os,;t t
+s,@ax_enable_builddir_sed@,$ax_enable_builddir_sed,;t t
+s,@THREAD_SAFE@,$THREAD_SAFE,;t t
+s,@ZLIB_INCL@,$ZLIB_INCL,;t t
+s,@ZLIB_LDIR@,$ZLIB_LDIR,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@CYGPATH_W@,$CYGPATH_W,;t t
+s,@PACKAGE@,$PACKAGE,;t t
+s,@VERSION@,$VERSION,;t t
+s,@ACLOCAL@,$ACLOCAL,;t t
+s,@AUTOCONF@,$AUTOCONF,;t t
+s,@AUTOMAKE@,$AUTOMAKE,;t t
+s,@AUTOHEADER@,$AUTOHEADER,;t t
+s,@MAKEINFO@,$MAKEINFO,;t t
+s,@install_sh@,$install_sh,;t t
+s,@STRIP@,$STRIP,;t t
+s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t
+s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t
+s,@mkdir_p@,$mkdir_p,;t t
+s,@AWK@,$AWK,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@am__leading_dot@,$am__leading_dot,;t t
+s,@AMTAR@,$AMTAR,;t t
+s,@am__tar@,$am__tar,;t t
+s,@am__untar@,$am__untar,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@DEPDIR@,$DEPDIR,;t t
+s,@am__include@,$am__include,;t t
+s,@am__quote@,$am__quote,;t t
+s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t
+s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t
+s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t
+s,@CCDEPMODE@,$CCDEPMODE,;t t
+s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t
+s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t
+s,@EGREP@,$EGREP,;t t
+s,@LN_S@,$LN_S,;t t
+s,@ECHO@,$ECHO,;t t
+s,@AR@,$AR,;t t
+s,@ac_ct_AR@,$ac_ct_AR,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@DLLTOOL@,$DLLTOOL,;t t
+s,@ac_ct_DLLTOOL@,$ac_ct_DLLTOOL,;t t
+s,@AS@,$AS,;t t
+s,@ac_ct_AS@,$ac_ct_AS,;t t
+s,@OBJDUMP@,$OBJDUMP,;t t
+s,@ac_ct_OBJDUMP@,$ac_ct_OBJDUMP,;t t
+s,@CPP@,$CPP,;t t
+s,@CXX@,$CXX,;t t
+s,@CXXFLAGS@,$CXXFLAGS,;t t
+s,@ac_ct_CXX@,$ac_ct_CXX,;t t
+s,@CXXDEPMODE@,$CXXDEPMODE,;t t
+s,@am__fastdepCXX_TRUE@,$am__fastdepCXX_TRUE,;t t
+s,@am__fastdepCXX_FALSE@,$am__fastdepCXX_FALSE,;t t
+s,@CXXCPP@,$CXXCPP,;t t
+s,@F77@,$F77,;t t
+s,@FFLAGS@,$FFLAGS,;t t
+s,@ac_ct_F77@,$ac_ct_F77,;t t
+s,@LIBTOOL@,$LIBTOOL,;t t
+s,@RELEASE_INFO@,$RELEASE_INFO,;t t
+s,@VERSION_INFO@,$VERSION_INFO,;t t
+s,@MAINTAINER_MODE_TRUE@,$MAINTAINER_MODE_TRUE,;t t
+s,@MAINTAINER_MODE_FALSE@,$MAINTAINER_MODE_FALSE,;t t
+s,@MAINT@,$MAINT,;t t
+s,@pkgconfig_libdir@,$pkgconfig_libdir,;t t
+s,@pkgconfig_libfile@,$pkgconfig_libfile,;t t
+s,@PERL@,$PERL,;t t
+s,@PYTHON@,$PYTHON,;t t
+s,@MKZIP@,$MKZIP,;t t
+s,@XMLTO@,$XMLTO,;t t
+s,@LARGEFILE_CFLAGS@,$LARGEFILE_CFLAGS,;t t
+s,@ZLIB_VERSION@,$ZLIB_VERSION,;t t
+s,@docdir@,$docdir,;t t
+s,@SDL@,$SDL,;t t
+s,@ZIPTESTS@,$ZIPTESTS,;t t
+s,@ZZIPLIB_LDFLAGS@,$ZZIPLIB_LDFLAGS,;t t
+s,@RESOLVES@,$RESOLVES,;t t
+s,@PKG_CONFIG@,$PKG_CONFIG,;t t
+s,@pkgconfigdir@,$pkgconfigdir,;t t
+s,@aclocaldir@,$aclocaldir,;t t
+s,@CONFIG_FILES@,$CONFIG_FILES,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+ cat >>$CONFIG_STATUS <<\_ACEOF
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+ ac_max_sed_lines=48
+ ac_sed_frag=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_lines # Line after last line for current file.
+ ac_more_lines=:
+ ac_sed_cmds=
+ while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ else
+ sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ fi
+ if test ! -s $tmp/subs.frag; then
+ ac_more_lines=false
+ else
+ # The purpose of the label and of the branching condition is to
+ # speed up the sed processing (if there are no `@' at all, there
+ # is no need to browse any of the substitutions).
+ # These are the two extra sed commands mentioned above.
+ (echo ':t
+ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+ fi
+ ac_sed_frag=`expr $ac_sed_frag + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_lines`
+ fi
+ done
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+ fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+ esac
+
+ if test x"$ac_file" != x-; then
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ rm -f "$ac_file"
+ fi
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ configure_input=
+ else
+ configure_input="$ac_file. "
+ fi
+ configure_input=$configure_input"Generated from `echo $ac_file_in |
+ sed 's,.*/,,'` by configure."
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+ rm -f $tmp/stdin
+ if test x"$ac_file" != x-; then
+ mv $tmp/out $ac_file
+ else
+ cat $tmp/out
+ rm -f $tmp/out
+ fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='[ ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ # Do quote $f, to prevent DOS paths from being IFS'd.
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+ # Remove the trailing spaces.
+ sed 's/[ ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h. The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status. Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless. Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo ' :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+ # Write a limited-size here document to $tmp/defines.sed.
+ echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#define' lines.
+ echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/defines.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo ' fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+ # Write a limited-size here document to $tmp/undefs.sed.
+ echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#undef'
+ echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+ rm -f conftest.undefs
+ mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ echo "/* Generated by configure. */" >$tmp/config.h
+ else
+ echo "/* $ac_file. Generated by configure. */" >$tmp/config.h
+ fi
+ cat $tmp/in >>$tmp/config.h
+ rm -f $tmp/in
+ if test x"$ac_file" != x-; then
+ if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ rm -f $ac_file
+ mv $tmp/config.h $ac_file
+ fi
+ else
+ cat $tmp/config.h
+ rm -f $tmp/config.h
+ fi
+# Compute $ac_file's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $ac_file | $ac_file:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null ||
+$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X$ac_file : 'X\(//\)[^/]' \| \
+ X$ac_file : 'X\(//\)$' \| \
+ X$ac_file : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X$ac_file |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`/stamp-h$_am_stamp_count
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_COMMANDS section.
+#
+for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
+ ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+ ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
+$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_dest" : 'X\(//\)[^/]' \| \
+ X"$ac_dest" : 'X\(//\)$' \| \
+ X"$ac_dest" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_dest" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+
+ { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
+echo "$as_me: executing $ac_dest commands" >&6;}
+ case $ac_dest in
+ buildir ) ac_top_srcdir="$ax_enable_builddir_srcdir"
+ if test ".$ax_enable_builddir" = "." ; then
+ if test -f "$top_srcdir/Makefile" ; then
+ { echo "$as_me:$LINENO: skipping top_srcdir/Makefile - left untouched" >&5
+echo "$as_me: skipping top_srcdir/Makefile - left untouched" >&6;}
+ else
+ { echo "$as_me:$LINENO: skipping top_srcdir/Makefile - not created" >&5
+echo "$as_me: skipping top_srcdir/Makefile - not created" >&6;}
+ fi
+ else
+ { echo "$as_me:$LINENO: create top_srcdir/Makefile guessed from local Makefile" >&5
+echo "$as_me: create top_srcdir/Makefile guessed from local Makefile" >&6;}
+ x='`' ; cat >$tmp/conftemp.sed <<_EOF
+/^\$/n
+x
+/^\$/bS
+x
+/\\\\\$/{H;d;}
+{H;s/.*//;x;}
+bM
+:S
+x
+/\\\\\$/{h;d;}
+{h;s/.*//;x;}
+:M
+s/\\(\\n\\) /\\1 /g
+/^ /d
+/^[ ]*[\\#]/d
+/^VPATH *=/d
+s/^srcdir *=.*/srcdir = ./
+s/^top_srcdir *=.*/top_srcdir = ./
+/[:=]/!d
+/^\\./d
+s/:.*/:/
+/:\$/s/ / /g
+/:\$/s/ / /g
+/^.*[=]/!s%\$% ; (cd \$(BUILD) \\&\\& \$(ISNOTSRCDIR) \\&\\& \$(MAKE) "\$\@") || exit ; \$(MAKE) done "RULE=\$\@"%
+_EOF
+ test ".$USE_MAINTAINER_MODE" = ".no" || \
+ cp "$tmp/conftemp.sed" "$ac_top_srcdir/makefile.sed~" ## DEBUGGING
+ echo 'BUILD=`uname -msr | tr " /" "__"`.d' >$ac_top_srcdir/Makefile
+ echo 'ISNOTSRCDIR=test ! -f configure' >>$ac_top_srcdir/Makefile
+ $ax_enable_builddir_sed -f $tmp/conftemp.sed Makefile >>$ac_top_srcdir/Makefile
+ echo 'done: ;@ if grep "$(RULE)-done .*:" Makefile > /dev/null; then echo $(MAKE) $(RULE)-done ; $(MAKE) $(RULE)-done ; else true ; fi' >> $ac_top_srcdir/Makefile
+ if test -f "$ac_top_srcdir/Makefile.mk" ; then
+ { echo "$as_me:$LINENO: extend top_srcdir/Makefile with top_srcdir/Makefile.mk" >&5
+echo "$as_me: extend top_srcdir/Makefile with top_srcdir/Makefile.mk" >&6;}
+ cat $ac_top_srcdir/Makefile.mk >>$ac_top_srcdir/Makefile
+ fi
+ { echo "$as_me:$LINENO: make uses BUILD=$ax_enable_builddir (on $ax_enable_builddir_host:)" >&5
+echo "$as_me: make uses BUILD=$ax_enable_builddir (on $ax_enable_builddir_host:)" >&6;}
+ fi
+ ;;
+ depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # So let's grep whole file.
+ if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
+ dirpart=`(dirname "$mf") 2>/dev/null ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`(dirname "$file") 2>/dev/null ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p $dirpart/$fdir
+ else
+ as_dir=$dirpart/$fdir
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5
+echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+ ;;
+ zzip/_config.h ) ac_prefix_conf_OUT=`echo zzip/_config.h`
+ac_prefix_conf_DEF=`echo _$ac_prefix_conf_OUT | sed -e "y:abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:" -e "s/[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g"`
+ac_prefix_conf_PKG=`echo zzip`
+ac_prefix_conf_LOW=`echo _$ac_prefix_conf_PKG | sed -e "y:ABCDEFGHIJKLMNOPQRSTUVWXYZ-:abcdefghijklmnopqrstuvwxyz_:"`
+ac_prefix_conf_UPP=`echo $ac_prefix_conf_PKG | sed -e "y:abcdefghijklmnopqrstuvwxyz-:ABCDEFGHIJKLMNOPQRSTUVWXYZ_:" -e "/^[0123456789]/s/^/_/"`
+ac_prefix_conf_INP=`echo "config.h" | sed -e 's/ *//'`
+if test ".$ac_prefix_conf_INP" = "."; then
+ for ac_file in : $CONFIG_HEADERS; do test "_$ac_file" = _: && continue
+ case "$ac_file" in
+ *.h) ac_prefix_conf_INP=$ac_file ;;
+ *)
+ esac
+ test ".$ac_prefix_conf_INP" != "." && break
+ done
+fi
+if test ".$ac_prefix_conf_INP" = "."; then
+ case "$ac_prefix_conf_OUT" in
+ */*) ac_prefix_conf_INP=`basename "$ac_prefix_conf_OUT"`
+ ;;
+ *-*) ac_prefix_conf_INP=`echo "$ac_prefix_conf_OUT" | sed -e "s/[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*-//"`
+ ;;
+ *) ac_prefix_conf_INP=config.h
+ ;;
+ esac
+fi
+if test -z "$ac_prefix_conf_PKG" ; then
+ { { echo "$as_me:$LINENO: error: no prefix for _PREFIX_PKG_CONFIG_H" >&5
+echo "$as_me: error: no prefix for _PREFIX_PKG_CONFIG_H" >&2;}
+ { (exit 1); exit 1; }; }
+else
+ if test ! -f "$ac_prefix_conf_INP" ; then if test -f "$srcdir/$ac_prefix_conf_INP" ; then
+ ac_prefix_conf_INP="$srcdir/$ac_prefix_conf_INP"
+ fi fi
+ { echo "$as_me:$LINENO: creating $ac_prefix_conf_OUT - prefix $ac_prefix_conf_UPP for $ac_prefix_conf_INP defines" >&5
+echo "$as_me: creating $ac_prefix_conf_OUT - prefix $ac_prefix_conf_UPP for $ac_prefix_conf_INP defines" >&6;}
+ if test -f $ac_prefix_conf_INP ; then
+ echo "s/#undef *\\([ABCDEFGHIJKLMNOPQRSTUVWXYZ_]\\)/#undef $ac_prefix_conf_UPP""_\\1/" > conftest.prefix
+ echo "s/#undef *\\([abcdefghijklmnopqrstuvwxyz]\\)/#undef $ac_prefix_conf_LOW""_\\1/" >> conftest.prefix
+ echo "s/#define *\\([ABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*\\)\\(.*\\)/#ifndef $ac_prefix_conf_UPP""_\\1 \\" >> conftest.prefix
+ echo "#define $ac_prefix_conf_UPP""_\\1 \\2 \\" >> conftest.prefix
+ echo "#endif/" >>conftest.prefix
+ echo "s/#define *\\([abcdefghijklmnopqrstuvwxyz][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*\\)\\(.*\\)/#ifndef $ac_prefix_conf_LOW""_\\1 \\" >> conftest.prefix
+ echo "#define $ac_prefix_conf_LOW""_\\1 \\2 \\" >> conftest.prefix
+ echo "#endif/" >> conftest.prefix
+ # now executing _script on _DEF input to create _OUT output file
+ echo "#ifndef $ac_prefix_conf_DEF" >$tmp/pconfig.h
+ echo "#define $ac_prefix_conf_DEF 1" >>$tmp/pconfig.h
+ echo ' ' >>$tmp/pconfig.h
+ echo /'*' $ac_prefix_conf_OUT. Generated automatically at end of configure. '*'/ >>$tmp/pconfig.h
+
+ sed -f conftest.prefix $ac_prefix_conf_INP >>$tmp/pconfig.h
+ echo ' ' >>$tmp/pconfig.h
+ echo '/* once:' $ac_prefix_conf_DEF '*/' >>$tmp/pconfig.h
+ echo "#endif" >>$tmp/pconfig.h
+ if cmp -s $ac_prefix_conf_OUT $tmp/pconfig.h 2>/dev/null; then
+ { echo "$as_me:$LINENO: $ac_prefix_conf_OUT is unchanged" >&5
+echo "$as_me: $ac_prefix_conf_OUT is unchanged" >&6;}
+ else
+ ac_dir=`(dirname "$ac_prefix_conf_OUT") 2>/dev/null ||
+$as_expr X"$ac_prefix_conf_OUT" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_prefix_conf_OUT" : 'X\(//\)[^/]' \| \
+ X"$ac_prefix_conf_OUT" : 'X\(//\)$' \| \
+ X"$ac_prefix_conf_OUT" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_prefix_conf_OUT" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ rm -f "$ac_prefix_conf_OUT"
+ mv $tmp/pconfig.h "$ac_prefix_conf_OUT"
+ fi
+ cp conftest.prefix _configs.sed
+ else
+ { { echo "$as_me:$LINENO: error: input file $ac_prefix_conf_INP does not exist - skip generating $ac_prefix_conf_OUT" >&5
+echo "$as_me: error: input file $ac_prefix_conf_INP does not exist - skip generating $ac_prefix_conf_OUT" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ rm -f conftest.*
+fi
+ ;;
+ zzip/_msvc.h ) ac_prefix_conf_OUT=`echo zzip/_msvc.h`
+ac_prefix_conf_DEF=`echo _$ac_prefix_conf_OUT | sed -e "y:abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:" -e "s/[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g"`
+ac_prefix_conf_PKG=`echo zzip`
+ac_prefix_conf_LOW=`echo _$ac_prefix_conf_PKG | sed -e "y:ABCDEFGHIJKLMNOPQRSTUVWXYZ-:abcdefghijklmnopqrstuvwxyz_:"`
+ac_prefix_conf_UPP=`echo $ac_prefix_conf_PKG | sed -e "y:abcdefghijklmnopqrstuvwxyz-:ABCDEFGHIJKLMNOPQRSTUVWXYZ_:" -e "/^[0123456789]/s/^/_/"`
+ac_prefix_conf_INP=`echo "zzip/_msvc.in" | sed -e 's/ *//'`
+if test ".$ac_prefix_conf_INP" = "."; then
+ for ac_file in : $CONFIG_HEADERS; do test "_$ac_file" = _: && continue
+ case "$ac_file" in
+ *.h) ac_prefix_conf_INP=$ac_file ;;
+ *)
+ esac
+ test ".$ac_prefix_conf_INP" != "." && break
+ done
+fi
+if test ".$ac_prefix_conf_INP" = "."; then
+ case "$ac_prefix_conf_OUT" in
+ */*) ac_prefix_conf_INP=`basename "$ac_prefix_conf_OUT"`
+ ;;
+ *-*) ac_prefix_conf_INP=`echo "$ac_prefix_conf_OUT" | sed -e "s/[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*-//"`
+ ;;
+ *) ac_prefix_conf_INP=config.h
+ ;;
+ esac
+fi
+if test -z "$ac_prefix_conf_PKG" ; then
+ { { echo "$as_me:$LINENO: error: no prefix for _PREFIX_PKG_CONFIG_H" >&5
+echo "$as_me: error: no prefix for _PREFIX_PKG_CONFIG_H" >&2;}
+ { (exit 1); exit 1; }; }
+else
+ if test ! -f "$ac_prefix_conf_INP" ; then if test -f "$srcdir/$ac_prefix_conf_INP" ; then
+ ac_prefix_conf_INP="$srcdir/$ac_prefix_conf_INP"
+ fi fi
+ { echo "$as_me:$LINENO: creating $ac_prefix_conf_OUT - prefix $ac_prefix_conf_UPP for $ac_prefix_conf_INP defines" >&5
+echo "$as_me: creating $ac_prefix_conf_OUT - prefix $ac_prefix_conf_UPP for $ac_prefix_conf_INP defines" >&6;}
+ if test -f $ac_prefix_conf_INP ; then
+ echo "s/#undef *\\([ABCDEFGHIJKLMNOPQRSTUVWXYZ_]\\)/#undef $ac_prefix_conf_UPP""_\\1/" > conftest.prefix
+ echo "s/#undef *\\([abcdefghijklmnopqrstuvwxyz]\\)/#undef $ac_prefix_conf_LOW""_\\1/" >> conftest.prefix
+ echo "s/#define *\\([ABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*\\)\\(.*\\)/#ifndef $ac_prefix_conf_UPP""_\\1 \\" >> conftest.prefix
+ echo "#define $ac_prefix_conf_UPP""_\\1 \\2 \\" >> conftest.prefix
+ echo "#endif/" >>conftest.prefix
+ echo "s/#define *\\([abcdefghijklmnopqrstuvwxyz][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*\\)\\(.*\\)/#ifndef $ac_prefix_conf_LOW""_\\1 \\" >> conftest.prefix
+ echo "#define $ac_prefix_conf_LOW""_\\1 \\2 \\" >> conftest.prefix
+ echo "#endif/" >> conftest.prefix
+ # now executing _script on _DEF input to create _OUT output file
+ echo "#ifndef $ac_prefix_conf_DEF" >$tmp/pconfig.h
+ echo "#define $ac_prefix_conf_DEF 1" >>$tmp/pconfig.h
+ echo ' ' >>$tmp/pconfig.h
+ echo /'*' $ac_prefix_conf_OUT. Generated automatically at end of configure. '*'/ >>$tmp/pconfig.h
+
+ sed -f conftest.prefix $ac_prefix_conf_INP >>$tmp/pconfig.h
+ echo ' ' >>$tmp/pconfig.h
+ echo '/* once:' $ac_prefix_conf_DEF '*/' >>$tmp/pconfig.h
+ echo "#endif" >>$tmp/pconfig.h
+ if cmp -s $ac_prefix_conf_OUT $tmp/pconfig.h 2>/dev/null; then
+ { echo "$as_me:$LINENO: $ac_prefix_conf_OUT is unchanged" >&5
+echo "$as_me: $ac_prefix_conf_OUT is unchanged" >&6;}
+ else
+ ac_dir=`(dirname "$ac_prefix_conf_OUT") 2>/dev/null ||
+$as_expr X"$ac_prefix_conf_OUT" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_prefix_conf_OUT" : 'X\(//\)[^/]' \| \
+ X"$ac_prefix_conf_OUT" : 'X\(//\)$' \| \
+ X"$ac_prefix_conf_OUT" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_prefix_conf_OUT" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ rm -f "$ac_prefix_conf_OUT"
+ mv $tmp/pconfig.h "$ac_prefix_conf_OUT"
+ fi
+ cp conftest.prefix _configs.sed
+ else
+ { { echo "$as_me:$LINENO: error: input file $ac_prefix_conf_INP does not exist - skip generating $ac_prefix_conf_OUT" >&5
+echo "$as_me: error: input file $ac_prefix_conf_INP does not exist - skip generating $ac_prefix_conf_OUT" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ rm -f conftest.*
+fi
+ ;;
+ $ax_create_pkgconfig_generate )
+pkgconfig_generate="$ax_create_pkgconfig_generate"
+if test ! -f "$pkgconfig_generate.in"
+then generate="true"
+elif grep ' generated by configure ' $pkgconfig_generate.in >/dev/null
+then generate="true"
+else generate="false";
+fi
+if $generate ; then
+{ echo "$as_me:$LINENO: creating $pkgconfig_generate.in" >&5
+echo "$as_me: creating $pkgconfig_generate.in" >&6;}
+cat > $pkgconfig_generate.in <<AXEOF
+# generated by configure / remove this line to disable regeneration
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+datadir=@datadir@
+sysconfdir=@sysconfdir@
+includedir=@includedir@
+package=@PACKAGE@
+suffix=@suffix@
+
+Name: @PACKAGE_NAME@
+Description: @PACKAGE_DESCRIPTION@
+Version: @PACKAGE_VERSION@
+Requires: @PACKAGE_REQUIRES@
+Libs: -L\${libdir} @LDFLAGS@ @LIBS@
+Cflags: -I\${includedir} @CPPFLAGS@
+AXEOF
+fi # DONE generate $pkgconfig_generate.in
+{ echo "$as_me:$LINENO: creating $pkgconfig_generate" >&5
+echo "$as_me: creating $pkgconfig_generate" >&6;}
+cat >conftest.sed <<AXEOF
+s|@prefix@|${pkgconfig_prefix}|
+s|@exec_prefix@|${pkgconfig_execprefix}|
+s|@bindir@|${pkgconfig_bindir}|
+s|@libdir@|${pkgconfig_libdir}|
+s|@datadir@|${pkgconfig_datadir}|
+s|@sysconfdir@|${pkgconfig_sysconfdir}|
+s|@includedir@|${pkgconfig_includedir}|
+s|@suffix@|${pkgconfig_suffix}|
+s|@PACKAGE@|${pkgconfig_package}|
+s|@PACKAGE_NAME@|${pkgconfig_libname}|
+s|@PACKAGE_DESCRIPTION@|${pkgconfig_description}|
+s|@PACKAGE_VERSION@|${pkgconfig_version}|
+s|@PACKAGE_REQUIRES@|${pkgconfig_requires}|
+s|@LIBS@|${pkgconfig_libs}|
+s|@LDFLAGS@|${pkgconfig_ldflags}|
+s|@CPPFLAGS@|${pkgconfig_cppflags}|
+AXEOF
+sed -f conftest.sed $pkgconfig_generate.in > $pkgconfig_generate
+if test ! -s $pkgconfig_generate ; then
+ { { echo "$as_me:$LINENO: error: $pkgconfig_generate is empty" >&5
+echo "$as_me: error: $pkgconfig_generate is empty" >&2;}
+ { (exit 1); exit 1; }; }
+fi ; rm conftest.sed # DONE generate $pkgconfig_generate
+pkgconfig_uninstalled=`echo $pkgconfig_generate |sed 's/.pc$/-uninstalled.pc/'`
+{ echo "$as_me:$LINENO: creating $pkgconfig_uninstalled" >&5
+echo "$as_me: creating $pkgconfig_uninstalled" >&6;}
+cat >conftest.sed <<AXEOF
+s|@prefix@|${pkgconfig_prefix}|
+s|@exec_prefix@|${pkgconfig_execprefix}|
+s|@bindir@|${pkgconfig_bindir}|
+s|@libdir@|${pkgconfig_src_libdir}|
+s|@datadir@|${pkgconfig_datadir}|
+s|@sysconfdir@|${pkgconfig_sysconfdir}|
+s|@includedir@|${pkgconfig_src_headers}|
+s|@suffix@|${pkgconfig_suffix}|
+s|@PACKAGE@|${pkgconfig_package}|
+s|@PACKAGE_NAME@|${pkgconfig_libname}|
+s|@PACKAGE_DESCRIPTION@|${pkgconfig_description}|
+s|@PACKAGE_VERSION@|${pkgconfig_version}|
+s|@PACKAGE_REQUIRES@|${pkgconfig_requires}|
+s|@LIBS@|${pkgconfig_libs}|
+s|@LDFLAGS@|${pkgconfig_ldflags}|
+s|@CPPFLAGS@|${pkgconfig_cppflags}|
+AXEOF
+sed -f conftest.sed $pkgconfig_generate.in > $pkgconfig_uninstalled
+if test ! -s $pkgconfig_uninstalled ; then
+ { { echo "$as_me:$LINENO: error: $pkgconfig_uninstalled is empty" >&5
+echo "$as_me: error: $pkgconfig_uninstalled is empty" >&2;}
+ { (exit 1); exit 1; }; }
+fi ; rm conftest.sed # DONE generate $pkgconfig_uninstalled
+ pkgconfig_requires_add=`echo ${pkgconfig_requires}`
+if test ".$pkgconfig_requires_add" != "." ; then
+ pkgconfig_requires_add="pkg-config $pkgconfig_requires_add"
+ else pkgconfig_requires_add=":" ; fi
+pkgconfig_uninstalled=`echo $pkgconfig_generate |sed 's/.pc$/-uninstalled.sh/'`
+{ echo "$as_me:$LINENO: creating $pkgconfig_uninstalled" >&5
+echo "$as_me: creating $pkgconfig_uninstalled" >&6;}
+cat >conftest.sed <<AXEOF
+s|@prefix@|\"${pkgconfig_prefix}\"|
+s|@exec_prefix@|\"${pkgconfig_execprefix}\"|
+s|@bindir@|\"${pkgconfig_bindir}\"|
+s|@libdir@|\"${pkgconfig_src_libdir}\"|
+s|@datadir@|\"${pkgconfig_datadir}\"|
+s|@sysconfdir@|\"${pkgconfig_sysconfdir}\"|
+s|@includedir@|\"${pkgconfig_src_headers}\"|
+s|@suffix@|\"${pkgconfig_suffix}\"|
+s|@PACKAGE@|\"${pkgconfig_package}\"|
+s|@PACKAGE_NAME@|\"${pkgconfig_libname}\"|
+s|@PACKAGE_DESCRIPTION@|\"${pkgconfig_description}\"|
+s|@PACKAGE_VERSION@|\"${pkgconfig_version}\"|
+s|@PACKAGE_REQUIRES@|\"${pkgconfig_requires}\"|
+s|@LIBS@|\"${pkgconfig_libs}\"|
+s|@LDFLAGS@|\"${pkgconfig_ldflags}\"|
+s|@CPPFLAGS@|\"${pkgconfig_cppflags}\"|
+s>Name:>for option\\; do case \"\$option\" in --list-all|--name) echo >
+s>Description: *>\\;\\; --help) pkg-config --help \\; echo Buildscript Of >
+s>Version: *>\\;\\; --modversion|--version) echo >
+s>Requires:>\\;\\; --requires) echo $pkgconfig_requires_add>
+s>Libs: *>\\;\\; --libs) echo >
+s>Cflags: *>\\;\\; --cflags) echo >
+/--libs)/a\\
+ $pkgconfig_requires_add
+/--cflags)/a\\
+ $pkgconfig_requires_add\\
+;; --variable=*) eval echo '\$'\`echo \$option | sed -e 's/.*=//'\`\\
+;; --uninstalled) exit 0 \\
+;; *) ;; esac done
+AXEOF
+sed -f conftest.sed $pkgconfig_generate.in > $pkgconfig_uninstalled
+if test ! -s $pkgconfig_uninstalled ; then
+ { { echo "$as_me:$LINENO: error: $pkgconfig_uninstalled is empty" >&5
+echo "$as_me: error: $pkgconfig_uninstalled is empty" >&2;}
+ { (exit 1); exit 1; }; }
+fi ; rm conftest.sed # DONE generate $pkgconfig_uninstalled
+ ;;
+ esac
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+# libtool-1.4 specific, on zsh target the final requoting does one too much
+case "$host_os" in
+ darwin*)
+ if grep "1.92" libtool >/dev/null ; then
+echo "$as_me:$LINENO: result: patching libtool on .so-sharedlib creation (zsh overquoting)" >&5
+echo "${ECHO_T}patching libtool on .so-sharedlib creation (zsh overquoting)" >&6
+ test -f libtool.old || (mv libtool libtool.old && cp libtool.old libtool)
+ sed -e '/archive_cmds=/s:[\\][\\][\\]*":\\":g' libtool >libtool.new
+ (test -s libtool.new || rm libtool.new) 2>/dev/null
+ test -f libtool.new && mv libtool.new libtool # not 2>/dev/null !!
+ test -f libtool || mv libtool.old libtool
+ fi
+ ;;
+esac
+
+# patch libtool to fix sys_lib_search_path (e.g. crosscompiling a win32 dll)
+if test "_$PATH_SEPARATOR" = "_:" ; then
+ if grep "^sys_lib_search_path_spec.*:" libtool >/dev/null ; then
+echo "$as_me:$LINENO: result: patching libtool to fix sys_lib_search_path_spec" >&5
+echo "${ECHO_T}patching libtool to fix sys_lib_search_path_spec" >&6
+ test -f libtool.old || (mv libtool libtool.old && cp libtool.old libtool)
+ sed -e "/^sys_lib_search_path_spec/s/:/ /g" libtool >libtool.new
+ (test -s libtool.new || rm libtool.new) 2>/dev/null
+ test -f libtool.new && mv libtool.new libtool # not 2>/dev/null !!
+ test -f libtool || mv libtool.old libtool
+ fi
+fi
+
+# patch libtool to add HOST_CC sometimes needed in crosscompiling a win32 dll
+if grep "HOST_CC" libtool >/dev/null; then
+ if test "$build" != "$host" ; then
+ if test "_$HOST_CC" = "_" ; then
+ HOST_CC="false"
+ for i in `echo $PATH | sed 's,:, ,g'` ; do
+ test -x $i/cc && HOST_CC=$i/cc
+ done
+ fi
+echo "$as_me:$LINENO: result: patching libtool to add HOST_CC=$HOST_CC" >&5
+echo "${ECHO_T}patching libtool to add HOST_CC=$HOST_CC" >&6
+ test -f libtool.old || (mv libtool libtool.old && cp libtool.old libtool)
+ sed -e "/BEGIN.*LIBTOOL.*CONFIG/a\\
+HOST_CC=$HOST_CC" libtool >libtool.new
+ (test -s libtool.new || rm libtool.new) 2>/dev/null
+ test -f libtool.new && mv libtool.new libtool # not 2>/dev/null !!
+ test -f libtool || mv libtool.old libtool
+ fi
+fi
+
+# ---------------------------------------------------------------
+echo '-----' $PACKAGE $VERSION $prefix
+$SHELL libtool --features || true
+echo "CFLAGS=$CFLAGS"
+test "$enable_mmap" != "no" && echo "enable mmap ($enable_mmap)"
+test "$enable_mmap" = "no" && echo "disable mmap ($enable_mmap)"
+test "$with_lowstk" != "no" && echo "with lowstk ($with_lowstk)"
+test "$with_lowstk" = "no" && echo "without lowstk ($with_lowstk)"
+test "$with_debug" != "no" && echo "with debug ($with_debug)"
+test "$with_debug" = "no" && echo "without debug ($with_debug)"
+# test -f ./zziplib.spec && echo warning - do not build in the source dirs
+echo '# make && make check && make install'
diff --git a/Build/source/libs/zziplib/configure.ac b/Build/source/libs/zziplib/configure.ac
new file mode 100644
index 00000000000..fc0c7ff9bbf
--- /dev/null
+++ b/Build/source/libs/zziplib/configure.ac
@@ -0,0 +1,320 @@
+AC_INIT(zziplib.spec)
+AC_PREREQ(2.49)
+AC_COPYRIGHT([Guido Draheim <guido@gmx.de> for ZZipLib.SF.net])
+AC_REVISION($Revision: 1.6 $)
+AC_CONFIG_AUX_DIR(uses)
+# =======================================================================
+AC_CANONICAL_SYSTEM
+dnl AM_ENABLE_MULTILIB([Makefile],[$host])
+AX_ENABLE_BUILDDIR_UNAME
+AC_SET_DEFAULT_PATHS_SYSTEM
+# -----------------------------------------------------------------------
+AC_ARG_ENABLE(thread-safe,AC_HELP_STRING(
+ [--disable-thread-safe],[disable thread-safe libtool option])
+ ,,[ enable_thread_safe="yes"])
+THREAD_SAFE=""
+test "$enable_thread_safe" = "yes" && THREAD_SAFE="-thread-safe"
+test "$enable_thread_safe" = "$host_os" && THREAD_SAFE="-thread-safe"
+AC_SUBST(THREAD_SAFE)
+if test -n "$THREAD_SAFE" ; then
+ AC_MSG_RESULT(...using thread-safe linkage)
+else
+ AC_MSG_RESULT(disabled thread-safe linkage)
+fi
+# ----------------------------------------------------------------
+AC_MSG_CHECKING(zlib install prefix)
+AC_ARG_WITH(zlib, AC_HELP_STRING(
+ [--with-zlib],[zlib prefix (e.g. '$HOME/software')])
+ ,,[with_zlib="no"])
+if test "${with_zlib}" = yes ; then # choose --prefix paths
+ if test "${prefix}" = NONE ; then
+ AC_MSG_RESULT(oops, but only itself...)
+ AC_MSG_ERROR(--with-zlib requires a path argument or a --prefix path set)
+ fi
+ with_zlib="$prefix"
+fi
+
+case ".$with_zlib" in
+ .no|.no,*)
+ AC_MSG_RESULT(none)
+ with_zlib="no, not configured" ;;
+ ./usr)
+ AC_MSG_RESULT([oops, ignored (may try --with-zlib=/usr/.)])
+ with_zlib="no, /usr ignored" ;;
+ *) if test ! -d "$with_zlib/include" ; then
+ AC_MSG_RESULT(oops, given but...)
+ AC_MSG_ERROR("$with_zlib/include" is not a directory)
+ fi
+ if test ! -d "$with_zlib/lib" ; then
+ AC_MSG_RESULT(oops, given but...)
+ AC_MSG_ERROR("$with_zlib/lib" is not a directory)
+ fi
+ AC_MSG_RESULT($with_zlib)
+ ZLIB_INCL="-I$with_zlib/include"
+ ZLIB_LDIR="-L$with_zlib/lib"
+ AC_MSG_RESULT(..adding CPPFLAGS $ZLIB_INCL)
+ AC_MSG_RESULT(..adding LDFLAGS $ZLIB_LDIR)
+ CPPFLAGS="$CPPFLAGS $ZLIB_INCL"
+ LDFLAGS="$LDFLAGS $ZLIB_LDIR"
+ ;;
+esac
+AC_SUBST(ZLIB_INCL)
+AC_SUBST(ZLIB_LDIR)
+# -----------------------------------------------------------------------
+AX_SPEC_DEFAULTS
+AM_INIT_AUTOMAKE($PACKAGE,$VERSION)
+dnl test ".$CFLAGS" = "." && CFLAGS=""
+AC_PROG_CC
+dnl test ".$CFLAGS" = "." && test "$GCC" = "yes" && CFLAGS="-O3"
+AC_PROG_INSTALL
+AC_LIBTOOL_WIN32_DLL
+AM_PROG_LIBTOOL
+AX_SET_VERSION_INFO
+
+# -----------------------------------------------------------------------
+AC_MSG_RESULT([creating zzip/_msvc.in via zzip/_msvc.sed of config.h.in])
+test -d zzip || mkdir zzip
+sed -f $srcdir/zzip/_msvc.sed $srcdir/config.h.in >zzip/_msvc.in
+AC_CONFIG_HEADER(config.h)
+AX_PREFIX_CONFIG_H([zzip/_config.h],[zzip],[config.h])
+AX_PREFIX_CONFIG_H([zzip/_msvc.h],[zzip],[zzip/_msvc.in])
+AM_MAINTAINER_MODE
+
+AX_CREATE_PKGCONFIG_INFO(dnl
+[zzip/zziplib.pc], [zzip-zlib-config],[-lzzip])
+# -----------------------------------------------------------------------
+AC_PATH_PROGS(PERL, perl5 perl, echo no perl found for)
+AC_PATH_PROGS(PYTHON, python2.2 python2.3 python, echo no python found for)
+AC_PATH_PROGS(MKZIP, zip pkzip, :)
+AC_PATH_PROGS(XMLTO, xmlto, :)
+
+AC_C_INLINE
+AC_C_CONST
+ACX_C_RESTRICT
+AC_STDC_HEADERS
+AC_HEADER_DIRENT
+AC_CHECK_HEADERS(stdint.h unistd.h windows.h winnt.h winbase.h sys/int_types.h)
+AC_CHECK_HEADERS(sys/types.h sys/mman.h sys/stat.h sys/param.h) dnl posix'ish
+AC_CHECK_HEADERS(io.h direct.h zlib.h byteswap.h)
+AC_CHECK_HEADERS(fnmatch.h)
+AC_CHECK_FUNCS( strcasecmp strndup )
+
+AC_TYPE_OFF_T
+AC_TYPE_SIZE_T
+dnl AC_TYPE_SSIZE_T
+AC_CHECK_TYPE(ssize_t,int)
+AC_CHECK_TYPE(off64_t,_zzip_off_t)
+AC_CHECK_TYPE(__int64,long long)
+AC_COMPILE_CHECK_SIZEOF(short)
+AC_COMPILE_CHECK_SIZEOF(int)
+AC_COMPILE_CHECK_SIZEOF(long)
+AC_C_BIGENDIAN
+dnl -------------------------------------------------------------
+# the default is _disabled_!! anyway, result is prefixed in zzip/_config.h!!
+AC_SYS_LARGEFILE_SENSITIVE
+test ".$LARGEFILE_CFLAGS" = "." && LARGEFILE_CFLAGS=""
+AC_ARG_WITH(largefile,AC_HELP_STRING(
+ [--with-largefile],[compile as off64_t instead of 32bit off_t])
+ ,,[with_largefile="no"])
+if test ".$ac_cv_sys_largefile_sensitive" = ".no" ; then
+ AC_MSG_RESULT(compiles library with the only off_t seen)
+elif test ".$with_largefile" != ".no" ; then
+ AC_MSG_RESULT(compiles library as 64bit off_t variant dnl
+- and renaming some function names)
+ LARGEFILE_CFLAGS="$LARGEFILE_CFLAGS -D_LARGEFILE_SOURCE"
+ AC_MSG_RESULT(..adding CFLAGS $LARGEFILE_CFLAGS)
+ CFLAGS="$CFLAGS $LARGEFILE_CFLAGS"
+ AC_MSG_RESULT(..adding 64 into RELEASE_INFO for the libraries)
+ RELEASE_INFO="$RELEASE_INFO-64"
+else
+ AC_MSG_RESULT(compiles library as 32bit off_t variant dnl
+- largefile is not the default here)
+fi
+AC_SUBST(LARGEFILE_CFLAGS)
+dnl -------------------------------------------------------------
+AC_MSG_CHECKING(for zlib being found)
+if test "_$ac_cv_header_zlib_h" != "_yes" ; then
+ AC_MSG_RESULT(dnl
+...oops: zlib.h not found - try adding some CPPFLAGS to configure call)
+ AC_MSG_RESULT(dnl
+...note: and when linkage fails you might also need to set some LDFLAGS)
+ case "$prefix" in
+ NONE|/usr)
+ AC_MSG_RESULT(dnl
+...note: both can be set by specifying the install prefix of the zlib library)
+ AC_MSG_RESULT(dnl
+...note: via --with-zlib=path ... it will test for -Ipath/include -Lpath/lib)
+ ;;
+ *) if test -d $prefix/include ; then
+ AC_MSG_RESULT(dnl
+...note: -I$prefix/include is not added to CPPFLAGS automatically and)
+ AC_MSG_RESULT(dnl
+...note: neither is -L$prefix/lib for LDFLAGS .. both will be if you specify)
+ AC_MSG_RESULT(dnl
+...note: --with-zlib to configure call, or use --with-zlib=installprefix)
+ fi
+ ;;
+ esac
+ AC_MSG_ERROR(zlib.h not found: "zlib" is required to build "$PACKAGE")
+ exit 1
+fi
+cat >conftest.c <<EOF
+#include <zlib.h>
+const char* zlib_VeRsIoN = ZLIB_VERSION "dEtEcT";
+EOF
+ZLIB_VERSION=`(eval "$ac_cpp conftest.c") 2>/dev/null \
+| grep zlib_VeRsIoN | sed -e 's,.*= *.,,' -e 's,. *.dEtEcT.*,,'`
+rm conftest.c
+AC_SUBST(ZLIB_VERSION)
+AC_MSG_RESULT(yes - $ZLIB_VERSION)
+# ----------------------------------------------------------------
+AC_MSG_CHECKING(docdir default)
+AC_ARG_WITH(docdir, AC_HELP_STRING(
+ [--with-docdir],[docdir prefix (prefix/share/doc)])
+ ,,[with_docdir="no"])
+case "${with_docdir}" in
+ prefix/*) docdir=` echo "$withval" | sed 's/^prefix/${prefix}'` ;;
+ datadir/*) docdir=` echo "$withval" | sed 's/^datadir/${datadir}'` ;;
+ yes) docdir='${prefix}/doc' ;;
+ no) docdir='${datadir}/doc' ;;
+ /*|\\*|[a-zA-Z]:*) docdir="$with_docdir" ;;
+ *) AC_MSG_RESULT(oops)
+ AC_MSG_ERROR(bad value ${withval} for --with-docdir)
+ ;;
+esac
+AC_SUBST(docdir)
+AC_MSG_RESULT($docdir)
+# ----------------------------------------------------------------
+AC_MSG_CHECKING(whether using debugging messages in libraries)
+AC_ARG_WITH(debug, AC_HELP_STRING(
+ [--with-debug],[debug messages in library])
+ , [case "${withval}" in
+ yes|no) with_debug="$withval" ;;
+ *) AC_MSG_RESULT(oops)
+ AC_MSG_ERROR(bad value ${withval} for --with-debug) ;;
+ esac], [with_debug="no"])
+test "$with_debug" != "yes" && with_debug="no" # yes or no
+test "$with_debug" = "yes" && export CFLAGS="$CFLAGS -DDEBUG"
+result="$with_debug" ; test "$result" = "yes" && result="yes, added -DDEBUG"
+AC_MSG_RESULT($result)
+if test "$with_debug" = "yes" ; then if test -n "$RELEASE_INFO" ; then
+ RELEASE_INFO="$RELEASE_INFO-dbg"
+ AC_MSG_RESULT(modified release, $RELEASE_INFO)
+fi fi
+# ----------------------------------------------------------------
+AC_MSG_CHECKING(whether thread stack is too small for bufsiz buffers)
+ # many embedded platforms, superthreaded systems and kernel usage
+ # will severely limit the stackspace for its threads. Use _LOWSTK
+ # compile-define on those platforms.
+AC_ARG_WITH(lowstk, AC_HELP_STRING(
+ [--with-lowstk], [limited thread stack])
+ , [case "${withval}" in
+ yes|no|auto) with_lowstk="$withval" ;;
+ *) AC_MSG_ERROR(bad value ${withval} for --with-lowstk) ;;
+ esac], [with_lowstk="auto"])
+if test "$with_lowstk" = "auto"; then
+ case $target in
+ *-palmos-*) $with_lowstk="yes" ;;
+ esac
+fi
+test "$with_lowstk" != "yes" && with_lowstk="no" # yes or no
+test "$with_lowstk" = "yes" && CFLAGS="$CFLAGS -D_LOWSTK"
+result="$with_lowstk" ; test "$result" = "yes" && result="yes, added -D_LOWSTK"
+AC_MSG_RESULT($with_lowstk)
+# ---------------------------------------------------------------
+AC_MSG_CHECKING(whether can use mmap for file scanning)
+ # system with mmap are probably better performing an searching
+ # and parsing - atleast memory consumption is far better
+AC_ARG_ENABLE(mmap, AC_HELP_STRING(
+ [--disable-mmap],[disable mmap usage])
+ , [case "${enableval}" in
+ yes|no|auto) enable_mmap="${enableval}" ;;
+ *) AC_MSG_RESULT(oops)
+ AC_MSG_ERROR(bad value ${enableval} for --disable-mmap) ;;
+ esac], [enable_mmap="auto"])
+if test "$enable_mmap" = "auto"
+then
+ test "$ac_cv_header_winbase_h" && enable_mmap="yes, winbase.h"
+ test "$ac_cv_header_sys_mman_h" && enable_mmap="yes, sys/mman.h"
+fi
+case "$enable_mmap" in
+ yes|yes,*) CFLAGS="$CFLAGS -D_USE_MMAP"
+ AC_MSG_RESULT($enable_mmap, added -D_USE_MMAP) ;;
+ *) enable_mmap="no"
+ AC_MSG_RESULT(no (just a bit slower)) ;;
+esac
+# ---------------------------------------------------------------
+AC_MSG_CHECKING(whether making SDL parts)
+SDL=""
+AC_ARG_ENABLE(sdl, AC_HELP_STRING(
+ [--enable-sdl],[enable SDL usage (if present)])
+ ,,[enable_sdl="no"])
+if test "$enable_sdl" = "no" ; then
+ AC_MSG_RESULT([no, disabled])
+else
+ enable_sdl=`sdl-config --version 2>/dev/null`
+ case ".$enable_sdl" in
+ .1.*) AC_MSG_RESULT([yes, for SDL $enable_sdl])
+ SDL="SDL" ;;
+ .2.*) AC_MSG_RESULT([yes, untested $enable_sdl])
+ SDL="SDL" ;;
+ *) AC_MSG_RESULT([no, $enable_sdl]) ;;
+ esac
+fi
+AC_SUBST(SDL)
+# ---------------------------------------------------------------
+AC_MSG_CHECKING(running extra tests on make check)
+if test "MKZIP" != ":" ; then
+ AC_MSG_RESULT(yes)
+ ZIPTESTS=""
+else
+ AC_MSG_RESULT(no)
+ ZIPTESTS="#"
+fi
+AC_SUBST(ZIPTESTS)
+# ---------------------------------------------------------------
+AC_MSG_CHECKING(link options)
+case "$host_os" in
+ mingw*)
+ ZZIPLIB_LDFLAGS="-no-undefined -export-all-symbols -mconsole"
+ RESOLVES=' '
+ ;;
+ *)
+ ZZIPLIB_LDFLAGS="--export-dynamic"
+ RESOLVES=' # '
+ ;;
+esac
+AC_MSG_RESULT([$ZZIPLIB_LDFLAGS $RESOLVES])
+AC_SUBST([ZZIPLIB_LDFLAGS])
+AC_SUBST([RESOLVES])
+# ---------------------------------------------------------------
+AX_MAINTAINER_MODE_AUTO_SILENT
+AX_NOT_ENABLE_FRAME_POINTER
+AX_CFLAGS_WARN_ALL
+AX_CFLAGS_NO_WRITABLE_STRINGS
+AX_CFLAGS_STRICT_PROTOTYPES
+AX_CFLAGS_GCC_OPTION(-Wpointer-arith)
+AX_CFLAGS_GCC_OPTION(-Wsign-compare)
+AX_CFLAGS_GCC_OPTION(-Wmissing-declarations)
+# ---------------------------------------------------------------
+AX_ENABLE_DEFAULT_PKGCONFIGDIR
+AX_ENABLE_DEFAULT_ACLOCALDIR
+AC_SUBST([CONFIG_FILES])
+AC_OUTPUT([Makefile zzip/Makefile zzipwrap/Makefile SDL/Makefile
+ docs/Makefile test/Makefile bins/Makefile])
+dnl -------------------------------------------------------------
+PATCH_LIBTOOL_ON_DARWIN_ZSH_OVERQUOTING
+PATCH_LIBTOOL_SYS_LIB_SEARCH_PATH_SPEC
+PATCH_LIBTOOL_TO_ADD_HOST_CC
+# ---------------------------------------------------------------
+echo '-----' $PACKAGE $VERSION $prefix
+$SHELL libtool --features || true
+echo "CFLAGS=$CFLAGS"
+test "$enable_mmap" != "no" && echo "enable mmap ($enable_mmap)"
+test "$enable_mmap" = "no" && echo "disable mmap ($enable_mmap)"
+test "$with_lowstk" != "no" && echo "with lowstk ($with_lowstk)"
+test "$with_lowstk" = "no" && echo "without lowstk ($with_lowstk)"
+test "$with_debug" != "no" && echo "with debug ($with_debug)"
+test "$with_debug" = "no" && echo "without debug ($with_debug)"
+# test -f ./zziplib.spec && echo warning - do not build in the source dirs
+echo '# make && make check && make install'
diff --git a/Build/source/libs/zziplib/docs/64on32.htm b/Build/source/libs/zziplib/docs/64on32.htm
new file mode 100644
index 00000000000..4da84140d5c
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/64on32.htm
@@ -0,0 +1,195 @@
+<section> <date> 13. Aug 2003 </date>
+<h2> 64on32 largefile information </h2>
+
+<section><!--border-->
+<h3> largefile problems </h3>
+
+<P>
+ Through actual problems with handling files larger than 2 Gigabyte,
+ I had to face the fact that there are serious problems with the
+ largefile implementation around shared-libraries. This is bound
+ to the effect that 64on32 platforms allow a preprocessor #define
+ _FILE_OFFSET_BITS=64 which will shift the integretal type of
+ off_t from a 32bit to a 64bit entity.
+</P>
+
+<P>
+ That will in fact lead to problems if an application is compiled
+ with a different off_t size than the shared-library it will be
+ linked to. Among the problems are different sizes of the callframe
+ for those functions that take an argument of off_t type. Note how
+ the "seek" call uses an off_t in the middle of its arguments which
+ may be 32bit or 64bit depending on a preprocessor define. And
+ you know that zziplib wraps up "seek"-like calls as well.
+</P>
+
+<P>
+ The observations were largely made independent of the zziplib
+ however, as a zip-file does uses 32bit offsets in its header
+ fields anyway, and therefore a single zip-archive (or any of
+ its wrapped files) can not be larger than 2 Gigabyte anyway.
+ I would to refer you for deeper information to my website
+ about this problem-space at
+</P>
+<p><center><big>
+ <a href="http://ac-archive.sf.net/largefile" remap="url">
+ ac-archive.sf.net/largefile </a>
+</big></center></p>
+
+</section><section>
+<h3> zziplib related </h3>
+
+<P>
+ Still however the problems hold for zziplib usage when
+ the functions are linked dynamically as a shared-library.
+ Here we can face the fact that an application (or a higher
+ level library) uses a different off_t size than the
+ underlying zziplib shared-library.
+</P>
+
+<P>
+ If you read the <code>zzip/zzip.h</code> header file then
+ you will surely see a number of off_t usages around, here
+ they are wrapped in the form of zzip_off_t to get away with
+ platforms not predefining off_t in the first place. Those
+ functions are (at the time of writing):
+<blockquote><ul>
+<li> <code>zzip_telldir</code> (return type) </li>
+<li> <code>zzip_seekdir</code> (second param) </li>
+<li> <code>zzip_tell</code> (return type) </li>
+<li> <code>zzip_seek</code> (second param of three)</li>
+</ul></blockquote>
+</P>
+
+<P>
+ What might be not as obvious however: you will find
+ also the off_t type being used in the plugin-handlers
+ callback functions. That is based on the fact that
+ the plugin-structures is filled by default with the
+ posix-functions from the C library. A 64on32 platform
+ however offers quite usually a mixedmode C library
+ exporting two symbols for tell/seek calls to match
+ either 32bit off_t or 64bit off_t
+<blockquote><ul>
+<li> <code>zzip_plugin_io->seeks</code> (return type and second param) </li>
+<li> <code>zzip_plugin_io->filesize</code> (return type) </li>
+</ul></blockquote>
+</P>
+
+<P>
+ The problem here: the application might not make use of
+ zzip_seek/zzip_tell explicitly, but may be the internal
+ implementation of a zzip call uses io->seeks or io->filesize.
+ When an application uses plugin-io with these callbacks
+ overridden then surely problems will arise.
+</P>
+
+</section><section>
+<h3> zziplib mixedmode option </h3>
+
+<P>
+ I have extended the zziplib implementation to allow itself to
+ live fine on 64on32 systems. The 64on32 system are like linux
+ and solaris where the default off_t is 32bit and only by the
+ preprocessor hint they shift into 64bit. The C library on
+ these systems is a mixedmode one offering a pair for each of
+ the problematic functions - lseek <em>and</em> lseek64 for
+ example.
+</P>
+
+<P>
+ The zziplib header file detects when it is present on a
+ 64on32 system (through hints in configured zzip/conf.h)
+ and that _FILE_OFFSET_BITS has been set to 64bit. In that
+ case it does automatically issue #defines that shift the
+ symbol-name from zzip_seek into zzip_seek64. Likewise,
+ <em>all</em> the *_ext_io functions are renamed into
+ *_ext_io64 calls
+</P>
+
+<P>
+ The zziplib library itself will also pick up the renamings
+ when it is compiled with 64bit off_t - in effect an application
+ with a 64bit-off_t dependency can only link with a zziplib
+ compiled in 64bit-off_t mode. If the application does not
+ use any call symbol with an off_t dependency then it does
+ not matter and the link will succeed. That's simply because
+ function calls without an off_t dependency will not be
+ renamed and they are the same for a 32bit-off_t zziplib or
+ a 64bit-off_t zziplib.
+</P>
+
+<P>
+ As an extra, the zziplib exports a few of its common calls
+ like being a mixedmode library when you compile it both in
+ 64bit mode and as a shared library. In that case, the
+ resulting shared library will export symbol pairs for the
+ calls with an off_t dependency, i.e. both zzip_seek and
+ zzip_seek64 are present.
+</P>
+
+<P>
+ Note that for reasons of being a lightweight library, the
+ zziplib library does not export mixmode call pairs for
+ the *_ext_io family of functions. The current generation
+ of zziplib does call io->seeks unconditionally of any
+ case'ing flag and so far there are no problems with the
+ current design.
+</P>
+
+</section><section>
+<h3> Implementation details </h3>
+
+<P>
+ In the header file zzip/zzip.h you will find the define
+ ZZIP_LARGEFILE_RENAME which triggers the renaming process.
+ See zzip/conf.h on the conditions where it is being triggered.
+</P>
+
+<P>
+ For the implementation of the mixedmode symbol pairs, see
+ zzip/dir.c for an example for the zzip_seekdir/zzip_seekdir64
+ pair - here we use libtools -DPIC to detect the situation of
+ being compiled as shared-library, we use the preprocessor
+ #def ZZIP_LARGEFILE_RENAME to know we are on a 64on32
+ system compiled in 64bit-off_t, and we check the transitional
+ largefile API to be present by looking for EOVERFLOW errno.
+</P>
+
+<P>
+ When all the three are present then we simply #undef the
+ renaming preprocessor macro and define a function symbol
+ (without the renaming) and call the renamed symbol
+ already compiled a few lines before. We use the pre-off_t
+ type "long" for the 32bit entity of these calls. While
+ we mostly let the compiler do the shrink/expand of these
+ integer types, we do also sometimes check for overflows
+ of the seekvalue.
+</P>
+
+</section><section>
+<h3> rpm extras and pkg-config </h3>
+
+<P>
+ The provided .spec file shows how to compile both variants
+ of the zziplib shared library and to install them in
+ parallel in the system. Also we provide doubled sets
+ of .pc files for pkg-config installation. That should make
+ it a lot easier for applications to link to the correct
+ library they want.
+</P>
+
+<P>
+ Here are all the variants that you can find after installing
+ the vanilla rpm files from zziplib.sf.net:
+<pre>
+$ pkg-config --list-all | sort | grep zzip
+zziplib32 zziplib32 - ZZipLib - libZ-based ZIP-access Library
+zziplib64 zziplib64 - ZZipLib - libZ-based ZIP-access Library
+zziplib zziplib - ZZipLib - libZ-based ZIP-access Library
+zzip-sdl-config zzip-sdl-config - SDL Config (for ZZipLib)
+zzip-sdl-rwops zzip-sdl-rwops - SDL_rwops for ZZipLib
+zzipwrap zzipwrap - Callback Wrappers for ZZipLib
+zzip-zlib-config zzip-zlib-config - ZLib Config (for ZZipLib)
+</pre></P>
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/COPYING.LIB b/Build/source/libs/zziplib/docs/COPYING.LIB
new file mode 100644
index 00000000000..eb685a5ec98
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/COPYING.LIB
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/Build/source/libs/zziplib/docs/COPYING.MPL b/Build/source/libs/zziplib/docs/COPYING.MPL
new file mode 100644
index 00000000000..18f8109b797
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/COPYING.MPL
@@ -0,0 +1,567 @@
+ MOZILLA PUBLIC LICENSE
+ Version 1.1
+
+ ---------------
+
+1. Definitions.
+
+ 1.0.1. "Commercial Use" means distribution or otherwise making the
+ Covered Code available to a third party.
+
+ 1.1. "Contributor" means each entity that creates or contributes to
+ the creation of Modifications.
+
+ 1.2. "Contributor Version" means the combination of the Original
+ Code, prior Modifications used by a Contributor, and the Modifications
+ made by that particular Contributor.
+
+ 1.3. "Covered Code" means the Original Code or Modifications or the
+ combination of the Original Code and Modifications, in each case
+ including portions thereof.
+
+ 1.4. "Electronic Distribution Mechanism" means a mechanism generally
+ accepted in the software development community for the electronic
+ transfer of data.
+
+ 1.5. "Executable" means Covered Code in any form other than Source
+ Code.
+
+ 1.6. "Initial Developer" means the individual or entity identified
+ as the Initial Developer in the Source Code notice required by Exhibit
+ A.
+
+ 1.7. "Larger Work" means a work which combines Covered Code or
+ portions thereof with code not governed by the terms of this License.
+
+ 1.8. "License" means this document.
+
+ 1.8.1. "Licensable" means having the right to grant, to the maximum
+ extent possible, whether at the time of the initial grant or
+ subsequently acquired, any and all of the rights conveyed herein.
+
+ 1.9. "Modifications" means any addition to or deletion from the
+ substance or structure of either the Original Code or any previous
+ Modifications. When Covered Code is released as a series of files, a
+ Modification is:
+ A. Any addition to or deletion from the contents of a file
+ containing Original Code or previous Modifications.
+
+ B. Any new file that contains any part of the Original Code or
+ previous Modifications.
+
+ 1.10. "Original Code" means Source Code of computer software code
+ which is described in the Source Code notice required by Exhibit A as
+ Original Code, and which, at the time of its release under this
+ License is not already Covered Code governed by this License.
+
+ 1.10.1. "Patent Claims" means any patent claim(s), now owned or
+ hereafter acquired, including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by grantor.
+
+ 1.11. "Source Code" means the preferred form of the Covered Code for
+ making modifications to it, including all modules it contains, plus
+ any associated interface definition files, scripts used to control
+ compilation and installation of an Executable, or source code
+ differential comparisons against either the Original Code or another
+ well known, available Covered Code of the Contributor's choice. The
+ Source Code can be in a compressed or archival form, provided the
+ appropriate decompression or de-archiving software is widely available
+ for no charge.
+
+ 1.12. "You" (or "Your") means an individual or a legal entity
+ exercising rights under, and complying with all of the terms of, this
+ License or a future version of this License issued under Section 6.1.
+ For legal entities, "You" includes any entity which controls, is
+ controlled by, or is under common control with You. For purposes of
+ this definition, "control" means (a) the power, direct or indirect,
+ to cause the direction or management of such entity, whether by
+ contract or otherwise, or (b) ownership of more than fifty percent
+ (50%) of the outstanding shares or beneficial ownership of such
+ entity.
+
+2. Source Code License.
+
+ 2.1. The Initial Developer Grant.
+ The Initial Developer hereby grants You a world-wide, royalty-free,
+ non-exclusive license, subject to third party intellectual property
+ claims:
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Initial Developer to use, reproduce,
+ modify, display, perform, sublicense and distribute the Original
+ Code (or portions thereof) with or without Modifications, and/or
+ as part of a Larger Work; and
+
+ (b) under Patents Claims infringed by the making, using or
+ selling of Original Code, to make, have made, use, practice,
+ sell, and offer for sale, and/or otherwise dispose of the
+ Original Code (or portions thereof).
+
+ (c) the licenses granted in this Section 2.1(a) and (b) are
+ effective on the date Initial Developer first distributes
+ Original Code under the terms of this License.
+
+ (d) Notwithstanding Section 2.1(b) above, no patent license is
+ granted: 1) for code that You delete from the Original Code; 2)
+ separate from the Original Code; or 3) for infringements caused
+ by: i) the modification of the Original Code or ii) the
+ combination of the Original Code with other software or devices.
+
+ 2.2. Contributor Grant.
+ Subject to third party intellectual property claims, each Contributor
+ hereby grants You a world-wide, royalty-free, non-exclusive license
+
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Contributor, to use, reproduce, modify,
+ display, perform, sublicense and distribute the Modifications
+ created by such Contributor (or portions thereof) either on an
+ unmodified basis, with other Modifications, as Covered Code
+ and/or as part of a Larger Work; and
+
+ (b) under Patent Claims infringed by the making, using, or
+ selling of Modifications made by that Contributor either alone
+ and/or in combination with its Contributor Version (or portions
+ of such combination), to make, use, sell, offer for sale, have
+ made, and/or otherwise dispose of: 1) Modifications made by that
+ Contributor (or portions thereof); and 2) the combination of
+ Modifications made by that Contributor with its Contributor
+ Version (or portions of such combination).
+
+ (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+ effective on the date Contributor first makes Commercial Use of
+ the Covered Code.
+
+ (d) Notwithstanding Section 2.2(b) above, no patent license is
+ granted: 1) for any code that Contributor has deleted from the
+ Contributor Version; 2) separate from the Contributor Version;
+ 3) for infringements caused by: i) third party modifications of
+ Contributor Version or ii) the combination of Modifications made
+ by that Contributor with other software (except as part of the
+ Contributor Version) or other devices; or 4) under Patent Claims
+ infringed by Covered Code in the absence of Modifications made by
+ that Contributor.
+
+3. Distribution Obligations.
+
+ 3.1. Application of License.
+ The Modifications which You create or to which You contribute are
+ governed by the terms of this License, including without limitation
+ Section 2.2. The Source Code version of Covered Code may be
+ distributed only under the terms of this License or a future version
+ of this License released under Section 6.1, and You must include a
+ copy of this License with every copy of the Source Code You
+ distribute. You may not offer or impose any terms on any Source Code
+ version that alters or restricts the applicable version of this
+ License or the recipients' rights hereunder. However, You may include
+ an additional document offering the additional rights described in
+ Section 3.5.
+
+ 3.2. Availability of Source Code.
+ Any Modification which You create or to which You contribute must be
+ made available in Source Code form under the terms of this License
+ either on the same media as an Executable version or via an accepted
+ Electronic Distribution Mechanism to anyone to whom you made an
+ Executable version available; and if made available via Electronic
+ Distribution Mechanism, must remain available for at least twelve (12)
+ months after the date it initially became available, or at least six
+ (6) months after a subsequent version of that particular Modification
+ has been made available to such recipients. You are responsible for
+ ensuring that the Source Code version remains available even if the
+ Electronic Distribution Mechanism is maintained by a third party.
+
+ 3.3. Description of Modifications.
+ You must cause all Covered Code to which You contribute to contain a
+ file documenting the changes You made to create that Covered Code and
+ the date of any change. You must include a prominent statement that
+ the Modification is derived, directly or indirectly, from Original
+ Code provided by the Initial Developer and including the name of the
+ Initial Developer in (a) the Source Code, and (b) in any notice in an
+ Executable version or related documentation in which You describe the
+ origin or ownership of the Covered Code.
+
+ 3.4. Intellectual Property Matters
+ (a) Third Party Claims.
+ If Contributor has knowledge that a license under a third party's
+ intellectual property rights is required to exercise the rights
+ granted by such Contributor under Sections 2.1 or 2.2,
+ Contributor must include a text file with the Source Code
+ distribution titled "LEGAL" which describes the claim and the
+ party making the claim in sufficient detail that a recipient will
+ know whom to contact. If Contributor obtains such knowledge after
+ the Modification is made available as described in Section 3.2,
+ Contributor shall promptly modify the LEGAL file in all copies
+ Contributor makes available thereafter and shall take other steps
+ (such as notifying appropriate mailing lists or newsgroups)
+ reasonably calculated to inform those who received the Covered
+ Code that new knowledge has been obtained.
+
+ (b) Contributor APIs.
+ If Contributor's Modifications include an application programming
+ interface and Contributor has knowledge of patent licenses which
+ are reasonably necessary to implement that API, Contributor must
+ also include this information in the LEGAL file.
+
+ (c) Representations.
+ Contributor represents that, except as disclosed pursuant to
+ Section 3.4(a) above, Contributor believes that Contributor's
+ Modifications are Contributor's original creation(s) and/or
+ Contributor has sufficient rights to grant the rights conveyed by
+ this License.
+
+ 3.5. Required Notices.
+ You must duplicate the notice in Exhibit A in each file of the Source
+ Code. If it is not possible to put such notice in a particular Source
+ Code file due to its structure, then You must include such notice in a
+ location (such as a relevant directory) where a user would be likely
+ to look for such a notice. If You created one or more Modification(s)
+ You may add your name as a Contributor to the notice described in
+ Exhibit A. You must also duplicate this License in any documentation
+ for the Source Code where You describe recipients' rights or ownership
+ rights relating to Covered Code. You may choose to offer, and to
+ charge a fee for, warranty, support, indemnity or liability
+ obligations to one or more recipients of Covered Code. However, You
+ may do so only on Your own behalf, and not on behalf of the Initial
+ Developer or any Contributor. You must make it absolutely clear than
+ any such warranty, support, indemnity or liability obligation is
+ offered by You alone, and You hereby agree to indemnify the Initial
+ Developer and every Contributor for any liability incurred by the
+ Initial Developer or such Contributor as a result of warranty,
+ support, indemnity or liability terms You offer.
+
+ 3.6. Distribution of Executable Versions.
+ You may distribute Covered Code in Executable form only if the
+ requirements of Section 3.1-3.5 have been met for that Covered Code,
+ and if You include a notice stating that the Source Code version of
+ the Covered Code is available under the terms of this License,
+ including a description of how and where You have fulfilled the
+ obligations of Section 3.2. The notice must be conspicuously included
+ in any notice in an Executable version, related documentation or
+ collateral in which You describe recipients' rights relating to the
+ Covered Code. You may distribute the Executable version of Covered
+ Code or ownership rights under a license of Your choice, which may
+ contain terms different from this License, provided that You are in
+ compliance with the terms of this License and that the license for the
+ Executable version does not attempt to limit or alter the recipient's
+ rights in the Source Code version from the rights set forth in this
+ License. If You distribute the Executable version under a different
+ license You must make it absolutely clear that any terms which differ
+ from this License are offered by You alone, not by the Initial
+ Developer or any Contributor. You hereby agree to indemnify the
+ Initial Developer and every Contributor for any liability incurred by
+ the Initial Developer or such Contributor as a result of any such
+ terms You offer.
+
+ 3.7. Larger Works.
+ You may create a Larger Work by combining Covered Code with other code
+ not governed by the terms of this License and distribute the Larger
+ Work as a single product. In such a case, You must make sure the
+ requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+ If it is impossible for You to comply with any of the terms of this
+ License with respect to some or all of the Covered Code due to
+ statute, judicial order, or regulation then You must: (a) comply with
+ the terms of this License to the maximum extent possible; and (b)
+ describe the limitations and the code they affect. Such description
+ must be included in the LEGAL file described in Section 3.4 and must
+ be included with all distributions of the Source Code. Except to the
+ extent prohibited by statute or regulation, such description must be
+ sufficiently detailed for a recipient of ordinary skill to be able to
+ understand it.
+
+5. Application of this License.
+
+ This License applies to code to which the Initial Developer has
+ attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+ 6.1. New Versions.
+ Netscape Communications Corporation ("Netscape") may publish revised
+ and/or new versions of the License from time to time. Each version
+ will be given a distinguishing version number.
+
+ 6.2. Effect of New Versions.
+ Once Covered Code has been published under a particular version of the
+ License, You may always continue to use it under the terms of that
+ version. You may also choose to use such Covered Code under the terms
+ of any subsequent version of the License published by Netscape. No one
+ other than Netscape has the right to modify the terms applicable to
+ Covered Code created under this License.
+
+ 6.3. Derivative Works.
+ If You create or use a modified version of this License (which you may
+ only do in order to apply it to code which is not already Covered Code
+ governed by this License), You must (a) rename Your license so that
+ the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+ "MPL", "NPL" or any confusingly similar phrase do not appear in your
+ license (except to note that your license differs from this License)
+ and (b) otherwise make it clear that Your version of the license
+ contains terms which differ from the Mozilla Public License and
+ Netscape Public License. (Filling in the name of the Initial
+ Developer, Original Code or Contributor in the notice described in
+ Exhibit A shall not of themselves be deemed to be modifications of
+ this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+ COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+ DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+ THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+ IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+ YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+ COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+ OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+ ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+ 8.1. This License and the rights granted hereunder will terminate
+ automatically if You fail to comply with terms herein and fail to cure
+ such breach within 30 days of becoming aware of the breach. All
+ sublicenses to the Covered Code which are properly granted shall
+ survive any termination of this License. Provisions which, by their
+ nature, must remain in effect beyond the termination of this License
+ shall survive.
+
+ 8.2. If You initiate litigation by asserting a patent infringement
+ claim (excluding declatory judgment actions) against Initial Developer
+ or a Contributor (the Initial Developer or Contributor against whom
+ You file such action is referred to as "Participant") alleging that:
+
+ (a) such Participant's Contributor Version directly or indirectly
+ infringes any patent, then any and all rights granted by such
+ Participant to You under Sections 2.1 and/or 2.2 of this License
+ shall, upon 60 days notice from Participant terminate prospectively,
+ unless if within 60 days after receipt of notice You either: (i)
+ agree in writing to pay Participant a mutually agreeable reasonable
+ royalty for Your past and future use of Modifications made by such
+ Participant, or (ii) withdraw Your litigation claim with respect to
+ the Contributor Version against such Participant. If within 60 days
+ of notice, a reasonable royalty and payment arrangement are not
+ mutually agreed upon in writing by the parties or the litigation claim
+ is not withdrawn, the rights granted by Participant to You under
+ Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+ the 60 day notice period specified above.
+
+ (b) any software, hardware, or device, other than such Participant's
+ Contributor Version, directly or indirectly infringes any patent, then
+ any rights granted to You by such Participant under Sections 2.1(b)
+ and 2.2(b) are revoked effective as of the date You first made, used,
+ sold, distributed, or had made, Modifications made by that
+ Participant.
+
+ 8.3. If You assert a patent infringement claim against Participant
+ alleging that such Participant's Contributor Version directly or
+ indirectly infringes any patent where such claim is resolved (such as
+ by license or settlement) prior to the initiation of patent
+ infringement litigation, then the reasonable value of the licenses
+ granted by such Participant under Sections 2.1 or 2.2 shall be taken
+ into account in determining the amount or value of any payment or
+ license.
+
+ 8.4. In the event of termination under Sections 8.1 or 8.2 above,
+ all end user license agreements (excluding distributors and resellers)
+ which have been validly granted by You or any distributor hereunder
+ prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+ (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+ DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+ OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+ ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+ CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+ WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+ COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+ INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+ LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+ RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+ PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+ EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+ THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+ The Covered Code is a "commercial item," as that term is defined in
+ 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+ software" and "commercial computer software documentation," as such
+ terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+ C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+ all U.S. Government End Users acquire Covered Code with only those
+ rights set forth herein.
+
+11. MISCELLANEOUS.
+
+ This License represents the complete agreement concerning subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. This License shall be governed by
+ California law provisions (except to the extent applicable law, if
+ any, provides otherwise), excluding its conflict-of-law provisions.
+ With respect to disputes in which at least one party is a citizen of,
+ or an entity chartered or registered to do business in the United
+ States of America, any litigation relating to this License shall be
+ subject to the jurisdiction of the Federal Courts of the Northern
+ District of California, with venue lying in Santa Clara County,
+ California, with the losing party responsible for costs, including
+ without limitation, court costs and reasonable attorneys' fees and
+ expenses. The application of the United Nations Convention on
+ Contracts for the International Sale of Goods is expressly excluded.
+ Any law or regulation which provides that the language of a contract
+ shall be construed against the drafter shall not apply to this
+ License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+ As between Initial Developer and the Contributors, each party is
+ responsible for claims and damages arising, directly or indirectly,
+ out of its utilization of rights under this License and You agree to
+ work with Initial Developer and Contributors to distribute such
+ responsibility on an equitable basis. Nothing herein is intended or
+ shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+ Initial Developer may designate portions of the Covered Code as
+ "Multiple-Licensed". "Multiple-Licensed" means that the Initial
+ Developer permits you to utilize portions of the Covered Code under
+ Your choice of the NPL or the alternative licenses, if any, specified
+ by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+
+ ``The contents of this file are subject to the Mozilla Public License
+ Version 1.1 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ License for the specific language governing rights and limitations
+ under the License.
+
+ The Original Code is ______________________________________.
+
+ The Initial Developer of the Original Code is ________________________.
+ Portions created by ______________________ are Copyright (C) ______
+ _______________________. All Rights Reserved.
+
+ Contributor(s): ______________________________________.
+
+ Alternatively, the contents of this file may be used under the terms
+ of the _____ license (the "[___] License"), in which case the
+ provisions of [______] License are applicable instead of those
+ above. If you wish to allow use of your version of this file only
+ under the terms of the [____] License and not to allow others to use
+ your version of this file under the MPL, indicate your decision by
+ deleting the provisions above and replace them with the notice and
+ other provisions required by the [___] License. If you do not delete
+ the provisions above, a recipient may use your version of this file
+ under either the MPL or the [___] License."
+
+ [NOTE: The text of this Exhibit A may differ slightly from the text of
+ the notices in the Source Code files of the Original Code. You should
+ use the text of this Exhibit A rather than the text found in the
+ Original Code Source Code for Your Modifications.]
+
+ ----------------------------------------------------------------------
+
+ AMENDMENTS
+
+ The Netscape Public License Version 1.1 ("NPL") consists of the
+ Mozilla Public License Version 1.1 with the following Amendments,
+ including Exhibit A-Netscape Public License. Files identified with
+ "Exhibit A-Netscape Public License" are governed by the Netscape
+ Public License Version 1.1.
+
+ Additional Terms applicable to the Netscape Public License.
+ I. Effect.
+ These additional terms described in this Netscape Public
+ License -- Amendments shall apply to the Mozilla Communicator
+ client code and to all Covered Code under this License.
+
+ II. "Netscape's Branded Code" means Covered Code that Netscape
+ distributes and/or permits others to distribute under one or more
+ trademark(s) which are controlled by Netscape but which are not
+ licensed for use under this License.
+
+ III. Netscape and logo.
+ This License does not grant any rights to use the trademarks
+ "Netscape", the "Netscape N and horizon" logo or the "Netscape
+ lighthouse" logo, "Netcenter", "Gecko", "Java" or "JavaScript",
+ "Smart Browsing" even if such marks are included in the Original
+ Code or Modifications.
+
+ IV. Inability to Comply Due to Contractual Obligation.
+ Prior to licensing the Original Code under this License, Netscape
+ has licensed third party code for use in Netscape's Branded Code.
+ To the extent that Netscape is limited contractually from making
+ such third party code available under this License, Netscape may
+ choose to reintegrate such code into Covered Code without being
+ required to distribute such code in Source Code form, even if
+ such code would otherwise be considered "Modifications" under
+ this License.
+
+ V. Use of Modifications and Covered Code by Initial Developer.
+ V.1. In General.
+ The obligations of Section 3 apply to Netscape, except to
+ the extent specified in this Amendment, Section V.2 and V.3.
+
+ V.2. Other Products.
+ Netscape may include Covered Code in products other than the
+ Netscape's Branded Code which are released by Netscape
+ during the two (2) years following the release date of the
+ Original Code, without such additional products becoming
+ subject to the terms of this License, and may license such
+ additional products on different terms from those contained
+ in this License.
+
+ V.3. Alternative Licensing.
+ Netscape may license the Source Code of Netscape's Branded
+ Code, including Modifications incorporated therein, without
+ such Netscape Branded Code becoming subject to the terms of
+ this License, and may license such Netscape Branded Code on
+ different terms from those contained in this License.
+
+ VI. Litigation.
+ Notwithstanding the limitations of Section 11 above, the
+ provisions regarding litigation in Section 11(a), (b) and (c) of
+ the License shall apply to all disputes relating to this License.
+
+ EXHIBIT A-Netscape Public License.
+
+ "The contents of this file are subject to the Netscape Public
+ License Version 1.1 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of
+ the License at http://www.mozilla.org/NPL/
+
+ Software distributed under the License is distributed on an "AS
+ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ rights and limitations under the License.
+
+ The Original Code is Mozilla Communicator client code, released
+ March 31, 1998.
+
+ The Initial Developer of the Original Code is Netscape
+ Communications Corporation. Portions created by Netscape are
+ Copyright (C) 1998-1999 Netscape Communications Corporation. All
+ Rights Reserved.
+
+ Contributor(s): ______________________________________.
+
+ Alternatively, the contents of this file may be used under the
+ terms of the _____ license (the "[___] License"), in which case
+ the provisions of [______] License are applicable instead of
+ those above. If you wish to allow use of your version of this
+ file only under the terms of the [____] License and not to allow
+ others to use your version of this file under the NPL, indicate
+ your decision by deleting the provisions above and replace them
+ with the notice and other provisions required by the [___]
+ License. If you do not delete the provisions above, a recipient
+ may use your version of this file under either the NPL or the
+ [___] License."
diff --git a/Build/source/libs/zziplib/docs/COPYING.ZLIB b/Build/source/libs/zziplib/docs/COPYING.ZLIB
new file mode 100644
index 00000000000..b21b5724b39
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/COPYING.ZLIB
@@ -0,0 +1,30 @@
+
+ THE ZLIB/LIBPNG LICENSE (copy from opensource.org)
+
+ Copyright (c) <year> <copyright holders>
+
+ This software is provided 'as-is', without any express
+ or implied warranty. In no event will the authors be
+ held liable for any damages arising from the use of this
+ software.
+
+ Permission is granted to anyone to use this software for
+ any purpose, including commercial applications, and to
+ alter it and redistribute it freely, subject to the
+ following restrictions:
+
+ 1. The origin of this software must not be
+ misrepresented; you must not claim that you
+ wrote the original software. If you use this
+ software in a product, an acknowledgment in
+ the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly
+ marked as such, and must not be
+ misrepresented as being the original
+ software.
+
+ 3. This notice may not be removed or altered
+ from any source distribution.
+
diff --git a/Build/source/libs/zziplib/docs/Makefile.am b/Build/source/libs/zziplib/docs/Makefile.am
new file mode 100644
index 00000000000..559758b81d2
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/Makefile.am
@@ -0,0 +1,249 @@
+AUTOMAKE_OPTIONS = 1.4 foreign
+AUTOTOOL_VERSION=autoconf-2.52 automake-1.5 libtool-1.4.2
+
+doc_FILES = README.MSVC6 README.SDL COPYING.MPL COPYING.LIB COPYING.ZLIB \
+ zziplib.html
+htm_FILES = zzip-index.htm zzip-zip.htm zzip-file.htm zzip-sdl-rwops.htm \
+ zzip-extio.htm zzip-xor.htm zzip-crypt.htm zzip-cryptoid.htm \
+ zzip-api.htm zzip-basics.htm zzip-extras.htm zzip-parse.htm \
+ 64on32.htm future.htm fseeko.htm mmapped.htm memdisk.htm \
+ configs.htm sfx-make.htm developer.htm download.htm \
+ history.htm referentials.htm faq.htm copying.htm
+SDL = @top_srcdir@/SDL
+SDL_RWOPS = $(SDL)/SDL_rwops_zzcat.c \
+ $(SDL)/SDL_rwops_zzip.c $(SDL)/SDL_rwops_zzip.h
+changelog = @top_srcdir@/ChangeLog
+
+EXTRA_DIST = make-doc.py $(doc_FILES) $(htm_FILES) $(SDL_RWOPS) \
+ make-doc.pl make-dbk.pl mksite.sh mksite.pl body.htm \
+ manpages.ar zziplib-master.dbk
+CLEANFILES = *.pc *.omf
+DISTCLEANFILES = zziplib.spec manpages.ar htmpages.ar *.html *.xml
+
+html_FILES = $(htm_FILES:.htm=.html) \
+ $(htm_FILES:.htm=.print.html) \
+ site.html site.print.html
+
+default : doc
+clean-doc clean-docs : clean-unpack
+ - rm $(DISTCLEANFILES)
+ - rm $(MAINTAINERCLEANFILES)
+
+# -------------------------------------------------------------------
+zziplib.spec : @top_srcdir@/$(PACKAGE).spec
+ @ $(LN_S) $? $@ # the two zzip-doc.* will grep thru zziplib.spec
+doc : $(doc_FILES) site.html
+docs : doc manpages.ar htmpages.ar
+docu : docs
+zziplib0.html : zziplib0.xml
+zziplib0.xml : zziplib.spec @srcdir@/Makefile.am @srcdir@/make-doc.pl \
+ $(srcdir)/make-doc.pl @top_srcdir@/zzip/*.c
+ - @PERL@ $(srcdir)/make-doc.pl @top_srcdir@/zzip/*.c \
+ "suffix=0" "package=$(PACKAGE)" "version=$(VERSION)" \
+ "mainheader=zzip/zzip.h" "exported=<zzip/zzip.h> // or <zziplib.h>" \
+ "docbookfile=$@"
+ - test -s $@
+zziplib1.html : zziplib1.xml
+zziplib1.xml : zziplib.spec @srcdir@/Makefile.am @srcdir@/make-doc.py \
+ $(srcdir)/make-doc.py @top_srcdir@/zzip/*.c
+ - @PYTHON@ $(srcdir)/make-doc.py @top_srcdir@/zzip/*.c suffix=1
+ - test -f zziplib1.docbook && mv zziplib1.docbook $@ ; test -s $@
+zziplib.html : zziplib1.html zziplib0.html
+ - test -s zziplib0.html && cp zziplib0.html zziplib.html
+ - test -s zziplib1.html && cp zziplib1.html zziplib.html
+ test -s $@
+zziplib.xml : zziplib1.xml zziplib0.xml
+ - test -s zziplib0.xml && cp zziplib0.xml zziplib.xml
+ - test -s zziplib1.xml && cp zziplib1.xml zziplib.xml
+ test -s $@ || rm $@
+
+omfdir=${datadir}/omf
+pkgomfdir=${omfdir}/${PACKAGE}
+SFNETDIR=/groups/z/zz/zziplib/htdocs
+SFNETDOC=${datadir}${SFNETDIR}
+pkgdocdir=${datadir}${SFNETDIR}
+bins = @top_srcdir@/bins
+DOCEXAMPLES = $(bins)/zzdir.c $(bins)/zzcat.c \
+ $(bins)/zzobfuscated.c $(bins)/zziptest.c \
+ $(bins)/zzxordir.c $(bins)/zzxorcat.c \
+ $(bins)/zzxorcopy.c $(SDL_RWOPS)
+
+install-docu: $(doc_FILES) $(man_FILES) site.html $(PACKAGE)-doc.omf
+ $(mkinstalldirs) $(DESTDIR)$(pkgdocdir)
+ for i in $(html_FILES) ; do cat $$i \
+ | sed -e 's:--START-->:-- :' -e 's:<!--ENDS--: --:' \
+ -e "s:\\(href=\"[^/\"]*\\)[.]html\":\\1.htm\":" \
+ -e "s:\\(href=\"[^/\"]*\\)[.]html\#:\\1.htm\#:" \
+ > $(DESTDIR)$(pkgdocdir)/$$i ; done
+ @ for i in $(doc_FILES) $(DOCEXAMPLES) $(srcdir)/README.* \
+ ; do $(INSTALL_DATA) `test -f $$i || echo $(srcdir)/`$$i \
+ $(DESTDIR)$(pkgdocdir) ; done
+ (cd $(DESTDIR)$(pkgdocdir) && ln -sf zziplib.html zziplib.htm)
+ $(mkinstalldirs) $(DESTDIR)$(pkgomfdir)
+ $(INSTALL_DATA) $(PACKAGE)-doc.omf $(DESTDIR)$(pkgomfdir)/
+ - test ".$(DESTDIR)" != "." || scrollkeeper-update
+
+install-sfnet: $(doc_FILES) $(man_FILES) site.html htmpages.ar
+ $(mkinstalldirs) $(DESTDIR)$(SFNETDOC)
+ $(INSTALL_DATA) $(html_FILES) $(DESTDIR)$(SFNETDOC)
+ for i in $(doc_FILES) $(DOCEXAMPLES) $(changelog) $(srcdir)/README.* \
+ ; do $(INSTALL_DATA) `test -f $$i || echo $(srcdir)/`$$i \
+ $(DESTDIR)$(SFNETDOC) ; done
+ (cd $(DESTDIR)$(SFNETDOC) && ln -sf zzip-index.html index.html)
+ $(mkinstalldirs) $(DESTDIR)$(SFNETDOC)/man
+ (test -f htmpages.ar || cd "$srcdir" ; P=`pwd` \
+ ; cd $(DESTDIR)$(SFNETDOC)/man && ar x $$P/htmpages.ar)
+
+install-doc : install-docu install-sfnet
+
+# --------------------------------------------------------------------
+man manpages : manpages.ar
+htm htmpages : htmpages.ar
+
+manpages.ar : zziplib.xml
+ @ if test "$(XMLTO)" = ":" \
+ ; then echo no xmlto found - could not regenerate "$@" - skipped \
+ ; echo just touching the output file "$@" ; touch "$@" \
+ ; else echo going to regenerate "$@" in subdir "'"man"'" \
+ ; echo 'test ! -d man || rm man/* ; test -d man || mkdir man' \
+ ; test ! -d man || rm man/* ; test -d man || mkdir man \
+ ; echo '(cd man && xmlto man ../zziplib.xml)' \
+ ; (cd man && xmlto man ../zziplib.xml) \
+ ; echo 'test ! -f $@ || mv $@ $@.old' \
+ ; test ! -f $@ || mv $@ $@.old \
+ ; echo '(cd man && ar qc ../$@ *.3)' \
+ ; (cd man && ar qc ../$@ *.3) \
+ ; echo '(rm man/*.3 ; rmdir man)' \
+ ; (rm man/*.3 ; rmdir man) \
+ ; fi ; test -s $@ || mv $@.old $@ \
+ || mv $(srcdir)/$@.old $@ || test -s $@.old >$@
+
+htmpages.ar : zziplib.xml
+ @ if test "$(XMLTO)" = ":" \
+ ; then echo no xmlto found - could not regenerate "$@" - skipped \
+ ; echo just touching the output file "$@" ; touch "$@" \
+ ; else echo going to regenerate "$@" in subdir "'"man"'" \
+ ; echo 'test ! -d man || rm /* ; test -d man || mkdir man' \
+ ; test ! -d man || rm man/* ; test -d man || mkdir man \
+ ; echo '(cd man && xmlto html ../zziplib.xml | tee written.lst)' \
+ ; (cd man && xmlto html ../zziplib.xml | tee written.lst) \
+ ; echo 'test ! -f $@ || mv $@ $@.old' \
+ ; test ! -f $@ || mv $@ $@.old \
+ ; echo '(cd man && ar qc ../$@ *.*)' \
+ ; (cd man && ar qc ../$@ *.*) \
+ ; echo '(rm man/*.* ; rmdir man)' \
+ ; (rm man/*.* ; rmdir man) \
+ ; fi ; test -s $@ || mv $@.old $@ \
+ || mv $(srcdir)/$@.old $@ || test -s $@.old >$@
+
+install-man3 : manpages.ar
+ $(mkinstalldirs) $(DESTDIR)$(mandir)/man3
+ P=`pwd` ; cd $(DESTDIR)$(mandir)/man3 \
+ && ar x $$P/manpages.ar && chmod 664 *
+
+unpack : manpages.ar htmpages.ar
+ (rm -rf _htm && mkdir _htm && cd _htm && ar x ../htmpages.ar)
+ (rm -rf _man && mkdir _man && cd _man && ar x ../manpages.ar)
+clean-unpack :
+ rm -rf _htm
+ rm -rf _man
+
+# -------------------------------------------------------------------
+spec_file=$(top_srcdir)/$(PACKAGE).spec
+DOCSERIES= 775fb73e-1874-11d7-93e9-e18cd7ea3c2e
+FROMSPEC= $(spec_file) | head -1 | sed -e 's,<,\&lt;,g' -e 's,>,\&gt;,g'
+DATESPEC= `date +%Y-%m-%d`
+
+$(PACKAGE)-doc.omf : $(spec_file) Makefile
+ echo '<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>' >$@
+ echo '<omf><resource><creator> Guido Draheim </creator>' >>$@
+ grep Packager $(FROMSPEC) | sed -e 's,Packager *: *, <maintainer>,' \
+ -e '/<maintainer>/s,$$,</maintainer>,' >>$@
+ grep Summary $(FROMSPEC) | sed -e 's,Summary *: *, <title>,' \
+ -e '/<title>/s,$$,</title>,' >>$@
+ echo ' <date>'$(DATESPEC)'</date>' >>$@
+ echo ' <version identifier="$(VERSION)" date="'$(DATESPEC)'"/>' >>$@
+ grep Group $(FROMSPEC) | sed -e 's,Group *: *, <subject category=",' \
+ -e 's,/,|,g' -e '/<subject/s,$$," />,' >>$@
+ echo ' <format mime="text/html"/>' >>$@
+ echo ' <identifier url="file:$(pkgdocdir)/zzip-index.htm"/>' >>$@
+ echo ' <language code="C"/>' >>$@
+ echo ' <relation seriesid="$(DOCSERIES)"/>' >>$@
+ echo ' <rights type="GNU LGPL" holder="Guido Draheim"' >>$@
+ echo ' license="$(pkgdocdir)/COPYING.LIB"/>' >>$@
+ echo '</resource></omf>' >>$@
+
+DOCBOOKDTD= -//OASIS/DTD Docbook V4.1.2//EN
+MANSERIES= a302c642-1888-11d7-86f6-ba4b52ef847d
+$(PACKAGE)-man.omf : $(PACKAGE)-doc.omf $(PACKAGE).xml
+ sed -e 's,"text/html","text/xml" dtd="$(DOCBOOKDTD)",' \
+ -e 's,</title>, (Function Reference)</title>,' \
+ -e 's,/index.html,/manpages.xml,' \
+ -e 's,$(DOCSERIES),$(MANSERIES),' $(PACKAGE)-doc.omf > $@
+ test -s $@ || rm $@
+
+omf : $(PACKAGE)-doc.omf $(PACKAGE)-man.omf $(PACKAGE).xml
+install-omf : $(PACKAGE)-doc.omf $(PACKAGE)-man.omf $(PACKAGE).xml
+ $(mkinstalldirs) $(DESTDIR)$(pkgomfdir)
+ $(INSTALL_DATA) $(PACKAGE)-doc.omf $(DESTDIR)$(pkgomfdir)/
+ $(mkinstalldirs) $(DESTDIR)$(pkgdocdir)
+ $(INSTALL_DATA) $(PACKAGE).xml $(DESTDIR)$(pkgdocdir)/manpages.xml
+ $(INSTALL_DATA) $(PACKAGE)-man.omf $(DESTDIR)$(pkgomfdir)/
+ - test ".$(DESTDIR)" != "." || scrollkeeper-update -v
+
+# -------------------------------------------------------------------
+datehead = <hr><table border="0" width="100%"><tr><td> \
+ <a href="mailto:guidod@gmx.de?subject=$(PACKAGE):">guidod@gmx.de</a> \
+ </td><td align="right">
+datetail = </td></tr></table>
+borderhead = <table cellpadding="10"><tr><td>
+bordertail = </td></tr></table>
+
+site.htm : body.htm
+ cp $(srcdir)/body.htm site.htm
+mksite_sh_args = --VERSION=$(VERSION) --xml --src-dir=$(srcdir)
+site.html : site.htm mksite.sh $(htm_FILES)
+ perl $(srcdir)/mksite.pl $(mksite_sh_args) site.htm || \
+ $(SHELL) $(srcdir)/mksite.sh $(mksite_sh_args) site.htm
+
+x : $(htm_FILES:.htm=.htmls)
+$(htm_FILES:.htm=.htmls) : body.htm
+%.htmls : %.htm
+ @ title=`grep '<h2>' $< | sed -e 's:</h2>.*::' -e 's:<[^<>]*>::g'` \
+ ; D=$(DATESPEC) ; cat $(srcdir)/body.htm \
+ | sed -e "s/<!--VERSION-->/$(VERSION)/" \
+ | sed -e "s/<!--DATE-->/$$D/" \
+ | sed -e "s:</title>: - $$title</title>:" \
+ | sed -e "/$@.>/s:\\([^<>]*\\)</a>:<b>\\1</b></a>:" \
+ > $@
+ @ echo $< '>>' $@; cat $< | sed -e "s/<!--VERSION-->/$(VERSION)/" \
+ -e "s:</h2>\\(.*\\):</h2></td><td><i>\\1</i></td></tr></table>:" \
+ -e 's:<h2>:<table width="100%"><tr valign="bottom"><td><h2>:' \
+ -e 's:<td><i>:<td align="right"><br> <i>:' \
+ -e 's:<P>:<p class="justify"><span class="justify">:g' \
+ -e 's:</P>:</span></p>:g' \
+ -e 's,<date>,<!--DATE: ,' -e 's,</date>, -->,' \
+ -e 's,<!--border-->,$(borderhead)<!--BORDER-->,' >>$@
+ @ if grep '<!--BORDER-->' $@ >/dev/null ; then : \
+ ; echo "$(bordertail)<!--/BORDER-->" >>$@ ; fi
+ @ D=`grep '<!--DATE:' $@ | sed -e 's,.*<!--DATE: *,,' -e 's, *-->,,'` \
+ ; if test ".$$D" != "." ; then echo '$(datehead)' >>$@ \
+ ; echo "$$D" >> $@ ; echo "$(datetail)" >> $@ ; fi
+ @ echo "</td></tr></table></body></html>" >>$@
+
+# ----------------------------------------------- create pdf via docbook xml
+zzip.xml : $(htm_FILES) zziplib.xml make-dbk.pl
+ @PERL@ make-dbk.pl $(htm_FILES) zziplib.xml >$@
+ test -s "$@" || rm "$@"
+
+zzip.html : zzip.xml
+ xmlto html-nochunks zzip.xml
+zzip.pdf : zzip.xml
+ xmlto pdf zzip.xml
+
+zziplib.pdf : $(htm_FILES) $(srcdir)/zziplib-master.dbk mksite.pl
+ cp $(srcdir)/zziplib-master.dbk zziplib.docbook
+ xmlto pdf zziplib.docbook ; rm zziplib.docbook
+ test -s zziplib.pdf
+
+pdf : zziplib.pdf
diff --git a/Build/source/libs/zziplib/docs/Makefile.in b/Build/source/libs/zziplib/docs/Makefile.in
new file mode 100644
index 00000000000..889fffd6ff2
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/Makefile.in
@@ -0,0 +1,618 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = docs
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in COPYING.LIB
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_compile_check_sizeof.m4 \
+ $(top_srcdir)/m4/ac_set_default_paths_system.m4 \
+ $(top_srcdir)/m4/ac_sys_largefile_sensitive.m4 \
+ $(top_srcdir)/m4/acx_restrict.m4 \
+ $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \
+ $(top_srcdir)/m4/ax_cflags_no_writable_strings.m4 \
+ $(top_srcdir)/m4/ax_cflags_strict_prototypes.m4 \
+ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \
+ $(top_srcdir)/m4/ax_create_pkgconfig_info.m4 \
+ $(top_srcdir)/m4/ax_enable_builddir_uname.m4 \
+ $(top_srcdir)/m4/ax_expand_prefix.m4 \
+ $(top_srcdir)/m4/ax_maintainer_mode_auto_silent.m4 \
+ $(top_srcdir)/m4/ax_not_enable_frame_pointer.m4 \
+ $(top_srcdir)/m4/ax_prefix_config_h.m4 \
+ $(top_srcdir)/m4/ax_set_version_info.m4 \
+ $(top_srcdir)/m4/ax_spec_file.m4 \
+ $(top_srcdir)/m4/ax_spec_package_version.m4 \
+ $(top_srcdir)/m4/ax_warning_default_aclocaldir.m4 \
+ $(top_srcdir)/m4/ax_warning_default_pkgconfig.m4 \
+ $(top_srcdir)/m4/patch_libtool_on_darwin_zsh_overquoting.m4 \
+ $(top_srcdir)/m4/patch_libtool_sys_lib_search_path_spec.m4 \
+ $(top_srcdir)/m4/patch_libtool_to_add_host_cc.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/uses/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONFIG_FILES = @CONFIG_FILES@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LARGEFILE_CFLAGS = @LARGEFILE_CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+MKZIP = @MKZIP@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RELEASE_INFO = @RELEASE_INFO@
+RESOLVES = @RESOLVES@
+SDL = @top_srcdir@/SDL
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+THREAD_SAFE = @THREAD_SAFE@
+VERSION = @VERSION@
+VERSION_INFO = @VERSION_INFO@
+XMLTO = @XMLTO@
+ZIPTESTS = @ZIPTESTS@
+ZLIB_INCL = @ZLIB_INCL@
+ZLIB_LDIR = @ZLIB_LDIR@
+ZLIB_VERSION = @ZLIB_VERSION@
+ZZIPLIB_LDFLAGS = @ZZIPLIB_LDFLAGS@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_AS = @ac_ct_AS@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DLLTOOL = @ac_ct_DLLTOOL@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_OBJDUMP = @ac_ct_OBJDUMP@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+aclocaldir = @aclocaldir@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_enable_builddir_sed = @ax_enable_builddir_sed@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+docdir = @docdir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pkgconfig_libdir = @pkgconfig_libdir@
+pkgconfig_libfile = @pkgconfig_libfile@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+AUTOMAKE_OPTIONS = 1.4 foreign
+AUTOTOOL_VERSION = autoconf-2.52 automake-1.5 libtool-1.4.2
+doc_FILES = README.MSVC6 README.SDL COPYING.MPL COPYING.LIB COPYING.ZLIB \
+ zziplib.html
+
+htm_FILES = zzip-index.htm zzip-zip.htm zzip-file.htm zzip-sdl-rwops.htm \
+ zzip-extio.htm zzip-xor.htm zzip-crypt.htm zzip-cryptoid.htm \
+ zzip-api.htm zzip-basics.htm zzip-extras.htm zzip-parse.htm \
+ 64on32.htm future.htm fseeko.htm mmapped.htm memdisk.htm \
+ configs.htm sfx-make.htm developer.htm download.htm \
+ history.htm referentials.htm faq.htm copying.htm
+
+SDL_RWOPS = $(SDL)/SDL_rwops_zzcat.c \
+ $(SDL)/SDL_rwops_zzip.c $(SDL)/SDL_rwops_zzip.h
+
+changelog = @top_srcdir@/ChangeLog
+EXTRA_DIST = make-doc.py $(doc_FILES) $(htm_FILES) $(SDL_RWOPS) \
+ make-doc.pl make-dbk.pl mksite.sh mksite.pl body.htm \
+ manpages.ar zziplib-master.dbk
+
+CLEANFILES = *.pc *.omf
+DISTCLEANFILES = zziplib.spec manpages.ar htmpages.ar *.html *.xml
+html_FILES = $(htm_FILES:.htm=.html) \
+ $(htm_FILES:.htm=.print.html) \
+ site.html site.print.html
+
+omfdir = ${datadir}/omf
+pkgomfdir = ${omfdir}/${PACKAGE}
+SFNETDIR = /groups/z/zz/zziplib/htdocs
+SFNETDOC = ${datadir}${SFNETDIR}
+pkgdocdir = ${datadir}${SFNETDIR}
+bins = @top_srcdir@/bins
+DOCEXAMPLES = $(bins)/zzdir.c $(bins)/zzcat.c \
+ $(bins)/zzobfuscated.c $(bins)/zziptest.c \
+ $(bins)/zzxordir.c $(bins)/zzxorcat.c \
+ $(bins)/zzxorcopy.c $(SDL_RWOPS)
+
+
+# -------------------------------------------------------------------
+spec_file = $(top_srcdir)/$(PACKAGE).spec
+DOCSERIES = 775fb73e-1874-11d7-93e9-e18cd7ea3c2e
+FROMSPEC = $(spec_file) | head -1 | sed -e 's,<,\&lt;,g' -e 's,>,\&gt;,g'
+DATESPEC = `date +%Y-%m-%d`
+DOCBOOKDTD = -//OASIS/DTD Docbook V4.1.2//EN
+MANSERIES = a302c642-1888-11d7-86f6-ba4b52ef847d
+
+# -------------------------------------------------------------------
+datehead = <hr><table border="0" width="100%"><tr><td> \
+ <a href="mailto:guidod@gmx.de?subject=$(PACKAGE):">guidod@gmx.de</a> \
+ </td><td align="right">
+
+datetail = </td></tr></table>
+borderhead = <table cellpadding="10"><tr><td>
+bordertail = </td></tr></table>
+mksite_sh_args = --VERSION=$(VERSION) --xml --src-dir=$(srcdir)
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign docs/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign docs/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ $(mkdir_p) $(distdir)/$(SDL)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-exec install-exec-am \
+ install-info install-info-am install-man install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \
+ uninstall-info-am
+
+
+default : doc
+clean-doc clean-docs : clean-unpack
+ - rm $(DISTCLEANFILES)
+ - rm $(MAINTAINERCLEANFILES)
+
+# -------------------------------------------------------------------
+zziplib.spec : @top_srcdir@/$(PACKAGE).spec
+ @ $(LN_S) $? $@ # the two zzip-doc.* will grep thru zziplib.spec
+doc : $(doc_FILES) site.html
+docs : doc manpages.ar htmpages.ar
+docu : docs
+zziplib0.html : zziplib0.xml
+zziplib0.xml : zziplib.spec @srcdir@/Makefile.am @srcdir@/make-doc.pl \
+ $(srcdir)/make-doc.pl @top_srcdir@/zzip/*.c
+ - @PERL@ $(srcdir)/make-doc.pl @top_srcdir@/zzip/*.c \
+ "suffix=0" "package=$(PACKAGE)" "version=$(VERSION)" \
+ "mainheader=zzip/zzip.h" "exported=<zzip/zzip.h> // or <zziplib.h>" \
+ "docbookfile=$@"
+ - test -s $@
+zziplib1.html : zziplib1.xml
+zziplib1.xml : zziplib.spec @srcdir@/Makefile.am @srcdir@/make-doc.py \
+ $(srcdir)/make-doc.py @top_srcdir@/zzip/*.c
+ - @PYTHON@ $(srcdir)/make-doc.py @top_srcdir@/zzip/*.c suffix=1
+ - test -f zziplib1.docbook && mv zziplib1.docbook $@ ; test -s $@
+zziplib.html : zziplib1.html zziplib0.html
+ - test -s zziplib0.html && cp zziplib0.html zziplib.html
+ - test -s zziplib1.html && cp zziplib1.html zziplib.html
+ test -s $@
+zziplib.xml : zziplib1.xml zziplib0.xml
+ - test -s zziplib0.xml && cp zziplib0.xml zziplib.xml
+ - test -s zziplib1.xml && cp zziplib1.xml zziplib.xml
+ test -s $@ || rm $@
+
+install-docu: $(doc_FILES) $(man_FILES) site.html $(PACKAGE)-doc.omf
+ $(mkinstalldirs) $(DESTDIR)$(pkgdocdir)
+ for i in $(html_FILES) ; do cat $$i \
+ | sed -e 's:--START-->:-- :' -e 's:<!--ENDS--: --:' \
+ -e "s:\\(href=\"[^/\"]*\\)[.]html\":\\1.htm\":" \
+ -e "s:\\(href=\"[^/\"]*\\)[.]html\#:\\1.htm\#:" \
+ > $(DESTDIR)$(pkgdocdir)/$$i ; done
+ @ for i in $(doc_FILES) $(DOCEXAMPLES) $(srcdir)/README.* \
+ ; do $(INSTALL_DATA) `test -f $$i || echo $(srcdir)/`$$i \
+ $(DESTDIR)$(pkgdocdir) ; done
+ (cd $(DESTDIR)$(pkgdocdir) && ln -sf zziplib.html zziplib.htm)
+ $(mkinstalldirs) $(DESTDIR)$(pkgomfdir)
+ $(INSTALL_DATA) $(PACKAGE)-doc.omf $(DESTDIR)$(pkgomfdir)/
+ - test ".$(DESTDIR)" != "." || scrollkeeper-update
+
+install-sfnet: $(doc_FILES) $(man_FILES) site.html htmpages.ar
+ $(mkinstalldirs) $(DESTDIR)$(SFNETDOC)
+ $(INSTALL_DATA) $(html_FILES) $(DESTDIR)$(SFNETDOC)
+ for i in $(doc_FILES) $(DOCEXAMPLES) $(changelog) $(srcdir)/README.* \
+ ; do $(INSTALL_DATA) `test -f $$i || echo $(srcdir)/`$$i \
+ $(DESTDIR)$(SFNETDOC) ; done
+ (cd $(DESTDIR)$(SFNETDOC) && ln -sf zzip-index.html index.html)
+ $(mkinstalldirs) $(DESTDIR)$(SFNETDOC)/man
+ (test -f htmpages.ar || cd "$srcdir" ; P=`pwd` \
+ ; cd $(DESTDIR)$(SFNETDOC)/man && ar x $$P/htmpages.ar)
+
+install-doc : install-docu install-sfnet
+
+# --------------------------------------------------------------------
+man manpages : manpages.ar
+htm htmpages : htmpages.ar
+
+manpages.ar : zziplib.xml
+ @ if test "$(XMLTO)" = ":" \
+ ; then echo no xmlto found - could not regenerate "$@" - skipped \
+ ; echo just touching the output file "$@" ; touch "$@" \
+ ; else echo going to regenerate "$@" in subdir "'"man"'" \
+ ; echo 'test ! -d man || rm man/* ; test -d man || mkdir man' \
+ ; test ! -d man || rm man/* ; test -d man || mkdir man \
+ ; echo '(cd man && xmlto man ../zziplib.xml)' \
+ ; (cd man && xmlto man ../zziplib.xml) \
+ ; echo 'test ! -f $@ || mv $@ $@.old' \
+ ; test ! -f $@ || mv $@ $@.old \
+ ; echo '(cd man && ar qc ../$@ *.3)' \
+ ; (cd man && ar qc ../$@ *.3) \
+ ; echo '(rm man/*.3 ; rmdir man)' \
+ ; (rm man/*.3 ; rmdir man) \
+ ; fi ; test -s $@ || mv $@.old $@ \
+ || mv $(srcdir)/$@.old $@ || test -s $@.old >$@
+
+htmpages.ar : zziplib.xml
+ @ if test "$(XMLTO)" = ":" \
+ ; then echo no xmlto found - could not regenerate "$@" - skipped \
+ ; echo just touching the output file "$@" ; touch "$@" \
+ ; else echo going to regenerate "$@" in subdir "'"man"'" \
+ ; echo 'test ! -d man || rm /* ; test -d man || mkdir man' \
+ ; test ! -d man || rm man/* ; test -d man || mkdir man \
+ ; echo '(cd man && xmlto html ../zziplib.xml | tee written.lst)' \
+ ; (cd man && xmlto html ../zziplib.xml | tee written.lst) \
+ ; echo 'test ! -f $@ || mv $@ $@.old' \
+ ; test ! -f $@ || mv $@ $@.old \
+ ; echo '(cd man && ar qc ../$@ *.*)' \
+ ; (cd man && ar qc ../$@ *.*) \
+ ; echo '(rm man/*.* ; rmdir man)' \
+ ; (rm man/*.* ; rmdir man) \
+ ; fi ; test -s $@ || mv $@.old $@ \
+ || mv $(srcdir)/$@.old $@ || test -s $@.old >$@
+
+install-man3 : manpages.ar
+ $(mkinstalldirs) $(DESTDIR)$(mandir)/man3
+ P=`pwd` ; cd $(DESTDIR)$(mandir)/man3 \
+ && ar x $$P/manpages.ar && chmod 664 *
+
+unpack : manpages.ar htmpages.ar
+ (rm -rf _htm && mkdir _htm && cd _htm && ar x ../htmpages.ar)
+ (rm -rf _man && mkdir _man && cd _man && ar x ../manpages.ar)
+clean-unpack :
+ rm -rf _htm
+ rm -rf _man
+
+$(PACKAGE)-doc.omf : $(spec_file) Makefile
+ echo '<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>' >$@
+ echo '<omf><resource><creator> Guido Draheim </creator>' >>$@
+ grep Packager $(FROMSPEC) | sed -e 's,Packager *: *, <maintainer>,' \
+ -e '/<maintainer>/s,$$,</maintainer>,' >>$@
+ grep Summary $(FROMSPEC) | sed -e 's,Summary *: *, <title>,' \
+ -e '/<title>/s,$$,</title>,' >>$@
+ echo ' <date>'$(DATESPEC)'</date>' >>$@
+ echo ' <version identifier="$(VERSION)" date="'$(DATESPEC)'"/>' >>$@
+ grep Group $(FROMSPEC) | sed -e 's,Group *: *, <subject category=",' \
+ -e 's,/,|,g' -e '/<subject/s,$$," />,' >>$@
+ echo ' <format mime="text/html"/>' >>$@
+ echo ' <identifier url="file:$(pkgdocdir)/zzip-index.htm"/>' >>$@
+ echo ' <language code="C"/>' >>$@
+ echo ' <relation seriesid="$(DOCSERIES)"/>' >>$@
+ echo ' <rights type="GNU LGPL" holder="Guido Draheim"' >>$@
+ echo ' license="$(pkgdocdir)/COPYING.LIB"/>' >>$@
+ echo '</resource></omf>' >>$@
+$(PACKAGE)-man.omf : $(PACKAGE)-doc.omf $(PACKAGE).xml
+ sed -e 's,"text/html","text/xml" dtd="$(DOCBOOKDTD)",' \
+ -e 's,</title>, (Function Reference)</title>,' \
+ -e 's,/index.html,/manpages.xml,' \
+ -e 's,$(DOCSERIES),$(MANSERIES),' $(PACKAGE)-doc.omf > $@
+ test -s $@ || rm $@
+
+omf : $(PACKAGE)-doc.omf $(PACKAGE)-man.omf $(PACKAGE).xml
+install-omf : $(PACKAGE)-doc.omf $(PACKAGE)-man.omf $(PACKAGE).xml
+ $(mkinstalldirs) $(DESTDIR)$(pkgomfdir)
+ $(INSTALL_DATA) $(PACKAGE)-doc.omf $(DESTDIR)$(pkgomfdir)/
+ $(mkinstalldirs) $(DESTDIR)$(pkgdocdir)
+ $(INSTALL_DATA) $(PACKAGE).xml $(DESTDIR)$(pkgdocdir)/manpages.xml
+ $(INSTALL_DATA) $(PACKAGE)-man.omf $(DESTDIR)$(pkgomfdir)/
+ - test ".$(DESTDIR)" != "." || scrollkeeper-update -v
+
+site.htm : body.htm
+ cp $(srcdir)/body.htm site.htm
+site.html : site.htm mksite.sh $(htm_FILES)
+ perl $(srcdir)/mksite.pl $(mksite_sh_args) site.htm || \
+ $(SHELL) $(srcdir)/mksite.sh $(mksite_sh_args) site.htm
+
+x : $(htm_FILES:.htm=.htmls)
+$(htm_FILES:.htm=.htmls) : body.htm
+%.htmls : %.htm
+ @ title=`grep '<h2>' $< | sed -e 's:</h2>.*::' -e 's:<[^<>]*>::g'` \
+ ; D=$(DATESPEC) ; cat $(srcdir)/body.htm \
+ | sed -e "s/<!--VERSION-->/$(VERSION)/" \
+ | sed -e "s/<!--DATE-->/$$D/" \
+ | sed -e "s:</title>: - $$title</title>:" \
+ | sed -e "/$@.>/s:\\([^<>]*\\)</a>:<b>\\1</b></a>:" \
+ > $@
+ @ echo $< '>>' $@; cat $< | sed -e "s/<!--VERSION-->/$(VERSION)/" \
+ -e "s:</h2>\\(.*\\):</h2></td><td><i>\\1</i></td></tr></table>:" \
+ -e 's:<h2>:<table width="100%"><tr valign="bottom"><td><h2>:' \
+ -e 's:<td><i>:<td align="right"><br> <i>:' \
+ -e 's:<P>:<p class="justify"><span class="justify">:g' \
+ -e 's:</P>:</span></p>:g' \
+ -e 's,<date>,<!--DATE: ,' -e 's,</date>, -->,' \
+ -e 's,<!--border-->,$(borderhead)<!--BORDER-->,' >>$@
+ @ if grep '<!--BORDER-->' $@ >/dev/null ; then : \
+ ; echo "$(bordertail)<!--/BORDER-->" >>$@ ; fi
+ @ D=`grep '<!--DATE:' $@ | sed -e 's,.*<!--DATE: *,,' -e 's, *-->,,'` \
+ ; if test ".$$D" != "." ; then echo '$(datehead)' >>$@ \
+ ; echo "$$D" >> $@ ; echo "$(datetail)" >> $@ ; fi
+ @ echo "</td></tr></table></body></html>" >>$@
+
+# ----------------------------------------------- create pdf via docbook xml
+zzip.xml : $(htm_FILES) zziplib.xml make-dbk.pl
+ @PERL@ make-dbk.pl $(htm_FILES) zziplib.xml >$@
+ test -s "$@" || rm "$@"
+
+zzip.html : zzip.xml
+ xmlto html-nochunks zzip.xml
+zzip.pdf : zzip.xml
+ xmlto pdf zzip.xml
+
+zziplib.pdf : $(htm_FILES) $(srcdir)/zziplib-master.dbk mksite.pl
+ cp $(srcdir)/zziplib-master.dbk zziplib.docbook
+ xmlto pdf zziplib.docbook ; rm zziplib.docbook
+ test -s zziplib.pdf
+
+pdf : zziplib.pdf
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Build/source/libs/zziplib/docs/README.MSVC6 b/Build/source/libs/zziplib/docs/README.MSVC6
new file mode 100644
index 00000000000..ee042c35092
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/README.MSVC6
@@ -0,0 +1,137 @@
+To compile zziplib with MSVC++ 6 you can use the workspace and project
+files shipped along with the zziplib tarball in the msvc6/ directory.
+This will save you most of the following steps, atleast skip step 1.
+
+Step 1: create zziplib workspace file
+
+- Create a workspace and a project file for "zzip".
+- Add all .c and .h files in the zzip/ directory. Yes, all.
+- Add the toplevel directory (containing the zzip/ directory) as an
+ "Additional Include Directory" to the search path. Best do this in
+ -> Project -> Settings -> Tab: C/C++
+ -> Category: Preprocessor -> "Additional Include Directories".
+ This is a comma-separated list, in the workspace files shipped along
+ with the zziplib tarball, you will see ".." in there where ".." (or ..\..)
+ is the path to the toplevel directory of the unpacked sources.
+- if you did choose "DLL" as a project type then you will automatically
+ see a define _USRDLL and ZZIP_EXPORTS in (this is just a hint)...
+ -> Project -> Settings -> Tab: C/C++
+ -> Category: Preprocessor -> "Preprocessor Definitions".
+- remove any LIB imports other than "kernel32.lib"
+ -> Project -> Settings -> Tab: Link
+ -> Category: Input -> "Object/Library Modules"
+
+Step 2: add zlib dependencies of zziplib.dll
+
+- if you do not have installed zlib in the system then you may want to
+ download "lib" + "bin" parts from http://gnuwin32.sf.net/packages/zlib.htm
+ (I found this msvcrt package via a reference at http://www.zlib.org)
+- suppose you have the zlib.h file in "D:\include" and the libz.lib file
+ is in "D:\lib" then we need to add those dependencies to the project.
+- add the path to zlib.h as an "Additional Include Path", best do this in
+ -> Project -> Settings -> Tab: C/C++
+ -> Category: Preprocessor -> "Additional Include Directories".
+ This is a comma-separated list, after you have changed it, it might
+ look like "..,.,D:\include" (for ".." part see description in Step 1)
+- That is enough to build a zziplib.lib, in order to create a zziplib.dll
+ we need to resolve its linker dependencies as well, best do this in
+ -> Project -> Settings -> Tab: Link
+ -> Category: Input -> "Object/Library Modules"
+ This is a space separated list (!!), add "libz.lib" there, so after
+ changing it it might look like "kernel32.lib libz.lib". Also modify
+ -> Project -> Settings -> Tab: Link
+ -> Category: Input -> "Additional Library Path"
+ which is usually empty. After changing it, it might contain "D:\lib".
+- Also add ZZIP_DLL or ZZIP_EXPORTS for dllspec(exports), best do this in
+ -> Project -> Settings -> Tab: C/C++
+ -> Category: Preprocessor" -> "Preprocessor Definitions".
+ After changing it, it might look like
+ "NDEBUG,WIN32,_WINDOWS,_MBCS,_USRDLL,ZZIP_EXPORTS"
+
+Step 3: example binaries to link with zziplib.dll
+
+- dynamic linking is best to avoid any copyright problems, the "Lesser GPL"
+ does not restrict usage of zziplib for the case of a separated zzip.dll
+- the example workspace builds two zziplib libraries, where zziplib.lib
+ points to the staticlink variant and zzip.lib to the dynalink variant
+ which will add a dependency on zzip-1.dll being in the PATH
+- the example binaries shipped with zziplib tarball do only have a single
+ .c file per output .exe, we pick zzcat.exe to guide you through.
+- if you do not use our shipped project files, create a project "zzcat"
+ and add "bins/zzcat.c" in there.
+- adjust the "Additional Include Directories":
+ -> Project -> Settings -> Tab: C/C++
+ -> Category: Preprocessor -> "Additional Include Directories".
+ like in Step 1 add the path to "./zzip" owning the zziplib headers.
+ We do _not_ need the zlib headers to compile "zzcat.exe", so it might
+ just look like ".." (or "..\.." or "..\zziplib-0.10.82")
+- adjust the "Object/Library Modules"
+ -> Project -> Settings -> Tab: Link
+ -> Category: Input -> "Object/Library Modules"
+ adding "zzip.lib libz.lib" with a space. The result might look like
+ "kernel32.lib zzip.lib libz.lib" or "kernel32.lib zziplib.lib libz.lib".
+- adjust the "Additional Library Path"
+ -> Project -> Settings -> Tab: Link
+ -> Category: Input -> "Additional Library Path"
+ and add both zziplib libpath and libz libpath, separated by comma, i.e.
+ ".\Release,D:\lib" or ".\Debug,D:\lib"
+
+Step 4: Customization
+- have a look at the info parts that can be put into the DLL project:
+ -> Project -> Settings -> Tab: Link
+ -> Category: Output -> "Version Information"
+ e.g. Major: "10" Minor: "82" for Release 0.10.82 of zziplib
+ -> Project -> Settings -> Tab: Resources -> "Language"
+ or just ignore the value when no messages are there
+ -> Project -> Settings -> Tab: Link
+ -> Category: General -> "Output Filename"
+ e.g. "zzip-1.dll" intead of "zzip.dll" for this first generation
+ (needs also to rename dll dependencies from "zzip.lib" to "zzip-1.lib")
+- there are a few defines that trigger extra code in zziplib, e.g.
+ ZZIP_HARDEN - extra sanity check for obfuscated zip files
+ ZZIP_CHECK_BACKSLASH_DIRSEPARATOR - to check for win32-like paths
+ (for the magic part within a zip archive we always assume a "/" separator)
+ ZZIP_USE_ZIPLIKES - not only do magic checks for ".zip" files to
+ be handled like directories, also do that for a few other zip documents
+ ZZIP_WRAPWRAP - if there problems on unusual targets then try this one.
+ -> Project -> Settings -> Tab: C/C++
+ -> Category: Preprocessor" -> "Preprocessor Definitions".
+
+Step 5: Testing
+- copy the *.dll and *.exe files from msvc6/Release/ to a place reachable
+ from your PATH (perhaps d:\bin), or even simpler, go the other way round,
+ copy the file test/test.zip to the msvc6/Release/ directory.
+- open a command window (usually with a "MSDOS" symbol) and go the
+ directory containing the test.zip (e.g. cd zziplib-0.10.82/msvc6/Release)
+- run `zzcat test/README` which should extract the file README from the
+ test.zip archive and print it to the screen. Try `zzdir test` to see
+ that it was really a compressed file printed to the screen.
+- If it works then everything is alright round zziplib which is a good
+ thing to know when there are other problems
+- at the time of writing (0.10.82 of zziplib), the set of bin files are
+ precompiled with msvc6 and pushed to the download center at sourceforge.
+
+cheers, -- guido
+
+# finally, the older description for zziplib 0.10.5x
+
+To build zziplib you need to add the path to zlib to the include directories
+search path. You find this under
+
+ Project, Settings, C/C++, Preprocessor, Additional Include Directories.
+
+Example:
+You have installed zlib to D:\zlib. You then change the edit box
+ Additional Include Directories
+from
+ ..
+to
+ ..,D:\zlib
+
+
+Included are two project files for zziplib. One that creates
+zziplib as a DLL, and one that creates zziplib as a static library.
+The DLL version is compiled with multi-threaded support. The static library
+version is currently set to link with libc(d).lib, i.e. only single-threaded
+CRT. If this does not suit your needs, you can change this under
+ Project, Settings, C/C++, Code Generation, Use run-time library.
diff --git a/Build/source/libs/zziplib/docs/README.SDL b/Build/source/libs/zziplib/docs/README.SDL
new file mode 100644
index 00000000000..29a504621e7
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/README.SDL
@@ -0,0 +1,125 @@
+16122002, Thomas.Eder@nmi.at, Using the zziplib library with SDL
+
+
+PREREQUISITES
+
+ Tested versions:
+ zziplib 0.10.66 (preview), SDL 1.2.5, Win32, MSVC6
+
+ Homepages (download)
+ zziplib.sourceforge.net (zziplib-0.10.66.tar.gz)
+ www.libsdl.org (SDL-devel-1.2.5a-VC6.zip)
+
+ Also you have to get zlib, I used
+ from SDL_image-1.2.2.zip in VisualC.zip:
+ zlib.lib (12.7.1998, 34674 bytes)
+ zlib.h ( 9.7.1998, 41791 bytes, 1.1.3)
+ zconf.h ( 8.7.1998, 8089 bytes)
+
+ from SDL_image-devel-1.2.2-VC6.zip:
+ zlib.dll ( 5.4.2001, 53760 bytes, 1.1.3.1)
+
+ Maybe you should get the latest version (currently 1.1.4) from
+ http://gnuwin32.sourceforge.net/install.html
+ (see notes at end of page!)
+
+
+CREATING zzlib.dll/zzlib.lib
+
+ Copy your versions of zlib.lib, zlib.h and zconf.h to the zzlib
+ directory.
+ In MSVC (start zziplib.dsw)
+ Add zlib.lib to the files for the zziplib_DLL project.
+ Add ZLIB_DLL to the preprocessor definitions.
+
+ Set the active project and the active configuration to create zziplib.dll
+ and zziplib.lib (I created and used the release version).
+
+
+USING zzlib WITH SDL
+
+ Include/add the following files to your SDL-Project
+ (put them in proper directories, etc.):
+
+ Header files:
+ zconf.h
+ zlib.h
+ zzip.h
+ zzip-conf.h
+ zzip-io.h
+ zziplib.h
+ zzip-msvc.h
+ zzip-stdint.h
+
+ Libraries:
+ zlib.lib
+ zziplib.lib
+
+ DLLs:
+ zlib.dll
+ zziplib.dll
+
+ you may also want to use
+ SDL_rwops_zzip.c
+ SDL_rwops_zzip.h
+
+
+ For compiling it should be sufficient to use
+ #include <zziplib.h>
+ in the files where you use zziplib-functions.
+
+
+NOTE
+
+ It is possible to use both original (unzipped) and zipped versions of files,
+ and zziplib will take one of them (depending on the modes when calling
+ zziplib).
+
+ But this didnt work for all of my original files, so I suggest using zipped
+ files only (and remove the original unzipped files, so zziplib doesnt try to
+ open the original version).
+
+
+HINT
+
+ When opening many files from a zip, its faster to open the zip-directory
+ only once, and not for every file access. You may want to modify
+ SDL_rwops_zzip for this to get code like:
+
+
+ SDL_Surface* image;
+ SDL_RWops* rw;
+ SDL_Surface* temp1 = NULL; //default > NULL > error
+ SDL_Surface* temp2 = NULL; //default > NULL > error
+
+ //last param may be used for err return
+ ZZIP_DIR* zzipdir = zzip_dir_open( "figures.zip", NULL );
+
+ ZZIP_FILE* zfile = zzip_file_open(zzipdir, "f1.bmp", ZZIP_CASELESS);
+
+ if (zfile)
+ {
+ rw = SDL_RWFromZZIP(zfile); //modified version
+ if (rw)
+ {
+ temp1 = IMG_Load_RW(rw, 0);
+ SDL_FreeRW(rw);
+ }
+ int zret = zzip_file_close( zfile );
+ }
+
+ zfile = zzip_file_open(zzipdir, "f2.bmp", ZZIP_CASELESS);
+ if (zfile)
+ {
+ rw = SDL_RWFromZZIP(zfile); //modified version
+ if (rw)
+ {
+ temp2 = IMG_Load_RW(rw, 0);
+ SDL_FreeRW(rw);
+ }
+ int zret = zzip_file_close( zfile );
+ }
+
+ //.. etc
+
+ zzip_dir_close( zzipdir );
diff --git a/Build/source/libs/zziplib/docs/body.htm b/Build/source/libs/zziplib/docs/body.htm
new file mode 100644
index 00000000000..60e72627a1b
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/body.htm
@@ -0,0 +1,98 @@
+<html><head><title>zziplib <!--$title?--> </title>
+<link rel="stylesheet" type="text/css" href="sdocbook.css" />
+ <style>
+ a:link { text-decoration : none ; color : #000080 ; }
+ a:visited { text-decoration : none ; color : #200060 ; }
+ .justify { text-align : justify ; }
+ .navlist { background-color : #F0F0F0 ;
+ width : 9em ; speak : none ; }
+ .navprint { pause-after : 200ms ; speak : spell-out ; }
+ body { background-color : white ; }
+ .P { text-align : justify ; margin-right: 1em ;
+ margin-left: 1em ; }
+ .BLOCKQUOTE { text-align : justify ; margin-right: 3em ;
+ margin-left: 3em ; }
+ .PRE { margin-right: 2em ;
+ margin-left: 2em ; }
+ .DT { font-weight : bold ; }
+ .DD { text-align : justify ; margin-right: 1em ; }
+ </style>
+</head><body>
+<!--mksite:sectioninfo--> <!--mksite:nosimplevars-->
+<table width="100%"><tr valign="top"><td class="navlist">
+<center><sub>
+ <!--mksite:printerfriendly-->
+ <a href="${printerfriendly:=site.htm}" title="printer friendly version">
+ <img alt="printer / text mode version" width="8" height="8" border="0" /></a>
+ </sub> &nbsp;
+ <big><big><big><b>
+ <font color="#800080"><sup>Z</sup>ZIP<sub>lib</sub></font>
+ </b></big></big></big>
+<br><big><b> <!--$VERSION--> </b></big>
+</center>
+<hr><a href="zzip-index.html">Library</a>
+<br>-<a href="zzip-zip.html"> ZIP Access</a>
+<br>-<a href="zzip-file.html"> Transparently</a>
+<br>-<a href="zzip-sdl-rwops.html"> SDLrwops <small>Example</small></a>
+<br>-<a href="zzip-extio.html"> ext/io <small>Customization</small></a>
+<br><><a href="zzip-xor.html"> xor/io <small>Obfuscation</small></a>
+<br><><a href="zzip-crypt.html"> zip/no <small>Encryption</small></a>
+<small><a href="zzip-cryptoid.html">(2)</a></small>
+<br>-<a href="zzip-api.html"> Library API</a>
+<br><><a href="zzip-basics.html"> basics</a></u>
+<><a href="zzip-extras.html"> extras</a></u>
+<br>=<a href="zzip-parse.html">Parsing ZIPs</a>
+<br>-<a href="64on32.html"> 64on32 extras</a>
+<br>-<a href="future.html"> Next To Come</a> <br> <>
+<small><a href="fseeko.html"> fseeko </a></small>
+<small><a href="mmapped.html"> mmapped </a></small>
+<small><a href="memdisk.html"> memdisk </a></small>
+<br>-<a href="configs.html"> Config Helpers</a>
+<br>-<a href="sfx-make.html"> Making a zip/exe</a>
+<br>=<a href="history.html">Hints And Links</a>
+<br>-<a href="referentials.html"> Referentials</a>
+<br> -<a href="zziplib.html"> Functions List #</a>
+<!--START-->
+<br> -<a href="man/index.html"> <small>The</small> Manual Pages #</a>
+<!--ENDS-->
+
+<br>&nbsp&nbsp&nbsp <small>(#&nbsp;autogenerated)</small>
+
+<br>&nbsp;
+<hr><a href="download.html"> Download Area </a>
+<br><><a href="developer.html"> Developer Area </a>
+<br><><a href="http://sourceforge.net/projects/zziplib"> Sourceforge Project</a>
+<br><><a href="http://zziplib.sourceforge.net"> zziplib.sf.net
+ <small><i>Home</i></small></a>
+
+<br><small><a href="copying.html"> LGPL/MPL license</a></small>
+<br><small><a href="faq.html">faq</a></small>
+<br>&nbsp;
+<hr>
+<center><!--START-->
+ <a href="http://sourceforge.net/project/?group_id=6389">
+ <img src="http://sourceforge.net/sflogo.php?group_id=6389&type=2"
+ border="0" alt="sourceforge.net" width="125" height="37">
+ </a>
+<br><small><a href="site.html">-sitemap-</a></small>
+</center><!--ENDS-->
+
+<p align="right"><small>
+generated <!--$today-->
+</small>
+<br> <small>(C)</small> Guido Draheim
+<br><i> guidod<small>@</small>gmx.de</i>
+</p>
+<!--mksite:emailfooter:guidod@gmx.de?subject=zzip:-->
+
+<p align="right"><small><small>
+ formatted by <a href="http://zziplib.sf.net/mksite">mksite.sh</a>
+</p>
+
+<p><b>as xml:</b></p>
+<hr><a href="zzip-index.xml">Library</a>
+<br>-<a href="64on32.xml"> 64on32 extras</a>
+<br>-<a href="future.xml"> Next To Come</a> <br> <>
+</td><td>
+
+</td></tr></table></body></html>
diff --git a/Build/source/libs/zziplib/docs/configs.htm b/Build/source/libs/zziplib/docs/configs.htm
new file mode 100644
index 00000000000..49631e673de
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/configs.htm
@@ -0,0 +1,164 @@
+<section> <date> February 2003 </date>
+<h2> Configuration </h2> of other projects using zziplib
+
+<!--border-->
+
+<P>
+ If using the zziplib with other project then you can use a number
+ of possibility to configure and link. The zziplib had been usually
+ included within the projects that made use of it - some did even
+ pick up the advantage to be allowed to staticlink in a limited
+ set of conditions. Recently however, the zziplib is shipped as a
+ standard library of various linux/freebsd distros - mostly for
+ the usage by the php-zip module. This allows third party software
+ makers to link to the preinstalled library in the system and
+ consequently reduce the memory consumption - even more than now
+ with the zziplib being a lightweight anyway (the i386 .so is
+ usually less than 20k)
+</P>
+
+<section>
+<h3> pkg-config --libs </h3>
+
+<P>
+ Within modern software development, one should be advised to use
+ pkg-config as soon as it is available. The pkg-config helper can
+ handle a lot of problems that can usually come up with linking
+ to third party libraries in case that those link again dynamically
+ with other libraries themselves. It does correctly order the
+ list of "libs", it can throw away duplicate "-L" hints, and same
+ for cflags "-I" hints, plus it will throw away some sys-includes
+ that gcc3.2 will warn about with a false positive.
+</P>
+<P>
+ There is a number of pkg-config targets installed in the system
+ but the one you want to use is <b>pkg-config zziplib</b>.
+ Therefore, a simple Makefile could read like
+ <pre>
+ PROGRAM = my_prog
+ CFLAGS = -Dhappy `pkg-config zziplib --cflags`
+ LIBS = -Wl,-E `pkg-config zziplib --libs`
+
+ my_prog.o : my_prog.c
+ $(CC) $(CFLAGS) $&lt; -o $@
+ my_prog : my_prog.o
+ $(LINK) $&lt; $(LIBS)
+ </pre>
+</P>
+<P>
+ The `pkg-config zziplibs --libs` will usually expand to
+ something like <code>-lzzip -lz</code> which are the
+ two (!!) libraries that you need to link with - in that
+ order. The zziplib builds on top of the z-lib algorithms
+ for compression of files within the zip-archive. That's
+ the same for other lib-parts of the zziplib project as
+ well, e.g. the sdl-rwops part which does also need to
+ link with the sdl-lib - and that's where the pkg-config
+ infrastructure can be of great help. That's the reason
+ why zziplib installs a few more ".pc" files, you can
+ get a list of them like this:
+ <pre>
+ $ pkg-config --list-all | sort | grep zzip
+ zziplib zziplib - ZZipLib - libZ-based ZIP-access Library
+ zzip-sdl-config zzip-sdl-config - SDL Config (for ZZipLib)
+ zzip-sdl-rwops zzip-sdl-rwops - SDL_rwops for ZZipLib
+ zzipwrap zzipwrap - Callback Wrappers for ZZipLib
+ zzip-zlib-config zzip-zlib-config - ZLib Config (for ZZipLib)
+ </pre>
+</P><P>
+ The two entries like "zzip-sdl-config" and "zzip-zlib-config"
+ happen to be ".pc" files for the libz.so and libSDL.so that
+ were seen at configure-time of zziplib - you may want to reuse
+ these in your projects as well whenever you need to link to
+ either of zlib or libsdl even in places where there is no direct
+ need for zziplib. It basically looks like:
+ <pre>
+ $ pkg-config zzip-zlib-config --modversion
+ 1.1.4
+ $ pkg-config zzip-zlib-config --libs
+ -lz
+ </pre>
+</P>
+
+</section><section>
+<h3> zzip-config </h3>
+<P>
+ The pkg-config ".pc" files are relativly young in the history of
+ zziplib. A long time before that there was the `zzip-config`
+ script installed in the system. These `*-config` were common
+ before the pkg-config came about, and in fact the pkg-config
+ infrastructure was invented to flatten away the problems of
+ using multiple `*-config` scripts for a project. As long as you
+ do not combine multiple `*-config`s then it should be well okay
+ to use the `zzip-config` directly - it does also kill another
+ dependency on the `pkg-config` tool to build your project, the
+ zziplib is all that's needed.
+</P>
+<P>
+ In its call-structure the `zzip-config` script uses the same
+ options as `pkg-config`, (well they are historic cousins anyway).
+ and that simply means you can replace each call above like
+ `pkg-config zziplib...` with `zzip-config...`.
+
+ <pre>
+ PROGRAM = my_prog
+ CFLAGS = -Dhappy `zzip-config --cflags`
+ LIBS = -Wl,-E `zzip-config --libs`
+
+ my_prog.o : my_prog.c
+ $(CC) $(CFLAGS) $&lt; -o $@
+ my_prog : my_prog.o
+ $(LINK) $&lt; $(LIBS)
+ </pre>
+</P>
+<P>
+ Be informed that the zzip-config script is low-maintained and
+ starting with 2004 it will be replaced with a one-line script
+ that simply reads `pkg-config zziplib $*`. By that time the
+ rpm/deb packages will also list "pkgconfig" as a dependency
+ on the zziplib-devel/zziplib-dev part.
+</P>
+
+</section><section>
+<h3> autoconf macro </h3>
+
+<P>
+ There is currently an autoconf macro installed along into
+ the usual /usr/share/aclocal space for making it easier for
+ you to pick up the configure-time cflags/libs needed to
+ build/link with zziplib. In any way it does look like
+ this:
+ <pre>
+ dnl PKG_CHECK_ZZIPLIB(ZSTUFF, min-version, action-if, action-not)
+ AC_DEFUN([PKG_CHECK_ZZIPLIB],[dnl
+ PKG_CHECK_MODULES([$1], [zziplib $2], [$3], [$4])])
+ </pre>
+</P>
+<P>
+ You are strongly advised to take advantage of the pkgconfig's
+ macro directly - you can find the macro in
+ <code>/usr/share/aclocal/pkg.m4</code> and it allows to
+ combine the flags of a list of library modules that you
+ want to have. If it is only zziplib, than you could simply
+ use this in your configure.ac:
+<pre>
+ <b>PKG_CHECK_MODULES</b>([<b>ZZIP</b>],[zziplib &gt;= 0.10.75])
+ </pre>
+</P><P>
+ which will provide you with two autoconf/automake variables
+ named <b><code>ZZIP_CFLAGS</code></b> and <b><code>ZZIP_LIBS</code></b>
+ respectivly.
+</P>
+<P>
+ Up to 2004, the macro in zziplib.m4 will be however carry
+ a copy of the pkg.m4 so that you do not need another
+ dependency for your software project. The macro is called
+ like shown above PKG_CHECK_ZZIPLIB and you would call it
+ like
+<br><code>&nbsp;&nbsp;&nbsp;&nbsp;
+ PKG_CHECK_ZZIPLIB([ZZIP],[0.10.75])</code><br>
+ which will give you the two autoconf/automake variables
+ as well, <code>ZZIP_CFLAGS</code> and <code>ZZIP_LIBS</code>
+</P>
+
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/copying.htm b/Build/source/libs/zziplib/docs/copying.htm
new file mode 100644
index 00000000000..2f0c8c96d79
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/copying.htm
@@ -0,0 +1,113 @@
+<section> <date> 2004 </date>
+<h2> COPYING - license information </h2> the public license terms
+
+<P>
+ The zziplib is a small library that allows for some parts of
+ obfuscation. This is very handy in commercial projects which tend
+ to incorporate a copy into their source tree. And with
+ <a href="zzip-xor.htm">obfuscation</a> it is often advisable
+ to staticlink the zziplib part and `strip` the symbols from
+ the resulting binary - in order to obfuscate the usage of a
+ standard library for semi-`encryption` of data files.
+</P>
+
+<P>
+ In the past I have been modifying the original LGPL license
+ with a text that allows staticlinking thereby taking over a
+ few paragraphs from the MPL as restrictions to do so, just to
+ defend against improper usage. However I kept being asked
+ legalese questions since most people do not want to interpret
+ added text either and on their own without a lawyer. However
+ that accounts to me as well.
+</P>
+<P>
+ The public license(s) are simply there to protect me and
+ my work, none of this is fixed and it is neither the only
+ possible way to get hold of a proper license. You can
+ always contact me to negotiate a special one if you do
+ need so. In most cases I will just say okay and you get
+ it for free, perhaps after some presentations I will
+ ask for som tax-reductable compensation sent to
+ a wellfare organisation (never me!).
+</P>
+<P>
+ A last hint from a friend did make me think as well, as
+ that the whole point of using standard public licenses
+ is to protect against the need to use your own lawyers
+ in the case that someone breaks the license rules. If
+ one uses a standard license then it is in the interest
+ of that big organization XY that the license will be
+ enforced and that it will be shown valid in all courts.
+ At the time of writing, no opensource license has
+ ever been discussed to an end in a court trial.
+</P>
+<P>
+ That's why at last, I decided to change the COPYING
+ details once again - and start shipping under a dual
+ MPL / LGPL license where each of them is separate
+ and restrictions apply alternatively. Remember that
+ each license is non-exclusive anyway, and I can give
+ out as many licenses as I want, here we have one as
+ MPL, then we have one as LGPL, and perhaps you ask me
+ for a third text to send you over. The public ones
+ are just there for you as a free choice which you can
+ pick without negotiations or a fee.
+</P>
+<P>
+ And yes, you will be on established legal grounds as
+ long as you restrict your usage of the library to the
+ details contained in either COPYING text. And better
+ yet, the legal possibilities have been discussed
+ a few hundred times before. You will surely find
+ good answers on the internet as well to guide you
+ to decisions in your company whether zziplib may
+ be adopted for a specific task.
+</P>
+<P>
+ The sources themselves are sent out under a dual license,
+ with both MPL and LGPL license options, and as long as
+ the MPL part is not removed then the recpient of some
+ modified sources will be entitled to the same choice
+ among the public licenses of LGPL / MPL. Note that some
+ example sources are given away under the ZLIB license
+ which is nothing more than asking for nice behavior
+ which should have been the case even without such a text.
+ <small><small>(However, it is just a fact that some people
+ happen to behave anti-social especially under pressure of
+ capitalist needs, said to lower the risks for commercial
+ success/failure of a company. You have to enforce good
+ behavior or it will be "forgotten". With a license it is
+ not just an error, it is a risk in itself to forget about it)
+ </small></small>
+</P>
+<P>
+ As for staticlinking, let us explore that a bit - there has
+ been a debate that the LGPL warrants in fact the freedom of
+ the final recipient as you must give him the original or
+ modified sources of zziplib, to allow them to modify that
+ part again, and then (re-)link to your own parts. Your own
+ parts may come in the form of precompiled objects without
+ sources (as opposed to the GPL restrictions). In here, it
+ is simply easier to use a dynamic linker that does the
+ re-linking job at startup-time of the whole project instead
+ to provide a makefile and linkage descriptions to let the
+ user do the staticlink it into a combined executable object.
+ The latter however is often needed for embedded environments
+ and it is quite of the original motivation to ask for a
+ staticlink option where in fact the LGPL does allow it anyway
+ as long as you ship all parts separatly as well.
+</P>
+
+<P>
+ The MPL defines the area of a combined work a bit differently,
+ in a way it derives some ideas from BSD'ish licenses. This
+ part does more care to protect the `Intellectual Properties`
+ of the original developers. It does ask to prominently show
+ off that you have gone to link with the work of someone else
+ in your project. Take special note of <em>"3.5 Required Notices"</em>,
+ <em>"3.6 Distribution of Executable Versions"</em> and
+ <em>"3.7 Larger Works"</em> here. Or read a lawyer text on
+ the legal result of the whole license.
+</P>
+
+</section>
diff --git a/Build/source/libs/zziplib/docs/developer.htm b/Build/source/libs/zziplib/docs/developer.htm
new file mode 100644
index 00000000000..57c5c685ca7
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/developer.htm
@@ -0,0 +1,67 @@
+<section> <date> 2004-05-18 </date>
+<H2> Developer </H2> sourceforge CVS area
+
+<center>
+<a href="http://sourceforge.net/cvs/?group_id=6389">
+ http://sourceforge.net/cvs/?group_id=6389 </a>
+</center>
+
+<P>
+ Since 0.13.x the zziplib is using a cvs module "zzip-0" at the
+ sourceforge cvs source repository host. You can get a snapshot
+ from that area anytime, the access details can be found under the
+ link above. All later releases are actually snapshots of some
+ cvs day. (Prior releases had seen too many reshuffling of the
+ build system which cvs is not the best tool to handle gracefully).
+</P>
+<P>
+ I am using the sourceforge compilefarm to do remote testing of
+ releses for crossplatform compatibility. This includes usually
+ some unix compatible platforms such as Linux, Solaris,
+ FreeBSD, Darwin/MacOSX including i386, amd64, sparc, sparc64,
+ powerpc when available. Even the latest daytoday cvs snapshots
+ should be fine for these platforms.
+</P>
+<P>
+ In the labs of my employer some more platforms exist but these are
+ only checked once in a few months, mostly summertime and christmas
+ season if the general workload is low. That includes hp/ux but more
+ importantly a real MSVC6 installation and a few PCs with win32 flavours.
+ I do not use win32 at home! Any help in that area is greatly appreciated,
+ the zziplib was written in strict ansi-C but the build system and dll hell
+ is sometimes very weird for win32 platforms. I feel it often requires
+ experienced hands to detect the source of a problem should there be one.
+</P>
+<P>
+ Note also that I do not use PHP, there is a regular flow of questions
+ circulating around the php-zip module which is built around zziplib. But
+ I can not answer any questions about the build and installation for that.
+ It would be greatly appreciated if I can find contact to a PHP hacker
+ to whom I can forward php related mails! The php zip wrapper is not part
+ of the zziplib in any way.
+</P>
+<P>
+ Since there is an MSVC6 system in reach now, I have not been updating my
+ gcc/mingw32 installations as rigidly as most other win32 developers
+ have. I understand there are great advancements in the msys/mingw32 area
+ and the provided technology which made them follow quickly. However in
+ the labs only some older releases are used for these are called more
+ "stable". Remember that I do not use win32 at home, only crosscompile to
+ mingw32 is checked out sometimes but I know that it is somewhat different
+ than the selfhosted msys environment. Any help is greatly appreciated.
+</P>
+<P>
+ Lastly, I am trying to make the zziplib as close as possible to the
+ thing called "industrial strength". But remember that this is still
+ an opensource spare time probject. <b>I take patches</b>! Many of the
+ interesting parts of zziplib have been introduced by submission which
+ I have later integrated more heavily to make the zziplib be what it
+ was always intended for: to be a small, fast and portable library allowing
+ to use a zip file as a special variant of a data filesystem. The ext/io
+ obfuscation stuff was one of the best feature submissions so far. Thanks.
+</P>
+<P>
+ Looking forward to hear from <em>YOU</em>.
+ - <a href="mailto:guidod@gmx.de?subject=zzip:">guidod@gmx.de</a>
+</P>
+</section>
diff --git a/Build/source/libs/zziplib/docs/download.htm b/Build/source/libs/zziplib/docs/download.htm
new file mode 100644
index 00000000000..d52111155fc
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/download.htm
@@ -0,0 +1,56 @@
+<section> <date> 2004-05-18 </date>
+<H2> Download </H2> what to get to get it
+
+<section>
+<H4>Sourceforge File Area</H4>
+
+<center>
+<a href="http://sourceforge.net/project/showfiles.php?group_id=6389">
+ sourceforge.net/project/showfiles.php?group_id=6389 </a>
+</center>
+
+<P>
+ All source releases and some binary releases are listed at the
+ sourceforge download area under the link show above. The sourceforge
+ file area is replicated all over the world and should be accessible
+ with highest bandwith in all corners of the world.
+</P>
+
+</section><section>
+<H4> Which Version To Download </H4>
+
+<P>
+ Do not use 0.10.x anymore! It is listed as stable since it is the
+ only release of zziplib tested to work on a few dozen platforms.
+ However there were some problematic zip files out there that can
+ trigger segfaults. Later zzip file decoders have extra checks and
+ helper routines for that. It's just that the later zziplib have not
+ been given as many crossplatform build tets as the 0.10.x generation.
+</P>
+<P>
+ Use a 0.12.x (proto-stable) or a 0.13.x (developer) variant of
+ zziplib, especially if you intend to make heavy usage of the zip
+ decoders in specialized environments - I will not add any fixes to
+ the 0.10.x series anymore (it's deep frozen) but if you hit a
+ problem with 0.13.x I can help you quickly with a patch and official
+ bugfix release. The later versions are regulary checked crossplatform
+ atleast for <b>Linux, Solaris, FreeBSD, Darwin/MacOSX, Win32/NT</b>
+ including i386, amd64, sparc, sparc64, powerpc where available.
+</P>
+<P>
+ Note that all generations 0.10.x through 0.13.x are strictly
+ <b>backward compatible</b>. There is a core API (file and dir
+ handling) being binary compatible, which is also true for most
+ of the helper routines (data getters). Only some rarely used
+ entries are made source level compatible, and so far no one had
+ ever any problem with binary compatibility of the zziplib DLLs.
+</P>
+<P>
+ The MSVC users are strongly advised to use a a later version as
+ well since I have tested the 0.12.x/0.13.x myself and making
+ some msc binary dll releases directly - prior versions were
+ thirdparty contributions which were working smoothly since I have
+ been preparing zziplib for win32 using the gcc/mingw compile suite.
+ Please check also the <a href="developer.html">developer pages</a>.
+</P>
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/faq.htm b/Build/source/libs/zziplib/docs/faq.htm
new file mode 100644
index 00000000000..56d79366655
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/faq.htm
@@ -0,0 +1,182 @@
+<section> <date> 2004 </date>
+<H2> FAQ </H2> (non)frequently asked questions
+
+<BLOCKQUOTE>
+ While using the zziplib some people come up with questions and
+ problems that need a little longer to be explained. So here is
+ a list of these notes for your information. Keep it up.
+</BLOCKQUOTE>
+<ul>
+<li> <a href="#latin-1">extended ascii characters in names of zipped files </a>
+</li>
+<li> <a href="#utf-8">unicode support for names of zipped files </a>
+</li>
+<li> <a href="#timestamps">timestamps of zipped files </a>
+</li>
+<li> <a href="#install">installation instructions </a>
+</li>
+<li> <a href="#php">php zip module installation </a>
+</li>
+<li> <a href="#license">commercial support </a>
+</li>
+</ul>
+
+<DL>
+<DT><a name="latin-1" />
+ zziplib does not support extended ascii characaters, winzip does</DT>
+<DD><P>
+ That's somehow incorrect - the ascii range is the 7bit lower plane of
+ an 8bit character encoding. The upper plane had been non-standard for
+ decades including the age when the ZIP file format was invented. The
+ first instances of pkware's zip compressor were used on DOS with a
+ codepage 437 which has a way different encoding for the upper plane
+ than todays latin-1 encoding which in fact used in <em>all</em>
+ modern operating systems. So what really see is a mismatch of
+ character encodings that you are used to.
+</P><P>
+ Even more than that the character encoding had never been specified
+ at all for the filenames in the central directory part. An alert
+ reader will however recognize that <em>each</em> file entry does
+ also have version-info field telling about the compressor that did
+ create the file entry. That version-info has an upper byte telling
+ about the host OS being in use while packaging. A heavy-weight
+ zip decoder might use that value to infer the character encoding
+ on the host OS (while compressing), to detect a mismatch to the
+ current OS (while decompressing), and going to re-code the filename
+ accordingly.
+</P><P>
+ Even more than that the zip file format has seen various extensions
+ over time that have found their place in an extra info block. There
+ are info blocks telling more about the filename / codeset. However
+ the zziplib library does not even attempt to decode a single extra
+ info block as zziplib is originally meant to be a light-weight library.
+ However one might want to put a layer on top of the structure decoding
+ of zziplib that does the necessary detection of character encodings and
+ re-coding of name entries. Such a layer has not been written so far.
+</P></DD>
+<DT><a name="utf-8" />
+ zziplib does not support any unicode plane for filenames </DT>
+<DD><P>
+ The pkware's appnote.text has an extra info block (id-8) for the
+ unicode name of the file entry but it was never actually being
+ used AFAICS. This might be related to the current developments of
+ older systems to drop usage of latin-1 encoding in the upper plane
+ of 8bit characters and instead choosing the multibyte encoding
+ according to UTF-8. This is again highly system specific.
+</P><P>
+ Basically, you would need to instruct the compressor to use
+ UTF-8 encoding for the file-entries to arrive at a zip archive
+ with filenames in that specific character encoding. Along with
+ this zip archive one can switch the application into utf-8 usage
+ as well and take advantage of filename matches in that encoding.
+ This will make it so there is not mismatch in character encoding
+ and implicit re-coding being needed.
+</P></DD>
+<DT><a name="timestamps" />
+ zziplib does not return stat values for file timestamps </DT>
+<DD><P>
+ That's correct and again a re-coding problem. The original
+ timestamp in each file entry is in DOS format (i.e. old-FAT).
+ The stat value is usually expected to be in POSIX format. The
+ win32 API has an extra function for conversion but none of the
+ unix compatibles has one, so it would be needed to ship a
+ conversion function along with zziplib.
+</P><P>
+ However the zziplib is intended to be light-weight system and
+ used largely for packaging data for an application. There it
+ is not used strictly as a variant of Virtual File System (vfs)
+ that would need to map any information from the zip file system
+ to native host system. Of course applications are free to cut
+ out the DOS file timestamp and re-code it on their own. It's
+ just that zziplib does not provide that re-coding originally.
+</P></DD>
+<DT><a name="install" />
+ how can one install the zziplib package </DT>
+<DD><P>
+ The zziplib project is opensource which effectly gives two ways of
+ installing the package: one can download the source archive and use
+ a C compiler to derive a binary executable for whatever computer
+ it needs to be on (see the platform compatibility list). This is
+ the preferred way but for convenience one can download a binary
+ installation archive with precompiled executables.
+</P><P>
+ The current project uses autoconf/automake for cross platform
+ support which includes most unix compatible systems and their
+ native C compilers. The derivates of the GNU C compiler (gcc) have
+ replaced most of these native C compilers in the past years. The
+ <a href="http://www.mingw.org">mingw32</a> project has ported a
+ unix born C compiler to win32 and zziplib can be compiled with
+ it for the various win32 platforms.
+</P><P>
+ There exist some C compilers which can not be embedded easily into
+ a unix compilation framework. The zziplib source archive ships with
+ project files for MSVC6 and MSVC6 (Microsoft Visual C). Adapting
+ these project files might help with installation problems of the
+ DLL hell on win32 platforms. There exist no sufficient guidelines to
+ mix binary helper libraries for many applications on windows.
+</P><P>
+ There exists win32 binary archives as zip files on the download area
+ of zziplib (MSI is always on my wishlist). Including the project as
+ a helper library however you should not use it but instead compile
+ from source. The general library installation on unix are better,
+ the zziplib download area contains regularly some linux binary
+ archives (rpm). Many vendors of unix compatible systems provide
+ precompiled binary packages of zziplib on their own.
+</P></DD>
+<DT><a name="php" />
+ after installing zziplib the php zip module still does not work </DT>
+<DD><P>
+ Now that is one of <b>the most</b> frequently asked questions that
+ I do receive. There is just one major problem with it: I did not
+ write the php zip module (which uses zziplib) and I have no idea
+ how php modules work or how to tell apache's php sandbox to make
+ it work. Really, I do not have the slightest clue on that.
+</P><P>
+ I was posting to some php developer sites to spread awareness of
+ the fact and hopefully to find a guy that I could forward any
+ questions on the php zip module installation. But so far there is
+ nothing, it merily seems that such installation problems are in no
+ way related to zziplib anyway but exists <b>with any other module with a
+ third party library dependency</b> as well. So the answers on php forum
+ sites will ask for details of the current php and apache configuration.
+</P><P>
+ Since I do not run a php zip whatever nor any other php stuff, it's
+ just that those hints were not quite helpful to me. It would be really
+ really great if someone with a php zip background could be so nice to
+ write a short roundup of the areas to check when a php zip module
+ installation fails, so that I could post it here. Where are you?
+ Yours desperatly...&nbsp;;-)
+</P></DD>
+<DT><a name="license" />
+ how to obtain a license and support contract for a commercial project </DT>
+<DD><P>
+ The zziplib has been created as a spare time project and it is put
+ under a very easy free public license. Even for commercial projects
+ there is hardly any need to negotiate a separate license since the
+ restrictions of the GNU LGPL or MPL can be matched easily. As a
+ general hint, if the zziplib is shipped unmodified with your project
+ then you are right within the limits of the free public license.
+</P><P>
+ Sometimes the question for a personal license comes up for very
+ different reason - the need for a support contract and/or the setting
+ of functionality guarantees. The free public licenses include a safeguard
+ clause to that end, "in the hope that it will be useful,
+ but <em>without any warranty</em>; without even the implied warranty of
+ <em>merchantability</em> or <em>fitness for a particular purpose</em>."
+ Since the project was developed as a spare time project however there
+ have never been personal licenses going beyond.
+</P><P>
+ In general you can still try to negotiate a support contract but it
+ will be very costly. It is much more profitable for you to tell one
+ of your developers to have a look at the source code and ensure the
+ required functionality is there, with hands on. The source code is
+ written to be very readable, maintainable and extensible. Just be
+ reminded that the free public licenses have restrictions on shipping
+ modified binaries but I can give you a cheap personal license to
+ escape these. (Such licenses can be obtained in return for tax-deductible
+ donations to organisations supporting opensource software).
+</P></DD>
+</DL>
+
+<P> and as always - <em> Patches are welcome </em> - </P>
+</section>
diff --git a/Build/source/libs/zziplib/docs/fseeko.htm b/Build/source/libs/zziplib/docs/fseeko.htm
new file mode 100644
index 00000000000..89c3195e36d
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/fseeko.htm
@@ -0,0 +1,193 @@
+<section> <date> 2005 </date>
+<H2> zzip/fseeko </H2> zip access for stdio handle
+
+<BLOCKQUOTE>
+ These routines are fully independent from the traditional zzip
+ implementation. They assume a readonly seekable stdio handle
+ representing a complete zip file. The functions show how to
+ parse the structure, find files and return a decoded bytestream.
+</BLOCKQUOTE>
+
+<section>
+<H3> stdio disk handle </H3>
+
+<P>
+ Other than with the <a href="mmapped.html">mmapped</a> alternative
+ interface there is no need to build special handle for the zip
+ disk file. The normal stdio file handle (of type <b><code>FILE</code></b>)
+ serves as the disk access representation. You can open that stdio file
+ handle any way you want. Note however that the <code>zzipfseeko</code>
+ routines modify the access state of that file handle, especially the
+ read position.
+</P>
+
+<P>
+ To get access to a zipped file, you need a zip archive entry known
+ under the type <code>ZZIP_ENTRY</code>. This is again modelled after
+ the <code>DIR_ENTRY</code> type in being a representation of a file
+ name inside the zip central directory. To get a fresh zzip entry, use
+ <code>zzip_entry_findfirst</code>, to get the next use
+ <code>zzip_entry_findnext</code>, and do not forget to free the
+ resource with <code>zzip_entry_free</code>.
+</P>
+<PRE>
+ extern ZZIP_ENTRY* zzip_entry_findfirst(FILE* disk);
+ extern ZZIP_ENTRY* zzip_entry_findnext(ZZIP_ENTRY* entry);
+ extern int zzip_entry_free(ZZIP_ENTRY* entry);
+</PRE>
+<P>
+ These three calls will allow to walk all zip archive members in the
+ order listed in the zip central directory. To actually implement a
+ directory lister ("zzipdir"), you need to get the name string of the
+ zzip entry. This is not just a pointer: the zzip disk entry is not
+ null terminated actually. Therefore we have a helper function that
+ will <code>strdup</code> the entry name as a normal C string:
+</P>
+<PRE>
+ #include &lt;zzip/fseeko.h&gt;
+ void _zzip_dir(FILE* disk)
+ {
+ for (ZZIP_ENTRY* entry = zzip_findfirst (disk);
+ entry ; entry = zzip_findnext (entry)) {
+ char* name = zzip_entry_strdup_name (entry);
+ puts (name); free (name);
+ }
+ }
+</PRE>
+
+</section><section>
+<H3> find a zipped file </H3>
+
+<P>
+ The central directory walk can be used to find any file in the
+ zip archive. The <code>zzipfseeko</code> library however provides
+ two convenience functions that allow to jump directly to the
+ zip disk entry of a given name or pattern. You are free to use
+ the newly allocated <code>ZZIP_ENTRY</code> for later calls on
+ that handle type. Do not forget to <code>zzip_entry_free</code>
+ the handle unless the handle is consumed by a routine, e.g.
+ <code>zzip_entry_findnext</code> to hit the end of directory.
+</P>
+<PRE>
+ extern ZZIP_ENTRY* zzip_entry_findfile(FILE* disk, char* filename,
+ ZZIP_ENTRY* _zzip_restrict entry,
+ zzip_strcmp_fn_t compare);
+
+ extern ZZIP_ENTRY* zzip_entry_findmatch(FILE* disk, char* filespec,
+ ZZIP_ENTRY* _zzip_restrict entry,
+ zzip_fnmatch_fn_t compare, int flags);
+</PRE>
+<P>
+ In general only the first two arguments are non-null pointing to the
+ stdio disk handle and the file name to look for. The "entry" argument
+ is an old value and allows you to walk the zip directory similar to
+ <code>zzip_entry_findnext</code> but actually leaping forward. The
+ compare function can be used for alternate match behavior: the default
+ of <code>strcmp</code> might be changed to <code>strncmp</code> for
+ a caseless match. The "flags" of the second call are forwarded to the
+ posix <code>fnmatch</code> which we use as the default function.
+</P>
+<P>
+ If you do know a specific filename then you can just use
+ <code>zzip_entry_findfile</code> and supply the return value to
+ <code>zzip_entry_fopen</code> with the second argument set to "1"
+ to tell the function to actually consume whichever entry was given.
+ That allows you to skip an explicit <code>zzip_entry_free</code>
+ as it is included in a later <code>zzip_entry_fclose</code>.
+</P>
+<PRE>
+ #include &lt;zzip/fseeko.h&gt;
+<small>
+ /* zzipfseeko already exports this convenience function: */</small>
+ ZZIP_ENTRY_FILE* zzip_entry_ffile(FILE* disk, char* filename) {
+ return zzip_entry_fopen (zzip_entry_findfile (filename, 0, 0), 1);
+ }
+
+ int _zzip_read(FILE* disk, char* filename, void* buffer, int bytes)
+ {
+ ZZIP_ENTRY_FILE* file = zzip_entry_ffile (disk, filename);
+ if (! file) return -1;
+ int bytes = zzip_entry_fread (buffer, 1, bytes, file);
+ zzip_entry_fclose (file);
+ return bytes;
+ }
+</PRE>
+
+</section><section>
+<H3> reading bytes </H3>
+
+<P>
+ The example has shown already how to read some bytes off the head of
+ a zipped file. In general the zzipfseeko api is used to replace a few
+ stdio routines that access a file. For that purpose we provide three
+ functions that look very similar to the stdio functions of
+ <code>fopen()</code>, <code>fread()</code> and <code>fclose()</code>.
+ These work on an active file descriptor of type <code>ZZIP_ENTRY_FILE</code>.
+ Note that this <code>zzip_entry_fopen()</code> uses <code>ZZIP_ENTRY</code>
+ argument as returned by the findfile api. To open a new reader handle from
+ a disk archive and file name you can use the <code>zzip_entry_ffile()</code>
+ convenience call.
+</P>
+
+<PRE>
+ ZZIP_ENTRY_FILE* zzip_entry_ffile (FILE* disk, char* filename);
+ ZZIP_ENTRY_FILE* zzip_entry_fopen (ZZIP_ENTRY* entry, int takeover);
+ zzip_size_t zzip_entry_fread (void* ptr,
+ zzip_size_t sized, zzip_size_t nmemb,
+ ZZIP_ENTRY_FILE* file);
+ int zzip_entry_fclose (ZZIP_ENTRY_FILE* file);
+ int zzip_entry_feof (ZZIP_ENTRY_FILE* file);
+</PRE>
+
+<P>
+ In all of the examples you need to remember that you provide a single
+ stdio <code>FILE</code> descriptor which is in reality a virtual
+ filesystem on its own. Per default filenames are matched case
+ sensitive also on win32 systems. The findnext function will walk all
+ files on the zip virtual filesystem table and return a name entry
+ with the full pathname, i.e. including any directory names to the
+ root of the zip disk <code>FILE</code>.
+</P>
+
+</section><section>
+<H3> ZZIP_ENTRY inspection </H3>
+
+<P>
+ The <code>ZZIP_ENTRY_FILE</code> is a special file descriptor handle
+ of the <code>zzipfseeko</code> library - but the <code>ZZIP_ENTRY</code>
+ is not so special. It is actually a bytewise copy of the data inside the
+ zip disk archive (plus some internal hints appended). While
+ <code>zzip/fseeko.h</code> will not reveal the structure on its own,
+ you can include <code>zzip/format.h</code> to get access to the actual
+ structure content of a <code>ZZIP_ENTRY</code> by (up)casting it to
+<br><b><code>&nbsp;&nbsp;&nbsp;&nbsp;struct zzip_disk_entry</code></b>.
+</P>
+
+<P>
+ In reality however it is not a good idea to actually read the bytes
+ in the <code>zzip_disk_entry</code> structure unless you seriously know
+ the internals of a zip archive entry. That includes any byteswapping
+ needed on bigendian platforms. Instead you want to take advantage of
+ helper macros defined in <code>zzip/fetch.h</code>. These will take
+ care to convert any struct data member to the host native format.
+</P>
+<PRE>
+extern uint16_t zzip_disk_entry_get_flags( zzip_disk_entry* entry);
+extern uint16_t zzip_disk_entry_get_compr( zzip_disk_entry* entry);
+extern uint32_t zzip_disk_entry_get_crc32( zzip_disk_entry* entry);
+
+extern zzip_size_t zzip_disk_entry_csize( zzip_disk_entry* entry);
+extern zzip_size_t zzip_disk_entry_usize( zzip_disk_entry* entry);
+extern zzip_size_t zzip_disk_entry_namlen( zzip_disk_entry* entry);
+extern zzip_size_t zzip_disk_entry_extras( zzip_disk_entry* entry);
+extern zzip_size_t zzip_disk_entry_comment( zzip_disk_entry* entry);
+extern int zzip_disk_entry_diskstart( zzip_disk_entry* entry);
+extern int zzip_disk_entry_filetype( zzip_disk_entry* entry);
+extern int zzip_disk_entry_filemode( zzip_disk_entry* entry);
+
+extern zzip_off_t zzip_disk_entry_fileoffset( zzip_disk_entry* entry);
+extern zzip_size_t zzip_disk_entry_sizeof_tail( zzip_disk_entry* entry);
+extern zzip_size_t zzip_disk_entry_sizeto_end( zzip_disk_entry* entry);
+extern char* zzip_disk_entry_skipto_end( zzip_disk_entry* entry);
+</PRE>
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/future.htm b/Build/source/libs/zziplib/docs/future.htm
new file mode 100644
index 00000000000..e116429abb1
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/future.htm
@@ -0,0 +1,80 @@
+<?xml-stylesheet type="text/css" href="sdocbook.css" ?>
+<section> <date> 15. July 2002 </date>
+<h2> ZZIP Future </h2> What next to come.
+
+<section><!--border-->
+<h3> ZIP-Write </h3>
+
+<P>
+ Anybody out there who wants to program the write-support for the
+ zziplib? Actually, I just do not have the time to do it and no
+ real need to but I guess it would be nice for people as for
+ example to spit out savegame files in zipformat. The actual
+ programming path is almost obvious - start off with the zziplib
+ as it is, and let it open an existing zip-file. This will parse
+ the central directory into memory - including the file-offsets
+ for each file. Then, truncate the zip-realfile to the place that
+ the central-dir was found (identical with the end of the last
+ file). If a datafile is opened for writing, either add a new
+ entry or modify the start-offset of the existing entry to the
+ end of the zip-realfile - the old data is simply junk. Then
+ init zlib to do the deflation of the data and append it to the
+ current zip-realfile. When the zipdir-handle is getting closed
+ from write-mode, the zip's central-directory needs to be appended
+ to the file on disk. This coincides with creating a new zip-file
+ with an empty central-directory that can be spit out to disk.
+ During development, do not care about creating temp-files to
+ guard against corruption for partial writes - the usual application
+ will use the zziplib to create zip savegames in one turn, no
+ "update"-operation needs to be implemented like exists in the
+ standalone zip command utilities.
+</P>
+
+</section><section>
+<h3> readdir for subdir inside zip magicdir </h3>
+
+<P>
+ See the notes in the first paragraphs of <a href="zzip-api.html">
+ ZZIP Programmers Interface</a> description. It would add some
+ complexity for something I never needed so far. The question
+ came up with using zziplib as the backend of a dynamic webserver
+ to store the content in compressed form possibly through the
+ incarnation of a php module - and some scripted functionality
+ that walks all directories to index the files hosted. I'm not
+ going to implement that myself but perhaps someone else wants
+ to do it and send me patches for free.
+</P>
+
+</section><section>
+<h3> obfuscation example project </h3>
+
+<P>
+ A subproject that shows <b>all</b> the steps from a dat-tree
+ to a dat-zip to an obfuscated-dat along with build-files and
+ source-files for all helper tools needed to obfuscate and
+ deobfuscate, plus a sample program to use the obfuscated
+ dat-file and make some use of it. Along with some extra
+ documentation about 20..40 hours. Don't underestimate the
+ amount of work for it! (otherwise a great student project).
+</P>
+
+</section><section>
+<h3> zip/unzip tool </h3>
+
+<P>
+ The infozip tools implement a full set of zip/unzip routines
+ based on internal code to access the zip-format. The zziplib
+ has its own set of zip-format routines. Still, it should be
+ possible to write a frontend to the library that implements
+ parts (if not all) of the options of the infozip zip/unzip
+ tools. Even without write-support in zziplib it would be
+ interesting to see an normal unzip-tool that does not use
+ the magic-wrappers thereby only going off at plain zip-files.
+ On the upside, such a tool would be smaller than the infozip
+ tools since it can use the library routines that are shared
+ with other tools as well. Again - don't underestimate the
+ amount of work for it, I guess 40..80 hours as there is a lot
+ of fine-tuning needed to match the infozip model.
+</P>
+</section>
+</section>
diff --git a/Build/source/libs/zziplib/docs/history.htm b/Build/source/libs/zziplib/docs/history.htm
new file mode 100644
index 00000000000..7250729e877
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/history.htm
@@ -0,0 +1,92 @@
+<section><date>created 1.Jun.2000, last updated 25.Apr.2002 </date>
+<h2> History and Links </h2> plus Installation and Contact Hints
+
+<!--border-->
+
+<section>
+<h3> A Bit Of History </h3>
+
+<P>
+You'll find <a href="http://www.gzip.org">gzip</a> using the same compression
+that was written by Jean-loup <a href="http://gailly.net">Gailly</a>
+for the <a href="http://www.info-zip.org">Info-Zip</a> Group
+whose <a href="http://www.info-zip.org/pub/infozip/Zip.html">Zip</a>
+program is compatible with msdos PKZIP program from
+<a href="http://www.pkware.com">PK&nbsp;Ware</a>. Then, in collaboration
+with <a href="http://www.alumni.caltech.edu/~madler">Mark Adler</a>
+he wrote the <a href="http://www.gzip.org/zlib">zlib</a>
+compression library which was later standardized in the
+<a href="ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html">
+zlib RFCs</a>, namely
+<a href="http://www.ietf.org/rfc/rfc1950.txt">RFC 1950</a>
+<a href="ftp://ftp.uu.net/graphics/png/documents/zlib/rfc-zlib.html.Z">
+zlib&nbsp;3.3</a>,
+<a href="http://www.ietf.org/rfc/rfc1951.txt">RFC 1951</a>
+<a href="ftp://ftp.uu.net/graphics/png/documents/zlib/rfc-deflate.html.Z">
+deflate&nbsp;1.3</a> and
+<a href="http://www.ietf.org/rfc/rfc1952.txt">RFC 1952</a>
+<a href="ftp://ftp.uu.net/graphics/png/documents/zlib/rfc-gzip.html">
+gzip&nbsp;4.3</a>. The free algorithm can be found in lots of places
+today including PPP packet compression and PNG picture compression.
+</P>
+
+</section><section>
+<h3> Installation </h3>
+
+<P>
+ The installation is from the source .tar.gz tarball does follow
+ the simple gnu style: type <tt>''configure && make install''</tt>
+ in the unpacked directory. This will actually perform the usual
+ sequence of <tt>''configure && make && make install''</tt>. The
+ use of <tt>''make rpm''</tt> will make rpms based on your system
+ setup, and using a decent mingw32 compiler (e.g. the crossgcc
+ from <a href="http://libsdl.org/Xmingw32">libsdl.org/Xmingw32</a>)
+ will allow you to create windows dlls using a gnu development
+ environment. MSVC and Borland support (Make-)files should be
+ easy to be derived from the <a href="Makefile.am">Makefile.am</a>
+</P>
+
+</section><section>
+<h3> Contact </h3>
+
+<P>
+ The library was developed by
+ <a href="mailto:guidod@gmx.de?subject=zziplib">
+ Guido Draheim </a> based on the library
+ <a href="http://freshmeat.net/appindex/1999/08/02/933593367.html">
+ <tt>zip08x</tt> </a>
+ by <a href="mailto:too@iki.fi"> Tomi Ollila </a> (many thanks
+ for his support of the zziplib project). He has provided
+ a good deal of testing rounds and very helpful comments.
+ It may be assumed that this library supersedes
+ <a href="http://www.iki.fi/too/sw/zip08x.readme">
+ <tt>zip08x</tt></a>, and in April 2002, he
+ has even given up copyright restrictions coming from zip08x
+ and changed the <a href="http://www.iki.fi/too/sw/zip08x.readme">zip08x</a>
+ readme to point to <a href="http://zziplib.sf.net">zziplib</a>.
+ Anyone who wants to contribute in accessing zip-archives
+ with the zlib-library is hereby kindly invited to send us
+ comments and sourcecode.
+</P>
+
+</section><section>
+<h3> Links </h3>
+
+<P>
+The <a href="zziplib.html">zziplib library</a> must be
+linked with the free <b><a href="http://www.gzip.org/zlib/">zlib</a></b>
+<a href="http://www.info-zip.org/pub/infozip/zlib">[1]</a>
+<a href="http://www.lifl.fr/PRIVATE/Manuals/gnulang/zlib">[2]</a>
+<a href="http://pobox.com/~newt">[3]</a> package originally developed
+by the <a href="http://www.info-zip.org">Info-Zip</a> Group
+and now maintained at the <a href="http://www.gzip.org">GZip</a> Group.
+As of late, the pkware appnote.txt has been revised into a whitepaper
+document named
+<a href="http://www.pkware.com/products/enterprise/white_papers/appnote.html">
+ "APPNOTE.TXT - .ZIP File Format Specification"</a>.
+Be also aware of other zzip like projects, e.g.
+<a href="http://zipios.sourceforge.net">zipios++</a> that
+mangles zip access into C++ iostream facilities.
+</P>
+
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/make-dbk.pl b/Build/source/libs/zziplib/docs/make-dbk.pl
new file mode 100644
index 00000000000..e1fe56683df
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/make-dbk.pl
@@ -0,0 +1,118 @@
+#! /usr/local/bin/perl
+# this file converts simple html text into a docbook xml variant.
+# The mapping of markups and links is far from perfect. But all we
+# want is the docbook-to-pdf converter and similar technology being
+# present in the world of docbook-to-anything converters.
+
+use strict;
+
+my %o;
+
+my %file;
+my $F;
+my @order;
+
+for $F (@ARGV)
+{
+ if ($F =~ /^(\w+)=(.*)/)
+ {
+ $o{$1} = $2;
+ }else{
+ open F, "<$F" or next;
+ my $T = join ("",<F>); close F;
+ $file{$F}{text} = $T;
+ $file{$F}{orig} = $F;
+ push @order, $F;
+ }
+}
+
+$o{version} = `date` if not length $o{version};
+
+for $F (keys %file)
+{
+ $_ = $file{$F}{text};
+ s{<!--VERSION-->}{ $o{version} }gse;
+ s{</h2>(.*)}{</title>\n<subtitle>$1</subtitle>}mg;
+ s{<h2>}{<sect1 id=\"$F\"><title>}mg;
+ s{<[Pp]([> ])}{<para$1}mg; s{</[Pp]>}{</para>}mg;
+ s{<pre>}{<screen>}mg; s{</pre>}{</screen>}mg;
+ s{<h3>}{<sect2><title>}mg;
+ s{</h3>((?:.(?!<sect2>))*.?)}{</title>$1</sect2>}sg;
+ s{<!doctype [^<>]*>}{}sg;
+ s{<!DOCTYPE [^<>]*>}{}sg;
+ s{(<\w+\b[^<>]*\swidth=)(\d+\%)}{$1\"$2\"}sg;
+ s{(<\w+\b[^<>]*\s\w+=)(\d+)}{$1\"$2\"}sg;
+ s{&&}{\&amp\;\&amp\;}sg;
+ s{\$\<}{\$\&lt\;}sg;
+ s{&(\w+[\),])}{\&amp\;$1}sg;
+ s{(</?)span(\s[^<>]*)?>}{$1."phrase$2>"}sge;
+ s{(</?)small(\s[^<>]*)?>}{$1."note$2>"}sge;
+ s{(</?)(b|em|i)>}{$1."emphasis>"}sge;
+ s{(</?)(li)>}{$1."listitem>"}sge;
+ s{(</?)(ul)>}{$1."itemizedlist>"}sge;
+ s{(</?)(ol)>}{$1."orderedlist>"}sge;
+ s{(</?)(dl)>}{$1."variablelist>"}sge;
+ s{<dt\b([^<>]*)>}{"<varlistentry$1><term>"}sge;
+ s{</dt\b([^<>]*)>}{"</term>"}sge;
+ s{<dd\b([^<>]*)>}{"<listitem$1>"}sge;
+ s{</dd\b([^<>]*)>}{"</listitem></varlistentry>"}sge;
+ s{<table\b([^<>]*)>}{"<informaltable$1><tgroup cols=\"2\"><tbody>"}sge;
+ s{</table\b([^<>]*)>}{"</tbody></tgroup></informaltable>"}sge;
+ s{(</?)tr(\s[^<>]*)?>}{$1."row$2>"}sge;
+ s{(</?)td(\s[^<>]*)?>}{$1."entry$2>"}sge;
+ s{<informaltable\b[^<>]*>\s*<tgroup\b[^<>]*>\s*<tbody>
+ \s*<row\b[^<>]*>\s*<entry\b[^<>]*>\s*<informaltable\b}
+ {<informaltable}gsx;
+ s{</informaltable>\s*</entry>\s*</row>
+ \s*</tbody>\s*</tgroup>\s*</informaltable>}
+ {</informaltable>}gsx;
+ s{(<informaltable[^<>]*\swidth=\"100\%\")}{$1 pgwide=\"1\"}gs;
+ s{(<tbody>\s*<row[^<>]*>\s*<entry[^<>]*\s)(width=\"50\%\")}
+ {<colspec colwidth=\"1*\" /><colspec colwidth=\"1*\" />\n$1$2}gs;
+
+ s{<nobr>([\'\`]*)<tt>}{<cmdsynopsis>$1}sg;
+ s{</tt>([\'\`]*)</nobr>}{$2</cmdsynopsis>}sg;
+ s{<nobr><(?:tt|code)>([\`\"\'])}{<cmdsynopsis>$1}sg;
+ s{<(?:tt|code)><nobr>([\`\"\'])}{<cmdsynopsis>$1}sg;
+ s{([\`\"\'])</(?:tt|code)></nobr>}{$1</cmdsynopsis>}sg;
+ s{([\`\"\'])</nobr></(?:tt|code)>}{$1</cmdsynopsis>}sg;
+ s{(</?)tt>}{$1."constant>"}sge;
+ s{(</?)code>}{$1."literal>"}sge;
+ s{>([^<>]+)<br>}{><highlights>$1</highlights>}sg;
+ s{<br>}{<br />}sg;
+
+ s{(</?)date>}{$1."sect1info>"}sge;
+ s{<reference>}{<reference id=\"reference\">}s;
+
+ s{<a\s+href=\"((?:http|ftp|mailto):[^<>]+)\"\s*>((?:.(?!</a>))*.)</a>}
+ { "<ulink url=\"$1\">$2</ulink>" }sge;
+ s{<a\s+href=\"zziplib.html\#([\w_]+)\"\s*>((?:.(?!</a>))*.)</a>}
+ { "<link linkend=\"$1\">$2</link>" }sge;
+ s{<a\s+href=\"(zziplib.html)\"\s*>((?:.(?!</a>))*.)</a>}
+ { "<link linkend=\"reference\">$2</link>" }sge;
+ s{<a\s+href=\"([\w-]+[.]html)\"\s*>((?:.(?!</a>))*.)</a>}
+ { my $K = $1; chop $K;
+ if (not exists $file{$K}) { print STDERR "bad link $1\n"; }
+ "<link linkend=\"$K\">$2</link>" }sge;
+ s{<a\s+href=\"([\w-]+[.](?:h|c|am|txt))\"\s*>((?:.(?!</a>))*.)</a>}
+ { "<ulink url=\"file:$1\">$2</ulink>" }sge;
+ s{<a\s+href=\"([A-Z0-9]+[.][A-Z0-9]+)\"\s*>((?:.(?!</a>))*.)</a>}
+ { "<ulink url=\"file:$1\">$2</ulink>" }sge;
+
+# s{(</?)subtitle>}{$1."para>"}ge;
+
+ $_ .= "</sect1>" if /<sect1[> ]/;
+ $file{$F}{text} = $_;
+}
+
+my $n = "\n";
+
+print '<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"',$n;
+print ' "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">',$n;
+print '<book><chapter><title>Documentation</title>',$n;
+for $F (@order)
+{
+ print "</chapter>" if $file{$F}{text} =~ /<reference /;
+ print $file{$F}{text},$n,$n;
+}
+print '</book>',$n;
diff --git a/Build/source/libs/zziplib/docs/make-doc.pl b/Build/source/libs/zziplib/docs/make-doc.pl
new file mode 100644
index 00000000000..89da2f6a95c
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/make-doc.pl
@@ -0,0 +1,580 @@
+
+use strict "vars";
+
+my $x;
+my $F;
+my @regs;
+my %file;
+my %func;
+
+my %o = ( verbose => 0 );
+
+$o{version} =
+ `grep -i "^version *:" *.spec | sed -e "s/[Vv]ersion *: *//"`;
+$o{package} =
+ `grep -i "^name *:" *.spec | sed -e "s/[Nn]ame *: *//"`;
+$o{version} =~ s{\s*}{}gs;
+$o{package} =~ s{\s*}{}gs;
+
+$o{version} = `date +%Y.%m.%d` if not length $o{version};
+$o{package} = "_project" if not length $o{package};
+
+$o{suffix} = "-doc1";
+$o{mainheader} = "$o{package}.h";
+
+my %fn;
+my $id = 1000;
+
+for $F (@ARGV)
+{
+ if ($F =~ /^(\w+)=(.*)/)
+ {
+ $o{$1} = $2;
+ }else{
+ open F, "<$F" or next;
+ my $T = join ("",<F>); close F;
+
+ $T =~ s/\&/\&amp\;/sg;
+ $T =~ s/¬/\&#AC\;/sg;
+ $T =~ s/\*\//¬/sg;
+
+ # cut per-function comment block
+ while ( $T =~
+ s{ [/][*][*](?=\s) ([^¬]+) ¬ ([^\{\}\;\#]+) [\{\;] }
+ { per_function_comment_and_declaration($F," ".$1,$2) }gsex
+ ) {}
+
+ # cut per-file comment block
+ if ( $T =~ m{ ^ [/][*]+(?=\s) ([^¬]+) ¬
+ (\s*\#include\s*<[^<>]*>(?:\s*/[/*][^\n]*)?) }sx)
+ {
+ $file{$F}{comment} = $1;
+ $file{$F}{include} = $2;
+ $file{$F}{comment} =~ s/¬/\*\//sg;
+ $file{$F}{include} =~ s/¬/\*\//sg;
+ $file{$F}{include} =~ s{[/][*]}{//}s;
+ $file{$F}{include} =~ s{[*][/]}{\n}s;
+ $file{$F}{include} =~ s{<}{\&lt\;}sg;
+ $file{$F}{include} =~ s{>}{\&gt\;}sg;
+ }
+ elsif ( $T =~ m{ ^ [/][*]+(?=\s) ([^¬]+) ¬ }sx)
+ {
+ $file{$F}{comment} = $1;
+ $file{$F}{comment} =~ s/¬/\*\//sg;
+ }
+
+ # throw away the rest - further processing on memorized strings only
+ }
+}
+
+$o{outputfilestem}= "$o{package}$o{suffix}" if not length $o{outputfilestem};
+$o{docbookfile}= "$o{outputfilestem}.docbook" if not length $o{docbookfile};
+$o{libhtmlfile}= "$o{outputfilestem}.html" if not length $o{libhtmlfile};
+$o{dumpdocfile}= "$o{outputfilestem}.dxml" if not length $o{dumpdocfile};
+
+sub per_function_comment_and_declaration
+{
+ my ($filename, $comment, $prototype) = @_;
+
+ $prototype =~ s{¬}{*/}sg;
+ $comment =~ s{¬}{*/}sg;
+ $comment =~ s{<([\w\.\-]+\@[\w\.\-]+\w\w)>}{&lt;$1&gt;}sg;
+ $func{$id}{filename} = $filename;
+ $func{$id}{comment} = $comment;
+ $func{$id}{prototype} = $prototype;
+ $id ++;
+ return $prototype;
+}
+# -----------------------------------------------------------------------
+sub pre { # used for non-star lines in comment blocks
+ my $T = $_[0]; $T =~ s/\&/\&amp\;/g;
+ $T =~ s/\</\&lt\;/g; $T =~ s/\>/\&gt\;/g; $T =~ s/\"/\&quot\;/g;
+ $T =~ s/^/\ /gm; # $T =~ s/^/\| /gm;
+ return " <pre> $T </pre> ";
+}
+
+# per-file comment block handling
+my $name;
+for $name (keys %file)
+{
+ $file{$name}{comment} =~ s{<([\w\.\-]+\@[\w\.\-]+\w\w)>}{&lt;$1&gt;}sg;
+ $file{$name}{comment} =~ s{ ^\s?\s?\s? ([^\*\s]+ .*) $}{&pre($1)}mgex;
+ $file{$name}{comment} =~ s{ ^\s*[*]\s* $}{ <p> }gmx;
+ $file{$name}{comment} =~ s{ ^\s?\s?\s?\* (.*) $}{ $1 }gmx;
+ $file{$name}{comment} =~ s{ </pre>(\s*)<pre> }{$1}gsx;
+ $file{$name}{comment} =~ s{ <([^<>\;]+\@[^<>\;]+)> }{<email>$1</email>}gsx;
+ $file{$name}{comment} =~ s{ \&lt\;([^<>\&\;]+\@[^<>\&\;]+)\&gt\; }
+ {<email>$1</email>}gsx;
+ $file{$name}{comment} .= "<p>";
+
+ $file{$name}{comment} =~ s{ \b[Aa]uthor\s*:(.*<\/email>) }
+ {
+ $file{$name}{author} = "$1";
+ "<author>"."$1"."</author>"
+ }sex;
+
+ $file{$name}{comment} =~ s{ \b[Cc]opyright[\s:]([^<>]*)<p> }
+ {
+ $file{$name}{copyright} = "$1";
+ "<copyright>"."$1"."</copyright>"
+ }sex;
+# if ($name =~ /file/) {
+# print STDERR $file{$name}{comment},"\n";
+# }
+ if ($file{$name}{include} =~ m{//\s*(\w+)[.][.][.]\s*})
+ {
+ if (length $o{$1}) {
+ $file{$name}{include} = "#include "
+ .$o{$1}."\n";
+ $file{$name}{include} =~ s{<}{\&lt\;}sg;
+ $file{$name}{include} =~ s{>}{\&gt\;}sg;
+ }
+ }
+}
+
+# -----------------------------------------------------------------------
+
+# pass 1 of per-func strings:
+# (a) cut prototype into prespec/namespec/callspec
+# (b) sanitize comment-block into proper docbook format
+# do this while copying strings from $func{$name} to $fn{name} strstrhash
+my @namelist;
+for $x (sort keys %func)
+{
+ my $name = $func{$x}{prototype};
+ $name =~ s/^.*[^.]\b(\w[\w.]*\w)\b\s*\(.*$/$1/s;
+ push @namelist, $name; # may be you want to omit some funcs from output?
+
+ $func{$x}{prototype} =~ m{ ^(.*[^.]) \b(\w[\w.]*\w)\b (\s*\(.*) $ }sx;
+ $fn{$name}{prespec} = $1;
+ $fn{$name}{namespec} = $2;
+ $fn{$name}{callspec} = $3;
+
+ $fn{$name}{comment} = $func{$x}{comment};
+ $fn{$name}{comment} =~ s/(^|\s)\=\>\"([^\"]*)\"/$1<link>$2<\/link>/gmx;
+ $fn{$name}{comment} =~ s/(^|\s)\=\>\'([^\"]*)\'/$1<link>$2<\/link>/gmx;
+ $fn{$name}{comment} =~ s/(^|\s)\=\>\s(\w[\w.]*\w)\b/$1<link>$2<\/link>/gmx;
+ $fn{$name}{comment} =~
+ s/(^|\s)\=\>\s([^\s\,\.\!\?\:\;\<\>\&\'\=\-]+)/$1<link>$2<\/link>/gmx;
+
+ # cut comment in first-line (describe) and only keep the rest in comment
+ $fn{$name}{describe} = $fn{$name}{comment};
+ $fn{$name}{describe} =~ s{^([^\n]*\n).*}{$1}gs;
+ $fn{$name}{comment} =~ s{^[^\n]*\n}{}gs;
+ if ($fn{$name}{describe} =~ /^\s*$/s)
+ {
+ $fn{$name}{describe} = "(".$func{$x}{filename}.")";
+ $fn{$name}{describe} =~ s,[.][.][/],,g;
+ }
+
+ $fn{$name}{comment} =~ s/ ^\s?\s?\s? ([^\*\s]+ .*) $/&pre($1)/mgex;
+ $fn{$name}{comment} =~ s/ ^\s?\s?\s?\* (.*) $/ <br \/> $1 /gmx;
+ $fn{$name}{comment} =~ s/ ^\s*<br\s*\/>\s* $/ <p> /gmx;
+ $fn{$name}{comment} =~ s{<<}{&lt;}sg;
+ $fn{$name}{comment} =~ s{>>}{&gt;}sg;
+ $fn{$name}{comment} =~ s/ (<p>\s*)<br\s*\/?>/$1/gsx;
+ $fn{$name}{comment} =~ s/ (<p>\s*)<br\s*\/?>/$1/gsx;
+ $fn{$name}{comment} =~ s/ (<br\s*\/?>\s*)<br\s*\/?>/$1/gsx;
+ $fn{$name}{comment} =~ s/<c>/<code>/gs;
+ $fn{$name}{comment} =~ s/<\/c>/<\/code>/gs;
+ $fn{$name}{comment} =~ s/<\/pre>(\s*)<pre>/$1/gs;
+
+ $fn{$name}{filename} = $func{$x}{filename};
+ $fn{$name}{callspec} =~ s{^ \s*}{}gsx;
+ $fn{$name}{prespec} =~ s{^ \s*}{}gsx;
+ $fn{$id} = $x;
+}
+
+# add extra docbook markups to callspec in $fn-hash
+for $name (@namelist) # <paramdef>
+{
+ $fn{$name}{callspec} =~ s:^([^\(\)]*)\(:$1<parameters>\(<paramdef>:s;
+ $fn{$name}{callspec} =~ s:\)([^\(\)]*)$:</paramdef>\)</parameters>$1:s;
+ $fn{$name}{callspec} =~ s:,:</paramdef>,<paramdef>:gs;
+ $fn{$name}{callspec} =~ s:<paramdef>(\s+):$1<paramdef>:gs;
+ $fn{$name}{callspec} =~ s:(\s+)</paramdef>:</paramdef>$1:gs;
+}
+
+# html-formatting of callspec strings
+for $name (@namelist)
+{
+ $fn{$name}{declcode} =
+ "<td valign=\"top\"><code>".$fn{$name}{prespec}."<\/code><\/td>"
+ ."<td valign=\"top\">&nbsp;&nbsp;</td>"
+ ."<td valign=\"top\"><a href=\"#$name\">"
+ ."\n <code>".$fn{$name}{namespec}."<\/code>\n"
+ ."<\/a><\/td>"
+ ."<td valign=\"top\">&nbsp;&nbsp;</td>"
+ ."<td valign=\"top\">".$fn{$name}{callspec}."<\/td>";
+
+ $fn{$name}{implcode} =
+ "<code>".$fn{$name}{prespec}."<\/code>"
+ ."\n <br \/><b><code>".$fn{$name}{namespec}."<\/code><\/b>"
+ ."\n &nbsp; <code>".$fn{$name}{callspec}."<\/code>";
+
+ $fn{$name}{declcode} =~ s{\s+<paramdef>}{\n<nobr>}gs;
+ $fn{$name}{implcode} =~ s{\s+<paramdef>}{\n<nobr>}gs;
+ $fn{$name}{declcode} =~ s{<paramdef>}{<nobr>}gs;
+ $fn{$name}{implcode} =~ s{<paramdef>}{<nobr>}gs;
+ $fn{$name}{declcode} =~ s{</paramdef>}{</nobr>}gs;
+ $fn{$name}{implcode} =~ s{</paramdef>}{</nobr>}gs;
+ $fn{$name}{declcode} =~ s{<parameters>}{\n <code>}gs;
+ $fn{$name}{implcode} =~ s{<parameters>}{\n <code>}gs;
+ $fn{$name}{declcode} =~ s{</parameters>}{</code>\n}gs;
+ $fn{$name}{implcode} =~ s{</parameters>}{</code>\n}gs;
+}
+
+# whether each function should get its own page or combined with others
+my $combinedstyle = 1;
+
+for $name (@namelist)
+{
+ if ($fn{$name}{describe} =~ /^ \s* <link>(\w[\w.]*\w)<\/link> /sx)
+ {
+ if ($combinedstyle and exists $fn{$1})
+ {
+ # $into tells later steps which func-name is the leader of a man
+ # page and that this func should add its descriptions over there.
+ $fn{$name}{into} = $1;
+ }
+ }
+
+ if ($fn{$name}{describe} =~ s/(.*)also:(.*)/$1/)
+ {
+ $fn{$name}{_seealso} = $2;
+ }
+
+ # and prepare items for being filled in $combinedstyle (html-mode)
+ # which includes adding descriptions of the leader functions firsthand
+ $fn{$name}{_anchors} = "<a name=\"$name\" />";
+ $fn{$name}{_impcode} = "<code>".$fn{$name}{implcode}."</code>";
+ $fn{$name}{_comment} = "<p> &nbsp;".$fn{$name}{describe}."\n";
+ $fn{$name}{_comment} .= "<p>".$fn{$name}{comment};
+}
+
+for $name (@namelist) # and add descriptions of non-leader entries (html-mode)
+{
+ next if not exists $fn{$name}{into}; # skip leader pages
+ my $into = $fn{$name}{into};
+ $fn{$into}{_anchors} .= "<a name=\"$name\" />";
+ $fn{$into}{_impcode} .= "<br />\n";
+ $fn{$into}{_impcode} .= "<code>".$fn{$name}{implcode}."</code>";
+ my $text = $fn{$name}{comment};
+ $text =~ s/ (T|t)his \s (function|procedure) /$1."he ".$name." ".$2/gsex;
+ $fn{$name}{_comment} .= "<p>".$text;
+}
+
+my $htmlTOC = "";
+my $htmlTXT = "";
+
+# generate the index-block at the start of the onepage-html file
+for $name (@namelist)
+{
+ $fn{$name}{_comment} =~ s/ (<p>\s*)<br\s*\/>/$1/gsx;
+
+ $htmlTOC .= "<tr valign=\"top\">\n".$fn{$name}{declcode}."</tr>";
+ next if $combinedstyle and exists $fn{$name}{into};
+
+ $htmlTXT .= "\n<dt>".$fn{$name}{_anchors}.$fn{$name}{_impcode}."<dt>";
+ $htmlTXT .= "\n<dd>".$fn{$name}{_comment};
+ $htmlTXT .= "\n<p align=\"right\"><small>("
+ .$fn{$name}{filename}.")</small></p></dd>";
+}
+
+# link ref-names in this page with its endpoints on the same html page
+$htmlTXT =~ s/ <link>(\w+)([^<>]*)<\/link> / &a_name($1,$2) /gsex;
+sub a_name
+{
+ my ($n,$m) = @_;
+ if (exists $fn{$n}) { return "<a href=\"#$n\"><code>$n$m</code></a>"; }
+ else { return "<code>$n$m</code>"; }
+}
+$htmlTXT =~ s/ \-\> /<small>-\&gt\;<\/small>/gsx; # just sanitize
+
+# and finally print the html-formatted output
+open F, ">$o{libhtmlfile}" or die "could not open '$o{libhtmlfile}': $!";
+print F "<html><head><title> $o{package} autodoc documentation </title>";
+print F "</head>\n<body>\n";
+print F "\n<h1>",$o{package}," <small><small><i>-", $o{version};
+print F "</i></small></small></h1>";
+print F "\n<table border=0 cellspacing=2 cellpadding=0>";
+print F $htmlTOC;
+print F "\n</table>";
+print F "\n<h3>Documentation</h3>\n";
+print F "\n<dl>";
+print F $htmlTXT;
+print F "\n</dl>";
+print F "\n</body></html>\n";
+close F;
+
+# =========================================================================== #
+# let's go for the pure docbook, a reference type master file for all man pages
+my @headerlist; # leader function pages - a file will be created for each of th
+my @mergedlist; # non-leader function that end up in one of those in headerlist
+
+for $name (@namelist)
+{
+ push @headerlist, $name if not exists $fn{$name}{into};
+ push @mergedlist, $name if exists $fn{$name}{into};
+
+ # and initialize the fields need for a man page entry - the fields are
+ # named after the docbook-markup that encloses (!!) the text we store
+ # in the strstrhash - therefore, {}{_refhint} = "hello" will be printed
+ # as <refhint>hello</refhint>. Names with scores at the end are only used
+ # as temporaries but they are memorized - perhaps they are useful later.
+
+ $fn{$name}{_refhint} =
+ "\n<!--========= ".$name." (3) ===========-->\n";
+ $fn{$name}{_refstart} = "";
+ $fn{$name}{_date_} = $o{version};
+ $fn{$name}{_date_} =~ s{\s*}{}gs;
+ $fn{$name}{_refentryinfo}
+ = "\n <date>".$fn{$name}{_date_}."</date>";
+ $fn{$name}{_productname_} = $o{package};
+ $fn{$name}{_productname_} =~ s{\s*}{}gs;
+ $fn{$name}{_refentryinfo}
+ .= "\n <productname>".$fn{$name}{_productname_}."</productname>";
+# if (exists $file{ $fn{$name}{filename} }{author})
+# {
+# $H = $file{ $fn{$name}{filename} }{author};
+# $H =~ s{ \s* ([^<>]*) (<email>[^<>]*</email>) }{
+# $fn{$name}{_refentryinfo} .= "\n <author>".$1.$2."</author>";
+# "" }gmex;
+# }
+ $fn{$name}{_refmeta} = "";
+ $fn{$name}{_refnamediv} = "";
+ $fn{$name}{_mainheader} = $o{mainheader};
+ $fn{$name}{_includes} = $file{ $fn{$name}{filename} }{include};
+ $fn{$name}{_manvolnum} = "3";
+ $fn{$name}{_funcsynopsisinfo} = "";
+ $fn{$name}{_funcsynopsis} = "";
+ $fn{$name}{_description} = "";
+ $fn{$name}{_refends} = "";
+}
+
+push @headerlist, @mergedlist; # aaahmm...
+
+# let's walk all (!!) entries...
+for $name (@headerlist)
+{
+ # $into is the target-manpage to add descriptions to. Initially it does
+ # reference the name of the function itself - but it overridden in the
+ # next line when we see an {into} mark. The self/into state is registered
+ # in two vars: $into is an index into %fn-strstrhash to be used instead of
+ # the $name-runvar and $me just a boolean value to conditionally add texts
+ my $into = $name; my $me = 1;
+
+ if (exists $fn{$name}{into})
+ {
+ $into = $fn{$name}{into}; $me = 0;
+ $fn{$name}{_refhint} =
+ "\n <!-- see ".$fn{$name}{mergeinto}." -->\n";
+ }
+
+ $fn{$into}{_refstart} .= '<refentry id="'.$name.'">' if $me;
+ $fn{$into}{_refends} .= "\n</refentry>\n" if $me;
+
+ $fn{$name}{_title_} = $name;
+ $fn{$name}{_title_} =~ s{\s*}{}gs;
+ $fn{$name}{_refentryinfo}
+ .= "\n <title>".$fn{$name}{_title_}."</title>" if $me;
+ $fn{$into}{_refmeta}
+ .= "\n <manvolnum>".$fn{$name}{_manvolnum}."</manvolnum>" if $me;
+ $fn{$into}{_refmeta}
+ .= "\n <refentrytitle>".$name."</refentrytitle>" if $me;
+
+ $fn{$name}{_funcsynopsisinfo}
+ = "\n".' #include &lt;'.$fn{$into}{_mainheader}.'&gt;' if $me;
+ $fn{$name}{_funcsynopsisinfo}
+ = "\n".$fn{$into}{_includes} if $me and length $fn{$into}{_includes};
+ $fn{$name}{_funcsynopsisinfo}
+ .= " // ".$o{synopsis} if $me and length $o{synopsis};
+
+ $fn{$into}{_refnamediv} .= "\n ".
+ "<refpurpose>".$fn{$name}{describe}." </refpurpose>" if $me;
+ $fn{$into}{_refnamediv} .= "\n".' <refname>'.$name.'</refname>';
+
+ # add to {}{_funcsynopsis}...
+ $fn{$into}{_funcsynopsis} .= "\n <funcprototype>\n <funcdef>";
+ $fn{$into}{_funcsynopsis} .= $fn{$name}{prespec}
+ ." <function>".$name."</function></funcdef>";
+ $fn{$name}{_callspec_} = $fn{$name}{callspec};
+ $fn{$name}{_callspec_} =~ s{<parameters>\s*\(}{ }gs;
+ $fn{$name}{_callspec_} =~ s{\)\s*</parameters>}{ }gs;
+ $fn{$name}{_callspec_} =~ s{</paramdef>\s*,\s*}{</paramdef>\n }gs;
+ $fn{$into}{_funcsynopsis}
+ .= "\n".$fn{$name}{_callspec_}." </funcprototype>";
+
+ # add to {}{_description}...
+ $fn{$name}{_comment_} = "<para>\n".$fn{$name}{comment}."\n</para>";
+ $fn{$name}{_comment_} =~ s{ (T|t)his \s (function|procedure) }
+ { $1."he <function>".$name."</function> ".$2 }gsex;
+ $fn{$name}{_comment_} =~ s{<p>}{"\n</para><para>\n"}gsex;
+ $fn{$name}{_comment_} =~ s{<br\s*/?>}{}gs;
+ $fn{$name}{_comment_} =~ s{(</?)em>}{$1emphasis>}gs;
+ $fn{$name}{_comment_} =~ s{<code>}{<userinput>}gs;
+ $fn{$name}{_comment_} =~ s{</code>}{</userinput>}gs;
+ $fn{$name}{_comment_} =~ s{<link>}{<function>}gs;
+ $fn{$name}{_comment_} =~ s{</link>}{</function>}gs;
+ $fn{$name}{_comment_} =~ s{<pre>}{<screen>}gs; # only xmlto .8 and
+ $fn{$name}{_comment_} =~ s{</pre>}{</screen>}gs; # higher !!
+# $fn{$name}{_comment_} =~ s{<ul>}{</para><itemizedlist>}gs;
+# $fn{$name}{_comment_} =~ s{</ul>}{</itemizedlist><para>}gs;
+# $fn{$name}{_comment_} =~ s{<li>}{<listitem><para>}gs;
+# $fn{$name}{_comment_} =~ s{</li>}{</para></listitem>\n}gs;
+ $fn{$name}{_comment_} =~ s{<ul>}{</para><programlisting>\n}gs;
+ $fn{$name}{_comment_} =~ s{</ul>}{</programlisting><para>}gs;
+ $fn{$name}{_comment_} =~ s{<li>}{}gs;
+ $fn{$name}{_comment_} =~ s{</li>}{}gs;
+ $fn{$into}{_description} .= $fn{$name}{_comment_};
+
+ if (length $fn{$name}{_seealso} and not $me)
+ {
+ $fn{$into}{_seealso} .= ", " if length $fn{$into}{_seealso};
+ $fn{$into}{_seealso} .= $fn{$name}{_seealso};
+ }
+
+ if (exists $file{ $fn{$name}{filename} }{author})
+ {
+ my $authors = $file{ $fn{$name}{filename} }{author};
+ $fn{$into}{_authors} = "<itemizedlist>";
+ $authors =~ s{ \s* ([^<>]*) (<email>[^<>]*</email>) }{
+ $fn{$into}{_authors}
+ .= "\n <listitem><para>".$1." ".$2."</para></listitem>";
+ "" }gmex;
+ $fn{$into}{_authors} .= "</itemizedlist>";
+ }
+
+ if (exists $file{ $fn{$name}{filename} }{copyright})
+ {
+ $fn{$into}{_copyright}
+ = "<screen>\n".$file{ $fn{$name}{filename} }{copyright}."</screen>\n";
+ }
+}
+
+# printing the docbook file is a two-phase process - we spit out the
+# leader pages first - later we add more pages with _refstart pointing
+# to the lader page, so that xmlto will add the functions there. Only the
+# leader page contains some extra info needed for troff page processing.
+
+my %header;
+
+open F, ">$o{docbookfile}" or die "could not open $o{docbookfile}: $!";
+print F '<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"';
+print F "\n",' "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">';
+print F "\n\n",'<reference><title>Manual Pages</title>',"\n";
+for $name (@namelist)
+{
+ print F $fn{$name}{_refhint};
+ next if exists $fn{$name}{into};
+ print F $fn{$name}{_refstart};
+ print F "\n<refentryinfo>", $fn{$name}{_refentryinfo}
+ , "\n</refentryinfo>\n" if length $fn{$name}{_refentryinfo};
+ print F "\n<refmeta>", $fn{$name}{_refmeta}
+ , "\n</refmeta>\n" if length $fn{$name}{_refmeta};
+ print F "\n<refnamediv>", $fn{$name}{_refnamediv}
+ , "\n</refnamediv>\n" if length $fn{$name}{_refnamediv};
+
+ print F "\n<refsynopsisdiv>" if length $fn{$name}{_funcsynopsis};
+ print F "\n<funcsynopsisinfo>", $fn{$name}{_funcsynopsisinfo}
+ , "\n</funcsynopsisinfo>" if length $fn{$name}{_funcsynopsisinfo};
+ print F "\n<funcsynopsis>", $fn{$name}{_funcsynopsis}
+ , "\n</funcsynopsis>" if length $fn{$name}{_funcsynopsis};
+ print F "\n</refsynopsisdiv>" if length $fn{$name}{_funcsynopsis};
+ print F "\n<refsect1><title>Description</title>", $fn{$name}{_description}
+ , "\n</refsect1>" if length $fn{$name}{_description};
+ print F "\n<refsect1><title>Author</title>", $fn{$name}{_authors}
+ , "\n</refsect1>" if length $fn{$name}{_authors};
+ print F "\n<refsect1><title>Copyright</title>", $fn{$name}{_copyright}
+ , "\n</refsect1>" if length $fn{$name}{_copyright};
+ print F "\n<refsect1><title>See Also</title>", $fn{$name}{_seealso}
+ , "\n</refsect1>" if length $fn{$name}{_seealso};
+
+ print F $fn{$name}{_refends};
+
+ # ------------------------------------------------------------------
+ # creating the per-header manpage - a combination of function man pages
+
+ my $H = $fn{$name}{_mainheader}; # a shorthand for the mainheader index
+ my $me = 0; $me = 1 if not exists $header{$H};
+ my $HH = $H; $HH =~ s/[^\w\.]/-/g;
+ $header{$H}{_refstart} = "\n<refentry id=\"".$HH."\">" if $me;
+ $header{$H}{_refends} = "\n</refentry>\n" if $me;
+ $header{$H}{_refentryinfo} = $fn{$name}{_refentryinfo} if $me;
+ $header{$H}{_refentryinfo}
+ =~ s/(<title>)([^<>]*)(<\/title>)/$1 the library $3/s if $me;
+ $header{$H}{_refmeta}
+ = "\n <manvolnum>".$fn{$name}{_manvolnum}."</manvolnum>\n"
+ . "\n <refentrytitle>".$fn{$name}{_mainheader}."</refentrytitle>" if $me;
+ $header{$H}{_refnamediv} = "\n <refpurpose> library </refpurpose>";
+ $header{$H}{_refnamediv} .= "\n <refname>".$HH."</refname>";
+
+ $header{$H}{_refsynopsisinfo}
+ = $fn{$name}{_refsynopsisinfo} if exists $fn{$name}{_refsynopsisinfo};
+ $header{$H}{_funcsynopsis}
+ .= "\n".$fn{$name}{_funcsynopsis} if exists $fn{$name}{_funcsynopsis};
+# $header{$H}{_funcsynopsisdiv} .= "\n<funcsynopsis>"
+# .$fn{$name}{_funcsynopsis}."</funcsynopsis>"
+# if exists $fn{$name}{_funcsynopsis};
+ $header{$H}{_copyright}
+ = $fn{$name}{_copyright} if exists $fn{$name}{_copyright} and $me;
+ $header{$H}{_authors}
+ = $fn{$name}{_authors} if exists $fn{$name}{_authors} and $me;
+ if ($me)
+ {
+ my $T = `cat $o{package}.spec`;
+ if ($T =~ /\%description\b([^\%]*)\%/s)
+ {
+ $header{$H}{_description} = $1;
+ }elsif (not length $header{$H}{_description})
+ {
+ $header{$H}{_description} = "$o{package} library";
+ }
+ }
+}
+
+my $H;
+for $H (keys %header) # second pass
+{
+ next if not length $header{$H}{_refstart};
+ print F "\n<!-- _______ ",$H," _______ -->";
+ print F $header{$H}{_refstart};
+ print F "\n<refentryinfo>", $header{$H}{_refentryinfo}
+ , "\n</refentryinfo>\n" if length $header{$H}{_refentryinfo};
+ print F "\n<refmeta>", $header{$H}{_refmeta}
+ , "\n</refmeta>\n" if length $header{$H}{_refmeta};
+ print F "\n<refnamediv>", $header{$H}{_refnamediv}
+ , "\n</refnamediv>\n" if length $header{$H}{_refnamediv};
+
+ print F "\n<refsynopsisdiv>" if length $header{$H}{_funcsynopsis};
+ print F "\n<funcsynopsisinfo>", $header{$H}{_funcsynopsisinfo}
+ , "\n</funcsynopsisinfo>" if length $header{$H}{_funcsynopsisinfo};
+ print F "\n<funcsynopsis>", $header{$H}{_funcsynopsis}
+ , "\n</funcsynopsis>" if length $header{$H}{_funcsynopsis};
+ print F "\n</refsynopsisdiv>" if length $header{$H}{_funcsynopsis};
+
+ print F "\n<refsect1><title>Description</title>", $header{$H}{_description}
+ , "\n</refsect1>" if length $header{$H}{_description};
+ print F "\n<refsect1><title>Author</title>", $header{$H}{_authors}
+ , "\n</refsect1>" if length $header{$H}{_authors};
+ print F "\n<refsect1><title>Copyright</title>", $header{$H}{_copyright}
+ , "\n</refsect1>" if length $header{$H}{_copyright};
+
+ print F $header{$H}{_refends};
+}
+print F "\n",'</reference>',"\n";
+close (F);
+
+# _____________________________________________________________________
+open F, ">$o{dumpdocfile}" or die "could not open $o{dumpdocfile}: $!";
+
+for $name (sort keys %fn)
+{
+ print F "<fn id=\"$name\"><!-- FOR \"$name\" -->\n";
+ for $H (sort keys %{$fn{$name}})
+ {
+ print F "<$H name=\"$name\">",$fn{$name}{$H},"</$H>\n";
+ }
+ print F "</fn><!-- END \"$name\" -->\n\n";
+}
+close F;
diff --git a/Build/source/libs/zziplib/docs/make-doc.py b/Build/source/libs/zziplib/docs/make-doc.py
new file mode 100644
index 00000000000..c58427c4a5c
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/make-doc.py
@@ -0,0 +1,1028 @@
+#! /usr/bin/python
+# -*- coding: UTF-8 -*-
+import sys
+import re
+import string
+import commands
+import warnings
+
+errors = 0
+def warn(msg, error=None):
+ global errors
+ errors += 1
+ if error is None:
+ warnings.warn("-- "+str(errors)+" --\n "+msg, RuntimeWarning, 2)
+ else:
+ warnings.warn("-- "+str(errors)+" --\n "+msg+
+ "\n error was "+str(error), RuntimeWarning, 2)
+#fu
+
+# beware, stupid python interprets backslashes in repl only partially!
+def s(string, pattern, repl, count=0):
+ return re.sub(pattern, repl, string, count)
+def m(string, pattern):
+ return re.match(pattern, string)
+def sorted_keys(dict):
+ keys = dict.keys()
+ keys.sort()
+ return keys
+
+# we make up a few formatter routines to help in the processing:
+def html2docbook(text):
+ """ the C comment may contain html markup - simulate with docbook tags """
+ return (
+ s(s(s(s(s(s(s(s(s(s(s(text,
+ r"<br\s*/?>",""),
+ r"(</?)em>",r"\1emphasis>"),
+ r"<code>","<userinput>"),
+ r"</code>","</userinput>"),
+ r"<link>","<function>"),
+ r"</link>","</function>"),
+ r"(?s)\s*</screen>","</screen>"),
+# r"<ul>","</para><itemizedlist>"),
+# r"</ul>","</itemizedlist><para>"),
+# r"<li>","<listitem><para>"),
+# r"</li>","</para></listitem>\n"),
+ r"<ul>","</para><programlisting>\n"),
+ r"</ul>","</programlisting><para>"),
+ r"<li>",""),
+ r"</li>",""))
+def paramdef2html(text):
+ return s(s(s(s(s(text,
+ r"\s+<paramdef>", r"\n<nobr>"),
+ r"<paramdef>",r"<nobr>"),
+ r"</paramdef>",r"</nobr>"),
+ r"<parameters>",r"\n <code>"),
+ r"</parameters>",r"</code>\n")
+def section2html(text):
+ mapping = { "<screen>" : "<pre>", "</screen>" : "</pre>",
+ "<para>" : "<p>", "</para>" : "</p>" ,
+ "<function>" : "<link>", "</function>" : "</link>" }
+ for str in mapping:
+ text = string.replace(text, str, mapping[str])
+ return text
+def html(text):
+ return section2html(paramdef2html(text))
+def cdata1(text):
+ return string.replace(text, "&", "&amp;")
+def cdata31(text):
+ return string.replace(string.replace(text, "<","&lt;"), ">","&gt;")
+def cdata3(text):
+ return cdata31(cdata1(text))
+def cdata43(text):
+ return string.replace(text,"\"", "&quot;")
+def cdata41(text):
+ return cdata43(cdata31(text))
+def cdata4(text):
+ return cdata43(cdata3(text))
+def markup_as_screen41 (text):
+ """ used for non-star lines in comment blocks """
+ return " <screen> " + s(cdata41(text), r"(?m)^", r" ") +" </screen> "
+
+def file_comment2section(text):
+ """ convert a C comment into a series of <para> and <screen> parts """
+ return ("<para>\n"+
+ s(s(s(s(s(s(s(text,
+ r"(?s){<([\w\.\-]+\@[\w\.\-]+\w\w)>",
+ r"&lt;\1&gt;"),
+ r"(?mx) ^\s?\s?\s? ([^\*\s]+ .*) $",
+ lambda x : markup_as_screen41 (x.group(1))),
+ r"(?mx) ^\s*[*]\s* $", r" \n</para><para>\n"),
+ r"(?mx) ^\s?\s?\s?\* (.*) $", r" \1 "),
+ r"(?sx) </screen>(\s*)<screen> ", r"\1"),
+ r"(?sx) <([^<>\;]+\@[^<>\;]+)> ", r"<email>\1</email>"),
+ r"(?sx) \&lt\;([^<>\&\;]+\@[^<>\&\;]+)\&gt\; ",
+ r"<email>\1</email>") + "\n</para>")
+def func_comment2section(text):
+ """ convert a C comment into a series of <para> and <screen> parts
+ and sanitize a few markups already present in the comment text
+ """
+ return ("<para>\n"+
+ s(s(s(s(s(s(s(s(s(s(s(text,
+ r"<c>",r"<code>"), r"</c>", r"</code>"),
+ r"(?mx) ^\s?\s?\s? ([^\*\s]+.*)",
+ lambda x: markup_as_screen41 (x.group(1))),
+ r"(?mx) ^\s?\s?\s?\* (.*) $", r" <br /> \1"),
+ r"(?mx) ^\s*<br\s*\/>\s* $", r"\n</para><para>\n"),
+ r"<<",r"&lt;"), r">>",r"&gt;"),
+ r"(?sx) (</?para>\s*)<br\s*\/?>",r"\1"),
+ r"(?sx) (</?para>\s*)<br\s*\/?>",r"\1"),
+ r"(?sx) (<br\s*\/?>\s*)<br\s*\/?>",r"\1"),
+ r"(?sx) <\/screen>(\s*)<screen>",r"\1") + "\n</para>")
+def markup_link_syntax(text):
+ """ markup the link-syntax ` => somewhere ` in the text block """
+ return (
+ s(s(s(s(text,
+ r"(?mx) (^|\s)\=\>\"([^\"]*)\"", r"\1<link>\2</link>"),
+ r"(?mx) (^|\s)\=\>\'([^\"]*)\'", r"\1<link>\2</link>"),
+ r"(?mx) (^|\s)\=\>\s(\w[\w.]*\w)\b", r"\1<link>\2</link>"),
+ r"(?mx) (^|\s)\=\>\s([^\s\,\.\!\?\:\;\<\>\&\'\=\-]+)",
+ r"\1<link>\2</link>"))
+def this_function_link(text, name):
+ return s(text, r"(?sx) (T|t)his \s (function|procedure) ", lambda x
+ : "<function>"+x.group(1)+"he "+name+" "+x.group(2)+"</function>")
+
+# -----------------------------------------------------------------------
+class Options:
+ var = {}
+ def __getattr__(self, name):
+ if not self.var.has_key(name): return None
+ return self.var[name]
+ def __setattr__(self, name, value):
+ self.var[name] = value
+#end
+
+o = Options()
+o.verbose = 0
+
+o.version = s( commands.getoutput(
+ """ grep -i "^version *:" *.spec 2>/dev/null |
+ sed -e "s/[Vv]ersion *: *//" """), r"\s*",r"")
+o.package = s(commands.getoutput(
+ """ grep -i "^name *:" *.spec 2>/dev/null |
+ sed -e "s/[Nn]ame *: *//" """), r"\s*",r"")
+
+if not len(o.version):
+ o.version = commands.getoutput(""" date +%Y.%m.%d """)
+if not len(o.package):
+ o.package = "_project"
+
+o.suffix = "-doc3"
+o.mainheader = o.package+".h"
+
+class File:
+ def __init__(self, filename):
+ self.name = filename
+ self.mainheader = o.mainheader
+ self.authors = ""
+ self.copyright = ""
+ def __getattr__(self, name):
+ """ defend against program to break on uninited members """
+ if self.__dict__.has_key(name): return self.__dict__[name]
+ warn("no such member: "+name); return None
+ def set_author(self, text):
+ if self.authors:
+ self.authors += "\n"
+ self.authors += text
+ return text
+ def set_copyright(self, text):
+ self.copyright = text
+ return text
+
+class InputFiles:
+ """ for each set of input files we can create an object
+ it does correspond with a single html-output page and
+ a single docbook <reference> master page to be output
+ """
+ def __init__(self):
+ # the id will tell us in which order
+ # we did meet each function definition
+ self.id = 1000
+ self.files = [] # file_list
+ self.funcs = [] # func_list: of hidden class FuncDeclaration
+ self.file = None # current file
+ def new_File(self, name):
+ self.file = File(name)
+ self.files.append(self.file)
+ return self.file
+ def next_id(self):
+ id = self.id ; self.id += 1
+ return id
+ def add_function_declaration(self, comment, prototype):
+ class FuncDeclaration: # note that both decl.comment and
+ pass # decl.prototype are in cdata1 format
+ func = FuncDeclaration()
+ func.file = self.file
+ func.comment = s(comment, # need to take out email-style markups
+ r"<([\w\.\-]+\@[\w\.\-]+\w\w)>", r"&lt;\1&gt;")
+ func.prototype = prototype
+ func.id = all.next_id()
+ self.funcs.append(func)
+ # print id
+ return prototype
+
+def scan_options (options, list):
+ def encode(text):
+ return s(s(text, r"¬", r"&#AC;"), r"\*/",r"¬")
+ def decode(text):
+ return s(text, r"¬", r"*/")
+
+ for name in options:
+ found = m(name, r"^(\w+)=(.*)")
+ if found:
+ o.var[found.group(1)] = found.group(2)
+ continue
+ #else
+ try:
+ input = open(name, "r")
+ except IOError, error:
+ warn(#...... (scan_options) ...............
+ "can not open input file: "+name, error)
+ continue
+ text = input.read() ; input.close()
+ text = encode (cdata1 (text))
+
+ file = list.new_File(name)
+
+ # cut per-function comment block
+ text = s(text, r"(?x) [/][*][*](?=\s) ([^¬]+) ¬ ([^\{\}\;\#]+) [\{\;]",
+ lambda x : list.add_function_declaration(
+ decode(x.group(1)), decode(x.group(2))))
+
+ # cut per-file comment block
+ found = m(text, r"(?sx) [/][*]+(?=\s) ([^¬]+) ¬ "
+ r"(?:\s*\#define\s*\S+)*"
+ r"(\s*\#include\s*<[^<>]*>(?:\s*//[^\n]*)?)")
+ if found:
+ file.comment = decode(found.group(1))
+ file.include = cdata31(found.group(2))
+ else:
+ file.comment = None
+ file.include = None
+ found = m(text, r"(?sx) ^ [/][*]+(?=\s) ([^¬]+) ¬ ")
+ if found:
+ file.comment = decode(found.group(1))
+ #fi
+ # throw away the rest - further processing on memorized strings only
+
+ return None
+
+all = InputFiles()
+scan_options (sys.argv[1:], all)
+
+if not o.docbookfile:
+ o.docbookfile = o.package+o.suffix+".docbook"
+if not o.libhtmlfile:
+ o.libhtmlfile = o.package+o.suffix+".html"
+if not o.dumpdocfile:
+ o.dumpdocfile = o.package+o.suffix+".dxml"
+
+# ...........................................................................
+# check out information in the file.comment section
+
+def all_files_comment2section(list):
+ for file in list:
+ if file.comment is None: continue
+ file.section = file_comment2section(file.comment)
+
+ file.section = s(
+ file.section, r"(?sx) \b[Aa]uthor\s*:(.*</email>) ", lambda x
+ : "<author>" + file.set_author(x.group(1)) + "</author>")
+ file.section = s(
+ file.section, r"(?sx) \b[Cc]opyright\s*:([^<>]*)</para> ",lambda x
+ : "<copyright>" + file.set_copyright(x.group(1)) + "</copyright>")
+ # if "file" in file.name: print >> sys.stderr, file.comment # 2.3
+ #od
+all_files_comment2section(all.files)
+
+# -----------------------------------------------------------------------
+
+class Function:
+ " <prespec>void* </><namespec>hello</><namespec> (int) const</callspec> "
+ def __init__(self):
+ self.prespec = ""
+ self.namespec = ""
+ self.callspec = ""
+ self.name = ""
+# def set(self, **defines):
+# name = defines.keys()[0]
+# self.__dict__[name] = defines[name]
+# return defines[name]
+# def cut(self, **defines):
+# name = defines.keys()[0]
+# self.__dict__[name] += defines[name]
+# return ""
+ def __getattr__(self, name):
+ """ defend against program exit on members being not inited """
+ if self.__dict__.has_key(name): return self.__dict__[name]
+ warn("no such member: "+name); return None
+ def dict(self):
+ return self.__dict__
+ def dict_sorted_keys(self):
+ keys = self.__dict__.keys()
+ keys.sort()
+ return keys
+ def parse(self, prototype):
+ found = m(prototype, r"(?sx) ^(.*[^.]) \b(\w[\w.]*\w)\b (\s*\(.*) $ ")
+ if found:
+ self.prespec = found.group(1).lstrip()
+ self.namespec = found.group(2)
+ self.callspec = found.group(3).lstrip()
+ self.name = self.namespec.strip()
+ return self.name
+ return None
+
+# pass 1 of per-func strings ...............................................
+# (a) cut prototype into prespec/namespec/callspec
+# (b) cut out first line of comment as headline information
+# (c) sanitize rest of comment block into proper docbook formatted .body
+#
+# do this while copying strings from all.funcs to function_list
+# and remember the original order in name_list
+
+def markup_callspec(text):
+ return (
+ s(s(s(s(s(text,
+ r"(?sx) ^([^\(\)]*)\(", r"\1<parameters>(<paramdef>",1),
+ r"(?sx) \)([^\(\)]*)$", r"</paramdef>)</parameters>\1",1),
+ r"(?sx) , ", r"</paramdef>,<paramdef>"),
+ r"(?sx) <paramdef>(\s+) ", r"\1<paramdef>"),
+ r"(?sx) (\s+)</paramdef>", r"</paramdef>\1"))
+
+def parse_all_functions(func_list): # list of FunctionDeclarations
+ """ parse all FunctionDeclarations and create a list of Functions """
+ list = []
+ for func in all.funcs:
+ function = Function()
+ if not function.parse (func.prototype): continue
+
+ list.append(function)
+
+ function.body = markup_link_syntax(func.comment)
+ if "\n" not in function.body: # single-line comment is the head
+ function.head = function.body
+ function.body = ""
+ else: # cut comment in first-line and only keep the rest as descr body
+ function.head = s(function.body, r"(?sx) ^([^\n]*\n).*",r"\1",1)
+ function.body = s(function.body, r"(?sx) ^[^\n]*\n", r"", 1)
+ #fi
+ if m(function.head, r"(?sx) ^\s*$ "): # empty head line, autofill here
+ function.head = s("("+func.file.name+")", r"[.][.][/]", r"")
+
+ function.body = func_comment2section(function.body)
+ function.src = func # keep a back reference
+
+ # add extra docbook markups to callspec in $fn-hash
+ function.callspec = markup_callspec (function.callspec)
+ #od
+ return list
+function_list = parse_all_functions(all.funcs)
+
+def examine_head_anchors(func_list):
+ """ .into tells later steps which func-name is the leader of a man
+ page and that this func should add its descriptions over there. """
+ for function in func_list:
+ function.into = None
+ function.seealso = None
+
+ found = m(function.head, r"(?sx) ^ \s* <link>(\w[\w.]*\w)<\/link>")
+ # if found and found.group(1) in func_list.names:
+ if found and found.group(1):
+ function.into = found.group(1)
+
+ def set_seealso(f, value):
+ f.seealso = value
+ return value
+ function.head = s(function.head, r"(.*)also:(.*)", lambda x
+ : set_seealso(function, x.group(2)) and x.group(1))
+ if function.seealso and None:
+ print "function[",function.name,"].seealso=",function.seealso
+examine_head_anchors(function_list)
+
+# =============================================================== HTML =====
+
+def find_by_name(func_list, name):
+ for func in func_list:
+ if func.name == name:
+ return func
+ #od
+ return None
+#fu
+
+class HtmlFunction:
+ def __init__(self, func):
+ self.src = func.src
+ self.into = func.into
+ self.name = func.name
+ self.toc_line = paramdef2html(
+ " <td valign=\"top\"><code>"+func.prespec+"</code></td>\n"+
+ " <td valign=\"top\">&nbsp;&nbsp;</td>\n"+
+ " <td valign=\"top\"><a href=\"#"+func.name+"\">\n"+
+ " <code>"+func.namespec+"</code>"+
+ " </a></td>\n"+
+ " <td valign=\"top\">&nbsp;&nbsp;</td>\n"+
+ " <td valign=\"top\">"+func.callspec+"</td>\n")
+ self.synopsis = paramdef2html(
+ " <code>"+func.prespec+"</code>\n"+
+ " <br /><b><code>"+func.namespec+"</code></b>\n"+
+ " &nbsp; <code>"+func.callspec+"</code>\n")
+ self.anchor = "<a name=\""+func.name+"\" />"
+ self.section = "<para><em> &nbsp;"+func.head+"\n"+ \
+ "\n</em></para>"+section2html(func.body)
+#class
+
+class HtmlFunctionFamily(HtmlFunction):
+ def __init__(page, func):
+ HtmlFunction.__init__(page, func)
+ page.toc_line_list = [ page.toc_line ]
+ # page.html_txt = page.synopsis
+ page.synopsis_list = [ page.synopsis ]
+ page.anchor_list = [ page.anchor ]
+ page.section_list = [ this_function_link(page.section, func.name) ]
+
+def ensure_name(text, name):
+ adds = "<small><code>"+name+"</code></small> -"
+ match = r"(?sx) .*>[^<>]*\b" + name + r"\b[^<>]*<.*"
+ found = m(text, match)
+ if found: return text
+ found = m(text, r".*<p(ara)?>.*")
+ if found: return s(text, r"(<p(ara)?>)", r"\1"+adds, 1)
+ return adds+text
+
+def combined_html_pages(func_list):
+ """ and now add descriptions of non-leader entries (html-mode) """
+ combined = {}
+
+ for func in func_list: # assemble leader pages
+ if func.into is not None: continue
+ combined[func.name] = HtmlFunctionFamily(func)
+
+ for func in func_list:
+ if func.into is None: continue
+ if func.into not in combined :
+ warn(#......... (combine_html_pages) ..............
+ "function '"+func.name+"'s into => '"+func.into+
+ "\n: no such target function: "+func.into)
+ combined[func.name] = HtmlFunctionFamily(func)
+ continue
+ #fi
+ page = HtmlFunction(func)
+ into = combined[func.into]
+ into.toc_line_list.append( page.toc_line )
+ into.anchor_list.append( page.anchor )
+ into.synopsis_list.append( page.synopsis )
+ into.section_list.append(
+ s(ensure_name(this_function_link(section2html( func.body ),
+ func.name), func.name),
+ r"(?sx) (</?para>\s*) <br\s*\/>", r"\1"))
+ return combined.values()
+html_pages = combined_html_pages(function_list)
+
+def html_resolve_links_on_page(text, list):
+ """ link ref-names of a page with its endpoint on the same html page"""
+ def html_link (name , extra):
+ """ make <link>s to <href> of correct target or make it <code> """
+ if find_by_name(list, name) is None:
+ return "<code>"+name+extra+"</code>"
+ else:
+ return "<a href=\"#"+name+"\"><code>"+name+extra+"</code></a>"
+ #fu html_link
+ return s(s(text, r"(?sx) <link>(\w+)([^<>]*)<\/link> ",
+ lambda x : html_link(x.group(1),x.group(2))),
+ r"(?sx) \-\> ", r"<small>-&gt;</small>") # just sanitize..
+#fu html_resolve_links
+
+class HtmlPage:
+ def __init__(self):
+ self.toc = ""
+ self.txt = ""
+ self.package = o.package
+ self.version = o.version
+ def page_text(self):
+ """ render .toc and .txt parts into proper <html> page """
+ T = ""
+ T += "<html><head>"
+ T += "<title>"+self.package+"autodoc documentation </title>"
+ T += "</head>\n<body>\n"
+ T += "\n<h1>"+self.package+" <small><small><i>- "+self.version
+ T += "</i></small></small></h1>"
+ T += "\n<table border=0 cellspacing=2 cellpadding=0>"
+ T += self.toc
+ T += "\n</table>"
+ T += "\n<h3>Documentation</h3>\n\n<dl>"
+ T += html_resolve_links_on_page(self.txt, function_list)
+ T += "\n</dl>\n</body></html>\n"
+ return T
+ def add_page_map(self, list):
+ """ generate the index-block at the start of the onepage-html file """
+ keys = list.keys()
+ keys.sort()
+ for name in keys:
+ self.toc += "<tr valign=\"top\">\n"+ \
+ "\n</tr><tr valign=\"top\">\n".join(
+ list[name].toc_line_list)+"</tr>\n"
+ self.txt += "\n<dt>"+" ".join(list[name].anchor_list)
+ self.txt += "\n"+"\n<br />".join(list[name].synopsis_list)+"<dt>"
+ self.txt += "\n<dd>\n"+"\n".join(list[name].section_list)
+ self.txt += ("\n<p align=\"right\">"+
+ "<small>("+list[name].src.file.name+")</small>"+
+ "</p></dd>")
+ def add_page_list(self, functions):
+ """ generate the index-block at the start of the onepage-html file """
+ mapp = {}
+ for func in functions:
+ mapp[func.name] = func
+ #od
+ self.add_page_map(mapp)
+#end
+
+html = HtmlPage()
+# html.add_function_dict(Fn)
+# html.add_function_list(Fn.sort.values())
+html.add_page_list(html_pages)
+
+# and finally print the html-formatted output
+try:
+ F = open(o.libhtmlfile, "w")
+except IOError, error:
+ warn(# ............. open(o.libhtmlfile, "w") ..............
+ "can not open html output file: "+o.libhtmlfile, error)
+else:
+ print >> F, html.page_text()
+ F.close()
+#fi
+
+# ========================================================== DOCBOOK =====
+# let's go for the pure docbook, a reference type master for all man pages
+
+class RefPage:
+ def __init__(self, func):
+ """ initialize the fields needed for a man page entry - the fields are
+ named after the docbook-markup that encloses (!!) the text we store
+ the entries like X.refhint = "hello" will be printed therefore as
+ <refhint>hello</refhint>. Names with underscores are only used as
+ temporaries but they are memorized, perhaps for later usage. """
+ self.refhint = "\n<!--========= "+func.name+" (3) ===========-->\n"
+ self.refentry = None
+ self.refentry_date = o.version.strip() # //refentryinfo/date
+ self.refentry_productname = o.package.strip() # //refentryinfo/prod*
+ self.refentry_title = None # //refentryinfo/title
+ self.refentryinfo = None # override
+ self.manvolnum = "3" # //refmeta/manvolnum
+ self.refentrytitle = None # //refmeta/refentrytitle
+ self.refmeta = None # override
+ self.refpurpose = None # //refnamediv/refpurpose
+ self.refname = None # //refnamediv/refname
+ self.refname_list = []
+ self.refnamediv = None # override
+ self.mainheader = func.src.file.mainheader
+ self.includes = func.src.file.include
+ self.funcsynopsisinfo = "" # //funcsynopsisdiv/funcsynopsisinfo
+ self.funcsynopsis = None # //funcsynopsisdiv/funcsynopsis
+ self.funcsynopsis_list = []
+ self.description = None
+ self.description_list = []
+ # optional sections
+ self.authors_list = [] # //sect1[authors]/listitem
+ self.authors = None # override
+ self.copyright = None
+ self.copyright_list = []
+ self.seealso = None
+ self.seealso_list = []
+ if func.seealso:
+ self.seealso_list.append(func.seealso)
+ # func.func references
+ self.func = func
+ self.file_authors = None
+ if func.src.file.authors:
+ self.file_authors = func.src.file.authors
+ self.file_copyright = None
+ if func.src.file.copyright:
+ self.file_copyright = func.src.file.copyright
+ #fu
+ def refentryinfo_text(page):
+ """ the manvol formatter wants to render a footer line and header line
+ on each manpage and such info is set in <refentryinfo> """
+ if page.refentryinfo:
+ return page.refentryinfo
+ if page.refentry_date and \
+ page.refentry_productname and \
+ page.refentry_title: return (
+ "\n <date>"+page.refentry_date+"</date>"+
+ "\n <productname>"+page.refentry_productname+"</productname>"+
+ "\n <title>"+page.refentry_title+"</title>")
+ if page.refentry_date and \
+ page.refentry_productname: return (
+ "\n <date>"+page.refentry_date+"</date>"+
+ "\n <productname>"+page.refentry_productname+"</productname>")
+ return ""
+ def refmeta_text(page):
+ """ the manvol formatter needs to know the filename of the manpage to
+ be made up and these parts are set in <refmeta> actually """
+ if page.refmeta:
+ return page.refmeta
+ if page.manvolnum and page.refentrytitle:
+ return (
+ "\n <refentrytitle>"+page.refentrytitle+"</refentrytitle>"+
+ "\n <manvolnum>"+page.manvolnum+"</manvolnum>")
+ if page.manvolnum and page.func.name:
+ return (
+ "\n <refentrytitle>"+page.func.name+"</refentrytitle>"+
+ "\n <manvolnum>"+page.manvolnum+"</manvolnum>")
+ return ""
+ def refnamediv_text(page):
+ """ the manvol formatter prints a header line with a <refpurpose> line
+ and <refname>'d functions that are described later. For each of
+ the <refname>s listed here, a mangpage is generated, and for each
+ of the <refname>!=<refentrytitle> then a symlink is created """
+ if page.refnamediv:
+ return page.refnamediv
+ if page.refpurpose and page.refname:
+ return ("\n <refname>"+page.refname+'</refname>'+
+ "\n <refpurpose>"+page.refpurpose+" </refpurpose>")
+ if page.refpurpose and page.refname_list:
+ T = ""
+ for refname in page.refname_list:
+ T += "\n <refname>"+refname+'</refname>'
+ T += "\n <refpurpose>"+page.refpurpose+" </refpurpose>"
+ return T
+ return ""
+ def funcsynopsisdiv_text(page):
+ """ refsynopsisdiv shall be between the manvol mangemaent information
+ and the reference page description blocks """
+ T=""
+ if page.funcsynopsis:
+ T += "\n<funcsynopsis>"
+ if page.funcsynopsisinfo:
+ T += "\n<funcsynopsisinfo>"+ page.funcsynopsisinfo + \
+ "\n</funcsynopsisinfo>\n"
+ T += page.funcsynopsis + \
+ "\n</funcsynopsis>\n"
+ if page.funcsynopsis_list:
+ T += "\n<funcsynopsis>"
+ if page.funcsynopsisinfo:
+ T += "\n<funcsynopsisinfo>"+ page.funcsynopsisinfo + \
+ "\n</funcsynopsisinfo>\n"
+ for funcsynopsis in page.funcsynopsis_list:
+ T += funcsynopsis
+ T += "\n</funcsynopsis>\n"
+ #fi
+ return T
+ def description_text(page):
+ """ the description section on a manpage is the main part. Here
+ it is generated from the per-function comment area. """
+ if page.description:
+ return page.description
+ if page.description_list:
+ T = ""
+ for description in page.description_list:
+ if not description: continue
+ T += description
+ if T: return T
+ return ""
+ def authors_text(page):
+ """ part of the footer sections on a manpage and a description of
+ original authors. We prever an itimizedlist to let the manvol
+ show a nice vertical aligment of authors of this ref item """
+ if page.authors:
+ return page.authors
+ if page.authors_list:
+ T = "<itemizedlist>"
+ previous=""
+ for authors in page.authors_list:
+ if not authors: continue
+ if previous == authors: continue
+ T += "\n <listitem><para>"+authors+"</para></listitem>"
+ previous = authors
+ T += "</itemizedlist>"
+ return T
+ if page.authors:
+ return page.authors
+ return ""
+ def copyright_text(page):
+ """ the copyright section is almost last on a manpage and purely
+ optional. We list the part of the per-file copyright info """
+ if page.copyright:
+ return page.copyright
+ """ we only return the first valid instead of merging them """
+ if page.copyright_list:
+ T = ""
+ for copyright in page.copyright_list:
+ if not copyright: continue
+ return copyright # !!!
+ return ""
+ def seealso_text(page):
+ """ the last section on a manpage is called 'SEE ALSO' usally and
+ contains a comma-separated list of references. Some manpage
+ viewers can parse these and convert them into hyperlinks """
+ if page.seealso:
+ return page.seealso
+ if page.seealso_list:
+ T = ""
+ for seealso in page.seealso_list:
+ if not seealso: continue
+ if T: T += ", "
+ T += seealso
+ if T: return T
+ return ""
+ def refentry_text(page, id=None):
+ """ combine fields into a proper docbook refentry """
+ if id is None:
+ id = page.refentry
+ if id:
+ T = '<refentry id="'+id+'">'
+ else:
+ T = '<refentry>' # this is an error
+
+ if page.refentryinfo_text():
+ T += "\n<refentryinfo>"+ page.refentryinfo_text()+ \
+ "\n</refentryinfo>\n"
+ if page.refmeta_text():
+ T += "\n<refmeta>"+ page.refmeta_text() + \
+ "\n</refmeta>\n"
+ if page.refnamediv_text():
+ T += "\n<refnamediv>"+ page.refnamediv_text() + \
+ "\n</refnamediv>\n"
+ if page.funcsynopsisdiv_text():
+ T += "\n<refsynopsisdiv>\n"+ page.funcsynopsisdiv_text()+ \
+ "\n</refsynopsisdiv>\n"
+ if page.description_text():
+ T += "\n<refsect1><title>Description</title> " + \
+ page.description_text() + "\n</refsect1>"
+ if page.authors_text():
+ T += "\n<refsect1><title>Author</title> " + \
+ page.authors_text() + "\n</refsect1>"
+ if page.copyright_text():
+ T += "\n<refsect1><title>Copyright</title> " + \
+ page.copyright_text() + "\n</refsect1>\n"
+ if page.seealso_text():
+ T += "\n<refsect1><title>See Also</title><para> " + \
+ page.seealso_text() + "\n</para></refsect1>\n"
+
+ T += "\n</refentry>\n"
+ return T
+ #fu
+#end
+
+# -----------------------------------------------------------------------
+class FunctionRefPage(RefPage):
+ def reinit(page):
+ """ here we parse the input function for its values """
+ if page.func.into:
+ page.refhint = "\n <!-- see "+page.func.into+" -->\n"
+ #fi
+ page.refentry = page.func.name # //refentry@id
+ page.refentry_title = page.func.name.strip() # //refentryinfo/title
+ page.refentrytitle = page.func.name # //refmeta/refentrytitle
+ if page.includes:
+ page.funcsynopsisinfo += "\n"+page.includes
+ if not page.funcsynopsisinfo:
+ page.funcsynopsisinfo="\n"+' #include &lt;'+page.mainheader+'&gt;'
+ page.refpurpose = page.func.head
+ page.refname = page.func.name
+
+ def funcsynopsis_of(func):
+ return (
+ "\n <funcprototype>\n <funcdef>"+func.prespec+
+ " <function>"+func.name+"</function></funcdef>"+
+ "\n"+s(s(s(func.callspec,
+ r"<parameters>\s*\(",r" "),
+ r"\)\s*</parameters>",r" "),
+ r"</paramdef>\s*,\s*",r"</paramdef>\n ")+
+ " </funcprototype>")
+ page.funcsynopsis = funcsynopsis_of(page.func)
+
+ page.description = (
+ html2docbook(this_function_link(page.func.body, page.func.name)))
+
+ if page.file_authors:
+ def add_authors(page, ename, email):
+ page.authors_list.append( ename+' '+email )
+ return ename+email
+ s(page.file_authors,
+ r"(?sx) \s* ([^<>]*) (<email>[^<>]*</email>) ", lambda x
+ : add_authors(page, x.group(1), x.group(2)))
+ #fi
+
+ if page.file_copyright:
+ page.copyright = "<screen>\n"+page.file_copyright+"</screen>\n"
+ #fi
+ return page
+ def __init__(page,func):
+ RefPage.__init__(page, func)
+ FunctionRefPage.reinit(page)
+
+def refpage_list_from_function_list(funclist):
+ list = []
+ mapp = {}
+ for func in funclist:
+ mapp[func.name] = func
+ #od
+ for func in funclist:
+ page = FunctionRefPage(func)
+ if func.into and func.into not in mapp:
+ warn (# ............ (refpage_list_from_function_list) .......
+ "page '"+page.func.name+"' has no target => "+
+ "'"+page.func.into+"'"
+ "\n: going to reset .into of Function '"+page.func.name+"'")
+ func.into = None
+ #fi
+ list.append(FunctionRefPage(func))
+ return list
+#fu
+
+# ordered list of pages
+refpage_list = refpage_list_from_function_list(function_list)
+
+class FunctionFamilyRefPage(RefPage):
+ def __init__(self, page):
+ RefPage.__init__(self, page.func)
+ self.seealso_list = [] # reset
+ self.refhint_list = []
+ def refhint_list_text(page):
+ T = ""
+ for hint in page.refhint_list:
+ T += hint
+ return T
+ def refentry_text(page):
+ return page.refhint_list_text() + "\n" + \
+ RefPage.refentry_text(page)
+ pass
+
+def docbook_pages_recombine(pagelist):
+ """ take a list of RefPages and create a new list where sections are
+ recombined in a way that their description is listed on the same
+ page and the manvol formatter creates symlinks to the combined
+ function description page - use the attribute 'into' to guide the
+ processing here as each of these will be removed from the output
+ list. If no into-pages are there then the returned list should
+ render to the very same output text like the input list would do """
+
+ list = []
+ combined = {}
+ for orig in pagelist:
+ if orig.func.into: continue
+ page = FunctionFamilyRefPage(orig)
+ combined[orig.func.name] = page ; list.append(page)
+
+ page.refentry = orig.refentry # //refentry@id
+ page.refentry_title = orig.refentrytitle # //refentryinfo/title
+ page.refentrytitle = orig.refentrytitle # //refmeta/refentrytitle
+ page.includes = orig.includes
+ page.funcsynopsisinfo = orig.funcsynopsisinfo
+ page.refpurpose = orig.refpurpose
+ if orig.refhint:
+ page.refhint_list.append( orig.refhint )
+ if orig.refname:
+ page.refname_list.append( orig.refname )
+ elif orig.refname_list:
+ page.refname_list.extend( orig.refname_list )
+ if orig.funcsynopsis:
+ page.funcsynopsis_list.append( orig.funcsynopsis )
+ elif orig.refname_list:
+ page.funcsynopsis_list.extend( orig.funcsynopsis_list )
+ if orig.description:
+ page.description_list.append( orig.description )
+ elif orig.refname_list:
+ page.description_list.extend( orig.description_list )
+ if orig.seealso:
+ page.seealso_list.append( orig.seealso )
+ elif orig.seealso_list:
+ page.seealso_list.extend( orig.seealso_list )
+ if orig.authors:
+ page.authors_list.append( orig.authors )
+ elif orig.authors_list:
+ page.authors_list.extend( orig.authors_list )
+ if orig.copyright:
+ page.copyright_list.append( orig.copyright )
+ elif orig.refname_list:
+ page.copyright_list.extend( orig.copyright_list )
+ #od
+ for orig in pagelist:
+ if not orig.func.into: continue
+ if orig.func.into not in combined:
+ warn("page for '"+orig.func.name+
+ "' has no target => '"+orig.func.into+"'")
+ page = FunctionFamilyRefPage(orig)
+ else:
+ page = combined[orig.func.into]
+
+ if orig.refname:
+ page.refname_list.append( orig.refname )
+ elif orig.refname_list:
+ page.refname_list.extend( orig.refname_list )
+ if orig.funcsynopsis:
+ page.funcsynopsis_list.append( orig.funcsynopsis )
+ elif orig.refname_list:
+ page.funcsynopsis_list.extend( orig.funcsynopsis_list )
+ if orig.description:
+ page.description_list.append( orig.description )
+ elif orig.refname_list:
+ page.description_list.extend( orig.description_list )
+ if orig.seealso:
+ page.seealso_list.append( orig.seealso )
+ elif orig.seealso_list:
+ page.seealso_list.extend( orig.seealso_list )
+ if orig.authors:
+ page.authors_list.append( orig.authors )
+ elif orig.authors_list:
+ page.authors_list.extend( orig.authors_list )
+ if orig.copyright:
+ page.copyright_list.append( orig.copyright )
+ elif orig.refname_list:
+ page.copyright_list.extend( orig.copyright_list )
+ #od
+ return list
+#fu
+
+combined_pages = docbook_pages_recombine(pagelist = refpage_list)
+
+# -----------------------------------------------------------------------
+
+class HeaderRefPage(RefPage):
+ pass
+
+def docbook_refpages_perheader(page_list): # headerlist
+ " creating the per-header manpage - a combination of function man pages "
+ header = {}
+ for page in page_list:
+ assert not page.func.into
+ file = page.func.src.file.mainheader # short for the mainheader index
+ if file not in header:
+ header[file] = HeaderRefPage(page.func)
+ header[file].id = s(file, r"[^\w\.]","-")
+ header[file].refentry = header[file].id
+ header[file].refentryinfo = None
+ header[file].refentry_date = page.refentry_date
+ header[file].refentry_productname = (
+ "the library "+page.refentry_productname)
+ header[file].manvolnum = page.manvolnum
+ header[file].refentrytitle = file
+ header[file].funcsynopsis = ""
+ if 1: # or += or if not header[file].refnamediv:
+ header[file].refpurpose = " library "
+ header[file].refname = header[file].id
+
+ if not header[file].funcsynopsisinfo and page.funcsynopsisinfo:
+ header[file].funcsynopsisinfo = page.funcsynopsisinfo
+ if page.funcsynopsis:
+ header[file].funcsynopsis += "\n"+page.funcsynopsis
+ if not header[file].copyright and page.copyright:
+ header[file].copyright = page.copyright
+ if not header[file].authors and page.authors:
+ header[file].authors = page.authors
+ if not header[file].authors and page.authors_list:
+ header[file].authors_list = page.authors_list
+ if not header[file].description:
+ found = m(commands.getoutput("cat "+o.package+".spec"),
+ r"(?s)\%description\b([^\%]*)\%")
+ if found:
+ header[file].description = found.group(1)
+ elif not header[file].description:
+ header[file].description = "<para>" + (
+ page.refentry_productname + " library") + "</para>";
+ #fi
+ #fi
+ #od
+ return header#list
+#fu
+
+def leaders(pagelist):
+ list = []
+ for page in pagelist:
+ if page.func.into : continue
+ list.append(page)
+ return list
+header_refpages = docbook_refpages_perheader(leaders(refpage_list))
+
+# -----------------------------------------------------------------------
+# printing the docbook file is a two-phase process - we spit out the
+# leader pages first - later we add more pages with _refstart pointing
+# to the leader page, so that xmlto will add the functions there. Only the
+# leader page contains some extra info needed for troff page processing.
+
+doctype = '<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"'
+doctype += "\n "
+doctype += '"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">'+"\n"
+
+try:
+ F = open(o.docbookfile,"w")
+except IOError, error:
+ warn("can not open docbook output file: "+o.docbookfile, error)
+else:
+ print >> F, doctype, '<reference><title>Manual Pages</title>'
+
+ for page in combined_pages:
+ print >> F, page.refentry_text()
+ #od
+
+ for page in header_refpages.values():
+ if not page.refentry: continue
+ print >> F, "\n<!-- _______ "+page.id+" _______ -->",
+ print >> F, page.refentry_text()
+ #od
+
+ print >> F, "\n",'</reference>',"\n"
+ F.close()
+#fi
+
+# _____________________________________________________________________
+try:
+ F = open( o.dumpdocfile, "w")
+except IOError, error:
+ warn ("can not open"+o.dumpdocfile,error)
+else:
+ for func in function_list:
+ name = func.name
+ print >> F, "<fn id=\""+name+"\">"+"<!-- FOR \""+name+"\" -->\n"
+ for H in sorted_keys(func.dict()):
+ print >> F, "<"+H+" name=\""+name+"\">",
+ print >> F, str(func.dict()[H]),
+ print >> F, "</"+H+">"
+ #od
+ print >> F, "</fn><!-- END \""+name+"\" -->\n\n";
+ #od
+ F.close();
+#fi
+
+if errors: sys.exit(errors)
diff --git a/Build/source/libs/zziplib/docs/manpages.ar b/Build/source/libs/zziplib/docs/manpages.ar
new file mode 100644
index 00000000000..4d45c3b07d5
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/manpages.ar
@@ -0,0 +1,2719 @@
+!<arch>
+// 1400 `
+zzip_compr_str.3/
+zzip_createdir.3/
+zzip_dir_alloc.3/
+zzip_dir_alloc_ext_io.3/
+zzip_dir_close.3/
+zzip_dir_creat.3/
+zzip_dir_creat_ext_io.3/
+zzip_dir_fdopen.3/
+zzip_dir_fdopen_ext_io.3/
+zzip_dirhandle.3/
+zzip_dir_open_ext_io.3/
+zzip_disk_close.3/
+zzip_disk_entry_fopen.3/
+zzip_disk_entry_strdup_comment.3/
+zzip_disk_entry_strdup_name.3/
+zzip_disk_entry_to_data.3/
+zzip_disk_entry_to_file_header.3/
+zzip_disk_fclose.3/
+zzip_disk_feof.3/
+zzip_disk_findfile.3/
+zzip_disk_findfirst.3/
+zzip_disk_findmatch.3/
+zzip_disk_findnext.3/
+zzip_disk_fopen.3/
+zzip_disk_fread.3/
+zzip_disk_init.3/
+zzip_disk_mmap.3/
+zzip_disk_munmap.3/
+zzip_disk_open.3/
+zzip_entry_data_offset.3/
+zzip_entry_fclose.3/
+zzip_entry_feof.3/
+zzip_entry_ffile.3/
+zzip_entry_findfile.3/
+zzip_entry_findfirst.3/
+zzip_entry_findmatch.3/
+zzip_entry_findnext.3/
+zzip_entry_fopen.3/
+zzip_entry_fread.3/
+zzip_entry_fread_file_header.3/
+zzip_entry_free.3/
+zzip_entry_strdup_name.3/
+__zzip_fetch_disk_trailer.3/
+zzip_file_close.3/
+zzip_file_creat.3/
+zzip_file_mkdir.3/
+zzip_file_open.3/
+zzip_file_read.3/
+zzip_file_real.3/
+zzip_file_stat.3/
+zzip_file_write.3/
+zzip_get_default_io.3/
+zzip_inflate_init.3/
+zzip_mem_disk_fdopen.3/
+zzip_mem_disk_load.3/
+zzip_mem_disk_open.3/
+zzip_mem_entry_new.3/
+zzip_opendir_ext_io.3/
+zzip_open_ext_io.3/
+zzip_open_shared_io.3/
+__zzip_parse_root_directory.3/
+zzip_rewinddir.3/
+zzip_strerror_of.3/
+__zzip_try_open.3/
+
+zzip_close.3/ 1154977710 1001 0 100644 23 `
+.so man3/zzip_fclose.3
+
+zzip_closedir.3/1154977710 1001 0 100644 1054 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_CLOSEDIR" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_closedir \- (zzip/dir.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 18
+\fBint\ \fBzzip_closedir\fR\fR\fB(\fR\fBZZIP_DIR*\ dir\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe zzip_closedir function\fR
+is the equivalent of
+\fBclosedir\fR(3) for a realdir or zipfile.
+.PP
+\fBThe zzip_closedir function\fR
+is magic \- if the given arg\-ZZIP_DIR is a real directory, it will call the real
+\fBclosedir\fR(3) and then free the wrapping ZZIP_DIR structure. Otherwise it will divert to
+\fBzzip_dir_close\fR
+which will free the ZZIP_DIR structure.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+/0 1154977710 1001 0 100644 789 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_COMPR_STR" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_compr_str \- (zzip/info.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 28
+\fBzzip_char_t*\ \fBzzip_compr_str\fR\fR\fB(\fR\fBint\ compr\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+return static const string of the known compression methods, otherwise just "zipped" is returned
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+
+zzip_creat.3/ 1154977710 1001 0 100644 22 `
+.so man3/zzip_mkdir.3
+/18 1154977710 1001 0 100644 2443 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_CREATEDIR" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_createdir \- create a new archive area for writing
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 25
+\fBZZIP_DIR*\ \fBzzip_createdir\fR\fR\fB(\fR\fBzzip_char_t*\ name\fR\fB, \fR\fBint\ o_mode\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+.PP
+\fBThe zzip_createdir function\fR
+will create a new archive area. This may either be a a new zip archive or a new directory in the filesystem. The returned parameter is a new "zzip dir" handle that should be saved to a variable so it can be used a base argument for
+\fBzzip_file_mkdir\fR
+and
+\fBzzip_file_creat\fR
+calls. The returned handle wraps both possibilities, it can be representing a zip central directory that must be saved to disk using
+\fBzzip_closedir\fR
+or it is just a handle for the name of the real directory that still must be run through
+\fBzzip_closedir\fR
+to release the wrapper around the directory name.
+.PP
+The magic is pushed through the o_mode argument. Using a mode that has no group\-write bit set (S_IWGRP = 0040) then the file is created as a zip directory. Note that this is unabridged of any umask value in the system where the argument to
+\fBthe zzip_createdir function\fR
+could be 0775 but with an umask of 0755 it turns out as 0755 for a real directory. Using 0755 directly would not create it as a real directory but as a zip archive handle.
+.PP
+\fBThe zzip_createdir function\fR
+is not yet implemented, check for #def ZZIP_NO_CREAT Write\-support will extend
+\fBzzip_closedir\fR
+with semantics to finalize the zip\-archive by writing the zip\-trailer and closing the archive file.
+.PP
+Returns null on error and sets errno. Remember, according to posix the
+\fBcreat\fR(2) call is equivalent to
+.sp
+.nf
+ open (path, O_WRONLY | O_CREAT | O_TRUNC, o_mode)
+.fi
+.sp
+so any previous zip\-archive will be overwritten unconditionally and EEXIST errors from
+\fBmkdir\fR(2) are suppressed. (fixme: delete the given subtree? like suggested by O_TRUNC? not done so far!)
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+
+/36 1154977710 1001 0 100644 33 `
+.so man3/zzip_dir_alloc_ext_io.3
+
+/54 1154977710 1001 0 100644 1523 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_DIR_ALLOC_EXT_I" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_dir_alloc_ext_io, zzip_dir_alloc \- (zzip/zip.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 32
+\fBZZIP_DIR*\ \fBzzip_dir_alloc_ext_io\fR\fR\fB(\fR\fBzzip_strings_t*\ ext\fR\fB, \fR\fBconst\ zzip_plugin_io_t\ io\fR\fB);\fR
+.HP 25
+\fBZZIP_DIR*\ \fBzzip_dir_alloc\fR\fR\fB(\fR\fBzzip_strings_t*\ fileext\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+allocate a new ZZIP_DIR handle and do basic initializations before usage by
+\fBzzip_dir_fdopen\fR\fBzzip_dir_open\fR\fBzzip_file_open\fR
+or through
+\fBzzip_open\fR
+(ext==null flags uses { ".zip" , ".ZIP" } ) (io ==null flags use of posix io defaults)
+.PP
+\fBthe zzip_dir_alloc function\fR
+is obsolete \- it was generally used for implementation and exported to let other code build on it. It is now advised to use
+\fBzzip_dir_alloc_ext_io\fR
+now on explicitly, just set that second argument to zero to achieve the same functionality as the old style.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<too@iki.fi>
+.TP
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<too@iki.fi>
+
+/79 1154977710 1001 0 100644 25 `
+.so man3/zzip_dir_free.3
+
+/97 1154977710 1001 0 100644 2417 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_DIR_CREAT" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_dir_creat, zzip_dir_creat_ext_io \- create a new zip archive for writing
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 25
+\fBZZIP_DIR*\ \fBzzip_dir_creat\fR\fR\fB(\fR\fBzzip_char_t*\ name\fR\fB, \fR\fBint\ o_mode\fR\fB);\fR
+.HP 32
+\fBZZIP_DIR*\ \fBzzip_dir_creat_ext_io\fR\fR\fB(\fR\fBzzip_char_t*\ name\fR\fB, \fR\fBint\ o_mode\fR\fB, \fR\fBzzip_strings_t*\ ext\fR\fB, \fR\fBzzip_plugin_io_t\ io\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+.PP
+\fBThe zzip_dir_creat function\fR
+will create a new zip archive. The returned parameter is a new "zzip dir" handle that should be saved to a variable so it can be used a base argument for
+\fBzzip_mkdir\fR
+and
+\fBzzip_creat\fR
+calls. The returned handle represents a zip central directory that must be saved to disk using
+\fBzzip_closedir\fR.
+.PP
+Returns null on error and sets errno. Remember, according to posix the
+\fBcreat\fR(2) call is equivalent to
+.sp
+.nf
+ open (path, O_WRONLY | O_CREAT | O_TRUNC, o_mode)
+.fi
+.sp
+so any previous zip\-archive will be overwritten unconditionally and EEXIST errors from
+\fBmkdir\fR(2) are suppressed. (fixme: delete the given subtree? like suggested by O_TRUNC? not done so far!)
+.PP
+.PP
+If the third argument "ext" has another special meaning here, as it is used to ensure that a given zip\-file is created with the first entry of the ext\-list appended as an extension unless the file\-path already ends with a file\-extension registered in the list. Therefore {"",0} matches all files and creates them as zip\-archives under the given nonmodified name. (Some magic here? If the path ends in the path separator then make a real directory even in the presence of ext\-list?)
+.PP
+\fBThe zzip_dir_creat_ext_io function\fR
+is not yet implemented, check for #def ZZIP_NO_CREAT Write\-support will extend
+\fBzzip_closedir\fR
+with semantics to finalize the zip\-archive by writing the zip\-trailer and closing the archive file.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+
+/115 1154977710 1001 0 100644 26 `
+.so man3/zzip_dir_creat.3
+zzip_dirfd.3/ 1154977710 1001 0 100644 26 `
+.so man3/zzip_dirhandle.3
+/140 1154977710 1001 0 100644 1543 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_DIR_FDOPEN" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_dir_fdopen, zzip_dir_fdopen_ext_io \- (zzip/zip.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 27
+\fBZZIP_DIR\ *\ \fBzzip_dir_fdopen\fR\fR\fB(\fR\fBint\ fd\fR\fB, \fR\fBzzip_error_t\ *\ errcode_p\fR\fB);\fR
+.HP 34
+\fBZZIP_DIR\ *\ \fBzzip_dir_fdopen_ext_io\fR\fR\fB(\fR\fBint\ fd\fR\fB, \fR\fBzzip_error_t\ *\ errcode_p\fR\fB, \fR\fBzzip_strings_t*\ ext\fR\fB, \fR\fBconst\ zzip_plugin_io_t\ io\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+used by the
+\fBzzip_dir_open\fR
+and zzip_opendir(2) call. Opens the zip\-archive as specified with the fd which points to an already openend file.
+\fBThe zzip_dir_fdopen function\fR
+then search and parse the zip's central directory.
+.PP
+NOTE: refcount is zero, so an _open/_close pair will also delete this _dirhandle
+.PP
+\fBthe zzip_dir_fdopen_ext_io function\fR
+uses explicit ext and io instead of the internal defaults, setting these to zero is equivalent to
+\fBzzip_dir_fdopen\fR
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<too@iki.fi>
+.TP
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<too@iki.fi>
+
+/159 1154977710 1001 0 100644 27 `
+.so man3/zzip_dir_fdopen.3
+
+zzip_dir_free.3/1154977710 1001 0 100644 1347 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_DIR_FREE" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_dir_free, zzip_dir_close \- (zzip/zip.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 18
+\fBint\ \fBzzip_dir_free\fR\fR\fB(\fR\fBZZIP_DIR\ *\ dir\fR\fB);\fR
+.HP 19
+\fBint\ \fBzzip_dir_close\fR\fR\fB(\fR\fBZZIP_DIR\ *\ dir\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+will free the zzip_dir handle unless there are still zzip_files attached (that may use its cache buffer). This is the inverse of
+\fBzzip_dir_alloc\fR
+, and both are helper functions used implicitly in other zzipcalls e.g.
+\fBzzip_dir_close\fR
+= zzip_close
+.PP
+returns zero on sucess returns the refcount when files are attached.
+.PP
+It will also
+\fBfree\fR(2) the
+\fBZZIP_DIR\fR\-handle given. the counterpart for
+\fBzzip_dir_open\fR
+see also
+\fBzzip_dir_free\fR
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<too@iki.fi>
+.TP
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<too@iki.fi>
+
+/185 1154977710 1001 0 100644 1257 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_DIRHANDLE" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_dirhandle, zzip_dirfd \- (zzip/info.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 26
+\fBZZIP_DIR\ *\ \fBzzip_dirhandle\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB);\fR
+.HP 15
+\fBint\ \fBzzip_dirfd\fR\fR\fB(\fR\fBZZIP_DIR*\ dir\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe zzip_dirhandle function\fR
+will just return fp\->dir
+.PP
+If a ZZIP_FILE is contained within a zip\-file that one will be a valid pointer, otherwise a NULL is returned and the ZZIP_FILE wraps a real file.
+.PP
+\fBThe zzip_dirfd function\fR
+will just return dir\->fd
+.PP
+If a ZZIP_DIR does point to a zipfile then the file\-descriptor of that zipfile is returned, otherwise a NULL is returned and the ZZIP_DIR wraps a real directory DIR (if you have dirent on your system).
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+
+zzip_dir_open.3/1154977710 1001 0 100644 1709 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_DIR_OPEN" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_dir_open, zzip_dir_open_ext_io, zzip_dir_read \- (zzip/zip.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 24
+\fBZZIP_DIR*\ \fBzzip_dir_open\fR\fR\fB(\fR\fBzzip_char_t*\ filename\fR\fB, \fR\fBzzip_error_t*\ e\fR\fB);\fR
+.HP 31
+\fBZZIP_DIR*\ \fBzzip_dir_open_ext_io\fR\fR\fB(\fR\fBzzip_char_t*\ filename\fR\fB, \fR\fBzzip_error_t*\ e\fR\fB, \fR\fBzzip_strings_t*\ ext\fR\fB, \fR\fBzzip_plugin_io_t\ io\fR\fB);\fR
+.HP 18
+\fBint\ \fBzzip_dir_read\fR\fR\fB(\fR\fBZZIP_DIR\ *\ dir\fR\fB, \fR\fBZZIP_DIRENT\ *\ d\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+Opens the zip\-archive (if available). the two ext_io arguments will default to use posix io and a set of default fileext that can atleast add .zip ext itself.
+.PP
+\fBthe zzip_dir_open_ext_io function\fR
+uses explicit ext and io instead of the internal defaults. Setting these to zero is equivalent to
+\fBzzip_dir_open\fR
+.PP
+fills the dirent\-argument with the values and increments the read\-pointer of the dir\-argument.
+.PP
+returns 0 if there no entry (anymore).
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<too@iki.fi>
+.TP
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<too@iki.fi>
+.TP
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<too@iki.fi>
+
+/203 1154977710 1001 0 100644 25 `
+.so man3/zzip_dir_open.3
+
+zzip_dir_read.3/1154977710 1001 0 100644 25 `
+.so man3/zzip_dir_open.3
+
+zzip_dir_real.3/1154977710 1001 0 100644 26 `
+.so man3/zzip_file_real.3
+zzip_dir_stat.3/1154977710 1001 0 100644 2029 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_DIR_STAT" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_dir_stat, zzip_file_stat, zzip_fstat \- (zzip/stat.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 18
+\fBint\ \fBzzip_dir_stat\fR\fR\fB(\fR\fBZZIP_DIR\ *\ dir\fR\fB, \fR\fBzzip_char_t*\ name\fR\fB, \fR\fBZZIP_STAT\ *\ zs\fR\fB, \fR\fBint\ flags\fR\fB);\fR
+.HP 19
+\fBint\ \fBzzip_file_stat\fR\fR\fB(\fR\fBZZIP_FILE*\ file\fR\fB, \fR\fBZZIP_STAT*\ zs\fR\fB);\fR
+.HP 15
+\fBint\ \fBzzip_fstat\fR\fR\fB(\fR\fBZZIP_FILE*\ file\fR\fB, \fR\fBZZIP_STAT*\ zs\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+obtain information about a filename in an opened zip\-archive without opening that file first. Mostly used to obtain the uncompressed size of a file inside a zip\-archive. see
+\fBzzip_dir_open\fR.
+.PP
+\fBThe zzip_file_stat function\fR
+will obtain information about a opened file _within_ a zip\-archive. The file is supposed to be open (otherwise \-1 is returned). The st_size stat\-member contains the uncompressed size. The optional d_name is never set here.
+.PP
+\fBThe zzip_fstat function\fR
+will obtain information about a opened file which may be either real/zipped. The file is supposed to be open (otherwise \-1 is returned). The st_size stat\-member contains the uncompressed size. The optional d_name is never set here. For a real file, we do set the d_csize := st_size and d_compr := 0 for meaningful defaults.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+.TP
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+.TP
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+
+/227 1154977710 1001 0 100644 26 `
+.so man3/zzip_disk_mmap.3
+/246 1154977710 1001 0 100644 27 `
+.so man3/zzip_disk_fopen.3
+
+/271 1154977710 1001 0 100644 35 `
+.so man3/zzip_disk_entry_to_data.3
+
+/305 1154977710 1001 0 100644 35 `
+.so man3/zzip_disk_entry_to_data.3
+
+/336 1154977710 1001 0 100644 2418 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_DISK_ENTRY_TO_D" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_disk_entry_to_data, zzip_disk_entry_to_file_header, zzip_disk_entry_strdup_name, zzip_disk_entry_strdup_comment \- helper functions for (mmapped) zip access api
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 37
+\fBzzip_byte_t*\ \fBzzip_disk_entry_to_data\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB, \fR\fBstruct\ zzip_disk_entry*\ entry\fR\fB);\fR
+.HP 56
+\fBstruct\ zzip_file_header*\ \fBzzip_disk_entry_to_file_header\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB, \fR\fBstruct\ zzip_disk_entry*\ entry\fR\fB);\fR
+.HP 46
+\fBzzip__new__\ char*\ \fBzzip_disk_entry_strdup_name\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB, \fR\fBstruct\ zzip_disk_entry*\ entry\fR\fB);\fR
+.HP 49
+\fBzzip__new__\ char*\ \fBzzip_disk_entry_strdup_comment\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB, \fR\fBstruct\ zzip_disk_entry*\ entry\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+.PP
+\fBThe zzip_disk_entry_to_data function\fR
+augments the other zzip_disk_entry_* helpers: here we move a disk_entry pointer (as returned by _find* functions) into a pointer to the data block right after the file_header. Only disk\->buffer would be needed to perform the seek but we check the mmapped range end as well.
+.PP
+\fBThe zzip_disk_entry_to_file_header function\fR
+does half the job of
+\fBzzip_disk_entry_to_data\fR
+where it can augment with
+\fBzzip_file_header_to_data\fR
+helper from format/fetch.h
+.PP
+\fBThe zzip_disk_entry_strdup_name function\fR
+is a big helper despite its little name: in a zip file the encoded filenames are usually NOT zero\-terminated but for common usage with libc we need it that way. Secondly, the filename SHOULD be present in the zip central directory but if not then we fallback to the filename given in the file_header of each compressed data portion.
+.PP
+\fBThe zzip_disk_entry_strdup_comment function\fR
+is similar creating a reference to a zero terminated string but it can only exist in the zip central directory entry.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+/363 1154977710 1001 0 100644 35 `
+.so man3/zzip_disk_entry_to_data.3
+
+/397 1154977710 1001 0 100644 27 `
+.so man3/zzip_disk_fopen.3
+
+/417 1154977710 1001 0 100644 27 `
+.so man3/zzip_disk_fopen.3
+
+/435 1154977710 1001 0 100644 4351 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_DISK_FINDFILE" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_disk_findfile, zzip_disk_findfirst, zzip_disk_findnext, zzip_disk_findmatch \- search for files in the (mmapped) zip central directory
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 43
+\fBstruct\ zzip_disk_entry*\ \fBzzip_disk_findfile\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB, \fR\fBchar*\ filename\fR\fB, \fR\fBstruct\ zzip_disk_entry*\ after\fR\fB, \fR\fBzzip_strcmp_fn_t\ compare\fR\fB);\fR
+.HP 44
+\fBstruct\ zzip_disk_entry*\ \fBzzip_disk_findfirst\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB);\fR
+.HP 43
+\fBstruct\ zzip_disk_entry*\ \fBzzip_disk_findnext\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB, \fR\fBstruct\ zzip_disk_entry*\ entry\fR\fB);\fR
+.HP 44
+\fBstruct\ zzip_disk_entry*\ \fBzzip_disk_findmatch\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB, \fR\fBchar*\ filespec\fR\fB, \fR\fBstruct\ zzip_disk_entry*\ after\fR\fB, \fR\fBzzip_fnmatch_fn_t\ compare\fR\fB, \fR\fBint\ flags\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+.PP
+\fBThe zzip_disk_findfile function\fR
+is given a filename as an additional argument, to find the disk_entry matching a given filename. The compare\-function is usually strcmp or strcasecmp or perhaps strcoll, if null then strcmp is used. \- use null as argument for "after"\-entry when searching the first matching entry, otherwise the last returned value if you look for other entries with a special "compare" function (if null then a doubled search is rather useless with this variant of _findfile).
+.PP
+.PP
+\fBThe zzip_disk_findfirst function\fR
+is the first call of all the zip access functions here. It contains the code to find the first entry of the zip central directory. Here we require the mmapped block to represent a real zip file where the disk_trailer is _last_ in the file area, so that its position would be at a fixed offset from the end of the file area if not for the comment field allowed to be of variable length (which needs us to do a little search for the disk_tailer). However, in this simple implementation we disregard any disk_trailer info telling about multidisk archives, so we just return a pointer to the zip central directory.
+.PP
+For an actual means, we are going to search backwards from the end of the mmaped block looking for the PK\-magic signature of a disk_trailer. If we see one then we check the rootseek value to find the first disk_entry of the root central directory. If we find the correct PK\-magic signature of a disk_entry over there then we assume we are done and we are going to return a pointer to that label.
+.PP
+The return value is a pointer to the first zzip_disk_entry being checked to be within the bounds of the file area specified by the arguments. If no disk_trailer was found then null is returned, and likewise we only accept a disk_trailer with a seekvalue that points to a disk_entry and both parts have valid PK\-magic parts. Beyond some sanity check we try to catch a common brokeness with zip archives that still allows us to find the start of the zip central directory.
+.PP
+.PP
+\fBThe zzip_disk_findnext function\fR
+takes an existing disk_entry in the central root directory (e.g. from zzip_disk_findfirst) and returns the next entry within in the given bounds of the mmapped file area.
+.PP
+.PP
+\fBThe zzip_disk_findmatch function\fR
+uses a compare\-function with an additional argument and it is called just like fnmatch(3) from POSIX.2 AD:1993), i.e. the argument filespec first and the ziplocal filename second with the integer\-flags put in as third to the indirect call. If the platform has fnmatch available then null\-compare will use that one and otherwise we fall back to mere strcmp, so if you need fnmatch searching then please provide an implementation somewhere else. \- use null as argument for "after"\-entry when searching the first matching entry, or the last disk_entry return\-value to find the next entry matching the given filespec.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+
+/457 1154977710 1001 0 100644 30 `
+.so man3/zzip_disk_findfile.3
+/480 1154977710 1001 0 100644 30 `
+.so man3/zzip_disk_findfile.3
+/503 1154977710 1001 0 100644 30 `
+.so man3/zzip_disk_findfile.3
+/525 1154977710 1001 0 100644 2763 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_DISK_FOPEN" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_disk_fopen, zzip_disk_entry_fopen, zzip_disk_fread, zzip_disk_fclose, zzip_disk_feof \- openening a file part wrapped within a (mmapped) zip archive
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 44
+\fBzzip__new__\ ZZIP_DISK_FILE*\ \fBzzip_disk_fopen\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB, \fR\fBchar*\ filename\fR\fB);\fR
+.HP 50
+\fBzzip__new__\ ZZIP_DISK_FILE*\ \fBzzip_disk_entry_fopen\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB, \fR\fBZZIP_DISK_ENTRY*\ entry\fR\fB);\fR
+.HP 28
+\fBzzip_size_t\ \fBzzip_disk_fread\fR\fR\fB(\fR\fBvoid*\ ptr\fR\fB, \fR\fBzzip_size_t\ sized\fR\fB, \fR\fBzzip_size_t\ nmemb\fR\fB, \fR\fBZZIP_DISK_FILE*\ file\fR\fB);\fR
+.HP 21
+\fBint\ \fBzzip_disk_fclose\fR\fR\fB(\fR\fBZZIP_DISK_FILE*\ file\fR\fB);\fR
+.HP 19
+\fBint\ \fBzzip_disk_feof\fR\fR\fB(\fR\fBZZIP_DISK_FILE*\ file\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+.PP
+\fBThe zzip_disk_fopen function\fR
+opens a file found by name, so it does a search into the zip central directory with
+\fBzzip_disk_findfile\fR
+and whatever is found first is given to
+\fBzzip_disk_entry_fopen\fR
+.PP
+.PP
+the ZZIP_DISK_FILE* is rather simple in just encapsulating the arguments given to
+\fBthe zzip_disk_entry_fopen function\fR
+plus a zlib deflate buffer. Note that the ZZIP_DISK pointer does already contain the full mmapped file area of a zip disk, so open()ing a file part within that area happens to be a lookup of its bounds and encoding. That information is memorized on the ZZIP_DISK_FILE so that subsequent _read() operations will be able to get the next data portion or return an eof condition for that file part wrapped in the zip archive.
+.PP
+.PP
+\fBThe zzip_disk_fread function\fR
+reads more bytes into the output buffer specified as arguments. The return value is null on eof or error, the stdio\-like interface can not distinguish between these so you need to check with
+\fBzzip_disk_feof\fR
+for the difference.
+.PP
+\fBThe zzip_disk_fclose function\fR
+releases any zlib decoder info needed for decompression and dumps the ZZIP_DISK_FILE* then.
+.PP
+.PP
+\fBThe zzip_disk_feof function\fR
+allows to distinguish an error from an eof condition. Actually, if we found an error but we did already reach eof then we just keep on saying that it was an eof, so the app can just continue.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+
+/544 1154977710 1001 0 100644 27 `
+.so man3/zzip_disk_fopen.3
+
+/563 1154977710 1001 0 100644 26 `
+.so man3/zzip_disk_mmap.3
+/581 1154977710 1001 0 100644 2532 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_DISK_MMAP" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_disk_mmap, zzip_disk_init, zzip_disk_new, zzip_disk_munmap, zzip_disk_open, zzip_disk_close \- turn a filehandle into a mmapped zip disk archive handle
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 38
+\fBzzip__new__\ ZZIP_DISK*\ \fBzzip_disk_mmap\fR\fR\fB(\fR\fBint\ fd\fR\fB);\fR
+.HP 19
+\fBint\ \fBzzip_disk_init\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB, \fR\fBvoid*\ buffer\fR\fB, \fR\fBzzip_size_t\ buflen\fR\fB);\fR
+.HP 37
+\fBzzip__new__\ ZZIP_DISK*\ \fBzzip_disk_new\fR\fR\fB(\fR\fBvoid\fR\fB);\fR
+.HP 21
+\fBint\ \fBzzip_disk_munmap\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB);\fR
+.HP 38
+\fBZZIP_DISK*\ zzip__new__\ \fBzzip_disk_open\fR\fR\fB(\fR\fBchar*\ filename\fR\fB);\fR
+.HP 20
+\fBint\ \fBzzip_disk_close\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+.PP
+\fBThe zzip_disk_mmap function\fR
+uses the given file\-descriptor to detect the length of the file and calls the system
+\fBmmap\fR(2) to put it in main memory. If it is successful then a newly allocated ZZIP_DISK* is returned with disk\->buffer pointing to the mapview of the zipdisk content.
+.PP
+\fBThe zzip_disk_init function\fR
+does primary initialization of a disk\-buffer struct.
+.PP
+\fBThe zzip_disk_new function\fR
+allocates a new disk\-buffer with
+\fBmalloc\fR(3)
+.PP
+\fBThe zzip_disk_munmap function\fR
+is the inverse of
+\fBzzip_disk_mmap\fR
+and using the system munmap(2) on the buffer area and
+\fBfree\fR(3) on the ZZIP_DISK structure.
+.PP
+.PP
+\fBThe zzip_disk_open function\fR
+opens the given archive by name and turn the filehandle to
+\fBzzip_disk_mmap\fR
+for bringing it to main memory. If it can not be
+\fBmmap\fR(2)'ed then we slurp the whole file into a newly
+\fBmalloc\fR(2)'ed memory block. Only if that fails too then we return null. Since handling of disk\->buffer is ambigous it should not be snatched away please.
+.PP
+.PP
+\fBThe zzip_disk_close function\fR
+will release all data needed to access a (mmapped) zip archive, including any malloc()ed blocks, sharedmem mappings and it dumps the handle struct as well.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+/599 1154977710 1001 0 100644 26 `
+.so man3/zzip_disk_mmap.3
+zzip_disk_new.3/1154977710 1001 0 100644 26 `
+.so man3/zzip_disk_mmap.3
+/619 1154977710 1001 0 100644 26 `
+.so man3/zzip_disk_mmap.3
+/637 1154977710 1001 0 100644 2171 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_ENTRY_DATA_OFFS" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_entry_data_offset, zzip_entry_fread_file_header, zzip_entry_strdup_name \- helper functions for (fseeko) zip access api
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 34
+\fBzzip_off_t\ \fBzzip_entry_data_offset\fR\fR\fB(\fR\fBZZIP_ENTRY*\ entry\fR\fB);\fR
+.HP 47
+\fBstatic\ zzip_off_t\ \fBzzip_entry_fread_file_header\fR\fR\fB(\fR\fBZZIP_ENTRY*\ entry\fR\fB, \fR\fBstruct\ zzip_file_header*\ file_header\fR\fB);\fR
+.HP 41
+\fBzzip__new__\ char*\ \fBzzip_entry_strdup_name\fR\fR\fB(\fR\fBZZIP_ENTRY*\ entry\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+.PP
+\fBThe zzip_entry_data_offset function\fRs returns the seekval offset of the data portion of the file referenced by the given zzip_entry. It requires an intermediate check of the file_header structure (i.e. it reads it from disk). After this call, the contained diskfile readposition is already set to the data_offset returned here. On error \-1 is returned.
+.PP
+\fBThe zzip_entry_fread_file_header function\fRs read the correspoding struct zzip_file_header from the zip disk of the given "entry". The returned off_t points to the end of the file_header where the current fseek pointer has stopped. This is used to immediatly parse out any filename/extras block following the file_header. The return value is null on error.
+.PP
+\fBThe zzip_entry_strdup_name function\fR
+is a big helper despite its little name: in a zip file the encoded filenames are usually NOT zero\-terminated but for common usage with libc we need it that way. Secondly, the filename SHOULD be present in the zip central directory but if not then we fallback to the filename given in the file_header of each compressed data portion.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+
+/663 1154977710 1001 0 100644 28 `
+.so man3/zzip_entry_fopen.3
+/684 1154977710 1001 0 100644 28 `
+.so man3/zzip_entry_fopen.3
+/703 1154977710 1001 0 100644 28 `
+.so man3/zzip_entry_fopen.3
+/723 1154977710 1001 0 100644 5123 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_ENTRY_FINDFILE" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_entry_findfile, zzip_entry_findfirst, zzip_entry_findnext, zzip_entry_free, zzip_entry_findmatch \- search for files in the (fseeko) zip central directory
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 44
+\fBzzip__new__\ ZZIP_ENTRY*\ \fBzzip_entry_findfile\fR\fR\fB(\fR\fBFILE*\ disk\fR\fB, \fR\fBchar*\ filename\fR\fB, \fR\fBZZIP_ENTRY*\ _zzip_restrict\ entry\fR\fB, \fR\fBzzip_strcmp_fn_t\ compare\fR\fB);\fR
+.HP 45
+\fBzzip__new__\ ZZIP_ENTRY*\ \fBzzip_entry_findfirst\fR\fR\fB(\fR\fBFILE*\ disk\fR\fB);\fR
+.HP 44
+\fBzzip__new__\ ZZIP_ENTRY*\ \fBzzip_entry_findnext\fR\fR\fB(\fR\fBZZIP_ENTRY*\ _zzip_restrict\ entry\fR\fB);\fR
+.HP 20
+\fBint\ \fBzzip_entry_free\fR\fR\fB(\fR\fBZZIP_ENTRY*\ entry\fR\fB);\fR
+.HP 45
+\fBzzip__new__\ ZZIP_ENTRY*\ \fBzzip_entry_findmatch\fR\fR\fB(\fR\fBFILE*\ disk\fR\fB, \fR\fBchar*\ filespec\fR\fB, \fR\fBZZIP_ENTRY*\ _zzip_restrict\ entry\fR\fB, \fR\fBzzip_fnmatch_fn_t\ compare\fR\fB, \fR\fBint\ flags\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+.PP
+\fBThe zzip_entry_findfile function\fR
+is given a filename as an additional argument, to find the disk_entry matching a given filename. The compare\-function is usually strcmp or strcasecmp or perhaps strcoll, if null then strcmp is used. \- use null as argument for "old"\-entry when searching the first matching entry, otherwise the last returned value if you look for other entries with a special "compare" function (if null then a doubled search is rather useless with this variant of _findfile). If no further entry is found then null is returned and any "old"\-entry gets already free()d.
+.PP
+.PP
+\fBThe zzip_entry_findfirst function\fR
+is the first call of all the zip access functions here. It contains the code to find the first entry of the zip central directory. Here we require the stdio handle to represent a real zip file where the disk_trailer is _last_ in the file area, so that its position would be at a fixed offset from the end of the file area if not for the comment field allowed to be of variable length (which needs us to do a little search for the disk_tailer). However, in this simple implementation we disregard any disk_trailer info telling about multidisk archives, so we just return a pointer to the first entry in the zip central directory of that file.
+.PP
+For an actual means, we are going to search backwards from the end of the mmaped block looking for the PK\-magic signature of a disk_trailer. If we see one then we check the rootseek value to find the first disk_entry of the root central directory. If we find the correct PK\-magic signature of a disk_entry over there then we assume we are done and we are going to return a pointer to that label.
+.PP
+The return value is a pointer to the first zzip_disk_entry being checked to be within the bounds of the file area specified by the arguments. If no disk_trailer was found then null is returned, and likewise we only accept a disk_trailer with a seekvalue that points to a disk_entry and both parts have valid PK\-magic parts. Beyond some sanity check we try to catch a common brokeness with zip archives that still allows us to find the start of the zip central directory.
+.PP
+.PP
+\fBThe zzip_entry_findnext function\fR
+takes an existing "entry" in the central root directory (e.g. from zzip_entry_findfirst) and moves it to point to the next entry. On error it returns 0, otherwise the old entry. If no further match is found then null is returned and the entry already free()d. If you want to stop searching for matches before that case then please call
+\fBzzip_entry_free\fR
+on the cursor struct ZZIP_ENTRY.
+.PP
+\fBthe zzip_entry_free function\fR
+releases the malloc()ed areas needed for zzip_entry, the pointer is invalid afterwards.
+\fBThe zzip_entry_free function\fR
+has #define synonyms of zzip_entry_findlast(), zzip_entry_findlastfile(), zzip_entry_findlastmatch()
+.PP
+.PP
+\fBThe zzip_entry_findmatch function\fR
+uses a compare\-function with an additional argument and it is called just like fnmatch(3) from POSIX.2 AD:1993), i.e. the argument filespec first and the ziplocal filename second with the integer\-flags put in as third to the indirect call. If the platform has fnmatch available then null\-compare will use that one and otherwise we fall back to mere strcmp, so if you need fnmatch searching then please provide an implementation somewhere else. \- use null as argument for "after"\-entry when searching the first matching entry, or the last disk_entry return\-value to find the next entry matching the given filespec. If no further entry is found then null is returned and any "old"\-entry gets already free()d.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+
+/746 1154977710 1001 0 100644 31 `
+.so man3/zzip_entry_findfile.3
+
+/770 1154977710 1001 0 100644 31 `
+.so man3/zzip_entry_findfile.3
+
+/794 1154977710 1001 0 100644 31 `
+.so man3/zzip_entry_findfile.3
+
+/817 1154977710 1001 0 100644 2825 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_ENTRY_FOPEN" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_entry_fopen, zzip_entry_ffile, zzip_entry_fread, zzip_entry_fclose, zzip_entry_feof \- open a file within a zip disk for reading
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 46
+\fBzzip__new__\ ZZIP_ENTRY_FILE*\ \fBzzip_entry_fopen\fR\fR\fB(\fR\fBZZIP_ENTRY*\ entry\fR\fB, \fR\fBint\ takeover\fR\fB);\fR
+.HP 46
+\fBzzip__new__\ ZZIP_ENTRY_FILE*\ \fBzzip_entry_ffile\fR\fR\fB(\fR\fBFILE*\ disk\fR\fB, \fR\fBchar*\ filename\fR\fB);\fR
+.HP 29
+\fBzzip_size_t\ \fBzzip_entry_fread\fR\fR\fB(\fR\fBvoid*\ ptr\fR\fB, \fR\fBzzip_size_t\ sized\fR\fB, \fR\fBzzip_size_t\ nmemb\fR\fB, \fR\fBZZIP_ENTRY_FILE*\ file\fR\fB);\fR
+.HP 22
+\fBint\ \fBzzip_entry_fclose\fR\fR\fB(\fR\fBZZIP_ENTRY_FILE*\ file\fR\fB);\fR
+.HP 20
+\fBint\ \fBzzip_entry_feof\fR\fR\fB(\fR\fBZZIP_ENTRY_FILE*\ file\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+.PP
+\fBThe zzip_entry_fopen function\fR
+does take an "entry" argument and copies it (or just takes it over as owner) to a new ZZIP_ENTRY_FILE handle structure. That structure contains also a zlib buffer for decoding.
+\fBThe zzip_entry_fopen function\fR
+does seek to the file_header of the given "entry" and validates it for the data buffer following it. We do also prefetch some data from the data buffer thereby trying to match the disk pagesize for faster access later. The
+\fBzzip_entry_fread\fR
+will then read in chunks of pagesizes which is the size of the internal readahead buffer. If an error occurs then null is returned.
+.PP
+.PP
+\fBThe zzip_entry_ffile function\fR
+opens a file found by name, so it does a search into the zip central directory with
+\fBzzip_entry_findfile\fR
+and whatever is found first is given to
+\fBzzip_entry_fopen\fR
+.PP
+.PP
+\fBThe zzip_entry_fread function\fR
+reads more bytes into the output buffer specified as arguments. The return value is null on eof or error, the stdio\-like interface can not distinguish between these so you need to check with
+\fBzzip_entry_feof\fR
+for the difference.
+.PP
+\fBThe zzip_entry_fclose function\fR
+releases any zlib decoder info needed for decompression and dumps the ZZIP_ENTRY_FILE struct then.
+.PP
+.PP
+\fBThe zzip_entry_feof function\fR
+allows to distinguish an error from an eof condition. Actually, if we found an error but we did already reach eof then we just keep on saying that it was an eof, so the app can just continue.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+
+/837 1154977710 1001 0 100644 28 `
+.so man3/zzip_entry_fopen.3
+/857 1154977710 1001 0 100644 34 `
+.so man3/zzip_entry_data_offset.3
+/889 1154977710 1001 0 100644 31 `
+.so man3/zzip_entry_findfile.3
+
+/908 1154977710 1001 0 100644 34 `
+.so man3/zzip_entry_data_offset.3
+zzip_errno.3/ 1154977710 1001 0 100644 988 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_ERRNO" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_errno \- (zzip/err.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 15
+\fBint\ \fBzzip_errno\fR\fR\fB(\fR\fBint\ errcode\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+map the error code to a system error code. This is used for the drop\-in replacement functions to return a value that can be interpreted correctly by code sections that are unaware of the fact they their
+\fBopen\fR(2) call had been diverted to a file inside a zip\-archive.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+zzip_error.3/ 1154977710 1001 0 100644 1001 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_ERROR" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_error, zzip_seterror \- (zzip/info.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 15
+\fBint\ \fBzzip_error\fR\fR\fB(\fR\fBZZIP_DIR\ *\ dir\fR\fB);\fR
+.HP 19
+\fBvoid\ \fBzzip_seterror\fR\fR\fB(\fR\fBZZIP_DIR\ *\ dir\fR\fB, \fR\fBint\ errcode\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+just returns dir\->errcode of the ZZIP_DIR handle see:
+\fBzzip_dir_open\fR,
+\fBzzip_diropen\fR,
+\fBzzip_readdir\fR,
+\fBzzip_dir_read\fR
+.PP
+\fBThe zzip_seterror function\fR
+just does dir\->errcode = errcode
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+
+zzip_fclose.3/ 1154977710 1001 0 100644 1094 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_FCLOSE" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_fclose, zzip_close \- (zzip/file.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 16
+\fBint\ \fBzzip_fclose\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB);\fR
+.HP 15
+\fBint\ \fBzzip_close\fR\fR\fB(\fR\fBZZIP_FILE*\ fp\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe zzip_fclose function\fR
+closes the given ZZIP_FILE handle.
+.PP
+If the ZZIP_FILE wraps a normal stat'fd then it is just that int'fd that is being closed and the otherwise empty ZZIP_FILE gets freed.
+.PP
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+.TP
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+/934 1154977710 1001 0 100644 1053 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "__ZZIP_FETCH_DISK_TR" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+__zzip_fetch_disk_trailer \- (zzip/zip.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 30
+\fBint\ \fB__zzip_fetch_disk_trailer\fR\fR\fB(\fR\fBint\ fd\fR\fB, \fR\fBzzip_off_t\ filesize\fR\fB, \fR\fBstruct\ _disk_trailer\ *\ _zzip_restrict\ trailer\fR\fB, \fR\fBzzip_plugin_io_t\ io\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe __zzip_fetch_disk_trailer function\fR
+is used by
+\fBzzip_file_open\fR. It tries to find the zip's central directory info that is usually a few bytes off the end of the file.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<too@iki.fi>
+
+/963 1154977710 1001 0 100644 1031 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_FILE_CLOSE" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_file_close \- (zzip/file.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 20
+\fBint\ \fBzzip_file_close\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+the direct function of
+\fBzzip_close\fR(fp). it will cleanup the inflate\-portion of
+\fBzlib\fR
+and free the structure given.
+.PP
+it is called quite from the error\-cleanup parts of the various
+\fB_open\fR
+functions.
+.PP
+the .refcount is decreased and if zero the fp\->dir is closed just as well.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+
+/982 1154977710 1001 0 100644 3089 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_FILE_CREAT" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_file_creat, zzip_file_mkdir \- start next file entry in a zip archive
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 27
+\fBZZIP_FILE*\ \fBzzip_file_creat\fR\fR\fB(\fR\fBZZIP_DIR*\ dir\fR\fB, \fR\fBzzip_char_t*\ name\fR\fB, \fR\fBint\ o_mode\fR\fB);\fR
+.HP 20
+\fBint\ \fBzzip_file_mkdir\fR\fR\fB(\fR\fBZZIP_DIR*\ dir\fR\fB, \fR\fBzzip_char_t*\ name\fR\fB, \fR\fBint\ o_mode\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+.PP
+\fBThe zzip_file_creat function\fR
+will create a new file within a zzip archive, the one given as the primary argument and additionally to the posix creat(2) \- just like zzip_mkdir has an additional argument over the posix mkdir(2) spec. For
+\fBthe zzip_file_creat function\fR
+the primary parameter can be null as well thereby creating a real file instead of a new one inside the zip\-archive otherwise given. If the primary parameter is not null but wraps a real directory then all new files are also real.
+.PP
+\fBThe zzip_file_creat function\fR
+is not yet implemented, check for #def ZZIP_NO_CREAT
+.PP
+Returns NULL on an error setting errno, and opening a file _within_ a zip archive using O_RDONLY (and similar stuff) will surely lead to an error.
+.PP
+.PP
+\fBThe zzip_file_mkdir function\fR
+has an additional primary argument over the posix mkdir(2) \- if it is null then
+\fBthe zzip_file_mkdir function\fR
+behaves just like posix mkdir(2). The zzip_dir argument can be set to the result of a
+\fBzzip_createdir\fR
+which allows for some magic that the given directory name is created as an entry in the zip archive.
+.PP
+If the given dir name argument is not within the basepath of the zip central directory then a real directory is created. Any EEXIST errors are not suppressed unlike with
+\fBzzip_createdir\fR
+.PP
+Standard usage accepts a global/threaded/modular ZZIP_DIR pointer for all zip archive operations like in:
+.sp
+.nf
+ ZZIP_DIR* zip = zzip_createdir (sysconfpath, 0755, zip);
+ zzip_file_mkdir (zip, filepath[i], 0755);
+ ZZIP_FILE* file = zzip_file_creat (zip, filename[i], 0644);
+ zzip_write (file, buf, len);
+ zzip_close (file); file = 0;
+ zzip_closedir (zip); zip = 0;
+.fi
+.sp
+.PP
+compare with
+\fBzzip_mkdir\fR
+inline macro which allows to collapse the examples script to
+.sp
+.nf
+ #define zzip_savefile myproject_saveconfig
+ #include <zzip/zzip.h>
+ ZZIP_DIR* zzip_savefile = zzip_createdir (sysconfpath, 0755);
+ zzip_mkdir (filepath[i], 0755);
+ ZZIP_FILE* file = zzip_creat(filepath[i], 0644);
+ zzip_write (file, buf, len);
+ zzip_close (file); file = 0;
+ zzip_closedir (zip_savefile);
+.fi
+.sp
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+
+/1001 1154977710 1001 0 100644 27 `
+.so man3/zzip_file_creat.3
+
+/1020 1154977710 1001 0 100644 1105 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_FILE_OPEN" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_file_open \- (zzip/file.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 27
+\fBZZIP_FILE\ *\ \fBzzip_file_open\fR\fR\fB(\fR\fBZZIP_DIR\ *\ dir\fR\fB, \fR\fBzzip_char_t*\ name\fR\fB, \fR\fBint\ o_mode\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+open an
+\fBZZIP_FILE\fR
+from an already open
+\fBZZIP_DIR\fR
+handle. Since we have a chance to reuse a cached
+\fBbuf32k\fR
+and
+\fBZZIP_FILE\fR
+memchunk this is the best choice to unpack multiple files.
+.PP
+Note: the zlib supports 2..15 bit windowsize, hence we provide a 32k memchunk here... just to be safe.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+
+/1038 1154977710 1001 0 100644 1400 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_FILE_READ" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_file_read \- (zzip/file.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 28
+\fBzzip_ssize_t\ \fBzzip_file_read\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB, \fR\fBchar\ *\ buf\fR\fB, \fR\fBzzip_size_t\ len\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe zzip_file_read function\fRs read data from zip\-contained file.
+.PP
+It works like
+\fBread\fR(2) and will fill the given buffer with bytes from the opened file. It will return the number of bytes read, so if the
+\fBEOF\fR
+is encountered you will be prompted with the number of bytes actually read.
+.PP
+This is the routines that needs the
+\fBbuf32k\fR
+buffer, and it would have need for much more polishing but it does already work quite well.
+.PP
+Note: the 32K buffer is rather big. The original inflate\-algorithm required just that but the latest zlib would work just fine with a smaller buffer.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+/1056 1154977710 1001 0 100644 1662 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_FILE_REAL" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_file_real, zzip_dir_real, zzip_realdir, zzip_realfd \- (zzip/info.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 19
+\fBint\ \fBzzip_file_real\fR\fR\fB(\fR\fBZZIP_FILE*\ fp\fR\fB);\fR
+.HP 18
+\fBint\ \fBzzip_dir_real\fR\fR\fB(\fR\fBZZIP_DIR*\ dir\fR\fB);\fR
+.HP 19
+\fBvoid*\ \fBzzip_realdir\fR\fR\fB(\fR\fBZZIP_DIR*\ dir\fR\fB);\fR
+.HP 16
+\fBint\ \fBzzip_realfd\fR\fR\fB(\fR\fBZZIP_FILE*\ fp\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe zzip_file_real function\fR
+checks if the ZZIP_FILE\-handle is wrapping a real file or a zip\-contained file. Returns 1 for a stat'able file, and 0 for a file inside a zip\-archive.
+.PP
+\fBThe zzip_dir_real function\fR
+checks if the ZZIP_DIR\-handle is wrapping a real directory or a zip\-archive. Returns 1 for a stat'able directory, and 0 for a handle to zip\-archive.
+.PP
+\fBThe zzip_realdir function\fR
+returns the posix DIR* handle (if one exists). Check before with
+\fBzzip_dir_real\fR
+if the the ZZIP_DIR points to a real directory.
+.PP
+\fBThe zzip_realfd function\fR
+returns the posix file descriptor (if one exists). Check before with
+\fBzzip_file_real\fR
+if the the ZZIP_FILE points to a real file.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+/1074 1154977710 1001 0 100644 25 `
+.so man3/zzip_dir_stat.3
+
+/1092 1154977710 1001 0 100644 22 `
+.so man3/zzip_write.3
+zzip_fopen.3/ 1154977710 1001 0 100644 4212 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_FOPEN" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_fopen, zzip_freopen \- (zzip/file.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 22
+\fBZZIP_FILE*\ \fBzzip_fopen\fR\fR\fB(\fR\fBzzip_char_t*\ filename\fR\fB, \fR\fBzzip_char_t*\ mode\fR\fB);\fR
+.HP 24
+\fBZZIP_FILE*\ \fBzzip_freopen\fR\fR\fB(\fR\fBzzip_char_t*\ filename\fR\fB, \fR\fBzzip_char_t*\ mode\fR\fB, \fR\fBZZIP_FILE*\ stream\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe zzip_fopen function\fR
+will
+\fBfopen\fR(3) a real/zipped file.
+.PP
+It has some magic functionality builtin \- it will first try to open the given
+\fIfilename\fR
+as a normal file. If it does not exist, the given path to the filename (if any) is split into its directory\-part and the file\-part. A ".zip" extension is then added to the directory\-part to create the name of a zip\-archive. That zip\-archive (if it exists) is being searched for the file\-part, and if found a zzip\-handle is returned.
+.PP
+Note that if the file is found in the normal fs\-directory the returned structure is mostly empty and the
+\fBzzip_read\fR
+call will use the libc
+\fBread\fR
+to obtain data. Otherwise a
+\fBzzip_file_open\fR
+is performed and any error mapped to
+\fBerrno\fR(3).
+.PP
+unlike the posix\-wrapper
+\fBzzip_open\fR
+the mode\-argument is a string which allows for more freedom to support the extra zzip modes called ZZIP_CASEINSENSITIVE and ZZIP_IGNOREPATH. Currently, this
+\fBzzip_fopen\fR
+call will convert the following characters in the mode\-string into their corrsponding mode\-bits:
+.sp
+.nf
+\fB "r" : O_RDONLY : \fR read\-only
+ \fB "b" : O_BINARY : \fR binary (win32 specific)
+ \fB "f" : O_NOCTTY : \fR no char device (unix)
+ \fB "i" : ZZIP_CASELESS : \fR inside zip file
+ \fB "*" : ZZIP_NOPATHS : \fR inside zip file only
+
+.fi
+.PP
+all other modes will be ignored for zip\-contained entries but they are transferred for compatibility and portability, including these extra sugar bits:
+.sp
+.nf
+\fB "x" : O_EXCL :\fR fail if file did exist
+ \fB "s" : O_SYNC :\fR synchronized access
+ \fB "n" : O_NONBLOCK :\fR nonblocking access
+ \fB "z#" : compression level :\fR for zlib
+ \fB "g#" : group access :\fR unix access bits
+ \fB "u#" : owner access :\fR unix access bits
+ \fB "o#" : world access :\fR unix access bits
+
+.fi
+.PP
+... the access bits are in traditional unix bit format with 7 = read/write/execute, 6 = read/write, 4 = read\-only.
+.PP
+The default access mode is 0664, and the compression level is ignored since the lib can not yet write zip files, otherwise it would be the initialisation value for the zlib deflateInit where 0 = no\-compression, 1 = best\-speed, 9 = best\-compression.
+.PP
+.PP
+\fBThe zzip_freopen function\fR
+receives an additional argument pointing to a ZZIP_FILE* being already in use. If this extra argument is null then
+\fBthe zzip_freopen function\fR
+is identical with calling
+\fBzzip_fopen\fR
+.PP
+Per default, the old file stream is closed and only the internal structures associated with it are kept. These internal structures may be reused for the return value, and this is a lot quicker when the filename matches a zipped file that is incidently in the very same zip arch as the old filename wrapped in the stream struct.
+.PP
+That's simply because the zip arch's central directory does not need to be read again. As an extension for
+\fBthe zzip_freopen function\fR, if the mode\-string contains a "q" then the old stream is not closed but left untouched, instead it is only given as a hint that a new file handle may share/copy the zip arch structures of the old file handle if that is possible, i.e when they are in the same zip arch.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+.TP
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+zzip_fread.3/ 1154977710 1001 0 100644 21 `
+.so man3/zzip_read.3
+
+zzip_freopen.3/ 1154977710 1001 0 100644 22 `
+.so man3/zzip_fopen.3
+zzip_fstat.3/ 1154977710 1001 0 100644 25 `
+.so man3/zzip_dir_stat.3
+
+zzip_fwrite.3/ 1154977710 1001 0 100644 22 `
+.so man3/zzip_write.3
+__zzip_get16.3/ 1154977710 1001 0 100644 24 `
+.so man3/__zzip_get32.3
+__zzip_get32.3/ 1154977710 1001 0 100644 1714 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "__ZZIP_GET32" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+__zzip_get32, __zzip_get16, __zzip_get64, __zzip_set32, __zzip_set16, __zzip_set64 \- (zzip/fetch.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 22
+\fBuint32_t\ \fB__zzip_get32\fR\fR\fB(\fR\fBunsigned\ char\ *\ s\fR\fB);\fR
+.HP 22
+\fBuint16_t\ \fB__zzip_get16\fR\fR\fB(\fR\fBunsigned\ char\ *\ s\fR\fB);\fR
+.HP 22
+\fBuint64_t\ \fB__zzip_get64\fR\fR\fB(\fR\fBunsigned\ char\ *\ s\fR\fB);\fR
+.HP 18
+\fBvoid\ \fB__zzip_set32\fR\fR\fB(\fR\fBunsigned\ char\ *\ s\fR\fB, \fR\fBuint32_t\ v\fR\fB);\fR
+.HP 18
+\fBvoid\ \fB__zzip_set16\fR\fR\fB(\fR\fBunsigned\ char\ *\ s\fR\fB, \fR\fBuint16_t\ v\fR\fB);\fR
+.HP 18
+\fBvoid\ \fB__zzip_set64\fR\fR\fB(\fR\fBunsigned\ char\ *\ s\fR\fB, \fR\fBuint64_t\ v\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+Make 32 bit value in host byteorder from little\-endian mapped octet\-data (works also on machines which SIGBUS on misaligned data access (eg. 68000))
+.PP
+\fBThe __zzip_get16 function\fR
+does the same for a 16 bit value.
+.PP
+\fBThe __zzip_get64 function\fR
+does the same for an off64_t value.
+.PP
+\fBThe __zzip_set32 function\fR
+pushes a 32bit value at the specified address
+.PP
+\fBThe __zzip_set16 function\fR
+does the same for a 16 bit value.
+.PP
+\fBThe __zzip_set64 function\fR
+pushes a off64_t value at the specified address
+__zzip_get64.3/ 1154977710 1001 0 100644 24 `
+.so man3/__zzip_get32.3
+/1111 1154977710 1001 0 100644 24 `
+.so man3/zzip_init_io.3
+/1134 1154977710 1001 0 100644 886 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_INFLATE_INIT" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_inflate_init \- (zzip/file.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 29
+\fBstatic\ int\ \fBzzip_inflate_init\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB, \fR\fBstruct\ zzip_dir_hdr*\ hdr\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+call
+\fBinflateInit\fR
+and setup fp's iterator variables, used by lowlevel
+\fB_open\fR
+functions.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+zzip_init_io.3/ 1154977710 1001 0 100644 1257 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_INIT_IO" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_init_io, zzip_get_default_io \- (zzip/plugin.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 17
+\fBint\ \fBzzip_init_io\fR\fR\fB(\fR\fBzzip_plugin_io_handlers_t\ io\fR\fB, \fR\fBint\ flags\fR\fB);\fR
+.HP 37
+\fBzzip_plugin_io_t\ \fBzzip_get_default_io\fR\fR\fB(\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe zzip_init_io function\fR
+initializes the users handler struct to default values being the posix io functions in default configured environments.
+.PP
+\fBThe zzip_get_default_io function\fR
+returns a zzip_plugin_io_t handle to static defaults wrapping the posix io file functions for actual file access.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Mike Nordell
+<tamlin\-@\-algonet\-se>
+.TP
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Mike Nordell
+<tamlin\-@\-algonet\-se>
+
+zziplib.h.3/ 1154977710 1001 0 100644 6218 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIPLIB.H" "3" "0.13.47" "the library zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zziplib.h \- library
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 20
+\fBvoid\ \fBzzip_rewinddir\fR\fR\fB(\fR\fBZZIP_DIR\ *\ dir\fR\fB);\fR
+.HP 26
+\fBZZIP_DIRENT*\ \fBzzip_readdir\fR\fR\fB(\fR\fBZZIP_DIR\ *\ dir\fR\fB);\fR
+.HP 23
+\fBZZIP_DIR*\ \fBzzip_opendir\fR\fR\fB(\fR\fBzzip_char_t*\ filename\fR\fB);\fR
+.HP 18
+\fBint\ \fBzzip_closedir\fR\fR\fB(\fR\fBZZIP_DIR*\ dir\fR\fB);\fR
+.HP 27
+\fBzzip_char_t*\ \fBzzip_strerror\fR\fR\fB(\fR\fBint\ errcode\fR\fB);\fR
+.HP 15
+\fBint\ \fBzzip_errno\fR\fR\fB(\fR\fBint\ errcode\fR\fB);\fR
+.HP 22
+\fBuint32_t\ \fB__zzip_get32\fR\fR\fB(\fR\fBunsigned\ char\ *\ s\fR\fB);\fR
+.HP 20
+\fBint\ \fBzzip_file_close\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB);\fR
+.HP 27
+\fBZZIP_FILE\ *\ \fBzzip_file_open\fR\fR\fB(\fR\fBZZIP_DIR\ *\ dir\fR\fB, \fR\fBzzip_char_t*\ name\fR\fB, \fR\fBint\ o_mode\fR\fB);\fR
+.HP 29
+\fBstatic\ int\ \fBzzip_inflate_init\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB, \fR\fBstruct\ zzip_dir_hdr*\ hdr\fR\fB);\fR
+.HP 16
+\fBint\ \fBzzip_fclose\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB);\fR
+.HP 28
+\fBzzip_ssize_t\ \fBzzip_file_read\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB, \fR\fBchar\ *\ buf\fR\fB, \fR\fBzzip_size_t\ len\fR\fB);\fR
+.HP 23
+\fBzzip_ssize_t\ \fBzzip_read\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB, \fR\fBchar\ *\ buf\fR\fB, \fR\fBzzip_size_t\ len\fR\fB);\fR
+.HP 22
+\fBZZIP_FILE*\ \fBzzip_fopen\fR\fR\fB(\fR\fBzzip_char_t*\ filename\fR\fB, \fR\fBzzip_char_t*\ mode\fR\fB);\fR
+.HP 21
+\fBZZIP_FILE*\ \fBzzip_open\fR\fR\fB(\fR\fBzzip_char_t*\ filename\fR\fB, \fR\fBint\ o_flags\fR\fB);\fR
+.HP 16
+\fBint\ \fBzzip_rewind\fR\fR\fB(\fR\fBZZIP_FILE\ *fp\fR\fB);\fR
+.HP 21
+\fBzzip_off_t\ \fBzzip_seek\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB, \fR\fBzzip_off_t\ offset\fR\fB, \fR\fBint\ whence\fR\fB);\fR
+.HP 21
+\fBzzip_off_t\ \fBzzip_tell\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB);\fR
+.HP 34
+\fBzzip_off_t\ \fBzzip_entry_data_offset\fR\fR\fB(\fR\fBZZIP_ENTRY*\ entry\fR\fB);\fR
+.HP 44
+\fBzzip__new__\ ZZIP_ENTRY*\ \fBzzip_entry_findfile\fR\fR\fB(\fR\fBFILE*\ disk\fR\fB, \fR\fBchar*\ filename\fR\fB, \fR\fBZZIP_ENTRY*\ _zzip_restrict\ entry\fR\fB, \fR\fBzzip_strcmp_fn_t\ compare\fR\fB);\fR
+.HP 46
+\fBzzip__new__\ ZZIP_ENTRY_FILE*\ \fBzzip_entry_fopen\fR\fR\fB(\fR\fBZZIP_ENTRY*\ entry\fR\fB, \fR\fBint\ takeover\fR\fB);\fR
+.HP 15
+\fBint\ \fBzzip_error\fR\fR\fB(\fR\fBZZIP_DIR\ *\ dir\fR\fB);\fR
+.HP 26
+\fBZZIP_DIR\ *\ \fBzzip_dirhandle\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB);\fR
+.HP 28
+\fBzzip_char_t*\ \fBzzip_compr_str\fR\fR\fB(\fR\fBint\ compr\fR\fB);\fR
+.HP 19
+\fBint\ \fBzzip_file_real\fR\fR\fB(\fR\fBZZIP_FILE*\ fp\fR\fB);\fR
+.HP 46
+\fBzzip__new__\ ZZIP_MEM_DISK*\ \fBzzip_mem_disk_open\fR\fR\fB(\fR\fBchar*\ filename\fR\fB);\fR
+.HP 48
+\fBzzip__new__\ ZZIP_MEM_DISK*\ \fBzzip_mem_disk_fdopen\fR\fR\fB(\fR\fBint\ fd\fR\fB);\fR
+.HP 24
+\fBlong\ \fBzzip_mem_disk_load\fR\fR\fB(\fR\fBZZIP_MEM_DISK*\ dir\fR\fB, \fR\fBZZIP_DISK*\ disk\fR\fB);\fR
+.HP 47
+\fBzzip__new__\ ZZIP_MEM_ENTRY*\ \fBzzip_mem_entry_new\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB, \fR\fBZZIP_DISK_ENTRY*\ entry\fR\fB);\fR
+.HP 38
+\fBzzip__new__\ ZZIP_DISK*\ \fBzzip_disk_mmap\fR\fR\fB(\fR\fBint\ fd\fR\fB);\fR
+.HP 37
+\fBzzip_byte_t*\ \fBzzip_disk_entry_to_data\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB, \fR\fBstruct\ zzip_disk_entry*\ entry\fR\fB);\fR
+.HP 43
+\fBstruct\ zzip_disk_entry*\ \fBzzip_disk_findfile\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB, \fR\fBchar*\ filename\fR\fB, \fR\fBstruct\ zzip_disk_entry*\ after\fR\fB, \fR\fBzzip_strcmp_fn_t\ compare\fR\fB);\fR
+.HP 44
+\fBzzip__new__\ ZZIP_DISK_FILE*\ \fBzzip_disk_fopen\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB, \fR\fBchar*\ filename\fR\fB);\fR
+.HP 17
+\fBint\ \fBzzip_init_io\fR\fR\fB(\fR\fBzzip_plugin_io_handlers_t\ io\fR\fB, \fR\fBint\ flags\fR\fB);\fR
+.HP 18
+\fBint\ \fBzzip_dir_stat\fR\fR\fB(\fR\fBZZIP_DIR\ *\ dir\fR\fB, \fR\fBzzip_char_t*\ name\fR\fB, \fR\fBZZIP_STAT\ *\ zs\fR\fB, \fR\fBint\ flags\fR\fB);\fR
+.HP 25
+\fBZZIP_DIR*\ \fBzzip_dir_creat\fR\fR\fB(\fR\fBzzip_char_t*\ name\fR\fB, \fR\fBint\ o_mode\fR\fB);\fR
+.HP 25
+\fBZZIP_DIR*\ \fBzzip_createdir\fR\fR\fB(\fR\fBzzip_char_t*\ name\fR\fB, \fR\fBint\ o_mode\fR\fB);\fR
+.HP 27
+\fBZZIP_FILE*\ \fBzzip_file_creat\fR\fR\fB(\fR\fBZZIP_DIR*\ dir\fR\fB, \fR\fBzzip_char_t*\ name\fR\fB, \fR\fBint\ o_mode\fR\fB);\fR
+.HP 24
+\fBzzip_ssize_t\ \fBzzip_write\fR\fR\fB(\fR\fBZZIP_FILE*\ file\fR\fB, \fR\fBconst\ void*\ ptr\fR\fB, \fR\fBzzip_size_t\ len\fR\fB);\fR
+.HP 22
+\fBint\ inline\ \fBzzip_mkdir\fR\fR\fB(\fR\fBzzip_char_t*\ name\fR\fB, \fR\fBint\ o_mode\fR\fB);\fR
+.HP 24
+\fBvoid\ inline\ \fBzzip_mkfifo\fR\fR\fB(\fR\fBzzip_char_t*\ name\fR\fB, \fR\fBint\ o_mode\fR\fB);\fR
+.HP 30
+\fBint\ \fB__zzip_fetch_disk_trailer\fR\fR\fB(\fR\fBint\ fd\fR\fB, \fR\fBzzip_off_t\ filesize\fR\fB, \fR\fBstruct\ _disk_trailer\ *\ _zzip_restrict\ trailer\fR\fB, \fR\fBzzip_plugin_io_t\ io\fR\fB);\fR
+.HP 32
+\fBint\ \fB__zzip_parse_root_directory\fR\fR\fB(\fR\fBint\ fd\fR\fB, \fR\fBstruct\ _disk_trailer\ *\ trailer\fR\fB, \fR\fBstruct\ zzip_dir_hdr\ **\ hdr_return\fR\fB, \fR\fBzzip_plugin_io_t\ io\fR\fB);\fR
+.HP 32
+\fBZZIP_DIR*\ \fBzzip_dir_alloc_ext_io\fR\fR\fB(\fR\fBzzip_strings_t*\ ext\fR\fB, \fR\fBconst\ zzip_plugin_io_t\ io\fR\fB);\fR
+.HP 18
+\fBint\ \fBzzip_dir_free\fR\fR\fB(\fR\fBZZIP_DIR\ *\ dir\fR\fB);\fR
+.HP 27
+\fBZZIP_DIR\ *\ \fBzzip_dir_fdopen\fR\fR\fB(\fR\fBint\ fd\fR\fB, \fR\fBzzip_error_t\ *\ errcode_p\fR\fB);\fR
+.HP 20
+\fBint\ \fB__zzip_try_open\fR\fR\fB(\fR\fBzzip_char_t*\ filename\fR\fB, \fR\fBint\ filemode\fR\fB, \fR\fBzzip_strings_t*\ ext\fR\fB, \fR\fBzzip_plugin_io_t\ io\fR\fB);\fR
+.HP 24
+\fBZZIP_DIR*\ \fBzzip_dir_open\fR\fR\fB(\fR\fBzzip_char_t*\ filename\fR\fB, \fR\fBzzip_error_t*\ e\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+zziplib library
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<too@iki.fi>
+/1155 1154977710 1001 0 100644 766 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_MEM_DISK_FDOPEN" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_mem_disk_fdopen \- create new diskdir handle.
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 48
+\fBzzip__new__\ ZZIP_MEM_DISK*\ \fBzzip_mem_disk_fdopen\fR\fR\fB(\fR\fBint\ fd\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+wraps underlying zzip_disk_open.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+/1179 1154977710 1001 0 100644 870 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_MEM_DISK_LOAD" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_mem_disk_load \- parse central dir.
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 24
+\fBlong\ \fBzzip_mem_disk_load\fR\fR\fB(\fR\fBZZIP_MEM_DISK*\ dir\fR\fB, \fR\fBZZIP_DISK*\ disk\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+creates an internal copy of each entry converted to the local platform. returns: number of entries, or \-1 on error (setting errno)
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+/1201 1154977710 1001 0 100644 768 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_MEM_DISK_OPEN" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_mem_disk_open \- create new diskdir handle.
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 46
+\fBzzip__new__\ ZZIP_MEM_DISK*\ \fBzzip_mem_disk_open\fR\fR\fB(\fR\fBchar*\ filename\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+wraps underlying zzip_disk_open.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+/1223 1154977710 1001 0 100644 1113 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_MEM_ENTRY_NEW" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_mem_entry_new \- convert a zip disk entry to internal format.
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 47
+\fBzzip__new__\ ZZIP_MEM_ENTRY*\ \fBzzip_mem_entry_new\fR\fR\fB(\fR\fBZZIP_DISK*\ disk\fR\fB, \fR\fBZZIP_DISK_ENTRY*\ entry\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+creates a new item parsing the information out of the various places in the zip archive. This is a good place to extend functionality if you have a project with extra requirements as you can push more bits right into the diskdir_entry for later usage in higher layers. returns: new item, or null on error (setting errno)
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+
+zzip_mkdir.3/ 1154977710 1001 0 100644 2200 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_MKDIR" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_mkdir, zzip_creat \- create a zipped file/directory
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 22
+\fBint\ inline\ \fBzzip_mkdir\fR\fR\fB(\fR\fBzzip_char_t*\ name\fR\fB, \fR\fBint\ o_mode\fR\fB);\fR
+.HP 29
+\fBZZIP_FILE*\ inline\ \fBzzip_creat\fR\fR\fB(\fR\fBzzip_char_t*\ name\fR\fB, \fR\fBint\ o_mode\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+.PP
+\fBThe zzip_mkdir function\fR
+creates a directory entry in the default zip\-archive. If you did not specify a "#define zzip_savefile somevar" then the default zip\-archive is null and all directories are created as real directories in the filesystem.
+\fBThe zzip_mkdir function\fR
+is really a preprocessor macro or preferably an inline function around
+\fBzzip_file_mkdir\fR, there is no such symbol generated into the library. The prototype is modelled after the posix
+\fBmkdir\fR(2) call.
+.sp
+.nf
+ #ifndef zzip_savefile
+ #define zzip_savefile 0
+ #endif
+ #define zzip_mkdir(name,mode) \\ \-
+.fi
+.sp
+zzip_file_mkdir(zzip_savefile,name,mode)
+.PP
+.PP
+.PP
+\fBThe zzip_creat function\fR
+creates a file in the default zip\-archive. If you did not specify a "#define zzip_savefile somevar" then the default zip\-archive is null and all files are created as real files.
+\fBThe zzip_creat function\fR
+is really a preprocessor macro or preferably an inline function around
+\fBzzip_file_creat\fR, there is no such symbol generated into the library. The prototype is modelled after the posix
+\fBcreat\fR(2) call.
+.sp
+.nf
+ #ifndef zzip_savefile
+ #define zzip_savefile 0
+ #endif
+ #define zzip_creat(name,mode) \\ \-
+.fi
+.sp
+zzip_file_creat(zzip_savefile,name,mode)
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.SH "SEE ALSO"
+.PP
+zzip_dir_creat, mkdir(2), creat(2), zzip_start
+zzip_mkfifo.3/ 1154977710 1001 0 100644 2613 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_MKFIFO" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_mkfifo, zzip_sync \- start writing to the magic zzip_savefile
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 24
+\fBvoid\ inline\ \fBzzip_mkfifo\fR\fR\fB(\fR\fBzzip_char_t*\ name\fR\fB, \fR\fBint\ o_mode\fR\fB);\fR
+.HP 22
+\fBvoid\ inline\ \fBzzip_sync\fR\fR\fB(\fR\fBvoid\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+.PP
+open a zip archive for writing via the magic zzip_savefile macro variable. The name and mode are given to
+\fBzzip_createdir\fR
+and the result is stored into
+\fBzzip_savefile\fR
+\- if the
+\fBzzip_savefile\fR
+did already have a zzip_dir handle then it is automatically finalized with
+\fBzzip_sync\fR
+and the handle closed and the zzip_savefile variable reused for the new zip archive just started with this call. \-
+\fBThe zzip_mkfifo function\fR
+is really a preprocessor macro or preferably an inline function around
+\fBzzip_dir_create\fR, there is no such symbol generated into the library.
+.sp
+.nf
+ #ifndef zzip_savefile
+ #define zzip_savefile 0
+ #endif
+ #define zzip_start(name,mode,ext) \\ \-
+.fi
+.sp
+{ if (zzip_savefile) zzip_closedir(zzip_savefile); \\ \- zzip_savefile = zzip_createdir(name,mode,ext); }
+\fBThe zzip_mkfifo function\fR
+returns null on error or a zzip_dir handle on success. It is perfectly okay to continue with a null in the zzip_savefile variable since it makes subsequent calls to
+\fBzzip_creat\fR
+and
+\fBzzip_mkdir\fR
+to run as
+\fBcreat\fR(2) /
+\fBmkdir\fR(2) on the real filesystem.
+.PP
+.PP
+finalize a zip archive thereby writing the central directory to the end of the file. If it was a real directory then we do just nothing \- even that the prototype of the call itself is modelled to be similar to the posix
+\fBsync\fR(2) call.
+\fBThe zzip_sync function\fR
+is really a preprocessor macro or preferably an inline function around
+\fBzzip_closedir\fR, there is no such symbol generated into the library.
+.sp
+.nf
+ #ifndef zzip_savefile
+ #define zzip_savefile 0
+ #endif
+ #define zzip_sync(name,mode) \\ \-
+.fi
+.sp
+{ zzip_closedir(zzip_savefile); zzip_savefile = 0; }
+.PP
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.SH "SEE ALSO"
+.PP
+zzip_creat, zzip_write, zzip_closedir, sync(2)
+
+zzip_open.3/ 1154977710 1001 0 100644 4164 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_OPEN" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_open, zzip_open_ext_io, zzip_open_shared_io \- (zzip/file.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 21
+\fBZZIP_FILE*\ \fBzzip_open\fR\fR\fB(\fR\fBzzip_char_t*\ filename\fR\fB, \fR\fBint\ o_flags\fR\fB);\fR
+.HP 28
+\fBZZIP_FILE*\ \fBzzip_open_ext_io\fR\fR\fB(\fR\fBzzip_char_t*\ filename\fR\fB, \fR\fBint\ o_flags\fR\fB, \fR\fBint\ o_modes\fR\fB, \fR\fBzzip_strings_t*\ ext\fR\fB, \fR\fBzzip_plugin_io_t\ io\fR\fB);\fR
+.HP 31
+\fBZZIP_FILE*\ \fBzzip_open_shared_io\fR\fR\fB(\fR\fBZZIP_FILE*\ stream\fR\fB, \fR\fBzzip_char_t*\ filename\fR\fB, \fR\fBint\ o_flags\fR\fB, \fR\fBint\ o_modes\fR\fB, \fR\fBzzip_strings_t*\ ext\fR\fB, \fR\fBzzip_plugin_io_t\ io\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe zzip_open function\fR
+will
+\fBopen\fR(2) a real/zipped file
+.PP
+It has some magic functionality builtin \- it will first try to open the given
+\fIfilename\fR
+as a normal file. If it does not exist, the given path to the filename (if any) is split into its directory\-part and the file\-part. A ".zip" extension is then added to the directory\-part to create the name of a zip\-archive. That zip\-archive (if it exists) is being searched for the file\-part, and if found a zzip\-handle is returned.
+.PP
+Note that if the file is found in the normal fs\-directory the returned structure is mostly empty and the
+\fBzzip_read\fR
+call will use the libc
+\fBread\fR
+to obtain data. Otherwise a
+\fBzzip_file_open\fR
+is performed and any error mapped to
+\fBerrno\fR(3).
+.PP
+There was a possibility to transfer zziplib\-specific openmodes through o_flags but you should please not use them anymore and look into
+\fBzzip_open_ext_io\fR
+to submit them down.
+\fBThe zzip_open function\fR
+is shallow in that it just extracts the zzipflags and calls
+.sp
+.nf
+\fB
+ zzip_open_ext_io(filename, o_flags, zzipflags|0664, 0, 0) \fR
+.fi
+.PP
+you must stop using this extra functionality (not well known anyway) since zzip_open might be later usable to open files for writing in which case the _EXTRAFLAGS will get in conflict.
+.PP
+compare with
+\fBopen\fR(2) and
+\fBzzip_fopen\fR
+.PP
+.PP
+\fBThe zzip_open_ext_io function\fR
+uses explicit ext and io instead of the internal defaults, setting them to zero is equivalent to
+\fBzzip_open\fR
+.PP
+note that the two flag types have been split into an o_flags (for fcntl\-like openflags) and o_modes where the latter shall carry the zzip_flags and possibly accessmodes for unix filesystems. Since this version of zziplib can not write zipfiles, it is not yet used for anything else than zzip\-specific modeflags.
+.PP
+.PP
+\fBThe zzip_open_shared_io function\fR
+takes an extra stream argument \- if a handle has been then ext/io can be left null and the new stream handle will pick up the ext/io. This should be used only in specific environment however since
+\fBzzip_file_real\fR
+does not store any ext\-sequence.
+.PP
+The benefit for
+\fBthe zzip_open_shared_io function\fR
+comes in when the old file handle was openened from a file within a zip archive. When the new file is in the same zip archive then the internal zzip_dir structures will be shared. It is even quicker, as no check needs to be done anymore trying to guess the zip archive place in the filesystem, here we just check whether the zip archive's filepath is a prefix part of the filename to be opened.
+.PP
+Note that
+\fBthe zzip_open_shared_io function\fR
+is also used by
+\fBzzip_freopen\fR
+that will unshare the old handle, thereby possibly closing the handle.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+.TP
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+.TP
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+zzip_opendir.3/ 1154977710 1001 0 100644 1490 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_OPENDIR" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_opendir, zzip_opendir_ext_io \- (zzip/dir.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 23
+\fBZZIP_DIR*\ \fBzzip_opendir\fR\fR\fB(\fR\fBzzip_char_t*\ filename\fR\fB);\fR
+.HP 30
+\fBZZIP_DIR*\ \fBzzip_opendir_ext_io\fR\fR\fB(\fR\fBzzip_char_t*\ filename\fR\fB, \fR\fBint\ o_modes\fR\fB, \fR\fBzzip_strings_t*\ ext\fR\fB, \fR\fBzzip_plugin_io_t\ io\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe zzip_opendir function\fR
+is the equivalent of
+\fBopendir\fR(3) for a realdir or zipfile.
+.PP
+\fBThe zzip_opendir function\fR
+has some magic \- if the given argument\-path is a directory, it will wrap a real
+\fBopendir\fR(3) into the ZZIP_DIR structure. Otherwise it will divert to
+\fBzzip_dir_open\fR
+which can also attach a ".zip" extension if needed to find the archive.
+.PP
+the error\-code is mapped to
+\fBerrno\fR(3).
+.PP
+\fBThe zzip_opendir_ext_io function\fR
+uses explicit ext and io instead of the internal defaults, setting them to zero is equivalent to
+\fBzzip_opendir\fR
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+/1245 1154977710 1001 0 100644 24 `
+.so man3/zzip_opendir.3
+/1268 1154977710 1001 0 100644 21 `
+.so man3/zzip_open.3
+
+/1288 1154977710 1001 0 100644 21 `
+.so man3/zzip_open.3
+
+/1311 1154977710 1001 0 100644 1125 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "__ZZIP_PARSE_ROOT_DI" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+__zzip_parse_root_directory \- (zzip/zip.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 32
+\fBint\ \fB__zzip_parse_root_directory\fR\fR\fB(\fR\fBint\ fd\fR\fB, \fR\fBstruct\ _disk_trailer\ *\ trailer\fR\fB, \fR\fBstruct\ zzip_dir_hdr\ **\ hdr_return\fR\fB, \fR\fBzzip_plugin_io_t\ io\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe __zzip_parse_root_directory function\fR
+is used by
+\fBzzip_file_open\fR, it is usually called after
+\fB__zzip_find_disk_trailer\fR. It will parse the zip's central directory information and create a zziplib private directory table in memory.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<too@iki.fi>
+
+zzip_read.3/ 1154977710 1001 0 100644 1578 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_READ" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_read, zzip_fread \- (zzip/file.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 23
+\fBzzip_ssize_t\ \fBzzip_read\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB, \fR\fBchar\ *\ buf\fR\fB, \fR\fBzzip_size_t\ len\fR\fB);\fR
+.HP 23
+\fBzzip_size_t\ \fBzzip_fread\fR\fR\fB(\fR\fBvoid\ *ptr\fR\fB, \fR\fBzzip_size_t\ size\fR\fB, \fR\fBzzip_size_t\ nmemb\fR\fB, \fR\fBZZIP_FILE\ *file\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe zzip_read function\fR
+will read(2) data from a real/zipped file.
+.PP
+the replacement for
+\fBread\fR(2) will fill the given buffer with bytes from the opened file. It will return the number of bytes read, so if the EOF is encountered you will be prompted with the number of bytes actually read.
+.PP
+If the file\-handle is wrapping a stat'able file then it will actually just perform a normal
+\fBread\fR(2)\-call, otherwise
+\fBzzip_file_read\fR
+is called to decompress the data stream and any error is mapped to
+\fBerrno\fR(3).
+.PP
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+.TP
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+zzip_readdir.3/ 1154977710 1001 0 100644 1125 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_READDIR" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_readdir \- (zzip/dir.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 26
+\fBZZIP_DIRENT*\ \fBzzip_readdir\fR\fR\fB(\fR\fBZZIP_DIR\ *\ dir\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe zzip_readdir function\fR
+is the equivalent of a
+\fBreaddir\fR(2) for a realdir or a zipfile referenced by the ZZIP_DIR returned from
+\fBzzip_opendir\fR.
+.PP
+The ZZIP_DIR handle (as returned by
+\fBzzip_opendir\fR) contains a few more entries than being copied into the ZZIP_DIRENT. The only valid fields in a ZZIP_DIRENT are d_name (the file name), d_compr (compression), d_csize (compressed size), st_size (uncompressed size).
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+
+zzip_realdir.3/ 1154977710 1001 0 100644 26 `
+.so man3/zzip_file_real.3
+zzip_realfd.3/ 1154977710 1001 0 100644 26 `
+.so man3/zzip_file_real.3
+zzip_rewind.3/ 1154977710 1001 0 100644 889 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_REWIND" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_rewind \- (zzip/file.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 16
+\fBint\ \fBzzip_rewind\fR\fR\fB(\fR\fBZZIP_FILE\ *fp\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe zzip_rewind function\fR
+will rewind a real/zipped file.
+.PP
+It seeks to the beginning of this file's data in the zip, or the beginning of the file for a stat'fd.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+
+/1342 1154977710 1001 0 100644 1398 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_REWINDDIR" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_rewinddir, zzip_telldir, zzip_seekdir \- (zzip/dir.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 20
+\fBvoid\ \fBzzip_rewinddir\fR\fR\fB(\fR\fBZZIP_DIR\ *\ dir\fR\fB);\fR
+.HP 24
+\fBzzip_off_t\ \fBzzip_telldir\fR\fR\fB(\fR\fBZZIP_DIR*\ dir\fR\fB);\fR
+.HP 18
+\fBvoid\ \fBzzip_seekdir\fR\fR\fB(\fR\fBZZIP_DIR*\ dir\fR\fB, \fR\fBzzip_off_t\ offset\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe zzip_rewinddir function\fR
+is the equivalent of a
+\fBrewinddir\fR(2) for a realdir or the zipfile in place of a directory. The ZZIP_DIR handle returned from
+\fBzzip_opendir\fR
+has a flag saying realdir or zipfile. As for a zipfile, the filenames will include the filesubpath, so take care.
+.PP
+\fBThe zzip_telldir function\fR
+is the equivalent of
+\fBtelldir\fR(2) for a realdir or zipfile.
+.PP
+\fBThe zzip_seekdir function\fR
+is the equivalent of
+\fBseekdir\fR(2) for a realdir or zipfile.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+zzip_seek.3/ 1154977710 1001 0 100644 1450 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_SEEK" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_seek \- (zzip/file.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 21
+\fBzzip_off_t\ \fBzzip_seek\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB, \fR\fBzzip_off_t\ offset\fR\fB, \fR\fBint\ whence\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe zzip_seek function\fR
+will perform a
+\fBlseek\fR(2) operation on a real/zipped file
+.PP
+It will try to seek to the offset specified by offset, relative to whence, which is one of SEEK_SET, SEEK_CUR or SEEK_END.
+.PP
+If the file\-handle is wrapping a stat'able file then it will actually just perform a normal
+\fBlseek\fR(2)\-call. Otherwise the relative offset is calculated, negative offsets are transformed into positive ones by rewinding the file, and then data is read until the offset is reached. This can make the function terribly slow, but this is how gzio implements it, so I'm not sure there is a better way without using the internals of the algorithm.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+zzip_seekdir.3/ 1154977710 1001 0 100644 26 `
+.so man3/zzip_rewinddir.3
+__zzip_set16.3/ 1154977710 1001 0 100644 24 `
+.so man3/__zzip_get32.3
+__zzip_set32.3/ 1154977710 1001 0 100644 24 `
+.so man3/__zzip_get32.3
+__zzip_set64.3/ 1154977710 1001 0 100644 24 `
+.so man3/__zzip_get32.3
+zzip_seterror.3/1154977710 1001 0 100644 22 `
+.so man3/zzip_error.3
+zzip_strerror.3/1154977710 1001 0 100644 1417 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_STRERROR" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_strerror, zzip_strerror_of \- (zzip/err.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 27
+\fBzzip_char_t*\ \fBzzip_strerror\fR\fR\fB(\fR\fBint\ errcode\fR\fB);\fR
+.HP 30
+\fBzzip_char_t*\ \fBzzip_strerror_of\fR\fR\fB(\fR\fBZZIP_DIR*\ dir\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+returns the static string for the given error code. The error code can be either a normal system error (a positive error code will flag this), it can be
+\fBlibz\fR
+error code (a small negative error code will flag this) or it can be an error code from
+\fBlibzzip\fR, which is an negative value lower than
+\fBZZIP_ERROR\fR
+.PP
+\fBThe zzip_strerror_of function\fR
+fetches the errorcode from the
+\fBDIR\fR\-handle and runs it through
+\fBzzip_strerror\fR
+to obtain the static string describing the error.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+.TP
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+
+/1360 1154977710 1001 0 100644 25 `
+.so man3/zzip_strerror.3
+
+zzip_sync.3/ 1154977710 1001 0 100644 23 `
+.so man3/zzip_mkfifo.3
+
+zzip_tell.3/ 1154977710 1001 0 100644 1154 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_TELL" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_tell \- (zzip/file.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 21
+\fBzzip_off_t\ \fBzzip_tell\fR\fR\fB(\fR\fBZZIP_FILE\ *\ fp\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+\fBThe zzip_tell function\fR
+will
+\fBtell\fR(2) the current position in a real/zipped file
+.PP
+It will return the current offset within the real/zipped file, measured in uncompressed bytes for the zipped\-file case.
+.PP
+If the file\-handle is wrapping a stat'able file then it will actually just perform a normal
+\fBtell\fR(2)\-call, otherwise the offset is calculated from the amount of data left and the total uncompressed size;
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<Tomi.Ollila@iki.fi>
+zzip_telldir.3/ 1154977710 1001 0 100644 26 `
+.so man3/zzip_rewinddir.3
+/1380 1154977710 1001 0 100644 991 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "__ZZIP_TRY_OPEN" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+__zzip_try_open \- (zzip/zip.c)
+.SH "SYNOPSIS"
+.PP
+\fB
+
+
+#include <zzip/lib.h>
+\fR
+.HP 20
+\fBint\ \fB__zzip_try_open\fR\fR\fB(\fR\fBzzip_char_t*\ filename\fR\fB, \fR\fBint\ filemode\fR\fB, \fR\fBzzip_strings_t*\ ext\fR\fB, \fR\fBzzip_plugin_io_t\ io\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+will attach a .zip extension and tries to open it the with
+\fBopen\fR(2). This is a helper function for
+\fBzzip_dir_open\fR,
+\fBzzip_opendir\fR
+and
+\fBzzip_open\fR.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.TP
+\(bu
+Tomi Ollila
+<too@iki.fi>
+
+zzip_write.3/ 1154977710 1001 0 100644 2460 `
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "ZZIP_WRITE" "3" "0.13.47" "zziplib" "Manual Pages"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+zzip_write, zzip_file_write, zzip_fwrite \- write to zzip storage
+.SH "SYNOPSIS"
+.PP
+\fB
+ #include <zziplib.h>
+\fR
+.HP 24
+\fBzzip_ssize_t\ \fBzzip_write\fR\fR\fB(\fR\fBZZIP_FILE*\ file\fR\fB, \fR\fBconst\ void*\ ptr\fR\fB, \fR\fBzzip_size_t\ len\fR\fB);\fR
+.HP 29
+\fBzzip_ssize_t\ \fBzzip_file_write\fR\fR\fB(\fR\fBZZIP_FILE*\ file\fR\fB, \fR\fBconst\ void*\ ptr\fR\fB, \fR\fBzzip_size_t\ len\fR\fB);\fR
+.HP 24
+\fBzzip_size_t\ \fBzzip_fwrite\fR\fR\fB(\fR\fBconst\ void*\ ptr\fR\fB, \fR\fBzzip_size_t\ len\fR\fB, \fR\fBzzip_size_t\ multiply\fR\fB, \fR\fBZZIP_FILE*\ file\fR\fB);\fR
+.SH "DESCRIPTION"
+.PP
+.PP
+\fBThe zzip_write function\fR
+will write data to a file descriptor. If the file descriptor represents a real file then it will be forwarded to call posix
+\fBwrite\fR(2) directly. If it is a descriptor for a file within a zip directory then the data will be "deflated" using
+\fBzlib\fR(3) and appended to the zip archive file.
+.PP
+.PP
+\fBThe zzip_file_write function\fR
+will write data to a file descriptor inside a zip archive. The data will be "deflated" using
+\fBzlib\fR(3) compression and appended to the end of the zip archive file. Only one file descriptor may be open per zzip_dir archive handle (fifo\-like).
+.PP
+\fBThe zzip_file_write function\fR
+is not yet implemented, check for #def ZZIP_NO_CREAT It returns immediately \-1 and sets errno=EROFS for indication.
+.PP
+\fBThe zzip_fwrite function\fR
+is the stdc variant for writing and the arguments are forwarded to
+\fBzzip_write\fR
+\- the return value is floored to null as for STDC spec but there is no zzip_ferror call so far for the zziplib (later? is it actually needed?).
+.PP
+\fBThe zzip_fwrite function\fR
+is not yet implemented, check for #def ZZIP_NO_CREAT Write\-support extends
+\fBzzip_close\fR
+with semantics to write out a file\-trailer to the zip\-archive leaving a name/offset marker in the (still\-open) ZZIP_DIR handle.
+.SH "AUTHOR"
+.TP 3
+\(bu
+Guido Draheim
+<guidod@gmx.de>
+.SH "SEE ALSO"
+.PP
+write(2), zlib(3), zzip_file_creat
diff --git a/Build/source/libs/zziplib/docs/memdisk.htm b/Build/source/libs/zziplib/docs/memdisk.htm
new file mode 100644
index 00000000000..d5d25c9952d
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/memdisk.htm
@@ -0,0 +1,116 @@
+<section> <date> 2005 </date>
+<H2> zzip/memdisk </H2> zip cache for mmapped views
+
+<BLOCKQUOTE>
+ These routines are fully independent from the traditional zzip
+ implementation. They build on top of
+ <a href="mmapped.html">zzip/mmapped</a> that uses a readonly
+ mmapped sharedmem block. These functions add additional hints
+ how to parse extension blocks and how to cache the zip central
+ directory entries which does furthermore allow to convert them
+ to any host-local format as required.
+</BLOCKQUOTE>
+
+<section>
+<H3> zzip disk handle </H3>
+
+<P>
+ Other than with the <a href="fseeko.html">fseeko</a> alternative
+ interface there is no need to have an actual disk handle to the
+ zip archive. Instead you can use a bytewise copy of a file or
+ even use a mmapped view of a file. This is generally the fastest
+ way to get to the data contained in a zipped file. All it requires
+ is enough of virtual memory space but a desktop computer with a
+ a modern operating system will easily take care of that.
+</P>
+
+<P>
+ The zzipmmapped library provides a number of calls to create a
+ disk handle representing a zip archive in virtual memory. Per
+ default we use the sys/mmap.h (or MappedView) functionality
+ of the operating system. See for more details in the
+ <a href="mmapped.html">zzip/mmapped</a> descriptions.
+</P>
+<P>
+ The zzip/memdisk extensions of zzip/mmapped are made to have a
+ very similar call API - therefore you will find again open and
+ close functions for filenames or filehandles. However the
+ direct mmap interface is not re-exported under the zzip_mem_disk
+ prefix (of the underlying zzip_disk prefix). The "_mem_" part
+ hints that the central directory of the underlying zzip_disk
+ is preparsed to a separate memory block.
+<PRE>
+ ZZIP_MEM_DISK* zzip_mem_disk_open(char* filename);
+ ZZIP_MEM_DISK* zzip_mem_disk_fdopen(int fd);
+ void zzip_mem_disk_close(ZZIP_MEM_DISK* disk);
+
+ int zzip_mem_disk_load (ZZIP_MEM_DISK* dir, ZZIP_DISK* disk);
+ void zzip_mem_disk_unload (ZZIP_MEM_DISK* dir);
+</PRE>
+ The last two functions export some parts of the underlying
+ interface. It is possible to bind an existing ZZIP_MEM_DISK
+ handle with an arbitrary ZZIP_DISK handle. Upon calling "load"
+ the central directory will be loaded from the underlying zip
+ disk content and parsed to an internal mem block. The corresponding
+ "unload" function will trash that central directory cache but it
+ leaves the handles intact.
+</P>
+
+</section><section>
+<H3> reading the central directory </H3>
+
+<P>
+ All other zzip_mem_disk functions are simply re-exporting the
+ underlying zzip_disk functions. Note that the first field in
+ the ZZIP_MEM_DISK is a "ZZIP_DISK* disk" - the header file
+ zzip/memdisk.h will simply export inline functions where there
+ is no special zzip_mem_disk function. Therefore, whenever a
+ function call on a ZZIP_DISK handle is appropriate one can
+ also use its cousin for a ZZIP_MEM_DISK handle without any
+ penalties but future compatibility for extra functionality in
+ zzip/memdisk layer of the zzip/mmapped library.
+</P>
+
+<P><small>Note: by default the re-exports are done with the help
+ of the C precompiler as precompiler macros. Using USE_INLINE
+ will force to make them real inlines. In the future that may
+ change in favor of a better autodetection for inline capabilities
+ of the compiler and/or using a standard cpp-define that enables
+ the C/C++ inline functions. The inline functions do have the
+ added value of having strongtyped arguments provoking more
+ readable warning messages in user application code.</small></P>
+
+<PRE>
+ inline ZZIP_DISK_ENTRY*
+zzip_mem_disk_findfirst(ZZIP_MEM_DISK* dir);
+ inline ZZIP_DISK_ENTRY*
+zzip_mem_disk_findnext(ZZIP_MEM_DISK* dir, ZZIP_DISK_ENTRY* entry);
+ inline char* _zzip_restrict
+zzip_mem_disk_entry_strdup_name(ZZIP_MEM_DISK* dir,
+ ZZIP_DISK_ENTRY* entry);
+ inline struct zzip_file_header*
+zzip_mem_disk_entry_to_file_header(ZZIP_MEM_DISK* dir,
+ ZZIP_DISK_ENTRY* entry);
+ inline char*
+zzip_mem_disk_entry_to_data(ZZIP_MEM_DISK* dir, ZZIP_DISK_ENTRY* entry);
+ inline ZZIP_DISK_ENTRY*
+zzip_mem_disk_findfile(ZZIP_MEM_DISK* dir,
+ char* filename, ZZIP_DISK_ENTRY* after,
+ zzip_strcmp_fn_t compare);
+ inline ZZIP_DISK_ENTRY*
+zzip_mem_disk_findmatch(ZZIP_MEM_DISK* dir,
+ char* filespec, ZZIP_DISK_ENTRY* after,
+ zzip_fnmatch_fn_t compare, int flags);
+ inline ZZIP_DISK_FILE* _zzip_restrict
+zzip_mem_disk_entry_fopen (ZZIP_MEM_DISK* dir, ZZIP_DISK_ENTRY* entry);
+ inline ZZIP_DISK_FILE* _zzip_restrict
+zzip_mem_disk_fopen (ZZIP_MEM_DISK* dir, char* filename);
+ inline _zzip_size_t
+zzip_mem_disk_fread (void* ptr, _zzip_size_t size, _zzip_size_t nmemb,
+ ZZIP_DISK_FILE* file);
+ inline int
+zzip_mem_disk_fclose (ZZIP_DISK_FILE* file);
+ inline int
+zzip_mem_disk_feof (ZZIP_DISK_FILE* file);
+</PRE>
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/mksite.pl b/Build/source/libs/zziplib/docs/mksite.pl
new file mode 100644
index 00000000000..650a8adec29
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/mksite.pl
@@ -0,0 +1,2114 @@
+#! /usr/bin/perl
+# this is the perl variant of the mksite script. It based directly on a
+# copy of mksite.sh which is derived from snippets that I was using to
+# finish doc pages for website publishing. Using only sh/sed along with
+# files has a great disadvantage: it is very slow process atleast. The
+# perl language in contrast has highly optimized string, replace, search
+# functions as well as data structures to store intermediate values. As
+# an advantage large parts of the syntax are similar to the sh/sed variant.
+#
+# http://zziplib.sf.net/mksite/
+# THE MKSITE.SH (ZLIB/LIBPNG) LICENSE
+# Copyright (c) 2004 Guido Draheim <guidod@gmx.de>
+# This software is provided 'as-is', without any express or implied warranty
+# In no event will the authors be held liable for any damages arising
+# from the use of this software.
+# Permission is granted to anyone to use this software for any purpose,
+# including commercial applications, and to alter it and redistribute it
+# freely, subject to the following restrictions:
+# 1. The origin of this software must not be misrepresented; you must not
+# claim that you wrote the original software. If you use this software
+# in a product, an acknowledgment in the product documentation would be
+# appreciated but is not required.
+# 2. Altered source versions must be plainly marked as such, and must not
+# be misrepresented as being the original software.
+# 3. This notice may not be removed or altered from any source distribution.
+# $Id: mksite.pl,v 1.1 2005/12/13 00:27:06 guidod Exp $
+
+use strict; use warnings; no warnings "uninitialized";
+use File::Basename qw(basename);
+use POSIX qw(strftime);
+
+# initialize some defaults
+my $SITEFILE="";
+$SITEFILE="site.htm" if not $SITEFILE and -f "site.htm";
+$SITEFILE="site.html" if not $SITEFILE and -f "site.html";
+$SITEFILE="site.htm" if not $SITEFILE;
+# my $MK="-mksite"; # note the "-" at the start
+my $SED="sed";
+
+my $INFO="~~"; # extension for meta data files
+my $HEAD="~head~"; # extension for head sed script
+my $BODY="~body~"; # extension for body sed script
+my $FOOT="~foot~"; # append to body text (non sed)
+
+my $SED_LONGSCRIPT="$SED -f";
+
+my $az="a-z"; # for perl
+my $AZ="A-Z"; # we may assume there are
+my $NN="0-9"; # char-ranges available
+my $AA="_$NN$AZ$az"; # that makes the resulting
+my $AX="$AA.+-"; # script more readable
+
+my $n = "\n";
+
+# LANG="C" ; LANGUAGE="C" ; LC_COLLATE="C" # these are needed for proper
+# export LANG LANGUAGE LC_COLLATE # lowercasing as some collate
+ # treat A-Z to include a-z
+
+# ==========================================================================
+# reading options from the command line GETOPT
+my %o = (); # to store option variables
+$o{variables}="files";
+$o{fileseparator}="?";
+$o{files}="";
+$o{main_file}="";
+$o{formatter}="$0";
+my $opt="";
+for my $arg (@ARGV) { # this variant should allow to embed spaces in $arg
+ if ($opt) {
+ $o{$opt}=$arg;
+ $opt="";
+ } else {
+ $_=$arg;
+ if (/^-.*=.*$/) {
+ $opt=$arg; $opt =~ s/-*([$AA][$AA-]*).*/$1/; $opt =~ y/-/_/;
+ if (not $opt) {
+ print STDERR "ERROR: invalid option $arg$n";
+ } else {
+ $arg =~ s/^[^=]*=//;
+ $o{$opt} = $arg;
+ $o{variables} .= " ".$opt;
+ }
+ $opt="";;
+ } elsif (/^-.*-.*$/) {
+ $opt=$arg; $opt =~ s/-*([$AA][$AA-]*).*/$1/; $opt =~ y/-/_/;
+ if (not $opt) {
+ print STDERR "ERROR: invalid option $arg$n";
+ $opt="";
+ } else {
+ # keep the option for next round
+ } ;;
+ } elsif (/^-.*/) {
+ $opt=$arg; $opt =~ s/^-*([$AA][$AA-]*).*/$1/; $opt =~ y/-/_/;
+ if (not $opt) {
+ print STDERR "ERROR: invalid option $arg$n";
+ } else {
+ $arg =~ s/^[^=]*=//;
+ $o{$opt} = ' ';
+ }
+ $opt="" ;;
+ } else {
+ if (not $o{main_file}) { $o{main_file} = $arg; } else {
+ $o{files} .= $o{fileseparator} if $o{files};
+ $o{files} .= $arg; };
+ $opt="" ;;
+ };
+ }
+} ; if ($opt) {
+ $o{$opt}=" ";
+ $opt="";
+ }
+
+### env | grep ^opt
+
+$SITEFILE=$o{main_file} if $o{main_file} and -f $o{main_file};
+$SITEFILE=$o{site_file} if $o{site_file} and -f $o{site_file};
+
+if ($o{help}) {
+ $_=$SITEFILE;
+ print "$0 [sitefile]$n";
+ print " default sitefile = $_$n";
+ print "options:$n"
+ . " --filelist : show list of target files as ectracted from $_$n"
+ . " --src xx : if source files are not where mksite is executed$n";
+ exit;
+ print " internal:$n"
+ ."--fileseparator=x : for building the internal filelist (def. '?')$n"
+ ."--files xx : for list of additional files to be processed$n"
+ ."--main-file xx : for the main sitefile to take file list from$n";
+}
+
+if (not $SITEFILE) {
+ print STDERR "error: no SITEFILE found (default would be 'site.htm')$n";
+ exit 1;
+} else {
+ print STDERR "NOTE: sitefile: ",`ls -s $SITEFILE`,"$n";
+}
+
+# we use internal hashes to store mappings - kind of relational tables
+my @MK_TAGS= (); # "./$MK.tags.tmp"
+my @MK_VARS= (); # "./$MK.vars.tmp"
+my @MK_META= (); # "./$MK.meta.tmp"
+my @MK_METT= (); # "./$MK.mett.tmp"
+my @MK_TEST= (); # "./$MK.test.tmp"
+my @MK_FAST= (); # "./$MK.fast.tmp"
+my @MK_GETS= (); # "./$MK.gets.tmp"
+my @MK_PUTS= (); # "./$MK.puts.tmp"
+my @MK_OLDS= (); # "./$MK.olds.tmp"
+my @MK_SITE= (); # "./$MK.site.tmp"
+my @MK_SECT1= (); # "./$MK.sect1.tmp"
+my @MK_SECT2= (); # "./$MK.sect2.tmp"
+my @MK_SECT3= (); # "./$MK.sect3.tmp"
+my @MK_INFO= (); # "./$MK~~"
+my %INFO= (); # used for $F.$PARTs
+my %FAST= ();
+
+# ========================================================================
+# ========================================================================
+# ========================================================================
+# MAGIC VARS
+# IN $SITEFILE
+my $printerfriendly="";
+my $sectionlayout="list";
+my $sitemaplayout="list";
+my $simplevars="warn"; # <!--varname-->default
+my $attribvars=" "; # <x ref="${varname:=default}">
+my $updatevars=" "; # <!--$varname:=-->default
+my $expandvars=" "; # <!--$varname-->
+my $commentvars=" "; # $updatevars && $expandsvars && $simplevars
+my $sectiontab=" "; # highlight ^<td class=...>...href="$section"
+my $currenttab=" "; # highlight ^<br>..<a href="$topic">
+my $headsection="no";
+my $tailsection="no";
+my $sectioninfo="no"; # using <h2> title <h2> = info text
+my $emailfooter="no";
+
+for (source($SITEFILE)) {
+ if (/<!--multi-->/) {
+ warn("WARNING: do not use <!--multi-->,"
+ ." change to <!--mksite:multi--> $SITEFILE"
+ ."warning: or"
+ ." <!--mksite:multisectionlayout-->"
+ ." <!--mksite:multisitemaplayout-->");
+ $sectionlayout="multi";
+ $sitemaplayout="multi";
+ }
+ if (/<!--mksite:multi-->/) {
+ $sectionlayout="multi";
+ $sitemaplayout="multi";
+ }
+ if (/<!--mksite:multilayout-->/) {
+ $sectionlayout="multi";
+ $sitemaplayout="multi";
+ }
+}
+
+sub mksite_magic_option
+{
+ # $1 is word/option to check for
+ my ($U,$INP,$Z) = @_;
+ $INP=$SITEFILE if not $INP;
+ for (source($INP)) {
+ s/(<!--mksite:)($U)-->/$1$2: -->/g;
+ s/(<!--mksite:)(\w\w*)($U)-->/$1$3:$2-->/g;
+ /<!--mksite:$U:/ or next;
+ s/.*<!--mksite:$U:([^<>]*)-->.*/$1/;
+ s/.*<!--mksite:$U:([^-]*)-->.*/$1/;
+ /<!--mksite:$U:/ and next;
+ chomp;
+ return $_;
+ }
+ return "";
+}
+
+{
+ my $x;
+ $x=mksite_magic_option("sectionlayout"); if
+ ($x =~ /^(list|multi)$/) { $sectionlayout="$x" ; }
+ $x=mksite_magic_option("sitemaplayout"); if
+ ($x =~ /^(list|multi)$/) { $sitemaplayout="$x" ; }
+ $x=mksite_magic_option("simplevars"); if
+ ($x =~ /^( |no|warn)$/) { $simplevars="$x" ; }
+ $x=mksite_magic_option("attribvars"); if
+ ($x =~ /^( |no|warn)$/) { $attribvars="$x" ; }
+ $x=mksite_magic_option("updatevars"); if
+ ($x =~ /^( |no|warn)$/) { $updatevars="$x" ; }
+ $x=mksite_magic_option("expandvars"); if
+ ($x =~ /^( |no|warn)$/) { $expandvars="$x" ; }
+ $x=mksite_magic_option("commentvars"); if
+ ($x =~ /^( |no|warn)$/) { $commentvars="$x" ; }
+ $x=mksite_magic_option("printerfriendly"); if
+ ($x =~ /^( |[.].*|[-]-.*)$/) { $printerfriendly="$x" ; }
+ $x=mksite_magic_option("sectiontab"); if
+ ($x =~ /^( |no|warn)$/) { $sectiontab="$x" ; }
+ $x=mksite_magic_option("currenttab"); if
+ ($x =~ /^( |no|warn)$/) { $currenttab="$x" ; }
+ $x=mksite_magic_option("sectioninfo"); if
+ ($x =~ /^( |no|[=:-])$/) { $sectioninfo="$x" ; }
+ $x=mksite_magic_option("commentvars"); if
+ ($x =~ /^( |no|warn)$/) { $commentvars="$x" ; }
+ $x=mksite_magic_option("emailfooter"); if
+ ($x) { $emailfooter="$x"; }
+}
+
+$printerfriendly=$o{print} if $o{print};
+$updatevars="no" if $commentvars eq "no"; # duplicated into
+$expandvars="no" if $commentvars eq "no"; # info2vars_sed
+$simplevars="no" if $commentvars eq "no"; # function above
+
+print "NOTE: '$sectionlayout\'sectionlayout '$sitemaplayout\'sitemaplayout$n"
+ if -d "DEBUG";
+print "NOTE: '$simplevars\'simplevars '$printerfriendly\'printerfriendly$n"
+ if -d "DEBUG";
+print "NOTE: '$attribvars\'attribvars '$updatevars\'updatevars$n"
+ if -d "DEBUG";
+print "NOTE: '$expandvars\'expandvars '$commentvars\'commentvars $n"
+ if -d "DEBUG";
+print "NOTE: '$currenttab\'currenttab '$sectiontab\'sectiontab$n"
+ if -d "DEBUG";
+print "NOTE: '$headsection\'headsection '$tailsection\'tailsection$n"
+ if -d "DEBUG";
+
+# ==========================================================================
+# init a few global variables
+# 0. INIT
+
+# $MK.tags.tmp - originally, we would use a lambda execution on each
+# uppercased html tag to replace <P> with <p class="P">. Here we just
+# walk over all the known html tags and make an sed script that does
+# the very same conversion. There would be a chance to convert a single
+# tag via "h;y;x" or something we do want to convert all the tags on
+# a single line of course.
+@MK_TAGS=();
+for my $P (qw/P H1 H2 H3 H4 H5 H6 DL DD DT UL OL LI PRE CODE TABLE TR TD TH
+ B U I S Q EM STRONG STRIKE CITE BIG SMALL SUP SUB TT THEAD TBODY
+ CENTER HR BR NOBR WBR SPAN DIV IMG ADRESS BLOCKQUOTE/) {
+ my $M=lc($P);
+ push @MK_TAGS, "s|<$P>|<$M class=\\\"$P\\\">|g;";
+ push @MK_TAGS, "s|<$P |<$M class=\\\"$P\\\" |g;";
+ push @MK_TAGS, "s|</$P>|</$M>|g;";
+}
+push @MK_TAGS, "s|<>|\\&nbsp\\;|g;";
+push @MK_TAGS, "s|<->|<WBR />\\;|g;";
+# also make sure that some non-html entries are cleaned away that
+# we are generally using to inject meta information. We want to see
+# that meta ino in the *.htm browser view during editing but they
+# shall not get present in the final html page for publishing.
+my @DC_VARS =
+ ("contributor", "date", "source", "language", "coverage", "identifier",
+ "rights", "relation", "creator", "subject", "description",
+ "publisher", "DCMIType");
+my @_EQUIVS =
+ ("refresh", "expires", "content-type", "cache-control",
+ "redirect", "charset", # mapped to refresh / content-type
+ "content-language", "content-script-type", "content-style-type");
+for my $P (@DC_VARS) { # dublin core embedded
+ push @MK_TAGS, "s|<$P>[^<>]*</$P>||g;";
+}
+for my $P (@_EQUIVS) {
+ push @MK_TAGS, "s|<$P>[^<>]*</$P>||g;";
+}
+push @MK_TAGS, "s|<!--sect[$AZ$NN]-->||g;";
+push @MK_TAGS, "s|<!--[$AX]*[?]-->||g;";
+push @MK_TAGS, "s|<!--\\\$[$AX]*[?]:-->||g;";
+push @MK_TAGS, "s|<!--\\\$[$AX]*:[?=]-->||g;";
+push @MK_TAGS, "s|(<[^<>]*)\\\${[$AX]*:[?=]([^<{}>]*)}([^<>]*>)|\$1\$2\$3|g;";
+
+my $TRIMM=" -e 's:^ *::' -e 's: *\$::'"; # trimm away leading/trailing spaces
+sub trimm
+{
+ my ($T,$Z) = @_;
+ $T =~ s:\A\s*::s; $T =~ s:\s*\Z::s;
+ return $T;
+}
+sub trimmm
+{
+ my ($T,$Z) = @_;
+ $T =~ s:\A\s*::s; $T =~ s:\s*\Z::s; $T =~ s:\s+: :g;
+ return $T;
+}
+sub timezone
+{
+ # +%z is an extension while +%Z is supposed to be posix
+ my $tz;
+ eval { $tz = strftime("%z", localtime()) };
+ return $tz if $tz =~ /[+]/;
+ return $tz if $tz =~ /[-]/;
+ return strftime("%Z", localtime());
+}
+
+sub timetoday
+{
+ return strftime("%Y-%m-%d", localtime());
+}
+sub timetodays
+{
+ return strftime("%Y-%m%d", localtime());
+}
+
+sub esc
+{
+ my ($TXT,$XXX) = @_;
+ $TXT =~ s|&|\\\\&|g;
+ return $TXT;
+}
+
+my %SOURCE;
+sub source # $file : @lines
+{
+ my ($FILE,$Z) = @_;
+ if (exists $SOURCE{$FILE}) { return @{$SOURCE{$FILE}}; }
+ my @TEXT = ();
+ open FILE, "<$FILE" or die "could not open $FILE: $!";
+ for my $line (<FILE>) {
+ push @TEXT, $line;
+ } close FILE;
+ @{$SOURCE{$FILE}} = @TEXT;
+ return @{$SOURCE{$FILE}};
+}
+sub savesource # $file \@lines
+{
+ my ($FILE,$LINES,$Z) = @_;
+ @{$SOURCE{$FILE}} = @{$LINES};
+}
+
+my $F; # current file during loop <<<<<<<<<
+my $i = 100;
+sub savelist {
+ if (-d "DEBUG") {
+ my $X = "$F._$i"; $i++; $X =~ s|/|:|g;
+ open X, ">DEBUG/$X" or die "could not open $X: $!";
+ print X "#! /usr/bin/perl -".$#_."$n";
+ print X join("$n", @{$_[0]}),$n; close X;
+ }
+}
+
+sub eval_MK_LIST # $str @list
+{
+ my $result = $_[0]; shift @_;
+ my $extra = "";
+ my $script = "\$_ = \$result; my \$Z;";
+ $script .= join(";$n ", @_);
+ $script .= "$n;\$result = \$_;$n";
+ eval $script;
+ return $result.$extra;
+}
+
+sub eval_MK_FILE {
+ my $FILENAME = $_[0]; shift @_;
+ my $result = "";
+ my $script = "my \$FILE; my \$extra = ''; my \$Z; $n";
+ $script.= "for (source('$FILENAME')) { $n";
+ $script.= join(";$n ", @_);
+ $script.= "$n; \$result .= \$_; ";
+ $script.= "$n if(\$extra){\$result.=\$extra;\$extra='';\$result.=\"\\n\"}";
+ $script.= "$n} if(\$extra){\$result.=\$extra;}$n";
+ savelist([$script,""]);
+ eval $script;
+ return $result;
+}
+my $sed_add = "\$extra .= "; # "/r ";
+
+sub foo { print " '$F'$n"; }
+sub ls_s {
+ my $result = `ls -s @_`;
+ chomp($result);
+ return $result;
+}
+
+# ======================================================================
+# FUNCS
+
+my $SOURCEFILE; # current file <<<<<<<<
+my @FILELIST; # <<<<<<<
+
+sub sed_slash_key # helper to escape chars special in /anchor/ regex
+{ # currently escaping "/" "[" "]" "."
+ my $R = $_[0]; $R =~ s|[\"./[-]|\\$&|g; $R =~ s|\]|\\\\$&|g;
+ return $R;
+}
+sub sed_piped_key # helper to escape chars special in s|anchor|| regex
+{ # currently escaping "|" "[" "]" "."
+ my $R = $_[0]; $R =~ s/[\".|[-]/\\$&/g; $R =~ s/\]/\\\\$&/g;
+ return $R;
+}
+
+sub back_path # helper to get the series of "../" for a given path
+{
+ my ($R,$Z) = @_; if ($R !~ /\//) { return ""; }
+ $R =~ s|/[^/]*$|/|; $R =~ s|[^/]*/|../|g;
+ return $R;
+}
+
+sub dir_name
+{
+ my $R = $_[0]; $R =~ s:/[^/][^/]*\$::;
+ return $R;
+}
+
+sub info2test_sed # \@ \@ # cut out all old-style <!--vars--> usages
+{
+ my ($INP,$XXX) = @_;
+ $INP = \@{$INFO{$F}} if not $INP;
+ my @OUT = ();
+ my $V8=" *([^ ][^ ]*) (.*)";
+ my $V9=" *DC[.]([^ ][^ ]*) (.*)";
+ my $q="\\\$";
+ my ($_x_,$_y_,$_X_,$_Y_); my $W = "WARNING:";
+ $_x_= sub {"$W: assumed simplevar <!--$1--> changed to <!--$q$1:=-->" };
+ $_y_= sub {"$W: assumed simplevar <!--$1--> changed to <!--$q$1:?-->" };
+ $_X_= sub {"$W: assumed tailvar <!--$q$1:--> changed to <!--$q$1:=-->" };
+ $_Y_= sub {"$W: assumed tailvar <!--$q$1:--> changed to <!--$q$1:?-->" };
+ push @OUT, "s/^/ /;";
+ for (@$INP) {
+ if (/^=....=formatter /) { next; };
+ if (/=[Tt]ext=$V9%/){ push @OUT, esc("s|.*<!--($1)-->.*|".&$_x_."|;");}
+ if (/=[Nn]ame=$V9%/){ push @OUT, esc("s|.*<!--($1)[?]-->.*|".&$_y_."|;");}
+ if (/=[Tt]ext=$V8%/){ push @OUT, esc("s|.*<!--($1)-->.*|".&$_x_."|;");}
+ if (/=[Nn]ame=$V8%/){ push @OUT, esc("s|.*<!--($1)[?]-->.*|".&$_y_."|;");}
+ }
+ for (@$INP) {
+ if (/^=....=formatter /) { next; };
+ if (/=[Tt]ext=$V9%/){ push @OUT, esc("s|.*<!--($1):-->.*|".&$_X_."|;");}
+ if (/=[Nn]ame=$V9%/){ push @OUT, esc("s|.*<!--($1)[?]:-->.*|".&$_Y_."|;");}
+ if (/=[Tt]ext=$V8%/){ push @OUT, esc("s|.*<!--($1):-->.*|".&$_X_."|;");}
+ if (/=[Nn]ame=$V8%/){ push @OUT, esc("s|.*<!--($1)[?]:-->.*|".&$_Y_."|;");}
+ }
+ push @OUT, "/^WARNING:/ || next;";
+ return @OUT;
+}
+
+sub info2vars_sed # generate <!--$vars--> substition sed addon script
+{
+ my ($INP,$Z) = @_;
+ $INP = \@{$INFO{$F}} if not $INP;
+ my @OUT = ();
+ my $V8=" *([^ ][^ ]*) +(.*)";
+ my $V9=" *DC[.]([^ ][^ ]*) +(.*)";
+ my $N8=" *([^ ][^ ]*) ([$NN].*)";
+ my $N9=" *DC[.]([^ ][^ ]*) ([$NN].*)";
+ my $V0="([<]*)\\\$";
+ my $V1="([^<>]*)\\\$";
+ my $V2="([^{<>}]*)";
+ my $V3="([^<>]*)";
+ my $SS="<"."<>".">"; # spacer so value="2004" dont make for s|\(...\)|\12004|
+ $Z="\$Z=";
+ $updatevars = "no" if $commentvars eq "no"; # duplicated from
+ $expandvars = "no" if $commentvars eq "no"; # option handling
+ $simplevars = "no" if $commentvars eq "no"; # tests below
+ my @_INP = (); for (@{$INP}) { my $x=$_; $x =~ s/'/\\'/; push @_INP, $x; }
+ if ($expandvars ne "no") {
+ for (@_INP) {
+ if (/^=....=formatter /) { next; }
+ elsif (/^=name=$V9/){push @OUT, "\$Z='$2';s|<!--$V0$1\\?-->|- \$Z|;"}
+ elsif (/^=Name=$V9/){push @OUT, "\$Z='$2';s|<!--$V0$1\\?-->|(\$Z)|;"}
+ elsif (/^=name=$V8/){push @OUT, "\$Z='$2';s|<!--$V0$1\\?-->|- \$Z|;"}
+ elsif (/^=Name=$V8/){push @OUT, "\$Z='$2';s|<!--$V0$1\\?-->|(\$Z)|;"}
+ }
+ }
+ if ($expandvars ne "no") {
+ for (@_INP) {
+ if (/^=....=formatter /) { next; }
+ elsif (/^=text=$V9/){push @OUT, "\$Z='$2';s|<!--$V1$1-->|\$1$SS\$Z|;"}
+ elsif (/^=Text=$V9/){push @OUT, "\$Z='$2';s|<!--$V1$1-->|\$1$SS\$Z|;"}
+ elsif (/^=name=$V9/){push @OUT, "\$Z='$2';s|<!--$V1$1\\?-->|\$1$SS\$Z|;"}
+ elsif (/^=Name=$V9/){push @OUT, "\$Z='$2';s|<!--$V1$1\\?-->|\$1$SS\$Z|;"}
+ elsif (/^=text=$V8/){push @OUT, "\$Z='$2';s|<!--$V1$1-->|\$1$SS\$Z|;"}
+ elsif (/^=Text=$V8/){push @OUT, "\$Z='$2';s|<!--$V1$1-->|\$1$SS\$Z|;"}
+ elsif (/^=name=$V8/){push @OUT, "\$Z='$2';s|<!--$V1$1\\?-->|\$1$SS\$Z|;"}
+ elsif (/^=Name=$V8/){push @OUT, "\$Z='$2';s|<!--$V1$1\\?-->|\$1$SS\$Z|;"}
+ }
+ }
+ if ($simplevars ne "no" && $updatevars ne "no") {
+ for (@_INP) { my $Q = "[$AX]*";
+ if (/^=....=formatter /) { next; }
+ elsif (/^=text=$V9/){push @OUT, "\$Z='$2';s|<!--$V0$1:-->$Q|\$Z|;"}
+ elsif (/^=Text=$V9/){push @OUT, "\$Z='$2';s|<!--$V0$1:-->$Q|\$Z|;"}
+ elsif (/^=name=$V9/){push @OUT, "\$Z='$2';s|<!--$V0$1\\?:-->$Q|- \$Z|;"}
+ elsif (/^=Name=$V9/){push @OUT, "\$Z='$2';s|<!--$V0$1\\?:-->$Q|(\$Z)|;"}
+ elsif (/^=text=$V8/){push @OUT, "\$Z='$2';s|<!--$V0$1:-->$Q|\$Z|;"}
+ elsif (/^=Text=$V8/){push @OUT, "\$Z='$2';s|<!--$V0$1:-->$Q|\$Z|;"}
+ elsif (/^=name=$V8/){push @OUT, "\$Z='$2';s|<!--$V0$1\\?:-->$Q|- \$Z|;"}
+ elsif (/^=Name=$V8/){push @OUT, "\$Z='$2';s|<!--$V0$1\\?:-->$Q|(\$Z)|;"}
+ }
+ }
+ if ($updatevars ne "no") {
+ for (@_INP) { my $Q = "[^<>]*";
+ if (/^=....=formatter /) { next; }
+ elsif (/^=name=$V9/){push @OUT, "\$Z='$2';s|<!--$V0$1:\\?-->$Q|- \$Z|;"}
+ elsif (/^=Name=$V9/){push @OUT, "\$Z='$2';s|<!--$V0$1:\\?-->$Q|(\$Z)|;"}
+ elsif (/^=name=$V8/){push @OUT, "\$Z='$2';s|<!--$V0$1:\\?-->$Q|- \$Z|;"}
+ elsif (/^=Name=$V8/){push @OUT, "\$Z='$2';s|<!--$V0$1:\\?-->$Q|(\$Z)|;"}
+ }
+ }
+ if ($updatevars ne "no") {
+ for (@_INP) { my $Q = "[^<>]*";
+ if (/^=....=formatter /) { next; }
+ elsif (/^=text=$V9/){push @OUT,"\$Z='$2';s|<!--$V1$1:\\=-->$Q|\$1$SS\$Z|;"}
+ elsif (/^=Text=$V9/){push @OUT,"\$Z='$2';s|<!--$V1$1:\\=-->$Q|\$1$SS\$Z|;"}
+ elsif (/^=name=$V9/){push @OUT,"\$Z='$2';s|<!--$V1$1:\\?-->$Q|\$1$SS\$Z|;"}
+ elsif (/^=Name=$V9/){push @OUT,"\$Z='$2';s|<!--$V1$1:\\?-->$Q|\$1$SS\$Z|;"}
+ elsif (/^=text=$V8/){push @OUT,"\$Z='$2';s|<!--$V1$1:\\=-->$Q|\$1$SS\$Z|;"}
+ elsif (/^=Text=$V8/){push @OUT,"\$Z='$2';s|<!--$V1$1:\\=-->$Q|\$1$SS\$Z|;"}
+ elsif (/^=name=$V8/){push @OUT,"\$Z='$2';s|<!--$V1$1:\\?-->$Q|\$1$SS\$Z|;"}
+ elsif (/^=Name=$V8/){push @OUT,"\$Z='$2';s|<!--$V1$1:\\?-->$Q|\$1$SS\$Z|;"}
+ }
+ }
+ if ($attribvars ne "no") {
+ for (@_INP) { my $Q = "[^<>]*";
+ if (/^=....=formatter /) { next; }
+ elsif (/^=text=$V9/){push @OUT,"\$Z='$2';s|<$V1\{$1:[=]$V2}$V3>|<\$1$SS\$Z\$3>|;"}
+ elsif (/^=Text=$V9/){push @OUT,"\$Z='$2';s|<$V1\{$1:[=]$V2}$V3>|<\$1$SS\$Z\$3>|;"}
+ elsif (/^=name=$V9/){push @OUT,"\$Z='$2';s|<$V1\{$1:[?]$V2}$V3>|<\$1$SS\$Z\$3>|;"}
+ elsif (/^=Name=$V9/){push @OUT,"\$Z='$2';s|<$V1\{$1:[?]$V2}$V3>|<\$1$SS\$Z\$3>|;"}
+ elsif (/^=text=$V8/){push @OUT,"\$Z='$2';s|<$V1\{$1:[=]$V2}$V3>|<\$1$SS\$Z\$3>|;"}
+ elsif (/^=Text=$V8/){push @OUT,"\$Z='$2';s|<$V1\{$1:[=]$V2}$V3>|<\$1$SS\$Z\$3>|;"}
+ elsif (/^=name=$V8/){push @OUT,"\$Z='$2';s|<$V1\{$1:[?]$V2}$V3>|<\$1$SS\$Z\$3>|;"}
+ elsif (/^=Name=$V8/){push @OUT,"\$Z='$2';s|<$V1\{$1:[?]$V2}$V3>|<\$1$SS\$Z\$3>|;"}
+ }
+ for (split / /, $o{variables}) {
+ {push @OUT,"\$Z='$o{$_}';s|<$V1\{$_:[?]$V2}$V3>|<\$1$SS\$Z\$3>|;"}
+ }
+ }
+ if ($simplevars ne "no") {
+ for (@_INP) { my $Q = "[$AX]*";
+ if (/^=....=formatter /) { next; }
+ elsif (/^=text=$V9/){push @OUT, "\$Z='$2';s|<!--$1-->$Q|\$Z|;"}
+ elsif (/^=Text=$V9/){push @OUT, "\$Z='$2';s|<!--$1-->$Q|\$Z|;"}
+ elsif (/^=name=$V9/){push @OUT, "\$Z='$2';s|<!--$1\\?-->$Q| - \$Z|;"}
+ elsif (/^=Name=$V9/){push @OUT, "\$Z='$2';s|<!--$1\\?-->$Q| (\$Z)|;"}
+ elsif (/^=text=$V8/){push @OUT, "\$Z='$2';s|<!--$1-->$Q|\$Z|;"}
+ elsif (/^=Text=$V8/){push @OUT, "\$Z='$2';s|<!--$1-->$Q|\$Z|;"}
+ elsif (/^=name=$V8/){push @OUT, "\$Z='$2';s|<!--$1\\?-->$Q| - \$Z|;"}
+ elsif (/^=Name=$V8/){push @OUT, "\$Z='$2';s|<!--$1\\?-->$Q| (\$Z)|;"}
+ }
+ }
+ # if value="2004" then generated sed might be "\\12004" which is bad
+ # instead we generate an edited value of "\\1$SS$value" and cut out
+ # the spacer now after expanding the variable values:
+ push @OUT, "s|$SS||g;";
+ return @OUT;
+
+}
+
+sub info2meta_sed # generate <meta name..> text portion
+{
+ my ($INP,$XXX) = @_;
+ $INP = \@{$INFO{$F}} if not $INP;
+ my @OUT = ();
+ # http://www.metatab.de/meta_tags/DC_type.htm
+ my $V6=" *HTTP[.]([^ ]+) (.*)";
+ my $V7=" *DC[.]([^ ]+) (.*)";
+ my $V8=" *([^ ]+) (.*)" ;
+ sub __TYPE_SCHEME { "name=\"DC.type\" content=\"$2\" scheme=\"$1\"" };
+ sub __DCMI { "name=\"$1\" content=\"$2\" scheme=\"DCMIType\"" };
+ sub __NAME { "name=\"$1\" content=\"$2\"" };
+ sub __NAME_TZ { "name=\"$1\" content=\"$2 ".&timezone()."\"" };
+ sub __HTTP { "http-equiv=\"$1\" content=\"$2\"" };
+ for (@$INP) {
+ if (/=....=today /) { next; }
+ if (/=meta=HTTP[.]/ && /=meta=$V6/) {
+ push @OUT, " <meta ${\(__HTTP)} />" if $2; next; }
+ if (/=meta=DC[.]DCMIType / && /=meta=$V7/) {
+ push @OUT, " <meta ${\(__TYPE_SCHEME)} />" if $2; next; }
+ if (/=meta=DC[.]type Collection$/ && /=meta=$V8/) {
+ push @OUT, " <meta ${\(__DCMI)} />" if $2; next; }
+ if (/=meta=DC[.]type Dataset$/ && /=meta=$V8/) {
+ push @OUT, " <meta ${\(__DCMI)} />" if $2; next; }
+ if (/=meta=DC[.]type Event$/ && /=meta=$V8/) {
+ push @OUT, " <meta ${\(__DCMI)} />" if $2; next; }
+ if (/=meta=DC[.]type Image$/ && /=meta=$V8/) {
+ push @OUT, " <meta ${\(__DCMI)} />" if $2; next; }
+ if (/=meta=DC[.]type Service$/ && /=meta=$V8/) {
+ push @OUT, " <meta ${\(__DCMI)} />" if $2; next; }
+ if (/=meta=DC[.]type Software$/ && /=meta=$V8/) {
+ push @OUT, " <meta ${\(__DCMI)} />" if $2; next; }
+ if (/=meta=DC[.]type Sound$/ && /=meta=$V8/) {
+ push @OUT, " <meta ${\(__DCMI)} />" if $2; next; }
+ if (/=meta=DC[.]type Text$/ && /=meta=$V8/) {
+ push @OUT, " <meta ${\(__DCMI)} />" if $2; next; }
+ if (/=meta=DC[.]date[.].*[+]/ && /=meta=$V8/) {
+ push @OUT, " <meta ${\(__NAME)} />" if $2; next; }
+ if (/=meta=DC[.]date[.].*[:]/ && /=meta=$V8/) {
+ push @OUT, " <meta ${\(__NAME_TZ)} />" if $2; next; }
+ if (/=meta=/ && /=meta=$V8/) {
+ push @OUT, " <meta ${\(__NAME)} />" if $2; next; }
+ }
+ return @OUT;
+}
+
+sub info_get_entry # get the first <!--vars--> value known so far
+{
+ my ($TXT,$INP,$XXX) = @_;
+ $TXT = "sect" if not $TXT;
+ $INP = \@{$INFO{$F}} if not $INP;
+ for (grep {/=text=$TXT /} @$INP) {
+ my $info = $_;
+ $info =~ s/=text=$TXT //;
+ chomp($info); chomp($info); return $info;
+ }
+}
+
+sub info1grep # test for a <!--vars--> substition to be already present
+{
+ my ($TXT,$INP,$XXX) = @_;
+ $TXT = "sect" if not $TXT;
+ $INP = \@{$INFO{$F}} if not $INP;
+ return scalar(grep {/^=text=$TXT /} @$INP); # returning the count
+}
+
+sub dx_init
+{
+ @{$INFO{$F}} = ();
+ &dx_meta ("formatter", basename($o{formatter}));
+ for (split / /, $o{variables}) { # commandline --def=value
+ if (/_/) { my $u=$_; $u =~ y/_/-/; # makes for <!--$def--> override
+ &dx_meta ($u, $o{$_});
+ } else { &dx_text ($_, $o{$_}); }
+ }
+}
+
+sub dx_line
+{
+ my ($U,$V,$W,$Z) = @_; chomp($U); chomp($V);
+ push @{$INFO{$F}}, $U.$V." ".trimmm($W);
+}
+
+sub DX_line
+{
+ my ($U,$V,$W,$Z) = @_; $W =~ s/<[^<>]*>//g;
+ &dx_line ($U,$V,$W);
+}
+
+sub dx_text
+{
+ my ($U,$V,$Z) = @_;
+ &dx_line ("=text=",$U,$V);
+}
+
+sub DX_text # add a <!--vars--> substition includings format variants
+{
+ my ($N, $T,$XXX) = @_;
+ $N = trimm($N); $T = trimm($T);
+ if ($N) {
+ if ($T) {
+ my $text=lc("$T"); $text =~ s/<[^<>]*>//g;
+ &dx_line ("=text=",$N,$T);
+ &dx_line ("=name=",$N,$text);
+ my $varname=$N; $varname =~ s/.*[.]//; # cut out front part
+ if ($N ne $varname and $varname) {
+ $text=lc("$varname $T"); $text =~ s/<[^<>]*>//g;
+ &dx_line ("=Text=",$varname,$T);
+ &dx_line ("=Name=",$varname,$text);
+ }
+ }
+ }
+}
+
+sub dx_meta
+{
+ my ($U,$V,$Z) = @_;
+ &DX_line ("=meta=",$U,$V);
+}
+
+sub DX_meta # add simple meta entry and its <!--vars--> subsitution
+{
+ my ($U,$V,$Z) = @_;
+ &DX_line ("=meta=",$U,$V);
+ &DX_text ("$U", $V);
+}
+
+sub DC_meta # add new DC.meta entry plus two <!--vars--> substitutions
+{
+ my ($U,$V,$Z) = @_;
+ &DX_line ("=meta=","DC.$U",$V);
+ &DX_text ("DC.$U", $V);
+ &DX_text ("$U", $V);
+}
+
+sub HTTP_meta # add new HTTP.meta entry plus two <!--vars--> substitutions
+{
+ my ($U,$V,$Z) = @_;
+ &DX_line ("=meta=","HTTP.$U",$V);
+ &DX_text ("HTTP.$U", $V);
+ &DX_text ("$U", $V);
+}
+
+sub DC_VARS_Of # check DC vars as listed in $DC_VARS global/generate DC_meta
+{ # the results will be added to .meta.tmp and .vars.tmp later
+ my ($FILENAME,$Z)= @_;
+ $FILENAME=$SOURCEFILE if not $FILENAME;
+ for my $M (@DC_VARS, "title") {
+ # scan for a <markup> of this name FIXME
+ my ($part,$text);
+ for (source($FILENAME)) {
+ /<$M>/ or next; s|.*<$M>||; s|</$M>.*||;
+ $part = trimm($_); last;
+ }
+ $text=$part; $text =~ s|^\w*:||; $text = trimm($text);
+ next if not $text;
+ # <mark:part> will be <meta name="mark.part">
+ if ($text ne $part) {
+ my $N=$part; $N =~ s/:.*//;
+ &DC_meta ("$M.$N", $text);
+ } elsif ($M eq "date") {
+ &DC_meta ("$M.issued", $text); # "<date>" -> "<date>issued:"
+ } else {
+ &DC_meta ("$M", $text);
+ }
+ }
+}
+
+sub HTTP_VARS_Of # check HTTP-EQUIVs as listed in $_EQUIV global then
+{ # generate meta tags that are http-equiv= instead of name=
+ my ($FILENAME,$Z)= @_;
+ $FILENAME=$SOURCEFILE if not $FILENAME;
+ for my $M (@_EQUIVS) {
+ # scan for a <markup> of this name FIXME
+ my ($part,$text);
+ for (source($FILENAME)) {
+ /<$M>/ or next; s|.*<$M>||; s|</$M>.*||;
+ $part = trimm($_); last;
+ }
+ $text=$part; $text =~ s|^\w*:||; $text = trimm($text);
+ next if not $text;
+ if ($M eq "redirect") {
+ &HTTP_meta ("refresh", "5; url=$text"); &DX_text ("$M", $text);
+ } elsif ($M eq "charset") {
+ &HTTP_meta ("content-type", "text/html; charset=$text");
+ } else {
+ &HTTP_meta ("$M", $text);
+ }
+ }
+}
+
+sub DC_isFormatOf # make sure there is this DC.relation.isFormatOf tag
+{ # choose argument for a fallback (usually $SOURCEFILE)
+ my ($NAME,$Z) = @_;
+ $NAME=$SOURCEFILE if not $NAME;
+ if (not &info1grep ("DC.relation.isFormatOf")) {
+ &DC_meta ("relation.isFormatOf", "$NAME");
+ }
+}
+
+sub DC_publisher # make sure there is this DC.publisher meta tag
+{ # choose argument for a fallback (often $USER)
+ my ($NAME,$Z) = @_;
+ $NAME=$ENV{"USER"} if not $NAME;
+ if (not &info1grep ("DC.publisher")) {
+ &DC_meta ("publisher", "$NAME");
+ }
+}
+
+sub DC_modified # make sure there is a DC.date.modified meta tag
+{ # maybe choose from filesystem dates if possible
+ my ($Q,$Z) = @_; # target file
+ if (not &info1grep ("DC.date.modified")) {
+ my @stats = stat($Q);
+ my $text = strftime("%Y-%m-%d", localtime($stats[9]));
+ &DC_meta ("date.modified", $text);
+ }
+}
+
+sub DC_date # make sure there is this DC.date meta tag
+{ # choose from one of the available DC.date.* specials
+ my ($Q,$Z) = @_; # source file
+ if (&info1grep ("DC.date")) {
+ &DX_text ("issue", "dated ".&info_get_entry("DC.date"));
+ &DX_text ("updated", &info_get_entry("DC.date"));
+ } else {
+ my $text=""; my $kind;
+ for $kind (qw/available issued modified created/) {
+ $text=&info_get_entry("DC.date.$kind");
+ # test ".$text" != "." && echo "$kind = date = $text ($Q)"
+ last if $text;
+ }
+ if (not $text) {
+ my $part; my $M="date";
+ for (source($Q)) {
+ /<$M>/ or next; s|.*<$M>||; s|</$M>.*||;
+ $part=trimm($_); last;
+ }
+ $text=$part; $text =~ s|^[$AA]*:||;
+ $text = &trimm ($text);
+ }
+ if (not $text) {
+ my $part; my $M="!--date:*=*--"; # takeover updateable variable...
+ for (source($Q)) {
+ /<$M>/ or next; s|.*<$M>||; s|</.*||;
+ $part=trimm($_); last;
+ }
+ $text=$part; $text =~ s|^[$AA]*:||; $text =~ s|\&.*||;
+ $text = &trimm ($text);
+ }
+ $text =~ s/[$NN]*:.*//; # cut way seconds
+ &DX_text ("updated", $text);
+ my $text1=$text; $text1 =~ s|^.* *updated ||;
+ if ($text ne $text1) {
+ $kind="modified" ; $text=$text1; $text =~ s|,.*||;
+ }
+ $text1=$text; $text1 =~ s|^.* *modified ||;
+ if ($text ne $text1) {
+ $kind="modified" ; $text=$text1; $text =~ s|,.*||;
+ }
+ $text1=$text; $text1 =~ s|^.* *created ||;
+ if ($text ne $text1) {
+ $kind="created" ; $text=$text1; $text =~ s|,.*||;
+ }
+ &DC_meta ("date", "$text");
+ &DX_text ("issue", "$kind $text");
+ }
+}
+
+sub DC_title
+{
+ # choose a title for the document, either an explicit title-tag
+ # or one of the section headers in the document or fallback to filename
+ my ($Q,$Z) = @_; # target file
+ my ($term, $text);
+ if (not &info1grep ("DC.title")) {
+ for my $M (qw/TITLE title H1 h1 H2 h2 H3 H3 H4 H4 H5 h5 H6 h6/) {
+ for (source($Q)) {
+ /<$M>/ or next; s|.*<$M>||; s|</$M>.*||;
+ $text = trimm($_); last;
+ }
+ last if $text;
+ for (source($Q)) {
+ /<$M [^<>]*>/ or next; s|.*<$M [^<>]*>||; s|</$M>.*||;
+ $text = trimm($_); last;
+ }
+ last if $text;
+ }
+ if (not $text) {
+ $text=basename($Q,".html");
+ $text=basename($text,".htm"); $text =~ y/_/ /; $text =~ s/$/ info/;
+ $text=~ s/\n/ /g;
+ }
+ $term=$text; $term =~ s/.*[\(]//; $term =~ s/[\)].*//;
+ $text =~ s/[\(][^\(\)]*[\)]//;
+ if (not $term or $term eq $text) {
+ &DC_meta ("title", "$text");
+ } else {
+ &DC_meta ("title", "$term - $text");
+ }
+ }
+}
+
+sub site_get_section # return parent section page of given page
+{
+ my $_F_ = &sed_slash_key(@_);
+ for my $x (grep {/=sect=$_F_ /} @MK_INFO) {
+ my $info = $x; $info =~ s/=sect=[^ ]* //; return $info;
+ }
+}
+
+sub DC_section # not really a DC relation (shall we use isPartOf ?)
+{ # each document should know its section father
+ my $sectn = &site_get_section($F);
+ if ($sectn) {
+ &DC_meta ("relation.section", $sectn);
+ }
+}
+
+sub info_get_entry_section
+{
+ return &info_get_entry("DC.relation.section");
+}
+
+sub site_get_selected # return section of given page
+{
+ my $_F_ = &sed_slash_key(@_);
+ for my $x (grep {/=[u]se.=$_F_ /} @MK_INFO) {
+ my $info = $x; $info =~ s/=[u]se.=[^ ]* //; return $info;
+ }
+}
+
+sub DC_selected # not really a DC title (shall we use alternative ?)
+{
+ # each document might want to highlight the currently selected item
+ my $short=&site_get_selected($F);
+ if ($short) {
+ &DC_meta ("title.selected", $short);
+ }
+}
+
+sub info_get_entry_selected
+{
+ return &info_get_entry("DC.title.selected");
+}
+
+sub site_get_rootsections # return all sections from root of nav tree
+{
+ my @OUT;
+ for (grep {/=[u]se1=/} @MK_INFO) {
+ my $x = $_;
+ $x =~ s/=[u]se.=([^ ]*) .*/$1/;
+ push @OUT, $x;
+ }
+ return @OUT;
+}
+
+sub site_get_sectionpages # return all children pages in the given section
+{
+ my $_F_=&sed_slash_key(@_);
+ my @OUT = ();
+ for (grep {/^=sect=[^ ]* $_F_$/} @MK_INFO) {
+ my $x = $_;
+ $x =~ s/^=sect=//; $x =~ s/ .*//;
+ push @OUT, $x;
+ }
+ return @OUT;
+}
+
+sub site_get_subpages # return all page children of given page
+{
+ my $_F_=&sed_slash_key(@_);
+ my @OUT = ();
+ for (grep {/^=node=[^ ]* $_F_$/} @MK_INFO) {
+ my $x = $_;
+ $x =~ s/^=node=//; $x =~ s/ .*//;
+ push @OUT, $x;
+ }
+ return @OUT;
+}
+
+sub site_get_parentpage # ret parent page for given page (".." for sections)
+{
+ my $_F_=&sed_slash_key(@_);
+ for (grep {/^=node=$_F_ /} @MK_INFO) {
+ my $x = $_;
+ $x =~ s/^=node=[^ ]* //;
+ return $x;
+ }
+}
+
+sub DX_alternative # detect wether page asks for alternative style
+{ # which is generally a shortpage variant
+ my ($U,$Z) = @_;
+ my $x=&mksite_magic_option("alternative",$U);
+ $x =~ s/^ *//; $x =~s/ .*//;
+ if ($x) {
+ &DX_text ("alternative", $x);
+ }
+}
+
+sub info2head_sed # append alternative handling script to $HEAD
+{
+ my @OUT = ();
+ my $have=&info_get_entry("alternative");
+ if ($have) {
+ push @OUT, "/<!--mksite:alternative:$have .*-->/ && do {";
+ push @OUT, "s/<!--mksite:alternative:$have( .*)-->/\$1/";
+ push @OUT, "$sed_add \$_; last; };";
+ }
+ return @OUT;
+}
+sub info2body_sed # append alternative handling script to $BODY
+{
+ my @OUT = ();
+ my $have=&info_get_entry("alternative");
+ if ($have) {
+ push @OUT, "s/<!--mksite:alternative:$have( .*)-->/\$1/";
+ }
+ return @OUT;
+}
+
+sub bodymaker_for_sectioninfo
+{
+ if ($sectioninfo eq "no") { return ""; }
+ my $_x_="<!--mksite:sectioninfo::-->";
+ my $_q_="([^<>]*[$AX][^<>]*)";
+ $_q_="[ ][ ]*$sectioninfo([ ])" if $sectioninfo ne " ";
+ my @OUT = ();
+ push @OUT, "s|(^<[hH][$NN][ >].*</[hH][$NN]>)$_q_|\$1$_x_\$2|";
+ push @OUT, "/$_x_/ and s|^|<table width=\"100%\"><tr valign=\"bottom\"><td>|";
+ push @OUT, "/$_x_/ and s|</[hH][$NN]>|&</td><td align=\"right\"><i>|";
+ push @OUT, "/$_x_/ and s|\$|</i></td></tr></table>|";
+ push @OUT, "s|$_x_||";
+ return @OUT;
+}
+
+sub fast_href # args "$FILETOREFERENCE" "$FROMCURRENTFILE:$F"
+{ # prints path to $FILETOREFERENCE href-clickable in $FROMCURRENTFILE
+ # if no subdirectoy then output is the same as input $FILETOREFERENCE
+ my ($T,$R,$Z) = @_;
+ my $S=&back_path ($R);
+ if (not $S) {
+ return $T;
+ } else {
+ my $t=$T;
+ $t =~ s/^ *$//; $t =~ s/^\/.*//;
+ $t =~ s/^[.][.].*//; $t =~ s/^\w*:.*//;
+ if (not $t) { # don't move any in the pattern above
+ return $T;
+ } else {
+ return "$S$T"; # prefixed with backpath
+ }
+ }
+}
+
+sub make_fast # experimental - make a FAST file that can be applied
+{ # to htm sourcefiles in a subdirectory of the sitefile.
+# R="$1" ; test ".$R" = "." && R="$F"
+ my ($R,$Z) = @_;
+ my $S=&back_path ($R);
+ my @OUT = ();
+ if (not $S) {
+ # echo "backpath '$F' = none needed"
+ return @OUT;
+ } else {
+ # print "backpath '$F' -> '$S'$n";
+ my @hrefs = ();
+ for (source($SITEFILE)) {
+ /href=\"[^\"]*\"/ or next;
+ s/.*href=\"//; s/\".*//; chomp;
+ if (/^ *$/ || /^\// || /^[.][.]/ || /^[\w]*:/) { next; }
+ push @hrefs, $_;
+ }
+ for (source($SOURCEFILE)) {
+ /href=\"[^\"]*\"/ or next;
+ s/.*href=\"//; s/\".*//; chomp;
+ if (/^ *$/ || /^\// || /^[.][.]/ || /^[\w]*:/) { next; }
+ push @hrefs, $_;
+ }
+ my $ref = "";
+ for (sort(@hrefs)) {
+ next if /\$/; # some href="${...}" is problematic
+ next if $ref eq $_; $ref = $_; # uniq
+ push @OUT, "s|href=\\\"$ref\\\"|href=\\\"$S$ref\\\"|;";
+ }
+ return @OUT;
+ }
+}
+
+# ============================================================== SITE MAP INFO
+# each entry needs atleast a list-title, a long-title, and a list-date
+# these are the basic information to be printed in the sitemap file
+# where it is bound the hierarchy of sect/subsect of the entries.
+
+sub site_map_list_title # $file $text
+{
+ my ($U,$V,$Z) = @_; chomp($U);
+ push @MK_INFO, "=list=$U ".trimm($V);
+}
+sub info_map_list_title # $file $text
+{
+ my ($U,$V,$Z) = @_; chomp($U);
+ push @{$INFO{$U}}, "=list=".trimm($V);
+}
+sub site_map_long_title # $file $text
+{
+ my ($U,$V,$Z) = @_; chomp($U);
+ push @MK_INFO, "=long=$U ".trimm($V);
+}
+sub info_map_long_title # $file $text
+{
+ my ($U,$V,$Z) = @_; chomp($U);
+ push @{$INFO{$U}}, "=long=".trimm($V);
+}
+sub site_map_list_date # $file $text
+{
+ my ($U,$V,$Z) = @_; chomp($U);
+ push @MK_INFO, "=date=$U ".trimm($V);
+}
+sub info_map_list_date # $file $text
+{
+ my ($U,$V,$Z) = @_; chomp($U);
+ push @{$INFO{$U}}, "=date=".trimm($V);
+}
+
+sub site_get_list_title
+{
+ my ($U,$V,$Z) = @_;
+ for (@MK_INFO) { if (m|^=list=$U (.*)|) { return $1; } } return "";
+}
+sub site_get_long_title
+{
+ my ($U,$V,$Z) = @_;
+ for (@MK_INFO) { if (m|^=long=$U (.*)|) { return $1; } } return "";
+}
+sub site_get_list_date
+{
+ my ($U,$V,$Z) = @_;
+ for (@MK_INFO) { if (m|^=date=$U (.*)|) { return $1; } } return "";
+}
+
+sub siteinfo2sitemap# generate <name><page><date> addon sed scriptlet
+{ # the resulting script will act on each item/line
+ # containing <!--"filename"--> and expand any following
+ # reference of <!--name--> or <!--date--> or <!--long-->
+ my ($INP,$Z) = @_ ; $INP= \@MK_INFO if not $INP;
+ my @OUT = ();
+ my $_list_=
+ sub{"s|<!--\\\"$1\\\"-->.*<!--name-->|\$\&<name href=\\\"$1\\\">$2</name>|"};
+ my $_date_=
+ sub{"s|<!--\\\"$1\\\"-->.*<!--date-->|\$\&<date>$2</date>|"};
+ my $_long_=
+ sub{"s|<!--\\\"$1\\\"-->.*<!--long-->|\$\&<long>$2</long>|"};
+
+ for (@$INP) {
+ my $info = $_;
+ $info =~ s:=list=([^ ]*) (.*):&$_list_:e;
+ $info =~ s:=date=([^ ]*) (.*):&$_date_:e;
+ $info =~ s:=long=([^ ]*) (.*):&$_long_:e;
+ $info =~ /^s\|/ || next;
+ push @OUT, $info;
+ }
+ return @OUT;
+}
+
+sub make_multisitemap
+{ # each category gets its own column along with the usual entries
+ my ($INPUTS,$Z)= @_ ; $INPUTS=\@MK_INFO if not $INPUTS;
+ @MK_SITE = &siteinfo2sitemap(); # have <name><long><date> addon-sed
+ my @OUT = ();
+ my $_form_= sub{"<!--\"$2\"--><!--use$1--><!--long--><!--end$1-->"
+ ."<br><!--name--><!--date-->" };
+ my $_tiny_="small><small><small" ; my $_tinyX_="small></small></small ";
+ my $_tabb_="<br><$_tiny_> </$_tinyX_>" ; my $_bigg_="<big> </big>";
+ push @OUT, "<table width=\"100%\"><tr><td> ".$n;
+ for (grep {/=[u]se.=/} @$INPUTS) {
+ my $x = $_;
+ $x =~ s|=[u]se(.)=([^ ]*) .*|&$_form_|e;
+ $x = &eval_MK_LIST($x, @MK_SITE); $x =~ /<name/ or next;
+ $x =~ s|<!--[u]se1-->|</td><td valign=\"top\"><b>|;
+ $x =~ s|<!--[e]nd1-->|</b>|;
+ $x =~ s|<!--[u]se2-->|<br>|;
+ $x =~ s|<!--[u]se.-->|<br>|; $x =~ s/<!--[^<>]*-->/ /g;
+ $x =~ s|<long>||; $x =~ s|</long>||;
+ $x =~ s|<name |<$_tiny_><a |; $x =~ s|</name>||;
+ $x =~ s|<date>| |; $x =~ s|</date>|</a><br></$_tinyX_>|;
+ push @OUT, $x.$n;
+ }
+ push @OUT, "</td><tr></table>".$n;
+ return @OUT;
+}
+
+sub make_listsitemap
+{ # traditional - the body contains a list with date and title extras
+ my ($INPUTS,$Z)= @_ ; $INPUTS=\@MK_INFO if not $INPUTS;
+ @MK_SITE = &siteinfo2sitemap(); # have <name><long><date> addon-sed
+ my @OUT = ();
+ my $_form_=sub{
+ "<!--\"$2\"--><!--use$1--><!--name--><!--date--><!--long-->"};
+ my $_tabb_="<td>\&nbsp\;</td>";
+ push @OUT, "<table cellspacing=\"0\" cellpadding=\"0\">".$n;
+ my $xx;
+ for $xx (grep {/=[u]se.=/} @$INPUTS) {
+ my $x = "".$xx;
+ $x =~ s|=[u]se(.)=([^ ]*) .*|&$_form_|e;
+ $x = &eval_MK_LIST($x, @MK_SITE); $x =~ /<name/ or next;
+ $x =~ s|<!--[u]se(1)-->|<tr class=\"listsitemap$1\"><td>*</td>|;
+ $x =~ s|<!--[u]se(2)-->|<tr class=\"listsitemap$1\"><td>-</td>|;
+ $x =~ s|<!--[u]se(.)-->|<tr class=\"listsitemap$1\"><td> </td>|;
+ $x =~ /<tr.class=\"listsitemap3\">/ and $x =~ s|<name [^<>]*>|$&- |;
+ $x =~ s|<!--[^<>]*-->| |g;
+ $x =~ s|<name href=\"name:sitemap:|<name href=\"|;
+ $x =~ s|<name |<td><a |; $x =~ s|</name>|</a></td>$_tabb_|;
+ $x =~ s|<date>|<td><small>|; $x =~ s|</date>|</small></td>$_tabb_|;
+ $x =~ s|<long>|<td><em>|; $x =~ s|</long>|</em></td></tr>|;
+ push @OUT, $x;
+ }
+ for $xx (grep {/=[u]se.=/} @$INPUTS) {
+ my $x = $xx; $x =~ s/=[u]se.=name:sitemap://; $x =~ s:\s*::gs;
+ if (-f $x) {
+ for (grep {/<tr.class=\"listsitemap\d\">/} source($x)) {
+ push @OUT, $_;
+ }
+ }
+ }
+ push @OUT, "</table>".$n;
+ return @OUT;
+}
+
+sub print_extension
+{
+ my ($ARG,$Z)= @_ ; $ARG=$o{print} if not $ARG;
+ if ($ARG =~ /^([.-])/) {
+ return $ARG;
+ } else {
+ return ".print";
+ }
+}
+
+sub html_sourcefile # generally just cut away the trailing "l" (ell)
+{ # making "page.html" argument into "page.htm" return
+ my ($U,$Z) = @_;
+ my $_SRCFILE_=$U; $_SRCFILE_ =~ s/l$//;
+ if (-f $_SRCFILE_) {
+ return $_SRCFILE_;
+ } elsif (-f "$o{src_dir}/$_SRCFILE_") {
+ return "$o{src_dir}/$_SRCFILE_";
+ } else {
+ return ".//$_SRCFILE_";
+ }
+}
+sub html_printerfile_sourcefile
+{
+ my ($U,$Z) = @_;
+ if (not $printerfriendly) {
+ $U =~ s/l\$//; return $U;
+ } else {
+ my $_ext_=&sed_slash_key(&print_extension($printerfriendly));
+ $U =~ s/l\$//; $U =~ s/$_ext_([.][\w]*)$/$1/; return $U;
+ }
+}
+
+sub fast_html_printerfile {
+ my ($U,$V,$Z) = @_;
+ my $x=&html_printerfile($U) ; return basename($x);
+# my $x=&html_printerfile($U) ; return &fast_href($x,$V);
+}
+
+sub html_printerfile # generate the printerfile for a given normal output
+{
+ my ($U,$Z) = @_;
+ my $_ext_=&esc(&print_extension($printerfriendly));
+ $U =~ s/([.][\w]*)$/$_ext_$1/; return $U; # index.html -> index.print.html
+}
+
+sub make_printerfile_fast # generate s/file.html/file.print.html/ for hrefs
+{ # we do that only for the $FILELIST
+ my ($U,$Z) = @_;
+ my $ALLPAGES=$U;
+ my @OUT = ();
+ for my $p (@$ALLPAGES) {
+ my $a=&sed_slash_key($p);
+ my $b=&html_printerfile($p);
+ if ($b ne $p) {
+ $b =~ s:/:\\/:g;
+ push @OUT,
+ "s/<a href=\\\"$a\\\"([^<>])*>/<a href=\\\"$b\\\"\$1>/;";
+ }
+ }
+ return @OUT;
+}
+
+sub echo_printsitefile_style
+{
+ my $_bold_="text-decoration : none ; font-weight : bold ; ";
+ return " <style>"
+ ."$n a:link { $_bold_ color : #000060 ; }"
+ ."$n a:visited { $_bold_ color : #000040 ; }"
+ ."$n body { background-color : white ; }"
+ ."$n </style>"
+ ."$n";
+}
+
+sub make_printsitefile_head # $sitefile
+{
+ my $MK_STYLE = &echo_printsitefile_style();
+ my @OUT = ();
+ for (source($SITEFILE)) {
+ if (/<head>/) { push @OUT, $_;
+ push @OUT, $MK_STYLE; next; }
+ if (/<title>/) { push @OUT, $_; next; }
+ if (/<\/head>/) { push @OUT, $_; next; }
+ if (/<body>/) { push @OUT, $_; next; }
+ if (/<link [^<>]*rel=\"shortcut icon\"[^<>]*>/) {
+ push @OUT, $_; next;
+ }
+ }
+ return @OUT;
+}
+
+# ------------------------------------------------------------------------
+# The printsitefile is a long text containing html href markups where
+# each of the href lines in the file is being prefixed with the section
+# relation. During a secondary call the printsitefile can grepp'ed for
+# those lines that match a given output fast-file. The result is a
+# navigation header with 1...3 lines matching the nesting level
+
+# these alt-texts will be only visible in with a text-mode browser:
+my $printsitefile_square="width=\"8\" height=\"8\" border=\"0\"";
+my $printsitefile_img_1="<img alt=\"|go text:\" $printsitefile_square />";
+my $printsitefile_img_2="<img alt=\"||topics:\" $printsitefile_square />";
+my $printsitefile_img_3="<img alt=\"|||pages:\" $printsitefile_square />";
+my $_SECT="mksite:sect:";
+
+sub echo_current_line # $sect $extra
+{
+ # add the prefix which is used by select_in_printsitefile to cut out things
+ my ($N,$M,$Z) = @_;
+ return "<!--$_SECT\"$N\"-->$M";
+}
+sub make_current_entry # $sect $file ## requires $MK_SITE
+{
+ my ($S,$R,$Z) = @_;
+ my $RR=&sed_slash_key($R);
+ my $sep=" - " ; my $_left_=" [ " ; my $_right_=" ] ";
+ my $name = site_get_list_title($R);
+ $_ = &echo_current_line ("$S", "<a href=\"$R\">$name</a>$sep");
+ if ($R eq $S) {
+ s/<a href/$_left_$&/;
+ s/<\/a>/$&$_right_/;
+ }
+ return $_;
+}
+sub echo_subpage_line # $sect $extra
+{
+ my ($N,$M,$Z) = @_;
+ return "<!--$_SECT*:\"$N\"-->$M";
+}
+
+sub make_subpage_entry
+{
+ my ($S,$R,$Z) = @_;
+ my $RR=&sed_slash_key($R);
+ my $sep=" - " ;
+ my $name = site_get_list_title($R);
+ $_ = &echo_subpage_line ("$S", "<a href=\"$R\">$name</a>$sep");
+ return $_;
+}
+
+sub make_printsitefile
+{
+ # building the printsitefile looks big but its really a loop over sects
+ my ($INPUTS,$Z) = @_; $INPUTS=\@MK_INFO if not $INPUTS;
+ @MK_SITE = &siteinfo2sitemap(); # have <name><long><date> addon-sed
+ savelist(\@MK_SITE);
+ my @OUT = &make_printsitefile_head ($SITEFILE);
+
+ my $sep=" - " ;
+ my $_sect1=
+ "<a href=\"#.\" title=\"section\">$printsitefile_img_1</a> ||$sep";
+ my $_sect2=
+ "<a href=\"#.\" title=\"topics\">$printsitefile_img_2</a> ||$sep";
+ my $_sect3=
+ "<a href=\"#.\" title=\"pages\">$printsitefile_img_3</a> ||$sep";
+
+ my $_SECT1="mksite:sect1";
+ my $_SECT2="mksite:sect2";
+ my $_SECT3="mksite:sect3";
+
+ @MK_SECT1 = &site_get_rootsections();
+ # round one - for each root section print a current menu
+ for my $r (@MK_SECT1) {
+ push @OUT, &echo_current_line ("$r", "<!--$_SECT1:A--><br>$_sect1");
+ for my $s (@MK_SECT1) {
+ push @OUT, &make_current_entry ("$r", "$s");
+ }
+ push @OUT, &echo_current_line ("$r", "<!--$_SECT1:Z-->");
+ }
+
+ # round two - for each subsection print a current and subpage menu
+ for my $r (@MK_SECT1) {
+ @MK_SECT2 = &site_get_subpages ("$r");
+ for my $s (@MK_SECT2) {
+ push @OUT, &echo_current_line ("$s", "<!--$_SECT2:A--><br>$_sect2");
+ for my $t (@MK_SECT2) {
+ push @OUT, &make_current_entry ("$s", "$t");
+ } # "$t"
+ push @OUT, &echo_current_line ("$s", "<!--$_SECT2:Z-->");
+ } # "$s"
+ my $_have_children_="";
+ for my $t (@MK_SECT2) {
+ if (not $_have_children_) {
+ push @OUT, &echo_subpage_line ("$r", "<!--$_SECT2:A--><br>$_sect2"); }
+ $_have_children_ .= "1";
+ push @OUT, &make_subpage_entry ("$r", "$t");
+ }
+ if ($_have_children_) {
+ push @OUT, &echo_subpage_line ("$r", "<!--$_SECT2:Z-->"); }
+ } # "$r"
+
+ # round three - for each subsubsection print a current and subpage menu
+ for my $r (@MK_SECT1) {
+ @MK_SECT2 = &site_get_subpages ("$r");
+ for my $s (@MK_SECT2) {
+ @MK_SECT3 = &site_get_subpages ("$s");
+ for my $t (@MK_SECT3) {
+ push @OUT, &echo_current_line ("$t", "<!--$_SECT3:A--><br>$_sect3");
+ for my $u (@MK_SECT3) {
+ push @OUT, &make_current_entry ("$t", "$u");
+ } # "$t"
+ push @OUT, &echo_current_line ("$t", "<!--$_SECT3:Z-->");
+ } # "$t"
+ my $_have_children_="";
+ for my $u (@MK_SECT3) {
+ if (not $_have_children_) {
+ push @OUT, &echo_subpage_line ("$s", "<!--$_SECT3:A--><br>$_sect3"); }
+ $_have_children_ .= "1";
+ push @OUT, &make_subpage_entry ("$s", "$u");
+ }
+ if ($_have_children_) {
+ push @OUT, &echo_subpage_line ("$s", "<!--$_SECT3:Z-->"); }
+ } # "$s"
+ } # "$r"
+ push @OUT, "<a name=\".\"></a>";
+ push @OUT, "</body></html>";
+ return @OUT;
+}
+
+# create a selector that can grep a printsitefile for the matching entries
+sub select_in_printsitefile # arg = "page" : return to stdout >> $P.$HEAD
+{
+ my ($N,$Z) = @_;
+ my $_selected_="$N" ; $_selected_="$F" if not $_selected_;
+ my $_section_=&sed_slash_key($_selected_);
+ my @OUT = ();
+ push @OUT, "s/^<!--$_SECT\\\"$_section_\\\"-->//;"; # sect3
+ push @OUT, "s/^<!--$_SECT\[*\]:\\\"$_section_\\\"-->//;"; # children
+ $_selected_=&site_get_parentpage($_selected_);
+ if ($F =~ /testscript/) { print "($F)parent=$_selected_$n"; }
+ $_section_=&sed_slash_key($_selected_);
+ push @OUT, "s/^<!--$_SECT\\\"$_section_\\\"-->//;"; # sect2
+ $_selected_=&site_get_parentpage($_selected_);
+ $_section_=&sed_slash_key($_selected_);
+ push @OUT, "s/^<!--$_SECT\\\"$_section_\\\"-->//;"; # sect1
+ push @OUT, "/^<!--$_SECT\\\"[^\\\"]*\\\"-->/ and next;";
+ push @OUT, "/^<!--$_SECT\[*\]:\\\"[^\\\"]*\\\"-->/ and next;";
+ push @OUT, "s/^<!--mksite:sect[$NN]:[$AZ]-->//;";
+ return @OUT;
+}
+
+sub body_for_emailfooter
+{
+ return "" if $emailfooter eq "no";
+ my $_email_=$emailfooter; $_email_ =~ s|[?].*||;
+ my $_dated_=&info_get_entry("updated");
+ return "<hr><table border=\"0\" width=\"100%\"><tr><td>"
+ ."$n"."<a href=\"mailto:$emailfooter\">$_email_</a>"
+ ."$n"."</td><td align=\"right\">"
+ ."$n"."$_dated_</td></tr></table>"
+ ."$n";
+}
+
+# ==========================================================================
+#
+# During processing we will create a series of intermediate files that
+# store relations. They all have the same format being
+# =relationtype=key value
+# where key is usually s filename or an anchor. For mere convenience
+# we assume that the source html text does not have lines that start
+# off with =xxxx= (btw, ye remember perl section notation...). Of course
+# any other format would be usuable as well.
+#
+
+# we scan the SITEFILE for href references to be converted
+# - in the new variant we use a ".gets.tmp" sed script that SECTS
+# marks all interesting lines so they can be checked later
+# with an sed anchor of <!--sect[$NN]--> (or <!--sect[$AZ]-->)
+my $S="\\&nbsp\\;";
+# S="[&]nbsp[;]"
+
+# HR and EM style markups must exist in input - BR sometimes left out
+# these routines in(ter)ject hardspace before, between, after markups
+# note that "<br>" is sometimes used with HR - it must exist in input
+sub echo_HR_EM_PP
+{
+ my ($U,$V,$W,$X,$Z) = @_;
+ my @list = (
+ "/^$U$V$W*<a href=/ and s/^/$X/;",
+ "/^<>$U$V$W*<a href=/ and s/^/$X/;",
+ "/^$S$U$V$W*<a href=/ and s/^/$X/;",
+ "/^$U<>$V$W*<a href=/ and s/^/$X/;",
+ "/^$U$S$V$W*<a href=/ and s/^/$X/;",
+ "/^$U$V<>$W*<a href=/ and s/^/$X/;",
+ "/^$U$V$S$W*<a href=/ and s/^/$X/;" );
+ return @list;
+}
+
+sub echo_br_EM_PP
+{
+ my ($U,$V,$W,$X,$Z) = @_;
+ my @list = &echo_HR_EM_PP ("$U", "$V", "$W", "$X");
+ my @listt = (
+ "/^$V$W*<a href=/ and s/^/$X/;",
+ "/^<>$V$W*<a href=/ and s/^/$X/;",
+ "/^$S$V$W*<a href=/ and s/^/$X/;",
+ "/^$V<>$W*<a href=/ and s/^/$X/;",
+ "/^$V$S$W*<a href=/ and s/^/$X/;" );
+ push @list, @listt;
+ return @list;
+}
+
+sub echo_HR_PP
+{
+ my ($U,$V,$W,$Z) = @_;
+ my @list = (
+ "/^$U$V*<a href=/ and s/^/$W/;",
+ "/^<>$U$V*<a href=/ and s/^/$W/;",
+ "/^$S$U$V*<a href=/ and s/^/$W/;",
+ "/^$U<>$V*<a href=/ and s/^/$W/;",
+ "/^$U$S$V*<a href=/ and s/^/$W/;" );
+ return @list;
+}
+sub echo_br_PP
+{
+ my ($U,$V,$W,$Z) = @_;
+ my @list = &echo_HR_PP ("$U", "$V", "$W");
+ my @listt = (
+ "/^$V*<a href=/ and s/^/$W/;",
+ "/^<>$V*<a href=/ and s/^/$W/;",
+ "/^$S$V*<a href=/ and s/^/$W/;" );
+ push @list, @listt;
+ return @list;
+}
+sub echo_sp_PP
+{
+ my ($U,$V,$Z) = @_;
+ my @list = (
+ "/^<>$U*<a href=/ and s/^/$V/;",
+ "/^$S$U*<a href=/ and s/^/$V/;",
+ "/^<><>$U*<a href=/ and s/^/$V/;",
+ "/^$S$S$U*<a href=/ and s/^/$V/;",
+ "/^<>$U<>*<a href=/ and s/^/$V/;",
+ "/^$S$U$S*<a href=/ and s/^/$V/;",
+ "/^$U<><>*<a href=/ and s/^/$V/;",
+ "/^$U$S$S*<a href=/ and s/^/$V/;",
+ "/^$U<>*<a href=/ and s/^/$V/;",
+ "/^$U$S*<a href=/ and s/^/$V/;" );
+ return @list;
+}
+sub echo_sp_sp
+{
+ my ($U,$V,$Z) = @_;
+ my @list = (
+ "/^$U*<a name=/ and s/^/$V/;",
+ "/^<>$U*<a name=/ and s/^/$V/;",
+ "/^$S$U*<a name=/ and s/^/$V/;",
+ "/^<><>$U*<a name=/ and s/^/$V/;",
+ "/^$S$S$U*<a name=/ and s/^/$V/;",
+ "/^<>$U<>*<a name=/ and s/^/$V/;",
+ "/^$S$U$S*<a name=/ and s/^/$V/;",
+ "/^$U<><>*<a name=/ and s/^/$V/;",
+ "/^$U$S$S*<a name=/ and s/^/$V/;",
+ "/^$U<>*<a name=/ and s/^/$V/;",
+ "/^$U$S*<a name=/ and s/^/$V/;" );
+ return @list;
+}
+
+sub make_sitemap_init
+{
+ # build a list of detectors that map site.htm entries to a section table
+ # note that the resulting .gets.tmp / .puts.tmp are real sed-script
+ my $h1="[-|[]";
+ my $b1="[*=]";
+ my $b2="[-|[]";
+ my $b3="[\\/:]";
+ my $q3="[\\/:,[]";
+ @MK_GETS = ();
+ push @MK_GETS, &echo_HR_PP ("<hr>", "$h1", "<!--sect1-->");
+ push @MK_GETS, &echo_HR_EM_PP("<hr>","<em>", "$h1", "<!--sect1-->");
+ push @MK_GETS, &echo_HR_EM_PP("<hr>","<strong>", "$h1", "<!--sect1-->");
+ push @MK_GETS, &echo_HR_PP ("<br>", , "$b1$b1", "<!--sect1-->");
+ push @MK_GETS, &echo_HR_PP ("<br>", , "$b2$b2", "<!--sect2-->");
+ push @MK_GETS, &echo_HR_PP ("<br>", , "$b3$b3", "<!--sect3-->");
+ push @MK_GETS, &echo_br_PP ("<br>", , "$b2$b2", "<!--sect2-->");
+ push @MK_GETS, &echo_br_PP ("<br>", , "$b3$b3", "<!--sect3-->");
+ push @MK_GETS, &echo_br_EM_PP("<br>","<small>" , "$q3" , "<!--sect3-->");
+ push @MK_GETS, &echo_br_EM_PP("<br>","<em>" , "$q3" , "<!--sect3-->");
+ push @MK_GETS, &echo_br_EM_PP("<br>","<u>" , "$q3" , "<!--sect3-->");
+ push @MK_GETS, &echo_HR_PP ("<br>", , "$q3" , "<!--sect3-->");
+ push @MK_GETS, &echo_sp_PP ( "$q3" , "<!--sect3-->");
+ push @MK_GETS, &echo_sp_sp ( "$q3" , "<!--sect9-->");
+ @MK_PUTS = map { my $x=$_; $x =~ s/(>)(\[)/$1 *$2/; $x } @MK_GETS;
+ # the .puts.tmp variant is used to <b><a href=..></b> some hrefs which
+ # shall not be used otherwise for being generated - this is nice for
+ # some quicklinks somewhere. The difference: a whitspace "<hr> <a...>"
+}
+
+my $_uses_= sub{"=use$1=$2 $3" }; my $_name_= sub{"=use$1=name:$2 $3" };
+my $_getW_="<!--sect([$NN])-->";
+my $_getX_="<!--sect([$NN])--><[^<>]*>[^<>]*";
+my $_getY_="<!--sect([$NN])--><[^<>]*>[^<>]*<[^<>]*>[^<>]*";
+
+sub make_sitemap_list
+{
+ # scan sitefile for references pages - store as "=use+=href+ anchortext"
+ for (source($SITEFILE)) {
+# print join("$n;",@MK_GETS),$n;
+ $_ = &eval_MK_LIST($_, @MK_GETS);
+ /^<!--sect[$NN]-->/ or next;
+ s{^$_getX_<a href=\"([^\"]*)\"[^<>]*>(.*)</a>.*}{&$_uses_}e;
+ s{^$_getY_<a href=\"([^\"]*)\"[^<>]*>(.*)</a>.*}{&$_uses_}e;
+ s{^$_getW_<a name=\"([^\"]*)\"[^<>]*>(.*)</a>.*}{&$_name_}e;
+ s{^$_getX_<a name=\"([^\"]*)\"[^<>]*>(.*)</a>.*}{&$_name_}e;
+ s{^$_getY_<a name=\"([^\"]*)\"[^<>]*>(.*)</a>.*}{&$_name_}e;
+ /^=....=/ or next;
+ push @MK_INFO, $_;
+ }
+}
+
+sub make_sitemap_sect
+{
+ # scan used pages and store prime section group relation =sect= and =node=
+ # (A) each "use1" creates "=sect=href+ href1" for all following non-"use1"
+ # (B) each "use1" creates "=node=href2 href1" for all following "use2"
+ my $sect = "";
+ for (grep {/=[u]se.=/} @MK_INFO) {
+ if (/=[u]se1=([^ ]*) .*/) { $sect = $1; }
+ my $x = $_; $x =~ s/=[u]se.=([^ ]*) .*/=sect=$1/; chomp $x;
+ push @MK_INFO, "$x $sect";
+ }
+ for (grep {/=[u]se.=/} @MK_INFO) {
+ if (/=[u]se1=([^ ]*) .*/) { $sect = $1; }
+ /=[u]se[13456789]=/ and next;
+ my $x = $_; $x =~ s/=[u]se.=([^ ]*) .*/=node=$1/; chomp $x;
+ push @MK_INFO, "$x $sect";
+ }
+}
+
+sub make_sitemap_page
+{
+ # scan used pages and store secondary group relation =page= and =node=
+ # the parenting =node= for use3 is usually a use2 (or use1 if none there)
+ my $sect = "";
+ for (grep {/=[u]se.=/} @MK_INFO) {
+ if (/=[u]se1=([^ ]*) .*/) { $sect = $1; }
+ if (/=[u]se2=([^ ]*) .*/) { $sect = $1; }
+ /=[u]se[1]=/ and next;
+ my $x = $_; $x =~ s/=[u]se.=([^ ]*) .*/=page=$1/; chomp $x;
+ push @MK_INFO, "$x $sect";
+ }
+ for (grep {/=[u]se.=/} @MK_INFO) {
+ if (/=[u]se1=([^ ]*) .*/) { $sect = $1; }
+ if (/=[u]se2=([^ ]*) .*/) { $sect = $1; }
+ /=[u]se[12456789]=/ and next;
+ my $x = $_; $x =~ s/=[u]se.=([^ ]*) .*/=node=$1/; chomp $x;
+ push @MK_INFO, "$x $sect"; print "(",$_,")","$x $sect", $n;
+ }
+ # and for the root sections we register ".." as the parenting group
+ for (grep {/=[u]se1=/} @MK_INFO) {
+ my $x = $_; $x =~ s/=[u]se.=([^ ]*) .*/=node=$1/; chomp $x;
+ push @MK_INFO, trimm("$x ..");
+ }
+}
+sub echo_site_filelist
+{
+ my @OUT = ();
+ for (grep {/=[u]se.=/} @MK_INFO) {
+ my $x = $_; $x =~ s/=[u]se.=//; $x =~ s/ .*[\n]*//;
+ push @OUT, $x;
+ }
+ return @OUT;
+}
+
+# ==========================================================================
+# originally this was a one-pass compiler but the more information
+# we were scanning out the more slower the system ran - since we
+# were rescanning files for things like section information. Now
+# we scan the files first for global information.
+# 1.PASS
+
+sub scan_sitefile # $F
+{
+ $SOURCEFILE=&html_sourcefile($F);
+ if ($SOURCEFILE ne $F) {
+ dx_init "$F";
+ dx_text ("today", &timetoday());
+ my $short=$F;
+ $short =~ s:.*/::; $short =~ s:[.].*::; # basename for all exts
+ $short .=" ~";
+ DC_meta ("title", "$short");
+ DC_meta ("date.available", &timetoday());
+ DC_meta ("subject", "sitemap");
+ DC_meta ("DCMIType", "Collection");
+ DC_VARS_Of ($SOURCEFILE) ; HTTP_VARS_Of ($SOURCEFILE) ;
+ DC_modified ($SOURCEFILE) ; DC_date ($SOURCEFILE);
+ DC_section ($F);
+ DX_text ("date.formatted", &timetoday());
+ if ($printerfriendly) {
+ DX_text ("printerfriendly", fast_html_printerfile($F)); }
+ if ($ENV{USER}) { DC_publisher ($ENV{USER}); }
+ print "'$SOURCEFILE': $short (sitemap)$n";
+ site_map_list_title ($F, "$short");
+ site_map_long_title ($F, "generated sitemap index");
+ site_map_list_date ($F, &timetoday());
+ }
+}
+
+sub scan_htmlfile # "$F"
+{
+ my ($FF,$Z) = @_;
+ $SOURCEFILE=&html_sourcefile($F); # SCAN :
+ if ($SOURCEFILE ne $F) { # HTML :
+ if ( -f $SOURCEFILE) {
+ @{$FAST{$F}} = &make_fast ($F);
+ dx_init "$F";
+ dx_text ("today", &timetoday());
+ dx_text ("todays", &timetodays());
+ DC_VARS_Of ($SOURCEFILE); HTTP_VARS_Of ($SOURCEFILE);
+ DC_title ($SOURCEFILE);
+ DC_isFormatOf ($SOURCEFILE);
+ DC_modified ($SOURCEFILE);
+ DC_date ($SOURCEFILE); DC_date ($SITEFILE);
+ DC_section ($F); DC_selected ($F); DX_alternative ($SOURCEFILE);
+ if ($ENV{USER}) { DC_publisher ($ENV{USER}); }
+ DX_text ("date.formatted", &timetoday());
+ if ($printerfriendly) {
+ DX_text ("printerfriendly", fast_html_printerfile($F)); }
+ my $sectn=&info_get_entry("DC.relation.section");
+ my $short=&info_get_entry("DC.title.selected");
+ &site_map_list_title ($F, "$short");
+ &info_map_list_title ($F, "$short");
+ my $title=&info_get_entry("DC.title");
+ &site_map_long_title ($F, "$title");
+ &info_map_long_title ($F, "$title");
+ my $edate=&info_get_entry("DC.date");
+ my $issue=&info_get_entry("issue");
+ &site_map_list_date ($F, "$edate");
+ &info_map_list_date ($F, "$edate");
+ print "'$SOURCEFILE': '$title' ('$short') @ '$issue' ('$sectn')$n";
+ }else {
+ print "'$SOURCEFILE': does not exist$n";
+ site_map_list_title ($F, "$F");
+ site_map_long_title ($F, "$F (no source)");
+ }
+ } else {
+ print "<$F> - skipped - ($SOURCEFILE)$n";
+ }
+}
+
+sub scan_namespec
+{
+ # nothing so far
+ # my ($F,$ZZZ) = @_;
+ if ($F =~ /^name:sitemap:/) {
+ my $short=$F;
+ $short =~ s:.*/::; $short =~ s:[.].*::; # basename for all exts
+ $short =~ s/name:sitemap://;
+ $short .=" ~";
+ site_map_list_title ($F, "$short");
+ site_map_long_title ($F, "external sitemap index");
+ site_map_list_date ($F, &timetoday());
+ print "'$F' external sitemap index$n";
+ }
+}
+sub scan_httpspec
+{
+ # nothing so far
+}
+
+sub skip_namespec
+{
+ # nothing so far
+}
+sub skip_httpspec
+{
+ # nothing so far
+}
+
+# ==========================================================================
+# and now generate the output pages
+# 2.PASS
+
+sub head_sed_sitemap # $filename $section
+{
+ my ($U,$V,$Z) = @_;
+ my $FF=&sed_slash_key($U);
+ my $SECTION=&sed_slash_key($V);
+ my $SECTS="<!--sect[$NN$AZ]-->" ;
+ my $SECTN="<!--sect[$NN]-->"; # lines with hrefs
+ my @OUT = ();
+ push @OUT, "/^$SECTS.*<a href=\\\"$FF\\\">/ and s|</a>|</a></b>|;";
+ push @OUT, "/^$SECTS.*<a href=\\\"$FF\\\">/ and s|<a href=|<b><a href=|;";
+ push @OUT, "/ href=\\\"$SECTION\\\"/ "
+ ."and s|^<td class=\\\"[^\\\"]*\\\"|<td |;" if $sectiontab ne "no";
+ return @OUT;
+}
+
+sub head_sed_listsection # $filename $section
+{
+ # traditional.... the sitefile is the full navigation bar
+ my ($U,$V,$Z) = @_;
+ my $FF=&sed_slash_key($U);
+ my $SECTION=&sed_slash_key($V);
+ my $SECTS="<!--sect[$NN$AZ]-->" ;
+ my $SECTN="<!--sect[$NN]-->"; # lines with hrefs
+ my @OUT = ();
+ push @OUT, "/^$SECTS.*<a href=\\\"$FF\\\">/ and s|</a>|</a></b>|;";
+ push @OUT, "/^$SECTS.*<a href=\\\"$FF\\\">/ and s|<a href=|<b><a href=|;";
+ push @OUT, "/ href=\\\"$SECTION\\\"/ "
+ ."and s|^<td class=\\\"[^\\\"]*\\\"|<td |;" if $sectiontab ne "no";
+ return @OUT;
+}
+
+sub head_sed_multisection # $filename $section
+{
+ # sitefile navigation bar is split into sections
+ my ($U,$V,$Z) = @_;
+ my $FF=&sed_slash_key($U);
+ my $SECTION=&sed_slash_key($V);
+ my $SECTS="<!--sect[$NN$AZ]-->" ;
+ my $SECTN="<!--sect[$NN]-->"; # lines with hrefs
+ my @OUT = ();
+ # grep all pages with a =sect= relation to current $SECTION and
+ # build foreach an sed line "s|$SECTS\(<a href=$F>\)|<!--sectX-->\1|"
+ # after that all the (still) numeric SECTNs are deactivated / killed.
+ for my $section ($SECTION, $headsection, $tailsection) {
+ next if $section eq "no";
+ for (grep {/^=sect=[^ ]* $section/} @MK_INFO) {
+ my $x = $_;
+ $x =~ s, .*,\\\"\)|<!--sectX-->\$1|,;
+ $x =~ s,^=sect=,s|^$SECTS\(.*<a href=\\\",;
+ push @OUT, $x.";";
+ }
+ }
+ push @OUT, "s|^$SECTN\[^ \]*(<a href=[^<>]*>).*|<!-- \$1 -->|;";
+ push @OUT, "/^$SECTS.*<a href=\\\"$FF\\\">/ and s|</a>|</a></b>|;";
+ push @OUT, "/^$SECTS.*<a href=\\\"$FF\\\">/ and s|<a href=|<b><a href=|;";
+ push @OUT, "/ href=\\\"$SECTION\\\"/ "
+ ."and s|^<td class=\\\"[^\\\"]*\\\"|<td |;" if $sectiontab ne "no";
+ return @OUT;
+}
+
+sub make_sitefile # "$F"
+{
+ $SOURCEFILE=&html_sourcefile($F);
+ if ($SOURCEFILE ne $F) {
+ if (-f $SOURCEFILE) {
+ # remember that in this case "${SITEFILE}l" = "$F" = "${SOURCEFILE}l"
+ @MK_VARS = &info2vars_sed(); # have <!--title--> vars substituted
+ @MK_META = &info2meta_sed(); # add <meta name="DC.title"> values
+ if ( $simplevars eq "warn") {
+ @MK_TEST = &info2test_sed(); # check <!--title--> vars old-style
+## $SED_LONGSCRIPT ./$MK_TEST $SOURCEFILE | tee -a ./$MK_OLDS ; fi
+ }
+ my @F_HEAD = (); my @F_FOOT = ();
+ push @F_HEAD, @MK_PUTS;
+ push @F_HEAD, &head_sed_sitemap ($F, &info_get_entry_section());
+ push @F_HEAD, "/<head>/ and $sed_add join(\"\\n\", \@MK_META);";
+ push @F_HEAD, @MK_VARS; push @F_HEAD, @MK_TAGS;
+ push @F_HEAD, "/<\\/body>/ and next;"; #cut lastline
+ if ( $sitemaplayout eq "multi") {
+ push @F_FOOT, &make_multisitemap(); # here we use ~foot~ to
+ } else {
+ push @F_FOOT, &make_listsitemap(); # hold the main text
+ }
+
+ my $html = ""; #
+ $html .= &eval_MK_FILE($SITEFILE, @F_HEAD);
+ $html .= join("", @F_FOOT);
+ for (source($SITEFILE)) {
+ /<\/body>/ or next;
+ $html .= &eval_MK_LIST($_, @MK_VARS);
+ }
+ open F, ">$F"; print F $html; close F;
+ print "'$SOURCEFILE': ",ls_s($SOURCEFILE)," >-> ",ls_s($F),"$n";
+ savesource("$F.~head~", \@F_HEAD);
+ savesource("$F.~foot~", \@F_FOOT);
+} else {
+ print "'$SOURCEFILE': does not exist$n";
+} }
+}
+
+sub make_htmlfile # "$F"
+{
+ $SOURCEFILE=&html_sourcefile($F); # 2.PASS
+ if ("$SOURCEFILE" ne "$F") {
+ if (-f "$SOURCEFILE") {
+ if (grep {/<meta name="formatter"/} source($SOURCEFILE)) {
+ print "$SOURCEFILE: SKIP, this sourcefile looks like a formatted file$n";
+ print "$SOURCEFILE: (may be a sourcefile in place of a targetfile?)$n";
+ return; }
+ @MK_VARS = &info2vars_sed(); # have <!--title--> vars substituted
+ @MK_META = &info2meta_sed(); # add <meta name="DC.title"> values
+ if ( $simplevars eq "warn") {
+ @MK_TEST = &info2test_sed(); # check <!--title--> vars old-style
+## $SED_LONGSCRIPT ./$MK_TEST $SOURCEFILE | tee -a ./$MK_OLDS ; fi
+ }
+ my @F_HEAD = (); my @F_BODY = (); my $F_FOOT = "";
+ push @F_HEAD, @MK_PUTS;
+ if ( $sectionlayout eq "multi") {
+ push @F_HEAD, &head_sed_multisection ($F, &info_get_entry_section());
+ } else {
+ push @F_HEAD, &head_sed_listsection ($F, &info_get_entry_section());
+ }
+ push @F_HEAD, @MK_VARS; push @F_HEAD, @MK_TAGS; #tag and vars
+ push @F_HEAD, "/<\\/body>/ and next;"; #cut lastline
+ push @F_HEAD, "/<head>/ and $sed_add join(\"\\n\",\@MK_META);"; #add metatags
+ push @F_BODY, "/<title>/ and next;"; #not that line
+ push @F_BODY, @MK_VARS; push @F_BODY, @MK_TAGS; #tag and vars
+ push @F_BODY, &bodymaker_for_sectioninfo(); #if sectioninfo
+ push @F_BODY, &info2body_sed(); #cut early
+ push @F_HEAD, &info2head_sed();
+ push @F_HEAD, @{$FAST{$F}};
+ if ($emailfooter ne "no") {
+ $F_FOOT = &body_for_emailfooter();
+ }
+ my $html = "";
+ $html .= eval_MK_FILE($SITEFILE, @F_HEAD);
+ $html .= eval_MK_FILE($SOURCEFILE, @F_BODY);
+ $html .= $F_FOOT;
+ for (source($SITEFILE)) {
+ /<\/body>/ or next;
+ $_ = &eval_MK_LIST($_, @MK_VARS);
+ $html .= $_;
+ }
+ savelist(\@{$INFO{$F}});
+ open F, ">$F" or die "could not write $F: $!"; print F $html; close F;
+ print "'$SOURCEFILE': ",&ls_s($SOURCEFILE)," -> ",&ls_s($F),"$n";
+ savesource("$F.~head~", \@F_HEAD);
+ savesource("$F.~body~", \@F_BODY);
+ } else {
+ print "'$SOURCEFILE': does not exist$n";
+ }} else {
+ print "<$F> - skipped$n";
+ }
+}
+
+my $PRINTSITEFILE;
+sub make_printerfriendly # "$F"
+{ # PRINTER
+ my $printsitefile="0"; # FRIENDLY
+ my @F_FAST = (); my $BODY_TXT; my $BODY_SED;
+ my $P=&html_printerfile ($F);
+ my @P_HEAD = (); my @P_BODY = ();
+ if ("$F" =~ /^(${SITEFILE}|${SITEFILE}l)$/) {
+ @F_FAST = &make_fast ("$F");
+ $printsitefile=">=>" ; $BODY_TXT="$F.~foot~" ;
+ } elsif ("$F" =~ /^(.*[.]html)$/) {
+ $printsitefile="=>" ; $BODY_TXT="$SOURCEFILE";
+ }
+ if (grep {/<meta name="formatter"/} source($BODY_TXT)) { return; }
+ if ($printsitefile ne "0" and -f $SOURCEFILE) {
+ @MK_FAST = &make_printerfile_fast (\@FILELIST);
+ push @P_HEAD, @MK_VARS; push @P_HEAD, @MK_TAGS; push @P_HEAD, @MK_FAST;
+ @MK_METT = map { my $x = $_; $x =~
+ /DC.relation.isFormatOf/ and $x =~ s|content=\"[^\"]*\"|content=\"$F\"| ;
+ $x } @MK_META;
+ push @P_HEAD, "/<head>/ and $sed_add join(\"\\n\", \@MK_METT);";
+ push @P_HEAD, "/<\\/body>/ and next;";
+ push @P_HEAD, &select_in_printsitefile ("$F");
+ my $_ext_=&print_extension($printerfriendly);
+ push @P_HEAD, map { my $x=$_; $x =~ s/[.]html\"|/$_ext_$&/g; $x} @F_FAST;
+# my $line_=&sed_slash_key($printsitefile_img_2);
+ push @P_HEAD, "/\\|\\|topics:/"
+ ." and s| href=\\\"\\#\\.\\\"| href=\\\"$F\\\"|;";
+ push @P_HEAD, "/\\|\\|\\|pages:/"
+ ." and s| href=\\\"\\#\\.\\\"| href=\\\"$F\\\"|;";
+ push @P_HEAD, @F_FAST;
+ push @P_BODY, @MK_VARS; push @P_BODY, @MK_TAGS; push @P_BODY, @MK_FAST;
+ push @P_BODY, map { my $x=$_; $x =~ s/[.]html\"|/$_ext_$&/g; $x} @F_FAST;
+ push @P_BODY, @F_FAST;
+ my $html = "";
+ $html .= eval_MK_FILE($PRINTSITEFILE, @P_HEAD);
+ $html .= eval_MK_FILE($BODY_TXT, @P_BODY);
+ for (source($PRINTSITEFILE)) {
+ /<\/body>/ or next;
+ $_ = &eval_MK_LIST($_, @MK_VARS);
+ $html .= $_;
+ }
+ open P, ">$P" or die "could not write $P: $!"; print P $html; close P;
+ print "'$SOURCEFILE': ",ls_s($SOURCEFILE)," $printsitefile ",ls_s($P),"$n";
+ }
+}
+
+
+# ========================================================================
+# ========================================================================
+# ========================================================================
+# ========================================================================
+# #### 0. INIT
+$F=$SITEFILE;
+&make_sitemap_init();
+&make_sitemap_list();
+&make_sitemap_sect();
+&make_sitemap_page();
+savelist(\@MK_INFO);
+
+@FILELIST=&echo_site_filelist();
+if ($o{filelist} or $o{list} eq "file" or $o{list} eq "files") {
+ for (@FILELIST) { print $_,"$n"; } exit; # --filelist
+}
+if ($o{files}) { @FILELIST=split(/ /, $o{files}); } # --files
+if ($#FILELIST < 0) { print STDERR "nothing to do$n"; }
+if ($#FILELIST == 0 and
+ $FILELIST[0] eq $SITEFILE) { print STDERR "only '$SITEFILE'!?$n"; }
+
+for (@FILELIST) { #### 1. PASS
+ $F = $_;
+ if (/^(name:.*)$/) {
+ &scan_namespec ("$F");
+ } elsif (/^(http:.*|.*:\/\/.*)$/) {
+ &scan_httpspec ("$F");
+ } elsif (/^(${SITEFILE}|${SITEFILE}l)$/) {
+ &scan_sitefile ("$F") ;; # ........... SCAN SITE
+ } elsif (/^(\.\.\/.*)$/) {
+ print "!! -> '$F' (skipping topdir build)$n";
+# */*.html)
+# make_fast # try for later subdir build
+# echo "!! -> '$F' (skipping subdir build)"
+# ;;
+# */*/*/|*/*/|*/|*/index.htm|*/index.html)
+# echo "!! -> '$F' (skipping subdir index.html)"
+# ;;
+ } elsif (/^(.*\.html)$/) {
+ &scan_htmlfile ("$F") ;; # ........... SCAN HTML
+ } elsif (/^(.*\/)$/) {
+ print "'$F' : directory - skipped$n";
+ &site_map_list_title ("$F", &sed_slash_key($F));
+ &site_map_long_title ("$F", "(directory)");
+ } else {
+ print "?? -> '$F'$n";
+ }
+}
+
+if ($printerfriendly) { # .......... PRINT VERSION
+ my $_ext_=esc(&print_extension($printerfriendly));
+ $PRINTSITEFILE=$SITEFILE; $PRINTSITEFILE =~ s/(\.\w*)$/$_ext_$1/;
+ $F=$PRINTSITEFILE;
+ my @TEXT = &make_printsitefile();
+ print "NOTE: going to create printer-friendly sitefile '$PRINTSITEFILE'"
+ ." $F._$i$n";
+ savelist(\@TEXT);
+ my @LINES = map { chomp; $_."$n" } @TEXT;
+ savesource($PRINTSITEFILE, \@LINES);
+ if (1) {
+ if (open PRINTSITEFILE, ">$PRINTSITEFILE") {
+ print PRINTSITEFILE join("", @LINES); close PRINTSITEFILE;
+ }
+ }
+}
+
+if ($simplevars eq " ") {
+ @MK_OLDS = ();
+}
+
+for (@FILELIST) { #### 2. PASS
+ $F = $_;
+ if (/^(name:.*)$/) {
+ &skip_namespec ("$F") ;;
+ } elsif (/^(http:.*|.*:\/\/.*)$/) {
+ &skip_httpspec ("$F") ;;
+ } elsif (/^(${SITEFILE}|${SITEFILE}l)$/) {
+ &make_sitefile ("$F") ;; # ........ SITE FILE
+ &make_printerfriendly ("$F") if ($printerfriendly);
+ } elsif (/^(\.\.\/.*)$/) {
+ print "!! -> '$F' (skipping topdir build)$n";
+# */*.html)
+# echo "!! -> '$F' (skipping subdir build)"
+# ;;
+# */*/*/|*/*/|*/|*/index.htm|*/index.html)
+# echo "!! -> '$F' (skipping subdir index.html)"
+# ;;
+ } elsif (/^(.*\.html)$/) {
+ &make_htmlfile ("$F") ;; # .................. HTML FILES
+ &make_printerfriendly ("$F") if ($printerfriendly);
+ } elsif (/^(.*\/)$/) {
+ print "'$F' : directory - skipped$n";
+ } else {
+ print "?? -> '$F'$n";
+ }
+# .............. debug ....................
+## if test -d DEBUG && test -f "./$F" ; then
+## cp ./$F.$INFO DEBUG/$F.info.TMP
+## for P in tags vars meta page date list html sect info ; do
+## test -f ./$MK.$P.tmp && cp ./$MK.$P.tmp DEBUG/$F.$P.tmp
+## test -f ./$MK.$P.TMP && cp ./$MK.$P.TMP DEBUG/$F.$P.TMP
+## done
+## fi
+} # done
+
+if ( $simplevars eq "warn") {
+ my $oldvars = $#MK_OLDS; $oldvars ++;
+ if (not $oldvars) {
+print "HINT: you have no simplevars in your htm sources, so you may want to$n";
+print "hint: set the magic <!--mksite:nosimplevars--> in your $SITEFILE$n";
+print "hint: which makes execution _faster_ actually in the 2. pass$n";
+print "note: simplevars expansion was the oldstyle way of variable expansion$n";
+} else {
+print "HINT: there were $oldvars simplevars found in your htm sources.$n";
+print "hint: This style of variable expansion will be disabled in the near$n";
+print "hint: future. If you do not want change then add the $SITEFILE magic$n";
+print "hint: <!--mksite:simplevars--> somewhere to suppress this warning$n";
+print "note: simplevars expansion will be an explicit option in the future.$n";
+print "note: errornous simplevar detection can be suppressed with a magic$n";
+print "note: hint of <!--mksite:nosimplevars--> in the $SITEFILE for now.$n";
+} }
+
+## rm ./$MK.*.tmp
+exit 0
diff --git a/Build/source/libs/zziplib/docs/mksite.sh b/Build/source/libs/zziplib/docs/mksite.sh
new file mode 100644
index 00000000000..22a06431060
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/mksite.sh
@@ -0,0 +1,1789 @@
+#! /bin/sh
+# this is the sh/sed variant of the mksite script. It is largely
+# derived from snippets that I was using to finish doc pages for
+# website publishing. For the mksite project the functionaliy has
+# been expanded of course. Still this one does only use simple unix
+# commands like sed, date, and test. And it still works. :-)=)
+# http://zziplib.sf.net/mksite/
+# THE MKSITE.SH (ZLIB/LIBPNG) LICENSE
+# Copyright (c) 2004 Guido Draheim <guidod@gmx.de>
+# This software is provided 'as-is', without any express or implied warranty
+# In no event will the authors be held liable for any damages arising
+# from the use of this software.
+# Permission is granted to anyone to use this software for any purpose,
+# including commercial applications, and to alter it and redistribute it
+# freely, subject to the following restrictions:
+# 1. The origin of this software must not be misrepresented; you must not
+# claim that you wrote the original software. If you use this software
+# in a product, an acknowledgment in the product documentation would be
+# appreciated but is not required.
+# 2. Altered source versions must be plainly marked as such, and must not
+# be misrepresented as being the original software.
+# 3. This notice may not be removed or altered from any source distribution.
+# $Id: mksite.sh,v 1.4 2005/05/14 15:08:23 guidod Exp $
+
+# Zsh is not Bourne compatible without the following: (seen in autobook)
+if test -n "$ZSH_VERSION"; then
+ emulate sh
+ NULLCMD=:
+fi
+
+# initialize some defaults
+test ".$SITEFILE" = "." && test -f "site.htm" && SITEFILE="site.htm"
+test ".$SITEFILE" = "." && test -f "site.html" && SITEFILE="site.html"
+test ".$SITEFILE" = "." && SITEFILE="site.htm"
+MK="-mksite" # note the "-" at the start
+SED="sed"
+CAT="cat" # "sed -e n" would be okay too
+GREP="grep"
+DATE_NOW="date" # should be available on all posix systems
+DATE_R="date -r" # gnu date has it / solaris date not
+STAT_R="stat" # gnu linux
+LS_L="ls -l" # linux uses one less char than solaris
+
+INFO="~~" # extension for meta data files
+HEAD="~head~" # extension for head sed script
+BODY="~body~" # extension for body sed script
+FOOT="~foot~" # append to body text (non sed)
+FAST="~move~" # extension for printer friendly sed
+
+NULL="/dev/null" # to divert stdout/stderr
+CATNULL="$CAT $NULL" # to create 0-byte files
+SED_LONGSCRIPT="$SED -f"
+
+LOWER="abcdefghijklmnopqrstuvwxyz"
+UPPER="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+az="$LOWER" # some old sed tools can not
+AZ="$UPPER" # use char-ranges in the
+NN="0123456789" # match expressions so that
+AA="_$NN$AZ$az" # we use their unrolled
+AX="$AA.+-" # definition here
+if $SED -V 2>$NULL | $GREP "GNU sed" >$NULL ; then
+az="a-z" # but if we have GNU sed
+AZ="A-Z" # then we assume there are
+NN="0-9" # char-ranges available
+AA="_$NN$AZ$az" # that makes the resulting
+AX="$AA.+-" # script more readable
+elif uname -s | $GREP HP-UX >$NULL ; then
+SED_LONGSCRIPT="sed_longscript" # due to 100 sed lines limit
+fi
+
+LANG="C" ; LANGUAGE="C" ; LC_COLLATE="C" # these are needed for proper
+export LANG LANGUAGE LC_COLLATE # lowercasing as some collate
+ # treat A-Z to include a-z
+
+# ==========================================================================
+# reading options from the command line GETOPT
+opt_variables="files"
+opt_fileseparator="?"
+opt_files=""
+opt_main_file=""
+opt_formatter="$0"
+opt=""
+for arg in "$@" # this variant should allow to embed spaces in $arg
+do if test ".$opt" != "." ; then
+ eval "export opt_$opt='$arg'"
+ opt=""
+ else
+ case "$arg" in
+ -*=*)
+ opt=`echo "$arg" | $SED -e "s/-*\\([$AA][$AA-]*\\).*/\\1/" -e y/-/_/`
+ if test ".$opt" = "." ; then
+ echo "ERROR: invalid option $arg" >&2
+ else
+ arg=`echo "$arg" | $SED -e "s/^[^=]*=//"`
+ eval "export opt_$opt='$arg'"
+ opt_variables="$opt_variables $opt"
+ fi
+ opt="" ;;
+ -*-*)
+ opt=`echo "$arg" | $SED -e "s/-*\\([$AA][$AA-]*\\).*/\\1/" -e y/-/_/`
+ if test ".$opt" = "." ; then
+ echo "ERROR: invalid option $arg" >&2
+ opt=""
+ else :
+ # keep the option for next round
+ fi ;;
+ -*)
+ opt=`echo "$arg" | $SED -e "s/^-*\\([$AA][$AA-]*\\).*/\\1/" -e y/-/_/`
+ if test ".$opt" = "." ; then
+ echo "ERROR: invalid option $arg" >&2
+ else
+ arg=`echo "$arg" | $SED -e "s/^[^=]*=//"`
+ eval "export opt_$opt=' '"
+ fi
+ opt="" ;;
+ *) if test ".$opt_main_file" = "." ; then opt_main_file="$arg" ; else
+ test ".$opt_files" != "." && opt_files="$opt_files$opt_fileseparator"
+ opt_files="$opt_files$arg" ; fi
+ opt="" ;;
+ esac
+ fi
+done ; if test ".$opt" != "." ; then
+ eval "export opt_$opt='$arg'"
+ opt=""
+fi
+### env | grep ^opt
+
+test ".$opt_main_file" != "." && test -f "$opt_main_file" && \
+SITEFILE="$opt_main_file"
+test ".$opt_site_file" != "." && test -f "$opt_site_file" && \
+SITEFILE="$opt_site_file"
+
+if test ".$opt_help" != "." ; then
+ F="$SITEFILE"
+ echo "$0 [sitefile]";
+ echo " default sitefile = $F";
+ echo "options:";
+ echo " --filelist : show list of target files as ectracted from $F"
+ echo " --src-dir xx : if source files are not where mksite is executed"
+ echo " --tmp-dir xx : use temp instead of local directory"
+ echo " --tmp : use automatic temp directory in ${TEMP-/tmp}/mksite.*"
+ exit;
+ echo " internal:"
+ echo "--fileseparator=x : for building the internal filelist (default '?')"
+ echo "--files xx : for list of additional files to be processed"
+ echo "--main-file xx : for the main sitefile to take file list from"
+fi
+
+if test ".$SITEFILE" = "." ; then
+ echo "error: no SITEFILE found (default would be 'site.htm')"
+ exit 1
+else
+ echo "NOTE: sitefile: `ls -s $SITEFILE`"
+fi
+
+if "${SHELL-/bin/sh}" -c 'foo () { exit 0; }; foo' 2>$NULL ; then : ; else
+echo "!! sorry, this shell '$SHELL' does not support shell functions"; exit 1
+fi
+
+tmp="." ; if test ".$opt_tmp_dir" != "." ; then tmp="$opt_tmp_dir" ; fi
+if test ".$opt_tmp_dir" = "." && test ".$opt_tmp" != "." ; then
+tmp="${TEMP-/tmp}/mksite.$$" ; fi
+
+# we use external files to store mappings - kind of relational tables
+MK_TAGS="$tmp/$MK.tags.tmp"
+MK_VARS="$tmp/$MK.vars.tmp"
+MK_META="$tmp/$MK.meta.tmp"
+MK_METT="$tmp/$MK.mett.tmp"
+MK_TEST="$tmp/$MK.test.tmp"
+MK_FAST="$tmp/$MK.fast.tmp"
+MK_GETS="$tmp/$MK.gets.tmp"
+MK_PUTS="$tmp/$MK.puts.tmp"
+MK_OLDS="$tmp/$MK.olds.tmp"
+MK_SITE="$tmp/$MK.site.tmp"
+MK_SECT1="$tmp/$MK.sect1.tmp"
+MK_SECT2="$tmp/$MK.sect2.tmp"
+MK_SECT3="$tmp/$MK.sect3.tmp"
+MK_STYLE="$tmp/$MK.style.tmp"
+MK_INFO="$tmp/$MK.$INFO"
+
+# ========================================================================
+# ========================================================================
+# ========================================================================
+# MAGIC VARS
+# IN $SITEFILE
+printerfriendly=""
+sectionlayout="list"
+sitemaplayout="list"
+simplevars="warn" # <!--varname-->default
+attribvars=" " # <x ref="${varname:=default}">
+updatevars=" " # <!--$varname:=-->default
+expandvars=" " # <!--$varname-->
+commentvars=" " # $updatevars && $expandsvars && $simplevars
+sectiontab=" " # highlight ^<td class=...>...href="$section"
+currenttab=" " # highlight ^<br>..<a href="$topic">
+headsection="no"
+tailsection="no"
+sectioninfo="no" # using <h2> title <h2> = info text
+emailfooter="no"
+
+if $GREP "<!--multi-->" $SITEFILE >$NULL ; then
+echo \
+"WARNING: do not use <!--multi-->, change to <!--mksite:multi--> " "$SITEFILE"
+echo \
+"warning: or <!--mksite:multisectionlayout--> <!--mksite:multisitemaplayout-->"
+sectionlayout="multi"
+sitemaplayout="multi"
+fi
+if $GREP "<!--mksite:multi-->" $SITEFILE >$NULL ; then
+sectionlayout="multi"
+sitemaplayout="multi"
+fi
+if $GREP "<!--mksite:multilayout-->" $SITEFILE >$NULL ; then
+sectionlayout="multi"
+sitemaplayout="multi"
+fi
+
+mksite_magic_option ()
+{
+ # $1 is word/option to check for
+ INP="$2" ; test ".$INP" = "." && INP="$SITEFILE"
+ $SED \
+ -e "s/\\(<!--mksite:\\)\\($1\\)-->/\\1\\2: -->/g" \
+ -e "s/\\(<!--mksite:\\)\\([$AA][$AA]*\\)\\($1\\)-->/\\1\\3:\\2-->/g" \
+ -e "/<!--mksite:$1:/!d" \
+ -e "s/.*<!--mksite:$1:\\([^<>]*\\)-->.*/\\1/" \
+ -e "s/.*<!--mksite:$1:\\([^-]*\\)-->.*/\\1/" \
+ -e "/<!--mksite:$1:/d" -e q $INP # $++
+}
+
+x=`mksite_magic_option sectionlayout` ; case "$x" in
+ "list"|"multi") sectionlayout="$x" ;; esac
+x=`mksite_magic_option sitemaplayout` ; case "$x" in
+ "list"|"multi") sitemaplayout="$x" ;; esac
+x=`mksite_magic_option simplevars` ; case "$x" in
+ " "|"no"|"warn") simplevars="$x" ;; esac
+x=`mksite_magic_option attribvars` ; case "$x" in
+ " "|"no"|"warn") attribvars="$x" ;; esac
+x=`mksite_magic_option updatevars` ; case "$x" in
+ " "|"no"|"warn") updatevars="$x" ;; esac
+x=`mksite_magic_option expandvars` ; case "$x" in
+ " "|"no"|"warn") expandvars="$x" ;; esac
+x=`mksite_magic_option commentvars` ; case "$x" in
+ " "|"no"|"warn") commentvars="$x" ;; esac
+x=`mksite_magic_option printerfriendly` ; case "$x" in
+ " "|".*"|"-*") printerfriendly="$x" ;; esac
+x=`mksite_magic_option sectiontab` ; case "$x" in
+ " "|"no"|"warn") sectiontab="$x" ;; esac
+x=`mksite_magic_option currenttab` ; case "$x" in
+ " "|"no"|"warn") currenttab="$x" ;; esac
+x=`mksite_magic_option sectioninfo` ; case "$x" in
+ " "|"no"|"[=:-]") sectioninfo="$x" ;; esac
+x=`mksite_magic_option emailfooter`
+ test ".$x" != "." && emailfooter="$x"
+
+test ".$opt_print" != "." && printerfriendly="$opt_print"
+test ".$commentvars" = ".no" && updatevars="no" # duplicated into
+test ".$commentvars" = ".no" && expandvars="no" # info2vars_sed ()
+test ".$commentvars" = ".no" && simplevars="no" # function above
+
+test -d DEBUG && \
+echo "NOTE: '$sectionlayout'sectionlayout '$sitemaplayout'sitemaplayout"
+test -d DEBUG && \
+echo "NOTE: '$simplevars'simplevars '$printerfriendly'printerfriendly"
+test -d DEBUG && \
+echo "NOTE: '$attribvars'attribvars '$updatevars'updatevars"
+test -d DEBUG && \
+echo "NOTE: '$expandvars'expandvars '$commentvars'commentvars "
+test -d DEBUG && \
+echo "NOTE: '$currenttab'currenttab '$sectiontab'sectiontab"
+test -d DEBUG && \
+echo "NOTE: '$headsection'headsection '$tailsection'tailsection"
+
+if ($STAT_R "$SITEFILE" >$NULL) 2>$NULL ; then : ; else STAT_R=":" ; fi
+# ==========================================================================
+# init a few global variables
+# 0. INIT
+
+mkpathdir () {
+ if test -n "$1" && test ! -d "$1" ; then
+ echo "!! mkdir '$1'" ; mkdir "$1"
+ test ! -d "$1" || mkdir -p "$1"
+ fi
+}
+
+mkpathfile () {
+ dirname=`echo "$1" | $SED -e "s:/[^/][^/]*\$::"`
+ if test ".$1" != ".$dirname" && test ".$dirname" != "." ;
+ then mkpathdir "$dirname"; fi
+}
+
+mknewfile () {
+ mkpathfile "$1"
+ $CATNULL > "$1"
+}
+
+tmp_dir_was_created="no"
+if test ! -d "$tmp" ; then mkpathdir "$tmp" ; tmp_dir_was_created="yes" ; fi
+
+# $MK_TAGS - originally, we would use a lambda execution on each
+# uppercased html tag to replace <P> with <p class="P">. Here we just
+# walk over all the known html tags and make an sed script that does
+# the very same conversion. There would be a chance to convert a single
+# tag via "h;y;x" or something we do want to convert all the tags on
+# a single line of course.
+mknewfile "$MK_TAGS"
+for P in P H1 H2 H3 H4 H5 H6 DL DD DT UL OL LI PRE CODE TABLE TR TD TH \
+ B U I S Q EM STRONG STRIKE CITE BIG SMALL SUP SUB TT THEAD TBODY \
+ CENTER HR BR NOBR WBR SPAN DIV IMG ADRESS BLOCKQUOTE
+do M=`echo "$P" | $SED -e "y/$UPPER/$LOWER/"`
+ echo "s|<$P>|<$M class=\"$P\">|g" >> "$MK_TAGS"
+ echo "s|<$P |<$M class=\"$P\" |g" >> "$MK_TAGS"
+ echo "s|</$P>|</$M>|g" >> "$MK_TAGS"
+done
+ echo "s|<>|\\&nbsp\\;|g" >> "$MK_TAGS"
+ echo "s|<->|<WBR />\\;|g" >> "$MK_TAGS"
+# also make sure that some non-html entries are cleaned away that
+# we are generally using to inject meta information. We want to see
+# that meta ino in the *.htm browser view during editing but they
+# shall not get present in the final html page for publishing.
+DC_VARS="contributor date source language coverage identifier"
+DC_VARS="$DC_VARS rights relation creator subject description"
+DC_VARS="$DC_VARS publisher DCMIType"
+_EQUIVS="refresh expires content-type cache-control"
+_EQUIVS="$_EQUIVS redirect charset" # mapped to refresh / content-type
+_EQUIVS="$_EQUIVS content-language content-script-type content-style-type"
+for P in $DC_VARS $_EQUIVS ; do # dublin core embedded
+ echo "s|<$P>[^<>]*</$P>||g" >> "$MK_TAGS"
+done
+ echo "s|<!--sect[$AZ$NN]-->||g" >> "$MK_TAGS"
+ echo "s|<!--[$AX]*[?]-->||g" >> "$MK_TAGS"
+ echo "s|<!--\\\$[$AX]*[?]:-->||g" >> "$MK_TAGS"
+ echo "s|<!--\\\$[$AX]*:[?=]-->||g" >> "$MK_TAGS"
+ echo "s|\\(<[^<>]*\\)\\\${[$AX]*:[?=]\\([^<{}>]*\\)}\\([^<>]*>\\)|\\1\\2\\3|g" >>$MK_TAGS
+
+# see overview at www.metatab.de - http-equivs are
+# <refresh>5; url=target</reresh> or <redirect>target</redirect>
+# <content-type>text/html; charset=koi8-r</content-type> iso-8859-1/UTF-8
+# <content-language>de</content-language> <charset>UTF-8</charset>
+# <content-script-type>text/javascript</content-script-type> /jscript/vbscript
+# <content-style-type>text/css</content-style-type>
+# <cache-control>no-cache</cache-control>
+
+trimm ()
+{
+ echo "$1" | $SED -e "s:^ *::" -e "s: *\$::";
+}
+trimmm ()
+{
+ echo "$1" | $SED -e "s:^ *::" -e "s: *\$::" -e "s:[ ][ ]*: :g";
+}
+
+timezone ()
+{
+ # +%z is an extension while +%Z is supposed to be posix
+ _timezone=`$DATE_NOW +%z`
+ case "$_timezone" in
+ *+*) echo "$_timezone" ;;
+ *-*) echo "$_timezone" ;;
+ *) $DATE_NOW +%Z
+ esac
+}
+timetoday ()
+{
+ $DATE_NOW +%Y-%m-%d
+}
+timetodays ()
+{
+ $DATE_NOW +%Y-%m%d
+}
+
+# ======================================================================
+# FUNCS
+
+sed_longscript ()
+{
+ # hpux sed has a limit of 100 entries per sed script !
+ $SED -e "100q" "$1" > "$1~1~"
+ $SED -e "1,100d" -e "200q" "$1" > "$1~2~"
+ $SED -e "1,200d" -e "300q" "$1" > "$1~3~"
+ $SED -e "1,300d" -e "400q" "$1" > "$1~4~"
+ $SED -e "1,400d" -e "500q" "$1" > "$1~5~"
+ $SED -e "1,500d" -e "600q" "$1" > "$1~6~"
+ $SED -e "1,600d" -e "700q" "$1" > "$1~7~"
+ $SED -e "1,700d" -e "800q" "$1" > "$1~8~"
+ $SED -e "1,800d" -e "900q" "$1" > "$1~9~"
+ $SED -f "$1~1~" -f "$1~2~" -f "$1~3~" -f "$1~4~" -f "$1~5~" \
+ -f "$1~6~" -f "$1~7~" -f "$1~8~" -f "$1~9~" "$2"
+}
+
+sed_slash_key () # helper to escape chars special in /anchor/ regex
+{ # currently escaping "/" "[" "]" "."
+ echo "$1" | $SED -e "s|[./[-]|\\\\&|g" -e "s|\\]|\\\\&|g"
+}
+sed_piped_key () # helper to escape chars special in s|anchor|| regex
+{ # currently escaping "|" "[" "]" "."
+ echo "$1" | $SED -e "s/[.|[-]/\\\\&/g" -e "s/\\]/\\\\&/g"
+}
+
+back_path () # helper to get the series of "../" for a given path
+{
+ echo "$1" | $SED -e "/\\//!d" -e "s|/[^/]*\$|/|" -e "s|[^/]*/|../|g"
+}
+
+dir_name ()
+{
+ echo "$1" | $SED -e "s:/[^/][^/]*\$::"
+}
+
+info2test_sed () # cut out all old-style <!--vars--> usages
+{
+ INP="$1" ; test ".$INP" = "." && INP="$tmp/$F.$INFO"
+ V8=" *\\([^ ][^ ]*\\) \\(.*\\)"
+ V9=" *DC[.]\\([^ ][^ ]*\\) \\(.*\\)"
+ q="\\\$"
+ _x_="WARNING: assumed simplevar <!--\\\\1--> changed to <!--$q\\\\1:=-->"
+ _y_="WARNING: assumed simplevar <!--\\\\1--> changed to <!--$q\\\\1:?-->"
+ _X_="WARNING: assumed tailvar <!--$q\\\\1:--> changed to <!--$q\\\\1:=-->"
+ _Y_="WARNING: assumed tailvar <!--$q\\\\1:--> changed to <!--$q\\\\1:?-->"
+ echo "s/^/ /" # $++
+ $SED -e "/^=....=formatter /d" \
+ -e "/=text=/s%=text=$V9%s|.*<!--\\\\(\\1\\\\)-->.*|$_x_|%" \
+ -e "/=Text=/s%=Text=$V9%s|.*<!--\\\\(\\1\\\\)-->.*|$_x_|%" \
+ -e "/=name=/s%=name=$V9%s|.*<!--\\\\(\\1\\\\)[?]-->.*|$_y_|%" \
+ -e "/=Name=/s%=Name=$V9%s|.*<!--\\\\(\\1\\\\)[?]-->.*|$_y_|%" \
+ -e "/=text=/s%=text=$V8%s|.*<!--\\\\(\\1\\\\)-->.*|$_x_|%" \
+ -e "/=Text=/s%=Text=$V8%s|.*<!--\\\\(\\1\\\\)-->.*|$_x_|%" \
+ -e "/=name=/s%=name=$V8%s|.*<!--\\\\(\\1\\\\)[?]-->.*|$_y_|%" \
+ -e "/=Name=/s%=Name=$V8%s|.*<!--\\\\(\\1\\\\)[?]-->.*|$_y_|%" \
+ -e "/^=/d" -e "s|&|\\\\&|g" $INP # $++
+ $SED -e "/^=....=formatter /d" \
+ -e "/=text=/s%=text=$V9%s|.*<!--$q\\\\(\\1\\\\):-->.*|$_X_|%" \
+ -e "/=Text=/s%=Text=$V9%s|.*<!--$q\\\\(\\1\\\\):-->.*|$_X_|%" \
+ -e "/=name=/s%=name=$V9%s|.*<!--$q\\\\(\\1\\\\)[?]:-->.*|$_Y_|%" \
+ -e "/=Name=/s%=Name=$V9%s|.*<!--$q\\\\(\\1\\\\)[?]:-->.*|$_Y_|%" \
+ -e "/=text=/s%=text=$V8%s|.*<!--$q\\\\(\\1\\\\):-->.*|$_X_|%" \
+ -e "/=Text=/s%=Text=$V8%s|.*<!--$q\\\\(\\1\\\\):-->.*|$_X_|%" \
+ -e "/=name=/s%=name=$V8%s|.*<!--$q\\\\(\\1\\\\)[?]:-->.*|$_Y_|%" \
+ -e "/=Name=/s%=Name=$V8%s|.*<!--$q\\\\(\\1\\\\)[?]:-->.*|$_Y_|%" \
+ -e "/^=/d" -e "s|&|\\\\&|g" $INP # $++
+ echo "/^WARNING:/!d" # $++
+}
+
+info2vars_sed () # generate <!--$vars--> substition sed addon script
+{
+ INP="$1" ; test ".$INP" = "." && INP="$tmp/$F.$INFO"
+ V8=" *\\([^ ][^ ]*\\) \\(.*\\)"
+ V9=" *DC[.]\\([^ ][^ ]*\\) \\(.*\\)"
+ N8=" *\\([^ ][^ ]*\\) \\([$NN].*\\)"
+ N9=" *DC[.]\\([^ ][^ ]*\\) \\([$NN].*\\)"
+ V0="\\\\([<]*\\\\)\\\\\\\$"
+ V1="\\\\([^<>]*\\\\)\\\\\\\$"
+ V2="\\\\([^{<>}]*\\\\)"
+ V3="\\\\([^<>]*\\\\)"
+ SS="<""<>"">" # spacer so value="2004" does not make for s|\(...\)|\12004|
+ test ".$commentvars" = ".no" && updatevars="no" # duplicated from
+ test ".$commentvars" = ".no" && expandvars="no" # option handling
+ test ".$commentvars" = ".no" && simplevars="no" # tests below
+ test ".$expandvars" != ".no" && \
+ $SED -e "/^=....=formatter /d" \
+ -e "/^=name=/s,=name=$V9,s|<!--$V0\\1[?]-->|- \\2|," \
+ -e "/^=Name=/s,=Name=$V9,s|<!--$V0\\1[?]-->|(\\2)|," \
+ -e "/^=name=/s,=name=$V8,s|<!--$V0\\1[?]-->|- \\2|," \
+ -e "/^=Name=/s,=Name=$V8,s|<!--$V0\\1[?]-->|(\\2)|," \
+ -e "/^=/d" -e "s|&|\\\\&|g" $INP # $++
+ test ".$expandvars" != ".no" && \
+ $SED -e "/^=....=formatter /d" \
+ -e "/^=text=/s,=text=$V9,s|<!--$V1\\1-->|\\\\1$SS\\2|," \
+ -e "/^=Text=/s,=Text=$V9,s|<!--$V1\\1-->|\\\\1$SS\\2|," \
+ -e "/^=name=/s,=name=$V9,s|<!--$V1\\1[?]-->|\\\\1$SS\\2|," \
+ -e "/^=Name=/s,=Name=$V9,s|<!--$V1\\1[?]-->|\\\\1$SS\\2|," \
+ -e "/^=text=/s,=text=$V8,s|<!--$V1\\1-->|\\\\1$SS\\2|," \
+ -e "/^=Text=/s,=Text=$V8,s|<!--$V1\\1-->|\\\\1$SS\\2|," \
+ -e "/^=name=/s,=name=$V8,s|<!--$V1\\1[?]-->|\\\\1$SS\\2|," \
+ -e "/^=Name=/s,=Name=$V8,s|<!--$V1\\1[?]-->|\\\\1$SS\\2|," \
+ -e "/^=/d" -e "s|&|\\\\&|g" $INP # $++
+ test ".$simplevars" != ".no" && test ".$updatevars" != ".no" && \
+ $SED -e "/^=....=formatter /d" \
+ -e "/^=text=/s,=text=$V9,s|<!--$V0\\1:-->[$AX]*|\\2|," \
+ -e "/^=Text=/s,=Text=$V9,s|<!--$V0\\1:-->[$AX]*|\\2|," \
+ -e "/^=name=/s,=name=$V9,s|<!--$V0\\1[?]:-->[$AX]*|- \\2|," \
+ -e "/^=Name=/s,=Name=$V9,s|<!--$V0\\1[?]:-->[$AX]*| (\\2) |," \
+ -e "/^=text=/s,=text=$V8,s|<!--$V0\\1:-->[$AX]*|\\2|," \
+ -e "/^=Text=/s,=Text=$V8,s|<!--$V0\\1:-->[$AX]*|\\2|," \
+ -e "/^=name=/s,=name=$V8,s|<!--$V0\\1[?]:-->[$AX]*|- \\2|," \
+ -e "/^=Name=/s,=Name=$V8,s|<!--$V0\\1[?]:-->[$AX]*| (\\2) |," \
+ -e "/^=/d" -e "s|&|\\\\&|g" $INP # $++
+ test ".$updatevars" != ".no" && \
+ $SED -e "/^=....=formatter /d" \
+ -e "/^=name=/s,=name=$V9,s|<!--$V0\\1:[?]-->[^<>]*|- \\2|," \
+ -e "/^=Name=/s,=Name=$V9,s|<!--$V0\\1:[?]-->[^<>]*| (\\2) |," \
+ -e "/^=name=/s,=name=$V8,s|<!--$V0\\1:[?]-->[^<>]*|- \\2|," \
+ -e "/^=Name=/s,=Name=$V8,s|<!--$V0\\1:[?]-->[^<>]*| (\\2) |," \
+ -e "/^=/d" -e "s|&|\\\\&|g" $INP # $++
+ test ".$updatevars" != ".no" && \
+ $SED -e "/^=....=formatter /d" \
+ -e "/^=text=/s,=text=$V9,s|<!--$V1\\1:[=]-->[^<>]*|\\\\1$SS\\2|," \
+ -e "/^=Text=/s,=Text=$V9,s|<!--$V1\\1:[=]-->[^<>]*|\\\\1$SS\\2|," \
+ -e "/^=name=/s,=name=$V9,s|<!--$V1\\1:[?]-->[^<>]*|\\\\1$SS\\2|," \
+ -e "/^=Name=/s,=Name=$V9,s|<!--$V1\\1:[?]-->[^<>]*|\\\\1$SS\\2|," \
+ -e "/^=text=/s,=text=$V8,s|<!--$V1\\1:[=]-->[^<>]*|\\\\1$SS\\2|," \
+ -e "/^=Text=/s,=Text=$V8,s|<!--$V1\\1:[=]-->[^<>]*|\\\\1$SS\\2|," \
+ -e "/^=name=/s,=name=$V8,s|<!--$V1\\1:[?]-->[^<>]*|\\\\1$SS\\2|," \
+ -e "/^=Name=/s,=Name=$V8,s|<!--$V1\\1:[?]-->[^<>]*|\\\\1$SS\\2|," \
+ -e "/^=/d" -e "s|&|\\\\&|g" $INP # $++
+ test ".$attribvars" != ".no" && \
+ $SED -e "/^=....=formatter /d" \
+ -e "/^=text=/s,=text=$V9,s|<$V1{\\1:[=]$V2}$V3>|<\\\\1$SS\\2\\\\3>|," \
+ -e "/^=Text=/s,=Text=$V9,s|<$V1{\\1:[=]$V2}$V3>|<\\\\1$SS\\2\\\\3>|," \
+ -e "/^=name=/s,=name=$V9,s|<$V1{\\1:[?]$V2}$V3>|<\\\\1$SS\\2\\\\3>|," \
+ -e "/^=Name=/s,=Name=$V9,s|<$V1{\\1:[?]$V2}$V3>|<\\\\1$SS\\2\\\\3>|," \
+ -e "/^=text=/s,=text=$V8,s|<$V1{\\1:[=]$V2}$V3>|<\\\\1$SS\\2\\\\3>|," \
+ -e "/^=Text=/s,=Text=$V8,s|<$V1{\\1:[=]$V2}$V3>|<\\\\1$SS\\2\\\\3>|," \
+ -e "/^=name=/s,=name=$V8,s|<$V1{\\1:[?]$V2}$V3>|<\\\\1$SS\\2\\\\3>|," \
+ -e "/^=Name=/s,=Name=$V8,s|<$V1{\\1:[?]$V2}$V3>|<\\\\1$SS\\2\\\\3>|," \
+ -e "/^=/d" -e "s|&|\\\\&|g" $INP # $++
+ test ".$simplevars" != ".no" && \
+ $SED -e "/^=....=formatter /d" \
+ -e "/^=text=/s,=text=$V9,s|<!--\\1-->[$AX]*|\\2|," \
+ -e "/^=Text=/s,=Text=$V9,s|<!--\\1-->[$AX]*|\\2|," \
+ -e "/^=name=/s,=name=$V9,s|<!--\\1[?]-->[$AX]*| - \\2|," \
+ -e "/^=Name=/s,=Name=$V9,s|<!--\\1[?]-->[$AX]*| (\\2) |," \
+ -e "/^=text=/s,=text=$V8,s|<!--\\1-->[$AX]*|\\2|," \
+ -e "/^=Text=/s,=Text=$V8,s|<!--\\1-->[$AX]*|\\2|," \
+ -e "/^=name=/s,=name=$V8,s|<!--\\1[?]-->[$AX]*| - \\2|," \
+ -e "/^=Name=/s,=Name=$V8,s|<!--\\1[?]-->[$AX]*| (\\2) |," \
+ -e "/^=/d" -e "s|&|\\\\&|g" $INP # $++
+ # if value="2004" then generated sed might be "\\12004" which is bad
+ # instead we generate an edited value of "\\1$SS$value" and cut out
+ # the spacer now after expanding the variable values:
+ echo "s|$SS||g" # $++
+}
+
+info2meta_sed () # generate <meta name..> text portion
+{
+ # http://www.metatab.de/meta_tags/DC_type.htm
+ INP="$1" ; test ".$INP" = "." && INP="$tmp/$F.$INFO"
+ V6=" *HTTP[.]\\([^ ][^ ]*\\) \\(.*\\)"
+ V7=" *DC[.]\\([^ ][^ ]*\\) \\(.*\\)"
+ V8=" *\\([^ ][^ ]*\\) \\(.*\\)"
+ INFO_META_TYPE_SCHEME="name=\"DC.type\" content=\"\\2\" scheme=\"\\1\""
+ INFO_META_DCMI="name=\"\\1\" content=\"\\2\" scheme=\"DCMIType\""
+ INFO_META_NAME_TZ="name=\"\\1\" content=\"\\2 `timezone`\""
+ INFO_META_NAME="name=\"\\1\" content=\"\\2\""
+ INFO_META_HTTP="http-equiv=\"\\1\" content=\"\\2\""
+ $SED -e "/=....=today /d" \
+ -e "/=meta=HTTP[.]/s,=meta=$V6, <meta $INFO_META_HTTP />," \
+ -e "/=meta=DC[.]DCMIType /s,=meta=$V7, <meta $INFO_META_TYPE_SCHEME />," \
+ -e "/=meta=DC[.]type Collection$/s,=meta=$V8, <meta $INFO_META_DCMI />," \
+ -e "/=meta=DC[.]type Dataset$/s,=meta=$V8, <meta $INFO_META_DCMI />," \
+ -e "/=meta=DC[.]type Event$/s,=meta=$V8, <meta $INFO_META_DCMI />," \
+ -e "/=meta=DC[.]type Image$/s,=meta=$V8, <meta $INFO_META_DCMI />," \
+ -e "/=meta=DC[.]type Service$/s,=meta=$V8, <meta $INFO_META_DCMI />," \
+ -e "/=meta=DC[.]type Software$/s,=meta=$V8, <meta $INFO_META_DCMI />," \
+ -e "/=meta=DC[.]type Sound$/s,=meta=$V8, <meta $INFO_META_DCMI />," \
+ -e "/=meta=DC[.]type Text$/s,=meta=$V8, <meta $INFO_META_DCMI />," \
+ -e "/=meta=DC[.]date[.].*[+]/s,=meta=$V8, <meta $INFO_META_NAME />," \
+ -e "/=meta=DC[.]date[.].*[:]/s,=meta=$V8, <meta $INFO_META_NAME_TZ />," \
+ -e "/=meta=/s,=meta=$V8, <meta $INFO_META_NAME />," \
+ -e "/<meta name=\"[^\"]*\" content=\"\" /d" \
+ -e "/<meta http-equiv=\"[^\"]*\" content=\"\" /d" \
+ -e "/^=/d" $INP # $++
+}
+
+info_get_entry () # get the first <!--vars--> value known so far
+{
+ TXT="$1" ; test ".$TXT" = "." && TXT="sect"
+ INP="$2" ; test ".$INP" = "." && INP="$tmp/$F.$INFO"
+ $SED -e "/=text=$TXT /!d" -e "s/=text=$TXT //" -e "q" $INP # $++
+}
+
+info1grep () # test for a <!--vars--> substition to be already present
+{
+ TXT="$1" ; test ".$TXT" = "." && TXT="sect"
+ INP="$2" ; test ".$INP" = "." && INP="$tmp/$F.$INFO"
+ $GREP "^=text=$TXT " $INP >$NULL
+ return $?
+}
+
+dx_init()
+{
+ mkpathdir "$tmp"
+ dx_meta formatter `basename $opt_formatter` > "$tmp/$F.$INFO"
+ for opt in $opt_variables ; do case "$opt" in # commandline --def=value
+ *_*) op_=`echo "$opt" | sed -e "y/_/-/"` # makes for <!--$def-->
+ dx_meta "$op_" `eval echo "\\\$opt_$opt"` ;;
+ *) dx_text "$opt" `eval echo "\\\$opt_$opt"` ;;
+ esac ; done
+}
+
+dx_line ()
+{
+ echo "$1$2 "`trimmm "$3"` >> "$tmp/$F.$INFO"
+}
+
+DX_line ()
+{
+ dx_val_=`echo "$3" | sed -e "s/<[^<>]*>//g"`
+ dx_line "$1" "$2" "$dx_val_"
+}
+
+dx_text ()
+{
+ dx_line "=text=" "$1" "$2"
+}
+
+DX_text () # add a <!--vars--> substition includings format variants
+{
+ N=`trimm "$1"` ; T=`trimm "$2"`
+ if test ".$N" != "." ; then
+ if test ".$T" != "." ; then
+ text=`echo "$T" | $SED -e "y/$UPPER/$LOWER/" -e "s/<[^<>]*>//g"`
+ dx_line "=text=" "$N" "$T"
+ dx_line "=name=" "$N" "$text"
+ varname=`echo "$N" | $SED -e 's/.*[.]//'` # cut out front part
+ if test ".$N" != ".$varname" ; then
+ text=`echo "$varname $T" | $SED -e "y/$UPPER/$LOWER/" -e "s/<[^<>]*>//g"`
+ dx_line "=Text=" "$varname" "$T"
+ dx_line "=Name=" "$varname" "$text"
+ fi
+ fi
+ fi
+}
+
+dx_meta ()
+{
+ DX_line "=meta=" "$1" "$2"
+}
+
+DX_meta () # add simple meta entry and its <!--vars--> subsitution
+{
+ DX_line "=meta=" "$1" "$2"
+ DX_text "$1" "$2"
+}
+
+DC_meta () # add new DC.meta entry plus two <!--vars--> substitutions
+{
+ DX_line "=meta=" "DC.$1" "$2"
+ DX_text "DC.$1" "$2"
+ DX_text "$1" "$2"
+}
+
+HTTP_meta () # add new HTTP.meta entry plus two <!--vars--> substitutions
+{
+ DX_line "=meta=" "HTTP.$1" "$2"
+ DX_text "HTTP.$1" "$2"
+ DX_text "$1" "$2"
+}
+
+DC_VARS_Of () # check DC vars as listed in $DC_VARS global and generate DC_meta
+{ # the results will be added to .meta.tmp and .vars.tmp later
+ FILENAME="$1" ; test ".$FILENAME" = "." && FILENAME="$SOURCEFILE"
+ for M in $DC_VARS title ; do
+ # scan for a <markup> of this name
+ part=`$SED -e "/<$M>/!d" -e "s|.*<$M>||" -e "s|</$M>.*||" -e q $FILENAME`
+ part=`trimm "$part"`
+ text=`echo "$part" | $SED -e "s|^[$AA]*:||"`
+ text=`trimm "$text"`
+ test ".$text" = "." && continue
+ # <mark:part> will be <meta name="mark.part">
+ if test ".$text" != ".$part" ; then
+ N=`echo "$part" | $SED -e "s/:.*//"`
+ DC_meta "$M.$N" "$text"
+ elif test ".$M" = ".date" ; then
+ DC_meta "$M.issued" "$text" # "<date>" -> "<date>issued:"
+ else
+ DC_meta "$M" "$text"
+ fi
+ done
+}
+
+HTTP_VARS_Of () # check HTTP-EQUIVs as listed in $_EQUIV global then
+{ # generate meta tags that are http-equiv= instead of name=
+ FILENAME="$1" ; test ".$FILENAME" = "." && FILENAME="$SOURCEFILE"
+ for M in $_EQUIVS ; do
+ # scan for a <markup> of this name
+ part=`$SED -e "/<$M>/!d" -e "s|.*<$M>||" -e "s|</$M>.*||" -e q $FILENAME`
+ part=`trimm "$part"`
+ text=`echo "$part" | $SED -e "s|^[$AA]*:||"`
+ text=`trimm "$text"`
+ test ".$text" = "." && continue
+ if test ".$M" = ".redirect" ; then
+ HTTP_meta "refresh" "5; url=$text" ; DX_text "$M" "$text"
+ elif test ".$M" = ".charset" ; then
+ HTTP_meta "content-type" "text/html; charset=$text"
+ else
+ HTTP_meta "$M" "$text"
+ fi
+ done
+}
+
+DC_isFormatOf () # make sure there is this DC.relation.isFormatOf tag
+{ # choose argument for a fallback (usually $SOURCEFILE)
+ NAME="$1" ; test ".$NAME" = "." && NAME="$SOURCEFILE"
+ info1grep DC.relation.isFormatOf || DC_meta relation.isFormatOf "$NAME"
+}
+
+DC_publisher () # make sure there is this DC.publisher meta tag
+{ # choose argument for a fallback (often $USER)
+ NAME="$1" ; test ".$NAME" = "." && NAME="$USER"
+ info1grep DC.publisher || DC_meta publisher "$NAME"
+}
+
+DC_modified () # make sure there is a DC.date.modified meta tag
+{ # maybe choose from filesystem dates if possible
+ Q="$1" # target file
+ if info1grep DC.date.modified ; then :
+ else
+ _42_chars="........................................."
+ cut_42_55="s/^$_42_chars\\(.............\\).*/\\1/" # i.e.`cut -b 42-55`
+ text=`$STAT_R $Q 2>$NULL | $SED -e '/odify:/!d' -e 's|.*fy:||' -e q`
+ text=`echo "$text" | $SED -e "s/:..[.][$NN]*//"`
+ text=`trimm "$text"`
+ test ".$text" = "." && \
+ text=`$DATE_R "$Q" +%Y-%m-%d 2>$NULL` # GNU sed
+ test ".$text" = "." &&
+ text=`$LS_L "$Q" | $SED -e "$cut_42_55" -e "s/^ *//g" -e "q"`
+ text=`echo "$text" | $SED -e "s/[$NN]*:.*//"` # cut way seconds
+ DC_meta date.modified `trimm "$text"`
+ fi
+}
+
+DC_date () # make sure there is this DC.date meta tag
+{ # choose from one of the available DC.date.* specials
+ Q="$1" # source file
+ if info1grep DC.date
+ then DX_text issue "dated `info_get_entry DC.date`"
+ DX_text updated "`info_get_entry DC.date`"
+ else text=""
+ for kind in available issued modified created ; do
+ text=`info_get_entry DC.date.$kind`
+ # test ".$text" != "." && echo "$kind = date = $text ($Q)"
+ test ".$text" != "." && break
+ done
+ if test ".$text" = "." ; then
+ M="date"
+ part=`$SED -e "/<$M>/!d" -e "s|.*<$M>||" -e "s|</$M>.*||" -e q $Q`
+ part=`trimm "$part"`
+ text=`echo "$part" | $SED -e "s|^[$AA]*:||"`
+ text=`trimm "$text"`
+ fi
+ if test ".$text" = "." ; then
+ M="!--date:*=*--" # takeover updateable variable...
+ part=`$SED -e "/<$M>/!d" -e "s|.*<$M>||" -e "s|</.*||" -e q $Q`
+ part=`trimm "$part"`
+ text=`echo "$part" | $SED -e "s|^[$AA]*:||" -e "s|\\&.*||"`
+ text=`trimm "$text"`
+ fi
+ text=`echo "$text" | $SED -e "s/[$NN]*:.*//"` # cut way seconds
+ DX_text updated "$text"
+ text1=`echo "$text" | $SED -e "s|^.* *updated ||"`
+ if test ".$text" != ".$text1" ; then
+ kind="modified" ; text=`echo "$text1" | $SED -e "s|,.*||"`
+ fi
+ text1=`echo "$text" | $SED -e "s|^.* *modified ||"`
+ if test ".$text" != ".$text1" ; then
+ kind="modified" ; text=`echo "$text1" | $SED -e "s|,.*||"`
+ fi
+ text1=`echo "$text" | $SED -e "s|^.* *created ||"`
+ if test ".$text" != ".$text1" ; then
+ kind="created" ; text=`echo "$text1" | $SED -e "s|,.*||"`
+ fi
+ text=`echo "$text" | $SED -e "s/[$NN]*:.*//"` # cut way seconds
+ DC_meta date `trimm "$text"`
+ DX_text issue `trimm "$kind $text"`
+ fi
+}
+
+DC_title ()
+{
+ # choose a title for the document, either an explicit title-tag
+ # or one of the section headers in the document or fallback to filename
+ Q="$1" # target file
+ if info1grep DC.title ; then :
+ else
+ for M in TITLE title H1 h1 H2 h2 H3 H3 H4 H4 H5 h5 H6 h6 ; do
+ text=`$SED -e "/<$M>/!d" -e "s|.*<$M>||" -e "s|</$M>.*||" -e q $Q`
+ text=`trimm "$text"` ; test ".$text" != "." && break
+ MM="$M [^<>]*"
+ text=`$SED -e "/<$MM>/!d" -e "s|.*<$MM>||" -e "s|</$M>.*||" -e q $Q`
+ text=`trimm "$text"` ; test ".$text" != "." && break
+ done
+ if test ".text" = "." ; then
+ text=`basename $Q .html`
+ text=`basename $text .htm | $SED -e 'y/_/ /' -e "s/\\$/ info/"`
+ fi
+ term=`echo "$text" | $SED -e 's/.*[(]//' -e 's/[)].*//'`
+ text=`echo "$text" | $SED -e 's/[(][^()]*[)]//'`
+ if test ".$term" = "." || test ".$term" = ".$text" ; then
+ DC_meta title "$text"
+ else
+ DC_meta title "$term - $text"
+ fi
+ fi
+}
+
+site_get_section () # return parent section page of given page
+{
+ _F_=`sed_slash_key "$1"`
+ $SED -e "/^=sect=$_F_ /!d" -e "s/^=sect=$_F_ //" -e q "$MK_INFO" # $++
+}
+
+DC_section () # not really a DC relation (shall we use isPartOf ?)
+{ # each document should know its section father
+ sectn=`site_get_section "$F"`
+ if test ".$sectn" != "." ; then
+ DC_meta relation.section "$sectn"
+ fi
+}
+
+info_get_entry_section()
+{
+ info_get_entry DC.relation.section # $++
+}
+
+site_get_selected () # return section of given page
+{
+ _F_=`sed_slash_key "$1"`
+ $SED -e "/=use.=$_F_ /!d" -e "s/=use.=[^ ]* //" -e q "$MK_INFO" # $++
+}
+
+DC_selected () # not really a DC title (shall we use alternative ?)
+{
+ # each document might want to highlight the currently selected item
+ short=`site_get_selected "$F"`
+ if test ".$short" != "." ; then
+ DC_meta title.selected "$short"
+ fi
+}
+
+info_get_entry_selected ()
+{
+ info_get_entry DC.title.selected # $++
+}
+
+site_get_rootsections () # return all sections from root of nav tree
+{
+ $SED -e "/=use1=/!d" -e "s/=use.=\\([^ ]*\\) .*/\\1/" "$MK_INFO" # $++
+}
+
+site_get_sectionpages () # return all children pages in the given section
+{
+ _F_=`sed_slash_key "$1"`
+ $SED -e "/^=sect=[^ ]* $_F_\$/!d" -e "s/^=sect=//" \
+ -e "s/ .*//" "$MK_INFO" # $++
+}
+
+site_get_subpages () # return all page children of given page
+{
+ _F_=`sed_slash_key "$1"`
+ $SED -e "/^=node=[^ ]* $_F_\$/!d" -e "s/^=node=//" -e "s/ .*//" "$MK_INFO"
+ # $++
+}
+
+site_get_parentpage () # return parent page for given page (".." for sections)
+{
+ _F_=`sed_slash_key "$1"`
+ $SED -e "/^=node=$_F_ /!d" -e "s/^=node=[^ ]* //" -e "q" "$MK_INFO" # $++
+}
+
+DX_alternative () # detect wether page asks for alternative style
+{ # which is generally a shortpage variant
+ x=`mksite_magic_option alternative $1 | sed -e "s/^ *//" -e "s/ .*//"`
+ if test ".$x" != "." ; then
+ DX_text alternative "$x"
+ fi
+}
+
+info2head_sed () # append alternative handling script to $HEAD
+{
+ have=`info_get_entry alternative`
+ if test ".$have" != "." ; then
+ echo "/<!--mksite:alternative:$have .*-->/{" # $++
+ echo "s/<!--mksite:alternative:$have\\( .*\\)-->/\\1/" # $++
+ echo "q" # $++
+ echo "}" # $++
+ fi
+}
+info2body_sed () # append alternative handling script to $BODY
+{
+ have=`info_get_entry alternative`
+ if test ".$have" != "." ; then
+ echo "s/<!--mksite:alternative:$have\\( .*\\)-->/\\1/" # $++
+ fi
+}
+
+bodymaker_for_sectioninfo ()
+{
+ test ".$sectioninfo" = ".no" && return
+ _x_="<!--mksite:sectioninfo::-->"
+ _q_="\\([^<>]*[$AX][^<>]*\\)"
+ test ".$sectioninfo" != ". " && _q_="[ ][ ]*$sectioninfo\\([ ]\\)"
+ echo "s|\\(^<[hH][$NN][ >].*</[hH][$NN]>\\)$_q_|\\1$_x_\\2|" # $++
+ echo "/$_x_/s|^|<table width=\"100%\"><tr valign=\"bottom\"><td>|" # $++
+ echo "/$_x_/s|</[hH][$NN]>|&</td><td align=\"right\"><i>|" # $++
+ echo "/$_x_/s|\$|</i></td></tr></table>|" # $++
+ echo "s|$_x_||" # $++
+}
+
+fast_href () # args "$FILETOREFERENCE" "$FROMCURRENTFILE:$F"
+{ # prints path to $FILETOREFERENCE href-clickable in $FROMCURRENTFILE
+ # if no subdirectoy then output is the same as input $FILETOREFERENCE
+ R="$2" ; test ".$R" = "." && R="$F"
+ S=`back_path "$R"`
+ if test ".$S" = "."
+ then echo "$1" # $++
+ else _1_=`echo "$1" | \
+ $SED -e "/^ *\$/d" -e "/^\\//d" -e "/^[.][.]/d" -e "/^[$AA]*:/d" `
+ if test ".$_1_" = "." # don't move any in the pattern above
+ then echo "$1" # $++
+ else echo "$S$1" # $++ prefixed with backpath
+ fi fi
+}
+
+make_fast () # experimental - make a FAST file that can be applied
+{ # to htm sourcefiles in a subdirectory of the sitefile.
+# R="$1" ; test ".$R" = "." && R="$F"
+ S=`back_path "$F"`
+ if test ".$S" = "" ; then
+ # echo "backpath '$F' = none needed"
+ $CATNULL # $++
+ else
+ # echo "backpath '$F' -> '$S'"
+ $SED -e "/href=\"[^\"]*\"/!d" -e "s/.*href=\"//" -e "s/\".*//" \
+ -e "/^ *\$/d" -e "/^\\//d" -e "/^[.][.]/d" -e "/^[$AA]*:/d" \
+ $SITEFILE $SOURCEFILE | sort | uniq \
+ | $SED -e "s,.*,s|href=\"&\"|href=\"$S&\"|," # $++
+ fi
+}
+
+# ============================================================== SITE MAP INFO
+# each entry needs atleast a list-title, a long-title, and a list-date
+# these are the basic information to be printed in the sitemap file
+# where it is bound the hierarchy of sect/subsect of the entries.
+
+site_map_list_title() # $file $text
+{
+ echo "=list=$1 $2" >> "$MK_INFO"
+}
+info_map_list_title() # $file $text
+{
+ echo "=list=$2" >> "$tmp/$1.$INFO"
+}
+site_map_long_title() # $file $text
+{
+ echo "=long=$1 $2" >> "$MK_INFO"
+}
+info_map_long_title() # $file $text
+{
+ echo "=long=$2" >> "$tmp/$1.$INFO"
+}
+site_map_list_date() # $file $text
+{
+ echo "=date=$1 $2" >> "$MK_INFO"
+}
+info_map_list_date() # $file $text
+{
+ echo "=date=$2" >> "$tmp/$1.$INFO"
+}
+
+siteinfo2sitemap () # generate <name><page><date> addon sed scriptlet
+{ # the resulting script will act on each item/line
+ # containing <!--"filename"--> and expand any following
+ # reference of <!--name--> or <!--date--> or <!--long-->
+ INP="$1" ; test ".$INP" = "." && INP="$MK_INFO"
+ _list_="s|<!--\"\\1\"-->.*<!--name-->|\\&<name href=\"\\1\">\\2</name>|"
+ _date_="s|<!--\"\\1\"-->.*<!--date-->|\\&<date>\\2</date>|"
+ _long_="s|<!--\"\\1\"-->.*<!--long-->|\\&<long>\\2</long>|"
+ $SED -e "s:&:\\\\&:g" \
+ -e "s:=list=\\([^ ]*\\) \\(.*\\):$_list_:" \
+ -e "s:=date=\\([^ ]*\\) \\(.*\\):$_date_:" \
+ -e "s:=long=\\([^ ]*\\) \\(.*\\):$_long_:" \
+ -e "/^s|/!d" $INP # $++
+}
+
+make_multisitemap ()
+{ # each category gets its own column along with the usual entries
+ INPUTS="$1" ; test ".$INPUTS" = "." && INPUTS="$MK_INFO"
+ siteinfo2sitemap > "$MK_SITE" # have <name><long><date> addon-sed
+ _form_="<!--\"\\2\"--><!--use\\1--><!--long--><!--end\\1-->"
+ _form_="$_form_<br><!--name--><!--date-->"
+ _tiny_="small><small><small" ; _tinyX_="small></small></small "
+ _tabb_="<br><$_tiny_> </$_tinyX_>" ; _bigg_="<big> </big>"
+ echo "<table width=\"100%\"><tr><td> " # $++
+ $SED -e "/=use.=/!d" -e "s|=use\\(.\\)=\\([^ ]*\\) .*|$_form_|" \
+ -f "$MK_SITE" -e "/<name/!d" \
+ -e "s|<!--use1-->|</td><td valign=\"top\"><b>|" \
+ -e "s|<!--end1-->|</b>|" \
+ -e "s|<!--use2-->|<br>|" \
+ -e "s|<!--use.-->|<br>|" -e "s/<!--[^<>]*-->/ /g" \
+ -e "s|<long>||" -e "s|</long>||" \
+ -e "s|<name |<$_tiny_><a |" -e "s|</name>||" \
+ -e "s|<date>| |" -e "s|</date>|</a><br></$_tinyX_>|" \
+ $INPUTS # $++
+ echo "</td><tr></table>" # $++
+}
+
+make_listsitemap ()
+{ # traditional - the body contains a list with date and title extras
+ INPUTS="$1" ; test ".$INPUTS" = "." && INPUTS="$MK_INFO"
+ siteinfo2sitemap > "$MK_SITE" # have <name><long><date> addon-sed
+ _form_="<!--\"\\2\"--><!--use\\1--><!--name--><!--date--><!--long-->"
+ _tabb_="<td>\\&nbsp\\;</td>"
+ echo "<table cellspacing=\"0\" cellpadding=\"0\">" # $++
+ $SED -e "/=use.=/!d" -e "s|=use\\(.\\)=\\([^ ]*\\) .*|$_form_|" \
+ -f "$MK_SITE" -e "/<name/!d" \
+ -e "s|<!--use\\(1\\)-->|<tr class=\"listsitemap\\1\"><td>*</td>|" \
+ -e "s|<!--use\\(2\\)-->|<tr class=\"listsitemap\\1\"><td>-</td>|" \
+ -e "s|<!--use\\(.\\)-->|<tr class=\"listsitemap\\1\"><td> </td>|" \
+ -e "/<tr.class=\"listsitemap3\">/s|<name [^<>]*>|&- |" \
+ -e "s|<!--[^<>]*-->| |g" \
+ -e "s|<name href=\"name:sitemap:|<name href=\"|" \
+ -e "s|<name |<td><a |" -e "s|</name>|</a></td>$_tabb_|" \
+ -e "s|<date>|<td><small>|" -e "s|</date>|</small></td>$_tabb_|" \
+ -e "s|<long>|<td><em>|" -e "s|</long>|</em></td></tr>|" \
+ $INPUTS # $++
+ for xx in `grep "=use.=name:sitemap:" $INPUTS` ; do
+ xx=`echo $xx | sed -e "s/=use.=name:sitemap://"`
+ if test -f "$xx" ; then
+ grep "<tr.class=\"listsitemap[$NN]\">" $xx # $++
+ fi
+ done
+ echo "</table>" # $++
+}
+
+print_extension ()
+{
+ ARG="$1" ; test ".$ARG" = "." && ARG="$opt_print"
+ case "$ARG" in
+ -*|.*) echo "$ARG" ;; # $++
+ *) echo ".print" ;; # $++
+ esac
+}
+
+html_sourcefile () # generally just cut away the trailing "l" (ell)
+{ # making "page.html" argument into "page.htm" return
+ _SRCFILE_=`echo "$1" | $SED -e "s/l\\$//"`
+ if test -f "$_SRCFILE_" ; then echo "$_SRCFILE_" # $++
+ elif test -f "$opt_src_dir/$_SRCFILE_"
+ then echo "$opt_src_dir/$_SRCFILE_" # $++
+ else echo ".//$_SRCFILE_" # $++
+ fi
+}
+html_printerfile_sourcefile ()
+{
+ if test ".$printerfriendly" = "."
+ then
+ echo "$1" | sed -e "s/l\$//" # $++
+ else
+ _ext_=`print_extension "$printerfriendly"`
+ _ext_=`sed_slash_key "$_ext_"`
+ echo "$1" | sed -e "s/l\$//" -e "s/$_ext_\\([.][$AA]*\\)\$/\\1/" # $++
+ fi
+}
+
+fast_html_printerfile () {
+ x=`html_printerfile "$1"` ; basename "$x" # $++
+# x=`html_printerfile "$1"` ; fast_href "$x" $2 # $++
+}
+
+html_printerfile () # generate the printerfile for a given normal output
+{
+ _ext_=`print_extension "$printerfriendly" | sed -e "s/&/\\\\&/"`
+ echo "$1" | sed -e "s/\\([.][$AA]*\\)\$/$_ext_\\1/" # $++
+}
+
+make_printerfile_fast () # generate s/file.html/file.print.html/ for hrefs
+{ # we do that only for the $FILELIST
+ ALLPAGES="$1" ; # ="$FILELIST"
+ for p in $ALLPAGES ; do
+ a=`sed_slash_key "$p"`
+ b=`html_printerfile "$p"`
+ if test "$b" != "$p" ; then
+ b=`html_printerfile "$p" | sed -e "s:&:\\\\&:g" -e "s:/:\\\\\\/:g"`
+ echo "s/<a href=\"$a\">/<a href=\"$b\">/" # $++
+ echo "s/<a href=\"$a\" /<a href=\"$b\" /" # $++
+ fi
+ done
+}
+
+echo_printsitefile_style ()
+{
+ _bold_="text-decoration : none ; font-weight : bold ; "
+ echo " <style>" # $+++
+ echo " a:link { $_bold_ color : #000060 ; }" # $+++
+ echo " a:visited { $_bold_ color : #000040 ; }" # $+++
+ echo " body { background-color : white ; }" # $+++
+ echo " </style>" # $+++
+}
+
+make_printsitefile_head() # $sitefile
+{
+ echo_printsitefile_style > "$MK_STYLE"
+ $SED -e "/<title>/p" -e "/<title>/d" \
+ -e "/<head>/p" -e "/<head>/d" \
+ -e "/<\/head>/p" -e "/<\/head>/d" \
+ -e "/<body>/p" -e "/<body>/d" \
+ -e "/^.*<link [^<>]*rel=\"shortcut icon\"[^<>]*>.*\$/p" \
+ -e "d" $SITEFILE | $SED -e "/<head>/r $MK_STYLE" # $+++
+}
+
+
+# ------------------------------------------------------------------------
+# The printsitefile is a long text containing html href markups where
+# each of the href lines in the file is being prefixed with the section
+# relation. During a secondary call the printsitefile can grepp'ed for
+# those lines that match a given output fast-file. The result is a
+# navigation header with 1...3 lines matching the nesting level
+
+# these alt-texts will be only visible in with a text-mode browser:
+printsitefile_square="width=\"8\" height=\"8\" border=\"0\""
+printsitefile_img_1="<img alt=\"|go text:\" $printsitefile_square />"
+printsitefile_img_2="<img alt=\"||topics:\" $printsitefile_square />"
+printsitefile_img_3="<img alt=\"|||pages:\" $printsitefile_square />"
+_SECT="mksite:sect:"
+
+echo_current_line () # $sect $extra
+{
+ echo "<!--$_SECT\"$1\"-->$2" # $++
+}
+make_current_entry () # $sect $file ## requires $MK_SITE
+{
+ S="$1" ; R="$2"
+ SSS=`sed_slash_key "$S"`
+ sep=" - " ; _left_=" [ " ; _right_=" ] "
+ echo_current_line "$S" "<a href=\"$R\"><!--\"$R\"--><!--name--></a>$sep" \
+ | $SED -f "$MK_SITE" -e "s/<name[^<>]*>//" -e "s/<\\/name>//" \
+ -e "/<a href=\"$SSS\"/s/<a href/$_left_&/" \
+ -e "/<a href=\"$SSS\"/s/<\\/a>/&$_right_/" \
+ -e "s/<!--\"[^\"]*\"--><!--name-->//" # $+++
+}
+echo_subpage_line () # $sect $extra
+{
+ echo "<!--$_SECT*:\"$1\"-->$2" # $++
+}
+
+make_subpage_entry ()
+{
+ S="$1" ; R="$2"
+ RR=`sed_slash_key "$R"`
+ sep=" - " ;
+ echo_subpage_line "$S" "<a href=\"$R\"><!--\"$R\"--><!--name--></a>$sep" \
+ | $SED -f "$MK_SITE" -e "s/<name[^<>]*>//" -e "s/<\\/name>//" \
+ -e "s/<!--\"[^\"]*\"--><!--name-->//" # $+++
+}
+
+make_printsitefile ()
+{
+ # building the printsitefile looks big but its really a loop over sects
+ INPUTS="$1" ; test ".$INPUTS" = "." && INPUTS="$MK_INFO"
+ siteinfo2sitemap > "$MK_SITE" # have <name><long><date> addon-sed
+ make_printsitefile_head $SITEFILE # $++
+
+ sep=" - "
+ _sect1="<a href=\"#.\" title=\"section\">$printsitefile_img_1</a> ||$sep"
+ _sect2="<a href=\"#.\" title=\"topics\">$printsitefile_img_2</a> ||$sep"
+ _sect3="<a href=\"#.\" title=\"pages\">$printsitefile_img_3</a> ||$sep"
+ site_get_rootsections > "$MK_SECT1"
+ # round one - for each root section print a current menu
+ for r in `cat "$MK_SECT1"` ; do
+ echo_current_line "$r" "<!--mksite:sect1:A--><br>$_sect1" # $++
+ for s in `cat "$MK_SECT1"` ; do
+ make_current_entry "$r" "$s" # $++
+ done
+ echo_current_line "$r" "<!--mksite:sect1:Z-->" # $++
+ done # "$r"
+
+ # round two - for each subsection print a current and subpage menu
+ for r in `cat "$MK_SECT1"` ; do
+ site_get_subpages "$r" > "$MK_SECT2"
+ for s in `cat "$MK_SECT2"` ; do test "$r" = "$s" && continue
+ echo_current_line "$s" "<!--mksite:sect2:A--><br>$_sect2" # $++
+ for t in `cat "$MK_SECT2"` ; do test "$r" = "$t" && continue
+ make_current_entry "$s" "$t" # $++
+ done # "$t"
+ echo_current_line "$s" "<!--mksite:sect2:Z-->" # $++
+ done # "$s"
+ _have_children_="0"
+ for t in `cat "$MK_SECT2"` ; do test "$r" = "$t" && continue
+ test "$_have_children_" = "0" && _have_children_="1" && \
+ echo_subpage_line "$r" "<!--mksite:sect2:A--><br>$_sect2" # $++
+ make_subpage_entry "$r" "$t" # $++
+ done # "$t"
+ test "$_have_children_" = "1" && \
+ echo_subpage_line "$r" "<!--mksite:sect2:Z-->" # $++
+ done # "$r"
+
+ # round three - for each subsubsection print a current and subpage menu
+ for r in `cat "$MK_SECT1"` ; do
+ site_get_subpages "$r" > "$MK_SECT2"
+ for s in `cat "$MK_SECT2"` ; do test "$r" = "$s" && continue
+ site_get_subpages "$s" > "$MK_SECT3"
+ for t in `cat "$MK_SECT3"` ; do test "$s" = "$t" && continue
+ echo_current_line "$t" "<!--mksite:sect3:A--><br>$_sect3" # $++
+ for u in `cat "$MK_SECT3"` ; do test "$s" = "$u" && continue
+ make_current_entry "$t" "$u" # $++
+ done # "$u"
+ echo_current_line "$t" "<!--mksite:sect3:Z-->" # $++
+ done # "$t"
+ _have_children_="0"
+ for u in `cat "$MK_SECT3"` ; do test "$u" = "$s" && continue
+ test "$_have_children_" = "0" && _have_children_="1" && \
+ echo_subpage_line "$s" "<!--mksite:sect3:A--><br>$_sect3" # $++
+ make_subpage_entry "$s" "$u" # $++
+ done # "$u"
+ test "$_have_children_" = "1" && \
+ echo_subpage_line "$s" "<!--mksite:sect3:Z-->" # $++
+ done # "$s"
+ done # "$r"
+ echo "<a name=\".\"></a>" # $++
+ echo "</body></html>" # $++
+}
+
+# create a selector that can grep a printsitefile for the matching entries
+select_in_printsitefile () # arg = "page" : return to stdout >> $P.$HEAD
+{
+ _selected_="$1" ; test ".$_selected_" = "." && _selected_="$F"
+ _section_=`sed_slash_key "$_selected_"`
+ echo "s/^<!--$_SECT\"$_section_\"-->//" # sect3
+ echo "s/^<!--$_SECT[*]:\"$_section_\"-->//" # children
+ _selected_=`site_get_parentpage "$_selected_"`
+ _section_=`sed_slash_key "$_selected_"`
+ echo "s/^<!--$_SECT\"$_section_\"-->//" # sect2
+ _selected_=`site_get_parentpage "$_selected_"`
+ _section_=`sed_slash_key "$_selected_"`
+ echo "s/^<!--$_SECT\"$_section_\"-->//" # sect1
+ echo "/^<!--$_SECT\"[^\"]*\"-->/d"
+ echo "/^<!--$_SECT[*]:\"[^\"]*\"-->/d"
+ echo "s/^<!--mksite:sect[$NN]:[$AZ]-->//"
+}
+
+body_for_emailfooter ()
+{
+ test ".$emailfooter" = ".no" && return
+ _email_=`echo "$emailfooter" | sed -e "s|[?].*||"`
+ _dated_=`info_get_entry updated`
+ echo "<hr><table border=\"0\" width=\"100%\"><tr><td>"
+ echo "<a href=\"mailto:$emailfooter\">$_email_</a>"
+ echo "</td><td align=\"right\">"
+ echo "$_dated_</td></tr></table>"
+}
+
+# ==========================================================================
+#
+# During processing we will create a series of intermediate files that
+# store relations. They all have the same format being
+# =relationtype=key value
+# where key is usually s filename or an anchor. For mere convenience
+# we assume that the source html text does not have lines that start
+# off with =xxxx= (btw, ye remember perl section notation...). Of course
+# any other format would be usuable as well.
+#
+
+# we scan the SITEFILE for href references to be converted
+# - in the new variant we use a ".gets.tmp" sed script that SECTS
+# marks all interesting lines so they can be checked later
+# with an sed anchor of <!--sect[$NN]--> (or <!--sect[$AZ]-->)
+S="\\&nbsp\\;"
+# S="[&]nbsp[;]"
+
+# HR and EM style markups must exist in input - BR sometimes left out
+# these routines in(ter)ject hardspace before, between, after markups
+# note that "<br>" is sometimes used with HR - it must exist in input
+echo_HR_EM_PP ()
+{
+ echo "/^$1$2$3*<a href=/s/^/$4/"
+ echo "/^<>$1$2$3*<a href=/s/^/$4/"
+ echo "/^$S$1$2$3*<a href=/s/^/$4/"
+ echo "/^$1<>$2$3*<a href=/s/^/$4/"
+ echo "/^$1$S$2$3*<a href=/s/^/$4/"
+ echo "/^$1$2<>$3*<a href=/s/^/$4/"
+ echo "/^$1$2$S$3*<a href=/s/^/$4/"
+}
+
+echo_br_EM_PP ()
+{
+ echo_HR_EM_PP "$1" "$2" "$3" "$4"
+ echo "/^$2$3*<a href=/s/^/$4/"
+ echo "/^<>$2$3*<a href=/s/^/$4/"
+ echo "/^$S$2$3*<a href=/s/^/$4/"
+ echo "/^$2<>$3*<a href=/s/^/$4/"
+ echo "/^$2$S$3*<a href=/s/^/$4/"
+}
+
+echo_HR_PP ()
+{
+ echo "/^$1$2*<a href=/s/^/$3/"
+ echo "/^<>$1$2*<a href=/s/^/$3/"
+ echo "/^$S$1$2*<a href=/s/^/$3/"
+ echo "/^$1<>$2*<a href=/s/^/$3/"
+ echo "/^$1$S$2*<a href=/s/^/$3/"
+}
+echo_br_PP ()
+{
+ echo_HR_PP "$1" "$2" "$3"
+ echo "/^$2*<a href=/s/^/$3/"
+ echo "/^<>$2*<a href=/s/^/$3/"
+ echo "/^$S$2*<a href=/s/^/$3/"
+}
+echo_sp_PP ()
+{
+ echo "/^<>$1*<a href=/s/^/$2/"
+ echo "/^$S$1*<a href=/s/^/$2/"
+ echo "/^<><>$1*<a href=/s/^/$2/"
+ echo "/^$S$S$1*<a href=/s/^/$2/"
+ echo "/^<>$1<>*<a href=/s/^/$2/"
+ echo "/^$S$1$S*<a href=/s/^/$2/"
+ echo "/^$1<><>*<a href=/s/^/$2/"
+ echo "/^$1$S$S*<a href=/s/^/$2/"
+ echo "/^$1<>*<a href=/s/^/$2/"
+ echo "/^$1$S*<a href=/s/^/$2/"
+}
+
+echo_sp_sp ()
+{
+ echo "/^$1*<a name=/s/^/$2/"
+ echo "/^<>$1*<a name=/s/^/$2/"
+ echo "/^$S$1*<a name=/s/^/$2/"
+ echo "/^<><>$1*<a name=/s/^/$2/"
+ echo "/^$S$S$1*<a name=/s/^/$2/"
+ echo "/^<>$1<>*<a name=/s/^/$2/"
+ echo "/^$S$1$S*<a name=/s/^/$2/"
+ echo "/^$1<><>*<a name=/s/^/$2/"
+ echo "/^$1$S$S*<a name=/s/^/$2/"
+ echo "/^$1<>*<a name=/s/^/$2/"
+ echo "/^$1$S*<a name=/s/^/$2/"
+}
+
+make_sitemap_init()
+{
+ # build a list of detectors that map site.htm entries to a section table
+ # note that the resulting .gets.tmp / .puts.tmp are real sed-script
+ h1="[-|[]"
+ b1="[*=]"
+ b2="[-|[]"
+ b3="[\\/:]"
+ q3="[\\/:,[]"
+ echo_HR_PP "<hr>" "$h1" "<!--sect1-->" > "$MK_GETS"
+ echo_HR_EM_PP "<hr>" "<em>" "$h1" "<!--sect1-->" >> "$MK_GETS"
+ echo_HR_EM_PP "<hr>" "<strong>" "$h1" "<!--sect1-->" >> "$MK_GETS"
+ echo_HR_PP "<br>" "$b1$b1" "<!--sect1-->" >> "$MK_GETS"
+ echo_HR_PP "<br>" "$b2$b2" "<!--sect2-->" >> "$MK_GETS"
+ echo_HR_PP "<br>" "$b3$b3" "<!--sect3-->" >> "$MK_GETS"
+ echo_br_PP "<br>" "$b2$b2" "<!--sect2-->" >> "$MK_GETS"
+ echo_br_PP "<br>" "$b3$b3" "<!--sect3-->" >> "$MK_GETS"
+ echo_br_EM_PP "<br>" "<small>" "$q3" "<!--sect3-->" >> "$MK_GETS"
+ echo_br_EM_PP "<br>" "<em>" "$q3" "<!--sect3-->" >> "$MK_GETS"
+ echo_br_EM_PP "<br>" "<u>" "$q3" "<!--sect3-->" >> "$MK_GETS"
+ echo_HR_PP "<br>" "$q3" "<!--sect3-->" >> "$MK_GETS"
+ echo_sp_PP "$q3" "<!--sect3-->" >> "$MK_GETS"
+ echo_sp_sp "$q3" "<!--sect9-->" >> "$MK_GETS"
+ $SED -e "s/\\(>\\)\\(\\[\\)/\\1 *\\2/" "$MK_GETS" > "$MK_PUTS"
+ # the .puts.tmp variant is used to <b><a href=..></b> some hrefs which
+ # shall not be used otherwise for being generated - this is nice for
+ # some quicklinks somewhere. The difference: a whitspace "<hr> <a...>"
+}
+
+_uses_="=use\\1=\\2 \\3" ; _name_="=use\\1=name:\\2 \\3" ;
+_getW_="<!--sect\\([$NN]\\)-->"
+_getX_="<!--sect\\([$NN]\\)--><[^<>]*>[^<>]*"
+_getY_="<!--sect\\([$NN]\\)--><[^<>]*>[^<>]*<[^<>]*>[^<>]*"
+
+make_sitemap_list()
+{
+ # scan sitefile for references pages - store as "=use+=href+ anchortext"
+ $SED -f $MK_GETS -e "/^<!--sect[$NN]-->/!d" \
+ -e "s|^$_getX_<a href=\"\\([^\"]*\\)\"[^<>]*>\\(.*\\)</a>.*|$_uses_|" \
+ -e "s|^$_getY_<a href=\"\\([^\"]*\\)\"[^<>]*>\\(.*\\)</a>.*|$_uses_|" \
+ -e "s|^$_getW_<a name=\"\\([^\"]*\\)\"[^<>]*>\\(.*\\)</a>.*|$_name_|" \
+ -e "s|^$_getX_<a name=\"\\([^\"]*\\)\"[^<>]*>\\(.*\\)</a>.*|$_name_|" \
+ -e "s|^$_getY_<a name=\"\\([^\"]*\\)\"[^<>]*>\\(.*\\)</a>.*|$_name_|" \
+ -e "/^=....=/!d" "$SITEFILE" > "$MK_INFO"
+}
+
+make_sitemap_sect()
+{
+ # scan used pages and store prime section group relation =sect= and =node=
+ # (A) each "use1" creates "=sect=href+ href1" for all following non-"use1"
+ # (B) each "use1" creates "=node=href2 href1" for all following "use2"
+ $SED -e "/=use.=/!d" \
+ -e "/=use1=/{" -e "h" -e "s:=use1=\\([^ ]*\\) .*:\\1:" -e "x" -e "}" \
+ -e "s/=use.=\\([^ ]*\\) .*/=sect=\\1/" \
+ -e G -e "s:\\n: :" "$MK_INFO" >> "$MK_INFO"
+ $SED -e "/=use.=/!d" \
+ -e "/=use1=/{" -e "h" -e "s:=use1=\\([^ ]*\\) .*:\\1:" -e "x" -e "}" \
+ -e "/=use[13456789]=/d" \
+ -e "s/=use.=\\([^ ]*\\) .*/=node=\\1/" \
+ -e G -e "s:\\n: :" "$MK_INFO" >> "$MK_INFO"
+}
+
+make_sitemap_page()
+{
+ # scan used pages and store secondary group relation =page= and =node=
+ # the parenting =node= for use3 is usually a use2 (or use1 if none there)
+ $SED -e "/=use.=/!d" \
+ -e "/=use1=/{" -e "h" -e "s:=use1=\\([^ ]*\\) .*:\\1:" -e "x" -e "}" \
+ -e "/=use2=/{" -e "h" -e "s:=use2=\\([^ ]*\\) .*:\\1:" -e "x" -e "}" \
+ -e "/=use[1]=/d" \
+ -e "s/=use.=\\([^ ]*\\) .*/=page=\\1/" \
+ -e G -e "s:\\n: :" "$MK_INFO" >> "$MK_INFO"
+ $SED -e "/=use.=/!d" \
+ -e "/=use1=/{" -e "h" -e "s:=use1=\\([^ ]*\\) .*:\\1:" -e "x" -e "}" \
+ -e "/=use2=/{" -e "h" -e "s:=use2=\\([^ ]*\\) .*:\\1:" -e "x" -e "}" \
+ -e "/=use[12456789]=/d" \
+ -e "s/=use.=\\([^ ]*\\) .*/=node=\\1/" \
+ -e G -e "s:\\n: :" "$MK_INFO" >> "$MK_INFO"
+ # and for the root sections we register ".." as the parenting group
+ $SED -e "/=use1=/!d" \
+ -e "s/=use.=\\([^ ]*\\) .*/=node=\\1 ../" "$MK_INFO" >> "$MK_INFO"
+}
+echo_site_filelist()
+{
+ $SED -e "/=use.=/!d" -e "s/=use.=//" -e "s/ .*//" "$MK_INFO"
+}
+
+# ==========================================================================
+# originally this was a one-pass compiler but the more information
+# we were scanning out the more slower the system ran - since we
+# were rescanning files for things like section information. Now
+# we scan the files first for global information.
+# 1.PASS
+
+scan_sitefile () # $F
+{
+ SOURCEFILE=`html_sourcefile "$F"`
+ if test "$SOURCEFILE" != "$F" ; then
+ dx_init "$F"
+ dx_text today "`timetoday`"
+ short=`echo "$F" | $SED -e "s:.*/::" -e "s:[.].*::"` # basename for all exts
+ short="$short ~"
+ DC_meta title "$short"
+ DC_meta date.available "`timetoday`"
+ DC_meta subject sitemap
+ DC_meta DCMIType Collection
+ DC_VARS_Of "$SOURCEFILE" ; HTTP_VARS_Of "$SOURCEFILE"
+ DC_modified "$SOURCEFILE" ; DC_date "$SOURCEFILE"
+ DC_section "$F"
+ DX_text date.formatted `timetoday`
+ test ".$printerfriendly" != "." && \
+ DX_text "printerfriendly" `fast_html_printerfile "$F"`
+ test ".$USER" != "." && DC_publisher "$USER"
+ echo "'$SOURCEFILE': $short (sitemap)"
+ site_map_list_title "$F" "$short"
+ site_map_long_title "$F" "generated sitemap index"
+ site_map_list_date "$F" "`timetoday`"
+ fi
+}
+
+scan_htmlfile() # "$F"
+{
+ SOURCEFILE=`html_sourcefile "$F"` # SCAN :
+ if test "$SOURCEFILE" != "$F" ; then : # HTML :
+ if test -f "$SOURCEFILE" ; then make_fast "$F" > "$tmp/$F.$FAST"
+ dx_init "$F"
+ dx_text today "`timetoday`"
+ dx_text todays "`timetodays`"
+ DC_VARS_Of "$SOURCEFILE" ; HTTP_VARS_Of "$SOURCEFILE"
+ DC_title "$SOURCEFILE"
+ DC_isFormatOf "$SOURCEFILE"
+ DC_modified "$SOURCEFILE" ; DC_date "$SOURCEFILE" ; DC_date "$SITEFILE"
+ DC_section "$F" ; DC_selected "$F" ; DX_alternative "$SOURCEFILE"
+ test ".$USER" != "." && DC_publisher "$USER"
+ DX_text date.formatted "`timetoday`"
+ test ".$printerfriendly" != "." && \
+ DX_text "printerfriendly" `fast_html_printerfile "$F"`
+ sectn=`info_get_entry DC.relation.section`
+ short=`info_get_entry DC.title.selected`
+ site_map_list_title "$F" "$short"
+ info_map_list_title "$F" "$short"
+ title=`info_get_entry DC.title`
+ site_map_long_title "$F" "$title"
+ info_map_long_title "$F" "$title"
+ edate=`info_get_entry DC.date`
+ issue=`info_get_entry issue`
+ site_map_list_date "$F" "$edate"
+ info_map_list_date "$F" "$edate"
+ echo "'$SOURCEFILE': '$title' ('$short') @ '$issue' ('$sectn')"
+ else
+ echo "'$SOURCEFILE': does not exist"
+ site_map_list_title "$F" "$F"
+ site_map_long_title "$F" "$F (no source)"
+ fi ; else
+ echo "<$F> - skipped"
+ fi
+}
+
+scan_namespec ()
+{
+ # nothing so far
+ case "$1" in
+ name:sitemap:*)
+ short=`echo "$F" | $SED -e "s:.*/::" -e "s:[.].*::"`
+ short=`echo "$short ~" | $SED -e "s/name:sitemap://"`
+ site_map_list_title "$F" "$short"
+ site_map_long_title "$F" "external sitemap index"
+ site_map_list_date "$F" "`timetoday`"
+ echo "'$F' external sitemap index$n"
+ ;;
+ esac
+}
+scan_httpspec ()
+{
+ # nothing so far
+ return;
+}
+
+skip_namespec ()
+{
+ # nothing so far
+ return;
+}
+skip_httpspec ()
+{
+ # nothing so far
+ return;
+}
+
+# ==========================================================================
+# and now generate the output pages
+# 2.PASS
+
+head_sed_sitemap() # $filename $section
+{
+ FF="$1"
+ SECTION=`sed_slash_key "$2"`
+ SECTS="<!--sect[$NN$AZ]-->" ; SECTN="<!--sect[$NN]-->" # lines with hrefs
+ echo "/^$SECTS.*<a href=\"$FF\">/s|</a>|</a></b>|" # $++
+ echo "/^$SECTS.*<a href=\"$FF\">/s|<a href=|<b><a href=|" # $++
+ test ".$sectiontab" != ".no" && \
+ echo "/ href=\"$SECTION\"/s|^<td class=\"[^\"]*\"|<td |" # $++
+}
+
+head_sed_listsection() # $filename $section
+{
+ # traditional.... the sitefile is the full navigation bar
+ FF=`sed_slash_key "$1"`
+ SECTION=`sed_slash_key "$2"`
+ SECTS="<!--sect[$NN$AZ]-->" ; SECTN="<!--sect[$NN]-->" # lines with hrefs
+ echo "/^$SECTS.*<a href=\"$FF\">/s|</a>|</a></b>|" # $++
+ echo "/^$SECTS.*<a href=\"$FF\">/s|<a href=|<b><a href=|" # $++
+ test ".$sectiontab" != ".no" && \
+ echo "/ href=\"$SECTION\"/s|^<td class=\"[^\"]*\"|<td |" # $++
+}
+
+head_sed_multisection() # $filename $section
+{
+ # sitefile navigation bar is split into sections
+ FF=`sed_slash_key "$1"`
+ SECTION=`sed_slash_key "$2"`
+ SECTS="<!--sect[$NN$AZ]-->" ; SECTN="<!--sect[$NN]-->" # lines with hrefs
+ # grep all pages with a =sect= relation to current $SECTION and
+ # build foreach an sed line "s|$SECTS\(<a href=$F>\)|<!--sectX-->\1|"
+ # after that all the (still) numeric SECTNs are deactivated / killed.
+ for section in $SECTION $headsection $tailsection ; do
+ test ".$section" = ".no" && continue
+ $SED -e "/^=sect=[^ ]* $section/!d" \
+ -e "s, .*,\"\\\\)|<!--sectX-->\\\\1|," \
+ -e "s,^=sect=,s|^$SECTS\\\\(.*<a href=\"," "$MK_INFO" # $++
+ done
+ echo "s|^$SECTN[^ ]*\\(<a href=[^<>]*>\\).*|<!-- \\1 -->|" # $++
+ echo "/^$SECTS.*<a href=\"$FF\">/s|</a>|</a></b>|" # $++
+ echo "/^$SECTS.*<a href=\"$FF\">/s|<a href=|<b><a href=|" # $++
+ test ".$sectiontab" != ".no" && \
+ echo "/ href=\"$SECTION\"/s|^<td class=\"[^\"]*\"|<td |" # $++
+}
+
+make_sitefile () # "$F"
+{
+ SOURCEFILE=`html_sourcefile "$F"`
+ if test "$SOURCEFILE" != "$F" ; then
+ if test -f "$SOURCEFILE" ; then
+ # remember that in this case "${SITEFILE}l" = "$F" = "${SOURCEFILE}l"
+ info2vars_sed > $MK_VARS # have <!--title--> vars substituted
+ info2meta_sed > $MK_META # add <meta name="DC.title"> values
+ if test ".$simplevars" = ".warn" ; then
+ info2test_sed > $MK_TEST # check <!--title--> vars old-style
+ $SED_LONGSCRIPT "$MK_TEST" "$SOURCEFILE" | tee -a "$MK_OLDS" ; fi
+ F_HEAD="$tmp/$F.$HEAD" ; F_FOOT="$tmp/$F.$FOOT"
+ $CAT "$MK_PUTS" > "$F_HEAD"
+ head_sed_sitemap "$F" "`info_get_entry_section`" >> "$F_HEAD"
+ echo "/<head>/r $MK_META" >> "$F_HEAD"
+ $CAT "$MK_VARS" "$MK_TAGS" >> "$F_HEAD"
+ echo "/<\\/body>/d" >> "$F_HEAD"
+ case "$sitemaplayout" in
+ multi) make_multisitemap > "$F_FOOT" ;; # here we use ~foot~ to
+ *) make_listsitemap > "$F_FOOT" ;; # hold the main text
+ esac
+
+ mkpathfile "$F"
+ $SED_LONGSCRIPT "$F_HEAD" "$SITEFILE" > $F # ~head~
+ $CAT "$F_FOOT" >> $F # ~body~
+ $SED -e "/<\\/body>/!d" -f "$MK_VARS" "$SITEFILE" >> $F #</body>
+ echo "'$SOURCEFILE': " `ls -s $SOURCEFILE` ">->" `ls -s $F` "(sitemap)"
+ else
+ echo "'$SOURCEFILE': does not exist"
+ fi fi
+}
+
+make_htmlfile() # "$F"
+{
+ SOURCEFILE=`html_sourcefile "$F"` # 2.PASS
+ if test "$SOURCEFILE" != "$F" ; then
+ if test -f "$SOURCEFILE" ; then
+ if grep '<meta name="formatter"' "$SOURCEFILE" >/dev/null ; then
+ echo "$SOURCEFILE: SKIP, this sourcefile looks like a formatted file"
+ echo "$SOURCEFILE: (may be a sourcefile in place of a targetfile?)"
+ return
+ fi
+ info2vars_sed > $MK_VARS # have <!--$title--> vars substituted
+ info2meta_sed > $MK_META # add <meta name="DC.title"> values
+ if test ".$simplevars" = ".warn" ; then
+ info2test_sed > $MK_TEST # check <!--title--> vars old-style
+ $SED_LONGSCRIPT "$MK_TEST" "$SOURCEFILE" | tee -a "$MK_OLDS" ; fi
+ F_HEAD="$tmp/$F.$HEAD" ; F_BODY="$tmp/$F.$BODY" ; F_FOOT="$tmp/$F.$FOOT"
+ $CAT "$MK_PUTS" > "$F_HEAD"
+ case "$sectionlayout" in
+ multi) head_sed_multisection "$F" "`info_get_entry_section`" >> "$F_HEAD" ;;
+ *) head_sed_listsection "$F" "`info_get_entry_section`" >> "$F_HEAD" ;;
+ esac
+ $CAT "$MK_VARS" "$MK_TAGS" >> "$F_HEAD" #tag and vars
+ echo "/<\\/body>/d" >> "$F_HEAD" #cut lastline
+ echo "/<head>/r $MK_META" >> "$F_HEAD" #add metatags
+ echo "/<title>/d" > "$F_BODY" #not that line
+ $CAT "$MK_VARS" "$MK_TAGS" >> "$F_BODY" #tag and vars
+ bodymaker_for_sectioninfo >> "$F_BODY" #if sectioninfo
+ info2body_sed >> "$F_BODY" #cut early
+ info2head_sed >> "$F_HEAD"
+ $CAT "$tmp/$F.$FAST" >> "$F_HEAD"
+ test ".$emailfooter" != ".no" && \
+ body_for_emailfooter > "$F_FOOT"
+
+ mkpathfile "$F"
+ $SED_LONGSCRIPT "$F_HEAD" $SITEFILE > $F # ~head~
+ $SED_LONGSCRIPT "$F_BODY" $SOURCEFILE >> $F # ~body~
+ test -f "$F_FOOT" && $CAT "$F_FOOT" >> $F # ~foot~
+ $SED -e "/<\\/body>/!d" -f "$MK_VARS" "$SITEFILE" >> $F #</body>
+ echo "'$SOURCEFILE': " `ls -s $SOURCEFILE` "->" `ls -s $F`
+ else # test -f $SOURDEFILE
+ echo "'$SOURCEFILE': does not exist"
+ fi ; else
+ echo "<$F> - skipped"
+ fi
+}
+
+make_printerfriendly () # "$F"
+{ # PRINTER
+ printsitefile="0" # FRIENDLY
+ P=`html_printerfile "$F"`
+ F_FAST="$tmp/$F.$FAST"
+ P_HEAD="$tmp/$P.$HEAD"
+ P_BODY="$tmp/$P.$BODY"
+ case "$F" in
+ ${SITEFILE}|${SITEFILE}l) make_fast "$F" > "$F_FAST"
+ printsitefile=">=>" ; BODY_TXT="$tmp/$F.$FOOT" ;;
+ *.html) printsitefile="=>" ; BODY_TXT="$SOURCEFILE" ;;
+ esac
+ if grep '<meta name="formatter"' "$BODY_TXT" >/dev/null ; then return; fi
+ if test ".$printsitefile" != ".0" && test -f "$SOURCEFILE" ; then
+ make_printerfile_fast "$FILELIST" > ./$MK_FAST
+ $CAT "$MK_VARS" "$MK_TAGS" "$MK_FAST" > "$P_HEAD"
+ $SED -e "/DC.relation.isFormatOf/s|content=\"[^\"]*\"|content=\"$F\"|" \
+ "$MK_META" > "$MK_METT"
+ echo "/<head>/r $MK_METT" >> "$P_HEAD" # meta
+ echo "/<\\/body>/d" >> "$P_HEAD"
+ select_in_printsitefile "$F" >> "$P_HEAD"
+ _ext_=`print_extension "$printerfriendly"` # head-
+ $SED -e "s/[.]html\"|/$_ext_&/g" "$F_FAST" >> "$P_HEAD" # hrefs
+ # line_=`sed_slash_key "$printsitefile_img_2"` # back-
+ echo "/||topics:/s| href=\"[#][.]\"| href=\"$F\"|" >> "$P_HEAD"
+ echo "/|||pages:/s| href=\"[#][.]\"| href=\"$F\"|" >> "$P_HEAD"
+ $CAT "$F_FAST" >> "$P_HEAD" # subdir
+ $CAT "$MK_VARS" "$MK_TAGS" "$MK_FAST" > "$P_BODY"
+ $SED -e "s/[.]html\"|/$_ext_&/g" "$F_FAST" >> "$P_BODY" # body-
+ $CAT "$F_FAST" >> "$P_BODY" # hrefs
+
+ mkpathfile "$P"
+ $SED_LONGSCRIPT "$P_HEAD" $PRINTSITEFILE > $P # ~head~
+ $SED_LONGSCRIPT "$P_BODY" $BODY_TXT >> $P # ~body~
+ $SED -e "/<\\/body>/!d" -f $MK_VARS $PRINTSITEFILE >> $P #</body>
+ echo "'$SOURCEFILE': " `ls -s $SOURCEFILE` "$printsitefile" `ls -s $P`
+ fi
+}
+
+
+# ========================================================================
+# ========================================================================
+# ========================================================================
+
+# ========================================================================
+# #### 0. INIT
+make_sitemap_init
+make_sitemap_list
+make_sitemap_sect
+make_sitemap_page
+
+FILELIST=`echo_site_filelist`
+if test ".$opt_filelist" != "." || test ".$opt_list" = ".file"; then
+ for F in $FILELIST; do echo "$F" ; done ; exit # --filelist
+fi
+if test ".$opt_files" != "." ; then FILELIST="$opt_files" ; fi # --files
+if test ".$FILELIST" = "."; then echo "nothing to do" >&2 ; fi
+if test ".$FILELIST" = ".SITEFILE" ; then echo "only '$SITEFILE'?!" >&2 ; fi
+
+for F in $FILELIST ; do case "$F" in #### 1. PASS
+name:*) scan_namespec "$F" ;;
+http:*|*://*) scan_httpspec "$F" ;;
+${SITEFILE}|${SITEFILE}l) scan_sitefile "$F" ;; # ........... SCAN SITE
+../*)
+ echo "!! -> '$F' (skipping topdir build)"
+ ;;
+# */*.html)
+# make_fast > $F.$FAST # try for later subdir build
+# echo "!! -> '$F' (skipping subdir build)"
+# ;;
+# */*/*/|*/*/|*/|*/index.htm|*/index.html)
+# echo "!! -> '$F' (skipping subdir index.html)"
+# ;;
+*.html) scan_htmlfile "$F" ;; # ........... SCAN HTML
+*/) echo "'$F' : directory - skipped"
+ site_map_list_title "$F" "`sed_slash_key $F`"
+ site_map_long_title "$F" "(directory)"
+ ;;
+*) echo "?? -> '$F'"
+ ;;
+esac done
+
+if test ".$printerfriendly" != "." ; then # .......... PRINT VERSION
+ _ext_=`print_extension "$printerfriendly" | sed -e "s/&/\\\\&/"`
+ PRINTSITEFILE=`echo "$SITEFILE" | sed -e "s/\\.[$AA]*\$/$_ext_&/"`
+ echo "NOTE: going to create printer-friendly sitefile $PRINTSITEFILE"
+ make_printsitefile > "$PRINTSITEFILE"
+fi
+
+if test ".$simplevars" = ". " ; then
+mknewfile $MK_OLDS
+fi
+
+for F in $FILELIST ; do case "$F" in #### 2. PASS
+name:*) skip_namespec "$F" ;;
+http:*|*://*) skip_httpspec "$F" ;;
+${SITEFILE}|${SITEFILE}l) make_sitefile "$F" # ........ SITE FILE
+ if test ".$printerfriendly" != "." ; then make_printerfriendly "$F" ; fi ;;
+../*)
+ echo "!! -> '$F' (skipping topdir build)"
+ ;;
+# */*.html)
+# echo "!! -> '$F' (skipping subdir build)"
+# ;;
+# */*/*/|*/*/|*/|*/index.htm|*/index.html)
+# echo "!! -> '$F' (skipping subdir index.html)"
+# ;;
+*.html) make_htmlfile "$F" # .................. HTML FILES
+ if test ".$printerfriendly" != "." ; then make_printerfriendly "$F" ; fi ;;
+*/) echo "'$F' : directory - skipped"
+ ;;
+*) echo "?? -> '$F'"
+ ;;
+esac
+# .............. debug ....................
+ if test -d DEBUG && test -f "./$F" ; then
+ FFFF=`echo "$F" | sed -e s,/,:,g`
+ cp "$tmp/$F.$INFO" DEBUG/$FFFF.info.TMP
+ for P in tags vars meta page date list html sect info ; do
+ test -f $tmp/$MK.$P.tmp && cp $tmp/$MK.$P.tmp DEBUG/$FFFF.$P.tmp
+ test -f $tmp/$MK.$P.TMP && cp $tmp/$MK.$P.TMP DEBUG/$FFFF.$P.TMP
+ done
+ fi
+done
+
+if test ".$simplevars" = ".warn" ; then if test -f "$MK_OLDS" ; then
+oldvars=`cat "$MK_OLDS" | wc -l | $SED -e "s/ *//g"`
+if test "$oldvars" = "0" ; then
+echo "HINT: you have no simplevars in your htm sources, so you may want to"
+echo "hint: set the magic <!--mksite:nosimplevars--> in your $SITEFILE"
+echo "hint: which makes execution _faster_ actually in the 2. pass"
+echo "note: simplevars expansion was the oldstyle way of variable expansion"
+else
+echo "HINT: there were $oldvars simplevars found in your htm sources."
+echo "hint: This style of variable expansion will be disabled in the near"
+echo "hint: future. If you do not want change then add the $SITEFILE magic"
+echo "hint: <!--mksite:simplevars--> somewhere to suppress this warning"
+echo "note: simplevars expansion will be an explicit option in the future."
+echo "note: errornous simplevar detection can be suppressed with a magic"
+echo "note: hint of <!--mksite:nosimplevars--> in the $SITEFILE for now."
+fi fi fi
+
+rm $tmp/$MK.*.tmp
+if test ".$tmp_dir_was_created" != ".no" ; then rm $tmp/* ; rmdir $tmp ; fi
+exit 0
diff --git a/Build/source/libs/zziplib/docs/mmapped.htm b/Build/source/libs/zziplib/docs/mmapped.htm
new file mode 100644
index 00000000000..9ac35ece988
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/mmapped.htm
@@ -0,0 +1,226 @@
+<section> <date> 2005 </date>
+<H2> zzip/mmapped </H2> zip access for mmapped views
+
+<BLOCKQUOTE>
+ These routines are fully independent from the traditional zzip
+ implementation. They assume a readonly mmapped sharedmem block
+ representing a complete zip file. The functions show how to
+ parse the structure, find files and return a decoded bytestream.
+</BLOCKQUOTE>
+
+<section>
+<H3> zzip disk handle </H3>
+
+<P>
+ Other than with the <a href="fseeko.html">fseeko</a> alternative
+ interface there is no need to have an actual disk handle to the
+ zip archive. Instead you can use a bytewise copy of a file or
+ even use a mmapped view of a file. This is generally the fastest
+ way to get to the data contained in a zipped file. All it requires
+ is enough of virtual memory space but a desktop computer with a
+ a modern operating system will easily take care of that.
+</P>
+
+<P>
+ The zzipmmapped library provides a number of calls to create a
+ disk handle representing a zip archive in virtual memory. Per
+ default we use the sys/mmap.h (or MappedView) functionality
+ of the operating system. The <code>zzip_disk_open</code> will
+ open a system file descriptor and try to <code>zzip_disk_mmap</code>
+ the complete zip content. When finished with the zip archive
+ call <code>zzip_disk_close</code> to release the mapped view
+ and all management data.
+</P>
+
+<PRE>
+ ZZIP_DISK* zzip_disk_open(char* filename);
+ int zzip_disk_close(ZZIP_DISK* disk);
+
+ ZZIP_DISK* zzip_disk_new(void);
+ ZZIP_DISK* zzip_disk_mmap(int fd);
+ int zzip_disk_munmap(ZZIP_DISK* disk);
+ int zzip_disk_init(ZZIP_DISK* disk,
+ char* buffer, zzip_size_t buflen);
+</PRE>
+
+</section><section>
+<H3> reading the central directory </H3>
+
+<P>
+ To get access to a zipped file, you need a pointer to an entry in the
+ mmapped zip disk known under the type <code>ZZIP_DISK_ENTRY</code>.
+ This is again modelled after the <code>DIR_ENTRY</code> type in being
+ a representation of a file name inside the zip central directory. To
+ get an initial zzip disk entry pointer, use <code>zzip_disk_findfirst</code>,
+ to move the pointer to the next entry use <code>zzip_disk_findnext</code>.
+</P>
+<PRE>
+ extern ZZIP_ENTRY* zzip_disk_findfirst(FILE* disk);
+ extern ZZIP_ENTRY* zzip_disk_findnext(ZZIP_ENTRY* entry);
+</PRE>
+<P>
+ These two calls will allow to walk all zip archive members in the
+ order listed in the zip central directory. To actually implement a
+ directory lister ("zzipdir"), you need to get the name string of the
+ zzip entry. This is not just a pointer: the zzip disk entry is not
+ null terminated actually. Therefore we have a helper function that
+ will <code>strdup</code> the entry name as a normal C string:
+</P>
+<PRE>
+ #include &lt;zzip/mmapped.h&gt;
+ void _zzip_dir(char* filename)
+ {
+ ZZIP_DISK* disk = zzip_disk_open (filename);
+ if (! disk) return disk;
+ for (ZZIP_DISK_ENTRY* entry = zzip_disk_findfirst (disk);
+ entry ; entry = zzip_disk_findnext (entry)) {
+ char* name = zzip_disk_entry_strdup_name (entry);
+ puts (name); free (name);
+ }
+ }
+</PRE>
+
+</section><section>
+<H3> find a zipped file </H3>
+
+<P>
+ The central directory walk can be used to find any file in the
+ zip archive. The <code>zzipfseeko</code> library however provides
+ two convenience functions that allow to jump directly to the
+ zip disk entry of a given name or pattern. You are free to use
+ the returned <code>ZZIP_DISK_ENTRY</code> pointer for later calls
+ that type. There is no need to free this pointer as it is really
+ a pointer into the mmapped area of the <code>ZZIP_DISK</code>.
+ But do not forget to free that one via <code>zzip_disk_close</code>.
+</P>
+<PRE>
+ ZZIP_DISK_ENTRY* zzip_disk_findfile(ZZIP_DISK* disk, char* filename,
+ ZZIP_DISK_ENTRY* after,
+ zzip_strcmp_fn_t compare);
+
+ ZZIP_DISK_ENTRY* zzip_disk_findmatch(ZZIP_DISK* disk, char* filespec,
+ ZZIP_ENTRY* after,
+ zzip_fnmatch_fn_t compare, int flags);
+</PRE>
+<P>
+ In general only the first two arguments are non-null pointing to the
+ zip disk handle and the file name to look for. The "after" argument
+ is an old value and allows you to walk the zip directory similar to
+ <code>zzip_disk_entry_findnext</code> but actually leaping forward. The
+ compare function can be used for alternate match behavior: the default
+ of <code>strcmp</code> might be changed to <code>strncmp</code> for
+ a caseless match. The "flags" of the second call are forwarded to the
+ posix <code>fnmatch</code> which we use as the default function.
+</P>
+<P>
+ If you do know a specific zzipped filename then you can just use
+ <code>zzip_disk_entry_findfile</code> and supply the return value to
+ <code>zzip_disk_entry_fopen</code>. There is a convenience function
+ <code>zzip_disk_fopen</code> that will do just that and therefore
+ only requires a disk handle and a filename to find-n-open.
+</P>
+<PRE>
+ #include &lt;zzip/mmapped.h&gt;
+
+ int _zzip_read(ZZIP_DISK* disk, char* filename, void* buffer, int bytes)
+ {
+ ZZIP_DISK_FILE* file = zzip_disk_fopen (disk, filename);
+ if (! file) return -1;
+ int bytes = zzip_disk_fread (buffer, 1, bytes, file);
+ zzip_disk_fclose (file);
+ return bytes;
+ }
+</PRE>
+
+</section><section>
+<H3> reading bytes </H3>
+
+<P>
+ The example has shown already how to read some bytes off the head of
+ a zipped file. In general the zzipmmapped api is used to replace a few
+ system file routines that access a file. For that purpose we provide three
+ functions that look very similar to the stdio functions of
+ <code>fopen()</code>, <code>fread()</code> and <code>fclose()</code>.
+ These work on an active file descriptor of type <code>ZZIP_DISK_FILE</code>.
+</P>
+
+<PRE>
+ ZZIP_DISK_FILE* zzip_disk_entry_fopen (ZZIP_DISK* disk,
+ ZZIP_DISK_ENTRY* entry);
+ ZZIP_DISK_FILE* zzip_disk_fopen (ZZIP_DISK* disk, char* filename);
+ zzip_size_t zzip_disk_fread (void* ptr,
+ zzip_size_t sized, zzip_size_t nmemb,
+ ZZIP_DISK_FILE* file);
+ int zzip_disk_fclose (ZZIP_DISK_FILE* file);
+ int zzip_disk_feof (ZZIP_DISK_FILE* file);
+</PRE>
+
+<P>
+ In all of the examples you need to remember that you provide a single
+ <code>ZZIP_DISK</code> descriptor for a memory block which is in reality
+ a virtual filesystem on its own. Per default filenames are matched case
+ sensitive also on win32 systems. The findnext function will walk all
+ files on the zip virtual filesystem table and return a name entry
+ with the full pathname, i.e. including any directory names to the
+ root of the zip disk <code>FILE</code>.
+</P>
+
+</section><section>
+<H3> ZZIP_DISK_ENTRY inspection </H3>
+
+<P>
+ The <code>ZZIP_DISK_FILE</code> is a special file descriptor handle
+ of the <code>zzipmmapped</code> library - but the
+ <code>ZZIP_DISK_ENTRY</code> is not so special. It is actually a pointer
+ directly into the zip central directory managed by <code>ZZIP_DISK</code>.
+ While <code>zzip/mmapped.h</code> will not reveal the structure on its own,
+ you can include <code>zzip/format.h</code> to get access to the actual
+ structure content of a <code>ZZIP_DISK_ENTRY</code> by its definition
+<br><b><code>&nbsp;&nbsp;&nbsp;&nbsp;struct zzip_disk_entry</code></b>.
+</P>
+
+<P>
+ In reality however it is not a good idea to actually read the bytes
+ in the <code>zzip_disk_entry</code> structure unless you seriously know
+ the internals of a zip archive entry. That includes any byteswapping
+ needed on bigendian platforms. Instead you want to take advantage of
+ helper macros defined in <code>zzip/fetch.h</code>. These will take
+ care to convert any struct data member to the host native format.
+</P>
+<PRE>
+extern uint16_t zzip_disk_entry_get_flags( zzip_disk_entry* entry);
+extern uint16_t zzip_disk_entry_get_compr( zzip_disk_entry* entry);
+extern uint32_t zzip_disk_entry_get_crc32( zzip_disk_entry* entry);
+
+extern zzip_size_t zzip_disk_entry_csize( zzip_disk_entry* entry);
+extern zzip_size_t zzip_disk_entry_usize( zzip_disk_entry* entry);
+extern zzip_size_t zzip_disk_entry_namlen( zzip_disk_entry* entry);
+extern zzip_size_t zzip_disk_entry_extras( zzip_disk_entry* entry);
+extern zzip_size_t zzip_disk_entry_comment( zzip_disk_entry* entry);
+extern int zzip_disk_entry_diskstart( zzip_disk_entry* entry);
+extern int zzip_disk_entry_filetype( zzip_disk_entry* entry);
+extern int zzip_disk_entry_filemode( zzip_disk_entry* entry);
+
+extern zzip_off_t zzip_disk_entry_fileoffset( zzip_disk_entry* entry);
+extern zzip_size_t zzip_disk_entry_sizeof_tail( zzip_disk_entry* entry);
+extern zzip_size_t zzip_disk_entry_sizeto_end( zzip_disk_entry* entry);
+extern char* zzip_disk_entry_skipto_end( zzip_disk_entry* entry);
+</PRE>
+
+<P>
+ Additionally the <code>zzipmmapped</code> library has two additional
+ functions that can convert a mmapped disk entry to (a) the local
+ file header of a compressed file and (b) the start of the data area
+ of the compressed file. These are used internally upon opening of
+ a disk entry but they may be useful too for direct inspection of the
+ zip data area in special applications.
+</P>
+<PRE>
+ char* zzip_disk_entry_to_data(ZZIP_DISK* disk,
+ struct zzip_disk_entry* entry);
+ struct zzip_file_header*
+ zzip_disk_entry_to_file_header(ZZIP_DISK* disk,
+ struct zzip_disk_entry* entry);
+</PRE>
+
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/referentials.htm b/Build/source/libs/zziplib/docs/referentials.htm
new file mode 100644
index 00000000000..3ba1171e32c
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/referentials.htm
@@ -0,0 +1,65 @@
+<section><date> 15. July 2002 </date>
+<h2> ZZIP Referentials </h2> Where is it used.
+
+<!--noborder-->
+
+<section>
+<h3> GPL Rant </h3>
+
+<BLOCKQUOTE>
+ The GPL/LGPL do not have a clause like MPL and others to notify the
+ original author about certain usages of the library - that's a pity
+ since I do not get to know many of the areas where zziplib has come
+ to be used. I can only ask you to send me an e-mail, so I can put a
+ link from here to your project. Within thousands of downloads less
+ than a handful of people wrote to me - mostly for having found a bug
+ or having a feature request. Be nice, and write even if you have had
+ successfully implanted zziplib in your project... I love to hear that ;-)
+</BLOCKQUOTE>
+
+</section><section>
+<h3> opensource games </h3>
+
+<BLOCKQUOTE>
+ Although the library has not been written focusing on game data,
+ it has it greatest success just there. The SDL-rwops example did
+ further it by great amounts, people just like it to have the
+ thousand of small bitmaps to be assembled into one big dat file,
+ and put the AI scripts just next to them.
+</BLOCKQUOTE>
+
+<ul><li> Underworld Adventures: <br>
+<a href="http://uwadv.sourceforge.net">
+ http://uwadv.sourceforge.net</a>
+</li></ul>
+
+</section><section>
+<h3> opensource apps/libs </h3>
+
+<BLOCKQUOTE>
+ Here the most important feature has been the smalls size of this
+ library and the possible to use its autoconf script and even for
+ those who don't, it is easy to make a custom configuration. The
+ source code is easy to understand and therefore to customize for
+ the needs of the app/lib that wants to use the functionality.
+</BLOCKQUOTE>
+
+<ul><li> PHP ZIP Module <br>
+<a href="http://www.php.net/manual/en/ref.zip.php">
+ http://www.php.net/manual/en/ref.zip.php</a>
+</li></ul>
+
+</section><section>
+<h3> commercial usage </h3>
+
+<BLOCKQUOTE>
+ For commercial usage, you can bind many small files into a zip
+ file for easier handling. Obfuscation and io-wrapping help
+ greatly to implant it in areas even far from posix-io grounds.
+</BLOCKQUOTE>
+
+<ul><li> Media Portal Backside <br>
+<a href="http://www.appwares.com">
+ http://www.appwares.com</a>
+</li></ul>
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/sfx-make.htm b/Build/source/libs/zziplib/docs/sfx-make.htm
new file mode 100644
index 00000000000..5e092e47a11
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/sfx-make.htm
@@ -0,0 +1,167 @@
+<section> <date> February 2003 </date>
+<h2> SFX-Make </h2> combining an EXE with a ZIP archive
+
+<!--border-->
+
+<section>
+<h3> How To </h3>
+<P>
+ In this section we walk you through the steps of combining an EXE
+ with a ZIP archive. The basic scheme goes like this: the final
+ file will have an EXE starting at offset null, followed by the
+ data entries of a ZIP archive. The <em>last</em> part of the ZIP
+ archive is the ZIP central-directory which ends at the end of the file.
+</P>
+<P>
+ The basic problem lies in the fact that the zip central-directory
+ entries reference their data section with an offset from the
+ start-of-file so that you can not just append a zip archive after
+ an exe stub. The trick goes like adding the EXE as the first data
+ part of the ZIP archive - so that the offsets for each entry will
+ be correct when we are finished with it.
+</P>
+<P>
+ Again, one can not just use a zip tool to put the EXE as the first
+ part - since each data part is preceded with an infoblock of a
+ few bytes. The data of the first data part will therefore not
+ start at offset zero. We solve this problem with moving the data
+ a few bytes later - so that the final file will not start with a
+ "PK" magic (from the zip info header) but with an "MZ" or "ELF"
+ magic (from the exe info header).
+</P>
+
+</section><section>
+<h3> Step 1: Creating The Zip Combination </h3>
+<P>
+ Choose your exe file (example.exe) and wrap that file into a
+ zip container - ensure that the zip tool does <em>not</em>
+ use any compression algorithm on the data. This is usually
+ done with saying "zero compression level" as an option to
+ the zip tool. Also note that <em>no other</em> file is
+ wrapped as some zip tools reorder the entries from the
+ order on the command line to alphabetic order. Here is an
+ example with infozip's `zip` (e.g. on linux):
+ <pre> zip -0 -j example.zip example.exe </pre>
+</P>
+<P>
+ There is no zip tool that would reorder the data entries in
+ an existing zip archive. This mode is used here - the real
+ compressed data entries can now be added to the existing
+ zip archive that currently just wraps the exe part. With
+ specifying maximum compression ("-9" = compression level 9)
+ and throwing away any subdirectory part ("-j" = junk path)
+ it might look like
+ <pre> zip -9 -j example.zip data/* </pre>
+</P>
+<P>
+ Now we need to move the exe part by a few bytes to the
+ real start of the file. This can be done as easily as
+ writing the exe file again on to the start of the file.
+ However, one can not just use a shell-direction or
+ copy-operation since that would truncate (!!) the zip
+ file to the length of the exe part. The overwrite-operation
+ must be done without truncation. For maximum OS independence
+ the zziplib ships with a little tool in "test/zzipsetstub.c"
+ that you can reuse for this task:
+ <pre> zzipsetstub example.zip example.exe </pre>
+</P>
+<P>
+ This is it - the `unzip` tool can still access all data
+ entries but the first EXE - the first EXE will be listed
+ in the central-directory of the ZIP archive but one can
+ not extract the data since the "PK" magic at offset null
+ has been overwritten with the EXE magic. The data of all
+ the other entries can still be extracted with a normal
+ `unzip` tool - or any tool from the zziplib be used for
+ the same task.
+</P>
+
+</section><section>
+<h3> Step 2: Accessing The Data From The Program </h3>
+
+<P>
+ There is an example in test/zzipself.c that show how to do
+ it. The OS will provide each program with its own name in
+ argv[0] of the main() routine. This program file (!!) is
+ also the zip archive that carries the compressed data
+ entries along. Therefore, we can just issue a zzip_opendir
+ on argv[0] to access the zip central-directory.
+</P>
+<P>
+ Likewise one can open a file within it by just prepending
+ the string argv[0] to the filename stem, i.e. you could
+ do like
+ <pre> ZZIP_FILE* f = zzip_fopen ("example.exe/start.gif", "rbi")</pre>
+</P><P>
+ however you are advised to use the _ext_io cousin to be
+ platform independet - different Operating Systems use
+ different file extensions for executables, it's not always
+ an ".exe".
+</P>
+<P>
+ Once the file is opened, the data can be zzip_fread or
+ passed through an SDL_rwops structure into the inner
+ parts of your program.
+</P>
+
+</section><section>
+<h3> Step 3: Using Obfuscation Along </h3>
+
+<P>
+ The next level uses obfuscatation on the data part of the
+ application. That way there is no visible data to be seen
+ from outside, it looks like it had been compiled right into
+ the C source part. One can furthermore confuse a possible
+ attacker with staticlinking the zziplib into the executable
+ (this is possible in a limited set of conditions).
+</P>
+<P>
+ The first pass is again in creating the zip - here we must
+ ensure that only the ZIP archive part is obfuscated but
+ the EXE part must be plain data so that the operationg
+ system can read and relocate it into main memory. Using
+ xor-obfuscation this is easy - applying xor twice will
+ yield the original data. The steps look like this now:
+ <pre>
+ zzipxorcopy example.exe example.xor
+ zip -0 application.zip example.xor
+ zip -9 application.zip data/*
+ zzipsetstub application.zip example.xor
+ zzipxorcopy application.zip application.exe
+ </pre>
+</P>
+<P>
+ In the second step the open-routine in your application
+ needs to be modified - there are quite some examples in
+ the zziplib that show you how to add an xor-read routine
+ and passing it in the "io"-part of an zzip_open_ext_io
+ routine (see zzipxorcat.c).
+ <pre>
+ static int xor_value = 0x55;
+
+ static zzip_ssize_t xor_read (int f, void* p, zzip_size_t l)
+ {
+ zzip_ssize_t r = read(f, p, l);
+ zzip_ssize_t x; char* q; for (x=0, q=p; x &lt; r; x++) q[x] ^= xor_value;
+ return r;
+ }
+
+ static struct zzip_plugin_io xor_handlers;
+ static zzip_strings_t xor_fileext[] = { ".exe", ".EXE", "", 0 };
+
+ main(...)
+ {
+ zzip_init_io (&amp;xor_handlers, 0); xor_handlers.read = &amp;xor_read;
+
+ ZZIP_FILE* fp = zzip_open_ext_io (filename,
+ O_RDONLY|O_BINARY, ZZIP_CASELESS|ZZIP_ONLYZIP,
+ xor_fileext, &amp;xor_handlers);
+ ....
+ </pre>
+</P>
+<P>
+ You may want to pick your own xor-value instead of the default 0x55,
+ the zziplib-shipped tool `zzipxorcopy` does know an option to just
+ set the xor-value with which to obfuscate the data.
+</P>
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/zzip-api.htm b/Build/source/libs/zziplib/docs/zzip-api.htm
new file mode 100644
index 00000000000..79bed1401d4
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/zzip-api.htm
@@ -0,0 +1,30 @@
+<section> <date> 20. July 2002 </date>
+<h2> ZZIP Programmers Interface </h2> The complete API description.
+
+<!--border-->
+
+<P>
+ The zzip library was orginally developped by Tomi Ollila as a
+ set of zip decoder routines. Guido Draheim did pick it up and
+ wrapped them under a call synopsis matching their posix
+ api calls. Therefore <code>zzip_open()</code> has the same
+ synopsis as <code>open(2)</code> but it can open zipped files.
+ Later the distinction was made between magic wrappers and apis
+ for direct access to zip archives and the files contained
+ in the archive.
+</P>
+<P>
+ These (three) functional apis have little helper functions
+ alongside including those to get the posix filehandle out of a
+ zzip handle and to get some attributes about the data handle
+ represented by a zzip handle. Plus checking for error codes
+ that may have been generated from internal checks.
+</P>
+
+<dl>
+<dt> <a href="zzip-basics.html">Basics</a> </dt>
+<dd> Magic Wrappers, Zip Archive Dir access, Zipped File access </dd>
+<dt> <a href="zzip-extras.html">Extras</a> </dt>
+<dd> ext/io init, StdC calls, Error defs, ReOpen, FileStat </dd>
+</dl>
+</section>
diff --git a/Build/source/libs/zziplib/docs/zzip-basics.htm b/Build/source/libs/zziplib/docs/zzip-basics.htm
new file mode 100644
index 00000000000..0d0504710e7
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/zzip-basics.htm
@@ -0,0 +1,163 @@
+<section> <date> 20. July 2002 </date>
+<h2> ZZIP API Basics </h2> The open/close API description.
+
+<!--border-->
+
+<section>
+<h3> Basics </h3>
+
+<P>
+ The naming schem of functions in this library follow a simple rule:
+ if you see a function with a <code>zzip_</code> prefix followed by
+ compact name representing otherwise a C library or posix function then
+ it is a magic wrapper that can automagically handle both real
+ files/directories or zip-contained files. This includes:
+</P>
+<table cellpadding=10 width=100%><tr><td><table width=100% border=1>
+ <tr><td width=50%> zzip_opendir </td><td width=50%> opendir </td></tr>
+ <tr><td width=50%> zzip_readdir </td><td width=50%> readdir </td></tr>
+ <tr><td width=50%> zzip_closedir </td><td width=50%> closedir </td></tr>
+ <tr><td width=50%> zzip_rewinddir </td><td width=50%> rewinddir </td></tr>
+ <tr><td width=50%> zzip_telldir </td><td width=50%> telldir </td></tr>
+ <tr><td width=50%> zzip_seekdir </td><td width=50%> seekdir </td></tr>
+</table></td></tr></table>
+<P>
+ The ZZIP_DIR handle can wrap both a real directory or a zip-file.
+ Note that you can not open a virtual directory <em>within</em> a
+ zip-file, the ZZIP_DIR is either a real DIR-handle of a real
+ directory or the reference of ZIP-file but never a DIR-handle
+ within a ZIP-file - there is no such schema of a SUB-DIR handle
+ implemented in this library. A ZZIP_DIR does actually represent
+ the central directory of a ZIP-file, so that each file entry in
+ this ZZIP-DIR can possibly have a subpath prepended.
+</P>
+
+<P>
+ This form of magic has historic reasons as originally the
+ magic wrappers of this library were not meant to wrap a complete
+ subtree of a real file tree but only a single directory being
+ wrapped with into a zip-file and placed instead. Later proposals
+ and patches were coming in to support subtree wrapping by not
+ only making a split between the dir-part and file-part but
+ going recursivly up through all "/"-dirseparators of a filepath
+ given to <code>zzip_open</code> and looking for zip-file there.
+</P>
+
+<P>
+ To open a zip-file unconditionally one should be using their
+ respective methods that would return a ZZIP_DIR handle being
+ the representant memory instance of a ZIP-DIR, the central
+ directory of a zip-file. From that ZZIP-DIR one can open a
+ compressed file entry which will be returned as a ZZIP_FILE
+ pointer.
+</P>
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_dir_open </td>
+ <td width=50%> open a zip-file and parse the central directory
+ to a memory shadow</td></tr>
+ <tr><td width=50%> zzip_dir_close </td>
+ <td width=50%> close a zip-file and free the memory shadow</td></tr>
+ <tr><td width=50%> zzip_dir_fdopen </td>
+ <td width=50%> aquire the given posix-file and try to parse it
+ as a zip-file.</td></tr>
+ <tr><td width=50%> zzip_dir_read </td>
+ <td width=50%> return the next info entry of a zip-file's central
+ directory - this would include a possible subpath </td></tr>
+</table></td></tr></table>
+
+<P>
+ To unconditionally access a zipped-file (as the counter-part of a
+ zip-file's directory) you should be using the functions having a
+ <code>zzip_file_</code> prefix which are the methods working on
+ ZZIP_FILE pointers directly and assuming those are references of
+ a zipped file with a ZZIP_DIR.
+</P>
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_file_open </td>
+ <td width=50%> open a file within a zip and prepare a zlib
+ compressor for it - note the ZZIP_DIR argument,
+ multiple ZZIP_FILE's may share the same central
+ directory shadow.</td></tr>
+ <tr><td width=50%> zzip_file_close </td>
+ <td width=50%> close the handle of zippedfile
+ and free zlib compressor of it</td></tr>
+ <tr><td width=50%> zzip_file_read </td>
+ <td width=50%> decompress the next part of a compressed file
+ within a zip-file</td></tr>
+</table></td></tr></table>
+<P>
+ From here it is only a short step to the magic wrappers for
+ file-access - when being given a filepath to zzip_open then
+ the filepath is checked first for being possibly a real file
+ (we can often do that by a <code>stat</code> call) and if there is
+ a real file under that name then the returned ZZIP_FILE is
+ nothing more than a wrapper around a file-descriptor of the
+ underlying operating system. Any other calls like zzip_read
+ will see the realfd-flag in the ZZIP_FILE and forward the
+ execution to the read() function of the underlying operating system.
+</P>
+
+<P>
+ However if that fails then the filepath is cut at last directory
+ separator, i.e. a filepath of "this/test/README" is cut into the
+ dir-part "this/test" and a file-part "README". Then the possible
+ zip-extensions are attached (".zip" and ".ZIP") and we check if
+ there is a real file under that name. If a file "this/test.zip"
+ does exist then it is given to zzip_dir_open which will create
+ a ZZIP_DIR instance of it, and when that was successul (so it
+ was in zip-format) then we call zzip_file_open which will see
+ two arguments - the just opened ZZIP_DIR and the file-part. The
+ resulting ZZIP_FILE has its own copy of a ZZIP_DIR, so if you
+ open multiple files from the same zip-file than you will also
+ have multiple in-memory copies of the zip's central directory
+ whereas otherwise multiple ZZIP_FILE's may share a common
+ ZZIP_DIR when being opened with zzip_file_open directly - the
+ zzip_file_open's first argument is the ZZIP_DIR and the second
+ one the file-part to be looked up within that zip-directory.
+</P>
+
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_open </td>
+ <td width=50%> try the file-path as a real-file, and if not
+ there, look for the existance of ZZIP_DIR by
+ applying extensions, and open the file
+ contained within that one.</td></tr>
+ <tr><td width=50%> zzip_close </td>
+ <td width=50%> if the ZZIP_FILE wraps a real-file, then call
+ read(), otherwise call zzip_file_read() </td></tr>
+ <tr><td width=50%> zzip_close </td>
+ <td width=50%> if the ZZIP_FILE wraps a real-file, then call
+ close(), otherwise call zzip_file_close() </td></tr>
+</table></td></tr></table>
+
+<P>
+ Up to here we have the original functionality of the zziplib
+ when I (Guido Draheim) created the magic functions around the work from
+ Tomi Ollila who wrote the routines to read and decompress files from
+ a zip archive - unlike other libraries it was quite readable and
+ intelligible source code (after many changes there is not much
+ left of the original zip08x source code but that's another story).
+ Later however some request and proposals and patches were coming in.
+</P>
+
+<P>
+ Among the first extensions was the recursive zzip_open magic. In
+ the first instance, the library did just do as described above:
+ a file-path of "this/test/README" might be a zip-file known as
+ "this/test.zip" containing a compressed file "README". But if
+ there is neither a real file "this/test/README" and no real
+ zip-file "this/test.zip" then the call would have failed but
+ know the zzip_open call will recursivly check the parent
+ directories - so it can now find a zip-file "this.zip" which
+ contains a file-part "test/README".
+</P>
+
+<P>
+ This dissolves the original meaning of a ZZIP_DIR and it has lead
+ to some confusion later on - you can not create a DIRENT-like handle
+ for "this/test/" being within a "test.zip" file. And actually, I did
+ never see a reason to implement it so far (open "this.zip" and set
+ an initial subpath of "test" and let zzip_readdir skip all entries
+ that do not start with "test/"). This is left for excercie ;-)
+</P>
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/zzip-crypt.htm b/Build/source/libs/zziplib/docs/zzip-crypt.htm
new file mode 100644
index 00000000000..9d55ba97215
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/zzip-crypt.htm
@@ -0,0 +1,92 @@
+<section> <date> 15. July 2002 </date>
+<h2> ZIP Std Encryption </h2> Standard Zip Encryption is Weak!
+
+<!--border-->
+
+<section>
+<h3> Some rationale </h3>
+
+<P>
+ Some people might ask why not adding standard zip-encryption. Well,
+ first of all the standard zip-encryption has not been strong enough
+ for modern computers, and there are hacker tools that even a
+ half-literate computer-user can use to crack the password of a
+ zip-archive. In other words: <b> every encrypted zip file can be
+ cracked using freely downloadable helper tools </b>. That's because
+ standard zip encryption is weak regarding modern personal computer
+ power. Furthermore, adding <em>real</em> encryption is a heavy weight
+ that many people do not need, see the last argument for seeing the
+ standard one is useless anyway, and adding a non-standard one
+ should not be the case of the standard zziplib either, ye know.
+</P><P>
+ On the other hand, obfuscation is a means to fear off half-literates
+ just as well - there are no <em>premade</em> tools for the obfuscation you
+ can invent from the xor examples. And a hacker that can de-obfuscate
+ such a dat-file is able to dissassemble your program as well - just to
+ remind you that the disassembly of a program will reveal the decryption
+ routine <em>and</em> the decryption key, even for a heavyweight crypt
+ algorithm. Although there is a difference, it just ranges on about times
+ and exprience, not magnitudes. Remember the old saying: you can irritate
+ some people for some time but not irritate all people for all the time.
+ As for encryption of artwork and AI scripts in games and applications,
+ just keep in mind that the final recipient has the decryption key on
+ his system anyway, just obfuscated. So each such encryption is nothing
+ more than just a clever form of obfuscation, nothing mathematical strong.
+</P><P>
+ Some other people might ask why to obfuscate anyway. Well, the reason
+ is theft. Even people who write opensource free software generally
+ like to get some reward for what they do, some fame or atleast some
+ sweet dream to have helped the world go a bit easier in the future.
+ As for program text this is quite natural for the programmers who
+ pick up some code from somewhere else - it happens that most of them
+ have gone through some formation and they know how hard it is to get
+ even some lines of code out of your brain. This is not the case for
+ some artwork and AI parameters, people do not have much respect for
+ those - they just pick it up, put it under their umbrella, and
+ that's it - they even claim they could have done that themselves,
+ and in most cases it is that they never have been really trying to
+ do it and think of it as being comparable to that action-art they've
+ seen on TV.
+</P><P>
+ Just be sure that there is nothing wrong with obfuscating
+ things for a binary distribution of your program even for the
+ opensource case - the program text itself is an obfuscation in its
+ source form when being compiled into cpu instructions. Still, the
+ interested people can get hold of the source code since you provide
+ it somewhere and actually the original programmers like to hear
+ from literate people who could help with modifying the project. The
+ same is true for you artwork and AI scripts, the interested people
+ can still see them in the opensource project material, but only
+ those will look who dare to, not just the halfwit next door.
+</P><P>
+ Well, you do not need to that on the other hand - ID software has
+ shown that it can be very helpful since people will start to
+ write new maps and new bots, pack them and publish them. An open
+ data format is a form of attraction for people who can use a
+ graphics program and an editor but who do not know how to program.
+ And if you use obfuscation within an opensource program, it is
+ surely enought to just use the xor-format presented here, so that
+ it easy for third people to get involved if they want to, they
+ just have to rewrite their new datapacks with zzxorcopy, and
+ that's it.
+</P><P>
+ As for the non-opensource projects, be aware that there are
+ some ways to even staticlink the zziplib into your project, so
+ you can even hide that you used zip tools to create your dat files.
+ This is well enough for anyone to do - as soon as a hacker will
+ get to the point to notice you used a zip format, he would have
+ had found any other deobfusation or decryption routine as well.
+ If you are frightened, just encrypt the executable with tools
+ you bought from somewhere else. On the other hand, should there
+ be problems or bugs, you have an easier time to find them when
+ they could be caused by your dat entries, and it is again easy
+ to send a fixup file to your clients, since the command line
+ tools are just a breeze compared with some other anti-hacking
+ tools you'll find on the market.
+</P><P>
+ Well, hope this is enough rationale to tell you that I do not
+ see a need to implement anything more than obfuscation within
+ zziplib - if you need real encryption, use real encryption
+ software and its fileformat that supports it, not zip files.
+</P>
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/zzip-cryptoid.htm b/Build/source/libs/zziplib/docs/zzip-cryptoid.htm
new file mode 100644
index 00000000000..ee6b120d7f9
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/zzip-cryptoid.htm
@@ -0,0 +1,106 @@
+<section> <date> 11. May 2004 </date>
+<h2> ZIP Ext Encryption </h2> ext/io used for cryptoid plugins
+
+<!--border-->
+
+<section>
+<h3> Stronger Obfuscation For ZZip </h3>
+
+<P>
+ Some people feel that a simple bytewise xor is not strong enough
+ as an obfuscation for the data. There we have the question how to
+ implant a stronger obfuscation routine to protect that data of an
+ application from artwork theft. Perhaps there is even the idea to
+ use an obfuscation in the range of a real crypt routine - in which
+ case I want to recommend strongly to read the
+ <a href="zzip-crypt.html"> reasoning page </a> why it can not be
+ real encryption and that the resulting obfuscation has an upper
+ limit being <em>lower</em> than the crypt routine complexity.
+</P>
+
+<P>
+ After reminding you of this fact we can go at evaluationg how to
+ implant a stronger obfusction routine to protect your data. The
+ ext/io feature uses a callback routine "read" that must read a
+ block of the given size - for the obfuscation case it will call
+ the "read()" function of the underlying operation system, and
+ the obfuscated block will be deobfuscated before returning it to
+ the caller.
+</P>
+
+<P>
+ In this mechanism there is not asseration at which file-offset
+ the ext/io-read() callback is triggered. That is the reason we
+ have shown obfuscation with bytewise xor-key example - formally
+ this is using obfuscation blocks of 8bit width being aligned
+ on 8bit boundaries in the data file, and our decryption stream
+ is stateless being the same for each obfuscation block (of 8bit
+ width).
+</P>
+<P>
+ In order for a stronger obfuscation we have to break those
+ limitations which are directly derived from the natural way
+ of the handling of files by a contemporary operating system.
+ This is triggered as the call synopsis of the ext/io read()
+ callback matches <em>exactly</em> the one of posix, so that
+ one can use the posix read() function reference as the default
+ for ensuring the most minimal overhead in accessing non-obfuscated
+ zip files.
+<br><small>And btw, the abbreviation "posix" stands for
+ "Portable Open System in Unix".</small>
+</P>
+
+<P>
+ The trick we show here: the first argument of the ext/io read
+ callback is the file descriptor of the underlying operationg
+ system. While we can not add another argument to the ext/io
+ read call we can pick up additional information with the help
+ of that file descriptor id being globally unique even across
+ multiple threads. One solution would make the application map
+ that descriptor id to a special argument but this is often too
+ much overhead: the current file position is enough.
+</P>
+<P>
+ The current file position is managed by the operation system
+ via the file descriptor table. There is a function call to
+ map a file descriptor to the current read position offset
+ usually named "tell(fd)". Since this call is not mandated by
+ posix, you can emulate it with the posix lseek() call which
+ returns the resulting offset after the operation was performed,
+ so we just seek by a zero offset: <br><code>
+ <> <> <> <> #define tell(fd) lseek(fd,0,SEEK_CUR)
+</code>
+</P>
+
+<P>
+ That file offset is measured from the start of the zip archive,
+ not per each zipped file. Remind yourself of that fact when
+ creating your own "zzobfuscate.exe" which should work on the
+ zip archive and not per file before zipping. That is a difference
+ over normal zip archives where the user can atleast recognized the
+ dat file as a zip archive and see a list of files contained in the
+ archive, atleast their names and data start offset.
+</P>
+<P>
+ Now, let's use the file read offset to break the blocking
+ limitations of 8bit/8bit to a larger xor-key. In our example
+ we expand to a 32bit/32bit xor-key giving a search space of
+ 4<>billion keys instead of the just 256<>keys in 8bit blocking.
+ That is simply done by a static 4<>byte xor-key sequence and using
+ modulo operations for alignment. For the 2^X cases any modulo
+ operations shrink to a set of ultra-fast bitwise-and operations.
+</P>
+
+<pre>
+ static char xor_value[4] = { 0x55, 0x63, 0x27, 0x31 };
+ static zzip_ssize_t xor_read (int f, void* p, zzip_size_t l)
+ {
+ zzip_off_t y = tell(f);
+ zzip_size_t r = read(f, p, l);
+ zzip_size_t x; char* q = p;
+ for (x=0; x &lt; r; x++) q[x] ^= xor_value[(y+x)&amp;3];
+ return r;
+ }
+</pre>
+
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/zzip-extio.htm b/Build/source/libs/zziplib/docs/zzip-extio.htm
new file mode 100644
index 00000000000..c7c47f1a37d
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/zzip-extio.htm
@@ -0,0 +1,188 @@
+<section> <date>15. July 2002 </date>
+<h2> ZZIP-EXT/IO </h2> Customizing the file access
+
+<!--border-->
+
+<section>
+<h3> The EXT/IO calls </h3>
+
+<P>
+ There were quite some requests from game developers and graphics-apps
+ developers who wanted various extensions to be included into the
+ <a href="zziplib.html">zziplib library</a>, but most of them were
+ only of specific usage. After some discussions we came up with a
+ model to customize the <a href="zziplib.html">zziplib library</a>
+ calls in a number of ways - and adding two or three arguments to
+ the zzip_* calls. The standard <a href="zziplib.html">zziplib library</a>
+ will actually call these *_ext_io functions with these extra arguments
+ to be set to zero.
+</P><P>
+ The EXT feature describes a way to customize the extensions used in
+ the magic wrapper to find a .ZIP file. It turned out that there are
+ quite a number of applications that did chose the zip file format as
+ their native document format and where just the file extension had
+ been changed. This includes file types like Quake3 ".PK3" files from
+ ID Software, the Java library files called ".JAR", and lately the
+ OpenOffice-6 (resp. StarOffice-6) documents which carry xml-files along.
+ Just build a zero-termined string-list of file-extensions and submit it
+ to the _ext_io calls to let the <a href="zziplib.html">zziplib</a> find
+ parts of those zip-documents automagically.
+</P><P>
+ In quite some of these cases, it is very benefical to make use of the
+ o_modes functionality that allows to submit extra bit-options into
+ the <a href="zziplib.html">zziplib</a> - this includes options like
+ <code>ZZIP_PREFERZIP</code> or even <code>ZZIP_ONLYZIP</code> which
+ modifies the default behaviour of looking for real files first instead
+ of some within a zipped directory tree. Other bit-options include
+ <code>ZZIP_CASELESS</code> to imitate win32-like filematching for a
+ zipped filetree.
+</P><P>
+ Other wishes on <a href="zziplib.html">zziplib</a> circulated around
+ <a href="zzip-xor.html">obfuscation</a> or access to zip-files wrapped
+ in other data areas including encrpyted resources from other applications.
+ This has been adressed with the IO-handlers that you can explicitly
+ submit to the *_ext_io functions - the default will be posix-IO
+ open/read/write and seek/tell. An application using
+ <a href="zziplib.html">zziplib</a> can divert these to its own set of
+ these calls - and it only needs to declare them on opening a zipped file.
+</P>
+
+</section><section>
+<h3> The EXT stringlist </h3>
+
+<P>
+ Declaring an EXT stringlist is very simple as it is simply a
+ list of strings, the <a href="zziplib.html">zziplib</a> provides
+ you with a double-const <code>zzip_strings_t</code> type to help
+ you move a global declaration into the writeonly segment of your
+ app - it turned out that about all developers wanted just some
+ extensions on the default and they were fine with having them
+ global-const for their application, nothing like dynamically
+ modifying them. Well, you are still allowed to make it fully
+ dynamic... if you find a use case for that.
+</P><P>
+ Extending the magic zip-extensions is just done by adding the
+ additional extensions to be recognized - just remember to add
+ the uppercased variants too since those will be needed on
+ (unx-like) filesystems that are case-sensitive. In the internet
+ age, quite some downloaded will appear in uppercased format since
+ the other side declared it as that and that other end was happy
+ with it as being a (w32-like) case-insensitive server. Therefore,
+ it should look like <pre>
+ static zzip_strings_t my_ext[] = { ".zip", ".ZIP", ".jar", ".JAR", 0 };
+ </pre>
+</P><P>
+ There is one frequently asked question in this area - how to open
+ a zipped file as "test.zip/README" instead of "test/README". Other
+ than some people might expect, the library will not find it - if
+ you want to have that one needs a fileext list that contains the
+ empty string - not the zero string, an empty string that is. It
+ looks like <pre>
+ static zzip_strings_t my_ext[] = { ".zip", ".ZIP", "", 0 };
+ </pre>
+</P><P>
+ And last not least, people want to tell the libary to not try to
+ open a real file that lives side by side with the same path as the
+ file path that can be matched by the zziplib. Actually, the magic
+ wrappers were never meant to be used like - the developer should
+ have used zzip_dir_* functions to open a zip-file and the
+ zzip_file_* functions to read entries from that zip-file. However,
+ the magic-wrappers look rather more familiar, and so you will find
+ now a bit-option ZZIP_ONLYZIP that can be passed down to the _ext_io
+ variants of the magic-wrapper calls, and a real-file will never get
+ tested for existance. Actually, I would rather recommend that for
+ application data the option ZZIP_PREFERZIP, so that one can enter
+ debugging mode by unpacking the zip-file as a real directory tree
+ in the place of the original zip.
+</P>
+
+</section><section>
+<h3> The IO handlers </h3>
+
+<P>
+ While you will find the zzip_plugin_io_t declared in the zziplib
+ headers, you are not advised to make much assumptions about their
+ structure. Still we gone the path of simplicity, so you can use
+ a global static for this struct too just like one can do for the
+ EXT-list. This again mimics the internals of zziplib. There is
+ even a helper function zzip_init_io that will copy the zziplib
+ internal handlers to your own handlers-set. Actually, this is
+ barely needed since the zziplib library will not check for nulls
+ in the plugin_io structure, all handlers must be filled, and the
+ zziplib routines call them unconditionally - that's simply
+ because a conditional-call will be ten times slower than an
+ unconditional call which adds mostly just one or two cpu cycles
+ in the place so you won't ever notice zziplib to be anywhat
+ slower than before adding IO-handlers.
+</P><P>
+ However, you better instantiate your handlers in your application
+ and call that zzip_init_io on that instance to have everything
+ filled, only then modify the entry you actually wish to have
+ modified. For <a href="zzip-xor.html">obfuscation</a> this
+ will mostly be just the <code>read()</code> routine. But one can
+ also use IO-handlers to wrap zip-files into another data part
+ for which one (also) wants to modify the open/close routines
+ as well.
+</P><P>
+ Therefore, you can modify your normal stdio code to start using
+ zipped files by exchaning the fopen/fread/fclose calls by their
+ magic counterparts, i.e. <pre>
+ // FILE* file = fopen ("test/README", "rb");
+ ZZIP_FILE* file = zzip_fopen ("test/README", "rb");
+ // while (0 &lt; fread (buffer, 1, buflen, file)))
+ while (0 &lt; zzip_fread (buffer, 1, buflen, file)))
+ { do something }
+ // fclose (file);
+ zzip_fclose (file);
+ </pre>
+</P><P>
+ and you then need to prefix this code with some additional
+ code to support your own EXT/IO set, so the code will finally
+ look like <pre>
+ /* use .DAT extension to find some files */
+ static zzip_strings_t ext[] = { ".dat", ".DAT", "", 0 };
+ /* add obfuscation routine - see zzxorcat.c examples */
+ static zzip_plugin_io_t io;
+ zzip_init_io (&amp; io, 0);
+ io.read = xor_read;
+ /* and the rest of the code, just as above, but with ext/io */
+ ZZIP_FILE* file = zzip_open_ext_io ("test/README", O_RDONLY|O_BINARY,
+ ZZIP_ONLYZIP|ZZIP_CASELESS, ext, io);
+ while (0 &lt; zzip_fread (buffer, 1, buflen, file)))
+ { do something }
+ zzip_fclose (file);
+ </pre>
+</P>
+
+</section><section>
+<h3> Finally </h3>
+
+<P>
+ What's more to it? Well, if you have some ideas then please mail me
+ about it - don't worry, I'll probably reject it to be part of the
+ standard zziplib dll, but perhaps it is worth to be added as a
+ configure option and can help others later, and even more perhaps
+ it can be somehow generalized just as the ext/io features have been
+ generalized now. In most respects, this ext/io did not add much
+ code to the <a href="zziplib.html">zziplib</a> - the posix-calls
+ in the implemenation, like <code>"read(file)"</code> were simply
+ exchanged with <code>"zip-&gt;io-&gt;read(file)"</code>, and the
+ old <code>"zzip_open(name,mode)"</code> call is split up - the old
+ entry still persists but directly calls
+ <code>"zzip_open_ext_io(name,mode,0,0,0)"</code> which has the
+ old implementation code with just one addition: when the ZIP_FILE
+ handle is created, it uses the transferred io-handlers (or the
+ default ones if io==0), and initialized the io-member of that
+ structure for usage within the <code>zzip_read</code> calls.
+</P><P>
+ This adds just a few bytes to the libs and just consumes additional
+ cpu cycles that can be rightfully called to be negligable (unlike
+ most commerical vendors will tell you when they indeed want to
+ tell you that for soooo many new features you have to pay a price).
+ It makes for greater variability without adding fatness to the
+ core in the default case, this is truly efficient I'd say. Well,
+ call this a German desease :-)=) ... and again, if you have another
+ idea, write today... or next week.
+</P>
+
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/zzip-extras.htm b/Build/source/libs/zziplib/docs/zzip-extras.htm
new file mode 100644
index 00000000000..1d771160cb9
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/zzip-extras.htm
@@ -0,0 +1,164 @@
+<section><date> 20. July 2002 </date>
+<h2> ZZIP API extras </h2> The check/init API description.
+
+<!--border-->
+
+<section>
+<h3> Extras </h3>
+
+<P>
+ The next requests circulated around other file-extensions to
+ automagically look inside filetypes that have zip-format too but
+ carry other fileextensions - most famous might be the ".PK3"
+ files of ID's Quake game. There have been a number of these
+ requests and in a lot of cases it dawned to me that those guys
+ may have overlooked the zzip_dir_open functions to travel
+ through documents of zipformat under any name - that is that the
+ "magic" was not actually needed but they just wanted to read
+ files in zipformat with the zziplib.
+</P>
+
+<P>
+ Other requests circulated around encryption but I did reject
+ those bluntly, always. Instead there have been always examples
+ for doing some obfuscation around the zip-format so that the
+ stock zip/unzip tools do not recognize them but a game
+ software developer can pack/unpack his AI scripts and bitmaps
+ into such a zipformat-like file.
+</P>
+
+<P>
+ After some dead-end patches (being shipped along with the
+ zziplib as configure-time compile-options - greetings to
+ Lutz Sammer and Andreas Schiffler), the general approach
+ of _ext_io came up, and finally implemented (greetings go
+ to Mike Nordell). The _open()-calls do now each have a
+ cousin of _open_ext_io() with two/three additional arguments
+ being a set of extensions to loop through our magic testing,
+ a callback-handler plugin-table for obfuscation-means,
+ and (often) a bit-mask for extra-options - this bitmask even
+ has "PREFERZIP" and "ONLYZIP" options to skip the real-file
+ test magic in those <code>zzip_*open</code> functions.
+</P>
+
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_open(name,flags) </td>
+ <td width=50%> zzip_open_ext_io(name,flags,mode,ext,io) </td></tr>
+ <tr><td width=50%> zzip_opendir(name) </td>
+ <td width=50%> zzip_opendir_ext_io(name,mode,ext,io) </td></tr>
+ <tr><td width=50%> zzip_dir_open(name,errp) </td>
+ <td width=50%> zzip_dir_open_ext_io(name,errp,ext,io) </td></tr>
+ <tr><td width=50%> zzip_dir_fdopen(fd,errp) </td>
+ <td width=50%> zzip_dir_fdopen_ext_io(fd,errp,ext,io) </td></tr>
+ <tr><td width=50%> zzip_file_open(dir,name,mode) </td>
+ <td width=50%> zzip_file_open_ext_io(dir,name,mode,ext,io) </td></tr>
+</table></td></tr></table>
+
+<P>
+ Oh, and note that the mode,ext,io extras are memorized
+ in the respecitive ZZIP_DIR handle attached, so each
+ of the other calls like <code>zzip_file_open()</code>
+ and <code>zzip_read()</code> will be using them. There
+ are a few helper routines to help setup a new io-plugin
+ where the init_io will currently just memcopy the
+ default_io entries into the user-supplied plugin-struct.
+</P>
+
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_init_io </td>
+ <td width=50%> the recommended way to do things </td></tr>
+ <tr><td width=50%> zzip_get_default_io </td>
+ <td width=50%> used internally whenever you supply a null
+ for the io-argument of a _ext_io()-call </td></tr>
+ <tr><td width=50%> zzip_get_default_ext </td>
+ <td width=50%> used internally but not exported </td></tr>
+</table></td></tr></table>
+
+
+<P>
+ And last some stdio-like replacements were build but these
+ happen to be actually just small wrappers around the other
+ posix-like magic-calls. It just offers some convenience
+ since wrappers like "SDL_rwops" tend to use a stringised
+ open-mode - and I took the occasion to fold the zzip-bits
+ for the _ext_io-calls right in there recognized via
+ special extensions to the openmode-string of zzip_fopen().
+</P>
+
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_fopen </td>
+ <td width=50%> convert stringmode and call zzip_open_ext_io </td></tr>
+ <tr><td width=50%> zzip_fread </td>
+ <td width=50%> slower way to say zzip_read </td></tr>
+ <tr><td width=50%> zzip_fclose </td>
+ <td width=50%> a synonym of zzip_close </td></tr>
+</table></td></tr></table>
+
+<P>
+ For some reason, people did need the full set of function-calls()
+ to be working on zzip-wrappers too, so here they are - if the
+ ZZIP_FILE instance did wrap a real file, then the real posix-call
+ will be used, otherwise it is simulated on the compressed stream
+ with a zip-contained file - especially <code>seek()</code> can be
+ a slow operation:
+ if the new point is later then just read out more bytes till we
+ hit that position but if it is an earlier point then rewind to the
+ beginning of the compressed data and start reading/decompression
+ until the position is met.
+</P>
+
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_rewind </td>
+ <td width=50%> magic for rewind() </td></tr>
+ <tr><td width=50%> zzip_tell </td>
+ <td width=50%> magic for tell() </td></tr>
+ <tr><td width=50%> zzip_seek </td>
+ <td width=50%> magic for seek() </td></tr>
+</table></td></tr></table>
+
+<P>
+ And last not least, there are few informative functions to
+ use function-calls to read parts of the opaque structures
+ of zzip-objects and their zzip-factory.
+</P>
+
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_dir_stat </td>
+ <td width=50%> a stat()-like thing on a file within a ZZIP_DIR </td></tr>
+ <tr><td width=50%> zzip_dir_real </td>
+ <td width=50%> check if ZZIP_DIR wraps a stat'able posix-dirent</td></tr>
+ <tr><td width=50%> zzip_file_real </td>
+ <td width=50%> check if ZZIP_FILE wraps a stat'able posix-file </td></tr>
+ <tr><td width=50%> zzip_realdir </td>
+ <td width=50%> if zzip_dir_real then return the posix-dirent </td></tr>
+ <tr><td width=50%> zzip_realfd </td>
+ <td width=50%> if zzip_file_real then return the posix-file </td></tr>
+ <tr><td width=50%> zzip_dirhandle </td>
+ <td width=50%> the attached ZZIP_DIR of compressed ZZIP_FILE </td></tr>
+ <tr><td width=50%> zzip_dirfd </td>
+ <td width=50%> the attached posix-file of ZZIP_DIR zip-file </td></tr>
+ <tr><td width=50%> zzip_set_error </td>
+ <td width=50%> set the last ZZIP_DIR error-code </td></tr>
+ <tr><td width=50%> zzip_error </td>
+ <td width=50%> get the last ZZIP_DIR error-code </td></tr>
+ <tr><td width=50%> zzip_strerror </td>
+ <td width=50%> convert a zzip_error into a readable string </td></tr>
+ <tr><td width=50%> zzip_strerror_of </td>
+ <td width=50%> combine both above zzip_strerror of zzip_error </td></tr>
+ <tr><td width=50%> zzip_errno </td>
+ <td width=50%> helper to wrap a zzip-error to a posix-errno </td></tr>
+ <tr><td width=50%> zzip_compr_str </td>
+ <td width=50%> helper to wrap a compr-number to a readable string
+ </td></tr>
+ <tr><td width=50%> zzip_dir_free </td>
+ <td width=50%> internally called by zzip_dir_close if the ref-count
+ of the ZZIP_DIR has gone zero</td></tr>
+ <tr><td width=50%> zzip_freopen </td>
+ <td width=50%> to reuse the ZZIP_DIR from another ZZIP_FILE so it does
+ not need to be parsed again </td></tr>
+ <tr><td width=50%> zzip_open_shared_io </td>
+ <td width=50%> the ext/io cousin but it does not close the old ZZIP_FILE
+ and instead just shares the ZZIP_DIR if possible</td></tr>
+</table></td></tr></table>
+
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/zzip-file.htm b/Build/source/libs/zziplib/docs/zzip-file.htm
new file mode 100644
index 00000000000..241baef85a7
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/zzip-file.htm
@@ -0,0 +1,183 @@
+<section> <date> 1. June 2000 </date>
+<h2> ZIP File Access </h2> Using Zipped Files Transparently
+
+<!--border-->
+
+<section>
+<h3>The Typedef</h3>
+
+<P>
+ The typedef <code>ZZIP_FILE</code> can serve as a replacement
+ for a normal file descriptor. As long as it is only used
+ for reading a file, the zzlib-user can actually replace
+ the posix functions <code>open/read/close</code>
+ by their counterparts from the
+ <a href="zziplib.html">zziplib library</a>:
+ <code>zzip_open/zzip_read/zzip_close</code>.
+</P>
+<P>
+ As long as the filename path given to <code>zzip_open</code>
+ refers to a real file in the filesystem, it will almost
+ directly forward the call to the respective posix <code>open</code>
+ call. The returned file descriptor is then stored in
+ a member-variable of the <code>ZZIP_FILE</code> structure.
+</P>
+<P>
+ Any subsequent calls to <code>zzip_read</code> will then
+ be forwarded to the posix <code>read</code> call on the
+ memorized file descriptor. The same about <code>zzip_close</code>
+ which will call the posix <code>close</code> function and then
+ <code>free</code> the <code>ZZIP_FILE</code> structure.
+</P>
+<P>
+ The real benefit of the
+ <a href="zziplib.html">zziplib library</a>
+ comes about when the filename argument does actually refer
+ to a file that is zipped in a zip-archive. It happens that
+ even both a real file and a zipped file can live under the
+ same pathname given to the <code>zzip_open</code> call,
+ whereas the real file is used in preference.
+</P>
+
+</section><section>
+<h3>Zipped File</h3>
+
+<P>
+ Suppose you have subdirectory called '<tt>test/</tt>'. In
+ this directory is just one file, called '<tt>README</tt>'.
+ Calling the <code>zzip_open</code> function with an
+ argument of '<i>optional-path/</i> <tt>test/README</tt>',
+ then it will open that file for subsequent reading with
+ <code>zzip_read</code>. In this case the real (<i>stat'able</i>)
+ file is opened.
+</P>
+<P>
+ Now you can go to the '<tt>test/</tt>' directory and zip up
+ the files in there by calling
+ <nobr><tt>`zip ../test.zip *`</tt></nobr>.
+ After this, you can delete the '<tt>test/</tt>' directory and
+ the call to <code>zzip_open</code> will still succeed.
+ The reason is that the part of the path saying
+ '<tt>test/README</tt>' will be replaced by sth. like
+ '<tt>test.zip:README</tt>' - that is the real file '<tt>test.zip</tt>'
+ is opened and searched for a contained file '<tt>README</tt>'.
+</P>
+<P>
+ Calling <code>zzip_read</code> on the zipped '<tt>README</tt>' file
+ will return the very same data as if it is a real file in a
+ real directory. If the zipped file is compressed it will be
+ decompressed on the fly.
+</P>
+
+</section><section>
+<h3>Zip Directory</h3>
+
+<P>
+ The same applies to the use of <code>opendir/readdir/closedir</code>
+ which can safely be replaced with their counterparts from the
+ <a href="zziplib.html">zziplib library</a> - again their prototype
+ follows the scheme of the original calls, just prepend <tt>zzip_</tt>
+ to the function calls and <tt>ZZIP_</tt> to the struct-typedefs.
+</P>
+<P>
+ To call <code>zzip_opendir</code> on a real directory will then
+ return a <code>ZZIP_DIR</code> whose member-variable
+ <code>realdir</code> points to the actual <code>DIR</code>-structure
+ returned by the underlying posix <code>opendir</code>-call.
+</P>
+<P>
+ If a real directory '<tt>test</tt>' does not exist, then the
+ <code>zzip_opendir</code> will try to open a file '<tt>test.zip</tt>'
+ with a call to <code>zzip_dir_open</code>.
+ Subsequent calls to <code>zzip_readdir</code> will then return
+ information as being obtained from the central archive directory
+ of the zip-file.
+</P>
+
+</section><section>
+<h3>Differences</h3>
+
+<P>
+ There are no differences between the posix calls and their counterparts
+ from the <a href="zziplib.html">zziplib library</a> - well, just
+ as long as the zip-file contains just the plain files from a directory.
+</P>
+<P>
+ If the zip-file contains directory entries you may be prompted with
+ some awkward behaviour, since in zip-file a directory happens to be
+ just an empty file. Note that the posix function <code>open</code>
+ may also open a directory for reading - it will only return
+ <code>EISDIR</code> if the <code>open</code> mode-argument included
+ write-access.
+</P>
+<P>
+ What the current of version of the
+ <a href="zziplib.html">zziplib library</a>
+ can definitly not do: calling zzip_opendir on a directory zippend
+ <em>inside</em> a zip-file.
+</P>
+<P>
+ To prevent the enrollment of directories into the zip-archive, you
+ can use the <tt>-D</tt> option of the <tt>zip</tt> program. That
+ is in any <tt>Makefile</tt> you may want to use
+ <nobr><tt>`cd $(dir) &amp;&amp; zip -D ../$(dir).zip *`</tt></nobr>.
+</P>
+
+</section><section>
+<h3>Advantages</h3>
+
+<P>
+ Distribution of a set of files is much easier if it just means
+ to wrap up a group of files into a zip-archive - and copy that
+ zip-archive to the respective destination directory.
+ Even more the files can be compressed and unlike a <tt>tar.gz</tt>
+ archive there is no need to decompress the archive in temporary
+ location before accessing a member-file.
+</P>
+<P>
+ On the other hand, there is no chance to scatter files around
+ on the disk like it could easily happen with a set of gzip'ed
+ man-pages in a single `<tt>man</tt>`-directory. The reader
+ application does not specifically need to know that the file
+ is compressed, so that reading a script like
+ `<tt>share/guile/x.x.x/ice-9/popen.scm</tt>` is done by simple
+ calls to <code>zzip_read</code> which works on zip-file named
+ `<tt>share/guile/x.x.x/ice-9.zip</tt>`.
+</P>
+<P>
+ A version mismatch between different files in a group is now
+ obvious: either the opened file belongs to the distribution
+ archive, or otherwise in resides in a real directory <em>just
+ next to the zip-archive that contains the original</em>.
+</P>
+
+</section><section>
+<h3>Issues</h3>
+
+<P>
+ The <a href="zziplib.html">zziplib library</a> does not
+ use any code piece from the <code>zip</code> programs, neither
+ <em>pkzip</em> nor <em>infozip</em>, so there is no license
+ issue here. The decompression is done by using the free
+ <a href="http://www.gzip.org/zlib">zlib library</a> which has no special
+ issues with respect to licensing.
+ The rights to the <a href="zziplib.html">zziplib library</a>
+ are reserved to the copyright holders, there is a public
+ license that puts most the sources themselves under
+ <a href="COPYING.LIB">the GNU Lesser General Public License</a>,
+ so that the use of a shared library instance of the
+ <a href="zziplib.html">zziplib library</a>
+ has no restrictions of interest to application programmers.
+ For more details and hints about static linking, check
+ the <a href="copying.html">COPYING</a> information.
+</P>
+<P>
+ The only issue you have with the
+ <a href="zziplib.html">zziplib library</a>
+ is the fact that you can only <em>read</em> the contained files.
+ Writing/Compression is not implemented. Even more, a compressed
+ file is not seekable at the moment although I hope that someone
+ will stand up to implement that functionality someday.
+</P>
+
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/zzip-index.htm b/Build/source/libs/zziplib/docs/zzip-index.htm
new file mode 100644
index 00000000000..8b7a9bb6637
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/zzip-index.htm
@@ -0,0 +1,55 @@
+<section> <date> created 1.Jun.2000, last updated 09.Feb.2003 </date>
+<h2> The Library </h2> Overview
+
+<!--border-->
+
+<!-- 1. section of zzip-zip.html -->
+
+<P>
+ The <a href="zziplib.html">zziplib library</a> is intentionally
+ lightweight, it offers the ability to easily extract data from
+ files archived in a single zip file. Applications can bundle
+ files into a single zip archive and access them.
+ The implementation is based only on the (free) subset of
+ compression with the <a href="http://www.gzip.org/zlib">
+ zlib algorithm</a> which is actually used by the <tt>zip/unzip</tt> tools.
+</P>
+
+<center>
+ The library allows reading zip archives in a number of ways,
+</center><dl>
+<dt>archive mode:</dt>
+<dd> reading the zip directory and extracting files from it.
+ This is the traditional mode as seen with unzip-utilities.
+ Some extra unzip-utiles for transparent/magic mode are
+ shipped as&nbsp;well.
+</dd>
+<dt>replacement mode:</dt>
+<dd> Use ZZIP_FILE / ZZIP_DIR pointers provided by zziplib and
+ put them to work with routines originally developped to
+ work with real directories and file handles. The API calls
+ do follow traditional synopsis from posix/stdio.
+</dd>
+<dt>transparent mode:</dt>
+<dd> Use replacement handles and allow the open()-calls to
+ automatically detect when a file is contained in a zip
+ archive or when it is a real file in the file system.
+ A filepath can be partly in a real filesystem and partly
+ within the zip archive when one is seen.
+</dd>
+<dt> ext magic </dt>
+<dd> Use the same filepath to access either a zipped or real
+ file - it looks for a real file and there is none then
+ every subdirectory of the path is checked, a ".zip"
+ extension appended, and the zipped file transparently
+ opened. This can speed up dat-file development
+ dramatically.
+</dd>
+<dt> io/xor magic </dt>
+<dd> The access to the filesystem can be hooked up - examples
+ are given for xor obfuscation which is great for game
+ artwork and AI data. A small intro for SDLrwops usage is
+ given as well.
+</dd>
+</dl>
+</section>
diff --git a/Build/source/libs/zziplib/docs/zzip-parse.htm b/Build/source/libs/zziplib/docs/zzip-parse.htm
new file mode 100644
index 00000000000..a3c49dcba76
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/zzip-parse.htm
@@ -0,0 +1,219 @@
+<section> <date> 17. December 2002 </date>
+<h2> ZIP Format </h2> About Zip Parsing Internals...
+
+<!--border-->
+
+<section>
+<h3> ZIP Trailer Block </h3>
+
+<P>
+ The general ZIP file format is written sequentially - each file
+ being added gets a local file header and its inflated data. When
+ all files are written then a central directory is written - and
+ this central directory may even span multiple disks. And each
+ disk gets a descriptor block that contains a pointer to the start
+ of the central directory. This descriptor is always written last
+ and therefore we call it the "ZIP File Trailer Block".
+</P>
+<P>
+ Okay, so we know that this ZIP Trailer is always at the end of a zip
+ file and that is has a fixed length, and a magic four-byte value at
+ its block start. That should make it easy to detect zip files but in
+ the real world it is not that easy - it is allowed to add a zip
+ archive comment text <em>after</em> the Trailer block. It's rarely
+ used these days but it turns out that a zip reader must be ready
+ to search for the Trailer block starting at the end of the file
+ and looking upwards for the Trailer magic (it's "PK\5\6" btw).
+</P>
+<P>
+ Now that's what the internal function __zip_find_disk_trailer is
+ used for. It's somewhat optimized as we try to use mmap features
+ of the underlying operating system. The returned structure is
+ called zzip_disk_trailer in the library source code, and we only
+ need two values actually: u_rootseek and u_rootsize. The first of
+ these can be used to lseek to the place of the central directory
+ and the second value tells us the byte size of the central directory.
+</P>
+
+</section><section>
+<h3> ZIP Central Directory </h3>
+
+<P>
+ So here we are at the central directory. The disk trailer did also
+ tell us how many entries are there but it is not that easy to read
+ them. Each directory entry (zzip_root_dirent type) has again a
+ magic value up front followed by a few items but they all have some
+ dos format - consider the timestamps, and atleast size/seek values
+ are in intel byteorder. So we might want to parse them into a format
+ that is easier to handle in internal code.
+</P>
+<P>
+ That is also needed for another reason - there are three items in that
+ directory entry being size values of three variadic fields following
+ right after the directory. That's right, three of these. The first
+ variadic field is the filename of this directory entry. In other
+ words, the root directory entry does not contain a seek value of
+ where the filename starts off, the start of the filename is
+ implicitly given with the end address of the directory entry.
+</P>
+<P>
+ The size value for the filename does simply say how long the
+ filename is - however, and more importantly, it allows us to
+ compute the start of the next variadic field, called the extra
+ info field. Well, we do not need any value from that extra info
+ block (it has unix filemode bits when packed under unix) but we
+ can be quite sure that this field is not null either. And that
+ was the second variadic field.
+</P>
+<P>
+ There is a third variadic field however - it's the comment field.
+ That was pretty heavily used in the good old DOS days. We are not
+ used to it anymore since filenames are generally self-descriptive
+ today but in the DOS days a filename was 8+3 chars maximum - and
+ it was in the comment field that told users what's in there. It
+ turned out that many software archives used zip format for just
+ that purpose as their primary distribution format - for being
+ able to attach a comment line with each entry.
+</P>
+<P>
+ Now, these three variadic fields have each an entry in the
+ directory entry header telling of their size. And after these
+ three variadic fields the next directory entry follows right in.
+ Yes, again there is no seek value here - we have to take the sum
+ of the three field sizes and add that to the end address of the
+ directory entry - just to be able to get to the next entry.
+</P>
+
+</section><section>
+<h3> Internal Directory </h3>
+
+<P>
+ Now, the external ZIP format is too complicated. We cut it down
+ to the bare minimum we actually need. The fields in the entry
+ are parsed into a format directly usable, and from the variadic
+ fields we only keep the filename. Oh, and we ensure that the
+ filename gets a trailing null byte, so it can surely be passed
+ down into libc routines.
+</P>
+<P>
+ There is another trick by the way - we use the u_rootsize value
+ to malloc a block for the internal directory. That ensures the
+ internal root directory entries are in nearby locations, and
+ including the filenames themselves which we put in between the
+ dirent entries. That's not only similar to the external directory
+ format, but when calling readdir and looking for a matching
+ filename of an zzip_open call, this will ensure the memory is
+ fetched in a linear fashion. Modern cpu architectures are able
+ to burst through it.
+</P>
+<P>
+ One might think to use a more complicated internal directory
+ format - like hash tables or something. However, they all suffer
+ from the fact that memory access patterns will be somewhat random
+ which eats a lot of speed. It is hardly predictable under what
+ circumstances it gets us a benefit, but the problem is certainly
+ not off-world: there are zzip archives with 13k+ entries. In a real
+ filesystem people will not put 13k files into one directory, of
+ course - but for the zip central directory all entries are listed
+ in parallel with their subdirectory paths attached. So, if the
+ original subtree had a number of directories, they'll end up in
+ parallel in the zip's central directory.
+</P>
+
+</section><section>
+<h3> File Entry </h3>
+
+<P>
+ The zip directory entry has one value that is called z_off in the
+ zziplib sources - it's the seek value to the start of the actual
+ file data, or more correctly it points to the "local file header".
+ Each file data block is preceded/followed with a little frame.
+ There is not much interesting information in these framing blocks,
+ the values are duplicates of the ones found in the zip central
+ directory - however, we must skip the local file header (and a
+ possible duplicate of filename and extrainfo) to arrive at the
+ actual file data.
+</P>
+<P>
+ When the start of the actual file data, we can finally read data.
+ The zziplib library does only know about two choices defined by
+ the value in the z_compr field - a value of "0" means "stored"
+ and data has been stored in uncompresed format, so that we can
+ just copy it out of the file to the application buffer.
+</P>
+<P>
+ A value of "8" means "deflated", and here we initialize the zlib
+ and every file data is decompressed before copying it to the
+ application buffer. Care must be taken here since zlib input data
+ and decompressed data may differ significantly. The zlib compression
+ will not even obey byte boundaries - a single bit may expand to
+ hundreds of bytes. That's why each ZZIP_FILE has a decompression
+ buffer attached.
+</P>
+<P>
+ All the other z_compr values are only of historical meaning,
+ the infozip unix tools will only create deflated content, and
+ the same applies to pkzip 2.x tools. If there would be any other
+ value than "0" or "8" then zziplib can not decompress it, simple
+ as that.
+</P>
+
+</section><section>
+<h3> ZZIP_DIR / ZZIP_FILE </h3>
+
+<P>
+ The ZZIP_DIR internal structures stores a posix handle to the
+ zip file, and a pointer to the parsed central directory block.
+ One can use readdir/rewinddir to walk each entry in the central
+ directory and compare with the filenames attached. And that's
+ what will be done at a zzip_open call to find the file entry.
+</P>
+<P>
+ There are a few more fields in the ZZIP_DIR structure, where
+ most of these are related to the use of this struct as a
+ shared recource. You can use zzip_file_open to walk the
+ preparsed central directory and return a new ZZIP_FILE handle
+ for that entry.
+</P>
+<P>
+ That ZZIP_FILE handle contains a back pointer its ZZIP_DIR
+ that it was made from - and the back pointer also serves as flag
+ that the ZZIP_FILE handle points to a file within a ZIP file as
+ opposed to wrapping a real file in the real directory tree.
+ Each ZZIP_FILE will increment a shared counter, so that the
+ next dir_close will be deferred until all ZZIP_FILE have been
+ destroyed.
+</P>
+<P>
+ Another optmization is the cache-pointer in the ZZIP_DIR. It is
+ quite common to read data entries sequentially, as that the
+ zip directory is scanned for files matching a specific pattern,
+ and when a match is seen, that file is openened. However, each
+ ZZIP_FILE needs a decompression buffer, and we keep a cache of
+ the last one freed so that it can be picked up right away for the
+ next zzip_file_open.
+</P>
+<P>
+ Note that using multiple zzip_open() directly, each will open
+ and parse a zip directory of its own. That's bloat both in
+ terms of memory consumption and execution speed. One should try
+ to take advantage of the feature that multiple ZZIP_FILE's can
+ share a common ZZIP_DIR with a common preparsed copy of the
+ zip's central directory. That can be done directly with using
+ zzip_file_open to use a ZZIP_DIR as a factory for ZZIP_FILE,
+ but also zzip_freopen can be used to reuse the old internal
+ central directory, instead of parsing it again.
+</P>
+<P>
+ And while zzip_freopen would release the old ZZIP_FILE handle
+ only resuing the ZZIP_DIR attached, one can use another routine
+ directly called zzip_open_shared that will create a ZZIP_FILE
+ from an existing ZZIP_FILE. Oh, and not need to worry about
+ problems when a filepath given to zzip_freopen() happens to
+ be in another place, another directory, another zip archive.
+ In that case, the old zzip's internal directory is freed and
+ the others directory read - the preparsed central directory
+ is only used if that is actually possible.
+</P>
+
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/zzip-sdl-rwops.htm b/Build/source/libs/zziplib/docs/zzip-sdl-rwops.htm
new file mode 100644
index 00000000000..38923f6f0be
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/zzip-sdl-rwops.htm
@@ -0,0 +1,90 @@
+<section> <date> 19. Aug 2001 </date>
+<h2> SDL rwops </h2> Example to make an SDL_rwops interface.
+
+<p><small> some <b>MSVC</b> help in
+ <a href="README.MSVC6">README.MSVC6</a> and
+ <a href="README.SDL">README.SDL</a>
+</small></p>
+
+<!--border-->
+
+<section>
+<h3> Source </h3>
+
+<P>
+ The example sources of the <a href="zziplib.html">zziplib library</a>
+ are usually put under the <a href="COPYING.ZLIB">ZLIB license</a> so
+ that you can reuse the code freely in your own projects. Here we talk
+ about the example that might be most useful for
+ <a href="http://libsdl.org">SDL</a> based programs.
+ Just copy the two files
+ <a href="SDL_rwops_zzip.h">SDL_rwops_zzip.h</a>
+ and
+ <a href="SDL_rwops_zzip.c">SDL_rwops_zzip.c</a>
+ to the directory with your other project sources, and make sure
+ to link it somehow to your programs. I did not make the effort to
+ create a seperate library out of it - it would just export one
+ single function <tt>SDL_RWFromZZIP</tt> that has the same call-synopsis
+ like <tt>SDL_RWFromFile</tt> (but it can not (yet) write a zip-file).
+</P>
+
+<P>
+ The source file <a href="SDL_rwops_zzip.c">SDL_rwops_zzip.c</a> is
+ quite short - it just stores a ZZIP_FILE handle in the userdata
+ field of the <tt>SDL_rwops</tt> structure. The SDL'rwop calls will then
+ fetch that pointer and call the corresponding functions from the
+ <a href="zziplib.html">zziplib library</a>. Most of the glue code
+ is in the <tt>SDL_RWFromZZIP</tt> function that allocates an
+ <tt>SDL_rwops</tt> structure and fills the handler-functions
+ into the callback fields.
+</P>
+
+</section><section>
+<h3> Usage </h3>
+
+<P>
+ If you link this file to your project, remember that your executables
+ do now have additional dependencies - not only -lzzip to link with
+ the <a href="zziplib.html">zziplib library</a> - do not forget to
+ link with zlib library via -lz. Of course, there is a lib-config
+ script that you can use: `zzip-config --libs` will return these
+ linker-infos (unless you have a native-windows system - it is
+ shell-script).
+</P>
+
+<P>
+ As an example, replace that <tt>SDL_RWFromFile</tt> that accesses your
+ game-graphic files - these files are stored in shared/myapp
+ of course where they belong. When you've done that
+ then go to X/share/myapp and
+<br><code>&nbsp;&nbsp;&nbsp;
+ `(cd graphics/ && zip -9r ../graphics.zip .)` </code><br>
+ and rename the graphics/ subfolder - and still all your files
+ are found: a filepath like X/shared/graphics/game/greetings.bmp
+ will open X/shared/graphics.zip and return the zipped file
+ game/greetings.bmp in the zip-archive (for reading that is).
+</P>
+
+</section><section>
+<h3> Test </h3>
+
+<P>
+ The <a href="zziplib.html">zziplib</a> configure script does not
+ look for <a href="http://libsdl.org">SDL</a>. If you know that
+ you have <a href="http://libsdl.org">SDL</a> installed
+ then you can check this <tt>SDL_rwops</tt> example by using
+ <code><nobr>`make testsdl`</nobr></code>. This will compile the
+ two source files <a href="SDL_rwops_zzip.c">SDL_rwops_zzip.c</a>
+ and <a href="SDL_rwops_zzcat.c">SDL_rwops_zzcat.c</a> to be linked
+ together into an executable called <code>zzcatsdl</code>. The test
+ will continue with a <code><nobr>`zzcatsdl test/README`</nobr></code>
+ - just like it is done for <code><nobr>`make test3`</nobr></code>.
+</P>
+<P>
+ The corresponding section in the <a href="Makefile.am">Makefile.am</a>
+ is also an example how to use lib-config scripts to build files. Here
+ there is no build-processing that had been tweaked much by automake/autoconf.
+ Just use sdl-config and zzip-config to add the needed flags.
+</P>
+</section></section>
+
diff --git a/Build/source/libs/zziplib/docs/zzip-xor.htm b/Build/source/libs/zziplib/docs/zzip-xor.htm
new file mode 100644
index 00000000000..2434c2974a9
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/zzip-xor.htm
@@ -0,0 +1,77 @@
+<section> <date> 15. July 2002 </date>
+<h2> ZIP Obfuscation </h2> Using obfuscations like XOR.
+
+<!--border-->
+
+<section>
+<h3> The EXT/IO calls </h3>
+
+<P>
+ You really should read the section about the
+ <a href="zzip-extio.html">EXT/IO feature</a> of the zziplib since the
+ obfuscation routines are built on top of it. In order to use obfuscation,
+ you will generally need to use all the three additional argument that
+ can be passsed to _open_ext_io functions. For the XOR-example, only one
+ IO-handler is modified being the read()-call that will simply xor each
+ data byte upon read with a specific value. It two advantages - doing an
+ xor twice does yield the same data, so as a developer you do not have
+ to wonder about the encryption/decryption pair, and it is a stateless
+ obfuscation that does not need to know about the current position
+ within the zip-datafile or zippedfile-datatream.
+</P><P>
+ The examples provided just use a simple routine for xoring data that
+ is defined in all the three of the example programs: <pre>
+ static int xor_value = 0x55;
+ static zzip_ssize_t xor_read (int f, void* p, zzip_size_t l)
+ {
+ zzip_size_t r = read(f, p, l);
+ zzip_size_t x; char* q = p;
+ for (x=0; x &lt; r; x++) q[x] ^= xor_value;
+ return r;
+ }
+ </pre>
+</P><P>
+ and place this routine into the io-handlers after initializing
+ the structure: <pre>
+ zzip_init_io (&amp;xor_handlers, 0); xor_handlers.read = &amp;xor_read;
+ </pre>
+</P>
+
+</section><section>
+<h3> The examples </h3>
+
+<P>
+ There are three example programs. The first one is
+ <a href="zzxorcopy.c">zzxorcopy.c</a> which actually is not a zziplib
+ based program. It just opens a file via stdio, loops through all data bytes
+ it can read thereby xor'ing it, and writes it out to the output file. A
+ call like <code><nobr>"zzxorcopy file.zip file.dat"</nobr></code> will
+ create an obfuscated dat-file from a zip-file that has been possibly
+ create with the normal infozip tools or any other archive program to
+ generate a zip-file. The output dat-file is not recognized by normal
+ zip-enabled apps - the filemagic is obfuscated too. This output
+ dat-file however is subject to the other two example programs.
+</P><P>
+ The <a href="zzxordir.c">zzxordir.c</a> program will open such an obfuscated
+ zip file and decode the central directory of that zip. Everything is
+ still there in just the way it can be shown with the normal unzip
+ programs and routines. And the <a href="zzxorcat.c">zzxorcat.c</a> program
+ can extract data from this obfuscated zip - and print it un-obfuscated
+ to the screen. These example programs can help you jumpstart with
+ your own set of obfuscator routines, possibly more complex ones.
+</P><P>
+ By the way, just compare those with their non-xor counterparts that
+ you can find in <a href="zzdir.c">zzdir.c</a> and
+ <a href="zzxorcat.c">zzxorcat.c</a>. Notice that the difference is
+ in the setup part until the _open_ call after which one can just
+ use the normal zzip_ routines on that obfuscated file. This is
+ great for developing since you can start of with the magic-wrappers
+ working on real-files then slowly turning to pack-files that hold
+ most of the data and finally ending with a zip-only and obfuscated
+ dat-file for your project.
+</P>
+
+<p align="right"><small><small>
+<a href="copying.html">staticlinking?</a>
+</small></small></p>
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/zzip-zip.htm b/Build/source/libs/zziplib/docs/zzip-zip.htm
new file mode 100644
index 00000000000..141700044a5
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/zzip-zip.htm
@@ -0,0 +1,146 @@
+<section><date> 1. June 2000 </date>
+<h2> ZIP Access </h2> Accessing Zip Archives with ZLib Decompression
+
+<!--border-->
+
+<section>
+<h3> The Library </h3>
+
+<P>
+ The <a href="zziplib.html">zziplib library</a> offers users the
+ ability to easily extract data from files archived in a single
+ zip file. This way, programs that use many "read-only" files from
+ a program specific source directory can have a single zip
+ archive
+</P>
+<P>
+ This library offers only a (free) subset of compression methods
+ provided in a full implementation but that is well enough. The
+ idea here is that <tt>zip/unzip</tt> utilities can be used
+ to create archives that will later be read by using this library.
+ Yet those programmes (or a library with their functionality)
+ is not needed in that final operation.
+</P>
+
+</section><section>
+<h3> Using A Zip-File </h3>
+
+<P>
+ Before a file in the zip-archive is accessed, the application
+ must first get a handle to the central directory contained in the
+ zip-file. This is achived by calling
+ <a href="zziplib.html#zzip_dir_open"> zzip_dir_open </a>
+ or
+ <a href="zziplib.html#zzip_dir_fdopen"> zzip_dir_fdopen </a>.
+ The directory entries in the zip-archives can be obtained
+ with
+ <a href="zziplib.html#zzip_dir_read"> zzip_dir_read </a>.
+ After being done, the zip-dir handle should be closed with
+ <a href="zziplib.html#zzip_dir_close"> zzip_dir_close </a>.
+</P>
+<p><pre> ZZIP_DIR* dir = zzip_dir_open("test.zip",0);
+ if (dir) {
+ ZZIP_DIRENT dirent;
+ if (zzip_dir_read(dir,&amp;dirent) {
+ /* show info for first file */
+ print("%s %i/%i", dirent.d_name, dirent.d_csize, dirent.st_size);
+ }
+ zzip_dir_close(dir);
+ }
+</pre></p>
+<P>
+ From the zip-dir handle a compressed file can be opened
+ for reading. This is achieved by using
+ <a href="zziplib.html#zzip_file_open"> zzip_file_open </a>
+ and providing it with the dir-handle and a name of the file.
+ The function
+ <a href="zziplib.html#zzip_file_read"> zzip_file_read </a>
+ is used to get pieces of uncompressed data from the file, and
+ the file-handle should be closed with
+ <a href="zziplib.html#zzip_file_close"> zzip_file_close </a>
+</P>
+<p><pre> ZZIP_FILE* fp = zzip_file_open(dir,"README",0);
+ if (fp) {
+ char buf[10];
+ zzip_ssize_t len = zzip_file_read(fp, buf, 10);
+ if (len) {
+ /* show head of README */
+ write(1, buf, len);
+ }
+ zzip_file_close(fp);
+ }
+</pre></p>
+
+</section><section>
+<h3> Magic Zipped Files </h3>
+
+<P>
+ There is actually no need to directly use the zip-centric functions
+ as described above. Instead there are magic replacements for the
+ posix calls <code>open/read/close</code> and
+ <code>opendir/readdir/closedir</code>. The prototypes of these
+ functions had been the guideline for the design of their magic
+ counterparts of the
+ <a href="zziplib.html">zziplib library</a>.
+</P>
+<P>
+ The magic functions are described in a seperated document on
+ <a href="zzip-file.html"> Using Zipped Files </a>. In general,
+ the functions have a prefix <tt>zzip_</tt> and their argument
+ types have a prefix <tt>ZZIP_</tt> where appropriate. Calls
+ to the magic functions and the direct functions above can
+ be mixed as long as the magic functions have not been opening
+ a real file.
+</P>
+<P>
+ To detect a real file (or directory), the info functions
+ <a href="zziplib.html#zzip_file_real"> zzip_file_real </a>
+ and
+ <a href="zziplib.html#zzip_dir_real"> zzip_dir_real </a>
+ can be used.
+ If these return a true value, the standard posix functions
+ are more apropriate. The posix handles can be obtained with
+ a call to
+ <a href="zziplib.html#zzip_realdir"> zzip_realdir </a> and
+ <a href="zziplib.html#zzip_realfd"> zzip_realfd </a> respectivly.
+</P>
+
+</section><section>
+<h3> Errors &amp; Infos </h3>
+
+<P>
+ There are a set of error and info functions available. To handle
+ error conditions specific to the
+ <a href="zziplib.html">zziplib library</a>
+ there are these functions:
+ <a href="zziplib.html#zzip_error"> zzip_error </a>,
+ <a href="zziplib.html#zzip_seterror"> zzip_seterror </a>
+ and their string representations with
+ <a href="zziplib.html#zzip_strerror"> zzip_strerror </a>,
+ <a href="zziplib.html#zzip_strerror_of"> zzip_strerror_of </a>.
+ The magic functions will map any of these specific library
+ error conditions to the more generic system <code>errno</code>
+ codes with
+ <a href="zziplib.html#zzip_errno"> zzip_errno </a>.
+</P>
+<P>
+ More information on stream can be obtained with
+ <a href="zziplib.html#zzip_dir_stat"> zzip_dir_stat </a> and
+ <a href="zziplib.html#zzip_dirhandle"> zzip_dirhandle. </a>
+ The latter is used to obtain the dir-handle that every zipped file
+ handle has even if not explicitly opened.
+</P>
+<P>
+ The usage of many functions are shown in the example programs
+ that come along with the
+ <a href="zziplib.html">zziplib library</a>. See the files
+ <a href="zzcat.c"> zzcat.c </a> and
+ <a href="zzdir.c"> zzdir.c </a>. The
+ <a href="zziptest.c"> zziptest.c </a> program needs the
+ private header file
+ <a href="zzip.h"> zzip.h </a> whereas the library installer
+ will only copy the public include file
+ <a href="zziplib.h"> zziplib.h </a> to your system's
+ <tt>include</tt> directory.
+</P>
+</section></section>
diff --git a/Build/source/libs/zziplib/docs/zziplib-master.dbk b/Build/source/libs/zziplib/docs/zziplib-master.dbk
new file mode 100644
index 00000000000..8384c282428
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/zziplib-master.dbk
@@ -0,0 +1,59 @@
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+<!-- using <chapter> allows to append a <reference> with manpages -->
+<section>
+<sectioninfo>
+<date> 2006-01-01</date>
+<authorblurb><simpara> Guido Draheim </simpara></authorblurb>
+</sectioninfo>
+<title> ZZIPlib Documentation </title>
+
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="zzip-index.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="zzip-zip.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="zzip-file.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="zzip-sdl-rwops.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="zzip-extio.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="zzip-xor.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="zzip-crypt.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="zzip-cryptoid.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="zzip-api.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="zzip-basics.xml" />
+<!--
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="zzip-extras.xml" />
+-->
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="zzip-parse.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="64on32.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="future.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="fseeko.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="mmapped.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="memdisk.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="configs.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="sfx-make.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="history.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="referentials.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="copying.xml" />
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"
+ href="faq.xml" />
+</section>
diff --git a/Build/source/libs/zziplib/docs/zziplib.html b/Build/source/libs/zziplib/docs/zziplib.html
new file mode 100644
index 00000000000..96852c510cc
--- /dev/null
+++ b/Build/source/libs/zziplib/docs/zziplib.html
@@ -0,0 +1,3795 @@
+<html><head><title>zziplibautodoc documentation </title></head>
+<body>
+
+<h1>zziplib <small><small><i>- 0.13.47</i></small></small></h1>
+<table border=0 cellspacing=2 cellpadding=0><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#__zzip_fetch_disk_trailer">
+ <code>__zzip_fetch_disk_trailer</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>int fd</nobr>,
+<nobr>zzip_off_t filesize</nobr>,
+<nobr>struct _disk_trailer * _zzip_restrict trailer</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>uint32_t </code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#__zzip_get32">
+ <code>__zzip_get32</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>unsigned char * s</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>uint16_t </code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#__zzip_get16">
+ <code>__zzip_get16</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>unsigned char * s</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>uint64_t </code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#__zzip_get64">
+ <code>__zzip_get64</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>unsigned char * s</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>void </code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#__zzip_set32">
+ <code>__zzip_set32</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>unsigned char * s</nobr>,
+<nobr>uint32_t v</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>void </code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#__zzip_set16">
+ <code>__zzip_set16</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>unsigned char * s</nobr>,
+<nobr>uint16_t v</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>void </code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#__zzip_set64">
+ <code>__zzip_set64</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>unsigned char * s</nobr>,
+<nobr>uint64_t v</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#__zzip_parse_root_directory">
+ <code>__zzip_parse_root_directory</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>int fd</nobr>,
+<nobr>struct _disk_trailer * trailer</nobr>,
+<nobr>struct zzip_dir_hdr ** hdr_return</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#__zzip_try_open">
+ <code>__zzip_try_open</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>int filemode</nobr>,
+<nobr>zzip_strings_t* ext</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_closedir">
+ <code>zzip_closedir</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR* dir</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip_char_t*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_compr_str">
+ <code>zzip_compr_str</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>int compr</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>ZZIP_DIR*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_createdir">
+ <code>zzip_createdir</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>ZZIP_DIR*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_dir_alloc_ext_io">
+ <code>zzip_dir_alloc_ext_io</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_strings_t* ext</nobr>,
+<nobr>const zzip_plugin_io_t io</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>ZZIP_DIR*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_dir_alloc">
+ <code>zzip_dir_alloc</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_strings_t* fileext</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>ZZIP_DIR*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_dir_creat">
+ <code>zzip_dir_creat</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>ZZIP_DIR*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_dir_creat_ext_io">
+ <code>zzip_dir_creat_ext_io</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>,
+<nobr>zzip_strings_t* ext</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>ZZIP_DIR *
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_dir_fdopen">
+ <code>zzip_dir_fdopen</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>int fd</nobr>,
+<nobr>zzip_error_t * errcode_p</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>ZZIP_DIR *
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_dir_fdopen_ext_io">
+ <code>zzip_dir_fdopen_ext_io</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>int fd</nobr>,
+<nobr>zzip_error_t * errcode_p</nobr>,
+<nobr>zzip_strings_t* ext</nobr>,
+<nobr>const zzip_plugin_io_t io</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_dir_free">
+ <code>zzip_dir_free</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR * dir</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_dir_close">
+ <code>zzip_dir_close</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR * dir</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>ZZIP_DIR*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_dir_open">
+ <code>zzip_dir_open</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>zzip_error_t* e</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>ZZIP_DIR*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_dir_open_ext_io">
+ <code>zzip_dir_open_ext_io</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>zzip_error_t* e</nobr>,
+<nobr>zzip_strings_t* ext</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_dir_read">
+ <code>zzip_dir_read</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR * dir</nobr>,
+<nobr>ZZIP_DIRENT * d</nobr> )</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_dir_stat">
+ <code>zzip_dir_stat</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR * dir</nobr>,
+<nobr>zzip_char_t* name</nobr>,
+<nobr>ZZIP_STAT * zs</nobr>,
+<nobr>int flags</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int </code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_file_stat">
+ <code>zzip_file_stat</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE* file</nobr>,
+<nobr>ZZIP_STAT* zs</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int </code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_fstat">
+ <code>zzip_fstat</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE* file</nobr>,
+<nobr>ZZIP_STAT* zs</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>ZZIP_DIR *
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_dirhandle">
+ <code>zzip_dirhandle</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE * fp</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_dirfd">
+ <code>zzip_dirfd</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR* dir</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip_byte_t*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_entry_to_data">
+ <code>zzip_disk_entry_to_data</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>struct zzip_disk_entry* entry</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>struct zzip_file_header*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_entry_to_file_header">
+ <code>zzip_disk_entry_to_file_header</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>struct zzip_disk_entry* entry</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip__new__ char*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_entry_strdup_name">
+ <code>zzip_disk_entry_strdup_name</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>struct zzip_disk_entry* entry</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip__new__ char*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_entry_strdup_comment">
+ <code>zzip_disk_entry_strdup_comment</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>struct zzip_disk_entry* entry</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>struct zzip_disk_entry*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_findfile">
+ <code>zzip_disk_findfile</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>char* filename</nobr>,
+<nobr>struct zzip_disk_entry* after</nobr>,
+<nobr>zzip_strcmp_fn_t compare</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>struct zzip_disk_entry*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_findfirst">
+ <code>zzip_disk_findfirst</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK* disk</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>struct zzip_disk_entry*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_findnext">
+ <code>zzip_disk_findnext</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>struct zzip_disk_entry* entry</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>struct zzip_disk_entry*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_findmatch">
+ <code>zzip_disk_findmatch</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>char* filespec</nobr>,
+<nobr>struct zzip_disk_entry* after</nobr>,
+<nobr>zzip_fnmatch_fn_t compare</nobr>,
+<nobr>int flags</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip__new__ ZZIP_DISK_FILE*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_fopen">
+ <code>zzip_disk_fopen</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>char* filename</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip__new__ ZZIP_DISK_FILE*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_entry_fopen">
+ <code>zzip_disk_entry_fopen</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>ZZIP_DISK_ENTRY* entry</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip_size_t
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_fread">
+ <code>zzip_disk_fread</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>void* ptr</nobr>,
+<nobr>zzip_size_t sized</nobr>,
+<nobr>zzip_size_t nmemb</nobr>,
+<nobr>ZZIP_DISK_FILE* file</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_fclose">
+ <code>zzip_disk_fclose</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK_FILE* file</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_feof">
+ <code>zzip_disk_feof</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK_FILE* file</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip__new__ ZZIP_DISK*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_mmap">
+ <code>zzip_disk_mmap</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>int fd</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_init">
+ <code>zzip_disk_init</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>void* buffer</nobr>,
+<nobr>zzip_size_t buflen</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip__new__ ZZIP_DISK*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_new">
+ <code>zzip_disk_new</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>void</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_munmap">
+ <code>zzip_disk_munmap</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK* disk</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>ZZIP_DISK* zzip__new__
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_open">
+ <code>zzip_disk_open</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>char* filename</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_disk_close">
+ <code>zzip_disk_close</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK* disk</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip_off_t
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_entry_data_offset">
+ <code>zzip_entry_data_offset</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_ENTRY* entry</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>static zzip_off_t
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_entry_fread_file_header">
+ <code>zzip_entry_fread_file_header</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_ENTRY* entry</nobr>,
+<nobr>struct zzip_file_header* file_header</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip__new__ char*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_entry_strdup_name">
+ <code>zzip_entry_strdup_name</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_ENTRY* entry</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip__new__ ZZIP_ENTRY*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_entry_findfile">
+ <code>zzip_entry_findfile</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>FILE* disk</nobr>,
+<nobr>char* filename</nobr>,
+<nobr>ZZIP_ENTRY* _zzip_restrict entry</nobr>,
+<nobr>zzip_strcmp_fn_t compare</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip__new__ ZZIP_ENTRY*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_entry_findfirst">
+ <code>zzip_entry_findfirst</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>FILE* disk</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip__new__ ZZIP_ENTRY*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_entry_findnext">
+ <code>zzip_entry_findnext</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_ENTRY* _zzip_restrict entry</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_entry_free">
+ <code>zzip_entry_free</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_ENTRY* entry</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip__new__ ZZIP_ENTRY*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_entry_findmatch">
+ <code>zzip_entry_findmatch</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>FILE* disk</nobr>,
+<nobr>char* filespec</nobr>,
+<nobr>ZZIP_ENTRY* _zzip_restrict entry</nobr>,
+<nobr>zzip_fnmatch_fn_t compare</nobr>,
+<nobr>int flags</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip__new__ ZZIP_ENTRY_FILE*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_entry_fopen">
+ <code>zzip_entry_fopen</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_ENTRY* entry</nobr>,
+<nobr>int takeover</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip__new__ ZZIP_ENTRY_FILE*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_entry_ffile">
+ <code>zzip_entry_ffile</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>FILE* disk</nobr>,
+<nobr>char* filename</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip_size_t
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_entry_fread">
+ <code>zzip_entry_fread</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>void* ptr</nobr>,
+<nobr>zzip_size_t sized</nobr>,
+<nobr>zzip_size_t nmemb</nobr>,
+<nobr>ZZIP_ENTRY_FILE* file</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_entry_fclose">
+ <code>zzip_entry_fclose</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_ENTRY_FILE* file</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_entry_feof">
+ <code>zzip_entry_feof</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_ENTRY_FILE* file</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_errno">
+ <code>zzip_errno</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>int errcode</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_error">
+ <code>zzip_error</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR * dir</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>void
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_seterror">
+ <code>zzip_seterror</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR * dir</nobr>,
+<nobr>int errcode</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_fclose">
+ <code>zzip_fclose</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE * fp</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_close">
+ <code>zzip_close</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE* fp</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_file_close">
+ <code>zzip_file_close</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE * fp</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>ZZIP_FILE*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_file_creat">
+ <code>zzip_file_creat</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR* dir</nobr>,
+<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_file_mkdir">
+ <code>zzip_file_mkdir</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR* dir</nobr>,
+<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>ZZIP_FILE *
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_file_open">
+ <code>zzip_file_open</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR * dir</nobr>,
+<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip_ssize_t
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_file_read">
+ <code>zzip_file_read</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE * fp</nobr>,
+<nobr>char * buf</nobr>,
+<nobr>zzip_size_t len</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_file_real">
+ <code>zzip_file_real</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE* fp</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_dir_real">
+ <code>zzip_dir_real</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR* dir</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>void*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_realdir">
+ <code>zzip_realdir</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR* dir</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_realfd">
+ <code>zzip_realfd</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE* fp</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>ZZIP_FILE*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_fopen">
+ <code>zzip_fopen</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>zzip_char_t* mode</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>ZZIP_FILE*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_freopen">
+ <code>zzip_freopen</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>zzip_char_t* mode</nobr>,
+<nobr>ZZIP_FILE* stream</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>static int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_inflate_init">
+ <code>zzip_inflate_init</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE * fp</nobr>,
+<nobr>struct zzip_dir_hdr* hdr</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>int </code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_init_io">
+ <code>zzip_init_io</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_plugin_io_handlers_t io</nobr>,
+<nobr>int flags</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip_plugin_io_t
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_get_default_io">
+ <code>zzip_get_default_io</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr></nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip__new__ ZZIP_MEM_DISK*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_mem_disk_fdopen">
+ <code>zzip_mem_disk_fdopen</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>int fd</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>long
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_mem_disk_load">
+ <code>zzip_mem_disk_load</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_MEM_DISK* dir</nobr>,
+<nobr>ZZIP_DISK* disk</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip__new__ ZZIP_MEM_DISK*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_mem_disk_open">
+ <code>zzip_mem_disk_open</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>char* filename</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip__new__ ZZIP_MEM_ENTRY*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_mem_entry_new">
+ <code>zzip_mem_entry_new</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>ZZIP_DISK_ENTRY* entry</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>int inline
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_mkdir">
+ <code>zzip_mkdir</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>ZZIP_FILE* inline
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_creat">
+ <code>zzip_creat</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>void inline
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_mkfifo">
+ <code>zzip_mkfifo</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>void inline
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_sync">
+ <code>zzip_sync</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>void</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>ZZIP_FILE*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_open">
+ <code>zzip_open</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>int o_flags</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>ZZIP_FILE*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_open_ext_io">
+ <code>zzip_open_ext_io</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>int o_flags</nobr>,
+<nobr>int o_modes</nobr>,
+<nobr>zzip_strings_t* ext</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>ZZIP_FILE*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_open_shared_io">
+ <code>zzip_open_shared_io</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE* stream</nobr>,
+<nobr>zzip_char_t* filename</nobr>,
+<nobr>int o_flags</nobr>,
+<nobr>int o_modes</nobr>,
+<nobr>zzip_strings_t* ext</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>ZZIP_DIR*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_opendir">
+ <code>zzip_opendir</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_char_t* filename</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>ZZIP_DIR*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_opendir_ext_io">
+ <code>zzip_opendir_ext_io</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>int o_modes</nobr>,
+<nobr>zzip_strings_t* ext</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip_ssize_t
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_read">
+ <code>zzip_read</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE * fp</nobr>,
+<nobr>char * buf</nobr>,
+<nobr>zzip_size_t len</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip_size_t
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_fread">
+ <code>zzip_fread</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>void *ptr</nobr>,
+<nobr>zzip_size_t size</nobr>,
+<nobr>zzip_size_t nmemb</nobr>,
+<nobr>ZZIP_FILE *file</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>ZZIP_DIRENT*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_readdir">
+ <code>zzip_readdir</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR * dir</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>int
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_rewind">
+ <code>zzip_rewind</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE *fp</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>void
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_rewinddir">
+ <code>zzip_rewinddir</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR * dir</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip_off_t
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_telldir">
+ <code>zzip_telldir</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR* dir</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>void
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_seekdir">
+ <code>zzip_seekdir</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR* dir</nobr>,
+<nobr>zzip_off_t offset</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip_off_t
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_seek">
+ <code>zzip_seek</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE * fp</nobr>,
+<nobr>zzip_off_t offset</nobr>,
+<nobr>int whence</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip_char_t*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_strerror">
+ <code>zzip_strerror</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>int errcode</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip_char_t*
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_strerror_of">
+ <code>zzip_strerror_of</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_DIR* dir</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip_off_t
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_tell">
+ <code>zzip_tell</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE * fp</nobr>)</code>
+
+</td>
+</tr>
+<tr valign="top">
+ <td valign="top"><code>zzip_ssize_t
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_write">
+ <code>zzip_write</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE* file</nobr>,
+<nobr>const void* ptr</nobr>,
+<nobr>zzip_size_t len</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip_ssize_t
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_file_write">
+ <code>zzip_file_write</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>ZZIP_FILE* file</nobr>,
+<nobr>const void* ptr</nobr>,
+<nobr>zzip_size_t len</nobr>)</code>
+
+</td>
+
+</tr><tr valign="top">
+ <td valign="top"><code>zzip_size_t
+</code></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="#zzip_fwrite">
+ <code>zzip_fwrite</code> </a></td>
+ <td valign="top">&nbsp;&nbsp;</td>
+ <td valign="top">
+ <code>(<nobr>const void* ptr</nobr>,
+<nobr>zzip_size_t len</nobr>,
+<nobr>zzip_size_t multiply</nobr>,
+<nobr>ZZIP_FILE* file</nobr>)</code>
+
+</td>
+</tr>
+
+</table>
+<h3>Documentation</h3>
+
+<dl>
+<dt><a name="__zzip_fetch_disk_trailer" />
+ <code>int
+</code>
+ <br /><b><code>__zzip_fetch_disk_trailer</code></b>
+ &nbsp; <code>
+ <code>(<nobr>int fd</nobr>,
+<nobr>zzip_off_t filesize</nobr>,
+<nobr>struct _disk_trailer * _zzip_restrict trailer</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/zip.c)
+
+</em></para><p>
+ <br /> <function>The __zzip_fetch_disk_trailer function</function> is used by <a href="#zzip_file_open"><code>zzip_file_open</code></a>. It tries to find
+ <br /> the zip's central directory info that is usually a few
+ <br /> bytes off the end of the file.
+
+</p>
+<p align="right"><small>(../../zzip/zip.c)</small></p></dd>
+<dt><a name="__zzip_get32" /> <a name="__zzip_get16" /> <a name="__zzip_get64" /> <a name="__zzip_set32" /> <a name="__zzip_set16" /> <a name="__zzip_set64" />
+ <code>uint32_t </code>
+ <br /><b><code>__zzip_get32</code></b>
+ &nbsp; <code>
+ <code>(<nobr>unsigned char * s</nobr>)</code>
+
+</code>
+
+<br /> <code>uint16_t </code>
+ <br /><b><code>__zzip_get16</code></b>
+ &nbsp; <code>
+ <code>(<nobr>unsigned char * s</nobr>)</code>
+
+</code>
+
+<br /> <code>uint64_t </code>
+ <br /><b><code>__zzip_get64</code></b>
+ &nbsp; <code>
+ <code>(<nobr>unsigned char * s</nobr>)</code>
+
+</code>
+
+<br /> <code>void </code>
+ <br /><b><code>__zzip_set32</code></b>
+ &nbsp; <code>
+ <code>(<nobr>unsigned char * s</nobr>,
+<nobr>uint32_t v</nobr>)</code>
+
+</code>
+
+<br /> <code>void </code>
+ <br /><b><code>__zzip_set16</code></b>
+ &nbsp; <code>
+ <code>(<nobr>unsigned char * s</nobr>,
+<nobr>uint16_t v</nobr>)</code>
+
+</code>
+
+<br /> <code>void </code>
+ <br /><b><code>__zzip_set64</code></b>
+ &nbsp; <code>
+ <code>(<nobr>unsigned char * s</nobr>,
+<nobr>uint64_t v</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/fetch.c)
+
+</em></para><p>
+ <br /> Make 32 bit value in host byteorder from little-endian mapped octet-data
+ <br /> (works also on machines which SIGBUS on misaligned data access (eg. 68000))
+
+</p>
+<p>
+ <br /> <function>The __zzip_get16 function</function> does the same for a 16 bit value.
+
+</p>
+<p>
+ <br /> <function>The __zzip_get64 function</function> does the same for an off64_t value.
+
+</p>
+<p>
+ <br /> <function>The __zzip_set32 function</function> pushes a 32bit value at the specified address
+
+</p>
+<p>
+ <br /> <function>The __zzip_set16 function</function> does the same for a 16 bit value.
+
+</p>
+<p>
+ <br /> <function>The __zzip_set64 function</function> pushes a off64_t value at the specified address
+
+</p>
+<p align="right"><small>(../../zzip/fetch.c)</small></p></dd>
+<dt><a name="__zzip_parse_root_directory" />
+ <code>int
+</code>
+ <br /><b><code>__zzip_parse_root_directory</code></b>
+ &nbsp; <code>
+ <code>(<nobr>int fd</nobr>,
+<nobr>struct _disk_trailer * trailer</nobr>,
+<nobr>struct zzip_dir_hdr ** hdr_return</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/zip.c)
+
+</em></para><p>
+ <br /> <function>The __zzip_parse_root_directory function</function> is used by <a href="#zzip_file_open"><code>zzip_file_open</code></a>, it is usually called after
+ <br /> <code>__zzip_find_disk_trailer</code>. It will parse the zip's central directory
+ <br /> information and create a zziplib private directory table in
+ <br /> memory.
+
+</p>
+<p align="right"><small>(../../zzip/zip.c)</small></p></dd>
+<dt><a name="__zzip_try_open" />
+ <code>int
+</code>
+ <br /><b><code>__zzip_try_open</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>int filemode</nobr>,
+<nobr>zzip_strings_t* ext</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/zip.c)
+
+</em></para><p>
+ <br /> will attach a .zip extension and tries to open it
+ <br /> the with <code>open</code>(2). This is a helper function for
+ <br /> <a href="#zzip_dir_open"><code>zzip_dir_open</code></a>, <a href="#zzip_opendir"><code>zzip_opendir</code></a> and <a href="#zzip_open"><code>zzip_open</code></a>.
+
+</p>
+<p align="right"><small>(../../zzip/zip.c)</small></p></dd>
+<dt><a name="zzip_closedir" />
+ <code>int
+</code>
+ <br /><b><code>zzip_closedir</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR* dir</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/dir.c)
+
+</em></para><p>
+ <br /> <function>The zzip_closedir function</function> is the equivalent of <code>closedir</code>(3) for a realdir or zipfile.
+
+</p><p>
+
+ <function>The zzip_closedir function</function> is magic - if the given arg-ZZIP_DIR
+ <br /> is a real directory, it will call the real <code>closedir</code>(3) and then
+ <br /> free the wrapping ZZIP_DIR structure. Otherwise it will divert
+ <br /> to <a href="#zzip_dir_close"><code>zzip_dir_close</code></a> which will free the ZZIP_DIR structure.
+
+</p>
+<p align="right"><small>(../../zzip/dir.c)</small></p></dd>
+<dt><a name="zzip_compr_str" />
+ <code>zzip_char_t*
+</code>
+ <br /><b><code>zzip_compr_str</code></b>
+ &nbsp; <code>
+ <code>(<nobr>int compr</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/info.c)
+
+</em></para><p>
+ <br /> return static const string of the known compression methods,
+ <br /> otherwise just "zipped" is returned
+
+</p>
+<p align="right"><small>(../../zzip/info.c)</small></p></dd>
+<dt><a name="zzip_createdir" />
+ <code>ZZIP_DIR*
+</code>
+ <br /><b><code>zzip_createdir</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; create a new archive area for writing
+
+
+</em></para><p>
+
+</p><p>
+
+ <function>The zzip_createdir function</function> will create a new archive area. This may either be a
+ <br /> a new zip archive or a new directory in the filesystem. The returned
+ <br /> parameter is a new "zzip dir" handle that should be saved to a variable
+ <br /> so it can be used a base argument for <a href="#zzip_file_mkdir"><code>zzip_file_mkdir</code></a> and
+ <br /> <a href="#zzip_file_creat"><code>zzip_file_creat</code></a> calls. The returned handle wraps both possibilities,
+ <br /> it can be representing a zip central directory that must be
+ <br /> saved to disk using <a href="#zzip_closedir"><code>zzip_closedir</code></a> or it is just a handle for the
+ <br /> name of the real directory that still must be run through
+ <br /> <a href="#zzip_closedir"><code>zzip_closedir</code></a> to release the wrapper around the directory name.
+
+</p><p>
+
+ The magic is pushed through the o_mode argument. Using a mode that
+ <br /> has no group-write bit set (S_IWGRP = 0040) then the file is
+ <br /> created as a zip directory. Note that this is unabridged of any
+ <br /> umask value in the system where the argument to <function>the zzip_createdir function</function> could
+ <br /> be 0775 but with an umask of 0755 it turns out as 0755 for a real
+ <br /> directory. Using 0755 directly would not create it as a real directory
+ <br /> but as a zip archive handle.
+
+</p><p>
+
+ <function>The zzip_createdir function</function> is not yet implemented, check for #def ZZIP_NO_CREAT
+ <br /> Write-support will extend <a href="#zzip_closedir"><code>zzip_closedir</code></a> with semantics to finalize the
+ <br /> zip-archive by writing the zip-trailer and closing the archive file.
+
+</p><p>
+
+ Returns null on error and sets errno. Remember, according to posix
+ <br /> the <code>creat</code>(2) call is equivalent to
+ <pre> open (path, O_WRONLY | O_CREAT | O_TRUNC, o_mode) </pre>
+ <br /> so any previous zip-archive will be overwritten unconditionally and
+ <br /> EEXIST errors from <code>mkdir</code>(2) are suppressed. (fixme: delete the
+ <br /> given subtree? like suggested by O_TRUNC? not done so far!)
+
+</p>
+<p align="right"><small>(../../zzip/write.c)</small></p></dd>
+<dt><a name="zzip_dir_alloc_ext_io" /> <a name="zzip_dir_alloc" />
+ <code>ZZIP_DIR*
+</code>
+ <br /><b><code>zzip_dir_alloc_ext_io</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_strings_t* ext</nobr>,
+<nobr>const zzip_plugin_io_t io</nobr>)</code>
+
+</code>
+
+<br /> <code>ZZIP_DIR*
+</code>
+ <br /><b><code>zzip_dir_alloc</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_strings_t* fileext</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/zip.c)
+
+</em></para><p>
+ <br /> allocate a new ZZIP_DIR handle and do basic
+ <br /> initializations before usage by <a href="#zzip_dir_fdopen"><code>zzip_dir_fdopen</code></a>
+ <br /> <a href="#zzip_dir_open"><code>zzip_dir_open</code></a> <a href="#zzip_file_open"><code>zzip_file_open</code></a> or through
+ <br /> <a href="#zzip_open"><code>zzip_open</code></a>
+ <br /> (ext==null flags uses { ".zip" , ".ZIP" } )
+ <br /> (io ==null flags use of posix io defaults)
+
+</p>
+<p>
+ <br /> <function>the zzip_dir_alloc function</function> is obsolete - it was generally used for implementation
+ <br /> and exported to let other code build on it. It is now advised to
+ <br /> use <a href="#zzip_dir_alloc_ext_io"><code>zzip_dir_alloc_ext_io</code></a> now on explicitly, just set that second
+ <br /> argument to zero to achieve the same functionality as the old style.
+
+</p>
+<p align="right"><small>(../../zzip/zip.c)</small></p></dd>
+<dt><a name="zzip_dir_creat" /> <a name="zzip_dir_creat_ext_io" />
+ <code>ZZIP_DIR*
+</code>
+ <br /><b><code>zzip_dir_creat</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</code>
+
+<br /> <code>ZZIP_DIR*
+</code>
+ <br /><b><code>zzip_dir_creat_ext_io</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>,
+<nobr>zzip_strings_t* ext</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; create a new zip archive for writing
+
+
+</em></para><p>
+
+</p><p>
+
+ <function>The zzip_dir_creat function</function> will create a new zip archive. The returned parameter
+ <br /> is a new "zzip dir" handle that should be saved to a variable so it
+ <br /> can be used a base argument for <a href="#zzip_mkdir"><code>zzip_mkdir</code></a> and <a href="#zzip_creat"><code>zzip_creat</code></a> calls.
+ <br /> The returned handle represents a zip central directory that must be
+ <br /> saved to disk using <a href="#zzip_closedir"><code>zzip_closedir</code></a>.
+
+</p><p>
+
+ Returns null on error and sets errno. Remember, according to posix
+ <br /> the <code>creat</code>(2) call is equivalent to
+ <pre> open (path, O_WRONLY | O_CREAT | O_TRUNC, o_mode) </pre>
+ <br /> so any previous zip-archive will be overwritten unconditionally and
+ <br /> EEXIST errors from <code>mkdir</code>(2) are suppressed. (fixme: delete the
+ <br /> given subtree? like suggested by O_TRUNC? not done so far!)
+
+</p>
+<p>
+
+</p><p>
+
+ If the third argument "ext" has another special meaning here, as it
+ <br /> is used to ensure that a given zip-file is created with the first entry
+ <br /> of the ext-list appended as an extension unless the file-path already
+ <br /> ends with a file-extension registered in the list. Therefore {"",0}
+ <br /> matches all files and creates them as zip-archives under the given
+ <br /> nonmodified name. (Some magic here? If the path ends in the path
+ <br /> separator then make a real directory even in the presence of ext-list?)
+
+</p><p>
+
+ <function>The zzip_dir_creat_ext_io function</function> is not yet implemented, check for #def ZZIP_NO_CREAT
+ <br /> Write-support will extend <a href="#zzip_closedir"><code>zzip_closedir</code></a> with semantics to finalize the
+ <br /> zip-archive by writing the zip-trailer and closing the archive file.
+
+</p>
+<p align="right"><small>(../../zzip/write.c)</small></p></dd>
+<dt><a name="zzip_dir_fdopen" /> <a name="zzip_dir_fdopen_ext_io" />
+ <code>ZZIP_DIR *
+</code>
+ <br /><b><code>zzip_dir_fdopen</code></b>
+ &nbsp; <code>
+ <code>(<nobr>int fd</nobr>,
+<nobr>zzip_error_t * errcode_p</nobr>)</code>
+
+</code>
+
+<br /> <code>ZZIP_DIR *
+</code>
+ <br /><b><code>zzip_dir_fdopen_ext_io</code></b>
+ &nbsp; <code>
+ <code>(<nobr>int fd</nobr>,
+<nobr>zzip_error_t * errcode_p</nobr>,
+<nobr>zzip_strings_t* ext</nobr>,
+<nobr>const zzip_plugin_io_t io</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/zip.c)
+
+</em></para><p>
+ <br /> used by the <a href="#zzip_dir_open"><code>zzip_dir_open</code></a> and zzip_opendir(2) call. Opens the
+ <br /> zip-archive as specified with the fd which points to an
+ <br /> already openend file. <function>The zzip_dir_fdopen function</function> then search and parse
+ <br /> the zip's central directory.
+
+</p><p>
+
+ NOTE: refcount is zero, so an _open/_close pair will also delete
+ <br /> this _dirhandle
+
+</p>
+<p>
+ <br /> <function>the zzip_dir_fdopen_ext_io function</function> uses explicit ext and io instead of the internal
+ <br /> defaults, setting these to zero is equivalent to <a href="#zzip_dir_fdopen"><code>zzip_dir_fdopen</code></a>
+
+</p>
+<p align="right"><small>(../../zzip/zip.c)</small></p></dd>
+<dt><a name="zzip_dir_free" /> <a name="zzip_dir_close" />
+ <code>int
+</code>
+ <br /><b><code>zzip_dir_free</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR * dir</nobr>)</code>
+
+</code>
+
+<br /> <code>int
+</code>
+ <br /><b><code>zzip_dir_close</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR * dir</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/zip.c)
+
+</em></para><p>
+ <br /> will free the zzip_dir handle unless there are still
+ <br /> zzip_files attached (that may use its cache buffer).
+ <br /> This is the inverse of <a href="#zzip_dir_alloc"><code>zzip_dir_alloc</code></a> , and both
+ <br /> are helper functions used implicitly in other zzipcalls
+ <br /> e.g. <a href="#zzip_dir_close"><code>zzip_dir_close</code></a> = zzip_close
+
+</p><p>
+
+ returns zero on sucess
+ <br /> returns the refcount when files are attached.
+
+</p>
+<p><small><code>zzip_dir_close</code></small> -
+ <br /> It will also <code>free</code>(2) the <code>ZZIP_DIR</code>-handle given.
+ <br /> the counterpart for <a href="#zzip_dir_open"><code>zzip_dir_open</code></a>
+ <br /> see also <a href="#zzip_dir_free"><code>zzip_dir_free</code></a>
+
+</p>
+<p align="right"><small>(../../zzip/zip.c)</small></p></dd>
+<dt><a name="zzip_dir_open" /> <a name="zzip_dir_open_ext_io" /> <a name="zzip_dir_read" />
+ <code>ZZIP_DIR*
+</code>
+ <br /><b><code>zzip_dir_open</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>zzip_error_t* e</nobr>)</code>
+
+</code>
+
+<br /> <code>ZZIP_DIR*
+</code>
+ <br /><b><code>zzip_dir_open_ext_io</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>zzip_error_t* e</nobr>,
+<nobr>zzip_strings_t* ext</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</code>
+
+<br /> <code>int
+</code>
+ <br /><b><code>zzip_dir_read</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR * dir</nobr>,
+<nobr>ZZIP_DIRENT * d</nobr> )</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/zip.c)
+
+</em></para><p>
+ <br /> Opens the zip-archive (if available).
+ <br /> the two ext_io arguments will default to use posix io and
+ <br /> a set of default fileext that can atleast add .zip ext itself.
+
+</p>
+<p>
+ <br /> <function>the zzip_dir_open_ext_io function</function> uses explicit ext and io instead of the internal
+ <br /> defaults. Setting these to zero is equivalent to <a href="#zzip_dir_open"><code>zzip_dir_open</code></a>
+
+</p>
+<p><small><code>zzip_dir_read</code></small> -
+ <br /> fills the dirent-argument with the values and
+ <br /> increments the read-pointer of the dir-argument.
+
+</p><p>
+
+ returns 0 if there no entry (anymore).
+
+</p>
+<p align="right"><small>(../../zzip/zip.c)</small></p></dd>
+<dt><a name="zzip_dir_stat" /> <a name="zzip_file_stat" /> <a name="zzip_fstat" />
+ <code>int
+</code>
+ <br /><b><code>zzip_dir_stat</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR * dir</nobr>,
+<nobr>zzip_char_t* name</nobr>,
+<nobr>ZZIP_STAT * zs</nobr>,
+<nobr>int flags</nobr>)</code>
+
+</code>
+
+<br /> <code>int </code>
+ <br /><b><code>zzip_file_stat</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE* file</nobr>,
+<nobr>ZZIP_STAT* zs</nobr>)</code>
+
+</code>
+
+<br /> <code>int </code>
+ <br /><b><code>zzip_fstat</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE* file</nobr>,
+<nobr>ZZIP_STAT* zs</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/stat.c)
+
+</em></para><p>
+ <br /> obtain information about a filename in an opened zip-archive without
+ <br /> opening that file first. Mostly used to obtain the uncompressed
+ <br /> size of a file inside a zip-archive. see <a href="#zzip_dir_open"><code>zzip_dir_open</code></a>.
+
+</p>
+<p>
+ <br /> <function>The zzip_file_stat function</function> will obtain information about a opened file _within_ a
+ <br /> zip-archive. The file is supposed to be open (otherwise -1 is returned).
+ <br /> The st_size stat-member contains the uncompressed size. The optional
+ <br /> d_name is never set here.
+
+</p>
+<p>
+ <br /> <function>The zzip_fstat function</function> will obtain information about a opened file which may be
+ <br /> either real/zipped. The file is supposed to be open (otherwise -1 is
+ <br /> returned). The st_size stat-member contains the uncompressed size.
+ <br /> The optional d_name is never set here. For a real file, we do set the
+ <br /> d_csize := st_size and d_compr := 0 for meaningful defaults.
+
+</p>
+<p align="right"><small>(../../zzip/stat.c)</small></p></dd>
+<dt><a name="zzip_dirhandle" /> <a name="zzip_dirfd" />
+ <code>ZZIP_DIR *
+</code>
+ <br /><b><code>zzip_dirhandle</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE * fp</nobr>)</code>
+
+</code>
+
+<br /> <code>int
+</code>
+ <br /><b><code>zzip_dirfd</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR* dir</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/info.c)
+
+</em></para><p>
+ <br /> <function>The zzip_dirhandle function</function> will just return fp<small>-&gt;</small>dir
+
+</p><p>
+
+ If a ZZIP_FILE is contained within a zip-file that one will be a valid
+ <br /> pointer, otherwise a NULL is returned and the ZZIP_FILE wraps a real file.
+
+</p>
+<p>
+ <br /> <function>The zzip_dirfd function</function> will just return dir<small>-&gt;</small>fd
+
+</p><p>
+
+ If a ZZIP_DIR does point to a zipfile then the file-descriptor of that
+ <br /> zipfile is returned, otherwise a NULL is returned and the ZZIP_DIR wraps
+ <br /> a real directory DIR (if you have dirent on your system).
+
+</p>
+<p align="right"><small>(../../zzip/info.c)</small></p></dd>
+<dt><a name="zzip_disk_entry_to_data" /> <a name="zzip_disk_entry_to_file_header" /> <a name="zzip_disk_entry_strdup_name" /> <a name="zzip_disk_entry_strdup_comment" />
+ <code>zzip_byte_t*
+</code>
+ <br /><b><code>zzip_disk_entry_to_data</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>struct zzip_disk_entry* entry</nobr>)</code>
+
+</code>
+
+<br /> <code>struct zzip_file_header*
+</code>
+ <br /><b><code>zzip_disk_entry_to_file_header</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>struct zzip_disk_entry* entry</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip__new__ char*
+</code>
+ <br /><b><code>zzip_disk_entry_strdup_name</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>struct zzip_disk_entry* entry</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip__new__ char*
+</code>
+ <br /><b><code>zzip_disk_entry_strdup_comment</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>struct zzip_disk_entry* entry</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; helper functions for (mmapped) zip access api
+
+
+</em></para><p>
+
+</p><p>
+
+ <function>The zzip_disk_entry_to_data function</function> augments the other zzip_disk_entry_* helpers: here we move
+ <br /> a disk_entry pointer (as returned by _find* functions) into a pointer to
+ <br /> the data block right after the file_header. Only disk<small>-&gt;</small>buffer would be
+ <br /> needed to perform the seek but we check the mmapped range end as well.
+
+</p>
+<p>
+ <br /> <function>The zzip_disk_entry_to_file_header function</function> does half the job of <a href="#zzip_disk_entry_to_data"><code>zzip_disk_entry_to_data</code></a> where it
+ <br /> can augment with <code>zzip_file_header_to_data</code> helper from format/fetch.h
+
+</p>
+<p>
+ <br /> <function>The zzip_disk_entry_strdup_name function</function> is a big helper despite its little name: in a zip file the
+ <br /> encoded filenames are usually NOT zero-terminated but for common usage
+ <br /> with libc we need it that way. Secondly, the filename SHOULD be present
+ <br /> in the zip central directory but if not then we fallback to the filename
+ <br /> given in the file_header of each compressed data portion.
+
+</p>
+<p>
+ <br /> <function>The zzip_disk_entry_strdup_comment function</function> is similar creating a reference to a zero terminated
+ <br /> string but it can only exist in the zip central directory entry.
+
+</p>
+<p align="right"><small>(../../zzip/mmapped.c)</small></p></dd>
+<dt><a name="zzip_disk_findfile" /> <a name="zzip_disk_findfirst" /> <a name="zzip_disk_findnext" /> <a name="zzip_disk_findmatch" />
+ <code>struct zzip_disk_entry*
+</code>
+ <br /><b><code>zzip_disk_findfile</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>char* filename</nobr>,
+<nobr>struct zzip_disk_entry* after</nobr>,
+<nobr>zzip_strcmp_fn_t compare</nobr>)</code>
+
+</code>
+
+<br /> <code>struct zzip_disk_entry*
+</code>
+ <br /><b><code>zzip_disk_findfirst</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK* disk</nobr>)</code>
+
+</code>
+
+<br /> <code>struct zzip_disk_entry*
+</code>
+ <br /><b><code>zzip_disk_findnext</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>struct zzip_disk_entry* entry</nobr>)</code>
+
+</code>
+
+<br /> <code>struct zzip_disk_entry*
+</code>
+ <br /><b><code>zzip_disk_findmatch</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>char* filespec</nobr>,
+<nobr>struct zzip_disk_entry* after</nobr>,
+<nobr>zzip_fnmatch_fn_t compare</nobr>,
+<nobr>int flags</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; search for files in the (mmapped) zip central directory
+
+
+</em></para><p>
+
+</p><p>
+
+ <function>The zzip_disk_findfile function</function> is given a filename as an additional argument, to find the
+ <br /> disk_entry matching a given filename. The compare-function is usually
+ <br /> strcmp or strcasecmp or perhaps strcoll, if null then strcmp is used.
+ <br /> - use null as argument for "after"-entry when searching the first
+ <br /> matching entry, otherwise the last returned value if you look for other
+ <br /> entries with a special "compare" function (if null then a doubled search
+ <br /> is rather useless with this variant of _findfile).
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_disk_findfirst function</function> is the first call of all the zip access functions here.
+ <br /> It contains the code to find the first entry of the zip central directory.
+ <br /> Here we require the mmapped block to represent a real zip file where the
+ <br /> disk_trailer is _last_ in the file area, so that its position would be at
+ <br /> a fixed offset from the end of the file area if not for the comment field
+ <br /> allowed to be of variable length (which needs us to do a little search
+ <br /> for the disk_tailer). However, in this simple implementation we disregard
+ <br /> any disk_trailer info telling about multidisk archives, so we just return
+ <br /> a pointer to the zip central directory.
+
+</p><p>
+
+ For an actual means, we are going to search backwards from the end
+ <br /> of the mmaped block looking for the PK-magic signature of a
+ <br /> disk_trailer. If we see one then we check the rootseek value to
+ <br /> find the first disk_entry of the root central directory. If we find
+ <br /> the correct PK-magic signature of a disk_entry over there then we
+ <br /> assume we are done and we are going to return a pointer to that label.
+
+</p><p>
+
+ The return value is a pointer to the first zzip_disk_entry being checked
+ <br /> to be within the bounds of the file area specified by the arguments. If
+ <br /> no disk_trailer was found then null is returned, and likewise we only
+ <br /> accept a disk_trailer with a seekvalue that points to a disk_entry and
+ <br /> both parts have valid PK-magic parts. Beyond some sanity check we try to
+ <br /> catch a common brokeness with zip archives that still allows us to find
+ <br /> the start of the zip central directory.
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_disk_findnext function</function> takes an existing disk_entry in the central root directory
+ <br /> (e.g. from zzip_disk_findfirst) and returns the next entry within in
+ <br /> the given bounds of the mmapped file area.
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_disk_findmatch function</function> uses a compare-function with an additional argument
+ <br /> and it is called just like fnmatch(3) from POSIX.2 AD:1993), i.e.
+ <br /> the argument filespec first and the ziplocal filename second with
+ <br /> the integer-flags put in as third to the indirect call. If the
+ <br /> platform has fnmatch available then null-compare will use that one
+ <br /> and otherwise we fall back to mere strcmp, so if you need fnmatch
+ <br /> searching then please provide an implementation somewhere else.
+ <br /> - use null as argument for "after"-entry when searching the first
+ <br /> matching entry, or the last disk_entry return-value to find the
+ <br /> next entry matching the given filespec.
+
+</p>
+<p align="right"><small>(../../zzip/mmapped.c)</small></p></dd>
+<dt><a name="zzip_disk_fopen" /> <a name="zzip_disk_entry_fopen" /> <a name="zzip_disk_fread" /> <a name="zzip_disk_fclose" /> <a name="zzip_disk_feof" />
+ <code>zzip__new__ ZZIP_DISK_FILE*
+</code>
+ <br /><b><code>zzip_disk_fopen</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>char* filename</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip__new__ ZZIP_DISK_FILE*
+</code>
+ <br /><b><code>zzip_disk_entry_fopen</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>ZZIP_DISK_ENTRY* entry</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip_size_t
+</code>
+ <br /><b><code>zzip_disk_fread</code></b>
+ &nbsp; <code>
+ <code>(<nobr>void* ptr</nobr>,
+<nobr>zzip_size_t sized</nobr>,
+<nobr>zzip_size_t nmemb</nobr>,
+<nobr>ZZIP_DISK_FILE* file</nobr>)</code>
+
+</code>
+
+<br /> <code>int
+</code>
+ <br /><b><code>zzip_disk_fclose</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK_FILE* file</nobr>)</code>
+
+</code>
+
+<br /> <code>int
+</code>
+ <br /><b><code>zzip_disk_feof</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK_FILE* file</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; openening a file part wrapped within a (mmapped) zip archive
+
+
+</em></para><p>
+
+</p><p>
+
+ <function>The zzip_disk_fopen function</function> opens a file found by name, so it does a search into
+ <br /> the zip central directory with <a href="#zzip_disk_findfile"><code>zzip_disk_findfile</code></a> and whatever
+ <br /> is found first is given to <a href="#zzip_disk_entry_fopen"><code>zzip_disk_entry_fopen</code></a>
+
+</p>
+<p>
+
+</p><p>
+
+ the ZZIP_DISK_FILE* is rather simple in just encapsulating the
+ <br /> arguments given to <function>the zzip_disk_entry_fopen function</function> plus a zlib deflate buffer.
+ <br /> Note that the ZZIP_DISK pointer does already contain the full
+ <br /> mmapped file area of a zip disk, so open()ing a file part within
+ <br /> that area happens to be a lookup of its bounds and encoding. That
+ <br /> information is memorized on the ZZIP_DISK_FILE so that subsequent
+ <br /> _read() operations will be able to get the next data portion or
+ <br /> return an eof condition for that file part wrapped in the zip archive.
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_disk_fread function</function> reads more bytes into the output buffer specified as
+ <br /> arguments. The return value is null on eof or error, the stdio-like
+ <br /> interface can not distinguish between these so you need to check
+ <br /> with <a href="#zzip_disk_feof"><code>zzip_disk_feof</code></a> for the difference.
+
+</p>
+<p>
+ <br /> <function>The zzip_disk_fclose function</function> releases any zlib decoder info needed for decompression
+ <br /> and dumps the ZZIP_DISK_FILE* then.
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_disk_feof function</function> allows to distinguish an error from an eof condition.
+ <br /> Actually, if we found an error but we did already reach eof then we
+ <br /> just keep on saying that it was an eof, so the app can just continue.
+
+</p>
+<p align="right"><small>(../../zzip/mmapped.c)</small></p></dd>
+<dt><a name="zzip_disk_mmap" /> <a name="zzip_disk_init" /> <a name="zzip_disk_new" /> <a name="zzip_disk_munmap" /> <a name="zzip_disk_open" /> <a name="zzip_disk_close" />
+ <code>zzip__new__ ZZIP_DISK*
+</code>
+ <br /><b><code>zzip_disk_mmap</code></b>
+ &nbsp; <code>
+ <code>(<nobr>int fd</nobr>)</code>
+
+</code>
+
+<br /> <code>int
+</code>
+ <br /><b><code>zzip_disk_init</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>void* buffer</nobr>,
+<nobr>zzip_size_t buflen</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip__new__ ZZIP_DISK*
+</code>
+ <br /><b><code>zzip_disk_new</code></b>
+ &nbsp; <code>
+ <code>(<nobr>void</nobr>)</code>
+
+</code>
+
+<br /> <code>int
+</code>
+ <br /><b><code>zzip_disk_munmap</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK* disk</nobr>)</code>
+
+</code>
+
+<br /> <code>ZZIP_DISK* zzip__new__
+</code>
+ <br /><b><code>zzip_disk_open</code></b>
+ &nbsp; <code>
+ <code>(<nobr>char* filename</nobr>)</code>
+
+</code>
+
+<br /> <code>int
+</code>
+ <br /><b><code>zzip_disk_close</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK* disk</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; turn a filehandle into a mmapped zip disk archive handle
+
+
+</em></para><p>
+
+</p><p>
+
+ <function>The zzip_disk_mmap function</function> uses the given file-descriptor to detect the length of the
+ <br /> file and calls the system <code>mmap</code>(2) to put it in main memory. If it is
+ <br /> successful then a newly allocated ZZIP_DISK* is returned with
+ <br /> disk<small>-&gt;</small>buffer pointing to the mapview of the zipdisk content.
+
+</p>
+<p>
+ <br /> <function>The zzip_disk_init function</function> does primary initialization of a disk-buffer struct.
+
+</p>
+<p>
+ <br /> <function>The zzip_disk_new function</function> allocates a new disk-buffer with <code>malloc</code>(3)
+
+</p>
+<p>
+ <br /> <function>The zzip_disk_munmap function</function> is the inverse of <a href="#zzip_disk_mmap"><code>zzip_disk_mmap</code></a> and using the system
+ <br /> munmap(2) on the buffer area and <code>free</code>(3) on the ZZIP_DISK structure.
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_disk_open function</function> opens the given archive by name and turn the filehandle
+ <br /> to <a href="#zzip_disk_mmap"><code>zzip_disk_mmap</code></a> for bringing it to main memory. If it can not
+ <br /> be <code>mmap</code>(2)'ed then we slurp the whole file into a newly <code>malloc</code>(2)'ed
+ <br /> memory block. Only if that fails too then we return null. Since handling
+ <br /> of disk<small>-&gt;</small>buffer is ambigous it should not be snatched away please.
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_disk_close function</function> will release all data needed to access a (mmapped)
+ <br /> zip archive, including any malloc()ed blocks, sharedmem mappings
+ <br /> and it dumps the handle struct as well.
+
+</p>
+<p align="right"><small>(../../zzip/mmapped.c)</small></p></dd>
+<dt><a name="zzip_entry_data_offset" /> <a name="zzip_entry_fread_file_header" /> <a name="zzip_entry_strdup_name" />
+ <code>zzip_off_t
+</code>
+ <br /><b><code>zzip_entry_data_offset</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_ENTRY* entry</nobr>)</code>
+
+</code>
+
+<br /> <code>static zzip_off_t
+</code>
+ <br /><b><code>zzip_entry_fread_file_header</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_ENTRY* entry</nobr>,
+<nobr>struct zzip_file_header* file_header</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip__new__ char*
+</code>
+ <br /><b><code>zzip_entry_strdup_name</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_ENTRY* entry</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; helper functions for (fseeko) zip access api
+
+
+</em></para><p>
+
+</p><p>
+
+ <function>The zzip_entry_data_offset function</function>s returns the seekval offset of the data portion of the
+ <br /> file referenced by the given zzip_entry. It requires an intermediate
+ <br /> check of the file_header structure (i.e. it reads it from disk). After
+ <br /> this call, the contained diskfile readposition is already set to the
+ <br /> data_offset returned here. On error -1 is returned.
+
+</p>
+<p>
+ <br /> <function>The zzip_entry_fread_file_header function</function>s read the correspoding struct zzip_file_header from
+ <br /> the zip disk of the given "entry". The returned off_t points to the
+ <br /> end of the file_header where the current fseek pointer has stopped.
+ <br /> This is used to immediatly parse out any filename/extras block following
+ <br /> the file_header. The return value is null on error.
+
+</p>
+<p>
+ <br /> <function>The zzip_entry_strdup_name function</function> is a big helper despite its little name: in a zip file the
+ <br /> encoded filenames are usually NOT zero-terminated but for common usage
+ <br /> with libc we need it that way. Secondly, the filename SHOULD be present
+ <br /> in the zip central directory but if not then we fallback to the filename
+ <br /> given in the file_header of each compressed data portion.
+
+</p>
+<p align="right"><small>(../../zzip/fseeko.c)</small></p></dd>
+<dt><a name="zzip_entry_findfile" /> <a name="zzip_entry_findfirst" /> <a name="zzip_entry_findnext" /> <a name="zzip_entry_free" /> <a name="zzip_entry_findmatch" />
+ <code>zzip__new__ ZZIP_ENTRY*
+</code>
+ <br /><b><code>zzip_entry_findfile</code></b>
+ &nbsp; <code>
+ <code>(<nobr>FILE* disk</nobr>,
+<nobr>char* filename</nobr>,
+<nobr>ZZIP_ENTRY* _zzip_restrict entry</nobr>,
+<nobr>zzip_strcmp_fn_t compare</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip__new__ ZZIP_ENTRY*
+</code>
+ <br /><b><code>zzip_entry_findfirst</code></b>
+ &nbsp; <code>
+ <code>(<nobr>FILE* disk</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip__new__ ZZIP_ENTRY*
+</code>
+ <br /><b><code>zzip_entry_findnext</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_ENTRY* _zzip_restrict entry</nobr>)</code>
+
+</code>
+
+<br /> <code>int
+</code>
+ <br /><b><code>zzip_entry_free</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_ENTRY* entry</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip__new__ ZZIP_ENTRY*
+</code>
+ <br /><b><code>zzip_entry_findmatch</code></b>
+ &nbsp; <code>
+ <code>(<nobr>FILE* disk</nobr>,
+<nobr>char* filespec</nobr>,
+<nobr>ZZIP_ENTRY* _zzip_restrict entry</nobr>,
+<nobr>zzip_fnmatch_fn_t compare</nobr>,
+<nobr>int flags</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; search for files in the (fseeko) zip central directory
+
+
+</em></para><p>
+
+</p><p>
+
+ <function>The zzip_entry_findfile function</function> is given a filename as an additional argument, to find the
+ <br /> disk_entry matching a given filename. The compare-function is usually
+ <br /> strcmp or strcasecmp or perhaps strcoll, if null then strcmp is used.
+ <br /> - use null as argument for "old"-entry when searching the first
+ <br /> matching entry, otherwise the last returned value if you look for other
+ <br /> entries with a special "compare" function (if null then a doubled search
+ <br /> is rather useless with this variant of _findfile). If no further entry is
+ <br /> found then null is returned and any "old"-entry gets already free()d.
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_entry_findfirst function</function> is the first call of all the zip access functions here.
+ <br /> It contains the code to find the first entry of the zip central directory.
+ <br /> Here we require the stdio handle to represent a real zip file where the
+ <br /> disk_trailer is _last_ in the file area, so that its position would be at
+ <br /> a fixed offset from the end of the file area if not for the comment field
+ <br /> allowed to be of variable length (which needs us to do a little search
+ <br /> for the disk_tailer). However, in this simple implementation we disregard
+ <br /> any disk_trailer info telling about multidisk archives, so we just return
+ <br /> a pointer to the first entry in the zip central directory of that file.
+
+</p><p>
+
+ For an actual means, we are going to search backwards from the end
+ <br /> of the mmaped block looking for the PK-magic signature of a
+ <br /> disk_trailer. If we see one then we check the rootseek value to
+ <br /> find the first disk_entry of the root central directory. If we find
+ <br /> the correct PK-magic signature of a disk_entry over there then we
+ <br /> assume we are done and we are going to return a pointer to that label.
+
+</p><p>
+
+ The return value is a pointer to the first zzip_disk_entry being checked
+ <br /> to be within the bounds of the file area specified by the arguments. If
+ <br /> no disk_trailer was found then null is returned, and likewise we only
+ <br /> accept a disk_trailer with a seekvalue that points to a disk_entry and
+ <br /> both parts have valid PK-magic parts. Beyond some sanity check we try to
+ <br /> catch a common brokeness with zip archives that still allows us to find
+ <br /> the start of the zip central directory.
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_entry_findnext function</function> takes an existing "entry" in the central root directory
+ <br /> (e.g. from zzip_entry_findfirst) and moves it to point to the next entry.
+ <br /> On error it returns 0, otherwise the old entry. If no further match is
+ <br /> found then null is returned and the entry already free()d. If you want
+ <br /> to stop searching for matches before that case then please call
+ <br /> <a href="#zzip_entry_free"><code>zzip_entry_free</code></a> on the cursor struct ZZIP_ENTRY.
+
+</p>
+<p>
+ <br /> <function>the zzip_entry_free function</function> releases the malloc()ed areas needed for zzip_entry, the
+ <br /> pointer is invalid afterwards. <function>The zzip_entry_free function</function> has #define synonyms of
+ <br /> zzip_entry_findlast(), zzip_entry_findlastfile(), zzip_entry_findlastmatch()
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_entry_findmatch function</function> uses a compare-function with an additional argument
+ <br /> and it is called just like fnmatch(3) from POSIX.2 AD:1993), i.e.
+ <br /> the argument filespec first and the ziplocal filename second with
+ <br /> the integer-flags put in as third to the indirect call. If the
+ <br /> platform has fnmatch available then null-compare will use that one
+ <br /> and otherwise we fall back to mere strcmp, so if you need fnmatch
+ <br /> searching then please provide an implementation somewhere else.
+ <br /> - use null as argument for "after"-entry when searching the first
+ <br /> matching entry, or the last disk_entry return-value to find the
+ <br /> next entry matching the given filespec. If no further entry is
+ <br /> found then null is returned and any "old"-entry gets already free()d.
+
+</p>
+<p align="right"><small>(../../zzip/fseeko.c)</small></p></dd>
+<dt><a name="zzip_entry_fopen" /> <a name="zzip_entry_ffile" /> <a name="zzip_entry_fread" /> <a name="zzip_entry_fclose" /> <a name="zzip_entry_feof" />
+ <code>zzip__new__ ZZIP_ENTRY_FILE*
+</code>
+ <br /><b><code>zzip_entry_fopen</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_ENTRY* entry</nobr>,
+<nobr>int takeover</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip__new__ ZZIP_ENTRY_FILE*
+</code>
+ <br /><b><code>zzip_entry_ffile</code></b>
+ &nbsp; <code>
+ <code>(<nobr>FILE* disk</nobr>,
+<nobr>char* filename</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip_size_t
+</code>
+ <br /><b><code>zzip_entry_fread</code></b>
+ &nbsp; <code>
+ <code>(<nobr>void* ptr</nobr>,
+<nobr>zzip_size_t sized</nobr>,
+<nobr>zzip_size_t nmemb</nobr>,
+<nobr>ZZIP_ENTRY_FILE* file</nobr>)</code>
+
+</code>
+
+<br /> <code>int
+</code>
+ <br /><b><code>zzip_entry_fclose</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_ENTRY_FILE* file</nobr>)</code>
+
+</code>
+
+<br /> <code>int
+</code>
+ <br /><b><code>zzip_entry_feof</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_ENTRY_FILE* file</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; open a file within a zip disk for reading
+
+
+</em></para><p>
+
+</p><p>
+
+ <function>The zzip_entry_fopen function</function> does take an "entry" argument and copies it (or just takes
+ <br /> it over as owner) to a new ZZIP_ENTRY_FILE handle structure. That
+ <br /> structure contains also a zlib buffer for decoding. <function>The zzip_entry_fopen function</function> does
+ <br /> seek to the file_header of the given "entry" and validates it for the
+ <br /> data buffer following it. We do also prefetch some data from the data
+ <br /> buffer thereby trying to match the disk pagesize for faster access later.
+ <br /> The <a href="#zzip_entry_fread"><code>zzip_entry_fread</code></a> will then read in chunks of pagesizes which is
+ <br /> the size of the internal readahead buffer. If an error occurs then null
+ <br /> is returned.
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_entry_ffile function</function> opens a file found by name, so it does a search into
+ <br /> the zip central directory with <a href="#zzip_entry_findfile"><code>zzip_entry_findfile</code></a> and whatever
+ <br /> is found first is given to <a href="#zzip_entry_fopen"><code>zzip_entry_fopen</code></a>
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_entry_fread function</function> reads more bytes into the output buffer specified as
+ <br /> arguments. The return value is null on eof or error, the stdio-like
+ <br /> interface can not distinguish between these so you need to check
+ <br /> with <a href="#zzip_entry_feof"><code>zzip_entry_feof</code></a> for the difference.
+
+</p>
+<p>
+ <br /> <function>The zzip_entry_fclose function</function> releases any zlib decoder info needed for decompression
+ <br /> and dumps the ZZIP_ENTRY_FILE struct then.
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_entry_feof function</function> allows to distinguish an error from an eof condition.
+ <br /> Actually, if we found an error but we did already reach eof then we
+ <br /> just keep on saying that it was an eof, so the app can just continue.
+
+</p>
+<p align="right"><small>(../../zzip/fseeko.c)</small></p></dd>
+<dt><a name="zzip_errno" />
+ <code>int
+</code>
+ <br /><b><code>zzip_errno</code></b>
+ &nbsp; <code>
+ <code>(<nobr>int errcode</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/err.c)
+
+</em></para><p>
+ <br /> map the error code to a system error code. This is used
+ <br /> for the drop-in replacement functions to return a value
+ <br /> that can be interpreted correctly by code sections that
+ <br /> are unaware of the fact they their <code>open</code>(2) call had been
+ <br /> diverted to a file inside a zip-archive.
+
+</p>
+<p align="right"><small>(../../zzip/err.c)</small></p></dd>
+<dt><a name="zzip_error" /> <a name="zzip_seterror" />
+ <code>int
+</code>
+ <br /><b><code>zzip_error</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR * dir</nobr>)</code>
+
+</code>
+
+<br /> <code>void
+</code>
+ <br /><b><code>zzip_seterror</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR * dir</nobr>,
+<nobr>int errcode</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/info.c)
+
+</em></para><p>
+ <br /> just returns dir<small>-&gt;</small>errcode of the ZZIP_DIR handle
+ <br /> see: <a href="#zzip_dir_open"><code>zzip_dir_open</code></a>, <code>zzip_diropen</code>, <a href="#zzip_readdir"><code>zzip_readdir</code></a>, <a href="#zzip_dir_read"><code>zzip_dir_read</code></a>
+
+</p>
+<p>
+ <br /> <function>The zzip_seterror function</function> just does dir<small>-&gt;</small>errcode = errcode
+
+</p>
+<p align="right"><small>(../../zzip/info.c)</small></p></dd>
+<dt><a name="zzip_fclose" /> <a name="zzip_close" />
+ <code>int
+</code>
+ <br /><b><code>zzip_fclose</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE * fp</nobr>)</code>
+
+</code>
+
+<br /> <code>int
+</code>
+ <br /><b><code>zzip_close</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE* fp</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/file.c)
+
+</em></para><p>
+ <br /> <function>The zzip_fclose function</function> closes the given ZZIP_FILE handle.
+
+</p><p>
+
+ If the ZZIP_FILE wraps a normal stat'fd then it is just that int'fd
+ <br /> that is being closed and the otherwise empty ZZIP_FILE gets freed.
+
+</p>
+<p><small><code>zzip_close</code></small> -
+
+</p>
+<p align="right"><small>(../../zzip/file.c)</small></p></dd>
+<dt><a name="zzip_file_close" />
+ <code>int
+</code>
+ <br /><b><code>zzip_file_close</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE * fp</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/file.c)
+
+</em></para><p>
+ <br /> the direct function of <a href="#zzip_close"><code>zzip_close</code></a>(fp). it will cleanup the
+ <br /> inflate-portion of <code>zlib</code> and free the structure given.
+
+</p><p>
+
+ it is called quite from the error-cleanup parts
+ <br /> of the various <code>_open</code> functions.
+
+</p><p>
+
+ the .refcount is decreased and if zero the fp<small>-&gt;</small>dir is closed just as well.
+
+</p>
+<p align="right"><small>(../../zzip/file.c)</small></p></dd>
+<dt><a name="zzip_file_creat" /> <a name="zzip_file_mkdir" />
+ <code>ZZIP_FILE*
+</code>
+ <br /><b><code>zzip_file_creat</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR* dir</nobr>,
+<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</code>
+
+<br /> <code>int
+</code>
+ <br /><b><code>zzip_file_mkdir</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR* dir</nobr>,
+<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; start next file entry in a zip archive
+
+
+</em></para><p>
+
+</p><p>
+
+ <function>The zzip_file_creat function</function> will create a new file within a zzip archive, the
+ <br /> one given as the primary argument and additionally to the posix
+ <br /> creat(2) - just like zzip_mkdir has an additional argument over
+ <br /> the posix mkdir(2) spec. For <function>the zzip_file_creat function</function> the primary parameter
+ <br /> can be null as well thereby creating a real file instead of a new
+ <br /> one inside the zip-archive otherwise given. If the primary parameter is
+ <br /> not null but wraps a real directory then all new files are also real.
+
+</p><p>
+
+ <function>The zzip_file_creat function</function> is not yet implemented, check for #def ZZIP_NO_CREAT
+
+</p><p>
+
+ Returns NULL on an error setting errno, and opening a file _within_
+ <br /> a zip archive using O_RDONLY (and similar stuff) will surely lead to
+ <br /> an error.
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_file_mkdir function</function> has an additional primary argument over the posix
+ <br /> mkdir(2) - if it is null then <function>the zzip_file_mkdir function</function> behaves just like
+ <br /> posix mkdir(2). The zzip_dir argument can be set to the result
+ <br /> of a <a href="#zzip_createdir"><code>zzip_createdir</code></a> which allows for some magic that the
+ <br /> given directory name is created as an entry in the zip archive.
+
+</p><p>
+
+ If the given dir name argument is not within the basepath of
+ <br /> the zip central directory then a real directory is created.
+ <br /> Any EEXIST errors are not suppressed unlike with <a href="#zzip_createdir"><code>zzip_createdir</code></a>
+
+</p><p>
+
+ Standard usage accepts a global/threaded/modular ZZIP_DIR pointer
+ <br /> for all zip archive operations like in:
+ <pre> ZZIP_DIR* zip = zzip_createdir (sysconfpath, 0755, zip);
+ zzip_file_mkdir (zip, filepath[i], 0755);
+ ZZIP_FILE* file = zzip_file_creat (zip, filename[i], 0644);
+ zzip_write (file, buf, len);
+ zzip_close (file); file = 0;
+ zzip_closedir (zip); zip = 0; </pre>
+
+</p><p>
+
+ compare with <a href="#zzip_mkdir"><code>zzip_mkdir</code></a> inline macro which allows to
+ <br /> collapse the examples script to
+ <pre> #define zzip_savefile myproject_saveconfig
+ #include &lt;zzip/zzip.h&gt;
+ ZZIP_DIR* zzip_savefile = zzip_createdir (sysconfpath, 0755);
+ zzip_mkdir (filepath[i], 0755);
+ ZZIP_FILE* file = zzip_creat(filepath[i], 0644);
+ zzip_write (file, buf, len);
+ zzip_close (file); file = 0;
+ zzip_closedir (zip_savefile); </pre>
+
+</p>
+<p align="right"><small>(../../zzip/write.c)</small></p></dd>
+<dt><a name="zzip_file_open" />
+ <code>ZZIP_FILE *
+</code>
+ <br /><b><code>zzip_file_open</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR * dir</nobr>,
+<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/file.c)
+
+</em></para><p>
+ <br /> open an <code>ZZIP_FILE</code> from an already open <code>ZZIP_DIR</code> handle. Since
+ <br /> we have a chance to reuse a cached <code>buf32k</code> and <code>ZZIP_FILE</code> memchunk
+ <br /> this is the best choice to unpack multiple files.
+
+</p><p>
+
+ Note: the zlib supports 2..15 bit windowsize, hence we provide a 32k
+ <br /> memchunk here... just to be safe.
+
+</p>
+<p align="right"><small>(../../zzip/file.c)</small></p></dd>
+<dt><a name="zzip_file_read" />
+ <code>zzip_ssize_t
+</code>
+ <br /><b><code>zzip_file_read</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE * fp</nobr>,
+<nobr>char * buf</nobr>,
+<nobr>zzip_size_t len</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/file.c)
+
+</em></para><p>
+ <br /> <function>The zzip_file_read function</function>s read data from zip-contained file.
+
+</p><p>
+
+ It works like <code>read</code>(2) and will fill the given buffer with bytes from
+ <br /> the opened file. It will return the number of bytes read, so if the <code>EOF</code>
+ <br /> is encountered you will be prompted with the number of bytes actually read.
+
+</p><p>
+
+ This is the routines that needs the <code>buf32k</code> buffer, and it would have
+ <br /> need for much more polishing but it does already work quite well.
+
+</p><p>
+
+ Note: the 32K buffer is rather big. The original inflate-algorithm
+ <br /> required just that but the latest zlib would work just fine with
+ <br /> a smaller buffer.
+
+</p>
+<p align="right"><small>(../../zzip/file.c)</small></p></dd>
+<dt><a name="zzip_file_real" /> <a name="zzip_dir_real" /> <a name="zzip_realdir" /> <a name="zzip_realfd" />
+ <code>int
+</code>
+ <br /><b><code>zzip_file_real</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE* fp</nobr>)</code>
+
+</code>
+
+<br /> <code>int
+</code>
+ <br /><b><code>zzip_dir_real</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR* dir</nobr>)</code>
+
+</code>
+
+<br /> <code>void*
+</code>
+ <br /><b><code>zzip_realdir</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR* dir</nobr>)</code>
+
+</code>
+
+<br /> <code>int
+</code>
+ <br /><b><code>zzip_realfd</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE* fp</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/info.c)
+
+</em></para><p>
+ <br /> <function>The zzip_file_real function</function> checks if the ZZIP_FILE-handle is wrapping
+ <br /> a real file or a zip-contained file.
+ <br /> Returns 1 for a stat'able file, and 0 for a file inside a zip-archive.
+
+</p>
+<p>
+ <br /> <function>The zzip_dir_real function</function> checks if the ZZIP_DIR-handle is wrapping
+ <br /> a real directory or a zip-archive.
+ <br /> Returns 1 for a stat'able directory, and 0 for a handle to zip-archive.
+
+</p>
+<p>
+ <br /> <function>The zzip_realdir function</function> returns the posix DIR* handle (if one exists).
+ <br /> Check before with <a href="#zzip_dir_real"><code>zzip_dir_real</code></a> if the
+ <br /> the ZZIP_DIR points to a real directory.
+
+</p>
+<p>
+ <br /> <function>The zzip_realfd function</function> returns the posix file descriptor (if one exists).
+ <br /> Check before with <a href="#zzip_file_real"><code>zzip_file_real</code></a> if the
+ <br /> the ZZIP_FILE points to a real file.
+
+</p>
+<p align="right"><small>(../../zzip/info.c)</small></p></dd>
+<dt><a name="zzip_fopen" /> <a name="zzip_freopen" />
+ <code>ZZIP_FILE*
+</code>
+ <br /><b><code>zzip_fopen</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>zzip_char_t* mode</nobr>)</code>
+
+</code>
+
+<br /> <code>ZZIP_FILE*
+</code>
+ <br /><b><code>zzip_freopen</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>zzip_char_t* mode</nobr>,
+<nobr>ZZIP_FILE* stream</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/file.c)
+
+</em></para><p>
+ <br /> <function>The zzip_fopen function</function> will <code>fopen</code>(3) a real/zipped file.
+
+</p><p>
+
+ It has some magic functionality builtin - it will first try to open
+ <br /> the given <em>filename</em> as a normal file. If it does not
+ <br /> exist, the given path to the filename (if any) is split into
+ <br /> its directory-part and the file-part. A ".zip" extension is
+ <br /> then added to the directory-part to create the name of a
+ <br /> zip-archive. That zip-archive (if it exists) is being searched
+ <br /> for the file-part, and if found a zzip-handle is returned.
+
+</p><p>
+
+ Note that if the file is found in the normal fs-directory the
+ <br /> returned structure is mostly empty and the <a href="#zzip_read"><code>zzip_read</code></a> call will
+ <br /> use the libc <code>read</code> to obtain data. Otherwise a <a href="#zzip_file_open"><code>zzip_file_open</code></a>
+ <br /> is performed and any error mapped to <code>errno</code>(3).
+
+</p><p>
+
+ unlike the posix-wrapper <a href="#zzip_open"><code>zzip_open</code></a> the mode-argument is
+ <br /> a string which allows for more freedom to support the extra
+ <br /> zzip modes called ZZIP_CASEINSENSITIVE and ZZIP_IGNOREPATH.
+ <br /> Currently, this <a href="#zzip_fopen"><code>zzip_fopen</code></a> call will convert the following
+ <br /> characters in the mode-string into their corrsponding mode-bits:
+ <br /> <ul><li><code> "r" : O_RDONLY : </code> read-only
+ <br /> </li><li><code> "b" : O_BINARY : </code> binary (win32 specific)
+ <br /> </li><li><code> "f" : O_NOCTTY : </code> no char device (unix)
+ <br /> </li><li><code> "i" : ZZIP_CASELESS : </code> inside zip file
+ <br /> </li><li><code> "*" : ZZIP_NOPATHS : </code> inside zip file only
+ <br /> </ul> all other modes will be ignored for zip-contained entries
+ <br /> but they are transferred for compatibility and portability,
+ <br /> including these extra sugar bits:
+ <br /> <ul><li><code> "x" : O_EXCL :</code> fail if file did exist
+ <br /> </li><li><code> "s" : O_SYNC :</code> synchronized access
+ <br /> </li><li><code> "n" : O_NONBLOCK :</code> nonblocking access
+ <br /> </li><li><code> "z#" : compression level :</code> for zlib
+ <br /> </li><li><code> "g#" : group access :</code> unix access bits
+ <br /> </li><li><code> "u#" : owner access :</code> unix access bits
+ <br /> </li><li><code> "o#" : world access :</code> unix access bits
+ <br /> </ul>... the access bits are in traditional unix bit format
+ <br /> with 7 = read/write/execute, 6 = read/write, 4 = read-only.
+
+</p><p>
+
+ The default access mode is 0664, and the compression level
+ <br /> is ignored since the lib can not yet write zip files, otherwise
+ <br /> it would be the initialisation value for the zlib deflateInit
+ <br /> where 0 = no-compression, 1 = best-speed, 9 = best-compression.
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_freopen function</function> receives an additional argument pointing to
+ <br /> a ZZIP_FILE* being already in use. If this extra argument is
+ <br /> null then <function>the zzip_freopen function</function> is identical with calling <a href="#zzip_fopen"><code>zzip_fopen</code></a>
+
+</p><p>
+
+ Per default, the old file stream is closed and only the internal
+ <br /> structures associated with it are kept. These internal structures
+ <br /> may be reused for the return value, and this is a lot quicker when
+ <br /> the filename matches a zipped file that is incidently in the very
+ <br /> same zip arch as the old filename wrapped in the stream struct.
+
+</p><p>
+
+ That's simply because the zip arch's central directory does not
+ <br /> need to be read again. As an extension for <function>the zzip_freopen function</function>, if the
+ <br /> mode-string contains a "q" then the old stream is not closed but
+ <br /> left untouched, instead it is only given as a hint that a new
+ <br /> file handle may share/copy the zip arch structures of the old file
+ <br /> handle if that is possible, i.e when they are in the same zip arch.
+
+</p>
+<p align="right"><small>(../../zzip/file.c)</small></p></dd>
+<dt><a name="zzip_inflate_init" />
+ <code>static int
+</code>
+ <br /><b><code>zzip_inflate_init</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE * fp</nobr>,
+<nobr>struct zzip_dir_hdr* hdr</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/file.c)
+
+</em></para><p>
+ <br /> call <code>inflateInit</code> and setup fp's iterator variables,
+ <br /> used by lowlevel <code>_open</code> functions.
+
+</p>
+<p align="right"><small>(../../zzip/file.c)</small></p></dd>
+<dt><a name="zzip_init_io" /> <a name="zzip_get_default_io" />
+ <code>int </code>
+ <br /><b><code>zzip_init_io</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_plugin_io_handlers_t io</nobr>,
+<nobr>int flags</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip_plugin_io_t
+</code>
+ <br /><b><code>zzip_get_default_io</code></b>
+ &nbsp; <code>
+ <code>(<nobr></nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/plugin.c)
+
+</em></para><p>
+ <br /> <function>The zzip_init_io function</function> initializes the users handler struct to default values
+ <br /> being the posix io functions in default configured environments.
+
+</p>
+<p>
+ <br /> <function>The zzip_get_default_io function</function> returns a zzip_plugin_io_t handle to static defaults
+ <br /> wrapping the posix io file functions for actual file access.
+
+</p>
+<p align="right"><small>(../../zzip/plugin.c)</small></p></dd>
+<dt><a name="zzip_mem_disk_fdopen" />
+ <code>zzip__new__ ZZIP_MEM_DISK*
+</code>
+ <br /><b><code>zzip_mem_disk_fdopen</code></b>
+ &nbsp; <code>
+ <code>(<nobr>int fd</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; create new diskdir handle.
+
+
+</em></para><p>
+ <br /> wraps underlying zzip_disk_open.
+</p>
+<p align="right"><small>(../../zzip/memdisk.c)</small></p></dd>
+<dt><a name="zzip_mem_disk_load" />
+ <code>long
+</code>
+ <br /><b><code>zzip_mem_disk_load</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_MEM_DISK* dir</nobr>,
+<nobr>ZZIP_DISK* disk</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; parse central dir.
+
+
+</em></para><p>
+ <br /> creates an internal copy of each entry converted to the local platform.
+ <br /> returns: number of entries, or -1 on error (setting errno)
+
+</p>
+<p align="right"><small>(../../zzip/memdisk.c)</small></p></dd>
+<dt><a name="zzip_mem_disk_open" />
+ <code>zzip__new__ ZZIP_MEM_DISK*
+</code>
+ <br /><b><code>zzip_mem_disk_open</code></b>
+ &nbsp; <code>
+ <code>(<nobr>char* filename</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; create new diskdir handle.
+
+
+</em></para><p>
+ <br /> wraps underlying zzip_disk_open.
+</p>
+<p align="right"><small>(../../zzip/memdisk.c)</small></p></dd>
+<dt><a name="zzip_mem_entry_new" />
+ <code>zzip__new__ ZZIP_MEM_ENTRY*
+</code>
+ <br /><b><code>zzip_mem_entry_new</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DISK* disk</nobr>,
+<nobr>ZZIP_DISK_ENTRY* entry</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; convert a zip disk entry to internal format.
+
+
+</em></para><p>
+ <br /> creates a new item parsing the information out of the various places
+ <br /> in the zip archive. This is a good place to extend functionality if
+ <br /> you have a project with extra requirements as you can push more bits
+ <br /> right into the diskdir_entry for later usage in higher layers.
+ <br /> returns: new item, or null on error (setting errno)
+
+</p>
+<p align="right"><small>(../../zzip/memdisk.c)</small></p></dd>
+<dt><a name="zzip_mkdir" /> <a name="zzip_creat" />
+ <code>int inline
+</code>
+ <br /><b><code>zzip_mkdir</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</code>
+
+<br /> <code>ZZIP_FILE* inline
+</code>
+ <br /><b><code>zzip_creat</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; create a zipped file/directory
+
+
+</em></para><p>
+
+</p><p>
+
+ <function>The zzip_mkdir function</function> creates a directory entry in the default zip-archive.
+ <br /> If you did not specify a "#define zzip_savefile somevar"
+ <br /> then the default zip-archive is null and all directories are
+ <br /> created as real directories in the filesystem. <function>The zzip_mkdir function</function> is
+ <br /> really a preprocessor macro or preferably an inline function
+ <br /> around <a href="#zzip_file_mkdir"><code>zzip_file_mkdir</code></a>, there is no such symbol generated
+ <br /> into the library. The prototype is modelled after the posix
+ <br /> <code>mkdir</code>(2) call.
+ <pre> #ifndef zzip_savefile
+ #define zzip_savefile 0
+ #endif
+ #define zzip_mkdir(name,mode) \ - </pre>
+ zzip_file_mkdir(zzip_savefile,name,mode)
+
+</p><p>
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_creat function</function> creates a file in the default zip-archive.
+ <br /> If you did not specify a "#define zzip_savefile somevar"
+ <br /> then the default zip-archive is null and all files are created
+ <br /> as real files. <function>The zzip_creat function</function> is really a preprocessor macro
+ <br /> or preferably an inline function around <a href="#zzip_file_creat"><code>zzip_file_creat</code></a>,
+ <br /> there is no such symbol generated into the library. The prototype
+ <br /> is modelled after the posix <code>creat</code>(2) call.
+ <pre> #ifndef zzip_savefile
+ #define zzip_savefile 0
+ #endif
+ #define zzip_creat(name,mode) \ - </pre>
+ zzip_file_creat(zzip_savefile,name,mode)
+
+</p>
+<p align="right"><small>(../../zzip/write.c)</small></p></dd>
+<dt><a name="zzip_mkfifo" /> <a name="zzip_sync" />
+ <code>void inline
+</code>
+ <br /><b><code>zzip_mkfifo</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_char_t* name</nobr>,
+<nobr>int o_mode</nobr>)</code>
+
+</code>
+
+<br /> <code>void inline
+</code>
+ <br /><b><code>zzip_sync</code></b>
+ &nbsp; <code>
+ <code>(<nobr>void</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; start writing to the magic zzip_savefile
+
+
+</em></para><p>
+
+</p><p>
+
+ open a zip archive for writing via the magic zzip_savefile macro
+ <br /> variable. The name and mode are given to <a href="#zzip_createdir"><code>zzip_createdir</code></a> and
+ <br /> the result is stored into <code>zzip_savefile</code> - if the <code>zzip_savefile</code>
+ <br /> did already have a zzip_dir handle then it is automatically
+ <br /> finalized with <a href="#zzip_sync"><code>zzip_sync</code></a> and the handle closed and the
+ <br /> zzip_savefile variable reused for the new zip archive just started
+ <br /> with this call. - <function>The zzip_mkfifo function</function> is really a preprocessor macro
+ <br /> or preferably an inline function around <code>zzip_dir_create</code>, there
+ <br /> is no such symbol generated into the library.
+ <pre> #ifndef zzip_savefile
+ #define zzip_savefile 0
+ #endif
+ #define zzip_start(name,mode,ext) \ - </pre>
+ { if (zzip_savefile) zzip_closedir(zzip_savefile); \ -
+ zzip_savefile = zzip_createdir(name,mode,ext); }
+ <br /> <function>The zzip_mkfifo function</function> returns null on error or a zzip_dir handle on
+ <br /> success. It is perfectly okay to continue with a null in the
+ <br /> zzip_savefile variable since it makes subsequent calls to
+ <br /> <a href="#zzip_creat"><code>zzip_creat</code></a> and <a href="#zzip_mkdir"><code>zzip_mkdir</code></a> to run as <code>creat</code>(2) / <code>mkdir</code>(2)
+ <br /> on the real filesystem.
+
+</p>
+<p>
+
+</p><p>
+
+ finalize a zip archive thereby writing the central directory to
+ <br /> the end of the file. If it was a real directory then we do just
+ <br /> nothing - even that the prototype of the call itself is modelled
+ <br /> to be similar to the posix <code>sync</code>(2) call. <function>The zzip_sync function</function> is
+ <br /> really a preprocessor macro or preferably an inline function
+ <br /> around <a href="#zzip_closedir"><code>zzip_closedir</code></a>, there is no such symbol generated
+ <br /> into the library.
+ <pre> #ifndef zzip_savefile
+ #define zzip_savefile 0
+ #endif
+ #define zzip_sync(name,mode) \ - </pre>
+ { zzip_closedir(zzip_savefile); zzip_savefile = 0; }
+
+</p><p>
+
+</p>
+<p align="right"><small>(../../zzip/write.c)</small></p></dd>
+<dt><a name="zzip_open" /> <a name="zzip_open_ext_io" /> <a name="zzip_open_shared_io" />
+ <code>ZZIP_FILE*
+</code>
+ <br /><b><code>zzip_open</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>int o_flags</nobr>)</code>
+
+</code>
+
+<br /> <code>ZZIP_FILE*
+</code>
+ <br /><b><code>zzip_open_ext_io</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>int o_flags</nobr>,
+<nobr>int o_modes</nobr>,
+<nobr>zzip_strings_t* ext</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</code>
+
+<br /> <code>ZZIP_FILE*
+</code>
+ <br /><b><code>zzip_open_shared_io</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE* stream</nobr>,
+<nobr>zzip_char_t* filename</nobr>,
+<nobr>int o_flags</nobr>,
+<nobr>int o_modes</nobr>,
+<nobr>zzip_strings_t* ext</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/file.c)
+
+</em></para><p>
+ <br /> <function>The zzip_open function</function> will <code>open</code>(2) a real/zipped file
+
+</p><p>
+
+ It has some magic functionality builtin - it will first try to open
+ <br /> the given <em>filename</em> as a normal file. If it does not
+ <br /> exist, the given path to the filename (if any) is split into
+ <br /> its directory-part and the file-part. A ".zip" extension is
+ <br /> then added to the directory-part to create the name of a
+ <br /> zip-archive. That zip-archive (if it exists) is being searched
+ <br /> for the file-part, and if found a zzip-handle is returned.
+
+</p><p>
+
+ Note that if the file is found in the normal fs-directory the
+ <br /> returned structure is mostly empty and the <a href="#zzip_read"><code>zzip_read</code></a> call will
+ <br /> use the libc <code>read</code> to obtain data. Otherwise a <a href="#zzip_file_open"><code>zzip_file_open</code></a>
+ <br /> is performed and any error mapped to <code>errno</code>(3).
+
+</p><p>
+
+ There was a possibility to transfer zziplib-specific openmodes
+ <br /> through o_flags but you should please not use them anymore and
+ <br /> look into <a href="#zzip_open_ext_io"><code>zzip_open_ext_io</code></a> to submit them down. <function>The zzip_open function</function>
+ <br /> is shallow in that it just extracts the zzipflags and calls <ul><li><code>
+ <br /> zzip_open_ext_io(filename, o_flags, zzipflags|0664, 0, 0) </code></li></ul>
+ <br /> you must stop using this extra functionality (not well known
+ <br /> anyway) since zzip_open might be later usable to open files
+ <br /> for writing in which case the _EXTRAFLAGS will get in conflict.
+
+</p><p>
+
+ compare with <code>open</code>(2) and <a href="#zzip_fopen"><code>zzip_fopen</code></a>
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_open_ext_io function</function> uses explicit ext and io instead of the internal
+ <br /> defaults, setting them to zero is equivalent to <a href="#zzip_open"><code>zzip_open</code></a>
+
+</p><p>
+
+ note that the two flag types have been split into an o_flags
+ <br /> (for fcntl-like openflags) and o_modes where the latter shall
+ <br /> carry the zzip_flags and possibly accessmodes for unix filesystems.
+ <br /> Since this version of zziplib can not write zipfiles, it is not
+ <br /> yet used for anything else than zzip-specific modeflags.
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_open_shared_io function</function> takes an extra stream argument - if a handle has been
+ <br /> then ext/io can be left null and the new stream handle will pick up
+ <br /> the ext/io. This should be used only in specific environment however
+ <br /> since <a href="#zzip_file_real"><code>zzip_file_real</code></a> does not store any ext-sequence.
+
+</p><p>
+
+ The benefit for <function>the zzip_open_shared_io function</function> comes in when the old file handle
+ <br /> was openened from a file within a zip archive. When the new file
+ <br /> is in the same zip archive then the internal zzip_dir structures
+ <br /> will be shared. It is even quicker, as no check needs to be done
+ <br /> anymore trying to guess the zip archive place in the filesystem,
+ <br /> here we just check whether the zip archive's filepath is a prefix
+ <br /> part of the filename to be opened.
+
+</p><p>
+
+ Note that <function>the zzip_open_shared_io function</function> is also used by <a href="#zzip_freopen"><code>zzip_freopen</code></a> that
+ <br /> will unshare the old handle, thereby possibly closing the handle.
+
+</p>
+<p align="right"><small>(../../zzip/file.c)</small></p></dd>
+<dt><a name="zzip_opendir" /> <a name="zzip_opendir_ext_io" />
+ <code>ZZIP_DIR*
+</code>
+ <br /><b><code>zzip_opendir</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_char_t* filename</nobr>)</code>
+
+</code>
+
+<br /> <code>ZZIP_DIR*
+</code>
+ <br /><b><code>zzip_opendir_ext_io</code></b>
+ &nbsp; <code>
+ <code>(<nobr>zzip_char_t* filename</nobr>,
+<nobr>int o_modes</nobr>,
+<nobr>zzip_strings_t* ext</nobr>,
+<nobr>zzip_plugin_io_t io</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/dir.c)
+
+</em></para><p>
+ <br /> <function>The zzip_opendir function</function> is the equivalent of <code>opendir</code>(3) for a realdir or zipfile.
+
+</p><p>
+
+ <function>The zzip_opendir function</function> has some magic - if the given argument-path
+ <br /> is a directory, it will wrap a real <code>opendir</code>(3) into the ZZIP_DIR
+ <br /> structure. Otherwise it will divert to <a href="#zzip_dir_open"><code>zzip_dir_open</code></a> which
+ <br /> can also attach a ".zip" extension if needed to find the archive.
+
+</p><p>
+
+ the error-code is mapped to <code>errno</code>(3).
+
+</p>
+<p>
+ <br /> <function>The zzip_opendir_ext_io function</function> uses explicit ext and io instead of the internal
+ <br /> defaults, setting them to zero is equivalent to <a href="#zzip_opendir"><code>zzip_opendir</code></a>
+
+</p>
+<p align="right"><small>(../../zzip/dir.c)</small></p></dd>
+<dt><a name="zzip_read" /> <a name="zzip_fread" />
+ <code>zzip_ssize_t
+</code>
+ <br /><b><code>zzip_read</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE * fp</nobr>,
+<nobr>char * buf</nobr>,
+<nobr>zzip_size_t len</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip_size_t
+</code>
+ <br /><b><code>zzip_fread</code></b>
+ &nbsp; <code>
+ <code>(<nobr>void *ptr</nobr>,
+<nobr>zzip_size_t size</nobr>,
+<nobr>zzip_size_t nmemb</nobr>,
+<nobr>ZZIP_FILE *file</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/file.c)
+
+</em></para><p>
+ <br /> <function>The zzip_read function</function> will read(2) data from a real/zipped file.
+
+</p><p>
+
+ the replacement for <code>read</code>(2) will fill the given buffer with bytes from
+ <br /> the opened file. It will return the number of bytes read, so if the EOF
+ <br /> is encountered you will be prompted with the number of bytes actually read.
+
+</p><p>
+
+ If the file-handle is wrapping a stat'able file then it will actually just
+ <br /> perform a normal <code>read</code>(2)-call, otherwise <a href="#zzip_file_read"><code>zzip_file_read</code></a> is called
+ <br /> to decompress the data stream and any error is mapped to <code>errno</code>(3).
+
+</p>
+<p><small><code>zzip_fread</code></small> -
+
+</p>
+<p align="right"><small>(../../zzip/file.c)</small></p></dd>
+<dt><a name="zzip_readdir" />
+ <code>ZZIP_DIRENT*
+</code>
+ <br /><b><code>zzip_readdir</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR * dir</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/dir.c)
+
+</em></para><p>
+ <br /> <function>The zzip_readdir function</function> is the equivalent of a <code>readdir</code>(2) for a realdir
+ <br /> or a zipfile referenced by the ZZIP_DIR returned from <a href="#zzip_opendir"><code>zzip_opendir</code></a>.
+
+</p><p>
+
+ The ZZIP_DIR handle (as returned by <a href="#zzip_opendir"><code>zzip_opendir</code></a>) contains a few more
+ <br /> entries than being copied into the ZZIP_DIRENT. The only valid fields in
+ <br /> a ZZIP_DIRENT are d_name (the file name), d_compr (compression), d_csize
+ <br /> (compressed size), st_size (uncompressed size).
+
+</p>
+<p align="right"><small>(../../zzip/dir.c)</small></p></dd>
+<dt><a name="zzip_rewind" />
+ <code>int
+</code>
+ <br /><b><code>zzip_rewind</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE *fp</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/file.c)
+
+</em></para><p>
+ <br /> <function>The zzip_rewind function</function> will rewind a real/zipped file.
+
+</p><p>
+
+ It seeks to the beginning of this file's data in the zip,
+ <br /> or the beginning of the file for a stat'fd.
+
+</p>
+<p align="right"><small>(../../zzip/file.c)</small></p></dd>
+<dt><a name="zzip_rewinddir" /> <a name="zzip_telldir" /> <a name="zzip_seekdir" />
+ <code>void
+</code>
+ <br /><b><code>zzip_rewinddir</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR * dir</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip_off_t
+</code>
+ <br /><b><code>zzip_telldir</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR* dir</nobr>)</code>
+
+</code>
+
+<br /> <code>void
+</code>
+ <br /><b><code>zzip_seekdir</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR* dir</nobr>,
+<nobr>zzip_off_t offset</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/dir.c)
+
+</em></para><p>
+ <br /> <function>The zzip_rewinddir function</function> is the equivalent of a <code>rewinddir</code>(2) for a realdir or
+ <br /> the zipfile in place of a directory. The ZZIP_DIR handle returned from
+ <br /> <a href="#zzip_opendir"><code>zzip_opendir</code></a> has a flag saying realdir or zipfile. As for a zipfile,
+ <br /> the filenames will include the filesubpath, so take care.
+
+</p>
+<p>
+ <br /> <function>The zzip_telldir function</function> is the equivalent of <code>telldir</code>(2) for a realdir or zipfile.
+
+</p>
+<p>
+ <br /> <function>The zzip_seekdir function</function> is the equivalent of <code>seekdir</code>(2) for a realdir or zipfile.
+
+</p>
+<p align="right"><small>(../../zzip/dir.c)</small></p></dd>
+<dt><a name="zzip_seek" />
+ <code>zzip_off_t
+</code>
+ <br /><b><code>zzip_seek</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE * fp</nobr>,
+<nobr>zzip_off_t offset</nobr>,
+<nobr>int whence</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/file.c)
+
+</em></para><p>
+ <br /> <function>The zzip_seek function</function> will perform a <code>lseek</code>(2) operation on a real/zipped file
+
+</p><p>
+
+ It will try to seek to the offset specified by offset, relative to whence,
+ <br /> which is one of SEEK_SET, SEEK_CUR or SEEK_END.
+
+</p><p>
+
+ If the file-handle is wrapping a stat'able file then it will actually just
+ <br /> perform a normal <code>lseek</code>(2)-call. Otherwise the relative offset
+ <br /> is calculated, negative offsets are transformed into positive ones
+ <br /> by rewinding the file, and then data is read until the offset is
+ <br /> reached. This can make the function terribly slow, but this is
+ <br /> how gzio implements it, so I'm not sure there is a better way
+ <br /> without using the internals of the algorithm.
+
+</p>
+<p align="right"><small>(../../zzip/file.c)</small></p></dd>
+<dt><a name="zzip_strerror" /> <a name="zzip_strerror_of" />
+ <code>zzip_char_t*
+</code>
+ <br /><b><code>zzip_strerror</code></b>
+ &nbsp; <code>
+ <code>(<nobr>int errcode</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip_char_t*
+</code>
+ <br /><b><code>zzip_strerror_of</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_DIR* dir</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/err.c)
+
+</em></para><p>
+ <br /> returns the static string for the given error code. The
+ <br /> error code can be either a normal system error (a
+ <br /> positive error code will flag this), it can be <code>libz</code>
+ <br /> error code (a small negative error code will flag this)
+ <br /> or it can be an error code from <code>libzzip</code>, which is an
+ <br /> negative value lower than <code>ZZIP_ERROR</code>
+
+</p>
+<p>
+ <br /> <function>The zzip_strerror_of function</function> fetches the errorcode from the <code>DIR</code>-handle and
+ <br /> runs it through <a href="#zzip_strerror"><code>zzip_strerror</code></a> to obtain the static string
+ <br /> describing the error.
+
+</p>
+<p align="right"><small>(../../zzip/err.c)</small></p></dd>
+<dt><a name="zzip_tell" />
+ <code>zzip_off_t
+</code>
+ <br /><b><code>zzip_tell</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE * fp</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp;(zzip/file.c)
+
+</em></para><p>
+ <br /> <function>The zzip_tell function</function> will <code>tell</code>(2) the current position in a real/zipped file
+
+</p><p>
+
+ It will return the current offset within the real/zipped file,
+ <br /> measured in uncompressed bytes for the zipped-file case.
+
+</p><p>
+
+ If the file-handle is wrapping a stat'able file then it will actually just
+ <br /> perform a normal <code>tell</code>(2)-call, otherwise the offset is
+ <br /> calculated from the amount of data left and the total uncompressed
+ <br /> size;
+
+</p>
+<p align="right"><small>(../../zzip/file.c)</small></p></dd>
+<dt><a name="zzip_write" /> <a name="zzip_file_write" /> <a name="zzip_fwrite" />
+ <code>zzip_ssize_t
+</code>
+ <br /><b><code>zzip_write</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE* file</nobr>,
+<nobr>const void* ptr</nobr>,
+<nobr>zzip_size_t len</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip_ssize_t
+</code>
+ <br /><b><code>zzip_file_write</code></b>
+ &nbsp; <code>
+ <code>(<nobr>ZZIP_FILE* file</nobr>,
+<nobr>const void* ptr</nobr>,
+<nobr>zzip_size_t len</nobr>)</code>
+
+</code>
+
+<br /> <code>zzip_size_t
+</code>
+ <br /><b><code>zzip_fwrite</code></b>
+ &nbsp; <code>
+ <code>(<nobr>const void* ptr</nobr>,
+<nobr>zzip_size_t len</nobr>,
+<nobr>zzip_size_t multiply</nobr>,
+<nobr>ZZIP_FILE* file</nobr>)</code>
+
+</code>
+<dt>
+<dd>
+<para><em> &nbsp; write to zzip storage
+
+
+</em></para><p>
+
+</p><p>
+
+ <function>The zzip_write function</function> will write data to a file descriptor. If the file
+ <br /> descriptor represents a real file then it will be forwarded to
+ <br /> call posix <code>write</code>(2) directly. If it is a descriptor for a
+ <br /> file within a zip directory then the data will be "deflated"
+ <br /> using <code>zlib</code>(3) and appended to the zip archive file.
+
+</p>
+<p>
+
+</p><p>
+
+ <function>The zzip_file_write function</function> will write data to a file descriptor inside a zip
+ <br /> archive. The data will be "deflated" using <code>zlib</code>(3) compression
+ <br /> and appended to the end of the zip archive file. Only one file
+ <br /> descriptor may be open per zzip_dir archive handle (fifo-like).
+
+</p><p>
+
+ <function>The zzip_file_write function</function> is not yet implemented, check for #def ZZIP_NO_CREAT
+ <br /> It returns immediately -1 and sets errno=EROFS for indication.
+
+</p>
+<p>
+ <br /> <function>The zzip_fwrite function</function> is the stdc variant for writing and the arguments
+ <br /> are forwarded to <a href="#zzip_write"><code>zzip_write</code></a> - the return value is floored to
+ <br /> null as for STDC spec but there is no zzip_ferror call so far
+ <br /> for the zziplib (later? is it actually needed?).
+
+</p><p>
+
+ <function>The zzip_fwrite function</function> is not yet implemented, check for #def ZZIP_NO_CREAT
+ <br /> Write-support extends <a href="#zzip_close"><code>zzip_close</code></a> with semantics to write out a
+ <br /> file-trailer to the zip-archive leaving a name/offset marker in
+ <br /> the (still-open) ZZIP_DIR handle.
+
+</p>
+<p align="right"><small>(../../zzip/write.c)</small></p></dd>
+</dl>
+</body></html>
+
diff --git a/Build/source/libs/zziplib/m4/ac_compile_check_sizeof.m4 b/Build/source/libs/zziplib/m4/ac_compile_check_sizeof.m4
new file mode 100644
index 00000000000..fbdb534b41f
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ac_compile_check_sizeof.m4
@@ -0,0 +1,78 @@
+dnl @synopsis AC_COMPILE_CHECK_SIZEOF(TYPE [, HEADERS [, EXTRA_SIZES...]])
+dnl
+dnl This macro checks for the size of TYPE using compile checks, not
+dnl run checks. You can supply extra HEADERS to look into. the check
+dnl will cycle through 1 2 4 8 16 and any EXTRA_SIZES the user
+dnl supplies. If a match is found, it will #define SIZEOF_`TYPE' to
+dnl that value. Otherwise it will emit a configure time error
+dnl indicating the size of the type could not be determined.
+dnl
+dnl The trick is that C will not allow duplicate case labels. While
+dnl this is valid C code:
+dnl
+dnl switch (0) case 0: case 1:;
+dnl
+dnl The following is not:
+dnl
+dnl switch (0) case 0: case 0:;
+dnl
+dnl Thus, the AC_TRY_COMPILE will fail if the currently tried size does
+dnl not match.
+dnl
+dnl Here is an example skeleton configure.in script, demonstrating the
+dnl macro's usage:
+dnl
+dnl AC_PROG_CC
+dnl AC_CHECK_HEADERS(stddef.h unistd.h)
+dnl AC_TYPE_SIZE_T
+dnl AC_CHECK_TYPE(ssize_t, int)
+dnl
+dnl headers='#ifdef HAVE_STDDEF_H
+dnl #include <stddef.h>
+dnl #endif
+dnl #ifdef HAVE_UNISTD_H
+dnl #include <unistd.h>
+dnl #endif
+dnl '
+dnl
+dnl AC_COMPILE_CHECK_SIZEOF(char)
+dnl AC_COMPILE_CHECK_SIZEOF(short)
+dnl AC_COMPILE_CHECK_SIZEOF(int)
+dnl AC_COMPILE_CHECK_SIZEOF(long)
+dnl AC_COMPILE_CHECK_SIZEOF(unsigned char *)
+dnl AC_COMPILE_CHECK_SIZEOF(void *)
+dnl AC_COMPILE_CHECK_SIZEOF(size_t, $headers)
+dnl AC_COMPILE_CHECK_SIZEOF(ssize_t, $headers)
+dnl AC_COMPILE_CHECK_SIZEOF(ptrdiff_t, $headers)
+dnl AC_COMPILE_CHECK_SIZEOF(off_t, $headers)
+dnl
+dnl @category Misc
+dnl @author Kaveh Ghazi <ghazi@caip.rutgers.edu>
+dnl @version 2000-07-19
+dnl @license GPLWithACException
+
+AC_DEFUN([AC_COMPILE_CHECK_SIZEOF],
+[changequote(<<, >>)dnl
+dnl The name to #define.
+define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
+dnl The cache variable name.
+define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
+changequote([, ])dnl
+AC_MSG_CHECKING(size of $1)
+AC_CACHE_VAL(AC_CV_NAME,
+[for ac_size in 4 8 1 2 16 $2 ; do # List sizes in rough order of prevalence.
+ AC_TRY_COMPILE([#include "confdefs.h"
+#include <sys/types.h>
+$2
+], [switch (0) case 0: case (sizeof ($1) == $ac_size):;], AC_CV_NAME=$ac_size)
+ if test x$AC_CV_NAME != x ; then break; fi
+done
+])
+if test x$AC_CV_NAME = x ; then
+ AC_MSG_ERROR([cannot determine a size for $1])
+fi
+AC_MSG_RESULT($AC_CV_NAME)
+AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The number of bytes in type $1])
+undefine([AC_TYPE_NAME])dnl
+undefine([AC_CV_NAME])dnl
+])
diff --git a/Build/source/libs/zziplib/m4/ac_set_default_paths_system.m4 b/Build/source/libs/zziplib/m4/ac_set_default_paths_system.m4
new file mode 100644
index 00000000000..6c201488ec2
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ac_set_default_paths_system.m4
@@ -0,0 +1,104 @@
+dnl @synopsis AC_SET_DEFAULT_PATHS_SYSTEM
+dnl
+dnl the most interesting changes go about windows-targets - where the
+dnl default_prefix is set to /programs, and quite some directories are
+dnl aliased: sbindir := libdir := bindir and the docprefix-defaults are
+dnl also a bit different, even on FHS2-compliant systems where the
+dnl mandir is going to $prefix/man only if prefix=/usr, otherwise they
+dnl shall go to $datadir/man. We use an extra docprefix to express it
+dnl which is either defined as being prefix or datadir. not SUBSTed
+dnl here.
+dnl
+dnl @category Misc
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2001-08-25
+dnl @license GPLWithACException
+
+AC_DEFUN([AC_SET_DEFAULT_PATHS_SYSTEM],
+[AC_REQUIRE([AC_CANONICAL_HOST]) # --------------------------------------------
+case "$prefix:$ac_default_prefix" in
+ NONE:/usr/local)
+ result=""
+ AC_MSG_CHECKING(default prefix path)
+ case "${target_os}" in
+ *cygwin* | *mingw* | *uwin* | *djgpp | *emx* )
+ if test "${host_os}" = "${target_os}" ; then
+ ac_default_prefix="/programs"
+ result="(win/dos target)"
+ else
+ case "$PATH" in
+ *:/usr/local/cross-tools/$target_alias/bin:*)
+ ac_default_prefix="/usr/local/cross-tools/$target_alias" ;;
+ *:/usr/local/$target_alias/bin:*)
+ ac_default_prefix="/usr/local/$target_alias" ;;
+ *:/usr/local/$target_cpu-$target_os/bin:*)
+ ac_default_prefix="/usr/local/$target_cpu-$target_os" ;;
+ *)
+ ac_default_prefix="/programs" ;;
+ esac
+ result="(win/dos cross-compiler)"
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT($ac_default_prefix $result)
+ ;;
+esac
+AC_MSG_CHECKING(default prefix system)
+result="$prefix" ; test "$result" = "NONE" && result="$ac_default_prefix"
+case ${result} in
+ /programs | /programs/*) result="is win-/programs"
+ # on win/dos, .exe .dll and .cfg live in the same directory
+ libdir=`echo $libdir |sed -e 's:^..exec_prefix./lib$:${bindir}:'`
+ sbindir=`echo $sbindir |sed -e 's:^..exec_prefix./sbin$:${libdir}:'`
+ sysconfdir=`echo $sysconfdir |sed -e 's:^..prefix./etc$:${sbindir}:'`
+ libexecdir=`echo $libexecdir |sed -e 's:/libexec$:/system:'`
+ # help-files shall be set with --infodir, docprefix is datadir
+ docprefix="${datadir}"
+ mandir=`echo $mandir \
+ |sed -e 's:^..prefix./man$:${datadir}/info:'`
+ includedir=`echo $includedir \
+ |sed -e 's:^..prefix./include$:${datadir}/include:'`
+ # other state files (but /etc) are moved to datadir
+ sharedstatedir=`echo $sharedstatedir \
+ |sed -e 's:^..prefix./com$:${datadir}/default:'`
+ localstatedir=`echo $localstatedir \
+ |sed -e 's:^..prefix./var$:${datadir}/current:'`
+ ;;
+ /usr) result="is /usr-shipped"
+ # doc files are left at prefix
+ docprefix="${prefix}"
+ # state files go under /top
+ sysconfdir=`echo $sysconfdir |sed -e 's:^..prefix./etc$:/etc:'`
+ sharedstatedir=`echo $sharedstatedir \
+ |sed -e 's:^..prefix./com$:/etc/default:'`
+ # $prefix/var is going to end up in /var/lib
+ localstatedir=`echo $localstatedir \
+ |sed -e 's:^..prefix./var$:/var/lib:'`
+ ;;
+ /opt | /opt/*) result="is /opt-package"
+ # state files go under /top/prefix
+ sysconfdir=`echo $sysconfdir \
+ |sed -e 's:^..prefix./etc$:/etc${prefix}:'`
+ sharedstatedir=`echo $sharedstatedir \
+ |sed -e 's:^..prefix./com$:/etc/default${prefix}:'`
+ # $prefix/var is going to to be /var$prefix... once again
+ localstatedir=`echo $localstatedir \
+ |sed -e 's:^..prefix./var$:/var${prefix}:'`
+ # doc files are left at prefix
+ docprefix="${prefix}"
+ ;;
+ *) result="is /local-package"
+ # doc files are moved from prefix down to datadir
+ docprefix="${datadir}"
+ mandir=`echo $mandir \
+ |sed -e 's:^..prefix./man$:${datadir}/man:'`
+ infodir=`echo $infodir \
+ |sed -e 's:^..prefix./infodir$:${datadir}/info:'`
+ # never use $prefix/com - that is no good idea
+ sharedstatedir=`echo $sharedstatedir \
+ |sed -e 's:^..prefix./com$:${sysconfdir}/default:'`
+ ;;
+esac
+AC_MSG_RESULT($result)
+# --------------------------------------------------------
+])
diff --git a/Build/source/libs/zziplib/m4/ac_sys_largefile_sensitive.m4 b/Build/source/libs/zziplib/m4/ac_sys_largefile_sensitive.m4
new file mode 100644
index 00000000000..6116b827deb
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ac_sys_largefile_sensitive.m4
@@ -0,0 +1,46 @@
+dnl @synopsis AC_SYS_LARGEFILE_SENSITIVE
+dnl
+dnl checker whether the current system is sensitive to -Ddefines making
+dnl off_t having different types/sizes. Automatically define a config.h
+dnl symbol LARGEFILE_SENSITIVE if that is the case, otherwise leave
+dnl everything as is.
+dnl
+dnl This macro builds on top of AC_SYS_LARGEFILE to detect whether
+dnl special options are neede to make the code use 64bit off_t - in
+dnl many setups this will also make the code use 64bit off_t
+dnl immediatly.
+dnl
+dnl The common use of a LARGEFILE_SENSITIVE config.h-define is to
+dnl rename exported functions, usually adding a 64 to the original
+dnl function name. Such renamings are only needed on systems being both
+dnl (a) 32bit off_t by default and (b) implementing large.file
+dnl extensions (as for unix98).
+dnl
+dnl a renaming section could look like this:
+dnl
+dnl #if defined LARGEFILE_SENSITIVE && _FILE_OFFSET_BITS+0 == 64
+dnl #define zzip_open zzip_open64
+dnl #define zzip_seek zzip_seek64
+dnl #endif
+dnl
+dnl for libraries, it is best to take advantage of the prefix-config.h
+dnl macro, otherwise you want to export a renamed LARGEFILE_SENSITIVE
+dnl in an installed header file. -> see AX_PREFIX_CONFIG_H
+dnl
+dnl @category Misc
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2003-02-02
+dnl @license GPLWithACException
+
+AC_DEFUN([AC_SYS_LARGEFILE_SENSITIVE],[dnl
+AC_REQUIRE([AC_SYS_LARGEFILE])dnl
+# we know about some internals of ac_sys_largefile here...
+AC_MSG_CHECKING(whether system differentiates 64bit off_t by defines)
+ac_cv_sys_largefile_sensitive="no"
+if test ".$ac_cv_sys_file_offset_bits$ac_cv_sys_large_files" != ".nono"
+then ac_cv_sys_largefile_sensitive="yes"
+ AC_DEFINE(LARGEFILE_SENSITIVE, 1,
+ [whether the system defaults to 32bit off_t but can do 64bit when requested])
+fi
+AC_MSG_RESULT([$ac_cv_sys_largefile_sensitive])
+])
diff --git a/Build/source/libs/zziplib/m4/acx_restrict.m4 b/Build/source/libs/zziplib/m4/acx_restrict.m4
new file mode 100644
index 00000000000..333f2592df4
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/acx_restrict.m4
@@ -0,0 +1,32 @@
+dnl @synopsis ACX_C_RESTRICT
+dnl
+dnl This macro determines whether the C compiler supports the "restrict"
+dnl keyword introduced in ANSI C99, or an equivalent. Does nothing if
+dnl the compiler accepts the keyword. Otherwise, if the compiler supports
+dnl an equivalent (like gcc's __restrict__) defines "restrict" to be that.
+dnl Otherwise, defines "restrict" to be empty.
+dnl
+dnl @version $Id: acx_restrict.m4,v 1.1 2005/12/09 07:47:34 guidod Exp $
+dnl @author Steven G. Johnson <stevenj@alum.mit.edu>
+
+AC_DEFUN([ACX_C_RESTRICT],
+[AC_CACHE_CHECK([for C restrict keyword], acx_cv_c_restrict,
+[acx_cv_c_restrict=unsupported
+ AC_LANG_SAVE
+ AC_LANG_C
+ # Try the official restrict keyword, then gcc's __restrict__, then
+ # SGI's __restrict. __restrict has slightly different semantics than
+ # restrict (it's a bit stronger, in that __restrict pointers can't
+ # overlap even with non __restrict pointers), but I think it should be
+ # okay under the circumstances where restrict is normally used.
+ for acx_kw in restrict __restrict__ __restrict; do
+ AC_TRY_COMPILE([], [float * $acx_kw x;], [acx_cv_c_restrict=$acx_kw; break])
+ done
+ AC_LANG_RESTORE
+])
+ if test "$acx_cv_c_restrict" != "restrict"; then
+ acx_kw="$acx_cv_c_restrict"
+ if test "$acx_kw" = unsupported; then acx_kw=""; fi
+ AC_DEFINE_UNQUOTED(restrict, $acx_kw, [Define to equivalent of C99 restrict keyword, or to nothing if this is not supported. Do not define if restrict is supported directly.])
+ fi
+])
diff --git a/Build/source/libs/zziplib/m4/ax_cflags_gcc_option.m4 b/Build/source/libs/zziplib/m4/ax_cflags_gcc_option.m4
new file mode 100644
index 00000000000..dcd85797e54
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ax_cflags_gcc_option.m4
@@ -0,0 +1,187 @@
+dnl @synopsis AX_CFLAGS_GCC_OPTION (optionflag [,[shellvar][,[A][,[NA]]])
+dnl
+dnl AX_CFLAGS_GCC_OPTION(-fvomit-frame) would show a message as like
+dnl "checking CFLAGS for gcc -fvomit-frame ... yes" and adds the
+dnl optionflag to CFLAGS if it is understood. You can override the
+dnl shellvar-default of CFLAGS of course. The order of arguments stems
+dnl from the explicit macros like AX_CFLAGS_WARN_ALL.
+dnl
+dnl The cousin AX_CXXFLAGS_GCC_OPTION would check for an option to add
+dnl to CXXFLAGS - and it uses the autoconf setup for C++ instead of C
+dnl (since it is possible to use different compilers for C and C++).
+dnl
+dnl The macro is a lot simpler than any special AX_CFLAGS_* macro (or
+dnl ac_cxx_rtti.m4 macro) but allows to check for arbitrary options.
+dnl However, if you use this macro in a few places, it would be great
+dnl if you would make up a new function-macro and submit it to the
+dnl ac-archive.
+dnl
+dnl - $1 option-to-check-for : required ("-option" as non-value)
+dnl - $2 shell-variable-to-add-to : CFLAGS (or CXXFLAGS in the other case)
+dnl - $3 action-if-found : add value to shellvariable
+dnl - $4 action-if-not-found : nothing
+dnl
+dnl note: in earlier versions, $1-$2 were swapped. We try to detect the
+dnl situation and accept a $2=~/-/ as being the old
+dnl option-to-check-for.
+dnl
+dnl also: there are other variants that emerged from the original macro
+dnl variant which did just test an option to be possibly added.
+dnl However, some compilers accept an option silently, or possibly for
+dnl just another option that was not intended. Therefore, we have to do
+dnl a generic test for a compiler family. For gcc we check "-pedantic"
+dnl being accepted which is also understood by compilers who just want
+dnl to be compatible with gcc even when not being made from gcc
+dnl sources.
+dnl
+dnl see also:
+dnl
+dnl AX_CFLAGS_SUN_OPTION AX_CFLAGS_HPUX_OPTION
+dnl AX_CFLAGS_AIX_OPTION AX_CFLAGS_IRIX_OPTION
+dnl
+dnl @category C
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2003-11-04
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_CFLAGS_GCC_OPTION_OLD], [dnl
+AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_gcc_option_$2])dnl
+AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for gcc m4_ifval($2,$2,-option)],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_C
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-pedantic % m4_ifval($2,$2,-option)" dnl GCC
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+
+dnl the only difference - the LANG selection... and the default FLAGS
+
+AC_DEFUN([AX_CXXFLAGS_GCC_OPTION_OLD], [dnl
+AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_gcc_option_$2])dnl
+AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for gcc m4_ifval($2,$2,-option)],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_CXX
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-pedantic % m4_ifval($2,$2,-option)" dnl GCC
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+dnl -------------------------------------------------------------------------
+
+AC_DEFUN([AX_CFLAGS_GCC_OPTION_NEW], [dnl
+AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_gcc_option_$1])dnl
+AC_CACHE_CHECK([m4_ifval($2,$2,FLAGS) for gcc m4_ifval($1,$1,-option)],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_C
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-pedantic % m4_ifval($1,$1,-option)" dnl GCC
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($2,$2,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($2,$2,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"])
+ m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+
+dnl the only difference - the LANG selection... and the default FLAGS
+
+AC_DEFUN([AX_CXXFLAGS_GCC_OPTION_NEW], [dnl
+AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_gcc_option_$1])dnl
+AC_CACHE_CHECK([m4_ifval($2,$2,FLAGS) for gcc m4_ifval($1,$1,-option)],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_CXX
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-pedantic % m4_ifval($1,$1,-option)" dnl GCC
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($2,$2,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($2,$2,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"])
+ m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+AC_DEFUN([AX_CFLAGS_GCC_OPTION],[ifelse(m4_bregexp([$2],[-]),-1,
+[AX_CFLAGS_GCC_OPTION_NEW($@)],[AX_CFLAGS_GCC_OPTION_OLD($@)])])
+
+AC_DEFUN([AX_CXXFLAGS_GCC_OPTION],[ifelse(m4_bregexp([$2],[-]),-1,
+[AX_CXXFLAGS_GCC_OPTION_NEW($@)],[AX_CXXFLAGS_GCC_OPTION_OLD($@)])])
diff --git a/Build/source/libs/zziplib/m4/ax_cflags_no_writable_strings.m4 b/Build/source/libs/zziplib/m4/ax_cflags_no_writable_strings.m4
new file mode 100644
index 00000000000..e13ec09c278
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ax_cflags_no_writable_strings.m4
@@ -0,0 +1,140 @@
+dnl @synopsis AX_CFLAGS_NO_WRITABLE_STRINGS [(shellvar [,default, [A/NA]])]
+dnl
+dnl Try to find a compiler option that makes all stringliteral
+dnl readonly.
+dnl
+dnl The sanity check is done by looking at string.h which has a set of
+dnl strcpy definitions that should be defined with const-modifiers to
+dnl not emit a warning in all so many places.
+dnl
+dnl For the GNU CC compiler it will be -fno-writable-strings
+dnl -Wwrite-strings The result is added to the shellvar being CFLAGS by
+dnl default.
+dnl
+dnl DEFAULTS:
+dnl
+dnl - $1 shell-variable-to-add-to : CFLAGS
+dnl - $2 add-value-if-not-found : nothing
+dnl - $3 action-if-found : add value to shellvariable
+dnl - $4 action-if-not-found : nothing
+dnl
+dnl @category C
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2003-05-21
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_CFLAGS_NO_WRITABLE_STRINGS],[dnl
+AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_no_writable_strings])dnl
+AC_CACHE_CHECK([m4_ifval([$1],[$1],FLAGS) making strings readonly],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_C
+ ac_save_[]FLAGS="$[]FLAGS"
+# IRIX C compiler:
+# -use_readonly_const is the default for IRIX C,
+# puts them into .rodata, but they are copied later.
+# need to be "-G0 -rdatashared" for strictmode but
+# I am not sure what effect that has really. - guidod
+for ac_arg dnl
+in "-Wall % -fno-writable-strings -Wwrite-strings" dnl GCC
+ "-v -Xc % -xstrconst" dnl Solaris C - strings go into readonly segment
+ "+w1 -Aa % +ESlit" dnl HP-UX C - strings go into readonly segment
+ "-w0 -std1 % -readonly_strings" dnl Digital Unix - again readonly segment
+ "-fullwarn -use_readonly_const %% ok, its the default" dnl IRIX C
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+case ".$VAR" in
+ .|.no|.no,*) ;;
+ *) # sanity check - testing strcpy() from string.h
+ cp config.log config.tmp
+ AC_TRY_COMPILE([#include <string.h>],[
+ char test[16];
+ if (strcpy (test, "test")) return 1;],
+ dnl the original did use test -n `$CC testprogram.c`
+ [if test `diff config.log config.tmp | grep -i warning | wc -l` != 0
+ then VAR="no, suppressed, string.h," ; fi],
+ [VAR="no, suppressed, string.h"])
+ rm config.tmp
+ ;;
+esac
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4,[m4_ifval($2,[
+ AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])]) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+dnl the only difference - the LANG selection... and the default FLAGS
+
+AC_DEFUN([AX_CXXFLAGS_NO_WRITABLE_STRINGS],[dnl
+AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_no_writable_strings])dnl
+AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) making strings readonly],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_CXX
+ ac_save_[]FLAGS="$[]FLAGS"
+# IRIX C compiler:
+# -use_readonly_const is the default for IRIX C,
+# puts them into .rodata, but they are copied later.
+# need to be "-G0 -rdatashared" for strictmode but
+# I am not sure what effect that has really. - guidod
+for ac_arg dnl
+in "-Wall % -fno-writable-strings -Wwrite-strings" dnl GCC
+ "-v -Xc % -xstrconst" dnl Solaris C - strings go into readonly segment
+ "+w1 -Aa % +ESlit" dnl HP-UX C - strings go into readonly segment
+ "-w0 -std1 % -readonly_strings" dnl Digital Unix - again readonly segment
+ "-fullwarn -use_readonly_const %% ok, its the default" dnl IRIX C
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+case ".$VAR" in
+ .|.no|.no,*) ;;
+ *) # sanity check - testing strcpy() from string.h
+ cp config.log config.tmp
+ AC_TRY_COMPILE([#include <string.h>],[[
+ char test[16];
+ if (strcpy (test, "test")) return 1;]],
+ dnl the original did use test -n `$CC testprogram.c`
+ [if test `diff config.log config.tmp | grep -i warning | wc -l` != 0
+ then VAR="no, suppressed, string.h," ; fi],
+ [VAR="no, suppressed, string.h"])
+ rm config.tmp
+ ;;
+esac
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4,[m4_ifval($2,[
+ AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])]) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
diff --git a/Build/source/libs/zziplib/m4/ax_cflags_strict_prototypes.m4 b/Build/source/libs/zziplib/m4/ax_cflags_strict_prototypes.m4
new file mode 100644
index 00000000000..518c247e8fd
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ax_cflags_strict_prototypes.m4
@@ -0,0 +1,127 @@
+dnl @synopsis AX_CFLAGS_STRICT_PROTOTYPES [(shellvar [,default, [A/NA]]
+dnl
+dnl Try to find a compiler option that requires strict prototypes.
+dnl
+dnl The sanity check is done by looking at sys/signal.h which has a set
+dnl of macro-definitions SIG_DFL and SIG_IGN that are cast to the local
+dnl signal-handler type. If that signal-handler type is not fully
+dnl qualified then the system headers are not seen as strictly
+dnl prototype clean.
+dnl
+dnl For the GNU CC compiler it will be -fstrict-prototypes
+dnl -Wstrict-prototypes The result is added to the shellvar being
+dnl CFLAGS by default.
+dnl
+dnl DEFAULTS:
+dnl
+dnl - $1 shell-variable-to-add-to : CFLAGS
+dnl - $2 add-value-if-not-found : nothing
+dnl - $3 action-if-found : add value to shellvariable
+dnl - $4 action-if-not-found : nothing
+dnl
+dnl @category C
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2003-05-21
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_CFLAGS_STRICT_PROTOTYPES],[dnl
+AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_strict_prototypes])dnl
+AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for strict prototypes],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_C
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-Wall % -fstrict-prototypes -Wstrict-prototypes" dnl GCC
+ "-Wall % -Wstrict-prototypes" dnl try to warn atleast
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+case ".$VAR" in
+ .|.no|.no,*) ;;
+ *) # sanity check with signal() from sys/signal.h
+ cp config.log config.tmp
+ AC_TRY_COMPILE([#include <signal.h>],[
+ if (signal (SIGINT, SIG_IGN) == SIG_DFL) return 1;
+ if (signal (SIGINT, SIG_IGN) != SIG_DFL) return 2;],
+ dnl the original did use test -n `$CC testprogram.c`
+ [if test `diff config.log config.tmp | grep -i warning | wc -l` != 0
+then if test `diff config.log config.tmp | grep -i warning | wc -l` != 1
+then VAR="no, suppressed, signal.h," ; fi ; fi],
+ [VAR="no, suppressed, signal.h"])
+ rm config.tmp
+ ;;
+esac
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4,[m4_ifval($2,[
+ AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])]) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+dnl the only difference - the LANG selection... and the default FLAGS
+
+AC_DEFUN([AX_CXXFLAGS_STRICT_PROTOTYPES],[dnl
+AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_strict_prototypes])dnl
+AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for strict prototypes],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_CXX
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-Wall % -fstrict-prototypes -Wstrict-prototypes" dnl GCC
+ "-Wall % -Wstrict-prototypes" dnl try to warn atleast
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+case ".$VAR" in
+ .|.no|.no,*) ;;
+ *) # sanity check with signal() from sys/signal.h
+ cp config.log config.tmp
+ AC_TRY_COMPILE([#include <signal.h>],[
+ if (signal (SIGINT, SIG_IGN) == SIG_DFL) return 1;
+ if (signal (SIGINT, SIG_IGN) != SIG_DFL) return 2;],
+ dnl the original did use test -n `$CC testprogram.c`
+ [if test `diff config.log config.tmp | grep -i warning | wc -l` != 0
+then if test `diff config.log config.tmp | grep -i warning | wc -l` != 1
+then VAR="no, suppressed, signal.h," ; fi ; fi],
+ [VAR="no, suppressed, signal.h"])
+ rm config.tmp
+ ;;
+esac
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4,[m4_ifval($2,[
+ AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])]) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
diff --git a/Build/source/libs/zziplib/m4/ax_cflags_warn_all.m4 b/Build/source/libs/zziplib/m4/ax_cflags_warn_all.m4
new file mode 100644
index 00000000000..fa9bf30e17f
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ax_cflags_warn_all.m4
@@ -0,0 +1,118 @@
+dnl @synopsis AX_CFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
+dnl
+dnl Try to find a compiler option that enables most reasonable
+dnl warnings. This macro is directly derived from VL_PROG_CC_WARNINGS
+dnl which is split up into two AX_CFLAGS_WARN_ALL and
+dnl AX_CFLAGS_WARN_ALL_ANSI
+dnl
+dnl For the GNU CC compiler it will be -Wall (and -ansi -pedantic) The
+dnl result is added to the shellvar being CFLAGS by default.
+dnl
+dnl Currently this macro knows about GCC, Solaris C compiler, Digital
+dnl Unix C compiler, C for AIX Compiler, HP-UX C compiler, IRIX C
+dnl compiler, NEC SX-5 (Super-UX 10) C compiler, and Cray J90 (Unicos
+dnl 10.0.0.8) C compiler.
+dnl
+dnl - $1 shell-variable-to-add-to : CFLAGS
+dnl - $2 add-value-if-not-found : nothing
+dnl - $3 action-if-found : add value to shellvariable
+dnl - $4 action-if-not-found : nothing
+dnl
+dnl @category C
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2003-01-06
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_CFLAGS_WARN_ALL],[dnl
+AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_warn_all])dnl
+AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_C
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-pedantic % -Wall" dnl GCC
+ "-xstrconst % -v" dnl Solaris C
+ "-std1 % -verbose -w0 -warnprotos" dnl Digital Unix
+ "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX
+ "-ansi -ansiE % -fullwarn" dnl IRIX
+ "+ESlit % +w1" dnl HP-UX C
+ "-Xc % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10)
+ "-h conform % -h msglevel 2" dnl Cray C (Unicos)
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4,[m4_ifval($2,[
+ AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])]) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+dnl the only difference - the LANG selection... and the default FLAGS
+
+AC_DEFUN([AX_CXXFLAGS_WARN_ALL],[dnl
+AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_warn_all])dnl
+AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_CXX
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-pedantic % -Wall" dnl GCC
+ "-xstrconst % -v" dnl Solaris C
+ "-std1 % -verbose -w0 -warnprotos" dnl Digital Unix
+ "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX
+ "-ansi -ansiE % -fullwarn" dnl IRIX
+ "+ESlit % +w1" dnl HP-UX C
+ "-Xc % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10)
+ "-h conform % -h msglevel 2" dnl Cray C (Unicos)
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4,[m4_ifval($2,[
+ AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])]) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+dnl implementation tactics:
+dnl the for-argument contains a list of options. The first part of
+dnl these does only exist to detect the compiler - usually it is
+dnl a global option to enable -ansi or -extrawarnings. All other
+dnl compilers will fail about it. That was needed since a lot of
+dnl compilers will give false positives for some option-syntax
+dnl like -Woption or -Xoption as they think of it is a pass-through
+dnl to later compile stages or something. The "%" is used as a
+dnl delimimiter. A non-option comment can be given after "%%" marks.
diff --git a/Build/source/libs/zziplib/m4/ax_create_pkgconfig_info.m4 b/Build/source/libs/zziplib/m4/ax_create_pkgconfig_info.m4
new file mode 100644
index 00000000000..7cf6c2c6ca3
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ax_create_pkgconfig_info.m4
@@ -0,0 +1,312 @@
+dnl @synopsis AX_CREATE_PKGCONFIG_INFO [(outputfile, [requires [,libs [,summary [,cflags [, ldflags]]]]])]
+dnl
+dnl defaults:
+dnl
+dnl $1 = $PACKAGE_NAME.pc
+dnl $2 = (empty)
+dnl $3 = $PACKAGE_LIBS $LIBS (as set at that point in configure.ac)
+dnl $4 = $PACKAGE_SUMMARY (or $1 Library)
+dnl $5 = $CPPFLAGS $PACKAGE_CFLAGS (as set at the point in configure.ac)
+dnl $6 = $LDFLAGS $PACKAGE_LDFLAGS (as set at the point in configure.ac)
+dnl
+dnl PACKAGE_NAME defaults to $PACKAGE if not set.
+dnl PACKAGE_LIBS defaults to -l$PACKAGE_NAME if not set.
+dnl
+dnl the resulting file is called $PACKAGE.pc.in / $PACKAGE.pc
+dnl
+dnl You will find this macro most useful in conjunction with
+dnl ax_spec_defaults that can read good initializers from the .spec
+dnl file. In consequencd, most of the generatable installable stuff can
+dnl be made from information being updated in a single place for the
+dnl whole project.
+dnl
+dnl @category InstalledPackages
+dnl @author Sven Verdoolaege <skimo*liacs.nl>
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2003-10-19
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_CREATE_PKGCONFIG_INFO],[dnl
+AS_VAR_PUSHDEF([PKGCONFIG_suffix],[ax_create_pkgconfig_suffix])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_libdir],[ax_create_pkgconfig_libdir])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_libfile],[ax_create_pkgconfig_libfile])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_libname],[ax_create_pkgconfig_libname])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_version],[ax_create_pkgconfig_version])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_description],[ax_create_pkgconfig_description])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_requires],[ax_create_pkgconfig_requires])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_pkglibs],[ax_create_pkgconfig_pkglibs])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_libs],[ax_create_pkgconfig_libs])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_ldflags],[ax_create_pkgconfig_ldflags])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_cppflags],[ax_create_pkgconfig_cppflags])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_generate],[ax_create_pkgconfig_generate])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_src_libdir],[ax_create_pkgconfig_src_libdir])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_src_headers],[ax_create_pkgconfig_src_headers])dnl
+
+# we need the expanded forms...
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+AC_MSG_CHECKING(our pkgconfig libname)
+test ".$PKGCONFIG_libname" != "." || \
+PKGCONFIG_libname="ifelse($1,,${PACKAGE_NAME},`basename $1 .pc`)"
+test ".$PKGCONFIG_libname" != "." || \
+PKGCONFIG_libname="$PACKAGE"
+PKGCONFIG_libname=`eval echo "$PKGCONFIG_libname"`
+PKGCONFIG_libname=`eval echo "$PKGCONFIG_libname"`
+AC_MSG_RESULT($PKGCONFIG_libname)
+
+AC_MSG_CHECKING(our pkgconfig version)
+test ".$PKGCONFIG_version" != "." || \
+PKGCONFIG_version="${PACKAGE_VERSION}"
+test ".$PKGCONFIG_version" != "." || \
+PKGCONFIG_version="$VERSION"
+PKGCONFIG_version=`eval echo "$PKGCONFIG_version"`
+PKGCONFIG_version=`eval echo "$PKGCONFIG_version"`
+AC_MSG_RESULT($PKGCONFIG_version)
+
+AC_MSG_CHECKING(our pkgconfig_libdir)
+test ".$pkgconfig_libdir" = "." && \
+pkgconfig_libdir='${libdir}/pkgconfig'
+PKGCONFIG_libdir=`eval echo "$pkgconfig_libdir"`
+PKGCONFIG_libdir=`eval echo "$PKGCONFIG_libdir"`
+PKGCONFIG_libdir=`eval echo "$PKGCONFIG_libdir"`
+AC_MSG_RESULT($pkgconfig_libdir)
+test "$pkgconfig_libdir" != "$PKGCONFIG_libdir" && (
+AC_MSG_RESULT(expanded our pkgconfig_libdir... $PKGCONFIG_libdir))
+AC_SUBST([pkgconfig_libdir])
+
+AC_MSG_CHECKING(our pkgconfig_libfile)
+test ".$pkgconfig_libfile" != "." || \
+pkgconfig_libfile="ifelse($1,,$PKGCONFIG_libname.pc,`basename $1`)"
+PKGCONFIG_libfile=`eval echo "$pkgconfig_libfile"`
+PKGCONFIG_libfile=`eval echo "$PKGCONFIG_libfile"`
+AC_MSG_RESULT($pkgconfig_libfile)
+test "$pkgconfig_libfile" != "$PKGCONFIG_libfile" && (
+AC_MSG_RESULT(expanded our pkgconfig_libfile... $PKGCONFIG_libfile))
+AC_SUBST([pkgconfig_libfile])
+
+AC_MSG_CHECKING(our package / suffix)
+PKGCONFIG_suffix="$program_suffix"
+test ".$PKGCONFIG_suffix" != .NONE || PKGCONFIG_suffix=""
+AC_MSG_RESULT(${PACKAGE_NAME} / ${PKGCONFIG_suffix})
+
+AC_MSG_CHECKING(our pkgconfig description)
+PKGCONFIG_description="ifelse($4,,$PACKAGE_SUMMARY,$4)"
+test ".$PKGCONFIG_description" != "." || \
+PKGCONFIG_description="$PKGCONFIG_libname Library"
+PKGCONFIG_description=`eval echo "$PKGCONFIG_description"`
+PKGCONFIG_description=`eval echo "$PKGCONFIG_description"`
+AC_MSG_RESULT($PKGCONFIG_description)
+
+AC_MSG_CHECKING(our pkgconfig requires)
+PKGCONFIG_requires="ifelse($2,,$PACKAGE_REQUIRES,$2)"
+PKGCONFIG_requires=`eval echo "$PKGCONFIG_requires"`
+PKGCONFIG_requires=`eval echo "$PKGCONFIG_requires"`
+AC_MSG_RESULT($PKGCONFIG_requires)
+
+AC_MSG_CHECKING(our pkgconfig ext libs)
+PKGCONFIG_pkglibs="$PACKAGE_LIBS"
+test ".$PKGCONFIG_pkglibs" != "." || PKGCONFIG_pkglibs="-l$PKGCONFIG_libname"
+PKGCONFIG_libs="ifelse($3,,$PKGCONFIG_pkglibs $LIBS,$3)"
+PKGCONFIG_libs=`eval echo "$PKGCONFIG_libs"`
+PKGCONFIG_libs=`eval echo "$PKGCONFIG_libs"`
+AC_MSG_RESULT($PKGCONFIG_libs)
+
+AC_MSG_CHECKING(our pkgconfig cppflags)
+PKGCONFIG_cppflags="ifelse($5,,$CPPFLAGS $PACKAGE_CFLAGS,$5)"
+PKGCONFIG_cppflags=`eval echo "$PKGCONFIG_cppflags"`
+PKGCONFIG_cppflags=`eval echo "$PKGCONFIG_cppflags"`
+AC_MSG_RESULT($PKGCONFIG_cppflags)
+
+AC_MSG_CHECKING(our pkgconfig ldflags)
+PKGCONFIG_ldflags="ifelse($6,,$LDFLAGS $PACKAGE_LDFLAGS,$5)"
+PKGCONFIG_ldflags=`eval echo "$PKGCONFIG_ldflags"`
+PKGCONFIG_ldflags=`eval echo "$PKGCONFIG_ldflags"`
+AC_MSG_RESULT($PKGCONFIG_ldflags)
+
+test ".$PKGCONFIG_generate" != "." || \
+PKGCONFIG_generate="ifelse($1,,$PKGCONFIG_libname.pc,$1)"
+PKGCONFIG_generate=`eval echo "$PKGCONFIG_generate"`
+PKGCONFIG_generate=`eval echo "$PKGCONFIG_generate"`
+test "$pkgconfig_libfile" != "$PKGCONFIG_generate" && (
+AC_MSG_RESULT(generate the pkgconfig later... $PKGCONFIG_generate))
+
+if test ".$PKGCONFIG_src_libdir" = "." ; then
+PKGCONFIG_src_libdir=`pwd`
+PKGCONFIG_src_libdir=`AS_DIRNAME("$PKGCONFIG_src_libdir/$PKGCONFIG_generate")`
+test ! -d $PKGCONFIG_src_libdir/src || \
+PKGCONFIG_src_libdir="$PKGCONFIG_src_libdir/src"
+case ".$objdir" in
+*libs) PKGCONFIG_src_libdir="$PKGCONFIG_src_libdir/$objdir" ;; esac
+AC_MSG_RESULT(noninstalled pkgconfig -L $PKGCONFIG_src_libdir)
+fi
+
+if test ".$PKGCONFIG_src_headers" = "." ; then
+PKGCONFIG_src_headers=`pwd`
+v="$ac_top_srcdir" ;
+test ".$v" != "." || v="$ax_spec_dir"
+test ".$v" != "." || v="$srcdir"
+case "$v" in /*) PKG_CONFIG_src_headers="" ;; esac
+PKGCONFIG_src_headers=`AS_DIRNAME("$PKGCONFIG_src_headers/$v/x")`
+test ! -d $PKGCONFIG_src_headers/incl[]ude || \
+PKGCONFIG_src_headers="$PKGCONFIG_src_headers/incl[]ude"
+AC_MSG_RESULT(noninstalled pkgconfig -I $PKGCONFIG_src_headers)
+fi
+
+
+dnl AC_CONFIG_COMMANDS crap disallows to use $PKGCONFIG_libfile here...
+AC_CONFIG_COMMANDS([$ax_create_pkgconfig_generate],[
+pkgconfig_generate="$ax_create_pkgconfig_generate"
+if test ! -f "$pkgconfig_generate.in"
+then generate="true"
+elif grep ' generated by configure ' $pkgconfig_generate.in >/dev/null
+then generate="true"
+else generate="false";
+fi
+if $generate ; then
+AC_MSG_NOTICE(creating $pkgconfig_generate.in)
+cat > $pkgconfig_generate.in <<AXEOF
+# generated by configure / remove this line to disable regeneration
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+datadir=@datadir@
+sysconfdir=@sysconfdir@
+includedir=@includedir@
+package=@PACKAGE@
+suffix=@suffix@
+
+Name: @PACKAGE_NAME@
+Description: @PACKAGE_DESCRIPTION@
+Version: @PACKAGE_VERSION@
+Requires: @PACKAGE_REQUIRES@
+Libs: -L\${libdir} @LDFLAGS@ @LIBS@
+Cflags: -I\${includedir} @CPPFLAGS@
+AXEOF
+fi # DONE generate $pkgconfig_generate.in
+AC_MSG_NOTICE(creating $pkgconfig_generate)
+cat >conftest.sed <<AXEOF
+s|@prefix@|${pkgconfig_prefix}|
+s|@exec_prefix@|${pkgconfig_execprefix}|
+s|@bindir@|${pkgconfig_bindir}|
+s|@libdir@|${pkgconfig_libdir}|
+s|@datadir@|${pkgconfig_datadir}|
+s|@sysconfdir@|${pkgconfig_sysconfdir}|
+s|@includedir@|${pkgconfig_includedir}|
+s|@suffix@|${pkgconfig_suffix}|
+s|@PACKAGE@|${pkgconfig_package}|
+s|@PACKAGE_NAME@|${pkgconfig_libname}|
+s|@PACKAGE_DESCRIPTION@|${pkgconfig_description}|
+s|@PACKAGE_VERSION@|${pkgconfig_version}|
+s|@PACKAGE_REQUIRES@|${pkgconfig_requires}|
+s|@LIBS@|${pkgconfig_libs}|
+s|@LDFLAGS@|${pkgconfig_ldflags}|
+s|@CPPFLAGS@|${pkgconfig_cppflags}|
+AXEOF
+sed -f conftest.sed $pkgconfig_generate.in > $pkgconfig_generate
+if test ! -s $pkgconfig_generate ; then
+ AC_MSG_ERROR([$pkgconfig_generate is empty])
+fi ; rm conftest.sed # DONE generate $pkgconfig_generate
+pkgconfig_uninstalled=`echo $pkgconfig_generate |sed 's/.pc$/-uninstalled.pc/'`
+AC_MSG_NOTICE(creating $pkgconfig_uninstalled)
+cat >conftest.sed <<AXEOF
+s|@prefix@|${pkgconfig_prefix}|
+s|@exec_prefix@|${pkgconfig_execprefix}|
+s|@bindir@|${pkgconfig_bindir}|
+s|@libdir@|${pkgconfig_src_libdir}|
+s|@datadir@|${pkgconfig_datadir}|
+s|@sysconfdir@|${pkgconfig_sysconfdir}|
+s|@includedir@|${pkgconfig_src_headers}|
+s|@suffix@|${pkgconfig_suffix}|
+s|@PACKAGE@|${pkgconfig_package}|
+s|@PACKAGE_NAME@|${pkgconfig_libname}|
+s|@PACKAGE_DESCRIPTION@|${pkgconfig_description}|
+s|@PACKAGE_VERSION@|${pkgconfig_version}|
+s|@PACKAGE_REQUIRES@|${pkgconfig_requires}|
+s|@LIBS@|${pkgconfig_libs}|
+s|@LDFLAGS@|${pkgconfig_ldflags}|
+s|@CPPFLAGS@|${pkgconfig_cppflags}|
+AXEOF
+sed -f conftest.sed $pkgconfig_generate.in > $pkgconfig_uninstalled
+if test ! -s $pkgconfig_uninstalled ; then
+ AC_MSG_ERROR([$pkgconfig_uninstalled is empty])
+fi ; rm conftest.sed # DONE generate $pkgconfig_uninstalled
+ pkgconfig_requires_add=`echo ${pkgconfig_requires}`
+if test ".$pkgconfig_requires_add" != "." ; then
+ pkgconfig_requires_add="pkg-config $pkgconfig_requires_add"
+ else pkgconfig_requires_add=":" ; fi
+pkgconfig_uninstalled=`echo $pkgconfig_generate |sed 's/.pc$/-uninstalled.sh/'`
+AC_MSG_NOTICE(creating $pkgconfig_uninstalled)
+cat >conftest.sed <<AXEOF
+s|@prefix@|\"${pkgconfig_prefix}\"|
+s|@exec_prefix@|\"${pkgconfig_execprefix}\"|
+s|@bindir@|\"${pkgconfig_bindir}\"|
+s|@libdir@|\"${pkgconfig_src_libdir}\"|
+s|@datadir@|\"${pkgconfig_datadir}\"|
+s|@sysconfdir@|\"${pkgconfig_sysconfdir}\"|
+s|@includedir@|\"${pkgconfig_src_headers}\"|
+s|@suffix@|\"${pkgconfig_suffix}\"|
+s|@PACKAGE@|\"${pkgconfig_package}\"|
+s|@PACKAGE_NAME@|\"${pkgconfig_libname}\"|
+s|@PACKAGE_DESCRIPTION@|\"${pkgconfig_description}\"|
+s|@PACKAGE_VERSION@|\"${pkgconfig_version}\"|
+s|@PACKAGE_REQUIRES@|\"${pkgconfig_requires}\"|
+s|@LIBS@|\"${pkgconfig_libs}\"|
+s|@LDFLAGS@|\"${pkgconfig_ldflags}\"|
+s|@CPPFLAGS@|\"${pkgconfig_cppflags}\"|
+s>Name:>for option\\; do case \"\$option\" in --list-all|--name) echo >
+s>Description: *>\\;\\; --help) pkg-config --help \\; echo Buildscript Of >
+s>Version: *>\\;\\; --modversion|--version) echo >
+s>Requires:>\\;\\; --requires) echo $pkgconfig_requires_add>
+s>Libs: *>\\;\\; --libs) echo >
+s>Cflags: *>\\;\\; --cflags) echo >
+/--libs)/a\\
+ $pkgconfig_requires_add
+/--cflags)/a\\
+ $pkgconfig_requires_add\\
+;; --variable=*) eval echo '\$'\`echo \$option | sed -e 's/.*=//'\`\\
+;; --uninstalled) exit 0 \\
+;; *) ;; esac done
+AXEOF
+sed -f conftest.sed $pkgconfig_generate.in > $pkgconfig_uninstalled
+if test ! -s $pkgconfig_uninstalled ; then
+ AC_MSG_ERROR([$pkgconfig_uninstalled is empty])
+fi ; rm conftest.sed # DONE generate $pkgconfig_uninstalled
+],[
+dnl AC_CONFIG_COMMANDS crap, the AS_PUSHVAR defines are invalid here...
+ax_create_pkgconfig_generate="$ax_create_pkgconfig_generate"
+pkgconfig_prefix='$prefix'
+pkgconfig_execprefix='$exec_prefix'
+pkgconfig_bindir='$bindir'
+pkgconfig_libdir='$libdir'
+pkgconfig_includedir='$includedir'
+pkgconfig_datadir='$datadir'
+pkgconfig_sysconfdir='$sysconfdir'
+pkgconfig_suffix='$ax_create_pkgconfig_suffix'
+pkgconfig_package='$PACKAGE_NAME'
+pkgconfig_libname='$ax_create_pkgconfig_libname'
+pkgconfig_description='$ax_create_pkgconfig_description'
+pkgconfig_version='$ax_create_pkgconfig_version'
+pkgconfig_requires='$ax_create_pkgconfig_requires'
+pkgconfig_libs='$ax_create_pkgconfig_libs'
+pkgconfig_ldflags='$ax_create_pkgconfig_ldflags'
+pkgconfig_cppflags='$ax_create_pkgconfig_cppflags'
+pkgconfig_src_libdir='$ax_create_pkgconfig_src_libdir'
+pkgconfig_src_headers='$ax_create_pkgconfig_src_headers'
+])dnl
+AS_VAR_POPDEF([PKGCONFIG_suffix])dnl
+AS_VAR_POPDEF([PKGCONFIG_libdir])dnl
+AS_VAR_POPDEF([PKGCONFIG_libfile])dnl
+AS_VAR_POPDEF([PKGCONFIG_libname])dnl
+AS_VAR_POPDEF([PKGCONFIG_version])dnl
+AS_VAR_POPDEF([PKGCONFIG_description])dnl
+AS_VAR_POPDEF([PKGCONFIG_requires])dnl
+AS_VAR_POPDEF([PKGCONFIG_pkglibs])dnl
+AS_VAR_POPDEF([PKGCONFIG_libs])dnl
+AS_VAR_POPDEF([PKGCONFIG_ldflags])dnl
+AS_VAR_POPDEF([PKGCONFIG_cppflags])dnl
+AS_VAR_POPDEF([PKGCONFIG_generate])dnl
+AS_VAR_POPDEF([PKGCONFIG_src_libdir])dnl
+AS_VAR_POPDEF([PKGCONFIG_src_headers])dnl
+])
diff --git a/Build/source/libs/zziplib/m4/ax_enable_builddir_uname.m4 b/Build/source/libs/zziplib/m4/ax_enable_builddir_uname.m4
new file mode 100644
index 00000000000..4e795fc8274
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ax_enable_builddir_uname.m4
@@ -0,0 +1,160 @@
+dnl @synopsis AX_ENABLE_BUILDDIR_UNAME [(dirstring-or-command [,Makefile.mk])]
+dnl
+dnl if the current configure was run within the srcdir then we move all
+dnl configure-files into a subdir and let the configure steps continue
+dnl there. We provide an option --disable-builddir to suppress the move
+dnl into a separate builddir.
+dnl
+dnl Defaults:
+dnl
+dnl $1 = $build (defaults to `uname -msr`.d)
+dnl $2 = Makefile.mk
+dnl $3 = -all
+dnl
+dnl This macro must be called before AM_INIT_AUTOMAKE.
+dnl
+dnl it creates a default toplevel srcdir Makefile from the information
+dnl found in the created toplevel builddir Makefile. It just copies the
+dnl variables and rule-targets, each extended with a default
+dnl rule-execution that recurses into the build directory of the
+dnl current "BUILD". You can override the auto-dection through
+dnl `uname -msr | tr " /" "__"`.d at build-time of course, as in
+dnl
+dnl make BUILD=i386-mingw-cross
+dnl
+dnl After the default has been created, additional rules can be
+dnl appended that will not just recurse into the subdirectories and
+dnl only ever exist in the srcdir toplevel makefile - these parts are
+dnl read from the $2 = Makefile.mk file
+dnl
+dnl The automatic rules are usually scanning the toplevel Makefile for
+dnl lines like '#### $build |$builddir' to recognize the place where to
+dnl recurse into. Usually, the last one is the only one used. However,
+dnl almost all targets have an additional "*-all" rule which makes the
+dnl script to recurse into _all_ variants of the current BUILD (!!)
+dnl setting. The "-all" suffix can be overriden for the macro as well.
+dnl
+dnl a special rule is only given for things like "dist" that will copy
+dnl the tarball from the builddir to the sourcedir (or $(PUB)) for
+dnl reason of convenience.
+dnl
+dnl @category Misc
+dnl @author Guido U. Draheim
+dnl @version 2005-12-03
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_ENABLE_BUILDDIR_UNAME],[AC_REQUIRE([AC_CANONICAL_HOST])[]dnl
+AC_BEFORE([$0],[AM_INIT_AUTOMAKE])dnl
+AS_VAR_PUSHDEF([SUB],[ax_enable_builddir])dnl
+AS_VAR_PUSHDEF([SED],[ax_enable_builddir_sed])dnl
+SUB="."
+AC_ARG_ENABLE([builddir], AC_HELP_STRING(
+ [--disable-builddir],[disable automatic build in subdir of sources])
+ ,[SUB="$enableval"], [SUB="yes"])
+if test ".$ac_srcdir_defaulted" != ".no" ; then
+if test ".$srcdir" = ".." ; then
+ if test -f config.status ; then
+ AC_MSG_NOTICE(toplevel srcdir already configured... skipping subdir build)
+ else
+ test ".$SUB" = "." && SUB="."
+ test ".$SUB" = ".no" && SUB="."
+ test ".$BUILD" = "." && BUILD=`uname -msr | tr " /" "__"`.d
+ test ".$SUB" = ".yes" && SUB="m4_ifval([$1], [$1],[$BUILD])"
+ if test ".$SUB" != ".." ; then # we know where to go and
+ AS_MKDIR_P([$SUB])
+ echo __.$SUB.__ > $SUB/conftest.tmp
+ cd $SUB
+ if grep __.$SUB.__ conftest.tmp >/dev/null 2>/dev/null ; then
+ rm conftest.tmp
+ AC_MSG_RESULT([continue configure in default builddir "./$SUB"])
+ else
+ AC_MSG_ERROR([could not change to default builddir "./$SUB"])
+ fi
+ srcdir=`echo "$SUB" |
+ sed -e 's,^\./,,;s,[[^/]]$,&/,;s,[[^/]]*/,../,g;s,[[/]]$,,;'`
+ # going to restart from subdirectory location
+ test -f $srcdir/config.log && mv $srcdir/config.log .
+ test -f $srcdir/confdefs.h && mv $srcdir/confdefs.h .
+ test -f $srcdir/conftest.log && mv $srcdir/conftest.log .
+ test -f $srcdir/$cache_file && mv $srcdir/$cache_file .
+ AC_MSG_RESULT(....exec $SHELL $srcdir/[$]0 "--srcdir=$srcdir" "--enable-builddir=$SUB" ${1+"[$]@"})
+ case "[$]0" in # restart
+ [/\\]) exec $SHELL [$]0 "--srcdir=$srcdir" "--enable-builddir=$SUB" ${1+"[$]@"} ;;
+ *) exec $SHELL $srcdir/[$]0 "--srcdir=$srcdir" "--enable-builddir=$SUB" ${1+"[$]@"} ;;
+ esac
+ fi
+ fi
+fi fi
+dnl ac_path_prog uses "set dummy" to override $@ which would defeat the "exec"
+AC_PATH_PROG(SED,gsed sed, sed)
+AS_VAR_POPDEF([SED])dnl
+AS_VAR_POPDEF([SUB])dnl
+AC_CONFIG_COMMANDS([buildir],[dnl .............. config.status ..............
+AS_VAR_PUSHDEF([SUB],[ax_enable_builddir])dnl
+AS_VAR_PUSHDEF([TOP],[top_srcdir])dnl
+AS_VAR_PUSHDEF([SRC],[ac_top_srcdir])dnl
+AS_VAR_PUSHDEF([SED],[ax_enable_builddir_sed])dnl
+pushdef([END],[Makefile.mk])dnl
+ SRC="$ax_enable_builddir_srcdir"
+ if test ".$SUB" = "." ; then
+ if test -f "$TOP/Makefile" ; then
+ AC_MSG_NOTICE([skipping TOP/Makefile - left untouched])
+ else
+ AC_MSG_NOTICE([skipping TOP/Makefile - not created])
+ fi
+ else
+ AC_MSG_NOTICE([create TOP/Makefile guessed from local Makefile])
+ x='`' ; cat >$tmp/conftemp.sed <<_EOF
+/^\$/n
+x
+/^\$/bS
+x
+/\\\\\$/{H;d;}
+{H;s/.*//;x;}
+bM
+:S
+x
+/\\\\\$/{h;d;}
+{h;s/.*//;x;}
+:M
+s/\\(\\n\\) /\\1 /g
+/^ /d
+/^[[ ]]*[[\\#]]/d
+/^VPATH *=/d
+s/^srcdir *=.*/srcdir = ./
+s/^top_srcdir *=.*/top_srcdir = ./
+/[[:=]]/!d
+/^\\./d
+s/:.*/:/
+/:\$/s/ / /g
+/:\$/s/ / /g
+/^.*[[=]]/!s%\$% ; (cd \$(BUILD) \\&\\& \$(ISNOTSRCDIR) \\&\\& \$(MAKE) "\$\@") || exit ; \$(MAKE) done "RULE=\$\@"%
+_EOF
+ test ".$USE_MAINTAINER_MODE" = ".no" || \
+ cp "$tmp/conftemp.sed" "$SRC/makefile.sed~" ## DEBUGGING
+ echo 'BUILD=`uname -msr | tr " /" "__"`.d' >$SRC/Makefile
+ echo 'ISNOTSRCDIR=test ! -f configure' >>$SRC/Makefile
+ $SED -f $tmp/conftemp.sed Makefile >>$SRC/Makefile
+ echo 'done: ;@ if grep "$(RULE)-done .*:" Makefile > /dev/null; then dnl
+ echo $(MAKE) $(RULE)-done ; $(MAKE) $(RULE)-done ; else true ; fi' dnl
+ >> $SRC/Makefile
+ if test -f "$SRC/m4_ifval([$2],[$2],[END])" ; then
+ AC_MSG_NOTICE([extend TOP/Makefile with TOP/m4_ifval([$2],[$2],[END])])
+ cat $SRC/END >>$SRC/Makefile
+ fi
+ AC_MSG_NOTICE([make uses BUILD=$SUB (on $ax_enable_builddir_host:)])
+ fi
+popdef([END])dnl
+AS_VAR_POPDEF([SED])dnl
+AS_VAR_POPDEF([SRC])dnl
+AS_VAR_POPDEF([TOP])dnl
+AS_VAR_POPDEF([SUB])dnl
+],[dnl
+ax_enable_builddir_srcdir="$srcdir" # $srcdir
+ax_enable_builddir_host="$HOST" # $HOST / $host
+ax_enable_builddir_version="$VERSION" # $VERSION
+ax_enable_builddir_package="$PACKAGE" # $PACKAGE
+ax_enable_builddir_sed="$ax_enable_builddir_sed" # $SED
+ax_enable_builddir="$ax_enable_builddir" # $SUB
+])dnl
+])
diff --git a/Build/source/libs/zziplib/m4/ax_expand_prefix.m4 b/Build/source/libs/zziplib/m4/ax_expand_prefix.m4
new file mode 100644
index 00000000000..95407ce99e2
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ax_expand_prefix.m4
@@ -0,0 +1,33 @@
+dnl @synopsis AX_EXPAND_PREFIX
+dnl
+dnl when $prefix and $exec_prefix are still set to NONE then set them
+dnl to the usual default values - being based on $ac_default_prefix. -
+dnl this macro can be AC_REQUIREd by other macros that need to compute
+dnl values for installation directories. It has been observed that it
+dnl was done wrong over and over again, so this is a bit more safe to
+dnl do.
+dnl
+dnl remember - setting exec_prefix='${prefix}' needs you interpolate
+dnl directories multiple times, it is not sufficient to just say
+dnl MYVAR="${datadir}/putter" but you do have to run `eval` a few
+dnl times, sth. like MYVAR=`eval "echo \"$MYVAR\""` done atleast two
+dnl times.
+dnl
+dnl The implementation of this macro simply picks up the lines that
+dnl would be run at the start of AC_OUTPUT anyway to set the
+dnl prefix/exec_prefix defaults. Between AC_INIT and the first command
+dnl to AC_REQUIRE this macro you can set the two variables to something
+dnl explicit instead. Probably, any command to compute installation
+dnl directories should be run _after_ AM_INIT_AUTOMAKE
+dnl
+dnl @category Misc
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2005-01-21
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_EXPAND_PREFIX],[dnl
+ # The prefix default can be set in configure.ac (otherwise it is /usr/local)
+ test "x$prefix" = xNONE && prefix=$ac_default_prefix
+ # Let make expand exec_prefix. Allows to override the makevar 'prefix' later
+ test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+])
diff --git a/Build/source/libs/zziplib/m4/ax_maintainer_mode_auto_silent.m4 b/Build/source/libs/zziplib/m4/ax_maintainer_mode_auto_silent.m4
new file mode 100644
index 00000000000..de6c41ec04c
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ax_maintainer_mode_auto_silent.m4
@@ -0,0 +1,38 @@
+dnl @synopsis AX_MAINTAINER_MODE_AUTO_SILENT
+dnl
+dnl Set autotools to error/sleep settings so that they are not run when
+dnl being errornously triggered. Likewise make libtool-silent when
+dnl libtool has been used.
+dnl
+dnl I am using the macro quite a lot since some automake versions had
+dnl the tendency to try to rerun some autotools on a mere make even
+dnl when not quite in --maintainer-mode. That is very annoying.
+dnl Likewise, a user who installs from source does not want to see
+dnl doubled compiler messages.
+dnl
+dnl I did not put an AC-REQUIRE(MAINTAINER_MODE) in here - should I?
+dnl
+dnl @category Misc
+dnl @category Automake
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2005-01-21
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_MAINTAINER_MODE_AUTO_SILENT],[dnl
+dnl ac_REQUIRE([am_MAINTAINER_MODE])dn
+AC_MSG_CHECKING(auto silent in maintainer mode)
+if test "$USE_MAINTAINER_MODE" = "no" ; then
+ test ".$TIMEOUT" = "." && TIMEOUT="9"
+ AUTOHEADER="sleep $TIMEOUT ; true || autoheader || skipped"
+ AUTOMAKE="sleep $TIMEOUT ; true || automake || skipped"
+ AUTOCONF="sleep $TIMEOUT ; true || autoconf || skipped"
+ if test ".$LIBTOOL" != "." ; then
+ LIBTOOL="$LIBTOOL --silent"
+ AC_MSG_RESULT([libtool-silent, auto-sleep-9])
+ else
+ AC_MSG_RESULT([auto-sleep-9])
+ fi
+else
+ AC_MSG_RESULT([no])
+fi
+])
diff --git a/Build/source/libs/zziplib/m4/ax_not_enable_frame_pointer.m4 b/Build/source/libs/zziplib/m4/ax_not_enable_frame_pointer.m4
new file mode 100644
index 00000000000..94be736537b
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ax_not_enable_frame_pointer.m4
@@ -0,0 +1,31 @@
+
+dnl ______ /usr/share/aclocal/guidod/ax_not_enable_frame_pointer.m4 ______
+dnl @synopsis AX_NOT_ENABLE_FRAME_POINTER ([shellvar])
+dnl
+dnl add --enable-frame-pointer option, the default will add the gcc
+dnl --fomit-frame-pointer option to the shellvar (per default CFLAGS)
+dnl and remove the " -g " debuginfo option from it. In other words,
+dnl the default is "--disable-frame-pointer"
+dnl
+dnl @author guidod@gmx.de
+dnl @version 2004-11-30
+
+AC_DEFUN([AX_NOT_ENABLE_FRAME_POINTER],[dnl
+AS_VAR_PUSHDEF([VAR],[enable_frame_pointer])dnl
+AC_MSG_CHECKING([m4_ifval($1,$1,CFLAGS) frame-pointer])
+AC_ARG_ENABLE([frame-pointer], AC_HELP_STRING(
+ [--enable-frame-pointer],[enable callframe generation for debugging]))
+case ".$VAR" in
+ .|.no|.no,*) test ".$VAR" = "." && VAR="no"
+ m4_ifval($1,$1,CFLAGS)=`echo dnl
+ " $m4_ifval($1,$1,CFLAGS) " | sed -e 's/ -g / /'`
+ if test ".$GCC" = ".yes" ; then
+ m4_ifval($1,$1,CFLAGS)="$m4_ifval($1,$1,CFLAGS) -fomit-frame-pointer"
+ AC_MSG_RESULT([$VAR, -fomit-frame-pointer added])
+ else
+ AC_MSG_RESULT([$VAR, -g removed])
+ fi ;;
+ *) AC_MSG_RESULT([$VAR, kept]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+])
diff --git a/Build/source/libs/zziplib/m4/ax_prefix_config_h.m4 b/Build/source/libs/zziplib/m4/ax_prefix_config_h.m4
new file mode 100644
index 00000000000..efd8bad52f8
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ax_prefix_config_h.m4
@@ -0,0 +1,171 @@
+dnl @synopsis AX_PREFIX_CONFIG_H [(OUTPUT-HEADER [,PREFIX [,ORIG-HEADER]])]
+dnl
+dnl This is a new variant from ac_prefix_config_ this one will use a
+dnl lowercase-prefix if the config-define was starting with a
+dnl lowercase-char, e.g. "#define const", "#define restrict", or
+dnl "#define off_t", (and this one can live in another directory, e.g.
+dnl testpkg/config.h therefore I decided to move the output-header to
+dnl be the first arg)
+dnl
+dnl takes the usual config.h generated header file; looks for each of
+dnl the generated "#define SOMEDEF" lines, and prefixes the defined
+dnl name (ie. makes it "#define PREFIX_SOMEDEF". The result is written
+dnl to the output config.header file. The PREFIX is converted to
+dnl uppercase for the conversions.
+dnl
+dnl Defaults:
+dnl
+dnl OUTPUT-HEADER = $PACKAGE-config.h
+dnl PREFIX = $PACKAGE
+dnl ORIG-HEADER, from AM_CONFIG_HEADER(config.h)
+dnl
+dnl Your configure.ac script should contain both macros in this order,
+dnl and unlike the earlier variations of this prefix-macro it is okay
+dnl to place the AX_PREFIX_CONFIG_H call before the AC_OUTPUT
+dnl invokation.
+dnl
+dnl Example:
+dnl
+dnl AC_INIT(config.h.in) # config.h.in as created by "autoheader"
+dnl AM_INIT_AUTOMAKE(testpkg, 0.1.1) # makes #undef VERSION and PACKAGE
+dnl AM_CONFIG_HEADER(config.h) # prep config.h from config.h.in
+dnl AX_PREFIX_CONFIG_H(mylib/_config.h) # prep mylib/_config.h from it..
+dnl AC_MEMORY_H # makes "#undef NEED_MEMORY_H"
+dnl AC_C_CONST_H # makes "#undef const"
+dnl AC_OUTPUT(Makefile) # creates the "config.h" now
+dnl # and also mylib/_config.h
+dnl
+dnl if the argument to AX_PREFIX_CONFIG_H would have been omitted then
+dnl the default outputfile would have been called simply
+dnl "testpkg-config.h", but even under the name "mylib/_config.h" it
+dnl contains prefix-defines like
+dnl
+dnl #ifndef TESTPKG_VERSION
+dnl #define TESTPKG_VERSION "0.1.1"
+dnl #endif
+dnl #ifndef TESTPKG_NEED_MEMORY_H
+dnl #define TESTPKG_NEED_MEMORY_H 1
+dnl #endif
+dnl #ifndef _testpkg_const
+dnl #define _testpkg_const _const
+dnl #endif
+dnl
+dnl and this "mylib/_config.h" can be installed along with other
+dnl header-files, which is most convenient when creating a shared
+dnl library (that has some headers) where some functionality is
+dnl dependent on the OS-features detected at compile-time. No need to
+dnl invent some "mylib-confdefs.h.in" manually. :-)
+dnl
+dnl Note that some AC_DEFINEs that end up in the config.h file are
+dnl actually self-referential - e.g. AC_C_INLINE, AC_C_CONST, and the
+dnl AC_TYPE_OFF_T say that they "will define inline|const|off_t if the
+dnl system does not do it by itself". You might want to clean up about
+dnl these - consider an extra mylib/conf.h that reads something like:
+dnl
+dnl #include <mylib/_config.h>
+dnl #ifndef _testpkg_const
+dnl #define _testpkg_const const
+dnl #endif
+dnl
+dnl and then start using _testpkg_const in the header files. That is
+dnl also a good thing to differentiate whether some library-user has
+dnl starting to take up with a different compiler, so perhaps it could
+dnl read something like this:
+dnl
+dnl #ifdef _MSC_VER
+dnl #include <mylib/_msvc.h>
+dnl #else
+dnl #include <mylib/_config.h>
+dnl #endif
+dnl #ifndef _testpkg_const
+dnl #define _testpkg_const const
+dnl #endif
+dnl
+dnl @category Misc
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2003-07-03
+dnl @license GPLWithACException
+AC_DEFUN([AX_PREFIX_CONFIG_H],[AC_REQUIRE([AC_CONFIG_HEADER])
+AC_CONFIG_COMMANDS([ifelse($1,,$PACKAGE-config.h,$1)],[dnl
+AS_VAR_PUSHDEF([_OUT],[ac_prefix_conf_OUT])dnl
+AS_VAR_PUSHDEF([_DEF],[ac_prefix_conf_DEF])dnl
+AS_VAR_PUSHDEF([_PKG],[ac_prefix_conf_PKG])dnl
+AS_VAR_PUSHDEF([_LOW],[ac_prefix_conf_LOW])dnl
+AS_VAR_PUSHDEF([_UPP],[ac_prefix_conf_UPP])dnl
+AS_VAR_PUSHDEF([_INP],[ac_prefix_conf_INP])dnl
+m4_pushdef([_script],[conftest.prefix])dnl
+m4_pushdef([_symbol],[m4_cr_Letters[]m4_cr_digits[]_])dnl
+_OUT=`echo ifelse($1, , $PACKAGE-config.h, $1)`
+_DEF=`echo _$_OUT | sed -e "y:m4_cr_letters:m4_cr_LETTERS[]:" -e "s/@<:@^m4_cr_Letters@:>@/_/g"`
+_PKG=`echo ifelse($2, , $PACKAGE, $2)`
+_LOW=`echo _$_PKG | sed -e "y:m4_cr_LETTERS-:m4_cr_letters[]_:"`
+_UPP=`echo $_PKG | sed -e "y:m4_cr_letters-:m4_cr_LETTERS[]_:" -e "/^@<:@m4_cr_digits@:>@/s/^/_/"`
+_INP=`echo "ifelse($3,,,$3)" | sed -e 's/ *//'`
+if test ".$_INP" = "."; then
+ for ac_file in : $CONFIG_HEADERS; do test "_$ac_file" = _: && continue
+ case "$ac_file" in
+ *.h) _INP=$ac_file ;;
+ *)
+ esac
+ test ".$_INP" != "." && break
+ done
+fi
+if test ".$_INP" = "."; then
+ case "$_OUT" in
+ */*) _INP=`basename "$_OUT"`
+ ;;
+ *-*) _INP=`echo "$_OUT" | sed -e "s/@<:@_symbol@:>@*-//"`
+ ;;
+ *) _INP=config.h
+ ;;
+ esac
+fi
+if test -z "$_PKG" ; then
+ AC_MSG_ERROR([no prefix for _PREFIX_PKG_CONFIG_H])
+else
+ if test ! -f "$_INP" ; then if test -f "$srcdir/$_INP" ; then
+ _INP="$srcdir/$_INP"
+ fi fi
+ AC_MSG_NOTICE(creating $_OUT - prefix $_UPP for $_INP defines)
+ if test -f $_INP ; then
+ echo "s/@%:@undef *\\(@<:@m4_cr_LETTERS[]_@:>@\\)/@%:@undef $_UPP""_\\1/" > _script
+ echo "s/@%:@undef *\\(@<:@m4_cr_letters@:>@\\)/@%:@undef $_LOW""_\\1/" >> _script
+ echo "s/@%:@def[]ine *\\(@<:@m4_cr_LETTERS[]_@:>@@<:@_symbol@:>@*\\)\\(.*\\)/@%:@ifndef $_UPP""_\\1 \\" >> _script
+ echo "@%:@def[]ine $_UPP""_\\1 \\2 \\" >> _script
+ echo "@%:@endif/" >>_script
+ echo "s/@%:@def[]ine *\\(@<:@m4_cr_letters@:>@@<:@_symbol@:>@*\\)\\(.*\\)/@%:@ifndef $_LOW""_\\1 \\" >> _script
+ echo "@%:@define $_LOW""_\\1 \\2 \\" >> _script
+ echo "@%:@endif/" >> _script
+ # now executing _script on _DEF input to create _OUT output file
+ echo "@%:@ifndef $_DEF" >$tmp/pconfig.h
+ echo "@%:@def[]ine $_DEF 1" >>$tmp/pconfig.h
+ echo ' ' >>$tmp/pconfig.h
+ echo /'*' $_OUT. Generated automatically at end of configure. '*'/ >>$tmp/pconfig.h
+
+ sed -f _script $_INP >>$tmp/pconfig.h
+ echo ' ' >>$tmp/pconfig.h
+ echo '/* once:' $_DEF '*/' >>$tmp/pconfig.h
+ echo "@%:@endif" >>$tmp/pconfig.h
+ if cmp -s $_OUT $tmp/pconfig.h 2>/dev/null; then
+ AC_MSG_NOTICE([$_OUT is unchanged])
+ else
+ ac_dir=`AS_DIRNAME(["$_OUT"])`
+ AS_MKDIR_P(["$ac_dir"])
+ rm -f "$_OUT"
+ mv $tmp/pconfig.h "$_OUT"
+ fi
+ cp _script _configs.sed
+ else
+ AC_MSG_ERROR([input file $_INP does not exist - skip generating $_OUT])
+ fi
+ rm -f conftest.*
+fi
+m4_popdef([_symbol])dnl
+m4_popdef([_script])dnl
+AS_VAR_POPDEF([_INP])dnl
+AS_VAR_POPDEF([_UPP])dnl
+AS_VAR_POPDEF([_LOW])dnl
+AS_VAR_POPDEF([_PKG])dnl
+AS_VAR_POPDEF([_DEF])dnl
+AS_VAR_POPDEF([_OUT])dnl
+],[PACKAGE="$PACKAGE"])])
diff --git a/Build/source/libs/zziplib/m4/ax_set_version_info.m4 b/Build/source/libs/zziplib/m4/ax_set_version_info.m4
new file mode 100644
index 00000000000..742b6c19772
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ax_set_version_info.m4
@@ -0,0 +1,178 @@
+dnl @synopsis AX_SET_VERSION_INFO [(VERSION [,PREFIX])]
+dnl @synopsis default $1 = $PACKAGE_VERSION
+dnl @synopsis default $2 = <none>
+dnl
+dnl This macro is the successor of AC_SET_RELEASEINFO_VERSIONINFO but
+dnl it can be used in parallel because it uses all different variables.
+dnl
+dnl check the $VERSION number and cut the two last digit-sequences off
+dnl which will form a -version-info in a @VERSION_INFO@ ac_subst while
+dnl the rest is going to the -release name in a @RELEASE_INFO@
+dnl ac_subst.
+dnl
+dnl you should keep these two seperate - the release-name may contain
+dnl alpha-characters and can be modified later with extra release-hints
+dnl e.g. RELEASE_INFO="$RELEASE_INFO-debug" for a debug version of your
+dnl lib. The $VERSION_INFO however should not be touched.
+dnl
+dnl example: a VERSION="2.4.18" will be transformed into
+dnl
+dnl RELEASE_INFO = -release 2
+dnl VERSION_INFO = -versioninfo 4:18
+dnl
+dnl then use these two variables and push them to your libtool linker
+dnl
+dnl libtest_la_LIBADD = @RELEASE_INFO@ @VERSION_INFO@
+dnl
+dnl and for a linux-target this will tell libtool to install the lib as
+dnl
+dnl libmy.so libmy.la libmy.a libmy-2.so.4 libmy-2.so.4.0.18
+dnl
+dnl and executables will get link-resolve-infos for libmy-2.so.4 -
+dnl therefore the patch-level is ignored during ldso linking, and ldso
+dnl will use the one with the highest patchlevel. Using just "-release
+dnl $(VERSION)" during libtool-linking would not do that - omitting the
+dnl -version-info will libtool install libmy.so libmy.la libmy.a
+dnl libmy-2.4.18.so and executables would get hardlinked with the
+dnl 2.4.18 version of your lib.
+dnl
+dnl This background does also explain the default dll name for a win32
+dnl target : libtool will choose to make up libmy-2-4.dll for this
+dnl version spec.
+dnl
+dnl this macro does also set the usual three parts of a version spec
+dnl $MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION but does not ac_subst
+dnl for the plain AX_SET_VERSION_INFO macro. Use instead one of the
+dnl numbered macros AX_SET_VERSION_INFO1 (use first number for release
+dnl part) or that AX_SET_VERSION_INFO2 (use the first two numbers for
+dnl release part).
+dnl
+dnl You may add sublevel parts like "1.4.2-ac5" where the sublevel is
+dnl just killed from these version/release substvars. That allows to
+dnl grab the version off a .spec file like with AX_SPEC_PACKAGE_VERSION
+dnl where the $VERSION is used to name a tarball or distpack like
+dnl mylib-2.2.9pre4
+dnl
+dnl Unlike earlier macros, you can use this one to break up different
+dnl VERSIONs and put them into different variables, just hint with
+dnl PREFIX-setting - i.e. _VERSION(2.4.5,TEST) will set variables named
+dnl TEST_MAJOR_VERSION=2... and of course $TEST_RELEASE_INFO etc. (for
+dnl the moment, it needs to be a literal prefix *sigh*)
+dnl
+dnl @category Misc
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2005-01-21
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_SET_VERSION_INFO1],[dnl
+AS_VAR_PUSHDEF([MAJOR],ifelse($2,,[MAJOR_VERSION],[$2_MAJOR_VERSION]))dnl
+AS_VAR_PUSHDEF([MINOR],ifelse($2,,[MINOR_VERSION],[$2_MINOR_VERSION]))dnl
+AS_VAR_PUSHDEF([MICRO],ifelse($2,,[MICRO_VERSION],[$2_MICRO_VERSION]))dnl
+AS_VAR_PUSHDEF([PATCH],ifelse($2,,[PATCH_VERSION],[$2_PATCH_VERSION]))dnl
+AS_VAR_PUSHDEF([LTREL],ifelse($2,,[RELEASE_INFO],[$2_RELEASE_INFO]))dnl
+AS_VAR_PUSHDEF([LTVER],ifelse($2,,[VERSION_INFO],[$2_VERSION_INFO]))dnl
+test ".$PACKAGE_VERSION" = "." && PACKAGE_VERSION="$VERSION"
+AC_MSG_CHECKING(ifelse($2,,,[$2 ])out linker version info dnl
+ifelse($1,,$PACKAGE_VERSION,$1) )
+ MINOR=`echo ifelse( $1, , $PACKAGE_VERSION, $1 )`
+ MAJOR=`echo "$MINOR" | sed -e 's/[[.]].*//'`
+ MINOR=`echo "$MINOR" | sed -e "s/^$MAJOR//" -e 's/^.//'`
+ MICRO="$MINOR"
+ MINOR=`echo "$MICRO" | sed -e 's/[[.]].*//'`
+ MICRO=`echo "$MICRO" | sed -e "s/^$MINOR//" -e 's/^.//'`
+ PATCH="$MICRO"
+ MICRO=`echo "$PATCH" | sed -e 's/[[^0-9]].*//'`
+ PATCH=`echo "$PATCH" | sed -e "s/^$MICRO//" -e 's/^[[-.]]//'`
+ if test "_$MICRO" = "_" ; then MICRO="0" ; fi
+ if test "_$MINOR" = "_" ; then MINOR="$MAJOR" ; MAJOR="0" ; fi
+ MINOR=`echo "$MINOR" | sed -e 's/[[^0-9]].*//'`
+ LTREL="-release $MAJOR"
+ LTVER="-version-info $MINOR:$MICRO"
+AC_MSG_RESULT([/$MAJOR/$MINOR:$MICRO (-$MAJOR.so.$MINOR.0.$MICRO)])
+AC_SUBST(MAJOR)
+AC_SUBST(MINOR)
+AC_SUBST(MICRO)
+AC_SUBST(PATCH)
+AC_SUBST(LTREL)
+AC_SUBST(LTVER)
+AS_VAR_POPDEF([LTVER])dnl
+AS_VAR_POPDEF([LTREL])dnl
+AS_VAR_POPDEF([PATCH])dnl
+AS_VAR_POPDEF([MICRO])dnl
+AS_VAR_POPDEF([MINOR])dnl
+AS_VAR_POPDEF([MAJOR])dnl
+])
+
+AC_DEFUN([AX_SET_VERSION_INFO2],[dnl
+AS_VAR_PUSHDEF([MAJOR],ifelse($2,,[MAJOR_VERSION],[$2_MAJOR_VERSION]))dnl
+AS_VAR_PUSHDEF([MINOR],ifelse($2,,[MINOR_VERSION],[$2_MINOR_VERSION]))dnl
+AS_VAR_PUSHDEF([MICRO],ifelse($2,,[MICRO_VERSION],[$2_MICRO_VERSION]))dnl
+AS_VAR_PUSHDEF([PATCH],ifelse($2,,[PATCH_VERSION],[$2_PATCH_VERSION]))dnl
+AS_VAR_PUSHDEF([LTREL],ifelse($2,,[RELEASE_INFO],[$2_RELEASE_INFO]))dnl
+AS_VAR_PUSHDEF([LTVER],ifelse($2,,[VERSION_INFO],[$2_VERSION_INFO]))dnl
+test ".$PACKAGE_VERSION" = "." && PACKAGE_VERSION="$VERSION"
+AC_MSG_CHECKING(ifelse($2,,,[$2 ])out linker version info dnl
+ifelse($1,,$PACKAGE_VERSION,$1) )
+ MINOR=`echo ifelse( $1, , $PACKAGE_VERSION, $1 )`
+ MAJOR=`echo "$MINOR" | sed -e 's/[[.]].*//'`
+ MINOR=`echo "$MINOR" | sed -e "s/^$MAJOR//" -e 's/^.//'`
+ MICRO="$MINOR"
+ MINOR=`echo "$MICRO" | sed -e 's/[[.]].*//'`
+ MICRO=`echo "$MICRO" | sed -e "s/^$MINOR//" -e 's/^.//'`
+ PATCH="$MICRO"
+ MICRO=`echo "$PATCH" | sed -e 's/[[^0-9]].*//'`
+ PATCH=`echo "$PATCH" | sed -e "s/^$MICRO//" -e 's/^[[-.]]//'`
+ test "_$MICRO" != "_" || MICRO="0"
+ if test "_$MINOR" != "_" ; then MINOR="$MAJOR" ; MAJOR="0" ; fi
+ MINOR=`echo "$MINOR" | sed -e 's/[[^0-9]].*//'`
+ LTREL="-release $MAJOR.$MINOR"
+ LTVER="-version-info 0:$MICRO"
+AC_MSG_RESULT([/$MAJOR/$MINOR:$MICRO (-$MAJOR.so.$MINOR.0.$MICRO)])
+AC_SUBST(MAJOR)
+AC_SUBST(MINOR)
+AC_SUBST(MICRO)
+AC_SUBST(PATCH)
+AC_SUBST(LTREL)
+AC_SUBST(LTVER)
+AS_VAR_POPDEF([LTVER])dnl
+AS_VAR_POPDEF([LTREL])dnl
+AS_VAR_POPDEF([PATCH])dnl
+AS_VAR_POPDEF([MICRO])dnl
+AS_VAR_POPDEF([MINOR])dnl
+AS_VAR_POPDEF([MAJOR])dnl
+])
+
+AC_DEFUN([AX_SET_VERSION_INFO],[dnl
+AS_VAR_PUSHDEF([MAJOR],ifelse($2,,[MAJOR_VERSION],[$2_MAJOR_VERSION]))dnl
+AS_VAR_PUSHDEF([MINOR],ifelse($2,,[MINOR_VERSION],[$2_MINOR_VERSION]))dnl
+AS_VAR_PUSHDEF([MICRO],ifelse($2,,[MICRO_VERSION],[$2_MICRO_VERSION]))dnl
+AS_VAR_PUSHDEF([PATCH],ifelse($2,,[PATCH_VERSION],[$2_PATCH_VERSION]))dnl
+AS_VAR_PUSHDEF([LTREL],ifelse($2,,[RELEASE_INFO],[$2_RELEASE_INFO]))dnl
+AS_VAR_PUSHDEF([LTVER],ifelse($2,,[VERSION_INFO],[$2_VERSION_INFO]))dnl
+test ".$PACKAGE_VERSION" = "." && PACKAGE_VERSION="$VERSION"
+AC_MSG_CHECKING(ifelse($2,,,[$2 ])out linker version info dnl
+ifelse($1,,$PACKAGE_VERSION,$1) )
+ MINOR=`echo ifelse( $1, , $PACKAGE_VERSION, $1 )`
+ MAJOR=`echo "$MINOR" | sed -e 's/[[.]].*//'`
+ MINOR=`echo "$MINOR" | sed -e "s/^$MAJOR//" -e 's/^.//'`
+ MICRO="$MINOR"
+ MINOR=`echo "$MICRO" | sed -e 's/[[.]].*//'`
+ MICRO=`echo "$MICRO" | sed -e "s/^$MINOR//" -e 's/^.//'`
+ PATCH="$MICRO"
+ MICRO=`echo "$PATCH" | sed -e 's/[[^0-9]].*//'`
+ PATCH=`echo "$PATCH" | sed -e "s/^$MICRO//" -e 's/[[-.]]//'`
+ if test "_$MICRO" = "_" ; then MICRO="0" ; fi
+ if test "_$MINOR" = "_" ; then MINOR="$MAJOR" ; MAJOR="0" ; fi
+ MINOR=`echo "$MINOR" | sed -e 's/[[^0-9]].*//'`
+ LTREL="-release $MAJOR"
+ LTVER="-version-info $MINOR:$MICRO"
+AC_MSG_RESULT([/$MAJOR/$MINOR:$MICRO (-$MAJOR.so.$MINOR.0.$MICRO)])
+AC_SUBST(LTREL)
+AC_SUBST(LTVER)
+AS_VAR_POPDEF([LTVER])dnl
+AS_VAR_POPDEF([LTREL])dnl
+AS_VAR_POPDEF([PATCH])dnl
+AS_VAR_POPDEF([MICRO])dnl
+AS_VAR_POPDEF([MINOR])dnl
+AS_VAR_POPDEF([MAJOR])dnl
+])
diff --git a/Build/source/libs/zziplib/m4/ax_spec_file.m4 b/Build/source/libs/zziplib/m4/ax_spec_file.m4
new file mode 100644
index 00000000000..a12955db3dd
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ax_spec_file.m4
@@ -0,0 +1,98 @@
+dnl @synopsis AX_SPEC_FILE [(rpmspecfile [,subdirpath])]
+dnl
+dnl set the specfile - if no argument has been given then check whether
+dnl the ac_unique_file looks like a .spec file and use it. This macro
+dnl is ac_REQUIRED by many AX_SPEC_ routines.
+dnl
+dnl the AX_SPEC_EXTRACT macro is a helper used by many AX_SPEC_
+dnl routines and therefore placed here to be automatically included in
+dnl the macro set of (older) aclocal/acinclude.
+dnl
+dnl AX_SPEC_EXTRACT(shellvar [,specvar [,defaultvalue]])
+dnl
+dnl @category Misc
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2005-01-21
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_SPEC_FILE],
+[ AC_MSG_CHECKING([rpm spec file])
+ if test ".$1" != "." ; then
+ ax_spec_file_="$1"
+ ax_spec_file=`basename $1`
+ else
+ case ".$ac_unique_file" in
+ *.spec) ax_spec_file="$ac_unique_file"
+ ax_spec_file_="$ac_unique_file" ;;
+ *) ax_spec_file="TODO"
+ if test ".$PACKAGE" != "."
+ then ax_spec_file_="$PACKAGE.spec"
+ else ax_spec_file_="README"
+ fi
+ cat m4_ifset([AS_MESSAGE_LOG_FD],[>&AS_MESSAGE_LOG_FD],[>>config.log]) <<EOF
+ no ax_spec_file argument has been given, using defaults of
+ (1) $ax_spec_file_
+ (2) $ax_spec_file
+EOF
+ ;;
+ esac
+ fi
+ # find specfile
+ for i in ifelse($2,,,$2) . $srcdir $srcdir/.. .. ; do
+ if test -f "$i/$ax_spec_file_" ; then
+ ax_spec_dir="$i"
+ ax_spec_file="$ax_spec_dir/$ax_spec_file_"
+ break
+ fi
+ if test -f "$i/$ax_spec_file" ; then
+ ax_spec_dir="$i"
+ ax_spec_file="$ax_spec_dir/$ax_spec_file"
+ break
+ fi
+ done
+ case "$ax_spec_file" in
+ ./*) if test "$ax_spec_file" = "./$ax_spec_file_" ; then
+ ax_spec_file="$ax_spec_file_"
+ fi
+ AC_MSG_RESULT([$ax_spec_file]) ;;
+ */*) AC_MSG_RESULT([$ax_spec_file]) ;;
+ *) AC_MSG_ERROR([no rpm spec file found]) ;;
+ esac
+ m4_define([m4_ax_spec_file],[ax_spec_file])
+])
+
+dnl AX_SPEC_EXTRACT(shellvar [,specvar [,defaultvalue]])
+
+AC_DEFUN([AX_SPEC_EXTRACT],
+[
+ if test ".$[]$1" = "." ; then
+ $1=`grep -i '^[[ ]]*m4_ifval([$2],[$2],[$1])[[ ]]*:' dnl
+ "$ax_spec_file" | sed -e 's/.*:[[ ]]*//' dnl
+ -e 's/[[ ]][[ ]]*/ /g' -e 's/^ //' -e 's/ $[]//' -e 'q'`
+ if test ".$[]$1" = "." ; then
+ for $1 in $2 $1 m4_tolower([$1]) ; do
+ $1=`echo "$[]$1" | sed -e 's/^%//g'`
+ $1=`sed dnl
+ -e "/^%[[ ]]*def[]ine[[ ]][[ ]]*$[]$1[[ ]]/!d" dnl
+ -e "s/^%[[ ]]*def[]ine[[ ]][[ ]]*$[]$1[[ ]]*//" dnl
+ -e 's/[[ ]][[ ]]*/ /' -e 's/ $[]//' -e 'q' $ax_spec_file`
+ test ".$1" != "." && break
+ done
+ fi
+ case ".$[]$1" in
+ .%{*)
+ $1=`echo "$[]$1" | sed -e 's/%{//' -e 's/}$[]//'`
+ $1=`sed dnl
+ -e "/^%[[ ]]*def[]ine[[ ]][[ ]]*$[]$1[[ ]]/!d" dnl
+ -e "s/^%[[ ]]*def[]ine[[ ]][[ ]]*$[]$1[[ ]]*//" dnl
+ -e 's/[[ ]][[ ]]*/ /' -e 's/ $[]//' -e 'q' $ax_spec_file` ;;
+ .%*)
+ $1=`echo "$[]$1" | sed -e 's/%//'`
+ $1=`sed dnl
+ -e "/^%[[ ]]*def[]ine[[ ]][[ ]]*$[]$1[[ ]]/!d" dnl
+ -e "s/^%[[ ]]*def[]ine[[ ]][[ ]]*$[]$1[[ ]]*//" dnl
+ -e 's/[[ ]][[ ]]*/ /' -e 's/ $[]//' -e 'q' $ax_spec_file` ;;
+ esac
+ m4_ifval([$3],[test ".$[]$1" = "." && $1="$3"])
+ fi # test ".$[]$1" = "."
+])
diff --git a/Build/source/libs/zziplib/m4/ax_spec_package_version.m4 b/Build/source/libs/zziplib/m4/ax_spec_package_version.m4
new file mode 100644
index 00000000000..39766d96091
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ax_spec_package_version.m4
@@ -0,0 +1,227 @@
+dnl @synopsis AX_SPEC_PACKAGE_AND_VERSION ([specfile])
+dnl @synopsis AX_SPEC_PACKAGE_NAME ([shellvar],[defaultvalue])
+dnl @synopsis AX_SPEC_PACKAGE_VERSION ([shellvar],[defaultvalue])
+dnl @synopsis AX_SPEC_PACKAGE_SUMMARY ([shellvar],[defaultvalue])
+dnl @synopsis AX_SPEC_PACKAGE_LICENSE ([shellvar],[defaultvalue])
+dnl @synopsis AX_SPEC_PACKAGE_CATEGORY ([shellvar],[defaultvalue])
+dnl @synopsis AX_SPEC_PACKAGE_ICON ([shellvar],[defaultvalue])
+dnl @synopsis AX_SPEC_DEFAULTS([specfile])
+dnl
+dnl set PACKAGE from the given specfile - default to basename of the
+dnl rpmspecfile if no "name:" could be found in the spec file.
+dnl
+dnl set VERSION from the given specfile - default to a date-derived
+dnl value if no "version:" could be found in the spec file.
+dnl
+dnl this macro builds on top of AX_SPEC_FILE / AX_SPEC_EXTRACT
+dnl
+dnl more specific: if not "name:" or "%define name" was found in the
+dnl myproject.spec file then the PACKAGE var is set to the basename
+dnl "myproject". When no spec file was present then it will usually
+dnl default to "TODO".
+dnl
+dnl The version spec looks for "version:" or "%define version" in the
+dnl spec file. When no such value was seen or no spec file had been
+dnl present then the value is set to `date +0.%y.%W%w`.
+dnl
+dnl the version value itself is sanitized somewhat with making it to
+dnl always carry atleast three digits (1.2.3) and clensing superflous
+dnl "0" chars around from generating numbers elsewhere.
+dnl
+dnl additional macros are provided that extract a specific value from
+dnl the spec file, among these:
+dnl
+dnl set PACKAGE_SUMMARY from the given specfile - default to package
+dnl and try to detect a type suffix if "summary:" was not in the spec
+dnl file
+dnl
+dnl set PACKAGE_LICENSE from the given specfile - if no "license:" tag
+dnl was given in the spec file then various COPYING files are grepped
+dnl to have a guess and the final fallback will be GNU GPL (or GNU
+dnl LGPL).
+dnl
+dnl set PACKAGE_ICON from the given specfile - if no "icon:" tag was
+dnl given in the spec file then we default to $PACKAGE-icon.png
+dnl
+dnl the final AX_SPEC_INIT(specfile) will initialize all variables to
+dnl its defaults according to the spec file given.
+dnl
+dnl @category Misc
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2005-01-21
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_SPEC_PACKAGE_LICENSE],[AC_REQUIRE([AX_SPEC_FILE])dnl
+ AS_VAR_PUSHDEF([VAR],[PACKAGE_LICENSE])dnl
+ AC_MSG_CHECKING([for spec license type])
+ if test ".$VAR" = "." ; then if test ! -f $ax_spec_file
+ then k="(w/o spec)"
+ else k=""
+ AX_SPEC_EXTRACT(VAR,[license],m4_ifval($1,$1))
+ VAR=`echo $VAR | sed -e 's/ *License//g'`
+ fi fi
+ test ".$VAR" = "." && k="(fallback)"
+ ifelse($2,,[dnl here the defaults for LICENSE / COPYRIGHT
+ if test ".$VAR" = "." ; then
+ for ac_file in "$srcdir/COPYING" "$srcdir/COPYING" "$srcdir/LICENSE" ; do
+ test -f "$ac_file" || continue
+dnl http://www.ibiblio.org/osrt/omf/omf_elements "16. Rights"
+ if grep "GNU LESSER GENERAL PUBLIC LICENSE" "$ac_file" >/dev/null
+ then VAR="GNU LGPL" ; break
+ elif grep "GNU GENERAL PUBLIC LICENSE" "$ac_file" >/dev/null
+ then VAR="GNU GPL" ; break
+ elif grep "MOZILLA PUBLIC LICENSE" "$ac_file" >/dev/null
+ then VAR="MPL" ; break
+ elif grep "Mozilla Public License" "$ac_file" >/dev/null
+ then VAR="MPL" ; break
+ elif grep -i "artistic license" "$ac_file" >/dev/null
+ then VAR="Artistic" ; break
+ elif grep -i "artistic control" "$ac_file" >/dev/null
+ then VAR="Artistic" ; break
+ elif grep -i "semblance of artistic" "$ac_file" >/dev/null
+ then VAR="Artistic" ; break
+ elif grep -i "above copyright notice" "$ac_file" >/dev/null
+ then VAR="BSD" ; break
+ fi
+ done
+ if test ".$VAR" = "." ; then
+ if test "$srcdir/COPYING.LIB" ; then VAR="GNU LGPL"
+ elif test ".$ltmain" != "." ; then VAR="GNU LGPL"
+ else VAR="GNU GPL"
+ fi
+ fi
+ fi
+ ],[test ".$VAR" = "." && VAR="$2"])
+ test "$VAR" = "GPL" && VAR="GNU GPL"
+ test "$VAR" = "LGPL" && VAR="GNU LGPL"
+ AC_MSG_RESULT([m4_ifval([$1],[$1 = ])$VAR $k])
+ AS_VAR_POPDEF([VAR])dnl
+])
+
+AC_DEFUN([AX_SPEC_PACKAGE_SUMMARY],[AC_REQUIRE([AX_SPEC_FILE])dnl
+ AS_VAR_PUSHDEF([VAR],[PACKAGE_SUMMARY])dnl
+ AC_MSG_CHECKING([for spec summary])
+ if test ".$VAR" = "." ; then if test ! -f $ax_spec_file
+ then k="(w/o spec)"
+ else k=""
+ AX_SPEC_EXTRACT(VAR,[summary],m4_ifval($1,$1))
+ fi fi
+ test ".$VAR" = "." && k="(fallback)"
+ ifelse($2,,[dnl here the defaults for SUMMARY
+ if test ".$VAR" = "." ; then VAR="$PACKAGE"
+ test ".$VAR" = "." && VAR="foo"
+ test ".$ltmain" != "." && VAR="$VAR library"
+ fi
+ ],[test ".$VAR" = "." && VAR="$2"])
+ AC_MSG_RESULT([m4_ifval([$1],[$1 = ])$VAR $k])
+ AS_VAR_POPDEF([VAR])dnl
+])
+
+AC_DEFUN([AX_SPEC_PACKAGE_ICON],[AC_REQUIRE([AX_SPEC_FILE])dnl
+ AS_VAR_PUSHDEF([VAR],[PACKAGE_ICON])dnl
+ AC_MSG_CHECKING([for spec icon])
+ if test ".$VAR" = "." ; then if test ! -f $ax_spec_file
+ then k="(w/o spec)"
+ else k=""
+ AX_SPEC_EXTRACT(VAR,[icon],m4_ifval($1,$1))
+ fi fi
+ test ".$VAR" = "." && k="(fallback)"
+ ifelse($2,,[dnl here the defaults for ICON
+ if test ".$VAR" = "." ; then VAR="$PACKAGE-icon.png" ; fi
+ ],[test ".$VAR" = "." && VAR="$2"])
+ AC_MSG_RESULT([m4_ifval([$1],[$1 = ])$VAR $k])
+ AS_VAR_POPDEF([VAR])dnl
+])
+
+AC_DEFUN([AX_SPEC_PACKAGE_CATEGORY],[AC_REQUIRE([AX_SPEC_FILE])dnl
+ AS_VAR_PUSHDEF([VAR],[PACKAGE_CATEGORY])dnl
+ AC_MSG_CHECKING([for spec category])
+ if test ".$VAR" = "." ; then if test ! -f $ax_spec_file
+ then k="(w/o spec)"
+ else k=""
+ AX_SPEC_EXTRACT(VAR,[group],m4_ifval($1,$1))
+ VAR=`echo $VAR | sed -e 's/ /-/g'`
+ fi fi
+ test ".$VAR" = "." && k="(fallback)"
+ ifelse($2,,[dnl here the defaults for CATEGORY
+ if test ".$VAR" = "." ; then if test ".$ltmain" != "."
+ then VAR="Development/Library"
+ else VAR="Development/Other"
+ fi fi
+ ],[test ".$VAR" = "." && VAR="$2"])
+ AC_MSG_RESULT([m4_ifval([$1],[$1 = ])$VAR $k])
+ AS_VAR_POPDEF([VAR])dnl
+])
+
+AC_DEFUN([AX_SPEC_PACKAGE_NAME],[AC_REQUIRE([AX_SPEC_FILE])dnl
+ AS_VAR_PUSHDEF([VAR],[PACKAGE_NAME])dnl
+ AC_MSG_CHECKING([for spec package])
+ if test ".$VAR" = "." ; then if test ! -f $ax_spec_file
+ then k="(w/o spec)"
+ else k=""
+ AX_SPEC_EXTRACT(VAR,[name],m4_ifval($1,$1))
+ VAR=`echo $VAR | sed -e 's/ /-/g'`
+ fi fi
+ test ".$VAR" = "." && k="(fallback)"
+ ifelse($2,,[dnl here the defaults for PACKAGE
+ test ".$VAR" = "." && VAR=`basename $ax_spec_file .spec`
+ test ".$VAR" = ".README" && VAR="TODO"
+ test ".$VAR" = ".TODO" && VAR="foo"
+ ],[test ".$VAR" = "." && VAR="$2"])
+ test "VAR" = "PACKAGE_NAME" && test ".$PACKAGE" = "." && PACKAGE="$VAR"
+ AC_MSG_RESULT([m4_ifval([$1],[$1 = ])$VAR $k])
+ AS_VAR_POPDEF([VAR])dnl
+])
+
+AC_DEFUN([AX_SPEC_PACKAGE_VERSION_],[AC_REQUIRE([AX_SPEC_FILE])dnl
+ AS_VAR_PUSHDEF([VAR],[PACKAGE_VERSION])dnl
+ AC_MSG_CHECKING([for spec version])
+ if test ".$VAR" = "." ; then if test ! -f $ax_spec_file
+ then k="(w/o spec)"
+ else k=""
+ AX_SPEC_EXTRACT(VAR,[version],m4_ifval($1,$1))
+ VAR=`echo $VAR | sed -e 's/ /-/g'`
+ fi fi
+ test ".$VAR" = "." && k="(fallback)"
+ ifelse($2,,[dnl here the defaults for VERSION
+ test ".$VAR" = "." && VAR=`date +0.%y.%W%w`
+ ],[test ".$VAR" = "." && VAR="$2"])
+ test "VAR" = "PACKAGE_VERSION" && test ".$VERSION" = "." && VERSION="$VAR"
+ case "$VAR" in # note we set traditional VERSION before cleaning things up
+ *.*.) VAR="$VAR"`date +%W%w` ;;
+ *.*.*) ;;
+ *.) VAR="$VAR"`date +%y.%W%w` ;;
+ *.*) VAR="$VAR.0" ;;
+ *) VAR=AS_TR_SH([$VAR]) ; VAR="$VAR.`date +%y.%W%w`" ;;
+ esac
+ VAR=`echo $VAR | sed -e "s/[[.]][0]\\([0-9]\\)/.\\1/g"`
+ AC_MSG_RESULT([m4_ifval([$1],[$1 = ])$VAR $k])
+ AS_VAR_POPDEF([VAR])dnl
+])
+
+dnl for compatibility, we define ax_spec_package_version
+dnl to do all of ax_spec_package_name as well.
+AC_DEFUN([AX_SPEC_PACKAGE_VERSION],[AC_REQUIRE([AX_SPEC_FILE])dnl
+ ifelse($1,,
+ AC_MSG_WARN([please use ax_spec_package_AND_version now!]),
+ AC_MSG_ERROR([please use ax_spec_package_AND_version now!]))
+ AX_SPEC_PACKAGE_NAME
+ AX_SPEC_PACKAGE_VERSION_
+
+])
+
+AC_DEFUN([AX_SPEC_PACKAGE_AND_VERSION],[
+ m4_ifset([m4_ax_spec_file],,[AX_SPEC_FILE($1)])
+ AX_SPEC_PACKAGE_NAME
+ AX_SPEC_PACKAGE_VERSION_
+])
+
+AC_DEFUN([AX_SPEC_DEFAULTS],[
+ m4_ifset([m4_ax_spec_file],,[AX_SPEC_FILE($1)])
+ AX_SPEC_PACKAGE_NAME
+ AX_SPEC_PACKAGE_VERSION_
+ AX_SPEC_PACKAGE_LICENSE
+ AX_SPEC_PACKAGE_SUMMARY
+ AX_SPEC_PACKAGE_CATEGORY
+ AX_SPEC_PACKAGE_ICON
+])
diff --git a/Build/source/libs/zziplib/m4/ax_warning_default_aclocaldir.m4 b/Build/source/libs/zziplib/m4/ax_warning_default_aclocaldir.m4
new file mode 100644
index 00000000000..c53576fd83f
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ax_warning_default_aclocaldir.m4
@@ -0,0 +1,113 @@
+dnl @synopsis AX_WARNING_DEFAULT_ACLOCALDIR [(dirvariable [,[defsetting][,[A][,[N/A]]]])]
+dnl @synopsis AX_ENABLE_DEFAULT_ACLOCALDIR [(dirvariable [,defsetting])]
+dnl
+dnl print a warning message if the $(datadir)/aclocal directory is not
+dnl in the dirlist searched by the aclocal tool. This macro is useful
+dnl if some `make install` would target $(datadir)/aclocal to install
+dnl an autoconf m4 file of your project to be picked up by other
+dnl projects.
+dnl
+dnl default $1 dirvariable = aclocaldir
+dnl default $2 defsetting = ${datadir}/aclocal
+dnl default $3 action = nothing to do
+dnl default $4 action = warn the user about mismatch
+dnl
+dnl In the _WARNING_ variant, the defsetting is not placed in
+dnl dirvariable nor is it ac_subst'ed in any way. The default
+dnl fail-action $4 is to send a warning message to the user, and the
+dnl default accept-action $3 is nothing. It is expected that a Makefile
+dnl is generated with aclocaldir=${datadir}/aclocal
+dnl
+dnl The _ENABLE_ variant however will set not only the $aclocaldir
+dnl shell var of the script, but it is also AC-SUBST'ed on default -
+dnl and furthermore a configure option "--enable-default-aclocaldir" is
+dnl provided. Only if that option is set then $2 default is not set to
+dnl the canonic default in the a $prefix subpath but instead $2 default
+dnl is set to the primary path where `aclocal` looks for macros. The
+dnl user may also override the default on the command line.
+dnl
+dnl @category Misc
+dnl @category Automake
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2005-01-21
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_WARNING_DEFAULT_ACLOCALDIR],[dnl
+AC_REQUIRE([AX_EXPAND_PREFIX])dnl
+AS_VAR_PUSHDEF([DIR],[ax_warning_default_aclocal_dir])dnl
+AS_VAR_PUSHDEF([BIN],[ax_warning_default_aclocal_bin])dnl
+AS_VAR_PUSHDEF([LOC],[ax_warning_default_aclocal_loc])dnl
+LOC='m4_if([$2],,[${datadir}/aclocal],[$2])'
+m4_ifval([$1],[test ".$[]$1" != "." && LOC="$[]$1"])
+ if test ".$ACLOCAL" = "." ; then
+ AC_PATH_PROG([ACLOCAL],[aclocal],[:])
+ fi
+ BIN="$ACLOCAL"
+ test ".$BIN" = "." && BIN="aclocal"
+ DIR=`test ".$SHELL" = "." && SHELL="'sh'" ; eval "$BIN --print-ac-dir"`
+ test ".$DIR" = "." && test -d "/usr/share/aclocal" && DIR="/usr/share/aclocal"
+ test ".$DIR" = "." && DIR="/tmp"
+DIR=`eval "echo $DIR"` # we need to expand
+DIR=`eval "echo $DIR"`
+LOC=`eval "echo $LOC"`
+LOC=`eval "echo $LOC"`
+LOC=`eval "echo $LOC"`
+LOC=`eval "echo $LOC"`
+AC_RUN_LOG([: test "$LOC" = "$DIR"])
+if test "$LOC" != "$DIR" ; then
+ if test -f "$DIR/dirlist" ; then
+ for DIR in `cat $DIR/dirlist` $DIR ; do
+ AC_RUN_LOG([: test "$LOC" = "$DIR"])
+ test "$LOC" = "$DIR" && break
+ done
+ fi
+ if test "$LOC" != "$DIR" ; then
+ m4_ifval([$4],[$4],[dnl
+ AC_MSG_NOTICE([warning: m4_if([$1],,[aclocaldir],[$1])=$LOC dnl
+(see config.log)])
+ AC_MSG_NOTICE([perhaps: make install m4_if([$1],,[aclocaldir],[$1])=$DIR])
+ cat m4_ifset([AS_MESSAGE_LOG_FD],[>&AS_MESSAGE_LOG_FD],[>>config.log]) <<EOF
+ aclocaldir: the m4_if([$1],,[default aclocaldir],[$1 value]) of $LOC
+ aclocaldir: is not listed in the dirlist where aclocal will look
+ aclocaldir: for macros - you can override the install-path using
+ aclocaldir: make install aclocaldir=$DIR
+ aclocaldir: or append the directory to aclocal reconfigures later as
+ aclocaldir: aclocal -I $LOC
+ aclocaldir: when an autoconf macro is needed from that directory
+EOF
+ m4_ifvaln([$5],[$5])])dnl
+ m4_ifvaln([$3],[else $3])dnl
+ fi
+fi
+AS_VAR_POPDEF([LOC])dnl
+AS_VAR_POPDEF([BIN])dnl
+AS_VAR_POPDEF([DIR])dnl
+])
+
+AC_DEFUN([AX_ENABLE_DEFAULT_ACLOCALDIR],[dnl
+AS_VAR_PUSHDEF([BIN],[ax_warning_default_aclocal_bin])dnl
+AS_VAR_PUSHDEF([DIR],[ax_warning_default_aclocal_def])dnl
+AS_VAR_PUSHDEF([DEF],[ax_warning_default_aclocal_def])dnl
+AC_ARG_ENABLE([enable-default-aclocaldir],
+[ --enable-default-aclocaldir(=PATH) override the datadir/aclocal default])
+test ".$enable_default_aclocaldir" = "." && enable_default_aclocaldir="no"
+case ".$enable_default_aclocaldir" in
+ .no) DIR='m4_if([$2],,[${datadir}/aclocal],[$2])' ;;
+ .yes) # autodetect
+ if test ".$ACLOCAL" = "." ; then
+ AC_PATH_PROG([ACLOCAL],[aclocal],[:])
+ fi
+ BIN="$ACLOCAL"
+ test ".$BIN" = "." && BIN="aclocal"
+ DIR=`test ".$SHELL" = "." && SHELL="'sh'" ; eval "$BIN --print-ac-dir"`
+ test ".$DIR" = "." && test -d "/usr/share/aclocal" && DIR="/usr/share/aclocal"
+ test ".$DIR" = "." && DIR="/tmp" ;;
+ *) DIR="$enable_default_aclocaldir" ;;
+esac
+AX_WARNING_DEFAULT_ACLOCALDIR([$1],[$DEF],[$3],[$4],[$5])
+m4_if([$1],,[aclocaldir],[$1])="$ax_warning_default_aclocal_dir"
+AC_SUBST(m4_if([$1],,[aclocaldir],[$1]))
+AS_VAR_POPDEF([DEF])dnl
+AS_VAR_POPDEF([DIR])dnl
+AS_VAR_POPDEF([BIN])dnl
+])
diff --git a/Build/source/libs/zziplib/m4/ax_warning_default_pkgconfig.m4 b/Build/source/libs/zziplib/m4/ax_warning_default_pkgconfig.m4
new file mode 100644
index 00000000000..557588e0c17
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/ax_warning_default_pkgconfig.m4
@@ -0,0 +1,127 @@
+dnl @synopsis AX_WARNING_DEFAULT_PKGCONFIGDIR [(dirvariable [,[defsetting][,[A][,[N/A]]]])]
+dnl @synopsis AX_ENABLE_DEFAULT_PKGCONFIGDIR [(dirvariable [,defsetting])]
+dnl
+dnl print a warning message if the $(datadir)/aclocal directory is not
+dnl in the dirlist searched by the aclocal tool. This macro is useful
+dnl if some `make install` would target $(datadir)/aclocal to install
+dnl an autoconf m4 file of your project to be picked up by other
+dnl projects.
+dnl
+dnl default $1 dirvariable = pkgconfigdir
+dnl default $2 defsetting = ${libdir}/pkgconfig
+dnl default $3 action = nothing to do
+dnl default $4 action = warn the user about mismatch
+dnl
+dnl In the _WARNING_ variant, the defsetting is not placed in
+dnl dirvariable nor is it ac_subst'ed in any way. The default
+dnl fail-action $4 is to send a warning message to the user, and the
+dnl default accept-action $3 is nothing. It is expected that a Makefile
+dnl is generated with pkgconfigdir=${libdir}/pkgconfig
+dnl
+dnl The _ENABLE_ variant however will set not only the $pkgconfigdir
+dnl shell var of the script, but it is also AC-SUBST'ed on default -
+dnl and furthermore a configure option "--enable-default-pkgconfigdir"
+dnl is provided. Only if that option is set then $2 default is not set
+dnl to the canonic default in the a $prefix subpath but instead $2
+dnl default is set to the primary path where `pkg-config` looks for .pc
+dnl files. The user may also override the default on the command line.
+dnl
+dnl @category Misc
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2005-01-21
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_WARNING_DEFAULT_PKGCONFIGDIR],[dnl
+AC_REQUIRE([AX_EXPAND_PREFIX])dnl
+AS_VAR_PUSHDEF([DIR],[ax_warning_default_pkgconfig_dir])dnl
+AS_VAR_PUSHDEF([BIN],[ax_warning_default_pkgconfig_bin])dnl
+AS_VAR_PUSHDEF([LOC],[ax_warning_default_pkgconfig_loc])dnl
+LOC='m4_if([$2],,[${libdir}/pkgconfig],[$2])'
+m4_ifval([$1],[test ".$[]$1" != "." && LOC="$[]$1"])
+ if test ".$PKG_CONFIG" = "." ; then # we use the same default as in pkg.m4
+ AC_PATH_PROG([PKG_CONFIG],[pkg-config],[no])
+ fi
+ if test "$PKG_CONFIG" = "no"
+ then DIR="/" ; test -d "/usr/lib/pkgconfig" && DIR="/usr/lib/pkgconfig"
+ else BIN=`AS_DIRNAME(["$DIR"])` ;
+ if test -d "$BIN/lib/pkgconfig" ; then
+ DIR="$BIN/lib/pkgconfig"
+ else BIN=`AS_DIRNAME(["$DIR"])`
+ if test -d "$BIN/lib/pkgconfig" ; then
+ DIR="$BIN/lib/pkgconfig"
+ else
+ if test -d "/usr/lib/pkgconfig" ; then
+ DIR="/usr/lib/pkgconfig"
+ else
+ DIR="/"
+ fi fi fi
+ fi
+AC_RUN_LOG([: last pkgconfig dir is assumed as "$DIR"])
+DIR=`eval "echo $DIR"`
+DIR=`eval "echo $DIR"`
+LOC=`eval "echo $LOC"`
+LOC=`eval "echo $LOC"`
+LOC=`eval "echo $LOC"`
+LOC=`eval "echo $LOC"`
+for DIR in `echo "$PKG_CONFIG_PATH:$DIR" | sed -e 's,:, ,g'` ; do
+ AC_RUN_LOG([: test ".$LOC" = ".$DIR"])
+ test ".$LOC" = ".$DIR" && break
+done
+if test "$LOC" != "$DIR" ; then
+ m4_ifval([$4],[$4],[dnl
+ AC_MSG_NOTICE([warning: m4_if([$1],,[pkgconfigdir],[$1])=$LOC dnl
+(see config.log)])
+ AC_MSG_NOTICE([perhaps: make install m4_if([$1],,[pkgconfigdir],[$1])=$DIR])
+ cat m4_ifset([AS_MESSAGE_LOG_FD],[>&AS_MESSAGE_LOG_FD],[>>config.log]) <<EOF
+ pkgconfigdir: the m4_if([$1],,[default pkgconfigdir],[$1 value]) of $LOC
+ pkgconfigdir: is not listed in the dirlist where pkg-config will look for
+ pkgconfigdir: package-configs - you can override the install-path using
+ pkgconfigdir: make install m4_if([$1],,[pkgconfigdir],[$1])=$DIR
+ pkgconfigdir: or set/append the directory to the environment variable
+ pkgconfigdir: PKG_CONFIG_PATH="$LOC"
+EOF
+ m4_ifvaln([$5],[$5])])dnl
+ m4_ifvaln([$3],[else $3])dnl
+fi
+AS_VAR_POPDEF([LOC])dnl
+AS_VAR_POPDEF([BIN])dnl
+AS_VAR_POPDEF([DIR])dnl
+])
+
+AC_DEFUN([AX_ENABLE_DEFAULT_PKGCONFIGDIR],[dnl
+AS_VAR_PUSHDEF([BIN],[ax_warning_default_pkgconfig_bin])dnl
+AS_VAR_PUSHDEF([DIR],[ax_warning_default_pkgconfig_def])dnl
+AS_VAR_PUSHDEF([DEF],[ax_warning_default_pkgconfig_def])dnl
+AC_ARG_ENABLE([enable-default-pkgconfigdir],
+[ --enable-default-pkgconfigdir(=PATH) override the libdir/pkgconfig default])
+test ".$enable_default_pkgconfigdir" = "." && enable_default_pkgconfigdir="no"
+case ".$enable_default_pkgconfigdir" in
+ .no) DIR='m4_if([$2],,[${libdir}/pkgconfig],[$2])' ;;
+ .yes) # autodetect
+ if test ".$PKG_CONFIG" = "." ; then # we use the same default as in pkg.m4
+ AC_PATH_PROG([PKG_CONFIG],[pkg-config],[no])
+ fi
+ if test "$PKG_CONFIG" = "no"
+ then DIR="/tmp" ; test -d "/usr/lib/pkgconfig" && DIR="/usr/lib/pkgconfig"
+ else BIN=`AS_DIRNAME(["$DIR"])` ;
+ if test -d "$BIN/lib/pkgconfig" ; then
+ DIR="$BIN/lib/pkgconfig"
+ else BIN=`AS_DIRNAME(["$DIR"])`
+ if test -d "$BIN/lib/pkgconfig" ; then
+ DIR="$BIN/lib/pkgconfig"
+ else
+ if test -d "/usr/lib/pkgconfig" ; then
+ DIR="/usr/lib/pkgconfig"
+ else
+ DIR="/tmp"
+ fi fi fi
+ fi ;;
+ *) DIR="$enable_default_pkgconfigdir" ;;
+esac
+AX_WARNING_DEFAULT_PKGCONFIGDIR([$1],[$DEF],[$3],[$4],[$5])
+m4_if([$1],,[pkgconfigdir],[$1])="$ax_warning_default_pkgconfig_dir"
+AC_SUBST(m4_if([$1],,[pkgconfigdir],[$1]))
+AS_VAR_POPDEF([DEF])dnl
+AS_VAR_POPDEF([DIR])dnl
+AS_VAR_POPDEF([BIN])dnl
+])
diff --git a/Build/source/libs/zziplib/m4/patch_libtool_on_darwin_zsh_overquoting.m4 b/Build/source/libs/zziplib/m4/patch_libtool_on_darwin_zsh_overquoting.m4
new file mode 100644
index 00000000000..99100148e0f
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/patch_libtool_on_darwin_zsh_overquoting.m4
@@ -0,0 +1,36 @@
+dnl @synopsis PATCH_LIBTOOL_ON_DARWIN_ZSH_OVERQUOTING
+dnl
+dnl libtool 1.4.x has a bug on darwin where the "zsh" is installed as
+dnl the bourne shell replacement. Of course, the zsh is called in a
+dnl compatibility mode but there is a common problem with it, probably
+dnl a bug of zsh. Newer darwin systems have a "bash" installed now, but
+dnl the configure-default will be "zsh" in most systems still.
+dnl
+dnl The bug revelas itself as an overquoted statement in the libtool
+dnl cmds-spec for sharedlib creation on testing for "module" builds.
+dnl Later libtool has gone rid of it by simply removing the quotes at
+dnl that point . Here we maintain the original style and simply remove
+dnl the extra escape character, i.e. we look for "archive_cmds" and
+dnl replace a sequence of triple-backslash-and-doublequote with
+dnl single-backslash-and-doublequote.
+dnl
+dnl @category Misc
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2003-03-23
+dnl @license GPLWithACException
+
+AC_DEFUN([PATCH_LIBTOOL_ON_DARWIN_ZSH_OVERQUOTING],
+[# libtool-1.4 specific, on zsh target the final requoting does one too much
+case "$host_os" in
+ darwin*)
+ if grep "1.92" libtool >/dev/null ; then
+AC_MSG_RESULT(patching libtool on .so-sharedlib creation (zsh overquoting))
+ test -f libtool.old || (mv libtool libtool.old && cp libtool.old libtool)
+ sed -e '/archive_cmds=/s:[[\\]][[\\]][[\\]]*":\\":g' libtool >libtool.new
+ (test -s libtool.new || rm libtool.new) 2>/dev/null
+ test -f libtool.new && mv libtool.new libtool # not 2>/dev/null !!
+ test -f libtool || mv libtool.old libtool
+ fi
+ ;;
+esac
+])
diff --git a/Build/source/libs/zziplib/m4/patch_libtool_sys_lib_search_path_spec.m4 b/Build/source/libs/zziplib/m4/patch_libtool_sys_lib_search_path_spec.m4
new file mode 100644
index 00000000000..1310373291c
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/patch_libtool_sys_lib_search_path_spec.m4
@@ -0,0 +1,37 @@
+dnl @synopsis PATCH_LIBTOOL_SYS_LIB_SEARCH_PATH_SPEC
+dnl
+dnl Cross-compiling to win32 from a unix system reveals a bug - the
+dnl path-separator has been set to ";" depending on the target system.
+dnl However, the crossgcc search_path_spec works in a unix-environment
+dnl with unix-style directories and unix-stylish path_separator. The
+dnl result: the search_path_spec is a single word still containing the
+dnl ":" separators.
+dnl
+dnl This macro fixes the situation: when we see the libtool PATH_SEP to
+dnl be ":" and search_path_spec to contain ":" characters, then these
+dnl are replaced with spaces to let the resulting string work as a
+dnl for-loop argument in libtool scripts that resolve -no-undefined
+dnl libraries.
+dnl
+dnl Later libtool generations have fixed the situation with using
+dnl $PATH_SEPARATOR in the first place as the original path delimiter
+dnl that will be scanned for and replaced into spaces.
+dnl
+dnl @category Misc
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2005-01-21
+dnl @license GPLWithACException
+
+AC_DEFUN([PATCH_LIBTOOL_SYS_LIB_SEARCH_PATH_SPEC],
+[# patch libtool to fix sys_lib_search_path (e.g. crosscompiling a win32 dll)
+if test "_$PATH_SEPARATOR" = "_:" ; then
+ if grep "^sys_lib_search_path_spec.*:" libtool >/dev/null ; then
+AC_MSG_RESULT(patching libtool to fix sys_lib_search_path_spec)
+ test -f libtool.old || (mv libtool libtool.old && cp libtool.old libtool)
+ sed -e "/^sys_lib_search_path_spec/s/:/ /g" libtool >libtool.new
+ (test -s libtool.new || rm libtool.new) 2>/dev/null
+ test -f libtool.new && mv libtool.new libtool # not 2>/dev/null !!
+ test -f libtool || mv libtool.old libtool
+ fi
+fi
+])
diff --git a/Build/source/libs/zziplib/m4/patch_libtool_to_add_host_cc.m4 b/Build/source/libs/zziplib/m4/patch_libtool_to_add_host_cc.m4
new file mode 100644
index 00000000000..22b45ca8396
--- /dev/null
+++ b/Build/source/libs/zziplib/m4/patch_libtool_to_add_host_cc.m4
@@ -0,0 +1,64 @@
+dnl @synopsis PATCH_LIBTOOL_TO_ADD_HOST_CC
+dnl
+dnl The libtool 1.4.x processing (and patched 1.3.5) uses a little
+dnl "impgen" tool to turn a "*.dll" into an import "*.lib" as it is
+dnl needed for win32 targets. However, this little tool is not shipped
+dnl by binutils, it is not even a command option of dlltool or dllwrap.
+dnl It happens to be a C source snippet implanted into the libtool
+dnl sources - it gets written to ".libs", compiled into a binary
+dnl on-the-fly, and executed right away on the "dll" file to create the
+dnl import-lib (dll.a files in gcc-speak).
+dnl
+dnl This mode works fine for a native build within mingw or cygwin, but
+dnl it does not work in cross-compile mode since CC is a crosscompiler
+dnl - it will create an .exe file on a non-win32 system, and as a
+dnl result an impgen.exe is created on-the-fly that can not be executed
+dnl on-the-fly. Luckily, the actual libtool snippet uses HOST_CC to
+dnl compile the sources which has a fallback to CC when the HOST_CC
+dnl variable was not set.
+dnl
+dnl this ac-macro is trying to detect a valid HOST_CC which is not a
+dnl cross-compiler. This is done by looking into the $PATH for a "cc"
+dnl and the result is patched into libtool a HOST_CC, iow it adds
+dnl another configured variable at the top of the libtool script.
+dnl
+dnl In discussions on the libtool mailinglist it occurred that later
+dnl gcc/binutils generations are able to link with dlls directly, i.e.
+dnl there is no import-lib needed anymore. The import-table is created
+dnl within the linker itself (in-memory) and bound to the .exe/.dll
+dnl currently in the making. The whole stuff of impgen exe and
+dnl compiling it on-the-fly, well, it is superflouos then.
+dnl
+dnl Since mingw crosscompilers tend to be quite a fresh development it
+dnl was agreed to remove the impgen stuff completly from libtool
+dnl sources. Still however, this macro does not hurt since it does not
+dnl patch impgen cmds but it just adds HOST_CC which might be useful in
+dnl other cross-compiling cases as well. Therefore, you can leave it in
+dnl for maximum compatibility and portability.
+dnl
+dnl @category Misc
+dnl @category C
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @version 2005-01-21
+dnl @license GPLWithACException
+
+AC_DEFUN([PATCH_LIBTOOL_TO_ADD_HOST_CC],
+[# patch libtool to add HOST_CC sometimes needed in crosscompiling a win32 dll
+if grep "HOST_CC" libtool >/dev/null; then
+ if test "$build" != "$host" ; then
+ if test "_$HOST_CC" = "_" ; then
+ HOST_CC="false"
+ for i in `echo $PATH | sed 's,:, ,g'` ; do
+ test -x $i/cc && HOST_CC=$i/cc
+ done
+ fi
+AC_MSG_RESULT(patching libtool to add HOST_CC=$HOST_CC)
+ test -f libtool.old || (mv libtool libtool.old && cp libtool.old libtool)
+ sed -e "/BEGIN.*LIBTOOL.*CONFIG/a\\
+HOST_CC=$HOST_CC" libtool >libtool.new
+ (test -s libtool.new || rm libtool.new) 2>/dev/null
+ test -f libtool.new && mv libtool.new libtool # not 2>/dev/null !!
+ test -f libtool || mv libtool.old libtool
+ fi
+fi
+])
diff --git a/Build/source/libs/zziplib/msvc6/zzcat.dsp b/Build/source/libs/zziplib/msvc6/zzcat.dsp
new file mode 100644
index 00000000000..861c81b5d44
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc6/zzcat.dsp
@@ -0,0 +1,98 @@
+# Microsoft Developer Studio Project File - Name="zzcat" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=zzcat - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "zzcat.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "zzcat.mak" CFG="zzcat - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "zzcat - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "zzcat - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "zzcat - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release/zzcat"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x41d /d "NDEBUG"
+# ADD RSC /l 0x41d /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib zzip-1.lib libz.lib /nologo /version:10 /subsystem:console /machine:I386 /libpath:"d:\lib" /libpath:"Release"
+
+!ELSEIF "$(CFG)" == "zzcat - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug/zzcat"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x41d /d "_DEBUG"
+# ADD RSC /l 0x41d /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib zziplib.lib libz.lib /nologo /version:10 /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"d:\lib" /libpath:"Debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "zzcat - Win32 Release"
+# Name "zzcat - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "c;cpp"
+# Begin Source File
+
+SOURCE=..\bins\zzcat.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h"
+# End Group
+# End Target
+# End Project
diff --git a/Build/source/libs/zziplib/msvc6/zzdir.dsp b/Build/source/libs/zziplib/msvc6/zzdir.dsp
new file mode 100644
index 00000000000..37431dc6c84
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc6/zzdir.dsp
@@ -0,0 +1,98 @@
+# Microsoft Developer Studio Project File - Name="zzdir" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=zzdir - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "zzdir.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "zzdir.mak" CFG="zzdir - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "zzdir - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "zzdir - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "zzdir - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release/zzdir"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x41d /d "NDEBUG"
+# ADD RSC /l 0x41d /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib zzip-1.lib libz.lib /nologo /version:10 /subsystem:console /machine:I386 /libpath:"d:\lib" /libpath:"Release"
+
+!ELSEIF "$(CFG)" == "zzdir - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug/zzdir"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x41d /d "_DEBUG"
+# ADD RSC /l 0x41d /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib zziplib.lib libz.lib /nologo /version:10 /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"d:\lib" /libpath:"Debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "zzdir - Win32 Release"
+# Name "zzdir - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "c;cpp"
+# Begin Source File
+
+SOURCE=..\bins\zzdir.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h"
+# End Group
+# End Target
+# End Project
diff --git a/Build/source/libs/zziplib/msvc6/zzip.dsp b/Build/source/libs/zziplib/msvc6/zzip.dsp
new file mode 100644
index 00000000000..09ce2566a14
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc6/zzip.dsp
@@ -0,0 +1,183 @@
+# Microsoft Developer Studio Project File - Name="zzip" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=zzip - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "zzip.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "zzip.mak" CFG="zzip - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "zzip - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "zzip - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "zzip - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release/zzip"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZZIP_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I ".." /I "d:\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZZIP_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib libz.lib /nologo /version:10 /dll /machine:I386 /out:"Release/zzip-1.dll" /libpath:"d:\lib"
+
+!ELSEIF "$(CFG)" == "zzip - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug/zzip"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZZIP_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".." /I "D:\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZZIP_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x407 /d "_DEBUG"
+# ADD RSC /l 0x407 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib libz.lib /nologo /version:10 /dll /debug /machine:I386 /out:"Debug/zzip-1.dll" /pdbtype:sept /libpath:"d:\lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "zzip - Win32 Release"
+# Name "zzip - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\zzip\dir.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\err.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\file.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\info.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\plugin.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\stat.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\write.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\zip.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\zzip\__dirent.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\__mmap.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\_msvc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\conf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\file.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\format.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\lib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\plugin.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\stdint.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\zzip.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=..\docs\README.MSVC6
+# End Source File
+# End Target
+# End Project
diff --git a/Build/source/libs/zziplib/msvc6/zziplib.dsp b/Build/source/libs/zziplib/msvc6/zziplib.dsp
new file mode 100644
index 00000000000..ac5b7eab754
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc6/zziplib.dsp
@@ -0,0 +1,172 @@
+# Microsoft Developer Studio Project File - Name="zziplib" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=zziplib - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "zziplib.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "zziplib.mak" CFG="zziplib - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "zziplib - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "zziplib - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "zziplib - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release/zziplib"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I ".." /I "d:\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x41d /d "NDEBUG"
+# ADD RSC /l 0x41d /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "zziplib - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug/zziplib"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /I "d:\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x41d /d "_DEBUG"
+# ADD RSC /l 0x41d /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "zziplib - Win32 Release"
+# Name "zziplib - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "c;cpp"
+# Begin Source File
+
+SOURCE="..\zzip\dir.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zzip\err.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zzip\file.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zzip\info.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zzip\plugin.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zzip\stat.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zzip\write.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zzip\zip.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h"
+# Begin Source File
+
+SOURCE="..\zzip\__dirent.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zzip\__mmap.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zzip\_config.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zzip\_msvc.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zzip\conf.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zzip\file.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\format.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\lib.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\zzip\plugin.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\zzip\stdint.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\zzip\zzip.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\docs\README.MSVC6
+# End Source File
+# End Target
+# End Project
diff --git a/Build/source/libs/zziplib/msvc6/zziplib.dsw b/Build/source/libs/zziplib/msvc6/zziplib.dsw
new file mode 100644
index 00000000000..5c7e1766bca
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc6/zziplib.dsw
@@ -0,0 +1,116 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "zzcat"=".\zzcat.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name zziplib
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "zzdir"=".\zzdir.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name zziplib
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "zzip"=".\zzip.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "zziplib"=".\zziplib.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "zziptest"=".\zziptest.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name zziplib
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "zzipwrap"=".\zzipwrap.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name zziplib
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "zzobfuscated"=".\zzobfuscated.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name zziplib
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/Build/source/libs/zziplib/msvc6/zziptest.dsp b/Build/source/libs/zziplib/msvc6/zziptest.dsp
new file mode 100644
index 00000000000..605265be925
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc6/zziptest.dsp
@@ -0,0 +1,98 @@
+# Microsoft Developer Studio Project File - Name="zziptest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=zziptest - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "zziptest.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "zziptest.mak" CFG="zziptest - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "zziptest - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "zziptest - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "zziptest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release/zziptest"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x41d /d "NDEBUG"
+# ADD RSC /l 0x41d /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib zzip-1.lib libz.lib /nologo /version:10 /subsystem:console /machine:I386 /libpath:"d:\lib" /libpath:"Release"
+
+!ELSEIF "$(CFG)" == "zziptest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug/zziptest"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x41d /d "_DEBUG"
+# ADD RSC /l 0x41d /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib zziplib.lib libz.lib /nologo /version:10 /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"d:\lib" /libpath:"Debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "zziptest - Win32 Release"
+# Name "zziptest - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "c;cpp"
+# Begin Source File
+
+SOURCE=..\bins\zziptest.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h"
+# End Group
+# End Target
+# End Project
diff --git a/Build/source/libs/zziplib/msvc6/zzipwrap.dsp b/Build/source/libs/zziplib/msvc6/zzipwrap.dsp
new file mode 100644
index 00000000000..4f6a328aac8
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc6/zzipwrap.dsp
@@ -0,0 +1,106 @@
+# Microsoft Developer Studio Project File - Name="zzipwrap" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=zzipwrap - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "zzipwrap.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "zzipwrap.mak" CFG="zzipwrap - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "zzipwrap - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "zzipwrap - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "zzipwrap - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release/zzipwrap"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x41d /d "NDEBUG"
+# ADD RSC /l 0x41d /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib zzip-1.lib libz.lib /nologo /version:10 /subsystem:console /machine:I386 /libpath:"d:\lib" /libpath:"Release"
+
+!ELSEIF "$(CFG)" == "zzipwrap - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug/zzipwrap"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x41d /d "_DEBUG"
+# ADD RSC /l 0x41d /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib zziplib.lib libz.lib /nologo /version:10 /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"d:\lib" /libpath:"Debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "zzipwrap - Win32 Release"
+# Name "zzipwrap - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "c;cpp"
+# Begin Source File
+
+SOURCE=..\zzipwrap\wrap.c
+# End Source File
+# Begin Source File
+
+SOURCE="..\zzipwrap\zzipwrap.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h"
+# Begin Source File
+
+SOURCE=..\zzipwrap\wrap.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/Build/source/libs/zziplib/msvc6/zzobfuscated.dsp b/Build/source/libs/zziplib/msvc6/zzobfuscated.dsp
new file mode 100644
index 00000000000..566365cf4ac
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc6/zzobfuscated.dsp
@@ -0,0 +1,98 @@
+# Microsoft Developer Studio Project File - Name="zzobfuscated" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=zzobfuscated - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "zzobfuscated.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "zzobfuscated.mak" CFG="zzobfuscated - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "zzobfuscated - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "zzobfuscated - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "zzobfuscated - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release/zzobfuscated"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x41d /d "NDEBUG"
+# ADD RSC /l 0x41d /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib zzip-1.lib libz.lib /nologo /version:10 /subsystem:console /machine:I386 /libpath:"d:\lib" /libpath:"Release"
+
+!ELSEIF "$(CFG)" == "zzobfuscated - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug/zzobfuscated"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x41d /d "_DEBUG"
+# ADD RSC /l 0x41d /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib zziplib.lib libz.lib /nologo /version:10 /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"d:\lib" /libpath:"Debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "zzobfuscated - Win32 Release"
+# Name "zzobfuscated - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "c;cpp"
+# Begin Source File
+
+SOURCE=..\bins\zzobfuscated.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h"
+# End Group
+# End Target
+# End Project
diff --git a/Build/source/libs/zziplib/msvc7/test.zip b/Build/source/libs/zziplib/msvc7/test.zip
new file mode 100644
index 00000000000..ce4770015f4
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/test.zip
Binary files differ
diff --git a/Build/source/libs/zziplib/msvc7/test1.zip b/Build/source/libs/zziplib/msvc7/test1.zip
new file mode 100644
index 00000000000..c46015d9431
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/test1.zip
Binary files differ
diff --git a/Build/source/libs/zziplib/msvc7/zzcat.sln b/Build/source/libs/zziplib/msvc7/zzcat.sln
new file mode 100644
index 00000000000..1dca79c0131
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zzcat.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziptest", "zziptest.vcproj", "{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ ConfigName.0 = Debug
+ ConfigName.1 = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.ActiveCfg = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.Build.0 = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.ActiveCfg = Release|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc7/zzcat.vcproj b/Build/source/libs/zziplib/msvc7/zzcat.vcproj
new file mode 100644
index 00000000000..a9d4809e91e
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zzcat.vcproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="zziptest"
+ ProjectGUID="{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zziptest-$(ConfigurationName).exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/zziptest.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zziptest-$(ConfigurationName).exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+ >
+ <File
+ RelativePath="..\bins\zziptest.c"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="zziplib.sln"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/msvc7/zzdir.sln b/Build/source/libs/zziplib/msvc7/zzdir.sln
new file mode 100644
index 00000000000..1dca79c0131
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zzdir.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziptest", "zziptest.vcproj", "{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ ConfigName.0 = Debug
+ ConfigName.1 = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.ActiveCfg = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.Build.0 = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.ActiveCfg = Release|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc7/zzdir.vcproj b/Build/source/libs/zziplib/msvc7/zzdir.vcproj
new file mode 100644
index 00000000000..a6c40e2a8fa
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zzdir.vcproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="zzdir"
+ ProjectGUID="{C118D86C-06E2-4949-B4F1-DB05C823C8E1}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzdir-$(ConfigurationName).exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/zziptest.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzdir-$(ConfigurationName).exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+ >
+ <File
+ RelativePath="..\bins\zzdir.c"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="zziplib.sln"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/msvc7/zzip.sln b/Build/source/libs/zziplib/msvc7/zzip.sln
new file mode 100644
index 00000000000..74c2b124420
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zzip.sln
@@ -0,0 +1,69 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual C++ Express 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziptest", "zzcat.vcproj", "{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD} = {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zzcat", "zzipself.vcproj", "{0FBB8EFD-652C-4BD6-B165-6C65357FEDFC}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD} = {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zzipsetstub", "zzipsetstub.vcproj", "{D15BE737-CF23-4243-A8C4-DB5EE3F5689D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD} = {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zzdir", "zzdir.vcproj", "{C118D86C-06E2-4949-B4F1-DB05C823C8E1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD} = {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziplib", "zziplib.vcproj", "{CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zzipself", "zziptest.vcproj", "{8D0233CC-F821-4853-BE2A-B55B680A49E9}"
+ ProjectSection(ProjectDependencies) = postProject
+ {D15BE737-CF23-4243-A8C4-DB5EE3F5689D} = {D15BE737-CF23-4243-A8C4-DB5EE3F5689D}
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD} = {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zzipobfuscated", "zzobfuscated.vcproj", "{3EC53ADE-2D87-4023-B34A-BA1CF0EA0F01}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD} = {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug|Win32.Build.0 = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release|Win32.ActiveCfg = Release|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release|Win32.Build.0 = Release|Win32
+ {0FBB8EFD-652C-4BD6-B165-6C65357FEDFC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0FBB8EFD-652C-4BD6-B165-6C65357FEDFC}.Release|Win32.ActiveCfg = Release|Win32
+ {0FBB8EFD-652C-4BD6-B165-6C65357FEDFC}.Release|Win32.Build.0 = Release|Win32
+ {D15BE737-CF23-4243-A8C4-DB5EE3F5689D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D15BE737-CF23-4243-A8C4-DB5EE3F5689D}.Release|Win32.ActiveCfg = Release|Win32
+ {D15BE737-CF23-4243-A8C4-DB5EE3F5689D}.Release|Win32.Build.0 = Release|Win32
+ {C118D86C-06E2-4949-B4F1-DB05C823C8E1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C118D86C-06E2-4949-B4F1-DB05C823C8E1}.Release|Win32.ActiveCfg = Release|Win32
+ {C118D86C-06E2-4949-B4F1-DB05C823C8E1}.Release|Win32.Build.0 = Release|Win32
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Debug|Win32.Build.0 = Debug|Win32
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Release|Win32.ActiveCfg = Release|Win32
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Release|Win32.Build.0 = Release|Win32
+ {8D0233CC-F821-4853-BE2A-B55B680A49E9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {8D0233CC-F821-4853-BE2A-B55B680A49E9}.Release|Win32.ActiveCfg = Release|Win32
+ {8D0233CC-F821-4853-BE2A-B55B680A49E9}.Release|Win32.Build.0 = Release|Win32
+ {3EC53ADE-2D87-4023-B34A-BA1CF0EA0F01}.Debug|Win32.ActiveCfg = Debug|Win32
+ {3EC53ADE-2D87-4023-B34A-BA1CF0EA0F01}.Release|Win32.ActiveCfg = Release|Win32
+ {3EC53ADE-2D87-4023-B34A-BA1CF0EA0F01}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc7/zzip.vcproj b/Build/source/libs/zziplib/msvc7/zzip.vcproj
new file mode 100644
index 00000000000..77c4646d077
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zzip.vcproj
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding = "Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.00"
+ Name="zzip"
+ ProjectGUID="{CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="lib/zziplibd.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories="C:\lib\zziplib"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="TRUE"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="lib/zziplib.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
+ <File
+ RelativePath="..\zzip\dir.c">
+ </File>
+ <File
+ RelativePath="..\zzip\err.c">
+ </File>
+ <File
+ RelativePath="..\zzip\file.c">
+ </File>
+ <File
+ RelativePath="..\zzip\info.c">
+ </File>
+ <File
+ RelativePath="..\zzip\plugin.c">
+ </File>
+ <File
+ RelativePath="..\zzip\stat.c">
+ </File>
+ <File
+ RelativePath="..\zzip\zip.c">
+ </File>
+ </Filter>
+ <Filter
+ Name="Headerdateien"
+ Filter="h;hpp;hxx;hm;inl;inc">
+ <File
+ RelativePath="..\zzip\__debug.h">
+ </File>
+ <File
+ RelativePath="..\zzip\__dirent.h">
+ </File>
+ <File
+ RelativePath="..\zzip\__hints.h">
+ </File>
+ <File
+ RelativePath="..\zzip\__mmap.h">
+ </File>
+ <File
+ RelativePath="..\zzip\_config.h">
+ </File>
+ <File
+ RelativePath="..\zzip\_msvc.h">
+ </File>
+ <File
+ RelativePath="..\zzip\conf.h">
+ </File>
+ <File
+ RelativePath="..\zzip\file.h">
+ </File>
+ <File
+ RelativePath="..\zzip\format.h">
+ </File>
+ <File
+ RelativePath="..\zzip\lib.h">
+ </File>
+ <File
+ RelativePath="..\zzip\plugin.h">
+ </File>
+ <File
+ RelativePath="..\zzip\stdint.h">
+ </File>
+ <File
+ RelativePath="..\zzip\zzip.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Ressourcendateien"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ </Filter>
+ <File
+ RelativePath="ReadMe.txt">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/msvc7/zziplib.sln b/Build/source/libs/zziplib/msvc7/zziplib.sln
new file mode 100644
index 00000000000..087e0bb3dc3
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zziplib.sln
@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual C++ Express 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziplib", "zziplib.vcproj", "{CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Debug|Win32.Build.0 = Debug|Win32
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Release|Win32.ActiveCfg = Release|Win32
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc7/zziplib.vcproj b/Build/source/libs/zziplib/msvc7/zziplib.vcproj
new file mode 100644
index 00000000000..6c5f71c06c5
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zziplib.vcproj
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="zziplib"
+ ProjectGUID="{CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../zlib/include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories="C:\lib\zziplib"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="zdll.lib"
+ OutputFile="zziplib-$(ConfigurationName).lib"
+ AdditionalLibraryDirectories="../zlib/lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..;../zlib/include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="zdll.lib"
+ OutputFile="zziplib-$(ConfigurationName).lib"
+ AdditionalLibraryDirectories="../zlib/lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+ >
+ <File
+ RelativePath="..\zzip\dir.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\err.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\file.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\info.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\plugin.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\stat.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\zip.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Headerdateien"
+ Filter="h;hpp;hxx;hm;inl;inc"
+ >
+ <File
+ RelativePath="..\zzip\__debug.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\__dirent.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\__hints.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\__mmap.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\_config.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\_msvc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\conf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\file.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\format.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\lib.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\plugin.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\stdint.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\zzip.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Ressourcendateien"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ </Filter>
+ <File
+ RelativePath="ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/msvc7/zzipself.bat b/Build/source/libs/zziplib/msvc7/zzipself.bat
new file mode 100755
index 00000000000..b0bc8688def
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zzipself.bat
@@ -0,0 +1,18 @@
+@echo off
+rem DOS pkzip.exe does not work under WinXP !
+rem instead using infozip zip.exe
+
+IF EXIST zzipselftest%1.zip del zzipselftest%1.zip
+echo zip -0 zzipselftest%1.zip zzipself%1.exe
+ zip -0 zzipselftest%1.zip zzipself%1.exe
+echo zip -9 zzipselftest%1.zip zzipself.txt
+ zip -9 zzipselftest%1.zip zzipself.txt
+echo zzipsetstub%1.exe zzipselftest%1.zip zzipself%1.exe
+ zzipsetstub%1.exe zzipselftest%1.zip zzipself%1.exe
+echo rename zzipselftest%1.zip zzipselftest%1.exe
+IF EXIST zzipselftest%1.exe del zzipselftest%1.exe
+ ren zzipselftest%1.zip zzipselftest%1.exe
+
+REM testrun:
+echo now testing zzipselftest%1.exe
+zzipselftest%1.exe zzipself.txt
diff --git a/Build/source/libs/zziplib/msvc7/zzipself.sln b/Build/source/libs/zziplib/msvc7/zzipself.sln
new file mode 100644
index 00000000000..1dca79c0131
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zzipself.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziptest", "zziptest.vcproj", "{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ ConfigName.0 = Debug
+ ConfigName.1 = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.ActiveCfg = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.Build.0 = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.ActiveCfg = Release|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc7/zzipself.txt b/Build/source/libs/zziplib/msvc7/zzipself.txt
new file mode 100644
index 00000000000..f423a018e29
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zzipself.txt
@@ -0,0 +1,9 @@
+HOWTO create an exe-file with an appended zip-resource - file
+
+we assume an imaginary game called "tetris.exe"
+1. create a zip-archive "tetris.zip" and store "tetris.exe" with NO COMPRESSION (-e0 option in pkzip)
+2. add your data-files, images and sounds to "tetris.zip" with arbitrary compression
+3. call "setstub tetris.zip tetris.exe"
+4. rename tetris.zip into tetris.exe
+
+now your app should be able read data from itself. \ No newline at end of file
diff --git a/Build/source/libs/zziplib/msvc7/zzipself.vcproj b/Build/source/libs/zziplib/msvc7/zzipself.vcproj
new file mode 100644
index 00000000000..a2ecfa151c4
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zzipself.vcproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="zzcat"
+ ProjectGUID="{0FBB8EFD-652C-4BD6-B165-6C65357FEDFC}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzcat-$(ConfigurationName).exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/zziptest.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzcat-$(ConfigurationName).exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+ >
+ <File
+ RelativePath="..\bins\zzcat.c"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="zziplib.sln"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/msvc7/zzipsetstub.sln b/Build/source/libs/zziplib/msvc7/zzipsetstub.sln
new file mode 100644
index 00000000000..fb070235225
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zzipsetstub.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zzipsetstub", "zzipsetstub.vcproj", "{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ ConfigName.0 = Debug
+ ConfigName.1 = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.ActiveCfg = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.Build.0 = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.ActiveCfg = Release|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc7/zzipsetstub.vcproj b/Build/source/libs/zziplib/msvc7/zzipsetstub.vcproj
new file mode 100644
index 00000000000..a2d58135ca2
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zzipsetstub.vcproj
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="zzipsetstub"
+ ProjectGUID="{D15BE737-CF23-4243-A8C4-DB5EE3F5689D}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzipsetstub-$(ConfigurationName).exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/zzipsetstub.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzipsetstub-$(ConfigurationName).exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+ >
+ <File
+ RelativePath="..\test\zzipsetstub.c"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="zziplib.sln"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/msvc7/zziptest.sln b/Build/source/libs/zziplib/msvc7/zziptest.sln
new file mode 100644
index 00000000000..1dca79c0131
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zziptest.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziptest", "zziptest.vcproj", "{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ ConfigName.0 = Debug
+ ConfigName.1 = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.ActiveCfg = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.Build.0 = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.ActiveCfg = Release|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc7/zziptest.vcproj b/Build/source/libs/zziplib/msvc7/zziptest.vcproj
new file mode 100644
index 00000000000..b34253efbda
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zziptest.vcproj
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="zzipself"
+ ProjectGUID="{8D0233CC-F821-4853-BE2A-B55B680A49E9}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzipself-$(ConfigurationName).exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/zziptest.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="zzipself.bat -$(ConfigurationName)"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzipself-$(ConfigurationName).exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="zzipself.bat -$(ConfigurationName)"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+ >
+ <File
+ RelativePath="..\test\zzipself.c"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="zziplib.sln"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/msvc7/zzobfuscated.sln b/Build/source/libs/zziplib/msvc7/zzobfuscated.sln
new file mode 100644
index 00000000000..1dca79c0131
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zzobfuscated.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziptest", "zziptest.vcproj", "{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ ConfigName.0 = Debug
+ ConfigName.1 = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.ActiveCfg = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.Build.0 = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.ActiveCfg = Release|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc7/zzobfuscated.vcproj b/Build/source/libs/zziplib/msvc7/zzobfuscated.vcproj
new file mode 100644
index 00000000000..e2de1c1008b
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc7/zzobfuscated.vcproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="zzipobfuscated"
+ ProjectGUID="{3EC53ADE-2D87-4023-B34A-BA1CF0EA0F01}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzipobfuscated-$(ConfigurationName).exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/zziptest.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzipobfuscated-$(ConfigurationName).exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+ >
+ <File
+ RelativePath="..\bins\zzobfuscated.c"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="zziplib.sln"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/msvc8/README.TXT b/Build/source/libs/zziplib/msvc8/README.TXT
new file mode 100644
index 00000000000..dbbd5febabf
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/README.TXT
@@ -0,0 +1,31 @@
+These project files were tested with the
+free Microsoft Visual C++ 2005 Express Edition.
+
+Visual C++ Express does NOT include the Win32 SDK Headers.
+They must be downloaded separately as documented in the
+installation instructions at Microsoft - consequently that
+extra installation must be referenced via a system variable:
+Set MSSdk=C:\Program Files\Microsoft Platform SDK
+
+In order to compile you need a valid Zlib SDK - you can
+download it from zlib.org in the archive zlib123-dll.zip -
+I had unpacked them to $(zziplibdir)/zlib inside the
+toplevel of the zziplib source tree. That SDK does ship
+with a "zlib1.dll" runtime and "zdll.lib" import library.
+
+The new Visual Studio has depracated most of the Win32 API
+just as well as most of the Posix API. That provokes a lot
+of warning message in surplus of the many warning message
+that occur on every implicit conversion between signed and
+unsigned types. Other compilers are more clever about
+detecting real conversion issues, therefore they are not
+going to be "patched away" with an explicit conversion in
+the source files (I expect Microsoft to get it right somewhen).
+
+== Download Places ==
+download.microsoft.com/download/a/5/f/a5f0d781-e201-4ab6-8c6a-9bb4efed1e1a/
+PSDK-x86.exe = Win32 SDK - online installer
+download.microsoft.com/download/A/9/1/A91D6B2B-A798-47DF-9C7E-A97854B7DD18/
+VC.iso = Visual C++ Express CD-image
+download.microsoft.com/download/C/6/F/C6F4733B-67C7-4C15-9F21-61F7A3167505/
+VCS.iso = Visual C# Express CD-image
diff --git a/Build/source/libs/zziplib/msvc8/test.zip b/Build/source/libs/zziplib/msvc8/test.zip
new file mode 100644
index 00000000000..ce4770015f4
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/test.zip
Binary files differ
diff --git a/Build/source/libs/zziplib/msvc8/test1.zip b/Build/source/libs/zziplib/msvc8/test1.zip
new file mode 100644
index 00000000000..c46015d9431
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/test1.zip
Binary files differ
diff --git a/Build/source/libs/zziplib/msvc8/zzcat.sln b/Build/source/libs/zziplib/msvc8/zzcat.sln
new file mode 100644
index 00000000000..1dca79c0131
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zzcat.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziptest", "zziptest.vcproj", "{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ ConfigName.0 = Debug
+ ConfigName.1 = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.ActiveCfg = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.Build.0 = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.ActiveCfg = Release|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc8/zzcat.vcproj b/Build/source/libs/zziplib/msvc8/zzcat.vcproj
new file mode 100644
index 00000000000..a9d4809e91e
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zzcat.vcproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="zziptest"
+ ProjectGUID="{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zziptest-$(ConfigurationName).exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/zziptest.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zziptest-$(ConfigurationName).exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+ >
+ <File
+ RelativePath="..\bins\zziptest.c"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="zziplib.sln"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/msvc8/zzdir.sln b/Build/source/libs/zziplib/msvc8/zzdir.sln
new file mode 100644
index 00000000000..1dca79c0131
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zzdir.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziptest", "zziptest.vcproj", "{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ ConfigName.0 = Debug
+ ConfigName.1 = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.ActiveCfg = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.Build.0 = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.ActiveCfg = Release|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc8/zzdir.vcproj b/Build/source/libs/zziplib/msvc8/zzdir.vcproj
new file mode 100644
index 00000000000..a6c40e2a8fa
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zzdir.vcproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="zzdir"
+ ProjectGUID="{C118D86C-06E2-4949-B4F1-DB05C823C8E1}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzdir-$(ConfigurationName).exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/zziptest.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzdir-$(ConfigurationName).exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+ >
+ <File
+ RelativePath="..\bins\zzdir.c"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="zziplib.sln"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/msvc8/zzip.sln b/Build/source/libs/zziplib/msvc8/zzip.sln
new file mode 100644
index 00000000000..74c2b124420
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zzip.sln
@@ -0,0 +1,69 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual C++ Express 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziptest", "zzcat.vcproj", "{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD} = {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zzcat", "zzipself.vcproj", "{0FBB8EFD-652C-4BD6-B165-6C65357FEDFC}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD} = {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zzipsetstub", "zzipsetstub.vcproj", "{D15BE737-CF23-4243-A8C4-DB5EE3F5689D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD} = {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zzdir", "zzdir.vcproj", "{C118D86C-06E2-4949-B4F1-DB05C823C8E1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD} = {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziplib", "zziplib.vcproj", "{CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zzipself", "zziptest.vcproj", "{8D0233CC-F821-4853-BE2A-B55B680A49E9}"
+ ProjectSection(ProjectDependencies) = postProject
+ {D15BE737-CF23-4243-A8C4-DB5EE3F5689D} = {D15BE737-CF23-4243-A8C4-DB5EE3F5689D}
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD} = {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zzipobfuscated", "zzobfuscated.vcproj", "{3EC53ADE-2D87-4023-B34A-BA1CF0EA0F01}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD} = {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug|Win32.Build.0 = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release|Win32.ActiveCfg = Release|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release|Win32.Build.0 = Release|Win32
+ {0FBB8EFD-652C-4BD6-B165-6C65357FEDFC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0FBB8EFD-652C-4BD6-B165-6C65357FEDFC}.Release|Win32.ActiveCfg = Release|Win32
+ {0FBB8EFD-652C-4BD6-B165-6C65357FEDFC}.Release|Win32.Build.0 = Release|Win32
+ {D15BE737-CF23-4243-A8C4-DB5EE3F5689D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D15BE737-CF23-4243-A8C4-DB5EE3F5689D}.Release|Win32.ActiveCfg = Release|Win32
+ {D15BE737-CF23-4243-A8C4-DB5EE3F5689D}.Release|Win32.Build.0 = Release|Win32
+ {C118D86C-06E2-4949-B4F1-DB05C823C8E1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C118D86C-06E2-4949-B4F1-DB05C823C8E1}.Release|Win32.ActiveCfg = Release|Win32
+ {C118D86C-06E2-4949-B4F1-DB05C823C8E1}.Release|Win32.Build.0 = Release|Win32
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Debug|Win32.Build.0 = Debug|Win32
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Release|Win32.ActiveCfg = Release|Win32
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Release|Win32.Build.0 = Release|Win32
+ {8D0233CC-F821-4853-BE2A-B55B680A49E9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {8D0233CC-F821-4853-BE2A-B55B680A49E9}.Release|Win32.ActiveCfg = Release|Win32
+ {8D0233CC-F821-4853-BE2A-B55B680A49E9}.Release|Win32.Build.0 = Release|Win32
+ {3EC53ADE-2D87-4023-B34A-BA1CF0EA0F01}.Debug|Win32.ActiveCfg = Debug|Win32
+ {3EC53ADE-2D87-4023-B34A-BA1CF0EA0F01}.Release|Win32.ActiveCfg = Release|Win32
+ {3EC53ADE-2D87-4023-B34A-BA1CF0EA0F01}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc8/zzip.vcproj b/Build/source/libs/zziplib/msvc8/zzip.vcproj
new file mode 100644
index 00000000000..77c4646d077
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zzip.vcproj
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding = "Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.00"
+ Name="zzip"
+ ProjectGUID="{CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="lib/zziplibd.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories="C:\lib\zziplib"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="TRUE"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="lib/zziplib.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
+ <File
+ RelativePath="..\zzip\dir.c">
+ </File>
+ <File
+ RelativePath="..\zzip\err.c">
+ </File>
+ <File
+ RelativePath="..\zzip\file.c">
+ </File>
+ <File
+ RelativePath="..\zzip\info.c">
+ </File>
+ <File
+ RelativePath="..\zzip\plugin.c">
+ </File>
+ <File
+ RelativePath="..\zzip\stat.c">
+ </File>
+ <File
+ RelativePath="..\zzip\zip.c">
+ </File>
+ </Filter>
+ <Filter
+ Name="Headerdateien"
+ Filter="h;hpp;hxx;hm;inl;inc">
+ <File
+ RelativePath="..\zzip\__debug.h">
+ </File>
+ <File
+ RelativePath="..\zzip\__dirent.h">
+ </File>
+ <File
+ RelativePath="..\zzip\__hints.h">
+ </File>
+ <File
+ RelativePath="..\zzip\__mmap.h">
+ </File>
+ <File
+ RelativePath="..\zzip\_config.h">
+ </File>
+ <File
+ RelativePath="..\zzip\_msvc.h">
+ </File>
+ <File
+ RelativePath="..\zzip\conf.h">
+ </File>
+ <File
+ RelativePath="..\zzip\file.h">
+ </File>
+ <File
+ RelativePath="..\zzip\format.h">
+ </File>
+ <File
+ RelativePath="..\zzip\lib.h">
+ </File>
+ <File
+ RelativePath="..\zzip\plugin.h">
+ </File>
+ <File
+ RelativePath="..\zzip\stdint.h">
+ </File>
+ <File
+ RelativePath="..\zzip\zzip.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Ressourcendateien"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ </Filter>
+ <File
+ RelativePath="ReadMe.txt">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/msvc8/zziplib.sln b/Build/source/libs/zziplib/msvc8/zziplib.sln
new file mode 100644
index 00000000000..087e0bb3dc3
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zziplib.sln
@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual C++ Express 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziplib", "zziplib.vcproj", "{CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Debug|Win32.Build.0 = Debug|Win32
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Release|Win32.ActiveCfg = Release|Win32
+ {CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc8/zziplib.vcproj b/Build/source/libs/zziplib/msvc8/zziplib.vcproj
new file mode 100644
index 00000000000..6c5f71c06c5
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zziplib.vcproj
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="zziplib"
+ ProjectGUID="{CB440073-2ED3-48CE-A1A1-B6EACB3A44BD}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../zlib/include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories="C:\lib\zziplib"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="zdll.lib"
+ OutputFile="zziplib-$(ConfigurationName).lib"
+ AdditionalLibraryDirectories="../zlib/lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..;../zlib/include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="zdll.lib"
+ OutputFile="zziplib-$(ConfigurationName).lib"
+ AdditionalLibraryDirectories="../zlib/lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+ >
+ <File
+ RelativePath="..\zzip\dir.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\err.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\file.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\info.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\plugin.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\stat.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\zip.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Headerdateien"
+ Filter="h;hpp;hxx;hm;inl;inc"
+ >
+ <File
+ RelativePath="..\zzip\__debug.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\__dirent.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\__hints.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\__mmap.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\_config.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\_msvc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\conf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\file.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\format.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\lib.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\plugin.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\stdint.h"
+ >
+ </File>
+ <File
+ RelativePath="..\zzip\zzip.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Ressourcendateien"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ </Filter>
+ <File
+ RelativePath="ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/msvc8/zzipself.bat b/Build/source/libs/zziplib/msvc8/zzipself.bat
new file mode 100755
index 00000000000..b0bc8688def
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zzipself.bat
@@ -0,0 +1,18 @@
+@echo off
+rem DOS pkzip.exe does not work under WinXP !
+rem instead using infozip zip.exe
+
+IF EXIST zzipselftest%1.zip del zzipselftest%1.zip
+echo zip -0 zzipselftest%1.zip zzipself%1.exe
+ zip -0 zzipselftest%1.zip zzipself%1.exe
+echo zip -9 zzipselftest%1.zip zzipself.txt
+ zip -9 zzipselftest%1.zip zzipself.txt
+echo zzipsetstub%1.exe zzipselftest%1.zip zzipself%1.exe
+ zzipsetstub%1.exe zzipselftest%1.zip zzipself%1.exe
+echo rename zzipselftest%1.zip zzipselftest%1.exe
+IF EXIST zzipselftest%1.exe del zzipselftest%1.exe
+ ren zzipselftest%1.zip zzipselftest%1.exe
+
+REM testrun:
+echo now testing zzipselftest%1.exe
+zzipselftest%1.exe zzipself.txt
diff --git a/Build/source/libs/zziplib/msvc8/zzipself.sln b/Build/source/libs/zziplib/msvc8/zzipself.sln
new file mode 100644
index 00000000000..1dca79c0131
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zzipself.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziptest", "zziptest.vcproj", "{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ ConfigName.0 = Debug
+ ConfigName.1 = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.ActiveCfg = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.Build.0 = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.ActiveCfg = Release|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc8/zzipself.txt b/Build/source/libs/zziplib/msvc8/zzipself.txt
new file mode 100644
index 00000000000..f423a018e29
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zzipself.txt
@@ -0,0 +1,9 @@
+HOWTO create an exe-file with an appended zip-resource - file
+
+we assume an imaginary game called "tetris.exe"
+1. create a zip-archive "tetris.zip" and store "tetris.exe" with NO COMPRESSION (-e0 option in pkzip)
+2. add your data-files, images and sounds to "tetris.zip" with arbitrary compression
+3. call "setstub tetris.zip tetris.exe"
+4. rename tetris.zip into tetris.exe
+
+now your app should be able read data from itself. \ No newline at end of file
diff --git a/Build/source/libs/zziplib/msvc8/zzipself.vcproj b/Build/source/libs/zziplib/msvc8/zzipself.vcproj
new file mode 100644
index 00000000000..a2ecfa151c4
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zzipself.vcproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="zzcat"
+ ProjectGUID="{0FBB8EFD-652C-4BD6-B165-6C65357FEDFC}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzcat-$(ConfigurationName).exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/zziptest.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzcat-$(ConfigurationName).exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+ >
+ <File
+ RelativePath="..\bins\zzcat.c"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="zziplib.sln"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/msvc8/zzipsetstub.sln b/Build/source/libs/zziplib/msvc8/zzipsetstub.sln
new file mode 100644
index 00000000000..fb070235225
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zzipsetstub.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zzipsetstub", "zzipsetstub.vcproj", "{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ ConfigName.0 = Debug
+ ConfigName.1 = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.ActiveCfg = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.Build.0 = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.ActiveCfg = Release|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc8/zzipsetstub.vcproj b/Build/source/libs/zziplib/msvc8/zzipsetstub.vcproj
new file mode 100644
index 00000000000..a2d58135ca2
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zzipsetstub.vcproj
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="zzipsetstub"
+ ProjectGUID="{D15BE737-CF23-4243-A8C4-DB5EE3F5689D}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzipsetstub-$(ConfigurationName).exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/zzipsetstub.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzipsetstub-$(ConfigurationName).exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+ >
+ <File
+ RelativePath="..\test\zzipsetstub.c"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="zziplib.sln"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/msvc8/zziptest.sln b/Build/source/libs/zziplib/msvc8/zziptest.sln
new file mode 100644
index 00000000000..1dca79c0131
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zziptest.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziptest", "zziptest.vcproj", "{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ ConfigName.0 = Debug
+ ConfigName.1 = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.ActiveCfg = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.Build.0 = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.ActiveCfg = Release|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc8/zziptest.vcproj b/Build/source/libs/zziplib/msvc8/zziptest.vcproj
new file mode 100644
index 00000000000..b34253efbda
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zziptest.vcproj
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="zzipself"
+ ProjectGUID="{8D0233CC-F821-4853-BE2A-B55B680A49E9}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzipself-$(ConfigurationName).exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/zziptest.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="zzipself.bat -$(ConfigurationName)"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzipself-$(ConfigurationName).exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="zzipself.bat -$(ConfigurationName)"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+ >
+ <File
+ RelativePath="..\test\zzipself.c"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="zziplib.sln"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/msvc8/zzobfuscated.sln b/Build/source/libs/zziplib/msvc8/zzobfuscated.sln
new file mode 100644
index 00000000000..1dca79c0131
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zzobfuscated.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zziptest", "zziptest.vcproj", "{FCEF4E99-72DB-4422-95BB-3C83673B66E9}"
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ ConfigName.0 = Debug
+ ConfigName.1 = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.ActiveCfg = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Debug.Build.0 = Debug|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.ActiveCfg = Release|Win32
+ {FCEF4E99-72DB-4422-95BB-3C83673B66E9}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Build/source/libs/zziplib/msvc8/zzobfuscated.vcproj b/Build/source/libs/zziplib/msvc8/zzobfuscated.vcproj
new file mode 100644
index 00000000000..e2de1c1008b
--- /dev/null
+++ b/Build/source/libs/zziplib/msvc8/zzobfuscated.vcproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="zzipobfuscated"
+ ProjectGUID="{3EC53ADE-2D87-4023-B34A-BA1CF0EA0F01}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzipobfuscated-$(ConfigurationName).exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/zziptest.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..;../zlib/include;&quot;$(MSSdk)/Include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zziplib-$(ConfigurationName).lib"
+ OutputFile="zzipobfuscated-$(ConfigurationName).exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+ >
+ <File
+ RelativePath="..\bins\zzobfuscated.c"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="zziplib.sln"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/zziplib/test/.deps/zzipself.Po b/Build/source/libs/zziplib/test/.deps/zzipself.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/test/.deps/zzipself.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/test/.deps/zzipsetstub.Po b/Build/source/libs/zziplib/test/.deps/zzipsetstub.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/test/.deps/zzipsetstub.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/test/Makefile.am b/Build/source/libs/zziplib/test/Makefile.am
new file mode 100644
index 00000000000..38195247bfc
--- /dev/null
+++ b/Build/source/libs/zziplib/test/Makefile.am
@@ -0,0 +1,263 @@
+AUTOMAKE_OPTIONS = 1.4 foreign
+AUTOTOOL_VERSION=autoconf-2.52 automake-1.5 libtool-1.4.2
+DEFAULT_INCLUDES = # nothing - no default of -I. -I$(srcdir)
+DEFS = @DEFS@ -I$(top_builddir) -I$(top_srcdir) # also for automake 1.4
+
+EXTRA_DIST = test.zip test1.zip
+DISTCLEANFILES = test*.dat test2.zip test3.zip
+
+zzcat = ../bins/zzcat$(EXEEXT)
+zzdir = ../bins/zzdir$(EXEEXT)
+zziptest = ../bins/zziptest$(EXEEXT)
+zzxorcat = ../bins/zzxorcat$(EXEEXT)
+zzxordir = ../bins/zzxordir$(EXEEXT)
+zzxorcopy = ../bins/zzxorcopy$(EXEEXT)
+
+$(zzcat) $(zzdir) $(zziptest) $(zzxorcat) $(zzxordir) $(xorcopy) : \
+ @top_srcdir@/bins/*.c @top_srcdir@/zzip/*.c
+ (cd ../bins && $(MAKE))
+
+# -------------------------------------------------------------------
+NULL=/dev/null
+README = $(top_srcdir)/README
+testdatadir = $(top_srcdir)/testdata.d
+
+testzip testzips : test.zip test1.zip test2.zip test3.zip
+
+test.zip tmp/../test.zip : $(README)
+ - test -d tmp || mkdir tmp
+ - $(MAKE) test0.zip && mv test0.zip $@
+ test -s $@ || cp $(srcdir)/test.zip $@
+test0.zip : $(README)
+ test -f README || ln -s $(README) .
+ - $(MKZIP) test_.zip README
+ @ if test -s test_.zip ;then echo mv test_.zip $@ ; mv test_.zip $@ ;fi
+ @ test -d $(testdatadir) || mkdir $(testdatadir); if test -s $@ \
+ ; then echo cp $@ $(testdatadir)/ ; cp $@ $(testdatadir)/ \
+ ; else echo cp $(testdatadir)/$@ .; cp $(testdatadir)/$@ . \
+ ; fi ; echo test -s $@ ; test -s $@
+
+test1.zip :
+ @ echo $(MKZIP) $@ ... "(10 files)" \
+ ; mkdir test.tmp \
+ ; for i in 1 2 3 4 5 6 8 9 \
+ ; do echo "file-$i" >test.tmp/file.$$i ; done \
+ ; echo " a plain text file here" >test.tmp/README \
+ ; (cd test.tmp && $(MKZIP) ../$@ file.* >$(NULL)) \
+ ; rm -rf test.tmp
+ @ test -d $(testdatadir) || mkdir $(testdatadir); if test -s $@ \
+ ; then echo cp $@ $(testdatadir)/ ; cp $@ $(testdatadir)/ \
+ ; else echo cp $(testdatadir)/$@ .; cp $(testdatadir)/$@ . \
+ ; fi ; echo test -s $@ ; test -s $@
+
+test2.zip : # will not be shipped in source tarball
+ @ echo $(MKZIP) $@ ... "(100 files)" \
+ ; mkdir test.tmp \
+ ; for i in 1 2 3 4 5 6 8 9 ; do for j in 1 2 3 4 5 6 7 8 9 \
+ ; do echo "file-$i" >test.tmp/file.$$j$$i ; done done \
+ ; (cd test.tmp && $(MKZIP) ../$@ file.* >$(NULL)) \
+ ; rm -rf test.tmp
+ @ test -d $(testdatadir) || mkdir $(testdatadir); if test -s $@ \
+ ; then echo cp $@ $(testdatadir)/ ; cp $@ $(testdatadir)/ \
+ ; else echo cp $(testdatadir)/$@ .; cp $(testdatadir)/$@ . \
+ ; fi ; echo test -s $@ ; test -s $@
+
+test3.zip : # will not be shipped in source tarball
+ @ echo $(MKZIP) $@ ... "(1000 files)" \
+ ; mkdir test.tmp ; for h in 1 2 3 4 5 6 7 8 9 ; do : \
+ ; for i in 1 2 3 4 5 6 8 9 ; do for j in 1 2 3 4 5 6 7 8 9 \
+ ; do echo "file-$i" >test.tmp/file.$$h$$j$$i ; done done done \
+ ; (cd test.tmp && $(MKZIP) ../$@ file.* >$(NULL)) \
+ ; rm -rf test.tmp
+ @ test -d $(testdatadir) || mkdir $(testdatadir); if test -s $@ \
+ ; then echo cp $@ $(testdatadir)/ ; cp $@ $(testdatadir)/ \
+ ; else echo cp $(testdatadir)/$@ .; cp $(testdatadir)/$@ . \
+ ; fi ; echo test -s $@ ; test -s $@
+
+test.dat : test.zip
+ $(zzxorcopy) $? $@
+test1.dat : test1.zip
+ $(zzxorcopy) $? $@
+test2.dat : test2.zip
+ $(zzxorcopy) $? $@
+test3.dat : test3.zip
+ $(zzxorcopy) $? $@
+
+# -------------------------------------------------------------------
+
+stdtests = @ZIPTESTS@ check-test0 check-test1 check-zzdir check-zzcat
+xortests = @ZIPTESTS@ check-zzxor check-zzxordir check-zzxorcat
+sfxtests = @ZIPTESTS@ check-sfx
+
+check-local: check-readme $(stdtests) $(xortests) $(sfxtests)
+
+check-readme : $(zzcat) test.zip
+ @ test -f test.zip || $(MAKE) tmp/../test.zip
+ test -s test.zip
+ @ echo :$@: checking $(zzcat) test/README
+ @ $(zzcat) test/README >test.out
+ @ if diff test.out $(README) >$(NULL) \
+ ; then rm test.out ; echo check OK ; true \
+ ; else rm test.out ; echo check FAIL ; false ; fi
+
+check-zzxor : $(zzxorcat) test.dat
+ @ echo :$@: checking $(zzxorcat) test.dat/README
+ @ $(zzxorcat) test.dat/README >test.out
+ @ if diff test.out $(README) >$(NULL) \
+ ; then rm test.out ; echo check OK ; true \
+ ; else rm test.out ; echo check FAIL ; false ; fi
+
+test: test0 test1 test2 test3
+test0: $(zziptest)
+ $(zziptest) test.zip
+test1: $(zziptest)
+ $(zziptest) test1.zip
+test2: $(zzcat)
+ $(zzcat) test/README
+test3: $(zzdir)
+ $(zzdir) test1.zip
+
+check-test0 : $(zziptest)
+ @ echo :$@: quick selftest
+ $(zziptest) test.zip >test.out
+ rm test.out
+check-test1 : $(zziptest)
+ @ test -f test1.zip || ln -s $(srcdir)/test1.zip test1.zip
+ @ echo :$@: longer selftest "(about ten seconds)"
+ $(zziptest) test1.zip >test.out
+ rm test.out
+
+check-zzdir : test1.zip test2.zip test3.zip $(zzdir)
+ @ echo :$@: zip directory access
+ ./$(zzdir) test1 > test.out
+ @ X="$(zzdir) test1 "\
+ ; if grep file.1 test.out >$(NULL) ; then : \
+ ; if grep file.9 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ ./$(zzdir) test2 > test.out
+ @ X="$(zzdir) test2 "\
+ ; if grep file.11 test.out >$(NULL) ; then : \
+ ; if grep file.99 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ ./$(zzdir) test3 > test.out
+ @ X="$(zzdir) test3 "\
+ ; if grep file.111 test.out >$(NULL) ; then : \
+ ; if grep file.999 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ @ X="$(zzdir) test000" ; echo ./$$X "(negative test)" \
+ ; if ./$(zzdir) test000 >test.out ; then : \
+ ; echo ..$$X.. FAIL ; false ; else echo ..$$X.. OK ; true ; fi
+ rm test.out
+
+check-zzcat : test1.zip test2.zip test3.zip $(zzcat)
+ @ echo ___ $@ ___
+ ./$(zzcat) test1/file.1 test1/file.9 > test.out
+ @ X="$(zzcat) test1/file.1 test1/file.9 "\
+ ; if grep file-1 test.out >$(NULL) ; then : \
+ ; if grep file-9 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ ./$(zzcat) test2/file.11 test2/file.99 > test.out
+ @ X="$(zzcat) test2/file.10 test2/file.99 "\
+ ; if grep file-10 test.out >$(NULL) ; then : \
+ ; if grep file-99 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ ./$(zzcat) test3/file.111 test3/file.999 > test.out
+ @ X="$(zzcat) test3/file.111 test3/file.999 "\
+ ; if grep file-100 test.out >$(NULL) ; then : \
+ ; if grep file-999 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ @ X="$(zzcat) test1/file.999" ; echo ./$$X "(negative test)" \
+ ; if ./$(zzdir) test1/file.999 >test.out ; then : \
+ ; echo ..$$X.. FAIL ; false ; else echo ..$$X.. OK ; true ; fi
+ rm test.out
+
+check-zzxordir : test1.dat test2.dat $(zzxordir)
+ @ echo ___ $@ ___
+ ./$(zzxordir) test1 > test.out
+ @ X="$(zzxordir) test1 "\
+ ; if grep file.1 test.out >$(NULL) ; then : \
+ ; if grep file.9 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ ./$(zzxordir) test2.dat > test.out
+ @ X="$(zzxordir) test2.dat "\
+ ; if grep file.11 test.out >$(NULL) ; then : \
+ ; if grep file.99 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ rm test.out
+
+check-zzxorcat : test1.dat test2.dat $(zzxorcat)
+ @ echo ___ $@ ___
+ ./$(zzxorcat) test1/file.1 test1/file.9 > test.out
+ @ X="$(zzxorcat) test1/file.1 test1/file.9 "\
+ ; if grep file-1 test.out >$(NULL) ; then : \
+ ; if grep file-9 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ ./$(zzxorcat) test2.dat/file.11 test2/file.99 > test.out
+ @ X="$(zzxorcat) test2.dat/file.10 test2/file.99 "\
+ ; if grep file-10 test.out >$(NULL) ; then : \
+ ; if grep file-99 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ rm test.out
+
+# -------------------------------------------------------------------
+ECHON = echo -n
+BRUTE = 0 # default is less than a thousand tests
+brute : # which is still a brute force selftest
+ @ echo $(MKZIP) $@: \
+ ; for u in 1 2 3 4 5 6 8 9 ; do for v in 1 2 3 4 5 6 7 8 9 ; do : \
+ ; for w in 1 2 3 4 5 6 8 9 ; do for x in $(BRUTE) ; do : \
+ ; $(ECHON) $$u$$v$$w$$x: \
+ ; rm -rf test.tmp ; mkdir test.tmp \
+ ; for i in 1 2 3 4 5 6 8 9 ; do for j in 1 2 3 4 5 6 7 8 9 ; do : \
+ ; for m in 1 2 3 4 5 6 8 9 ; do for n in $(BRUTE) ; do : \
+ ; echo "file-$$i$$j$$m$$n" >test.tmp/file$$i$$j$$m$$n.txt \
+ ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; test -f test.tmp/file$$i$$j$$m$$n.txt || exit 2 \
+ ; (cd test.tmp && $(MKZIP) ../test$$u$$v$$w$$x.zip file*.* >$(NULL)) \
+ ; rm -rf test.tmp \
+ ; for i in 1 2 3 4 5 6 8 9 ; do for j in 1 2 3 4 5 6 7 8 9 ; do : \
+ ; for m in 1 2 3 4 5 6 8 9 ; do for n in $(BRUTE) ; do : \
+ ; ./$(zzcat) test$$u$$v$$w$$x/file$$i$$j$$m$$n.txt >test.out \
+ ; if grep file-$$i$$j$$m$$n test.out >$(NULL) ; then rm test.out \
+ ; else echo ERROR file-$$i$$j$$m$$n diff in test$$u$$v$$w$$x \
+ ; exit 1 ; fi \
+ ; ./$(zzdir) test$$u$$v$$w$$x >test.out \
+ ; if grep file$$i$$j$$m$$n.txt test.out >$(NULL) ; then rm test.out \
+ ; else echo ERROR file$$i$$j$$m$$n.txt not in test$$u$$v$$w$$x \
+ ; exit 1 ; fi \
+ ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; rm test$$u$$v$$w$$x.zip \
+ ; done ; done ; done ; done ; true
+
+# -------------------------------------------------------------------
+
+noinst_PROGRAMS = zzipself zzipsetstub
+
+zzipself_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzipself_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+
+../zzip/libzzip.la : @top_srcdir@/zzip/*.c
+ (cd ../zzip && $(MAKE) `basename $@`)
+
+zzshowme$(EXEEXT) : zzipself$(EXEEXT) zzipsetstub$(EXEEXT)
+ $(MKZIP) -0 -j $@ .libs/zzipself$(EXEEXT)
+ $(MKZIP) -9 -j $@ $(README)
+ - test -s $@ || cp test2.zip $@
+ test ! -f $@.zip || mv $@.zip $@
+ ./zzipsetstub $@ .libs/zzipself$(EXEEXT)
+ - chmod +x $@
+
+check-sfx : zzshowme$(EXEEXT)
+ echo :$@: "./zzshowme readme >readme.out 2>readme.err"
+ export LD_LIBRARY_PATH="../zzip/.libs:$$LD_LIBRARY_PATH" \
+ ; ./zzshowme readme >readme.out 2>readme.err ; true
+ @ echo 'diff readme.out $(README) || grep "libzzip-" readme.err' \
+ ; if test -s readme.out ; then diff readme.out $(README) \
+ ; else grep "libzzip-" readme.err || echo "readme.out is empty!" ; fi
+ rm readme.out readme.err
diff --git a/Build/source/libs/zziplib/test/Makefile.in b/Build/source/libs/zziplib/test/Makefile.in
new file mode 100644
index 00000000000..996f9dfbbd4
--- /dev/null
+++ b/Build/source/libs/zziplib/test/Makefile.in
@@ -0,0 +1,737 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+noinst_PROGRAMS = zzipself$(EXEEXT) zzipsetstub$(EXEEXT)
+subdir = test
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_compile_check_sizeof.m4 \
+ $(top_srcdir)/m4/ac_set_default_paths_system.m4 \
+ $(top_srcdir)/m4/ac_sys_largefile_sensitive.m4 \
+ $(top_srcdir)/m4/acx_restrict.m4 \
+ $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \
+ $(top_srcdir)/m4/ax_cflags_no_writable_strings.m4 \
+ $(top_srcdir)/m4/ax_cflags_strict_prototypes.m4 \
+ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \
+ $(top_srcdir)/m4/ax_create_pkgconfig_info.m4 \
+ $(top_srcdir)/m4/ax_enable_builddir_uname.m4 \
+ $(top_srcdir)/m4/ax_expand_prefix.m4 \
+ $(top_srcdir)/m4/ax_maintainer_mode_auto_silent.m4 \
+ $(top_srcdir)/m4/ax_not_enable_frame_pointer.m4 \
+ $(top_srcdir)/m4/ax_prefix_config_h.m4 \
+ $(top_srcdir)/m4/ax_set_version_info.m4 \
+ $(top_srcdir)/m4/ax_spec_file.m4 \
+ $(top_srcdir)/m4/ax_spec_package_version.m4 \
+ $(top_srcdir)/m4/ax_warning_default_aclocaldir.m4 \
+ $(top_srcdir)/m4/ax_warning_default_pkgconfig.m4 \
+ $(top_srcdir)/m4/patch_libtool_on_darwin_zsh_overquoting.m4 \
+ $(top_srcdir)/m4/patch_libtool_sys_lib_search_path_spec.m4 \
+ $(top_srcdir)/m4/patch_libtool_to_add_host_cc.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/uses/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+zzipself_SOURCES = zzipself.c
+zzipself_OBJECTS = zzipself.$(OBJEXT)
+zzipself_DEPENDENCIES = ../zzip/libzzip.la
+zzipsetstub_SOURCES = zzipsetstub.c
+zzipsetstub_OBJECTS = zzipsetstub.$(OBJEXT)
+zzipsetstub_LDADD = $(LDADD)
+depcomp = $(SHELL) $(top_srcdir)/uses/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = zzipself.c zzipsetstub.c
+DIST_SOURCES = zzipself.c zzipsetstub.c
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONFIG_FILES = @CONFIG_FILES@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@ -I$(top_builddir) -I$(top_srcdir) # also for automake 1.4
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LARGEFILE_CFLAGS = @LARGEFILE_CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+MKZIP = @MKZIP@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RELEASE_INFO = @RELEASE_INFO@
+RESOLVES = @RESOLVES@
+SDL = @SDL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+THREAD_SAFE = @THREAD_SAFE@
+VERSION = @VERSION@
+VERSION_INFO = @VERSION_INFO@
+XMLTO = @XMLTO@
+ZIPTESTS = @ZIPTESTS@
+ZLIB_INCL = @ZLIB_INCL@
+ZLIB_LDIR = @ZLIB_LDIR@
+ZLIB_VERSION = @ZLIB_VERSION@
+ZZIPLIB_LDFLAGS = @ZZIPLIB_LDFLAGS@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_AS = @ac_ct_AS@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DLLTOOL = @ac_ct_DLLTOOL@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_OBJDUMP = @ac_ct_OBJDUMP@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+aclocaldir = @aclocaldir@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_enable_builddir_sed = @ax_enable_builddir_sed@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+docdir = @docdir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pkgconfig_libdir = @pkgconfig_libdir@
+pkgconfig_libfile = @pkgconfig_libfile@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+AUTOMAKE_OPTIONS = 1.4 foreign
+AUTOTOOL_VERSION = autoconf-2.52 automake-1.5 libtool-1.4.2
+DEFAULT_INCLUDES = # nothing - no default of -I. -I$(srcdir)
+EXTRA_DIST = test.zip test1.zip
+DISTCLEANFILES = test*.dat test2.zip test3.zip
+zzcat = ../bins/zzcat$(EXEEXT)
+zzdir = ../bins/zzdir$(EXEEXT)
+zziptest = ../bins/zziptest$(EXEEXT)
+zzxorcat = ../bins/zzxorcat$(EXEEXT)
+zzxordir = ../bins/zzxordir$(EXEEXT)
+zzxorcopy = ../bins/zzxorcopy$(EXEEXT)
+
+# -------------------------------------------------------------------
+NULL = /dev/null
+README = $(top_srcdir)/README
+testdatadir = $(top_srcdir)/testdata.d
+
+# -------------------------------------------------------------------
+stdtests = @ZIPTESTS@ check-test0 check-test1 check-zzdir check-zzcat
+xortests = @ZIPTESTS@ check-zzxor check-zzxordir check-zzxorcat
+sfxtests = @ZIPTESTS@ check-sfx
+
+# -------------------------------------------------------------------
+ECHON = echo -n
+BRUTE = 0 # default is less than a thousand tests
+zzipself_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzipself_LDADD = ../zzip/libzzip.la @RESOLVES@ -lz
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign test/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+zzipself$(EXEEXT): $(zzipself_OBJECTS) $(zzipself_DEPENDENCIES)
+ @rm -f zzipself$(EXEEXT)
+ $(LINK) $(zzipself_LDFLAGS) $(zzipself_OBJECTS) $(zzipself_LDADD) $(LIBS)
+zzipsetstub$(EXEEXT): $(zzipsetstub_OBJECTS) $(zzipsetstub_DEPENDENCIES)
+ @rm -f zzipsetstub$(EXEEXT)
+ $(LINK) $(zzipsetstub_LDFLAGS) $(zzipsetstub_OBJECTS) $(zzipsetstub_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzipself.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzipsetstub.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am check-local clean \
+ clean-generic clean-libtool clean-noinstPROGRAMS ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-exec install-exec-am install-info \
+ install-info-am install-man install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-info-am
+
+
+$(zzcat) $(zzdir) $(zziptest) $(zzxorcat) $(zzxordir) $(xorcopy) : \
+ @top_srcdir@/bins/*.c @top_srcdir@/zzip/*.c
+ (cd ../bins && $(MAKE))
+
+testzip testzips : test.zip test1.zip test2.zip test3.zip
+
+test.zip tmp/../test.zip : $(README)
+ - test -d tmp || mkdir tmp
+ - $(MAKE) test0.zip && mv test0.zip $@
+ test -s $@ || cp $(srcdir)/test.zip $@
+test0.zip : $(README)
+ test -f README || ln -s $(README) .
+ - $(MKZIP) test_.zip README
+ @ if test -s test_.zip ;then echo mv test_.zip $@ ; mv test_.zip $@ ;fi
+ @ test -d $(testdatadir) || mkdir $(testdatadir); if test -s $@ \
+ ; then echo cp $@ $(testdatadir)/ ; cp $@ $(testdatadir)/ \
+ ; else echo cp $(testdatadir)/$@ .; cp $(testdatadir)/$@ . \
+ ; fi ; echo test -s $@ ; test -s $@
+
+test1.zip :
+ @ echo $(MKZIP) $@ ... "(10 files)" \
+ ; mkdir test.tmp \
+ ; for i in 1 2 3 4 5 6 8 9 \
+ ; do echo "file-$i" >test.tmp/file.$$i ; done \
+ ; echo " a plain text file here" >test.tmp/README \
+ ; (cd test.tmp && $(MKZIP) ../$@ file.* >$(NULL)) \
+ ; rm -rf test.tmp
+ @ test -d $(testdatadir) || mkdir $(testdatadir); if test -s $@ \
+ ; then echo cp $@ $(testdatadir)/ ; cp $@ $(testdatadir)/ \
+ ; else echo cp $(testdatadir)/$@ .; cp $(testdatadir)/$@ . \
+ ; fi ; echo test -s $@ ; test -s $@
+
+test2.zip : # will not be shipped in source tarball
+ @ echo $(MKZIP) $@ ... "(100 files)" \
+ ; mkdir test.tmp \
+ ; for i in 1 2 3 4 5 6 8 9 ; do for j in 1 2 3 4 5 6 7 8 9 \
+ ; do echo "file-$i" >test.tmp/file.$$j$$i ; done done \
+ ; (cd test.tmp && $(MKZIP) ../$@ file.* >$(NULL)) \
+ ; rm -rf test.tmp
+ @ test -d $(testdatadir) || mkdir $(testdatadir); if test -s $@ \
+ ; then echo cp $@ $(testdatadir)/ ; cp $@ $(testdatadir)/ \
+ ; else echo cp $(testdatadir)/$@ .; cp $(testdatadir)/$@ . \
+ ; fi ; echo test -s $@ ; test -s $@
+
+test3.zip : # will not be shipped in source tarball
+ @ echo $(MKZIP) $@ ... "(1000 files)" \
+ ; mkdir test.tmp ; for h in 1 2 3 4 5 6 7 8 9 ; do : \
+ ; for i in 1 2 3 4 5 6 8 9 ; do for j in 1 2 3 4 5 6 7 8 9 \
+ ; do echo "file-$i" >test.tmp/file.$$h$$j$$i ; done done done \
+ ; (cd test.tmp && $(MKZIP) ../$@ file.* >$(NULL)) \
+ ; rm -rf test.tmp
+ @ test -d $(testdatadir) || mkdir $(testdatadir); if test -s $@ \
+ ; then echo cp $@ $(testdatadir)/ ; cp $@ $(testdatadir)/ \
+ ; else echo cp $(testdatadir)/$@ .; cp $(testdatadir)/$@ . \
+ ; fi ; echo test -s $@ ; test -s $@
+
+test.dat : test.zip
+ $(zzxorcopy) $? $@
+test1.dat : test1.zip
+ $(zzxorcopy) $? $@
+test2.dat : test2.zip
+ $(zzxorcopy) $? $@
+test3.dat : test3.zip
+ $(zzxorcopy) $? $@
+
+check-local: check-readme $(stdtests) $(xortests) $(sfxtests)
+
+check-readme : $(zzcat) test.zip
+ @ test -f test.zip || $(MAKE) tmp/../test.zip
+ test -s test.zip
+ @ echo :$@: checking $(zzcat) test/README
+ @ $(zzcat) test/README >test.out
+ @ if diff test.out $(README) >$(NULL) \
+ ; then rm test.out ; echo check OK ; true \
+ ; else rm test.out ; echo check FAIL ; false ; fi
+
+check-zzxor : $(zzxorcat) test.dat
+ @ echo :$@: checking $(zzxorcat) test.dat/README
+ @ $(zzxorcat) test.dat/README >test.out
+ @ if diff test.out $(README) >$(NULL) \
+ ; then rm test.out ; echo check OK ; true \
+ ; else rm test.out ; echo check FAIL ; false ; fi
+
+test: test0 test1 test2 test3
+test0: $(zziptest)
+ $(zziptest) test.zip
+test1: $(zziptest)
+ $(zziptest) test1.zip
+test2: $(zzcat)
+ $(zzcat) test/README
+test3: $(zzdir)
+ $(zzdir) test1.zip
+
+check-test0 : $(zziptest)
+ @ echo :$@: quick selftest
+ $(zziptest) test.zip >test.out
+ rm test.out
+check-test1 : $(zziptest)
+ @ test -f test1.zip || ln -s $(srcdir)/test1.zip test1.zip
+ @ echo :$@: longer selftest "(about ten seconds)"
+ $(zziptest) test1.zip >test.out
+ rm test.out
+
+check-zzdir : test1.zip test2.zip test3.zip $(zzdir)
+ @ echo :$@: zip directory access
+ ./$(zzdir) test1 > test.out
+ @ X="$(zzdir) test1 "\
+ ; if grep file.1 test.out >$(NULL) ; then : \
+ ; if grep file.9 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ ./$(zzdir) test2 > test.out
+ @ X="$(zzdir) test2 "\
+ ; if grep file.11 test.out >$(NULL) ; then : \
+ ; if grep file.99 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ ./$(zzdir) test3 > test.out
+ @ X="$(zzdir) test3 "\
+ ; if grep file.111 test.out >$(NULL) ; then : \
+ ; if grep file.999 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ @ X="$(zzdir) test000" ; echo ./$$X "(negative test)" \
+ ; if ./$(zzdir) test000 >test.out ; then : \
+ ; echo ..$$X.. FAIL ; false ; else echo ..$$X.. OK ; true ; fi
+ rm test.out
+
+check-zzcat : test1.zip test2.zip test3.zip $(zzcat)
+ @ echo ___ $@ ___
+ ./$(zzcat) test1/file.1 test1/file.9 > test.out
+ @ X="$(zzcat) test1/file.1 test1/file.9 "\
+ ; if grep file-1 test.out >$(NULL) ; then : \
+ ; if grep file-9 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ ./$(zzcat) test2/file.11 test2/file.99 > test.out
+ @ X="$(zzcat) test2/file.10 test2/file.99 "\
+ ; if grep file-10 test.out >$(NULL) ; then : \
+ ; if grep file-99 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ ./$(zzcat) test3/file.111 test3/file.999 > test.out
+ @ X="$(zzcat) test3/file.111 test3/file.999 "\
+ ; if grep file-100 test.out >$(NULL) ; then : \
+ ; if grep file-999 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ @ X="$(zzcat) test1/file.999" ; echo ./$$X "(negative test)" \
+ ; if ./$(zzdir) test1/file.999 >test.out ; then : \
+ ; echo ..$$X.. FAIL ; false ; else echo ..$$X.. OK ; true ; fi
+ rm test.out
+
+check-zzxordir : test1.dat test2.dat $(zzxordir)
+ @ echo ___ $@ ___
+ ./$(zzxordir) test1 > test.out
+ @ X="$(zzxordir) test1 "\
+ ; if grep file.1 test.out >$(NULL) ; then : \
+ ; if grep file.9 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ ./$(zzxordir) test2.dat > test.out
+ @ X="$(zzxordir) test2.dat "\
+ ; if grep file.11 test.out >$(NULL) ; then : \
+ ; if grep file.99 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ rm test.out
+
+check-zzxorcat : test1.dat test2.dat $(zzxorcat)
+ @ echo ___ $@ ___
+ ./$(zzxorcat) test1/file.1 test1/file.9 > test.out
+ @ X="$(zzxorcat) test1/file.1 test1/file.9 "\
+ ; if grep file-1 test.out >$(NULL) ; then : \
+ ; if grep file-9 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ ./$(zzxorcat) test2.dat/file.11 test2/file.99 > test.out
+ @ X="$(zzxorcat) test2.dat/file.10 test2/file.99 "\
+ ; if grep file-10 test.out >$(NULL) ; then : \
+ ; if grep file-99 test.out >$(NULL) ; then : \
+ ; echo ..$$X.. OK ; true ; else echo ..$$X.. FAIL ; false ; fi fi
+ rm test.out
+brute : # which is still a brute force selftest
+ @ echo $(MKZIP) $@: \
+ ; for u in 1 2 3 4 5 6 8 9 ; do for v in 1 2 3 4 5 6 7 8 9 ; do : \
+ ; for w in 1 2 3 4 5 6 8 9 ; do for x in $(BRUTE) ; do : \
+ ; $(ECHON) $$u$$v$$w$$x: \
+ ; rm -rf test.tmp ; mkdir test.tmp \
+ ; for i in 1 2 3 4 5 6 8 9 ; do for j in 1 2 3 4 5 6 7 8 9 ; do : \
+ ; for m in 1 2 3 4 5 6 8 9 ; do for n in $(BRUTE) ; do : \
+ ; echo "file-$$i$$j$$m$$n" >test.tmp/file$$i$$j$$m$$n.txt \
+ ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; test -f test.tmp/file$$i$$j$$m$$n.txt || exit 2 \
+ ; (cd test.tmp && $(MKZIP) ../test$$u$$v$$w$$x.zip file*.* >$(NULL)) \
+ ; rm -rf test.tmp \
+ ; for i in 1 2 3 4 5 6 8 9 ; do for j in 1 2 3 4 5 6 7 8 9 ; do : \
+ ; for m in 1 2 3 4 5 6 8 9 ; do for n in $(BRUTE) ; do : \
+ ; ./$(zzcat) test$$u$$v$$w$$x/file$$i$$j$$m$$n.txt >test.out \
+ ; if grep file-$$i$$j$$m$$n test.out >$(NULL) ; then rm test.out \
+ ; else echo ERROR file-$$i$$j$$m$$n diff in test$$u$$v$$w$$x \
+ ; exit 1 ; fi \
+ ; ./$(zzdir) test$$u$$v$$w$$x >test.out \
+ ; if grep file$$i$$j$$m$$n.txt test.out >$(NULL) ; then rm test.out \
+ ; else echo ERROR file$$i$$j$$m$$n.txt not in test$$u$$v$$w$$x \
+ ; exit 1 ; fi \
+ ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; test "$$i$$j$$m$$n" = "$$u$$v$$w$$x" && break \
+ ; done ; rm test$$u$$v$$w$$x.zip \
+ ; done ; done ; done ; done ; true
+
+../zzip/libzzip.la : @top_srcdir@/zzip/*.c
+ (cd ../zzip && $(MAKE) `basename $@`)
+
+zzshowme$(EXEEXT) : zzipself$(EXEEXT) zzipsetstub$(EXEEXT)
+ $(MKZIP) -0 -j $@ .libs/zzipself$(EXEEXT)
+ $(MKZIP) -9 -j $@ $(README)
+ - test -s $@ || cp test2.zip $@
+ test ! -f $@.zip || mv $@.zip $@
+ ./zzipsetstub $@ .libs/zzipself$(EXEEXT)
+ - chmod +x $@
+
+check-sfx : zzshowme$(EXEEXT)
+ echo :$@: "./zzshowme readme >readme.out 2>readme.err"
+ export LD_LIBRARY_PATH="../zzip/.libs:$$LD_LIBRARY_PATH" \
+ ; ./zzshowme readme >readme.out 2>readme.err ; true
+ @ echo 'diff readme.out $(README) || grep "libzzip-" readme.err' \
+ ; if test -s readme.out ; then diff readme.out $(README) \
+ ; else grep "libzzip-" readme.err || echo "readme.out is empty!" ; fi
+ rm readme.out readme.err
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Build/source/libs/zziplib/test/README b/Build/source/libs/zziplib/test/README
new file mode 100644
index 00000000000..5668eda043a
--- /dev/null
+++ b/Build/source/libs/zziplib/test/README
@@ -0,0 +1,47 @@
+PROJECT
+ The zziplib provides read access to zipped files in a zip-archive,
+ using compression based solely on free algorithms provided by zlib.
+ It also provides a functionality to overlay the archive filesystem
+ with the filesystem of the operating system environment.
+
+AUTHOR
+ The project was originally written by Tomi Ollila, later largely
+ rewritten by Guido Draheim, and extended with contributions in
+ the years to follow. Guido Draheim <guidod@gmx.de> holds the full
+ copyright to the zziplib sources.
+
+COPYING
+ The zziplib may be used freely under the restrictions of the
+ GNU Lesser General Public License version 2 or later. Alternativly
+ the Mozilla Public license can be chosen. The sources are under
+ a dual license, as long as the MPL hint is not removed, the modified
+ files will be again under a dual license for the final recipient.
+
+LICENSING
+ If you can not use a dynalinked library according to LGPL rules,
+ then look at docs/copying.htm for a few hints. Generally the LGPL
+ has a way for staticlinking as well as the MPL has a way. Anyway,
+ special (paid) licenses can be negotiated with the copyright holder.
+
+HOMEPAGE
+ The zziplib project is hosted at SourceForge, the complete
+ documentation can be found at http://zziplib.sf.net - the
+ SourceForge servers are also used to distribute the sources
+ of the zziplib project. Releases are announced via the
+ freshmeat services on http://freshmeat.net/projects/zziplib
+
+INSTALLATION
+ The zziplib sources are built with gnu autotools and they should
+ be easy to install on unixish systems via the usual sequence of
+ `configure && make && make check && make install`. Many distributors
+ ship prebuilt packages e.g. in rpm format. Additionally there are
+ MSVC project files shipped along for usage with the Microsoft
+ VisualC series of compilers. There should be no problem either
+ when crosscompiling the zziplib for a third host platform.
+
+MAINTAINANCE
+ The zziplib library is intentionally a lightweight interface to
+ zip files. The author take patches but please consider to put
+ complex extensions into separate modules rather than implanting them
+ right into the core of the library engine. All Patches and Bug Reports
+ should be sent to Guido Draheim <guidod@gmx.de>.
diff --git a/Build/source/libs/zziplib/test/test.zip b/Build/source/libs/zziplib/test/test.zip
new file mode 100644
index 00000000000..8f361c77f3f
--- /dev/null
+++ b/Build/source/libs/zziplib/test/test.zip
Binary files differ
diff --git a/Build/source/libs/zziplib/test/test1.zip b/Build/source/libs/zziplib/test/test1.zip
new file mode 100644
index 00000000000..c46015d9431
--- /dev/null
+++ b/Build/source/libs/zziplib/test/test1.zip
Binary files differ
diff --git a/Build/source/libs/zziplib/test/zzipself.c b/Build/source/libs/zziplib/test/zzipself.c
new file mode 100644
index 00000000000..2cd115e75af
--- /dev/null
+++ b/Build/source/libs/zziplib/test/zzipself.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2000,2001,2002 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB License
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <zzip/zzip.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static const char usage[] =
+{
+ " zzipself <file>... \n"
+ " - prints the file to stdout, so you may want to redirect the output; \n"
+ " the file can be a normal file or an inflated part of a zip-archive, \n"
+ " however in this case the zip-archive happens to be the executed\n"
+ " binary itself, as if this program is a self-extract header of a zip. \n"
+ " zzipself README # same as # zzcat zzipself/README \n"
+};
+
+int
+main (int argc, char ** argv)
+{
+ int status = 0;
+ int argn;
+ if (argc <= 1)
+ {
+ printf (usage);
+ exit (0);
+ }
+
+ for (argn=1; argn < argc; argn++)
+ {
+ /* ZZIP_FILE* fp = zzip_fopen (argv[0]+"/"+argv[argn], "rbi"); */
+ /* .... = zzip_open (argv[0]+"/"+argv[argn], O_RDONLY|O_BINARY,
+ * ZZIP_CASELESS|ZZIP_ONLYZIP, ext, 0); */
+
+ static const char* ext[] = { "", ".exe", ".EXE", 0 };
+ ZZIP_FILE* fp;
+ ZZIP_DIR* zip = zzip_opendir_ext_io (argv[0],
+ ZZIP_CASELESS|ZZIP_ONLYZIP, ext, 0);
+
+ if (! zip) { perror(argv[0]); break; }
+
+ fp = zzip_file_open (zip, argv[argn], ZZIP_CASELESS);
+
+ if (! fp)
+ {
+ perror (argv[argn]);
+ continue;
+ }else{
+ char buf[17];
+ int n;
+
+ /* read chunks of 16 bytes into buf and print them to stdout */
+ while (0 < (n = zzip_read(fp, buf, 16)))
+ {
+ buf[n] = '\0';
+# ifdef STDOUT_FILENO
+ write (STDOUT_FILENO, buf, n);
+# else
+ fwrite (buf, 1, n, stdout);
+# endif
+ }
+
+ if (n == -1)
+ {
+ perror (argv[argn]);
+ status ++;
+ }
+ }
+
+ zzip_file_close (fp);
+ zzip_closedir (zip);
+ }
+
+ return status;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/test/zzipsetstub.c b/Build/source/libs/zziplib/test/zzipsetstub.c
new file mode 100644
index 00000000000..5d5ad0c903b
--- /dev/null
+++ b/Build/source/libs/zziplib/test/zzipsetstub.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+static const char usage[] =
+{
+ "zzipsetstub <zipfile> <zipsfxstub>... \n"
+ " overwrite the header of the zipfile with the sfxstub code.\n"
+ " this is usually the last step in creating a selfextract archive\n"
+ " or an application with all its data appended as a zip.\n"
+};
+
+int
+main (int argc, char ** argv)
+{
+ int argn;
+ if (argc <= 2)
+ {
+ printf (usage);
+ exit (0);
+ }
+
+ {
+ char buf[17]; int n;
+ char* zipfile = 0; FILE* zipFILE = 0;
+ char* sfxfile = 0; FILE* sfxFILE = 0;
+
+ for (argn=1; argn < argc; argn++)
+ {
+ if (argv[argn][0] == '-') continue;
+ if (! zipfile) { zipfile = argv[argn]; continue; }
+ if (! sfxfile) { sfxfile = argv[argn]; continue; }
+ /* superflous argument */
+ }
+
+ zipFILE = fopen (zipfile, "r+b");
+ if (! zipFILE) { perror (zipfile); return 1; }
+
+ sfxFILE = fopen (sfxfile, "rb");
+ if (! sfxFILE) { perror (sfxfile); return 1; }
+
+ while (0 < (n = fread(buf, 1, 16, sfxFILE)))
+ {
+ buf[n] = '\0';
+ fwrite (buf, 1, n, zipFILE);
+ }
+
+ if (n == -1)
+ perror (argv[argn]);
+
+ fclose (sfxFILE);
+ fclose (zipFILE);
+ }
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/uses/config.guess b/Build/source/libs/zziplib/uses/config.guess
new file mode 100755
index 00000000000..910f4ee342a
--- /dev/null
+++ b/Build/source/libs/zziplib/uses/config.guess
@@ -0,0 +1,1473 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-07-08'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case "${UNAME_MACHINE}" in
+ i?86)
+ test -z "$VENDOR" && VENDOR=pc
+ ;;
+ *)
+ test -z "$VENDOR" && VENDOR=unknown
+ ;;
+esac
+test -f /etc/SuSE-release -o -f /.buildenv && VENDOR=suse
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ x86:Interix*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-linux
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-${VENDOR}-linux
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-linux
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-linux
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-linux
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && { echo "${CPU}-${VENDOR}-linux"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && { echo "${CPU}-${VENDOR}-linux"; exit; }
+ ;;
+ ppc:Linux:*:*)
+ echo powerpc-${VENDOR}-linux
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-${VENDOR}-linux
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-${VENDOR}-linux${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-${VENDOR}-linux ;;
+ PA8*) echo hppa2.0-${VENDOR}-linux ;;
+ *) echo hppa-${VENDOR}-linux ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-${VENDOR}-linux
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-linux
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-linux
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-linux
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-${VENDOR}-linux
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-${VENDOR}-linux"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-${VENDOR}-linuxaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-${VENDOR}-linuxcoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linuxoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-${VENDOR}-linuxoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-${VENDOR}-linux-${LIBC}" | sed 's/linux-gnu/linux/'
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ *86) UNAME_PROCESSOR=i686 ;;
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/Build/source/libs/zziplib/uses/config.sub b/Build/source/libs/zziplib/uses/config.sub
new file mode 100755
index 00000000000..6e2bdbf5a4b
--- /dev/null
+++ b/Build/source/libs/zziplib/uses/config.sub
@@ -0,0 +1,1576 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-07-08'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | ms1 \
+ | msp430 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m32c)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | ms1-* \
+ | msp430-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ m32c-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/Build/source/libs/zziplib/uses/depcomp b/Build/source/libs/zziplib/uses/depcomp
new file mode 100755
index 00000000000..02458b8923a
--- /dev/null
+++ b/Build/source/libs/zziplib/uses/depcomp
@@ -0,0 +1,397 @@
+#! /bin/sh
+
+# depcomp - compile a program generating dependencies as side-effects
+# Copyright 1999, 2000 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+ echo "depcomp: Variables source, object and depmode must be set" 1>&2
+ exit 1
+fi
+# `libtool' can also be set to `yes' or `no'.
+
+depfile=${depfile-`echo "$object" | sed 's,\([^/]*\)$,.deps/\1,;s/\.\([^.]*\)$/.P\1/'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags. We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write. Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+ # HP compiler uses -M and no extra arg.
+ gccflag=-M
+ depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+ # This is just like dashmstdout with a different argument.
+ dashmflag=-xM
+ depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want. Yay!
+ "$@" -MT "$object" -MF "$tmpdepfile" -MD -MP
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ mv "$tmpdepfile" "$depfile"
+ ;;
+
+gcc)
+## There are various ways to get dependency output from gcc. Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+## up in a subdir. Having to rename by hand is ugly.
+## (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+## -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+## than renaming).
+ if test -z "$gccflag"; then
+ gccflag=-MD,
+ fi
+ "$@" -Wp,"$gccflag$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+ sed -e 's/^[^:]*: / /' \
+ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header). We avoid this by adding
+## dummy dependencies for each header file. Too bad gcc doesn't do
+## this for us directly.
+ tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'. On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+sgi)
+ if test "$libtool" = yes; then
+ "$@" "-Wp,-MDupdate,$tmpdepfile"
+ else
+ "$@" -MDupdate "$tmpdepfile"
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+
+ if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
+ echo "$object : \\" > "$depfile"
+
+ # Clip off the initial element (the dependent). Don't try to be
+ # clever and replace this with sed code, as IRIX sed won't handle
+ # lines with more than a fixed number of characters (4096 in
+ # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
+ # the IRIX cc adds comments like `#:fec' to the end of the
+ # dependency line.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+ tr '
+' ' ' >> $depfile
+ echo >> $depfile
+
+ # The second pass generates a dummy entry for each header file.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> $depfile
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+aix)
+ # The C for AIX Compiler uses -M and outputs the dependencies
+ # in a .u file. This file always lives in the current directory.
+ # Also, the AIX compiler puts `$object:' at the start of each line;
+ # $object doesn't have directory information.
+ stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'`
+ tmpdepfile="$stripped.u"
+ outname="$stripped.o"
+ if test "$libtool" = yes; then
+ "$@" -Wc,-M
+ else
+ "$@" -M
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+
+ if test -f "$tmpdepfile"; then
+ # Each line is of the form `foo.o: dependent.h'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
+ sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+tru64)
+ # The Tru64 AIX compiler uses -MD to generate dependencies as a side
+ # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+ # Subdirectories are respected.
+
+ tmpdepfile="$object.d"
+ if test "$libtool" = yes; then
+ "$@" -Wc,-MD
+ else
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a space and a tab in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+#nosideeffect)
+ # This comment above is used by automake to tell side-effect
+ # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the proprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ test -z "$dashmflag" && dashmflag=-M
+ ( IFS=" "
+ case " $* " in
+ *" --mode=compile "*) # this is libtool, let us make it quiet
+ for arg
+ do # cycle over the arguments
+ case "$arg" in
+ "--mode=compile")
+ # insert --quiet before "--mode=compile"
+ set fnord "$@" --quiet
+ shift # fnord
+ ;;
+ esac
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # "$arg"
+ done
+ ;;
+ esac
+ "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+dashXmstdout)
+ # This case only exists to satisfy depend.m4. It is never actually
+ # run, as this mode is specially recognized in the preamble.
+ exit 1
+ ;;
+
+makedepend)
+ # X makedepend
+ (
+ shift
+ cleared=no
+ for arg in "$@"; do
+ case $cleared in no)
+ set ""; shift
+ cleared=yes
+ esac
+ case "$arg" in
+ -D*|-I*)
+ set fnord "$@" "$arg"; shift;;
+ -*)
+ ;;
+ *)
+ set fnord "$@" "$arg"; shift;;
+ esac
+ done
+ obj_suffix="`echo $object | sed 's/^.*\././'`"
+ touch "$tmpdepfile"
+ ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ tail +3 "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile" "$tmpdepfile".bak
+ ;;
+
+cpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the proprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ ( IFS=" "
+ case " $* " in
+ *" --mode=compile "*)
+ for arg
+ do # cycle over the arguments
+ case $arg in
+ "--mode=compile")
+ # insert --quiet before "--mode=compile"
+ set fnord "$@" --quiet
+ shift # fnord
+ ;;
+ esac
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # "$arg"
+ done
+ ;;
+ esac
+ "$@" -E |
+ sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+ sed '$ s: \\$::' > "$tmpdepfile"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ cat < "$tmpdepfile" >> "$depfile"
+ sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvisualcpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the proprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ ( IFS=" "
+ case " $* " in
+ *" --mode=compile "*)
+ for arg
+ do # cycle over the arguments
+ case $arg in
+ "--mode=compile")
+ # insert --quiet before "--mode=compile"
+ set fnord "$@" --quiet
+ shift # fnord
+ ;;
+ esac
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # "$arg"
+ done
+ ;;
+ esac
+ "$@" -E |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
+ echo " " >> "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+none)
+ exec "$@"
+ ;;
+
+*)
+ echo "Unknown depmode $depmode" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/Build/source/libs/zziplib/uses/install-sh b/Build/source/libs/zziplib/uses/install-sh
new file mode 100755
index 00000000000..e9de23842dc
--- /dev/null
+++ b/Build/source/libs/zziplib/uses/install-sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/Build/source/libs/zziplib/uses/ltmain.sh b/Build/source/libs/zziplib/uses/ltmain.sh
new file mode 100644
index 00000000000..eecedf23e43
--- /dev/null
+++ b/Build/source/libs/zziplib/uses/ltmain.sh
@@ -0,0 +1,6500 @@
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun configure.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+basename="s,^.*/,,g"
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+# The name of this program:
+progname=`echo "$progpath" | $SED $basename`
+modename="$progname"
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.5.18
+TIMESTAMP=" (1.1220.2.245 2005/05/16 08:55:27)"
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes.
+if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+fi
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell, and then maybe $echo will work.
+ exec $SHELL "$progpath" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit $EXIT_SUCCESS
+fi
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+# test EBCDIC or ASCII
+case `echo A|tr A '\301'` in
+ A) # EBCDIC based system
+ SP2NL="tr '\100' '\n'"
+ NL2SP="tr '\r\n' '\100\100'"
+ ;;
+ *) # Assume ASCII based system
+ SP2NL="tr '\040' '\012'"
+ NL2SP="tr '\015\012' '\040\040'"
+ ;;
+esac
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+if test "${LC_ALL+set}" = set; then
+ save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
+fi
+if test "${LANG+set}" = set; then
+ save_LANG="$LANG"; LANG=C; export LANG
+fi
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS=" $lt_nl"
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ $echo "$modename: not configured to build any kind of library" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit $EXIT_FAILURE
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+quote_scanset='[[~#^*{};<>?'"'"' ]'
+
+#####################################
+# Shell function definitions:
+# This seems to be the best place for them
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+func_win32_libid ()
+{
+ win32_libid_type="unknown"
+ win32_fileres=`file -L $1 2>/dev/null`
+ case $win32_fileres in
+ *ar\ archive\ import\ library*) # definitely import
+ win32_libid_type="x86 archive import"
+ ;;
+ *ar\ archive*) # could be an import, or static
+ if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
+ $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+ win32_nmres=`eval $NM -f posix -A $1 | \
+ sed -n -e '1,100{/ I /{x;/import/!{s/^/import/;h;p;};x;};}'`
+ if test "X$win32_nmres" = "Ximport" ; then
+ win32_libid_type="x86 archive import"
+ else
+ win32_libid_type="x86 archive static"
+ fi
+ fi
+ ;;
+ *DLL*)
+ win32_libid_type="x86 DLL"
+ ;;
+ *executable*) # but shell scripts are "executable" too...
+ case $win32_fileres in
+ *MS\ Windows\ PE\ Intel*)
+ win32_libid_type="x86 DLL"
+ ;;
+ esac
+ ;;
+ esac
+ $echo $win32_libid_type
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+ if test -n "$available_tags" && test -z "$tagname"; then
+ CC_quoted=
+ for arg in $CC; do
+ case $arg in
+ *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+ arg="\"$arg\""
+ ;;
+ esac
+ CC_quoted="$CC_quoted $arg"
+ done
+ case $@ in
+ # Blanks in the command may have been stripped by the calling shell,
+ # but not from the CC environment variable when configure was run.
+ " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;;
+ # Blanks at the start of $base_compile will cause this to fail
+ # if we don't check for them as well.
+ *)
+ for z in $available_tags; do
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+ CC_quoted=
+ for arg in $CC; do
+ # Double-quote args containing other shell metacharacters.
+ case $arg in
+ *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+ arg="\"$arg\""
+ ;;
+ esac
+ CC_quoted="$CC_quoted $arg"
+ done
+ case "$@ " in
+ " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*)
+ # The compiler in the base compile command matches
+ # the one in the tagged configuration.
+ # Assume this is the tagged configuration we want.
+ tagname=$z
+ break
+ ;;
+ esac
+ fi
+ done
+ # If $tagname still isn't set, then no tagged configuration
+ # was found and let the user know that the "--tag" command
+ # line option must be used.
+ if test -z "$tagname"; then
+ $echo "$modename: unable to infer tagged configuration"
+ $echo "$modename: specify a tag with \`--tag'" 1>&2
+ exit $EXIT_FAILURE
+# else
+# $echo "$modename: using $tagname tagged configuration"
+ fi
+ ;;
+ esac
+ fi
+}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+ f_ex_an_ar_dir="$1"; shift
+ f_ex_an_ar_oldlib="$1"
+
+ $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
+ $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
+ if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
+ exit $EXIT_FAILURE
+ fi
+}
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+ my_gentop="$1"; shift
+ my_oldlibs=${1+"$@"}
+ my_oldobjs=""
+ my_xlib=""
+ my_xabs=""
+ my_xdir=""
+ my_status=""
+
+ $show "${rm}r $my_gentop"
+ $run ${rm}r "$my_gentop"
+ $show "$mkdir $my_gentop"
+ $run $mkdir "$my_gentop"
+ my_status=$?
+ if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
+ exit $my_status
+ fi
+
+ for my_xlib in $my_oldlibs; do
+ # Extract the objects.
+ case $my_xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+ *) my_xabs=`pwd`"/$my_xlib" ;;
+ esac
+ my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
+ my_xdir="$my_gentop/$my_xlib"
+
+ $show "${rm}r $my_xdir"
+ $run ${rm}r "$my_xdir"
+ $show "$mkdir $my_xdir"
+ $run $mkdir "$my_xdir"
+ status=$?
+ if test "$status" -ne 0 && test ! -d "$my_xdir"; then
+ exit $status
+ fi
+ case $host in
+ *-darwin*)
+ $show "Extracting $my_xabs"
+ # Do not bother doing anything if just a dry run
+ if test -z "$run"; then
+ darwin_orig_dir=`pwd`
+ cd $my_xdir || exit $?
+ darwin_archive=$my_xabs
+ darwin_curdir=`pwd`
+ darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'`
+ darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
+ if test -n "$darwin_arches"; then
+ darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
+ darwin_arch=
+ $show "$darwin_base_archive has multiple architectures $darwin_arches"
+ for darwin_arch in $darwin_arches ; do
+ mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+ cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+ cd "$darwin_curdir"
+ $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+ done # $darwin_arches
+ ## Okay now we have a bunch of thin objects, gotta fatten them up :)
+ darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP`
+ darwin_file=
+ darwin_files=
+ for darwin_file in $darwin_filelist; do
+ darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+ lipo -create -output "$darwin_file" $darwin_files
+ done # $darwin_filelist
+ ${rm}r unfat-$$
+ cd "$darwin_orig_dir"
+ else
+ cd "$darwin_orig_dir"
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ fi # $darwin_arches
+ fi # $run
+ ;;
+ *)
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ ;;
+ esac
+ my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+ done
+ func_extract_archives_result="$my_oldobjs"
+}
+# End of Shell function definitions
+#####################################
+
+# Darwin sucks
+eval std_shrext=\"$shrext_cmds\"
+
+# Parse our command line options once, thoroughly.
+while test "$#" -gt 0
+do
+ arg="$1"
+ shift
+
+ case $arg in
+ -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ execute_dlfiles)
+ execute_dlfiles="$execute_dlfiles $arg"
+ ;;
+ tag)
+ tagname="$arg"
+ preserve_args="${preserve_args}=$arg"
+
+ # Check whether tagname contains only valid characters
+ case $tagname in
+ *[!-_A-Za-z0-9,/]*)
+ $echo "$progname: invalid tag name: $tagname" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $tagname in
+ CC)
+ # Don't test for the "default" C tag, as we know, it's there, but
+ # not specially marked.
+ ;;
+ *)
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then
+ taglist="$taglist $tagname"
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`"
+ else
+ $echo "$progname: ignoring unknown tag $tagname" 1>&2
+ fi
+ ;;
+ esac
+ ;;
+ *)
+ eval "$prev=\$arg"
+ ;;
+ esac
+
+ prev=
+ prevopt=
+ continue
+ fi
+
+ # Have we seen a non-optional argument yet?
+ case $arg in
+ --help)
+ show_help=yes
+ ;;
+
+ --version)
+ $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
+ $echo
+ $echo "Copyright (C) 2005 Free Software Foundation, Inc."
+ $echo "This is free software; see the source for copying conditions. There is NO"
+ $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+ exit $?
+ ;;
+
+ --config)
+ ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath
+ # Now print the configurations for the tags.
+ for tagname in $taglist; do
+ ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
+ done
+ exit $?
+ ;;
+
+ --debug)
+ $echo "$progname: enabling shell trace mode"
+ set -x
+ preserve_args="$preserve_args $arg"
+ ;;
+
+ --dry-run | -n)
+ run=:
+ ;;
+
+ --features)
+ $echo "host: $host"
+ if test "$build_libtool_libs" = yes; then
+ $echo "enable shared libraries"
+ else
+ $echo "disable shared libraries"
+ fi
+ if test "$build_old_libs" = yes; then
+ $echo "enable static libraries"
+ else
+ $echo "disable static libraries"
+ fi
+ exit $?
+ ;;
+
+ --finish) mode="finish" ;;
+
+ --mode) prevopt="--mode" prev=mode ;;
+ --mode=*) mode="$optarg" ;;
+
+ --preserve-dup-deps) duplicate_deps="yes" ;;
+
+ --quiet | --silent)
+ show=:
+ preserve_args="$preserve_args $arg"
+ ;;
+
+ --tag) prevopt="--tag" prev=tag ;;
+ --tag=*)
+ set tag "$optarg" ${1+"$@"}
+ shift
+ prev=tag
+ preserve_args="$preserve_args --tag"
+ ;;
+
+ -dlopen)
+ prevopt="-dlopen"
+ prev=execute_dlfiles
+ ;;
+
+ -*)
+ $echo "$modename: unrecognized option \`$arg'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+
+ *)
+ nonopt="$arg"
+ break
+ ;;
+ esac
+done
+
+if test -n "$prevopt"; then
+ $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+fi
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end. This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+if test -z "$show_help"; then
+
+ # Infer the operation mode.
+ if test -z "$mode"; then
+ $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
+ $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2
+ case $nonopt in
+ *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
+ mode=link
+ for arg
+ do
+ case $arg in
+ -c)
+ mode=compile
+ break
+ ;;
+ esac
+ done
+ ;;
+ *db | *dbx | *strace | *truss)
+ mode=execute
+ ;;
+ *install*|cp|mv)
+ mode=install
+ ;;
+ *rm)
+ mode=uninstall
+ ;;
+ *)
+ # If we have no mode, but dlfiles were specified, then do execute mode.
+ test -n "$execute_dlfiles" && mode=execute
+
+ # Just use the default operation mode.
+ if test -z "$mode"; then
+ if test -n "$nonopt"; then
+ $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+ else
+ $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+ fi
+ fi
+ ;;
+ esac
+ fi
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$execute_dlfiles" && test "$mode" != execute; then
+ $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help="$help"
+ help="Try \`$modename --help --mode=$mode' for more information."
+
+ # These modes are in order of execution frequency so that they run quickly.
+ case $mode in
+ # libtool compile mode
+ compile)
+ modename="$modename: compile"
+ # Get the compilation command and the source file.
+ base_compile=
+ srcfile="$nonopt" # always keep a non-empty value in "srcfile"
+ suppress_opt=yes
+ suppress_output=
+ arg_mode=normal
+ libobj=
+ later=
+
+ for arg
+ do
+ case "$arg_mode" in
+ arg )
+ # do not "continue". Instead, add this to base_compile
+ lastarg="$arg"
+ arg_mode=normal
+ ;;
+
+ target )
+ libobj="$arg"
+ arg_mode=normal
+ continue
+ ;;
+
+ normal )
+ # Accept any command-line options.
+ case $arg in
+ -o)
+ if test -n "$libobj" ; then
+ $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ arg_mode=target
+ continue
+ ;;
+
+ -static | -prefer-pic | -prefer-non-pic)
+ later="$later $arg"
+ continue
+ ;;
+
+ -no-suppress)
+ suppress_opt=no
+ continue
+ ;;
+
+ -Xcompiler)
+ arg_mode=arg # the next one goes into the "base_compile" arg list
+ continue # The current "srcfile" will either be retained or
+ ;; # replaced later. I would guess that would be a bug.
+
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
+ lastarg=
+ save_ifs="$IFS"; IFS=','
+ for arg in $args; do
+ IFS="$save_ifs"
+
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ case $arg in
+ *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+ arg="\"$arg\""
+ ;;
+ esac
+ lastarg="$lastarg $arg"
+ done
+ IFS="$save_ifs"
+ lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
+
+ # Add the arguments to base_compile.
+ base_compile="$base_compile $lastarg"
+ continue
+ ;;
+
+ * )
+ # Accept the current argument as the source file.
+ # The previous "srcfile" becomes the current argument.
+ #
+ lastarg="$srcfile"
+ srcfile="$arg"
+ ;;
+ esac # case $arg
+ ;;
+ esac # case $arg_mode
+
+ # Aesthetically quote the previous argument.
+ lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+ case $lastarg in
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, and some SunOS ksh mistreat backslash-escaping
+ # in scan sets (worked around with variable expansion),
+ # and furthermore cannot handle '|' '&' '(' ')' in scan sets
+ # at all, so we specify them separately.
+ *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+ lastarg="\"$lastarg\""
+ ;;
+ esac
+
+ base_compile="$base_compile $lastarg"
+ done # for arg
+
+ case $arg_mode in
+ arg)
+ $echo "$modename: you must specify an argument for -Xcompile"
+ exit $EXIT_FAILURE
+ ;;
+ target)
+ $echo "$modename: you must specify a target with \`-o'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ *)
+ # Get the name of the library object.
+ [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+ ;;
+ esac
+
+ # Recognize several different file suffixes.
+ # If the user specifies -o file.o, it is replaced with file.lo
+ xform='[cCFSifmso]'
+ case $libobj in
+ *.ada) xform=ada ;;
+ *.adb) xform=adb ;;
+ *.ads) xform=ads ;;
+ *.asm) xform=asm ;;
+ *.c++) xform=c++ ;;
+ *.cc) xform=cc ;;
+ *.ii) xform=ii ;;
+ *.class) xform=class ;;
+ *.cpp) xform=cpp ;;
+ *.cxx) xform=cxx ;;
+ *.f90) xform=f90 ;;
+ *.for) xform=for ;;
+ *.java) xform=java ;;
+ esac
+
+ libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+ case $libobj in
+ *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+ *)
+ $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ func_infer_tag $base_compile
+
+ for arg in $later; do
+ case $arg in
+ -static)
+ build_old_libs=yes
+ continue
+ ;;
+
+ -prefer-pic)
+ pic_mode=yes
+ continue
+ ;;
+
+ -prefer-non-pic)
+ pic_mode=no
+ continue
+ ;;
+ esac
+ done
+
+ qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
+ case $qlibobj in
+ *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+ qlibobj="\"$qlibobj\"" ;;
+ esac
+ if test "X$libobj" != "X$qlibobj"; then
+ $echo "$modename: libobj name \`$libobj' may not contain shell special characters."
+ exit $EXIT_FAILURE
+ fi
+ objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+ xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$obj"; then
+ xdir=
+ else
+ xdir=$xdir/
+ fi
+ lobj=${xdir}$objdir/$objname
+
+ if test -z "$base_compile"; then
+ $echo "$modename: you must specify a compilation command" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Delete any leftover library objects.
+ if test "$build_old_libs" = yes; then
+ removelist="$obj $lobj $libobj ${libobj}T"
+ else
+ removelist="$lobj $libobj ${libobj}T"
+ fi
+
+ $run $rm $removelist
+ trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+
+ # On Cygwin there's no "real" PIC flag so we must build both object types
+ case $host_os in
+ cygwin* | mingw* | pw32* | os2*)
+ pic_mode=default
+ ;;
+ esac
+ if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+ # non-PIC code in shared libraries is not supported
+ pic_mode=default
+ fi
+
+ # Calculate the filename of the output object if compiler does
+ # not support -o with -c
+ if test "$compiler_c_o" = no; then
+ output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+ lockfile="$output_obj.lock"
+ removelist="$removelist $output_obj $lockfile"
+ trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+ else
+ output_obj=
+ need_locks=no
+ lockfile=
+ fi
+
+ # Lock this critical section if it is needed
+ # We use this script file to make the link, it avoids creating a new file
+ if test "$need_locks" = yes; then
+ until $run ln "$progpath" "$lockfile" 2>/dev/null; do
+ $show "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ elif test "$need_locks" = warn; then
+ if test -f "$lockfile"; then
+ $echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+ $echo "$srcfile" > "$lockfile"
+ fi
+
+ if test -n "$fix_srcfile_path"; then
+ eval srcfile=\"$fix_srcfile_path\"
+ fi
+ qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
+ case $qsrcfile in
+ *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+ qsrcfile="\"$qsrcfile\"" ;;
+ esac
+
+ $run $rm "$libobj" "${libobj}T"
+
+ # Create a libtool object file (analogous to a ".la" file),
+ # but don't create it if we're doing a dry run.
+ test -z "$run" && cat > ${libobj}T <<EOF
+# $libobj - a libtool object file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+EOF
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test "$build_libtool_libs" = yes; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ if test "$pic_mode" != no; then
+ command="$base_compile $qsrcfile $pic_flag"
+ else
+ # Don't build PIC code
+ command="$base_compile $qsrcfile"
+ fi
+
+ if test ! -d "${xdir}$objdir"; then
+ $show "$mkdir ${xdir}$objdir"
+ $run $mkdir ${xdir}$objdir
+ status=$?
+ if test "$status" -ne 0 && test ! -d "${xdir}$objdir"; then
+ exit $status
+ fi
+ fi
+
+ if test -z "$output_obj"; then
+ # Place PIC objects in $objdir
+ command="$command -o $lobj"
+ fi
+
+ $run $rm "$lobj" "$output_obj"
+
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ test -n "$output_obj" && $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$need_locks" = warn &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed, then go on to compile the next one
+ if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+ $show "$mv $output_obj $lobj"
+ if $run $mv $output_obj $lobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Append the name of the PIC object to the libtool object file.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object='$objdir/$objname'
+
+EOF
+
+ # Allow error messages only from the first compilation.
+ if test "$suppress_opt" = yes; then
+ suppress_output=' >/dev/null 2>&1'
+ fi
+ else
+ # No PIC object so indicate it doesn't exist in the libtool
+ # object file.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object=none
+
+EOF
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test "$build_old_libs" = yes; then
+ if test "$pic_mode" != yes; then
+ # Don't build PIC code
+ command="$base_compile $qsrcfile"
+ else
+ command="$base_compile $qsrcfile $pic_flag"
+ fi
+ if test "$compiler_c_o" = yes; then
+ command="$command -o $obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ command="$command$suppress_output"
+ $run $rm "$obj" "$output_obj"
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$need_locks" = warn &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed
+ if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+ $show "$mv $output_obj $obj"
+ if $run $mv $output_obj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Append the name of the non-PIC object the libtool object file.
+ # Only append if the libtool object file exists.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object='$objname'
+
+EOF
+ else
+ # Append the name of the non-PIC object the libtool object file.
+ # Only append if the libtool object file exists.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object=none
+
+EOF
+ fi
+
+ $run $mv "${libobj}T" "${libobj}"
+
+ # Unlock the critical section if it was locked
+ if test "$need_locks" != no; then
+ $run $rm "$lockfile"
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool link mode
+ link | relink)
+ modename="$modename: link"
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ # It is impossible to link a dll without this setting, and
+ # we shouldn't force the makefile maintainer to figure out
+ # which system we are compiling for in order to pass an extra
+ # flag for every libtool invocation.
+ # allow_undefined=no
+
+ # FIXME: Unfortunately, there are problems with the above when trying
+ # to make a dll which has undefined symbols, in which case not
+ # even a static library is built. For now, we need to specify
+ # -no-undefined on the libtool link line when we can be certain
+ # that all symbols are satisfied, otherwise we get a static library.
+ allow_undefined=yes
+ ;;
+ *)
+ allow_undefined=yes
+ ;;
+ esac
+ libtool_args="$nonopt"
+ base_compile="$nonopt $@"
+ compile_command="$nonopt"
+ finalize_command="$nonopt"
+
+ compile_rpath=
+ finalize_rpath=
+ compile_shlibpath=
+ finalize_shlibpath=
+ convenience=
+ old_convenience=
+ deplibs=
+ old_deplibs=
+ compiler_flags=
+ linker_flags=
+ dllsearchpath=
+ lib_search_path=`pwd`
+ inst_prefix_dir=
+
+ avoid_version=no
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ ltlibs=
+ module=no
+ no_install=no
+ objs=
+ non_pic_objects=
+ precious_files_regex=
+ prefer_static_libs=no
+ preload=no
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+ vinfo_number=no
+
+ func_infer_tag $base_compile
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case $arg in
+ -all-static | -static)
+ if test "X$arg" = "X-all-static"; then
+ if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+ $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ else
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ fi
+ build_libtool_libs=no
+ build_old_libs=yes
+ prefer_static_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ while test "$#" -gt 0; do
+ arg="$1"
+ shift
+ case $arg in
+ *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+ qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
+ ;;
+ *) qarg=$arg ;;
+ esac
+ libtool_args="$libtool_args $qarg"
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ output)
+ compile_command="$compile_command @OUTPUT@"
+ finalize_command="$finalize_command @OUTPUT@"
+ ;;
+ esac
+
+ case $prev in
+ dlfiles|dlprefiles)
+ if test "$preload" = no; then
+ # Add the symbol object into the linking commands.
+ compile_command="$compile_command @SYMFILE@"
+ finalize_command="$finalize_command @SYMFILE@"
+ preload=yes
+ fi
+ case $arg in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test "$dlself" = no; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test "$prev" = dlprefiles; then
+ dlself=yes
+ elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ else
+ dlprefiles="$dlprefiles $arg"
+ fi
+ prev=
+ continue
+ ;;
+ esac
+ ;;
+ expsyms)
+ export_symbols="$arg"
+ if test ! -f "$arg"; then
+ $echo "$modename: symbol file \`$arg' does not exist"
+ exit $EXIT_FAILURE
+ fi
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex="$arg"
+ prev=
+ continue
+ ;;
+ inst_prefix)
+ inst_prefix_dir="$arg"
+ prev=
+ continue
+ ;;
+ precious_regex)
+ precious_files_regex="$arg"
+ prev=
+ continue
+ ;;
+ release)
+ release="-$arg"
+ prev=
+ continue
+ ;;
+ objectlist)
+ if test -f "$arg"; then
+ save_arg=$arg
+ moreargs=
+ for fil in `cat $save_arg`
+ do
+# moreargs="$moreargs $fil"
+ arg=$fil
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ # If there is no directory component, then add one.
+ case $arg in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ if test -z "$pic_object" || \
+ test -z "$non_pic_object" ||
+ test "$pic_object" = none && \
+ test "$non_pic_object" = none; then
+ $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ if test "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ libobjs="$libobjs $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object="$xdir$non_pic_object"
+
+ # A standard non-PIC object
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ if test -z "$pic_object" || test "$pic_object" = none ; then
+ arg="$non_pic_object"
+ fi
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if test -z "$run"; then
+ $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+ exit $EXIT_FAILURE
+ else
+ # Dry-run case.
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+ non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+ libobjs="$libobjs $pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ fi
+ done
+ else
+ $echo "$modename: link input file \`$save_arg' does not exist"
+ exit $EXIT_FAILURE
+ fi
+ arg=$save_arg
+ prev=
+ continue
+ ;;
+ rpath | xrpath)
+ # We need an absolute path.
+ case $arg in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ if test "$prev" = rpath; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) rpath="$rpath $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) xrpath="$xrpath $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ xcompiler)
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ compile_command="$compile_command $qarg"
+ finalize_command="$finalize_command $qarg"
+ continue
+ ;;
+ xlinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $wl$qarg"
+ prev=
+ compile_command="$compile_command $wl$qarg"
+ finalize_command="$finalize_command $wl$qarg"
+ continue
+ ;;
+ xcclinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ compile_command="$compile_command $qarg"
+ finalize_command="$finalize_command $qarg"
+ continue
+ ;;
+ shrext)
+ shrext_cmds="$arg"
+ prev=
+ continue
+ ;;
+ darwin_framework)
+ compiler_flags="$compiler_flags $arg"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ prev=
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi # test -n "$prev"
+
+ prevarg="$arg"
+
+ case $arg in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ # FIXME: remove this flag sometime in the future.
+ $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+ continue
+ ;;
+
+ -avoid-version)
+ avoid_version=yes
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ export_dynamic=yes
+ continue
+ ;;
+
+ -export-symbols | -export-symbols-regex)
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: more than one -exported-symbols argument is not allowed"
+ exit $EXIT_FAILURE
+ fi
+ if test "X$arg" = "X-export-symbols"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ continue
+ ;;
+
+ -framework)
+ prev=darwin_framework
+ compiler_flags="$compiler_flags $arg"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ continue
+ ;;
+
+ -inst-prefix-dir)
+ prev=inst_prefix
+ continue
+ ;;
+
+ # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+ # so, if we see these flags be careful not to treat them like -L
+ -L[A-Z][A-Z]*:*)
+ case $with_gcc/$host in
+ no/*-*-irix* | /*-*-irix*)
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ ;;
+ esac
+ continue
+ ;;
+
+ -L*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ dir="$absdir"
+ ;;
+ esac
+ case "$deplibs " in
+ *" -L$dir "*) ;;
+ *)
+ deplibs="$deplibs -L$dir"
+ lib_search_path="$lib_search_path $dir"
+ ;;
+ esac
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ case :$dllsearchpath: in
+ *":$dir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$dir";;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+
+ -l*)
+ if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+ case $host in
+ *-*-cygwin* | *-*-pw32* | *-*-beos*)
+ # These systems don't actually have a C or math library (as such)
+ continue
+ ;;
+ *-*-mingw* | *-*-os2*)
+ # These systems don't actually have a C library (as such)
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc due to us having libc/libc_r.
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C and math libraries are in the System framework
+ deplibs="$deplibs -framework System"
+ continue
+ esac
+ elif test "X$arg" = "X-lc_r"; then
+ case $host in
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc_r directly, use -pthread flag.
+ continue
+ ;;
+ esac
+ fi
+ deplibs="$deplibs $arg"
+ continue
+ ;;
+
+ # Tru64 UNIX uses -model [arg] to determine the layout of C++
+ # classes, name mangling, and exception handling.
+ -model)
+ compile_command="$compile_command $arg"
+ compiler_flags="$compiler_flags $arg"
+ finalize_command="$finalize_command $arg"
+ prev=xcompiler
+ continue
+ ;;
+
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
+ compiler_flags="$compiler_flags $arg"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ continue
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+ # -r[0-9][0-9]* specifies the processor on the SGI compiler
+ # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+ # +DA*, +DD* enable 64-bit mode on the HP compiler
+ # -q* pass through compiler args for the IBM compiler
+ # -m* pass through architecture-specific compiler args for GCC
+ -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*)
+
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+ arg="\"$arg\""
+ ;;
+ esac
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ if test "$with_gcc" = "yes" ; then
+ compiler_flags="$compiler_flags $arg"
+ fi
+ continue
+ ;;
+
+ -shrext)
+ prev=shrext
+ continue
+ ;;
+
+ -no-fast-install)
+ fast_install=no
+ continue
+ ;;
+
+ -no-install)
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ # The PATH hackery in wrapper scripts is required on Windows
+ # in order for the loader to find any dlls it needs.
+ $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
+ $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
+ fast_install=no
+ ;;
+ *) no_install=yes ;;
+ esac
+ continue
+ ;;
+
+ -no-undefined)
+ allow_undefined=no
+ continue
+ ;;
+
+ -objectlist)
+ prev=objectlist
+ continue
+ ;;
+
+ -o) prev=output ;;
+
+ -precious-files-regex)
+ prev=precious_regex
+ continue
+ ;;
+
+ -release)
+ prev=release
+ continue
+ ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -R)
+ prev=xrpath
+ continue
+ ;;
+
+ -R*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ continue
+ ;;
+
+ -static)
+ # The effects of -static are defined in a previous loop.
+ # We used to do the same as -all-static on platforms that
+ # didn't have a PIC flag, but the assumption that the effects
+ # would be equivalent was wrong. It would break on at least
+ # Digital Unix and AIX.
+ continue
+ ;;
+
+ -thread-safe)
+ thread_safe=yes
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+ -version-number)
+ prev=vinfo
+ vinfo_number=yes
+ continue
+ ;;
+
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Wl,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $wl$flag"
+ linker_flags="$linker_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Xcompiler)
+ prev=xcompiler
+ continue
+ ;;
+
+ -Xlinker)
+ prev=xlinker
+ continue
+ ;;
+
+ -XCClinker)
+ prev=xcclinker
+ continue
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+
+ *.$objext)
+ # A standard object.
+ objs="$objs $arg"
+ ;;
+
+ *.lo)
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ # If there is no directory component, then add one.
+ case $arg in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ if test -z "$pic_object" || \
+ test -z "$non_pic_object" ||
+ test "$pic_object" = none && \
+ test "$non_pic_object" = none; then
+ $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ if test "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ libobjs="$libobjs $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object="$xdir$non_pic_object"
+
+ # A standard non-PIC object
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ if test -z "$pic_object" || test "$pic_object" = none ; then
+ arg="$non_pic_object"
+ fi
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if test -z "$run"; then
+ $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+ exit $EXIT_FAILURE
+ else
+ # Dry-run case.
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+ non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+ libobjs="$libobjs $pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ fi
+ ;;
+
+ *.$libext)
+ # An archive.
+ deplibs="$deplibs $arg"
+ old_deplibs="$old_deplibs $arg"
+ continue
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ if test "$prev" = dlfiles; then
+ # This library was specified with -dlopen.
+ dlfiles="$dlfiles $arg"
+ prev=
+ elif test "$prev" = dlprefiles; then
+ # The library was specified with -dlpreopen.
+ dlprefiles="$dlprefiles $arg"
+ prev=
+ else
+ deplibs="$deplibs $arg"
+ fi
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+ esac # arg
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+ done # argument parsing loop
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+
+ oldlibs=
+ # calculate the name of the file, without its directory
+ outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+ libobjs_save="$libobjs"
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+ else
+ shlib_search_path=
+ fi
+ eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+ # Create the object directory.
+ if test ! -d "$output_objdir"; then
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ status=$?
+ if test "$status" -ne 0 && test ! -d "$output_objdir"; then
+ exit $status
+ fi
+ fi
+
+ # Determine the type of output
+ case $output in
+ "")
+ $echo "$modename: you must specify an output file" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ *.$libext) linkmode=oldlib ;;
+ *.lo | *.$objext) linkmode=obj ;;
+ *.la) linkmode=lib ;;
+ *) linkmode=prog ;; # Anything else should be a program.
+ esac
+
+ case $host in
+ *cygwin* | *mingw* | *pw32*)
+ # don't eliminate duplications in $postdeps and $predeps
+ duplicate_compiler_generated_deps=yes
+ ;;
+ *)
+ duplicate_compiler_generated_deps=$duplicate_deps
+ ;;
+ esac
+ specialdeplibs=
+
+ libs=
+ # Find all interdependent deplibs by searching for libraries
+ # that are linked more than once (e.g. -la -lb -la)
+ for deplib in $deplibs; do
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ libs="$libs $deplib"
+ done
+
+ if test "$linkmode" = lib; then
+ libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+ # Compute libraries that are listed more than once in $predeps
+ # $postdeps and mark them as special (i.e., whose duplicates are
+ # not to be eliminated).
+ pre_post_deps=
+ if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then
+ for pre_post_dep in $predeps $postdeps; do
+ case "$pre_post_deps " in
+ *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+ esac
+ pre_post_deps="$pre_post_deps $pre_post_dep"
+ done
+ fi
+ pre_post_deps=
+ fi
+
+ deplibs=
+ newdependency_libs=
+ newlib_search_path=
+ need_relink=no # whether we're linking any uninstalled libtool libraries
+ notinst_deplibs= # not-installed libtool libraries
+ notinst_path= # paths that contain not-installed libtool libraries
+ case $linkmode in
+ lib)
+ passes="conv link"
+ for file in $dlfiles $dlprefiles; do
+ case $file in
+ *.la) ;;
+ *)
+ $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ done
+ ;;
+ prog)
+ compile_deplibs=
+ finalize_deplibs=
+ alldeplibs=no
+ newdlfiles=
+ newdlprefiles=
+ passes="conv scan dlopen dlpreopen link"
+ ;;
+ *) passes="conv"
+ ;;
+ esac
+ for pass in $passes; do
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan"; then
+ libs="$deplibs"
+ deplibs=
+ fi
+ if test "$linkmode" = prog; then
+ case $pass in
+ dlopen) libs="$dlfiles" ;;
+ dlpreopen) libs="$dlprefiles" ;;
+ link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+ esac
+ fi
+ if test "$pass" = dlopen; then
+ # Collect dlpreopened libraries
+ save_deplibs="$deplibs"
+ deplibs=
+ fi
+ for deplib in $libs; do
+ lib=
+ found=no
+ case $deplib in
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ compiler_flags="$compiler_flags $deplib"
+ fi
+ continue
+ ;;
+ -l*)
+ if test "$linkmode" != lib && test "$linkmode" != prog; then
+ $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
+ continue
+ fi
+ name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
+ for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ for search_ext in .la $std_shrext .so .a; do
+ # Search the libtool library
+ lib="$searchdir/lib${name}${search_ext}"
+ if test -f "$lib"; then
+ if test "$search_ext" = ".la"; then
+ found=yes
+ else
+ found=no
+ fi
+ break 2
+ fi
+ done
+ done
+ if test "$found" != yes; then
+ # deplib doesn't seem to be a libtool library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ else # deplib is a libtool library
+ # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+ # We need to do some special things here, and not later.
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $deplib "*)
+ if (${SED} -e '2q' $lib |
+ grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ library_names=
+ old_library=
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ for l in $old_library $library_names; do
+ ll="$l"
+ done
+ if test "X$ll" = "X$old_library" ; then # only static version available
+ found=no
+ ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$ladir" = "X$lib" && ladir="."
+ lib=$ladir/$old_library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+ fi
+ fi
+ ;; # -l
+ -L*)
+ case $linkmode in
+ lib)
+ deplibs="$deplib $deplibs"
+ test "$pass" = conv && continue
+ newdependency_libs="$deplib $newdependency_libs"
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ ;;
+ prog)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ if test "$pass" = scan; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ ;;
+ *)
+ $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2
+ ;;
+ esac # linkmode
+ continue
+ ;; # -L
+ -R*)
+ if test "$pass" = link; then
+ dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+ # Make sure the xrpath contains only unique directories.
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ fi
+ deplibs="$deplib $deplibs"
+ continue
+ ;;
+ *.la) lib="$deplib" ;;
+ *.$libext)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ case $linkmode in
+ lib)
+ valid_a_lib=no
+ case $deplibs_check_method in
+ match_pattern*)
+ set dummy $deplibs_check_method
+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ if eval $echo \"$deplib\" 2>/dev/null \
+ | $SED 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ valid_a_lib=yes
+ fi
+ ;;
+ pass_all)
+ valid_a_lib=yes
+ ;;
+ esac
+ if test "$valid_a_lib" != yes; then
+ $echo
+ $echo "*** Warning: Trying to link with static lib archive $deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because the file extensions .$libext of this argument makes me believe"
+ $echo "*** that it is just a static archive that I should not used here."
+ else
+ $echo
+ $echo "*** Warning: Linking the shared library $output against the"
+ $echo "*** static library $deplib is not portable!"
+ deplibs="$deplib $deplibs"
+ fi
+ continue
+ ;;
+ prog)
+ if test "$pass" != link; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ continue
+ ;;
+ esac # linkmode
+ ;; # *.$libext
+ *.lo | *.$objext)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ elif test "$linkmode" = prog; then
+ if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlopen support or we're linking statically,
+ # we need to preload.
+ newdlprefiles="$newdlprefiles $deplib"
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ newdlfiles="$newdlfiles $deplib"
+ fi
+ fi
+ continue
+ ;;
+ %DEPLIBS%)
+ alldeplibs=yes
+ continue
+ ;;
+ esac # case $deplib
+ if test "$found" = yes || test -f "$lib"; then :
+ else
+ $echo "$modename: cannot find the library \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$ladir" = "X$lib" && ladir="."
+
+ dlname=
+ dlopen=
+ dlpreopen=
+ libdir=
+ library_names=
+ old_library=
+ # If the library was installed with an old release of libtool,
+ # it will not redefine variables installed, or shouldnotlink
+ installed=yes
+ shouldnotlink=no
+ avoidtemprpath=
+
+
+ # Read the .la file
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan" ||
+ { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+ test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+ test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+ fi
+
+ if test "$pass" = conv; then
+ # Only check for convenience libraries
+ deplibs="$lib $deplibs"
+ if test -z "$libdir"; then
+ if test -z "$old_library"; then
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ # It is a libtool convenience library, so add in its objects.
+ convenience="$convenience $ladir/$objdir/$old_library"
+ old_convenience="$old_convenience $ladir/$objdir/$old_library"
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+ elif test "$linkmode" != prog && test "$linkmode" != lib; then
+ $echo "$modename: \`$lib' is not a convenience library" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ continue
+ fi # $pass = conv
+
+
+ # Get the name of the library we link against.
+ linklib=
+ for l in $old_library $library_names; do
+ linklib="$l"
+ done
+ if test -z "$linklib"; then
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # This library was specified with -dlopen.
+ if test "$pass" = dlopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test -z "$dlname" ||
+ test "$dlopen_support" != yes ||
+ test "$build_libtool_libs" = no; then
+ # If there is no dlname, no dlopen support or we're linking
+ # statically, we need to preload. We also need to preload any
+ # dependent libraries so libltdl's deplib preloader doesn't
+ # bomb out in the load deplibs phase.
+ dlprefiles="$dlprefiles $lib $dependency_libs"
+ else
+ newdlfiles="$newdlfiles $lib"
+ fi
+ continue
+ fi # $pass = dlopen
+
+ # We need an absolute path.
+ case $ladir in
+ [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+ *)
+ abs_ladir=`cd "$ladir" && pwd`
+ if test -z "$abs_ladir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
+ $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+ abs_ladir="$ladir"
+ fi
+ ;;
+ esac
+ laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+
+ # Find the relevant object directory and library name.
+ if test "X$installed" = Xyes; then
+ if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ $echo "$modename: warning: library \`$lib' was moved." 1>&2
+ dir="$ladir"
+ absdir="$abs_ladir"
+ libdir="$abs_ladir"
+ else
+ dir="$libdir"
+ absdir="$libdir"
+ fi
+ test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+ else
+ if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ dir="$ladir"
+ absdir="$abs_ladir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ else
+ dir="$ladir/$objdir"
+ absdir="$abs_ladir/$objdir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ fi
+ fi # $installed = yes
+ name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+
+ # This library was specified with -dlpreopen.
+ if test "$pass" = dlpreopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ newdlprefiles="$newdlprefiles $dir/$old_library"
+ # Otherwise, use the dlname, so that lt_dlopen finds it.
+ elif test -n "$dlname"; then
+ newdlprefiles="$newdlprefiles $dir/$dlname"
+ else
+ newdlprefiles="$newdlprefiles $dir/$linklib"
+ fi
+ fi # $pass = dlpreopen
+
+ if test -z "$libdir"; then
+ # Link the convenience library
+ if test "$linkmode" = lib; then
+ deplibs="$dir/$old_library $deplibs"
+ elif test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$dir/$old_library $compile_deplibs"
+ finalize_deplibs="$dir/$old_library $finalize_deplibs"
+ else
+ deplibs="$lib $deplibs" # used for prog,scan pass
+ fi
+ continue
+ fi
+
+
+ if test "$linkmode" = prog && test "$pass" != link; then
+ newlib_search_path="$newlib_search_path $ladir"
+ deplibs="$lib $deplibs"
+
+ linkalldeplibs=no
+ if test "$link_all_deplibs" != no || test -z "$library_names" ||
+ test "$build_libtool_libs" = no; then
+ linkalldeplibs=yes
+ fi
+
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
+ esac
+ # Need to link against all dependency_libs?
+ if test "$linkalldeplibs" = yes; then
+ deplibs="$deplib $deplibs"
+ else
+ # Need to hardcode shared library paths
+ # or/and link against static libraries
+ newdependency_libs="$deplib $newdependency_libs"
+ fi
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done # for deplib
+ continue
+ fi # $linkmode = prog...
+
+ if test "$linkmode,$pass" = "prog,link"; then
+ if test -n "$library_names" &&
+ { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+ # We need to hardcode the library path
+ if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath " in
+ *" $dir "*) ;;
+ *" $absdir "*) ;;
+ *) temp_rpath="$temp_rpath $dir" ;;
+ esac
+ fi
+
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ fi # $linkmode,$pass = prog,link...
+
+ if test "$alldeplibs" = yes &&
+ { test "$deplibs_check_method" = pass_all ||
+ { test "$build_libtool_libs" = yes &&
+ test -n "$library_names"; }; }; then
+ # We only need to search for static libraries
+ continue
+ fi
+ fi
+
+ link_static=no # Whether the deplib will be linked statically
+ if test -n "$library_names" &&
+ { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+ if test "$installed" = no; then
+ notinst_deplibs="$notinst_deplibs $lib"
+ need_relink=yes
+ fi
+ # This is a shared library
+
+ # Warn about portability, can't link against -module's on
+ # some systems (darwin)
+ if test "$shouldnotlink" = yes && test "$pass" = link ; then
+ $echo
+ if test "$linkmode" = prog; then
+ $echo "*** Warning: Linking the executable $output against the loadable module"
+ else
+ $echo "*** Warning: Linking the shared library $output against the loadable module"
+ fi
+ $echo "*** $linklib is not portable!"
+ fi
+ if test "$linkmode" = lib &&
+ test "$hardcode_into_libs" = yes; then
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ fi
+
+ if test -n "$old_archive_from_expsyms_cmds"; then
+ # figure out the soname
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+ libname=`eval \\$echo \"$libname_spec\"`
+ # use dlname if we got it. it's perfectly good, no?
+ if test -n "$dlname"; then
+ soname="$dlname"
+ elif test -n "$soname_spec"; then
+ # bleh windows
+ case $host in
+ *cygwin* | mingw*)
+ major=`expr $current - $age`
+ versuffix="-$major"
+ ;;
+ esac
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+
+ # Make a new name for the extract_expsyms_cmds to use
+ soroot="$soname"
+ soname=`$echo $soroot | ${SED} -e 's/^.*\///'`
+ newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
+
+ # If the library has no export list, then create one now
+ if test -f "$output_objdir/$soname-def"; then :
+ else
+ $show "extracting exported symbol list from \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ cmds=$extract_expsyms_cmds
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Create $newlib
+ if test -f "$output_objdir/$newlib"; then :; else
+ $show "generating import library for \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ cmds=$old_archive_from_expsyms_cmds
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+ # make sure the library variables are pointing to the new library
+ dir=$output_objdir
+ linklib=$newlib
+ fi # test -n "$old_archive_from_expsyms_cmds"
+
+ if test "$linkmode" = prog || test "$mode" != relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ lib_linked=yes
+ case $hardcode_action in
+ immediate | unsupported)
+ if test "$hardcode_direct" = no; then
+ add="$dir/$linklib"
+ case $host in
+ *-*-sco3.2v5* ) add_dir="-L$dir" ;;
+ *-*-darwin* )
+ # if the lib is a module then we can not link against
+ # it, someone is ignoring the new warnings I added
+ if /usr/bin/file -L $add 2> /dev/null | $EGREP "bundle" >/dev/null ; then
+ $echo "** Warning, lib $linklib is a module, not a shared library"
+ if test -z "$old_library" ; then
+ $echo
+ $echo "** And there doesn't seem to be a static archive available"
+ $echo "** The link will probably fail, sorry"
+ else
+ add="$dir/$old_library"
+ fi
+ fi
+ esac
+ elif test "$hardcode_minus_L" = no; then
+ case $host in
+ *-*-sunos*) add_shlibpath="$dir" ;;
+ esac
+ add_dir="-L$dir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ relink)
+ if test "$hardcode_direct" = yes; then
+ add="$dir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$dir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case "$libdir" in
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ *) lib_linked=no ;;
+ esac
+
+ if test "$lib_linked" != yes; then
+ $echo "$modename: configuration error: unsupported hardcode properties"
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$add_shlibpath"; then
+ case :$compile_shlibpath: in
+ *":$add_shlibpath:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+ esac
+ fi
+ if test "$linkmode" = prog; then
+ test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+ test -n "$add" && compile_deplibs="$add $compile_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ if test "$hardcode_direct" != yes && \
+ test "$hardcode_minus_L" != yes && \
+ test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ fi
+ fi
+ fi
+
+ if test "$linkmode" = prog || test "$mode" = relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ # Finalize command for both is simple: just hardcode it.
+ if test "$hardcode_direct" = yes; then
+ add="$libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$libdir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ add="-l$name"
+ elif test "$hardcode_automatic" = yes; then
+ if test -n "$inst_prefix_dir" &&
+ test -f "$inst_prefix_dir$libdir/$linklib" ; then
+ add="$inst_prefix_dir$libdir/$linklib"
+ else
+ add="$libdir/$linklib"
+ fi
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ add_dir="-L$libdir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case "$libdir" in
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ fi
+
+ if test "$linkmode" = prog; then
+ test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+ test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ fi
+ fi
+ elif test "$linkmode" = prog; then
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test "$hardcode_direct" != unsupported; then
+ test -n "$old_library" && linklib="$old_library"
+ compile_deplibs="$dir/$linklib $compile_deplibs"
+ finalize_deplibs="$dir/$linklib $finalize_deplibs"
+ else
+ compile_deplibs="-l$name -L$dir $compile_deplibs"
+ finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+ fi
+ elif test "$build_libtool_libs" = yes; then
+ # Not a shared library
+ if test "$deplibs_check_method" != pass_all; then
+ # We're trying link a shared library against a static one
+ # but the system doesn't support it.
+
+ # Just print a warning and add the library to dependency_libs so
+ # that the program can be linked against the static library.
+ $echo
+ $echo "*** Warning: This system can not link to static lib archive $lib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have."
+ if test "$module" = yes; then
+ $echo "*** But as you try to build a module library, libtool will still create "
+ $echo "*** a static module, that should work as long as the dlopening application"
+ $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+ if test -z "$global_symbol_pipe"; then
+ $echo
+ $echo "*** However, this would only work if libtool was able to extract symbol"
+ $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ $echo "*** not find such a program. So, this module is probably useless."
+ $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ else
+ convenience="$convenience $dir/$old_library"
+ old_convenience="$old_convenience $dir/$old_library"
+ deplibs="$dir/$old_library $deplibs"
+ link_static=yes
+ fi
+ fi # link shared/static library?
+
+ if test "$linkmode" = lib; then
+ if test -n "$dependency_libs" &&
+ { test "$hardcode_into_libs" != yes ||
+ test "$build_old_libs" = yes ||
+ test "$link_static" = yes; }; then
+ # Extract -R from dependency_libs
+ temp_deplibs=
+ for libdir in $dependency_libs; do
+ case $libdir in
+ -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
+ case " $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) xrpath="$xrpath $temp_xrpath";;
+ esac;;
+ *) temp_deplibs="$temp_deplibs $libdir";;
+ esac
+ done
+ dependency_libs="$temp_deplibs"
+ fi
+
+ newlib_search_path="$newlib_search_path $absdir"
+ # Link against this library
+ test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+ # ... and its dependency_libs
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ newdependency_libs="$deplib $newdependency_libs"
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+
+ if test "$link_all_deplibs" != no; then
+ # Add the search paths of all dependency libraries
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) path="$deplib" ;;
+ *.la)
+ dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$deplib" && dir="."
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+ absdir="$dir"
+ fi
+ ;;
+ esac
+ if grep "^installed=no" $deplib > /dev/null; then
+ path="$absdir/$objdir"
+ else
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test "$absdir" != "$libdir"; then
+ $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
+ fi
+ path="$absdir"
+ fi
+ depdepl=
+ case $host in
+ *-*-darwin*)
+ # we do not want to link against static libs,
+ # but need to link against shared
+ eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+ if test -n "$deplibrary_names" ; then
+ for tmp in $deplibrary_names ; do
+ depdepl=$tmp
+ done
+ if test -f "$path/$depdepl" ; then
+ depdepl="$path/$depdepl"
+ fi
+ # do not add paths which are already there
+ case " $newlib_search_path " in
+ *" $path "*) ;;
+ *) newlib_search_path="$newlib_search_path $path";;
+ esac
+ fi
+ path=""
+ ;;
+ *)
+ path="-L$path"
+ ;;
+ esac
+ ;;
+ -l*)
+ case $host in
+ *-*-darwin*)
+ # Again, we only want to link against shared libraries
+ eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
+ for tmp in $newlib_search_path ; do
+ if test -f "$tmp/lib$tmp_libs.dylib" ; then
+ eval depdepl="$tmp/lib$tmp_libs.dylib"
+ break
+ fi
+ done
+ path=""
+ ;;
+ *) continue ;;
+ esac
+ ;;
+ *) continue ;;
+ esac
+ case " $deplibs " in
+ *" $path "*) ;;
+ *) deplibs="$path $deplibs" ;;
+ esac
+ case " $deplibs " in
+ *" $depdepl "*) ;;
+ *) deplibs="$depdepl $deplibs" ;;
+ esac
+ done
+ fi # link_all_deplibs != no
+ fi # linkmode = lib
+ done # for deplib in $libs
+ dependency_libs="$newdependency_libs"
+ if test "$pass" = dlpreopen; then
+ # Link the dlpreopened libraries before other libraries
+ for deplib in $save_deplibs; do
+ deplibs="$deplib $deplibs"
+ done
+ fi
+ if test "$pass" != dlopen; then
+ if test "$pass" != conv; then
+ # Make sure lib_search_path contains only unique directories.
+ lib_search_path=
+ for dir in $newlib_search_path; do
+ case "$lib_search_path " in
+ *" $dir "*) ;;
+ *) lib_search_path="$lib_search_path $dir" ;;
+ esac
+ done
+ newlib_search_path=
+ fi
+
+ if test "$linkmode,$pass" != "prog,link"; then
+ vars="deplibs"
+ else
+ vars="compile_deplibs finalize_deplibs"
+ fi
+ for var in $vars dependency_libs; do
+ # Add libraries to $var in reverse order
+ eval tmp_libs=\"\$$var\"
+ new_libs=
+ for deplib in $tmp_libs; do
+ # FIXME: Pedantically, this is the right thing to do, so
+ # that some nasty dependency loop isn't accidentally
+ # broken:
+ #new_libs="$deplib $new_libs"
+ # Pragmatically, this seems to cause very few problems in
+ # practice:
+ case $deplib in
+ -L*) new_libs="$deplib $new_libs" ;;
+ -R*) ;;
+ *)
+ # And here is the reason: when a library appears more
+ # than once as an explicit dependence of a library, or
+ # is implicitly linked in more than once by the
+ # compiler, it is considered special, and multiple
+ # occurrences thereof are not removed. Compare this
+ # with having the same library being listed as a
+ # dependency of multiple other libraries: in this case,
+ # we know (pedantically, we assume) the library does not
+ # need to be listed more than once, so we keep only the
+ # last copy. This is not always right, but it is rare
+ # enough that we require users that really mean to play
+ # such unportable linking tricks to link the library
+ # using -Wl,-lname, so that libtool does not consider it
+ # for duplicate removal.
+ case " $specialdeplibs " in
+ *" $deplib "*) new_libs="$deplib $new_libs" ;;
+ *)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$deplib $new_libs" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ tmp_libs=
+ for deplib in $new_libs; do
+ case $deplib in
+ -L*)
+ case " $tmp_libs " in
+ *" $deplib "*) ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ done
+ eval $var=\"$tmp_libs\"
+ done # for var
+ fi
+ # Last step: remove runtime libs from dependency_libs
+ # (they stay in deplibs)
+ tmp_libs=
+ for i in $dependency_libs ; do
+ case " $predeps $postdeps $compiler_lib_search_path " in
+ *" $i "*)
+ i=""
+ ;;
+ esac
+ if test -n "$i" ; then
+ tmp_libs="$tmp_libs $i"
+ fi
+ done
+ dependency_libs=$tmp_libs
+ done # for pass
+ if test "$linkmode" = prog; then
+ dlfiles="$newdlfiles"
+ dlprefiles="$newdlprefiles"
+ fi
+
+ case $linkmode in
+ oldlib)
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+ fi
+
+ # Now set the variables for building old libraries.
+ build_libtool_libs=no
+ oldlibs="$output"
+ objs="$objs$old_deplibs"
+ ;;
+
+ lib)
+ # Make sure we only generate libraries of the form `libNAME.la'.
+ case $outputname in
+ lib*)
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ ;;
+ *)
+ if test "$module" = no; then
+ $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test "$need_lib_prefix" != no; then
+ # Add the "lib" prefix for modules if required
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ else
+ libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ fi
+ ;;
+ esac
+
+ if test -n "$objs"; then
+ if test "$deplibs_check_method" != pass_all; then
+ $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
+ exit $EXIT_FAILURE
+ else
+ $echo
+ $echo "*** Warning: Linking the shared library $output against the non-libtool"
+ $echo "*** objects $objs is not portable!"
+ libobjs="$libobjs $objs"
+ fi
+ fi
+
+ if test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
+ fi
+
+ set dummy $rpath
+ if test "$#" -gt 2; then
+ $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+ fi
+ install_libdir="$2"
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test "$build_libtool_libs" = yes; then
+ # Building a libtool convenience library.
+ # Some compilers have problems with a `.al' extension so
+ # convenience libraries should have the same extension an
+ # archive normally would.
+ oldlibs="$output_objdir/$libname.$libext $oldlibs"
+ build_libtool_libs=convenience
+ build_old_libs=yes
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+ fi
+ else
+
+ # Parse the version information argument.
+ save_ifs="$IFS"; IFS=':'
+ set dummy $vinfo 0 0 0
+ IFS="$save_ifs"
+
+ if test -n "$8"; then
+ $echo "$modename: too many parameters to \`-version-info'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # convert absolute version numbers to libtool ages
+ # this retains compatibility with .la files and attempts
+ # to make the code below a bit more comprehensible
+
+ case $vinfo_number in
+ yes)
+ number_major="$2"
+ number_minor="$3"
+ number_revision="$4"
+ #
+ # There are really only two kinds -- those that
+ # use the current revision as the major version
+ # and those that subtract age and use age as
+ # a minor version. But, then there is irix
+ # which has an extra 1 added just for fun
+ #
+ case $version_type in
+ darwin|linux|osf|windows)
+ current=`expr $number_major + $number_minor`
+ age="$number_minor"
+ revision="$number_revision"
+ ;;
+ freebsd-aout|freebsd-elf|sunos)
+ current="$number_major"
+ revision="$number_minor"
+ age="0"
+ ;;
+ irix|nonstopux)
+ current=`expr $number_major + $number_minor - 1`
+ age="$number_minor"
+ revision="$number_minor"
+ ;;
+ esac
+ ;;
+ no)
+ current="$2"
+ revision="$3"
+ age="$4"
+ ;;
+ esac
+
+ # Check that each of the things are valid numbers.
+ case $current in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $revision in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $age in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ if test "$age" -gt "$current"; then
+ $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Calculate the version variables.
+ major=
+ versuffix=
+ verstring=
+ case $version_type in
+ none) ;;
+
+ darwin)
+ # Like Linux, but with the current version available in
+ # verstring for coding it into the library header
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ # Darwin ld doesn't like 0 for these options...
+ minor_current=`expr $current + 1`
+ verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+ ;;
+
+ freebsd-aout)
+ major=".$current"
+ versuffix=".$current.$revision";
+ ;;
+
+ freebsd-elf)
+ major=".$current"
+ versuffix=".$current";
+ ;;
+
+ irix | nonstopux)
+ major=`expr $current - $age + 1`
+
+ case $version_type in
+ nonstopux) verstring_prefix=nonstopux ;;
+ *) verstring_prefix=sgi ;;
+ esac
+ verstring="$verstring_prefix$major.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test "$loop" -ne 0; do
+ iface=`expr $revision - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring_prefix$major.$iface:$verstring"
+ done
+
+ # Before this point, $major must not contain `.'.
+ major=.$major
+ versuffix="$major.$revision"
+ ;;
+
+ linux)
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ ;;
+
+ osf)
+ major=.`expr $current - $age`
+ versuffix=".$current.$age.$revision"
+ verstring="$current.$age.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test "$loop" -ne 0; do
+ iface=`expr $current - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring:${iface}.0"
+ done
+
+ # Make executables depend on our current version.
+ verstring="$verstring:${current}.0"
+ ;;
+
+ sunos)
+ major=".$current"
+ versuffix=".$current.$revision"
+ ;;
+
+ windows)
+ # Use '-' rather than '.', since we only want one
+ # extension on DOS 8.3 filesystems.
+ major=`expr $current - $age`
+ versuffix="-$major"
+ ;;
+
+ *)
+ $echo "$modename: unknown library version type \`$version_type'" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ # Clear the version info if we defaulted, and they specified a release.
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ case $version_type in
+ darwin)
+ # we can't check for "0.0" in archive_cmds due to quoting
+ # problems, so we reset it completely
+ verstring=
+ ;;
+ *)
+ verstring="0.0"
+ ;;
+ esac
+ if test "$need_version" = no; then
+ versuffix=
+ else
+ versuffix=".0.0"
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test "$avoid_version" = yes && test "$need_version" = no; then
+ major=
+ versuffix=
+ verstring=""
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test "$allow_undefined" = yes; then
+ if test "$allow_undefined_flag" = unsupported; then
+ $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+ build_libtool_libs=no
+ build_old_libs=yes
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag="$no_undefined_flag"
+ fi
+ fi
+
+ if test "$mode" != relink; then
+ # Remove our outputs, but don't remove object files since they
+ # may have been created when compiling PIC objects.
+ removelist=
+ tempremovelist=`$echo "$output_objdir/*"`
+ for p in $tempremovelist; do
+ case $p in
+ *.$objext)
+ ;;
+ $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+ if test "X$precious_files_regex" != "X"; then
+ if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+ then
+ continue
+ fi
+ fi
+ removelist="$removelist $p"
+ ;;
+ *) ;;
+ esac
+ done
+ if test -n "$removelist"; then
+ $show "${rm}r $removelist"
+ $run ${rm}r $removelist
+ fi
+ fi
+
+ # Now set the variables for building old libraries.
+ if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+ oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+ fi
+
+ # Eliminate all temporary directories.
+ for path in $notinst_path; do
+ lib_search_path=`$echo "$lib_search_path " | ${SED} -e 's% $path % %g'`
+ deplibs=`$echo "$deplibs " | ${SED} -e 's% -L$path % %g'`
+ dependency_libs=`$echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'`
+ done
+
+ if test -n "$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ temp_xrpath=
+ for libdir in $xrpath; do
+ temp_xrpath="$temp_xrpath -R$libdir"
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+ fi
+
+ # Make sure dlfiles contains only unique files that won't be dlpreopened
+ old_dlfiles="$dlfiles"
+ dlfiles=
+ for lib in $old_dlfiles; do
+ case " $dlprefiles $dlfiles " in
+ *" $lib "*) ;;
+ *) dlfiles="$dlfiles $lib" ;;
+ esac
+ done
+
+ # Make sure dlprefiles contains only unique files
+ old_dlprefiles="$dlprefiles"
+ dlprefiles=
+ for lib in $old_dlprefiles; do
+ case "$dlprefiles " in
+ *" $lib "*) ;;
+ *) dlprefiles="$dlprefiles $lib" ;;
+ esac
+ done
+
+ if test "$build_libtool_libs" = yes; then
+ if test -n "$rpath"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C library is in the System framework
+ deplibs="$deplibs -framework System"
+ ;;
+ *-*-netbsd*)
+ # Don't link with libc until the a.out ld.so is fixed.
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc due to us having libc/libc_r.
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *)
+ # Add libc to deplibs on all other systems if necessary.
+ if test "$build_libtool_need_lc" = "yes"; then
+ deplibs="$deplibs -lc"
+ fi
+ ;;
+ esac
+ fi
+
+ # Transform deplibs into only deplibs that can be linked in shared.
+ name_save=$name
+ libname_save=$libname
+ release_save=$release
+ versuffix_save=$versuffix
+ major_save=$major
+ # I'm not sure if I'm treating the release correctly. I think
+ # release should show up in the -l (ie -lgmp5) so we don't want to
+ # add it in twice. Is that correct?
+ release=""
+ versuffix=""
+ major=""
+ newdeplibs=
+ droppeddeps=no
+ case $deplibs_check_method in
+ pass_all)
+ # Don't check for shared/static. Everything works.
+ # This might be a little naive. We might want to check
+ # whether the library exists or not. But this is on
+ # osf3 & osf4 and I'm not really sure... Just
+ # implementing what was already the behavior.
+ newdeplibs=$deplibs
+ ;;
+ test_compile)
+ # This code stresses the "libraries are programs" paradigm to its
+ # limits. Maybe even breaks it. We compile a program, linking it
+ # against the deplibs as a proxy for the library. Then we can check
+ # whether they linked in statically or dynamically with ldd.
+ $rm conftest.c
+ cat > conftest.c <<EOF
+ int main() { return 0; }
+EOF
+ $rm conftest
+ $LTCC -o conftest conftest.c $deplibs
+ if test "$?" -eq 0 ; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" -ne "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: dynamic linker does not accept needed library $i."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which I believe you do not have"
+ $echo "*** because a test_compile did reveal that the linker did not use it for"
+ $echo "*** its dynamic dependency list that programs get resolved with at runtime."
+ fi
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ else
+ # Error occurred in the first compile. Let's try to salvage
+ # the situation: Compile a separate program for each library.
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" != "0"; then
+ $rm conftest
+ $LTCC -o conftest conftest.c $i
+ # Did it work?
+ if test "$?" -eq 0 ; then
+ ldd_output=`ldd conftest`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: dynamic linker does not accept needed library $i."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because a test_compile did reveal that the linker did not use this one"
+ $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+ fi
+ fi
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning! Library $i is needed by this library but I was not able to"
+ $echo "*** make it link in! You will probably need to install it or some"
+ $echo "*** library that it depends on before this library will be fully"
+ $echo "*** functional. Installing it before continuing would be even better."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method
+ file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ for a_deplib in $deplibs; do
+ name="`expr $a_deplib : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" != "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ # Follow soft links.
+ if ls -lLd "$potent_lib" 2>/dev/null \
+ | grep " -> " >/dev/null; then
+ continue
+ fi
+ # The statement above tries to avoid entering an
+ # endless loop below, in case of cyclic links.
+ # We might still enter an endless loop, since a link
+ # loop can be closed while we follow links,
+ # but so what?
+ potlib="$potent_lib"
+ while test -h "$potlib" 2>/dev/null; do
+ potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+ case $potliblink in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+ *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+ | ${SED} 10q \
+ | $EGREP "$file_magic_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: linker path does not have real file for library $a_deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ $echo "*** with $libname but no candidates were found. (...for file magic test)"
+ else
+ $echo "*** with $libname and none of the candidates passed a file format test"
+ $echo "*** using a file magic. Last file checked: $potlib"
+ fi
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ match_pattern*)
+ set dummy $deplibs_check_method
+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ for a_deplib in $deplibs; do
+ name="`expr $a_deplib : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test -n "$name" && test "$name" != "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ potlib="$potent_lib" # see symlink-check above in file_magic test
+ if eval $echo \"$potent_lib\" 2>/dev/null \
+ | ${SED} 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: linker path does not have real file for library $a_deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
+ else
+ $echo "*** with $libname and none of the candidates passed a file format test"
+ $echo "*** using a regex pattern. Last file checked: $potlib"
+ fi
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=""
+ tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+ -e 's/ -[LR][^ ]*//g'`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ for i in $predeps $postdeps ; do
+ # can't use Xsed below, because $i might contain '/'
+ tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
+ done
+ fi
+ if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \
+ | grep . >/dev/null; then
+ $echo
+ if test "X$deplibs_check_method" = "Xnone"; then
+ $echo "*** Warning: inter-library dependencies are not supported in this platform."
+ else
+ $echo "*** Warning: inter-library dependencies are not known to be supported."
+ fi
+ $echo "*** All declared inter-library dependencies are being dropped."
+ droppeddeps=yes
+ fi
+ ;;
+ esac
+ versuffix=$versuffix_save
+ major=$major_save
+ release=$release_save
+ libname=$libname_save
+ name=$name_save
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ ;;
+ esac
+
+ if test "$droppeddeps" = yes; then
+ if test "$module" = yes; then
+ $echo
+ $echo "*** Warning: libtool could not satisfy all declared inter-library"
+ $echo "*** dependencies of module $libname. Therefore, libtool will create"
+ $echo "*** a static module, that should work as long as the dlopening"
+ $echo "*** application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ $echo
+ $echo "*** However, this would only work if libtool was able to extract symbol"
+ $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ $echo "*** not find such a program. So, this module is probably useless."
+ $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ else
+ $echo "*** The inter-library dependencies that have been dropped here will be"
+ $echo "*** automatically added whenever a program is linked with this library"
+ $echo "*** or is declared to -dlopen it."
+
+ if test "$allow_undefined" = no; then
+ $echo
+ $echo "*** Since this library must not contain undefined symbols,"
+ $echo "*** because either the platform does not support them or"
+ $echo "*** it was explicitly requested with -no-undefined,"
+ $echo "*** libtool will only create a static version of it."
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ fi
+ fi
+ # Done checking deplibs!
+ deplibs=$newdeplibs
+ fi
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+
+ # Test again, we may have decided not to build it any more
+ if test "$build_libtool_libs" = yes; then
+ if test "$hardcode_into_libs" = yes; then
+ # Hardcode the library paths
+ hardcode_libdirs=
+ dep_rpath=
+ rpath="$finalize_rpath"
+ test "$mode" != relink && rpath="$compile_rpath$rpath"
+ for libdir in $rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ dep_rpath="$dep_rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ if test -n "$hardcode_libdir_flag_spec_ld"; then
+ eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
+ else
+ eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+ fi
+ fi
+ if test -n "$runpath_var" && test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+ fi
+ test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+ fi
+
+ shlibpath="$finalize_shlibpath"
+ test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+ if test -n "$shlibpath"; then
+ eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+ fi
+
+ # Get the real and link names of the library.
+ eval shared_ext=\"$shrext_cmds\"
+ eval library_names=\"$library_names_spec\"
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+
+ if test -n "$soname_spec"; then
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+ if test -z "$dlname"; then
+ dlname=$soname
+ fi
+
+ lib="$output_objdir/$realname"
+ for link
+ do
+ linknames="$linknames $link"
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ cmds=$export_symbols_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ if len=`expr "X$cmd" : ".*"` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ skipped_export=false
+ else
+ # The command line is too long to execute in one step.
+ $show "using reloadable object file for export list..."
+ skipped_export=:
+ fi
+ done
+ IFS="$save_ifs"
+ if test -n "$export_symbols_regex"; then
+ $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+ $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+ $run eval '$mv "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+ fi
+
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+ fi
+
+ tmp_deplibs=
+ for test_deplib in $deplibs; do
+ case " $convenience " in
+ *" $test_deplib "*) ;;
+ *)
+ tmp_deplibs="$tmp_deplibs $test_deplib"
+ ;;
+ esac
+ done
+ deplibs="$tmp_deplibs"
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ libobjs="$libobjs $func_extract_archives_result"
+ fi
+ fi
+
+ if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ linker_flags="$linker_flags $flag"
+ fi
+
+ # Make a backup of the uninstalled library when relinking
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
+ fi
+
+ # Do each of the archive commands.
+ if test "$module" = yes && test -n "$module_cmds" ; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ eval test_cmds=\"$module_expsym_cmds\"
+ cmds=$module_expsym_cmds
+ else
+ eval test_cmds=\"$module_cmds\"
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval test_cmds=\"$archive_expsym_cmds\"
+ cmds=$archive_expsym_cmds
+ else
+ eval test_cmds=\"$archive_cmds\"
+ cmds=$archive_cmds
+ fi
+ fi
+
+ if test "X$skipped_export" != "X:" && len=`expr "X$test_cmds" : ".*"` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ :
+ else
+ # The command line is too long to link in one step, link piecewise.
+ $echo "creating reloadable object files..."
+
+ # Save the value of $output and $libobjs because we want to
+ # use them later. If we have whole_archive_flag_spec, we
+ # want to use save_libobjs as it was before
+ # whole_archive_flag_spec was expanded, because we can't
+ # assume the linker understands whole_archive_flag_spec.
+ # This may have to be revisited, in case too many
+ # convenience libraries get linked in and end up exceeding
+ # the spec.
+ if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ fi
+ save_output=$output
+ output_la=`$echo "X$output" | $Xsed -e "$basename"`
+
+ # Clear the reloadable object creation command queue and
+ # initialize k to one.
+ test_cmds=
+ concat_cmds=
+ objlist=
+ delfiles=
+ last_robj=
+ k=1
+ output=$output_objdir/$output_la-${k}.$objext
+ # Loop over the list of objects to be linked.
+ for obj in $save_libobjs
+ do
+ eval test_cmds=\"$reload_cmds $objlist $last_robj\"
+ if test "X$objlist" = X ||
+ { len=`expr "X$test_cmds" : ".*"` &&
+ test "$len" -le "$max_cmd_len"; }; then
+ objlist="$objlist $obj"
+ else
+ # The command $test_cmds is almost too long, add a
+ # command to the queue.
+ if test "$k" -eq 1 ; then
+ # The first file doesn't have a previous command to add.
+ eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+ else
+ # All subsequent reloadable object files will link in
+ # the last one created.
+ eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
+ fi
+ last_robj=$output_objdir/$output_la-${k}.$objext
+ k=`expr $k + 1`
+ output=$output_objdir/$output_la-${k}.$objext
+ objlist=$obj
+ len=1
+ fi
+ done
+ # Handle the remaining objects by creating one last
+ # reloadable object file. All subsequent reloadable object
+ # files will link in the last one created.
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+
+ if ${skipped_export-false}; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ libobjs=$output
+ # Append the command to create the export file.
+ eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
+ fi
+
+ # Set up a command to remove the reloadable object files
+ # after they are used.
+ i=0
+ while test "$i" -lt "$k"
+ do
+ i=`expr $i + 1`
+ delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
+ done
+
+ $echo "creating a temporary reloadable object file: $output"
+
+ # Loop through the commands generated above and execute them.
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $concat_cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ libobjs=$output
+ # Restore the value of output.
+ output=$save_output
+
+ if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ fi
+ # Expand the library linking commands again to reset the
+ # value of $libobjs for piecewise linking.
+
+ # Do each of the archive commands.
+ if test "$module" = yes && test -n "$module_cmds" ; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ cmds=$module_expsym_cmds
+ else
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ cmds=$archive_expsym_cmds
+ else
+ cmds=$archive_cmds
+ fi
+ fi
+
+ # Append the command to remove the reloadable object files
+ # to the just-reset $cmds.
+ eval cmds=\"\$cmds~\$rm $delfiles\"
+ fi
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+ exit $EXIT_SUCCESS
+ fi
+
+ # Create links to the real library.
+ for linkname in $linknames; do
+ if test "$realname" != "$linkname"; then
+ $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+ fi
+ done
+
+ # If -module or -export-dynamic was specified, set the dlname.
+ if test "$module" = yes || test "$export_dynamic" = yes; then
+ # On all known operating systems, these are identical.
+ dlname="$soname"
+ fi
+ fi
+ ;;
+
+ obj)
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+ fi
+
+ case $output in
+ *.lo)
+ if test -n "$objs$old_deplibs"; then
+ $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ libobj="$output"
+ obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+ ;;
+ *)
+ libobj=
+ obj="$output"
+ ;;
+ esac
+
+ # Delete the old objects.
+ $run $rm $obj $libobj
+
+ # Objects from convenience libraries. This assumes
+ # single-version convenience libraries. Whenever we create
+ # different ones for PIC/non-PIC, this we'll have to duplicate
+ # the extraction.
+ reload_conv_objs=
+ gentop=
+ # reload_cmds runs $LD directly, so let us get rid of
+ # -Wl from whole_archive_flag_spec
+ wl=
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${obj}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ reload_conv_objs="$reload_objs $func_extract_archives_result"
+ fi
+ fi
+
+ # Create the old-style object.
+ reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+ output="$obj"
+ cmds=$reload_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Exit if we aren't doing a library object file.
+ if test -z "$libobj"; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ if test "$build_libtool_libs" != yes; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ # $show "echo timestamp > $libobj"
+ # $run eval "echo timestamp > $libobj" || exit $?
+ exit $EXIT_SUCCESS
+ fi
+
+ if test -n "$pic_flag" || test "$pic_mode" != default; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs $reload_conv_objs"
+ output="$libobj"
+ cmds=$reload_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ prog)
+ case $host in
+ *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
+ esac
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+ fi
+
+ if test "$preload" = yes; then
+ if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
+ test "$dlopen_self_static" = unknown; then
+ $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+ fi
+ fi
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ ;;
+ esac
+
+ case $host in
+ *darwin*)
+ # Don't allow lazy linking, it breaks C++ global constructors
+ if test "$tagname" = CXX ; then
+ compile_command="$compile_command ${wl}-bind_at_load"
+ finalize_command="$finalize_command ${wl}-bind_at_load"
+ fi
+ ;;
+ esac
+
+ compile_command="$compile_command $compile_deplibs"
+ finalize_command="$finalize_command $finalize_deplibs"
+
+ if test -n "$rpath$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath $xrpath; do
+ # This is the magic to use -rpath.
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ fi
+
+ # Now hardcode the library paths
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ case :$dllsearchpath: in
+ *":$libdir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$libdir";;
+ esac
+ ;;
+ esac
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ compile_rpath="$rpath"
+
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ finalize_rpath="$rpath"
+
+ if test -n "$libobjs" && test "$build_old_libs" = yes; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ fi
+
+ dlsyms=
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ if test -n "$NM" && test -n "$global_symbol_pipe"; then
+ dlsyms="${outputname}S.c"
+ else
+ $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+ fi
+ fi
+
+ if test -n "$dlsyms"; then
+ case $dlsyms in
+ "") ;;
+ *.c)
+ # Discover the nlist of each of the dlfiles.
+ nlist="$output_objdir/${outputname}.nm"
+
+ $show "$rm $nlist ${nlist}S ${nlist}T"
+ $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+ # Parse the name list into a source file.
+ $show "creating $output_objdir/$dlsyms"
+
+ test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test "$dlself" = yes; then
+ $show "generating symbol list for \`$output'"
+
+ test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+ # Add our own program objects to the symbol list.
+ progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ for arg in $progfiles; do
+ $show "extracting global C symbols from \`$arg'"
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -n "$exclude_expsyms"; then
+ $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ if test -n "$export_symbols_regex"; then
+ $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ export_symbols="$output_objdir/$outputname.exp"
+ $run $rm $export_symbols
+ $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ else
+ $run eval "${SED} -e 's/\([ ][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+ $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+ $run eval 'mv "$nlist"T "$nlist"'
+ fi
+ fi
+
+ for arg in $dlprefiles; do
+ $show "extracting global C symbols from \`$arg'"
+ name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
+ $run eval '$echo ": $name " >> "$nlist"'
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -z "$run"; then
+ # Make sure we have at least an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ if test -n "$exclude_expsyms"; then
+ $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+ $mv "$nlist"T "$nlist"
+ fi
+
+ # Try sorting and uniquifying the output.
+ if grep -v "^: " < "$nlist" |
+ if sort -k 3 </dev/null >/dev/null 2>&1; then
+ sort -k 3
+ else
+ sort +2
+ fi |
+ uniq > "$nlist"S; then
+ :
+ else
+ grep -v "^: " < "$nlist" > "$nlist"S
+ fi
+
+ if test -f "$nlist"S; then
+ eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+ else
+ $echo '/* NONE */' >> "$output_objdir/$dlsyms"
+ fi
+
+ $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+"
+
+ case $host in
+ *cygwin* | *mingw* )
+ $echo >> "$output_objdir/$dlsyms" "\
+/* DATA imports from DLLs on WIN32 can't be const, because
+ runtime relocations are performed -- see ld's documentation
+ on pseudo-relocs */
+struct {
+"
+ ;;
+ * )
+ $echo >> "$output_objdir/$dlsyms" "\
+const struct {
+"
+ ;;
+ esac
+
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ const char *name;
+ lt_ptr address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+ eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ {0, (lt_ptr) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+ fi
+
+ pic_flag_for_symtable=
+ case $host in
+ # compiling the symbol table file with pic_flag works around
+ # a FreeBSD bug that causes programs to crash when -lm is
+ # linked before any other PIC object. But we must not use
+ # pic_flag when linking with -static. The problem exists in
+ # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+ *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
+ esac;;
+ *-*-hpux*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag";;
+ esac
+ esac
+
+ # Now compile the dynamic symbol file.
+ $show "(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+ $run eval '(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+ # Clean up the generated files.
+ $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+ $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+ # Transform the symbol file into the correct name.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ ;;
+ *)
+ $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ else
+ # We keep going just in case the user didn't refer to
+ # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+
+ # Nullify the symbol file.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+ fi
+
+ if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+ # Replace the output file specification.
+ compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ link_command="$compile_command$compile_rpath"
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ $show "$link_command"
+ $run eval "$link_command"
+ status=$?
+
+ # Delete the generated files.
+ if test -n "$dlsyms"; then
+ $show "$rm $output_objdir/${outputname}S.${objext}"
+ $run $rm "$output_objdir/${outputname}S.${objext}"
+ fi
+
+ exit $status
+ fi
+
+ if test -n "$shlibpath_var"; then
+ # We should set the shlibpath_var
+ rpath=
+ for dir in $temp_rpath; do
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*)
+ # Absolute path.
+ rpath="$rpath$dir:"
+ ;;
+ *)
+ # Relative path: add a thisdir entry.
+ rpath="$rpath\$thisdir/$dir:"
+ ;;
+ esac
+ done
+ temp_rpath="$rpath"
+ fi
+
+ if test -n "$compile_shlibpath$finalize_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ compile_var=
+ finalize_var=
+ if test -n "$runpath_var"; then
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ if test -n "$finalize_perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $finalize_perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test "$no_install" = yes; then
+ # We don't need to create a wrapper script.
+ link_command="$compile_var$compile_command$compile_rpath"
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ # Delete the old output file.
+ $run $rm $output
+ # Link the executable and exit
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+ exit $EXIT_SUCCESS
+ fi
+
+ if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+ $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+ $echo "$modename: \`$output' will be relinked during installation" 1>&2
+ else
+ if test "$fast_install" != no; then
+ link_command="$finalize_var$compile_command$finalize_rpath"
+ if test "$fast_install" = yes; then
+ relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+ else
+ # fast_install is set to needless
+ relink_command=
+ fi
+ else
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+ fi
+ fi
+
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+ # Delete the old output files.
+ $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+
+ # Now create the wrapper script.
+ $show "creating $output"
+
+ # Quote the relink command for shipping.
+ if test -n "$relink_command"; then
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ relink_command="(cd `pwd`; $relink_command)"
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Quote $echo for shipping.
+ if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then
+ case $progpath in
+ [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
+ *) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
+ esac
+ qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+ else
+ qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Only actually do things if our run command is non-null.
+ if test -z "$run"; then
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+ *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
+ esac
+ # test for cygwin because mv fails w/o .exe extensions
+ case $host in
+ *cygwin*)
+ exeext=.exe
+ outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
+ *) exeext= ;;
+ esac
+ case $host in
+ *cygwin* | *mingw* )
+ cwrappersource=`$echo ${objdir}/lt-${outputname}.c`
+ cwrapper=`$echo ${output}.exe`
+ $rm $cwrappersource $cwrapper
+ trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+ cat > $cwrappersource <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+ Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+
+ The $output program cannot be directly executed until all the libtool
+ libraries that it depends on are installed.
+
+ This wrapper executable should never be moved out of the build directory.
+ If it is, it will not operate correctly.
+
+ Currently, it simply execs the wrapper *script* "/bin/sh $output",
+ but could eventually absorb all of the scripts functionality and
+ exec $objdir/$outputname directly.
+*/
+EOF
+ cat >> $cwrappersource<<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef DIR_SEPARATOR
+#define DIR_SEPARATOR '/'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+ defined (__OS2__)
+#define HAVE_DOS_BASED_FILE_SYSTEM
+#ifndef DIR_SEPARATOR_2
+#define DIR_SEPARATOR_2 '\\'
+#endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+ if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+const char *program_name = NULL;
+
+void * xmalloc (size_t num);
+char * xstrdup (const char *string);
+char * basename (const char *name);
+char * fnqualify(const char *path);
+char * strendzap(char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+
+int
+main (int argc, char *argv[])
+{
+ char **newargz;
+ int i;
+
+ program_name = (char *) xstrdup ((char *) basename (argv[0]));
+ newargz = XMALLOC(char *, argc+2);
+EOF
+
+ cat >> $cwrappersource <<EOF
+ newargz[0] = "$SHELL";
+EOF
+
+ cat >> $cwrappersource <<"EOF"
+ newargz[1] = fnqualify(argv[0]);
+ /* we know the script has the same name, without the .exe */
+ /* so make sure newargz[1] doesn't end in .exe */
+ strendzap(newargz[1],".exe");
+ for (i = 1; i < argc; i++)
+ newargz[i+1] = xstrdup(argv[i]);
+ newargz[argc+1] = NULL;
+EOF
+
+ cat >> $cwrappersource <<EOF
+ execv("$SHELL",newargz);
+EOF
+
+ cat >> $cwrappersource <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+ void * p = (void *) malloc (num);
+ if (!p)
+ lt_fatal ("Memory exhausted");
+
+ return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+ return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
+;
+}
+
+char *
+basename (const char *name)
+{
+ const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ /* Skip over the disk name in MSDOS pathnames. */
+ if (isalpha (name[0]) && name[1] == ':')
+ name += 2;
+#endif
+
+ for (base = name; *name; name++)
+ if (IS_DIR_SEPARATOR (*name))
+ base = name + 1;
+ return (char *) base;
+}
+
+char *
+fnqualify(const char *path)
+{
+ size_t size;
+ char *p;
+ char tmp[LT_PATHMAX + 1];
+
+ assert(path != NULL);
+
+ /* Is it qualified already? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ if (isalpha (path[0]) && path[1] == ':')
+ return xstrdup (path);
+#endif
+ if (IS_DIR_SEPARATOR (path[0]))
+ return xstrdup (path);
+
+ /* prepend the current directory */
+ /* doesn't handle '~' */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal ("getcwd failed");
+ size = strlen(tmp) + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */
+ p = XMALLOC(char, size);
+ sprintf(p, "%s%c%s", tmp, DIR_SEPARATOR, path);
+ return p;
+}
+
+char *
+strendzap(char *str, const char *pat)
+{
+ size_t len, patlen;
+
+ assert(str != NULL);
+ assert(pat != NULL);
+
+ len = strlen(str);
+ patlen = strlen(pat);
+
+ if (patlen <= len)
+ {
+ str += len - patlen;
+ if (strcmp(str, pat) == 0)
+ *str = '\0';
+ }
+ return str;
+}
+
+static void
+lt_error_core (int exit_status, const char * mode,
+ const char * message, va_list ap)
+{
+ fprintf (stderr, "%s: %s: ", program_name, mode);
+ vfprintf (stderr, message, ap);
+ fprintf (stderr, ".\n");
+
+ if (exit_status >= 0)
+ exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+ va_list ap;
+ va_start (ap, message);
+ lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+ va_end (ap);
+}
+EOF
+ # we should really use a build-platform specific compiler
+ # here, but OTOH, the wrappers (shell script and this C one)
+ # are only useful if you want to execute the "real" binary.
+ # Since the "real" binary is built for $host, then this
+ # wrapper might as well be built for $host, too.
+ $run $LTCC -s -o $cwrapper $cwrappersource
+ ;;
+ esac
+ $rm $output
+ trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
+
+ $echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='${SED} -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+ # install mode needs the following variable:
+ notinst_deplibs='$notinst_deplibs'
+else
+ # When we are sourced in execute mode, \$file and \$echo are already set.
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ echo=\"$qecho\"
+ file=\"\$0\"
+ # Make sure echo works.
+ if test \"X\$1\" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+ elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+ # Yippee, \$echo works!
+ :
+ else
+ # Restart under the correct shell, and then maybe \$echo will work.
+ exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+ fi
+ fi\
+"
+ $echo >> $output "\
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test \"x\$destdir\" != \"x\$file\"; then
+ case \"\$destdir\" in
+ [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+ *) thisdir=\"\$thisdir/\$destdir\" ;;
+ esac
+ fi
+
+ file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+ done
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test "$fast_install" = yes; then
+ $echo >> $output "\
+ program=lt-'$outputname'$exeext
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" || \\
+ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+
+ if test ! -d \"\$progdir\"; then
+ $mkdir \"\$progdir\"
+ else
+ $rm \"\$progdir/\$file\"
+ fi"
+
+ $echo >> $output "\
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+ if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+ else
+ $echo \"\$relink_command_output\" >&2
+ $rm \"\$progdir/\$file\"
+ exit $EXIT_FAILURE
+ fi
+ fi
+
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+ { $rm \"\$progdir/\$program\";
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+ $rm \"\$progdir/\$file\"
+ fi"
+ else
+ $echo >> $output "\
+ program='$outputname'
+ progdir=\"\$thisdir/$objdir\"
+"
+ fi
+
+ $echo >> $output "\
+
+ if test -f \"\$progdir/\$program\"; then"
+
+ # Export our shlibpath_var if we have one.
+ if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ $echo >> $output "\
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ # The second colon is a workaround for a bug in BeOS R4 sed
+ $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ # fixup the dll searchpath if we need to.
+ if test -n "$dllsearchpath"; then
+ $echo >> $output "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ $echo >> $output "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+"
+ case $host in
+ # Backslashes separate directories on plain windows
+ *-*-mingw | *-*-os2*)
+ $echo >> $output "\
+ exec \$progdir\\\\\$program \${1+\"\$@\"}
+"
+ ;;
+
+ *)
+ $echo >> $output "\
+ exec \$progdir/\$program \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $echo >> $output "\
+ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
+ exit $EXIT_FAILURE
+ fi
+ else
+ # The program doesn't exist.
+ \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
+ \$echo \"This script is just a wrapper for \$program.\" 1>&2
+ $echo \"See the $PACKAGE documentation for more information.\" 1>&2
+ exit $EXIT_FAILURE
+ fi
+fi\
+"
+ chmod +x $output
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+ esac
+
+ # See if we need to build an old-fashioned archive.
+ for oldlib in $oldlibs; do
+
+ if test "$build_libtool_libs" = convenience; then
+ oldobjs="$libobjs_save"
+ addlibs="$convenience"
+ build_libtool_libs=no
+ else
+ if test "$build_libtool_libs" = module; then
+ oldobjs="$libobjs_save"
+ build_libtool_libs=no
+ else
+ oldobjs="$old_deplibs $non_pic_objects"
+ fi
+ addlibs="$old_convenience"
+ fi
+
+ if test -n "$addlibs"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $addlibs
+ oldobjs="$oldobjs $func_extract_archives_result"
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+ cmds=$old_archive_from_new_cmds
+ else
+ # POSIX demands no paths to be encoded in archives. We have
+ # to avoid creating archives with duplicate basenames if we
+ # might have to extract them afterwards, e.g., when creating a
+ # static archive out of a convenience library, or when linking
+ # the entirety of a libtool archive into another (currently
+ # not supported by libtool).
+ if (for obj in $oldobjs
+ do
+ $echo "X$obj" | $Xsed -e 's%^.*/%%'
+ done | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "copying selected object files to avoid basename conflicts..."
+
+ if test -z "$gentop"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "$mkdir $gentop"
+ $run $mkdir "$gentop"
+ status=$?
+ if test "$status" -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ fi
+
+ save_oldobjs=$oldobjs
+ oldobjs=
+ counter=1
+ for obj in $save_oldobjs
+ do
+ objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+ case " $oldobjs " in
+ " ") oldobjs=$obj ;;
+ *[\ /]"$objbase "*)
+ while :; do
+ # Make sure we don't pick an alternate name that also
+ # overlaps.
+ newobj=lt$counter-$objbase
+ counter=`expr $counter + 1`
+ case " $oldobjs " in
+ *[\ /]"$newobj "*) ;;
+ *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+ esac
+ done
+ $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+ $run ln "$obj" "$gentop/$newobj" ||
+ $run cp "$obj" "$gentop/$newobj"
+ oldobjs="$oldobjs $gentop/$newobj"
+ ;;
+ *) oldobjs="$oldobjs $obj" ;;
+ esac
+ done
+ fi
+
+ eval cmds=\"$old_archive_cmds\"
+
+ if len=`expr "X$cmds" : ".*"` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ cmds=$old_archive_cmds
+ else
+ # the command line is too long to link in one step, link in parts
+ $echo "using piecewise archive linking..."
+ save_RANLIB=$RANLIB
+ RANLIB=:
+ objlist=
+ concat_cmds=
+ save_oldobjs=$oldobjs
+
+ # Is there a better way of finding the last object in the list?
+ for obj in $save_oldobjs
+ do
+ last_oldobj=$obj
+ done
+ for obj in $save_oldobjs
+ do
+ oldobjs="$objlist $obj"
+ objlist="$objlist $obj"
+ eval test_cmds=\"$old_archive_cmds\"
+ if len=`expr "X$test_cmds" : ".*"` &&
+ test "$len" -le "$max_cmd_len"; then
+ :
+ else
+ # the above command should be used before it gets too long
+ oldobjs=$objlist
+ if test "$obj" = "$last_oldobj" ; then
+ RANLIB=$save_RANLIB
+ fi
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+ objlist=
+ fi
+ done
+ RANLIB=$save_RANLIB
+ oldobjs=$objlist
+ if test "X$oldobjs" = "X" ; then
+ eval cmds=\"\$concat_cmds\"
+ else
+ eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+ fi
+ fi
+ fi
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ eval cmd=\"$cmd\"
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$generated"; then
+ $show "${rm}r$generated"
+ $run ${rm}r$generated
+ fi
+
+ # Now create the libtool archive.
+ case $output in
+ *.la)
+ old_library=
+ test "$build_old_libs" = yes && old_library="$libname.$libext"
+ $show "creating $output"
+
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ # Quote the link command for shipping.
+ relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ if test "$hardcode_automatic" = yes ; then
+ relink_command=
+ fi
+
+
+ # Only create the output if not a dry run.
+ if test -z "$run"; then
+ for installed in no yes; do
+ if test "$installed" = yes; then
+ if test -z "$install_libdir"; then
+ break
+ fi
+ output="$output_objdir/$outputname"i
+ # Replace all uninstalled libtool libraries with the installed ones
+ newdependency_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ *.la)
+ name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdependency_libs="$newdependency_libs $libdir/$name"
+ ;;
+ *) newdependency_libs="$newdependency_libs $deplib" ;;
+ esac
+ done
+ dependency_libs="$newdependency_libs"
+ newdlfiles=
+ for lib in $dlfiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdlfiles="$newdlfiles $libdir/$name"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdlprefiles="$newdlprefiles $libdir/$name"
+ done
+ dlprefiles="$newdlprefiles"
+ else
+ newdlfiles=
+ for lib in $dlfiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ newdlfiles="$newdlfiles $abs"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ newdlprefiles="$newdlprefiles $abs"
+ done
+ dlprefiles="$newdlprefiles"
+ fi
+ $rm $output
+ # place dlname in correct position for cygwin
+ tdlname=$dlname
+ case $host,$output,$installed,$module,$dlname in
+ *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+ esac
+ $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+ if test "$installed" = no && test "$need_relink" = yes; then
+ $echo >> $output "\
+relink_command=\"$relink_command\""
+ fi
+ done
+ fi
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+ $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
+ ;;
+ esac
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool install mode
+ install)
+ modename="$modename: install"
+
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+ # Allow the use of GNU shtool's install command.
+ $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then
+ # Aesthetically quote it.
+ arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$arg "
+ arg="$1"
+ shift
+ else
+ install_prog=
+ arg="$nonopt"
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog$arg"
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=no
+ stripme=
+ for arg
+ do
+ if test -n "$dest"; then
+ files="$files $dest"
+ dest="$arg"
+ continue
+ fi
+
+ case $arg in
+ -d) isdir=yes ;;
+ -f) prev="-f" ;;
+ -g) prev="-g" ;;
+ -m) prev="-m" ;;
+ -o) prev="-o" ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*) ;;
+
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ prev=
+ else
+ dest="$arg"
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog $arg"
+ done
+
+ if test -z "$install_prog"; then
+ $echo "$modename: you must specify an install program" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prev' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ $echo "$modename: no file or destination specified" 1>&2
+ else
+ $echo "$modename: you must specify a destination" 1>&2
+ fi
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Strip any trailing slash from the destination.
+ dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=yes
+ if test "$isdir" = yes; then
+ destdir="$dest"
+ destname=
+ else
+ destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$destdir" = "X$dest" && destdir=.
+ destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files
+ if test "$#" -gt 2; then
+ $echo "$modename: \`$dest' is not a directory" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ fi
+ case $destdir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ for file in $files; do
+ case $file in
+ *.lo) ;;
+ *)
+ $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case $file in
+ *.$libext)
+ # Do the static libraries later.
+ staticlibs="$staticlibs $file"
+ ;;
+
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ library_names=
+ old_library=
+ relink_command=
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) current_libdirs="$current_libdirs $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) future_libdirs="$future_libdirs $libdir" ;;
+ esac
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
+ test "X$dir" = "X$file/" && dir=
+ dir="$dir$objdir"
+
+ if test -n "$relink_command"; then
+ # Determine the prefix the user has applied to our future dir.
+ inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
+ # are installed to the same prefix.
+ # At present, this check doesn't affect windows .dll's that
+ # are installed into $libdir/../bin (currently, that works fine)
+ # but it's something to keep an eye on.
+ if test "$inst_prefix_dir" = "$destdir"; then
+ $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$inst_prefix_dir"; then
+ # Stick the inst_prefix_dir data into the link command.
+ relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+ else
+ relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+ fi
+
+ $echo "$modename: warning: relinking \`$file'" 1>&2
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ fi
+
+ # See the names of the shared library.
+ set dummy $library_names
+ if test -n "$2"; then
+ realname="$2"
+ shift
+ shift
+
+ srcname="$realname"
+ test -n "$relink_command" && srcname="$realname"T
+
+ # Install the shared library and build the symlinks.
+ $show "$install_prog $dir/$srcname $destdir/$realname"
+ $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
+ if test -n "$stripme" && test -n "$striplib"; then
+ $show "$striplib $destdir/$realname"
+ $run eval "$striplib $destdir/$realname" || exit $?
+ fi
+
+ if test "$#" -gt 0; then
+ # Delete the old symlinks, and create new ones.
+ for linkname
+ do
+ if test "$linkname" != "$realname"; then
+ $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+ fi
+ done
+ fi
+
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ cmds=$postinstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Install the pseudo-library for information purposes.
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ instname="$dir/$name"i
+ $show "$install_prog $instname $destdir/$name"
+ $run eval "$install_prog $instname $destdir/$name" || exit $?
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case $destfile in
+ *.lo)
+ staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+ ;;
+ *.$objext)
+ staticdest="$destfile"
+ destfile=
+ ;;
+ *)
+ $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ if test -n "$destfile"; then
+ $show "$install_prog $file $destfile"
+ $run eval "$install_prog $file $destfile" || exit $?
+ fi
+
+ # Install the old object if enabled.
+ if test "$build_old_libs" = yes; then
+ # Deduce the name of the old-style object file.
+ staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+ $show "$install_prog $staticobj $staticdest"
+ $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+
+ *)
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # If the file is missing, and there is a .exe on the end, strip it
+ # because it is most likely a libtool script we actually want to
+ # install
+ stripped_ext=""
+ case $file in
+ *.exe)
+ if test ! -f "$file"; then
+ file=`$echo $file|${SED} 's,.exe$,,'`
+ stripped_ext=".exe"
+ fi
+ ;;
+ esac
+
+ # Do a test to see if this is really a libtool program.
+ case $host in
+ *cygwin*|*mingw*)
+ wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
+ ;;
+ *)
+ wrapper=$file
+ ;;
+ esac
+ if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
+ notinst_deplibs=
+ relink_command=
+
+ # To insure that "foo" is sourced, and not "foo.exe",
+ # finese the cygwin/MSYS system by explicitly sourcing "foo."
+ # which disallows the automatic-append-.exe behavior.
+ case $build in
+ *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
+ *) wrapperdot=${wrapper} ;;
+ esac
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . ${wrapperdot} ;;
+ *) . ./${wrapperdot} ;;
+ esac
+
+ # Check the variables that should have been set.
+ if test -z "$notinst_deplibs"; then
+ $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ finalize=yes
+ for lib in $notinst_deplibs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ # If there is no directory component, then add one.
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ fi
+ libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+ finalize=no
+ fi
+ done
+
+ relink_command=
+ # To insure that "foo" is sourced, and not "foo.exe",
+ # finese the cygwin/MSYS system by explicitly sourcing "foo."
+ # which disallows the automatic-append-.exe behavior.
+ case $build in
+ *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
+ *) wrapperdot=${wrapper} ;;
+ esac
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . ${wrapperdot} ;;
+ *) . ./${wrapperdot} ;;
+ esac
+
+ outputname=
+ if test "$fast_install" = no && test -n "$relink_command"; then
+ if test "$finalize" = yes && test -z "$run"; then
+ tmpdir="/tmp"
+ test -n "$TMPDIR" && tmpdir="$TMPDIR"
+ tmpdir="$tmpdir/libtool-$$"
+ save_umask=`umask`
+ umask 0077
+ if $mkdir "$tmpdir"; then
+ umask $save_umask
+ else
+ umask $save_umask
+ $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
+ continue
+ fi
+ file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
+ outputname="$tmpdir/$file"
+ # Replace the output file specification.
+ relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ ${rm}r "$tmpdir"
+ continue
+ fi
+ file="$outputname"
+ else
+ $echo "$modename: warning: cannot relink \`$file'" 1>&2
+ fi
+ else
+ # Install the binary that we compiled earlier.
+ file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ # remove .exe since cygwin /usr/bin/install will append another
+ # one anyways
+ case $install_prog,$host in
+ */usr/bin/install*,*cygwin*)
+ case $file:$destfile in
+ *.exe:*.exe)
+ # this is ok
+ ;;
+ *.exe:*)
+ destfile=$destfile.exe
+ ;;
+ *:*.exe)
+ destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
+ ;;
+ esac
+ ;;
+ esac
+ $show "$install_prog$stripme $file $destfile"
+ $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+ test -n "$outputname" && ${rm}r "$tmpdir"
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+ # Set up the ranlib parameters.
+ oldlib="$destdir/$name"
+
+ $show "$install_prog $file $oldlib"
+ $run eval "$install_prog \$file \$oldlib" || exit $?
+
+ if test -n "$stripme" && test -n "$old_striplib"; then
+ $show "$old_striplib $oldlib"
+ $run eval "$old_striplib $oldlib" || exit $?
+ fi
+
+ # Do each command in the postinstall commands.
+ cmds=$old_postinstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$future_libdirs"; then
+ $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+ fi
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ test -n "$run" && current_libdirs=" -n$current_libdirs"
+ exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+ else
+ exit $EXIT_SUCCESS
+ fi
+ ;;
+
+ # libtool finish mode
+ finish)
+ modename="$modename: finish"
+ libdirs="$nonopt"
+ admincmds=
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for dir
+ do
+ libdirs="$libdirs $dir"
+ done
+
+ for libdir in $libdirs; do
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ cmds=$finish_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || admincmds="$admincmds
+ $cmd"
+ done
+ IFS="$save_ifs"
+ fi
+ if test -n "$finish_eval"; then
+ # Do the single finish_eval.
+ eval cmds=\"$finish_eval\"
+ $run eval "$cmds" || admincmds="$admincmds
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ test "$show" = : && exit $EXIT_SUCCESS
+
+ $echo "----------------------------------------------------------------------"
+ $echo "Libraries have been installed in:"
+ for libdir in $libdirs; do
+ $echo " $libdir"
+ done
+ $echo
+ $echo "If you ever happen to want to link against installed libraries"
+ $echo "in a given directory, LIBDIR, you must either use libtool, and"
+ $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+ $echo "flag during linking and do at least one of the following:"
+ if test -n "$shlibpath_var"; then
+ $echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
+ $echo " during execution"
+ fi
+ if test -n "$runpath_var"; then
+ $echo " - add LIBDIR to the \`$runpath_var' environment variable"
+ $echo " during linking"
+ fi
+ if test -n "$hardcode_libdir_flag_spec"; then
+ libdir=LIBDIR
+ eval flag=\"$hardcode_libdir_flag_spec\"
+
+ $echo " - use the \`$flag' linker flag"
+ fi
+ if test -n "$admincmds"; then
+ $echo " - have your system administrator run these commands:$admincmds"
+ fi
+ if test -f /etc/ld.so.conf; then
+ $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+ fi
+ $echo
+ $echo "See any operating system documentation about shared libraries for"
+ $echo "more information, such as the ld(1) and ld.so(8) manual pages."
+ $echo "----------------------------------------------------------------------"
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool execute mode
+ execute)
+ modename="$modename: execute"
+
+ # The first argument is the command name.
+ cmd="$nonopt"
+ if test -z "$cmd"; then
+ $echo "$modename: you must specify a COMMAND" 1>&2
+ $echo "$help"
+ exit $EXIT_FAILURE
+ fi
+
+ # Handle -dlopen flags immediately.
+ for file in $execute_dlfiles; do
+ if test ! -f "$file"; then
+ $echo "$modename: \`$file' is not a file" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ dir=
+ case $file in
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+ continue
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+
+ if test -f "$dir/$objdir/$dlname"; then
+ dir="$dir/$objdir"
+ else
+ $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ ;;
+
+ *)
+ $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir="$absdir"
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic="$magic"
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case $file in
+ -*) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+ if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+ args="$args \"$file\""
+ done
+
+ if test -z "$run"; then
+ if test -n "$shlibpath_var"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+ fi
+
+ # Restore saved environment variables
+ if test "${save_LC_ALL+set}" = set; then
+ LC_ALL="$save_LC_ALL"; export LC_ALL
+ fi
+ if test "${save_LANG+set}" = set; then
+ LANG="$save_LANG"; export LANG
+ fi
+
+ # Now prepare to actually exec the command.
+ exec_cmd="\$cmd$args"
+ else
+ # Display what would be done.
+ if test -n "$shlibpath_var"; then
+ eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+ $echo "export $shlibpath_var"
+ fi
+ $echo "$cmd$args"
+ exit $EXIT_SUCCESS
+ fi
+ ;;
+
+ # libtool clean and uninstall mode
+ clean | uninstall)
+ modename="$modename: $mode"
+ rm="$nonopt"
+ files=
+ rmforce=
+ exit_status=0
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ for arg
+ do
+ case $arg in
+ -f) rm="$rm $arg"; rmforce=yes ;;
+ -*) rm="$rm $arg" ;;
+ *) files="$files $arg" ;;
+ esac
+ done
+
+ if test -z "$rm"; then
+ $echo "$modename: you must specify an RM program" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ rmdirs=
+
+ origobjdir="$objdir"
+ for file in $files; do
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$file"; then
+ dir=.
+ objdir="$origobjdir"
+ else
+ objdir="$dir/$origobjdir"
+ fi
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ test "$mode" = uninstall && objdir="$dir"
+
+ # Remember objdir for removal later, being careful to avoid duplicates
+ if test "$mode" = clean; then
+ case " $rmdirs " in
+ *" $objdir "*) ;;
+ *) rmdirs="$rmdirs $objdir" ;;
+ esac
+ fi
+
+ # Don't error if the file doesn't exist and rm -f was used.
+ if (test -L "$file") >/dev/null 2>&1 \
+ || (test -h "$file") >/dev/null 2>&1 \
+ || test -f "$file"; then
+ :
+ elif test -d "$file"; then
+ exit_status=1
+ continue
+ elif test "$rmforce" = yes; then
+ continue
+ fi
+
+ rmfiles="$file"
+
+ case $name in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ . $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ rmfiles="$rmfiles $objdir/$n"
+ done
+ test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+ test "$mode" = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+
+ if test "$mode" = uninstall; then
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ cmds=$postuninstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test "$?" -ne 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ cmds=$old_postuninstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test "$?" -ne 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
+ IFS="$save_ifs"
+ fi
+ # FIXME: should reinstall the best remaining shared library.
+ fi
+ fi
+ ;;
+
+ *.lo)
+ # Possibly a libtool object, so verify it.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+
+ # Read the .lo file
+ . $dir/$name
+
+ # Add PIC object to the list of files to remove.
+ if test -n "$pic_object" \
+ && test "$pic_object" != none; then
+ rmfiles="$rmfiles $dir/$pic_object"
+ fi
+
+ # Add non-PIC object to the list of files to remove.
+ if test -n "$non_pic_object" \
+ && test "$non_pic_object" != none; then
+ rmfiles="$rmfiles $dir/$non_pic_object"
+ fi
+ fi
+ ;;
+
+ *)
+ if test "$mode" = clean ; then
+ noexename=$name
+ case $file in
+ *.exe)
+ file=`$echo $file|${SED} 's,.exe$,,'`
+ noexename=`$echo $name|${SED} 's,.exe$,,'`
+ # $file with .exe has already been added to rmfiles,
+ # add $file without .exe
+ rmfiles="$rmfiles $file"
+ ;;
+ esac
+ # Do a test to see if this is a libtool program.
+ if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ relink_command=
+ . $dir/$noexename
+
+ # note $name still contains .exe if it was in $file originally
+ # as does the version of $file that was added into $rmfiles
+ rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+ if test "$fast_install" = yes && test -n "$relink_command"; then
+ rmfiles="$rmfiles $objdir/lt-$name"
+ fi
+ if test "X$noexename" != "X$name" ; then
+ rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+ fi
+ fi
+ fi
+ ;;
+ esac
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles || exit_status=1
+ done
+ objdir="$origobjdir"
+
+ # Try to remove the ${objdir}s in the directories where we deleted files
+ for dir in $rmdirs; do
+ if test -d "$dir"; then
+ $show "rmdir $dir"
+ $run rmdir $dir >/dev/null 2>&1
+ fi
+ done
+
+ exit $exit_status
+ ;;
+
+ "")
+ $echo "$modename: you must specify a MODE" 1>&2
+ $echo "$generic_help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ if test -z "$exec_cmd"; then
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$generic_help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+fi # test -z "$show_help"
+
+if test -n "$exec_cmd"; then
+ eval exec $exec_cmd
+ exit $EXIT_FAILURE
+fi
+
+# We need to display help for each of the modes.
+case $mode in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+ --config show all configuration variables
+ --debug enable verbose shell tracing
+-n, --dry-run display commands without modifying any files
+ --features display basic configuration information and exit
+ --finish same as \`--mode=finish'
+ --help display this help message and exit
+ --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
+ --quiet same as \`--silent'
+ --silent don't print informational messages
+ --tag=TAG use configuration variables from tag TAG
+ --version print version information
+
+MODE must be one of the following:
+
+ clean remove files from the build directory
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE.
+
+Report bugs to <bug-libtool@gnu.org>."
+ exit $EXIT_SUCCESS
+ ;;
+
+clean)
+ $echo \
+"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+compile)
+ $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+ -o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -prefer-pic try to building PIC objects only
+ -prefer-non-pic try to building non-PIC objects only
+ -static always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+ ;;
+
+execute)
+ $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+ ;;
+
+finish)
+ $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the \`--dry-run' option if you just want to see what would be executed."
+ ;;
+
+install)
+ $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+ ;;
+
+link)
+ $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -avoid-version do not add a version suffix if possible
+ -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -export-symbols SYMFILE
+ try to export only the symbols listed in SYMFILE
+ -export-symbols-regex REGEX
+ try to export only the symbols matching REGEX
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -module build a library that can dlopened
+ -no-fast-install disable the fast-install mode
+ -no-install link a not-installable executable
+ -no-undefined declare that a library does not refer to external symbols
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -objectlist FILE Use a list of object files found in FILE to specify objects
+ -precious-files-regex REGEX
+ don't remove output files matching REGEX
+ -release RELEASE specify package release information
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
+ -static do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename. Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+ ;;
+
+uninstall)
+ $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+*)
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+esac
+
+$echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit $?
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries. Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them. This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration. But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) $echo no;; *) $echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/Build/source/libs/zziplib/uses/missing b/Build/source/libs/zziplib/uses/missing
new file mode 100755
index 00000000000..5f9da90636f
--- /dev/null
+++ b/Build/source/libs/zziplib/uses/missing
@@ -0,0 +1,265 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+run=:
+
+case "$1" in
+--run)
+ # Try to run requested program, and just exit if it succeeds.
+ run=
+ shift
+ "$@" && exit 0
+ ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case "$1" in
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+ --run try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ help2man touch the output file
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ tar try tar, gnutar, gtar, then tar without non-portable flags
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing 0.3 - GNU automake"
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+ aclocal)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acinclude.m4' or \`configure.in'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`configure.in'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acconfig.h' or \`configure.in'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case "$f" in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f y.tab.h ]; then
+ echo >y.tab.h
+ fi
+ if [ ! -f y.tab.c ]; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f lex.yy.c ]; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ help2man)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a dependency of a manual page. You may need the
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
+
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
+ fi
+ if [ -f "$file" ]; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo ".ab help2man is required to generate this page"
+ exit 1
+ fi
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+ fi
+ touch $file
+ ;;
+
+ tar)
+ shift
+ if test -n "$run"; then
+ echo 1>&2 "ERROR: \`tar' requires --run"
+ exit 1
+ fi
+
+ # We have already tried tar in the generic part.
+ # Look for gnutar/gtar before invocation to avoid ugly error
+ # messages.
+ if (gnutar --version > /dev/null 2>&1); then
+ gnutar ${1+"$@"} && exit 0
+ fi
+ if (gtar --version > /dev/null 2>&1); then
+ gtar ${1+"$@"} && exit 0
+ fi
+ firstarg="$1"
+ if shift; then
+ case "$firstarg" in
+ *o*)
+ firstarg=`echo "$firstarg" | sed s/o//`
+ tar "$firstarg" ${1+"$@"} && exit 0
+ ;;
+ esac
+ case "$firstarg" in
+ *h*)
+ firstarg=`echo "$firstarg" | sed s/h//`
+ tar "$firstarg" ${1+"$@"} && exit 0
+ ;;
+ esac
+ fi
+
+ echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+ You may want to install GNU tar or Free paxutils, or check the
+ command line arguments."
+ exit 1
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+ system. You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequirements for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/Build/source/libs/zziplib/uses/mkinstalldirs b/Build/source/libs/zziplib/uses/mkinstalldirs
new file mode 100755
index 00000000000..0a4bfabbae1
--- /dev/null
+++ b/Build/source/libs/zziplib/uses/mkinstalldirs
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.1.1.1 2001/07/22 21:03:38 guidod Exp $
+
+errstatus=0
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/Build/source/libs/zziplib/zzip/Makefile b/Build/source/libs/zziplib/zzip/Makefile
new file mode 100644
index 00000000000..51828cab270
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/Makefile
@@ -0,0 +1,22 @@
+
+top_srcdir = ../../../../src/libs/zziplib
+srcdir = $(top_srcdir)/zzip
+
+CC = gcc
+AR = ar cru
+RANLIB = ranlib
+
+OBJECTS =dir.o err.o fetch.o file.o info.o memdisk.o mmapped.o \
+ plugin.o stat.o write.o zip.o
+
+_CFLAGS = -DHAVE_CONFIG_H -I.. -I../../../../src/libs/zziplib -I../../../../src/libs/zlib -Wall
+
+XCFLAGS = $(_CFLAGS)
+
+all: $(OBJECTS)
+ $(AR) libzzip.a $(OBJECTS)
+ $(RANLIB) libzzip.a
+
+%.o: $(srcdir)/%.c
+ $(CC) $(CFLAGS) $(XCFLAGS) -c $< -o $@
+
diff --git a/Build/source/libs/zziplib/zzip/Makefile.am b/Build/source/libs/zziplib/zzip/Makefile.am
new file mode 100644
index 00000000000..95fb8f17f78
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/Makefile.am
@@ -0,0 +1,142 @@
+AUTOMAKE_OPTIONS = 1.5 foreign
+AUTOTOOL_VERSION=autoconf-2.52 automake-1.5 libtool-1.4.2
+DEFAULT_INCLUDES = # nothing - no default of -I. -I$(srcdir)
+DEFS = @DEFS@ -I$(top_builddir) -I$(top_srcdir) # also for automake 1.4
+
+lib_LTLIBRARIES = libzzip.la libzzipmmapped.la libzzipfseeko.la
+zzipdir = ${includedir}/zzip
+zzip_HEADERS = $(libzzip_la_headers) \
+ $(libzzipmmapped_la_headers) \
+ $(libzzipfseeko_la_headers)
+noinst_HEADERS = __debug.h __hints.h __mmap.h __dirent.h __fnmatch.h
+#
+VERSION_INFO=@VERSION_INFO@
+RELEASE_INFO=@RELEASE_INFO@
+THREAD_SAFE=@THREAD_SAFE@
+#
+
+libzzip_la_SOURCES = \
+ zip.c \
+ file.c \
+ dir.c \
+ stat.c \
+ info.c \
+ err.c \
+ plugin.c \
+ write.c \
+ fetch.c
+libzzip_la_headers = \
+ stdint.h \
+ file.h \
+ plugin.h \
+ lib.h \
+ zzip.h \
+ fetch.h \
+ format.h \
+ info.h \
+ autoconf.h \
+ types.h \
+ conf.h \
+ _config.h \
+ _msvc.h
+libzzip_la_LDFLAGS= @ZZIPLIB_LDFLAGS@ $(RELEASE_INFO) $(VERSION_INFO) \
+ $(THREAD_SAFE)
+libzzip_la_LIBADD= -lz @RESOLVES@
+
+libzzipmmapped_la_SOURCES = mmapped.c memdisk.c fetch.c
+libzzipmmapped_la_headers = mmapped.h memdisk.h fetch.h
+libzzipmmapped_la_LDFLAGS= @ZZIPLIB_LDFLAGS@ $(RELEASE_INFO) $(VERSION_INFO) \
+ $(THREAD_SAFE)
+libzzipmmapped_la_LIBADD= -lz @RESOLVES@
+
+libzzipfseeko_la_SOURCES = fseeko.c fetch.c
+libzzipfseeko_la_headers = fseeko.h fetch.h
+libzzipfseeko_la_LDFLAGS= @ZZIPLIB_LDFLAGS@ $(RELEASE_INFO) $(VERSION_INFO) \
+ $(THREAD_SAFE)
+libzzipfseeko_la_LIBADD= -lz @RESOLVES@
+
+WCC10_DIST = zziplib.wpj
+WCC10_CLEAN = *.obj *.lk1 *.mk1 *.mk *.sym *.tgt
+
+EXTRA_DIST = $(WCC10_DIST) _msvc.sed
+CONFIG_CLEAN_FILES = _config.h
+MAINTAINERCLEANFILES = _msvc.h
+CLEANFILES = $(WCC10_CLEAN) *.pc *.omf
+
+# here is some backward compatibility with version 0.10.* of zziplib
+install-data-local : install-zzipHEADERS
+ echo '#ifndef ZZIP_WARNING' > $(DESTDIR)$(includedir)/zzip.h
+ echo '#define ZZIP_WARNING 1' >>$(DESTDIR)$(includedir)/zzip.h
+ echo '#ifdef __GNUC__' >>$(DESTDIR)$(includedir)/zzip.h
+ echo '#warning do no not use <zzip.h>, update to include <zzip/lib.h>'\
+ >>$(DESTDIR)$(includedir)/zzip.h
+ echo '#else' >>$(DESTDIR)$(includedir)/zzip.h
+ echo '#error do no not use <zzip.h>, update to include <zzip/lib.h>'\
+ >>$(DESTDIR)$(includedir)/zzip.h
+ echo '#endif' >>$(DESTDIR)$(includedir)/zzip.h
+ echo '#endif' >>$(DESTDIR)$(includedir)/zzip.h
+ echo '#include "zzip/lib.h"' >>$(DESTDIR)$(includedir)/zzip.h
+ sed -e 's|zzip.h|zziplib.h|' -e 's|zzip/lib.h|zzip/zzip.h|' \
+ $(DESTDIR)$(includedir)/zzip.h >$(DESTDIR)$(includedir)/zziplib.h
+ sed -e 's|zzip.h|zzip-io.h|' -e 's|zzip/lib.h|zzip/plugin.h|' \
+ $(DESTDIR)$(includedir)/zzip.h >$(DESTDIR)$(includedir)/zzip-io.h
+
+install-exec-local:
+ @ for i in . $(DESTDIR)$(libdir)/libzzip*.so.13 \
+ ; do test -d $$i && continue ; lib=`basename "$$i" .so.13` \
+ ; echo "$(DESTDIR)$(libdir): ln -s $$lib.so.13 $$lib.so.10" \
+ ; (cd $(DESTDIR)$(libdir) && ln -s $$lib.so.13 $$lib.so.10) \
+ ; echo "$(DESTDIR)$(libdir): ln -s $$lib.so.13 $$lib.so.11" \
+ ; (cd $(DESTDIR)$(libdir) && ln -s $$lib.so.13 $$lib.so.11) \
+ ; echo "$(DESTDIR)$(libdir): ln -s $$lib.so.13 $$lib.so.12" \
+ ; (cd $(DESTDIR)$(libdir) && ln -s $$lib.so.13 $$lib.so.12) \
+ ; done ; true
+
+uninstall-local :
+ (cd $(DESTDIR)$(includedir) && rm zziplib.h zzip.h zzip-io.h)
+
+
+# ----------------------------------------------------------------------
+pkgconfigdir=$(libdir)/pkgconfig
+pkgconfig_HEADERS= zzip-zlib-config.pc zziplib.pc \
+ zzipmmapped.pc zzipfseeko.pc
+
+zziplib.pc : Makefile
+ (cd .. && sh config.status zzip/zziplib.pc)
+
+zzip-zlib-config.pc : Makefile
+ @ echo "zlib_libs=@ZLIB_LDIR@ -lz" >$@
+ @ echo "zlib_cflags=@ZLIB_INCL@" >>$@
+ @ echo " " >>$@
+ @ echo "Name: zzip-zlib-config" >>$@
+ @ echo "Version: @ZLIB_VERSION@" >>$@
+ @ echo "Description: ZLib Config (for ZZipLib)" >>$@
+ echo 'Libs: $${zlib_libs}' >>$@
+ echo 'Cflags: $${zlib_cflags}' >>$@
+
+zzipmmapped.pc : zziplib.pc
+ sed -e 's/-lzzip/-lzzipmmapped/' -e 's/zziplib/zzipmmapped/' \
+ zziplib.pc >$@
+zzipfseeko.pc : zziplib.pc
+ sed -e 's/-lzzip/-lzzipfseeko/' -e 's/zziplib/zzipfseeko/' \
+ zziplib.pc >$@
+
+__zziplib.pc : Makefile
+ @ echo "prefix=$(prefix)" >$@
+ @ echo "libdir=$(libdir)" >>$@
+ @ echo "includedir=$(includedir)" >>$@
+ @ echo "largefile=$(LARGEFILE_CFLAGS)" >>$@
+ @ echo "zlib_libs=@ZLIB_LDIR@ -lz" >>$@
+ @ echo "zlib_cflags=@ZLIB_INCL@" >>$@
+ @ echo " " >>$@
+ @ echo "Name: zziplib" >>$@
+ @ echo "Version: $(VERSION)" >>$@
+ @ head $(top_srcdir)/$(PACKAGE).spec \
+ | grep Summary | sed -e s,Summary,Description, >> $@
+ echo 'Requires: zzip-zlib-config' >>$@
+ echo 'Libs: -L$${libdir} -lzzip' >>$@
+ echo 'Cflags: $${largefile} -I$${includedir}' >>$@
+
+# ----------------------------------------------------------------------
+.c.i :
+ $(COMPILE) -E $< >$@
diff --git a/Build/source/libs/zziplib/zzip/Makefile.in b/Build/source/libs/zziplib/zzip/Makefile.in
new file mode 100644
index 00000000000..695af34ae04
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/Makefile.in
@@ -0,0 +1,712 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = zzip
+DIST_COMMON = $(noinst_HEADERS) $(pkgconfig_HEADERS) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in $(zzip_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_compile_check_sizeof.m4 \
+ $(top_srcdir)/m4/ac_set_default_paths_system.m4 \
+ $(top_srcdir)/m4/ac_sys_largefile_sensitive.m4 \
+ $(top_srcdir)/m4/acx_restrict.m4 \
+ $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \
+ $(top_srcdir)/m4/ax_cflags_no_writable_strings.m4 \
+ $(top_srcdir)/m4/ax_cflags_strict_prototypes.m4 \
+ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \
+ $(top_srcdir)/m4/ax_create_pkgconfig_info.m4 \
+ $(top_srcdir)/m4/ax_enable_builddir_uname.m4 \
+ $(top_srcdir)/m4/ax_expand_prefix.m4 \
+ $(top_srcdir)/m4/ax_maintainer_mode_auto_silent.m4 \
+ $(top_srcdir)/m4/ax_not_enable_frame_pointer.m4 \
+ $(top_srcdir)/m4/ax_prefix_config_h.m4 \
+ $(top_srcdir)/m4/ax_set_version_info.m4 \
+ $(top_srcdir)/m4/ax_spec_file.m4 \
+ $(top_srcdir)/m4/ax_spec_package_version.m4 \
+ $(top_srcdir)/m4/ax_warning_default_aclocaldir.m4 \
+ $(top_srcdir)/m4/ax_warning_default_pkgconfig.m4 \
+ $(top_srcdir)/m4/patch_libtool_on_darwin_zsh_overquoting.m4 \
+ $(top_srcdir)/m4/patch_libtool_sys_lib_search_path_spec.m4 \
+ $(top_srcdir)/m4/patch_libtool_to_add_host_cc.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/uses/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \
+ "$(DESTDIR)$(zzipdir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libzzip_la_DEPENDENCIES =
+am_libzzip_la_OBJECTS = zip.lo file.lo dir.lo stat.lo info.lo err.lo \
+ plugin.lo write.lo fetch.lo
+libzzip_la_OBJECTS = $(am_libzzip_la_OBJECTS)
+libzzipfseeko_la_DEPENDENCIES =
+am_libzzipfseeko_la_OBJECTS = fseeko.lo fetch.lo
+libzzipfseeko_la_OBJECTS = $(am_libzzipfseeko_la_OBJECTS)
+libzzipmmapped_la_DEPENDENCIES =
+am_libzzipmmapped_la_OBJECTS = mmapped.lo memdisk.lo fetch.lo
+libzzipmmapped_la_OBJECTS = $(am_libzzipmmapped_la_OBJECTS)
+depcomp = $(SHELL) $(top_srcdir)/uses/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libzzip_la_SOURCES) $(libzzipfseeko_la_SOURCES) \
+ $(libzzipmmapped_la_SOURCES)
+DIST_SOURCES = $(libzzip_la_SOURCES) $(libzzipfseeko_la_SOURCES) \
+ $(libzzipmmapped_la_SOURCES)
+pkgconfigHEADERS_INSTALL = $(INSTALL_HEADER)
+zzipHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(noinst_HEADERS) $(pkgconfig_HEADERS) $(zzip_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONFIG_FILES = @CONFIG_FILES@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@ -I$(top_builddir) -I$(top_srcdir) # also for automake 1.4
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LARGEFILE_CFLAGS = @LARGEFILE_CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+MKZIP = @MKZIP@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RELEASE_INFO = @RELEASE_INFO@
+RESOLVES = @RESOLVES@
+SDL = @SDL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+THREAD_SAFE = @THREAD_SAFE@
+VERSION = @VERSION@
+#
+VERSION_INFO = @VERSION_INFO@
+XMLTO = @XMLTO@
+ZIPTESTS = @ZIPTESTS@
+ZLIB_INCL = @ZLIB_INCL@
+ZLIB_LDIR = @ZLIB_LDIR@
+ZLIB_VERSION = @ZLIB_VERSION@
+ZZIPLIB_LDFLAGS = @ZZIPLIB_LDFLAGS@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_AS = @ac_ct_AS@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DLLTOOL = @ac_ct_DLLTOOL@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_OBJDUMP = @ac_ct_OBJDUMP@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+aclocaldir = @aclocaldir@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_enable_builddir_sed = @ax_enable_builddir_sed@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+docdir = @docdir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pkgconfig_libdir = @pkgconfig_libdir@
+pkgconfig_libfile = @pkgconfig_libfile@
+
+# ----------------------------------------------------------------------
+pkgconfigdir = $(libdir)/pkgconfig
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+AUTOMAKE_OPTIONS = 1.5 foreign
+AUTOTOOL_VERSION = autoconf-2.52 automake-1.5 libtool-1.4.2
+DEFAULT_INCLUDES = # nothing - no default of -I. -I$(srcdir)
+lib_LTLIBRARIES = libzzip.la libzzipmmapped.la libzzipfseeko.la
+zzipdir = ${includedir}/zzip
+zzip_HEADERS = $(libzzip_la_headers) \
+ $(libzzipmmapped_la_headers) \
+ $(libzzipfseeko_la_headers)
+
+noinst_HEADERS = __debug.h __hints.h __mmap.h __dirent.h __fnmatch.h
+#
+libzzip_la_SOURCES = \
+ zip.c \
+ file.c \
+ dir.c \
+ stat.c \
+ info.c \
+ err.c \
+ plugin.c \
+ write.c \
+ fetch.c
+
+libzzip_la_headers = \
+ stdint.h \
+ file.h \
+ plugin.h \
+ lib.h \
+ zzip.h \
+ fetch.h \
+ format.h \
+ info.h \
+ autoconf.h \
+ types.h \
+ conf.h \
+ _config.h \
+ _msvc.h
+
+libzzip_la_LDFLAGS = @ZZIPLIB_LDFLAGS@ $(RELEASE_INFO) $(VERSION_INFO) \
+ $(THREAD_SAFE)
+
+libzzip_la_LIBADD = -lz @RESOLVES@
+libzzipmmapped_la_SOURCES = mmapped.c memdisk.c fetch.c
+libzzipmmapped_la_headers = mmapped.h memdisk.h fetch.h
+libzzipmmapped_la_LDFLAGS = @ZZIPLIB_LDFLAGS@ $(RELEASE_INFO) $(VERSION_INFO) \
+ $(THREAD_SAFE)
+
+libzzipmmapped_la_LIBADD = -lz @RESOLVES@
+libzzipfseeko_la_SOURCES = fseeko.c fetch.c
+libzzipfseeko_la_headers = fseeko.h fetch.h
+libzzipfseeko_la_LDFLAGS = @ZZIPLIB_LDFLAGS@ $(RELEASE_INFO) $(VERSION_INFO) \
+ $(THREAD_SAFE)
+
+libzzipfseeko_la_LIBADD = -lz @RESOLVES@
+WCC10_DIST = zziplib.wpj
+WCC10_CLEAN = *.obj *.lk1 *.mk1 *.mk *.sym *.tgt
+EXTRA_DIST = $(WCC10_DIST) _msvc.sed
+CONFIG_CLEAN_FILES = _config.h
+MAINTAINERCLEANFILES = _msvc.h
+CLEANFILES = $(WCC10_CLEAN) *.pc *.omf
+pkgconfig_HEADERS = zzip-zlib-config.pc zziplib.pc \
+ zzipmmapped.pc zzipfseeko.pc
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .i .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign zzip/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign zzip/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libzzip.la: $(libzzip_la_OBJECTS) $(libzzip_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(libzzip_la_LDFLAGS) $(libzzip_la_OBJECTS) $(libzzip_la_LIBADD) $(LIBS)
+libzzipfseeko.la: $(libzzipfseeko_la_OBJECTS) $(libzzipfseeko_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(libzzipfseeko_la_LDFLAGS) $(libzzipfseeko_la_OBJECTS) $(libzzipfseeko_la_LIBADD) $(LIBS)
+libzzipmmapped.la: $(libzzipmmapped_la_OBJECTS) $(libzzipmmapped_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(libzzipmmapped_la_LDFLAGS) $(libzzipmmapped_la_OBJECTS) $(libzzipmmapped_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dir.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/err.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fetch.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fseeko.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memdisk.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmapped.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zip.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+install-pkgconfigHEADERS: $(pkgconfig_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgconfigdir)" || $(mkdir_p) "$(DESTDIR)$(pkgconfigdir)"
+ @list='$(pkgconfig_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(pkgconfigHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ $(pkgconfigHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+
+uninstall-pkgconfigHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgconfig_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+install-zzipHEADERS: $(zzip_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(zzipdir)" || $(mkdir_p) "$(DESTDIR)$(zzipdir)"
+ @list='$(zzip_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(zzipHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(zzipdir)/$$f'"; \
+ $(zzipHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(zzipdir)/$$f"; \
+ done
+
+uninstall-zzipHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(zzip_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(zzipdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(zzipdir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(zzipdir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local install-pkgconfigHEADERS \
+ install-zzipHEADERS
+
+install-exec-am: install-exec-local install-libLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES \
+ uninstall-local uninstall-pkgconfigHEADERS \
+ uninstall-zzipHEADERS
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am \
+ install-data-local install-exec install-exec-am \
+ install-exec-local install-info install-info-am \
+ install-libLTLIBRARIES install-man install-pkgconfigHEADERS \
+ install-strip install-zzipHEADERS installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-info-am uninstall-libLTLIBRARIES \
+ uninstall-local uninstall-pkgconfigHEADERS \
+ uninstall-zzipHEADERS
+
+
+# here is some backward compatibility with version 0.10.* of zziplib
+install-data-local : install-zzipHEADERS
+ echo '#ifndef ZZIP_WARNING' > $(DESTDIR)$(includedir)/zzip.h
+ echo '#define ZZIP_WARNING 1' >>$(DESTDIR)$(includedir)/zzip.h
+ echo '#ifdef __GNUC__' >>$(DESTDIR)$(includedir)/zzip.h
+ echo '#warning do no not use <zzip.h>, update to include <zzip/lib.h>'\
+ >>$(DESTDIR)$(includedir)/zzip.h
+ echo '#else' >>$(DESTDIR)$(includedir)/zzip.h
+ echo '#error do no not use <zzip.h>, update to include <zzip/lib.h>'\
+ >>$(DESTDIR)$(includedir)/zzip.h
+ echo '#endif' >>$(DESTDIR)$(includedir)/zzip.h
+ echo '#endif' >>$(DESTDIR)$(includedir)/zzip.h
+ echo '#include "zzip/lib.h"' >>$(DESTDIR)$(includedir)/zzip.h
+ sed -e 's|zzip.h|zziplib.h|' -e 's|zzip/lib.h|zzip/zzip.h|' \
+ $(DESTDIR)$(includedir)/zzip.h >$(DESTDIR)$(includedir)/zziplib.h
+ sed -e 's|zzip.h|zzip-io.h|' -e 's|zzip/lib.h|zzip/plugin.h|' \
+ $(DESTDIR)$(includedir)/zzip.h >$(DESTDIR)$(includedir)/zzip-io.h
+
+install-exec-local:
+ @ for i in . $(DESTDIR)$(libdir)/libzzip*.so.13 \
+ ; do test -d $$i && continue ; lib=`basename "$$i" .so.13` \
+ ; echo "$(DESTDIR)$(libdir): ln -s $$lib.so.13 $$lib.so.10" \
+ ; (cd $(DESTDIR)$(libdir) && ln -s $$lib.so.13 $$lib.so.10) \
+ ; echo "$(DESTDIR)$(libdir): ln -s $$lib.so.13 $$lib.so.11" \
+ ; (cd $(DESTDIR)$(libdir) && ln -s $$lib.so.13 $$lib.so.11) \
+ ; echo "$(DESTDIR)$(libdir): ln -s $$lib.so.13 $$lib.so.12" \
+ ; (cd $(DESTDIR)$(libdir) && ln -s $$lib.so.13 $$lib.so.12) \
+ ; done ; true
+
+uninstall-local :
+ (cd $(DESTDIR)$(includedir) && rm zziplib.h zzip.h zzip-io.h)
+
+zziplib.pc : Makefile
+ (cd .. && sh config.status zzip/zziplib.pc)
+
+zzip-zlib-config.pc : Makefile
+ @ echo "zlib_libs=@ZLIB_LDIR@ -lz" >$@
+ @ echo "zlib_cflags=@ZLIB_INCL@" >>$@
+ @ echo " " >>$@
+ @ echo "Name: zzip-zlib-config" >>$@
+ @ echo "Version: @ZLIB_VERSION@" >>$@
+ @ echo "Description: ZLib Config (for ZZipLib)" >>$@
+ echo 'Libs: $${zlib_libs}' >>$@
+ echo 'Cflags: $${zlib_cflags}' >>$@
+
+zzipmmapped.pc : zziplib.pc
+ sed -e 's/-lzzip/-lzzipmmapped/' -e 's/zziplib/zzipmmapped/' \
+ zziplib.pc >$@
+zzipfseeko.pc : zziplib.pc
+ sed -e 's/-lzzip/-lzzipfseeko/' -e 's/zziplib/zzipfseeko/' \
+ zziplib.pc >$@
+
+__zziplib.pc : Makefile
+ @ echo "prefix=$(prefix)" >$@
+ @ echo "libdir=$(libdir)" >>$@
+ @ echo "includedir=$(includedir)" >>$@
+ @ echo "largefile=$(LARGEFILE_CFLAGS)" >>$@
+ @ echo "zlib_libs=@ZLIB_LDIR@ -lz" >>$@
+ @ echo "zlib_cflags=@ZLIB_INCL@" >>$@
+ @ echo " " >>$@
+ @ echo "Name: zziplib" >>$@
+ @ echo "Version: $(VERSION)" >>$@
+ @ head $(top_srcdir)/$(PACKAGE).spec \
+ | grep Summary | sed -e s,Summary,Description, >> $@
+ echo 'Requires: zzip-zlib-config' >>$@
+ echo 'Libs: -L$${libdir} -lzzip' >>$@
+ echo 'Cflags: $${largefile} -I$${includedir}' >>$@
+
+# ----------------------------------------------------------------------
+.c.i :
+ $(COMPILE) -E $< >$@
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Build/source/libs/zziplib/zzip/__debug.h b/Build/source/libs/zziplib/zzip/__debug.h
new file mode 100644
index 00000000000..13c7d895443
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/__debug.h
@@ -0,0 +1,89 @@
+#ifndef __ZZIP_INTERNAL_DEBUG_H
+#define __ZZIP_INTERNAL_DEBUG_H
+
+#include <zzip/conf.h>
+#include <zzip/__hints.h>
+
+/* perhaps want to show on syslog(3) ?? */
+
+#ifdef DEBUG
+#include <stdio.h>
+#define DBG1(X1) ZZIP_FOR1 { \
+ fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \
+ ); } ZZIP_END1
+#define DBG2(X1,X2) ZZIP_FOR1 { \
+ fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \
+ ,X2);} ZZIP_END1
+#define DBG3(X1,X2,X3) ZZIP_FOR1 { \
+ fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \
+ ,X2,X3); } ZZIP_END1
+#define DBG4(X1,X2,X3,X4) ZZIP_FOR1 { \
+ fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \
+ ,X2,X3,X4); } ZZIP_END1
+#define DBG5(X1,X2,X3,X4,X5) ZZIP_FOR1 { \
+ fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \
+ ,X2,X3,X4,X5); } ZZIP_END1
+#define DBG6(X1,X2,X3,X4,X5,X6) ZZIP_FOR1 { \
+ fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \
+ ,X2,X3,X4,X5,X6); } ZZIP_END1
+
+#else
+#define DBG1(X1) {}
+#define DBG2(X1,X2) {}
+#define DBG3(X1,X2,X3) {}
+#define DBG4(X1,X2,X3,X4) {}
+#define DBG5(X1,X2,X3,X4,X5) {}
+#define DBG6(X1,X2,X3,X4,X5,X6) {}
+#endif
+
+#define HINT1(X1) DBG1("HINT: " X1)
+#define HINT2(X1,X2) DBG2("HINT: " X1,X2)
+#define HINT3(X1,X2,X3) DBG3("HINT: " X1,X2,X3)
+#define HINT4(X1,X2,X3,X4) DBG4("HINT: " X1,X2,X3,X4)
+#define HINT5(X1,X2,X3,X4,X5) DBG5("HINT: " X1,X2,X3,X4,X5)
+#define HINT6(X1,X2,X3,X4,X5,X6) DBG6("HINT: " X1,X2,X3,X4,X5,X6)
+
+#define NOTE1(X1) DBG1("NOTE: " X1)
+#define NOTE2(X1,X2) DBG2("NOTE: " X1,X2)
+#define NOTE3(X1,X2,X3) DBG3("NOTE: " X1,X2,X3)
+#define NOTE4(X1,X2,X3,X4) DBG4("NOTE: " X1,X2,X3,X4)
+#define NOTE5(X1,X2,X3,X4,X5) DBG5("NOTE: " X1,X2,X3,X4,X5)
+#define NOTE6(X1,X2,X3,X4,X5,X6) DBG6("NOTE: " X1,X2,X3,X4,X5,X6)
+
+#define WARN1(X1) DBG1("WARN: " X1)
+#define WARN2(X1,X2) DBG2("WARN: " X1,X2)
+#define WARN3(X1,X2,X3) DBG3("WARN: " X1,X2,X3)
+#define WARN4(X1,X2,X3,X4) DBG4("WARN: " X1,X2,X3,X4)
+#define WARN5(X1,X2,X3,X4,X5) DBG5("WARN: " X1,X2,X3,X4,X5)
+#define WARN6(X1,X2,X3,X4,X5,X6) DBG6("WARN: " X1,X2,X3,X4,X5,X6)
+
+#define FAIL1(X1) DBG1("FAIL: " X1)
+#define FAIL2(X1,X2) DBG2("FAIL: " X1,X2)
+#define FAIL3(X1,X2,X3) DBG3("FAIL: " X1,X2,X3)
+#define FAIL4(X1,X2,X3,X4) DBG4("FAIL: " X1,X2,X3,X4)
+#define FAIL5(X1,X2,X3,X4,X5) DBG5("FAIL: " X1,X2,X3,X4,X5)
+#define FAIL6(X1,X2,X3,X4,X5,X6) DBG6("FAIL: " X1,X2,X3,X4,X5,X6)
+
+
+
+#ifdef DEBUG
+_zzip_inline static void zzip_debug_xbuf (unsigned char* p, int l)
+ /* ZZIP_GNUC_UNUSED */
+{
+# define q(a) ((a&0x7F)<32?32:(a&0x7F))
+ while (l > 0)
+ {
+ fprintf (stderr,
+ "%02x %02x %02x %02x "
+ "%02x %02x %02x %02x "
+ "%c%c%c%c %c%c%c%c\n",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
+ q(p[0]), q(p[1]), q(p[2]), q(p[3]),
+ q(p[4]), q(p[5]), q(p[6]), q(p[7]));
+ p += 8; l -= 8;
+ }
+# undef q
+}
+#endif
+
+#endif
diff --git a/Build/source/libs/zziplib/zzip/__dirent.h b/Build/source/libs/zziplib/zzip/__dirent.h
new file mode 100644
index 00000000000..fc3e08f03d1
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/__dirent.h
@@ -0,0 +1,393 @@
+#ifndef ZZIP_INTERNAL_DIRENT_H
+#define ZZIP_INTERNAL_DIRENT_H
+#include <zzip/conf.h>
+
+/*
+ * DO NOT USE THIS CODE.
+ *
+ * It is an internal header file for zziplib that carries some inline
+ * functions (or just static members) and a few defines, simply to be
+ * able to reuse these across - and have everything in a specific place.
+ *
+ * Copyright (c) 2002,2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#ifdef ZZIP_HAVE_DIRENT_H
+#define USE_DIRENT 1
+
+#define _zzip_opendir opendir
+#define _zzip_readdir readdir
+#define _zzip_closedir closedir
+#define _zzip_rewinddir rewinddir
+#define _zzip_telldir telldir
+#define _zzip_seekdir seekdir
+#define _zzip_DIR DIR
+
+#include <dirent.h>
+
+#elif defined ZZIP_HAVE_WINBASE_H
+#define USE_DIRENT 2
+
+#define _zzip_opendir win32_opendir
+#define _zzip_readdir win32_readdir
+#define _zzip_closedir win32_closedir
+#define _zzip_rewinddir win32_rewinddir
+#define _zzip_telldir win32_telldir
+#define _zzip_seekdir win32_seekdir
+#define _zzip_DIR DIR
+
+/*
+ * DIRENT.H (formerly DIRLIB.H)
+ *
+ * by M. J. Weinstein Released to public domain 1-Jan-89
+ *
+ * Because I have heard that this feature (opendir, readdir, closedir)
+ * it so useful for programmers coming from UNIX or attempting to port
+ * UNIX code, and because it is reasonably light weight, I have included
+ * it in the Mingw32 package. I have also added an implementation of
+ * rewinddir, seekdir and telldir.
+ * - Colin Peters <colin@bird.fu.is.saga-u.ac.jp>
+ *
+ * This code is distributed in the hope that is will be useful but
+ * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+ * DISCLAMED. This includeds but is not limited to warranties of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#include <io.h>
+
+struct dirent
+{
+ long d_ino; /* Always zero. */
+ unsigned short d_reclen; /* Always zero. */
+ unsigned short d_namlen; /* Length of name in d_name. */
+ char* d_name; /* File name. */
+ /* NOTE: The name in the dirent structure points to the name in the
+ * finddata_t structure in the DIR. */
+};
+
+/*
+ * This is an internal data structure. Good programmers will not use it
+ * except as an argument to one of the functions below.
+ */
+typedef struct
+{
+ /* disk transfer area for this dir */
+ struct _finddata_t dd_dta;
+
+ /* dirent struct to return from dir (NOTE: this makes this thread
+ * safe as long as only one thread uses a particular DIR struct at
+ * a time) */
+ struct dirent dd_dir;
+
+ /* _findnext handle */
+ long dd_handle;
+
+ /*
+ * Status of search:
+ * 0 = not started yet (next entry to read is first entry)
+ * -1 = off the end
+ * positive = 0 based index of next entry
+ */
+ short dd_stat;
+
+ /* given path for dir with search pattern (struct is extended) */
+ char dd_name[1];
+} DIR;
+
+/*
+ * dirent.c
+ *
+ * Derived from DIRLIB.C by Matt J. Weinstein
+ * This note appears in the DIRLIB.H
+ * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89
+ *
+ * Updated by Jeremy Bettis <jeremy@hksys.com>
+ * Significantly revised and rewinddir, seekdir and telldir added by Colin
+ * Peters <colin@fu.is.saga-u.ac.jp>
+ */
+
+#include <direct.h>
+#include <errno.h>
+#include <io.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#define win32_SUFFIX "*"
+#define win32_SLASH "\\"
+
+#ifndef S_ISDIR
+#define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR) /* is a directory */
+#endif S_ISDIR
+
+
+/*
+ opendir
+
+ Returns a pointer to a DIR structure appropriately filled in to begin
+ searching a directory.
+*/
+static DIR*
+win32_opendir (const char *szPath)
+{
+ DIR *nd;
+ struct _stat statDir;
+
+ errno = 0;
+
+ if (!szPath) {
+ errno = EFAULT;
+ return (DIR *) 0;
+ }
+
+ if (szPath[0] == '\0') {
+ errno = ENOTDIR;
+ return (DIR *) 0;
+ }
+
+ /* Attempt to determine if the given path really is a directory. */
+ if (_stat (szPath, &statDir)) {
+ /* Error, stat should have set an error value. */
+ return (DIR *) 0;
+ }
+
+ if (!S_ISDIR (statDir.st_mode)) {
+ /* Error, stat reports not a directory. */
+ errno = ENOTDIR;
+ return (DIR *) 0;
+ }
+
+ /* Allocate enough space to store DIR structure and the complete *
+ directory path given. */
+ nd = (DIR *) calloc (1, sizeof (DIR) + strlen (szPath)
+ + strlen (win32_SLASH) + strlen (win32_SUFFIX));
+
+ if (!nd) {
+ /* Error, out of memory. */
+ errno = ENOMEM;
+ return (DIR *) 0;
+ }
+
+ /* Create the search expression. */
+ strcpy (nd->dd_name, szPath);
+
+ /* Add on a slash if the path does not end with one. */
+ if (nd->dd_name[0] != '\0' &&
+ nd->dd_name[strlen (nd->dd_name) - 1] != '/' &&
+ nd->dd_name[strlen (nd->dd_name) - 1] != '\\') {
+ strcat (nd->dd_name, win32_SLASH);
+ }
+
+ /* Add on the search pattern */
+ strcat (nd->dd_name, win32_SUFFIX);
+
+ /* Initialize handle to -1 so that a premature closedir doesn't try * to
+ call _findclose on it. */
+ nd->dd_handle = -1;
+
+ /* Initialize the status. */
+ nd->dd_stat = 0;
+
+ /* Initialize the dirent structure. ino and reclen are invalid under *
+ Win32, and name simply points at the appropriate part of the *
+ findfirst_t structure. */
+ nd->dd_dir.d_ino = 0;
+ nd->dd_dir.d_reclen = 0;
+ nd->dd_dir.d_namlen = 0;
+ nd->dd_dir.d_name = nd->dd_dta.name;
+
+ return nd;
+}
+
+/*
+ readdir
+
+ Return a pointer to a dirent structure filled with the information on the
+ next entry in the directory.
+*/
+static struct dirent *
+win32_readdir (DIR * dirp)
+{
+ errno = 0;
+
+ /* Check for valid DIR struct. */
+ if (!dirp) {
+ errno = EFAULT;
+ return (struct dirent *) 0;
+ }
+
+ if (dirp->dd_dir.d_name != dirp->dd_dta.name) {
+ /* The structure does not seem to be set up correctly. */
+ errno = EINVAL;
+ return (struct dirent *) 0;
+ }
+
+ if (dirp->dd_stat < 0) {
+ /* We have already returned all files in the directory * (or the
+ structure has an invalid dd_stat). */
+ return (struct dirent *) 0;
+ } else if (dirp->dd_stat == 0) {
+ /* We haven't started the search yet. */
+ /* Start the search */
+ dirp->dd_handle = _findfirst (dirp->dd_name, &(dirp->dd_dta));
+
+ if (dirp->dd_handle == -1) {
+ /* Whoops! Seems there are no files in that * directory. */
+ dirp->dd_stat = -1;
+ } else {
+ dirp->dd_stat = 1;
+ }
+ } else {
+ /* Get the next search entry. */
+ if (_findnext (dirp->dd_handle, &(dirp->dd_dta))) {
+ /* We are off the end or otherwise error. */
+ _findclose (dirp->dd_handle);
+ dirp->dd_handle = -1;
+ dirp->dd_stat = -1;
+ } else {
+ /* Update the status to indicate the correct * number. */
+ dirp->dd_stat++;
+ }
+ }
+
+ if (dirp->dd_stat > 0) {
+ /* Successfully got an entry. Everything about the file is * already
+ appropriately filled in except the length of the * file name. */
+ dirp->dd_dir.d_namlen = (unsigned short) strlen (dirp->dd_dir.d_name);
+ return &dirp->dd_dir;
+ }
+
+ return (struct dirent *) 0;
+}
+
+/*
+ closedir
+
+ Frees up resources allocated by opendir.
+*/
+static int
+win32_closedir (DIR * dirp)
+{
+ int rc;
+
+ errno = 0;
+ rc = 0;
+
+ if (!dirp) {
+ errno = EFAULT;
+ return -1;
+ }
+
+ if (dirp->dd_handle != -1) {
+ rc = _findclose (dirp->dd_handle);
+ }
+
+ /* Delete the dir structure. */
+ free (dirp);
+
+ return rc;
+}
+
+/*
+ rewinddir
+
+ Return to the beginning of the directory "stream". We simply call findclose
+ and then reset things like an opendir.
+*/
+static void
+win32_rewinddir (DIR * dirp)
+{
+ errno = 0;
+
+ if (!dirp) {
+ errno = EFAULT;
+ return;
+ }
+
+ if (dirp->dd_handle != -1) {
+ _findclose (dirp->dd_handle);
+ }
+
+ dirp->dd_handle = -1;
+ dirp->dd_stat = 0;
+}
+
+/*
+ telldir
+
+ Returns the "position" in the "directory stream" which can be used with
+ seekdir to go back to an old entry. We simply return the value in stat.
+*/
+static long
+win32_telldir (DIR * dirp)
+{
+ errno = 0;
+
+ if (!dirp) {
+ errno = EFAULT;
+ return -1;
+ }
+ return dirp->dd_stat;
+}
+
+/*
+ seekdir
+
+ Seek to an entry previously returned by telldir. We rewind the directory
+ and call readdir repeatedly until either dd_stat is the position number
+ or -1 (off the end). This is not perfect, in that the directory may
+ have changed while we weren't looking. But that is probably the case with
+ any such system.
+*/
+static void
+win32_seekdir (DIR * dirp, long lPos)
+{
+ errno = 0;
+
+ if (!dirp) {
+ errno = EFAULT;
+ return;
+ }
+
+ if (lPos < -1) {
+ /* Seeking to an invalid position. */
+ errno = EINVAL;
+ return;
+ } else if (lPos == -1) {
+ /* Seek past end. */
+ if (dirp->dd_handle != -1) {
+ _findclose (dirp->dd_handle);
+ }
+ dirp->dd_handle = -1;
+ dirp->dd_stat = -1;
+ } else {
+ /* Rewind and read forward to the appropriate index. */
+ win32_rewinddir (dirp);
+
+ while ((dirp->dd_stat < lPos) && win32_readdir (dirp));
+ }
+}
+
+#else
+#define USE_DIRENT 0
+
+#define _zzip_opendir(_N_) 0
+#define _zzip_readdir(_D_) 0
+#define _zzip_closedir(_D_) /* omit return code */
+#define _zzip_rewinddir(_D_)
+#define _zzip_telldir(_D_) 0
+#define _zzip_seekdir(_D_,_V_) /* omit return code */
+#define _zzip_DIR void*
+
+/* end of DIRENT implementation */
+#endif
+
+/* once */
+#endif
diff --git a/Build/source/libs/zziplib/zzip/__fnmatch.h b/Build/source/libs/zziplib/zzip/__fnmatch.h
new file mode 100644
index 00000000000..9759a7423d8
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/__fnmatch.h
@@ -0,0 +1,28 @@
+#ifndef __ZZIP_INTERNAL_FNMATCH_H
+#define __ZZIP_INTERNAL_FNMATCH_H
+/** included by fseeko.c, mmapped.c, memdisk.c */
+
+#include <zzip/conf.h>
+
+#ifdef ZZIP_HAVE_FNMATCH_H
+#include <fnmatch.h>
+#endif
+
+#ifdef ZZIP_HAVE_FNMATCH_H
+#define _zzip_fnmatch fnmatch
+# ifdef FNM_CASEFOLD
+# define _zzip_fnmatch_CASEFOLD FNM_CASEFOLD
+# else
+# define _zzip_fnmatch_CASEFOLD 0
+# endif
+#else
+# define _zzip_fnmatch_CASEFOLD 0
+/* if your system does not have fnmatch, we fall back to strcmp: */
+static int _zzip_fnmatch(char* pattern, char* string, int flags)
+{
+ puts ("<zzip:mmapped:strcmp>");
+ return strcmp (pattern, string);
+}
+#endif
+
+#endif
diff --git a/Build/source/libs/zziplib/zzip/__hints.h b/Build/source/libs/zziplib/zzip/__hints.h
new file mode 100644
index 00000000000..ed5b2ad9799
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/__hints.h
@@ -0,0 +1,189 @@
+#ifndef __ZZIP_INTERNAL_HINTS_H
+#define __ZZIP_INTERNAL_HINTS_H
+#include <zzip/conf.h>
+
+#ifndef ZZIP_GNUC_ATLEAST
+# if defined __GNUC__ && defined __GNUC_MINOR__
+# define ZZIP_GNUC_ATLEAST(_M_,_N_) \
+ ((__GNUC__ << 10) + __GNUC_MINOR__ >= ((_M_) << 10) + (_N_))
+# elif defined __GNUC__
+# define ZZIP_GNUC_ATLEAST(_M_,_N_) \
+ ((__GNUC__ << 10) >= ((_M_) << 10))
+# else
+# define ZZIP_GNUC_ATLEAST(_M_, _N_) 0
+# endif
+#endif
+
+#ifndef ZZIP_GNUC_EXTENSION
+# if ZZIP_GNUC_ATLEAST(2,8)
+# define ZZIP_GNUC_EXTENSION __extension__
+# else
+# define ZZIP_GNUC_EXTENSION
+# endif
+#endif
+
+/* func has no side effects, return value depends only on params and globals */
+#ifndef ZZIP_GNUC_PURE
+# if ZZIP_GNUC_ATLEAST(2,8)
+# define ZZIP_GNUC_PURE __attribute__((__pure__))
+# else
+# define ZZIP_GNUC_PURE
+# endif
+#endif
+
+/* func has no side effects, return value depends only on params */
+#ifndef ZZIP_GNUC_CONST
+# if ZZIP_GNUC_ATLEAST(2,4)
+# define ZZIP_GNUC_CONST __attribute__((__const__))
+# else
+# define ZZIP_GNUC_CONST
+# endif
+#endif
+
+/* typename / variable / function possibly unused */
+#ifndef ZZIP_GNUC_UNUSED
+# if ZZIP_GNUC_ATLEAST(2,4)
+# define ZZIP_GNUC_UNUSED __attribute__((__unused__))
+# else
+# define ZZIP_GNUC_UNUSED
+# endif
+#endif
+
+/* obvious. btw, a noreturn-func should return void */
+#ifndef ZZIP_GNUC_NORETURN
+# if ZZIP_GNUC_ATLEAST(2,5)
+# define ZZIP_GNUC_NORETURN __attribute__((__noreturn__))
+# else
+# define ZZIP_GNUC_NORETURN
+# endif
+#endif
+
+/* omit function from profiling with -finstrument-functions */
+#ifndef ZZIP_GNUC_NO_INSTRUMENT
+# if ZZIP_GNUC_ATLEAST(2,4)
+# define ZZIP_GNUC_NO_INSTRUMENT __attribute__((__no_instrument_function__))
+# else
+# define ZZIP_GNUC_NO_INSTRUMENT
+# endif
+#endif
+
+/* all pointer args must not be null, and allow optimiztons based on the fact*/
+#ifndef ZZIP_GNUC_NONNULL
+# if ZZIP_GNUC_ATLEAST(3,1)
+# define ZZIP_GNUC_NONNULL __attribute__((nonnull))
+# else
+# define ZZIP_GNUC_NONNULL
+# endif
+#endif
+
+/* the function can not throw - the libc function are usually nothrow */
+#ifndef ZZIP_GNUC_NOTHROW
+# if ZZIP_GNUC_ATLEAST(3,2)
+# define ZZIP_GNUC_NOTHROW __attribute__((nothrow))
+# else
+# define ZZIP_GNUC_NOTHROW
+# endif
+#endif
+
+/* typename / function / variable is obsolete but still listed in headers */
+#ifndef ZZIP_GNUC_DEPRECATED
+# if ZZIP_GNUC_ATLEAST(3,1)
+# define ZZIP_GNUC_DEPRECATED __attribute__((deprecated))
+# else
+# define ZZIP_GNUC_DEPRECATED
+# endif
+#endif
+
+/* resolve references to this function during pre-linking the libary */
+#ifndef ZZIP_GNUC_LIB_PROTECTED
+# if ZZIP_GNUC_ATLEAST(3,1)
+# define ZZIP_GNUC_LIB_PROTECTED __attribute__((visiblity("protected")))
+# else
+# define ZZIP_GNUC_LIB_PROTECTED
+# endif
+#endif
+
+/* func shall only be usable within the same lib (so, no entry in lib symtab)*/
+#ifndef ZZIP_GNUC_LIB_PRIVATE
+# if ZZIP_GNUC_ATLEAST(3,1)
+# define ZZIP_GNUC_LIB_PRIVATE __attribute__((visiblity("hidden")))
+# else
+# define ZZIP_GNUC_LIB_PRIVATE
+# endif
+#endif
+
+/* ... and not even passed as a function pointer reference to outside the lib*/
+#ifndef ZZIP_GNUC_LIB_INTERNAL
+# if ZZIP_GNUC_ATLEAST(3,1)
+# define ZZIP_GNUC_LIB_INTERNAL __attribute__((visiblity("internal")))
+# else
+# define ZZIP_GNUC_LIB_INTERNAL
+# endif
+#endif
+
+
+#ifndef ZZIP_GNUC_FORMAT
+# if ZZIP_GNUC_ATLEAST(2,4)
+# define ZZIP_GNUC_FORMAT(_X_) __attribute__((__format_arg__(_X_)))
+# else
+# define ZZIP_GNUC_FORMAT(_X_)
+# endif
+#endif
+
+#ifndef ZZIP_GNUC_SCANF
+# if ZZIP_GNUC_ATLEAST(2,4)
+# define ZZIP_GNUC_SCANF(_S_,_X_) __attribute__((__scanf__(_S_,_X_)))
+# else
+# define ZZIP_GNUC_SCANF(_S_,_X_)
+# endif
+#endif
+
+#ifndef ZZIP_GNUC_PRINTF
+# if ZZIP_GNUC_ATLEAST(2,4)
+# define ZZIP_GNUC_PRINTF(_S_,_X_) __attribute__((__printf__(_S_,_X_)))
+# else
+# define ZZIP_GNUC_PRINTF(_S_,_X_)
+# endif
+#endif
+
+#ifndef ZZIP_FUNCTION
+# if ZZIP_GNUC_ATLEAST(2,6)
+# define ZZIP_FUNC __FUNCTION__
+# define ZZIP_FUNCTION __FUNCTION__
+# elif defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+# define ZZIP_FUNC __func__
+# define ZZIP_FUNCTION ""
+# else
+# define ZZIP_FUNC 0
+# define ZZIP_FUNCTION ""
+# endif
+#endif
+
+#ifndef ZZIP_STRING
+#define ZZIP_STRING(_X_) ZZIP_STRING_(_X_)
+#define ZZIP_STRING_(_Y_) #_Y_
+#endif
+
+#ifndef ZZIP_DIM
+#define ZZIP_DIM(_A_) (sizeof(_A_) / sizeof ((_A_)[0]))
+#endif
+
+#if !(defined ZZIP_FOR1 && defined ZZIP_END1)
+# if defined sun || defined __sun__
+# define ZZIP_FOR1 if (1)
+# define ZZIP_END1 else (void)0
+# else
+# define ZZIP_FOR1 do
+# define ZZIP_END1 while (0)
+# endif
+#endif
+
+#ifndef ZZIP_BRANCH_OVER
+# if ZZIP_GNUC_ATLEAST(2,96)
+# define ZZIP_BRANCH_OVER(_X_) __builtin_expect((_X_),0)
+# else
+# define ZZIP_BRANCH_OVER(_X_) (_X_)
+# endif
+#endif
+
+#endif
diff --git a/Build/source/libs/zziplib/zzip/__mmap.h b/Build/source/libs/zziplib/zzip/__mmap.h
new file mode 100644
index 00000000000..121c8bd82f8
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/__mmap.h
@@ -0,0 +1,107 @@
+#ifndef __ZZIP_INTERNAL_MMAP_H
+#define __ZZIP_INTERNAL_MMAP_H
+#include <zzip/types.h>
+
+/*
+ * DO NOT USE THIS CODE.
+ *
+ * It is an internal header file for zziplib that carries some inline
+ * functions (or just static members) and a few defines, simply to be
+ * able to reuse these across - and have everything in a specific place.
+ *
+ * Copyright (c) 2002,2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#ifdef _USE_MMAP
+#if defined ZZIP_HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#define USE_POSIX_MMAP 1
+#elif defined ZZIP_HAVE_WINBASE_H || defined WIN32
+#include <windows.h>
+#define USE_WIN32_MMAP 1
+#else
+#undef _USE_MMAP
+#endif
+#endif
+
+/* -------------- specify MMAP function imports --------------------------- */
+
+#if defined USE_POSIX_MMAP
+#define USE_MMAP 1
+
+#define _zzip_mmap(user, fd, offs, len) \
+ mmap (0, len, PROT_READ, MAP_SHARED, fd, offs)
+#define _zzip_munmap(user, ptr, len) \
+ munmap (ptr, len)
+#define _zzip_getpagesize(user) getpagesize()
+
+#ifndef MAP_FAILED /* hpux10.20 does not have it */
+#define MAP_FAILED ((void*)(-1))
+#endif
+
+#elif defined USE_WIN32_MMAP
+#define USE_MMAP 1
+#ifndef MAP_FAILED
+#define MAP_FAILED 0
+#endif
+/* we (ab)use the "*user" variable to store the FileMapping handle */
+ /* which assumes (sizeof(long) == sizeof(HANDLE)) */
+
+static size_t win32_getpagesize ()
+{
+ SYSTEM_INFO si; GetSystemInfo (&si);
+ return si.dwAllocationGranularity;
+}
+static void* win32_mmap (long* user, int fd, zzip_off_t offs, size_t len)
+{
+ if (! user || *user != 1) /* || offs % getpagesize() */
+ return 0;
+ {
+ HANDLE hFile = (HANDLE)_get_osfhandle(fd);
+ if (hFile)
+ *user = (int) CreateFileMapping (hFile, 0, PAGE_READONLY, 0, 0, NULL);
+ if (*user)
+ {
+ char* p = 0;
+ p = MapViewOfFile(*(HANDLE*)user, FILE_MAP_READ, 0, offs, len);
+ if (p) return p + offs;
+ CloseHandle (*(HANDLE*)user); *user = 1;
+ }
+ return MAP_FAILED;
+ }
+}
+static void win32_munmap (long* user, char* fd_map, size_t len)
+{
+ UnmapViewOfFile (fd_map);
+ CloseHandle (*(HANDLE*)user); *user = 1;
+}
+
+#define _zzip_mmap(user, fd, offs, len) \
+ win32_mmap ((long*) &(user), fd, offs, len)
+#define _zzip_munmap(user, ptr, len) \
+ win32_munmap ((long*) &(user), ptr, len)
+#define _zzip_getpagesize(user) win32_getpagesize()
+
+#else /* disable */
+#define USE_MMAP 0
+/* USE_MAP is intentional: we expect the compiler to do some "code removal"
+ * on any source code enclosed in if (USE_MMAP) {...} i.e. the unreachable
+ * branch of an if (0) {....} is not emitted to the final object binary. */
+
+#ifndef MAP_FAILED
+#define MAP_FAILED 0
+#endif
+
+#define _zzip_mmap(user, fd, offs, len) (MAP_FAILED)
+#define _zzip_munmap(user, ptr, len) {}
+#define _zzip_getpagesize(user) 1
+
+#endif /* USE_MMAP defines */
+
+
+#endif
diff --git a/Build/source/libs/zziplib/zzip/_config.h b/Build/source/libs/zziplib/zzip/_config.h
new file mode 100644
index 00000000000..ebc6aab6f82
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/_config.h
@@ -0,0 +1,247 @@
+#ifndef _ZZIP__CONFIG_H
+#define _ZZIP__CONFIG_H 1
+
+/* Define to 1 if you have the <byteswap.h> header file. */
+/* #undef ZZIP_HAVE_BYTESWAP_H */
+
+/* TH need this to get the proper definition of _mkdir() in write.c */
+
+/* Define to 1 if you have the <direct.h> header file. */
+#ifndef ZZIP_HAVE_DIRECT_H
+#ifdef WIN32
+#define ZZIP_HAVE_DIRECT_H 1
+#endif
+#endif
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#ifndef ZZIP_HAVE_DIRENT_H
+#define ZZIP_HAVE_DIRENT_H 1
+#endif
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#ifndef ZZIP_HAVE_DLFCN_H
+#define ZZIP_HAVE_DLFCN_H 1
+#endif
+
+/*TH Zziplibs's own __fnmatch.h gives a compiler warning because it
+ uses puts() without loading stdio.h, so I prefer not to use it if
+ there is a correct system header, even though the warning is
+ harmless.
+*/
+
+/* Define to 1 if you have the <fnmatch.h> header file. */
+#ifndef ZZIP_HAVE_FNMATCH_H
+#ifndef WIN32
+#define ZZIP_HAVE_FNMATCH_H 1
+#endif
+#endif
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#ifndef ZZIP_HAVE_INTTYPES_H
+#define ZZIP_HAVE_INTTYPES_H 1
+#endif
+
+/* Define to 1 if you have the <io.h> header file. */
+#ifndef ZZIP_HAVE_IO_H
+#ifdef WIN32
+#define ZZIP_HAVE_IO_H 1
+#endif
+#endif
+
+/* Define to 1 if you have the <memory.h> header file. */
+#ifndef ZZIP_HAVE_MEMORY_H
+#define ZZIP_HAVE_MEMORY_H 1
+#endif
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef ZZIP_HAVE_NDIR_H */
+
+#ifdef __sun__
+/* Define to 1 if you have the <sys/int_types.h> header file. */
+#define ZZIP_HAVE_SYS_INT_TYPES_H 1
+#else
+/* Define to 1 if you have the <stdint.h> header file. */
+#define ZZIP_HAVE_STDINT_H 1
+#endif
+
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#ifndef ZZIP_HAVE_STDLIB_H
+#define ZZIP_HAVE_STDLIB_H 1
+#endif
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#ifndef ZZIP_HAVE_STRCASECMP
+#define ZZIP_HAVE_STRCASECMP 1
+#endif
+
+/* Define to 1 if you have the <strings.h> header file. */
+#ifndef ZZIP_HAVE_STRINGS_H
+#define ZZIP_HAVE_STRINGS_H 1
+#endif
+
+/* Define to 1 if you have the <string.h> header file. */
+#ifndef ZZIP_HAVE_STRING_H
+#define ZZIP_HAVE_STRING_H 1
+#endif
+
+/* Define to 1 if you have the `strndup' function. */
+#ifndef ZZIP_HAVE_STRNDUP
+#define ZZIP_HAVE_STRNDUP 1
+#endif
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+/* #undef ZZIP_HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+/* undefe ZZIP_HAVE_SYS_MMAN_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+/* #undef ZZIP_HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#ifndef ZZIP_HAVE_SYS_PARAM_H
+#define ZZIP_HAVE_SYS_PARAM_H 1
+#endif
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#ifndef ZZIP_HAVE_SYS_STAT_H
+#define ZZIP_HAVE_SYS_STAT_H 1
+#endif
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#ifndef ZZIP_HAVE_SYS_TYPES_H
+#define ZZIP_HAVE_SYS_TYPES_H 1
+#endif
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#ifndef ZZIP_HAVE_UNISTD_H
+#define ZZIP_HAVE_UNISTD_H 1
+#endif
+
+/* Define to 1 if you have the <winbase.h> header file. */
+/* #undef ZZIP_HAVE_WINBASE_H */
+
+/* Define to 1 if you have the <windows.h> header file. */
+/* #undef ZZIP_HAVE_WINDOWS_H */
+
+/* Define to 1 if you have the <winnt.h> header file. */
+/* #undef ZZIP_HAVE_WINNT_H */
+
+/* Define to 1 if you have the <zlib.h> header file. */
+#ifndef ZZIP_HAVE_ZLIB_H
+#define ZZIP_HAVE_ZLIB_H 1
+#endif
+
+/* whether the system defaults to 32bit off_t but can do 64bit when requested
+ */
+#ifndef ZZIP_LARGEFILE_SENSITIVE
+#define ZZIP_LARGEFILE_SENSITIVE 1
+#endif
+
+/* Name of package */
+#ifndef ZZIP_PACKAGE
+#define ZZIP_PACKAGE "zziplib"
+#endif
+
+/* Define to the address where bug reports for this package should be sent. */
+#ifndef ZZIP_PACKAGE_BUGREPORT
+#define ZZIP_PACKAGE_BUGREPORT ""
+#endif
+
+/* Define to the full name of this package. */
+#ifndef ZZIP_PACKAGE_NAME
+#define ZZIP_PACKAGE_NAME ""
+#endif
+
+/* Define to the full name and version of this package. */
+#ifndef ZZIP_PACKAGE_STRING
+#define ZZIP_PACKAGE_STRING ""
+#endif
+
+/* Define to the one symbol short name of this package. */
+#ifndef ZZIP_PACKAGE_TARNAME
+#define ZZIP_PACKAGE_TARNAME ""
+#endif
+
+/* Define to the version of this package. */
+#ifndef ZZIP_PACKAGE_VERSION
+#define ZZIP_PACKAGE_VERSION ""
+#endif
+
+/* The number of bytes in type int */
+#ifndef ZZIP_SIZEOF_INT
+#define ZZIP_SIZEOF_INT 4
+#endif
+
+/* The number of bytes in type long */
+#ifndef ZZIP_SIZEOF_LONG
+#define ZZIP_SIZEOF_LONG 4
+#endif
+
+/* The number of bytes in type short */
+#ifndef ZZIP_SIZEOF_SHORT
+#define ZZIP_SIZEOF_SHORT 2
+#endif
+
+/* Define to 1 if you have the ANSI C header files. */
+#ifndef ZZIP_STDC_HEADERS
+#define ZZIP_STDC_HEADERS 1
+#endif
+
+/* Version number of package */
+#ifndef ZZIP_VERSION
+#define ZZIP_VERSION "0.13.47"
+#endif
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef ZZIP_WORDS_BIGENDIAN */
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#ifndef ZZIP__FILE_OFFSET_BITS
+#define ZZIP__FILE_OFFSET_BITS 64
+#endif
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef ZZIP__LARGE_FILES */
+
+/* Define to `long long' if <sys/types.h> does not define. */
+#ifndef ZZIP___int64
+#define ZZIP___int64 long long
+#endif
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef _zzip_const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef _zzip_inline */
+#endif
+
+/* Define to `_zzip_off_t' if <sys/types.h> does not define. */
+#ifndef _zzip_off64_t
+#define _zzip_off64_t _zzip_off_t
+#endif
+
+/* Define to `long' if <sys/types.h> does not define. */
+/* #undef _zzip_off_t */
+
+/* Define to equivalent of C99 restrict keyword, or to nothing if this is not
+ supported. Do not define if restrict is supported directly. */
+#ifndef _zzip_restrict
+#define _zzip_restrict
+#endif
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef _zzip_size_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef _zzip_ssize_t */
+
+/* once: _ZZIP__CONFIG_H */
+#endif
diff --git a/Build/source/libs/zziplib/zzip/_msvc.h b/Build/source/libs/zziplib/zzip/_msvc.h
new file mode 100644
index 00000000000..e852513445c
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/_msvc.h
@@ -0,0 +1,211 @@
+#ifndef _ZZIP__MSVC_H
+#define _ZZIP__MSVC_H 1
+
+/* zzip/_msvc.h. Generated automatically at end of configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the <byteswap.h> header file. */
+/* #undef ZZIP_HAVE_BYTESWAP_H */
+
+/* Define to 1 if you have the <direct.h> header file. */
+#ifndef ZZIP_HAVE_DIRECT_H
+#define ZZIP_HAVE_DIRECT_H 1
+#endif
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+/* #undef ZZIP_HAVE_DIRENT_H */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+/* #undef ZZIP_HAVE_DLFCN_H */
+
+/* Define to 1 if you have the <fnmatch.h> header file. */
+/* #undef ZZIP_HAVE_FNMATCH_H */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+/* #undef ZZIP_HAVE_INTTYPES_H */
+
+/* Define to 1 if you have the <io.h> header file. */
+#ifndef ZZIP_HAVE_IO_H
+#define ZZIP_HAVE_IO_H 1
+#endif
+
+/* Define to 1 if you have the <memory.h> header file. */
+#ifndef ZZIP_HAVE_MEMORY_H
+#define ZZIP_HAVE_MEMORY_H 1
+#endif
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef ZZIP_HAVE_NDIR_H */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+/* #undef ZZIP_HAVE_STDINT_H */
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#ifndef ZZIP_HAVE_STDLIB_H
+#define ZZIP_HAVE_STDLIB_H 1
+#endif
+
+/* Define to 1 if you have the `strcasecmp' function. */
+/* #undef ZZIP_HAVE_STRCASECMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+/* #undef ZZIP_HAVE_STRINGS_H */
+
+/* Define to 1 if you have the <string.h> header file. */
+#ifndef ZZIP_HAVE_STRING_H
+#define ZZIP_HAVE_STRING_H 1
+#endif
+
+/* Define to 1 if you have the `strndup' function. */
+/* #undef ZZIP_HAVE_STRNDUP */
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+/* #undef ZZIP_HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/int_types.h> header file. */
+/* #undef ZZIP_HAVE_SYS_INT_TYPES_H */
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+/* #undef ZZIP_HAVE_SYS_MMAN_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+/* #undef ZZIP_HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+/* #undef ZZIP_HAVE_SYS_PARAM_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#ifndef ZZIP_HAVE_SYS_STAT_H
+#define ZZIP_HAVE_SYS_STAT_H 1
+#endif
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#ifndef ZZIP_HAVE_SYS_TYPES_H
+#define ZZIP_HAVE_SYS_TYPES_H 1
+#endif
+
+/* Define to 1 if you have the <unistd.h> header file. */
+/* #undef ZZIP_HAVE_UNISTD_H */
+
+/* Define to 1 if you have the <winbase.h> header file. */
+#ifndef ZZIP_HAVE_WINBASE_H
+#define ZZIP_HAVE_WINBASE_H 1 /* hmm, is that win32 ? */
+#endif
+
+/* Define to 1 if you have the <windows.h> header file. */
+#ifndef ZZIP_HAVE_WINDOWS_H
+#define ZZIP_HAVE_WINDOWS_H 1 /* yes, this is windows */
+#endif
+
+/* Define to 1 if you have the <winnt.h> header file. */
+#ifndef ZZIP_HAVE_WINNT_H
+#define ZZIP_HAVE_WINNT_H 1 /* is that always true? */
+#endif
+
+/* Define to 1 if you have the <zlib.h> header file. */
+#ifndef ZZIP_HAVE_ZLIB_H
+#define ZZIP_HAVE_ZLIB_H 1 /* you do have it, right? */
+#endif
+
+/* whether the system defaults to 32bit off_t but can do 64bit when requested
+ */
+/* #undef ZZIP_LARGEFILE_SENSITIVE */
+
+/* Name of package */
+#ifndef ZZIP_PACKAGE
+#define ZZIP_PACKAGE "zziplib-msvc" /* yes, make it known */
+#endif
+
+/* Define to the address where bug reports for this package should be sent. */
+/* #undef ZZIP_PACKAGE_BUGREPORT */
+
+/* Define to the full name of this package. */
+/* #undef ZZIP_PACKAGE_NAME */
+
+/* Define to the full name and version of this package. */
+/* #undef ZZIP_PACKAGE_STRING */
+
+/* Define to the one symbol short name of this package. */
+/* #undef ZZIP_PACKAGE_TARNAME */
+
+/* Define to the version of this package. */
+/* #undef ZZIP_PACKAGE_VERSION */
+
+/* The number of bytes in type int */
+#ifndef ZZIP_SIZEOF_INT
+#define ZZIP_SIZEOF_INT 4
+#endif
+
+/* The number of bytes in type long */
+#ifndef ZZIP_SIZEOF_LONG
+#define ZZIP_SIZEOF_LONG 4
+#endif
+
+/* The number of bytes in type short */
+#ifndef ZZIP_SIZEOF_SHORT
+#define ZZIP_SIZEOF_SHORT 2
+#endif
+
+/* Define to 1 if you have the ANSI C header files. */
+#ifndef ZZIP_STDC_HEADERS
+#define ZZIP_STDC_HEADERS 1
+#endif
+
+/* Version number of package */
+#ifndef ZZIP_VERSION
+#define ZZIP_VERSION "0.13.x"
+#endif
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef ZZIP_WORDS_BIGENDIAN */
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef ZZIP__FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef ZZIP__LARGE_FILES */
+
+/* Define to `long long' if <sys/types.h> does not define. */
+/* #undef ZZIP___int64 */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef _zzip_const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#ifndef _zzip_inline
+#define _zzip_inline __inline
+#endif
+#endif
+
+/* Define to `_zzip_off_t' if <sys/types.h> does not define. */
+#ifndef _zzip_off64_t
+#define _zzip_off64_t __int64
+#endif
+
+/* Define to `long' if <sys/types.h> does not define. */
+#ifndef _zzip_off_t
+#define _zzip_off_t long
+#endif
+
+/* Define to equivalent of C99 restrict keyword, or to nothing if this is not
+ supported. Do not define if restrict is supported directly. */
+#ifndef _zzip_restrict
+#define _zzip_restrict
+#endif
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef _zzip_size_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+#ifndef _zzip_ssize_t
+#define _zzip_ssize_t int
+#endif
+
+/* once: _ZZIP__MSVC_H */
+#endif
diff --git a/Build/source/libs/zziplib/zzip/_msvc.sed b/Build/source/libs/zziplib/zzip/_msvc.sed
new file mode 100644
index 00000000000..ec1fcbba192
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/_msvc.sed
@@ -0,0 +1,26 @@
+s:undef *HAVE_MEMORY_H *$:define HAVE_MEMORY_H 1:
+s:undef *HAVE_STDLIB_H *$:define HAVE_STDLIB_H 1:
+s:undef *HAVE_STRING_H *$:define HAVE_STRING_H 1:
+s:undef *HAVE_SYS_STAT_H *$:define HAVE_SYS_STAT_H 1:
+s:undef *HAVE_SYS_TYPES_H *$:define HAVE_SYS_TYPES_H 1:
+s:undef *HAVE_DIRECT_H *$:define HAVE_DIRECT_H 1:
+s:undef *HAVE_IO_H *$:define HAVE_IO_H 1:
+s:undef *HAVE_WINDOWS_H *$:define HAVE_WINDOWS_H 1 /* yes, this is windows */:
+s:undef *HAVE_WINBASE_H *$:define HAVE_WINBASE_H 1 /* hmm, is that win32 ? */:
+s:undef *HAVE_WINNT_H *$:define HAVE_WINNT_H 1 /* is that always true? */:
+s:undef *HAVE_ZLIB_H *$:define HAVE_ZLIB_H 1 /* you do have it, right? */:
+s:undef *PACKAGE *$:define PACKAGE "zziplib-msvc" /* yes, make it known */:
+s:undef *SIZEOF_INT *$:define SIZEOF_INT 4:
+s:undef *SIZEOF_LONG *$:define SIZEOF_LONG 4:
+s:undef *SIZEOF_SHORT *$:define SIZEOF_SHORT 2:
+s:undef *STDC_HEADERS *$:define STDC_HEADERS 1:
+s:undef *inline *$:define inline __inline:
+s:undef *off_t *$:define off_t long:
+s:undef *off64_t *$:define off64_t __int64:
+s:undef *ssize_t *$:define ssize_t int:
+s:undef restrict *$:define restrict:
+s:undef VERSION:define VERSION "0.13.x":
+s:^ *# *undef.*$:/* & */:
+/Generated automatically .* by autoheader/a\
+/* config values have been automatically set by zzip/_msvc.sed */
+
diff --git a/Build/source/libs/zziplib/zzip/autoconf.h b/Build/source/libs/zziplib/zzip/autoconf.h
new file mode 100644
index 00000000000..f0d6841454a
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/autoconf.h
@@ -0,0 +1,45 @@
+#ifndef _ZZIP_AUTOCONF_H_
+#define _ZZIP_AUTOCONF_H_ 1
+
+/*
+ * This file is trying to override configure time checks of zzip with
+ * definitions at compile time. This is not used by zzip sources themselves
+ * but it may be really helpful with thirdparty software that happens to
+ * include zzip headers from a central place but running on a different host.
+ */
+
+#include "conf.h" /* <zzip/conf.h> : <zzip/_config.h> */
+
+#if defined HAVE_ENDIAN_H || defined ZZIP_HAVE_ENDIAN_H
+#include <endian.h> /* glibc */
+#elif defined HAVE_SYS_PARAM_H || defined ZZIP_HAVE_SYS_PARAM_H
+#include <sys/param.h> /* solaris */
+#endif
+
+#if defined __BYTE_ORDER
+#define ZZIP_BYTE_ORDER __BYTE_ORDER
+#elif defined BYTE_ORDER
+#define ZZIP_BYTE_ORDER BYTE_ORDER
+#elif defined _LITTLE_ENDIAN
+#define ZZIP_BYTE_ORDER 1234
+#elif defined _BIG_ENDIAN
+#define ZZIP_BYTE_ORDER 4321
+#elif defined __i386__
+#define ZZIP_BYTE_ORDER 1234
+#elif defined WORDS_BIGENDIAN || defined ZZIP_WORDS_BIGENDIAN
+#define ZZIP_BYTE_ORDER 4321
+#else
+#define ZZIP_BYTE_ORDER 1234
+#endif
+
+/* override ZZIP_WORDS_BIGENDIAN : macros ZZIP_GET16 / ZZIP_GET32 */
+#ifdef ZZIP_BYTE_ORDER+0 == 1234
+#undef ZZIP_WORDS_BIGENDIAN
+#endif
+#ifdef ZZIP_BYTE_ORDER+0 == 4321
+#ifndef ZZIP_WORDS_BIGENDIAN
+#define ZZIP_WORDS_BIGENDIAN 1
+#endif
+#endif
+
+#endif
diff --git a/Build/source/libs/zziplib/zzip/conf.h b/Build/source/libs/zziplib/zzip/conf.h
new file mode 100644
index 00000000000..1f58a164dba
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/conf.h
@@ -0,0 +1,270 @@
+/*
+ * Here we postprocess autoconf generated prefix-config.h entries.
+ * This is generally for things like "off_t" which is left undefined
+ * in plain config.h if the host system does already have it but we do
+ * need the prefix variant - so we add here a #define _zzip_off_t off_t
+ *
+ * This file is supposed to only carry '#define's.
+ * See <zzip/types.h> for definitions that might be seen by the compiler.
+ *
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 2001,2002,2003,2004 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#ifndef _ZZIP_CONF_H
+#define _ZZIP_CONF_H 1
+
+#if !defined ZZIP_OMIT_CONFIG_H
+# if defined _MSC_VER || defined __BORLANDC__ || defined __WATCOMC__
+# include <zzip/_msvc.h>
+# elif defined ZZIP_1_H
+# include "zzip-1.h"
+# elif defined ZZIP_2_H
+# include "zzip-2.h"
+# elif defined ZZIP_3_H
+# include "zzip-3.h"
+# elif defined ZZIP_4_H
+# include "zzip-4.h"
+# elif defined ZZIP_5_H
+# include "zzip-5.h"
+# else /* autoconf generated */
+# include <zzip/_config.h>
+# endif
+#endif
+
+/* especially win32 platforms do not declare off_t so far - see zzip-msvc.h */
+#ifndef _zzip_off_t
+#ifdef ZZIP_off_t
+#define _zzip_off_t ZZIP_off_t
+#else
+#define _zzip_off_t off_t
+#endif
+#endif
+
+#ifndef _zzip_off64_t
+#ifdef ZZIP_off64_t
+#define _zzip_off64_t ZZIP_off64_t
+#else
+#define _zzip_off64_t off64_t
+#endif
+#endif
+
+/* currently unused, all current zziplib-users do have ansi-C94 compilers. */
+#ifndef _zzip_const
+#ifdef ZZIP_const
+#define _zzip_const ZZIP_const
+#else
+#define _zzip_const const
+#endif
+#endif
+#ifndef _zzip_inline
+#ifdef ZZIP_inline
+#define _zzip_inline ZZIP_inline
+#else
+#define _zzip_inline inline
+#endif
+#endif
+#ifndef _zzip_restrict
+#ifdef ZZIP_restrict
+#define _zzip_restrict ZZIP_restrict
+#else
+#define _zzip_restrict restrict
+#endif
+#endif
+#if defined __linux__ && __GNUC__+0 >= 4
+#define zzip__new__ __attribute__((malloc))
+#elif defined __linux__ && __GNUC__+0 >= 3 && __GNUC_MINOR_+0 >= 3
+#define zzip__new__ __attribute__((malloc))
+#else
+#define zzip__new__
+#endif
+
+#ifndef _zzip_size_t
+#ifdef ZZIP_size_t
+#define _zzip_size_t ZZIP_size_t
+#else
+#define _zzip_size_t size_t
+#endif
+#endif
+#ifndef _zzip_ssize_t
+#ifdef ZZIP_ssize_t
+#define _zzip_ssize_t ZZIP_ssize_t
+#else
+#define _zzip_ssize_t ssize_t
+#endif
+#endif
+#ifndef _zzip___int64
+#ifdef ZZIP___int64
+#define _zzip___int64 ZZIP___int64
+#else
+#define _zzip___int64 long long
+#endif
+#endif
+
+/* whether this library shall use a 64bit off_t largefile variant in 64on32: */
+/* (some exported names must be renamed to avoid bad calls after linking) */
+#if defined ZZIP_LARGEFILE_SENSITIVE
+# if _FILE_OFFSET_BITS+0 == 64
+# define ZZIP_LARGEFILE_RENAME
+# elif defined _LARGE_FILES /* used on older AIX to get at 64bit off_t */
+# define ZZIP_LARGEFILE_RENAME
+# elif defined _ZZIP_LARGEFILE /* or simply use this one for zzip64 runs */
+# define ZZIP_LARGEFILE_RENAME
+# endif
+#endif
+
+/* if the environment did not setup these for 64bit off_t largefile... */
+#ifdef ZZIP_LARGEFILE_RENAME
+# ifndef _FILE_OFFSET_BITS
+# ifdef ZZIP__FILE_OFFSET_BITS /* == 64 */
+# define _FILE_OFFSET_BITS ZZIP__FILE_OFFSET_BITS
+# endif
+# endif
+# ifndef _LARGE_FILES
+# ifdef ZZIP__LARGE_FILES /* == 1 */
+# define _LARGE_FILES ZZIP__LARGE_FILES
+# endif
+# endif
+# ifndef _LARGEFILE_SOURCE
+# ifdef ZZIP__LARGEFILE_SOURCE /* == 1 */
+# define _LARGEFILE_SOURCE ZZIP__LARGEFILE_SOURCE
+# endif
+# endif
+#endif
+
+#include <errno.h>
+
+/* mingw32msvc errno : would be in winsock.h */
+#ifndef EREMOTE
+#define EREMOTE ESPIPE
+#endif
+
+#ifndef ELOOP
+#if defined EILSEQ
+#define ELOOP EILSEQ
+#else
+#define ELOOP ENOEXEC
+#endif
+#endif
+
+#if defined __WATCOMC__
+#undef _zzip_inline
+#define _zzip_inline static
+#endif
+
+#if defined _MSC_VER || defined __WATCOMC__
+#include <io.h>
+#endif
+
+#ifdef _MSC_VER
+# if !__STDC__
+# ifndef _zzip_lseek
+# define _zzip_lseek _lseek
+# endif
+# ifndef _zzip_read
+# define _zzip_read _read
+# endif
+# ifndef _zzip_write
+# define _zzip_write _write
+# endif
+# if 0
+# ifndef _zzip_stat
+# define _zzip_stat _stat
+# endif
+# endif
+# endif /* !__STDC__ */
+#endif
+ /*MSVC*/
+
+#if defined _MSC_VER || defined __WATCOMC__
+# ifndef strcasecmp
+# define strcasecmp _stricmp
+# endif
+#endif
+
+# ifndef _zzip_lseek
+# define _zzip_lseek lseek
+# endif
+
+# ifndef _zzip_read
+# define _zzip_read read
+# endif
+
+# ifndef _zzip_write
+# define _zzip_write write
+# endif
+
+# if 0
+# ifndef _zzip_stat
+# define _zzip_stat stat
+# endif
+# endif
+
+
+#if defined __GNUC__ || defined __attribute__
+#define __zzip_attribute__(X) __attribute__(X)
+#else
+#define __zzip_attribute__(X)
+#endif
+
+#if defined ZZIP_EXPORTS || defined ZZIPLIB_EXPORTS
+# undef ZZIP_DLL
+#define ZZIP_DLL 1
+#endif
+
+/* based on zconf.h : */
+/* compile with -DZZIP_DLL for Windows DLL support */
+#if defined ZZIP_DLL
+# if defined _WINDOWS || defined WINDOWS || defined _WIN32
+/*# include <windows.h>*/
+# endif
+# if !defined _zzip_export && defined _MSC_VER && (defined WIN32 || defined _WIN32)
+# define _zzip_export __declspec(dllexport) /*WINAPI*/
+# endif
+# if !defined _zzip_export && defined __BORLANDC__
+# if __BORLANDC__ >= 0x0500 && defined WIN32
+# include <windows.h>
+# define _zzip_export __declspec(dllexport) /*WINAPI*/
+# else
+# if defined _Windows && defined __DLL__
+# define _zzip_export _export
+# endif
+# endif
+# endif
+# if !defined _zzip_export && defined __GNUC__
+# if defined __declspec
+# define _zzip_export extern __declspec(dllexport)
+# else
+# define _zzip_export extern
+# endif
+# endif
+# if !defined _zzip_export && defined __BEOS__
+# define _zzip_export extern __declspec(export)
+# endif
+# if !defined _zzip_export && defined __WATCOMC__
+# define _zzip_export extern __declspec(dllexport)
+# define ZEXPORT __syscall
+# define ZEXTERN extern
+# endif
+#endif
+
+#if !defined _zzip_export
+# if defined __GNUC__ /* || !defined HAVE_LIBZZIP */
+# define _zzip_export extern
+# elif defined __declspec || (defined _MSC_VER && defined ZZIP_DLL)
+# define _zzip_export extern __declspec(dllimport)
+# else
+# define _zzip_export extern
+# endif
+#endif
+
+#endif
+
+
diff --git a/Build/source/libs/zziplib/zzip/dir.c b/Build/source/libs/zziplib/zzip/dir.c
new file mode 100644
index 00000000000..a84a130486a
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/dir.c
@@ -0,0 +1,296 @@
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 1999,2000,2001,2002,2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#include <zzip/lib.h> /* exported... */
+#include <zzip/file.h>
+#include <stddef.h> /*offsetof*/
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef ZZIP_HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#else
+#include <stdio.h>
+#endif
+
+#include <zzip/__dirent.h>
+
+#ifndef offsetof
+#pragma warning had to DEFINE offsetof as it was not in stddef.h
+#define offsetof(T,M) ((unsigned)(& ((T*)0)->M))
+#endif
+
+#ifdef ZZIP_HAVE_SYS_STAT_H
+/* MSVC does have IFbitmask but not the corresponding IStests */
+# if !defined S_ISDIR && defined S_IFDIR
+# define S_ISDIR(_X_) ((_X_) & S_IFDIR)
+# endif
+# if !defined S_ISREG && defined S_IFREG
+# define S_ISREG(_X_) ((_X_) & S_IFREG)
+# endif
+#endif
+
+/**
+ * This function is the equivalent of a => rewinddir(2) for a realdir or
+ * the zipfile in place of a directory. The ZZIP_DIR handle returned from
+ * => zzip_opendir has a flag saying realdir or zipfile. As for a zipfile,
+ * the filenames will include the filesubpath, so take care.
+ */
+void
+zzip_rewinddir(ZZIP_DIR * dir)
+{
+ if (! dir) return;
+
+ if (USE_DIRENT && dir->realdir)
+ {
+ _zzip_rewinddir(dir->realdir);
+ return;
+ }
+
+ if (dir->hdr0)
+ dir->hdr = dir->hdr0;
+ else
+ dir->hdr = 0;
+}
+
+#if ! USE_DIRENT
+#define real_readdir(_X_) 1
+#else
+static int
+real_readdir(ZZIP_DIR* dir)
+{
+ struct stat st = { 0 };
+ char filename[PATH_MAX];
+ struct dirent* dirent = _zzip_readdir(dir->realdir);
+ if (! dirent) return 0;
+
+ dir->dirent.d_name = dirent->d_name;
+ strcpy(filename, dir->realname);
+ strcat(filename, "/");
+ strcat(filename, dirent->d_name);
+
+ if (stat(filename, &st) == -1)
+ return -1;
+
+ dir->dirent.d_csize = dir->dirent.st_size = st.st_size;
+
+ if (st.st_mode)
+ {
+ if (! S_ISREG(st.st_mode))
+ {
+ dir->dirent.d_compr = st.st_mode;
+ dir->dirent.d_compr |= 0x80000000;
+ /* makes it effectively negative,
+ * but can still be fed to S_ISXXX(x) */
+ }else
+ {
+ dir->dirent.d_compr = 0; /* stored */
+ }
+ }else
+ {
+ dir->dirent.d_compr = 0; /* stored */
+ }
+
+ return 1;
+}
+#endif
+
+/**
+ * This function is the equivalent of a => readdir(2) for a realdir
+ * or a zipfile referenced by the ZZIP_DIR returned from => zzip_opendir.
+ *
+ * The ZZIP_DIR handle (as returned by => zzip_opendir) contains a few more
+ * entries than being copied into the ZZIP_DIRENT. The only valid fields in
+ * a ZZIP_DIRENT are d_name (the file name), d_compr (compression), d_csize
+ * (compressed size), st_size (uncompressed size).
+ */
+ZZIP_DIRENT*
+zzip_readdir(ZZIP_DIR * dir)
+{
+ if (! dir) { errno=EBADF; return 0; }
+
+ if (USE_DIRENT && dir->realdir)
+ {
+ if (! real_readdir(dir))
+ return 0;
+ }else
+ {
+ if (! dir->hdr) return 0;
+
+ dir->dirent.d_name = dir->hdr->d_name;
+ dir->dirent.d_compr = dir->hdr->d_compr;
+
+ dir->dirent.d_csize = dir->hdr->d_csize;
+ dir->dirent.st_size = dir->hdr->d_usize;
+
+ if (! dir->hdr->d_reclen) dir->hdr = 0;
+ else dir->hdr = (struct zzip_dir_hdr *)
+ ((char *)dir->hdr + dir->hdr->d_reclen);
+ }
+ return &dir->dirent;
+}
+
+/** => zzip_rewinddir
+ * This function is the equivalent of => telldir(2) for a realdir or zipfile.
+ */
+zzip_off_t
+zzip_telldir(ZZIP_DIR* dir)
+{
+ if (! dir) { errno=EBADF; return -1; }
+
+ if (USE_DIRENT && dir->realdir)
+ {
+ return _zzip_telldir(dir->realdir);
+ }else
+ {
+ return ((zzip_off_t) ((char*) dir->hdr - (char*) dir->hdr0));
+ }
+}
+
+/** => zzip_rewinddir
+ * This function is the equivalent of => seekdir(2) for a realdir or zipfile.
+ */
+void
+zzip_seekdir(ZZIP_DIR* dir, zzip_off_t offset)
+{
+ if (! dir) return;
+
+ if (USE_DIRENT && dir->realdir)
+ {
+ _zzip_seekdir(dir->realdir, offset);
+ }else
+ {
+ dir->hdr = (struct zzip_dir_hdr*)
+ (dir->hdr0 ? (char*) dir->hdr0 + (size_t) offset : 0);
+ }
+}
+
+#if defined ZZIP_LARGEFILE_RENAME && defined EOVERFLOW && defined PIC
+#undef zzip_seekdir /* zzip_seekdir64 */
+#undef zzip_telldir /* zzip_telldir64 */
+
+long zzip_telldir(ZZIP_DIR* dir);
+void zzip_seekdir(ZZIP_DIR* dir, long offset);
+
+/* DLL compatibility layer - so that 32bit code can link with this lib too */
+
+long zzip_telldir(ZZIP_DIR* dir)
+{
+ off_t off = zzip_telldir64 (dir);
+ long offs = off;
+ if (offs != off) { errno = EOVERFLOW; return -1; }
+ return offs;
+}
+
+void zzip_seekdir(ZZIP_DIR* dir, long offset)
+{
+ zzip_seekdir64 (dir, offset);
+}
+#endif
+
+/**
+ * This function is the equivalent of => opendir(3) for a realdir or zipfile.
+ *
+ * This function has some magic - if the given argument-path
+ * is a directory, it will wrap a real => opendir(3) into the ZZIP_DIR
+ * structure. Otherwise it will divert to => zzip_dir_open which
+ * can also attach a ".zip" extension if needed to find the archive.
+ *
+ * the error-code is mapped to => errno(3).
+ */
+ZZIP_DIR*
+zzip_opendir(zzip_char_t* filename)
+{
+ return zzip_opendir_ext_io (filename, 0, 0, 0);
+}
+
+/** => zzip_opendir
+ * This function uses explicit ext and io instead of the internal
+ * defaults, setting them to zero is equivalent to => zzip_opendir
+ */
+ZZIP_DIR*
+zzip_opendir_ext_io(zzip_char_t* filename, int o_modes,
+ zzip_strings_t* ext, zzip_plugin_io_t io)
+{
+ zzip_error_t e;
+ ZZIP_DIR* dir;
+
+# ifdef ZZIP_HAVE_SYS_STAT_H
+ struct stat st;
+# endif
+
+ if (o_modes & (ZZIP_PREFERZIP|ZZIP_ONLYZIP)) goto try_zzip;
+ try_real:
+
+# ifdef ZZIP_HAVE_SYS_STAT_H
+ if (stat(filename, &st) >= 0 && S_ISDIR(st.st_mode)
+ ){
+ if (USE_DIRENT)
+ {
+ _zzip_DIR* realdir = _zzip_opendir(filename);
+ if (realdir)
+ {
+ if (! (dir = (ZZIP_DIR *)calloc(1, sizeof (*dir))))
+ {
+ _zzip_closedir(realdir);
+ return 0;
+ }else
+ {
+ dir->realdir = realdir;
+ dir->realname = strdup(filename);
+ return dir;
+ }
+ }
+ }
+ return 0;
+ }
+# endif /* HAVE_SYS_STAT_H */
+
+ try_zzip:
+ dir = zzip_dir_open_ext_io (filename, &e, ext, io);
+ if (! dir && (o_modes & ZZIP_PREFERZIP)) goto try_real;
+ if (e) errno = zzip_errno(e);
+ return dir;
+}
+
+/**
+ * This function is the equivalent of => closedir(3) for a realdir or zipfile.
+ *
+ * This function is magic - if the given arg-ZZIP_DIR
+ * is a real directory, it will call the real => closedir(3) and then
+ * free the wrapping ZZIP_DIR structure. Otherwise it will divert
+ * to => zzip_dir_close which will free the ZZIP_DIR structure.
+ */
+int
+zzip_closedir(ZZIP_DIR* dir)
+{
+ if (! dir) { errno = EBADF; return -1; }
+
+ if (USE_DIRENT && dir->realdir)
+ {
+ _zzip_closedir(dir->realdir);
+ free(dir->realname);
+ free(dir);
+ return 0;
+ }else
+ {
+ zzip_dir_close(dir);
+ return 0;
+ }
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/zzip/err.c b/Build/source/libs/zziplib/zzip/err.c
new file mode 100644
index 00000000000..2f05bb92247
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/err.c
@@ -0,0 +1,156 @@
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ * Tomi Ollila <Tomi.Ollila@iki.fi>
+ *
+ * Copyright (c) 1999,2000,2001,2002,2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#include <zzip/lib.h> /* exported... */
+#include <zlib.h>
+
+#include <string.h>
+#include <errno.h>
+
+#include <zzip/file.h>
+
+static struct errlistentry { int code; const char* mesg; }
+errlist[] =
+{
+ { ZZIP_NO_ERROR, "No error" },
+ { ZZIP_OUTOFMEM,
+ "could not get temporary memory for internal structures" },
+ { ZZIP_DIR_OPEN, "Failed to open zip-file %s" },
+ { ZZIP_DIR_STAT, "Failed to fstat zip-file %s" },
+ { ZZIP_DIR_SEEK, "Failed to lseek zip-file %s" },
+ { ZZIP_DIR_READ, "Failed to read zip-file %s"},
+ { ZZIP_DIR_TOO_SHORT, "zip-file %s too short" },
+ { ZZIP_DIR_EDH_MISSING, "zip-file central directory not found" },
+ { ZZIP_DIRSIZE, "Directory size too big..." },
+ { ZZIP_ENOENT, "No such file found in zip-file %s" },
+ { ZZIP_UNSUPP_COMPR, "Unsupported compression format" },
+ { ZZIP_CORRUPTED, "Zipfile corrupted" },
+ { ZZIP_UNDEF, "Some undefined error occurred" },
+ { ZZIP_DIR_LARGEFILE, "Directory is largefile variant" },
+ { 0, 0 },
+};
+
+#define errlistSIZE (sizeof(errlist)/sizeof(*errlist))
+
+/**
+ * returns the static string for the given error code. The
+ * error code can be either a normal system error (a
+ * positive error code will flag this), it can be => libz
+ * error code (a small negative error code will flag this)
+ * or it can be an error code from => libzzip, which is an
+ * negative value lower than => ZZIP_ERROR
+ */
+zzip_char_t*
+zzip_strerror(int errcode)
+{
+ if (errcode < ZZIP_ERROR && errcode > ZZIP_ERROR-32)
+ {
+ struct errlistentry* err = errlist;
+ for (; err->mesg ; err++)
+ {
+ if (err->code == errcode)
+ return err->mesg;
+ }
+ errcode = EINVAL;
+ }
+
+ if (errcode < 0)
+ {
+ if (errcode == -1)
+ return strerror(errcode);
+ else
+ return zError(errcode);
+ }
+
+ return strerror (errcode);
+}
+
+/** => zzip_strerror
+ * This function fetches the errorcode from the => DIR-handle and
+ * runs it through => zzip_strerror to obtain the static string
+ * describing the error.
+ */
+zzip_char_t*
+zzip_strerror_of(ZZIP_DIR* dir)
+{
+ if (! dir) return strerror (errno);
+ return zzip_strerror(dir->errcode);
+}
+
+static struct errnolistentry { int code; int e_no; }
+errnolist[] =
+{
+ { Z_STREAM_ERROR, EPIPE },
+ { Z_DATA_ERROR, ESPIPE },
+ { Z_MEM_ERROR, ENOMEM },
+ { Z_BUF_ERROR, EMFILE },
+ { Z_VERSION_ERROR, ENOEXEC },
+
+ { ZZIP_DIR_OPEN, ENOTDIR },
+ { ZZIP_DIR_STAT, EREMOTE },
+ { ZZIP_DIR_SEEK, ESPIPE },
+# ifdef ESTRPIPE
+ { ZZIP_DIR_READ, ESTRPIPE},
+# else
+ { ZZIP_DIR_READ, EPIPE},
+# endif
+ { ZZIP_DIR_TOO_SHORT, ENOEXEC },
+# ifdef ENOMEDIUM
+ { ZZIP_DIR_EDH_MISSING, ENOMEDIUM },
+# else
+ { ZZIP_DIR_EDH_MISSING, EIO },
+# endif
+ { ZZIP_DIRSIZE, EFBIG },
+ { ZZIP_OUTOFMEM, ENOMEM },
+ { ZZIP_ENOENT, ENOENT },
+# ifdef EPFNOSUPPORT
+ { ZZIP_UNSUPP_COMPR, EPFNOSUPPORT },
+# else
+ { ZZIP_UNSUPP_COMPR, EACCES },
+# endif
+# ifdef EILSEQ
+ { ZZIP_CORRUPTED, EILSEQ },
+# else
+ { ZZIP_CORRUPTED, ELOOP },
+# endif
+ { ZZIP_UNDEF, EINVAL },
+ { 0, 0 },
+};
+
+/**
+ * map the error code to a system error code. This is used
+ * for the drop-in replacement functions to return a value
+ * that can be interpreted correctly by code sections that
+ * are unaware of the fact they their => open(2) call had been
+ * diverted to a file inside a zip-archive.
+ */
+int
+zzip_errno(int errcode)
+{
+ if (errcode >= -1) return errno;
+
+ { struct errnolistentry* err = errnolist;
+ for (; err->code ; err++)
+ {
+ if (err->code == errcode)
+ return err->e_no;
+ }
+ }
+ return EINVAL;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/zzip/fetch.c b/Build/source/libs/zziplib/zzip/fetch.c
new file mode 100644
index 00000000000..23be82376df
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/fetch.c
@@ -0,0 +1,117 @@
+#include <zzip/fetch.h>
+
+#if defined ZZIP_WORDS_BIGENDIAN && \
+ defined bswap_16 && defined bswap_32 && defined bswap_64
+# define __ZZIP_GET16(__p) bswap_16(*(uint16_t*)(__p))
+# define __ZZIP_GET32(__p) bswap_32(*(uint32_t*)(__p))
+# define __ZZIP_SET16(__p,__x) (*(uint16_t*)(__p) = bswap_16((uint16_t)(__x)))
+# define __ZZIP_SET32(__p,__x) (*(uint32_t*)(__p) = bswap_32((uint32_t)(__x)))
+# define __ZZIP_GET64(__p) bswap_64(*(zzip_off64_t*)(__p))
+# define __ZZIP_SET64(__p,__x) \
+ (*(zzip_off64_t*)(__p) = bswap_64((zzip_off64_t)(__x)))
+#endif
+
+/* ------------------------- fetch helpers --------------------------------- */
+
+/**
+ * Make 32 bit value in host byteorder from little-endian mapped octet-data
+ * (works also on machines which SIGBUS on misaligned data access (eg. 68000))
+ */
+uint32_t __zzip_get32(unsigned char * s)
+{
+#if defined __ZZIP_GET32
+ return __ZZIP_GET32(s);
+#else
+ return ((uint32_t)s[3] << 24) | ((uint32_t)s[2] << 16)
+ | ((uint32_t)s[1] << 8) | ((uint32_t)s[0]);
+#endif
+}
+
+/** => __zzip_get32
+ * This function does the same for a 16 bit value.
+ */
+uint16_t __zzip_get16(unsigned char * s)
+{
+#if defined __ZZIP_GET16
+ return __ZZIP_GET16(s);
+#else
+ return ((uint16_t)s[1] << 8) | ((uint16_t)s[0]);
+#endif
+}
+
+/** => __zzip_get32
+ * This function does the same for an off64_t value.
+ */
+uint64_t __zzip_get64(unsigned char * s)
+{
+#ifdef __GNUC__
+ register uint64_t v
+ = s[7]; v <<= 8;
+ v |= s[6]; v <<= 8;
+ v |= s[5]; v <<= 8;
+ v |= s[4]; v <<= 8;
+ v |= s[3]; v <<= 8;
+ v |= s[2]; v <<= 8;
+ v |= s[1]; v <<= 8;
+ v |= s[0]; return v;
+#else
+ return ((uint64_t)s[7] << 56) | ((uint64_t)s[6] << 48)
+ | ((uint64_t)s[5] << 40) | ((uint64_t)s[4] << 32)
+ | ((uint64_t)s[3] << 24) | ((uint64_t)s[2] << 16)
+ | ((uint64_t)s[1] << 8) | ((uint64_t)s[0]);
+#endif
+}
+
+/** => __zzip_get32
+ * This function pushes a 32bit value at the specified address
+ */
+void __zzip_set32(unsigned char * s, uint32_t v)
+{
+#if defined __ZZIP_SET32
+ return __ZZIP_SET32(s, v);
+#else
+ s[0] = (unsigned char) (v);
+ v >>= 8;
+ s[1] = (unsigned char) (v);
+ v >>= 8;
+ s[2] = (unsigned char) (v);
+ v >>= 8;
+ s[3] = (unsigned char) (v);
+#endif
+}
+
+/** => __zzip_get32
+ * This function does the same for a 16 bit value.
+ */
+void __zzip_set16(unsigned char * s, uint16_t v)
+{
+#if defined __ZZIP_SET16
+ return __ZZIP_SET16(s, v);
+#else
+ s[0] = (unsigned char) (v);
+ v >>= 8;
+ s[1] = (unsigned char) (v);
+#endif
+}
+
+/** => __zzip_get32
+ * This function pushes a off64_t value at the specified address
+ */
+void __zzip_set64(unsigned char * s, uint64_t v)
+{
+ s[0] = (unsigned char) (v);
+ v >>= 8;
+ s[1] = (unsigned char) (v);
+ v >>= 8;
+ s[2] = (unsigned char) (v);
+ v >>= 8;
+ s[3] = (unsigned char) (v);
+ v >>= 8;
+ s[4] = (unsigned char) (v);
+ v >>= 8;
+ s[5] = (unsigned char) (v);
+ v >>= 8;
+ s[6] = (unsigned char) (v);
+ v >>= 8;
+ s[7] = (unsigned char) (v);
+}
diff --git a/Build/source/libs/zziplib/zzip/fetch.h b/Build/source/libs/zziplib/zzip/fetch.h
new file mode 100644
index 00000000000..fda6f9067e6
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/fetch.h
@@ -0,0 +1,343 @@
+#ifndef _ZZIP_FORMATS_H
+#define _ZZIP_FORMATS_H
+
+#include <zzip/types.h>
+#include <zzip/format.h>
+#include <zzip/stdint.h>
+
+/* linux knows "byteswap.h" giving us an optimized variant */
+#ifdef ZZIP_HAVE_BYTESWAP_H
+#include <byteswap.h>
+#endif
+
+/* get 16/32 bits from little-endian zip-file to host byteorder */
+extern uint32_t __zzip_get32(zzip_byte_t * s) __zzip_attribute__((const));
+extern uint16_t __zzip_get16(zzip_byte_t * s) __zzip_attribute__((const));
+extern void __zzip_set32(zzip_byte_t * s, uint32_t v);
+extern void __zzip_set16(zzip_byte_t * s, uint16_t v);
+
+extern uint64_t __zzip_get64(zzip_byte_t * s) __zzip_attribute__((const));
+extern void __zzip_set64(zzip_byte_t * s, uint64_t v);
+
+#ifdef ZZIP_WORDS_BIGENDIAN
+# if defined bswap_16 && defined bswap_32 && defined bswap_64 /* i.e. linux */
+# define ZZIP_GET16(__p) bswap_16(*(uint16_t*)(__p))
+# define ZZIP_GET32(__p) bswap_32(*(uint32_t*)(__p))
+# define ZZIP_GET64(__p) bswap_64(*(uint64_t*)(__p))
+# define ZZIP_SET16(__p,__x) (*(uint16_t*)(__p) = bswap_16((uint16_t)(__x)))
+# define ZZIP_SET32(__p,__x) (*(uint32_t*)(__p) = bswap_32((uint32_t)(__x)))
+# define ZZIP_SET64(__p,__x) (*(uint64_t*)(__p) = bswap_64((uint64_t)(__x)))
+# else
+# define ZZIP_GET64(__p) (__zzip_get64((__p)))
+# define ZZIP_GET32(__p) (__zzip_get32((__p)))
+# define ZZIP_GET16(__p) (__zzip_get16((__p)))
+# define ZZIP_SET64(__p,__x) (__zzip_set64((__p),(__x)))
+# define ZZIP_SET32(__p,__x) (__zzip_set32((__p),(__x)))
+# define ZZIP_SET16(__p,__x) (__zzip_set16((__p),(__x)))
+# endif
+#else /* little endian is the original zip format byteorder */
+# define ZZIP_GET16(__p) (*(uint16_t*)(__p))
+# define ZZIP_GET32(__p) (*(uint32_t*)(__p))
+# define ZZIP_GET64(__p) (*(uint64_t*)(__p))
+# define ZZIP_SET16(__p,__x) (*(uint16_t*)(__p) = (uint16_t)(__x))
+# define ZZIP_SET32(__p,__x) (*(uint32_t*)(__p) = (uint32_t)(__x))
+# define ZZIP_SET64(__p,__x) (*(uint64_t*)(__p) = (uint64_t)(__x))
+#endif
+
+/* ..................... bitcorrect physical access .................... */
+
+/* zzip_file_header - the local file header */
+#define zzip_file_header_get_magic(__p) ZZIP_GET32((__p)->z_magic)
+#define zzip_file_header_set_magic(__p,__x) ZZIP_SET32((__p)->z_magic,(__x))
+#define zzip_file_header_get_flags(__p) ZZIP_GET16((__p)->z_flags)
+#define zzip_file_header_set_flags(__p,__x) ZZIP_SET16((__p)->z_flags,(__x))
+#define zzip_file_header_get_compr(__p) ZZIP_GET16((__p)->z_compr)
+#define zzip_file_header_set_compr(__p,__x) ZZIP_SET16((__p)->z_compr,(__x))
+#define zzip_file_header_get_crc32(__p) ZZIP_GET32((__p)->z_crc32)
+#define zzip_file_header_set_crc32(__p,__x) ZZIP_SET32((__p)->z_crc32,(__x))
+#define zzip_file_header_get_csize(__p) ZZIP_GET32((__p)->z_csize)
+#define zzip_file_header_set_csize(__p,__x) ZZIP_SET32((__p)->z_csize,(__x))
+#define zzip_file_header_get_usize(__p) ZZIP_GET32((__p)->z_usize)
+#define zzip_file_header_set_usize(__p,__x) ZZIP_SET32((__p)->z_usize,(__x))
+#define zzip_file_header_get_namlen(__p) ZZIP_GET16((__p)->z_namlen)
+#define zzip_file_header_set_namlen(__p,__x) ZZIP_SET16((__p)->z_namlen,(__x))
+#define zzip_file_header_get_extras(__p) ZZIP_GET16((__p)->z_extras)
+#define zzip_file_header_set_extras(__p,__x) ZZIP_SET16((__p)->z_extras,(__x))
+#define zzip_file_header_sizeof_tails(__p) (zzip_file_header_get_namlen(__p)+\
+ zzip_file_header_get_extras(__p) )
+#define zzip_file_header_check_magic(__p) ZZIP_FILE_HEADER_CHECKMAGIC((__p))
+
+/* zzip_file_trailer - data descriptor per file block */
+#define zzip_file_trailer_get_magic(__p) ZZIP_GET32((__p)->z_magic)
+#define zzip_file_trailer_set_magic(__p,__x) ZZIP_SET32((__p)->z_magic,(__x))
+#define zzip_file_header_get_crc32(__p) ZZIP_GET32((__p)->z_crc32)
+#define zzip_file_trailer_set_crc32(__p,__x) ZZIP_SET32((__p)->z_crc32,(__x))
+#define zzip_file_trailer_get_csize(__p) ZZIP_GET32((__p)->z_csize)
+#define zzip_file_trailer_set_csize(__p,__x) ZZIP_SET32((__p)->z_csize,(__x))
+#define zzip_file_trailer_get_usize(__p) ZZIP_GET32((__p)->z_usize)
+#define zzip_file_trailer_set_usize(__p,__x) ZZIP_SET32((__p)->z_usize,(__x))
+#define zzip_file_trailer_sizeof_tails(__p) 0
+#define zzip_file_trailer_check_magic(__p) ZZIP_FILE_TRAILER_CHECKMAGIC((__p))
+/* zzip_disk_entry (currently named zzip_root_dirent) */
+#define zzip_disk_entry_get_magic(__p) ZZIP_GET32((__p)->z_magic)
+#define zzip_disk_entry_set_magic(__p,__x) ZZIP_SET32((__p)->z_magic,(__x))
+#define zzip_disk_entry_get_flags(__p) ZZIP_GET16((__p)->z_flags)
+#define zzip_disk_entry_set_flags(__p,__x) ZZIP_SET16((__p)->z_flags,(__x))
+#define zzip_disk_entry_get_compr(__p) ZZIP_GET16((__p)->z_compr)
+#define zzip_disk_entry_set_compr(__p,__x) ZZIP_SET16((__p)->z_compr,(__x))
+#define zzip_disk_entry_get_crc32(__p) ZZIP_GET32((__p)->z_crc32)
+#define zzip_disk_entry_set_crc32(__p,__x) ZZIP_SET32((__p)->z_crc32,(__x))
+#define zzip_disk_entry_get_csize(__p) ZZIP_GET32((__p)->z_csize)
+#define zzip_disk_entry_set_csize(__p,__x) ZZIP_SET32((__p)->z_csize,(__x))
+#define zzip_disk_entry_get_usize(__p) ZZIP_GET32((__p)->z_usize)
+#define zzip_disk_entry_set_usize(__p,__x) ZZIP_SET32((__p)->z_usize,(__x))
+#define zzip_disk_entry_get_namlen(__p) ZZIP_GET16((__p)->z_namlen)
+#define zzip_disk_entry_set_namlen(__p,__x) ZZIP_SET16((__p)->z_namlen,(__x))
+#define zzip_disk_entry_get_extras(__p) ZZIP_GET16((__p)->z_extras)
+#define zzip_disk_entry_set_extras(__p,__x) ZZIP_SET16((__p)->z_extras,(__x))
+#define zzip_disk_entry_get_comment(__p) ZZIP_GET16((__p)->z_comment)
+#define zzip_disk_entry_set_comment(__p,__x) ZZIP_SET16((__p)->z_comment,(__x))
+#define zzip_disk_entry_get_diskstart(__p) ZZIP_GET16((__p)->z_diskstart)
+#define zzip_disk_entry_set_diskstart(__p,__x) ZZIP_SET16((__p)->z_diskstart,(__x))
+#define zzip_disk_entry_get_filetype(__p) ZZIP_GET16((__p)->z_filetype)
+#define zzip_disk_entry_set_filetype(__p,__x) ZZIP_SET16((__p)->z_filetype,(__x))
+#define zzip_disk_entry_get_filemode(__p) ZZIP_GET32((__p)->z_filemode)
+#define zzip_disk_entry_set_filemode(__p,__x) ZZIP_SET32((__p)->z_filemode,(__x))
+#define zzip_disk_entry_get_offset(__p) ZZIP_GET32((__p)->z_offset)
+#define zzip_disk_entry_set_offset(__p,__x) ZZIP_SET32((__p)->z_offset,(__x))
+#define zzip_disk_entry_sizeof_tails(__p) (zzip_disk_entry_get_namlen(__p) +\
+ zzip_disk_entry_get_extras(__p) +\
+ zzip_disk_entry_get_comment(__p) )
+#define zzip_disk_entry_check_magic(__p) ZZIP_DISK_ENTRY_CHECKMAGIC((__p))
+
+/* zzip_disk_trailer - the zip archive entry point */
+#define zzip_disk_trailer_get_magic(__p) ZZIP_GET32((__p)->z_magic)
+#define zzip_disk_trailer_set_magic(__p,__x) ZZIP_SET32((__p)->z_magic,(__x))
+#define zzip_disk_trailer_get_disk(__p) ZZIP_GET16((__p)->z_disk)
+#define zzip_disk_trailer_set_disk(__p,__x) ZZIP_SET16((__p)->z_disk,(__x))
+#define zzip_disk_trailer_get_finaldisk(__p) ZZIP_GET16((__p)->z_finaldisk)
+#define zzip_disk_trailer_set_finaldisk(__p,__x) ZZIP_SET16((__p)->z_finaldisk,(__x))
+#define zzip_disk_trailer_get_entries(__p) ZZIP_GET16((__p)->z_entries)
+#define zzip_disk_trailer_set_entries(__p,__x) ZZIP_SET16((__p)->z_entries,(__x))
+#define zzip_disk_trailer_get_finalentries(__p) ZZIP_GET16((__p)->z_finalentries)
+#define zzip_disk_trailer_set_finalentries(__p,__x) ZZIP_SET16((__p)->z_finalentries,(__x))
+#define zzip_disk_trailer_get_rootsize(__p) ZZIP_GET32((__p)->z_rootsize)
+#define zzip_disk_trailer_set_rootsize(__p,__x) ZZIP_SET32((__p)->z_rootsize,(__x))
+#define zzip_disk_trailer_get_rootseek(__p) ZZIP_GET32((__p)->z_rootseek)
+#define zzip_disk_trailer_set_rootseek(__p,__x) ZZIP_SET32((__p)->z_rootseek,(__x))
+#define zzip_disk_trailer_get_comment(__p) ZZIP_GET16((__p)->z_comment)
+#define zzip_disk_trailer_set_comment(__p,__x) ZZIP_SET16((__p)->z_comment,(__x))
+#define zzip_disk_trailer_sizeof_tails(__p) ( zzip_disk_entry_get_comment(__p))
+#define zzip_disk_trailer_check_magic(__p) ZZIP_DISK_TRAILER_CHECKMAGIC((__p))
+
+/* extra field should be type + size + data + type + size + data ... */
+#define zzip_extra_block_get_datatype(__p) ZZIP_GET16((zzip_byte_t*)(__p))
+#define zzip_extra_block_set_datatype(__p,__x) ZZIP_SET16((zzip_byte_t*)(__p),__x)
+#define zzip_extra_block_get_datasize(__p) ZZIP_GET16((zzip_byte_t*)(__p)+2)
+#define zzip_extra_block_set_datasize(__p,__x) ZZIP_SET16((zzip_byte_t*)(__p)+2,__x)
+
+/* zzip64_disk_trailer - the zip64 archive entry point */
+#define zzip_disk64_trailer_get_magic(__p) ZZIP_GET32((__p)->z_magic)
+#define zzip_disk64_trailer_set_magic(__p,__x) ZZIP_SET32((__p)->z_magic,(__x))
+#define zzip_disk64_trailer_get_size(__p) ZZIP_GET64((__p)->z_size)
+#define zzip_disk64_trailer_set_size(__p,__x) ZZIP_SET64((__p)->z_size,(__x))
+#define zzip_disk64_trailer_get_disk(__p) ZZIP_GET32((__p)->z_disk)
+#define zzip_disk64_trailer_set_disk(__p,__x) ZZIP_SET32((__p)->z_disk,(__x))
+#define zzip_disk64_trailer_get_finaldisk(__p) ZZIP_GET32((__p)->z_finaldisk)
+#define zzip_disk64_trailer_set_finaldisk(__p,__x) ZZIP_SET32((__p)->z_finaldisk,(__x))
+#define zzip_disk64_trailer_get_entries(__p) ZZIP_GET64((__p)->z_entries)
+#define zzip_disk64_trailer_set_entries(__p,__x) ZZIP_SET64((__p)->z_entries,(__x))
+#define zzip_disk64_trailer_get_finalentries(__p) ZZIP_GET64((__p)->z_finalentries)
+#define zzip_disk64_trailer_set_finalentries(__p,__x) ZZIP_SET64((__p)->z_finalentries,(__x))
+#define zzip_disk64_trailer_get_rootsize(__p) ZZIP_GET64((__p)->z_rootsize)
+#define zzip_disk64_trailer_set_rootsize(__p,__x) ZZIP_SET64((__p)->z_rootsize,(__x))
+#define zzip_disk64_trailer_get_rootseek(__p) ZZIP_GET64((__p)->z_rootseek)
+#define zzip_disk64_trailer_set_rootseek(__p,__x) ZZIP_SET64((__p)->z_rootseek,(__x))
+#define zzip_disk64_trailer_check_magic(__p) ZZIP_DISK64_TRAILER_CHECKMAGIC((__p))
+
+/* .............. some logical typed access wrappers ....................... */
+
+/* zzip_file_header - the local file header */
+#define zzip_file_header_csize(__p) ((zzip_size_t) \
+ zzip_file_header_get_csize(__p))
+#define zzip_file_header_usize(__p) ((zzip_size_t) \
+ zzip_file_header_get_usize(__p))
+#define zzip_file_header_namlen(__p) ((zzip_size_t) \
+ zzip_file_header_get_namlen(__p))
+#define zzip_file_header_extras(__p) ((zzip_size_t) \
+ zzip_file_header_get_extras(__p))
+#define zzip_file_header_sizeof_tail(__p) ((zzip_size_t) \
+ zzip_file_header_sizeof_tails(__p))
+#define zzip_file_header_sizeto_end(__p) ((zzip_size_t) \
+ (zzip_file_header_sizeof_tail(__p) + zzip_file_header_headerlength))
+#define zzip_file_header_skipto_end(__p) ((void*) (__p) + \
+ (zzip_file_header_sizeof_tail(__p) + zzip_file_header_headerlength))
+
+#define zzip_file_header_to_filename(__p) ((char*) \
+ ((char*)(__p) + zzip_file_header_headerlength))
+#define zzip_file_header_to_extras(__p) ((char*) \
+ (zzip_file_header_to_filename(__p) + zzip_file_header_namlen(__p)))
+#define zzip_file_header_to_data(__p) ((zzip_byte_t*) \
+ (zzip_file_header_to_extras(__p) + zzip_file_header_extras(__p)))
+#define zzip_file_header_to_trailer(__p) ((struct zzip_file_trailer*) \
+ (zzip_file_header_to_data(__p) + zzip_file_header_csize(__p)))
+
+/* zzip_file_trailer - data descriptor per file block */
+#define zzip_file_trailer_csize(__p) ((zzip_size_t) \
+ zzip_file_trailer_get_csize(__p))
+#define zzip_file_trailer_usize(__p) ((zzip_size_t) \
+ zzip_file_trailer_get_usize(__p))
+#define zzip_file_trailer_sizeof_tail(__p) ((zzip_size_t) \
+ zzip_file_trailer_sizeof_tails(__p))
+#define zzip_file_trailer_sizeto_end(__p) ((zzip_size_t) \
+ (zzip_file_trailer_sizeof_tail(__p) + zzip_file_trailer_headerlength))
+#define zzip_file_trailer_skipto_end(__p) ((void*) (__p) + \
+ (zzip_file_trailer_sizeof_tail(__p) + zzip_file_trailer_headerlength))
+
+/* zzip_disk_entry (currently named zzip_root_dirent) */
+#define zzip_disk_entry_csize(__p) ((zzip_size_t) \
+ zzip_disk_entry_get_csize(__p))
+#define zzip_disk_entry_usize(__p) ((zzip_size_t) \
+ zzip_disk_entry_get_usize(__p))
+#define zzip_disk_entry_namlen(__p) ((zzip_size_t) \
+ zzip_disk_entry_get_namlen(__p))
+#define zzip_disk_entry_extras(__p) ((zzip_size_t) \
+ zzip_disk_entry_get_extras(__p))
+#define zzip_disk_entry_comment(__p) ((zzip_size_t) \
+ zzip_disk_entry_get_comment(__p))
+#define zzip_disk_entry_diskstart(__p) ((int) \
+ zzip_disk_entry_get_diskstart(__p))
+#define zzip_disk_entry_filetype(__p) ((int) \
+ zzip_disk_entry_get_filetype(__p))
+#define zzip_disk_entry_filemode(__p) ((int) \
+ zzip_disk_entry_get_filemode(__p))
+#define zzip_disk_entry_fileoffset(__p) ((zzip_off_t) \
+ zzip_disk_entry_get_offset(__p))
+#define zzip_disk_entry_sizeof_tail(__p) ((zzip_size_t) \
+ zzip_disk_entry_sizeof_tails(__p))
+#define zzip_disk_entry_sizeto_end(__p) ((zzip_size_t) \
+ (zzip_disk_entry_sizeof_tail(__p) + zzip_disk_entry_headerlength))
+#define zzip_disk_entry_skipto_end(__p) ((zzip_byte_t*) (__p) + \
+ (zzip_disk_entry_sizeof_tail(__p) + zzip_disk_entry_headerlength))
+
+#define zzip_disk_entry_to_filename(__p) ((char*) \
+ ((char*)(__p) + zzip_disk_entry_headerlength))
+#define zzip_disk_entry_to_extras(__p) ((char*) \
+ (zzip_disk_entry_to_filename(__p) + zzip_disk_entry_namlen(__p)))
+#define zzip_disk_entry_to_comment(__p) ((char*) \
+ (zzip_disk_entry_to_extras(__p) + zzip_disk_entry_extras(__p)))
+#define zzip_disk_entry_to_next_entry(__p) ((struct zzip_disk_entry*) \
+ (zzip_disk_entry_to_comment(__p) + zzip_disk_entry_comment(__p)))
+
+/* zzip_disk_trailer - the zip archive entry point */
+#define zzip_disk_trailer_localdisk(__p) ((int) \
+ zzip_disk_trailer_get_disk(__p))
+#define zzip_disk_trailer_finaldisk(__p) ((int) \
+ zzip_disk_trailer_get_finaldisk(__p))
+#define zzip_disk_trailer_localentries(__p) ((int) \
+ zzip_disk_trailer_get_entries(__p))
+#define zzip_disk_trailer_finalentries(__p) ((int) \
+ zzip_disk_trailer_get_finalentries(__p))
+#define zzip_disk_trailer_rootsize(__p) ((zzip_off_t) \
+ zzip_disk_trailer_get_rootsize(__p))
+#define zzip_disk_trailer_rootseek(__p) ((zzip_off_t) \
+ zzip_disk_trailer_get_rootseek(__p))
+#define zzip_disk_trailer_comment(__p) ((zzip_size_t) \
+ zzip_disk_trailer_get_comment(__p))
+#define zzip_disk_trailer_sizeof_tail(__p) ((zzip_size_t) \
+ zzip_disk_trailer_sizeof_tails(__p))
+#define zzip_disk_trailer_sizeto_end(__p) ((zzip_size_t) \
+ (zzip_disk_trailer_sizeof_tail(__p) + zzip_disk_trailer_headerlength))
+#define zzip_disk_trailer_skipto_end(__p) ((void*) (__p) \
+ (zzip_disk_trailer_sizeof_tail(__p) + zzip_disk_trailer_headerlength))
+
+#define zzip_disk_trailer_to_comment(__p) ((char*) \
+ ((char*)(__p) + zzip_disk_trailer_headerlength))
+#define zzip_disk_trailer_to_endoffile(__p) ((void*) \
+ (zzip_disk_trailer_to_comment(__p) + zzip_disk_trailer_comment(__p)))
+
+/* zzip_disk64_trailer - the zip archive entry point */
+#define zzip_disk64_trailer_localdisk(__p) ((int) \
+ zzip_disk64_trailer_get_disk(__p))
+#define zzip_disk64_trailer_finaldisk(__p) ((int) \
+ zzip_disk64_trailer_get_finaldisk(__p))
+#define zzip_disk64_trailer_localentries(__p) ((int) \
+ zzip_disk64_trailer_get_entries(__p))
+#define zzip_disk64_trailer_finalentries(__p) ((int) \
+ zzip_disk64_trailer_get_finalentries(__p))
+#define zzip_disk64_trailer_rootsize(__p) ((zzip_off64_t) \
+ zzip_disk64_trailer_get_rootsize(__p))
+#define zzip_disk64_trailer_rootseek(__p) ((zzip_off64_t) \
+ zzip_disk64_trailer_get_rootseek(__p))
+#define zzip_disk64_trailer_sizeof_tail(__p) ((zzip_size_t) \
+ zzip_disk64_trailer_get_size(__p) - zzip_disk64_trailer_headerlength)
+#define zzip_disk64_trailer_sizeto_end(__p) ((zzip_size_t) \
+ zzip_disk64_trailer_get_size(__p))
+#define zzip_disk64_trailer_skipto_end(__p) ((void*) \
+ ((char*)(__p) + zzip_disk64_sizeto_end(__p)))
+
+/* extra field should be type + size + data + type + size + data ... */
+#define zzip_extra_block_sizeof_tail(__p) ((zzip_size_t) \
+ (zzip_extra_block_get_datasize(__p)))
+#define zzip_extra_block_sizeto_end(__p) ((zzip_size_t) \
+ (zzip_extra_block_sizeof_tail(__p) + zzip_extra_block_headerlength))
+#define zzip_extra_block_skipto_end(__p) ((void*) (__p) \
+ (zzip_extra_block_sizeof_tail(__p) + zzip_extra_block_headerlength))
+
+/* ................... and put these to the next level ................ */
+
+#define zzip_file_header_data_encrypted(__p) \
+ ZZIP_IS_ENCRYPTED( zzip_file_header_get_flags(__p) )
+#define zzip_file_header_data_comprlevel(__p) \
+ ZZIP_IS_COMPRLEVEL( zzip_file_header_get_flags(__p) )
+#define zzip_file_header_data_streamed(__p) \
+ ZZIP_IS_STREAMED( zzip_file_header_get_flags(__p) )
+#define zzip_file_header_data_stored(__p) \
+ ( ZZIP_IS_STORED == zzip_file_header_get_compr(__p) )
+#define zzip_file_header_data_deflated(__p) \
+ ( ZZIP_IS_DEFLATED == zzip_file_header_get_compr(__p) )
+
+#define zzip_disk_entry_data_encrypted(__p) \
+ ZZIP_IS_ENCRYPTED( zzip_disk_entry_get_flags(__p) )
+#define zzip_disk_entry_data_comprlevel(__p) \
+ ZZIP_IS_COMPRLEVEL( zzip_disk_entry_get_flags(__p) )
+#define zzip_disk_entry_data_streamed(__p) \
+ ZZIP_IS_STREAMED( zzip_disk_entry_get_flags(__p) )
+#define zzip_disk_entry_data_stored(__p) \
+ ( ZZIP_IS_STORED == zzip_disk_entry_get_compr(__p) )
+#define zzip_disk_entry_data_deflated(__p) \
+ ( ZZIP_IS_DEFLATED == zzip_disk_entry_get_compr(__p) )
+#define zzip_disk_entry_data_ascii(__p) \
+ ( zzip_disk_entry_get_filetype(__p) & 1)
+
+#define zzip_file_header_data_not_deflated(__p) \
+ (zzip_file_header_data_stored(__p))
+#define zzip_file_header_data_std_deflated(__p) \
+ (zzip_file_header_data_deflated(__p) && \
+ zzip_file_header_data_comprlevel(__p) == ZZIP_DEFLATED_STD_COMPR)
+#define zzip_file_header_data_max_deflated(__p) \
+ (zzip_file_header_data_deflated(__p) && \
+ zzip_file_header_data_comprlevel(__p) == ZZIP_DEFLATED_MAX_COMPR)
+#define zzip_file_header_data_low_deflated(__p) \
+ (zzip_file_header_data_deflated(__p) && \
+ zzip_file_header_data_comprlevel(__p) == ZZIP_DEFLATED_LOW_COMPR)
+#define zzip_file_header_data_min_deflated(__p) \
+ (zzip_file_header_data_deflated(__p) && \
+ zzip_file_header_data_comprlevel(__p) == ZZIP_DEFLATED_MIN_COMPR)
+
+#define zzip_disk_entry_data_not_deflated(__p) \
+ (zzip_disk_entry_data_stored(__p))
+#define zzip_disk_entry_data_std_deflated(__p) \
+ (zzip_disk_entry_data_deflated(__p) && \
+ zzip_disk_entry_data_comprlevel(__p) == ZZIP_DEFLATED_STD_COMPR)
+#define zzip_disk_entry_data_max_deflated(__p) \
+ (zzip_disk_entry_data_deflated(__p) && \
+ zzip_disk_entry_data_comprlevel(__p) == ZZIP_DEFLATED_MAX_COMPR)
+#define zzip_disk_entry_data_low_deflated(__p) \
+ (zzip_disk_entry_data_deflated(__p) && \
+ zzip_disk_entry_data_comprlevel(__p) == ZZIP_DEFLATED_LOW_COMPR)
+#define zzip_disk_entry_data_min_deflated(__p) \
+ (zzip_disk_entry_data_deflated(__p) && \
+ zzip_disk_entry_data_comprlevel(__p) == ZZIP_DEFLATED_MIN_COMPR)
+
+#endif
diff --git a/Build/source/libs/zziplib/zzip/file.c b/Build/source/libs/zziplib/zzip/file.c
new file mode 100644
index 00000000000..4944cd7c74a
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/file.c
@@ -0,0 +1,1029 @@
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ * Tomi Ollila <Tomi.Ollila@iki.fi>
+ *
+ * Copyright (c) 1999,2000,2001,2002,2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#include <zzip/lib.h> /* exported...*/
+#include <zzip/file.h>
+
+#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <zzip/format.h>
+#include <zzip/fetch.h>
+#include <zzip/__debug.h>
+
+#if 0
+# if defined ZZIP_HAVE_IO_H
+# include <io.h> /* tell */
+# else
+# define tell(fd) lseek(fd,0,SEEK_CUR)
+# endif
+#else
+#define tells(fd) seeks(fd,0,SEEK_CUR)
+#endif
+
+/**
+ * the direct function of => zzip_close(fp). it will cleanup the
+ * inflate-portion of => zlib and free the structure given.
+ *
+ * it is called quite from the error-cleanup parts
+ * of the various => _open functions.
+ *
+ * the .refcount is decreased and if zero the fp->dir is closed just as well.
+ */
+int
+zzip_file_close(ZZIP_FILE * fp)
+{
+ auto int self;
+ ZZIP_DIR * dir = fp->dir;
+
+ if (fp->method)
+ inflateEnd(&fp->d_stream); /* inflateEnd() can be called many times */
+
+ if (dir->cache.locked == NULL)
+ dir->cache.locked = &self;
+
+ if (fp->buf32k)
+ {
+ if (dir->cache.locked == &self &&
+ dir->cache.buf32k == NULL) dir->cache.buf32k = fp->buf32k;
+ else free(fp->buf32k);
+ }
+
+ if (dir->currentfp == fp)
+ dir->currentfp = NULL;
+
+ dir->refcount--;
+ /* ease to notice possible dangling reference errors */
+ memset(fp, 0, sizeof(*fp));
+
+ if (dir->cache.locked == &self &&
+ dir->cache.fp == NULL) dir->cache.fp = fp;
+ else free(fp);
+
+ if (dir->cache.locked == &self)
+ dir->cache.locked = NULL;
+
+ if (! dir->refcount) return zzip_dir_close(dir); else return 0;
+}
+
+
+static int
+zzip_file_saveoffset(ZZIP_FILE * fp)
+{
+ if (fp)
+ {
+ int fd = fp->dir->fd;
+ zzip_off_t off = fp->io->fd.seeks(fd, 0, SEEK_CUR);
+ if (off < 0)
+ return -1;
+
+ fp->offset = off;
+ }
+ return 0;
+}
+
+# ifndef ZZIP_CHECK_BACKSLASH_DIRSEPARATOR /* NOTE: also default */
+# define ZZIP_CHECK_BACKSLASH_DIRSEPARATOR 0 /* to "NO" on win32 ! */
+# endif
+
+# if !defined strcasecmp && !defined ZZIP_HAVE_STRCASECMP
+# define ZZIP_CHECK_BACKSLASH_DIRSEPARATOR 1
+# endif
+
+#if ! ZZIP_CHECK_BACKSLASH_DIRSEPARATOR+0
+#define dirsep_strrchr(N,C) strrchr(N,C)
+#define dirsep_casecmp strcasecmp
+#else
+#define dirsep_strrchr(N,C) _dirsep_strrchr(N)
+#define dirsep_casecmp _dirsep_casecmp
+static zzip_char_t*
+_dirsep_strrchr (zzip_char_t* name)
+{
+ char* n = strrchr (name, '/');
+ char* m = strrchr (name, '\\');
+ if (m && n && m > n) n = m;
+ return n;
+}
+static int
+_dirsep_casecmp (zzip_char_t* s1, zzip_char_t* s2)
+{
+ /* ASCII tolower - including mapping of backslash in normal slash */
+ static const char mapping[] = "@abcdefghijklmnopqrstuvwxyz[/]^_";
+ int c1, c2;
+ while (*s1 && *s2)
+ {
+ c1 = (int)(unsigned char) *s1;
+ c2 = (int)(unsigned char) *s2;
+ if ((c1&0xE0) == 0x40) c1 = mapping[c1&0x1f];
+ if ((c2&0xE0) == 0x40) c2 = mapping[c2&0x1f];
+ if (c1 != c2)
+ return (c1 - c2);
+ s1++; s2++;
+ }
+
+ return (((int)(unsigned char) *s1) - ((int)(unsigned char) *s2));
+}
+#endif
+
+static int zzip_inflate_init(ZZIP_FILE *, struct zzip_dir_hdr *);
+
+/**
+ * open an => ZZIP_FILE from an already open => ZZIP_DIR handle. Since
+ * we have a chance to reuse a cached => buf32k and => ZZIP_FILE memchunk
+ * this is the best choice to unpack multiple files.
+ *
+ * Note: the zlib supports 2..15 bit windowsize, hence we provide a 32k
+ * memchunk here... just to be safe.
+ */
+ZZIP_FILE *
+zzip_file_open(ZZIP_DIR * dir, zzip_char_t* name, int o_mode)
+{
+ auto int self;
+ zzip_error_t err = 0;
+ struct zzip_file * fp = 0;
+ struct zzip_dir_hdr * hdr = dir->hdr0;
+ int (*cmp)(zzip_char_t*, zzip_char_t*);
+
+ cmp = (o_mode & ZZIP_CASELESS)? dirsep_casecmp: strcmp;
+
+ if (! dir || !dir->fd || dir->fd == -1 ) return 0;
+
+ if (o_mode & ZZIP_NOPATHS)
+ {
+ register zzip_char_t* n = dirsep_strrchr(name, '/');
+ if (n) name = n + 1;
+ }
+
+ if (hdr)
+ while (1)
+ {
+ register zzip_char_t* hdr_name = hdr->d_name;
+ if (o_mode & ZZIP_NOPATHS)
+ {
+ register zzip_char_t* n = dirsep_strrchr(hdr_name, '/');
+ if (n) hdr_name = n + 1;
+ }
+
+ HINT4("name='%s', compr=%d, size=%d\n",
+ hdr->d_name, hdr->d_compr, hdr->d_usize);
+
+ if (!cmp(hdr_name, name))
+ {
+ switch (hdr->d_compr)
+ {
+ case 0: /* store */
+ case 8: /* inflate */
+ break;
+ default:
+ { err = ZZIP_UNSUPP_COMPR; goto error; }
+ }
+
+ if (dir->cache.locked == NULL)
+ dir->cache.locked = &self;
+
+ if (dir->cache.locked == &self &&
+ dir->cache.fp)
+ {
+ fp = dir->cache.fp; dir->cache.fp = NULL;
+ /* memset(zfp, 0, sizeof *fp); cleared in zzip_file_close() */
+ }else
+ {
+ if (! (fp = (ZZIP_FILE *)calloc(1, sizeof(*fp))))
+ { err = ZZIP_OUTOFMEM; goto error; }
+ }
+
+ fp->dir = dir;
+ fp->io = dir->io;
+ dir->refcount++;
+
+ if (dir->cache.locked == &self &&
+ dir->cache.buf32k)
+ { fp->buf32k = dir->cache.buf32k; dir->cache.buf32k = NULL; }
+ else
+ {
+ if (! (fp->buf32k = (char *)malloc(ZZIP_32K)))
+ { err = ZZIP_OUTOFMEM; goto error; }
+ }
+
+ if (dir->cache.locked == &self)
+ dir->cache.locked = NULL;
+ /*
+ * In order to support simultaneous open files in one zip archive
+ * we'll fix the fd offset when opening new file/changing which
+ * file to read...
+ */
+
+ if (zzip_file_saveoffset(dir->currentfp) < 0)
+ { err = ZZIP_DIR_SEEK; goto error; }
+
+ fp->offset = hdr->d_off;
+ dir->currentfp = fp;
+
+ if (dir->io->fd.seeks(dir->fd, hdr->d_off, SEEK_SET) < 0)
+ { err = ZZIP_DIR_SEEK; goto error; }
+
+ { /* skip local header - should test tons of other info,
+ * but trust that those are correct */
+ zzip_ssize_t dataoff;
+ struct zzip_file_header * p = (void*) fp->buf32k;
+
+ dataoff = dir->io->fd.read(dir->fd, (void*)p, sizeof(*p));
+ if (dataoff < (zzip_ssize_t)sizeof(*p))
+ { err = ZZIP_DIR_READ; goto error; }
+ if (! zzip_file_header_check_magic(p)) /* PK\3\4 */
+ { err = ZZIP_CORRUPTED; goto error; }
+
+ dataoff = zzip_file_header_sizeof_tail(p);
+
+ if (dir->io->fd.seeks(dir->fd, dataoff, SEEK_CUR) < 0)
+ { err = ZZIP_DIR_SEEK; goto error; }
+
+ fp->dataoffset = dir->io->fd.tells(dir->fd);
+ fp->usize = hdr->d_usize;
+ fp->csize = hdr->d_csize;
+ }
+
+ err = zzip_inflate_init (fp, hdr);
+ if (err) { goto error; }
+
+ return fp;
+ }else
+ {
+ if (hdr->d_reclen == 0)
+ break;
+ hdr = (struct zzip_dir_hdr *)((char *)hdr + hdr->d_reclen);
+ }/*cmp name*/
+ }/*forever*/
+ dir->errcode = ZZIP_ENOENT; zzip_errno(ZZIP_ENOENT);
+ return NULL;
+error:
+ if (fp) zzip_file_close(fp);
+ dir->errcode = err; zzip_errno(err);
+ return NULL;
+}
+
+/**
+ * call => inflateInit and setup fp's iterator variables,
+ * used by lowlevel => _open functions.
+ */
+static int
+zzip_inflate_init(ZZIP_FILE * fp, struct zzip_dir_hdr* hdr)
+{
+ int err;
+ fp->method = hdr->d_compr;
+ fp->restlen = hdr->d_usize;
+
+ if (fp->method)
+ {
+ memset(&fp->d_stream, 0, sizeof(fp->d_stream));
+
+ err = inflateInit2(&fp->d_stream, -MAX_WBITS);
+ if (err != Z_OK) { goto error; }
+
+ fp->crestlen = hdr->d_csize;
+ }
+ return 0;
+error:
+ if (fp) zzip_file_close(fp);
+ return err;
+}
+
+/**
+ * This function closes the given ZZIP_FILE handle.
+ *
+ * If the ZZIP_FILE wraps a normal stat'fd then it is just that int'fd
+ * that is being closed and the otherwise empty ZZIP_FILE gets freed.
+ */
+int
+zzip_fclose(ZZIP_FILE * fp)
+{
+ if (! fp) return 0;
+ if (! fp->dir)
+ { int r = fp->io->fd.close(fp->fd); free(fp); return r; } /* stat fd */
+ else return zzip_file_close(fp);
+}
+
+/** => zzip_fclose
+ */
+int
+zzip_close(ZZIP_FILE* fp)
+{
+ return zzip_fclose (fp);
+}
+
+/**
+ * This functions read data from zip-contained file.
+ *
+ * It works like => read(2) and will fill the given buffer with bytes from
+ * the opened file. It will return the number of bytes read, so if the => EOF
+ * is encountered you will be prompted with the number of bytes actually read.
+ *
+ * This is the routines that needs the => buf32k buffer, and it would have
+ * need for much more polishing but it does already work quite well.
+ *
+ * Note: the 32K buffer is rather big. The original inflate-algorithm
+ * required just that but the latest zlib would work just fine with
+ * a smaller buffer.
+ */
+zzip_ssize_t
+zzip_file_read(ZZIP_FILE * fp, char * buf, zzip_size_t len)
+{
+ ZZIP_DIR * dir;
+ zzip_size_t l;
+ zzip_ssize_t rv;
+
+ if (! fp || ! fp->dir) return 0;
+
+ dir = fp->dir;
+ l = fp->restlen > len ? len : fp->restlen;
+ if (fp->restlen == 0)
+ return 0;
+
+ /*
+ * If this is other handle than previous, save current seek pointer
+ * and read the file position of `this' handle.
+ */
+ if (dir->currentfp != fp)
+ {
+ if (zzip_file_saveoffset(dir->currentfp) < 0
+ || fp->io->fd.seeks(dir->fd, fp->offset, SEEK_SET) < 0)
+ { dir->errcode = ZZIP_DIR_SEEK; return -1; }
+ else
+ { dir->currentfp = fp; }
+ }
+
+ /* if more methods is to be supported, change this to `switch ()' */
+ if (fp->method) /* method != 0 == 8, inflate */
+ {
+ fp->d_stream.avail_out = l;
+ fp->d_stream.next_out = (unsigned char *)buf;
+
+ do {
+ int err;
+ zzip_size_t startlen;
+
+ if (fp->crestlen > 0 && fp->d_stream.avail_in == 0)
+ {
+ zzip_size_t cl = ( fp->crestlen < ZZIP_32K ?
+ fp->crestlen : ZZIP_32K );
+ /* zzip_size_t cl = fp->crestlen > 128 ? 128 : fp->crestlen; */
+
+ zzip_ssize_t i = fp->io->fd.read(dir->fd, fp->buf32k, cl);
+ if (i <= 0)
+ {
+ dir->errcode = ZZIP_DIR_READ; /* or ZZIP_DIR_READ_EOF ? */
+ return -1;
+ }
+ fp->crestlen -= i;
+ fp->d_stream.avail_in = i;
+ fp->d_stream.next_in = (unsigned char *)fp->buf32k;
+ }
+
+ startlen = fp->d_stream.total_out;
+ err = inflate(&fp->d_stream, Z_NO_FLUSH);
+
+ if (err == Z_STREAM_END)
+ { fp->restlen = 0; }
+ else
+ if (err == Z_OK)
+ { fp->restlen -= (fp->d_stream.total_out - startlen); }
+ else
+ { dir->errcode = err; return -1; }
+ } while (fp->restlen && fp->d_stream.avail_out);
+
+ return l - fp->d_stream.avail_out;
+ }else
+ { /* method == 0 -- unstore */
+ rv = fp->io->fd.read(dir->fd, buf, l);
+ if (rv > 0)
+ { fp->restlen-= rv; }
+ else
+ if (rv < 0)
+ { dir->errcode = ZZIP_DIR_READ; }
+ return rv;
+ }
+}
+
+/**
+ * This function will read(2) data from a real/zipped file.
+ *
+ * the replacement for => read(2) will fill the given buffer with bytes from
+ * the opened file. It will return the number of bytes read, so if the EOF
+ * is encountered you will be prompted with the number of bytes actually read.
+ *
+ * If the file-handle is wrapping a stat'able file then it will actually just
+ * perform a normal => read(2)-call, otherwise => zzip_file_read is called
+ * to decompress the data stream and any error is mapped to => errno(3).
+ */
+zzip_ssize_t
+zzip_read(ZZIP_FILE * fp, char * buf, zzip_size_t len)
+{
+ if (! fp) return 0;
+ if (! fp->dir)
+ { return fp->io->fd.read(fp->fd, buf, len); } /* stat fd */
+ else
+ { register zzip_ssize_t v;
+ v = zzip_file_read(fp, buf, len);
+ if (v == -1) { errno = zzip_errno(fp->dir->errcode); }
+ return v;
+ }
+}
+
+/** => zzip_read
+ */
+zzip_size_t
+zzip_fread(void *ptr, zzip_size_t size, zzip_size_t nmemb, ZZIP_FILE *file)
+{
+ if (! size) size=1;
+ return zzip_read (file, ptr, size*nmemb)/size;
+}
+
+
+#define ZZIP_WRONLY O_WRONLY
+#define ZZIP_EXCL O_EXCL
+
+#if defined O_SYNC
+#define ZZIP_SYNC O_SYNC
+#else
+#define ZZIP_SYNC 0
+#endif
+
+#if defined O_NONBLOCK
+#define ZZIP_NONBLOCK O_NONBLOCK
+#elif defined O_NDELAY
+#define ZZIP_NOCTTY O_NDELAY
+#else
+#define ZZIP_NOCTTY 0
+#endif
+
+/* ------------------------------------------------------------------- */
+
+/**
+ * This function will => fopen(3) a real/zipped file.
+ *
+ * It has some magic functionality builtin - it will first try to open
+ * the given <em>filename</em> as a normal file. If it does not
+ * exist, the given path to the filename (if any) is split into
+ * its directory-part and the file-part. A ".zip" extension is
+ * then added to the directory-part to create the name of a
+ * zip-archive. That zip-archive (if it exists) is being searched
+ * for the file-part, and if found a zzip-handle is returned.
+ *
+ * Note that if the file is found in the normal fs-directory the
+ * returned structure is mostly empty and the => zzip_read call will
+ * use the libc => read to obtain data. Otherwise a => zzip_file_open
+ * is performed and any error mapped to => errno(3).
+ *
+ * unlike the posix-wrapper => zzip_open the mode-argument is
+ * a string which allows for more freedom to support the extra
+ * zzip modes called ZZIP_CASEINSENSITIVE and ZZIP_IGNOREPATH.
+ * Currently, this => zzip_fopen call will convert the following
+ * characters in the mode-string into their corrsponding mode-bits:
+ * <ul><li><code> "r" : O_RDONLY : </code> read-only
+ * </li><li><code> "b" : O_BINARY : </code> binary (win32 specific)
+ * </li><li><code> "f" : O_NOCTTY : </code> no char device (unix)
+ * </li><li><code> "i" : ZZIP_CASELESS : </code> inside zip file
+ * </li><li><code> "*" : ZZIP_NOPATHS : </code> inside zip file only
+ * </ul> all other modes will be ignored for zip-contained entries
+ * but they are transferred for compatibility and portability,
+ * including these extra sugar bits:
+ * <ul><li><code> "x" : O_EXCL :</code> fail if file did exist
+ * </li><li><code> "s" : O_SYNC :</code> synchronized access
+ * </li><li><code> "n" : O_NONBLOCK :</code> nonblocking access
+ * </li><li><code> "z#" : compression level :</code> for zlib
+ * </li><li><code> "g#" : group access :</code> unix access bits
+ * </li><li><code> "u#" : owner access :</code> unix access bits
+ * </li><li><code> "o#" : world access :</code> unix access bits
+ * </ul>... the access bits are in traditional unix bit format
+ * with 7 = read/write/execute, 6 = read/write, 4 = read-only.
+ *
+ * The default access mode is 0664, and the compression level
+ * is ignored since the lib can not yet write zip files, otherwise
+ * it would be the initialisation value for the zlib deflateInit
+ * where 0 = no-compression, 1 = best-speed, 9 = best-compression.
+ */
+ZZIP_FILE*
+zzip_fopen(zzip_char_t* filename, zzip_char_t* mode)
+{
+ return zzip_freopen (filename, mode, 0);
+}
+
+/** => zzip_fopen
+ *
+ * This function receives an additional argument pointing to
+ * a ZZIP_FILE* being already in use. If this extra argument is
+ * null then this function is identical with calling => zzip_fopen
+ *
+ * Per default, the old file stream is closed and only the internal
+ * structures associated with it are kept. These internal structures
+ * may be reused for the return value, and this is a lot quicker when
+ * the filename matches a zipped file that is incidently in the very
+ * same zip arch as the old filename wrapped in the stream struct.
+ *
+ * That's simply because the zip arch's central directory does not
+ * need to be read again. As an extension for this function, if the
+ * mode-string contains a "q" then the old stream is not closed but
+ * left untouched, instead it is only given as a hint that a new
+ * file handle may share/copy the zip arch structures of the old file
+ * handle if that is possible, i.e when they are in the same zip arch.
+ */
+ZZIP_FILE*
+zzip_freopen(zzip_char_t* filename, zzip_char_t* mode, ZZIP_FILE* stream)
+{
+ int o_flags = 0;
+ int o_modes = 0664;
+ if (!mode) mode = "rb";
+
+# ifndef O_BINARY
+# define O_BINARY 0
+# endif
+# ifndef O_NOCTTY
+# define O_NOCTTY 0
+# endif
+# ifndef O_SYNC
+# define O_SYNC 0
+# endif
+# ifndef O_NONBLOCK
+# define O_NONBLOCK 0
+# endif
+
+ for(; *mode; mode++)
+ {
+ switch (*mode)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ continue; /* ignore if not attached to other info */
+ case 'r': o_flags |= mode[1] == '+' ? O_RDWR : O_RDONLY; break;
+ case 'w': o_flags |= mode[1] == '+' ? O_RDWR : O_WRONLY;
+ o_flags |= O_TRUNC; break;
+ case 'b': o_flags |= O_BINARY; break;
+ case 'f': o_flags |= O_NOCTTY; break;
+ case 'i': o_modes |= ZZIP_CASELESS; break;
+ case '*': o_modes |= ZZIP_NOPATHS; break;
+ case 'x': o_flags |= O_EXCL; break;
+ case 's': o_flags |= O_SYNC; break;
+ case 'n': o_flags |= O_NONBLOCK; break;
+ case 'o': o_modes &=~ 07;
+ o_modes |= ((mode[1] - '0'))&07; continue;
+ case 'g': o_modes &=~ 070;
+ o_modes |= ((mode[1] - '0')<<3)&070; continue;
+ case 'u': o_modes &=~ 0700;
+ o_modes |= ((mode[1] - '0')<<6)&0700; continue;
+ case 'q': o_modes |= ZZIP_FACTORY; break;
+ case 'z': /* compression level */
+ continue; /* currently ignored, just for write mode */
+ }
+ }
+
+ {
+ ZZIP_FILE* fp =
+ zzip_open_shared_io (stream, filename, o_flags, o_modes, 0, 0);
+
+ if (! o_modes&ZZIP_FACTORY && stream)
+ zzip_file_close (stream);
+
+ return fp;
+ }
+}
+
+/**
+ * This function will => open(2) a real/zipped file
+ *
+ * It has some magic functionality builtin - it will first try to open
+ * the given <em>filename</em> as a normal file. If it does not
+ * exist, the given path to the filename (if any) is split into
+ * its directory-part and the file-part. A ".zip" extension is
+ * then added to the directory-part to create the name of a
+ * zip-archive. That zip-archive (if it exists) is being searched
+ * for the file-part, and if found a zzip-handle is returned.
+ *
+ * Note that if the file is found in the normal fs-directory the
+ * returned structure is mostly empty and the => zzip_read call will
+ * use the libc => read to obtain data. Otherwise a => zzip_file_open
+ * is performed and any error mapped to => errno(3).
+ *
+ * There was a possibility to transfer zziplib-specific openmodes
+ * through o_flags but you should please not use them anymore and
+ * look into => zzip_open_ext_io to submit them down. This function
+ * is shallow in that it just extracts the zzipflags and calls <ul><li><code>
+ * zzip_open_ext_io(filename, o_flags, zzipflags|0664, 0, 0) </code></li></ul>
+ * you must stop using this extra functionality (not well known
+ * anyway) since zzip_open might be later usable to open files
+ * for writing in which case the _EXTRAFLAGS will get in conflict.
+ *
+ * compare with => open(2) and => zzip_fopen
+ */
+ZZIP_FILE*
+zzip_open(zzip_char_t* filename, int o_flags)
+{
+ /* backward compatibility */
+ int o_modes = 0664;
+ if (o_flags & ZZIP_CASEINSENSITIVE)
+ { o_flags ^= ZZIP_CASEINSENSITIVE; o_modes |= ZZIP_CASELESS; }
+ if (o_flags & ZZIP_IGNOREPATH)
+ { o_flags ^= ZZIP_IGNOREPATH; o_modes |= ZZIP_NOPATHS; }
+ return zzip_open_ext_io(filename, o_flags, o_modes, 0, 0);
+}
+
+/* ZZIP_ONLYZIP won't work on platforms with sizeof(int) == 16bit */
+#if ZZIP_SIZEOF_INT+0 == 2
+#undef ZZIP_ONLYZIP
+#endif
+
+/** => zzip_open
+ *
+ * This function uses explicit ext and io instead of the internal
+ * defaults, setting them to zero is equivalent to => zzip_open
+ *
+ * note that the two flag types have been split into an o_flags
+ * (for fcntl-like openflags) and o_modes where the latter shall
+ * carry the zzip_flags and possibly accessmodes for unix filesystems.
+ * Since this version of zziplib can not write zipfiles, it is not
+ * yet used for anything else than zzip-specific modeflags.
+ */
+ZZIP_FILE*
+zzip_open_ext_io(zzip_char_t* filename, int o_flags, int o_modes,
+ zzip_strings_t* ext, zzip_plugin_io_t io)
+{
+ return zzip_open_shared_io (0, filename, o_flags, o_modes, ext, io);
+}
+
+/** => zzip_open
+ *
+ * This function takes an extra stream argument - if a handle has been
+ * then ext/io can be left null and the new stream handle will pick up
+ * the ext/io. This should be used only in specific environment however
+ * since => zzip_file_real does not store any ext-sequence.
+ *
+ * The benefit for this function comes in when the old file handle
+ * was openened from a file within a zip archive. When the new file
+ * is in the same zip archive then the internal zzip_dir structures
+ * will be shared. It is even quicker, as no check needs to be done
+ * anymore trying to guess the zip archive place in the filesystem,
+ * here we just check whether the zip archive's filepath is a prefix
+ * part of the filename to be opened.
+ *
+ * Note that this function is also used by => zzip_freopen that
+ * will unshare the old handle, thereby possibly closing the handle.
+ */
+ZZIP_FILE*
+zzip_open_shared_io (ZZIP_FILE* stream,
+ zzip_char_t* filename, int o_flags, int o_modes,
+ zzip_strings_t* ext, zzip_plugin_io_t io)
+{
+ if (stream && stream->dir)
+ {
+ if (! ext) ext = stream->dir->fileext;
+ if (! io) io = stream->dir->io;
+ }
+ if (! io) io = zzip_get_default_io ();
+
+ if (o_modes & (ZZIP_PREFERZIP|ZZIP_ONLYZIP)) goto try_zzip;
+ try_real:
+ /* prefer an existing real file */
+ {
+ zzip_plugin_io_t os = (o_modes & ZZIP_ALLOWREAL)
+ ? zzip_get_default_io () : io;
+ int fd = os->fd.open(filename, o_flags); /* io->fd.open */
+ if (fd != -1)
+ {
+ ZZIP_FILE* fp = calloc (1, sizeof(ZZIP_FILE));
+ if (!fp) { os->fd.close(fd); return 0; } /* io->fd.close */
+
+ fp->fd = fd;
+ fp->io = os;
+ return fp;
+ }
+ if (o_modes & ZZIP_PREFERZIP) return 0;
+ }
+ try_zzip:
+
+ /* if the user had it in place of a normal xopen, then
+ * we better defend this lib against illegal usage */
+ if (o_flags & (O_CREAT|O_WRONLY)) { errno = EINVAL; return 0; }
+ if (o_flags & (O_RDWR)) { o_flags ^= O_RDWR; o_flags |= O_RDONLY; }
+
+ /* this is just for backward compatibility -and strictly needed to
+ * prepare ourselves for more options and more options later on... */
+ /*# if (o_modes & ZZIP_CASELESS) { o_flags |= ZZIP_CASEINSENSITIVE; } */
+ /*# if (o_modes & ZZIP_NOPATHS) { o_flags |= ZZIP_IGNOREPATH; } */
+
+ /* see if we can open a file that is a zip file */
+ { char basename[PATH_MAX];
+ char* p;
+ strcpy (basename, filename);
+
+ /* see if we can share the same zip directory */
+ if (stream && stream->dir && stream->dir->realname)
+ {
+ zzip_size_t len = strlen (stream->dir->realname);
+ if (! memcmp (filename, stream->dir->realname, len) &&
+ filename[len] == '/' && filename[len+1])
+ {
+ ZZIP_FILE* fp =
+ zzip_file_open (stream->dir, filename+len+1, o_modes);
+ if (! fp) { errno = zzip_errno (stream->dir->errcode); }
+ return fp;
+ }
+ }
+
+ /* per each slash in filename, check if it there is a zzip around */
+ while ((p = strrchr (basename, '/')))
+ {
+ zzip_error_t e = 0;
+ ZZIP_DIR* dir;
+ ZZIP_FILE* fp;
+ int fd;
+
+ *p = '\0'; /* cut at path separator == possible zipfile basename */
+ fd = __zzip_try_open (basename, o_flags|O_RDONLY|O_BINARY, ext, io);
+ if (fd == -1) { continue; }
+/* found: */
+ /* found zip-file, now try to parse it */
+ dir = zzip_dir_fdopen_ext_io(fd, &e, ext, io);
+ if (e) { errno = zzip_errno(e); io->fd.close(fd); return 0; }
+
+ /* (p - basename) is the lenghtof zzip_dir part of the filename */
+ fp = zzip_file_open(dir, filename + (p - basename) +1, o_modes);
+ if (! fp) { errno = zzip_errno(dir->errcode); }
+ else { if (! dir->realname) dir->realname = strdup (basename); }
+
+ zzip_dir_close(dir);
+ /* note: since (fp) is attached that (dir) will survive */
+ /* but (dir) is implicitly closed on next zzip_close(fp) */
+
+ return fp;
+ } /*again*/
+
+ if (o_modes & ZZIP_PREFERZIP) goto try_real;
+ errno = ENOENT; return 0;
+ }
+}
+
+#if defined ZZIP_LARGEFILE_RENAME && defined EOVERFLOW && defined PIC
+#undef zzip_open_shared_io /* zzip_open_shared_io64 */
+#undef zzip_open_ext_io /* zzip_open_ext_io64 */
+#undef zzip_opendir_ext_io /* zzip_opendir_ext_io64 */
+
+_zzip_export
+ZZIP_FILE * zzip_open_shared_io(ZZIP_FILE* stream,
+ zzip_char_t* name, int o_flags, int o_modes,
+ zzip_strings_t* ext, zzip_plugin_io_t io);
+_zzip_export
+ZZIP_FILE * zzip_open_ext_io(zzip_char_t* name, int o_flags, int o_modes,
+ zzip_strings_t* ext, zzip_plugin_io_t io);
+_zzip_export
+ZZIP_DIR * zzip_opendir_ext_io(zzip_char_t* name, int o_modes,
+ zzip_strings_t* ext, zzip_plugin_io_t io);
+
+/* DLL compatibility layer - so that 32bit code can link with this lib too */
+
+_zzip_export
+ZZIP_FILE * zzip_open_shared_io(ZZIP_FILE* stream,
+ zzip_char_t* name, int o_flags, int o_modes,
+ zzip_strings_t* ext, zzip_plugin_io_t io)
+{
+ if (! io) return zzip_open_shared_io64 (stream, name, o_flags, o_modes,
+ ext, io);
+ errno = EOVERFLOW; return NULL;
+}
+
+_zzip_export
+ZZIP_FILE * zzip_open_ext_io(zzip_char_t* name, int o_flags, int o_modes,
+ zzip_strings_t* ext, zzip_plugin_io_t io)
+{
+ if (! io) return zzip_open_ext_io64 (name, o_flags, o_modes, ext, io);
+ errno = EOVERFLOW; return NULL;
+}
+
+_zzip_export
+ZZIP_DIR * zzip_opendir_ext_io(zzip_char_t* name, int o_modes,
+ zzip_strings_t* ext, zzip_plugin_io_t io)
+{
+ if (! io) return zzip_opendir_ext_io64 (name, o_modes, ext, io);
+ errno = EOVERFLOW; return NULL;
+}
+
+#endif /* ZZIP_LARGEFILE_RENAME && EOVERFLOW && PIC */
+
+/* ------------------------------------------------------------------- */
+
+/**
+ * This function will rewind a real/zipped file.
+ *
+ * It seeks to the beginning of this file's data in the zip,
+ * or the beginning of the file for a stat'fd.
+ */
+int
+zzip_rewind(ZZIP_FILE *fp)
+{
+ ZZIP_DIR *dir;
+ int err;
+
+ if (! fp)
+ return -1;
+
+ if (! fp->dir)
+ { /* stat fd */
+ fp->io->fd.seeks(fp->fd,0,SEEK_SET);
+ return 0;
+ }
+
+ dir = fp->dir;
+ /*
+ * If this is other handle than previous, save current seek pointer
+ */
+ if (dir->currentfp != fp)
+ {
+ if (zzip_file_saveoffset(dir->currentfp) < 0)
+ { dir->errcode = ZZIP_DIR_SEEK; return -1; }
+ else
+ { dir->currentfp = fp; }
+ }
+
+ /* seek to beginning of this file */
+ if (fp->io->fd.seeks(dir->fd, fp->dataoffset, SEEK_SET) < 0)
+ return -1;
+
+ /* reset the inflate init stuff */
+ fp->restlen = fp->usize;
+ fp->offset = fp->dataoffset;
+
+ if (fp->method)
+ { /* method == 8, deflate */
+ err = inflateReset(&fp->d_stream);
+ if (err != Z_OK) { goto error; }
+
+ /* start over at next inflate with a fresh read() */
+ fp->d_stream.avail_in = 0;
+ fp->crestlen = fp->csize;
+ }
+
+ return 0;
+
+ error:
+ if (fp) zzip_file_close(fp);
+ return err;
+}
+
+/**
+ * This function will perform a => lseek(2) operation on a real/zipped file
+ *
+ * It will try to seek to the offset specified by offset, relative to whence,
+ * which is one of SEEK_SET, SEEK_CUR or SEEK_END.
+ *
+ * If the file-handle is wrapping a stat'able file then it will actually just
+ * perform a normal => lseek(2)-call. Otherwise the relative offset
+ * is calculated, negative offsets are transformed into positive ones
+ * by rewinding the file, and then data is read until the offset is
+ * reached. This can make the function terribly slow, but this is
+ * how gzio implements it, so I'm not sure there is a better way
+ * without using the internals of the algorithm.
+ */
+zzip_off_t
+zzip_seek(ZZIP_FILE * fp, zzip_off_t offset, int whence)
+{
+ zzip_off_t cur_pos, rel_ofs, read_size, ofs;
+ ZZIP_DIR *dir;
+
+ if (! fp)
+ return -1;
+
+ if (! fp->dir)
+ { /* stat fd */
+ return fp->io->fd.seeks(fp->fd, offset, whence);
+ }
+
+ cur_pos = zzip_tell(fp);
+
+ /* calculate relative offset */
+ switch (whence)
+ {
+ case SEEK_SET: /* from beginning */
+ rel_ofs = offset - cur_pos;
+ break;
+ case SEEK_CUR: /* from current */
+ rel_ofs = offset;
+ break;
+ case SEEK_END: /* from end */
+ rel_ofs = fp->usize + offset - cur_pos;
+ break;
+ default: /* something wrong */
+ return -1;
+ }
+
+ if (rel_ofs == 0)
+ return cur_pos; /* don't have to move */
+
+ if (rel_ofs < 0)
+ { /* convert backward into forward */
+ if (zzip_rewind(fp) == -1)
+ return -1;
+
+ read_size = cur_pos + rel_ofs;
+ cur_pos = 0;
+ }else
+ { /* amount to read is positive relative offset */
+ read_size = rel_ofs;
+ }
+
+ if (read_size < 0) /* bad offset, before beginning of file */
+ return -1;
+
+ if (read_size + cur_pos > (zzip_off_t)fp->usize) /* bad offset, past EOF */
+ return -1;
+
+ if (read_size == 0) /* nothing to read */
+ return cur_pos;
+
+ dir = fp->dir;
+ /*
+ * If this is other handle than previous, save current seek pointer
+ * and read the file position of `this' handle.
+ */
+ if (dir->currentfp != fp)
+ {
+ if (zzip_file_saveoffset(dir->currentfp) < 0
+ || dir->currentfp->io->fd.seeks(dir->fd, fp->offset, SEEK_SET) < 0)
+ { dir->errcode = ZZIP_DIR_SEEK; return -1; }
+ else
+ { dir->currentfp = fp; }
+ }
+
+ if (fp->method == 0)
+ { /* unstore, just lseek relatively */
+ ofs = fp->io->fd.tells(dir->fd);
+ ofs = fp->io->fd.seeks(dir->fd,read_size,SEEK_CUR);
+ if (ofs > 0)
+ { /* readjust from beginning of file */
+ ofs -= fp->dataoffset;
+ fp->restlen = fp->usize - ofs;
+ }
+ return ofs;
+ }else
+ { /* method == 8, inflate */
+ char *buf;
+ /*FIXME: use a static buffer! */
+ buf = (char *)malloc(ZZIP_32K);
+ if (! buf) return -1;
+
+ while (read_size > 0)
+ {
+ zzip_off_t size = ZZIP_32K;
+ if (read_size < size/*32K*/) size = read_size;
+
+ size = zzip_file_read(fp, buf, (zzip_size_t)size);
+ if (size <= 0) { free(buf); return -1; }
+
+ read_size -= size;
+ }
+
+ free (buf);
+ }
+
+ return zzip_tell(fp);
+}
+
+/**
+ * This function will => tell(2) the current position in a real/zipped file
+ *
+ * It will return the current offset within the real/zipped file,
+ * measured in uncompressed bytes for the zipped-file case.
+ *
+ * If the file-handle is wrapping a stat'able file then it will actually just
+ * perform a normal => tell(2)-call, otherwise the offset is
+ * calculated from the amount of data left and the total uncompressed
+ * size;
+ */
+zzip_off_t
+zzip_tell(ZZIP_FILE * fp)
+{
+ if (! fp)
+ return -1;
+
+ if (! fp->dir) /* stat fd */
+ return fp->io->fd.tells(fp->fd);
+
+ /* current uncompressed offset is uncompressed size - data left */
+ return (fp->usize - fp->restlen);
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/zzip/file.h b/Build/source/libs/zziplib/zzip/file.h
new file mode 100644
index 00000000000..fcff276bb23
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/file.h
@@ -0,0 +1,81 @@
+/*
+ * this is an internal header file - the structure contains two off_t
+ * atleast making it LARGEFILE_SENSITIVE on linux2 and solaris systems
+ * whereas about all functions just return a ZZIP_FILE* in zzip/zzip.h
+ *
+ * and so, this structure should be handled version-specific and
+ * subject to change - it had been kept binary-compatible for quite
+ * a while now so perhaps some program sources have errnously taken
+ * advantage of this file.
+ *
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ * Tomi Ollila <Tomi.Ollila@tfi.net>
+ *
+ * Copyright (c) 1999,2000,2001,2002 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#ifndef _ZZIP_FILE_H /* zzip-file.h */
+#define _ZZIP_FILE_H 1
+
+#ifndef ZZIP_32K
+#ifdef __GNUC__
+/* include zzip/lib.h beforehand in order to suppress the following warning */
+#warning zzip/file.h is an internal header, do not use it freely
+#endif
+#endif
+
+#include <zzip/lib.h>
+#include <zlib.h>
+
+#ifdef ZZIP_HAVE_UNISTD_H
+#include <unistd.h>
+#else
+#include <stdio.h>
+# ifdef ZZIP_HAVE_SYS_TYPES_H
+# include <sys/types.h>
+# endif
+#endif
+
+#ifdef ZZIP_HAVE_SYS_PARAM_H
+#include <sys/param.h> /* PATH_MAX */
+#endif
+
+#ifndef PATH_MAX
+# ifdef MAX_PATH /* windows */
+# define PATH_MAX MAX_PATH
+# else
+# define PATH_MAX 512
+# endif
+#endif
+/*
+ * ZZIP_FILE structure... currently no need to unionize, since structure needed
+ * for inflate is superset of structure needed for unstore.
+ *
+ * Don't make this public. Instead, create methods for needed operations.
+ */
+
+struct zzip_file
+{
+ struct zzip_dir* dir;
+ int fd;
+ int method;
+ zzip_size_t restlen;
+ zzip_size_t crestlen;
+ zzip_size_t usize;
+ zzip_size_t csize;
+ /* added dataoffset member - data offset from start of zipfile*/
+ zzip_off_t dataoffset;
+ char* buf32k;
+ zzip_off_t offset; /* offset from the start of zipfile... */
+ z_stream d_stream;
+ zzip_plugin_io_t io;
+};
+
+#endif /* _ZZIP_FILE_H */
+
diff --git a/Build/source/libs/zziplib/zzip/format.h b/Build/source/libs/zziplib/zzip/format.h
new file mode 100644
index 00000000000..fba4000aa76
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/format.h
@@ -0,0 +1,233 @@
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 2000,2001,2002,2003 Guido Draheim
+ * All rights reserved
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ *
+ * The information was taken from appnote-981119-iz.zip
+ * at http://www.freesoftware.com/pub/infozip/doc/
+ * which in turn is based on PKWARE's appnote.txt
+ * (newer link: ftp://ftp.info-zip.org/pub/infozip/doc/)
+ */
+#ifndef _ZZIP_FORMAT_H /* zzipformat.h */
+#define _ZZIP_FORMAT_H
+
+#include <zzip/types.h>
+/* we have ICO C 9X types defined */
+
+/*
+ * Overall zipfile format
+ * [local file header + file data stream + checksum descriptor] ...
+ * ... [disk central directory] [disk trailer record]
+ */
+
+# ifdef _MSC_VER
+# pragma pack(push, 1)
+# endif
+
+struct zzip_version
+{
+ zzip_byte_t version[1];
+ zzip_byte_t ostype[1];
+} __zzip_attribute__((packed));
+
+struct zzip_dostime
+{
+ zzip_byte_t time[2];
+ zzip_byte_t date[2];
+} __zzip_attribute__((packed));
+
+#ifdef ZZIP_NEED_PACKED
+/* if your compiler does interesting things about struct packing... */
+typedef zzip_byte_t zzip_version_t[2];
+typedef zzip_byte_t zzip_dostime_t[4];
+#else
+typedef struct zzip_version zzip_version_t;
+typedef struct zzip_dostime zzip_dostime_t;
+#endif
+
+#define ZZIP_CHECKMAGIC(__p,__A,__B,__C,__D) \
+ ( (((zzip_byte_t*)(__p))[0]==(__A)) && \
+ (((zzip_byte_t*)(__p))[1]==(__B)) && \
+ (((zzip_byte_t*)(__p))[2]==(__C)) && \
+ (((zzip_byte_t*)(__p))[3]==(__D)) )
+
+/* A. Local file header */
+struct zzip_file_header
+{
+# define ZZIP_FILE_HEADER_MAGIC 0x04034b50
+# define ZZIP_FILE_HEADER_CHECKMAGIC(__p) ZZIP_CHECKMAGIC(__p,'P','K','\3','\4')
+ zzip_byte_t z_magic[4]; /* local file header signature (0x04034b50) */
+ zzip_version_t z_extract; /* version needed to extract */
+ zzip_byte_t z_flags[2]; /* general purpose bit flag */
+ zzip_byte_t z_compr[2]; /* compression method */
+ zzip_dostime_t z_dostime; /* last mod file time (dos format) */
+ zzip_byte_t z_crc32[4]; /* crc-32 */
+ zzip_byte_t z_csize[4]; /* compressed size */
+ zzip_byte_t z_usize[4]; /* uncompressed size */
+ zzip_byte_t z_namlen[2]; /* filename length (null if stdin) */
+ zzip_byte_t z_extras[2]; /* extra field length */
+ /* followed by filename (of variable size) */
+ /* followed by extra field (of variable size) */
+} __zzip_attribute__((packed));
+#define zzip_file_header_headerlength (4+2+2+2+4+4+4+4+2+2)
+
+/* B. data descriptor
+ * the data descriptor exists only if bit 3 of z_flags is set. It is byte aligned
+ * and immediately follows the last byte of compressed data. It is only used if
+ * the output media of the compressor was not seekable, eg. standard output.
+ */
+struct zzip_file_trailer
+{
+# define ZZIP_FILE_TRAILER_MAGIC 0x08074B50
+# define ZZIP_FILE_TRAILER_CHECKMAGIC(__p) ZZIP_CHECKMAGIC(__p,'P','K','\7','\8')
+ zzip_byte_t z_magic[4]; /* data descriptor signature (0x08074b50) */
+ zzip_byte_t z_crc32[4]; /* crc-32 */
+ zzip_byte_t z_csize[4]; /* compressed size */
+ zzip_byte_t z_usize[4]; /* uncompressed size */
+} __zzip_attribute__((packed));
+#define zzip_file_trailer_headerlength (4+4+4+4)
+
+/* C. central directory structure:
+ [file header] . . . end of central dir record
+*/
+
+/* directory file header
+ * - a single entry including filename, extras and comment may not exceed 64k.
+ */
+
+struct zzip_disk_entry
+{
+# define ZZIP_DISK_ENTRY_MAGIC 0x02014b50
+# define ZZIP_DISK_ENTRY_CHECKMAGIC(__p) ZZIP_CHECKMAGIC(__p,'P','K','\1','\2')
+ zzip_byte_t z_magic[4]; /* central file header signature (0x02014b50) */
+ zzip_version_t z_encoder; /* version made by */
+ zzip_version_t z_extract; /* version need to extract */
+ zzip_byte_t z_flags[2]; /* general purpose bit flag */
+ zzip_byte_t z_compr[2]; /* compression method */
+ zzip_dostime_t z_dostime; /* last mod file time&date (dos format) */
+ zzip_byte_t z_crc32[4]; /* crc-32 */
+ zzip_byte_t z_csize[4]; /* compressed size */
+ zzip_byte_t z_usize[4]; /* uncompressed size */
+ zzip_byte_t z_namlen[2]; /* filename length (null if stdin) */
+ zzip_byte_t z_extras[2]; /* extra field length */
+ zzip_byte_t z_comment[2]; /* file comment length */
+ zzip_byte_t z_diskstart[2]; /* disk number of start (if spanning zip over multiple disks) */
+ zzip_byte_t z_filetype[2]; /* internal file attributes, bit0 = ascii */
+ zzip_byte_t z_filemode[4]; /* extrnal file attributes, eg. msdos attrib byte */
+ zzip_byte_t z_offset[4]; /* relative offset of local file header, seekval if singledisk */
+ /* followed by filename (of variable size) */
+ /* followed by extra field (of variable size) */
+ /* followed by file comment (of variable size) */
+} __zzip_attribute__((packed));
+#define zzip_disk_entry_headerlength (4+2+2+2+2+4+4+4+4+2+2+2+2+2+4+4)
+
+
+struct zzip_root_dirent
+{ /* the old name of the structure above */
+# define ZZIP_ROOT_DIRENT_MAGIC 0x02014b50
+# define ZZIP_ROOT_DIRENT_CHECKMAGIC(__p) ZZIP_DISK_ENTRY_CHECKMAGIC(__p)
+ zzip_byte_t z_magic[4];
+ zzip_version_t z_encoder;
+ zzip_version_t z_extract;
+ zzip_byte_t z_flags[2];
+ zzip_byte_t z_compr[2];
+ zzip_dostime_t z_dostime;
+ zzip_byte_t z_crc32[4];
+ zzip_byte_t z_csize[4];
+ zzip_byte_t z_usize[4];
+ zzip_byte_t z_namlen[2];
+ zzip_byte_t z_extras[2];
+ zzip_byte_t z_comment[2];
+ zzip_byte_t z_diskstart[2];
+ zzip_byte_t z_filetype[2];
+ zzip_byte_t z_filemode[4];
+ zzip_byte_t z_off[4];
+} __zzip_attribute__((packed));
+
+
+/* end of central dir record */
+struct zzip_disk_trailer
+{
+# define ZZIP_DISK_TRAILER_MAGIC 0x06054b50
+# define ZZIP_DISK_TRAILER_CHECKMAGIC(__p) ZZIP_CHECKMAGIC(__p,'P','K','\5','\6')
+ zzip_byte_t z_magic[4]; /* end of central dir signature (0x06054b50) */
+ zzip_byte_t z_disk[2]; /* number of this disk */
+ zzip_byte_t z_finaldisk[2]; /* number of the disk with the start of the central dir */
+ zzip_byte_t z_entries[2]; /* total number of entries in the central dir on this disk */
+ zzip_byte_t z_finalentries[2]; /* total number of entries in the central dir */
+ zzip_byte_t z_rootsize[4]; /* size of the central directory */
+ zzip_byte_t z_rootseek[4]; /* offset of start of central directory with respect to *
+ * the starting disk number */
+ zzip_byte_t z_comment[2]; /* zipfile comment length */
+ /* followed by zipfile comment (of variable size) */
+} __zzip_attribute__((packed));
+#define zzip_disk_trailer_headerlength (4+2+2+2+2+4+4+2)
+
+/* extra field should be type + size + data + type + size + data ... */
+struct zzip_extra_block
+{ /* fetch.h macros do not need this struct */
+ zzip_byte_t z_datatype[2]; /* as input type - a mere <char*> is okay */
+ zzip_byte_t z_datasize[2]; /* being returned by xx_to_extras usually */
+} __zzip_attribute__((packed));
+#define zzip_extra_block_headerlength (2+2)
+
+/* Zip64 end of central dir record */
+struct zzip_disk64_trailer
+{
+# define ZZIP_DISK64_TRAILER_MAGIC 0x06064b50
+# define ZZIP_DISK64_TRAILER_CHECKMAGIC(__p) ZZIP_CHECKMAGIC(__p,'P','K','\6','\6')
+ zzip_byte_t z_magic[4]; /* end of central dir signature (0x06054b50) */
+ zzip_byte_t z_size[8]; /* size of this central directory record */
+ zzip_version_t z_encoder; /* version made by */
+ zzip_version_t z_extract; /* version need to extract */
+ zzip_byte_t z_disk[4]; /* number of this disk */
+ zzip_byte_t z_finaldisk[4]; /* number of the disk with the start of the central dir */
+ zzip_byte_t z_entries[8]; /* total number of entries in the central dir on this disk */
+ zzip_byte_t z_finalentries[8]; /* total number of entries in the central dir */
+ zzip_byte_t z_rootsize[8]; /* size of the central directory */
+ zzip_byte_t z_rootseek[8]; /* offset of start of central directory with respect to *
+ * the starting disk number */
+ /* followed by zip64 extensible data sector (of variable size) */
+} __zzip_attribute__((packed));
+#define zzip_disk64_trailer_headerlength (4+8+2+2+4+4+8+8+8+8)
+
+/* z_flags */
+#define ZZIP_IS_ENCRYPTED(p) ((*(zzip_byte_t*)p)&1)
+#define ZZIP_IS_COMPRLEVEL(p) (((*(zzip_byte_t*)p)>>1)&3)
+#define ZZIP_IS_STREAMED(p) (((*(zzip_byte_t*)p)>>3)&1)
+#define ZZIP_IS_PATCHED(p) (((*(zzip_byte_t*)p)>>5)&1)
+
+/* z_compr */
+#define ZZIP_IS_STORED 0
+#define ZZIP_IS_SHRUNK 1
+#define ZZIP_IS_REDUCEDx1 2
+#define ZZIP_IS_REDUCEDx2 3
+#define ZZIP_IS_REDUCEDx3 4
+#define ZZIP_IS_REDUCEDx4 5
+#define ZZIP_IS_IMPLODED 6
+#define ZZIP_IS_TOKENIZED 7
+#define ZZIP_IS_DEFLATED 8
+#define ZZIP_IS_DEFLATED_BETTER 9
+#define ZZIP_IS_IMPLODED_BETTER 10
+
+/* deflated comprlevel */
+#define ZZIP_DEFLATED_STD_COMPR 0
+#define ZZIP_DEFLATED_MAX_COMPR 1
+#define ZZIP_DEFLATED_LOW_COMPR 2
+#define ZZIP_DEFLATED_MIN_COMPR 3
+
+# ifdef _MSC_VER
+# pragma pack(pop)
+# endif
+
+#endif /* _ZZIPFORMAT_H */
+
+
+
+
diff --git a/Build/source/libs/zziplib/zzip/fseeko.c b/Build/source/libs/zziplib/zzip/fseeko.c
new file mode 100644
index 00000000000..2207f5dc981
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/fseeko.c
@@ -0,0 +1,580 @@
+/*
+ * NOTE: this is part of libzzipfseeko (i.e. it is not libzzip).
+ *
+ * These routines are fully independent from the traditional zzip
+ * implementation. They assume a readonly seekable stdio handle
+ * representing a complete zip file. The functions show how to
+ * parse the structure, find files and return a decoded bytestream.
+ *
+ * These routines are a bit simple and really here for documenting
+ * the way to access a zip file. The complexity of zip access comes
+ * from staggered reading of bytes and reposition of a filepointer in
+ * a big archive with lots of files and long compressed datastreams.
+ * Plus varaints of drop-in stdio replacements, obfuscation routines,
+ * auto fileextensions, drop-in dirent replacements, and so on...
+ *
+ * btw, we can _not_ use fgetpos/fsetpos since an fpos_t has no asserted
+ * relation to a linear seek value as specified in zip info headers. In
+ * general it is not a problem if your system has no fseeko/ftello pair
+ * since we can fallback to fseek/ftell which limits the zip disk size
+ * to 2MiBs but the zip-storable seek values are 32bit limited anyway.
+ *
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 2003,2004 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#define _LARGEFILE_SOURCE 1
+#define _ZZIP_ENTRY_STRUCT 1
+
+#include <zzip/types.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#if defined ZZIP_HAVE_STRING_H
+#include <string.h>
+#elif defined ZZIP_HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#include <zlib.h>
+#include <zzip/format.h>
+#include <zzip/fseeko.h>
+#include <zzip/fetch.h>
+#include <zzip/__mmap.h>
+#include <zzip/__fnmatch.h>
+
+#if __STDC_VERSION__+0 > 199900L
+#define ___
+#define ____
+#else
+#define ___ {
+#define ____ }
+#endif
+
+#ifndef ZZIP_HAVE_FSEEKO
+#define fseeko fseek
+#define ftello ftello
+#endif
+
+/* note that the struct zzip_entry inherits the zzip_disk_entry values
+ * and usually carries a copy of its values (in disk format!). To make the
+ * following code more readable, we use a shorthand notation for the
+ * upcast needed in C (not needed in C++) as "disk_(entry)".
+ */
+#ifdef __zzip_entry_extends_zzip_disk_entry
+#define disk_(_entry_) _entry_
+#else
+#define disk_(_entry_) (& (_entry_)->head)
+#endif
+
+/* we try to round all seeks to the pagesize - since we do not use
+ * the sys/mmap interface we have to guess a good value here: */
+#define PAGESIZE 8192
+
+/* ====================================================================== */
+/* helper functions */
+
+/** => zzip_entry_data_offset
+ * This functions read the correspoding struct zzip_file_header from
+ * the zip disk of the given "entry". The returned off_t points to the
+ * end of the file_header where the current fseek pointer has stopped.
+ * This is used to immediatly parse out any filename/extras block following
+ * the file_header. The return value is null on error.
+ */
+static zzip_off_t
+zzip_entry_fread_file_header (ZZIP_ENTRY* entry,
+ struct zzip_file_header* file_header)
+{
+ if (! entry || ! file_header) return 0;
+ ___ zzip_off_t offset = zzip_disk_entry_fileoffset (disk_(entry));
+ if (0 > offset || offset >= entry->disksize) return 0;
+
+ fseeko (entry->diskfile, offset, SEEK_SET);
+ return (fread (file_header, sizeof(*file_header), 1, entry->diskfile)
+ ? offset+sizeof(*file_header) : 0 ); ____;
+}
+
+/** helper functions for (fseeko) zip access api
+ *
+ * This functions returns the seekval offset of the data portion of the
+ * file referenced by the given zzip_entry. It requires an intermediate
+ * check of the file_header structure (i.e. it reads it from disk). After
+ * this call, the contained diskfile readposition is already set to the
+ * data_offset returned here. On error -1 is returned.
+ */
+zzip_off_t
+zzip_entry_data_offset(ZZIP_ENTRY* entry)
+{
+ struct zzip_file_header file_header;
+ if (! entry) return -1;
+ ___ zzip_off_t offset =
+ zzip_entry_fread_file_header (entry, & file_header);
+ if (! offset) return -1;
+ offset += zzip_file_header_sizeof_tails (& file_header);
+ fseeko (entry->diskfile, offset, SEEK_SET);
+ return offset; ____;
+}
+
+/** => zzip_entry_data_offset
+ * This function is a big helper despite its little name: in a zip file the
+ * encoded filenames are usually NOT zero-terminated but for common usage
+ * with libc we need it that way. Secondly, the filename SHOULD be present
+ * in the zip central directory but if not then we fallback to the filename
+ * given in the file_header of each compressed data portion.
+ */
+zzip__new__ char*
+zzip_entry_strdup_name(ZZIP_ENTRY* entry)
+{
+ if (! entry) return 0;
+
+ ___ zzip_size_t len;
+ if ((len = zzip_disk_entry_namlen (disk_(entry)))) {
+ char* name = malloc (len+1);
+ if (! name) return 0;
+ memcpy (name, entry->tail, len);
+ name[len] = '\0';
+ return name;
+ }
+ ___ auto struct zzip_file_header header;
+ if (zzip_entry_fread_file_header (entry, &header)
+ && ( len = zzip_file_header_namlen(&header) )) {
+ char* name = malloc (len+1);
+ if (! name) return 0;
+ fread (name, 1, len, entry->diskfile);
+ name[len] = '\0';
+ return name;
+ }
+ return 0;
+ ____;____;
+}
+
+static int
+prescan_entry(ZZIP_ENTRY* entry)
+{
+ assert (entry);
+ ___ zzip_off_t tailsize = zzip_disk_entry_sizeof_tails (disk_(entry));
+ if (tailsize+1 > entry->tailalloc) {
+ char* newtail = realloc (entry->tail, tailsize+1);
+ if (! newtail) return ENOMEM;
+ entry->tail = newtail;
+ entry->tailalloc = tailsize+1;
+ }
+ fread (entry->tail, 1, tailsize, entry->diskfile);
+ /* name + comment + extras */
+ return 0; ____;
+}
+
+static void
+prescan_clear(ZZIP_ENTRY* entry)
+{
+ assert (entry);
+ if (entry->tail) free (entry->tail);
+ entry->tail = 0; entry->tailalloc = 0;
+}
+
+/* ====================================================================== */
+
+/** => zzip_entry_findfile
+ *
+ * This function is the first call of all the zip access functions here.
+ * It contains the code to find the first entry of the zip central directory.
+ * Here we require the stdio handle to represent a real zip file where the
+ * disk_trailer is _last_ in the file area, so that its position would be at
+ * a fixed offset from the end of the file area if not for the comment field
+ * allowed to be of variable length (which needs us to do a little search
+ * for the disk_tailer). However, in this simple implementation we disregard
+ * any disk_trailer info telling about multidisk archives, so we just return
+ * a pointer to the first entry in the zip central directory of that file.
+ *
+ * For an actual means, we are going to search backwards from the end
+ * of the mmaped block looking for the PK-magic signature of a
+ * disk_trailer. If we see one then we check the rootseek value to
+ * find the first disk_entry of the root central directory. If we find
+ * the correct PK-magic signature of a disk_entry over there then we
+ * assume we are done and we are going to return a pointer to that label.
+ *
+ * The return value is a pointer to the first zzip_disk_entry being checked
+ * to be within the bounds of the file area specified by the arguments. If
+ * no disk_trailer was found then null is returned, and likewise we only
+ * accept a disk_trailer with a seekvalue that points to a disk_entry and
+ * both parts have valid PK-magic parts. Beyond some sanity check we try to
+ * catch a common brokeness with zip archives that still allows us to find
+ * the start of the zip central directory.
+ */
+zzip__new__ ZZIP_ENTRY*
+zzip_entry_findfirst(FILE* disk)
+{
+ if (! disk) return 0;
+ fseeko (disk, 0, SEEK_END);
+ ___ zzip_off_t disksize = ftello (disk);
+ if (disksize < (zzip_off_t) sizeof(struct zzip_disk_trailer)) return 0;
+ /* we read out chunks of 8 KiB in the hope to match disk granularity */
+ ___ zzip_off_t pagesize = PAGESIZE; /* getpagesize() */
+ ___ ZZIP_ENTRY* entry = malloc (sizeof(*entry)); if (! entry) return 0;
+ ___ unsigned char* buffer = malloc (pagesize); if (! buffer) goto nomem;
+
+ assert (pagesize/2 > (zzip_off_t) sizeof (struct zzip_disk_trailer));
+ /* at each step, we will fread a pagesize block which overlaps with the
+ * previous read by means of pagesize/2 step at the end of the while(1) */
+ ___ zzip_off_t mapoffs = disksize &~ (pagesize-1);
+ ___ zzip_off_t mapsize = disksize - mapoffs;
+ if (mapoffs && mapsize < pagesize/2) {
+ mapoffs -= pagesize/2; mapsize += pagesize/2; }
+ while(1) {
+ fseeko (disk, mapoffs, SEEK_SET);
+ fread (buffer, 1, mapsize, disk);
+ ___ unsigned char* p =
+ buffer + mapsize - sizeof(struct zzip_disk_trailer);
+ for (; p >= buffer ; p--)
+ {
+ zzip_off_t root; /* (struct zzip_disk_entry*) */
+ if (zzip_disk_trailer_check_magic(p)) {
+ root = zzip_disk_trailer_rootseek (
+ (struct zzip_disk_trailer*)p);
+ if (root > disksize - (long)sizeof(struct zzip_disk_trailer)) {
+ /* first disk_entry is after the disk_trailer? can't be! */
+ zzip_off_t rootsize = zzip_disk_trailer_rootsize (
+ (struct zzip_disk_trailer*)p);
+ if (rootsize > mapoffs) continue;
+ /* a common brokeness that can be fixed: we just assume the
+ * central directory was written directly before : */
+ root = mapoffs - rootsize;
+ }
+ } else if (zzip_disk64_trailer_check_magic(p)) {
+ if (sizeof(zzip_off_t) < 8) return 0;
+ root = zzip_disk64_trailer_rootseek (
+ (struct zzip_disk64_trailer*)p);
+ } else continue;
+
+ assert (0 <= root && root < mapsize);
+ fseeko (disk, root, SEEK_SET);
+ fread (disk_(entry), 1, sizeof(*disk_(entry)), disk);
+ if (zzip_disk_entry_check_magic(entry)) {
+ free (buffer);
+ entry->headseek = root;
+ entry->diskfile = disk;
+ entry->disksize = disksize;
+ if (prescan_entry(entry)) goto nomem;
+ return entry;
+ }
+ } ____;
+ if (! mapoffs) break; assert (mapsize >= pagesize/2);
+ mapoffs -= pagesize/2; /* mapsize += pagesize/2; */
+ mapsize = pagesize; /* if (mapsize > pagesize) ... */
+ if (disksize - mapoffs > 64*1024) break;
+ }
+ free (buffer);
+ nomem:
+ free (entry); ____;____;____;____;____;____;
+ return 0;
+}
+
+/** => zzip_entry_findfile
+ *
+ * This function takes an existing "entry" in the central root directory
+ * (e.g. from zzip_entry_findfirst) and moves it to point to the next entry.
+ * On error it returns 0, otherwise the old entry. If no further match is
+ * found then null is returned and the entry already free()d. If you want
+ * to stop searching for matches before that case then please call
+ * => zzip_entry_free on the cursor struct ZZIP_ENTRY.
+ */
+zzip__new__ ZZIP_ENTRY*
+zzip_entry_findnext(ZZIP_ENTRY* _zzip_restrict entry)
+{
+ if (! entry) return entry;
+ if (! zzip_disk_entry_check_magic (entry)) goto err;
+ ___ zzip_off_t seek =
+ entry->headseek + zzip_disk_entry_sizeto_end (disk_(entry));
+ if (seek + (zzip_off_t) sizeof(*disk_(entry)) > entry->disksize) goto err;
+
+ fseeko (entry->diskfile, seek, SEEK_SET);
+ fread (disk_(entry), 1, sizeof(*disk_(entry)), entry->diskfile);
+ entry->headseek = seek;
+ if (! zzip_disk_entry_check_magic (entry)) goto err;
+ if (prescan_entry(entry)) goto err;
+ return entry;
+ err:
+ zzip_entry_free (entry);
+ return 0; ____;
+}
+
+/** => zzip_entry_findfile
+ * this function releases the malloc()ed areas needed for zzip_entry, the
+ * pointer is invalid afterwards. This function has #define synonyms of
+ * zzip_entry_findlast(), zzip_entry_findlastfile(), zzip_entry_findlastmatch()
+ */
+int
+zzip_entry_free(ZZIP_ENTRY* entry)
+{
+ if (! entry) return 0;
+ prescan_clear (entry);
+ free (entry);
+ return 1;
+}
+
+/** search for files in the (fseeko) zip central directory
+ *
+ * This function is given a filename as an additional argument, to find the
+ * disk_entry matching a given filename. The compare-function is usually
+ * strcmp or strcasecmp or perhaps strcoll, if null then strcmp is used.
+ * - use null as argument for "old"-entry when searching the first
+ * matching entry, otherwise the last returned value if you look for other
+ * entries with a special "compare" function (if null then a doubled search
+ * is rather useless with this variant of _findfile). If no further entry is
+ * found then null is returned and any "old"-entry gets already free()d.
+ */
+zzip__new__ ZZIP_ENTRY*
+zzip_entry_findfile(FILE* disk, char* filename,
+ ZZIP_ENTRY* _zzip_restrict entry,
+ zzip_strcmp_fn_t compare)
+{
+ if (! filename || ! disk) return 0;
+ entry = ( ! entry ) ? zzip_entry_findfirst (disk)
+ : zzip_entry_findnext (entry);
+ if (! compare) compare = (zzip_strcmp_fn_t)(strcmp);
+
+ for (; entry ; entry = zzip_entry_findnext (entry))
+ { /* filenames within zip files are often not null-terminated! */
+ char* realname = zzip_entry_strdup_name (entry);
+ if (! realname) continue;
+ if (! compare (filename, realname)) {
+ free (realname); return entry;
+ } else {
+ free (realname); continue;
+ }
+ }
+ return 0;
+}
+
+#ifdef ZZIP_HAVE_FNMATCH_H
+#define _zzip_fnmatch fnmatch
+# ifdef FNM_CASEFOLD
+# define _zzip_fnmatch_CASEFOLD FNM_CASEFOLD
+# else
+# define _zzip_fnmatch_CASEFOLD 0
+# endif
+#else
+# define _zzip_fnmatch_CASEFOLD 0
+/* if your system does not have fnmatch, we fall back to strcmp: */
+static int _zzip_fnmatch(char* pattern, char* string, int flags)
+{
+ puts ("<zzip:strcmp>");
+ return strcmp (pattern, string);
+}
+#endif
+
+/** => zzip_entry_findfile
+ *
+ * This function uses a compare-function with an additional argument
+ * and it is called just like fnmatch(3) from POSIX.2 AD:1993), i.e.
+ * the argument filespec first and the ziplocal filename second with
+ * the integer-flags put in as third to the indirect call. If the
+ * platform has fnmatch available then null-compare will use that one
+ * and otherwise we fall back to mere strcmp, so if you need fnmatch
+ * searching then please provide an implementation somewhere else.
+ * - use null as argument for "after"-entry when searching the first
+ * matching entry, or the last disk_entry return-value to find the
+ * next entry matching the given filespec. If no further entry is
+ * found then null is returned and any "old"-entry gets already free()d.
+ */
+zzip__new__ ZZIP_ENTRY*
+zzip_entry_findmatch(FILE* disk, char* filespec,
+ ZZIP_ENTRY* _zzip_restrict entry,
+ zzip_fnmatch_fn_t compare, int flags)
+{
+ if (! filespec || ! disk) return 0;
+ entry = ( ! entry ) ? zzip_entry_findfirst (disk)
+ : zzip_entry_findnext (entry);
+ if (! compare) compare = (zzip_fnmatch_fn_t) _zzip_fnmatch;
+
+ for (; entry ; entry = zzip_entry_findnext (entry))
+ { /* filenames within zip files are often not null-terminated! */
+ char* realname = zzip_entry_strdup_name (entry);
+ if (! realname) continue;
+ if (! compare (filespec, realname, flags)) {
+ free (realname); return entry;
+ } else {
+ free (realname); continue;
+ }
+ }
+ return 0;
+}
+
+/* ====================================================================== */
+
+/**
+ * typedef struct zzip_disk_file ZZIP_ENTRY_FILE;
+ */
+struct zzip_entry_file /* : zzip_file_header */
+{
+ struct zzip_file_header header; /* fopen detected header */
+ ZZIP_ENTRY* entry; /* fopen entry */
+ zzip_off_t data; /* for stored blocks */
+ zzip_size_t avail; /* memorized for checks on EOF */
+ zzip_size_t compressed; /* compressed flag and datasize */
+ zzip_size_t dataoff; /* offset from data start */
+ z_stream zlib; /* for inflated blocks */
+ unsigned char buffer[PAGESIZE]; /* work buffer for inflate algorithm */
+};
+
+/** open a file within a zip disk for reading
+ *
+ * This function does take an "entry" argument and copies it (or just takes
+ * it over as owner) to a new ZZIP_ENTRY_FILE handle structure. That
+ * structure contains also a zlib buffer for decoding. This function does
+ * seek to the file_header of the given "entry" and validates it for the
+ * data buffer following it. We do also prefetch some data from the data
+ * buffer thereby trying to match the disk pagesize for faster access later.
+ * The => zzip_entry_fread will then read in chunks of pagesizes which is
+ * the size of the internal readahead buffer. If an error occurs then null
+ * is returned.
+ */
+zzip__new__ ZZIP_ENTRY_FILE*
+zzip_entry_fopen (ZZIP_ENTRY* entry, int takeover)
+{
+ if (! entry) return 0;
+ if (! takeover) {
+ ZZIP_ENTRY* found = malloc (sizeof(*entry));
+ if (! found) return 0;
+ memcpy (found, entry, sizeof(*entry)); /* prescan_copy */
+ found->tail = malloc (found->tailalloc);
+ if (! found->tail) { free (found); return 0; }
+ memcpy (found->tail, entry->tail, entry->tailalloc);
+ entry = found;
+ }
+ ___ ZZIP_ENTRY_FILE* file = malloc(sizeof(*file));
+ if (! file) goto fail1;
+ file->entry = entry;
+ if (! zzip_entry_fread_file_header (entry, &file->header))
+ goto fail2;
+ file->avail = zzip_file_header_usize (&file->header);
+ file->data = zzip_entry_data_offset (entry);
+ file->dataoff = 0;
+
+ if (! file->avail || zzip_file_header_data_stored (&file->header))
+ { file->compressed = 0; return file; }
+
+ file->compressed = zzip_file_header_csize (&file->header);
+ file->zlib.opaque = 0;
+ file->zlib.zalloc = Z_NULL;
+ file->zlib.zfree = Z_NULL;
+
+ ___ zzip_off_t seek = file->data;
+ seek += sizeof(file->buffer); seek -= seek & (sizeof(file->buffer)-1);
+ assert (file->data < seek); /* pre-read to next PAGESIZE boundary... */
+ fseeko (file->entry->diskfile, file->data + file->dataoff, SEEK_SET);
+ file->zlib.next_in = file->buffer;
+ file->zlib.avail_in = fread (file->buffer, 1, seek - file->data,
+ file->entry->diskfile);
+ file->dataoff += file->zlib.avail_in; ____;
+
+ if (! zzip_file_header_data_deflated (&file->header)
+ || inflateInit2 (& file->zlib, -MAX_WBITS) != Z_OK) goto fail2;
+
+ return file;
+ fail2:
+ free (file);
+ fail1:
+ zzip_entry_free (entry);
+ return 0; ____;
+}
+
+/** => zzip_entry_fopen
+ *
+ * This function opens a file found by name, so it does a search into
+ * the zip central directory with => zzip_entry_findfile and whatever
+ * is found first is given to => zzip_entry_fopen
+ */
+zzip__new__ ZZIP_ENTRY_FILE*
+zzip_entry_ffile (FILE* disk, char* filename)
+{
+ ZZIP_ENTRY* entry = zzip_entry_findfile (disk, filename, 0, 0);
+ if (! entry) return 0;
+ return zzip_entry_fopen (entry, 1);
+}
+
+
+/** => zzip_entry_fopen
+ *
+ * This function reads more bytes into the output buffer specified as
+ * arguments. The return value is null on eof or error, the stdio-like
+ * interface can not distinguish between these so you need to check
+ * with => zzip_entry_feof for the difference.
+ */
+zzip_size_t
+zzip_entry_fread (void* ptr, zzip_size_t sized, zzip_size_t nmemb,
+ ZZIP_ENTRY_FILE* file)
+{
+ if (! file) return 0;
+ ___ zzip_size_t size = sized*nmemb;
+ if (! file->compressed) {
+ if (size > file->avail) size = file->avail;
+ fread (ptr, 1, size, file->entry->diskfile);
+ file->dataoff += size;
+ file->avail -= size;
+ return size;
+ }
+
+ file->zlib.avail_out = size;
+ file->zlib.next_out = ptr;
+ ___ zzip_size_t total_old = file->zlib.total_out;
+ while (1) {
+ if (! file->zlib.avail_in) {
+ size = file->compressed - file->dataoff;
+ if (size > sizeof(file->buffer)) size = sizeof(file->buffer);
+ /* fseek (file->data + file->dataoff, file->entry->diskfile); */
+ file->zlib.avail_in = fread (file->buffer, 1, size,
+ file->entry->diskfile);
+ file->zlib.next_in = file->buffer;
+ file->dataoff += file->zlib.avail_in;
+ }
+ if (! file->zlib.avail_in) return 0;
+
+ ___ int err = inflate (& file->zlib, Z_NO_FLUSH);
+ if (err == Z_STREAM_END)
+ file->avail = 0;
+ else if (err == Z_OK)
+ file->avail -= file->zlib.total_out - total_old;
+ else
+ return 0;
+ ____;
+ if (file->zlib.avail_out && ! file->zlib.avail_in) continue;
+ return file->zlib.total_out - total_old;
+ }____;____;
+}
+
+/** => zzip_entry_fopen
+ * This function releases any zlib decoder info needed for decompression
+ * and dumps the ZZIP_ENTRY_FILE struct then.
+ */
+int
+zzip_entry_fclose (ZZIP_ENTRY_FILE* file)
+{
+ if (! file) return 0;
+ if (file->compressed)
+ inflateEnd (& file->zlib);
+ zzip_entry_free (file->entry);
+ free (file);
+ return 0;
+}
+
+/** => zzip_entry_fopen
+ *
+ * This function allows to distinguish an error from an eof condition.
+ * Actually, if we found an error but we did already reach eof then we
+ * just keep on saying that it was an eof, so the app can just continue.
+ */
+int
+zzip_entry_feof (ZZIP_ENTRY_FILE* file)
+{
+ return ! file || ! file->avail;
+}
diff --git a/Build/source/libs/zziplib/zzip/fseeko.h b/Build/source/libs/zziplib/zzip/fseeko.h
new file mode 100644
index 00000000000..cbe40f7db4a
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/fseeko.h
@@ -0,0 +1,116 @@
+#ifndef _ZZIP_FSEEKO_H_
+#define _ZZIP_FSEEKO_H_
+/*
+ * NOTE: this is part of libzzipfseeko (i.e. it is not libzzip).
+ *
+ * simplified zip disk access using fseeko on a stdio FILE handle
+ *
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 2003,2004 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+
+#include <zzip/types.h>
+#include <stdio.h>
+
+typedef struct zzip_entry ZZIP_ENTRY;
+typedef struct zzip_entry_file ZZIP_ENTRY_FILE;
+
+typedef int (*zzip_strcmp_fn_t)(char*, char*);
+typedef int (*zzip_fnmatch_fn_t)(char*, char*, int);
+
+#ifndef zzip_entry_extern
+#define zzip_entry_extern extern
+#endif
+
+zzip_entry_extern zzip_off_t
+zzip_entry_data_offset(ZZIP_ENTRY* entry);
+
+zzip__new__
+zzip_entry_extern ZZIP_ENTRY*
+zzip_entry_findfirst(FILE* file);
+
+zzip__new__
+zzip_entry_extern ZZIP_ENTRY*
+zzip_entry_findnext(ZZIP_ENTRY* _zzip_restrict entry);
+
+#define zzip_entry_findlast zzip_entry_free
+#define zzip_entry_findlastfile zzip_entry_free
+#define zzip_entry_findlastmatch zzip_entry_free
+
+zzip_entry_extern int
+zzip_entry_free(ZZIP_ENTRY* entry);
+
+zzip__new__
+zzip_entry_extern char*
+zzip_entry_strdup_name(ZZIP_ENTRY* entry);
+zzip_entry_extern char*
+zzip_entry_to_data(ZZIP_ENTRY* entry);
+
+zzip__new__
+zzip_entry_extern ZZIP_ENTRY*
+zzip_entry_findfile(FILE* disk, char* filename,
+ ZZIP_ENTRY* _zzip_restrict old,
+ zzip_strcmp_fn_t compare);
+zzip__new__
+zzip_entry_extern ZZIP_ENTRY*
+zzip_entry_findmatch(FILE* disk, char* filespec,
+ ZZIP_ENTRY* _zzip_restrict old,
+ zzip_fnmatch_fn_t compare, int flags);
+zzip__new__
+zzip_entry_extern ZZIP_ENTRY_FILE*
+zzip_entry_fopen (ZZIP_ENTRY* entry, int takeover);
+
+zzip__new__
+zzip_entry_extern ZZIP_ENTRY_FILE*
+zzip_entry_ffile (FILE* disk, char* filename);
+
+zzip_entry_extern _zzip_size_t
+zzip_entry_fread (void* ptr, _zzip_size_t size, _zzip_size_t nmemb,
+ ZZIP_ENTRY_FILE* file);
+zzip_entry_extern int
+zzip_entry_fclose (ZZIP_ENTRY_FILE* file);
+int
+zzip_entry_feof (ZZIP_ENTRY_FILE* file);
+
+# ifdef _ZZIP_ENTRY_STRUCT
+# ifdef __cplusplus
+# define __zzip_entry_extends_zzip_disk_entry
+struct zzip_entry : public struct zzip_disk_entry
+{
+ char* _zzip_restrict tail;
+ zzip_off_t tailalloc; /* the allocated size of tail */
+ FILE* diskfile; /* a file reference */
+ zzip_off_t disksize; /* the size of the file */
+ zzip_off_t headseek; /* the offset within the file */
+ zzip_off_t zz_usize;
+ zzip_off_t zz_csize; /* items scanned from header */
+ zzip_off_t zz_offset; /* or zip64 extension block */
+ int zz_diskstart;
+};
+# else
+struct zzip_entry /* : struct zzip_disk_entry */
+{
+ struct zzip_disk_entry head;
+ char* _zzip_restrict tail;
+ zzip_off_t tailalloc; /* the allocated size of tail */
+ FILE* diskfile; /* a file reference */
+ zzip_off_t disksize; /* the size of the file */
+ zzip_off_t headseek; /* the offset within the file */
+ zzip_off_t zz_usize;
+ zzip_off_t zz_csize; /* items scanned from header */
+ zzip_off_t zz_offset; /* or zip64 extension block */
+ int zz_diskstart;
+};
+# endif /* __cplusplus */
+# endif /* _ZZIP_MEM_ENTRY_PRIVATE */
+
+#endif
+
diff --git a/Build/source/libs/zziplib/zzip/info.c b/Build/source/libs/zziplib/zzip/info.c
new file mode 100644
index 00000000000..144b163d9e8
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/info.c
@@ -0,0 +1,161 @@
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 2000,2001,2002,2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#include <zzip/lib.h> /* exported... */
+#include <zzip/file.h>
+#include <zzip/format.h>
+
+#ifdef ZZIP_HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#endif
+
+/**
+ * just returns dir->errcode of the ZZIP_DIR handle
+ * see: => zzip_dir_open, => zzip_diropen, => zzip_readdir, => zzip_dir_read
+ */
+int
+zzip_error(ZZIP_DIR * dir)
+{
+ return dir->errcode;
+}
+
+/** => zzip_error
+ * This function just does dir->errcode = errcode
+ */
+void
+zzip_seterror(ZZIP_DIR * dir, int errcode)
+{ dir->errcode = errcode; }
+
+/**
+ * This function will just return fp->dir
+ *
+ * If a ZZIP_FILE is contained within a zip-file that one will be a valid
+ * pointer, otherwise a NULL is returned and the ZZIP_FILE wraps a real file.
+ */
+ZZIP_DIR *
+zzip_dirhandle(ZZIP_FILE * fp)
+{
+ return fp->dir;
+}
+
+/** => zzip_dirhandle
+ * This function will just return dir->fd
+ *
+ * If a ZZIP_DIR does point to a zipfile then the file-descriptor of that
+ * zipfile is returned, otherwise a NULL is returned and the ZZIP_DIR wraps
+ * a real directory DIR (if you have dirent on your system).
+ */
+int
+zzip_dirfd(ZZIP_DIR* dir)
+{
+ return dir->fd;
+}
+
+/**
+ * return static const string of the known compression methods,
+ * otherwise just "zipped" is returned
+ */
+zzip_char_t*
+zzip_compr_str(int compr)
+{
+ switch(compr)
+ {
+ case ZZIP_IS_STORED: return "stored";
+ case ZZIP_IS_SHRUNK: return "shrunk";
+ case ZZIP_IS_REDUCEDx1:
+ case ZZIP_IS_REDUCEDx2:
+ case ZZIP_IS_REDUCEDx3:
+ case ZZIP_IS_REDUCEDx4: return "reduced";
+ case ZZIP_IS_IMPLODED: return "imploded";
+ case ZZIP_IS_TOKENIZED: return "tokenized";
+ case ZZIP_IS_DEFLATED: return "deflated";
+ case ZZIP_IS_DEFLATED_BETTER: return "deflatedX";
+ case ZZIP_IS_IMPLODED_BETTER: return "implodedX";
+ default:
+ if (0 < compr && compr < 256) return "zipped";
+ else
+ {
+# ifdef S_ISDIR
+ if (S_ISDIR(compr)) return "directory";
+# endif
+# ifdef S_ISCHR
+ if (S_ISCHR(compr)) return "is/chr";
+# endif
+# ifdef S_ISBLK
+ if (S_ISBLK(compr)) return "is/blk";
+# endif
+# ifdef S_ISFIFO
+ if (S_ISFIFO(compr)) return "is/fifo";
+# endif
+# ifdef S_ISSOCK
+ if (S_ISSOCK(compr)) return "is/sock";
+# endif
+# ifdef S_ISLNK
+ if (S_ISLNK(compr)) return "is/lnk";
+# endif
+ return "special";
+ }
+ }/*switch*/
+}
+
+/** => zzip_file_real
+ * This function checks if the ZZIP_DIR-handle is wrapping
+ * a real directory or a zip-archive.
+ * Returns 1 for a stat'able directory, and 0 for a handle to zip-archive.
+ */
+int
+zzip_dir_real(ZZIP_DIR* dir)
+{
+ return dir->realdir != 0;
+}
+
+/**
+ * This function checks if the ZZIP_FILE-handle is wrapping
+ * a real file or a zip-contained file.
+ * Returns 1 for a stat'able file, and 0 for a file inside a zip-archive.
+ */
+int
+zzip_file_real(ZZIP_FILE* fp)
+{
+ return fp->dir == 0; /* ie. not dependent on a zip-arch-dir */
+}
+
+/** => zzip_file_real
+ * This function returns the posix DIR* handle (if one exists).
+ * Check before with => zzip_dir_real if the
+ * the ZZIP_DIR points to a real directory.
+ */
+void*
+zzip_realdir(ZZIP_DIR* dir)
+{
+ return dir->realdir;
+}
+
+/** => zzip_file_real
+ * This function returns the posix file descriptor (if one exists).
+ * Check before with => zzip_file_real if the
+ * the ZZIP_FILE points to a real file.
+ */
+int
+zzip_realfd(ZZIP_FILE* fp)
+{
+ return fp->fd;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/zzip/info.h b/Build/source/libs/zziplib/zzip/info.h
new file mode 100644
index 00000000000..0ab6edab561
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/info.h
@@ -0,0 +1,25 @@
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 2000,2001,2002,2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#ifdef ZZIP_USE_INTERNAL
+/* do not make these public, they are for internal use only */
+
+#define ZZIP_error(__dir) __dir->errcode
+#define ZZIP_seterror(__dir, __code) __dir->errcode = __code
+#define ZZIP_dirhandle(__fp) __fp->dir
+#define ZZIP_dirfd(__dir) __dir->fd
+#define ZZIP_dir_real(__dir) __dir->realdir != 0
+#define ZZIP_file_real(__fp) __fp->dir == 0
+#define ZZIP_realdir(__dir) __dir->realdir
+#define ZZIP_reafd(__fp) __fp->fd
+
+#endif
diff --git a/Build/source/libs/zziplib/zzip/lib.h b/Build/source/libs/zziplib/zzip/lib.h
new file mode 100644
index 00000000000..b1ad0690042
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/lib.h
@@ -0,0 +1,83 @@
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ * Tomi Ollila <Tomi.Ollila@iki.fi>
+ *
+ * Copyright (c) 1999,2000,2001,2002,2003 Guido Draheim
+ * All rights reserved
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ *
+ * This is the private header containing definitions that are not
+ * use by a libzzip user application. Writing an extension lib that
+ * uses libzzip will still want to include this. The extension
+ * write should make way to have the ISO C9X integer types defined.
+ */
+#ifndef _ZZIP_LIB_H /* zzip.h */
+#define _ZZIP_LIB_H
+
+#include <zzip/zzip.h>
+#include <zzip/plugin.h>
+#include <zzip/stdint.h>
+
+/*
+ * this structure cannot be wildly enlarged... (see zzip-zip.c)
+ */
+struct zzip_dir_hdr
+{
+ uint32_t d_usize; /* uncompressed size */
+ uint32_t d_csize; /* compressed size */
+ uint32_t d_crc32; /* the adler32-checksum */
+ uint32_t d_off; /* offset of file in zipfile */
+ uint16_t d_reclen; /* next dir_hdr structure offset */
+ uint16_t d_namlen; /* explicit namelen of d_name */
+ uint8_t d_compr; /* the compression type, 0 = store, 8 = inflate */
+ char d_name[1]; /* the actual name of the entry, may contain DIRSEPs */
+};
+#define _ZZIP_DIRENT_HAVE_D_NAMLEN
+#define _ZZIP_DIRENT_HAVE_D_OFF
+#define _ZZIP_DIRENT_HAVE_D_RECLEN
+
+/*
+ * you shall not use this struct anywhere else than in zziplib sources.
+ */
+struct zzip_dir
+{
+ int fd;
+ int errcode; /* zzip_error_t */
+ long refcount;
+ struct { /* reduce a lot of alloc/deallocations by caching these: */
+ int * volatile locked;
+ struct zzip_file * volatile fp;
+ char * volatile buf32k;
+ } cache;
+ struct zzip_dir_hdr * hdr0; /* zfi; */
+ struct zzip_dir_hdr * hdr; /* zdp; directory pointer, for dirent stuff */
+ struct zzip_file * currentfp; /* last fp used... */
+ struct zzip_dirent dirent;
+ void* realdir; /* e.g. DIR* from posix dirent.h */
+ char* realname;
+ zzip_strings_t* fileext; /* list of fileext to test for */
+ zzip_plugin_io_t io; /* vtable for io routines */
+};
+
+#define ZZIP_32K 32768
+
+/* try to open a zip-basename with default_fileext */
+int __zzip_try_open (zzip_char_t* filename, int filemode,
+ zzip_strings_t* ext, zzip_plugin_io_t io);
+
+ZZIP_DIR *
+zzip_dir_fdopen(int fd, zzip_error_t * errcode_p);
+
+ZZIP_DIR*
+zzip_dir_fdopen_ext_io(int fd, zzip_error_t * errorcode_p,
+ zzip_strings_t* ext, const zzip_plugin_io_t io);
+
+ZZIP_DIR* /*depracated*/
+zzip_dir_alloc_ext_io (zzip_strings_t* ext, const zzip_plugin_io_t io);
+
+#endif /* _ZZIP_H */
+
diff --git a/Build/source/libs/zziplib/zzip/memdisk.c b/Build/source/libs/zziplib/zzip/memdisk.c
new file mode 100644
index 00000000000..7d66352add8
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/memdisk.c
@@ -0,0 +1,394 @@
+/*
+ * NOTE: this is part of libzzipmmapped (i.e. it is not libzzip).
+ *
+ * The mem_disk cache will parse the central information of a zip archive
+ * and store it internally. One the one hand it allows to find files
+ * faster - no disk access is required and endian conversion is not
+ * needed. If zzip is compiled with zip extensions then it is about
+ * the only way to build maintainable code around the zip format.
+ *
+ * Note that 64bit support is almost entirely living in extension
+ * blocks as well as different character encodings and file access
+ * control bits that are mostly platform specific.
+ *
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 1999,2000,2001,2002,2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+#define _ZZIP_DISK_FILE_STRUCT 1
+
+#include <zzip/types.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include <zlib.h>
+#include <zzip/format.h>
+#include <zzip/fetch.h>
+#include <zzip/mmapped.h>
+#include <zzip/memdisk.h>
+#include <zzip/__fnmatch.h>
+
+#define ___ {
+#define ____ }
+
+static const char* error[] = {
+ "Ok",
+# define _zzip_mem_disk_open_fail 1
+ "zzip_mem_disk_open: zzip_disk_open did fail",
+# define _zzip_mem_disk_fdopen_fail 2
+ "zzip_mem_disk_fdopen: zzip_disk_mmap did fail"
+};
+
+#define R _zzip_restrict /* a.k.a. allocated */
+
+
+#define ZZIP_EXTRA_zip64 0x0001
+typedef struct _zzip_extra_zip64 { /* ZIP64 extended information extra field */
+ zzip_byte_t z_datatype[2]; /* Tag for this "extra" block type */
+ zzip_byte_t z_datasize[2]; /* Size of this "extra" block */
+ zzip_byte_t z_usize[8]; /* Original uncompressed file size */
+ zzip_byte_t z_csize[8]; /* Size of compressed data */
+ zzip_byte_t z_offset[8]; /* Offset of local header record */
+ zzip_byte_t z_diskstart[4]; /* Number of the disk for file start*/
+} zzip_extra_zip64;
+
+/*forward*/
+
+zzip__new__ static ZZIP_MEM_ENTRY*
+zzip_mem_entry_new(ZZIP_DISK* disk, ZZIP_DISK_ENTRY* entry);
+zzip__new__ static void
+zzip_mem_entry_free(ZZIP_MEM_ENTRY* _zzip_restrict item);
+
+zzip__new__ ZZIP_MEM_DISK*
+zzip_mem_disk_new(void)
+{
+ return calloc(1, sizeof(ZZIP_MEM_DISK));
+}
+
+/** create new diskdir handle.
+ * wraps underlying zzip_disk_open. */
+zzip__new__ ZZIP_MEM_DISK*
+zzip_mem_disk_open(char* filename)
+{
+ ZZIP_DISK* disk = zzip_disk_open(filename);
+ if (! disk) { perror(error[_zzip_mem_disk_open_fail]); return 0; }
+ ___ ZZIP_MEM_DISK* dir = zzip_mem_disk_new();
+ zzip_mem_disk_load(dir, disk);
+ return dir; ____;
+}
+
+/** create new diskdir handle.
+ * wraps underlying zzip_disk_open. */
+zzip__new__ ZZIP_MEM_DISK*
+zzip_mem_disk_fdopen(int fd)
+{
+ ZZIP_DISK* disk = zzip_disk_mmap(fd);
+ if (! disk) { perror(error[_zzip_mem_disk_fdopen_fail]); return 0; }
+ ___ ZZIP_MEM_DISK* dir = zzip_mem_disk_new();
+ zzip_mem_disk_load(dir, disk);
+ return dir; ____;
+}
+
+/** parse central dir.
+ * creates an internal copy of each entry converted to the local platform.
+ * returns: number of entries, or -1 on error (setting errno)
+ */
+long
+zzip_mem_disk_load(ZZIP_MEM_DISK* dir, ZZIP_DISK* disk)
+{
+ if (! dir || ! disk) { errno=EINVAL; return -1; }
+ if (dir->list) zzip_mem_disk_unload(dir);
+ ___ long count = 0;
+ ___ struct zzip_disk_entry* entry = zzip_disk_findfirst(disk);
+ for (; entry ; entry = zzip_disk_findnext(disk, entry)) {
+ ZZIP_MEM_ENTRY* item = zzip_mem_entry_new(disk, entry);
+ if (! item) goto error;
+ if (dir->last) { dir->last->zz_next = item; } /* chain last */
+ else { dir->list = item; }; dir->last = item; /* to earlier */
+ count++;
+ } ____;
+ dir->disk = disk;
+ return count; ____;
+ error:
+ zzip_mem_disk_unload (dir);
+ return -1;
+}
+
+/** convert a zip disk entry to internal format.
+ * creates a new item parsing the information out of the various places
+ * in the zip archive. This is a good place to extend functionality if
+ * you have a project with extra requirements as you can push more bits
+ * right into the diskdir_entry for later usage in higher layers.
+ * returns: new item, or null on error (setting errno)
+ */
+zzip__new__ ZZIP_MEM_ENTRY*
+zzip_mem_entry_new(ZZIP_DISK* disk, ZZIP_DISK_ENTRY* entry)
+{
+ if (! disk || ! entry) { errno=EINVAL; return 0; }
+ ___ ZZIP_MEM_ENTRY* item = calloc(1, sizeof(*item));
+ if (! item) return 0; /* errno=ENOMEM; */
+ ___ struct zzip_file_header* header =
+ zzip_disk_entry_to_file_header(disk, entry);
+ /* there is a number of duplicated information in the file header
+ * or the disk entry block. Theoretically some part may be missing
+ * that exists in the other, ... but we will prefer the disk entry.
+ */
+ item->zz_comment = zzip_disk_entry_strdup_comment(disk, entry);
+ item->zz_name = zzip_disk_entry_strdup_name(disk, entry);
+ item->zz_data = zzip_file_header_to_data(header);
+ item->zz_flags = zzip_disk_entry_get_flags(entry);
+ item->zz_compr = zzip_disk_entry_get_compr(entry);
+ item->zz_mktime = zzip_disk_entry_get_mktime(entry);
+ item->zz_crc32 = zzip_disk_entry_get_crc32(entry);
+ item->zz_csize = zzip_disk_entry_get_csize(entry);
+ item->zz_usize = zzip_disk_entry_get_usize(entry);
+ item->zz_diskstart = zzip_disk_entry_get_diskstart(entry);
+ item->zz_filetype = zzip_disk_entry_get_filetype(entry);
+
+ { /* copy the extra blocks to memory as well */
+ int ext1 = zzip_disk_entry_get_extras(entry);
+ char* R ptr1 = zzip_disk_entry_to_extras(entry);
+ int ext2 = zzip_file_header_get_extras(header);
+ char* R ptr2 = zzip_file_header_to_extras(header);
+
+ if (ext1) {
+ void* mem = malloc (ext1+2);
+ item->zz_ext[1] = mem;
+ memcpy (mem, ptr1, ext1);
+ ((char*)(mem))[ext1+0] = 0;
+ ((char*)(mem))[ext1+1] = 0;
+ }
+ if (ext2) {
+ void* mem = malloc (ext2+2);
+ item->zz_ext[2] = mem;
+ memcpy (mem, ptr2, ext2);
+ ((char*)(mem))[ext2+0] = 0;
+ ((char*)(mem))[ext2+1] = 0;
+ }
+ }
+ { /* override sizes/offsets with zip64 values for largefile support */
+ zzip_extra_zip64* block = (zzip_extra_zip64*)
+ zzip_mem_entry_extra_block (item, ZZIP_EXTRA_zip64);
+ if (block) {
+ item->zz_usize = __zzip_get64(block->z_usize);
+ item->zz_csize = __zzip_get64(block->z_csize);
+ item->zz_offset = __zzip_get64(block->z_offset);
+ item->zz_diskstart = __zzip_get32(block->z_diskstart);
+ }
+ }
+ /* NOTE:
+ * All information from the central directory entry is now in memory.
+ * Effectivly that allows us to modify it and write it back to disk.
+ */
+ return item; ____;____;
+}
+
+/* find an extra block for the given datatype code.
+ * We assume that the central directory has been preparsed to memory.
+ */
+ZZIP_EXTRA_BLOCK*
+zzip_mem_entry_extra_block (ZZIP_MEM_ENTRY* entry, short datatype)
+{
+ int i = 2;
+ while (1) {
+ ZZIP_EXTRA_BLOCK* ext = entry->zz_ext[i];
+ if (ext) {
+ while (*(short*)(ext->z_datatype)) {
+ if (datatype == zzip_extra_block_get_datatype (ext)) {
+ return ext;
+ }
+ ___ char* e = (char*) ext;
+ e += zzip_extra_block_headerlength;
+ e += zzip_extra_block_get_datasize (ext);
+ ext = (void*) e; ____;
+ }
+ }
+ if (! i) return 0;
+ i--;
+ }
+}
+
+void
+zzip_mem_entry_free(ZZIP_MEM_ENTRY* _zzip_restrict item)
+{
+ if (item) {
+ if (item->zz_ext[0]) free (item->zz_ext[0]);
+ if (item->zz_ext[1]) free (item->zz_ext[1]);
+ if (item->zz_ext[2]) free (item->zz_ext[2]);
+ if (item->zz_comment) free (item->zz_comment);
+ if (item->zz_name) free (item->zz_name);
+ free (item);
+ }
+}
+
+void
+zzip_mem_disk_unload(ZZIP_MEM_DISK* dir)
+{
+ ZZIP_MEM_ENTRY* item = dir->list;
+ while (item) {
+ ZZIP_MEM_ENTRY* next = item->zz_next;
+ zzip_mem_entry_free(item); item = next;
+ }
+ dir->list = dir->last = 0; dir->disk = 0;
+}
+
+void
+zzip_mem_disk_close(ZZIP_MEM_DISK* _zzip_restrict dir)
+{
+ if (dir) {
+ zzip_mem_disk_unload (dir);
+ zzip_disk_close(dir->disk);
+ free (dir);
+ }
+}
+
+#if 0
+static void foo (short zz_datatype) {
+ switch (zz_datatype) {
+ case 0x0001: /* ZIP64 extended information extra field */
+ case 0x0007: /* AV Info */
+ case 0x0008: /* Reserved for future Unicode file name data (PFS) */
+ case 0x0009: /* OS/2 */
+ case 0x000a: /* NTFS */
+ case 0x000c: /* OpenVMS */
+ case 0x000d: /* Unix */
+ case 0x000e: /* Reserved for file stream and fork descriptors */
+ case 0x000f: /* Patch Descriptor */
+ case 0x0014: /* PKCS#7 Store for X.509 Certificates */
+ case 0x0015: /* X.509 Certificate ID and Signature for file */
+ case 0x0016: /* X.509 Certificate ID for Central Directory */
+ case 0x0017: /* Strong Encryption Header */
+ case 0x0018: /* Record Management Controls */
+ case 0x0019: /* PKCS#7 Encryption Recipient Certificate List */
+ case 0x0065: /* IBM S/390, AS/400 attributes - uncompressed */
+ case 0x0066: /* Reserved for IBM S/390, AS/400 attr - compressed */
+ case 0x07c8: /* Macintosh */
+ case 0x2605: /* ZipIt Macintosh */
+ case 0x2705: /* ZipIt Macintosh 1.3.5+ */
+ case 0x2805: /* ZipIt Macintosh 1.3.5+ */
+ case 0x334d: /* Info-ZIP Macintosh */
+ case 0x4341: /* Acorn/SparkFS */
+ case 0x4453: /* Windows NT security descriptor (binary ACL) */
+ case 0x4704: /* VM/CMS */
+ case 0x470f: /* MVS */
+ case 0x4b46: /* FWKCS MD5 (see below) */
+ case 0x4c41: /* OS/2 access control list (text ACL) */
+ case 0x4d49: /* Info-ZIP OpenVMS */
+ case 0x4f4c: /* Xceed original location extra field */
+ case 0x5356: /* AOS/VS (ACL) */
+ case 0x5455: /* extended timestamp */
+ case 0x554e: /* Xceed unicode extra field */
+ case 0x5855: /* Info-ZIP Unix (original, also OS/2, NT, etc) */
+ case 0x6542: /* BeOS/BeBox */
+ case 0x756e: /* ASi Unix */
+ case 0x7855: /* Info-ZIP Unix (new) */
+ case 0xfd4a: /* SMS/QDOS */
+ }
+}
+#endif
+
+ZZIP_MEM_ENTRY*
+zzip_mem_disk_findfile(ZZIP_MEM_DISK* dir,
+ char* filename, ZZIP_MEM_ENTRY* after,
+ zzip_strcmp_fn_t compare)
+{
+ ZZIP_MEM_ENTRY* entry = (! after ? dir->list : after->zz_next);
+ if (! compare) compare = (zzip_strcmp_fn_t) (strcmp);
+ for (; entry ; entry = entry->zz_next) {
+ if (! compare (filename, entry->zz_name)) {
+ return entry;
+ }
+ }
+ return 0;
+}
+
+ZZIP_MEM_ENTRY*
+zzip_mem_disk_findmatch(ZZIP_MEM_DISK* dir,
+ char* filespec, ZZIP_MEM_ENTRY* after,
+ zzip_fnmatch_fn_t compare, int flags)
+{
+ ZZIP_MEM_ENTRY* entry = (! after ? dir->list : after->zz_next);
+ if (! compare) compare = (zzip_fnmatch_fn_t) _zzip_fnmatch;
+ for (; entry ; entry = entry->zz_next) {
+ if (! compare (filespec, entry->zz_name, flags)) {
+ return entry;
+ }
+ }
+ return 0;
+}
+
+zzip__new__ ZZIP_MEM_DISK_FILE*
+zzip_mem_entry_fopen (ZZIP_MEM_DISK* dir, ZZIP_MEM_ENTRY* entry)
+{
+ /* keep this in sync with zzip_disk_entry_fopen */
+ ZZIP_DISK_FILE* file = malloc(sizeof(ZZIP_MEM_DISK_FILE));
+ if (! file) return file;
+ file->buffer = dir->disk->buffer;
+ file->endbuf = dir->disk->endbuf;
+ file->avail = zzip_mem_entry_usize (entry);
+
+ if (! file->avail || zzip_mem_entry_data_stored (entry))
+ { file->stored = zzip_mem_entry_to_data (entry); return file; }
+
+ file->stored = 0;
+ file->zlib.opaque = 0;
+ file->zlib.zalloc = Z_NULL;
+ file->zlib.zfree = Z_NULL;
+ file->zlib.avail_in = zzip_mem_entry_csize (entry);
+ file->zlib.next_in = zzip_mem_entry_to_data (entry);
+
+ if (! zzip_mem_entry_data_deflated (entry) ||
+ inflateInit2 (& file->zlib, -MAX_WBITS) != Z_OK)
+ { free (file); return 0; }
+
+ return file;
+}
+
+zzip__new__ ZZIP_MEM_DISK_FILE*
+zzip_mem_disk_fopen (ZZIP_MEM_DISK* dir, char* filename)
+{
+ ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfile (dir, filename, 0, 0);
+ if (! entry) return 0; else return zzip_mem_entry_fopen (dir, entry);
+}
+_zzip_size_t
+zzip_mem_disk_fread (void* ptr, _zzip_size_t size, _zzip_size_t nmemb,
+ ZZIP_MEM_DISK_FILE* file)
+{
+ return zzip_disk_fread (ptr, size, nmemb, file);
+}
+
+int
+zzip_mem_disk_fclose (ZZIP_MEM_DISK_FILE* file)
+{
+ return zzip_disk_fclose (file);
+}
+
+int
+zzip_mem_disk_feof (ZZIP_MEM_DISK_FILE* file)
+{
+ return zzip_disk_feof (file);
+}
+
+/* convert dostime of entry to unix time_t */
+long zzip_disk_entry_get_mktime(ZZIP_DISK_ENTRY* entry)
+{
+ uint16_t dostime = ZZIP_GET16 (entry->z_dostime.time);
+ uint16_t dosdate = ZZIP_GET16 (entry->z_dostime.date);
+ struct tm date;
+ date.tm_sec = (dostime) & 0x1F; /* bits 0..4 */
+ date.tm_min = (dostime >> 5) & 0x3F; /* bits 5..10 */
+ date.tm_hour = (dostime >> 11); /* bits 11..15 */
+ date.tm_mday = (dosdate) & 0x1F; /* bits 16..20 */
+ date.tm_mon = (dosdate >> 5) & 0xF; /* bits 21..24 */
+ date.tm_year = (dosdate >> 9) + 80; /* bits 25..31 */
+ return mktime (&date); /* well, unix has that function... */
+}
diff --git a/Build/source/libs/zziplib/zzip/memdisk.h b/Build/source/libs/zziplib/zzip/memdisk.h
new file mode 100644
index 00000000000..4403282f730
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/memdisk.h
@@ -0,0 +1,162 @@
+#ifndef __ZZIP_MEMDISK_H
+#define __ZZIP_MEMDISK_H
+
+/* NOTE: this is part of libzzipmmapped (i.e. it is not libzzip). */
+
+#include <zzip/types.h>
+#include <zzip/mmapped.h>
+
+typedef struct _zzip_mem_disk ZZIP_MEM_DISK;
+typedef struct _zzip_mem_entry ZZIP_MEM_ENTRY;
+
+struct _zzip_mem_disk {
+ ZZIP_DISK* disk;
+ ZZIP_MEM_ENTRY* list;
+ ZZIP_MEM_ENTRY* last;
+};
+
+#ifndef zzip_mem_disk_extern
+#define zzip_mem_disk_extern
+#endif
+
+zzip_mem_disk_extern zzip__new__ ZZIP_MEM_DISK*
+zzip_mem_disk_new (void);
+zzip_mem_disk_extern zzip__new__ ZZIP_MEM_DISK*
+zzip_mem_disk_open (char* filename);
+zzip_mem_disk_extern zzip__new__ ZZIP_MEM_DISK*
+zzip_mem_disk_fdopen (int fd);
+zzip_mem_disk_extern void
+zzip_mem_disk_close (ZZIP_MEM_DISK* _zzip_restrict dir);
+
+zzip_mem_disk_extern long
+zzip_mem_disk_load (ZZIP_MEM_DISK* dir, ZZIP_DISK* disk);
+zzip_mem_disk_extern void
+zzip_mem_disk_unload (ZZIP_MEM_DISK* dir);
+ZZIP_EXTRA_BLOCK*
+zzip_mem_entry_extra_block (ZZIP_MEM_ENTRY* entry, short datatype);
+
+#ifdef USE_INLINE
+_zzip_inline ZZIP_DISK* zzip_disk (ZZIP_MEM_DISK* dir) { return dir->disk; }
+#else
+#define zzip_disk(_X_) ((_X_)->disk)
+#endif
+
+
+/* these functions are much faster than the orgiinal zzip_disk_ functions */
+
+/* zzip_mem_entry <is similar to> zzip_disk_entry */
+struct _zzip_mem_entry {
+ struct _zzip_mem_entry* zz_next;
+ char* zz_name; /* zero-terminated (from "filename") */
+ zzip_byte_t* zz_data; /* compressed content start (mmap addr) */
+ int zz_flags; /* (from "z_flags") */
+ int zz_compr; /* (from "z_compr") */
+ long zz_mktime; /* (from "z_dostime") */
+ long zz_crc32; /* (from "z_crc32") */
+ zzip_off_t zz_csize; /* (from "z_csize") overridden by zip64 */
+ zzip_off_t zz_usize; /* (from "z_usize") overridden by zip64 */
+ zzip_off_t zz_offset; /* (from "z_offset") overridden by zip64 */
+ int zz_diskstart; /* (from "z_diskstart") rridden by zip64 */
+ int zz_filetype; /* (from "z_filetype") */
+ char* zz_comment; /* zero-terminated (from "comment") */
+ ZZIP_EXTRA_BLOCK* zz_ext[3]; /* terminated by null in z_datatype */
+}; /* the extra blocks are NOT converted */
+
+#define _zzip_mem_disk_findfirst(_d_) ((_d_)->list)
+#define _zzip_mem_disk_findnext(_d_,_e_) (!(_e_)?(_d_)->list:(_e_)->zz_next)
+#define _zzip_mem_entry_findnext(_e_) ((_e_)->zz_next)
+
+#ifndef USE_INLINE
+#define zzip_mem_disk_findfirst _zzip_mem_disk_findfirst
+#define zzip_mem_disk_findnext _zzip_mem_disk_findnext
+#define zzip_mem_entry_findnext _zzip_mem_entry_findnext
+#else
+
+_zzip_inline ZZIP_MEM_ENTRY*
+zzip_mem_disk_findfirst(ZZIP_MEM_DISK* dir) {
+ if (! dir) return 0;
+ return _zzip_mem_disk_findfirst(dir); }
+_zzip_inline ZZIP_MEM_ENTRY*
+zzip_mem_disk_findnext(ZZIP_MEM_DISK* dir, ZZIP_MEM_ENTRY* entry) {
+ if (! dir) return 0;
+ return _zzip_mem_disk_findnext(dir, entry); }
+_zzip_inline ZZIP_MEM_ENTRY*
+zzip_mem_entry_findnext(ZZIP_MEM_ENTRY* entry) {
+ if (! entry) return 0;
+ return _zzip_mem_entry_findnext(entry); }
+#endif
+
+#define _zzip_mem_entry_to_name(_e_) ((_e_)->zz_name)
+#define _zzip_mem_entry_to_comment(_e_) ((_e_)->zz_comment)
+#define _zzip_mem_entry_strdup_name(_e_) (strdup((_e_)->zz_name))
+#define _zzip_mem_entry_to_data(_e_) ((_e_)->zz_data)
+
+#ifndef USE_INLINE
+#define zzip_mem_entry_to_name _zzip_mem_entry_to_name
+#define zzip_mem_entry_to_comment _zzip_mem_entry_to_comment
+#define zzip_mem_entry_strdup_name _zzip_mem_entry_strdup_name
+#define zzip_mem_entry_to_data _zzip_mem_entry_to_data
+#else
+_zzip_inline char*
+zzip_mem_entry_to_name(ZZIP_MEM_ENTRY* entry) {
+ if (! entry) return 0;
+ return _zzip_mem_entry_to_name(entry); }
+_zzip_inline char*
+zzip_mem_entry_to_comment(ZZIP_MEM_ENTRY* entry) {
+ if (! entry) return 0;
+ return _zzip_mem_entry_to_comment(entry); }
+zzip__new__
+_zzip_inline char*
+zzip_mem_entry_strdup_name(ZZIP_MEM_ENTRY* entry) {
+ if (! entry) return 0;
+ return _zzip_mem_entry_strdup_name(entry); }
+_zzip_inline zzip_byte_t*
+zzip_mem_entry_to_data(ZZIP_MEM_ENTRY* entry) {
+ if (! entry) return 0;
+ return _zzip_mem_entry_to_data(entry); }
+#endif
+
+ZZIP_MEM_ENTRY*
+zzip_mem_disk_findfile(ZZIP_MEM_DISK* dir,
+ char* filename, ZZIP_MEM_ENTRY* after,
+ zzip_strcmp_fn_t compare);
+
+ZZIP_MEM_ENTRY*
+zzip_mem_disk_findmatch(ZZIP_MEM_DISK* dir,
+ char* filespec, ZZIP_MEM_ENTRY* after,
+ zzip_fnmatch_fn_t compare, int flags);
+
+/* named access -------------------------------------------------------- */
+#define zzip_mem_entry_usize(_e_) ((_e_)->zz_usize)
+#define zzip_mem_entry_csize(_e_) ((_e_)->zz_csize)
+#define zzip_mem_entry_data_encrypted(_e_) ZZIP_IS_ENCRYPTED((_e_)->zz_flags)
+#define zzip_mem_entry_data_streamed(_e_) ZZIP_IS_STREAMED((_e_)->zz_flags)
+#define zzip_mem_entry_data_comprlevel(_e_) ((_e_)->zz_compr)
+#define zzip_mem_entry_data_stored(_e_) ((_e_)->zz_compr == ZZIP_IS_STORED)
+#define zzip_mem_entry_data_deflated(_e_) ((_e_)->zz_compr == ZZIP_IS_DEFLATED)
+
+/* zzip_mem_disk_file -------------------------------------------------- */
+
+/* since only the header data is being cached, all the real data
+ * operations are actually the same as in mmapped.h - just fopen makes
+ * access to the header data in memory instead of the zip archive.
+ */
+
+typedef ZZIP_DISK_FILE ZZIP_MEM_DISK_FILE;
+
+zzip__new__ ZZIP_MEM_DISK_FILE*
+zzip_mem_entry_fopen (ZZIP_MEM_DISK* dir, ZZIP_MEM_ENTRY* entry);
+zzip__new__ ZZIP_MEM_DISK_FILE*
+zzip_mem_disk_fopen (ZZIP_MEM_DISK* dir, char* filename);
+_zzip_size_t
+zzip_mem_disk_fread (void* ptr, _zzip_size_t size, _zzip_size_t nmemb,
+ ZZIP_MEM_DISK_FILE* file);
+int
+zzip_mem_disk_fclose (ZZIP_MEM_DISK_FILE* file);
+int
+zzip_mem_disk_feof (ZZIP_MEM_DISK_FILE* file);
+
+/* convert dostime of entry to unix time_t */
+long zzip_disk_entry_get_mktime(ZZIP_DISK_ENTRY* entry);
+
+#endif
diff --git a/Build/source/libs/zziplib/zzip/mmapped.c b/Build/source/libs/zziplib/zzip/mmapped.c
new file mode 100644
index 00000000000..a3a4a46d922
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/mmapped.c
@@ -0,0 +1,565 @@
+/*
+ * NOTE: this is part of libzzipmmapped (i.e. it is not libzzip).
+ *
+ * These routines are fully independent from the traditional zzip
+ * implementation. They assume a readonly mmapped sharedmem block
+ * representing a complete zip file. The functions show how to
+ * parse the structure, find files and return a decoded bytestream.
+ *
+ * These routines are a bit simple and really here for documenting
+ * the way to access a zip file. The complexity of zip access comes
+ * from staggered reading of bytes and reposition of a filepointer in
+ * a big archive with lots of files and long compressed datastreams.
+ * Plus varaints of drop-in stdio replacements, obfuscation routines,
+ * auto fileextensions, drop-in dirent replacements, and so on...
+ *
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 2003,2004 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#ifdef __linux__
+#define _GNU_SOURCE _glibc_developers_are_idiots_to_call_this_gnu_specific_
+#endif
+
+#define _ZZIP_DISK_FILE_STRUCT 1
+
+#include <zzip/types.h>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#if defined ZZIP_HAVE_UNISTD_H
+#include <unistd.h>
+#elif defined ZZIP_HAVE_IO_H
+#include <io.h>
+#endif
+
+#if defined ZZIP_HAVE_STRING_H
+#include <string.h>
+#elif defined ZZIP_HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#include <zlib.h>
+#include <zzip/mmapped.h>
+#include <zzip/format.h>
+#include <zzip/fetch.h>
+#include <zzip/__mmap.h>
+#include <zzip/__fnmatch.h>
+
+#if __STDC_VERSION__+0 > 199900L
+#define ___
+#define ____
+#else
+#define ___ {
+#define ____ }
+#endif
+
+/** => zzip_disk_mmap
+ * This function does primary initialization of a disk-buffer struct.
+ */
+int
+zzip_disk_init(ZZIP_DISK* disk, void* buffer, zzip_size_t buflen)
+{
+ disk->buffer = (zzip_byte_t*) buffer;
+ disk->endbuf = (zzip_byte_t*) buffer + buflen;
+ disk->reserved = 0;
+ disk->flags = 0;
+ disk->mapped = 0;
+ /* do not touch disk->user */
+ /* do not touch disk->code */
+ return 0;
+}
+
+/** => zzip_disk_mmap
+ * This function allocates a new disk-buffer with => malloc(3)
+ */
+zzip__new__ ZZIP_DISK*
+zzip_disk_new(void)
+{
+ ZZIP_DISK* disk = malloc(sizeof(disk));
+ if (! disk) return disk;
+ zzip_disk_init (disk, 0, 0);
+ return disk;
+}
+
+/** turn a filehandle into a mmapped zip disk archive handle
+ *
+ * This function uses the given file-descriptor to detect the length of the
+ * file and calls the system => mmap(2) to put it in main memory. If it is
+ * successful then a newly allocated ZZIP_DISK* is returned with
+ * disk->buffer pointing to the mapview of the zipdisk content.
+ */
+zzip__new__ ZZIP_DISK*
+zzip_disk_mmap(int fd)
+{
+ struct stat st;
+ if (fstat (fd, &st) || !st.st_size) return 0;
+ ___ ZZIP_DISK* disk = zzip_disk_new (); if (! disk) return 0;
+ disk->buffer = _zzip_mmap (& zzip->mapped, fd, 0, st.st_size);
+ if (disk->buffer == MAP_FAILED) { free (disk); return 0; }
+ disk->endbuf = disk->buffer + st.st_size;
+ return disk; ____;
+}
+
+/** => zzip_disk_mmap
+ * This function is the inverse of => zzip_disk_mmap and using the system
+ * munmap(2) on the buffer area and => free(3) on the ZZIP_DISK structure.
+ */
+int
+zzip_disk_munmap(ZZIP_DISK* disk)
+{
+ if (! disk) return 0;
+ _zzip_munmap (disk->mapped, disk->buffer, disk->endbuf-disk->buffer);
+ free (disk);
+ return 0;
+}
+
+/** => zzip_disk_mmap
+ *
+ * This function opens the given archive by name and turn the filehandle
+ * to => zzip_disk_mmap for bringing it to main memory. If it can not
+ * be => mmap(2)'ed then we slurp the whole file into a newly => malloc(2)'ed
+ * memory block. Only if that fails too then we return null. Since handling
+ * of disk->buffer is ambigous it should not be snatched away please.
+ */
+ZZIP_DISK* zzip__new__
+zzip_disk_open(char* filename)
+{
+# ifndef O_BINARY
+# define O_BINARY 0
+# endif
+ struct stat st;
+ if (stat (filename, &st) || !st.st_size) return 0;
+ ___ int fd = open (filename, O_RDONLY|O_BINARY);
+ if (fd <= 0) return 0;
+ ___ ZZIP_DISK* disk = zzip_disk_mmap (fd);
+ if (disk) return disk;
+ ___ zzip_byte_t* buffer = malloc (st.st_size);
+ if (! buffer) return 0;
+ if ((st.st_size == read (fd, buffer, st.st_size)) &&
+ (disk = zzip_disk_new ()))
+ {
+ disk->buffer = buffer;
+ disk->endbuf = buffer+st.st_size;
+ disk->mapped = -1;
+ }else free (buffer);
+ return disk; ____;____;____;
+}
+
+/** => zzip_disk_mmap
+ *
+ * This function will release all data needed to access a (mmapped)
+ * zip archive, including any malloc()ed blocks, sharedmem mappings
+ * and it dumps the handle struct as well.
+ */
+int
+zzip_disk_close(ZZIP_DISK* disk)
+{
+ if (! disk) return 0;
+ if (disk->mapped != -1) return zzip_disk_munmap (disk);
+ free (disk->buffer);
+ free (disk);
+ return 0;
+}
+
+/* ====================================================================== */
+/* helper functions */
+
+#ifdef ZZIP_HAVE_STRNDUP
+#define _zzip_strndup strndup
+#else
+/* if your system does not have strndup: */
+zzip__new__ static char* _zzip_strndup(char* p, int maxlen)
+{
+ if (! p) return 0;
+ ___ zzip_byte_t* r = malloc (maxlen+1);
+ if (! r) return r;
+ strncpy (r, p, maxlen);
+ r[maxlen] = '\0';
+ return r; ____;
+}
+#endif
+
+#if defined ZZIP_HAVE_STRCASECMP || defined strcasecmp
+#define _zzip_strcasecmp strcasecmp
+#else
+/* if your system does not have strcasecmp: */
+static int _zzip_strcasecmp(char* __zzip_restrict a, char* _zzip_restrict b)
+{
+ if (! a) return (b) ? 1 : 0;
+ if (! b) return -1;
+ while (1)
+ {
+ int v = tolower(*a) - tolower(*b);
+ if (v) return v;
+ if (! *a) return 1;
+ if (! *b) return -1;
+ a++; b++;
+ }
+}
+#endif
+
+/** helper functions for (mmapped) zip access api
+ *
+ * This function augments the other zzip_disk_entry_* helpers: here we move
+ * a disk_entry pointer (as returned by _find* functions) into a pointer to
+ * the data block right after the file_header. Only disk->buffer would be
+ * needed to perform the seek but we check the mmapped range end as well.
+ */
+zzip_byte_t*
+zzip_disk_entry_to_data(ZZIP_DISK* disk, struct zzip_disk_entry* entry)
+{
+ struct zzip_file_header* file =
+ zzip_disk_entry_to_file_header(disk, entry);
+ if (file) return zzip_file_header_to_data (file);
+ return 0;
+}
+
+/** => zzip_disk_entry_to_data
+ * This function does half the job of => zzip_disk_entry_to_data where it
+ * can augment with => zzip_file_header_to_data helper from format/fetch.h
+ */
+struct zzip_file_header*
+zzip_disk_entry_to_file_header(ZZIP_DISK* disk, struct zzip_disk_entry* entry)
+{
+ zzip_byte_t* file_header = /* (struct zzip_file_header*) */
+ (disk->buffer + zzip_disk_entry_fileoffset (entry));
+ if (disk->buffer > file_header || file_header >= disk->endbuf)
+ return 0;
+ return (struct zzip_file_header*) file_header;
+}
+
+/** => zzip_disk_entry_to_data
+ * This function is a big helper despite its little name: in a zip file the
+ * encoded filenames are usually NOT zero-terminated but for common usage
+ * with libc we need it that way. Secondly, the filename SHOULD be present
+ * in the zip central directory but if not then we fallback to the filename
+ * given in the file_header of each compressed data portion.
+ */
+zzip__new__ char*
+zzip_disk_entry_strdup_name(ZZIP_DISK* disk, struct zzip_disk_entry* entry)
+{
+ if (! disk || ! entry) return 0;
+
+ ___ char* name; zzip_size_t len;
+ struct zzip_file_header* file;
+ if ((len = zzip_disk_entry_namlen (entry)))
+ name = zzip_disk_entry_to_filename (entry);
+ else if ((file = zzip_disk_entry_to_file_header (disk, entry)) &&
+ (len = zzip_file_header_namlen (file)))
+ name = zzip_file_header_to_filename (file);
+ else
+ return 0;
+
+ if ((zzip_byte_t*) name < disk->buffer ||
+ (zzip_byte_t*) name+len > disk->endbuf)
+ return 0;
+
+ return _zzip_strndup (name, len); ____;
+}
+
+/** => zzip_disk_entry_to_data
+ * This function is similar creating a reference to a zero terminated
+ * string but it can only exist in the zip central directory entry.
+ */
+zzip__new__ char*
+zzip_disk_entry_strdup_comment(ZZIP_DISK* disk, struct zzip_disk_entry* entry)
+{
+ if (! disk || ! entry) return 0;
+
+ ___ char* text; zzip_size_t len;
+ if ((len = zzip_disk_entry_comment (entry)))
+ text = zzip_disk_entry_to_comment (entry);
+ else
+ return 0;
+
+ if ((zzip_byte_t*) text < disk->buffer ||
+ (zzip_byte_t*) text+len > disk->endbuf)
+ return 0;
+
+ return _zzip_strndup (text, len); ____;
+}
+
+/* ====================================================================== */
+
+/** => zzip_disk_findfile
+ *
+ * This function is the first call of all the zip access functions here.
+ * It contains the code to find the first entry of the zip central directory.
+ * Here we require the mmapped block to represent a real zip file where the
+ * disk_trailer is _last_ in the file area, so that its position would be at
+ * a fixed offset from the end of the file area if not for the comment field
+ * allowed to be of variable length (which needs us to do a little search
+ * for the disk_tailer). However, in this simple implementation we disregard
+ * any disk_trailer info telling about multidisk archives, so we just return
+ * a pointer to the zip central directory.
+ *
+ * For an actual means, we are going to search backwards from the end
+ * of the mmaped block looking for the PK-magic signature of a
+ * disk_trailer. If we see one then we check the rootseek value to
+ * find the first disk_entry of the root central directory. If we find
+ * the correct PK-magic signature of a disk_entry over there then we
+ * assume we are done and we are going to return a pointer to that label.
+ *
+ * The return value is a pointer to the first zzip_disk_entry being checked
+ * to be within the bounds of the file area specified by the arguments. If
+ * no disk_trailer was found then null is returned, and likewise we only
+ * accept a disk_trailer with a seekvalue that points to a disk_entry and
+ * both parts have valid PK-magic parts. Beyond some sanity check we try to
+ * catch a common brokeness with zip archives that still allows us to find
+ * the start of the zip central directory.
+ */
+struct zzip_disk_entry*
+zzip_disk_findfirst(ZZIP_DISK* disk)
+{
+ if (disk->buffer > disk->endbuf-sizeof(struct zzip_disk_trailer))
+ return 0;
+ ___ zzip_byte_t* p = disk->endbuf-sizeof(struct zzip_disk_trailer);
+ for (; p >= disk->buffer ; p--)
+ {
+ zzip_byte_t* root; /* (struct zzip_disk_entry*) */
+ if (zzip_disk_trailer_check_magic(p)) {
+ root = disk->buffer + zzip_disk_trailer_get_rootseek (
+ (struct zzip_disk_trailer*)p);
+ if (root > p)
+ { /* the first disk_entry is after the disk_trailer? can't be! */
+ zzip_size_t rootsize = zzip_disk_trailer_get_rootsize (
+ (struct zzip_disk_trailer*)p);
+ if (disk->buffer+rootsize > p) continue;
+ /* a common brokeness that can be fixed: we just assume the
+ * central directory was written directly before the trailer:*/
+ root = p - rootsize;
+ }
+ } else if (zzip_disk64_trailer_check_magic(p)) {
+ if (sizeof(void*) < 8) return 0; /* EOVERFLOW */
+ root = disk->buffer + zzip_disk64_trailer_get_rootseek (
+ (struct zzip_disk64_trailer*)p);
+ if (root > p) continue;
+ } else continue;
+
+ if (root < disk->buffer) continue;
+ if (zzip_disk_entry_check_magic(root))
+ return (struct zzip_disk_entry*) root;
+ }____;
+ return 0;
+}
+
+/** => zzip_disk_findfile
+ *
+ * This function takes an existing disk_entry in the central root directory
+ * (e.g. from zzip_disk_findfirst) and returns the next entry within in
+ * the given bounds of the mmapped file area.
+ */
+struct zzip_disk_entry*
+zzip_disk_findnext(ZZIP_DISK* disk, struct zzip_disk_entry* entry)
+{
+ if ((zzip_byte_t*)entry < disk->buffer ||
+ (zzip_byte_t*)entry > disk->endbuf-sizeof(entry) ||
+ ! zzip_disk_entry_check_magic (entry) ||
+ zzip_disk_entry_sizeto_end (entry) > 64*1024)
+ return 0;
+ entry = zzip_disk_entry_to_next_entry (entry);
+ if ((zzip_byte_t*)entry > disk->endbuf-sizeof(entry) ||
+ ! zzip_disk_entry_check_magic (entry) ||
+ zzip_disk_entry_sizeto_end (entry) > 64*1024 ||
+ zzip_disk_entry_skipto_end (entry) + sizeof(entry) > disk->endbuf)
+ return 0;
+ else
+ return entry;
+}
+
+/** search for files in the (mmapped) zip central directory
+ *
+ * This function is given a filename as an additional argument, to find the
+ * disk_entry matching a given filename. The compare-function is usually
+ * strcmp or strcasecmp or perhaps strcoll, if null then strcmp is used.
+ * - use null as argument for "after"-entry when searching the first
+ * matching entry, otherwise the last returned value if you look for other
+ * entries with a special "compare" function (if null then a doubled search
+ * is rather useless with this variant of _findfile).
+ */
+struct zzip_disk_entry*
+zzip_disk_findfile(ZZIP_DISK* disk, char* filename,
+ struct zzip_disk_entry* after, zzip_strcmp_fn_t compare)
+{
+ struct zzip_disk_entry* entry = (! after ? zzip_disk_findfirst (disk)
+ : zzip_disk_findnext (disk, after));
+ if (! compare)
+ compare = (zzip_strcmp_fn_t)( (disk->flags&1) ?
+ (_zzip_strcasecmp) : (strcmp));
+ for (; entry ; entry = zzip_disk_findnext (disk, entry))
+ {
+ /* filenames within zip files are often not null-terminated! */
+ char* realname = zzip_disk_entry_strdup_name (disk, entry);
+ if (realname && ! compare(filename, realname))
+ {
+ free (realname);
+ return entry;
+ }
+ free (realname);
+ }
+ return 0;
+}
+
+/** => zzip_disk_findfile
+ *
+ * This function uses a compare-function with an additional argument
+ * and it is called just like fnmatch(3) from POSIX.2 AD:1993), i.e.
+ * the argument filespec first and the ziplocal filename second with
+ * the integer-flags put in as third to the indirect call. If the
+ * platform has fnmatch available then null-compare will use that one
+ * and otherwise we fall back to mere strcmp, so if you need fnmatch
+ * searching then please provide an implementation somewhere else.
+ * - use null as argument for "after"-entry when searching the first
+ * matching entry, or the last disk_entry return-value to find the
+ * next entry matching the given filespec.
+ */
+struct zzip_disk_entry*
+zzip_disk_findmatch(ZZIP_DISK* disk, char* filespec,
+ struct zzip_disk_entry* after,
+ zzip_fnmatch_fn_t compare, int flags)
+{
+ struct zzip_disk_entry* entry = (! after ? zzip_disk_findfirst (disk)
+ : zzip_disk_findnext (disk, after));
+ if (! compare) {
+ compare = (zzip_fnmatch_fn_t) _zzip_fnmatch;
+ if (disk->flags&1) disk->flags |= _zzip_fnmatch_CASEFOLD;
+ }
+ for (; entry ; entry = zzip_disk_findnext (disk, entry))
+ {
+ /* filenames within zip files are often not null-terminated! */
+ char* realname = zzip_disk_entry_strdup_name(disk, entry);
+ if (realname && ! compare(filespec, realname, flags))
+ {
+ free (realname);
+ return entry;
+ }
+ free (realname);
+ }
+ return 0;
+}
+
+/* ====================================================================== */
+
+/** => zzip_disk_fopen
+ *
+ * the ZZIP_DISK_FILE* is rather simple in just encapsulating the
+ * arguments given to this function plus a zlib deflate buffer.
+ * Note that the ZZIP_DISK pointer does already contain the full
+ * mmapped file area of a zip disk, so open()ing a file part within
+ * that area happens to be a lookup of its bounds and encoding. That
+ * information is memorized on the ZZIP_DISK_FILE so that subsequent
+ * _read() operations will be able to get the next data portion or
+ * return an eof condition for that file part wrapped in the zip archive.
+ */
+zzip__new__ ZZIP_DISK_FILE*
+zzip_disk_entry_fopen (ZZIP_DISK* disk, ZZIP_DISK_ENTRY* entry)
+{
+ /* keep this in sync with zzip_mem_entry_fopen */
+ struct zzip_file_header* header =
+ zzip_disk_entry_to_file_header (disk, entry);
+ if (! header) return 0;
+ ___ ZZIP_DISK_FILE* file = malloc(sizeof(ZZIP_DISK_FILE));
+ if (! file) return file;
+ file->buffer = disk->buffer;
+ file->endbuf = disk->endbuf;
+ file->avail = zzip_file_header_usize (header);
+
+ if (! file->avail || zzip_file_header_data_stored (header))
+ { file->stored = zzip_file_header_to_data (header); return file; }
+
+ file->stored = 0;
+ file->zlib.opaque = 0;
+ file->zlib.zalloc = Z_NULL;
+ file->zlib.zfree = Z_NULL;
+ file->zlib.avail_in = zzip_file_header_csize (header);
+ file->zlib.next_in = zzip_file_header_to_data (header);
+
+ if (! zzip_file_header_data_deflated (header) ||
+ inflateInit2 (& file->zlib, -MAX_WBITS) != Z_OK)
+ { free (file); return 0; }
+
+ return file; ____;
+}
+
+/** openening a file part wrapped within a (mmapped) zip archive
+ *
+ * This function opens a file found by name, so it does a search into
+ * the zip central directory with => zzip_disk_findfile and whatever
+ * is found first is given to => zzip_disk_entry_fopen
+ */
+zzip__new__ ZZIP_DISK_FILE*
+zzip_disk_fopen (ZZIP_DISK* disk, char* filename)
+{
+ ZZIP_DISK_ENTRY* entry = zzip_disk_findfile (disk, filename, 0, 0);
+ if (! entry) return 0; else return zzip_disk_entry_fopen (disk, entry);
+}
+
+
+/** => zzip_disk_fopen
+ *
+ * This function reads more bytes into the output buffer specified as
+ * arguments. The return value is null on eof or error, the stdio-like
+ * interface can not distinguish between these so you need to check
+ * with => zzip_disk_feof for the difference.
+ */
+zzip_size_t
+zzip_disk_fread (void* ptr, zzip_size_t sized, zzip_size_t nmemb,
+ ZZIP_DISK_FILE* file)
+{
+ zzip_size_t size = sized*nmemb;
+ if (size > file->avail) size = file->avail;
+ if (file->stored)
+ {
+ memcpy (ptr, file->stored, size);
+ file->stored += size;
+ file->avail -= size;
+ return size;
+ }
+
+ file->zlib.avail_out = sized*nmemb;
+ file->zlib.next_out = ptr;
+ ___ zzip_size_t total_old = file->zlib.total_out;
+ ___ int err = inflate (& file->zlib, Z_NO_FLUSH);
+ if (err == Z_STREAM_END)
+ file->avail = 0;
+ else if (err == Z_OK)
+ file->avail -= file->zlib.total_out - total_old;
+ else
+ return 0;
+ return file->zlib.total_out - total_old;
+ ____;____;
+}
+
+/** => zzip_disk_fopen
+ * This function releases any zlib decoder info needed for decompression
+ * and dumps the ZZIP_DISK_FILE* then.
+ */
+int
+zzip_disk_fclose (ZZIP_DISK_FILE* file)
+{
+ if (! file->stored)
+ inflateEnd (& file->zlib);
+ free (file);
+ return 0;
+}
+
+/** => zzip_disk_fopen
+ *
+ * This function allows to distinguish an error from an eof condition.
+ * Actually, if we found an error but we did already reach eof then we
+ * just keep on saying that it was an eof, so the app can just continue.
+ */
+int
+zzip_disk_feof (ZZIP_DISK_FILE* file)
+{
+ return ! file || ! file->avail;
+}
diff --git a/Build/source/libs/zziplib/zzip/mmapped.h b/Build/source/libs/zziplib/zzip/mmapped.h
new file mode 100644
index 00000000000..5f434544800
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/mmapped.h
@@ -0,0 +1,120 @@
+#ifndef _ZZIP_MMAPPED_H_
+#define _ZZIP_MMAPPED_H_
+/*
+ * NOTE: this is part of libzzipmmapped (i.e. it is not libzzip).
+ *
+ * simplified zip disk access using a mmapping of the whole archive.
+ *
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 2003,2004 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+
+#include <zzip/types.h>
+
+typedef struct zzip_disk_file ZZIP_DISK_FILE;
+typedef struct zzip_disk ZZIP_DISK;
+/* def struct zzip_disk_entry ZZIP_DISK_ENTRY; */
+
+/* we expose this structure so third party applications can augment
+ * on them. The mmapped zip access usually just needs the two pointers
+ * specifying the mmapped area, whereever you have that from.
+ */
+struct zzip_disk
+{
+ zzip_byte_t* buffer; /* start of mmapped area, the base of all seekvals */
+ zzip_byte_t* endbuf; /* end of mmapped area, i.e. buffer + buflen */
+ void* reserved; /* - for later extensions (might be renamed) */
+ void* user; /* - free for applications (use this!) */
+ long flags; /* bit 0: findfile searches case-insensitive */
+ long mapped; /* used for mmap() wrappers of zzip/__mmap.h */
+ long unused; /* - for later extensions (might be renamed) */
+ long code; /* - free for applications (use this!) */
+};
+
+typedef int (*zzip_strcmp_fn_t)(char*, char*);
+typedef int (*zzip_fnmatch_fn_t)(char*, char*, int);
+
+#define zzip_disk_extern extern
+
+zzip_disk_extern int
+zzip_disk_init(ZZIP_DISK* disk, void* buffer, zzip_size_t buflen);
+
+zzip_disk_extern zzip__new__ ZZIP_DISK*
+zzip_disk_new(void);
+
+zzip_disk_extern zzip__new__ ZZIP_DISK*
+zzip_disk_mmap(int fd);
+
+zzip_disk_extern int
+zzip_disk_munmap(ZZIP_DISK* disk);
+
+zzip_disk_extern zzip__new__ ZZIP_DISK*
+zzip_disk_open(char* filename);
+
+zzip_disk_extern int
+zzip_disk_close(ZZIP_DISK* disk);
+
+
+zzip_disk_extern ZZIP_DISK_ENTRY*
+zzip_disk_findfirst(ZZIP_DISK* disk);
+
+zzip_disk_extern ZZIP_DISK_ENTRY*
+zzip_disk_findnext(ZZIP_DISK* disk, ZZIP_DISK_ENTRY* entry);
+
+zzip_disk_extern zzip__new__ char*
+zzip_disk_entry_strdup_name(ZZIP_DISK* disk, ZZIP_DISK_ENTRY* entry);
+zzip_disk_extern zzip__new__ char*
+zzip_disk_entry_strdup_comment(ZZIP_DISK* disk, ZZIP_DISK_ENTRY* entry);
+zzip_disk_extern struct zzip_file_header*
+zzip_disk_entry_to_file_header(ZZIP_DISK* disk, ZZIP_DISK_ENTRY* entry);
+zzip_disk_extern zzip_byte_t*
+zzip_disk_entry_to_data(ZZIP_DISK* disk, ZZIP_DISK_ENTRY* entry);
+
+zzip_disk_extern ZZIP_DISK_ENTRY*
+zzip_disk_findfile(ZZIP_DISK* disk,
+ char* filename, ZZIP_DISK_ENTRY* after,
+ zzip_strcmp_fn_t compare);
+zzip_disk_extern ZZIP_DISK_ENTRY*
+zzip_disk_findmatch(ZZIP_DISK* disk,
+ char* filespec, ZZIP_DISK_ENTRY* after,
+ zzip_fnmatch_fn_t compare, int flags);
+
+
+zzip_disk_extern zzip__new__ ZZIP_DISK_FILE*
+zzip_disk_entry_fopen (ZZIP_DISK* disk, ZZIP_DISK_ENTRY* entry);
+
+zzip_disk_extern zzip__new__ ZZIP_DISK_FILE*
+zzip_disk_fopen (ZZIP_DISK* disk, char* filename);
+
+zzip_disk_extern _zzip_size_t
+zzip_disk_fread (void* ptr, _zzip_size_t size, _zzip_size_t nmemb,
+ ZZIP_DISK_FILE* file);
+zzip_disk_extern int
+zzip_disk_fclose (ZZIP_DISK_FILE* file);
+int
+zzip_disk_feof (ZZIP_DISK_FILE* file);
+
+#ifdef _ZZIP_DISK_FILE_STRUCT
+/**
+ * typedef struct zzip_disk_file ZZIP_DISK_FILE;
+ */
+struct zzip_disk_file
+{
+ zzip_byte_t* buffer; /* fopen disk->buffer */
+ zzip_byte_t* endbuf; /* fopen disk->endbuf */
+ zzip_size_t avail; /* memorized for checks on EOF */
+ z_stream zlib; /* for inflated blocks */
+ zzip_byte_t* stored; /* for stored blocks */
+};
+#endif
+
+#endif
+
diff --git a/Build/source/libs/zziplib/zzip/plugin.c b/Build/source/libs/zziplib/zzip/plugin.c
new file mode 100644
index 00000000000..ad17adb6486
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/plugin.c
@@ -0,0 +1,84 @@
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ * Mike Nordell <tamlin-@-algonet-se>
+ *
+ * Copyright (c) 2002,2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#include <zzip/lib.h>
+#include <zzip/plugin.h>
+
+#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+#include <zzip/file.h>
+#include <zzip/format.h>
+
+zzip_off_t
+zzip_filesize(int fd)
+{
+ struct stat st;
+
+ if (fstat(fd, &st) < 0)
+ return -1;
+
+# if defined DEBUG && ! defined _WIN32
+ if (! st.st_size && st.st_blocks > 1) /* seen on some darwin 10.1 machines */
+ fprintf(stderr, "broken fstat(2) ?? st_size=%ld st_blocks=%ld\n",
+ (long) st.st_size, (long) st.st_blocks);
+# endif
+
+ return st.st_size;
+}
+
+static const struct zzip_plugin_io default_io =
+{
+ &open,
+ &close,
+ &_zzip_read,
+ &_zzip_lseek,
+ &zzip_filesize,
+ 1, 1,
+ &_zzip_write
+};
+
+/** => zzip_init_io
+ * This function returns a zzip_plugin_io_t handle to static defaults
+ * wrapping the posix io file functions for actual file access.
+ */
+zzip_plugin_io_t
+zzip_get_default_io()
+{
+ return (zzip_plugin_io_t) &default_io;
+}
+
+/**
+ * This function initializes the users handler struct to default values
+ * being the posix io functions in default configured environments.
+ */
+int zzip_init_io(zzip_plugin_io_handlers_t io, int flags)
+{
+ if (!io) {
+ return ZZIP_ERROR;
+ }
+ memcpy(io, &default_io, sizeof(default_io));
+ io->fd.sys = flags;
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/zzip/plugin.h b/Build/source/libs/zziplib/zzip/plugin.h
new file mode 100644
index 00000000000..b6ccbe8a66f
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/plugin.h
@@ -0,0 +1,96 @@
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 2002,2003 Guido Draheim
+ * All rights reserved
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ *
+ * the interfaces for the plugin_io system
+ *
+ * Using the following you can provide your own file I/O functions to
+ * e.g. read data directly from memory, provide simple
+ * "encryption"/"decryption" of on-disk .zip-files...
+ * Note that this currently only provides a subset of the functionality
+ * in zziplib. It does not attempt to provide any directory functions,
+ * but if your program 1) only uses ordinary on-disk files and you
+ * just want this for file obfuscation, or 2) you only access your
+ * .zip archives using zzip_open & co., this is sufficient.
+ *
+ * Currently the default io are the POSIX functions, except
+ * for 'filesize' that is zziplibs own provided zzip_filesize function,
+ * using standard POSIX fd's. You are however free to replace this with
+ * whatever data type you need, so long as you provide implementations
+ * for all the functions, and the data type fits an int.
+ *
+ * all functions receiving ext_io are able to cope with both arguments
+ * set to zero which will let them default to a ZIP ext and posix io.
+ */
+#ifndef _ZZIP_PLUGIN_H /* zzip-io.h */
+#define _ZZIP_PLUGIN_H 1
+
+#include <zzip/zzip.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* we have renamed zzip_plugin_io.use_mmap to zzip_plugin_io.sys */
+#define ZZIP_PLUGIN_IO_SYS 1
+
+struct zzip_plugin_io { /* use "zzip_plugin_io_handlers" in applications !! */
+ int (*open)(zzip_char_t* name, int flags, ...);
+ int (*close)(int fd);
+ zzip_ssize_t (*read)(int fd, void* buf, zzip_size_t len);
+ zzip_off_t (*seeks)(int fd, zzip_off_t offset, int whence);
+ zzip_off_t (*filesize)(int fd);
+ long sys;
+ long type;
+ zzip_ssize_t (*write)(int fd, _zzip_const void* buf, zzip_size_t len);
+};
+
+typedef union _zzip_plugin_io
+{
+ struct zzip_plugin_io fd;
+ struct { void* padding[8]; } ptr;
+} zzip_plugin_io_handlers;
+
+#define _zzip_plugin_io_handlers zzip_plugin_io_handlers
+/* for backward compatibility, and the following to your application code:
+ * #ifndef _zzip_plugin_io_handlers
+ * #define _zzip_plugin_io_handlers struct zzip_plugin_io
+ */
+typedef zzip_plugin_io_handlers* zzip_plugin_io_handlers_t;
+
+#ifdef ZZIP_LARGEFILE_RENAME
+#define zzip_filesize zzip_filesize64
+#define zzip_get_default_io zzip_get_default_io64
+#define zzip_init_io zzip_init_io64
+#endif
+
+_zzip_export zzip_off_t
+zzip_filesize(int fd);
+
+/* get the default file I/O functions */
+_zzip_export zzip_plugin_io_t zzip_get_default_io(void);
+
+/*
+ * Initializes a zzip_plugin_io_t to the zziplib default io.
+ * This is useful if you only want to override e.g. the 'read' function.
+ * all zzip functions that can receive a zzip_plugin_io_t can
+ * handle a zero pointer in that place and default to posix io.
+ */
+_zzip_export
+int zzip_init_io(zzip_plugin_io_handlers_t io, int flags);
+
+/* zzip_init_io flags : */
+# define ZZIP_IO_USE_MMAP 1
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/Build/source/libs/zziplib/zzip/stat.c b/Build/source/libs/zziplib/zzip/stat.c
new file mode 100644
index 00000000000..0395c67b60a
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/stat.c
@@ -0,0 +1,119 @@
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ * Tomi Ollila <Tomi.Ollila@iki.fi>
+ *
+ * Copyright (c) 1999,2000,2001,2002 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ *
+ * Description:
+ * although this file is defining a function called zzip_stat it
+ * will not need a real stat(2) exported by the Operating System.
+ * It will just try to fill the fields of the ZZIP_STAT structure
+ * of
+ */
+
+#include <zzip/lib.h> /* exported...*/
+#include <zzip/file.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#define ZZIP_USE_INTERNAL
+#include <zzip/info.h>
+
+/**
+ * obtain information about a filename in an opened zip-archive without
+ * opening that file first. Mostly used to obtain the uncompressed
+ * size of a file inside a zip-archive. see => zzip_dir_open.
+ */
+int
+zzip_dir_stat(ZZIP_DIR * dir, zzip_char_t* name, ZZIP_STAT * zs, int flags)
+{
+ struct zzip_dir_hdr * hdr = dir->hdr0;
+ int (*cmp)(zzip_char_t*, zzip_char_t*);
+
+ cmp = (flags & ZZIP_CASEINSENSITIVE) ? strcasecmp : strcmp;
+
+ if (flags & ZZIP_IGNOREPATH)
+ {
+ char* n = strrchr(name, '/');
+ if (n) name = n + 1;
+ }
+
+ if (hdr)
+ while (1)
+ {
+ register char* hdr_name = hdr->d_name;
+ if (flags & ZZIP_IGNOREPATH)
+ {
+ register char* n = strrchr(hdr_name, '/');
+ if (n) hdr_name = n + 1;
+ }
+
+ if (! cmp(hdr_name, name))
+ break;
+
+ if (! hdr->d_reclen)
+ {
+ dir->errcode = ZZIP_ENOENT;
+ return -1;
+ }
+
+ hdr = (struct zzip_dir_hdr *) ((char *)hdr + hdr->d_reclen);
+ }
+
+ zs->d_compr = hdr->d_compr;
+ zs->d_csize = hdr->d_csize;
+ zs->st_size = hdr->d_usize;
+ zs->d_name = hdr->d_name;
+
+ return 0;
+}
+
+/** => zzip_dir_stat
+ * This function will obtain information about a opened file _within_ a
+ * zip-archive. The file is supposed to be open (otherwise -1 is returned).
+ * The st_size stat-member contains the uncompressed size. The optional
+ * d_name is never set here.
+ */
+int zzip_file_stat (ZZIP_FILE* file, ZZIP_STAT* zs)
+{
+ if (! file) return -1;
+ zs->d_compr = file->method;
+ zs->d_csize = file->csize;
+ zs->st_size = file->usize;
+ zs->d_name = 0;
+ return 0;
+}
+
+/** => zzip_dir_stat
+ * This function will obtain information about a opened file which may be
+ * either real/zipped. The file is supposed to be open (otherwise -1 is
+ * returned). The st_size stat-member contains the uncompressed size.
+ * The optional d_name is never set here. For a real file, we do set the
+ * d_csize := st_size and d_compr := 0 for meaningful defaults.
+ */
+int zzip_fstat (ZZIP_FILE* file, ZZIP_STAT* zs)
+{
+ if (ZZIP_file_real(file))
+ {
+ struct stat st;
+ if (fstat (file->fd, &st) < 0) return -1;
+ zs->st_size = st.st_size;
+ zs->d_csize = st.st_size;
+ zs->d_compr = 0;
+ return 0;
+ }else{
+ return zzip_file_stat (file, zs);
+ }
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/zzip/stdint.h b/Build/source/libs/zziplib/zzip/stdint.h
new file mode 100644
index 00000000000..4552c5b04e0
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/stdint.h
@@ -0,0 +1,45 @@
+#ifndef _ZZIP__STDINT_H /* zzip-stdint.h */
+#define _ZZIP__STDINT_H 1
+/* this file ensures that we have some kind of typedef declarations for
+ unsigned C9X typedefs. The ISO C 9X: 7.18 Integer types file is stdint.h
+ */
+
+#include <zzip/conf.h>
+
+/* enforce use of ifdef'd C9X entries in system headers */
+#define __USE_ANSI 1
+#define __USE_ISOC9X 1
+
+#ifdef ZZIP_HAVE_STDINT_H
+ /* ISO C 9X: 7.18 Integer types <stdint.h> */
+#include <stdint.h>
+#elif defined ZZIP_HAVE_SYS_INT_TYPES_H /*solaris*/
+#include <sys/int_types.h>
+#elif defined ZZIP_HAVE_INTTYPES_H /*freebsd*/
+#include <inttypes.h>
+#else
+ typedef unsigned char uint8_t; typedef signed char int8_t;
+
+# if ZZIP_SIZEOF_INT && ZZIP_SIZEOF_INT == 2
+ typedef unsigned int uint16_t; typedef signed int int16_t;
+# elif ZZIP_SIZEOF_SHORT && ZZIP_SIZEOF_SHORT == 2
+ typedef unsigned short uint16_t; typedef signed short int16_t;
+# else
+# error unable to typedef int16_t from either int or short
+ typedef unsigned short uint16_t; typedef signed short int16_t;
+# endif
+
+# if defined ZZIP_SIZEOF_INT && ZZIP_SIZEOF_INT == 4
+ typedef unsigned int uint32_t; typedef signed int int32_t;
+# elif defined ZZIP_SIZEOF_LONG && ZZIP_SIZEOF_LONG == 4
+ typedef unsigned long uint32_t; typedef signed long int32_t;
+# else
+# error unable to typedef int32_t from either int or long
+ typedef unsigned long uint32_t; typedef signed long int32_t;
+# endif
+
+typedef unsigned _zzip___int64 uint64_t; typedef _zzip___int64 int64_t;
+#endif
+
+#endif /*_ZZIP_STDINT_H*/
+
diff --git a/Build/source/libs/zziplib/zzip/types.h b/Build/source/libs/zziplib/zzip/types.h
new file mode 100644
index 00000000000..c20f128daa8
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/types.h
@@ -0,0 +1,51 @@
+/*
+ * unlike in <zzip/conf.h> we are allowed to make up typedefs here,
+ * while over there only #defines are allowed
+ *
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 2003,2004 Guido Draheim
+ * All rights reserved,
+ * usage allowed under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ *
+ * if you see "unknown symbol" errors, check first that `-I ..` is part of
+ * your compiler options - a special hint to VC/IDE users who tend to make up
+ * their own workspace files. All includes look like #include <zzip|*.h>, so
+ * you need to add an include path to the dir containing (!!) the ./zzip/ dir
+ */
+
+#ifndef _ZZIP_TYPES_H_
+#define _ZZIP_TYPES_H_
+
+#include <zzip/conf.h>
+#include <fcntl.h>
+#include <stddef.h> /* size_t and friends */
+#ifdef ZZIP_HAVE_SYS_TYPES_H
+#include <sys/types.h> /* bsd (mac) has size_t here */
+#endif
+/* msvc6 has neither ssize_t (we assume "int") nor off_t (assume "long") */
+
+typedef unsigned char zzip_byte_t; // especially zlib decoding data
+
+typedef _zzip_off64_t zzip_off64_t;
+typedef _zzip_off_t zzip_off_t;
+typedef _zzip_size_t zzip_size_t;
+typedef _zzip_ssize_t zzip_ssize_t;
+
+/* in <zzip/format.h> */
+typedef struct zzip_disk64_trailer ZZIP_DISK64_TRAILER;
+typedef struct zzip_disk_trailer ZZIP_DISK_TRAILER;
+typedef struct zzip_file_trailer ZZIP_FILE_TRAILER;
+typedef struct zzip_root_dirent ZZIP_ROOT_DIRENT;
+typedef struct zzip_file_header ZZIP_FILE_HEADER;
+typedef struct zzip_disk_entry ZZIP_DISK_ENTRY;
+typedef struct zzip_extra_block ZZIP_EXTRA_BLOCK;
+
+
+
+#endif
+
diff --git a/Build/source/libs/zziplib/zzip/write.c b/Build/source/libs/zziplib/zzip/write.c
new file mode 100644
index 00000000000..36637ddbcc9
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/write.c
@@ -0,0 +1,461 @@
+/*
+ * The write-support in zziplib is not a full-flegded interface to the
+ * internals that zip file-header or zip archive an contain. It's
+ * primary use goes for savegames or transfer `pack-n-go` archives
+ * where time-stamps are rather unimportant. Here we can create an
+ * archive with filenames and their data portions, possibly obfuscated.
+ *
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#define _ZZIP_WRITE_SOURCE
+
+#if defined DDDD || defined DDDDD || defined DDDDDD || defined DDDDDDD
+#define _ZZIP_ENABLE_WRITE
+#else /* per default, we add support for passthrough to posix write */
+#define _ZZIP_POSIX_WRITE
+#endif
+
+#include <zzip/lib.h> /* exported...*/
+#include <zzip/file.h>
+
+#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#ifdef ZZIP_HAVE_DIRECT_H
+#include <direct.h>
+#endif
+
+#include <zzip/format.h>
+#include <zzip/plugin.h>
+#include <zzip/__debug.h>
+
+#define ___ {
+#define ____ }
+
+#ifndef EROFS
+# ifdef ENOSYS
+#define EROFS ENOSYS
+# else
+#define EROFS EPERM
+#endif
+#endif
+
+/* try real zlib routines for writing ? very experimental, very very ex... */
+#ifndef _ZZIP_ENABLE_WRITE
+#define _ZZIP_TRY 0
+#else
+#define _ZZIP_TRY 1
+#endif
+
+/* btw, is there any system that did define those different ? get away.. */
+# ifndef S_IWGRP
+# define S_IWGRP 00020
+# endif
+# ifndef S_IRWXO
+# define S_IRWXO 00007
+# endif
+
+# ifdef ZZIP_HAVE_DIRECT_H
+# define _mkdir(a,b) mkdir(a)
+# else
+# define _mkdir mkdir
+# endif
+
+/** create a new zip archive for writing
+ *
+ * This function will create a new zip archive. The returned parameter
+ * is a new "zzip dir" handle that should be saved to a variable so it
+ * can be used a base argument for => zzip_mkdir and => zzip_creat calls.
+ * The returned handle represents a zip central directory that must be
+ * saved to disk using => zzip_closedir.
+ *
+ * Returns null on error and sets errno. Remember, according to posix
+ * the => creat(2) call is equivalent to
+ open (path, O_WRONLY | O_CREAT | O_TRUNC, o_mode)
+ * so any previous zip-archive will be overwritten unconditionally and
+ * EEXIST errors from => mkdir(2) are suppressed. (fixme: delete the
+ * given subtree? like suggested by O_TRUNC? not done so far!)
+ */
+ZZIP_DIR*
+zzip_dir_creat(zzip_char_t* name, int o_mode)
+{
+ return zzip_dir_creat_ext_io (name, o_mode, 0, 0);
+}
+
+/** => zzip_dir_creat
+ *
+ * If the third argument "ext" has another special meaning here, as it
+ * is used to ensure that a given zip-file is created with the first entry
+ * of the ext-list appended as an extension unless the file-path already
+ * ends with a file-extension registered in the list. Therefore {"",0}
+ * matches all files and creates them as zip-archives under the given
+ * nonmodified name. (Some magic here? If the path ends in the path
+ * separator then make a real directory even in the presence of ext-list?)
+ *
+ * This function is not yet implemented, check for #def ZZIP_NO_CREAT
+ * Write-support will extend => zzip_closedir with semantics to finalize the
+ * zip-archive by writing the zip-trailer and closing the archive file.
+ */
+ZZIP_DIR*
+zzip_dir_creat_ext_io(zzip_char_t* name, int o_mode,
+ zzip_strings_t* ext, zzip_plugin_io_t io)
+{
+ if (! io) io = zzip_get_default_io ();
+
+ if (io != zzip_get_default_io())
+ { /* the current io-structure does not contain a "write" entry,
+ * and therefore this parameter is useless. Anyone to expect
+ * some behavior should be warned, so here we let the function
+ * fail bluntly - and leaving the recovery to the application
+ */
+ errno = EINVAL;
+ return 0;
+ }
+
+
+ if (!_ZZIP_TRY)
+ { /* not implemented - however, we respect that a null argument to
+ * zzip_mkdir and zzip_creat works, so we silently still do the mkdir
+ */
+ if (! _mkdir (name, o_mode) || errno == EEXIST)
+ errno = EROFS;
+ return 0;
+ } else {
+# define MAX_EXT_LEN 10
+ ZZIP_DIR* dir = zzip_dir_alloc (ext);
+ int name_len = strlen(name);
+ dir->realname = malloc (name_len+MAX_EXT_LEN);
+ if (! dir->realname) goto error;
+
+ memcpy (dir->realname, name, name_len+1);
+ ___ int fd = __zzip_try_open (
+ dir->realname, O_EXCL|O_TRUNC|O_WRONLY, ext, io);
+ if (fd != -1) { dir->fd = fd; return dir; }
+
+ ___ zzip_strings_t* exx = ext; int exx_len;
+ for (; *exx ; exx++)
+ {
+ if ((exx_len = strlen (*exx)+1) <= name_len &&
+ !memcmp (dir->realname+(name_len-exx_len), *exx, exx_len))
+ break; /* keep unmodified */
+ exx++; if (*exx) continue;
+
+ if (! (exx_len = strlen (*exx)) || exx_len >= MAX_EXT_LEN) break;
+ memcpy (dir->realname+name_len, exx, exx_len); /* append! */
+ }____;
+ fd = io->fd.open (dir->realname, O_CREAT|O_TRUNC|O_WRONLY, o_mode);
+ dir->realname[name_len] = '\0'; /* keep ummodified */
+ if (fd != -1) { dir->fd = fd; return dir; }
+ error:
+ zzip_dir_free (dir); return 0;
+ ____;
+ }
+}
+
+/** create a new archive area for writing
+ *
+ * This function will create a new archive area. This may either be a
+ * a new zip archive or a new directory in the filesystem. The returned
+ * parameter is a new "zzip dir" handle that should be saved to a variable
+ * so it can be used a base argument for => zzip_file_mkdir and
+ * => zzip_file_creat calls. The returned handle wraps both possibilities,
+ * it can be representing a zip central directory that must be
+ * saved to disk using => zzip_closedir or it is just a handle for the
+ * name of the real directory that still must be run through
+ * => zzip_closedir to release the wrapper around the directory name.
+ *
+ * The magic is pushed through the o_mode argument. Using a mode that
+ * has no group-write bit set (S_IWGRP = 0040) then the file is
+ * created as a zip directory. Note that this is unabridged of any
+ * umask value in the system where the argument to this function could
+ * be 0775 but with an umask of 0755 it turns out as 0755 for a real
+ * directory. Using 0755 directly would not create it as a real directory
+ * but as a zip archive handle.
+ *
+ * This function is not yet implemented, check for #def ZZIP_NO_CREAT
+ * Write-support will extend => zzip_closedir with semantics to finalize the
+ * zip-archive by writing the zip-trailer and closing the archive file.
+ *
+ * Returns null on error and sets errno. Remember, according to posix
+ * the => creat(2) call is equivalent to
+ open (path, O_WRONLY | O_CREAT | O_TRUNC, o_mode)
+ * so any previous zip-archive will be overwritten unconditionally and
+ * EEXIST errors from => mkdir(2) are suppressed. (fixme: delete the
+ * given subtree? like suggested by O_TRUNC? not done so far!)
+ */
+ZZIP_DIR*
+zzip_createdir(zzip_char_t* name, int o_mode)
+{
+ if (o_mode & S_IWGRP)
+ {
+ if (-1 == _mkdir(name, o_mode) && errno != EEXIST) /* fail */
+ return 0;
+ return zzip_opendir (name);
+ } else
+ return zzip_dir_creat (name, o_mode);
+}
+
+/** => zzip_file_creat => mkdir(2), creat(2), zzip_dir_creat
+ *
+ * This function has an additional primary argument over the posix
+ * mkdir(2) - if it is null then this function behaves just like
+ * posix mkdir(2). The zzip_dir argument can be set to the result
+ * of a => zzip_createdir which allows for some magic that the
+ * given directory name is created as an entry in the zip archive.
+ *
+ * If the given dir name argument is not within the basepath of
+ * the zip central directory then a real directory is created.
+ * Any EEXIST errors are not suppressed unlike with => zzip_createdir
+ *
+ * Standard usage accepts a global/threaded/modular ZZIP_DIR pointer
+ * for all zip archive operations like in:
+ ZZIP_DIR* zip = zzip_createdir (sysconfpath, 0755, zip);
+ zzip_file_mkdir (zip, filepath[i], 0755);
+ ZZIP_FILE* file = zzip_file_creat (zip, filename[i], 0644);
+ zzip_write (file, buf, len);
+ zzip_close (file); file = 0;
+ zzip_closedir (zip); zip = 0;
+ *
+ * compare with => zzip_mkdir inline macro which allows to
+ * collapse the examples script to
+ #define zzip_savefile myproject_saveconfig
+ #include <zzip/zzip.h>
+ ZZIP_DIR* zzip_savefile = zzip_createdir (sysconfpath, 0755);
+ zzip_mkdir (filepath[i], 0755);
+ ZZIP_FILE* file = zzip_creat(filepath[i], 0644);
+ zzip_write (file, buf, len);
+ zzip_close (file); file = 0;
+ zzip_closedir (zip_savefile);
+ */
+int
+zzip_file_mkdir(ZZIP_DIR* dir, zzip_char_t* name, int o_mode)
+{
+ if (! dir)
+ return _mkdir(name, o_mode);
+
+ if (!_ZZIP_TRY)
+ {/* not implemented */
+ errno = EROFS;
+ return -1;
+ } else {
+ errno = EROFS;
+ return -1;
+ }
+}
+
+/** start next file entry in a zip archive
+ *
+ * This function will create a new file within a zzip archive, the
+ * one given as the primary argument and additionally to the posix
+ * creat(2) - just like zzip_mkdir has an additional argument over
+ * the posix mkdir(2) spec. For this function the primary parameter
+ * can be null as well thereby creating a real file instead of a new
+ * one inside the zip-archive otherwise given. If the primary parameter is
+ * not null but wraps a real directory then all new files are also real.
+ *
+ * This function is not yet implemented, check for #def ZZIP_NO_CREAT
+ *
+ * Returns NULL on an error setting errno, and opening a file _within_
+ * a zip archive using O_RDONLY (and similar stuff) will surely lead to
+ * an error.
+ */
+ZZIP_FILE*
+zzip_file_creat(ZZIP_DIR* dir, zzip_char_t* name, int o_mode)
+{
+ if (! dir)
+ return zzip_open (name, o_mode);
+
+ if (!_ZZIP_TRY)
+ {/* not implemented */
+ errno = EROFS;
+ return 0;
+ } else {
+ errno = EROFS;
+ return 0;
+ }
+}
+
+/** write to zzip storage also: write(2), zlib(3)
+ *
+ * This function will write data to a file descriptor. If the file
+ * descriptor represents a real file then it will be forwarded to
+ * call posix => write(2) directly. If it is a descriptor for a
+ * file within a zip directory then the data will be "deflated"
+ * using => zlib(3) and appended to the zip archive file.
+ */
+zzip_ssize_t
+zzip_write(ZZIP_FILE* file, const void* ptr, zzip_size_t len)
+{
+ if (zzip_file_real(file))
+ return write (zzip_realfd (file), ptr, len);
+ else
+ return zzip_file_write (file, ptr, len);
+}
+
+/** => zzip_write also: zzip_file_creat
+ *
+ * This function will write data to a file descriptor inside a zip
+ * archive. The data will be "deflated" using => zlib(3) compression
+ * and appended to the end of the zip archive file. Only one file
+ * descriptor may be open per zzip_dir archive handle (fifo-like).
+ *
+ * This function is not yet implemented, check for #def ZZIP_NO_CREAT
+ * It returns immediately -1 and sets errno=EROFS for indication.
+ */
+zzip_ssize_t
+zzip_file_write(ZZIP_FILE* file, const void* ptr, zzip_size_t len)
+{
+ if (!_ZZIP_TRY)
+ {/* not implemented */
+ errno = EROFS;
+ return -1;
+ } else {
+ /* add calls to zlib here... */
+ errno = EROFS;
+ return -1;
+ }
+}
+
+/** => zzip_write
+ * This function is the stdc variant for writing and the arguments
+ * are forwarded to => zzip_write - the return value is floored to
+ * null as for STDC spec but there is no zzip_ferror call so far
+ * for the zziplib (later? is it actually needed?).
+ *
+ * This function is not yet implemented, check for #def ZZIP_NO_CREAT
+ * Write-support extends => zzip_close with semantics to write out a
+ * file-trailer to the zip-archive leaving a name/offset marker in
+ * the (still-open) ZZIP_DIR handle.
+ */
+zzip_size_t
+zzip_fwrite(const void* ptr, zzip_size_t len, zzip_size_t multiply,
+ ZZIP_FILE* file)
+{
+ zzip_ssize_t value = zzip_write (file, ptr, len * multiply);
+ if (value == -1)
+ value = 0;
+ return (zzip_size_t) value;
+}
+
+#if 0 /* pure documentation */
+/** create a zipped file/directory also: zzip_dir_creat, mkdir(2)
+ *
+ * This function creates a directory entry in the default zip-archive.
+ * If you did not specify a "#define zzip_savefile somevar"
+ * then the default zip-archive is null and all directories are
+ * created as real directories in the filesystem. This function is
+ * really a preprocessor macro or preferably an inline function
+ * around => zzip_file_mkdir, there is no such symbol generated
+ * into the library. The prototype is modelled after the posix
+ * => mkdir(2) call.
+ #ifndef zzip_savefile
+ #define zzip_savefile 0
+ #endif
+ #define zzip_mkdir(name,mode) \ -
+ zzip_file_mkdir(zzip_savefile,name,mode)
+ *
+ */
+int inline
+zzip_mkdir(zzip_char_t* name, int o_mode)
+{
+ return zzip_file_creat(zzip_savefile, name, mode);
+}
+#endif
+
+#if 0 /* pure documentation */
+/** => zzip_mkdir also: creat(2), zzip_start
+ *
+ * This function creates a file in the default zip-archive.
+ * If you did not specify a "#define zzip_savefile somevar"
+ * then the default zip-archive is null and all files are created
+ * as real files. This function is really a preprocessor macro
+ * or preferably an inline function around => zzip_file_creat,
+ * there is no such symbol generated into the library. The prototype
+ * is modelled after the posix => creat(2) call.
+ #ifndef zzip_savefile
+ #define zzip_savefile 0
+ #endif
+ #define zzip_creat(name,mode) \ -
+ zzip_file_creat(zzip_savefile,name,mode)
+ */
+ZZIP_FILE* inline
+zzip_creat(zzip_char_t* name, int o_mode)
+{
+ return zzip_file_creat(zzip_savefile, name, mode);
+}
+#endif
+
+
+#if 0 /* pure documentation */
+/** start writing to the magic zzip_savefile also: zzip_creat, zzip_write
+ *
+ * open a zip archive for writing via the magic zzip_savefile macro
+ * variable. The name and mode are given to => zzip_createdir and
+ * the result is stored into => zzip_savefile - if the => zzip_savefile
+ * did already have a zzip_dir handle then it is automatically
+ * finalized with => zzip_sync and the handle closed and the
+ * zzip_savefile variable reused for the new zip archive just started
+ * with this call. - This function is really a preprocessor macro
+ * or preferably an inline function around => zzip_dir_create, there
+ * is no such symbol generated into the library.
+ #ifndef zzip_savefile
+ #define zzip_savefile 0
+ #endif
+ #define zzip_start(name,mode,ext) \ -
+ { if (zzip_savefile) zzip_closedir(zzip_savefile); \ -
+ zzip_savefile = zzip_createdir(name,mode,ext); }
+ * This function returns null on error or a zzip_dir handle on
+ * success. It is perfectly okay to continue with a null in the
+ * zzip_savefile variable since it makes subsequent calls to
+ * => zzip_creat and => zzip_mkdir to run as => creat(2) / => mkdir(2)
+ * on the real filesystem.
+ */
+void inline
+zzip_mkfifo(zzip_char_t* name, int o_mode)
+{
+ if (zzip_savefile) zzip_closedir (zzip_savefile);
+ zzip_savefile = zzip_createdir(name, o_mode);
+}
+#endif
+
+#if 0 /* pure documentation */
+/** => zzip_mkfifo also: zzip_closedir, sync(2)
+ *
+ * finalize a zip archive thereby writing the central directory to
+ * the end of the file. If it was a real directory then we do just
+ * nothing - even that the prototype of the call itself is modelled
+ * to be similar to the posix => sync(2) call. This function is
+ * really a preprocessor macro or preferably an inline function
+ * around => zzip_closedir, there is no such symbol generated
+ * into the library.
+ #ifndef zzip_savefile
+ #define zzip_savefile 0
+ #endif
+ #define zzip_sync(name,mode) \ -
+ { zzip_closedir(zzip_savefile); zzip_savefile = 0; }
+ *
+ */
+void inline
+zzip_sync(void)
+{
+ zzip_closedir (zzip_savefile); zzip_savefile = 0;
+}
+#endif
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/zzip/zip.c b/Build/source/libs/zziplib/zzip/zip.c
new file mode 100644
index 00000000000..5133a11613b
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/zip.c
@@ -0,0 +1,759 @@
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ * Tomi Ollila <too@iki.fi>
+ *
+ * Copyright (c) 1999,2000,2001,2002,2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#include <zzip/lib.h> /* archive handling */
+#include <zzip/file.h>
+#include <zzip/format.h>
+#include <zzip/fetch.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#ifdef ZZIP_HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#include <zzip/__mmap.h>
+#include <zzip/__debug.h>
+
+#define __sizeof(X) ((zzip_ssize_t)(sizeof(X)))
+
+/* per default, we use a little hack to correct bad z_rootseek parts */
+#define ZZIP_CORRECT_ROOTSEEK 1
+
+#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || (__GNUC__ >= 4)
+# ifdef DEBUG
+# warning suppress a warning where the compiler should have optimized instead.
+# endif
+#define _255 254
+#else
+#define _255 255
+#endif
+
+#define ZZIP_DISK64_TRAILER
+
+#ifdef ZZIP_DISK64_TRAILER
+struct _disk_trailer {
+ void* zz_tail;
+ void* zz_for_correct_rootseek; // ZZIP_CORRECT_ROOTSEEK
+ zzip_off64_t zz_entries;
+ zzip_off64_t zz_finalentries;
+ zzip_off64_t zz_rootseek;
+ zzip_off64_t zz_rootsize;
+};
+#define _disk_trailer_entries(__p) ((__p)->zz_entries)
+#define _disk_trailer_localentries(__p) ((__p)->zz_entries)
+#define _disk_trailer_finalentries(__p) ((__p)->zz_entries)
+#define _disk_trailer_rootseek(__p) ((__p)->zz_rootseek)
+#define _disk_trailer_rootsize(__p) ((__p)->zz_rootsize)
+#define _disk_trailer_set_rootseek(__p,__v) ((__p)->rootseek = (__v))
+
+#else
+#define _disk_trailer zzip_disk_trailer
+#define _disk_trailer_entries zzip_disk_trailer_entries
+#define _disk_trailer_localentries zzip_disk_trailer_localentries
+#define _disk_trailer_finalentries zzip_disk_trailer_finalentries
+#define _disk_trailer_rootseek zzip_disk_trailer_rootseek
+#define _disk_trailer_rootsize zzip_disk_trailer_rootsize
+#define _disk_trailer_set_rootseek zzip_disk_trailer_set_rootseek
+#define __zzip_fetch_disk_trailer __zzip_find_disk_trailer
+#endif
+
+/* --------------------------- internals -------------------------------- */
+/* internal functions of zziplib, avoid at all cost, changes w/o warning.
+ * we do export them for debugging purpose and special external tools
+ * which know what they do and which can adapt from version to version
+ */
+
+int __zzip_fetch_disk_trailer( int fd, zzip_off_t filesize,
+ struct _disk_trailer * _zzip_restrict trailer,
+ zzip_plugin_io_t io);
+int __zzip_parse_root_directory( int fd,
+ struct _disk_trailer * trailer,
+ struct zzip_dir_hdr ** hdr_return,
+ zzip_plugin_io_t io);
+
+_zzip_inline char* __zzip_aligned4(char* p);
+
+/* ------------------------ harden routines ------------------------------ */
+
+#ifdef ZZIP_HARDEN
+/*
+ * check for inconsistent values in trailer and prefer lower seek value
+ * - we fix values assuming the root directory was written at the end
+ * and it is just before the zip trailer. Therefore, ...
+ */
+_zzip_inline static void __fixup_rootseek(
+ zzip_off_t offset_of_trailer,
+ struct _disk_trailer* trailer)
+{
+ if ( _disk_trailer_rootseek (trailer) >
+ offset_of_trailer - _disk_trailer_rootsize (trailer) &&
+ offset_of_trailer > _disk_trailer_rootsize (trailer))
+ {
+ register zzip_off_t offset;
+ offset = offset_of_trailer - _disk_trailer_rootsize (trailer);
+ _disk_trailer_set_rootseek (trailer, offset);
+ HINT2("new rootseek=%li", (long) _disk_trailer_rootseek (trailer));
+ }
+}
+#define __correct_rootseek(A,B,C)
+
+#elif defined ZZIP_CORRECT_ROOTSEEK
+/* store the seekvalue of the trailer into the "z_magic" field and with
+ * a 64bit off_t we overwrite z_disk/z_finaldisk as well. If you change
+ * anything in zziplib or dump the trailer structure then watch out that
+ * these are still unused, so that this code may still (ab)use those. */
+#define __fixup_rootseek(_offset_of_trailer, _trailer) \
+ *(zzip_off_t*)_trailer = _offset_of_trailer;
+#define __correct_rootseek( _u_rootseek, _u_rootsize, _trailer) \
+ if (_u_rootseek > *(zzip_off_t*)_trailer - _u_rootsize) \
+ _u_rootseek = *(zzip_off_t*)_trailer - _u_rootsize;
+#else
+#define __fixup_rootseek(A,B)
+#define __correct_rootseek(A,B,C)
+#endif
+
+
+#ifdef DEBUG
+_zzip_inline static void __debug_dir_hdr (struct zzip_dir_hdr* hdr)
+{
+ if (sizeof(struct zzip_dir_hdr) > sizeof(struct zzip_disk_entry))
+ { WARN1("internal sizeof-mismatch may break wreakage"); }
+ /* the internal directory structure is never bigger than the
+ * external zip central directory space had been beforehand
+ * (as long as the following assertion holds...)
+ */
+
+ if (((zzip_off_t)hdr)&3)
+ { NOTE1("this machine's malloc(3) returns sth. not u32-aligned"); }
+ /* we assume that if this machine's malloc has returned a non-aligned
+ * memory block, then it is actually safe to access misaligned data, and
+ * since it does only affect the first hdr it should not even bring about
+ * too much of that cpu's speed penalty
+ */
+}
+#else
+#define __debug_dir_hdr(X)
+#endif
+
+/* -------------------------- low-level interface -------------------------- */
+
+#if defined BUFSIZ
+#if BUFSIZ == 1024 || BUFSIZ == 512 || BUFSIZ == 256
+#define ZZIP_BUFSIZ BUFSIZ
+#endif
+#endif
+
+#ifndef ZZIP_BUFSIZ
+#define ZZIP_BUFSIZ 512
+/* #define ZZIP_BUFSIZ 64 */ /* for testing */
+#endif
+
+/**
+ * This function is used by => zzip_file_open. It tries to find
+ * the zip's central directory info that is usually a few
+ * bytes off the end of the file.
+ */
+int
+__zzip_fetch_disk_trailer(int fd, zzip_off_t filesize,
+ struct _disk_trailer * _zzip_restrict trailer,
+ zzip_plugin_io_t io)
+{
+#ifdef DEBUG
+#define return(val) { e=val; HINT2("%s", zzip_strerror(e)); goto cleanup; }
+#else
+#define return(val) { e=val; goto cleanup; }
+#endif
+ register int e;
+
+#ifndef _LOWSTK
+ auto char buffer[2*ZZIP_BUFSIZ];
+ char* buf = buffer;
+#else
+ char* buf = malloc(2*ZZIP_BUFSIZ);
+#endif
+ zzip_off_t offset = 0;
+ zzip_ssize_t maplen = 0; /* mmap(),read(),getpagesize() use size_t !! */
+ char* fd_map = 0;
+
+ if (!trailer)
+ { return(EINVAL); }
+
+ if (filesize < __sizeof(struct zzip_disk_trailer))
+ { return(ZZIP_DIR_TOO_SHORT); }
+
+ if (!buf)
+ { return(ZZIP_OUTOFMEM); }
+
+ offset = filesize; /* a.k.a. old offset */
+ while(1) /* outer loop */
+ {
+ register unsigned char* mapped;
+
+ if (offset <= 0) { return(ZZIP_DIR_EDH_MISSING); }
+
+ /* trailer cannot be farther away than 64K from fileend */
+ if (filesize-offset > 64*1024)
+ { return(ZZIP_DIR_EDH_MISSING); }
+
+ /* the new offset shall overlap with the area after the old offset! */
+ if (USE_MMAP && io->fd.sys)
+ {
+ zzip_off_t mapoff = offset;
+ {
+ zzip_ssize_t pagesize = _zzip_getpagesize (io->fd.sys);
+ if (pagesize < ZZIP_BUFSIZ) goto non_mmap; /* an error? */
+ if (mapoff == filesize && filesize > pagesize)
+ mapoff -= pagesize;
+ if (mapoff < pagesize) {
+ maplen = (zzip_ssize_t)mapoff + pagesize; mapoff = 0;
+ } else {
+ mapoff -= pagesize; maplen = 2*pagesize;
+ if ((zzip_ssize_t)mapoff & (pagesize-1)) { /*only 1. run */
+ pagesize -= (zzip_ssize_t)mapoff & (pagesize-1);
+ mapoff += pagesize;
+ maplen -= pagesize;
+ }
+ }
+ if (mapoff + maplen > filesize) maplen = filesize - mapoff;
+ }
+
+ fd_map = _zzip_mmap(io->fd.sys, fd, mapoff, (zzip_size_t)maplen);
+ if (fd_map == MAP_FAILED) goto non_mmap;
+ mapped = (unsigned char*) fd_map; offset = mapoff; /* success */
+ HINT3("mapped *%p len=%li", fd_map, (long) maplen);
+ } else {
+ non_mmap:
+ fd_map = 0; /* have no mmap */
+ {
+ zzip_off_t pagesize = ZZIP_BUFSIZ;
+ if (offset == filesize && filesize > pagesize)
+ offset -= pagesize;
+ if (offset < pagesize) {
+ maplen = (zzip_ssize_t)offset + pagesize; offset = 0;
+ } else {
+ offset -= pagesize; maplen = 2*pagesize;
+ if ((zzip_ssize_t)offset & (pagesize-1)) { /*on 1st run*/
+ pagesize -= (zzip_ssize_t)offset & (pagesize-1);
+ offset += pagesize;
+ maplen -= pagesize;
+ }
+ }
+ if (offset + maplen > filesize) maplen = filesize - offset;
+ }
+
+ if (io->fd.seeks(fd, offset, SEEK_SET) < 0)
+ { return(ZZIP_DIR_SEEK); }
+ if (io->fd.read(fd, buf, (zzip_size_t)maplen) < maplen)
+ { return(ZZIP_DIR_READ); }
+ mapped = (unsigned char*) buf; /* success */
+ HINT5("offs=$%lx len=%li filesize=%li pagesize=%i",
+ (long)offset, (long)maplen, (long)filesize, ZZIP_BUFSIZ);
+ }
+
+ {/* now, check for the trailer-magic, hopefully near the end of file */
+ register unsigned char* end = mapped + maplen;
+ register unsigned char* tail;
+ for (tail = end-1; (tail >= mapped); tail--)
+ {
+ if ((*tail == 'P') && /* quick pre-check for trailer magic */
+ end-tail >= __sizeof(struct zzip_disk_trailer)-2 &&
+ zzip_disk_trailer_check_magic(tail))
+ {
+# ifndef ZZIP_DISK64_TRAILER
+ /* if the file-comment is not present, it happens
+ that the z_comment field often isn't either */
+ if (end-tail >= __sizeof(*trailer))
+ {
+ memcpy (trailer, tail, sizeof(*trailer));
+ }else{
+ memcpy (trailer, tail, sizeof(*trailer)-2);
+ trailer->z_comment[0] = 0;
+ trailer->z_comment[1] = 0;
+ }
+# else
+ struct zzip_disk_trailer* orig = (struct zzip_disk_trailer*) tail;
+ trailer->zz_tail = tail;
+ trailer->zz_entries = zzip_disk_trailer_localentries (orig);
+ trailer->zz_finalentries = zzip_disk_trailer_finalentries (orig);
+ trailer->zz_rootseek = zzip_disk_trailer_rootseek (orig);
+ trailer->zz_rootsize = zzip_disk_trailer_rootsize (orig);
+# endif
+
+ __fixup_rootseek (offset + tail-mapped, trailer);
+ { return(0); }
+ } else if ((*tail == 'P') &&
+ end-tail >= __sizeof(struct zzip_disk64_trailer)-2 &&
+ zzip_disk64_trailer_check_magic(tail))
+ {
+# ifndef ZZIP_DISK64_TRAILER
+ return(ZZIP_DIR_LARGEFILE);
+# else
+ struct zzip_disk64_trailer* orig = (struct zzip_disk64_trailer*) tail;
+ trailer->zz_tail = tail;
+ trailer->zz_entries = zzip_disk64_trailer_localentries (orig);
+ trailer->zz_finalentries = zzip_disk64_trailer_finalentries (orig);
+ trailer->zz_rootseek = zzip_disk64_trailer_rootseek (orig);
+ trailer->zz_rootsize = zzip_disk64_trailer_rootsize (orig);
+ { return(0); }
+# endif
+ }
+ }
+ }
+
+ if (USE_MMAP && fd_map)
+ {
+ HINT3("unmap *%p len=%li", fd_map, (long) maplen);
+ _zzip_munmap(io->fd.sys, fd_map, (zzip_size_t)maplen);
+ fd_map = 0;
+ }
+ } /*outer loop*/
+
+ cleanup:
+ if (USE_MMAP && fd_map)
+ {
+ HINT3("unmap *%p len=%li", fd_map, (long) maplen);
+ _zzip_munmap(io->fd.sys, fd_map, (zzip_size_t)maplen);
+ }
+# ifdef _LOWSTK
+ free(buf);
+# endif
+# undef return
+ return e;
+}
+
+/*
+ * making pointer alignments to values that can be handled as structures
+ * is tricky. We assume here that an align(4) is sufficient even for
+ * 64 bit machines. Note that binary operations are not usually allowed
+ * to pointer types but we do need only the lower bits in this implementation,
+ * so we can just cast the value to a long value.
+ */
+_zzip_inline char* __zzip_aligned4(char* p)
+{
+#define aligned4 __zzip_aligned4
+ p += ((long)p)&1; /* warnings about truncation of a "pointer" */
+ p += ((long)p)&2; /* to a "long int" may be safely ignored :) */
+ return p;
+}
+
+/**
+ * This function is used by => zzip_file_open, it is usually called after
+ * => __zzip_find_disk_trailer. It will parse the zip's central directory
+ * information and create a zziplib private directory table in
+ * memory.
+ */
+int
+__zzip_parse_root_directory(int fd,
+ struct _disk_trailer * trailer,
+ struct zzip_dir_hdr ** hdr_return,
+ zzip_plugin_io_t io)
+{
+ auto struct zzip_disk_entry dirent;
+ struct zzip_dir_hdr * hdr;
+ struct zzip_dir_hdr * hdr0;
+ uint16_t * p_reclen = 0;
+ unsigned long entries; /* 32bit is enough */
+ zzip_off64_t zz_offset; /* offset from start of root directory */
+ char* fd_map = 0;
+ zzip_off64_t zz_fd_gap = 0;
+ zzip_off64_t zz_entries = _disk_trailer_localentries (trailer);
+ zzip_off64_t zz_rootsize = _disk_trailer_rootsize (trailer);
+ zzip_off64_t zz_rootseek = _disk_trailer_rootseek (trailer);
+ __correct_rootseek (zz_rootseek, zz_rootsize, trailer);
+
+ hdr0 = (struct zzip_dir_hdr*) malloc(zz_rootsize);
+ if (!hdr0)
+ return ZZIP_DIRSIZE;
+ hdr = hdr0; __debug_dir_hdr (hdr);
+
+ if (USE_MMAP && io->fd.sys)
+ {
+ zz_fd_gap = zz_rootseek & (_zzip_getpagesize(io->fd.sys)-1) ;
+ HINT4(" fd_gap=%ld, mapseek=0x%lx, maplen=%ld", (long)(zz_fd_gap),
+ (long)(zz_rootseek-zz_fd_gap), (long)(zz_rootsize+zz_fd_gap));
+ fd_map = _zzip_mmap(io->fd.sys, fd,
+ zz_rootseek-zz_fd_gap, zz_rootsize+zz_fd_gap);
+ /* if mmap failed we will fallback to seek/read mode */
+ if (fd_map == MAP_FAILED) {
+ NOTE2("map failed: %s",strerror(errno));
+ fd_map=0;
+ }else{
+ HINT3("mapped *%p len=%li", fd_map, (long)(zz_rootsize+zz_fd_gap));
+ }
+ }
+
+ for (entries=zz_entries, zz_offset=0; entries; entries--)
+ {
+ register struct zzip_disk_entry * d;
+ uint16_t u_extras, u_comment, u_namlen;
+
+ if (fd_map)
+ { d = (void*)(fd_map+zz_fd_gap+zz_offset); } /* fd_map+fd_gap==u_rootseek */
+ else
+ {
+ if (io->fd.seeks(fd, zz_rootseek+zz_offset, SEEK_SET) < 0)
+ return ZZIP_DIR_SEEK;
+ if (io->fd.read(fd, &dirent, sizeof(dirent)) < __sizeof(dirent))
+ return ZZIP_DIR_READ;
+ d = &dirent;
+ }
+
+ if ((zzip_off64_t)(zz_offset+sizeof(*d)) > zz_rootsize ||
+ (zzip_off64_t)(zz_offset+sizeof(*d)) < 0)
+ { FAIL4("%li's entry stretches beyond root directory (O:%li R:%li)",
+ (long)entries, (long)(zz_offset), (long)zz_rootsize); break;}
+
+# if 0 && defined DEBUG
+ zzip_debug_xbuf ((unsigned char*) d, sizeof(*d) + 8);
+# endif
+
+ u_extras = zzip_disk_entry_get_extras (d);
+ u_comment = zzip_disk_entry_get_comment (d);
+ u_namlen = zzip_disk_entry_get_namlen (d);
+ HINT5("offset=0x%lx, size %ld, dirent *%p, hdr %p\n",
+ (long)(zz_offset+zz_rootseek), (long)zz_rootsize, d, hdr);
+
+ /* writes over the read buffer, Since the structure where data is
+ copied is smaller than the data in buffer this can be done.
+ It is important that the order of setting the fields is considered
+ when filling the structure, so that some data is not trashed in
+ first structure read.
+ at the end the whole copied list of structures is copied into
+ newly allocated buffer */
+ hdr->d_crc32 = zzip_disk_entry_get_crc32 (d);
+ hdr->d_csize = zzip_disk_entry_get_csize (d);
+ hdr->d_usize = zzip_disk_entry_get_usize (d);
+ hdr->d_off = zzip_disk_entry_get_offset (d);
+ hdr->d_compr = zzip_disk_entry_get_compr (d);
+ if (hdr->d_compr > _255) hdr->d_compr = 255;
+
+ if ((zzip_off64_t)(zz_offset+sizeof(*d) + u_namlen) > zz_rootsize ||
+ (zzip_off64_t)(zz_offset+sizeof(*d) + u_namlen) < 0)
+ { FAIL4("%li's name stretches beyond root directory (O:%li N:%li)",
+ (long)entries, (long)(zz_offset), (long)(u_namlen)); break; }
+
+ if (fd_map)
+ { memcpy(hdr->d_name, fd_map+zz_fd_gap + zz_offset+sizeof(*d), u_namlen); }
+ else { io->fd.read(fd, hdr->d_name, u_namlen); }
+ hdr->d_name[u_namlen] = '\0';
+ hdr->d_namlen = u_namlen;
+
+ /* update offset by the total length of this entry -> next entry */
+ zz_offset += sizeof(*d) + u_namlen + u_extras + u_comment;
+
+ if (zz_offset > zz_rootsize)
+ { FAIL3("%li's entry stretches beyond root directory (O:%li)",
+ (long)entries, (long)(zz_offset)); entries--; break; }
+
+ HINT5("file %ld { compr=%d crc32=$%x offset=%d",
+ (long)entries, hdr->d_compr, hdr->d_crc32, hdr->d_off);
+ HINT5("csize=%d usize=%d namlen=%d extras=%d",
+ hdr->d_csize, hdr->d_usize, u_namlen, u_extras);
+ HINT5("comment=%d name='%s' %s <sizeof %d> } ",
+ u_comment, hdr->d_name, "",(int) sizeof(*d));
+
+ p_reclen = &hdr->d_reclen;
+
+ { register char* p = (char*) hdr;
+ register char* q = aligned4 (p + sizeof(*hdr) + u_namlen + 1);
+ *p_reclen = (uint16_t)(q - p);
+ hdr = (struct zzip_dir_hdr*) q;
+ }
+ }/*for*/
+
+ if (USE_MMAP && fd_map)
+ {
+ HINT3("unmap *%p len=%li", fd_map, (long)(zz_rootsize+zz_fd_gap));
+ _zzip_munmap(io->fd.sys, fd_map, zz_rootsize+zz_fd_gap);
+ }
+
+ if (p_reclen)
+ {
+ *p_reclen = 0; /* mark end of list */
+
+ if (hdr_return)
+ *hdr_return = hdr0;
+ } /* else zero (sane) entries */
+ return (entries ? ZZIP_CORRUPTED : 0);
+}
+
+/* ------------------------- high-level interface ------------------------- */
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static zzip_strings_t* zzip_get_default_ext(void)
+{
+ static zzip_strings_t ext [] =
+ {
+ ".zip", ".ZIP", /* common extension */
+# ifdef ZZIP_USE_ZIPLIKES
+ ".pk3", ".PK3", /* ID Software's Quake3 zipfiles */
+ ".jar", ".JAR", /* Java zipfiles */
+# endif
+ 0
+ };
+
+ return ext;
+}
+
+/**
+ * allocate a new ZZIP_DIR handle and do basic
+ * initializations before usage by => zzip_dir_fdopen
+ * => zzip_dir_open => zzip_file_open or through
+ * => zzip_open
+ * (ext==null flags uses { ".zip" , ".ZIP" } )
+ * (io ==null flags use of posix io defaults)
+ */
+ZZIP_DIR*
+zzip_dir_alloc_ext_io (zzip_strings_t* ext, const zzip_plugin_io_t io)
+{
+ ZZIP_DIR* dir;
+ if ((dir = (ZZIP_DIR *)calloc(1, sizeof(*dir))) == NULL)
+ return 0;
+
+ /* dir->fileext is currently unused - so what, still initialize it */
+ dir->fileext = ext ? ext : zzip_get_default_ext();
+ dir->io = io ? io : zzip_get_default_io ();
+ return dir;
+}
+
+/** => zzip_dir_alloc_ext_io
+ * this function is obsolete - it was generally used for implementation
+ * and exported to let other code build on it. It is now advised to
+ * use => zzip_dir_alloc_ext_io now on explicitly, just set that second
+ * argument to zero to achieve the same functionality as the old style.
+ */
+ZZIP_DIR*
+zzip_dir_alloc (zzip_strings_t* fileext)
+{
+ return zzip_dir_alloc_ext_io (fileext, 0);
+}
+
+/**
+ * will free the zzip_dir handle unless there are still
+ * zzip_files attached (that may use its cache buffer).
+ * This is the inverse of => zzip_dir_alloc , and both
+ * are helper functions used implicitly in other zzipcalls
+ * e.g. => zzip_dir_close = zzip_close
+ *
+ * returns zero on sucess
+ * returns the refcount when files are attached.
+ */
+int
+zzip_dir_free(ZZIP_DIR * dir)
+{
+ if (dir->refcount)
+ return (dir->refcount); /* still open files attached */
+
+ if (dir->fd >= 0) dir->io->fd.close(dir->fd);
+ if (dir->hdr0) free(dir->hdr0);
+ if (dir->cache.fp) free(dir->cache.fp);
+ if (dir->cache.buf32k) free(dir->cache.buf32k);
+ if (dir->realname) free(dir->realname);
+ free(dir);
+ return 0;
+}
+
+/** => zzip_dir_free
+ * It will also => free(2) the => ZZIP_DIR-handle given.
+ * the counterpart for => zzip_dir_open
+ * see also => zzip_dir_free
+ */
+int
+zzip_dir_close(ZZIP_DIR * dir)
+{
+ dir->refcount &=~ 0x10000000; /* explicit dir close */
+ return zzip_dir_free(dir);
+}
+
+/**
+ * used by the => zzip_dir_open and zzip_opendir(2) call. Opens the
+ * zip-archive as specified with the fd which points to an
+ * already openend file. This function then search and parse
+ * the zip's central directory.
+ *
+ * NOTE: refcount is zero, so an _open/_close pair will also delete
+ * this _dirhandle
+ */
+ZZIP_DIR *
+zzip_dir_fdopen(int fd, zzip_error_t * errcode_p)
+{
+ return zzip_dir_fdopen_ext_io(fd, errcode_p, 0, 0);
+}
+
+static zzip_error_t __zzip_dir_parse (ZZIP_DIR* dir); /* forward */
+
+/** => zzip_dir_fdopen
+ * this function uses explicit ext and io instead of the internal
+ * defaults, setting these to zero is equivalent to => zzip_dir_fdopen
+ */
+ZZIP_DIR *
+zzip_dir_fdopen_ext_io(int fd, zzip_error_t * errcode_p,
+ zzip_strings_t* ext, const zzip_plugin_io_t io)
+{
+ zzip_error_t rv;
+ ZZIP_DIR * dir;
+
+ if ((dir = zzip_dir_alloc_ext_io (ext, io)) == NULL)
+ { rv = ZZIP_OUTOFMEM; goto error; }
+
+ dir->fd = fd;
+ if ((rv = __zzip_dir_parse (dir)))
+ goto error;
+
+ dir->hdr = dir->hdr0;
+ dir->refcount |= 0x10000000;
+
+ if (errcode_p) *errcode_p = rv;
+ return dir;
+error:
+ if (dir) zzip_dir_free(dir);
+ if (errcode_p) *errcode_p = rv;
+ return NULL;
+}
+
+static zzip_error_t
+__zzip_dir_parse (ZZIP_DIR* dir)
+{
+ zzip_error_t rv;
+ zzip_off_t filesize;
+ struct _disk_trailer trailer;
+ /* if (! dir || dir->fd < 0)
+ * { rv = EINVAL; goto error; }
+ */
+
+ HINT2("------------------ fd=%i", (int) dir->fd);
+ if ((filesize = dir->io->fd.filesize(dir->fd)) < 0)
+ { rv = ZZIP_DIR_STAT; goto error; }
+
+ HINT2("------------------ filesize=%ld", (long) filesize);
+ if ((rv = __zzip_fetch_disk_trailer(dir->fd, filesize, &trailer,
+ dir->io)) != 0)
+ { goto error; }
+
+ HINT5("directory = { entries= %ld/%ld, size= %ld, seek= %ld } ",
+ (long) _disk_trailer_localentries (&trailer),
+ (long) _disk_trailer_finalentries (&trailer),
+ (long) _disk_trailer_rootsize (&trailer),
+ (long) _disk_trailer_rootseek (&trailer));
+
+ if ( (rv = __zzip_parse_root_directory(dir->fd, &trailer, &dir->hdr0,
+ dir->io)) != 0)
+ { goto error; }
+ error:
+ return rv;
+}
+
+/**
+ * will attach a .zip extension and tries to open it
+ * the with => open(2). This is a helper function for
+ * => zzip_dir_open, => zzip_opendir and => zzip_open.
+ */
+int
+__zzip_try_open(zzip_char_t* filename, int filemode,
+ zzip_strings_t* ext, zzip_plugin_io_t io)
+{
+ auto char file[PATH_MAX];
+ int fd;
+ zzip_size_t len = strlen (filename);
+
+ if (len+4 >= PATH_MAX) return -1;
+ memcpy(file, filename, len+1);
+
+ if (!io) io = zzip_get_default_io();
+ if (!ext) ext = zzip_get_default_ext();
+
+ for ( ; *ext ; ++ext)
+ {
+ strcpy (file+len, *ext);
+ fd = io->fd.open(file, filemode);
+ if (fd != -1) return fd;
+ }
+ return -1;
+}
+
+/**
+ * Opens the zip-archive (if available).
+ * the two ext_io arguments will default to use posix io and
+ * a set of default fileext that can atleast add .zip ext itself.
+ */
+ZZIP_DIR*
+zzip_dir_open(zzip_char_t* filename, zzip_error_t* e)
+{
+ return zzip_dir_open_ext_io (filename, e, 0, 0);
+}
+
+/** => zzip_dir_open
+ * this function uses explicit ext and io instead of the internal
+ * defaults. Setting these to zero is equivalent to => zzip_dir_open
+ */
+ZZIP_DIR*
+zzip_dir_open_ext_io(zzip_char_t* filename, zzip_error_t* e,
+ zzip_strings_t* ext, zzip_plugin_io_t io)
+{
+ int fd;
+
+ if (!io) io = zzip_get_default_io();
+ if (!ext) ext = zzip_get_default_ext();
+
+ fd = io->fd.open(filename, O_RDONLY|O_BINARY);
+ if (fd != -1)
+ { return zzip_dir_fdopen_ext_io(fd, e, ext, io); }
+ else
+ {
+ fd = __zzip_try_open(filename, O_RDONLY|O_BINARY, ext, io);
+ if (fd != -1)
+ { return zzip_dir_fdopen_ext_io(fd, e, ext, io); }
+ else
+ {
+ if (e) { *e = ZZIP_DIR_OPEN; }
+ return 0;
+ }
+ }
+}
+
+/** => zzip_dir_open
+ * fills the dirent-argument with the values and
+ * increments the read-pointer of the dir-argument.
+ *
+ * returns 0 if there no entry (anymore).
+ */
+int
+zzip_dir_read(ZZIP_DIR * dir, ZZIP_DIRENT * d )
+{
+ if (! dir || ! dir->hdr || ! d) return 0;
+
+ d->d_compr = dir->hdr->d_compr;
+ d->d_csize = dir->hdr->d_csize;
+ d->st_size = dir->hdr->d_usize;
+ d->d_name = dir->hdr->d_name;
+
+ if (! dir->hdr->d_reclen)
+ { dir->hdr = 0; }
+ else
+ { dir->hdr = (struct zzip_dir_hdr *)((char *)dir->hdr + dir->hdr->d_reclen); }
+
+ return 1;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/zzip/zzip.h b/Build/source/libs/zziplib/zzip/zzip.h
new file mode 100644
index 00000000000..eecc4737af1
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/zzip.h
@@ -0,0 +1,323 @@
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ * Tomi Ollila <Tomi.Ollila@iki.fi>
+ *
+ * Copyright (c) 1999,2000,2001,2002,2003,2004 Guido Draheim
+ * All rights reserved,
+ * usage allowed under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ *
+ * if you see "unknown symbol" errors, check first that `-I ..` is part of
+ * your compiler options - a special hint to VC/IDE users who tend to make up
+ * their own workspace files. All includes look like #include <zzip|*.h>, so
+ * you need to add an include path to the dir containing (!!) the ./zzip/ dir
+ */
+
+#ifndef _ZZIP_ZZIP_H /* zziplib.h */
+#define _ZZIP_ZZIP_H
+
+#include <zzip/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* the zzip_error_t is also used to pass back ZLIB errors... */
+#define ZZIP_ERROR -4096
+
+typedef enum
+{
+ ZZIP_NO_ERROR = 0, /* no error, may be used if user sets it. */
+ ZZIP_OUTOFMEM = ZZIP_ERROR-20, /* out of memory */
+ ZZIP_DIR_OPEN = ZZIP_ERROR-21, /* failed to open zipfile, see errno for details */
+ ZZIP_DIR_STAT = ZZIP_ERROR-22, /* failed to fstat zipfile, see errno for details */
+ ZZIP_DIR_SEEK = ZZIP_ERROR-23, /* failed to lseek zipfile, see errno for details */
+ ZZIP_DIR_READ = ZZIP_ERROR-24, /* failed to read zipfile, see errno for details */
+ ZZIP_DIR_TOO_SHORT = ZZIP_ERROR-25,
+ ZZIP_DIR_EDH_MISSING = ZZIP_ERROR-26,
+ ZZIP_DIRSIZE = ZZIP_ERROR-27,
+ ZZIP_ENOENT = ZZIP_ERROR-28,
+ ZZIP_UNSUPP_COMPR = ZZIP_ERROR-29,
+ ZZIP_CORRUPTED = ZZIP_ERROR-31,
+ ZZIP_UNDEF = ZZIP_ERROR-32,
+ ZZIP_DIR_LARGEFILE = ZZIP_ERROR-33
+} zzip_error_t;
+
+/*
+ * zzip_open flags.
+ */
+#define ZZIP_CASEINSENSITIVE O_APPEND /* do not use anymore. use CASLESS */
+#define ZZIP_IGNOREPATH O_TRUNC /* do not use anymore. use NOPATHS */
+#define ZZIP_EXTRAFLAGS (ZZIP_CASEINSENSITIVE|ZZIP_IGNOREPATH)
+
+/* zzip_open_ext_io o_modes flags : new style. use these from now on! */
+#define ZZIP_CASELESS (1<<12) /* ignore filename case inside zips */
+#define ZZIP_NOPATHS (1<<13) /* ignore subdir paths, just filename*/
+#define ZZIP_PREFERZIP (1<<14) /* try first zipped file, then real*/
+#define ZZIP_ONLYZIP (1<<16) /* try _only_ zipped file, skip real*/
+#define ZZIP_FACTORY (1<<17) /* old file handle is not closed */
+#define ZZIP_ALLOWREAL (1<<18) /* real files use default_io (magic) */
+#define ZZIP_THREADED (1<<19) /* try to be safe for multithreading */
+
+/*
+ * zzip largefile renames
+ */
+#ifdef ZZIP_LARGEFILE_RENAME
+#define zzip_telldir zzip_telldir64
+#define zzip_seekdir zzip_seekdir64
+#endif
+
+/*
+ * zzip typedefs
+ */
+/* zzip_strings_t ext[] = { ".zip", ".jar", ".pk3", 0 } */
+typedef char _zzip_const * _zzip_const zzip_strings_t;
+typedef char _zzip_const zzip_char_t;
+typedef struct zzip_dir ZZIP_DIR;
+typedef struct zzip_file ZZIP_FILE;
+typedef struct zzip_dirent ZZIP_DIRENT;
+typedef struct zzip_dirent ZZIP_STAT;
+
+struct zzip_dirent
+{
+ int d_compr; /* compression method */
+ int d_csize; /* compressed size */
+ int st_size; /* file size / decompressed size */
+ char * d_name; /* file name / strdupped name */
+};
+
+/*
+ * Getting error strings
+ * zzip/err.c
+ */
+_zzip_export /* error in _opendir : */
+zzip_char_t* zzip_strerror(int errcode);
+_zzip_export /* error in other functions : */
+zzip_char_t* zzip_strerror_of(ZZIP_DIR * dir);
+_zzip_export /* error mapped to errno.h defines : */
+int zzip_errno(int errcode);
+
+
+/*
+ * Functions to grab information from ZZIP_DIR/ZZIP_FILE structure
+ * (if ever needed)
+ * zzip/info.c
+ */
+_zzip_export
+int zzip_error(ZZIP_DIR * dir);
+_zzip_export
+void zzip_seterror(ZZIP_DIR * dir, int errcode);
+_zzip_export
+zzip_char_t* zzip_compr_str(int compr);
+
+_zzip_export
+ZZIP_DIR * zzip_dirhandle(ZZIP_FILE * fp);
+_zzip_export
+int zzip_dirfd(ZZIP_DIR * dir);
+_zzip_export
+int zzip_dir_real(ZZIP_DIR * dir);
+_zzip_export
+int zzip_file_real(ZZIP_FILE * fp);
+_zzip_export
+void* zzip_realdir(ZZIP_DIR * dir);
+_zzip_export
+int zzip_realfd(ZZIP_FILE * fp);
+
+/*
+ * zip handle management
+ * zzip/zip.c
+ */
+_zzip_export
+ZZIP_DIR * zzip_dir_alloc(zzip_strings_t* fileext);
+_zzip_export
+int zzip_dir_free(ZZIP_DIR *);
+
+/*
+ * Opening/closing a zip archive
+ * zzip-zip.c
+ */
+_zzip_export
+ZZIP_DIR * zzip_dir_fdopen(int fd, zzip_error_t * errcode_p);
+_zzip_export
+ZZIP_DIR * zzip_dir_open(zzip_char_t* filename, zzip_error_t * errcode_p);
+_zzip_export
+int zzip_dir_close(ZZIP_DIR * dir);
+_zzip_export
+int zzip_dir_read(ZZIP_DIR * dir, ZZIP_DIRENT * dirent);
+
+
+/*
+ * Scanning files in zip archive
+ * zzip/dir.c
+ * zzip/zip.c
+ */
+_zzip_export
+ZZIP_DIR * zzip_opendir(zzip_char_t* filename);
+_zzip_export
+int zzip_closedir(ZZIP_DIR * dir);
+_zzip_export
+ZZIP_DIRENT * zzip_readdir(ZZIP_DIR * dir);
+_zzip_export
+void zzip_rewinddir(ZZIP_DIR * dir);
+_zzip_export
+zzip_off_t zzip_telldir(ZZIP_DIR * dir);
+_zzip_export
+void zzip_seekdir(ZZIP_DIR * dir, zzip_off_t offset);
+
+/*
+ * 'opening', 'closing' and reading invidual files in zip archive.
+ * zzip/file.c
+ */
+_zzip_export
+ZZIP_FILE * zzip_file_open(ZZIP_DIR * dir, zzip_char_t* name, int flags);
+_zzip_export
+int zzip_file_close(ZZIP_FILE * fp);
+_zzip_export
+zzip_ssize_t zzip_file_read(ZZIP_FILE * fp, char* buf, zzip_size_t len);
+
+_zzip_export
+ZZIP_FILE * zzip_open(zzip_char_t* name, int flags);
+_zzip_export
+int zzip_close(ZZIP_FILE * fp);
+_zzip_export
+zzip_ssize_t zzip_read(ZZIP_FILE * fp, char * buf, zzip_size_t len);
+
+/*
+ * the stdc variant to open/read/close files. - Take note of the freopen()
+ * call as it may reuse an existing preparsed copy of a zip central directory
+ */
+_zzip_export
+ZZIP_FILE* zzip_freopen(zzip_char_t* name, zzip_char_t* mode, ZZIP_FILE*);
+_zzip_export
+ZZIP_FILE* zzip_fopen(zzip_char_t* name, zzip_char_t* mode);
+_zzip_export
+zzip_size_t zzip_fread(void *ptr, zzip_size_t size, zzip_size_t nmemb,
+ ZZIP_FILE * file);
+_zzip_export
+int zzip_fclose(ZZIP_FILE * fp);
+
+/*
+ * seek and tell functions
+ */
+_zzip_export
+int zzip_rewind(ZZIP_FILE *fp);
+_zzip_export
+zzip_off_t zzip_seek(ZZIP_FILE * fp, zzip_off_t offset, int whence);
+_zzip_export
+zzip_off_t zzip_tell(ZZIP_FILE * fp);
+
+/*
+ * reading info of a single file
+ * zzip/stat.c
+ */
+_zzip_export
+int zzip_dir_stat(ZZIP_DIR * dir, zzip_char_t* name,
+ ZZIP_STAT * zs, int flags);
+_zzip_export
+int zzip_file_stat(ZZIP_FILE * fp, ZZIP_STAT * zs);
+_zzip_export
+int zzip_fstat(ZZIP_FILE * fp, ZZIP_STAT * zs);
+
+#ifdef ZZIP_LARGEFILE_RENAME
+#define zzip_open_shared_io zzip_open_shared_io64
+#define zzip_open_ext_io zzip_open_ext_io64
+#define zzip_opendir_ext_io zzip_opendir_ext_io64
+#define zzip_dir_open_ext_io zzip_dir_open_ext_io64
+#define zzip_plugin_io_t zzip_plugin_io64_t
+#endif
+
+/*
+ * all ext_io functions can be called with a default of ext/io == zero/zero
+ * which will default to a ".zip" extension and posix io of the system.
+ */
+typedef union _zzip_plugin_io _zzip_const * zzip_plugin_io_t;
+
+_zzip_export
+ZZIP_FILE * zzip_open_shared_io(ZZIP_FILE* stream,
+ zzip_char_t* name, int o_flags, int o_modes,
+ zzip_strings_t* ext, zzip_plugin_io_t io);
+
+_zzip_export
+ZZIP_FILE * zzip_open_ext_io(zzip_char_t* name, int o_flags, int o_modes,
+ zzip_strings_t* ext, zzip_plugin_io_t io);
+
+_zzip_export
+ZZIP_DIR * zzip_opendir_ext_io(zzip_char_t* name, int o_modes,
+ zzip_strings_t* ext, zzip_plugin_io_t io);
+
+_zzip_export
+ZZIP_DIR * zzip_dir_open_ext_io(zzip_char_t* filename,
+ zzip_error_t* errcode_p,
+ zzip_strings_t* ext, zzip_plugin_io_t io);
+
+/* zzip_file_open_ext_io => zzip_dir_open_ext_io + zzip_file_open */
+
+#if defined _ZZIP_WRITE_SOURCE
+/* ........................................................................
+ * write support is not yet implemented
+ * zzip/write.c
+ */
+#define ZZIP_NO_CREAT 1
+
+ZZIP_DIR* zzip_dir_creat_ext_io(zzip_char_t* name, int o_mode,
+ zzip_strings_t* ext, zzip_plugin_io_t io);
+ZZIP_DIR* zzip_dir_creat(zzip_char_t* name, int o_mode);
+int zzip_file_mkdir(ZZIP_DIR* dir, zzip_char_t* name, int o_mode);
+ZZIP_FILE* zzip_file_creat(ZZIP_DIR* dir, zzip_char_t* name, int o_mode);
+zzip_ssize_t zzip_file_write(ZZIP_FILE* file,
+ const void* ptr, zzip_size_t len);
+
+ZZIP_DIR* zzip_createdir(zzip_char_t* name, int o_mode);
+zzip_ssize_t zzip_write(ZZIP_FILE* file, const void* ptr, zzip_size_t len);
+zzip_size_t zzip_fwrite(const void* ptr, zzip_size_t len,
+ zzip_size_t multiply, ZZIP_FILE* file);
+#ifndef zzip_savefile
+#define zzip_savefile 0
+#define zzip_savefile_is_null
+#endif
+
+#ifdef _ZZIP_NO_INLINE
+#define zzip_mkdir(_name_,_mode_) \
+ zzip_file_mkdir((zzip_savefile),(_name_),(_mode_))
+#define zzip_creat(_name_,_mode_) \
+ zzip_file_creat((zzip_savefile),(_name_),(_mode_))
+#define zzip_sync() \
+ { zzip_closedir((zzip_savefile)); (zzip_savefile) = 0; }
+#define zzip_start(_name_,_mode_,_ext_) \
+ { if ((zzip_savefile)) zzip_closedir((zzip_savefile));
+ zzip_savefile = zzip_dir_creat(_name_, _mode_,_ext_); }
+
+#else
+
+_zzip_inline static int zzip_mkdir(zzip_char_t* name, int o_mode)
+{ return zzip_file_mkdir(zzip_savefile, name, o_mode); }
+_zzip_inline static ZZIP_FILE* zzip_creat(zzip_char_t* name, int o_mode)
+{ return zzip_file_creat(zzip_savefile, name, o_mode); }
+
+#ifndef zzip_savefile_is_null
+_zzip_inline static void zzip_sync(void)
+{ zzip_closedir(zzip_savefile); zzip_savefile = 0; }
+_zzip_inline static void zzip_mkfifo(zzip_char_t* name, int o_mode)
+{ if ((zzip_savefile)) zzip_closedir (zzip_savefile);
+ zzip_savefile = zzip_createdir(_name_,_mode_); }
+#else
+_zzip_inline static void zzip_sync(void) {}
+_zzip_inline static void zzip_mkfifo(zzip_char_t* name, int o_mode) {}
+#endif
+#endif /* _ZZIP_NO_INLINE */
+#endif /* _ZZIP_WRITE_SOURCE */
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* _ZZIPLIB_H */
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
diff --git a/Build/source/libs/zziplib/zzip/zziplib.wpj b/Build/source/libs/zziplib/zzip/zziplib.wpj
new file mode 100755
index 00000000000..e371b9b38bb
--- /dev/null
+++ b/Build/source/libs/zziplib/zzip/zziplib.wpj
@@ -0,0 +1,103 @@
+40
+projectIdent
+0
+VpeMain
+1
+WRect
+0
+0
+7680
+10240
+2
+MProject
+3
+MCommand
+0
+4
+MCommand
+0
+4
+5
+WFileName
+11
+zziplib.tgt
+6
+WFileName
+9
+zzcat.tgt
+7
+WFileName
+9
+zzdir.tgt
+8
+WFileName
+12
+zziptest.tgt
+9
+WVList
+4
+10
+VComponent
+11
+WRect
+0
+0
+5670
+4215
+0
+0
+12
+WFileName
+11
+zziplib.tgt
+0
+0
+13
+VComponent
+14
+WRect
+678
+665
+5670
+4215
+0
+0
+15
+WFileName
+9
+zzcat.tgt
+0
+0
+16
+VComponent
+17
+WRect
+1868
+1467
+5670
+4215
+0
+0
+18
+WFileName
+9
+zzdir.tgt
+0
+0
+19
+VComponent
+20
+WRect
+1356
+1348
+5670
+4215
+0
+0
+21
+WFileName
+12
+zziptest.tgt
+0
+0
+19
diff --git a/Build/source/libs/zziplib/zzipback.sed b/Build/source/libs/zziplib/zzipback.sed
new file mode 100644
index 00000000000..b3e5e768525
--- /dev/null
+++ b/Build/source/libs/zziplib/zzipback.sed
@@ -0,0 +1,19 @@
+s:<zzip/_config.h>:<zzip-config.h>:
+s:<zzip/_msvc.h>:<zzip-msvc.h>:
+s:<zzip/conf.h>:<zzip-conf.h>:
+s:<zzip/dir.h>:<zzip-dir.h>:
+s:<zzip/err.h>:<zzip-err.h>:
+s:<zzip/file.h>:<zzip-file.h>:
+s:<zzip/format.h>:<zzipformat.h>:
+s:<zzip/info.h>:<zzip-info.h>:
+s:<zzip/lib.h>:<zzip.h>:
+s:<zzip/zzip.h>:<zziplib.h>:
+s:<zzip/plugin.h>:<zzip-io.h>:
+s:<zzip/stat.h>:<zzip-stat.h>:
+s:<zzip/stdint.h>:<zzip-stdint.h>:
+s:<zzip/__debug.h>:"__debug.h":
+s:<zzip/__dirent.h>:"__dirent.h":
+s:<zzip/__hints.h>:"__hints.h":
+s:<zzip/__mmap.h>:"__mmap.h":
+s:<zzip/wrap.h>:"zzipwrap.h":
+/#inc/s:"wrap.h":"zzipwrap.h":
diff --git a/Build/source/libs/zziplib/zziplib.spec b/Build/source/libs/zziplib/zziplib.spec
new file mode 100644
index 00000000000..55e92649cd1
--- /dev/null
+++ b/Build/source/libs/zziplib/zziplib.spec
@@ -0,0 +1,157 @@
+%define lib lib010
+Summary: ZZipLib - libZ-based ZIP-access Library
+Name: zziplib
+Version: 0.13.47
+Release: 1.suse100
+Serial: 1
+Copyright: LGPL
+Group: Development/Libraries
+URL: http://zziplib.sf.net
+Vendor: Guido Draheim <guidod@gmx.de>
+Source0: http://prdownloads.sf.net/%{name}/%{name}-%{version}.tar.bz2
+BuildRoot: /var/tmp/%{name}-%{version}-%{release}
+
+Distribution: Original
+Packager: Guido Draheim <guidod@gmx.de>
+Requires: zlib
+BuildRequires: zlib-devel
+BuildRequires: SDL-devel
+
+#Begin3
+# Author1: too@iki.fi (Tomi Ollila)
+# Author2: guidod@gmx.de (Guido Draheim)
+# Maintained-by: guidod@gmx.de (Guido Draheim)
+# Primary-Site: zziplib.sf.net
+# Keywords: zip zlib inflate archive gamedata
+# Platforms: zlib posix
+# Copying-Policy: Lesser GPL Version 2
+#End
+
+%package %lib
+Summary: ZZipLib - Documentation Files
+Group: Development/Libraries
+Provides: zziplib
+Provides: libzzip0
+Provides: libzzip-0.so.10
+
+%package doc
+Summary: ZZipLib - Documentation Files
+Group: Development/Libraries
+
+%package devel
+Summary: ZZipLib - Development Files
+Group: Development/Libraries
+Requires: zziplib-%lib = %version
+# Requires: pkgconfig (not yet)
+
+%description
+ : zziplib provides read access to zipped files in a zip-archive,
+ : using compression based solely on free algorithms provided by zlib.
+
+%description %lib
+ : zziplib provides read access to zipped files in a zip-archive,
+ : using compression based solely on free algorithms provided by zlib.
+ zziplib provides an additional API to transparently access files
+ being either real files or zipped files with the same filepath argument.
+ This is handy to package many files being shared data into a single
+ zip file - as it is sometimes used with gamedata or script repositories.
+ The library itself is fully multithreaded, and it is namespace clean
+ using the zzip_ prefix for its exports and declarations.
+
+%description doc
+ : zziplib provides read access to zipped files in a zip-archive,
+ : using compression based solely on free algorithms provided by zlib.
+ these are the (html) docs, mostly generated actually.
+
+%description devel
+ : zziplib provides read access to zipped files in a zip-archive,
+ : using compression based solely on free algorithms provided by zlib.
+ these are the header files needed to develop programs using zziplib.
+ there are test binaries to hint usage of the library in user programs.
+
+%prep
+#'
+%setup
+# fixing relink problems during install too
+LDFLAGS="-L%buildroot%_libdir" \
+CFLAGS="$RPM_OPT_FLAGS" \
+sh configure --prefix=%{_prefix} --enable-sdl --disable-builddir \
+ --with-docdir=%{_docdir} --mandir=%{_mandir} TIMEOUT=9
+cp -a zzip zzip64
+
+%build
+%define _FILE_OFFSET64 -D_ZZIP_LARGEFILE -D_FILE_OFFSET_BITS=64
+%define _RELEASEINFO64 "RELEASE_INFO=-release 0-64"
+%define _CFLAGS_OFFSET64 "AM_CFLAGS=%_FILE_OFFSET64"
+make
+(cd zzip64 && make %_CFLAGS_OFFSET64 %_RELEASEINFO64)
+make doc
+
+%install
+rm -rf %{buildroot}
+(cd zzip64 && make install %_RELEASEINFO64 DESTDIR=%{buildroot})
+(cd %buildroot/%_libdir && mv libzzip.so libzzip64.so)
+(cd %buildroot/%_libdir && mv libzzip.a libzzip64.a)
+(cd %buildroot/%_libdir && \
+sed -e 's/zzip.so/zzip64.so/' -e 's/zzip.a/zzip64.a/' libzzip.la >libzzip64.la)
+(cd %buildroot/%_libdir/pkgconfig && \
+sed -e 's/largefile=/largefile= %_FILE_OFFSET64/' \
+ -e 's/-lzzip/-lzzip64/' -e 's/zziplib/zziplib64/' zziplib.pc >zziplib64.pc)
+
+make install DESTDIR=%{buildroot}
+(cd %buildroot/%_libdir && mv libzzip.so libzzip32.so)
+(cd %buildroot/%_libdir && mv libzzip.a libzzip32.a)
+(cd %buildroot/%_libdir && ln -s libzzip32.so libzzip.so)
+(cd %buildroot/%_libdir && ln -s libzzip32.a libzzip.a)
+(cd %buildroot/%_libdir && \
+sed -e 's/zzip.so/zzip32.so/' -e 's/zzip.a/zzip32.a/' libzzip.la >libzzip32.la)
+(cd %buildroot/%_libdir/pkgconfig && \
+sed -e 's/-lzzip/-lzzip32/' -e 's/zziplib/zziplib32/' zziplib.pc >zziplib32.pc)
+
+# the 12.8x and 11.8x and 10.8x packages are all the same actually
+(cd %buildroot/%_libdir && \
+(for i in libzzip*.so.1? ; do : \
+; v10=`echo $i | sed -e "s/.so.../.so.10/"` \
+; v11=`echo $i | sed -e "s/.so.../.so.11/"` \
+; v12=`echo $i | sed -e "s/.so.../.so.12/"` \
+; test ! -e $v10 && test -e $v12 && ln -s $v12 $v10 \
+; test ! -e $v12 && test -e $v10 && ln -s $v10 $v12 \
+; ln -s $v10 $v11 || true; done))
+
+make install-doc DESTDIR=%{buildroot}
+make install-man3 DESTDIR=%{buildroot}
+
+%post -p /sbin/ldconfig
+%postun -p /sbin/ldconfig
+
+%clean
+rm -rf %{buildroot}
+
+%files %lib
+ %defattr(-,root,root)
+ %{_libdir}/lib*.so.*
+
+%files doc
+ %defattr(-,root,root)
+ %{_datadir}/groups/*
+%dir %{_datadir}/omf/%{name}
+ %{_datadir}/omf/%{name}/*
+%post doc
+test ! -f %_bindir/scrollkeeper-update || %_bindir/scrollkeeper-update
+%postun doc
+test ! -f %_bindir/scrollkeeper-update || %_bindir/scrollkeeper-update
+
+%files devel
+ %defattr(-,root,root)
+ %{_bindir}/*
+%dir %{_includedir}/zzip
+ %{_includedir}/zzip/*
+ %{_includedir}/*.h
+ %{_libdir}/lib*.so
+ %{_libdir}/lib*.a
+ %{_libdir}/lib*.la
+ %{_libdir}/pkgconfig/*
+%dir %{_datadir}/%{name}
+ %{_datadir}/%{name}/*
+ %{_datadir}/aclocal/%{name}*.m4
+ %{_mandir}/man3/*
diff --git a/Build/source/libs/zziplib/zzipwrap/.deps/wrap.Plo b/Build/source/libs/zziplib/zzipwrap/.deps/wrap.Plo
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/zzipwrap/.deps/wrap.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/zzipwrap/.deps/zzipwrap.Po b/Build/source/libs/zziplib/zzipwrap/.deps/zzipwrap.Po
new file mode 100644
index 00000000000..9ce06a81ea4
--- /dev/null
+++ b/Build/source/libs/zziplib/zzipwrap/.deps/zzipwrap.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/Build/source/libs/zziplib/zzipwrap/Makefile.am b/Build/source/libs/zziplib/zzipwrap/Makefile.am
new file mode 100644
index 00000000000..2c5b4719841
--- /dev/null
+++ b/Build/source/libs/zziplib/zzipwrap/Makefile.am
@@ -0,0 +1,51 @@
+AUTOMAKE_OPTIONS = 1.4 foreign
+AUTOTOOL_VERSION=autoconf-2.52 automake-1.5 libtool-1.4.2
+DEFAULT_INCLUDES = # nothing - no default of -I. -I$(srcdir)
+DEFS = @DEFS@ -I$(top_builddir) -I$(top_srcdir) # also for automake 1.4
+
+noinst_PROGRAMS = zzipwrap
+lib_LTLIBRARIES = libzzipwrap.la
+zzipdir = ${includedir}/zzip
+zzip_HEADERS = $(libzzipwrap_la_headers)
+#
+VERSION_INFO=@VERSION_INFO@
+RELEASE_INFO=@RELEASE_INFO@
+THREAD_SAFE=@THREAD_SAFE@
+#
+
+libzzipwrap_la_SOURCES = \
+ wrap.c
+libzzipwrap_la_headers = \
+ wrap.h
+
+libzzipwrap_la_LDFLAGS= @ZZIPLIB_LDFLAGS@ $(RELEASE_INFO) $(VERSION_INFO) \
+ $(THREAD_SAFE)
+libzzipwrap_la_LIBADD= ../zzip/libzzip.la @RESOLVES@ -lz
+
+../zzip/libzzip.la : @top_srcdir@/zzip/*.c
+ (cd ../zzip && $(MAKE) `basename $@`)
+
+
+WCC10_CLEAN = *.obj *.lk1 *.mk1 *.mk *.sym *.tgt
+
+EXTRA_DIST =
+CLEANFILES = $(WCC10_CLEAN) *.pc *.omf
+
+zzipwrap_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzipwrap_LDADD = libzzipwrap.la @RESOLVES@ ../zzip/libzzip.la -lz
+
+# ----------------------------------------------------------------------
+pkgconfigdir=$(libdir)/pkgconfig
+pkgconfig_HEADERS= zzipwrap.pc
+
+zzipwrap.pc : Makefile
+ @ echo "prefix=$(prefix)" >$@
+ @ echo "libdir=$(libdir)" >>$@
+ @ echo "includedir=$(includedir)" >>$@
+ @ echo " " >>$@
+ @ echo "Name: zzipwrap" >>$@
+ @ echo "Version: $(VERSION)" >>$@
+ @ echo "Description: Callback Wrappers for ZZipLib" >>$@
+ echo 'Requires: zziplib' >>$@
+ echo 'Libs: -L$${libdir} -lzzipwrap' >>$@
+ echo 'Cflags: -I$${includedir}' >>$@
diff --git a/Build/source/libs/zziplib/zzipwrap/Makefile.in b/Build/source/libs/zziplib/zzipwrap/Makefile.in
new file mode 100644
index 00000000000..92d06fb1e84
--- /dev/null
+++ b/Build/source/libs/zziplib/zzipwrap/Makefile.in
@@ -0,0 +1,606 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+noinst_PROGRAMS = zzipwrap$(EXEEXT)
+subdir = zzipwrap
+DIST_COMMON = $(pkgconfig_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(zzip_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_compile_check_sizeof.m4 \
+ $(top_srcdir)/m4/ac_set_default_paths_system.m4 \
+ $(top_srcdir)/m4/ac_sys_largefile_sensitive.m4 \
+ $(top_srcdir)/m4/acx_restrict.m4 \
+ $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \
+ $(top_srcdir)/m4/ax_cflags_no_writable_strings.m4 \
+ $(top_srcdir)/m4/ax_cflags_strict_prototypes.m4 \
+ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \
+ $(top_srcdir)/m4/ax_create_pkgconfig_info.m4 \
+ $(top_srcdir)/m4/ax_enable_builddir_uname.m4 \
+ $(top_srcdir)/m4/ax_expand_prefix.m4 \
+ $(top_srcdir)/m4/ax_maintainer_mode_auto_silent.m4 \
+ $(top_srcdir)/m4/ax_not_enable_frame_pointer.m4 \
+ $(top_srcdir)/m4/ax_prefix_config_h.m4 \
+ $(top_srcdir)/m4/ax_set_version_info.m4 \
+ $(top_srcdir)/m4/ax_spec_file.m4 \
+ $(top_srcdir)/m4/ax_spec_package_version.m4 \
+ $(top_srcdir)/m4/ax_warning_default_aclocaldir.m4 \
+ $(top_srcdir)/m4/ax_warning_default_pkgconfig.m4 \
+ $(top_srcdir)/m4/patch_libtool_on_darwin_zsh_overquoting.m4 \
+ $(top_srcdir)/m4/patch_libtool_sys_lib_search_path_spec.m4 \
+ $(top_srcdir)/m4/patch_libtool_to_add_host_cc.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/uses/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \
+ "$(DESTDIR)$(zzipdir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libzzipwrap_la_DEPENDENCIES = ../zzip/libzzip.la
+am_libzzipwrap_la_OBJECTS = wrap.lo
+libzzipwrap_la_OBJECTS = $(am_libzzipwrap_la_OBJECTS)
+PROGRAMS = $(noinst_PROGRAMS)
+zzipwrap_SOURCES = zzipwrap.c
+zzipwrap_OBJECTS = zzipwrap.$(OBJEXT)
+zzipwrap_DEPENDENCIES = libzzipwrap.la ../zzip/libzzip.la
+depcomp = $(SHELL) $(top_srcdir)/uses/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libzzipwrap_la_SOURCES) zzipwrap.c
+DIST_SOURCES = $(libzzipwrap_la_SOURCES) zzipwrap.c
+pkgconfigHEADERS_INSTALL = $(INSTALL_HEADER)
+zzipHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(pkgconfig_HEADERS) $(zzip_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONFIG_FILES = @CONFIG_FILES@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@ -I$(top_builddir) -I$(top_srcdir) # also for automake 1.4
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LARGEFILE_CFLAGS = @LARGEFILE_CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+MKZIP = @MKZIP@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RELEASE_INFO = @RELEASE_INFO@
+RESOLVES = @RESOLVES@
+SDL = @SDL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+THREAD_SAFE = @THREAD_SAFE@
+VERSION = @VERSION@
+#
+VERSION_INFO = @VERSION_INFO@
+XMLTO = @XMLTO@
+ZIPTESTS = @ZIPTESTS@
+ZLIB_INCL = @ZLIB_INCL@
+ZLIB_LDIR = @ZLIB_LDIR@
+ZLIB_VERSION = @ZLIB_VERSION@
+ZZIPLIB_LDFLAGS = @ZZIPLIB_LDFLAGS@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_AS = @ac_ct_AS@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DLLTOOL = @ac_ct_DLLTOOL@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_OBJDUMP = @ac_ct_OBJDUMP@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+aclocaldir = @aclocaldir@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_enable_builddir_sed = @ax_enable_builddir_sed@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+docdir = @docdir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pkgconfig_libdir = @pkgconfig_libdir@
+pkgconfig_libfile = @pkgconfig_libfile@
+
+# ----------------------------------------------------------------------
+pkgconfigdir = $(libdir)/pkgconfig
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+AUTOMAKE_OPTIONS = 1.4 foreign
+AUTOTOOL_VERSION = autoconf-2.52 automake-1.5 libtool-1.4.2
+DEFAULT_INCLUDES = # nothing - no default of -I. -I$(srcdir)
+lib_LTLIBRARIES = libzzipwrap.la
+zzipdir = ${includedir}/zzip
+zzip_HEADERS = $(libzzipwrap_la_headers)
+#
+libzzipwrap_la_SOURCES = \
+ wrap.c
+
+libzzipwrap_la_headers = \
+ wrap.h
+
+libzzipwrap_la_LDFLAGS = @ZZIPLIB_LDFLAGS@ $(RELEASE_INFO) $(VERSION_INFO) \
+ $(THREAD_SAFE)
+
+libzzipwrap_la_LIBADD = ../zzip/libzzip.la @RESOLVES@ -lz
+WCC10_CLEAN = *.obj *.lk1 *.mk1 *.mk *.sym *.tgt
+EXTRA_DIST =
+CLEANFILES = $(WCC10_CLEAN) *.pc *.omf
+zzipwrap_LDFLAGS = @ZZIPLIB_LDFLAGS@
+zzipwrap_LDADD = libzzipwrap.la @RESOLVES@ ../zzip/libzzip.la -lz
+pkgconfig_HEADERS = zzipwrap.pc
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign zzipwrap/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign zzipwrap/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libzzipwrap.la: $(libzzipwrap_la_OBJECTS) $(libzzipwrap_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(libzzipwrap_la_LDFLAGS) $(libzzipwrap_la_OBJECTS) $(libzzipwrap_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+zzipwrap$(EXEEXT): $(zzipwrap_OBJECTS) $(zzipwrap_DEPENDENCIES)
+ @rm -f zzipwrap$(EXEEXT)
+ $(LINK) $(zzipwrap_LDFLAGS) $(zzipwrap_OBJECTS) $(zzipwrap_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wrap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzipwrap.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+install-pkgconfigHEADERS: $(pkgconfig_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgconfigdir)" || $(mkdir_p) "$(DESTDIR)$(pkgconfigdir)"
+ @list='$(pkgconfig_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(pkgconfigHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ $(pkgconfigHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+
+uninstall-pkgconfigHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgconfig_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+install-zzipHEADERS: $(zzip_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(zzipdir)" || $(mkdir_p) "$(DESTDIR)$(zzipdir)"
+ @list='$(zzip_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(zzipHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(zzipdir)/$$f'"; \
+ $(zzipHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(zzipdir)/$$f"; \
+ done
+
+uninstall-zzipHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(zzip_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(zzipdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(zzipdir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(zzipdir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pkgconfigHEADERS install-zzipHEADERS
+
+install-exec-am: install-libLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES \
+ uninstall-pkgconfigHEADERS uninstall-zzipHEADERS
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool clean-noinstPROGRAMS ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-exec install-exec-am install-info \
+ install-info-am install-libLTLIBRARIES install-man \
+ install-pkgconfigHEADERS install-strip install-zzipHEADERS \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-info-am \
+ uninstall-libLTLIBRARIES uninstall-pkgconfigHEADERS \
+ uninstall-zzipHEADERS
+
+
+../zzip/libzzip.la : @top_srcdir@/zzip/*.c
+ (cd ../zzip && $(MAKE) `basename $@`)
+
+zzipwrap.pc : Makefile
+ @ echo "prefix=$(prefix)" >$@
+ @ echo "libdir=$(libdir)" >>$@
+ @ echo "includedir=$(includedir)" >>$@
+ @ echo " " >>$@
+ @ echo "Name: zzipwrap" >>$@
+ @ echo "Version: $(VERSION)" >>$@
+ @ echo "Description: Callback Wrappers for ZZipLib" >>$@
+ echo 'Requires: zziplib' >>$@
+ echo 'Libs: -L$${libdir} -lzzipwrap' >>$@
+ echo 'Cflags: -I$${includedir}' >>$@
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Build/source/libs/zziplib/zzipwrap/wrap.c b/Build/source/libs/zziplib/zzipwrap/wrap.c
new file mode 100644
index 00000000000..2bea0c39e5b
--- /dev/null
+++ b/Build/source/libs/zziplib/zzipwrap/wrap.c
@@ -0,0 +1,223 @@
+
+/* Wrapper interface for zziplib's file IO functions.
+ *
+ * -- In memory-access IO function --
+ * Provides default fileio functions open/read/lseek/close and functions
+ * that enable blocked, memory buffered IO.
+ *
+ * (c) A. Schiffler, aschiffler@home.com
+ * Released under same license as zziplib (LGPL), Oct 2001
+ *
+ * modified 2002 to use new plugin_io interface by Guido Draheim
+ */
+
+#include <zzip/conf.h>
+#include <zzip/plugin.h>
+/* #incl <zzip/wrap.h> */
+#include "wrap.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef ZZIP_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* Some globals that we use for operation */
+
+static int zzip_memory_blocksize=0;
+static zzipwrap_pfn_t zzip_memory_callback=NULL;
+static void *zzip_memory_callbackdata=NULL;
+static char *zzip_memory_buffer=NULL;
+static int zzip_memory_bufferblock=0;
+static int zzip_memory_fd=-1;
+static int zzip_memory_pos=0;
+static int zzip_memory_size=0;
+
+/* at the moment, we do not export the five handlers of zzip_memry plugin_io */
+#define ZZIP_memory static
+
+ZZIP_memory void zzip_memory_reset(void)
+{
+ zzip_memory_buffer=NULL;
+ zzip_memory_bufferblock=0;
+ zzip_memory_pos=0;
+ zzip_memory_size=0;
+ zzip_memory_fd=-1;
+}
+
+ZZIP_memory int zzip_memory_read(int fd, char *buf, size_t count)
+{
+ int requested_block;
+ int transfer_start;
+ int transfer_bytes;
+ int bytes_read;
+ int bytes_to_write;
+ int bytes_written;
+
+ /* Check file descriptor */
+ if (fd!=zzip_memory_fd) {
+ return(-1);
+ }
+
+ if ((int)count<0)
+ return -1;
+
+ /* Work out how many bytes we have to read based */
+ /* on filepos and requested buffersize. */
+ bytes_to_write=zzip_memory_size-zzip_memory_pos;
+ if (bytes_to_write>=(int)count) {
+ bytes_to_write=(int)count;
+ }
+
+ /* Read/transfer loop */
+ bytes_written=0;
+ while (bytes_to_write>0) {
+ /* Check which block we are reading from */
+ requested_block=zzip_memory_pos/zzip_memory_blocksize;
+ /* Check if we have this block available */
+ if (zzip_memory_bufferblock!=requested_block) {
+ /* Read this block */
+ lseek(fd,requested_block*zzip_memory_blocksize,SEEK_SET);
+ bytes_read=read(fd,zzip_memory_buffer,zzip_memory_blocksize);
+ /* Clear unused bytes */
+ if ((bytes_read>=0) && (bytes_read<zzip_memory_blocksize)) {
+ memset(&zzip_memory_buffer[bytes_read],0,zzip_memory_blocksize-bytes_read);
+ }
+ /* Set current block pos */
+ zzip_memory_bufferblock=requested_block;
+ /* Process buffer if callback is set */
+ if (zzip_memory_callback) {
+ zzip_memory_callback(zzip_memory_buffer,zzip_memory_blocksize,zzip_memory_callbackdata);
+ }
+ } else {
+ bytes_read=zzip_memory_blocksize;
+ }
+ /* Check if we have read any data */
+ if (bytes_read > 0) {
+ /* Copy data to output buffer */
+ transfer_start=zzip_memory_pos-zzip_memory_bufferblock*zzip_memory_blocksize;
+ transfer_bytes=zzip_memory_blocksize-transfer_start;
+ if (transfer_bytes>bytes_to_write) {
+ transfer_bytes=bytes_to_write;
+ }
+ memcpy (&buf[bytes_written], &zzip_memory_buffer[transfer_start],transfer_bytes);
+ zzip_memory_pos += transfer_bytes;
+ bytes_written += transfer_bytes;
+ bytes_to_write -= transfer_bytes;
+ } else {
+ /* Exit on error during read */
+ bytes_to_write=0;
+ }
+ }
+ return(bytes_written);
+}
+
+ZZIP_memory int zzip_memory_open(const char *pathname, int flags)
+{
+ int fd;
+ struct stat stat_buffer;
+
+ /* Deallocate any memory buffer laying around */
+ if (zzip_memory_buffer) {
+ free(zzip_memory_buffer);
+ }
+ /* Reset variables */
+ zzip_memory_reset();
+ /* Open file */
+ fd=open(pathname, flags);
+ if (fd<0) {
+ return(-1);
+ } else {
+ /* Get filesize */
+ if (fstat(fd, &stat_buffer)<0) {
+ return(-1);
+ }
+ if (stat_buffer.st_size<1) {
+ return(-1);
+ }
+ /* Store filesize */
+ zzip_memory_size = stat_buffer.st_size;
+ /* Allocate readbuffer */
+ zzip_memory_buffer = malloc(zzip_memory_blocksize);
+ /* Invalidate buffer block */
+ zzip_memory_bufferblock = -1;
+ /* Store file descriptor */
+ zzip_memory_fd=fd;
+ /* Return file descriptor */
+ return(fd);
+ }
+}
+
+ZZIP_memory int zzip_memory_close(int fd)
+{
+ /* Check file descriptor */
+ if (fd!=zzip_memory_fd) {
+ return(-1);
+ }
+ /* Clear any memory buffer that might be laying around */
+ if (zzip_memory_buffer) {
+ free(zzip_memory_buffer);
+ }
+ /* Reset variables */
+ zzip_memory_reset();
+ /* Close file */
+ return(close(fd));
+}
+
+ZZIP_memory off_t zzip_memory_lseek(int fildes, off_t offset, int whence)
+{
+ /* Check file descriptor */
+ if (fildes!=zzip_memory_fd) {
+ return(-1);
+ }
+ /* Change position pointer */
+ switch (whence) {
+ case SEEK_SET:
+ zzip_memory_pos=offset;
+ break;
+ case SEEK_CUR:
+ zzip_memory_pos += offset;
+ break;
+ case SEEK_END:
+ zzip_memory_pos = zzip_memory_size-1;
+ break;
+ }
+ /* Limit position to the last byte of the file */
+ if (zzip_memory_pos>(zzip_memory_size-1)) {
+ zzip_memory_pos=zzip_memory_size-1;
+ }
+ /* Return current position */
+ return(zzip_memory_pos);
+}
+
+/* -------- Control wrapper usage */
+
+
+zzip_plugin_io_t
+zzipwrap_use_memory_io(int blocksize,
+ zzipwrap_pfn_t callback, void *callbackdata)
+{
+ static const struct zzip_plugin_io zzip_memory_io =
+ {
+ (void *) zzip_memory_open,
+ (void *) zzip_memory_close,
+ (void *) zzip_memory_read,
+ (void *) zzip_memory_lseek,
+ (void *) zzip_filesize,
+ 0
+ };
+
+ /* Store blocksize and block-processing callback data */
+
+ zzip_memory_blocksize = blocksize;
+ zzip_memory_callback = callback;
+ zzip_memory_callbackdata = callbackdata;
+
+ return (zzip_plugin_io_t) &zzip_memory_io;
+}
+
diff --git a/Build/source/libs/zziplib/zzipwrap/wrap.h b/Build/source/libs/zziplib/zzipwrap/wrap.h
new file mode 100644
index 00000000000..e4f4f5b7efc
--- /dev/null
+++ b/Build/source/libs/zziplib/zzipwrap/wrap.h
@@ -0,0 +1,36 @@
+/*
+ * Author:
+ * Andreas Schiffler <aschiffler@appwares.com>
+ *
+ * Copyright (c) 2001 Andreas Schiffler
+ * All rights reserved,
+ * usage allowed under the restrictions of the
+ * Lesser GNU General Public License
+ */
+
+#ifndef _ZZIPWRAP_H
+#define _ZZIPWRAP_H
+
+#include <zzip/zzip.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * toggle alternate read routine and set callback and callback data
+ * return: a plugin_io pointer to be used
+ * with => zzip_opendir_ext_io or => zzip_open_ext_io and cousins
+ */
+typedef void (*zzipwrap_pfn_t)(void* mem, int blocksize, void* privatedata);
+_zzip_export
+zzip_plugin_io_t
+zzipwrap_use_memory_io(int blocksize, zzipwrap_pfn_t callback, void *callbackdata);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* _ZZIPWRAP_H */
+
diff --git a/Build/source/libs/zziplib/zzipwrap/zzipwrap.c b/Build/source/libs/zziplib/zzipwrap/zzipwrap.c
new file mode 100644
index 00000000000..447ce23f5b4
--- /dev/null
+++ b/Build/source/libs/zziplib/zzipwrap/zzipwrap.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2000,2001 Guido Draheim <guidod@gmx.de>
+ * Use freely under the restrictions of the ZLIB license.
+ *
+ * Modified by Andreas Schiffler, 2001, for the zzipwrap feature
+ * Modified by Guido Draheim in 2002 for the plugin_io feature
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h> /* exit */
+
+#include <zzip/zzip.h>
+/* #incl <zzip/wrap.h> */
+#include "wrap.h"
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static const char usage[] =
+{
+ "zzipwrap <dir>.. \n"
+ " - prints a content table to stdout, but the dir can also be a zip-arch."
+ "\n"
+ " To show the contents of a zip-archive named 'test.zip', you may write \n"
+ " zzipwrap test \n"
+};
+
+/* This is a demo block callback routine that has access to the buffer */
+/* that was just read BEFORE it is used by zziplib. */
+static void demo_block_callback (void *buffer, int buffersize, void *data)
+{
+ fprintf (stderr,
+ "demo_block_callback( buffer-pointer=%p"
+ " buffer-size=%i data='%s' )\n",
+ buffer,buffersize,(char*)data);
+}
+
+int
+main (int argc, char ** argv)
+{
+ zzip_plugin_io_t io;
+ int argn;
+
+ if (argc <= 1)
+ {
+ printf (usage);
+ exit(0);
+ }
+
+ /* Enable blocked (32 bytes) memory buffered IO routines with a */
+ /* demo callback routine. */
+ io = zzipwrap_use_memory_io(32, demo_block_callback,
+ (void*) "Some callback data");
+ if (! io)
+ {
+ fprintf(stderr, "could not initialize memory-io");
+ return 1;
+ }
+
+ for (argn=1; argn < argc; argn++)
+ {
+ ZZIP_DIR * dir;
+ ZZIP_DIRENT * d;
+
+ dir = zzip_opendir_ext_io(argv[argn], 0, 0, io);
+ if (! dir)
+ {
+ fprintf (stderr, "did not open %s:", argv[argn]);
+ perror(argv[argn]);
+ continue;
+ }
+
+ if (argc > 2) printf ("%s:\n", argv[argn]);
+
+ /* read each dir entry and show one line of info per file */
+ while ((d = zzip_readdir (dir)))
+ {
+ /* orignalsize / compression-type / compression-ratio / filename */
+ if (d->st_size > 999999)
+ {
+ printf ("%5dK %-9s %2d%% %s\n",
+ d->st_size>>10,
+ zzip_compr_str(d->d_compr),
+ 100 - (d->d_csize|1)/((d->st_size/100)|1),
+ d->d_name);
+ }else{
+ printf ("%6d %-9s %2d%% %s\n",
+ d->st_size,
+ zzip_compr_str(d->d_compr),
+ 100 - (d->d_csize|1)*100/(d->st_size|1),
+ d->d_name);
+ }
+ }
+
+ zzip_closedir(dir);
+ }
+
+ return 0;
+}
+
diff --git a/Build/source/libs/zziplib/zzipwrap/zzipwrap.pc b/Build/source/libs/zziplib/zzipwrap/zzipwrap.pc
new file mode 100644
index 00000000000..a22620f8aa4
--- /dev/null
+++ b/Build/source/libs/zziplib/zzipwrap/zzipwrap.pc
@@ -0,0 +1,10 @@
+prefix=/usr/local
+libdir=/usr/local/lib
+includedir=/usr/local/include
+
+Name: zzipwrap
+Version: 2006.0807
+Description: Callback Wrappers for ZZipLib
+Requires: zziplib
+Libs: -L${libdir} -lzzipwrap
+Cflags: -I${includedir}
diff --git a/Build/source/texk/web2c/Makefile.in b/Build/source/texk/web2c/Makefile.in
index 0ec24cdef95..bd687a9ac8f 100644
--- a/Build/source/texk/web2c/Makefile.in
+++ b/Build/source/texk/web2c/Makefile.in
@@ -1,4 +1,4 @@
-# $Id: //depot/Build/source.development/TeX/texk/web2c/Makefile.in#66 $
+# $Id$
# @configure_input@
# Makefile for web2c --kb@mail.tug.org. Public domain.
version = @WEB2CVERSION@
@@ -555,6 +555,7 @@ trip-clean:
#
# Helper makefile fragment for pdf*tex.
kpse_include pdftexdir/pdftexlib.mk
+#LUATEXkpse_include pdftexdir/luatexlib.mk
#
# Makefile fragments:
kpse_include etexdir/etex.mk
@@ -562,6 +563,7 @@ kpse_include omegadir/omega.mk
kpse_include alephdir/aleph.mk
kpse_include pdftexdir/pdftex.mk
kpse_include xetexdir/xetex.mk
+#LUATEXkpse_include luatexdir/luatex.mk
#
# non-engine programs.
@@ -575,7 +577,8 @@ programs = bibtex ctangle ctie cweave dvicopy dvitomp dvitype gftodvi gftopk \
engines = $(tex) $(etex) $(mf) $(mfn) $(metapost) \
$(omega) $(aleph) \
$(pdftex) $(pdfetex) \
- $(xetex)
+ $(xetex) #LUATEX\
+#LUATEX $(luatex)
programs: $(programs) $(engines) $(mpware_programs) \
$(omegafonts_programs) $(otps_programs) $(pdftosrc)
@@ -1125,7 +1128,7 @@ installcheck:
#
# Cleaning.
-all_subdirs = doc lib man $(mpware) web2c window $(omegafonts) $(otps) $(pdftexdir) $(mpostdir)
+all_subdirs = doc lib man $(mpware) web2c window $(omegafonts) $(otps) $(pdftexdir) $(mpostdir) #LUATEX $(luatexdir)
# Having a multiple-target rule with the subdir loop fails because of
# the dependencies introduced by clean.mk. Yet, we want the
diff --git a/Build/source/texk/web2c/luatexdir/.indent.pro b/Build/source/texk/web2c/luatexdir/.indent.pro
new file mode 100644
index 00000000000..e9e690f1ba8
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/.indent.pro
@@ -0,0 +1,12 @@
+/* $Id$ */
+--k-and-r-style
+--blank-lines-after-procedures
+--line-length 80
+--procnames-start-lines
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--space-after-cast
+/* this does not work in indent 2.2.6 :-( */
+--no-tabs
+/* this is new in indent 2.2.9 */
+--preprocessor-indentation 2
diff --git a/Build/source/texk/web2c/luatexdir/ChangeLog b/Build/source/texk/web2c/luatexdir/ChangeLog
new file mode 100644
index 00000000000..d6004e43700
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/ChangeLog
@@ -0,0 +1,69 @@
+2004-08-21 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * pdfetex.ch2: Adapted to e-TeX version 2.2.
+
+2004-08-26 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * pdfetexextra.in: File was renamed from pdftexextra.h; the
+ current pdfTeX and e-TeX versions are substituted from
+ ../pdftexdir/pdftex.version and ../etexdir/etex.version. Variant
+ of code supplied by Peter Breitenlohner <peb@mppmu.mpg.de>.
+
+ * pdfetex.mk: Added rule to insert pdfTeX and e-TeX versions into
+ pdfetexextra.h. Variant of code supplied by Peter Breitenlohner
+ <peb@mppmu.mpg.de>.
+
+2004-08-25 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * pdfetex.mk: vadjust.ch moved from pdfxtexdir to pdftexdir.
+
+2004-08-17 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * pdfetex.mk: Resurrected etex.fix, there is again a need to
+ include late-breaking changes.
+
+2004-07-29 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * pdfetex.ch[12]: Somewhat rearrange handling of kern and math
+ nodes in order to reduce interference between eTeX and pdfTeX
+ change files.
+
+ * pdfetex.ch1 (hlist_out): Keep full mixed direction typesetting
+ code.
+
+2004-07-25 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * pdfetex.ch[12]: Reorganize additional command codes for convert
+ and last_item in order to reduce interference between eTeX and
+ pdfTeX change files.
+
+2004-07-23 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * pdfetex.ch[12], tex.ch[01]: Reorganize handling of banner
+ string in order to reduce interference between eTeX, pdfTeX,
+ and web2c change files.
+
+2004-07-22 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * pdfetex.ch[12]: Removed unused token types for pdfTeX's
+ additional token list parameters.
+
+2004-07-19 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * pdfetex.ch[12], tex.ch0: Reorganize handling of additional
+ token list and integer parameters and e-TeX's additional
+ penalties in order to reduce interference between eTeX, pdfTeX,
+ and web2c change files.
+
+ * pdfetex.mk (pdfetex.ch): Remove tex.ch2 from build rules.
+
+ * tex.ch2: Removed.
+
+2004-07-17 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * pdfetex.mk: Rewrite build rules for pdfetex.{web,ch},
+ remove etex.{ch0,ch1,fix}, tex.ch2, and several non-dependencies.
+
+ * pdfetex.ch2: Adapt to eTeX changes.
+
+ * ChangeLog: New file.
diff --git a/Build/source/texk/web2c/luatexdir/Makefile.in b/Build/source/texk/web2c/luatexdir/Makefile.in
new file mode 100644
index 00000000000..a959a42d56b
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/Makefile.in
@@ -0,0 +1,141 @@
+# Makefile for libpdf - te@dbs.uni-hannover.de
+# $Id$
+
+kpse_include ../make/common.mk
+kpse_include ../make/programs.mk
+kpse_include ../make/library.mk
+
+kpathsea_srcdir_parent = $(srcdir)/../..
+kpathsea_dir_parent = ../..
+
+ALL_CXXFLAGS = @CXXFLAGS@ @DEFS@ $(XXCFLAGS) -I. -I$(srcdir) -I$(kpathsea_dir_parent) -I$(kpathsea_srcdir_parent) @LIBXPDFCPPFLAGS@ -I$(LIBOBSDCOMPATDIR) -I$(LIBOBSDCOMPATDIR)/.. -I$(LIBOBSDCOMPATFSRCDIR) -I$(LIBOBSDCOMPATFSRCDIR)/.. -I$(LIBPNGSRCDIR) -I$(ZLIBSRCDIR)
+CXX = @CXX@
+
+CTANGLE = ../ctangle
+
+.SUFFIXES: .cc .o
+.cc.o:
+ $(CXX) $(ALL_CXXFLAGS) -c $< -o $@
+
+# XCFLAGS=-Wstrict-prototypes -Wmissing-prototypes
+
+LIBPNGDIR=../../../libs/libpng
+LIBPNGSRCDIR=$(srcdir)/$(LIBPNGDIR)
+
+ZLIBDIR=../../../libs/zlib
+ZLIBSRCDIR=$(srcdir)/$(ZLIBDIR)
+
+LIBXPDFDIR=../../../libs/xpdf
+LIBXPDFSRCDIR=$(srcdir)/$(LIBXPDFDIR)
+
+LIBMD5DIR=../../../libs/md5
+LIBMD5SRCDIR=$(srcdir)/$(LIBMD5DIR)
+
+LIBOBSDCOMPATDIR=../../../libs/obsdcompat
+LIBOBSDCOMPATFSRCDIR=$(srcdir)/$(LIBOBSDCOMPATDIR)
+
+XCPPFLAGS=-I.. -I$(srcdir)/.. -I../.. -I$(srcdir)/../.. -I$(LIBMD5DIR) \
+ -I$(LIBMD5SRCDIR) @LIBPNGCPPFLAGS@ @ZLIBCPPFLAGS@ \
+ -I$(LIBXPDFDIR) -I$(LIBXPDFDIR)/.. -I$(LIBXPDFSRCDIR) -I$(LIBXPDFSRCDIR)/.. \
+ -I$(LIBOBSDCOMPATDIR) -I$(LIBOBSDCOMPATDIR)/.. -I$(LIBOBSDCOMPATFSRCDIR) \
+ -I$(LIBOBSDCOMPATFSRCDIR)/.. -DpdfTeX
+
+
+OBJS = \
+avl.o \
+avlstuff.o \
+font/mapfile.o \
+font/pkin.o \
+font/subfont.o \
+font/tounicode.o \
+font/vfpacket.o \
+font/writeenc.o \
+font/writefont.o \
+font/writet1.o \
+font/writet3.o \
+font/writettf.o \
+font/writetype0.o \
+font/writetype2.o \
+font/writecff.o \
+font/tt_glyf.o \
+font/tt_table.o \
+font/sfnt.o \
+font/texfont.o \
+font/tfmofm.o \
+font/vfovf.o \
+font/luafont.o \
+font/dofont.o \
+image/epdf.o \
+image/pdftoepdf.o \
+image/writeimg.o \
+image/writejbig2.o \
+image/writejpg.o \
+image/writepng.o \
+lua/loslibext.o \
+lua/lcallbacklib.o \
+lua/lkpselib.o \
+lua/llualib.o \
+lua/lnodelib.o \
+lua/lpdflib.o \
+lua/lstatslib.o \
+lua/ltexiolib.o \
+lua/ltexlib.o \
+lua/ltokenlib.o \
+lua/lfontlib.o \
+lua/texluac.o \
+lua/luainit.o \
+lua/luastuff.o \
+lua/luatex.o \
+lua/luatoken.o \
+lua/luanode.o \
+lua/llanglib.o \
+lua/limglib.o \
+lua/mp.o \
+lua/psout.o \
+lua/lmplib.o \
+lang/hnjalloc.o \
+lang/hyphen.o \
+lang/texlang.o \
+tex/linebreak.o \
+tex/postlinebreak.o \
+tex/texnodes.o \
+tex/textoken.o \
+tex/texpdf.o \
+managed-sa.o \
+mathcodes.o \
+textcodes.o \
+utils.o \
+writezip.o
+
+all: libpdf.a makecpool
+
+libpdf.a: lua/mp.c lua/psout.c $(OBJS)
+ rm -f $@
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+ $(RANLIB) $@
+
+lua/mp.c: lua/mp.w
+ $(CTANGLE) $(srcdir)/lua/mp.w - lua/mp.c
+
+lua/psout.c: lua/psout.w
+ $(CTANGLE) $(srcdir)/lua/psout.w - lua/psout.c
+
+makecpool: makecpool.o
+ $(link_command) makecpool.o
+
+kpse_include ../make/clean.mk
+
+clean::
+ rm -f libpdf.a ttf2afm pdftosrc
+
+depend:
+ rm -f $(OBJS) $(srcdir)/depend.mk
+ for a in $(OBJS); do \
+ env XXCFLAGS="-MM -MT \$$@" XCFLAGS="-MM -MT \$$@" $(MAKE) -k $$a; \
+ touch $$a; \
+ grep -a -v "^$(CC)\|$(CXX)\|$(AR)\|make\|klibtool" $$a | \
+ sed 's: [^ ]*/\.\./libs/[^ ]*::g' >> $(srcdir)/depend.mk; \
+ done; \
+ rm -f $(OBJS)
+
+kpse_include luatexdir/depend.mk
diff --git a/Build/source/texk/web2c/luatexdir/NEWS b/Build/source/texk/web2c/luatexdir/NEWS
new file mode 100644
index 00000000000..626b5c95a0b
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/NEWS
@@ -0,0 +1,537 @@
+---------------------------------------------------------------
+pdfTeX 3.141592-1.40.0-beta-20060811 was released on 2006-08-11
+---------------------------------------------------------------
+- renamed primitives:
+ \primitive -> \pdfprimitive
+ \ifprimitive -> \ifpdfprimitive
+ \ifabsdim -> \ifpdfabsdim
+ \ifabsnum -> \ifpdfabsnum
+- new version of \primitive/\ifprimitive (but see above)
+- new dimen: \pdfpxdimen
+- support for jbig2 files
+- new library: obsdcompat, which has improved string functions and allows the
+ use of __attribute__
+- update libpng to 1.2.12
+- added JFIF detection patch to writejpg.c (was bug 548)
+- bugfix: truetype OS/2 v3 fonts (594)
+- bugfix: file with only \immediate\pdfobj stream results in garbage (505)
+- bugfix: invalid pdf created if font name contains space (509)
+
+---------------------------------------------------------------
+pdfTeX 3.141592-1.40.0-beta-20060725 was released on 2006-07-25
+---------------------------------------------------------------
+- added patches by Christian Schenk forwarded by Hartmut
+- added patch 421 (popen) from Taco
+- added lots of (void) to writettf* and ttf2afm to silence the compiler
+- removed some unused variables from tounicode.c
+- add new code by Thanh (patch 580)
+- added security patch for xpdf :-(
+- added JFIF detection patch to writejpg.c (bug 548)
+
+---------------------------------------------------------------
+pdfTeX 3.141592-1.40.0-beta-20060213 was released on 2006-02-13
+---------------------------------------------------------------
+- pdftex.web has been improved a bit
+- new patch:
+ - 473 \ifabsnum and \ifabsdim
+- the manual has been updated a bit and is again included
+
+---------------------------------------------------------------
+pdfTeX 3.141592-1.40.0-beta-20060125 was released on 2006-01-25
+---------------------------------------------------------------
+- pdfTeX now includes pdfeTeX, i.e. there is no way to make a binary without
+ eTeX support. Also the sources of TeX, eTeX and pdfTeX have been merged into
+ one file pdftex.web
+- most pdfTeX change files are gone; only one file (pdftex.ch) remains.
+- improved patches:
+ - 393 Ensure newline before endstream
+
+---------------------------------------------------------------
+pdfTeX 3.141592-1.40.0-beta-20060117 was released on 2006-01-17
+---------------------------------------------------------------
+- pdfTeX is now pdfeTeX, i.e. there is no way to make a binary without eTeX
+ support. Also the sources of TeX, eTeX and pdfTeX have been merged into one
+ file pdfetex.web
+- strip trailing zeros in fractions of reals written
+- removed patch 467 \ifindef
+- improved logging of objstreams
+
+----------------------------------------------------------------
+pdfTeX 3.141592-1.40.0-alpha-20060111 was released on 2006-01-11
+----------------------------------------------------------------
+- new patches:
+ - 466 \primitive and \ifprimitive
+ - 467 \ifinedef
+- improved patches:
+ - 393 Ensure newline before endstream
+- pdfTeX now sets /ModDate and /Trapped by default (the values can be
+ overridden with /pdfinfo)
+- more fixes to remove warnings from -Wall
+
+----------------------------------------------------------------
+pdfTeX 3.141592-1.40.0-alpha-20060106 was released on 2006-01-06
+----------------------------------------------------------------
+- many small fixes to remove warnings from -Wall
+- removed some unused variables
+- really fix bug 444
+- add some GCC extensions and use *nprintf instead of *printf where possible
+- fixed a unicode bug in ttf2afm
+
+----------------------------------------------------------------
+pdfTeX 3.141592-1.40.0-alpha-20051226 was released on 2005-12-26
+----------------------------------------------------------------
+- improved patches:
+ - 453 Object Streams for PDF-1.5
+ - take PK resolution from "pk_dpi" parameter in texmf.cnf, if it has not
+ been set by the format file or by the user
+ - 432 Rules in a PDF qQ group
+- some fixes for Thanhs patch
+- some improvements from -Wall
+- .indent.pro for indent
+
+----------------------------------------------------------------
+pdfTeX 3.141592-1.40.0-alpha-20051221 was released on 2005-12-21
+----------------------------------------------------------------
+- has a large patch from Thanh
+- pdflastlink has been fixed
+- remove generated pdf in case of fatal error
+
+----------------------------------------------------------------
+pdfTeX 3.141592-1.40.0-alpha-20051208 was released on 2005-12-08
+----------------------------------------------------------------
+- improved patches:
+ - 386 grow obj_tab and dest_names arrays dynamically
+ - 453 Object Streams for PDF-1.5
+ - take PK resolution from "pk_dpi" parameter in texmf.cnf, if it has not
+ been set by the format file or by the user
+- write out PDF statistics later to make them correct
+- makefile target pdfetex-all.pdf for a huge file
+
+----------------------------------------------------------------
+pdfTeX 3.141592-1.40.0-alpha-20051205 was released on 2005-12-05
+----------------------------------------------------------------
+- has these patches:
+ - 386 grow obj_tab and dest_names arrays dynamically
+ - 416 new primitive pdflastlink
+ - 427 Character positioning patch
+ - 432 Rules in a PDF qQ group
+ - 434 Remove queued map item handling
+ - 438 \pdfsavepos in DVI mode
+ - 443 512 zeros in Type1 fonts not copied anymore
+ - 447 Don't write /Encoding for non-reencoded fonts
+ - 453 Object Streams for PDF-1.5
+ - take PK resolution from "pk_dpi" parameter in texmf.cnf, if it has not
+ been set by the format file or by the user
+
+-------------------------------------------------
+pdfTeX 3.141592-1.30.6 was released on 2006-02-16
+-------------------------------------------------
+- bugfix: updated xpdf to 3.01pl2
+
+-------------------------------------------------
+pdfTeX 3.141592-1.30.5 was released on 2005-12-04
+-------------------------------------------------
+- bugfix: \pdfximage prints the file name twice (bug 441)
+- bugfix: buffer overflow with \pdfmatch (bug 444)
+- bugfix: updated xpdf to 3.01pl1
+
+-------------------------------------------------
+pdfTeX 3.141592-1.30.4 was released on 2005-10-17
+-------------------------------------------------
+- bugfix: whitespaces in filenames didn't work on Unix anymore (bug 377)
+- bugfix: two \immediates cancel themselves (bug 437)
+- bugfix: wrong file name in error messages of image inclusion (bug 435)
+
+-------------------------------------------------
+pdfTeX 3.141592-1.30.3 was released on 2005-09-04
+-------------------------------------------------
+- bugfix: \write18
+
+-------------------------------------------------
+pdfTeX 3.141592-1.30.2 was released on 2005-08-25
+-------------------------------------------------
+- fixed some build problems and minor bugs introduced in 1.30.1
+
+-------------------------------------------------
+pdfTeX 3.141592-1.30.1 was released on 2005-08-21
+-------------------------------------------------
+- the eTeX extensions can now be enabled with the cmdline switch -etex
+- pdfTeX uses xpdf 3.01
+
+-------------------------------------------------
+pdfTeX 3.141592-1.30.0 was released on 2005-08-01
+-------------------------------------------------
+- pdfxtex (introduced with 1.20a) is gone; all extensions are now in pdf(e)tex.
+- Some primitives have been renamed; the old names will still work, but are
+ deprecated and some give a warning that they are obsolete:
+ \pdfoptionpdfminorversion -> \pdfminorversion
+ \pdfoptionalwaysusepdfpagebox -> \pdfforcepagebox
+ \pdfoptionpdfinclusionerrorlevel -> \pdfinclusionerrorlevel
+- pdftex knows two new units:
+ - new Didot (1nd=0.375mm)
+ - new Cicero (1nc=12nd)
+- New primitives:
+ - Inclusion of pngs has been greatly improved: It now does
+ - alpha channel and transparency (only if %!PDF >=1.4)
+ - 16-bit colour (only if %!PDF >=1.5); this must be enabled by setting
+ \pdfimagehicolor to 1.
+ - gamma correction; this must be enabled by setting \pdfimageapplygamma to
+ 1. The device gamma is taken from \pdfgamma. If no embedded value can be
+ found in the png image, then the value of \pdfimagegamma is used instead.
+ - fast direct embedding of png streams, if their structure allows this; the
+ automatic fall-back is to decompress and re-compress as before.
+ - pdfTeX now has an interface to the precise system time (if available) as an
+ aid in benchmarking TeX macro code.
+ - \pdfelapsedtime is a read-only integer that (initially) returns the
+ amount of time passed since the start of this run. This amount is given
+ in `scaled seconds': the value 65536 counts as one second. If more time
+ has passed than 32767 seconds, (2^31)-1 will be returned.
+ - \pdfresettimer updates the internal timer, such that subsequent calls to
+ \pdfelapsedtime will restart from 0.
+ - pdfTeX can now generate random numbers:
+ - \pdfuniformdeviate <count> generates a uniformly distributed random
+ integer value between 0 (inclusive) and <count> (exclusive).
+ - \pdfnormaldeviate expands to a random integer value with a mean of 0 and
+ a unit of 65536.
+ - \pdfrandomseed allows access to the current seed value.
+ - \pdfsetrandomseed <count> sets the random seed to a specific value.
+ - \pdfnoligatures\f disables ligatures for the loaded font \f.
+ - Escaping strings:
+ - \pdfescapestring{<a>} escapes the string <a> so that it can be used as
+ PDF string.
+ - \pdfescapename{<a>} escapes the string <a> so that it can be used as PDF
+ name.
+ - \pdfescapehex{<a>} converts the string <a> to uppercase hexadecimal
+ representation.
+ - \pdfunescapehex{<b>} reverses the effect of \pdfescapehex
+ - \pdfcreationdate expands to the date string that pdfTeX uses in the info
+ dict as default.
+ - \pdffilemoddate{<file>} expands to the modification date of <file> in the
+ same format as \pdfcreationdate (PDF date format).
+ - \pdffilesize{<file>} expands to the size of <file> as string.
+ - \pdfmdfivesum{<abc>} or \pdfmdfivesum file {<file>} calculates the md5
+ sum (of a string or a file) and converts it to uppercase hexadecimal format
+ (same as \pdfescapehex).
+ - \pdffiledump [offset <int>] [length <int>] <general text>
+ Expands to a hex dump of the file given in <general text>, starting at
+ given offset or 0 with given length.
+ - \pdfshellescape is a read-only integer that is 1 if \write18 is enabled, 0
+ otherwise.
+ - \pdfxformname <object number>, which expands to the number in the
+ corresponding form XObject name.
+ - \leftmarginkern <box number> and \rightmarginkern <box number> tell the
+ margin kern at the left and right side of the horizontal list stored in box
+ <box number>.
+ - \pdfpkmode is a token register that sets the MF mode for pixel font
+ generation. The contents of this register is dumped into the format, so one
+ can (optionally) preset it e.g. in part of pdftexconfig.tex.
+ - \pdftracingfonts: An integer variable controlling the tracing of font
+ expansion. It is zero by default; then we get a log (with fontexpansion)
+ like this
+ ...\tenrm t
+ ...\tenrm (+20) e
+ Without font expansion, this default should be compatible with TeX's
+ original log output.
+ If \pdftracingfonts is set to 1 (or greater), we get a more verbose log:
+ ...\xivtt (cmtt10@14.0pt) t
+ ...\xivtt (cmtt10+20@14.0pt) e
+ See also bug 304.
+- New experimental primitives:
+ - \pdfmatch [icase] [subcount <number>}] {<pattern>}{<string>}
+ Implements pattern matching using the POSIX regex.
+ It returns the same values as \pdfstrcmp, but with the following semantics:
+ -1: error case (invalid pattern, ...)
+ 0: no match
+ 1: match found
+ Options:
+ * icase: case insensitive matching
+ * subcount: it sets the table size for found subpatterns.
+ A number "-1" resets the table size to the start default.
+ - \pdflastmatch <number>
+ The result of \pdfmatch is stored in an array. The entry "0" contains the
+ match, the following entries submatches. The positions of the matches are
+ also available. They are encoded:
+ <position> "->" <match string>
+ The position "-1" with an empty string indicates that this entry is not
+ set.
+ - \pdfstrcmp{<a>}{<b>} compares two strings and returns the strings "0" if
+ <a> equals <b>, "-1" if <a> is less than <b>, "1" if <a> is greater than
+ <b>
+- The primitive \pdfmovechars has been removed (bug 294)
+- Bugfixes:
+ - empty strings are not supressed anymore (bug 335)
+ - \unhboxing and character protusion didn't work well together (bug 292)
+ - --jobname didn't work if there was no filename at all (bug 302)
+ - Some problem with fonts on solaris (bug 315)
+ - Dangling font objects with non-replacable fonts (bug 311).
+ - \pdfxform didn't work with box>255 (bug 310)
+ - cmap: unicode ???? is mapped to multiple glyphs (bug 306).
+- pdfTeX uses zlib 1.2.3
+
+------------------------------------------------
+pdfTeX 3.141592-1.21a was released on 2005-02-04
+------------------------------------------------
+- ttf2afm 1.0:
+ - added support for refering to glyphs via unicode in encoding files (ie 'uniXXX')
+ - added some more info to the AFM output
+ - some minor bug fixes
+ - a short documentation available
+- pdftex now understand forms 'uniXXXX' in encoding files (only makes sense
+ with TrueType fonts)
+- added subset tag for TrueType fonts
+- PDF strings are now printed as following:
+ (This is a string) -> (This is a string)
+ This is a string -> (This is a string)
+ <a1b245c1a2...> -> <a1b245c1a2...>
+- check for double newline char to get rid of empty lines in PDF output
+- Fixed a bug in the scanning of map lines introduced in the fix of bug #242 in
+ 1.20b.
+- Fixed three problems in xpdf; xpdf is now 3.00pl3
+- \ifeof18 is a simple method to test if \write18 is enabled.
+- a few extensions in pdfxtex:
+ - \pdflastximagecolordepth returns the last color depth
+ - \pdfximage supports a keyword "colorspace" following an object number
+ representing a ColorSpace object
+ - \pdfstrcmp compares two strings
+ - \pdfescapestring/\pdflastescapedstring provide a way to escape string
+ - \pdffirstlineheight/\pdflastlinedepth/\pdfeachlineheight/\pdfeachlinedepth
+ allow fixing line dimen
+ - patches from Taco
+ - px dimen unit
+ - tagcode patch
+ - quitvmode patch
+
+------------------------------------------------
+pdfTeX 3.141592-1.20b was released on 2004-12-22
+------------------------------------------------
+- Fixed some minor bugs, mostly with hz
+- The info line "output format initialized to PDF/DVI" isn't shown anymore, as
+ this info wasn't reliable (bug 112).
+- Now the PDF-related statistics (PDF objects...) in the .log file is only
+ shown in PDF output mode. It start with a line "PDF statistics:".
+- \pdfimageresolution is not limited to 2400 [dpi] anymore, can now be between
+ 0 and 65535 [dpi].
+- pdfTeX uses xpdf 3.00pl2
+- pdfTeX uses libpng 1.2.8, which fixes some png-related bugs.
+
+------------------------------------------------
+pdfTeX 3.141592-1.20a was released on 2004-09-06
+------------------------------------------------
+- There is a new program pdfxtex, which contains experimental features which
+ might end up in pdftex in the future.
+- Most distributions now use eTeX as the default engine, so when you call
+ pdftex you will get pdfeTeX. Most distributions now also use pdfTeX as the
+ default engine, so when you call latex you will get pdfeTeX running LaTeX.:-)
+- We are setting up pdfTeX as a project at sarovar
+ (http://sarovar.org/projects/pdftex/). Please report bugs etc. through the
+ site.
+- Support for the file pdftex.cfg is gone completely. All parameters that had
+ previously been set by it can be set through primitives; their values are
+ dumped to the format file.
+- The searchpath for encoding and mapfiles has been changed.
+ See http://tug.org/pipermail/tex-live/2004-January/004734.html and
+ http://tug.org/pipermail/tex-live/2004-January/004791.html
+- eTeX is now version 2.2, incorporating the last changes to TeX (3.141592).
+- New options for \pdfmapfile:
+ General functionality: Map items (map files, new: also single map lines; see
+ \pdfmapline) are put in list of pending map items. During the next shipout,
+ pending map items are sequentially scanned for their map entries, and an
+ internal map entry database is updated, using the modes below. Then the list
+ of pending map items is cleared. Map entries of fonts already in use are left
+ untouched. New: All \pdfmapfile and \pdfmapline commands can also be given
+ after shipout of the first page.
+ - \pdfmapfile {foo.map} clears the list of pending map items and starts a new
+ list with the only pending file foo.map. When the map entry lines of
+ foo.map are scanned, duplicate map entries are ignored and a warning is
+ issued. This is the old behaviour.
+ - \pdfmapfile {+foo.map} puts foo.map in the list of pending map items. When
+ the map entry lines of foo.map are scanned, duplicate map entries are
+ ignored and a warning is issued.
+ - \pdfmapfile {=foo.map} puts foo.map in the list of pending map items. When
+ foo.map is scanned, matching map entries in database are replaced by new
+ entries from foo.map.
+ - \pdfmapfile {-foo.map} puts foo.map in the list of pending map items. When
+ foo.map is scanned, matching map entries are deleted from database.
+ - \pdfmapfile {} clears the list of pending map items. It does not affect map
+ entries already registered into the database. This is the old behaviour.
+- New command \pdfmapline {line}. It's like \pdfmapfile but here you can set
+ single map lines like in the map files directly. The modifiers (+-=) have the
+ same effect as with \pdfmapfile.
+- Simplified the handling of the 14 Type 1 "standard fonts" (Times,
+ Helvetica...): They are now more or less handled like any other Type 1 font.
+ See http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000648.html
+- hz: So far the font expansion feature required that the user must be able to
+ create expanded tfms (eg cmr10+10.tfm). Now font expansion can be used
+ without creating these tfms.
+ See http://www.ntg.nl/pipermail/ntg-pdftex/2004-May/000504.html
+- hz: Changed \pdffontexpand primitive --> the expand factor is now fixed to
+ 1000 and the argument is ignored. This will lead to spurious texts of "1000"
+ in your output if you compile old documents.
+- New command \pdftexbanner which returns a string with the full banner of the
+ current binary (e.g. "This is pdfTeX, Version 3.141592-1.20a (Web2C 7.5.3)
+ kpathsea version 3.5.3")
+- The PTEX.FullBanner key is now inserted in the document info dict instead of
+ the catalog. Newer versions of Acrobat display it.
+- Now includes support for encTeX.
+- Extended \pdfannot to use reserveobjnum/useobjnum
+ See http://www.ntg.nl/pipermail/ntg-pdftex/2004-March/000424.html
+- Bugfix: pdfTeX would read an .xpdfrc when including pdfs.
+ See http://tug.org/pipermail/pdftex/2004-March/004835.html
+- Bugfix: The strings in /ID would sometimes be empty.
+- Bugfix: Even when mapfiles or encodings or PostScript font files were
+ missing, pdfTeX still produced a (most often corrupt) pdf. Now it aborts with
+ an error in these cases.
+- numerous small bugfixes.
+- pdfTeX now uses the GNU libavl from Ben Pfaff for managing of fontmap
+ entries.
+- pdfTeX uses zlib 1.2.1
+- pdfTeX uses xpdf 3.00
+- pdfTeX uses libpng 1.2.7
+
+------------------------------------------------
+pdfTeX 3.141592-1.11b was released on 2003-10-06
+------------------------------------------------
+- Bugfix: The handling of /Rotate produced displaced images when /Rotate was 90
+ or 270.
+
+------------------------------------------------
+pdfTeX 3.141592-1.11a was released on 2003-08-02
+------------------------------------------------
+- New command \pdftrailer analogue to \pdfcatalog whose argument ends up in the
+ trailer dictionary.
+- The behaviour when an included pdf has a newer version than the one specified
+ with \pdfoptionpdfminorversion can be controlled by the new internal integer
+ \pdfoptionpdfinclusionerrorlevel: If it's 0, pdfTeX gives only a warning; if
+ it's 1, it raises an error.
+ This can also be set in pdftex.cfg with pdf_inclusion_errorlevel
+- The syntax for outlines has been extended to allow attributes:
+ <outline spec> --> <attr spec> <action spec> [count <number>] <general text>
+ See http://www.ntg.nl/pipermail/ntg-pdftex/2003-June/000165.html
+- The syntax of \pdfobj has been extended:
+ \pdfobj <object type spec> (h, v, m)
+ <object type spec> --> reserveobjnum
+ | [useobjnum <number>] [<attr spec>] [stream [<attr spec>]] <object contents>
+ <object contents> --> <file spec>
+ | <general text>
+ When the optional keyword `reserveobjnum' and `useobjnum' is not given, the
+ behaviour is unchanged.
+ See also http://tug.org/mailman/htdig/pdftex/2003-March/003814.html
+- Bugfix: /CreationDate didn't care for the timezone and could be fooled.
+ See http://www.ntg.nl/pipermail/ntg-pdftex/2003-July/000223.html
+- Bugfix: The translation of 8-bit characters in included pdfs that had their
+ eighth bit set sometimes got wrong because of a missing typecast.
+ See http://www.ntg.nl/pipermail/ntg-pdftex/2003-July/000216.html
+- Bugfix: pdfTeX -ini would crash with a minimal file because it didn't read
+ it's config and so didn't know anything about fonts.
+ See http://tug.org/pipermail/pdftex/2003-July/004262.html
+- Bugfix: \pdfstartlink would produce spurious /NewWindow entries. Also the
+ syntax of <action spec> and <goto-action spec> has been cleaned up.
+ See http://www.ntg.nl/pipermail/ntg-pdftex/2003-June/000167.html
+- Bugfix: \pdffontattr was not used for T3 fonts.
+ See http://tug.org/pipermail/pdftex/2003-June/004127.html
+- Bugfix: The cropbox of an included pdf would sometimes not be used.
+ See http://tug.org/pipermail/pdftex/2003-May/004037.html
+- pdfTeX uses xpdf 2.02
+
+------------------------------------------------
+pdfTeX 3.141592-1.10b was released on 2003-02-26
+------------------------------------------------
+- The numbers in transformation matrices are allways written with maximum
+ precision (see http://tug.org/pipermail/pdftex/2003-February/003596.html).
+- Incorporated the new version of TeX: 3.141592
+- Bugfix: Numbers in pdfs would sometimes be just a wee bit of (changed
+ implementation of pdftoepdf.convertNumToPDF).
+- Bugfix: When setting the /Producer, /Creator or /CreationDate keys with
+ /pdfinfo pdfTeX would also insert default values which caused duplicate keys
+ in the info dict (see
+ http://tug.org/pipermail/pdftex/2003-February/003524.html).
+- The reading of mapfiles is much faster (see
+ http://tug.org/pipermail/pdftex/2002-July/002843.html).
+- Bugfix: AR5 had problems with the CTM when displaying in "fit visible" mode
+ (see http://tug.org/pipermail/pdftex/2002-May/002688.html).
+- Bugfix: str_in_str had wrong indices (see
+ http://tug.org/pipermail/pdftex/2002-March/002367.html).
+- Bugfix: decimal_digits defaulted to 0, which caused problems with included
+ images when including pdfs (see
+ http://tug.org/pipermail/pdftex/2003-February/003518.html).
+ It now defaults to 4.
+- Bugfix: the type of included images was decided based only on the extensions;
+ now pdfTeX looks for magic bytes at the start of files (see
+ http://tug.org/pipermail/pdftex/2003-February/003519.html)
+
+-----------------------------------------------
+pdfTeX 3.14159-1.10a was released on 2003-01-16
+-----------------------------------------------
+- pdfTeX is now able to produce pdf1.4 (which is also the default) and has
+ almost complete support for including pdf1.4 files:
+ - Additional attributes like MetaData are copied from included pdfs.
+ - Currently the Page Group attribute (see sections 7.3.6 and 7.5.5 of the pdf
+ 1.4 reference) of included pdfs is NOT copied (as we don't know how to
+ handle this when imposing pdfs).
+ This means including pdfs with transparency features will work as long as
+ the included pdf doesn't use Page Groups; if it does, the result might not
+ be what is expected (One application known to use Page Groups is Adobe
+ Illustrator v9++). The distributed pdfTeX binaries will give a warning
+ about any occurance of a Page Group in an included pdf and ignore the Page
+ Group (thus producing syntactically correct pdfs but probably not the
+ intended output).
+ Acrobat 5++ and newer versions of Jaws display files without Page Groups
+ correctly, so this might not really be a problem.
+ See pdftoepdf.cc for preprocessor flags which allow this behaviour to be
+ changed (copying the Page Group (most likely producing incorrect pdf) or
+ treating Page Groups as errors).
+- The new primitive \pdfoptionpdfminorversion sets the pdf version of the
+ generated file and the latest allowed pdf version of included pdfs:
+ \pdfoptionpdfminorversion=3
+ tells pdfTeX to set the pdf version to 1.3 and allows only included pdfs with
+ versions <= 1.3 .
+ The default for \pdfoptionpdfminorversion is 4 for pdf 1.4
+ This must appear before any data is written to the generated pdf file, so
+ you should put it at the very start of your files.
+ This can also be set in pdftex.cfg with pdf_minorversion
+- It is now possible to specify the pdf page box to use when including pdfs.
+ The syntax has been extended:
+ \pdfximage [<image attr spec>] <general text> (h, v, m)
+ <image attr spec> --> [<rule spec>] [<attr spec>] [<page spec>] [<pdf box spec>]
+ <pdf box spec> --> mediabox|cropbox|bleedbox|trimbox|artbox
+ The default is cropbox (which defaults to mediabox), to be compatible with
+ previous versions of pdfTeX.
+ The page box specified at \pdfximage can be globally overridden with the
+ config parameter always_use_pdfpagebox and the command
+ \pdfoptionalwaysusepdfpagebox <integer>, where 0 is the default (use whatever
+ is specified with \pdfximage), 1 is media, 2 is crop, 3 is bleed, 4 is trim
+ and 5 is artbox. This can only be set once per object, i.e. the value used at
+ \pdfximage is remembered.
+ See the pdf reference for an explanation of the boxes.
+- The support for the inclusion of jpeg images has been extended to allow the
+ inclusion of JPEG/Exif files which are produced by digital photo cameras
+ (thanks to Hartmut Henkel).
+- The support for the inclusion of tif images has been removed as it was of
+ limited use (it worked only for gray-scale and rgb images) and produced wrong
+ results (all other images types where treated as rgb images).
+ Tif images can be converted on *nix on-the-fly to pngs with the help of
+ ImageMagick, epstopdf.sty or pdftex.def v0.4 or newer, and this rule:
+ \DeclareGraphicsRule{.tif}{png}{.png}{`convert #1 `basename #1 .tif`.png}
+- The extensions for pdf encryption have been removed, since they make the
+ pdfTeX code overly complex. Those needing pdf encryption are encouraged to
+ produce a standalone program for encrypting pdfs.
+- pdfTeX now writes a usage statistic about the pdfTeX specific memory to the
+ log.
+- numerous bugfixes, most of them in the inclusion of pdfs.
+- pdfTeX uses xpdf 2.01
+- pdfTeX uses libpng 1.2.5
+
+---------------------------------------------------------------------
+pdfTeX 3.14159-1.00a-pretest-20011127-ojmw was released on 2002-01-29
+---------------------------------------------------------------------
+
+----------------------------------------------------------------
+pdfTeX 3.14159-1.00a-pretest-20010806 was released on 2001-08-06
+----------------------------------------------------------------
+
+----------------------------------------------------------------
+pdfTeX 3.14159-1.00a-pretest-20010804 was released on 2001-08-04
+----------------------------------------------------------------
+
+$Id$
+// vim: tw=79:ts=2:expandtab:autoindent
diff --git a/Build/source/texk/web2c/luatexdir/README b/Build/source/texk/web2c/luatexdir/README
new file mode 100644
index 00000000000..f1e142f1b25
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/README
@@ -0,0 +1,87 @@
+pdfTeX
+======
+
+README for version 3.14159-1.40.0-beta-20060811
+===============================================
+
+This directory contains the version 1.40.0-alpha-20060811 of pdfTeX, an
+extended version of eTeX that can create PDF directly from TeX source files
+and enhance the result of TeX typesetting with the help of PDF. When PDF
+output is not selected, pdfTeX produces normal DVI output, otherwise it
+produces PDF output that looks identical to the DVI output. An important
+aspect of this project is to investigate alternative justification
+algorithms, optionally making use of multiple master fonts.
+
+pdfTeX is based on the original eTeX sources and Web2c, and has been
+successfully compiled on Unix, Win32 and DOS systems. It is still under
+development and features may change; it produces reasonable PDF code.
+
+See the file NEWS for changes to the program.
+
+Documentation about pdfTeX can be found at http://www.pdftex.org
+
+There is also a mailing list on pdfTeX; go to
+http://tug.org/mailman/listinfo/pdftex for more information about it. Its
+searchable archive can be found at http://tug.org/pipermail/pdftex/
+Please read http://www.catb.org/~esr/faqs/smart-questions.html before
+asking any questions on the pdfTeX mailing list.
+
+A mailing list for the developement of pdfTeX can be found at
+http://www.ntg.nl/mailman/listinfo/ntg-pdftex
+
+
+LEGAL ISSUES
+============
+
+pdfTeX is copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+pdfTeX is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+pdfTeX is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+details.
+
+You should have received a copy of the GNU General Public License along
+with pdfTeX; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+pdfTeX uses code from TeX; for these parts the original copyright by Don
+Knuth applies. See the source files for details.
+
+pdfeTeX uses code from eTeX; for these parts the original copyright by
+Peter Breitenlohner applies. See the source files for details.
+
+
+WHAT TO DO IF YOU BELIEVE YOU HAVE FOUND A BUG IN pdfTeX
+========================================================
+
+Please read http://www.chiark.greenend.org.uk/~sgtatham/bugs.html and
+follow the guidelines there. Then go to the sarovar site of pdfTeX
+(http://sarovar.org/projects/pdftex/) and submit your bug report there.
+Here you can also report feature requests or patches.
+
+
+CONTRIBUTORS
+============
+
+Peter Breitenlohner, Ricardo Sanchez Carmenes, Otfried Cheong, Thomas
+Esser, Hans Hagen, Hartmut Henkel, Taco Hoekwater, Pawel Jackowski, Tom
+Kacvinsky, Akira Kakuto, Reinhard Kotucha, Derek B. Noonburg, Heiko
+Oberdiek, Jiri Osoba, Fabrice Popineau, Sebastian Rahtz, Tomas Rokicki,
+Martin Schröder, Petr Sojka, Ralf Utermann, Olaf Weber, Jiri Zlatuska.
+
+pdfTeX is built on top of TeX, written by Donald Knuth cum suis (Liang and
+so), and eTeX, written by Peter Breitenlohner cum suis; part of the
+paragraph optimization is inspired by the work of Hermann Zapf.
+
+
+------------------------------------------------------------------------------
+
+Please send bug reports, offers of help, etc. to martin@pdftex.org
+
+$Id$
+// vim: tw=75
diff --git a/Build/source/texk/web2c/luatexdir/avl.c b/Build/source/texk/web2c/luatexdir/avl.c
new file mode 100644
index 00000000000..a25239e8d93
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/avl.c
@@ -0,0 +1,893 @@
+/* Produced by texiweb from libavl.w. */
+
+/* libavl - library for manipulation of binary trees.
+ Copyright (C) 1998-2002, 2004 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The author may be contacted at <blp@gnu.org> on the Internet, or
+ write to Ben Pfaff, Stanford University, Computer Science Dept., 353
+ Serra Mall, Stanford CA 94305, USA.
+*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "avl.h"
+
+/* Creates and returns a new table
+ with comparison function |compare| using parameter |param|
+ and memory allocator |allocator|.
+ Returns |NULL| if memory allocation failed. */
+struct avl_table *
+avl_create (avl_comparison_func *compare, void *param,
+ struct libavl_allocator *allocator)
+{
+ struct avl_table *tree;
+
+ assert (compare != NULL);
+
+ if (allocator == NULL)
+ allocator = &avl_allocator_default;
+
+ tree = allocator->libavl_malloc (allocator, sizeof *tree);
+ if (tree == NULL)
+ return NULL;
+
+ tree->avl_root = NULL;
+ tree->avl_compare = compare;
+ tree->avl_param = param;
+ tree->avl_alloc = allocator;
+ tree->avl_count = 0;
+ tree->avl_generation = 0;
+
+ return tree;
+}
+
+/* Search |tree| for an item matching |item|, and return it if found.
+ Otherwise return |NULL|. */
+void *
+avl_find (const struct avl_table *tree, const void *item)
+{
+ const struct avl_node *p;
+
+ assert (tree != NULL && item != NULL);
+ for (p = tree->avl_root; p != NULL; )
+ {
+ int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param);
+
+ if (cmp < 0)
+ p = p->avl_link[0];
+ else if (cmp > 0)
+ p = p->avl_link[1];
+ else /* |cmp == 0| */
+ return p->avl_data;
+ }
+
+ return NULL;
+}
+
+/* Inserts |item| into |tree| and returns a pointer to |item|'s address.
+ If a duplicate item is found in the tree,
+ returns a pointer to the duplicate without inserting |item|.
+ Returns |NULL| in case of memory allocation failure. */
+void **
+avl_probe (struct avl_table *tree, void *item)
+{
+ struct avl_node *y, *z; /* Top node to update balance factor, and parent. */
+ struct avl_node *p, *q; /* Iterator, and parent. */
+ struct avl_node *n; /* Newly inserted node. */
+ struct avl_node *w; /* New root of rebalanced subtree. */
+ int dir; /* Direction to descend. */
+
+ unsigned char da[AVL_MAX_HEIGHT]; /* Cached comparison results. */
+ int k = 0; /* Number of cached results. */
+
+ assert (tree != NULL && item != NULL);
+
+ z = (struct avl_node *) &tree->avl_root;
+ y = tree->avl_root;
+ dir = 0;
+ for (q = z, p = y; p != NULL; q = p, p = p->avl_link[dir])
+ {
+ int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param);
+ if (cmp == 0)
+ return &p->avl_data;
+
+ if (p->avl_balance != 0)
+ z = q, y = p, k = 0;
+ da[k++] = dir = cmp > 0;
+ }
+
+ n = q->avl_link[dir] =
+ tree->avl_alloc->libavl_malloc (tree->avl_alloc, sizeof *n);
+ if (n == NULL)
+ return NULL;
+
+ tree->avl_count++;
+ n->avl_data = item;
+ n->avl_link[0] = n->avl_link[1] = NULL;
+ n->avl_balance = 0;
+ if (y == NULL)
+ return &n->avl_data;
+
+ for (p = y, k = 0; p != n; p = p->avl_link[da[k]], k++)
+ if (da[k] == 0)
+ p->avl_balance--;
+ else
+ p->avl_balance++;
+
+ if (y->avl_balance == -2)
+ {
+ struct avl_node *x = y->avl_link[0];
+ if (x->avl_balance == -1)
+ {
+ w = x;
+ y->avl_link[0] = x->avl_link[1];
+ x->avl_link[1] = y;
+ x->avl_balance = y->avl_balance = 0;
+ }
+ else
+ {
+ assert (x->avl_balance == +1);
+ w = x->avl_link[1];
+ x->avl_link[1] = w->avl_link[0];
+ w->avl_link[0] = x;
+ y->avl_link[0] = w->avl_link[1];
+ w->avl_link[1] = y;
+ if (w->avl_balance == -1)
+ x->avl_balance = 0, y->avl_balance = +1;
+ else if (w->avl_balance == 0)
+ x->avl_balance = y->avl_balance = 0;
+ else /* |w->avl_balance == +1| */
+ x->avl_balance = -1, y->avl_balance = 0;
+ w->avl_balance = 0;
+ }
+ }
+ else if (y->avl_balance == +2)
+ {
+ struct avl_node *x = y->avl_link[1];
+ if (x->avl_balance == +1)
+ {
+ w = x;
+ y->avl_link[1] = x->avl_link[0];
+ x->avl_link[0] = y;
+ x->avl_balance = y->avl_balance = 0;
+ }
+ else
+ {
+ assert (x->avl_balance == -1);
+ w = x->avl_link[0];
+ x->avl_link[0] = w->avl_link[1];
+ w->avl_link[1] = x;
+ y->avl_link[1] = w->avl_link[0];
+ w->avl_link[0] = y;
+ if (w->avl_balance == +1)
+ x->avl_balance = 0, y->avl_balance = -1;
+ else if (w->avl_balance == 0)
+ x->avl_balance = y->avl_balance = 0;
+ else /* |w->avl_balance == -1| */
+ x->avl_balance = +1, y->avl_balance = 0;
+ w->avl_balance = 0;
+ }
+ }
+ else
+ return &n->avl_data;
+ z->avl_link[y != z->avl_link[0]] = w;
+
+ tree->avl_generation++;
+ return &n->avl_data;
+}
+
+/* Inserts |item| into |table|.
+ Returns |NULL| if |item| was successfully inserted
+ or if a memory allocation error occurred.
+ Otherwise, returns the duplicate item. */
+void *
+avl_insert (struct avl_table *table, void *item)
+{
+ void **p = avl_probe (table, item);
+ return p == NULL || *p == item ? NULL : *p;
+}
+
+/* Inserts |item| into |table|, replacing any duplicate item.
+ Returns |NULL| if |item| was inserted without replacing a duplicate,
+ or if a memory allocation error occurred.
+ Otherwise, returns the item that was replaced. */
+void *
+avl_replace (struct avl_table *table, void *item)
+{
+ void **p = avl_probe (table, item);
+ if (p == NULL || *p == item)
+ return NULL;
+ else
+ {
+ void *r = *p;
+ *p = item;
+ return r;
+ }
+}
+
+/* Deletes from |tree| and returns an item matching |item|.
+ Returns a null pointer if no matching item found. */
+void *
+avl_delete (struct avl_table *tree, const void *item)
+{
+ /* Stack of nodes. */
+ struct avl_node *pa[AVL_MAX_HEIGHT]; /* Nodes. */
+ unsigned char da[AVL_MAX_HEIGHT]; /* |avl_link[]| indexes. */
+ int k; /* Stack pointer. */
+
+ struct avl_node *p; /* Traverses tree to find node to delete. */
+ int cmp; /* Result of comparison between |item| and |p|. */
+
+ assert (tree != NULL && item != NULL);
+
+ k = 0;
+ p = (struct avl_node *) &tree->avl_root;
+ for (cmp = -1; cmp != 0;
+ cmp = tree->avl_compare (item, p->avl_data, tree->avl_param))
+ {
+ int dir = cmp > 0;
+
+ pa[k] = p;
+ da[k++] = dir;
+
+ p = p->avl_link[dir];
+ if (p == NULL)
+ return NULL;
+ }
+ item = p->avl_data;
+
+ if (p->avl_link[1] == NULL)
+ pa[k - 1]->avl_link[da[k - 1]] = p->avl_link[0];
+ else
+ {
+ struct avl_node *r = p->avl_link[1];
+ if (r->avl_link[0] == NULL)
+ {
+ r->avl_link[0] = p->avl_link[0];
+ r->avl_balance = p->avl_balance;
+ pa[k - 1]->avl_link[da[k - 1]] = r;
+ da[k] = 1;
+ pa[k++] = r;
+ }
+ else
+ {
+ struct avl_node *s;
+ int j = k++;
+
+ for (;;)
+ {
+ da[k] = 0;
+ pa[k++] = r;
+ s = r->avl_link[0];
+ if (s->avl_link[0] == NULL)
+ break;
+
+ r = s;
+ }
+
+ s->avl_link[0] = p->avl_link[0];
+ r->avl_link[0] = s->avl_link[1];
+ s->avl_link[1] = p->avl_link[1];
+ s->avl_balance = p->avl_balance;
+
+ pa[j - 1]->avl_link[da[j - 1]] = s;
+ da[j] = 1;
+ pa[j] = s;
+ }
+ }
+
+ tree->avl_alloc->libavl_free (tree->avl_alloc, p);
+
+ assert (k > 0);
+ while (--k > 0)
+ {
+ struct avl_node *y = pa[k];
+
+ if (da[k] == 0)
+ {
+ y->avl_balance++;
+ if (y->avl_balance == +1)
+ break;
+ else if (y->avl_balance == +2)
+ {
+ struct avl_node *x = y->avl_link[1];
+ if (x->avl_balance == -1)
+ {
+ struct avl_node *w;
+ assert (x->avl_balance == -1);
+ w = x->avl_link[0];
+ x->avl_link[0] = w->avl_link[1];
+ w->avl_link[1] = x;
+ y->avl_link[1] = w->avl_link[0];
+ w->avl_link[0] = y;
+ if (w->avl_balance == +1)
+ x->avl_balance = 0, y->avl_balance = -1;
+ else if (w->avl_balance == 0)
+ x->avl_balance = y->avl_balance = 0;
+ else /* |w->avl_balance == -1| */
+ x->avl_balance = +1, y->avl_balance = 0;
+ w->avl_balance = 0;
+ pa[k - 1]->avl_link[da[k - 1]] = w;
+ }
+ else
+ {
+ y->avl_link[1] = x->avl_link[0];
+ x->avl_link[0] = y;
+ pa[k - 1]->avl_link[da[k - 1]] = x;
+ if (x->avl_balance == 0)
+ {
+ x->avl_balance = -1;
+ y->avl_balance = +1;
+ break;
+ }
+ else
+ x->avl_balance = y->avl_balance = 0;
+ }
+ }
+ }
+ else
+ {
+ y->avl_balance--;
+ if (y->avl_balance == -1)
+ break;
+ else if (y->avl_balance == -2)
+ {
+ struct avl_node *x = y->avl_link[0];
+ if (x->avl_balance == +1)
+ {
+ struct avl_node *w;
+ assert (x->avl_balance == +1);
+ w = x->avl_link[1];
+ x->avl_link[1] = w->avl_link[0];
+ w->avl_link[0] = x;
+ y->avl_link[0] = w->avl_link[1];
+ w->avl_link[1] = y;
+ if (w->avl_balance == -1)
+ x->avl_balance = 0, y->avl_balance = +1;
+ else if (w->avl_balance == 0)
+ x->avl_balance = y->avl_balance = 0;
+ else /* |w->avl_balance == +1| */
+ x->avl_balance = -1, y->avl_balance = 0;
+ w->avl_balance = 0;
+ pa[k - 1]->avl_link[da[k - 1]] = w;
+ }
+ else
+ {
+ y->avl_link[0] = x->avl_link[1];
+ x->avl_link[1] = y;
+ pa[k - 1]->avl_link[da[k - 1]] = x;
+ if (x->avl_balance == 0)
+ {
+ x->avl_balance = +1;
+ y->avl_balance = -1;
+ break;
+ }
+ else
+ x->avl_balance = y->avl_balance = 0;
+ }
+ }
+ }
+ }
+
+ tree->avl_count--;
+ tree->avl_generation++;
+ return (void *) item;
+}
+
+/* Refreshes the stack of parent pointers in |trav|
+ and updates its generation number. */
+static void
+trav_refresh (struct avl_traverser *trav)
+{
+ assert (trav != NULL);
+
+ trav->avl_generation = trav->avl_table->avl_generation;
+
+ if (trav->avl_node != NULL)
+ {
+ avl_comparison_func *cmp = trav->avl_table->avl_compare;
+ void *param = trav->avl_table->avl_param;
+ struct avl_node *node = trav->avl_node;
+ struct avl_node *i;
+
+ trav->avl_height = 0;
+ for (i = trav->avl_table->avl_root; i != node; )
+ {
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ assert (i != NULL);
+
+ trav->avl_stack[trav->avl_height++] = i;
+ i = i->avl_link[cmp (node->avl_data, i->avl_data, param) > 0];
+ }
+ }
+}
+
+/* Initializes |trav| for use with |tree|
+ and selects the null node. */
+void
+avl_t_init (struct avl_traverser *trav, struct avl_table *tree)
+{
+ trav->avl_table = tree;
+ trav->avl_node = NULL;
+ trav->avl_height = 0;
+ trav->avl_generation = tree->avl_generation;
+}
+
+/* Initializes |trav| for |tree|
+ and selects and returns a pointer to its least-valued item.
+ Returns |NULL| if |tree| contains no nodes. */
+void *
+avl_t_first (struct avl_traverser *trav, struct avl_table *tree)
+{
+ struct avl_node *x;
+
+ assert (tree != NULL && trav != NULL);
+
+ trav->avl_table = tree;
+ trav->avl_height = 0;
+ trav->avl_generation = tree->avl_generation;
+
+ x = tree->avl_root;
+ if (x != NULL)
+ while (x->avl_link[0] != NULL)
+ {
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ trav->avl_stack[trav->avl_height++] = x;
+ x = x->avl_link[0];
+ }
+ trav->avl_node = x;
+
+ return x != NULL ? x->avl_data : NULL;
+}
+
+/* Initializes |trav| for |tree|
+ and selects and returns a pointer to its greatest-valued item.
+ Returns |NULL| if |tree| contains no nodes. */
+void *
+avl_t_last (struct avl_traverser *trav, struct avl_table *tree)
+{
+ struct avl_node *x;
+
+ assert (tree != NULL && trav != NULL);
+
+ trav->avl_table = tree;
+ trav->avl_height = 0;
+ trav->avl_generation = tree->avl_generation;
+
+ x = tree->avl_root;
+ if (x != NULL)
+ while (x->avl_link[1] != NULL)
+ {
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ trav->avl_stack[trav->avl_height++] = x;
+ x = x->avl_link[1];
+ }
+ trav->avl_node = x;
+
+ return x != NULL ? x->avl_data : NULL;
+}
+
+/* Searches for |item| in |tree|.
+ If found, initializes |trav| to the item found and returns the item
+ as well.
+ If there is no matching item, initializes |trav| to the null item
+ and returns |NULL|. */
+void *
+avl_t_find (struct avl_traverser *trav, struct avl_table *tree, void *item)
+{
+ struct avl_node *p, *q;
+
+ assert (trav != NULL && tree != NULL && item != NULL);
+ trav->avl_table = tree;
+ trav->avl_height = 0;
+ trav->avl_generation = tree->avl_generation;
+ for (p = tree->avl_root; p != NULL; p = q)
+ {
+ int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param);
+
+ if (cmp < 0)
+ q = p->avl_link[0];
+ else if (cmp > 0)
+ q = p->avl_link[1];
+ else /* |cmp == 0| */
+ {
+ trav->avl_node = p;
+ return p->avl_data;
+ }
+
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ trav->avl_stack[trav->avl_height++] = p;
+ }
+
+ trav->avl_height = 0;
+ trav->avl_node = NULL;
+ return NULL;
+}
+
+/* Attempts to insert |item| into |tree|.
+ If |item| is inserted successfully, it is returned and |trav| is
+ initialized to its location.
+ If a duplicate is found, it is returned and |trav| is initialized to
+ its location. No replacement of the item occurs.
+ If a memory allocation failure occurs, |NULL| is returned and |trav|
+ is initialized to the null item. */
+void *
+avl_t_insert (struct avl_traverser *trav, struct avl_table *tree, void *item)
+{
+ void **p;
+
+ assert (trav != NULL && tree != NULL && item != NULL);
+
+ p = avl_probe (tree, item);
+ if (p != NULL)
+ {
+ trav->avl_table = tree;
+ trav->avl_node =
+ ((struct avl_node *)
+ ((char *) p - offsetof (struct avl_node, avl_data)));
+ trav->avl_generation = tree->avl_generation - 1;
+ return *p;
+ }
+ else
+ {
+ avl_t_init (trav, tree);
+ return NULL;
+ }
+}
+
+/* Initializes |trav| to have the same current node as |src|. */
+void *
+avl_t_copy (struct avl_traverser *trav, const struct avl_traverser *src)
+{
+ assert (trav != NULL && src != NULL);
+
+ if (trav != src)
+ {
+ trav->avl_table = src->avl_table;
+ trav->avl_node = src->avl_node;
+ trav->avl_generation = src->avl_generation;
+ if (trav->avl_generation == trav->avl_table->avl_generation)
+ {
+ trav->avl_height = src->avl_height;
+ memcpy (trav->avl_stack, (const void *) src->avl_stack,
+ sizeof *trav->avl_stack * trav->avl_height);
+ }
+ }
+
+ return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
+}
+
+/* Returns the next data item in inorder
+ within the tree being traversed with |trav|,
+ or if there are no more data items returns |NULL|. */
+void *
+avl_t_next (struct avl_traverser *trav)
+{
+ struct avl_node *x;
+
+ assert (trav != NULL);
+
+ if (trav->avl_generation != trav->avl_table->avl_generation)
+ trav_refresh (trav);
+
+ x = trav->avl_node;
+ if (x == NULL)
+ {
+ return avl_t_first (trav, trav->avl_table);
+ }
+ else if (x->avl_link[1] != NULL)
+ {
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ trav->avl_stack[trav->avl_height++] = x;
+ x = x->avl_link[1];
+
+ while (x->avl_link[0] != NULL)
+ {
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ trav->avl_stack[trav->avl_height++] = x;
+ x = x->avl_link[0];
+ }
+ }
+ else
+ {
+ struct avl_node *y;
+
+ do
+ {
+ if (trav->avl_height == 0)
+ {
+ trav->avl_node = NULL;
+ return NULL;
+ }
+
+ y = x;
+ x = trav->avl_stack[--trav->avl_height];
+ }
+ while (y == x->avl_link[1]);
+ }
+ trav->avl_node = x;
+
+ return x->avl_data;
+}
+
+/* Returns the previous data item in inorder
+ within the tree being traversed with |trav|,
+ or if there are no more data items returns |NULL|. */
+void *
+avl_t_prev (struct avl_traverser *trav)
+{
+ struct avl_node *x;
+
+ assert (trav != NULL);
+
+ if (trav->avl_generation != trav->avl_table->avl_generation)
+ trav_refresh (trav);
+
+ x = trav->avl_node;
+ if (x == NULL)
+ {
+ return avl_t_last (trav, trav->avl_table);
+ }
+ else if (x->avl_link[0] != NULL)
+ {
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ trav->avl_stack[trav->avl_height++] = x;
+ x = x->avl_link[0];
+
+ while (x->avl_link[1] != NULL)
+ {
+ assert (trav->avl_height < AVL_MAX_HEIGHT);
+ trav->avl_stack[trav->avl_height++] = x;
+ x = x->avl_link[1];
+ }
+ }
+ else
+ {
+ struct avl_node *y;
+
+ do
+ {
+ if (trav->avl_height == 0)
+ {
+ trav->avl_node = NULL;
+ return NULL;
+ }
+
+ y = x;
+ x = trav->avl_stack[--trav->avl_height];
+ }
+ while (y == x->avl_link[0]);
+ }
+ trav->avl_node = x;
+
+ return x->avl_data;
+}
+
+/* Returns |trav|'s current item. */
+void *
+avl_t_cur (struct avl_traverser *trav)
+{
+ assert (trav != NULL);
+
+ return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
+}
+
+/* Replaces the current item in |trav| by |new| and returns the item replaced.
+ |trav| must not have the null item selected.
+ The new item must not upset the ordering of the tree. */
+void *
+avl_t_replace (struct avl_traverser *trav, void *new)
+{
+ void *old;
+
+ assert (trav != NULL && trav->avl_node != NULL && new != NULL);
+ old = trav->avl_node->avl_data;
+ trav->avl_node->avl_data = new;
+ return old;
+}
+
+/* Destroys |new| with |avl_destroy (new, destroy)|,
+ first setting right links of nodes in |stack| within |new|
+ to null pointers to avoid touching uninitialized data. */
+static void
+copy_error_recovery (struct avl_node **stack, int height,
+ struct avl_table *new, avl_item_func *destroy)
+{
+ assert (stack != NULL && height >= 0 && new != NULL);
+
+ for (; height > 2; height -= 2)
+ stack[height - 1]->avl_link[1] = NULL;
+ avl_destroy (new, destroy);
+}
+
+/* Copies |org| to a newly created tree, which is returned.
+ If |copy != NULL|, each data item in |org| is first passed to |copy|,
+ and the return values are inserted into the tree,
+ with |NULL| return values taken as indications of failure.
+ On failure, destroys the partially created new tree,
+ applying |destroy|, if non-null, to each item in the new tree so far,
+ and returns |NULL|.
+ If |allocator != NULL|, it is used for allocation in the new tree.
+ Otherwise, the same allocator used for |org| is used. */
+struct avl_table *
+avl_copy (const struct avl_table *org, avl_copy_func *copy,
+ avl_item_func *destroy, struct libavl_allocator *allocator)
+{
+ struct avl_node *stack[2 * (AVL_MAX_HEIGHT + 1)];
+ int height = 0;
+
+ struct avl_table *new;
+ const struct avl_node *x;
+ struct avl_node *y;
+
+ assert (org != NULL);
+ new = avl_create (org->avl_compare, org->avl_param,
+ allocator != NULL ? allocator : org->avl_alloc);
+ if (new == NULL)
+ return NULL;
+ new->avl_count = org->avl_count;
+ if (new->avl_count == 0)
+ return new;
+
+ x = (const struct avl_node *) &org->avl_root;
+ y = (struct avl_node *) &new->avl_root;
+ for (;;)
+ {
+ while (x->avl_link[0] != NULL)
+ {
+ assert (height < 2 * (AVL_MAX_HEIGHT + 1));
+
+ y->avl_link[0] =
+ new->avl_alloc->libavl_malloc (new->avl_alloc,
+ sizeof *y->avl_link[0]);
+ if (y->avl_link[0] == NULL)
+ {
+ if (y != (struct avl_node *) &new->avl_root)
+ {
+ y->avl_data = NULL;
+ y->avl_link[1] = NULL;
+ }
+
+ copy_error_recovery (stack, height, new, destroy);
+ return NULL;
+ }
+
+ stack[height++] = (struct avl_node *) x;
+ stack[height++] = y;
+ x = x->avl_link[0];
+ y = y->avl_link[0];
+ }
+ y->avl_link[0] = NULL;
+
+ for (;;)
+ {
+ y->avl_balance = x->avl_balance;
+ if (copy == NULL)
+ y->avl_data = x->avl_data;
+ else
+ {
+ y->avl_data = copy (x->avl_data, org->avl_param);
+ if (y->avl_data == NULL)
+ {
+ y->avl_link[1] = NULL;
+ copy_error_recovery (stack, height, new, destroy);
+ return NULL;
+ }
+ }
+
+ if (x->avl_link[1] != NULL)
+ {
+ y->avl_link[1] =
+ new->avl_alloc->libavl_malloc (new->avl_alloc,
+ sizeof *y->avl_link[1]);
+ if (y->avl_link[1] == NULL)
+ {
+ copy_error_recovery (stack, height, new, destroy);
+ return NULL;
+ }
+
+ x = x->avl_link[1];
+ y = y->avl_link[1];
+ break;
+ }
+ else
+ y->avl_link[1] = NULL;
+
+ if (height <= 2)
+ return new;
+
+ y = stack[--height];
+ x = stack[--height];
+ }
+ }
+}
+
+/* Frees storage allocated for |tree|.
+ If |destroy != NULL|, applies it to each data item in inorder. */
+void
+avl_destroy (struct avl_table *tree, avl_item_func *destroy)
+{
+ struct avl_node *p, *q;
+
+ assert (tree != NULL);
+
+ for (p = tree->avl_root; p != NULL; p = q)
+ if (p->avl_link[0] == NULL)
+ {
+ q = p->avl_link[1];
+ if (destroy != NULL && p->avl_data != NULL)
+ destroy (p->avl_data, tree->avl_param);
+ tree->avl_alloc->libavl_free (tree->avl_alloc, p);
+ }
+ else
+ {
+ q = p->avl_link[0];
+ p->avl_link[0] = q->avl_link[1];
+ q->avl_link[1] = p;
+ }
+
+ tree->avl_alloc->libavl_free (tree->avl_alloc, tree);
+}
+
+/* Allocates |size| bytes of space using |malloc()|.
+ Returns a null pointer if allocation fails. */
+void *
+avl_malloc (struct libavl_allocator *allocator, size_t size)
+{
+ assert (allocator != NULL && size > 0);
+ return malloc (size);
+}
+
+/* Frees |block|. */
+void
+avl_free (struct libavl_allocator *allocator, void *block)
+{
+ assert (allocator != NULL && block != NULL);
+ free (block);
+}
+
+/* Default memory allocator that uses |malloc()| and |free()|. */
+struct libavl_allocator avl_allocator_default =
+ {
+ avl_malloc,
+ avl_free
+ };
+
+#undef NDEBUG
+#include <assert.h>
+
+/* Asserts that |avl_insert()| succeeds at inserting |item| into |table|. */
+void
+(avl_assert_insert) (struct avl_table *table, void *item)
+{
+ void **p = avl_probe (table, item);
+ assert (p != NULL && *p == item);
+}
+
+/* Asserts that |avl_delete()| really removes |item| from |table|,
+ and returns the removed item. */
+void *
+(avl_assert_delete) (struct avl_table *table, void *item)
+{
+ void *p = avl_delete (table, item);
+ assert (p != NULL);
+ return p;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/avl.h b/Build/source/texk/web2c/luatexdir/avl.h
new file mode 100644
index 00000000000..b9f9e3c01a9
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/avl.h
@@ -0,0 +1,115 @@
+/* Produced by texiweb from libavl.w. */
+
+/* libavl - library for manipulation of binary trees.
+ Copyright (C) 1998-2002, 2004 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The author may be contacted at <blp@gnu.org> on the Internet, or
+ write to Ben Pfaff, Stanford University, Computer Science Dept., 353
+ Serra Mall, Stanford CA 94305, USA.
+*/
+
+#ifndef AVL_H
+#define AVL_H 1
+
+#include <stddef.h>
+
+/* Function types. */
+typedef int avl_comparison_func (const void *avl_a, const void *avl_b,
+ void *avl_param);
+typedef void avl_item_func (void *avl_item, void *avl_param);
+typedef void *avl_copy_func (void *avl_item, void *avl_param);
+
+#ifndef LIBAVL_ALLOCATOR
+#define LIBAVL_ALLOCATOR
+/* Memory allocator. */
+struct libavl_allocator
+ {
+ void *(*libavl_malloc) (struct libavl_allocator *, size_t libavl_size);
+ void (*libavl_free) (struct libavl_allocator *, void *libavl_block);
+ };
+#endif
+
+/* Default memory allocator. */
+extern struct libavl_allocator avl_allocator_default;
+void *avl_malloc (struct libavl_allocator *, size_t);
+void avl_free (struct libavl_allocator *, void *);
+
+/* Maximum AVL height. */
+#ifndef AVL_MAX_HEIGHT
+#define AVL_MAX_HEIGHT 32
+#endif
+
+/* Tree data structure. */
+struct avl_table
+ {
+ struct avl_node *avl_root; /* Tree's root. */
+ avl_comparison_func *avl_compare; /* Comparison function. */
+ void *avl_param; /* Extra argument to |avl_compare|. */
+ struct libavl_allocator *avl_alloc; /* Memory allocator. */
+ size_t avl_count; /* Number of items in tree. */
+ unsigned long avl_generation; /* Generation number. */
+ };
+
+/* An AVL tree node. */
+struct avl_node
+ {
+ struct avl_node *avl_link[2]; /* Subtrees. */
+ void *avl_data; /* Pointer to data. */
+ signed char avl_balance; /* Balance factor. */
+ };
+
+/* AVL traverser structure. */
+struct avl_traverser
+ {
+ struct avl_table *avl_table; /* Tree being traversed. */
+ struct avl_node *avl_node; /* Current node in tree. */
+ struct avl_node *avl_stack[AVL_MAX_HEIGHT];
+ /* All the nodes above |avl_node|. */
+ size_t avl_height; /* Number of nodes in |avl_parent|. */
+ unsigned long avl_generation; /* Generation number. */
+ };
+
+/* Table functions. */
+struct avl_table *avl_create (avl_comparison_func *, void *,
+ struct libavl_allocator *);
+struct avl_table *avl_copy (const struct avl_table *, avl_copy_func *,
+ avl_item_func *, struct libavl_allocator *);
+void avl_destroy (struct avl_table *, avl_item_func *);
+void **avl_probe (struct avl_table *, void *);
+void *avl_insert (struct avl_table *, void *);
+void *avl_replace (struct avl_table *, void *);
+void *avl_delete (struct avl_table *, const void *);
+void *avl_find (const struct avl_table *, const void *);
+void avl_assert_insert (struct avl_table *, void *);
+void *avl_assert_delete (struct avl_table *, void *);
+
+#define avl_count(table) ((size_t) (table)->avl_count)
+
+/* Table traverser functions. */
+void avl_t_init (struct avl_traverser *, struct avl_table *);
+void *avl_t_first (struct avl_traverser *, struct avl_table *);
+void *avl_t_last (struct avl_traverser *, struct avl_table *);
+void *avl_t_find (struct avl_traverser *, struct avl_table *, void *);
+void *avl_t_insert (struct avl_traverser *, struct avl_table *, void *);
+void *avl_t_copy (struct avl_traverser *, const struct avl_traverser *);
+void *avl_t_next (struct avl_traverser *);
+void *avl_t_prev (struct avl_traverser *);
+void *avl_t_cur (struct avl_traverser *);
+void *avl_t_replace (struct avl_traverser *, void *);
+
+#endif /* avl.h */
diff --git a/Build/source/texk/web2c/luatexdir/avlstuff.c b/Build/source/texk/web2c/luatexdir/avlstuff.c
new file mode 100644
index 00000000000..74fcf6b8eda
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/avlstuff.c
@@ -0,0 +1,180 @@
+/*
+Copyright (c) 2004-2005 Han The Thanh, <thanh@pdftex.org>
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by Free
+Software Foundation; either version 2 of the License, or (at your option)
+any later version.
+
+This file is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this file; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id$
+
+*/
+
+#include "ptexlib.h"
+#include <kpathsea/c-vararg.h>
+#include <kpathsea/c-proto.h>
+#include "avl.h"
+
+static struct avl_table *PdfObjTree[pdf_objtype_max + 1] =
+ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+/**********************************************************************/
+/* memory management functions for AVL */
+
+void *avl_xmalloc(struct libavl_allocator *allocator, size_t size)
+{
+ assert(allocator != NULL && size > 0);
+ return xmalloc(size);
+}
+
+void avl_xfree(struct libavl_allocator *allocator, void *block)
+{
+ assert(allocator != NULL && block != NULL);
+ xfree(block);
+}
+
+struct libavl_allocator avl_xallocator = {
+ avl_xmalloc,
+ avl_xfree
+};
+
+/**********************************************************************/
+/* general AVL comparison functions */
+
+int comp_int_entry(const void *pa, const void *pb, void *p)
+{
+ cmp_return(*(const int *) pa, *(const int *) pb);
+ return 0;
+}
+
+int comp_string_entry(const void *pa, const void *pb, void *p)
+{
+ return strcmp((const char *) pa, (const char *) pb);
+}
+
+/**********************************************************************/
+/* One AVL tree for each obj_type 0...pdfobjtypemax */
+
+
+typedef struct oentry_ {
+ integer int0;
+ integer objptr;
+} oentry;
+
+/* AVL sort oentry into avl_table[] */
+
+int compare_info(const void *pa, const void *pb, void *param)
+{
+ integer a, b;
+ int as, ae, bs, be, al, bl;
+
+ a = ((const oentry *) pa)->int0;
+ b = ((const oentry *) pb)->int0;
+ if (a < 0 && b < 0) { /* string comparison */
+ if (a <= 2097152 && b <= 2097152) {
+ a+=2097152;
+ b+=2097152;
+ as = str_start[-a];
+ ae = str_start[-a + 1]; /* start of next string in pool */
+ bs = str_start[-b];
+ be = str_start[-b + 1];
+ al = ae - as;
+ bl = be - bs;
+ if (al < bl) /* compare first by string length */
+ return -1;
+ if (al > bl)
+ return 1;
+ for (; as < ae; as++, bs++) {
+ if (str_pool[as] < str_pool[bs])
+ return -1;
+ if (str_pool[as] > str_pool[bs])
+ return 1;
+ }
+ } else {
+ pdftex_fail("avlstuff.c: compare_items() for single characters: NI");
+ }
+ } else { /* integer comparison */
+ if (a < b)
+ return -1;
+ if (a > b)
+ return 1;
+ }
+ return 0;
+}
+
+void avl_put_obj(integer objptr, integer t)
+{
+ static void **pp;
+ static oentry *oe;
+
+ if (PdfObjTree[t] == NULL) {
+ PdfObjTree[t] = avl_create(compare_info, NULL, &avl_xallocator);
+ if (PdfObjTree[t] == NULL)
+ pdftex_fail("avlstuff.c: avl_create() PdfObjTree failed");
+ }
+ oe = xtalloc(1, oentry);
+ oe->int0 = obj_tab[objptr].int0;
+ oe->objptr = objptr; /* allows to relocate objtab */
+ pp = avl_probe(PdfObjTree[t], oe);
+ if (pp == NULL)
+ pdftex_fail("avlstuff.c: avl_probe() out of memory in insertion");
+}
+
+
+/* replacement for linear search pascal function "find_obj()" */
+
+integer avl_find_obj(integer t, integer i, integer byname)
+{
+ static oentry *p;
+ static oentry tmp;
+
+ if (byname > 0)
+ tmp.int0 = -i;
+ else
+ tmp.int0 = i;
+ if (PdfObjTree[t] == NULL)
+ return 0;
+ p = (oentry *) avl_find(PdfObjTree[t], &tmp);
+ if (p == NULL)
+ return 0;
+ return p->objptr;
+}
+
+/**********************************************************************/
+
+struct avl_table *mf_tree = NULL;
+
+typedef struct {
+ char *tfm_name;
+ internalfontnumber fontnum;
+} mf_entry;
+
+/**********************************************************************/
+/* cleaning up... */
+
+static void destroy_oentry(void *pa, void *pb)
+{
+ oentry *p = (oentry *) pa;
+ xfree(p);
+}
+
+void PdfObjTree_free()
+{
+ int i;
+
+ for (i = 0; i <= pdf_objtype_max; i++) {
+ if (PdfObjTree[i] != NULL)
+ avl_destroy(PdfObjTree[i], destroy_oentry);
+ }
+}
+
+/**********************************************************************/
diff --git a/Build/source/texk/web2c/luatexdir/avlstuff.h b/Build/source/texk/web2c/luatexdir/avlstuff.h
new file mode 100644
index 00000000000..e5a4de894d2
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/avlstuff.h
@@ -0,0 +1,29 @@
+/*
+Copyright (c) 2004 Han The Thanh, <thanh@pdftex.org>
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by Free
+Software Foundation; either version 2 of the License, or (at your option)
+any later version.
+
+This file is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this file; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id$
+
+formatted by indent -kr
+*/
+
+#include "avl.h"
+
+/* memory management functions for avl */
+
+extern struct libavl_allocator avl_xallocator;
+
+/* end of file avlstuff.h */
diff --git a/Build/source/texk/web2c/luatexdir/change-files.txt b/Build/source/texk/web2c/luatexdir/change-files.txt
new file mode 100644
index 00000000000..c6a3387f41d
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/change-files.txt
@@ -0,0 +1,35 @@
+How change files are applied for pdftex/pdfetex?
+
+============================= pdftex =============================
+
+2) pdftex.ch is generated from
+ ./tie -c pdftex.ch pdftex.web \
+ $(srcdir)/pdftexdir/tex.ch0 \
+ $(srcdir)/tex.ch \
+ $(srcdir)/pdftexdir/tex.ch1 \
+ $(srcdir)/pdftexdir/tex.pch
+
+Input:
+ pdftex.web:
+ pdftex without system-dependent changes
+
+ pdftexdir/tex.ch0:
+ % Change file to assist in creating the web2c-specific change file.
+ % This one comes first, resolves inconsistencies between the
+ % generated pdftex.web and tex.ch
+
+ change the pdftex banner to tex banner, so tex.ch can be applied
+
+ tex.ch:
+ the main web2c-specific (or other system-dependent) change file
+
+ pdftexdir/pdftex.ch:
+
+ % Change file to assist in creating the web2c-specific change file.
+ % This one resolves inconsistencies between tex.ch and tex.pch.
+
+ change the tex banner to pdftex banner (reverse tex.ch0)
+
+Output:
+ pdftex.ch (not pdftexdir/pdftex.ch):
+ additional & system-dependent changes
diff --git a/Build/source/texk/web2c/luatexdir/depend.mk b/Build/source/texk/web2c/luatexdir/depend.mk
new file mode 100644
index 00000000000..8d1bf394648
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/depend.mk
@@ -0,0 +1,2874 @@
+avl.o: ../../../../src/texk/web2c/luatexdir/avl.c \
+ ../../../../src/texk/web2c/luatexdir/avl.h
+avlstuff.o: ../../../../src/texk/web2c/luatexdir/avlstuff.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+font/mapfile.o: ../../../../src/texk/web2c/luatexdir/font/mapfile.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+
+font/pkin.o: ../../../../src/texk/web2c/luatexdir/font/pkin.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+font/subfont.o: ../../../../src/texk/web2c/luatexdir/font/subfont.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+font/tounicode.o: ../../../../src/texk/web2c/luatexdir/font/tounicode.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+font/vfpacket.o: ../../../../src/texk/web2c/luatexdir/font/vfpacket.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+font/writeenc.o: ../../../../src/texk/web2c/luatexdir/font/writeenc.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+font/writefont.o: ../../../../src/texk/web2c/luatexdir/font/writefont.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+font/writet1.o: ../../../../src/texk/web2c/luatexdir/font/writet1.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+
+font/writet3.o: ../../../../src/texk/web2c/luatexdir/font/writet3.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-glyph.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/magstep.h
+font/writettf.o: ../../../../src/texk/web2c/luatexdir/font/writettf.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/font/writettf.h \
+ ../../../../src/texk/web2c/luatexdir/font/macnames.c
+font/writetype0.o: \
+ ../../../../src/texk/web2c/luatexdir/font/writetype0.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/font/writettf.h \
+ ../../../../src/texk/web2c/luatexdir/font/writecff.h
+font/writetype2.o: \
+ ../../../../src/texk/web2c/luatexdir/font/writetype2.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/font/writettf.h \
+ ../../../../src/texk/web2c/luatexdir/font/writecff.h \
+ ../../../../src/texk/web2c/luatexdir/font/sfnt.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/font/tt_glyf.h
+font/writecff.o: ../../../../src/texk/web2c/luatexdir/font/writecff.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/font/writecff.h
+font/tt_glyf.o: ../../../../src/texk/web2c/luatexdir/font/tt_glyf.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/font/sfnt.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/font/tt_table.h \
+ ../../../../src/texk/web2c/luatexdir/font/tt_glyf.h
+font/tt_table.o: ../../../../src/texk/web2c/luatexdir/font/tt_table.c \
+ ../../../../src/texk/web2c/luatexdir/font/sfnt.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/font/tt_table.h
+font/sfnt.o: ../../../../src/texk/web2c/luatexdir/font/sfnt.c \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/font/sfnt.h
+font/texfont.o: ../../../../src/texk/web2c/luatexdir/font/texfont.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+
+font/tfmofm.o: ../../../../src/texk/web2c/luatexdir/font/tfmofm.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+
+font/vfovf.o: ../../../../src/texk/web2c/luatexdir/font/vfovf.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+
+font/luafont.o: ../../../../src/texk/web2c/luatexdir/font/luafont.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+font/dofont.o: ../../../../src/texk/web2c/luatexdir/font/dofont.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+
+image/epdf.o: ../../../../src/texk/web2c/luatexdir/image/epdf.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+image/pdftoepdf.o: \
+ ../../../../src/texk/web2c/luatexdir/image/pdftoepdf.cc \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/image/epdf.h \
+ ../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../web2c/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../web2c/luatexdir/ptexmac.h \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+
+image/writeimg.o: ../../../../src/texk/web2c/luatexdir/image/writeimg.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+
+image/writejbig2.o: \
+ ../../../../src/texk/web2c/luatexdir/image/writejbig2.c \
+ ../../../../src/texk/web2c/luatexdir/image/writejbig2.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h
+image/writejpg.o: ../../../../src/texk/web2c/luatexdir/image/writejpg.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h
+image/writepng.o: ../../../../src/texk/web2c/luatexdir/image/writepng.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h
+lua/loslibext.o: ../../../../src/texk/web2c/luatexdir/lua/loslibext.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+lua/lcallbacklib.o: \
+ ../../../../src/texk/web2c/luatexdir/lua/lcallbacklib.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+lua/lkpselib.o: ../../../../src/texk/web2c/luatexdir/lua/lkpselib.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/expand.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-glyph.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/readable.h
+lua/llualib.o: ../../../../src/texk/web2c/luatexdir/lua/llualib.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+lua/lnodelib.o: ../../../../src/texk/web2c/luatexdir/lua/lnodelib.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+lua/lpdflib.o: ../../../../src/texk/web2c/luatexdir/lua/lpdflib.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+lua/lstatslib.o: ../../../../src/texk/web2c/luatexdir/lua/lstatslib.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+lua/ltexiolib.o: ../../../../src/texk/web2c/luatexdir/lua/ltexiolib.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+lua/ltexlib.o: ../../../../src/texk/web2c/luatexdir/lua/ltexlib.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+lua/ltokenlib.o: ../../../../src/texk/web2c/luatexdir/lua/ltokenlib.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+lua/lfontlib.o: ../../../../src/texk/web2c/luatexdir/lua/lfontlib.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+lua/texluac.o: ../../../../src/texk/web2c/luatexdir/lua/texluac.c \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+
+lua/luainit.o: ../../../../src/texk/web2c/luatexdir/lua/luainit.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h ../luatexdir/luatexextra.h
+lua/luastuff.o: ../../../../src/texk/web2c/luatexdir/lua/luastuff.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+lua/luatex.o: ../../../../src/texk/web2c/luatexdir/lua/luatex.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+
+lua/luatoken.o: ../../../../src/texk/web2c/luatexdir/lua/luatoken.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/tokens.h
+lua/luanode.o: ../../../../src/texk/web2c/luatexdir/lua/luanode.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+lua/llanglib.o: ../../../../src/texk/web2c/luatexdir/lua/llanglib.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+lua/limglib.o: ../../../../src/texk/web2c/luatexdir/lua/limglib.c \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/lua/../image/image.h
+lang/hnjalloc.o: ../../../../src/texk/web2c/luatexdir/lang/hnjalloc.c
+lang/hyphen.o: ../../../../src/texk/web2c/luatexdir/lang/hyphen.c \
+ ../../../../src/texk/web2c/luatexdir/lang/hnjalloc.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+lang/texlang.o: ../../../../src/texk/web2c/luatexdir/lang/texlang.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h
+tex/linebreak.o: ../../../../src/texk/web2c/luatexdir/tex/linebreak.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+tex/postlinebreak.o: \
+ ../../../../src/texk/web2c/luatexdir/tex/postlinebreak.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+tex/texnodes.o: ../../../../src/texk/web2c/luatexdir/tex/texnodes.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+tex/textoken.o: ../../../../src/texk/web2c/luatexdir/tex/textoken.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/tokens.h
+tex/texpdf.o: ../../../../src/texk/web2c/luatexdir/tex/texpdf.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h
+managed-sa.o: ../../../../src/texk/web2c/luatexdir/managed-sa.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/managed-sa.h
+mathcodes.o: ../../../../src/texk/web2c/luatexdir/mathcodes.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/managed-sa.h
+textcodes.o: ../../../../src/texk/web2c/luatexdir/textcodes.c \
+ ../../../../src/texk/web2c/luatexdir/luatex-api.h \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/managed-sa.h
+utils.o: ../../../../src/texk/web2c/luatexdir/utils.c \
+ \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-stat.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+ ../../../../src/texk/web2c/luatexdir/svnversion.h \
+ \
+
+writezip.o: ../../../../src/texk/web2c/luatexdir/writezip.c \
+ ../../../../src/texk/web2c/luatexdir/ptexlib.h ../luatexd.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmp.h \
+ ../../../../src/texk/web2c/luatexdir/../cpascal.h \
+ ../../../../src/texk/web2c/luatexdir/../config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/config.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-std.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-unistd.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/systypes.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-memstr.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-errno.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-minmax.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-limits.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-proto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/debug.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/types.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/lib.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/progname.h \
+ ../../web2c/c-auto.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-fopen.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/getopt.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/proginit.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/tex-file.h \
+ ../../../../src/texk/web2c/luatexdir/../help.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-pathch.h \
+ ../../../../src/texk/web2c/luatexdir/../../kpathsea/c-ctype.h \
+ ../../../../src/texk/web2c/luatexdir/../texmfmem.h ../luatexcoerce.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/luatex.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/ptexlib.h \
+ ../../../../src/texk/web2c/luatexdir/ptexmac.h \
+ ../../../../src/texk/web2c/luatexdir/avlstuff.h \
+ ../../../../src/texk/web2c/luatexdir/avl.h \
+ ../../../../src/texk/web2c/luatexdir/image/image.h \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ ../../../../src/texk/web2c/luatexdir/font/texfont.h \
+ ../../../../src/texk/web2c/luatexdir/../luatexdir/managed-sa.h \
+ ../../../../src/texk/web2c/luatexdir/hyphen.h \
+ ../../../../src/texk/web2c/luatexdir/nodes.h \
+
diff --git a/Build/source/texk/web2c/luatexdir/font/.indent.pro b/Build/source/texk/web2c/luatexdir/font/.indent.pro
new file mode 100644
index 00000000000..e9e690f1ba8
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/.indent.pro
@@ -0,0 +1,12 @@
+/* $Id$ */
+--k-and-r-style
+--blank-lines-after-procedures
+--line-length 80
+--procnames-start-lines
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--space-after-cast
+/* this does not work in indent 2.2.6 :-( */
+--no-tabs
+/* this is new in indent 2.2.9 */
+--preprocessor-indentation 2
diff --git a/Build/source/texk/web2c/luatexdir/font/dofont.c b/Build/source/texk/web2c/luatexdir/font/dofont.c
new file mode 100644
index 00000000000..fbe44c29ba9
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/dofont.c
@@ -0,0 +1,183 @@
+/*
+Copyright (c) 1996-2006 Taco Hoekwater <taco@luatex.org>
+
+This file is part of LuaTeX.
+
+LuaTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+LuaTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with LuaTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: dofont.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+
+#include "luatex-api.h"
+
+#define TIMERS 0
+
+#if TIMERS
+#include <sys/time.h>
+#endif
+
+
+/* a bit more interfacing is needed for proper error reporting */
+
+static char *
+font_error_message (pointer u, char *nom, scaled s) {
+ char *str = xmalloc(256);
+ char *c = makecstring(zget_cs_text(u));
+ char *extra = "metric data not found or bad";
+ if (s>=0 ) {
+ snprintf(str,255,"Font \\%s=%s at %gpt not loadable: %s", c, nom, (double)s/65536, extra);
+ } else if (s!=-1000) {
+ snprintf(str,255,"Font \\%s=%s scaled %d not loadable: %s", c, nom, (int)(-s), extra);
+ } else {
+ snprintf(str,255,"Font \\%s=%s not loadable: %s", c, nom, extra);
+ }
+ return str;
+}
+
+static int
+do_define_font (integer f, char *cnom, char *caire, scaled s, integer natural_dir) {
+
+ boolean res; /* was the callback successful? */
+ integer callback_id;
+ char *cnam;
+#if TIMERS
+ struct timeval tva;
+ struct timeval tvb;
+ double tvdiff;
+#endif
+ int r;
+ res = 0;
+
+ callback_id=callback_defined(define_font_callback);
+ if (callback_id>0) {
+ if (caire == NULL || strlen(caire)==0) {
+ cnam = xstrdup(cnom);
+ } else {
+ cnam = xmalloc(strlen(cnom)+strlen(caire)+2);
+ sprintf(cnam,"%s/%s",caire,cnom);
+ }
+#if TIMERS
+ gettimeofday(&tva,NULL);
+#endif
+ callback_id = run_and_save_callback(callback_id,"Sdd->",cnam,s,f);
+#if TIMERS
+ gettimeofday(&tvb,NULL);
+ tvdiff = tvb.tv_sec*1000000.0;
+ tvdiff += (double)tvb.tv_usec;
+ tvdiff -= (tva.tv_sec*1000000.0);
+ tvdiff -= (double)tva.tv_usec;
+ tvdiff /= 1000000;
+ fprintf(stdout,"\ncallback('define_font',%s,%i): %f seconds\n", cnam,f,tvdiff);
+#endif
+ free(cnam);
+ if (callback_id>0) { /* success */
+ luaL_checkstack(Luas[0],1,"out of stack space");
+ lua_rawgeti(Luas[0],LUA_REGISTRYINDEX, callback_id);
+ if (lua_istable(Luas[0],-1)) {
+#if TIMERS
+ gettimeofday(&tva,NULL);
+#endif
+ res = font_from_lua(Luas[0],f);
+ destroy_saved_callback (callback_id);
+#if TIMERS
+ gettimeofday(&tvb,NULL);
+ tvdiff = tvb.tv_sec*1000000.0;
+ tvdiff += (double)tvb.tv_usec;
+ tvdiff -= (tva.tv_sec*1000000.0);
+ tvdiff -= (double)tva.tv_usec;
+ tvdiff /= 1000000;
+ fprintf(stdout,"font_from_lua(%s,%i): %f seconds\n", font_name(f),f,tvdiff);
+#endif
+ lua_pop(Luas[0],1);
+ } else if (lua_isnumber(Luas[0],-1)) {
+ r = lua_tonumber(Luas[0],-1);
+ destroy_saved_callback (callback_id);
+ delete_font(f);
+ lua_pop(Luas[0],1);
+ return r;
+ } else {
+ lua_pop(Luas[0],1);
+ delete_font(f);
+ return 0;
+ }
+ }
+ } else {
+ res = read_tfm_info(f,cnom,caire,s);
+ if (res) {
+ set_hyphen_char(f,get_default_hyphen_char());
+ set_skew_char(f,get_default_skew_char());
+ }
+ }
+ if (res) {
+ do_vf(f);
+ set_font_natural_dir(f,natural_dir);
+ return f;
+ } else {
+ delete_font(f);
+ return 0;
+ }
+
+}
+
+int
+read_font_info(pointer u, strnumber nom, strnumber aire, scaled s,
+ integer natural_dir) {
+ integer f;
+ char *cnom, *caire = NULL;
+ char *msg;
+ cnom = xstrdup(makecstring(nom));
+ if (aire != 0)
+ caire = xstrdup(makecstring(aire));
+
+ f = new_font();
+ if ((f = do_define_font(f, cnom,caire,s,natural_dir))) {
+ if (caire != NULL) free(caire);
+ free(cnom);
+ return f;
+ } else {
+ char *help[] = {"I wasn't able to read the size data for this font,",
+ "so I will ignore the font specification.",
+ "[Wizards can fix TFM files using TFtoPL/PLtoTF.]",
+ "You might try inserting a different font spec;",
+ "e.g., type `I\font<same font id>=<substitute font name>'.",
+ NULL } ;
+ if(!get_suppress_fontnotfound_error()) {
+ msg = font_error_message(u, cnom, s);
+ tex_error(msg,help);
+ free(msg);
+ }
+ if (caire != NULL) free(caire);
+ free(cnom);
+ return 0;
+ }
+}
+
+/* TODO This function is a placeholder. There can easily appears holes in
+ the |font_tables| array, and we could attempt to reuse those
+*/
+
+int
+find_font_id (char *nom, char *aire, scaled s) {
+ integer f;
+ f = new_font();
+ if ((f = do_define_font(f, nom, aire,s,-1))) {
+ return f;
+ } else {
+ return 0;
+ }
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/font/luafont.c b/Build/source/texk/web2c/luatexdir/font/luafont.c
new file mode 100644
index 00000000000..be32e39de9f
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/luafont.c
@@ -0,0 +1,1733 @@
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+#include "nodes.h"
+
+#define noVERBOSE
+
+#define SAVE_REF 1
+
+char *font_type_strings[] = {"unknown","virtual","real", NULL};
+char *font_format_strings[] = {"unknown","type1","type3","truetype", "opentype", NULL};
+char *font_embedding_strings[] = {"unknown","no","subset", "full", NULL};
+char *ligature_type_strings[] = {"=:", "=:|", "|=:", "|=:|", "", "=:|>", "|=:>", "|=:|>", "", "", "", "|=:|>>", NULL };
+
+void
+font_char_to_lua (lua_State *L, internalfontnumber f, charinfo *co) {
+ int i;
+ liginfo *l;
+ kerninfo *ki;
+
+ lua_createtable(L,0,10);
+
+ lua_pushstring(L,"width");
+ lua_pushnumber(L,get_charinfo_width(co));
+ lua_rawset(L,-3);
+
+ lua_pushstring(L,"height");
+ lua_pushnumber(L,get_charinfo_height(co));
+ lua_rawset(L,-3);
+
+ lua_pushstring(L,"depth");
+ lua_pushnumber(L,get_charinfo_depth(co));
+ lua_rawset(L,-3);
+
+ lua_pushstring(L,"italic");
+ lua_pushnumber(L,get_charinfo_italic(co));
+ lua_rawset(L,-3);
+
+ if (get_charinfo_ef(co)!=0) {
+ lua_pushstring(L,"expansion_factor");
+ lua_pushnumber(L,get_charinfo_ef(co));
+ lua_rawset(L,-3);
+ }
+
+ if (get_charinfo_lp(co)!=0) {
+ lua_pushstring(L,"left_protruding");
+ lua_pushnumber(L,get_charinfo_lp(co));
+ lua_rawset(L,-3);
+ }
+
+ if (get_charinfo_lp(co)!=0) {
+ lua_pushstring(L,"right_protruding");
+ lua_pushnumber(L,get_charinfo_rp(co));
+ lua_rawset(L,-3);
+ }
+
+
+ if (font_encodingbytes(f) == 2 ) {
+ lua_pushstring(L,"index");
+ lua_pushnumber(L,get_charinfo_index(co));
+ lua_rawset(L,-3);
+ }
+
+ if (get_charinfo_name(co)!=NULL) {
+ lua_pushstring(L,"name");
+ lua_pushstring(L,get_charinfo_name(co));
+ lua_rawset(L,-3);
+ }
+
+ if (get_charinfo_tounicode(co)!=NULL) {
+ lua_pushstring(L,"tounicode");
+ lua_pushstring(L,get_charinfo_tounicode(co));
+ lua_rawset(L,-3);
+ }
+
+ if (get_charinfo_tag(co) == list_tag) {
+ lua_pushstring(L,"next");
+ lua_pushnumber(L,get_charinfo_remainder(co));
+ lua_rawset(L,-3);
+ }
+
+ lua_pushstring(L,"used");
+ lua_pushboolean(L,(get_charinfo_used(co) ? true : false));
+ lua_rawset(L,-3);
+
+ if (get_charinfo_tag(co) == ext_tag) {
+ lua_pushstring(L,"extensible");
+ lua_createtable(L,0,4);
+ lua_pushnumber(L,get_charinfo_extensible(co,EXT_TOP));
+ lua_setfield(L,-2,"top");
+ lua_pushnumber(L,get_charinfo_extensible(co,EXT_BOT));
+ lua_setfield(L,-2,"bot");
+ lua_pushnumber(L,get_charinfo_extensible(co,EXT_MID));
+ lua_setfield(L,-2,"mid");
+ lua_pushnumber(L,get_charinfo_extensible(co,EXT_REP));
+ lua_setfield(L,-2,"rep");
+ lua_rawset(L,-3);
+ }
+ ki = get_charinfo_kerns(co);
+ if (ki != NULL) {
+ lua_pushstring(L,"kerns");
+ lua_createtable(L,10,1);
+ for (i=0;!kern_end(ki[i]);i++) {
+ if (kern_char(ki[i]) == right_boundarychar) {
+ lua_pushstring(L,"right_boundary");
+ } else {
+ lua_pushnumber(L,kern_char(ki[i]));
+ }
+ lua_pushnumber(L,kern_kern(ki[i]));
+ lua_rawset(L,-3);
+ }
+ lua_rawset(L,-3);
+ }
+ l = get_charinfo_ligatures(co);
+ if (l!=NULL) {
+ lua_pushstring(L,"ligatures");
+ lua_createtable(L,10,1);
+ for (i=0;!lig_end(l[i]);i++) {
+ if (lig_char(l[i]) == right_boundarychar) {
+ lua_pushstring(L,"right_boundary");
+ } else {
+ lua_pushnumber(L,lig_char(l[i]));
+ }
+ lua_createtable(L,0,2);
+ lua_pushstring(L,"type");
+ lua_pushnumber(L,lig_type(l[i]));
+ lua_rawset(L,-3);
+ lua_pushstring(L,"char");
+ lua_pushnumber(L,lig_replacement(l[i]));
+ lua_rawset(L,-3);
+ lua_rawset(L,-3);
+ }
+ lua_rawset(L,-3);
+ }
+}
+
+static void
+write_lua_parameters (lua_State *L, int f) {
+ int k;
+ lua_newtable(L);
+ for (k=1;k<=font_params(f);k++) {
+ lua_pushnumber(L,font_param(f,k));
+ switch (k) {
+ case slant_code: lua_setfield(L,-2,"slant"); break;
+ case space_code: lua_setfield(L,-2,"space"); break;
+ case space_stretch_code: lua_setfield(L,-2,"space_stretch"); break;
+ case space_shrink_code: lua_setfield(L,-2,"space_shrink"); break;
+ case x_height_code: lua_setfield(L,-2,"x_height"); break;
+ case quad_code: lua_setfield(L,-2,"quad"); break;
+ case extra_space_code: lua_setfield(L,-2,"extra_space"); break;
+ default:
+ lua_rawseti(L,-2,k);
+ }
+ }
+ lua_setfield(L,-2,"parameters");
+}
+
+
+int
+font_to_lua (lua_State *L, int f) {
+ int k;
+ charinfo *co;
+ if (font_cache_id(f)) {
+ /* fetch the table from the registry if it was
+ saved there by font_from_lua() */
+ lua_rawgeti(L,LUA_REGISTRYINDEX,font_cache_id(f));
+ /* fontdimens can be changed from tex code */
+ write_lua_parameters(L,f);
+ return 1;
+ }
+
+ lua_newtable(L);
+ lua_pushstring(L,font_name(f));
+ lua_setfield(L,-2,"name");
+ if(font_area(f)!=NULL) {
+ lua_pushstring(L,font_area(f));
+ lua_setfield(L,-2,"area");
+ }
+ if(font_filename(f)!=NULL) {
+ lua_pushstring(L,font_filename(f));
+ lua_setfield(L,-2,"filename");
+ }
+ if(font_fullname(f)!=NULL) {
+ lua_pushstring(L,font_fullname(f));
+ lua_setfield(L,-2,"fullname");
+ }
+ if(font_encodingname(f)!=NULL) {
+ lua_pushstring(L,font_encodingname(f));
+ lua_setfield(L,-2,"encodingname");
+ }
+
+ lua_pushboolean(L,(font_used(f) ? true : false));
+ lua_setfield(L,-2,"used");
+
+
+ lua_pushstring(L,font_type_strings[font_type(f)]);
+ lua_setfield(L,-2,"type");
+ lua_pushstring(L,font_format_strings[font_format(f)]);
+ lua_setfield(L,-2,"format");
+ lua_pushstring(L,font_embedding_strings[font_embedding(f)]);
+ lua_setfield(L,-2,"embedding");
+
+ lua_pushnumber(L,font_size(f));
+ lua_setfield(L,-2,"size");
+ lua_pushnumber(L,font_dsize(f));
+ lua_setfield(L,-2,"designsize");
+ lua_pushnumber(L,font_checksum(f));
+ lua_setfield(L,-2,"checksum");
+ lua_pushnumber(L,font_slant(f));
+ lua_setfield(L,-2,"slant");
+ lua_pushnumber(L,font_extend(f));
+ lua_setfield(L,-2,"extend");
+ lua_pushnumber(L,font_natural_dir(f));
+ lua_setfield(L,-2,"direction");
+ lua_pushnumber(L,font_encodingbytes(f));
+ lua_setfield(L,-2,"encodingbytes");
+ lua_pushnumber(L,font_tounicode(f));
+ lua_setfield(L,-2,"tounicode");
+
+ /* pdf parameters */
+ /* skip the first four for now, that are very much interal */
+ /*
+ if (pdf_font_size(f) != 0) {
+ lua_pushnumber(L,pdf_font_size(f));
+ lua_setfield(L,-2,"pdf_size");
+ }
+ if (pdf_font_num(f) != 0) {
+ lua_pushnumber(L,pdf_font_num(f));
+ lua_setfield(L,-2,"pdf_num");
+ }
+ if (pdf_font_blink(f) != 0) {
+ lua_pushnumber(L,pdf_font_blink(f));
+ lua_setfield(L,-2,"pdf_blink");
+ }
+ if (pdf_font_elink(f) != 0) {
+ lua_pushnumber(L,pdf_font_elink(f));
+ lua_setfield(L,-2,"pdf_elink");
+ }
+ */
+ /* the next one is read only */
+ if (pdf_font_expand_ratio(f) != 0) {
+ lua_pushnumber(L,pdf_font_expand_ratio(f));
+ lua_setfield(L,-2,"expand_ratio");
+ }
+ if (pdf_font_shrink(f) != 0) {
+ lua_pushnumber(L,pdf_font_shrink(f));
+ lua_setfield(L,-2,"shrink");
+ }
+ if (pdf_font_stretch(f) != 0) {
+ lua_pushnumber(L,pdf_font_stretch(f));
+ lua_setfield(L,-2,"stretch");
+ }
+ if (pdf_font_step(f) != 0) {
+ lua_pushnumber(L,pdf_font_step(f));
+ lua_setfield(L,-2,"step");
+ }
+ if (pdf_font_auto_expand(f) != 0) {
+ lua_pushboolean(L,pdf_font_auto_expand(f));
+ lua_setfield(L,-2,"auto_expand");
+ }
+ if (pdf_font_attr(f) != 0) {
+ lua_pushstring(L,makecstring(pdf_font_attr(f)));
+ lua_setfield(L,-2,"attributes");
+ }
+
+ /* params */
+ write_lua_parameters(L,f);
+
+ /* chars */
+ lua_createtable(L,font_tables[f]->charinfo_size,0); /* all characters */
+
+ if (has_left_boundary(f)) {
+ co = get_charinfo(f,left_boundarychar);
+ font_char_to_lua(L,f,co);
+ lua_setfield(L,-2,"left_boundary");
+ }
+ if (has_right_boundary(f)) {
+ co = get_charinfo(f,right_boundarychar);
+ font_char_to_lua(L,f,co);
+ lua_setfield(L,-2,"right_boundary");
+ }
+
+ for (k=font_bc(f);k<=font_ec(f);k++) {
+ if (char_exists(f,k)) {
+ lua_pushnumber(L,k);
+ co = get_charinfo(f,k);
+ font_char_to_lua(L,f,co);
+ lua_rawset(L,-3);
+ }
+ }
+ lua_setfield(L,-2,"characters");
+ return 1;
+}
+
+static int
+count_hash_items (lua_State *L, int name_index){
+ int n = -1;
+ lua_rawgeti(L,LUA_REGISTRYINDEX,name_index);
+ lua_rawget(L,-2);
+ if (!lua_isnil(L,-1)) {
+ if (lua_istable(L,-1)) {
+ n = 0;
+ /* now find the number */
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, -2) != 0) {
+ n++;
+ lua_pop(L,1);
+ }
+ }
+ }
+ lua_pop(L,1);
+ return n;
+}
+
+#define streq(a,b) (strcmp(a,b)==0)
+
+#define append_packet(k) { cpackets[np++] = k; }
+
+#define do_store_four(l) { \
+ append_packet((l&0xFF000000)>>24); \
+ append_packet((l&0x00FF0000)>>16); \
+ append_packet((l&0x0000FF00)>>8); \
+ append_packet((l&0x000000FF)); }
+
+/*
+*/
+
+#define lua_roundnumber(a,b) (int)floor((double)lua_tonumber(L,-1)+0.5)
+
+static int
+numeric_field (lua_State *L, char *name, int dflt) {
+ int i = dflt;
+ lua_pushstring(L,name);
+ lua_rawget(L,-2);
+ if (lua_isnumber(L,-1)) {
+ i = lua_roundnumber(L,-1);
+ }
+ lua_pop(L,1);
+ return i;
+}
+
+static int
+n_numeric_field (lua_State *L, int name_index, int dflt) {
+ register int i = dflt;
+ lua_rawgeti(L,LUA_REGISTRYINDEX, name_index); /* fetch the stringptr */
+ lua_rawget(L,-2);
+ if (lua_type(L,-1)==LUA_TNUMBER) {
+ i = lua_roundnumber(L,-1);
+ }
+ lua_pop(L,1);
+ return i;
+}
+
+
+static int
+enum_field (lua_State *L, char *name, int dflt, char **values) {
+ int k;
+ char *s;
+ int i = dflt;
+ lua_pushstring(L,name);
+ lua_rawget(L,-2);
+ if (lua_isnumber(L,-1)) {
+ i = lua_tonumber(L,-1);
+ } else if (lua_isstring(L,-1)) {
+ s = (char *)lua_tostring(L,-1);
+ k = 0;
+ while (values[k] != NULL) {
+ if (strcmp(values[k],s) == 0) {
+ i = k;
+ break;
+ }
+ k++;
+ }
+ }
+ lua_pop(L,1);
+ return i;
+}
+
+static int
+boolean_field (lua_State *L, char *name, int dflt) {
+ int i = dflt;
+ lua_pushstring(L,name);
+ lua_rawget(L,-2);
+ if (lua_isboolean(L,-1)) {
+ i = lua_toboolean(L,-1);
+ }
+ lua_pop(L,1);
+ return i;
+}
+
+static int
+n_boolean_field (lua_State *L, int name_index, int dflt) {
+ int i = dflt;
+ lua_rawgeti(L,LUA_REGISTRYINDEX, name_index); /* fetch the stringptr */
+ lua_rawget(L,-2);
+ if (lua_isboolean(L,-1)) {
+ i = lua_toboolean(L,-1);
+ }
+ lua_pop(L,1);
+ return i;
+}
+
+
+static char *
+string_field (lua_State *L, char *name, char *dflt) {
+ char *i;
+ lua_pushstring(L,name);
+ lua_rawget(L,-2);
+ if (lua_isstring(L,-1)) {
+ i = xstrdup(lua_tostring(L,-1));
+ } else if (dflt==NULL) {
+ i = NULL;
+ } else {
+ i = xstrdup(dflt);
+ }
+ lua_pop(L,1);
+ return i;
+}
+
+static char *
+n_string_field (lua_State *L, int name_index, char *dflt) {
+ char *i;
+ lua_rawgeti(L,LUA_REGISTRYINDEX, name_index); /* fetch the stringptr */
+ lua_rawget(L,-2);
+ if (lua_isstring(L,-1)) {
+ i = xstrdup(lua_tostring(L,-1));
+ } else if (dflt==NULL) {
+ i = NULL;
+ } else {
+ i = xstrdup(dflt);
+ }
+ lua_pop(L,1);
+ return i;
+}
+
+#define init_luaS_index(a) do { \
+ lua_pushliteral(L,#a); \
+ luaS_##a##_ptr = (char *)lua_tostring(L,-1); \
+ luaS_##a##_index = luaL_ref (L,LUA_REGISTRYINDEX); \
+ } while (0)
+
+#define make_luaS_index(a) \
+ static int luaS_##a##_index = 0; \
+ static char * luaS_##a##_ptr = NULL
+
+#define luaS_index(a) luaS_##a##_index
+
+#define luaS_ptr_eq(a,b) (a==luaS_##b##_ptr)
+
+make_luaS_index(width);
+make_luaS_index(height);
+make_luaS_index(depth);
+make_luaS_index(italic);
+make_luaS_index(index);
+make_luaS_index(left_protruding);
+make_luaS_index(right_protruding);
+make_luaS_index(expansion_factor);
+make_luaS_index(top);
+make_luaS_index(bot);
+make_luaS_index(rep);
+make_luaS_index(mid);
+make_luaS_index(next);
+make_luaS_index(used);
+make_luaS_index(name);
+make_luaS_index(tounicode);
+make_luaS_index(font);
+make_luaS_index(char);
+make_luaS_index(slot);
+make_luaS_index(comment);
+make_luaS_index(push);
+make_luaS_index(pop);
+make_luaS_index(rule);
+make_luaS_index(right);
+make_luaS_index(node);
+make_luaS_index(down);
+make_luaS_index(special);
+make_luaS_index(slant);
+make_luaS_index(space);
+make_luaS_index(space_stretch);
+make_luaS_index(space_shrink);
+make_luaS_index(x_height);
+make_luaS_index(quad);
+make_luaS_index(extra_space);
+make_luaS_index(left_boundary);
+make_luaS_index(right_boundary);
+make_luaS_index(kerns);
+make_luaS_index(ligatures);
+make_luaS_index(fonts);
+
+void init_font_string_pointers (lua_State *L) {
+ init_luaS_index(width);
+ init_luaS_index(height);
+ init_luaS_index(depth);
+ init_luaS_index(italic);
+ init_luaS_index(index);
+ init_luaS_index(left_protruding);
+ init_luaS_index(right_protruding);
+ init_luaS_index(expansion_factor);
+ init_luaS_index(top);
+ init_luaS_index(bot);
+ init_luaS_index(rep);
+ init_luaS_index(mid);
+ init_luaS_index(next);
+ init_luaS_index(used);
+ init_luaS_index(name);
+ init_luaS_index(tounicode);
+ init_luaS_index(font);
+ init_luaS_index(char);
+ init_luaS_index(slot);
+ init_luaS_index(comment);
+ init_luaS_index(push);
+ init_luaS_index(pop);
+ init_luaS_index(rule);
+ init_luaS_index(right);
+ init_luaS_index(node);
+ init_luaS_index(down);
+ init_luaS_index(special);
+
+ init_luaS_index(slant);
+ init_luaS_index(space);
+ init_luaS_index(space_stretch);
+ init_luaS_index(space_shrink);
+ init_luaS_index(x_height);
+ init_luaS_index(quad);
+ init_luaS_index(extra_space);
+
+ init_luaS_index(left_boundary);
+ init_luaS_index(right_boundary);
+ init_luaS_index(kerns);
+ init_luaS_index(ligatures);
+ init_luaS_index(fonts);
+}
+
+static int
+count_char_packet_bytes (lua_State *L) {
+ register int i;
+ register int l = 0;
+ int ff = 0;
+ for (i=1;i<=lua_objlen(L,-1);i++) {
+ lua_rawgeti(L,-1,i);
+ if (lua_istable(L,-1)) {
+ lua_rawgeti(L,-1,1);
+ if (lua_isstring(L,-1)) {
+ char *s = (char *)lua_tostring(L,-1);
+ if (luaS_ptr_eq(s,font)) { l+= 5; ff =1; }
+ else if (luaS_ptr_eq(s,char)) { if (ff==0) { l+=5; } l += 5; ff = 1; }
+ else if (luaS_ptr_eq(s,slot)) { l += 10; ff = 1;}
+ else if (luaS_ptr_eq(s,comment)) { ; }
+ else if (luaS_ptr_eq(s,push) ||
+ luaS_ptr_eq(s,pop)) { l++; }
+ else if (luaS_ptr_eq(s,rule)) { l+=9; }
+ else if (luaS_ptr_eq(s,right) ||
+ luaS_ptr_eq(s,node) ||
+ luaS_ptr_eq(s,down)) { l+=5; }
+ else if (luaS_ptr_eq(s,special)) {
+ size_t len;
+ lua_rawgeti(L,-2,2);
+ (void)lua_tolstring(L,-1,&len);
+ lua_pop(L,1);
+ if (len>0) { l = l + 5 + len; }
+ }
+ else { fprintf(stdout,"unknown packet command %s!\n",s); }
+ } else {
+ fprintf(stdout,"no packet command!\n");
+ }
+ lua_pop(L,1); /* command name */
+ }
+ lua_pop(L,1); /* item */
+ }
+ return l;
+}
+
+
+
+scaled
+sp_to_dvi (halfword sp, halfword atsize) {
+ double result, mult;
+ mult = (double)(atsize>>16);
+ result = (sp << 4);
+ return floor (result/mult );
+}
+
+
+static void
+read_char_packets (lua_State *L, integer *l_fonts, charinfo *co, int atsize) {
+ int i, n, m;
+ size_t l;
+ int cmd;
+ char *s;
+ real_eight_bits *cpackets;
+ int ff = 0;
+ int np = 0;
+ int max_f = 0;
+ int pc = count_char_packet_bytes (L);
+ if (pc<=0)
+ return;
+ assert(l_fonts != NULL);
+ assert(l_fonts[1] != 0);
+ while (l_fonts[(max_f+1)]!=0)
+ max_f++;
+
+ cpackets = xmalloc(pc+1);
+ for (i=1;i<=lua_objlen(L,-1);i++) {
+ lua_rawgeti(L,-1,i);
+ if (lua_istable(L,-1)) {
+ /* fetch the command code */
+ lua_rawgeti(L,-1,1);
+ if (lua_isstring(L,-1)) {
+ s = (char *)lua_tostring(L,-1);
+ cmd = 0;
+ if (luaS_ptr_eq(s,font)) {
+ cmd = packet_font_code;
+ } else if (luaS_ptr_eq(s,char)) {
+ cmd = packet_char_code;
+ if (ff==0) {
+ append_packet(packet_font_code);
+ ff = l_fonts[1];
+ do_store_four(ff);
+ }
+ } else if (luaS_ptr_eq(s,slot)) {
+ cmd = packet_nop_code;
+ lua_rawgeti(L,-2,2); n = lua_tointeger(L,-1);
+ ff = (n>max_f ? l_fonts[1] : l_fonts[n]);
+ lua_rawgeti(L,-3,3); n = lua_tointeger(L,-1);
+ lua_pop(L,2);
+ append_packet(packet_font_code);
+ do_store_four(ff);
+ append_packet(packet_char_code);
+ do_store_four(n);
+ }
+ else if (luaS_ptr_eq(s,comment)) { cmd = packet_nop_code; }
+ else if (luaS_ptr_eq(s,node)) { cmd = packet_node_code; }
+ else if (luaS_ptr_eq(s,push)) { cmd = packet_push_code; }
+ else if (luaS_ptr_eq(s,pop)) { cmd = packet_pop_code; }
+ else if (luaS_ptr_eq(s,rule)) { cmd = packet_rule_code; }
+ else if (luaS_ptr_eq(s,right)) { cmd = packet_right_code; }
+ else if (luaS_ptr_eq(s,down)) { cmd = packet_down_code; }
+ else if (luaS_ptr_eq(s,special)) { cmd = packet_special_code; }
+
+ switch(cmd) {
+ case packet_push_code:
+ case packet_pop_code:
+ append_packet(cmd);
+ break;
+ case packet_font_code:
+ append_packet(cmd);
+ lua_rawgeti(L,-2,2);
+ n = lua_tointeger(L,-1);
+ ff = (n>max_f ? l_fonts[1] : l_fonts[n]);
+ do_store_four(ff);
+ lua_pop(L,1);
+ break;
+ case packet_node_code:
+ append_packet(cmd);
+ lua_rawgeti(L,-2,2);
+ n = copy_node_list(nodelist_from_lua(L));
+ do_store_four(n);
+ lua_pop(L,1);
+ break;
+ case packet_char_code:
+ append_packet(cmd);
+ lua_rawgeti(L,-2,2);
+ n = lua_tointeger(L,-1);
+ do_store_four(n);
+ lua_pop(L,1);
+ break;
+ case packet_right_code:
+ case packet_down_code:
+ append_packet(cmd);
+ lua_rawgeti(L,-2,2);
+ n = lua_tointeger(L,-1);
+ do_store_four(sp_to_dvi(n,atsize));
+ lua_pop(L,1);
+ break;
+ case packet_rule_code:
+ append_packet(cmd);
+ lua_rawgeti(L,-2,2);
+ n = lua_tointeger(L,-1);
+ do_store_four(sp_to_dvi(n,atsize));
+ lua_rawgeti(L,-3,3);
+ n = lua_tointeger(L,-1);
+ do_store_four(sp_to_dvi(n,atsize));
+ lua_pop(L,2);
+ break;
+ case packet_special_code:
+ append_packet(cmd);
+ lua_rawgeti(L,-2,2);
+ s = (char *)lua_tolstring(L,-1,&l);
+ if (l>0) {
+ do_store_four(l);
+ m = (int)l;
+ while(m>0) {
+ n = *s++;
+ m--;
+ append_packet(n);
+ }
+ }
+ lua_pop(L,1);
+ break;
+ case packet_nop_code:
+ break;
+ default:
+ fprintf(stdout,"Unknown char packet code %s (char %d in font %s)\n",s,(int)c,font_name(f));
+ }
+ }
+ lua_pop(L,1); /* command code */
+ } else {
+ fprintf(stdout,"Found a `commands' item that is not a table (char %d in font %s)\n",(int)c,font_name(f));
+ }
+ lua_pop(L,1); /* command table */
+ }
+ append_packet(packet_end_code);
+ set_charinfo_packets(co,cpackets);
+ return;
+}
+
+
+static void
+read_lua_cidinfo (lua_State *L, int f) {
+ int i;
+ char *s;
+ lua_getfield(L,-1,"cidinfo");
+ if (lua_istable(L,-1)) {
+ i = numeric_field(L,"version",0);
+ set_font_cidversion(f,i);
+ i = numeric_field(L,"supplement",0);
+ set_font_cidsupplement(f,i);
+ s = string_field(L,"registry","Adobe"); /* Adobe-Identity-0 */
+ set_font_cidregistry(f,s);
+ s = string_field(L,"ordering","Identity");
+ set_font_cidordering(f,s);
+ }
+ lua_pop(L,1);
+}
+
+
+static void
+read_lua_parameters (lua_State *L, int f) {
+ int i, n;
+ char *s;
+ lua_getfield(L,-1,"parameters");
+ if (lua_istable(L,-1)) {
+ /* the number of parameters is the max(IntegerKeys(L)),7) */
+ n = 7;
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, -2) != 0) {
+ if (lua_isnumber(L,-2)) {
+ i = lua_tonumber(L,-2);
+ if (i > n) n = i;
+ }
+ lua_pop(L,1); /* pop value */
+ }
+ if (n>7) set_font_params(f,n);
+ /* sometimes it is handy to have all integer keys */
+ for (i=1;i<=7;i++) {
+ lua_rawgeti(L,-1,i);
+ if (lua_isnumber(L,-1)) {
+ n = lua_roundnumber(L,-1);
+ set_font_param(f,i, n);
+ }
+ lua_pop(L,1);
+ }
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, -2) != 0) {
+ if (lua_isnumber(L,-2)) {
+ i = lua_tointeger(L,-2);
+ if (i>=8) {
+ n = (lua_isnumber(L,-1) ? lua_roundnumber(L,-1) : 0);
+ set_font_param(f,i, n);
+ }
+ } else if (lua_isstring(L,-2)) {
+ s = (char *)lua_tostring(L,-2);
+ n = (lua_isnumber(L,-1) ? lua_roundnumber(L,-1) : 0);
+ if (luaS_ptr_eq(s,slant)) { set_font_param(f,slant_code,n); }
+ else if (luaS_ptr_eq(s,space)) { set_font_param(f,space_code,n); }
+ else if (luaS_ptr_eq(s,space_stretch)) { set_font_param(f,space_stretch_code,n); }
+ else if (luaS_ptr_eq(s,space_shrink)) { set_font_param(f,space_shrink_code,n); }
+ else if (luaS_ptr_eq(s,x_height)) { set_font_param(f,x_height_code,n); }
+ else if (luaS_ptr_eq(s,quad)) { set_font_param(f,quad_code,n); }
+ else if (luaS_ptr_eq(s,extra_space)) { set_font_param(f,extra_space_code,n); }
+ }
+ lua_pop(L,1);
+ }
+ }
+ lua_pop(L,1);
+
+}
+
+void
+font_char_from_lua (lua_State *L, internal_font_number f, integer i, integer *l_fonts) {
+ int k,r,t;
+ charinfo *co;
+ kerninfo *ckerns;
+ liginfo *cligs;
+ scaled j;
+ char *s;
+ int nl = 0; /* number of ligature table items */
+ int nk = 0; /* number of kern table items */
+ int ctr = 0;
+ int atsize = font_size(f);
+ if (lua_istable(L,-1)) {
+ co = get_charinfo(f,i);
+ set_charinfo_tag (co,0);
+ j = n_numeric_field(L,luaS_width_index,0); set_charinfo_width (co,j);
+ j = n_numeric_field(L,luaS_height_index,0); set_charinfo_height (co,j);
+ j = n_numeric_field(L,luaS_depth_index,0); set_charinfo_depth (co,j);
+ j = n_numeric_field(L,luaS_italic_index,0); set_charinfo_italic (co,j);
+ j = n_numeric_field(L,luaS_index_index,0); set_charinfo_index(co,j);
+ j = n_numeric_field(L,luaS_expansion_factor_index,0); set_charinfo_ef(co,j);
+ j = n_numeric_field(L,luaS_left_protruding_index,0); set_charinfo_lp(co,j);
+ j = n_numeric_field(L,luaS_right_protruding_index,0); set_charinfo_rp(co,j);
+ k = n_boolean_field(L,luaS_used_index,0); set_charinfo_used(co,k);
+ s = n_string_field (L,luaS_name_index,NULL); set_charinfo_name(co,s);
+ s = n_string_field (L,luaS_tounicode_index,NULL); set_charinfo_tounicode(co,s);
+ k = n_numeric_field(L,luaS_next_index,-1);
+ if (k>=0) {
+ set_charinfo_tag (co,list_tag);
+ set_charinfo_remainder (co,k);
+ }
+ lua_getfield(L,-1,"extensible");
+ if (lua_istable(L,-1)){
+ int top, bot,mid, rep;
+ top = n_numeric_field(L,luaS_top_index,0);
+ bot = n_numeric_field(L,luaS_bot_index,0);
+ mid = n_numeric_field(L,luaS_mid_index,0);
+ rep = n_numeric_field(L,luaS_rep_index,0);
+ if (top != 0 || bot != 0 || mid != 0 || rep != 0) {
+ set_charinfo_tag (co,ext_tag);
+ set_charinfo_extensible (co,top,bot,mid,rep);
+ } else {
+ pdftex_warn("lua-loaded font %s char [%d] has an invalid extensible field!",font_name(f),(int)i);
+ }
+ }
+ lua_pop(L,1);
+
+ nk = count_hash_items(L,luaS_index(kerns));
+ if (nk>0) {
+ ckerns = xcalloc((nk+1),sizeof(kerninfo));
+ lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(kerns));
+ lua_rawget(L,-2);
+ if (lua_istable(L,-1)) { /* there are kerns */
+ ctr = 0;
+ lua_pushnil(L);
+ while (lua_next(L, -2) != 0) {
+ k = non_boundarychar;
+ if (lua_isnumber(L,-2)) {
+ k = lua_tonumber(L,-2); /* adjacent char */
+ if (k<0)
+ k = non_boundarychar;
+ } else if (lua_isstring(L,-2)) {
+ s = (char *)lua_tostring(L,-2);
+ if (luaS_ptr_eq(s,right_boundary)) {
+ k = right_boundarychar;
+ if (!has_right_boundary(f))
+ set_right_boundary(f,get_charinfo(f,right_boundarychar));
+ }
+ }
+ j = lua_roundnumber(L,-1); /* movement */
+ if (k!=non_boundarychar) {
+ set_kern_item(ckerns[ctr],k,j);
+ ctr++;
+ } else {
+ pdftex_warn("lua-loaded font %s char [%d] has an invalid kern field!",font_name(f),(int)i);
+ }
+ lua_pop(L,1);
+ }
+ /* guard against empty tables */
+ if (ctr>0) {
+ set_kern_item(ckerns[ctr],end_kern,0);
+ set_charinfo_kerns(co,ckerns);
+ } else {
+ pdftex_warn("lua-loaded font %s char [%d] has an invalid kerns field!",font_name(f),(int)i);
+ }
+ }
+ lua_pop(L,1);
+ }
+
+ /* packet commands */
+ lua_getfield(L,-1,"commands");
+ if (lua_istable(L,-1)){
+ lua_pushnil(L); /* first key */
+ if (lua_next(L, -2) != 0) {
+ lua_pop(L,2);
+ read_char_packets(L,(integer *)l_fonts,co,atsize);
+ }
+ }
+ lua_pop(L,1);
+
+ /* ligatures */
+ nl = count_hash_items(L,luaS_index(ligatures));
+
+ if (nl>0) {
+ cligs = xcalloc((nl+1),sizeof(liginfo));
+ lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(ligatures));
+ lua_rawget(L,-2);
+ if (lua_istable(L,-1)){/* do ligs */
+ ctr = 0;
+ lua_pushnil(L);
+ while (lua_next(L, -2) != 0) {
+ k = non_boundarychar;
+ if (lua_isnumber(L,-2)) {
+ k = lua_tonumber(L,-2); /* adjacent char */
+ if (k<0) {
+ k = non_boundarychar;
+ }
+ } else if (lua_isstring(L,-2)) {
+ s = (char *)lua_tostring(L,-2);
+ if (luaS_ptr_eq(s,right_boundary)) {
+ k = right_boundarychar;
+ if (!has_right_boundary(f))
+ set_right_boundary(f,get_charinfo(f,right_boundarychar));
+ }
+ }
+ r = -1;
+ if (lua_istable(L,-1)) {
+ r = n_numeric_field(L,luaS_char_index,-1); /* ligature */
+ }
+ if (r != -1 && k != non_boundarychar) {
+ t = enum_field(L,"type",0,ligature_type_strings);
+ set_ligature_item(cligs[ctr],(t*2)+1,k,r);
+ ctr++;
+ } else {
+ pdftex_warn("lua-loaded font %s char [%d] has an invalid ligature field!",font_name(f),(int)i);
+ }
+ lua_pop(L,1); /* iterator value */
+ }
+ /* guard against empty tables */
+ if (ctr>0) {
+ set_ligature_item(cligs[ctr],0,end_ligature,0);
+ set_charinfo_ligatures(co,cligs);
+ } else {
+ pdftex_warn("lua-loaded font %s char [%d] has an invalid ligatures field!",font_name(f),(int)i);
+ }
+ }
+ lua_pop(L,1); /* ligatures table */
+ }
+ }
+}
+
+
+
+/* The caller has to fix the state of the lua stack when there is an error! */
+
+
+int
+font_from_lua (lua_State *L, int f) {
+ int i,n,r,t;
+ int s_top; /* lua stack top */
+ int bc; /* first char index */
+ int ec; /* last char index */
+ char *s;
+ integer *l_fonts = NULL;
+ /* the table is at stack index -1 */
+
+ if (luaS_width_index==0)
+ init_font_string_pointers(L);
+
+ s = string_field(L,"area",""); set_font_area(f,s);
+ s = string_field(L,"filename",NULL); set_font_filename(f,s);
+ s = string_field(L,"encodingname",NULL); set_font_encodingname(f,s);
+
+ s = string_field(L,"name",NULL); set_font_name(f,s);
+ s = string_field(L,"fullname",font_name(f)); set_font_fullname(f,s);
+
+ if (s==NULL) {
+ pdftex_fail("lua-loaded font [%d] has no name!",f);
+ return false;
+ }
+
+ i = numeric_field(L,"designsize",655360); set_font_dsize(f,i);
+ i = numeric_field(L,"size",font_dsize(f)); set_font_size(f,i);
+ i = numeric_field(L,"checksum",0); set_font_checksum(f,i);
+ i = numeric_field(L,"direction",0); set_font_natural_dir(f,i);
+ i = numeric_field(L,"encodingbytes",0); set_font_encodingbytes(f,i);
+ i = numeric_field(L,"tounicode",0); set_font_tounicode(f,i);
+
+ i = numeric_field(L,"extend",0);
+ if (i<-2000) i = -2000; if (i>2000) i = 2000; if (i==1000) i = 0;
+ set_font_extend(f,i);
+ i = numeric_field(L,"slant",0);
+ if (i<-1000) i = -1000; if (i>1000) i = 1000;
+ set_font_slant(f,i);
+
+ i = numeric_field(L,"hyphenchar",get_default_hyphen_char()); set_hyphen_char(f,i);
+ i = numeric_field(L,"skewchar",get_default_skew_char()); set_skew_char(f,i);
+ i = boolean_field(L,"used",0); set_font_used(f,i);
+
+ s = string_field (L,"attributes",NULL);
+ if (s!=NULL && strlen(s)>0) {
+ i = maketexstring(s);
+ set_pdf_font_attr(f,i);
+ }
+
+ i = enum_field(L,"type", unknown_font_type,font_type_strings); set_font_type(f,i);
+ i = enum_field(L,"format", unknown_format, font_format_strings); set_font_format(f,i);
+ i = enum_field(L,"embedding",unknown_embedding,font_embedding_strings); set_font_embedding(f,i);
+ if (font_encodingbytes(f)==0 &&
+ (font_format(f)==opentype_format || font_format(f)==truetype_format)) {
+ set_font_encodingbytes(f,2);
+ }
+
+ /* now fetch the base fonts, if needed */
+ n = count_hash_items(L,luaS_index(fonts));
+ if (n>0) {
+ l_fonts = xmalloc((n+2)*sizeof(integer));
+ memset (l_fonts,0,(n+2)*sizeof(integer));
+ lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(fonts));
+ lua_rawget(L,-2);
+ for (i=1;i<=n;i++) {
+ lua_rawgeti(L,-1,i);
+ if (lua_istable(L,-1)) {
+ lua_getfield(L,-1,"id");
+ if (lua_isnumber(L,-1)) {
+ l_fonts[i] = lua_tonumber(L,-1);
+ lua_pop(L,2); /* pop id and entry */
+ continue;
+ }
+ lua_pop(L,1); /* pop id */
+ };
+ s = NULL;
+ if (lua_istable(L,-1)) {
+ lua_getfield(L,-1,"name");
+ if (lua_isstring(L,-1)) {
+ s = (char *)lua_tostring(L,-1);
+ }
+ lua_pop(L,1); /* pop name */
+ }
+ if (s!= NULL) {
+ lua_getfield(L,-1,"size");
+ t = (lua_isnumber(L,-1) ? lua_roundnumber(L,-1) : -1000);
+ lua_pop(L,1);
+
+ /* TODO: the stack is messed up, otherwise this
+ * explicit resizing would not be needed
+ */
+ s_top = lua_gettop(L);
+ l_fonts[i] = find_font_id(s,"",t);
+ lua_settop(L,s_top);
+ } else {
+ pdftex_fail("Invalid local font in font %s!\n", font_name(f));
+ }
+ lua_pop(L,1); /* pop list entry */
+ }
+ lua_pop(L,1); /* pop list entry */
+ } else {
+ if(font_type(f) == virtual_font_type) {
+ pdftex_fail("Invalid local fonts in font %s!\n", font_name(f));
+ } else {
+ l_fonts = xmalloc(3*sizeof(integer));
+ l_fonts[0] = 0;
+ l_fonts[1] = f;
+ l_fonts[2] = 0;
+ }
+ }
+
+ /* parameters */
+ read_lua_parameters(L,f);
+ read_lua_cidinfo(L,f);
+
+ /* characters */
+ lua_getfield(L,-1,"characters");
+ if (lua_istable(L,-1)) {
+ /* find the array size values */
+ ec = 0; bc = -1;
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, -2) != 0) {
+ if (lua_isnumber(L,-2)) {
+ i = lua_tointeger(L,-2);
+ if (i>=0) {
+ if (lua_istable(L,-1)) {
+ if (i>ec) ec = i;
+ if (bc<0) bc = i;
+ if (bc>=0 && i<bc) bc = i;
+ }
+ }
+ }
+ lua_pop(L, 1);
+ }
+
+ if (bc != -1) {
+ /* fprintf(stdout,"defined a font at %d with %d-%d\n",f,bc,ec); */
+ set_font_bc(f,bc);
+ set_font_ec(f,ec);
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, -2) != 0) {
+ if (lua_isnumber(L,-2)) {
+ i = lua_tonumber(L,-2);
+ if (i>=0) {
+ font_char_from_lua(L,f, i, l_fonts);
+ }
+ } else if (lua_isstring(L,-2)) {
+ s = (char *)lua_tostring(L,-2);
+ if (luaS_ptr_eq(s,left_boundary)) {
+ font_char_from_lua(L,f, left_boundarychar, l_fonts);
+ } else if (luaS_ptr_eq(s,right_boundary)) {
+ font_char_from_lua(L,f, right_boundarychar, l_fonts);
+ }
+ }
+ lua_pop(L, 1);
+ }
+ lua_pop(L, 1);
+
+ /* handle font expansion last: the |copy_font| routine is called eventually,
+ and that needs to know |bc| and |ec|. */
+ if (font_type(f)!=virtual_font_type) {
+ int fstep = numeric_field(L,"step",0);
+ if (fstep<0) fstep = 0;
+ if (fstep>100) fstep = 100;
+ if (fstep!=0) {
+ int fshrink = numeric_field(L,"shrink",0);
+ int fstretch = numeric_field(L,"stretch",0);
+ int fexpand = boolean_field(L,"auto_expand",0);
+ if (fshrink<0) fshrink = 0;
+ if (fshrink>500) fshrink = 500;
+ fshrink -= (fshrink % fstep);
+ if (fshrink<0) fshrink = 0;
+ if (fstretch<0) fstretch = 0;
+ if (fstretch>1000) fstretch = 1000;
+ fstretch -= (fstretch % fstep);
+ if (fstretch<0) fstretch = 0;
+ set_expand_params(f, fexpand, fstretch, fshrink, fstep, 0);
+ }
+ }
+
+ } else { /* jikes, no characters */
+ pdftex_warn("lua-loaded font [%d] (%s) has no characters!",f, font_name(f));
+ }
+
+#if SAVE_REF
+ r = luaL_ref(Luas[0],LUA_REGISTRYINDEX); /* pops the table */
+ set_font_cache_id(f,r);
+#else
+ lua_pop(Luas[0],1);
+#endif
+ } else { /* jikes, no characters */
+ pdftex_warn("lua-loaded font [%d] (%s) has no character table!",f, font_name(f));
+ }
+
+ if (l_fonts!=NULL)
+ free(l_fonts);
+ return true;
+}
+
+/* ====================================================================
+ *
+ * L I G A T U R I N G
+ *
+ * ==================================================================== */
+
+
+#define assert_disc(a) \
+ assert(pre_break(a)!=null); /* expect head_node */ \
+ assert(type(pre_break(a))==nesting_node); \
+ assert((vlink_pre_break(a)==null && tlink_pre_break(a)==null) || tail_of_list(vlink_pre_break(a))==tlink_pre_break(a)); \
+ assert(post_break(a)!=null); /* expect head_node */ \
+ assert(type(post_break(a))==nesting_node); \
+ assert((vlink_post_break(a)==null && tlink_post_break(a)==null) || tail_of_list(vlink_post_break(a))==tlink_post_break(a)); \
+ assert(no_break(a)!=null); /* expect head_node */ \
+ assert(type(no_break(a))==nesting_node); \
+ assert((vlink_no_break(a)==null && tlink_no_break(a)==null) || tail_of_list(vlink_no_break(a))==tlink_no_break(a));
+
+static void
+nesting_append (halfword nest, halfword newn) {
+ halfword tail = tlink(nest);
+ assert(alink(nest)==null);
+ assert(vlink(newn)==null);
+ assert(alink(newn)==null);
+ if (tail==null) {
+ assert(vlink(nest)==null);
+ couple_nodes(nest,newn);
+ } else {
+ assert(vlink(tail)==null);
+ assert(tail_of_list(vlink(nest))==tail);
+ couple_nodes(tail,newn);
+ }
+ tlink(nest) = newn;
+}
+
+
+static void
+nesting_prepend (halfword nest, halfword newn) {
+ halfword head = vlink(nest);
+ assert(alink(nest)==null);
+ assert(vlink(newn)==null);
+ assert(alink(newn)==null);
+ couple_nodes(nest,newn);
+ if (head==null) {
+ assert(tlink(nest)==null);
+ tlink(nest) = newn;
+ } else {
+ assert(alink(head)==nest);
+ assert(tail_of_list(head)==tlink(nest));
+ couple_nodes(newn,head);
+ }
+}
+
+
+static int
+test_ligature( liginfo *lig, halfword left, halfword right ) {
+ if (type(left)!=glyph_node)
+ return 0;
+ assert(type(right)==glyph_node);
+ if (font(left)!=font(right)) return 0;
+ if (is_ghost(left) || is_ghost(right)) return 0;
+ *lig = get_ligature(font(left),character(left),character(right));
+ if (is_valid_ligature(*lig)) {
+ return 1;
+ }
+ return 0;
+}
+
+
+static int
+try_ligature(halfword *frst, halfword fwd) {
+ halfword cur = *frst;
+ liginfo lig;
+ if (test_ligature(&lig,cur,fwd)) {
+ int move_after = (lig_type(lig) & 0x0C)>>2;
+ int keep_right = ((lig_type(lig) & 0x01) != 0);
+ int keep_left = ((lig_type(lig) & 0x02) != 0);
+ halfword newgl = raw_glyph_node();
+ font(newgl) = font(cur);
+ character(newgl) = lig_replacement(lig);
+ set_is_ligature(newgl);
+
+ /* below might not be correct in contrived border case.
+ * but we use it only for debugging, so ... */
+ if (character(cur)<0) {
+ set_is_leftboundary(newgl);
+ }
+ if (character(fwd)<0) {
+ set_is_rightboundary(newgl);
+ }
+ if (character(cur)<0) {
+ if (character(fwd)<0) {
+ build_attribute_list(newgl);
+ } else {
+ add_node_attr_ref(node_attr(fwd));
+ node_attr(newgl) = node_attr(fwd);
+ }
+ } else {
+ add_node_attr_ref(node_attr(cur));
+ node_attr(newgl) = node_attr(cur);
+ }
+
+ /* TODO/FIXME if this ligature is consists of another ligature
+ * we should add it's lig_ptr to the new glyphs lig_ptr (and
+ * cleanup the no longer needed node) LOW PRIORITY */
+ /* left side */
+ if (keep_left) {
+ halfword new_first = copy_node(cur);
+ lig_ptr(newgl) = new_first;
+ couple_nodes(cur,newgl);
+ if (move_after) {
+ move_after--;
+ cur = newgl;
+ }
+ } else {
+ halfword prev = alink(cur);
+ uncouple_node(cur);
+ lig_ptr(newgl) = cur;
+ assert(prev!=null);
+ couple_nodes(prev,newgl);
+ cur = newgl; /* as cur has disappeared */
+ }
+ /* right side */
+ if (keep_right) {
+ halfword new_second = copy_node(fwd);
+ /* correct, because we _know_ lig_ptr points to _one_ node */
+ couple_nodes(lig_ptr(newgl),new_second);
+ couple_nodes(newgl,fwd);
+ if (move_after) {
+ move_after--;
+ cur = fwd;
+ }
+ } else {
+ halfword next = vlink(fwd);
+ uncouple_node(fwd);
+ /* correct, because we _know_ lig_ptr points to _one_ node */
+ couple_nodes(lig_ptr(newgl),fwd);
+ if (next!=null) {couple_nodes(newgl,next);}
+ }
+
+ /* check and return */
+ /* assert(move_after==0);*/
+ *frst = cur;
+ return 1;
+ }
+ return 0;
+}
+
+
+/* there shouldn't be any ligatures here - we only add them at the end of
+ * xxx_break in a DISC-1 - DISC-2 situation and we stop processing DISC-1
+ * (we continue with DISC-1's post_ and no_break */
+static halfword
+handle_lig_nest(halfword root, halfword cur) {
+ if (cur==null) return root;
+ while (vlink(cur)!=null) {
+ halfword fwd = vlink(cur);
+ if (type(cur)==glyph_node && type(fwd)==glyph_node &&
+ font(cur)==font(fwd) && try_ligature(&cur,fwd)) continue;
+ cur = vlink(cur);
+ assert(vlink(alink(cur))==cur);
+ }
+ tlink(root) = cur;
+ return root;
+}
+
+
+static halfword
+handle_lig_word(halfword cur) {
+ halfword right=null;
+
+ if (type(cur)==whatsit_node && subtype(cur)==cancel_boundary_node) {
+ halfword prev= alink(cur);
+ halfword fwd = vlink(cur);
+/* uncouple_node(cur); */ /* not needed, it is freed */
+ flush_node(cur);
+ if (fwd==null) {
+ vlink(prev) = fwd;
+ return prev;
+ }
+ couple_nodes(prev,fwd);
+ if (type(fwd)!=glyph_node) return prev;
+ cur = fwd;
+ } else if (has_left_boundary(font(cur))) {
+ halfword prev= alink(cur);
+ halfword p = new_glyph(font(cur),left_boundarychar);
+ couple_nodes(prev,p);
+ couple_nodes(p,cur);
+ cur = p;
+ }
+ if (has_right_boundary(font(cur))) {
+ right = new_glyph(font(cur),right_boundarychar);
+ }
+
+ while (1) {
+ /* A glyph followed by ... */
+ if (type(cur)==glyph_node) {
+ halfword fwd = vlink(cur);
+ if (fwd==null) { /* last character of paragraph */
+ if (right==null) break;
+ couple_nodes(cur,right);
+ right = null;
+ continue;
+ }
+ assert(alink(fwd)==cur);
+ if (type(fwd)==glyph_node) { /* GLYPH - GLYPH */
+ if (font(cur)!=font(fwd)) break;
+ if (try_ligature(&cur,fwd)) continue;
+ } else if (type(fwd)==disc_node) { /* GLYPH - DISC */
+
+ /* if a{bx}{}{y} and a+b=>B convert to {Bx}{}{ay} */
+ halfword pre = vlink_pre_break(fwd);
+ halfword nob = vlink_no_break(fwd);
+ liginfo lig;
+ assert_disc(fwd);
+ /* Check on: a{b?}{?}{?} and a+b=>B : {B?}{?}{a?}*/
+ /* Check on: a{?}{?}{b?} and a+b=>B : {a?}{?}{B?} */
+ if ( (pre!=null && type(pre)==glyph_node && test_ligature(&lig,cur,pre))
+ || (nob!=null && type(nob)==glyph_node && test_ligature(&lig,cur,nob))) {
+ /* move cur from before disc, to skipped part */
+ halfword prev = alink(cur);
+ assert(vlink(prev)==cur);
+ uncouple_node(cur);
+ couple_nodes(prev,fwd);
+ nesting_prepend(no_break(fwd),cur);
+ /* now ligature the pre_break */
+ nesting_prepend(pre_break(fwd),copy_node(cur));
+ /* As we have removed cur, we need to start again ... */
+ cur = prev;
+ }
+ /* Check on: a{?}{?}{}b and a+b=>B : {a?}{?b}{B}*/
+ halfword next = vlink(fwd);
+ if (nob==null && next != null && type(next)==glyph_node
+ && test_ligature(&lig,cur,next)) {
+ /* move cur from before disc to no_break part */
+ halfword prev = alink(cur);
+ assert(alink(next)==fwd);
+ assert(vlink(prev)==cur);
+ uncouple_node(cur);
+ couple_nodes(prev,fwd);
+ couple_nodes(no_break(fwd),cur); /* we _know_ it's empty */
+ /* now copy cur the pre_break */
+ nesting_prepend(pre_break(fwd),copy_node(cur));
+ /* move next from after disc to no_break part */
+ halfword tail = vlink(next);
+ uncouple_node(next);
+ try_couple_nodes(fwd,tail);
+ couple_nodes(cur,next); /* we _know_ this works */
+ tlink(no_break(fwd)) = next; /* and make sure the list is correct */
+ /* now copy next to the post_break */
+ nesting_append(post_break(fwd),copy_node(next));
+ /* As we have removed cur, we need to start again ... */
+ cur = prev;
+ }
+ /* we are finished with the pre_break */
+ handle_lig_nest(pre_break(fwd),vlink_pre_break(fwd));
+ } else if (type(fwd)==whatsit_node && subtype(fwd)==cancel_boundary_node) {
+ halfword next = vlink(fwd);
+ try_couple_nodes(cur,next);
+ flush_node(fwd);
+ if (right!=null) {
+ flush_node(right); /* Shame, didn't need it */
+ /* right = null; */ /* no need, we're going to leave the loop anyway */
+ }
+ break;
+ } else { /* fwd is something unknown */
+ if (right==null) break;
+ couple_nodes(cur,right);
+ couple_nodes(right,fwd);
+ right = null;
+ continue;
+ }
+ /* A discretionary followed by ... */
+ } else if (type(cur)==disc_node) {
+ assert_disc(cur);
+ /* If {?}{x}{?} or {?}{?}{y} then ... */
+ if (vlink_no_break(cur)!=null || vlink_post_break(cur)!=null) {
+ halfword fwd;
+ halfword lists[511]; /* max 8 levels */
+
+ int i, max_depth=0;
+ lists[max_depth++] = handle_lig_nest(post_break(cur),vlink_post_break(cur));
+ lists[max_depth++] = handle_lig_nest(no_break(cur),vlink_no_break(cur));
+ while (1) {
+ if ((fwd = vlink(cur))==null) return cur;
+ if ( type(fwd)==glyph_node) {
+ for (i=0; i<max_depth; i++) {
+ liginfo lig;
+ halfword tail = tlink(lists[i]);
+ if ( tail!=null && test_ligature(&lig,tail,fwd))
+ goto add_glyph_to_all;
+ }
+ /* if we get here, nothing had a ligature, so we stop */
+ break;
+add_glyph_to_all:
+ for (i=0; i<max_depth; i++) {
+ halfword copy = copy_node(fwd);
+ halfword tail = tlink(lists[i]);
+ nesting_append(lists[i],copy);
+ if (tail==null) continue; /* first character - never a ligature */
+ handle_lig_nest(lists[i],tail);
+ }
+ halfword next = vlink(fwd);
+ uncouple_node(fwd);
+ try_couple_nodes(cur,next);
+ flush_node(fwd);
+ } else if ( type(fwd)==disc_node) {
+ /* MAGIC WARNING
+ * A disc followed by a disc can have different kernings
+ * depending on which path is choosen, and it is impossible to
+ * store the possible kernings: fe {}{A}{W} {V}{}{A}
+ * So we _always_ add discs so only a simple path remains. */
+ int m=max_depth; /* as max_depth changes in this loop */
+ for (i=0; i<m; i++) {
+ halfword copy = copy_node(fwd);
+ halfword tail = tlink(lists[i]);
+ if (tail!=null) {
+ halfword prev = alink(tail);
+ assert(alink(tail)!=null);
+ uncouple_node(tail);
+ vlink(prev) = null;
+ if (prev==lists[i]) {
+ tlink(prev) = null;
+ } else {
+ tlink(lists[i]) = prev;
+ }
+ nesting_prepend(pre_break(copy),tail);
+ nesting_prepend(no_break(copy),copy_node(tail));
+ }
+ nesting_append(lists[i],copy);
+ handle_lig_nest(pre_break(copy),vlink_pre_break(copy));
+ assert(max_depth<256);
+ lists[max_depth++] = handle_lig_nest(no_break(copy),vlink_no_break(copy));
+ lists[i] = handle_lig_nest(post_break(copy),vlink_post_break(copy));
+ }
+ halfword next = vlink(fwd);
+ uncouple_node(fwd);
+ try_couple_nodes(cur,next);
+ flush_node(fwd);
+ } else {
+ return cur;
+ }
+ }
+ }
+ } else { /* NO GLYPH NOR DISC */
+ /* fprintf(stdout,"This is a %d node\n",type(cur));*/
+ /* assert(0);*/ /* TODO howcome there can be a glue here? */
+ return cur;
+ }
+ /* step-to-next-node */
+ {
+ halfword prev = cur;
+ cur = vlink(cur);
+ assert(cur!=null);
+ assert(alink(cur)==prev);
+ /* alink(cur) = prev;*/
+ }
+ }
+
+ return cur;
+}
+
+/* return = new tail, head should be a dummy */
+
+halfword
+handle_ligaturing(halfword head, halfword tail) {
+ halfword save_tail ; /* trick to allow explicit node==null tests */
+ halfword cur, prev;
+
+ if (vlink(head)==null)
+ return tail;
+ save_tail = vlink(tail);
+ vlink(tail) = null;
+
+ /* if (fix_node_lists) */
+ fix_node_list(head);
+
+ prev = head;
+ cur = vlink(prev);
+
+ while (cur!=null) {
+ if ( type(cur)==glyph_node ||
+ (type(cur)==whatsit_node && subtype(cur)==cancel_boundary_node)) {
+ cur = handle_lig_word(cur);
+ }
+ prev = cur;
+ cur = vlink(cur);
+ assert(cur==null||alink(cur) == prev);
+ }
+ if (valid_node(save_tail)) {
+ try_couple_nodes(prev,save_tail);
+ }
+ return prev;
+}
+
+
+/* ====================================================================
+ *
+ * K E R N I N G
+ *
+ * ==================================================================== */
+
+static void
+add_kern_before(halfword left, halfword right) {
+ if ((!is_rightghost(right)) &&
+ font(left)==font(right) &&
+ has_kern(font(left),character(left))) {
+ int k = get_kern(font(left),character(left),character(right));
+ if (k!=0) {
+ halfword kern = new_kern(k);
+ halfword prev = alink(right);
+ assert(vlink(prev)==right);
+ couple_nodes(prev,kern);
+ couple_nodes(kern,right);
+ }
+ }
+}
+
+
+static void
+add_kern_after(halfword left, halfword right, halfword aft) {
+ if ((!is_rightghost(right)) &&
+ font(left)==font(right) &&
+ has_kern(font(left),character(left))) {
+ int k = get_kern(font(left),character(left),character(right));
+ if (k!=0) {
+ halfword kern = new_kern(k);
+ halfword next = vlink(aft);
+ assert(next==null||alink(next)==aft);
+ couple_nodes(aft,kern);
+ try_couple_nodes(kern,next);
+ }
+ }
+}
+
+
+static void
+do_handle_kerning (halfword root, halfword init_left, halfword init_right) {
+ halfword cur = vlink(root);
+ halfword left = null;
+ assert(init_left==null || type(init_left)==glyph_node);
+ assert(init_right==null || type(init_right)==glyph_node);
+ if (cur==null) {
+ if (init_left!=null && init_right!=null) {
+ add_kern_after(init_left,init_right,root);
+ tlink(root)=vlink(root);
+ }
+ return;
+ }
+ if (type(cur)==glyph_node) {
+ set_is_glyph(cur);
+ if (init_left!=null)
+ add_kern_before(init_left,cur);
+ left = cur;
+ }
+ while ((cur=vlink(cur))!=null) {
+ if (type(cur)==glyph_node) {
+ set_is_glyph(cur);
+ if (left != null) {
+ add_kern_before(left,cur);
+ if (character(left)<0 || is_ghost(left)) {
+ halfword prev = alink(left);
+ couple_nodes(prev,cur);
+ flush_node(left);
+ }
+ }
+ left = cur;
+ } else {
+ if (type(cur)==disc_node) {
+ halfword right= type(vlink(cur))==glyph_node ? vlink(cur) : null;
+ do_handle_kerning(pre_break(cur),left,null);
+ do_handle_kerning(post_break(cur),null,right);
+ do_handle_kerning(no_break(cur),left,right);
+ }
+ if (left != null) {
+ if (character(left)<0 || is_ghost(left)) {
+ halfword prev = alink(left);
+ couple_nodes(prev,cur);
+ flush_node(left);
+ }
+ left = null;
+ }
+ }
+ }
+ if (left!=null) {
+ if (init_right!=null)
+ add_kern_after(left,init_right,left);
+ if (character(left)<0 || is_ghost(left)) {
+ halfword prev = alink(left);
+ halfword next = vlink(left);
+ if (next!=null) {
+ couple_nodes(prev,next);
+ tlink(root) = next;
+ assert(vlink(next)==null);
+ assert(type(next)==kern_node);
+ } else if (prev!=root) {
+ vlink(prev) = null;
+ tlink(root) = prev;
+ } else {
+ vlink(root) = null;
+ tlink(root) = null;
+ }
+ flush_node(left);
+ }
+ }
+}
+
+
+halfword
+handle_kerning (halfword head, halfword tail) {
+ halfword save_link;
+ save_link = vlink(tail);
+ vlink(tail) = null;
+ tlink(head) = tail;
+ do_handle_kerning(head,null,null);
+ tail = tlink(head);
+ if (valid_node(save_link)) {
+ try_couple_nodes(tail,save_link);
+ }
+ return tail;
+}
+
+/* ====================================================================
+ *
+ * L I G A T U R I N G and K E R N I N G : L U A - I N T E R F A C E
+ *
+ * ==================================================================== */
+
+static halfword
+run_lua_ligkern_callback (halfword head, halfword tail, int callback_id){
+ lua_State *L = Luas[0];
+ lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id);
+ lua_rawgeti(L,-1, callback_id);
+ if (!lua_isfunction(L,-1)) {
+ lua_pop(L,2);
+ return tail;
+ }
+ nodelist_to_lua(L,head);
+ nodelist_to_lua(L,tail);
+ if (lua_pcall(L,2,1,0) != 0) {
+ fprintf(stdout,"error: %s\n",lua_tostring(L,-1));
+ lua_pop(L,2);
+ lua_error(L);
+ return tail;
+ }
+ tail = nodelist_from_lua(L);
+ if (fix_node_lists)
+ fix_node_list(head);
+ lua_pop(L,2);
+ return tail;
+}
+
+
+halfword
+new_ligkern(halfword head, halfword tail) {
+ int callback_id = 0;
+
+ assert(head!=null);
+ if (vlink(head)==null)
+ return tail;
+
+ callback_id = callback_defined(ligaturing_callback);
+ if (callback_id>0) {
+ tail = run_lua_ligkern_callback(head,tail,callback_id);
+ if (tail==null) tail = tail_of_list(head);
+ } else {
+ tail = handle_ligaturing(head,tail);
+ }
+
+ callback_id = callback_defined(kerning_callback);
+ if (callback_id>0) {
+ tail = run_lua_ligkern_callback(head,tail,callback_id);
+ if (tail==null) tail = tail_of_list(head);
+ } else {
+ halfword nest = new_node(nesting_node,1);
+ halfword cur = vlink(head);
+ halfword aft = vlink(tail);
+ couple_nodes(nest,cur);
+ tlink(nest)=tail;
+ vlink(tail)=null;
+ do_handle_kerning(nest,null,null);
+ couple_nodes(head,vlink(nest));
+ tail = tlink(nest);
+ try_couple_nodes(tail,aft);
+ flush_node(nest);
+ }
+ return tail;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/font/macnames.c b/Build/source/texk/web2c/luatexdir/font/macnames.c
new file mode 100644
index 00000000000..941f087ef56
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/macnames.c
@@ -0,0 +1,312 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: macnames.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+const char notdef[] = ".notdef";
+
+const char *mac_glyph_names[] = {
+/* 0x00 */
+ notdef,
+ ".null",
+ "CR",
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quotesingle",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+/* 0x10 */
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+/* 0x20 */
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+/* 0x30 */
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+/* 0x40 */
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "grave",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+/* 0x50 */
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+/* 0x60 */
+ "braceright",
+ "asciitilde",
+ "Adieresis",
+ "Aring",
+ "Ccedilla",
+ "Eacute",
+ "Ntilde",
+ "Odieresis",
+ "Udieresis",
+ "aacute",
+ "agrave",
+ "acircumflex",
+ "adieresis",
+ "atilde",
+ "aring",
+ "ccedilla",
+/* 0x70 */
+ "eacute",
+ "egrave",
+ "ecircumflex",
+ "edieresis",
+ "iacute",
+ "igrave",
+ "icircumflex",
+ "idieresis",
+ "ntilde",
+ "oacute",
+ "ograve",
+ "ocircumflex",
+ "odieresis",
+ "otilde",
+ "uacute",
+ "ugrave",
+/* 0x80 */
+ "ucircumflex",
+ "udieresis",
+ "dagger",
+ "degree",
+ "cent",
+ "sterling",
+ "section",
+ "bullet",
+ "paragraph",
+ "germandbls",
+ "registered",
+ "copyright",
+ "trademark",
+ "acute",
+ "dieresis",
+ "notequal",
+/* 0x90 */
+ "AE",
+ "Oslash",
+ "infinity",
+ "plusminus",
+ "lessequal",
+ "greaterequal",
+ "yen",
+ "mu",
+ "partialdiff",
+ "Sigma",
+ "Pi",
+ "pi",
+ "integral",
+ "ordfeminine",
+ "ordmasculine",
+ "Omega",
+/* 0xa0 */
+ "ae",
+ "oslash",
+ "questiondown",
+ "exclamdown",
+ "logicalnot",
+ "radical",
+ "florin",
+ "approxequal",
+ "Delta",
+ "guillemotleft",
+ "guillemotright",
+ "ellipsis",
+ "nbspace",
+ "Agrave",
+ "Atilde",
+ "Otilde",
+/* 0xb0 */
+ "OE",
+ "oe",
+ "endash",
+ "emdash",
+ "quotedblleft",
+ "quotedblright",
+ "quoteleft",
+ "quoteright",
+ "divide",
+ "lozenge",
+ "ydieresis",
+ "Ydieresis",
+ "fraction",
+ "currency",
+ "guilsinglleft",
+ "guilsinglright",
+/* 0xc0 */
+ "fi",
+ "fl",
+ "daggerdbl",
+ "periodcentered",
+ "quotesinglbase",
+ "quotedblbase",
+ "perthousand",
+ "Acircumflex",
+ "Ecircumflex",
+ "Aacute",
+ "Edieresis",
+ "Egrave",
+ "Iacute",
+ "Icircumflex",
+ "Idieresis",
+ "Igrave",
+/* 0xd0 */
+ "Oacute",
+ "Ocircumflex",
+ "applelogo",
+ "Ograve",
+ "Uacute",
+ "Ucircumflex",
+ "Ugrave",
+ "dotlessi",
+ "circumflex",
+ "tilde",
+ "macron",
+ "breve",
+ "dotaccent",
+ "ring",
+ "cedilla",
+ "hungarumlaut",
+/* 0xe0 */
+ "ogonek",
+ "caron",
+ "Lslash",
+ "lslash",
+ "Scaron",
+ "scaron",
+ "Zcaron",
+ "zcaron",
+ "brokenbar",
+ "Eth",
+ "eth",
+ "Yacute",
+ "yacute",
+ "Thorn",
+ "thorn",
+ "minus",
+/* 0xf0 */
+ "multiply",
+ "onesuperior",
+ "twosuperior",
+ "threesuperior",
+ "onehalf",
+ "onequarter",
+ "threequarters",
+ "franc",
+ "Gbreve",
+ "gbreve",
+ "Idot",
+ "Scedilla",
+ "scedilla",
+ "Cacute",
+ "cacute",
+ "Ccaron",
+/* 0x100 */
+ "ccaron",
+ "dmacron"
+};
+
+const char *ambiguous_names[] = {
+ "Delta", /* increment */
+ "Omega", /* Ohm */
+ "Pi", /* product */
+ "Sigma", /* summation */
+ "dmacron", /* dslash */
+ "macron", /* overscore */
+ "periodcentered", /* middot */
+ NULL
+};
diff --git a/Build/source/texk/web2c/luatexdir/font/mapfile.c b/Build/source/texk/web2c/luatexdir/font/mapfile.c
new file mode 100644
index 00000000000..1c444e5c1d4
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/mapfile.c
@@ -0,0 +1,967 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: mapfile.c 1013 2008-02-14 00:09:02Z oneiros $
+
+*/
+
+#include <math.h>
+#include "ptexlib.h"
+#include <kpathsea/c-auto.h>
+#include <kpathsea/c-memstr.h>
+#include <string.h>
+#include "luatex-api.h"
+
+#define FM_BUF_SIZE 1024
+
+static FILE *fm_file;
+
+static unsigned char *fm_buffer = NULL;
+static integer fm_size = 0;
+static integer fm_curbyte = 0;
+
+#define fm_open() \
+ open_input (&fm_file, kpse_fontmap_format, FOPEN_RBIN_MODE)
+#define fm_read_file() \
+ readbinfile(fm_file,&fm_buffer,&fm_size)
+#define fm_close() xfclose(fm_file, cur_file_name)
+#define fm_getchar() fm_buffer[fm_curbyte++]
+#define fm_eof() (fm_curbyte>=fm_size)
+
+typedef enum { FM_DUPIGNORE, FM_REPLACE, FM_DELETE } updatemode;
+typedef enum { MAPFILE, MAPLINE } maptype;
+
+typedef struct mitem {
+ updatemode mode; /* FM_DUPIGNORE or FM_REPLACE or FM_DELETE */
+ maptype type; /* map file or map line */
+ char *line; /* pointer to map file name or map line */
+ int lineno; /* line number in map file */
+} mapitem;
+mapitem *mitem = NULL;
+
+static const char nontfm[] = "<nontfm>";
+
+#define read_field(r, q, buf) do { \
+ q = buf; \
+ while (*r != ' ' && *r != '<' && *r != '"' && *r != '\0') \
+ *q++ = *r++; \
+ *q = '\0'; \
+ skip (r, ' '); \
+} while (0)
+
+#define set_field(F) do { \
+ if (q > buf) \
+ fm->F = xstrdup(buf); \
+ if (*r == '\0') \
+ goto done; \
+} while (0)
+
+fm_entry *new_fm_entry(void)
+{
+ fm_entry *fm;
+ fm = xtalloc(1, fm_entry);
+ fm->tfm_name = NULL;
+ fm->sfd_name = NULL;
+ fm->ps_name = NULL;
+ fm->fd_flags = 4;
+ fm->ff_name = NULL;
+ fm->encname = NULL;
+ fm->type = 0;
+ fm->slant = 0;
+ fm->extend = 0;
+ fm->links = 0;
+ fm->pid = -1;
+ fm->eid = -1;
+ fm->subfont = NULL;
+ fm->in_use = false;
+ return fm;
+}
+
+void delete_fm_entry(fm_entry * fm)
+{
+ xfree(fm->tfm_name);
+ xfree(fm->sfd_name);
+ xfree(fm->ps_name);
+ xfree(fm->ff_name);
+ xfree(fm);
+}
+
+static ff_entry *new_ff_entry (void)
+{
+ ff_entry *ff;
+ ff = xtalloc (1, ff_entry);
+ ff->ff_name = NULL;
+ ff->ff_path = NULL;
+ return ff;
+}
+
+static void delete_ff_entry (ff_entry * ff)
+{
+ xfree (ff->ff_name);
+ xfree (ff->ff_path);
+ xfree (ff);
+}
+
+static fm_entry *dummy_fm_entry ()
+{
+ static const fm_entry const_fm_entry;
+ return (fm_entry *) & const_fm_entry;
+}
+
+/**********************************************************************/
+
+struct avl_table *tfm_tree = NULL;
+struct avl_table *ps_tree = NULL;
+struct avl_table *ff_tree = NULL;
+struct avl_table *encname_tree = NULL;
+
+/* AVL sort fm_entry into tfm_tree by tfm_name */
+
+static int comp_fm_entry_tfm (const void *pa, const void *pb, void *p)
+{
+ return strcmp (((const fm_entry *) pa)->tfm_name,
+ ((const fm_entry *) pb)->tfm_name);
+}
+
+/* AVL sort fm_entry into ps_tree by ps_name, slant, and extend */
+
+static int comp_fm_entry_ps(const void *pa, const void *pb, void *p)
+{
+ int i;
+ const fm_entry *p1 = (const fm_entry *) pa, *p2 = (const fm_entry *) pb;
+ assert(p1->ps_name != NULL && p2->ps_name != NULL);
+ if ((i = strcmp(p1->ps_name, p2->ps_name)))
+ return i;
+ cmp_return(p1->slant, p2->slant);
+ cmp_return(p1->extend, p2->extend);
+ return 0;
+}
+
+/* AVL sort ff_entry into ff_tree by ff_name */
+
+static int comp_ff_entry (const void *pa, const void *pb, void *p)
+{
+ return strcmp (((const ff_entry *) pa)->ff_name,
+ ((const ff_entry *) pb)->ff_name);
+}
+
+static void create_avl_trees ()
+{
+ assert(tfm_tree == NULL);
+ tfm_tree = avl_create(comp_fm_entry_tfm, NULL, &avl_xallocator);
+ assert(tfm_tree != NULL);
+ assert(ps_tree == NULL);
+ ps_tree = avl_create(comp_fm_entry_ps, NULL, &avl_xallocator);
+ assert(ps_tree != NULL);
+ assert(ff_tree == NULL);
+ ff_tree = avl_create(comp_ff_entry, NULL, &avl_xallocator);
+ assert(ff_tree != NULL);
+ assert(encname_tree == NULL);
+ encname_tree = avl_create(comp_string_entry, NULL, &avl_xallocator);
+ assert(encname_tree != NULL);
+}
+
+/*
+The function avl_do_entry() is not completely symmetrical with regards
+to tfm_name and ps_name handling, e. g. a duplicate tfm_name gives a
+"goto exit", and no ps_name link is tried. This is to keep it compatible
+with the original version.
+*/
+
+int avl_do_entry(fm_entry * fm, int mode)
+{
+ fm_entry *p;
+ void *a;
+ void **aa;
+
+ /* handle tfm_name link */
+
+ if (strcmp(fm->tfm_name, nontfm)) {
+ p = (fm_entry *) avl_find(tfm_tree, fm);
+ if (p != NULL) {
+ switch (mode) {
+ case FM_DUPIGNORE:
+ pdftex_warn
+ ("fontmap entry for `%s' already exists, duplicates ignored",
+ fm->tfm_name);
+ goto exit;
+ break;
+ case FM_REPLACE:
+ case FM_DELETE:
+ if (p->in_use) {
+ pdftex_warn
+ ("fontmap entry for `%s' has been used, replace/delete not allowed",
+ fm->tfm_name);
+ goto exit;
+ }
+ a = avl_delete(tfm_tree, p);
+ assert(a != NULL);
+ unset_tfmlink(p);
+ if (!has_pslink(p))
+ delete_fm_entry(p);
+ break;
+ default:
+ assert(0);
+ }
+ }
+ if (mode != FM_DELETE) {
+ aa = avl_probe(tfm_tree, fm);
+ assert(aa != NULL);
+ set_tfmlink(fm);
+ }
+ }
+
+ /* handle ps_name link */
+
+ if (fm->ps_name != NULL) {
+ p = (fm_entry *) avl_find(ps_tree, fm);
+ if (p != NULL) {
+ switch (mode) {
+ case FM_DUPIGNORE:
+ goto exit;
+ break;
+ case FM_REPLACE:
+ case FM_DELETE:
+ if (p->in_use)
+ goto exit;
+ a = avl_delete(ps_tree, p);
+ assert(a != NULL);
+ unset_pslink(p);
+ if (!has_tfmlink(p))
+ delete_fm_entry(p);
+ break;
+ default:
+ assert(0);
+ }
+ }
+ if (mode != FM_DELETE && is_t1fontfile(fm) && is_included(fm)) {
+ aa = avl_probe(ps_tree, fm);
+ assert(aa != NULL);
+ set_pslink(fm);
+ }
+ }
+ exit:
+ if (!has_tfmlink(fm) && !has_pslink(fm)) /* e. g. after FM_DELETE */
+ return 1; /* deallocation of fm_entry structure required */
+ else
+ return 0;
+}
+
+/* add the encoding name to an AVL tree. this has nothing to do with writeenc.c */
+
+char *add_encname(char *s)
+{
+ char *p;
+ void **aa;
+ assert(s != NULL);
+ assert(encname_tree != NULL);
+ if ((p = (char *) avl_find(encname_tree, s)) == NULL) { /* encoding name not yet registered */
+ p = xstrdup(s);
+ aa = avl_probe(encname_tree, p);
+ assert(aa != NULL);
+ }
+ return p;
+}
+
+/**********************************************************************/
+/* consistency check for map entry, with warn flag */
+
+int check_fm_entry(fm_entry * fm, boolean warn)
+{
+ int a = 0;
+ assert(fm != NULL);
+
+ if (is_fontfile(fm) && !is_included(fm)) {
+ if (warn)
+ pdftex_warn
+ ("ambiguous entry for `%s': font file present but not included, "
+ "will be treated as font file not present", fm->tfm_name);
+ xfree(fm->ff_name);
+ /* do not set variable |a| as this entry will be still accepted */
+ }
+
+ /* if both ps_name and font file are missing, drop this entry */
+ if (fm->ps_name == NULL && !is_fontfile(fm)) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': both ps_name and font file missing",
+ fm->tfm_name);
+ a += 1;
+ }
+
+ /* TrueType fonts cannot be reencoded without subsetting */
+ if (is_truetype(fm) && is_reencoded(fm) && !is_subsetted(fm)) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': only subsetted TrueType font can be reencoded",
+ fm->tfm_name);
+ a += 2;
+ }
+
+ /* SlantFont and ExtendFont can be used only with Type1 fonts */
+ if ((fm->slant != 0 || fm->extend != 0)
+ && !(is_t1fontfile(fm) && is_included(fm))) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': SlantFont/ExtendFont can be used only with embedded Type1 fonts",
+ fm->tfm_name);
+ a += 4;
+ }
+
+ /* the value of SlantFont and ExtendFont must be reasonable */
+ if (abs(fm->slant) > 1000) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': too big value of SlantFont (%g)",
+ fm->tfm_name, fm->slant / 1000.0);
+ a += 8;
+ }
+ if (abs(fm->extend) > 2000) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': too big value of ExtendFont (%g)",
+ fm->tfm_name, fm->extend / 1000.0);
+ a += 16;
+ }
+
+ /* subfonts must be used with subsetted non-reencoded TrueType fonts */
+ if (fm->pid != -1 &&
+ !(is_truetype(fm) && is_subsetted(fm) && !is_reencoded(fm))) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': PidEid can be used only with subsetted non-reencoded TrueType fonts",
+ fm->tfm_name);
+ a += 32;
+ }
+
+ return a;
+}
+
+/**********************************************************************/
+/* returns true if s is one of the 14 std. font names; speed-trimmed. */
+
+boolean check_std_t1font(char *s)
+{
+ static const char *std_t1font_names[] = {
+ "Courier", /* 0:7 */
+ "Courier-Bold", /* 1:12 */
+ "Courier-Oblique", /* 2:15 */
+ "Courier-BoldOblique", /* 3:19 */
+ "Helvetica", /* 4:9 */
+ "Helvetica-Bold", /* 5:14 */
+ "Helvetica-Oblique", /* 6:17 */
+ "Helvetica-BoldOblique", /* 7:21 */
+ "Symbol", /* 8:6 */
+ "Times-Roman", /* 9:11 */
+ "Times-Bold", /* 10:10 */
+ "Times-Italic", /* 11:12 */
+ "Times-BoldItalic", /* 12:16 */
+ "ZapfDingbats" /* 13:12 */
+ };
+ static const int index[] =
+ { -1, -1, -1, -1, -1, -1, 8, 0, -1, 4, 10, 9, -1, -1, 5, 2, 12, 6, -1,
+ 3, -1, 7
+ };
+ const size_t n = strlen(s);
+ int k = -1;
+ if (n > 21)
+ return false;
+ if (n == 12) { /* three names have length 12 */
+ switch (*s) {
+ case 'C':
+ k = 1; /* Courier-Bold */
+ break;
+ case 'T':
+ k = 11; /* Times-Italic */
+ break;
+ case 'Z':
+ k = 13; /* ZapfDingbats */
+ break;
+ default:
+ return false;
+ }
+ } else
+ k = index[n];
+ if (k > -1 && !strcmp(std_t1font_names[k], s))
+ return true;
+ return false;
+};
+
+/**********************************************************************/
+
+static void fm_scan_line()
+{
+ int a, b, c, j, u = 0, v = 0;
+ float d;
+ fm_entry *fm;
+ char fm_line[FM_BUF_SIZE], buf[FM_BUF_SIZE];
+ char *p, *q, *r, *s;
+ switch (mitem->type) {
+ case MAPFILE:
+ p = fm_line;
+ do {
+ c = fm_getchar();
+ append_char_to_buf(c, p, fm_line, FM_BUF_SIZE);
+ }
+ while (c != 10 && !fm_eof());
+ *(--p) = '\0';
+ r = fm_line;
+ break;
+ case MAPLINE:
+ r = mitem->line; /* work on string from makecstring() */
+ break;
+ default:
+ assert(0);
+ }
+ if (*r == '\0' || is_cfg_comment(*r))
+ return;
+ fm = new_fm_entry();
+ read_field(r, q, buf);
+ set_field(tfm_name);
+ if (!isdigit(*r)) { /* 2nd field ps_name may not start with a digit */
+ read_field(r, q, buf);
+ set_field(ps_name);
+ }
+ if (isdigit(*r)) { /* font descriptor /Flags given? */
+ for (s = r; isdigit(*s); s++);
+ if (*s == ' ' || *s == '"' || *s == '<' || *s == '\0') { /* not e. g. 8r.enc */
+ fm->fd_flags = atoi(r);
+ while (isdigit(*r))
+ r++;
+ }
+ }
+ while (1) { /* loop through "specials", encoding, font file */
+ skip(r, ' ');
+ switch (*r) {
+ case '\0':
+ goto done;
+ case '"': /* opening quote */
+ r++;
+ u = v = 0;
+ do {
+ skip(r, ' ');
+ if (sscanf(r, "%f %n", &d, &j) > 0) {
+ s = r + j; /* jump behind number, eat also blanks, if any */
+ if (*(s - 1) == 'E' || *(s - 1) == 'e')
+ s--; /* e. g. 0.5ExtendFont: %f = 0.5E */
+ if (str_prefix(s, "SlantFont")) {
+ d *= 1000.0; /* correct rounding also for neg. numbers */
+ fm->slant = (integer) (d > 0 ? d + 0.5 : d - 0.5);
+ r = s + strlen("SlantFont");
+ } else if (str_prefix(s, "ExtendFont")) {
+ d *= 1000.0;
+ fm->extend = (integer) (d > 0 ? d + 0.5 : d - 0.5);
+ if (fm->extend == 1000)
+ fm->extend = 0;
+ r = s + strlen("ExtendFont");
+ } else { /* unknown name */
+ for (r = s; *r != ' ' && *r != '"' && *r != '\0'; r++); /* jump over name */
+ c = *r; /* remember char for temporary end of string */
+ *r = '\0';
+ pdftex_warn
+ ("invalid entry for `%s': unknown name `%s' ignored",
+ fm->tfm_name, s);
+ *r = c;
+ }
+ } else
+ for (; *r != ' ' && *r != '"' && *r != '\0'; r++);
+ }
+ while (*r == ' ');
+ if (*r == '"') /* closing quote */
+ r++;
+ else {
+ pdftex_warn
+ ("invalid entry for `%s': closing quote missing",
+ fm->tfm_name);
+ goto bad_line;
+ }
+ break;
+ case 'P': /* handle cases for subfonts like 'PidEid=3,1' */
+ if (sscanf(r, "PidEid=%i, %i %n", &a, &b, &c) >= 2) {
+ fm->pid = a;
+ fm->eid = b;
+ r += c;
+ break;
+ }
+ default: /* encoding or font file specification */
+ a = b = 0;
+ if (*r == '<') {
+ a = *r++;
+ if (*r == '<' || *r == '[')
+ b = *r++;
+ }
+ read_field(r, q, buf);
+ /* encoding, formats: '8r.enc' or '<8r.enc' or '<[8r.enc' */
+ if (strlen(buf) > 4 && strcasecmp(strend(buf) - 4, ".enc") == 0) {
+ fm->encname = add_encname(buf);
+ u = v = 0; /* u, v used if intervening blank: "<< foo" */
+ } else if (strlen(buf) > 0) { /* file name given */
+ /* font file, formats:
+ * subsetting: '<cmr10.pfa'
+ * no subsetting: '<<cmr10.pfa'
+ * no embedding: 'cmr10.pfa'
+ */
+ if (a == '<' || u == '<') {
+ set_included(fm);
+ if ((a == '<' && b == 0) || (a == 0 && v == 0))
+ set_subsetted(fm);
+ /* otherwise b == '<' (or '[') => no subsetting */
+ }
+ set_field(ff_name);
+ u = v = 0;
+ } else {
+ u = a;
+ v = b;
+ }
+ }
+ }
+ done:
+ if (fm->ps_name != NULL && check_std_t1font(fm->ps_name))
+ set_std_t1font(fm);
+ if (is_fontfile(fm)) {
+ if (strcasecmp(strend(fm_fontfile(fm)) - 4, ".ttf") == 0)
+ set_truetype(fm);
+ else if (strcasecmp(strend(fm_fontfile(fm)) - 4, ".otf") == 0)
+ set_opentype(fm);
+ else
+ set_type1(fm);
+ } else
+ set_type1(fm); /* assume a builtin font is Type1 */
+ if (check_fm_entry(fm, true) != 0)
+ goto bad_line;
+ /*
+ Until here the map line has been completely scanned without errors;
+ fm points to a valid, freshly filled-out fm_entry structure.
+ Now follows the actual work of registering/deleting.
+ */
+ if (handle_subfont_fm(fm, mitem->mode)) /* is this a subfont? */
+ return;
+ if (avl_do_entry(fm, mitem->mode) == 0) /* if success */
+ return;
+ bad_line:
+ delete_fm_entry(fm);
+}
+
+/**********************************************************************/
+
+void fm_read_info ()
+{
+ int callback_id;
+ int file_opened = 0;
+ char *ftemp = NULL;
+ if (tfm_tree == NULL)
+ create_avl_trees ();
+ if (mitem->line == NULL) /* nothing to do */
+ return;
+ mitem->lineno = 1;
+ switch (mitem->type) {
+ case MAPFILE:
+ set_cur_file_name (mitem->line);
+ if (fm_buffer!=NULL) {
+ xfree(fm_buffer);
+ fm_buffer=NULL;
+ }
+ fm_curbyte=0;
+ fm_size=0;
+ callback_id=callback_defined(find_map_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ free(nameoffile);
+ namelength = strlen(ftemp);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),ftemp);
+ free(ftemp);
+ }
+ }
+ }
+ callback_id=callback_defined(read_map_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1),
+ &file_opened, &fm_buffer,&fm_size)) {
+ if(file_opened) {
+ if (fm_size>0) {
+ cur_file_name = (char *) nameoffile + 1;
+ if (tracefilenames)
+ tex_printf ("{%s", cur_file_name);
+ while (!fm_eof ()) {
+ fm_scan_line ();
+ mitem->lineno++;
+ }
+ if (tracefilenames)
+ tex_printf ("}");
+ fm_file = NULL;
+ }
+ } else {
+ pdftex_warn ("cannot open font map file");
+ }
+ } else {
+ pdftex_warn ("cannot open font map file");
+ }
+ } else {
+ if (!fm_open ()) {
+ pdftex_warn ("cannot open font map file");
+ } else {
+ fm_read_file();
+ cur_file_name = (char *) nameoffile + 1;
+ tex_printf ("{%s", cur_file_name);
+ while (!fm_eof ()) {
+ fm_scan_line ();
+ mitem->lineno++;
+ }
+ fm_close ();
+ tex_printf ("}");
+ fm_file = NULL;
+ }
+ }
+ break;
+ case MAPLINE:
+ cur_file_name = NULL; /* makes pdftex_warn() shorter */
+ fm_scan_line ();
+ break;
+ default:
+ assert (0);
+ }
+ mitem->line = NULL; /* done with this line */
+ cur_file_name = NULL;
+ return;
+}
+
+/**********************************************************************/
+
+static fm_entry_ptr fmlookup(internalfontnumber f)
+{
+ char *tfm;
+ fm_entry *fm;
+ fm_entry tmp;
+ if (tfm_tree == NULL)
+ fm_read_info(); /* only to read default map file */
+ tfm = font_name(f);
+ assert(strcmp(tfm, nontfm));
+
+ /* Look up for full <tfmname>[+-]<expand> */
+ tmp.tfm_name = tfm;
+ fm = (fm_entry *) avl_find(tfm_tree, &tmp);
+ if (fm != NULL) {
+ fm->in_use = true;
+ return (fm_entry_ptr) fm;
+ }
+ return (fm_entry_ptr) dummy_fm_entry();
+}
+
+boolean hasfmentry(internalfontnumber f)
+{
+ if (font_map(f) == NULL)
+ set_font_map(f, (fm_entry_ptr) fmlookup(f));
+ assert(font_map(f) != NULL);
+ return font_map(f) != (fm_entry_ptr) dummy_fm_entry();
+}
+
+/* check whether a map entry is valid for font replacement */
+
+static boolean fm_valid_for_font_replacement(fm_entry * fm)
+{
+ ff_entry *ff;
+
+ assert(fm != NULL);
+ assert(is_fontfile(fm)); /* ps_tree should contain only entries with font file */
+ assert(is_type1(fm)); /* ps_tree should contain only Type1 entries */
+
+ ff = check_ff_exist(fm->ff_name, false);
+ assert(ff != NULL);
+ if (ff->ff_path == NULL) /* ...there is no font file available */
+ return false;
+ return true; /* all tests passed */
+}
+
+/**********************************************************************/
+/*
+ * lookup fontmap by ps_name;
+ * used for Type1 font replacement when embedding of PDF files
+ */
+
+fm_entry *lookup_fontmap(char *ps_name)
+{
+ fm_entry *fm, *fm2, tmp;
+ char *a, *b, *c, *d, *e, *s;
+ int i, sl, ex;
+ struct avl_traverser t, t2;
+ if (tfm_tree == NULL)
+ fm_read_info(); /* only to read default map file */
+ assert(ps_name != NULL);
+ s = ps_name;
+ if (strlen(ps_name) > 7) { /* check for subsetted name tag */
+ for (i = 0; i < 6; i++, s++)
+ if (*s < 'A' || *s > 'Z')
+ break;
+ if (i == 6 && *s == '+')
+ s++; /* if name tag found, skip behind it */
+ else
+ s = ps_name;
+ }
+
+ /*
+ * Scan -Slant_<slant> and -Extend_<extend> font name extensions;
+ * three valid formats:
+ * <fontname>-Slant_<slant>
+ * <fontname>-Slant_<slant>-Extend_<extend>
+ * <fontname>-Extend_<extend>
+ * Slant entry must come _before_ Extend entry
+ */
+
+ tmp.slant = 0;
+ tmp.extend = 0;
+ if ((a = strstr(s, "-Slant_")) != NULL) {
+ b = a + strlen("-Slant_");
+ sl = (int) strtol(b, &e, 10);
+ if ((e != b) && (e == strend(b))) {
+ tmp.slant = sl;
+ *a = '\0'; /* ps_name string ends before "-Slant_" */
+ } else {
+ if (e != b) { /* only if <slant> is valid number */
+ if ((c = strstr(e, "-Extend_")) != NULL) {
+ d = c + strlen("-Extend_");
+ ex = (int) strtol(d, &e, 10);
+ if ((e != d) && (e == strend(d))) {
+ tmp.slant = sl;
+ tmp.extend = ex;
+ *a = '\0'; /* ps_name string ends before "-Slant_" */
+ }
+ }
+ }
+ }
+ } else {
+ if ((a = strstr(s, "-Extend_")) != NULL) {
+ b = a + strlen("-Extend_");
+ ex = (int) strtol(b, &e, 10);
+ if ((e != b) && (e == strend(b))) {
+ tmp.extend = ex;
+ *a = '\0'; /* ps_name string ends before "-Extend_" */
+ }
+ }
+ }
+ tmp.ps_name = s;
+
+ fm = (fm_entry *) avl_t_find(&t, ps_tree, &tmp);
+ if (fm == NULL)
+ return NULL; /* no entry found */
+
+ /* at this point we know there is at least one fm_entry with given ps_name;
+ * we test all such entries and return the first one that is valid for font
+ * replacement */
+
+ t2 = t;
+ fm2 = (fm_entry *) avl_t_prev(&t2);
+
+ /* search forward */
+ do {
+ if (fm_valid_for_font_replacement(fm))
+ return fm;
+ fm = (fm_entry *) avl_t_next(&t);
+ } while (fm != NULL && comp_fm_entry_ps(fm, &tmp, NULL) == 0);
+
+ /* search backward */
+ while (fm2 != NULL && comp_fm_entry_ps(fm2, &tmp, NULL) == 0) {
+ if (fm_valid_for_font_replacement(fm2))
+ return fm2;
+ fm2 = (fm_entry *) avl_t_prev(&t2);
+ }
+
+ return NULL;
+}
+
+/**********************************************************************/
+/*
+ * Process map file given by its name or map line contents. Items not
+ * beginning with [+-=] flush default map file, if it has not yet been
+ * read. Leading blanks and blanks immediately following [+-=] are
+ * ignored.
+ */
+
+void process_map_item(char *s, int type)
+{
+ char *p;
+ int mode;
+ if (*s == ' ')
+ s++; /* ignore leading blank */
+ switch (*s) {
+ case '+': /* +mapfile.map, +mapline */
+ mode = FM_DUPIGNORE; /* insert entry, if it is not duplicate */
+ s++;
+ break;
+ case '=': /* =mapfile.map, =mapline */
+ mode = FM_REPLACE; /* try to replace earlier entry */
+ s++;
+ break;
+ case '-': /* -mapfile.map, -mapline */
+ mode = FM_DELETE; /* try to delete entry */
+ s++;
+ break;
+ default:
+ mode = FM_DUPIGNORE; /* like +, but also: */
+ mitem->line = NULL; /* flush default map file name */
+ }
+ if (*s == ' ')
+ s++; /* ignore blank after [+-=] */
+ p = s; /* map item starts here */
+ switch (type) {
+ case MAPFILE: /* remove blank at end */
+ while (*p != '\0' && *p != ' ')
+ p++;
+ *p = '\0';
+ break;
+ case MAPLINE: /* blank at end allowed */
+ break;
+ default:
+ assert(0);
+ }
+ if (mitem->line != NULL) /* read default map file first */
+ fm_read_info();
+ if (*s != '\0') { /* only if real item to process */
+ mitem->mode = mode;
+ mitem->type = type;
+ mitem->line = s;
+ fm_read_info();
+ }
+}
+
+void pdfmapfile(integer t)
+{
+ process_map_item(makecstring(tokens_to_string(t)), MAPFILE);
+ flush_str(last_tokens_string);
+}
+
+void pdfmapline(integer t)
+{
+ process_map_item(makecstring(tokens_to_string(t)), MAPLINE);
+ flush_str(last_tokens_string);
+}
+
+void pdf_init_map_file(string map_name)
+{
+ assert(mitem == NULL);
+ mitem = xtalloc(1, mapitem);
+ mitem->mode = FM_DUPIGNORE;
+ mitem->type = MAPFILE;
+ mitem->line = xstrdup(map_name);
+}
+
+
+/**********************************************************************/
+/*
+ * Early check whether a font file exists. Search tree ff_tree is used
+ * in 1st instance, as it may be faster than the kpse_find_file(), and
+ * kpse_find_file() is called only once per font file name + expansion
+ * parameter. This might help keeping speed, if many PDF pages with
+ * same fonts are to be embedded.
+ *
+ * The ff_tree contains only font files, which are actually needed,
+ * so this tree typically is much smaller than the tfm_tree or ps_tree.
+ */
+
+ff_entry *check_ff_exist(char *ff_name, boolean is_tt)
+{
+ ff_entry *ff;
+ ff_entry tmp;
+ void **aa;
+ int callback_id;
+ char *filepath=NULL;
+
+ assert(ff_name != NULL);
+ tmp.ff_name = ff_name;
+ ff = (ff_entry *) avl_find(ff_tree, &tmp);
+ if (ff == NULL) { /* not yet in database */
+ ff = new_ff_entry();
+ ff->ff_name = xstrdup(ff_name);
+ if (is_tt) {
+ callback_id=callback_defined(find_truetype_file_callback);
+ if (callback_id>0) {
+ run_callback(callback_id,"S->S",ff_name,&filepath);
+ if (filepath && strlen(filepath)==0)
+ filepath=NULL;
+ ff->ff_path = filepath;
+ } else {
+ ff->ff_path = kpse_find_file (ff_name, kpse_truetype_format, 0);
+ }
+ }
+ else {
+ callback_id=callback_defined(find_type1_file_callback);
+ if (callback_id>0) {
+ run_callback(callback_id,"S->S",ff_name,&filepath);
+ if (filepath && strlen(filepath)==0)
+ filepath=NULL;
+ ff->ff_path = filepath;
+ } else {
+ ff->ff_path = kpse_find_file (ff_name, kpse_type1_format, 0);
+ }
+ }
+ aa = avl_probe(ff_tree, ff);
+ assert(aa != NULL);
+ }
+ return ff;
+}
+
+/**********************************************************************/
+/* cleaning up... */
+
+static void destroy_fm_entry_tfm(void *pa, void *pb)
+{
+ fm_entry *fm;
+ fm = (fm_entry *) pa;
+ if (!has_pslink(fm))
+ delete_fm_entry(fm);
+ else
+ unset_tfmlink(fm);
+}
+
+static void destroy_fm_entry_ps(void *pa, void *pb)
+{
+ fm_entry *fm;
+ fm = (fm_entry *) pa;
+ if (!has_tfmlink(fm))
+ delete_fm_entry(fm);
+ else
+ unset_pslink(fm);
+}
+
+static void destroy_ff_entry(void *pa, void *pb)
+{
+ ff_entry *ff;
+ ff = (ff_entry *) pa;
+ delete_ff_entry(ff);
+}
+
+void fm_free(void)
+{
+ if (tfm_tree != NULL) {
+ avl_destroy(tfm_tree, destroy_fm_entry_tfm);
+ tfm_tree = NULL;
+ }
+ if (ps_tree != NULL) {
+ avl_destroy(ps_tree, destroy_fm_entry_ps);
+ ps_tree = NULL;
+ }
+ if (ff_tree != NULL) {
+ avl_destroy(ff_tree, destroy_ff_entry);
+ ff_tree = NULL;
+ }
+}
+
+/**********************************************************************/
+/* end of mapfile.c */
diff --git a/Build/source/texk/web2c/luatexdir/font/pkin.c b/Build/source/texk/web2c/luatexdir/font/pkin.c
new file mode 100644
index 00000000000..5067d6dbd66
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/pkin.c
@@ -0,0 +1,439 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: pkin.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+/*
+ * NAME
+ * pkin.c - implementation of readchar()
+ * DESCRIPTION
+ * This implementation of readchar() uses parts of the program dvips
+ * written by Tomas Rokicki--the inventor of the pkformat--(loadfont.c,
+ * download.c and unpack.c). Dvips in turn is derived from pktype.
+ * Pktype(TeX) is described in debt in ``The PKtype processor'',
+ * which is available as pktype.weave as part of the METAFONTware.
+ * What was needed to implement readchar() is rearranged in pkfile.c to
+ * get more modularity in the style of MODULA2.
+ * BUGFIXES
+ * May 1997: Eric Delaunay <delaunay@lix.polytechnique.fr> reports a
+ * problem with huge fonts (greater than 1008 DPI). The code for
+ * handling PK characters in `extended format' was wrongly derived
+ * from dvips. Made some minor improvements regarding error handling.
+ * REDESIGN
+ * Piet Tutelaers
+ * rcpt@urc.tue.nl
+ *
+ * Modified for use with pdftex by Han The Thanh <thanh@fi.muni.cz>.
+ */
+
+#include "ptexlib.h"
+
+/*
+ * Now we have some routines to get stuff from the pk file. pkbyte returns
+ * the next byte from the pk file.
+ */
+
+
+/*
+static FILE *pkfile ;
+*/
+
+extern FILE *t3_file;
+#define pkfile t3_file
+
+static shalfword pkbyte(void)
+{
+ register shalfword i;
+
+ if ((i = xgetc(pkfile)) == EOF)
+ pdftex_fail("unexpected eof in pk file");
+ return (i);
+}
+
+static integer pkduo(void)
+{
+ register integer i;
+
+ i = pkbyte();
+ if (i > 127)
+ i -= 256;
+ i = i * 256 + pkbyte();
+ return (i);
+}
+
+static integer pktrio(void)
+{
+ register integer i;
+
+ i = pkbyte();
+ if (i > 127)
+ i -= 256;
+ i = i * 256 + pkbyte();
+ i = i * 256 + pkbyte();
+ return (i);
+}
+
+static integer pkquad(void)
+{
+ register integer i;
+
+ i = pkbyte();
+ if (i > 127)
+ i -= 256;
+ i = i * 256 + pkbyte();
+ i = i * 256 + pkbyte();
+ i = i * 256 + pkbyte();
+ return (i);
+}
+
+/*
+ * The next part is devoted to unpacking the character data.
+ */
+
+/*
+ * We need procedures to get a nybble, bit, and packed word from the
+ * packed data structure.
+ */
+
+static halfword inputbyte, flagbyte;
+static halfword bitweight;
+static halfword dynf;
+static halfword repeatcount;
+
+static shalfword getnyb(void)
+{
+ halfword temp;
+ if (bitweight == 0) {
+ bitweight = 16;
+ inputbyte = pkbyte();
+ temp = inputbyte >> 4;
+ } else {
+ bitweight = 0;
+ temp = inputbyte & 15;
+ }
+ return (temp);
+}
+
+static boolean getbit(void)
+{
+ bitweight >>= 1;
+ if (bitweight == 0) {
+ inputbyte = pkbyte();
+ bitweight = 128;
+ }
+ return (inputbyte & bitweight);
+}
+
+static halfword(*realfunc) (void);
+long pk_remainder;
+static halfword handlehuge(halfword i, halfword k);
+
+static halfword pkpackednum(void)
+{
+ register halfword i, j;
+ i = getnyb();
+ if (i == 0) {
+ do {
+ j = getnyb();
+ i++;
+ } while (!(j != 0));
+ if (i > 3) {
+/*
+ * Damn, we got a huge count! We *fake* it by giving an artificially
+ * large repeat count.
+ */
+ return (handlehuge(i, j));
+ } else {
+ while (i > 0) {
+ j = j * 16 + getnyb();
+ i--;
+ }
+ return (j - 15 + (13 - dynf) * 16 + dynf);
+ }
+ } else if (i <= dynf)
+ return (i);
+ else if (i < 14)
+ return ((i - dynf - 1) * 16 + getnyb() + dynf + 1);
+ else {
+ if (i == 14)
+ repeatcount = pkpackednum();
+ else
+ repeatcount = 1;
+#ifdef DEBUG
+ printf("[%d]", (int) repeatcount);
+#endif
+ return ((*realfunc) ());
+ }
+}
+
+static halfword rest(void)
+{
+ halfword i;
+
+ if (pk_remainder < 0) {
+ pk_remainder = -pk_remainder;
+ return (0);
+ } else if (pk_remainder > 0) {
+ if (pk_remainder > 4000) {
+ pk_remainder = 4000 - pk_remainder;
+ return (4000);
+ } else {
+ i = pk_remainder;
+ pk_remainder = 0;
+ realfunc = pkpackednum;
+ return (i);
+ }
+ } else {
+ pdftex_fail("shouldn't happen");
+ return 0;
+ /*NOTREACHED*/}
+}
+
+static halfword handlehuge(halfword i, halfword k)
+{
+ register long j = k;
+
+ while (i) {
+ j = (j << 4L) + getnyb();
+ i--;
+ }
+ pk_remainder = j - 15 + (13 - dynf) * 16 + dynf;
+ realfunc = rest;
+ return (rest());
+}
+
+/*
+ * And now we have our unpacking routine.
+ */
+
+static halfword gpower[17] = { 0, 1, 3, 7, 15, 31, 63, 127,
+ 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535
+};
+
+static void unpack(chardesc * cd)
+{
+ register integer i, j;
+ register halfword word, wordweight;
+ halfword *raster;
+ shalfword rowsleft;
+ boolean turnon;
+ shalfword hbit;
+ halfword count;
+ shalfword wordwidth;
+
+ wordwidth = (cd->cwidth + 15) / 16;
+ i = 2 * cd->cheight * (long) wordwidth;
+ if (i <= 0)
+ i = 2;
+ if (i > cd->rastersize) {
+ xfree(cd->raster);
+ cd->rastersize = i;
+ cd->raster = xtalloc(cd->rastersize, halfword);
+ }
+ raster = cd->raster;
+ realfunc = pkpackednum;
+ dynf = flagbyte / 16;
+ turnon = flagbyte & 8;
+ if (dynf == 14) {
+ bitweight = 0;
+ for (i = 1; i <= cd->cheight; i++) {
+ word = 0;
+ wordweight = 32768;
+ for (j = 1; j <= cd->cwidth; j++) {
+ if (getbit())
+ word += wordweight;
+ wordweight >>= 1;
+ if (wordweight == 0) {
+ *raster++ = word;
+ word = 0;
+ wordweight = 32768;
+ }
+ }
+ if (wordweight != 32768)
+ *raster++ = word;
+ }
+ } else {
+ rowsleft = cd->cheight;
+ hbit = cd->cwidth;
+ repeatcount = 0;
+ wordweight = 16;
+ word = 0;
+ bitweight = 0;
+ while (rowsleft > 0) {
+ count = (*realfunc) ();
+#ifdef DEBUG
+ if (turnon)
+ printf("(%d) ", (int) count);
+ else
+ printf("%d ", (int) count);
+#endif
+ while (count != 0) {
+ if ((count < wordweight) && (count < hbit)) {
+ if (turnon)
+ word += gpower[wordweight] - gpower[wordweight - count];
+ hbit -= count;
+ wordweight -= count;
+ count = 0;
+ } else if ((count >= hbit) && (hbit <= wordweight)) {
+ if (turnon)
+ word += gpower[wordweight] - gpower[wordweight - hbit];
+ *raster++ = word;
+ for (i = 1; i <= repeatcount; i++) {
+ for (j = 1; j <= wordwidth; j++) {
+ *raster = *(raster - wordwidth);
+ raster++;
+ }
+ }
+ rowsleft -= repeatcount + 1;
+ repeatcount = 0;
+ word = 0;
+ wordweight = 16;
+ count -= hbit;
+ hbit = cd->cwidth;
+ } else {
+ if (turnon)
+ word += gpower[wordweight];
+ *raster++ = word;
+ word = 0;
+ count -= wordweight;
+ hbit -= wordweight;
+ wordweight = 16;
+ }
+ }
+ turnon = !turnon;
+ }
+ if ((rowsleft != 0) || ((integer) hbit != cd->cwidth))
+ pdftex_fail("error while unpacking; more bits than required");
+ }
+}
+
+/*
+ * readchar(): the main routine
+ * Reads the character definition of character `c' into `cd' if available,
+ * return FALSE (0) otherwise.
+ */
+
+/*
+ * readchar(): the main routine
+ * check pk preamble if necessary,
+ * read the next character definition into `cd',
+ * return EOF if no character definition is available
+ */
+
+int readchar(boolean check_preamble, chardesc * cd)
+{
+ register shalfword i;
+ register integer k;
+ register integer length = 0;
+
+/*
+ * Check the preamble of the pkfile
+ */
+ if (check_preamble) {
+ if (pkbyte() != 247)
+ pdftex_fail("bad pk file, expected pre");
+ if (pkbyte() != 89)
+ pdftex_fail("bad version of pk file");
+ for (i = pkbyte(); i > 0; i--) /* creator of pkfile */
+ (void) pkbyte();
+ (void) pkquad(); /* design size */
+ k = pkquad(); /* checksum */
+ k = pkquad(); /* hppp */
+ k = pkquad(); /* vppp */
+ }
+/*
+ * Now we skip to the desired character definition
+ */
+ while ((flagbyte = pkbyte()) != 245) {
+ if (flagbyte < 240) {
+ switch (flagbyte & 7) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ length = (flagbyte & 7) * 256 + pkbyte() - 3;
+ cd->charcode = pkbyte();
+ (void) pktrio(); /* TFMwidth */
+ cd->xescape = pkbyte(); /* pixel width */
+ cd->cwidth = pkbyte();
+ cd->cheight = pkbyte();
+ cd->xoff = pkbyte();
+ cd->yoff = pkbyte();
+ if (cd->xoff > 127)
+ cd->xoff -= 256;
+ if (cd->yoff > 127)
+ cd->yoff -= 256;
+ break;
+ case 4:
+ case 5:
+ case 6:
+ length = (flagbyte & 3) * 65536L + pkbyte() * 256L;
+ length = length + pkbyte() - 4L;
+ cd->charcode = pkbyte();
+ (void) pktrio(); /* TFMwidth */
+ cd->xescape = pkduo(); /* pixelwidth */
+ cd->cwidth = pkduo();
+ cd->cheight = pkduo();
+ cd->xoff = pkduo();
+ cd->yoff = pkduo();
+ break;
+ case 7:
+ length = pkquad() - 9L;
+ cd->charcode = pkquad();
+ (void) pkquad(); /* TFMwidth */
+ cd->xescape = pkquad(); /* pixelwidth */
+ k = pkquad();
+ cd->cwidth = pkquad();
+ cd->cheight = pkquad();
+ cd->xoff = pkquad();
+ cd->yoff = pkquad();
+ }
+ if (length <= 0)
+ pdftex_fail("packet length (%i) too small", (int) length);
+ unpack(cd);
+ return 1;
+ } else {
+ k = 0;
+ switch (flagbyte) {
+ case 243:
+ k = pkbyte();
+ if (k > 127)
+ k -= 256;
+ case 242:
+ k = k * 256 + pkbyte();
+ case 241:
+ k = k * 256 + pkbyte();
+ case 240:
+ k = k * 256 + pkbyte();
+ while (k-- > 0)
+ i = pkbyte();
+ break;
+ case 244:
+ k = pkquad();
+ break;
+ case 246:
+ break;
+ default:
+ pdftex_fail("unexpected command (%i)", (int) flagbyte);
+ }
+ }
+ }
+ return 0; /* character not found */
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/sfnt.c b/Build/source/texk/web2c/luatexdir/font/sfnt.c
new file mode 100644
index 00000000000..95453a531a0
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/sfnt.c
@@ -0,0 +1,647 @@
+/* $Header: /home/cvsroot/dvipdfmx/src/sfnt.c,v 1.12 2004/09/11 14:50:29 hirata Exp $
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+/* Based on dvipdfmx-0.13.2c */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H_ */
+
+#include <string.h>
+
+#ifndef pdfTeX
+#include "system.h"
+
+#include "error.h"
+#include "mem.h"
+#include "mfileio.h"
+#else
+extern void pdftex_fail (const char *fmt, ...); /* utils.c */
+#endif
+
+#include "sfnt.h"
+
+#ifdef XETEX
+UNSIGNED_BYTE
+ft_unsigned_byte(sfnt* f)
+{
+ unsigned char byte;
+ unsigned long length = 1;
+
+ if (FT_Load_Sfnt_Table(f->ft_face, 0, f->loc, &byte, &length) != 0)
+ TT_ERROR("sfnt: Freetype failure...");
+ f->loc += 1;
+
+ return byte;
+}
+
+SIGNED_BYTE
+ft_signed_byte(sfnt* f)
+{
+ int b = ft_unsigned_byte(f);
+ if (b >= 0x80)
+ b -= 0x100;
+ return (SIGNED_BYTE)b;
+}
+
+UNSIGNED_PAIR
+ft_unsigned_pair(sfnt* f)
+{
+ unsigned char buf[2];
+ unsigned long length = 2;
+
+ if (FT_Load_Sfnt_Table(f->ft_face, 0, f->loc, buf, &length) != 0)
+ TT_ERROR("sfnt: Freetype failure...");
+ f->loc += 2;
+
+ return (UNSIGNED_PAIR)((unsigned)buf[0] << 8) + buf[1];
+}
+
+SIGNED_PAIR
+ft_signed_pair(sfnt* f)
+{
+ int p = ft_unsigned_pair(f);
+ if (p >= 0x8000U)
+ p -= 0x10000U;
+
+ return (SIGNED_PAIR)p;
+}
+
+UNSIGNED_QUAD
+ft_unsigned_quad(sfnt* f)
+{
+ unsigned char buf[4];
+ unsigned long length = 4;
+
+ if (FT_Load_Sfnt_Table(f->ft_face, 0, f->loc, buf, &length) != 0)
+ TT_ERROR("sfnt: Freetype failure...");
+ f->loc += 4;
+
+ return ((unsigned long)buf[0] << 24) + ((unsigned long)buf[1] << 16)
+ + ((unsigned long)buf[2] << 8) + (unsigned long)buf[3];
+}
+
+unsigned long
+ft_read(unsigned char* buf, unsigned long len, sfnt* f)
+{
+ unsigned long length = len;
+ if (FT_Load_Sfnt_Table(f->ft_face, 0, f->loc, buf, &length) != 0)
+ TT_ERROR("sfnt: Freetype failure...");
+ f->loc += len;
+
+ return length;
+}
+#endif
+
+
+/*
+ * type:
+ * `true' (0x74727565): TrueType (Mac)
+ * `typ1' (0x74797031) (Mac): PostScript font housed in a sfnt wrapper
+ * 0x00010000: TrueType (Win)/OpenType
+ * `OTTO': PostScript CFF font with OpenType wrapper
+ * `ttcf': TrueType Collection
+*/
+#define SFNT_TRUETYPE 0x00010000UL
+#define SFNT_MAC_TRUE 0x74727565UL
+#define SFNT_OPENTYPE 0x00010000UL
+#define SFNT_POSTSCRIPT 0x4f54544fUL
+#define SFNT_TTC 0x74746366UL
+
+#ifdef XETEX
+sfnt *
+sfnt_open (FT_Face face, int accept_types)
+{
+ sfnt *sfont;
+ ULONG type;
+
+ if (!face || !FT_IS_SFNT(face))
+ return NULL;
+
+ sfont = NEW(1, sfnt);
+ sfont->ft_face = face;
+ sfont->loc = 0;
+ sfont->type = 0;
+
+ type = sfnt_get_ulong(sfont);
+
+ if (type == SFNT_TRUETYPE || type == SFNT_MAC_TRUE) {
+ sfont->type = SFNT_TYPE_TRUETYPE;
+ } else if (type == SFNT_OPENTYPE) {
+ sfont->type = SFNT_TYPE_OPENTYPE;
+ } else if (type == SFNT_POSTSCRIPT) {
+ sfont->type = SFNT_TYPE_POSTSCRIPT;
+ } else if (type == SFNT_TTC) {
+ sfont->type = SFNT_TYPE_TTC;
+ }
+
+ if ((sfont->type & accept_types) == 0) {
+ RELEASE(sfont);
+ return NULL;
+ }
+
+ sfont->loc = 0;
+
+ sfont->directory = NULL;
+
+ return sfont;
+}
+#else /* not XETEX */
+#ifdef pdfTeX
+sfnt *
+sfnt_open (unsigned char *buffer, integer buflen)
+{
+ sfnt *sfont;
+ ULONG type;
+
+ sfont = xmalloc(sizeof(sfnt));
+ sfont->loc = 0;
+ sfont->buffer = buffer;
+ sfont->buflen = buflen;
+
+ type = sfnt_get_ulong(sfont);
+
+ if (type == SFNT_TRUETYPE || type == SFNT_MAC_TRUE) {
+ sfont->type = SFNT_TYPE_TRUETYPE;
+ } else if (type == SFNT_OPENTYPE) {
+ sfont->type = SFNT_TYPE_OPENTYPE;
+ } else if (type == SFNT_POSTSCRIPT) {
+ sfont->type = SFNT_TYPE_POSTSCRIPT;
+ } else if (type == SFNT_TTC) {
+ sfont->type = SFNT_TYPE_TTC;
+ }
+
+ sfont->loc=0;
+ sfont->directory = NULL;
+ return sfont;
+}
+#else
+sfnt *
+sfnt_open (FILE *fp)
+{
+ sfnt *sfont;
+ ULONG type;
+
+ ASSERT(fp);
+
+ rewind(fp);
+
+ sfont = NEW(1, sfnt);
+
+ sfont->stream = fp;
+
+ type = sfnt_get_ulong(sfont);
+
+ if (type == SFNT_TRUETYPE || type == SFNT_MAC_TRUE) {
+ sfont->type = SFNT_TYPE_TRUETYPE;
+ } else if (type == SFNT_OPENTYPE) {
+ sfont->type = SFNT_TYPE_OPENTYPE;
+ } else if (type == SFNT_POSTSCRIPT) {
+ sfont->type = SFNT_TYPE_POSTSCRIPT;
+ } else if (type == SFNT_TTC) {
+ sfont->type = SFNT_TYPE_TTC;
+ }
+
+ rewind(sfont->stream);
+
+ sfont->directory = NULL;
+
+ return sfont;
+}
+#endif
+#endif
+
+static void
+release_directory (struct sfnt_table_directory *td)
+{
+ long i;
+
+ if (td) {
+ if (td->tables) {
+ for (i = 0; i < td->num_tables; i++) {
+ if (td->tables[i].data)
+ RELEASE(td->tables[i].data);
+ }
+ RELEASE(td->tables);
+ }
+ if (td->flags)
+ RELEASE(td->flags);
+ RELEASE(td);
+ }
+
+ return;
+}
+
+void
+sfnt_close (sfnt *sfont)
+{
+
+ if (sfont) {
+ if (sfont->directory)
+ release_directory(sfont->directory);
+ RELEASE(sfont);
+ }
+
+ return;
+}
+
+int
+put_big_endian (void *s, LONG q, int n)
+{
+ int i;
+ char *p;
+
+ p = (char *) s;
+ for (i = n - 1; i >= 0; i--) {
+ p[i] = (char) (q & 0xff);
+ q >>= 8;
+ }
+
+ return n;
+}
+
+/* Convert four-byte number to big endianess
+ * in a machine independent way.
+ */
+static void
+convert_tag (char *tag, unsigned long u_tag)
+{
+ int i;
+
+ for (i = 3; i >= 0; i--) {
+ tag[i] = (char) (u_tag % 256);
+ u_tag /= 256;
+ }
+
+ return;
+}
+
+/*
+ * Computes the max power of 2 <= n
+ */
+static unsigned
+max2floor (unsigned n)
+{
+ int val = 1;
+
+ while (n > 1) {
+ n /= 2;
+ val *= 2;
+ }
+
+ return val;
+}
+
+/*
+ * Computes the log2 of the max power of 2 <= n
+ */
+static unsigned
+log2floor (unsigned n)
+{
+ unsigned val = 0;
+
+ while (n > 1) {
+ n /= 2;
+ val++;
+ }
+
+ return val;
+}
+
+static ULONG
+sfnt_calc_checksum(void *data, ULONG length)
+{
+ ULONG chksum = 0;
+ BYTE *p, *endptr;
+ int count = 0;
+
+ p = (BYTE *) data;
+ endptr = p + length;
+ while (p < endptr) {
+ chksum += (p[0] << (8 * ( 3 - count)));
+ count = ((count + 1) & 3);
+ p++;
+ }
+
+ return chksum;
+}
+
+static int
+find_table_index (struct sfnt_table_directory *td, const char *tag)
+{
+ int idx;
+
+ if (!td)
+ return -1;
+
+ for (idx = 0; idx < td->num_tables; idx++) {
+ if (!memcmp(td->tables[idx].tag, tag, 4))
+ return idx;
+ }
+
+ return -1;
+}
+
+void
+sfnt_set_table (sfnt *sfont, const char *tag, void *data, ULONG length)
+{
+ struct sfnt_table_directory *td;
+ int idx;
+
+ ASSERT(sfont);
+
+ td = sfont->directory;
+ idx = find_table_index(td, tag);
+
+ if (idx < 0) {
+ idx = td->num_tables;
+ td->num_tables++;
+ td->tables = RENEW(td->tables, td->num_tables, struct sfnt_table);
+ memcpy(td->tables[idx].tag, tag, 4);
+ }
+
+ td->tables[idx].check_sum = sfnt_calc_checksum(data, length);
+ td->tables[idx].offset = 0L;
+ td->tables[idx].length = length;
+ td->tables[idx].data = data;
+
+ return;
+}
+
+ULONG
+sfnt_find_table_len (sfnt *sfont, const char *tag)
+{
+ ULONG length;
+ struct sfnt_table_directory *td;
+ int idx;
+
+ ASSERT(sfont && tag);
+
+ td = sfont->directory;
+ idx = find_table_index(td, tag);
+ if (idx < 0)
+ length = 0;
+ else {
+ length = td->tables[idx].length;
+ }
+
+ return length;
+}
+
+ULONG
+sfnt_find_table_pos (sfnt *sfont, const char *tag)
+{
+ ULONG offset;
+ struct sfnt_table_directory *td;
+ int idx;
+
+ ASSERT(sfont && tag);
+
+ td = sfont->directory;
+ idx = find_table_index(td, tag);
+ if (idx < 0)
+ offset = 0;
+ else {
+ offset = td->tables[idx].offset;
+ }
+
+ return offset;
+}
+
+ULONG
+sfnt_locate_table (sfnt *sfont, const char *tag)
+{
+ ULONG offset;
+
+ ASSERT(sfont && tag);
+
+ offset = sfnt_find_table_pos(sfont, tag);
+ if (offset == 0)
+ TT_ERROR("sfnt: table not found...");
+
+ sfnt_seek_set(sfont, offset);
+
+ return offset;
+}
+
+int
+sfnt_read_table_directory (sfnt *sfont, ULONG offset)
+{
+ struct sfnt_table_directory *td;
+ unsigned long i, u_tag;
+
+ ASSERT(sfont);
+
+ if (sfont->directory)
+ release_directory(sfont->directory);
+ sfont->directory = td = NEW (1, struct sfnt_table_directory);
+
+#ifdef XETEX
+ ASSERT(sfont->ft_face);
+#elif defined(pdfTeX)
+ ASSERT(sfont->buffer);
+#else
+ ASSERT(sfont->stream);
+#endif
+
+ sfnt_seek_set(sfont, offset);
+
+ td->version = sfnt_get_ulong(sfont);
+ td->num_tables = sfnt_get_ushort(sfont);
+ td->search_range = sfnt_get_ushort(sfont);
+ td->entry_selector = sfnt_get_ushort(sfont);
+ td->range_shift = sfnt_get_ushort(sfont);
+
+ td->flags = NEW(td->num_tables, char);
+ td->tables = NEW(td->num_tables, struct sfnt_table);
+
+ for (i = 0; i < td->num_tables; i++) {
+ u_tag = sfnt_get_ulong(sfont);
+
+ convert_tag(td->tables[i].tag, u_tag);
+ td->tables[i].check_sum = sfnt_get_ulong(sfont);
+ td->tables[i].offset = sfnt_get_ulong(sfont);
+ td->tables[i].length = sfnt_get_ulong(sfont);
+ td->tables[i].data = NULL;
+
+ td->flags[i] = 0;
+ }
+
+ td->num_kept_tables = 0;
+
+ return 0;
+}
+
+int
+sfnt_require_table (sfnt *sfont, const char *tag, int must_exist)
+{
+ struct sfnt_table_directory *td;
+ int idx;
+
+ ASSERT(sfont && sfont->directory);
+
+ td = sfont->directory;
+ idx = find_table_index(td, tag);
+ if (idx < 0) {
+ if (must_exist)
+ return -1;
+ } else {
+ td->flags[idx] |= SFNT_TABLE_REQUIRED;
+ td->num_kept_tables++;
+ }
+
+ return 0;
+}
+
+#ifndef pdfTeX
+#include "pdfobj.h"
+#endif
+
+/*
+ * o All tables begin on four byte boundries, and pad any remaining space
+ * between tables with zeros
+ *
+ * o Entries in the Table Directory must be sorted in ascending order by tag
+ *
+ * o The head table contains checksum of the whole font file.
+ * To compute: first set it to 0, sum the entire font as ULONG,
+ * then store 0xB1B0AFBA - sum.
+ */
+
+#ifdef pdfTeX
+extern pdf_obj *pdf_new_stream(void);
+extern void pdf_add_stream(pdf_obj *, unsigned char *, long);
+extern void pdf_release_obj(pdf_obj *);
+#undef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define STREAM_COMPRESS
+#endif
+
+static unsigned char wbuf[1024], padbytes[4] = {0, 0, 0, 0};
+
+pdf_obj *
+sfnt_create_FontFile_stream (sfnt *sfont)
+{
+ pdf_obj *stream;
+#ifndef pdfTeX
+ pdf_obj *stream_dict;
+#endif
+ struct sfnt_table_directory *td;
+ long offset, nb_read, length;
+ int i, sr;
+ char *p;
+
+ ASSERT(sfont && sfont->directory);
+
+ stream = pdf_new_stream(STREAM_COMPRESS);
+
+ td = sfont->directory;
+
+ /* Header */
+ p = (char *) wbuf;
+ p += sfnt_put_ulong (p, td->version);
+ p += sfnt_put_ushort(p, td->num_kept_tables);
+ sr = max2floor(td->num_kept_tables) * 16;
+ p += sfnt_put_ushort(p, sr);
+ p += sfnt_put_ushort(p, log2floor(td->num_kept_tables));
+ p += sfnt_put_ushort(p, td->num_kept_tables * 16 - sr);
+
+ pdf_add_stream(stream, wbuf, 12);
+
+ /*
+ * Compute start of actual tables (after headers).
+ */
+ offset = 12 + 16 * td->num_kept_tables;
+ for (i = 0; i < td->num_tables; i++) {
+ /* This table must exist in FontFile */
+ if (td->flags[i] & SFNT_TABLE_REQUIRED) {
+ if ((offset % 4) != 0) {
+ offset += 4 - (offset % 4);
+ }
+
+ p = (char *) wbuf;
+ memcpy(p, td->tables[i].tag, 4);
+ p += 4;
+ p += sfnt_put_ulong(p, td->tables[i].check_sum);
+ p += sfnt_put_ulong(p, offset);
+ p += sfnt_put_ulong(p, td->tables[i].length);
+ pdf_add_stream(stream, wbuf, 16);
+
+ offset += td->tables[i].length;
+ }
+ }
+
+ offset = 12 + 16 * td->num_kept_tables;
+ for (i = 0; i < td->num_tables; i++) {
+ if (td->flags[i] & SFNT_TABLE_REQUIRED) {
+ if ((offset % 4) != 0) {
+ length = 4 - (offset % 4);
+ pdf_add_stream(stream, padbytes, length);
+ offset += length;
+ }
+ if (!td->tables[i].data) {
+#ifdef XETEX
+ if (!sfont->ft_face)
+#elif defined(pdfTeX)
+ if (!sfont->buffer)
+#else
+ if (!sfont->stream)
+#endif
+ {
+ pdf_release_obj(stream);
+ TT_ERROR("Font file not opened or already closed...");
+ return NULL;
+ }
+
+ length = td->tables[i].length;
+ sfnt_seek_set(sfont, td->tables[i].offset);
+ while (length > 0) {
+ nb_read = sfnt_read(wbuf, MIN(length, 1024), sfont);
+ if (nb_read < 0) {
+ pdf_release_obj(stream);
+ TT_ERROR("Reading file failed...");
+ return NULL;
+ } else if (nb_read > 0) {
+ pdf_add_stream(stream, wbuf, nb_read);
+ }
+ length -= nb_read;
+ }
+ } else {
+ pdf_add_stream(stream,
+ (unsigned char *)td->tables[i].data,
+ td->tables[i].length);
+ RELEASE(td->tables[i].data);
+ td->tables[i].data = NULL;
+ }
+ /* Set offset for next table */
+ offset += td->tables[i].length;
+ }
+ }
+
+#ifndef pdfTeX
+ stream_dict = pdf_stream_dict(stream);
+ pdf_add_dict(stream_dict,
+ pdf_new_name("Length1"),
+ pdf_new_number(offset));
+#endif
+ return stream;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/sfnt.h b/Build/source/texk/web2c/luatexdir/font/sfnt.h
new file mode 100644
index 00000000000..8db54dd9c39
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/sfnt.h
@@ -0,0 +1,197 @@
+/* $Header: /home/cvsroot/dvipdfmx/src/sfnt.h,v 1.9 2004/09/11 14:50:29 hirata Exp $
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+#ifndef _SFNT_H_
+#define _SFNT_H_
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H_ */
+
+#ifndef pdfTeX
+#include "mfileio.h"
+#include "numbers.h"
+#include "pdfobj.h"
+#endif
+
+#ifdef XETEX
+#include "ft2build.h"
+#include FT_FREETYPE_H
+#include FT_TRUETYPE_TABLES_H
+#endif
+
+/* Data Types as described in Apple's TTRefMan */
+typedef unsigned char BYTE;
+typedef signed char ICHAR;
+typedef unsigned short USHORT;
+typedef signed short SHORT;
+typedef unsigned long ULONG;
+typedef signed long LONG;
+typedef unsigned long Fixed; /* 16.16-bit signed fixed-point number */
+typedef short FWord;
+typedef unsigned short uFWord;
+typedef short F2Dot14; /* 16-bit signed fixed number with the low
+ 14 bits representing fraction. */
+
+struct sfnt_table
+{
+ /* table header */
+ char tag[4];
+ ULONG check_sum;
+ ULONG offset;
+ ULONG length;
+ char *data; /* table data */
+};
+
+#define SFNT_TABLE_REQUIRED (1 << 0)
+
+struct sfnt_table_directory
+{
+ ULONG version; /* Fixed for Win */
+ USHORT num_tables;
+ USHORT search_range;
+ USHORT entry_selector;
+ USHORT range_shift;
+ USHORT num_kept_tables; /* number of kept tables */
+ char *flags; /* keep or omit */
+ struct sfnt_table *tables;
+};
+
+/* sfnt resource */
+#define SFNT_TYPE_TRUETYPE (1 << 0)
+#define SFNT_TYPE_OPENTYPE (1 << 1)
+#define SFNT_TYPE_POSTSCRIPT (1 << 2)
+#define SFNT_TYPE_TTC (1 << 4)
+
+typedef struct
+{
+ int type;
+ struct sfnt_table_directory *directory;
+#ifdef XETEX
+ FT_Face ft_face;
+ long loc;
+#elif defined(pdfTeX)
+ BYTE *buffer;
+ long buflen;
+ long loc;
+#else
+ FILE *stream;
+#endif
+} sfnt;
+
+/* Convert sfnt "fixed" type to double */
+#define fixed(a) ((double)((a)%0x10000L)/(double)(0x10000L) + \
+ (a)/0x10000L - (((a)/0x10000L > 0x7fffL) ? 0x10000L : 0))
+
+#ifdef XETEX
+UNSIGNED_BYTE ft_unsigned_byte(sfnt* f);
+SIGNED_BYTE ft_signed_byte(sfnt* f);
+UNSIGNED_PAIR ft_unsigned_pair(sfnt* f);
+SIGNED_PAIR ft_signed_pair(sfnt* f);
+UNSIGNED_QUAD ft_unsigned_quad(sfnt* f);
+unsigned long ft_read(unsigned char* buf, unsigned long len, sfnt* f);
+
+#define sfnt_get_byte(s) ((BYTE) ft_unsigned_byte(s))
+#define sfnt_get_char(s) ((ICHAR) ft_signed_byte (s))
+#define sfnt_get_ushort(s) ((USHORT) ft_unsigned_pair(s))
+#define sfnt_get_short(s) ((SHORT) ft_signed_pair (s))
+#define sfnt_get_ulong(s) ((ULONG) ft_unsigned_quad(s))
+#define sfnt_get_long(s) ((LONG) ft_signed_quad (s))
+
+#define sfnt_seek_set(s,o) (s)->loc = (o)
+#define sfnt_read(b,l,s) ft_read((b), (l), (s))
+#elif defined(pdfTeX)
+BYTE get_unsigned_byte(sfnt* f);
+ICHAR get_signed_byte(sfnt* f);
+USHORT get_unsigned_pair(sfnt* f);
+SHORT get_signed_pair(sfnt* f);
+ULONG get_unsigned_quad(sfnt* f);
+int do_sfnt_read (unsigned char *dest, int len, sfnt *f);
+
+#define sfnt_get_byte(s) ((BYTE) get_unsigned_byte(s))
+#define sfnt_get_char(s) ((ICHAR) get_signed_byte (s))
+#define sfnt_get_ushort(s) ((USHORT) get_unsigned_pair(s))
+#define sfnt_get_short(s) ((SHORT) get_signed_pair (s))
+#define sfnt_get_ulong(s) ((ULONG) get_unsigned_quad(s))
+#define sfnt_get_long(s) ((LONG) get_signed_quad (s))
+
+#define sfnt_seek_set(s,o) (s)->loc = (o)
+#define sfnt_read(b,l,s) do_sfnt_read((b), (l), (s))
+#else
+/* get_***_*** from numbers.h */
+#define sfnt_get_byte(s) ((BYTE) get_unsigned_byte((s)->stream))
+#define sfnt_get_char(s) ((ICHAR) get_signed_byte ((s)->stream))
+#define sfnt_get_ushort(s) ((USHORT) get_unsigned_pair((s)->stream))
+#define sfnt_get_short(s) ((SHORT) get_signed_pair ((s)->stream))
+#define sfnt_get_ulong(s) ((ULONG) get_unsigned_quad((s)->stream))
+#define sfnt_get_long(s) ((LONG) get_signed_quad ((s)->stream))
+
+#define sfnt_seek_set(s,o) seek_absolute((s)->stream, (o))
+#define sfnt_read(b,l,s) fread((b), 1, (l), (s)->stream)
+#endif
+
+extern int put_big_endian (void *s, LONG q, int n);
+
+#define sfnt_put_ushort(s,v) put_big_endian((s), v, 2);
+#define sfnt_put_short(s,v) put_big_endian((s), v, 2);
+#define sfnt_put_ulong(s,v) put_big_endian((s), v, 4);
+#define sfnt_put_long(s,v) put_big_endian((s), v, 4);
+
+#ifdef XETEX
+extern sfnt *sfnt_open (FT_Face face, int accept_types);
+#elif defined(pdfTeX)
+extern sfnt *sfnt_open (unsigned char *buffer, integer buflen);
+#else
+extern sfnt *sfnt_open (FILE *fp);
+#endif
+extern void sfnt_close (sfnt *sfont);
+
+/* table directory */
+extern int sfnt_read_table_directory (sfnt *sfont, ULONG offset);
+extern ULONG sfnt_find_table_len (sfnt *sfont, const char *tag);
+extern ULONG sfnt_find_table_pos (sfnt *sfont, const char *tag);
+extern ULONG sfnt_locate_table (sfnt *sfont, const char *tag);
+
+extern void sfnt_set_table (sfnt *sfont,
+ const char *tag, void *data, ULONG length);
+extern int sfnt_require_table (sfnt *sfont, const char *tag, int must_exist);
+
+#ifdef pdfTeX
+typedef struct
+{
+ ULONG length;
+ BYTE *data;
+} pdf_obj;
+
+#define ASSERT(a) assert(a)
+#define RELEASE(a) free(a)
+#define NEW(a,b) xmalloc((a)*sizeof(b))
+#define RENEW(a,b,c) xrealloc(a, ((b)*sizeof(c)))
+#define TT_ERROR pdftex_fail
+#define WARN printf
+
+
+#endif
+
+extern pdf_obj *sfnt_create_FontFile_stream (sfnt *sfont);
+
+#endif /* _SFNT_H_ */
diff --git a/Build/source/texk/web2c/luatexdir/font/subfont.c b/Build/source/texk/web2c/luatexdir/font/subfont.c
new file mode 100644
index 00000000000..836985c10fd
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/subfont.c
@@ -0,0 +1,264 @@
+/*
+Copyright (c) 2005-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "ptexlib.h"
+#include <string.h>
+
+static struct avl_table *sfd_tree = NULL;
+
+static unsigned char *sfd_buffer = NULL;
+static integer sfd_size = 0;
+static integer sfd_curbyte = 0;
+
+#define SFD_BUF_SIZE SMALL_BUF_SIZE
+
+#define sfd_close() xfclose(sfd_file, cur_file_name)
+#define sfd_open() open_input(&sfd_file, kpse_sfd_format, FOPEN_RBIN_MODE)
+
+#define sfd_read_file() readbinfile(sfd_file,&sfd_buffer,&sfd_size)
+#define sfd_getchar() sfd_buffer[sfd_curbyte++]
+#define sfd_eof() (sfd_curbyte>sfd_size)
+
+
+static FILE *sfd_file;
+static char sfd_line[SFD_BUF_SIZE];
+
+static subfont_entry *new_subfont_entry (void)
+{
+ int i;
+ subfont_entry *subfont;
+ subfont = xtalloc (1, subfont_entry);
+ subfont->infix = NULL;
+ for (i = 0; i < 256; ++i)
+ subfont->charcodes[i] = -1; /* unassigned */
+ subfont->next = NULL;
+ return subfont;
+}
+
+static sfd_entry *new_sfd_entry (void)
+{
+ sfd_entry *sfd;
+ sfd = xtalloc (1, sfd_entry);
+ sfd->name = NULL;
+ sfd->subfont = NULL;
+ return sfd;
+}
+
+static void destroy_sfd_entry (void *pa, void *pb)
+{
+ subfont_entry *p, *q;
+ sfd_entry *sfd;
+ sfd = (sfd_entry *) pa;
+ p = sfd->subfont;
+ while (p != NULL) {
+ q = p->next;
+ xfree (p->infix);
+ xfree (p);
+ p = q;
+ }
+ xfree (sfd->name);
+}
+
+static int comp_sfd_entry (const void *pa, const void *pb, void *p)
+{
+ return strcmp (((const sfd_entry *) pa)->name,
+ ((const sfd_entry *) pb)->name);
+}
+
+void sfd_free (void)
+{
+ if (sfd_tree != NULL)
+ avl_destroy (sfd_tree, destroy_sfd_entry);
+}
+
+static void sfd_getline (boolean expect_eof)
+{
+ char *p;
+ int c;
+ restart:
+ if (sfd_eof ()) {
+ if (expect_eof)
+ return;
+ else
+ pdftex_fail ("unexpected end of file");
+ }
+ p = sfd_line;
+ do {
+ c = sfd_getchar ();
+ append_char_to_buf (c, p, sfd_line, SFD_BUF_SIZE);
+ } while (c != 10 && !sfd_eof());
+ append_eol (p, sfd_line, SFD_BUF_SIZE);
+ if (p - sfd_line < 2 || *sfd_line == '#')
+ goto restart;
+}
+
+static sfd_entry *read_sfd (char *sfd_name)
+{
+ void **aa;
+ sfd_entry *sfd, tmp_sfd;
+ subfont_entry *sf;
+ char *ftemp = NULL;
+ char buf[SMALL_BUF_SIZE], *p;
+ long int i, j, k;
+ int n;
+ int callback_id=0;
+ int file_opened=0;
+ /* check whether this sfd has been read */
+ tmp_sfd.name = sfd_name;
+ if (sfd_tree == NULL) {
+ sfd_tree = avl_create (comp_sfd_entry, NULL, &avl_xallocator);
+ assert (sfd_tree != NULL);
+ }
+ sfd = (sfd_entry *) avl_find (sfd_tree, &tmp_sfd);
+ if (sfd != NULL)
+ return sfd;
+ set_cur_file_name (sfd_name);
+ if (sfd_buffer!=NULL) {
+ xfree(sfd_buffer);
+ sfd_buffer=NULL;
+ }
+ sfd_curbyte=0;
+ sfd_size=0;
+
+ callback_id=callback_defined(find_sfd_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",cur_file_name,&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ if (cur_file_name)
+ free(cur_file_name);
+ cur_file_name = xstrdup(ftemp);
+ free(ftemp);
+ }
+ }
+ }
+ callback_id=callback_defined(read_sfd_file_callback);
+ if (callback_id>0) {
+ if(! (run_callback(callback_id,"S->bSd",cur_file_name,
+ &file_opened, &sfd_buffer,&sfd_size) &&
+ file_opened &&
+ sfd_size>0 ) ) {
+ pdftex_warn ("cannot open SFD file for reading");
+ cur_file_name = NULL;
+ return NULL;
+ }
+ sfd_read_file();
+ sfd_close();
+ }
+ tex_printf ("{");
+ tex_printf (cur_file_name);
+ sfd = new_sfd_entry ();
+ sfd->name = xstrdup (sfd_name);
+ while (!sfd_eof ()) {
+ sfd_getline (true);
+ if (*sfd_line == 10) /* empty line indicating eof */
+ break;
+ sf = new_subfont_entry ();
+ sf->next = sfd->subfont;
+ sfd->subfont = sf;
+ sscanf (sfd_line, "%s %n", buf, &n);
+ sf->infix = xstrdup (buf);
+ p = sfd_line + n; /* skip to the next word */
+ k = 0;
+ read_ranges:
+ for (;;) {
+ if (*p == '\\') { /* continue on next line */
+ sfd_getline (false);
+ p = sfd_line;
+ goto read_ranges;
+ } else if (*p == 0) /* end of subfont */
+ break;
+ if (sscanf (p, " %li %n", &i, &n) == 0)
+ pdftex_fail ("invalid token:\n%s", p);
+ p += n;
+ if (*p == ':') { /* offset */
+ k = i;
+ p++;
+ } else if (*p == '_') { /* range */
+ if (sscanf (p + 1, " %li %n", &j, &n) == 0)
+ pdftex_fail ("invalid token:\n%s", p);
+ if (i > j || k + (j - i) > 255)
+ pdftex_fail ("invalid range:\n%s", p);
+ while (i <= j)
+ sf->charcodes[k++] = i++;
+ p += n + 1;
+ } else /* codepoint */
+ sf->charcodes[k++] = i;
+ }
+ }
+ tex_printf ("}");
+ aa = avl_probe (sfd_tree, sfd);
+ assert (aa != NULL);
+ return sfd;
+}
+
+boolean handle_subfont_fm (fm_entry * fm, int mode)
+{
+ size_t l;
+ char *p, *q, *r;
+ sfd_entry *sfd;
+ subfont_entry *sf;
+ fm_entry *fm2;
+ char buf[SMALL_BUF_SIZE];
+ assert (fm->tfm_name != NULL);
+ p = fm->tfm_name;
+ q = strchr (p, '@'); /* search for the first '@' */
+ if (q == NULL)
+ return false;
+ r = strchr (q + 1, '@'); /* search for the second '@' */
+ if (r == NULL)
+ return false;
+ if (q <= p || r <= q + 1 /* prefix or sfd name is empty */
+ || r - p != strlen (p) - 1) /* or the second '@' is not the last char yet */
+ return false;
+ l = r - (q + 1); /* length of sfd name */
+ strncpy (buf, q + 1, l);
+ buf[l] = 0;
+ check_buf(strlen(buf) + 4, SMALL_BUF_SIZE);
+ strcat (buf, ".sfd");
+ sfd = read_sfd (buf);
+ if (sfd == NULL)
+ return false;
+ /* at this point we know fm is a subfont */
+ set_subfont (fm);
+ xfree (fm->ps_name);
+ fm->ps_name = NULL;
+ /* set default values for PidEid */
+ if (fm->pid == -1) {
+ fm->pid = 3;
+ fm->eid = 1;
+ }
+ l = q - p; /* length of base tfm name (prefix) */
+ for (sf = sfd->subfont; sf != NULL; sf = sf->next) {
+ strncpy (buf, p, l);
+ buf[l] = 0;
+ strcat (buf, sf->infix);
+ fm2 = new_fm_entry ();
+ fm2->tfm_name = xstrdup (buf);
+ fm2->ff_name = xstrdup (fm->ff_name);
+ fm2->type = fm->type;
+ fm2->pid = fm->pid;
+ fm2->eid = fm->eid;
+ fm2->subfont = sf;
+ if (avl_do_entry (fm2, mode) != 0) /* try to insert the entry */
+ delete_fm_entry (fm2); /* delete it if failed */
+ }
+ delete_fm_entry (fm);
+ return true;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/subfont.txt b/Build/source/texk/web2c/luatexdir/font/subfont.txt
new file mode 100644
index 00000000000..9fe053cbb9c
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/subfont.txt
@@ -0,0 +1,74 @@
+map entry:
+
+cyberb@Unicode@ <cyberbit.ttf PidEid=3,1
+
+means
+
+cyberb<INFIX> => look at Unicode.sfd => find the mapping => charcode
+ => PidEid=3,1 => glyphs
+
+eg cyberb01 => subfont 01 in Unicode.sfd => charcodes
+
+Infix can be anything, thus the question: given a tfm name, how to find out
+whether this is a subfont?
+
+It is safe to limit the infix to be composed from hexadecimal digits only?
+
+If so, one possibility is:
+
+(1)
+while last-char-of-tfmname is a hexdigit do
+ remove the last char from tfmname
+ do a lookup for the tfmname
+ if found an entry with subfont flag then
+ break
+enddo
+
+(2)
+Or, when a map entry with subfont flag is scanned, let pdftex create all
+the relevant entries. Which may be a safer and faster solution (but wastes more
+memory)
+
+
+Let's do (2), as infix can be any word.
+
+
+
+Implementation:
+
+- let's have a map entry:
+
+cyberb@Unicode@ <cyberbit.ttf PidEid=3,1
+
+- actions:
+ - read Unicode.sfd
+ - create corresponding sfd mapping like ("01", "Unicode") => long[256]
+ - added those subfont to an AVL tree
+ - create map entries for cyberb01--cyberbff, each has a pointer to the
+ corresponding sfd mapping entry
+
+- extended attributes for map entry:
+ - Pid
+ - Eid
+ - sfd_map
+
+- sfd_mapping:
+ - name: sfd name, eg "Unicode"
+ - infix, eg "01"
+ - mapping: long[256]
+
+- how to find out whether a sfd has been loaded:
+ - lookup for any entry with the given sfd name
+
+- functions:
+ - load_sfd
+ - lookup_subfont
+ - extend reading map entries
+
+- when writting ttf:
+ - if re-encoded --> process like in case of type1 fonts
+ - if PidEid is being used:
+ - read cmap tables: store (ttfname, pid, eid)
+ - search for used chars
+ - use sfd to find the charcodes
+ - look into cmap to
diff --git a/Build/source/texk/web2c/luatexdir/font/texfont.c b/Build/source/texk/web2c/luatexdir/font/texfont.c
new file mode 100644
index 00000000000..150c2cba769
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/texfont.c
@@ -0,0 +1,1094 @@
+/*
+ Copyright (c) 1996-2006 Taco Hoekwater <taco@luatex.org>
+
+ This file is part of LuaTeX.
+
+ LuaTeX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ LuaTeX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with LuaTeX; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ $Id: texfont.c 1013 2008-02-14 00:09:02Z oneiros $ */
+
+/* Main font API implementation for the pascal parts */
+
+/* stuff to watch out for:
+ *
+ * - Knuth had a 'null_character' that was used when a character could
+ * not be found by the fetch() routine, to signal an error. This has
+ * been deleted, but it may mean that the output of luatex is
+ * incompatible with TeX after fetch() has detected an error condition.
+ *
+ * - Knuth also had a font_glue() optimization. I've removed that
+ * because it was a bit of dirty programming and it also was
+ * problematic if 0 != null.
+ */
+
+#include "ptexlib.h"
+#include "luatex-api.h"
+
+#define proper_char_index(c) (c<=font_ec(f) && c>=font_bc(f))
+#define dxfree(a,b) { xfree(a); a = b ; }
+#define do_realloc(a,b,d) a = xrealloc(a,(b)*sizeof(d))
+
+texfont **font_tables = NULL;
+
+static integer font_arr_max = 0;
+static integer font_id_maxval = 0;
+
+static void grow_font_table (integer id) {
+ int j;
+ if (id>=font_arr_max) {
+ font_bytes += (font_arr_max-id+8)*sizeof(texfont *);
+ font_tables = xrealloc(font_tables,(id+8)*sizeof(texfont *));
+ j = 8;
+ while (j--) {
+ font_tables[id+j] = NULL;
+ }
+ font_arr_max = id+8;
+ }
+}
+
+integer
+new_font_id (void) {
+ int i;
+ for (i=0;i<font_arr_max;i++) {
+ if (font_tables[i]==NULL) {
+ break;
+ }
+ }
+ if (i>=font_arr_max)
+ grow_font_table (i);
+ if (i>font_id_maxval)
+ font_id_maxval = i;
+ return i;
+}
+
+integer
+max_font_id (void) {
+ return font_id_maxval;
+}
+
+void
+set_max_font_id (integer i) {
+ font_id_maxval = i;
+}
+
+integer
+new_font (void) {
+ int k;
+ int id;
+ charinfo *ci;
+ id = new_font_id();
+ font_bytes += sizeof(texfont);
+ /* most stuff is zero */
+ font_tables[id] = xcalloc(1,sizeof(texfont));
+ font_tables[id]->_font_name = NULL;
+ font_tables[id]->_font_area = NULL;
+ font_tables[id]->_font_filename = NULL;
+ font_tables[id]->_font_fullname = NULL;
+ font_tables[id]->_font_encodingname = NULL;
+ font_tables[id]->_font_cidregistry = NULL;
+ font_tables[id]->_font_cidordering = NULL;
+ font_tables[id]->_left_boundary = NULL;
+ font_tables[id]->_right_boundary = NULL;
+ font_tables[id]->_param_base = NULL;
+
+ set_font_bc(id, 1); /* ec = 0 */
+ set_hyphen_char(id,'-');
+ set_skew_char(id,-1);
+
+ /* allocate eight values including 0 */
+ set_font_params(id,7);
+ for (k=0;k<=7;k++) {
+ set_font_param(id,k,0);
+ }
+ /* character info zero is reserved for notdef */
+ font_tables[id]->characters = new_sa_tree(1, 0); /* stack size 1, default item value 0 */
+
+ ci = xcalloc(1,sizeof(charinfo));
+ set_charinfo_name(ci,xstrdup(".notdef"));
+ font_tables[id]->charinfo = ci;
+ font_tables[id]->charinfo_cache = NULL;
+
+ return id;
+}
+
+#define Charinfo_count(a) font_tables[a]->charinfo_count
+#define Charinfo_size(a) font_tables[a]->charinfo_size
+#define Characters(a) font_tables[a]->characters
+
+charinfo *
+get_charinfo (internal_font_number f, integer c) {
+ sa_tree_item glyph;
+ charinfo *ci;
+ if (proper_char_index(c)) {
+ glyph = get_sa_item(Characters(f), c);
+ if (!glyph) {
+ /* this could be optimized using controlled growth */
+ font_bytes += sizeof(charinfo);
+ glyph = ++font_tables[f]->charinfo_count;
+ do_realloc(font_tables[f]->charinfo, (glyph+1), charinfo);
+ memset (&(font_tables[f]->charinfo[glyph]),0,sizeof(charinfo));
+ font_tables[f]->charinfo[glyph].ef = 1000; /* init */
+ font_tables[f]->charinfo_size = glyph;
+ set_sa_item(font_tables[f]->characters, c, glyph, 1); /* 1= global */
+ }
+ return &(font_tables[f]->charinfo[glyph]);
+ } else if (c == left_boundarychar) {
+ if (left_boundary(f)==NULL) {
+ ci = xcalloc(1,sizeof(charinfo));
+ font_bytes += sizeof(charinfo);
+ set_left_boundary(f,ci);
+ }
+ return left_boundary(f);
+ } else if (c == right_boundarychar) {
+ if (right_boundary(f)==NULL) {
+ ci = xcalloc(1,sizeof(charinfo));
+ font_bytes += sizeof(charinfo);
+ set_right_boundary(f,ci);
+ }
+ return right_boundary(f);
+ }
+ return &(font_tables[f]->charinfo[0]);
+}
+
+void
+set_charinfo (internal_font_number f, integer c, charinfo *ci) {
+ sa_tree_item glyph;
+ if (proper_char_index(c)) {
+ glyph = get_sa_item(Characters(f), c);
+ if (glyph) {
+ font_tables[f]->charinfo[glyph] = *ci;
+ } else {
+ pdftex_fail("font: %s","character insertion failed");
+ }
+ } else if (c == left_boundarychar) {
+ set_left_boundary(f,ci);
+ } else if (c == right_boundarychar) {
+ set_right_boundary(f,ci);
+ }
+}
+
+
+
+charinfo *
+copy_charinfo (charinfo *ci) {
+ int x;
+ kerninfo *kern;
+ liginfo *lig;
+ real_eight_bits *packet;
+ charinfo *co = NULL;
+ if (ci==NULL)
+ return NULL;
+ co = xmalloc(sizeof(charinfo));
+ memcpy(co,ci,sizeof(charinfo));
+ set_charinfo_used(co,false);
+ co->name = NULL;
+ co->tounicode = NULL;
+ co->packets = NULL;
+ co->ligatures = NULL;
+ co->kerns = NULL;
+ co->extensible = NULL;
+ if (ci->name!=NULL) {
+ co->name = xstrdup(ci->name);
+ }
+ if (ci->tounicode!=NULL) {
+ co->tounicode = xstrdup(ci->tounicode);
+ }
+ /* kerns */
+ if ((kern = get_charinfo_kerns(ci)) != NULL) {
+ x = 0;
+ while (!kern_end(kern[x])) { x++; } x++;
+ co->kerns = xmalloc (x*sizeof(kerninfo));
+ memcpy(co->kerns,ci->kerns,(x*sizeof(kerninfo)));
+ }
+ /* ligs */
+ if ((lig = get_charinfo_ligatures(ci)) != NULL) {
+ x = 0;
+ while (!lig_end(lig[x])) { x++; } x++;
+ co->ligatures = xmalloc (x*sizeof(liginfo));
+ memcpy(co->ligatures,ci->ligatures,(x*sizeof(liginfo)));
+ }
+ /* packets */
+ if ((packet = get_charinfo_packets(ci)) != NULL) {
+ x = vf_packet_bytes(ci);
+ co->packets = xmalloc (x);
+ memcpy(co->packets,ci->packets,x);
+ }
+ if (get_charinfo_tag(ci)==ext_tag) {
+ int top, bot, rep, mid;
+ top = get_charinfo_extensible(ci,EXT_TOP);
+ bot = get_charinfo_extensible(ci,EXT_BOT);
+ mid = get_charinfo_extensible(ci,EXT_MID);
+ rep = get_charinfo_extensible(ci,EXT_REP);
+ set_charinfo_extensible(co,top,bot,mid,rep);
+ }
+ return co;
+}
+
+#if 0
+int
+find_charinfo_id (internal_font_number f, integer c) {
+ register int g=0;
+ if (font_tables[f]->charinfo_cache==NULL) {
+ int i = (font_ec(f)+1)*sizeof(int);
+ font_tables[f]->charinfo_cache = xmalloc(i);
+ memset(font_tables[f]->charinfo_cache,0,i);
+ } else {
+ g = font_tables[f]->charinfo_cache[c];
+ }
+ if (g==0) {
+ g = get_sa_item(font_tables[f]->characters, c);
+ font_tables[f]->charinfo_cache[c] = g;
+ }
+ return g;
+}
+#else
+#define find_charinfo_id(f,c) get_sa_item(font_tables[f]->characters,c)
+#endif
+
+
+charinfo *
+char_info (internal_font_number f, integer c) {
+ if (f>font_id_maxval)
+ return 0;
+ if (proper_char_index(c)) {
+ register int glyph = find_charinfo_id(f,c);
+ return &(font_tables[f]->charinfo[glyph]);
+ } else if (c == left_boundarychar && left_boundary(f)!=NULL) {
+ return left_boundary(f);
+ } else if (c == right_boundarychar && right_boundary(f)!=NULL) {
+ return right_boundary(f);
+ }
+ return &(font_tables[f]->charinfo[0]);
+}
+
+charinfo_short
+char_info_short (internal_font_number f, integer c) {
+ charinfo_short s;
+ charinfo *i;
+ i = char_info(f,c);
+ s.ci_wd = i->width;
+ s.ci_dp = i->depth;
+ s.ci_ht = i->height;
+ return s;
+}
+
+integer
+char_exists (internal_font_number f, integer c) {
+ if (f>font_id_maxval)
+ return 0;
+ if (proper_char_index(c)) {
+ return find_charinfo_id(f,c);
+ } else if ((c == left_boundarychar) && has_left_boundary(f)) {
+ return 1;
+ } else if ((c == right_boundarychar) && has_right_boundary(f)) {
+ return 1;
+ }
+ return 0;
+}
+
+int
+lua_char_exists_callback (internal_font_number f, integer c) {
+ integer callback_id ;
+ lua_State *L = Luas[0];
+ int ret=0;
+ callback_id = callback_defined(char_exists_callback);
+ if (callback_id!=0) {
+ lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id);
+ lua_rawgeti(L,-1, callback_id);
+ if (!lua_isfunction(L,-1)) {
+ lua_pop(L,2);
+ return 0;
+ }
+ lua_pushnumber(L,f);
+ lua_pushnumber(L,c);
+ if (lua_pcall(L,2,1,0) != 0) { /* two args, 1 result */
+ fprintf(stdout,"error: %s\n",lua_tostring(L,-1));
+ lua_pop(L,2);
+ error();
+ } else {
+ ret = lua_toboolean(L,-1);
+ }
+ }
+ return ret;
+}
+
+
+void set_charinfo_width (charinfo *ci, scaled val) { ci->width = val; }
+void set_charinfo_height (charinfo *ci, scaled val) { ci->height = val; }
+void set_charinfo_depth (charinfo *ci, scaled val) { ci->depth = val; }
+void set_charinfo_italic (charinfo *ci, scaled val) { ci->italic = val; }
+void set_charinfo_tag (charinfo *ci, scaled val) { ci->tag = val; }
+void set_charinfo_remainder (charinfo *ci, scaled val) { ci->remainder = val; }
+void set_charinfo_used (charinfo *ci, scaled val) { ci->used = val; }
+void set_charinfo_index (charinfo *ci, scaled val) { ci->index = val; }
+void set_charinfo_name (charinfo *ci, char *val) { dxfree(ci->name,val); }
+void set_charinfo_tounicode (charinfo *ci, char *val) { dxfree(ci->tounicode,val); }
+void set_charinfo_ligatures (charinfo *ci, liginfo *val) { dxfree(ci->ligatures,val); }
+void set_charinfo_kerns (charinfo *ci, kerninfo *val) { dxfree(ci->kerns,val); }
+void set_charinfo_packets (charinfo *ci, real_eight_bits *val){ dxfree(ci->packets,val); }
+void set_charinfo_ef (charinfo *ci, scaled val) { ci->ef = val; }
+void set_charinfo_lp (charinfo *ci, scaled val) { ci->lp = val; }
+void set_charinfo_rp (charinfo *ci, scaled val) { ci->rp = val; }
+
+
+
+void set_charinfo_extensible (charinfo *ci, int top, int bot, int mid, int rep) {
+ if (top == 0 && bot == 0 && mid == 0 && rep == 0) {
+ if (ci->extensible != NULL) {
+ free(ci->extensible);
+ ci->extensible = NULL;
+ }
+ } else {
+ if (ci->extensible == NULL) {
+ ci->extensible = xmalloc(4*sizeof(integer));
+ }
+ ci->extensible[EXT_TOP] = top;
+ ci->extensible[EXT_BOT] = bot;
+ ci->extensible[EXT_MID] = mid;
+ ci->extensible[EXT_REP] = rep;
+ }
+}
+
+scaled get_charinfo_width (charinfo *ci) { return ci->width; }
+scaled get_charinfo_height (charinfo *ci) { return ci->height; }
+scaled get_charinfo_depth (charinfo *ci) { return ci->depth; }
+scaled get_charinfo_italic (charinfo *ci) { return ci->italic; }
+char get_charinfo_tag (charinfo *ci) { return ci->tag; }
+integer get_charinfo_remainder (charinfo *ci) { return ci->remainder; }
+char get_charinfo_used (charinfo *ci) { return ci->used; }
+integer get_charinfo_index (charinfo *ci) { return ci->index; }
+char *get_charinfo_name (charinfo *ci) { return ci->name; }
+char *get_charinfo_tounicode (charinfo *ci) { return ci->tounicode; }
+liginfo *get_charinfo_ligatures (charinfo *ci) { return ci->ligatures; }
+kerninfo *get_charinfo_kerns (charinfo *ci) { return ci->kerns; }
+real_eight_bits *get_charinfo_packets (charinfo *ci) { return ci->packets; }
+integer get_charinfo_ef (charinfo *ci) { return ci->ef; }
+integer get_charinfo_rp (charinfo *ci) { return ci->rp; }
+integer get_charinfo_lp (charinfo *ci) { return ci->lp; }
+
+integer get_charinfo_extensible (charinfo *ci, int whch) {
+ int w = 0;
+ if (ci->extensible != NULL)
+ w = ci->extensible[whch];
+ return w;
+}
+
+integer ext_top (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ integer w = get_charinfo_extensible(ci,EXT_TOP);
+ /* fprintf(stdout,"top of char 0x%4x in font %s: %i\n",c,font_name(f),w);*/
+ return w;
+}
+
+integer ext_bot (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ integer w = get_charinfo_extensible(ci,EXT_BOT);
+ /*fprintf(stdout,"bot of char 0x%4x in font %s: %i\n",c,font_name(f),w);*/
+ return w;
+}
+integer ext_mid (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ integer w = get_charinfo_extensible(ci,EXT_MID);
+ /*fprintf(stdout,"mid of char 0x%4x in font %s: %i\n",c,font_name(f),w);*/
+ return w;
+}
+integer ext_rep (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ integer w = get_charinfo_extensible(ci,EXT_REP);
+ /*fprintf(stdout,"rep of char 0x%4x in font %s: %i\n",c,font_name(f),w);*/
+ return w;
+}
+
+scaled char_width (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ scaled w = get_charinfo_width(ci);
+ /*fprintf(stdout,"width of char 0x%x in font %s: %i\n",c,font_name(f),w);*/
+ return w;
+}
+
+scaled char_depth (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ scaled w = get_charinfo_depth(ci);
+ /*fprintf(stdout,"depth of char 0x%x in font %s: %i\n",c,font_name(f),w);*/
+ return w;
+}
+
+scaled char_height (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ scaled w = get_charinfo_height(ci);
+ /*fprintf(stdout,"height of char 0x%x in font %s: %i\n",c,font_name(f),w);*/
+ return w;
+}
+
+scaled char_italic (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_italic(ci);
+}
+
+integer char_remainder (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_remainder(ci);
+}
+
+char char_tag (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_tag(ci);
+}
+
+char char_used (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_used(ci);
+}
+
+char *char_name (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_name(ci);
+}
+
+integer char_index (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_index(ci);
+}
+
+liginfo * char_ligatures (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_ligatures(ci);
+}
+
+kerninfo * char_kerns (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_kerns(ci);
+}
+
+real_eight_bits * char_packets (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_packets(ci);
+}
+
+
+void
+set_font_params(internal_font_number f, int b) {
+ int i;
+ i = font_params(f);
+ if (i!=b) {
+ font_bytes += (b-font_params(f))*sizeof(scaled);
+ do_realloc(param_base(f), (b+1), integer);
+ font_params(f) = b;
+ if (b>i) {
+ while (i<b) {
+ i++;
+ set_font_param(f,i,0);
+ }
+ }
+ }
+}
+
+
+integer
+copy_font (integer f) {
+ int i;
+ charinfo *ci , *co;
+ integer k = new_font();
+ memcpy(font_tables[k],font_tables[f],sizeof(texfont));
+
+ set_font_cache_id(k,0);
+ set_font_used(k,0);
+ set_font_touched(k,0);
+
+ font_tables[k]->_font_name = NULL;
+ font_tables[k]->_font_filename = NULL;
+ font_tables[k]->_font_fullname = NULL;
+ font_tables[k]->_font_encodingname = NULL;
+ font_tables[k]->_font_area = NULL;
+ font_tables[k]->_font_cidregistry = NULL;
+ font_tables[k]->_font_cidordering = NULL;
+ font_tables[k]->_left_boundary = NULL;
+ font_tables[k]->_right_boundary = NULL;
+
+ set_font_name(k,xstrdup(font_name(f)));
+ if (font_filename(f)!= NULL)
+ set_font_filename(k,xstrdup(font_filename(f)));
+ if (font_fullname(f)!= NULL)
+ set_font_fullname(k,xstrdup(font_fullname(f)));
+ if (font_encodingname(f)!= NULL)
+ set_font_encodingname(k,xstrdup(font_encodingname(f)));
+ if (font_area(f)!= NULL)
+ set_font_area(k,xstrdup(font_area(f)));
+ if (font_cidregistry(f)!= NULL)
+ set_font_cidregistry(k,xstrdup(font_cidregistry(f)));
+ if (font_cidordering(f)!= NULL)
+ set_font_cidordering(k,xstrdup(font_cidordering(f)));
+
+ i = sizeof(*param_base(f))*font_params(f);
+ font_bytes += i;
+ param_base(k) = xmalloc (i);
+ memcpy(param_base(k),param_base(f), i);
+
+ i = sizeof(charinfo)*(Charinfo_size(f)+1);
+ font_bytes += i;
+ font_tables[k]->charinfo = xmalloc(i);
+ memset(font_tables[k]->charinfo,0,i);
+ for(i=0;i<=Charinfo_size(k);i++) {
+ ci = copy_charinfo(&font_tables[f]->charinfo[i]);
+ font_tables[k]->charinfo[i] = *ci;
+ }
+
+ if (left_boundary(f)!= NULL ) {
+ ci = copy_charinfo(left_boundary(f));
+ set_charinfo(k,left_boundarychar,ci);
+ }
+
+ if (right_boundary(f)!= NULL ) {
+ ci = copy_charinfo(right_boundary(f));
+ set_charinfo(k,right_boundarychar,ci);
+ }
+ return k;
+}
+
+void delete_font (integer f) {
+ int i;
+ charinfo *co;
+ assert(f>0);
+ if (font_tables[f]!=NULL) {
+ set_font_name(f,NULL);
+ set_font_filename(f,NULL);
+ set_font_fullname(f,NULL);
+ set_font_encodingname(f,NULL);
+ set_font_area(f,NULL);
+ set_font_cidregistry(f,NULL);
+ set_font_cidordering(f,NULL);
+ set_left_boundary(f,NULL);
+ set_right_boundary(f,NULL);
+
+ for(i=font_bc(f); i<=font_ec(f); i++) {
+ if (char_exists(f,i)) {
+ co = char_info(f,i);
+ set_charinfo_name(co,NULL);
+ set_charinfo_tounicode(co,NULL);
+ set_charinfo_packets(co,NULL);
+ set_charinfo_ligatures(co,NULL);
+ set_charinfo_kerns(co,NULL);
+ set_charinfo_extensible(co,0,0,0,0);
+ }
+ }
+ /* free .notdef */
+ set_charinfo_name(font_tables[f]->charinfo+0,NULL);
+ free(font_tables[f]->charinfo);
+ destroy_sa_tree(font_tables[f]->characters);
+
+ free(param_base(f));
+ free(font_tables[f]);
+ font_tables[f] = NULL;
+
+ if (font_id_maxval==f) {
+ font_id_maxval--;
+ }
+ }
+}
+
+void
+create_null_font (void) {
+ int i = new_font();
+ assert(i==0);
+ set_font_name(i,xstrdup("nullfont"));
+ set_font_area(i,xstrdup(""));
+ set_font_touched(i,1);
+}
+
+boolean
+is_valid_font (integer id) {
+ int ret=0;
+ if (id>=0 && id<=font_id_maxval && font_tables[id]!=NULL)
+ ret=1;
+ return ret;
+}
+
+/* return 1 == identical */
+boolean
+cmp_font_name (integer id, strnumber t) {
+ char *tid , *tt;
+ if (!is_valid_font(id))
+ return 0;
+ tt = makecstring(t);
+ tid = font_name(id);
+ if (tt == NULL && tid == NULL)
+ return 1;
+ if (tt == NULL || tid == NULL || strcmp(tid,tt)!=0)
+ return 0;
+ return 1;
+}
+
+boolean
+cmp_font_area (integer id, strnumber t) {
+ char *tt = NULL;
+ char *tid = font_area(id);
+ if (t == 0) {
+ if (tid == NULL || strlen(tid)==0)
+ return 1;
+ else
+ return 0;
+ }
+ tt = makecstring(t);
+ if ((tt == NULL || strlen(tt)==0) && (tid == NULL || strlen(tid)==0))
+ return 1;
+ if (tt == NULL || strcmp(tid,tt)!=0)
+ return 0;
+ return 1;
+}
+
+
+static boolean
+same_font_name (integer id, integer t) {
+ int ret = 0;
+ if (font_name(t) == NULL ||
+ font_name(id) == NULL ||
+ strcmp(font_name(t),font_name(id))!=0) {
+ ;
+ } else {
+ ret =1 ;
+ }
+ return ret;
+}
+
+boolean
+font_shareable (internal_font_number f, internal_font_number k) {
+ int ret = 0;
+ if (font_cidregistry(f) == NULL) {
+ if ( hasfmentry ( k )
+ && ( font_map ( k ) == font_map ( f ) )
+ && ( same_font_name ( k , f )
+ ||
+ ( pdf_font_auto_expand (f)
+ && ( pdf_font_blink (f) != 0 ) /* 0 = nullfont */
+ && same_font_name ( k , pdf_font_blink (f) ) ) ) ) {
+ ret = 1;
+ }
+ } else {
+ if ((font_filename(k) != NULL && font_filename(f) != NULL &&
+ strcmp(font_filename(k),font_filename(f)) == 0)
+ ||
+ ( pdf_font_auto_expand (f)
+ && ( pdf_font_blink (f) != 0 ) /* 0 = nullfont */
+ && same_font_name ( k , pdf_font_blink (f) ) ) ) {
+ ret = 1;
+ }
+ }
+ return ret;
+}
+
+integer
+test_no_ligatures (internal_font_number f) {
+ integer c;
+ for (c=font_bc(f);c<=font_ec(f);c++) {
+ if (has_lig(f,c)) /* char_exists(f,c) */
+ return 0;
+ }
+ return 1;
+}
+
+integer
+get_tag_code (internal_font_number f, integer c) {
+ small_number i;
+ if (char_exists(f,c)) {
+ i = char_tag(f,c);
+ if (i==lig_tag) return 1;
+ else if (i==list_tag) return 2;
+ else if (i==ext_tag) return 4;
+ else return 0;
+ }
+ return -1;
+}
+
+integer
+get_lp_code (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_lp(ci);
+}
+
+integer
+get_rp_code (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_rp(ci);
+}
+
+integer
+get_ef_code (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_ef(ci);
+}
+
+void
+set_tag_code (internal_font_number f, integer c, integer i) {
+ integer fixedi;
+ charinfo * co;
+ if (char_exists(f,c)) {
+ /* abs(fix_int(i-7,0)) */
+ fixedi = - (i<-7 ? -7 : (i>0 ? 0 : i )) ;
+ co = char_info(f,c);
+ if (fixedi >= 4) {
+ if (char_tag(f,c) == ext_tag)
+ set_charinfo_tag(co,(char_tag(f,c)- ext_tag));
+ fixedi = fixedi - 4;
+ }
+ if (fixedi >= 2) {
+ if (char_tag(f,c) == list_tag)
+ set_charinfo_tag(co,(char_tag(f,c)- list_tag));
+ fixedi = fixedi - 2;
+ };
+ if (fixedi >= 1) {
+ if (has_lig(f,c))
+ set_charinfo_ligatures(co,NULL);
+ if (has_kern(f,c))
+ set_charinfo_kerns(co,NULL);
+ }
+ }
+}
+
+
+void
+set_lp_code(internal_font_number f, integer c, integer i) {
+ charinfo * co;
+ if (char_exists(f,c)) {
+ co = char_info(f,c);
+ set_charinfo_lp(co,i);
+ }
+}
+
+void
+set_rp_code(internal_font_number f, integer c, integer i) {
+ charinfo * co;
+ if (char_exists(f,c)) {
+ co = char_info(f,c);
+ set_charinfo_rp(co,i);
+ }
+}
+
+void
+set_ef_code(internal_font_number f, integer c, integer i) {
+ charinfo * co;
+ if (char_exists(f,c)) {
+ co = char_info(f,c);
+ set_charinfo_ef(co,i);
+ }
+}
+
+void
+set_no_ligatures (internal_font_number f) {
+ integer c;
+ charinfo * co;
+
+ if (font_tables[f]->ligatures_disabled)
+ return;
+
+ co = char_info(f,left_boundarychar);
+ set_charinfo_ligatures(co,NULL);
+ co = char_info(f,right_boundarychar); /* this is weird */
+ set_charinfo_ligatures(co,NULL);
+ for (c=0;c<font_tables[f]->charinfo_count;c++) {
+ co = font_tables[f]->charinfo+c;
+ set_charinfo_ligatures(co,NULL);
+ }
+ font_tables[f]->ligatures_disabled =1;
+}
+
+liginfo
+get_ligature (internal_font_number f, integer lc, integer rc) {
+ liginfo t, u;
+ charinfo * co;
+ t.lig = 0;
+ t.type = 0;
+ t.adj = 0;
+ if (lc == non_boundarychar || rc == non_boundarychar || (!has_lig(f,lc)) )
+ return t;
+ k = 0;
+ co = char_info(f,lc);
+ while (1) {
+ u = charinfo_ligature(co,k);
+ if (lig_end(u))
+ break;
+ if (lig_char(u) == rc) {
+ if (lig_disabled(u)) {
+ return t;
+ } else {
+ return u;
+ }
+ }
+ k++;
+ }
+ return t;
+}
+
+
+scaled
+get_kern(internal_font_number f, integer lc, integer rc)
+{
+ integer k;
+ kerninfo u;
+ charinfo * co;
+ if (lc == non_boundarychar || rc == non_boundarychar || (!has_kern(f,lc)) )
+ return 0;
+ k = 0;
+ co = char_info(f,lc);
+ while (1) {
+ u = charinfo_kern(co,k);
+ if (kern_end(u))
+ break;
+ if (kern_char(u) == rc) {
+ if (kern_disabled(u))
+ return 0;
+ else
+ return kern_kern(u);
+ }
+ k++;
+ }
+ return 0;
+}
+
+
+/* dumping and undumping fonts */
+
+#define dump_string(a) \
+ if (a!=NULL) { \
+ x = strlen(a)+1; \
+ dump_int(x); dump_things(*a, x); \
+ } else { \
+ x = 0; dump_int(x); \
+ }
+
+void
+dump_charinfo (int f , int c) {
+ charinfo *co;
+ int x;
+ liginfo *lig;
+ kerninfo *kern;
+
+ dump_int(c);
+ co = char_info(f,c);
+ set_charinfo_used(co,0);
+ dump_int(get_charinfo_width(co));
+ dump_int(get_charinfo_height(co));
+ dump_int(get_charinfo_depth(co));
+ dump_int(get_charinfo_italic(co));
+ dump_int(get_charinfo_tag(co));
+ dump_int(get_charinfo_ef(co));
+ dump_int(get_charinfo_rp(co));
+ dump_int(get_charinfo_lp(co));
+ dump_int(get_charinfo_remainder(co));
+ dump_int(get_charinfo_used(co));
+ dump_int(get_charinfo_index(co));
+ dump_string(get_charinfo_name(co));
+ dump_string(get_charinfo_tounicode(co));
+
+ /* ligatures */
+ x = 0;
+ if ((lig = get_charinfo_ligatures(co)) != NULL) {
+ while (!lig_end(lig[x])) { x++; }
+ x++;
+ dump_int(x); dump_things(*lig, x);
+ } else {
+ dump_int(x);
+ }
+ /* kerns */
+ x = 0;
+ if ((kern = get_charinfo_kerns(co)) != NULL) {
+ while (!kern_end(kern[x])) { x++; }
+ x++;
+ dump_int(x); dump_things(*kern, x);
+ } else {
+ dump_int(x);
+ }
+ /* packets */
+ x= vf_packet_bytes(co);
+ dump_int(x);
+ if (x>0) {
+ dump_things(*get_charinfo_packets(co), x);
+ }
+
+ if (get_charinfo_tag(co)==ext_tag) {
+ x = get_charinfo_extensible(co,EXT_TOP); dump_int(x);
+ x = get_charinfo_extensible(co,EXT_BOT); dump_int(x);
+ x = get_charinfo_extensible(co,EXT_MID); dump_int(x);
+ x = get_charinfo_extensible(co,EXT_REP); dump_int(x);
+ }
+}
+
+void
+dump_font (int f) {
+ int i,x;
+
+ set_font_used(f,0);
+ font_tables[f]->charinfo_cache = NULL;
+ dump_things(*(font_tables[f]), 1);
+ dump_string(font_name(f));
+ dump_string(font_area(f));
+ dump_string(font_filename(f));
+ dump_string(font_fullname(f));
+ dump_string(font_encodingname(f));
+ dump_string(font_cidregistry(f));
+ dump_string(font_cidordering(f));
+
+ dump_things(*param_base(f),(font_params(f)+1));
+
+ if (has_left_boundary(f)) {
+ dump_int(1); dump_charinfo(f,left_boundarychar);
+ } else {
+ dump_int(0);
+ }
+ if (has_right_boundary(f)) {
+ dump_int(1); dump_charinfo(f,right_boundarychar);
+ } else {
+ dump_int(0);
+ }
+
+ for(i=font_bc(f); i<=font_ec(f); i++) {
+ if (char_exists(f,i)) {
+ dump_charinfo(f,i);
+ }
+ }
+}
+
+int
+undump_charinfo (int f) {
+ charinfo *co;
+ int x,i;
+ char *s = NULL;
+ liginfo *lig = NULL;
+ kerninfo *kern = NULL;
+ real_eight_bits *packet = NULL;
+ int top = 0, bot = 0, mid = 0, rep = 0;
+
+ undump_int(i);
+ co = get_charinfo(f,i);
+ undump_int(x); set_charinfo_width(co,x);
+ undump_int(x); set_charinfo_height(co,x);
+ undump_int(x); set_charinfo_depth(co,x);
+ undump_int(x); set_charinfo_italic(co,x);
+ undump_int(x); set_charinfo_tag(co,x);
+ undump_int(x); set_charinfo_ef(co,x);
+ undump_int(x); set_charinfo_rp(co,x);
+ undump_int(x); set_charinfo_lp(co,x);
+ undump_int(x); set_charinfo_remainder(co,x);
+ undump_int(x); set_charinfo_used(co,x);
+ undump_int(x); set_charinfo_index(co,x);
+
+ /* name */
+ undump_int (x);
+ if (x>0) {
+ font_bytes += x;
+ s = xmalloc(x);
+ undump_things(*s,x);
+ }
+ set_charinfo_name(co,s);
+
+ /* tounicode */
+ undump_int (x);
+ if (x>0) {
+ font_bytes += x;
+ s = xmalloc(x);
+ undump_things(*s,x);
+ }
+ set_charinfo_tounicode(co,s);
+
+ /* ligatures */
+ undump_int (x);
+ if (x>0) {
+ font_bytes += x*sizeof(liginfo);
+ lig = xmalloc(x*sizeof(liginfo));
+ undump_things(*lig,x);
+ }
+ set_charinfo_ligatures(co,lig);
+
+ /* kerns */
+ undump_int (x);
+ if (x>0) {
+ font_bytes += x*sizeof(kerninfo);
+ kern = xmalloc(x*sizeof(kerninfo));
+ undump_things(*kern,x);
+ }
+ set_charinfo_kerns(co,kern);
+
+ /* packets */
+ undump_int (x);
+ if (x>0) {
+ font_bytes += x;
+ packet = xmalloc(x);
+ undump_things(*packet,x);
+ }
+ set_charinfo_packets(co,packet);
+
+ if (get_charinfo_tag(co)==ext_tag) {
+ undump_int(top);
+ undump_int(bot);
+ undump_int(mid);
+ undump_int(rep);
+ set_charinfo_extensible(co,top,bot,mid,rep);
+ }
+ return i;
+}
+
+#define undump_font_string(a) undump_int (x); \
+ if (x>0) { \
+ font_bytes += x; \
+ s = xmalloc(x); undump_things(*s,x); \
+ a(f,s); }
+
+
+void
+undump_font(int f)
+{
+ int x, i;
+ texfont *tt;
+ charinfo *ci;
+ char *s;
+ grow_font_table (f);
+ font_tables[f] = NULL;
+ font_bytes += sizeof(texfont);
+ tt = xmalloc(sizeof(texfont));
+ undump_things(*tt,1);
+ font_tables[f] = tt;
+
+ undump_font_string(set_font_name);
+ undump_font_string(set_font_area);
+ undump_font_string(set_font_filename);
+ undump_font_string(set_font_fullname);
+ undump_font_string(set_font_encodingname);
+ undump_font_string(set_font_cidregistry);
+ undump_font_string(set_font_cidordering);
+
+ i = sizeof(*param_base(f))*(font_params(f)+1);
+ font_bytes += i;
+ param_base(f) = xmalloc (i);
+ undump_things(*param_base(f), (font_params(f)+1));
+
+ font_tables[f]->_left_boundary = NULL;
+ undump_int(x);
+ if (x) { i = undump_charinfo(f); } /* left boundary */
+
+ font_tables[f]->_right_boundary = NULL;
+ undump_int(x);
+ if (x) { i = undump_charinfo(f); } /* right boundary */
+
+
+ font_tables[f]->characters = new_sa_tree(1, 0); /* stack size 1, default item value 0 */
+ ci = xcalloc(1,sizeof(charinfo));
+ set_charinfo_name(ci,xstrdup(".notdef"));
+ font_tables[f]->charinfo = ci;
+
+ i = font_bc(f);
+ while(i<font_ec(f)) {
+ i = undump_charinfo(f);
+ }
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/font/texfont.h b/Build/source/texk/web2c/luatexdir/font/texfont.h
new file mode 100644
index 00000000000..21b79f1e876
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/texfont.h
@@ -0,0 +1,524 @@
+/*
+ Copyright (c) 1996-2006 Taco Hoekwater <taco@luatex.org>
+
+ This file is part of LuaTeX.
+
+ LuaTeX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ LuaTeX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with LuaTeX; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ $Id: texfont.h 1117 2008-03-21 15:26:12Z hhenkel $ */
+
+/* Here we have the interface to LuaTeX's font system, as seen from the
+ main pascal program. There is a companion list in luatex.defines to
+ keep web2c happy */
+
+/* this file is read at the end of ptexlib.h, which is called for at
+ the end of luatexcoerce.h, as well as from the C sources
+*/
+
+#ifndef TEXFONT_H
+#define TEXFONT_H 1
+
+#include "luatexdir/managed-sa.h"
+
+#define pointer halfword
+
+typedef struct liginfo {
+ integer adj;
+ integer lig;
+ char type;
+} liginfo;
+
+typedef struct kerninfo {
+ integer adj;
+ scaled sc;
+} kerninfo;
+
+typedef struct charinfo {
+ char *name; /* postscript character name */
+ liginfo *ligatures; /* ligature items */
+ kerninfo *kerns; /* kern items */
+ real_eight_bits *packets; /* virtual commands. */
+ integer *extensible; /* extensible recipe (if any) */
+ unsigned short index; /* CID index */
+ integer remainder; /* spare value for odd items, could be union-ed with extensible */
+ scaled width; /* width */
+ scaled height; /* height */
+ scaled depth; /* depth */
+ scaled italic; /* italic correction */
+ integer ef; /* font expansion factor */
+ integer lp; /* left protruding factor */
+ integer rp; /* right protruding factor */
+ char tag ; /* list / ext taginfo */
+ char used ; /* char is typeset ? */
+ char *tounicode; /* unicode equivalent */
+} charinfo;
+
+
+/* this is for speed reasons, it is called from the web source
+ when more than two of the traditional four char values are needed
+ at the same time. the structure |charinfo_short| is defined in
+ web */
+
+#ifndef luaTeX
+typedef struct charinfo_short {
+ scaled ci_wd; /* width */
+ scaled ci_ht; /* height */
+ scaled ci_dp; /* depth */
+} charinfo_short;
+#endif
+
+
+extern charinfo_short char_info_short (internal_font_number f, integer c);
+
+
+
+typedef struct texfont {
+ integer _font_size ;
+ integer _font_dsize ;
+ char * _font_name ;
+ char * _font_area ;
+ char * _font_filename ;
+ char * _font_fullname ;
+ char * _font_encodingname ;
+ char * _font_cidregistry ;
+ char * _font_cidordering ;
+ integer _font_cidversion ;
+ integer _font_cidsupplement ;
+
+ integer _font_ec ;
+ integer _font_checksum ; /* internal information */
+ char _font_used ; /* internal information */
+ char _font_touched ; /* internal information */
+ integer _font_cache_id ; /* internal information */
+ char _font_encodingbytes ; /* 1 or 2 bytes */
+ integer _font_slant ; /* a slant in ppt */
+ integer _font_extend ; /* an extension in ppt, or 0 */
+ char _font_tounicode ; /* 1 if info is present */
+ fm_entry_ptr _font_map;
+ integer _font_type;
+ integer _font_format;
+ integer _font_embedding;
+ integer _font_bc ;
+ integer _hyphen_char ;
+ integer _skew_char ;
+ integer _font_natural_dir;
+
+ charinfo *_left_boundary;
+ charinfo *_right_boundary;
+
+ integer _font_params;
+ scaled *_param_base;
+
+ sa_tree characters;
+ integer charinfo_count;
+ integer charinfo_size;
+ charinfo *charinfo;
+ int *charinfo_cache;
+ integer ligatures_disabled;
+
+ integer _pdf_font_num; /* maps to a PDF resource ID */
+ scaled _pdf_font_size; /* maps to a PDF font size */
+ internal_font_number _pdf_font_blink; /* link to base font for expanded fonts */
+ internal_font_number _pdf_font_elink; /* link to expanded fonts for base font */
+ integer _pdf_font_expand_ratio; /* expansion ratio of a particular font */
+ internal_font_number _pdf_font_shrink; /* font at limit of shrinking */
+ internal_font_number _pdf_font_stretch; /* font at limit of stretching */
+ integer _pdf_font_step; /* amount of one step of expansion */
+ boolean _pdf_font_auto_expand; /* this font is auto-expanded? */
+ str_number _pdf_font_attr; /* pointer to additional attributes */
+} texfont;
+
+typedef enum {
+ unknown_font_type=0, /* new font (has not been used yet) */
+ virtual_font_type, /* virtual font */
+ real_font_type, /* real font */
+} font_types;
+
+typedef enum {
+ unknown_format=0,
+ type1_format,
+ type3_format,
+ truetype_format,
+ opentype_format,
+} font_formats;
+
+typedef enum {
+ unknown_embedding=0,
+ no_embedding,
+ subset_embedding,
+ full_embedding,
+} font_embedding_option;
+
+extern char *font_type_strings[];
+extern char *font_format_strings[];
+extern char *font_embedding_strings[];
+
+
+#define font_checksum(a) font_tables[a]->_font_checksum
+#define set_font_checksum(a,b) font_checksum(a) = b
+
+#define font_check_0(a) ((font_tables[a]->_font_checksum&0xFF000000)>>24)
+#define font_check_1(a) ((font_tables[a]->_font_checksum&0x00FF0000)>>16)
+#define font_check_2(a) ((font_tables[a]->_font_checksum&0x0000FF00)>>8)
+#define font_check_3(a) (font_tables[a]->_font_checksum&0x000000FF)
+
+#define font_size(a) font_tables[a]->_font_size
+#define set_font_size(a,b) font_size(a) = b
+#define font_dsize(a) font_tables[a]->_font_dsize
+#define set_font_dsize(a,b) font_dsize(a) = b
+
+#define font_name(a) font_tables[a]->_font_name
+#define get_font_name(a) (unsigned char *)font_name(a)
+#define set_font_name(f,b) font_name(f) = b
+#define tex_font_name(a) maketexstring(font_name(a))
+
+boolean cmp_font_name (integer, strnumber);
+
+#define font_area(a) font_tables[a]->_font_area
+#define get_font_area(a) (unsigned char *)font_area(a)
+#define set_font_area(f,b) font_area(f) = b
+#define tex_font_area(a) maketexstring(font_area(a))
+
+boolean cmp_font_area (integer, strnumber);
+
+#define font_reassign(a,b) { if (a!=NULL) free(a); a = b; }
+
+#define font_filename(a) font_tables[a]->_font_filename
+#define set_font_filename(f,b) font_reassign(font_filename(f),b)
+
+#define font_fullname(a) font_tables[a]->_font_fullname
+#define set_font_fullname(f,b) font_reassign(font_fullname(f),b)
+
+#define font_encodingname(a) font_tables[a]->_font_encodingname
+#define set_font_encodingname(f,b) font_reassign(font_encodingname(f),b)
+
+boolean font_shareable(internal_font_number,internal_font_number);
+
+#define cmp_font_filename(a,b) (!(font_filename(a)!=NULL || font_filename(b)!=NULL || \
+ strcmp(font_filename(a),font_filename(b))))
+#define cmp_font_fullname(a,b) (!(font_fullname(a)!=NULL || font_fullname(b)!=NULL || \
+ strcmp(font_fullname(a),font_fullname(b))))
+#define cmp_font_encodingname(a,b) (!(font_encoding(a)!=NULL || font_encodingname(b)!=NULL || \
+ strcmp(font_encodingname(a),font_encodingname(b))))
+
+#define font_bc(a) font_tables[a]->_font_bc
+#define set_font_bc(f,b) font_bc(f) = b
+
+#define font_ec(a) font_tables[a]->_font_ec
+#define set_font_ec(f,b) font_ec(f) = b
+
+#define font_used(a) (font_tables[a]!=NULL && font_tables[a]->_font_used)
+#define set_font_used(a,b) font_tables[a]->_font_used = b
+
+#define font_touched(a) font_tables[a]->_font_touched
+#define set_font_touched(a,b) font_touched(a) = b
+
+#define font_type(a) font_tables[a]->_font_type
+#define set_font_type(a,b) { /* fprintf(stdout,"set font type of %s to %i: %s\n",font_name(a),b,__FILE__); */ \
+ font_type(a) = b; }
+
+#define font_format(a) font_tables[a]->_font_format
+#define font_format_name(a) font_format_strings[font_tables[a]->_font_format]
+#define set_font_format(a,b) font_format(a) = b
+
+#define font_embedding(a) font_tables[a]->_font_embedding
+#define set_font_embedding(a,b) font_embedding(a) = b
+
+#define font_cidversion(a) font_tables[a]->_font_cidversion
+#define set_font_cidversion(a,b) font_cidversion(a) = b
+
+#define font_cidsupplement(a) font_tables[a]->_font_cidsupplement
+#define set_font_cidsupplement(a,b) font_cidsupplement(a) = b
+
+#define font_cidordering(a) font_tables[a]->_font_cidordering
+#define set_font_cidordering(f,b) font_reassign(font_cidordering(f),b)
+
+#define font_cidregistry(a) font_tables[a]->_font_cidregistry
+#define set_font_cidregistry(f,b) font_reassign(font_cidregistry(f),b)
+
+#define font_map(a) font_tables[a]->_font_map
+#define set_font_map(a,b) font_map(a) = b
+
+#define font_cache_id(a) font_tables[a]->_font_cache_id
+#define set_font_cache_id(a,b) font_cache_id(a) = b
+
+#define font_encodingbytes(a) font_tables[a]->_font_encodingbytes
+#define set_font_encodingbytes(a,b) font_encodingbytes(a) = b
+
+#define font_slant(a) font_tables[a]->_font_slant
+#define set_font_slant(a,b) font_slant(a) = b
+
+#define font_extend(a) font_tables[a]->_font_extend
+#define set_font_extend(a,b) font_extend(a) = b
+
+#define font_tounicode(a) font_tables[a]->_font_tounicode
+#define set_font_tounicode(a,b) font_tounicode(a) = b
+
+#define hyphen_char(a) font_tables[a]->_hyphen_char
+#define set_hyphen_char(a,b) hyphen_char(a) = b
+
+#define skew_char(a) font_tables[a]->_skew_char
+#define set_skew_char(a,b) skew_char(a) = b
+
+#define font_natural_dir(a) font_tables[a]->_font_natural_dir
+#define set_font_natural_dir(a,b) font_natural_dir(a) = b
+
+#define pdf_font_size(a) font_tables[a]->_pdf_font_size
+#define set_pdf_font_size(a,b) pdf_font_size(a) = b
+
+#define pdf_font_num(a) font_tables[a]->_pdf_font_num
+#define set_pdf_font_num(a,b) pdf_font_num(a) = b
+
+#define pdf_font_blink(a) font_tables[a]->_pdf_font_blink
+#define set_pdf_font_blink(a,b) pdf_font_blink(a) = b
+
+#define pdf_font_elink(a) font_tables[a]->_pdf_font_elink
+#define set_pdf_font_elink(a,b) pdf_font_elink(a) = b
+
+#define pdf_font_expand_ratio(a) font_tables[a]->_pdf_font_expand_ratio
+#define set_pdf_font_expand_ratio(a,b) pdf_font_expand_ratio(a) = b
+
+#define pdf_font_shrink(a) font_tables[a]->_pdf_font_shrink
+#define set_pdf_font_shrink(a,b) pdf_font_shrink(a) = b
+
+#define pdf_font_stretch(a) font_tables[a]->_pdf_font_stretch
+#define set_pdf_font_stretch(a,b) pdf_font_stretch(a) = b
+
+#define pdf_font_step(a) font_tables[a]->_pdf_font_step
+#define set_pdf_font_step(a,b) pdf_font_step(a) = b
+
+#define pdf_font_auto_expand(a) font_tables[a]->_pdf_font_auto_expand
+#define set_pdf_font_auto_expand(a,b) pdf_font_auto_expand(a) = b
+
+#define pdf_font_attr(a) font_tables[a]->_pdf_font_attr
+#define set_pdf_font_attr(a,b) pdf_font_attr(a) = b
+
+
+#define left_boundarychar -1
+#define right_boundarychar -2
+#define non_boundarychar -3
+
+#define left_boundary(a) font_tables[a]->_left_boundary
+#define has_left_boundary(a) (left_boundary(a)!=NULL)
+#define set_left_boundary(a,b) font_reassign(left_boundary(a),b)
+
+#define right_boundary(a) font_tables[a]->_right_boundary
+#define has_right_boundary(a) (right_boundary(a)!=NULL)
+#define set_right_boundary(a,b) font_reassign(right_boundary(a),b)
+
+#define font_bchar(a) (right_boundary(a)!=NULL ? right_boundarychar : non_boundarychar)
+
+/* font parameters */
+
+#define font_params(a) font_tables[a]->_font_params
+#define param_base(a) font_tables[a]->_param_base
+#define font_param(a,b) font_tables[a]->_param_base[b]
+
+extern void set_font_params(internal_font_number f, int b);
+
+#define set_font_param(f,n,b) \
+ { if (font_params(f)<n) set_font_params(f,n); \
+ font_param(f,n) = b; }
+
+/* Font parameters are sometimes referred to as |slant(f)|, |space(f)|, etc.*/
+
+typedef enum {
+ slant_code = 1,
+ space_code = 2,
+ space_stretch_code = 3,
+ space_shrink_code = 4,
+ x_height_code = 5,
+ quad_code = 6,
+ extra_space_code = 7 } font_parameter_codes ;
+
+#define slant(f) font_param(f,slant_code)
+#define space(f) font_param(f,space_code)
+#define space_stretch(f) font_param(f,space_stretch_code)
+#define space_shrink(f) font_param(f,space_shrink_code)
+#define x_height(f) font_param(f,x_height_code)
+#define quad(f) font_param(f,quad_code)
+#define extra_space(f) font_param(f,extra_space_code)
+
+/* now for characters */
+
+extern charinfo *get_charinfo (internal_font_number f, integer c) ;
+extern integer char_exists (internal_font_number f, integer c);
+extern charinfo *char_info (internal_font_number f, integer c);
+
+
+extern void set_charinfo_width (charinfo *ci, scaled val);
+extern void set_charinfo_height (charinfo *ci, scaled val);
+extern void set_charinfo_depth (charinfo *ci, scaled val);
+extern void set_charinfo_italic (charinfo *ci, scaled val);
+extern void set_charinfo_tag (charinfo *ci, scaled val);
+extern void set_charinfo_remainder (charinfo *ci, scaled val);
+extern void set_charinfo_used (charinfo *ci, scaled val);
+extern void set_charinfo_index (charinfo *ci, scaled val);
+extern void set_charinfo_name (charinfo *ci, char *val) ;
+extern void set_charinfo_tounicode (charinfo *ci, char *val) ;
+extern void set_charinfo_ligatures (charinfo *ci, liginfo *val);
+extern void set_charinfo_kerns (charinfo *ci, kerninfo *val);
+extern void set_charinfo_packets (charinfo *ci, real_eight_bits *val);
+extern void set_charinfo_extensible (charinfo *ci, int a, int b, int c, int d);
+
+#define set_char_used(f,a,b) set_charinfo_used(get_charinfo(f,a),b)
+
+extern scaled get_charinfo_width (charinfo *ci);
+extern scaled get_charinfo_height (charinfo *ci);
+extern scaled get_charinfo_depth (charinfo *ci);
+extern scaled get_charinfo_italic (charinfo *ci);
+extern char get_charinfo_tag (charinfo *ci);
+extern integer get_charinfo_remainder (charinfo *ci);
+extern char get_charinfo_used (charinfo *ci);
+extern integer get_charinfo_index (charinfo *ci);
+extern char * get_charinfo_name (charinfo *ci) ;
+extern char * get_charinfo_tounicode (charinfo *ci) ;
+extern liginfo * get_charinfo_ligatures (charinfo *ci);
+extern kerninfo *get_charinfo_kerns (charinfo *ci);
+extern real_eight_bits *get_charinfo_packets (charinfo *ci);
+extern integer get_charinfo_extensible (charinfo *ci, int which);
+
+extern integer ext_top (internal_font_number f, integer c);
+extern integer ext_bot (internal_font_number f, integer c);
+extern integer ext_rep (internal_font_number f, integer c);
+extern integer ext_mid (internal_font_number f, integer c);
+
+#define set_ligature_item(f,b,c,d) { f.type = b; f.adj = c; f.lig = d; }
+
+#define set_kern_item(f,b,c) { f.adj = b; f.sc = c; }
+
+
+/* character information */
+
+#define non_char 65536 /* a code that can't match a real character */
+#define non_address 0 /* a spurious |bchar_label| */
+
+
+/* character kerns and ligatures */
+
+#define end_kern 0x7FFFFF /* otherchar value meaning "stop" */
+#define ignored_kern 0x800000 /* otherchar value meaning "disabled" */
+
+#define charinfo_kern(b,c) b->kerns[c]
+
+#define kern_char(b) (b).adj
+#define kern_kern(b) (b).sc
+#define kern_end(b) ((b).adj == end_kern)
+#define kern_disabled(b) ((b).adj > end_kern)
+
+/* character ligatures */
+
+#define end_ligature 0x7FFFFF /* otherchar value meaning "stop" */
+#define ignored_ligature 0x800000 /* otherchar value meaning "disabled" */
+
+#define charinfo_ligature(b,c) b->ligatures[c]
+
+#define is_valid_ligature(a) ((a).type!=0)
+#define lig_type(a) ((a).type>>1)
+#define lig_char(a) (a).adj
+#define lig_replacement(a) (a).lig
+#define lig_end(a) (lig_char(a) == end_ligature)
+#define lig_disabled(a) (lig_char(a) > end_ligature)
+
+#define no_tag 0 /* vanilla character */
+#define lig_tag 1 /* character has a ligature/kerning program */
+#define list_tag 2 /* character has a successor in a charlist */
+#define ext_tag 3 /* character is extensible */
+
+extern scaled char_height (internal_font_number f, integer c);
+extern scaled char_width (internal_font_number f, integer c);
+extern scaled char_depth (internal_font_number f, integer c);
+extern scaled char_italic (internal_font_number f, integer c);
+
+extern liginfo * char_ligatures (internal_font_number f, integer c);
+extern kerninfo * char_kerns (internal_font_number f, integer c);
+extern real_eight_bits * char_packets (internal_font_number f, integer c);
+
+#define has_lig(f,b) (char_exists(f,b) &&( char_ligatures(f,b) != NULL))
+#define has_kern(f,b) (char_exists(f,b) && (char_kerns(f,b) != NULL))
+#define has_packet(f,b) (char_exists(f,b) && (char_packets(f,b) != NULL))
+
+extern integer char_remainder (internal_font_number f, integer c);
+extern char char_tag (internal_font_number f, integer c);
+extern char char_used (internal_font_number f, integer c);
+extern char * char_name (internal_font_number f, integer c);
+extern integer char_index (internal_font_number f, integer c);
+
+scaled get_kern(internalfontnumber f, integer lc, integer rc);
+liginfo get_ligature(internalfontnumber f, integer lc, integer rc);
+
+#define EXT_TOP 0
+#define EXT_BOT 1
+#define EXT_MID 2
+#define EXT_REP 3
+
+extern texfont **font_tables;
+
+integer new_font (void) ;
+integer copy_font (integer id) ;
+integer scale_font (integer id, integer atsize) ;
+integer max_font_id (void);
+void set_max_font_id (integer id);
+integer new_font_id (void);
+void create_null_font (void);
+void delete_font(integer id);
+boolean is_valid_font (integer id);
+
+void dump_font (int font_number);
+void undump_font (int font_number);
+
+integer test_no_ligatures (internal_font_number f) ;
+void set_no_ligatures (internal_font_number f) ;
+
+extern integer get_tag_code (internal_font_number f, integer c);
+extern integer get_lp_code (internal_font_number f, integer c);
+extern integer get_rp_code (internal_font_number f, integer c);
+extern integer get_ef_code (internal_font_number f, integer c);
+
+extern void set_tag_code (internal_font_number f, integer c, integer i) ;
+extern void set_lp_code(internal_font_number f, integer c, integer i) ;
+extern void set_rp_code(internal_font_number f, integer c, integer i) ;
+extern void set_ef_code(internal_font_number f, integer c, integer i) ;
+
+int read_tfm_info(internal_font_number f, char *nom, char *aire, scaled s);
+
+
+/* from dofont.c */
+
+extern int read_font_info (pointer u, strnumber nom, strnumber aire, scaled s, integer ndir);
+extern int find_font_id (char *nom, char *aire, scaled s);
+
+/* for and from vfpacket.c */
+
+#define scan_special 3 /* look into special text */ /* this is a hack */
+
+typedef enum { packet_char_code,
+ packet_font_code,
+ packet_pop_code,
+ packet_push_code,
+ packet_special_code,
+ packet_right_code,
+ packet_down_code,
+ packet_rule_code,
+ packet_node_code,
+ packet_nop_code,
+ packet_end_code } packet_command_codes;
+
+extern scaled sqxfw (scaled sq, integer fw);
+
+extern void do_vf_packet (internal_font_number vf_f, integer c);
+extern int vf_packet_bytes (charinfo *co);
+
+#endif
diff --git a/Build/source/texk/web2c/luatexdir/font/tfmofm.c b/Build/source/texk/web2c/luatexdir/font/tfmofm.c
new file mode 100644
index 00000000000..db82f94deba
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/tfmofm.c
@@ -0,0 +1,1005 @@
+/*
+Copyright (c) 1996-2006 Taco Hoekwater <taco@luatex.org>
+
+This file is part of LuaTeX.
+
+LuaTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+LuaTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with LuaTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: tfmofm.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+
+#include "luatex-api.h"
+
+/* Here are some macros that help process ligatures and kerns */
+
+#define lig_kern_start(f,c) char_remainder(f,c)
+#define stop_flag 128 /* value indicating `\.{STOP}' in a lig/kern program */
+#define kern_flag 128 /* op code for a kern step */
+
+#define skip_byte(z) lig_kerns[z].b0
+#define next_char(z) lig_kerns[z].b1
+#define op_byte(z) lig_kerns[z].b2
+#define rem_byte(z) lig_kerns[z].b3
+#define lig_kern_restart(c) (256*op_byte(c)+rem_byte(c))
+
+/*
+
+The information in a \.{TFM} file appears in a sequence of 8-bit bytes.
+Since the number of bytes is always a multiple of 4, we could
+also regard the file as a sequence of 32-bit words, but \TeX\ uses the
+byte interpretation. The format of \.{TFM} files was designed by
+Lyle Ramshaw in 1980. The intent is to convey a lot of different kinds
+@^Ramshaw, Lyle Harold@>
+of information in a compact but useful form.
+
+$\Omega$ is capable of reading not only \.{TFM} files, but also
+\.{OFM} files, which can describe fonts with up to 65536 characters
+and with huge lig/kern tables. These fonts will often be virtual
+fonts built up from real fonts with 256 characters, but $\Omega$
+is not aware of this.
+
+The documentation below describes \.{TFM} files, with slight additions
+to show where \.{OFM} files differ.
+ */
+/*
+@ The first 24 bytes (6 words) of a \.{TFM} file contain twelve 16-bit
+integers that give the lengths of the various subsequent portions
+of the file. These twelve integers are, in order:
+$$\vbox{\halign{\hfil#&$\null=\null$#\hfil\cr
+|lf|&length of the entire file, in words;\cr
+|lh|&length of the header data, in words;\cr
+|bc|&smallest character code in the font;\cr
+|ec|&largest character code in the font;\cr
+|nw|&number of words in the width table;\cr
+|nh|&number of words in the height table;\cr
+|nd|&number of words in the depth table;\cr
+|ni|&number of words in the italic correction table;\cr
+|nl|&number of words in the lig/kern table;\cr
+|nk|&number of words in the kern table;\cr
+|ne|&number of words in the extensible character table;\cr
+|np|&number of font parameter words.\cr}}$$
+They are all nonnegative and less than $2^{15}$. We must have |bc-1<=ec<=255|,
+and
+$$\hbox{|lf=6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np|.}$$
+Note that a \.{TFM} font may contain as many as 256 characters
+(if |bc=0| and |ec=255|), and as few as 0 characters (if |bc=ec+1|).
+
+Incidentally, when two or more 8-bit bytes are combined to form an integer of
+16 or more bits, the most significant bytes appear first in the file.
+This is called BigEndian order.
+@!@^BigEndian order@>
+
+The first 52 bytes (13 words) of an \.{OFM} file contains thirteen
+32-bit integers that give the lengths of the various subsequent
+portions of the file. The first word is 0 (future versions of
+\.{OFM} files could have different values; what is important is that
+the first two bytes be 0 to differentiate \.{TFM} and \.{OFM} files).
+The next twelve integers are as above, all nonegative and less
+than~$2^{31}$. We must have |bc-1<=ec<=65535|, and
+$$\hbox{|lf=13+lh+2*(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np|.}$$
+Note that an \.{OFM} font may contain as many as 65536 characters
+(if |bc=0| and |ec=65535|), and as few as 0 characters (if |bc=ec+1|).
+
+@ The rest of the \.{TFM} file may be regarded as a sequence of ten data
+arrays having the informal specification
+$$\def\arr$[#1]#2${\&{array} $[#1]$ \&{of} #2}
+\vbox{\halign{\hfil\\{#}&$\,:\,$\arr#\hfil\cr
+header&|[0..lh-1]@t\\{stuff}@>|\cr
+char\_info&|[bc..ec]char_info_word|\cr
+width&|[0..nw-1]fix_word|\cr
+height&|[0..nh-1]fix_word|\cr
+depth&|[0..nd-1]fix_word|\cr
+italic&|[0..ni-1]fix_word|\cr
+lig\_kern&|[0..nl-1]lig_kern_command|\cr
+kern&|[0..nk-1]fix_word|\cr
+exten&|[0..ne-1]extensible_recipe|\cr
+param&|[1..np]fix_word|\cr}}$$
+The most important data type used here is a |@!fix_word|, which is
+a 32-bit representation of a binary fraction. A |fix_word| is a signed
+quantity, with the two's complement of the entire word used to represent
+negation. Of the 32 bits in a |fix_word|, exactly 12 are to the left of the
+binary point; thus, the largest |fix_word| value is $2048-2^{-20}$, and
+the smallest is $-2048$. We will see below, however, that all but two of
+the |fix_word| values must lie between $-16$ and $+16$.
+
+@ The first data array is a block of header information, which contains
+general facts about the font. The header must contain at least two words,
+|header[0]| and |header[1]|, whose meaning is explained below.
+Additional header information of use to other software routines might
+also be included, but \TeX82 does not need to know about such details.
+For example, 16 more words of header information are in use at the Xerox
+Palo Alto Research Center; the first ten specify the character coding
+scheme used (e.g., `\.{XEROX text}' or `\.{TeX math symbols}'), the next five
+give the font identifier (e.g., `\.{HELVETICA}' or `\.{CMSY}'), and the
+last gives the ``face byte.'' The program that converts \.{DVI} files
+to Xerox printing format gets this information by looking at the \.{TFM}
+file, which it needs to read anyway because of other information that
+is not explicitly repeated in \.{DVI}~format.
+
+\yskip\hang|header[0]| is a 32-bit check sum that \TeX\ will copy into
+the \.{DVI} output file. Later on when the \.{DVI} file is printed,
+possibly on another computer, the actual font that gets used is supposed
+to have a check sum that agrees with the one in the \.{TFM} file used by
+\TeX. In this way, users will be warned about potential incompatibilities.
+(However, if the check sum is zero in either the font file or the \.{TFM}
+file, no check is made.) The actual relation between this check sum and
+the rest of the \.{TFM} file is not important; the check sum is simply an
+identification number with the property that incompatible fonts almost
+always have distinct check sums.
+@^check sum@>
+
+\yskip\hang|header[1]| is a |fix_word| containing the design size of
+the font, in units of \TeX\ points. This number must be at least 1.0; it is
+fairly arbitrary, but usually the design size is 10.0 for a ``10 point''
+font, i.e., a font that was designed to look best at a 10-point size,
+whatever that really means. When a \TeX\ user asks for a font
+`\.{at} $\delta$ \.{pt}', the effect is to override the design size
+and replace it by $\delta$, and to multiply the $x$ and~$y$ coordinates
+of the points in the font image by a factor of $\delta$ divided by the
+design size. {\sl All other dimensions in the\/ \.{TFM} file are
+|fix_word|\kern-1pt\ numbers in design-size units}, with the exception of
+|param[1]| (which denotes the slant ratio). Thus, for example, the value
+of |param[6]|, which defines the \.{em} unit, is often the |fix_word| value
+$2^{20}=1.0$, since many fonts have a design size equal to one em.
+The other dimensions must be less than 16 design-size units in absolute
+value; thus, |header[1]| and |param[1]| are the only |fix_word|
+entries in the whole \.{TFM} file whose first byte might be something
+besides 0 or 255.
+
+@ Next comes the |char_info| array, which contains one |@!char_info_word|
+per character. Each word in this part of a \.{TFM} file contains six fields
+packed into four bytes as follows.
+
+\yskip\hang first byte: |@!width_index| (8 bits)\par
+\hang second byte: |@!height_index| (4 bits) times 16, plus |@!depth_index|
+ (4~bits)\par
+\hang third byte: |@!italic_index| (6 bits) times 4, plus |@!tag|
+ (2~bits)\par
+\hang fourth byte: |@!remainder| (8 bits)\par
+\yskip\noindent
+The actual width of a character is \\{width}|[width_index]|, in design-size
+units; this is a device for compressing information, since many characters
+have the same width. Since it is quite common for many characters
+to have the same height, depth, or italic correction, the \.{TFM} format
+imposes a limit of 16 different heights, 16 different depths, and
+64 different italic corrections.
+
+For \.{OFM} files, two words (eight bytes) are used.
+The arrangement is as follows.
+
+\yskip\hang first and second bytes: |@!width_index| (16 bits)\par
+\hang third byte: |@!height_index| (8 bits)\par
+\hang fourth byte: |@!depth_index| (8~bits)\par
+\hang fifth and sixth bytes:
+|@!italic_index| (14 bits) times 4, plus |@!tag| (2~bits)\par
+\hang seventh and eighth bytes: |@!remainder| (16 bits)\par
+\yskip\noindent
+Therefore the \.{OFM} format imposes a limit of 256 different heights,
+256 different depths, and 16384 different italic corrections.
+
+@!@^italic correction@>
+The italic correction of a character has two different uses.
+(a)~In ordinary text, the italic correction is added to the width only if
+the \TeX\ user specifies `\.{\\/}' after the character.
+(b)~In math formulas, the italic correction is always added to the width,
+except with respect to the positioning of subscripts.
+
+Incidentally, the relation $\\{width}[0]=\\{height}[0]=\\{depth}[0]=
+\\{italic}[0]=0$ should always hold, so that an index of zero implies a
+value of zero. The |width_index| should never be zero unless the
+character does not exist in the font, since a character is valid if and
+only if it lies between |bc| and |ec| and has a nonzero |width_index|.
+*/
+
+ /*
+@ \TeX\ checks the information of a \.{TFM} file for validity as the
+file is being read in, so that no further checks will be needed when
+typesetting is going on. The somewhat tedious subroutine that does this
+is called |read_font_info|. It has four parameters: the user font
+identifier~|u|, the file name and area strings |nom| and |aire|, and the
+``at'' size~|s|. If |s|~is negative, it's the negative of a scale factor
+to be applied to the design size; |s=-1000| is the normal case.
+Otherwise |s| will be substituted for the design size; in this
+case, |s| must be positive and less than $2048\rm\,pt$
+(i.e., it must be less than $2^{27}$ when considered as an integer).
+
+The subroutine opens and closes a global file variable called |tfm_file|.
+It returns the value of the internal font number that was just loaded.
+If an error is detected, an error message is issued and no font
+information is stored; |null_font| is returned in this case.
+
+@d bad_tfm=11 {label for |read_font_info|}
+@d abort==goto bad_tfm {do this when the \.{TFM} data is wrong}
+
+*/
+
+/*
+The |tag| field in a |char_info_word| has four values that explain how to
+interpret the |remainder| field.
+
+\yskip\hangg|tag=0| (|no_tag|) means that |remainder| is unused.\par
+\hangg|tag=1| (|lig_tag|) means that this character has a ligature/kerning
+program starting at position |remainder| in the |lig_kern| array.\par
+\hangg|tag=2| (|list_tag|) means that this character is part of a chain of
+characters of ascending sizes, and not the largest in the chain. The
+|remainder| field gives the character code of the next larger character.\par
+\hangg|tag=3| (|ext_tag|) means that this character code represents an
+extensible character, i.e., a character that is built up of smaller pieces
+so that it can be made arbitrarily large. The pieces are specified in
+|@!exten[remainder]|.\par
+\yskip\noindent
+Characters with |tag=2| and |tag=3| are treated as characters with |tag=0|
+unless they are used in special circumstances in math formulas. For example,
+the \.{\\sum} operation looks for a |list_tag|, and the \.{\\left}
+operation looks for both |list_tag| and |ext_tag|.
+*/
+
+/* The |lig_kern| array contains instructions in a simple programming language
+that explains what to do for special letter pairs. Each word in this array,
+in a \.{TFM} file, is a |@!lig_kern_command| of four bytes.
+
+\yskip\hang first byte: |skip_byte|, indicates that this is the final program
+ step if the byte is 128 or more, otherwise the next step is obtained by
+ skipping this number of intervening steps.\par
+\hang second byte: |next_char|, ``if |next_char| follows the current character,
+ then perform the operation and stop, otherwise continue.''\par
+\hang third byte: |op_byte|, indicates a ligature step if less than~128,
+ a kern step otherwise.\par
+\hang fourth byte: |remainder|.\par
+\yskip\noindent
+In an \.{OFM} file, eight bytes are used, two bytes for each field.
+
+In a kern step, an
+additional space equal to |kern[256*(op_byte-128)+remainder]| is inserted
+between the current character and |next_char|. This amount is
+often negative, so that the characters are brought closer together
+by kerning; but it might be positive.
+
+There are eight kinds of ligature steps, having |op_byte| codes $4a+2b+c$ where
+$0\le a\le b+c$ and $0\le b,c\le1$. The character whose code is
+|remainder| is inserted between the current character and |next_char|;
+then the current character is deleted if $b=0$, and |next_char| is
+deleted if $c=0$; then we pass over $a$~characters to reach the next
+current character (which may have a ligature/kerning program of its own).
+
+If the very first instruction of the |lig_kern| array has |skip_byte=255|,
+the |next_char| byte is the so-called right boundary character of this font;
+the value of |next_char| need not lie between |bc| and~|ec|.
+If the very last instruction of the |lig_kern| array has |skip_byte=255|,
+there is a special ligature/kerning program for a left boundary character,
+beginning at location |256*op_byte+remainder|.
+The interpretation is that \TeX\ puts implicit boundary characters
+before and after each consecutive string of characters from the same font.
+These implicit characters do not appear in the output, but they can affect
+ligatures and kerning.
+
+If the very first instruction of a character's |lig_kern| program has
+|skip_byte>128|, the program actually begins in location
+|256*op_byte+remainder|. This feature allows access to large |lig_kern|
+arrays, because the first instruction must otherwise
+appear in a location |<=255| in a \.{TFM} file, |<=65535| in an \.{OFM} file.
+
+Any instruction with |skip_byte>128| in the |lig_kern| array must satisfy
+the condition
+$$\hbox{|256*op_byte+remainder<nl|.}$$
+If such an instruction is encountered during
+normal program execution, it denotes an unconditional halt; no ligature
+or kerning command is performed.
+*/
+
+/*
+ Extensible characters are specified by an |@!extensible_recipe|, which
+consists of four bytes in a \.{TFM} file,
+called |@!top|, |@!mid|, |@!bot|, and |@!rep| (in this order).
+In an \.{OFM} file, each field takes two bytes, for eight in total.
+These bytes are the character codes of individual pieces used to
+build up a large symbol. If |top|, |mid|, or |bot| are zero, they are not
+present in the built-up result. For example, an extensible vertical line is
+like an extensible bracket, except that the top and bottom pieces are missing.
+
+Let $T$, $M$, $B$, and $R$ denote the respective pieces, or an empty box
+if the piece isn't present. Then the extensible characters have the form
+$TR^kMR^kB$ from top to bottom, for some |k>=0|, unless $M$ is absent;
+in the latter case we can have $TR^kB$ for both even and odd values of~|k|.
+The width of the extensible character is the width of $R$; and the
+height-plus-depth is the sum of the individual height-plus-depths of the
+components used, since the pieces are butted together in a vertical list.
+*/
+
+/*
+The final portion of a \.{TFM} file is the |param| array, which is another
+sequence of |fix_word| values.
+
+\yskip\hang|param[1]=slant| is the amount of italic slant, which is used
+to help position accents. For example, |slant=.25| means that when you go
+up one unit, you also go .25 units to the right. The |slant| is a pure
+number; it's the only |fix_word| other than the design size itself that is
+not scaled by the design size.
+
+\hang|param[2]=space| is the normal spacing between words in text.
+Note that character |" "| in the font need not have anything to do with
+blank spaces.
+
+\hang|param[3]=space_stretch| is the amount of glue stretching between words.
+
+\hang|param[4]=space_shrink| is the amount of glue shrinking between words.
+
+\hang|param[5]=x_height| is the size of one ex in the font; it is also
+the height of letters for which accents don't have to be raised or lowered.
+
+\hang|param[6]=quad| is the size of one em in the font.
+
+\hang|param[7]=extra_space| is the amount added to |param[2]| at the
+ends of sentences.
+
+\yskip\noindent
+If fewer than seven parameters are present, \TeX\ sets the missing parameters
+to zero. Fonts used for math symbols are required to have
+additional parameter information, which is explained later.
+*/
+
+/*
+ There are programs called \.{TFtoPL} and \.{PLtoTF} that convert
+ between the \.{TFM} format and a symbolic property-list format
+ that can be easily edited. These programs contain extensive
+ diagnostic information, so \TeX\ does not have to bother giving
+ precise details about why it rejects a particular \.{TFM} file.
+
+*/
+
+#define tfm_abort { font_tables[f]->_font_name = NULL; \
+ font_tables[f]->_font_area = NULL; \
+ xfree(tfm_buffer); xfree(kerns); \
+ xfree(widths); xfree(heights); xfree(depths); \
+ xfree(italics); xfree(extens); xfree(lig_kerns); \
+ xfree(xligs); xfree(xkerns); \
+ return 0; }
+
+#define tfm_success { xfree(tfm_buffer); xfree(kerns); \
+ xfree(widths); xfree(heights); xfree(depths); \
+ xfree(italics); xfree(extens); xfree(lig_kerns); \
+ xfree(xligs); xfree(xkerns); return 1; }
+
+
+int
+open_tfm_file(char *nom, char *aire, unsigned char **tfm_buf, integer *tfm_siz) {
+ boolean res; /* was the callback successful? */
+ boolean opened; /* was |tfm_file| successfully opened?*/
+ integer callback_id;
+ FILE *tfm_file;
+ /* packfilename(nom,aire,getnullstr()); */
+ if(nameoffile != NULL)
+ xfree(nameoffile);
+ nameoffile = malloc(strlen(nom)+2);
+ strcpy(stringcast(nameoffile+1),nom);
+ namelength = strlen(nom);
+ callback_id=callback_defined(read_font_file_callback);
+ if (callback_id>0) {
+ res = run_callback(callback_id,"S->bSd",stringcast(nameoffile+1),
+ &opened, tfm_buf, tfm_siz);
+ if (res && opened && (*tfm_siz>0)) {
+ return 1;
+ }
+ if (!opened)
+ return -1;
+ } else {
+ if (ofm_open_in(tfm_file)) {
+ res = read_tfm_file(tfm_file,tfm_buf,tfm_siz);
+ b_close(tfm_file);
+ if (res) {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ Note: A malformed \.{TFM} file might be shorter than it claims to be;
+ thus |eof(tfm_file)| might be true when |read_font_info| refers to
+ |tfm_file^| or when it says |get(tfm_file)|. If such circumstances
+ cause system error messages, you will have to defeat them somehow,
+ for example by defining |fget| to be `\ignorespaces|begin get(tfm_file);|
+ |if eof(tfm_file) then abort; end|\unskip'.
+ @^system dependencies@>
+*/
+
+#define fget tfm_byte++
+#define fbyte tfm_buffer[tfm_byte]
+
+#define read_sixteen(a) \
+ { a=tfm_buffer[tfm_byte++]; \
+ if (a>127) { tfm_abort; } \
+ a=(a*256)+tfm_buffer[tfm_byte]; }
+
+#define read_sixteen_unsigned(a) \
+ { a=tfm_buffer[tfm_byte++]; \
+ a=(a*256)+tfm_buffer[tfm_byte]; }
+
+#define read_thirtytwo(a) \
+ { a=tfm_buffer[++tfm_byte]; \
+ if (a>127) { tfm_abort; } \
+ a=(a*256)+tfm_buffer[++tfm_byte]; \
+ a=(a*256)+tfm_buffer[++tfm_byte]; \
+ a=(a*256)+tfm_buffer[++tfm_byte]; }
+
+#define store_four_bytes(z) \
+ { a=tfm_buffer[++tfm_byte]; \
+ a=(a*256)+tfm_buffer[++tfm_byte]; \
+ a=(a*256)+tfm_buffer[++tfm_byte]; \
+ a=(a*256)+tfm_buffer[++tfm_byte]; \
+ z = a; }
+
+#define store_char_info(z) \
+ { if (font_level!=-1) { \
+ fget; read_sixteen_unsigned(a); \
+ ci._width_index=a; \
+ fget; read_sixteen_unsigned(b); \
+ ci._height_index=b>>8; \
+ ci._depth_index=b%256; \
+ fget; read_sixteen_unsigned(c); \
+ ci._italic_index=c>>8; \
+ ci._tag=c%4; \
+ fget; read_sixteen_unsigned(d); \
+ ci._remainder=d; \
+ } else { \
+ a=tfm_buffer[++tfm_byte]; \
+ ci._width_index=a; \
+ b=tfm_buffer[++tfm_byte]; \
+ ci._height_index=b>>4; \
+ ci._depth_index=b%16; \
+ c=tfm_buffer[++tfm_byte]; \
+ ci._italic_index=c>>2; \
+ ci._tag=c%4; \
+ d=tfm_buffer[++tfm_byte]; \
+ ci._remainder=d; \
+ } }
+
+#define read_four_quarters(q) \
+ { if (font_level!=-1) { \
+ fget; read_sixteen_unsigned(a); q.b0=a; \
+ fget; read_sixteen_unsigned(b); q.b1=b; \
+ fget; read_sixteen_unsigned(c); q.b2=c; \
+ fget; read_sixteen_unsigned(d); q.b3=d; \
+ } else { \
+ a=tfm_buffer[++tfm_byte]; q.b0=a; \
+ b=tfm_buffer[++tfm_byte]; q.b1=b; \
+ c=tfm_buffer[++tfm_byte]; q.b2=c; \
+ d=tfm_buffer[++tfm_byte]; q.b3=d; \
+ } }
+
+#define check_byte_range(z) { if ((z<bc)||(z>ec)) tfm_abort ; }
+
+
+/* A |fix_word| whose four bytes are $(a,b,c,d)$ from left to right represents
+ the number
+ $$x=\left\{\vcenter{\halign{$#$,\hfil\qquad&if $#$\hfil\cr
+ b\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=0;\cr
+ -16+b\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=255.\cr}}\right.$$
+ (No other choices of |a| are allowed, since the magnitude of a number in
+ design-size units must be less than 16.) We want to multiply this
+ quantity by the integer~|z|, which is known to be less than $2^{27}$.
+ If $|z|<2^{23}$, the individual multiplications $b\cdot z$,
+ $c\cdot z$, $d\cdot z$ cannot overflow; otherwise we will divide |z| by 2,
+ 4, 8, or 16, to obtain a multiplier less than $2^{23}$, and we can
+ compensate for this later. If |z| has thereby been replaced by
+ $|z|^\prime=|z|/2^e$, let $\beta=2^{4-e}$; we shall compute
+ $$\lfloor(b+c\cdot2^{-8}+d\cdot2^{-16})\,z^\prime/\beta\rfloor$$
+ if $a=0$, or the same quantity minus $\alpha=2^{4+e}z^\prime$ if $a=255$.
+ This calculation must be done exactly, in order to guarantee portability
+ of \TeX\ between computers.
+*/
+
+#define store_scaled(zz) \
+ { fget; a=fbyte; fget; b=fbyte; \
+ fget; c=fbyte; fget; d=fbyte; \
+ sw=(((((d*z)>>8)+(c*z))>>8)+(b*z)) / beta; \
+ if (a==0) { zz=sw; } else if (a==255) { zz=sw-alpha; } else tfm_abort; \
+ }
+
+#define check_existence(z) \
+ { check_byte_range(z); \
+ if (!char_exists(f,z)) tfm_abort; \
+ }
+
+typedef struct tfmcharacterinfo {
+ integer _kern_index;
+ integer _lig_index;
+ integer _width_index;
+ integer _height_index;
+ integer _depth_index;
+ integer _italic_index;
+ integer _remainder;
+ unsigned char _tag ;
+} tfmcharacterinfo;
+
+extern charinfo *copy_charinfo(charinfo *ci);
+
+int
+read_tfm_info(internalfontnumber f, char *cnom, char *caire, scaled s) {
+ integer k; /* index into |font_info| */
+ halfword lf,lh,bc,ec,nw,nh,nd,ni,nl,nk,ne,np,slh; /* sizes of subfiles */
+ scaled *widths, *heights, *depths, *italics, *kerns;
+ halfword font_dir;
+ integer a,b,c,d; /* byte variables */
+ integer i; /* counter */
+ integer font_level,header_length;
+ integer nco,ncw,npc,nlw,neew;
+ tfmcharacterinfo ci;
+ charinfo *co;
+ four_quarters qw;
+ four_quarters *lig_kerns, *extens;
+ scaled sw; /* accumulators */
+ integer bch_label; /* left boundary start location, or infinity */
+ int bchar; /* :0..too_big_char; */ /* right boundary character, or |too_big_char| */
+ integer first_two;
+ scaled z; /* the design size or the ``at'' size */
+ integer alpha;
+ char beta; /* :1..16*/
+ integer *xligs, *xkerns; /* aux. for ligkern processing */
+ liginfo *cligs;
+ kerninfo *ckerns;
+ int fligs, fkerns;
+ char *tmpnam;
+ integer tfm_byte = 0; /* index into |tfm_buffer| */
+ integer saved_tfm_byte = 0; /* saved index into |tfm_buffer| */
+ unsigned char *tfm_buffer = NULL; /* byte buffer for tfm files */
+ integer tfm_size = 0; /* total size of the tfm file */
+
+ widths=NULL;
+ heights=NULL;
+ depths = NULL;
+ italics = NULL;
+ kerns = NULL;
+ lig_kerns = NULL;
+ extens = NULL;
+ xkerns = NULL;
+ ckerns = NULL;
+ xligs = NULL;
+ cligs = NULL;
+
+ font_dir = 0;
+
+ memset(&ci,0,sizeof(tfmcharacterinfo));
+
+ if(open_tfm_file(cnom,caire,&tfm_buffer,&tfm_size)!=1)
+ tfm_abort;
+
+ /* cnom can be an absolute filename, xbasename() fixes that. */
+
+ tmpnam=strdup(xbasename(cnom));
+ if (strcmp(tmpnam+strlen(tmpnam)-4,".tfm")==0) {
+ *(tmpnam+strlen(tmpnam)-4) =0;
+ }
+ set_font_name(f,tmpnam);
+ set_font_area(f,xstrdup(caire)); /* perhaps it leaks, but it doesnt crash */
+
+ /* @<Read the {\.{TFM}} size fields@>; */
+ nco=0; ncw=0; npc=0;
+ read_sixteen(first_two);
+ if (first_two!=0) {
+ font_level=-1;
+ lf=first_two;
+ fget; read_sixteen(lh);
+ fget; read_sixteen(bc);
+ fget; read_sixteen(ec);
+ if ((bc>ec+1)||(ec>255)) tfm_abort;
+ if (bc>255) { /* |bc=256| and |ec=255| */
+ bc=1; ec=0;
+ };
+ fget; read_sixteen(nw);
+ fget; read_sixteen(nh);
+ fget; read_sixteen(nd);
+ fget; read_sixteen(ni);
+ fget; read_sixteen(nl);
+ fget; read_sixteen(nk);
+ fget; read_sixteen(ne);
+ fget; read_sixteen(np);
+ header_length=6;
+ ncw=(ec-bc+1);
+ nlw=nl;
+ neew=ne;
+ } else {
+ fget; read_sixteen(font_level);
+ if (font_level!=0) tfm_abort;
+ read_thirtytwo(lf);
+ read_thirtytwo(lh);
+ read_thirtytwo(bc);
+ read_thirtytwo(ec);
+ if ((bc>ec+1)||(ec>65535)) tfm_abort;
+ if (bc>65535) { /* |bc=65536| and |ec=65535| */
+ bc=1; ec=0;
+ };
+ read_thirtytwo(nw);
+ read_thirtytwo(nh);
+ read_thirtytwo(nd);
+ read_thirtytwo(ni);
+ read_thirtytwo(nl);
+ read_thirtytwo(nk);
+ read_thirtytwo(ne);
+ read_thirtytwo(np);
+ read_thirtytwo(font_dir); /* junk */
+ nlw=2*nl;
+ neew=2*ne;
+ header_length=14;
+ ncw=2*(ec-bc+1);
+ };
+ if (lf!=(header_length+lh+ncw+nw+nh+nd+ni+nlw+nk+neew+np)) tfm_abort;
+
+ /* @<Use size fields to allocate font information@>; */
+
+ set_font_natural_dir(f,font_dir);
+ set_font_bc(f,bc);
+ set_font_ec(f,ec);
+
+ /* read the arrays first */
+ widths = xmalloc(nw*sizeof(scaled));
+ heights = xmalloc(nh*sizeof(scaled));
+ depths = xmalloc(nd*sizeof(scaled));
+ italics = xmalloc(ni*sizeof(scaled));
+ extens = xmalloc(ne*sizeof(four_quarters));
+ lig_kerns = xmalloc(nl*sizeof(four_quarters));
+ kerns = xmalloc(nk*sizeof(scaled));
+
+ /* @<Read the {\.{TFM}} header@>; */
+
+ /* Only the first two words of the header are needed by \TeX82. */
+ slh = lh;
+ if (lh<2)
+ tfm_abort;
+ store_four_bytes(font_checksum(f));
+ fget; read_sixteen(z); /* this rejects a negative design size */
+ fget; z=z*256+fbyte; fget; z=(z*16)+(fbyte>>4);
+ if (z<unity) tfm_abort;
+ while (lh>2) {
+ fget;fget;fget;fget;
+ lh--; /* ignore the rest of the header */
+ };
+
+ /* read the arrays before the character info */
+
+ set_font_dsize(f,z);
+ if (s!=-1000) {
+ z = (s>=0 ? s : xn_over_d(z,-s,1000));
+ }
+ set_font_size(f,z);
+
+ if (np>7)
+ set_font_params(f,np);
+
+ saved_tfm_byte = tfm_byte;
+ tfm_byte = (header_length+slh+ncw)*4 - 1;
+
+ /* @<Replace |z| by $|z|^\prime$ and compute $\alpha,\beta$@>; */
+
+ alpha=16;
+ while (z>=040000000) {
+ z=z>>1; alpha=alpha+alpha;
+ };
+ beta=256/alpha; alpha=alpha*z;
+
+ /* @<Read box dimensions@>; */
+
+ for (k=0;k<nw;k++) {
+ store_scaled(sw); widths[k] = sw;
+ }
+ if (widths[0]!=0) /* \\{width}[0] must be zero */
+ tfm_abort;
+ for (k=0;k<nh;k++) {
+ store_scaled(sw); heights[k] = sw;
+ }
+ if (heights[0]!=0)
+ tfm_abort; /* \\{height}[0] must be zero */
+ for (k=0;k<nd;k++) {
+ store_scaled(sw); depths[k] = sw;
+ }
+ if (depths[0]!=0)
+ tfm_abort; /* \\{depth}[0] must be zero */
+ for (k=0;k<ni;k++) {
+ store_scaled(sw); italics[k] = sw;
+ }
+ if (italics[0]!=0)
+ tfm_abort; /* \\{italic}[0] must be zero */
+
+
+ /* @<Read ligature/kern program@>; */
+
+ bch_label=nl; /* infinity*/
+ bchar=65536;
+ if (nl>0) {
+ for (k=0;k<nl;k++) {
+ read_four_quarters(qw);
+ lig_kerns[k] = qw;
+ if (a>128) {
+ if (256*c+d>=nl) tfm_abort;
+ if (a==255 && k==0) bchar=b;
+ } else {
+ /* if (b!=bchar) check_existence(b); */
+ if (c<128) {
+ /* check_existence(d); */ /* check ligature */
+ } else if (256*(c-128)+d>=nk) {
+ tfm_abort; /* check kern */
+ }
+ if ((a<128) && (k-0+a+1>=nl)) tfm_abort;
+ };
+ };
+ if (a==255) bch_label=256*c+d;
+ };
+
+ /* the actual kerns */
+ for (k=0;k<nk;k++) {
+ store_scaled(sw); kerns[k] = sw;
+ }
+
+ /* @<Read extensible character recipes@>; */
+ for (k=0;k<ne;k++) {
+ read_four_quarters(qw); extens[k] = qw;
+ }
+
+ /* @<Read font parameters@>; */
+
+ if (np>7) {
+ set_font_params(f,np);
+ }
+ for (k=1;k<=np;k++) {
+ if (k==1) { /* the |slant| parameter is a pure number */
+ fget; sw=fbyte;
+ if (sw>127) sw=sw-256;
+ fget; sw=sw*256+fbyte;
+ fget; sw=sw*256+fbyte;
+ fget; sw=(sw*16)+(fbyte>>4);
+ set_font_param(f,k,sw);
+ } else {
+ store_scaled(font_param(f,k));
+ }
+ }
+
+ /*
+ We check to see that the \.{TFM} file doesn't end prematurely; but
+ no error message is given for files having more than |lf| words.
+ */
+
+ if (tfm_byte<tfm_size-1) tfm_abort;
+
+ tfm_byte = saved_tfm_byte ;
+
+ /* fix up the left boundary character */
+ fligs = 0;
+ fkerns = 0;
+ if (bch_label != nl ) {
+ k = bch_label;
+ /*
+ if (skip_byte(k) > stop_flag)
+ k = lig_kern_restart(k);
+ */
+ while (1) {
+ if (skip_byte(k) <= stop_flag) {
+ if(op_byte(k) >= kern_flag) { /* kern */
+ fkerns++;
+ } else { /* lig */
+ fligs++;
+ }
+ }
+ if (skip_byte(k) == 0) {
+ k++;
+ } else {
+ if (skip_byte(k) >= stop_flag)
+ break;
+ k += skip_byte(k) + 1;
+ }
+ }
+ }
+ if (fkerns >0 || fligs > 0) {
+ if (fligs>0) cligs = xcalloc((fligs+1),sizeof(liginfo));
+ if (fkerns>0) ckerns = xcalloc((fkerns+1),sizeof(kerninfo));
+ fligs = 0;
+ fkerns = 0;
+ k = bch_label;
+ /*
+ if (skip_byte(k) > stop_flag)
+ k = lig_kern_restart(k);
+ */
+ while (1) {
+ if (skip_byte(k) <= stop_flag) {
+ if(op_byte(k) >= kern_flag) { /* kern */
+ set_kern_item(ckerns[fkerns],next_char(k),kerns[256*(op_byte(k)-128)+rem_byte(k)]);
+ fkerns++;
+ } else { /* lig */
+ set_ligature_item(cligs[fligs],(op_byte(k)*2+1),next_char(k),rem_byte(k));
+ fligs++;
+ }
+ }
+ if (skip_byte(k) == 0) {
+ k++;
+ } else {
+ if (skip_byte(k) >= stop_flag)
+ break;
+ k += skip_byte(k) + 1;
+ }
+ }
+ if (fkerns>0 || fligs>0){
+ co = get_charinfo(f,left_boundarychar);
+ if (fkerns>0) {
+ set_kern_item(ckerns[fkerns],end_kern,0);
+ fkerns++;
+ set_charinfo_kerns(co,ckerns);
+ }
+ if (fligs>0){
+ set_ligature_item(cligs[fligs],0,end_ligature,0);
+ fligs++;
+ set_charinfo_ligatures(co,cligs);
+ }
+ set_charinfo_remainder(co,0);
+ }
+ }
+
+ /* @<Read character data@>; */
+ for (k=bc;k<=ec;k++) {
+ store_char_info(k);
+ if (ci._width_index==0)
+ continue;
+ if (ci._width_index>=nw||ci._height_index>=nh||
+ ci._depth_index>=nd||ci._italic_index>=ni) tfm_abort;
+ d = ci._remainder;
+ switch (ci._tag) {
+ case lig_tag: if (d>=nl) tfm_abort; break;
+ case ext_tag: if (d>=ne) tfm_abort; break;
+ case list_tag:
+ /* We want to make sure that there is no cycle of characters linked together
+ by |list_tag| entries, since such a cycle would get \TeX\ into an endless
+ loop. If such a cycle exists, the routine here detects it when processing
+ the largest character code in the cycle.
+ */
+ check_byte_range(d);
+ while (d<k) { /* current_character == k */
+ if (char_tag(f,d)!=list_tag)
+ goto NOT_FOUND; /* not a cycle */
+ d=char_remainder(f,d); /* next character on the list */
+ };
+ if (d==k) tfm_abort; /* yes, there's a cycle */
+ NOT_FOUND:
+ break;
+ }
+ /* put it in the actual font */
+ co = get_charinfo(f,k);
+ set_charinfo_index (co,k);
+ set_charinfo_tag (co,ci._tag);
+ if (ci._tag == ext_tag) {
+ set_charinfo_extensible(co,
+ extens[ci._remainder].b0, /* top */
+ extens[ci._remainder].b2, /* bot */
+ extens[ci._remainder].b1, /* mid */
+ extens[ci._remainder].b3); /* rep */
+ set_charinfo_remainder (co,0);
+ } else {
+ set_charinfo_remainder (co,ci._remainder);
+ }
+ set_charinfo_width (co,widths[ci._width_index]);
+ set_charinfo_height (co,heights[ci._height_index]);
+ set_charinfo_depth (co,depths[ci._depth_index]);
+ set_charinfo_italic (co,italics[ci._italic_index]);
+ };
+
+ /* first pass: count ligs and kerns */
+
+ xligs = xcalloc((ec+1),sizeof(integer));
+ xkerns = xcalloc((ec+1),sizeof(integer));
+
+ for (i=bc;i<=ec;i++) {
+ if (char_tag(f,i) == lig_tag) {
+ k = lig_kern_start(f,i);
+ if (skip_byte(k) > stop_flag)
+ k = lig_kern_restart(k);
+ /* now k is the start index */
+ while (1) {
+ if (skip_byte(k) <= stop_flag) {
+ if(op_byte(k) >= kern_flag) { /* kern */
+ xkerns[i]++;
+ if (next_char(k) == bchar)
+ xkerns[i]++;
+ } else { /* lig */
+ xligs[i]++;
+ if (next_char(k) == bchar)
+ xligs[i]++;
+ }
+ }
+ if (skip_byte(k) == 0) {
+ k++;
+ } else {
+ if (skip_byte(k) >= stop_flag)
+ break;
+ k += skip_byte(k) + 1;
+ }
+ }
+ }
+ }
+
+ cligs = NULL;
+ ckerns = NULL;
+
+ for (i=bc;i<=ec;i++) {
+ fligs = 0;
+ fkerns = 0;
+ if (char_tag(f,i) == lig_tag) {
+ k = lig_kern_start(f,i);
+ if (skip_byte(k) > stop_flag)
+ k = lig_kern_restart(k);
+ /* now k is the start index */
+ if (xligs[i]>0) cligs = xcalloc((xligs[i]+1),sizeof(liginfo));
+ if (xkerns[i]>0) ckerns = xcalloc((xkerns[i]+1),sizeof(kerninfo));
+ while (1) {
+ if (skip_byte(k) <= stop_flag) {
+ if(op_byte(k) >= kern_flag) { /* kern */
+ if (next_char(k) == bchar) {
+ set_kern_item(ckerns[fkerns],right_boundarychar,kerns[256*(op_byte(k)-128)+rem_byte(k)]);
+ fkerns++;
+ }
+ set_kern_item(ckerns[fkerns],next_char(k),kerns[256*(op_byte(k)-128)+rem_byte(k)]);
+ fkerns++;
+ } else { /* lig */
+ if (next_char(k) == bchar) {
+ set_ligature_item(cligs[fligs],(op_byte(k)*2+1),right_boundarychar,rem_byte(k));
+ fligs++;
+ }
+ set_ligature_item(cligs[fligs],(op_byte(k)*2+1),next_char(k),rem_byte(k));
+ fligs++;
+ }
+ }
+ if (skip_byte(k) == 0) {
+ k++;
+ } else {
+ if (skip_byte(k) >= stop_flag)
+ break;
+ k += skip_byte(k) + 1;
+ }
+ }
+ if (fkerns>0 || fligs>0){
+ co = get_charinfo(f,i);
+ if (fkerns>0) {
+ set_kern_item(ckerns[fkerns],end_kern,0);
+ fkerns++;
+ set_charinfo_kerns(co,ckerns);
+ }
+ if (fligs>0){
+ set_ligature_item(cligs[fligs],0,end_ligature,0);
+ fligs++;
+ set_charinfo_ligatures(co,cligs);
+ }
+ set_charinfo_remainder(co,0);
+ }
+ }
+ }
+
+
+ /* @<Make final adjustments and |goto done|@> */
+
+ /* Now to wrap it up, we have checked all the necessary things about the \.{TFM}
+ file, and all we need to do is put the finishing touches on the data for
+ the new font.
+ */
+
+ if (bchar!= 65536) {
+ co = copy_charinfo(char_info(f,bchar));
+ set_right_boundary(f,co);
+ }
+
+ tfm_success;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/font/tounicode.c b/Build/source/texk/web2c/luatexdir/font/tounicode.c
new file mode 100644
index 00000000000..ff86a8512e2
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/tounicode.c
@@ -0,0 +1,604 @@
+/*
+Copyright (c) 2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "ptexlib.h"
+
+#define isXdigit(c) (isdigit(c) || ('A' <= (c) && (c) <= 'F'))
+#define UNI_UNDEF -1
+#define UNI_STRING -2 /* string allocated by def_tounicode() */
+#define UNI_EXTRA_STRING -3 /* string allocated by set_glyph_unicode() */
+
+static struct avl_table *glyph_unicode_tree = NULL;
+
+static int comp_glyph_unicode_entry(const void *pa, const void *pb, void *p)
+{
+ return strcmp(((const glyph_unicode_entry *) pa)->name,
+ ((const glyph_unicode_entry *) pb)->name);
+}
+
+static glyph_unicode_entry *new_glyph_unicode_entry(void)
+{
+ glyph_unicode_entry *e;
+ e = xtalloc(1, glyph_unicode_entry);
+ e->name = NULL;
+ e->code = UNI_UNDEF;
+ e->unicode_seq = NULL;
+ return e;
+}
+
+static void destroy_glyph_unicode_entry(void *pa, void *pb)
+{
+ glyph_unicode_entry *e = (glyph_unicode_entry *) pa;
+ xfree(e->name);
+ if (e->code == UNI_STRING) {
+ assert(e->unicode_seq != NULL);
+ xfree(e->unicode_seq);
+ }
+}
+
+void glyph_unicode_free(void)
+{
+ if (glyph_unicode_tree != NULL)
+ avl_destroy(glyph_unicode_tree, destroy_glyph_unicode_entry);
+}
+
+void def_tounicode(strnumber glyph, strnumber unistr)
+{
+ char buf[SMALL_BUF_SIZE], *p;
+ char buf2[SMALL_BUF_SIZE], *q;
+ int valid_unistr; /* 0: invalid; 1: unicode value; 2: string */
+ int i, l;
+ glyph_unicode_entry *gu, t;
+ void **aa;
+
+ p = makecstring(glyph);
+ assert(strlen(p) < SMALL_BUF_SIZE);
+ strcpy(buf, p); /* copy the result to buf before next call of makecstring() */
+ p = makecstring(unistr);
+ while (*p == ' ')
+ p++; /* ignore leading spaces */
+ l = strlen(p);
+ while (l > 0 && p[l - 1] == ' ')
+ l--; /* ignore traling spaces */
+ valid_unistr = 1; /* a unicode value is the most common case */
+ for (i = 0; i < l; i++) {
+ if (p[i] == ' ')
+ valid_unistr = 2; /* if a space occurs we treat this entry as a string */
+ else if (!isXdigit(p[i])) {
+ valid_unistr = 0;
+ break;
+ }
+ }
+ if (l == 0 || valid_unistr == 0 || strlen(buf) == 0
+ || strcmp(buf, notdef) == 0) {
+ pdftex_warn("ToUnicode: invalid parameter(s): `%s' => `%s'", buf, p);
+ return;
+ }
+ if (glyph_unicode_tree == NULL) {
+ glyph_unicode_tree =
+ avl_create(comp_glyph_unicode_entry, NULL, &avl_xallocator);
+ assert(glyph_unicode_tree != NULL);
+ }
+ t.name = buf;
+ /* allow overriding existing entries */
+ if ((gu = (glyph_unicode_entry *) avl_find(glyph_unicode_tree, &t)) != NULL) {
+ if (gu->code == UNI_STRING) {
+ assert(gu->unicode_seq != NULL);
+ xfree(gu->unicode_seq);
+ }
+ } else { /* make new entry */
+ gu = new_glyph_unicode_entry();
+ gu->name = xstrdup(buf);
+ }
+ if (valid_unistr == 2) { /* a string with space(s) */
+ /* copy p to buf2, ignoring spaces */
+ for (q = buf2; *p != 0; p++)
+ if (*p != ' ')
+ *q++ = *p;
+ *q = 0;
+ gu->code = UNI_STRING;
+ gu->unicode_seq = xstrdup(buf2);
+ } else {
+ i = sscanf(p, "%lX", &(gu->code));
+ assert(i == 1);
+ }
+ aa = avl_probe(glyph_unicode_tree, gu);
+ assert(aa != NULL);
+}
+
+
+static long check_unicode_value(char *s, boolean multiple_value)
+{
+ int l = strlen(s);
+ int i;
+ long code;
+
+ if (l == 0)
+ return UNI_UNDEF;
+ if (multiple_value && l % 4 != 0)
+ return UNI_UNDEF;
+ if (!multiple_value && !(4 <= l && l <= 6))
+ return UNI_UNDEF;
+
+ for (i = 0; i < l; i++) {
+ if (!isXdigit(s[i]))
+ return UNI_UNDEF;
+ if (multiple_value) {
+ if (i % 4 == 3) {
+ if (sscanf(s + i - 3, "%4lX", &code) != 1)
+ return UNI_UNDEF;
+ if (!((0x0000 <= code && code <= 0xD7FF) ||
+ (0xE000 <= code && code <= 0xFFFF)))
+ return UNI_UNDEF;
+ }
+ } else { /* single value */
+ if (i == l - 1) {
+ if (sscanf(s, "%lX", &code) != 1)
+ return UNI_UNDEF;
+ if (!((0x0000 <= code && code <= 0xD7FF) ||
+ (0xE000 <= code && code <= 0x10FFFF)))
+ return UNI_UNDEF;
+ }
+ }
+ }
+ return code;
+}
+
+static char *utf16be_str(long code)
+{
+ static char buf[SMALL_BUF_SIZE];
+ long v;
+ unsigned vh, vl;
+
+ assert(code >= 0);
+
+ if (code <= 0xFFFF)
+ sprintf(buf, "%04lX", code);
+ else {
+ v = code - 0x10000;
+ vh = v / 0x400 + 0xD800;
+ vl = v % 0x400 + 0xDC00;
+ sprintf(buf, "%04X%04X", vh, vl);
+ }
+ return buf;
+}
+
+
+/* this function set proper values to *gp based on s; in case it returns
+ * gp->code == UNI_EXTRA_STRING then the caller is responsible for freeing
+ * gp->unicode_seq too */
+static void set_glyph_unicode(char *s, glyph_unicode_entry * gp)
+{
+ char buf[SMALL_BUF_SIZE], buf2[SMALL_BUF_SIZE], *p;
+ long code;
+ boolean last_component;
+ glyph_unicode_entry tmp, *ptmp;
+
+ /* skip dummy entries */
+ if (s == NULL || s == notdef)
+ return;
+
+ /* strip everything after the first dot */
+ p = strchr(s, '.');
+ if (p != NULL) {
+ *buf = 0;
+ strncat(buf, s, p - s);
+ s = buf;
+ }
+
+ if (strlen(s) == 0)
+ return;
+
+ /* check for case of multiple components separated by '_' */
+ p = strchr(s, '_');
+ if (p != NULL) {
+ assert(strlen(s) < sizeof(buf));
+ if (s != buf) {
+ strcpy(buf, s);
+ p = strchr(buf, '_');
+ s = buf;
+ }
+ *buf2 = 0;
+ last_component = false;
+ for (;;) {
+ *p = 0;
+ tmp.code = UNI_UNDEF;
+ set_glyph_unicode(s, &tmp);
+ switch (tmp.code) {
+ case UNI_UNDEF: /* not found, do nothing */
+ break;
+ case UNI_STRING: /* s matched an entry with string value in the database */
+ assert(tmp.unicode_seq != NULL);
+ assert(strlen(buf2) + strlen(tmp.unicode_seq) < sizeof(buf2));
+ strcat(buf2, tmp.unicode_seq);
+ break;
+ case UNI_EXTRA_STRING: /* s is a multiple value of form "uniXXXX" */
+ assert(strlen(buf2) + strlen(tmp.unicode_seq) < sizeof(buf2));
+ strcat(buf2, tmp.unicode_seq);
+ xfree(tmp.unicode_seq);
+ break;
+ default: /* s matched an entry with numeric value in the
+ database, or a value derived from "uXXXX" */
+ assert(tmp.code >= 0);
+ strcat(buf2, utf16be_str(tmp.code));
+ }
+ if (last_component)
+ break;
+ s = p + 1;
+ p = strchr(s, '_');
+ if (p == NULL) {
+ p = strend(s);
+ last_component = true;
+ }
+ }
+ gp->code = UNI_EXTRA_STRING;
+ gp->unicode_seq = xstrdup(buf2);
+ return;
+ }
+
+ /* lookup for glyph name in the database */
+ tmp.name = s;
+ tmp.code = UNI_UNDEF;
+ ptmp = (glyph_unicode_entry *) avl_find(glyph_unicode_tree, &tmp);
+ if (ptmp != NULL) {
+ gp->code = ptmp->code;
+ gp->unicode_seq = ptmp->unicode_seq;
+ return;
+ }
+
+ /* check for case of "uniXXXX" (multiple 4-hex-digit values allowed) */
+ if (str_prefix(s, "uni")) {
+ p = s + strlen("uni");
+ code = check_unicode_value(p, true);
+ if (code != UNI_UNDEF) {
+ if (strlen(p) == 4) /* single value */
+ gp->code = code;
+ else { /* multiple value */
+ gp->code = UNI_EXTRA_STRING;
+ gp->unicode_seq = xstrdup(p);
+ }
+ }
+ return; /* since the last case cannot happen */
+ }
+
+ /* check for case of "uXXXX" (single value up to 6 hex digits) */
+ if (str_prefix(s, "u")) {
+ p = s + strlen("u");
+ code = check_unicode_value(p, false);
+ if (code != UNI_UNDEF) {
+ assert(code >= 0);
+ gp->code = code;
+ }
+ }
+}
+
+static void set_cid_glyph_unicode(long index, glyph_unicode_entry * gp,
+ internal_font_number f) {
+ char *s;
+ if (font_tounicode(f)) {
+ if ((s = get_charinfo_tounicode(char_info(f,index)))!=NULL) {
+ gp->code = UNI_EXTRA_STRING;
+ gp->unicode_seq = xstrdup(s);
+ }
+ } else {
+ gp->code = index; /* fallback */
+ }
+}
+
+
+integer write_tounicode(char **glyph_names, char *name)
+{
+ char buf[SMALL_BUF_SIZE], *p;
+ static char builtin_suffix[] = "-builtin";
+ short range_size[257];
+ glyph_unicode_entry gtab[257];
+ integer objnum;
+ int i, j;
+ int bfchar_count, bfrange_count, subrange_count;
+ assert(strlen(name) + strlen(builtin_suffix) < SMALL_BUF_SIZE);
+ if (glyph_unicode_tree == NULL) {
+ pdftex_warn("no GlyphToUnicode entry has been inserted yet!");
+ fixed_gen_tounicode = 0;
+ return 0;
+ }
+ strcpy(buf, name);
+ if ((p = strrchr(buf, '.')) != NULL && strcmp(p, ".enc") == 0)
+ *p = 0; /* strip ".enc" from encoding name */
+ else
+ strcat(buf, builtin_suffix); /* ".enc" not present, this is a builtin
+ encoding so the name is eg "cmr10-builtin" */
+ objnum = pdf_new_objnum();
+ pdf_begin_dict(objnum, 0);
+ pdf_begin_stream();
+ pdf_printf("%%!PS-Adobe-3.0 Resource-CMap\n"
+ "%%%%DocumentNeededResources: ProcSet (CIDInit)\n"
+ "%%%%IncludeResource: ProcSet (CIDInit)\n"
+ "%%%%BeginResource: CMap (TeX-%s-0)\n"
+ "%%%%Title: (TeX-%s-0 TeX %s 0)\n"
+ "%%%%Version: 1.000\n"
+ "%%%%EndComments\n"
+ "/CIDInit /ProcSet findresource begin\n"
+ "12 dict begin\n"
+ "begincmap\n"
+ "/CIDSystemInfo\n"
+ "<< /Registry (TeX)\n"
+ "/Ordering (%s)\n"
+ "/Supplement 0\n"
+ ">> def\n"
+ "/CMapName /TeX-%s-0 def\n"
+ "/CMapType 2 def\n"
+ "1 begincodespacerange\n"
+ "<00> <FF>\n" "endcodespacerange\n", buf, buf, buf, buf, buf);
+
+ /* set gtab */
+ for (i = 0; i < 256; ++i) {
+ gtab[i].code = UNI_UNDEF;
+ set_glyph_unicode(glyph_names[i], &gtab[i]);
+ }
+ gtab[256].code = UNI_UNDEF;
+
+ /* set range_size */
+ for (i = 0; i < 256;) {
+ if (gtab[i].code == UNI_STRING || gtab[i].code == UNI_EXTRA_STRING) {
+ range_size[i] = 1; /* single entry */
+ i++;
+ } else if (gtab[i].code == UNI_UNDEF) {
+ range_size[i] = 0; /* no entry */
+ i++;
+ } else { /* gtab[i].code >= 0 */
+ j = i;
+ while (i < 256 && gtab[i + 1].code >= 0 &&
+ gtab[i].code + 1 == gtab[i + 1].code)
+ i++;
+ /* at this point i is the last entry of the subrange */
+ i++; /* move i to the next entry */
+ range_size[j] = i - j;
+ }
+ }
+
+ /* calculate bfrange_count and bfchar_count */
+ bfrange_count = 0;
+ bfchar_count = 0;
+ for (i = 0; i < 256;) {
+ if (range_size[i] == 1) {
+ bfchar_count++;
+ i++;
+ } else if (range_size[i] > 1) {
+ bfrange_count++;
+ i += range_size[i];
+ } else
+ i++;
+ }
+
+ /* write out bfrange */
+ i = 0;
+ write_bfrange:
+ if (bfrange_count > 100)
+ subrange_count = 100;
+ else
+ subrange_count = bfrange_count;
+ bfrange_count -= subrange_count;
+ pdf_printf("%i beginbfrange\n", subrange_count);
+ for (j = 0; j < subrange_count; j++) {
+ while (range_size[i] <= 1 && i < 256)
+ i++;
+ assert(i < 256);
+ pdf_printf("<%02X> <%02X> <%s>\n", i, i + range_size[i] - 1,
+ utf16be_str(gtab[i].code));
+ i += range_size[i];
+ }
+ pdf_printf("endbfrange\n");
+ if (bfrange_count > 0)
+ goto write_bfrange;
+
+ /* write out bfchar */
+ i = 0;
+ write_bfchar:
+ if (bfchar_count > 100)
+ subrange_count = 100;
+ else
+ subrange_count = bfchar_count;
+ bfchar_count -= subrange_count;
+ pdf_printf("%i beginbfchar\n", subrange_count);
+ for (j = 0; j < subrange_count; j++) {
+ while (i < 256) {
+ if (range_size[i] > 1)
+ i += range_size[i];
+ else if (range_size[i] == 0)
+ i++;
+ else /* range_size[i] == 1 */
+ break;
+ }
+ assert(i < 256 && gtab[i].code != UNI_UNDEF);
+ if (gtab[i].code == UNI_STRING || gtab[i].code == UNI_EXTRA_STRING) {
+ assert(gtab[i].unicode_seq != NULL);
+ pdf_printf("<%02X> <%s>\n", i, gtab[i].unicode_seq);
+ } else
+ pdf_printf("<%02X> <%s>\n", i, utf16be_str(gtab[i].code));
+ i++;
+ }
+ pdf_printf("endbfchar\n");
+ if (bfchar_count > 0)
+ goto write_bfchar;
+
+ /* free strings allocated by set_glyph_unicode() */
+ for (i = 0; i < 256; ++i) {
+ if (gtab[i].code == UNI_EXTRA_STRING)
+ xfree(gtab[i].unicode_seq);
+ }
+
+ pdf_printf("endcmap\n"
+ "CMapName currentdict /CMap defineresource pop\n"
+ "end\n" "end\n" "%%%%EndResource\n" "%%%%EOF\n");
+ pdf_end_stream();
+ return objnum;
+}
+
+integer write_cid_tounicode(fo_entry * fo, internalfontnumber f) {
+
+ int range_size[65537];
+ glyph_unicode_entry gtab[65537];
+ integer objnum;
+ int i, j, k;
+ int bfchar_count, bfrange_count, subrange_count;
+ char *buf;
+
+ assert(fo->fd->fontname);
+ buf = xmalloc(strlen(fo->fd->fontname)+8);
+ sprintf(buf,"%s-%s",(fo->fd->subset_tag!=NULL ? fo->fd->subset_tag : "UCS"),
+ fo->fd->fontname);
+
+ objnum = pdf_new_objnum();
+ pdf_begin_dict(objnum, 0);
+ pdf_begin_stream();
+ pdf_printf("%%!PS-Adobe-3.0 Resource-CMap\n"
+ "%%%%DocumentNeededResources: ProcSet (CIDInit)\n"
+ "%%%%IncludeResource: ProcSet (CIDInit)\n"
+ "%%%%BeginResource: CMap (TeX-%s-0)\n"
+ "%%%%Title: (TeX-%s-0 TeX %s 0)\n"
+ "%%%%Version: 1.000\n"
+ "%%%%EndComments\n"
+ "/CIDInit /ProcSet findresource begin\n"
+ "12 dict begin\n"
+ "begincmap\n"
+ "/CIDSystemInfo\n"
+ "<< /Registry (TeX)\n"
+ "/Ordering (%s)\n"
+ "/Supplement 0\n"
+ ">> def\n"
+ "/CMapName /TeX-Identity-%s def\n"
+ "/CMapType 2 def\n"
+ "1 begincodespacerange\n"
+ "<0000> <FFFF>\n"
+ "endcodespacerange\n", buf, buf, buf, buf, buf);
+ xfree(buf);
+ /* set up gtab */
+ for (i = 0; i < 65537; ++i) {
+ gtab[i].code = UNI_UNDEF;
+ }
+ for (k = 1; k <= max_font_id(); k++) {
+ if (k == f || -f == pdf_font_num(k)) {
+ for (i = font_bc(k); i <= font_ec(k); i++) {
+ if (char_exists(k,i) && char_used(k,i)) {
+ j = char_index(k,i);
+ if (gtab[j].code == UNI_UNDEF) {
+ set_cid_glyph_unicode(i, &gtab[j], f);
+ }
+ }
+ }
+ }
+ }
+
+ /* set range_size */
+ for (i = 0; i < 65536;) {
+ if (gtab[i].code == UNI_STRING || gtab[i].code == UNI_EXTRA_STRING) {
+ range_size[i] = 1; /* single entry */
+ i++;
+ } else if (gtab[i].code == UNI_UNDEF) {
+ range_size[i] = 0; /* no entry */
+ i++;
+ } else { /* gtab[i].code >= 0 */
+ j = i;
+ while (i < 65536 && gtab[i + 1].code >= 0 &&
+ gtab[i].code + 1 == gtab[i + 1].code)
+ i++;
+ /* at this point i is the last entry of the subrange */
+ i++; /* move i to the next entry */
+ range_size[j] = i - j;
+ }
+ }
+
+ /* calculate bfrange_count and bfchar_count */
+ bfrange_count = 0;
+ bfchar_count = 0;
+ for (i = 0; i < 65536;) {
+ if (range_size[i] == 1) {
+ bfchar_count++;
+ i++;
+ } else if (range_size[i] > 1) {
+ bfrange_count++;
+ i += range_size[i];
+ } else
+ i++;
+ }
+
+ /* write out bfrange */
+ i = 0;
+ write_bfrange:
+ if (bfrange_count > 100)
+ subrange_count = 100;
+ else
+ subrange_count = bfrange_count;
+ bfrange_count -= subrange_count;
+ pdf_printf("%i beginbfrange\n", subrange_count);
+ for (j = 0; j < subrange_count; j++) {
+ while (range_size[i] <= 1 && i < 65536)
+ i++;
+ assert(i < 65536);
+ pdf_printf("<%04X> <%04X> <%s>\n", i, i + range_size[i] - 1,
+ utf16be_str(gtab[i].code));
+ i += range_size[i];
+ }
+ pdf_printf("endbfrange\n");
+ if (bfrange_count > 0)
+ goto write_bfrange;
+
+ /* write out bfchar */
+ i = 0;
+ write_bfchar:
+ if (bfchar_count > 100)
+ subrange_count = 100;
+ else
+ subrange_count = bfchar_count;
+ bfchar_count -= subrange_count;
+ pdf_printf("%i beginbfchar\n", subrange_count);
+ for (j = 0; j < subrange_count; j++) {
+ while (i < 65536) {
+ if (range_size[i] > 1)
+ i += range_size[i];
+ else if (range_size[i] == 0)
+ i++;
+ else /* range_size[i] == 1 */
+ break;
+ }
+ assert(i < 65536 && gtab[i].code != UNI_UNDEF);
+ if (gtab[i].code == UNI_STRING || gtab[i].code == UNI_EXTRA_STRING) {
+ assert(gtab[i].unicode_seq != NULL);
+ pdf_printf("<%04X> <%s>\n", i, gtab[i].unicode_seq);
+ } else
+ pdf_printf("<%04X> <%s>\n", i, utf16be_str(gtab[i].code));
+ i++;
+ }
+ pdf_printf("endbfchar\n");
+ if (bfchar_count > 0)
+ goto write_bfchar;
+
+ /* free strings allocated by set_glyph_unicode() */
+ for (i = 0; i < 65536; ++i) {
+ if (gtab[i].code == UNI_EXTRA_STRING)
+ xfree(gtab[i].unicode_seq);
+ }
+
+ pdf_printf("endcmap\n"
+ "CMapName currentdict /CMap defineresource pop\n"
+ "end\n" "end\n" "%%%%EndResource\n" "%%%%EOF\n");
+ pdf_end_stream();
+ return objnum;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/tt_glyf.c b/Build/source/texk/web2c/luatexdir/font/tt_glyf.c
new file mode 100644
index 00000000000..bf21e58c49a
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/tt_glyf.c
@@ -0,0 +1,658 @@
+/* $Header: /home/cvsroot/dvipdfmx/src/tt_glyf.c,v 1.2 2005/06/09 14:31:11 hirata Exp $
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+/*
+ * Subsetting glyf, updating loca, hmtx, ...
+ *
+ */
+
+#include "ptexlib.h"
+
+#include "sfnt.h"
+#include "tt_table.h"
+#include "tt_glyf.h"
+
+#define NUM_GLYPH_LIMIT 65534
+#define TABLE_DATA_ALLOC_SIZE 40960
+#define GLYPH_ARRAY_ALLOC_SIZE 256
+
+static USHORT
+find_empty_slot (struct tt_glyphs *g)
+{
+ USHORT gid;
+
+ ASSERT(g);
+
+ for (gid = 0; gid < NUM_GLYPH_LIMIT; gid++) {
+ if (!(g->used_slot[gid/8] & (1 << (7 - (gid % 8)))))
+ break;
+ }
+ if (gid == NUM_GLYPH_LIMIT)
+ TT_ERROR("No empty glyph slot available.");
+
+ return gid;
+}
+
+USHORT
+tt_find_glyph (struct tt_glyphs *g, USHORT gid)
+{
+ USHORT idx, new_gid = 0;
+
+ ASSERT(g);
+
+ for (idx = 0; idx < g->num_glyphs; idx++) {
+ if (gid == g->gd[idx].ogid) {
+ new_gid = g->gd[idx].gid;
+ break;
+ }
+ }
+
+ return new_gid;
+}
+
+USHORT
+tt_get_index (struct tt_glyphs *g, USHORT gid)
+{
+ USHORT idx;
+
+ ASSERT(g);
+
+ for (idx = 0; idx < g->num_glyphs; idx++) {
+ if (gid == g->gd[idx].gid)
+ break;
+ }
+ if (idx == g->num_glyphs)
+ idx = 0;
+
+ return idx;
+}
+
+USHORT
+tt_add_glyph (struct tt_glyphs *g, USHORT gid, USHORT new_gid)
+{
+ ASSERT(g);
+
+ if (g->used_slot[new_gid/8] & (1 << (7 - (new_gid % 8)))) {
+ WARN("Slot %u already used.", new_gid);
+ } else {
+ if (g->num_glyphs+1 >= NUM_GLYPH_LIMIT)
+ TT_ERROR("Too many glyphs.");
+
+ if (g->num_glyphs >= g->max_glyphs) {
+ g->max_glyphs += GLYPH_ARRAY_ALLOC_SIZE;
+ g->gd = RENEW(g->gd, g->max_glyphs, struct tt_glyph_desc);
+ }
+ g->gd[g->num_glyphs].gid = new_gid;
+ g->gd[g->num_glyphs].ogid = gid;
+ g->gd[g->num_glyphs].length = 0;
+ g->gd[g->num_glyphs].data = NULL;
+ g->used_slot[new_gid/8] |= (1 << (7 - (new_gid % 8)));
+ g->num_glyphs += 1;
+ }
+
+ if (new_gid > g->last_gid) {
+ g->last_gid = new_gid;
+ }
+
+ return new_gid;
+}
+
+/*
+ * Initialization
+ */
+struct tt_glyphs *
+tt_build_init (void)
+{
+ struct tt_glyphs *g;
+
+ g = NEW(1, struct tt_glyphs);
+
+ g->num_glyphs = 0;
+ g->max_glyphs = 0;
+ g->last_gid = 0;
+ g->emsize = 1;
+ g->default_advh = 0;
+ g->default_tsb = 0;
+ g->gd = NULL;
+ g->used_slot = NEW(8192, unsigned char);
+ memset(g->used_slot, 0, 8192);
+ tt_add_glyph(g, 0, 0);
+
+ return g;
+}
+
+void
+tt_build_finish (struct tt_glyphs *g)
+{
+ if (g) {
+ if (g->gd) {
+ USHORT idx;
+ for (idx = 0; idx < g->num_glyphs; idx++) {
+ if (g->gd[idx].data)
+ RELEASE(g->gd[idx].data);
+ }
+ RELEASE(g->gd);
+ }
+ if (g->used_slot)
+ RELEASE(g->used_slot);
+ RELEASE(g);
+ }
+}
+
+static int
+glyf_cmp (const void *v1, const void *v2)
+{
+ int cmp = 0;
+ struct tt_glyph_desc *sv1, *sv2;
+
+ sv1 = (struct tt_glyph_desc *) v1;
+ sv2 = (struct tt_glyph_desc *) v2;
+
+ if (sv1->gid == sv2->gid)
+ cmp = 0;
+ else if (sv1->gid < sv2->gid)
+ cmp = -1;
+ else
+ cmp = 1;
+
+ return cmp;
+}
+
+/*
+ * TrueType outline data.
+ */
+#define ARG_1_AND_2_ARE_WORDS (1 << 0)
+#define ARGS_ARE_XY_VALUES (1 << 1)
+#define ROUND_XY_TO_GRID (1 << 2)
+#define WE_HAVE_A_SCALE (1 << 3)
+#define RESERVED (1 << 4)
+#define MORE_COMPONENT (1 << 5)
+#define WE_HAVE_AN_X_AND_Y_SCALE (1 << 6)
+#define WE_HAVE_A_TWO_BY_TWO (1 << 7)
+#define WE_HAVE_INSTRUCTIONS (1 << 8)
+#define USE_MY_METRICS (1 << 9)
+
+int
+tt_build_tables (sfnt *sfont, struct tt_glyphs *g)
+{
+ char *hmtx_table_data = NULL, *loca_table_data = NULL;
+ char *glyf_table_data = NULL;
+ ULONG hmtx_table_size, loca_table_size, glyf_table_size;
+ /* some information available from other TrueType table */
+ struct tt_head_table *head = NULL;
+ struct tt_hhea_table *hhea = NULL;
+ struct tt_maxp_table *maxp = NULL;
+ struct tt_longMetrics *hmtx, *vmtx = NULL;
+ struct tt_os2__table *os2;
+ /* temp */
+ ULONG *location, offset;
+ long i;
+ USHORT *w_stat; /* Estimate most frequently appeared width */
+
+ ASSERT(g);
+
+ if (sfont->type != SFNT_TYPE_TRUETYPE &&
+ sfont->type != SFNT_TYPE_TTC)
+ TT_ERROR("Invalid font type");
+
+ if (g->num_glyphs > NUM_GLYPH_LIMIT)
+ TT_ERROR("Too many glyphs.");
+
+ /*
+ * Read head, hhea, maxp, loca:
+ *
+ * unitsPerEm --> head
+ * numHMetrics --> hhea
+ * indexToLocFormat --> head
+ * numGlyphs --> maxp
+ */
+ head = tt_read_head_table(sfont);
+ hhea = tt_read_hhea_table(sfont);
+ maxp = tt_read_maxp_table(sfont);
+
+ if (hhea->metricDataFormat != 0)
+ TT_ERROR("Unknown metricDataFormat.");
+
+ g->emsize = head->unitsPerEm;
+
+ sfnt_locate_table(sfont, "hmtx");
+ hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics);
+
+ os2 = tt_read_os2__table(sfont);
+ if (os2) {
+ g->default_advh = os2->sTypoAscender - os2->sTypoDescender;
+ g->default_tsb = g->default_advh - os2->sTypoAscender;
+ }
+
+ if (sfnt_find_table_pos(sfont, "vmtx") > 0) {
+ struct tt_vhea_table *vhea;
+ vhea = tt_read_vhea_table(sfont);
+ sfnt_locate_table(sfont, "vmtx");
+ vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics);
+ RELEASE(vhea);
+ } else {
+ vmtx = NULL;
+ }
+
+ sfnt_locate_table(sfont, "loca");
+ location = NEW(maxp->numGlyphs + 1, ULONG);
+ if (head->indexToLocFormat == 0) {
+ for (i = 0; i <= maxp->numGlyphs; i++)
+ location[i] = 2*((ULONG) sfnt_get_ushort(sfont));
+ } else if (head->indexToLocFormat == 1) {
+ for (i = 0; i <= maxp->numGlyphs; i++)
+ location[i] = sfnt_get_ulong(sfont);
+ } else {
+ TT_ERROR("Unknown IndexToLocFormat.");
+ }
+
+ w_stat = NEW(g->emsize+2, USHORT);
+ memset(w_stat, 0, sizeof(USHORT)*(g->emsize+2));
+ /*
+ * Read glyf table.
+ */
+ offset = sfnt_locate_table(sfont, "glyf");
+ /*
+ * The num_glyphs may grow when composite glyph is found.
+ * A component of glyph refered by a composite glyph is appended
+ * to used_glyphs if it is not already registered in used_glyphs.
+ * Glyph programs of composite glyphs are modified so that it
+ * correctly refer to new gid of their components.
+ */
+ for (i = 0; i < NUM_GLYPH_LIMIT; i++) {
+ USHORT gid; /* old gid */
+ ULONG loc, len;
+ BYTE *p, *endptr;
+ SHORT number_of_contours;
+
+ if (i >= g->num_glyphs) /* finished */
+ break;
+
+ gid = g->gd[i].ogid;
+ if (gid >= maxp->numGlyphs)
+ TT_ERROR("Invalid glyph index (gid %u)", gid);
+
+ loc = location[gid];
+ len = location[gid+1] - loc;
+ g->gd[i].advw = hmtx[gid].advance;
+ g->gd[i].lsb = hmtx[gid].sideBearing;
+ if (vmtx) {
+ g->gd[i].advh = vmtx[gid].advance;
+ g->gd[i].tsb = vmtx[gid].sideBearing;
+ } else {
+ g->gd[i].advh = g->default_advh;
+ g->gd[i].tsb = g->default_tsb;
+ }
+ g->gd[i].length = len;
+ g->gd[i].data = NULL;
+ if (g->gd[i].advw <= g->emsize) {
+ w_stat[g->gd[i].advw] += 1;
+ } else {
+ w_stat[g->emsize+1] += 1; /* larger than em */
+ }
+
+ if (len == 0) { /* Does not contains any data. */
+ continue;
+ } else if (len < 10) {
+ TT_ERROR("Invalid TrueType glyph data (gid %u).", gid);
+ }
+
+ g->gd[i].data = p = NEW(len, BYTE);
+ endptr = p + len;
+
+ sfnt_seek_set(sfont, offset+loc);
+ number_of_contours = sfnt_get_short(sfont);
+ p += sfnt_put_short(p, number_of_contours);
+
+ /* BoundingBox: FWord x 4 */
+ g->gd[i].llx = sfnt_get_short(sfont);
+ g->gd[i].lly = sfnt_get_short(sfont);
+ g->gd[i].urx = sfnt_get_short(sfont);
+ g->gd[i].ury = sfnt_get_short(sfont);
+ /* _FIXME_ */
+#if 1
+ if (!vmtx) /* vertOriginY == sTypeAscender */
+ g->gd[i].tsb = g->default_advh - g->default_tsb - g->gd[i].ury;
+#endif
+ p += sfnt_put_short(p, g->gd[i].llx);
+ p += sfnt_put_short(p, g->gd[i].lly);
+ p += sfnt_put_short(p, g->gd[i].urx);
+ p += sfnt_put_short(p, g->gd[i].ury);
+
+ /* Read evrything else. */
+ sfnt_read(p, len - 10, sfont);
+ /*
+ * Fix GIDs of composite glyphs.
+ */
+ if (number_of_contours < 0) {
+ USHORT flags, cgid, new_gid; /* flag, gid of a component */
+ do {
+ if (p >= endptr)
+ TT_ERROR("Invalid TrueType glyph data (gid %u): %u bytes", gid, (unsigned int)len);
+ /*
+ * Flags and gid of component glyph are both USHORT.
+ */
+ flags = ((*p) << 8)| *(p+1);
+ p += 2;
+ cgid = ((*p) << 8)| *(p+1);
+ if (cgid >= maxp->numGlyphs) {
+ TT_ERROR("Invalid gid (%u > %u) in composite glyph %u.", cgid, maxp->numGlyphs, gid);
+ }
+ new_gid = tt_find_glyph(g, cgid);
+ if (new_gid == 0) {
+ new_gid = tt_add_glyph(g, cgid, find_empty_slot(g));
+ }
+ p += sfnt_put_ushort(p, new_gid);
+ /*
+ * Just skip remaining part.
+ */
+ p += (flags & ARG_1_AND_2_ARE_WORDS) ? 4 : 2;
+ if (flags & WE_HAVE_A_SCALE) /* F2Dot14 */
+ p += 2;
+ else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) /* F2Dot14 x 2 */
+ p += 4;
+ else if (flags & WE_HAVE_A_TWO_BY_TWO) /* F2Dot14 x 4 */
+ p += 8;
+ } while (flags & MORE_COMPONENT);
+ /*
+ * TrueType instructions comes here:
+ * length_of_instruction (ushort)
+ * instruction (byte * length_of_instruction)
+ */
+ }
+ }
+ RELEASE(location);
+ RELEASE(hmtx);
+ if (vmtx)
+ RELEASE(vmtx);
+
+ {
+ int max_count = -1;
+
+ g->dw = g->gd[0].advw;
+ for (i = 0; i < g->emsize + 1; i++) {
+ if (w_stat[i] > max_count) {
+ max_count = w_stat[i];
+ g->dw = i;
+ }
+ }
+ }
+ RELEASE(w_stat);
+
+ qsort(g->gd, g->num_glyphs, sizeof(struct tt_glyph_desc), glyf_cmp);
+ {
+ USHORT prev, last_advw;
+ char *p, *q;
+ int padlen, num_hm_known;
+
+ glyf_table_size = 0UL;
+ num_hm_known = 0;
+ last_advw = g->gd[g->num_glyphs - 1].advw;
+ for (i = g->num_glyphs - 1; i >= 0; i--) {
+ padlen = (g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0;
+ glyf_table_size += g->gd[i].length + padlen;
+ if (!num_hm_known && last_advw != g->gd[i].advw) {
+ hhea->numberOfHMetrics = g->gd[i].gid + 2;
+ num_hm_known = 1;
+ }
+ }
+ /* All advance widths are same. */
+ if (!num_hm_known) {
+ hhea->numberOfHMetrics = 1;
+ }
+ hmtx_table_size = hhea->numberOfHMetrics * 2 + (g->last_gid + 1) * 2;
+
+ /*
+ * Choosing short format does not always give good result
+ * when compressed. Sometimes increases size.
+ */
+ if (glyf_table_size < 0x20000UL) {
+ head->indexToLocFormat = 0;
+ loca_table_size = (g->last_gid + 2)*2;
+ } else {
+ head->indexToLocFormat = 1;
+ loca_table_size = (g->last_gid + 2)*4;
+ }
+
+ hmtx_table_data = p = NEW(hmtx_table_size, char);
+ loca_table_data = q = NEW(loca_table_size, char);
+ glyf_table_data = NEW(glyf_table_size, char);
+
+ offset = 0UL; prev = 0;
+ for (i = 0; i < g->num_glyphs; i++) {
+ long gap, j;
+ gap = (long) g->gd[i].gid - prev - 1;
+ for (j = 1; j <= gap; j++) {
+ if (prev + j == hhea->numberOfHMetrics - 1) {
+ p += sfnt_put_ushort(p, last_advw);
+ } else if (prev + j < hhea->numberOfHMetrics) {
+ p += sfnt_put_ushort(p, 0);
+ }
+ p += sfnt_put_short (p, 0);
+ if (head->indexToLocFormat == 0) {
+ q += sfnt_put_ushort(q, (USHORT) (offset/2));
+ } else {
+ q += sfnt_put_ulong(q, offset);
+ }
+ }
+ padlen = (g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0;
+ if (g->gd[i].gid < hhea->numberOfHMetrics) {
+ p += sfnt_put_ushort(p, g->gd[i].advw);
+ }
+ p += sfnt_put_short (p, g->gd[i].lsb);
+ if (head->indexToLocFormat == 0) {
+ q += sfnt_put_ushort(q, (USHORT) (offset/2));
+ } else {
+ q += sfnt_put_ulong(q, offset);
+ }
+ memset(glyf_table_data + offset, 0, g->gd[i].length + padlen);
+ memcpy(glyf_table_data + offset, g->gd[i].data, g->gd[i].length);
+ offset += g->gd[i].length + padlen;
+ prev = g->gd[i].gid;
+ /* free data here since it consume much memory */
+ RELEASE(g->gd[i].data);
+ g->gd[i].length = 0; g->gd[i].data = NULL;
+ }
+ if (head->indexToLocFormat == 0) {
+ q += sfnt_put_ushort(q, (USHORT) (offset/2));
+ } else {
+ q += sfnt_put_ulong(q, offset);
+ }
+
+ sfnt_set_table(sfont, "hmtx", (char *) hmtx_table_data, hmtx_table_size);
+ sfnt_set_table(sfont, "loca", (char *) loca_table_data, loca_table_size);
+ sfnt_set_table(sfont, "glyf", (char *) glyf_table_data, glyf_table_size);
+ }
+
+ head->checkSumAdjustment = 0;
+ maxp->numGlyphs = g->last_gid + 1;
+
+ /* TODO */
+ sfnt_set_table(sfont, "maxp", tt_pack_maxp_table(maxp), TT_MAXP_TABLE_SIZE);
+ sfnt_set_table(sfont, "hhea", tt_pack_hhea_table(hhea), TT_HHEA_TABLE_SIZE);
+ sfnt_set_table(sfont, "head", tt_pack_head_table(head), TT_HEAD_TABLE_SIZE);
+ RELEASE(maxp);
+ RELEASE(hhea);
+ RELEASE(head);
+ if (os2)
+ RELEASE(os2);
+
+ return 0;
+}
+
+int
+tt_get_metrics (sfnt *sfont, struct tt_glyphs *g)
+{
+ struct tt_head_table *head = NULL;
+ struct tt_hhea_table *hhea = NULL;
+ struct tt_maxp_table *maxp = NULL;
+ struct tt_longMetrics *hmtx, *vmtx = NULL;
+ struct tt_os2__table *os2;
+ /* temp */
+ ULONG *location, offset;
+ long i;
+ USHORT *w_stat;
+
+ ASSERT(g);
+
+ if (sfont == NULL ||
+#ifdef XETEX
+ sfont->ft_face == NULL
+#elif defined(pdfTeX)
+ sfont->buffer == NULL
+#else
+ sfont->stream == NULL
+#endif
+ )
+ TT_ERROR("File not opened.");
+
+ if (sfont->type != SFNT_TYPE_TRUETYPE &&
+ sfont->type != SFNT_TYPE_TTC)
+ TT_ERROR("Invalid font type");
+
+ /*
+ * Read head, hhea, maxp, loca:
+ *
+ * unitsPerEm --> head
+ * numHMetrics --> hhea
+ * indexToLocFormat --> head
+ * numGlyphs --> maxp
+ */
+ head = tt_read_head_table(sfont);
+ hhea = tt_read_hhea_table(sfont);
+ maxp = tt_read_maxp_table(sfont);
+
+ if (hhea->metricDataFormat != 0)
+ TT_ERROR("Unknown metricDataFormat.");
+
+ g->emsize = head->unitsPerEm;
+
+ sfnt_locate_table(sfont, "hmtx");
+ hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics);
+
+ os2 = tt_read_os2__table(sfont);
+ g->default_advh = os2->sTypoAscender - os2->sTypoDescender;
+ g->default_tsb = g->default_advh - os2->sTypoAscender;
+
+ if (sfnt_find_table_pos(sfont, "vmtx") > 0) {
+ struct tt_vhea_table *vhea;
+ vhea = tt_read_vhea_table(sfont);
+ sfnt_locate_table(sfont, "vmtx");
+ vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics);
+ RELEASE(vhea);
+ } else {
+ vmtx = NULL;
+ }
+
+ sfnt_locate_table(sfont, "loca");
+ location = NEW(maxp->numGlyphs + 1, ULONG);
+ if (head->indexToLocFormat == 0) {
+ for (i = 0; i <= maxp->numGlyphs; i++)
+ location[i] = 2*((ULONG) sfnt_get_ushort(sfont));
+ } else if (head->indexToLocFormat == 1) {
+ for (i = 0; i <= maxp->numGlyphs; i++)
+ location[i] = sfnt_get_ulong(sfont);
+ } else {
+ TT_ERROR("Unknown IndexToLocFormat.");
+ }
+
+ w_stat = NEW(g->emsize+2, USHORT);
+ memset(w_stat, 0, sizeof(USHORT)*(g->emsize+2));
+ /*
+ * Read glyf table.
+ */
+ offset = sfnt_locate_table(sfont, "glyf");
+ for (i = 0; i < g->num_glyphs; i++) {
+ USHORT gid; /* old gid */
+ ULONG loc, len;
+ SHORT number_of_contours;
+
+ gid = g->gd[i].ogid;
+ if (gid >= maxp->numGlyphs)
+ TT_ERROR("Invalid glyph index (gid %u)", gid);
+
+ loc = location[gid];
+ len = location[gid+1] - loc;
+ g->gd[i].advw = hmtx[gid].advance;
+ g->gd[i].lsb = hmtx[gid].sideBearing;
+ if (vmtx) {
+ g->gd[i].advh = vmtx[gid].advance;
+ g->gd[i].tsb = vmtx[gid].sideBearing;
+ } else {
+ g->gd[i].advh = g->default_advh;
+ g->gd[i].tsb = g->default_tsb;
+ }
+ g->gd[i].length = len;
+ g->gd[i].data = NULL;
+
+ if (g->gd[i].advw <= g->emsize) {
+ w_stat[g->gd[i].advw] += 1;
+ } else {
+ w_stat[g->emsize+1] += 1; /* larger than em */
+ }
+
+ if (len == 0) { /* Does not contains any data. */
+ continue;
+ } else if (len < 10) {
+ TT_ERROR("Invalid TrueType glyph data (gid %u).", gid);
+ }
+
+ sfnt_seek_set(sfont, offset+loc);
+ number_of_contours = sfnt_get_short(sfont);
+
+ /* BoundingBox: FWord x 4 */
+ g->gd[i].llx = sfnt_get_short(sfont);
+ g->gd[i].lly = sfnt_get_short(sfont);
+ g->gd[i].urx = sfnt_get_short(sfont);
+ g->gd[i].ury = sfnt_get_short(sfont);
+ /* _FIXME_ */
+#if 1
+ if (!vmtx) /* vertOriginY == sTypeAscender */
+ g->gd[i].tsb = g->default_advh - g->default_tsb - g->gd[i].ury;
+#endif
+ }
+ RELEASE(location);
+ RELEASE(hmtx);
+ RELEASE(maxp);
+ RELEASE(hhea);
+ RELEASE(head);
+ RELEASE(os2);
+
+ if (vmtx)
+ RELEASE(vmtx);
+
+ {
+ int max_count = -1;
+
+ g->dw = g->gd[0].advw;
+ for (i = 0; i < g->emsize + 1; i++) {
+ if (w_stat[i] > max_count) {
+ max_count = w_stat[i];
+ g->dw = i;
+ }
+ }
+ }
+ RELEASE(w_stat);
+
+
+ return 0;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/tt_glyf.h b/Build/source/texk/web2c/luatexdir/font/tt_glyf.h
new file mode 100644
index 00000000000..cf33af6733f
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/tt_glyf.h
@@ -0,0 +1,60 @@
+/* $Header: /home/cvsroot/dvipdfmx/src/tt_glyf.h,v 1.1 2004/09/11 14:50:29 hirata Exp $
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+#ifndef _TT_GLYF_H_
+#define _TT_GLYF_H_
+
+struct tt_glyph_desc
+{
+ USHORT gid;
+ USHORT ogid; /* GID in original font */
+ USHORT advw, advh;
+ SHORT lsb, tsb;
+ SHORT llx, lly, urx, ury;
+ ULONG length;
+ BYTE *data;
+};
+
+struct tt_glyphs
+{
+ USHORT num_glyphs;
+ USHORT max_glyphs;
+ USHORT last_gid;
+ USHORT emsize;
+ USHORT dw; /* optimal value for DW */
+ USHORT default_advh; /* default value */
+ SHORT default_tsb; /* default value */
+ struct tt_glyph_desc *gd;
+ unsigned char *used_slot;
+};
+
+extern struct tt_glyphs *tt_build_init (void);
+extern void tt_build_finish (struct tt_glyphs *g);
+
+extern USHORT tt_add_glyph (struct tt_glyphs *g, USHORT gid, USHORT new_gid);
+extern USHORT tt_get_index (struct tt_glyphs *g, USHORT gid);
+extern USHORT tt_find_glyph (struct tt_glyphs *g, USHORT gid);
+
+extern int tt_build_tables (sfnt *sfont, struct tt_glyphs *g);
+extern int tt_get_metrics (sfnt *sfont, struct tt_glyphs *g);
+
+#endif /* _TT_GLYF_H_ */
diff --git a/Build/source/texk/web2c/luatexdir/font/tt_table.c b/Build/source/texk/web2c/luatexdir/font/tt_table.c
new file mode 100644
index 00000000000..4f82552d9df
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/tt_table.c
@@ -0,0 +1,483 @@
+/* $Header: /home/cvsroot/dvipdfmx/src/tt_table.c,v 1.7 2004/09/11 14:50:29 hirata Exp $
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+#include <stdio.h>
+
+#ifndef pdfTeX
+#include "system.h"
+#include "error.h"
+#include "mem.h"
+#include "mfileio.h"
+#else
+extern void pdftex_fail (const char *fmt, ...); /* utils.c */
+#endif
+
+#include "sfnt.h"
+#include "tt_table.h"
+
+/*
+ tables contains information refered by other tables
+ maxp->numGlyphs, etc --> loca, etc
+ hhea->numberOfHMetrics --> hmtx
+ head->indexToLocFormat --> loca
+ head->glyphDataFormat --> glyf
+*/
+
+char *tt_pack_head_table (struct tt_head_table *table)
+{
+ int i;
+ char *p, *data;
+
+ if (table == NULL)
+ TT_ERROR("passed NULL pointer\n");
+
+ p = data = NEW(TT_HEAD_TABLE_SIZE, char);
+ p += sfnt_put_ulong(p, table->version);
+ p += sfnt_put_ulong(p, table->fontRevision);
+ p += sfnt_put_ulong(p, table->checkSumAdjustment);
+ p += sfnt_put_ulong(p, table->magicNumber);
+ p += sfnt_put_ushort(p, table->flags);
+ p += sfnt_put_ushort(p, table->unitsPerEm);
+ for (i=0; i<8; i++) {
+ *(p++) = (table->created)[i];
+ }
+ for (i=0; i<8; i++) {
+ *(p++) = (table->modified)[i];
+ }
+ p += sfnt_put_short(p, table->xMin);
+ p += sfnt_put_short(p, table->yMin);
+ p += sfnt_put_short(p, table->xMax);
+ p += sfnt_put_short(p, table->yMax);
+ p += sfnt_put_ushort(p, table->macStyle);
+ p += sfnt_put_ushort(p, table->lowestRecPPEM);
+ p += sfnt_put_short(p, table->fontDirectionHint);
+ p += sfnt_put_short(p, table->indexToLocFormat);
+ p += sfnt_put_short(p, table->glyphDataFormat);
+
+ return data;
+}
+
+struct tt_head_table *tt_read_head_table (sfnt *sfont)
+{
+ int i;
+ struct tt_head_table *table = NULL;
+
+ table = NEW(1, struct tt_head_table);
+
+ sfnt_locate_table(sfont, "head");
+
+ table->version = sfnt_get_ulong(sfont);
+ table->fontRevision = sfnt_get_ulong(sfont);
+ table->checkSumAdjustment = sfnt_get_ulong(sfont);
+ table->magicNumber = sfnt_get_ulong(sfont);
+ table->flags = sfnt_get_ushort(sfont);
+ table->unitsPerEm = sfnt_get_ushort(sfont);
+ for (i=0; i<8; i++) {
+ (table->created)[i] = sfnt_get_byte (sfont);
+ }
+ for (i=0; i<8; i++) {
+ (table->modified)[i] = sfnt_get_byte (sfont);
+ }
+ table->xMin = sfnt_get_short(sfont);
+ table->yMin = sfnt_get_short(sfont);
+ table->xMax = sfnt_get_short(sfont);
+ table->yMax = sfnt_get_short(sfont);
+ table->macStyle = sfnt_get_short(sfont);
+ table->lowestRecPPEM = sfnt_get_short(sfont);
+ table->fontDirectionHint = sfnt_get_short(sfont);
+ table->indexToLocFormat = sfnt_get_short(sfont);
+ table->glyphDataFormat = sfnt_get_short(sfont);
+
+ return table;
+}
+
+char *tt_pack_maxp_table (struct tt_maxp_table *table)
+{
+ char *p, *data;
+
+ p = data = NEW(TT_MAXP_TABLE_SIZE, char);
+ p += sfnt_put_ulong(p, table->version);
+ p += sfnt_put_ushort(p, table->numGlyphs);
+ p += sfnt_put_ushort(p, table->maxPoints);
+ p += sfnt_put_ushort(p, table->maxContours);
+ p += sfnt_put_ushort(p, table->maxComponentPoints);
+ p += sfnt_put_ushort(p, table->maxComponentContours);
+ p += sfnt_put_ushort(p, table->maxZones);
+ p += sfnt_put_ushort(p, table->maxTwilightPoints);
+ p += sfnt_put_ushort(p, table->maxStorage);
+ p += sfnt_put_ushort(p, table->maxFunctionDefs);
+ p += sfnt_put_ushort(p, table->maxInstructionDefs);
+ p += sfnt_put_ushort(p, table->maxStackElements);
+ p += sfnt_put_ushort(p, table->maxSizeOfInstructions);
+ p += sfnt_put_ushort(p, table->maxComponentElements);
+ p += sfnt_put_ushort(p, table->maxComponentDepth);
+
+ return data;
+}
+
+struct tt_maxp_table *tt_read_maxp_table (sfnt *sfont)
+{
+ struct tt_maxp_table *table = NULL;
+
+ table = NEW(1, struct tt_maxp_table);
+
+ sfnt_locate_table(sfont, "maxp");
+ table->version = sfnt_get_ulong(sfont);
+ table->numGlyphs = sfnt_get_ushort(sfont);
+ table->maxPoints = sfnt_get_ushort(sfont);
+ table->maxContours = sfnt_get_ushort(sfont);
+ table->maxComponentPoints = sfnt_get_ushort(sfont);
+ table->maxComponentContours = sfnt_get_ushort(sfont);
+ table->maxZones = sfnt_get_ushort(sfont);
+ table->maxTwilightPoints = sfnt_get_ushort(sfont);
+ table->maxStorage = sfnt_get_ushort(sfont);
+ table->maxFunctionDefs = sfnt_get_ushort(sfont);
+ table->maxInstructionDefs = sfnt_get_ushort(sfont);
+ table->maxStackElements = sfnt_get_ushort(sfont);
+ table->maxSizeOfInstructions = sfnt_get_ushort(sfont);
+ table->maxComponentElements = sfnt_get_ushort(sfont);
+ table->maxComponentDepth = sfnt_get_ushort(sfont);
+
+ return table;
+}
+
+char *tt_pack_hhea_table (struct tt_hhea_table *table)
+{
+ int i;
+ char *p, *data;
+
+ p = data = NEW(TT_HHEA_TABLE_SIZE, char);
+ p += sfnt_put_ulong(p, table->version);
+ p += sfnt_put_short(p, table->Ascender);
+ p += sfnt_put_short(p, table->Descender);
+ p += sfnt_put_short(p, table->LineGap);
+ p += sfnt_put_ushort(p, table->advanceWidthMax);
+ p += sfnt_put_short(p, table->minLeftSideBearing);
+ p += sfnt_put_short(p, table->minRightSideBearing);
+ p += sfnt_put_short(p, table->xMaxExtent);
+ p += sfnt_put_short(p, table->caretSlopeRise);
+ p += sfnt_put_short(p, table->caretSlopeRun);
+ for (i = 0; i < 5; i++) {
+ p += sfnt_put_short(p, table->reserved[i]);
+ }
+ p += sfnt_put_short(p, table->metricDataFormat);
+ p += sfnt_put_ushort(p, table->numberOfHMetrics);
+
+ return data;
+}
+
+struct tt_hhea_table *
+tt_read_hhea_table (sfnt *sfont)
+{
+ int i;
+ struct tt_hhea_table *table = NULL;
+
+ table = NEW(1, struct tt_hhea_table);
+
+ sfnt_locate_table(sfont, "hhea");
+ table->version = sfnt_get_ulong(sfont);
+ table->Ascender = sfnt_get_short (sfont);
+ table->Descender = sfnt_get_short(sfont);
+ table->LineGap = sfnt_get_short(sfont);
+ table->advanceWidthMax = sfnt_get_ushort(sfont);
+ table->minLeftSideBearing = sfnt_get_short(sfont);
+ table->minRightSideBearing = sfnt_get_short(sfont);
+ table->xMaxExtent = sfnt_get_short(sfont);
+ table->caretSlopeRise = sfnt_get_short(sfont);
+ table->caretSlopeRun = sfnt_get_short(sfont);
+ for(i = 0; i < 5; i++) {
+ table->reserved[i] = sfnt_get_short(sfont);
+ }
+ table->metricDataFormat = sfnt_get_short(sfont);
+ if (table->metricDataFormat != 0)
+ TT_ERROR("unknown metricDaraFormat");
+ table->numberOfHMetrics = sfnt_get_ushort(sfont);
+
+ return table;
+}
+
+/* vhea */
+char *
+tt_pack_vhea_table (struct tt_vhea_table *table)
+{
+ int i;
+ char *p, *data;
+
+ p = data = NEW(TT_VHEA_TABLE_SIZE, char);
+ p += sfnt_put_ulong(p, table->version);
+ p += sfnt_put_short(p, table->vertTypoAscender);
+ p += sfnt_put_short(p, table->vertTypoDescender);
+ p += sfnt_put_short(p, table->vertTypoLineGap);
+ p += sfnt_put_short(p, table->advanceHeightMax); /* ushort ? */
+ p += sfnt_put_short(p, table->minTopSideBearing);
+ p += sfnt_put_short(p, table->minBottomSideBearing);
+ p += sfnt_put_short(p, table->yMaxExtent);
+ p += sfnt_put_short(p, table->caretSlopeRise);
+ p += sfnt_put_short(p, table->caretSlopeRun);
+ p += sfnt_put_short(p, table->caretOffset);
+ for(i = 0; i < 5; i++) {
+ p += sfnt_put_short(p, table->reserved[i]);
+ }
+ p += sfnt_put_ushort(p, table->numOfLongVerMetrics);
+
+ return data;
+}
+
+struct tt_vhea_table *tt_read_vhea_table (sfnt *sfont)
+{
+ int i;
+ struct tt_vhea_table *table = NULL;
+
+ table = NEW(1, struct tt_vhea_table);
+
+ sfnt_locate_table(sfont, "vhea");
+ table->version = sfnt_get_ulong(sfont);
+ table->vertTypoAscender = sfnt_get_short (sfont);
+ table->vertTypoDescender = sfnt_get_short(sfont);
+ table->vertTypoLineGap = sfnt_get_short(sfont);
+ table->advanceHeightMax = sfnt_get_short(sfont); /* ushort ? */
+ table->minTopSideBearing = sfnt_get_short(sfont);
+ table->minBottomSideBearing = sfnt_get_short(sfont);
+ table->yMaxExtent = sfnt_get_short(sfont);
+ table->caretSlopeRise = sfnt_get_short(sfont);
+ table->caretSlopeRun = sfnt_get_short(sfont);
+ table->caretOffset = sfnt_get_short(sfont);
+ for(i=0;i<5;i++) {
+ (table->reserved)[i] = sfnt_get_short(sfont);
+ }
+ table->numOfLongVerMetrics = sfnt_get_ushort(sfont);
+
+ return table;
+}
+
+
+struct tt_VORG_table *
+tt_read_VORG_table (sfnt *sfont)
+{
+ struct tt_VORG_table *vorg;
+ ULONG offset;
+ USHORT i;
+
+ offset = sfnt_find_table_pos(sfont, "VORG");
+
+ if (offset > 0) {
+ vorg = NEW(1, struct tt_VORG_table);
+
+ sfnt_locate_table(sfont, "VORG");
+ if (sfnt_get_ushort(sfont) != 1 ||
+ sfnt_get_ushort(sfont) != 0)
+ TT_ERROR("Unsupported VORG version.");
+
+ vorg->defaultVertOriginY = sfnt_get_short(sfont);
+ vorg->numVertOriginYMetrics = sfnt_get_ushort(sfont);
+ vorg->vertOriginYMetrics = NEW(vorg->numVertOriginYMetrics,
+ struct tt_vertOriginYMetrics);
+ /*
+ * The vertOriginYMetrics array must be sorted in increasing
+ * glyphIndex order.
+ */
+ for (i = 0;
+ i < vorg->numVertOriginYMetrics; i++) {
+ vorg->vertOriginYMetrics[i].glyphIndex = sfnt_get_ushort(sfont);
+ vorg->vertOriginYMetrics[i].vertOriginY = sfnt_get_short(sfont);
+ }
+ } else {
+ vorg = NULL;
+ }
+
+ return vorg;
+}
+
+/*
+ * hmtx and vmtx
+ *
+ * Reading/writing hmtx and vmtx depend on other tables, maxp and hhea/vhea.
+ */
+
+struct tt_longMetrics *
+tt_read_longMetrics (sfnt *sfont, USHORT numGlyphs, USHORT numLongMetrics)
+{
+ struct tt_longMetrics *m;
+ USHORT gid, last_adv = 0;
+
+ m = NEW(numGlyphs, struct tt_longMetrics);
+ for (gid = 0; gid < numGlyphs; gid++) {
+ if (gid < numLongMetrics)
+ last_adv = sfnt_get_ushort(sfont);
+ m[gid].sideBearing = sfnt_get_short(sfont);
+ m[gid].advance = last_adv;
+ }
+
+ return m;
+}
+
+/* OS/2 table */
+/* this table may not exist */
+struct tt_os2__table *
+tt_read_os2__table (sfnt *sfont)
+{
+ struct tt_os2__table *table = NULL;
+ int i;
+
+ if (sfnt_find_table_pos(sfont, "OS/2") == 0)
+ return NULL;
+
+ sfnt_locate_table(sfont, "OS/2");
+
+ table = NEW(1, struct tt_os2__table);
+
+ table->version = sfnt_get_ushort(sfont);
+ table->xAvgCharWidth = sfnt_get_short(sfont);
+ table->usWeightClass = sfnt_get_ushort(sfont);
+ table->usWidthClass = sfnt_get_ushort(sfont);
+ table->fsType = sfnt_get_short(sfont);
+ table->ySubscriptXSize = sfnt_get_short(sfont);
+ table->ySubscriptYSize = sfnt_get_short(sfont);
+ table->ySubscriptXOffset = sfnt_get_short(sfont);
+ table->ySubscriptYOffset = sfnt_get_short(sfont);
+ table->ySuperscriptXSize = sfnt_get_short(sfont);
+ table->ySuperscriptYSize = sfnt_get_short(sfont);
+ table->ySuperscriptXOffset = sfnt_get_short(sfont);
+ table->ySuperscriptYOffset = sfnt_get_short(sfont);
+ table->yStrikeoutSize = sfnt_get_short(sfont);
+ table->yStrikeoutPosition = sfnt_get_short(sfont);
+ table->sFamilyClass = sfnt_get_short(sfont);
+ for (i = 0; i < 10; i++) {
+ table->panose[i] = sfnt_get_byte(sfont);
+ }
+ table->ulUnicodeRange1 = sfnt_get_ulong(sfont);
+ table->ulUnicodeRange2 = sfnt_get_ulong(sfont);
+ table->ulUnicodeRange3 = sfnt_get_ulong(sfont);
+ table->ulUnicodeRange4 = sfnt_get_ulong(sfont);
+ for (i = 0; i < 4; i++) {
+ table->achVendID[i] = sfnt_get_char(sfont);
+ }
+ table->fsSelection = sfnt_get_ushort(sfont);
+ table->usFirstCharIndex = sfnt_get_ushort(sfont);
+ table->usLastCharIndex = sfnt_get_ushort(sfont);
+ table->sTypoAscender = sfnt_get_short(sfont);
+ table->sTypoDescender = sfnt_get_short(sfont);
+ table->sTypoLineGap = sfnt_get_short(sfont);
+ table->usWinAscent = sfnt_get_ushort(sfont);
+ table->usWinDescent = sfnt_get_ushort(sfont);
+ table->ulCodePageRange1 = sfnt_get_ulong(sfont);
+ table->ulCodePageRange2 = sfnt_get_ulong(sfont);
+ if (table->version == 0x0002) {
+ table->sxHeight = sfnt_get_short(sfont);
+ table->sCapHeight = sfnt_get_short(sfont);
+ table->usDefaultChar = sfnt_get_ushort(sfont);
+ table->usBreakChar = sfnt_get_ushort(sfont);
+ table->usMaxContext = sfnt_get_ushort(sfont);
+ }
+
+ return table;
+}
+
+USHORT
+tt_get_name (sfnt *sfont, char *dest, USHORT destlen,
+ USHORT plat_id, USHORT enco_id,
+ USHORT lang_id, USHORT name_id)
+{
+ USHORT length = 0;
+ USHORT num_names, string_offset;
+ ULONG name_offset;
+ int i;
+
+ name_offset = sfnt_locate_table (sfont, "name");
+
+ if (sfnt_get_ushort(sfont))
+ TT_ERROR ("Expecting zero");
+
+ num_names = sfnt_get_ushort(sfont);
+ string_offset = sfnt_get_ushort(sfont);
+ for (i=0;i<num_names;i++) {
+ USHORT p_id, e_id, n_id, l_id;
+ USHORT offset;
+
+ p_id = sfnt_get_ushort(sfont);
+ e_id = sfnt_get_ushort(sfont);
+ l_id = sfnt_get_ushort(sfont);
+ n_id = sfnt_get_ushort(sfont);
+ length = sfnt_get_ushort(sfont);
+ offset = sfnt_get_ushort(sfont);
+ /* language ID value 0xffffu for `accept any language ID' */
+ if ((p_id == plat_id) && (e_id == enco_id) &&
+ (lang_id == 0xffffu || l_id == lang_id) && (n_id == name_id)) {
+ if (length > destlen - 1) {
+ fprintf(stderr, "\n** Notice: Name string too long. Truncating **\n");
+ length = destlen - 1;
+ }
+ sfnt_seek_set (sfont, name_offset+string_offset+offset);
+ sfnt_read((unsigned char*)dest, length, sfont);
+ dest[length] = '\0';
+ break;
+ }
+ }
+ if (i == num_names) {
+ length = 0;
+ }
+
+ return length;
+}
+
+USHORT
+tt_get_ps_fontname (sfnt *sfont, char *dest, USHORT destlen)
+{
+ USHORT namelen = 0;
+
+#ifdef XETEX
+
+ const char* name = FT_Get_Postscript_Name(sfont->ft_face);
+ namelen = strlen(name);
+ if (namelen > destlen - 1) {
+ strncpy(dest, name, destlen - 1);
+ dest[destlen] = 0;
+ }
+ else
+ strcpy(dest, name);
+
+#else
+
+ /* First try Mac-Roman PS name and then Win-Unicode PS name */
+ if ((namelen = tt_get_name(sfont, dest, destlen, 1, 0, 0, 6)) != 0 ||
+ (namelen = tt_get_name(sfont, dest, destlen, 3, 1, 0x409u, 6)) != 0 ||
+ (namelen = tt_get_name(sfont, dest, destlen, 3, 5, 0x412u, 6)) != 0)
+ return namelen;
+
+ fprintf(stderr, "\n** Warning: No valid PostScript name available **\n");
+ /*
+ Wrokaround for some bad TTfonts:
+ Language ID value 0xffffu for `accept any language ID'
+ */
+ if ((namelen = tt_get_name(sfont, dest, destlen, 1, 0, 0xffffu, 6)) == 0) {
+ /*
+ Finally falling back to Mac Roman name field.
+ Warning: Some bad Japanese TTfonts using SJIS encoded string in the
+ Mac Roman name field.
+ */
+ namelen = tt_get_name(sfont, dest, destlen, 1, 0, 0, 1);
+ }
+
+#endif
+
+ return namelen;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/tt_table.h b/Build/source/texk/web2c/luatexdir/font/tt_table.h
new file mode 100644
index 00000000000..ffb2c5b8f45
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/tt_table.h
@@ -0,0 +1,193 @@
+/* $Header: /home/cvsroot/dvipdfmx/src/tt_table.h,v 1.6 2004/09/11 14:50:29 hirata Exp $
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+#ifndef _TT_TABLE_H_
+#define _TT_TABLE_H_
+
+#include "sfnt.h"
+
+#define TT_HEAD_TABLE_SIZE 54UL
+#define TT_MAXP_TABLE_SIZE 32UL
+#define TT_HHEA_TABLE_SIZE 36UL
+#define TT_VHEA_TABLE_SIZE 36UL
+
+struct tt_head_table
+{
+ Fixed version;
+ Fixed fontRevision;
+ ULONG checkSumAdjustment;
+ ULONG magicNumber;
+ USHORT flags;
+ USHORT unitsPerEm;
+ BYTE created[8];
+ BYTE modified[8];
+ FWord xMin, yMin, xMax, yMax;
+ USHORT macStyle;
+ USHORT lowestRecPPEM;
+ SHORT fontDirectionHint;
+ SHORT indexToLocFormat;
+ SHORT glyphDataFormat;
+};
+
+struct tt_hhea_table
+{
+ Fixed version;
+ FWord Ascender;
+ FWord Descender;
+ FWord LineGap;
+ uFWord advanceWidthMax;
+ FWord minLeftSideBearing;
+ FWord minRightSideBearing;
+ FWord xMaxExtent;
+ SHORT caretSlopeRise;
+ SHORT caretSlopeRun;
+ SHORT reserved[5]; /* set to 0 */
+ SHORT metricDataFormat;
+ USHORT numberOfHMetrics;
+};
+
+struct tt_vhea_table
+{
+ Fixed version;
+ SHORT vertTypoAscender; /* v.1.1 name */
+ SHORT vertTypoDescender; /* v.1.1 name */
+ SHORT vertTypoLineGap; /* v.1.1 name */
+ SHORT advanceHeightMax;
+ SHORT minTopSideBearing;
+ SHORT minBottomSideBearing;
+ SHORT yMaxExtent;
+ SHORT caretSlopeRise;
+ SHORT caretSlopeRun;
+ SHORT caretOffset;
+ SHORT reserved[5]; /* set to 0 */
+ USHORT numOfLongVerMetrics;
+};
+
+struct tt_maxp_table
+{
+ Fixed version;
+ USHORT numGlyphs;
+ USHORT maxPoints;
+ USHORT maxContours;
+ USHORT maxComponentPoints;
+ USHORT maxComponentContours;
+ USHORT maxZones;
+ USHORT maxTwilightPoints;
+ USHORT maxStorage;
+ USHORT maxFunctionDefs;
+ USHORT maxInstructionDefs;
+ USHORT maxStackElements;
+ USHORT maxSizeOfInstructions;
+ USHORT maxComponentElements;
+ USHORT maxComponentDepth;
+};
+
+struct tt_os2__table
+{
+ USHORT version; /* 0x0001 or 0x0002 */
+ SHORT xAvgCharWidth;
+ USHORT usWeightClass;
+ USHORT usWidthClass;
+ SHORT fsType; /* if (faType & 0x08) editable_embedding */
+ SHORT ySubscriptXSize;
+ SHORT ySubscriptYSize;
+ SHORT ySubscriptXOffset;
+ SHORT ySubscriptYOffset;
+ SHORT ySuperscriptXSize;
+ SHORT ySuperscriptYSize;
+ SHORT ySuperscriptXOffset;
+ SHORT ySuperscriptYOffset;
+ SHORT yStrikeoutSize;
+ SHORT yStrikeoutPosition;
+ SHORT sFamilyClass;
+ BYTE panose[10];
+ ULONG ulUnicodeRange1;
+ ULONG ulUnicodeRange2;
+ ULONG ulUnicodeRange3;
+ ULONG ulUnicodeRange4;
+ ICHAR achVendID[4];
+ USHORT fsSelection;
+ USHORT usFirstCharIndex;
+ USHORT usLastCharIndex;
+ SHORT sTypoAscender; /* TTF spec. from MS is wrong */
+ SHORT sTypoDescender; /* TTF spec. from MS is wrong */
+ SHORT sTypoLineGap; /* TTF spec. from MS is wrong */
+ USHORT usWinAscent;
+ USHORT usWinDescent;
+ ULONG ulCodePageRange1;
+ ULONG ulCodePageRange2;
+ /* version 0x0002 */
+ SHORT sxHeight;
+ SHORT sCapHeight;
+ USHORT usDefaultChar;
+ USHORT usBreakChar;
+ USHORT usMaxContext;
+};
+
+struct tt_vertOriginYMetrics {
+ USHORT glyphIndex;
+ SHORT vertOriginY;
+};
+
+struct tt_VORG_table {
+ SHORT defaultVertOriginY;
+ USHORT numVertOriginYMetrics;
+ struct tt_vertOriginYMetrics *vertOriginYMetrics;
+};
+
+/* hmtx and vmtx */
+struct tt_longMetrics
+{
+ USHORT advance;
+ SHORT sideBearing;
+};
+
+
+/* head, hhea, maxp */
+extern char *tt_pack_head_table (struct tt_head_table *table);
+extern struct tt_head_table *tt_read_head_table (sfnt *sfont);
+extern char *tt_pack_hhea_table (struct tt_hhea_table *table);
+extern struct tt_hhea_table *tt_read_hhea_table (sfnt *sfont);
+extern char *tt_pack_maxp_table (struct tt_maxp_table *table);
+extern struct tt_maxp_table *tt_read_maxp_table (sfnt *sfont);
+
+/* vhea */
+extern char *tt_pack_vhea_table (struct tt_vhea_table *table);
+extern struct tt_vhea_table *tt_read_vhea_table (sfnt *sfont);
+
+/* VORG */
+extern struct tt_VORG_table *tt_read_VORG_table (sfnt *sfont);
+
+/* hmtx and vmtx */
+extern struct tt_longMetrics *tt_read_longMetrics (sfnt *sfont,
+ USHORT numGlyphs, USHORT numLongMetrics);
+
+/* OS/2 table */
+extern struct tt_os2__table *tt_read_os2__table (sfnt *sfont);
+
+/* name table */
+extern USHORT tt_get_name (sfnt *sfont, char *dest, USHORT destlen,
+ USHORT plat_id, USHORT enco_id,
+ USHORT lang_id, USHORT name_id);
+extern USHORT tt_get_ps_fontname (sfnt *sfont, char *dest, USHORT destlen);
+
+#endif /* _TT_TABLE_H_ */
diff --git a/Build/source/texk/web2c/luatexdir/font/vfovf.c b/Build/source/texk/web2c/luatexdir/font/vfovf.c
new file mode 100644
index 00000000000..0f23cb07b94
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/vfovf.c
@@ -0,0 +1,1349 @@
+/*
+Copyright (c) 1996-2006 Taco Hoekwater <taco@luatex.org>
+
+This file is part of LuaTeX.
+
+LuaTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+LuaTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with LuaTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: vfovf.c 1022 2008-02-14 11:49:30Z taco $
+*/
+
+#include "ptexlib.h"
+
+#include "luatex-api.h"
+
+/* this is a hack! */
+#define font_max 5000
+
+#define set_char_0 0 /* typeset character 0 and move right */
+#define set1 128 /* typeset a character and move right */
+#define set2 129 /* typeset a character and move right */
+#define set3 130 /* typeset a character and move right */
+#define set4 131 /* typeset a character and move right */
+#define set_rule 132 /* typeset a rule and move right */
+#define put1 133 /* typeset a character without moving */
+#define put2 134 /* typeset a character without moving */
+#define put3 135 /* typeset a character without moving */
+#define put4 136 /* typeset a character without moving */
+#define put_rule 137 /* typeset a rule */
+#define nop 138 /* no operation */
+#define bop 139 /* beginning of page */
+#define eop 140 /* ending of page */
+#define push 141 /* save the current positions */
+#define pop 142 /* restore previous positions */
+#define right1 143 /* move right */
+#define right2 144 /* move right */
+#define right3 145 /* move right */
+#define right4 146 /* move right, 4 bytes */
+#define w0 147 /* move right by |w| */
+#define w1 148 /* move right and set |w| */
+#define w2 149 /* move right and set |w| */
+#define w3 150 /* move right and set |w| */
+#define w4 151 /* move right and set |w| */
+#define x0 152 /* move right by |x| */
+#define x1 153 /* move right and set |x| */
+#define x2 154 /* move right and set |x| */
+#define x3 155 /* move right and set |x| */
+#define x4 156 /* move right and set |x| */
+#define down1 157 /* move down */
+#define down2 158 /* move down */
+#define down3 159 /* move down */
+#define down4 160 /* move down, 4 bytes */
+#define y0 161 /* move down by |y| */
+#define y1 162 /* move down and set |y| */
+#define y2 163 /* move down and set |y| */
+#define y3 164 /* move down and set |y| */
+#define y4 165 /* move down and set |y| */
+#define z0 166 /* move down by |z| */
+#define z1 167 /* move down and set |z| */
+#define z2 168 /* move down and set |z| */
+#define z3 169 /* move down and set |z| */
+#define z4 170 /* move down and set |z| */
+#define fnt_num_0 171 /* set current font to 0 */
+#define fnt1 235 /* set current font */
+#define fnt2 236 /* set current font */
+#define fnt3 237 /* set current font */
+#define fnt4 238 /* set current font */
+#define xxx1 239 /* extension to DVI primitives */
+#define xxx2 240 /* extension to DVI primitives */
+#define xxx3 241 /* extension to DVI primitives */
+#define xxx4 242 /* potentially long extension to DVI primitives */
+#define fnt_def1 243 /* define the meaning of a font number */
+#define pre 247 /* preamble */
+#define post 248 /* postamble beginning */
+#define post_post 249 /* postamble ending */
+#define yyy1 250 /* PDF literal text */
+#define yyy2 251 /* PDF literal text */
+#define yyy3 252 /* PDF literal text */
+#define yyy4 253 /* PDF literal text */
+
+#define null_font 0
+
+#define long_char 242 /* \.{VF} command for general character packet */
+#define vf_id 202 /* identifies \.{VF} files */
+
+/* go out \.{VF} processing with an error message */
+#define bad_vf(a) { xfree(vf_buffer); print_nlp(); \
+ print_string("Error in processing VF font ("); \
+ print_string(font_name(f)); \
+ print_string(".vf): "); \
+ print_string(a); \
+ print_string(", virtual font will be ignored"); \
+ print_ln(); return; }
+
+#define lua_bad_vf(a) { xfree(vf_buffer); \
+ lua_settop(L,s_top); \
+ lua_pushnil(L); \
+ lua_pushstring(L,a); \
+ return 2; }
+
+#define tmp_b0 tmp_w.qqqq.b0
+#define tmp_b1 tmp_w.qqqq.b1
+#define tmp_b2 tmp_w.qqqq.b2
+#define tmp_b3 tmp_w.qqqq.b3
+#define tmp_int tmp_w.cint
+
+#define vf_stack_size 100 /* \.{DVI} files shouldn't |push| beyond this depth */
+
+typedef unsigned char vf_stack_index ; /* an index into the stack */
+
+typedef struct vf_stack_record {
+ scaled stack_w, stack_x, stack_y, stack_z;
+} vf_stack_record;
+
+boolean auto_expand_vf(internal_font_number f); /* forward */
+
+/* get a byte from\.{VF} file */
+
+#define vf_byte(a) { real_eight_bits vf_tmp_b; \
+ if (vf_cur>=vf_size) { \
+ pdftex_fail("unexpected eof on virtual font"); \
+ } \
+ vf_tmp_b = vf_buffer[vf_cur++] ; a = vf_tmp_b; }
+
+
+#define vf_replace_z() { \
+ vf_alpha=16; \
+ while (vf_z>=040000000) { \
+ vf_z= vf_z / 2; \
+ vf_alpha += vf_alpha; \
+ } \
+ vf_beta=256 / vf_alpha; \
+ vf_alpha=vf_alpha*vf_z; }
+
+/* read |k| bytes as an integer from \.{VF} file */
+
+#define vf_read(k,l) { integer itmp = 0, dtmp = k, jtmp = 0; \
+ while (dtmp > 0) { \
+ vf_byte(jtmp); \
+ if ((dtmp==k) && jtmp>127) \
+ jtmp = jtmp - 256; \
+ itmp = itmp*256 + jtmp; \
+ decr(dtmp); \
+ } \
+ l = itmp; }
+
+#define vf_read_u(k,l) { unsigned int dtmp=k, itmp = 0, jtmp = 0; \
+ while (dtmp-- > 0) { \
+ vf_byte(jtmp); \
+ itmp = itmp*256 + jtmp; \
+ } \
+ l = itmp; }
+
+void
+pdf_check_vf_cur_val (void) {
+ internal_font_number f;
+ f = cur_val;
+ if (font_type(f) == virtual_font_type)
+ pdf_error("font", "command cannot be used with virtual font");
+}
+
+static void
+vf_local_font_warning(internal_font_number f, internal_font_number k, char *s, integer a, integer b) {
+ print_nlp();
+ print_string(s);
+ print_string(" in local font ");
+ print_string(font_name(k));
+ print_string(" (");
+ print_int(b);
+ print_string(" != ");
+ print_int(a);
+ print_string(") in virtual font ");
+ print_string(font_name(f));
+ print_string(".vf ignored.");
+}
+
+
+/* process a local font in \.{VF} file */
+
+internal_font_number
+vf_def_font(internal_font_number f,unsigned char *vf_buffer, integer *vf_cr) {
+ internal_font_number k;
+ str_number s;
+ scaled ds,fs;
+ four_quarters cs;
+ memory_word tmp_w; /* accumulator */
+ integer junk;
+ unsigned long checksum;
+ cs.b0 = vf_buffer[(*vf_cr)];
+ cs.b1 = vf_buffer[(*vf_cr)+1];
+ cs.b2 = vf_buffer[(*vf_cr)+2];
+ cs.b3 = vf_buffer[(*vf_cr)+3]; (*vf_cr)+=4;
+ checksum = cs.b0*256*256*256 + cs.b1*256*256 + cs.b2*256 + cs.b3;
+ k = vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ if (k>127) k-=256;
+ k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+
+ fs = sqxfw(k, font_size(f));
+
+ k = vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ if (k>127) k-=256;
+ k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+
+ ds = k / 16;
+
+
+ tmp_b0 = vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ tmp_b1 = vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ while (tmp_b0 > 0) {
+ tmp_b0--;
+ (*vf_cr)++; /* skip the font path */
+ }
+ string_room(tmp_b1);
+ while (tmp_b1 > 0) {
+ tmp_b1--;
+ junk = vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ append_pool_char(junk);
+ }
+ s = make_string();
+ k = tfm_lookup(s, fs);
+ if (k == null_font)
+ k = read_font_info(get_nullcs(), s, get_nullstr(), fs, -1);
+ if (k != null_font) {
+ if (checksum!=0 && font_checksum(k)!=0 && checksum!= font_checksum(k))
+ vf_local_font_warning(f, k, "checksum mismatch",checksum,font_checksum(k));
+ if (ds != font_dsize(k))
+ vf_local_font_warning(f, k, "design size mismatch",ds,font_dsize(k));
+ }
+ if (pdf_font_expand_ratio(f) != 0)
+ set_expand_params(k, pdf_font_auto_expand(f),
+ pdf_font_expand_ratio(pdf_font_stretch(f)),
+ -pdf_font_expand_ratio(pdf_font_shrink(f)),
+ pdf_font_step(f), pdf_font_expand_ratio(f));
+ return k;
+}
+
+
+int
+open_vf_file (char *fn, unsigned char **vbuffer, integer *vsize) {
+ boolean res; /* was the callback successful? */
+ integer callback_id;
+ boolean file_read; /* was |vf_file| successfully read? */
+ FILE *vf_file;
+ char *fnam = NULL;
+
+
+
+
+ namelength = strlen(fn);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),fn);
+
+ callback_id=callback_defined(find_vf_file_callback);
+ if (callback_id>0) {
+ res = run_callback(callback_id,"S->S",fn, &fnam);
+ if (res && (fnam!=NULL) && (strlen(fnam)>0)) {
+ /* @<Fixup |nameoffile| after callback@>; */
+ free(nameoffile);
+ namelength = strlen(fnam);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),fnam);
+ } else {
+ return 0;
+ }
+ }
+ callback_id=callback_defined(read_vf_file_callback);
+ if (callback_id>0) {
+ file_read = false;
+ res = run_callback(callback_id,"S->bSd",stringcast(nameoffile+1),
+ &file_read, vbuffer,vsize);
+ if (res && file_read && (*vsize>0)) {
+ return 1;
+ }
+ if (!file_read)
+ return 0; /* -1 */
+ } else {
+ if (ovf_b_open_in(vf_file) || vf_b_open_in(vf_file)) {
+ res = read_vf_file(vf_file,vbuffer,vsize);
+ b_close(vf_file);
+ if (res) {
+ return 1;
+ }
+ } else {
+ return 0; /* -1 */
+ }
+ }
+ return 0;
+}
+
+
+/*
+ @ The |do_vf| procedure attempts to read the \.{VF} file for a font, and sets
+ |font_type()| to |real_font_type| if the \.{VF} file could not be found
+ or loaded, otherwise sets |font_type()| to |virtual_font_type|. At this
+ time, |tmp_f| is the internal font number of the current \.{TFM} font. To
+ process font definitions in virtual font we call |vf_def_font|.
+*/
+
+#define append_packet(k) vpackets[vf_np++] = k
+
+/* life is easier if all internal font commands are fnt4 and
+ all character commands are set4 or put4 */
+
+#define append_fnt_set(k) { \
+ assert(k>0) ; \
+ append_packet(packet_font_code); \
+ append_four(k); }
+
+#define append_four(k) { \
+ append_packet((k&0xFF000000)>>24); \
+ append_packet((k&0x00FF0000)>>16); \
+ append_packet((k&0x0000FF00)>>8); \
+ append_packet((k&0x000000FF)); }
+
+/* some of these things happen twice, adding a define is simplest */
+
+#define test_checksum() { vf_byte(tmp_b0); vf_byte(tmp_b1); \
+ vf_byte(tmp_b2); vf_byte(tmp_b3); \
+ if (((tmp_b0 != 0) || (tmp_b1 != 0) || (tmp_b2 != 0) || (tmp_b3 != 0)) && \
+ ((font_check_0(f) != 0) || (font_check_1(f) != 0) || \
+ (font_check_2(f) != 0) || (font_check_3(f) != 0)) && \
+ ((tmp_b0 != font_check_0(f)) || (tmp_b1 != font_check_1(f)) || \
+ (tmp_b2 != font_check_2(f)) || (tmp_b3 != font_check_3(f)))) { \
+ print_nlp(); \
+ print_string("checksum mismatch in font "); \
+ print_string(font_name(f)); \
+ print_string(".vf ignored "); } }
+
+#define test_dsize() { int read_tmp; vf_read(4,read_tmp); \
+ if ((read_tmp / 16) != font_dsize(f)) { \
+ print_nlp(); \
+ print_string("design size mismatch in font "); \
+ print_string(font_name(f)); \
+ print_string(".vf ignored"); \
+ } }
+
+
+int count_packet_bytes (real_eight_bits *vf_buf, int cur_bute, int count) {
+ int k = 0;
+ int ff = 0;
+ int acc = 0;
+ unsigned int cmd = 0;
+ unsigned int d = 0;
+ while (k<count) {
+ cmd = vf_buf[cur_bute+k]; k++;
+ if ((cmd >= set_char_0) && (cmd < set1)) {
+ if (ff==0) { ff = 1; acc+=5; }
+ acc+=5;
+ } else if ((fnt_num_0 <= cmd) && (cmd <= fnt_num_0 + 63)) {
+ ff = 1;
+ acc+=5;
+ } else {
+ switch (cmd) {
+ case fnt1: acc+=5; k+=1; ff=1 ; break;
+ case fnt2: acc+=5; k+=2; ff=1 ; break;
+ case fnt3: acc+=5; k+=3; ff=1 ; break;
+ case fnt4: acc+=5; k+=4; ff=1 ; break;
+ case set_rule: acc+=9; k+=8; break;
+ case put_rule: acc+=11; k+=8; break;
+ case set1: acc+=5; k+=1; if (ff==0) { ff = 1; acc+=5; } break;
+ case set2: acc+=5; k+=2; if (ff==0) { ff = 1; acc+=5; } break;
+ case set3: acc+=5; k+=3; if (ff==0) { ff = 1; acc+=5; } break;
+ case set4: acc+=5; k+=4; if (ff==0) { ff = 1; acc+=5; } break;
+ case put1: acc+=7; k+=1; if (ff==0) { ff = 1; acc+=5; } break;
+ case put2: acc+=7; k+=2; if (ff==0) { ff = 1; acc+=5; } break;
+ case put3: acc+=7; k+=3; if (ff==0) { ff = 1; acc+=5; } break;
+ case put4: acc+=7; k+=4; if (ff==0) { ff = 1; acc+=5; } break;
+ case right1: acc+=5; k+=1; break;
+ case right2: acc+=5; k+=2; break;
+ case right3: acc+=5; k+=3; break;
+ case right4: acc+=5; k+=4; break;
+ case w1: acc+=5; k+=1; break;
+ case w2: acc+=5; k+=2; break;
+ case w3: acc+=5; k+=3; break;
+ case w4: acc+=5; k+=4; break;
+ case x1: acc+=5; k+=1; break;
+ case x2: acc+=5; k+=2; break;
+ case x3: acc+=5; k+=3; break;
+ case x4: acc+=5; k+=4; break;
+ case down1: acc+=5; k+=1; break;
+ case down2: acc+=5; k+=2; break;
+ case down3: acc+=5; k+=3; break;
+ case down4: acc+=5; k+=4; break;
+ case y1: acc+=5; k+=1; break;
+ case y2: acc+=5; k+=2; break;
+ case y3: acc+=5; k+=3; break;
+ case y4: acc+=5; k+=4; break;
+ case z1: acc+=5; k+=1; break;
+ case z2: acc+=5; k+=2; break;
+ case z3: acc+=5; k+=3; break;
+ case z4: acc+=5; k+=4; break;
+ case xxx1:
+ d = vf_buf[cur_bute+k]; k++;
+ k += d; acc += 5 + d;
+ break;
+ case xxx2:
+ d = vf_buf[cur_bute+k]; k++;
+ d = d*256 + vf_buf[cur_bute+k]; k++;
+ k += d; acc += 5 + d;
+ break;
+ case xxx3:
+ d = vf_buf[cur_bute+k]; k++;
+ d = d*256 + vf_buf[cur_bute+k]; k++;
+ d = d*256 + vf_buf[cur_bute+k]; k++;
+ k += d; acc += 5 + d;
+ break;
+ case xxx4:
+ d = vf_buf[cur_bute+k]; k++;
+ d = d*256 + vf_buf[cur_bute+k]; k++;
+ d = d*256 + vf_buf[cur_bute+k]; k++;
+ d = d*256 + vf_buf[cur_bute+k]; k++;
+ k += d; acc += 5 + d;
+ break;
+ case w0: acc+=5; break;
+ case x0: acc+=5; break;
+ case y0: acc+=5; break;
+ case z0: acc+=5; break;
+ case nop: break;
+ case push: acc+=1; break;
+ case pop: acc+=1; break;
+ }
+ }
+ }
+ return (acc+1);
+}
+
+void
+do_vf(internal_font_number f) {
+ integer k, n, i;
+ unsigned cmd;
+ scaled x,y,w,z,h,v;
+ integer cc, cmd_length, packet_length;
+ charinfo *co;
+ scaled tfm_width;
+ integer save_cur_byte;
+ vf_stack_index stack_level;
+ integer vf_z; /* multiplier */
+ integer vf_alpha; /* correction for negative values */
+ char vf_beta; /* divisor */
+ integer vf_np;
+ real_eight_bits *vpackets;
+ memory_word tmp_w; /* accumulator */
+ vf_stack_record vf_stack[256];
+ integer junk;
+ unsigned char *vf_buffer;
+ integer vf_size;
+ integer vf_cur;
+ integer *vf_local_fnts = NULL; /* external font ids */
+ integer *vf_real_fnts = NULL; /* internal font ids */
+ unsigned vf_nf = 0; /* local font counter */
+
+ if (font_type(f)!= unknown_font_type)
+ return;
+ set_font_type(f,real_font_type);
+ if (auto_expand_vf(f))
+ return; /* auto-expanded virtual font */
+ stack_level = 0;
+ /* @<Open |vf_file|, return if not found@>; */
+ vf_cur=0; vf_buffer=NULL; vf_size=0;
+ if (!open_vf_file(font_name(f), &vf_buffer, &vf_size))
+ return;
+ /* @<Process the preamble@>;@/ */
+ set_font_type(f,virtual_font_type);
+ vf_byte(k);
+ if (k != pre)
+ bad_vf("PRE command expected");
+ vf_byte(k);
+ if (k != vf_id)
+ bad_vf("wrong id byte");
+ vf_byte(cmd_length);
+ for (k = 1;k<= cmd_length;k++)
+ vf_byte(junk);
+ test_checksum();
+ test_dsize();
+ /* update_terminal;*/
+ vf_z = font_size(f);
+ vf_replace_z();
+ /* @<Process the font definitions@>;@/ */
+ /* scan forward to find the number of internal fonts */
+ vf_nf = 0;
+ save_cur_byte = vf_cur;
+ vf_byte(cmd);
+ while ((cmd >= fnt_def1) && (cmd <= (fnt_def1 + 3))) {
+ vf_read((cmd - fnt_def1 + 1),junk);
+ vf_read(4,junk);
+ vf_read(4,junk);
+ vf_read(4,junk);
+ vf_byte(k);
+ vf_byte(junk);
+ k += junk;
+ while (k-- > 0) { vf_byte(junk); }
+ incr(vf_nf);
+ vf_byte(cmd);
+ }
+ vf_cur = save_cur_byte;
+ vf_byte(cmd);
+ /* malloc and fill the local font arrays */
+ if (vf_nf>0) {
+ i = vf_nf*sizeof(integer);
+ vf_local_fnts= xmalloc(i);
+ memset(vf_local_fnts,0,i);
+ vf_real_fnts= xmalloc(i);
+ memset(vf_real_fnts,0,i);
+ vf_nf = 0;
+ while ((cmd >= fnt_def1) && (cmd <= (fnt_def1 + 3))) {
+ vf_read_u((cmd - fnt_def1 + 1),vf_local_fnts[vf_nf]);
+ vf_real_fnts[vf_nf] = vf_def_font(f, vf_buffer, &vf_cur);
+ incr(vf_nf);
+ vf_byte(cmd);
+ }
+ }
+
+
+ while (cmd <= long_char) {
+ /* @<Build a character packet@>;@/ */
+ vf_np = 0;
+ if (cmd == long_char) {
+ vf_read_u(4,packet_length);
+ vf_read_u(4,cc);
+ if (!char_exists(f,cc)) {
+ bad_vf("invalid character code");
+ }
+ vf_read(4,k);
+ tfm_width = sqxfw(k, font_size(f));
+ } else {
+ packet_length = cmd;
+ vf_byte(cc);
+ if (!char_exists(f,cc)) {
+ bad_vf("invalid character code");
+ }
+ vf_read(3,k);
+ tfm_width = sqxfw(k, font_size(f));
+ }
+ if (packet_length < 0)
+ bad_vf("negative packet length");
+ if (tfm_width != char_width(f,cc)) {
+ /* precisely 'one off' errors are rampant */
+ if (abs(tfm_width - char_width(f,cc))>1) {
+ print_nlp();
+ print_string("character width mismatch in font ");
+ print_string(font_name(f));
+ print_string(".vf ignored");
+ }
+ }
+ k = count_packet_bytes(vf_buffer,vf_cur,packet_length);
+ vpackets = xmalloc(k+1);
+ co = get_charinfo(f,cc);
+ k = 0;
+ w = 0; x = 0; y = 0; z = 0;
+ while (packet_length > 0) {
+ vf_byte(cmd);
+ decr(packet_length);
+
+ if ((cmd >= set_char_0) && (cmd < set1)) {
+ if (k == 0) {
+ k = vf_real_fnts[0];
+ append_fnt_set(k);
+ }
+ append_packet(packet_char_code);
+ append_four(cmd);
+ cmd_length = 0;
+ cmd = nop;
+
+ } else if (((fnt_num_0 <= cmd) && (cmd <= fnt_num_0 + 63)) ||
+ ((fnt1 <= cmd) && (cmd <= fnt1 + 3))) {
+ if (cmd >= fnt1) {
+ vf_read_u((cmd - fnt1 + 1),k);
+ packet_length -= (cmd - fnt1 + 1);
+ } else {
+ k = cmd - fnt_num_0;
+ }
+
+ /* change from local to external font id */
+ n = 0;
+ while ((n < vf_nf) && (vf_local_fnts[n] != k))
+ n++;
+ if (n==vf_nf)
+ bad_vf("undefined local font");
+
+ k = vf_real_fnts[n];
+ append_fnt_set(k);
+ cmd_length = 0;
+ cmd = nop;
+ } else {
+ switch (cmd) {
+ case set_rule:
+ vf_read(4,h); vf_read(4,v);
+ append_packet(packet_rule_code);
+ append_four(h);
+ append_four(v);
+ packet_length -= 8;
+ break;
+ case put_rule:
+ vf_read(4,h); vf_read(4,v);
+ append_packet(packet_push_code);
+ append_packet(packet_rule_code);
+ append_four(h);
+ append_four(v);
+ append_packet(packet_pop_code);
+ packet_length -= 8;
+ break;
+ case set1:
+ case set2:
+ case set3:
+ case set4:
+ if (k == 0) {
+ k = vf_real_fnts[0];
+ append_fnt_set(k);
+ }
+ vf_read_u((cmd - set1 + 1),i);
+ append_packet(packet_char_code);
+ append_four(i);
+ packet_length -= (cmd - set1 + 1);
+ break;
+ case put1:
+ case put2:
+ case put3:
+ case put4:
+ if (k == 0) {
+ k = vf_real_fnts[0];
+ append_fnt_set(k);
+ }
+ vf_read_u((cmd - put1 + 1),i);
+ append_packet(packet_push_code);
+ append_packet(packet_char_code);
+ append_four(i);
+ append_packet(packet_pop_code);
+ packet_length -= (cmd - put1 + 1);
+ break;
+ case right1:
+ case right2:
+ case right3:
+ case right4:
+ vf_read((cmd - right1 + 1),i);
+ append_packet(packet_right_code);
+ append_four(i);
+ packet_length -= (cmd - right1 + 1);
+ break;
+ case w1:
+ case w2:
+ case w3:
+ case w4:
+ vf_read((cmd - w1 + 1),w);
+ append_packet(packet_right_code);
+ append_four(w);
+ packet_length -= (cmd - w1 + 1);
+ break;
+ case x1:
+ case x2:
+ case x3:
+ case x4:
+ vf_read((cmd - x1 + 1),x);
+ append_packet(packet_right_code);
+ append_four(x);
+ packet_length -= (cmd - x1 + 1);
+ break;
+ case down1:
+ case down2:
+ case down3:
+ case down4:
+ vf_read((cmd - down1 + 1),i);
+ append_packet(packet_down_code);
+ append_four(i);
+ packet_length -= (cmd - down1 + 1);
+ break;
+ case y1:
+ case y2:
+ case y3:
+ case y4:
+ vf_read((cmd - y1 + 1),y);
+ append_packet(packet_down_code);
+ append_four(y);
+ packet_length -= (cmd - y1 + 1);
+ break;
+ case z1:
+ case z2:
+ case z3:
+ case z4:
+ vf_read((cmd - z1 + 1),z);
+ append_packet(packet_down_code);
+ append_four(z);
+ packet_length -= (cmd - z1 + 1);
+ break;
+ case xxx1:
+ case xxx2:
+ case xxx3:
+ case xxx4:
+ vf_read_u((cmd - xxx1 + 1),cmd_length);
+ packet_length -= (cmd - xxx1 + 1);
+ if (cmd_length <= 0)
+ bad_vf("special of negative length");
+ packet_length -= cmd_length;
+
+ append_packet(packet_special_code);
+ append_four(cmd_length);
+ while (cmd_length > 0) {
+ cmd_length--;
+ vf_byte(i);
+ append_packet(i);
+ }
+ append_packet(0);
+ break;
+ case w0:
+ append_packet(packet_right_code);
+ append_four(w);
+ break;
+ case x0:
+ append_packet(packet_right_code);
+ append_four(x);
+ break;
+ case y0:
+ append_packet(packet_down_code);
+ append_four(y);
+ break;
+ case z0:
+ append_packet(packet_down_code);
+ append_four(z);
+ break;
+ case nop:
+ break;
+ case push:
+ if (stack_level == vf_stack_size) {
+ overflow_string("virtual font stack size", vf_stack_size);
+ } else {
+ vf_stack[stack_level].stack_w = w;
+ vf_stack[stack_level].stack_x = x;
+ vf_stack[stack_level].stack_y = y;
+ vf_stack[stack_level].stack_z = z;
+ incr(stack_level);
+ append_packet(packet_push_code);
+ }
+ break;
+ case pop:
+ if (stack_level == 0) {
+ bad_vf("more POPs than PUSHs in character");
+ } else {
+ decr(stack_level);
+ w = vf_stack[stack_level].stack_w;
+ x = vf_stack[stack_level].stack_x;
+ y = vf_stack[stack_level].stack_y;
+ z = vf_stack[stack_level].stack_z;
+ append_packet(packet_pop_code);
+ }
+ break;
+ default:
+ bad_vf("improver DVI command");
+ }
+ }
+ }
+ /* signal end of packet */
+ append_packet(packet_end_code);
+
+ if (stack_level != 0)
+ bad_vf("more PUSHs than POPs in character packet");
+ if (packet_length != 0)
+ bad_vf("invalid packet length or DVI command in packet");
+ /* @<Store the packet being built@>; */
+ set_charinfo_packets(co,vpackets);
+ vf_byte(cmd);
+ }
+ if (cmd != post)
+ bad_vf("POST command expected");
+
+ xfree(vf_buffer);
+}
+
+#define make_command0(N,K) { \
+ lua_newtable(L); \
+ lua_pushstring(L, N); \
+ lua_rawseti(L,-2, 1); \
+ lua_rawseti(L,-2, K); \
+ K++; }
+
+#define make_command1(N,V,K) { \
+ lua_newtable(L); \
+ lua_pushstring(L, N); \
+ lua_rawseti(L,-2, 1); \
+ lua_pushnumber(L, V); \
+ lua_rawseti(L,-2, 2); \
+ lua_rawseti(L,-2, K); \
+ K++; }
+
+#define make_command2(N,V,W,K) { \
+ lua_newtable(L); \
+ lua_pushstring(L, N); \
+ lua_rawseti(L,-2, 1); \
+ lua_pushnumber(L, V); \
+ lua_rawseti(L,-2, 2); \
+ lua_pushnumber(L, W); \
+ lua_rawseti(L,-2, 3); \
+ lua_rawseti(L,-2, K); \
+ K++; }
+
+#define make_commands(N,S,V,K) { \
+ lua_newtable(L); \
+ lua_pushstring(L, N); \
+ lua_rawseti(L,-2, 1); \
+ lua_pushlstring(L, S, V); \
+ lua_rawseti(L,-2, 2); \
+ lua_rawseti(L,-2, K); \
+ K++; }
+
+
+int
+make_vf_table(lua_State *L, char *cnom, scaled atsize) {
+ integer cmd, k, i;
+ integer cc, cmd_length, packet_length;
+ scaled tfm_width;
+ vf_stack_index stack_level;
+ integer vf_z; /* multiplier */
+ integer vf_alpha; /* correction for negative values */
+ char vf_beta; /* divisor */
+ char *s;
+ scaled h,v;
+ scaled w, x, y, z;
+ integer s_top; /* lua stack */
+ integer vf_nf ; /* local font counter */
+ scaled ds,fs;
+ four_quarters cs;
+ memory_word tmp_w; /* accumulator */
+ vf_stack_record vf_stack[256];
+ unsigned char *vf_buffer;
+ integer vf_size;
+ integer vf_cur;
+
+
+ stack_level = 0;
+ /* @<Open |vf_file|, return if not found@>; */
+ vf_cur=0; vf_buffer=NULL; vf_size=0;
+ if (!open_vf_file(cnom, &vf_buffer, &vf_size)) {
+ lua_pushnil(L);
+ return 1;
+ }
+
+ /* start by creating a table */
+ s_top = lua_gettop(L);
+ lua_newtable(L);
+
+ /* @<Process the preamble@>;@/ */
+ vf_byte(k);
+ if (k != pre)
+ lua_bad_vf("PRE command expected");
+ vf_byte(k);
+ if (k != vf_id)
+ lua_bad_vf("wrong id byte");
+ vf_byte(cmd_length);
+
+ s = xmalloc(cmd_length);
+ for (k = 1;k<= cmd_length;k++)
+ vf_byte(s[(k-1)]);
+
+ lua_pushlstring(L,s,cmd_length);
+ free(s);
+ lua_setfield(L,-2,"header");
+
+ vf_byte(cs.b0); vf_byte(cs.b1); vf_byte(cs.b2); vf_byte(cs.b3);
+ lua_pushnumber(L, (unsigned long)(cs.b0<<24)+(cs.b1<<16)+(cs.b2<<8)+cs.b3 );
+ lua_setfield(L,-2,"checksum");
+
+ vf_read(4,k);
+ ds = k /16;
+ lua_pushinteger(L,ds);
+ lua_setfield(L,-2,"designsize");
+
+
+ lua_pushstring(L,cnom);
+ lua_setfield(L,-2,"name");
+
+ lua_pushinteger(L,atsize);
+ lua_setfield(L,-2,"size");
+
+
+ /* update_terminal;*/
+ vf_z = atsize;
+ vf_replace_z();
+ /* @<Process the font definitions@>;@/ */
+ vf_byte(cmd);
+ lua_newtable(L);
+
+ i = 1;
+ while ((cmd >= fnt_def1) && (cmd <= fnt_def1 + 3)) {
+
+ lua_newtable(L);
+ vf_read_u((cmd - fnt_def1 + 1),vf_nf);
+ vf_nf++;
+ /* checksum */
+ vf_byte(cs.b0); vf_byte(cs.b1); vf_byte(cs.b2); vf_byte(cs.b3);
+
+ vf_read(4,k);
+ fs = sqxfw(k, atsize);
+ lua_pushstring(L,"size");
+ lua_pushnumber(L,fs);
+ lua_rawset(L,-3);
+
+ vf_read(4,k);
+ ds = k / 16; /* dsize, not used */
+
+ vf_byte(tmp_b0);
+ vf_byte(tmp_b1);
+ while (tmp_b0 > 0) { tmp_b0--; vf_byte(k); } /* skip the font path */
+
+ s = xmalloc(tmp_b1+1); k = 0;
+ while (tmp_b1-- > 0)
+ vf_byte(s[k++]);
+ s[k]=0;
+ lua_pushstring(L,"name");
+ lua_pushstring(L,xstrdup(s));
+ free(s);
+ lua_rawset(L,-3);
+
+ lua_rawseti(L,-2,vf_nf);
+ i++;
+ vf_byte(cmd);
+ }
+
+ if (i>1) {
+ lua_setfield(L,-2,"fonts");
+ } else {
+ lua_pop(L,1);
+ }
+
+ lua_newtable(L); /* 'characters' */
+ while (cmd <= long_char) {
+ /* @<Build a character packet@>;@/ */
+ if (cmd == long_char) {
+ vf_read_u(4,packet_length);
+ vf_read_u(4,cc);
+ vf_read(4,tfm_width);
+ } else {
+ packet_length = cmd;
+ vf_byte(cc);
+ vf_read(3,tfm_width);
+ }
+ if (packet_length < 0)
+ lua_bad_vf("negative packet length");
+
+ lua_newtable(L); /* for this character */
+
+ lua_pushnumber(L,tfm_width);
+ lua_setfield(L,-2,"width");
+
+ lua_newtable(L); /* for 'commands' */
+
+ k = 1; vf_nf = 0;
+ w = 0; x = 0; y = 0; z = 0;
+ while (packet_length > 0) {
+ vf_byte(cmd);
+ decr(packet_length);
+
+ if ((cmd >= set_char_0) && (cmd < set1)) {
+ if (vf_nf == 0) {
+ vf_nf = 1;
+ make_command1("font",vf_nf,k);
+ }
+ make_command1("char",cmd,k);
+
+ } else if (((fnt_num_0 <= cmd) && (cmd <= fnt_num_0 + 63)) ||
+ ((fnt1 <= cmd) && (cmd <= fnt1 + 3))) {
+ if (cmd >= fnt1) {
+ vf_read_u((cmd - fnt1 + 1),vf_nf); vf_nf++;
+ packet_length -= (cmd - fnt1 + 1);
+ } else {
+ vf_nf = cmd - fnt_num_0 + 1;
+ }
+ make_command1("font",vf_nf,k);
+ } else {
+ switch (cmd) {
+ case set_rule:
+ vf_read(4,h); vf_read(4,v);
+ make_command2("rule",sqxfw(h,atsize),sqxfw(v,atsize),k);
+ packet_length -= 8;
+ break;
+ case put_rule:
+ vf_read(4,h); vf_read(4,v);
+ make_command0("push",k);
+ make_command2("rule",sqxfw(h,atsize),sqxfw(v,atsize),k);
+ make_command0("pop",k);
+ packet_length -= 8;
+ break;
+ case set1:
+ case set2:
+ case set3:
+ case set4:
+ if (vf_nf == 0) {
+ vf_nf = 1;
+ make_command1("font",vf_nf,k);
+ }
+ vf_read_u((cmd - set1 + 1),i);
+ make_command1("char",i,k);
+ packet_length -= (cmd - set1 + 1);
+ break;
+ case put1:
+ case put2:
+ case put3:
+ case put4:
+ if (vf_nf == 0) {
+ vf_nf = 1;
+ make_command1("font",vf_nf,k);
+ }
+ vf_read_u((cmd - put1 + 1),i);
+ make_command0("push",k);
+ make_command1("char",i,k);
+ make_command0("pop",k);
+ packet_length -= (cmd - put1 + 1);
+ break;
+ case right1:
+ case right2:
+ case right3:
+ case right4:
+ vf_read((cmd - right1 + 1),i);
+ make_command1("right",sqxfw(i,atsize),k);
+ packet_length -= (cmd - right1 + 1);
+ break;
+ case w1:
+ case w2:
+ case w3:
+ case w4:
+ vf_read((cmd - w1 + 1),w);
+ make_command1("right",sqxfw(w,atsize),k);
+ packet_length -= (cmd - w1 + 1);
+ break;
+ case x1:
+ case x2:
+ case x3:
+ case x4:
+ vf_read((cmd - x1 + 1),x);
+ make_command1("right",sqxfw(x,atsize),k);
+ packet_length -= (cmd - x1 + 1);
+ break;
+ case down1:
+ case down2:
+ case down3:
+ case down4:
+ vf_read((cmd - down1 + 1),i);
+ make_command1("down",sqxfw(i,atsize),k);
+ packet_length -= (cmd - down1 + 1);
+ break;
+ case y1:
+ case y2:
+ case y3:
+ case y4:
+ vf_read((cmd - y1 + 1),y);
+ make_command1("down",sqxfw(y,atsize),k);
+ packet_length -= (cmd - y1 + 1);
+ break;
+ case z1:
+ case z2:
+ case z3:
+ case z4:
+ vf_read((cmd - z1 + 1),z);
+ make_command1("down",sqxfw(z,atsize),k);
+ packet_length -= (cmd - z1 + 1);
+ break;
+ case xxx1:
+ case xxx2:
+ case xxx3:
+ case xxx4:
+ vf_read_u((cmd - xxx1 + 1),cmd_length);
+ packet_length -= (cmd - xxx1 + 1);
+ if (cmd_length <= 0)
+ lua_bad_vf("special of negative length");
+ packet_length -= cmd_length;
+
+ s = xmalloc(cmd_length+1); i = 0;
+ while (cmd_length > 0) {
+ cmd_length--;
+ vf_byte(s[i]);
+ i++;
+ }
+ s[i]=0;
+ make_commands("special",strdup(s),i,k);
+ free(s);
+ break;
+ case w0:
+ make_command1("right",sqxfw(w,atsize),k);
+ break;
+ case x0:
+ make_command1("right",sqxfw(x,atsize),k);
+ break;
+ case y0:
+ make_command1("down",sqxfw(y,atsize),k);
+ break;
+ case z0:
+ make_command1("down",sqxfw(z,atsize),k);
+ break;
+ case nop:
+ break;
+ case push:
+ if (stack_level == vf_stack_size) {
+ overflow_string("virtual font stack size", vf_stack_size);
+ } else {
+ vf_stack[stack_level].stack_w = w;
+ vf_stack[stack_level].stack_x = x;
+ vf_stack[stack_level].stack_y = y;
+ vf_stack[stack_level].stack_z = z;
+ incr(stack_level);
+ make_command0("push",k);
+ }
+ break;
+ case pop:
+ if (stack_level == 0) {
+ lua_bad_vf("more POPs than PUSHs in character");
+ } else {
+ decr(stack_level);
+ w = vf_stack[stack_level].stack_w;
+ x = vf_stack[stack_level].stack_x;
+ y = vf_stack[stack_level].stack_y;
+ z = vf_stack[stack_level].stack_z;
+ make_command0("pop",k);
+ }
+ break;
+ default:
+ lua_bad_vf("improver DVI command");
+ }
+ }
+ }
+ /* signal end of packet */
+ lua_setfield(L,-2,"commands");
+
+ if (stack_level != 0)
+ lua_bad_vf("more PUSHs than POPs in character packet");
+ if (packet_length != 0)
+ lua_bad_vf("invalid packet length or DVI command in packet");
+
+ lua_rawseti(L,-2,cc);
+
+ vf_byte(cmd);
+ }
+ lua_setfield(L,-2,"characters");
+
+ if (cmd != post)
+ lua_bad_vf("POST command expected");
+ xfree(vf_buffer);
+ return 1;
+}
+
+
+extern void replace_packet_fonts(internal_font_number f, integer *old_fontid, integer *new_fontid, int count) ;
+extern integer *packet_local_fonts(internal_font_number f, integer *num);
+extern internal_font_number auto_expand_font (internal_font_number f, integer e) ;
+
+
+/* This function is called from |do_vf|, and fixes up the virtual data
+ inside an auto-expanded virtual font */
+
+boolean
+auto_expand_vf(internal_font_number f) {
+
+ internal_font_number bf;
+ integer e, k;
+ integer *vf_old_fonts, *vf_new_fonts;
+ integer num = 0;
+
+ if ((! pdf_font_auto_expand(f)) || (pdf_font_blink(f) == null_font))
+ return false ; /* not an auto-expanded font */
+ bf = pdf_font_blink(f);
+
+ if (font_type(bf) != virtual_font_type)
+ return false; /* not a virtual font */
+
+ e = pdf_font_expand_ratio(f);
+
+ vf_old_fonts = packet_local_fonts(bf,&num);
+ if (num>0) {
+ vf_new_fonts = xmalloc(num*sizeof(integer));
+ for (k=0;k<num;k++) {
+ vf_new_fonts[k] = auto_expand_font(vf_old_fonts[k], e);
+ copy_expand_params(vf_new_fonts[k], vf_old_fonts[k], e);
+ }
+ replace_packet_fonts(f,vf_old_fonts,vf_new_fonts,num);
+ xfree(vf_new_fonts);
+ xfree(vf_old_fonts);
+ }
+ set_font_type(f,virtual_font_type);
+ return true;
+}
+
+/* this function is not always safe, because it needs makecstring() */
+str_number
+expand_font_name (internal_font_number f, integer e) {
+ int old_setting;
+ old_setting=selector;
+ selector=new_string;
+ print_string(font_name(f));
+ if (e > 0) {
+ print_char('+');
+ }
+ print_int(e);
+ selector=old_setting;
+ return make_string();
+}
+
+
+internal_font_number
+auto_expand_font (internal_font_number f, integer e) {
+ internal_font_number k;
+ kerninfo *krn;
+ charinfo *co, *ci;
+ char *fn;
+ integer i;
+ scaled w;
+ k = copy_font(f);
+ i = strlen(font_name(f))+12;
+ fn = xmalloc(i);
+ snprintf(fn,i,"%s%s%d",font_name(f),(e>0 ? "+" : ""), (int)e);
+ set_font_name(k,fn);
+ for (i = font_bc(k);i<=font_ec(k);i++) {
+ if (char_exists(k,i)) {
+ co = get_charinfo(k,i);
+ w = round_xn_over_d(char_width(f,i), 1000 + e, 1000);
+ set_charinfo_width (co, w);
+ w = round_xn_over_d(char_italic(f,i), 1000 + e, 1000);
+ set_charinfo_italic(co, w);
+ krn = get_charinfo_kerns(co);
+ if (krn != NULL) {
+ while (!kern_end((*krn))) {
+ kern_kern(*krn) = round_xn_over_d(kern_kern(*krn), 1000 + e, 1000);
+ krn++;
+ }
+ }
+ }
+ }
+ return k;
+}
+
+void
+vf_expand_local_fonts(internal_font_number f) {
+ internal_font_number lf;
+ integer k, num;
+ integer *vf_old_fonts;
+ pdfassert(font_type(f) == virtual_font_type);
+ num = 0;
+ vf_old_fonts = packet_local_fonts(f,&num);
+ if (num>0) {
+ for (k = 0;k<num;k++) {
+ lf = vf_old_fonts[k];
+ set_expand_params(lf, pdf_font_auto_expand(f),
+ pdf_font_expand_ratio(pdf_font_stretch(f)),
+ -pdf_font_expand_ratio(pdf_font_shrink(f)),
+ pdf_font_step(f), pdf_font_expand_ratio(f));
+ if (font_type(lf) == virtual_font_type)
+ vf_expand_local_fonts(lf);
+ }
+ xfree(vf_old_fonts);
+ }
+}
+
+internal_font_number
+letter_space_font (halfword u, internal_font_number f, integer e) {
+ internal_font_number k;
+ scaled w, r;
+
+ char *new_font_name;
+ integer vf_z;
+ integer vf_alpha;
+ integer vf_beta;
+ memory_word tmp_w; /* accumulator */
+
+
+ /* read a new font and expand the character widths */
+ k = read_font_info(u, tex_font_name(f), get_nullstr(), font_size(f), font_natural_dir(f));
+ set_no_ligatures(k); /* disable ligatures for letter-spaced fonts */
+/*
+ for (i = 0;i <= font_widths(k);i++) {
+ set_font_width(k,i,font_width(f,i)+round_xn_over_d(quad(k), e, 1000));
+ }
+*/
+ /* append eg '+100ls' to font name */
+ new_font_name = xmalloc(strlen(font_name(k)) + 8); /* |abs(e) <= 1000| */
+ if (e > 0) {
+ sprintf(new_font_name,"%s+%ils",font_name(k),(int)e);
+ } else {
+ /* minus from %i */
+ sprintf(new_font_name,"%s%ils",font_name(k),(int)e);
+ }
+ set_font_name(k, new_font_name);
+
+ /* create the corresponding virtual font */
+ set_font_type(k,virtual_font_type);
+
+ vf_z = font_size(f);
+ vf_replace_z();
+ w = round_xn_over_d(quad(f), e, 2000);
+ if (w > 0) {
+ tmp_b0 = 0;
+ } else {
+ tmp_b0 = 255;
+ w = vf_alpha + w;
+ }
+ r = w*vf_beta;
+ tmp_b1 = r / vf_z;
+ r = r % vf_z;
+ if (r == 0) {
+ tmp_b2 = 0;
+ } else {
+ r = r * 256;
+ tmp_b2 = r / vf_z;
+ r = r % vf_z;
+ }
+ if (r == 0) {
+ tmp_b3 = 0;
+ } else {
+ r = r * 256;
+ tmp_b3 = r / vf_z;
+ }
+ /*
+ vf_packet_base[k] = new_vf_packet(k);
+
+ for (c=font_bc(k);c<=font_ec(k);c++) {
+ string_room(17);
+ append_fnt_set(f);
+ append_packet(right1 + 3);
+ append_packet(tmp_b0);
+ append_packet(tmp_b1);
+ append_packet(tmp_b2);
+ append_packet(tmp_b3);
+
+ append_packet(set1);
+ append_packet(c);
+
+ append_packet(right1 + 3);
+ append_packet(tmp_b0);
+ append_packet(tmp_b1);
+ append_packet(tmp_b2);
+ append_packet(tmp_b3);
+ s = make_string();
+ store_packet(k, c, s);
+ flush_str(s);
+ }
+*/
+ return k;
+}
+
+
diff --git a/Build/source/texk/web2c/luatexdir/font/vfpacket.c b/Build/source/texk/web2c/luatexdir/font/vfpacket.c
new file mode 100644
index 00000000000..4d8445f2227
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/vfpacket.c
@@ -0,0 +1,377 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: vfpacket.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+
+/*
+ The |do_vf_packet| procedure is called in order to interpret the
+ character packet for a virtual character. Such a packet may contain
+ the instruction to typeset a character from the same or an other
+ virtual font; in such cases |do_vf_packet| calls itself
+ recursively. The recursion level, i.e., the number of times this has
+ happened, is kept in the global variable |packet_cur_s| and should
+ not exceed |packet_max_recursion|.
+*/
+
+#define packet_max_recursion 100
+
+typedef unsigned char packet_stack_index ; /* an index into the stack */
+
+typedef struct packet_stack_record {
+ scaled stack_h;
+ scaled stack_v;
+} packet_stack_record;
+
+
+static packet_stack_index packet_cur_s = 0; /* current recursion level */
+static packet_stack_record packet_stack [packet_max_recursion];
+static packet_stack_index packet_stack_ptr = 0; /* pointer into |packet_stack| */
+
+
+/* Some macros for processing character packets. */
+
+#define do_packet_byte() vf_packets[cur_packet_byte++]
+
+#define packet_number(fw) { \
+ fw = do_packet_byte(); \
+ fw = fw*256 + do_packet_byte(); \
+ fw = fw*256 + do_packet_byte(); \
+ fw = fw*256 + do_packet_byte(); }
+
+#define packet_scaled(a,fs) { integer fw; \
+ fw = do_packet_byte(); \
+ if (fw>127) fw = fw - 256; \
+ fw = fw*256 + do_packet_byte(); \
+ fw = fw*256 + do_packet_byte(); \
+ fw = fw*256 + do_packet_byte(); \
+ a = sqxfw(fw, fs); }
+
+
+/* count the number of bytes in a command packet */
+int
+vf_packet_bytes (charinfo *co) {
+ real_eight_bits *vf_packets;
+ integer cur_packet_byte;
+ unsigned k;
+ int cmd;
+
+ vf_packets = get_charinfo_packets(co);
+ if (vf_packets == NULL) {
+ return 0;
+ }
+ cur_packet_byte = 0;
+ while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) {
+ cur_packet_byte++;
+ switch (cmd) {
+ case packet_char_code:
+ case packet_font_code:
+ case packet_right_code:
+ case packet_down_code:
+ case packet_node_code:
+ cur_packet_byte += 4;
+ break;
+ case packet_push_code:
+ case packet_pop_code:
+ break;
+ case packet_rule_code:
+ cur_packet_byte += 8;
+ break;
+ case packet_special_code:
+ packet_number(k); /* +4 */
+ cur_packet_byte += k;
+ break;
+ case packet_nop_code:
+ break;
+ default:
+ pdf_error("vf", "invalid DVI command");
+ }
+ };
+ return (cur_packet_byte +1);
+}
+
+
+/* typeset the \.{DVI} commands in the
+ character packet for character |c| in current font |f| */
+
+char *packet_command_names[] = {
+ "char", "font","pop", "push", "special",
+ "right","down","rule","node", "nop","end", NULL};
+
+
+void
+do_vf_packet (internal_font_number vf_f, integer c) {
+ internal_font_number lf;
+ charinfo *co;
+ scaled save_cur_h, save_cur_v;
+ real_eight_bits *vf_packets;
+ integer cur_packet_byte;
+ integer cmd, fs_f;
+ scaled i;
+ unsigned k;
+ str_number s;
+
+ packet_cur_s++;
+ if (packet_cur_s >= packet_max_recursion)
+ overflow_string("max level recursion of virtual fonts", packet_max_recursion);
+ save_cur_v = cur_v;
+ save_cur_h = cur_h;
+
+ lf = 0; /* for -Wall */
+ co = get_charinfo(vf_f,c);
+ vf_packets = get_charinfo_packets(co);
+ if (vf_packets == NULL) {
+ packet_cur_s--;
+ return ;
+ }
+ cur_packet_byte = 0;
+ fs_f = font_size(vf_f);
+ while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) {
+ cur_packet_byte++;
+ /*
+ if (cmd>packet_end_code) {
+ fprintf(stdout, "do_vf_packet(%i,%i) command code = illegal \n", vf_f,c);
+ } else {
+ fprintf(stdout, "do_vf_packet(%i,%i) command code = %s\n",vf_f, c, packet_command_names[cmd]);
+ }
+ */
+ switch (cmd) {
+ case packet_font_code:
+ packet_number(lf);
+ break;
+ case packet_push_code:
+ packet_stack[packet_stack_ptr].stack_h = cur_h;
+ packet_stack[packet_stack_ptr].stack_v = cur_v;
+ packet_stack_ptr++;
+ break;
+ case packet_pop_code:
+ packet_stack_ptr--;
+ cur_h = packet_stack[packet_stack_ptr].stack_h;
+ cur_v = packet_stack[packet_stack_ptr].stack_v;
+ break;
+ case packet_char_code:
+ packet_number(k);
+ if (!char_exists(lf,k)) {
+ char_warning(lf, k);
+ } else {
+ output_one_char(lf, k);
+ }
+ cur_h = cur_h + char_width(lf,k);
+ break;
+ case packet_rule_code:
+ packet_scaled(rule_ht,fs_f);
+ packet_scaled(rule_wd,fs_f);
+ if ((rule_wd > 0) && (rule_ht > 0)) {
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ cur_h = cur_h + rule_wd;
+ }
+ break;
+ case packet_right_code:
+ packet_scaled(i,fs_f);
+ cur_h = cur_h + i;
+ break;
+ case packet_down_code:
+ packet_scaled(i,fs_f);
+ cur_v = cur_v + i;
+ break;
+ case packet_special_code:
+ packet_number(k);
+ string_room(k);
+ while (k > 0) {
+ k--;
+ append_pool_char(do_packet_byte());
+ }
+ s = make_string();
+ literal(s, scan_special, false);
+ flush_str(s);
+ break;
+ case packet_node_code:
+ packet_number(k);
+ temp_ptr = k;
+ pdf_hlist_out();
+ break;
+ case packet_nop_code:
+ break;
+ default:
+ pdf_error("vf", "invalid DVI command");
+ }
+ };
+ cur_h = save_cur_h;
+ cur_v = save_cur_v;
+ packet_cur_s--;
+}
+
+
+integer *packet_local_fonts(internal_font_number f, integer *num) {
+ int c, cmd, cur_packet_byte, lf, k,l, i;
+ integer localfonts[256] = {0};
+ integer *lfs;
+ charinfo *co;
+
+ real_eight_bits *vf_packets;
+ k = 0;
+ for (c = font_bc(f);c <= font_ec(f);c++) {
+ if (char_exists(f,c)) {
+ co = get_charinfo(f,c);
+ vf_packets = get_charinfo_packets(co);
+ if (vf_packets == NULL)
+ continue;
+ cur_packet_byte = 0;
+ while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) {
+ cur_packet_byte++;
+ switch (cmd) {
+ case packet_font_code:
+ packet_number(lf);
+ for (l=0;l<k;l++) {
+ if (localfonts[l]==lf) {
+ break;
+ }
+ }
+ if (l==k) {
+ localfonts[k++]=lf;
+ }
+ break;
+ case packet_push_code:
+ case packet_pop_code:
+ case packet_nop_code:
+ break;
+ case packet_char_code:
+ case packet_right_code:
+ case packet_down_code:
+ case packet_node_code:
+ cur_packet_byte+=4;
+ break;
+ case packet_rule_code:
+ cur_packet_byte+=8;
+ break;
+ case packet_special_code:
+ packet_number(i);
+ while (i-- > 0)
+ (void)do_packet_byte();
+ break;
+ default:
+ pdf_error("vf", "invalid DVI command");
+ }
+ }
+ }
+ }
+ *num = k;
+ if (k>0) {
+ lfs = xmalloc (k*sizeof(integer));
+ memcpy(lfs,localfonts,k*sizeof(integer));
+ return lfs;
+ }
+ return NULL;
+}
+
+
+void
+replace_packet_fonts(internal_font_number f, integer *old_fontid, integer *new_fontid, int count) {
+ int c, cmd, cur_packet_byte, lf, k,l;
+ charinfo *co;
+ real_eight_bits *vf_packets;
+
+ k = 0;
+ for (c = font_bc(f);c <= font_ec(f);c++) {
+ if (char_exists(f,c)) {
+ co = get_charinfo(f,c);
+ vf_packets = get_charinfo_packets(co);
+ if (vf_packets == NULL)
+ continue;
+ cur_packet_byte = 0;
+ while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) {
+ cur_packet_byte++;
+ switch (cmd) {
+ case packet_font_code:
+ packet_number(lf);
+ for (l=0;l<count;l++) {
+ if (old_fontid[l]==lf) {
+ break;
+ }
+ }
+ if(l<count) {
+ k = new_fontid[l];
+ vf_packets[(cur_packet_byte-4)] = (k&0xFF000000)>>24;
+ vf_packets[(cur_packet_byte-3)] = (k&0x00FF0000)>>16;
+ vf_packets[(cur_packet_byte-2)] = (k&0x0000FF00)>>8;
+ vf_packets[(cur_packet_byte-1)] = (k&0x000000FF);
+ }
+ break;
+ case packet_push_code:
+ case packet_pop_code:
+ case packet_nop_code:
+ break;
+ case packet_char_code:
+ case packet_right_code:
+ case packet_down_code:
+ case packet_node_code:
+ cur_packet_byte+=4;
+ break;
+ case packet_rule_code:
+ cur_packet_byte+=8;
+ break;
+ case packet_special_code:
+ packet_number(k);
+ while (k-- > 0)
+ (void)do_packet_byte();
+ break;
+ default:
+ pdf_error("vf", "invalid DVI command");
+ }
+ }
+ }
+ }
+}
+
+/* this function was copied/borrowed/stolen from dvipdfm code */
+
+scaled sqxfw (scaled sq, integer fw)
+{
+ int sign = 1;
+ unsigned long a, b, c, d, ad, bd, bc, ac;
+ unsigned long e, f, g, h, i, j, k;
+ unsigned long result;
+ /* Make positive. */
+ if (sq < 0) {
+ sign = -sign;
+ sq = -sq;
+ }
+ if (fw < 0) {
+ sign = -sign;
+ fw = -fw;
+ }
+ a = ((unsigned long) sq) >> 16u;
+ b = ((unsigned long) sq) & 0xffffu;
+ c = ((unsigned long) fw) >> 16u;
+ d = ((unsigned long) fw) & 0xffffu;
+ ad = a*d; bd = b*d; bc = b*c; ac = a*c;
+ e = bd >> 16u;
+ f = ad >> 16u;
+ g = ad & 0xffffu;
+ h = bc >> 16u;
+ i = bc & 0xffffu;
+ j = ac >> 16u;
+ k = ac & 0xffffu;
+ result = (e+g+i + (1<<3)) >> 4u; /* 1<<3 is for rounding */
+ result += (f+h+k) << 12u;
+ result += j << 28u;
+ return (sign>0)?result:-result;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/writecff.c b/Build/source/texk/web2c/luatexdir/font/writecff.c
new file mode 100644
index 00000000000..69c35c6950e
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writecff.c
@@ -0,0 +1,3381 @@
+/*
+Copyright (c) 2007 Taco Hoekwater, taco@luatex.org
+
+This file is part of luaTeX.
+
+luaTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+luaTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with luaTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writecff.c 1021 2008-02-14 10:24:34Z taco $
+*/
+
+#include "ptexlib.h"
+
+#include "writecff.h"
+
+#define get_offset(s,n) get_unsigned(s, (n))
+#define get_card8(a) a->stream[a->offset++]
+#define get_card16(a) get_unsigned(a,2)
+
+#undef b0
+#undef b1
+#undef b2
+#undef b3
+
+#define WORK_BUFFER_SIZE 1024
+
+static char work_buffer[WORK_BUFFER_SIZE];
+
+static unsigned long get_unsigned (cff_font *cff, int n)
+{
+ unsigned long v = 0;
+ while (n-- > 0)
+ v = v*256 + get_card8(cff);
+ return v;
+}
+
+#define CFF_ERROR pdftex_fail
+#define WARN pdftex_warn
+
+
+const char *const cff_stdstr[CFF_STDSTR_MAX] = {
+ ".notdef", "space", "exclam", "quotedbl", "numbersign",
+ "dollar", "percent", "ampersand", "quoteright", "parenleft",
+ "parenright", "asterisk", "plus", "comma", "hyphen",
+ "period", "slash", "zero", "one", "two",
+ "three", "four", "five", "six", "seven",
+ "eight", "nine", "colon", "semicolon", "less",
+ "equal", "greater", "question", "at", "A",
+ "B", "C", "D", "E", "F",
+ "G", "H", "I", "J", "K",
+ "L", "M", "N", "O", "P",
+ "Q", "R", "S", "T", "U",
+ "V", "W", "X", "Y", "Z",
+ "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
+ "quoteleft", "a", "b", "c", "d",
+ "e", "f", "g", "h", "i",
+ "j", "k", "l", "m", "n",
+ "o", "p", "q", "r", "s",
+ "t", "u", "v", "w", "x",
+ "y", "z", "braceleft", "bar", "braceright",
+ "asciitilde", "exclamdown", "cent", "sterling", "fraction",
+ "yen", "florin", "section", "currency", "quotesingle",
+ "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi",
+ "fl", "endash", "dagger", "daggerdbl", "periodcentered",
+ "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright",
+ "guillemotright", "ellipsis", "perthousand", "questiondown", "grave",
+ "acute", "circumflex", "tilde", "macron", "breve",
+ "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut",
+ "ogonek", "caron", "emdash", "AE", "ordfeminine",
+ "Lslash", "Oslash", "OE", "ordmasculine", "ae",
+ "dotlessi", "lslash", "oslash", "oe", "germandbls",
+ "onesuperior", "logicalnot", "mu", "trademark", "Eth",
+ "onehalf", "plusminus", "Thorn", "onequarter", "divide",
+ "brokenbar", "degree", "thorn", "threequarters", "twosuperior",
+ "registered", "minus", "eth", "multiply", "threesuperior",
+ "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave",
+ "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex",
+ "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis",
+ "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis",
+ "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex",
+ "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron",
+ "aacute", "acircumflex", "adieresis", "agrave", "aring",
+ "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis",
+ "egrave", "iacute", "icircumflex", "idieresis", "igrave",
+ "ntilde", "oacute", "ocircumflex", "odieresis", "ograve",
+ "otilde", "scaron", "uacute", "ucircumflex", "udieresis",
+ "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall",
+ "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall",
+ "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "zerooldstyle",
+ "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle",
+ "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior",
+ "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior",
+ "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior",
+ "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior",
+ "tsuperior", "ff", "ffi", "ffl", "parenleftinferior",
+ "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall",
+ "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall",
+ "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall",
+ "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall",
+ "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
+ "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall",
+ "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall",
+ "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall",
+ "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash",
+ "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall",
+ "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird",
+ "twothirds", "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior",
+ "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior",
+ "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior",
+ "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior",
+ "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall",
+ "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall",
+ "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall",
+ "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall",
+ "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall",
+ "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall",
+ "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall",
+ "001.000", "001.001", "001.002", "001.003",
+ "Black", "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold"
+};
+
+
+/* Only read header part but not body */
+cff_index *
+cff_get_index_header (cff_font *cff)
+{
+ cff_index *idx;
+ card16 i, count;
+
+ idx = xcalloc(1, sizeof(cff_index));
+
+ idx->count = count = get_card16(cff);
+ if (count > 0) {
+ idx->offsize = get_card8(cff);
+ if (idx->offsize < 1 || idx->offsize > 4)
+ CFF_ERROR("invalid offsize data");
+
+ idx->offset = xcalloc(count+1, sizeof(l_offset));
+ for (i=0;i<count+1;i++) {
+ (idx->offset)[i] = get_offset(cff, idx->offsize);
+ }
+
+ if (idx->offset[0] != 1)
+ CFF_ERROR("cff_get_index(): invalid index data");
+
+ idx->data = NULL;
+ } else {
+ idx->offsize = 0;
+ idx->offset = NULL;
+ idx->data = NULL;
+ }
+
+ return idx;
+}
+
+
+
+cff_index *
+cff_get_index (cff_font *cff)
+{
+ cff_index *idx;
+ card16 i, count;
+ long length;
+
+ idx = xcalloc(1,sizeof(cff_index));
+
+ idx->count = count = get_card16(cff);
+ if (count > 0) {
+ idx->offsize = get_card8(cff);
+ if (idx->offsize < 1 || idx->offsize > 4)
+ CFF_ERROR("invalid offsize data");
+
+ idx->offset = xcalloc((count + 1),sizeof(l_offset));
+ for (i = 0 ; i < count + 1; i++) {
+ idx->offset[i] = get_offset(cff, idx->offsize);
+ }
+
+ if (idx->offset[0] != 1)
+ CFF_ERROR("Invalid CFF Index offset data");
+
+ length = idx->offset[count] - idx->offset[0];
+
+ idx->data = xcalloc(length,sizeof(card8));
+ memcpy(idx->data,&cff->stream[cff->offset],length);
+ cff->offset += length;
+
+ } else {
+ idx->offsize = 0;
+ idx->offset = NULL;
+ idx->data = NULL;
+ }
+ return idx;
+}
+
+
+long
+cff_pack_index (cff_index *idx, card8 *dest, long destlen)
+{
+ long len = 0;
+ unsigned long datalen;
+ card16 i;
+
+ if (idx->count < 1) {
+ if (destlen < 2)
+ CFF_ERROR("Not enough space available...");
+ memset(dest, 0, 2);
+ return 2;
+ }
+
+ len = cff_index_size(idx);
+ datalen = idx->offset[idx->count] - 1;
+
+ if (destlen < len)
+ CFF_ERROR("Not enough space available...");
+
+ *(dest++) = (idx->count >> 8) & 0xff;
+ *(dest++) = idx->count & 0xff;
+
+ if (datalen < 0xffUL) {
+ idx->offsize = 1;
+ *(dest++) = 1;
+ for (i = 0; i <= idx->count; i++) {
+ *(dest++) = (card8) (idx->offset[i] & 0xff);
+ }
+ } else if (datalen < 0xffffUL) {
+ idx->offsize = 2;
+ *(dest++) = 2;
+ for (i = 0; i <= idx->count; i++) {
+ *(dest++) = (card8) ((idx->offset[i] >> 8) & 0xff);
+ *(dest++) = (card8) ( idx->offset[i] & 0xff);
+ }
+ } else if (datalen < 0xffffffUL) {
+ idx->offsize = 3;
+ *(dest++) = 3;
+ for (i = 0; i <= idx->count; i++) {
+ *(dest++) = (card8)((idx->offset[i] >> 16) & 0xff);
+ *(dest++) = (card8)((idx->offset[i] >> 8) & 0xff);
+ *(dest++) = (card8)(idx->offset[i] & 0xff);
+ }
+ } else {
+ idx->offsize = 4;
+ *(dest++) = 4;
+ for (i = 0; i <= idx->count; i++) {
+ *(dest++) = (card8)((idx->offset[i] >> 24) & 0xff);
+ *(dest++) = (card8)((idx->offset[i] >> 16) & 0xff);
+ *(dest++) = (card8)((idx->offset[i] >> 8) & 0xff);
+ *(dest++) = (card8)(idx->offset[i] & 0xff);
+ }
+ }
+
+ memmove(dest, idx->data, idx->offset[idx->count] - 1);
+
+ return len;
+}
+
+long
+cff_index_size (cff_index *idx)
+{
+ if (idx->count > 0) {
+ l_offset datalen;
+
+ datalen = idx->offset[idx->count] - 1;
+ if (datalen < 0xffUL) {
+ idx->offsize = 1;
+ } else if (datalen < 0xffffUL) {
+ idx->offsize = 2;
+ } else if (datalen < 0xffffffUL) {
+ idx->offsize = 3;
+ } else {
+ idx->offsize = 4;
+ }
+ return (3 + (idx->offsize)*(idx->count + 1) + datalen);
+ } else {
+ return 2;
+ }
+}
+
+cff_index *cff_new_index (card16 count)
+{
+ cff_index *idx;
+
+ idx = xcalloc(1, sizeof(cff_index));
+ idx->count = count;
+ idx->offsize = 0;
+
+ if (count > 0) {
+ idx->offset = xcalloc(count + 1, sizeof(l_offset));
+ (idx->offset)[0] = 1;
+ } else {
+ idx->offset = NULL;
+ }
+ idx->data = NULL;
+
+ return idx;
+}
+
+
+void cff_release_index (cff_index *idx)
+{
+ if (idx) {
+ xfree(idx->data);
+ xfree(idx->offset);
+ xfree(idx);
+ }
+}
+
+void cff_release_dict (cff_dict *dict)
+{
+ if (dict) {
+ if (dict->entries) {
+ int i;
+ for (i=0;i<dict->count;i++) {
+ xfree((dict->entries)[i].values);
+ }
+ xfree(dict->entries);
+ }
+ xfree(dict);
+ }
+}
+
+
+void cff_release_encoding (cff_encoding *encoding)
+{
+ if (encoding) {
+ switch (encoding->format & (~0x80)) {
+ case 0: xfree(encoding->data.codes); break;
+ case 1: xfree(encoding->data.range1); break;
+ default: CFF_ERROR("Unknown Encoding format.");
+ }
+ if (encoding->format & 0x80)
+ xfree(encoding->supp);
+ xfree(encoding);
+ }
+}
+
+void
+cff_release_charsets (cff_charsets *charset)
+{
+ if (charset) {
+ switch (charset->format) {
+ case 0: xfree(charset->data.glyphs); break;
+ case 1: xfree(charset->data.range1); break;
+ case 2: xfree(charset->data.range2); break;
+ default: break;
+ }
+ xfree(charset);
+ }
+}
+
+void cff_release_fdselect (cff_fdselect *fdselect)
+{
+ if (fdselect) {
+ if (fdselect->format == 0) { xfree(fdselect->data.fds); }
+ else if (fdselect->format == 3) { xfree(fdselect->data.ranges); }
+ xfree(fdselect);
+ }
+}
+
+
+void
+cff_close (cff_font *cff)
+{
+ card16 i;
+
+ if (cff) {
+ if (cff->fontname) xfree(cff->fontname);
+ if (cff->name) cff_release_index(cff->name);
+ if (cff->topdict) cff_release_dict(cff->topdict);
+ if (cff->string) cff_release_index(cff->string);
+ if (cff->gsubr) cff_release_index(cff->gsubr);
+ if (cff->encoding) cff_release_encoding(cff->encoding);
+ if (cff->charsets) cff_release_charsets(cff->charsets);
+ if (cff->fdselect) cff_release_fdselect(cff->fdselect);
+ if (cff->cstrings) cff_release_index(cff->cstrings);
+ if (cff->fdarray) {
+ for (i=0;i<cff->num_fds;i++) {
+ if (cff->fdarray[i]) cff_release_dict(cff->fdarray[i]);
+ }
+ xfree(cff->fdarray);
+ }
+ if (cff->private) {
+ for (i=0;i<cff->num_fds;i++) {
+ if (cff->private[i]) cff_release_dict(cff->private[i]);
+ }
+ xfree(cff->private);
+ }
+ if (cff->subrs) {
+ for (i=0;i<cff->num_fds;i++) {
+ if (cff->subrs[i]) cff_release_index(cff->subrs[i]);
+ }
+ xfree(cff->subrs);
+ }
+ if (cff->_string)
+ cff_release_index(cff->_string);
+ xfree(cff);
+ }
+
+ return;
+}
+
+char *
+cff_get_name (cff_font *cff)
+{
+ char *fontname;
+ l_offset len;
+ cff_index *idx;
+
+ idx = cff->name;
+ len = idx->offset[cff->index + 1] - idx->offset[cff->index];
+ fontname = xmalloc((len + 1)*sizeof(char));
+ memcpy(fontname, idx->data + idx->offset[cff->index] - 1, len);
+ fontname[len] = '\0';
+
+ return fontname;
+}
+
+
+long
+cff_set_name (cff_font *cff, char *name)
+{
+ cff_index *idx;
+
+ if (strlen(name) > 127)
+ CFF_ERROR("FontName string length too large...");
+
+ if (cff->name)
+ cff_release_index(cff->name);
+
+ cff->name = idx = xcalloc(1, sizeof(cff_index));
+ idx->count = 1;
+ idx->offsize = 1;
+ idx->offset = xmalloc(2*sizeof(l_offset));
+ (idx->offset)[0] = 1;
+ (idx->offset)[1] = strlen(name) + 1;
+ idx->data = xcalloc(strlen(name), sizeof(card8));
+ memmove(idx->data, name, strlen(name)); /* no trailing '\0' */
+
+ return 5 + strlen(name);
+}
+
+long
+cff_put_header (cff_font *cff, card8 *dest, long destlen)
+{
+ if (destlen < 4)
+ CFF_ERROR("Not enough space available...");
+
+ *(dest++) = cff->header_major;
+ *(dest++) = cff->header_minor;
+ *(dest++) = 4; /* Additional data in between header and
+ * Name INDEX ignored.
+ */
+ /* We will set all offset (0) to four-byte integer. */
+ *(dest++) = 4;
+ cff->header_offsize = 4;
+
+ return 4;
+}
+
+#define CFF_PARSE_OK 0
+#define CFF_CFF_ERROR_PARSE_CFF_ERROR -1
+#define CFF_CFF_ERROR_STACK_OVERFLOW -2
+#define CFF_CFF_ERROR_STACK_UNDERFLOW -3
+#define CFF_CFF_ERROR_STACK_RANGECHECK -4
+
+#define DICT_ENTRY_MAX 16
+
+cff_dict *cff_new_dict (void)
+{
+ cff_dict *dict;
+
+ dict = xcalloc(1, sizeof(cff_dict));
+ dict->max = DICT_ENTRY_MAX;
+ dict->count = 0;
+ dict->entries = xcalloc(dict->max, sizeof(cff_dict_entry));
+ return dict;
+}
+
+/*
+ * Operand stack:
+ * only numbers are stored (as double)
+ *
+ * Operand types:
+ *
+ * number : double (integer or real)
+ * boolean: stored as a number
+ * SID : stored as a number
+ * array : array of numbers
+ * delta : array of numbers
+ */
+
+#define CFF_DICT_STACK_LIMIT 64
+static int stack_top = 0;
+static double arg_stack[CFF_DICT_STACK_LIMIT];
+
+/*
+ * CFF DICT encoding:
+ * TODO: default values
+ */
+
+#define CFF_LAST_DICT_OP1 22
+#define CFF_LAST_DICT_OP2 39
+#define CFF_LAST_DICT_OP (CFF_LAST_DICT_OP1 + CFF_LAST_DICT_OP2)
+
+static struct {
+ const char *opname;
+ int argtype;
+} dict_operator[CFF_LAST_DICT_OP] = {
+ {"version", CFF_TYPE_SID},
+ {"Notice", CFF_TYPE_SID},
+ {"FullName", CFF_TYPE_SID},
+ {"FamilyName", CFF_TYPE_SID},
+ {"Weight", CFF_TYPE_SID},
+ {"FontBBox", CFF_TYPE_ARRAY},
+ {"BlueValues", CFF_TYPE_DELTA},
+ {"OtherBlues", CFF_TYPE_DELTA},
+ {"FamilyBlues", CFF_TYPE_DELTA},
+ {"FamilyOtherBlues", CFF_TYPE_DELTA},
+ {"StdHW", CFF_TYPE_NUMBER},
+ {"StdVW", CFF_TYPE_NUMBER},
+ {NULL, -1}, /* first byte of two-byte operator */
+ /* Top */
+ {"UniqueID", CFF_TYPE_NUMBER},
+ {"XUID", CFF_TYPE_ARRAY},
+ {"charset", CFF_TYPE_OFFSET},
+ {"Encoding", CFF_TYPE_OFFSET},
+ {"CharStrings", CFF_TYPE_OFFSET},
+ {"Private", CFF_TYPE_SZOFF}, /* two numbers (size and offset) */
+ /* Private */
+ {"Subrs", CFF_TYPE_OFFSET},
+ {"defaultWidthX", CFF_TYPE_NUMBER},
+ {"nominalWidthX", CFF_TYPE_NUMBER},
+ /* Operator 2 */
+ {"Copyright", CFF_TYPE_SID},
+ {"IsFixedPitch", CFF_TYPE_BOOLEAN},
+ {"ItalicAngle", CFF_TYPE_NUMBER},
+ {"UnderlinePosition", CFF_TYPE_NUMBER},
+ {"UnderlineThickness", CFF_TYPE_NUMBER},
+ {"PaintType", CFF_TYPE_NUMBER},
+ {"CharstringType", CFF_TYPE_NUMBER},
+ {"FontMatrix", CFF_TYPE_ARRAY},
+ {"StrokeWidth", CFF_TYPE_NUMBER},
+ {"BlueScale", CFF_TYPE_NUMBER},
+ {"BlueShift", CFF_TYPE_NUMBER},
+ {"BlueFuzz", CFF_TYPE_NUMBER},
+ {"StemSnapH", CFF_TYPE_DELTA},
+ {"StemSnapV", CFF_TYPE_DELTA},
+ {"ForceBold", CFF_TYPE_BOOLEAN},
+ {NULL, -1},
+ {NULL, -1},
+ {"LanguageGroup", CFF_TYPE_NUMBER},
+ {"ExpansionFactor", CFF_TYPE_NUMBER},
+ {"InitialRandomSeed", CFF_TYPE_NUMBER},
+ {"SyntheticBase", CFF_TYPE_NUMBER},
+ {"PostScript", CFF_TYPE_SID},
+ {"BaseFontName", CFF_TYPE_SID},
+ {"BaseFontBlend", CFF_TYPE_DELTA}, /* MMaster ? */
+ {NULL, -1},
+ {NULL, -1},
+ {NULL, -1},
+ {NULL, -1},
+ {NULL, -1},
+ {NULL, -1},
+ /* CID-Keyed font */
+ {"ROS", CFF_TYPE_ROS}, /* SID SID number */
+ {"CIDFontVersion", CFF_TYPE_NUMBER},
+ {"CIDFontRevision", CFF_TYPE_NUMBER},
+ {"CIDFontType", CFF_TYPE_NUMBER},
+ {"CIDCount", CFF_TYPE_NUMBER},
+ {"UIDBase", CFF_TYPE_NUMBER},
+ {"FDArray", CFF_TYPE_OFFSET},
+ {"FDSelect", CFF_TYPE_OFFSET},
+ {"FontName", CFF_TYPE_SID},
+};
+
+/* Parse DICT data */
+static double get_integer (card8 **data, card8 *endptr, int *status)
+{
+ long result = 0;
+ card8 b0, b1, b2;
+
+ b0 = *(*data)++;
+ if (b0 == 28 && *data < endptr - 2) { /* shortint */
+ b1 = *(*data)++;
+ b2 = *(*data)++;
+ result = b1*256+b2;
+ if (result > 0x7fffL)
+ result -= 0x10000L;
+ } else if (b0 == 29 && *data < endptr - 4) { /* longint */
+ int i;
+ result = *(*data)++;
+ if (result > 0x7f)
+ result -= 0x100;
+ for (i=0;i<3;i++) {
+ result = result*256+(**data);
+ *data += 1;
+ }
+ } else if (b0 >= 32 && b0 <= 246) { /* int (1) */
+ result = b0 - 139;
+ } else if (b0 >= 247 && b0 <= 250) { /* int (2) */
+ b1 = *(*data)++;
+ result = (b0-247)*256+b1+108;
+ } else if (b0 >= 251 && b0 <= 254) {
+ b1 = *(*data)++;
+ result = -(b0-251)*256-b1-108;
+ } else {
+ *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
+ }
+
+ return (double) result;
+}
+
+/* Simply uses strtod */
+static double get_real(card8 **data, card8 *endptr, int *status)
+{
+ double result = 0.0;
+ int nibble = 0, pos = 0;
+ int len = 0, fail = 0;
+
+ if (**data != 30 || *data >= endptr -1) {
+ *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
+ return 0.0;
+ }
+
+ *data += 1; /* skip first byte (30) */
+
+ pos = 0;
+ while ((! fail) && len < WORK_BUFFER_SIZE - 2 && *data < endptr) {
+ /* get nibble */
+ if (pos % 2) {
+ nibble = **data & 0x0f;
+ *data += 1;
+ } else {
+ nibble = (**data >> 4) & 0x0f;
+ }
+ if (nibble >= 0x00 && nibble <= 0x09) {
+ work_buffer[len++] = nibble + '0';
+ } else if (nibble == 0x0a) { /* . */
+ work_buffer[len++] = '.';
+ } else if (nibble == 0x0b || nibble == 0x0c) { /* E, E- */
+ work_buffer[len++] = 'e';
+ if (nibble == 0x0c)
+ work_buffer[len++] = '-';
+ } else if (nibble == 0x0e) { /* `-' */
+ work_buffer[len++] = '-';
+ } else if (nibble == 0x0d) { /* skip */
+ /* do nothing */
+ } else if (nibble == 0x0f) { /* end */
+ work_buffer[len++] = '\0';
+ if (((pos % 2) == 0) && (**data != 0xff)) {
+ fail = 1;
+ }
+ break;
+ } else { /* invalid */
+ fail = 1;
+ }
+ pos++;
+ }
+
+ /* returned values */
+ if (fail || nibble != 0x0f) {
+ *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
+ } else {
+ char *s;
+ result = strtod(work_buffer, &s);
+ if (*s != 0 || errno == ERANGE) {
+ *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
+ }
+ }
+
+ return result;
+}
+
+/* operators */
+static void add_dict (cff_dict *dict,
+ card8 **data, card8 *endptr, int *status)
+{
+ int id, argtype;
+
+ id = **data;
+ if (id == 0x0c) {
+ *data += 1;
+ if (*data >= endptr ||
+ (id = **data + CFF_LAST_DICT_OP1) >= CFF_LAST_DICT_OP) {
+ *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
+ return;
+ }
+ } else if (id >= CFF_LAST_DICT_OP1) {
+ *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
+ return;
+ }
+
+ argtype = dict_operator[id].argtype;
+ if (dict_operator[id].opname == NULL || argtype < 0) {
+ *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
+ return;
+ } else if (stack_top < 1) {
+ *status = CFF_CFF_ERROR_STACK_UNDERFLOW;
+ return;
+ }
+
+ if (dict->count >= dict->max) {
+ dict->max += DICT_ENTRY_MAX;
+ /* not zeroed! */
+ dict->entries = xrealloc(dict->entries, dict->max*sizeof(cff_dict_entry));
+ }
+
+ (dict->entries)[dict->count].id = id;
+ (dict->entries)[dict->count].key = (char *) dict_operator[id].opname;
+ if (argtype == CFF_TYPE_NUMBER ||
+ argtype == CFF_TYPE_BOOLEAN ||
+ argtype == CFF_TYPE_SID ||
+ argtype == CFF_TYPE_OFFSET) {
+ stack_top--;
+ (dict->entries)[dict->count].count = 1;
+ (dict->entries)[dict->count].values = xcalloc(1, sizeof(double));
+ (dict->entries)[dict->count].values[0] = arg_stack[stack_top];
+ } else {
+ (dict->entries)[dict->count].count = stack_top;
+ (dict->entries)[dict->count].values = xcalloc(stack_top, sizeof(double));
+ while (stack_top > 0) {
+ stack_top--;
+ (dict->entries)[dict->count].values[stack_top] = arg_stack[stack_top];
+ }
+ }
+
+ dict->count += 1;
+ *data += 1;
+
+ return;
+}
+
+/*
+ * All operands are treated as number or array of numbers.
+ * Private: two numbers, size and offset
+ * ROS : three numbers, SID, SID, and a number
+ */
+cff_dict *cff_dict_unpack (card8 *data, card8 *endptr)
+{
+ cff_dict *dict;
+ int status = CFF_PARSE_OK;
+
+ stack_top = 0;
+
+ dict = cff_new_dict();
+ while (data < endptr && status == CFF_PARSE_OK) {
+ if (*data < 22) { /* operator */
+ add_dict(dict, &data, endptr, &status);
+ } else if (*data == 30) { /* real - First byte of a sequence (variable) */
+ if (stack_top < CFF_DICT_STACK_LIMIT) {
+ arg_stack[stack_top] = get_real(&data, endptr, &status);
+ stack_top++;
+ } else {
+ status = CFF_CFF_ERROR_STACK_OVERFLOW;
+ }
+ } else if (*data == 255 || (*data >= 22 && *data <= 27)) { /* reserved */
+ data++;
+ } else { /* everything else are integer */
+ if (stack_top < CFF_DICT_STACK_LIMIT) {
+ arg_stack[stack_top] = get_integer(&data, endptr, &status);
+ stack_top++;
+ } else {
+ status = CFF_CFF_ERROR_STACK_OVERFLOW;
+ }
+ }
+ }
+
+ if (status != CFF_PARSE_OK) {
+ pdftex_fail("Parsing CFF DICT failed. (error=%d)", status);
+ } else if (stack_top != 0) {
+ WARN("Garbage in CFF DICT data.");
+ stack_top = 0;
+ }
+
+ return dict;
+}
+
+
+int cff_dict_known (cff_dict *dict, const char *key)
+{
+ int i;
+
+ for (i = 0; i < dict->count; i++) {
+ if (key && strcmp(key, (dict->entries)[i].key) == 0
+ && (dict->entries)[i].count > 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+double cff_dict_get (cff_dict *dict, const char *key, int idx)
+{
+ double value = 0.0;
+ int i;
+
+ assert(key && dict);
+
+ for (i = 0; i < dict->count; i++) {
+ if (strcmp(key, (dict->entries)[i].key) == 0) {
+ if ((dict->entries)[i].count > idx)
+ value = (dict->entries)[i].values[idx];
+ else
+ pdftex_fail("Invalid index number.");
+ break;
+ }
+ }
+
+ if (i == dict->count)
+ pdftex_fail("DICT entry \"%s\" not found.", key);
+
+ return value;
+}
+
+card8 cff_fdselect_lookup (cff_font *cff, card16 gid)
+{
+ card8 fd = 0xff;
+ cff_fdselect *fdsel;
+
+ if (cff->fdselect == NULL)
+ CFF_ERROR("in cff_fdselect_lookup(): FDSelect not available");
+
+ fdsel = cff->fdselect;
+
+ if (gid >= cff->num_glyphs)
+ CFF_ERROR("in cff_fdselect_lookup(): Invalid glyph index");
+
+ switch (fdsel->format) {
+ case 0:
+ fd = fdsel->data.fds[gid];
+ break;
+ case 3:
+ {
+ if (gid == 0) {
+ fd = (fdsel->data).ranges[0].fd;
+ } else {
+ card16 i;
+ for (i=1;i<(fdsel->num_entries);i++) {
+ if (gid < (fdsel->data).ranges[i].first)
+ break;
+ }
+ fd = (fdsel->data).ranges[i-1].fd;
+ }
+ }
+ break;
+ default:
+ CFF_ERROR("in cff_fdselect_lookup(): Invalid FDSelect format");
+ break;
+ }
+
+ if (fd >= cff->num_fds)
+ CFF_ERROR("in cff_fdselect_lookup(): Invalid Font DICT index");
+
+ return fd;
+}
+
+long cff_read_subrs (cff_font *cff)
+{
+ long len = 0;
+ long offset;
+ int i;
+
+
+ if ((cff->flag & FONTTYPE_CIDFONT) && cff->fdselect == NULL) {
+ cff_read_fdselect(cff);
+ }
+
+ if ((cff->flag & FONTTYPE_CIDFONT) && cff->fdarray == NULL) {
+ cff_read_fdarray(cff);
+ }
+
+ if (cff->private == NULL)
+ cff_read_private(cff);
+
+ if (cff->gsubr == NULL) {
+ cff->offset = cff->gsubr_offset;
+ cff->gsubr = cff_get_index(cff);
+ }
+
+ cff->subrs = xcalloc(cff->num_fds, sizeof(cff_index *));
+ if (cff->flag & FONTTYPE_CIDFONT) {
+ for (i=0;i<cff->num_fds;i++) {
+ if (cff->private[i] == NULL ||
+ !cff_dict_known(cff->private[i], "Subrs")) {
+ (cff->subrs)[i] = NULL;
+ } else {
+ offset = (long) cff_dict_get(cff->fdarray[i], "Private", 1);
+ offset += (long) cff_dict_get(cff->private[i], "Subrs", 0);
+ cff->offset = offset;
+ (cff->subrs)[i] = cff_get_index(cff);
+ len += cff_index_size((cff->subrs)[i]);
+ }
+ }
+ } else {
+ if (cff->private[0] == NULL ||
+ !cff_dict_known(cff->private[0], "Subrs")) {
+ (cff->subrs)[0] = NULL;
+ } else {
+ offset = (long) cff_dict_get(cff->topdict, "Private", 1);
+ offset += (long) cff_dict_get(cff->private[0], "Subrs", 0);
+ cff->offset = offset;
+ (cff->subrs)[0] = cff_get_index(cff);
+ len += cff_index_size((cff->subrs)[0]);
+ }
+ }
+
+ return len;
+}
+
+
+long cff_read_fdarray (cff_font *cff)
+{
+ long len = 0;
+ cff_index *idx;
+ long offset, size;
+ card16 i;
+
+ if (cff->topdict == NULL)
+ CFF_ERROR("in cff_read_fdarray(): Top DICT not found");
+
+ if (!(cff->flag & FONTTYPE_CIDFONT))
+ return 0;
+
+ /* must exist */
+ offset = (long) cff_dict_get(cff->topdict, "FDArray", 0);
+ cff->offset = offset;
+ idx = cff_get_index(cff);
+ cff->num_fds = (card8)idx->count;
+ cff->fdarray = xcalloc(idx->count, sizeof(cff_dict *));
+ for (i=0;i<idx->count;i++) {
+ card8 *data = idx->data + (idx->offset)[i] - 1;
+ size = (idx->offset)[i+1] - (idx->offset)[i];
+ if (size > 0) {
+ (cff->fdarray)[i] = cff_dict_unpack(data, data+size);
+ } else {
+ (cff->fdarray)[i] = NULL;
+ }
+ }
+ len = cff_index_size(idx);
+ cff_release_index(idx);
+
+ return len;
+}
+
+
+long cff_read_private (cff_font *cff)
+{
+ long len = 0;
+ card8 *data;
+ long offset, size;
+
+ if (cff->flag & FONTTYPE_CIDFONT) {
+ int i;
+
+ if (cff->fdarray == NULL)
+ cff_read_fdarray(cff);
+
+ cff->private = xcalloc(cff->num_fds, sizeof(cff_dict *));
+ for (i=0;i<cff->num_fds;i++) {
+ if (cff->fdarray[i] != NULL &&
+ cff_dict_known(cff->fdarray[i], "Private") &&
+ (size = (long) cff_dict_get(cff->fdarray[i], "Private", 0))
+ > 0) {
+ offset = (long) cff_dict_get(cff->fdarray[i], "Private", 1);
+ cff->offset = offset;
+ data = xcalloc(size, sizeof(card8));
+ memcpy(data,&cff->stream[cff->offset],size);
+ cff->offset = size;
+ (cff->private)[i] = cff_dict_unpack(data, data+size);
+ xfree(data);
+ len += size;
+ } else {
+ (cff->private)[i] = NULL;
+ }
+ }
+ } else {
+ cff->num_fds = 1;
+ cff->private = xcalloc(1, sizeof(cff_dict *));
+ if (cff_dict_known(cff->topdict, "Private") &&
+ (size = (long) cff_dict_get(cff->topdict, "Private", 0)) > 0) {
+ offset = (long) cff_dict_get(cff->topdict, "Private", 1);
+ cff->offset = offset;
+ data = xcalloc(size, sizeof(card8));
+ memcpy(data,&cff->stream[cff->offset],size);
+ cff->offset = size;
+ cff->private[0] = cff_dict_unpack(data, data+size);
+ xfree(data);
+ len += size;
+ } else {
+ (cff->private)[0] = NULL;
+ len = 0;
+ }
+ }
+
+ return len;
+}
+
+
+cff_font *read_cff (unsigned char *buf,long buflength, int n)
+{
+ cff_font *cff;
+ cff_index *idx;
+ long offset ;
+
+
+ cff = xcalloc(1,sizeof(cff_font));
+
+ cff->stream = buf;
+ cff->stream_size = buflength;
+ cff->index = n;
+
+ cff->header_major = get_card8(cff);
+ cff->header_minor = get_card8(cff);
+ cff->header_hdr_size = get_card8(cff);
+ cff->header_offsize = get_card8(cff);
+ if (cff->header_offsize < 1 || cff->header_offsize > 4) {
+ WARN("invalid offsize data");
+ cff_close(cff);
+ return NULL;
+ }
+ if (cff->header_major > 1) {
+ pdftex_warn("CFF major version %u not supported.",cff->header_major);
+ cff_close(cff);
+ return NULL;
+ }
+ cff->offset = cff->header_hdr_size;
+
+ /* Name INDEX */
+ idx = cff_get_index(cff);
+ if (n > idx->count - 1) {
+ pdftex_warn("Invalid CFF fontset index number.");
+ cff_close(cff);
+ return NULL;
+ }
+
+ cff->name = idx;
+
+ cff->fontname = cff_get_name(cff);
+
+ /* Top DICT INDEX */
+ idx = cff_get_index(cff);
+ if (n > idx->count - 1) {
+ WARN("CFF Top DICT not exist...");
+ cff_close(cff);
+ return NULL;
+ }
+ cff->topdict = cff_dict_unpack(idx->data + idx->offset[n] - 1,
+ idx->data + idx->offset[n + 1] - 1);
+ if (!cff->topdict) {
+ WARN("Parsing CFF Top DICT data failed...");
+ cff_close(cff);
+ return NULL;
+ }
+ cff_release_index(idx);
+
+ if (cff_dict_known(cff->topdict, "CharstringType") &&
+ cff_dict_get(cff->topdict, "CharstringType", 0) != 2) {
+ WARN("Only Type 2 Charstrings supported...");
+ cff_close(cff);
+ return NULL;
+ }
+
+ if (cff_dict_known(cff->topdict, "SyntheticBase")) {
+ WARN("CFF Synthetic font not supported.");
+ cff_close(cff);
+ return NULL;
+ }
+
+ /* String INDEX */
+ cff->string = cff_get_index(cff);
+
+ /* offset to GSubr */
+ cff->gsubr_offset = cff->offset;
+
+ /* Number of glyphs */
+ offset = (long) cff_dict_get(cff->topdict, "CharStrings", 0);
+ cff->offset = offset;
+ cff->num_glyphs = get_card16(cff);
+
+ /* Check for font type */
+ if (cff_dict_known(cff->topdict, "ROS")) {
+ cff->flag |= FONTTYPE_CIDFONT;
+ } else {
+ cff->flag |= FONTTYPE_FONT;
+ }
+
+ /* Check for encoding */
+ if (cff_dict_known(cff->topdict, "Encoding")) {
+ offset = (long) cff_dict_get(cff->topdict, "Encoding", 0);
+ if (offset == 0) { /* predefined */
+ cff->flag |= ENCODING_STANDARD;
+ } else if (offset == 1) {
+ cff->flag |= ENCODING_EXPERT;
+ }
+ } else {
+ cff->flag |= ENCODING_STANDARD;
+ }
+
+ cff->offset = cff->gsubr_offset; /* seek back to GSubr */
+
+ return cff;
+}
+
+/* write a cff for opentype */
+
+
+
+/* Pack DICT data */
+static long pack_integer (card8 *dest, long destlen, long value)
+{
+ long len = 0;
+
+ if (value >= -107 && value <= 107) {
+ if (destlen < 1)
+ CFF_ERROR("Buffer overflow.");
+ dest[0] = (value + 139) & 0xff;
+ len = 1;
+ } else if (value >= 108 && value <= 1131) {
+ if (destlen < 2)
+ CFF_ERROR("Buffer overflow.");
+ value = 0xf700u + value - 108;
+ dest[0] = (value >> 8) & 0xff;
+ dest[1] = value & 0xff;
+ len = 2;
+ } else if (value >= -1131 && value <= -108) {
+ if (destlen < 2)
+ CFF_ERROR("Buffer overflow.");
+ value = 0xfb00u - value - 108;
+ dest[0] = (value >> 8) & 0xff;
+ dest[1] = value & 0xff;
+ len = 2;
+ } else if (value >= -32768 && value <= 32767) { /* shortint */
+ if (destlen < 3)
+ CFF_ERROR("Buffer overflow.");
+ dest[0] = 28;
+ dest[1] = (value >> 8) & 0xff;
+ dest[2] = value & 0xff;
+ len = 3;
+ } else { /* longint */
+ if (destlen < 5)
+ CFF_ERROR("Buffer overflow.");
+ dest[0] = 29;
+ dest[1] = (value >> 24) & 0xff;
+ dest[2] = (value >> 16) & 0xff;
+ dest[3] = (value >> 8) & 0xff;
+ dest[4] = value & 0xff;
+ len = 5;
+ }
+ return len;
+}
+
+static long pack_real (card8 *dest, long destlen, double value)
+{
+ long e;
+ int i = 0, pos = 2;
+#define CFF_REAL_MAX_LEN 17
+
+ if (destlen < 2)
+ CFF_ERROR("Buffer overflow.");
+
+ dest[0] = 30;
+
+ if (value == 0.0) {
+ dest[1] = 0x0f;
+ return 2;
+ }
+
+ if (value < 0.0) {
+ dest[1] = 0xe0;
+ value *= -1.0;
+ pos++;
+ }
+
+ e = 0;
+ if (value >= 10.0) {
+ while (value >= 10.0) {
+ value /= 10.0;
+ e++;
+ }
+ } else if (value < 1.0) {
+ while (value < 1.0) {
+ value *= 10.0;
+ e--;
+ }
+ }
+
+ sprintf(work_buffer, "%1.14g", value);
+ for (i=0;i<CFF_REAL_MAX_LEN;i++) {
+ unsigned char ch = 0;
+ if (work_buffer[i] == '\0') {
+ break;
+ } else if (work_buffer[i] == '.') {
+ ch = 0x0a;
+ } else if (work_buffer[i] >= '0' && work_buffer[i] <= '9') {
+ ch = work_buffer[i] - '0';
+ } else {
+ CFF_ERROR("Invalid character.");
+ }
+
+ if (destlen < pos/2 + 1)
+ CFF_ERROR("Buffer overflow.");
+
+ if (pos % 2) {
+ dest[pos/2] += ch;
+ } else {
+ dest[pos/2] = (ch << 4);
+ }
+ pos++;
+ }
+
+ if (e > 0) {
+ if (pos % 2) {
+ dest[pos/2] += 0x0b;
+ } else {
+ if (destlen < pos/2 + 1)
+ CFF_ERROR("Buffer overflow.");
+ dest[pos/2] = 0xb0;
+ }
+ pos++;
+ } else if (e < 0) {
+ if (pos % 2) {
+ dest[pos/2] += 0x0c;
+ } else {
+ if (destlen < pos/2 + 1)
+ CFF_ERROR("Buffer overflow.");
+ dest[pos/2] = 0xc0;
+ }
+ e *= -1;
+ pos++;
+ }
+
+ if (e != 0) {
+ sprintf(work_buffer, "%ld", e);
+ for (i=0;i<CFF_REAL_MAX_LEN;i++) {
+ unsigned char ch = 0;
+ if (work_buffer[i] == '\0') {
+ break;
+ } else if (work_buffer[i] == '.') {
+ ch = 0x0a;
+ } else if (work_buffer[i] >= '0' && work_buffer[i] <= '9') {
+ ch = work_buffer[i] - '0';
+ } else {
+ CFF_ERROR("Invalid character.");
+ }
+
+ if (destlen < pos/2 + 1)
+ CFF_ERROR("Buffer overflow.");
+
+ if (pos % 2) {
+ dest[pos/2] += ch;
+ } else {
+ dest[pos/2] = (ch << 4);
+ }
+ pos++;
+ }
+ }
+
+ if (pos % 2) {
+ dest[pos/2] += 0x0f;
+ pos++;
+ } else {
+ if (destlen < pos/2 + 1)
+ CFF_ERROR("Buffer overflow.");
+ dest[pos/2] = 0xff;
+ pos += 2;
+ }
+
+ return pos/2;
+}
+
+static long cff_dict_put_number (double value,
+ card8 *dest, long destlen,
+ int type)
+{
+ long len = 0;
+ double nearint;
+
+ nearint = floor(value+0.5);
+ /* set offset to longint */
+ if (type == CFF_TYPE_OFFSET) {
+ long lvalue;
+
+ lvalue = (long) value;
+ if (destlen < 5)
+ CFF_ERROR("Buffer overflow.");
+ dest[0] = 29;
+ dest[1] = (lvalue >> 24) & 0xff;
+ dest[2] = (lvalue >> 16) & 0xff;
+ dest[3] = (lvalue >> 8) & 0xff;
+ dest[4] = lvalue & 0xff;
+ len = 5;
+ } else if (value > CFF_INT_MAX || value < CFF_INT_MIN ||
+ (fabs(value - nearint) > 1.0e-5)) { /* real */
+ len = pack_real(dest, destlen, value);
+ } else { /* integer */
+ len = pack_integer(dest, destlen, (long) nearint);
+ }
+
+ return len;
+}
+
+static long
+put_dict_entry (cff_dict_entry *de,
+ card8 *dest, long destlen)
+{
+ long len = 0;
+ int i, type, id;
+
+ if (de->count > 0) {
+ id = de->id;
+ if (dict_operator[id].argtype == CFF_TYPE_OFFSET ||
+ dict_operator[id].argtype == CFF_TYPE_SZOFF) {
+ type = CFF_TYPE_OFFSET;
+ } else {
+ type = CFF_TYPE_NUMBER;
+ }
+ for (i = 0; i < de->count; i++) {
+ len += cff_dict_put_number(de->values[i],
+ dest+len,
+ destlen-len, type);
+ }
+ if (id >= 0 && id < CFF_LAST_DICT_OP1) {
+ if (len + 1 > destlen)
+ CFF_ERROR("Buffer overflow.");
+ dest[len++] = id;
+ } else if (id >= 0 && id < CFF_LAST_DICT_OP) {
+ if (len + 2 > destlen)
+ CFF_ERROR("in cff_dict_pack(): Buffer overflow");
+ dest[len++] = 12;
+ dest[len++] = id - CFF_LAST_DICT_OP1;
+ } else {
+ CFF_ERROR("Invalid CFF DICT operator ID.");
+ }
+ }
+
+ return len;
+}
+
+long cff_dict_pack (cff_dict *dict, card8 *dest, long destlen)
+{
+ long len = 0;
+ int i;
+
+ for (i = 0; i < dict->count; i++) {
+ if (!strcmp(dict->entries[i].key, "ROS")) {
+ len += put_dict_entry(&dict->entries[i], dest, destlen);
+ break;
+ }
+ }
+ for (i = 0; i < dict->count; i++) {
+ if (strcmp(dict->entries[i].key, "ROS")) {
+ len += put_dict_entry(&dict->entries[i], dest+len, destlen-len);
+ }
+ }
+
+ return len;
+}
+
+
+void cff_dict_add (cff_dict *dict, const char *key, int count)
+{
+ int id, i;
+
+ for (id=0;id<CFF_LAST_DICT_OP;id++) {
+ if (key && dict_operator[id].opname &&
+ strcmp(dict_operator[id].opname, key) == 0)
+ break;
+ }
+
+ if (id == CFF_LAST_DICT_OP)
+ CFF_ERROR("Unknown CFF DICT operator.");
+
+ for (i=0;i<dict->count;i++) {
+ if ((dict->entries)[i].id == id) {
+ if ((dict->entries)[i].count != count)
+ CFF_ERROR("Inconsistent DICT argument number.");
+ return;
+ }
+ }
+
+ if (dict->count + 1 >= dict->max) {
+ dict->max += 8;
+ dict->entries = xrealloc(dict->entries, (dict->max)*sizeof(cff_dict_entry));
+ }
+
+ (dict->entries)[dict->count].id = id;
+ (dict->entries)[dict->count].key = (char *) dict_operator[id].opname;
+ (dict->entries)[dict->count].count = count;
+ if (count > 0) {
+ (dict->entries)[dict->count].values = xcalloc(count, sizeof(double));
+ memset((dict->entries)[dict->count].values,
+ 0, sizeof(double)*count);
+ } else {
+ (dict->entries)[dict->count].values = NULL;
+ }
+ dict->count += 1;
+
+ return;
+}
+
+
+void cff_dict_remove (cff_dict *dict, const char *key)
+{
+ int i;
+ for (i = 0; i < dict->count; i++) {
+ if (key && strcmp(key, (dict->entries)[i].key) == 0) {
+ (dict->entries)[i].count = 0;
+ if ((dict->entries)[i].values)
+ xfree((dict->entries)[i].values);
+ (dict->entries)[i].values = NULL;
+ }
+ }
+}
+
+void cff_dict_set (cff_dict *dict, const char *key, int idx, double value)
+{
+ int i;
+
+ assert(dict && key);
+
+ for (i = 0 ; i < dict->count; i++) {
+ if (strcmp(key, (dict->entries)[i].key) == 0) {
+ if ((dict->entries)[i].count > idx)
+ (dict->entries)[i].values[idx] = value;
+ else
+ CFF_ERROR("Invalid index number.");
+ break;
+ }
+ }
+
+ if (i == dict->count)
+ pdftex_fail("DICT entry \"%s\" not found.", key);
+}
+
+
+/* Strings */
+char *cff_get_string (cff_font *cff, s_SID id)
+{
+ char *result = NULL;
+ long len;
+
+ if (id < CFF_STDSTR_MAX) {
+ len = strlen(cff_stdstr[id]);
+ result = xcalloc(len+1, sizeof(char));
+ memcpy(result, cff_stdstr[id], len);
+ result[len] = '\0';
+ } else if (cff && cff->string) {
+ cff_index *strings = cff->string;
+ id -= CFF_STDSTR_MAX;
+ if (id < strings->count) {
+ len = (strings->offset)[id+1] - (strings->offset)[id];
+ result = xcalloc(len + 1, sizeof(char));
+ memmove(result, strings->data + (strings->offset)[id] - 1, len);
+ result[len] = '\0';
+ }
+ }
+
+ return result;
+}
+
+long cff_get_sid (cff_font *cff, char *str)
+{
+ card16 i;
+
+ if (!cff || !str)
+ return -1;
+
+ /* I search String INDEX first. */
+ if (cff && cff->string) {
+ cff_index *idx = cff->string;
+ for (i = 0; i < idx->count; i++) {
+ if (strlen(str) == (idx->offset)[i+1] - (idx->offset)[i] &&
+ !memcmp(str, (idx->data)+(idx->offset)[i]-1, strlen(str)))
+ return (i + CFF_STDSTR_MAX);
+ }
+ }
+
+ for (i = 0; i < CFF_STDSTR_MAX; i++) {
+ if (!strcmp(str, cff_stdstr[i]))
+ return i;
+ }
+
+ return -1;
+}
+
+
+void cff_update_string (cff_font *cff)
+{
+ if (cff == NULL)
+ CFF_ERROR("CFF font not opened.");
+
+ if (cff->string)
+ cff_release_index(cff->string);
+ cff->string = cff->_string;
+ cff->_string = NULL;
+}
+
+
+s_SID cff_add_string (cff_font *cff, char *str)
+{
+ card16 idx;
+ cff_index *strings;
+ l_offset offset, size;
+
+ if (cff == NULL)
+ CFF_ERROR("CFF font not opened.");
+
+ if (cff->_string == NULL)
+ cff->_string = cff_new_index(0);
+ strings = cff->_string;
+
+ for (idx = 0; idx < strings->count; idx++) {
+ size = strings->offset[idx+1] - strings->offset[idx];
+ offset = strings->offset[idx];
+ if (size == strlen(str) &&
+ !memcmp(strings->data+offset-1, str, strlen(str)))
+ return (idx + CFF_STDSTR_MAX);
+ }
+
+ for (idx = 0; idx < CFF_STDSTR_MAX; idx++) {
+ if (cff_stdstr[idx] &&
+ !strcmp(cff_stdstr[idx], str))
+ return idx;
+ }
+ offset = (strings->count > 0) ? strings->offset[strings->count] : 1;
+ strings->offset = xrealloc(strings->offset, (strings->count+2)*sizeof(l_offset));
+ if (strings->count == 0)
+ strings->offset[0] = 1;
+ idx = strings->count;
+ strings->count += 1;
+ strings->offset[strings->count] = offset + strlen(str);
+ strings->data = xrealloc(strings->data, (offset+strlen(str)-1)*sizeof(card8));
+ memcpy(strings->data+offset-1, str, strlen(str));
+
+ return (idx + CFF_STDSTR_MAX);
+}
+
+
+void cff_dict_update (cff_dict *dict, cff_font *cff)
+{
+ int i;
+
+ for (i = 0;i < dict->count; i++) {
+ if ((dict->entries)[i].count > 0) {
+ char *str;
+ int id;
+
+ id = (dict->entries)[i].id;
+
+ if (dict_operator[id].argtype == CFF_TYPE_SID) {
+ str = cff_get_string(cff, (dict->entries)[i].values[0]);
+ (dict->entries)[i].values[0] = cff_add_string(cff, str);
+ xfree(str);
+ } else if (dict_operator[id].argtype == CFF_TYPE_ROS) {
+ str = cff_get_string(cff, (dict->entries)[i].values[0]);
+ (dict->entries)[i].values[0] = cff_add_string(cff, str);
+ xfree(str);
+ str = cff_get_string(cff, (dict->entries)[i].values[1]);
+ (dict->entries)[i].values[1] = cff_add_string(cff, str);
+ xfree(str);
+ }
+
+ }
+ }
+}
+
+/* charsets */
+
+long cff_read_charsets (cff_font *cff)
+{
+ cff_charsets *charset;
+ long offset, length;
+ card16 count, i;
+
+ if (cff->topdict == NULL)
+ CFF_ERROR("Top DICT not available");
+
+ if (!cff_dict_known(cff->topdict, "charset")) {
+ cff->flag |= CHARSETS_ISOADOBE;
+ cff->charsets = NULL;
+ return 0;
+ }
+
+ offset = (long) cff_dict_get(cff->topdict, "charset", 0);
+
+ if (offset == 0) { /* predefined */
+ cff->flag |= CHARSETS_ISOADOBE;
+ cff->charsets = NULL;
+ return 0;
+ } else if (offset == 1) {
+ cff->flag |= CHARSETS_EXPERT;
+ cff->charsets = NULL;
+ return 0;
+ } else if (offset == 2) {
+ cff->flag |= CHARSETS_EXPSUB;
+ cff->charsets = NULL;
+ return 0;
+ }
+
+ cff->offset = offset;
+ cff->charsets = charset = xcalloc(1, sizeof(cff_charsets));
+ charset->format = get_card8(cff);
+ charset->num_entries = 0;
+
+ count = cff->num_glyphs - 1;
+ length = 1;
+
+ /* Not sure. Not well documented. */
+ switch (charset->format) {
+ case 0:
+ charset->num_entries = cff->num_glyphs - 1; /* no .notdef */
+ charset->data.glyphs = xcalloc(charset->num_entries, sizeof(s_SID));
+ length += (charset->num_entries) * 2;
+ for (i=0;i<(charset->num_entries);i++) {
+ charset->data.glyphs[i] = get_card16(cff);
+ }
+ count = 0;
+ break;
+ case 1:
+ {
+ cff_range1 *ranges = NULL;
+ while (count > 0 && charset->num_entries < cff->num_glyphs) {
+ ranges = xrealloc(ranges, (charset->num_entries + 1)*sizeof(cff_range1));
+ ranges[charset->num_entries].first = get_card16(cff);
+ ranges[charset->num_entries].n_left = get_card8(cff);
+ count -= ranges[charset->num_entries].n_left + 1; /* no-overrap */
+ charset->num_entries += 1;
+ charset->data.range1 = ranges;
+ }
+ length += (charset->num_entries) * 3;
+ }
+ break;
+ case 2:
+ {
+ cff_range2 *ranges = NULL;
+ while (count > 0 && charset->num_entries < cff->num_glyphs) {
+ ranges = xrealloc(ranges, (charset->num_entries + 1)*sizeof(cff_range2));
+ ranges[charset->num_entries].first = get_card16(cff);
+ ranges[charset->num_entries].n_left = get_card16(cff);
+ count -= ranges[charset->num_entries].n_left + 1; /* non-overrapping */
+ charset->num_entries += 1;
+ }
+ charset->data.range2 = ranges;
+ length += (charset->num_entries) * 4;
+ }
+ break;
+ default:
+ xfree(charset);
+ CFF_ERROR("Unknown Charset format");
+ break;
+ }
+
+ if (count > 0)
+ CFF_ERROR("Charset data possibly broken");
+
+ return length;
+}
+
+long cff_pack_charsets (cff_font *cff, card8 *dest, long destlen)
+{
+ long len = 0;
+ card16 i;
+ cff_charsets *charset;
+
+ if (cff->flag & HAVE_STANDARD_CHARSETS || cff->charsets == NULL)
+ return 0;
+
+ if (destlen < 1)
+ CFF_ERROR("in cff_pack_charsets(): Buffer overflow");
+
+ charset = cff->charsets;
+
+ dest[len++] = charset->format;
+ switch (charset->format) {
+ case 0:
+ if (destlen < len + (charset->num_entries)*2)
+ CFF_ERROR("in cff_pack_charsets(): Buffer overflow");
+ for (i=0;i<(charset->num_entries);i++) {
+ s_SID sid = (charset->data).glyphs[i]; /* or CID */
+ dest[len++] = (sid >> 8) & 0xff;
+ dest[len++] = sid & 0xff;
+ }
+ break;
+ case 1:
+ {
+ if (destlen < len + (charset->num_entries)*3)
+ CFF_ERROR("in cff_pack_charsets(): Buffer overflow");
+ for (i=0;i<(charset->num_entries);i++) {
+ dest[len++] = ((charset->data).range1[i].first >> 8) & 0xff;
+ dest[len++] = (charset->data).range1[i].first & 0xff;
+ dest[len++] = (charset->data).range1[i].n_left;
+ }
+ }
+ break;
+ case 2:
+ {
+ if (destlen < len + (charset->num_entries)*4)
+ CFF_ERROR("in cff_pack_charsets(): Buffer overflow");
+ for (i=0;i<(charset->num_entries);i++) {
+ dest[len++] = ((charset->data).range2[i].first >> 8) & 0xff;
+ dest[len++] = (charset->data).range2[i].first & 0xff;
+ dest[len++] = ((charset->data).range2[i].n_left >> 8) & 0xff;
+ dest[len++] = (charset->data).range2[i].n_left & 0xff;
+ }
+ }
+ break;
+ default:
+ CFF_ERROR("Unknown Charset format");
+ break;
+ }
+
+ return len;
+}
+
+
+
+/*
+ * Type 2 Charstring support:
+ * Decode and encode Type 2 charstring
+ *
+ * All local/global subroutine calls in a given charstring is replace by the
+ * content of subroutine charstrings. We do this because some PostScript RIP
+ * may have problems with sparse subroutine array. Workaround for this is to
+ * re-order subroutine array so that no gap appears in the subroutine array,
+ * or put dummy charstrings that contains only `return' in the gap. However,
+ * re-ordering of subroutine is rather difficult for Type 2 charstrings due
+ * to the bias which depends on the total number of subroutines. Replacing
+ * callgsubr/callsubr calls with the content of the corresponding subroutine
+ * charstring may be more efficient than putting dummy subroutines in the
+ * case of subsetted font. Adobe distiller seems doing same thing.
+ *
+ * And also note that subroutine numbers within subroutines can depend on the
+ * content of operand stack as follows:
+ *
+ * ... l m callsubr << subr #(m+bias): n add callsubr >> ...
+ *
+ * I've not implemented the `random' operator which generates a pseudo-random
+ * number in the range (0, 1] and push them into argument stack.
+ * How pseudo-random sequences are generated is not documented in the Type 2
+ * charstring spec..
+ */
+
+
+#define CS_TYPE2_DEBUG_STR "Type2 Charstring Parser"
+#define CS_TYPE2_DEBUG 5
+
+/* decoder/encoder status codes */
+#define CS_BUFFER_CFF_ERROR -3
+#define CS_STACK_CFF_ERROR -2
+#define CS_PARSE_CFF_ERROR -1
+#define CS_PARSE_OK 0
+#define CS_PARSE_END 1
+#define CS_SUBR_RETURN 2
+#define CS_CHAR_END 3
+
+static int status = CS_PARSE_CFF_ERROR;
+
+#define DST_NEED(a,b) {if ((a) < (b)) { status = CS_BUFFER_CFF_ERROR ; return ; }}
+#define SRC_NEED(a,b) {if ((a) < (b)) { status = CS_PARSE_CFF_ERROR ; return ; }}
+#define NEED(a,b) {if ((a) < (b)) { status = CS_STACK_CFF_ERROR ; return ; }}
+
+/* hintmask and cntrmask need number of stem zones */
+static int num_stems = 0;
+static int phase = 0;
+
+/* subroutine nesting */
+static int cs2_nest = 0;
+
+/* advance width */
+static int have_width = 0;
+static double width = 0.0;
+
+/*
+ * Standard Encoding Accented Characters:
+ * Optional four arguments for endchar. See, CFF spec., p.35.
+ * This is obsolete feature and is no longer supported.
+ */
+#if 0
+/* adx ady bchar achar endchar */
+static double seac[4] = {0.0, 0.0, 0.0, 0.0};
+#endif
+
+/* Operand stack and Transient array */
+static int cs2_stack_top = 0;
+static double cs2_arg_stack[CS_ARG_STACK_MAX];
+static double trn_array[CS_TRANS_ARRAY_MAX];
+
+/*
+ * Type 2 CharString encoding
+ */
+
+/*
+ * 1-byte CharString operaotrs:
+ * cs_escape is first byte of two-byte operator
+ */
+
+/* RESERVED 0 */
+#define cs_hstem 1
+/* RESERVED 2 */
+#define cs_vstem 3
+#define cs_vmoveto 4
+#define cs_rlineto 5
+#define cs_hlineto 6
+#define cs_vlineto 7
+#define cs_rrcurveto 8
+/* cs_closepath 9 : TYPE1 */
+#define cs_callsubr 10
+#define cs_return 11
+#define cs_escape 12
+/* cs_hsbw 13 : TYPE1 */
+#define cs_endchar 14
+/* RESERVED 15 */
+/* RESERVED 16 */
+/* RESERVED 17 */
+#define cs_hstemhm 18
+#define cs_hintmask 19
+#define cs_cntrmask 20
+#define cs_rmoveto 21
+#define cs_hmoveto 22
+#define cs_vstemhm 23
+#define cs_rcurveline 24
+#define cs_rlinecurve 25
+#define cs_vvcurveto 26
+#define cs_hhcurveto 27
+/* SHORTINT 28 : first byte of shortint*/
+#define cs_callgsubr 29
+#define cs_vhcurveto 30
+#define cs_hvcurveto 31
+
+/*
+ * 2-byte CharString operaotrs:
+ * "dotsection" is obsoleted in Type 2 charstring.
+ */
+
+#define cs_dotsection 0
+/* cs_vstem3 1 : TYPE1 */
+/* cs_hstem3 2 : TYPE1 */
+#define cs_and 3
+#define cs_or 4
+#define cs_not 5
+/* cs_seac 6 : TYPE1 */
+/* cs_sbw 7 : TYPE1 */
+/* RESERVED 8 */
+#define cs_abs 9
+#define cs_add 10
+#define cs_sub 11
+#define cs_div 12
+/* RESERVED 13 */
+#define cs_neg 14
+#define cs_eq 15
+/* cs_callothersubr 16 : TYPE1 */
+/* cs_pop 17 : TYPE1 */
+#define cs_drop 18
+/* RESERVED 19 */
+#define cs_put 20
+#define cs_get 21
+#define cs_ifelse 22
+#define cs_random 23
+#define cs_mul 24
+/* RESERVED 25 */
+#define cs_sqrt 26
+#define cs_dup 27
+#define cs_exch 28
+#define cs_index 29
+#define cs_roll 30
+/* cs_setcurrentpoint 31 : TYPE1 */
+/* RESERVED 32 */
+/* RESERVED 33 */
+#define cs_hflex 34
+#define cs_flex 35
+#define cs_hflex1 36
+#define cs_flex1 37
+
+/*
+ * clear_stack() put all operands sotred in operand stack to dest.
+ */
+static void
+clear_stack (card8 **dest, card8 *limit)
+{
+ int i;
+
+ for (i = 0; i < cs2_stack_top; i++) {
+ double value;
+ long ivalue;
+ value = cs2_arg_stack[i];
+ /* Nearest integer value */
+ ivalue = (long) floor(value+0.5);
+ if (value >= 0x8000L || value <= (-0x8000L - 1)) {
+ /*
+ * This number cannot be represented as a single operand.
+ * We must use `a b mul ...' or `a c div' to represent large values.
+ */
+ CFF_ERROR("Argument value too large. (This is bug)");
+ } else if (fabs(value - ivalue) > 3.0e-5) {
+ /* 16.16-bit signed fixed value */
+ DST_NEED(limit, *dest + 5);
+ *(*dest)++ = 255;
+ ivalue = (long) floor(value); /* mantissa */
+ *(*dest)++ = (ivalue >> 8) & 0xff;
+ *(*dest)++ = ivalue & 0xff;
+ ivalue = (long)((value - ivalue) * 0x10000l); /* fraction */
+ *(*dest)++ = (ivalue >> 8) & 0xff;
+ *(*dest)++ = ivalue & 0xff;
+ /* Everything else are integers. */
+ } else if (ivalue >= -107 && ivalue <= 107) {
+ DST_NEED(limit, *dest + 1);
+ *(*dest)++ = ivalue + 139;
+ } else if (ivalue >= 108 && ivalue <= 1131) {
+ DST_NEED(limit, *dest + 2);
+ ivalue = 0xf700u + ivalue - 108;
+ *(*dest)++ = (ivalue >> 8) & 0xff;
+ *(*dest)++ = ivalue & 0xff;
+ } else if (ivalue >= -1131 && ivalue <= -108) {
+ DST_NEED(limit, *dest + 2);
+ ivalue = 0xfb00u - ivalue - 108;
+ *(*dest)++ = (ivalue >> 8) & 0xff;
+ *(*dest)++ = ivalue & 0xff;
+ } else if (ivalue >= -32768 && ivalue <= 32767) { /* shortint */
+ DST_NEED(limit, *dest + 3);
+ *(*dest)++ = 28;
+ *(*dest)++ = (ivalue >> 8) & 0xff;
+ *(*dest)++ = (ivalue) & 0xff;
+ } else { /* Shouldn't come here */
+ CFF_ERROR("Unexpected error.");
+ }
+ }
+
+ cs2_stack_top = 0; /* clear stack */
+
+ return;
+}
+
+/*
+ * Single byte operators:
+ * Path construction, Operator for finishing a path, Hint operators.
+ *
+ * phase:
+ * 0: inital state
+ * 1: hint declaration, first stack-clearing operator appeared
+ * 2: in path construction
+ */
+
+static void
+do_operator1 (card8 **dest, card8 *limit, card8 **data, card8 *endptr)
+{
+ card8 op = **data;
+
+ *data += 1;
+
+ switch (op) {
+ case cs_hstemhm:
+ case cs_vstemhm:
+ /* charstring may have hintmask if above operator have seen */
+ case cs_hstem:
+ case cs_vstem:
+ if (phase == 0 && (cs2_stack_top % 2)) {
+ have_width = 1;
+ width = cs2_arg_stack[0];
+ }
+ num_stems += cs2_stack_top/2;
+ clear_stack(dest, limit);
+ DST_NEED(limit, *dest + 1);
+ *(*dest)++ = op;
+ phase = 1;
+ break;
+ case cs_hintmask:
+ case cs_cntrmask:
+ if (phase < 2) {
+ if (phase == 0 && (cs2_stack_top % 2)) {
+ have_width = 1;
+ width = cs2_arg_stack[0];
+ }
+ num_stems += cs2_stack_top/2;
+ }
+ clear_stack(dest, limit);
+ DST_NEED(limit, *dest + 1);
+ *(*dest)++ = op;
+ if (num_stems > 0) {
+ int masklen = (num_stems + 7) / 8;
+ DST_NEED(limit, *dest + masklen);
+ SRC_NEED(endptr, *data + masklen);
+ memmove(*dest, *data, masklen);
+ *data += masklen;
+ *dest += masklen;
+ }
+ phase = 2;
+ break;
+ case cs_rmoveto:
+ if (phase == 0 && (cs2_stack_top % 2)) {
+ have_width = 1;
+ width = cs2_arg_stack[0];
+ }
+ clear_stack(dest, limit);
+ DST_NEED(limit, *dest + 1);
+ *(*dest)++ = op;
+ phase = 2;
+ break;
+ case cs_hmoveto:
+ case cs_vmoveto:
+ if (phase == 0 && (cs2_stack_top % 2) == 0) {
+ have_width = 1;
+ width = cs2_arg_stack[0];
+ }
+ clear_stack(dest, limit);
+ DST_NEED(limit, *dest + 1);
+ *(*dest)++ = op;
+ phase = 2;
+ break;
+ case cs_endchar:
+ if (cs2_stack_top == 1) {
+ have_width = 1;
+ width = cs2_arg_stack[0];
+ clear_stack(dest, limit);
+ } else if (cs2_stack_top == 4 || cs2_stack_top == 5) {
+ WARN("\"seac\" character deprecated in Type 2 charstring.");
+ status = CS_PARSE_CFF_ERROR;
+ return;
+ } else if (cs2_stack_top > 0) {
+ WARN("Operand stack not empty.");
+ }
+ DST_NEED(limit, *dest + 1);
+ *(*dest)++ = op;
+ status = CS_CHAR_END;
+ break;
+ /* above oprators are candidate for first stack-clearing operator */
+ case cs_rlineto:
+ case cs_hlineto:
+ case cs_vlineto:
+ case cs_rrcurveto:
+ case cs_rcurveline:
+ case cs_rlinecurve:
+ case cs_vvcurveto:
+ case cs_hhcurveto:
+ case cs_vhcurveto:
+ case cs_hvcurveto:
+ if (phase < 2) {
+ WARN("Broken Type 2 charstring.");
+ status = CS_PARSE_CFF_ERROR;
+ return;
+ }
+ clear_stack(dest, limit);
+ DST_NEED(limit, *dest + 1);
+ *(*dest)++ = op;
+ break;
+ /* all operotors above are stack-clearing operator */
+ /* no output */
+ case cs_return:
+ case cs_callgsubr:
+ case cs_callsubr:
+ CFF_ERROR("Unexpected call(g)subr/return");
+ break;
+ default:
+ /* no-op ? */
+ WARN("%s: Unknown charstring operator: 0x%02x", CS_TYPE2_DEBUG_STR, op);
+ status = CS_PARSE_CFF_ERROR;
+ break;
+ }
+
+ return;
+}
+
+/*
+ * Double byte operators:
+ * Flex, arithmetic, conditional, and storage operators.
+ *
+ * Following operators are not supported:
+ * random: How random ?
+ */
+static void
+do_operator2 (card8 **dest, card8 *limit, card8 **data, card8 *endptr)
+{
+ card8 op;
+
+ *data += 1;
+
+ SRC_NEED(endptr, *data + 1);
+
+ op = **data;
+ *data += 1;
+
+ switch(op) {
+ case cs_dotsection: /* deprecated */
+ WARN("Operator \"dotsection\" deprecated in Type 2 charstring.");
+ status = CS_PARSE_CFF_ERROR;
+ return;
+ break;
+ case cs_hflex:
+ case cs_flex:
+ case cs_hflex1:
+ case cs_flex1:
+ if (phase < 2) {
+ WARN("%s: Broken Type 2 charstring.", CS_TYPE2_DEBUG_STR);
+ status = CS_PARSE_CFF_ERROR;
+ return;
+ }
+ clear_stack(dest, limit);
+ DST_NEED(limit, *dest + 2);
+ *(*dest)++ = cs_escape;
+ *(*dest)++ = op;
+ break;
+ /* all operator above are stack-clearing */
+ /* no output */
+ case cs_and:
+ NEED(cs2_stack_top, 2);
+ cs2_stack_top--;
+ if (cs2_arg_stack[cs2_stack_top] && cs2_arg_stack[cs2_stack_top-1]) {
+ cs2_arg_stack[cs2_stack_top-1] = 1.0;
+ } else {
+ cs2_arg_stack[cs2_stack_top-1] = 0.0;
+ }
+ break;
+ case cs_or:
+ NEED(cs2_stack_top, 2);
+ cs2_stack_top--;
+ if (cs2_arg_stack[cs2_stack_top] || cs2_arg_stack[cs2_stack_top-1]) {
+ cs2_arg_stack[cs2_stack_top-1] = 1.0;
+ } else {
+ cs2_arg_stack[cs2_stack_top-1] = 0.0;
+ }
+ break;
+ case cs_not:
+ NEED(cs2_stack_top, 1);
+ if (cs2_arg_stack[cs2_stack_top-1]) {
+ cs2_arg_stack[cs2_stack_top-1] = 0.0;
+ } else {
+ cs2_arg_stack[cs2_stack_top-1] = 1.0;
+ }
+ break;
+ case cs_abs:
+ NEED(cs2_stack_top, 1);
+ cs2_arg_stack[cs2_stack_top-1] = fabs(cs2_arg_stack[cs2_stack_top-1]);
+ break;
+ case cs_add:
+ NEED(cs2_stack_top, 2);
+ cs2_arg_stack[cs2_stack_top-2] += cs2_arg_stack[cs2_stack_top-1];
+ cs2_stack_top--;
+ break;
+ case cs_sub:
+ NEED(cs2_stack_top, 2);
+ cs2_arg_stack[cs2_stack_top-2] -= cs2_arg_stack[cs2_stack_top-1];
+ cs2_stack_top--;
+ break;
+ case cs_div: /* doesn't check overflow */
+ NEED(cs2_stack_top, 2);
+ cs2_arg_stack[cs2_stack_top-2] /= cs2_arg_stack[cs2_stack_top-1];
+ cs2_stack_top--;
+ break;
+ case cs_neg:
+ NEED(cs2_stack_top, 1);
+ cs2_arg_stack[cs2_stack_top-1] *= -1.0;
+ break;
+ case cs_eq:
+ NEED(cs2_stack_top, 2);
+ cs2_stack_top--;
+ if (cs2_arg_stack[cs2_stack_top] == cs2_arg_stack[cs2_stack_top-1]) {
+ cs2_arg_stack[cs2_stack_top-1] = 1.0;
+ } else {
+ cs2_arg_stack[cs2_stack_top-1] = 0.0;
+ }
+ break;
+ case cs_drop:
+ NEED(cs2_stack_top, 1);
+ cs2_stack_top--;
+ break;
+ case cs_put:
+ NEED(cs2_stack_top, 2);
+ {
+ int idx = (int)cs2_arg_stack[--cs2_stack_top];
+ NEED(CS_TRANS_ARRAY_MAX, idx);
+ trn_array[idx] = cs2_arg_stack[--cs2_stack_top];
+ }
+ break;
+ case cs_get:
+ NEED(cs2_stack_top, 1);
+ {
+ int idx = (int)cs2_arg_stack[cs2_stack_top-1];
+ NEED(CS_TRANS_ARRAY_MAX, idx);
+ cs2_arg_stack[cs2_stack_top-1] = trn_array[idx];
+ }
+ break;
+ case cs_ifelse:
+ NEED(cs2_stack_top, 4);
+ cs2_stack_top -= 3;
+ if (cs2_arg_stack[cs2_stack_top+1] > cs2_arg_stack[cs2_stack_top+2]) {
+ cs2_arg_stack[cs2_stack_top-1] = cs2_arg_stack[cs2_stack_top];
+ }
+ break;
+ case cs_mul:
+ NEED(cs2_stack_top, 2);
+ cs2_arg_stack[cs2_stack_top-2] = cs2_arg_stack[cs2_stack_top-2] * cs2_arg_stack[cs2_stack_top-1];
+ cs2_stack_top--;
+ break;
+ case cs_sqrt:
+ NEED(cs2_stack_top, 1);
+ cs2_arg_stack[cs2_stack_top-1] = sqrt(cs2_arg_stack[cs2_stack_top-1]);
+ break;
+ case cs_dup:
+ NEED(cs2_stack_top, 1);
+ NEED(CS_ARG_STACK_MAX, cs2_stack_top+1);
+ cs2_arg_stack[cs2_stack_top] = cs2_arg_stack[cs2_stack_top-1];
+ cs2_stack_top++;
+ break;
+ case cs_exch:
+ NEED(cs2_stack_top, 2);
+ {
+ double save = cs2_arg_stack[cs2_stack_top-2];
+ cs2_arg_stack[cs2_stack_top-2] = cs2_arg_stack[cs2_stack_top-1];
+ cs2_arg_stack[cs2_stack_top-1] = save;
+ }
+ break;
+ case cs_index:
+ NEED(cs2_stack_top, 2); /* need two arguments at least */
+ {
+ int idx = (int)cs2_arg_stack[cs2_stack_top-1];
+ if (idx < 0) {
+ cs2_arg_stack[cs2_stack_top-1] = cs2_arg_stack[cs2_stack_top-2];
+ } else {
+ NEED(cs2_stack_top, idx+2);
+ cs2_arg_stack[cs2_stack_top-1] = cs2_arg_stack[cs2_stack_top-idx-2];
+ }
+ }
+ break;
+ case cs_roll:
+ NEED(cs2_stack_top, 2);
+ {
+ int N, J;
+ J = (int)cs2_arg_stack[--cs2_stack_top];
+ N = (int)cs2_arg_stack[--cs2_stack_top];
+ NEED(cs2_stack_top, N);
+ if (J > 0) {
+ J = J % N;
+ while (J-- > 0) {
+ double save = cs2_arg_stack[cs2_stack_top-1];
+ int i = cs2_stack_top - 1;
+ while (i > cs2_stack_top-N) {
+ cs2_arg_stack[i] = cs2_arg_stack[i-1];
+ i--;
+ }
+ cs2_arg_stack[i] = save;
+ }
+ } else {
+ J = (-J) % N;
+ while (J-- > 0) {
+ double save = cs2_arg_stack[cs2_stack_top-N];
+ int i = cs2_stack_top - N;
+ while (i < cs2_stack_top-1) {
+ cs2_arg_stack[i] = cs2_arg_stack[i+1];
+ i++;
+ }
+ cs2_arg_stack[i] = save;
+ }
+ }
+ }
+ break;
+ case cs_random:
+ WARN("%s: Charstring operator \"random\" found.", CS_TYPE2_DEBUG_STR);
+ NEED(CS_ARG_STACK_MAX, cs2_stack_top+1);
+ cs2_arg_stack[cs2_stack_top++] = 1.0;
+ break;
+ default:
+ /* no-op ? */
+ WARN("%s: Unknown charstring operator: 0x0c%02x", CS_TYPE2_DEBUG_STR, op);
+ status = CS_PARSE_CFF_ERROR;
+ break;
+ }
+
+ return;
+}
+
+/*
+ * integer:
+ * exactly the same as the DICT encoding (except 29)
+ */
+static void
+cs2_get_integer (card8 **data, card8 *endptr)
+{
+ long result = 0;
+ card8 b0 = **data, b1, b2;
+
+ *data += 1;
+
+ if (b0 == 28) { /* shortint */
+ SRC_NEED(endptr, *data + 2);
+ b1 = **data;
+ b2 = *(*data+1);
+ result = b1*256+b2;
+ if (result > 0x7fff)
+ result -= 0x10000L;
+ *data += 2;
+ } else if (b0 >= 32 && b0 <= 246) { /* int (1) */
+ result = b0 - 139;
+ } else if (b0 >= 247 && b0 <= 250) { /* int (2) */
+ SRC_NEED(endptr, *data + 1);
+ b1 = **data;
+ result = (b0-247)*256+b1+108;
+ *data += 1;
+ } else if (b0 >= 251 && b0 <= 254) {
+ SRC_NEED(endptr, *data + 1);
+ b1 = **data;
+ result = -(b0-251)*256-b1-108;
+ *data += 1;
+ } else {
+ status = CS_PARSE_CFF_ERROR;
+ return;
+ }
+
+ NEED(CS_ARG_STACK_MAX, cs2_stack_top+1);
+ cs2_arg_stack[cs2_stack_top++] = (double) result;
+
+ return;
+}
+
+/*
+ * Signed 16.16-bits fixed number for Type 2 charstring encoding
+ */
+static void
+get_fixed (card8 **data, card8 *endptr)
+{
+ long ivalue;
+ double rvalue;
+
+ *data += 1;
+
+ SRC_NEED(endptr, *data + 4);
+
+ ivalue = *(*data) * 0x100 + *(*data+1);
+ rvalue = (ivalue > 0x7fffL) ? (ivalue - 0x10000L) : ivalue;
+ ivalue = *(*data+2) * 0x100 + *(*data+3);
+ rvalue += ((double) ivalue) / 0x10000L;
+
+ NEED(CS_ARG_STACK_MAX, cs2_stack_top+1);
+ cs2_arg_stack[cs2_stack_top++] = rvalue;
+ *data += 4;
+
+ return;
+}
+
+/*
+ * Subroutines:
+ * The bias for subroutine number is introduced in type 2 charstrings.
+ *
+ * subr: set to a pointer to the subroutine charstring.
+ * len: set to the length of subroutine charstring.
+ * subr_idx: CFF INDEX data that contains subroutines.
+ * id: biased subroutine number.
+ */
+static void
+get_subr (card8 **subr, long *len, cff_index *subr_idx, long id)
+{
+ card16 count;
+
+ if (subr_idx == NULL)
+ CFF_ERROR("%s: Subroutine called but no subroutine found.", CS_TYPE2_DEBUG_STR);
+
+ count = subr_idx->count;
+
+ /* Adding bias number */
+ if (count < 1240) {
+ id += 107;
+ } else if (count < 33900) {
+ id += 1131;
+ } else {
+ id += 32768;
+ }
+
+ if (id > count)
+ CFF_ERROR("%s: Invalid Subr index: %ld (max=%u)", CS_TYPE2_DEBUG_STR, id, count);
+
+ *len = (subr_idx->offset)[id + 1] - (subr_idx->offset)[id];
+ *subr = subr_idx->data + (subr_idx->offset)[id] - 1;
+
+ return;
+}
+
+/*
+ * NOTE:
+ * The Type 2 interpretation of a number encoded in five-bytes (those with
+ * an initial byte value of 255) differs from how it is interpreted in the
+ * Type 1 format.
+ */
+
+static void
+do_charstring (card8 **dest, card8 *limit,
+ card8 **data, card8 *endptr,
+ cff_index *gsubr_idx, cff_index *subr_idx)
+{
+ card8 b0 = 0, *subr;
+ long len;
+
+ if (cs2_nest > CS_SUBR_NEST_MAX)
+ CFF_ERROR("%s: Subroutine nested too deeply.", CS_TYPE2_DEBUG_STR);
+
+ cs2_nest++;
+
+ while (*data < endptr && status == CS_PARSE_OK) {
+ b0 = **data;
+ if (b0 == 255) { /* 16-bit.16-bit fixed signed number */
+ get_fixed(data, endptr);
+ } else if (b0 == cs_return) {
+ status = CS_SUBR_RETURN;
+ } else if (b0 == cs_callgsubr) {
+ if (cs2_stack_top < 1) {
+ status = CS_STACK_CFF_ERROR;
+ } else {
+ cs2_stack_top--;
+ get_subr(&subr, &len, gsubr_idx, (long) cs2_arg_stack[cs2_stack_top]);
+ if (*dest + len > limit)
+ CFF_ERROR("%s: Possible buffer overflow.", CS_TYPE2_DEBUG_STR);
+ do_charstring(dest, limit, &subr, subr + len,
+ gsubr_idx, subr_idx);
+ *data += 1;
+ }
+ } else if (b0 == cs_callsubr) {
+ if (cs2_stack_top < 1) {
+ status = CS_STACK_CFF_ERROR;
+ } else {
+ cs2_stack_top--;
+ get_subr(&subr, &len, subr_idx, (long) cs2_arg_stack[cs2_stack_top]);
+ if (limit < *dest + len)
+ CFF_ERROR("%s: Possible buffer overflow.", CS_TYPE2_DEBUG_STR);
+ do_charstring(dest, limit, &subr, subr + len,
+ gsubr_idx, subr_idx);
+ *data += 1;
+ }
+ } else if (b0 == cs_escape) {
+ do_operator2(dest, limit, data, endptr);
+ } else if (b0 < 32 && b0 != 28) { /* 19, 20 need mask */
+ do_operator1(dest, limit, data, endptr);
+ } else if ((b0 <= 22 && b0 >= 27) || b0 == 31) { /* reserved */
+ status = CS_PARSE_CFF_ERROR; /* not an error ? */
+ } else { /* integer */
+ cs2_get_integer(data, endptr);
+ }
+ }
+
+ if (status == CS_SUBR_RETURN) {
+ status = CS_PARSE_OK;
+ } else if (status == CS_CHAR_END && *data < endptr) {
+ WARN("%s: Garbage after endchar.", CS_TYPE2_DEBUG_STR);
+ } else if (status < CS_PARSE_OK) { /* error */
+ CFF_ERROR("%s: Parsing charstring failed: (status=%d, stack=%d)",
+ CS_TYPE2_DEBUG_STR, status, cs2_stack_top);
+ }
+
+ cs2_nest--;
+
+ return;
+}
+
+static void
+cs_parse_init (void)
+{
+ status = CS_PARSE_OK;
+ cs2_nest = 0;
+ phase = 0;
+ num_stems = 0;
+ cs2_stack_top = 0;
+}
+
+/*
+ * Not just copying...
+ */
+long
+cs_copy_charstring (card8 *dst, long dstlen,
+ card8 *src, long srclen,
+ cff_index *gsubr, cff_index *subr,
+ double default_width, double nominal_width, cs_ginfo *ginfo)
+{
+ card8 *save = dst;
+
+ cs_parse_init();
+
+ width = 0.0;
+ have_width = 0;
+
+ /* expand call(g)subrs */
+ do_charstring(&dst, dst + dstlen, &src, src + srclen, gsubr, subr);
+
+ if (ginfo) {
+ ginfo->flags = 0; /* not used */
+ if (have_width) {
+ ginfo->wx = nominal_width + width;
+ } else {
+ ginfo->wx = default_width;
+ }
+ }
+
+ return (long)(dst - save);
+}
+
+/* encodings */
+
+/*
+ * Encoding and Charset
+ *
+ * Encoding and Charset arrays always begin with GID = 1.
+ */
+long cff_read_encoding (cff_font *cff)
+{
+ cff_encoding *encoding;
+ long offset, length;
+ card8 i;
+
+ if (cff->topdict == NULL) {
+ CFF_ERROR("Top DICT data not found");
+ }
+
+ if (!cff_dict_known(cff->topdict, "Encoding")) {
+ cff->flag |= ENCODING_STANDARD;
+ cff->encoding = NULL;
+ return 0;
+ }
+
+ offset = (long) cff_dict_get(cff->topdict, "Encoding", 0);
+ if (offset == 0) { /* predefined */
+ cff->flag |= ENCODING_STANDARD;
+ cff->encoding = NULL;
+ return 0;
+ } else if (offset == 1) {
+ cff->flag |= ENCODING_EXPERT;
+ cff->encoding = NULL;
+ return 0;
+ }
+
+ cff->offset= offset;
+ cff->encoding = encoding = xcalloc(1, sizeof(cff_encoding));
+ encoding->format = get_card8(cff);
+ length = 1;
+
+ switch (encoding->format & (~0x80)) {
+ case 0:
+ encoding->num_entries = get_card8(cff);
+ (encoding->data).codes = xcalloc(encoding->num_entries, sizeof(card8));
+ for (i=0;i<(encoding->num_entries);i++) {
+ (encoding->data).codes[i] = get_card8(cff);
+ }
+ length += encoding->num_entries + 1;
+ break;
+ case 1:
+ {
+ cff_range1 *ranges;
+ encoding->num_entries = get_card8(cff);
+ encoding->data.range1 = ranges
+ = xcalloc(encoding->num_entries, sizeof(cff_range1));
+ for (i=0;i<(encoding->num_entries);i++) {
+ ranges[i].first = get_card8(cff);
+ ranges[i].n_left = get_card8(cff);
+ }
+ length += (encoding->num_entries) * 2 + 1;
+ }
+ break;
+ default:
+ xfree(encoding);
+ CFF_ERROR("Unknown Encoding format");
+ break;
+ }
+
+ /* Supplementary data */
+ if ((encoding->format) & 0x80) {
+ cff_map *map;
+ encoding->num_supps = get_card8(cff);
+ encoding->supp = map = xcalloc(encoding->num_supps, sizeof(cff_map));
+ for (i=0;i<(encoding->num_supps);i++) {
+ map[i].code = get_card8(cff);
+ map[i].glyph = get_card16(cff); /* SID */
+ }
+ length += (encoding->num_supps) * 3 + 1;
+ } else {
+ encoding->num_supps = 0;
+ encoding->supp = NULL;
+ }
+
+ return length;
+}
+
+long cff_pack_encoding (cff_font *cff, card8 *dest, long destlen)
+{
+ long len = 0;
+ cff_encoding *encoding;
+ card16 i;
+
+ if (cff->flag & HAVE_STANDARD_ENCODING || cff->encoding == NULL)
+ return 0;
+
+ if (destlen < 2)
+ CFF_ERROR("in cff_pack_encoding(): Buffer overflow");
+
+ encoding = cff->encoding;
+
+ dest[len++] = encoding->format;
+ dest[len++] = encoding->num_entries;
+ switch (encoding->format & (~0x80)) {
+ case 0:
+ if (destlen < len + encoding->num_entries)
+ CFF_ERROR("in cff_pack_encoding(): Buffer overflow");
+ for (i=0;i<(encoding->num_entries);i++) {
+ dest[len++] = (encoding->data).codes[i];
+ }
+ break;
+ case 1:
+ {
+ if (destlen < len + (encoding->num_entries)*2)
+ CFF_ERROR("in cff_pack_encoding(): Buffer overflow");
+ for (i=0;i<(encoding->num_entries);i++) {
+ dest[len++] = (encoding->data).range1[i].first & 0xff;
+ dest[len++] = (encoding->data).range1[i].n_left;
+ }
+ }
+ break;
+ default:
+ CFF_ERROR("Unknown Encoding format");
+ break;
+ }
+
+ if ((encoding->format) & 0x80) {
+ if (destlen < len + (encoding->num_supps)*3 + 1)
+ CFF_ERROR("in cff_pack_encoding(): Buffer overflow");
+ dest[len++] = encoding->num_supps;
+ for (i=0;i<(encoding->num_supps);i++) {
+ dest[len++] = (encoding->supp)[i].code;
+ dest[len++] = ((encoding->supp)[i].glyph >> 8) & 0xff;
+ dest[len++] = (encoding->supp)[i].glyph & 0xff;
+ }
+ }
+
+ return len;
+}
+
+/* CID-Keyed font specific */
+long cff_read_fdselect (cff_font *cff)
+{
+ cff_fdselect *fdsel;
+ long offset, length;
+ card16 i;
+
+ if (cff->topdict == NULL)
+ CFF_ERROR("Top DICT not available");
+
+ if (!(cff->flag & FONTTYPE_CIDFONT))
+ return 0;
+
+ offset = (long) cff_dict_get(cff->topdict, "FDSelect", 0);
+ cff->offset = offset;
+ cff->fdselect = fdsel = xcalloc(1, sizeof(cff_fdselect));
+ fdsel->format = get_card8(cff);
+
+ length = 1;
+
+ switch (fdsel->format) {
+ case 0:
+ fdsel->num_entries = cff->num_glyphs;
+ (fdsel->data).fds = xcalloc(fdsel->num_entries, sizeof(card8));
+ for (i=0;i<(fdsel->num_entries);i++) {
+ (fdsel->data).fds[i] = get_card8(cff);
+ }
+ length += fdsel->num_entries;
+ break;
+ case 3:
+ {
+ cff_range3 *ranges;
+ fdsel->num_entries = get_card16(cff);
+ fdsel->data.ranges = ranges = xcalloc(fdsel->num_entries, sizeof(cff_range3));
+ for (i=0;i<(fdsel->num_entries);i++) {
+ ranges[i].first = get_card16(cff);
+ ranges[i].fd = get_card8(cff);
+ }
+ if (ranges[0].first != 0)
+ CFF_ERROR("Range not starting with 0.");
+ if (cff->num_glyphs != get_card16(cff))
+ CFF_ERROR("Sentinel value mismatched with number of glyphs.");
+ length += (fdsel->num_entries) * 3 + 4;
+ }
+ break;
+ default:
+ xfree(fdsel);
+ CFF_ERROR("Unknown FDSelect format.");
+ break;
+ }
+
+ return length;
+}
+
+
+long cff_pack_fdselect (cff_font *cff, card8 *dest, long destlen)
+{
+ cff_fdselect *fdsel;
+ long len = 0;
+ card16 i;
+
+ if (cff->fdselect == NULL)
+ return 0;
+
+ if (destlen < 1)
+ CFF_ERROR("in cff_pack_fdselect(): Buffur overflow");
+
+ fdsel = cff->fdselect;
+
+ dest[len++] = fdsel->format;
+ switch (fdsel->format) {
+ case 0:
+ if (fdsel->num_entries != cff->num_glyphs)
+ CFF_ERROR("in cff_pack_fdselect(): Invalid data");
+ if (destlen < len + fdsel->num_entries)
+ CFF_ERROR("in cff_pack_fdselect(): Buffer overflow");
+ for (i=0;i<fdsel->num_entries;i++) {
+ dest[len++] = (fdsel->data).fds[i];
+ }
+ break;
+ case 3:
+ {
+ if (destlen < len + 2)
+ CFF_ERROR("in cff_pack_fdselect(): Buffer overflow");
+ len += 2;
+ for (i=0;i<(fdsel->num_entries);i++) {
+ if (destlen < len + 3)
+ CFF_ERROR("in cff_pack_fdselect(): Buffer overflow");
+ dest[len++] = ((fdsel->data).ranges[i].first >> 8) & 0xff;
+ dest[len++] = (fdsel->data).ranges[i].first & 0xff;
+ dest[len++] = (fdsel->data).ranges[i].fd;
+ }
+ if (destlen < len + 2)
+ CFF_ERROR("in cff_pack_fdselect(): Buffer overflow");
+ dest[len++] = (cff->num_glyphs >> 8) & 0xff;
+ dest[len++] = cff->num_glyphs & 0xff;
+ dest[1] = ((len/3 - 1) >> 8) & 0xff;
+ dest[2] = (len/3 - 1) & 0xff;
+ }
+ break;
+ default:
+ CFF_ERROR("Unknown FDSelect format.");
+ break;
+ }
+
+ return len;
+}
+
+
+
+/*
+ * Create an instance of embeddable font.
+ */
+static void
+write_fontfile (cff_font *cffont, char *fullname)
+{
+ cff_index *topdict, *fdarray, *private;
+ unsigned char *dest;
+ long destlen = 0, i, size;
+ long offset, topdict_offset, fdarray_offset;
+
+ /* DICT sizes (offset set to long int) */
+ topdict = cff_new_index(1);
+ fdarray = cff_new_index(cffont->num_fds);
+ private = cff_new_index(cffont->num_fds);
+
+ cff_dict_remove(cffont->topdict, "UniqueID");
+ cff_dict_remove(cffont->topdict, "XUID");
+ cff_dict_remove(cffont->topdict, "Private"); /* some bad font may have */
+ cff_dict_remove(cffont->topdict, "Encoding"); /* some bad font may have */
+
+ topdict->offset[1] = cff_dict_pack(cffont->topdict,
+ (card8 *) work_buffer,
+ WORK_BUFFER_SIZE) + 1;
+ for (i = 0;i < cffont->num_fds; i++) {
+ size = 0;
+ if (cffont->private && cffont->private[i]) {
+ size = cff_dict_pack(cffont->private[i],
+ (card8 *) work_buffer, WORK_BUFFER_SIZE);
+ if (size < 1) { /* Private had contained only Subr */
+ cff_dict_remove(cffont->fdarray[i], "Private");
+ }
+ }
+ (private->offset)[i+1] = (private->offset)[i] + size;
+ (fdarray->offset)[i+1] = (fdarray->offset)[i] +
+ cff_dict_pack(cffont->fdarray[i],
+ (card8 *) work_buffer, WORK_BUFFER_SIZE);
+ }
+
+ destlen = 4; /* header size */
+ destlen += cff_set_name(cffont, fullname);
+ destlen += cff_index_size(topdict);
+ destlen += cff_index_size(cffont->string);
+ destlen += cff_index_size(cffont->gsubr);
+ destlen += (cffont->charsets->num_entries) * 2 + 1; /* charset format 0 */
+ destlen += (cffont->fdselect->num_entries) * 3 + 5; /* fdselect format 3 */
+ destlen += cff_index_size(cffont->cstrings);
+ destlen += cff_index_size(fdarray);
+ destlen += private->offset[private->count] - 1; /* Private is not INDEX */
+
+ dest = xcalloc(destlen, sizeof(card8));
+
+ offset = 0;
+ /* Header */
+ offset += cff_put_header(cffont, dest + offset, destlen - offset);
+ /* Name */
+ offset += cff_pack_index(cffont->name, dest + offset, destlen - offset);
+ /* Top DICT */
+ topdict_offset = offset;
+ offset += cff_index_size(topdict);
+ /* Strings */
+ offset += cff_pack_index(cffont->string, dest + offset, destlen - offset);
+ /* Global Subrs */
+ offset += cff_pack_index(cffont->gsubr, dest + offset, destlen - offset);
+
+ /* charset */
+ cff_dict_set(cffont->topdict, "charset", 0, offset);
+ offset += cff_pack_charsets(cffont, dest + offset, destlen - offset);
+
+ /* FDSelect */
+ cff_dict_set(cffont->topdict, "FDSelect", 0, offset);
+ offset += cff_pack_fdselect(cffont, dest + offset, destlen - offset);
+
+ /* CharStrings */
+ cff_dict_set(cffont->topdict, "CharStrings", 0, offset);
+ offset += cff_pack_index(cffont->cstrings,
+ dest + offset, cff_index_size(cffont->cstrings));
+ cff_release_index(cffont->cstrings);
+ cffont->cstrings = NULL; /* Charstrings cosumes huge memory */
+
+ /* FDArray and Private */
+ cff_dict_set(cffont->topdict, "FDArray", 0, offset);
+ fdarray_offset = offset;
+ offset += cff_index_size(fdarray);
+
+ fdarray->data = xcalloc(fdarray->offset[fdarray->count] - 1, sizeof(card8));
+ for (i = 0; i < cffont->num_fds; i++) {
+ size = private->offset[i+1] - private->offset[i];
+ if (cffont->private[i] && size > 0) {
+ cff_dict_pack(cffont->private[i], dest + offset, size);
+ cff_dict_set(cffont->fdarray[i], "Private", 0, size);
+ cff_dict_set(cffont->fdarray[i], "Private", 1, offset);
+ }
+ cff_dict_pack(cffont->fdarray[i],
+ fdarray->data + (fdarray->offset)[i] - 1,
+ fdarray->offset[fdarray->count] - 1);
+ offset += size;
+ }
+
+ cff_pack_index(fdarray, dest + fdarray_offset, cff_index_size(fdarray));
+ cff_release_index(fdarray);
+ cff_release_index(private);
+
+ /* Finally Top DICT */
+ topdict->data = xcalloc(topdict->offset[topdict->count] - 1, sizeof(card8));
+ cff_dict_pack(cffont->topdict,
+ topdict->data, topdict->offset[topdict->count] - 1);
+ cff_pack_index(topdict, dest + topdict_offset, cff_index_size(topdict));
+ cff_release_index(topdict);
+
+ for (i = 0; i < offset; i++)
+ fb_putchar (dest[i]);
+
+ /*fprintf(stdout," (%i/%i)",offset,cffont->stream_size);*/
+ xfree(dest);
+ return ;
+}
+
+
+/* if the CFF data was converted from an old type1 font, then the .notdef
+ glyph may not be at id 0, so in that case |uglytype1fix| is nonzero */
+
+void write_cff(cff_font *cffont, fd_entry *fd, int uglytype1fix) {
+ cff_index *charstrings, *cs_idx;
+
+ long charstring_len, max_len;
+ long size, offset = 0;
+
+ card8 *data;
+ card16 num_glyphs, cs_count, code, gid, last_cid;
+
+ double nominal_width, default_width;
+
+ char *fullname;
+
+ glw_entry *glyph, *found;
+ struct avl_traverser t;
+
+
+
+
+ fullname = xcalloc(8+strlen(fd->fontname),1);
+ sprintf(fullname,"%s+%s",fd->subset_tag,fd->fontname);
+
+ /* finish parsing the CFF */
+ cff_read_private(cffont);
+ cff_read_subrs (cffont);
+
+ /*
+ * Widths
+ */
+ if (cffont->private[0] &&
+ cff_dict_known(cffont->private[0], "defaultWidthX")) {
+ default_width = (double) cff_dict_get(cffont->private[0], "defaultWidthX", 0);
+ } else {
+ default_width = CFF_DEFAULTWIDTHX_DEFAULT;
+ }
+ if (cffont->private[0] &&
+ cff_dict_known(cffont->private[0], "nominalWidthX")) {
+ nominal_width = (double) cff_dict_get(cffont->private[0], "nominalWidthX", 0);
+ } else {
+ nominal_width = CFF_NOMINALWIDTHX_DEFAULT;
+ }
+
+ num_glyphs = 0;
+ last_cid = 0;
+ glyph = xtalloc(1,glw_entry);
+
+ /* insert notdef */
+ glyph->id = uglytype1fix;
+ if (avl_find(fd->gl_tree, glyph)==NULL) {
+ /*fprintf(stderr,"seeding .notdef at %i\n",uglytype1fix);*/
+ avl_insert(fd->gl_tree, glyph);
+ glyph = xtalloc(1,glw_entry);
+ }
+
+
+ avl_t_init(&t, fd->gl_tree);
+ for (found = (glw_entry *) avl_t_first(&t, fd->gl_tree);
+ found != NULL;
+ found = (glw_entry *) avl_t_next(&t)) {
+ if (found->id > last_cid)
+ last_cid = found->id;
+ num_glyphs++;
+ }
+
+ {
+ cff_fdselect *fdselect;
+
+ fdselect = xcalloc(1, sizeof(cff_fdselect));
+ fdselect->format = 3;
+ fdselect->num_entries = 1;
+ fdselect->data.ranges = xcalloc(1, sizeof(cff_range3));
+ fdselect->data.ranges[0].first = 0;
+ fdselect->data.ranges[0].fd = 0;
+ cffont->fdselect = fdselect;
+ }
+
+ {
+ cff_charsets *charset;
+
+ charset = xcalloc(1, sizeof(cff_charsets));
+ charset->format = 0;
+ charset->num_entries = num_glyphs-1;
+ charset->data.glyphs = xcalloc(num_glyphs, sizeof(s_SID));
+
+ gid = 0;
+
+ avl_t_init(&t, fd->gl_tree);
+ for (found = (glw_entry *) avl_t_first(&t, fd->gl_tree);
+ found != NULL;
+ found = (glw_entry *) avl_t_next(&t)) {
+ if(found->id!=0) {
+ charset->data.glyphs[gid] = found->id;
+ gid++;
+ }
+ }
+ cffont->charsets = charset;
+ }
+
+ cff_dict_add(cffont->topdict, "CIDCount", 1);
+ cff_dict_set(cffont->topdict, "CIDCount", 0, last_cid + 1);
+
+ cffont->fdarray = xcalloc(1, sizeof(cff_dict *));
+ cffont->fdarray[0] = cff_new_dict();
+ cff_dict_add(cffont->fdarray[0], "FontName", 1);
+ cff_dict_set(cffont->fdarray[0], "FontName", 0,
+ (double) cff_add_string(cffont, fullname)); /* FIXME: Skip XXXXXX+ */
+ cff_dict_add(cffont->fdarray[0], "Private", 2);
+ cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0);
+ cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0);
+ /* FDArray - index offset, not known yet */
+ cff_dict_add(cffont->topdict, "FDArray", 1);
+ cff_dict_set(cffont->topdict, "FDArray", 0, 0.0);
+ /* FDSelect - offset, not known yet */
+ cff_dict_add(cffont->topdict, "FDSelect", 1);
+ cff_dict_set(cffont->topdict, "FDSelect", 0, 0.0);
+
+ cff_dict_remove(cffont->topdict, "UniqueID");
+ cff_dict_remove(cffont->topdict, "XUID");
+ cff_dict_remove(cffont->topdict, "Private");
+ cff_dict_remove(cffont->topdict, "Encoding");
+
+ cffont->offset = cff_dict_get(cffont->topdict, "CharStrings", 0);
+ cs_idx = cff_get_index_header(cffont);
+
+ offset = cffont->offset;
+ cs_count = cs_idx->count;
+ if (cs_count < 2) {
+ CFF_ERROR("No valid charstring data found.");
+ }
+
+ /* build the new charstrings entry */
+ charstrings = cff_new_index(cs_count+1);
+ max_len = 2 * CS_STR_LEN_MAX;
+ charstrings->data = xcalloc(max_len, sizeof(card8));
+ charstring_len = 0;
+
+ gid = 0;
+ data = xcalloc(CS_STR_LEN_MAX, sizeof(card8));
+
+ for (code=0; code < cs_count; code++) {
+ glyph->id = code;
+ if ((avl_find(fd->gl_tree,glyph) != NULL)) {
+ size = cs_idx->offset[code+1] - cs_idx->offset[code];
+
+ if (size > CS_STR_LEN_MAX) {
+ pdftex_fail("Charstring too long: gid=%u, %ld bytes", code, size);
+ }
+ if (charstring_len + CS_STR_LEN_MAX >= max_len) {
+ max_len = charstring_len + 2 * CS_STR_LEN_MAX;
+ charstrings->data = xrealloc(charstrings->data, max_len*sizeof(card8));
+ }
+ (charstrings->offset)[gid] = charstring_len + 1;
+ cffont->offset= offset + (cs_idx->offset)[code] - 1;
+ memcpy(data,&cffont->stream[cffont->offset],size);
+ charstring_len += cs_copy_charstring(charstrings->data + charstring_len,
+ max_len - charstring_len,
+ data, size,
+ cffont->gsubr, (cffont->subrs)[0],
+ default_width, nominal_width, NULL);
+ gid++;
+ }
+ }
+
+ /* this happens if the internal metrics do not agree with the actual disk font */
+ if (gid < num_glyphs) {
+ WARN("embedded subset is smaller than expected: %d instead of %d glyphs.", gid, num_glyphs);
+ num_glyphs = gid;
+ }
+
+ xfree(data);
+ cff_release_index(cs_idx);
+
+ (charstrings->offset)[num_glyphs] = charstring_len + 1;
+ charstrings->count = num_glyphs;
+ cffont->num_glyphs = num_glyphs;
+ cffont->cstrings = charstrings;
+
+ /*
+ * We don't use subroutines at all.
+ */
+ if (cffont->gsubr)
+ cff_release_index(cffont->gsubr);
+ cffont->gsubr = cff_new_index(0);
+
+ if (cffont->subrs && cffont->subrs[0])
+ cff_release_index(cffont->subrs[0]);
+ cffont->subrs[0] = NULL;
+
+ if (cffont->private && (cffont->private)[0]) {
+ cff_dict_remove((cffont->private)[0], "Subrs"); /* no Subrs */
+ }
+
+ cff_add_string(cffont, (char *)"Adobe");
+ cff_add_string(cffont, (char *)"Identity");
+
+ cff_dict_update(cffont->topdict, cffont);
+ cff_dict_update(cffont->private[0], cffont);
+ cff_update_string(cffont);
+
+ /* CFF code need to be rewrote... */
+ cff_dict_add(cffont->topdict, "ROS", 3);
+ cff_dict_set(cffont->topdict, "ROS", 0,
+ (double) cff_get_sid(cffont, (char *)"Adobe"));
+ cff_dict_set(cffont->topdict, "ROS", 1,
+ (double) cff_get_sid(cffont, (char *)"Identity"));
+ cff_dict_set(cffont->topdict, "ROS", 2, 0.0);
+
+ write_fontfile(cffont,fullname);
+ xfree(fullname);
+ cff_close (cffont);
+
+}
+
+#define ERROR(a) { perror(a); return 0; }
+
+/* Input : SID or CID (16-bit unsigned int)
+ * Output: glyph index
+ */
+card16
+cff_charsets_lookup (cff_font *cff, card16 cid)
+{
+ card16 gid = 0;
+ cff_charsets *charset;
+ card16 i;
+
+ if (cff->flag & (CHARSETS_ISOADOBE|CHARSETS_EXPERT|CHARSETS_EXPSUB)) {
+ ERROR("Predefined CFF charsets not supported yet");
+ } else if (cff->charsets == NULL) {
+ ERROR("Charsets data not available");
+ }
+
+ if (cid == 0) {
+ return 0; /* GID 0 (.notdef) */
+ }
+
+ charset = cff->charsets;
+
+ gid = 0;
+ switch (charset->format) {
+ case 0:
+ for (i = 0; i <charset->num_entries; i++) {
+ if (cid == charset->data.glyphs[i]) {
+ gid = i + 1;
+ return gid;
+ }
+ }
+ break;
+ case 1:
+ for (i = 0; i < charset->num_entries; i++) {
+ if (cid >= charset->data.range1[i].first &&
+ cid <= charset->data.range1[i].first + charset->data.range1[i].n_left) {
+ gid += cid - charset->data.range1[i].first + 1;
+ return gid;
+ }
+ gid += charset->data.range1[i].n_left + 1;
+ }
+ break;
+ case 2:
+ for (i = 0; i < charset->num_entries; i++) {
+ if (cid >= charset->data.range2[i].first &&
+ cid <= charset->data.range2[i].first + charset->data.range2[i].n_left) {
+ gid += cid - charset->data.range2[i].first + 1;
+ return gid;
+ }
+ gid += charset->data.range2[i].n_left + 1;
+ }
+ break;
+ default:
+ ERROR("Unknown Charset format");
+ }
+
+ return 0; /* not found */
+}
+
+
+#define is_cidfont(a) ((a)->flag & FONTTYPE_CIDFONT)
+#define CID_MAX 65535
+
+void write_cid_cff(cff_font *cffont, fd_entry *fd, int uglytype1fix) {
+ cff_index *charstrings, *cs_idx;
+
+ long charstring_len, max_len;
+ long size, offset = 0;
+
+ card8 *data;
+ card16 num_glyphs, cs_count, gid, last_cid;
+
+
+ int fdsel, prev_fd, cid_count, cid;
+ char *fullname;
+
+ glw_entry *glyph;
+
+ unsigned char *CIDToGIDMap = NULL;
+
+ cff_fdselect *fdselect = NULL;
+ cff_charsets *charset = NULL;
+
+
+ if (!is_cidfont(cffont)) {
+ perror("Not a CIDfont.");
+ return;
+ }
+
+ fullname = xcalloc(8+strlen(fd->fontname),1);
+ sprintf(fullname,"%s+%s",fd->subset_tag,fd->fontname);
+
+ /* finish parsing the CFF */
+
+ if (cff_dict_known(cffont->topdict, "CIDCount")) {
+ cid_count = (card16) cff_dict_get(cffont->topdict, "CIDCount", 0);
+ } else {
+ cid_count = CFF_CIDCOUNT_DEFAULT;
+ }
+ cff_read_charsets(cffont);
+ CIDToGIDMap = xmalloc((2*cid_count) * sizeof(unsigned char));
+ memset(CIDToGIDMap, 0, 2*cid_count);
+
+
+ glyph = xtalloc(1,glw_entry);
+ /* insert notdef */
+ glyph->id = uglytype1fix;
+ if (avl_find(fd->gl_tree, glyph)==NULL) {
+ avl_insert(fd->gl_tree, glyph);
+ glyph = xtalloc(1,glw_entry);
+ }
+
+ cid = 0; last_cid = 0; num_glyphs = 0;
+ for (cid = 0; cid <= CID_MAX; cid++) {
+ glyph->id = cid;
+ if (avl_find(fd->gl_tree,glyph) != NULL) {
+ gid = cff_charsets_lookup(cffont, cid);
+ CIDToGIDMap[2*cid] = (gid >> 8) & 0xff;
+ CIDToGIDMap[2*cid+1] = gid & 0xff;
+ last_cid = cid;
+ num_glyphs++;
+ }
+ }
+
+ cff_read_fdselect(cffont);
+ cff_read_fdarray(cffont);
+ cff_read_private(cffont);
+
+ cff_read_subrs (cffont);
+
+
+ cffont->offset = cff_dict_get(cffont->topdict, "CharStrings", 0);
+ cs_idx = cff_get_index_header(cffont);
+
+ offset = cffont->offset;
+ cs_count = cs_idx->count;
+ if (cs_count < 2) {
+ CFF_ERROR("No valid charstring data found.");
+ }
+
+ charset = xcalloc(1, sizeof(cff_charsets));
+ charset->format = 0;
+ charset->num_entries = 0;
+ charset->data.glyphs = xcalloc(num_glyphs, sizeof(s_SID));
+
+ fdselect = xcalloc(1, sizeof(cff_fdselect));
+ fdselect->format = 3;
+ fdselect->num_entries = 0;
+ fdselect->data.ranges = xcalloc(num_glyphs, sizeof(cff_range3));
+
+ charstrings = cff_new_index(cs_count+1);
+ max_len = 2 * CS_STR_LEN_MAX;
+ charstrings->data = xcalloc(max_len, sizeof(card8));
+ charstring_len = 0;
+
+ prev_fd = -1; gid = 0;
+ data = xcalloc(CS_STR_LEN_MAX, sizeof(card8));
+ for (cid=0; cid <= last_cid; cid++) {
+ unsigned short gid_org;
+
+ glyph->id = cid;
+ if (avl_find(fd->gl_tree,glyph) == NULL)
+ continue;
+
+ gid_org = (CIDToGIDMap[2*cid] << 8)|(CIDToGIDMap[2*cid+1]);
+ size = cs_idx->offset[gid_org+1] - cs_idx->offset[gid_org];
+ if (size > CS_STR_LEN_MAX) {
+ pdftex_fail("Charstring too long: gid=%u, %ld bytes", cid, size);
+ }
+ if (charstring_len + CS_STR_LEN_MAX >= max_len) {
+ max_len = charstring_len + 2 * CS_STR_LEN_MAX;
+ charstrings->data = xrealloc(charstrings->data, max_len*sizeof(card8));
+ }
+ (charstrings->offset)[gid] = charstring_len + 1;
+ cffont->offset= offset + (cs_idx->offset)[gid_org] - 1;
+ memcpy(data,&cffont->stream[cffont->offset],size);
+ fdsel = cff_fdselect_lookup(cffont, gid_org);
+ charstring_len += cs_copy_charstring(charstrings->data + charstring_len,
+ max_len - charstring_len,
+ data, size,
+ cffont->gsubr, (cffont->subrs)[fdsel],
+ 0, 0, NULL);
+
+ if (cid>0 && gid_org > 0) {
+ charset->data.glyphs[charset->num_entries] = cid;
+ charset->num_entries += 1;
+ }
+ if (fdsel != prev_fd) {
+ fdselect->data.ranges[fdselect->num_entries].first = gid;
+ fdselect->data.ranges[fdselect->num_entries].fd = fdsel;
+ fdselect->num_entries += 1;
+ prev_fd = fdsel;
+ }
+ gid++;
+ }
+
+ if (gid != num_glyphs)
+ CFF_ERROR("Unexpected error: %i != %i", gid, num_glyphs);
+ xfree(data);
+ cff_release_index(cs_idx);
+
+ xfree(CIDToGIDMap);
+
+ (charstrings->offset)[num_glyphs] = charstring_len + 1;
+ charstrings->count = num_glyphs;
+ cffont->num_glyphs = num_glyphs;
+ cffont->cstrings = charstrings;
+
+ cff_release_charsets(cffont->charsets);
+ cffont->charsets = charset;
+ cff_release_fdselect(cffont->fdselect);
+ cffont->fdselect = fdselect;
+
+ /*
+ * We don't use subroutines at all.
+ */
+ if (cffont->gsubr)
+ cff_release_index(cffont->gsubr);
+ cffont->gsubr = cff_new_index(0);
+
+ for (fdsel = 0; fdsel < cffont->num_fds; fdsel++) {
+ if (cffont->subrs && cffont->subrs[fdsel]) {
+ cff_release_index(cffont->subrs[fdsel]);
+ cffont->subrs[fdsel] = NULL;
+ }
+ if (cffont->private && (cffont->private)[fdsel]) {
+ cff_dict_remove((cffont->private)[fdsel], "Subrs"); /* no Subrs */
+ }
+ }
+
+ write_fontfile(cffont,fullname);
+ xfree(fullname);
+ cff_close (cffont);
+
+}
+
+
+/* here is a sneaky trick: fontforge knows how to convert Type1 to CFF, so
+ * I have defined a utility function in luafflib.c that does exactly that.
+ * If it works out ok, I will clean up this code.
+ */
+
+extern int ff_createcff (char *, unsigned char **, integer *);
+
+void writetype1w (fd_entry *fd) {
+ cff_font *cff;
+ int i;
+ FILE *fp;
+ ff_entry *ff;
+ unsigned char *tfm_buffer = NULL;
+ integer tfm_size = 0;
+ int notdefpos = 0;
+
+ ff = check_ff_exist(fd->fm->ff_name, 0);
+
+ fp = fopen (ff->ff_path, "rb");
+ cur_file_name = ff->ff_path;
+
+ if (!fp) {
+ fprintf(stderr,"Type1: Could not open Type1 font: %s", cur_file_name);
+ uexit(1);
+ }
+ fclose(fp);
+
+ if (tracefilenames) {
+ if (is_subsetted(fd->fm))
+ tex_printf ("<%s", cur_file_name);
+ else
+ tex_printf ("<<%s", cur_file_name);
+ }
+
+ notdefpos = ff_createcff(ff->ff_path,&tfm_buffer,&tfm_size);
+
+ if (tfm_size>0) {
+ cff = read_cff(tfm_buffer,tfm_size,0);
+ if (cff != NULL) {
+ write_cff(cff,fd,notdefpos);
+ } else {
+ for (i = 0; i < tfm_size ; i++)
+ fb_putchar (tfm_buffer[i]);
+ }
+ fd->ff_found = 1;
+ } else {
+ fprintf(stderr,"Type1: Could not understand Type1 font: %s", cur_file_name);
+ uexit(1);
+ }
+ if (tracefilenames) {
+ if (is_subsetted (fd->fm))
+ tex_printf (">");
+ else
+ tex_printf (">>");
+ }
+ cur_file_name = NULL;
+}
+
+
diff --git a/Build/source/texk/web2c/luatexdir/font/writecff.h b/Build/source/texk/web2c/luatexdir/font/writecff.h
new file mode 100644
index 00000000000..8cb93024f7a
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writecff.h
@@ -0,0 +1,349 @@
+/* $Header: /home/cvsroot/dvipdfmx/src/cff_limits.h,v 1.3 2002/10/30 02:27:05 chofchof Exp $
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+#ifndef _CFF_LIMITS_H_
+#define _CFF_LIMITS_H_
+
+#include <limits.h>
+
+#define CFF_INT_MAX 0x7fffffff
+#define CFF_INT_MIN (-0x7fffffff - 1)
+
+#if (LONG_MAX < CFF_INT_MAX || LONG_MIN > CFF_INT_MIN)
+#error "CFF support won't work on this system."
+#endif
+
+#define CFF_SID_MAX 64999
+#define CFF_STDSTR_MAX 391
+
+/* Type 2 Charstring */
+#define CS_NUM_SUBR_MAX 65536
+#define CS_STR_LEN_MAX 65536
+#define CS_STEM_ZONE_MAX 96
+#define CS_ARG_STACK_MAX 48
+#define CS_TRANS_ARRAY_MAX 32
+#define CS_SUBR_NEST_MAX 10
+
+#endif /* _CFF_LIMITS_H_ */
+
+#ifndef _CFF_TYPES_H_
+#define _CFF_TYPES_H_
+
+/* CFF Data Types */
+
+#define CFF_TYPE_UNKNOWN 0
+#define CFF_TYPE_INTEGER (1 << 0)
+#define CFF_TYPE_REAL (1 << 1)
+#define CFF_TYPE_NUMBER (CFF_TYPE_INTEGER|CFF_TYPE_REAL)
+#define CFF_TYPE_BOOLEAN (1 << 2)
+#define CFF_TYPE_SID (1 << 3)
+#define CFF_TYPE_ARRAY (1 << 4)
+#define CFF_TYPE_DELTA (1 << 5)
+
+/* SID SID number */
+#define CFF_TYPE_ROS (1 << 6)
+/* offset(0) */
+#define CFF_TYPE_OFFSET (1 << 7)
+/* size offset(0) */
+#define CFF_TYPE_SZOFF (1 << 8)
+
+typedef unsigned char card8; /* 1-byte unsigned number */
+typedef unsigned short card16; /* 2-byte unsigned number */
+typedef unsigned char c_offsize; /* 1-byte unsigned number specifies the size
+ of an Offset field or fields, range 1-4 */
+typedef unsigned long l_offset; /* 1, 2, 3, or 4-byte offset */
+typedef unsigned short s_SID; /* 2-byte string identifier */
+
+typedef unsigned long l_size;
+
+typedef struct {
+ card16 count; /* number of objects stored in INDEX */
+ c_offsize offsize; /* Offset array element size, 1-4 */
+ l_offset *offset; /* Offset array, count + 1 offsets */
+ card8 *data; /* Object data */
+} cff_index;
+
+
+/* Dictionary */
+typedef struct {
+ int id; /* encoded data value (as card8 or card16) */
+ char *key; /* opname */
+ int count; /* number of values */
+ double *values; /* values */
+} cff_dict_entry;
+
+typedef struct {
+ int max;
+ int count;
+ cff_dict_entry *entries;
+} cff_dict;
+
+/* Encoding, Charset and FDSelect */
+typedef struct
+{
+ s_SID first; /* SID or CID, or card8 for Encoding */
+ card8 n_left; /* no. of remaining gids/codes in this range */
+} cff_range1;
+
+typedef struct
+{
+ s_SID first; /* SID or CID (card16) */
+ card16 n_left; /* card16-version of range1 */
+} cff_range2;
+
+typedef struct
+{
+ card8 code;
+ s_SID glyph;
+} cff_map;
+
+typedef struct
+{
+ card8 format; /* if (format & 0x80) then have supplement */
+ card8 num_entries; /* number of entries */
+ union {
+ card8 *codes; /* format 0 */
+ cff_range1 *range1; /* format 1 */
+ } data;
+ card8 num_supps; /* number of supplementary data */
+ cff_map *supp; /* supplement */
+} cff_encoding;
+
+typedef struct
+{
+ card8 format;
+ card16 num_entries;
+ union {
+ s_SID *glyphs; /* format 0 */
+ cff_range1 *range1; /* format 1 */
+ cff_range2 *range2; /* format 2 */
+ } data;
+} cff_charsets;
+
+/* CID-Keyed font specific */
+typedef struct
+{
+ card16 first;
+ card8 fd;
+} cff_range3;
+
+typedef struct
+{
+ card8 format;
+ card16 num_entries; /* number of glyphs/ranges */
+ union {
+ card8 *fds; /* format 0 */
+ cff_range3 *ranges; /* format 3 */
+ } data;
+ /* card16 sentinel; */ /* format 3 only, must be equals to num_glyphs */
+} cff_fdselect;
+
+#endif /* _CFF_TYPES_H_ */
+
+#ifndef _CFF_STDSTR_H_
+#define _CFF_STDSTR_H_
+
+#define CFF_STDSTR_MAX 391
+
+extern const char *const cff_stdstr[];
+#endif /* _CFF_STDSTR_H_ */
+
+#ifndef _CFF_H_
+#define _CFF_H_
+
+/*#include "mfileio.h"*/
+
+/* Flag */
+#define FONTTYPE_CIDFONT (1 << 0)
+#define FONTTYPE_FONT (1 << 1)
+#define FONTTYPE_MMASTER (1 << 2)
+
+#define ENCODING_STANDARD (1 << 3)
+#define ENCODING_EXPERT (1 << 4)
+
+#define CHARSETS_ISOADOBE (1 << 5)
+#define CHARSETS_EXPERT (1 << 6)
+#define CHARSETS_EXPSUB (1 << 7)
+
+#define HAVE_STANDARD_ENCODING (ENCODING_STANDARD|ENCODING_EXPERT)
+#define HAVE_STANDARD_CHARSETS \
+ (CHARSETS_ISOADOBE|CHARSETS_EXPERT|CHARSETS_EXPSUB)
+
+#define CFF_STRING_NOTDEF 65535
+
+typedef struct
+{
+ char *fontname; /* FontName */
+
+ /* - CFF structure - */
+
+ card8 header_major; /* major version */
+ card8 header_minor; /* minor version */
+ card8 header_hdr_size; /* Header size (bytes) */
+ c_offsize header_offsize; /* Absolute offset (0) size */
+
+ cff_index *name; /* Name INDEX */
+ cff_dict *topdict; /* Top DICT (single) */
+ cff_index *string; /* String INDEX */
+ cff_index *gsubr; /* Global Subr INDEX */
+ cff_encoding *encoding; /* Encodings */
+ cff_charsets *charsets; /* Charsets */
+ cff_fdselect *fdselect; /* FDSelect, CIDFont only */
+ cff_index *cstrings; /* CharStrings */
+ cff_dict **fdarray; /* CIDFont only */
+ cff_dict **private; /* per-Font DICT */
+ cff_index **subrs; /* Local Subr INDEX, per-Private DICT */
+
+ /* -- extra data -- */
+ l_offset gsubr_offset;
+ card16 num_glyphs; /* number of glyphs (CharString INDEX count) */
+ card8 num_fds; /* number of Font DICT */
+
+ /* Updated String INDEX.
+ * Please fix this. We should separate input and output.
+ */
+ cff_index *_string;
+
+ unsigned char *stream;
+ l_offset offset;
+ l_offset stream_size;
+
+ int index; /* CFF fontset index */
+ int flag; /* Flag: see above */
+} cff_font;
+
+extern cff_font *cff_open(unsigned char *stream, long stream_size, int n);
+extern void cff_close (cff_font *cff);
+
+#define cff_seek_set(c, p) seek_absolute (((c)->stream), ((c)->offset) + (p));
+
+/* CFF Header */
+extern long cff_put_header (cff_font *cff, card8 *dest, long destlen);
+
+/* CFF INDEX */
+extern cff_index *cff_get_index (cff_font *cff);
+extern cff_index *cff_get_index_header (cff_font *cff);
+extern void cff_release_index (cff_index *idx);
+extern cff_index *cff_new_index (card16 count);
+extern long cff_index_size (cff_index *idx);
+extern long cff_pack_index (cff_index *idx, card8 *dest, long destlen);
+
+/* Name INDEX */
+extern char *cff_get_name (cff_font *cff);
+extern long cff_set_name (cff_font *cff, char *name);
+
+/* Global and Local Subrs INDEX */
+extern long cff_read_subrs (cff_font *cff);
+
+/* Encoding */
+extern long cff_read_encoding (cff_font *cff);
+extern long cff_pack_encoding (cff_font *cff, card8 *dest, long destlen);
+extern card16 cff_encoding_lookup (cff_font *cff, card8 code);
+extern void cff_release_encoding (cff_encoding *encoding);
+
+/* Charsets */
+extern long cff_read_charsets (cff_font *cff);
+extern long cff_pack_charsets (cff_font *cff, card8 *dest, long destlen);
+
+/* Returns GID of PS name "glyph" */
+extern card16 cff_glyph_lookup (cff_font *cff, const char *glyph);
+/* Returns GID of glyph with SID/CID "cid" */
+extern card16 cff_charsets_lookup (cff_font *cff, card16 cid);
+extern void cff_release_charsets (cff_charsets *charset);
+/* Returns SID or CID */
+extern card16 cff_charsets_lookup_inverse (cff_font *cff, card16 gid);
+
+/* FDSelect */
+extern long cff_read_fdselect (cff_font *cff);
+extern long cff_pack_fdselect (cff_font *cff, card8 *dest, long destlen);
+extern card8 cff_fdselect_lookup (cff_font *cff, card16 gid);
+extern void cff_release_fdselect (cff_fdselect *fdselect);
+
+/* Font DICT(s) */
+extern long cff_read_fdarray (cff_font *cff);
+
+/* Private DICT(s) */
+extern long cff_read_private (cff_font *cff);
+
+/* String */
+extern int cff_match_string (cff_font *cff, const char *str, s_SID sid);
+extern char *cff_get_string (cff_font *cff, s_SID id);
+extern long cff_get_sid (cff_font *cff, char *str);
+extern s_SID cff_add_string (cff_font *cff, char *str);
+extern void cff_update_string (cff_font *cff);
+
+#define cff_is_stdstr(s) (cff_get_sid(NULL, (s)) >= 0)
+
+#endif /* _CFF_H_ */
+
+#ifndef _CFF_DICT_H_
+#define _CFF_DICT_H_
+
+#define CFF_CIDCOUNT_DEFAULT 8720
+#define CFF_NOMINALWIDTHX_DEFAULT 0.0
+#define CFF_DEFAULTWIDTHX_DEFAULT 0.0
+
+extern cff_dict *cff_new_dict (void);
+extern void cff_release_dict (cff_dict *dict);
+
+extern void cff_dict_set (cff_dict *dict, const char *key, int idx, double value);
+extern double cff_dict_get (cff_dict *dict, const char *key, int idx);
+extern void cff_dict_add (cff_dict *dict, const char *key, int count);
+extern void cff_dict_remove (cff_dict *dict, const char *key);
+extern int cff_dict_known (cff_dict *dict, const char *key);
+
+/* decode/encode DICT */
+extern cff_dict *cff_dict_unpack (card8 *data, card8 *endptr);
+extern long cff_dict_pack (cff_dict *dict, card8 *dest, long destlen);
+
+extern void cff_dict_update (cff_dict *dict, cff_font *cff);
+
+#endif /* _CFF_DICT_H_ */
+
+#ifndef _CS_TYPE2_H_
+#define _CS_TYPE2_H_
+
+typedef struct {
+ int flags; /* unused in Type 2 charstring */
+ double wx, wy;
+ struct {
+ double llx, lly, urx, ury;
+ } bbox;
+ struct {
+ double asb, adx, ady;
+ card8 bchar, achar;
+ } seac; /* unused in Type 2 charstring */
+} cs_ginfo;
+
+extern long cs_copy_charstring (card8 *dest, long destlen,
+ card8 *src, long srclen,
+ cff_index *gsubr, cff_index *subr,
+ double default_width, double nominal_width, cs_ginfo *ginfo);
+#endif /* _CS_TYPE2_H_ */
+
+#define cff_is_cidfont(a) (a->flag & FONTTYPE_CIDFONT)
+#define cff_understandable(a) (a->header_major==1)
+
+extern cff_font *read_cff(unsigned char *buf,long buflength, int subf);
+
+extern void write_cff(cff_font *cff, fd_entry *fd, int hack);
+extern void write_cid_cff(cff_font *cffont, fd_entry *fd, int uglytype1fix) ;
diff --git a/Build/source/texk/web2c/luatexdir/font/writeenc.c b/Build/source/texk/web2c/luatexdir/font/writeenc.c
new file mode 100644
index 00000000000..feaf1407d1e
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writeenc.c
@@ -0,0 +1,183 @@
+/*
+Copyright (c) 1996-2005 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writeenc.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+
+/**********************************************************************/
+/* All encoding entries go into AVL tree for fast search by name. */
+
+struct avl_table *fe_tree = NULL;
+
+/* AVL sort fe_entry into fe_tree by name */
+
+static int comp_fe_entry(const void *pa, const void *pb, void *p)
+{
+ return strcmp(((const fe_entry *) pa)->name, ((const fe_entry *) pb)->name);
+}
+
+fe_entry *new_fe_entry()
+{
+ fe_entry *fe;
+ fe = xtalloc(1, fe_entry);
+ fe->name = NULL;
+ fe->fe_objnum = 0;
+ fe->glyph_names = NULL; /* encoding file not yet read in */
+ fe->tx_tree = NULL;
+ return fe;
+}
+
+fe_entry *lookup_fe_entry(char *s)
+{
+ fe_entry fe;
+ assert(s != NULL);
+ fe.name = s;
+ if (fe_tree == NULL) {
+ fe_tree = avl_create(comp_fe_entry, NULL, &avl_xallocator);
+ assert(fe_tree != NULL);
+ }
+ return (fe_entry *) avl_find(fe_tree, &fe);
+}
+
+void register_fe_entry(fe_entry * fe)
+{
+ void **aa;
+ if (fe_tree == NULL) {
+ fe_tree = avl_create(comp_fe_entry, NULL, &avl_xallocator);
+ assert(fe_tree != NULL);
+ }
+ assert(fe != NULL);
+ assert(fe->name != NULL);
+ assert(lookup_fe_entry(fe->name) == NULL); /* encoding not yet registered */
+ aa = avl_probe(fe_tree, fe);
+ assert(aa != NULL);
+}
+
+fe_entry *get_fe_entry(char *s)
+{
+ fe_entry *fe;
+ char **gl;
+ if ((fe = lookup_fe_entry(s)) == NULL && (gl = load_enc_file(s)) != NULL) {
+ fe = new_fe_entry();
+ fe->name = s;
+ fe->glyph_names = gl;
+ register_fe_entry(fe);
+ }
+ return fe;
+}
+
+/**********************************************************************/
+
+void epdf_write_enc(char **glyph_names, integer fe_objnum)
+{
+ int i, i_old;
+ assert(glyph_names != NULL);
+ assert(fe_objnum != 0);
+ pdf_begin_dict(fe_objnum, 1);
+ pdf_puts("/Type /Encoding\n");
+ pdf_printf("/Differences [");
+ for (i = 0, i_old = -2; i < 256; i++)
+ if (glyph_names[i] != notdef) {
+ if (i == i_old + 1) /* no gap */
+ pdf_printf("/%s", glyph_names[i]);
+ else {
+ if (i_old == -2)
+ pdf_printf("%i/%s", i, glyph_names[i]);
+ else
+ pdf_printf(" %i/%s", i, glyph_names[i]);
+ }
+ i_old = i;
+ }
+ pdf_puts("]\n");
+ pdf_end_dict();
+}
+
+void write_enc(char **glyph_names, struct avl_table *tx_tree, integer fe_objnum)
+{
+ int i_old, *p;
+ struct avl_traverser t;
+ assert(glyph_names != NULL);
+ assert(tx_tree != NULL);
+ assert(fe_objnum != 0);
+ pdf_begin_dict(fe_objnum, 1);
+ pdf_puts("/Type /Encoding\n");
+ pdf_printf("/Differences [");
+ avl_t_init(&t, tx_tree);
+ for (i_old = -2, p = (int *) avl_t_first(&t, tx_tree); p != NULL;
+ p = (int *) avl_t_next(&t)) {
+ if (*p == i_old + 1) /* no gap */
+ pdf_printf("/%s", glyph_names[*p]);
+ else {
+ if (i_old == -2)
+ pdf_printf("%i/%s", *p, glyph_names[*p]);
+ else
+ pdf_printf(" %i/%s", *p, glyph_names[*p]);
+ }
+ i_old = *p;
+ }
+ pdf_puts("]\n");
+ pdf_end_dict();
+}
+
+void write_fontencoding(fe_entry * fe)
+{
+ assert(fe != NULL);
+ write_enc(fe->glyph_names, fe->tx_tree, fe->fe_objnum);
+}
+
+void write_fontencodings()
+{
+ fe_entry *fe;
+ struct avl_traverser t;
+ if (fe_tree == NULL)
+ return;
+ avl_t_init(&t, fe_tree);
+ for (fe = (fe_entry *) avl_t_first(&t, fe_tree); fe != NULL;
+ fe = (fe_entry *) avl_t_next(&t))
+ if (fe->fe_objnum != 0)
+ write_fontencoding(fe);
+}
+
+/**********************************************************************/
+/* cleaning up... */
+
+static void destroy_fe_entry(void *pa, void *pb)
+{
+ fe_entry *p;
+ int i;
+ p = (fe_entry *) pa;
+ xfree(p->name);
+ if (p->glyph_names != NULL)
+ for (i = 0; i < 256; i++)
+ if (p->glyph_names[i] != notdef)
+ xfree(p->glyph_names[i]);
+ xfree(p->glyph_names);
+ xfree(p);
+}
+
+void enc_free()
+{
+ if (fe_tree != NULL)
+ avl_destroy(fe_tree, destroy_fe_entry);
+ fe_tree = NULL;
+}
+
+/**********************************************************************/
diff --git a/Build/source/texk/web2c/luatexdir/font/writefont.c b/Build/source/texk/web2c/luatexdir/font/writefont.c
new file mode 100644
index 00000000000..05257746889
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writefont.c
@@ -0,0 +1,885 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writefont.c 1112 2008-03-20 14:46:32Z taco $
+*/
+
+#include "ptexlib.h"
+
+extern void writetype0 (fd_entry * fd) ;
+extern void writetype2 (fd_entry * fd) ;
+extern unsigned long cidtogid_obj;
+
+#ifdef DO_TYPE1C
+extern void writet1c(fd_entry * fd); /* in writecff.c */
+#endif
+
+extern void writet1w (fd_entry * fd); /* in writecff.c */
+extern void writetype1w (fd_entry * fd);
+extern integer write_cid_tounicode(fo_entry * fo, internalfontnumber f); /* in tounicode.c */
+
+
+void write_cid_fontdictionary(fo_entry * fo, internalfontnumber f);
+void create_cid_fontdictionary(fm_entry * fm, integer font_objnum, internalfontnumber f);
+
+/**********************************************************************/
+
+struct avl_table *fo_tree = NULL; /* tree of font dictionaries */
+struct avl_table *fd_tree = NULL; /* tree of font descriptor objects */
+
+static int comp_fo_entry(const void *pa, const void *pb, void *p)
+{
+ return strcmp(((const fo_entry *) pa)->fm->tfm_name,
+ ((const fo_entry *) pb)->fm->tfm_name);
+}
+
+static int comp_fd_entry(const void *pa, const void *pb, void *p)
+{
+ int i;
+ const fd_entry *p1 = (const fd_entry *) pa, *p2 = (const fd_entry *) pb;
+ assert(p1->fm != NULL && is_fontfile(p1->fm) &&
+ p2->fm != NULL && is_fontfile(p2->fm));
+ if ((i = strcmp(p1->fm->ff_name, p2->fm->ff_name)) != 0)
+ return i;
+ cmp_return(p1->fm->slant, p2->fm->slant);
+ cmp_return(p1->fm->extend, p2->fm->extend);
+ return 0;
+}
+
+/**********************************************************************/
+/* initialize data structure for /Type /Font */
+
+fo_entry *new_fo_entry(void)
+{
+ fo_entry *fo;
+ fo = xtalloc(1, fo_entry);
+ fo->fo_objnum = 0;
+ fo->tex_font = 0;
+ fo->fm = NULL;
+ fo->fd = NULL;
+ fo->fe = NULL;
+ fo->cw_objnum = 0;
+ fo->first_char = 1;
+ fo->last_char = 0;
+ fo->tx_tree = NULL;
+ fo->tounicode_objnum = 0;
+ return fo;
+}
+
+/* initialize data structure for /Type /FontDescriptor */
+
+fd_entry *new_fd_entry(void)
+{
+ fd_entry *fd;
+ int i;
+ fd = xtalloc(1, fd_entry);
+ fd->fd_objnum = 0;
+ fd->fontname = NULL;
+ fd->subset_tag = NULL;
+ fd->ff_found = false;
+ fd->ff_objnum = 0;
+ fd->fn_objnum = 0;
+ fd->all_glyphs = false;
+ fd->write_ttf_glyph_names = false;
+ for (i = 0; i < INT_KEYS_NUM; i++) {
+ fd->font_dim[i].val = 0;
+ fd->font_dim[i].set = false;
+ }
+ fd->fe = NULL;
+ fd->builtin_glyph_names = NULL;
+ fd->fm = NULL;
+ fd->tx_tree = NULL;
+ fd->gl_tree = NULL;
+ return fd;
+}
+
+/**********************************************************************/
+/*
+ * Only fallback values of font metrics are taken from the TFM info
+ * of f by preset_fontmetrics(). During reading of the font file,
+ * these values are replaced by metrics from the font, if available.
+ */
+
+static void preset_fontmetrics(fd_entry * fd, internalfontnumber f)
+{
+ int i;
+ fd->font_dim[ITALIC_ANGLE_CODE].val =
+ divide_scaled(-atan(get_slant(f) / 65536.0) * (180 / M_PI),
+ pdf_font_size(f), 3);
+ fd->font_dim[ASCENT_CODE].val =
+ divide_scaled(char_height(f, 'h'), pdf_font_size(f), 3);
+ fd->font_dim[CAPHEIGHT_CODE].val =
+ divide_scaled(char_height(f, 'H'), pdf_font_size(f), 3);
+ i = -divide_scaled(char_depth(f, 'y'), pdf_font_size(f), 3);
+ fd->font_dim[DESCENT_CODE].val = i < 0 ? i : 0;
+ fd->font_dim[STEMV_CODE].val =
+ divide_scaled(char_width(f, '.') / 3, pdf_font_size(f), 3);
+ fd->font_dim[XHEIGHT_CODE].val =
+ divide_scaled(get_x_height(f), pdf_font_size(f), 3);
+ fd->font_dim[FONTBBOX1_CODE].val = 0;
+ fd->font_dim[FONTBBOX2_CODE].val = fd->font_dim[DESCENT_CODE].val;
+ fd->font_dim[FONTBBOX3_CODE].val =
+ divide_scaled(get_quad(f), pdf_font_size(f), 3);
+ fd->font_dim[FONTBBOX4_CODE].val =
+ fd->font_dim[CAPHEIGHT_CODE].val > fd->font_dim[ASCENT_CODE].val ?
+ fd->font_dim[CAPHEIGHT_CODE].val : fd->font_dim[ASCENT_CODE].val;
+ for (i = 0; i < INT_KEYS_NUM; i++)
+ fd->font_dim[i].set = true;
+}
+
+static void write_fontmetrics(fd_entry * fd)
+{
+ int i;
+ if (fd->font_dim[FONTBBOX1_CODE].set && fd->font_dim[FONTBBOX2_CODE].set
+ && fd->font_dim[FONTBBOX3_CODE].set && fd->font_dim[FONTBBOX4_CODE].set)
+ pdf_printf("/%s [%i %i %i %i]\n", font_key[FONTBBOX1_CODE].pdfname,
+ (int) fd->font_dim[FONTBBOX1_CODE].val,
+ (int) fd->font_dim[FONTBBOX2_CODE].val,
+ (int) fd->font_dim[FONTBBOX3_CODE].val,
+ (int) fd->font_dim[FONTBBOX4_CODE].val);
+ for (i = 0; i < GEN_KEY_NUM; i++)
+ if (fd->font_dim[i].set)
+ pdf_printf("/%s %i\n", font_key[i].pdfname, fd->font_dim[i].val);
+}
+
+/**********************************************************************/
+
+static void preset_fontname(fo_entry * fo)
+{
+ if (fo->fm->ps_name != NULL)
+ fo->fd->fontname = xstrdup(fo->fm->ps_name); /* just fallback */
+ else
+ fo->fd->fontname = xstrdup(fo->fm->tfm_name);
+}
+
+static void write_fontname(fd_entry * fd, char *key)
+{
+ assert(fd->fontname != NULL);
+ pdf_puts("/");
+ if (key != NULL)
+ pdf_printf("%s /", key);
+ if (fd->subset_tag != NULL)
+ pdf_printf("%s+", fd->subset_tag);
+ pdf_printf("%s\n", fd->fontname);
+}
+
+static void write_fontname_object(fd_entry * fd)
+{
+ assert(fd->fn_objnum != 0);
+ pdf_begin_obj(fd->fn_objnum, 1);
+ write_fontname(fd, NULL);
+ pdf_end_obj();
+}
+
+/**********************************************************************/
+
+fd_entry *lookup_fd_entry(char *s, integer slant, integer extend)
+{
+ fd_entry fd;
+ fm_entry fm;
+ assert(s != NULL);
+ fm.ff_name = s;
+ fm.slant = slant;
+ fm.extend = extend;
+ fd.fm = &fm;
+ if (fd_tree == NULL) {
+ fd_tree = avl_create(comp_fd_entry, NULL, &avl_xallocator);
+ assert(fd_tree != NULL);
+ }
+ return (fd_entry *) avl_find(fd_tree, &fd);
+}
+
+fd_entry *lookup_fontdescriptor(fo_entry * fo)
+{
+ assert(fo != NULL);
+ assert(fo->fm != NULL);
+ assert(is_fontfile(fo->fm));
+ return lookup_fd_entry(fo->fm->ff_name, fo->fm->slant, fo->fm->extend);
+}
+
+void register_fd_entry(fd_entry * fd)
+{
+ void **aa;
+ if (fd_tree == NULL) {
+ fd_tree = avl_create(comp_fd_entry, NULL, &avl_xallocator);
+ assert(fd_tree != NULL);
+ }
+ assert(fd != NULL && fd->fm != NULL && is_fontfile(fd->fm));
+ assert(lookup_fd_entry(fd->fm->ff_name, fd->fm->slant, fd->fm->extend) == NULL); /* font descriptor not yet registered */
+ aa = avl_probe(fd_tree, fd);
+ assert(aa != NULL);
+}
+
+void create_fontdescriptor(fo_entry * fo, internalfontnumber f)
+{
+ assert(fo != NULL);
+ assert(fo->fm != NULL);
+ assert(fo->fd == NULL);
+ fo->fd = new_fd_entry();
+ preset_fontname(fo);
+ preset_fontmetrics(fo->fd, f);
+ fo->fd->fe = fo->fe; /* encoding needed by TrueType writing */
+ fo->fd->fm = fo->fm; /* map entry needed by TrueType writing */
+ fo->fd->gl_tree = avl_create(comp_string_entry, NULL, &avl_xallocator);
+ assert(fo->fd->gl_tree != NULL);
+}
+
+/**********************************************************************/
+/*
+ * For all used characters of TeX font f, get corresponding glyph names
+ * from external reencoding (.enc) file and collect these in the glyph
+ * tree gl_tree of font descriptor fd referenced by font dictionary fo.
+ */
+
+void mark_reenc_glyphs(fo_entry * fo, internalfontnumber f)
+{
+ int i;
+ char **g;
+ void **aa;
+ assert(fo->fe != NULL);
+ if (is_subsetted(fo->fm)) {
+ assert(is_included(fo->fm));
+ /* mark glyphs from TeX (externally reencoded characters) */
+ g = fo->fe->glyph_names;
+ for (i = fo->first_char; i <= fo->last_char; i++) {
+ if (pdf_char_marked(f, i) && g[i] != notdef
+ && (char *) avl_find(fo->fd->gl_tree, g[i]) == NULL) {
+ aa = avl_probe(fo->fd->gl_tree, xstrdup(g[i]));
+ assert(aa != NULL);
+ }
+ }
+ }
+}
+
+/*
+ * Function mark_chars() has 2 uses:
+ * 1. Mark characters as chars on TeX level.
+ * 2. Mark encoding pairs used by TeX to optimize encoding vector.
+ */
+
+struct avl_table *mark_chars(fo_entry * fo, struct avl_table *tx_tree,
+ internalfontnumber f)
+{
+ int i, *j;
+ void **aa;
+ if (tx_tree == NULL) {
+ tx_tree = avl_create(comp_int_entry, NULL, &avl_xallocator);
+ assert(tx_tree != NULL);
+ }
+ for (i = fo->first_char; i <= fo->last_char; i++) {
+ if (pdf_char_marked(f, i) && (int *) avl_find(tx_tree, &i) == NULL) {
+ j = xtalloc(1, int);
+ *j = i;
+ aa = avl_probe(tx_tree, j);
+ assert(aa != NULL);
+ }
+ }
+ return tx_tree;
+}
+
+/**********************************************************************/
+
+void get_char_range(fo_entry * fo, internalfontnumber f)
+{
+ int i;
+ assert(fo != NULL);
+ for (i = font_bc(f); i <= font_ec(f); i++) /* search for first_char and last_char */
+ if (pdf_char_marked(f, i))
+ break;
+ fo->first_char = i;
+ for (i = font_ec(f); i >= font_bc(f); i--)
+ if (pdf_char_marked(f, i))
+ break;
+ fo->last_char = i;
+ if ((fo->first_char > fo->last_char)
+ || !pdf_char_marked(f, fo->first_char)) { /* no character used from this font */
+ fo->last_char = 0;
+ fo->first_char = fo->last_char + 1;
+ }
+}
+
+static void write_charwidth_array(fo_entry * fo, internalfontnumber f)
+{
+ int i, j, *ip, *fip, width;
+ struct avl_traverser t;
+ assert(fo->tx_tree != NULL);
+ assert(fo->cw_objnum == 0);
+ fo->cw_objnum = pdf_new_objnum();
+ pdf_begin_obj(fo->cw_objnum, 1);
+ avl_t_init(&t, fo->tx_tree);
+ fip = (int *) avl_t_first(&t, fo->tx_tree);
+ assert(fip != NULL);
+ pdf_puts("[");
+ for (ip = fip, j = *ip; ip != NULL; ip = (int *) avl_t_next(&t)) {
+ if (ip != fip)
+ pdf_puts(" ");
+ i = *ip;
+ while (j < i - 1) {
+ pdf_puts("0 ");
+ j++;
+ }
+ j = i;
+ width = divide_scaled(char_width(f, i), pdf_font_size(f), 4);
+ pdf_printf("%i", (int) width / 10); /* see adv_char_width() in pdftex.web */
+ if ((width = width % 10) != 0)
+ pdf_printf(".%i", width);
+ }
+ pdf_puts("]\n");
+ pdf_end_obj();
+}
+
+/**********************************************************************/
+/*
+ * Remark: Font objects from embedded PDF files are never registered
+ * into fo_tree; they are individually written out.
+ */
+
+fo_entry *lookup_fo_entry(char *s)
+{
+ fo_entry fo;
+ fm_entry fm;
+ assert(s != NULL);
+ fm.tfm_name = s;
+ fo.fm = &fm;
+ if (fo_tree == NULL) {
+ fo_tree = avl_create(comp_fo_entry, NULL, &avl_xallocator);
+ assert(fo_tree != NULL);
+ }
+ return (fo_entry *) avl_find(fo_tree, &fo);
+}
+
+void register_fo_entry(fo_entry * fo)
+{
+ void **aa;
+ if (fo_tree == NULL) {
+ fo_tree = avl_create(comp_fo_entry, NULL, &avl_xallocator);
+ assert(fo_tree != NULL);
+ }
+ assert(fo != NULL);
+ assert(fo->fm != NULL);
+ assert(fo->fm->tfm_name != NULL);
+ assert (lookup_fo_entry(fo->fm->tfm_name) == NULL) ;
+ aa = avl_probe(fo_tree, fo);
+ assert(aa != NULL);
+}
+
+/**********************************************************************/
+
+static void write_fontfile(fd_entry * fd)
+{
+ assert(is_included(fd->fm));
+ if (is_cidkeyed(fd->fm)) {
+ if (is_opentype(fd->fm))
+ writetype0(fd);
+ else if (is_truetype(fd->fm))
+ writetype2(fd);
+ else if (is_type1(fd->fm))
+ writetype1w(fd);
+ else
+ assert(0);
+ } else {
+ if (is_type1(fd->fm))
+#ifdef DO_TYPE1C
+ writet1c(fd);
+#else
+ writet1(fd);
+#endif
+ else if (is_truetype(fd->fm))
+ writettf(fd);
+ else if (is_opentype(fd->fm))
+ writeotf(fd);
+ else
+ assert(0);
+ }
+ if (!fd->ff_found)
+ return;
+ assert(fd->ff_objnum == 0);
+ fd->ff_objnum = pdf_new_objnum();
+ pdf_begin_dict(fd->ff_objnum, 0); /* font file stream */
+ if (is_cidkeyed(fd->fm)) {
+ /* No subtype is used for TrueType-based OpenType fonts */
+ if (is_opentype(fd->fm) || is_type1(fd->fm))
+ pdf_puts("/Subtype /CIDFontType0C\n");
+ /* else
+ pdf_puts("/Subtype /OpenType\n");*/
+ } else {
+ if (is_type1(fd->fm))
+ pdf_printf("/Length1 %i\n/Length2 %i\n/Length3 %i\n",
+ (int) t1_length1, (int) t1_length2, (int) t1_length3);
+ else if (is_truetype(fd->fm))
+ pdf_printf("/Length1 %i\n", (int) ttf_length);
+ else if (is_opentype(fd->fm))
+ pdf_puts("/Subtype /Type1C\n");
+ else
+ assert(0);
+ }
+ pdf_begin_stream();
+ fb_flush();
+ pdf_end_stream();
+}
+
+/**********************************************************************/
+
+static void write_fontdescriptor(fd_entry * fd)
+{
+ char *glyph;
+ struct avl_traverser t;
+ assert(fd != NULL && fd->fm != NULL);
+
+ if (is_fontfile(fd->fm))
+ write_fontfile(fd); /* this will set fd->ff_found if font file is found */
+ if (fd->fn_objnum != 0)
+ write_fontname_object(fd);
+ if (fd->fd_objnum == 0)
+ fd->fd_objnum = pdf_new_objnum();
+ pdf_begin_dict(fd->fd_objnum, 1);
+ pdf_puts("/Type /FontDescriptor\n");
+ write_fontname(fd, "FontName");
+ if (!fd->ff_found && fd->fm->fd_flags == 4)
+ pdf_puts("/Flags 34\n"); /* assumes a roman sans serif font */
+ else
+ pdf_printf("/Flags %i\n", (int) fd->fm->fd_flags);
+ write_fontmetrics(fd);
+ if (is_cidkeyed(fd->fm)) {
+ if (is_type1(fd->fm))
+ pdf_printf("/FontFile3 %i 0 R\n", (int) fd->ff_objnum);
+ else if (is_truetype(fd->fm))
+ pdf_printf("/FontFile2 %i 0 R\n", (int) fd->ff_objnum);
+ else if (is_opentype(fd->fm))
+ pdf_printf("/FontFile3 %i 0 R\n", (int) fd->ff_objnum);
+ else
+ assert(0);
+ } else {
+ if (fd->ff_found) {
+ if (is_subsetted(fd->fm) && is_type1(fd->fm)) {
+ /* /CharSet is optional; names may appear in any order */
+ assert(fd->gl_tree != NULL);
+ avl_t_init(&t, fd->gl_tree);
+ pdf_puts("/CharSet (");
+ for (glyph = (char *) avl_t_first(&t, fd->gl_tree); glyph != NULL;
+ glyph = (char *) avl_t_next(&t))
+ pdf_printf("/%s", glyph);
+ pdf_puts(")\n");
+ }
+ if (is_type1(fd->fm))
+ pdf_printf("/FontFile %i 0 R\n", (int) fd->ff_objnum);
+ else if (is_truetype(fd->fm))
+ pdf_printf("/FontFile2 %i 0 R\n", (int) fd->ff_objnum);
+ else if (is_opentype(fd->fm))
+ pdf_printf("/FontFile3 %i 0 R\n", (int) fd->ff_objnum);
+ else
+ assert(0);
+ }
+ }
+ /* TODO: Optional keys for CID fonts.
+
+ The most interesting ones are
+ /Style << /Panose <12-byte string>>>
+ and
+ /CIDSET <stream>
+ the latter can be used in subsets, to give the included CIDs
+ as a bitmap on the whole list.
+ */
+ pdf_end_dict();
+}
+
+void write_fontdescriptors()
+{
+ fd_entry *fd;
+ struct avl_traverser t;
+ if (fd_tree == NULL)
+ return;
+ avl_t_init(&t, fd_tree);
+ for (fd = (fd_entry *) avl_t_first(&t, fd_tree); fd != NULL;
+ fd = (fd_entry *) avl_t_next(&t))
+ write_fontdescriptor(fd);
+}
+
+/**********************************************************************/
+
+void write_fontdictionary(fo_entry * fo)
+{
+ assert(fo != NULL);
+ assert(fo->fm != NULL);
+ assert(fo->fo_objnum != 0); /* reserved as pdf_font_num(f) in pdftex.web */
+
+ /* write ToUnicode entry if needed */
+ if (fixed_gen_tounicode > 0 && fo->fd != NULL) {
+ if (fo->fe != NULL) {
+ fo->tounicode_objnum =
+ write_tounicode(fo->fe->glyph_names, fo->fe->name);
+ } else if (is_type1(fo->fm)) {
+ assert(fo->fd->builtin_glyph_names != NULL);
+ fo->tounicode_objnum =
+ write_tounicode(fo->fd->builtin_glyph_names, fo->fm->tfm_name);
+ }
+ }
+
+ pdf_begin_dict(fo->fo_objnum, 1);
+ pdf_puts("/Type /Font\n");
+ pdf_puts("/Subtype /");
+ if (is_type1(fo->fm))
+#ifdef DO_TYPE1C
+ pdf_printf("%s\n", "Type1C");
+#else
+ pdf_printf("%s\n", "Type1");
+#endif
+ else if (is_truetype(fo->fm))
+ pdf_printf("%s\n", "TrueType");
+ else if (is_opentype(fo->fm))
+ pdf_printf("%s\n", "Type1");
+ else
+ assert(0);
+ assert(fo->fd != NULL && fo->fd->fd_objnum != 0);
+ write_fontname(fo->fd, "BaseFont");
+ pdf_printf("/FontDescriptor %i 0 R\n", (int) fo->fd->fd_objnum);
+ assert(fo->cw_objnum != 0);
+ pdf_printf("/FirstChar %i\n/LastChar %i\n/Widths %i 0 R\n",
+ (int) fo->first_char, (int) fo->last_char,
+ (int) fo->cw_objnum);
+ if ((is_type1(fo->fm) || is_opentype(fo->fm)) && fo->fe != NULL && fo->fe->fe_objnum != 0)
+ pdf_printf("/Encoding %i 0 R\n", (int) fo->fe->fe_objnum);
+ if (fo->tounicode_objnum != 0)
+ pdf_printf("/ToUnicode %i 0 R\n", (int) fo->tounicode_objnum);
+ if (pdf_font_attr(fo->tex_font) != get_nullstr()) {
+ pdf_print(pdf_font_attr(fo->tex_font));
+ pdf_puts("\n");
+ }
+ pdf_end_dict();
+}
+
+void write_fontdictionaries()
+{
+ fo_entry *fo;
+ struct avl_traverser t;
+ if (fo_tree == NULL)
+ return;
+ avl_t_init(&t, fo_tree);
+ for (fo = (fo_entry *) avl_t_first(&t, fo_tree); fo != NULL;
+ fo = (fo_entry *) avl_t_next(&t))
+ write_fontdictionary(fo);
+}
+
+/**********************************************************************/
+/*
+ * Final flush of all font related stuff by call from
+ * @<Output fonts definition@>= in pdftex.web.
+ */
+
+void write_fontstuff()
+{
+ write_fontdescriptors();
+ write_fontencodings(); /* see writeenc.c */
+ write_fontdictionaries();
+}
+
+/**********************************************************************/
+
+void create_fontdictionary(fm_entry * fm, integer font_objnum,
+ internalfontnumber f)
+{
+ fo_entry *fo = new_fo_entry();
+ get_char_range(fo, f); /* set fo->first_char and fo->last_char from f */
+ assert(fo->last_char >= fo->first_char);
+ fo->fm = fm;
+ fo->fo_objnum = font_objnum;
+ fo->tex_font = f;
+ if (is_reencoded(fo->fm)) { /* at least the map entry tells so */
+ fo->fe = get_fe_entry(fo->fm->encname); /* returns NULL if .enc file couldn't be opened */
+ if (fo->fe != NULL && (is_type1(fo->fm) || is_opentype(fo->fm))) {
+ if (fo->fe->fe_objnum == 0)
+ fo->fe->fe_objnum = pdf_new_objnum(); /* then it will be written out */
+ /* mark encoding pairs used by TeX to optimize encoding vector */
+ fo->fe->tx_tree = mark_chars(fo, fo->fe->tx_tree, f);
+ }
+ }
+ fo->tx_tree = mark_chars(fo, fo->tx_tree, f); /* for write_charwidth_array() */
+ write_charwidth_array(fo, f);
+ if (!is_builtin(fo->fm)) {
+ if (is_type1(fo->fm)) {
+ if ((fo->fd = lookup_fontdescriptor(fo)) == NULL) {
+ create_fontdescriptor(fo, f);
+ register_fd_entry(fo->fd);
+ }
+ } else
+ create_fontdescriptor(fo, f);
+ if (fo->fe != NULL) {
+ mark_reenc_glyphs(fo, f);
+ if (!is_type1(fo->fm)) {
+ /* mark reencoded characters as chars on TeX level */
+ assert(fo->fd->tx_tree == NULL);
+ fo->fd->tx_tree = mark_chars(fo, fo->fd->tx_tree, f);
+ if (is_truetype(fo->fm))
+ fo->fd->write_ttf_glyph_names = true;
+ }
+ } else
+ /* mark non-reencoded characters as chars on TeX level */
+ fo->fd->tx_tree = mark_chars(fo, fo->fd->tx_tree, f);
+ if (!is_type1(fo->fm))
+ write_fontdescriptor(fo->fd);
+ } else {
+ /* builtin fonts still need the /Widths array and /FontDescriptor
+ * (to avoid error 'font FOO contains bad /BBox')
+ */
+ create_fontdescriptor(fo, f);
+ write_fontdescriptor(fo->fd);
+ if (!is_std_t1font(fo->fm))
+ pdftex_warn("font `%s' is not a standard font; "
+ "I suppose it is available to your PDF viewer then",
+ fo->fm->ps_name);
+ }
+ if (is_type1(fo->fm))
+ register_fo_entry(fo);
+ else
+ write_fontdictionary(fo);
+}
+
+/**********************************************************************/
+
+
+void do_pdf_font(integer font_objnum, internalfontnumber f)
+{
+ fm_entry *fm;
+ /* This is not 100% true: CID is actually needed whenever (and
+ * only) there are more than 256 separate glyphs used. But for
+ * now, just assume the user knows what he is doing;
+ */
+ if (font_encodingbytes(f)==2) {
+ /* Create a virtual font map entry, as this is needed by the
+ * rest of the font inclusion mechanism.
+ */
+ fm = new_fm_entry();
+ fm->tfm_name = font_name(f); /* or whatever, not a real tfm */
+ fm->ff_name = font_filename(f); /* the actual file */
+ fm->encname = font_encodingname(f); /* for the CIDSystemInfo */
+ fm->ps_name = font_fullname(f); /* the true name */
+ fm->slant = font_slant(f); /* slant factor */
+ fm->extend = font_extend(f); /* extension factor */
+ fm->fd_flags = 4; /* can perhaps be done better */
+ fm->in_use = true;
+
+ switch (font_format(f)) {
+ case opentype_format: set_opentype(fm); break;
+ case truetype_format: set_truetype(fm); break;
+ case type1_format: set_type1(fm); break;
+ default:
+ pdftex_fail("writefont.c: The file format (%s) for font `%s' is incompatible with wide characters\n",
+ font_format_name(f),font_name(f));
+ }
+ /* This makes "unknown" default to subsetted inclusion */
+ if (font_embedding(f)!=no_embedding) {
+ set_included(fm);
+ if (font_embedding(f)!=full_embedding) {
+ set_subsetted(fm);
+ }
+ }
+ set_cidkeyed(fm);
+ create_cid_fontdictionary(fm, font_objnum, f);
+
+ } else {
+ fm = hasfmentry(f) ? (fm_entry *) font_map(f) : NULL;
+ if (fm == NULL || (fm->ps_name == NULL && fm->ff_name == NULL))
+ writet3(font_objnum, f);
+ else
+ create_fontdictionary(fm, font_objnum, f);
+ }
+}
+
+/**********************************************************************/
+
+
+/*
+ The glyph width is included in |glw_entry|, because that width
+ depends on the value it has in the font where it is actually
+ typeset from, not the font that is the 'owner' of the fd entry.
+
+ TODO: It is possible that the user messes with the metric width,
+ but handling that properly would require access to the 'hmtx' table
+ at this point in the program.
+*/
+
+int comp_glw_entry(const void *pa, const void *pb, void *p)
+{
+ unsigned short i, j;
+ i = (*(glw_entry *)pa).id;
+ j = (*(glw_entry *)pb).id;
+ cmp_return(i,j);
+ return 0;
+}
+
+void create_cid_fontdescriptor(fo_entry * fo, internalfontnumber f)
+{
+ assert(fo != NULL);
+ assert(fo->fm != NULL);
+ assert(fo->fd == NULL);
+ fo->fd = new_fd_entry();
+ preset_fontname(fo);
+ preset_fontmetrics(fo->fd, f);
+ fo->fd->fe = fo->fe; /* encoding needed by TrueType writing */
+ fo->fd->fm = fo->fm; /* map entry needed by TrueType writing */
+ fo->fd->gl_tree = avl_create(comp_glw_entry, NULL, &avl_xallocator);
+ assert(fo->fd->gl_tree != NULL);
+}
+
+/*
+ The values |font_bc()| and |font_ec()| are potentially large
+ character ids, but the strings that are written out use CID
+ indexes, and those are limited to 16-bit values.
+*/
+
+static void mark_cid_subset_glyphs(fo_entry *fo, internal_font_number f)
+{
+ int i, k;
+ glw_entry *j;
+ void *aa;
+ for (k = 1; k <= max_font_id(); k++) {
+ if ( k == f || -f == pdf_font_num(k)) {
+ for (i = font_bc(k); i <= font_ec(k); i++) {
+ if (char_exists(k,i) && char_used(k,i)) {
+ j = xtalloc(1,glw_entry);
+ j->id = char_index(k,i);
+ j->wd = divide_scaled_n(char_width(k, i), pdf_font_size(k), 10000.0);
+ if ((glw_entry *)avl_find(fo->fd->gl_tree,j) == NULL) {
+ aa = avl_probe(fo->fd->gl_tree, j);
+ assert(aa != NULL);
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+ It is possible to compress the widths array even better, by using the
+ alternate 'range' syntax and possibly even using /DW to set
+ a default value.
+
+ There is a some optimization here already: glyphs that are
+ not used do not appear in the widths array at all.
+
+ We have to make sure that we do not output an (incorrect!)
+ width for a character that exists in the font, but is not used
+ in typesetting. An enormous negative width is used as sentinel value
+*/
+
+
+static void write_cid_charwidth_array(fo_entry * fo)
+{
+ int i, j;
+ glw_entry *glyph;
+ struct avl_traverser t;
+
+ assert(fo->cw_objnum == 0);
+ fo->cw_objnum = pdf_new_objnum();
+ pdf_begin_obj(fo->cw_objnum, 1);
+ avl_t_init(&t, fo->fd->gl_tree);
+ glyph = (glw_entry *) avl_t_first(&t, fo->fd->gl_tree);
+ assert(glyph != NULL);
+ i = glyph->id;
+ pdf_printf("[ %i [", i);
+ for (; glyph != NULL; glyph = (glw_entry *) avl_t_next(&t)) {
+ j = glyph->wd;
+ if (glyph->id>(i+1)) {
+ pdf_printf("] %i [", glyph->id);
+ j = glyph->wd;
+ }
+ if (glyph->id==(i+1))
+ pdf_puts(" ");
+ pdf_printf("%i", (j/10));
+ if ((j % 10) != 0)
+ pdf_printf(".%i", (j % 10));
+ i = glyph->id;
+ }
+ pdf_puts("]]\n");
+ pdf_end_obj();
+}
+
+
+void create_cid_fontdictionary(fm_entry * fm, integer font_objnum,
+ internalfontnumber f)
+{
+ fo_entry *fo = new_fo_entry();
+ get_char_range(fo, f); /* set fo->first_char and fo->last_char from f */
+ assert(fo->last_char >= fo->first_char);
+ fo->fm = fm;
+ fo->fo_objnum = font_objnum;
+ fo->tex_font = f;
+ create_cid_fontdescriptor (fo, f);
+ mark_cid_subset_glyphs (fo,f);
+ if (is_subsetted(fo->fm)) {
+ /*
+ this is a bit sneaky. |make_subset_tag()| actually expects the glyph tree
+ to contain strings instead of |glw_entry| items. However, all calculations
+ are done using explicit typecasts, so it works out ok.
+ */
+ make_subset_tag(fo->fd);
+ }
+ write_cid_charwidth_array(fo);
+ write_fontdescriptor(fo->fd);
+
+ write_cid_fontdictionary(fo,f);
+}
+
+void write_cid_fontdictionary(fo_entry * fo, internalfontnumber f)
+{
+ int i;
+
+ fo->tounicode_objnum = write_cid_tounicode(fo,f);
+
+ pdf_begin_dict(fo->fo_objnum, 1);
+ pdf_puts("/Type /Font\n");
+ pdf_puts("/Subtype /Type0\n");
+ pdf_puts("/Encoding /Identity-H\n");
+ write_fontname(fo->fd, "BaseFont");
+ i = pdf_new_objnum();
+ pdf_printf("/DescendantFonts [%i 0 R]\n", i);
+ /* todo: the ToUnicode CMap */
+ if (fo->tounicode_objnum != 0)
+ pdf_printf("/ToUnicode %i 0 R\n", (int) fo->tounicode_objnum);
+
+ pdf_end_dict();
+
+ pdf_begin_dict(i, 1);
+ pdf_puts("/Type /Font\n");
+ if (is_opentype(fo->fm) || is_type1(fo->fm)) {
+ pdf_puts("/Subtype /CIDFontType0\n");
+ } else {
+ pdf_puts("/Subtype /CIDFontType2\n");
+ pdf_printf("/CIDToGIDMap /Identity\n");
+ }
+ write_fontname(fo->fd, "BaseFont");
+ pdf_printf("/FontDescriptor %i 0 R\n", (int) fo->fd->fd_objnum);
+ pdf_printf("/W %i 0 R\n",(int) fo->cw_objnum);
+ pdf_printf("/CIDSystemInfo <<\n");
+ pdf_printf("/Registry (%s)\n", (font_cidregistry(f)? font_cidregistry(f): "Adobe"));
+ pdf_printf("/Ordering (%s)\n",(font_cidordering(f)? font_cidordering(f) : "Identity")) ;
+ pdf_printf("/Supplement %u\n",(unsigned int)font_cidsupplement(f));
+ pdf_printf(">>\n");
+
+ /* I doubt there is anything useful that could be written here */
+ /*
+ if (pdf_font_attr(fo->tex_font) != get_nullstr()) {
+ pdf_print(pdf_font_attr(fo->tex_font));
+ pdf_puts("\n");
+ }
+ */
+ pdf_end_dict();
+
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/font/writet1.c b/Build/source/texk/web2c/luatexdir/font/writet1.c
new file mode 100644
index 00000000000..376135dc8be
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writet1.c
@@ -0,0 +1,1768 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id $
+
+*/
+
+# include "ptexlib.h"
+# include <kpathsea/c-vararg.h>
+# include <kpathsea/c-proto.h>
+# include <string.h>
+# include "luatex-api.h"
+
+# define t1_log(s) if(tracefilenames) tex_printf(s)
+# define get_length1() t1_length1 = t1_offset() - t1_save_offset
+# define get_length2() t1_length2 = t1_offset() - t1_save_offset
+# define get_length3() t1_length3 = fixedcontent? t1_offset() - t1_save_offset : 0
+# define save_offset() t1_save_offset = t1_offset()
+
+# define t1_putchar fb_putchar
+# define t1_offset fb_offset
+# define out_eexec_char t1_putchar
+
+# define end_last_eexec_line() \
+ t1_eexec_encrypt = false
+# define t1_char(c) c
+# define embed_all_glyphs(tex_font) fm_cur->all_glyphs
+# define extra_charset() fm_cur->charset
+# define update_subset_tag() \
+ strncpy(fb_array + t1_fontname_offset, fm_cur->subset_tag, 6)
+# define fixedcontent false
+
+integer t1_length1, t1_length2, t1_length3;
+static integer t1_save_offset;
+static integer t1_fontname_offset;
+extern char *fb_array;
+
+static unsigned char *t1_buffer = NULL;
+static integer t1_size = 0;
+static integer t1_curbyte = 0;
+
+#define t1_read_file() \
+ readbinfile(t1_file,&t1_buffer,&t1_size)
+#define t1_close() xfclose(t1_file,cur_file_name)
+#define t1_getchar() t1_buffer[t1_curbyte++]
+#define t1_ungetchar(c) t1_curbyte--
+#define t1_eof() (t1_curbyte>t1_size)
+
+#define t1_prefix(s) str_prefix(t1_line_array, s)
+#define t1_buf_prefix(s) str_prefix(t1_buf_array, s)
+#define t1_suffix(s) str_suffix(t1_line_array, t1_line_ptr, s)
+#define t1_buf_suffix(s) str_suffix(t1_buf_array, t1_buf_ptr, s)
+#define t1_charstrings() strstr(t1_line_array, charstringname)
+#define t1_subrs() t1_prefix("/Subrs")
+#define t1_end_eexec() t1_suffix("mark currentfile closefile")
+#define t1_cleartomark() t1_prefix("cleartomark")
+
+static unsigned char *enc_buffer = NULL;
+static integer enc_size = 0;
+static integer enc_curbyte = 0;
+
+#define enc_open() \
+ open_input(&enc_file, kpse_enc_format, FOPEN_RBIN_MODE)
+#define enc_read_file() \
+ readbinfile(enc_file,&enc_buffer,&enc_size)
+#define enc_close() xfclose(enc_file,cur_file_name)
+#define enc_getchar() enc_buffer[enc_curbyte++]
+#define enc_eof() (enc_curbyte>enc_size)
+
+#define valid_code(c) (c >= 0 && c < 256)
+#define fixedcontent false
+
+static const char *standard_glyph_names[256] = {
+ /* 0x00 */
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ /* 0x10 */
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ /* 0x20 */
+ "space", "exclam", "quotedbl", "numbersign", "dollar", "percent",
+ "ampersand", "quoteright", "parenleft", "parenright", "asterisk",
+ "plus", "comma", "hyphen", "period", "slash",
+ /* 0x30 */
+ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
+ "nine", "colon", "semicolon", "less", "equal", "greater", "question",
+ /* 0x40 */
+ "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
+ "O",
+ /* 0x50 */
+ "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft",
+ "backslash", "bracketright", "asciicircum", "underscore",
+ /* 0x60 */
+ "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
+ "m", "n", "o",
+ /* 0x70 */
+ "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar",
+ "braceright", "asciitilde", notdef,
+ /* 0x80 */
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ /* 0x90 */
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ /* 0xa0 */
+ notdef, "exclamdown", "cent", "sterling", "fraction", "yen", "florin",
+ "section", "currency", "quotesingle", "quotedblleft", "guillemotleft",
+ "guilsinglleft", "guilsinglright", "fi", "fl",
+ /* 0xb0 */
+ notdef, "endash", "dagger", "daggerdbl", "periodcentered", notdef,
+ "paragraph", "bullet", "quotesinglbase", "quotedblbase",
+ "quotedblright", "guillemotright", "ellipsis", "perthousand", notdef,
+ "questiondown",
+ /* 0xc0 */
+ notdef, "grave", "acute", "circumflex", "tilde", "macron", "breve",
+ "dotaccent", "dieresis", notdef,
+ "ring", "cedilla", notdef, "hungarumlaut", "ogonek", "caron",
+ /* 0xd0 */
+ "emdash", notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ /* 0xe0 */
+ notdef, "AE", notdef, "ordfeminine", notdef, notdef, notdef, notdef,
+ "Lslash", "Oslash", "OE", "ordmasculine", notdef, notdef, notdef,
+ notdef,
+ /* 0xf0 */
+ notdef, "ae", notdef, notdef, notdef, "dotlessi", notdef, notdef, "lslash",
+ "oslash", "oe", "germandbls", notdef, notdef, notdef, notdef
+};
+
+
+integer t1_length1, t1_length2, t1_length3;
+static integer t1_save_offset;
+static integer t1_fontname_offset;
+extern char *fb_array;
+static fd_entry *fd_cur;
+
+static char charstringname[] = "/CharStrings";
+
+enum { ENC_STANDARD, ENC_BUILTIN } t1_encoding;
+
+#define T1_BUF_SIZE 0x10
+#define ENC_BUF_SIZE 0x1000
+
+#define CS_HSTEM 1
+#define CS_VSTEM 3
+#define CS_VMOVETO 4
+#define CS_RLINETO 5
+#define CS_HLINETO 6
+#define CS_VLINETO 7
+#define CS_RRCURVETO 8
+#define CS_CLOSEPATH 9
+#define CS_CALLSUBR 10
+#define CS_RETURN 11
+#define CS_ESCAPE 12
+#define CS_HSBW 13
+#define CS_ENDCHAR 14
+#define CS_RMOVETO 21
+#define CS_HMOVETO 22
+#define CS_VHCURVETO 30
+#define CS_HVCURVETO 31
+#define CS_1BYTE_MAX (CS_HVCURVETO + 1)
+
+#define CS_DOTSECTION CS_1BYTE_MAX + 0
+#define CS_VSTEM3 CS_1BYTE_MAX + 1
+#define CS_HSTEM3 CS_1BYTE_MAX + 2
+#define CS_SEAC CS_1BYTE_MAX + 6
+#define CS_SBW CS_1BYTE_MAX + 7
+#define CS_DIV CS_1BYTE_MAX + 12
+#define CS_CALLOTHERSUBR CS_1BYTE_MAX + 16
+#define CS_POP CS_1BYTE_MAX + 17
+#define CS_SETCURRENTPOINT CS_1BYTE_MAX + 33
+#define CS_2BYTE_MAX (CS_SETCURRENTPOINT + 1)
+#define CS_MAX CS_2BYTE_MAX
+
+typedef unsigned char byte;
+
+typedef struct {
+ byte nargs; /* number of arguments */
+ boolean bottom; /* take arguments from bottom of stack? */
+ boolean clear; /* clear stack? */
+ boolean valid;
+} cc_entry; /* CharString Command */
+
+typedef struct {
+ char *name; /* glyph name (or notdef for Subrs entry) */
+ byte *data;
+ unsigned short len; /* length of the whole string */
+ unsigned short cslen; /* length of the encoded part of the string */
+ boolean used;
+ boolean valid;
+} cs_entry;
+
+static unsigned short t1_dr, t1_er;
+static const unsigned short t1_c1 = 52845, t1_c2 = 22719;
+static unsigned short t1_cslen;
+static short t1_lenIV;
+static char enc_line[ENC_BUF_SIZE];
+
+/* define t1_line_ptr, t1_line_array & t1_line_limit */
+typedef char t1_line_entry;
+define_array (t1_line);
+
+/* define t1_buf_ptr, t1_buf_array & t1_buf_limit */
+typedef char t1_buf_entry;
+define_array (t1_buf);
+
+static int cs_start;
+
+static cs_entry *cs_tab, *cs_ptr, *cs_notdef;
+static char *cs_dict_start, *cs_dict_end;
+static int cs_counter, cs_size, cs_size_pos;
+
+static cs_entry *subr_tab;
+static char *subr_array_start, *subr_array_end;
+static int subr_max, subr_size, subr_size_pos;
+
+/* This list contains the begin/end tokens commonly used in the */
+/* /Subrs array of a Type 1 font. */
+
+static const char *cs_token_pairs_list[][2] = {
+ {" RD", "NP"},
+ {" -|", "|"},
+ {" RD", "noaccess put"},
+ {" -|", "noaccess put"},
+ {NULL, NULL}
+};
+static const char **cs_token_pair;
+
+static boolean t1_pfa, t1_cs, t1_scan, t1_eexec_encrypt, t1_synthetic;
+static int t1_in_eexec; /* 0 before eexec-encrypted, 1 during, 2 after */
+static long t1_block_length;
+static int last_hexbyte;
+static FILE *t1_file;
+static FILE *enc_file;
+
+static void enc_getline (void)
+{
+ char *p;
+ int c;
+ restart:
+ if (enc_eof ())
+ pdftex_fail ("unexpected end of file");
+ p = enc_line;
+ do {
+ c = enc_getchar ();
+ append_char_to_buf (c, p, enc_line, ENC_BUF_SIZE);
+ }
+ while (c != 10 && !enc_eof());
+ append_eol (p, enc_line, ENC_BUF_SIZE);
+ if (p - enc_line < 2 || *enc_line == '%')
+ goto restart;
+}
+
+/* read encoding from .enc file, return glyph_names array, or pdffail() */
+
+char **load_enc_file(char *enc_name)
+{
+ int callback_id = 0;
+ int file_opened = 0;
+ char *ftemp = NULL;
+ char buf[ENC_BUF_SIZE], *p, *r;
+ int i, names_count;
+ char **glyph_names;
+ char *tempname ;
+ set_cur_file_name (enc_name);
+ callback_id=callback_defined(find_enc_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ free(nameoffile);
+ namelength = strlen(ftemp);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),ftemp);
+ free(ftemp);
+ } else {
+ return NULL;
+ }
+ }
+ }
+ callback_id=callback_defined(read_enc_file_callback);
+ enc_curbyte=0;
+ enc_size=0;
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1),
+ &file_opened, &enc_buffer,&enc_size)) {
+ if((!file_opened) || enc_size==0) {
+ pdftex_warn ("cannot open encoding file for reading");
+ cur_file_name = NULL;
+ return NULL;
+ }
+ }
+ } else {
+ if (!enc_open ()) {
+ pdftex_warn ("cannot open encoding file for reading");
+ cur_file_name = NULL;
+ return NULL;
+ }
+ enc_read_file();
+ enc_close();
+ }
+ glyph_names = xtalloc(256, char *);
+ for (i = 0; i < 256; i++)
+ glyph_names[i] = (char *) notdef;
+ t1_log ("{");
+
+ tempname = xmalloc(namelength+2);
+ strcpy(tempname,(char *)(nameoffile+1));
+ set_cur_file_name (tempname);
+ t1_log (cur_file_name);
+ enc_getline ();
+ if (*enc_line != '/' || (r = strchr (enc_line, '[')) == NULL) {
+ remove_eol (r, enc_line);
+ pdftex_fail
+ ("invalid encoding vector (a name or `[' missing): `%s'", enc_line);
+ }
+ names_count = 0;
+ r++; /* skip '[' */
+ skip (r, ' ');
+ for (;;) {
+ while (*r == '/') {
+ for (p = buf, r++;
+ *r != ' ' && *r != 10 && *r != ']' && *r != '/'; *p++ = *r++);
+ *p = 0;
+ skip (r, ' ');
+ if (names_count > 256)
+ pdftex_fail ("encoding vector contains more than 256 names");
+ if (strcmp (buf, notdef) != 0)
+ glyph_names[names_count] = xstrdup (buf);
+ names_count++;
+ }
+ if (*r != 10 && *r != '%') {
+ if (strncmp (r, "] def", strlen ("] def")) == 0)
+ goto done;
+ else {
+ remove_eol (r, enc_line);
+ pdftex_fail
+ ("invalid encoding vector: a name or `] def' expected: `%s'",
+ enc_line);
+ }
+ }
+ enc_getline ();
+ r = enc_line;
+ }
+ done:
+ t1_log ("}");
+ cur_file_name = NULL;
+ return glyph_names;
+}
+
+void free_glyph_names(char **glyph_names)
+{
+ int i;
+ assert(glyph_names != NULL);
+ for (i = 0; i < 256; i++)
+ if (glyph_names[i] != notdef)
+ xfree(glyph_names[i]);
+ xfree(glyph_names);
+}
+
+
+static void t1_check_pfa (void)
+{
+ const int c = t1_getchar ();
+ t1_pfa = (c != 128) ? true : false;
+ t1_ungetchar (c);
+}
+
+static int t1_getbyte (void)
+{
+ int c = t1_getchar ();
+ if (t1_pfa)
+ return c;
+ if (t1_block_length == 0) {
+ if (c != 128)
+ pdftex_fail ("invalid marker");
+ c = t1_getchar ();
+ if (c == 3) {
+ while (!t1_eof ())
+ (void)t1_getchar ();
+ return EOF;
+ }
+ t1_block_length = t1_getchar () & 0xff;
+ t1_block_length |= (t1_getchar () & 0xff) << 8;
+ t1_block_length |= (t1_getchar () & 0xff) << 16;
+ t1_block_length |= (t1_getchar () & 0xff) << 24;
+ c = t1_getchar ();
+ }
+ t1_block_length--;
+ return c;
+}
+
+static int hexval (int c)
+{
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ else if (c >= '0' && c <= '9')
+ return c - '0';
+ else
+ return -1;
+}
+
+static byte edecrypt (byte cipher)
+{
+ byte plain;
+ if (t1_pfa) {
+ while (cipher == 10 || cipher == 13)
+ cipher = t1_getbyte ();
+ last_hexbyte = cipher = (hexval (cipher) << 4) + hexval (t1_getbyte ());
+ }
+ plain = (cipher ^ (t1_dr >> 8));
+ t1_dr = (cipher + t1_dr) * t1_c1 + t1_c2;
+ return plain;
+}
+
+static byte cdecrypt (byte cipher, unsigned short *cr)
+{
+ const byte plain = (cipher ^ (*cr >> 8));
+ *cr = (cipher + *cr) * t1_c1 + t1_c2;
+ return plain;
+}
+
+static byte eencrypt (byte plain)
+{
+ const byte cipher = (plain ^ (t1_er >> 8));
+ t1_er = (cipher + t1_er) * t1_c1 + t1_c2;
+ return cipher;
+}
+
+static byte cencrypt (byte plain, unsigned short *cr)
+{
+ const byte cipher = (plain ^ (*cr >> 8));
+ *cr = (cipher + *cr) * t1_c1 + t1_c2;
+ return cipher;
+}
+
+static char *eol (char *s)
+{
+ char *p = strend (s);
+ if (p - s > 1 && p[-1] != 10) {
+ *p++ = 10;
+ *p = 0;
+ }
+ return p;
+}
+
+static float t1_scan_num (char *p, char **r)
+{
+ float f;
+ skip (p, ' ');
+ if (sscanf (p, "%g", &f) != 1) {
+ remove_eol (p, t1_line_array);
+ pdftex_fail ("a number expected: `%s'", t1_line_array);
+ }
+ if (r != NULL) {
+ for (; isdigit (*p) || *p == '.' ||
+ *p == 'e' || *p == 'E' || *p == '+' || *p == '-'; p++);
+ *r = p;
+ }
+ return f;
+}
+
+static boolean str_suffix (const char *begin_buf, const char *end_buf,
+ const char *s)
+{
+ const char *s1 = end_buf - 1, *s2 = strend (s) - 1;
+ if (*s1 == 10)
+ s1--;
+ while (s1 >= begin_buf && s2 >= s) {
+ if (*s1-- != *s2--)
+ return false;
+ }
+ return s2 < s;
+}
+
+static void t1_getline (void)
+{
+ int c, l, eexec_scan;
+ char *p;
+ static const char eexec_str[] = "currentfile eexec";
+ static int eexec_len = 17; /* strlen(eexec_str) */
+ restart:
+ if (t1_eof ())
+ pdftex_fail ("unexpected end of file");
+ t1_line_ptr = t1_line_array;
+ alloc_array (t1_line, 1, T1_BUF_SIZE);
+ t1_cslen = 0;
+ eexec_scan = 0;
+ c = t1_getbyte ();
+ if (c == EOF)
+ goto exit;
+ while (!t1_eof ()) {
+ if (t1_in_eexec == 1)
+ c = edecrypt (c);
+ alloc_array (t1_line, 1, T1_BUF_SIZE);
+ append_char_to_buf (c, t1_line_ptr, t1_line_array, t1_line_limit);
+ if (t1_in_eexec == 0 && eexec_scan >= 0 && eexec_scan < eexec_len) {
+ if (t1_line_array[eexec_scan] == eexec_str[eexec_scan])
+ eexec_scan++;
+ else
+ eexec_scan = -1;
+ }
+ if (c == 10 || (t1_pfa && eexec_scan == eexec_len && c == 32))
+ break;
+ if (t1_cs && t1_cslen == 0 && (t1_line_ptr - t1_line_array > 4) &&
+ (t1_suffix (" RD ") || t1_suffix (" -| "))) {
+ p = t1_line_ptr - 5;
+ while (*p != ' ')
+ p--;
+ t1_cslen = l = t1_scan_num (p + 1, 0);
+ cs_start = t1_line_ptr - t1_line_array; /* cs_start is an index now */
+ alloc_array (t1_line, l, T1_BUF_SIZE);
+ while (l-- > 0)
+ *t1_line_ptr++ = edecrypt (t1_getbyte ());
+ }
+ c = t1_getbyte ();
+ }
+ alloc_array (t1_line, 2, T1_BUF_SIZE); /* append_eol can append 2 chars */
+ append_eol (t1_line_ptr, t1_line_array, t1_line_limit);
+ if (t1_line_ptr - t1_line_array < 2)
+ goto restart;
+ if (eexec_scan == eexec_len)
+ t1_in_eexec = 1;
+ exit:
+ /* ensure that t1_buf_array has as much room as t1_line_array */
+ t1_buf_ptr = t1_buf_array;
+ alloc_array (t1_buf, t1_line_limit, t1_line_limit);
+}
+
+static void t1_putline (void)
+{
+ char *p = t1_line_array;
+ if (t1_line_ptr - t1_line_array <= 1)
+ return;
+ if (t1_eexec_encrypt) {
+ while (p < t1_line_ptr)
+ t1_putchar (eencrypt (*p++));
+ } else
+ while (p < t1_line_ptr)
+ t1_putchar (*p++);
+}
+
+static void t1_puts (const char *s)
+{
+ if (s != t1_line_array)
+ strcpy (t1_line_array, s);
+ t1_line_ptr = strend (t1_line_array);
+ t1_putline ();
+}
+
+__attribute__ ((format (printf, 1, 2)))
+static void t1_printf (const char *fmt, ...)
+{
+ va_list args;
+ va_start (args, fmt);
+ vsprintf (t1_line_array, fmt, args);
+ t1_puts (t1_line_array);
+ va_end (args);
+}
+
+static void t1_init_params (const char *open_name_prefix)
+{
+ t1_log (open_name_prefix);
+ t1_log (cur_file_name);
+ t1_lenIV = 4;
+ t1_dr = 55665;
+ t1_er = 55665;
+ t1_in_eexec = 0;
+ t1_cs = false;
+ t1_scan = true;
+ t1_synthetic = false;
+ t1_eexec_encrypt = false;
+ t1_block_length = 0;
+ t1_check_pfa ();
+}
+
+static void t1_close_font_file (const char *close_name_suffix)
+{
+ t1_log (close_name_suffix);
+ cur_file_name = NULL;
+}
+
+static void t1_check_block_len (boolean decrypt)
+{
+ int l, c;
+ if (t1_block_length == 0)
+ return;
+ c = t1_getbyte ();
+ if (decrypt)
+ c = edecrypt (c);
+ l = t1_block_length;
+ if (!(l == 0 && (c == 10 || c == 13))) {
+ pdftex_warn ("%i bytes more than expected were ignored", l + 1);
+ while (l-- > 0)
+ t1_getbyte ();
+ }
+}
+
+static void t1_start_eexec (void)
+{
+ int i;
+ assert(is_included(fd_cur->fm));
+ get_length1 ();
+ save_offset ();
+
+ if (!t1_pfa)
+ t1_check_block_len (false);
+ for (t1_line_ptr = t1_line_array, i = 0; i < 4; i++) {
+ edecrypt (t1_getbyte ());
+ *t1_line_ptr++ = 0;
+ }
+ t1_eexec_encrypt = true;
+ t1_putline (); /* to put the first four bytes */
+}
+
+static void t1_stop_eexec (void)
+{
+ int c;
+ assert(is_included(fd_cur->fm));
+ get_length2 ();
+ save_offset ();
+ t1_eexec_encrypt = false;
+ if (!t1_pfa)
+ t1_check_block_len (true);
+ else {
+ c = edecrypt (t1_getbyte ());
+ if (!(c == 10 || c == 13)) {
+ if (last_hexbyte == 0)
+ t1_puts ("00");
+ else
+ pdftex_warn ("unexpected data after eexec");
+ }
+ }
+ t1_cs = false;
+ t1_in_eexec = 2;
+}
+
+/* macros for various transforms; currently only slant and extend are used */
+
+# define do_xshift(x,a) {x[4]+=a;}
+# define do_yshift(x,a) {x[5]+=a;}
+# define do_xscale(x,a) {x[0]*=a; x[2]*=a; x[4]*=a;}
+# define do_yscale(x,a) {x[1]*=a; x[3]*=a; x[5]*=a;}
+# define do_extend(x,a) {do_xscale(x,a);}
+# define do_scale(x,a) {do_xscale(x,a); do_yscale(x,a);}
+# define do_slant(x,a) {x[0]+=x[1]*(a); x[2]+=x[3]*(a); x[4]+=x[5]*(a);}
+# define do_shear(x,a) {x[1]+=x[0]*(a); x[3]+=x[2]*(a); x[5]+=x[4]*(a);}
+# define do_rotate(x,a) \
+ {float t, u=cos(a), v=sin(a); \
+ t =x[0]*u+x[1]*-v; \
+ x[1] =x[0]*v+x[1]* u; x[0]=t; \
+ t =x[2]*u+x[3]*-v; \
+ x[3] =x[2]*v+x[3]* u; x[2]=t; \
+ t =x[4]*u+x[5]*-v; \
+ x[5] =x[4]*v+x[5]* u; x[4]=t;}
+
+static void t1_modify_fm (void)
+{
+ /*
+ * font matrix is given as six numbers a0..a5, which stands for the matrix
+ *
+ * a0 a1 0
+ * M = a2 a3 0
+ * a4 a5 1
+ *
+ * ExtendFont is given as
+ *
+ * e 0 0
+ * E = 0 1 0
+ * 0 0 1
+ *
+ * SlantFont is given as
+ *
+ * 1 0 0
+ * S = s 1 0
+ * 0 0 1
+ *
+ * The slant transform must be done _before_ the extend transform
+ * for compatibility!
+ */
+ float a[6];
+ int i, c;
+ char *p, *q, *r;
+ if ((p = strchr (t1_line_array, '[')) == 0)
+ if ((p = strchr (t1_line_array, '{')) == 0) {
+ remove_eol (p, t1_line_array);
+ pdftex_fail ("FontMatrix: an array expected: `%s'", t1_line_array);
+ }
+ c = *p++; /* save the character '[' resp. '{' */
+ strncpy (t1_buf_array, t1_line_array, (size_t) (p - t1_line_array));
+ r = t1_buf_array + (p - t1_line_array);
+ for (i = 0; i < 6; i++) {
+ a[i] = t1_scan_num (p, &q);
+ p = q;
+ }
+ if (fm_slant(fd_cur->fm) != 0)
+ do_slant(a, fm_slant(fd_cur->fm) * 1E-3);
+ if (fm_extend(fd_cur->fm) != 0)
+ do_extend(a, fm_extend(fd_cur->fm) * 1E-3);
+ for (i = 0; i < 6; i++) {
+ sprintf (r, "%g ", a[i]);
+ r = strend (r);
+ }
+ if (c == '[') {
+ while (*p != ']' && *p != 0)
+ p++;
+ } else {
+ while (*p != '}' && *p != 0)
+ p++;
+ }
+ if (*p == 0) {
+ remove_eol (p, t1_line_array);
+ pdftex_fail
+ ("FontMatrix: cannot find the corresponding character to '%c': `%s'",
+ c, t1_line_array);
+ }
+ strcpy (r, p);
+ strcpy (t1_line_array, t1_buf_array);
+ t1_line_ptr = eol (t1_line_array);
+}
+
+static void t1_modify_italic (void)
+{
+ float a;
+ char *p, *r;
+ if (fm_slant(fd_cur->fm) == 0)
+ return;
+ p = strchr (t1_line_array, ' ');
+ strncpy (t1_buf_array, t1_line_array, (size_t) (p - t1_line_array + 1));
+ a = t1_scan_num (p + 1, &r);
+ a -= atan (fm_slant(fd_cur->fm) * 1E-3) * (180 / M_PI);
+ sprintf (t1_buf_array + (p - t1_line_array + 1), "%g", a);
+ strcpy (strend (t1_buf_array), r);
+ strcpy (t1_line_array, t1_buf_array);
+ t1_line_ptr = eol (t1_line_array);
+ fd_cur->font_dim[ITALIC_ANGLE_CODE].val = round(a);
+ fd_cur->font_dim[ITALIC_ANGLE_CODE].set = true;
+}
+
+static void t1_scan_keys (void)
+{
+ int i, k;
+ char *p, *q, *r;
+ key_entry *key;
+ if (fm_extend(fd_cur->fm) != 0 || fm_slant(fd_cur->fm) != 0) {
+ if (t1_prefix ("/FontMatrix")) {
+ t1_modify_fm ();
+ return;
+ }
+ if (t1_prefix ("/ItalicAngle")) {
+ t1_modify_italic ();
+ return;
+ }
+ }
+ if (t1_prefix ("/FontType")) {
+ p = t1_line_array + strlen ("FontType") + 1;
+ if ((i = t1_scan_num (p, 0)) != 1)
+ pdftex_fail ("Type%d fonts unsupported by pdfTeX", i);
+ return;
+ }
+ for (key = (key_entry *) font_key; key - font_key < FONT_KEYS_NUM; key++) {
+ if (key->t1name[0] != '\0' &&
+ str_prefix(t1_line_array + 1, key->t1name))
+ break;
+ }
+ if (key - font_key == FONT_KEYS_NUM)
+ return;
+ p = t1_line_array + strlen (key->t1name) + 1;
+ skip (p, ' ');
+ if ((k = key - font_key) == FONTNAME_CODE) {
+ if (*p != '/') {
+ remove_eol (p, t1_line_array);
+ pdftex_fail ("a name expected: `%s'", t1_line_array);
+ }
+ r = ++p; /* skip the slash */
+ for (q = t1_buf_array; *p != ' ' && *p != 10; *q++ = *p++);
+ *q = 0;
+ if (fm_slant(fd_cur->fm) != 0) {
+ sprintf(q, "-Slant_%i", (int) fm_slant(fd_cur->fm));
+ q = strend (q);
+ }
+ if (fm_extend(fd_cur->fm) != 0) {
+ sprintf(q, "-Extend_%i", (int) fm_extend(fd_cur->fm));
+ }
+ xfree(fd_cur->fontname);
+ fd_cur->fontname = xstrdup(t1_buf_array);
+ /* at this moment we cannot call make_subset_tag() yet, as the encoding
+ * is not read; thus we mark the offset of the subset tag and write it
+ * later */
+ if (is_subsetted(fd_cur->fm)) {
+ assert(is_included(fd_cur->fm));
+ t1_fontname_offset = t1_offset () + (r - t1_line_array);
+ strcpy (t1_buf_array, p);
+ sprintf(r, "ABCDEF+%s%s", fd_cur->fontname, t1_buf_array);
+ t1_line_ptr = eol (r);
+ }
+ return;
+ }
+ if ((k == STEMV_CODE || k == FONTBBOX1_CODE)
+ && (*p == '[' || *p == '{'))
+ p++;
+ if (k == FONTBBOX1_CODE) {
+ for (i = 0; i < 4; i++, k++) {
+ fd_cur->font_dim[k].val = t1_scan_num(p, &r);
+ fd_cur->font_dim[k].set = true;
+ p = r;
+ }
+ return;
+ }
+ fd_cur->font_dim[k].val = t1_scan_num(p, 0);
+ fd_cur->font_dim[k].set = true;
+}
+
+static void t1_scan_param (void)
+{
+ static const char *lenIV = "/lenIV";
+ if (!t1_scan || *t1_line_array != '/')
+ return;
+ if (t1_prefix (lenIV)) {
+ t1_lenIV = t1_scan_num (t1_line_array + strlen (lenIV), 0);
+ return;
+ }
+ t1_scan_keys ();
+}
+
+static void copy_glyph_names (char **glyph_names, int a, int b)
+{
+ if (glyph_names[b] != notdef) {
+ xfree (glyph_names[b]);
+ glyph_names[b] = (char *) notdef;
+ }
+ if (glyph_names[a] != notdef) {
+ glyph_names[b] = xstrdup (glyph_names[a]);
+ }
+}
+
+/* read encoding from Type1 font file, return glyph_names array, or pdffail() */
+
+char **t1_builtin_enc(void)
+{
+ int i, a, b, c, counter = 0;
+ char *r, *p, **glyph_names;
+ /* At this moment "/Encoding" is the prefix of t1_line_array */
+ glyph_names = xtalloc(256, char *);
+ for (i = 0; i < 256; i++)
+ glyph_names[i] = (char *) notdef;
+ if (t1_suffix("def")) { /* predefined encoding */
+ sscanf(t1_line_array + strlen("/Encoding"), "%256s", t1_buf_array);
+ if (strcmp(t1_buf_array, "StandardEncoding") == 0) {
+ t1_encoding = ENC_STANDARD;
+ for (i = 0; i < 256; i++) {
+ if (standard_glyph_names[i] != notdef)
+ glyph_names[i] = xstrdup(standard_glyph_names[i]);
+ }
+ return glyph_names;
+ } else
+ pdftex_fail
+ ("cannot subset font (unknown predefined encoding `%s')",
+ t1_buf_array);
+ }
+ /* At this moment "/Encoding" is the prefix of t1_line_array, and the encoding is
+ * not a predefined encoding.
+ *
+ * We have two possible forms of Encoding vector. The first case is
+ *
+ * /Encoding [/a /b /c...] readonly def
+ *
+ * and the second case can look like
+ *
+ * /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for
+ * dup 0 /x put
+ * dup 1 /y put
+ * ...
+ * readonly def
+ */
+ t1_encoding = ENC_BUILTIN;
+ if (t1_prefix("/Encoding [") || t1_prefix("/Encoding[")) { /* the first case */
+ r = strchr(t1_line_array, '[') + 1;
+ skip(r, ' ');
+ for (;;) {
+ while (*r == '/') {
+ for (p = t1_buf_array, r++;
+ *r != 32 && *r != 10 && *r != ']' && *r != '/';
+ *p++ = *r++);
+ *p = 0;
+ skip(r, ' ');
+ if (counter > 255)
+ pdftex_fail("encoding vector contains more than 256 names");
+ if (strcmp(t1_buf_array, notdef) != 0)
+ glyph_names[counter] = xstrdup(t1_buf_array);
+ counter++;
+ }
+ if (*r != 10 && *r != '%') {
+ if (str_prefix(r, "] def")
+ || str_prefix(r, "] readonly def"))
+ break;
+ else {
+ remove_eol(r, t1_line_array);
+ pdftex_fail
+ ("a name or `] def' or `] readonly def' expected: `%s'",
+ t1_line_array);
+ }
+ }
+ t1_getline();
+ r = t1_line_array;
+ }
+ } else { /* the second case */
+ p = strchr(t1_line_array, 10);
+ for (;;) {
+ if (*p == 10) {
+ t1_getline();
+ p = t1_line_array;
+ }
+ /*
+ check for `dup <index> <glyph> put'
+ */
+ if (sscanf(p, "dup %i%256s put", &i, t1_buf_array) == 2 &&
+ *t1_buf_array == '/' && valid_code(i)) {
+ if (strcmp(t1_buf_array + 1, notdef) != 0)
+ glyph_names[i] = xstrdup(t1_buf_array + 1);
+ p = strstr(p, " put") + strlen(" put");
+ skip(p, ' ');
+ }
+ /*
+ check for `dup dup <to> exch <from> get put'
+ */
+ else if (sscanf(p, "dup dup %i exch %i get put", &b, &a) == 2
+ && valid_code(a) && valid_code(b)) {
+ copy_glyph_names(glyph_names, a, b);
+ p = strstr(p, " get put") + strlen(" get put");
+ skip(p, ' ');
+ }
+ /*
+ check for `dup dup <from> <size> getinterval <to> exch putinterval'
+ */
+ else if (sscanf
+ (p, "dup dup %i %i getinterval %i exch putinterval",
+ &a, &c, &b) == 3 && valid_code(a) && valid_code(b)
+ && valid_code(c)) {
+ for (i = 0; i < c; i++)
+ copy_glyph_names(glyph_names, a + i, b + i);
+ p = strstr(p, " putinterval") + strlen(" putinterval");
+ skip(p, ' ');
+ }
+ /*
+ check for `def' or `readonly def'
+ */
+ else if ((p == t1_line_array || (p > t1_line_array && p[-1] == ' '))
+ && strcmp(p, "def\n") == 0)
+ return glyph_names;
+ /*
+ skip an unrecognizable word
+ */
+ else {
+ while (*p != ' ' && *p != 10)
+ p++;
+ skip(p, ' ');
+ }
+ }
+ }
+ return glyph_names;
+}
+
+
+static void t1_check_end (void)
+{
+ if (t1_eof ())
+ return;
+ t1_getline ();
+ if (t1_prefix ("{restore}"))
+ t1_putline ();
+}
+
+static boolean t1_open_fontfile (const char *open_name_prefix)
+{
+ int callback_id = 0;
+ int file_opened = 0;
+ char *ftemp = NULL;
+ ff_entry *ff;
+ ff = check_ff_exist(fd_cur->fm->ff_name, is_truetype(fd_cur->fm));
+ t1_curbyte = 0;
+ t1_size = 0;
+ if (ff->ff_path != NULL) {
+ callback_id=callback_defined(find_type1_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",ff->ff_path,&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ strcpy(ff->ff_path,ftemp);
+ }
+ }
+ }
+ callback_id=callback_defined(read_type1_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->bSd",ff->ff_path,
+ &file_opened, &t1_buffer,&t1_size)
+ && file_opened && t1_size>0) {
+ cur_file_name = ff->ff_path;
+ } else {
+ set_cur_file_name (fd_cur->fm->ff_name);
+ pdftex_warn ("cannot open Type 1 font file for reading");
+ return false;
+ }
+ } else {
+ t1_file = xfopen (cur_file_name = ff->ff_path, FOPEN_RBIN_MODE);
+ t1_read_file();
+ t1_close();
+ }
+ }
+ else {
+ set_cur_file_name (fd_cur->fm->ff_name);
+ pdftex_warn ("cannot open Type 1 font file for reading");
+ return false;
+ }
+ t1_init_params (open_name_prefix);
+ return true;
+}
+
+static void t1_include (void)
+{
+ do {
+ t1_getline ();
+ t1_scan_param ();
+ t1_putline ();
+ }
+ while (t1_in_eexec == 0);
+ t1_start_eexec ();
+ do {
+ t1_getline ();
+ t1_scan_param ();
+ t1_putline ();
+ }
+ while (!(t1_charstrings () || t1_subrs ()));
+ t1_cs = true;
+ do {
+ t1_getline ();
+ t1_putline ();
+ }
+ while (!t1_end_eexec ());
+ t1_stop_eexec ();
+ if (fixedcontent) { /* copy 512 zeros (not needed for PDF) */
+ do {
+ t1_getline ();
+ t1_putline ();
+ }
+ while (!t1_cleartomark ());
+ t1_check_end (); /* write "{restore}if" if found */
+ }
+ get_length3 ();
+}
+
+#define check_subr(subr) \
+ if (subr >= subr_size || subr < 0) \
+ pdftex_fail("Subrs array: entry index out of range (%i)", subr);
+
+static const char **check_cs_token_pair ()
+{
+ const char **p = (const char **) cs_token_pairs_list;
+ for (; p[0] != NULL; ++p)
+ if (t1_buf_prefix (p[0]) && t1_buf_suffix (p[1]))
+ return p;
+ return NULL;
+}
+
+static void cs_store (boolean is_subr)
+{
+ char *p;
+ cs_entry *ptr;
+ int subr;
+ for (p = t1_line_array, t1_buf_ptr = t1_buf_array; *p != ' ';
+ *t1_buf_ptr++ = *p++);
+ *t1_buf_ptr = 0;
+ if (is_subr) {
+ subr = t1_scan_num (p + 1, 0);
+ check_subr (subr);
+ ptr = subr_tab + subr;
+ } else {
+ ptr = cs_ptr++;
+ if (cs_ptr - cs_tab > cs_size)
+ pdftex_fail
+ ("CharStrings dict: more entries than dict size (%i)", cs_size);
+ if (strcmp (t1_buf_array + 1, notdef) == 0) /* skip the slash */
+ ptr->name = (char *) notdef;
+ else
+ ptr->name = xstrdup (t1_buf_array + 1);
+ }
+ /* copy " RD " + cs data to t1_buf_array */
+ memcpy (t1_buf_array, t1_line_array + cs_start - 4,
+ (unsigned) (t1_cslen + 4));
+ /* copy the end of cs data to t1_buf_array */
+ for (p = t1_line_array + cs_start + t1_cslen, t1_buf_ptr =
+ t1_buf_array + t1_cslen + 4; *p != 10; *t1_buf_ptr++ = *p++);
+ *t1_buf_ptr++ = 10;
+ if (is_subr && cs_token_pair == NULL)
+ cs_token_pair = check_cs_token_pair ();
+ ptr->len = t1_buf_ptr - t1_buf_array;
+ ptr->cslen = t1_cslen;
+ ptr->data = xtalloc (ptr->len, byte);
+ memcpy (ptr->data, t1_buf_array, ptr->len);
+ ptr->valid = true;
+}
+
+#define store_subr() cs_store(true)
+#define store_cs() cs_store(false)
+
+#define CC_STACK_SIZE 24
+
+static integer cc_stack[CC_STACK_SIZE], *stack_ptr = cc_stack;
+static cc_entry cc_tab[CS_MAX];
+static boolean is_cc_init = false;
+
+
+#define cc_pop(N) \
+ if (stack_ptr - cc_stack < (N)) \
+ stack_error(N); \
+ stack_ptr -= N
+
+#define stack_error(N) { \
+ pdftex_warn("CharString: invalid access (%i) to stack (%i entries)", \
+ (int) N, (int)(stack_ptr - cc_stack)); \
+ goto cs_error; \
+}
+
+/*
+static integer cc_get(integer index)
+{
+ if (index < 0) {
+ if (stack_ptr + index < cc_stack )
+ stack_error(stack_ptr - cc_stack + index);
+ return *(stack_ptr + index);
+ }
+ else {
+ if (cc_stack + index >= stack_ptr)
+ stack_error(index);
+ return cc_stack[index];
+ }
+}
+*/
+
+#define cc_get(N) ((N) < 0 ? *(stack_ptr + (N)) : *(cc_stack + (N)))
+
+#define cc_push(V) *stack_ptr++ = V
+#define cc_clear() stack_ptr = cc_stack
+
+#define set_cc(N, B, A, C) \
+ cc_tab[N].nargs = A; \
+ cc_tab[N].bottom = B; \
+ cc_tab[N].clear = C; \
+ cc_tab[N].valid = true
+
+static void cc_init (void)
+{
+ int i;
+ if (is_cc_init)
+ return;
+ for (i = 0; i < CS_MAX; i++)
+ cc_tab[i].valid = false;
+ set_cc (CS_HSTEM, true, 2, true);
+ set_cc (CS_VSTEM, true, 2, true);
+ set_cc (CS_VMOVETO, true, 1, true);
+ set_cc (CS_RLINETO, true, 2, true);
+ set_cc (CS_HLINETO, true, 1, true);
+ set_cc (CS_VLINETO, true, 1, true);
+ set_cc (CS_RRCURVETO, true, 6, true);
+ set_cc (CS_CLOSEPATH, false, 0, true);
+ set_cc (CS_CALLSUBR, false, 1, false);
+ set_cc (CS_RETURN, false, 0, false);
+ /*
+ set_cc(CS_ESCAPE, false, 0, false);
+ */
+ set_cc (CS_HSBW, true, 2, true);
+ set_cc (CS_ENDCHAR, false, 0, true);
+ set_cc (CS_RMOVETO, true, 2, true);
+ set_cc (CS_HMOVETO, true, 1, true);
+ set_cc (CS_VHCURVETO, true, 4, true);
+ set_cc (CS_HVCURVETO, true, 4, true);
+ set_cc (CS_DOTSECTION, false, 0, true);
+ set_cc (CS_VSTEM3, true, 6, true);
+ set_cc (CS_HSTEM3, true, 6, true);
+ set_cc (CS_SEAC, true, 5, true);
+ set_cc (CS_SBW, true, 4, true);
+ set_cc (CS_DIV, false, 2, false);
+ set_cc (CS_CALLOTHERSUBR, false, 0, false);
+ set_cc (CS_POP, false, 0, false);
+ set_cc (CS_SETCURRENTPOINT, true, 2, true);
+ is_cc_init = true;
+}
+
+#define cs_getchar() cdecrypt(*data++, &cr)
+
+#define mark_subr(n) cs_mark(0, n)
+#define mark_cs(s) cs_mark(s, 0)
+
+__attribute__ ((format (printf, 3, 4)))
+static void cs_warn (const char *cs_name, int subr, const char *fmt, ...)
+{
+ char buf[SMALL_BUF_SIZE];
+ va_list args;
+ va_start (args, fmt);
+ vsprintf (buf, fmt, args);
+ va_end (args);
+ if (cs_name == NULL)
+ pdftex_warn ("Subr (%i): %s", (int) subr, buf);
+ else
+ pdftex_warn ("CharString (/%s): %s", cs_name, buf);
+}
+
+static void cs_mark (const char *cs_name, int subr)
+{
+ byte *data;
+ int i, b, cs_len;
+ integer a, a1, a2;
+ unsigned short cr;
+ static integer lastargOtherSubr3 = 3; /* the argument of last call to
+ OtherSubrs[3] */
+ cs_entry *ptr;
+ cc_entry *cc;
+ if (cs_name == NULL) {
+ check_subr (subr);
+ ptr = subr_tab + subr;
+ if (!ptr->valid)
+ return;
+ } else {
+ if (cs_notdef != NULL &&
+ (cs_name == notdef || strcmp (cs_name, notdef) == 0))
+ ptr = cs_notdef;
+ else {
+ for (ptr = cs_tab; ptr < cs_ptr; ptr++)
+ if (strcmp (ptr->name, cs_name) == 0)
+ break;
+ if (ptr == cs_ptr) {
+ pdftex_warn ("glyph `%s' undefined", cs_name);
+ return;
+ }
+ if (ptr->name == notdef)
+ cs_notdef = ptr;
+ }
+ }
+ /* only marked CharString entries and invalid entries can be skipped;
+ valid marked subrs must be parsed to keep the stack in sync */
+ if (!ptr->valid || (ptr->used && cs_name != NULL))
+ return;
+ ptr->used = true;
+ cr = 4330;
+ cs_len = ptr->cslen;
+ data = ptr->data + 4;
+ for (i = 0; i < t1_lenIV; i++, cs_len--)
+ cs_getchar ();
+ while (cs_len > 0) {
+ --cs_len;
+ b = cs_getchar ();
+ if (b >= 32) {
+ if (b <= 246)
+ a = b - 139;
+ else if (b <= 250) {
+ --cs_len;
+ a = ((b - 247) << 8) + 108 + cs_getchar ();
+ } else if (b <= 254) {
+ --cs_len;
+ a = -((b - 251) << 8) - 108 - cs_getchar ();
+ } else {
+ cs_len -= 4;
+ a = (cs_getchar () & 0xff) << 24;
+ a |= (cs_getchar () & 0xff) << 16;
+ a |= (cs_getchar () & 0xff) << 8;
+ a |= (cs_getchar () & 0xff) << 0;
+ if (sizeof (integer) > 4 && (a & 0x80000000))
+ a |= ~0x7FFFFFFF;
+ }
+ cc_push (a);
+ } else {
+ if (b == CS_ESCAPE) {
+ b = cs_getchar () + CS_1BYTE_MAX;
+ cs_len--;
+ }
+ if (b >= CS_MAX) {
+ cs_warn (cs_name, subr, "command value out of range: %i",
+ (int) b);
+ goto cs_error;
+ }
+ cc = cc_tab + b;
+ if (!cc->valid) {
+ cs_warn (cs_name, subr, "command not valid: %i", (int) b);
+ goto cs_error;
+ }
+ if (cc->bottom) {
+ if (stack_ptr - cc_stack < cc->nargs)
+ cs_warn (cs_name, subr,
+ "less arguments on stack (%i) than required (%i)",
+ (int) (stack_ptr - cc_stack), (int) cc->nargs);
+ else if (stack_ptr - cc_stack > cc->nargs)
+ cs_warn (cs_name, subr,
+ "more arguments on stack (%i) than required (%i)",
+ (int) (stack_ptr - cc_stack), (int) cc->nargs);
+ }
+ switch (cc - cc_tab) {
+ case CS_CALLSUBR:
+ a1 = cc_get (-1);
+ cc_pop (1);
+ mark_subr (a1);
+ if (!subr_tab[a1].valid) {
+ cs_warn (cs_name, subr, "cannot call subr (%i)", (int) a1);
+ goto cs_error;
+ }
+ break;
+ case CS_DIV:
+ cc_pop (2);
+ cc_push (0);
+ break;
+ case CS_CALLOTHERSUBR:
+ if (cc_get (-1) == 3)
+ lastargOtherSubr3 = cc_get (-3);
+ a1 = cc_get (-2) + 2;
+ cc_pop (a1);
+ break;
+ case CS_POP:
+ cc_push (lastargOtherSubr3);
+ /* the only case when we care about the value being pushed onto
+ stack is when POP follows CALLOTHERSUBR (changing hints by
+ OtherSubrs[3])
+ */
+ break;
+ case CS_SEAC:
+ a1 = cc_get (3);
+ a2 = cc_get (4);
+ cc_clear ();
+ mark_cs (standard_glyph_names[a1]);
+ mark_cs (standard_glyph_names[a2]);
+ break;
+ default:
+ if (cc->clear)
+ cc_clear ();
+ }
+ }
+ }
+ return;
+ cs_error: /* an error occured during parsing */
+ cc_clear ();
+ ptr->valid = false;
+ ptr->used = false;
+}
+
+/**********************************************************************/
+/* AVL search tree for glyph code by glyph name */
+
+static int comp_t1_glyphs(const void *pa, const void *pb, void *p)
+{
+ return strcmp(*((const char **) pa), *((const char **) pb));
+}
+
+struct avl_table *create_t1_glyph_tree(char **glyph_names)
+{
+ int i;
+ void **aa;
+ static struct avl_table *gl_tree;
+ gl_tree = avl_create(comp_t1_glyphs, NULL, &avl_xallocator);
+ assert(gl_tree != NULL);
+ for (i = 0; i < 256; i++) {
+ if (glyph_names[i] != notdef &&
+ (char **) avl_find(gl_tree, &glyph_names[i]) == NULL) {
+ /* no strdup here, just point to the glyph_names array members */
+ aa = avl_probe(gl_tree, &glyph_names[i]);
+ assert(aa != NULL);
+ }
+ }
+ return gl_tree;
+}
+
+void destroy_t1_glyph_tree(struct avl_table *gl_tree)
+{
+ assert(gl_tree != NULL);
+ avl_destroy(gl_tree, NULL);
+}
+
+/**********************************************************************/
+
+static void t1_subset_ascii_part(void)
+{
+ int j, *p;
+ char *glyph, **gg, **glyph_names;
+ struct avl_table *gl_tree;
+ struct avl_traverser t;
+ void **aa;
+ assert(fd_cur != NULL);
+ assert(fd_cur->gl_tree != NULL);
+ t1_getline();
+ while (!t1_prefix("/Encoding")) {
+ t1_scan_param();
+ t1_putline();
+ t1_getline();
+ }
+ glyph_names = t1_builtin_enc();
+ fd_cur->builtin_glyph_names = glyph_names;
+ if (is_subsetted(fd_cur->fm)) {
+ assert(is_included(fd_cur->fm));
+ if (fd_cur->tx_tree != NULL) {
+ /* take over collected non-reencoded characters from TeX */
+ avl_t_init(&t, fd_cur->tx_tree);
+ for (p = (int *) avl_t_first(&t, fd_cur->tx_tree); p != NULL;
+ p = (int *) avl_t_next(&t)) {
+ if ((char *) avl_find(fd_cur->gl_tree, glyph_names[*p]) == NULL) {
+ glyph = xstrdup(glyph_names[*p]);
+ aa = avl_probe(fd_cur->gl_tree, glyph);
+ assert(aa != NULL);
+ }
+ }
+ }
+ make_subset_tag(fd_cur);
+ assert(t1_fontname_offset != 0);
+ strncpy(fb_array + t1_fontname_offset, fd_cur->subset_tag, 6);
+ }
+ /* now really all glyphs needed from this font are in the fd_cur->gl_tree */
+ if (t1_encoding == ENC_STANDARD)
+ t1_puts("/Encoding StandardEncoding def\n");
+ else {
+ t1_puts
+ ("/Encoding 256 array\n0 1 255 {1 index exch /.notdef put} for\n");
+ gl_tree = create_t1_glyph_tree(glyph_names);
+ avl_t_init(&t, fd_cur->gl_tree);
+ j = 0;
+ for (glyph = (char *) avl_t_first(&t, fd_cur->gl_tree); glyph != NULL;
+ glyph = (char *) avl_t_next(&t)) {
+ if ((gg = (char **) avl_find(gl_tree, &glyph)) != NULL) {
+ t1_printf("dup %i /%s put\n", (int) (gg - glyph_names), *gg);
+ j++;
+ }
+ }
+ destroy_t1_glyph_tree(gl_tree);
+ if (j == 0)
+ /* We didn't mark anything for the Encoding array. */
+ /* We add "dup 0 /.notdef put" for compatibility */
+ /* with Acrobat 5.0. */
+ t1_puts("dup 0 /.notdef put\n");
+ t1_puts("readonly def\n");
+ }
+ do {
+ t1_getline();
+ t1_scan_param();
+ if (!t1_prefix("/UniqueID")) /* ignore UniqueID for subsetted fonts */
+ t1_putline();
+ }
+ while (t1_in_eexec == 0);
+}
+
+
+static void cs_init (void)
+{
+ cs_ptr = cs_tab = NULL;
+ cs_dict_start = cs_dict_end = NULL;
+ cs_counter = cs_size = cs_size_pos = 0;
+ cs_token_pair = NULL;
+ subr_tab = NULL;
+ subr_array_start = subr_array_end = NULL;
+ subr_max = subr_size = subr_size_pos = 0;
+}
+
+static void init_cs_entry (cs_entry * cs)
+{
+ cs->data = NULL;
+ cs->name = NULL;
+ cs->len = 0;
+ cs->cslen = 0;
+ cs->used = false;
+ cs->valid = false;
+}
+
+static void t1_read_subrs (void)
+{
+ int i, s;
+ cs_entry *ptr;
+ t1_getline ();
+ while (!(t1_charstrings () || t1_subrs ())) {
+ t1_scan_param ();
+ t1_putline ();
+ t1_getline ();
+ }
+ found:
+ t1_cs = true;
+ t1_scan = false;
+ if (!t1_subrs ())
+ return;
+ subr_size_pos = strlen ("/Subrs") + 1;
+ /* subr_size_pos points to the number indicating dict size after "/Subrs" */
+ subr_size = t1_scan_num (t1_line_array + subr_size_pos, 0);
+ if (subr_size == 0) {
+ while (!t1_charstrings ())
+ t1_getline ();
+ return;
+ }
+ subr_tab = xtalloc (subr_size, cs_entry);
+ for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
+ init_cs_entry (ptr);
+ subr_array_start = xstrdup (t1_line_array);
+ t1_getline ();
+ while (t1_cslen) {
+ store_subr ();
+ t1_getline ();
+ }
+ /* mark the first four entries without parsing */
+ for (i = 0; i < subr_size && i < 4; i++)
+ subr_tab[i].used = true;
+ /* the end of the Subrs array might have more than one line so we need to
+ concatnate them to subr_array_end. Unfortunately some fonts don't have
+ the Subrs array followed by the CharStrings dict immediately (synthetic
+ fonts). If we cannot find CharStrings in next POST_SUBRS_SCAN lines then
+ we will treat the font as synthetic and ignore everything until next
+ Subrs is found
+ */
+#define POST_SUBRS_SCAN 5
+ s = 0;
+ *t1_buf_array = 0;
+ for (i = 0; i < POST_SUBRS_SCAN; i++) {
+ if (t1_charstrings ())
+ break;
+ s += t1_line_ptr - t1_line_array;
+ alloc_array (t1_buf, s, T1_BUF_SIZE);
+ strcat (t1_buf_array, t1_line_array);
+ t1_getline ();
+ }
+ subr_array_end = xstrdup (t1_buf_array);
+ if (i == POST_SUBRS_SCAN) { /* CharStrings not found;
+ suppose synthetic font */
+ for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
+ if (ptr->valid)
+ xfree (ptr->data);
+ xfree (subr_tab);
+ xfree (subr_array_start);
+ xfree (subr_array_end);
+ cs_init ();
+ t1_cs = false;
+ t1_synthetic = true;
+ while (!(t1_charstrings () || t1_subrs ()))
+ t1_getline ();
+ goto found;
+ }
+}
+
+#define t1_subr_flush() t1_flush_cs(true)
+#define t1_cs_flush() t1_flush_cs(false)
+
+static void t1_flush_cs (boolean is_subr)
+{
+ char *p;
+ byte *r, *return_cs = NULL;
+ cs_entry *tab, *end_tab, *ptr;
+ char *start_line, *line_end;
+ int count, size_pos;
+ unsigned short cr, cs_len;
+ if (is_subr) {
+ start_line = subr_array_start;
+ line_end = subr_array_end;
+ size_pos = subr_size_pos;
+ tab = subr_tab;
+ count = subr_max + 1;
+ end_tab = subr_tab + count;
+ } else {
+ start_line = cs_dict_start;
+ line_end = cs_dict_end;
+ size_pos = cs_size_pos;
+ tab = cs_tab;
+ end_tab = cs_ptr;
+ count = cs_counter;
+ }
+ t1_line_ptr = t1_line_array;
+ for (p = start_line; p - start_line < size_pos;)
+ *t1_line_ptr++ = *p++;
+ while (isdigit (*p))
+ p++;
+ sprintf (t1_line_ptr, "%u", count);
+ strcat (t1_line_ptr, p);
+ t1_line_ptr = eol (t1_line_array);
+ t1_putline ();
+
+ cs_len = 0; /* for -Wall */
+ /* create return_cs to replace unsused subr's */
+ if (is_subr) {
+ cr = 4330;
+ cs_len = 0;
+ return_cs = xtalloc (t1_lenIV + 1, byte);
+ if (t1_lenIV > 0) {
+ for (cs_len = 0, r = return_cs; cs_len < t1_lenIV; cs_len++, r++)
+ *r = cencrypt (0x00, &cr);
+ *r = cencrypt (CS_RETURN, &cr);
+ } else {
+ *return_cs = CS_RETURN;
+ }
+ cs_len++;
+ }
+
+ for (ptr = tab; ptr < end_tab; ptr++) {
+ if (ptr->used) {
+ if (is_subr)
+ sprintf (t1_line_array, "dup %li %u", (long int)(ptr - tab), ptr->cslen);
+ else
+ sprintf (t1_line_array, "/%s %u", ptr->name, ptr->cslen);
+ p = strend (t1_line_array);
+ memcpy (p, ptr->data, ptr->len);
+ t1_line_ptr = p + ptr->len;
+ t1_putline ();
+ } else {
+ /* replace unsused subr's by return_cs */
+ if (is_subr) {
+ sprintf (t1_line_array, "dup %li %u%s ", (long int)(ptr - tab), cs_len,
+ cs_token_pair[0]);
+ p = strend (t1_line_array);
+ memcpy (p, return_cs, cs_len);
+ t1_line_ptr = p + cs_len;
+ t1_putline ();
+ sprintf (t1_line_array, " %s", cs_token_pair[1]);
+ t1_line_ptr = eol (t1_line_array);
+ t1_putline ();
+ }
+ }
+ xfree (ptr->data);
+ if (ptr->name != notdef)
+ xfree (ptr->name);
+ }
+ sprintf (t1_line_array, "%s", line_end);
+ t1_line_ptr = eol (t1_line_array);
+ t1_putline ();
+ if (is_subr)
+ xfree (return_cs);
+ xfree (tab);
+ xfree (start_line);
+ xfree (line_end);
+}
+
+static void t1_mark_glyphs(void)
+{
+ char *glyph;
+ struct avl_traverser t;
+ cs_entry *ptr;
+ if (t1_synthetic || fd_cur->all_glyphs) { /* mark everything */
+ if (cs_tab != NULL)
+ for (ptr = cs_tab; ptr < cs_ptr; ptr++)
+ if (ptr->valid)
+ ptr->used = true;
+ if (subr_tab != NULL) {
+ for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
+ if (ptr->valid)
+ ptr->used = true;
+ subr_max = subr_size - 1;
+ }
+ return;
+ }
+ mark_cs(notdef);
+ avl_t_init(&t, fd_cur->gl_tree);
+ for (glyph = (char *) avl_t_first(&t, fd_cur->gl_tree); glyph != NULL;
+ glyph = (char *) avl_t_next(&t)) {
+ mark_cs(glyph);
+ }
+ if (subr_tab != NULL)
+ for (subr_max = -1, ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
+ if (ptr->used && ptr - subr_tab > subr_max)
+ subr_max = ptr - subr_tab;
+}
+
+
+static void t1_subset_charstrings (void)
+{
+ cs_entry *ptr;
+ cs_size_pos =
+ strstr (t1_line_array, charstringname) + strlen (charstringname)
+ - t1_line_array + 1;
+ /* cs_size_pos points to the number indicating
+ dict size after "/CharStrings" */
+ cs_size = t1_scan_num (t1_line_array + cs_size_pos, 0);
+ cs_ptr = cs_tab = xtalloc (cs_size, cs_entry);
+ for (ptr = cs_tab; ptr - cs_tab < cs_size; ptr++)
+ init_cs_entry (ptr);
+ cs_notdef = NULL;
+ cs_dict_start = xstrdup (t1_line_array);
+ t1_getline ();
+ while (t1_cslen) {
+ store_cs ();
+ t1_getline ();
+ }
+ cs_dict_end = xstrdup (t1_line_array);
+ t1_mark_glyphs ();
+ if (subr_tab != NULL) {
+ if (cs_token_pair == NULL)
+ pdftex_fail
+ ("This Type 1 font uses mismatched subroutine begin/end token pairs.");
+ t1_subr_flush ();
+ }
+ for (cs_counter = 0, ptr = cs_tab; ptr < cs_ptr; ptr++)
+ if (ptr->used)
+ cs_counter++;
+ t1_cs_flush ();
+}
+
+static void t1_subset_end (void)
+{
+ if (t1_synthetic) { /* copy to "dup /FontName get exch definefont pop" */
+ while (!strstr (t1_line_array, "definefont")) {
+ t1_getline ();
+ t1_putline ();
+ }
+ while (!t1_end_eexec ())
+ t1_getline (); /* ignore the rest */
+ t1_putline (); /* write "mark currentfile closefile" */
+ } else
+ while (!t1_end_eexec ()) { /* copy to "mark currentfile closefile" */
+ t1_getline ();
+ t1_putline ();
+ }
+ t1_stop_eexec ();
+ if (fixedcontent) { /* copy 512 zeros (not needed for PDF) */
+ while (!t1_cleartomark ()) {
+ t1_getline ();
+ t1_putline ();
+ }
+ if (!t1_synthetic) /* don't check "{restore}if" for synthetic fonts */
+ t1_check_end (); /* write "{restore}if" if found */
+ }
+ get_length3 ();
+}
+
+void writet1(fd_entry * fd)
+{
+ fd_cur = fd; /* fd_cur is global inside writet1.c */
+ assert(fd_cur->fm != NULL);
+ assert(is_type1(fd->fm));
+ assert(is_included(fd->fm));
+
+ t1_save_offset = 0;
+ if (!is_subsetted(fd_cur->fm)) { /* include entire font */
+ if (!(fd->ff_found = t1_open_fontfile("<<")))
+ return;
+ t1_include ();
+ t1_close_font_file (">>");
+ return;
+ }
+ /* partial downloading */
+ if (!(fd->ff_found = t1_open_fontfile("<")))
+ return;
+ t1_subset_ascii_part ();
+ t1_start_eexec ();
+ cc_init ();
+ cs_init ();
+ t1_read_subrs ();
+ t1_subset_charstrings ();
+ t1_subset_end ();
+ t1_close_font_file (">");
+}
+
+void t1_free ()
+{
+ xfree (t1_line_array);
+ xfree (t1_buf_array);
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/font/writet3.c b/Build/source/texk/web2c/luatexdir/font/writet3.c
new file mode 100644
index 00000000000..42827d1b124
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writet3.c
@@ -0,0 +1,348 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writet3.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+#include <kpathsea/tex-glyph.h>
+#include <kpathsea/magstep.h>
+#include <string.h>
+
+#define T3_BUF_SIZE 1024
+
+typedef char t3_line_entry;
+define_array (t3_line);
+
+FILE *t3_file;
+static boolean t3_image_used;
+
+static integer t3_char_procs[256];
+static float t3_char_widths[256];
+static int t3_glyph_num;
+static float t3_font_scale;
+static integer t3_b0, t3_b1, t3_b2, t3_b3;
+static boolean is_pk_font;
+
+static unsigned char *t3_buffer = NULL;
+static integer t3_size = 0;
+static integer t3_curbyte = 0;
+
+
+#define t3_open() \
+ open_input(&t3_file, kpse_miscfonts_format, FOPEN_RBIN_MODE)
+#define t3_read_file() readbinfile(t3_file,&t3_buffer,&t3_size)
+#define t3_close() xfclose(t3_file, cur_file_name)
+#define t3_getchar() t3_buffer[t3_curbyte++]
+#define t3_eof() (t3_curbyte>t3_size)
+
+#define t3_prefix(s) (!strncmp(t3_line_array, s, strlen(s)))
+#define t3_putchar(c) pdfout(c)
+
+
+
+#define t3_check_eof() \
+ if (t3_eof()) \
+ pdftex_fail("unexpected end of file");
+
+
+static void update_bbox (integer llx, integer lly, integer urx, integer ury,
+ boolean is_first_glyph)
+{
+ if (is_first_glyph) {
+ t3_b0 = llx;
+ t3_b1 = lly;
+ t3_b2 = urx;
+ t3_b3 = ury;
+ } else {
+ if (llx < t3_b0)
+ t3_b0 = llx;
+ if (lly < t3_b1)
+ t3_b1 = lly;
+ if (urx > t3_b2)
+ t3_b2 = urx;
+ if (ury > t3_b3)
+ t3_b3 = ury;
+ }
+}
+
+static integer get_pk_font_scale (internalfontnumber f)
+{
+ return
+ divide_scaled (pk_scale_factor,
+ divide_scaled (pdf_font_size(f), one_hundred_bp,
+ fixed_decimal_digits + 2), 0);
+}
+
+static integer pk_char_width (internalfontnumber f, scaled w)
+{
+ return
+ divide_scaled (divide_scaled (w, pdf_font_size(f), 7),
+ get_pk_font_scale (f), 0);
+}
+
+scaled get_pk_char_width (internalfontnumber f, scaled w)
+{
+ return (get_pk_font_scale (f) / 100000.0) *
+ (pk_char_width (f, w) / 100.0) * pdf_font_size(f);
+}
+
+static boolean writepk (internalfontnumber f)
+{
+ kpse_glyph_file_type font_ret;
+ integer llx, lly, urx, ury;
+ integer cw, rw, i, j;
+ halfword *row;
+ char *name;
+ char *ftemp = NULL;
+ chardesc cd;
+ boolean is_null_glyph, check_preamble;
+ integer dpi;
+ int callback_id=0;
+ int file_opened=0;
+ int mallocsize=0;
+ if (t3_buffer!=NULL) {
+ xfree(t3_buffer);
+ t3_buffer=NULL;
+ }
+ t3_curbyte=0;
+ t3_size=0;
+
+ callback_id=callback_defined(find_pk_file_callback);
+
+ if (callback_id>0) {
+ dpi = round (fixed_pk_resolution *
+ (((float) pdf_font_size(f)) / font_dsize(f)));
+ /* <base>.dpi/<fontname>.<tdpi>pk */
+ cur_file_name = font_name(f);
+ mallocsize = strlen(cur_file_name)+24+9;
+ name = xmalloc(mallocsize);
+ snprintf(name,mallocsize,"%ddpi/%s.%dpk",(int)fixed_pk_resolution,cur_file_name,(int)dpi);
+ if(run_callback(callback_id,"S->S",name,&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ free(name);
+ name = xstrdup(ftemp);
+ free(ftemp);
+ }
+ }
+ } else {
+ dpi =
+ kpse_magstep_fix (round
+ (fixed_pk_resolution *
+ (((float) pdf_font_size(f)) / font_dsize(f))),
+ fixed_pk_resolution, NULL);
+ cur_file_name = font_name(f);
+ name = kpse_find_pk (cur_file_name, (unsigned) dpi, &font_ret);
+ if (name == NULL ||
+ !FILESTRCASEEQ (cur_file_name, font_ret.name) ||
+ !kpse_bitmap_tolerance ((float) font_ret.dpi, (float) dpi)) {
+ pdftex_warn ("Font %s at %i not found", cur_file_name, (int) dpi);
+ cur_file_name = NULL;
+ return false;
+ }
+ }
+ callback_id=callback_defined(read_pk_file_callback);
+ if (callback_id>0) {
+ if(! ( run_callback(callback_id,"S->bSd",name, &file_opened, &t3_buffer,&t3_size) &&
+ file_opened &&
+ t3_size>0 ) ) {
+ pdftex_warn ("Font %s at %i not found", cur_file_name, (int)dpi);
+ cur_file_name = NULL;
+ return false;
+ }
+ } else {
+ t3_file = xfopen (name, FOPEN_RBIN_MODE);
+ t3_read_file();
+ t3_close();
+ }
+ t3_image_used = true;
+ is_pk_font = true;
+ if (tracefilenames)
+ tex_printf (" <%s", (char *) name);
+ cd.rastersize = 256;
+ cd.raster = xtalloc (cd.rastersize, halfword);
+ check_preamble = true;
+ while (readchar (check_preamble, &cd) != 0) {
+ check_preamble = false;
+ if (!pdf_char_marked (f, cd.charcode))
+ continue;
+ t3_char_widths[cd.charcode] =
+ pk_char_width (f, get_charwidth (f, cd.charcode));
+ if (cd.cwidth < 1 || cd.cheight < 1) {
+ cd.xescape = cd.cwidth =
+ round (t3_char_widths[cd.charcode] / 100.0);
+ cd.cheight = 1;
+ cd.xoff = 0;
+ cd.yoff = 0;
+ is_null_glyph = true;
+ } else
+ is_null_glyph = false;
+ llx = -cd.xoff;
+ lly = cd.yoff - cd.cheight + 1;
+ urx = cd.cwidth + llx + 1;
+ ury = cd.cheight + lly;
+ update_bbox (llx, lly, urx, ury, t3_glyph_num == 0);
+ t3_glyph_num++;
+ pdf_new_dict (0, 0, 0);
+ t3_char_procs[cd.charcode] = obj_ptr;
+ pdf_begin_stream ();
+ pdf_print_real (t3_char_widths[cd.charcode], 2);
+ pdf_printf (" 0 %i %i %i %i d1\n",
+ (int) llx, (int) lly, (int) urx, (int) ury);
+ if (is_null_glyph)
+ goto end_stream;
+ pdf_printf ("q\n%i 0 0 %i %i %i cm\nBI\n", (int) cd.cwidth,
+ (int) cd.cheight, (int) llx, (int) lly);
+ pdf_printf ("/W %i\n/H %i\n", (int) cd.cwidth, (int) cd.cheight);
+ pdf_puts ("/IM true\n/BPC 1\n/D [1 0]\nID ");
+ cw = (cd.cwidth + 7) / 8;
+ rw = (cd.cwidth + 15) / 16;
+ row = cd.raster;
+ for (i = 0; i < cd.cheight; i++) {
+ for (j = 0; j < rw - 1; j++) {
+ pdfout (*row / 256);
+ pdfout (*row % 256);
+ row++;
+ }
+ pdfout (*row / 256);
+ if (2 * rw == cw)
+ pdfout (*row % 256);
+ row++;
+ }
+ pdf_puts ("\nEI\nQ\n");
+ end_stream:
+ pdf_end_stream ();
+ }
+ xfree (cd.raster);
+ cur_file_name = NULL;
+ return true;
+}
+
+void writet3 (int objnum, internalfontnumber f)
+{
+
+ int i;
+ integer wptr, eptr, cptr;
+ int first_char, last_char;
+ integer pk_font_scale;
+ boolean is_notdef;
+
+
+ t3_glyph_num = 0;
+ t3_image_used = false;
+ for (i = 0; i < 256; i++) {
+ t3_char_procs[i] = 0;
+ t3_char_widths[i] = 0;
+ }
+ pack_file_name (tex_font_name(f), get_nullstr (), maketexlstring (".pgc",4));
+ cur_file_name = makecstring (make_name_string ());
+ is_pk_font = false;
+
+ if (t3_buffer!=NULL) {
+ xfree(t3_buffer);
+ t3_buffer=NULL;
+ }
+ t3_curbyte=0;
+ t3_size=0;
+ if (!writepk (f)) {
+ cur_file_name = NULL;
+ return;
+ }
+ for (i = font_bc(f); i <= font_ec(f); i++)
+ if (pdf_char_marked (f, i))
+ break;
+ first_char = i;
+ for (i = font_ec(f); i > first_char; i--)
+ if (pdf_char_marked (f, i))
+ break;
+ last_char = i;
+ pdf_begin_dict (objnum, 1); /* Type 3 font dictionary */
+ pdf_puts ("/Type /Font\n/Subtype /Type3\n");
+ pdf_printf ("/Name /F%i\n", (int) f);
+ if (pdf_font_attr(f) != get_nullstr ()) {
+ pdf_print (pdf_font_attr(f));
+ pdf_puts ("\n");
+ }
+ if (is_pk_font) {
+ pk_font_scale = get_pk_font_scale (f);
+ pdf_puts ("/FontMatrix [");
+ pdf_print_real (pk_font_scale, 5);
+ pdf_puts (" 0 0 ");
+ pdf_print_real (pk_font_scale, 5);
+ pdf_puts (" 0 0]\n");
+ } else
+ pdf_printf ("/FontMatrix [%g 0 0 %g 0 0]\n",
+ (double) t3_font_scale, (double) t3_font_scale);
+ pdf_printf ("/%s [ %i %i %i %i ]\n",
+ font_key[FONTBBOX1_CODE].pdfname,
+ (int) t3_b0, (int) t3_b1, (int) t3_b2, (int) t3_b3);
+ pdf_printf ("/Resources << /ProcSet [ /PDF %s] >>\n",
+ t3_image_used ? "/ImageB " : "");
+ pdf_printf ("/FirstChar %i\n/LastChar %i\n", first_char, last_char);
+ wptr = pdf_new_objnum ();
+ eptr = pdf_new_objnum ();
+ cptr = pdf_new_objnum ();
+ pdf_printf ("/Widths %i 0 R\n/Encoding %i 0 R\n/CharProcs %i 0 R\n",
+ (int)wptr, (int)eptr, (int)cptr);
+ pdf_end_dict ();
+ pdf_begin_obj (wptr, 1); /* chars width array */
+ pdf_puts ("[");
+ if (is_pk_font)
+ for (i = first_char; i <= last_char; i++) {
+ pdf_print_real (t3_char_widths[i], 2);
+ pdf_puts (" ");
+ } else
+ for (i = first_char; i <= last_char; i++)
+ pdf_printf ("%i ", (int) t3_char_widths[i]);
+ pdf_puts ("]\n");
+ pdf_end_obj ();
+ pdf_begin_dict (eptr, 1); /* encoding dictionary */
+ pdf_printf ("/Type /Encoding\n/Differences [%i", first_char);
+ if (t3_char_procs[first_char] == 0) {
+ pdf_printf ("/%s", notdef);
+ is_notdef = true;
+ } else {
+ pdf_printf ("/a%i", first_char);
+ is_notdef = false;
+ }
+ for (i = first_char + 1; i <= last_char; i++) {
+ if (t3_char_procs[i] == 0) {
+ if (!is_notdef) {
+ pdf_printf (" %i/%s", i, notdef);
+ is_notdef = true;
+ }
+ } else {
+ if (is_notdef) {
+ pdf_printf (" %i", i);
+ is_notdef = false;
+ }
+ pdf_printf ("/a%i", i);
+ }
+ }
+ pdf_puts ("]\n");
+ pdf_end_dict ();
+ pdf_begin_dict (cptr, 1); /* CharProcs dictionary */
+ for (i = first_char; i <= last_char; i++)
+ if (t3_char_procs[i] != 0)
+ pdf_printf ("/a%i %i 0 R\n", (int) i, (int) t3_char_procs[i]);
+ pdf_end_dict ();
+ if (tracefilenames)
+ tex_printf (">");
+ cur_file_name = NULL;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/writettf.c b/Build/source/texk/web2c/luatexdir/font/writettf.c
new file mode 100644
index 00000000000..2a92706a0de
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writettf.c
@@ -0,0 +1,1509 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writettf.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+#include "writettf.h"
+#include <string.h>
+
+#define DEFAULT_NTABS 14
+#define NEW_CMAP_SIZE 2
+
+#define ttf_putchar fb_putchar
+#define ttf_offset fb_offset
+#define ttf_seek_outbuf fb_seek
+
+ /* #define INFILE ttf_file*/
+
+unsigned char *ttf_buffer = NULL;
+integer ttf_size = 0;
+integer ttf_curbyte = 0;
+
+typedef struct {
+ char *name; /* name of glyph */
+ long code; /* charcode in case of subfonts */
+ short newindex; /* new index of glyph in output file */
+
+} ttfenc_entry;
+
+typedef struct {
+ TTF_USHORT platform_id;
+ TTF_USHORT encoding_id;
+ TTF_USHORT language_id;
+ TTF_USHORT name_id;
+ TTF_USHORT length;
+ TTF_USHORT offset;
+ TTF_USHORT new_offset;
+ TTF_USHORT new_length;
+} name_record;
+
+typedef struct {
+ char *ttf_name;
+ TTF_USHORT pid;
+ TTF_USHORT eid;
+ short *table;
+} ttf_cmap_entry;
+
+static TTF_USHORT ntabs;
+static TTF_USHORT upem;
+static TTF_FIXED post_format;
+static TTF_SHORT loca_format;
+static TTF_ULONG last_glyf_offset;
+static TTF_USHORT glyphs_count;
+static TTF_USHORT new_glyphs_count;
+static TTF_USHORT nhmtxs;
+static TTF_USHORT new_ntabs;
+
+glyph_entry *glyph_tab;
+dirtab_entry *dir_tab;
+
+static long *glyph_index;
+static cmap_entry *cmap_tab, new_cmap_tab[NEW_CMAP_SIZE];
+static name_record *name_tab;
+static int name_record_num;
+static char *name_buf;
+static int name_buf_size;
+static char *glyph_name_buf;
+static TTF_ULONG checksum;
+static TTF_ULONG tab_length;
+static TTF_ULONG tmp_ulong;
+static TTF_ULONG checkSumAdjustment_offset;
+FILE *ttf_file;
+static ttfenc_entry ttfenc_tab[256];
+
+fd_entry *fd_cur; /* pointer to the current font descriptor */
+
+static struct avl_table *ttf_cmap_tree = NULL;
+
+integer ttf_length;
+
+#include "macnames.c"
+
+extern char *fb_array;
+extern char charsetstr[];
+
+static const char *newtabnames[] = {
+ "OS/2",
+ "PCLT",
+ "cmap",
+ "cvt ",
+ "fpgm",
+ "glyf",
+ "head",
+ "hhea",
+ "hmtx",
+ "loca",
+ "maxp",
+ "name",
+ "post",
+ "prep"
+};
+
+ttf_cmap_entry *new_ttf_cmap_entry (void)
+{
+ ttf_cmap_entry *e;
+ e = xtalloc (1, ttf_cmap_entry);
+ e->ttf_name = NULL;
+ e->table = NULL;
+ return e;
+}
+
+static void destroy_ttf_cmap_entry (void *pa, void *pb)
+{
+ ttf_cmap_entry *p;
+ p = (ttf_cmap_entry *) pa;
+ xfree (p->ttf_name);
+ xfree (p->table);
+ xfree (p);
+}
+
+void ttf_free (void)
+{
+ if (ttf_cmap_tree != NULL)
+ avl_destroy (ttf_cmap_tree, destroy_ttf_cmap_entry);
+}
+
+static int comp_ttf_cmap_entry (const void *pa, const void *pb, void *p)
+{
+ const ttf_cmap_entry *p1 = (const ttf_cmap_entry *) pa,
+ *p2 = (const ttf_cmap_entry *) pb;
+ int i;
+ assert (p1->ttf_name != NULL && p2->ttf_name != NULL);
+ if ((i = strcmp (p1->ttf_name, p2->ttf_name)) != 0)
+ return i;
+ cmp_return (p1->pid, p2->pid);
+ cmp_return (p1->eid, p2->eid);
+ return 0;
+}
+
+static unsigned char ttf_addchksm (unsigned char b)
+{
+ tmp_ulong = (tmp_ulong << 8) + b;
+ tab_length++;
+ if (tab_length % 4 == 0) {
+ checksum += tmp_ulong;
+ tmp_ulong = 0;
+ }
+ return b;
+}
+
+static TTF_ULONG ttf_getchksm (void)
+{
+ while (tab_length % 4 != 0)
+ ttf_putchar (ttf_addchksm (0)); /* ttf_addchksm updates tab_length */
+ return checksum;
+}
+
+long ttf_putnum (int s, long n)
+{
+ long i = n;
+ char buf[TTF_LONG_SIZE + 1], *p = buf;
+ while (s-- > 0) {
+ *p++ = i & 0xFF;
+ i >>= 8;
+ }
+ p--;
+ while (p >= buf)
+ ttf_putchar (ttf_addchksm (*p--));
+ return n;
+}
+
+long ttf_getnum (int s)
+{
+ long i = 0;
+ int c;
+ while (s > 0) {
+ if (ttf_eof())
+ pdftex_fail ("unexpected EOF");
+ c = ttf_getchar ();
+ i = (i << 8) + c;
+ s--;
+ }
+ return i;
+}
+
+static long ttf_funit (long n)
+{
+ if (n < 0)
+ return -((-n / upem) * 1000 + ((-n % upem) * 1000) / upem);
+ else
+ return (n / upem) * 1000 + ((n % upem) * 1000) / upem;
+}
+
+static void ttf_ncopy (int n)
+{
+ while (n-- > 0)
+ copy_byte ();
+}
+
+dirtab_entry *ttf_name_lookup (const char *s, boolean required)
+{
+ dirtab_entry *tab;
+ for (tab = dir_tab; tab - dir_tab < ntabs; tab++)
+ if (strncmp (tab->tag, s, 4) == 0)
+ break;
+ if (tab - dir_tab == ntabs) {
+ if (required)
+ pdftex_fail ("can't find table `%s'", s);
+ else
+ tab = NULL;
+ }
+ return tab;
+}
+
+dirtab_entry *ttf_seek_tab (const char *name, TTF_LONG offset)
+{
+ dirtab_entry *tab = ttf_name_lookup (name, true);
+ /*xfseek (INFILE, tab->offset + offset, SEEK_SET, cur_file_name);*/
+ ttf_curbyte = tab->offset + offset;
+ return tab;
+}
+
+static void ttf_seek_off (TTF_LONG offset)
+{
+ ttf_curbyte = offset;
+ //xfseek (INFILE, offset, SEEK_SET, cur_file_name);
+}
+
+static void ttf_copy_encoding(void)
+{
+ int i, *q;
+ void **aa;
+ char **glyph_names;
+ long *charcodes;
+ static char buf[SMALL_BUF_SIZE];
+ struct avl_traverser t;
+ ttfenc_entry *e = ttfenc_tab;
+
+ assert(fd_cur->tx_tree != NULL); /* this must be set in create_fontdictionary */
+
+ if (fd_cur->fe != NULL) {
+ glyph_names = fd_cur->fe->glyph_names;
+ assert(glyph_names != NULL);
+
+ for (i = 0; i < 256; i++)
+ ttfenc_tab[i].name = (char *) notdef;
+
+ /* a workaround for a bug of AcroReader 4.0 */
+ if (strcmp(glyph_names[97], "a") == 0) {
+ q = xtalloc(1, int);
+ *q = 'a';
+ aa = avl_probe(fd_cur->tx_tree, q);
+ assert(aa != NULL);
+ }
+ /* end of workaround */
+
+ /* take over collected characters from TeX, reencode them */
+ avl_t_init(&t, fd_cur->tx_tree);
+ for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL;
+ q = (int *) avl_t_next(&t)) {
+ assert(*q >= 0 && *q < 256);
+ ttfenc_tab[*q].name = glyph_names[*q];
+ }
+ make_subset_tag(fd_cur);
+ } else if (is_subfont(fd_cur->fm)) {
+ charcodes = fd_cur->fm->subfont->charcodes;
+ assert(charcodes != NULL);
+
+ for (i = 0; i < 256; i++)
+ ttfenc_tab[i].code = -1;
+
+ /* take over collected characters from TeX */
+ avl_t_init(&t, fd_cur->tx_tree);
+ for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL;
+ q = (int *) avl_t_next(&t)) {
+ assert(*q >= 0 && *q < 256);
+ e = ttfenc_tab + *q;
+ e->code = charcodes[*q];
+ if (e->code == -1)
+ pdftex_warn("character %i is not mapped to any charcode", *q);
+ else {
+ assert(e->code < 0x10000);
+ sprintf(buf, "/c%4.4X", (int) e->code);
+ aa = avl_probe(fd_cur->gl_tree, xstrdup(buf));
+ assert(aa != NULL);
+ }
+ }
+ make_subset_tag(fd_cur);
+ } else
+ assert(0);
+}
+
+#define ttf_append_byte(B)\
+do {\
+ if (name_tab[i].platform_id == 3)\
+ *q++ = 0;\
+ *q++ = B;\
+} while (0)
+
+static char *strip_spaces_and_delims(char *s, int l)
+{
+ static char buf[SMALL_BUF_SIZE];
+ char *p = buf;
+ int i;
+
+ assert(l >= 0 && l < (int) sizeof(buf));
+
+ for (i = 0; i < l; s++, i++) {
+ if (*s == '(' || *s == ')' || *s == '<' || *s == '>' ||
+ *s == '[' || *s == ']' || *s == '{' || *s == '}' ||
+ *s == '/' || *s == '%' || isspace(*s))
+ continue;
+ *p++ = *s;
+ }
+ *p = 0;
+ return buf;
+}
+
+static void ttf_read_name (void)
+{
+ int i, j;
+ dirtab_entry *tab = ttf_seek_tab ("name", TTF_USHORT_SIZE);
+ char *p;
+ name_record_num = get_ushort ();
+ name_tab = xtalloc (name_record_num, name_record);
+ name_buf_size = tab->length -
+ (3 * TTF_USHORT_SIZE + name_record_num * 6 * TTF_USHORT_SIZE);
+ name_buf = xtalloc (name_buf_size, char);
+ ttf_skip (TTF_USHORT_SIZE);
+ for (i = 0; i < name_record_num; i++) {
+ name_tab[i].platform_id = get_ushort ();
+ name_tab[i].encoding_id = get_ushort ();
+ name_tab[i].language_id = get_ushort ();
+ name_tab[i].name_id = get_ushort ();
+ name_tab[i].length = get_ushort ();
+ name_tab[i].offset = get_ushort ();
+ }
+ for (p = name_buf; p - name_buf < name_buf_size; p++)
+ *p = get_char ();
+ /* look for PS font name */
+ for (i = 0; i < name_record_num; i++) {
+ if (name_tab[i].platform_id == 1 &&
+ name_tab[i].encoding_id == 0 && name_tab[i].name_id == 6) {
+ xfree(fd_cur->fontname);
+ fd_cur->fontname =
+ xstrdup(strip_spaces_and_delims(name_buf + name_tab[i].offset,
+ name_tab[i].length));
+ fd_cur->font_dim[FONTNAME_CODE].set = true;
+ break;
+ }
+ }
+ if (!fd_cur->font_dim[FONTNAME_CODE].set) {
+ for (i = 0; i < name_record_num; i++) {
+ if (name_tab[i].platform_id == 3 &&
+ (name_tab[i].encoding_id == 0 ||
+ name_tab[i].encoding_id == 1) && name_tab[i].name_id == 6) {
+ for (j = 0, p = fd_cur->fontname; j < name_tab[i].length;
+ j += 2)
+ *p++ = name_buf[name_tab[i].offset + j + 1];
+ *p = 0;
+ fd_cur->font_dim[FONTNAME_CODE].set = true;
+ break;
+ }
+ }
+ }
+}
+
+static void ttf_read_mapx (void)
+{
+ glyph_entry *glyph;
+ ttf_seek_tab ("maxp", TTF_FIXED_SIZE);
+ glyph_tab = xtalloc (1 + (glyphs_count = get_ushort ()), glyph_entry);
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++) {
+ glyph->newindex = -1;
+ glyph->newoffset = 0;
+ glyph->name_index = 0;
+ glyph->name = (char *) notdef;
+ }
+ glyph_index = xtalloc (glyphs_count, long);
+ glyph_index[0] = 0; /* index of ".notdef" glyph */
+ glyph_index[1] = 1; /* index of ".null" glyph */
+}
+
+void ttf_read_head (void)
+{
+ ttf_seek_tab ("head",
+ 2 * TTF_FIXED_SIZE + 2 * TTF_ULONG_SIZE + TTF_USHORT_SIZE);
+ upem = get_ushort ();
+ ttf_skip (16);
+ fd_cur->font_dim[FONTBBOX1_CODE].val = ttf_funit(get_fword());
+ fd_cur->font_dim[FONTBBOX2_CODE].val = ttf_funit(get_fword());
+ fd_cur->font_dim[FONTBBOX3_CODE].val = ttf_funit(get_fword());
+ fd_cur->font_dim[FONTBBOX4_CODE].val = ttf_funit(get_fword());
+ fd_cur->font_dim[FONTBBOX1_CODE].set = true;
+ fd_cur->font_dim[FONTBBOX2_CODE].set = true;
+ fd_cur->font_dim[FONTBBOX3_CODE].set = true;
+ fd_cur->font_dim[FONTBBOX4_CODE].set = true;
+ ttf_skip (2 * TTF_USHORT_SIZE + TTF_SHORT_SIZE);
+ loca_format = get_short ();
+}
+
+void ttf_read_hhea (void)
+{
+ ttf_seek_tab ("hhea", TTF_FIXED_SIZE);
+ fd_cur->font_dim[ASCENT_CODE].val = ttf_funit(get_fword());
+ fd_cur->font_dim[DESCENT_CODE].val = ttf_funit(get_fword());
+ fd_cur->font_dim[ASCENT_CODE].set = true;
+ fd_cur->font_dim[DESCENT_CODE].set = true;
+ ttf_skip (TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3 * TTF_FWORD_SIZE +
+ 8 * TTF_SHORT_SIZE);
+ nhmtxs = get_ushort ();
+}
+
+void ttf_read_pclt (void)
+{
+ if (ttf_name_lookup ("PCLT", false) == NULL)
+ return;
+ ttf_seek_tab ("PCLT", TTF_FIXED_SIZE + TTF_ULONG_SIZE + TTF_USHORT_SIZE);
+ fd_cur->font_dim[XHEIGHT_CODE].val = ttf_funit(get_ushort());
+ ttf_skip(2 * TTF_USHORT_SIZE);
+ fd_cur->font_dim[CAPHEIGHT_CODE].val = ttf_funit(get_ushort());
+ fd_cur->font_dim[XHEIGHT_CODE].set = true;
+ fd_cur->font_dim[CAPHEIGHT_CODE].set = true;
+}
+
+static void ttf_read_hmtx (void)
+{
+ glyph_entry *glyph;
+ TTF_UFWORD last_advWidth;
+ ttf_seek_tab ("hmtx", 0);
+ for (glyph = glyph_tab; glyph - glyph_tab < nhmtxs; glyph++) {
+ glyph->advWidth = get_ufword ();
+ glyph->lsb = get_ufword ();
+ }
+ if (nhmtxs < glyphs_count) {
+ last_advWidth = glyph[-1].advWidth;
+ for (; glyph - glyph_tab < glyphs_count; glyph++) {
+ glyph->advWidth = last_advWidth;
+ glyph->lsb = get_ufword ();
+ }
+ }
+}
+
+void ttf_read_post (void)
+{
+ int k, nnames;
+ long length;
+ long int_part, frac_part;
+ int sign = 1;
+ TTF_FIXED italic_angle;
+ char *p;
+ glyph_entry *glyph;
+ const dirtab_entry *tab = ttf_seek_tab ("post", 0);
+ post_format = get_fixed ();
+ italic_angle = get_fixed ();
+ int_part = italic_angle >> 16;
+ if (int_part > 0x7FFF) { /* a negative number */
+ int_part = 0x10000 - int_part;
+ sign = -1;
+ }
+ frac_part = italic_angle % 0x10000;
+ fd_cur->font_dim[ITALIC_ANGLE_CODE].val =
+ sign * (int_part + frac_part * 1.0 / 0x10000);
+ fd_cur->font_dim[ITALIC_ANGLE_CODE].set = true;
+ if (glyph_tab == NULL)
+ return; /* being called from writeotf() */
+ ttf_skip (2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE);
+ switch (post_format) {
+ case 0x10000:
+ for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) {
+ glyph->name = (char *) mac_glyph_names[glyph - glyph_tab];
+ glyph->name_index = glyph - glyph_tab;
+ }
+ break;
+ case 0x20000:
+ nnames = get_ushort (); /* some fonts have this value different from nglyphs */
+ for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++)
+ glyph->name_index = get_ushort ();
+ /*length = tab->length - (xftell (INFILE, cur_file_name) - tab->offset);*/
+ length = tab->length - (ttf_curbyte - tab->offset);
+ glyph_name_buf = xtalloc (length, char);
+ for (p = glyph_name_buf; p - glyph_name_buf < length;) {
+ for (k = get_byte (); k > 0; k--)
+ *p++ = get_char ();
+ *p++ = 0;
+ }
+ for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++) {
+ if (glyph->name_index < NMACGLYPHS)
+ glyph->name = (char *) mac_glyph_names[glyph->name_index];
+ else {
+ p = glyph_name_buf;
+ k = glyph->name_index - NMACGLYPHS;
+ for (; k > 0; k--)
+ p = strend (p) + 1;
+ glyph->name = p;
+ }
+ }
+ break;
+ case 0x00030000:
+ for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) {
+ glyph->name_index = glyph - glyph_tab;
+ }
+ break;
+ default:
+ pdftex_fail ("unsupported format (%.8X) of `post' table",
+ (unsigned int) post_format);
+ }
+}
+
+static void ttf_read_loca (void)
+{
+ glyph_entry *glyph;
+ ttf_seek_tab ("loca", 0);
+ if (loca_format != 0)
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
+ glyph->offset = get_ulong ();
+ else
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
+ glyph->offset = get_ushort () << 1;
+}
+
+void ttf_read_tabdir (void)
+{
+ int i;
+ dirtab_entry *tab;
+ ttf_skip (TTF_FIXED_SIZE); /* ignore the sfnt number */
+ dir_tab = xtalloc (ntabs = get_ushort (), dirtab_entry);
+ ttf_skip (3 * TTF_USHORT_SIZE);
+ for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
+ for (i = 0; i < 4; i++)
+ tab->tag[i] = get_char ();
+ tab->checksum = get_ulong ();
+ tab->offset = get_ulong ();
+ tab->length = get_ulong ();
+ }
+}
+
+static ttf_cmap_entry *ttf_read_cmap (char *ttf_name, int pid, int eid,
+ boolean warn)
+{
+ seg_entry *seg_tab, *s;
+ TTF_USHORT *glyphId, format, segCount;
+ TTF_USHORT ncmapsubtabs, tmp_pid, tmp_eid;
+ TTF_ULONG cmap_offset, tmp_offset;
+ long n, i, k, length, index;
+ ttf_cmap_entry tmp_e, *p;
+ void **aa;
+
+ /* loop up in ttf_cmap_tree first, return if found */
+ tmp_e.ttf_name = ttf_name;
+ tmp_e.pid = pid;
+ tmp_e.eid = eid;
+ if (ttf_cmap_tree == NULL) {
+ ttf_cmap_tree = avl_create (comp_ttf_cmap_entry, NULL, &avl_xallocator);
+ assert (ttf_cmap_tree != NULL);
+ }
+ p = (ttf_cmap_entry *) avl_find (ttf_cmap_tree, &tmp_e);
+ if (p != NULL)
+ return p;
+
+ /* not found, have to read it */
+ ttf_seek_tab ("cmap", TTF_USHORT_SIZE); /* skip the table vesrion number (=0) */
+ ncmapsubtabs = get_ushort ();
+ /* cmap_offset = xftell (INFILE, cur_file_name) - 2 * TTF_USHORT_SIZE;*/
+ cmap_offset = ttf_curbyte - 2 * TTF_USHORT_SIZE;
+ cmap_tab = xtalloc (ncmapsubtabs, cmap_entry);
+ for (i = 0; i < ncmapsubtabs; ++i) {
+ tmp_pid = get_ushort ();
+ tmp_eid = get_ushort ();
+ tmp_offset = get_ulong ();
+ if (tmp_pid == pid && tmp_eid == eid) {
+ ttf_seek_off (cmap_offset + tmp_offset);
+ format = get_ushort ();
+ if (format == 4)
+ goto read_cmap_format_4;
+ else {
+ if (warn)
+ pdftex_warn ("cmap format %i unsupported", format);
+ return NULL;
+ }
+ }
+ }
+ if (warn)
+ pdftex_warn ("cannot find cmap subtable for (pid,eid) = (%i, %i)",
+ pid, eid);
+ return NULL;
+ read_cmap_format_4:
+ /* initialize the new entry */
+ p = new_ttf_cmap_entry ();
+ p->ttf_name = xstrdup (ttf_name);
+ p->pid = pid;
+ p->eid = eid;
+ p->table = xtalloc (0x10000, short);
+ for (i = 0; i < 0x10000; ++i)
+ p->table[i] = -1; /* unassigned yet */
+
+ /* read the subtable */
+ length = get_ushort (); /* length of subtable */
+ (void) get_ushort (); /* skip the version number */
+ segCount = get_ushort () / 2;
+ (void) get_ushort (); /* skip searchRange */
+ (void) get_ushort (); /* skip entrySelector */
+ (void) get_ushort (); /* skip rangeShift */
+ seg_tab = xtalloc (segCount, seg_entry);
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->endCode = get_ushort ();
+ (void) get_ushort (); /* skip reversedPad */
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->startCode = get_ushort ();
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->idDelta = get_ushort ();
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->idRangeOffset = get_ushort ();
+ length -= 8 * TTF_USHORT_SIZE + 4 * segCount * TTF_USHORT_SIZE;
+ n = length / TTF_USHORT_SIZE; /* number of glyphID's */
+ glyphId = xtalloc (n, TTF_USHORT);
+ for (i = 0; i < n; i++)
+ glyphId[i] = get_ushort ();
+ for (s = seg_tab; s - seg_tab < segCount; s++) {
+ for (i = s->startCode; i <= s->endCode; i++) {
+ if (i == 0xFFFF)
+ break;
+ if (s->idRangeOffset != 0xFFFF) {
+ if (s->idRangeOffset == 0)
+ index = (s->idDelta + i) & 0xFFFF;
+ else {
+ k = (i - s->startCode) + s->idRangeOffset / 2 +
+ (s - seg_tab) - segCount;
+ assert (k >= 0 && k < n);
+ index = glyphId[k];
+ if (index != 0)
+ index = (index + s->idDelta) & 0xFFFF;
+ }
+ if (index >= glyphs_count)
+ pdftex_fail ("cmap: glyph index %li out of range [0..%i)",
+ index, glyphs_count);
+ if (p->table[i] != -1)
+ pdftex_warn
+ ("cmap: multiple glyphs are mapped to unicode %.4lX, "
+ "only %i will be used (glyph %li being ignored)", i,
+ p->table[i], index);
+ else
+ p->table[i] = index;
+ }
+ }
+ }
+ xfree (seg_tab);
+ xfree (glyphId);
+ aa = avl_probe (ttf_cmap_tree, p);
+ assert (aa != NULL);
+ return p;
+}
+
+static void ttf_read_font (void)
+{
+ ttf_read_tabdir ();
+ if (ttf_name_lookup ("PCLT", false) == NULL)
+ new_ntabs--;
+ if (ttf_name_lookup ("fpgm", false) == NULL)
+ new_ntabs--;
+ if (ttf_name_lookup ("cvt ", false) == NULL)
+ new_ntabs--;
+ if (ttf_name_lookup ("prep", false) == NULL)
+ new_ntabs--;
+ ttf_read_mapx ();
+ ttf_read_head ();
+ ttf_read_hhea ();
+ ttf_read_pclt ();
+ ttf_read_hmtx ();
+ ttf_read_post ();
+ ttf_read_loca ();
+ ttf_read_name ();
+}
+
+static void ttf_reset_chksm (dirtab_entry * tab)
+{
+ checksum = 0;
+ tab_length = 0;
+ tmp_ulong = 0;
+ tab->offset = ttf_offset ();
+ if (tab->offset % 4 != 0)
+ pdftex_warn ("offset of `%4.4s' is not a multiple of 4", tab->tag);
+}
+
+
+static void ttf_set_chksm (dirtab_entry * tab)
+{
+ tab->length = ttf_offset () - tab->offset;
+ tab->checksum = ttf_getchksm ();
+}
+
+static void ttf_copytab (const char *name)
+{
+ long i;
+ dirtab_entry *tab = ttf_seek_tab (name, 0);
+ ttf_reset_chksm (tab);
+ for (i = tab->length; i > 0; i--)
+ copy_char ();
+ ttf_set_chksm (tab);
+}
+
+#define BYTE_ENCODING_LENGTH \
+ ((256)*TTF_BYTE_SIZE + 3*TTF_USHORT_SIZE)
+
+static void ttf_byte_encoding (void)
+{
+ ttfenc_entry *e;
+ (void) put_ushort (0); /* format number (0: byte encoding table) */
+ (void) put_ushort (BYTE_ENCODING_LENGTH); /* length of table */
+ (void) put_ushort (0); /* version number */
+ for (e = ttfenc_tab; e - ttfenc_tab < 256; e++)
+ if (e->newindex < 256) {
+ put_byte (e->newindex);
+ } else {
+ if (e->name != notdef)
+ pdftex_warn
+ ("glyph `%s' has been mapped to `%s' in `ttf_byte_encoding' cmap table",
+ e->name, notdef);
+ put_byte (0); /* notdef */
+ }
+}
+
+#define TRIMMED_TABLE_MAP_LENGTH (TTF_USHORT_SIZE*(5 + (256)))
+
+static void ttf_trimmed_table_map (void)
+{
+ ttfenc_entry *e;
+ (void) put_ushort (6); /* format number (6): trimmed table mapping */
+ (void) put_ushort (TRIMMED_TABLE_MAP_LENGTH);
+ (void) put_ushort (0); /* version number (0) */
+ (void) put_ushort (0); /* first character code */
+ (void) put_ushort (256); /* number of character code in table */
+ for (e = ttfenc_tab; e - ttfenc_tab < 256; e++)
+ (void) put_ushort (e->newindex);
+}
+
+#define SEG_MAP_DELTA_LENGTH ((16 + (256))*TTF_USHORT_SIZE)
+
+static void ttf_seg_map_delta (void)
+{
+ ttfenc_entry *e;
+ (void) put_ushort (4); /* format number (4: segment mapping to delta values) */
+ (void) put_ushort (SEG_MAP_DELTA_LENGTH);
+ (void) put_ushort (0); /* version number */
+ (void) put_ushort (4); /* 2*segCount */
+ (void) put_ushort (4); /* searchRange */
+ (void) put_ushort (1); /* entrySelector */
+ (void) put_ushort (0); /* rangeShift */
+ (void) put_ushort (0xF0FF); /* endCount[0] */
+ (void) put_ushort (0xFFFF); /* endCount[1] */
+ (void) put_ushort (0); /* reversedPad */
+ (void) put_ushort (0xF000); /* startCount[0] */
+ (void) put_ushort (0xFFFF); /* startCount[1] */
+ (void) put_ushort (0); /* idDelta[0] */
+ (void) put_ushort (1); /* idDelta[1] */
+ (void) put_ushort (2 * TTF_USHORT_SIZE); /* idRangeOffset[0] */
+ (void) put_ushort (0); /* idRangeOffset[1] */
+ for (e = ttfenc_tab; e - ttfenc_tab < 256; e++)
+ (void) put_ushort (e->newindex);
+}
+
+#define CMAP_ENTRY_LENGTH (2*TTF_USHORT_SIZE + TTF_ULONG_SIZE)
+
+static void ttf_select_cmap (void)
+{
+ assert (sizeof (new_cmap_tab) <= NEW_CMAP_SIZE * sizeof (cmap_entry));
+ new_cmap_tab[0].platform_id = 1; /* Macintosh */
+ new_cmap_tab[0].encoding_id = 0; /* Symbol; ignore code page */
+ new_cmap_tab[0].format = new_glyphs_count < 256 ? 0 /* byte encoding */
+ : 6; /* trimmed table mapping */
+ new_cmap_tab[1].platform_id = 3; /* Microsoft */
+ new_cmap_tab[1].encoding_id = 0; /* Symbol; ignore code page */
+ new_cmap_tab[1].format = 4; /* segment mapping to delta */
+}
+
+static void ttf_write_cmap (void)
+{
+ cmap_entry *ce;
+ long offset;
+ dirtab_entry *tab = ttf_name_lookup ("cmap", true);
+ ttf_select_cmap ();
+ ttf_reset_chksm (tab);
+ (void) put_ushort (0); /* table version number (0) */
+ (void) put_ushort (NEW_CMAP_SIZE); /* number of encoding tables */
+ offset = 2 * TTF_USHORT_SIZE + NEW_CMAP_SIZE * CMAP_ENTRY_LENGTH;
+ for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) {
+ ce->offset = offset;
+ switch (ce->format) {
+ case 0:
+ offset += BYTE_ENCODING_LENGTH;
+ break;
+ case 4:
+ offset += SEG_MAP_DELTA_LENGTH;
+ break;
+ case 6:
+ offset += TRIMMED_TABLE_MAP_LENGTH;
+ break;
+ default:
+ pdftex_fail ("invalid format (it should not have happened)");
+ }
+ (void) put_ushort (ce->platform_id);
+ (void) put_ushort (ce->encoding_id);
+ put_ulong (ce->offset);
+ }
+ for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) {
+ switch (ce->format) {
+ case 0:
+ ttf_byte_encoding ();
+ break;
+ case 4:
+ ttf_seg_map_delta ();
+ break;
+ case 6:
+ ttf_trimmed_table_map ();
+ break;
+ }
+ }
+ ttf_set_chksm (tab);
+}
+
+static int prepend_subset_tags (int index, char *p)
+{
+ const boolean is_unicode = (name_tab[index].platform_id == 3);
+ int i;
+ assert (index > 0 && index < name_record_num && fd_cur->subset_tag != NULL);
+ if (is_unicode) {
+ for (i = 0; i < 6; ++i) {
+ *p++ = 0;
+ *p++ = fd_cur->subset_tag[i];
+ }
+ *p++ = 0;
+ *p++ = '+';
+ return 14;
+ } else {
+ strncpy (p, fd_cur->subset_tag, 6);
+ p += 6;
+ *p++ = '+';
+ return 7;
+ }
+}
+
+
+static void ttf_write_name (void)
+{
+ int i, l;
+ char *p;
+ int new_name_buf_size;
+ char *new_name_buf;
+ name_record *n;
+ dirtab_entry *tab = ttf_name_lookup ("name", true);
+ if (is_subsetted (fd_cur->fm)) {
+ l = 0;
+ for (i = 0; i < name_record_num; i++)
+ l += name_tab[i].length + 14; /* maximum lengh of new stogare area */
+ new_name_buf = xtalloc (l, char);
+ /* additional space for subset tags */
+ p = new_name_buf;
+ for (i = 0; i < name_record_num; i++) {
+ n = name_tab + i;
+ n->new_offset = p - new_name_buf;
+ if ((n->name_id == 1 || n->name_id == 3 ||
+ n->name_id == 4 || n->name_id == 6) &&
+ ((n->platform_id == 1 && n->encoding_id == 0) ||
+ (n->platform_id == 3 && n->encoding_id == 0) ||
+ (n->platform_id == 3 && n->encoding_id == 1))) {
+ l = prepend_subset_tags (i, p);
+ p += l;
+ } else
+ l = 0;
+ memcpy (p, name_buf + n->offset, n->length);
+ p += n->length;
+ n->new_length = n->length + l;
+ }
+ new_name_buf_size = p - new_name_buf;
+ } else {
+ new_name_buf = name_buf;
+ new_name_buf_size = name_buf_size;
+ }
+ ttf_reset_chksm (tab);
+ (void) put_ushort (0); /* Format selector */
+ (void) put_ushort (name_record_num);
+ (void) put_ushort (3 * TTF_USHORT_SIZE +
+ name_record_num * 6 * TTF_USHORT_SIZE);
+ for (i = 0; i < name_record_num; i++) {
+ (void) put_ushort (name_tab[i].platform_id);
+ (void) put_ushort (name_tab[i].encoding_id);
+ (void) put_ushort (name_tab[i].language_id);
+ (void) put_ushort (name_tab[i].name_id);
+ (void) put_ushort (name_tab[i].new_length);
+ (void) put_ushort (name_tab[i].new_offset);
+ }
+ for (p = new_name_buf; p - new_name_buf < new_name_buf_size; p++)
+ put_char (*p);
+ ttf_set_chksm (tab);
+ if (new_name_buf != name_buf)
+ xfree (new_name_buf);
+}
+
+static void ttf_write_dirtab (void)
+{
+ dirtab_entry *tab;
+ TTF_ULONG i, k;
+ char *p;
+ const integer save_offset = ttf_offset ();
+ ttf_seek_outbuf (TABDIR_OFF);
+ if (is_subsetted (fd_cur->fm)) {
+ for (i = 0; i < DEFAULT_NTABS; i++) {
+ tab = ttf_name_lookup (newtabnames[i], false);
+ if (tab == NULL)
+ continue;
+ for (k = 0; k < 4; k++)
+ put_char (tab->tag[k]);
+ put_ulong (tab->checksum);
+ put_ulong (tab->offset);
+ put_ulong (tab->length);
+ }
+ } else {
+ for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
+ for (k = 0; k < 4; k++)
+ put_char (tab->tag[k]);
+ put_ulong (tab->checksum);
+ put_ulong (tab->offset);
+ put_ulong (tab->length);
+ }
+ }
+ /* adjust checkSumAdjustment */
+ tmp_ulong = 0;
+ checksum = 0;
+ for (p = fb_array, i = 0; i < (unsigned) save_offset;) {
+ tmp_ulong = (tmp_ulong << 8) + *p++;
+ i++;
+ if (i % 4 == 0) {
+ checksum += tmp_ulong;
+ tmp_ulong = 0;
+ }
+ }
+ if (i % 4 != 0) {
+ pdftex_warn ("font length is not a multiple of 4 (%li)", i);
+ checksum <<= 8 * (4 - i % 4);
+ }
+ k = 0xB1B0AFBA - checksum;
+ ttf_seek_outbuf (checkSumAdjustment_offset);
+ put_ulong (k);
+ ttf_seek_outbuf (save_offset);
+}
+
+static void ttf_write_glyf (void)
+{
+ long *id, k;
+ TTF_USHORT idx;
+ TTF_USHORT flags;
+ dirtab_entry *tab = ttf_name_lookup ("glyf", true);
+ const long glyf_offset = tab->offset;
+ const long new_glyf_offset = ttf_offset ();
+ ttf_reset_chksm (tab);
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
+ glyph_tab[*id].newoffset = ttf_offset () - new_glyf_offset;
+ if (glyph_tab[*id].offset != glyph_tab[*id + 1].offset) {
+ ttf_seek_off (glyf_offset + glyph_tab[*id].offset);
+ k = copy_short ();
+ ttf_ncopy (4 * TTF_FWORD_SIZE);
+ if (k < 0) {
+ do {
+ flags = copy_ushort ();
+ idx = get_ushort ();
+ if (glyph_tab[idx].newindex < 0) {
+ glyph_tab[idx].newindex = new_glyphs_count;
+ glyph_index[new_glyphs_count++] = idx;
+ /*
+ N.B.: Here we change `new_glyphs_count',
+ which appears in the condition of the `for' loop
+ */
+ }
+ (void) put_ushort (glyph_tab[idx].newindex);
+ if (flags & ARG_1_AND_2_ARE_WORDS)
+ ttf_ncopy (2 * TTF_SHORT_SIZE);
+ else
+ ttf_ncopy (TTF_USHORT_SIZE);
+ if (flags & WE_HAVE_A_SCALE)
+ ttf_ncopy (TTF_F2DOT14_SIZE);
+ else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
+ ttf_ncopy (2 * TTF_F2DOT14_SIZE);
+ else if (flags & WE_HAVE_A_TWO_BY_TWO)
+ ttf_ncopy (4 * TTF_F2DOT14_SIZE);
+ } while (flags & MORE_COMPONENTS);
+ if (flags & WE_HAVE_INSTRUCTIONS)
+ ttf_ncopy (copy_ushort ());
+ } else
+ ttf_ncopy (glyph_tab[*id + 1].offset - glyph_tab[*id].offset -
+ TTF_USHORT_SIZE - 4 * TTF_FWORD_SIZE);
+ }
+ }
+ last_glyf_offset = ttf_offset () - new_glyf_offset;
+ ttf_set_chksm (tab);
+}
+
+static void ttf_reindex_glyphs(void)
+{
+ ttfenc_entry *e;
+ glyph_entry *glyph;
+ int index;
+ short *t;
+ ttf_cmap_entry *cmap = NULL;
+ boolean cmap_not_found = false;
+
+ /*
+ * reindexing glyphs: we append index of used glyphs to `glyph_index'
+ * while going through `ttfenc_tab'. After appending a new entry to
+ * `glyph_index' we set field `newindex' of corresponding entries in both
+ * `glyph_tab' and `ttfenc_tab' to the newly created index
+ */
+ for (e = ttfenc_tab; e - ttfenc_tab < 256; e++) {
+ e->newindex = 0; /* index of ".notdef" glyph */
+
+ /* handle case of subfonts first */
+ if (is_subfont(fd_cur->fm)) {
+ if (e->code == -1)
+ continue;
+ assert(fd_cur->fm->pid != -1 && fd_cur->fm->eid != -1);
+ if (cmap == NULL && !cmap_not_found) {
+ cmap =
+ ttf_read_cmap(fd_cur->fm->ff_name, fd_cur->fm->pid,
+ fd_cur->fm->eid, true);
+ if (cmap == NULL)
+ cmap_not_found = true;
+ }
+ if (cmap == NULL)
+ continue;
+ t = cmap->table;
+ assert(t != NULL && e->code < 0x10000);
+ if (t[e->code] < 0) {
+ pdftex_warn
+ ("subfont %s: wrong mapping: character %li --> 0x%4.4lX --> .notdef",
+ fd_cur->fm->tfm_name, (long) (e - ttfenc_tab), e->code);
+ continue;
+ }
+ assert(t[e->code] >= 0 && t[e->code] < glyphs_count); /* t has been read from ttf */
+ glyph = glyph_tab + t[e->code];
+ goto append_new_glyph;
+ }
+
+ /* handle case of reencoded fonts */
+ if (e->name == notdef)
+ continue;
+ /* scan form `index123' */
+ if (sscanf(e->name, GLYPH_PREFIX_INDEX "%i", &index) == 1) {
+ if (index >= glyphs_count) {
+ pdftex_warn("`%s' out of valid range [0..%i)",
+ e->name, glyphs_count);
+ continue;
+ }
+ glyph = glyph_tab + index;
+ goto append_new_glyph;
+ }
+ /* scan form `uniABCD' */
+ if (sscanf(e->name, GLYPH_PREFIX_UNICODE "%X", &index) == 1) {
+ if (cmap == NULL && !cmap_not_found) {
+ /* need to read the unicode mapping, ie (pid,eid) = (3,1) or (0,3) */
+ cmap = ttf_read_cmap(fd_cur->fm->ff_name, 3, 1, false);
+ if (cmap == NULL)
+ cmap = ttf_read_cmap(fd_cur->fm->ff_name, 0, 3, false);
+ if (cmap == NULL) {
+ pdftex_warn
+ ("no unicode mapping found, all `uniXXXX' names will be ignored");
+ cmap_not_found = true; /* once only */
+ }
+ }
+ if (cmap == NULL)
+ continue;
+ t = cmap->table;
+ assert(t != NULL);
+ if (t[index] != -1) {
+ if (t[index] >= glyphs_count) {
+ pdftex_warn
+ ("`%s' is mapped to index %i which is out of valid range [0..%i)",
+ e->name, t[index], glyphs_count);
+ continue;
+ }
+ glyph = glyph_tab + t[index];
+ goto append_new_glyph;
+ } else {
+ pdftex_warn("`unicode %s%.4X' is not mapped to any glyph",
+ GLYPH_PREFIX_UNICODE, index);
+ continue;
+ }
+ }
+ /* look up by name */
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++)
+ if (glyph->name != notdef && strcmp(glyph->name, e->name) == 0)
+ break;
+ if (!(glyph - glyph_tab < glyphs_count)) {
+ pdftex_warn("glyph `%s' not found", e->name);
+ continue;
+ }
+ append_new_glyph:
+ assert(glyph > glyph_tab && glyph - glyph_tab < glyphs_count);
+ if (glyph->newindex < 0) {
+ glyph_index[new_glyphs_count] = (short) (glyph - glyph_tab);
+ glyph->newindex = new_glyphs_count;
+ new_glyphs_count++;
+ }
+ e->newindex = glyph->newindex;
+ }
+}
+
+static void ttf_write_head ()
+{
+ dirtab_entry *tab;
+ tab = ttf_seek_tab ("head", 0);
+ ttf_reset_chksm (tab);
+ ttf_ncopy (2 * TTF_FIXED_SIZE);
+ checkSumAdjustment_offset = ttf_offset ();
+ put_ulong (0);
+ ttf_skip (TTF_ULONG_SIZE); /* skip checkSumAdjustment */
+ ttf_ncopy (TTF_ULONG_SIZE + 2 * TTF_USHORT_SIZE + 16 +
+ 4 * TTF_FWORD_SIZE + 2 * TTF_USHORT_SIZE + TTF_SHORT_SIZE);
+ if (is_subsetted(fd_cur->fm)) {
+ (void) put_short (loca_format);
+ (void) put_short (0);
+ } else
+ ttf_ncopy (2 * TTF_SHORT_SIZE);
+ ttf_set_chksm (tab);
+}
+
+static void ttf_write_hhea (void)
+{
+ dirtab_entry *tab;
+ tab = ttf_seek_tab ("hhea", 0);
+ ttf_reset_chksm (tab);
+ ttf_ncopy (TTF_FIXED_SIZE + 3 * TTF_FWORD_SIZE + TTF_UFWORD_SIZE +
+ 3 * TTF_FWORD_SIZE + 8 * TTF_SHORT_SIZE);
+ (void) put_ushort (new_glyphs_count);
+ ttf_set_chksm (tab);
+}
+
+static void ttf_write_htmx (void)
+{
+ long *id;
+ dirtab_entry *tab = ttf_seek_tab ("hmtx", 0);
+ ttf_reset_chksm (tab);
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
+ put_ufword (glyph_tab[*id].advWidth);
+ put_ufword (glyph_tab[*id].lsb);
+ }
+ ttf_set_chksm (tab);
+}
+
+static void ttf_write_loca (void)
+{
+ long *id;
+ dirtab_entry *tab = ttf_seek_tab ("loca", 0);
+ ttf_reset_chksm (tab);
+ loca_format = 0;
+ if (last_glyf_offset >= 0x00020000 || (last_glyf_offset & 1))
+ loca_format = 1;
+ else
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
+ if (glyph_tab[*id].newoffset & 1) {
+ loca_format = 1;
+ break;
+ }
+ if (loca_format != 0) {
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
+ put_ulong (glyph_tab[*id].newoffset);
+ put_ulong (last_glyf_offset);
+ } else {
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
+ (void) put_ushort (glyph_tab[*id].newoffset / 2);
+ (void) put_ushort (last_glyf_offset / 2);
+ }
+ ttf_set_chksm (tab);
+}
+
+static void ttf_write_mapx (void)
+{
+ dirtab_entry *tab = ttf_seek_tab ("maxp", TTF_FIXED_SIZE + TTF_USHORT_SIZE);
+ ttf_reset_chksm (tab);
+ put_fixed (0x00010000);
+ (void) put_ushort (new_glyphs_count);
+ ttf_ncopy (13 * TTF_USHORT_SIZE);
+ ttf_set_chksm (tab);
+}
+
+static void ttf_write_OS2 (void)
+{
+ dirtab_entry *tab = ttf_seek_tab ("OS/2", 0);
+ TTF_USHORT version;
+ ttf_reset_chksm (tab);
+ version = get_ushort ();
+ if (version > 3)
+ pdftex_fail ("unknown version of OS/2 table (%.4X)", version);
+ (void) put_ushort (0x0001); /* fix version to 1 */
+ ttf_ncopy (2 * TTF_USHORT_SIZE + 13 * TTF_SHORT_SIZE + 10 * TTF_BYTE_SIZE);
+ ttf_skip (4 * TTF_ULONG_SIZE); /* ulUnicodeRange 1--4 */
+ put_ulong (0x00000003); /* Basic Latin + Latin-1 Supplement (0x0000--0x00FF) */
+ put_ulong (0x10000000); /* Private Use (0xE000--0xF8FF) */
+ put_ulong (0x00000000);
+ put_ulong (0x00000000);
+ ttf_ncopy (4 * TTF_CHAR_SIZE + TTF_USHORT_SIZE); /* achVendID + fsSelection */
+ ttf_skip (2 * TTF_USHORT_SIZE);
+ (void) put_ushort (0x0000); /* usFirstCharIndex */
+ (void) put_ushort (0xF0FF); /* usLastCharIndex */
+ ttf_ncopy (5 * TTF_USHORT_SIZE);
+ /* for version 0 the OS/2 table ends here, the rest is for version 1 */
+ put_ulong (0x80000000); /* Symbol Character Set---don't use any code page */
+ put_ulong (0x00000000);
+ ttf_set_chksm (tab);
+}
+
+static boolean unsafe_name (char *s)
+{
+ const char **p;
+ for (p = ambiguous_names; *p != NULL; p++)
+ if (strcmp (s, *p) == 0)
+ return true;
+ return false;
+}
+
+static void ttf_write_post (void)
+{
+ dirtab_entry *tab = ttf_seek_tab ("post", TTF_FIXED_SIZE);
+ glyph_entry *glyph;
+ char *s;
+ long *id;
+ int l;
+ ttf_reset_chksm (tab);
+ if (!fd_cur->write_ttf_glyph_names || post_format == 0x00030000) {
+ put_fixed (0x00030000);
+ ttf_ncopy (TTF_FIXED_SIZE + 2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE);
+ } else {
+ put_fixed (0x00020000);
+ ttf_ncopy (TTF_FIXED_SIZE + 2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE);
+ (void) put_ushort (new_glyphs_count);
+ k = 0;
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
+ glyph = glyph_tab + *id;
+ if (glyph->name_index >= NMACGLYPHS || unsafe_name (glyph->name))
+ glyph->name_index = NMACGLYPHS + k++;
+ (void) put_ushort (glyph->name_index);
+ }
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
+ glyph = glyph_tab + *id;
+ if (glyph->name_index >= NMACGLYPHS) {
+ s = glyph->name;
+ l = strlen (s);
+ put_byte (l);
+ while (l-- > 0)
+ put_char (*s++);
+ }
+ }
+ }
+ ttf_set_chksm (tab);
+}
+
+static void ttf_init_font (int n)
+{
+ int i, k;
+ for (i = 1, k = 0; i <= n; i <<= 1, k++);
+ put_fixed (0x00010000); /* font version */
+ (void) put_ushort (n); /* number of tables */
+ (void) put_ushort (i << 3); /* search range */
+ (void) put_ushort (k - 1); /* entry selector */
+ (void) put_ushort ((n << 4) - (i << 3)); /* range shift */
+ ttf_seek_outbuf (TABDIR_OFF + n * 4 * TTF_ULONG_SIZE);
+}
+
+static void ttf_subset_font (void)
+{
+ ttf_init_font (new_ntabs);
+ if (ttf_name_lookup ("PCLT", false) != NULL)
+ ttf_copytab ("PCLT");
+ if (ttf_name_lookup ("fpgm", false) != NULL)
+ ttf_copytab ("fpgm");
+ if (ttf_name_lookup ("cvt ", false) != NULL)
+ ttf_copytab ("cvt ");
+ if (ttf_name_lookup ("prep", false) != NULL)
+ ttf_copytab ("prep");
+ ttf_reindex_glyphs ();
+ ttf_write_glyf ();
+ ttf_write_loca ();
+ ttf_write_OS2 ();
+ ttf_write_head ();
+ ttf_write_hhea ();
+ ttf_write_htmx ();
+ ttf_write_mapx ();
+ ttf_write_name ();
+ ttf_write_post ();
+ ttf_write_cmap ();
+ ttf_write_dirtab ();
+}
+
+static void ttf_copy_font (void)
+{
+ dirtab_entry *tab;
+ ttf_init_font (ntabs);
+ for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
+ if (strncmp (tab->tag, "head", 4) == 0)
+ ttf_write_head ();
+ else
+ ttf_copytab (tab->tag);
+ }
+ ttf_write_dirtab ();
+}
+
+void writettf(fd_entry * fd)
+{
+ int callback_id;
+ int file_opened = 0;
+ char *ftemp = NULL;
+ fd_cur = fd; /* fd_cur is global inside writettf.c */
+ assert(fd_cur->fm != NULL);
+ assert(is_truetype(fd_cur->fm));
+ assert(is_included(fd_cur->fm));
+
+ set_cur_file_name(fd_cur->fm->ff_name);
+
+ if (is_subsetted(fd_cur->fm) && (fd_cur->fe == NULL)
+ && !is_subfont(fd_cur->fm)) {
+ pdftex_warn ("Subset TrueType must be a reencoded or a subfont");
+ cur_file_name = NULL;
+ return;
+ }
+ ttf_curbyte=0;
+ ttf_size=0;
+ callback_id=callback_defined(find_truetype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ free(nameoffile);
+ namelength = strlen(ftemp);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),ftemp);
+ free(ftemp);
+ }
+ }
+ }
+
+ callback_id=callback_defined(read_truetype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1),
+ &file_opened, &ttf_buffer,&ttf_size) &&
+ file_opened && ttf_size>0) {
+ } else {
+ pdftex_fail ("cannot open TrueType font file for reading");
+ }
+ } else {
+ if (!ttf_open ()) {
+ pdftex_fail ("cannot open TrueType font file for reading");
+ }
+ ttf_read_file();
+ ttf_close();
+ }
+ cur_file_name = (char *) nameoffile + 1;
+ if (tracefilenames) {
+ if (is_subsetted(fd_cur->fm))
+ tex_printf ("<%s", cur_file_name);
+ else
+ tex_printf ("<<%s", cur_file_name);
+ }
+ fd_cur->ff_found = true;
+ new_glyphs_count = 2;
+ new_ntabs = DEFAULT_NTABS;
+ dir_tab = NULL;
+ glyph_tab = NULL;
+ glyph_index = NULL;
+ glyph_name_buf = NULL;
+ name_tab = NULL;
+ name_buf = NULL;
+ ttf_read_font ();
+
+ pdf_save_offset = pdfoffset ();
+ pdf_flush ();
+
+ if (is_subsetted(fd_cur->fm)) {
+ ttf_copy_encoding ();
+ ttf_subset_font ();
+ } else
+ ttf_copy_font ();
+ ttf_length = ttf_offset ();
+
+ xfree (dir_tab);
+ xfree (glyph_tab);
+ xfree (glyph_index);
+ xfree (glyph_name_buf);
+ xfree (name_tab);
+ xfree (name_buf);
+ if (tracefilenames) {
+ if (is_subsetted (fd_cur->fm))
+ tex_printf (">");
+ else
+ tex_printf (">>");
+ }
+ cur_file_name = NULL;
+}
+
+void do_writeotf(fd_entry * fd)
+{
+ long i;
+ dirtab_entry *tab;
+ dir_tab = NULL;
+ glyph_tab = NULL;
+ if (tracefilenames)
+ tex_printf ("<<%s", cur_file_name);
+ ttf_read_tabdir ();
+ /* read font parameters */
+ if (ttf_name_lookup ("head", false) != NULL)
+ ttf_read_head ();
+ if (ttf_name_lookup ("hhea", false) != NULL)
+ ttf_read_hhea ();
+ if (ttf_name_lookup ("PCLT", false) != NULL)
+ ttf_read_pclt ();
+ if (ttf_name_lookup ("post", false) != NULL)
+ ttf_read_post ();
+ /* copy font file */
+ tab = ttf_seek_tab ("CFF ", 0);
+ for (i = tab->length; i > 0; i--)
+ copy_char ();
+ xfree (dir_tab);
+ /* ttf_close ();*/
+ if (tracefilenames)
+ tex_printf (">>");
+}
+
+void writeotf (fd_entry * fd) {
+ int callback_id;
+ int file_opened = 0;
+ char *ftemp = NULL;
+
+
+ fd_cur = fd; /* fd_cur is global inside writettf.c */
+ assert(fd_cur->fm != NULL);
+ assert(is_opentype(fd_cur->fm));
+ assert(is_included(fd_cur->fm));
+
+ set_cur_file_name(fd_cur->fm->ff_name);
+ ttf_curbyte=0;
+ ttf_size=0;
+ callback_id=callback_defined(find_opentype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ free(nameoffile);
+ namelength = strlen(ftemp);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),ftemp);
+ free(ftemp);
+ }
+ }
+ }
+ callback_id=callback_defined(read_opentype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1),
+ &file_opened, &ttf_buffer,&ttf_size) &&
+ file_opened && ttf_size>0) {
+ } else {
+ pdftex_fail ("cannot open OpenType font file for reading");
+ }
+ } else {
+ if (!otf_open ()) {
+ pdftex_fail ("cannot open OpenType font file for reading");
+ }
+ ttf_read_file();
+ ttf_close();
+ }
+
+ cur_file_name = (char *) nameoffile + 1;
+ fd_cur->ff_found = true;
+ do_writeotf(fd);
+ cur_file_name = NULL;
+}
+
+/*
+ To calculate the checkSum for the 'head' table which itself includes the
+ checkSumAdjustment entry for the entire font, do the following:
+
+ * Set the checkSumAdjustment to 0.
+ * Calculate the checksum for all the tables including the 'head' table
+ and enter that value into the table directory.
+ * Calculate the checksum for the entire font.
+ * Subtract that value from the hex value B1B0AFBA.
+ * Store the result in checkSumAdjustment.
+
+ The checkSum for the 'head table which includes the checkSumAdjustment
+ entry for the entire font is now incorrect. That is not a problem. Do not
+ change it. An application attempting to verify that the 'head' table has
+ not changed should calculate the checkSum for that table by not including
+ the checkSumAdjustment value, and compare the result with the entry in the
+ table directory.
+
+ The table directory also includes the offset of the associated tagged
+ table from the beginning of the font file and the length of that table.
+ */
diff --git a/Build/source/texk/web2c/luatexdir/font/writettf.h b/Build/source/texk/web2c/luatexdir/font/writettf.h
new file mode 100644
index 00000000000..ecfaa2c37e3
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writettf.h
@@ -0,0 +1,172 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writettf.h 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+typedef signed char TTF_CHAR;
+typedef unsigned char TTF_BYTE;
+typedef signed short TTF_SHORT;
+typedef unsigned short TTF_USHORT;
+typedef signed long TTF_LONG;
+typedef unsigned long TTF_ULONG;
+typedef unsigned long TTF_FIXED;
+typedef unsigned short TTF_FUNIT;
+typedef signed short TTF_FWORD;
+typedef unsigned short TTF_UFWORD;
+typedef unsigned short TTF_F2DOT14;
+
+#define TTF_CHAR_SIZE 1
+#define TTF_BYTE_SIZE 1
+#define TTF_SHORT_SIZE 2
+#define TTF_USHORT_SIZE 2
+#define TTF_LONG_SIZE 4
+#define TTF_ULONG_SIZE 4
+#define TTF_FIXED_SIZE 4
+#define TTF_FWORD_SIZE 2
+#define TTF_UFWORD_SIZE 2
+#define TTF_F2DOT14_SIZE 2
+
+#define ARG_1_AND_2_ARE_WORDS (1<<0)
+#define ARGS_ARE_XY_VALUES (1<<1)
+#define ROUND_XY_TO_GRID (1<<2)
+#define WE_HAVE_A_SCALE (1<<3)
+#define RESERVED (1<<4)
+#define MORE_COMPONENTS (1<<5)
+#define WE_HAVE_AN_X_AND_Y_SCALE (1<<6)
+#define WE_HAVE_A_TWO_BY_TWO (1<<7)
+#define WE_HAVE_INSTRUCTIONS (1<<8)
+#define USE_MY_METRICS (1<<9)
+
+#define get_type(t) ((t)ttf_getnum(t##_SIZE))
+#define ttf_skip(n) ttf_getnum(n)
+
+#define get_byte() get_type(TTF_BYTE)
+#define get_char() get_type(TTF_CHAR)
+#define get_ushort() get_type(TTF_USHORT)
+#define get_short() get_type(TTF_SHORT)
+#define get_ulong() get_type(TTF_ULONG)
+#define get_long() get_type(TTF_LONG)
+#define get_fixed() get_type(TTF_FIXED)
+#define get_funit() get_type(TTF_FUNIT)
+#define get_fword() get_type(TTF_FWORD)
+#define get_ufword() get_type(TTF_UFWORD)
+#define get_f2dot14() get_type(TTF_F2DOT14)
+
+#define put_num(t,n) ((t)ttf_putnum(t##_SIZE, n))
+
+#define put_char(n) (void)put_num(TTF_CHAR, n)
+#define put_byte(n) (void)put_num(TTF_BYTE, n)
+#define put_short(n) put_num(TTF_SHORT, n)
+#define put_ushort(n) put_num(TTF_USHORT, n)
+#define put_long(n) put_num(TTF_LONG, n)
+#define put_ulong(n) (void)put_num(TTF_ULONG, n)
+#define put_fixed(n) (void)put_num(TTF_FIXED, n)
+#define put_funit(n) put_num(TTF_FUNIT, n)
+#define put_fword(n) put_num(TTF_FWORD, n)
+#define put_ufword(n) (void)put_num(TTF_UFWORD, n)
+#define put_f2dot14(n) put_num(TTF_F2DOT14, n)
+
+#define copy_byte() put_byte(get_byte())
+#define copy_char() put_char(get_char())
+#define copy_ushort() put_ushort(get_ushort())
+#define copy_short() put_short(get_short())
+#define copy_ulong() put_ulong(get_ulong())
+#define copy_long() put_long(get_long())
+#define copy_fixed() put_fixed(get_fixed())
+#define copy_funit() put_funit(get_funit())
+#define copy_fword() put_fword(get_fword())
+#define copy_ufword() put_ufword(get_ufword())
+#define copy_f2dot14() put_f2dot14(get_f2dot14())
+
+#define is_unicode_mapping(e) \
+ (e->platform_id == 0 || (e->platform_id == 3 || e->encoding_id == 1))
+
+
+#define NMACGLYPHS 258
+#define TABDIR_OFF 12
+#define ENC_BUF_SIZE 1024
+
+#define GLYPH_PREFIX_INDEX "index"
+#define GLYPH_PREFIX_UNICODE "uni"
+
+typedef struct {
+ char tag[4];
+ TTF_ULONG checksum;
+ TTF_ULONG offset;
+ TTF_ULONG length;
+} dirtab_entry;
+
+typedef struct {
+ TTF_USHORT platform_id;
+ TTF_USHORT encoding_id;
+ TTF_ULONG offset;
+ TTF_USHORT format;
+} cmap_entry;
+
+typedef struct {
+ TTF_USHORT endCode;
+ TTF_USHORT startCode;
+ TTF_USHORT idDelta;
+ TTF_USHORT idRangeOffset;
+} seg_entry;
+
+typedef struct {
+ TTF_LONG offset;
+ TTF_LONG newoffset;
+ TTF_UFWORD advWidth;
+ TTF_FWORD lsb;
+ char *name; /* name of glyph */
+ TTF_SHORT newindex; /* new index of glyph in output file */
+ TTF_USHORT name_index; /* index of name as read from font file */
+} glyph_entry;
+
+/* some functions and variables are used by writetype0.c */
+
+extern fd_entry *fd_cur; /* pointer to the current font descriptor */
+extern unsigned char *ttf_buffer;
+extern integer ttf_size;
+extern integer ttf_curbyte;
+extern glyph_entry *glyph_tab;
+extern dirtab_entry *dir_tab;
+extern dirtab_entry *ttf_name_lookup (const char *s, boolean required);
+extern dirtab_entry *ttf_seek_tab (const char *name, TTF_LONG offset);
+
+extern void ttf_read_tabdir (void);
+extern void ttf_read_head (void);
+extern void ttf_read_hhea (void);
+extern void ttf_read_pclt (void);
+extern void ttf_read_post (void);
+
+extern FILE *ttf_file;
+
+#define ttf_open() \
+ open_input(&ttf_file, kpse_truetype_format, FOPEN_RBIN_MODE)
+#define otf_open() \
+ open_input(&ttf_file, kpse_opentype_format, FOPEN_RBIN_MODE)
+#define ttf_read_file() \
+ readbinfile(ttf_file,&ttf_buffer,&ttf_size)
+#define ttf_close() xfclose(ttf_file,cur_file_name)
+#define ttf_getchar() ttf_buffer[ttf_curbyte++]
+#define ttf_eof() (ttf_curbyte>ttf_size)
+
+extern long ttf_putnum (int s, long n);
+extern long ttf_getnum (int s);
+
+
diff --git a/Build/source/texk/web2c/luatexdir/font/writetype0.c b/Build/source/texk/web2c/luatexdir/font/writetype0.c
new file mode 100644
index 00000000000..0f9eecaac7c
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writetype0.c
@@ -0,0 +1,124 @@
+/*
+Copyright (c) 2007 Taco Hoekwater, taco@luatex.org
+
+This file is part of luaTeX.
+
+luaTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+luaTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with luaTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writetype0.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+
+#include "writettf.h"
+
+#include "writecff.h"
+
+void writetype0 (fd_entry * fd) {
+ int callback_id;
+ int file_opened = 0;
+ char *ftemp = NULL;
+ long i;
+ dirtab_entry *tab;
+ cff_font *cff;
+
+ dir_tab = NULL;
+ glyph_tab = NULL;
+
+ fd_cur = fd; /* fd_cur is global inside writettf.c */
+ assert(fd_cur->fm != NULL);
+ assert(is_opentype(fd_cur->fm));
+ assert(is_included(fd_cur->fm));
+
+ set_cur_file_name(fd_cur->fm->ff_name);
+ ttf_curbyte=0;
+ ttf_size=0;
+ callback_id=callback_defined(find_opentype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ free(nameoffile);
+ namelength = strlen(ftemp);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),ftemp);
+ free(ftemp);
+ }
+ }
+ }
+ callback_id=callback_defined(read_opentype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1),
+ &file_opened, &ttf_buffer,&ttf_size) &&
+ file_opened && ttf_size>0) {
+ } else {
+ pdftex_fail ("cannot open OpenType font file for reading");
+ }
+ } else {
+ if (!otf_open ()) {
+ pdftex_fail ("cannot open OpenType font file for reading");
+ }
+ ttf_read_file();
+ ttf_close();
+ }
+
+ cur_file_name = (char *) nameoffile + 1;
+ fd_cur->ff_found = true;
+
+ if (tracefilenames) {
+ if (is_subsetted(fd_cur->fm))
+ tex_printf ("<%s", cur_file_name);
+ else
+ tex_printf ("<<%s", cur_file_name);
+ }
+ ttf_read_tabdir ();
+ /* read font parameters */
+ if (ttf_name_lookup ("head", false) != NULL)
+ ttf_read_head ();
+ if (ttf_name_lookup ("hhea", false) != NULL)
+ ttf_read_hhea ();
+ if (ttf_name_lookup ("PCLT", false) != NULL)
+ ttf_read_pclt ();
+ if (ttf_name_lookup ("post", false) != NULL)
+ ttf_read_post ();
+
+ /* copy font file */
+ tab = ttf_seek_tab ("CFF ", 0);
+
+ /* TODO the next 0 is a subfont index */
+ cff = read_cff(ttf_buffer+ttf_curbyte,tab->length,0);
+ if (cff != NULL) {
+ if (cff_is_cidfont(cff)) {
+ write_cid_cff(cff,fd_cur,0);
+ /*
+ for (i = tab->length; i > 0; i--)
+ fb_putchar (ttf_getnum(1));
+ */
+ } else {
+ write_cff(cff,fd_cur,0);
+ }
+ } else {
+ /* not understood, just do a copy */
+ for (i = tab->length; i > 0; i--)
+ fb_putchar (ttf_getnum(1));
+ }
+ xfree (dir_tab);
+ if (tracefilenames) {
+ if (is_subsetted (fd_cur->fm))
+ tex_printf (">");
+ else
+ tex_printf (">>");
+ }
+ cur_file_name = NULL;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/writetype2.c b/Build/source/texk/web2c/luatexdir/font/writetype2.c
new file mode 100644
index 00000000000..649c350b707
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writetype2.c
@@ -0,0 +1,422 @@
+
+/*
+Copyright (c) 2007 Taco Hoekwater, taco@luatex.org
+
+This file is part of luaTeX.
+
+luaTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+luaTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with luaTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writetype2.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+#include "writettf.h"
+#include "writecff.h"
+
+#include "sfnt.h"
+#include "tt_glyf.h"
+
+/* forward*/
+void make_tt_subset (fd_entry * fd,unsigned char *buffer, integer buflen) ;
+
+unsigned long cidtogid_obj = 0;
+
+/* low-level helpers */
+
+#define test_loc(l) \
+ if ((f->loc+l)>f->buflen) { \
+ fprintf (stderr,"File ended prematurely\n"); \
+ uexit(1); \
+ }
+
+
+BYTE get_unsigned_byte(sfnt* f) {
+ test_loc(1);
+ return (BYTE)f->buffer[(f->loc++)];
+};
+
+ICHAR get_signed_byte(sfnt* f) {
+ test_loc(1);
+ return (ICHAR)f->buffer[(f->loc++)];
+};
+
+USHORT get_unsigned_pair(sfnt* f){
+ USHORT l;
+ test_loc(2);
+ l = f->buffer[(f->loc++)];
+ l = l*0x100 + f->buffer[(f->loc++)];
+ return l;
+};
+
+SHORT get_signed_pair(sfnt* f){
+ long l;
+ test_loc(2);
+ l = f->buffer[(f->loc++)];
+ if (l>0x80) l -= 0x100;
+ l = l*0x100 + f->buffer[(f->loc++)];
+ return l;
+};
+
+ULONG get_unsigned_quad(sfnt* f){
+ ULONG l;
+ test_loc(4);
+ l = f->buffer[(f->loc++)];
+ l = l*0x100 + f->buffer[(f->loc++)];
+ l = l*0x100 + f->buffer[(f->loc++)];
+ l = l*0x100 + f->buffer[(f->loc++)];
+ return l;
+};
+
+int do_sfnt_read (unsigned char *dest, int len, sfnt *f) {
+ int i;
+ test_loc(len);
+ for (i=0;i<len;i++) {
+ *(dest+i)=f->buffer[f->loc+i];
+ }
+ f->loc += len;
+ return len;
+};
+
+pdf_obj *pdf_new_stream(void) {
+ pdf_obj *stream = xmalloc(sizeof(pdf_obj)) ;
+ stream->length =0;
+ stream->data=NULL;
+ return stream;
+};
+
+void pdf_add_stream(pdf_obj *stream, unsigned char *buf, long len) {
+ int i;
+ assert (stream!=NULL);
+ if (stream->data==NULL) {
+ stream->data = xmalloc(len);
+ } else {
+ stream->data = xrealloc(stream->data,len+stream->length);
+ }
+ for (i=0;i<len;i++) {
+ *(stream->data+stream->length+i)=*(buf+i);
+ }
+ stream->length+=len;
+};
+
+void pdf_release_obj(pdf_obj *stream) {
+ if (stream!=NULL) {
+ if (stream->data!=NULL) {
+ xfree(stream->data);
+ }
+ xfree(stream);
+ }
+};
+
+
+void
+writetype2 (fd_entry * fd) {
+ int callback_id;
+ int file_opened = 0;
+ char *ftemp = NULL;
+
+ glyph_tab = NULL;
+
+ fd_cur = fd; /* fd_cur is global inside writettf.c */
+ assert(fd_cur->fm != NULL);
+ assert(is_truetype(fd_cur->fm));
+
+ if (!is_subsetted(fd_cur->fm)) {
+ writettf(fd);
+ return;
+ }
+
+ assert(is_included(fd_cur->fm));
+
+ set_cur_file_name(fd_cur->fm->ff_name);
+ ttf_curbyte=0;
+ ttf_size=0;
+ callback_id=callback_defined(find_opentype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ free(nameoffile);
+ namelength = strlen(ftemp);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),ftemp);
+ free(ftemp);
+ }
+ }
+ }
+ callback_id=callback_defined(read_opentype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1),
+ &file_opened, &ttf_buffer,&ttf_size) &&
+ file_opened && ttf_size>0) {
+ } else {
+ pdftex_fail ("cannot open OpenType font file for reading");
+ }
+ } else {
+ if (!otf_open ()) {
+ pdftex_fail ("cannot open OpenType font file for reading");
+ }
+ ttf_read_file();
+ ttf_close();
+ }
+
+ cur_file_name = (char *) nameoffile + 1;
+ fd_cur->ff_found = true;
+
+ if (tracefilenames) {
+ if (is_subsetted(fd_cur->fm))
+ tex_printf ("<%s", cur_file_name);
+ else
+ tex_printf ("<<%s", cur_file_name);
+ }
+
+ /* here is the real work */
+
+ make_tt_subset(fd,ttf_buffer,ttf_size);
+
+ /*xfree (dir_tab);*/
+ if (tracefilenames) {
+ if (is_subsetted (fd_cur->fm))
+ tex_printf (">");
+ else
+ tex_printf (">>");
+ }
+ cur_file_name = NULL;
+}
+
+/*
+ * PDF viewer applications use following tables (CIDFontType 2)
+ *
+ * head, hhea, loca, maxp, glyf, hmtx, fpgm, cvt_, prep
+ *
+ * - from PDF Ref. v.1.3, 2nd ed.
+ *
+ * The fpgm, cvt_, and prep tables appears only when TrueType instructions
+ * requires them. Those tables must be preserved if they exist.
+ * We use must_exist flag to indicate `preserve it if present'
+ * and to make sure not to cause an error when it does not exist.
+ *
+ * post and name table must exist in ordinary TrueType font file,
+ * but when a TrueType font is converted to CIDFontType 2 font, those tables
+ * are no longer required.
+ *
+ * The OS/2 table (required for TrueType font for Windows and OS/2) contains
+ * liscencing information, but PDF viewers seems not using them.
+ *
+ * The 'name' table added. See comments in ttf.c.
+ */
+
+static struct
+{
+ const char *name;
+ int must_exist;
+} required_table[] = {
+ {"OS/2", 0}, {"head", 1}, {"hhea", 1}, {"loca", 1}, {"maxp", 1},
+ {"name", 1}, {"glyf", 1}, {"hmtx", 1}, {"fpgm", 0}, {"cvt ", 0},
+ {"prep", 0}, {NULL, 0}
+};
+
+
+unsigned long ttc_read_offset (sfnt *sfont, int ttc_idx)
+{
+ long version;
+ unsigned long offset = 0;
+ unsigned long num_dirs = 0;
+
+ sfnt_seek_set (sfont, 4); /* skip version tag */
+
+ version = sfnt_get_ulong(sfont);
+ num_dirs = sfnt_get_ulong(sfont);
+ if (ttc_idx < 0 || ttc_idx > num_dirs - 1) {
+ fprintf(stderr,"Invalid TTC index number\n");
+ uexit(1);
+ }
+
+ sfnt_seek_set (sfont, 12 + ttc_idx * 4);
+ offset = sfnt_get_ulong (sfont);
+
+ return offset;
+}
+
+extern int ff_get_ttc_index(char *ffname, char*psname);
+
+void make_tt_subset (fd_entry * fd,unsigned char *buffer, integer buflen) {
+
+ long i, cid;
+ unsigned int last_cid;
+ glw_entry *glyph, *found;
+ struct avl_traverser t;
+ unsigned char *cidtogidmap ;
+ unsigned short num_glyphs, gid;
+ struct tt_glyphs *glyphs;
+ char *used_chars;
+ sfnt *sfont;
+ pdf_obj *fontfile;
+ int verbose = 0, error = 0;
+
+ cidtogidmap = NULL;
+
+ sfont = sfnt_open(buffer, buflen);
+
+ if (sfont->type == SFNT_TYPE_TTC) {
+ i = ff_get_ttc_index(fd->fm->ff_name,fd->fm->ps_name);
+ error = sfnt_read_table_directory(sfont, ttc_read_offset(sfont, i));
+ } else {
+ error = sfnt_read_table_directory(sfont, 0);
+ }
+
+ if (error < 0) {
+ fprintf(stderr,"Could not parse the ttf directory.\n");
+ uexit(1);
+ }
+
+ glyphs = tt_build_init();
+
+ last_cid = 0;
+ num_glyphs = 1; /* .notdef */
+
+ glyph = xtalloc(1,glw_entry);
+
+ avl_t_init(&t, fd->gl_tree);
+ for (found = (glw_entry *) avl_t_first(&t, fd->gl_tree);
+ found != NULL;
+ found = (glw_entry *) avl_t_next(&t)) {
+ if (found->id > last_cid)
+ last_cid = found->id;
+ }
+
+#ifndef NO_GHOSTSCRIPT_BUG
+ cidtogidmap = NULL;
+#else
+ cidtogidmap = xmalloc(((last_cid + 1) * 2) * sizeof(unsigned char));
+ memset(cidtogidmap, 0, (last_cid + 1) * 2);
+#endif
+
+ /* fill used_chars */
+ used_chars = xmalloc((last_cid + 1) * sizeof(char));
+ memset(used_chars, 0, (last_cid + 1));
+ avl_t_init(&t, fd->gl_tree);
+ for (found = (glw_entry *) avl_t_first(&t, fd->gl_tree);
+ found != NULL;
+ found = (glw_entry *) avl_t_next(&t)) {
+ used_chars[found->id] = 1;
+ }
+
+ /*
+ * Map CIDs to GIDs.
+ */
+
+ num_glyphs = 1; /* .notdef */
+ for (cid = 1; cid <= last_cid; cid++) {
+ if (used_chars[cid]==0)
+ continue;
+ gid = cid;
+
+
+#ifndef NO_GHOSTSCRIPT_BUG
+ gid = tt_add_glyph(glyphs, gid, cid);
+#else
+ gid = tt_add_glyph(glyphs, gid, num_glyphs);
+ cidtogidmap[2*cid ] = gid >> 8;
+ cidtogidmap[2*cid+1] = gid & 0xff;
+#endif /* !NO_GHOSTSCRIPT_BUG */
+
+ num_glyphs++;
+ }
+
+ if (num_glyphs==1) {
+ fprintf(stderr,"No glyphs in subset?.\n");
+ uexit(1);
+ }
+
+ if (tt_build_tables(sfont, glyphs) < 0) {
+ fprintf(stderr,"Could not parse the ttf buffer.\n");
+ uexit(1);
+ }
+
+ if (verbose > 1) {
+ fprintf(stdout,"[%u glyphs (Max CID: %u)]", glyphs->num_glyphs, last_cid);
+ }
+
+ tt_build_finish(glyphs);
+
+ /* Create font file */
+
+ for (i = 0; required_table[i].name; i++) {
+ if (sfnt_require_table(sfont,
+ required_table[i].name,
+ required_table[i].must_exist) < 0) {
+ fprintf(stderr,"Some required TrueType table does not exist.");
+ uexit(1);
+ }
+ }
+
+ fontfile = sfnt_create_FontFile_stream(sfont);
+
+ if (verbose > 1) {
+ fprintf(stdout,"[%ld bytes]", fontfile->length);
+ }
+
+ /* squeeze in the cidgidmap */
+ if (cidtogidmap!=NULL) {
+ cidtogid_obj = pdf_new_objnum();
+ pdf_begin_dict(cidtogid_obj, 0);
+ pdf_printf("/Length %i\n",((last_cid + 1) * 2));
+ pdf_end_dict();
+ pdf_printf("stream\n");
+ pdfroom ((last_cid + 1) * 2);
+ for (i = 0; i<((last_cid + 1) * 2); i++ ) {
+ pdf_buf[pdf_ptr++] = cidtogidmap[i];
+ }
+ pdf_printf("\nendstream\n");
+ }
+
+ /* the tff subset */
+ for (i = 0; i<fontfile->length; i++ )
+ fb_putchar (fontfile->data[i]);
+
+
+ /* other stuff that needs fixing: */
+
+ /*
+ * DW, W, DW2, and W2
+ */
+ /*
+ if (opt_flags & CIDFONT_FORCE_FIXEDPITCH) {
+ pdf_add_dict(font->fontdict,
+ pdf_new_name("DW"), pdf_new_number(1000.0));
+ } else {
+ add_TTCIDHMetrics(font->fontdict, glyphs, used_chars, cidtogidmap, last_cid);
+ if (v_used_chars)
+ add_TTCIDVMetrics(font->fontdict, glyphs, used_chars, cidtogidmap, last_cid);
+ }
+ */
+
+ /*
+ * CIDSet
+ */
+ /*
+ {
+ pdf_obj *cidset;
+
+ cidset = pdf_new_stream(STREAM_COMPRESS);
+ pdf_add_stream(cidset, used_chars, last_cid/8 + 1);
+ pdf_add_dict(font->descriptor,
+ pdf_new_name("CIDSet"),
+ pdf_ref_obj(cidset));
+ pdf_release_obj(cidset);
+ }
+ */
+
+ return;
+}
diff --git a/Build/source/texk/web2c/luatexdir/hyphen.h b/Build/source/texk/web2c/luatexdir/hyphen.h
new file mode 100644
index 00000000000..f665c7605b9
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/hyphen.h
@@ -0,0 +1,60 @@
+/* LibHnj is dual licensed under LGPL and MPL. Boilerplate for both
+ * licenses follows.
+ */
+
+/* LibHnj - a library for high quality hyphenation and justification
+ * Copyright (C) 1998 Raph Levien, (C) 2001 ALTLinux, Moscow
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307 USA.
+*/
+
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ *
+ */
+#ifndef __HYPHEN_H__
+#define __HYPHEN_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _HyphenDict HyphenDict;
+
+#include "ptexlib.h"
+#include "nodes.h"
+
+HyphenDict* hnj_hyphen_new();
+void hnj_hyphen_load(HyphenDict*dict, const unsigned char *fn);
+void hnj_hyphen_free (HyphenDict *dict);
+void hnj_hyphen_clear (HyphenDict *dict);
+void hnj_hyphen_hyphenate (HyphenDict *dict, halfword first, halfword last, int size, halfword left, halfword right, lang_variables*lan);
+unsigned char* hnj_serialize(HyphenDict*);
+void hnj_free_serialize(unsigned char*);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __HYPHEN_H__ */
diff --git a/Build/source/texk/web2c/luatexdir/image/.indent.pro b/Build/source/texk/web2c/luatexdir/image/.indent.pro
new file mode 100644
index 00000000000..e9e690f1ba8
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/.indent.pro
@@ -0,0 +1,12 @@
+/* $Id$ */
+--k-and-r-style
+--blank-lines-after-procedures
+--line-length 80
+--procnames-start-lines
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--space-after-cast
+/* this does not work in indent 2.2.6 :-( */
+--no-tabs
+/* this is new in indent 2.2.9 */
+--preprocessor-indentation 2
diff --git a/Build/source/texk/web2c/luatexdir/image/epdf.c b/Build/source/texk/web2c/luatexdir/image/epdf.c
new file mode 100644
index 00000000000..071181f17bd
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/epdf.c
@@ -0,0 +1,107 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: epdf.c 1012 2008-02-14 00:00:57Z oneiros $
+*/
+
+#include "ptexlib.h"
+
+
+#include <kpathsea/c-vararg.h>
+#include <kpathsea/c-proto.h>
+#include <string.h>
+
+extern void epdf_check_mem(void);
+extern void register_fd_entry(fd_entry *);
+
+
+int is_subsetable(fm_entry * fm)
+{
+ assert(is_included(fm));
+ return is_subsetted(fm);
+}
+
+fd_entry *epdf_create_fontdescriptor(fm_entry * fm)
+{
+ fd_entry *fd;
+ if ((fd = lookup_fd_entry(fm->ff_name, fm->slant, fm->extend)) == NULL) {
+ fm->in_use = true;
+ fd = new_fd_entry();
+ fd->fm = fm;
+ register_fd_entry(fd);
+ fd->fd_objnum = pdf_new_objnum();
+ assert(fm->ps_name != NULL);
+ fd->fontname = xstrdup(fm->ps_name); /* just fallback */
+ /* preset_fontmetrics (fo->fd, f); */
+ fd->gl_tree = avl_create(comp_string_entry, NULL, &avl_xallocator);
+ assert(fd->gl_tree != NULL);
+ }
+ return fd;
+}
+
+integer get_fd_objnum(fd_entry * fd)
+{
+ assert(fd->fd_objnum != 0);
+ return fd->fd_objnum;
+}
+
+integer get_fn_objnum(fd_entry * fd)
+{
+ if (fd->fn_objnum == 0)
+ fd->fn_objnum = pdf_new_objnum();
+ return fd->fn_objnum;
+}
+
+/***********************************************************************
+ * Mark glyphs used by embedded PDF file:
+ * 1. build fontdescriptor, if not yet existing
+ * 2. mark glyphs directly there
+ *
+ * Input charset from xpdf is a string of glyph names including
+ * leading slashes, but without blanks between them, like: /a/b/c
+***********************************************************************/
+
+void epdf_mark_glyphs(fd_entry * fd, char *charset)
+{
+ char *p, *q, *s;
+ char *glyph;
+ void **aa;
+ if (charset == NULL)
+ return;
+ assert(fd != NULL);
+ for (s = charset + 1, q = charset + strlen(charset); s < q; s = p + 1) {
+ for (p = s; *p != '\0' && *p != '/'; p++);
+ *p = '\0';
+ if ((char *) avl_find(fd->gl_tree, s) == NULL) {
+ glyph = xstrdup(s);
+ aa = avl_probe(fd->gl_tree, glyph);
+ assert(aa != NULL);
+ }
+ }
+}
+
+void embed_whole_font(fd_entry * fd)
+{
+ fd->all_glyphs = true;
+}
+
+void epdf_free(void)
+{
+ epdf_check_mem();
+}
diff --git a/Build/source/texk/web2c/luatexdir/image/epdf.h b/Build/source/texk/web2c/luatexdir/image/epdf.h
new file mode 100644
index 00000000000..2359d53d3db
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/epdf.h
@@ -0,0 +1,125 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: epdf.h 1031 2008-02-14 23:03:20Z hhenkel $
+*/
+
+extern "C" {
+
+#include <kpathsea/c-auto.h>
+
+ extern char *xstrdup(const char *);
+
+/* the following code is extremly ugly but needed for including web2c/config.h */
+
+#include <kpathsea/c-proto.h> /* define P?H macros */
+
+ typedef const char *const_string; /* including kpathsea/types.h doesn't work on some systems */
+
+#define KPATHSEA_CONFIG_H /* avoid including other kpathsea header files */
+ /* from web2c/config.h */
+
+#ifdef CONFIG_H /* CONFIG_H has been defined by some xpdf */
+# undef CONFIG_H /* header file */
+#endif
+
+#include <web2c/c-auto.h> /* define SIZEOF_LONG */
+#include <web2c/config.h> /* define type integer */
+
+#include <web2c/luatexdir/ptexmac.h>
+#include "openbsd-compat.h"
+#include "image.h"
+
+/* #-define pdfbufsize pdfbufmax */
+
+ extern integer epdf_page_box;
+ extern void *epdf_xref;
+
+ extern integer pdf_box_spec_media;
+ extern integer pdf_box_spec_crop;
+ extern integer pdf_box_spec_bleed;
+ extern integer pdf_box_spec_trim;
+ extern integer pdf_box_spec_art;
+
+ extern integer pdf_stream_length;
+ extern integer pdf_ptr;
+ extern integer pool_ptr;
+ typedef unsigned char eight_bits;
+ extern eight_bits *pdf_buf;
+ extern integer pdf_buf_size;
+ extern integer pdf_os_mode;
+ extern eight_bits pdf_last_byte;
+
+ extern char notdef[];
+
+ extern integer fixed_replace_font;
+
+ extern int is_subsetable(struct fm_entry *);
+ extern struct fm_entry *lookup_fontmap(char *);
+ extern integer get_fontfile(struct fm_entry *);
+ extern integer get_fontname(struct fm_entry *);
+ extern integer pdf_new_objnum(void);
+ extern void read_pdf_info(image_dict *, integer, integer);
+ extern void embed_whole_font(struct fd_entry *);
+ extern void epdf_check_mem(void);
+ extern void epdf_delete(image_dict *);
+ extern void epdf_free(void);
+ __attribute__ ((format(printf, 1, 2)))
+ extern void pdf_printf(const char *fmt, ...);
+ extern void pdf_puts(const char *);
+ extern void pdf_begin_stream(void);
+ extern void pdf_end_obj(void);
+ extern void pdf_end_stream(void);
+ extern void pdf_flush(void);
+ __attribute__ ((noreturn, format(printf, 1, 2)))
+ extern void pdftex_fail(const char *fmt, ...);
+ __attribute__ ((format(printf, 1, 2)))
+ extern void pdftex_warn(const char *fmt, ...);
+ __attribute__ ((format(printf, 1, 2)))
+ extern void tex_printf(const char *, ...);
+ extern void write_epdf(image_dict *);
+ extern void zpdf_begin_dict(integer, bool);
+ extern void zpdf_begin_obj(integer, bool);
+ extern void zpdf_create_obj(integer, integer);
+ extern void zpdf_new_dict(integer, integer, bool);
+ extern void zpdf_os_get_os_buf(integer);
+
+/* epdf.c */
+ extern void epdf_mark_glyphs(struct fd_entry *, char *);
+ extern struct fd_entry *epdf_create_fontdescriptor(struct fm_entry *);
+ extern int get_fd_objnum(struct fd_entry *);
+ extern int get_fn_objnum(struct fd_entry *);
+
+/* write_enc.c */
+ extern void epdf_write_enc(char **, integer);
+
+/* write_enc.c */
+ extern pdf_img_struct *new_pdf_img_struct(void);
+
+/* utils.c */
+ extern char *convertStringToPDFString(char *in, int len);
+ extern char *stripzeros(char *a);
+
+/* config.c */
+ extern integer cfgpar(integer);
+
+/* avlstuff.c */
+ extern void avl_put_obj(integer, integer);
+ extern integer avl_find_obj(integer, integer, integer);
+}
diff --git a/Build/source/texk/web2c/luatexdir/image/image.h b/Build/source/texk/web2c/luatexdir/image/image.h
new file mode 100644
index 00000000000..cf7d4f0dd88
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/image.h
@@ -0,0 +1,223 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: image.h 1100 2008-03-09 13:40:48Z hhenkel $
+*/
+
+#ifndef IMAGE_H
+# define IMAGE_H
+
+# include <../libpng/png.h>
+
+# define JPG_UINT16 unsigned int
+# define JPG_UINT32 unsigned long
+# define JPG_UINT8 unsigned char
+
+# define IMAGE_COLOR_B 1
+# define IMAGE_COLOR_C 2
+# define IMAGE_COLOR_I 4
+
+extern integer zround(double); /* from zround.c */
+# define bp2int(p) zround(p * (one_hundred_bp / 100.0))
+
+# define TYPE_IMG "image"
+# define TYPE_IMG_DICT "image-dict"
+
+# define scaled integer
+
+/**********************************************************************/
+
+typedef struct {
+ float width;
+ float height;
+ float orig_x;
+ float orig_y;
+ void *doc;
+} pdf_img_struct;
+
+typedef struct {
+ png_structp png_ptr;
+ png_infop info_ptr;
+} png_img_struct;
+
+typedef struct {
+ int color_space; /* used color space. See JPG_ constants */
+ JPG_UINT32 length; /* length of file/data */
+} jpg_img_struct;
+
+typedef struct { /* currently unused */
+} jb2_img_struct;
+
+typedef enum { DICT_NEW, /* fresh dictionary */
+ DICT_FILESCANNED, /* image file scanned */
+ DICT_REFERED, /* pdf_refximage_node in node list --> read-only dict */
+ DICT_OUTIMG, /* /Im* appears in pagestream */
+ DICT_SCHEDULED, /* image dict scheduled for writing */
+ DICT_WRITTEN /* image dict written to file */
+} dict_state;
+
+typedef enum { IMAGE_TYPE_NONE, IMAGE_TYPE_PDF, IMAGE_TYPE_PNG, IMAGE_TYPE_JPG,
+ IMAGE_TYPE_JBIG2, IMAGE_TYPE_SENTINEL
+} imgtype_e;
+
+typedef enum { IMG_KEEPOPEN, IMG_CLOSEINBETWEEN } img_readtype_e;
+
+typedef enum { PDF_BOX_SPEC_NONE, PDF_BOX_SPEC_MEDIA, PDF_BOX_SPEC_CROP,
+ PDF_BOX_SPEC_BLEED, PDF_BOX_SPEC_TRIM, PDF_BOX_SPEC_ART,
+ PDF_BOX_SPEC_SENTINEL
+} pdfboxspec_e;
+
+/**********************************************************************/
+
+typedef struct {
+ integer objnum;
+ integer index; /* /Im1, /Im2, ... */
+ integer x_size; /* dimensions in pixel counts as in JPG/PNG/JBIG2 file */
+ integer y_size;
+ integer x_res; /* pixel resolution as in JPG/PNG/JBIG2 file */
+ integer y_res;
+ integer colorspace; /* number of /ColorSpace object */
+ integer total_pages;
+ integer page_num; /* requested page (by number) */
+ char *pagename; /* requested page (by name) */
+ char *filename; /* requested raw file name */
+ char *filepath; /* full file path after kpathsea */
+ char *attr; /* additional image dict entries */
+ FILE *file;
+ imgtype_e image_type;
+ int color_space; /* used color space. See JPG_ constants */
+ int color_depth; /* color depth */
+ pdfboxspec_e page_box_spec; /* PDF page box spec.: media/crop/bleed/trim/art */
+ dict_state state;
+ union {
+ pdf_img_struct *pdf;
+ png_img_struct *png;
+ jpg_img_struct *jpg;
+ jb2_img_struct *jb2;
+ } img_struct;
+} image_dict;
+
+# define img_objnum(N) ((N)->objnum)
+# define img_index(N) ((N)->index)
+# define img_xsize(N) ((N)->x_size)
+# define img_ysize(N) ((N)->y_size)
+# define img_xres(N) ((N)->x_res)
+# define img_yres(N) ((N)->y_res)
+# define img_colorspace(N) ((N)->colorspace)
+# define img_totalpages(N) ((N)->total_pages)
+# define img_pagenum(N) ((N)->page_num)
+# define img_pagename(N) ((N)->pagename)
+# define img_filename(N) ((N)->filename)
+# define img_filepath(N) ((N)->filepath)
+# define img_attr(N) ((N)->attr)
+# define img_file(N) ((N)->file)
+# define img_type(N) ((N)->image_type)
+# define img_color(N) ((N)->color_space)
+# define img_colordepth(N) ((N)->color_depth)
+# define img_pagebox(N) ((N)->page_box_spec)
+# define img_state(N) ((N)->state)
+
+# define img_pdf_ptr(N) ((N)->img_struct.pdf)
+# define img_pdf_width(N) ((N)->img_struct.pdf->width)
+# define img_pdf_height(N) ((N)->img_struct.pdf->height)
+# define img_pdf_orig_x(N) ((N)->img_struct.pdf->orig_x)
+# define img_pdf_orig_y(N) ((N)->img_struct.pdf->orig_y)
+# define img_pdf_doc(N) ((N)->img_struct.pdf->doc)
+
+# define img_png_ptr(N) ((N)->img_struct.png)
+# define img_png_png_ptr(N) ((N)->img_struct.png->png_ptr)
+# define img_png_info_ptr(N) ((N)->img_struct.png->info_ptr)
+
+# define img_jpg_ptr(N) ((N)->img_struct.jpg)
+# define img_jpg_color(N) ((N)->img_struct.jpg->color_space)
+
+# define img_jb2_ptr(N) ((N)->img_struct.jb2)
+
+/**********************************************************************/
+
+typedef struct {
+ integer width; /* requested/actual TeX dimensions */
+ integer height;
+ integer depth;
+ integer transform;
+ integer flags;
+ image_dict *dict;
+ int dict_ref; /* luaL_ref() reference */
+} image;
+
+# define img_width(N) ((N)->width)
+# define img_height(N) ((N)->height)
+# define img_depth(N) ((N)->depth)
+# define img_transform(N) ((N)->transform)
+# define img_flags(N) ((N)->flags)
+# define img_dict(N) ((N)->dict)
+# define img_dictref(N) ((N)->dict_ref)
+
+# define F_FLAG_SCALED 0x01
+# define F_FLAG_REFERED 0x02
+
+# define img_flags(N) ((N)->flags)
+# define img_set_scaled(N) (img_flags(N) |= F_FLAG_SCALED)
+# define img_set_refered(N) (img_flags(N) |= F_FLAG_REFERED)
+# define img_unset_scaled(N) (img_flags(N) &= ~F_FLAG_SCALED)
+# define img_unset_refered(N) (img_flags(N) &= ~F_FLAG_REFERED)
+# define img_is_scaled(N) ((img_flags(N) & F_FLAG_SCALED) != 0)
+# define img_is_refered(N) ((img_flags(N) & F_FLAG_REFERED) != 0)
+
+# define set_wd_running(N) (img_width(N) = null_flag)
+# define set_ht_running(N) (img_height(N) = null_flag)
+# define set_dp_running(N) (img_depth(N) = null_flag)
+# define is_wd_running(N) (img_width(N) == null_flag)
+# define is_ht_running(N) (img_height(N) == null_flag)
+# define is_dp_running(N) (img_depth(N) == null_flag)
+
+/**********************************************************************/
+
+/* writeimg.c */
+
+image *new_image();
+image_dict *new_image_dict();
+void init_image(image *);
+void init_image_dict(image_dict *);
+void scale_img(image *);
+integer img_to_array(image *);
+void delete_image(image *);
+void free_image_dict(image_dict * p);
+void read_img(image_dict *, integer, integer);
+
+/* writepng.c */
+
+# ifndef boolean /* TODO: from where to get the original definition? */
+# define boolean int
+# endif
+
+void read_png_info(image_dict *, img_readtype_e);
+void read_jpg_info(image_dict *, img_readtype_e);
+void read_jbig2_info(image_dict *);
+void read_pdf_info(image_dict *, integer, integer);
+void write_img(image_dict *);
+void write_png(image_dict *);
+void write_jpg(image_dict *);
+void write_jbig2(image_dict *);
+void write_epdf(image_dict *);
+
+/* pdftoepdf.cc */
+
+void epdf_delete(image_dict * idict);
+
+#endif
diff --git a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc
new file mode 100644
index 00000000000..c5270eb58bd
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc
@@ -0,0 +1,1008 @@
+/*
+Copyright 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: pdftoepdf.cc 1058 2008-02-19 21:13:58Z hhenkel $
+*/
+
+#include <stdlib.h>
+#include <math.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <aconf.h>
+#include <GString.h>
+#include <gmem.h>
+#include <gfile.h>
+#include <config.h>
+#include <assert.h>
+#include "Object.h"
+#include "Stream.h"
+#include "Array.h"
+#include "Dict.h"
+#include "XRef.h"
+#include "Catalog.h"
+#include "Link.h"
+#include "Page.h"
+#include "GfxFont.h"
+#include "PDFDoc.h"
+#include "GlobalParams.h"
+#include "Error.h"
+
+#include "epdf.h"
+
+#define one_hundred_bp 6578176 /* 7227 * 65536 / 72 */
+
+// This file is mostly C and not very much C++; it's just used to interface
+// the functions of xpdf, which happens to be written in C++.
+
+// Used flags below:
+// PDFTEX_COPY_PAGEGROUP
+// If pdfTeX should copy a page group (a new feature in PDF 1.4 for
+// transparency) of an included file. The current support for this is
+// most likely broken. pdfTeX will at least give a warning if this flag
+// is not set. Surprisingly Acrobat and Jaws display files without a
+// page group correctly, so it might be safe to not set the flag.
+// See also PDFTEX_COPY_PAGEGROUP_NOFAIL.
+// PDFTEX_COPY_PAGEGROUP_NOFAIL
+// If set to false, pdfTeX will treat a page group in an included file
+// as an error and abort gracefully. This is only evaluated if
+// PDFTEX_COPY_PAGEGROUP is set.
+
+// The prefix "PTEX" for the PDF keys is special to pdfTeX;
+// this has been registered with Adobe by Hans Hagen.
+
+#define pdfkeyprefix "PTEX"
+
+// PdfObject encapsulates the xpdf Object type,
+// and properly frees its resources on destruction.
+// Use obj-> to access members of the Object,
+// and &obj to get a pointer to the object.
+// It is no longer necessary to call Object::free explicitely.
+
+class PdfObject {
+ public:
+ PdfObject() { // nothing
+ } ~PdfObject() {
+ iObject.free();
+ }
+ Object *operator->() {
+ return &iObject;
+ }
+ Object *operator&() {
+ return &iObject;
+ }
+ private: // no copying or assigning
+ PdfObject(const PdfObject &);
+ void operator=(const PdfObject &);
+ public:
+ Object iObject;
+};
+
+// When copying the Resources of the selected page, all objects are copied
+// recusively top-down. Indirect objects however are not fetched during
+// copying, but get a new object number from pdfTeX and then will be
+// appended into a linked list. Duplicates are checked and removed from the
+// list of indirect objects during appending.
+
+enum InObjType {
+ objFont,
+ objFontDesc,
+ objOther
+};
+
+struct InObj {
+ Ref ref; // ref in original PDF
+ InObjType type; // object type
+ InObj *next; // next entry in list of indirect objects
+ integer num; // new object number in output PDF
+ fd_entry *fd; // pointer to /FontDescriptor object structure
+ integer enc_objnum; // Encoding for objFont
+ int written; // has it been written to output PDF?
+};
+
+struct UsedEncoding {
+ integer enc_objnum;
+ GfxFont *font;
+ UsedEncoding *next;
+};
+
+static InObj *inObjList;
+static UsedEncoding *encodingList;
+static GBool isInit = gFalse;
+
+// --------------------------------------------------------------------
+// Maintain list of open embedded PDF files
+// --------------------------------------------------------------------
+
+struct PdfDocument {
+ char *file_name;
+ PDFDoc *doc;
+ XRef *xref;
+ InObj *inObjList;
+ int occurences; // number of references to the document; the doc can be
+ // deleted when this is negative
+ PdfDocument *next;
+};
+
+static PdfDocument *pdfDocuments = 0;
+
+static XRef *xref = 0;
+
+// Returns pointer to PdfDocument record for PDF file.
+// Creates a new record if it doesn't exist yet.
+// xref is made current for the document.
+
+static PdfDocument *find_add_document(char *file_name)
+{
+ PdfDocument *p = pdfDocuments;
+ while (p && strcmp(p->file_name, file_name) != 0)
+ p = p->next;
+ if (p) {
+ xref = p->xref;
+ (p->occurences)++;
+#ifdef DEBUG
+ fprintf(stderr, "\npdfTeX Debug: Incrementing %s (%d)\n", p->file_name,
+ p->occurences);
+#endif
+ return p;
+ }
+ p = new PdfDocument;
+ p->file_name = xstrdup(file_name);
+ p->xref = xref = 0;
+ p->occurences = 0;
+#ifdef DEBUG
+ fprintf(stderr, "\npdfTeX Debug: Creating %s (%d)\n", p->file_name,
+ p->occurences);
+#endif
+ GString *docName = new GString(p->file_name);
+ p->doc = new PDFDoc(docName); // takes ownership of docName
+ if (!p->doc->isOk() || !p->doc->okToPrint()) {
+ pdftex_fail("xpdf: reading PDF image failed");
+ }
+ p->inObjList = 0;
+ p->next = pdfDocuments;
+ pdfDocuments = p;
+ return p;
+}
+
+// Deallocate a PdfDocument with all its resources
+
+static void delete_document(PdfDocument * pdf_doc)
+{
+ PdfDocument **p = &pdfDocuments;
+ while (*p && *p != pdf_doc)
+ p = &((*p)->next);
+ // should not happen:
+ if (!*p)
+ return;
+ // unlink from list
+ *p = pdf_doc->next;
+ // free pdf_doc's resources
+ InObj *r, *n;
+ for (r = pdf_doc->inObjList; r != 0; r = n) {
+ n = r->next;
+ delete r;
+ }
+ xref = pdf_doc->xref;
+ delete pdf_doc->doc;
+ xfree(pdf_doc->file_name);
+ delete pdf_doc;
+}
+
+// Replacement for
+// Object *initDict(Dict *dict1){ initObj(objDict); dict = dict1; return this; }
+
+static void initDictFromDict(PdfObject & obj, Dict * dict)
+{
+ obj->initDict(xref);
+ for (int i = 0, l = dict->getLength(); i < l; i++) {
+ Object obj1;
+ obj->dictAdd(copyString(dict->getKey(i)), dict->getValNF(i, &obj1));
+ }
+}
+
+// --------------------------------------------------------------------
+
+static int addEncoding(GfxFont * gfont)
+{
+ UsedEncoding *n;
+ n = new UsedEncoding;
+ n->next = encodingList;
+ encodingList = n;
+ n->font = gfont;
+ n->enc_objnum = pdf_new_objnum();
+ return n->enc_objnum;
+}
+
+#define addFont(ref, fd, enc_objnum) \
+ addInObj(objFont, ref, fd, enc_objnum)
+
+// addFontDesc is only used to avoid writing the original FontDescriptor
+// from the PDF file.
+
+#define addFontDesc(ref, fd) \
+ addInObj(objFontDesc, ref, fd, 0)
+
+#define addOther(ref) \
+ addInObj(objOther, ref, 0, 0)
+
+static int addInObj(InObjType type, Ref ref, fd_entry * fd, integer e)
+{
+ InObj *p, *q, *n = new InObj;
+ if (ref.num == 0)
+ pdftex_fail("PDF inclusion: invalid reference");
+ n->ref = ref;
+ n->type = type;
+ n->next = 0;
+ n->fd = fd;
+ n->enc_objnum = e;
+ n->written = 0;
+ if (inObjList == 0)
+ inObjList = n;
+ else {
+ for (p = inObjList; p != 0; p = p->next) {
+ if (p->ref.num == ref.num && p->ref.gen == ref.gen) {
+ delete n;
+ return p->num;
+ }
+ q = p;
+ }
+ // it is important to add new objects at the end of the list,
+ // because new objects are being added while the list is being
+ // written out.
+ q->next = n;
+ }
+ if (type == objFontDesc)
+ n->num = get_fd_objnum(fd);
+ else
+ n->num = pdf_new_objnum();
+ return n->num;
+}
+
+static void copyObject(Object *);
+
+static void copyName(char *s)
+{
+ pdf_puts("/");
+ for (; *s != 0; s++) {
+ if (isdigit(*s) || isupper(*s) || islower(*s) || *s == '_' ||
+ *s == '.' || *s == '-')
+ pdfout(*s);
+ else
+ pdf_printf("#%.2X", *s & 0xFF);
+ }
+}
+
+static void copyDictEntry(Object * obj, int i)
+{
+ PdfObject obj1;
+ copyName(obj->dictGetKey(i));
+ pdf_puts(" ");
+ obj->dictGetValNF(i, &obj1);
+ copyObject(&obj1);
+ pdf_puts("\n");
+}
+
+static void copyDict(Object * obj)
+{
+ int i, l;
+ if (!obj->isDict())
+ pdftex_fail("PDF inclusion: invalid dict type <%s>",
+ obj->getTypeName());
+ for (i = 0, l = obj->dictGetLength(); i < l; ++i)
+ copyDictEntry(obj, i);
+}
+
+static void copyFontDict(Object * obj, InObj * r)
+{
+ int i, l;
+ char *key;
+ if (!obj->isDict())
+ pdftex_fail("PDF inclusion: invalid dict type <%s>",
+ obj->getTypeName());
+ pdf_puts("<<\n");
+ assert(r->type == objFont); // FontDescriptor is in fd_tree
+ for (i = 0, l = obj->dictGetLength(); i < l; ++i) {
+ key = obj->dictGetKey(i);
+ if (strncmp("FontDescriptor", key, strlen("FontDescriptor")) == 0
+ || strncmp("BaseFont", key, strlen("BaseFont")) == 0
+ || strncmp("Encoding", key, strlen("Encoding")) == 0)
+ continue; // skip original values
+ copyDictEntry(obj, i);
+ }
+ // write new FontDescriptor, BaseFont, and Encoding
+ pdf_printf("/FontDescriptor %d 0 R\n", (int) get_fd_objnum(r->fd));
+ pdf_printf("/BaseFont %d 0 R\n", (int) get_fn_objnum(r->fd));
+ pdf_printf("/Encoding %d 0 R\n", (int) r->enc_objnum);
+ pdf_puts(">>");
+}
+
+static void copyStream(Stream * str)
+{
+ int c;
+ str->reset();
+ while ((c = str->getChar()) != EOF)
+ pdfout(c);
+ pdf_last_byte = pdf_buf[pdf_ptr - 1];
+}
+
+static void copyProcSet(Object * obj)
+{
+ int i, l;
+ PdfObject procset;
+ if (!obj->isArray())
+ pdftex_fail("PDF inclusion: invalid ProcSet array type <%s>",
+ obj->getTypeName());
+ pdf_puts("/ProcSet [ ");
+ for (i = 0, l = obj->arrayGetLength(); i < l; ++i) {
+ obj->arrayGetNF(i, &procset);
+ if (!procset->isName())
+ pdftex_fail("PDF inclusion: invalid ProcSet entry type <%s>",
+ procset->getTypeName());
+ copyName(procset->getName());
+ pdf_puts(" ");
+ }
+ pdf_puts("]\n");
+}
+
+#define REPLACE_TYPE1C true
+
+static void copyFont(char *tag, Object * fontRef)
+{
+ PdfObject fontdict, subtype, basefont, fontdescRef, fontdesc, charset,
+ fontfile, ffsubtype;
+ GfxFont *gfont;
+ fd_entry *fd;
+ fm_entry *fontmap;
+ // Check whether the font has already been embedded before analysing it.
+ InObj *p;
+ Ref ref = fontRef->getRef();
+ for (p = inObjList; p; p = p->next) {
+ if (p->ref.num == ref.num && p->ref.gen == ref.gen) {
+ copyName(tag);
+ pdf_printf(" %d 0 R ", (int) p->num);
+ return;
+ }
+ }
+ // Only handle included Type1 (and Type1C) fonts; anything else will be copied.
+ // Type1C fonts are replaced by Type1 fonts, if REPLACE_TYPE1C is true.
+ if (fixed_replace_font && fontRef->fetch(xref, &fontdict)->isDict()
+ && fontdict->dictLookup("Subtype", &subtype)->isName()
+ && !strcmp(subtype->getName(), "Type1")
+ && fontdict->dictLookup("BaseFont", &basefont)->isName()
+ && fontdict->dictLookupNF("FontDescriptor", &fontdescRef)->isRef()
+ && fontdescRef->fetch(xref, &fontdesc)->isDict()
+ && (fontdesc->dictLookup("FontFile", &fontfile)->isStream()
+ || (REPLACE_TYPE1C
+ && fontdesc->dictLookup("FontFile3", &fontfile)->isStream()
+ && fontfile->streamGetDict()->lookup("Subtype",
+ &ffsubtype)->isName()
+ && !strcmp(ffsubtype->getName(), "Type1C")))
+ && (fontmap = lookup_fontmap(basefont->getName())) != NULL) {
+ fd = epdf_create_fontdescriptor(fontmap);
+ if (fontdesc->dictLookup("CharSet", &charset) &&
+ charset->isString() && is_subsetable(fontmap))
+ epdf_mark_glyphs(fd, charset->getString()->getCString());
+ else
+ embed_whole_font(fd);
+ addFontDesc(fontdescRef->getRef(), fd);
+ copyName(tag);
+ gfont = GfxFont::makeFont(xref, tag, fontRef->getRef(),
+ fontdict->getDict());
+ pdf_printf(" %d 0 R ", addFont(fontRef->getRef(), fd,
+ addEncoding(gfont)));
+ } else {
+ copyName(tag);
+ pdf_puts(" ");
+ copyObject(fontRef);
+ }
+}
+
+static void copyFontResources(Object * obj)
+{
+ PdfObject fontRef;
+ int i, l;
+ if (!obj->isDict())
+ pdftex_fail("PDF inclusion: invalid font resources dict type <%s>",
+ obj->getTypeName());
+ pdf_puts("/Font << ");
+ for (i = 0, l = obj->dictGetLength(); i < l; ++i) {
+ obj->dictGetValNF(i, &fontRef);
+ if (fontRef->isRef())
+ copyFont(obj->dictGetKey(i), &fontRef);
+ else
+ pdftex_fail("PDF inclusion: invalid font in reference type <%s>",
+ fontRef->getTypeName());
+ }
+ pdf_puts(">>\n");
+}
+
+static void copyOtherResources(Object * obj, char *key)
+{
+ // copies all other resources (write_epdf handles Fonts and ProcSets),
+ // but gives a warning if an object is not a dictionary.
+
+ if (!obj->isDict())
+ //FIXME: Write the message only to the log file
+ pdftex_warn("PDF inclusion: invalid other resource which is no dict"
+ " (key '%s', type <%s>); copying it anyway.",
+ key, obj->getTypeName());
+ copyName(key);
+ pdf_puts(" ");
+ copyObject(obj);
+}
+
+// Function onverts double to string; very small and very large numbers
+// are NOT converted to scientific notation.
+// n must be a number or real conforming to the implementation limits
+// of PDF as specified in appendix C.1 of the PDF Ref.
+// These are:
+// maximum value of ints is +2^32
+// maximum value of reals is +2^15
+// smalles values of reals is 1/(2^16)
+
+static char *convertNumToPDF(double n)
+{
+ static const int precision = 6;
+ static const int fact = (int) 1E6; // must be 10^precision
+ static const double epsilon = 0.5E-6; // 2epsilon must be 10^-precision
+ static char buf[64];
+ // handle very small values: return 0
+ if (fabs(n) < epsilon) {
+ buf[0] = '0';
+ buf[1] = '\0';
+ } else {
+ char ints[64];
+ int bindex = 0, sindex = 0;
+ int ival, fval;
+ // handle the sign part if n is negative
+ if (n < 0) {
+ buf[bindex++] = '-';
+ n = -n;
+ }
+ n += epsilon; // for rounding
+ // handle the integer part, simply with sprintf
+ ival = (int) floor(n);
+ n -= ival;
+ sprintf(ints, "%d", ival);
+ while (ints[sindex] != 0)
+ buf[bindex++] = ints[sindex++];
+ // handle the fractional part up to 'precision' digits
+ fval = (int) floor(n * fact);
+ if (fval) {
+ // set a dot
+ buf[bindex++] = '.';
+ sindex = bindex + precision;
+ buf[sindex--] = '\0';
+ // fill up trailing zeros with the string terminator NULL
+ while (((fval % 10) == 0) && (sindex >= bindex)) {
+ buf[sindex--] = '\0';
+ fval /= 10;
+ }
+ // fill up the fractional part back to front
+ while (sindex >= bindex) {
+ buf[sindex--] = (fval % 10) + '0';
+ fval /= 10;
+ }
+ } else
+ buf[bindex++] = 0;
+ }
+ return (char *) buf;
+}
+
+static void copyObject(Object * obj)
+{
+ PdfObject obj1;
+ int i, l, c;
+ Ref ref;
+ char *p;
+ GString *s;
+ if (obj->isBool()) {
+ pdf_printf("%s", obj->getBool()? "true" : "false");
+ } else if (obj->isInt()) {
+ pdf_printf("%i", obj->getInt());
+ } else if (obj->isReal()) {
+ pdf_printf("%s", convertNumToPDF(obj->getReal()));
+ } else if (obj->isNum()) {
+ pdf_printf("%s", convertNumToPDF(obj->getNum()));
+ } else if (obj->isString()) {
+ s = obj->getString();
+ p = s->getCString();
+ l = s->getLength();
+ if (strlen(p) == (unsigned int) l) {
+ pdf_puts("(");
+ for (; *p != 0; p++) {
+ c = (unsigned char) *p;
+ if (c == '(' || c == ')' || c == '\\')
+ pdf_printf("\\%c", c);
+ else if (c < 0x20 || c > 0x7F)
+ pdf_printf("\\%03o", c);
+ else
+ pdfout(c);
+ }
+ pdf_puts(")");
+ } else {
+ pdf_puts("<");
+ for (i = 0; i < l; i++) {
+ c = s->getChar(i) & 0xFF;
+ pdf_printf("%.2x", c);
+ }
+ pdf_puts(">");
+ }
+ } else if (obj->isName()) {
+ copyName(obj->getName());
+ } else if (obj->isNull()) {
+ pdf_puts("null");
+ } else if (obj->isArray()) {
+ pdf_puts("[");
+ for (i = 0, l = obj->arrayGetLength(); i < l; ++i) {
+ obj->arrayGetNF(i, &obj1);
+ if (!obj1->isName())
+ pdf_puts(" ");
+ copyObject(&obj1);
+ }
+ pdf_puts("]");
+ } else if (obj->isDict()) {
+ pdf_puts("<<\n");
+ copyDict(obj);
+ pdf_puts(">>");
+ } else if (obj->isStream()) {
+ initDictFromDict(obj1, obj->streamGetDict());
+ obj->streamGetDict()->incRef();
+ pdf_puts("<<\n");
+ copyDict(&obj1);
+ pdf_puts(">>\n");
+ pdf_puts("stream\n");
+ copyStream(obj->getStream()->getBaseStream());
+ if (pdf_last_byte != '\n')
+ pdf_puts("\n");
+ pdf_puts("endstream"); // can't simply write pdf_end_stream()
+ } else if (obj->isRef()) {
+ ref = obj->getRef();
+ if (ref.num == 0) {
+ pdftex_warn
+ ("PDF inclusion: reference to invalid object was replaced by <null>");
+ pdf_puts("null");
+ } else
+ pdf_printf("%d 0 R", addOther(ref));
+ } else {
+ pdftex_fail("PDF inclusion: type <%s> cannot be copied",
+ obj->getTypeName());
+ }
+}
+
+static void writeRefs()
+{
+ InObj *r;
+ for (r = inObjList; r != 0; r = r->next) {
+ if (!r->written) {
+ Object obj1;
+ r->written = 1;
+ xref->fetch(r->ref.num, r->ref.gen, &obj1);
+ if (r->type == objFont) {
+ assert(!obj1.isStream());
+ zpdf_begin_obj(r->num, 2); // \pdfobjcompresslevel = 2 is for this
+ copyFontDict(&obj1, r);
+ pdf_puts("\n");
+ pdf_end_obj();
+ } else if (r->type != objFontDesc) { // /FontDescriptor is written via write_fontdescriptor()
+ if (obj1.isStream())
+ zpdf_begin_obj(r->num, 0);
+ else
+ zpdf_begin_obj(r->num, 2); // \pdfobjcompresslevel = 2 is for this
+ copyObject(&obj1);
+ pdf_puts("\n");
+ pdf_end_obj();
+ }
+ obj1.free();
+ }
+ }
+}
+
+static void writeEncodings()
+{
+ UsedEncoding *r, *n;
+ char *glyphNames[256], *s;
+ int i;
+ for (r = encodingList; r != 0; r = r->next) {
+ for (i = 0; i < 256; i++) {
+ if (r->font->isCIDFont()) {
+ pdftex_warn
+ ("PDF inclusion: CID font included, encoding maybe wrong");
+ }
+ if ((s = ((Gfx8BitFont *) r->font)->getCharName(i)) != 0)
+ glyphNames[i] = s;
+ else
+ glyphNames[i] = notdef;
+ }
+ epdf_write_enc(glyphNames, r->enc_objnum);
+ }
+ for (r = encodingList; r != 0; r = n) {
+ n = r->next;
+ delete r->font;
+ delete r;
+ }
+}
+
+// get the pagebox according to the pagebox_spec
+
+static PDFRectangle *get_pagebox(Page * page, integer pagebox_spec)
+{
+ if (pagebox_spec == pdf_box_spec_media)
+ return page->getMediaBox();
+ else if (pagebox_spec == pdf_box_spec_crop)
+ return page->getCropBox();
+ else if (pagebox_spec == pdf_box_spec_bleed)
+ return page->getBleedBox();
+ else if (pagebox_spec == pdf_box_spec_trim)
+ return page->getTrimBox();
+ else if (pagebox_spec == pdf_box_spec_art)
+ return page->getArtBox();
+ else
+ pdftex_fail("PDF inclusion: unknown value of pagebox spec (%i)",
+ (int) pagebox_spec);
+ return page->getMediaBox(); // to make the compiler happy
+}
+
+
+// Reads various information about the PDF and sets it up for later inclusion.
+// This will fail if the PDF version of the PDF is higher than
+// minor_pdf_version_wanted or page_name is given and can not be found.
+// It makes no sense to give page_name _and_ page_num.
+// Returns the page number.
+
+void
+read_pdf_info(image_dict * idict, integer minor_pdf_version_wanted,
+ integer pdf_inclusion_errorlevel)
+{
+ PdfDocument *pdf_doc;
+ Page *page;
+ int rotate;
+ PDFRectangle *pagebox;
+ float pdf_version_found, pdf_version_wanted;
+ assert(idict != NULL);
+ assert(img_type(idict) == IMAGE_TYPE_PDF);
+ assert(img_pdf_ptr(idict) == NULL);
+ img_pdf_ptr(idict) = new_pdf_img_struct();
+ // initialize
+ if (!isInit) {
+ globalParams = new GlobalParams();
+ globalParams->setErrQuiet(gFalse);
+ isInit = gTrue;
+ }
+ // open PDF file
+ pdf_doc = find_add_document(img_filepath(idict));
+ img_pdf_doc(idict) = pdf_doc;
+
+ // check PDF version
+ // this works only for PDF 1.x -- but since any versions of PDF newer
+ // than 1.x will not be backwards compatible to PDF 1.x, pdfTeX will
+ // then have to changed drastically anyway.
+ pdf_version_found = pdf_doc->doc->getPDFVersion();
+ pdf_version_wanted = 1 + (minor_pdf_version_wanted * 0.1);
+ if (pdf_version_found > pdf_version_wanted) {
+ char msg[] =
+ "PDF inclusion: found PDF version <%.1f>, but at most version <%.1f> allowed";
+ if (pdf_inclusion_errorlevel > 0) {
+ pdftex_fail(msg, pdf_version_found, pdf_version_wanted);
+ } else {
+ pdftex_warn(msg, pdf_version_found, pdf_version_wanted);
+ }
+ }
+ img_totalpages(idict) = pdf_doc->doc->getCatalog()->getNumPages();
+ if (img_pagename(idict)) {
+ // get page by name
+ GString name(img_pagename(idict));
+ LinkDest *link = pdf_doc->doc->findDest(&name);
+ if (link == 0 || !link->isOk())
+ pdftex_fail("PDF inclusion: invalid destination <%s>",
+ img_pagename(idict));
+ Ref ref = link->getPageRef();
+ img_pagenum(idict) =
+ pdf_doc->doc->getCatalog()->findPage(ref.num, ref.gen);
+ if (img_pagenum(idict) == 0)
+ pdftex_fail("PDF inclusion: destination is not a page <%s>",
+ img_pagename(idict));
+ delete link;
+ } else {
+ // get page by number
+ if (img_pagenum(idict) <= 0
+ || img_pagenum(idict) > img_totalpages(idict))
+ pdftex_fail("PDF inclusion: required page <%i> does not exist",
+ (int) img_pagenum(idict));
+ }
+ // get the required page
+ page = pdf_doc->doc->getCatalog()->getPage(img_pagenum(idict));
+
+ // get the pagebox (media, crop...) to use.
+ pagebox = get_pagebox(page, img_pagebox(idict));
+ if (pagebox->x2 > pagebox->x1) {
+ img_pdf_orig_x(idict) = pagebox->x1;
+ img_pdf_width(idict) = pagebox->x2 - pagebox->x1;
+ } else {
+ img_pdf_orig_x(idict) = pagebox->x2;
+ img_pdf_width(idict) = pagebox->x1 - pagebox->x2;
+ }
+ if (pagebox->y2 > pagebox->y1) {
+ img_pdf_orig_y(idict) = pagebox->y1;
+ img_pdf_height(idict) = pagebox->y2 - pagebox->y1;
+ } else {
+ img_pdf_orig_y(idict) = pagebox->y2;
+ img_pdf_height(idict) = pagebox->y1 - pagebox->y2;
+ }
+
+ rotate = page->getRotate();
+ // handle page rotation and adjust dimens as needed
+ if (rotate != 0) {
+ if (rotate % 90 == 0) {
+ // handle only the simple case: multiple of 90s.
+ // these are the only values allowed according to the
+ // reference (v1.3, p. 78).
+ // 180 needs no special treatment here
+ register float f;
+ switch (rotate) {
+ case 90:
+ f = img_pdf_height(idict);
+ img_pdf_height(idict) = img_pdf_width(idict);
+ img_pdf_width(idict) = f;
+ break;
+ case 270:
+ f = img_pdf_height(idict);
+ img_pdf_height(idict) = img_pdf_width(idict);
+ img_pdf_width(idict) = f;
+ break;
+ }
+ }
+ }
+ pdf_doc->xref = pdf_doc->doc->getXRef();
+ img_xsize(idict) = bp2int(img_pdf_width(idict));
+ img_ysize(idict) = bp2int(img_pdf_height(idict));
+}
+
+// writes the current epf_doc.
+// Here the included PDF is copied, so most errors that can happen during PDF
+// inclusion will arise here.
+
+void write_epdf(image_dict * idict)
+{
+ Page *page;
+ PdfObject contents, obj1, obj2;
+ PdfObject group, metadata, pieceinfo, separationInfo;
+ Object info;
+ char *key;
+ char s[256];
+ int i, l;
+ int rotate;
+ double scale[6] = { 0, 0, 0, 0, 0, 0 };
+ bool writematrix = false;
+ PdfDocument *pdf_doc = (PdfDocument *) img_pdf_doc(idict);
+ (pdf_doc->occurences)--;
+#ifdef DEBUG
+ fprintf(stderr, "\npdfTeX Debug: Decrementing %s (%d)\n",
+ pdf_doc->file_name, pdf_doc->occurences);
+#endif
+ xref = pdf_doc->xref;
+ inObjList = pdf_doc->inObjList;
+ encodingList = 0;
+ page = pdf_doc->doc->getCatalog()->getPage(img_pagenum(idict));
+ rotate = page->getRotate();
+ PDFRectangle *pagebox;
+ // write the Page header
+ pdf_puts("/Type /XObject\n/Subtype /Form\n");
+ if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
+ pdf_printf("%s\n", img_attr(idict));
+ pdf_puts("/FormType 1\n");
+
+ // write additional information
+ pdf_printf("/%s.FileName (%s)\n", pdfkeyprefix,
+ convertStringToPDFString(pdf_doc->file_name,
+ strlen(pdf_doc->file_name)));
+ pdf_printf("/%s.PageNumber %i\n", pdfkeyprefix, (int) img_pagenum(idict));
+ pdf_doc->doc->getDocInfoNF(&info);
+ if (info.isRef()) {
+ // the info dict must be indirect (PDF Ref p. 61)
+ pdf_printf("/%s.InfoDict ", pdfkeyprefix);
+ pdf_printf("%d 0 R\n", addOther(info.getRef()));
+ }
+ // get the pagebox (media, crop...) to use.
+ pagebox = get_pagebox(page, img_pagebox(idict));
+
+ // handle page rotation
+ if (rotate != 0) {
+ if (rotate % 90 == 0) {
+ // this handles only the simple case: multiple of 90s but these
+ // are the only values allowed according to the reference
+ // (v1.3, p. 78).
+ // the image is rotated around its center.
+ // the /Rotate key is clockwise while the matrix is
+ // counterclockwise :-%
+ tex_printf(", page is rotated %d degrees", rotate);
+ switch (rotate) {
+ case 90:
+ scale[1] = -1;
+ scale[2] = 1;
+ scale[4] = pagebox->x1 - pagebox->y1;
+ scale[5] = pagebox->y1 + pagebox->x2;
+ writematrix = true;
+ break;
+ case 180:
+ scale[0] = scale[3] = -1;
+ scale[4] = pagebox->x1 + pagebox->x2;
+ scale[5] = pagebox->y1 + pagebox->y2;
+ writematrix = true;
+ break; // width and height are exchanged
+ case 270:
+ scale[1] = 1;
+ scale[2] = -1;
+ scale[4] = pagebox->x1 + pagebox->y2;
+ scale[5] = pagebox->y1 - pagebox->x1;
+ writematrix = true;
+ break;
+ }
+ if (writematrix) { // The matrix is only written if the image is rotated.
+ sprintf(s, "/Matrix [%.8f %.8f %.8f %.8f %.8f %.8f]\n",
+ scale[0],
+ scale[1], scale[2], scale[3], scale[4], scale[5]);
+ pdf_printf(stripzeros(s));
+ }
+ }
+ }
+
+ sprintf(s, "/BBox [%.8f %.8f %.8f %.8f]\n",
+ pagebox->x1, pagebox->y1, pagebox->x2, pagebox->y2);
+ pdf_printf(stripzeros(s));
+
+ // write the page Group if it's there
+ if (page->getGroup() != NULL) {
+#if PDFTEX_COPY_PAGEGROUP
+# if PDFTEX_COPY_PAGEGROUP_NOFAIL
+ // FIXME: This will most likely produce incorrect PDFs :-(
+ initDictFromDict(group, page->getGroup());
+ if (group->dictGetLength() > 0) {
+ pdf_puts("/Group ");
+ copyObject(&group);
+ pdf_puts("\n");
+ }
+# else
+ // FIXME: currently we don't know how to handle Page Groups so we abort gracefully :-(
+ pdftex_fail
+ ("PDF inclusion: Page Group detected which pdfTeX can't handle. Sorry.");
+# endif
+#else
+ // FIXME: currently we don't know how to handle Page Groups so we at least give a warning :-(
+ pdftex_warn
+ ("PDF inclusion: Page Group detected which pdfTeX can't handle. Ignoring it.");
+#endif
+ }
+ // write the page Metadata if it's there
+ if (page->getMetadata() != NULL) {
+ metadata->initStream(page->getMetadata());
+ pdf_puts("/Metadata ");
+ copyObject(&metadata);
+ pdf_puts("\n");
+ }
+ // write the page PieceInfo if it's there
+ if (page->getPieceInfo() != NULL) {
+ initDictFromDict(pieceinfo, page->getPieceInfo());
+ if (pieceinfo->dictGetLength() > 0) {
+ pdf_puts("/PieceInfo ");
+ copyObject(&pieceinfo);
+ pdf_puts("\n");
+ }
+ }
+ // write the page SeparationInfo if it's there
+ if (page->getSeparationInfo() != NULL) {
+ initDictFromDict(separationInfo, page->getSeparationInfo());
+ if (separationInfo->dictGetLength() > 0) {
+ pdf_puts("/SeparationInfo ");
+ copyObject(&separationInfo);
+ pdf_puts("\n");
+ }
+ }
+ // write the Resources dictionary
+ if (page->getResourceDict() == NULL) {
+ // Resources can be missing (files without them have been spotted
+ // in the wild). This violates the PDF Ref., which claims they are
+ // required, but all RIPs accept them.
+ // We "replace" them with empty /Resources, although in form xobjects
+ // /Resources are not required.
+ pdftex_warn
+ ("PDF inclusion: no /Resources detected. Replacing with empty /Resources.");
+ pdf_puts("/Resources <<>>\n");
+ } else {
+ initDictFromDict(obj1, page->getResourceDict());
+ page->getResourceDict()->incRef();
+ if (!obj1->isDict())
+ pdftex_fail("PDF inclusion: invalid resources dict type <%s>",
+ obj1->getTypeName());
+ pdf_puts("/Resources <<\n");
+ for (i = 0, l = obj1->dictGetLength(); i < l; ++i) {
+ obj1->dictGetVal(i, &obj2);
+ key = obj1->dictGetKey(i);
+ if (strcmp("Font", key) == 0)
+ copyFontResources(&obj2);
+ else if (strcmp("ProcSet", key) == 0)
+ copyProcSet(&obj2);
+ else
+ copyOtherResources(&obj2, key);
+ }
+ pdf_puts(">>\n");
+ }
+ // write the page contents
+ page->getContents(&contents);
+ if (contents->isStream()) {
+ initDictFromDict(obj1, contents->streamGetDict());
+ contents->streamGetDict()->incRef();
+ copyDict(&obj1);
+ pdf_puts(">>\nstream\n");
+ copyStream(contents->getStream()->getBaseStream());
+ pdf_end_stream();
+ } else if (contents->isArray()) {
+ pdf_begin_stream();
+ for (i = 0, l = contents->arrayGetLength(); i < l; ++i) {
+ Object contentsobj;
+ copyStream((contents->arrayGet(i, &contentsobj))->getStream());
+ contentsobj.free();
+ }
+ pdf_end_stream();
+ } else { // the contents are optional, but we need to include an empty stream
+ pdf_begin_stream();
+ pdf_end_stream();
+ }
+ // write out all indirect objects
+ writeRefs();
+ // write out all used encodings (and delete list)
+ writeEncodings();
+ // save object list, xref
+ pdf_doc->inObjList = inObjList;
+ pdf_doc->xref = xref;
+}
+
+// Called when an image has been written and it's resources in image_tab are
+// freed and it's not referenced anymore.
+
+void epdf_delete(image_dict * idict)
+{
+ PdfDocument *pdf_doc = (PdfDocument *) img_pdf_doc(idict);
+ xref = pdf_doc->xref;
+ if (pdf_doc->occurences < 0) {
+#ifdef DEBUG
+ fprintf(stderr, "\npdfTeX Debug: Deleting %s\n", pdf_doc->file_name);
+#endif
+ delete_document(pdf_doc);
+ }
+ img_pdf_doc(idict) = NULL;
+}
+
+// Called when PDF embedding system is finalized.
+// Now deallocate all remaining PdfDocuments.
+
+void epdf_check_mem()
+{
+ if (isInit) {
+ PdfDocument *p, *n;
+ for (p = pdfDocuments; p; p = n) {
+ n = p->next;
+ delete_document(p);
+ }
+ // see above for globalParams
+ delete globalParams;
+ }
+}
diff --git a/Build/source/texk/web2c/luatexdir/image/writeimg.c b/Build/source/texk/web2c/luatexdir/image/writeimg.c
new file mode 100644
index 00000000000..66eb459bc0c
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/writeimg.c
@@ -0,0 +1,677 @@
+/*
+Copyright (c) 1996-2002, 2005 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+pdfTeX is free software;
+you can redistribute it and / or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writeimg.c 1119 2008-03-22 11:27:02Z hhenkel $
+*/
+
+#include <assert.h>
+#include "ptexlib.h"
+#include <kpathsea/c-auto.h>
+#include <kpathsea/c-memstr.h>
+
+#include "image.h"
+
+#include <../lua51/lua.h>
+#include <../lua51/lauxlib.h>
+
+extern void pdf_print_real(integer m, integer d);
+
+#define obj_aux(A) obj_tab[(A)].int4
+
+/**********************************************************************/
+/*
+ Patch ImageTypeDetection 2003/02/08 by Heiko Oberdiek.
+
+ Function "readimage" performs some basic initializations.
+ Then it looks at the file extension to determine the
+ image type and calls specific code/functions.
+ The main disadvantage is that standard file extensions
+ have to be used, otherwise pdfTeX is not able to detect
+ the correct image type.
+
+ The patch now looks at the file header first regardless of
+ the file extension. This is implemented in function
+ "check_type_by_header". If this check fails, the traditional
+ test of standard file extension is tried, done in function
+ "check_type_by_extension".
+
+ Magic headers:
+
+ * "PNG (Portable Network Graphics) Specification", Version 1.2
+ (http://www.libpng.org/pub/png):
+
+ | 3.1. PNG file signature
+ |
+ | The first eight bytes of a PNG file always contain the following
+ | (decimal) values:
+ |
+ | 137 80 78 71 13 10 26 10
+
+ Translation to C: "\x89PNG\r\n\x1A\n"
+
+ * "JPEG File Interchange Format", Version 1.02:
+
+ | o you can identify a JFIF file by looking for the following
+ | sequence: X'FF', SOI X'FF', APP0, <2 bytes to be skipped>,
+ | "JFIF", X'00'.
+
+ Function "check_type_by_header" only looks at the first two bytes:
+ "\xFF\xD8"
+
+ * ISO/IEC JTC 1/SC 29/WG 1
+ (ITU-T SG8)
+ Coding of Still Pictures
+ Title: 14492 FCD
+ Source: JBIG Committee
+ Project: JTC 1.29.10
+ Status: Final Committee Draft
+
+ | D.4.1, ID string
+ |
+ | This is an 8-byte sequence containing 0x97 0x4A 0x42 0x32 0x0D 0x0A
+ | 0x1A 0x0A.
+
+ * "PDF Reference", third edition:
+ * The first line should contain "%PDF-1.0" until "%PDF-1.4"
+ (section 3.4.1 "File Header").
+ * The "implementation notes" say:
+
+ | 3.4.1, File Header
+ | 12. Acrobat viewers require only that the header appear
+ | somewhere within the first 1024 bytes of the file.
+ | 13. Acrobat viewers will also accept a header of the form
+ | %!PS-Adobe-N.n PDF-M.m
+
+ The check in function "check_type_by_header" only implements
+ the first issue. The implementation notes are not considered.
+ Therefore files with garbage at start of file must have the
+ standard extension.
+
+ Functions "check_type_by_header" and "check_type_by_extension":
+ img_type(img) is set to IMAGE_TYPE_NONE by new_image_dict().
+ Both functions try to detect a type and set img_type(img).
+ Thus a value other than IMAGE_TYPE_NONE indicates that a
+ type has been found.
+*/
+
+#define HEADER_JPG "\xFF\xD8"
+#define HEADER_PNG "\x89PNG\r\n\x1A\n"
+#define HEADER_JBIG2 "\x97\x4A\x42\x32\x0D\x0A\x1A\x0A"
+#define HEADER_PDF "%PDF-1."
+#define MAX_HEADER (sizeof(HEADER_PNG)-1)
+
+static void check_type_by_header(image_dict * idict)
+{
+ int i;
+ FILE *file = NULL;
+ char header[MAX_HEADER];
+
+ assert(idict != NULL);
+ if (img_type(idict) != IMAGE_TYPE_NONE) /* nothing to do */
+ return;
+ /* read the header */
+ file = xfopen(img_filepath(idict), FOPEN_RBIN_MODE);
+ for (i = 0; (unsigned) i < MAX_HEADER; i++) {
+ header[i] = xgetc(file);
+ if (feof(file))
+ pdftex_fail("reading image file failed");
+ }
+ xfclose(file, img_filepath(idict));
+ /* tests */
+ if (strncmp(header, HEADER_JPG, sizeof(HEADER_JPG) - 1) == 0)
+ img_type(idict) = IMAGE_TYPE_JPG;
+ else if (strncmp(header, HEADER_PNG, sizeof(HEADER_PNG) - 1) == 0)
+ img_type(idict) = IMAGE_TYPE_PNG;
+ else if (strncmp(header, HEADER_JBIG2, sizeof(HEADER_JBIG2) - 1) == 0)
+ img_type(idict) = IMAGE_TYPE_JBIG2;
+ else if (strncmp(header, HEADER_PDF, sizeof(HEADER_PDF) - 1) == 0)
+ img_type(idict) = IMAGE_TYPE_PDF;
+}
+
+static void check_type_by_extension(image_dict * idict)
+{
+ char *image_suffix;
+
+ assert(idict != NULL);
+ if (img_type(idict) != IMAGE_TYPE_NONE) /* nothing to do */
+ return;
+ /* tests */
+ if ((image_suffix = strrchr(img_filename(idict), '.')) == 0)
+ img_type(idict) = IMAGE_TYPE_NONE;
+ else if (strcasecmp(image_suffix, ".png") == 0)
+ img_type(idict) = IMAGE_TYPE_PNG;
+ else if (strcasecmp(image_suffix, ".jpg") == 0 ||
+ strcasecmp(image_suffix, ".jpeg") == 0)
+ img_type(idict) = IMAGE_TYPE_JPG;
+ else if (strcasecmp(image_suffix, ".jbig2") == 0 ||
+ strcasecmp(image_suffix, ".jb2") == 0)
+ img_type(idict) = IMAGE_TYPE_JBIG2;
+ else if (strcasecmp(image_suffix, ".pdf") == 0)
+ img_type(idict) = IMAGE_TYPE_PDF;
+}
+
+/**********************************************************************/
+
+pdf_img_struct *new_pdf_img_struct()
+{
+ pdf_img_struct *p;
+ p = xtalloc(1, pdf_img_struct);
+ p->width = 0;
+ p->height = 0;
+ p->orig_x = 0;
+ p->orig_y = 0;
+ p->doc = NULL;
+ return p;
+}
+
+void init_image(image * p)
+{
+ assert(p != NULL);
+ set_wd_running(p);
+ set_ht_running(p);
+ set_dp_running(p);
+ img_transform(p) = 0;
+ img_flags(p) = 0;
+ img_unset_refered(p); /* wd/ht/dp may be modified */
+ img_unset_scaled(p);
+ img_dict(p) = NULL;
+ img_dictref(p) = LUA_NOREF;
+}
+
+image *new_image()
+{
+ image *p = xtalloc(1, image);
+ init_image(p);
+ return p;
+}
+
+void init_image_dict(image_dict * p)
+{
+ assert(p != NULL);
+ img_objnum(p) = 0;
+ img_index(p) = 0;
+ img_xsize(p) = 0;
+ img_ysize(p) = 0;
+ img_xres(p) = 0;
+ img_yres(p) = 0;
+ img_colorspace(p) = 0;
+ img_totalpages(p) = 0;
+ img_pagenum(p) = 1;
+ img_pagename(p) = NULL;
+ img_filename(p) = NULL;
+ img_filepath(p) = NULL;
+ img_attr(p) = NULL;
+ img_file(p) = NULL;
+ img_type(p) = IMAGE_TYPE_NONE;
+ img_color(p) = 0;
+ img_colordepth(p) = 0;
+ img_pagebox(p) = PDF_BOX_SPEC_MEDIA;
+ img_state(p) = DICT_NEW;
+ img_pdf_ptr(p) = NULL; /* union */
+}
+
+image_dict *new_image_dict()
+{
+ image_dict *p = xtalloc(1, image_dict);
+ init_image_dict(p);
+ return p;
+}
+
+void free_dict_strings(image_dict * p)
+{
+ if (img_filename(p) != NULL)
+ xfree(img_filename(p));
+ img_filename(p) = NULL;
+ if (img_filepath(p) != NULL)
+ xfree(img_filepath(p));
+ img_filepath(p) = NULL;
+ if (img_attr(p) != NULL)
+ xfree(img_attr(p));
+ img_attr(p) = NULL;
+ if (img_pagename(p) != NULL)
+ xfree(img_pagename(p));
+ img_pagename(p) = NULL;
+}
+
+void free_image_dict(image_dict * p)
+{
+ free_dict_strings(p);
+ if (img_type(p) == IMAGE_TYPE_PDF)
+ epdf_delete(p);
+ assert(img_file(p) == NULL);
+ xfree(p);
+}
+
+/**********************************************************************/
+
+void pdf_print_resname_prefix()
+{
+ if (pdf_resname_prefix != 0)
+ pdf_printf(makecstring(pdf_resname_prefix));
+}
+
+void read_img(image_dict * idict, integer pdf_minor_version,
+ integer pdf_inclusion_errorlevel)
+{
+ char *filepath;
+ int callback_id;
+ assert(idict != NULL);
+ if (img_filename(idict) == NULL)
+ pdftex_fail("image file name missing");
+ callback_id = callback_defined(find_image_file_callback);
+ if (img_filepath(idict) == NULL) {
+ if (callback_id > 0
+ && run_callback(callback_id, "S->S", img_filename(idict),
+ &filepath)) {
+ if (filepath && (strlen(filepath) > 0))
+ img_filepath(idict) = strdup(filepath);
+ } else
+ img_filepath(idict) =
+ kpse_find_file(img_filename(idict), kpse_tex_format, true);
+ }
+ if (img_filepath(idict) == NULL)
+ pdftex_fail("cannot find image file");
+ /* type checks */
+ check_type_by_header(idict);
+ check_type_by_extension(idict);
+ /* read image */
+ switch (img_type(idict)) {
+ case IMAGE_TYPE_PDF:
+ read_pdf_info(idict, pdf_minor_version, pdf_inclusion_errorlevel);
+ break;
+ case IMAGE_TYPE_PNG:
+ read_png_info(idict, IMG_CLOSEINBETWEEN);
+ break;
+ case IMAGE_TYPE_JPG:
+ read_jpg_info(idict, IMG_CLOSEINBETWEEN);
+ break;
+ case IMAGE_TYPE_JBIG2:
+ if (pdf_minor_version < 4) {
+ pdftex_fail
+ ("JBIG2 images only possible with at least PDF 1.4; you are generating PDF 1.%i",
+ (int) pdf_minor_version);
+ }
+ read_jbig2_info(idict);
+ break;
+ default:
+ pdftex_fail("internal error: unknown image type");
+ }
+ cur_file_name = NULL;
+ if (img_state(idict) < DICT_FILESCANNED)
+ img_state(idict) = DICT_FILESCANNED;
+}
+
+void scale_img(image * img)
+{
+ integer x, y, xr, yr; /* size and resolution of image */
+ scaled w, h; /* indeed size corresponds to image resolution */
+ integer default_res;
+ assert(img != NULL);
+ image_dict *idict = img_dict(img);
+ assert(idict != NULL);
+ x = img_xsize(idict); /* dimensions, resolutions from image file */
+ y = img_ysize(idict);
+ xr = img_xres(idict);
+ yr = img_yres(idict);
+ if ((img_transform(img) & 1) == 1) {
+ int tmp = x;
+ x = y;
+ y = tmp;
+ tmp = xr;
+ xr = yr;
+ yr = tmp;
+ }
+ if (xr > 65535 || yr > 65535) {
+ xr = 0;
+ yr = 0;
+ pdftex_warn("ext1: too large image resolution ignored");
+ }
+ if (x <= 0 || y <= 0 || xr < 0 || yr < 0)
+ pdftex_fail("ext1: invalid image dimensions");
+ if (img_type(idict) == IMAGE_TYPE_PDF) {
+ w = x;
+ h = y;
+ } else {
+ default_res = fix_int(get_pdf_image_resolution(), 0, 65535);
+ if (default_res > 0 && (xr == 0 || yr == 0)) {
+ xr = default_res;
+ yr = default_res;
+ }
+ if (is_wd_running(img) && is_ht_running(img)) {
+ if (xr > 0 && yr > 0) {
+ w = ext_xn_over_d(one_hundred_inch, x, 100 * xr);
+ h = ext_xn_over_d(one_hundred_inch, y, 100 * yr);
+ } else {
+ w = ext_xn_over_d(one_hundred_inch, x, 7200);
+ h = ext_xn_over_d(one_hundred_inch, y, 7200);
+ }
+ }
+ }
+ if (is_wd_running(img) && is_ht_running(img) && is_dp_running(img)) {
+ img_width(img) = w;
+ img_height(img) = h;
+ img_depth(img) = 0;
+ } else if (is_wd_running(img)) {
+ /* image depth or height is explicitly specified */
+ if (is_ht_running(img)) {
+ /* image depth is explicitly specified */
+ img_width(img) = ext_xn_over_d(h, x, y);
+ img_height(img) = h - img_depth(img);
+ } else if (is_dp_running(img)) {
+ /* image height is explicitly specified */
+ img_width(img) = ext_xn_over_d(img_height(img), x, y);
+ img_depth(img) = 0;
+ } else {
+ /* both image depth and height are explicitly specified */
+ img_width(img) =
+ ext_xn_over_d(img_height(img) + img_depth(img), x, y);
+ }
+ } else {
+ /* image width is explicitly specified */
+ if (is_ht_running(img) && is_dp_running(img)) {
+ /* both image depth and height are not specified */
+ img_height(img) = ext_xn_over_d(img_width(img), y, x);
+ img_depth(img) = 0;
+ }
+ /* image depth is explicitly specified */
+ else if (is_ht_running(img)) {
+ img_height(img) =
+ ext_xn_over_d(img_width(img), y, x) - img_depth(img);
+ }
+ /* image height is explicitly specified */
+ else if (is_dp_running(img)) {
+ img_depth(img) = 0;
+ }
+ /* else both image depth and height are explicitly specified */
+ }
+ img_set_scaled(img);
+}
+
+void out_img(image * img, scaled hpos, scaled vpos)
+{
+ float a[7]; /* transformation matrix (todo: indices should be reduced!) */
+ int r; /* number of digits after the decimal point */
+ assert(img != 0);
+ image_dict *idict = img_dict(img);
+ assert(idict != 0);
+ scaled wd = img_width(img);
+ scaled ht = img_height(img);
+ scaled dp = img_depth(img);
+ if (img_type(idict) == IMAGE_TYPE_PDF) {
+ a[1] = wd * 1.0e6 / img_xsize(idict);
+ a[2] = 0;
+ a[3] = 0;
+ a[4] = (ht + dp) * 1.0e6 / img_ysize(idict);
+ a[5] = hpos -
+ (float) wd *bp2int(img_pdf_orig_x(idict)) / img_xsize(idict);
+ a[6] = vpos -
+ (float) ht *bp2int(img_pdf_orig_y(idict)) / img_ysize(idict);
+ r = 6;
+ } else {
+ a[1] = wd * 1.0e6 / one_hundred_bp;
+ a[2] = 0;
+ a[3] = 0;
+ a[4] = (ht + dp) * 1.0e6 / one_hundred_bp;
+ a[5] = hpos;
+ a[6] = vpos;
+ r = 4;
+ }
+ if ((img_transform(img) & 1) == 1) {
+ if (ht == -dp)
+ pdftex_fail("image transform: division by zero (height == -depth)");
+ if (wd == 0)
+ pdftex_fail("image transform: division by zero (width == 0)");
+ }
+ switch (img_transform(img) & 7) {
+ case 0: /* unrotated */
+ break;
+ case 1: /* rot. 90 deg. (counterclockwise) */
+ a[2] = a[1] * (ht + dp) / wd;
+ a[1] = 0;
+ a[3] = -a[4] * wd / (ht + dp);
+ a[4] = 0;
+ a[5] += wd;
+ break;
+ case 2: /* rot. 180 deg. */
+ a[1] = -a[1];
+ a[4] = -a[4];
+ a[5] += wd;
+ a[6] += ht + dp;
+ break;
+ case 3: /* rot. 270 deg. */
+ a[2] = -a[1] * (ht + dp) / wd;
+ a[1] = 0;
+ a[3] = a[4] * wd / (ht + dp);
+ a[4] = 0;
+ a[6] += ht + dp;
+ break;
+ case 4: /* mirrored, unrotated */
+ a[1] = -a[1];
+ a[5] += wd;
+ break;
+ case 5: /* mirrored, then rot. 90 deg. */
+ a[2] = -a[1] * (ht + dp) / wd;
+ a[1] = 0;
+ a[3] = -a[4] * wd / (ht + dp);
+ a[4] = 0;
+ a[5] += wd;
+ a[6] += ht + dp;
+ break;
+ case 6: /* mirrored, then rot. 180 deg. */
+ a[4] = -a[4];
+ a[6] += ht + dp;
+ break;
+ case 7: /* mirrored, then rot. 270 deg. */
+ a[2] = a[1] * (ht + dp) / wd;
+ a[1] = 0;
+ a[3] = a[4] * wd / (ht + dp);
+ a[4] = 0;
+ break;
+ default:
+ assert(0);
+ }
+ pdf_end_text();
+ pdf_printf("q\n");
+ pdf_print_real((integer) a[1], r);
+ pdfout(' ');
+ pdf_print_real((integer) a[2], r);
+ pdfout(' ');
+ pdf_print_real((integer) a[3], r);
+ pdfout(' ');
+ pdf_print_real((integer) a[4], r);
+ pdfout(' ');
+ pdf_print_bp((integer) a[5]);
+ pdfout(' ');
+ pdf_print_bp((integer) a[6]);
+ pdf_printf(" cm\n/Im");
+ pdf_print_int(img_index(idict));
+ pdf_print_resname_prefix();
+ pdf_printf(" Do\nQ\n");
+ if (img_state(idict) < DICT_OUTIMG)
+ img_state(idict) = DICT_OUTIMG;
+}
+
+void write_img(image_dict * idict)
+{
+ assert(idict != NULL);
+ if (img_state(idict) < DICT_WRITTEN) {
+ if (tracefilenames)
+ tex_printf(" <%s", img_filepath(idict));
+ switch (img_type(idict)) {
+ case IMAGE_TYPE_PNG:
+ write_png(idict);
+ break;
+ case IMAGE_TYPE_JPG:
+ write_jpg(idict);
+ break;
+ case IMAGE_TYPE_JBIG2:
+ write_jbig2(idict);
+ break;
+ case IMAGE_TYPE_PDF:
+ write_epdf(idict);
+ break;
+ default:
+ pdftex_fail("internal error: unknown image type");
+ }
+ if (tracefilenames)
+ tex_printf(">");
+ }
+ if (img_state(idict) < DICT_WRITTEN)
+ img_state(idict) = DICT_WRITTEN;
+}
+
+/**********************************************************************/
+
+typedef image *img_entry;
+/* define img_ptr, img_array, & img_limit */
+define_array(img); /* array of pointers to image structures */
+
+integer img_to_array(image * img)
+{
+ assert(img != NULL);
+ alloc_array(img, 1, SMALL_BUF_SIZE);
+ *img_ptr = img;
+ return img_ptr++ - img_array; /* now img is read-only */
+}
+
+/**********************************************************************/
+/* stuff to be accessible from TeX */
+
+integer read_image(integer objnum, integer index, strnumber filename,
+ integer page_num,
+ strnumber attr,
+ strnumber page_name,
+ integer colorspace, integer page_box,
+ integer pdf_minor_version, integer pdf_inclusion_errorlevel)
+{
+ integer ref;
+ image *a = new_image();
+ ref = img_to_array(a);
+ image_dict *idict = img_dict(a) = new_image_dict();
+ assert(idict != NULL);
+ img_objnum(idict) = objnum;
+ img_index(idict) = index;
+ /* img_xsize, img_ysize, img_xres, img_yres set by read_img() */
+ img_colorspace(idict) = colorspace;
+ img_pagenum(idict) = page_num;
+ /* img_totalpages set by read_img() */
+ if (page_name != 0)
+ img_pagename(idict) = xstrdup(makecstring(page_name));
+ cur_file_name = makecfilename(filename);
+ assert(cur_file_name != NULL);
+ img_filename(idict) = xstrdup(cur_file_name);
+ if (attr != 0)
+ img_attr(idict) = xstrdup(makecstring(attr));
+ img_pagebox(idict) = page_box;
+ read_img(idict, pdf_minor_version, pdf_inclusion_errorlevel);
+ img_unset_scaled(a);
+ img_set_refered(a);
+ return ref;
+}
+
+void set_image_dimensions(integer ref, integer wd, integer ht, integer dp)
+{
+ image *a = img_array[ref];
+ img_width(a) = wd;
+ img_height(a) = ht;
+ img_depth(a) = dp;
+}
+
+void scale_image(integer ref)
+{
+ scale_img(img_array[ref]);
+}
+
+void out_image(integer ref, scaled hpos, scaled vpos)
+{
+ image *a = img_array[ref];
+ out_img(a, hpos, vpos);
+}
+
+void write_image(integer ref)
+{
+ write_img(img_dict(img_array[ref]));
+}
+
+integer image_pages(integer ref)
+{
+ return img_totalpages(img_dict(img_array[ref]));
+}
+
+integer image_colordepth(integer ref)
+{
+ return img_colordepth(img_dict(img_array[ref]));
+}
+
+integer epdf_orig_x(integer ref)
+{
+ return bp2int(img_pdf_orig_x(img_dict(img_array[ref])));
+}
+
+integer epdf_orig_y(integer ref)
+{
+ return bp2int(img_pdf_orig_y(img_dict(img_array[ref])));
+}
+
+integer image_objnum(integer ref)
+{
+ return img_objnum(img_dict(img_array[ref]));
+}
+
+integer image_index(integer ref)
+{
+ return img_index(img_dict(img_array[ref]));
+}
+
+integer image_width(integer ref)
+{
+ return img_width(img_array[ref]);
+}
+
+integer image_height(integer ref)
+{
+ return img_height(img_array[ref]);
+}
+
+integer image_depth(integer ref)
+{
+ return img_depth(img_array[ref]);
+}
+
+void update_image_procset(integer ref)
+{
+ pdf_image_procset |= img_color(img_dict(img_array[ref]));
+}
+
+/**********************************************************************/
+
+boolean check_image_b(integer procset)
+{
+ return procset & IMAGE_COLOR_B;
+}
+
+boolean check_image_c(integer procset)
+{
+ return procset & IMAGE_COLOR_C;
+}
+
+boolean check_image_i(integer procset)
+{
+ return procset & IMAGE_COLOR_I;
+}
diff --git a/Build/source/texk/web2c/luatexdir/image/writejbig2.c b/Build/source/texk/web2c/luatexdir/image/writejbig2.c
new file mode 100644
index 00000000000..d50ed88c485
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/writejbig2.c
@@ -0,0 +1,749 @@
+/***********************************************************************
+Copyright (c) 2002-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your option)
+any later version.
+
+pdfTeX is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with pdfTeX; if not, write to the Free Software Foundation, Inc., 59
+Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+This is experimental JBIG2 image support to pdfTeX. JBIG2 image decoding
+is part of Adobe PDF-1.4, and requires Acroread 5.0 or later.
+
+References
+==========
+
+* 14492 FCD: Information technology -- coded representation of picture
+and audio information -- lossy/lossless coding of bi-level images /
+JBIG committee, 1999 July 16. This JBIG2 Working Draft is available from
+http://www.jpeg.org/public/fcd14492.pdf. The references in the C-code
+correspond to the sections of this document.
+
+* PDF Reference, 5th edition, version 1.6, 1985--2005 Adobe Systems
+Incorporated. Available online:
+
+http://partners.adobe.com/public/developer/en/pdf/PDFReference16.pdf
+
+News
+====
+
+31 May 2006: no need to wait for endoffileflag in sequential access
+organization.
+
+10 May 2006: ygetc() for some catching of broken JBIG2 files; modify to
+accept Example 3.4 from PDFRef 5th ed. with short end-of-file segment.
+
+09 May 2006: pages_maketree() and segments_maketree() by AVL tree,
+some cleaning up.
+
+06 May 2006: File list replaced by AVL tree; new_fileinfo(),
+new_pageinfo().
+
+04 May 2006: Updated for pdftex-1.40-beta-20060213.
+
+08 Jan. 2003: Added flushjbig2page0objects() function. Now at the end
+of the pdfTeX run all pending page0 objects are written out.
+
+08 Jan. 2003: Release on private webpage.
+
+04 Jan. 2003: Completely rewritten. Now with some data structures.
+Rudimentary local file and image bookkeeping. Multiple image inclusion
+from one JBIG2 file. Only required page0 segments are marked for
+inclusion.
+
+13 Nov. 2002: pdfcrypting removed.
+
+08 Dec. 2002: bug in page 0 stream writing repaired.
+Strategy for multiple page inclusion from same JBIG2 file: When writing
+1st image, create fresh PDF object for page 0, and include any page
+0 segments from complete file (even if these segments are not needed
+for image). When writing next image, check by filename comparison if
+PDF object for page 0 of this JBIG2 file has already been written. This
+can only remember the file name for the direct predecessor JBIG2 image
+(but images of other types might come inbetween). If such page 0 PDF
+object exists, reference it. Else create fresh one.
+
+09 Dec. 2002: JBIG2 seg. page numbers > 0 are now set to 1, see PDF Ref.
+
+$Id: writejbig2.c 1027 2008-02-14 21:01:03Z hhenkel $
+***********************************************************************/
+
+#include "writejbig2.h"
+#undef DEBUG
+
+/**********************************************************************/
+
+struct avl_table *file_tree = NULL;
+
+static int comp_file_entry(const void *pa, const void *pb, void *p)
+{
+ return strcmp(((const FILEINFO *) pa)->filepath,
+ ((const FILEINFO *) pb)->filepath);
+}
+
+static int comp_page_entry(const void *pa, const void *pb, void *p)
+{
+ return ((const PAGEINFO *) pa)->pagenum - ((const PAGEINFO *) pb)->pagenum;
+}
+
+static int comp_segment_entry(const void *pa, const void *pb, void *p)
+{
+ return ((const SEGINFO *) pa)->segnum - ((const SEGINFO *) pb)->segnum;
+}
+
+/**********************************************************************/
+
+int ygetc(FILE * stream)
+{
+ int c = getc(stream);
+ if (c < 0) {
+ if (c == EOF)
+ pdftex_fail("getc() failed; premature end of JBIG2 image file");
+ else
+ pdftex_fail("getc() failed (can't happen)");
+ }
+ return c;
+}
+
+/**********************************************************************/
+
+FILEINFO *new_fileinfo()
+{
+ FILEINFO *fip;
+ fip = xtalloc(1, FILEINFO);
+ fip->file = NULL;
+ fip->filepath = NULL;
+ fip->filesize = 0;
+ initlinkedlist(&(fip->pages));
+ initlinkedlist(&(fip->page0));
+ fip->filehdrflags = 0;
+ fip->sequentialaccess = false;
+ fip->numofpages = 0;
+ fip->streamstart = 0;
+ fip->pdfpage0objnum = 0;
+ fip->phase = INITIAL;
+ return fip;
+}
+
+PAGEINFO *new_pageinfo()
+{
+ PAGEINFO *pip;
+ pip = xtalloc(1, PAGEINFO);
+ initlinkedlist(&(pip->segments));
+ pip->pagenum = 0;
+ pip->width = 0;
+ pip->height = 0;
+ pip->xres = 0;
+ pip->yres = 0;
+ pip->pagesegmentflags = 0;
+ pip->stripinginfo = 0;
+ pip->stripedheight = 0;
+ return pip;
+}
+
+void init_seginfo(SEGINFO * sip)
+{
+ sip->segnum = 0;
+ sip->isrefered = false;
+ sip->refers = false;
+ sip->seghdrflags = 0;
+ sip->pageassocsizeflag = false;
+ sip->reftosegcount = 0;
+ sip->countofrefered = 0;
+ sip->fieldlen = 0;
+ sip->segnumwidth = 0;
+ sip->segpage = 0;
+ sip->segdatalen = 0;
+ sip->hdrstart = 0;
+ sip->hdrend = 0;
+ sip->datastart = 0;
+ sip->dataend = 0;
+ sip->endofstripeflag = false;
+ sip->endofpageflag = false;
+ sip->pageinfoflag = false;
+ sip->endoffileflag = false;
+}
+
+/**********************************************************************/
+
+void initlinkedlist(LIST * lp)
+{
+ lp->first = NULL;
+ lp->last = NULL;
+ lp->tree = NULL;
+}
+
+LIST *litem_append(LIST * lp)
+{
+ LITEM *ip;
+ ip = xtalloc(1, LITEM);
+ if (lp->first == NULL) {
+ lp->first = ip;
+ ip->prev = NULL;
+ } else {
+ lp->last->next = ip;
+ ip->prev = lp->last;
+ }
+ lp->last = ip;
+ ip->next = NULL;
+ ip->d = NULL;
+ return lp;
+}
+
+/**********************************************************************/
+
+void pages_maketree(LIST * plp)
+{
+ LITEM *ip;
+ void **aa;
+ assert(plp->tree == NULL);
+ plp->tree = avl_create(comp_page_entry, NULL, &avl_xallocator);
+ assert(plp->tree != NULL);
+ for (ip = plp->first; ip != NULL; ip = ip->next) {
+ aa = avl_probe(plp->tree, (PAGEINFO *) ip->d);
+ assert(aa != NULL);
+ }
+}
+
+void segments_maketree(LIST * slp)
+{
+ LITEM *ip;
+ void **aa;
+ assert(slp->tree == NULL);
+ slp->tree = avl_create(comp_segment_entry, NULL, &avl_xallocator);
+ assert(slp->tree != NULL);
+ for (ip = slp->first; ip != NULL; ip = ip->next) {
+ aa = avl_probe(slp->tree, (SEGINFO *) ip->d);
+ assert(aa != NULL);
+ }
+}
+
+/**********************************************************************/
+
+PAGEINFO *find_pageinfo(LIST * plp, unsigned long pagenum)
+{
+ PAGEINFO tmp;
+ tmp.pagenum = pagenum;
+ assert(plp->tree != NULL);
+ return (PAGEINFO *) avl_find(plp->tree, &tmp);
+}
+
+SEGINFO *find_seginfo(LIST * slp, unsigned long segnum)
+{
+ SEGINFO tmp;
+ tmp.segnum = segnum;
+ assert(slp->tree != NULL);
+ return (SEGINFO *) avl_find(slp->tree, &tmp);
+}
+
+/**********************************************************************/
+
+unsigned int read2bytes(FILE * f)
+{
+ unsigned int c = ygetc(f);
+ return (c << 8) + ygetc(f);
+}
+
+unsigned long read4bytes(FILE * f)
+{
+ unsigned int l = read2bytes(f);
+ return (l << 16) + read2bytes(f);
+}
+
+/**********************************************************************/
+
+unsigned long getstreamlen(LITEM * slip, boolean refer)
+{
+ SEGINFO *sip;
+ unsigned long len = 0;
+ for (; slip != NULL; slip = slip->next) {
+ sip = slip->d;
+ if (refer || sip->isrefered)
+ len += sip->hdrend - sip->hdrstart + sip->dataend - sip->datastart;
+ }
+ return len;
+}
+
+/**********************************************************************/
+
+void readfilehdr(FILEINFO * fip)
+{
+ unsigned int i;
+ /* Annex D.4 File header syntax */
+ /* Annex D.4.1 ID string */
+ unsigned char jbig2_id[] = { 0x97, 'J', 'B', '2', 0x0d, 0x0a, 0x1a, 0x0a };
+ xfseek(fip->file, 0, SEEK_SET, fip->filepath);
+ for (i = 0; i < 8; i++)
+ if (ygetc(fip->file) != jbig2_id[i])
+ pdftex_fail
+ ("readfilehdr(): reading JBIG2 image file failed: ID string missing");
+ /* Annex D.4.2 File header flags */
+ fip->filehdrflags = ygetc(fip->file);
+ fip->sequentialaccess = (fip->filehdrflags & 0x01) ? true : false;
+ if (fip->sequentialaccess) { /* Annex D.1 vs. Annex D.2 */
+ xfseek(fip->file, 0, SEEK_END, fip->filepath);
+ fip->filesize = xftell(fip->file, fip->filepath);
+ xfseek(fip->file, 9, SEEK_SET, fip->filepath);
+ }
+ /* Annex D.4.3 Number of pages */
+ if (!(fip->filehdrflags >> 1) & 0x01) /* known number of pages */
+ fip->numofpages = read4bytes(fip->file);
+ /* --- at end of file header --- */
+}
+
+/**********************************************************************/
+/* for first reading of file; return value tells if header been read */
+
+boolean readseghdr(FILEINFO * fip, SEGINFO * sip)
+{
+ unsigned int i;
+ sip->hdrstart = xftell(fip->file, fip->filepath);
+ if (fip->sequentialaccess && sip->hdrstart == fip->filesize)
+ return false; /* no endoffileflag is ok for sequentialaccess */
+#ifdef DEBUG
+ printf("\nhdrstart %d\n", sip->hdrstart);
+#endif
+ /* 7.2.2 Segment number */
+ sip->segnum = read4bytes(fip->file);
+#ifdef DEBUG
+ printf(" segnum %d\n", sip->segnum);
+#endif
+ /* 7.2.3 Segment header flags */
+ sip->seghdrflags = ygetc(fip->file);
+#ifdef DEBUG
+ printf(" hdrflags %d\n", sip->seghdrflags & 0x3f);
+#endif
+ checkseghdrflags(sip);
+ if (fip->sequentialaccess && sip->endoffileflag) /* accept shorter segment, */
+ return true; /* makes it compliant with Example 3.4 of PDFRef. 5th ed. */
+ sip->pageassocsizeflag = ((sip->seghdrflags >> 6) & 0x01) ? true : false;
+ /* 7.2.4 Referred-to segment count and retention flags */
+ sip->reftosegcount = (unsigned int) ygetc(fip->file);
+ sip->countofrefered = sip->reftosegcount >> 5;
+ if (sip->countofrefered < 5)
+ sip->fieldlen = 1;
+ else {
+ sip->fieldlen = 5 + sip->countofrefered / 8;
+ xfseek(fip->file, sip->fieldlen - 1, SEEK_CUR, fip->filepath);
+ }
+ /* 7.2.5 Referred-to segment numbers */
+ if (sip->segnum <= 256)
+ sip->segnumwidth = 1;
+ else if (sip->segnum <= 65536)
+ sip->segnumwidth = 2;
+ else
+ sip->segnumwidth = 4;
+ for (i = 0; i < sip->countofrefered; i++) {
+ switch (sip->segnumwidth) {
+ case 1:
+ (void) ygetc(fip->file);
+ break;
+ case 2:
+ (void) read2bytes(fip->file);
+ break;
+ case 4:
+ (void) read4bytes(fip->file);
+ break;
+ }
+ }
+ /* 7.2.6 Segment page association */
+ if (sip->pageassocsizeflag)
+ sip->segpage = read4bytes(fip->file);
+ else
+ sip->segpage = ygetc(fip->file);
+ /* 7.2.7 Segment data length */
+ sip->segdatalen = read4bytes(fip->file);
+ sip->hdrend = xftell(fip->file, fip->filepath);
+ /* ---- at end of segment header ---- */
+ return true;
+}
+
+/**********************************************************************/
+/* for writing, marks refered page0 segments, sets segpage > 0 to 1 */
+
+void writeseghdr(FILEINFO * fip, SEGINFO * sip)
+{
+ unsigned int i;
+ unsigned long referedseg = 0;
+ /* 7.2.2 Segment number */
+ /* 7.2.3 Segment header flags */
+ /* 7.2.4 Referred-to segment count and retention flags */
+ for (i = 0; i < 5 + sip->fieldlen; i++)
+ pdfout(ygetc(fip->file));
+ /* 7.2.5 Referred-to segment numbers */
+ for (i = 0; i < sip->countofrefered; i++) {
+ switch (sip->segnumwidth) {
+ case 1:
+ referedseg = ygetc(fip->file);
+ pdfout(referedseg);
+ break;
+ case 2:
+ referedseg = read2bytes(fip->file);
+ pdfout((referedseg >> 8) & 0xff);
+ pdfout(referedseg & 0xff);
+ break;
+ case 4:
+ referedseg = read4bytes(fip->file);
+ pdfout((referedseg >> 24) & 0xff);
+ pdfout((referedseg >> 16) & 0xff);
+ pdfout((referedseg >> 8) & 0xff);
+ pdfout(referedseg & 0xff);
+ break;
+ }
+ if (fip->page0.last != NULL && !sip->refers)
+ markpage0seg(fip, referedseg);
+ }
+ if (sip->countofrefered > 0)
+ sip->refers = true;
+ /* 7.2.6 Segment page association */
+ if (sip->pageassocsizeflag)
+ for (i = 0; i < 3; i++) {
+ (void) ygetc(fip->file);
+ pdfout(0);
+ }
+ (void) ygetc(fip->file);
+ pdfout((sip->segpage > 0) ? 1 : 0);
+ /* 7.2.7 Segment data length */
+ for (i = 0; i < 4; i++)
+ pdfout(ygetc(fip->file));
+ /* ---- at end of segment header ---- */
+}
+
+/**********************************************************************/
+/* for recursive marking of refered page0 segments */
+
+void checkseghdr(FILEINFO * fip, SEGINFO * sip)
+{
+ unsigned int i;
+ unsigned long referedseg = 0;
+ /* 7.2.2 Segment number */
+ /* 7.2.3 Segment header flags */
+ /* 7.2.4 Referred-to segment count and retention flags */
+ xfseek(fip->file, 5 + sip->fieldlen, SEEK_CUR, fip->filepath);
+ /* 7.2.5 Referred-to segment numbers */
+ for (i = 0; i < sip->countofrefered; i++) {
+ switch (sip->segnumwidth) {
+ case 1:
+ referedseg = ygetc(fip->file);
+ break;
+ case 2:
+ referedseg = read2bytes(fip->file);
+ break;
+ case 4:
+ referedseg = read4bytes(fip->file);
+ break;
+ }
+ if (!sip->refers)
+ markpage0seg(fip, referedseg);
+ }
+ if (sip->countofrefered > 0)
+ sip->refers = true;
+ /* 7.2.6 Segment page association */
+ /* 7.2.7 Segment data length */
+ if (sip->pageassocsizeflag)
+ xfseek(fip->file, 8, SEEK_CUR, fip->filepath);
+ else
+ xfseek(fip->file, 5, SEEK_CUR, fip->filepath);
+ /* ---- at end of segment header ---- */
+}
+
+/**********************************************************************/
+
+void checkseghdrflags(SEGINFO * sip)
+{
+ sip->endofstripeflag = false;
+ sip->endofpageflag = false;
+ sip->pageinfoflag = false;
+ sip->endoffileflag = false;
+ /* 7.3 Segment types */
+ switch (sip->seghdrflags & 0x3f) {
+ case M_SymbolDictionary:
+ case M_IntermediateTextRegion:
+ case M_ImmediateTextRegion:
+ case M_ImmediateLosslessTextRegion:
+ case M_PatternDictionary:
+ case M_IntermediateHalftoneRegion:
+ case M_ImmediateHalftoneRegion:
+ case M_ImmediateLosslessHalftoneRegion:
+ case M_IntermediateGenericRegion:
+ case M_ImmediateGenericRegion:
+ case M_ImmediateLosslessGenericRegion:
+ case M_IntermediateGenericRefinementRegion:
+ case M_ImmediateGenericRefinementRegion:
+ case M_ImmediateLosslessGenericRefinementRegion:
+ break;
+ case M_PageInformation:
+ sip->pageinfoflag = true;
+ break;
+ case M_EndOfPage:
+ sip->endofpageflag = true;
+ break;
+ case M_EndOfStripe:
+ sip->endofstripeflag = true;
+ break;
+ case M_EndOfFile:
+ sip->endoffileflag = true;
+ break;
+ case M_Profiles:
+ case M_Tables:
+ case M_Extension:
+ break;
+ default:
+ pdftex_fail
+ ("checkseghdrflags(): unknown segment type in JBIG2 image file");
+ break;
+ }
+}
+
+/**********************************************************************/
+
+void markpage0seg(FILEINFO * fip, unsigned long referedseg)
+{
+ PAGEINFO *pip;
+ SEGINFO *sip;
+ pip = fip->page0.first->d;
+ sip = find_seginfo(&(pip->segments), referedseg);
+ if (sip != NULL) {
+ if (!sip->refers && sip->countofrefered > 0)
+ checkseghdr(fip, sip);
+ sip->isrefered = true;
+ }
+}
+
+/**********************************************************************/
+
+unsigned long findstreamstart(FILEINFO * fip)
+{
+ SEGINFO tmp;
+ assert(!fip->sequentialaccess); /* D.2 Random-access organisation */
+ do /* find random-access stream start */
+ (void) readseghdr(fip, &tmp);
+ while (!tmp.endoffileflag);
+ fip->streamstart = tmp.hdrend;
+ readfilehdr(fip);
+ return fip->streamstart;
+}
+
+/**********************************************************************/
+
+void rd_jbig2_info(FILEINFO * fip)
+{
+ unsigned long seekdist = 0; /* for sequential-access only */
+ unsigned long streampos = 0; /* for random-access only */
+ unsigned long currentpage = 0;
+ boolean sipavail = false;
+ PAGEINFO *pip;
+ SEGINFO *sip = NULL;
+ LIST *plp, *slp;
+ fip->file = xfopen(fip->filepath, FOPEN_RBIN_MODE);
+ readfilehdr(fip);
+ if (!fip->sequentialaccess) /* D.2 Random-access organisation */
+ streampos = findstreamstart(fip);
+ while (true) { /* loop over segments */
+ if (!sipavail) {
+ sip = xtalloc(1, SEGINFO);
+ sipavail = true;
+ }
+ init_seginfo(sip);
+ if (!readseghdr(fip, sip) || sip->endoffileflag)
+ break;
+ if (sip->segpage > 0) {
+ if (sip->segpage > currentpage) {
+ plp = litem_append(&(fip->pages));
+ plp->last->d = new_pageinfo();
+ currentpage = sip->segpage;
+ }
+ pip = fip->pages.last->d;
+ } else {
+ if (fip->page0.last == NULL) {
+ plp = litem_append(&(fip->page0));
+ plp->last->d = new_pageinfo();
+ }
+ pip = fip->page0.last->d;
+ }
+ if (!sip->endofpageflag) {
+ slp = litem_append(&(pip->segments));
+ slp->last->d = sip;
+ sipavail = false;
+ }
+ if (!fip->sequentialaccess)
+ sip->datastart = streampos;
+ else
+ sip->datastart = sip->hdrend;
+ sip->dataend = sip->datastart + sip->segdatalen;
+ if (!fip->sequentialaccess
+ && (sip->pageinfoflag || sip->endofstripeflag))
+ xfseek(fip->file, sip->datastart, SEEK_SET, fip->filepath);
+ seekdist = sip->segdatalen;
+ /* 7.4.8 Page information segment syntax */
+ if (sip->pageinfoflag) {
+ pip->pagenum = sip->segpage;
+ pip->width = read4bytes(fip->file);
+ pip->height = read4bytes(fip->file);
+ pip->xres = read4bytes(fip->file);
+ pip->yres = read4bytes(fip->file);
+ pip->pagesegmentflags = ygetc(fip->file);
+ /* 7.4.8.6 Page striping information */
+ pip->stripinginfo = read2bytes(fip->file);
+ seekdist -= 19;
+ }
+ if (sip->endofstripeflag) {
+ pip->stripedheight = read4bytes(fip->file);
+ seekdist -= 4;
+ }
+ if (!fip->sequentialaccess
+ && (sip->pageinfoflag || sip->endofstripeflag))
+ xfseek(fip->file, sip->hdrend, SEEK_SET, fip->filepath);
+ if (!fip->sequentialaccess)
+ streampos += sip->segdatalen;
+ if (fip->sequentialaccess)
+ xfseek(fip->file, seekdist, SEEK_CUR, fip->filepath);
+ if (sip->endofpageflag && currentpage && (pip->stripinginfo >> 15))
+ pip->height = pip->stripedheight;
+ }
+ fip->phase = HAVEINFO;
+ if (sipavail)
+ xfree(sip);
+ xfclose(fip->file, fip->filepath);
+}
+
+/**********************************************************************/
+
+void wr_jbig2(FILEINFO * fip, unsigned long page)
+{
+ LITEM *slip;
+ PAGEINFO *pip;
+ SEGINFO *sip;
+ unsigned long i;
+ if (page > 0) {
+ pip = find_pageinfo(&(fip->pages), page);
+ assert(pip != NULL);
+ pdf_puts("/Type /XObject\n/Subtype /Image\n");
+ pdf_printf("/Width %i\n", pip->width);
+ pdf_printf("/Height %i\n", pip->height);
+ pdf_puts("/ColorSpace /DeviceGray\n");
+ pdf_puts("/BitsPerComponent 1\n");
+ pdf_printf("/Length %lu\n", getstreamlen(pip->segments.first, true));
+ pdf_puts("/Filter [/JBIG2Decode]\n");
+ if (fip->page0.last != NULL) {
+ if (fip->pdfpage0objnum == 0) {
+ pdf_create_obj(0, 0);
+ fip->pdfpage0objnum = obj_ptr;
+ }
+ pdf_printf("/DecodeParms [<< /JBIG2Globals %lu 0 R >>]\n",
+ fip->pdfpage0objnum);
+ }
+ } else {
+ pip = find_pageinfo(&(fip->page0), page);
+ assert(pip != NULL);
+ pdf_begin_dict(fip->pdfpage0objnum, 0);
+ pdf_printf("/Length %lu\n", getstreamlen(pip->segments.first, false));
+ }
+ pdf_puts(">>\n");
+ pdf_puts("stream\n");
+ fip->file = xfopen(fip->filepath, FOPEN_RBIN_MODE);
+ for (slip = pip->segments.first; slip != NULL; slip = slip->next) { /* loop over page segments */
+ sip = slip->d;
+ if (sip->isrefered || page > 0) {
+ xfseek(fip->file, sip->hdrstart, SEEK_SET, fip->filepath);
+ /* mark refered-to page 0 segments, change segpages > 1 to 1 */
+ writeseghdr(fip, sip);
+ xfseek(fip->file, sip->datastart, SEEK_SET, fip->filepath);
+ for (i = sip->datastart; i < sip->dataend; i++)
+ pdfout(ygetc(fip->file));
+ }
+ }
+ pdf_end_stream();
+ xfclose(fip->file, fip->filepath);
+}
+
+/**********************************************************************/
+
+void read_jbig2_info(image_dict * idict)
+{
+ FILEINFO *fip, tmp;
+ PAGEINFO *pip;
+ void **aa;
+ assert(idict != NULL);
+ img_type(idict) = IMAGE_TYPE_JBIG2;
+ if (img_pagenum(idict) < 1)
+ pdftex_fail
+ ("read_jbig2_info(): page %d not in JBIG2 image file; page must be > 0",
+ (int) img_pagenum(idict));
+ if (file_tree == NULL) {
+ file_tree = avl_create(comp_file_entry, NULL, &avl_xallocator);
+ assert(file_tree != NULL);
+ }
+ tmp.filepath = img_filepath(idict);
+ fip = (FILEINFO *) avl_find(file_tree, &tmp);
+ if (fip == NULL) {
+ fip = new_fileinfo();
+ fip->filepath = xstrdup(img_filepath(idict));
+ aa = avl_probe(file_tree, fip);
+ assert(aa != NULL);
+ }
+ if (fip->phase == INITIAL) {
+ rd_jbig2_info(fip);
+ pages_maketree(&(fip->pages));
+ if (fip->page0.last != NULL) {
+ pages_maketree(&(fip->page0));
+ pip = fip->page0.first->d;
+ segments_maketree(&(pip->segments));
+ }
+ }
+ pip = find_pageinfo(&(fip->pages), img_pagenum(idict));
+ if (pip == NULL)
+ pdftex_fail("read_jbig2_info(): page %d not found in JBIG2 image file",
+ (int) img_pagenum(idict));
+ img_xsize(idict) = pip->width;
+ img_ysize(idict) = pip->height;
+ img_xres(idict) = (int) (pip->xres * 0.0254 + 0.5);
+ img_yres(idict) = (int) (pip->yres * 0.0254 + 0.5);
+ img_colordepth(idict) = 1;
+}
+
+/**********************************************************************/
+
+void write_jbig2(image_dict * idict)
+{
+ FILEINFO *fip, tmp;
+ PAGEINFO *pip;
+ assert(idict != NULL);
+ assert(file_tree != NULL);
+ tmp.filepath = img_filepath(idict);
+ fip = (FILEINFO *) avl_find(file_tree, &tmp);
+ assert(fip != NULL);
+ assert(fip->phase == HAVEINFO); /* don't write before rd_jbig2_info() call */
+ pip = find_pageinfo(&(fip->pages), img_pagenum(idict));
+ assert(pip != NULL);
+ wr_jbig2(fip, pip->pagenum);
+ img_file(idict) = NULL;
+}
+
+/**********************************************************************/
+
+void flush_jbig2_page0_objects()
+{
+ FILEINFO *fip;
+ struct avl_traverser t;
+ if (file_tree != NULL) {
+ avl_t_init(&t, file_tree);
+ for (fip = avl_t_first(&t, file_tree); fip != NULL;
+ fip = avl_t_next(&t)) {
+ if (fip->page0.last != NULL)
+ wr_jbig2(fip, 0);
+ }
+ }
+}
+
+/**********************************************************************/
diff --git a/Build/source/texk/web2c/luatexdir/image/writejbig2.h b/Build/source/texk/web2c/luatexdir/image/writejbig2.h
new file mode 100644
index 00000000000..c1bec32d859
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/writejbig2.h
@@ -0,0 +1,151 @@
+/***********************************************************************
+Copyright (c) 2002-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your option)
+any later version.
+
+pdfTeX is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with pdfTeX; if not, write to the Free Software Foundation, Inc., 59
+Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+This is experimental JBIG2 image support to pdfTeX. JBIG2 image decoding
+is part of Adobe PDF-1.4, and requires Acroread 5.0 or later.
+
+$Id: writejbig2.h 1012 2008-02-14 00:00:57Z oneiros $
+***********************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include "ptexlib.h"
+#include "ptexmac.h"
+#include "image.h"
+
+/* 7.3 Segment types */
+#define M_SymbolDictionary 0
+#define M_IntermediateTextRegion 4
+#define M_ImmediateTextRegion 6
+#define M_ImmediateLosslessTextRegion 7
+#define M_PatternDictionary 16
+#define M_IntermediateHalftoneRegion 20
+#define M_ImmediateHalftoneRegion 22
+#define M_ImmediateLosslessHalftoneRegion 23
+#define M_IntermediateGenericRegion 36
+#define M_ImmediateGenericRegion 38
+#define M_ImmediateLosslessGenericRegion 39
+#define M_IntermediateGenericRefinementRegion 40
+#define M_ImmediateGenericRefinementRegion 42
+#define M_ImmediateLosslessGenericRefinementRegion 43
+#define M_PageInformation 48
+#define M_EndOfPage 49
+#define M_EndOfStripe 50
+#define M_EndOfFile 51
+#define M_Profiles 52
+#define M_Tables 53
+#define M_Extension 62
+
+/**********************************************************************/
+
+typedef enum { INITIAL, HAVEINFO, WRITEPDF } PHASE;
+
+typedef struct _LITEM {
+ struct _LITEM *prev;
+ struct _LITEM *next;
+ void *d; /* data */
+} LITEM;
+
+typedef struct _LIST {
+ LITEM *first;
+ LITEM *last;
+ struct avl_table *tree;
+} LIST;
+
+typedef struct _SEGINFO {
+ unsigned long segnum;
+ boolean isrefered;
+ boolean refers;
+ unsigned int seghdrflags; /* set by readseghdr() */
+ boolean pageassocsizeflag; /* set by readseghdr() */
+ unsigned int reftosegcount; /* set by readseghdr() */
+ unsigned int countofrefered; /* set by readseghdr() */
+ unsigned int fieldlen; /* set by readseghdr() */
+ unsigned int segnumwidth; /* set by readseghdr() */
+ long segpage; /* set by readseghdr() */
+ unsigned long segdatalen; /* set by readseghdr() */
+ unsigned long hdrstart; /* set by readseghdr() */
+ unsigned long hdrend; /* set by readseghdr() */
+ unsigned long datastart;
+ unsigned long dataend;
+ boolean endofstripeflag; /* set by checkseghdrflags() */
+ boolean endofpageflag; /* set by checkseghdrflags() */
+ boolean pageinfoflag; /* set by checkseghdrflags() */
+ boolean endoffileflag; /* set by checkseghdrflags() */
+} SEGINFO;
+
+typedef struct _PAGEINFO {
+ LIST segments; /* segments associated with page */
+ unsigned long pagenum;
+ unsigned int width;
+ unsigned int height;
+ unsigned int xres;
+ unsigned int yres;
+ unsigned int pagesegmentflags;
+ unsigned int stripinginfo;
+ unsigned int stripedheight;
+} PAGEINFO;
+
+typedef struct _FILEINFO {
+ FILE *file;
+ char *filepath;
+ long filesize;
+ LIST pages; /* not including page0 */
+ LIST page0;
+ unsigned int filehdrflags; /* set by readfilehdr() */
+ boolean sequentialaccess; /* set by readfilehdr() */
+ unsigned long numofpages; /* set by readfilehdr() */
+ unsigned long streamstart; /* set by get_jbig2_info() */
+ unsigned long pdfpage0objnum;
+ PHASE phase;
+} FILEINFO;
+
+/**********************************************************************/
+
+static int comp_file_entry(const void *, const void *, void *);
+static int comp_page_entry(const void *, const void *, void *);
+static int comp_segment_entry(const void *, const void *, void *);
+int ygetc(FILE *);
+FILEINFO *new_fileinfo();
+PAGEINFO *new_pageinfo();
+void initseginfo(SEGINFO *);
+void initlinkedlist(LIST *);
+LIST *litem_append(LIST *);
+void pages_maketree(LIST *);
+void segments_maketree(LIST *);
+PAGEINFO *find_pageinfo(LIST *, unsigned long);
+SEGINFO *find_seginfo(LIST *, unsigned long);
+unsigned int read2bytes(FILE *);
+unsigned long read4bytes(FILE *);
+unsigned long getstreamlen(LITEM *, boolean);
+void readfilehdr(FILEINFO *);
+boolean readseghdr(FILEINFO *, SEGINFO *);
+void writeseghdr(FILEINFO *, SEGINFO *);
+void checkseghdr(FILEINFO *, SEGINFO *);
+void checkseghdrflags(SEGINFO * sip);
+void markpage0seg(FILEINFO *, unsigned long);
+unsigned long findstreamstart(FILEINFO *);
+void rd_jbig2_info(FILEINFO *);
+void wr_jbig2(FILEINFO *, unsigned long);
+void read_jbig2_info(image_dict *);
+void write_jbig2(image_dict *);
+void flushjbig2page0objects();
+
+/**********************************************************************/
diff --git a/Build/source/texk/web2c/luatexdir/image/writejpg.c b/Build/source/texk/web2c/luatexdir/image/writejpg.c
new file mode 100644
index 00000000000..422c29470fb
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/writejpg.c
@@ -0,0 +1,277 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writejpg.c 1100 2008-03-09 13:40:48Z hhenkel $
+*/
+
+#include <assert.h>
+#include "ptexlib.h"
+#include "image.h"
+
+#define JPG_GRAY 1 /* Gray color space, use /DeviceGray */
+#define JPG_RGB 3 /* RGB color space, use /DeviceRGB */
+#define JPG_CMYK 4 /* CMYK color space, use /DeviceCMYK */
+
+typedef enum { /* JPEG marker codes */
+ M_SOF0 = 0xc0, /* baseline DCT */
+ M_SOF1 = 0xc1, /* extended sequential DCT */
+ M_SOF2 = 0xc2, /* progressive DCT */
+ M_SOF3 = 0xc3, /* lossless (sequential) */
+
+ M_SOF5 = 0xc5, /* differential sequential DCT */
+ M_SOF6 = 0xc6, /* differential progressive DCT */
+ M_SOF7 = 0xc7, /* differential lossless */
+
+ M_JPG = 0xc8, /* JPEG extensions */
+ M_SOF9 = 0xc9, /* extended sequential DCT */
+ M_SOF10 = 0xca, /* progressive DCT */
+ M_SOF11 = 0xcb, /* lossless (sequential) */
+
+ M_SOF13 = 0xcd, /* differential sequential DCT */
+ M_SOF14 = 0xce, /* differential progressive DCT */
+ M_SOF15 = 0xcf, /* differential lossless */
+
+ M_DHT = 0xc4, /* define Huffman tables */
+
+ M_DAC = 0xcc, /* define arithmetic conditioning table */
+
+ M_RST0 = 0xd0, /* restart */
+ M_RST1 = 0xd1, /* restart */
+ M_RST2 = 0xd2, /* restart */
+ M_RST3 = 0xd3, /* restart */
+ M_RST4 = 0xd4, /* restart */
+ M_RST5 = 0xd5, /* restart */
+ M_RST6 = 0xd6, /* restart */
+ M_RST7 = 0xd7, /* restart */
+
+ M_SOI = 0xd8, /* start of image */
+ M_EOI = 0xd9, /* end of image */
+ M_SOS = 0xda, /* start of scan */
+ M_DQT = 0xdb, /* define quantization tables */
+ M_DNL = 0xdc, /* define number of lines */
+ M_DRI = 0xdd, /* define restart interval */
+ M_DHP = 0xde, /* define hierarchical progression */
+ M_EXP = 0xdf, /* expand reference image(s) */
+
+ M_APP0 = 0xe0, /* application marker, used for JFIF */
+ M_APP1 = 0xe1, /* application marker */
+ M_APP2 = 0xe2, /* application marker */
+ M_APP3 = 0xe3, /* application marker */
+ M_APP4 = 0xe4, /* application marker */
+ M_APP5 = 0xe5, /* application marker */
+ M_APP6 = 0xe6, /* application marker */
+ M_APP7 = 0xe7, /* application marker */
+ M_APP8 = 0xe8, /* application marker */
+ M_APP9 = 0xe9, /* application marker */
+ M_APP10 = 0xea, /* application marker */
+ M_APP11 = 0xeb, /* application marker */
+ M_APP12 = 0xec, /* application marker */
+ M_APP13 = 0xed, /* application marker */
+ M_APP14 = 0xee, /* application marker, used by Adobe */
+ M_APP15 = 0xef, /* application marker */
+
+ M_JPG0 = 0xf0, /* reserved for JPEG extensions */
+ M_JPG13 = 0xfd, /* reserved for JPEG extensions */
+ M_COM = 0xfe, /* comment */
+
+ M_TEM = 0x01, /* temporary use */
+
+ M_ERROR = 0x100 /* dummy marker, internal use only */
+} JPEG_MARKER;
+
+static JPG_UINT16 read2bytes(FILE * f)
+{
+ int c = xgetc(f);
+ return (c << 8) + xgetc(f);
+}
+
+void close_and_cleanup_jpg(image_dict * idict)
+{
+ assert(idict != NULL);
+ assert(img_file(idict) != NULL);
+ assert(img_filepath(idict) != NULL);
+ xfclose(img_file(idict), img_filepath(idict));
+ img_file(idict) = NULL;
+ assert(img_jpg_ptr(idict) != NULL);
+ xfree(img_jpg_ptr(idict));
+ img_jpg_ptr(idict) = NULL;
+}
+
+void read_jpg_info(image_dict * idict, img_readtype_e readtype)
+{
+ int i, units = 0;
+ unsigned char jpg_id[] = "JFIF";
+ assert(idict != NULL);
+ assert(img_type(idict) == IMAGE_TYPE_JPG);
+ img_totalpages(idict) = 1;
+ img_pagenum(idict) = 1;
+ img_xres(idict) = img_yres(idict) = 0;
+ assert(img_file(idict) == NULL);
+ img_file(idict) = xfopen(img_filepath(idict), FOPEN_RBIN_MODE);
+ assert(img_jpg_ptr(idict) == NULL);
+ img_jpg_ptr(idict) = xtalloc(1, jpg_img_struct);
+ xfseek(img_file(idict), 0, SEEK_END, img_filepath(idict));
+ img_jpg_ptr(idict)->length = xftell(img_file(idict), img_filepath(idict));
+ xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict));
+ if (read2bytes(img_file(idict)) != 0xFFD8)
+ pdftex_fail("reading JPEG image failed (no JPEG header found)");
+ /* currently only true JFIF files allow extracting img_xres and img_yres */
+ if (read2bytes(img_file(idict)) == 0xFFE0) { /* check for JFIF */
+ (void) read2bytes(img_file(idict));
+ for (i = 0; i < 5; i++) {
+ if (xgetc(img_file(idict)) != jpg_id[i])
+ break;
+ }
+ if (i == 5) { /* it's JFIF */
+ read2bytes(img_file(idict));
+ units = xgetc(img_file(idict));
+ img_xres(idict) = read2bytes(img_file(idict));
+ img_yres(idict) = read2bytes(img_file(idict));
+ switch (units) {
+ case 1:
+ break; /* pixels per inch */
+ case 2:
+ img_xres(idict) *= 2.54;
+ img_yres(idict) *= 2.54;
+ break; /* pixels per cm */
+ default:
+ img_xres(idict) = img_yres(idict) = 0;
+ break;
+ }
+ }
+ }
+ xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict));
+ while (1) {
+ if (feof(img_file(idict)))
+ pdftex_fail("reading JPEG image failed (premature file end)");
+ if (fgetc(img_file(idict)) != 0xFF)
+ pdftex_fail("reading JPEG image failed (no marker found)");
+ switch (xgetc(img_file(idict))) {
+ case M_SOF5:
+ case M_SOF6:
+ case M_SOF7:
+ case M_SOF9:
+ case M_SOF10:
+ case M_SOF11:
+ case M_SOF13:
+ case M_SOF14:
+ case M_SOF15:
+ pdftex_fail("unsupported type of compression");
+ case M_SOF2:
+ if (fixed_pdf_minor_version <= 2)
+ pdftex_fail("cannot use progressive DCT with PDF-1.2");
+ case M_SOF0:
+ case M_SOF1:
+ case M_SOF3:
+ (void) read2bytes(img_file(idict)); /* read segment length */
+ img_colordepth(idict) = xgetc(img_file(idict));
+ img_ysize(idict) = read2bytes(img_file(idict));
+ img_xsize(idict) = read2bytes(img_file(idict));
+ img_jpg_color(idict) = xgetc(img_file(idict));
+ xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict));
+ switch (img_jpg_color(idict)) {
+ case JPG_GRAY:
+ img_color(idict) = IMAGE_COLOR_B;
+ break;
+ case JPG_RGB:
+ img_color(idict) = IMAGE_COLOR_C;
+ break;
+ case JPG_CMYK:
+ img_color(idict) = IMAGE_COLOR_C;
+ break;
+ default:
+ pdftex_fail("Unsupported color space %i",
+ (int) img_jpg_color(idict));
+ }
+ if (readtype == IMG_CLOSEINBETWEEN)
+ close_and_cleanup_jpg(idict);
+ return;
+ case M_SOI: /* ignore markers without parameters */
+ case M_EOI:
+ case M_TEM:
+ case M_RST0:
+ case M_RST1:
+ case M_RST2:
+ case M_RST3:
+ case M_RST4:
+ case M_RST5:
+ case M_RST6:
+ case M_RST7:
+ break;
+ default: /* skip variable length markers */
+ xfseek(img_file(idict), read2bytes(img_file(idict)) - 2,
+ SEEK_CUR, img_filepath(idict));
+ break;
+ }
+ }
+ assert(0);
+}
+
+static void reopen_jpg(image_dict * idict)
+{
+ integer width, height, xres, yres;
+ width = img_xsize(idict);
+ height = img_ysize(idict);
+ xres = img_xres(idict);
+ yres = img_yres(idict);
+ read_jpg_info(idict, IMG_KEEPOPEN);
+ if (width != img_xsize(idict) || height != img_ysize(idict)
+ || xres != img_xres(idict) || yres != img_yres(idict))
+ pdftex_fail("writejpg: image dimensions have changed");
+}
+
+void write_jpg(image_dict * idict)
+{
+ long unsigned l;
+ FILE *f;
+ assert(idict != NULL);
+ if (img_file(idict) == NULL)
+ reopen_jpg(idict);
+ assert(img_jpg_ptr(idict) != NULL);
+ pdf_puts("/Type /XObject\n/Subtype /Image\n");
+ if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
+ pdf_printf("%s\n", img_attr(idict));
+ pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n/Length %i\n",
+ (int) img_xsize(idict),
+ (int) img_ysize(idict),
+ (int) img_colordepth(idict), (int) img_jpg_ptr(idict)->length);
+ pdf_puts("/ColorSpace ");
+ if (img_colorspace(idict) != 0) {
+ pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
+ } else {
+ switch (img_jpg_color(idict)) {
+ case JPG_GRAY:
+ pdf_puts("/DeviceGray\n");
+ break;
+ case JPG_RGB:
+ pdf_puts("/DeviceRGB\n");
+ break;
+ case JPG_CMYK:
+ pdf_puts("/DeviceCMYK\n/Decode [1 0 1 0 1 0 1 0]\n");
+ break;
+ default:
+ pdftex_fail("Unsupported color space %i",
+ (int) img_jpg_color(idict));
+ }
+ }
+ pdf_puts("/Filter /DCTDecode\n>>\nstream\n");
+ for (l = img_jpg_ptr(idict)->length, f = img_file(idict); l > 0; l--)
+ pdfout(xgetc(f));
+ pdf_end_stream();
+ close_and_cleanup_jpg(idict);
+}
diff --git a/Build/source/texk/web2c/luatexdir/image/writepng.c b/Build/source/texk/web2c/luatexdir/image/writepng.c
new file mode 100644
index 00000000000..7f1269d9943
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/writepng.c
@@ -0,0 +1,635 @@
+/*
+Copyright (c) 1996-2004 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writepng.c 1101 2008-03-09 16:12:15Z hhenkel $
+*/
+
+#include <assert.h>
+#include "ptexlib.h"
+#include "image.h"
+
+void close_and_cleanup_png(image_dict * idict)
+{
+ assert(idict != NULL);
+ assert(img_file(idict) != NULL);
+ assert(img_filepath(idict) != NULL);
+ xfclose(img_file(idict), img_filepath(idict));
+ img_file(idict) = NULL;
+ assert(img_png_ptr(idict) != NULL);
+ png_destroy_read_struct(&(img_png_png_ptr(idict)),
+ &(img_png_info_ptr(idict)), NULL);
+ xfree(img_png_ptr(idict));
+ img_png_ptr(idict) = NULL;
+}
+
+void read_png_info(image_dict * idict, img_readtype_e readtype)
+{
+ double gamma;
+ png_structp png_p;
+ png_infop info_p;
+ assert(idict != NULL);
+ assert(img_type(idict) == IMAGE_TYPE_PNG);
+ img_totalpages(idict) = 1;
+ img_pagenum(idict) = 1;
+ img_xres(idict) = img_yres(idict) = 0;
+ assert(img_file(idict) == NULL);
+ img_file(idict) = xfopen(img_filepath(idict), FOPEN_RBIN_MODE);
+ assert(img_png_ptr(idict) == NULL);
+ img_png_ptr(idict) = xtalloc(1, png_img_struct);
+ if ((png_p = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL)) == NULL)
+ pdftex_fail("libpng: png_create_read_struct() failed");
+ img_png_png_ptr(idict) = png_p;
+ if ((info_p = png_create_info_struct(png_p)) == NULL)
+ pdftex_fail("libpng: png_create_info_struct() failed");
+ img_png_info_ptr(idict) = info_p;
+ if (setjmp(png_p->jmpbuf))
+ pdftex_fail("libpng: internal error");
+ png_init_io(png_p, img_file(idict));
+ png_read_info(png_p, info_p);
+ /* simple transparency support */
+ if (png_get_valid(png_p, info_p, PNG_INFO_tRNS)) {
+ png_set_tRNS_to_alpha(png_p);
+ }
+ /* alpha channel support */
+ if (fixed_pdf_minor_version < 4 && png_p->color_type | PNG_COLOR_MASK_ALPHA)
+ png_set_strip_alpha(png_p);
+ /* 16bit depth support */
+ if (fixed_pdf_minor_version < 5)
+ fixed_image_hicolor = 0;
+ if (info_p->bit_depth == 16 && !fixed_image_hicolor)
+ png_set_strip_16(png_p);
+ /* gamma support */
+ if (fixed_image_apply_gamma) {
+ if (png_get_gAMA(png_p, info_p, &gamma))
+ png_set_gamma(png_p, (fixed_gamma / 1000.0), gamma);
+ else
+ png_set_gamma(png_p, (fixed_gamma / 1000.0),
+ (1000.0 / fixed_image_gamma));
+ }
+ /* reset structure */
+ png_read_update_info(png_p, info_p);
+ /* resolution support */
+ img_xsize(idict) = info_p->width;
+ img_ysize(idict) = info_p->height;
+ if (info_p->valid & PNG_INFO_pHYs) {
+ img_xres(idict) =
+ round(0.0254 * png_get_x_pixels_per_meter(png_p, info_p));
+ img_yres(idict) =
+ round(0.0254 * png_get_y_pixels_per_meter(png_p, info_p));
+ }
+ switch (info_p->color_type) {
+ case PNG_COLOR_TYPE_PALETTE:
+ img_color(idict) = IMAGE_COLOR_C | IMAGE_COLOR_I;
+ break;
+ case PNG_COLOR_TYPE_GRAY:
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ img_color(idict) = IMAGE_COLOR_B;
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ img_color(idict) = IMAGE_COLOR_C;
+ break;
+ default:
+ pdftex_fail("unsupported type of color_type <%i>", info_p->color_type);
+ }
+ img_colordepth(idict) = info_p->bit_depth;
+ if (readtype == IMG_CLOSEINBETWEEN)
+ close_and_cleanup_png(idict);
+}
+
+#define write_gray_pixel_16(r) \
+ if (j % 4 == 0||j % 4 == 1) pdf_buf[pdf_ptr++] = *r++; \
+ else smask[smask_ptr++] = *r++
+
+#define write_gray_pixel_8(r) \
+ if (j % 2 == 0) pdf_buf[pdf_ptr++] = *r++; \
+ else smask[smask_ptr++] = *r++
+
+
+#define write_rgb_pixel_16(r) \
+ if (!(j % 8 == 6||j % 8 == 7)) pdf_buf[pdf_ptr++] = *r++; \
+ else smask[smask_ptr++] = *r++
+
+#define write_rgb_pixel_8(r) \
+ if (j % 4 != 3) pdf_buf[pdf_ptr++] = *r++; \
+ else smask[smask_ptr++] = *r++
+
+#define write_simple_pixel(r) pdf_buf[pdf_ptr++] = *r++
+
+#define write_noninterlaced(outmac) \
+ for (i = 0; (unsigned) i < (int)info_p->height; i++) { \
+ png_read_row(png_p, row, NULL); \
+ r = row; \
+ k = info_p->rowbytes; \
+ while(k > 0) { \
+ l = (k > pdf_buf_size)? pdf_buf_size : k; \
+ pdfroom(l); \
+ for (j = 0; j < l; j++) { \
+ outmac; \
+ } \
+ k -= l; \
+ } \
+ }
+
+#define write_interlaced(outmac) \
+ for (i = 0; (unsigned) i < (int)info_p->height; i++) { \
+ row = rows[i]; \
+ k = info_p->rowbytes; \
+ while(k > 0) { \
+ l = (k > pdf_buf_size)? pdf_buf_size : k;\
+ pdfroom(l); \
+ for (j = 0; j < l; j++) { \
+ outmac; \
+ } \
+ k -= l; \
+ } \
+ xfree(rows[i]); \
+ }
+
+void write_png_palette(image_dict * idict)
+{
+ int i, j, k, l;
+ png_structp png_p = img_png_png_ptr(idict);
+ png_infop info_p = img_png_info_ptr(idict);
+ png_bytep row, r, *rows;
+ integer palette_objnum = 0;
+ if (img_colorspace(idict) != 0) {
+ pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
+ } else {
+ pdf_create_obj(0, 0);
+ palette_objnum = obj_ptr;
+ pdf_printf("[/Indexed /DeviceRGB %i %i 0 R]\n",
+ (int) (info_p->num_palette - 1), (int) palette_objnum);
+ }
+ pdf_begin_stream();
+ if (info_p->interlace_type == PNG_INTERLACE_NONE) {
+ row = xtalloc(info_p->rowbytes, png_byte);
+ write_noninterlaced(write_simple_pixel(r));
+ xfree(row);
+ } else {
+ if (info_p->height * info_p->rowbytes >= 10240000L)
+ pdftex_warn
+ ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
+ rows = xtalloc(info_p->height, png_bytep);
+ for (i = 0; (unsigned) i < info_p->height; i++)
+ rows[i] = xtalloc(info_p->rowbytes, png_byte);
+ png_read_image(png_p, rows);
+ write_interlaced(write_simple_pixel(row));
+ xfree(rows);
+ }
+ pdf_end_stream();
+ if (palette_objnum > 0) {
+ pdf_begin_dict(palette_objnum, 0);
+ pdf_begin_stream();
+ for (i = 0; (unsigned) i < info_p->num_palette; i++) {
+ pdfroom(3);
+ pdf_buf[pdf_ptr++] = info_p->palette[i].red;
+ pdf_buf[pdf_ptr++] = info_p->palette[i].green;
+ pdf_buf[pdf_ptr++] = info_p->palette[i].blue;
+ }
+ pdf_end_stream();
+ }
+}
+
+void write_png_gray(image_dict * idict)
+{
+ int i, j, k, l;
+ png_structp png_p = img_png_png_ptr(idict);
+ png_infop info_p = img_png_info_ptr(idict);
+ png_bytep row, r, *rows;
+ if (img_colorspace(idict) != 0) {
+ pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
+ } else {
+ pdf_puts("/DeviceGray\n");
+ }
+ pdf_begin_stream();
+ if (info_p->interlace_type == PNG_INTERLACE_NONE) {
+ row = xtalloc(info_p->rowbytes, png_byte);
+ write_noninterlaced(write_simple_pixel(r));
+ xfree(row);
+ } else {
+ if (info_p->height * info_p->rowbytes >= 10240000L)
+ pdftex_warn
+ ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
+ rows = xtalloc(info_p->height, png_bytep);
+ for (i = 0; (unsigned) i < info_p->height; i++)
+ rows[i] = xtalloc(info_p->rowbytes, png_byte);
+ png_read_image(png_p, rows);
+ write_interlaced(write_simple_pixel(row));
+ xfree(rows);
+ }
+ pdf_end_stream();
+}
+
+void write_png_gray_alpha(image_dict * idict)
+{
+ int i, j, k, l;
+ png_structp png_p = img_png_png_ptr(idict);
+ png_infop info_p = img_png_info_ptr(idict);
+ png_bytep row, r, *rows;
+ integer smask_objnum = 0;
+ png_bytep smask;
+ integer smask_ptr = 0;
+ integer smask_size = 0;
+ int bitdepth;
+ if (img_colorspace(idict) != 0) {
+ pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
+ } else {
+ pdf_puts("/DeviceGray\n");
+ }
+ pdf_create_obj(0, 0);
+ smask_objnum = obj_ptr;
+ pdf_printf("/SMask %i 0 R\n", (int) smask_objnum);
+ smask_size = (info_p->rowbytes / 2) * info_p->height;
+ smask = xtalloc(smask_size, png_byte);
+ pdf_begin_stream();
+ if (info_p->interlace_type == PNG_INTERLACE_NONE) {
+ row = xtalloc(info_p->rowbytes, png_byte);
+ if ((info_p->bit_depth == 16) && fixed_image_hicolor) {
+ write_noninterlaced(write_gray_pixel_16(r));
+ } else {
+ write_noninterlaced(write_gray_pixel_8(r));
+ }
+ xfree(row);
+ } else {
+ if (info_p->height * info_p->rowbytes >= 10240000L)
+ pdftex_warn
+ ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
+ rows = xtalloc(info_p->height, png_bytep);
+ for (i = 0; (unsigned) i < info_p->height; i++)
+ rows[i] = xtalloc(info_p->rowbytes, png_byte);
+ png_read_image(png_p, rows);
+ if ((info_p->bit_depth == 16) && fixed_image_hicolor) {
+ write_interlaced(write_gray_pixel_16(row));
+ } else {
+ write_interlaced(write_gray_pixel_8(row));
+ }
+ xfree(rows);
+ }
+ pdf_end_stream();
+ pdf_flush();
+ /* now write the Smask object */
+ bitdepth = (int) info_p->bit_depth;
+ pdf_begin_dict(smask_objnum, 0);
+ pdf_puts("/Type /XObject\n/Subtype /Image\n");
+ if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
+ pdf_printf("%s\n", img_attr(idict));
+ pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n",
+ (int) info_p->width,
+ (int) info_p->height, (bitdepth == 16 ? 8 : bitdepth));
+ pdf_puts("/ColorSpace /DeviceGray\n");
+ pdf_begin_stream();
+ for (i = 0; i < smask_size; i++) {
+ if (i % 8 == 0)
+ pdfroom(8);
+ pdf_buf[pdf_ptr++] = smask[i];
+ if (bitdepth == 16)
+ i++;
+ }
+ pdf_end_stream();
+ xfree(smask);
+}
+
+void write_png_rgb(image_dict * idict)
+{
+ int i, j, k, l;
+ png_structp png_p = img_png_png_ptr(idict);
+ png_infop info_p = img_png_info_ptr(idict);
+ png_bytep row, r, *rows;
+ if (img_colorspace(idict) != 0) {
+ pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
+ } else {
+ pdf_puts("/DeviceRGB\n");
+ }
+ pdf_begin_stream();
+ if (info_p->interlace_type == PNG_INTERLACE_NONE) {
+ row = xtalloc(info_p->rowbytes, png_byte);
+ write_noninterlaced(write_simple_pixel(r));
+ xfree(row);
+ } else {
+ if (info_p->height * info_p->rowbytes >= 10240000L)
+ pdftex_warn
+ ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
+ rows = xtalloc(info_p->height, png_bytep);
+ for (i = 0; (unsigned) i < info_p->height; i++)
+ rows[i] = xtalloc(info_p->rowbytes, png_byte);
+ png_read_image(png_p, rows);
+ write_interlaced(write_simple_pixel(row));
+ xfree(rows);
+ }
+ pdf_end_stream();
+}
+
+void write_png_rgb_alpha(image_dict * idict)
+{
+ int i, j, k, l;
+ png_structp png_p = img_png_png_ptr(idict);
+ png_infop info_p = img_png_info_ptr(idict);
+ png_bytep row, r, *rows;
+ integer smask_objnum = 0;
+ png_bytep smask;
+ integer smask_ptr = 0;
+ integer smask_size = 0;
+ int bitdepth;
+ if (img_colorspace(idict) != 0) {
+ pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
+ } else {
+ pdf_puts("/DeviceRGB\n");
+ }
+ pdf_create_obj(0, 0);
+ smask_objnum = obj_ptr;
+ pdf_printf("/SMask %i 0 R\n", (int) smask_objnum);
+ smask_size = (info_p->rowbytes / 2) * info_p->height;
+ smask = xtalloc(smask_size, png_byte);
+ pdf_begin_stream();
+ if (info_p->interlace_type == PNG_INTERLACE_NONE) {
+ row = xtalloc(info_p->rowbytes, png_byte);
+ if ((info_p->bit_depth == 16) && fixed_image_hicolor) {
+ write_noninterlaced(write_rgb_pixel_16(r));
+ } else {
+ write_noninterlaced(write_rgb_pixel_8(r));
+ }
+ xfree(row);
+ } else {
+ if (info_p->height * info_p->rowbytes >= 10240000L)
+ pdftex_warn
+ ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
+ rows = xtalloc(info_p->height, png_bytep);
+ for (i = 0; (unsigned) i < info_p->height; i++)
+ rows[i] = xtalloc(info_p->rowbytes, png_byte);
+ png_read_image(png_p, rows);
+ if ((info_p->bit_depth == 16) && fixed_image_hicolor) {
+ write_interlaced(write_rgb_pixel_16(row));
+ } else {
+ write_interlaced(write_rgb_pixel_8(row));
+ }
+ xfree(rows);
+ }
+ pdf_end_stream();
+ pdf_flush();
+ /* now write the Smask object */
+ if (smask_objnum > 0) {
+ bitdepth = (int) info_p->bit_depth;
+ pdf_begin_dict(smask_objnum, 0);
+ pdf_puts("/Type /XObject\n/Subtype /Image\n");
+ if (img_attr(idict) != NULL)
+ pdf_printf("%s\n", img_attr(idict));
+ pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n",
+ (int) info_p->width,
+ (int) info_p->height, (bitdepth == 16 ? 8 : bitdepth));
+ pdf_puts("/ColorSpace /DeviceGray\n");
+ pdf_begin_stream();
+ for (i = 0; i < smask_size; i++) {
+ if (i % 8 == 0)
+ pdfroom(8);
+ pdf_buf[pdf_ptr++] = smask[i];
+ if (bitdepth == 16)
+ i++;
+ }
+ xfree(smask);
+ pdf_end_stream();
+ }
+}
+
+/**********************************************************************/
+/*
+ * The |copy_png| function is from Hartmut Henkel. The goal is to use
+ * pdf's native FlateDecode support if that is possible.
+ *
+ * Only a subset of the png files allows this, but when possible it
+ * greatly improves inclusion speed.
+ *
+ * Code cheerfully gleaned from Thomas Merz' PDFlib,
+ * file p_png.c "SPNG - Simple PNG"
+ */
+
+static int spng_getint(FILE * fp)
+{
+ unsigned char buf[4];
+ if (fread(buf, 1, 4, fp) != 4)
+ pdftex_fail("writepng: reading chunk type failed");
+ return ((((((int) buf[0] << 8) + buf[1]) << 8) + buf[2]) << 8) + buf[3];
+}
+
+#define SPNG_CHUNK_IDAT 0x49444154
+#define SPNG_CHUNK_IEND 0x49454E44
+
+void copy_png(image_dict * idict)
+{
+ assert(idict != NULL);
+ png_structp png_p = img_png_png_ptr(idict);
+ png_infop info_p = img_png_info_ptr(idict);
+ FILE *fp = (FILE *) png_p->io_ptr;
+ int i, len, type, streamlength = 0;
+ boolean endflag = false;
+ int idat = 0; /* flag to check continuous IDAT chunks sequence */
+ /* 1st pass to find overall stream /Length */
+ if (fseek(fp, 8, SEEK_SET) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed");
+ do {
+ len = spng_getint(fp);
+ type = spng_getint(fp);
+ switch (type) {
+ case SPNG_CHUNK_IEND:
+ endflag = true;
+ break;
+ case SPNG_CHUNK_IDAT:
+ streamlength += len;
+ default:
+ if (fseek(fp, len + 4, SEEK_CUR) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed");
+ }
+ } while (endflag == false);
+ pdf_printf("/Length %d\n", streamlength);
+ pdf_printf("/Filter /FlateDecode\n");
+ pdf_printf("/DecodeParms << ");
+ pdf_printf("/Colors %d ", info_p->color_type == 2 ? 3 : 1);
+ pdf_printf("/Columns %d ", (int) info_p->width);
+ pdf_printf("/BitsPerComponent %i ", (int) info_p->bit_depth);
+ pdf_printf("/Predictor %d ", 10); /* actual predictor defined on line basis */
+ pdf_printf(">>\n>>\nstream\n");
+ /* 2nd pass to copy data */
+ endflag = false;
+ if (fseek(fp, 8, SEEK_SET) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed");
+ do {
+ len = spng_getint(fp);
+ type = spng_getint(fp);
+ switch (type) {
+ case SPNG_CHUNK_IDAT: /* do copy */
+ if (idat == 2)
+ pdftex_fail("writepng: IDAT chunk sequence broken");
+ idat = 1;
+ while (len > 0) {
+ i = (len > pdf_buf_size) ? pdf_buf_size : len;
+ pdfroom(i);
+ fread(&pdf_buf[pdf_ptr], 1, i, fp);
+ pdf_ptr += i;
+ len -= i;
+ }
+ if (fseek(fp, 4, SEEK_CUR) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed");
+ break;
+ case SPNG_CHUNK_IEND: /* done */
+ pdf_end_stream();
+ endflag = true;
+ break;
+ default:
+ if (idat == 1)
+ idat = 2;
+ if (fseek(fp, len + 4, SEEK_CUR) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed");
+ }
+ } while (endflag == false);
+}
+
+void reopen_png(image_dict * idict)
+{
+ integer width, height, xres, yres;
+ width = img_xsize(idict); /* do consistency check */
+ height = img_ysize(idict);
+ xres = img_xres(idict);
+ yres = img_yres(idict);
+ read_png_info(idict, IMG_KEEPOPEN);
+ if (width != img_xsize(idict) || height != img_ysize(idict)
+ || xres != img_xres(idict) || yres != img_yres(idict))
+ pdftex_fail("writepng: image dimensions have changed");
+}
+
+void write_png(image_dict * idict)
+{
+ double gamma, checked_gamma;
+ int i;
+ integer palette_objnum = 0;
+ assert(idict != NULL);
+ if (img_file(idict) == NULL)
+ reopen_png(idict);
+ assert(img_png_ptr(idict) != NULL);
+ png_structp png_p = img_png_png_ptr(idict);
+ png_infop info_p = img_png_info_ptr(idict);
+ if (fixed_pdf_minor_version < 5)
+ fixed_image_hicolor = 0;
+ pdf_puts("/Type /XObject\n/Subtype /Image\n");
+ if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
+ pdf_printf("%s\n", img_attr(idict));
+ pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n",
+ (int) info_p->width,
+ (int) info_p->height, (int) info_p->bit_depth);
+ pdf_puts("/ColorSpace ");
+ checked_gamma = 1.0;
+ if (fixed_image_apply_gamma) {
+ if (png_get_gAMA(png_p, info_p, &gamma)) {
+ checked_gamma = (fixed_gamma / 1000.0) * gamma;
+ } else {
+ checked_gamma =
+ (fixed_gamma / 1000.0) * (1000.0 / fixed_image_gamma);
+ }
+ }
+ /* the switching between |info_p| and |png_p| queries has been trial and error.
+ */
+ if (fixed_pdf_minor_version > 1 && info_p->interlace_type == PNG_INTERLACE_NONE && (png_p->transformations == 0 || png_p->transformations == 0x2000) /* gamma */
+ &&!(png_p->color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
+ png_p->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ && (fixed_image_hicolor || (png_p->bit_depth <= 8))
+ && (checked_gamma <= 1.01 && checked_gamma > 0.99)
+ ) {
+ if (img_colorspace(idict) != 0) {
+ pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
+ } else {
+ switch (info_p->color_type) {
+ case PNG_COLOR_TYPE_PALETTE:
+ pdf_create_obj(0, 0);
+ palette_objnum = obj_ptr;
+ pdf_printf("[/Indexed /DeviceRGB %i %i 0 R]\n",
+ (int) (info_p->num_palette - 1),
+ (int) palette_objnum);
+ break;
+ case PNG_COLOR_TYPE_GRAY:
+ pdf_puts("/DeviceGray\n");
+ break;
+ default: /* RGB */
+ pdf_puts("/DeviceRGB\n");
+ };
+ }
+ if (tracefilenames)
+ tex_printf(" (PNG copy)");
+ copy_png(idict);
+ if (palette_objnum > 0) {
+ pdf_begin_dict(palette_objnum, 0);
+ pdf_begin_stream();
+ for (i = 0; (unsigned) i < info_p->num_palette; i++) {
+ pdfroom(3);
+ pdf_buf[pdf_ptr++] = info_p->palette[i].red;
+ pdf_buf[pdf_ptr++] = info_p->palette[i].green;
+ pdf_buf[pdf_ptr++] = info_p->palette[i].blue;
+ }
+ pdf_end_stream();
+ }
+ } else {
+ if (0) {
+ tex_printf(" PNG copy skipped because: ");
+ if (fixed_image_apply_gamma &&
+ (checked_gamma > 1.01 || checked_gamma < 0.99))
+ tex_printf("gamma delta=%lf ", checked_gamma);
+ if (png_p->transformations != PNG_TRANSFORM_IDENTITY)
+ tex_printf("transform=%lu", (long) png_p->transformations);
+ if ((info_p->color_type != PNG_COLOR_TYPE_GRAY)
+ && (info_p->color_type != PNG_COLOR_TYPE_RGB)
+ && (info_p->color_type != PNG_COLOR_TYPE_PALETTE))
+ tex_printf("colortype ");
+ if (fixed_pdf_minor_version <= 1)
+ tex_printf("version=%d ", (int) fixed_pdf_minor_version);
+ if (info_p->interlace_type != PNG_INTERLACE_NONE)
+ tex_printf("interlaced ");
+ if (info_p->bit_depth > 8)
+ tex_printf("bitdepth=%d ", info_p->bit_depth);
+ if (png_get_valid(png_p, info_p, PNG_INFO_tRNS))
+ tex_printf("simple transparancy ");
+ }
+ switch (info_p->color_type) {
+ case PNG_COLOR_TYPE_PALETTE:
+ write_png_palette(idict);
+ break;
+ case PNG_COLOR_TYPE_GRAY:
+ write_png_gray(idict);
+ break;
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ if (fixed_pdf_minor_version >= 4)
+ write_png_gray_alpha(idict);
+ else
+ write_png_gray(idict);
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ write_png_rgb(idict);
+ break;
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ if (fixed_pdf_minor_version >= 4)
+ write_png_rgb_alpha(idict);
+ else
+ write_png_rgb(idict);
+ break;
+ default:
+ pdftex_fail("unsupported type of color_type <%i>",
+ info_p->color_type);
+ }
+ }
+ pdf_flush();
+ close_and_cleanup_png(idict);
+}
diff --git a/Build/source/texk/web2c/luatexdir/lang/hnjalloc.c b/Build/source/texk/web2c/luatexdir/lang/hnjalloc.c
new file mode 100644
index 00000000000..59d62e2aabb
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lang/hnjalloc.c
@@ -0,0 +1,72 @@
+/* LibHnj is dual licensed under LGPL and MPL. Boilerplate for both
+ * licenses follows.
+ */
+
+/* LibHnj - a library for high quality hyphenation and justification
+ * Copyright (C) 1998 Raph Levien, (C) 2001 ALTLinux, Moscow
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307 USA.
+*/
+
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ *
+ */
+/* wrappers for malloc */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+void *
+hnj_malloc (int size)
+{
+ void *p;
+
+ p = malloc (size);
+ if (p == NULL)
+ {
+ fprintf (stderr, "can't allocate %d bytes\n", size);
+ exit (1);
+ }
+ return p;
+}
+
+void *
+hnj_realloc (void *p, int size)
+{
+ p = realloc (p, size);
+ if (p == NULL)
+ {
+ fprintf (stderr, "can't allocate %d bytes\n", size);
+ exit (1);
+ }
+ return p;
+}
+
+void
+hnj_free (void *p)
+{
+ free (p);
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/lang/hnjalloc.h b/Build/source/texk/web2c/luatexdir/lang/hnjalloc.h
new file mode 100644
index 00000000000..db82fb9c758
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lang/hnjalloc.h
@@ -0,0 +1,46 @@
+/* LibHnj is dual licensed under LGPL and MPL. Boilerplate for both
+ * licenses follows.
+ */
+
+/* LibHnj - a library for high quality hyphenation and justification
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307 USA.
+*/
+
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ *
+ */
+/* wrappers for malloc */
+
+void *
+hnj_malloc (int size);
+
+void *
+hnj_realloc (void *p, int size);
+
+void
+hnj_free (void *p);
+
diff --git a/Build/source/texk/web2c/luatexdir/lang/hyphen.c b/Build/source/texk/web2c/luatexdir/lang/hyphen.c
new file mode 100644
index 00000000000..140cde8d768
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lang/hyphen.c
@@ -0,0 +1,830 @@
+/* Libhnj is dual licensed under LGPL and MPL. Boilerplate for both
+ * licenses follows.
+ */
+
+/* LibHnj - a library for high quality hyphenation and justification
+ * Copyright (C) 1998 Raph Levien,
+ * (C) 2001 ALTLinux, Moscow (http://www.alt-linux.org),
+ * (C) 2001 Peter Novodvorsky (nidd@cs.msu.su)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307 USA.
+*/
+
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ *
+ */
+#include <stdlib.h> /* for NULL, malloc */
+#include <stdio.h> /* for fprintf */
+#include <string.h> /* for strdup */
+#include <stdlib.h> /* for malloc used by substring inclusion*/
+
+#define MAXPATHS 40960
+
+#ifdef UNX
+#include <unistd.h> /* for exit */
+#endif
+
+#include <ctype.h>
+
+/*#define VERBOSE*/
+
+#include "hnjalloc.h"
+#include "hyphen.h"
+
+/* SHOULD BE MOVED TO SEPARATE LIBRARY */
+static unsigned char * hnj_strdup(
+ const unsigned char *s
+) {
+ unsigned char *new;
+ int l;
+
+ l = strlen ((char*)s);
+ new = hnj_malloc (l + 1);
+ memcpy (new, s, l);
+ new[l] = 0;
+ return new;
+}
+
+static int is_utf8_follow(
+ unsigned char c
+) {
+ if (c>=0x80 && c<0xC0) return 1;
+ return 0;
+}
+
+/* --------------------------------------------------------------------
+ *
+ * Type definitions
+ *
+ * --------------------------------------------------------------------
+ */
+
+/* a little bit of a hash table implementation. This simply maps strings
+ to state numbers */
+
+typedef struct _HashTab HashTab;
+typedef struct _HashEntry HashEntry;
+typedef struct _HashIter HashIter;
+typedef union _HashVal HashVal;
+
+/* A cheap, but effective, hack. */
+#define HASH_SIZE 31627
+
+struct _HashTab {
+ HashEntry *entries[HASH_SIZE];
+};
+
+union _HashVal {
+ int state;
+ char* hyppat;
+};
+
+struct _HashEntry {
+ HashEntry *next;
+ unsigned char *key;
+ HashVal u;
+};
+
+struct _HashIter {
+ HashEntry** e;
+ HashEntry* cur;
+ int ndx;
+};
+
+/* State machine */
+typedef struct _HyphenState HyphenState;
+typedef struct _HyphenTrans HyphenTrans;
+#define MAX_CHARS 256
+#define MAX_NAME 20
+
+struct _HyphenDict {
+ int num_states;
+ int pat_length;
+ char cset[MAX_NAME];
+ HyphenState *states;
+ HashTab *patterns;
+ HashTab *merged;
+ HashTab *state_num;
+};
+
+struct _HyphenState {
+ char *match;
+ /*char *repl;*/
+ /*signed char replindex;*/
+ /*signed char replcut;*/
+ int fallback_state;
+ int num_trans;
+ HyphenTrans *trans;
+};
+
+struct _HyphenTrans {
+ int uni_ch;
+ int new_state;
+};
+
+
+/* Combine two right-aligned number patterns, 04000 + 020 becomes 04020*/
+static char *combine(
+ char *expr,
+ const char *subexpr
+) {
+ int l1 = strlen(expr);
+ int l2 = strlen(subexpr);
+ int off = l1-l2;
+ int j;
+ /* this works also for utf8 sequences because the substring is identical
+ * to the last substring-length bytes of expr except for the (single byte)
+ * hyphenation encoders
+ */
+ for (j=0; j<l2; j++) {
+ if (expr[off+j]<subexpr[j]) expr[off+j] = subexpr[j];
+ }
+ return expr;
+}
+
+
+/* --------------------------------------------------------------------
+ * ORIGINAL CODE
+ * --------------------------------------------------------------------
+ */
+
+HashIter* new_HashIter(
+ HashTab* h
+) {
+ HashIter* i = hnj_malloc(sizeof(HashIter));
+ i->e = h->entries;
+ i->cur = NULL;
+ i->ndx = -1;
+ return i;
+}
+
+
+int nextHashStealPattern(
+ HashIter*i,
+ unsigned char**word,
+ char **pattern
+) {
+ while (i->cur==NULL) {
+ if (i->ndx >= HASH_SIZE-1) return 0;
+ i->cur = i->e[++i->ndx];
+ }
+ *word = i->cur->key;
+ *pattern = i->cur->u.hyppat;
+ i->cur->u.hyppat = NULL;
+ i->cur = i->cur->next;
+ return 1;
+}
+
+
+int nextHash(
+ HashIter*i,
+ unsigned char**word
+) {
+ while (i->cur==NULL) {
+ if (i->ndx >= HASH_SIZE-1) return 0;
+ i->cur = i->e[++i->ndx];
+ }
+ *word = i->cur->key;
+ i->cur = i->cur->next;
+ return 1;
+}
+
+
+int eachHash(
+ HashIter*i,
+ unsigned char**word,
+ char**pattern
+) {
+ while (i->cur==NULL) {
+ if (i->ndx >= HASH_SIZE-1) return 0;
+ i->cur = i->e[++i->ndx];
+ }
+ *word = i->cur->key;
+ *pattern = i->cur->u.hyppat;
+ i->cur = i->cur->next;
+ return 1;
+}
+
+
+void delete_HashIter(
+ HashIter*i
+) {
+ hnj_free(i);
+}
+
+
+/* a char* hash function from ASU - adapted from Gtk+ */
+static unsigned int hnj_string_hash (
+ const unsigned char *s
+) {
+ const unsigned char *p;
+ unsigned int h=0, g;
+
+ for (p = s; *p != '\0'; p += 1) {
+ h = ( h << 4 ) + *p;
+ if ( ( g = h & 0xf0000000 ) ) {
+ h = h ^ (g >> 24);
+ h = h ^ g;
+ }
+ }
+ return h /* % M */;
+}
+
+
+/* assumes that key is not already present! */
+static void state_insert(
+ HashTab *hashtab,
+ unsigned char *key,
+ int state
+) {
+ int i;
+ HashEntry *e;
+
+ i = hnj_string_hash (key) % HASH_SIZE;
+ e = hnj_malloc (sizeof(HashEntry));
+ e->next = hashtab->entries[i];
+ e->key = key;
+ e->u.state = state;
+ hashtab->entries[i] = e;
+}
+
+
+/* assumes that key is not already present! */
+static void hyppat_insert(
+ HashTab *hashtab,
+ unsigned char *key,
+ char* hyppat
+) {
+ int i;
+ HashEntry *e;
+
+ i = hnj_string_hash (key) % HASH_SIZE;
+ for (e = hashtab->entries[i]; e; e=e->next) {
+ if (strcmp((char*)e->key,(char*)key)==0) {
+ if (e->u.hyppat) hnj_free(e->u.hyppat);
+ e->u.hyppat = hyppat;
+ hnj_free(key);
+ return;
+ }
+ }
+ e = hnj_malloc (sizeof(HashEntry));
+ e->next = hashtab->entries[i];
+ e->key = key;
+ e->u.hyppat = hyppat;
+ hashtab->entries[i] = e;
+}
+
+
+/* return state if found, otherwise -1 */
+static int state_lookup(
+ HashTab *hashtab,
+ const unsigned char *key
+) {
+ int i;
+ HashEntry *e;
+
+ i = hnj_string_hash (key) % HASH_SIZE;
+ for (e = hashtab->entries[i]; e; e = e->next) {
+ if (!strcmp ((char*)key, (char*)e->key)) {
+ return e->u.state;
+ }
+ }
+ return -1;
+}
+
+
+/* return state if found, otherwise -1 */
+static char* hyppat_lookup(
+ HashTab *hashtab,
+ const unsigned char *chars,
+ int l
+) {
+ int i;
+ HashEntry *e;
+ unsigned char key[128]; /* should be ample*/
+ strncpy((char*)key,(char*)chars,l); key[l]=0;
+ i = hnj_string_hash (key) % HASH_SIZE;
+ for (e = hashtab->entries[i]; e; e = e->next) {
+ if (!strcmp ((char*)key, (char*)e->key)) {
+ return e->u.hyppat;
+ }
+ }
+ return NULL;
+}
+
+
+/* Get the state number, allocating a new state if necessary. */
+static int hnj_get_state(
+ HyphenDict *dict,
+ const unsigned char *string,
+ int *state_num
+) {
+ *state_num = state_lookup(dict->state_num, string);
+
+ if (*state_num >= 0)
+ return *state_num;
+
+ state_insert(dict->state_num, hnj_strdup(string), dict->num_states);
+ /* predicate is true if dict->num_states is a power of two */
+ if (!(dict->num_states & (dict->num_states - 1))) {
+ dict->states = hnj_realloc(
+ dict->states,
+ (dict->num_states << 1) * sizeof(HyphenState));
+ }
+ dict->states[dict->num_states].match = NULL;
+ dict->states[dict->num_states].fallback_state = -1;
+ dict->states[dict->num_states].num_trans = 0;
+ dict->states[dict->num_states].trans = NULL;
+ return dict->num_states++;
+}
+
+
+/* add a transition from state1 to state2 through ch - assumes that the
+ transition does not already exist */
+static void hnj_add_trans(
+ HyphenDict *dict,
+ int state1,
+ int state2,
+ int uni_ch
+) {
+ int num_trans;
+ /* TH: this test was a bit too strict, it is quite normal for old
+ patterns to have chars in the range 0-31 or 127-159 (inclusive).
+ To ease the transition, let's only disallow NUL for now
+ (this is probably a requirement of the code anyway).
+ */
+ if (uni_ch==0) {
+ fprintf(stderr,"Character out of bounds: u%04x \n",uni_ch);
+ exit(1);
+ }
+ num_trans = dict->states[state1].num_trans;
+ if (num_trans == 0) {
+ dict->states[state1].trans = hnj_malloc(sizeof(HyphenTrans));
+ } else if (!(num_trans & (num_trans - 1))) {
+ dict->states[state1].trans = hnj_realloc(
+ dict->states[state1].trans,
+ (num_trans << 1) * sizeof(HyphenTrans));
+ }
+ dict->states[state1].trans[num_trans].uni_ch = uni_ch;
+ dict->states[state1].trans[num_trans].new_state = state2;
+ dict->states[state1].num_trans++;
+}
+
+
+#ifdef VERBOSE
+
+static unsigned char *get_state_str(
+ int state
+) {
+ int i;
+ HashEntry *e;
+
+ for (i = 0; i < HASH_SIZE; i++)
+ for (e = global->entries[i]; e; e = e->next)
+ if (e->u.state == state)
+ return e->key;
+ return NULL;
+}
+#endif
+
+
+/* I've changed the semantics a bit here: hnj_hyphen_load used to
+ operate on a file, but now the argument is a string buffer.
+ */
+
+static const unsigned char* next_pattern(
+ size_t* length,
+ const unsigned char **buf
+) {
+ const unsigned char *rover = *buf;
+ while (*rover && isspace(*rover)) rover++;
+ const unsigned char *here = rover;
+ while (*rover) {
+ if (isspace(*rover)) {
+ *length = rover-here;
+ *buf = rover;
+ return here;
+ }
+ rover++;
+ }
+ *length = rover-here;
+ *buf = rover;
+ return *length ? here : NULL; /* zero sensed */
+}
+
+static void init_hash(
+ HashTab**h
+) {
+ if (*h) return;
+ int i;
+ *h = hnj_malloc(sizeof(HashTab));
+ for (i = 0; i < HASH_SIZE; i++) (*h)->entries[i] = NULL;
+}
+
+
+static void clear_state_hash(
+ HashTab**h
+) {
+ if (*h==NULL) return;
+ int i;
+ for (i = 0; i < HASH_SIZE; i++) {
+ HashEntry *e, *next;
+ for (e = (*h)->entries[i]; e; e = next) {
+ next = e->next;
+ hnj_free (e->key);
+ hnj_free (e);
+ }
+ }
+ hnj_free(*h);
+ *h=NULL;
+}
+
+
+static void clear_hyppat_hash(
+ HashTab**h
+) {
+ if (*h==NULL) return;
+ int i;
+ for (i = 0; i < HASH_SIZE; i++) {
+ HashEntry *e, *next;
+ for (e = (*h)->entries[i]; e; e = next) {
+ next = e->next;
+ hnj_free(e->key);
+ if (e->u.hyppat) hnj_free(e->u.hyppat);
+ hnj_free(e);
+ }
+ }
+ hnj_free(*h);
+ *h=NULL;
+}
+
+
+static void init_dict(
+ HyphenDict* dict
+) {
+ dict->num_states = 1;
+ dict->pat_length = 0;
+ dict->states = hnj_malloc (sizeof(HyphenState));
+ dict->states[0].match = NULL;
+ dict->states[0].fallback_state = -1;
+ dict->states[0].num_trans = 0;
+ dict->states[0].trans = NULL;
+ dict->patterns = NULL;
+ dict->merged = NULL;
+ dict->state_num = NULL;
+ init_hash(&dict->patterns);
+}
+
+
+static void clear_dict(
+ HyphenDict* dict
+) {
+ int state_num;
+ for (state_num = 0; state_num < dict->num_states; state_num++) {
+ HyphenState *hstate = &dict->states[state_num];
+ if (hstate->match) hnj_free (hstate->match);
+ if (hstate->trans) hnj_free (hstate->trans);
+ }
+ hnj_free (dict->states);
+ clear_hyppat_hash(&dict->patterns);
+ clear_hyppat_hash(&dict->merged);
+ clear_state_hash(&dict->state_num);
+}
+
+
+
+HyphenDict* hnj_hyphen_new() {
+ HyphenDict* dict = hnj_malloc (sizeof(HyphenDict));
+ init_dict(dict);
+ return dict;
+}
+
+
+void hnj_hyphen_clear(
+ HyphenDict* dict
+) {
+ clear_dict(dict);
+ init_dict(dict);
+}
+
+
+void hnj_hyphen_free(
+ HyphenDict *dict
+) {
+ clear_dict(dict);
+ hnj_free(dict);
+}
+
+unsigned char* hnj_serialize(
+ HyphenDict* dict
+) {
+ HashIter *v;
+ unsigned char* word;
+ char* pattern;
+ unsigned char* buf = hnj_malloc(dict->pat_length);
+ unsigned char* cur = buf;
+ v = new_HashIter(dict->patterns);
+ while (eachHash(v,&word,&pattern)) {
+ int i=0, e=0;
+ while(word[e+i]) {
+ if (pattern[i]!='0') *cur++ = (unsigned char) pattern[i];
+ *cur++ = word[e+i++];
+ while (is_utf8_follow(word[e+i])) *cur++ = word[i+e++];
+ }
+ if (pattern[i]!='0') *cur++ = (unsigned char) pattern[i];
+ *cur++ = ' ';
+ }
+ delete_HashIter(v);
+ *cur = 0;
+ return buf;
+}
+
+
+void hnj_free_serialize(
+ unsigned char* c
+) {
+ hnj_free(c);
+}
+
+
+/* hyphenation pattern:
+ * signed bytes
+ * 0 indicates end (actually any negative number)
+ * : prio(1+),startpos,length,len1,[replace],len2,[replace]
+ * most basic example is:
+ * p n 0 0 0
+ * for a hyphenation point between characters
+ */
+
+
+void hnj_hyphen_load(
+ HyphenDict* dict,
+ const unsigned char *f
+) {
+ int state_num, last_state;
+ int i, j = 0;
+ int ch;
+ int found;
+ HashEntry *e;
+ HashIter *v;
+ unsigned char* word;
+ char* pattern;
+ size_t l = 0;
+
+
+ /***************************************/
+
+ const unsigned char* format;
+ const unsigned char* begin = f;
+ while((format = next_pattern(&l,&f))!=NULL) {
+ int i,j,e;
+ /*
+ printf("%s\n",format);
+ char* repl = strnchr(format, '/',l);
+ int replindex = 0;
+ int replcut = 0;
+ if (repl) {
+ int clen = l-(repl-format);
+ l = repl-format;
+ char * index = strnchr(repl + 1, ',',clen);
+ if (index) {
+ char * index2 = strnchr(index + 1, ',',clen-(index-repl));
+ if (index2) {
+ replindex = (signed char) atoi(index + 1) - 1;
+ replcut = (signed char) atoi(index2 + 1);
+ }
+ } else {
+ hnj_strchomp(repl + 1);
+ replindex = 0;
+ replcut = strlen(buf);
+ }
+ repl = hnj_strdup(repl + 1);
+ }
+ */
+ for (i=0,j=0,e=0; i<l; i++) {
+ if (format[i]>='0'&&format[i]<='9') j++;
+ if (is_utf8_follow(format[i])) e++;
+ }
+ /* l-e => number of _characters_ not _bytes_*/
+ /* l-e-j => number of pattern characters*/
+ unsigned char *pat = (unsigned char*) malloc(1+l-j);
+ char *org = ( char*) malloc(2+l-e-j);
+ /* remove hyphenation encoders (digits) from pat*/
+ org[0] = '0';
+ for (i=0,j=0,e=0; i<l; i++) {
+ unsigned char c = format[i];
+ if (is_utf8_follow(c)) {
+ pat[j+e++] = c;
+ } else if (c<'0' || c>'9') {
+ pat[e+j++] = c;
+ org[j] = '0';
+ } else {
+ org[j] = c;
+ }
+ }
+ pat[e+j] = 0;
+ org[j+1] = 0;
+ hyppat_insert(dict->patterns,pat,org);
+ }
+ dict->pat_length += (f-begin)+2; /* 2 for spurious spaces*/
+ init_hash(&dict->merged);
+ v = new_HashIter(dict->patterns);
+ while (nextHash(v,&word)) {
+ int wordsize = strlen((char*)word);
+ int j,l;
+ for (l=1; l<=wordsize; l++) {
+ if (is_utf8_follow(word[l])) continue; /* Do not clip an utf8 sequence*/
+ for (j=1; j<=l; j++) {
+ int i = l-j;
+ if (is_utf8_follow(word[i])) continue; /* Do not start halfway an utf8 sequence*/
+ char *subpat_pat;
+ if ((subpat_pat = hyppat_lookup(dict->patterns,word+i,j))!=NULL) {
+ char* newpat_pat;
+ if ((newpat_pat = hyppat_lookup(dict->merged,word,l))==NULL) {
+ unsigned char *newword=(unsigned char*)malloc(l+1);
+ strncpy((char*)newword, (char*)word,l); newword[l]=0;
+ int e=0;
+ for (i=0; i<l; i++) if (is_utf8_follow(newword[i])) e++;
+ char *neworg = malloc(l+2-e);
+ sprintf(neworg,"%0*d",l+1-e,0); /* fill with right amount of '0'*/
+ hyppat_insert(dict->merged,newword,combine(neworg,subpat_pat));
+ } else {
+ combine(newpat_pat,subpat_pat);
+ }
+ }
+ }
+ }
+ }
+ delete_HashIter(v);
+
+ init_hash(&dict->state_num);
+ state_insert(dict->state_num, hnj_strdup((unsigned char*)""), 0);
+ v = new_HashIter(dict->merged);
+ while (nextHashStealPattern(v,&word,&pattern)) {
+ static unsigned char mask[] = {0x3F,0x1F,0xF,0x7};
+ int j = strlen((char*)word);
+#ifdef VERBOSE
+ printf ("word %s pattern %s, j = %d\n", word, pattern, j);
+#endif
+ state_num = hnj_get_state( dict, word, &found );
+ dict->states[state_num].match = pattern;
+
+ /* now, put in the prefix transitions */
+ while (found < 0) {
+ j--;
+ last_state = state_num;
+ ch = word[j];
+ if (ch>=0x80) {
+ int i=1;
+ while (is_utf8_follow(word[j-i])) i++;
+ ch = word[j-i] & mask[i];
+ int m = j-i;
+ while (i--) {
+ ch = (ch<<6)+(0x3F & word[j-i]);
+ }
+ j = m;
+ }
+ word[j] = '\0';
+ state_num = hnj_get_state (dict, word, &found);
+ hnj_add_trans (dict, state_num, last_state, ch);
+ }
+ }
+ delete_HashIter(v);
+ clear_hyppat_hash(&dict->merged);
+
+ /***************************************/
+
+ /* put in the fallback states */
+ for (i = 0; i < HASH_SIZE; i++) {
+ for (e = dict->state_num->entries[i]; e; e = e->next) {
+ /* do not do state==0 otherwise things get confused*/
+ if (e->u.state) {
+ for (j = 1; 1; j++) {
+ state_num = state_lookup(dict->state_num, e->key + j);
+ if (state_num >= 0) break;
+ }
+ dict->states[e->u.state].fallback_state = state_num;
+ }
+ }
+ }
+#ifdef VERBOSE
+ for (i = 0; i < HASH_SIZE; i++) {
+ for (e = dict->state_num->entries[i]; e; e = e->next) {
+ printf ("%d string %s state %d, fallback=%d\n", i, e->key, e->u.state,
+ dict->states[e->u.state].fallback_state);
+ for (j = 0; j < dict->states[e->u.state].num_trans; j++) {
+ printf (" u%4x->%d\n", (int)dict->states[e->u.state].trans[j].uni_ch,
+ dict->states[e->u.state].trans[j].new_state);
+ }
+ }
+ }
+#endif
+ clear_state_hash(&dict->state_num);
+}
+
+
+void hnj_hyphen_hyphenate(
+ HyphenDict *dict,
+ halfword first,
+ halfword last,
+ int length,
+ halfword left,
+ halfword right,
+ lang_variables *lan
+) {
+ /* +2 for dots at each end, +1 for points /outside/ characters*/
+ int ext_word_len = length+2;
+ int hyphen_len = ext_word_len+1;
+ /*char *hyphens = hnj_malloc((hyphen_len*2)+1); */ /* LATER */
+ char *hyphens = hnj_malloc(hyphen_len+1);
+
+ /* Add a '.' to beginning and end to facilitate matching*/
+ set_vlink(begin_point,first);
+ set_vlink(end_point,get_vlink(last));
+ set_vlink(last,end_point);
+
+ int char_num;
+ for (char_num = 0; char_num < hyphen_len; char_num++) {
+ /* hyphens[char_num*2] = '0'; */ /* LATER */
+ /* hyphens[char_num*2+1] = '0'; */ /* LATER */
+ hyphens[char_num] = '0';
+ }
+ /*hyphens[hyphen_len*2] = 0; */ /* LATER */
+ hyphens[hyphen_len] = 0;
+
+ /* now, run the finite state machine */
+ int state = 0;
+ halfword here;
+ for (char_num=0, here=begin_point; here!=end_point; here=get_vlink(here)) {
+
+ int ch = get_character(here);
+
+ while (state!=-1) {
+ /* printf("%*s%s%c",char_num-strlen(get_state_str(state)),"",get_state_str(state),(char)ch);*/
+ HyphenState *hstate = &dict->states[state];
+ int k;
+ for (k = 0; k < hstate->num_trans; k++) {
+ if (hstate->trans[k].uni_ch == ch) {
+ state = hstate->trans[k].new_state;
+ /* printf(" state %d\n",state);*/
+ char *match = dict->states[state].match;
+ if (match) {
+ /* +2 because:
+ * 1 string length is one bigger than offset
+ * 1 hyphenation starts before first character
+ */
+ int offset = char_num + 2 - strlen (match);
+ /* printf ("%*s%s\n", offset,"", match);*/
+ int m;
+ for (m = 0; match[m]; m++) {
+ if (hyphens[offset+m] < match[m]) hyphens[offset+m] = match[m];
+ }
+ }
+ goto try_next_letter;
+ }
+ }
+ state = hstate->fallback_state;
+ /* printf (" back to %d\n", state);*/
+ }
+ /* nothing worked, let's go to the next character*/
+ state = 0;
+try_next_letter: ;
+ char_num++;
+ }
+
+ /* restore the correct pointers*/
+ set_vlink(last,get_vlink(end_point));
+
+ /* pattern is ^.^w^o^r^d^.^ word_len=4, ext_word_len=6, hyphens=7
+ * check ^ ^ ^ so drop first two and stop after word_len-1
+ */
+ for (here=first,char_num=2; here!=left; here=get_vlink(here)) char_num++;
+ for (; here!=right; here=get_vlink(here)) {
+ if (hyphens[char_num] & 1)
+ here = insert_syllable_discretionary(here, lan);
+ char_num++;
+ }
+ hnj_free(hyphens);
+}
diff --git a/Build/source/texk/web2c/luatexdir/lang/texlang.c b/Build/source/texk/web2c/luatexdir/lang/texlang.c
new file mode 100644
index 00000000000..12390ae2fcf
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lang/texlang.c
@@ -0,0 +1,825 @@
+/*
+Copyright (c) 2007 Taco Hoekwater <taco@latex.org>
+
+This file is part of luatex.
+
+luatex is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+luatex is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with luatex; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+This is texlang.c
+*/
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+#include <string.h>
+
+#include "nodes.h"
+#include "hyphen.h"
+
+/* functions from the fontforge unicode library */
+
+extern unsigned int *utf82u_strcpy(unsigned int *ubuf,const char *utf8buf);
+extern unsigned int u_strlen(unsigned int *ubuf);
+extern char *utf8_idpb(char *w,unsigned int i);
+
+#define noVERBOSE
+
+#define MAX_TEX_LANGUAGES 32767
+
+static struct tex_language *tex_languages[MAX_TEX_LANGUAGES] = {NULL};
+static int next_lang_id = 0;
+
+struct tex_language *
+new_language (void) {
+ struct tex_language* lang;
+ if (next_lang_id<MAX_TEX_LANGUAGES) {
+ lang = xmalloc(sizeof(struct tex_language));
+ tex_languages[next_lang_id] = lang;
+ lang->id = next_lang_id++;
+ lang->exceptions = 0;
+ lang->patterns = NULL;
+ lang->pre_hyphen_char = '-';
+ lang->post_hyphen_char = 0;
+ return lang;
+ } else {
+ return NULL;
+ }
+}
+
+struct tex_language *
+get_language (int n) {
+ if (n>=0 && n<=MAX_TEX_LANGUAGES ) {
+ if (tex_languages[n]!=NULL) {
+ return tex_languages[n];
+ } else {
+ return new_language();
+ }
+ } else {
+ return NULL;
+ }
+}
+
+void
+set_pre_hyphen_char (integer n, integer v) {
+ struct tex_language *l = get_language((int)n);
+ l->pre_hyphen_char = (int)v;
+}
+
+void
+set_post_hyphen_char (integer n, integer v) {
+ struct tex_language *l = get_language((int)n);
+ l->post_hyphen_char = (int)v;
+}
+
+integer
+get_pre_hyphen_char (integer n) {
+ struct tex_language *l = get_language((int)n);
+ return (integer)l->pre_hyphen_char;
+}
+
+integer
+get_post_hyphen_char (integer n) {
+ struct tex_language *l = get_language((int)n);
+ return (integer)l->post_hyphen_char;
+}
+
+void
+load_patterns (struct tex_language *lang, unsigned char *buffer) {
+ if (lang==NULL)
+ return;
+ if (lang->patterns==NULL) {
+ lang->patterns = hnj_hyphen_new();
+ }
+ hnj_hyphen_load (lang->patterns,buffer);
+}
+
+void
+clear_patterns (struct tex_language *lang) {
+ if (lang==NULL)
+ return;
+ if (lang->patterns!=NULL) {
+ hnj_hyphen_clear(lang->patterns);
+ }
+}
+
+void
+load_tex_patterns(int curlang, halfword head) {
+ char *s = tokenlist_to_cstring (head,1, NULL);
+ load_patterns(get_language(curlang),(unsigned char *)s);
+}
+
+
+#define STORE_CHAR(x) { word[w] = x ; if (w<MAX_WORD_LEN) w++; }
+
+/* todo change this! */
+
+char *
+clean_hyphenation (char *buffer, char **cleaned) {
+ int items;
+ unsigned char word [MAX_WORD_LEN+1];
+ int w = 0;
+ char *s = buffer;
+ while (*s && !isspace(*s)) {
+ if (*s == '-') { /* skip */
+ } else if (*s == '=') {
+ STORE_CHAR('-');
+ } else if (*s == '{') {
+ s++;
+ items=0;
+ while (*s && *s!='}') { s++; }
+ if (*s=='}') { items++; s++; }
+ while (*s && *s!='}') { s++; }
+ if (*s=='}') { items++; s++; }
+ if (*s=='{') { s++; }
+ while (*s && *s!='}') {STORE_CHAR(*s); s++; }
+ if (*s=='}') { items++; } else { s--; }
+ if (items!=3) { /* syntax error */
+ *cleaned = NULL;
+ while (*s && !isspace(*s)) { s++; }
+ return s;
+ }
+ } else {
+ STORE_CHAR(*s);
+ }
+ s++;
+ }
+ word[w] = 0;
+ *cleaned = xstrdup((char *)word);
+ return s;
+}
+
+void
+load_hyphenation (struct tex_language *lang, unsigned char *buffer) {
+ char *s, *value, *cleaned;
+ lua_State *L = Luas[0];
+ if (lang==NULL)
+ return;
+ if (lang->exceptions==0) {
+ lua_newtable(L);
+ lang->exceptions = luaL_ref(L,LUA_REGISTRYINDEX);
+ }
+ lua_rawgeti(L, LUA_REGISTRYINDEX, lang->exceptions);
+ s = (char *)buffer;
+ while (*s) {
+ while (isspace(*s)) s++;
+ if (*s) {
+ value = s;
+ s = clean_hyphenation(s, &cleaned);
+ if (cleaned!=NULL) {
+ if ((s-value)>0) {
+ lua_pushstring(L,cleaned);
+ lua_pushlstring(L,value,(s-value));
+ lua_rawset(L,-3);
+ }
+ free(cleaned);
+ } else {
+#ifdef VERBOSE
+ fprintf(stderr,"skipping invalid hyphenation exception: %s\n",value);
+#endif
+ }
+ }
+ }
+}
+
+void
+clear_hyphenation (struct tex_language *lang) {
+ if (lang==NULL)
+ return;
+ if (lang->exceptions!=0) {
+ luaL_unref(Luas[0],LUA_REGISTRYINDEX,lang->exceptions);
+ lang->exceptions = 0;
+ }
+}
+
+
+void
+load_tex_hyphenation(int curlang, halfword head) {
+ char *s = tokenlist_to_cstring (head,1, NULL);
+ load_hyphenation(get_language(curlang),(unsigned char *)s);
+}
+
+/* TODO: clean this up. The delete_attribute_ref() statements are not very
+ nice, but needed. Also, in the post-break, it would be nicer to get the
+ attribute list from vlink(n). No rush, as it is currently not used much. */
+
+halfword insert_discretionary ( halfword t, halfword pre, halfword post, halfword replace) {
+ halfword g, n;
+ n = new_node(disc_node,syllable_disc);
+ try_couple_nodes(n,vlink(t));
+ couple_nodes(t,n);
+ for (g=pre;g!=null;g=vlink(g)) {
+ font(g)=font(replace);
+ if (node_attr(t)!=null) {
+ delete_attribute_ref(node_attr(g));
+ node_attr(g) = node_attr(t);
+ attr_list_ref(node_attr(t)) += 1;
+ }
+ }
+ for (g=post;g!=null;g =vlink(g)) {
+ font(g)=font(replace);
+ if (node_attr(t)!=null) {
+ delete_attribute_ref(node_attr(g));
+ node_attr(g) = node_attr(t);
+ attr_list_ref(node_attr(t)) += 1;
+ }
+ }
+ for (g=replace;g!=null;g =vlink(g)) {
+ if (node_attr(t)!=null) {
+ delete_attribute_ref(node_attr(g));
+ node_attr(g) = node_attr(t);
+ attr_list_ref(node_attr(t)) += 1;
+ }
+ }
+ if (node_attr(t)!=null) {
+ delete_attribute_ref(node_attr(vlink(t)));
+ node_attr(vlink(t)) = node_attr(t);
+ attr_list_ref(node_attr(t)) += 1;
+ }
+ t = vlink(t);
+ set_disc_field(pre_break(t),pre);
+ set_disc_field(post_break(t),post);
+ set_disc_field(no_break(t),replace);
+ return t;
+}
+
+halfword
+insert_syllable_discretionary ( halfword t, lang_variables *lan) {
+ halfword g, n;
+ n = new_node(disc_node,syllable_disc);
+ couple_nodes(n,vlink(t));
+ couple_nodes(t,n);
+ delete_attribute_ref(node_attr(n));
+ if (node_attr(t)!=null) {
+ node_attr(n) = node_attr(t);
+ attr_list_ref(node_attr(t))++ ;
+ } else {
+ node_attr(n) = null;
+ }
+ if (lan->pre_hyphen_char >0) {
+ g = raw_glyph_node();
+ set_to_character(g);
+ character(g)=lan->pre_hyphen_char;
+ font(g)=font(t);
+ lang_data(g)=lang_data(t);
+ if (node_attr(t)!=null) {
+ node_attr(g) = node_attr(t);
+ attr_list_ref(node_attr(t)) ++;
+ }
+ set_disc_field(pre_break(n),g);
+ }
+
+ if (lan->post_hyphen_char >0) {
+ t = vlink(n);
+ g = raw_glyph_node();
+ set_to_character(g);
+ character(g)=lan->post_hyphen_char;
+ font(g)=font(t);
+ lang_data(g)=lang_data(t);
+ if (node_attr(t)!=null) {
+ node_attr(g) = node_attr(t);
+ attr_list_ref(node_attr(t)) += 1;
+ }
+ set_disc_field(post_break(n),g);
+ }
+ return n;
+}
+
+halfword insert_word_discretionary ( halfword t, lang_variables *lan) {
+ halfword pre = null, pos = null;
+ if (lan->pre_hyphen_char >0) pre = insert_character ( null, lan->pre_hyphen_char);
+ if (lan->post_hyphen_char>0) pos = insert_character ( null, lan->post_hyphen_char);
+ return insert_discretionary ( t, pre, pos, null);
+}
+
+halfword insert_complex_discretionary ( halfword t, lang_variables *lan,
+ halfword pre, halfword pos, halfword replace) {
+ return insert_discretionary ( t, pre, pos, replace);
+}
+
+
+halfword insert_character ( halfword t, int c) {
+ halfword p;
+ p=new_node(glyph_node,0);
+ set_to_character(p);
+ character(p)=c;
+ if (t!=null) {
+ couple_nodes(t,p);
+ }
+ return p;
+}
+
+
+void
+set_disc_field (halfword f, halfword t) {
+ if (t!=null) {
+ couple_nodes(f,t);
+ tlink(f) = tail_of_list(t);
+ }
+}
+
+
+
+char *hyphenation_exception(int exceptions, char *w) {
+ char *ret = NULL;
+ lua_State *L = Luas[0];
+ lua_checkstack(L,2);
+ lua_rawgeti(L,LUA_REGISTRYINDEX,exceptions);
+ if (lua_istable(L,-1)) { /* ?? */
+ lua_pushstring(L,w); /* word table */
+ lua_rawget(L,-2);
+ if (lua_isstring(L,-1)) {
+ ret = xstrdup((char *)lua_tostring(L,-1));
+ }
+ lua_pop(L,2);
+ } else {
+ lua_pop(L,1);
+ }
+ return ret;
+}
+
+
+char *exception_strings(struct tex_language *lang) {
+ char *value;
+ int size = 0, current =0;
+ size_t l =0;
+ char *ret = NULL;
+ lua_State *L = Luas[0];
+ if (lang->exceptions==0)
+ return NULL;
+ lua_checkstack(L,2);
+ lua_rawgeti(L,LUA_REGISTRYINDEX,lang->exceptions);
+ if (lua_istable(L,-1)) {
+ /* iterate and join */
+ lua_pushnil(L); /* first key */
+ while (lua_next(L,-2) != 0) {
+ value = (char *)lua_tolstring(L, -1, &l);
+ if (current + 2 + l > size ) {
+ ret = xrealloc(ret, (1.2*size)+current+l+1024);
+ size = (1.2*size)+current+l+1024;
+ }
+ *(ret+current) = ' ';
+ strcpy(ret+current+1,value);
+ current += l+1;
+ lua_pop(L, 1);
+ }
+ }
+ return ret;
+}
+
+
+/* the sequence from |wordstart| to |r| can contain only normal characters */
+/* it could be faster to modify a halfword pointer and return an integer */
+
+halfword find_exception_part(int *j, int *uword, int len) {
+ halfword g = null, gg = null;
+ register int i = *j;
+ i++; /* this puts uword[i] on the '{' */
+ while (i<len && uword[i+1] != '}') {
+ if (g==null) {
+ gg = new_char(0,uword[i+1]);
+ g = gg;
+ } else {
+ halfword s = new_char(0,uword[i+1]);
+ couple_nodes(g,s);
+ g = vlink(g);
+ }
+ i++;
+ }
+ *j = ++i;
+ return gg;
+}
+
+int count_exception_part(int *j, int *uword, int len) {
+ int ret=0;
+ register int i = *j;
+ i++; /* this puts uword[i] on the '{' */
+ while (i<len && uword[i+1] != '}') {
+ ret++;
+ i++;
+ }
+ *j = ++i;
+ return ret;
+}
+
+
+static char *PAT_ERROR[] = {
+ "Exception discretionaries should contain three pairs of braced items.",
+ "No intervening spaces are allowed.",
+ NULL };
+
+void do_exception (halfword wordstart, halfword r, char *replacement) {
+ int i;
+ halfword t;
+ unsigned len;
+ int clang;
+ lang_variables langdata;
+ int uword[MAX_WORD_LEN+1] = {0};
+ (void)utf82u_strcpy((unsigned int *)uword,replacement);
+ len = u_strlen((unsigned int *)uword);
+ i = 0;
+ t=wordstart;
+ clang = char_lang(wordstart);
+ langdata.pre_hyphen_char = get_pre_hyphen_char(clang);
+ langdata.post_hyphen_char = get_post_hyphen_char(clang);
+
+ for (i=0;i<len;i++) {
+ if (uword[i+1] == '-') { /* a hyphen follows */
+ while (vlink(t)!=r && (type(t)!=glyph_node || !is_simple_character(t)))
+ t = vlink(t);
+ if (vlink(t)==r)
+ break;
+ insert_syllable_discretionary(t, &langdata);
+ t = vlink(t); /* skip the new disc */
+ } else if (uword[i+1] == '=') {
+ /* do nothing ? */
+ t = vlink(t);
+ } else if (uword[i+1] == '{') {
+ halfword gg, hh, replace = null;
+ int repl;
+ gg = find_exception_part(&i,uword,len);
+ if (i==len || uword[i+1] != '{') {
+ tex_error ("broken pattern 1", PAT_ERROR);
+ }
+ hh = find_exception_part(&i,uword,len);
+ if (i==len || uword[i+1] != '{') {
+ tex_error ("broken pattern 2", PAT_ERROR);
+ }
+ repl = count_exception_part(&i,uword,len);
+ if (i==len) {
+ tex_error ("broken pattern 3", PAT_ERROR);
+ }
+ /*i++; */ /* jump over the last right brace */
+ if (vlink(t)==r)
+ break;
+ if (repl>0) {
+ halfword q = t;
+ replace = vlink(q);
+ while(repl>0 && q!=null) {
+ q=vlink(q);
+ if (type(q)==glyph_node) {
+ repl--;
+ }
+ }
+ try_couple_nodes(t,vlink(q));
+ vlink(q)=null;
+ }
+ t = insert_discretionary(t,gg,hh,replace);
+ } else {
+ t = vlink(t);
+ }
+ }
+}
+
+/* This is a documentation section from the pascal web file. It is not
+true any more, but I do not have time right now to rewrite it -- Taco
+
+When the line-breaking routine is unable to find a feasible sequence of
+breakpoints, it makes a second pass over the paragraph, attempting to
+hyphenate the hyphenatable words. The goal of hyphenation is to insert
+discretionary material into the paragraph so that there are more
+potential places to break.
+
+The general rules for hyphenation are somewhat complex and technical,
+because we want to be able to hyphenate words that are preceded or
+followed by punctuation marks, and because we want the rules to work
+for languages other than English. We also must contend with the fact
+that hyphens might radically alter the ligature and kerning structure
+of a word.
+
+A sequence of characters will be considered for hyphenation only if it
+belongs to a ``potentially hyphenatable part'' of the current paragraph.
+This is a sequence of nodes $p_0p_1\ldots p_m$ where $p_0$ is a glue node,
+$p_1\ldots p_{m-1}$ are either character or ligature or whatsit or
+implicit kern nodes, and $p_m$ is a glue or penalty or insertion or adjust
+or mark or whatsit or explicit kern node. (Therefore hyphenation is
+disabled by boxes, math formulas, and discretionary nodes already inserted
+by the user.) The ligature nodes among $p_1\ldots p_{m-1}$ are effectively
+expanded into the original non-ligature characters; the kern nodes and
+whatsits are ignored. Each character |c| is now classified as either a
+nonletter (if |lc_code(c)=0|), a lowercase letter (if
+|lc_code(c)=c|), or an uppercase letter (otherwise); an uppercase letter
+is treated as if it were |lc_code(c)| for purposes of hyphenation. The
+characters generated by $p_1\ldots p_{m-1}$ may begin with nonletters; let
+$c_1$ be the first letter that is not in the middle of a ligature. Whatsit
+nodes preceding $c_1$ are ignored; a whatsit found after $c_1$ will be the
+terminating node $p_m$. All characters that do not have the same font as
+$c_1$ will be treated as nonletters. The |hyphen_char| for that font
+must be between 0 and 255, otherwise hyphenation will not be attempted.
+\TeX\ looks ahead for as many consecutive letters $c_1\ldots c_n$ as
+possible; however, |n| must be less than 64, so a character that would
+otherwise be $c_{64}$ is effectively not a letter. Furthermore $c_n$ must
+not be in the middle of a ligature. In this way we obtain a string of
+letters $c_1\ldots c_n$ that are generated by nodes $p_a\ldots p_b$, where
+|1<=a<=b+1<=m|. If |n>=l_hyf+r_hyf|, this string qualifies for hyphenation;
+however, |uc_hyph| must be positive, if $c_1$ is uppercase.
+
+The hyphenation process takes place in three stages. First, the candidate
+sequence $c_1\ldots c_n$ is found; then potential positions for hyphens
+are determined by referring to hyphenation tables; and finally, the nodes
+$p_a\ldots p_b$ are replaced by a new sequence of nodes that includes the
+discretionary breaks found.
+
+Fortunately, we do not have to do all this calculation very often, because
+of the way it has been taken out of \TeX's inner loop. For example, when
+the second edition of the author's 700-page book {\sl Seminumerical
+Algorithms} was typeset by \TeX, only about 1.2 hyphenations needed to be
+@^Knuth, Donald Ervin@>
+tried per paragraph, since the line breaking algorithm needed to use two
+passes on only about 5 per cent of the paragraphs.
+
+
+When a word been set up to contain a candidate for hyphenation,
+\TeX\ first looks to see if it is in the user's exception dictionary. If not,
+hyphens are inserted based on patterns that appear within the given word,
+using an algorithm due to Frank~M. Liang.
+@^Liang, Franklin Mark@>
+*/
+
+/*
+ * This is incompatible with TEX because the first word of a paragraph
+ * can be hyphenated, but most european users seem to agree that
+ * prohibiting hyphenation there was not a the best idea ever.
+ */
+
+halfword find_next_wordstart(halfword r) {
+ register int l;
+ register int start_ok = 1;
+ int mathlevel = 1;
+ while (r!=null) {
+ switch (type(r)) {
+ case glue_node:
+ start_ok = 1;
+ break;
+ case math_node:
+ while (mathlevel>0 ){
+ r = vlink(r);
+ if (r==null)
+ return r;
+ if (type(r)==math_node) {
+ if (subtype(r)==before) {
+ mathlevel++;
+ } else {
+ mathlevel--;
+ }
+ }
+ }
+ break;
+ case glyph_node:
+ if (start_ok &&
+ is_simple_character(r) &&
+ (l = get_lc_code(character(r)))>0 &&
+ (char_uchyph(r) || l == character(r)))
+ return r;
+ /* fall through */
+ default:
+ start_ok = 0;
+ break;
+ }
+ r = vlink(r);
+ }
+ return r;
+}
+
+int valid_wordend( halfword s) {
+ register halfword r = s;
+ register int clang = char_lang(s);
+ if (r==null)
+ return 1;
+ while ((r!=null) &&
+ ((type(r)==glyph_node && is_simple_character(r) && clang == char_lang(r)) ||
+ (type(r)==kern_node && subtype(r)==normal))) {
+ r = vlink(r);
+ }
+ if (r==null ||
+ (type(r)==glyph_node && is_simple_character(r) && clang != char_lang(r)) ||
+ type(r)==glue_node ||
+ type(r)==whatsit_node ||
+ type(r)==ins_node ||
+ type(r)==adjust_node ||
+ type(r)==penalty_node ||
+ (type(r)==kern_node && subtype(r)==explicit))
+ return 1;
+ return 0;
+}
+
+void
+hnj_hyphenation (halfword head, halfword tail) {
+ int lchar, i;
+ struct tex_language* lang;
+ lang_variables langdata;
+ char utf8word[(4*MAX_WORD_LEN)+1] = {0};
+ int wordlen = 0;
+ char *hy = utf8word;
+ char *replacement = NULL;
+ halfword s, r = head, wordstart = null, save_tail = null, left = null, right = null;
+
+ /* this first movement assures two things:
+ * a) that we won't waste lots of time on something that has been
+ * handled already (in that case, none of the glyphs match |simple_character|).
+ * b) that the first word can be hyphenated. if the movement was
+ * not explicit, then the indentation at the start of a paragraph
+ * list would make find_next_wordstart() look too far ahead.
+ */
+
+ while (r!=null && (type(r)!=glyph_node || !is_simple_character(r)))
+ r =vlink(r);
+ /* this will make |r| a glyph node with subtype_character */
+ r = find_next_wordstart(r);
+ if (r==null)
+ return;
+
+ assert (tail!=null);
+ save_tail = vlink(tail);
+ s = new_penalty(0);
+ couple_nodes(tail, s);
+
+ while (r!=null) { /* could be while(1), but let's be paranoid */
+ wordstart = r;
+ assert (is_simple_character(wordstart));
+ int clang = char_lang(wordstart);
+ int lhmin = char_lhmin(wordstart);
+ int rhmin = char_rhmin(wordstart);
+ langdata.pre_hyphen_char = get_pre_hyphen_char(clang);
+ langdata.post_hyphen_char = get_post_hyphen_char(clang);
+ while (r!=null &&
+ type(r)==glyph_node &&
+ is_simple_character(r) &&
+ clang == char_lang(r) &&
+ (lchar = get_lc_code(character(r)))>0) {
+ wordlen++;
+ hy = utf8_idpb(hy,character(r));
+ /* this should not be needed any more */
+ /*if (vlink(r)!=null) alink(vlink(r))=r;*/
+ r = vlink(r);
+ }
+ if (valid_wordend(r) && wordlen>=lhmin+rhmin && (lang=tex_languages[clang])!=NULL) {
+ *hy=0;
+ if (lang->exceptions!=0 &&
+ (replacement = hyphenation_exception(lang->exceptions,utf8word))!=NULL) {
+#ifdef VERBOSE
+ fprintf(stderr,"replacing %s (c=%d) by %s\n",utf8word,clang,replacement);
+#endif
+ do_exception(wordstart,r,replacement);
+ free(replacement);
+ } else if (lang->patterns!=NULL) {
+
+ left = wordstart;
+ for (i=lhmin;i>1;i--) {
+ left = vlink(left);
+ while (!is_simple_character(left))
+ left = vlink(left);
+ }
+ right = r;
+ for (i=rhmin;i>0;i--) {
+ right = alink(right);
+ while (!is_simple_character(right))
+ right = alink(right);
+ }
+
+#ifdef VERBOSE
+ fprintf(stderr,"hyphenate %s (c=%d,l=%d,r=%d) from %c to %c\n",utf8word,
+ clang,lhmin,rhmin,
+ character(left), character(right));
+#endif
+ (void)hnj_hyphen_hyphenate(lang->patterns,wordstart,r,wordlen,left,right, &langdata);
+ }
+ }
+ wordlen = 0;
+ hy = utf8word;
+ if (r==null)
+ break;
+ r = find_next_wordstart(r);
+ }
+ flush_node(vlink(tail));
+ vlink(tail) = save_tail;
+}
+
+
+void
+new_hyphenation (halfword head, halfword tail) {
+ register int callback_id = 0;
+ if (head==null || vlink(head)==null)
+ return;
+ fix_node_list (head); /* TODO: use couple_nodes() in append_tail()!*/
+ callback_id = callback_defined(hyphenate_callback);
+ if (callback_id>0) {
+ lua_State *L = Luas[0];
+ lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id);
+ lua_rawgeti(L,-1, callback_id);
+ if (!lua_isfunction(L,-1)) {
+ lua_pop(L,2);
+ return;
+ }
+ nodelist_to_lua(L,head);
+ nodelist_to_lua(L,tail);
+ if (lua_pcall(L,2,0,0) != 0) {
+ fprintf(stdout,"error: %s\n",lua_tostring(L,-1));
+ lua_pop(L,2);
+ lua_error(L);
+ return;
+ }
+ lua_pop(L,1);
+ } else {
+ hnj_hyphenation(head,tail);
+ }
+}
+
+/* dumping and undumping fonts */
+
+#define dump_string(a) \
+ if (a!=NULL) { \
+ x = strlen(a)+1; \
+ dump_int(x); dump_things(*a, x); \
+ } else { \
+ x = 0; dump_int(x); \
+ }
+
+
+void dump_one_language (int i) {
+ char *s = NULL;
+ unsigned x = 0;
+ struct tex_language *lang;
+ lang = tex_languages[i];
+ dump_int(lang->id);
+ dump_int(lang->pre_hyphen_char);
+ dump_int(lang->post_hyphen_char);
+ if (lang->patterns!=NULL) {
+ s = (char *)hnj_serialize(lang->patterns);
+ }
+ dump_string(s);
+ if (s!=NULL) {
+ free(s);
+ s = NULL;
+ }
+ if (lang->exceptions!=0)
+ s = exception_strings(lang);
+ dump_string(s);
+ if (s!=NULL) {
+ free(s);
+ }
+ free (lang);
+}
+
+void dump_language_data (void) {
+ int i;
+ dump_int(next_lang_id);
+ for (i=0;i<next_lang_id;i++) {
+ if (tex_languages[i]) {
+ dump_int(1);
+ dump_one_language(i);
+ } else {
+ dump_int(0);
+ }
+ }
+}
+
+
+void undump_one_language (int i) {
+ char *s = NULL;
+ unsigned x = 0;
+ struct tex_language *lang = get_language(i);
+ undump_int(x); lang->id = x;
+ undump_int(x); lang->pre_hyphen_char = x;
+ undump_int(x); lang->post_hyphen_char = x;
+ /* patterns */
+ undump_int (x);
+ if (x>0) {
+ s = xmalloc(x);
+ undump_things(*s,x);
+ load_patterns(lang,(unsigned char *)s);
+ free(s);
+ }
+ /* exceptions */
+ undump_int (x);
+ if (x>0) {
+ s = xmalloc(x);
+ undump_things(*s,x);
+ load_hyphenation(lang,(unsigned char *)s);
+ free(s);
+ }
+}
+
+void undump_language_data (void) {
+ int i;
+ unsigned x, numlangs;
+ undump_int(numlangs);
+ for (i=0;i<numlangs;i++) {
+ undump_int(x);
+ if (x==1) {
+ undump_one_language(i);
+ }
+ }
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/lua/.indent.pro b/Build/source/texk/web2c/luatexdir/lua/.indent.pro
new file mode 100644
index 00000000000..e9e690f1ba8
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/.indent.pro
@@ -0,0 +1,12 @@
+/* $Id$ */
+--k-and-r-style
+--blank-lines-after-procedures
+--line-length 80
+--procnames-start-lines
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--space-after-cast
+/* this does not work in indent 2.2.6 :-( */
+--no-tabs
+/* this is new in indent 2.2.9 */
+--preprocessor-indentation 2
diff --git a/Build/source/texk/web2c/luatexdir/lua/lcallbacklib.c b/Build/source/texk/web2c/luatexdir/lua/lcallbacklib.c
new file mode 100644
index 00000000000..fa207420dfb
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/lcallbacklib.c
@@ -0,0 +1,463 @@
+/* $Id: lcallbacklib.c 1013 2008-02-14 00:09:02Z oneiros $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+extern int do_run_callback (int special, char *values, va_list vl);
+
+int callback_set[total_callbacks] = {0};
+
+static const char *const callbacknames[] = {
+ "", /* empty on purpose */
+ "find_write_file",
+ "find_output_file",
+ "find_image_file",
+ "find_format_file",
+ "find_read_file", "open_read_file",
+ "find_ocp_file", "read_ocp_file",
+ "find_vf_file", "read_vf_file",
+ "find_data_file", "read_data_file",
+ "find_font_file", "read_font_file",
+ "find_map_file", "read_map_file",
+ "find_enc_file", "read_enc_file",
+ "find_type1_file", "read_type1_file",
+ "find_truetype_file", "read_truetype_file",
+ "find_opentype_file", "read_opentype_file",
+ "find_sfd_file", "read_sfd_file",
+ "find_pk_file", "read_pk_file",
+ "show_error_hook",
+ "process_input_buffer",
+ "start_page_number", "stop_page_number",
+ "start_run", "stop_run",
+ "define_font",
+ "token_filter",
+ "pre_output_filter",
+ "buildpage_filter",
+ "hpack_filter", "vpack_filter",
+ "char_exists",
+ "hyphenate",
+ "ligaturing",
+ "kerning",
+ "pre_linebreak_filter",
+ "linebreak_filter",
+ "post_linebreak_filter",
+ NULL };
+
+int callback_callbacks_id = 0;
+
+void
+get_lua_boolean (char *table, char *name, boolean *target) {
+ int stacktop;
+ stacktop = lua_gettop(Luas[0]);
+ luaL_checkstack(Luas[0],2,"out of stack space");
+ lua_getglobal(Luas[0],table);
+ if (lua_istable(Luas[0],-1)) {
+ lua_getfield(Luas[0],-1,name);
+ if (lua_isboolean(Luas[0],-1)) {
+ *target = (lua_toboolean(Luas[0],-1));
+ } else if (lua_isnumber(Luas[0],-1)) {
+ *target = (lua_tonumber(Luas[0],-1)==0 ? 0 : 1);
+ }
+ }
+ lua_settop(Luas[0],stacktop);
+ return;
+}
+
+void
+get_saved_lua_boolean (int r, char *name, boolean *target) {
+ int stacktop;
+ stacktop = lua_gettop(Luas[0]);
+ luaL_checkstack(Luas[0],2,"out of stack space");
+ lua_rawgeti(Luas[0],LUA_REGISTRYINDEX,r);
+ if (lua_istable(Luas[0],-1)) {
+ lua_getfield(Luas[0],-1,name);
+ if (lua_isboolean(Luas[0],-1)) {
+ *target = lua_toboolean(Luas[0],-1);
+ } else if (lua_isnumber(Luas[0],-1)) {
+ *target = (lua_tonumber(Luas[0],-1)==0 ? 0 : 1);
+ }
+ }
+ lua_settop(Luas[0],stacktop);
+ return;
+}
+
+void
+get_lua_number (char *table, char *name, integer *target) {
+ int stacktop;
+ stacktop = lua_gettop(Luas[0]);
+ luaL_checkstack(Luas[0],2,"out of stack space");
+ lua_getglobal(Luas[0],table);
+ if (lua_istable(Luas[0],-1)) {
+ lua_getfield(Luas[0],-1,name);
+ if (lua_isnumber(Luas[0],-1)) {
+ *target = lua_tonumber(Luas[0],-1);
+ }
+ }
+ lua_settop(Luas[0],stacktop);
+ return;
+}
+
+void
+get_saved_lua_number (int r, char *name, integer *target) {
+ int stacktop;
+ stacktop = lua_gettop(Luas[0]);
+ luaL_checkstack(Luas[0],2,"out of stack space");
+ lua_rawgeti(Luas[0],LUA_REGISTRYINDEX,r);
+ if (lua_istable(Luas[0],-1)) {
+ lua_getfield(Luas[0],-1,name);
+ if (lua_isnumber(Luas[0],-1)) {
+ *target = lua_tonumber(Luas[0],-1);
+ }
+ }
+ lua_settop(Luas[0],stacktop);
+ return;
+}
+
+
+void
+get_lua_string (char *table, char *name, char **target) {
+ int stacktop;
+ stacktop = lua_gettop(Luas[0]);
+ luaL_checkstack(Luas[0],2,"out of stack space");
+ lua_getglobal(Luas[0],table);
+ if (lua_istable(Luas[0],-1)) {
+ lua_getfield(Luas[0],-1,name);
+ if (lua_isstring(Luas[0],-1)) {
+ *target = (char *)lua_tostring(Luas[0],-1);
+ }
+ }
+ lua_settop(Luas[0],stacktop);
+ return;
+}
+
+void
+get_saved_lua_string (int r, char *name, char **target) {
+ int stacktop;
+ stacktop = lua_gettop(Luas[0]);
+ luaL_checkstack(Luas[0],2,"out of stack space");
+ lua_rawgeti(Luas[0],LUA_REGISTRYINDEX,r);
+ if (lua_istable(Luas[0],-1)) {
+ lua_getfield(Luas[0],-1,name);
+ if (lua_isstring(Luas[0],-1)) {
+ *target = (char *)lua_tostring(Luas[0],-1);
+ }
+ }
+ lua_settop(Luas[0],stacktop);
+ return;
+}
+
+
+#define CALLBACK_BOOLEAN 'b'
+#define CALLBACK_INTEGER 'd'
+#define CALLBACK_LINE 'l'
+#define CALLBACK_STRNUMBER 's'
+#define CALLBACK_STRING 'S'
+#define CALLBACK_CHARNUM 'c'
+
+int
+run_saved_callback (int r, char *name, char *values, ...) {
+ va_list args;
+ int ret = 0;
+ lua_State *L = Luas[0];
+ int stacktop = lua_gettop(L);
+ va_start(args,values);
+ luaL_checkstack(L,2,"out of stack space");
+ lua_rawgeti(L,LUA_REGISTRYINDEX,r);
+ lua_pushstring(L,name);
+ lua_rawget(L,-2);
+ if (lua_isfunction(L,-1)) {
+ ret = do_run_callback(2,values,args);
+ }
+ va_end(args);
+ lua_settop(L,stacktop);
+ return ret;
+}
+
+
+int
+run_and_save_callback (int i, char *values, ...) {
+ va_list args;
+ int ret = 0;
+ lua_State *L = Luas[0];
+ int stacktop = lua_gettop(L);
+ va_start(args,values);
+ luaL_checkstack(L,2,"out of stack space");
+ lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id);
+ lua_rawgeti(L,-1,i);
+ if (lua_isfunction(L,-1)) {
+ ret = do_run_callback(1,values,args);
+ }
+ va_end(args);
+ if (ret>0) {
+ ret = luaL_ref(L,LUA_REGISTRYINDEX);
+ }
+ lua_settop(L,stacktop);
+ return ret;
+}
+
+
+int
+run_callback (int i, char *values, ...) {
+ va_list args;
+ int ret = 0;
+ lua_State *L = Luas[0];
+ int stacktop = lua_gettop(L);
+ va_start(args,values);
+ luaL_checkstack(L,2,"out of stack space");
+ lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id);
+ lua_rawgeti(L,-1, i);
+ if (lua_isfunction(L,-1)) {
+ ret = do_run_callback(0,values,args);
+ }
+ va_end(args);
+ lua_settop(L,stacktop);
+ return ret;
+}
+
+int
+do_run_callback (int special, char *values, va_list vl) {
+ int ret, len;
+ int narg,nres;
+ char *s;
+ char cs;
+ int *bufloc;
+ char *ss = NULL;
+ int retval = 0;
+ lua_State *L = Luas[0];
+ if (special==2) { /* copy the enclosing table */
+ luaL_checkstack(L,1,"out of stack space");
+ lua_pushvalue(L,-2);
+ }
+ for (narg = 0; *values; narg++) {
+ luaL_checkstack(L,1,"out of stack space");
+ switch (*values++) {
+ case CALLBACK_CHARNUM: /* an ascii char! */
+ cs = (char)va_arg(vl, int);
+ lua_pushlstring(L,&cs, 1);
+ break;
+ case CALLBACK_STRING: /* C string */
+ s = va_arg(vl, char *);
+ lua_pushstring(L, s);
+ break;
+ case CALLBACK_INTEGER: /* int */
+ lua_pushnumber(L, va_arg(vl, int));
+ break;
+ case CALLBACK_STRNUMBER: /* TeX string */
+ s = makeclstring(va_arg(vl, int),&len);
+ lua_pushlstring(L, s,len);
+ break;
+ case CALLBACK_BOOLEAN: /* boolean */
+ lua_pushboolean(L, va_arg(vl, int));
+ break;
+ case CALLBACK_LINE: /* a buffer section, with implied start */
+ lua_pushlstring(L, (char *)(buffer+first), va_arg(vl, int));
+ break;
+ case '-':
+ narg--;
+ break;
+ case '>':
+ goto ENDARGS;
+ default :
+ ;
+ }
+ }
+ ENDARGS:
+ nres = strlen(values);
+ if (special==1) {
+ nres++;
+ }
+ if (special==2) {
+ narg++;
+ }
+ if(lua_pcall(L,narg,nres,0) != 0) {
+ /* Can't be more precise here, could be called before
+ * TeX initialization is complete
+ */
+ fprintf(stderr,"This went wrong: %s\n",lua_tostring(L,-1));
+ error();
+ return 0;
+ };
+ if (nres==0) {
+ return 1;
+ }
+ nres = -nres;
+ while (*values) {
+ switch (*values++) {
+ case CALLBACK_BOOLEAN:
+ if (!lua_isboolean(L,nres)) {
+ fprintf(stderr,"Expected a boolean, not: %s\n", lua_typename(L,lua_type(L,nres)));
+ goto EXIT;
+ }
+ int b = lua_toboolean(L,nres);
+ *va_arg(vl, boolean *) = (boolean)b;
+ break;
+ case CALLBACK_INTEGER:
+ if (!lua_isnumber(L,nres)) {
+ fprintf(stderr,"Expected a number, not: %s\n", lua_typename(L,lua_type(L,nres)));
+ goto EXIT;
+ }
+ b = lua_tonumber(L,nres);
+ *va_arg(vl, int *) = b;
+ break;
+ case CALLBACK_LINE: /* TeX line */
+ if (!lua_isstring(L,nres)) {
+ if (!lua_isnil(L,nres))
+ fprintf(stderr,"Expected a string for (l), not: %s\n",
+ lua_typename(L,lua_type(L,nres)));
+ goto EXIT;
+ }
+ s = (char *)lua_tolstring(L,nres, (size_t *)&len);
+ if (s!=NULL) { /* |len| can be zero */
+ bufloc = va_arg(vl, int *);
+ ret = *bufloc;
+ check_buffer_overflow (ret+len);
+ while (len--) {
+ buffer[(*bufloc)++] = *s++;
+ }
+ while ((*bufloc)-1>ret && buffer[(*bufloc)-1] == ' ')
+ (*bufloc)--;
+ } else {
+ bufloc = 0;
+ }
+ break;
+ case CALLBACK_STRNUMBER: /* TeX string */
+ if (!lua_isstring(L,nres)) {
+ if (!lua_isnil(L,nres)) {
+ fprintf(stderr,"Expected a string for (s), not: %s\n",
+ lua_typename(L,lua_type(L,nres)));
+ goto EXIT;
+ }
+ }
+ s = (char *)lua_tolstring(L,nres,(size_t *)&len);
+ if (s==NULL) /* |len| can be zero */
+ *va_arg(vl, int *) = 0;
+ else {
+ *va_arg(vl, int *) = maketexlstring(s,len);
+ }
+ break;
+ case CALLBACK_STRING: /* C string aka buffer */
+ if (!lua_isstring(L,nres)) {
+ if (!lua_isnil(L,nres)) {
+ fprintf(stderr,"Expected a string for (S), not: %s\n",
+ lua_typename(L,lua_type(L,nres)));
+ goto EXIT;
+ }
+ }
+ s = (char *)lua_tolstring(L,nres,(size_t *)&len);
+
+ if (s==NULL) /* |len| can be zero */
+ *va_arg(vl, int *) = 0;
+ else {
+ ss = xmalloc(len+1);
+ (void)memcpy(ss,s,(len+1));
+ *va_arg(vl, char **) = ss;
+ }
+ break;
+ default:
+ fprintf(stdout,"invalid return value type");
+ goto EXIT;
+ }
+ nres++;
+ }
+ retval = 1;
+ EXIT:
+ return retval;
+}
+
+void
+destroy_saved_callback (int i) {
+ luaL_unref(Luas[0],LUA_REGISTRYINDEX,i);
+}
+
+static int callback_register (lua_State *L) {
+ int cb;
+ char *s;
+ if (!lua_isstring(L,1) ||
+ ((!lua_isfunction(L,2)) && !lua_isnil(L,2))) {
+ lua_pushnil(L);
+ lua_pushstring(L,"Invalid arguments to callback.register.");
+ return 2;
+ }
+ s = (char *)lua_tostring(L,1);
+ for(cb=0;cb<total_callbacks;cb++) {
+ if (strcmp(callbacknames[cb],s)==0)
+ break;
+ }
+ if (cb==total_callbacks) {
+ lua_pushnil(L);
+ lua_pushstring(L,"No such callback exists.");
+ return 2;
+ }
+ if (lua_isfunction(L,2)) {
+ callback_set[cb]=cb;
+ } else {
+ callback_set[cb]=0;
+ }
+ luaL_checkstack(L,2,"out of stack space");
+ lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id); /* push the table */
+ lua_pushvalue(L,2); /* the function or nil */
+ lua_rawseti(L,-2,cb);
+ lua_rawseti(L,LUA_REGISTRYINDEX,callback_callbacks_id);
+ lua_pushnumber(L,cb);
+ return 1;
+}
+
+static int callback_find (lua_State *L) {
+ int cb;
+ char * s;
+ if (!lua_isstring(L,1)) {
+ lua_pushnil(L);
+ lua_pushstring(L,"Invalid arguments to callback.find.");
+ return 2;
+ }
+ s = (char *)lua_tostring(L,1);
+ for(cb=0;cb<total_callbacks;cb++) {
+ if (strcmp(callbacknames[cb],s)==0)
+ break;
+ }
+ if (cb==total_callbacks) {
+ lua_pushnil(L);
+ lua_pushstring(L,"No such callback exists.");
+ return 2;
+ }
+ luaL_checkstack(L,2,"out of stack space");
+ lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id); /* push the table */
+ lua_rawgeti(L,-1,cb);
+ return 1;
+}
+
+
+static int callback_listf (lua_State *L) {
+ int i;
+ luaL_checkstack(L,3,"out of stack space");
+ lua_newtable(L);
+ for (i=1; callbacknames[i]; i++) {
+ lua_pushstring(L,callbacknames[i]);
+ if (callback_defined(i)) {
+ lua_pushboolean(L,1);
+ } else {
+ lua_pushboolean(L,0);
+ }
+ lua_rawset(L,-3);
+ }
+ return 1;
+}
+
+static const struct luaL_reg callbacklib [] = {
+ {"find", callback_find},
+ {"register",callback_register},
+ {"list", callback_listf},
+ {NULL, NULL} /* sentinel */
+};
+
+int luaopen_callback (lua_State *L)
+{
+ luaL_register(L, "callback", callbacklib);
+ luaL_checkstack(L,1,"out of stack space");
+ lua_newtable(L);
+ callback_callbacks_id = luaL_ref(L,LUA_REGISTRYINDEX);
+ return 1;
+}
+
+
+
diff --git a/Build/source/texk/web2c/luatexdir/lua/lfontlib.c b/Build/source/texk/web2c/luatexdir/lua/lfontlib.c
new file mode 100644
index 00000000000..13632527082
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/lfontlib.c
@@ -0,0 +1,213 @@
+/* $Id: lfontlib.c 1013 2008-02-14 00:09:02Z oneiros $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+#include "nodes.h"
+
+/* this function is in vfovf.c for the moment */
+extern int make_vf_table(lua_State *L, char *name, scaled s);
+
+static int
+font_read_tfm (lua_State *L) {
+ internalfontnumber f;
+ scaled s;
+ int k;
+ char *cnom;
+ if(lua_isstring(L, 1)) {
+ cnom = (char *)lua_tostring(L, 1);
+ if(lua_isnumber(L, 2)) {
+ s = (integer)lua_tonumber(L,2);
+ if (strlen(cnom)) {
+ f = new_font();
+ if (read_tfm_info(f, cnom, "", s)) {
+ k = font_to_lua(L,f);
+ delete_font(f);
+ return k;
+ } else {
+ delete_font(f);
+ lua_pushstring(L, "font loading failed");
+ lua_error(L);
+ }
+ } else {
+ lua_pushstring(L, "expected tfm name as first argument");
+ lua_error(L);
+ }
+ } else {
+ lua_pushstring(L, "expected an integer size as second argument");
+ lua_error(L);
+ }
+ } else {
+ lua_pushstring(L, "expected tfm name as first argument");
+ lua_error(L);
+ }
+ return 2; /* not reached */
+}
+
+
+static int
+font_read_vf (lua_State *L) {
+ scaled s;
+ char *cnom;
+ if(lua_isstring(L, 1)) {
+ cnom = (char *)lua_tostring(L, 1);
+ if (strlen(cnom)) {
+ if(lua_isnumber(L, 2)) {
+ s = lua_tonumber(L,2);
+ return make_vf_table(L,cnom,s);
+ } else {
+ lua_pushstring(L, "expected an integer size as second argument");
+ lua_error(L);
+ return 2;
+ }
+ }
+ }
+ lua_pushstring(L, "expected vf name as first argument");
+ lua_error(L);
+ return 2; /* not reached */
+}
+
+static int
+tex_current_font (lua_State *L) {
+ int i;
+ i = (int)luaL_optinteger(L,1,0);
+ if (i>0) {
+ if (is_valid_font(i)) {
+ zset_cur_font(i);
+ return 0;
+ } else {
+ lua_pushstring(L, "expected a valid font id");
+ lua_error(L);
+ return 2; /* not reached */
+ }
+ } else {
+ lua_pushnumber(L,get_cur_font());
+ return 1;
+ }
+}
+
+static int
+tex_max_font (lua_State *L) {
+ lua_pushnumber(L,max_font_id());
+ return 1;
+}
+
+
+static int
+tex_each_font_next (lua_State *L) {
+ int i,m; /* id */
+ m = lua_tonumber(L,1);
+ i = lua_tonumber(L,2);
+ i++;
+ while(i<=m && !is_valid_font(i))
+ i++;
+ if (i>m) {
+ lua_pushnil(L);
+ return 1;
+ } else {
+ lua_pushnumber(L, i);
+ font_to_lua (L, i);
+ return 2;
+ }
+}
+
+static int
+tex_each_font (lua_State *L) {
+ lua_pushcclosure(L, tex_each_font_next, 0);
+ lua_pushnumber(L, max_font_id());
+ lua_pushnumber(L, 0);
+ return 3;
+}
+
+static int
+frozenfont (lua_State *L) {
+ int i;
+ i = (int)luaL_checkinteger(L,1);
+ if (i) {
+ if (is_valid_font(i)) {
+ if (font_touched(i) || font_used(i)) {
+ lua_pushboolean(L,1);
+ } else {
+ lua_pushboolean(L,0);
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+ } else {
+ lua_pushstring(L, "expected an integer argument");
+ lua_error(L);
+ }
+ return 0; /* not reached */
+}
+
+
+static int
+setfont (lua_State *L) {
+ int i;
+ i = (int)luaL_checkinteger(L,-2);
+ if (i) {
+ luaL_checktype(L,-1,LUA_TTABLE);
+ if (is_valid_font(i)) {
+ if (! (font_touched(i) || font_used(i))) {
+ font_from_lua (L,i) ;
+ } else {
+ lua_pushstring(L, "that font has been accessed already, changing it is forbidden");
+ lua_error(L);
+ }
+ } else {
+ lua_pushstring(L, "that integer id is not a valid font");
+ lua_error(L);
+ }
+ }
+ return 0;
+}
+
+
+static int
+deffont (lua_State *L) {
+ int i;
+ luaL_checktype(L,-1,LUA_TTABLE);
+
+ i = new_font();
+ if(font_from_lua (L,i)) {
+ lua_pushnumber(L,i);
+ return 1;
+ } else {
+ lua_pop(L,1); /* pop the broken table */
+ delete_font(i);
+ lua_pushstring(L, "font creation failed");
+ lua_error(L);
+ }
+ return 0; /* not reached */
+}
+
+static int
+getfont (lua_State *L) {
+ int i;
+ i = (int)luaL_checkinteger(L,-1);
+ if (i && is_valid_font(i) && font_to_lua (L, i))
+ return 1;
+ lua_pushnil(L);
+ return 1;
+}
+
+
+static const struct luaL_reg fontlib [] = {
+ {"read_tfm", font_read_tfm},
+ {"read_vf", font_read_vf},
+ {"current", tex_current_font},
+ {"max", tex_max_font},
+ {"each", tex_each_font},
+ {"getfont", getfont},
+ {"setfont", setfont},
+ {"define", deffont},
+ {"frozen", frozenfont},
+ {NULL, NULL} /* sentinel */
+};
+
+int luaopen_font (lua_State *L)
+{
+ luaL_register(L, "font", fontlib);
+ make_table(L,"fonts","getfont","setfont");
+ return 1;
+}
diff --git a/Build/source/texk/web2c/luatexdir/lua/limglib.c b/Build/source/texk/web2c/luatexdir/lua/limglib.c
new file mode 100644
index 00000000000..fd75e49799a
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/limglib.c
@@ -0,0 +1,714 @@
+/* $Id: limglib.c 1098 2008-03-09 10:28:19Z hhenkel $ */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <../lua51/lua.h>
+#include <../lua51/lauxlib.h>
+#include <ptexlib.h>
+#include "../image/image.h"
+#include "../luatex-api.h"
+
+/**********************************************************************/
+
+#ifdef DEBUG
+static void stackDump(lua_State * L, char *s)
+{
+ int i;
+ int top = lua_gettop(L);
+ printf("\n=== stackDump <%s>: ", s);
+ for (i = 1; i <= top; i++) { /* repeat for each level */
+ int t = lua_type(L, i);
+ printf("%d: ", i);
+ switch (t) {
+ case LUA_TSTRING: /* strings */
+ printf("`%s'", lua_tostring(L, i));
+ break;
+ case LUA_TBOOLEAN: /* booleans */
+ printf(lua_toboolean(L, i) ? "true" : "false");
+ break;
+ case LUA_TNUMBER: /* numbers */
+ printf("%g", lua_tonumber(L, i));
+ break;
+ default: /* other values */
+ printf("%s", lua_typename(L, t));
+ break;
+ }
+ printf(" "); /* put a separator */
+ }
+ printf("\n");
+}
+#endif
+
+/**********************************************************************/
+
+typedef enum { P__ZERO, P_ATTR, P_COLORDEPTH, P_COLORSPACE, P_DEPTH, P_FILENAME,
+ P_FILEPATH, P_HEIGHT, P_IMAGETYPE, P_INDEX, P_OBJNUM, P_PAGE, P_PAGEBOX,
+ P_TOTALPAGES, P_TRANSFORM, P_WIDTH, P_XRES, P_XSIZE, P_YRES, P_YSIZE,
+ P__SENTINEL
+} parm_idx;
+
+typedef struct {
+ const char *name; /* parameter name */
+ parm_idx idx; /* index within img_parms array */
+} parm_struct;
+
+parm_struct img_parms[] = {
+ {NULL, P__ZERO}, /* dummy; lua indices run from 1 */
+ {"attr", P_ATTR},
+ {"colordepth", P_COLORDEPTH},
+ {"colorspace", P_COLORSPACE},
+ {"depth", P_DEPTH},
+ {"filename", P_FILENAME},
+ {"filepath", P_FILEPATH},
+ {"height", P_HEIGHT},
+ {"imagetype", P_IMAGETYPE},
+ {"index", P_INDEX},
+ {"objnum", P_OBJNUM},
+ {"page", P_PAGE},
+ {"pagebox", P_PAGEBOX},
+ {"pages", P_TOTALPAGES},
+ {"transform", P_TRANSFORM},
+ {"width", P_WIDTH},
+ {"xres", P_XRES},
+ {"xsize", P_XSIZE},
+ {"yres", P_YRES},
+ {"ysize", P_YSIZE},
+ {NULL, P__SENTINEL}
+};
+
+#define imgtype_max 4
+const char *imgtype_s[] = { "none", "pdf", "png", "jpg", "jbig2", NULL };
+
+#define pagebox_max 5
+const char *pdfboxspec_s[] =
+ { "none", "media", "crop", "bleed", "trim", "art", NULL };
+
+/**********************************************************************/
+
+static void image_to_lua(lua_State * L, image * a)
+{ /* key user ... */
+ int i, j;
+ image_dict *d = img_dict(a);
+ assert(d != NULL);
+ lua_pushvalue(L, -1); /* k k u ... */
+ lua_gettable(L, LUA_ENVIRONINDEX); /* i? k u ... */
+ if (!lua_isnumber(L, -1)) /* !i k u ... */
+ luaL_error(L, "image_to_lua not a valid image key: %s",
+ lua_tostring(L, -2));
+ i = lua_tointeger(L, -1); /* i k u ... */
+ lua_pop(L, 2); /* u ... */
+ switch (i) {
+ case P_WIDTH:
+ if (is_wd_running(a))
+ lua_pushnil(L);
+ else
+ lua_pushinteger(L, img_width(a));
+ break;
+ case P_HEIGHT:
+ if (is_ht_running(a))
+ lua_pushnil(L);
+ else
+ lua_pushinteger(L, img_height(a));
+ break;
+ case P_DEPTH:
+ if (is_dp_running(a))
+ lua_pushnil(L);
+ else
+ lua_pushinteger(L, img_depth(a));
+ break;
+ case P_TRANSFORM:
+ lua_pushinteger(L, img_transform(a));
+ break;
+ /* now follow all image_dict entries */
+ case P_FILENAME:
+ if (img_filename(d) == NULL || strlen(img_filename(d)) == 0)
+ lua_pushnil(L);
+ else
+ lua_pushstring(L, img_filename(d));
+ break;
+ case P_FILEPATH:
+ if (img_filepath(d) == NULL || strlen(img_filepath(d)) == 0)
+ lua_pushnil(L);
+ else
+ lua_pushstring(L, img_filepath(d));
+ break;
+ case P_ATTR:
+ if (img_attr(d) == NULL || strlen(img_attr(d)) == 0)
+ lua_pushnil(L);
+ else
+ lua_pushstring(L, img_attr(d));
+ break;
+ case P_PAGE:
+ if (img_pagename(d) != NULL && strlen(img_pagename(d)) != 0)
+ lua_pushstring(L, img_pagename(d));
+ else
+ lua_pushinteger(L, img_pagenum(d));
+ break;
+ case P_TOTALPAGES:
+ lua_pushinteger(L, img_totalpages(d));
+ break;
+ case P_XSIZE:
+ lua_pushinteger(L, img_xsize(d));
+ break;
+ case P_YSIZE:
+ lua_pushinteger(L, img_ysize(d));
+ break;
+ case P_XRES:
+ lua_pushinteger(L, img_xres(d));
+ break;
+ case P_YRES:
+ lua_pushinteger(L, img_yres(d));
+ break;
+ case P_COLORSPACE:
+ if (img_colorspace(d) == 0)
+ lua_pushnil(L);
+ else
+ lua_pushinteger(L, img_colorspace(d));
+ break;
+ case P_COLORDEPTH:
+ if (img_colordepth(d) == 0)
+ lua_pushnil(L);
+ else
+ lua_pushinteger(L, img_colordepth(d));
+ break;
+ case P_IMAGETYPE:
+ j = img_type(d);
+ if (j >= 0 && j <= imgtype_max) {
+ if (j == IMAGE_TYPE_NONE)
+ lua_pushnil(L);
+ else
+ lua_pushstring(L, imgtype_s[j]);
+ } else
+ assert(0);
+ break;
+ case P_PAGEBOX:
+ j = img_pagebox(d);
+ if (j >= 0 && j <= pagebox_max) {
+ if (j == PDF_BOX_SPEC_NONE)
+ lua_pushnil(L);
+ else
+ lua_pushstring(L, pdfboxspec_s[j]);
+ } else
+ assert(0);
+ break;
+ case P_OBJNUM:
+ if (img_objnum(d) == 0)
+ lua_pushnil(L);
+ else
+ lua_pushinteger(L, img_objnum(d));
+ break;
+ case P_INDEX:
+ if (img_index(d) == 0)
+ lua_pushnil(L);
+ else
+ lua_pushinteger(L, img_index(d));
+ break;
+ default:
+ assert(0);
+ } /* v u ... */
+}
+
+static void lua_to_image(lua_State * L, image * a)
+{ /* value key table ... */
+ int i;
+ image_dict *d = img_dict(a);
+ assert(d != NULL);
+ lua_pushvalue(L, -2); /* k v k t ... */
+ lua_gettable(L, LUA_ENVIRONINDEX); /* i? v k t ... */
+ if (!lua_isnumber(L, -1)) /* !i v k t ... */
+ luaL_error(L, "lua_to_image not a valid image key: %s",
+ lua_tostring(L, -3));
+ i = lua_tointeger(L, -1); /* i v k t ... */
+ lua_pop(L, 1); /* v k t ... */
+ switch (i) {
+ case P_WIDTH:
+ if (img_is_refered(a))
+ luaL_error(L, "image.width is now read-only");
+ if (lua_isnil(L, -1))
+ set_wd_running(a);
+ else if (lua_type(L, -1) == LUA_TNUMBER)
+ img_width(a) = lua_tointeger(L, -1);
+ else if (lua_type(L, -1) == LUA_TSTRING)
+ img_width(a) = dimen_to_number(L, (char *) lua_tostring(L, -1));
+ else
+ luaL_error(L,
+ "image.width needs integer or nil value or dimension string");
+ img_unset_scaled(a);
+ break;
+ case P_HEIGHT:
+ if (img_is_refered(a))
+ luaL_error(L, "image.height is now read-only");
+ if (lua_isnil(L, -1))
+ set_ht_running(a);
+ else if (lua_type(L, -1) == LUA_TNUMBER)
+ img_height(a) = lua_tointeger(L, -1);
+ else if (lua_type(L, -1) == LUA_TSTRING)
+ img_height(a) = dimen_to_number(L, (char *) lua_tostring(L, -1));
+ else
+ luaL_error(L,
+ "image.height needs integer or nil value or dimension string");
+ img_unset_scaled(a);
+ break;
+ case P_DEPTH:
+ if (img_is_refered(a))
+ luaL_error(L, "image.depth is now read-only");
+ if (lua_isnil(L, -1))
+ set_dp_running(a);
+ else if (lua_type(L, -1) == LUA_TNUMBER)
+ img_depth(a) = lua_tointeger(L, -1);
+ else if (lua_type(L, -1) == LUA_TSTRING)
+ img_depth(a) = dimen_to_number(L, (char *) lua_tostring(L, -1));
+ else
+ luaL_error(L,
+ "image.depth needs integer or nil value or dimension string");
+ img_unset_scaled(a);
+ break;
+ case P_TRANSFORM:
+ if (img_is_refered(a))
+ luaL_error(L, "image.transform is now read-only");
+ if (lua_isnumber(L, -1))
+ img_transform(a) = lua_tointeger(L, -1);
+ else
+ luaL_error(L, "image.transform needs integer value");
+ img_unset_scaled(a);
+ break;
+ /* now follow all image_dict entries */
+ case P_FILENAME:
+ if (img_state(d) >= DICT_FILESCANNED)
+ luaL_error(L, "image.filename is now read-only");
+ if (lua_isstring(L, -1)) {
+ if (img_filename(d) != NULL)
+ xfree(img_filename(d));
+ img_filename(d) = xstrdup(lua_tostring(L, -1));
+ } else
+ luaL_error(L, "image.filename needs string value");
+ break;
+ case P_ATTR:
+ if (img_state(d) >= DICT_FILESCANNED)
+ luaL_error(L, "image.attr is now read-only");
+ if (lua_isstring(L, -1) || lua_isnil(L, -1)) {
+ if (img_attr(d) != NULL)
+ xfree(img_attr(d));
+ if (lua_isstring(L, -1))
+ img_attr(d) = xstrdup(lua_tostring(L, -1));
+ } else
+ luaL_error(L, "image.attr needs string or nil value");
+ break;
+ case P_PAGE:
+ if (img_state(d) >= DICT_FILESCANNED)
+ luaL_error(L, "image.page is now read-only");
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ if (img_pagename(d) != NULL)
+ xfree(img_pagename(d));
+ img_pagename(d) = xstrdup(lua_tostring(L, -1));
+ img_pagenum(d) = 0;
+ } else if (lua_type(L, -1) == LUA_TNUMBER) {
+ img_pagenum(d) = lua_tointeger(L, -1);
+ if (img_pagename(d) != NULL)
+ xfree(img_pagename(d));
+ img_pagename(d) = NULL;
+ } else
+ luaL_error(L, "image.page needs integer or string value");
+ break;
+ case P_COLORSPACE:
+ if (img_state(d) >= DICT_FILESCANNED)
+ luaL_error(L, "image.colorspace is now read-only");
+ if (lua_isnil(L, -1))
+ img_colorspace(d) = 0;
+ else if (lua_isnumber(L, -1))
+ img_colorspace(d) = lua_tointeger(L, -1);
+ else
+ luaL_error(L, "image.colorspace needs integer or nil value");
+ break;
+ case P_PAGEBOX:
+ if (img_state(d) >= DICT_FILESCANNED)
+ luaL_error(L, "image.pagebox is now read-only");
+ if (lua_isnil(L, -1))
+ img_pagebox(d) = PDF_BOX_SPEC_NONE;
+ else if (lua_isstring(L, -1))
+ img_pagebox(d) = luaL_checkoption(L, -1, "none", pdfboxspec_s);
+ else
+ luaL_error(L, "image.pagebox needs string or nil value");
+ break;
+ case P_FILEPATH:
+ case P_TOTALPAGES:
+ case P_XSIZE:
+ case P_YSIZE:
+ case P_XRES:
+ case P_YRES:
+ case P_IMAGETYPE:
+ case P_OBJNUM:
+ case P_INDEX:
+ case P_COLORDEPTH:
+ luaL_error(L, "image.%s is a read-only variable", img_parms[i].name);
+ break;
+ default:
+ assert(0);
+ } /* v k t ... */
+}
+
+/**********************************************************************/
+
+void fix_image_size(lua_State * L, image * a)
+{
+ if (!img_is_scaled(a) || is_wd_running(a) || is_ht_running(a)
+ || is_dp_running(a)) {
+ if (img_is_refered(a))
+ luaL_error(L, "image is read-only");
+ scale_img(a);
+ }
+}
+
+void copy_image(lua_State * L, lua_Number scale)
+{
+ image *a, **aa, *b, **bb;
+ if (lua_gettop(L) != 1)
+ luaL_error(L, "img.copy() needs exactly 1 argument");
+ aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* a */
+ lua_pop(L, 1); /* - */
+ a = *aa;
+ bb = (image **) lua_newuserdata(L, sizeof(image *)); /* b */
+ luaL_getmetatable(L, TYPE_IMG); /* m b */
+ lua_setmetatable(L, -2); /* b */
+ b = *bb = new_image();
+ if (!is_wd_running(a))
+ img_width(b) = zround(img_width(a) * scale);
+ if (!is_ht_running(a))
+ img_height(b) = zround(img_height(a) * scale);
+ if (!is_dp_running(a))
+ img_depth(b) = zround(img_depth(a) * scale);
+ img_transform(b) = img_transform(a);
+ img_dict(b) = img_dict(a);
+ if (img_dictref(a) != LUA_NOREF) {
+ lua_rawgeti(L, LUA_GLOBALSINDEX, img_dictref(a)); /* ad b */
+ img_dictref(b) = luaL_ref(L, LUA_GLOBALSINDEX); /* b */
+ } else
+ assert(img_state(img_dict(a)) >= DICT_REFERED);
+}
+
+/**********************************************************************/
+
+static int l_new_image(lua_State * L)
+{
+ image *a, **aa;
+ if (lua_gettop(L) > 1)
+ luaL_error(L, "img.new() needs maximum 1 argument");
+ if (lua_gettop(L) == 1 && !lua_istable(L, 1))
+ luaL_error(L, "img.new() needs table as optional argument"); /* (t) */
+ aa = (image **) lua_newuserdata(L, sizeof(image *)); /* i (t) */
+ luaL_getmetatable(L, TYPE_IMG); /* m i (t) */
+ lua_setmetatable(L, -2); /* i (t) */
+ a = *aa = new_image();
+ image_dict **add = (image_dict **) lua_newuserdata(L, sizeof(image_dict *)); /* ad i (t) */
+ luaL_getmetatable(L, TYPE_IMG_DICT); /* m ad i (t) */
+ lua_setmetatable(L, -2); /* ad i (t) */
+ img_dict(a) = *add = new_image_dict();
+ img_dictref(a) = luaL_ref(L, LUA_GLOBALSINDEX); /* i (t) */
+ if (lua_gettop(L) != 1) { /* i t, else just i */
+ lua_insert(L, -2); /* t i */
+ lua_pushnil(L); /* n t i (1st key for iterator) */
+ while (lua_next(L, -2) != 0) { /* v k t i */
+ lua_to_image(L, a); /* v k t i */
+ lua_pop(L, 1); /* k t i */
+ } /* t i */
+ lua_pop(L, 1); /* i */
+ } /* i */
+ return 1; /* i */
+}
+
+static int l_copy_image(lua_State * L)
+{
+ if (lua_gettop(L) != 1)
+ luaL_error(L, "img.copy() needs exactly 1 argument");
+ if (lua_istable(L, 1))
+ l_new_image(L); /* image --- if everything worked well */
+ else
+ copy_image(L, 1.0); /* image */
+ return 1; /* image */
+}
+
+static int l_scan_image(lua_State * L)
+{
+ image *a, **aa;
+ if (lua_gettop(L) != 1)
+ luaL_error(L, "img.scan() needs exactly 1 argument");
+ if (lua_istable(L, 1))
+ l_new_image(L); /* image --- if everything worked well */
+ aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* image */
+ a = *aa;
+ image_dict *ad = img_dict(a);
+ if (img_state(ad) == DICT_NEW) {
+ read_img(ad, get_pdf_minor_version(), get_pdf_inclusion_errorlevel());
+ img_unset_scaled(a);
+ }
+ fix_image_size(L, a);
+ return 1; /* image */
+}
+
+/* these should go into some header file... */
+#define obj_type_ximage 8
+#define obj_aux(a) obj_tab[a].int4 /* auxiliary pointer */
+#define obj_data_ptr obj_aux /* pointer to |pdf_mem| */
+
+static halfword img_to_node(image * a, integer ref)
+{
+ image_dict *ad = img_dict(a);
+ assert(ad != NULL);
+ assert(img_objnum(ad) != 0);
+ halfword n = new_node(whatsit_node, pdf_refximage_node);
+ pdf_ximage_ref(n) = ref;
+ pdf_width(n) = img_width(a);
+ pdf_height(n) = img_height(a);
+ pdf_depth(n) = img_depth(a);
+ return n;
+}
+
+typedef enum { WR_WRITE, WR_IMMEDIATEWRITE, WR_NODE } wrtype_e;
+const char *wrtype_s[] =
+ { "img.write()", "img.immediatewrite()", "img.node()" };
+
+extern void lua_nodelib_push_fast(lua_State * L, halfword n);
+
+static void write_image_or_node(lua_State * L, wrtype_e writetype)
+{
+ image *a, **aa;
+ halfword n;
+ if (lua_gettop(L) != 1)
+ luaL_error(L, "%s needs exactly 1 argument", wrtype_s[writetype]);
+ if (lua_istable(L, 1))
+ l_new_image(L); /* image --- if everything worked well */
+ aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* image */
+ a = *aa;
+ image_dict *ad = img_dict(a);
+ assert(ad != NULL);
+ if (img_state(ad) == DICT_NEW) {
+ read_img(ad, get_pdf_minor_version(), get_pdf_inclusion_errorlevel());
+ img_unset_scaled(a);
+ }
+ fix_image_size(L, a);
+ check_pdfoutput(maketexstring(wrtype_s[writetype]), true);
+ flush_str(last_tex_string);
+ integer ref = img_to_array(a);
+ if (img_objnum(ad) == 0) { /* not strictly needed here, could be delayed until out_image() */
+ pdf_ximage_count++;
+ pdf_create_obj(obj_type_ximage, pdf_ximage_count);
+ img_objnum(ad) = obj_ptr;
+ img_index(ad) = pdf_ximage_count;
+ obj_data_ptr(obj_ptr) = ref;
+ }
+ switch (writetype) {
+ case WR_WRITE:
+ n = img_to_node(a, ref);
+ new_tail_append(n);
+ break; /* image */
+ case WR_IMMEDIATEWRITE:
+ check_pdfminorversion(); /* does initialization stuff */
+ pdf_begin_dict(img_objnum(ad), 0);
+ write_img(ad);
+ break; /* image */
+ case WR_NODE: /* image */
+ lua_pop(L, 1); /* - */
+ n = img_to_node(a, ref);
+ lua_nodelib_push_fast(L, n);
+ break; /* node */
+ default:
+ assert(0);
+ }
+ if (img_state(ad) < DICT_REFERED)
+ img_state(ad) = DICT_REFERED;
+ img_set_refered(a); /* now image may not be freed by gc */
+}
+
+static int l_write_image(lua_State * L)
+{
+ write_image_or_node(L, WR_WRITE);
+ return 1; /* image */
+}
+
+static int l_immediatewrite_image(lua_State * L)
+{
+ write_image_or_node(L, WR_IMMEDIATEWRITE);
+ return 1; /* image */
+}
+
+static int l_image_node(lua_State * L)
+{
+ write_image_or_node(L, WR_NODE);
+ return 1; /* node */
+}
+
+static int l_image_keys(lua_State * L)
+{
+ parm_struct *p = img_parms + 1;
+ if (lua_gettop(L) != 0)
+ luaL_error(L, "img.keys() goes without argument");
+ lua_newtable(L); /* t */
+ for (; p->name != NULL; p++) {
+ lua_pushinteger(L, (int) p->idx); /* k t */
+ lua_pushstring(L, p->name); /* v k t */
+ lua_settable(L, -3); /* t */
+ }
+ return 1;
+}
+
+static int l_image_types(lua_State * L)
+{
+ int i;
+ char **p;
+ if (lua_gettop(L) != 0)
+ luaL_error(L, "img.types() goes without argument");
+ lua_newtable(L); /* t */
+ for (i = 1, p = (char **) (imgtype_s + 1); *p != NULL; p++, i++) {
+ lua_pushinteger(L, (int) i); /* k t */
+ lua_pushstring(L, *p); /* v k t */
+ lua_settable(L, -3); /* t */
+ }
+ return 1;
+}
+
+static int l_image_boxes(lua_State * L)
+{
+ int i;
+ char **p;
+ if (lua_gettop(L) != 0)
+ luaL_error(L, "img.boxes() goes without argument");
+ lua_newtable(L); /* t */
+ for (i = 1, p = (char **) (pdfboxspec_s + 1); *p != NULL; p++, i++) {
+ lua_pushinteger(L, (int) i); /* k t */
+ lua_pushstring(L, *p); /* v k t */
+ lua_settable(L, -3); /* t */
+ }
+ return 1;
+}
+
+static const struct luaL_Reg imglib[] = {
+ {"new", l_new_image},
+ {"copy", l_copy_image},
+ {"scan", l_scan_image},
+ {"write", l_write_image},
+ {"immediatewrite", l_immediatewrite_image},
+ {"node", l_image_node},
+ {"keys", l_image_keys},
+ {"types", l_image_types},
+ {"boxes", l_image_boxes},
+ {NULL, NULL} /* sentinel */
+};
+
+/**********************************************************************/
+/* Metamethods for image */
+
+static int m_img_get(lua_State * L)
+{
+ image **aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* k u */
+ image_to_lua(L, *aa); /* v u */
+ return 1;
+}
+
+static int m_img_set(lua_State * L)
+{
+ image **aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* value key user */
+ lua_to_image(L, *aa); /* v k u */
+ return 0;
+}
+
+static int m_img_mul(lua_State * L)
+{
+ image **aa;
+ lua_Number scale;
+ if (lua_isnumber(L, 1)) { /* u? n */
+ aa = (image **) luaL_checkudata(L, 2, TYPE_IMG); /* u n */
+ lua_insert(L, -2); /* n a */
+ } else if (lua_isnumber(L, 2)) { /* n u? */
+ aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* n a */
+ } /* n a */
+ scale = lua_tonumber(L, 2); /* n a */
+ lua_pop(L, 1); /* a */
+ copy_image(L, scale); /* b */
+ return 1;
+}
+
+static int m_img_print(lua_State * L)
+{
+ image **aa = (image **) luaL_checkudata(L, 1, TYPE_IMG);
+ image_dict *d = img_dict(*aa);
+ if (img_pagename(d) != NULL && strlen(img_pagename(d)) != 0)
+ lua_pushfstring(L, "<img{filename=\"%s\", page=\"%s\"}>",
+ img_filename(d), img_pagename(d));
+ else
+ lua_pushfstring(L, "<img{filename=\"%s\", page=%d}>", img_filename(d),
+ img_pagenum(d));
+ return 1;
+}
+
+static int m_img_gc(lua_State * L)
+{
+ image *a, **aa;
+ aa = (image **) luaL_checkudata(L, 1, TYPE_IMG);
+ a = *aa;
+#ifdef DEBUG
+ printf("\n===== IMG GC ===== a=%d ad=%d\n", a, img_dict(a));
+#endif
+ luaL_unref(L, LUA_GLOBALSINDEX, img_dictref(a));
+ if (!img_is_refered(a))
+ xfree(a);
+ return 0;
+}
+
+static const struct luaL_Reg img_m[] = {
+ {"__index", m_img_get},
+ {"__newindex", m_img_set},
+ {"__mul", m_img_mul},
+ {"__tostring", m_img_print},
+ {"__gc", m_img_gc}, /* finalizer */
+ {NULL, NULL} /* sentinel */
+};
+
+/**********************************************************************/
+/* Metamethods for image_dict */
+
+static int m_img_dict_gc(lua_State * L)
+{
+ image_dict *ad, **add;
+ add = (image_dict **) luaL_checkudata(L, 1, TYPE_IMG_DICT);
+ ad = *add;
+#ifdef DEBUG
+ printf("\n===== IMG_DICT GC FREE ===== ad=%d\n", ad);
+#endif
+ if (img_state(ad) < DICT_REFERED)
+ free_image_dict(ad);
+ return 0;
+}
+
+static const struct luaL_Reg img_dict_m[] = {
+ {"__gc", m_img_dict_gc}, /* finalizer */
+ {NULL, NULL} /* sentinel */
+};
+
+/**********************************************************************/
+
+void preset_environment(lua_State * L, parm_struct * p)
+{
+ int i;
+ lua_newtable(L); /* t */
+ for (i = 1, ++p; p->name != NULL; i++, p++) {
+ assert(i == (int) p->idx);
+ lua_pushstring(L, p->name); /* k t */
+ lua_pushinteger(L, (int) p->idx); /* v k t */
+ lua_settable(L, -3); /* t */
+ }
+ lua_replace(L, LUA_ENVIRONINDEX); /* - */
+}
+
+int luaopen_img(lua_State * L)
+{
+ preset_environment(L, img_parms);
+ luaL_newmetatable(L, TYPE_IMG);
+ luaL_register(L, NULL, img_m);
+ luaL_newmetatable(L, TYPE_IMG_DICT);
+ luaL_register(L, NULL, img_dict_m);
+ luaL_register(L, "img", imglib);
+ return 1;
+}
+
+/**********************************************************************/
diff --git a/Build/source/texk/web2c/luatexdir/lua/lkpselib.c b/Build/source/texk/web2c/luatexdir/lua/lkpselib.c
new file mode 100644
index 00000000000..5ec4dfed869
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/lkpselib.c
@@ -0,0 +1,272 @@
+/* $Id: lkpselib.c 1061 2008-02-20 09:51:04Z taco $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+#include <kpathsea/expand.h>
+#include <kpathsea/variable.h>
+#include <kpathsea/tex-glyph.h>
+#include <kpathsea/readable.h>
+
+static const int filetypes[] = {
+ kpse_gf_format,
+ kpse_pk_format,
+ kpse_any_glyph_format,
+ kpse_tfm_format,
+ kpse_afm_format,
+ kpse_base_format,
+ kpse_bib_format,
+ kpse_bst_format,
+ kpse_cnf_format,
+ kpse_db_format,
+ kpse_fmt_format,
+ kpse_fontmap_format,
+ kpse_mem_format,
+ kpse_mf_format,
+ kpse_mfpool_format,
+ kpse_mft_format,
+ kpse_mp_format,
+ kpse_mppool_format,
+ kpse_mpsupport_format,
+ kpse_ocp_format,
+ kpse_ofm_format,
+ kpse_opl_format,
+ kpse_otp_format,
+ kpse_ovf_format,
+ kpse_ovp_format,
+ kpse_pict_format,
+ kpse_tex_format,
+ kpse_texdoc_format,
+ kpse_texpool_format,
+ kpse_texsource_format,
+ kpse_tex_ps_header_format,
+ kpse_troff_font_format,
+ kpse_type1_format,
+ kpse_vf_format,
+ kpse_dvips_config_format,
+ kpse_ist_format,
+ kpse_truetype_format,
+ kpse_type42_format,
+ kpse_web2c_format,
+ kpse_program_text_format,
+ kpse_program_binary_format,
+ kpse_miscfonts_format,
+ kpse_web_format,
+ kpse_cweb_format,
+ kpse_enc_format,
+ kpse_cmap_format,
+ kpse_sfd_format,
+ kpse_opentype_format,
+ kpse_pdftex_config_format,
+ kpse_lig_format,
+ kpse_texmfscripts_format };
+
+static const char *const filetypenames[] = {
+ "gf",
+ "pk",
+ "bitmap font",
+ "tfm",
+ "afm",
+ "base",
+ "bib",
+ "bst",
+ "cnf",
+ "ls-R",
+ "fmt",
+ "map",
+ "mem",
+ "mf",
+ "mfpool",
+ "mft",
+ "mp",
+ "mppool",
+ "MetaPost support",
+ "ocp",
+ "ofm",
+ "opl",
+ "otp",
+ "ovf",
+ "ovp",
+ "graphic/figure",
+ "tex",
+ "TeX system documentation",
+ "texpool",
+ "TeX system sources",
+ "PostScript header",
+ "Troff fonts",
+ "type1 fonts",
+ "vf",
+ "dvips config",
+ "ist",
+ "truetype fonts",
+ "type42 fonts",
+ "web2c files",
+ "other text files",
+ "other binary files",
+ "misc fonts",
+ "web",
+ "cweb",
+ "enc files",
+ "cmap files",
+ "subfont definition files",
+ "opentype fonts",
+ "pdftex config",
+ "lig files",
+ "texmfscripts",
+ NULL };
+
+/* set to 1 by the |program_name| function */
+
+int program_name_set = 0;
+
+#define TEST_PROGRAM_NAME_SET do { \
+ if (! program_name_set) { \
+ lua_pushstring(L, "Please call kpse.set_program_name() before using the library"); \
+ return lua_error(L); \
+ } \
+ } while (0)
+
+static int find_file (lua_State *L) {
+ int i;
+ char *st;
+ int ftype = kpse_tex_format;
+ int mexist = 0;
+ TEST_PROGRAM_NAME_SET;
+ if (!lua_isstring(L,1)) {
+ lua_pushstring(L, "not a file name");
+ lua_error(L);
+ }
+ st = (char *)lua_tostring(L,1);
+ i = lua_gettop(L);
+ while (i>1) {
+ if (lua_isboolean (L,i)) {
+ mexist = lua_toboolean (L,i);
+ } else if (lua_isnumber (L,i)) {
+ mexist = lua_tonumber (L,i) ;
+ } else if (lua_isstring(L,i)) {
+ int op = luaL_checkoption(L, i, NULL, filetypenames);
+ ftype = filetypes[op];
+ }
+ i--;
+ }
+ if (ftype==kpse_pk_format ||
+ ftype==kpse_gf_format ||
+ ftype==kpse_any_glyph_format) {
+ /* ret.format, ret.name, ret.dpi */
+ kpse_glyph_file_type ret;
+ lua_pushstring(L, kpse_find_glyph (st,mexist, ftype, &ret));
+ } else {
+ if (mexist>0)
+ mexist = 1;
+ if (mexist<0)
+ mexist = 0;
+ lua_pushstring(L, kpse_find_file (st,ftype,mexist));
+ }
+ return 1;
+}
+
+static int show_path (lua_State *L) {
+ int op = luaL_checkoption(L, -1, "tex", filetypenames);
+ int user_format = filetypes[op];
+ TEST_PROGRAM_NAME_SET;
+ if (!kpse_format_info[user_format].type) /* needed if arg was numeric */
+ kpse_init_format (user_format);
+ lua_pushstring (L, kpse_format_info[user_format].path);
+ return 1;
+}
+
+
+static int expand_path (lua_State *L) {
+ const char *st = luaL_checkstring(L,1);
+ TEST_PROGRAM_NAME_SET;
+ lua_pushstring(L, kpse_path_expand(st));
+ return 1;
+}
+
+static int expand_braces (lua_State *L) {
+ const char *st = luaL_checkstring(L,1);
+ TEST_PROGRAM_NAME_SET;
+ lua_pushstring(L, kpse_brace_expand(st));
+ return 1;
+}
+
+static int expand_var (lua_State *L) {
+ const char *st = luaL_checkstring(L,1);
+ TEST_PROGRAM_NAME_SET;
+ lua_pushstring(L, kpse_var_expand(st));
+ return 1;
+}
+
+static int var_value (lua_State *L) {
+ const char *st = luaL_checkstring(L,1);
+ TEST_PROGRAM_NAME_SET;
+ lua_pushstring(L, kpse_var_value(st));
+ return 1;
+}
+
+/* Engine support is a bit of a problem, because we do not want
+ * to interfere with the normal format discovery of |luatex|.
+ * Current approach: run |os.setenv()| if you have to.
+ */
+
+extern int luainit;
+
+static int set_program_name (lua_State *L) {
+ const char *exe_name = luaL_checkstring(L,1);
+ const char *prog_name = luaL_optstring(L,2,exe_name);
+ if (! program_name_set) {
+ kpse_set_program_name(exe_name, prog_name);
+ program_name_set = 1;
+ } else {
+ kpse_reset_program_name(prog_name);
+ }
+ /* fix up the texconfig entry */
+ lua_checkstack(L,3);
+ lua_getglobal(L,"texconfig");
+ if (lua_istable(L,-1)) {
+ lua_pushstring(L,"kpse_init");
+ lua_pushboolean(L,0);
+ lua_rawset(L,-3);
+ }
+ lua_pop(L,1);
+ return 0;
+}
+
+static int init_prog (lua_State *L) {
+ const char *prefix = luaL_checkstring(L,1);
+ unsigned dpi = luaL_checkinteger(L,2);
+ const char *mode = luaL_checkstring(L,3);
+ const char *fallback = luaL_optstring(L,4,NULL);
+ TEST_PROGRAM_NAME_SET;
+ kpse_init_prog(prefix,dpi,mode,fallback);
+ return 0;
+}
+
+static int readable_file (lua_State *L) {
+ const char *name = luaL_checkstring(L,1);
+ TEST_PROGRAM_NAME_SET;
+ lua_pushstring(L,(char *)kpse_readable_file (name));
+ return 1;
+}
+
+
+static const struct luaL_reg kpselib [] = {
+ {"set_program_name", set_program_name},
+ {"init_prog", init_prog},
+ {"readable_file", readable_file},
+ {"find_file", find_file},
+ {"expand_path", expand_path},
+ {"expand_var", expand_var},
+ {"expand_braces",expand_braces},
+ {"var_value",var_value},
+ {"show_path",show_path},
+ {NULL, NULL} /* sentinel */
+};
+
+
+int
+luaopen_kpse (lua_State *L)
+{
+ luaL_register(L,"kpse",kpselib);
+ return 1;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/lua/llanglib.c b/Build/source/texk/web2c/luatexdir/lua/llanglib.c
new file mode 100644
index 00000000000..63e8c45dec8
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/llanglib.c
@@ -0,0 +1,219 @@
+/*
+Copyright (c) 2007 Taco Hoekwater <taco@latex.org>
+
+This file is part of luatex.
+
+luatex is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+luatex is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with luatex; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+This is llanglib.c
+*/
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+#include "nodes.h"
+
+#define LANG_METATABLE "luatex.lang"
+
+#define check_islang(L,b) (struct tex_language **)luaL_checkudata(L,b,LANG_METATABLE)
+
+static int
+lang_new (lua_State *L) {
+ struct tex_language **lang;
+ if (lua_gettop(L)==0) {
+ lang = lua_newuserdata(L, sizeof(struct tex_language *));
+ *lang = new_language();
+ if (!*lang) {
+ lua_pushstring(L,"lang.new(): no room for a new language");
+ return lua_error(L);
+ }
+ } else {
+ lang = lua_newuserdata(L, sizeof(struct tex_language *));
+ *lang = get_language(lua_tonumber(L,1));
+ }
+ luaL_getmetatable(L,LANG_METATABLE);
+ lua_setmetatable(L,-2);
+ return 1;
+}
+
+static int
+lang_id (lua_State *L) {
+ struct tex_language **lang_ptr;
+ lang_ptr = check_islang(L,1);
+ lua_pushnumber(L,(*lang_ptr)->id);
+ return 1;
+}
+
+static int
+lang_patterns (lua_State *L) {
+ struct tex_language **lang_ptr;
+ lang_ptr = check_islang(L,1);
+ if (lua_gettop(L)!=1) {
+ if (!lua_isstring(L,2)) {
+ lua_pushstring(L,"lang.patterns(): argument should be a string");
+ return lua_error(L);
+ }
+ load_patterns(*lang_ptr, (unsigned char *)lua_tostring(L,2));
+ return 0;
+ } else {
+ if ((*lang_ptr)->patterns!=NULL) {
+ lua_pushstring(L,(char *)hnj_serialize((*lang_ptr)->patterns));
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+ }
+}
+
+static int
+lang_clear_patterns (lua_State *L) {
+ struct tex_language **lang_ptr;
+ lang_ptr = check_islang(L,1);
+ clear_patterns(*lang_ptr);
+ return 0;
+}
+
+
+static int
+lang_hyphenation (lua_State *L) {
+ struct tex_language **lang_ptr;
+ lang_ptr = check_islang(L,1);
+ if (lua_gettop(L)!=1) {
+ if(!lua_isstring(L,2)) {
+ lua_pushstring(L,"lang.hyphenation(): argument should be a string");
+ return lua_error(L);
+ }
+ load_hyphenation(*lang_ptr,(unsigned char *)lua_tostring(L,2));
+ return 0;
+ } else {
+ if ((*lang_ptr)->exceptions!=0) {
+ lua_pushstring(L,exception_strings(*lang_ptr));
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+ }
+}
+
+static int
+lang_pre_hyphen_char (lua_State *L) {
+ struct tex_language **lang_ptr;
+ lang_ptr = check_islang(L,1);
+ if (lua_gettop(L)!=1) {
+ if(!lua_isnumber(L,2)) {
+ lua_pushstring(L,"lang.prehyphenchar(): argument should be a character number");
+ return lua_error(L);
+ }
+ (*lang_ptr)->pre_hyphen_char = lua_tonumber(L,2);
+ return 0;
+ } else {
+ lua_pushnumber(L,(*lang_ptr)->pre_hyphen_char);
+ return 1;
+ }
+}
+
+static int
+lang_post_hyphen_char (lua_State *L) {
+ struct tex_language **lang_ptr;
+ lang_ptr = check_islang(L,1);
+ if (lua_gettop(L)!=1) {
+ if(!lua_isnumber(L,2)) {
+ lua_pushstring(L,"lang.posthyphenchar(): argument should be a character number");
+ return lua_error(L);
+ }
+ (*lang_ptr)->post_hyphen_char = lua_tonumber(L,2);
+ return 0;
+ } else {
+ lua_pushnumber(L,(*lang_ptr)->post_hyphen_char);
+ return 1;
+ }
+}
+
+static int
+lang_clear_hyphenation (lua_State *L) {
+ struct tex_language **lang_ptr;
+ lang_ptr = check_islang(L,1);
+ clear_hyphenation(*lang_ptr);
+ return 0;
+}
+
+
+static int
+do_lang_clean (lua_State *L) {
+ char *cleaned;
+ if (!lua_isstring(L,1)) {
+ lua_pushstring(L,"lang.clean(): argument should be a string");
+ return lua_error(L);
+ }
+ (void)clean_hyphenation((char *)lua_tostring(L,1),&cleaned);
+ lua_pushstring(L,cleaned);
+ return 1;
+}
+
+static int
+do_lang_hyphenate (lua_State *L) {
+ halfword *h,*t;
+ h = check_isnode(L,1);
+ if (lua_isuserdata(L,2)) {
+ t = check_isnode(L,2);
+ lua_pop(L,1);
+ } else {
+ t = h;
+ while (vlink(*t)!=null)
+ *t = vlink(*t);
+ }
+ hnj_hyphenation(*h,*t);
+ lua_pushboolean(L,1);
+ return 1;
+}
+
+
+static const struct luaL_reg langlib_d [] = {
+ {"clear_patterns", lang_clear_patterns},
+ {"clear_hyphenation", lang_clear_hyphenation},
+ {"patterns", lang_patterns},
+ {"hyphenation", lang_hyphenation},
+ {"prehyphenchar", lang_pre_hyphen_char},
+ {"posthyphenchar", lang_post_hyphen_char},
+ {"id", lang_id},
+ {NULL, NULL} /* sentinel */
+};
+
+
+static const struct luaL_reg langlib[] = {
+ {"clear_patterns", lang_clear_patterns},
+ {"clear_hyphenation", lang_clear_hyphenation},
+ {"patterns", lang_patterns},
+ {"hyphenation", lang_hyphenation},
+ {"prehyphenchar", lang_pre_hyphen_char},
+ {"posthyphenchar", lang_post_hyphen_char},
+ {"id", lang_id},
+ {"clean", do_lang_clean},
+ {"hyphenate", do_lang_hyphenate},
+ {"new", lang_new},
+ {NULL, NULL} /* sentinel */
+};
+
+
+int
+luaopen_lang (lua_State *L) {
+ luaL_newmetatable(L,LANG_METATABLE);
+ lua_pushvalue(L, -1); /* push metatable */
+ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
+ luaL_register(L, NULL, langlib_d); /* dict methods */
+ luaL_register(L, "lang", langlib);
+ return 1;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/lua/llualib.c b/Build/source/texk/web2c/luatexdir/lua/llualib.c
new file mode 100644
index 00000000000..0d13500a9b7
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/llualib.c
@@ -0,0 +1,229 @@
+
+/* $Id: llualib.c 1013 2008-02-14 00:09:02Z oneiros $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+#define LOAD_BUF_SIZE 256
+#define UINT_MAX32 0xFFFFFFFF
+
+typedef struct {
+ unsigned char* buf;
+ int size;
+ int done;
+ int alloc;
+} bytecode;
+
+static bytecode *lua_bytecode_registers = NULL;
+
+int luabytecode_max = -1;
+unsigned int luabytecode_bytes = 0;
+
+void dump_luac_registers (void) {
+ int k,n;
+ bytecode b;
+ dump_int(luabytecode_max);
+ if (lua_bytecode_registers != NULL) {
+ n = 0;
+ for (k=0;k<=luabytecode_max;k++) {
+ if (lua_bytecode_registers[k].size != 0)
+ n++;
+ }
+ dump_int(n);
+ for (k=0;k<=luabytecode_max;k++) {
+ b = lua_bytecode_registers[k];
+ if (b.size != 0) {
+ dump_int(k);
+ dump_int(b.size);
+ do_zdump ((char *)b.buf,1,(b.size), DUMP_FILE);
+ }
+ }
+ }
+}
+
+void undump_luac_registers (void) {
+ int k,n;
+ unsigned int i;
+ bytecode b;
+ undump_int(luabytecode_max);
+ if (luabytecode_max>=0) {
+ i = (luabytecode_max+1);
+ if ((int)(UINT_MAX32/sizeof(bytecode)+1)<=i) {
+ lua_fatal_error("Corrupt format file");
+ }
+ lua_bytecode_registers = xmalloc(i*sizeof(bytecode));
+ luabytecode_bytes = i*sizeof(bytecode);
+ for (i=0;i<=luabytecode_max;i++) {
+ lua_bytecode_registers[i].done = 0;
+ lua_bytecode_registers[i].size = 0;
+ lua_bytecode_registers[i].buf = NULL;
+ }
+ undump_int(n);
+ for (i=0;i<n;i++) {
+ undump_int(k);
+ undump_int(b.size);
+ b.buf=xmalloc(b.size);
+ luabytecode_bytes += b.size;
+ memset(b.buf, 0, b.size);
+ do_zundump ((char *)b.buf,1, b.size, DUMP_FILE);
+ lua_bytecode_registers[k].size = b.size;
+ lua_bytecode_registers[k].alloc = b.size;
+ lua_bytecode_registers[k].buf = b.buf;
+ }
+ }
+}
+
+static void
+bytecode_register_shadow_set (lua_State* L, int k){
+ /* the stack holds the value to be set */
+ lua_pushstring(L,"bytecode_shadow"); /* lua.bytecode_shadow */
+ lua_rawget(L,LUA_REGISTRYINDEX);
+ if (lua_istable(L, -1)) {
+ lua_pushvalue(L,-2);
+ lua_rawseti(L,-2,k);
+ }
+ lua_pop(L,1); /* pop table or nil */
+ lua_pop(L,1); /* pop value */
+}
+
+
+static int
+bytecode_register_shadow_get (lua_State* L, int k){
+ /* the stack holds the value to be set */
+ int ret = 0;
+ lua_pushstring(L,"bytecode_shadow");
+ lua_rawget(L,LUA_REGISTRYINDEX);
+ if (lua_istable(L, -1)) {
+ lua_rawgeti(L,-1,k);
+ if (!lua_isnil(L,-1))
+ ret = 1;
+ lua_insert(L,-3); /* store the value or nil, deeper down */
+ lua_pop(L,1); /* pop the value or nil at top */
+ }
+ lua_pop(L,1); /* pop table or nil */
+ return ret;
+}
+
+
+int writer(lua_State* L, const void* b, size_t size, void* B) {
+ bytecode* buf = (bytecode*)B;
+ if (buf->size + size > buf->alloc) {
+ buf->buf = xrealloc(buf->buf,buf->alloc+size+LOAD_BUF_SIZE);
+ buf->alloc = buf->alloc+size+LOAD_BUF_SIZE;
+ }
+ memcpy(buf->buf+buf->size, b, size);
+ buf->size += size;
+ luabytecode_bytes += size;
+ return 0;
+}
+
+const char* reader(lua_State* L, void* ud, size_t* size) {
+ bytecode* buf = (bytecode*)ud;
+ if (buf->done == buf->size) {
+ *size = 0;
+ buf->done = 0;
+ return NULL;
+ }
+ *size = buf->size;
+ buf->done = buf->size;
+ return (const char*)buf->buf;
+}
+
+int get_bytecode (lua_State *L) {
+ int k;
+ k = (int)luaL_checkinteger(L,-1);
+ if (k<0) {
+ lua_pushnil(L);
+ } else if (!bytecode_register_shadow_get(L,k)) {
+ if (k<=luabytecode_max && lua_bytecode_registers[k].buf != NULL) {
+ if(lua_load(L,reader,(void *)(lua_bytecode_registers+k),"bytecode")) {
+ lua_error(L);
+ lua_pushnil(L);
+ } else {
+ lua_pushvalue(L,-1);
+ bytecode_register_shadow_set(L,k);
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ }
+ return 1;
+}
+
+int set_bytecode (lua_State *L) {
+ int k, ltype;
+ unsigned int i;
+ k = (int)luaL_checkinteger(L,-2);
+ i = k+1;
+ if ((int)(UINT_MAX32/sizeof(bytecode)+1)<i) {
+ lua_pushstring(L, "value too large");
+ lua_error(L);
+ }
+ if (k<0) {
+ lua_pushstring(L, "negative values not allowed");
+ lua_error(L);
+ }
+ ltype = lua_type(L,-1);
+ if (ltype != LUA_TFUNCTION && ltype != LUA_TNIL){
+ lua_pushstring(L, "unsupported type");
+ lua_error(L);
+ }
+ if (k>luabytecode_max) {
+ i = sizeof(bytecode)*(k+1);
+ lua_bytecode_registers = xrealloc(lua_bytecode_registers,i);
+ if (luabytecode_max==-1) {
+ luabytecode_bytes += sizeof(bytecode)*(k+1);
+ } else {
+ luabytecode_bytes += sizeof(bytecode)*(k+1-luabytecode_max);
+ }
+ for (i=(luabytecode_max+1);i<=k;i++) {
+ lua_bytecode_registers[i].buf=NULL;
+ lua_bytecode_registers[i].size=0;
+ lua_bytecode_registers[i].done=0;
+ }
+ luabytecode_max = k;
+ }
+ if (lua_bytecode_registers[k].buf != NULL) {
+ xfree(lua_bytecode_registers[k].buf);
+ luabytecode_bytes -= lua_bytecode_registers[k].size;
+ lua_bytecode_registers[k].buf = NULL;
+ lua_bytecode_registers[k].size=0;
+ lua_bytecode_registers[k].done=0;
+ lua_pushnil(L);
+ bytecode_register_shadow_set(L,k);
+ }
+ if (ltype == LUA_TFUNCTION) {
+ lua_bytecode_registers[k].buf=xmalloc(LOAD_BUF_SIZE);
+ lua_bytecode_registers[k].alloc = LOAD_BUF_SIZE;
+ memset(lua_bytecode_registers[k].buf, 0, LOAD_BUF_SIZE);
+ lua_dump(L,writer,(void *)(lua_bytecode_registers+k));
+ }
+ lua_pop(L,1);
+ return 0;
+}
+
+static const struct luaL_reg lualib [] = {
+ {"getbytecode", get_bytecode},
+ {"setbytecode", set_bytecode},
+ {NULL, NULL} /* sentinel */
+};
+
+int luaopen_lua (lua_State *L, int n, char *fname)
+{
+ luaL_register(L, "lua", lualib);
+ make_table(L,"bytecode","getbytecode","setbytecode");
+ lua_newtable(L);
+ lua_setfield(L, LUA_REGISTRYINDEX, "bytecode_shadow");
+ lua_pushinteger(L, n);
+ lua_setfield(L, -2, "id");
+ lua_pushstring(L, "0.1");
+ lua_setfield(L, -2, "version");
+ if (fname == NULL) {
+ lua_pushnil(L);
+ } else {
+ lua_pushstring(L, fname);
+ }
+ lua_setfield(L, -2, "startupfile");
+ return 1;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/lua/lmplib.c b/Build/source/texk/web2c/luatexdir/lua/lmplib.c
new file mode 100644
index 00000000000..a194f9a55d8
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/lmplib.c
@@ -0,0 +1,1251 @@
+/* $Id$ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef pdfTeX
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+#else
+#include <../lua51/lua.h>
+#include <../lua51/lauxlib.h>
+#include <../lua51/lualib.h>
+#endif
+
+#include "mplib.h"
+#include "mpmp.h"
+#include "mppsout.h" /* for mp_edge_object */
+
+#define MPLIB_METATABLE "MPlib"
+#define MPLIB_FIG_METATABLE "MPlib.fig"
+#define MPLIB_GR_METATABLE "MPlib.gr"
+
+#define mplib_init_S(a) do { \
+ lua_pushliteral(L,#a); \
+ mplib_##a##_ptr = (char *)lua_tostring(L,-1); \
+ mplib_##a##_index = luaL_ref (L,LUA_REGISTRYINDEX); \
+ } while (0)
+
+#define mplib_push_S(a) do { \
+ lua_rawgeti(L,LUA_REGISTRYINDEX,mplib_##a##_index); \
+ } while (0)
+
+#define mplib_is_S(a,i) (mplib_##a##_ptr==(char *)lua_tostring(L,i))
+
+#define mplib_make_S(a) \
+ static int mplib_##a##_index = 0; \
+ static char *mplib_##a##_ptr = NULL
+
+static int mplib_type_Ses[mp_special_code+1] = {0}; /* [0] is not used */
+
+mplib_make_S(fill);
+mplib_make_S(outline);
+mplib_make_S(text);
+mplib_make_S(special);
+mplib_make_S(start_bounds);
+mplib_make_S(stop_bounds);
+mplib_make_S(start_clip);
+mplib_make_S(stop_clip);
+
+mplib_make_S(left_type);
+mplib_make_S(right_type);
+mplib_make_S(x_coord);
+mplib_make_S(y_coord);
+mplib_make_S(left_x);
+mplib_make_S(left_y);
+mplib_make_S(right_x);
+mplib_make_S(right_y);
+
+mplib_make_S(color);
+mplib_make_S(dash);
+mplib_make_S(depth);
+mplib_make_S(dsize);
+mplib_make_S(font);
+mplib_make_S(height);
+mplib_make_S(htap);
+mplib_make_S(linecap);
+mplib_make_S(linejoin);
+mplib_make_S(miterlimit);
+mplib_make_S(path);
+mplib_make_S(pen);
+mplib_make_S(postscript);
+mplib_make_S(prescript);
+mplib_make_S(transform);
+mplib_make_S(type);
+mplib_make_S(width);
+
+void mplib_init_Ses(lua_State *L) {
+ mplib_init_S(fill);
+ mplib_init_S(outline);
+ mplib_init_S(text);
+ mplib_init_S(start_bounds);
+ mplib_init_S(stop_bounds);
+ mplib_init_S(start_clip);
+ mplib_init_S(stop_clip);
+ mplib_init_S(special);
+
+ mplib_type_Ses[mp_fill_code] = mplib_fill_index;
+ mplib_type_Ses[mp_stroked_code] = mplib_outline_index;
+ mplib_type_Ses[mp_text_code] = mplib_text_index;
+ mplib_type_Ses[mp_start_bounds_code] = mplib_start_bounds_index;
+ mplib_type_Ses[mp_stop_bounds_code] = mplib_stop_bounds_index;
+ mplib_type_Ses[mp_start_clip_code] = mplib_start_clip_index;
+ mplib_type_Ses[mp_stop_clip_code] = mplib_stop_clip_index;
+ mplib_type_Ses[mp_special_code] = mplib_special_index;
+
+ mplib_init_S(left_type);
+ mplib_init_S(right_type);
+ mplib_init_S(x_coord);
+ mplib_init_S(y_coord);
+ mplib_init_S(left_x);
+ mplib_init_S(left_y);
+ mplib_init_S(right_x);
+ mplib_init_S(right_y);
+
+ mplib_init_S(color);
+ mplib_init_S(dash);
+ mplib_init_S(depth);
+ mplib_init_S(dsize);
+ mplib_init_S(font);
+ mplib_init_S(height);
+ mplib_init_S(htap);
+ mplib_init_S(linecap);
+ mplib_init_S(linejoin);
+ mplib_init_S(miterlimit);
+ mplib_init_S(path);
+ mplib_init_S(pen);
+ mplib_init_S(postscript);
+ mplib_init_S(prescript);
+ mplib_init_S(transform);
+ mplib_init_S(type);
+ mplib_init_S(width);
+}
+
+
+
+
+#define xfree(A) if ((A)!=NULL) { free((A)); A = NULL; }
+
+#define is_mp(L,b) (MP *)luaL_checkudata(L,b,MPLIB_METATABLE)
+#define is_fig(L,b) (struct mp_edge_object **)luaL_checkudata(L,b,MPLIB_FIG_METATABLE)
+#define is_gr_object(L,b) (struct mp_graphic_object **)luaL_checkudata(L,b,MPLIB_GR_METATABLE)
+
+/* Enumeration string arrays */
+
+static const char *interaction_options[] =
+ { "unknown","batch","nonstop","scroll","errorstop", NULL};
+
+static const char *mplib_filetype_names[] =
+ {"term", "error", "mp", "log", "ps", "mem", "tfm", "map", "pfb", "enc", NULL};
+
+/* only "endpoint" and "explicit" actually happen in paths,
+ as well as "open" in elliptical pens */
+
+static const char *knot_type_enum[] =
+ { "endpoint", "explicit", "given", "curl", "open", "end_cycle" };
+
+/* object fields */
+
+static const char *fill_fields[] =
+ { "type", "path", "htap", "pen", "color", "linejoin", "miterlimit",
+ "prescript", "postscript", NULL };
+
+static const char *stroked_fields[] =
+ { "type", "path", "pen", "color", "linejoin", "miterlimit", "linecap", "dash",
+ "prescript", "postscript", NULL };
+
+static const char *text_fields[] =
+ { "type", "text", "dsize", "font", "color", "width", "height", "depth", "transform",
+ "prescript", "postscript", NULL };
+
+static const char *special_fields[] =
+ { "type", "prescript", NULL };
+
+static const char *start_bounds_fields[] =
+ { "type", "path", NULL };
+
+static const char *start_clip_fields[] =
+ { "type", "path", NULL };
+
+static const char *stop_bounds_fields[] =
+ { "type", NULL };
+
+static const char *stop_clip_fields[] =
+ { "type", NULL };
+
+static const char *no_fields[] =
+ { NULL };
+
+typedef enum {
+ P_ERROR_LINE, P_HALF_LINE, P_MAX_LINE, P_MAIN_MEMORY,
+ P_HASH_SIZE, P_HASH_PRIME, P_PARAM_SIZE, P_IN_OPEN, P_RANDOM_SEED,
+ P_INTERACTION, P_INI_VERSION, P_TROFF_MODE, P_PRINT_NAMES, P_MEM_NAME,
+ P_JOB_NAME, P_FIND_FILE, P__SENTINEL
+} mplib_parm_idx;
+
+typedef struct {
+ const char *name; /* parameter name */
+ mplib_parm_idx idx; /* parameter index */
+} mplib_parm_struct;
+
+static mplib_parm_struct mplib_parms[] = {
+ {"error_line", P_ERROR_LINE },
+ {"half_error_line", P_HALF_LINE },
+ {"max_print_line", P_MAX_LINE },
+ {"main_memory", P_MAIN_MEMORY },
+ {"hash_size", P_HASH_SIZE },
+ {"hash_prime", P_HASH_PRIME },
+ {"param_size", P_PARAM_SIZE },
+ {"max_in_open", P_IN_OPEN },
+ {"random_seed", P_RANDOM_SEED },
+ {"interaction", P_INTERACTION },
+ {"ini_version", P_INI_VERSION },
+ {"troff_mode", P_TROFF_MODE },
+ {"print_found_names", P_PRINT_NAMES },
+ {"mem_name", P_MEM_NAME },
+ {"job_name", P_JOB_NAME },
+ {"find_file", P_FIND_FILE },
+ {NULL, P__SENTINEL }
+};
+
+typedef struct _FILE_ITEM {
+ FILE *f;
+} _FILE_ITEM ;
+
+typedef struct _FILE_ITEM File;
+
+#define make_stream_buf(A) char *A; size_t A##_size; size_t A##_used
+
+#define free_stream_buf(A) xfree(mplib_data->A); mplib_data->A##_size = 0; mplib_data->A##_used = 0
+
+typedef struct _MPLIB_INSTANCE_DATA {
+ void *term_file_ptr;
+ void *err_file_ptr;
+ void *log_file_ptr;
+ void *ps_file_ptr;
+ make_stream_buf(term_out);
+ make_stream_buf(error_out);
+ make_stream_buf(log_out);
+ make_stream_buf(ps_out);
+ char *input_data;
+ char *input_data_ptr;
+ size_t input_data_len;
+ struct mp_edge_object *edges ;
+ lua_State *LL;
+} _MPLIB_INSTANCE_DATA;
+
+typedef struct _MPLIB_INSTANCE_DATA mplib_instance;
+
+static mplib_instance *mplib_get_data (MP mp) {
+ return (mplib_instance *)mp->userdata;
+}
+
+static mplib_instance *mplib_make_data (void) {
+ mplib_instance *mplib_data = malloc(sizeof(mplib_instance));
+ memset(mplib_data,0,sizeof(mplib_instance));
+ return mplib_data ;
+}
+
+
+/* Start by defining all the callback routines for the library
+ * except |run_make_mpx| and |run_editor|.
+ */
+
+
+char *mplib_find_file (MP mp, const char *fname, const char *fmode, int ftype) {
+ mplib_instance *mplib_data = mplib_get_data(mp);
+ lua_State *L = mplib_data->LL;
+ lua_checkstack(L,4);
+ lua_getfield(L,LUA_REGISTRYINDEX,"mplib_file_finder");
+ if (lua_isfunction(L,-1)) {
+ char *s = NULL, *x = NULL;
+ lua_pushstring(L, fname);
+ lua_pushstring(L, fmode);
+ if (ftype >= mp_filetype_text) {
+ lua_pushnumber(L, ftype-mp_filetype_text);
+ } else {
+ lua_pushstring(L, mplib_filetype_names[ftype]);
+ }
+ if(lua_pcall(L,3,1,0) != 0) {
+ fprintf(stdout,"Error in mp.find_file: %s\n", (char *)lua_tostring(L,-1));
+ return NULL;
+ }
+ x = (char *)lua_tostring(L,-1);
+ if (x!=NULL)
+ s = strdup(x);
+ lua_pop(L,1); /* pop the string */
+ return s;
+ } else {
+ lua_pop(L,1);
+ }
+ if (fmode[0] != 'r' || (! access (fname,R_OK)) || ftype) {
+ return strdup(fname);
+ }
+ return NULL;
+}
+
+static int
+mplib_find_file_function (lua_State *L) {
+ if (! (lua_isfunction(L,-1)|| lua_isnil(L,-1) )) {
+ return 1; /* error */
+ }
+ lua_pushstring(L, "mplib_file_finder");
+ lua_pushvalue(L,-2);
+ lua_rawset(L,LUA_REGISTRYINDEX);
+ return 0;
+}
+
+void *mplib_open_file(MP mp, const char *fname, const char *fmode, int ftype) {
+ File *ff = malloc(sizeof (File));
+ if (ff) {
+ mplib_instance *mplib_data = mplib_get_data(mp);
+ ff->f = NULL;
+ if (ftype==mp_filetype_terminal) {
+ if (fmode[0] == 'r') {
+ ff->f = stdin;
+ } else {
+ xfree(mplib_data->term_file_ptr);
+ ff->f = malloc(1);
+ mplib_data->term_file_ptr = ff->f;
+ }
+ } else if (ftype==mp_filetype_error) {
+ xfree(mplib_data->err_file_ptr);
+ ff->f = malloc(1);
+ mplib_data->err_file_ptr = ff->f;
+ } else if (ftype == mp_filetype_log) {
+ xfree(mplib_data->log_file_ptr);
+ ff->f = malloc(1);
+ mplib_data->log_file_ptr = ff->f;
+ } else if (ftype == mp_filetype_postscript) {
+ xfree(mplib_data->ps_file_ptr);
+ ff->f = malloc(1);
+ mplib_data->ps_file_ptr = ff->f;
+ } else {
+ char realmode[3];
+ char *f = mplib_find_file(mp, fname,fmode,ftype);
+ if (f==NULL)
+ return NULL;
+ realmode[0] = *fmode;
+ realmode[1] = 'b';
+ realmode[2] = 0;
+ ff->f = fopen(f, realmode);
+ if ((fmode[0] == 'r') && (ff->f == NULL)) {
+ free(ff);
+ return NULL;
+ }
+ }
+ return ff;
+ }
+ return NULL;
+}
+
+static int
+mplib_get_char (void *f, mplib_instance *mplib_data) {
+ int c;
+ if (f==stdin && mplib_data->input_data != NULL) {
+ if (mplib_data->input_data_len==0) {
+ if (mplib_data->input_data_ptr!=NULL)
+ mplib_data->input_data_ptr = NULL;
+ else
+ mplib_data->input_data = NULL;
+ c = EOF;
+ } else {
+ mplib_data->input_data_len--;
+ c = *(mplib_data->input_data_ptr)++;
+ }
+ } else {
+ c = fgetc(f);
+ }
+ return c;
+}
+
+static void
+mplib_unget_char (void *f, mplib_instance *mplib_data, int c) {
+ if (f==stdin && mplib_data->input_data_ptr != NULL) {
+ mplib_data->input_data_len++;
+ mplib_data->input_data_ptr--;
+ } else {
+ ungetc(c,f);
+ }
+}
+
+
+char *mplib_read_ascii_file (MP mp, void *ff, size_t *size) {
+ char *s = NULL;
+ if (ff!=NULL) {
+ int c;
+ size_t len = 0, lim = 128;
+ mplib_instance *mplib_data = mplib_get_data(mp);
+ FILE *f = ((File *)ff)->f;
+ if (f==NULL)
+ return NULL;
+ *size = 0;
+ c = mplib_get_char(f,mplib_data);
+ if (c==EOF)
+ return NULL;
+ s = malloc(lim);
+ if (s==NULL) return NULL;
+ while (c!=EOF && c!='\n' && c!='\r') {
+ if (len==lim) {
+ s =realloc(s, (lim+(lim>>2)));
+ if (s==NULL) return NULL;
+ lim+=(lim>>2);
+ }
+ s[len++] = c;
+ c = mplib_get_char(f,mplib_data);
+ }
+ if (c=='\r') {
+ c = mplib_get_char(f,mplib_data);
+ if (c!=EOF && c!='\n')
+ mplib_unget_char(f,mplib_data,c);
+ }
+ s[len] = 0;
+ *size = len;
+ }
+ return s;
+}
+
+#define APPEND_STRING(a,b) do { \
+ if ((mplib_data->a##_used+strlen(b))>=mplib_data->a##_size) { \
+ mplib_data->a##_size += 256+(mplib_data->a##_size)/5+strlen(b); \
+ mplib_data->a = realloc(mplib_data->a,mplib_data->a##_size); \
+ } \
+ (void)strcpy(mplib_data->a+mplib_data->a##_used,b); \
+ mplib_data->a##_used += strlen(b); \
+ } while (0)
+
+void mplib_write_ascii_file (MP mp, void *ff, const char *s) {
+ if (ff!=NULL) {
+ void *f = ((File *)ff)->f;
+ mplib_instance *mplib_data = mplib_get_data(mp);
+ if (f!=NULL) {
+ if (f==mplib_data->term_file_ptr) {
+ APPEND_STRING(term_out,s);
+ } else if (f==mplib_data->err_file_ptr) {
+ APPEND_STRING(error_out,s);
+ } else if (f==mplib_data->log_file_ptr) {
+ APPEND_STRING(log_out,s);
+ } else if (f==mplib_data->ps_file_ptr) {
+ APPEND_STRING(ps_out,s);
+ } else {
+ fprintf((FILE *)f,s);
+ }
+ }
+ }
+}
+
+void mplib_read_binary_file (MP mp, void *ff, void **data, size_t *size) {
+ (void)mp;
+ if (ff!=NULL) {
+ size_t len = 0;
+ FILE *f = ((File *)ff)->f;
+ if (f!=NULL)
+ len = fread(*data,1,*size,f);
+ *size = len;
+ }
+}
+
+void mplib_write_binary_file (MP mp, void *ff, void *s, size_t size) {
+ (void)mp;
+ if (ff!=NULL) {
+ FILE *f = ((File *)ff)->f;
+ if (f!=NULL)
+ fwrite(s,size,1,f);
+ }
+}
+
+
+void mplib_close_file (MP mp, void *ff) {
+ if (ff!=NULL) {
+ mplib_instance *mplib_data = mplib_get_data(mp);
+ void *f = ((File *)ff)->f;
+ if (f != NULL && f != mplib_data->term_file_ptr && f != mplib_data->err_file_ptr
+ && f != mplib_data->log_file_ptr && f != mplib_data->ps_file_ptr) {
+ fclose(f);
+ }
+ free(ff);
+ }
+}
+
+int mplib_eof_file (MP mp, void *ff) {
+ if (ff!=NULL) {
+ mplib_instance *mplib_data = mplib_get_data(mp);
+ FILE *f = ((File *)ff)->f;
+ if (f==NULL)
+ return 1;
+ if (f==stdin && mplib_data->input_data != NULL) {
+ return (mplib_data->input_data_len==0);
+ }
+ return feof(f);
+ }
+ return 1;
+}
+
+void mplib_flush_file (MP mp, void *ff) {
+ (void)mp;
+ (void)ff;
+ return ;
+}
+
+#define APPEND_TO_EDGES(a) do { \
+ if (mplib_data->edges==NULL) { \
+ mplib_data->edges = hh; \
+ } else { \
+ struct mp_edge_object *p = mplib_data->edges; \
+ while (p->_next!=NULL) { p = p->_next; } \
+ p->_next = hh; \
+ } \
+} while (0)
+
+void mplib_shipout_backend (MP mp, int h) {
+ struct mp_edge_object *hh = mp_gr_export(mp, h);
+ if (hh) {
+ mplib_instance *mplib_data = mplib_get_data(mp);
+ APPEND_TO_EDGES(hh);
+ }
+}
+
+
+static void
+mplib_setup_file_ops(struct MP_options * options) {
+ options->find_file = mplib_find_file;
+ options->open_file = mplib_open_file;
+ options->close_file = mplib_close_file;
+ options->eof_file = mplib_eof_file;
+ options->flush_file = mplib_flush_file;
+ options->write_ascii_file = mplib_write_ascii_file;
+ options->read_ascii_file = mplib_read_ascii_file;
+ options->write_binary_file = mplib_write_binary_file;
+ options->read_binary_file = mplib_read_binary_file;
+ options->shipout_backend = mplib_shipout_backend;
+}
+
+static int
+mplib_new (lua_State *L) {
+ MP *mp_ptr;
+ mp_ptr = lua_newuserdata(L, sizeof(MP *));
+ if (mp_ptr) {
+ int i;
+ mplib_instance *mplib_data;
+ struct MP_options * options; /* instance options */
+ options = mp_options();
+ mplib_setup_file_ops(options);
+ mplib_data = mplib_make_data();
+ mplib_data->LL = L;
+ options->userdata = (void *)mplib_data;
+ options->noninteractive = 1; /* required ! */
+ options->print_found_names = 0;
+ if (lua_type(L,1)==LUA_TTABLE) {
+ for (i=0;mplib_parms[i].name!=NULL;i++) {
+ lua_getfield(L,1,mplib_parms[i].name);
+ if (lua_isnil(L,-1)) {
+ lua_pop(L,1);
+ continue; /* skip unset */
+ }
+ switch(mplib_parms[i].idx) {
+ case P_ERROR_LINE:
+ options->error_line = lua_tointeger(L,-1);
+ break;
+ case P_HALF_LINE:
+ options->half_error_line = lua_tointeger(L,-1);
+ break;
+ case P_MAX_LINE:
+ options->max_print_line = lua_tointeger(L,-1);
+ break;
+ case P_MAIN_MEMORY:
+ options->main_memory = lua_tointeger(L,-1);
+ break;
+ case P_HASH_SIZE:
+ options->hash_size = lua_tointeger(L,-1);
+ break;
+ case P_HASH_PRIME:
+ options->hash_prime = lua_tointeger(L,-1);
+ break;
+ case P_PARAM_SIZE:
+ options->param_size = lua_tointeger(L,-1);
+ break;
+ case P_IN_OPEN:
+ options->max_in_open = lua_tointeger(L,-1);
+ break;
+ case P_RANDOM_SEED:
+ options->random_seed = lua_tointeger(L,-1);
+ break;
+ case P_INTERACTION:
+ options->interaction = luaL_checkoption(L,-1,"errorstopmode", interaction_options);
+ break;
+ case P_INI_VERSION:
+ options->ini_version = lua_toboolean(L,-1);
+ break;
+ case P_TROFF_MODE:
+ options->troff_mode = lua_toboolean(L,-1);
+ break;
+ case P_PRINT_NAMES:
+ options->print_found_names = lua_toboolean(L,-1);
+ break;
+ /*
+ case P_COMMAND_LINE:
+ options->command_line = strdup((char *)lua_tostring(L,-1));
+ break;
+ */
+ case P_MEM_NAME:
+ options->mem_name = strdup((char *)lua_tostring(L,-1));
+ break;
+ case P_JOB_NAME:
+ options->job_name = strdup((char *)lua_tostring(L,-1));
+ break;
+ case P_FIND_FILE:
+ if(mplib_find_file_function(L)) { /* error here */
+ fprintf(stdout,"Invalid arguments to mp.new({find_file=...})\n");
+ }
+ break;
+ default:
+ break;
+ }
+ lua_pop(L,1);
+ }
+ }
+ *mp_ptr = mp_new(options);
+ xfree(options->command_line);
+ xfree(options->mem_name);
+ xfree(options->job_name);
+ free(options);
+ if (*mp_ptr) {
+ luaL_getmetatable(L,MPLIB_METATABLE);
+ lua_setmetatable(L,-2);
+ return 1;
+ }
+ }
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+mplib_collect (lua_State *L) {
+ MP *mp_ptr = is_mp(L,1);
+ xfree(*mp_ptr);
+ return 0;
+}
+
+static int
+mplib_tostring (lua_State *L) {
+ MP *mp_ptr = is_mp(L,1);
+ if (*mp_ptr!=NULL) {
+ lua_pushfstring(L,"<MP %p>",*mp_ptr);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+mplib_wrapresults(lua_State *L, mplib_instance *mplib_data, int h) {
+ lua_checkstack(L,5);
+ lua_newtable(L);
+ if (mplib_data->term_out != NULL) {
+ lua_pushstring(L,mplib_data->term_out);
+ lua_setfield(L,-2,"term");
+ free_stream_buf(term_out);
+ }
+ if (mplib_data->error_out != NULL) {
+ lua_pushstring(L,mplib_data->error_out);
+ lua_setfield(L,-2,"error");
+ free_stream_buf(error_out);
+ }
+ if (mplib_data->log_out != NULL ) {
+ lua_pushstring(L,mplib_data->log_out);
+ lua_setfield(L,-2,"log");
+ free_stream_buf(log_out);
+ }
+ if (mplib_data->edges != NULL ) {
+ struct mp_edge_object **v;
+ struct mp_edge_object *p = mplib_data->edges;
+ int i = 1;
+ lua_newtable(L);
+ while (p!=NULL) {
+ v = lua_newuserdata (L, sizeof(struct mp_edge_object *));
+ *v = p;
+ luaL_getmetatable(L,MPLIB_FIG_METATABLE);
+ lua_setmetatable(L,-2);
+ lua_rawseti(L,-2,i); i++;
+ p = p->_next;
+ }
+ lua_setfield(L,-2,"fig");
+ mplib_data->edges = NULL;
+ }
+ lua_pushnumber(L,h);
+ lua_setfield(L,-2,"status");
+ return 1;
+}
+
+static int
+mplib_execute (lua_State *L) {
+ MP *mp_ptr = is_mp(L,1);
+ if (*mp_ptr!=NULL && lua_isstring(L,2)) {
+ int h;
+ mplib_instance *mplib_data = mplib_get_data(*mp_ptr);
+ mplib_data->input_data = (char *)lua_tolstring(L,2, &(mplib_data->input_data_len));
+ mplib_data->input_data_ptr = mplib_data->input_data;
+ if ((*mp_ptr)->run_state==0) {
+ h = mp_initialize(*mp_ptr);
+ }
+ h = mp_execute(*mp_ptr);
+ if (mplib_data->input_data_len!=0) {
+ mplib_data->input_data = NULL;
+ mplib_data->input_data_ptr = NULL;
+ mplib_data->input_data_len=0;
+ }
+ return mplib_wrapresults(L, mplib_data, h);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int
+mplib_finish (lua_State *L) {
+ MP *mp_ptr = is_mp(L,1);
+ if (*mp_ptr!=NULL) {
+ mplib_instance *mplib_data = mplib_get_data(*mp_ptr);
+ int h = mp_finish(*mp_ptr);
+ return mplib_wrapresults(L, mplib_data, h);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int
+mplib_statistics (lua_State *L) {
+ MP *mp_ptr = is_mp(L,1);
+ if (*mp_ptr!=NULL) {
+ lua_newtable(L);
+ lua_pushnumber(L, mp_memory_usage (*mp_ptr));
+ lua_setfield(L,-2,"main_memory");
+ lua_pushnumber(L, mp_hash_usage (*mp_ptr));
+ lua_setfield(L,-2,"hash_size");
+ lua_pushnumber(L, mp_param_usage (*mp_ptr));
+ lua_setfield(L,-2,"param_size");
+ lua_pushnumber(L, mp_open_usage (*mp_ptr));
+ lua_setfield(L,-2,"max_in_open");
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+
+/* figure methods */
+
+static int
+mplib_fig_collect (lua_State *L) {
+ struct mp_edge_object **hh = is_fig(L,1);
+ if (*hh!=NULL) {
+ mp_gr_toss_objects (*hh);
+ *hh=NULL;
+ }
+ return 0;
+}
+
+static int
+mplib_fig_body (lua_State *L) {
+ int i = 1;
+ struct mp_graphic_object **v;
+ struct mp_graphic_object *p;
+ struct mp_edge_object **hh = is_fig(L,1);
+ lua_newtable(L);
+ p = (*hh)->body;
+ while (p!=NULL) {
+ v = lua_newuserdata (L, sizeof(struct mp_graphic_object *));
+ *v = p;
+ luaL_getmetatable(L,MPLIB_GR_METATABLE);
+ lua_setmetatable(L,-2);
+ lua_rawseti(L,-2,i); i++;
+ p = p->_link_field;
+ }
+ (*hh)->body = NULL; /* prevent double free */
+ return 1;
+}
+
+static int
+mplib_fig_copy_body (lua_State *L) {
+ int i = 1;
+ struct mp_graphic_object **v;
+ struct mp_graphic_object *p;
+ struct mp_edge_object **hh = is_fig(L,1);
+ lua_newtable(L);
+ p = (*hh)->body;
+ while (p!=NULL) {
+ v = lua_newuserdata (L, sizeof(struct mp_graphic_object *));
+ *v = mp_gr_copy_object((*hh)->_parent,p);
+ luaL_getmetatable(L,MPLIB_GR_METATABLE);
+ lua_setmetatable(L,-2);
+ lua_rawseti(L,-2,i); i++;
+ p = p->_link_field;
+ }
+ return 1;
+}
+
+
+static int
+mplib_fig_tostring (lua_State *L) {
+ struct mp_edge_object **hh = is_fig(L,1);
+ lua_pushfstring(L,"<figure %p>",*hh);
+ return 1;
+}
+
+
+
+static int
+mp_wrapped_shipout (struct mp_edge_object *hh, int prologues, int procset) {
+ MP mp = hh->_parent;
+ if (setjmp(mp->jump_buf)) {
+ return 0;
+ }
+ mp_gr_ship_out(hh,prologues,procset);
+ return 1;
+}
+
+static int
+mplib_fig_postscript (lua_State *L) {
+ struct mp_edge_object **hh = is_fig(L,1);
+ int prologues = luaL_optnumber(L,2,-1);
+ int procset = luaL_optnumber(L,3,-1);
+ mplib_instance *mplib_data = mplib_get_data((*hh)->_parent);
+ if (mplib_data->ps_out == NULL) {
+ if (mp_wrapped_shipout(*hh,prologues, procset)) {
+ if (mplib_data->ps_out!=NULL ) {
+ lua_pushstring(L, mplib_data->ps_out);
+ free_stream_buf(ps_out);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+ } else {
+ lua_pushnil(L);
+ lua_pushstring(L,mplib_data->log_out);
+ xfree(mplib_data->ps_out);
+ return 2;
+ }
+ }
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+mplib_fig_filename (lua_State *L) {
+ struct mp_edge_object **hh = is_fig(L,1);
+ if (*hh!= NULL) {
+ char *s = (*hh)->_filename;
+ lua_pushstring(L,s);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+
+static int
+mplib_fig_bb (lua_State *L) {
+ struct mp_edge_object **hh = is_fig(L,1);
+ lua_newtable(L);
+ lua_pushnumber(L, (double)(*hh)->_minx/65536.0);
+ lua_rawseti(L,-2,1);
+ lua_pushnumber(L, (double)(*hh)->_miny/65536.0);
+ lua_rawseti(L,-2,2);
+ lua_pushnumber(L, (double)(*hh)->_maxx/65536.0);
+ lua_rawseti(L,-2,3);
+ lua_pushnumber(L, (double)(*hh)->_maxy/65536.0);
+ lua_rawseti(L,-2,4);
+ return 1;
+}
+
+/* object methods */
+
+static int
+mplib_gr_collect (lua_State *L) {
+ struct mp_graphic_object **hh = is_gr_object(L,1);
+ if (*hh!=NULL) {
+ mp_gr_toss_object(*hh);
+ *hh=NULL;
+ }
+ return 0;
+}
+
+static int
+mplib_gr_tostring (lua_State *L) {
+ struct mp_graphic_object **hh = is_gr_object(L,1);
+ lua_pushfstring(L,"<object %p>",*hh);
+ return 1;
+}
+
+
+static int
+mplib_gr_fields (lua_State *L) {
+ const char **fields;
+ const char *f;
+ int i = 1;
+ struct mp_graphic_object **hh = is_gr_object(L,1);
+ if (*hh) {
+ switch ((*hh)->_type_field) {
+ case mp_fill_code: fields = fill_fields; break;
+ case mp_stroked_code: fields = stroked_fields; break;
+ case mp_text_code: fields = text_fields; break;
+ case mp_special_code: fields = special_fields; break;
+ case mp_start_clip_code: fields = start_clip_fields; break;
+ case mp_start_bounds_code: fields = start_bounds_fields; break;
+ case mp_stop_clip_code: fields = stop_clip_fields; break;
+ case mp_stop_bounds_code: fields = stop_bounds_fields; break;
+ default: fields = no_fields;
+ }
+ lua_newtable(L);
+ for (f = *fields; f != NULL; f++) {
+ lua_pushstring(L,f);
+ lua_rawseti(L,-2,i); i++;
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+
+#define mplib_push_number(L,x) lua_pushnumber(L,(lua_Number)(x)/65536.0)
+
+#define MPLIB_PATH 0
+#define MPLIB_PEN 1
+
+static void
+mplib_push_path (lua_State *L, struct mp_knot *h, int is_pen) {
+ struct mp_knot *p; /* for scanning the path */
+ int i=1;
+ p=h;
+ if (p!=NULL) {
+ lua_newtable(L);
+ do {
+ lua_createtable(L,0,6);
+ if (!is_pen) {
+ if (p->left_type_field != mp_explicit) {
+ mplib_push_S(left_type);
+ lua_pushstring(L,knot_type_enum[p->left_type_field]);
+ lua_rawset(L,-3);
+ }
+ if (p->right_type_field != mp_explicit) {
+ mplib_push_S(right_type);
+ lua_pushstring(L,knot_type_enum[p->right_type_field]);
+ lua_rawset(L,-3);
+ }
+ }
+ mplib_push_S(x_coord);
+ mplib_push_number(L,p->x_coord_field);
+ lua_rawset(L,-3);
+ mplib_push_S(y_coord);
+ mplib_push_number(L,p->y_coord_field);
+ lua_rawset(L,-3);
+ mplib_push_S(left_x);
+ mplib_push_number(L,p->left_x_field);
+ lua_rawset(L,-3);
+ mplib_push_S(left_y);
+ mplib_push_number(L,p->left_y_field);
+ lua_rawset(L,-3);
+ mplib_push_S(right_x);
+ mplib_push_number(L,p->right_x_field);
+ lua_rawset(L,-3);
+ mplib_push_S(right_y);
+ mplib_push_number(L,p->right_y_field);
+ lua_rawset(L,-3);
+ lua_rawseti(L,-2,i); i++;
+ if ( p->right_type_field==mp_endpoint ) {
+ return;
+ }
+ p=p->next_field;
+ } while (p!=h) ;
+ } else {
+ lua_pushnil(L);
+ }
+}
+
+#define set_color_objects(pq) \
+ object_color_model = pq->color_model_field; \
+ object_color_a = pq->color_field._a_val; \
+ object_color_b = pq->color_field._b_val; \
+ object_color_c = pq->color_field._c_val; \
+ object_color_d = pq->color_field._d_val;
+
+
+static void
+mplib_push_color (lua_State *L, struct mp_graphic_object *p ) {
+ int object_color_model;
+ int object_color_a, object_color_b, object_color_c, object_color_d ;
+ if (p!=NULL) {
+ if (p->_type_field == mp_fill_code) {
+ mp_fill_object *h = (mp_fill_object *)p;
+ set_color_objects(h);
+ } else if (p->_type_field == mp_stroked_code) {
+ mp_stroked_object *h = (mp_stroked_object *)p;
+ set_color_objects(h);
+ } else {
+ mp_text_object *h = (mp_text_object *)p;
+ set_color_objects(h);
+ }
+ lua_newtable(L);
+ if (object_color_model >= mp_grey_model) {
+ mplib_push_number(L,object_color_a);
+ lua_rawseti(L,-2,1);
+ if (object_color_model >= mp_rgb_model) {
+ mplib_push_number(L,object_color_b);
+ lua_rawseti(L,-2,2);
+ mplib_push_number(L,object_color_c);
+ lua_rawseti(L,-2,3);
+ if (object_color_model == mp_cmyk_model) {
+ mplib_push_number(L,object_color_d);
+ lua_rawseti(L,-2,4);
+ }
+ }
+ }
+ } else {
+ lua_pushnil(L);
+ }
+}
+
+/* the dash scale is not exported, the field has no external value */
+static void
+mplib_push_dash (lua_State *L, struct mp_stroked_object *h ) {
+ mp_dash_object *d;
+ if (h!=NULL && h->dash_p_field != NULL) {
+ d = h->dash_p_field;
+ lua_newtable(L);
+ mplib_push_number(L,d->offset_field);
+ lua_setfield(L,-2,"offset");
+ if (d->array_field!=NULL ) {
+ int i = 0;
+ lua_newtable(L);
+ while (*(d->array_field+i) != -1) {
+ mplib_push_number(L, *(d->array_field+1));
+ i++;
+ lua_rawseti(L,-2,i);
+ }
+ lua_setfield(L,-2,"dashes");
+ }
+ } else {
+ lua_pushnil(L);
+ }
+}
+
+static void
+mplib_push_transform (lua_State *L, struct mp_text_object *h ) {
+ int i = 1;
+ if (h!=NULL) {
+ lua_createtable(L,6,0);
+ mplib_push_number(L,h->tx_field);
+ lua_rawseti(L,-2,i); i++;
+ mplib_push_number(L,h->ty_field);
+ lua_rawseti(L,-2,i); i++;
+ mplib_push_number(L,h->txx_field);
+ lua_rawseti(L,-2,i); i++;
+ mplib_push_number(L,h->tyx_field);
+ lua_rawseti(L,-2,i); i++;
+ mplib_push_number(L,h->txy_field);
+ lua_rawseti(L,-2,i); i++;
+ mplib_push_number(L,h->tyy_field);
+ lua_rawseti(L,-2,i); i++;
+ } else {
+ lua_pushnil(L);
+ }
+}
+
+#define FIELD(A) (mplib_is_S(A,2))
+
+static void
+mplib_fill_field (lua_State *L, struct mp_fill_object *h) {
+ if (FIELD(path)) {
+ mplib_push_path(L, h->path_p_field, MPLIB_PATH);
+ } else if (FIELD(htap)) {
+ mplib_push_path(L, h->htap_p_field, MPLIB_PATH);
+ } else if (FIELD(pen)) {
+ mplib_push_path(L, h->pen_p_field, MPLIB_PEN);
+ } else if (FIELD(color)) {
+ mplib_push_color(L,(mp_graphic_object *)h);
+ } else if (FIELD(linejoin)) {
+ lua_pushnumber(L,h->ljoin_field);
+ } else if (FIELD(miterlimit)) {
+ mplib_push_number(L,h->miterlim_field);
+ } else if (FIELD(prescript)) {
+ lua_pushstring(L,h->pre_script_field);
+ } else if (FIELD(postscript)) {
+ lua_pushstring(L,h->post_script_field);
+ } else {
+ lua_pushnil(L);
+ }
+}
+
+static void
+mplib_stroked_field (lua_State *L, struct mp_stroked_object *h) {
+ if (FIELD(path)) {
+ mplib_push_path(L, h->path_p_field, MPLIB_PATH);
+ } else if (FIELD(pen)) {
+ mplib_push_path(L, h->pen_p_field, MPLIB_PEN);
+ } else if (FIELD(color)) {
+ mplib_push_color(L, (mp_graphic_object *)h);
+ } else if (FIELD(dash)) {
+ mplib_push_dash(L,h);
+ } else if (FIELD(linecap)) {
+ lua_pushnumber(L,h->lcap_field);
+ } else if (FIELD(linejoin)) {
+ lua_pushnumber(L,h->ljoin_field);
+ } else if (FIELD(miterlimit)) {
+ mplib_push_number(L,h->miterlim_field);
+ } else if (FIELD(prescript)) {
+ lua_pushstring(L,h->pre_script_field);
+ } else if (FIELD(postscript)) {
+ lua_pushstring(L,h->post_script_field);
+ } else {
+ lua_pushnil(L);
+ }
+}
+
+static void
+mplib_text_field (lua_State *L, struct mp_text_object *h) {
+ if (FIELD(text)) {
+ lua_pushstring(L,h->text_p_field);
+ } else if (FIELD(dsize)) {
+ mplib_push_number(L,(h->font_dsize_field/16));
+ } else if (FIELD(font)) {
+ lua_pushstring(L,h->font_name_field);
+ } else if (FIELD(color)) {
+ mplib_push_color(L,(mp_graphic_object *)h);
+ } else if (FIELD(width)) {
+ mplib_push_number(L,h->width_field);
+ } else if (FIELD(height)) {
+ mplib_push_number(L,h->height_field);
+ } else if (FIELD(depth)) {
+ mplib_push_number(L,h->depth_field);
+ } else if (FIELD(transform)) {
+ mplib_push_transform(L,h);
+ } else if (FIELD(prescript)) {
+ lua_pushstring(L,h->pre_script_field);
+ } else if (FIELD(postscript)) {
+ lua_pushstring(L,h->post_script_field);
+ } else {
+ lua_pushnil(L);
+ }
+}
+
+static void
+mplib_special_field (lua_State *L, struct mp_special_object *h) {
+ if (FIELD(prescript)) {
+ lua_pushstring(L,h->pre_script_field);
+ } else {
+ lua_pushnil(L);
+ }
+}
+
+static void
+mplib_start_bounds_field (lua_State *L, struct mp_bounds_object *h) {
+ if (FIELD(path)) {
+ mplib_push_path(L,h->path_p_field, MPLIB_PATH);
+ } else {
+ lua_pushnil(L);
+ }
+}
+
+static void
+mplib_start_clip_field (lua_State *L, struct mp_clip_object *h) {
+ if (FIELD(path)) {
+ mplib_push_path(L,h->path_p_field, MPLIB_PATH);
+ } else {
+ lua_pushnil(L);
+ }
+}
+
+static int
+mplib_gr_index (lua_State *L) {
+ struct mp_graphic_object **hh = is_gr_object(L,1);
+ if (*hh) {
+ struct mp_graphic_object *h = *hh;
+ if (mplib_is_S(type,2)) {
+ lua_rawgeti(L,LUA_REGISTRYINDEX,mplib_type_Ses[h->_type_field]);
+ } else {
+ switch (h->_type_field) {
+ case mp_fill_code: mplib_fill_field(L,(mp_fill_object *)h); break;
+ case mp_stroked_code: mplib_stroked_field(L,(mp_stroked_object *)h); break;
+ case mp_text_code: mplib_text_field(L,(mp_text_object *)h); break;
+ case mp_special_code: mplib_special_field(L,(mp_special_object *)h); break;
+ case mp_start_clip_code: mplib_start_clip_field(L,(mp_clip_object *)h); break;
+ case mp_start_bounds_code: mplib_start_bounds_field(L,(mp_bounds_object *)h); break;
+ /* case mp_stop_clip_code: */
+ /* case mp_stop_bounds_code: */
+ default: lua_pushnil(L);
+ }
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+
+static const struct luaL_reg mplib_meta[] = {
+ {"__gc", mplib_collect},
+ {"__tostring", mplib_tostring},
+ {NULL, NULL} /* sentinel */
+};
+
+static const struct luaL_reg mplib_fig_meta[] = {
+ {"__gc", mplib_fig_collect },
+ {"__tostring", mplib_fig_tostring },
+ {"objects", mplib_fig_body },
+ {"copy_objects", mplib_fig_copy_body },
+ {"filename", mplib_fig_filename },
+ {"postscript", mplib_fig_postscript },
+ {"boundingbox", mplib_fig_bb },
+ {NULL, NULL} /* sentinel */
+};
+
+static const struct luaL_reg mplib_gr_meta[] = {
+ {"__gc", mplib_gr_collect },
+ {"__tostring", mplib_gr_tostring },
+ {"__index", mplib_gr_index },
+ {"fields", mplib_gr_fields },
+ {NULL, NULL} /* sentinel */
+};
+
+
+static const struct luaL_reg mplib_d [] = {
+ {"execute", mplib_execute },
+ {"finish", mplib_finish },
+ {"statistics", mplib_statistics },
+ {NULL, NULL} /* sentinel */
+};
+
+
+static const struct luaL_reg mplib_m[] = {
+ {"new", mplib_new},
+ {NULL, NULL} /* sentinel */
+};
+
+
+int
+luaopen_mp (lua_State *L) {
+ mplib_init_Ses(L);
+ luaL_newmetatable(L,MPLIB_GR_METATABLE);
+ lua_pushvalue(L, -1); /* push metatable */
+ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
+ luaL_register(L, NULL, mplib_gr_meta); /* object meta methods */
+ lua_pop(L,1);
+
+ luaL_newmetatable(L,MPLIB_FIG_METATABLE);
+ lua_pushvalue(L, -1); /* push metatable */
+ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
+ luaL_register(L, NULL, mplib_fig_meta); /* figure meta methods */
+ lua_pop(L,1);
+
+ luaL_newmetatable(L,MPLIB_METATABLE);
+ lua_pushvalue(L, -1); /* push metatable */
+ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
+ luaL_register(L, NULL, mplib_meta); /* meta methods */
+ luaL_register(L, NULL, mplib_d); /* dict methods */
+ luaL_register(L, "mplib", mplib_m); /* module functions */
+ return 1;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/lua/lnodelib.c b/Build/source/texk/web2c/luatexdir/lua/lnodelib.c
new file mode 100644
index 00000000000..de269d5d9c8
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/lnodelib.c
@@ -0,0 +1,1967 @@
+/* $Id: lnodelib.c 1056 2008-02-19 15:42:17Z taco $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+#include "nodes.h"
+
+#define init_luaS_index(a) do { \
+ lua_pushliteral(L,#a); \
+ luaS_##a##_ptr = (char *)lua_tostring(L,-1); \
+ luaS_##a##_index = luaL_ref (L,LUA_REGISTRYINDEX); \
+ } while (0)
+
+#define make_luaS_index(a) \
+ static int luaS_##a##_index = 0; \
+ static char * luaS_##a##_ptr = NULL
+
+#define luaS_index(a) luaS_##a##_index
+
+#define luaS_ptr_eq(a,b) (a==luaS_##b##_ptr)
+
+#define NODE_METATABLE "luatex_node"
+
+make_luaS_index(luatex_node);
+
+halfword *check_isnode (lua_State *L, int ud) {
+ register halfword *p = lua_touserdata(L, ud);
+ if (p != NULL) {
+ if (lua_getmetatable(L, ud)) {
+ lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(luatex_node));
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ if (lua_rawequal(L, -1, -2)) {
+ lua_pop(L, 2);
+ return p;
+ }
+ }
+ }
+ luaL_typerror(L, ud, NODE_METATABLE);
+ return NULL;
+}
+
+/* This routine finds the numerical value of a string (or number) at
+ lua stack index |n|. If it is not a valid node type, returns -1 */
+
+static
+int do_get_node_type_id (lua_State *L, int n, node_info *data) {
+ register int j;
+ if (lua_type(L,n)==LUA_TSTRING) {
+ char *s = (char *)lua_tostring(L,n);
+ for (j=0;data[j].id!=-1;j++) {
+ if (strcmp(s,data[j].name)==0)
+ return j;
+ }
+ } else if (lua_type(L,n)==LUA_TNUMBER) {
+ register int i = lua_tointeger(L,n);
+ if (data[i].id==i)
+ return i;
+ for (j=0;data[j].id!=-1;j++) {
+ if (data[j].id==i)
+ return j;
+ }
+ }
+ return -1;
+}
+
+#define get_node_type_id(L,n) do_get_node_type_id(L,n,node_data)
+#define get_node_subtype_id(L,n) do_get_node_type_id(L,n,whatsit_node_data)
+
+static
+int get_valid_node_type_id (lua_State *L, int n) {
+ int i = get_node_type_id(L,n);
+ if (i==-1) {
+ if (lua_type(L,n)==LUA_TSTRING) {
+ lua_pushfstring(L, "Invalid node type id: %s",(char *)lua_tostring(L,n));
+ } else {
+ lua_pushfstring(L, "Invalid node type id: %d",(int)lua_tonumber(L,n));
+ }
+ return lua_error(L);
+ }
+ return i;
+}
+
+static
+int get_valid_node_subtype_id (lua_State *L, int n) {
+ int i = get_node_subtype_id(L,n);
+ if (i==-1) {
+ if (lua_type(L,n)==LUA_TSTRING) {
+ lua_pushfstring(L, "Invalid whatsit node id: %s",(char *)lua_tostring(L,n));
+ } else {
+ lua_pushfstring(L, "Invalid whatsit node id: %d",(int)lua_tonumber(L,n));
+ }
+ return lua_error(L);
+ }
+ return i;
+}
+
+
+
+/* Creates a userdata object for a number found at the stack top,
+ if it is representing a node (i.e. an pointer into |varmem|).
+ It replaces the stack entry with the new userdata, or pushes
+ |nil| if the number is |null|, or if the index is definately out of
+ range. This test could be improved.
+*/
+
+void
+lua_nodelib_push(lua_State *L) {
+ halfword n;
+ halfword *a;
+ n = -1;
+ if (lua_isnumber(L,-1)) {
+ n = lua_tointeger(L,-1);
+ }
+ lua_pop(L,1);
+ if ((n==null) || (n<0) || (n>var_mem_max)) {
+ lua_pushnil(L);
+ } else {
+ a = lua_newuserdata(L, sizeof(halfword));
+ *a = n;
+ lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(luatex_node));
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ lua_setmetatable(L,-2);
+ }
+ return;
+}
+
+void
+lua_nodelib_push_fast(lua_State *L, halfword n) {
+ halfword *a;
+ a = lua_newuserdata(L, sizeof(halfword));
+ *a = n;
+ lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(luatex_node));
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ lua_setmetatable(L,-2);
+ return;
+}
+
+
+/* converts type strings to type ids */
+
+static int
+lua_nodelib_id (lua_State *L) {
+ integer i = get_node_type_id(L,1);
+ if (i>=0) {
+ lua_pushnumber(L,i);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+
+static int
+lua_nodelib_subtype (lua_State *L) {
+ integer i = get_node_subtype_id(L,1);
+ if (i>=0) {
+ lua_pushnumber(L,i);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+/* converts id numbers to type names */
+
+static int
+lua_nodelib_type (lua_State *L) {
+ integer i = get_node_type_id(L,1);
+ if (i>=0) {
+ lua_pushstring(L,node_data[i].name);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+
+/* allocate a new node */
+
+static int
+lua_nodelib_new(lua_State *L) {
+ int i,j;
+ halfword n = null;
+ i = get_valid_node_type_id(L,1);
+
+ if (i==whatsit_node) {
+ j = -1;
+ if (lua_gettop(L)>1) { j = get_valid_node_subtype_id(L,2); }
+ if (j<0) {
+ lua_pushstring(L, "Creating a whatsit requires the subtype number as a second argument");
+ lua_error(L);
+ }
+ } else {
+ j = 0;
+ if (lua_gettop(L)>1) { j = lua_tointeger(L,2); }
+ }
+ n = new_node(i,j);
+ lua_nodelib_push_fast(L,n);
+ return 1;
+}
+
+
+/* Free a node.
+ This function returns the 'next' node, because that may be helpful */
+
+static int
+lua_nodelib_free(lua_State *L) {
+ halfword *n;
+ halfword p;
+ if (lua_gettop(L)<1) {
+ lua_pushnil(L);
+ return 1;
+ } else if(lua_isnil(L,1)) {
+ return 1; /* the nil itself */
+ }
+ n = check_isnode(L,1);
+ p = vlink(*n);
+ flush_node(*n);
+ lua_pushnumber(L,p);
+ lua_nodelib_push(L);
+ return 1;
+}
+
+/* Free a node list */
+
+static int
+lua_nodelib_flush_list(lua_State *L) {
+ halfword *n_ptr;
+ if ((lua_gettop(L)<1) || lua_isnil(L,1))
+ return 0;
+ n_ptr = check_isnode(L,1);
+ flush_node_list(*n_ptr);
+ return 0;
+}
+
+/* find prev, and fix backlinks */
+
+#define set_t_to_prev(head,current) \
+ t = head; \
+ while (vlink(t)!=current && t != null) { \
+ if (vlink(t)!=null) \
+ alink(vlink(t)) = t; \
+ t = vlink(t); \
+ }
+
+/* remove a node from a list */
+
+
+static int
+lua_nodelib_remove (lua_State *L) {
+ halfword head, current, t;
+ if (lua_gettop(L)<2) {
+ lua_pushstring(L,"Not enough arguments for node.remove()");
+ lua_error(L);
+ }
+ head = *(check_isnode(L,1));
+ if (lua_isnil(L,2)) {
+ return 2; /* the arguments, as they are */
+ }
+ current = *(check_isnode(L,2));
+
+ if (head == current) {
+ if (alink(head)!=null && vlink(current)!=null) {
+ alink(vlink(current)) = alink(head);
+ }
+ head = vlink(current);
+ current = head;
+ } else { /* head != current */
+ t = alink(current);
+ if (t==null || vlink(t)!=current) {
+ set_t_to_prev(head,current);
+ if (t==null) { /* error! */
+ lua_pushstring(L,"Attempt to node.remove() a non-existing node");
+ lua_error(L);
+ }
+ }
+ /* t is now the previous node */
+ vlink(t) = vlink(current);
+ if (vlink(current)!=null) {
+ alink(vlink(current)) = t;
+ }
+ current = vlink(current);
+ }
+ lua_pushnumber(L,head);
+ lua_nodelib_push(L);
+ lua_pushnumber(L,current);
+ lua_nodelib_push(L);
+ return 2;
+}
+
+/* Insert a node in a list */
+
+static int
+lua_nodelib_insert_before (lua_State *L) {
+ halfword head, current, n, t;
+ if (lua_gettop(L)<3) {
+ lua_pushstring(L,"Not enough arguments for node.insert_before()");
+ lua_error(L);
+ }
+ if (lua_isnil(L,3)) {
+ lua_pop(L,1);
+ return 2;
+ } else {
+ n = *(check_isnode(L,3));
+ }
+ if (lua_isnil(L,1)) { /* no head */
+ vlink(n) = null;
+ alink(n) = null;
+ lua_nodelib_push_fast(L,n);
+ lua_pushvalue(L,-1);
+ return 2;
+ } else {
+ head = *(check_isnode(L,1));
+ }
+ if (lua_isnil(L,2)) {
+ current = tail_of_list(head);
+ } else {
+ current = *(check_isnode(L,2));
+ }
+ t = alink(current);
+ if (t==null || vlink(t)!=current) {
+ set_t_to_prev(head,current);
+ if (t==null) { /* error! */
+ lua_pushstring(L,"Attempt to node.insert_before() a non-existing node");
+ lua_error(L);
+ }
+ }
+ couple_nodes(t,n);
+ couple_nodes(n,current);
+ if (head==current) {
+ lua_nodelib_push_fast(L,n);
+ } else {
+ lua_nodelib_push_fast(L,head);
+ }
+ lua_nodelib_push_fast(L,n);
+ return 2;
+}
+
+
+static int
+lua_nodelib_insert_after (lua_State *L) {
+ halfword head, current, n;
+ if (lua_gettop(L)<3) {
+ lua_pushstring(L,"Not enough arguments for node.insert_after()");
+ lua_error(L);
+ }
+ if (lua_isnil(L,3)) {
+ lua_pop(L,1);
+ return 2;
+ } else {
+ n = *(check_isnode(L,3));
+ }
+ if (lua_isnil(L,1)) { /* no head */
+ vlink(n) = null;
+ alink(n) = null;
+ lua_nodelib_push_fast(L,n);
+ lua_pushvalue(L,-1);
+ return 2;
+ } else {
+ head = *(check_isnode(L,1));
+ }
+ if (lua_isnil(L,2)) {
+ current = head;
+ while (vlink(current)!=null)
+ current = vlink(current);
+ } else {
+ current = *(check_isnode(L,2));
+ }
+ try_couple_nodes(n,vlink(current));
+ couple_nodes(current, n);
+
+ lua_pop(L,2);
+ lua_nodelib_push_fast(L,n);
+ return 2;
+}
+
+
+/* Copy a node list */
+
+static int
+lua_nodelib_copy_list (lua_State *L) {
+ halfword *n;
+ halfword m;
+ if (lua_isnil(L,1))
+ return 1; /* the nil itself */
+ n = check_isnode(L,1);
+ m = copy_node_list(*n);
+ lua_nodelib_push_fast(L,m);
+ return 1;
+}
+
+/* (Deep) copy a node */
+
+static int
+lua_nodelib_copy(lua_State *L) {
+ halfword *n;
+ halfword m;
+ if (lua_isnil(L,1))
+ return 1; /* the nil itself */
+ n = check_isnode(L,1);
+ m = copy_node(*n);
+ lua_nodelib_push_fast(L,m);
+ return 1;
+}
+
+/* output (write) a node to tex's processor */
+
+static int
+lua_nodelib_append(lua_State *L) {
+ halfword *n;
+ halfword m;
+ int i, j;
+ j = lua_gettop(L);
+ for (i=1;i<=j;i++) {
+ n = check_isnode(L,i);
+ m = copy_node_list(*n);
+ new_tail_append(m);
+ while (vlink(m)!= null) {
+ m = vlink(m);
+ new_tail_append(m);
+ }
+ }
+ return 0;
+}
+
+static int
+lua_nodelib_last_node(lua_State *L) {
+ halfword m;
+ m = pop_tail();
+ lua_pushnumber(L,m);
+ lua_nodelib_push(L);
+ return 1;
+}
+
+
+
+/* build a hbox */
+
+static int
+lua_nodelib_hpack(lua_State *L) {
+ halfword n, p;
+ char *s;
+ integer w = 0;
+ int m = 1;
+ n = *(check_isnode(L,1));
+ if (lua_gettop(L)>1) {
+ w = lua_tointeger(L,2);
+ if (lua_gettop(L)>2 && lua_type(L,3)==LUA_TSTRING) {
+ s = (char *)lua_tostring(L,3);
+ if (strcmp(s,"additional")==0) {
+ m = 1;
+ } else {
+ m = lua_tonumber(L,3);
+ }
+ }
+ }
+ p = hpack(n,w,m);
+ lua_nodelib_push_fast(L,p);
+ return 1;
+}
+
+/* This function is similar to |get_node_type_id|, for field
+ identifiers. It has to do some more work, because not all
+ identifiers are valid for all types of nodes.
+*/
+
+/* this inlining is an optimisation trick. it would be even faster to
+ compare string pointers on the lua stack, but that would require a
+ lot of code reworking that I don't have time for right now.
+*/
+
+
+make_luaS_index(id);
+make_luaS_index(next);
+make_luaS_index(char);
+make_luaS_index(font);
+make_luaS_index(attr);
+make_luaS_index(prev);
+make_luaS_index(lang);
+make_luaS_index(subtype);
+make_luaS_index(left);
+make_luaS_index(right);
+make_luaS_index(uchyph);
+make_luaS_index(components);
+make_luaS_index(xoffset);
+make_luaS_index(yoffset);
+
+
+void initialize_luaS_indexes(lua_State *L) {
+ init_luaS_index(id);
+ init_luaS_index(next);
+ init_luaS_index(char);
+ init_luaS_index(font);
+ init_luaS_index(attr);
+ init_luaS_index(prev);
+ init_luaS_index(lang);
+ init_luaS_index(subtype);
+ init_luaS_index(left);
+ init_luaS_index(right);
+ init_luaS_index(uchyph);
+ init_luaS_index(components);
+ init_luaS_index(xoffset);
+ init_luaS_index(yoffset);
+}
+
+static int
+get_node_field_id (lua_State *L, int n, int node ) {
+ register int t = type(node);
+ register char *s = (char *)lua_tostring(L,n);
+ if (luaS_ptr_eq(s,next)) { return 0; }
+ else if (luaS_ptr_eq(s,id)) { return 1; }
+ else if (luaS_ptr_eq(s,attr) &&
+ nodetype_has_attributes(t)) { return 3 ; }
+ else if (t==glyph_node) {
+ if (luaS_ptr_eq(s,subtype)) { return 2; }
+ else if (luaS_ptr_eq(s,font)) { return 5; }
+ else if (luaS_ptr_eq(s,char)) { return 4; }
+ else if (luaS_ptr_eq(s,prev)) { return -1; }
+ else if (luaS_ptr_eq(s,lang)) { return 6; }
+ else if (luaS_ptr_eq(s,left)) { return 7; }
+ else if (luaS_ptr_eq(s,right)) { return 8; }
+ else if (luaS_ptr_eq(s,uchyph)) { return 9; }
+ else if (luaS_ptr_eq(s,components)) { return 10; }
+ else if (luaS_ptr_eq(s,xoffset)) { return 11; }
+ else if (luaS_ptr_eq(s,yoffset)) { return 12; }
+ }
+ else if (luaS_ptr_eq(s,prev)) { return -1; }
+ else if (luaS_ptr_eq(s,subtype)) { return 2; }
+ else {
+ int j;
+ char **fields = node_data[t].fields;
+ if (t==whatsit_node)
+ fields = whatsit_node_data[subtype(node)].fields;
+ for (j=0;fields[j]!=NULL;j++) {
+ if (strcmp(s,fields[j])==0) {
+ return j+3;
+ }
+ }
+ }
+ return -2;
+}
+
+
+static int
+get_valid_node_field_id (lua_State *L, int n, int node ) {
+ int i = get_node_field_id(L,n,node);
+ if (i==-2) {
+ char *s = (char *)lua_tostring(L,n);
+ lua_pushfstring(L, "Invalid field id %s for node type %s (%d)" , s, node_data[type(node)].name,subtype(node));
+ lua_error(L);
+ }
+ return i;
+}
+
+static int
+lua_nodelib_has_field (lua_State *L) {
+ int i= -2;
+ if (!lua_isnil(L,1)) {
+ i = get_node_field_id(L,2,*(check_isnode(L,1)));
+ }
+ lua_pushboolean(L,(i!=-2));
+ return 1;
+}
+
+
+/* fetch the list of valid node types */
+
+static int
+do_lua_nodelib_types (lua_State *L, node_info *data) {
+ int i;
+ lua_newtable(L);
+ for (i=0;data[i].id!=-1;i++) {
+ lua_pushstring(L,data[i].name);
+ lua_rawseti(L,-2,data[i].id);
+ }
+ return 1;
+}
+
+static int
+lua_nodelib_types (lua_State *L) {
+ return do_lua_nodelib_types (L, node_data);
+}
+
+static int
+lua_nodelib_whatsits (lua_State *L) {
+ return do_lua_nodelib_types (L, whatsit_node_data);
+}
+
+
+/* fetch the list of valid fields */
+
+static int
+lua_nodelib_fields (lua_State *L) {
+ int i = -1;
+ char ** fields;
+ int t = get_valid_node_type_id(L,1);
+ if (t==whatsit_node ) {
+ t = get_valid_node_subtype_id(L,2);
+ fields = whatsit_node_data[t].fields;
+ } else {
+ fields = node_data[t].fields;
+ }
+ lua_checkstack(L,2);
+ lua_newtable(L);
+ lua_pushstring(L,"next");
+ lua_rawseti(L,-2,0);
+ lua_pushstring(L,"id");
+ lua_rawseti(L,-2,1);
+ lua_pushstring(L,"subtype");
+ lua_rawseti(L,-2,2);
+ if (fields!=NULL) {
+ lua_pushstring(L,"prev");
+ lua_rawseti(L,-2,-1);
+ for (i=0;fields[i]!=NULL;i++) {
+ lua_pushstring(L,fields[i]);
+ lua_rawseti(L,-2,(i+3));
+ }
+ }
+ return 1;
+}
+
+/* find the end of a list */
+
+static int
+lua_nodelib_tail (lua_State *L) {
+ halfword *n;
+ halfword t;
+ if (lua_isnil(L,1))
+ return 1; /* the nil itself */
+ n = check_isnode(L,1);
+ t=*n;
+ if (t==null)
+ return 1; /* the old userdata */
+ alink(t) = null;
+ while (vlink(t)!=null) {
+ alink(vlink(t)) = t;
+ t = vlink(t);
+ }
+ lua_nodelib_push_fast(L,t);
+ return 1;
+}
+
+/* a few utility functions for attribute stuff */
+
+static int
+lua_nodelib_has_attribute (lua_State *L) {
+ halfword *n;
+ int i, val ;
+ if (lua_isnil(L,1))
+ return 1; /* the nil itself */
+ n = check_isnode(L,1);
+ i = lua_tointeger(L,2);
+ val = luaL_optinteger(L,3,-1);
+ if((val = has_attribute(*n,i,val))>=0) {
+ lua_pushnumber(L,val);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int
+lua_nodelib_set_attribute (lua_State *L) {
+ halfword *n;
+ int i, val;
+ if (lua_gettop(L)==3) {
+ i = lua_tointeger(L,2);
+ val = lua_tointeger(L,3);
+ n = check_isnode(L,1);
+ if (val<0) {
+ (void)unset_attribute(*n,i,val);
+ } else {
+ set_attribute(*n,i,val);
+ }
+ } else {
+ lua_pushstring(L,"incorrect number of arguments");
+ lua_error(L);
+ }
+ return 0;
+}
+
+
+static int
+lua_nodelib_unset_attribute (lua_State *L) {
+ halfword *n;
+ int i, val, ret;
+ if (lua_gettop(L)<=3) {
+ i = luaL_checknumber(L,2);
+ val = luaL_optnumber(L,3,-1);
+ n = check_isnode(L,1);
+ ret = unset_attribute(*n,i,val);
+ if(ret>=0) {
+ lua_pushnumber(L,ret);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+ } else {
+ lua_pushstring(L,"incorrect number of arguments");
+ return lua_error(L);
+ }
+}
+
+
+/* iteration */
+
+static int nodelib_aux_nil (lua_State *L) {
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+nodelib_aux_next_filtered (lua_State *L) {
+ register halfword t; /* traverser */
+ register int i = lua_tointeger(L,lua_upvalueindex(1));
+ if (lua_isnil(L,2)) { /* first call */
+ t = *check_isnode(L,1);
+ } else {
+ t = *check_isnode(L,2);
+ t = vlink(t);
+ }
+ while (t!=null && type(t)!=i) { t = vlink(t); }
+ if (t==null) {
+ lua_pushnil(L);
+ } else {
+ lua_nodelib_push_fast(L,t);
+ }
+ return 1;
+}
+
+
+static int
+lua_nodelib_traverse_filtered (lua_State *L) {
+ halfword n;
+ if (lua_isnil(L,2)) {
+ lua_pushcclosure(L, nodelib_aux_nil, 0);
+ return 1;
+ }
+ n = *(check_isnode(L,2));
+ lua_pop(L,1); /* the node, integer remains */
+ lua_pushcclosure(L, nodelib_aux_next_filtered, 1);
+ lua_nodelib_push_fast(L,n);
+ lua_pushnil(L);
+ return 3;
+}
+
+static int
+nodelib_aux_next (lua_State *L) {
+ register halfword t; /* traverser */
+ if (lua_isnil(L,2)) { /* first call */
+ t = *check_isnode(L,1);
+ } else {
+ t = *check_isnode(L,2);
+ t = vlink(t);
+ }
+ if (t==null) {
+ lua_pushnil(L);
+ } else {
+ lua_nodelib_push_fast(L,t);
+ }
+ return 1;
+}
+
+static int
+lua_nodelib_traverse (lua_State *L) {
+ halfword n;
+ if (lua_isnil(L,1)) {
+ lua_pushcclosure(L, nodelib_aux_nil, 0);
+ return 1;
+ }
+ n = *(check_isnode(L,1));
+ lua_pushcclosure(L, nodelib_aux_next, 0);
+ lua_nodelib_push_fast(L,n);
+ lua_pushnil(L);
+ return 3;
+;
+}
+
+
+
+static int
+do_lua_nodelib_count (lua_State *L, halfword match, int i, halfword first) {
+ int count = 0;
+ int t = first;
+ while (t!=match) {
+ if (i<0 || type(t)==i) { count++; }
+ t = vlink(t);
+ }
+ lua_pushnumber(L,count);
+ return 1;
+}
+
+static int lua_nodelib_length (lua_State *L) {
+ halfword n;
+ halfword m = null;
+ if (lua_isnil(L,1)) {
+ lua_pushnumber(L,0);
+ return 1;
+ }
+ n = *(check_isnode(L,1));
+ if (lua_gettop(L)==2) {
+ m = *(check_isnode(L,2));
+ }
+ return do_lua_nodelib_count(L,m,-1,n);
+}
+
+
+static int lua_nodelib_count (lua_State *L) {
+ halfword n;
+ halfword m = null;
+ int i = -1;
+ i = lua_tointeger(L,1);
+ if (lua_isnil(L,2)) {
+ lua_pushnumber(L,0);
+ return 1;
+ }
+ n = *(check_isnode(L,2));
+ if (lua_gettop(L)==3)
+ m = *(check_isnode(L,3));
+ return do_lua_nodelib_count(L,m,i,n);
+}
+
+/* fetching a field from a node */
+
+#define nodelib_pushlist(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); }
+#define nodelib_pushattr(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); }
+#define nodelib_pushspec(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); }
+#define nodelib_pushaction(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); }
+#define nodelib_pushstring(L,n) { lua_pushstring(L,makecstring(n)); }
+
+static void
+lua_nodelib_getfield_whatsit (lua_State *L, int n, int field) {
+ if (field==2) {
+ lua_pushnumber(L,subtype(n));
+ } else {
+ switch (subtype(n)) {
+ case open_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,write_stream(n)); break;
+ case 5: nodelib_pushstring(L,open_name(n)); break;
+ case 6: nodelib_pushstring(L,open_area(n)); break;
+ case 7: nodelib_pushstring(L,open_ext(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case write_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,write_stream(n)); break;
+ case 5: tokenlist_to_lua(L,write_tokens(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case close_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,write_stream(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case special_node:
+ switch (field) {
+ case 4: tokenlist_to_luastring(L,write_tokens(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case local_par_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,local_pen_inter(n)); break;
+ case 5: lua_pushnumber(L,local_pen_broken(n)); break;
+ case 6: lua_pushnumber(L,local_par_dir(n)); break;
+ case 7: nodelib_pushlist(L,local_box_left(n)); break;
+ case 8: lua_pushnumber(L,local_box_left_width(n)); break;
+ case 9: nodelib_pushlist(L,local_box_right(n)); break;
+ case 10: lua_pushnumber(L,local_box_right_width(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case dir_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,dir_dir(n)); break;
+ case 5: lua_pushnumber(L,dir_level(n)); break;
+ case 6: lua_pushnumber(L,dir_dvi_ptr(n)); break;
+ case 7: lua_pushnumber(L,dir_dvi_h(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case pdf_literal_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,pdf_literal_mode(n)); break;
+ case 5: tokenlist_to_luastring(L,pdf_literal_data(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case pdf_refobj_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,pdf_obj_objnum(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case pdf_refxform_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,pdf_width(n)); break;
+ case 5: lua_pushnumber(L,pdf_height(n)); break;
+ case 6: lua_pushnumber(L,pdf_depth(n)); break;
+ case 7: lua_pushnumber(L,pdf_xform_objnum(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case pdf_refximage_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,pdf_width(n)); break;
+ case 5: lua_pushnumber(L,pdf_height(n)); break;
+ case 6: lua_pushnumber(L,pdf_depth(n)); break;
+ case 7: lua_pushnumber(L,pdf_ximage_objnum(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case pdf_annot_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,pdf_width(n)); break;
+ case 5: lua_pushnumber(L,pdf_height(n)); break;
+ case 6: lua_pushnumber(L,pdf_depth(n)); break;
+ case 7: lua_pushnumber(L,pdf_annot_objnum(n)); break;
+ case 8: tokenlist_to_luastring(L,pdf_annot_data(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case pdf_start_link_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,pdf_width(n)); break;
+ case 5: lua_pushnumber(L,pdf_height(n)); break;
+ case 6: lua_pushnumber(L,pdf_depth(n)); break;
+ case 7: lua_pushnumber(L,pdf_link_objnum(n)); break;
+ case 8: tokenlist_to_luastring(L,pdf_link_attr(n)); break;
+ case 9: nodelib_pushaction(L,pdf_link_action(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case pdf_dest_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,pdf_width(n)); break;
+ case 5: lua_pushnumber(L,pdf_height(n)); break;
+ case 6: lua_pushnumber(L,pdf_depth(n)); break;
+ case 7: lua_pushnumber(L,pdf_dest_named_id(n)); break;
+ case 8: if (pdf_dest_named_id(n) == 1)
+ tokenlist_to_luastring(L,pdf_dest_id(n));
+ else
+ lua_pushnumber(L,pdf_dest_id(n)); break;
+ case 9: lua_pushnumber(L,pdf_dest_type(n)); break;
+ case 10: lua_pushnumber(L,pdf_dest_xyz_zoom(n)); break;
+ case 11: lua_pushnumber(L,pdf_dest_objnum(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case pdf_thread_node:
+ case pdf_start_thread_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,pdf_width(n)); break;
+ case 5: lua_pushnumber(L,pdf_height(n)); break;
+ case 6: lua_pushnumber(L,pdf_depth(n)); break;
+ case 7: lua_pushnumber(L,pdf_thread_named_id(n)); break;
+ case 8: if (pdf_thread_named_id(n) == 1)
+ tokenlist_to_luastring(L,pdf_thread_id(n));
+ else
+ lua_pushnumber(L,pdf_thread_id(n)); break;
+ case 9: tokenlist_to_luastring(L,pdf_thread_attr(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case late_lua_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,late_lua_reg(n)); break;
+ case 5: tokenlist_to_luastring(L,late_lua_data(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case close_lua_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,late_lua_reg(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case pdf_colorstack_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,pdf_colorstack_stack(n)); break;
+ case 5: lua_pushnumber(L,pdf_colorstack_cmd(n)); break;
+ case 6: tokenlist_to_luastring(L,pdf_colorstack_data(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case pdf_setmatrix_node:
+ switch (field) {
+ case 4: tokenlist_to_luastring(L,pdf_setmatrix_data(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case user_defined_node:
+ switch (field) {
+ case 4: lua_pushnumber(L,user_node_id(n)); break;
+ case 5: lua_pushnumber(L,user_node_type(n)); break;
+ case 6:
+ switch (user_node_type(n)) {
+ case 'a': nodelib_pushlist(L,user_node_value(n)); break;
+ case 'd': lua_pushnumber(L,user_node_value(n)); break;
+ case 'n': nodelib_pushlist(L,user_node_value(n)); break;
+ case 's': nodelib_pushstring(L,user_node_value(n)); break;
+ case 't': tokenlist_to_lua(L,user_node_value(n)); break;
+ default: lua_pushnumber(L,user_node_value(n)); break;
+ } break;
+ default: lua_pushnil(L);
+ }
+ break;
+ default:
+ lua_pushnil(L);
+ break;
+ }
+ }
+}
+
+
+static int
+lua_nodelib_getfield (lua_State *L) {
+ halfword *n_ptr, n;
+ int field;
+ if (lua_isnil(L,1))
+ return 1; /* a nil */
+ n_ptr = check_isnode(L,1);
+ n = *n_ptr;
+ field = get_valid_node_field_id(L,2, n);
+
+ if (field<-1)
+ return 0;
+ if (field==0) {
+ lua_pushnumber(L,vlink(n));
+ lua_nodelib_push(L);
+ } else if (field==1) {
+ lua_pushnumber(L,type(n));
+ } else if (field==-1) {
+ lua_pushnumber(L,alink(n));
+ lua_nodelib_push(L);
+ } else if (field==3 && nodetype_has_attributes(type(n))) {
+ nodelib_pushattr(L,node_attr(n));
+ } else {
+ switch (type(n)) {
+ case hlist_node:
+ case vlist_node:
+ switch (field) {
+ case 2: lua_pushnumber(L,subtype(n)); break;
+ case 4: lua_pushnumber(L,width(n)); break;
+ case 5: lua_pushnumber(L,depth(n)); break;
+ case 6: lua_pushnumber(L,height(n)); break;
+ case 7: lua_pushnumber(L,box_dir(n)); break;
+ case 8: lua_pushnumber(L,shift_amount(n)); break;
+ case 9: lua_pushnumber(L,glue_order(n)); break;
+ case 10: lua_pushnumber(L,glue_sign(n)); break;
+ case 11: lua_pushnumber(L,(double)glue_set(n)); break;
+ case 12: nodelib_pushlist(L,list_ptr(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case unset_node:
+ switch (field) {
+ case 2: lua_pushnumber(L,0); break;
+ case 4: lua_pushnumber(L,width(n)); break;
+ case 5: lua_pushnumber(L,depth(n)); break;
+ case 6: lua_pushnumber(L,height(n)); break;
+ case 7: lua_pushnumber(L,box_dir(n)); break;
+ case 8: lua_pushnumber(L,glue_shrink(n)); break;
+ case 9: lua_pushnumber(L,glue_order(n)); break;
+ case 10: lua_pushnumber(L,glue_sign(n)); break;
+ case 11: lua_pushnumber(L,glue_stretch(n)); break;
+ case 12: lua_pushnumber(L,span_count(n)); break;
+ case 13: nodelib_pushlist(L,list_ptr(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case rule_node:
+ switch (field) {
+ case 2: lua_pushnumber(L,0); break;
+ case 4: lua_pushnumber(L,width(n)); break;
+ case 5: lua_pushnumber(L,depth(n)); break;
+ case 6: lua_pushnumber(L,height(n)); break;
+ case 7: lua_pushnumber(L,rule_dir(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case ins_node:
+ switch (field) {
+ case 2: lua_pushnumber(L,subtype(n)); break;
+ case 4: lua_pushnumber(L,float_cost(n)); break;
+ case 5: lua_pushnumber(L,depth(n)); break;
+ case 6: lua_pushnumber(L,height(n)); break;
+ case 7: nodelib_pushspec(L,split_top_ptr(n)); break;
+ case 8: nodelib_pushlist(L,ins_ptr(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case mark_node:
+ switch (field) {
+ case 2: lua_pushnumber(L,subtype(n)); break;
+ case 4: lua_pushnumber(L,mark_class(n)); break;
+ case 5: tokenlist_to_lua(L,mark_ptr(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case adjust_node:
+ switch (field) {
+ case 2: lua_pushnumber(L,subtype(n)); break;
+ case 4: nodelib_pushlist(L,adjust_ptr(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case disc_node:
+ switch (field) {
+ case 2: lua_pushnumber(L,subtype(n)); break;
+ case 4: nodelib_pushlist(L,vlink(pre_break(n))); break;
+ case 5: nodelib_pushlist(L,vlink(post_break(n))); break;
+ case 6: nodelib_pushlist(L,vlink(no_break(n))); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case math_node:
+ switch (field) {
+ case 2: lua_pushnumber(L,subtype(n)); break;
+ case 4: lua_pushnumber(L,surround(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case glue_node:
+ switch (field) {
+ case 2: lua_pushnumber(L,subtype(n)); break;
+ case 4: nodelib_pushspec(L,glue_ptr(n)); break;
+ case 5: nodelib_pushlist(L,leader_ptr(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case glue_spec_node:
+ switch (field) {
+ case 2: lua_pushnumber(L,0); break;
+ case 3: lua_pushnumber(L,width(n)); break;
+ case 4: lua_pushnumber(L,stretch(n)); break;
+ case 5: lua_pushnumber(L,shrink(n)); break;
+ case 6: lua_pushnumber(L,stretch_order(n)); break;
+ case 7: lua_pushnumber(L,shrink_order(n)); break;
+ case 8: lua_pushnumber(L,glue_ref_count(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case kern_node:
+ switch (field) {
+ case 2: lua_pushnumber(L,subtype(n)); break;
+ case 4: lua_pushnumber(L,width(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case penalty_node:
+ switch (field) {
+ case 2: lua_pushnumber(L,0); break;
+ case 4: lua_pushnumber(L,penalty(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case glyph_node:
+ switch (field) {
+ case 2: lua_pushnumber(L,subtype(n)); break;
+ case 4: lua_pushnumber(L,character(n)); break;
+ case 5: lua_pushnumber(L,font(n)); break;
+ case 6: lua_pushnumber(L,char_lang(n)); break;
+ case 7: lua_pushnumber(L,char_lhmin(n)); break;
+ case 8: lua_pushnumber(L,char_rhmin(n)); break;
+ case 9: lua_pushnumber(L,char_uchyph(n)); break;
+ case 10: nodelib_pushlist(L,lig_ptr(n)); break;
+ case 11: lua_pushnumber(L,x_displace(n)); break;
+ case 12: lua_pushnumber(L,y_displace(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case inserting_node:
+ switch (field) {
+ case 2: lua_pushnumber(L,subtype(n)); break;
+ case 3: nodelib_pushlist(L,last_ins_ptr(n)); break;
+ case 4: nodelib_pushlist(L,best_ins_ptr(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case split_up_node:
+ switch (field) {
+ case 2: lua_pushnumber(L,subtype(n)); break;
+ case 3: nodelib_pushlist(L,last_ins_ptr(n)); break;
+ case 4: nodelib_pushlist(L,best_ins_ptr(n)); break;
+ case 5: nodelib_pushlist(L,broken_ptr(n)); break;
+ case 6: nodelib_pushlist(L,broken_ins(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case margin_kern_node :
+ switch (field) {
+ case 2: lua_pushnumber(L,subtype(n)); break;
+ case 3: lua_pushnumber(L,width(n)); break;
+ case 4: nodelib_pushlist(L,margin_char(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case action_node:
+ switch (field) {
+ case 2: lua_pushnil(L); /* dummy subtype */ break;
+ case 3: lua_pushnumber(L,pdf_action_type(n)); break;
+ case 4: lua_pushnumber(L,pdf_action_named_id(n)); break;
+ case 5: if (pdf_action_named_id(n)==1) {
+ tokenlist_to_luastring(L,pdf_action_id(n));
+ } else {
+ lua_pushnumber(L,pdf_action_id(n));
+ } break;
+ case 6: tokenlist_to_luastring(L,pdf_action_file(n)); break;
+ case 7: lua_pushnumber(L,pdf_action_new_window(n)); break;
+ case 8: tokenlist_to_luastring(L,pdf_action_tokens(n));break;
+ case 9: lua_pushnumber(L,pdf_action_refcount(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case attribute_list_node :
+ switch (field) {
+ case 2: lua_pushnumber(L,0); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case attribute_node :
+ switch (field) {
+ case 2: lua_pushnumber(L,0); break;
+ case 3: lua_pushnumber(L,attribute_id(n)); break;
+ case 4: lua_pushnumber(L,attribute_value(n)); break;
+ default: lua_pushnil(L);
+ }
+ break;
+ case whatsit_node:
+ lua_nodelib_getfield_whatsit(L,n,field);
+ break;
+ default:
+ lua_pushnil(L);
+ break;
+ }
+ }
+ return 1;
+}
+
+
+static int nodelib_getlist(lua_State *L, int n) {
+ halfword *m;
+ if (lua_isuserdata(L,n)) {
+ m = check_isnode(L,n);
+ return *m;
+ } else {
+ return null ;
+ }
+}
+
+#define nodelib_getspec nodelib_getlist
+#define nodelib_getaction nodelib_getlist
+
+
+static str_number
+nodelib_getstring(lua_State *L, int a) {
+ size_t k;
+ char *s=(char *)lua_tolstring(L,a, &k);
+ return maketexlstring(s,k);
+}
+
+#define nodelib_gettoks(L,a) tokenlist_from_lua(L)
+
+static void nodelib_setattr (lua_State *L, int stackindex, halfword n) {
+ halfword p;
+ p = nodelib_getlist(L,stackindex);
+ if (node_attr(n) != p) {
+ if (node_attr(n)!=null)
+ delete_attribute_ref(node_attr(n));
+ node_attr(n) = p;
+ attr_list_ref(p)++;
+ }
+}
+
+static int nodelib_cantset (lua_State *L, int field, int n) {
+ lua_pushfstring(L,"You cannot set field %d in a node of type %s",
+ field, node_data[type(n)].name);
+ lua_error(L);
+ return 0;
+}
+
+static int
+lua_nodelib_setfield_whatsit(lua_State *L, int n, int field) {
+ switch (subtype(n)) {
+ case open_node:
+ switch (field) {
+ case 4: write_stream(n) = lua_tointeger(L,3); break;
+ case 5: open_name(n) = nodelib_getstring(L,3); break;
+ case 6: open_area(n) = nodelib_getstring(L,3); break;
+ case 7: open_ext(n) = nodelib_getstring(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case write_node:
+ switch (field) {
+ case 4: write_stream(n) = lua_tointeger(L,3); break;
+ case 5: write_tokens(n) = nodelib_gettoks(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case close_node:
+ switch (field) {
+ case 4: write_stream(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case special_node:
+ switch (field) {
+ case 4: write_tokens(n) = nodelib_gettoks(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case local_par_node:
+ switch (field) {
+ case 4: local_pen_inter(n) = lua_tointeger(L,3); break;
+ case 5: local_pen_broken(n) = lua_tointeger(L,3); break;
+ case 6: local_par_dir(n) = lua_tointeger(L,3); break;
+ case 7: local_box_left(n) = nodelib_getlist(L,3); break;
+ case 8: local_box_left_width(n) = lua_tointeger(L,3); break;
+ case 9: local_box_right(n) = nodelib_getlist(L,3); break;
+ case 10: local_box_right_width(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case dir_node:
+ switch (field) {
+ case 4: dir_dir(n) = lua_tointeger(L,3); break;
+ case 5: dir_level(n) = lua_tointeger(L,3); break;
+ case 6: dir_dvi_ptr(n) = lua_tointeger(L,3); break;
+ case 7: dir_dvi_h(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case pdf_literal_node:
+ switch (field) {
+ case 4: pdf_literal_mode(n) = lua_tointeger(L,3); break;
+ case 5: pdf_literal_data(n) = nodelib_gettoks(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case pdf_refobj_node:
+ switch (field) {
+ case 4: pdf_obj_objnum(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case pdf_refxform_node:
+ switch (field) {
+ case 4: pdf_width(n) = lua_tointeger(L,3); break;
+ case 5: pdf_height(n) = lua_tointeger(L,3); break;
+ case 6: pdf_depth(n) = lua_tointeger(L,3); break;
+ case 7: pdf_xform_objnum(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case pdf_refximage_node:
+ switch (field) {
+ case 4: pdf_width(n) = lua_tointeger(L,3); break;
+ case 5: pdf_height(n) = lua_tointeger(L,3); break;
+ case 6: pdf_depth(n) = lua_tointeger(L,3); break;
+ case 7: pdf_ximage_objnum(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case pdf_annot_node:
+ switch (field) {
+ case 4: pdf_width(n) = lua_tointeger(L,3); break;
+ case 5: pdf_height(n) = lua_tointeger(L,3); break;
+ case 6: pdf_depth(n) = lua_tointeger(L,3); break;
+ case 7: pdf_annot_objnum(n) = lua_tointeger(L,3); break;
+ case 8: pdf_annot_data(n) = nodelib_getstring(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case pdf_start_link_node:
+ switch (field) {
+ case 4: pdf_width(n) = lua_tointeger(L,3); break;
+ case 5: pdf_height(n) = lua_tointeger(L,3); break;
+ case 6: pdf_depth(n) = lua_tointeger(L,3); break;
+ case 7: pdf_link_objnum(n) = lua_tointeger(L,3); break;
+ case 8: pdf_link_attr(n) = nodelib_getstring(L,3); break;
+ case 9: pdf_link_action(n) = nodelib_getaction(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case pdf_end_link_node:
+ switch (field) {
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case pdf_dest_node:
+ switch (field) {
+ case 4: pdf_width(n) = lua_tointeger(L,3); break;
+ case 5: pdf_height(n) = lua_tointeger(L,3); break;
+ case 6: pdf_depth(n) = lua_tointeger(L,3); break;
+ case 7: pdf_dest_named_id(n) = lua_tointeger(L,3); break;
+ case 8: if (pdf_dest_named_id(n)==1)
+ pdf_dest_id(n) = nodelib_gettoks(L,3);
+ else
+ pdf_dest_id(n) = lua_tointeger(L,3); break;
+ case 9: pdf_dest_type(n) = lua_tointeger(L,3); break;
+ case 10: pdf_dest_xyz_zoom(n) = lua_tointeger(L,3); break;
+ case 11: pdf_dest_objnum(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case pdf_thread_node:
+ case pdf_start_thread_node:
+ switch (field) {
+ case 4: pdf_width(n) = lua_tointeger(L,3); break;
+ case 5: pdf_height(n) = lua_tointeger(L,3); break;
+ case 6: pdf_depth(n) = lua_tointeger(L,3); break;
+ case 7: pdf_thread_named_id(n) = lua_tointeger(L,3); break;
+ case 8: if (pdf_thread_named_id(n)==1)
+ pdf_thread_id(n) = nodelib_gettoks(L,3);
+ else
+ pdf_thread_id(n) = lua_tointeger(L,3); break;
+ case 9: pdf_thread_attr(n) = nodelib_gettoks(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case pdf_end_thread_node:
+ case pdf_save_pos_node:
+ return nodelib_cantset(L,field,n);
+ break;
+ case late_lua_node:
+ switch (field) {
+ case 4: late_lua_reg(n) = lua_tointeger(L,3); break;
+ case 5: late_lua_data(n) = nodelib_gettoks(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case close_lua_node:
+ switch (field) {
+ case 4: late_lua_reg(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case pdf_colorstack_node:
+ switch (field) {
+ case 4: pdf_colorstack_stack(n) = lua_tointeger(L,3); break;
+ case 5: pdf_colorstack_cmd(n) = lua_tointeger(L,3); break;
+ case 6: pdf_colorstack_data(n) = nodelib_gettoks(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case pdf_setmatrix_node:
+ switch (field) {
+ case 4: pdf_setmatrix_data(n) = nodelib_gettoks(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case pdf_save_node:
+ case pdf_restore_node:
+ case cancel_boundary_node:
+ return nodelib_cantset(L,field,n);
+ break;
+ case user_defined_node:
+ switch (field) {
+ case 4: user_node_id(n) = lua_tointeger(L,3); break;
+ case 5: user_node_type(n) = lua_tointeger(L,3); break;
+ case 6:
+ switch(user_node_type(n)) {
+ case 'a': user_node_value(n) = nodelib_getlist(L,3); break;
+ case 'd': user_node_value(n) = lua_tointeger(L,3); break;
+ case 'n': user_node_value(n) = nodelib_getlist(L,3); break;
+ case 's': user_node_value(n) = nodelib_getstring(L,3); break;
+ case 't': user_node_value(n) = nodelib_gettoks(L,3); break;
+ default: user_node_value(n) = lua_tointeger(L,3); break;
+ } break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ return 0;
+}
+
+static int
+lua_nodelib_setfield (lua_State *L) {
+ register halfword n;
+ register int field;
+ n = *check_isnode(L,1);
+ field = get_valid_node_field_id(L,2,n);
+ if (field<-1)
+ return 0;
+ if (field==0) {
+ vlink(n) = nodelib_getlist(L,3);
+ } else if (field==-1) {
+ alink(n) = nodelib_getlist(L,3);
+ } else if (field==3 && nodetype_has_attributes(type(n))) {
+ nodelib_setattr(L,3,n);
+ } else if (type(n)==glyph_node) {
+ switch (field) {
+ case 2: subtype(n) = lua_tointeger(L,3); break;
+ case 4: character(n) = lua_tointeger(L,3); break;
+ case 5: font(n) = lua_tointeger(L,3); break;
+ case 6: set_char_lang(n,lua_tointeger(L,3)); break;
+ case 7: set_char_lhmin(n,lua_tointeger(L,3)); break;
+ case 8: set_char_rhmin(n,lua_tointeger(L,3)); break;
+ case 9: set_char_uchyph(n,lua_tointeger(L,3)); break;
+ case 10: lig_ptr(n) = nodelib_getlist(L,3); break;
+ case 11: x_displace(n) = lua_tointeger(L,3); break;
+ case 12: y_displace(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ } else {
+ switch (type(n)) {
+ case hlist_node:
+ case vlist_node:
+ switch (field) {
+ case 2: subtype(n) = lua_tointeger(L,3); break;
+ case 4: width(n) = lua_tointeger(L,3); break;
+ case 5: depth(n) = lua_tointeger(L,3); break;
+ case 6: height(n) = lua_tointeger(L,3); break;
+ case 7: box_dir(n) = lua_tointeger(L,3); break;
+ case 8: shift_amount(n) = lua_tointeger(L,3); break;
+ case 9: glue_order(n) = lua_tointeger(L,3); break;
+ case 10: glue_sign(n) = lua_tointeger(L,3); break;
+ case 11: glue_set(n) = (double)lua_tonumber(L,3); break;
+ case 12: list_ptr(n) = nodelib_getlist(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case unset_node:
+ switch (field) {
+ case 2: /* dummy subtype */ break;
+ case 4: width(n) = lua_tointeger(L,3); break;
+ case 5: depth(n) = lua_tointeger(L,3); break;
+ case 6: height(n) = lua_tointeger(L,3); break;
+ case 7: box_dir(n) = lua_tointeger(L,3); break;
+ case 8: glue_shrink(n) = lua_tointeger(L,3); break;
+ case 9: glue_order(n) = lua_tointeger(L,3); break;
+ case 10: glue_sign(n) = lua_tointeger(L,3); break;
+ case 11: glue_stretch(n) = lua_tointeger(L,3); break;
+ case 12: span_count(n) = lua_tointeger(L,3); break;
+ case 13: list_ptr(n) = nodelib_getlist(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case rule_node:
+ switch (field) {
+ case 2: /* dummy subtype */ break;
+ case 4: width(n) = lua_tointeger(L,3); break;
+ case 5: depth(n) = lua_tointeger(L,3); break;
+ case 6: height(n) = lua_tointeger(L,3); break;
+ case 7: rule_dir(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case ins_node:
+ switch (field) {
+ case 2: subtype(n) = lua_tointeger(L,3); break;
+ case 4: float_cost(n) = lua_tointeger(L,3); break;
+ case 5: depth(n) = lua_tointeger(L,3); break;
+ case 6: height(n) = lua_tointeger(L,3); break;
+ case 7: split_top_ptr(n) = nodelib_getspec(L,3); break;
+ case 8: ins_ptr(n) = nodelib_getlist(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case mark_node:
+ switch (field) {
+ case 2: subtype(n) = lua_tointeger(L,3); break;
+ case 4: mark_class(n) = lua_tointeger(L,3); break;
+ case 5: mark_ptr(n) = nodelib_gettoks(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case adjust_node:
+ switch (field) {
+ case 2: subtype(n) = lua_tointeger(L,3); break;
+ case 4: adjust_ptr(n) = nodelib_getlist(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case disc_node:
+ switch (field) {
+ case 2: subtype(n) = lua_tointeger(L,3); break;
+ case 4: set_disc_field(pre_break(n),nodelib_getlist(L,3)); break;
+ case 5: set_disc_field(post_break(n),nodelib_getlist(L,3)); break;
+ case 6: set_disc_field(no_break(n),nodelib_getlist(L,3)); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case math_node:
+ switch (field) {
+ case 2: subtype(n) = lua_tointeger(L,3); break;
+ case 4: surround(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case glue_node:
+ switch (field) {
+ case 2: subtype(n) = lua_tointeger(L,3); break;
+ case 4: glue_ptr(n) = nodelib_getspec(L,3); break;
+ case 5: leader_ptr(n) = nodelib_getlist(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case glue_spec_node:
+ switch (field) {
+ case 2: /* dummy subtype */ break;
+ case 3: width(n) = lua_tointeger(L,3); break;
+ case 4: stretch(n) = lua_tointeger(L,3); break;
+ case 5: shrink(n) = lua_tointeger(L,3); break;
+ case 6: stretch_order(n) = lua_tointeger(L,3); break;
+ case 7: shrink_order(n) = lua_tointeger(L,3); break;
+ case 8: glue_ref_count(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case kern_node:
+ switch (field) {
+ case 2: subtype(n) = lua_tointeger(L,3); break;
+ case 4: width(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case penalty_node:
+ switch (field) {
+ case 2: /* dummy subtype */ break;
+ case 4: penalty(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case action_node:
+ switch (field) {
+ case 2: /* dummy subtype */ break;
+ case 3: pdf_action_type(n) = lua_tointeger(L,3); break;
+ case 4: pdf_action_named_id(n) = lua_tointeger(L,3); break;
+ case 5: if (pdf_action_named_id(n)==1) {
+ pdf_action_id(n) = nodelib_gettoks(L,3);
+ } else {
+ pdf_action_id(n) = lua_tointeger(L,3);
+ } break;
+ case 6: pdf_action_file(n) = nodelib_gettoks(L,3); break;
+ case 7: pdf_action_new_window(n) = lua_tointeger(L,3); break;
+ case 8: pdf_action_tokens(n) = nodelib_gettoks(L,3); break;
+ case 9: pdf_action_refcount(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case margin_kern_node:
+ switch (field) {
+ case 2: subtype(n) = lua_tointeger(L,3); break;
+ case 3: width(n) = lua_tointeger(L,3); break;
+ case 4: margin_char(n) = nodelib_getlist(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case inserting_node:
+ switch (field) {
+ case 2: subtype(n) = lua_tointeger(L,3); break;
+ case 3: last_ins_ptr(n) = nodelib_getlist(L,3); break;
+ case 4: best_ins_ptr(n) = nodelib_getlist(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case split_up_node:
+ switch (field) {
+ case 2: subtype(n) = lua_tointeger(L,3); break;
+ case 3: last_ins_ptr(n) = nodelib_getlist(L,3); break;
+ case 4: best_ins_ptr(n) = nodelib_getlist(L,3); break;
+ case 5: broken_ptr(n) = nodelib_getlist(L,3); break;
+ case 6: broken_ins(n) = nodelib_getlist(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case attribute_list_node:
+ switch (field) {
+ case 2: /* dummy subtype */ break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case attribute_node:
+ switch (field) {
+ case 2: /* dummy subtype */ break;
+ case 3: attribute_id(n) = lua_tointeger(L,3); break;
+ case 4: attribute_value(n) = lua_tointeger(L,3); break;
+ default: return nodelib_cantset(L,field,n);
+ }
+ break;
+ case whatsit_node:
+ lua_nodelib_setfield_whatsit(L,n,field);
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+ return 0;
+}
+
+static int
+lua_nodelib_print (lua_State *L) {
+ char *msg;
+ char a[7] = {' ',' ',' ', 'n', 'i', 'l', 0};
+ char v[7] = {' ',' ',' ', 'n', 'i', 'l', 0};
+ halfword *n;
+ n = check_isnode(L,1);
+ msg = xmalloc(256);
+ if (alink(*n)!=null)
+ snprintf(a,7,"%6d",(int)alink(*n));
+ if (vlink(*n)!=null)
+ snprintf(v,7,"%6d",(int)vlink(*n));
+ snprintf(msg,255,"<node %s < %6d > %s : %s %d>", a, (int)*n, v, node_data[type(*n)].name, subtype(*n));
+ lua_pushstring(L,msg);
+ free(msg);
+ return 1;
+}
+
+
+static int
+lua_nodelib_equal (lua_State *L) {
+ halfword n, m;
+ n = *(check_isnode(L,1));
+ m = *(check_isnode(L,2));
+ lua_pushboolean(L,(n==m));
+ return 1;
+}
+
+static int
+font_tex_ligaturing (lua_State *L) {
+ /* on the stack are two nodes and a direction */
+ halfword tmp_head;
+ halfword *h;
+ halfword t =null;
+ if (lua_gettop(L)<1) {
+ lua_pushnil(L);
+ lua_pushboolean(L,0);
+ return 2;
+ }
+ h = check_isnode(L,1);
+ if (lua_gettop(L)>1) {
+ t = *(check_isnode(L,2));
+ }
+ tmp_head = new_node(nesting_node,1);
+ couple_nodes(tmp_head,*h);
+ tlink(tmp_head)=t;
+ t = handle_ligaturing(tmp_head,t);
+ lua_pushnumber(L,vlink(tmp_head));
+ flush_node(tmp_head);
+ lua_nodelib_push(L);
+ lua_pushnumber(L,t);
+ lua_nodelib_push(L);
+ lua_pushboolean(L,1);
+ return 3;
+}
+
+static int
+font_tex_kerning (lua_State *L) {
+ /* on the stack are two nodes and a direction */
+
+ halfword tmp_head;
+ halfword *h;
+ halfword t =null;
+ if (lua_gettop(L)<1) {
+ lua_pushnil(L);
+ lua_pushboolean(L,0);
+ return 2;
+ }
+ h = check_isnode(L,1);
+ if (lua_gettop(L)>1) {
+ t = *(check_isnode(L,2));
+ }
+ tmp_head = new_node(nesting_node,1);
+ couple_nodes(tmp_head,*h);
+ tlink(tmp_head)=t;
+ t = handle_kerning(tmp_head,t);
+ lua_pushnumber(L,vlink(tmp_head));
+ flush_node(tmp_head);
+ lua_nodelib_push(L);
+ lua_pushnumber(L,t);
+ lua_nodelib_push(L);
+ lua_pushboolean(L,1);
+ return 3;
+}
+
+static int
+lua_nodelib_protect_glyphs (lua_State *L) {
+ int t = 0;
+ halfword head = *(check_isnode(L,1));
+ while (head!=null) {
+ if (type(head)==glyph_node) {
+ register int s = subtype(head);
+ if (s<256) {
+ t = 1;
+ subtype(head) = ((s&0xFE) << 8);
+ }
+ }
+ head = vlink(head);
+ }
+ lua_pushboolean(L,t);
+ lua_pushvalue(L,1);
+ return 2;
+}
+
+static int
+lua_nodelib_unprotect_glyphs (lua_State *L) {
+ int t = 0;
+ halfword head = *(check_isnode(L,1));
+ while (head!=null) {
+ if (type(head)==glyph_node) {
+ register int s = subtype(head);
+ if (s>=256) {
+ t = 1;
+ subtype(head) = (s >> 8);
+ }
+ }
+ head = vlink(head);
+ }
+ lua_pushboolean(L,t);
+ lua_pushvalue(L,1);
+ return 2;
+}
+
+
+static int
+lua_nodelib_first_character (lua_State *L) {
+ /* on the stack are two nodes and a direction */
+ halfword h, savetail = null, t = null;
+ if (lua_gettop(L)<1) {
+ lua_pushnil(L);
+ lua_pushboolean(L,0);
+ return 2;
+ }
+ h = *(check_isnode(L,1));
+ if (lua_gettop(L)>1) {
+ t = *(check_isnode(L,2));
+ savetail = vlink(t);
+ vlink(t) = null;
+ }
+ while (h!=null && !is_simple_character(h)) {
+ h = vlink(h);
+ }
+ if (savetail!=null) { vlink(t) = savetail; }
+ lua_pushnumber(L,h);
+ lua_nodelib_push(L);
+ lua_pushboolean(L,(h==null? 0 : 1));
+ return 2;
+}
+
+
+/* this is too simplistic, but it helps Hans to get going */
+
+halfword
+do_ligature_n (halfword prev, halfword stop, halfword lig) {
+ vlink(lig) = vlink(stop);
+ vlink(stop) = null;
+ lig_ptr(lig) = vlink(prev);
+ vlink(prev) = lig;
+ return lig;
+}
+
+
+
+/* node.do_ligature_n(node prev, node last, node lig) */
+static int
+lua_nodelib_do_ligature_n (lua_State *L) {
+ halfword n, m, o, p, tmp_head;
+ n = *(check_isnode(L,1));
+ m = *(check_isnode(L,2));
+ o = *(check_isnode(L,3));
+ if (alink(n)==null || vlink(alink(n))!=n) {
+ tmp_head = new_node(temp_node,0);
+ couple_nodes(tmp_head,n);
+ p = do_ligature_n(tmp_head,m,o);
+ flush_node(tmp_head);
+ } else {
+ p = do_ligature_n(alink(n),m,o);
+ }
+ lua_pushnumber(L,p);
+ lua_nodelib_push(L);
+ return 1;
+}
+
+extern halfword list_node_mem_usage (void) ;
+
+static int
+lua_nodelib_usedlist (lua_State *L) {
+ lua_pushnumber(L,list_node_mem_usage());
+ lua_nodelib_push(L);
+ return 1;
+}
+
+
+static const struct luaL_reg nodelib_f [] = {
+ {"id", lua_nodelib_id},
+ {"subtype", lua_nodelib_subtype},
+ {"type", lua_nodelib_type},
+ {"new", lua_nodelib_new},
+ {"length", lua_nodelib_length},
+ {"count", lua_nodelib_count},
+ {"traverse", lua_nodelib_traverse},
+ {"traverse_id", lua_nodelib_traverse_filtered},
+ {"slide", lua_nodelib_tail},
+ {"types", lua_nodelib_types},
+ {"whatsits", lua_nodelib_whatsits},
+ {"fields", lua_nodelib_fields},
+ {"has_field", lua_nodelib_has_field},
+ {"free", lua_nodelib_free},
+ {"flush_list", lua_nodelib_flush_list},
+ {"remove", lua_nodelib_remove},
+ {"insert_before", lua_nodelib_insert_before},
+ {"insert_after", lua_nodelib_insert_after},
+ {"write", lua_nodelib_append},
+ {"last_node", lua_nodelib_last_node},
+ {"copy", lua_nodelib_copy},
+ {"copy_list", lua_nodelib_copy_list},
+ {"hpack", lua_nodelib_hpack},
+ {"has_attribute", lua_nodelib_has_attribute},
+ {"set_attribute", lua_nodelib_set_attribute},
+ {"unset_attribute", lua_nodelib_unset_attribute},
+ {"do_ligature_n", lua_nodelib_do_ligature_n},
+ {"ligaturing", font_tex_ligaturing},
+ {"kerning", font_tex_kerning},
+ {"first_character", lua_nodelib_first_character},
+ {"usedlist", lua_nodelib_usedlist},
+ {"protect_glyphs", lua_nodelib_protect_glyphs},
+ {"unprotect_glyphs", lua_nodelib_unprotect_glyphs},
+ {NULL, NULL} /* sentinel */
+};
+
+static const struct luaL_reg nodelib_m [] = {
+ {"__index", lua_nodelib_getfield},
+ {"__newindex", lua_nodelib_setfield},
+ {"__tostring", lua_nodelib_print},
+ {"__eq", lua_nodelib_equal},
+ {NULL, NULL} /* sentinel */
+};
+
+
+
+int
+luaopen_node (lua_State *L)
+{
+ luaL_newmetatable(L,NODE_METATABLE);
+ luaL_register(L, NULL, nodelib_m);
+ luaL_register(L, "node", nodelib_f);
+ init_luaS_index(luatex_node);
+ initialize_luaS_indexes(L);
+ return 1;
+}
+
+void
+nodelist_to_lua (lua_State *L, int n) {
+ lua_pushnumber(L,n);
+ lua_nodelib_push(L);
+}
+
+int
+nodelist_from_lua (lua_State *L) {
+ halfword *n;
+ if (lua_isnil(L,-1))
+ return null;
+ n = check_isnode(L,-1);
+ return *n;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/lua/loslibext.c b/Build/source/texk/web2c/luatexdir/lua/loslibext.c
new file mode 100644
index 00000000000..003b031f627
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/loslibext.c
@@ -0,0 +1,627 @@
+/* $Id: loslibext.c 1066 2008-02-23 10:52:51Z taco $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+
+/* An attempt to figure out the basic platform, does not
+ care about niceties like version numbers yet,
+ and ignores platforms where luatex is unlikely to
+ successfully compile without major prorting effort
+ (amiga|mac|os2|vms) */
+
+#if defined(_WIN32) || defined(WIN32) || defined(__NT__)
+#define OS_PLATTYPE "windows"
+#define OS_PLATNAME "windows"
+#elif defined(__GO32__) || defined(__DJGPP__) || defined(__DOS__)
+#define OS_PLATTYPE "msdos"
+#define OS_PLATNAME "msdos"
+#else /* assume everything else is unix-y */
+#define OS_PLATTYPE "unix"
+/* this is just a first guess */
+#if defined(__BSD__)
+ #define OS_PLATNAME "bsd"
+#elif defined(__SYSV__)
+ #define OS_PLATNAME "sysv"
+#else
+ #define OS_PLATNAME "generic"
+#endif
+/* attempt to be more precise */
+#if defined(__LINUX__) || defined (__linux)
+ #undef OS_PLATNAME
+ #define OS_PLATNAME "linux"
+#elif defined(__FREEBSD__) || defined(__FreeBSD)
+ #undef OS_PLATNAME
+ #define OS_PLATNAME "freebsd"
+#elif defined(__OPENBSD__) || defined(__OpenBSD)
+ #undef OS_PLATNAME
+ #define OS_PLATNAME "openbsd"
+#elif defined(__SOLARIS__)
+ #undef OS_PLATNAME
+ #define OS_PLATNAME "solaris"
+#elif defined(__SUNOS__) || defined(__SUN__) || defined(sun)
+ #undef OS_PLATNAME
+ #define OS_PLATNAME "sunos"
+#elif defined(HPUX) || defined(__hpux)
+ #undef OS_PLATNAME
+ #define OS_PLATNAME "hpux"
+#elif defined(__sgi)
+ #undef OS_PLATNAME
+ #define OS_PLATNAME "irix"
+#elif defined(__MACH__) && defined(__APPLE__)
+ #undef OS_PLATNAME
+ #define OS_PLATNAME "macosx"
+#endif
+#endif
+
+
+
+
+
+/* there could be more platforms that don't have these two,
+ * but win32 and sunos are for sure.
+ * gettimeofday() for win32 is using an alternative definition
+ */
+
+#if (! defined(WIN32)) && (! defined(__SUNOS__))
+#include <sys/time.h> /* gettimeofday() */
+#include <sys/times.h> /* times() */
+#include <sys/wait.h>
+#endif
+
+/* set this to one for spawn instead of exec on windows */
+
+#define DONT_REALLY_EXIT 1
+
+#ifdef WIN32
+#include <process.h>
+#define spawn_command(a,b,c) _spawnvpe(_P_WAIT,(const char *)a,(const char* const*)b,(const char* const*)c)
+#if DONT_REALLY_EXIT
+#define exec_command(a,b,c) exit(spawn_command((a),(b),(c)))
+#else
+#define exec_command(a,b,c) _execvpe((const char *)a,(const char* const*)b,(const char* const*)c)
+#endif
+#else
+#include <unistd.h>
+#define DEFAULT_PATH "/bin:/usr/bin:."
+
+static int
+exec_command(const char *file, char *const *argv, char *const *envp)
+{
+ char path[PATH_MAX];
+ const char *searchpath, *esp;
+ size_t prefixlen, filelen, totallen;
+
+ if (strchr(file, '/')) /* Specific path */
+ return execve(file, argv, envp);
+
+ filelen = strlen(file);
+
+ searchpath = getenv("PATH");
+ if (!searchpath)
+ searchpath = DEFAULT_PATH;
+
+ errno = ENOENT; /* Default errno, if execve() doesn't change it */
+
+ do {
+ esp = strchr(searchpath, ':');
+ if (esp)
+ prefixlen = esp - searchpath;
+ else
+ prefixlen = strlen(searchpath);
+
+ if (prefixlen == 0 || searchpath[prefixlen - 1] == '/') {
+ totallen = prefixlen + filelen;
+ if (totallen >= PATH_MAX)
+ continue;
+ memcpy(path, searchpath, prefixlen);
+ memcpy(path + prefixlen, file, filelen);
+ } else {
+ totallen = prefixlen + filelen + 1;
+ if (totallen >= PATH_MAX)
+ continue;
+ memcpy(path, searchpath, prefixlen);
+ path[prefixlen] = '/';
+ memcpy(path + prefixlen + 1, file, filelen);
+ }
+ path[totallen] = '\0';
+
+ execve(path, argv, envp);
+ if (errno == E2BIG || errno == ENOEXEC ||
+ errno == ENOMEM || errno == ETXTBSY)
+ break; /* Report this as an error, no more search */
+
+ searchpath = esp + 1;
+ } while (esp);
+
+ return -1;
+}
+
+/*
+ It is not possible to mimic |spawnve()| completely. The main problem is
+ that the |fork|--|waitpid| combination cannot really do identical error
+ reporting to the parent process, because it has to pass all the possible
+ error conditions as well as the actual process return status through a
+ single 8-bit value.
+
+ The current implementation tries to give back meaningful results for |execve()|
+ errors in the child, for the cases that could also be returned by |spawnve()|,
+ and for |ETXTBSY|, because that can be triggered by our path searching routine.
+
+ This implementation does not differentiate abnormal status conditions reported
+ by |waitpid()|, but will simply return a single error indication value.
+
+ For all this, hyjacking a bunch of numbers in the range 1...255 is needed.
+ The chance of collisions is hopefully diminished by using a rather random
+ range in the 8-bit section.
+*/
+
+#define INVALID_RET_E2BIG 143
+#define INVALID_RET_ENOENT 144
+#define INVALID_RET_ENOEXEC 145
+#define INVALID_RET_ENOMEM 146
+#define INVALID_RET_ETXTBSY 147
+#define INVALID_RET_UNKNOWN 148
+#define INVALID_RET_INTR 149
+
+static int
+spawn_command(const char *file, char *const *argv, char *const *envp)
+{
+ pid_t pid, wait_pid;
+ int status;
+ pid = fork();
+ if (pid<0) {
+ return -1; /* fork failed */
+ }
+ if (pid>0) { /* parent */
+ status = 0;
+ wait_pid = waitpid (pid, &status,0);
+ if (wait_pid == pid) {
+ if (WIFEXITED(status))
+ return WEXITSTATUS(status);
+ else
+ return INVALID_RET_INTR;
+ } else {
+ return -1; /* some waitpid error */
+ }
+ } else {
+ int f;
+ /* somewhat random upper limit. ignore errors on purpose */
+ for (f = 0; f<256; f++)
+ (void)fsync(f);
+
+ if (exec_command(file, argv, envp)) {
+ /* let's hope no-one uses these values */
+ switch (errno) {
+ case E2BIG: exit(INVALID_RET_E2BIG);
+ case ETXTBSY: exit(INVALID_RET_ETXTBSY);
+ case ENOENT: exit(INVALID_RET_ENOENT);
+ case ENOEXEC: exit(INVALID_RET_ENOEXEC);
+ case ENOMEM: exit(INVALID_RET_ENOMEM);
+ default: exit(INVALID_RET_UNKNOWN);
+ }
+ return -1;
+ }
+ }
+}
+
+#endif
+
+extern char **environ;
+
+static char **
+do_split_command(char *maincmd)
+{
+ char *piece, *start_piece;
+ char *cmd;
+ char **cmdline = NULL;
+ unsigned int i, j;
+ int ret = 0;
+ int in_string = 0;
+ int quoted = 0;
+ if (strlen(maincmd) == 0)
+ return NULL;
+ /* allocate the array of options first. it will probably be
+ be a little bit too big, but better too much than to little */
+ j=2;
+ for (i = 0; i < strlen(maincmd); i++) { if (maincmd[i]==' ') j++; }
+ cmdline = malloc(sizeof(char *) * j);
+ for (i = 0; i < j; i++) { cmdline[i] = NULL; }
+ cmd = maincmd;
+ i = 0;
+ while (cmd[i] == ' ') i++; /* skip leading spaces */
+ start_piece = malloc(strlen(cmd)+1); /* a buffer */
+ piece = start_piece;
+ for (; i <= strlen(maincmd); i++) {
+ if (cmd[i]=='\\' &&
+ (cmd[i+1] == '\\' || cmd[i+1] == '\'' || cmd[i+1] == '"')) {
+ quoted =1;
+ continue;
+ }
+ if (in_string && cmd[i] == in_string && !quoted) {
+ in_string = 0;
+ continue;
+ }
+ if ((cmd[i] == '"' || cmd[i] == '\'')&& !quoted) {
+ in_string = cmd[i];
+ continue;
+ }
+ if ((in_string==0 && cmd[i] == ' ') || cmd[i]==0) {
+ *piece = 0;
+ cmdline[ret++] = xstrdup(start_piece);
+ piece = start_piece;
+ while (i < strlen(maincmd) && cmd[(i + 1)] == ' ')
+ i++;
+ continue;
+ }
+ *piece++ = cmd[i];
+ quoted=0;
+ }
+ xfree(start_piece);
+ return cmdline;
+}
+
+static char **
+do_flatten_command(lua_State *L, char **runcmd) {
+ unsigned int i, j ;
+ char *s;
+ char **cmdline = NULL;
+ *runcmd = NULL;
+
+ for (j = 1;;j++) {
+ lua_rawgeti(L,-1,j);
+ if (lua_isnil(L,-1)) {
+ lua_pop(L,1);
+ break;
+ }
+ lua_pop(L,1);
+ }
+ if (j == 1)
+ return NULL;
+ cmdline = malloc(sizeof(char *) * (j+1));
+ for (i = 1; i <= j; i++) {
+ cmdline[i] = NULL;
+ lua_rawgeti(L,-1,i);
+ if (lua_isnil(L,-1) || (s=(char *)lua_tostring(L,-1))==NULL) {
+ lua_pop(L,1);
+ if (i==1) {
+ xfree(cmdline) ;
+ return NULL;
+ } else {
+ break;
+ }
+ } else {
+ lua_pop(L,1);
+ cmdline[(i-1)] = xstrdup(s);
+ }
+ }
+ cmdline[i] = NULL;
+
+ lua_rawgeti(L,-1,0);
+ if (lua_isnil(L,-1) || (s=(char *)lua_tostring(L,-1))==NULL) {
+ *runcmd = cmdline[0];
+ } else {
+ *runcmd = xstrdup(s);
+ }
+ lua_pop(L,1);
+
+ return cmdline;
+}
+
+
+static int os_exec (lua_State *L) {
+ char * maincmd, * runcmd;
+ char ** cmdline = NULL;
+
+ if (lua_gettop(L)!=1) {
+ lua_pushnil(L);
+ lua_pushliteral(L,"invalid arguments passed");
+ return 2;
+ }
+ if (lua_type(L,1)==LUA_TSTRING) {
+ maincmd = (char *)lua_tostring(L, 1);
+ cmdline = do_split_command(maincmd);
+ runcmd = cmdline[0];
+ } else if (lua_type(L,1)==LUA_TTABLE) {
+ cmdline = do_flatten_command(L, & runcmd);
+ }
+ if (cmdline!=NULL) {
+#if defined(WIN32) && DONT_REALLY_EXIT
+ exec_command(runcmd, cmdline, environ);
+#else
+ if (exec_command(runcmd, cmdline, environ)==-1) {
+ lua_pushnil(L);
+ lua_pushfstring(L,"%s: %s",runcmd, strerror(errno));
+ lua_pushnumber(L, errno);
+ return 3;
+ }
+#endif
+ }
+ lua_pushnil(L);
+ lua_pushliteral(L,"invalid command line passed");
+ return 2;
+}
+
+#define do_error_return(A,B) do { \
+ lua_pushnil(L); \
+ lua_pushfstring(L,"%s: %s",runcmd,(A)); \
+ lua_pushnumber(L, B); \
+ return 3; \
+ } while (0)
+
+static int os_spawn (lua_State *L) {
+ char * maincmd, * runcmd;
+ char ** cmdline = NULL;
+ int i;
+
+ if (lua_gettop(L)!=1) {
+ lua_pushnil(L);
+ lua_pushliteral(L,"invalid arguments passed");
+ return 2;
+ }
+ if (lua_type(L,1)==LUA_TSTRING) {
+ maincmd = (char *)lua_tostring(L, 1);
+ cmdline = do_split_command(maincmd);
+ runcmd = cmdline[0];
+ } else if (lua_type(L,1)==LUA_TTABLE) {
+ cmdline = do_flatten_command(L, &runcmd);
+ }
+ if (cmdline!=NULL) {
+ i = spawn_command(runcmd, cmdline, environ);
+ if (i==0) {
+ lua_pushnumber(L, i);
+ return 1;
+ } else if (i==-1) {
+ /* this branch covers WIN32 as well as fork() and waitpid() errors */
+ do_error_return(strerror(errno),errno);
+#ifndef WIN32
+ } else if (i==INVALID_RET_E2BIG) { do_error_return(strerror(E2BIG),i);
+ } else if (i==INVALID_RET_ENOENT) { do_error_return(strerror(ENOENT),i);
+ } else if (i==INVALID_RET_ENOEXEC) { do_error_return(strerror(ENOEXEC),i);
+ } else if (i==INVALID_RET_ENOMEM) { do_error_return(strerror(ENOMEM),i);
+ } else if (i==INVALID_RET_ETXTBSY) { do_error_return(strerror(ETXTBSY),i);
+ } else if (i==INVALID_RET_UNKNOWN) { do_error_return("execution failed",i);
+ } else if (i==INVALID_RET_INTR) { do_error_return("execution interrupted",i);
+#endif
+ } else {
+ lua_pushnumber(L, i);
+ return 1;
+ }
+ }
+ lua_pushnil(L);
+ lua_pushliteral(L,"invalid command line passed");
+ return 2;
+}
+
+/* Hans wants to set env values */
+
+static int os_setenv (lua_State *L) {
+ char *value, *key, *val;
+ key = (char *)luaL_optstring(L, 1, NULL);
+ val = (char *)luaL_optstring(L, 2, NULL);
+ if (key) {
+ if (val) {
+ value = xmalloc(strlen(key)+strlen(val)+2);
+ sprintf(value,"%s=%s",key,val);
+ if (putenv(value)) {
+ return luaL_error(L, "unable to change environment");
+ }
+ } else {
+#if defined(WIN32) || defined(__sun__)
+ value = xmalloc(strlen(key)+2);
+ sprintf(value,"%s=",key);
+ if (putenv(value)) {
+ return luaL_error(L, "unable to change environment");
+ }
+#else
+ (void)unsetenv(key);
+#endif
+ }
+ }
+ lua_pushboolean (L, 1);
+ return 1;
+}
+
+
+void find_env (lua_State *L){
+ char *envitem, *envitem_orig;
+ char *envkey;
+ char **envpointer;
+ envpointer = environ;
+ lua_getglobal(L,"os");
+ if (envpointer!=NULL && lua_istable(L,-1)) {
+ luaL_checkstack(L,2,"out of stack space");
+ lua_pushstring(L,"env");
+ lua_newtable(L);
+ while (*envpointer) {
+ /* TODO: perhaps a memory leak here */
+ luaL_checkstack(L,2,"out of stack space");
+ envitem = xstrdup(*envpointer);
+ envitem_orig = envitem;
+ envkey=envitem;
+ while (*envitem != '=') {
+ envitem++;
+ }
+ *envitem=0;
+ envitem++;
+ lua_pushstring(L,envkey);
+ lua_pushstring(L,envitem);
+ lua_rawset(L,-3);
+ envpointer++;
+ free(envitem_orig);
+ }
+ lua_rawset(L,-3);
+ }
+ lua_pop(L,1);
+}
+
+static int ex_sleep(lua_State *L)
+{
+ lua_Number interval = luaL_checknumber(L, 1);
+ lua_Number units = luaL_optnumber(L, 2, 1);
+#ifdef WIN32
+ Sleep(1e3 * interval / units);
+#else /* assumes posix or bsd */
+ usleep(1e6 * interval / units);
+#endif
+ return 0;
+}
+
+#if (! defined (WIN32)) && (! defined (__SUNOS__))
+static int os_times (lua_State *L) {
+ struct tms r;
+ (void)times(&r);
+ lua_newtable(L);
+ lua_pushnumber(L, ((lua_Number)(r.tms_utime))/(lua_Number)sysconf(_SC_CLK_TCK));
+ lua_setfield(L,-2,"utime");
+ lua_pushnumber(L, ((lua_Number)(r.tms_stime))/(lua_Number)sysconf(_SC_CLK_TCK));
+ lua_setfield(L,-2,"stime");
+ lua_pushnumber(L, ((lua_Number)(r.tms_cutime))/(lua_Number)sysconf(_SC_CLK_TCK));
+ lua_setfield(L,-2,"cutime");
+ lua_pushnumber(L, ((lua_Number)(r.tms_cstime))/(lua_Number)sysconf(_SC_CLK_TCK));
+ lua_setfield(L,-2,"cstime");
+ return 1;
+}
+#endif
+
+#if ! defined (__SUNOS__)
+
+#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
+#else
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
+#endif
+
+static int os_gettimeofday (lua_State *L) {
+ double v;
+#ifndef WIN32
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ v = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
+#else
+ FILETIME ft;
+ unsigned __int64 tmpres = 0;
+
+ GetSystemTimeAsFileTime(&ft);
+
+ tmpres |= ft.dwHighDateTime;
+ tmpres <<= 32;
+ tmpres |= ft.dwLowDateTime;
+ tmpres /= 10;
+ tmpres -= DELTA_EPOCH_IN_MICROSECS; /*converting file time to unix epoch*/
+ v = (double)tmpres / 1000000.0;
+#endif
+ lua_pushnumber(L, v);
+ return 1;
+}
+#endif
+
+static const char repl[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+static int dirs_made = 0;
+
+#define MAXTRIES 36*36*36
+
+char *
+do_mkdtemp (char *tmpl)
+{
+ int count ;
+ int value ;
+ char *xes = &tmpl[strlen (tmpl) - 6];
+ /* this is not really all that random, but it will do */
+ if (dirs_made==0) {
+ srand(time(NULL));
+ }
+ value = rand();
+ for (count = 0; count < MAXTRIES; value += 8413, ++count) {
+ int v = value;
+ xes[0] = repl[v % 36]; v /= 36;
+ xes[1] = repl[v % 36]; v /= 36;
+ xes[2] = repl[v % 36]; v /= 36;
+ xes[3] = repl[v % 36]; v /= 36;
+ xes[4] = repl[v % 36]; v /= 36;
+ xes[5] = repl[v % 36];
+ if (mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR) >= 0) {
+ dirs_made++;
+ return tmpl;
+ } else if (errno != EEXIST) {
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+static int os_tmpdir (lua_State *L) {
+ char *s, *tempdir;
+ char *tmp = (char *)luaL_optstring(L, 1, "luatex.XXXXXX");
+ if (tmp==NULL ||
+ strlen(tmp)<6 ||
+ (strcmp(tmp+strlen(tmp)-6,"XXXXXX") != 0)) {
+ lua_pushnil(L);
+ lua_pushstring(L, "Invalid argument to os.tmpdir()");
+ return 2;
+ } else {
+ tempdir = xstrdup(tmp);
+ }
+#ifdef HAVE_MKDTEMP
+ s = mkdtemp(tempdir);
+#else
+ s = do_mkdtemp(tempdir);
+#endif
+ if (s==NULL) {
+ int en = errno; /* calls to Lua API may change this value */
+ lua_pushnil(L);
+ lua_pushfstring(L, "%s", strerror(en));
+ return 2;
+ } else {
+ lua_pushstring(L,s);
+ return 1;
+ }
+}
+
+
+void
+open_oslibext (lua_State *L, int safer_option) {
+
+ find_env(L);
+
+ lua_getglobal(L,"os");
+ lua_pushcfunction(L, ex_sleep);
+ lua_setfield(L,-2,"sleep");
+ lua_getglobal(L,"os");
+ lua_pushliteral(L, OS_PLATTYPE);
+ lua_setfield(L,-2,"type");
+ lua_getglobal(L,"os");
+ lua_pushliteral(L, OS_PLATNAME);
+ lua_setfield(L,-2,"name");
+#if (! defined (WIN32)) && (! defined (__SUNOS__))
+ lua_getglobal(L,"os");
+ lua_pushcfunction(L, os_times);
+ lua_setfield(L,-2,"times");
+#endif
+#if ! defined (__SUNOS__)
+ lua_getglobal(L,"os");
+ lua_pushcfunction(L, os_gettimeofday);
+ lua_setfield(L,-2,"gettimeofday");
+#endif
+ if (!safer_option) {
+ lua_getglobal(L,"os");
+ lua_pushcfunction(L, os_setenv);
+ lua_setfield(L,-2,"setenv");
+ lua_getglobal(L,"os");
+ lua_pushcfunction(L, os_exec);
+ lua_setfield(L,-2,"exec");
+ lua_getglobal(L,"os");
+ lua_pushcfunction(L, os_spawn);
+ lua_setfield(L,-2,"spawn");
+ lua_getglobal(L,"os");
+ lua_pushcfunction(L, os_tmpdir);
+ lua_setfield(L,-2,"tmpdir");
+
+ }
+
+
+}
diff --git a/Build/source/texk/web2c/luatexdir/lua/lpdflib.c b/Build/source/texk/web2c/luatexdir/lua/lpdflib.c
new file mode 100644
index 00000000000..9cf847c84c8
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/lpdflib.c
@@ -0,0 +1,127 @@
+/* $Id: lpdflib.c 1013 2008-02-14 00:09:02Z oneiros $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+
+static int
+findcurv (lua_State *L) {
+ int j;
+ j = get_cur_v();
+ lua_pushnumber(L, j);
+ return 1;
+}
+
+static int
+findcurh (lua_State *L) {
+ int j;
+ j = get_cur_h();
+ lua_pushnumber(L, j);
+ return 1;
+}
+
+
+typedef enum { set_origin, direct_page, direct_always } pdf_lit_mode;
+
+int luapdfprint(lua_State * L)
+{
+ int n;
+ unsigned i, len;
+ const char *outputstr, *st;
+ pdf_lit_mode literal_mode;
+ n = lua_gettop(L);
+ if (!lua_isstring(L, -1)) {
+ lua_pushstring(L, "no string to print");
+ lua_error(L);
+ }
+ literal_mode = set_origin;
+ if (n == 2) {
+ if (!lua_isstring(L, -2)) {
+ lua_pushstring(L, "invalid argument for print literal mode");
+ lua_error(L);
+ } else {
+ outputstr = (char *) lua_tostring(L, -2);
+ if (strcmp(outputstr, "direct") == 0)
+ literal_mode = direct_always;
+ else if (strcmp(outputstr, "page") == 0)
+ literal_mode = direct_page;
+ else {
+ lua_pushstring(L,
+ "invalid argument for print literal mode");
+ lua_error(L);
+ }
+ }
+ } else {
+ if (n != 1) {
+ lua_pushstring(L, "invalid number of arguments");
+ lua_error(L);
+ }
+ }
+ switch (literal_mode) {
+ case (set_origin):
+ pdf_end_text();
+ pdf_set_origin(cur_h, cur_v);
+ break;
+ case (direct_page):
+ pdf_end_text();
+ break;
+ case (direct_always):
+ pdf_end_string_nl();
+ break;
+ default:
+ assert(0);
+ }
+ st = lua_tolstring(L, n,&len);
+ for (i = 0; i < len; i++) {
+ if (i%16 == 0)
+ pdfroom(16);
+ pdf_buf[pdf_ptr++] = st[i];
+ }
+ return 0;
+}
+
+static int
+getpdf (lua_State *L) {
+ char *st;
+ if (lua_isstring(L,2)) {
+ st = (char *)lua_tostring(L,2);
+ if (st && *st) {
+ if (*st == 'h')
+ return findcurh(L);
+ else if (*st == 'v')
+ return findcurv(L);
+ }
+ }
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+setpdf (lua_State *L) {
+ return (L==NULL ? 0 : 0); /* for -Wall */
+}
+
+static const struct luaL_reg pdflib[] = {
+ {"print", luapdfprint},
+ {NULL, NULL} /* sentinel */
+};
+
+
+int
+luaopen_pdf (lua_State *L) {
+ luaL_register(L, "pdf", pdflib);
+ /* build meta table */
+ luaL_newmetatable(L,"pdf_meta");
+ lua_pushstring(L, "__index");
+ lua_pushcfunction(L, getpdf);
+ /* do these later, NYI */
+ if (0) {
+ lua_settable(L, -3);
+ lua_pushstring(L, "__newindex");
+ lua_pushcfunction(L, setpdf);
+ }
+ lua_settable(L, -3);
+ lua_setmetatable(L,-2); /* meta to itself */
+ return 1;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/lua/lstatslib.c b/Build/source/texk/web2c/luatexdir/lua/lstatslib.c
new file mode 100644
index 00000000000..025e851e775
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/lstatslib.c
@@ -0,0 +1,211 @@
+/* $Id: lstatslib.c 1013 2008-02-14 00:09:02Z oneiros $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+typedef struct statistic {
+ const char *name;
+ char type;
+ void *value;
+} statistic ;
+
+extern char *ptexbanner;
+/* extern string getcurrentfilenamestring; */
+
+typedef char * (*charfunc)(void);
+typedef integer (*intfunc)(void);
+
+char *getbanner (void) {
+ return ptexbanner;
+}
+
+/* hack, I really should implement the makecstring */
+char *getfilename (void) {
+ integer t;
+ t = get_current_name();
+ if (t>(1<<21))
+ return makecstring(t);
+ else
+ return xstrdup ("");
+}
+
+char *getlasterror (void) {
+ return makecstring(last_error);
+}
+
+
+extern int luabytecode_max;
+extern int luabytecode_bytes;
+extern int luastate_max;
+extern int luastate_bytes;
+
+static struct statistic stats[] = {
+ { "pdf_gone", 'g', &pdf_gone },
+ { "pdf_ptr", 'g', &pdf_ptr },
+ { "dvi_gone", 'g', &dvi_offset },
+ { "dvi_ptr", 'g', &dvi_ptr },
+ { "total_pages", 'g', &total_pages },
+ { "output_file_name", 's', &output_file_name },
+ { "log_name", 's', &texmf_log_name }, /* weird */
+ { "banner", 'S', &getbanner },
+ { "pdftex_banner", 's', &pdftex_banner },
+ /*
+ * mem stat
+ */
+ { "var_used", 'g', &var_used },
+ { "dyn_used", 'g', &dyn_used },
+ /*
+ * traditional tex stats
+ */
+ { "str_ptr", 'g', &str_ptr },
+ { "init_str_ptr", 'g', &init_str_ptr },
+ { "max_strings", 'g', &max_strings },
+ { "pool_ptr", 'g', &pool_ptr },
+ { "init_pool_ptr", 'g', &init_pool_ptr },
+ { "pool_size", 'g', &pool_size },
+ { "var_mem_max", 'g', &var_mem_max },
+ { "node_mem_usage", 'S', &sprint_node_mem_usage },
+ { "fix_mem_max", 'g', &fix_mem_max },
+ { "fix_mem_min", 'g', &fix_mem_min },
+ { "fix_mem_end", 'g', &fix_mem_end },
+ { "cs_count", 'g', &cs_count },
+ { "hash_size", 'G', &get_hash_size },
+ { "hash_extra", 'g', &hash_extra },
+ { "font_ptr", 'G', &max_font_id },
+ { "max_in_stack", 'g', &max_in_stack },
+ { "max_nest_stack", 'g', &max_nest_stack },
+ { "max_param_stack", 'g', &max_param_stack },
+ { "max_buf_stack", 'g', &max_buf_stack },
+ { "max_save_stack", 'g', &max_save_stack },
+ { "stack_size", 'g', &stack_size },
+ { "nest_size", 'g', &nest_size },
+ { "param_size", 'g', &param_size },
+ { "buf_size", 'g', &buf_size },
+ { "save_size", 'g', &save_size },
+ /* pdf stats */
+ { "obj_ptr", 'g', &obj_ptr },
+ { "obj_tab_size", 'g', &obj_tab_size },
+ { "pdf_os_cntr", 'g', &pdf_os_cntr },
+ { "pdf_os_objidx", 'g', &pdf_os_objidx },
+ { "pdf_dest_names_ptr", 'g', &pdf_dest_names_ptr },
+ { "dest_names_size", 'g', &dest_names_size },
+ { "pdf_mem_ptr", 'g', &pdf_mem_ptr },
+ { "pdf_mem_size", 'g', &pdf_mem_size },
+
+ { "largest_used_mark", 'g', &biggest_used_mark },
+
+ { "filename", 'S', &getfilename },
+ { "inputid", 'G', &get_current_name },
+ { "linenumber", 'g', &line },
+ { "lasterrorstring", 'S', &getlasterror },
+
+ { "luabytecodes", 'g', &luabytecode_max },
+ { "luabytecode_bytes", 'g', &luabytecode_bytes },
+ { "luastates", 'g', &luastate_max },
+ { "luastate_bytes", 'g', &luastate_bytes },
+
+ { "output_active", 'b', &output_active },
+
+ { NULL, 0 , 0 } };
+
+
+static int stats_name_to_id (char *name) {
+ int i;
+ for (i=0; stats[i].name!=NULL; i++) {
+ if (strcmp(stats[i].name, name) == 0)
+ return i;
+ }
+ return 0;
+}
+
+static int do_getstat (lua_State *L,int i) {
+ int t;
+ char *st;
+ charfunc f;
+ intfunc g;
+ int str;
+ t = stats[i].type;
+ switch(t) {
+ case 'S':
+ f = stats[i].value;
+ st = f();
+ lua_pushstring(L,st);
+ break;
+ case 's':
+ str = *(integer *)(stats[i].value);
+ if (str) {
+ lua_pushstring(L,makecstring(str));
+ } else {
+ lua_pushnil(L);
+ }
+ break;
+ case 'G':
+ g = stats[i].value;
+ lua_pushnumber(L,g());
+ break;
+ case 'g':
+ lua_pushnumber(L,*(integer *)(stats[i].value));
+ break;
+ case 'B':
+ g = stats[i].value;
+ lua_pushboolean(L,g());
+ break;
+ case 'b':
+ lua_pushboolean(L,*(integer *)(stats[i].value));
+ break;
+ default:
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int getstats (lua_State *L) {
+ char *st;
+ int i;
+ if (lua_isstring(L,-1)) {
+ st = (char *)lua_tostring(L,-1);
+ i = stats_name_to_id(st);
+ if (i>0) {
+ return do_getstat(L,i);
+ }
+ }
+ return 0;
+}
+
+static int setstats (lua_State *L) {
+ return 0;
+}
+
+static int statslist (lua_State *L) {
+ int i;
+ luaL_checkstack(L,1,"out of stack space");
+ lua_newtable(L);
+ for (i=0; stats[i].name!=NULL; i++) {
+ luaL_checkstack(L,2,"out of stack space");
+ lua_pushstring(L,stats[i].name);
+ do_getstat(L,i);
+ lua_rawset(L,-3);
+ }
+ return 1;
+}
+
+
+
+static const struct luaL_reg statslib [] = {
+ {"list",statslist},
+ {NULL, NULL} /* sentinel */
+};
+
+int luaopen_stats (lua_State *L)
+{
+ luaL_register(L, "status", statslib);
+ luaL_newmetatable(L,"stats_meta");
+ lua_pushstring(L, "__index");
+ lua_pushcfunction(L, getstats);
+ lua_settable(L, -3);
+ lua_pushstring(L, "__newindex");
+ lua_pushcfunction(L, setstats);
+ lua_settable(L, -3);
+ lua_setmetatable(L,-2); /* meta to itself */
+ return 1;
+}
diff --git a/Build/source/texk/web2c/luatexdir/lua/ltexiolib.c b/Build/source/texk/web2c/luatexdir/lua/ltexiolib.c
new file mode 100644
index 00000000000..a61409b2943
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/ltexiolib.c
@@ -0,0 +1,117 @@
+/* $Id: ltexiolib.c 1013 2008-02-14 00:09:02Z oneiros $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+typedef void (*texio_printer) (strnumber s);
+
+static char *loggable_info = NULL;
+
+static int
+do_texio_print (lua_State *L, texio_printer printfunction) {
+ strnumber texs,u;
+ char *s;
+ char save_selector;
+ int n,i;
+ size_t k;
+ u = 0;
+ n = lua_gettop(L);
+ if (n==0 || !lua_isstring(L, -1)) {
+ lua_pushstring(L, "no string to print");
+ lua_error(L);
+ }
+ save_selector = selector;
+ i = 1;
+ if (n>1) {
+ s=(char *)lua_tostring(L, 1);
+ if (strcmp(s,"log") == 0) { i++; selector = log_only; }
+ else if (strcmp(s,"term") == 0) { i++; selector = term_only; }
+ else if (strcmp(s,"term and log") == 0) { i++; selector = term_and_log; }
+ }
+ if (selector!=log_only && selector!=term_only && selector != term_and_log) {
+ normalize_selector(); /* sets selector */
+ }
+ /* just in case there is a string in progress */
+ if (str_start[str_ptr-0x200000]<pool_ptr)
+ u=make_string();
+ for (;i<=n;i++) {
+ s = (char *)lua_tolstring(L, i, &k);
+ texs = maketexlstring(s,k);
+ printfunction(texs);
+ flush_str(texs);
+ }
+ selector = save_selector;
+ if (u!=0) str_ptr--;
+ return 0;
+}
+
+static void
+do_texio_ini_print (lua_State *L, char *extra) {
+ char *s;
+ int i,n,l;
+ n = lua_gettop(L);
+ i = 1;
+ l = 3;
+ if (n>1) {
+ s=(char *)lua_tostring(L, 1);
+ if (strcmp(s,"log") == 0) { i++; l = 1; }
+ else if (strcmp(s,"term") == 0) { i++; l = 2; }
+ else if (strcmp(s,"term and log") == 0) { i++; l = 3; }
+ }
+ for (;i<=n;i++) {
+ if(lua_isstring(L, i)) {
+ s = (char *)lua_tostring(L, i);
+ if (l==2||l==3)
+ fprintf(stdout,"%s%s", extra, s);
+ if (l==1||l==3) {
+ if (loggable_info==NULL) {
+ loggable_info = strdup(s);
+ } else {
+ char *v = concat3 (loggable_info,extra,s);
+ free(loggable_info);
+ loggable_info = v;
+ }
+ }
+ }
+ }
+}
+
+static int
+texio_print (lua_State *L) {
+ if (ready_already!=314159 || pool_ptr==0 || job_name==0) {
+ do_texio_ini_print(L,"");
+ return 0;
+ }
+ return do_texio_print(L,zprint);
+}
+
+static int
+texio_printnl (lua_State *L) {
+ if (ready_already!=314159 || pool_ptr==0 || job_name==0) {
+ do_texio_ini_print(L,"\n");
+ return 0;
+ }
+ return do_texio_print(L,zprint_nl);
+}
+
+/* at the point this function is called, the selector is log_only */
+void flush_loggable_info (void) {
+ if (loggable_info!=NULL) {
+ fprintf(log_file,"%s\n",loggable_info);
+ free(loggable_info);
+ loggable_info=NULL;
+ }
+}
+
+
+static const struct luaL_reg texiolib [] = {
+ {"write", texio_print},
+ {"write_nl", texio_printnl},
+ {NULL, NULL} /* sentinel */
+};
+
+int
+luaopen_texio (lua_State *L) {
+ luaL_register(L,"texio",texiolib);
+ return 1;
+}
diff --git a/Build/source/texk/web2c/luatexdir/lua/ltexlib.c b/Build/source/texk/web2c/luatexdir/lua/ltexlib.c
new file mode 100644
index 00000000000..f2258010136
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/ltexlib.c
@@ -0,0 +1,820 @@
+/* $Id: ltexlib.c 1087 2008-03-07 23:52:35Z hhenkel $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+#include "nodes.h"
+
+typedef struct {
+ char *text;
+ unsigned int tsize;
+ void *next;
+ unsigned char partial;
+ int cattable;
+} rope;
+
+typedef struct {
+ rope *head;
+ rope *tail;
+ char complete; /* currently still writing ? */
+} spindle;
+
+#define PARTIAL_LINE 1
+#define FULL_LINE 0
+
+#define NO_CAT_TABLE -2
+#define DEFAULT_CAT_TABLE -1
+
+#define write_spindle spindles[spindle_index]
+#define read_spindle spindles[(spindle_index-1)]
+
+static int spindle_size = 0;
+static spindle *spindles = NULL;
+static int spindle_index = 0;
+
+
+static int
+do_luacprint (lua_State * L, int partial, int deftable) {
+ int i, n;
+ size_t tsize;
+ char *st, *sttemp;
+ rope *rn;
+ int cattable = deftable;
+ int startstrings = 1;
+ n = lua_gettop(L);
+ if (cattable != NO_CAT_TABLE) {
+ if (lua_type(L,1)==LUA_TNUMBER && n>1) {
+ cattable = lua_tonumber(L, 1);
+ startstrings = 2;
+ }
+ }
+ for (i = startstrings; i <= n; i++) {
+ if (!lua_isstring(L, i)) {
+ lua_pushstring(L, "no string to print");
+ lua_error(L);
+ }
+ sttemp = (char *)lua_tolstring(L, i,&tsize);
+ st = xmalloc((tsize+1));
+ memcpy(st,sttemp,(tsize+1));
+ if (st) {
+ /* fprintf(stderr,"W[%d]:=%s\n",spindle_index,st);*/
+ luacstrings++;
+ rn = (rope *)xmalloc(sizeof(rope)); /* valgrind says we leak here */
+ rn->text = st;
+ rn->tsize = tsize;
+ rn->partial = partial;
+ rn->cattable = cattable;
+ rn->next = NULL;
+ if (write_spindle.head == NULL) {
+ assert(write_spindle.tail == NULL);
+ write_spindle.head = rn;
+ } else {
+ write_spindle.tail->next = rn;
+ }
+ write_spindle.tail = rn;
+ write_spindle.complete = 0;
+ }
+ }
+ return 0;
+}
+
+int luacwrite(lua_State * L) {
+ return do_luacprint(L,FULL_LINE,NO_CAT_TABLE);
+}
+
+int luacprint(lua_State * L) {
+ return do_luacprint(L,FULL_LINE,DEFAULT_CAT_TABLE);
+}
+
+int luacsprint(lua_State * L) {
+ return do_luacprint(L,PARTIAL_LINE,DEFAULT_CAT_TABLE);
+}
+
+int
+luacstring_detokenized (void) {
+ return (read_spindle.tail->cattable == NO_CAT_TABLE);
+}
+
+int
+luacstring_defaultcattable (void) {
+ return (read_spindle.tail->cattable == DEFAULT_CAT_TABLE);
+}
+
+integer
+luacstring_cattable (void) {
+ return (integer)read_spindle.tail->cattable;
+}
+
+int
+luacstring_simple (void) {
+ return (read_spindle.tail->partial == PARTIAL_LINE);
+}
+
+int
+luacstring_penultimate (void) {
+ return (read_spindle.tail->next == NULL);
+}
+
+int
+luacstring_input (void) {
+ char *st;
+ int ret;
+ rope *t = read_spindle.head;
+ if (!read_spindle.complete) {
+ read_spindle.complete =1;
+ read_spindle.tail = NULL;
+ }
+ if (t == NULL) {
+ if(read_spindle.tail != NULL)
+ free(read_spindle.tail);
+ read_spindle.tail = NULL;
+ return 0;
+ }
+ if (t->text != NULL) {
+ st = t->text;
+ /* put that thing in the buffer */
+ last = first;
+ ret = last;
+ check_buffer_overflow (last + t->tsize);
+ while (t->tsize-->0)
+ buffer[last++] = *st++;
+ if (!t->partial) {
+ while (last-1>ret && buffer[last-1] == ' ')
+ last--;
+ }
+ free (t->text);
+ t->text = NULL;
+ }
+ if (read_spindle.tail != NULL) { /* not a one-liner */
+ free(read_spindle.tail);
+ }
+ read_spindle.tail = t;
+ read_spindle.head = t->next;
+ return 1;
+}
+
+/* open for reading, and make a new one for writing */
+void
+luacstring_start (int n) {
+ spindle_index++;
+ if(spindle_size == spindle_index) { /* add a new one */
+ spindles = xrealloc(spindles,sizeof(spindle)*(spindle_size+1));
+ spindles[spindle_index].head = NULL;
+ spindles[spindle_index].tail = NULL;
+ spindles[spindle_index].complete = 0;
+ spindle_size++;
+ }
+}
+
+/* close for reading */
+
+void
+luacstring_close (int n) {
+ rope *next, *t;
+ next = read_spindle.head;
+ while (next != NULL) {
+ if (next->text != NULL)
+ free(next->text);
+ t = next;
+ next = next->next;
+ free(t);
+ }
+ read_spindle.head = NULL;
+ if(read_spindle.tail != NULL)
+ free(read_spindle.tail);
+ read_spindle.tail = NULL;
+ read_spindle.complete = 0;
+ spindle_index--;
+}
+
+/* local (static) versions */
+
+#define width_offset 1
+#define depth_offset 2
+#define height_offset 3
+
+#define check_index_range(j) \
+ if (j<0 || j > 65535) { \
+ lua_pushstring(L, "incorrect index value"); \
+ lua_error(L); }
+
+
+int dimen_to_number (lua_State *L,char *s){
+ double v;
+ char *d;
+ int j;
+ v = strtod(s,&d);
+ if (strcmp (d,"in") == 0) { j = (int)(((v*7227)/100) *65536); }
+ else if (strcmp (d,"pc") == 0) { j = (int)((v*12) *65536); }
+ else if (strcmp (d,"cm") == 0) { j = (int)(((v*7227)/254) *65536); }
+ else if (strcmp (d,"mm") == 0) { j = (int)(((v*7227)/2540) *65536); }
+ else if (strcmp (d,"bp") == 0) { j = (int)(((v*7227)/7200) *65536); }
+ else if (strcmp (d,"dd") == 0) { j = (int)(((v*1238)/1157) *65536); }
+ else if (strcmp (d,"cc") == 0) { j = (int)(((v*14856)/1157) *65536); }
+ else if (strcmp (d,"nd") == 0) { j = (int)(((v*21681)/20320)*65536); }
+ else if (strcmp (d,"nc") == 0) { j = (int)(((v*65043)/5080) *65536); }
+ else if (strcmp (d,"pt") == 0) { j = (int)(v *65536); }
+ else if (strcmp (d,"sp") == 0) { j = (int)(v); }
+ else {
+ lua_pushstring(L, "unknown dimension specifier");
+ lua_error(L);
+ j = 0;
+ }
+ return j;
+}
+
+int setdimen (lua_State *L) {
+ int i,j;
+ size_t k;
+ int cur_cs;
+ int texstr;
+ char *s;
+ i = lua_gettop(L);
+ j = 0;
+ /* find the value*/
+ if (!lua_isnumber(L,i))
+ if (lua_isstring(L,i)) {
+ j = dimen_to_number(L,(char *)lua_tostring(L,i));
+ } else {
+ lua_pushstring(L, "unsupported value type");
+ lua_error(L);
+ }
+ else
+ j = (int)lua_tonumber(L,i);
+ /* find the index*/
+ if (lua_type(L,i-1)==LUA_TSTRING) {
+ s = (char *)lua_tolstring(L,i-1, &k);
+ texstr = maketexlstring(s,k);
+ cur_cs = string_lookup(texstr);
+ flush_str(texstr);
+ k = zget_equiv(cur_cs)-get_scaled_base();
+ } else {
+ k = (int)luaL_checkinteger(L,i-1);
+ }
+ check_index_range(k);
+ if(set_tex_dimen_register(k,j)) {
+ lua_pushstring(L, "incorrect value");
+ lua_error(L);
+ }
+ return 0;
+}
+
+int getdimen (lua_State *L) {
+ int i,j;
+ size_t k;
+ int cur_cs;
+ int texstr;
+ char *s;
+ i = lua_gettop(L);
+ if (lua_type(L,i)==LUA_TSTRING) {
+ s = (char *)lua_tolstring(L,i, &k);
+ texstr = maketexlstring(s,k);
+ cur_cs = string_lookup(texstr);
+ flush_str(texstr);
+ if (is_undefined_cs(cur_cs)) {
+ lua_pushnil(L);
+ return 1;
+ }
+ k = zget_equiv(cur_cs)-get_scaled_base();
+ } else {
+ k = (int)luaL_checkinteger(L,i);
+ }
+ check_index_range(k);
+ j = get_tex_dimen_register(k);
+ lua_pushnumber(L, j);
+ return 1;
+}
+
+int setcount (lua_State *L) {
+ int i,j;
+ size_t k;
+ int cur_cs;
+ int texstr;
+ char *s;
+ i = lua_gettop(L);
+ j = (int)luaL_checkinteger(L,i);
+ if (lua_type(L,i-1)==LUA_TSTRING) {
+ s = (char *)lua_tolstring(L,i-1,&k);
+ texstr = maketexlstring(s,k);
+ cur_cs = string_lookup(texstr);
+ flush_str(texstr);
+ k = zget_equiv(cur_cs)-get_count_base();
+ } else {
+ k = (int)luaL_checkinteger(L,i-1);
+ }
+ check_index_range(k);
+ if (set_tex_count_register(k,j)) {
+ lua_pushstring(L, "incorrect value");
+ lua_error(L);
+ }
+ return 0;
+}
+
+int getcount (lua_State *L) {
+ int i, j;
+ size_t k;
+ int cur_cs;
+ int texstr;
+ char *s;
+ i = lua_gettop(L);
+ if (lua_type(L,i)==LUA_TSTRING) {
+ s = (char *)lua_tolstring(L,i, &k);
+ texstr = maketexlstring(s,k);
+ cur_cs = string_lookup(texstr);
+ flush_str(texstr);
+ if (is_undefined_cs(cur_cs)) {
+ lua_pushnil(L);
+ return 1;
+ }
+ k = zget_equiv(cur_cs)-get_count_base();
+ } else {
+ k = (int)luaL_checkinteger(L,i);
+ }
+ check_index_range(k);
+ j = get_tex_count_register(k);
+ lua_pushnumber(L, j);
+ return 1;
+}
+
+
+int setattribute (lua_State *L) {
+ int i,j;
+ size_t k;
+ int cur_cs;
+ int texstr;
+ char *s;
+ i = lua_gettop(L);
+ j = (int)luaL_checkinteger(L,i);
+ if (lua_type(L,i-1)==LUA_TSTRING) {
+ s = (char *)lua_tolstring(L,i-1, &k);
+ texstr = maketexlstring(s,k);
+ cur_cs = string_lookup(texstr);
+ flush_str(texstr);
+ k = zget_equiv(cur_cs)-get_attribute_base();
+ } else {
+ k = (int)luaL_checkinteger(L,i-1);
+ }
+ check_index_range(k);
+ if (set_tex_attribute_register(k,j)) {
+ lua_pushstring(L, "incorrect value");
+ lua_error(L);
+ }
+ return 0;
+}
+
+int getattribute (lua_State *L) {
+ int i, j;
+ size_t k;
+ int cur_cs;
+ int texstr;
+ char *s;
+ i = lua_gettop(L);
+ if (lua_type(L,i)==LUA_TSTRING) {
+ s = (char *)lua_tolstring(L,i, &k);
+ texstr = maketexlstring(s,k);
+ cur_cs = string_lookup(texstr);
+ flush_str(texstr);
+ if (is_undefined_cs(cur_cs)) {
+ lua_pushnil(L);
+ return 1;
+ }
+ k = zget_equiv(cur_cs)-get_attribute_base();
+ } else {
+ k = (int)luaL_checkinteger(L,i);
+ }
+ check_index_range(k);
+ j = get_tex_attribute_register(k);
+ lua_pushnumber(L, j);
+ return 1;
+}
+
+int settoks (lua_State *L) {
+ int i,j;
+ size_t k,len;
+ int cur_cs;
+ int texstr;
+ char *s, *st;
+ i = lua_gettop(L);
+ if (!lua_isstring(L,i)) {
+ lua_pushstring(L, "unsupported value type");
+ lua_error(L);
+ }
+ st = (char *)lua_tolstring(L,i,&len);
+
+ if (lua_type(L,i-1)==LUA_TSTRING) {
+ s = (char *)lua_tolstring(L,i-1, &k);
+ texstr = maketexlstring(s,k);
+ cur_cs = string_lookup(texstr);
+ flush_str(texstr);
+ k = zget_equiv(cur_cs)-get_toks_base();
+ } else {
+ k = (int)luaL_checkinteger(L,i-1);
+ }
+ check_index_range(k);
+ j = maketexlstring(st,len);
+
+ if(zset_tex_toks_register(k,j)) {
+ flush_str(j);
+ lua_pushstring(L, "incorrect value");
+ lua_error(L);
+ }
+ return 0;
+}
+
+int gettoks (lua_State *L) {
+ int i;
+ size_t k;
+ strnumber t;
+ int cur_cs;
+ int texstr;
+ char *s;
+ i = lua_gettop(L);
+ if (lua_type(L,i)==LUA_TSTRING) {
+ s = (char *)lua_tolstring(L,i, &k);
+ texstr = maketexlstring(s,k);
+ cur_cs = string_lookup(texstr);
+ flush_str(texstr);
+ if (is_undefined_cs(cur_cs)) {
+ lua_pushnil(L);
+ return 1;
+ }
+ k = zget_equiv(cur_cs)-get_toks_base();
+ } else {
+ k = (int)luaL_checkinteger(L,i);
+ }
+
+ check_index_range(k);
+ t = get_tex_toks_register(k);
+ lua_pushstring(L, makecstring(t));
+ flush_str(t);
+ return 1;
+}
+
+int getbox (lua_State *L) {
+ int k, t;
+ k = (int)luaL_checkinteger(L,-1);
+ check_index_range(k);
+ t = get_tex_box_register(k);
+ nodelist_to_lua(L,t);
+ return 1;
+}
+
+int setbox (lua_State *L) {
+ int i,j,k;
+
+
+
+ k = (int)luaL_checkinteger(L,-2);
+ check_index_range(k);
+ i = get_tex_box_register(k);
+ if (lua_isboolean(L,-1)) {
+ j = lua_toboolean(L,-1);
+ if (j==0)
+ j = null;
+ else
+ return 0;
+ } else {
+ j = nodelist_from_lua(L);
+ }
+ if(set_tex_box_register(k,j)) {
+ lua_pushstring(L, "incorrect value");
+ lua_error(L);
+ }
+ return 0;
+}
+
+
+static int getboxdim (lua_State *L, int whichdim) {
+ int i, j;
+ i = lua_gettop(L);
+ j = (int)lua_tonumber(L,(i));
+ lua_settop(L,(i-2)); /* table at -1 */
+ if (j<0 || j > 65535) {
+ lua_pushstring(L, "incorrect index");
+ lua_error(L);
+ }
+ switch (whichdim) {
+ case width_offset:
+ lua_pushnumber(L, get_tex_box_width(j));
+ break;
+ case height_offset:
+ lua_pushnumber(L, get_tex_box_height(j));
+ break;
+ case depth_offset:
+ lua_pushnumber(L, get_tex_box_depth(j));
+ }
+ return 1;
+}
+
+int getboxwd (lua_State *L) {
+ return getboxdim (L, width_offset);
+}
+
+int getboxht (lua_State *L) {
+ return getboxdim (L, height_offset);
+}
+
+int getboxdp (lua_State *L) {
+ return getboxdim (L, depth_offset);
+}
+
+static int setboxdim (lua_State *L, int whichdim) {
+ int i,j,k,err;
+ i = lua_gettop(L);
+ if (!lua_isnumber(L,i)) {
+ j = dimen_to_number(L,(char *)lua_tostring(L,i));
+ } else {
+ j = (int)lua_tonumber(L,i);
+ }
+ k = (int)lua_tonumber(L,(i-1));
+ lua_settop(L,(i-3)); /* table at -2 */
+ if (k<0 || k > 65535) {
+ lua_pushstring(L, "incorrect index");
+ lua_error(L);
+ }
+ err = 0;
+ switch (whichdim) {
+ case width_offset:
+ err = set_tex_box_width(k,j);
+ break;
+ case height_offset:
+ err = set_tex_box_height(k,j);
+ break;
+ case depth_offset:
+ err = set_tex_box_depth(k,j);
+ }
+ if (err) {
+ lua_pushstring(L, "not a box");
+ lua_error(L);
+ }
+ return 0;
+}
+
+int setboxwd (lua_State *L) {
+ return setboxdim(L,width_offset);
+}
+
+int setboxht (lua_State *L) {
+ return setboxdim(L,height_offset);
+}
+
+int setboxdp (lua_State *L) {
+ return setboxdim(L,depth_offset);
+}
+
+int settex (lua_State *L) {
+ char *st;
+ int i,j,texstr;
+ size_t k;
+ int cur_cs, cur_cmd;
+ j = 0;
+ i = lua_gettop(L);
+ if (lua_isstring(L,(i-1))) {
+ st = (char *)lua_tolstring(L,(i-1), &k);
+ texstr = maketexlstring(st,k);
+ if (zis_primitive(texstr)) {
+ cur_cs = string_lookup(texstr);
+ flush_str(texstr);
+ cur_cmd = zget_eq_type(cur_cs);
+ if (is_int_assign(cur_cmd)) {
+ if (lua_isnumber(L,i)) {
+ assign_internal_int(zget_equiv(cur_cs),lua_tonumber(L,i));
+ } else {
+ lua_pushstring(L, "unsupported value type");
+ lua_error(L);
+ }
+ } else if (is_dim_assign(cur_cmd)) {
+ if (!lua_isnumber(L,i))
+ if (lua_isstring(L,i)) {
+ j = dimen_to_number(L,(char *)lua_tostring(L,i));
+ } else {
+ lua_pushstring(L, "unsupported value type");
+ lua_error(L);
+ }
+ else
+ j = (int)lua_tonumber(L,i);
+ assign_internal_dim(zget_equiv(cur_cs),j);
+ } else {
+ lua_pushstring(L, "unsupported tex internal assignment");
+ lua_error(L);
+ }
+ } else {
+ lua_rawset(L,(i-2));
+ }
+ } else {
+ lua_rawset(L,(i-2));
+ }
+ return 0;
+}
+
+char *
+get_something_internal (int cur_cmd, int cur_code) {
+ int texstr;
+ char *str;
+ int save_cur_val,save_cur_val_level;
+ save_cur_val = cur_val;
+ save_cur_val_level = cur_val_level;
+ zscan_something_simple(cur_cmd,cur_code);
+ texstr = the_scanned_result();
+ cur_val = save_cur_val;
+ cur_val_level = save_cur_val_level;
+ str = makecstring(texstr);
+ flush_str(texstr);
+ return str;
+}
+
+char *
+get_convert (int cur_code) {
+ int texstr;
+ char *str = NULL;
+ texstr = the_convert_string(cur_code);
+ if (texstr) {
+ str = makecstring(texstr);
+ flush_str(texstr);
+ }
+ return str;
+}
+
+
+int
+gettex (lua_State *L) {
+ char *st;
+ int i,texstr;
+ size_t k;
+ char *str;
+ int cur_cs, cur_cmd, cur_code;
+ i = lua_gettop(L);
+ if (lua_isstring(L,i)) {
+ st = (char *)lua_tolstring(L,i, &k);
+ texstr = maketexlstring(st,k);
+ cur_cs = zprim_lookup(texstr);
+ flush_str(texstr);
+ if (cur_cs) {
+ cur_cmd = zget_prim_eq_type(cur_cs);
+ cur_code = zget_prim_equiv(cur_cs);
+ if (is_convert(cur_cmd))
+ str = get_convert(cur_code);
+ else
+ str = get_something_internal(cur_cmd,cur_code);
+ if (str)
+ lua_pushstring(L,str);
+ else
+ lua_pushnil(L);
+ return 1;
+ } else {
+ lua_rawget(L,(i-1));
+ return 1;
+ }
+ } else {
+ lua_rawget(L,(i-1));
+ return 1;
+ }
+ return 0; /* not reached */
+}
+
+
+int
+getlist (lua_State *L) {
+ char *str;
+ if (lua_isstring(L,2)) {
+ str = (char *)lua_tostring(L,2);
+ if (strcmp(str,"page_ins_head")==0) {
+ lua_pushnumber(L,page_ins_head); lua_nodelib_push(L);
+ } else if (strcmp(str,"contrib_head")==0) {
+ lua_pushnumber(L,contrib_head); lua_nodelib_push(L);
+ } else if (strcmp(str,"page_head")==0) {
+ lua_pushnumber(L,page_head); lua_nodelib_push(L);
+ } else if (strcmp(str,"temp_head")==0) {
+ lua_pushnumber(L,temp_head); lua_nodelib_push(L);
+ } else if (strcmp(str,"hold_head")==0) {
+ lua_pushnumber(L,hold_head); lua_nodelib_push(L);
+ } else if (strcmp(str,"adjust_head")==0) {
+ lua_pushnumber(L,adjust_head); lua_nodelib_push(L);
+ } else if (strcmp(str,"pre_adjust_head")==0) {
+ lua_pushnumber(L,pre_adjust_head); lua_nodelib_push(L);
+ } else if (strcmp(str,"align_head")==0) {
+ lua_pushnumber(L,align_head); lua_nodelib_push(L);
+ } else {
+ lua_pushnil(L);
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+int
+setlist (lua_State *L) {
+ return 0;
+}
+
+#define infinity 2147483647
+
+static int
+do_integer_error(double m) {
+ char *help[] = {"I can only go up to 2147483647='17777777777=""7FFFFFFF,",
+ "so I'm using that number instead of yours.",
+ NULL } ;
+ tex_error("Number too big",help);
+ return (m>0.0 ? infinity : -infinity);
+}
+
+
+static int
+tex_roundnumber (lua_State *L) {
+ double m = lua_tonumber(L, 1)+0.5;
+ if (abs(m)>(double)infinity)
+ lua_pushnumber(L,do_integer_error(m));
+ else
+ lua_pushnumber(L,floor(m));
+ return 1;
+}
+
+static int
+tex_scaletable (lua_State *L) {
+ double delta = luaL_checknumber(L, 2);
+ if (lua_istable(L,1)) {
+ lua_newtable(L); /* the new table is at index 3 */
+ lua_pushnil(L);
+ while (lua_next(L,1)!= 0 ) { /* numeric value */
+ lua_pushvalue(L,-2);
+ lua_insert(L,-2);
+ if (lua_isnumber(L,-1)) {
+ double m = lua_tonumber(L,-1)*delta + 0.5;
+ lua_pop(L,1);
+ if (abs(m)>(double)infinity)
+ lua_pushnumber(L,do_integer_error(m));
+ else
+ lua_pushnumber(L,floor(m));
+ }
+ lua_rawset(L,3);
+ }
+ } else if (lua_isnumber(L,1)) {
+ double m = lua_tonumber(L,1)*delta + 0.5;
+ if (abs(m)>(double)infinity)
+ lua_pushnumber(L,do_integer_error(m));
+ else
+ lua_pushnumber(L,floor(m));
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static const struct luaL_reg texlib [] = {
+ {"write", luacwrite},
+ {"print", luacprint},
+ {"sprint", luacsprint},
+ {"setdimen", setdimen},
+ {"getdimen", getdimen},
+ {"setattribute", setattribute},
+ {"getattribute", getattribute},
+ {"setcount", setcount},
+ {"getcount", getcount},
+ {"settoks", settoks},
+ {"gettoks", gettoks},
+ {"setbox", setbox},
+ {"getbox", getbox},
+ {"setlist", setlist},
+ {"getlist", getlist},
+ {"setboxwd", setboxwd},
+ {"getboxwd", getboxwd},
+ {"setboxht", setboxht},
+ {"getboxht", getboxht},
+ {"setboxdp", setboxdp},
+ {"getboxdp", getboxdp},
+ {"round", tex_roundnumber},
+ {"scale", tex_scaletable},
+ {NULL, NULL} /* sentinel */
+};
+
+int luaopen_tex (lua_State *L)
+{
+ luaL_register(L, "tex", texlib);
+ make_table(L,"attribute","getattribute","setattribute");
+ make_table(L,"dimen","getdimen","setdimen");
+ make_table(L,"count","getcount","setcount");
+ make_table(L,"toks","gettoks","settoks");
+ make_table(L,"box","getbox","setbox");
+ make_table(L,"lists","getlist","setlist");
+ make_table(L,"wd","getboxwd","setboxwd");
+ make_table(L,"ht","getboxht","setboxht");
+ make_table(L,"dp","getboxdp","setboxdp");
+ /* make the meta entries */
+ /* fetch it back */
+ luaL_newmetatable(L,"tex_meta");
+ lua_pushstring(L, "__index");
+ lua_pushcfunction(L, gettex);
+ lua_settable(L, -3);
+ lua_pushstring(L, "__newindex");
+ lua_pushcfunction(L, settex);
+ lua_settable(L, -3);
+ lua_setmetatable(L,-2); /* meta to itself */
+ /* initialize the I/O stack: */
+ spindles = xmalloc(sizeof(spindle));
+ spindle_index = 0;
+ spindles[0].head = NULL;
+ spindles[0].tail = NULL;
+ spindle_size = 1;
+ return 1;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/lua/ltokenlib.c b/Build/source/texk/web2c/luatexdir/lua/ltokenlib.c
new file mode 100644
index 00000000000..582779623cf
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/ltokenlib.c
@@ -0,0 +1,263 @@
+/* $Id: ltokenlib.c 1013 2008-02-14 00:09:02Z oneiros $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+
+extern int get_command_id (char *);
+
+static int max_command = 0;
+static int hash_base = 0;
+static int active_base = 0;
+static int null_cs = 0;
+
+#define protected_token 0x1C00001
+
+#define is_valid_token(L,i) (lua_istable(L,i) && lua_objlen(L,i)==3)
+#define get_token_cmd(L,i) lua_rawgeti(L,i,1)
+#define get_token_chr(L,i) lua_rawgeti(L,i,2)
+#define get_token_cs(L,i) lua_rawgeti(L,i,3)
+
+static int
+test_expandable (lua_State *L) {
+ integer cmd = -1;
+ if (is_valid_token(L,-1)) {
+ get_token_cmd(L,-1);
+ if (lua_isnumber(L,-1)) {
+ cmd = lua_tointeger(L,-1);
+ } else if (lua_isstring(L,-1)) {
+ cmd = get_command_id((char *)lua_tostring(L,-1));
+ }
+ if (cmd>max_command) {
+ lua_pushboolean(L,1);
+ } else {
+ lua_pushboolean(L,0);
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+
+static int
+test_protected (lua_State *L) {
+ integer chr = -1;
+ if (is_valid_token(L,-1)) {
+ get_token_chr(L,-1);
+ if (lua_isnumber(L,-1)) {
+ chr = lua_tointeger(L,-1);
+ } else if (lua_isstring(L,-1)) {
+ chr = get_command_id((char *)lua_tostring(L,-1));
+ }
+ if (fixmem[fixmem[chr].hhrh].hhlh==protected_token) {
+ lua_pushboolean(L,1);
+ } else {
+ lua_pushboolean(L,0);
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int
+test_activechar (lua_State *L) {
+ integer cmd = -1;
+ if (is_valid_token(L,-1)) {
+ get_token_chr(L,-1);
+ if (lua_isnumber(L,-1)) {
+ cmd = lua_tointeger(L,-1);
+ }
+ if (cmd>0 && cmd==protected_token) {
+ lua_pushboolean(L,1);
+ } else {
+ lua_pushboolean(L,0);
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+
+static int
+run_get_command_name (lua_State *L) {
+ int cs;
+ if (is_valid_token(L,-1)) {
+ get_token_cmd(L,-1);
+ if (lua_isnumber(L,-1)) {
+ cs = lua_tointeger(L,-1);
+ lua_pushstring(L,command_names[cs].cmd_name);
+ } else {
+ lua_pushstring(L,"");
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int
+run_get_csname_name (lua_State *L) {
+ int cs,cmd,n;
+ char *s;
+
+ if (is_valid_token(L,-1)) {
+ get_token_cmd(L,-1);
+ if (lua_isnumber(L,-1)) {
+ cmd = lua_tointeger(L,-1);
+ }
+ lua_pop(L,1);
+ cs = 0;
+ get_token_cs(L,-1);
+ if (lua_isnumber(L,-1)) {
+ cs = lua_tointeger(L,-1);
+ }
+ lua_pop(L,1);
+
+ if (cs != 0 && (n = zget_cs_text(cs)) && n>=0) {
+ s = makecstring(n);
+ lua_pushstring(L,s);
+ } else {
+ lua_pushstring(L,"");
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int
+run_get_command_id (lua_State *L) {
+ int cs = -1;
+ if (lua_isstring(L,-1)) {
+ cs = get_command_id((char *)lua_tostring(L,-1));
+ }
+ lua_pushnumber(L,cs);
+ return 1;
+}
+
+
+static int
+run_get_csname_id (lua_State *L) {
+ int texstr;
+ char *s;
+ size_t k,cs = 0;
+ if (lua_isstring(L,-1)) {
+ s = (char *)lua_tolstring(L,-1, &k);
+ texstr = maketexlstring(s,k);
+ cs = string_lookup(texstr);
+ flush_str(texstr);
+ }
+ lua_pushnumber(L,cs);
+ return 1;
+}
+
+
+void
+make_token_table (lua_State *L, int cmd, int chr, int cs) {
+ lua_createtable(L,3,0);
+ lua_pushnumber(L,cmd);
+ lua_rawseti(L,-2,1);
+ lua_pushnumber(L,chr);
+ lua_rawseti(L,-2,2);
+ lua_pushnumber(L,cs);
+ lua_rawseti(L,-2,3);
+}
+
+static int
+run_get_next (lua_State *L) {
+ int save_nncs;
+ save_nncs = no_new_control_sequence;
+ no_new_control_sequence = 0;
+ get_next();
+ no_new_control_sequence = save_nncs;
+ make_token_table(L,cur_cmd,cur_chr,cur_cs);
+ return 1;
+}
+
+static int
+run_expand (lua_State *L) {
+ expand();
+ return 0;
+}
+
+
+static int
+run_lookup (lua_State *L) {
+ char *s;
+ size_t l;
+ str_number t;
+ integer cs,cmd,chr;
+ int save_nncs;
+ if (lua_isstring(L,-1)) {
+ s = (char *)lua_tolstring(L,-1,&l);
+ if (l>0) {
+ save_nncs = no_new_control_sequence;
+ no_new_control_sequence = true;
+ cs = id_lookup((last+1),l); /* cleans up the lookup buffer */
+ t = maketexlstring(s,l);
+ cs = string_lookup(t);
+ flush_str(t);
+ cmd = zget_eq_type(cs);
+ chr = zget_equiv(cs);
+ make_token_table(L,cmd,chr,cs);
+ no_new_control_sequence = save_nncs;
+ return 1;
+ }
+ }
+ lua_newtable(L);
+ return 1;
+}
+
+static int
+run_build (lua_State *L) {
+ integer cmd,chr,cs;
+ if (lua_isnumber(L,1)) {
+ cs =0;
+ chr = lua_tointeger(L,1);
+ cmd = luaL_optinteger(L,2,zget_char_cat_code(chr));
+ if (cmd==0 || cmd == 9 || cmd == 14 || cmd == 15) {
+ fprintf(stdout, "\n\nluatex error: not a good token.\nCatcode %i can not be returned, so I replaced it by 12 (other)",(int)cmd);
+ error();
+ cmd=12;
+ }
+ if (cmd == 13) {
+ cs=chr+active_base;
+ cmd=zget_eq_type(cs);
+ chr=zget_equiv(cs);
+ }
+ make_token_table(L,cmd,chr,cs);
+ return 1;
+ } else {
+ return run_lookup(L);
+ }
+}
+
+
+static const struct luaL_reg tokenlib [] = {
+ {"get_next", run_get_next},
+ {"expand", run_expand},
+ {"lookup", run_lookup},
+ {"create", run_build},
+ {"is_expandable",test_expandable},
+ {"is_activechar",test_activechar},
+ {"is_protected", test_protected},
+ {"csname_id", run_get_csname_id},
+ {"csname_name", run_get_csname_name},
+ {"command_name", run_get_command_name},
+ {"command_id", run_get_command_id},
+ {NULL, NULL} /* sentinel */
+};
+
+int luaopen_token (lua_State *L)
+{
+ luaL_register(L, "token", tokenlib);
+ max_command = get_max_command();
+ hash_base = get_hash_base();
+ active_base = get_active_base();
+ null_cs = get_nullcs();
+ return 1;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/lua/luainit.c b/Build/source/texk/web2c/luatexdir/lua/luainit.c
new file mode 100644
index 00000000000..c76b676c0f4
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/luainit.c
@@ -0,0 +1,520 @@
+#include <sys/stat.h>
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+#include <luatexdir/luatexextra.h>
+
+#ifndef program_invocation_name
+/* char *program_invocation_name = NULL; */
+#endif
+
+extern void parse_src_specials_option (char *n) ;
+
+const_string LUATEX_IHELP[] = {
+ "Usage: luatex --lua=FILE [OPTION]... [TEXNAME[.tex]] [COMMANDS]",
+ " or: luatex --lua=FILE [OPTION]... \\FIRST-LINE",
+ " or: luatex --lua=FILE [OPTION]... &FMT ARGS",
+ " Run luaTeX on TEXNAME, usually creating TEXNAME.pdf.",
+ " Any remaining COMMANDS are processed as luatex input, after TEXNAME is read.",
+ "",
+ " Alternatively, if the first non-option argument begins with a backslash,",
+ " interpret all non-option arguments as a line of luatex input.",
+ "",
+ " Alternatively, if the first non-option argument begins with a &, the",
+ " next word is taken as the FMT to read, overriding all else. Any",
+ " remaining arguments are processed as above.",
+ "",
+ " If no arguments or options are specified, prompt for input.",
+ "",
+ " --lua=FILE the lua initialization file",
+ " --safer disable some easily exploitable lua commands",
+ " --fmt=FORMAT load the format file FORMAT",
+ " --ini be initex, for dumping formats",
+ " --help display this help and exit",
+ " --version output version information and exit",
+ "",
+ " Alternate behaviour models can be obtained by special switches",
+ "",
+ " --luaonly run a lua file, then exit",
+ " --luaconly byte-compile a lua file, then exit",
+ NULL
+};
+
+static void
+prepare_cmdline(lua_State * L, char **argv, int argc, int zero_offset)
+{
+ int i;
+ luaL_checkstack(L, argc + 3, "too many arguments to script");
+ lua_createtable(L, 0, 0);
+ for (i = 0; i < argc; i++) {
+ lua_pushstring(L, argv[i]);
+ lua_rawseti(L, -2, (i-zero_offset));
+ }
+ lua_setglobal(L, "arg");
+ return;
+}
+
+extern string dump_name;
+extern const_string c_job_name;
+extern boolean srcspecialsoption;
+extern char *last_source_name;
+extern int last_lineno;
+
+string input_name = NULL;
+
+static string user_progname = NULL;
+
+extern char *ptexbanner;
+extern int program_name_set; /* in lkpselib.c */
+
+/* for topenin() */
+extern char **argv;
+extern int argc;
+
+char *startup_filename = NULL;
+int lua_only = 0;
+int lua_offset = 0;
+
+int safer_option = 0;
+
+/* Reading the options. */
+
+/* Test whether getopt found an option ``A''.
+ Assumes the option index is in the variable `option_index', and the
+ option table in a variable `long_options'. */
+#define ARGUMENT_IS(a) STREQ (long_options[option_index].name, a)
+
+/* SunOS cc can't initialize automatic structs, so make this static. */
+static struct option long_options[]
+ = { { "fmt", 1, 0, 0},
+ { "lua", 1, 0, 0},
+ { "luaonly", 0, 0, 0},
+ { "safer", 0, &safer_option, 1},
+ { "help", 0, 0, 0 },
+ { "ini", 0, &ini_version, 1 },
+ { "interaction", 1, 0, 0 },
+ { "halt-on-error", 0, &haltonerrorp, 1 },
+ { "kpathsea-debug", 1, 0, 0 },
+ { "progname", 1, 0, 0 },
+ { "version", 0, 0, 0 },
+ { "recorder", 0, &recorder_enabled, 1 },
+ { "etex", 0, 0, 0 },
+ { "output-comment", 1, 0, 0 },
+ { "output-directory", 1, 0, 0 },
+ { "draftmode", 0, 0, 0 },
+ { "output-format", 1, 0, 0 },
+ { "shell-escape", 0, &shellenabledp, 1 },
+ { "no-shell-escape", 0, &shellenabledp, -1 },
+ { "debug-format", 0, &debug_format_file, 1 },
+ { "src-specials", 2, 0, 0 },
+ { "file-line-error-style", 0, &filelineerrorstylep, 1 },
+ { "no-file-line-error-style", 0, &filelineerrorstylep, -1 },
+ /* Shorter option names for the above. */
+ { "file-line-error", 0, &filelineerrorstylep, 1 },
+ { "no-file-line-error", 0, &filelineerrorstylep, -1 },
+ { "jobname", 1, 0, 0 },
+ { "parse-first-line", 0, &parsefirstlinep, 1 },
+ { "no-parse-first-line", 0, &parsefirstlinep, -1 },
+ { "translate-file", 1, 0, 0 },
+ { "default-translate-file", 1, 0, 0 },
+ { "8bit", 0, 0, 0 },
+ { "mktex", 1, 0, 0 },
+ { "no-mktex", 1, 0, 0 },
+{0, 0, 0, 0}
+};
+
+static void
+parse_options(int argc, char **argv)
+{
+ int g; /* `getopt' return code. */
+ int option_index;
+ char *firstfile = NULL;
+ opterr = 0; /* dont whine */
+ for (;;) {
+ g = getopt_long_only(argc, argv, "+", long_options, &option_index);
+
+ if (g == -1) /* End of arguments, exit the loop. */
+ break;
+ if (g == '?') /* Unknown option. */
+ continue;
+
+ assert(g == 0); /* We have no short option names. */
+
+ if (ARGUMENT_IS("luaonly")) {
+ lua_only = 1;
+ lua_offset = optind;
+ luainit = 1 ;
+ } else if (ARGUMENT_IS("lua")) {
+ startup_filename = optarg;
+ lua_offset = (optind-1);
+ luainit = 1 ;
+
+ } else if (ARGUMENT_IS ("kpathsea-debug")) {
+ kpathsea_debug |= atoi (optarg);
+
+ } else if (ARGUMENT_IS("progname")) {
+ user_progname = optarg;
+
+ } else if (ARGUMENT_IS ("jobname")) {
+ c_job_name = optarg;
+
+ } else if (ARGUMENT_IS("fmt")) {
+ dump_name = optarg;
+
+ } else if (ARGUMENT_IS ("output-directory")) {
+ output_directory = optarg;
+
+ } else if (ARGUMENT_IS ("output-comment")) {
+ unsigned len = strlen (optarg);
+ if (len < 256) {
+ output_comment = optarg;
+ } else {
+ WARNING2 ("Comment truncated to 255 characters from %d. (%s)",
+ len, optarg);
+ output_comment = (string)xmalloc (256);
+ strncpy (output_comment, optarg, 255);
+ output_comment[255] = 0;
+ }
+
+ } else if (ARGUMENT_IS ("src-specials")) {
+ last_source_name = xstrdup("");
+ /* Option `--src" without any value means `auto' mode. */
+ if (optarg == NULL) {
+ insertsrcspecialeverypar = true;
+ insertsrcspecialauto = true;
+ srcspecialsoption = true;
+ srcspecialsp = true;
+ } else {
+ parse_src_specials_option(optarg);
+ }
+
+ } else if (ARGUMENT_IS ("output-format")) {
+ pdf_output_option = 1;
+ if (strcmp(optarg, "dvi") == 0) {
+ pdf_output_value = 0;
+ } else if (strcmp(optarg, "pdf") == 0) {
+ pdf_output_value = 2;
+ } else {
+ WARNING1 ("Ignoring unknown value `%s' for --output-format", optarg);
+ pdf_output_option = 0;
+ }
+
+ } else if (ARGUMENT_IS ("draftmode")) {
+ pdf_draftmode_option = 1;
+ pdf_draftmode_value = 1;
+
+ } else if (ARGUMENT_IS ("mktex")) {
+ kpse_maketex_option (optarg, true);
+
+ } else if (ARGUMENT_IS ("no-mktex")) {
+ kpse_maketex_option (optarg, false);
+
+ } else if (ARGUMENT_IS ("interaction")) {
+ /* These numbers match @d's in *.ch */
+ if (STREQ (optarg, "batchmode")) {
+ interactionoption = 0;
+ } else if (STREQ (optarg, "nonstopmode")) {
+ interactionoption = 1;
+ } else if (STREQ (optarg, "scrollmode")) {
+ interactionoption = 2;
+ } else if (STREQ (optarg, "errorstopmode")) {
+ interactionoption = 3;
+ } else {
+ WARNING1 ("Ignoring unknown argument `%s' to --interaction", optarg);
+ }
+
+ } else if (ARGUMENT_IS("help")) {
+ usagehelp(LUATEX_IHELP, BUG_ADDRESS);
+
+ } else if (ARGUMENT_IS("version")) {
+ char *versions;
+ initversionstring(&versions);
+ print_version_banner();
+
+ puts(
+"\n\nLuaTeX merges and builds upon (parts of) the code from these projects:\n\n"
+"tex by Donald Knuth\n"
+"etex by Peter Breitenlohner, Phil Taylor and friends\n"
+"omega by John Plaice and Yannis Haralambous\n"
+"aleph by Giuseppe Bilotta\n"
+"pdftex by Han The Thanh and friends\n"
+"kpathsea by Karl Berry, Olaf Weber and others\n"
+"lua by Roberto Ierusalimschy, Waldemar Celes,\n"
+" Luiz Henrique de Figueiredo\n"
+"metapost by John Hobby, Taco Hoekwater and friends.\n"
+"xpdf by Derek Noonberg (partial)\n"
+"fontforge by George Williams (partial)\n\n"
+"Some extensions to lua and additional lua libraries are used, as well as\n"
+"libraries for graphic inclusion. More details can be found in the source.\n"
+"Code development was sponsored by a grant from Colorado State University\n"
+"via the 'oriental tex' project, the TeX User Groups, and donations.\n\n"
+"The LuaTeX team is Hans Hagen, Hartmut Henkel, Taco Hoekwater.\n\n"
+"There is NO warranty. Redistribution of this software is covered by\n"
+"the terms of the GNU General Public License, version 2. For more\n"
+"information about these matters, see the file named COPYING and\n"
+"the LuaTeX source.\n\n"
+"Copyright 2008 Taco Hoekwater, the LuaTeX Team.\n");
+
+ puts(versions);
+ uexit(0);
+ }
+ }
+ /* attempt to find dump_name */
+ if (argv[optind] && argv[optind][0] == '&') {
+ dump_name = strdup(argv[optind] + 1);
+ } else if (argv[optind] && argv[optind][0] != '\\') {
+ if (argv[optind][0] == '*') {
+ input_name = strdup(argv[optind] + 1);
+ } else {
+ firstfile = strdup(argv[optind]);
+ if (lua_only) {
+ startup_filename = firstfile;
+ } else {
+ if ((strstr(firstfile,".lua") == firstfile+strlen(firstfile)-4) ||
+ (strstr(firstfile,".luc") == firstfile+strlen(firstfile)-4) ||
+ (strstr(firstfile,".LUA") == firstfile+strlen(firstfile)-4) ||
+ (strstr(firstfile,".LUC") == firstfile+strlen(firstfile)-4) ||
+ (strstr(argv[0],"luatexlua") != NULL) ||
+ (strstr(argv[0],"texlua") != NULL)) {
+ startup_filename = firstfile;
+ lua_only = 1;
+ lua_offset = optind;
+ luainit = 1 ;
+ } else {
+ input_name = firstfile;
+ }
+ }
+ }
+ } else {
+ if ((strstr(argv[0],"luatexlua") != NULL)||
+ (strstr(argv[0],"texlua") != NULL)) {
+ lua_only = 1;
+ luainit = 1 ;
+ }
+ }
+}
+
+/* test for readability */
+#define is_readable(a) (stat(a,&finfo)==0) && S_ISREG(finfo.st_mode) && \
+ (f=fopen(a,"r")) != NULL && !fclose(f)
+
+char *
+find_filename(char *name, char *envkey)
+{
+ struct stat finfo;
+ char *dirname = NULL;
+ char *filename = NULL;
+ FILE *f;
+ if (is_readable(name)) {
+ return name;
+ } else {
+ dirname = getenv(envkey);
+ if ((dirname != NULL) && strlen(dirname)) {
+ dirname = strdup(getenv(envkey));
+ if (*(dirname + strlen(dirname) - 1) == '/') {
+ *(dirname + strlen(dirname) - 1) = 0;
+ }
+ filename = xmalloc(strlen(dirname) + strlen(name) + 2);
+ filename = concat3(dirname, "/", name);
+ if (is_readable(filename)) {
+ xfree(dirname);
+ return filename;
+ }
+ xfree(filename);
+ }
+ }
+ return NULL;
+}
+
+
+void
+init_kpse (void) {
+
+ if (!user_progname) {
+ user_progname = dump_name;
+ } else if (!dump_name) {
+ dump_name = user_progname;
+ }
+ if (!user_progname) {
+ if (ini_version) {
+ user_progname = input_name;
+ } else {
+ if(!startup_filename) {
+ if (!dump_name) {
+ dump_name = strdup(argv[0]);
+ user_progname = dump_name;
+ }
+ }
+ }
+ }
+ if (!user_progname) {
+ fprintf(stdout,
+ "kpathsea mode needs a --progname or --fmt switch\n");
+ exit(1);
+ }
+ kpse_set_program_name(argv[0], user_progname);
+ program_name_set=1;
+}
+
+void
+fix_dumpname (void) {
+ int dist;
+ if (dump_name) {
+ /* adjust array for Pascal and provide extension, if needed */
+ dist = strlen(dump_name) - strlen(DUMP_EXT);
+ if (strstr(dump_name, DUMP_EXT) == dump_name + dist)
+ DUMP_VAR = concat(" ", dump_name);
+ else
+ DUMP_VAR = concat3(" ", dump_name, DUMP_EXT);
+ DUMP_LENGTH_VAR = strlen(DUMP_VAR + 1);
+ } else {
+ /* For dump_name to be NULL is a bug. */
+ if (!ini_version)
+ abort();
+ }
+}
+
+void
+lua_initialize(int ac, char **av)
+{
+
+ char *given_file = NULL;
+ int kpse_init;
+ int tex_table_id;
+ int pdf_table_id;
+ int token_table_id;
+ int node_table_id;
+ /* Save to pass along to topenin. */
+ argc = ac;
+ argv = av;
+
+ ptexbanner = BANNER;
+ program_invocation_name = argv[0];
+
+ /* be 'luac' */
+ if (argc>1 &&
+ (STREQ(argv[0],"texluac") ||
+ STREQ(argv[1],"--luaconly") ||
+ STREQ(argv[1],"--luac"))) {
+ exit(luac_main(ac,av));
+ }
+
+ /* Must be initialized before options are parsed. */
+ interactionoption = 4;
+ dump_name = NULL;
+ /* parse commandline */
+ parse_options(ac, av);
+
+ /* make sure that the locale is 'sane' (for lua) */
+ putenv("LC_CTYPE=C");
+ putenv("LC_COLLATE=C");
+ putenv("LC_NUMERIC=C");
+
+ /* this is sometimes needed */
+ putenv("engine=luatex");
+
+ luainterpreter(0);
+
+ prepare_cmdline(Luas[0], argv, argc, lua_offset); /* collect arguments */
+
+ if (startup_filename != NULL) {
+ given_file = xstrdup(startup_filename);
+ startup_filename = find_filename(startup_filename, "LUATEXDIR");
+ }
+ /* now run the file */
+ if (startup_filename != NULL) {
+ /* hide the 'tex' and 'pdf' table */
+ tex_table_id = hide_lua_table(Luas[0], "tex");
+ token_table_id = hide_lua_table(Luas[0], "token");
+ node_table_id = hide_lua_table(Luas[0], "node");
+ pdf_table_id = hide_lua_table(Luas[0], "pdf");
+
+ if (luaL_loadfile(Luas[0], startup_filename)) {
+ fprintf(stdout, "%s\n",lua_tostring(Luas[0], -1));
+ exit(1);
+ }
+ if (lua_pcall(Luas[0], 0, 0, 0)) {
+ fprintf(stdout, "%s\n",lua_tostring(Luas[0], -1));
+ exit(1);
+ }
+ /* no filename? quit now! */
+ if (!input_name) {
+ get_lua_string("texconfig", "jobname", &input_name);
+ }
+ if (!dump_name) {
+ get_lua_string("texconfig", "formatname", &dump_name);
+ }
+ if ((lua_only) || ((!input_name) && (!dump_name))) {
+ exit(0);
+ }
+ /* unhide the 'tex' and 'pdf' table */
+ unhide_lua_table(Luas[0], "tex", tex_table_id);
+ unhide_lua_table(Luas[0], "pdf", pdf_table_id);
+ unhide_lua_table(Luas[0], "token", token_table_id);
+ unhide_lua_table(Luas[0], "node", node_table_id);
+
+ /* kpse_init */
+ kpse_init = -1;
+ get_lua_boolean("texconfig", "kpse_init", &kpse_init);
+
+ if (kpse_init != 0) {
+ init_kpse();
+ }
+ /* prohibit_file_trace (boolean) */
+ tracefilenames = 1;
+ get_lua_boolean("texconfig", "trace_file_names", &tracefilenames);
+
+ /* src_special_xx */
+ insertsrcspecialauto = insertsrcspecialeverypar =
+ insertsrcspecialeveryparend = insertsrcspecialeverycr =
+ insertsrcspecialeverymath = insertsrcspecialeveryhbox =
+ insertsrcspecialeveryvbox = insertsrcspecialeverydisplay =
+ false;
+ get_lua_boolean("texconfig", "src_special_auto",
+ &insertsrcspecialauto);
+ get_lua_boolean("texconfig", "src_special_everypar",
+ &insertsrcspecialeverypar);
+ get_lua_boolean("texconfig", "src_special_everyparend",
+ &insertsrcspecialeveryparend);
+ get_lua_boolean("texconfig", "src_special_everycr",
+ &insertsrcspecialeverycr);
+ get_lua_boolean("texconfig", "src_special_everymath",
+ &insertsrcspecialeverymath);
+ get_lua_boolean("texconfig", "src_special_everyhbox",
+ &insertsrcspecialeveryhbox);
+ get_lua_boolean("texconfig", "src_special_everyvbox",
+ &insertsrcspecialeveryvbox);
+ get_lua_boolean("texconfig", "src_special_everydisplay",
+ &insertsrcspecialeverydisplay);
+
+ srcspecialsp = insertsrcspecialauto | insertsrcspecialeverypar |
+ insertsrcspecialeveryparend | insertsrcspecialeverycr |
+ insertsrcspecialeverymath | insertsrcspecialeveryhbox |
+ insertsrcspecialeveryvbox | insertsrcspecialeverydisplay;
+
+ /* file_line_error */
+ filelineerrorstylep = false;
+ get_lua_boolean("texconfig", "file_line_error",
+ &filelineerrorstylep);
+
+ /* halt_on_error */
+ haltonerrorp = false;
+ get_lua_boolean("texconfig", "halt_on_error", &haltonerrorp);
+
+ fix_dumpname();
+ } else {
+ if (luainit) {
+ if (given_file) {
+ fprintf(stdout, "%s file %s not found\n", (lua_only ? "Script" : "Configuration"), given_file);
+ } else {
+ fprintf(stdout, "No %s file given\n", (lua_only ? "script" : "configuration"));
+ }
+ exit(1);
+ } else {
+ /* init */
+ init_kpse();
+ fix_dumpname();
+ }
+ }
+}
diff --git a/Build/source/texk/web2c/luatexdir/lua/luanode.c b/Build/source/texk/web2c/luatexdir/lua/luanode.c
new file mode 100644
index 00000000000..17c8e7be8e2
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/luanode.c
@@ -0,0 +1,200 @@
+/* $Id: luanode.c 1013 2008-02-14 00:09:02Z oneiros $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+#include "nodes.h"
+
+#undef link /* defined by cpascal.h */
+#define info(a) fixmem[(a)].hhlh
+#define link(a) fixmem[(a)].hhrh
+
+
+static char *group_code_names[] = {
+ "",
+ "simple",
+ "hbox",
+ "adjusted_hbox",
+ "vbox",
+ "vtop",
+ "align",
+ "no_align",
+ "output",
+ "math",
+ "disc",
+ "insert",
+ "vcenter",
+ "math_choice",
+ "semi_simple",
+ "math_shift",
+ "math_left",
+ "local_box" ,
+ "split_off",
+ "split_keep",
+ "preamble",
+ "align_set",
+ "fin_row"};
+
+char *pack_type_name[] = { "exactly", "additional"};
+
+
+void
+lua_node_filter_s (int filterid, char *extrainfo, halfword head_node, halfword *tail_node) {
+ halfword ret;
+ int a;
+ lua_State *L = Luas[0];
+ int callback_id = callback_defined(filterid);
+ if (head_node==null || vlink(head_node)==null || callback_id==0)
+ return;
+ lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id);
+ lua_rawgeti(L,-1, callback_id);
+ if (!lua_isfunction(L,-1)) {
+ lua_pop(L,2);
+ return;
+ }
+ nodelist_to_lua(L,vlink(head_node)); /* arg 1 */
+ lua_pushstring(L,extrainfo); /* arg 2 */
+ if (lua_pcall(L,2,1,0) != 0) { /* no arg, 1 result */
+ fprintf(stdout,"error: %s\n",lua_tostring(L,-1));
+ lua_pop(L,2);
+ error();
+ return;
+ }
+ if (lua_isboolean(L,-1)) {
+ if (lua_toboolean(L,-1)!=1) {
+ flush_node_list(vlink(head_node));
+ vlink(head_node) = null;
+ }
+ } else {
+ a = nodelist_from_lua(L);
+ vlink(head_node)= a;
+ }
+ lua_pop(L,2); /* result and callback container table */
+ if (fix_node_lists)
+ fix_node_list(head_node);
+ ret = vlink(head_node);
+ if (ret!=null) {
+ while (vlink(ret)!=null)
+ ret=vlink(ret);
+ *tail_node=ret;
+ } else {
+ *tail_node=head_node;
+ }
+ return ;
+}
+
+void
+lua_node_filter (int filterid, int extrainfo, halfword head_node, halfword *tail_node) {
+ lua_node_filter_s(filterid, group_code_names[extrainfo], head_node, tail_node);
+ return ;
+}
+
+
+
+halfword
+lua_hpack_filter (halfword head_node, scaled size, int pack_type, int extrainfo) {
+ halfword ret;
+ lua_State *L = Luas[0];
+ int callback_id = callback_defined(hpack_filter_callback);
+ if (head_node==null || callback_id == 0)
+ return head_node;
+ lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id);
+ lua_rawgeti(L,-1, callback_id);
+ if (!lua_isfunction(L,-1)) {
+ lua_pop(L,2);
+ return head_node;
+ }
+
+ nodelist_to_lua(L,head_node);
+ lua_pushstring(L,group_code_names[extrainfo]);
+ lua_pushnumber(L,size);
+ lua_pushstring(L,pack_type_name[pack_type]);
+ if (lua_pcall(L,4,1,0) != 0) { /* no arg, 1 result */
+ fprintf(stdout,"error: %s\n",lua_tostring(L,-1));
+ lua_pop(L,2);
+ error();
+ return head_node;
+ }
+ ret = head_node;
+ if (lua_isboolean(L,-1)) {
+ if (lua_toboolean(L,-1)!=1) {
+ flush_node_list(head_node);
+ ret = null;
+ }
+ } else {
+ ret = nodelist_from_lua(L);
+ }
+ lua_pop(L,2); /* result and callback container table */
+ /* lua_gc(L,LUA_GCSTEP, LUA_GC_STEP_SIZE);*/
+ if (fix_node_lists)
+ fix_node_list(ret);
+ return ret;
+}
+
+halfword
+lua_vpack_filter (halfword head_node, scaled size, int pack_type, scaled maxd, int extrainfo) {
+ halfword ret;
+ integer callback_id ;
+ lua_State *L = Luas[0];
+ if (head_node==null)
+ return head_node;
+ if (strcmp("output",group_code_names[extrainfo])==0) {
+ callback_id = callback_defined(pre_output_filter_callback);
+ } else {
+ callback_id = callback_defined(vpack_filter_callback);
+ }
+ if (callback_id==0) {
+ return head_node;
+ }
+ lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id);
+ lua_rawgeti(L,-1, callback_id);
+ if (!lua_isfunction(L,-1)) {
+ lua_pop(L,2);
+ return head_node;
+ }
+ nodelist_to_lua(L,head_node);
+ lua_pushstring(L,group_code_names[extrainfo]);
+ lua_pushnumber(L,size);
+ lua_pushstring(L,pack_type_name[pack_type]);
+ lua_pushnumber(L,maxd);
+ if (lua_pcall(L,5,1,0) != 0) { /* no arg, 1 result */
+ fprintf(stdout,"error: %s\n",lua_tostring(L,-1));
+ lua_pop(L,2);
+ error();
+ return head_node;
+ }
+ ret = head_node;
+ if (lua_isboolean(L,-1)) {
+ if (lua_toboolean(L,-1)!=1) {
+ flush_node_list(head_node);
+ ret = null;
+ }
+ } else {
+ ret = nodelist_from_lua(L);
+ }
+ lua_pop(L,2); /* result and callback container table */
+ /* lua_gc(L,LUA_GCSTEP, LUA_GC_STEP_SIZE);*/
+ if (fix_node_lists)
+ fix_node_list(ret);
+ return ret;
+}
+
+
+/* This is a quick hack to fix etex's \lastnodetype now that
+ * there are many more visible node types. TODO: check the
+ * eTeX manual for the expected return values.
+ */
+
+int
+visible_last_node_type (int n) {
+ int i = type(n);
+ if ((i!=math_node) && (i<=unset_node))
+ return i+1;
+ if (i==glyph_node)
+ return -1;
+ if (i==whatsit_node && subtype(n)==local_par_node)
+ return -1;
+ if (i==255)
+ return -1 ; /* this is not right, probably dir nodes! */
+ return last_known_node +1 ;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/lua/luastuff.c b/Build/source/texk/web2c/luatexdir/lua/luastuff.c
new file mode 100644
index 00000000000..f48bfdb0171
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/luastuff.c
@@ -0,0 +1,310 @@
+/* $Id: luastuff.c 1079 2008-03-05 15:34:41Z taco $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+lua_State *Luas[65536];
+
+extern char *startup_filename;
+extern int safer_option;
+
+int luastate_max = 0;
+int luastate_bytes = 0;
+
+void
+make_table (lua_State *L, char *tab, char *getfunc, char *setfunc) {
+ /* make the table */ /* [{<tex>}] */
+ lua_pushstring(L,tab); /* [{<tex>},"dimen"] */
+ lua_newtable(L); /* [{<tex>},"dimen",{}] */
+ lua_settable(L, -3); /* [{<tex>}] */
+ /* fetch it back */
+ lua_pushstring(L,tab); /* [{<tex>},"dimen"] */
+ lua_gettable(L, -2); /* [{<tex>},{<dimen>}] */
+ /* make the meta entries */
+ luaL_newmetatable(L,tab); /* [{<tex>},{<dimen>},{<dimen_m>}] */
+ lua_pushstring(L, "__index"); /* [{<tex>},{<dimen>},{<dimen_m>},"__index"] */
+ lua_pushstring(L, getfunc); /* [{<tex>},{<dimen>},{<dimen_m>},"__index","getdimen"] */
+ lua_gettable(L, -5); /* [{<tex>},{<dimen>},{<dimen_m>},"__index",<tex.getdimen>] */
+ lua_settable(L, -3); /* [{<tex>},{<dimen>},{<dimen_m>}] */
+ lua_pushstring(L, "__newindex");/* [{<tex>},{<dimen>},{<dimen_m>},"__newindex"] */
+ lua_pushstring(L, setfunc); /* [{<tex>},{<dimen>},{<dimen_m>},"__newindex","setdimen"] */
+ lua_gettable(L, -5); /* [{<tex>},{<dimen>},{<dimen_m>},"__newindex",<tex.setdimen>] */
+ lua_settable(L, -3); /* [{<tex>},{<dimen>},{<dimen_m>}] */
+ lua_setmetatable(L,-2); /* [{<tex>},{<dimen>}] : assign the metatable */
+ lua_pop(L,1); /* [{<tex>}] : clean the stack */
+}
+
+static
+const char *getS(lua_State * L, void *ud, size_t * size) {
+ LoadS *ls = (LoadS *) ud;
+ (void) L;
+ if (ls->size == 0)
+ return NULL;
+ *size = ls->size;
+ ls->size = 0;
+ return ls->s;
+}
+
+void *my_luaalloc (void *ud, void *ptr, size_t osize, size_t nsize) {
+ void *ret = NULL;
+ if (nsize == 0)
+ free(ptr);
+ else
+ ret = realloc(ptr, nsize);
+ luastate_bytes += (nsize-osize);
+ return ret;
+}
+
+static int my_luapanic (lua_State *L) {
+ (void)L; /* to avoid warnings */
+ fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n",
+ lua_tostring(L, -1));
+ return 0;
+}
+
+
+void
+luainterpreter (int n) {
+ lua_State *L;
+ L = lua_newstate(my_luaalloc, NULL);
+ if (L==NULL) {
+ fprintf(stderr,"Can't create a new Lua state (%d).",n);
+ return;
+ }
+ lua_atpanic(L, &my_luapanic);
+
+ luastate_max++;
+ luaL_openlibs(L);
+
+ open_oslibext(L,safer_option);
+
+ lua_getglobal(L,"package");
+ lua_pushstring(L,"");
+ lua_setfield(L,-2,"cpath");
+ lua_pop(L,1); /* pop the table */
+
+ /*luaopen_unicode(L);*/
+ lua_pushcfunction(L, luaopen_unicode);
+ lua_pushstring(L, "unicode");
+ lua_call(L, 1, 0);
+
+ /*luaopen_zip(L);*/
+ lua_pushcfunction(L, luaopen_zip);
+ lua_pushstring(L, "zip");
+ lua_call(L, 1, 0);
+
+ /*luaopen_lpeg(L);*/
+ lua_pushcfunction(L, luaopen_lpeg);
+ lua_pushstring(L, "lpeg");
+ lua_call(L, 1, 0);
+
+ /*luaopen_md5(L);*/
+ lua_pushcfunction(L, luaopen_md5);
+ lua_pushstring(L, "md5");
+ lua_call(L, 1, 0);
+
+ /*luaopen_lfs(L);*/
+ lua_pushcfunction(L, luaopen_lfs);
+ lua_pushstring(L, "lfs");
+ lua_call(L, 1, 0);
+
+ /* zlib. slightly odd calling convention */
+ luaopen_zlib(L);
+ lua_setglobal(L,"zlib");
+ luaopen_gzip(L);
+ /* fontforge */
+ luaopen_ff(L);
+
+ luaopen_pdf(L);
+ luaopen_tex(L);
+ luaopen_token(L);
+ luaopen_node(L);
+ luaopen_texio(L);
+ luaopen_kpse(L);
+ if (n==0) {
+ luaopen_callback(L);
+ lua_createtable(L, 0, 0);
+ lua_setglobal(L, "texconfig");
+ }
+ luaopen_lua(L,n,startup_filename);
+ luaopen_stats(L);
+ luaopen_font(L);
+ luaopen_lang(L);
+
+ /* luaopen_img(L); */
+ lua_pushcfunction(L, luaopen_img);
+ lua_pushstring(L, "img");
+ lua_call(L, 1, 0);
+
+ luaopen_mp(L);
+
+ if (safer_option) {
+ /* disable some stuff if --safer */
+ (void)hide_lua_value(L, "os","execute");
+ (void)hide_lua_value(L, "os","rename");
+ (void)hide_lua_value(L, "os","remove");
+ (void)hide_lua_value(L, "io","popen");
+ /* make io.open only read files */
+ luaL_checkstack(L,2,"out of stack space");
+ lua_getglobal(L,"io");
+ lua_getfield(L,-1,"open_ro");
+ lua_setfield(L,-2,"open");
+ (void)hide_lua_value(L, "io","tmpfile");
+ (void)hide_lua_value(L, "io","output");
+ (void)hide_lua_value(L, "lfs","chdir");
+ (void)hide_lua_value(L, "lfs","lock");
+ (void)hide_lua_value(L, "lfs","touch");
+ (void)hide_lua_value(L, "lfs","rmdir");
+ (void)hide_lua_value(L, "lfs","mkdir");
+ }
+ Luas[n] = L;
+}
+
+int hide_lua_table(lua_State *L, char *name) {
+ int r=0;
+ lua_getglobal(L,name);
+ if(lua_istable(L,-1)) {
+ r = luaL_ref(L,LUA_REGISTRYINDEX);
+ lua_pushnil(L);
+ lua_setglobal(L,name);
+ }
+ return r;
+}
+
+void unhide_lua_table(lua_State *L, char *name, int r) {
+ lua_rawgeti(L,LUA_REGISTRYINDEX,r);
+ lua_setglobal(L,name);
+ luaL_unref(L,LUA_REGISTRYINDEX,r);
+}
+
+int hide_lua_value(lua_State *L, char *name, char *item) {
+ int r=0;
+ lua_getglobal(L,name);
+ if(lua_istable(L,-1)) {
+ lua_getfield(L,-1,item);
+ r = luaL_ref(L,LUA_REGISTRYINDEX);
+ lua_pushnil(L);
+ lua_setfield(L,-2,item);
+ }
+ return r;
+}
+
+void unhide_lua_value(lua_State *L, char *name, char *item, int r) {
+ lua_getglobal(L,name);
+ if(lua_istable(L,-1)) {
+ lua_rawgeti(L,LUA_REGISTRYINDEX,r);
+ lua_setfield(L,-2,item);
+ luaL_unref(L,LUA_REGISTRYINDEX,r);
+ }
+}
+
+
+void
+luacall(int n, int s) {
+ LoadS ls;
+ int i ;
+ char lua_id[12];
+ if (Luas[n] == NULL) {
+ luainterpreter(n);
+ }
+ luatex_load_init(s,&ls);
+ if (ls.size>0) {
+ snprintf((char *)lua_id,12,"luas[%d]",n);
+ i = lua_load(Luas[n], getS, &ls, lua_id);
+ if (i != 0) {
+ Luas[n] = luatex_error(Luas[n],(i == LUA_ERRSYNTAX ? 0 : 1));
+ } else {
+ i = lua_pcall(Luas[n], 0, 0, 0);
+ if (i != 0) {
+ Luas[n] = luatex_error(Luas[n],(i == LUA_ERRRUN ? 0 : 1));
+ }
+ }
+ }
+}
+
+void
+luatokencall(int n, int p) {
+ LoadS ls;
+ int i, l;
+ char *s=NULL;
+ char lua_id[12];
+ if (Luas[n] == NULL) {
+ luainterpreter(n);
+ }
+ l = 0;
+ s = tokenlist_to_cstring(p,1,&l);
+ ls.s = s;
+ ls.size = l;
+ if (ls.size>0) {
+ snprintf((char *)lua_id,12,"luas[%d]",n);
+ i = lua_load(Luas[n], getS, &ls, lua_id);
+ xfree(s);
+ if (i != 0) {
+ Luas[n] = luatex_error(Luas[n],(i == LUA_ERRSYNTAX ? 0 : 1));
+ } else {
+ i = lua_pcall(Luas[n], 0, 0, 0);
+ if (i != 0) {
+ Luas[n] = luatex_error(Luas[n],(i == LUA_ERRRUN ? 0 : 1));
+ }
+ }
+ }
+}
+
+
+
+void
+closelua(int n) {
+ if (n!=0 && Luas[n] != NULL) {
+ lua_close(Luas[n]);
+ luastate_max--;
+ Luas[n] = NULL;
+ }
+}
+
+
+void
+luatex_load_init (int s, LoadS *ls) {
+ ls->s = (const char *)&(str_pool[str_start[s]]);
+ ls->size = str_start[s + 1] - str_start[s];
+}
+
+lua_State *
+luatex_error (lua_State * L, int is_fatal) {
+
+ size_t len;
+ char *err;
+ strnumber s;
+ const char *luaerr = lua_tolstring(L, -1,&len);
+ err = (char *)xmalloc(len+1);
+ len = snprintf(err,(len+1),"%s",luaerr);
+ if (is_fatal>0) {
+ /* Normally a memory error from lua.
+ The pool may overflow during the maketexlstring(), but we
+ are crashing anyway so we may as well abort on the pool size */
+ s = maketexlstring(err, len);
+ lua_fatal_error(s);
+ /* never reached */
+ xfree (err);
+ lua_close(L);
+ luastate_max--;
+ return (lua_State *)NULL;
+ } else {
+ /* Here, the pool could be full already, but we can possibly escape from that
+ * condition, since the lua chunk that caused the error is the current string.
+ */
+ s = str_ptr-0x200000;
+ /* fprintf(stderr,"poolinfo: %d: %d,%d out of %d\n",s,pool_ptr,str_start[(s-1)],pool_size);*/
+ pool_ptr = str_start[(s-1)];
+ str_start[s] = pool_ptr;
+ if (pool_ptr+len>=pool_size) {
+ lua_norm_error(' ');
+ } else {
+ s = maketexlstring(err,len);
+ lua_norm_error(s);
+ flush_str(s);
+ }
+ xfree (err);
+ return L;
+ }
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/lua/luatex.c b/Build/source/texk/web2c/luatexdir/lua/luatex.c
new file mode 100644
index 00000000000..5172ca24292
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/luatex.c
@@ -0,0 +1,343 @@
+/* $Id: luatex.c 1013 2008-02-14 00:09:02Z oneiros $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+#include <zlib.h>
+
+/* do this aleph stuff here, for now */
+
+void
+b_test_in(void)
+{
+ string fname = kpse_find_file ((char *)(nameoffile + 1),
+ kpse_program_binary_format, true);
+
+ if (fname) {
+ libcfree(nameoffile);
+ nameoffile = xmalloc(2+strlen(fname));
+ namelength = strlen(fname);
+ strcpy((char *)nameoffile+1, fname);
+ }
+ else {
+ libcfree(nameoffile);
+ nameoffile = xmalloc(2);
+ namelength = 0;
+ nameoffile[0] = 0;
+ nameoffile[1] = 0;
+ }
+}
+
+
+int **ocp_tables;
+static int ocp_entries = 0;
+
+void
+allocate_ocp_table P2C(int, ocp_number, int, ocp_size)
+{
+ int i;
+ if (ocp_entries==0) {
+ ocp_tables = (int **) xmalloc(256*sizeof(int**));
+ ocp_entries=256;
+ } else if ((ocp_number==256)&&(ocp_entries==256)) {
+ ocp_tables = xrealloc(ocp_tables, 65536);
+ ocp_entries=65536;
+ }
+ ocp_tables[ocp_number] =
+ (int *) xmalloc((1+ocp_size)*sizeof(int));
+ ocp_tables[ocp_number][0] = ocp_size;
+ for (i=1; i<=ocp_size; i++) {
+ ocp_tables[ocp_number][i] = 0;
+ }
+}
+
+void
+dump_ocp_table P1C(int, ocp_number)
+{
+ dump_things(ocp_tables[ocp_number][0], ocp_tables[ocp_number][0]+1);
+}
+
+void
+undump_ocp_table P1C(int, ocp_number)
+{
+ int sizeword;
+ if (ocp_entries==0) {
+ ocp_tables = (int **) xmalloc(256*sizeof(int**));
+ ocp_entries=256;
+ } else if ((ocp_number==256)&&(ocp_entries==256)) {
+ ocp_tables = xrealloc(ocp_tables, 65536);
+ ocp_entries=65536;
+ }
+ undump_things(sizeword,1);
+ ocp_tables[ocp_number] =
+ (int *) xmalloc((1+sizeword)*sizeof(int));
+ ocp_tables[ocp_number][0] = sizeword;
+ undump_things(ocp_tables[ocp_number][1], sizeword);
+}
+
+
+void
+run_external_ocp P1C(string, external_ocp_name)
+{
+ char *in_file_name;
+ char *out_file_name;
+ FILE *in_file;
+ FILE *out_file;
+ char command_line[400];
+ int i;
+ unsigned c;
+ int c_in;
+#ifdef WIN32
+ char *tempenv;
+
+#define null_string(s) ((s == NULL) || (*s == '\0'))
+
+ tempenv = getenv("TMPDIR");
+ if (null_string(tempenv))
+ tempenv = getenv("TEMP");
+ if (null_string(tempenv))
+ tempenv = getenv("TMP");
+ if (null_string(tempenv))
+ tempenv = "c:/tmp"; /* "/tmp" is not good if we are on a CD-ROM */
+ in_file_name = concat(tempenv, "/__aleph__in__XXXXXX");
+ mktemp(in_file_name);
+#else
+ in_file_name = strdup("/tmp/__aleph__in__XXXXXX");
+ mkstemp(in_file_name);
+#endif /* WIN32 */
+
+ in_file = fopen(in_file_name, FOPEN_WBIN_MODE);
+
+ for (i=1; i<=otp_input_end; i++) {
+ c = otp_input_buf[i];
+ if (c>0xffff) {
+ fprintf(stderr, "Aleph does not currently support 31-bit chars\n");
+ exit(1);
+ }
+ if (c>0x4000000) {
+ fputc(0xfc | ((c>>30) & 0x1), in_file);
+ fputc(0x80 | ((c>>24) & 0x3f), in_file);
+ fputc(0x80 | ((c>>18) & 0x3f), in_file);
+ fputc(0x80 | ((c>>12) & 0x3f), in_file);
+ fputc(0x80 | ((c>>6) & 0x3f), in_file);
+ fputc(0x80 | (c & 0x3f), in_file);
+ } else if (c>0x200000) {
+ fputc(0xf8 | ((c>>24) & 0x3), in_file);
+ fputc(0x80 | ((c>>18) & 0x3f), in_file);
+ fputc(0x80 | ((c>>12) & 0x3f), in_file);
+ fputc(0x80 | ((c>>6) & 0x3f), in_file);
+ fputc(0x80 | (c & 0x3f), in_file);
+ } else if (c>0x10000) {
+ fputc(0xf0 | ((c>>18) & 0x7), in_file);
+ fputc(0x80 | ((c>>12) & 0x3f), in_file);
+ fputc(0x80 | ((c>>6) & 0x3f), in_file);
+ fputc(0x80 | (c & 0x3f), in_file);
+ } else if (c>0x800) {
+ fputc(0xe0 | ((c>>12) & 0xf), in_file);
+ fputc(0x80 | ((c>>6) & 0x3f), in_file);
+ fputc(0x80 | (c & 0x3f), in_file);
+ } else if (c>0x80) {
+ fputc(0xc0 | ((c>>6) & 0x1f), in_file);
+ fputc(0x80 | (c & 0x3f), in_file);
+ } else {
+ fputc(c & 0x7f, in_file);
+ }
+ }
+ fclose(in_file);
+
+#define advance_cin if ((c_in = fgetc(out_file)) == -1) { \
+ fprintf(stderr, "File contains bad char\n"); \
+ goto end_of_while; \
+ }
+
+#ifdef WIN32
+ out_file_name = concat(tempenv, "/__aleph__out__XXXXXX");
+ mktemp(out_file_name);
+#else
+ out_file_name = strdup("/tmp/__aleph__out__XXXXXX");
+ mkstemp(out_file_name);
+#endif
+
+ sprintf(command_line, "%s <%s >%s\n",
+ external_ocp_name+1, in_file_name, out_file_name);
+ system(command_line);
+ out_file = fopen(out_file_name, FOPEN_RBIN_MODE);
+ otp_output_end = 0;
+ otp_output_buf[otp_output_end] = 0;
+ while ((c_in = fgetc(out_file)) != -1) {
+ if (c_in>=0xfc) {
+ c = (c_in & 0x1) << 30;
+ {advance_cin}
+ c |= (c_in & 0x3f) << 24;
+ {advance_cin}
+ c |= (c_in & 0x3f) << 18;
+ {advance_cin}
+ c |= (c_in & 0x3f) << 12;
+ {advance_cin}
+ c |= (c_in & 0x3f) << 6;
+ {advance_cin}
+ c |= c_in & 0x3f;
+ } else if (c_in>=0xf8) {
+ c = (c_in & 0x3) << 24;
+ {advance_cin}
+ c |= (c_in & 0x3f) << 18;
+ {advance_cin}
+ c |= (c_in & 0x3f) << 12;
+ {advance_cin}
+ c |= (c_in & 0x3f) << 6;
+ {advance_cin}
+ c |= c_in & 0x3f;
+ } else if (c_in>=0xf0) {
+ c = (c_in & 0x7) << 18;
+ {advance_cin}
+ c |= (c_in & 0x3f) << 12;
+ {advance_cin}
+ c |= (c_in & 0x3f) << 6;
+ {advance_cin}
+ c |= c_in & 0x3f;
+ } else if (c_in>=0xe0) {
+ c = (c_in & 0xf) << 12;
+ {advance_cin}
+ c |= (c_in & 0x3f) << 6;
+ {advance_cin}
+ c |= c_in & 0x3f;
+ } else if (c_in>=0x80) {
+ c = (c_in & 0x1f) << 6;
+ {advance_cin}
+ c |= c_in & 0x3f;
+ } else {
+ c = c_in & 0x7f;
+ }
+ otp_output_buf[++otp_output_end] = c;
+ }
+
+end_of_while:
+ remove(in_file_name);
+ remove(out_file_name);
+}
+
+/* Read and write dump files through zlib */
+
+/* Earlier versions recast *f from FILE * to gzFile, but there is
+ * no guarantee that these have the same size, so a static variable
+ * is needed.
+ */
+
+static gzFile gz_fmtfile = NULL;
+
+void
+do_zdump (char *p, int item_size, int nitems, FILE *out_file)
+{
+ int err;
+ if (nitems==0)
+ return;
+ if (gzwrite (gz_fmtfile,(void *)p, item_size*nitems) != item_size*nitems)
+ {
+ fprintf (stderr, "! Could not write %d %d-byte item(s): %s.\n",
+ nitems, item_size, gzerror(gz_fmtfile,&err));
+ uexit (1);
+ }
+}
+
+void
+do_zundump (char *p, int item_size, int nitems, FILE *in_file)
+{
+ int err;
+ if (nitems==0)
+ return;
+ if (gzread (gz_fmtfile,(void *)p, item_size*nitems) <= 0)
+ {
+ fprintf (stderr, "Could not undump %d %d-byte item(s): %s.\n",
+ nitems, item_size, gzerror(gz_fmtfile,&err));
+ uexit (1);
+ }
+}
+
+#define COMPRESSION "R3"
+
+boolean
+zopen_w_input (FILE **f, int format, const_string fopen_mode) {
+ int callbackid;
+ int res;
+ char *fnam;
+ callbackid = callback_defined(find_format_file_callback);
+ if (callbackid>0) {
+ res = run_callback(callbackid,"S->S",(nameoffile+1),&fnam);
+ if (res && fnam && strlen(fnam)>0) {
+ xfree (nameoffile);
+ nameoffile = xmalloc (strlen(fnam)+2);
+ memcpy((nameoffile+1),fnam,strlen(fnam));
+ *(nameoffile+strlen(fnam)+1)=0;
+ *f = xfopen(fnam,fopen_mode);
+ if (*f == NULL) {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ } else {
+ res = open_input(f,format,fopen_mode);
+ }
+ if (res) {
+ gz_fmtfile = gzdopen(fileno(*f),"rb" COMPRESSION);
+ }
+ return res;
+}
+
+boolean
+zopen_w_output (FILE **f, const_string fopen_mode) {
+ int res = 1;
+ if (luainit) {
+ *f = fopen((nameoffile+1),fopen_mode);
+ if (*f == NULL) {
+ return 0;
+ }
+ } else {
+ res = open_output(f,fopen_mode);
+ }
+ if (res) {
+ gz_fmtfile = gzdopen(fileno(*f),"wb" COMPRESSION);
+ }
+ return res;
+}
+
+void
+zwclose (FILE *f) {
+ gzclose(gz_fmtfile);
+}
+
+/* create the dvi or pdf file */
+
+int
+open_outfile(FILE **f, char *name, char *mode) {
+ FILE *res;
+ res = fopen(name,mode);
+ if (res != NULL) {
+ *f = res;
+ return 1;
+ }
+ return 0;
+}
+
+
+/* the caller sets tfm_buffer=NULL and tfm_size=0 */
+
+int
+readbinfile (FILE *f, unsigned char **tfm_buffer, integer *tfm_size) {
+ void *buf;
+ int size;
+ if (fseek(f, 0, SEEK_END)==0) {
+ size = ftell(f);
+ if (size>0) {
+ buf = xmalloc(size);
+ if(fseek(f, 0, SEEK_SET)==0) {
+ if(fread((void *)buf,size,1,f)==1) {
+ *tfm_buffer=(unsigned char *)buf;
+ *tfm_size=(integer)size;
+ return 1;
+ }
+ }
+ }
+ } /* seek failed, or zero-sized file */
+ return 0;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/lua/luatoken.c b/Build/source/texk/web2c/luatexdir/lua/luatoken.c
new file mode 100644
index 00000000000..23d9ca82150
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/luatoken.c
@@ -0,0 +1,548 @@
+/* $Id: luatoken.c 1013 2008-02-14 00:09:02Z oneiros $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+#include "tokens.h"
+
+command_item command_names[] =
+ { { "relax", 0, NULL },
+ { "left_brace", 0 , NULL },
+ { "right_brace", 0 , NULL },
+ { "math_shift", 0 , NULL },
+ { "tab_mark", 0 , NULL },
+ { "car_ret", 0 , NULL },
+ { "mac_param", 0 , NULL },
+ { "sup_mark", 0 , NULL },
+ { "sub_mark", 0 , NULL },
+ { "endv", 0 , NULL },
+ { "spacer", 0 , NULL },
+ { "letter", 0 , NULL },
+ { "other_char", 0 , NULL },
+ { "par_end", 0 , NULL },
+ { "stop", 0 , NULL },
+ { "delim_num", 0 , NULL },
+ { "char_num", 0 , NULL },
+ { "math_char_num", 0 , NULL },
+ { "mark", 0 , NULL },
+ { "xray", 0 , NULL },
+ { "make_box", 0 , NULL },
+ { "hmove", 0 , NULL },
+ { "vmove", 0 , NULL },
+ { "un_hbox", 0 , NULL },
+ { "un_vbox", 0 , NULL },
+ { "remove_item", 0 , NULL },
+ { "hskip", 0 , NULL },
+ { "vskip", 0 , NULL },
+ { "mskip", 0 , NULL },
+ { "kern", 0 , NULL },
+ { "mkern", 0 , NULL },
+ { "leader_ship", 0 , NULL },
+ { "halign", 0 , NULL },
+ { "valign", 0 , NULL },
+ { "no_align", 0 , NULL },
+ { "vrule", 0 , NULL },
+ { "hrule", 0 , NULL },
+ { "insert", 0 , NULL },
+ { "vadjust", 0 , NULL },
+ { "ignore_spaces", 0 , NULL },
+ { "after_assignment", 0 , NULL },
+ { "after_group", 0 , NULL },
+ { "break_penalty", 0 , NULL },
+ { "start_par", 0 , NULL },
+ { "ital_corr", 0 , NULL },
+ { "accent", 0 , NULL },
+ { "math_accent", 0 , NULL },
+ { "discretionary", 0 , NULL },
+ { "eq_no", 0 , NULL },
+ { "left_right", 0 , NULL },
+ { "math_comp", 0 , NULL },
+ { "limit_switch", 0 , NULL },
+ { "above", 0 , NULL },
+ { "math_style", 0 , NULL },
+ { "math_choice", 0 , NULL },
+ { "non_script", 0 , NULL },
+ { "vcenter", 0 , NULL },
+ { "case_shift", 0 , NULL },
+ { "message", 0 , NULL },
+ { "extension", 0 , NULL },
+ { "in_stream", 0 , NULL },
+ { "begin_group", 0 , NULL },
+ { "end_group", 0 , NULL },
+ { "omit", 0 , NULL },
+ { "ex_space", 0 , NULL },
+ { "no_boundary", 0 , NULL },
+ { "radical", 0 , NULL },
+ { "end_cs_name", 0 , NULL },
+ { "char_ghost", 0 , NULL },
+ { "assign_local_box", 0 , NULL },
+ { "char_given", 0 , NULL },
+ { "math_given", 0 , NULL },
+ { "omath_given", 0 , NULL },
+ { "last_item", 0 , NULL },
+ { "toks_register", 0 , NULL },
+ { "assign_toks", 0, NULL },
+ { "assign_int", 0, NULL },
+ { "assign_dimen", 0 , NULL },
+ { "assign_glue", 0 ,NULL },
+ { "assign_mu_glue", 0 , NULL },
+ { "assign_font_dimen", 0 , NULL },
+ { "assign_font_int", 0 , NULL },
+ { "set_aux", 0 , NULL },
+ { "set_prev_graf", 0 , NULL },
+ { "set_page_dimen", 0 , NULL },
+ { "set_page_int", 0 , NULL },
+ { "set_box_dimen", 0 , NULL },
+ { "set_shape", 0, NULL },
+ { "def_code", 0 , NULL },
+ { "extdef_code", 0 , NULL },
+ { "def_family", 0 , NULL },
+ { "set_font", 0 , NULL },
+ { "def_font", 0 , NULL },
+ { "register", 0 , NULL },
+ { "assign_box_dir", 0 , NULL },
+ { "assign_dir", 0 , NULL },
+ { "advance", 0 , NULL },
+ { "multiply", 0 , NULL },
+ { "divide", 0 , NULL },
+ { "prefix", 0 , NULL },
+ { "let", 0 , NULL }, /* 100 */
+ { "shorthand_def", 0 , NULL },
+ { "read_to_cs", 0 , NULL },
+ { "def", 0 , NULL },
+ { "set_box", 0 , NULL },
+ { "hyph_data", 0 , NULL },
+ { "set_interaction", 0 , NULL },
+ { "letterspace_font", 0 , NULL },
+ { "set_ocp", 0 , NULL },
+ { "def_ocp", 0 , NULL },
+ { "set_ocp_list", 0 , NULL }, /* 110 */
+ { "def_ocp_list", 0 , NULL },
+ { "clear_ocp_lists", 0 , NULL },
+ { "push_ocp_list", 0 , NULL },
+ { "pop_ocp_list", 0 , NULL },
+ { "ocp_list_op", 0 , NULL },
+ { "ocp_trace_level", 0 , NULL},
+ { "undefined_cs", 0 , NULL },
+ { "expand_after", 0 , NULL },
+ { "no_expand", 0 , NULL },
+ { "input", 0 , NULL }, /* 120 */
+ { "if_test", 0 , NULL },
+ { "fi_or_else", 0 , NULL },
+ { "cs_name", 0 , NULL },
+ { "convert", 0 , NULL },
+ { "the", 0 , NULL },
+ { "top_bot_mark", 0 , NULL },
+ { "call", 0 , NULL },
+ { "long_call", 0 , NULL },
+ { "outer_call", 0 , NULL },
+ { "long_outer_call", 0 , NULL }, /* 130 */
+ { "end_template", 0 , NULL },
+ { "dont_expand", 0, NULL },
+ { "glue_ref", 0 , NULL },
+ { "shape_ref", 0 , NULL },
+ { "box_ref", 0 , NULL },
+ { "data", 0 , NULL },
+ { NULL, 0, NULL } };
+
+
+int get_command_id (char *s) {
+ int i;
+ int cmd = -1;
+ for (i=0;command_names[i].cmd_name != NULL;i++) {
+ if (strcmp(s,command_names[i].cmd_name) == 0)
+ break;
+ }
+ if (command_names[i].cmd_name!=NULL) {
+ cmd = i;
+ }
+ return cmd;
+}
+
+static int
+get_cur_cmd (lua_State *L) {
+ int r = 0;
+ cur_cs = 0;
+ int len = lua_objlen(L,-1);
+ if (len==3 || len==2) {
+ r = 1;
+ lua_rawgeti(L,-1,1);
+ cur_cmd = lua_tointeger(L,-1);
+ lua_rawgeti(L,-2,2);
+ cur_chr = lua_tointeger(L,-1);
+ if (len==3) {
+ lua_rawgeti(L,-3,3);
+ cur_cs = lua_tointeger(L,-1);
+ }
+ lua_pop(L,len);
+ if (cur_cs==0)
+ cur_tok=(cur_cmd*string_offset)+cur_chr;
+ else
+ cur_tok=cs_token_flag+cur_cs;
+ }
+ return r;
+}
+
+
+static int
+token_from_lua (lua_State *L) {
+ int cmd,chr;
+ int cs = 0;
+ int len = lua_objlen(L,-1);
+ if (len==3 || len==2) {
+ lua_rawgeti(L,-1,1);
+ cmd = lua_tointeger(L,-1);
+ lua_rawgeti(L,-2,2);
+ chr = lua_tointeger(L,-1);
+ if (len==3) {
+ lua_rawgeti(L,-3,3);
+ cs = lua_tointeger(L,-1);
+ }
+ lua_pop(L,len);
+ if (cs==0) {
+ return (cmd*string_offset)+chr;
+ } else {
+ return cs_token_flag+cs;
+ }
+ }
+ return -1;
+}
+
+static int
+get_cur_cs (lua_State *L) {
+ char *s;
+ unsigned j;
+ size_t l;
+ integer cs;
+ int save_nncs;
+ int ret;
+ ret = 0;
+ cur_cs = 0;
+ lua_getfield(L,-1,"name");
+ if (lua_isstring(L,-1)) {
+ s = (char *)lua_tolstring(L,-1,&l);
+ if (l>0) {
+ if (last+l>buf_size)
+ check_buffer_overflow(last+l);
+ for (j=0;j<l;j++) {
+ buffer[last+1+j]=*s++;
+ }
+ save_nncs = no_new_control_sequence;
+ no_new_control_sequence = false;
+ cs = id_lookup((last+1),l);
+ cur_tok = cs_token_flag+cs;
+ cur_cmd = zget_eq_type(cs);
+ cur_chr = zget_equiv(cs);
+ no_new_control_sequence = save_nncs;
+ ret = 1;
+ }
+ }
+ lua_pop(L,1);
+ return ret;
+}
+
+
+#define append_i_byte(a) { \
+ if ((i+2)>alloci) { \
+ ret = xrealloc(ret,alloci+64); \
+ alloci = alloci + 64; } \
+ ret[i++] = a; }
+
+#define Print_char(a) append_i_byte(a)
+
+#define Print_uchar(s) { \
+ if (s<=0x7F) { \
+ Print_char(s); \
+ } else if (s<=0x7FF) { \
+ Print_char(0xC0 + (s / 0x40)); \
+ Print_char(0x80 + (s % 0x40)); \
+ } else if (s<=0xFFFF) { \
+ Print_char(0xE0 + (s / 0x1000)); \
+ Print_char(0x80 + ((s % 0x1000) / 0x40)); \
+ Print_char(0x80 + ((s % 0x1000) % 0x40)); \
+ } else if (s>=0x10FF00) { \
+ Print_char(s-0x10FF00); \
+ } else { \
+ Print_char(0xF0 + (s / 0x40000)); \
+ Print_char(0x80 + ((s % 0x40000) / 0x1000)); \
+ Print_char(0x80 + (((s % 0x40000) % 0x1000) / 0x40)); \
+ Print_char(0x80 + (((s % 0x40000) % 0x1000) % 0x40)); \
+ } }
+
+
+#define Print_esc(b) { if (e>0 && e<string_offset) { Print_uchar (e); Print_uchar (e); } \
+ { char *v = b; while (*v) { Print_char(*v); v++; } } }
+
+#define single_letter(a) (length(a)==1)|| \
+ ((length(a)==4)&&(str_pool[str_start_macro(a)]>=0xF0))|| \
+ ((length(a)==3)&&(str_pool[str_start_macro(a)]>=0xE0))|| \
+ ((length(a)==2)&&(str_pool[str_start_macro(a)]>=0xC0))
+
+#define is_cat_letter(a) \
+ (get_char_cat_code(pool_to_unichar(str_start_macro(a))) == 11)
+
+static int active_base = 0;
+static int hash_base = 0;
+static int eqtb_size = 0;
+static int null_cs = 0;
+static int undefined_control_sequence;
+
+char *
+tokenlist_to_cstring ( int p , int inhibit_par, int *siz) {
+ integer m, c ;
+ integer q;
+ char *s;
+ int e;
+ char *ret=NULL;
+ int match_chr = '#';
+ int n = '0';
+ int alloci = 0;
+ int i = 0;
+ if (p==null || link(p)==null) {
+ if (siz!=NULL)
+ *siz = 0;
+ return NULL;
+ }
+ p = link(p); /* skip refcount */
+ if (active_base==0) {
+ active_base = get_active_base();
+ hash_base = get_hash_base();
+ null_cs = get_nullcs();
+ eqtb_size = get_eqtb_size();
+ undefined_control_sequence = get_undefined_control_sequence();
+ }
+ e = get_escape_char();
+ while ( p != null ) {
+ if (p < fix_mem_min || p > fix_mem_end ) {
+ Print_esc ("CLOBBERED.") ;
+ break;
+ }
+ if (info(p)>=cs_token_flag) {
+ if ( ! (inhibit_par && info(p)==par_token) ) {
+ q = info(p) - cs_token_flag;
+ if (q<hash_base) {
+ if (q==null_cs) {
+ /* Print_esc("csname"); Print_esc("endcsname"); */
+ } else {
+ if (q<active_base) {
+ Print_esc("IMPOSSIBLE.");
+ } else {
+ Print_uchar(q-active_base);
+ }
+ }
+ } else if ((q>=undefined_control_sequence)&&((q<=eqtb_size))||(q>eqtb_size+hash_extra)) {
+ Print_esc("IMPOSSIBLE.");
+ } else if ((zget_cs_text(q)<0)||(zget_cs_text(q)>=str_ptr)) {
+ Print_esc("NONEXISTENT.");
+ } else {
+ Print_uchar (e);
+ s = makecstring(zget_cs_text(q));
+ while (*s) { Print_char(*s); s++; }
+ if ((! single_letter(zget_cs_text(q))) || is_cat_letter(zget_cs_text(q))) {
+ Print_char(' ');
+ }
+ }
+ }
+ } else {
+ m=info(p) / string_offset;
+ c=info(p) % string_offset;
+ if ( info(p) < 0 ) {
+ Print_esc ( "BAD.") ;
+ } else {
+ switch ( m ) {
+ case 6 : /* falls through */
+ Print_uchar ( c ) ;
+ case 1 :
+ case 2 :
+ case 3 :
+ case 4 :
+ case 7 :
+ case 8 :
+ case 10 :
+ case 11 :
+ case 12 :
+ Print_uchar ( c ) ;
+ break ;
+ case 5 :
+ Print_uchar ( match_chr ) ;
+ if ( c <= 9 ) {
+ Print_char ( c + '0') ;
+ } else {
+ Print_char ( '!' ) ;
+ return NULL;
+ }
+ break ;
+ case 13 :
+ match_chr = c ;
+ Print_uchar ( c ) ;
+ incr ( n ) ;
+ Print_char ( n ) ;
+ if ( n > '9' )
+ return NULL;
+ break ;
+ case 14 :
+ if ( c == 0 ) {
+ Print_char ('-');
+ Print_char ('>') ;
+ }
+ break ;
+ default:
+ Print_esc ( "BAD.") ;
+ break ;
+ }
+ }
+ }
+ p = link(p);
+ }
+ ret[i]=0;
+ if (siz!=NULL)
+ *siz = i;
+ return ret;
+}
+
+
+void
+tokenlist_to_lua(lua_State *L, int p) {
+ int cmd,chr,cs;
+ int v;
+ int i = 1;
+ v = p;
+ while (v!=null && v < fix_mem_end) { i++; v = link(v); }
+ i = 1;
+ lua_createtable(L,i,0);
+ while (p!=null&& p < fix_mem_end) {
+ if (info(p)>=cs_token_flag) {
+ cs=info(p)-cs_token_flag;
+ cmd = zget_eq_type(cs);
+ chr = zget_equiv(cs);
+ make_token_table(L,cmd,chr,cs);
+ } else {
+ cmd=info(p) / string_offset;
+ chr=info(p) % string_offset;
+ make_token_table(L,cmd,chr,0);
+ }
+ lua_rawseti(L,-2,i++);
+ p = link(p);
+ }
+}
+
+
+void
+tokenlist_to_luastring(lua_State *L, int p) {
+ int l;
+ char *s;
+ s = tokenlist_to_cstring(p,1,&l);
+ lua_pushlstring(L,s,l);
+}
+
+
+int
+tokenlist_from_lua(lua_State *L) {
+ char *s;
+ int tok,i;
+ size_t j;
+ halfword p,q,r;
+ r = get_avail();
+ info(r)=0; /* ref count */
+ link(r)=null;
+ p = r;
+ if (lua_istable(L,-1)) {
+ j = lua_objlen(L,-1);
+ if (j>0) {
+ for (i=1;i<=j;i++) {
+ lua_rawgeti(L,-1,i);
+ tok = token_from_lua(L);
+ if (tok>=0) {
+ store_new_token(tok);
+ }
+ lua_pop(L,1);
+ };
+ }
+ return r;
+ } else if (lua_isstring(L,-1)) {
+ s = (char *)lua_tolstring(L,-1,&j);
+ for (i=0;i<j;i++) {
+ if (s[i] == 32) {
+ tok = (10*string_offset)+s[i];
+ } else {
+ tok = (12*string_offset)+s[i];
+ }
+ store_new_token(tok);
+ }
+ return r;
+ } else {
+ free_avail(r);
+ return null;
+ }
+}
+
+void
+do_get_token_lua (integer callback_id) {
+ lua_State *L = Luas[0];
+
+ lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id);
+ while (1) {
+ lua_rawgeti(L,-1, callback_id);
+ if (!lua_isfunction(L,-1)) {
+ lua_pop(L,2); /* the not-a-function callback and the container */
+ get_next();
+ return;
+ }
+ if (lua_pcall(L,0,1,0) != 0) { /* no arg, 1 result */
+ fprintf(stdout,"error: %s\n",lua_tostring(L,-1));
+ lua_pop(L,2);
+ error();
+ return;
+ }
+ if (lua_istable(L,-1)) {
+ lua_rawgeti(L,-1,1);
+ if (lua_istable(L,-1)) {
+ integer p,q,r;
+ int i,j;
+ lua_pop(L,1);
+ /* build a token list */
+ r = get_avail();
+ p = r;
+ j = lua_objlen(L,-1);
+ if (j>0) {
+ for (i=1;i<=j;i++) {
+ lua_rawgeti(L,-1,i);
+ if (get_cur_cmd(L) || get_cur_cs(L)) {
+ store_new_token(cur_tok);
+ }
+ lua_pop(L,1);
+ }
+ }
+ if (p!=r) {
+ p = link(r);
+ free_avail(r);
+ begin_token_list(p, inserted);
+ cur_input.nofilter_field=true;
+ get_next();
+ lua_pop(L,1);
+ break;
+ } else {
+ fprintf(stdout,"error: illegal or empty token list returned\n");
+ lua_pop(L,2);
+ error();
+ return;
+ }
+ } else {
+ lua_pop(L,1);
+ if (get_cur_cmd(L) || get_cur_cs(L)) {
+ lua_pop(L,1);
+ break;
+ } else {
+ lua_pop(L,2);
+ continue;
+ }
+ }
+ } else {
+ lua_pop(L,1);
+ continue;
+ }
+ }
+ lua_pop(L,1); /* callback container */
+ return;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/lua/mp.w b/Build/source/texk/web2c/luatexdir/lua/mp.w
new file mode 100644
index 00000000000..a459cc48fe1
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/mp.w
@@ -0,0 +1,26173 @@
+% $Id: mp.web,v 1.8 2005/08/24 10:54:02 taco Exp $
+% MetaPost, by John Hobby. Public domain.
+
+% Much of this program was copied with permission from MF.web Version 1.9
+% It interprets a language very similar to D.E. Knuth's METAFONT, but with
+% changes designed to make it more suitable for PostScript output.
+
+% TeX is a trademark of the American Mathematical Society.
+% METAFONT is a trademark of Addison-Wesley Publishing Company.
+% PostScript is a trademark of Adobe Systems Incorporated.
+
+% Here is TeX material that gets inserted after \input webmac
+\def\hang{\hangindent 3em\noindent\ignorespaces}
+\def\textindent#1{\hangindent2.5em\noindent\hbox to2.5em{\hss#1 }\ignorespaces}
+\def\ps{PostScript}
+\def\psqrt#1{\sqrt{\mathstrut#1}}
+\def\k{_{k+1}}
+\def\pct!{{\char`\%}} % percent sign in ordinary text
+\font\tenlogo=logo10 % font used for the METAFONT logo
+\font\logos=logosl10
+\def\MF{{\tenlogo META}\-{\tenlogo FONT}}
+\def\MP{{\tenlogo META}\-{\tenlogo POST}}
+\def\[#1]{\ignorespaces} % left over from pascal web
+\def\<#1>{$\langle#1\rangle$}
+\def\section{\mathhexbox278}
+\let\swap=\leftrightarrow
+\def\round{\mathop{\rm round}\nolimits}
+\mathchardef\vb="026A % synonym for `\|'
+
+\def\(#1){} % this is used to make section names sort themselves better
+\def\9#1{} % this is used for sort keys in the index via @@:sort key}{entry@@>
+\def\title{MetaPost}
+\pdfoutput=1
+\pageno=3
+
+@* \[1] Introduction.
+
+This is \MP, a graphics-language processor based on D. E. Knuth's \MF.
+
+The main purpose of the following program is to explain the algorithms of \MP\
+as clearly as possible. However, the program has been written so that it
+can be tuned to run efficiently in a wide variety of operating environments
+by making comparatively few changes. Such flexibility is possible because
+the documentation that follows is written in the \.{WEB} language, which is
+at a higher level than C.
+
+A large piece of software like \MP\ has inherent complexity that cannot
+be reduced below a certain level of difficulty, although each individual
+part is fairly simple by itself. The \.{WEB} language is intended to make
+the algorithms as readable as possible, by reflecting the way the
+individual program pieces fit together and by providing the
+cross-references that connect different parts. Detailed comments about
+what is going on, and about why things were done in certain ways, have
+been liberally sprinkled throughout the program. These comments explain
+features of the implementation, but they rarely attempt to explain the
+\MP\ language itself, since the reader is supposed to be familiar with
+{\sl The {\logos METAFONT\/}book} as well as the manual
+@.WEB@>
+@:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
+{\sl A User's Manual for MetaPost}, Computing Science Technical Report 162,
+AT\AM T Bell Laboratories.
+
+@ The present implementation is a preliminary version, but the possibilities
+for new features are limited by the desire to remain as nearly compatible
+with \MF\ as possible.
+
+On the other hand, the \.{WEB} description can be extended without changing
+the core of the program, and it has been designed so that such
+extensions are not extremely difficult to make.
+The |banner| string defined here should be changed whenever \MP\
+undergoes any modifications, so that it will be clear which version of
+\MP\ might be the guilty party when a problem arises.
+@^extensions to \MP@>
+@^system dependencies@>
+
+@d banner "This is MetaPost, Version 1.003" /* printed when \MP\ starts */
+@d metapost_version "1.003"
+@d mplib_version "0.30"
+@d version_string " (Cweb version 0.30)"
+
+@d true 1
+@d false 0
+
+@ The external library header for \MP\ is |mplib.h|. It contains a
+few typedefs and the header defintions for the externally used
+fuctions.
+
+The most important of the typedefs is the definition of the structure
+|MP_options|, that acts as a small, configurable front-end to the fairly
+large |MP_instance| structure.
+
+@(mplib.h@>=
+typedef struct MP_instance * MP;
+@<Exported types@>
+typedef struct MP_options {
+ @<Option variables@>
+} MP_options;
+@<Exported function headers@>
+
+@ The internal header file is much longer: it not only lists the complete
+|MP_instance|, but also a lot of functions that have to be available to
+the \ps\ backend, that is defined in a separate \.{WEB} file.
+
+The variables from |MP_options| are included inside the |MP_instance|
+wholesale.
+
+@(mpmp.h@>=
+#include <setjmp.h>
+typedef struct psout_data_struct * psout_data;
+typedef int boolean;
+typedef signed int integer;
+@<Declare helpers@>
+@<Types in the outer block@>
+@<Constants in the outer block@>
+# ifndef LIBAVL_ALLOCATOR
+# define LIBAVL_ALLOCATOR
+ struct libavl_allocator {
+ void *(*libavl_malloc) (struct libavl_allocator *, size_t libavl_size);
+ void (*libavl_free) (struct libavl_allocator *, void *libavl_block);
+ };
+# endif
+typedef struct MP_instance {
+ @<Option variables@>
+ @<Global variables@>
+} MP_instance;
+@<Internal library declarations@>
+
+@ @c
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <unistd.h> /* for access() */
+#include <time.h> /* for struct tm \& co */
+#include "mplib.h"
+#include "mpmp.h" /* internal header */
+#include "mppsout.h" /* internal header */
+@h
+@<Declarations@>
+@<Basic printing procedures@>
+@<Error handling procedures@>
+
+@ Here are the functions that set up the \MP\ instance.
+
+@<Declarations@> =
+@<Declare |mp_reallocate| functions@>
+struct MP_options *mp_options (void);
+MP mp_new (struct MP_options *opt);
+
+@ @c
+struct MP_options *mp_options (void) {
+ struct MP_options *opt;
+ opt = malloc(sizeof(MP_options));
+ if (opt!=NULL) {
+ memset (opt,0,sizeof(MP_options));
+ }
+ return opt;
+}
+
+@ The |__attribute__| pragma is gcc-only.
+
+@<Internal library ... @>=
+#if !defined(__GNUC__) || (__GNUC__ < 2)
+# define __attribute__(x)
+#endif /* !defined(__GNUC__) || (__GNUC__ < 2) */
+
+@ @c
+MP __attribute__ ((noinline))
+mp_new (struct MP_options *opt) {
+ MP mp;
+ mp = malloc(1*sizeof(MP_instance));
+ if (mp==NULL)
+ return mp;
+ @<Set |ini_version|@>;
+ @<Setup the non-local jump buffer in |mp_new|@>;
+ @<Allocate or initialize variables@>
+ if (opt->main_memory>mp->mem_max)
+ mp_reallocate_memory(mp,opt->main_memory);
+ mp_reallocate_paths(mp,1000);
+ mp_reallocate_fonts(mp,8);
+ return mp;
+}
+
+@ @c
+void mp_free (MP mp) {
+ int k; /* loop variable */
+ @<Dealloc variables@>
+ xfree(mp);
+}
+
+@ @c
+void __attribute__((noinline))
+mp_do_initialize ( MP mp) {
+ @<Local variables for initialization@>
+ @<Set initial values of key variables@>
+}
+int mp_initialize (MP mp) { /* this procedure gets things started properly */
+ mp->history=mp_fatal_error_stop; /* in case we quit during initialization */
+ @<Install and test the non-local jump buffer@>;
+ t_open_out; /* open the terminal for output */
+ @<Check the ``constant'' values...@>;
+ if ( mp->bad>0 ) {
+ char ss[256];
+ snprintf(ss,256,"Ouch---my internal constants have been clobbered!\n"
+ "---case %i",(int)mp->bad);
+ do_fprintf(mp->err_out,(char *)ss);
+@.Ouch...clobbered@>
+ return mp->history;
+ }
+ mp_do_initialize(mp); /* erase preloaded mem */
+ if (mp->ini_version) {
+ @<Run inimpost commands@>;
+ }
+ @<Initialize the output routines@>;
+ @<Get the first line of input and prepare to start@>;
+ mp_set_job_id(mp);
+ mp_init_map_file(mp, mp->troff_mode);
+ mp->history=mp_spotless; /* ready to go! */
+ if (mp->troff_mode) {
+ mp->internal[mp_gtroffmode]=unity;
+ mp->internal[mp_prologues]=unity;
+ }
+ if ( mp->start_sym>0 ) { /* insert the `\&{everyjob}' symbol */
+ mp->cur_sym=mp->start_sym; mp_back_input(mp);
+ }
+ return mp->history;
+}
+
+@
+@<Exported function headers@>=
+extern struct MP_options *mp_options (void);
+extern MP mp_new (struct MP_options *opt) ;
+extern void mp_free (MP mp);
+extern int mp_initialize (MP mp);
+
+@ The overall \MP\ program begins with the heading just shown, after which
+comes a bunch of procedure declarations and function declarations.
+Finally we will get to the main program, which begins with the
+comment `|start_here|'. If you want to skip down to the
+main program now, you can look up `|start_here|' in the index.
+But the author suggests that the best way to understand this program
+is to follow pretty much the order of \MP's components as they appear in the
+\.{WEB} description you are now reading, since the present ordering is
+intended to combine the advantages of the ``bottom up'' and ``top down''
+approaches to the problem of understanding a somewhat complicated system.
+
+@ Some of the code below is intended to be used only when diagnosing the
+strange behavior that sometimes occurs when \MP\ is being installed or
+when system wizards are fooling around with \MP\ without quite knowing
+what they are doing. Such code will not normally be compiled; it is
+delimited by the preprocessor test `|#ifdef DEBUG .. #endif|'.
+
+@ This program has two important variations: (1) There is a long and slow
+version called \.{INIMP}, which does the extra calculations needed to
+@.INIMP@>
+initialize \MP's internal tables; and (2)~there is a shorter and faster
+production version, which cuts the initialization to a bare minimum.
+
+Which is which is decided at runtime.
+
+@ The following parameters can be changed at compile time to extend or
+reduce \MP's capacity. They may have different values in \.{INIMP} and
+in production versions of \MP.
+@.INIMP@>
+@^system dependencies@>
+
+@<Constants...@>=
+#define file_name_size 255 /* file names shouldn't be longer than this */
+#define bistack_size 1500 /* size of stack for bisection algorithms;
+ should probably be left at this value */
+
+@ Like the preceding parameters, the following quantities can be changed
+at compile time to extend or reduce \MP's capacity. But if they are changed,
+it is necessary to rerun the initialization program \.{INIMP}
+@.INIMP@>
+to generate new tables for the production \MP\ program.
+One can't simply make helter-skelter changes to the following constants,
+since certain rather complex initialization
+numbers are computed from them.
+
+@ @<Glob...@>=
+int max_strings; /* maximum number of strings; must not exceed |max_halfword| */
+int pool_size; /* maximum number of characters in strings, including all
+ error messages and help texts, and the names of all identifiers */
+int mem_max; /* greatest index in \MP's internal |mem| array;
+ must be strictly less than |max_halfword|;
+ must be equal to |mem_top| in \.{INIMP}, otherwise |>=mem_top| */
+int mem_top; /* largest index in the |mem| array dumped by \.{INIMP};
+ must not be greater than |mem_max| */
+
+@ @<Option variables@>=
+int error_line; /* width of context lines on terminal error messages */
+int half_error_line; /* width of first lines of contexts in terminal
+ error messages; should be between 30 and |error_line-15| */
+int max_print_line; /* width of longest text lines output; should be at least 60 */
+int hash_size; /* maximum number of symbolic tokens,
+ must be less than |max_halfword-3*param_size| */
+int hash_prime; /* a prime number equal to about 85\pct! of |hash_size| */
+int param_size; /* maximum number of simultaneous macro parameters */
+int max_in_open; /* maximum number of input files and error insertions that
+ can be going on simultaneously */
+int main_memory; /* only for options, to set up |mem_max| and |mem_top| */
+void *userdata; /* this allows the calling application to setup local */
+
+@
+@d set_value(a,b,c) do { a=c; if (b>c) a=b; } while (0)
+
+@<Allocate or ...@>=
+mp->max_strings=500;
+mp->pool_size=10000;
+set_value(mp->error_line,opt->error_line,79);
+set_value(mp->half_error_line,opt->half_error_line,50);
+set_value(mp->max_print_line,opt->max_print_line,100);
+mp->main_memory=5000;
+mp->mem_max=5000;
+mp->mem_top=5000;
+set_value(mp->hash_size,opt->hash_size,9500);
+set_value(mp->hash_prime,opt->hash_prime,7919);
+set_value(mp->param_size,opt->param_size,150);
+set_value(mp->max_in_open,opt->max_in_open,10);
+mp->userdata=opt->userdata;
+
+@ In case somebody has inadvertently made bad settings of the ``constants,''
+\MP\ checks them using a global variable called |bad|.
+
+This is the first of many sections of \MP\ where global variables are
+defined.
+
+@<Glob...@>=
+integer bad; /* is some ``constant'' wrong? */
+
+@ Later on we will say `\ignorespaces|if (mem_max>=max_halfword) bad=10;|',
+or something similar. (We can't do that until |max_halfword| has been defined.)
+
+@<Check the ``constant'' values for consistency@>=
+mp->bad=0;
+if ( (mp->half_error_line<30)||(mp->half_error_line>mp->error_line-15) ) mp->bad=1;
+if ( mp->max_print_line<60 ) mp->bad=2;
+if ( mp->mem_top<=1100 ) mp->bad=4;
+if (mp->hash_prime>mp->hash_size ) mp->bad=5;
+
+@ Some |goto| labels are used by the following definitions. The label
+`|restart|' is occasionally used at the very beginning of a procedure; and
+the label `|reswitch|' is occasionally used just prior to a |case|
+statement in which some cases change the conditions and we wish to branch
+to the newly applicable case. Loops that are set up with the |loop|
+construction defined below are commonly exited by going to `|done|' or to
+`|found|' or to `|not_found|', and they are sometimes repeated by going to
+`|continue|'. If two or more parts of a subroutine start differently but
+end up the same, the shared code may be gathered together at
+`|common_ending|'.
+
+@ Here are some macros for common programming idioms.
+
+@d incr(A) (A)=(A)+1 /* increase a variable by unity */
+@d decr(A) (A)=(A)-1 /* decrease a variable by unity */
+@d negate(A) (A)=-(A) /* change the sign of a variable */
+@d double(A) (A)=(A)+(A)
+@d odd(A) ((A)%2==1)
+@d chr(A) (A)
+@d do_nothing /* empty statement */
+@d Return goto exit /* terminate a procedure call */
+@f return nil /* \.{WEB} will henceforth say |return| instead of \\{return} */
+
+@* \[2] The character set.
+In order to make \MP\ readily portable to a wide variety of
+computers, all of its input text is converted to an internal eight-bit
+code that includes standard ASCII, the ``American Standard Code for
+Information Interchange.'' This conversion is done immediately when each
+character is read in. Conversely, characters are converted from ASCII to
+the user's external representation just before they are output to a
+text file.
+@^ASCII code@>
+
+Such an internal code is relevant to users of \MP\ only with respect to
+the \&{char} and \&{ASCII} operations, and the comparison of strings.
+
+@ Characters of text that have been converted to \MP's internal form
+are said to be of type |ASCII_code|, which is a subrange of the integers.
+
+@<Types...@>=
+typedef unsigned char ASCII_code; /* eight-bit numbers */
+
+@ The present specification of \MP\ has been written under the assumption
+that the character set contains at least the letters and symbols associated
+with ASCII codes 040 through 0176; all of these characters are now
+available on most computer terminals.
+
+We shall use the name |text_char| to stand for the data type of the characters
+that are converted to and from |ASCII_code| when they are input and output.
+We shall also assume that |text_char| consists of the elements
+|chr(first_text_char)| through |chr(last_text_char)|, inclusive.
+The following definitions should be adjusted if necessary.
+@^system dependencies@>
+
+@d first_text_char 0 /* ordinal number of the smallest element of |text_char| */
+@d last_text_char 255 /* ordinal number of the largest element of |text_char| */
+
+@<Types...@>=
+typedef unsigned char text_char; /* the data type of characters in text files */
+
+@ @<Local variables for init...@>=
+integer i;
+
+@ The \MP\ processor converts between ASCII code and
+the user's external character set by means of arrays |xord| and |xchr|
+that are analogous to Pascal's |ord| and |chr| functions.
+
+@d xchr(A) mp->xchr[(A)]
+@d xord(A) mp->xord[(A)]
+
+@<Glob...@>=
+ASCII_code xord[256]; /* specifies conversion of input characters */
+text_char xchr[256]; /* specifies conversion of output characters */
+
+@ The core system assumes all 8-bit is acceptable. If it is not,
+a change file has to alter the below section.
+@^system dependencies@>
+
+Additionally, people with extended character sets can
+assign codes arbitrarily, giving an |xchr| equivalent to whatever
+characters the users of \MP\ are allowed to have in their input files.
+Appropriate changes to \MP's |char_class| table should then be made.
+(Unlike \TeX, each installation of \MP\ has a fixed assignment of category
+codes, called the |char_class|.) Such changes make portability of programs
+more difficult, so they should be introduced cautiously if at all.
+@^character set dependencies@>
+@^system dependencies@>
+
+@<Set initial ...@>=
+for (i=0;i<=0377;i++) { xchr(i)=i; }
+
+@ The following system-independent code makes the |xord| array contain a
+suitable inverse to the information in |xchr|. Note that if |xchr[i]=xchr[j]|
+where |i<j<0177|, the value of |xord[xchr[i]]| will turn out to be
+|j| or more; hence, standard ASCII code numbers will be used instead of
+codes below 040 in case there is a coincidence.
+
+@<Set initial ...@>=
+for (i=first_text_char;i<=last_text_char;i++) {
+ xord(chr(i))=0177;
+}
+for (i=0200;i<=0377;i++) { xord(xchr(i))=i;}
+for (i=0;i<=0176;i++) { xord(xchr(i))=i;}
+
+@* \[3] Input and output.
+The bane of portability is the fact that different operating systems treat
+input and output quite differently, perhaps because computer scientists
+have not given sufficient attention to this problem. People have felt somehow
+that input and output are not part of ``real'' programming. Well, it is true
+that some kinds of programming are more fun than others. With existing
+input/output conventions being so diverse and so messy, the only sources of
+joy in such parts of the code are the rare occasions when one can find a
+way to make the program a little less bad than it might have been. We have
+two choices, either to attack I/O now and get it over with, or to postpone
+I/O until near the end. Neither prospect is very attractive, so let's
+get it over with.
+
+The basic operations we need to do are (1)~inputting and outputting of
+text, to or from a file or the user's terminal; (2)~inputting and
+outputting of eight-bit bytes, to or from a file; (3)~instructing the
+operating system to initiate (``open'') or to terminate (``close'') input or
+output from a specified file; (4)~testing whether the end of an input
+file has been reached; (5)~display of bits on the user's screen.
+The bit-display operation will be discussed in a later section; we shall
+deal here only with more traditional kinds of I/O.
+
+@ Finding files happens in a slightly roundabout fashion: the \MP\
+instance object contains a field that holds a function pointer that finds a
+file, and returns its name, or NULL. For this, it receives three
+parameters: the non-qualified name |fname|, the intended |fopen|
+operation type |fmode|, and the type of the file |ftype|.
+
+The file types that are passed on in |ftype| can be used to
+differentiate file searches if a library like kpathsea is used,
+the fopen mode is passed along for the same reason.
+
+@<Types...@>=
+typedef unsigned char eight_bits ; /* unsigned one-byte quantity */
+
+@ @<Exported types@>=
+enum mp_filetype {
+ mp_filetype_terminal = 0, /* the terminal */
+ mp_filetype_error, /* the terminal */
+ mp_filetype_program , /* \MP\ language input */
+ mp_filetype_log, /* the log file */
+ mp_filetype_postscript, /* the postscript output */
+ mp_filetype_memfile, /* memory dumps */
+ mp_filetype_metrics, /* TeX font metric files */
+ mp_filetype_fontmap, /* PostScript font mapping files */
+ mp_filetype_font, /* PostScript type1 font programs */
+ mp_filetype_encoding, /* PostScript font encoding files */
+ mp_filetype_text /* first text file for readfrom and writeto primitives */
+};
+typedef char *(*mp_file_finder)(MP, const char *, const char *, int);
+typedef void *(*mp_file_opener)(MP, const char *, const char *, int);
+typedef char *(*mp_file_reader)(MP, void *, size_t *);
+typedef void (*mp_binfile_reader)(MP, void *, void **, size_t *);
+typedef void (*mp_file_closer)(MP, void *);
+typedef int (*mp_file_eoftest)(MP, void *);
+typedef void (*mp_file_flush)(MP, void *);
+typedef void (*mp_file_writer)(MP, void *, const char *);
+typedef void (*mp_binfile_writer)(MP, void *, void *, size_t);
+#define NOTTESTING 1
+
+@ @<Option variables@>=
+mp_file_finder find_file;
+mp_file_opener open_file;
+mp_file_reader read_ascii_file;
+mp_binfile_reader read_binary_file;
+mp_file_closer close_file;
+mp_file_eoftest eof_file;
+mp_file_flush flush_file;
+mp_file_writer write_ascii_file;
+mp_binfile_writer write_binary_file;
+
+@ The default function for finding files is |mp_find_file|. It is
+pretty stupid: it will only find files in the current directory.
+
+This function may disappear altogether, it is currently only
+used for the default font map file.
+
+@c
+char *mp_find_file (MP mp, const char *fname, const char *fmode, int ftype) {
+ (void) mp;
+ if (fmode[0] != 'r' || (! access (fname,R_OK)) || ftype) {
+ return strdup(fname);
+ }
+ return NULL;
+}
+
+@ This has to be done very early on, so it is best to put it in with
+the |mp_new| allocations
+
+@d set_callback_option(A) do { mp->A = mp_##A;
+ if (opt->A!=NULL) mp->A = opt->A;
+} while (0)
+
+@<Allocate or initialize ...@>=
+set_callback_option(find_file);
+set_callback_option(open_file);
+set_callback_option(read_ascii_file);
+set_callback_option(read_binary_file);
+set_callback_option(close_file);
+set_callback_option(eof_file);
+set_callback_option(flush_file);
+set_callback_option(write_ascii_file);
+set_callback_option(write_binary_file);
+
+@ Because |mp_find_file| is used so early, it has to be in the helpers
+section.
+
+@<Internal ...@>=
+char *mp_find_file (MP mp, const char *fname, const char *fmode, int ftype) ;
+void *mp_open_file (MP mp , const char *fname, const char *fmode, int ftype) ;
+char *mp_read_ascii_file (MP mp, void *f, size_t *size) ;
+void mp_read_binary_file (MP mp, void *f, void **d, size_t *size) ;
+void mp_close_file (MP mp, void *f) ;
+int mp_eof_file (MP mp, void *f) ;
+void mp_flush_file (MP mp, void *f) ;
+void mp_write_ascii_file (MP mp, void *f, const char *s) ;
+void mp_write_binary_file (MP mp, void *f, void *s, size_t t) ;
+
+@ The function to open files can now be very short.
+
+@c
+void *mp_open_file(MP mp, const char *fname, const char *fmode, int ftype) {
+ char realmode[3];
+ (void) mp;
+ realmode[0] = *fmode;
+ realmode[1] = 'b';
+ realmode[2] = 0;
+#if NOTTESTING
+ if (ftype==mp_filetype_terminal) {
+ return (fmode[0] == 'r' ? stdin : stdout);
+ } else if (ftype==mp_filetype_error) {
+ return stderr;
+ } else if (fname != NULL && (fmode[0] != 'r' || (! access (fname,R_OK)))) {
+ return (void *)fopen(fname, realmode);
+ }
+#endif
+ return NULL;
+}
+
+@ This is a legacy interface: (almost) all file names pass through |name_of_file|.
+
+@<Glob...@>=
+char name_of_file[file_name_size+1]; /* the name of a system file */
+int name_length;/* this many characters are actually
+ relevant in |name_of_file| (the rest are blank) */
+
+@ @<Option variables@>=
+int print_found_names; /* configuration parameter */
+
+@ If this parameter is true, the terminal and log will report the found
+file names for input files instead of the requested ones.
+It is off by default because it creates an extra filename lookup.
+
+@<Allocate or initialize ...@>=
+mp->print_found_names = (opt->print_found_names>0 ? true : false);
+
+@ \MP's file-opening procedures return |false| if no file identified by
+|name_of_file| could be opened.
+
+The |OPEN_FILE| macro takes care of the |print_found_names| parameter.
+It is not used for opening a mem file for read, because that file name
+is never printed.
+
+@d OPEN_FILE(A) do {
+ if (mp->print_found_names) {
+ char *s = (mp->find_file)(mp,mp->name_of_file,A,ftype);
+ if (s!=NULL) {
+ *f = (mp->open_file)(mp,mp->name_of_file,A, ftype);
+ strncpy(mp->name_of_file,s,file_name_size);
+ xfree(s);
+ } else {
+ *f = NULL;
+ }
+ } else {
+ *f = (mp->open_file)(mp,mp->name_of_file,A, ftype);
+ }
+} while (0);
+return (*f ? true : false)
+
+@c
+boolean mp_a_open_in (MP mp, void **f, int ftype) {
+ /* open a text file for input */
+ OPEN_FILE("r");
+}
+@#
+boolean mp_w_open_in (MP mp, void **f) {
+ /* open a word file for input */
+ *f = (mp->open_file)(mp,mp->name_of_file,"r",mp_filetype_memfile);
+ return (*f ? true : false);
+}
+@#
+boolean mp_a_open_out (MP mp, void **f, int ftype) {
+ /* open a text file for output */
+ OPEN_FILE("w");
+}
+@#
+boolean mp_b_open_out (MP mp, void **f, int ftype) {
+ /* open a binary file for output */
+ OPEN_FILE("w");
+}
+@#
+boolean mp_w_open_out (MP mp, void **f) {
+ /* open a word file for output */
+ int ftype = mp_filetype_memfile;
+ OPEN_FILE("w");
+}
+
+@ @c
+char *mp_read_ascii_file (MP mp, void *ff, size_t *size) {
+ int c;
+ size_t len = 0, lim = 128;
+ char *s = NULL;
+ FILE *f = (FILE *)ff;
+ *size = 0;
+ (void) mp; /* for -Wunused */
+#if NOTTESTING
+ c = fgetc(f);
+ if (c==EOF)
+ return NULL;
+ s = malloc(lim);
+ if (s==NULL) return NULL;
+ while (c!=EOF && c!='\n' && c!='\r') {
+ if (len==lim) {
+ s =realloc(s, (lim+(lim>>2)));
+ if (s==NULL) return NULL;
+ lim+=(lim>>2);
+ }
+ s[len++] = c;
+ c =fgetc(f);
+ }
+ if (c=='\r') {
+ c = fgetc(f);
+ if (c!=EOF && c!='\n')
+ ungetc(c,f);
+ }
+ s[len] = 0;
+ *size = len;
+#endif
+ return s;
+}
+
+@ @c
+void mp_write_ascii_file (MP mp, void *f, const char *s) {
+ (void) mp;
+#if NOTTESTING
+ if (f!=NULL) {
+ fputs(s,(FILE *)f);
+ }
+#endif
+}
+
+@ @c
+void mp_read_binary_file (MP mp, void *f, void **data, size_t *size) {
+ size_t len = 0;
+ (void) mp;
+#if NOTTESTING
+ len = fread(*data,1,*size,(FILE *)f);
+#endif
+ *size = len;
+}
+
+@ @c
+void mp_write_binary_file (MP mp, void *f, void *s, size_t size) {
+ (void) mp;
+#if NOTTESTING
+ if (f!=NULL)
+ fwrite(s,size,1,(FILE *)f);
+#endif
+}
+
+
+@ @c
+void mp_close_file (MP mp, void *f) {
+ (void) mp;
+#if NOTTESTING
+ fclose((FILE *)f);
+#endif
+}
+
+@ @c
+int mp_eof_file (MP mp, void *f) {
+ (void) mp;
+#if NOTTESTING
+ return feof((FILE *)f);
+#else
+ return 0;
+#endif
+}
+
+@ @c
+void mp_flush_file (MP mp, void *f) {
+ (void) mp;
+#if NOTTESTING
+ fflush((FILE *)f);
+#endif
+}
+
+@ Input from text files is read one line at a time, using a routine called
+|input_ln|. This function is defined in terms of global variables called
+|buffer|, |first|, and |last| that will be described in detail later; for
+now, it suffices for us to know that |buffer| is an array of |ASCII_code|
+values, and that |first| and |last| are indices into this array
+representing the beginning and ending of a line of text.
+
+@<Glob...@>=
+size_t buf_size; /* maximum number of characters simultaneously present in
+ current lines of open files */
+ASCII_code *buffer; /* lines of characters being read */
+size_t first; /* the first unused position in |buffer| */
+size_t last; /* end of the line just input to |buffer| */
+size_t max_buf_stack; /* largest index used in |buffer| */
+
+@ @<Allocate or initialize ...@>=
+mp->buf_size = 200;
+mp->buffer = xmalloc((mp->buf_size+1),sizeof(ASCII_code));
+
+@ @<Dealloc variables@>=
+xfree(mp->buffer);
+
+@ @c
+void mp_reallocate_buffer(MP mp, size_t l) {
+ ASCII_code *buffer;
+ if (l>max_halfword) {
+ mp_confusion(mp,"buffer size"); /* can't happen (I hope) */
+ }
+ buffer = xmalloc((l+1),sizeof(ASCII_code));
+ memcpy(buffer,mp->buffer,(mp->buf_size+1));
+ xfree(mp->buffer);
+ mp->buffer = buffer ;
+ mp->buf_size = l;
+}
+
+@ The |input_ln| function brings the next line of input from the specified
+field into available positions of the buffer array and returns the value
+|true|, unless the file has already been entirely read, in which case it
+returns |false| and sets |last:=first|. In general, the |ASCII_code|
+numbers that represent the next line of the file are input into
+|buffer[first]|, |buffer[first+1]|, \dots, |buffer[last-1]|; and the
+global variable |last| is set equal to |first| plus the length of the
+line. Trailing blanks are removed from the line; thus, either |last=first|
+(in which case the line was entirely blank) or |buffer[last-1]<>" "|.
+@^inner loop@>
+
+The variable |max_buf_stack|, which is used to keep track of how large
+the |buf_size| parameter must be to accommodate the present job, is
+also kept up to date by |input_ln|.
+
+@c
+boolean mp_input_ln (MP mp, void *f ) {
+ /* inputs the next line or returns |false| */
+ char *s;
+ size_t size = 0;
+ mp->last=mp->first; /* cf.\ Matthew 19\thinspace:\thinspace30 */
+ s = (mp->read_ascii_file)(mp,f, &size);
+ if (s==NULL)
+ return false;
+ if (size>0) {
+ mp->last = mp->first+size;
+ if ( mp->last>=mp->max_buf_stack ) {
+ mp->max_buf_stack=mp->last+1;
+ while ( mp->max_buf_stack>=mp->buf_size ) {
+ mp_reallocate_buffer(mp,(mp->buf_size+(mp->buf_size>>2)));
+ }
+ }
+ memcpy((mp->buffer+mp->first),s,size);
+ /* while ( mp->buffer[mp->last]==' ' ) mp->last--; */
+ }
+ free(s);
+ return true;
+}
+
+@ The user's terminal acts essentially like other files of text, except
+that it is used both for input and for output. When the terminal is
+considered an input file, the file variable is called |term_in|, and when it
+is considered an output file the file variable is |term_out|.
+@^system dependencies@>
+
+@<Glob...@>=
+void * term_in; /* the terminal as an input file */
+void * term_out; /* the terminal as an output file */
+void * err_out; /* the terminal as an output file */
+
+@ Here is how to open the terminal files. In the default configuration,
+nothing happens except that the command line (if there is one) is copied
+to the input buffer. The variable |command_line| will be filled by the
+|main| procedure. The copying can not be done earlier in the program
+logic because in the |INI| version, the |buffer| is also used for primitive
+initialization.
+
+@^system dependencies@>
+
+@d t_open_out do {/* open the terminal for text output */
+ mp->term_out = (mp->open_file)(mp,"terminal", "w", mp_filetype_terminal);
+ mp->err_out = (mp->open_file)(mp,"error", "w", mp_filetype_error);
+} while (0)
+@d t_open_in do { /* open the terminal for text input */
+ mp->term_in = (mp->open_file)(mp,"terminal", "r", mp_filetype_terminal);
+ if (mp->command_line!=NULL) {
+ mp->last = strlen(mp->command_line);
+ strncpy((char *)mp->buffer,mp->command_line,mp->last);
+ xfree(mp->command_line);
+ } else {
+ mp->last = 0;
+ }
+} while (0)
+
+@d t_close_out do { /* close the terminal */
+ (mp->close_file)(mp,mp->term_out);
+ (mp->close_file)(mp,mp->err_out);
+} while (0)
+
+@d t_close_in do { /* close the terminal */
+ (mp->close_file)(mp,mp->term_in);
+} while (0)
+
+@<Option variables@>=
+char *command_line;
+
+@ @<Allocate or initialize ...@>=
+mp->command_line = xstrdup(opt->command_line);
+
+@ Sometimes it is necessary to synchronize the input/output mixture that
+happens on the user's terminal, and three system-dependent
+procedures are used for this
+purpose. The first of these, |update_terminal|, is called when we want
+to make sure that everything we have output to the terminal so far has
+actually left the computer's internal buffers and been sent.
+The second, |clear_terminal|, is called when we wish to cancel any
+input that the user may have typed ahead (since we are about to
+issue an unexpected error message). The third, |wake_up_terminal|,
+is supposed to revive the terminal if the user has disabled it by
+some instruction to the operating system. The following macros show how
+these operations can be specified:
+@^system dependencies@>
+
+@d update_terminal (mp->flush_file)(mp,mp->term_out) /* empty the terminal output buffer */
+@d clear_terminal do_nothing /* clear the terminal input buffer */
+@d wake_up_terminal (mp->flush_file)(mp,mp->term_out)
+ /* cancel the user's cancellation of output */
+
+@ We need a special routine to read the first line of \MP\ input from
+the user's terminal. This line is different because it is read before we
+have opened the transcript file; there is sort of a ``chicken and
+egg'' problem here. If the user types `\.{input cmr10}' on the first
+line, or if some macro invoked by that line does such an \.{input},
+the transcript file will be named `\.{cmr10.log}'; but if no \.{input}
+commands are performed during the first line of terminal input, the transcript
+file will acquire its default name `\.{mpout.log}'. (The transcript file
+will not contain error messages generated by the first line before the
+first \.{input} command.)
+
+The first line is even more special. It's nice to let the user start
+running a \MP\ job by typing a command line like `\.{MP cmr10}'; in
+such a case, \MP\ will operate as if the first line of input were
+`\.{cmr10}', i.e., the first line will consist of the remainder of the
+command line, after the part that invoked \MP.
+
+@ Different systems have different ways to get started. But regardless of
+what conventions are adopted, the routine that initializes the terminal
+should satisfy the following specifications:
+
+\yskip\textindent{1)}It should open file |term_in| for input from the
+ terminal. (The file |term_out| will already be open for output to the
+ terminal.)
+
+\textindent{2)}If the user has given a command line, this line should be
+ considered the first line of terminal input. Otherwise the
+ user should be prompted with `\.{**}', and the first line of input
+ should be whatever is typed in response.
+
+\textindent{3)}The first line of input, which might or might not be a
+ command line, should appear in locations |first| to |last-1| of the
+ |buffer| array.
+
+\textindent{4)}The global variable |loc| should be set so that the
+ character to be read next by \MP\ is in |buffer[loc]|. This
+ character should not be blank, and we should have |loc<last|.
+
+\yskip\noindent(It may be necessary to prompt the user several times
+before a non-blank line comes in. The prompt is `\.{**}' instead of the
+later `\.*' because the meaning is slightly different: `\.{input}' need
+not be typed immediately after~`\.{**}'.)
+
+@d loc mp->cur_input.loc_field /* location of first unread character in |buffer| */
+
+@ The following program does the required initialization
+without retrieving a possible command line.
+It should be clear how to modify this routine to deal with command lines,
+if the system permits them.
+@^system dependencies@>
+
+@c
+boolean mp_init_terminal (MP mp) { /* gets the terminal input started */
+ t_open_in;
+ if (mp->last!=0) {
+ loc = mp->first = 0;
+ return true;
+ }
+ while (1) {
+ if (!mp->noninteractive) {
+ wake_up_terminal; do_fprintf(mp->term_out,"**"); update_terminal;
+@.**@>
+ }
+ if ( ! mp_input_ln(mp, mp->term_in ) ) { /* this shouldn't happen */
+ do_fprintf(mp->term_out,"\n! End of file on the terminal... why?");
+@.End of file on the terminal@>
+ return false;
+ }
+ loc=mp->first;
+ while ( (loc<(int)mp->last)&&(mp->buffer[loc]==' ') )
+ incr(loc);
+ if ( loc<(int)mp->last ) {
+ return true; /* return unless the line was all blank */
+ }
+ if (!mp->noninteractive) {
+ do_fprintf(mp->term_out,"Please type the name of your input file.\n");
+ }
+ }
+}
+
+@ @<Declarations@>=
+boolean mp_init_terminal (MP mp) ;
+
+
+@* \[4] String handling.
+Symbolic token names and diagnostic messages are variable-length strings
+of eight-bit characters. Many strings \MP\ uses are simply literals
+in the compiled source, like the error messages and the names of the
+internal parameters. Other strings are used or defined from the \MP\ input
+language, and these have to be interned.
+
+\MP\ uses strings more extensively than \MF\ does, but the necessary
+operations can still be handled with a fairly simple data structure.
+The array |str_pool| contains all of the (eight-bit) ASCII codes in all
+of the strings, and the array |str_start| contains indices of the starting
+points of each string. Strings are referred to by integer numbers, so that
+string number |s| comprises the characters |str_pool[j]| for
+|str_start[s]<=j<str_start[ss]| where |ss=next_str[s]|. The string pool
+is allocated sequentially and |str_pool[pool_ptr]| is the next unused
+location. The first string number not currently in use is |str_ptr|
+and |next_str[str_ptr]| begins a list of free string numbers. String
+pool entries |str_start[str_ptr]| up to |pool_ptr| are reserved for a
+string currently being constructed.
+
+String numbers 0 to 255 are reserved for strings that correspond to single
+ASCII characters. This is in accordance with the conventions of \.{WEB},
+@.WEB@>
+which converts single-character strings into the ASCII code number of the
+single character involved, while it converts other strings into integers
+and builds a string pool file. Thus, when the string constant \.{"."} appears
+in the program below, \.{WEB} converts it into the integer 46, which is the
+ASCII code for a period, while \.{WEB} will convert a string like \.{"hello"}
+into some integer greater than~255. String number 46 will presumably be the
+single character `\..'\thinspace; but some ASCII codes have no standard visible
+representation, and \MP\ may need to be able to print an arbitrary
+ASCII character, so the first 256 strings are used to specify exactly what
+should be printed for each of the 256 possibilities.
+
+@<Types...@>=
+typedef int pool_pointer; /* for variables that point into |str_pool| */
+typedef int str_number; /* for variables that point into |str_start| */
+
+@ @<Glob...@>=
+ASCII_code *str_pool; /* the characters */
+pool_pointer *str_start; /* the starting pointers */
+str_number *next_str; /* for linking strings in order */
+pool_pointer pool_ptr; /* first unused position in |str_pool| */
+str_number str_ptr; /* number of the current string being created */
+pool_pointer init_pool_ptr; /* the starting value of |pool_ptr| */
+str_number init_str_use; /* the initial number of strings in use */
+pool_pointer max_pool_ptr; /* the maximum so far of |pool_ptr| */
+str_number max_str_ptr; /* the maximum so far of |str_ptr| */
+
+@ @<Allocate or initialize ...@>=
+mp->str_pool = xmalloc ((mp->pool_size +1),sizeof(ASCII_code));
+mp->str_start = xmalloc ((mp->max_strings+1),sizeof(pool_pointer));
+mp->next_str = xmalloc ((mp->max_strings+1),sizeof(str_number));
+
+@ @<Dealloc variables@>=
+xfree(mp->str_pool);
+xfree(mp->str_start);
+xfree(mp->next_str);
+
+@ Most printing is done from |char *|s, but sometimes not. Here are
+functions that convert an internal string into a |char *| for use
+by the printing routines, and vice versa.
+
+@d str(A) mp_str(mp,A)
+@d rts(A) mp_rts(mp,A)
+
+@<Internal ...@>=
+int mp_xstrcmp (const char *a, const char *b);
+char * mp_str (MP mp, str_number s);
+
+@ @<Declarations@>=
+str_number mp_rts (MP mp, const char *s);
+str_number mp_make_string (MP mp);
+
+@ The attempt to catch interrupted strings that is in |mp_rts|, is not
+very good: it does not handle nesting over more than one level.
+
+@c
+int mp_xstrcmp (const char *a, const char *b) {
+ if (a==NULL && b==NULL)
+ return 0;
+ if (a==NULL)
+ return -1;
+ if (b==NULL)
+ return 1;
+ return strcmp(a,b);
+}
+
+@ @c
+char * mp_str (MP mp, str_number ss) {
+ char *s;
+ int len;
+ if (ss==mp->str_ptr) {
+ return NULL;
+ } else {
+ len = length(ss);
+ s = xmalloc(len+1,sizeof(char));
+ strncpy(s,(char *)(mp->str_pool+(mp->str_start[ss])),len);
+ s[len] = 0;
+ return (char *)s;
+ }
+}
+str_number mp_rts (MP mp, const char *s) {
+ int r; /* the new string */
+ int old; /* a possible string in progress */
+ int i=0;
+ if (strlen(s)==0) {
+ return 256;
+ } else if (strlen(s)==1) {
+ return s[0];
+ } else {
+ old=0;
+ str_room((integer)strlen(s));
+ if (mp->str_start[mp->str_ptr]<mp->pool_ptr)
+ old = mp_make_string(mp);
+ while (*s) {
+ append_char(*s);
+ s++;
+ }
+ r = mp_make_string(mp);
+ if (old!=0) {
+ str_room(length(old));
+ while (i<length(old)) {
+ append_char((mp->str_start[old]+i));
+ }
+ mp_flush_string(mp,old);
+ }
+ return r;
+ }
+}
+
+@ Except for |strs_used_up|, the following string statistics are only
+maintained when code between |stat| $\ldots$ |tats| delimiters is not
+commented out:
+
+@<Glob...@>=
+integer strs_used_up; /* strings in use or unused but not reclaimed */
+integer pool_in_use; /* total number of cells of |str_pool| actually in use */
+integer strs_in_use; /* total number of strings actually in use */
+integer max_pl_used; /* maximum |pool_in_use| so far */
+integer max_strs_used; /* maximum |strs_in_use| so far */
+
+@ Several of the elementary string operations are performed using \.{WEB}
+macros instead of functions, because many of the
+operations are done quite frequently and we want to avoid the
+overhead of procedure calls. For example, here is
+a simple macro that computes the length of a string.
+@.WEB@>
+
+@d str_stop(A) mp->str_start[mp->next_str[(A)]] /* one cell past the end of string
+ number \# */
+@d length(A) (str_stop((A))-mp->str_start[(A)]) /* the number of characters in string \# */
+
+@ The length of the current string is called |cur_length|. If we decide that
+the current string is not needed, |flush_cur_string| resets |pool_ptr| so that
+|cur_length| becomes zero.
+
+@d cur_length (mp->pool_ptr - mp->str_start[mp->str_ptr])
+@d flush_cur_string mp->pool_ptr=mp->str_start[mp->str_ptr]
+
+@ Strings are created by appending character codes to |str_pool|.
+The |append_char| macro, defined here, does not check to see if the
+value of |pool_ptr| has gotten too high; this test is supposed to be
+made before |append_char| is used.
+
+To test if there is room to append |l| more characters to |str_pool|,
+we shall write |str_room(l)|, which tries to make sure there is enough room
+by compacting the string pool if necessary. If this does not work,
+|do_compaction| aborts \MP\ and gives an apologetic error message.
+
+@d append_char(A) /* put |ASCII_code| \# at the end of |str_pool| */
+{ mp->str_pool[mp->pool_ptr]=(A); incr(mp->pool_ptr);
+}
+@d str_room(A) /* make sure that the pool hasn't overflowed */
+ { if ( mp->pool_ptr+(A) > mp->max_pool_ptr ) {
+ if ( mp->pool_ptr+(A) > mp->pool_size ) mp_do_compaction(mp, (A));
+ else mp->max_pool_ptr=mp->pool_ptr+(A); }
+ }
+
+@ The following routine is similar to |str_room(1)| but it uses the
+argument |mp->pool_size| to prevent |do_compaction| from aborting when
+string space is exhausted.
+
+@<Declare the procedure called |unit_str_room|@>=
+void mp_unit_str_room (MP mp);
+
+@ @c
+void mp_unit_str_room (MP mp) {
+ if ( mp->pool_ptr>=mp->pool_size ) mp_do_compaction(mp, mp->pool_size);
+ if ( mp->pool_ptr>=mp->max_pool_ptr ) mp->max_pool_ptr=mp->pool_ptr+1;
+}
+
+@ \MP's string expressions are implemented in a brute-force way: Every
+new string or substring that is needed is simply copied into the string pool.
+Space is eventually reclaimed by a procedure called |do_compaction| with
+the aid of a simple system system of reference counts.
+@^reference counts@>
+
+The number of references to string number |s| will be |str_ref[s]|. The
+special value |str_ref[s]=max_str_ref=127| is used to denote an unknown
+positive number of references; such strings will never be recycled. If
+a string is ever referred to more than 126 times, simultaneously, we
+put it in this category. Hence a single byte suffices to store each |str_ref|.
+
+@d max_str_ref 127 /* ``infinite'' number of references */
+@d add_str_ref(A) { if ( mp->str_ref[(A)]<max_str_ref ) incr(mp->str_ref[(A)]);
+ }
+
+@<Glob...@>=
+int *str_ref;
+
+@ @<Allocate or initialize ...@>=
+mp->str_ref = xmalloc ((mp->max_strings+1),sizeof(int));
+
+@ @<Dealloc variables@>=
+xfree(mp->str_ref);
+
+@ Here's what we do when a string reference disappears:
+
+@d delete_str_ref(A) {
+ if ( mp->str_ref[(A)]<max_str_ref ) {
+ if ( mp->str_ref[(A)]>1 ) decr(mp->str_ref[(A)]);
+ else mp_flush_string(mp, (A));
+ }
+ }
+
+@<Declare the procedure called |flush_string|@>=
+void mp_flush_string (MP mp,str_number s) ;
+
+
+@ We can't flush the first set of static strings at all, so there
+is no point in trying
+
+@c
+void mp_flush_string (MP mp,str_number s) {
+ if (length(s)>1) {
+ mp->pool_in_use=mp->pool_in_use-length(s);
+ decr(mp->strs_in_use);
+ if ( mp->next_str[s]!=mp->str_ptr ) {
+ mp->str_ref[s]=0;
+ } else {
+ mp->str_ptr=s;
+ decr(mp->strs_used_up);
+ }
+ mp->pool_ptr=mp->str_start[mp->str_ptr];
+ }
+}
+
+@ C literals cannot be simply added, they need to be set so they can't
+be flushed.
+
+@d intern(A) mp_intern(mp,(A))
+
+@c
+str_number mp_intern (MP mp, const char *s) {
+ str_number r ;
+ r = rts(s);
+ mp->str_ref[r] = max_str_ref;
+ return r;
+}
+
+@ @<Declarations@>=
+str_number mp_intern (MP mp, const char *s);
+
+
+@ Once a sequence of characters has been appended to |str_pool|, it
+officially becomes a string when the function |make_string| is called.
+This function returns the identification number of the new string as its
+value.
+
+When getting the next unused string number from the linked list, we pretend
+that
+$$ \hbox{|max_str_ptr+1|, |max_str_ptr+2|, $\ldots$, |mp->max_strings|} $$
+are linked sequentially even though the |next_str| entries have not been
+initialized yet. We never allow |str_ptr| to reach |mp->max_strings|;
+|do_compaction| is responsible for making sure of this.
+
+@<Declarations@>=
+@<Declare the procedure called |do_compaction|@>
+@<Declare the procedure called |unit_str_room|@>
+str_number mp_make_string (MP mp);
+
+@ @c
+str_number mp_make_string (MP mp) { /* current string enters the pool */
+ str_number s; /* the new string */
+RESTART:
+ s=mp->str_ptr;
+ mp->str_ptr=mp->next_str[s];
+ if ( mp->str_ptr>mp->max_str_ptr ) {
+ if ( mp->str_ptr==mp->max_strings ) {
+ mp->str_ptr=s;
+ mp_do_compaction(mp, 0);
+ goto RESTART;
+ } else {
+#ifdef DEBUG
+ if ( mp->strs_used_up!=mp->max_str_ptr ) mp_confusion(mp, "s");
+@:this can't happen s}{\quad \.s@>
+#endif
+ mp->max_str_ptr=mp->str_ptr;
+ mp->next_str[mp->str_ptr]=mp->max_str_ptr+1;
+ }
+ }
+ mp->str_ref[s]=1;
+ mp->str_start[mp->str_ptr]=mp->pool_ptr;
+ incr(mp->strs_used_up);
+ incr(mp->strs_in_use);
+ mp->pool_in_use=mp->pool_in_use+length(s);
+ if ( mp->pool_in_use>mp->max_pl_used )
+ mp->max_pl_used=mp->pool_in_use;
+ if ( mp->strs_in_use>mp->max_strs_used )
+ mp->max_strs_used=mp->strs_in_use;
+ return s;
+}
+
+@ The most interesting string operation is string pool compaction. The idea
+is to recover unused space in the |str_pool| array by recopying the strings
+to close the gaps created when some strings become unused. All string
+numbers~$k$ where |str_ref[k]=0| are to be linked into the list of free string
+numbers after |str_ptr|. If this fails to free enough pool space we issue an
+|overflow| error unless |needed=mp->pool_size|. Calling |do_compaction|
+with |needed=mp->pool_size| supresses all overflow tests.
+
+The compaction process starts with |last_fixed_str| because all lower numbered
+strings are permanently allocated with |max_str_ref| in their |str_ref| entries.
+
+@<Glob...@>=
+str_number last_fixed_str; /* last permanently allocated string */
+str_number fixed_str_use; /* number of permanently allocated strings */
+
+@ @<Declare the procedure called |do_compaction|@>=
+void mp_do_compaction (MP mp, pool_pointer needed) ;
+
+@ @c
+void mp_do_compaction (MP mp, pool_pointer needed) {
+ str_number str_use; /* a count of strings in use */
+ str_number r,s,t; /* strings being manipulated */
+ pool_pointer p,q; /* destination and source for copying string characters */
+ @<Advance |last_fixed_str| as far as possible and set |str_use|@>;
+ r=mp->last_fixed_str;
+ s=mp->next_str[r];
+ p=mp->str_start[s];
+ while ( s!=mp->str_ptr ) {
+ while ( mp->str_ref[s]==0 ) {
+ @<Advance |s| and add the old |s| to the list of free string numbers;
+ then |break| if |s=str_ptr|@>;
+ }
+ r=s; s=mp->next_str[s];
+ incr(str_use);
+ @<Move string |r| back so that |str_start[r]=p|; make |p| the location
+ after the end of the string@>;
+ }
+ @<Move the current string back so that it starts at |p|@>;
+ if ( needed<mp->pool_size ) {
+ @<Make sure that there is room for another string with |needed| characters@>;
+ }
+ @<Account for the compaction and make sure the statistics agree with the
+ global versions@>;
+ mp->strs_used_up=str_use;
+}
+
+@ @<Advance |last_fixed_str| as far as possible and set |str_use|@>=
+t=mp->next_str[mp->last_fixed_str];
+while (t!=mp->str_ptr && mp->str_ref[t]==max_str_ref) {
+ incr(mp->fixed_str_use);
+ mp->last_fixed_str=t;
+ t=mp->next_str[t];
+}
+str_use=mp->fixed_str_use
+
+@ Because of the way |flush_string| has been written, it should never be
+necessary to |break| here. The extra line of code seems worthwhile to
+preserve the generality of |do_compaction|.
+
+@<Advance |s| and add the old |s| to the list of free string numbers;...@>=
+{
+t=s;
+s=mp->next_str[s];
+mp->next_str[r]=s;
+mp->next_str[t]=mp->next_str[mp->str_ptr];
+mp->next_str[mp->str_ptr]=t;
+if ( s==mp->str_ptr ) break;
+}
+
+@ The string currently starts at |str_start[r]| and ends just before
+|str_start[s]|. We don't change |str_start[s]| because it might be needed
+to locate the next string.
+
+@<Move string |r| back so that |str_start[r]=p|; make |p| the location...@>=
+q=mp->str_start[r];
+mp->str_start[r]=p;
+while ( q<mp->str_start[s] ) {
+ mp->str_pool[p]=mp->str_pool[q];
+ incr(p); incr(q);
+}
+
+@ Pointers |str_start[str_ptr]| and |pool_ptr| have not been updated. When
+we do this, anything between them should be moved.
+
+@ @<Move the current string back so that it starts at |p|@>=
+q=mp->str_start[mp->str_ptr];
+mp->str_start[mp->str_ptr]=p;
+while ( q<mp->pool_ptr ) {
+ mp->str_pool[p]=mp->str_pool[q];
+ incr(p); incr(q);
+}
+mp->pool_ptr=p
+
+@ We must remember that |str_ptr| is not allowed to reach |mp->max_strings|.
+
+@<Make sure that there is room for another string with |needed| char...@>=
+if ( str_use>=mp->max_strings-1 )
+ mp_reallocate_strings (mp,str_use);
+if ( mp->pool_ptr+needed>mp->max_pool_ptr ) {
+ mp_reallocate_pool(mp, mp->pool_ptr+needed);
+ mp->max_pool_ptr=mp->pool_ptr+needed;
+}
+
+@ @<Declarations@>=
+void mp_reallocate_strings (MP mp, str_number str_use) ;
+void mp_reallocate_pool(MP mp, pool_pointer needed) ;
+
+@ @c
+void mp_reallocate_strings (MP mp, str_number str_use) {
+ while ( str_use>=mp->max_strings-1 ) {
+ int l = mp->max_strings + (mp->max_strings>>2);
+ XREALLOC (mp->str_ref, l, int);
+ XREALLOC (mp->str_start, l, pool_pointer);
+ XREALLOC (mp->next_str, l, str_number);
+ mp->max_strings = l;
+ }
+}
+void mp_reallocate_pool(MP mp, pool_pointer needed) {
+ while ( needed>mp->pool_size ) {
+ int l = mp->pool_size + (mp->pool_size>>2);
+ XREALLOC (mp->str_pool, l, ASCII_code);
+ mp->pool_size = l;
+ }
+}
+
+@ @<Account for the compaction and make sure the statistics agree with...@>=
+if ( (mp->str_start[mp->str_ptr]!=mp->pool_in_use)||(str_use!=mp->strs_in_use) )
+ mp_confusion(mp, "string");
+@:this can't happen string}{\quad string@>
+incr(mp->pact_count);
+mp->pact_chars=mp->pact_chars+mp->pool_ptr-str_stop(mp->last_fixed_str);
+mp->pact_strs=mp->pact_strs+str_use-mp->fixed_str_use;
+#ifdef DEBUG
+s=mp->str_ptr; t=str_use;
+while ( s<=mp->max_str_ptr ){
+ if ( t>mp->max_str_ptr ) mp_confusion(mp, "\"");
+ incr(t); s=mp->next_str[s];
+};
+if ( t<=mp->max_str_ptr ) mp_confusion(mp, "\"");
+#endif
+
+@ A few more global variables are needed to keep track of statistics when
+|stat| $\ldots$ |tats| blocks are not commented out.
+
+@<Glob...@>=
+integer pact_count; /* number of string pool compactions so far */
+integer pact_chars; /* total number of characters moved during compactions */
+integer pact_strs; /* total number of strings moved during compactions */
+
+@ @<Initialize compaction statistics@>=
+mp->pact_count=0;
+mp->pact_chars=0;
+mp->pact_strs=0;
+
+@ The following subroutine compares string |s| with another string of the
+same length that appears in |buffer| starting at position |k|;
+the result is |true| if and only if the strings are equal.
+
+@c
+boolean mp_str_eq_buf (MP mp,str_number s, integer k) {
+ /* test equality of strings */
+ pool_pointer j; /* running index */
+ j=mp->str_start[s];
+ while ( j<str_stop(s) ) {
+ if ( mp->str_pool[j++]!=mp->buffer[k++] )
+ return false;
+ }
+ return true;
+}
+
+@ Here is a similar routine, but it compares two strings in the string pool,
+and it does not assume that they have the same length. If the first string
+is lexicographically greater than, less than, or equal to the second,
+the result is respectively positive, negative, or zero.
+
+@c
+integer mp_str_vs_str (MP mp, str_number s, str_number t) {
+ /* test equality of strings */
+ pool_pointer j,k; /* running indices */
+ integer ls,lt; /* lengths */
+ integer l; /* length remaining to test */
+ ls=length(s); lt=length(t);
+ if ( ls<=lt ) l=ls; else l=lt;
+ j=mp->str_start[s]; k=mp->str_start[t];
+ while ( l-->0 ) {
+ if ( mp->str_pool[j]!=mp->str_pool[k] ) {
+ return (mp->str_pool[j]-mp->str_pool[k]);
+ }
+ incr(j); incr(k);
+ }
+ return (ls-lt);
+}
+
+@ The initial values of |str_pool|, |str_start|, |pool_ptr|,
+and |str_ptr| are computed by the \.{INIMP} program, based in part
+on the information that \.{WEB} has output while processing \MP.
+@.INIMP@>
+@^string pool@>
+
+@c
+void mp_get_strings_started (MP mp) {
+ /* initializes the string pool,
+ but returns |false| if something goes wrong */
+ int k; /* small indices or counters */
+ str_number g; /* a new string */
+ mp->pool_ptr=0; mp->str_ptr=0; mp->max_pool_ptr=0; mp->max_str_ptr=0;
+ mp->str_start[0]=0;
+ mp->next_str[0]=1;
+ mp->pool_in_use=0; mp->strs_in_use=0;
+ mp->max_pl_used=0; mp->max_strs_used=0;
+ @<Initialize compaction statistics@>;
+ mp->strs_used_up=0;
+ @<Make the first 256 strings@>;
+ g=mp_make_string(mp); /* string 256 == "" */
+ mp->str_ref[g]=max_str_ref;
+ mp->last_fixed_str=mp->str_ptr-1;
+ mp->fixed_str_use=mp->str_ptr;
+ return;
+}
+
+@ @<Declarations@>=
+void mp_get_strings_started (MP mp);
+
+@ The first 256 strings will consist of a single character only.
+
+@<Make the first 256...@>=
+for (k=0;k<=255;k++) {
+ append_char(k);
+ g=mp_make_string(mp);
+ mp->str_ref[g]=max_str_ref;
+}
+
+@ The first 128 strings will contain 95 standard ASCII characters, and the
+other 33 characters will be printed in three-symbol form like `\.{\^\^A}'
+unless a system-dependent change is made here. Installations that have
+an extended character set, where for example |xchr[032]=@t\.{'^^Z'}@>|,
+would like string 032 to be printed as the single character 032 instead
+of the three characters 0136, 0136, 0132 (\.{\^\^Z}). On the other hand,
+even people with an extended character set will want to represent string
+015 by \.{\^\^M}, since 015 is ASCII's ``carriage return'' code; the idea is
+to produce visible strings instead of tabs or line-feeds or carriage-returns
+or bell-rings or characters that are treated anomalously in text files.
+
+Unprintable characters of codes 128--255 are, similarly, rendered
+\.{\^\^80}--\.{\^\^ff}.
+
+The boolean expression defined here should be |true| unless \MP\ internal
+code number~|k| corresponds to a non-troublesome visible symbol in the
+local character set.
+If character |k| cannot be printed, and |k<0200|, then character |k+0100| or
+|k-0100| must be printable; moreover, ASCII codes |[060..071, 0141..0146]|
+must be printable.
+@^character set dependencies@>
+@^system dependencies@>
+
+@<Character |k| cannot be printed@>=
+ (k<' ')||(k>'~')
+
+@* \[5] On-line and off-line printing.
+Messages that are sent to a user's terminal and to the transcript-log file
+are produced by several `|print|' procedures. These procedures will
+direct their output to a variety of places, based on the setting of
+the global variable |selector|, which has the following possible
+values:
+
+\yskip
+\hang |term_and_log|, the normal setting, prints on the terminal and on the
+ transcript file.
+
+\hang |log_only|, prints only on the transcript file.
+
+\hang |term_only|, prints only on the terminal.
+
+\hang |no_print|, doesn't print at all. This is used only in rare cases
+ before the transcript file is open.
+
+\hang |pseudo|, puts output into a cyclic buffer that is used
+ by the |show_context| routine; when we get to that routine we shall discuss
+ the reasoning behind this curious mode.
+
+\hang |new_string|, appends the output to the current string in the
+ string pool.
+
+\hang |>=write_file| prints on one of the files used for the \&{write}
+@:write_}{\&{write} primitive@>
+ command.
+
+\yskip
+\noindent The symbolic names `|term_and_log|', etc., have been assigned
+numeric codes that satisfy the convenient relations |no_print+1=term_only|,
+|no_print+2=log_only|, |term_only+2=log_only+1=term_and_log|. These
+relations are not used when |selector| could be |pseudo|, or |new_string|.
+We need not check for unprintable characters when |selector<pseudo|.
+
+Three additional global variables, |tally|, |term_offset| and |file_offset|
+record the number of characters that have been printed
+since they were most recently cleared to zero. We use |tally| to record
+the length of (possibly very long) stretches of printing; |term_offset|,
+and |file_offset|, on the other hand, keep track of how many
+characters have appeared so far on the current line that has been output
+to the terminal, the transcript file, or the \ps\ output file, respectively.
+
+@d new_string 0 /* printing is deflected to the string pool */
+@d pseudo 2 /* special |selector| setting for |show_context| */
+@d no_print 3 /* |selector| setting that makes data disappear */
+@d term_only 4 /* printing is destined for the terminal only */
+@d log_only 5 /* printing is destined for the transcript file only */
+@d term_and_log 6 /* normal |selector| setting */
+@d write_file 7 /* first write file selector */
+
+@<Glob...@>=
+void * log_file; /* transcript of \MP\ session */
+void * ps_file; /* the generic font output goes here */
+unsigned int selector; /* where to print a message */
+unsigned char dig[23]; /* digits in a number being output */
+integer tally; /* the number of characters recently printed */
+unsigned int term_offset;
+ /* the number of characters on the current terminal line */
+unsigned int file_offset;
+ /* the number of characters on the current file line */
+ASCII_code *trick_buf; /* circular buffer for pseudoprinting */
+integer trick_count; /* threshold for pseudoprinting, explained later */
+integer first_count; /* another variable for pseudoprinting */
+
+@ @<Allocate or initialize ...@>=
+memset(mp->dig,0,23);
+mp->trick_buf = xmalloc((mp->error_line+1),sizeof(ASCII_code));
+
+@ @<Dealloc variables@>=
+xfree(mp->trick_buf);
+
+@ @<Initialize the output routines@>=
+mp->selector=term_only; mp->tally=0; mp->term_offset=0; mp->file_offset=0;
+
+@ Macro abbreviations for output to the terminal and to the log file are
+defined here for convenience. Some systems need special conventions
+for terminal output, and it is possible to adhere to those conventions
+by changing |wterm|, |wterm_ln|, and |wterm_cr| here.
+@^system dependencies@>
+
+@d do_fprintf(f,b) (mp->write_ascii_file)(mp,f,b)
+@d wterm(A) do_fprintf(mp->term_out,(A))
+@d wterm_chr(A) { unsigned char ss[2]; ss[0]=(A); ss[1]=0; do_fprintf(mp->term_out,(char *)ss); }
+@d wterm_cr do_fprintf(mp->term_out,"\n")
+@d wterm_ln(A) { wterm_cr; do_fprintf(mp->term_out,(A)); }
+@d wlog(A) do_fprintf(mp->log_file,(A))
+@d wlog_chr(A) { unsigned char ss[2]; ss[0]=(A); ss[1]=0; do_fprintf(mp->log_file,(char *)ss); }
+@d wlog_cr do_fprintf(mp->log_file, "\n")
+@d wlog_ln(A) { wlog_cr; do_fprintf(mp->log_file,(A)); }
+
+
+@ To end a line of text output, we call |print_ln|. Cases |0..max_write_files|
+use an array |wr_file| that will be declared later.
+
+@d mp_print_text(A) mp_print_str(mp,text((A)))
+
+@<Internal ...@>=
+void mp_print_ln (MP mp);
+void mp_print_visible_char (MP mp, ASCII_code s);
+void mp_print_char (MP mp, ASCII_code k);
+void mp_print (MP mp, const char *s);
+void mp_print_str (MP mp, str_number s);
+void mp_print_nl (MP mp, const char *s);
+void mp_print_two (MP mp,scaled x, scaled y) ;
+void mp_print_scaled (MP mp,scaled s);
+
+@ @<Basic print...@>=
+void mp_print_ln (MP mp) { /* prints an end-of-line */
+ switch (mp->selector) {
+ case term_and_log:
+ wterm_cr; wlog_cr;
+ mp->term_offset=0; mp->file_offset=0;
+ break;
+ case log_only:
+ wlog_cr; mp->file_offset=0;
+ break;
+ case term_only:
+ wterm_cr; mp->term_offset=0;
+ break;
+ case no_print:
+ case pseudo:
+ case new_string:
+ break;
+ default:
+ do_fprintf(mp->wr_file[(mp->selector-write_file)],"\n");
+ }
+} /* note that |tally| is not affected */
+
+@ The |print_visible_char| procedure sends one character to the desired
+destination, using the |xchr| array to map it into an external character
+compatible with |input_ln|. (It assumes that it is always called with
+a visible ASCII character.) All printing comes through |print_ln| or
+|print_char|, which ultimately calls |print_visible_char|, hence these
+routines are the ones that limit lines to at most |max_print_line| characters.
+But we must make an exception for the \ps\ output file since it is not safe
+to cut up lines arbitrarily in \ps.
+
+Procedure |unit_str_room| needs to be declared |forward| here because it calls
+|do_compaction| and |do_compaction| can call the error routines. Actually,
+|unit_str_room| avoids |overflow| errors but it can call |confusion|.
+
+@<Basic printing...@>=
+void mp_print_visible_char (MP mp, ASCII_code s) { /* prints a single character */
+ switch (mp->selector) {
+ case term_and_log:
+ wterm_chr(xchr(s)); wlog_chr(xchr(s));
+ incr(mp->term_offset); incr(mp->file_offset);
+ if ( mp->term_offset==(unsigned)mp->max_print_line ) {
+ wterm_cr; mp->term_offset=0;
+ };
+ if ( mp->file_offset==(unsigned)mp->max_print_line ) {
+ wlog_cr; mp->file_offset=0;
+ };
+ break;
+ case log_only:
+ wlog_chr(xchr(s)); incr(mp->file_offset);
+ if ( mp->file_offset==(unsigned)mp->max_print_line ) mp_print_ln(mp);
+ break;
+ case term_only:
+ wterm_chr(xchr(s)); incr(mp->term_offset);
+ if ( mp->term_offset==(unsigned)mp->max_print_line ) mp_print_ln(mp);
+ break;
+ case no_print:
+ break;
+ case pseudo:
+ if ( mp->tally<mp->trick_count )
+ mp->trick_buf[mp->tally % mp->error_line]=s;
+ break;
+ case new_string:
+ if ( mp->pool_ptr>=mp->max_pool_ptr ) {
+ mp_unit_str_room(mp);
+ if ( mp->pool_ptr>=mp->pool_size )
+ goto DONE; /* drop characters if string space is full */
+ };
+ append_char(s);
+ break;
+ default:
+ { char ss[2]; ss[0] = xchr(s); ss[1]=0;
+ do_fprintf(mp->wr_file[(mp->selector-write_file)],(char *)ss);
+ }
+ }
+DONE:
+ incr(mp->tally);
+}
+
+@ The |print_char| procedure sends one character to the desired destination.
+File names and string expressions might contain |ASCII_code| values that
+can't be printed using |print_visible_char|. These characters will be
+printed in three- or four-symbol form like `\.{\^\^A}' or `\.{\^\^e4}'.
+(This procedure assumes that it is safe to bypass all checks for unprintable
+characters when |selector| is in the range |0..max_write_files-1|.
+The user might want to write unprintable characters.
+
+@d print_lc_hex(A) do { l=(A);
+ mp_print_visible_char(mp, (l<10 ? l+'0' : l-10+'a'));
+ } while (0)
+
+@<Basic printing...@>=
+void mp_print_char (MP mp, ASCII_code k) { /* prints a single character */
+ int l; /* small index or counter */
+ if ( mp->selector<pseudo || mp->selector>=write_file) {
+ mp_print_visible_char(mp, k);
+ } else if ( @<Character |k| cannot be printed@> ) {
+ mp_print(mp, "^^");
+ if ( k<0100 ) {
+ mp_print_visible_char(mp, k+0100);
+ } else if ( k<0200 ) {
+ mp_print_visible_char(mp, k-0100);
+ } else {
+ print_lc_hex(k / 16);
+ print_lc_hex(k % 16);
+ }
+ } else {
+ mp_print_visible_char(mp, k);
+ }
+}
+
+@ An entire string is output by calling |print|. Note that if we are outputting
+the single standard ASCII character \.c, we could call |print("c")|, since
+|"c"=99| is the number of a single-character string, as explained above. But
+|print_char("c")| is quicker, so \MP\ goes directly to the |print_char|
+routine when it knows that this is safe. (The present implementation
+assumes that it is always safe to print a visible ASCII character.)
+@^system dependencies@>
+
+@<Basic print...@>=
+void mp_do_print (MP mp, const char *ss, unsigned int len) { /* prints string |s| */
+ unsigned int j = 0;
+ while ( j<len ){
+ mp_print_char(mp, ss[j]); incr(j);
+ }
+}
+
+@
+@<Basic print...@>=
+void mp_print (MP mp, const char *ss) {
+ mp_do_print(mp, ss, strlen(ss));
+}
+void mp_print_str (MP mp, str_number s) {
+ pool_pointer j; /* current character code position */
+ if ( (s<0)||(s>mp->max_str_ptr) ) {
+ mp_do_print(mp,"???",3); /* this can't happen */
+@.???@>
+ }
+ j=mp->str_start[s];
+ mp_do_print(mp, (char *)(mp->str_pool+j), (str_stop(s)-j));
+}
+
+
+@ Here is the very first thing that \MP\ prints: a headline that identifies
+the version number and base name. The |term_offset| variable is temporarily
+incorrect, but the discrepancy is not serious since we assume that the banner
+and mem identifier together will occupy at most |max_print_line|
+character positions.
+
+@<Initialize the output...@>=
+wterm (banner);
+wterm (version_string);
+if (mp->mem_ident!=NULL)
+ mp_print(mp,mp->mem_ident);
+mp_print_ln(mp);
+update_terminal;
+
+@ The procedure |print_nl| is like |print|, but it makes sure that the
+string appears at the beginning of a new line.
+
+@<Basic print...@>=
+void mp_print_nl (MP mp, const char *s) { /* prints string |s| at beginning of line */
+ switch(mp->selector) {
+ case term_and_log:
+ if ( (mp->term_offset>0)||(mp->file_offset>0) ) mp_print_ln(mp);
+ break;
+ case log_only:
+ if ( mp->file_offset>0 ) mp_print_ln(mp);
+ break;
+ case term_only:
+ if ( mp->term_offset>0 ) mp_print_ln(mp);
+ break;
+ case no_print:
+ case pseudo:
+ case new_string:
+ break;
+ } /* there are no other cases */
+ mp_print(mp, s);
+}
+
+@ An array of digits in the range |0..9| is printed by |print_the_digs|.
+
+@<Basic print...@>=
+void mp_print_the_digs (MP mp, eight_bits k) {
+ /* prints |dig[k-1]|$\,\ldots\,$|dig[0]| */
+ while ( k>0 ){
+ decr(k); mp_print_char(mp, '0'+mp->dig[k]);
+ }
+}
+
+@ The following procedure, which prints out the decimal representation of a
+given integer |n|, has been written carefully so that it works properly
+if |n=0| or if |(-n)| would cause overflow. It does not apply |%| or |/|
+to negative arguments, since such operations are not implemented consistently
+on all platforms.
+
+@<Basic print...@>=
+void mp_print_int (MP mp,integer n) { /* prints an integer in decimal form */
+ integer m; /* used to negate |n| in possibly dangerous cases */
+ int k = 0; /* index to current digit; we assume that $|n|<10^{23}$ */
+ if ( n<0 ) {
+ mp_print_char(mp, '-');
+ if ( n>-100000000 ) {
+ negate(n);
+ } else {
+ m=-1-n; n=m / 10; m=(m % 10)+1; k=1;
+ if ( m<10 ) {
+ mp->dig[0]=m;
+ } else {
+ mp->dig[0]=0; incr(n);
+ }
+ }
+ }
+ do {
+ mp->dig[k]=n % 10; n=n / 10; incr(k);
+ } while (n!=0);
+ mp_print_the_digs(mp, k);
+}
+
+@ @<Internal ...@>=
+void mp_print_int (MP mp,integer n);
+
+@ \MP\ also makes use of a trivial procedure to print two digits. The
+following subroutine is usually called with a parameter in the range |0<=n<=99|.
+
+@c
+void mp_print_dd (MP mp,integer n) { /* prints two least significant digits */
+ n=abs(n) % 100;
+ mp_print_char(mp, '0'+(n / 10));
+ mp_print_char(mp, '0'+(n % 10));
+}
+
+
+@ @<Internal ...@>=
+void mp_print_dd (MP mp,integer n);
+
+@ Here is a procedure that asks the user to type a line of input,
+assuming that the |selector| setting is either |term_only| or |term_and_log|.
+The input is placed into locations |first| through |last-1| of the
+|buffer| array, and echoed on the transcript file if appropriate.
+
+This procedure is never called when |interaction<mp_scroll_mode|.
+
+@d prompt_input(A) do {
+ if (!mp->noninteractive) {
+ wake_up_terminal; mp_print(mp, (A));
+ }
+ mp_term_input(mp);
+ } while (0) /* prints a string and gets a line of input */
+
+@c
+void mp_term_input (MP mp) { /* gets a line from the terminal */
+ size_t k; /* index into |buffer| */
+ update_terminal; /* Now the user sees the prompt for sure */
+ if (!mp_input_ln(mp, mp->term_in )) {
+ if (!mp->noninteractive) {
+ mp_fatal_error(mp, "End of file on the terminal!");
+@.End of file on the terminal@>
+ } else { /* we are done with this input chunk */
+ longjmp(mp->jump_buf,1);
+ }
+ }
+ if (!mp->noninteractive) {
+ mp->term_offset=0; /* the user's line ended with \<\rm return> */
+ decr(mp->selector); /* prepare to echo the input */
+ if ( mp->last!=mp->first ) {
+ for (k=mp->first;k<=mp->last-1;k++) {
+ mp_print_char(mp, mp->buffer[k]);
+ }
+ }
+ mp_print_ln(mp);
+ mp->buffer[mp->last]='%';
+ incr(mp->selector); /* restore previous status */
+ }
+}
+
+@* \[6] Reporting errors.
+When something anomalous is detected, \MP\ typically does something like this:
+$$\vbox{\halign{#\hfil\cr
+|print_err("Something anomalous has been detected");|\cr
+|help3("This is the first line of my offer to help.")|\cr
+|("This is the second line. I'm trying to")|\cr
+|("explain the best way for you to proceed.");|\cr
+|error;|\cr}}$$
+A two-line help message would be given using |help2|, etc.; these informal
+helps should use simple vocabulary that complements the words used in the
+official error message that was printed. (Outside the U.S.A., the help
+messages should preferably be translated into the local vernacular. Each
+line of help is at most 60 characters long, in the present implementation,
+so that |max_print_line| will not be exceeded.)
+
+The |print_err| procedure supplies a `\.!' before the official message,
+and makes sure that the terminal is awake if a stop is going to occur.
+The |error| procedure supplies a `\..' after the official message, then it
+shows the location of the error; and if |interaction=error_stop_mode|,
+it also enters into a dialog with the user, during which time the help
+message may be printed.
+@^system dependencies@>
+
+@ The global variable |interaction| has four settings, representing increasing
+amounts of user interaction:
+
+@<Exported types@>=
+enum mp_interaction_mode {
+ mp_unspecified_mode=0, /* extra value for command-line switch */
+ mp_batch_mode, /* omits all stops and omits terminal output */
+ mp_nonstop_mode, /* omits all stops */
+ mp_scroll_mode, /* omits error stops */
+ mp_error_stop_mode /* stops at every opportunity to interact */
+};
+
+@ @<Option variables@>=
+int interaction; /* current level of interaction */
+int noninteractive; /* do we have a terminal? */
+
+@ Set it here so it can be overwritten by the commandline
+
+@<Allocate or initialize ...@>=
+mp->interaction=opt->interaction;
+if (mp->interaction==mp_unspecified_mode || mp->interaction>mp_error_stop_mode)
+ mp->interaction=mp_error_stop_mode;
+if (mp->interaction<mp_unspecified_mode)
+ mp->interaction=mp_batch_mode;
+mp->noninteractive=opt->noninteractive;
+
+@
+
+@d print_err(A) mp_print_err(mp,(A))
+
+@<Internal ...@>=
+void mp_print_err(MP mp, const char * A);
+
+@ @c
+void mp_print_err(MP mp, const char * A) {
+ if ( mp->interaction==mp_error_stop_mode )
+ wake_up_terminal;
+ mp_print_nl(mp, "! ");
+ mp_print(mp, A);
+@.!\relax@>
+}
+
+
+@ \MP\ is careful not to call |error| when the print |selector| setting
+might be unusual. The only possible values of |selector| at the time of
+error messages are
+
+\yskip\hang|no_print| (when |interaction=mp_batch_mode|
+ and |log_file| not yet open);
+
+\hang|term_only| (when |interaction>mp_batch_mode| and |log_file| not yet open);
+
+\hang|log_only| (when |interaction=mp_batch_mode| and |log_file| is open);
+
+\hang|term_and_log| (when |interaction>mp_batch_mode| and |log_file| is open).
+
+@<Initialize the print |selector| based on |interaction|@>=
+if ( mp->interaction==mp_batch_mode ) mp->selector=no_print; else mp->selector=term_only
+
+@ A global variable |deletions_allowed| is set |false| if the |get_next|
+routine is active when |error| is called; this ensures that |get_next|
+will never be called recursively.
+@^recursion@>
+
+The global variable |history| records the worst level of error that
+has been detected. It has four possible values: |spotless|, |warning_issued|,
+|error_message_issued|, and |fatal_error_stop|.
+
+Another global variable, |error_count|, is increased by one when an
+|error| occurs without an interactive dialog, and it is reset to zero at
+the end of every statement. If |error_count| reaches 100, \MP\ decides
+that there is no point in continuing further.
+
+@<Types...@>=
+enum mp_history_states {
+ mp_spotless=0, /* |history| value when nothing has been amiss yet */
+ mp_warning_issued, /* |history| value when |begin_diagnostic| has been called */
+ mp_error_message_issued, /* |history| value when |error| has been called */
+ mp_fatal_error_stop /* |history| value when termination was premature */
+};
+
+@ @<Glob...@>=
+boolean deletions_allowed; /* is it safe for |error| to call |get_next|? */
+int history; /* has the source input been clean so far? */
+int error_count; /* the number of scrolled errors since the last statement ended */
+
+@ The value of |history| is initially |fatal_error_stop|, but it will
+be changed to |spotless| if \MP\ survives the initialization process.
+
+@<Allocate or ...@>=
+mp->deletions_allowed=true; mp->error_count=0; /* |history| is initialized elsewhere */
+
+@ Since errors can be detected almost anywhere in \MP, we want to declare the
+error procedures near the beginning of the program. But the error procedures
+in turn use some other procedures, which need to be declared |forward|
+before we get to |error| itself.
+
+It is possible for |error| to be called recursively if some error arises
+when |get_next| is being used to delete a token, and/or if some fatal error
+occurs while \MP\ is trying to fix a non-fatal one. But such recursion
+@^recursion@>
+is never more than two levels deep.
+
+@<Declarations@>=
+void mp_get_next (MP mp);
+void mp_term_input (MP mp);
+void mp_show_context (MP mp);
+void mp_begin_file_reading (MP mp);
+void mp_open_log_file (MP mp);
+void mp_clear_for_error_prompt (MP mp);
+void mp_debug_help (MP mp);
+@<Declare the procedure called |flush_string|@>
+
+@ @<Internal ...@>=
+void mp_normalize_selector (MP mp);
+
+@ Individual lines of help are recorded in the array |help_line|, which
+contains entries in positions |0..(help_ptr-1)|. They should be printed
+in reverse order, i.e., with |help_line[0]| appearing last.
+
+@d hlp1(A) mp->help_line[0]=(A); }
+@d hlp2(A) mp->help_line[1]=(A); hlp1
+@d hlp3(A) mp->help_line[2]=(A); hlp2
+@d hlp4(A) mp->help_line[3]=(A); hlp3
+@d hlp5(A) mp->help_line[4]=(A); hlp4
+@d hlp6(A) mp->help_line[5]=(A); hlp5
+@d help0 mp->help_ptr=0 /* sometimes there might be no help */
+@d help1 { mp->help_ptr=1; hlp1 /* use this with one help line */
+@d help2 { mp->help_ptr=2; hlp2 /* use this with two help lines */
+@d help3 { mp->help_ptr=3; hlp3 /* use this with three help lines */
+@d help4 { mp->help_ptr=4; hlp4 /* use this with four help lines */
+@d help5 { mp->help_ptr=5; hlp5 /* use this with five help lines */
+@d help6 { mp->help_ptr=6; hlp6 /* use this with six help lines */
+
+@<Glob...@>=
+const char * help_line[6]; /* helps for the next |error| */
+unsigned int help_ptr; /* the number of help lines present */
+boolean use_err_help; /* should the |err_help| string be shown? */
+str_number err_help; /* a string set up by \&{errhelp} */
+str_number filename_template; /* a string set up by \&{filenametemplate} */
+
+@ @<Allocate or ...@>=
+mp->help_ptr=0; mp->use_err_help=false; mp->err_help=0; mp->filename_template=0;
+
+@ The |jump_out| procedure just cuts across all active procedure levels and
+goes to |end_of_MP|. This is the only nonlocal |goto| statement in the
+whole program. It is used when there is no recovery from a particular error.
+
+The program uses a |jump_buf| to handle this, this is initialized at three
+spots: the start of |mp_new|, the start of |mp_initialize|, and the start
+of |mp_run|. Those are the only library enty points.
+
+@^system dependencies@>
+
+@<Glob...@>=
+jmp_buf jump_buf;
+
+@ @<Install and test the non-local jump buffer@>=
+if (setjmp(mp->jump_buf) != 0) { return mp->history; }
+
+@ @<Setup the non-local jump buffer in |mp_new|@>=
+if (setjmp(mp->jump_buf) != 0) return NULL;
+
+
+@ If the array of internals is still |NULL| when |jump_out| is called, a
+crash occured during initialization, and it is not safe to run the normal
+cleanup routine.
+
+@<Error hand...@>=
+void mp_jump_out (MP mp) {
+ if(mp->internal!=NULL)
+ mp_close_files_and_terminate(mp);
+ longjmp(mp->jump_buf,1);
+}
+
+@ Here now is the general |error| routine.
+
+@<Error hand...@>=
+void mp_error (MP mp) { /* completes the job of error reporting */
+ ASCII_code c; /* what the user types */
+ integer s1,s2,s3; /* used to save global variables when deleting tokens */
+ pool_pointer j; /* character position being printed */
+ if ( mp->history<mp_error_message_issued )
+ mp->history=mp_error_message_issued;
+ mp_print_char(mp, '.'); mp_show_context(mp);
+ if ((!mp->noninteractive) && (mp->interaction==mp_error_stop_mode )) {
+ @<Get user's advice and |return|@>;
+ }
+ incr(mp->error_count);
+ if ( mp->error_count==100 ) {
+ mp_print_nl(mp,"(That makes 100 errors; please try again.)");
+@.That makes 100 errors...@>
+ mp->history=mp_fatal_error_stop; mp_jump_out(mp);
+ }
+ @<Put help message on the transcript file@>;
+}
+void mp_warn (MP mp, const char *msg) {
+ int saved_selector = mp->selector;
+ mp_normalize_selector(mp);
+ mp_print_nl(mp,"Warning: ");
+ mp_print(mp,msg);
+ mp_print_ln(mp);
+ mp->selector = saved_selector;
+}
+
+@ @<Exported function ...@>=
+void mp_error (MP mp);
+void mp_warn (MP mp, const char *msg);
+
+
+@ @<Get user's advice...@>=
+while (1) {
+CONTINUE:
+ mp_clear_for_error_prompt(mp); prompt_input("? ");
+@.?\relax@>
+ if ( mp->last==mp->first ) return;
+ c=mp->buffer[mp->first];
+ if ( c>='a' ) c=c+'A'-'a'; /* convert to uppercase */
+ @<Interpret code |c| and |return| if done@>;
+}
+
+@ It is desirable to provide an `\.E' option here that gives the user
+an easy way to return from \MP\ to the system editor, with the offending
+line ready to be edited. But such an extension requires some system
+wizardry, so the present implementation simply types out the name of the
+file that should be
+edited and the relevant line number.
+@^system dependencies@>
+
+@<Exported types@>=
+typedef void (*mp_run_editor_command)(MP, char *, int);
+
+@ @<Option variables@>=
+mp_run_editor_command run_editor;
+
+@ @<Allocate or initialize ...@>=
+set_callback_option(run_editor);
+
+@ @<Declarations@>=
+void mp_run_editor (MP mp, char *fname, int fline);
+
+@ @c void mp_run_editor (MP mp, char *fname, int fline) {
+ mp_print_nl(mp, "You want to edit file ");
+@.You want to edit file x@>
+ mp_print(mp, fname);
+ mp_print(mp, " at line ");
+ mp_print_int(mp, fline);
+ mp->interaction=mp_scroll_mode;
+ mp_jump_out(mp);
+}
+
+@
+There is a secret `\.D' option available when the debugging routines haven't
+been commented~out.
+@^debugging@>
+
+@<Interpret code |c| and |return| if done@>=
+switch (c) {
+case '0': case '1': case '2': case '3': case '4':
+case '5': case '6': case '7': case '8': case '9':
+ if ( mp->deletions_allowed ) {
+ @<Delete |c-"0"| tokens and |continue|@>;
+ }
+ break;
+#ifdef DEBUG
+case 'D':
+ mp_debug_help(mp); continue;
+ break;
+#endif
+case 'E':
+ if ( mp->file_ptr>0 ){
+ (mp->run_editor)(mp,
+ str(mp->input_stack[mp->file_ptr].name_field),
+ mp_true_line(mp));
+ }
+ break;
+case 'H':
+ @<Print the help information and |continue|@>;
+ break;
+case 'I':
+ @<Introduce new material from the terminal and |return|@>;
+ break;
+case 'Q': case 'R': case 'S':
+ @<Change the interaction level and |return|@>;
+ break;
+case 'X':
+ mp->interaction=mp_scroll_mode; mp_jump_out(mp);
+ break;
+default:
+ break;
+}
+@<Print the menu of available options@>
+
+@ @<Print the menu...@>=
+{
+ mp_print(mp, "Type <return> to proceed, S to scroll future error messages,");
+@.Type <return> to proceed...@>
+ mp_print_nl(mp, "R to run without stopping, Q to run quietly,");
+ mp_print_nl(mp, "I to insert something, ");
+ if ( mp->file_ptr>0 )
+ mp_print(mp, "E to edit your file,");
+ if ( mp->deletions_allowed )
+ mp_print_nl(mp, "1 or ... or 9 to ignore the next 1 to 9 tokens of input,");
+ mp_print_nl(mp, "H for help, X to quit.");
+}
+
+@ Here the author of \MP\ apologizes for making use of the numerical
+relation between |"Q"|, |"R"|, |"S"|, and the desired interaction settings
+|mp_batch_mode|, |mp_nonstop_mode|, |mp_scroll_mode|.
+@^Knuth, Donald Ervin@>
+
+@<Change the interaction...@>=
+{
+ mp->error_count=0; mp->interaction=mp_batch_mode+c-'Q';
+ mp_print(mp, "OK, entering ");
+ switch (c) {
+ case 'Q': mp_print(mp, "batchmode"); decr(mp->selector); break;
+ case 'R': mp_print(mp, "nonstopmode"); break;
+ case 'S': mp_print(mp, "scrollmode"); break;
+ } /* there are no other cases */
+ mp_print(mp, "..."); mp_print_ln(mp); update_terminal; return;
+}
+
+@ When the following code is executed, |buffer[(first+1)..(last-1)]| may
+contain the material inserted by the user; otherwise another prompt will
+be given. In order to understand this part of the program fully, you need
+to be familiar with \MP's input stacks.
+
+@<Introduce new material...@>=
+{
+ mp_begin_file_reading(mp); /* enter a new syntactic level for terminal input */
+ if ( mp->last>mp->first+1 ) {
+ loc=mp->first+1; mp->buffer[mp->first]=' ';
+ } else {
+ prompt_input("insert>"); loc=mp->first;
+@.insert>@>
+ };
+ mp->first=mp->last+1; mp->cur_input.limit_field=mp->last; return;
+}
+
+@ We allow deletion of up to 99 tokens at a time.
+
+@<Delete |c-"0"| tokens...@>=
+{
+ s1=mp->cur_cmd; s2=mp->cur_mod; s3=mp->cur_sym; mp->OK_to_interrupt=false;
+ if ( (mp->last>mp->first+1) && (mp->buffer[mp->first+1]>='0')&&(mp->buffer[mp->first+1]<='9') )
+ c=c*10+mp->buffer[mp->first+1]-'0'*11;
+ else
+ c=c-'0';
+ while ( c>0 ) {
+ mp_get_next(mp); /* one-level recursive call of |error| is possible */
+ @<Decrease the string reference count, if the current token is a string@>;
+ decr(c);
+ };
+ mp->cur_cmd=s1; mp->cur_mod=s2; mp->cur_sym=s3; mp->OK_to_interrupt=true;
+ help2("I have just deleted some text, as you asked.")
+ ("You can now delete more, or insert, or whatever.");
+ mp_show_context(mp);
+ goto CONTINUE;
+}
+
+@ @<Print the help info...@>=
+{
+ if ( mp->use_err_help ) {
+ @<Print the string |err_help|, possibly on several lines@>;
+ mp->use_err_help=false;
+ } else {
+ if ( mp->help_ptr==0 ) {
+ help2("Sorry, I don't know how to help in this situation.")
+ ("Maybe you should try asking a human?");
+ }
+ do {
+ decr(mp->help_ptr); mp_print(mp, mp->help_line[mp->help_ptr]); mp_print_ln(mp);
+ } while (mp->help_ptr!=0);
+ };
+ help4("Sorry, I already gave what help I could...")
+ ("Maybe you should try asking a human?")
+ ("An error might have occurred before I noticed any problems.")
+ ("``If all else fails, read the instructions.''");
+ goto CONTINUE;
+}
+
+@ @<Print the string |err_help|, possibly on several lines@>=
+j=mp->str_start[mp->err_help];
+while ( j<str_stop(mp->err_help) ) {
+ if ( mp->str_pool[j]!='%' ) mp_print_str(mp, mp->str_pool[j]);
+ else if ( j+1==str_stop(mp->err_help) ) mp_print_ln(mp);
+ else if ( mp->str_pool[j+1]!='%' ) mp_print_ln(mp);
+ else { incr(j); mp_print_char(mp, '%'); };
+ incr(j);
+}
+
+@ @<Put help message on the transcript file@>=
+if ( mp->interaction>mp_batch_mode ) decr(mp->selector); /* avoid terminal output */
+if ( mp->use_err_help ) {
+ mp_print_nl(mp, "");
+ @<Print the string |err_help|, possibly on several lines@>;
+} else {
+ while ( mp->help_ptr>0 ){
+ decr(mp->help_ptr); mp_print_nl(mp, mp->help_line[mp->help_ptr]);
+ };
+}
+mp_print_ln(mp);
+if ( mp->interaction>mp_batch_mode ) incr(mp->selector); /* re-enable terminal output */
+mp_print_ln(mp)
+
+@ In anomalous cases, the print selector might be in an unknown state;
+the following subroutine is called to fix things just enough to keep
+running a bit longer.
+
+@c
+void mp_normalize_selector (MP mp) {
+ if ( mp->log_opened ) mp->selector=term_and_log;
+ else mp->selector=term_only;
+ if ( mp->job_name==NULL ) mp_open_log_file(mp);
+ if ( mp->interaction==mp_batch_mode ) decr(mp->selector);
+}
+
+@ The following procedure prints \MP's last words before dying.
+
+@d succumb { if ( mp->interaction==mp_error_stop_mode )
+ mp->interaction=mp_scroll_mode; /* no more interaction */
+ if ( mp->log_opened ) mp_error(mp);
+ /*| if ( mp->interaction>mp_batch_mode ) mp_debug_help(mp); |*/
+ mp->history=mp_fatal_error_stop; mp_jump_out(mp); /* irrecoverable error */
+ }
+
+@<Error hand...@>=
+void mp_fatal_error (MP mp, const char *s) { /* prints |s|, and that's it */
+ mp_normalize_selector(mp);
+ print_err("Emergency stop"); help1(s); succumb;
+@.Emergency stop@>
+}
+
+@ @<Exported function ...@>=
+void mp_fatal_error (MP mp, const char *s);
+
+
+@ Here is the most dreaded error message.
+
+@<Error hand...@>=
+void mp_overflow (MP mp, const char *s, integer n) { /* stop due to finiteness */
+ mp_normalize_selector(mp);
+ print_err("MetaPost capacity exceeded, sorry [");
+@.MetaPost capacity exceeded ...@>
+ mp_print(mp, s); mp_print_char(mp, '='); mp_print_int(mp, n); mp_print_char(mp, ']');
+ help2("If you really absolutely need more capacity,")
+ ("you can ask a wizard to enlarge me.");
+ succumb;
+}
+
+@ @<Internal library declarations@>=
+void mp_overflow (MP mp, const char *s, integer n);
+
+@ The program might sometime run completely amok, at which point there is
+no choice but to stop. If no previous error has been detected, that's bad
+news; a message is printed that is really intended for the \MP\
+maintenance person instead of the user (unless the user has been
+particularly diabolical). The index entries for `this can't happen' may
+help to pinpoint the problem.
+@^dry rot@>
+
+@<Internal library ...@>=
+void mp_confusion (MP mp, const char *s);
+
+@ @<Error hand...@>=
+void mp_confusion (MP mp, const char *s) {
+ /* consistency check violated; |s| tells where */
+ mp_normalize_selector(mp);
+ if ( mp->history<mp_error_message_issued ) {
+ print_err("This can't happen ("); mp_print(mp, s); mp_print_char(mp, ')');
+@.This can't happen@>
+ help1("I'm broken. Please show this to someone who can fix can fix");
+ } else {
+ print_err("I can\'t go on meeting you like this");
+@.I can't go on...@>
+ help2("One of your faux pas seems to have wounded me deeply...")
+ ("in fact, I'm barely conscious. Please fix it and try again.");
+ }
+ succumb;
+}
+
+@ Users occasionally want to interrupt \MP\ while it's running.
+If the runtime system allows this, one can implement
+a routine that sets the global variable |interrupt| to some nonzero value
+when such an interrupt is signaled. Otherwise there is probably at least
+a way to make |interrupt| nonzero using the C debugger.
+@^system dependencies@>
+@^debugging@>
+
+@d check_interrupt { if ( mp->interrupt!=0 )
+ mp_pause_for_instructions(mp); }
+
+@<Global...@>=
+integer interrupt; /* should \MP\ pause for instructions? */
+boolean OK_to_interrupt; /* should interrupts be observed? */
+integer run_state; /* are we processing input ?*/
+
+@ @<Allocate or ...@>=
+mp->interrupt=0; mp->OK_to_interrupt=true; mp->run_state=0;
+
+@ When an interrupt has been detected, the program goes into its
+highest interaction level and lets the user have the full flexibility of
+the |error| routine. \MP\ checks for interrupts only at times when it is
+safe to do this.
+
+@c
+void mp_pause_for_instructions (MP mp) {
+ if ( mp->OK_to_interrupt ) {
+ mp->interaction=mp_error_stop_mode;
+ if ( (mp->selector==log_only)||(mp->selector==no_print) )
+ incr(mp->selector);
+ print_err("Interruption");
+@.Interruption@>
+ help3("You rang?")
+ ("Try to insert some instructions for me (e.g.,`I show x'),")
+ ("unless you just want to quit by typing `X'.");
+ mp->deletions_allowed=false; mp_error(mp); mp->deletions_allowed=true;
+ mp->interrupt=0;
+ }
+}
+
+@ Many of \MP's error messages state that a missing token has been
+inserted behind the scenes. We can save string space and program space
+by putting this common code into a subroutine.
+
+@c
+void mp_missing_err (MP mp, const char *s) {
+ print_err("Missing `"); mp_print(mp, s); mp_print(mp, "' has been inserted");
+@.Missing...inserted@>
+}
+
+@* \[7] Arithmetic with scaled numbers.
+The principal computations performed by \MP\ are done entirely in terms of
+integers less than $2^{31}$ in magnitude; thus, the arithmetic specified in this
+program can be carried out in exactly the same way on a wide variety of
+computers, including some small ones.
+@^small computers@>
+
+But C does not rigidly define the |/| operation in the case of negative
+dividends; for example, the result of |(-2*n-1) / 2| is |-(n+1)| on some
+computers and |-n| on others (is this true ?). There are two principal
+types of arithmetic: ``translation-preserving,'' in which the identity
+|(a+q*b)/b=(a/b)+q| is valid; and ``negation-preserving,'' in which
+|(-a)/b=-(a/b)|. This leads to two \MP s, which can produce
+different results, although the differences should be negligible when the
+language is being used properly. The \TeX\ processor has been defined
+carefully so that both varieties of arithmetic will produce identical
+output, but it would be too inefficient to constrain \MP\ in a similar way.
+
+@d el_gordo 017777777777 /* $2^{31}-1$, the largest value that \MP\ likes */
+
+@ One of \MP's most common operations is the calculation of
+$\lfloor{a+b\over2}\rfloor$,
+the midpoint of two given integers |a| and~|b|. The most decent way to do
+this is to write `|(a+b)/2|'; but on many machines it is more efficient
+to calculate `|(a+b)>>1|'.
+
+Therefore the midpoint operation will always be denoted by `|half(a+b)|'
+in this program. If \MP\ is being implemented with languages that permit
+binary shifting, the |half| macro should be changed to make this operation
+as efficient as possible. Since some systems have shift operators that can
+only be trusted to work on positive numbers, there is also a macro |halfp|
+that is used only when the quantity being halved is known to be positive
+or zero.
+
+@d half(A) ((A) / 2)
+@d halfp(A) ((A) >> 1)
+
+@ A single computation might use several subroutine calls, and it is
+desirable to avoid producing multiple error messages in case of arithmetic
+overflow. So the routines below set the global variable |arith_error| to |true|
+instead of reporting errors directly to the user.
+@^overflow in arithmetic@>
+
+@<Glob...@>=
+boolean arith_error; /* has arithmetic overflow occurred recently? */
+
+@ @<Allocate or ...@>=
+mp->arith_error=false;
+
+@ At crucial points the program will say |check_arith|, to test if
+an arithmetic error has been detected.
+
+@d check_arith { if ( mp->arith_error ) mp_clear_arith(mp); }
+
+@c
+void mp_clear_arith (MP mp) {
+ print_err("Arithmetic overflow");
+@.Arithmetic overflow@>
+ help4("Uh, oh. A little while ago one of the quantities that I was")
+ ("computing got too large, so I'm afraid your answers will be")
+ ("somewhat askew. You'll probably have to adopt different")
+ ("tactics next time. But I shall try to carry on anyway.");
+ mp_error(mp);
+ mp->arith_error=false;
+}
+
+@ Addition is not always checked to make sure that it doesn't overflow,
+but in places where overflow isn't too unlikely the |slow_add| routine
+is used.
+
+@c integer mp_slow_add (MP mp,integer x, integer y) {
+ if ( x>=0 ) {
+ if ( y<=el_gordo-x ) {
+ return x+y;
+ } else {
+ mp->arith_error=true;
+ return el_gordo;
+ }
+ } else if ( -y<=el_gordo+x ) {
+ return x+y;
+ } else {
+ mp->arith_error=true;
+ return -el_gordo;
+ }
+}
+
+@ Fixed-point arithmetic is done on {\sl scaled integers\/} that are multiples
+of $2^{-16}$. In other words, a binary point is assumed to be sixteen bit
+positions from the right end of a binary computer word.
+
+@d quarter_unit 040000 /* $2^{14}$, represents 0.250000 */
+@d half_unit 0100000 /* $2^{15}$, represents 0.50000 */
+@d three_quarter_unit 0140000 /* $3\cdot2^{14}$, represents 0.75000 */
+@d unity 0200000 /* $2^{16}$, represents 1.00000 */
+@d two 0400000 /* $2^{17}$, represents 2.00000 */
+@d three 0600000 /* $2^{17}+2^{16}$, represents 3.00000 */
+
+@<Types...@>=
+typedef integer scaled; /* this type is used for scaled integers */
+typedef unsigned char small_number; /* this type is self-explanatory */
+
+@ The following function is used to create a scaled integer from a given decimal
+fraction $(.d_0d_1\ldots d_{k-1})$, where |0<=k<=17|. The digit $d_i$ is
+given in |dig[i]|, and the calculation produces a correctly rounded result.
+
+@c
+scaled mp_round_decimals (MP mp,small_number k) {
+ /* converts a decimal fraction */
+ integer a = 0; /* the accumulator */
+ while ( k-->0 ) {
+ a=(a+mp->dig[k]*two) / 10;
+ }
+ return halfp(a+1);
+}
+
+@ Conversely, here is a procedure analogous to |print_int|. If the output
+of this procedure is subsequently read by \MP\ and converted by the
+|round_decimals| routine above, it turns out that the original value will
+be reproduced exactly. A decimal point is printed only if the value is
+not an integer. If there is more than one way to print the result with
+the optimum number of digits following the decimal point, the closest
+possible value is given.
+
+The invariant relation in the \&{repeat} loop is that a sequence of
+decimal digits yet to be printed will yield the original number if and only if
+they form a fraction~$f$ in the range $s-\delta\L10\cdot2^{16}f<s$.
+We can stop if and only if $f=0$ satisfies this condition; the loop will
+terminate before $s$ can possibly become zero.
+
+@<Basic printing...@>=
+void mp_print_scaled (MP mp,scaled s) { /* prints scaled real, rounded to five digits */
+ scaled delta; /* amount of allowable inaccuracy */
+ if ( s<0 ) {
+ mp_print_char(mp, '-');
+ negate(s); /* print the sign, if negative */
+ }
+ mp_print_int(mp, s / unity); /* print the integer part */
+ s=10*(s % unity)+5;
+ if ( s!=5 ) {
+ delta=10;
+ mp_print_char(mp, '.');
+ do {
+ if ( delta>unity )
+ s=s+0100000-(delta / 2); /* round the final digit */
+ mp_print_char(mp, '0'+(s / unity));
+ s=10*(s % unity);
+ delta=delta*10;
+ } while (s>delta);
+ }
+}
+
+@ We often want to print two scaled quantities in parentheses,
+separated by a comma.
+
+@<Basic printing...@>=
+void mp_print_two (MP mp,scaled x, scaled y) { /* prints `|(x,y)|' */
+ mp_print_char(mp, '(');
+ mp_print_scaled(mp, x);
+ mp_print_char(mp, ',');
+ mp_print_scaled(mp, y);
+ mp_print_char(mp, ')');
+}
+
+@ The |scaled| quantities in \MP\ programs are generally supposed to be
+less than $2^{12}$ in absolute value, so \MP\ does much of its internal
+arithmetic with 28~significant bits of precision. A |fraction| denotes
+a scaled integer whose binary point is assumed to be 28 bit positions
+from the right.
+
+@d fraction_half 01000000000 /* $2^{27}$, represents 0.50000000 */
+@d fraction_one 02000000000 /* $2^{28}$, represents 1.00000000 */
+@d fraction_two 04000000000 /* $2^{29}$, represents 2.00000000 */
+@d fraction_three 06000000000 /* $3\cdot2^{28}$, represents 3.00000000 */
+@d fraction_four 010000000000 /* $2^{30}$, represents 4.00000000 */
+
+@<Types...@>=
+typedef integer fraction; /* this type is used for scaled fractions */
+
+@ In fact, the two sorts of scaling discussed above aren't quite
+sufficient; \MP\ has yet another, used internally to keep track of angles
+in units of $2^{-20}$ degrees.
+
+@d forty_five_deg 0264000000 /* $45\cdot2^{20}$, represents $45^\circ$ */
+@d ninety_deg 0550000000 /* $90\cdot2^{20}$, represents $90^\circ$ */
+@d one_eighty_deg 01320000000 /* $180\cdot2^{20}$, represents $180^\circ$ */
+@d three_sixty_deg 02640000000 /* $360\cdot2^{20}$, represents $360^\circ$ */
+
+@<Types...@>=
+typedef integer angle; /* this type is used for scaled angles */
+
+@ The |make_fraction| routine produces the |fraction| equivalent of
+|p/q|, given integers |p| and~|q|; it computes the integer
+$f=\lfloor2^{28}p/q+{1\over2}\rfloor$, when $p$ and $q$ are
+positive. If |p| and |q| are both of the same scaled type |t|,
+the ``type relation'' |make_fraction(t,t)=fraction| is valid;
+and it's also possible to use the subroutine ``backwards,'' using
+the relation |make_fraction(t,fraction)=t| between scaled types.
+
+If the result would have magnitude $2^{31}$ or more, |make_fraction|
+sets |arith_error:=true|. Most of \MP's internal computations have
+been designed to avoid this sort of error.
+
+If this subroutine were programmed in assembly language on a typical
+machine, we could simply compute |(@t$2^{28}$@>*p)div q|, since a
+double-precision product can often be input to a fixed-point division
+instruction. But when we are restricted to int-eger arithmetic it
+is necessary either to resort to multiple-precision maneuvering
+or to use a simple but slow iteration. The multiple-precision technique
+would be about three times faster than the code adopted here, but it
+would be comparatively long and tricky, involving about sixteen
+additional multiplications and divisions.
+
+This operation is part of \MP's ``inner loop''; indeed, it will
+consume nearly 10\pct! of the running time (exclusive of input and output)
+if the code below is left unchanged. A machine-dependent recoding
+will therefore make \MP\ run faster. The present implementation
+is highly portable, but slow; it avoids multiplication and division
+except in the initial stage. System wizards should be careful to
+replace it with a routine that is guaranteed to produce identical
+results in all cases.
+@^system dependencies@>
+
+As noted below, a few more routines should also be replaced by machine-dependent
+code, for efficiency. But when a procedure is not part of the ``inner loop,''
+such changes aren't advisable; simplicity and robustness are
+preferable to trickery, unless the cost is too high.
+@^inner loop@>
+
+@<Internal ...@>=
+fraction mp_make_fraction (MP mp,integer p, integer q);
+integer mp_take_scaled (MP mp,integer q, scaled f) ;
+
+@ If FIXPT is not defined, we need these preprocessor values
+
+@d ELGORDO 0x7fffffff
+@d TWEXP31 2147483648.0
+@d TWEXP28 268435456.0
+@d TWEXP16 65536.0
+@d TWEXP_16 (1.0/65536.0)
+@d TWEXP_28 (1.0/268435456.0)
+
+
+@c
+fraction mp_make_fraction (MP mp,integer p, integer q) {
+#ifdef FIXPT
+ integer f; /* the fraction bits, with a leading 1 bit */
+ integer n; /* the integer part of $\vert p/q\vert$ */
+ integer be_careful; /* disables certain compiler optimizations */
+ boolean negative = false; /* should the result be negated? */
+ if ( p<0 ) {
+ negate(p); negative=true;
+ }
+ if ( q<=0 ) {
+#ifdef DEBUG
+ if ( q==0 ) mp_confusion(mp, '/');
+#endif
+@:this can't happen /}{\quad \./@>
+ negate(q); negative = ! negative;
+ };
+ n=p / q; p=p % q;
+ if ( n>=8 ){
+ mp->arith_error=true;
+ return ( negative ? -el_gordo : el_gordo);
+ } else {
+ n=(n-1)*fraction_one;
+ @<Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$@>;
+ return (negative ? (-(f+n)) : (f+n));
+ }
+#else /* FIXPT */
+ register double d;
+ register integer i;
+#ifdef DEBUG
+ if (q==0) mp_confusion(mp,'/');
+#endif /* DEBUG */
+ d = TWEXP28 * (double)p /(double)q;
+ if ((p^q) >= 0) {
+ d += 0.5;
+ if (d>=TWEXP31) {mp->arith_error=true; return ELGORDO;}
+ i = (integer) d;
+ if (d==i && ( ((q>0 ? -q : q)&077777)
+ * (((i&037777)<<1)-1) & 04000)!=0) --i;
+ } else {
+ d -= 0.5;
+ if (d<= -TWEXP31) {mp->arith_error=true; return -ELGORDO;}
+ i = (integer) d;
+ if (d==i && ( ((q>0 ? q : -q)&077777)
+ * (((i&037777)<<1)+1) & 04000)!=0) ++i;
+ }
+ return i;
+#endif /* FIXPT */
+}
+
+@ The |repeat| loop here preserves the following invariant relations
+between |f|, |p|, and~|q|:
+(i)~|0<=p<q|; (ii)~$fq+p=2^k(q+p_0)$, where $k$ is an integer and
+$p_0$ is the original value of~$p$.
+
+Notice that the computation specifies
+|(p-q)+p| instead of |(p+p)-q|, because the latter could overflow.
+Let us hope that optimizing compilers do not miss this point; a
+special variable |be_careful| is used to emphasize the necessary
+order of computation. Optimizing compilers should keep |be_careful|
+in a register, not store it in memory.
+@^inner loop@>
+
+@<Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$@>=
+{
+ f=1;
+ do {
+ be_careful=p-q; p=be_careful+p;
+ if ( p>=0 ) {
+ f=f+f+1;
+ } else {
+ f+=f; p=p+q;
+ }
+ } while (f<fraction_one);
+ be_careful=p-q;
+ if ( be_careful+p>=0 ) incr(f);
+}
+
+@ The dual of |make_fraction| is |take_fraction|, which multiplies a
+given integer~|q| by a fraction~|f|. When the operands are positive, it
+computes $p=\lfloor qf/2^{28}+{1\over2}\rfloor$, a symmetric function
+of |q| and~|f|.
+
+This routine is even more ``inner loopy'' than |make_fraction|;
+the present implementation consumes almost 20\pct! of \MP's computation
+time during typical jobs, so a machine-language substitute is advisable.
+@^inner loop@> @^system dependencies@>
+
+@<Declarations@>=
+integer mp_take_fraction (MP mp,integer q, fraction f) ;
+
+@ @c
+#ifdef FIXPT
+integer mp_take_fraction (MP mp,integer q, fraction f) {
+ integer p; /* the fraction so far */
+ boolean negative; /* should the result be negated? */
+ integer n; /* additional multiple of $q$ */
+ integer be_careful; /* disables certain compiler optimizations */
+ @<Reduce to the case that |f>=0| and |q>=0|@>;
+ if ( f<fraction_one ) {
+ n=0;
+ } else {
+ n=f / fraction_one; f=f % fraction_one;
+ if ( q<=el_gordo / n ) {
+ n=n*q ;
+ } else {
+ mp->arith_error=true; n=el_gordo;
+ }
+ }
+ f=f+fraction_one;
+ @<Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$@>;
+ be_careful=n-el_gordo;
+ if ( be_careful+p>0 ){
+ mp->arith_error=true; n=el_gordo-p;
+ }
+ if ( negative )
+ return (-(n+p));
+ else
+ return (n+p);
+#else /* FIXPT */
+integer mp_take_fraction (MP mp,integer p, fraction q) {
+ register double d;
+ register integer i;
+ d = (double)p * (double)q * TWEXP_28;
+ if ((p^q) >= 0) {
+ d += 0.5;
+ if (d>=TWEXP31) {
+ if (d!=TWEXP31 || (((p&077777)*(q&077777))&040000)==0)
+ mp->arith_error = true;
+ return ELGORDO;
+ }
+ i = (integer) d;
+ if (d==i && (((p&077777)*(q&077777))&040000)!=0) --i;
+ } else {
+ d -= 0.5;
+ if (d<= -TWEXP31) {
+ if (d!= -TWEXP31 || ((-(p&077777)*(q&077777))&040000)==0)
+ mp->arith_error = true;
+ return -ELGORDO;
+ }
+ i = (integer) d;
+ if (d==i && ((-(p&077777)*(q&077777))&040000)!=0) ++i;
+ }
+ return i;
+#endif /* FIXPT */
+}
+
+@ @<Reduce to the case that |f>=0| and |q>=0|@>=
+if ( f>=0 ) {
+ negative=false;
+} else {
+ negate( f); negative=true;
+}
+if ( q<0 ) {
+ negate(q); negative=! negative;
+}
+
+@ The invariant relations in this case are (i)~$\lfloor(qf+p)/2^k\rfloor
+=\lfloor qf_0/2^{28}+{1\over2}\rfloor$, where $k$ is an integer and
+$f_0$ is the original value of~$f$; (ii)~$2^k\L f<2^{k+1}$.
+@^inner loop@>
+
+@<Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$@>=
+p=fraction_half; /* that's $2^{27}$; the invariants hold now with $k=28$ */
+if ( q<fraction_four ) {
+ do {
+ if ( odd(f) ) p=halfp(p+q); else p=halfp(p);
+ f=halfp(f);
+ } while (f!=1);
+} else {
+ do {
+ if ( odd(f) ) p=p+halfp(q-p); else p=halfp(p);
+ f=halfp(f);
+ } while (f!=1);
+}
+
+
+@ When we want to multiply something by a |scaled| quantity, we use a scheme
+analogous to |take_fraction| but with a different scaling.
+Given positive operands, |take_scaled|
+computes the quantity $p=\lfloor qf/2^{16}+{1\over2}\rfloor$.
+
+Once again it is a good idea to use a machine-language replacement if
+possible; otherwise |take_scaled| will use more than 2\pct! of the running time
+when the Computer Modern fonts are being generated.
+@^inner loop@>
+
+@c
+#ifdef FIXPT
+integer mp_take_scaled (MP mp,integer q, scaled f) {
+ integer p; /* the fraction so far */
+ boolean negative; /* should the result be negated? */
+ integer n; /* additional multiple of $q$ */
+ integer be_careful; /* disables certain compiler optimizations */
+ @<Reduce to the case that |f>=0| and |q>=0|@>;
+ if ( f<unity ) {
+ n=0;
+ } else {
+ n=f / unity; f=f % unity;
+ if ( q<=el_gordo / n ) {
+ n=n*q;
+ } else {
+ mp->arith_error=true; n=el_gordo;
+ }
+ }
+ f=f+unity;
+ @<Compute $p=\lfloor qf/2^{16}+{1\over2}\rfloor-q$@>;
+ be_careful=n-el_gordo;
+ if ( be_careful+p>0 ) {
+ mp->arith_error=true; n=el_gordo-p;
+ }
+ return ( negative ?(-(n+p)) :(n+p));
+#else /* FIXPT */
+integer mp_take_scaled (MP mp,integer p, scaled q) {
+ register double d;
+ register integer i;
+ d = (double)p * (double)q * TWEXP_16;
+ if ((p^q) >= 0) {
+ d += 0.5;
+ if (d>=TWEXP31) {
+ if (d!=TWEXP31 || (((p&077777)*(q&077777))&040000)==0)
+ mp->arith_error = true;
+ return ELGORDO;
+ }
+ i = (integer) d;
+ if (d==i && (((p&077777)*(q&077777))&040000)!=0) --i;
+ } else {
+ d -= 0.5;
+ if (d<= -TWEXP31) {
+ if (d!= -TWEXP31 || ((-(p&077777)*(q&077777))&040000)==0)
+ mp->arith_error = true;
+ return -ELGORDO;
+ }
+ i = (integer) d;
+ if (d==i && ((-(p&077777)*(q&077777))&040000)!=0) ++i;
+ }
+ return i;
+#endif /* FIXPT */
+}
+
+@ @<Compute $p=\lfloor qf/2^{16}+{1\over2}\rfloor-q$@>=
+p=half_unit; /* that's $2^{15}$; the invariants hold now with $k=16$ */
+@^inner loop@>
+if ( q<fraction_four ) {
+ do {
+ p = (odd(f) ? halfp(p+q) : halfp(p));
+ f=halfp(f);
+ } while (f!=1);
+} else {
+ do {
+ p = (odd(f) ? p+halfp(q-p) : halfp(p));
+ f=halfp(f);
+ } while (f!=1);
+}
+
+@ For completeness, there's also |make_scaled|, which computes a
+quotient as a |scaled| number instead of as a |fraction|.
+In other words, the result is $\lfloor2^{16}p/q+{1\over2}\rfloor$, if the
+operands are positive. \ (This procedure is not used especially often,
+so it is not part of \MP's inner loop.)
+
+@<Internal library ...@>=
+scaled mp_make_scaled (MP mp,integer p, integer q) ;
+
+@ @c
+scaled mp_make_scaled (MP mp,integer p, integer q) {
+#ifdef FIXPT
+ integer f; /* the fraction bits, with a leading 1 bit */
+ integer n; /* the integer part of $\vert p/q\vert$ */
+ boolean negative; /* should the result be negated? */
+ integer be_careful; /* disables certain compiler optimizations */
+ if ( p>=0 ) negative=false;
+ else { negate(p); negative=true; };
+ if ( q<=0 ) {
+#ifdef DEBUG
+ if ( q==0 ) mp_confusion(mp, "/");
+@:this can't happen /}{\quad \./@>
+#endif
+ negate(q); negative=! negative;
+ }
+ n=p / q; p=p % q;
+ if ( n>=0100000 ) {
+ mp->arith_error=true;
+ return (negative ? (-el_gordo) : el_gordo);
+ } else {
+ n=(n-1)*unity;
+ @<Compute $f=\lfloor 2^{16}(1+p/q)+{1\over2}\rfloor$@>;
+ return ( negative ? (-(f+n)) :(f+n));
+ }
+#else /* FIXPT */
+ register double d;
+ register integer i;
+#ifdef DEBUG
+ if (q==0) mp_confusion(mp,"/");
+#endif /* DEBUG */
+ d = TWEXP16 * (double)p /(double)q;
+ if ((p^q) >= 0) {
+ d += 0.5;
+ if (d>=TWEXP31) {mp->arith_error=true; return ELGORDO;}
+ i = (integer) d;
+ if (d==i && ( ((q>0 ? -q : q)&077777)
+ * (((i&037777)<<1)-1) & 04000)!=0) --i;
+ } else {
+ d -= 0.5;
+ if (d<= -TWEXP31) {mp->arith_error=true; return -ELGORDO;}
+ i = (integer) d;
+ if (d==i && ( ((q>0 ? q : -q)&077777)
+ * (((i&037777)<<1)+1) & 04000)!=0) ++i;
+ }
+ return i;
+#endif /* FIXPT */
+}
+
+@ @<Compute $f=\lfloor 2^{16}(1+p/q)+{1\over2}\rfloor$@>=
+f=1;
+do {
+ be_careful=p-q; p=be_careful+p;
+ if ( p>=0 ) f=f+f+1;
+ else { f+=f; p=p+q; };
+} while (f<unity);
+be_careful=p-q;
+if ( be_careful+p>=0 ) incr(f)
+
+@ Here is a typical example of how the routines above can be used.
+It computes the function
+$${1\over3\tau}f(\theta,\phi)=
+{\tau^{-1}\bigl(2+\sqrt2\,(\sin\theta-{1\over16}\sin\phi)
+ (\sin\phi-{1\over16}\sin\theta)(\cos\theta-\cos\phi)\bigr)\over
+3\,\bigl(1+{1\over2}(\sqrt5-1)\cos\theta+{1\over2}(3-\sqrt5\,)\cos\phi\bigr)},$$
+where $\tau$ is a |scaled| ``tension'' parameter. This is \MP's magic
+fudge factor for placing the first control point of a curve that starts
+at an angle $\theta$ and ends at an angle $\phi$ from the straight path.
+(Actually, if the stated quantity exceeds 4, \MP\ reduces it to~4.)
+
+The trigonometric quantity to be multiplied by $\sqrt2$ is less than $\sqrt2$.
+(It's a sum of eight terms whose absolute values can be bounded using
+relations such as $\sin\theta\cos\theta\L{1\over2}$.) Thus the numerator
+is positive; and since the tension $\tau$ is constrained to be at least
+$3\over4$, the numerator is less than $16\over3$. The denominator is
+nonnegative and at most~6. Hence the fixed-point calculations below
+are guaranteed to stay within the bounds of a 32-bit computer word.
+
+The angles $\theta$ and $\phi$ are given implicitly in terms of |fraction|
+arguments |st|, |ct|, |sf|, and |cf|, representing $\sin\theta$, $\cos\theta$,
+$\sin\phi$, and $\cos\phi$, respectively.
+
+@c
+fraction mp_velocity (MP mp,fraction st, fraction ct, fraction sf,
+ fraction cf, scaled t) {
+ integer acc,num,denom; /* registers for intermediate calculations */
+ acc=mp_take_fraction(mp, st-(sf / 16), sf-(st / 16));
+ acc=mp_take_fraction(mp, acc,ct-cf);
+ num=fraction_two+mp_take_fraction(mp, acc,379625062);
+ /* $2^{28}\sqrt2\approx379625062.497$ */
+ denom=fraction_three+mp_take_fraction(mp, ct,497706707)+mp_take_fraction(mp, cf,307599661);
+ /* $3\cdot2^{27}\cdot(\sqrt5-1)\approx497706706.78$ and
+ $3\cdot2^{27}\cdot(3-\sqrt5\,)\approx307599661.22$ */
+ if ( t!=unity ) num=mp_make_scaled(mp, num,t);
+ /* |make_scaled(fraction,scaled)=fraction| */
+ if ( num / 4>=denom )
+ return fraction_four;
+ else
+ return mp_make_fraction(mp, num, denom);
+}
+
+@ The following somewhat different subroutine tests rigorously if $ab$ is
+greater than, equal to, or less than~$cd$,
+given integers $(a,b,c,d)$. In most cases a quick decision is reached.
+The result is $+1$, 0, or~$-1$ in the three respective cases.
+
+@d mp_ab_vs_cd(M,A,B,C,D) mp_do_ab_vs_cd(A,B,C,D)
+
+@c
+integer mp_do_ab_vs_cd (integer a,integer b, integer c, integer d) {
+ integer q,r; /* temporary registers */
+ @<Reduce to the case that |a,c>=0|, |b,d>0|@>;
+ while (1) {
+ q = a / d; r = c / b;
+ if ( q!=r )
+ return ( q>r ? 1 : -1);
+ q = a % d; r = c % b;
+ if ( r==0 )
+ return (q ? 1 : 0);
+ if ( q==0 ) return -1;
+ a=b; b=q; c=d; d=r;
+ } /* now |a>d>0| and |c>b>0| */
+}
+
+@ @<Reduce to the case that |a...@>=
+if ( a<0 ) { negate(a); negate(b); };
+if ( c<0 ) { negate(c); negate(d); };
+if ( d<=0 ) {
+ if ( b>=0 ) {
+ if ( (a==0||b==0)&&(c==0||d==0) ) return 0;
+ else return 1;
+ }
+ if ( d==0 )
+ return ( a==0 ? 0 : -1);
+ q=a; a=c; c=q; q=-b; b=-d; d=q;
+} else if ( b<=0 ) {
+ if ( b<0 ) if ( a>0 ) return -1;
+ return (c==0 ? 0 : -1);
+}
+
+@ We conclude this set of elementary routines with some simple rounding
+and truncation operations.
+
+@<Internal library declarations@>=
+#define mp_floor_scaled(M,i) ((i)&(-65536))
+#define mp_round_unscaled(M,i) (((i>>15)+1)>>1)
+#define mp_round_fraction(M,i) (((i>>11)+1)>>1)
+
+
+@* \[8] Algebraic and transcendental functions.
+\MP\ computes all of the necessary special functions from scratch, without
+relying on |real| arithmetic or system subroutines for sines, cosines, etc.
+
+@ To get the square root of a |scaled| number |x|, we want to calculate
+$s=\lfloor 2^8\!\sqrt x +{1\over2}\rfloor$. If $x>0$, this is the unique
+integer such that $2^{16}x-s\L s^2<2^{16}x+s$. The following subroutine
+determines $s$ by an iterative method that maintains the invariant
+relations $x=2^{46-2k}x_0\bmod 2^{30}$, $0<y=\lfloor 2^{16-2k}x_0\rfloor
+-s^2+s\L q=2s$, where $x_0$ is the initial value of $x$. The value of~$y$
+might, however, be zero at the start of the first iteration.
+
+@<Declarations@>=
+scaled mp_square_rt (MP mp,scaled x) ;
+
+@ @c
+scaled mp_square_rt (MP mp,scaled x) {
+ small_number k; /* iteration control counter */
+ integer y,q; /* registers for intermediate calculations */
+ if ( x<=0 ) {
+ @<Handle square root of zero or negative argument@>;
+ } else {
+ k=23; q=2;
+ while ( x<fraction_two ) { /* i.e., |while x<@t$2^{29}$@>|\unskip */
+ decr(k); x=x+x+x+x;
+ }
+ if ( x<fraction_four ) y=0;
+ else { x=x-fraction_four; y=1; };
+ do {
+ @<Decrease |k| by 1, maintaining the invariant
+ relations between |x|, |y|, and~|q|@>;
+ } while (k!=0);
+ return (halfp(q));
+ }
+}
+
+@ @<Handle square root of zero...@>=
+{
+ if ( x<0 ) {
+ print_err("Square root of ");
+@.Square root...replaced by 0@>
+ mp_print_scaled(mp, x); mp_print(mp, " has been replaced by 0");
+ help2("Since I don't take square roots of negative numbers,")
+ ("I'm zeroing this one. Proceed, with fingers crossed.");
+ mp_error(mp);
+ };
+ return 0;
+}
+
+@ @<Decrease |k| by 1, maintaining...@>=
+x+=x; y+=y;
+if ( x>=fraction_four ) { /* note that |fraction_four=@t$2^{30}$@>| */
+ x=x-fraction_four; incr(y);
+};
+x+=x; y=y+y-q; q+=q;
+if ( x>=fraction_four ) { x=x-fraction_four; incr(y); };
+if ( y>q ){ y=y-q; q=q+2; }
+else if ( y<=0 ) { q=q-2; y=y+q; };
+decr(k)
+
+@ Pythagorean addition $\psqrt{a^2+b^2}$ is implemented by an elegant
+iterative scheme due to Cleve Moler and Donald Morrison [{\sl IBM Journal
+@^Moler, Cleve Barry@>
+@^Morrison, Donald Ross@>
+of Research and Development\/ \bf27} (1983), 577--581]. It modifies |a| and~|b|
+in such a way that their Pythagorean sum remains invariant, while the
+smaller argument decreases.
+
+@<Internal library ...@>=
+integer mp_pyth_add (MP mp,integer a, integer b);
+
+
+@ @c
+integer mp_pyth_add (MP mp,integer a, integer b) {
+ fraction r; /* register used to transform |a| and |b| */
+ boolean big; /* is the result dangerously near $2^{31}$? */
+ a=abs(a); b=abs(b);
+ if ( a<b ) { r=b; b=a; a=r; }; /* now |0<=b<=a| */
+ if ( b>0 ) {
+ if ( a<fraction_two ) {
+ big=false;
+ } else {
+ a=a / 4; b=b / 4; big=true;
+ }; /* we reduced the precision to avoid arithmetic overflow */
+ @<Replace |a| by an approximation to $\psqrt{a^2+b^2}$@>;
+ if ( big ) {
+ if ( a<fraction_two ) {
+ a=a+a+a+a;
+ } else {
+ mp->arith_error=true; a=el_gordo;
+ };
+ }
+ }
+ return a;
+}
+
+@ The key idea here is to reflect the vector $(a,b)$ about the
+line through $(a,b/2)$.
+
+@<Replace |a| by an approximation to $\psqrt{a^2+b^2}$@>=
+while (1) {
+ r=mp_make_fraction(mp, b,a);
+ r=mp_take_fraction(mp, r,r); /* now $r\approx b^2/a^2$ */
+ if ( r==0 ) break;
+ r=mp_make_fraction(mp, r,fraction_four+r);
+ a=a+mp_take_fraction(mp, a+a,r); b=mp_take_fraction(mp, b,r);
+}
+
+
+@ Here is a similar algorithm for $\psqrt{a^2-b^2}$.
+It converges slowly when $b$ is near $a$, but otherwise it works fine.
+
+@c
+integer mp_pyth_sub (MP mp,integer a, integer b) {
+ fraction r; /* register used to transform |a| and |b| */
+ boolean big; /* is the input dangerously near $2^{31}$? */
+ a=abs(a); b=abs(b);
+ if ( a<=b ) {
+ @<Handle erroneous |pyth_sub| and set |a:=0|@>;
+ } else {
+ if ( a<fraction_four ) {
+ big=false;
+ } else {
+ a=halfp(a); b=halfp(b); big=true;
+ }
+ @<Replace |a| by an approximation to $\psqrt{a^2-b^2}$@>;
+ if ( big ) double(a);
+ }
+ return a;
+}
+
+@ @<Replace |a| by an approximation to $\psqrt{a^2-b^2}$@>=
+while (1) {
+ r=mp_make_fraction(mp, b,a);
+ r=mp_take_fraction(mp, r,r); /* now $r\approx b^2/a^2$ */
+ if ( r==0 ) break;
+ r=mp_make_fraction(mp, r,fraction_four-r);
+ a=a-mp_take_fraction(mp, a+a,r); b=mp_take_fraction(mp, b,r);
+}
+
+@ @<Handle erroneous |pyth_sub| and set |a:=0|@>=
+{
+ if ( a<b ){
+ print_err("Pythagorean subtraction "); mp_print_scaled(mp, a);
+ mp_print(mp, "+-+"); mp_print_scaled(mp, b);
+ mp_print(mp, " has been replaced by 0");
+@.Pythagorean...@>
+ help2("Since I don't take square roots of negative numbers,")
+ ("I'm zeroing this one. Proceed, with fingers crossed.");
+ mp_error(mp);
+ }
+ a=0;
+}
+
+@ The subroutines for logarithm and exponential involve two tables.
+The first is simple: |two_to_the[k]| equals $2^k$. The second involves
+a bit more calculation, which the author claims to have done correctly:
+|spec_log[k]| is $2^{27}$ times $\ln\bigl(1/(1-2^{-k})\bigr)=
+2^{-k}+{1\over2}2^{-2k}+{1\over3}2^{-3k}+\cdots\,$, rounded to the
+nearest integer.
+
+@d two_to_the(A) (1<<(A))
+
+@<Constants ...@>=
+static const integer spec_log[29] = { 0, /* special logarithms */
+93032640, 38612034, 17922280, 8662214, 4261238, 2113709,
+1052693, 525315, 262400, 131136, 65552, 32772, 16385,
+8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 1 };
+
+@ @<Local variables for initialization@>=
+integer k; /* all-purpose loop index */
+
+
+@ Here is the routine that calculates $2^8$ times the natural logarithm
+of a |scaled| quantity; it is an integer approximation to $2^{24}\ln(x/2^{16})$,
+when |x| is a given positive integer.
+
+The method is based on exercise 1.2.2--25 in {\sl The Art of Computer
+Programming\/}: During the main iteration we have $1\L 2^{-30}x<1/(1-2^{1-k})$,
+and the logarithm of $2^{30}x$ remains to be added to an accumulator
+register called~$y$. Three auxiliary bits of accuracy are retained in~$y$
+during the calculation, and sixteen auxiliary bits to extend |y| are
+kept in~|z| during the initial argument reduction. (We add
+$100\cdot2^{16}=6553600$ to~|z| and subtract 100 from~|y| so that |z| will
+not become negative; also, the actual amount subtracted from~|y| is~96,
+not~100, because we want to add~4 for rounding before the final division by~8.)
+
+@c
+scaled mp_m_log (MP mp,scaled x) {
+ integer y,z; /* auxiliary registers */
+ integer k; /* iteration counter */
+ if ( x<=0 ) {
+ @<Handle non-positive logarithm@>;
+ } else {
+ y=1302456956+4-100; /* $14\times2^{27}\ln2\approx1302456956.421063$ */
+ z=27595+6553600; /* and $2^{16}\times .421063\approx 27595$ */
+ while ( x<fraction_four ) {
+ double(x); y-=93032639; z-=48782;
+ } /* $2^{27}\ln2\approx 93032639.74436163$ and $2^{16}\times.74436163\approx 48782$ */
+ y=y+(z / unity); k=2;
+ while ( x>fraction_four+4 ) {
+ @<Increase |k| until |x| can be multiplied by a
+ factor of $2^{-k}$, and adjust $y$ accordingly@>;
+ }
+ return (y / 8);
+ }
+}
+
+@ @<Increase |k| until |x| can...@>=
+{
+ z=((x-1) / two_to_the(k))+1; /* $z=\lceil x/2^k\rceil$ */
+ while ( x<fraction_four+z ) { z=halfp(z+1); incr(k); };
+ y+=spec_log[k]; x-=z;
+}
+
+@ @<Handle non-positive logarithm@>=
+{
+ print_err("Logarithm of ");
+@.Logarithm...replaced by 0@>
+ mp_print_scaled(mp, x); mp_print(mp, " has been replaced by 0");
+ help2("Since I don't take logs of non-positive numbers,")
+ ("I'm zeroing this one. Proceed, with fingers crossed.");
+ mp_error(mp);
+ return 0;
+}
+
+@ Conversely, the exponential routine calculates $\exp(x/2^8)$,
+when |x| is |scaled|. The result is an integer approximation to
+$2^{16}\exp(x/2^{24})$, when |x| is regarded as an integer.
+
+@c
+scaled mp_m_exp (MP mp,scaled x) {
+ small_number k; /* loop control index */
+ integer y,z; /* auxiliary registers */
+ if ( x>174436200 ) {
+ /* $2^{24}\ln((2^{31}-1)/2^{16})\approx 174436199.51$ */
+ mp->arith_error=true;
+ return el_gordo;
+ } else if ( x<-197694359 ) {
+ /* $2^{24}\ln(2^{-1}/2^{16})\approx-197694359.45$ */
+ return 0;
+ } else {
+ if ( x<=0 ) {
+ z=-8*x; y=04000000; /* $y=2^{20}$ */
+ } else {
+ if ( x<=127919879 ) {
+ z=1023359037-8*x;
+ /* $2^{27}\ln((2^{31}-1)/2^{20})\approx 1023359037.125$ */
+ } else {
+ z=8*(174436200-x); /* |z| is always nonnegative */
+ }
+ y=el_gordo;
+ };
+ @<Multiply |y| by $\exp(-z/2^{27})$@>;
+ if ( x<=127919879 )
+ return ((y+8) / 16);
+ else
+ return y;
+ }
+}
+
+@ The idea here is that subtracting |spec_log[k]| from |z| corresponds
+to multiplying |y| by $1-2^{-k}$.
+
+A subtle point (which had to be checked) was that if $x=127919879$, the
+value of~|y| will decrease so that |y+8| doesn't overflow. In fact,
+$z$ will be 5 in this case, and |y| will decrease by~64 when |k=25|
+and by~16 when |k=27|.
+
+@<Multiply |y| by...@>=
+k=1;
+while ( z>0 ) {
+ while ( z>=spec_log[k] ) {
+ z-=spec_log[k];
+ y=y-1-((y-two_to_the(k-1)) / two_to_the(k));
+ }
+ incr(k);
+}
+
+@ The trigonometric subroutines use an auxiliary table such that
+|spec_atan[k]| contains an approximation to the |angle| whose tangent
+is~$1/2^k$. $\arctan2^{-k}$ times $2^{20}\cdot180/\pi$
+
+@<Constants ...@>=
+static const angle spec_atan[27] = { 0, 27855475, 14718068, 7471121, 3750058,
+1876857, 938658, 469357, 234682, 117342, 58671, 29335, 14668, 7334, 3667,
+1833, 917, 458, 229, 115, 57, 29, 14, 7, 4, 2, 1 };
+
+@ Given integers |x| and |y|, not both zero, the |n_arg| function
+returns the |angle| whose tangent points in the direction $(x,y)$.
+This subroutine first determines the correct octant, then solves the
+problem for |0<=y<=x|, then converts the result appropriately to
+return an answer in the range |-one_eighty_deg<=@t$\theta$@><=one_eighty_deg|.
+(The answer is |+one_eighty_deg| if |y=0| and |x<0|, but an answer of
+|-one_eighty_deg| is possible if, for example, |y=-1| and $x=-2^{30}$.)
+
+The octants are represented in a ``Gray code,'' since that turns out
+to be computationally simplest.
+
+@d negate_x 1
+@d negate_y 2
+@d switch_x_and_y 4
+@d first_octant 1
+@d second_octant (first_octant+switch_x_and_y)
+@d third_octant (first_octant+switch_x_and_y+negate_x)
+@d fourth_octant (first_octant+negate_x)
+@d fifth_octant (first_octant+negate_x+negate_y)
+@d sixth_octant (first_octant+switch_x_and_y+negate_x+negate_y)
+@d seventh_octant (first_octant+switch_x_and_y+negate_y)
+@d eighth_octant (first_octant+negate_y)
+
+@c
+angle mp_n_arg (MP mp,integer x, integer y) {
+ angle z; /* auxiliary register */
+ integer t; /* temporary storage */
+ small_number k; /* loop counter */
+ int octant; /* octant code */
+ if ( x>=0 ) {
+ octant=first_octant;
+ } else {
+ negate(x); octant=first_octant+negate_x;
+ }
+ if ( y<0 ) {
+ negate(y); octant=octant+negate_y;
+ }
+ if ( x<y ) {
+ t=y; y=x; x=t; octant=octant+switch_x_and_y;
+ }
+ if ( x==0 ) {
+ @<Handle undefined arg@>;
+ } else {
+ @<Set variable |z| to the arg of $(x,y)$@>;
+ @<Return an appropriate answer based on |z| and |octant|@>;
+ }
+}
+
+@ @<Handle undefined arg@>=
+{
+ print_err("angle(0,0) is taken as zero");
+@.angle(0,0)...zero@>
+ help2("The `angle' between two identical points is undefined.")
+ ("I'm zeroing this one. Proceed, with fingers crossed.");
+ mp_error(mp);
+ return 0;
+}
+
+@ @<Return an appropriate answer...@>=
+switch (octant) {
+case first_octant: return z;
+case second_octant: return (ninety_deg-z);
+case third_octant: return (ninety_deg+z);
+case fourth_octant: return (one_eighty_deg-z);
+case fifth_octant: return (z-one_eighty_deg);
+case sixth_octant: return (-z-ninety_deg);
+case seventh_octant: return (z-ninety_deg);
+case eighth_octant: return (-z);
+}; /* there are no other cases */
+return 0
+
+@ At this point we have |x>=y>=0|, and |x>0|. The numbers are scaled up
+or down until $2^{28}\L x<2^{29}$, so that accurate fixed-point calculations
+will be made.
+
+@<Set variable |z| to the arg...@>=
+while ( x>=fraction_two ) {
+ x=halfp(x); y=halfp(y);
+}
+z=0;
+if ( y>0 ) {
+ while ( x<fraction_one ) {
+ x+=x; y+=y;
+ };
+ @<Increase |z| to the arg of $(x,y)$@>;
+}
+
+@ During the calculations of this section, variables |x| and~|y|
+represent actual coordinates $(x,2^{-k}y)$. We will maintain the
+condition |x>=y|, so that the tangent will be at most $2^{-k}$.
+If $x<2y$, the tangent is greater than $2^{-k-1}$. The transformation
+$(a,b)\mapsto(a+b\tan\phi,b-a\tan\phi)$ replaces $(a,b)$ by
+coordinates whose angle has decreased by~$\phi$; in the special case
+$a=x$, $b=2^{-k}y$, and $\tan\phi=2^{-k-1}$, this operation reduces
+to the particularly simple iteration shown here. [Cf.~John E. Meggitt,
+@^Meggitt, John E.@>
+{\sl IBM Journal of Research and Development\/ \bf6} (1962), 210--226.]
+
+The initial value of |x| will be multiplied by at most
+$(1+{1\over2})(1+{1\over8})(1+{1\over32})\cdots\approx 1.7584$; hence
+there is no chance of integer overflow.
+
+@<Increase |z|...@>=
+k=0;
+do {
+ y+=y; incr(k);
+ if ( y>x ){
+ z=z+spec_atan[k]; t=x; x=x+(y / two_to_the(k+k)); y=y-t;
+ };
+} while (k!=15);
+do {
+ y+=y; incr(k);
+ if ( y>x ) { z=z+spec_atan[k]; y=y-x; };
+} while (k!=26)
+
+@ Conversely, the |n_sin_cos| routine takes an |angle| and produces the sine
+and cosine of that angle. The results of this routine are
+stored in global integer variables |n_sin| and |n_cos|.
+
+@<Glob...@>=
+fraction n_sin;fraction n_cos; /* results computed by |n_sin_cos| */
+
+@ Given an integer |z| that is $2^{20}$ times an angle $\theta$ in degrees,
+the purpose of |n_sin_cos(z)| is to set
+|x=@t$r\cos\theta$@>| and |y=@t$r\sin\theta$@>| (approximately),
+for some rather large number~|r|. The maximum of |x| and |y|
+will be between $2^{28}$ and $2^{30}$, so that there will be hardly
+any loss of accuracy. Then |x| and~|y| are divided by~|r|.
+
+@c
+void mp_n_sin_cos (MP mp,angle z) { /* computes a multiple of the sine
+ and cosine */
+ small_number k; /* loop control variable */
+ int q; /* specifies the quadrant */
+ fraction r; /* magnitude of |(x,y)| */
+ integer x,y,t; /* temporary registers */
+ while ( z<0 ) z=z+three_sixty_deg;
+ z=z % three_sixty_deg; /* now |0<=z<three_sixty_deg| */
+ q=z / forty_five_deg; z=z % forty_five_deg;
+ x=fraction_one; y=x;
+ if ( ! odd(q) ) z=forty_five_deg-z;
+ @<Subtract angle |z| from |(x,y)|@>;
+ @<Convert |(x,y)| to the octant determined by~|q|@>;
+ r=mp_pyth_add(mp, x,y);
+ mp->n_cos=mp_make_fraction(mp, x,r);
+ mp->n_sin=mp_make_fraction(mp, y,r);
+}
+
+@ In this case the octants are numbered sequentially.
+
+@<Convert |(x,...@>=
+switch (q) {
+case 0: break;
+case 1: t=x; x=y; y=t; break;
+case 2: t=x; x=-y; y=t; break;
+case 3: negate(x); break;
+case 4: negate(x); negate(y); break;
+case 5: t=x; x=-y; y=-t; break;
+case 6: t=x; x=y; y=-t; break;
+case 7: negate(y); break;
+} /* there are no other cases */
+
+@ The main iteration of |n_sin_cos| is similar to that of |n_arg| but
+applied in reverse. The values of |spec_atan[k]| decrease slowly enough
+that this loop is guaranteed to terminate before the (nonexistent) value
+|spec_atan[27]| would be required.
+
+@<Subtract angle |z|...@>=
+k=1;
+while ( z>0 ){
+ if ( z>=spec_atan[k] ) {
+ z=z-spec_atan[k]; t=x;
+ x=t+y / two_to_the(k);
+ y=y-t / two_to_the(k);
+ }
+ incr(k);
+}
+if ( y<0 ) y=0 /* this precaution may never be needed */
+
+@ And now let's complete our collection of numeric utility routines
+by considering random number generation.
+\MP\ generates pseudo-random numbers with the additive scheme recommended
+in Section 3.6 of {\sl The Art of Computer Programming}; however, the
+results are random fractions between 0 and |fraction_one-1|, inclusive.
+
+There's an auxiliary array |randoms| that contains 55 pseudo-random
+fractions. Using the recurrence $x_n=(x_{n-55}-x_{n-31})\bmod 2^{28}$,
+we generate batches of 55 new $x_n$'s at a time by calling |new_randoms|.
+The global variable |j_random| tells which element has most recently
+been consumed.
+The global variable |random_seed| was introduced in version 0.9,
+for the sole reason of stressing the fact that the initial value of the
+random seed is system-dependant. The initialization code below will initialize
+this variable to |(internal[mp_time] div unity)+internal[mp_day]|, but this
+is not good enough on modern fast machines that are capable of running
+multiple MetaPost processes within the same second.
+@^system dependencies@>
+
+@<Glob...@>=
+fraction randoms[55]; /* the last 55 random values generated */
+int j_random; /* the number of unused |randoms| */
+
+@ @<Option variables@>=
+int random_seed; /* the default random seed */
+
+@ @<Allocate or initialize ...@>=
+mp->random_seed = (scaled)opt->random_seed;
+
+@ To consume a random fraction, the program below will say `|next_random|'
+and then it will fetch |randoms[j_random]|.
+
+@d next_random { if ( mp->j_random==0 ) mp_new_randoms(mp);
+ else decr(mp->j_random); }
+
+@c
+void mp_new_randoms (MP mp) {
+ int k; /* index into |randoms| */
+ fraction x; /* accumulator */
+ for (k=0;k<=23;k++) {
+ x=mp->randoms[k]-mp->randoms[k+31];
+ if ( x<0 ) x=x+fraction_one;
+ mp->randoms[k]=x;
+ }
+ for (k=24;k<= 54;k++){
+ x=mp->randoms[k]-mp->randoms[k-24];
+ if ( x<0 ) x=x+fraction_one;
+ mp->randoms[k]=x;
+ }
+ mp->j_random=54;
+}
+
+@ @<Declarations@>=
+void mp_init_randoms (MP mp,scaled seed);
+
+@ To initialize the |randoms| table, we call the following routine.
+
+@c
+void mp_init_randoms (MP mp,scaled seed) {
+ fraction j,jj,k; /* more or less random integers */
+ int i; /* index into |randoms| */
+ j=abs(seed);
+ while ( j>=fraction_one ) j=halfp(j);
+ k=1;
+ for (i=0;i<=54;i++ ){
+ jj=k; k=j-k; j=jj;
+ if ( k<0 ) k=k+fraction_one;
+ mp->randoms[(i*21)% 55]=j;
+ }
+ mp_new_randoms(mp);
+ mp_new_randoms(mp);
+ mp_new_randoms(mp); /* ``warm up'' the array */
+}
+
+@ To produce a uniform random number in the range |0<=u<x| or |0>=u>x|
+or |0=u=x|, given a |scaled| value~|x|, we proceed as shown here.
+
+Note that the call of |take_fraction| will produce the values 0 and~|x|
+with about half the probability that it will produce any other particular
+values between 0 and~|x|, because it rounds its answers.
+
+@c
+scaled mp_unif_rand (MP mp,scaled x) {
+ scaled y; /* trial value */
+ next_random; y=mp_take_fraction(mp, abs(x),mp->randoms[mp->j_random]);
+ if ( y==abs(x) ) return 0;
+ else if ( x>0 ) return y;
+ else return (-y);
+}
+
+@ Finally, a normal deviate with mean zero and unit standard deviation
+can readily be obtained with the ratio method (Algorithm 3.4.1R in
+{\sl The Art of Computer Programming\/}).
+
+@c
+scaled mp_norm_rand (MP mp) {
+ integer x,u,l; /* what the book would call $2^{16}X$, $2^{28}U$, and $-2^{24}\ln U$ */
+ do {
+ do {
+ next_random;
+ x=mp_take_fraction(mp, 112429,mp->randoms[mp->j_random]-fraction_half);
+ /* $2^{16}\sqrt{8/e}\approx 112428.82793$ */
+ next_random; u=mp->randoms[mp->j_random];
+ } while (abs(x)>=u);
+ x=mp_make_fraction(mp, x,u);
+ l=139548960-mp_m_log(mp, u); /* $2^{24}\cdot12\ln2\approx139548959.6165$ */
+ } while (mp_ab_vs_cd(mp, 1024,l,x,x)<0);
+ return x;
+}
+
+@* \[9] Packed data.
+In order to make efficient use of storage space, \MP\ bases its major data
+structures on a |memory_word|, which contains either a (signed) integer,
+possibly scaled, or a small number of fields that are one half or one
+quarter of the size used for storing integers.
+
+If |x| is a variable of type |memory_word|, it contains up to four
+fields that can be referred to as follows:
+$$\vbox{\halign{\hfil#&#\hfil&#\hfil\cr
+|x|&.|int|&(an |integer|)\cr
+|x|&.|sc|\qquad&(a |scaled| integer)\cr
+|x.hh.lh|, |x.hh|&.|rh|&(two halfword fields)\cr
+|x.hh.b0|, |x.hh.b1|, |x.hh|&.|rh|&(two quarterword fields, one halfword
+ field)\cr
+|x.qqqq.b0|, |x.qqqq.b1|, |x.qqqq|&.|b2|, |x.qqqq.b3|\hskip-100pt
+ &\qquad\qquad\qquad(four quarterword fields)\cr}}$$
+This is somewhat cumbersome to write, and not very readable either, but
+macros will be used to make the notation shorter and more transparent.
+The code below gives a formal definition of |memory_word| and
+its subsidiary types, using packed variant records. \MP\ makes no
+assumptions about the relative positions of the fields within a word.
+
+@d max_quarterword 0x3FFF /* largest allowable value in a |quarterword| */
+@d max_halfword 0xFFFFFFF /* largest allowable value in a |halfword| */
+
+@ Here are the inequalities that the quarterword and halfword values
+must satisfy (or rather, the inequalities that they mustn't satisfy):
+
+@<Check the ``constant''...@>=
+if (mp->ini_version) {
+ if ( mp->mem_max!=mp->mem_top ) mp->bad=8;
+} else {
+ if ( mp->mem_max<mp->mem_top ) mp->bad=8;
+}
+if ( max_quarterword<255 ) mp->bad=9;
+if ( max_halfword<65535 ) mp->bad=10;
+if ( max_quarterword>max_halfword ) mp->bad=11;
+if ( mp->mem_max>=max_halfword ) mp->bad=12;
+if ( mp->max_strings>max_halfword ) mp->bad=13;
+
+@ The macros |qi| and |qo| are used for input to and output
+from quarterwords. These are legacy macros.
+@^system dependencies@>
+
+@d qo(A) (A) /* to read eight bits from a quarterword */
+@d qi(A) (A) /* to store eight bits in a quarterword */
+
+@ The reader should study the following definitions closely:
+@^system dependencies@>
+
+@d sc cint /* |scaled| data is equivalent to |integer| */
+
+@<Types...@>=
+typedef short quarterword; /* 1/4 of a word */
+typedef int halfword; /* 1/2 of a word */
+typedef union {
+ struct {
+ halfword RH, LH;
+ } v;
+ struct { /* Make B0,B1 overlap the most significant bytes of LH. */
+ halfword junk;
+ quarterword B0, B1;
+ } u;
+} two_halves;
+typedef struct {
+ struct {
+ quarterword B2, B3, B0, B1;
+ } u;
+} four_quarters;
+typedef union {
+ two_halves hh;
+ integer cint;
+ four_quarters qqqq;
+} memory_word;
+#define b0 u.B0
+#define b1 u.B1
+#define b2 u.B2
+#define b3 u.B3
+#define rh v.RH
+#define lh v.LH
+
+@ When debugging, we may want to print a |memory_word| without knowing
+what type it is; so we print it in all modes.
+@^debugging@>
+
+@c
+void mp_print_word (MP mp,memory_word w) {
+ /* prints |w| in all ways */
+ mp_print_int(mp, w.cint); mp_print_char(mp, ' ');
+ mp_print_scaled(mp, w.sc); mp_print_char(mp, ' ');
+ mp_print_scaled(mp, w.sc / 010000); mp_print_ln(mp);
+ mp_print_int(mp, w.hh.lh); mp_print_char(mp, '=');
+ mp_print_int(mp, w.hh.b0); mp_print_char(mp, ':');
+ mp_print_int(mp, w.hh.b1); mp_print_char(mp, ';');
+ mp_print_int(mp, w.hh.rh); mp_print_char(mp, ' ');
+ mp_print_int(mp, w.qqqq.b0); mp_print_char(mp, ':');
+ mp_print_int(mp, w.qqqq.b1); mp_print_char(mp, ':');
+ mp_print_int(mp, w.qqqq.b2); mp_print_char(mp, ':');
+ mp_print_int(mp, w.qqqq.b3);
+}
+
+
+@* \[10] Dynamic memory allocation.
+
+The \MP\ system does nearly all of its own memory allocation, so that it
+can readily be transported into environments that do not have automatic
+facilities for strings, garbage collection, etc., and so that it can be in
+control of what error messages the user receives. The dynamic storage
+requirements of \MP\ are handled by providing a large array |mem| in
+which consecutive blocks of words are used as nodes by the \MP\ routines.
+
+Pointer variables are indices into this array, or into another array
+called |eqtb| that will be explained later. A pointer variable might
+also be a special flag that lies outside the bounds of |mem|, so we
+allow pointers to assume any |halfword| value. The minimum memory
+index represents a null pointer.
+
+@d null 0 /* the null pointer */
+@d mp_void (null+1) /* a null pointer different from |null| */
+
+
+@<Types...@>=
+typedef halfword pointer; /* a flag or a location in |mem| or |eqtb| */
+
+@ The |mem| array is divided into two regions that are allocated separately,
+but the dividing line between these two regions is not fixed; they grow
+together until finding their ``natural'' size in a particular job.
+Locations less than or equal to |lo_mem_max| are used for storing
+variable-length records consisting of two or more words each. This region
+is maintained using an algorithm similar to the one described in exercise
+2.5--19 of {\sl The Art of Computer Programming}. However, no size field
+appears in the allocated nodes; the program is responsible for knowing the
+relevant size when a node is freed. Locations greater than or equal to
+|hi_mem_min| are used for storing one-word records; a conventional
+\.{AVAIL} stack is used for allocation in this region.
+
+Locations of |mem| between |0| and |mem_top| may be dumped as part
+of preloaded mem files, by the \.{INIMP} preprocessor.
+@.INIMP@>
+Production versions of \MP\ may extend the memory at the top end in order to
+provide more space; these locations, between |mem_top| and |mem_max|,
+are always used for single-word nodes.
+
+The key pointers that govern |mem| allocation have a prescribed order:
+$$\hbox{|null=0<lo_mem_max<hi_mem_min<mem_top<=mem_end<=mem_max|.}$$
+
+@<Glob...@>=
+memory_word *mem; /* the big dynamic storage area */
+pointer lo_mem_max; /* the largest location of variable-size memory in use */
+pointer hi_mem_min; /* the smallest location of one-word memory in use */
+
+
+@
+@d xfree(A) do { mp_xfree(A); A=NULL; } while (0)
+@d xrealloc(P,A,B) mp_xrealloc(mp,P,A,B)
+@d xmalloc(A,B) mp_xmalloc(mp,A,B)
+@d xstrdup(A) mp_xstrdup(mp,A)
+@d XREALLOC(a,b,c) a = xrealloc(a,(b+1),sizeof(c));
+
+@<Declare helpers@>=
+void mp_xfree (void *x);
+void *mp_xrealloc (MP mp, void *p, size_t nmem, size_t size) ;
+void *mp_xmalloc (MP mp, size_t nmem, size_t size) ;
+char *mp_xstrdup(MP mp, const char *s);
+
+@ The |max_size_test| guards against overflow, on the assumption that
+|size_t| is at least 31bits wide.
+
+@d max_size_test 0x7FFFFFFF
+
+@c
+void mp_xfree (void *x) {
+ if (x!=NULL) free(x);
+}
+void *mp_xrealloc (MP mp, void *p, size_t nmem, size_t size) {
+ void *w ;
+ if ((max_size_test/size)<nmem) {
+ do_fprintf(mp->err_out,"Memory size overflow!\n");
+ mp->history =mp_fatal_error_stop; mp_jump_out(mp);
+ }
+ w = realloc (p,(nmem*size));
+ if (w==NULL) {
+ do_fprintf(mp->err_out,"Out of memory!\n");
+ mp->history =mp_fatal_error_stop; mp_jump_out(mp);
+ }
+ return w;
+}
+void *mp_xmalloc (MP mp, size_t nmem, size_t size) {
+ void *w;
+ if ((max_size_test/size)<nmem) {
+ do_fprintf(mp->err_out,"Memory size overflow!\n");
+ mp->history =mp_fatal_error_stop; mp_jump_out(mp);
+ }
+ w = malloc (nmem*size);
+ if (w==NULL) {
+ do_fprintf(mp->err_out,"Out of memory!\n");
+ mp->history =mp_fatal_error_stop; mp_jump_out(mp);
+ }
+ return w;
+}
+char *mp_xstrdup(MP mp, const char *s) {
+ char *w;
+ if (s==NULL)
+ return NULL;
+ w = strdup(s);
+ if (w==NULL) {
+ do_fprintf(mp->err_out,"Out of memory!\n");
+ mp->history =mp_fatal_error_stop; mp_jump_out(mp);
+ }
+ return w;
+}
+
+
+@
+@<Allocate or initialize ...@>=
+mp->mem = xmalloc ((mp->mem_max+1),sizeof (memory_word));
+memset(mp->mem,0,(mp->mem_max+1)*sizeof (memory_word));
+
+@ @<Dealloc variables@>=
+xfree(mp->mem);
+
+@ Users who wish to study the memory requirements of particular applications can
+can use optional special features that keep track of current and
+maximum memory usage. When code between the delimiters |stat| $\ldots$
+|tats| is not ``commented out,'' \MP\ will run a bit slower but it will
+report these statistics when |mp_tracing_stats| is positive.
+
+@<Glob...@>=
+integer var_used; integer dyn_used; /* how much memory is in use */
+
+@ Let's consider the one-word memory region first, since it's the
+simplest. The pointer variable |mem_end| holds the highest-numbered location
+of |mem| that has ever been used. The free locations of |mem| that
+occur between |hi_mem_min| and |mem_end|, inclusive, are of type
+|two_halves|, and we write |info(p)| and |link(p)| for the |lh|
+and |rh| fields of |mem[p]| when it is of this type. The single-word
+free locations form a linked list
+$$|avail|,\;\hbox{|link(avail)|},\;\hbox{|link(link(avail))|},\;\ldots$$
+terminated by |null|.
+
+@d link(A) mp->mem[(A)].hh.rh /* the |link| field of a memory word */
+@d info(A) mp->mem[(A)].hh.lh /* the |info| field of a memory word */
+
+@<Glob...@>=
+pointer avail; /* head of the list of available one-word nodes */
+pointer mem_end; /* the last one-word node used in |mem| */
+
+@ If one-word memory is exhausted, it might mean that the user has forgotten
+a token like `\&{enddef}' or `\&{endfor}'. We will define some procedures
+later that try to help pinpoint the trouble.
+
+@c
+@<Declare the procedure called |show_token_list|@>
+@<Declare the procedure called |runaway|@>
+
+@ The function |get_avail| returns a pointer to a new one-word node whose
+|link| field is null. However, \MP\ will halt if there is no more room left.
+@^inner loop@>
+
+@c
+pointer mp_get_avail (MP mp) { /* single-word node allocation */
+ pointer p; /* the new node being got */
+ p=mp->avail; /* get top location in the |avail| stack */
+ if ( p!=null ) {
+ mp->avail=link(mp->avail); /* and pop it off */
+ } else if ( mp->mem_end<mp->mem_max ) { /* or go into virgin territory */
+ incr(mp->mem_end); p=mp->mem_end;
+ } else {
+ decr(mp->hi_mem_min); p=mp->hi_mem_min;
+ if ( mp->hi_mem_min<=mp->lo_mem_max ) {
+ mp_runaway(mp); /* if memory is exhausted, display possible runaway text */
+ mp_overflow(mp, "main memory size",mp->mem_max);
+ /* quit; all one-word nodes are busy */
+@:MetaPost capacity exceeded main memory size}{\quad main memory size@>
+ }
+ }
+ link(p)=null; /* provide an oft-desired initialization of the new node */
+ incr(mp->dyn_used);/* maintain statistics */
+ return p;
+}
+
+@ Conversely, a one-word node is recycled by calling |free_avail|.
+
+@d free_avail(A) /* single-word node liberation */
+ { link((A))=mp->avail; mp->avail=(A); decr(mp->dyn_used); }
+
+@ There's also a |fast_get_avail| routine, which saves the procedure-call
+overhead at the expense of extra programming. This macro is used in
+the places that would otherwise account for the most calls of |get_avail|.
+@^inner loop@>
+
+@d fast_get_avail(A) {
+ (A)=mp->avail; /* avoid |get_avail| if possible, to save time */
+ if ( (A)==null ) { (A)=mp_get_avail(mp); }
+ else { mp->avail=link((A)); link((A))=null; incr(mp->dyn_used); }
+ }
+
+@ The available-space list that keeps track of the variable-size portion
+of |mem| is a nonempty, doubly-linked circular list of empty nodes,
+pointed to by the roving pointer |rover|.
+
+Each empty node has size 2 or more; the first word contains the special
+value |max_halfword| in its |link| field and the size in its |info| field;
+the second word contains the two pointers for double linking.
+
+Each nonempty node also has size 2 or more. Its first word is of type
+|two_halves|\kern-1pt, and its |link| field is never equal to |max_halfword|.
+Otherwise there is complete flexibility with respect to the contents
+of its other fields and its other words.
+
+(We require |mem_max<max_halfword| because terrible things can happen
+when |max_halfword| appears in the |link| field of a nonempty node.)
+
+@d empty_flag max_halfword /* the |link| of an empty variable-size node */
+@d is_empty(A) (link((A))==empty_flag) /* tests for empty node */
+@d node_size info /* the size field in empty variable-size nodes */
+@d llink(A) info((A)+1) /* left link in doubly-linked list of empty nodes */
+@d rlink(A) link((A)+1) /* right link in doubly-linked list of empty nodes */
+
+@<Glob...@>=
+pointer rover; /* points to some node in the list of empties */
+
+@ A call to |get_node| with argument |s| returns a pointer to a new node
+of size~|s|, which must be 2~or more. The |link| field of the first word
+of this new node is set to null. An overflow stop occurs if no suitable
+space exists.
+
+If |get_node| is called with $s=2^{30}$, it simply merges adjacent free
+areas and returns the value |max_halfword|.
+
+@<Internal library declarations@>=
+pointer mp_get_node (MP mp,integer s) ;
+
+@ @c
+pointer mp_get_node (MP mp,integer s) { /* variable-size node allocation */
+ pointer p; /* the node currently under inspection */
+ pointer q; /* the node physically after node |p| */
+ integer r; /* the newly allocated node, or a candidate for this honor */
+ integer t,tt; /* temporary registers */
+@^inner loop@>
+ RESTART:
+ p=mp->rover; /* start at some free node in the ring */
+ do {
+ @<Try to allocate within node |p| and its physical successors,
+ and |goto found| if allocation was possible@>;
+ if (rlink(p)==null || (rlink(p)==p && p!=mp->rover)) {
+ print_err("Free list garbled");
+ help3("I found an entry in the list of free nodes that links")
+ ("badly. I will try to ignore the broken link, but something")
+ ("is seriously amiss. It is wise to warn the maintainers.")
+ mp_error(mp);
+ rlink(p)=mp->rover;
+ }
+ p=rlink(p); /* move to the next node in the ring */
+ } while (p!=mp->rover); /* repeat until the whole list has been traversed */
+ if ( s==010000000000 ) {
+ return max_halfword;
+ };
+ if ( mp->lo_mem_max+2<mp->hi_mem_min ) {
+ if ( mp->lo_mem_max+2<=max_halfword ) {
+ @<Grow more variable-size memory and |goto restart|@>;
+ }
+ }
+ mp_overflow(mp, "main memory size",mp->mem_max);
+ /* sorry, nothing satisfactory is left */
+@:MetaPost capacity exceeded main memory size}{\quad main memory size@>
+FOUND:
+ link(r)=null; /* this node is now nonempty */
+ mp->var_used+=s; /* maintain usage statistics */
+ return r;
+}
+
+@ The lower part of |mem| grows by 1000 words at a time, unless
+we are very close to going under. When it grows, we simply link
+a new node into the available-space list. This method of controlled
+growth helps to keep the |mem| usage consecutive when \MP\ is
+implemented on ``virtual memory'' systems.
+@^virtual memory@>
+
+@<Grow more variable-size memory and |goto restart|@>=
+{
+ if ( mp->hi_mem_min-mp->lo_mem_max>=1998 ) {
+ t=mp->lo_mem_max+1000;
+ } else {
+ t=mp->lo_mem_max+1+(mp->hi_mem_min-mp->lo_mem_max) / 2;
+ /* |lo_mem_max+2<=t<hi_mem_min| */
+ }
+ if ( t>max_halfword ) t=max_halfword;
+ p=llink(mp->rover); q=mp->lo_mem_max; rlink(p)=q; llink(mp->rover)=q;
+ rlink(q)=mp->rover; llink(q)=p; link(q)=empty_flag;
+ node_size(q)=t-mp->lo_mem_max;
+ mp->lo_mem_max=t; link(mp->lo_mem_max)=null; info(mp->lo_mem_max)=null;
+ mp->rover=q;
+ goto RESTART;
+}
+
+@ @<Try to allocate...@>=
+q=p+node_size(p); /* find the physical successor */
+while ( is_empty(q) ) { /* merge node |p| with node |q| */
+ t=rlink(q); tt=llink(q);
+@^inner loop@>
+ if ( q==mp->rover ) mp->rover=t;
+ llink(t)=tt; rlink(tt)=t;
+ q=q+node_size(q);
+}
+r=q-s;
+if ( r>p+1 ) {
+ @<Allocate from the top of node |p| and |goto found|@>;
+}
+if ( r==p ) {
+ if ( rlink(p)!=p ) {
+ @<Allocate entire node |p| and |goto found|@>;
+ }
+}
+node_size(p)=q-p /* reset the size in case it grew */
+
+@ @<Allocate from the top...@>=
+{
+ node_size(p)=r-p; /* store the remaining size */
+ mp->rover=p; /* start searching here next time */
+ goto FOUND;
+}
+
+@ Here we delete node |p| from the ring, and let |rover| rove around.
+
+@<Allocate entire...@>=
+{
+ mp->rover=rlink(p); t=llink(p);
+ llink(mp->rover)=t; rlink(t)=mp->rover;
+ goto FOUND;
+}
+
+@ Conversely, when some variable-size node |p| of size |s| is no longer needed,
+the operation |free_node(p,s)| will make its words available, by inserting
+|p| as a new empty node just before where |rover| now points.
+
+@<Internal library declarations@>=
+void mp_free_node (MP mp, pointer p, halfword s) ;
+
+@ @c
+void mp_free_node (MP mp, pointer p, halfword s) { /* variable-size node
+ liberation */
+ pointer q; /* |llink(rover)| */
+ node_size(p)=s; link(p)=empty_flag;
+@^inner loop@>
+ q=llink(mp->rover); llink(p)=q; rlink(p)=mp->rover; /* set both links */
+ llink(mp->rover)=p; rlink(q)=p; /* insert |p| into the ring */
+ mp->var_used-=s; /* maintain statistics */
+}
+
+@ Just before \.{INIMP} writes out the memory, it sorts the doubly linked
+available space list. The list is probably very short at such times, so a
+simple insertion sort is used. The smallest available location will be
+pointed to by |rover|, the next-smallest by |rlink(rover)|, etc.
+
+@c
+void mp_sort_avail (MP mp) { /* sorts the available variable-size nodes
+ by location */
+ pointer p,q,r; /* indices into |mem| */
+ pointer old_rover; /* initial |rover| setting */
+ p=mp_get_node(mp, 010000000000); /* merge adjacent free areas */
+ p=rlink(mp->rover); rlink(mp->rover)=max_halfword; old_rover=mp->rover;
+ while ( p!=old_rover ) {
+ @<Sort |p| into the list starting at |rover|
+ and advance |p| to |rlink(p)|@>;
+ }
+ p=mp->rover;
+ while ( rlink(p)!=max_halfword ) {
+ llink(rlink(p))=p; p=rlink(p);
+ };
+ rlink(p)=mp->rover; llink(mp->rover)=p;
+}
+
+@ The following |while| loop is guaranteed to
+terminate, since the list that starts at
+|rover| ends with |max_halfword| during the sorting procedure.
+
+@<Sort |p|...@>=
+if ( p<mp->rover ) {
+ q=p; p=rlink(q); rlink(q)=mp->rover; mp->rover=q;
+} else {
+ q=mp->rover;
+ while ( rlink(q)<p ) q=rlink(q);
+ r=rlink(p); rlink(p)=rlink(q); rlink(q)=p; p=r;
+}
+
+@* \[11] Memory layout.
+Some areas of |mem| are dedicated to fixed usage, since static allocation is
+more efficient than dynamic allocation when we can get away with it. For
+example, locations |0| to |1| are always used to store a
+two-word dummy token whose second word is zero.
+The following macro definitions accomplish the static allocation by giving
+symbolic names to the fixed positions. Static variable-size nodes appear
+in locations |0| through |lo_mem_stat_max|, and static single-word nodes
+appear in locations |hi_mem_stat_min| through |mem_top|, inclusive.
+
+@d null_dash (2) /* the first two words are reserved for a null value */
+@d dep_head (null_dash+3) /* we will define |dash_node_size=3| */
+@d zero_val (dep_head+2) /* two words for a permanently zero value */
+@d temp_val (zero_val+2) /* two words for a temporary value node */
+@d end_attr temp_val /* we use |end_attr+2| only */
+@d inf_val (end_attr+2) /* and |inf_val+1| only */
+@d test_pen (inf_val+2)
+ /* nine words for a pen used when testing the turning number */
+@d bad_vardef (test_pen+9) /* two words for \&{vardef} error recovery */
+@d lo_mem_stat_max (bad_vardef+1) /* largest statically
+ allocated word in the variable-size |mem| */
+@#
+@d sentinel mp->mem_top /* end of sorted lists */
+@d temp_head (mp->mem_top-1) /* head of a temporary list of some kind */
+@d hold_head (mp->mem_top-2) /* head of a temporary list of another kind */
+@d spec_head (mp->mem_top-3) /* head of a list of unprocessed \&{special} items */
+@d hi_mem_stat_min (mp->mem_top-3) /* smallest statically allocated word in
+ the one-word |mem| */
+
+@ The following code gets the dynamic part of |mem| off to a good start,
+when \MP\ is initializing itself the slow way.
+
+@<Initialize table entries (done by \.{INIMP} only)@>=
+mp->rover=lo_mem_stat_max+1; /* initialize the dynamic memory */
+link(mp->rover)=empty_flag;
+node_size(mp->rover)=1000; /* which is a 1000-word available node */
+llink(mp->rover)=mp->rover; rlink(mp->rover)=mp->rover;
+mp->lo_mem_max=mp->rover+1000;
+link(mp->lo_mem_max)=null; info(mp->lo_mem_max)=null;
+for (k=hi_mem_stat_min;k<=(int)mp->mem_top;k++) {
+ mp->mem[k]=mp->mem[mp->lo_mem_max]; /* clear list heads */
+}
+mp->avail=null; mp->mem_end=mp->mem_top;
+mp->hi_mem_min=hi_mem_stat_min; /* initialize the one-word memory */
+mp->var_used=lo_mem_stat_max+1;
+mp->dyn_used=mp->mem_top+1-(hi_mem_stat_min); /* initialize statistics */
+@<Initialize a pen at |test_pen| so that it fits in nine words@>;
+
+@ The procedure |flush_list(p)| frees an entire linked list of one-word
+nodes that starts at a given position, until coming to |sentinel| or a
+pointer that is not in the one-word region. Another procedure,
+|flush_node_list|, frees an entire linked list of one-word and two-word
+nodes, until coming to a |null| pointer.
+@^inner loop@>
+
+@c
+void mp_flush_list (MP mp,pointer p) { /* makes list of single-word nodes available */
+ pointer q,r; /* list traversers */
+ if ( p>=mp->hi_mem_min ) if ( p!=sentinel ) {
+ r=p;
+ do {
+ q=r; r=link(r);
+ decr(mp->dyn_used);
+ if ( r<mp->hi_mem_min ) break;
+ } while (r!=sentinel);
+ /* now |q| is the last node on the list */
+ link(q)=mp->avail; mp->avail=p;
+ }
+}
+@#
+void mp_flush_node_list (MP mp,pointer p) {
+ pointer q; /* the node being recycled */
+ while ( p!=null ){
+ q=p; p=link(p);
+ if ( q<mp->hi_mem_min )
+ mp_free_node(mp, q,2);
+ else
+ free_avail(q);
+ }
+}
+
+@ If \MP\ is extended improperly, the |mem| array might get screwed up.
+For example, some pointers might be wrong, or some ``dead'' nodes might not
+have been freed when the last reference to them disappeared. Procedures
+|check_mem| and |search_mem| are available to help diagnose such
+problems. These procedures make use of two arrays called |free| and
+|was_free| that are present only if \MP's debugging routines have
+been included. (You may want to decrease the size of |mem| while you
+@^debugging@>
+are debugging.)
+
+Because |boolean|s are typedef-d as ints, it is better to use
+unsigned chars here.
+
+@<Glob...@>=
+unsigned char *free; /* free cells */
+unsigned char *was_free; /* previously free cells */
+pointer was_mem_end; pointer was_lo_max; pointer was_hi_min;
+ /* previous |mem_end|, |lo_mem_max|,and |hi_mem_min| */
+boolean panicking; /* do we want to check memory constantly? */
+
+@ @<Allocate or initialize ...@>=
+mp->free = xmalloc ((mp->mem_max+1),sizeof (unsigned char));
+mp->was_free = xmalloc ((mp->mem_max+1), sizeof (unsigned char));
+
+@ @<Dealloc variables@>=
+xfree(mp->free);
+xfree(mp->was_free);
+
+@ @<Allocate or ...@>=
+mp->was_mem_end=0; /* indicate that everything was previously free */
+mp->was_lo_max=0; mp->was_hi_min=mp->mem_max;
+mp->panicking=false;
+
+@ @<Declare |mp_reallocate| functions@>=
+void mp_reallocate_memory(MP mp, int l) ;
+
+@ @c
+void mp_reallocate_memory(MP mp, int l) {
+ XREALLOC(mp->free, l, unsigned char);
+ XREALLOC(mp->was_free, l, unsigned char);
+ if (mp->mem) {
+ int newarea = l-mp->mem_max;
+ XREALLOC(mp->mem, l, memory_word);
+ memset (mp->mem+(mp->mem_max+1),0,sizeof(memory_word)*(newarea));
+ } else {
+ XREALLOC(mp->mem, l, memory_word);
+ memset(mp->mem,0,sizeof(memory_word)*(l+1));
+ }
+ mp->mem_max = l;
+ if (mp->ini_version)
+ mp->mem_top = l;
+}
+
+
+
+@ Procedure |check_mem| makes sure that the available space lists of
+|mem| are well formed, and it optionally prints out all locations
+that are reserved now but were free the last time this procedure was called.
+
+@c
+void mp_check_mem (MP mp,boolean print_locs ) {
+ pointer p,q,r; /* current locations of interest in |mem| */
+ boolean clobbered; /* is something amiss? */
+ for (p=0;p<=mp->lo_mem_max;p++) {
+ mp->free[p]=false; /* you can probably do this faster */
+ }
+ for (p=mp->hi_mem_min;p<= mp->mem_end;p++) {
+ mp->free[p]=false; /* ditto */
+ }
+ @<Check single-word |avail| list@>;
+ @<Check variable-size |avail| list@>;
+ @<Check flags of unavailable nodes@>;
+ @<Check the list of linear dependencies@>;
+ if ( print_locs ) {
+ @<Print newly busy locations@>;
+ }
+ memcpy(mp->was_free,mp->free, sizeof(char)*(mp->mem_end+1));
+ mp->was_mem_end=mp->mem_end;
+ mp->was_lo_max=mp->lo_mem_max;
+ mp->was_hi_min=mp->hi_mem_min;
+}
+
+@ @<Check single-word...@>=
+p=mp->avail; q=null; clobbered=false;
+while ( p!=null ) {
+ if ( (p>mp->mem_end)||(p<mp->hi_mem_min) ) clobbered=true;
+ else if ( mp->free[p] ) clobbered=true;
+ if ( clobbered ) {
+ mp_print_nl(mp, "AVAIL list clobbered at ");
+@.AVAIL list clobbered...@>
+ mp_print_int(mp, q); break;
+ }
+ mp->free[p]=true; q=p; p=link(q);
+}
+
+@ @<Check variable-size...@>=
+p=mp->rover; q=null; clobbered=false;
+do {
+ if ( (p>=mp->lo_mem_max)||(p<0) ) clobbered=true;
+ else if ( (rlink(p)>=mp->lo_mem_max)||(rlink(p)<0) ) clobbered=true;
+ else if ( !(is_empty(p))||(node_size(p)<2)||
+ (p+node_size(p)>mp->lo_mem_max)|| (llink(rlink(p))!=p) ) clobbered=true;
+ if ( clobbered ) {
+ mp_print_nl(mp, "Double-AVAIL list clobbered at ");
+@.Double-AVAIL list clobbered...@>
+ mp_print_int(mp, q); break;
+ }
+ for (q=p;q<=p+node_size(p)-1;q++) { /* mark all locations free */
+ if ( mp->free[q] ) {
+ mp_print_nl(mp, "Doubly free location at ");
+@.Doubly free location...@>
+ mp_print_int(mp, q); break;
+ }
+ mp->free[q]=true;
+ }
+ q=p; p=rlink(p);
+} while (p!=mp->rover)
+
+
+@ @<Check flags...@>=
+p=0;
+while ( p<=mp->lo_mem_max ) { /* node |p| should not be empty */
+ if ( is_empty(p) ) {
+ mp_print_nl(mp, "Bad flag at "); mp_print_int(mp, p);
+@.Bad flag...@>
+ }
+ while ( (p<=mp->lo_mem_max) && ! mp->free[p] ) incr(p);
+ while ( (p<=mp->lo_mem_max) && mp->free[p] ) incr(p);
+}
+
+@ @<Print newly busy...@>=
+{
+ @<Do intialization required before printing new busy locations@>;
+ mp_print_nl(mp, "New busy locs:");
+@.New busy locs@>
+ for (p=0;p<= mp->lo_mem_max;p++ ) {
+ if ( ! mp->free[p] && ((p>mp->was_lo_max) || mp->was_free[p]) ) {
+ @<Indicate that |p| is a new busy location@>;
+ }
+ }
+ for (p=mp->hi_mem_min;p<=mp->mem_end;p++ ) {
+ if ( ! mp->free[p] &&
+ ((p<mp->was_hi_min) || (p>mp->was_mem_end) || mp->was_free[p]) ) {
+ @<Indicate that |p| is a new busy location@>;
+ }
+ }
+ @<Finish printing new busy locations@>;
+}
+
+@ There might be many new busy locations so we are careful to print contiguous
+blocks compactly. During this operation |q| is the last new busy location and
+|r| is the start of the block containing |q|.
+
+@<Indicate that |p| is a new busy location@>=
+{
+ if ( p>q+1 ) {
+ if ( q>r ) {
+ mp_print(mp, ".."); mp_print_int(mp, q);
+ }
+ mp_print_char(mp, ' '); mp_print_int(mp, p);
+ r=p;
+ }
+ q=p;
+}
+
+@ @<Do intialization required before printing new busy locations@>=
+q=mp->mem_max; r=mp->mem_max
+
+@ @<Finish printing new busy locations@>=
+if ( q>r ) {
+ mp_print(mp, ".."); mp_print_int(mp, q);
+}
+
+@ The |search_mem| procedure attempts to answer the question ``Who points
+to node~|p|?'' In doing so, it fetches |link| and |info| fields of |mem|
+that might not be of type |two_halves|. Strictly speaking, this is
+undefined, and it can lead to ``false drops'' (words that seem to
+point to |p| purely by coincidence). But for debugging purposes, we want
+to rule out the places that do {\sl not\/} point to |p|, so a few false
+drops are tolerable.
+
+@c
+void mp_search_mem (MP mp, pointer p) { /* look for pointers to |p| */
+ integer q; /* current position being searched */
+ for (q=0;q<=mp->lo_mem_max;q++) {
+ if ( link(q)==p ){
+ mp_print_nl(mp, "LINK("); mp_print_int(mp, q); mp_print_char(mp, ')');
+ }
+ if ( info(q)==p ) {
+ mp_print_nl(mp, "INFO("); mp_print_int(mp, q); mp_print_char(mp, ')');
+ }
+ }
+ for (q=mp->hi_mem_min;q<=mp->mem_end;q++) {
+ if ( link(q)==p ) {
+ mp_print_nl(mp, "LINK("); mp_print_int(mp, q); mp_print_char(mp, ')');
+ }
+ if ( info(q)==p ) {
+ mp_print_nl(mp, "INFO("); mp_print_int(mp, q); mp_print_char(mp, ')');
+ }
+ }
+ @<Search |eqtb| for equivalents equal to |p|@>;
+}
+
+@* \[12] The command codes.
+Before we can go much further, we need to define symbolic names for the internal
+code numbers that represent the various commands obeyed by \MP. These codes
+are somewhat arbitrary, but not completely so. For example,
+some codes have been made adjacent so that |case| statements in the
+program need not consider cases that are widely spaced, or so that |case|
+statements can be replaced by |if| statements. A command can begin an
+expression if and only if its code lies between |min_primary_command| and
+|max_primary_command|, inclusive. The first token of a statement that doesn't
+begin with an expression has a command code between |min_command| and
+|max_statement_command|, inclusive. Anything less than |min_command| is
+eliminated during macro expansions, and anything no more than |max_pre_command|
+is eliminated when expanding \TeX\ material. Ranges such as
+|min_secondary_command..max_secondary_command| are used when parsing
+expressions, but the relative ordering within such a range is generally not
+critical.
+
+The ordering of the highest-numbered commands
+(|comma<semicolon<end_group<stop|) is crucial for the parsing and
+error-recovery methods of this program as is the ordering |if_test<fi_or_else|
+for the smallest two commands. The ordering is also important in the ranges
+|numeric_token..plus_or_minus| and |left_brace..ampersand|.
+
+At any rate, here is the list, for future reference.
+
+@d start_tex 1 /* begin \TeX\ material (\&{btex}, \&{verbatimtex}) */
+@d etex_marker 2 /* end \TeX\ material (\&{etex}) */
+@d mpx_break 3 /* stop reading an \.{MPX} file (\&{mpxbreak}) */
+@d max_pre_command mpx_break
+@d if_test 4 /* conditional text (\&{if}) */
+@d fi_or_else 5 /* delimiters for conditionals (\&{elseif}, \&{else}, \&{fi}) */
+@d input 6 /* input a source file (\&{input}, \&{endinput}) */
+@d iteration 7 /* iterate (\&{for}, \&{forsuffixes}, \&{forever}, \&{endfor}) */
+@d repeat_loop 8 /* special command substituted for \&{endfor} */
+@d exit_test 9 /* premature exit from a loop (\&{exitif}) */
+@d relax 10 /* do nothing (\.{\char`\\}) */
+@d scan_tokens 11 /* put a string into the input buffer */
+@d expand_after 12 /* look ahead one token */
+@d defined_macro 13 /* a macro defined by the user */
+@d min_command (defined_macro+1)
+@d save_command 14 /* save a list of tokens (\&{save}) */
+@d interim_command 15 /* save an internal quantity (\&{interim}) */
+@d let_command 16 /* redefine a symbolic token (\&{let}) */
+@d new_internal 17 /* define a new internal quantity (\&{newinternal}) */
+@d macro_def 18 /* define a macro (\&{def}, \&{vardef}, etc.) */
+@d ship_out_command 19 /* output a character (\&{shipout}) */
+@d add_to_command 20 /* add to edges (\&{addto}) */
+@d bounds_command 21 /* add bounding path to edges (\&{setbounds}, \&{clip}) */
+@d tfm_command 22 /* command for font metric info (\&{ligtable}, etc.) */
+@d protection_command 23 /* set protection flag (\&{outer}, \&{inner}) */
+@d show_command 24 /* diagnostic output (\&{show}, \&{showvariable}, etc.) */
+@d mode_command 25 /* set interaction level (\&{batchmode}, etc.) */
+@d mp_random_seed 26 /* initialize random number generator (\&{randomseed}) */
+@d message_command 27 /* communicate to user (\&{message}, \&{errmessage}) */
+@d every_job_command 28 /* designate a starting token (\&{everyjob}) */
+@d delimiters 29 /* define a pair of delimiters (\&{delimiters}) */
+@d special_command 30 /* output special info (\&{special})
+ or font map info (\&{fontmapfile}, \&{fontmapline}) */
+@d write_command 31 /* write text to a file (\&{write}) */
+@d type_name 32 /* declare a type (\&{numeric}, \&{pair}, etc.) */
+@d max_statement_command type_name
+@d min_primary_command type_name
+@d left_delimiter 33 /* the left delimiter of a matching pair */
+@d begin_group 34 /* beginning of a group (\&{begingroup}) */
+@d nullary 35 /* an operator without arguments (e.g., \&{normaldeviate}) */
+@d unary 36 /* an operator with one argument (e.g., \&{sqrt}) */
+@d str_op 37 /* convert a suffix to a string (\&{str}) */
+@d cycle 38 /* close a cyclic path (\&{cycle}) */
+@d primary_binary 39 /* binary operation taking `\&{of}' (e.g., \&{point}) */
+@d capsule_token 40 /* a value that has been put into a token list */
+@d string_token 41 /* a string constant (e.g., |"hello"|) */
+@d internal_quantity 42 /* internal numeric parameter (e.g., \&{pausing}) */
+@d min_suffix_token internal_quantity
+@d tag_token 43 /* a symbolic token without a primitive meaning */
+@d numeric_token 44 /* a numeric constant (e.g., \.{3.14159}) */
+@d max_suffix_token numeric_token
+@d plus_or_minus 45 /* either `\.+' or `\.-' */
+@d max_primary_command plus_or_minus /* should also be |numeric_token+1| */
+@d min_tertiary_command plus_or_minus
+@d tertiary_secondary_macro 46 /* a macro defined by \&{secondarydef} */
+@d tertiary_binary 47 /* an operator at the tertiary level (e.g., `\.{++}') */
+@d max_tertiary_command tertiary_binary
+@d left_brace 48 /* the operator `\.{\char`\{}' */
+@d min_expression_command left_brace
+@d path_join 49 /* the operator `\.{..}' */
+@d ampersand 50 /* the operator `\.\&' */
+@d expression_tertiary_macro 51 /* a macro defined by \&{tertiarydef} */
+@d expression_binary 52 /* an operator at the expression level (e.g., `\.<') */
+@d equals 53 /* the operator `\.=' */
+@d max_expression_command equals
+@d and_command 54 /* the operator `\&{and}' */
+@d min_secondary_command and_command
+@d secondary_primary_macro 55 /* a macro defined by \&{primarydef} */
+@d slash 56 /* the operator `\./' */
+@d secondary_binary 57 /* an operator at the binary level (e.g., \&{shifted}) */
+@d max_secondary_command secondary_binary
+@d param_type 58 /* type of parameter (\&{primary}, \&{expr}, \&{suffix}, etc.) */
+@d controls 59 /* specify control points explicitly (\&{controls}) */
+@d tension 60 /* specify tension between knots (\&{tension}) */
+@d at_least 61 /* bounded tension value (\&{atleast}) */
+@d curl_command 62 /* specify curl at an end knot (\&{curl}) */
+@d macro_special 63 /* special macro operators (\&{quote}, \.{\#\AT!}, etc.) */
+@d right_delimiter 64 /* the right delimiter of a matching pair */
+@d left_bracket 65 /* the operator `\.[' */
+@d right_bracket 66 /* the operator `\.]' */
+@d right_brace 67 /* the operator `\.{\char`\}}' */
+@d with_option 68 /* option for filling (\&{withpen}, \&{withweight}, etc.) */
+@d thing_to_add 69
+ /* variant of \&{addto} (\&{contour}, \&{doublepath}, \&{also}) */
+@d of_token 70 /* the operator `\&{of}' */
+@d to_token 71 /* the operator `\&{to}' */
+@d step_token 72 /* the operator `\&{step}' */
+@d until_token 73 /* the operator `\&{until}' */
+@d within_token 74 /* the operator `\&{within}' */
+@d lig_kern_token 75
+ /* the operators `\&{kern}' and `\.{=:}' and `\.{=:\char'174}', etc. */
+@d assignment 76 /* the operator `\.{:=}' */
+@d skip_to 77 /* the operation `\&{skipto}' */
+@d bchar_label 78 /* the operator `\.{\char'174\char'174:}' */
+@d double_colon 79 /* the operator `\.{::}' */
+@d colon 80 /* the operator `\.:' */
+@#
+@d comma 81 /* the operator `\.,', must be |colon+1| */
+@d end_of_statement (mp->cur_cmd>comma)
+@d semicolon 82 /* the operator `\.;', must be |comma+1| */
+@d end_group 83 /* end a group (\&{endgroup}), must be |semicolon+1| */
+@d stop 84 /* end a job (\&{end}, \&{dump}), must be |end_group+1| */
+@d max_command_code stop
+@d outer_tag (max_command_code+1) /* protection code added to command code */
+
+@<Types...@>=
+typedef int command_code;
+
+@ Variables and capsules in \MP\ have a variety of ``types,''
+distinguished by the code numbers defined here. These numbers are also
+not completely arbitrary. Things that get expanded must have types
+|>mp_independent|; a type remaining after expansion is numeric if and only if
+its code number is at least |numeric_type|; objects containing numeric
+parts must have types between |transform_type| and |pair_type|;
+all other types must be smaller than |transform_type|; and among the types
+that are not unknown or vacuous, the smallest two must be |boolean_type|
+and |string_type| in that order.
+
+@d undefined 0 /* no type has been declared */
+@d unknown_tag 1 /* this constant is added to certain type codes below */
+@d unknown_types mp_unknown_boolean: case mp_unknown_string:
+ case mp_unknown_pen: case mp_unknown_picture: case mp_unknown_path
+
+@<Types...@>=
+enum mp_variable_type {
+mp_vacuous=1, /* no expression was present */
+mp_boolean_type, /* \&{boolean} with a known value */
+mp_unknown_boolean,
+mp_string_type, /* \&{string} with a known value */
+mp_unknown_string,
+mp_pen_type, /* \&{pen} with a known value */
+mp_unknown_pen,
+mp_path_type, /* \&{path} with a known value */
+mp_unknown_path,
+mp_picture_type, /* \&{picture} with a known value */
+mp_unknown_picture,
+mp_transform_type, /* \&{transform} variable or capsule */
+mp_color_type, /* \&{color} variable or capsule */
+mp_cmykcolor_type, /* \&{cmykcolor} variable or capsule */
+mp_pair_type, /* \&{pair} variable or capsule */
+mp_numeric_type, /* variable that has been declared \&{numeric} but not used */
+mp_known, /* \&{numeric} with a known value */
+mp_dependent, /* a linear combination with |fraction| coefficients */
+mp_proto_dependent, /* a linear combination with |scaled| coefficients */
+mp_independent, /* \&{numeric} with unknown value */
+mp_token_list, /* variable name or suffix argument or text argument */
+mp_structured, /* variable with subscripts and attributes */
+mp_unsuffixed_macro, /* variable defined with \&{vardef} but no \.{\AT!\#} */
+mp_suffixed_macro /* variable defined with \&{vardef} and \.{\AT!\#} */
+} ;
+
+@ @<Declarations@>=
+void mp_print_type (MP mp,small_number t) ;
+
+@ @<Basic printing procedures@>=
+void mp_print_type (MP mp,small_number t) {
+ switch (t) {
+ case mp_vacuous:mp_print(mp, "mp_vacuous"); break;
+ case mp_boolean_type:mp_print(mp, "boolean"); break;
+ case mp_unknown_boolean:mp_print(mp, "unknown boolean"); break;
+ case mp_string_type:mp_print(mp, "string"); break;
+ case mp_unknown_string:mp_print(mp, "unknown string"); break;
+ case mp_pen_type:mp_print(mp, "pen"); break;
+ case mp_unknown_pen:mp_print(mp, "unknown pen"); break;
+ case mp_path_type:mp_print(mp, "path"); break;
+ case mp_unknown_path:mp_print(mp, "unknown path"); break;
+ case mp_picture_type:mp_print(mp, "picture"); break;
+ case mp_unknown_picture:mp_print(mp, "unknown picture"); break;
+ case mp_transform_type:mp_print(mp, "transform"); break;
+ case mp_color_type:mp_print(mp, "color"); break;
+ case mp_cmykcolor_type:mp_print(mp, "cmykcolor"); break;
+ case mp_pair_type:mp_print(mp, "pair"); break;
+ case mp_known:mp_print(mp, "known numeric"); break;
+ case mp_dependent:mp_print(mp, "dependent"); break;
+ case mp_proto_dependent:mp_print(mp, "proto-dependent"); break;
+ case mp_numeric_type:mp_print(mp, "numeric"); break;
+ case mp_independent:mp_print(mp, "independent"); break;
+ case mp_token_list:mp_print(mp, "token list"); break;
+ case mp_structured:mp_print(mp, "mp_structured"); break;
+ case mp_unsuffixed_macro:mp_print(mp, "unsuffixed macro"); break;
+ case mp_suffixed_macro:mp_print(mp, "suffixed macro"); break;
+ default: mp_print(mp, "undefined"); break;
+ }
+}
+
+@ Values inside \MP\ are stored in two-word nodes that have a |name_type|
+as well as a |type|. The possibilities for |name_type| are defined
+here; they will be explained in more detail later.
+
+@<Types...@>=
+enum mp_name_type {
+ mp_root=0, /* |name_type| at the top level of a variable */
+ mp_saved_root, /* same, when the variable has been saved */
+ mp_structured_root, /* |name_type| where a |mp_structured| branch occurs */
+ mp_subscr, /* |name_type| in a subscript node */
+ mp_attr, /* |name_type| in an attribute node */
+ mp_x_part_sector, /* |name_type| in the \&{xpart} of a node */
+ mp_y_part_sector, /* |name_type| in the \&{ypart} of a node */
+ mp_xx_part_sector, /* |name_type| in the \&{xxpart} of a node */
+ mp_xy_part_sector, /* |name_type| in the \&{xypart} of a node */
+ mp_yx_part_sector, /* |name_type| in the \&{yxpart} of a node */
+ mp_yy_part_sector, /* |name_type| in the \&{yypart} of a node */
+ mp_red_part_sector, /* |name_type| in the \&{redpart} of a node */
+ mp_green_part_sector, /* |name_type| in the \&{greenpart} of a node */
+ mp_blue_part_sector, /* |name_type| in the \&{bluepart} of a node */
+ mp_cyan_part_sector, /* |name_type| in the \&{redpart} of a node */
+ mp_magenta_part_sector, /* |name_type| in the \&{greenpart} of a node */
+ mp_yellow_part_sector, /* |name_type| in the \&{bluepart} of a node */
+ mp_black_part_sector, /* |name_type| in the \&{greenpart} of a node */
+ mp_grey_part_sector, /* |name_type| in the \&{bluepart} of a node */
+ mp_capsule, /* |name_type| in stashed-away subexpressions */
+ mp_token /* |name_type| in a numeric token or string token */
+};
+
+@ Primitive operations that produce values have a secondary identification
+code in addition to their command code; it's something like genera and species.
+For example, `\.*' has the command code |primary_binary|, and its
+secondary identification is |times|. The secondary codes start at 30 so that
+they don't overlap with the type codes; some type codes (e.g., |mp_string_type|)
+are used as operators as well as type identifications. The relative values
+are not critical, except for |true_code..false_code|, |or_op..and_op|,
+and |filled_op..bounded_op|. The restrictions are that
+|and_op-false_code=or_op-true_code|, that the ordering of
+|x_part...blue_part| must match that of |x_part_sector..mp_blue_part_sector|,
+and the ordering of |filled_op..bounded_op| must match that of the code
+values they test for.
+
+@d true_code 30 /* operation code for \.{true} */
+@d false_code 31 /* operation code for \.{false} */
+@d null_picture_code 32 /* operation code for \.{nullpicture} */
+@d null_pen_code 33 /* operation code for \.{nullpen} */
+@d job_name_op 34 /* operation code for \.{jobname} */
+@d read_string_op 35 /* operation code for \.{readstring} */
+@d pen_circle 36 /* operation code for \.{pencircle} */
+@d normal_deviate 37 /* operation code for \.{normaldeviate} */
+@d read_from_op 38 /* operation code for \.{readfrom} */
+@d close_from_op 39 /* operation code for \.{closefrom} */
+@d odd_op 40 /* operation code for \.{odd} */
+@d known_op 41 /* operation code for \.{known} */
+@d unknown_op 42 /* operation code for \.{unknown} */
+@d not_op 43 /* operation code for \.{not} */
+@d decimal 44 /* operation code for \.{decimal} */
+@d reverse 45 /* operation code for \.{reverse} */
+@d make_path_op 46 /* operation code for \.{makepath} */
+@d make_pen_op 47 /* operation code for \.{makepen} */
+@d oct_op 48 /* operation code for \.{oct} */
+@d hex_op 49 /* operation code for \.{hex} */
+@d ASCII_op 50 /* operation code for \.{ASCII} */
+@d char_op 51 /* operation code for \.{char} */
+@d length_op 52 /* operation code for \.{length} */
+@d turning_op 53 /* operation code for \.{turningnumber} */
+@d color_model_part 54 /* operation code for \.{colormodel} */
+@d x_part 55 /* operation code for \.{xpart} */
+@d y_part 56 /* operation code for \.{ypart} */
+@d xx_part 57 /* operation code for \.{xxpart} */
+@d xy_part 58 /* operation code for \.{xypart} */
+@d yx_part 59 /* operation code for \.{yxpart} */
+@d yy_part 60 /* operation code for \.{yypart} */
+@d red_part 61 /* operation code for \.{redpart} */
+@d green_part 62 /* operation code for \.{greenpart} */
+@d blue_part 63 /* operation code for \.{bluepart} */
+@d cyan_part 64 /* operation code for \.{cyanpart} */
+@d magenta_part 65 /* operation code for \.{magentapart} */
+@d yellow_part 66 /* operation code for \.{yellowpart} */
+@d black_part 67 /* operation code for \.{blackpart} */
+@d grey_part 68 /* operation code for \.{greypart} */
+@d font_part 69 /* operation code for \.{fontpart} */
+@d text_part 70 /* operation code for \.{textpart} */
+@d path_part 71 /* operation code for \.{pathpart} */
+@d pen_part 72 /* operation code for \.{penpart} */
+@d dash_part 73 /* operation code for \.{dashpart} */
+@d sqrt_op 74 /* operation code for \.{sqrt} */
+@d m_exp_op 75 /* operation code for \.{mexp} */
+@d m_log_op 76 /* operation code for \.{mlog} */
+@d sin_d_op 77 /* operation code for \.{sind} */
+@d cos_d_op 78 /* operation code for \.{cosd} */
+@d floor_op 79 /* operation code for \.{floor} */
+@d uniform_deviate 80 /* operation code for \.{uniformdeviate} */
+@d char_exists_op 81 /* operation code for \.{charexists} */
+@d font_size 82 /* operation code for \.{fontsize} */
+@d ll_corner_op 83 /* operation code for \.{llcorner} */
+@d lr_corner_op 84 /* operation code for \.{lrcorner} */
+@d ul_corner_op 85 /* operation code for \.{ulcorner} */
+@d ur_corner_op 86 /* operation code for \.{urcorner} */
+@d arc_length 87 /* operation code for \.{arclength} */
+@d angle_op 88 /* operation code for \.{angle} */
+@d cycle_op 89 /* operation code for \.{cycle} */
+@d filled_op 90 /* operation code for \.{filled} */
+@d stroked_op 91 /* operation code for \.{stroked} */
+@d textual_op 92 /* operation code for \.{textual} */
+@d clipped_op 93 /* operation code for \.{clipped} */
+@d bounded_op 94 /* operation code for \.{bounded} */
+@d plus 95 /* operation code for \.+ */
+@d minus 96 /* operation code for \.- */
+@d times 97 /* operation code for \.* */
+@d over 98 /* operation code for \./ */
+@d pythag_add 99 /* operation code for \.{++} */
+@d pythag_sub 100 /* operation code for \.{+-+} */
+@d or_op 101 /* operation code for \.{or} */
+@d and_op 102 /* operation code for \.{and} */
+@d less_than 103 /* operation code for \.< */
+@d less_or_equal 104 /* operation code for \.{<=} */
+@d greater_than 105 /* operation code for \.> */
+@d greater_or_equal 106 /* operation code for \.{>=} */
+@d equal_to 107 /* operation code for \.= */
+@d unequal_to 108 /* operation code for \.{<>} */
+@d concatenate 109 /* operation code for \.\& */
+@d rotated_by 110 /* operation code for \.{rotated} */
+@d slanted_by 111 /* operation code for \.{slanted} */
+@d scaled_by 112 /* operation code for \.{scaled} */
+@d shifted_by 113 /* operation code for \.{shifted} */
+@d transformed_by 114 /* operation code for \.{transformed} */
+@d x_scaled 115 /* operation code for \.{xscaled} */
+@d y_scaled 116 /* operation code for \.{yscaled} */
+@d z_scaled 117 /* operation code for \.{zscaled} */
+@d in_font 118 /* operation code for \.{infont} */
+@d intersect 119 /* operation code for \.{intersectiontimes} */
+@d double_dot 120 /* operation code for improper \.{..} */
+@d substring_of 121 /* operation code for \.{substring} */
+@d min_of substring_of
+@d subpath_of 122 /* operation code for \.{subpath} */
+@d direction_time_of 123 /* operation code for \.{directiontime} */
+@d point_of 124 /* operation code for \.{point} */
+@d precontrol_of 125 /* operation code for \.{precontrol} */
+@d postcontrol_of 126 /* operation code for \.{postcontrol} */
+@d pen_offset_of 127 /* operation code for \.{penoffset} */
+@d arc_time_of 128 /* operation code for \.{arctime} */
+@d mp_version 129 /* operation code for \.{mpversion} */
+@d envelope_of 130 /* operation code for \.{envelope} */
+
+@c void mp_print_op (MP mp,quarterword c) {
+ if (c<=mp_numeric_type ) {
+ mp_print_type(mp, c);
+ } else {
+ switch (c) {
+ case true_code:mp_print(mp, "true"); break;
+ case false_code:mp_print(mp, "false"); break;
+ case null_picture_code:mp_print(mp, "nullpicture"); break;
+ case null_pen_code:mp_print(mp, "nullpen"); break;
+ case job_name_op:mp_print(mp, "jobname"); break;
+ case read_string_op:mp_print(mp, "readstring"); break;
+ case pen_circle:mp_print(mp, "pencircle"); break;
+ case normal_deviate:mp_print(mp, "normaldeviate"); break;
+ case read_from_op:mp_print(mp, "readfrom"); break;
+ case close_from_op:mp_print(mp, "closefrom"); break;
+ case odd_op:mp_print(mp, "odd"); break;
+ case known_op:mp_print(mp, "known"); break;
+ case unknown_op:mp_print(mp, "unknown"); break;
+ case not_op:mp_print(mp, "not"); break;
+ case decimal:mp_print(mp, "decimal"); break;
+ case reverse:mp_print(mp, "reverse"); break;
+ case make_path_op:mp_print(mp, "makepath"); break;
+ case make_pen_op:mp_print(mp, "makepen"); break;
+ case oct_op:mp_print(mp, "oct"); break;
+ case hex_op:mp_print(mp, "hex"); break;
+ case ASCII_op:mp_print(mp, "ASCII"); break;
+ case char_op:mp_print(mp, "char"); break;
+ case length_op:mp_print(mp, "length"); break;
+ case turning_op:mp_print(mp, "turningnumber"); break;
+ case x_part:mp_print(mp, "xpart"); break;
+ case y_part:mp_print(mp, "ypart"); break;
+ case xx_part:mp_print(mp, "xxpart"); break;
+ case xy_part:mp_print(mp, "xypart"); break;
+ case yx_part:mp_print(mp, "yxpart"); break;
+ case yy_part:mp_print(mp, "yypart"); break;
+ case red_part:mp_print(mp, "redpart"); break;
+ case green_part:mp_print(mp, "greenpart"); break;
+ case blue_part:mp_print(mp, "bluepart"); break;
+ case cyan_part:mp_print(mp, "cyanpart"); break;
+ case magenta_part:mp_print(mp, "magentapart"); break;
+ case yellow_part:mp_print(mp, "yellowpart"); break;
+ case black_part:mp_print(mp, "blackpart"); break;
+ case grey_part:mp_print(mp, "greypart"); break;
+ case color_model_part:mp_print(mp, "colormodel"); break;
+ case font_part:mp_print(mp, "fontpart"); break;
+ case text_part:mp_print(mp, "textpart"); break;
+ case path_part:mp_print(mp, "pathpart"); break;
+ case pen_part:mp_print(mp, "penpart"); break;
+ case dash_part:mp_print(mp, "dashpart"); break;
+ case sqrt_op:mp_print(mp, "sqrt"); break;
+ case m_exp_op:mp_print(mp, "mexp"); break;
+ case m_log_op:mp_print(mp, "mlog"); break;
+ case sin_d_op:mp_print(mp, "sind"); break;
+ case cos_d_op:mp_print(mp, "cosd"); break;
+ case floor_op:mp_print(mp, "floor"); break;
+ case uniform_deviate:mp_print(mp, "uniformdeviate"); break;
+ case char_exists_op:mp_print(mp, "charexists"); break;
+ case font_size:mp_print(mp, "fontsize"); break;
+ case ll_corner_op:mp_print(mp, "llcorner"); break;
+ case lr_corner_op:mp_print(mp, "lrcorner"); break;
+ case ul_corner_op:mp_print(mp, "ulcorner"); break;
+ case ur_corner_op:mp_print(mp, "urcorner"); break;
+ case arc_length:mp_print(mp, "arclength"); break;
+ case angle_op:mp_print(mp, "angle"); break;
+ case cycle_op:mp_print(mp, "cycle"); break;
+ case filled_op:mp_print(mp, "filled"); break;
+ case stroked_op:mp_print(mp, "stroked"); break;
+ case textual_op:mp_print(mp, "textual"); break;
+ case clipped_op:mp_print(mp, "clipped"); break;
+ case bounded_op:mp_print(mp, "bounded"); break;
+ case plus:mp_print_char(mp, '+'); break;
+ case minus:mp_print_char(mp, '-'); break;
+ case times:mp_print_char(mp, '*'); break;
+ case over:mp_print_char(mp, '/'); break;
+ case pythag_add:mp_print(mp, "++"); break;
+ case pythag_sub:mp_print(mp, "+-+"); break;
+ case or_op:mp_print(mp, "or"); break;
+ case and_op:mp_print(mp, "and"); break;
+ case less_than:mp_print_char(mp, '<'); break;
+ case less_or_equal:mp_print(mp, "<="); break;
+ case greater_than:mp_print_char(mp, '>'); break;
+ case greater_or_equal:mp_print(mp, ">="); break;
+ case equal_to:mp_print_char(mp, '='); break;
+ case unequal_to:mp_print(mp, "<>"); break;
+ case concatenate:mp_print(mp, "&"); break;
+ case rotated_by:mp_print(mp, "rotated"); break;
+ case slanted_by:mp_print(mp, "slanted"); break;
+ case scaled_by:mp_print(mp, "scaled"); break;
+ case shifted_by:mp_print(mp, "shifted"); break;
+ case transformed_by:mp_print(mp, "transformed"); break;
+ case x_scaled:mp_print(mp, "xscaled"); break;
+ case y_scaled:mp_print(mp, "yscaled"); break;
+ case z_scaled:mp_print(mp, "zscaled"); break;
+ case in_font:mp_print(mp, "infont"); break;
+ case intersect:mp_print(mp, "intersectiontimes"); break;
+ case substring_of:mp_print(mp, "substring"); break;
+ case subpath_of:mp_print(mp, "subpath"); break;
+ case direction_time_of:mp_print(mp, "directiontime"); break;
+ case point_of:mp_print(mp, "point"); break;
+ case precontrol_of:mp_print(mp, "precontrol"); break;
+ case postcontrol_of:mp_print(mp, "postcontrol"); break;
+ case pen_offset_of:mp_print(mp, "penoffset"); break;
+ case arc_time_of:mp_print(mp, "arctime"); break;
+ case mp_version:mp_print(mp, "mpversion"); break;
+ case envelope_of:mp_print(mp, "envelope"); break;
+ default: mp_print(mp, ".."); break;
+ }
+ }
+}
+
+@ \MP\ also has a bunch of internal parameters that a user might want to
+fuss with. Every such parameter has an identifying code number, defined here.
+
+@<Types...@>=
+enum mp_given_internal {
+ mp_tracing_titles=1, /* show titles online when they appear */
+ mp_tracing_equations, /* show each variable when it becomes known */
+ mp_tracing_capsules, /* show capsules too */
+ mp_tracing_choices, /* show the control points chosen for paths */
+ mp_tracing_specs, /* show path subdivision prior to filling with polygonal a pen */
+ mp_tracing_commands, /* show commands and operations before they are performed */
+ mp_tracing_restores, /* show when a variable or internal is restored */
+ mp_tracing_macros, /* show macros before they are expanded */
+ mp_tracing_output, /* show digitized edges as they are output */
+ mp_tracing_stats, /* show memory usage at end of job */
+ mp_tracing_lost_chars, /* show characters that aren't \&{infont} */
+ mp_tracing_online, /* show long diagnostics on terminal and in the log file */
+ mp_year, /* the current year (e.g., 1984) */
+ mp_month, /* the current month (e.g., 3 $\equiv$ March) */
+ mp_day, /* the current day of the month */
+ mp_time, /* the number of minutes past midnight when this job started */
+ mp_char_code, /* the number of the next character to be output */
+ mp_char_ext, /* the extension code of the next character to be output */
+ mp_char_wd, /* the width of the next character to be output */
+ mp_char_ht, /* the height of the next character to be output */
+ mp_char_dp, /* the depth of the next character to be output */
+ mp_char_ic, /* the italic correction of the next character to be output */
+ mp_design_size, /* the unit of measure used for |mp_char_wd..mp_char_ic|, in points */
+ mp_pausing, /* positive to display lines on the terminal before they are read */
+ mp_showstopping, /* positive to stop after each \&{show} command */
+ mp_fontmaking, /* positive if font metric output is to be produced */
+ mp_linejoin, /* as in \ps: 0 for mitered, 1 for round, 2 for beveled */
+ mp_linecap, /* as in \ps: 0 for butt, 1 for round, 2 for square */
+ mp_miterlimit, /* controls miter length as in \ps */
+ mp_warning_check, /* controls error message when variable value is large */
+ mp_boundary_char, /* the right boundary character for ligatures */
+ mp_prologues, /* positive to output conforming PostScript using built-in fonts */
+ mp_true_corners, /* positive to make \&{llcorner} etc. ignore \&{setbounds} */
+ mp_default_color_model, /* the default color model for unspecified items */
+ mp_restore_clip_color,
+ mp_procset, /* wether or not create PostScript command shortcuts */
+ mp_gtroffmode /* whether the user specified |-troff| on the command line */
+};
+
+@
+
+@d max_given_internal mp_gtroffmode
+
+@<Glob...@>=
+scaled *internal; /* the values of internal quantities */
+char **int_name; /* their names */
+int int_ptr; /* the maximum internal quantity defined so far */
+int max_internal; /* current maximum number of internal quantities */
+
+@ @<Option variables@>=
+int troff_mode;
+
+@ @<Allocate or initialize ...@>=
+mp->max_internal=2*max_given_internal;
+mp->internal = xmalloc ((mp->max_internal+1), sizeof(scaled));
+mp->int_name = xmalloc ((mp->max_internal+1), sizeof(char *));
+mp->troff_mode=(opt->troff_mode>0 ? true : false);
+
+@ @<Exported function ...@>=
+int mp_troff_mode(MP mp);
+
+@ @c
+int mp_troff_mode(MP mp) { return mp->troff_mode; }
+
+@ @<Set initial ...@>=
+for (k=0;k<= mp->max_internal; k++ ) {
+ mp->internal[k]=0;
+ mp->int_name[k]=NULL;
+}
+mp->int_ptr=max_given_internal;
+
+@ The symbolic names for internal quantities are put into \MP's hash table
+by using a routine called |primitive|, which will be defined later. Let us
+enter them now, so that we don't have to list all those names again
+anywhere else.
+
+@<Put each of \MP's primitives into the hash table@>=
+mp_primitive(mp, "tracingtitles",internal_quantity,mp_tracing_titles);
+@:tracingtitles_}{\&{tracingtitles} primitive@>
+mp_primitive(mp, "tracingequations",internal_quantity,mp_tracing_equations);
+@:mp_tracing_equations_}{\&{tracingequations} primitive@>
+mp_primitive(mp, "tracingcapsules",internal_quantity,mp_tracing_capsules);
+@:mp_tracing_capsules_}{\&{tracingcapsules} primitive@>
+mp_primitive(mp, "tracingchoices",internal_quantity,mp_tracing_choices);
+@:mp_tracing_choices_}{\&{tracingchoices} primitive@>
+mp_primitive(mp, "tracingspecs",internal_quantity,mp_tracing_specs);
+@:mp_tracing_specs_}{\&{tracingspecs} primitive@>
+mp_primitive(mp, "tracingcommands",internal_quantity,mp_tracing_commands);
+@:mp_tracing_commands_}{\&{tracingcommands} primitive@>
+mp_primitive(mp, "tracingrestores",internal_quantity,mp_tracing_restores);
+@:mp_tracing_restores_}{\&{tracingrestores} primitive@>
+mp_primitive(mp, "tracingmacros",internal_quantity,mp_tracing_macros);
+@:mp_tracing_macros_}{\&{tracingmacros} primitive@>
+mp_primitive(mp, "tracingoutput",internal_quantity,mp_tracing_output);
+@:mp_tracing_output_}{\&{tracingoutput} primitive@>
+mp_primitive(mp, "tracingstats",internal_quantity,mp_tracing_stats);
+@:mp_tracing_stats_}{\&{tracingstats} primitive@>
+mp_primitive(mp, "tracinglostchars",internal_quantity,mp_tracing_lost_chars);
+@:mp_tracing_lost_chars_}{\&{tracinglostchars} primitive@>
+mp_primitive(mp, "tracingonline",internal_quantity,mp_tracing_online);
+@:mp_tracing_online_}{\&{tracingonline} primitive@>
+mp_primitive(mp, "year",internal_quantity,mp_year);
+@:mp_year_}{\&{year} primitive@>
+mp_primitive(mp, "month",internal_quantity,mp_month);
+@:mp_month_}{\&{month} primitive@>
+mp_primitive(mp, "day",internal_quantity,mp_day);
+@:mp_day_}{\&{day} primitive@>
+mp_primitive(mp, "time",internal_quantity,mp_time);
+@:time_}{\&{time} primitive@>
+mp_primitive(mp, "charcode",internal_quantity,mp_char_code);
+@:mp_char_code_}{\&{charcode} primitive@>
+mp_primitive(mp, "charext",internal_quantity,mp_char_ext);
+@:mp_char_ext_}{\&{charext} primitive@>
+mp_primitive(mp, "charwd",internal_quantity,mp_char_wd);
+@:mp_char_wd_}{\&{charwd} primitive@>
+mp_primitive(mp, "charht",internal_quantity,mp_char_ht);
+@:mp_char_ht_}{\&{charht} primitive@>
+mp_primitive(mp, "chardp",internal_quantity,mp_char_dp);
+@:mp_char_dp_}{\&{chardp} primitive@>
+mp_primitive(mp, "charic",internal_quantity,mp_char_ic);
+@:mp_char_ic_}{\&{charic} primitive@>
+mp_primitive(mp, "designsize",internal_quantity,mp_design_size);
+@:mp_design_size_}{\&{designsize} primitive@>
+mp_primitive(mp, "pausing",internal_quantity,mp_pausing);
+@:mp_pausing_}{\&{pausing} primitive@>
+mp_primitive(mp, "showstopping",internal_quantity,mp_showstopping);
+@:mp_showstopping_}{\&{showstopping} primitive@>
+mp_primitive(mp, "fontmaking",internal_quantity,mp_fontmaking);
+@:mp_fontmaking_}{\&{fontmaking} primitive@>
+mp_primitive(mp, "linejoin",internal_quantity,mp_linejoin);
+@:mp_linejoin_}{\&{linejoin} primitive@>
+mp_primitive(mp, "linecap",internal_quantity,mp_linecap);
+@:mp_linecap_}{\&{linecap} primitive@>
+mp_primitive(mp, "miterlimit",internal_quantity,mp_miterlimit);
+@:mp_miterlimit_}{\&{miterlimit} primitive@>
+mp_primitive(mp, "warningcheck",internal_quantity,mp_warning_check);
+@:mp_warning_check_}{\&{warningcheck} primitive@>
+mp_primitive(mp, "boundarychar",internal_quantity,mp_boundary_char);
+@:mp_boundary_char_}{\&{boundarychar} primitive@>
+mp_primitive(mp, "prologues",internal_quantity,mp_prologues);
+@:mp_prologues_}{\&{prologues} primitive@>
+mp_primitive(mp, "truecorners",internal_quantity,mp_true_corners);
+@:mp_true_corners_}{\&{truecorners} primitive@>
+mp_primitive(mp, "mpprocset",internal_quantity,mp_procset);
+@:mp_procset_}{\&{mpprocset} primitive@>
+mp_primitive(mp, "troffmode",internal_quantity,mp_gtroffmode);
+@:troffmode_}{\&{troffmode} primitive@>
+mp_primitive(mp, "defaultcolormodel",internal_quantity,mp_default_color_model);
+@:mp_default_color_model_}{\&{defaultcolormodel} primitive@>
+mp_primitive(mp, "restoreclipcolor",internal_quantity,mp_restore_clip_color);
+@:mp_restore_clip_color_}{\&{restoreclipcolor} primitive@>
+
+@ Colors can be specified in four color models. In the special
+case of |no_model|, MetaPost does not output any color operator to
+the postscript output.
+
+Note: these values are passed directly on to |with_option|. This only
+works because the other possible values passed to |with_option| are
+8 and 10 respectively (from |with_pen| and |with_picture|).
+
+There is a first state, that is only used for |gs_colormodel|. It flags
+the fact that there has not been any kind of color specification by
+the user so far in the game.
+
+@<Types...@>=
+enum mp_color_model {
+ mp_no_model=1,
+ mp_grey_model=3,
+ mp_rgb_model=5,
+ mp_cmyk_model=7,
+ mp_uninitialized_model=9
+};
+
+
+@ @<Initialize table entries (done by \.{INIMP} only)@>=
+mp->internal[mp_default_color_model]=(mp_rgb_model*unity);
+mp->internal[mp_restore_clip_color]=unity;
+
+@ Well, we do have to list the names one more time, for use in symbolic
+printouts.
+
+@<Initialize table...@>=
+mp->int_name[mp_tracing_titles]=xstrdup("tracingtitles");
+mp->int_name[mp_tracing_equations]=xstrdup("tracingequations");
+mp->int_name[mp_tracing_capsules]=xstrdup("tracingcapsules");
+mp->int_name[mp_tracing_choices]=xstrdup("tracingchoices");
+mp->int_name[mp_tracing_specs]=xstrdup("tracingspecs");
+mp->int_name[mp_tracing_commands]=xstrdup("tracingcommands");
+mp->int_name[mp_tracing_restores]=xstrdup("tracingrestores");
+mp->int_name[mp_tracing_macros]=xstrdup("tracingmacros");
+mp->int_name[mp_tracing_output]=xstrdup("tracingoutput");
+mp->int_name[mp_tracing_stats]=xstrdup("tracingstats");
+mp->int_name[mp_tracing_lost_chars]=xstrdup("tracinglostchars");
+mp->int_name[mp_tracing_online]=xstrdup("tracingonline");
+mp->int_name[mp_year]=xstrdup("year");
+mp->int_name[mp_month]=xstrdup("month");
+mp->int_name[mp_day]=xstrdup("day");
+mp->int_name[mp_time]=xstrdup("time");
+mp->int_name[mp_char_code]=xstrdup("charcode");
+mp->int_name[mp_char_ext]=xstrdup("charext");
+mp->int_name[mp_char_wd]=xstrdup("charwd");
+mp->int_name[mp_char_ht]=xstrdup("charht");
+mp->int_name[mp_char_dp]=xstrdup("chardp");
+mp->int_name[mp_char_ic]=xstrdup("charic");
+mp->int_name[mp_design_size]=xstrdup("designsize");
+mp->int_name[mp_pausing]=xstrdup("pausing");
+mp->int_name[mp_showstopping]=xstrdup("showstopping");
+mp->int_name[mp_fontmaking]=xstrdup("fontmaking");
+mp->int_name[mp_linejoin]=xstrdup("linejoin");
+mp->int_name[mp_linecap]=xstrdup("linecap");
+mp->int_name[mp_miterlimit]=xstrdup("miterlimit");
+mp->int_name[mp_warning_check]=xstrdup("warningcheck");
+mp->int_name[mp_boundary_char]=xstrdup("boundarychar");
+mp->int_name[mp_prologues]=xstrdup("prologues");
+mp->int_name[mp_true_corners]=xstrdup("truecorners");
+mp->int_name[mp_default_color_model]=xstrdup("defaultcolormodel");
+mp->int_name[mp_procset]=xstrdup("mpprocset");
+mp->int_name[mp_gtroffmode]=xstrdup("troffmode");
+mp->int_name[mp_restore_clip_color]=xstrdup("restoreclipcolor");
+
+@ The following procedure, which is called just before \MP\ initializes its
+input and output, establishes the initial values of the date and time.
+@^system dependencies@>
+
+Note that the values are |scaled| integers. Hence \MP\ can no longer
+be used after the year 32767.
+
+@c
+void mp_fix_date_and_time (MP mp) {
+ time_t aclock = time ((time_t *) 0);
+ struct tm *tmptr = localtime (&aclock);
+ mp->internal[mp_time]=
+ (tmptr->tm_hour*60+tmptr->tm_min)*unity; /* minutes since midnight */
+ mp->internal[mp_day]=(tmptr->tm_mday)*unity; /* fourth day of the month */
+ mp->internal[mp_month]=(tmptr->tm_mon+1)*unity; /* seventh month of the year */
+ mp->internal[mp_year]=(tmptr->tm_year+1900)*unity; /* Anno Domini */
+}
+
+@ @<Declarations@>=
+void mp_fix_date_and_time (MP mp) ;
+
+@ \MP\ is occasionally supposed to print diagnostic information that
+goes only into the transcript file, unless |mp_tracing_online| is positive.
+Now that we have defined |mp_tracing_online| we can define
+two routines that adjust the destination of print commands:
+
+@<Declarations@>=
+void mp_begin_diagnostic (MP mp) ;
+void mp_end_diagnostic (MP mp,boolean blank_line);
+void mp_print_diagnostic (MP mp, const char *s, const char *t, boolean nuline) ;
+
+@ @<Basic printing...@>=
+@<Declare a function called |true_line|@>
+void mp_begin_diagnostic (MP mp) { /* prepare to do some tracing */
+ mp->old_setting=mp->selector;
+ if ((mp->internal[mp_tracing_online]<=0)&&(mp->selector==term_and_log)){
+ decr(mp->selector);
+ if ( mp->history==mp_spotless ) mp->history=mp_warning_issued;
+ }
+}
+@#
+void mp_end_diagnostic (MP mp,boolean blank_line) {
+ /* restore proper conditions after tracing */
+ mp_print_nl(mp, "");
+ if ( blank_line ) mp_print_ln(mp);
+ mp->selector=mp->old_setting;
+}
+
+@
+
+@<Glob...@>=
+unsigned int old_setting;
+
+@ We will occasionally use |begin_diagnostic| in connection with line-number
+printing, as follows. (The parameter |s| is typically |"Path"| or
+|"Cycle spec"|, etc.)
+
+@<Basic printing...@>=
+void mp_print_diagnostic (MP mp, const char *s, const char *t, boolean nuline) {
+ mp_begin_diagnostic(mp);
+ if ( nuline ) mp_print_nl(mp, s); else mp_print(mp, s);
+ mp_print(mp, " at line ");
+ mp_print_int(mp, mp_true_line(mp));
+ mp_print(mp, t); mp_print_char(mp, ':');
+}
+
+@ The 256 |ASCII_code| characters are grouped into classes by means of
+the |char_class| table. Individual class numbers have no semantic
+or syntactic significance, except in a few instances defined here.
+There's also |max_class|, which can be used as a basis for additional
+class numbers in nonstandard extensions of \MP.
+
+@d digit_class 0 /* the class number of \.{0123456789} */
+@d period_class 1 /* the class number of `\..' */
+@d space_class 2 /* the class number of spaces and nonstandard characters */
+@d percent_class 3 /* the class number of `\.\%' */
+@d string_class 4 /* the class number of `\."' */
+@d right_paren_class 8 /* the class number of `\.)' */
+@d isolated_classes 5: case 6: case 7: case 8 /* characters that make length-one tokens only */
+@d letter_class 9 /* letters and the underline character */
+@d left_bracket_class 17 /* `\.[' */
+@d right_bracket_class 18 /* `\.]' */
+@d invalid_class 20 /* bad character in the input */
+@d max_class 20 /* the largest class number */
+
+@<Glob...@>=
+int char_class[256]; /* the class numbers */
+
+@ If changes are made to accommodate non-ASCII character sets, they should
+follow the guidelines in Appendix~C of {\sl The {\logos METAFONT\/}book}.
+@:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
+@^system dependencies@>
+
+@<Set initial ...@>=
+for (k='0';k<='9';k++)
+ mp->char_class[k]=digit_class;
+mp->char_class['.']=period_class;
+mp->char_class[' ']=space_class;
+mp->char_class['%']=percent_class;
+mp->char_class['"']=string_class;
+mp->char_class[',']=5;
+mp->char_class[';']=6;
+mp->char_class['(']=7;
+mp->char_class[')']=right_paren_class;
+for (k='A';k<= 'Z';k++ )
+ mp->char_class[k]=letter_class;
+for (k='a';k<='z';k++)
+ mp->char_class[k]=letter_class;
+mp->char_class['_']=letter_class;
+mp->char_class['<']=10;
+mp->char_class['=']=10;
+mp->char_class['>']=10;
+mp->char_class[':']=10;
+mp->char_class['|']=10;
+mp->char_class['`']=11;
+mp->char_class['\'']=11;
+mp->char_class['+']=12;
+mp->char_class['-']=12;
+mp->char_class['/']=13;
+mp->char_class['*']=13;
+mp->char_class['\\']=13;
+mp->char_class['!']=14;
+mp->char_class['?']=14;
+mp->char_class['#']=15;
+mp->char_class['&']=15;
+mp->char_class['@@']=15;
+mp->char_class['$']=15;
+mp->char_class['^']=16;
+mp->char_class['~']=16;
+mp->char_class['[']=left_bracket_class;
+mp->char_class[']']=right_bracket_class;
+mp->char_class['{']=19;
+mp->char_class['}']=19;
+for (k=0;k<' ';k++)
+ mp->char_class[k]=invalid_class;
+mp->char_class['\t']=space_class;
+mp->char_class['\f']=space_class;
+for (k=127;k<=255;k++)
+ mp->char_class[k]=invalid_class;
+
+@* \[13] The hash table.
+Symbolic tokens are stored and retrieved by means of a fairly standard hash
+table algorithm called the method of ``coalescing lists'' (cf.\ Algorithm 6.4C
+in {\sl The Art of Computer Programming\/}). Once a symbolic token enters the
+table, it is never removed.
+
+The actual sequence of characters forming a symbolic token is
+stored in the |str_pool| array together with all the other strings. An
+auxiliary array |hash| consists of items with two halfword fields per
+word. The first of these, called |next(p)|, points to the next identifier
+belonging to the same coalesced list as the identifier corresponding to~|p|;
+and the other, called |text(p)|, points to the |str_start| entry for
+|p|'s identifier. If position~|p| of the hash table is empty, we have
+|text(p)=0|; if position |p| is either empty or the end of a coalesced
+hash list, we have |next(p)=0|.
+
+An auxiliary pointer variable called |hash_used| is maintained in such a
+way that all locations |p>=hash_used| are nonempty. The global variable
+|st_count| tells how many symbolic tokens have been defined, if statistics
+are being kept.
+
+The first 256 locations of |hash| are reserved for symbols of length one.
+
+There's a parallel array called |eqtb| that contains the current equivalent
+values of each symbolic token. The entries of this array consist of
+two halfwords called |eq_type| (a command code) and |equiv| (a secondary
+piece of information that qualifies the |eq_type|).
+
+@d next(A) mp->hash[(A)].lh /* link for coalesced lists */
+@d text(A) mp->hash[(A)].rh /* string number for symbolic token name */
+@d eq_type(A) mp->eqtb[(A)].lh /* the current ``meaning'' of a symbolic token */
+@d equiv(A) mp->eqtb[(A)].rh /* parametric part of a token's meaning */
+@d hash_base 257 /* hashing actually starts here */
+@d hash_is_full (mp->hash_used==hash_base) /* are all positions occupied? */
+
+@<Glob...@>=
+pointer hash_used; /* allocation pointer for |hash| */
+integer st_count; /* total number of known identifiers */
+
+@ Certain entries in the hash table are ``frozen'' and not redefinable,
+since they are used in error recovery.
+
+@d hash_top (hash_base+mp->hash_size) /* the first location of the frozen area */
+@d frozen_inaccessible hash_top /* |hash| location to protect the frozen area */
+@d frozen_repeat_loop (hash_top+1) /* |hash| location of a loop-repeat token */
+@d frozen_right_delimiter (hash_top+2) /* |hash| location of a permanent `\.)' */
+@d frozen_left_bracket (hash_top+3) /* |hash| location of a permanent `\.[' */
+@d frozen_slash (hash_top+4) /* |hash| location of a permanent `\./' */
+@d frozen_colon (hash_top+5) /* |hash| location of a permanent `\.:' */
+@d frozen_semicolon (hash_top+6) /* |hash| location of a permanent `\.;' */
+@d frozen_end_for (hash_top+7) /* |hash| location of a permanent \&{endfor} */
+@d frozen_end_def (hash_top+8) /* |hash| location of a permanent \&{enddef} */
+@d frozen_fi (hash_top+9) /* |hash| location of a permanent \&{fi} */
+@d frozen_end_group (hash_top+10) /* |hash| location of a permanent `\.{endgroup}' */
+@d frozen_etex (hash_top+11) /* |hash| location of a permanent \&{etex} */
+@d frozen_mpx_break (hash_top+12) /* |hash| location of a permanent \&{mpxbreak} */
+@d frozen_bad_vardef (hash_top+13) /* |hash| location of `\.{a bad variable}' */
+@d frozen_undefined (hash_top+14) /* |hash| location that never gets defined */
+@d hash_end (hash_top+14) /* the actual size of the |hash| and |eqtb| arrays */
+
+@<Glob...@>=
+two_halves *hash; /* the hash table */
+two_halves *eqtb; /* the equivalents */
+
+@ @<Allocate or initialize ...@>=
+mp->hash = xmalloc((hash_end+1),sizeof(two_halves));
+mp->eqtb = xmalloc((hash_end+1),sizeof(two_halves));
+
+@ @<Dealloc variables@>=
+xfree(mp->hash);
+xfree(mp->eqtb);
+
+@ @<Set init...@>=
+next(1)=0; text(1)=0; eq_type(1)=tag_token; equiv(1)=null;
+for (k=2;k<=hash_end;k++) {
+ mp->hash[k]=mp->hash[1]; mp->eqtb[k]=mp->eqtb[1];
+}
+
+@ @<Initialize table entries...@>=
+mp->hash_used=frozen_inaccessible; /* nothing is used */
+mp->st_count=0;
+text(frozen_bad_vardef)=intern("a bad variable");
+text(frozen_etex)=intern("etex");
+text(frozen_mpx_break)=intern("mpxbreak");
+text(frozen_fi)=intern("fi");
+text(frozen_end_group)=intern("endgroup");
+text(frozen_end_def)=intern("enddef");
+text(frozen_end_for)=intern("endfor");
+text(frozen_semicolon)=intern(";");
+text(frozen_colon)=intern(":");
+text(frozen_slash)=intern("/");
+text(frozen_left_bracket)=intern("[");
+text(frozen_right_delimiter)=intern(")");
+text(frozen_inaccessible)=intern(" INACCESSIBLE");
+eq_type(frozen_right_delimiter)=right_delimiter;
+
+@ @<Check the ``constant'' values...@>=
+if ( hash_end+mp->max_internal>max_halfword ) mp->bad=17;
+
+@ Here is the subroutine that searches the hash table for an identifier
+that matches a given string of length~|l| appearing in |buffer[j..
+(j+l-1)]|. If the identifier is not found, it is inserted; hence it
+will always be found, and the corresponding hash table address
+will be returned.
+
+@c
+pointer mp_id_lookup (MP mp,integer j, integer l) { /* search the hash table */
+ integer h; /* hash code */
+ pointer p; /* index in |hash| array */
+ pointer k; /* index in |buffer| array */
+ if (l==1) {
+ @<Treat special case of length 1 and |break|@>;
+ }
+ @<Compute the hash code |h|@>;
+ p=h+hash_base; /* we start searching here; note that |0<=h<hash_prime| */
+ while (true) {
+ if (text(p)>0 && length(text(p))==l && mp_str_eq_buf(mp, text(p),j))
+ break;
+ if ( next(p)==0 ) {
+ @<Insert a new symbolic token after |p|, then
+ make |p| point to it and |break|@>;
+ }
+ p=next(p);
+ }
+ return p;
+}
+
+@ @<Treat special case of length 1...@>=
+ p=mp->buffer[j]+1; text(p)=p-1; return p;
+
+
+@ @<Insert a new symbolic...@>=
+{
+if ( text(p)>0 ) {
+ do {
+ if ( hash_is_full )
+ mp_overflow(mp, "hash size",mp->hash_size);
+@:MetaPost capacity exceeded hash size}{\quad hash size@>
+ decr(mp->hash_used);
+ } while (text(mp->hash_used)!=0); /* search for an empty location in |hash| */
+ next(p)=mp->hash_used;
+ p=mp->hash_used;
+}
+str_room(l);
+for (k=j;k<=j+l-1;k++) {
+ append_char(mp->buffer[k]);
+}
+text(p)=mp_make_string(mp);
+mp->str_ref[text(p)]=max_str_ref;
+incr(mp->st_count);
+break;
+}
+
+
+@ The value of |hash_prime| should be roughly 85\pct! of |hash_size|, and it
+should be a prime number. The theory of hashing tells us to expect fewer
+than two table probes, on the average, when the search is successful.
+[See J.~S. Vitter, {\sl Journal of the ACM\/ \bf30} (1983), 231--258.]
+@^Vitter, Jeffrey Scott@>
+
+@<Compute the hash code |h|@>=
+h=mp->buffer[j];
+for (k=j+1;k<=j+l-1;k++){
+ h=h+h+mp->buffer[k];
+ while ( h>=mp->hash_prime ) h=h-mp->hash_prime;
+}
+
+@ @<Search |eqtb| for equivalents equal to |p|@>=
+for (q=1;q<=hash_end;q++) {
+ if ( equiv(q)==p ) {
+ mp_print_nl(mp, "EQUIV(");
+ mp_print_int(mp, q);
+ mp_print_char(mp, ')');
+ }
+}
+
+@ We need to put \MP's ``primitive'' symbolic tokens into the hash
+table, together with their command code (which will be the |eq_type|)
+and an operand (which will be the |equiv|). The |primitive| procedure
+does this, in a way that no \MP\ user can. The global value |cur_sym|
+contains the new |eqtb| pointer after |primitive| has acted.
+
+@c
+void mp_primitive (MP mp, const char *ss, halfword c, halfword o) {
+ pool_pointer k; /* index into |str_pool| */
+ small_number j; /* index into |buffer| */
+ small_number l; /* length of the string */
+ str_number s;
+ s = intern(ss);
+ k=mp->str_start[s]; l=str_stop(s)-k;
+ /* we will move |s| into the (empty) |buffer| */
+ for (j=0;j<=l-1;j++) {
+ mp->buffer[j]=mp->str_pool[k+j];
+ }
+ mp->cur_sym=mp_id_lookup(mp, 0,l);
+ if ( s>=256 ) { /* we don't want to have the string twice */
+ mp_flush_string(mp, text(mp->cur_sym)); text(mp->cur_sym)=s;
+ };
+ eq_type(mp->cur_sym)=c;
+ equiv(mp->cur_sym)=o;
+}
+
+
+@ Many of \MP's primitives need no |equiv|, since they are identifiable
+by their |eq_type| alone. These primitives are loaded into the hash table
+as follows:
+
+@<Put each of \MP's primitives into the hash table@>=
+mp_primitive(mp, "..",path_join,0);
+@:.._}{\.{..} primitive@>
+mp_primitive(mp, "[",left_bracket,0); mp->eqtb[frozen_left_bracket]=mp->eqtb[mp->cur_sym];
+@:[ }{\.{[} primitive@>
+mp_primitive(mp, "]",right_bracket,0);
+@:] }{\.{]} primitive@>
+mp_primitive(mp, "}",right_brace,0);
+@:]]}{\.{\char`\}} primitive@>
+mp_primitive(mp, "{",left_brace,0);
+@:][}{\.{\char`\{} primitive@>
+mp_primitive(mp, ":",colon,0); mp->eqtb[frozen_colon]=mp->eqtb[mp->cur_sym];
+@:: }{\.{:} primitive@>
+mp_primitive(mp, "::",double_colon,0);
+@::: }{\.{::} primitive@>
+mp_primitive(mp, "||:",bchar_label,0);
+@:::: }{\.{\char'174\char'174:} primitive@>
+mp_primitive(mp, ":=",assignment,0);
+@::=_}{\.{:=} primitive@>
+mp_primitive(mp, ",",comma,0);
+@:, }{\., primitive@>
+mp_primitive(mp, ";",semicolon,0); mp->eqtb[frozen_semicolon]=mp->eqtb[mp->cur_sym];
+@:; }{\.; primitive@>
+mp_primitive(mp, "\\",relax,0);
+@:]]\\}{\.{\char`\\} primitive@>
+@#
+mp_primitive(mp, "addto",add_to_command,0);
+@:add_to_}{\&{addto} primitive@>
+mp_primitive(mp, "atleast",at_least,0);
+@:at_least_}{\&{atleast} primitive@>
+mp_primitive(mp, "begingroup",begin_group,0); mp->bg_loc=mp->cur_sym;
+@:begin_group_}{\&{begingroup} primitive@>
+mp_primitive(mp, "controls",controls,0);
+@:controls_}{\&{controls} primitive@>
+mp_primitive(mp, "curl",curl_command,0);
+@:curl_}{\&{curl} primitive@>
+mp_primitive(mp, "delimiters",delimiters,0);
+@:delimiters_}{\&{delimiters} primitive@>
+mp_primitive(mp, "endgroup",end_group,0);
+ mp->eqtb[frozen_end_group]=mp->eqtb[mp->cur_sym]; mp->eg_loc=mp->cur_sym;
+@:endgroup_}{\&{endgroup} primitive@>
+mp_primitive(mp, "everyjob",every_job_command,0);
+@:every_job_}{\&{everyjob} primitive@>
+mp_primitive(mp, "exitif",exit_test,0);
+@:exit_if_}{\&{exitif} primitive@>
+mp_primitive(mp, "expandafter",expand_after,0);
+@:expand_after_}{\&{expandafter} primitive@>
+mp_primitive(mp, "interim",interim_command,0);
+@:interim_}{\&{interim} primitive@>
+mp_primitive(mp, "let",let_command,0);
+@:let_}{\&{let} primitive@>
+mp_primitive(mp, "newinternal",new_internal,0);
+@:new_internal_}{\&{newinternal} primitive@>
+mp_primitive(mp, "of",of_token,0);
+@:of_}{\&{of} primitive@>
+mp_primitive(mp, "randomseed",mp_random_seed,0);
+@:mp_random_seed_}{\&{randomseed} primitive@>
+mp_primitive(mp, "save",save_command,0);
+@:save_}{\&{save} primitive@>
+mp_primitive(mp, "scantokens",scan_tokens,0);
+@:scan_tokens_}{\&{scantokens} primitive@>
+mp_primitive(mp, "shipout",ship_out_command,0);
+@:ship_out_}{\&{shipout} primitive@>
+mp_primitive(mp, "skipto",skip_to,0);
+@:skip_to_}{\&{skipto} primitive@>
+mp_primitive(mp, "special",special_command,0);
+@:special}{\&{special} primitive@>
+mp_primitive(mp, "fontmapfile",special_command,1);
+@:fontmapfile}{\&{fontmapfile} primitive@>
+mp_primitive(mp, "fontmapline",special_command,2);
+@:fontmapline}{\&{fontmapline} primitive@>
+mp_primitive(mp, "step",step_token,0);
+@:step_}{\&{step} primitive@>
+mp_primitive(mp, "str",str_op,0);
+@:str_}{\&{str} primitive@>
+mp_primitive(mp, "tension",tension,0);
+@:tension_}{\&{tension} primitive@>
+mp_primitive(mp, "to",to_token,0);
+@:to_}{\&{to} primitive@>
+mp_primitive(mp, "until",until_token,0);
+@:until_}{\&{until} primitive@>
+mp_primitive(mp, "within",within_token,0);
+@:within_}{\&{within} primitive@>
+mp_primitive(mp, "write",write_command,0);
+@:write_}{\&{write} primitive@>
+
+@ Each primitive has a corresponding inverse, so that it is possible to
+display the cryptic numeric contents of |eqtb| in symbolic form.
+Every call of |primitive| in this program is therefore accompanied by some
+straightforward code that forms part of the |print_cmd_mod| routine
+explained below.
+
+@<Cases of |print_cmd_mod| for symbolic printing of primitives@>=
+case add_to_command:mp_print(mp, "addto"); break;
+case assignment:mp_print(mp, ":="); break;
+case at_least:mp_print(mp, "atleast"); break;
+case bchar_label:mp_print(mp, "||:"); break;
+case begin_group:mp_print(mp, "begingroup"); break;
+case colon:mp_print(mp, ":"); break;
+case comma:mp_print(mp, ","); break;
+case controls:mp_print(mp, "controls"); break;
+case curl_command:mp_print(mp, "curl"); break;
+case delimiters:mp_print(mp, "delimiters"); break;
+case double_colon:mp_print(mp, "::"); break;
+case end_group:mp_print(mp, "endgroup"); break;
+case every_job_command:mp_print(mp, "everyjob"); break;
+case exit_test:mp_print(mp, "exitif"); break;
+case expand_after:mp_print(mp, "expandafter"); break;
+case interim_command:mp_print(mp, "interim"); break;
+case left_brace:mp_print(mp, "{"); break;
+case left_bracket:mp_print(mp, "["); break;
+case let_command:mp_print(mp, "let"); break;
+case new_internal:mp_print(mp, "newinternal"); break;
+case of_token:mp_print(mp, "of"); break;
+case path_join:mp_print(mp, ".."); break;
+case mp_random_seed:mp_print(mp, "randomseed"); break;
+case relax:mp_print_char(mp, '\\'); break;
+case right_brace:mp_print(mp, "}"); break;
+case right_bracket:mp_print(mp, "]"); break;
+case save_command:mp_print(mp, "save"); break;
+case scan_tokens:mp_print(mp, "scantokens"); break;
+case semicolon:mp_print(mp, ";"); break;
+case ship_out_command:mp_print(mp, "shipout"); break;
+case skip_to:mp_print(mp, "skipto"); break;
+case special_command: if ( m==2 ) mp_print(mp, "fontmapline"); else
+ if ( m==1 ) mp_print(mp, "fontmapfile"); else
+ mp_print(mp, "special"); break;
+case step_token:mp_print(mp, "step"); break;
+case str_op:mp_print(mp, "str"); break;
+case tension:mp_print(mp, "tension"); break;
+case to_token:mp_print(mp, "to"); break;
+case until_token:mp_print(mp, "until"); break;
+case within_token:mp_print(mp, "within"); break;
+case write_command:mp_print(mp, "write"); break;
+
+@ We will deal with the other primitives later, at some point in the program
+where their |eq_type| and |equiv| values are more meaningful. For example,
+the primitives for macro definitions will be loaded when we consider the
+routines that define macros.
+It is easy to find where each particular
+primitive was treated by looking in the index at the end; for example, the
+section where |"def"| entered |eqtb| is listed under `\&{def} primitive'.
+
+@* \[14] Token lists.
+A \MP\ token is either symbolic or numeric or a string, or it denotes
+a macro parameter or capsule; so there are five corresponding ways to encode it
+@^token@>
+internally: (1)~A symbolic token whose hash code is~|p|
+is represented by the number |p|, in the |info| field of a single-word
+node in~|mem|. (2)~A numeric token whose |scaled| value is~|v| is
+represented in a two-word node of~|mem|; the |type| field is |known|,
+the |name_type| field is |token|, and the |value| field holds~|v|.
+The fact that this token appears in a two-word node rather than a
+one-word node is, of course, clear from the node address.
+(3)~A string token is also represented in a two-word node; the |type|
+field is |mp_string_type|, the |name_type| field is |token|, and the
+|value| field holds the corresponding |str_number|. (4)~Capsules have
+|name_type=capsule|, and their |type| and |value| fields represent
+arbitrary values (in ways to be explained later). (5)~Macro parameters
+are like symbolic tokens in that they appear in |info| fields of
+one-word nodes. The $k$th parameter is represented by |expr_base+k| if it
+is of type \&{expr}, or by |suffix_base+k| if it is of type \&{suffix}, or
+by |text_base+k| if it is of type \&{text}. (Here |0<=k<param_size|.)
+Actual values of these parameters are kept in a separate stack, as we will
+see later. The constants |expr_base|, |suffix_base|, and |text_base| are,
+of course, chosen so that there will be no confusion between symbolic
+tokens and parameters of various types.
+
+Note that
+the `\\{type}' field of a node has nothing to do with ``type'' in a
+printer's sense. It's curious that the same word is used in such different ways.
+
+@d type(A) mp->mem[(A)].hh.b0 /* identifies what kind of value this is */
+@d name_type(A) mp->mem[(A)].hh.b1 /* a clue to the name of this value */
+@d token_node_size 2 /* the number of words in a large token node */
+@d value_loc(A) ((A)+1) /* the word that contains the |value| field */
+@d value(A) mp->mem[value_loc((A))].cint /* the value stored in a large token node */
+@d expr_base (hash_end+1) /* code for the zeroth \&{expr} parameter */
+@d suffix_base (expr_base+mp->param_size) /* code for the zeroth \&{suffix} parameter */
+@d text_base (suffix_base+mp->param_size) /* code for the zeroth \&{text} parameter */
+
+@<Check the ``constant''...@>=
+if ( text_base+mp->param_size>max_halfword ) mp->bad=18;
+
+@ We have set aside a two word node beginning at |null| so that we can have
+|value(null)=0|. We will make use of this coincidence later.
+
+@<Initialize table entries...@>=
+link(null)=null; value(null)=0;
+
+@ A numeric token is created by the following trivial routine.
+
+@c
+pointer mp_new_num_tok (MP mp,scaled v) {
+ pointer p; /* the new node */
+ p=mp_get_node(mp, token_node_size); value(p)=v;
+ type(p)=mp_known; name_type(p)=mp_token;
+ return p;
+}
+
+@ A token list is a singly linked list of nodes in |mem|, where
+each node contains a token and a link. Here's a subroutine that gets rid
+of a token list when it is no longer needed.
+
+@c void mp_flush_token_list (MP mp,pointer p) {
+ pointer q; /* the node being recycled */
+ while ( p!=null ) {
+ q=p; p=link(p);
+ if ( q>=mp->hi_mem_min ) {
+ free_avail(q);
+ } else {
+ switch (type(q)) {
+ case mp_vacuous: case mp_boolean_type: case mp_known:
+ break;
+ case mp_string_type:
+ delete_str_ref(value(q));
+ break;
+ case unknown_types: case mp_pen_type: case mp_path_type:
+ case mp_picture_type: case mp_pair_type: case mp_color_type:
+ case mp_cmykcolor_type: case mp_transform_type: case mp_dependent:
+ case mp_proto_dependent: case mp_independent:
+ mp_recycle_value(mp,q);
+ break;
+ default: mp_confusion(mp, "token");
+@:this can't happen token}{\quad token@>
+ }
+ mp_free_node(mp, q,token_node_size);
+ }
+ }
+}
+
+@ The procedure |show_token_list|, which prints a symbolic form of
+the token list that starts at a given node |p|, illustrates these
+conventions. The token list being displayed should not begin with a reference
+count. However, the procedure is intended to be fairly robust, so that if the
+memory links are awry or if |p| is not really a pointer to a token list,
+almost nothing catastrophic can happen.
+
+An additional parameter |q| is also given; this parameter is either null
+or it points to a node in the token list where a certain magic computation
+takes place that will be explained later. (Basically, |q| is non-null when
+we are printing the two-line context information at the time of an error
+message; |q| marks the place corresponding to where the second line
+should begin.)
+
+The generation will stop, and `\.{\char`\ ETC.}' will be printed, if the length
+of printing exceeds a given limit~|l|; the length of printing upon entry is
+assumed to be a given amount called |null_tally|. (Note that
+|show_token_list| sometimes uses itself recursively to print
+variable names within a capsule.)
+@^recursion@>
+
+Unusual entries are printed in the form of all-caps tokens
+preceded by a space, e.g., `\.{\char`\ BAD}'.
+
+@<Declare the procedure called |show_token_list|@>=
+void mp_show_token_list (MP mp, integer p, integer q, integer l,
+ integer null_tally) ;
+
+@ @c
+void mp_show_token_list (MP mp, integer p, integer q, integer l,
+ integer null_tally) {
+ small_number class,c; /* the |char_class| of previous and new tokens */
+ integer r,v; /* temporary registers */
+ class=percent_class;
+ mp->tally=null_tally;
+ while ( (p!=null) && (mp->tally<l) ) {
+ if ( p==q )
+ @<Do magic computation@>;
+ @<Display token |p| and set |c| to its class;
+ but |return| if there are problems@>;
+ class=c; p=link(p);
+ }
+ if ( p!=null )
+ mp_print(mp, " ETC.");
+@.ETC@>
+ return;
+}
+
+@ @<Display token |p| and set |c| to its class...@>=
+c=letter_class; /* the default */
+if ( (p<0)||(p>mp->mem_end) ) {
+ mp_print(mp, " CLOBBERED"); return;
+@.CLOBBERED@>
+}
+if ( p<mp->hi_mem_min ) {
+ @<Display two-word token@>;
+} else {
+ r=info(p);
+ if ( r>=expr_base ) {
+ @<Display a parameter token@>;
+ } else {
+ if ( r<1 ) {
+ if ( r==0 ) {
+ @<Display a collective subscript@>
+ } else {
+ mp_print(mp, " IMPOSSIBLE");
+@.IMPOSSIBLE@>
+ }
+ } else {
+ r=text(r);
+ if ( (r<0)||(r>mp->max_str_ptr) ) {
+ mp_print(mp, " NONEXISTENT");
+@.NONEXISTENT@>
+ } else {
+ @<Print string |r| as a symbolic token
+ and set |c| to its class@>;
+ }
+ }
+ }
+}
+
+@ @<Display two-word token@>=
+if ( name_type(p)==mp_token ) {
+ if ( type(p)==mp_known ) {
+ @<Display a numeric token@>;
+ } else if ( type(p)!=mp_string_type ) {
+ mp_print(mp, " BAD");
+@.BAD@>
+ } else {
+ mp_print_char(mp, '"'); mp_print_str(mp, value(p)); mp_print_char(mp, '"');
+ c=string_class;
+ }
+} else if ((name_type(p)!=mp_capsule)||(type(p)<mp_vacuous)||(type(p)>mp_independent) ) {
+ mp_print(mp, " BAD");
+} else {
+ mp_print_capsule(mp,p); c=right_paren_class;
+}
+
+@ @<Display a numeric token@>=
+if ( class==digit_class )
+ mp_print_char(mp, ' ');
+v=value(p);
+if ( v<0 ){
+ if ( class==left_bracket_class )
+ mp_print_char(mp, ' ');
+ mp_print_char(mp, '['); mp_print_scaled(mp, v); mp_print_char(mp, ']');
+ c=right_bracket_class;
+} else {
+ mp_print_scaled(mp, v); c=digit_class;
+}
+
+
+@ Strictly speaking, a genuine token will never have |info(p)=0|.
+But we will see later (in the |print_variable_name| routine) that
+it is convenient to let |info(p)=0| stand for `\.{[]}'.
+
+@<Display a collective subscript@>=
+{
+if ( class==left_bracket_class )
+ mp_print_char(mp, ' ');
+mp_print(mp, "[]"); c=right_bracket_class;
+}
+
+@ @<Display a parameter token@>=
+{
+if ( r<suffix_base ) {
+ mp_print(mp, "(EXPR"); r=r-(expr_base);
+@.EXPR@>
+} else if ( r<text_base ) {
+ mp_print(mp, "(SUFFIX"); r=r-(suffix_base);
+@.SUFFIX@>
+} else {
+ mp_print(mp, "(TEXT"); r=r-(text_base);
+@.TEXT@>
+}
+mp_print_int(mp, r); mp_print_char(mp, ')'); c=right_paren_class;
+}
+
+
+@ @<Print string |r| as a symbolic token...@>=
+{
+c=mp->char_class[mp->str_pool[mp->str_start[r]]];
+if ( c==class ) {
+ switch (c) {
+ case letter_class:mp_print_char(mp, '.'); break;
+ case isolated_classes: break;
+ default: mp_print_char(mp, ' '); break;
+ }
+}
+mp_print_str(mp, r);
+}
+
+@ @<Declarations@>=
+void mp_print_capsule (MP mp, pointer p);
+
+@ @<Declare miscellaneous procedures that were declared |forward|@>=
+void mp_print_capsule (MP mp, pointer p) {
+ mp_print_char(mp, '('); mp_print_exp(mp,p,0); mp_print_char(mp, ')');
+}
+
+@ Macro definitions are kept in \MP's memory in the form of token lists
+that have a few extra one-word nodes at the beginning.
+
+The first node contains a reference count that is used to tell when the
+list is no longer needed. To emphasize the fact that a reference count is
+present, we shall refer to the |info| field of this special node as the
+|ref_count| field.
+@^reference counts@>
+
+The next node or nodes after the reference count serve to describe the
+formal parameters. They consist of zero or more parameter tokens followed
+by a code for the type of macro.
+
+@d ref_count info
+ /* reference count preceding a macro definition or picture header */
+@d add_mac_ref(A) incr(ref_count((A))) /* make a new reference to a macro list */
+@d general_macro 0 /* preface to a macro defined with a parameter list */
+@d primary_macro 1 /* preface to a macro with a \&{primary} parameter */
+@d secondary_macro 2 /* preface to a macro with a \&{secondary} parameter */
+@d tertiary_macro 3 /* preface to a macro with a \&{tertiary} parameter */
+@d expr_macro 4 /* preface to a macro with an undelimited \&{expr} parameter */
+@d of_macro 5 /* preface to a macro with
+ undelimited `\&{expr} |x| \&{of}~|y|' parameters */
+@d suffix_macro 6 /* preface to a macro with an undelimited \&{suffix} parameter */
+@d text_macro 7 /* preface to a macro with an undelimited \&{text} parameter */
+
+@c
+void mp_delete_mac_ref (MP mp,pointer p) {
+ /* |p| points to the reference count of a macro list that is
+ losing one reference */
+ if ( ref_count(p)==null ) mp_flush_token_list(mp, p);
+ else decr(ref_count(p));
+}
+
+@ The following subroutine displays a macro, given a pointer to its
+reference count.
+
+@c
+@<Declare the procedure called |print_cmd_mod|@>
+void mp_show_macro (MP mp, pointer p, integer q, integer l) {
+ pointer r; /* temporary storage */
+ p=link(p); /* bypass the reference count */
+ while ( info(p)>text_macro ){
+ r=link(p); link(p)=null;
+ mp_show_token_list(mp, p,null,l,0); link(p)=r; p=r;
+ if ( l>0 ) l=l-mp->tally; else return;
+ } /* control printing of `\.{ETC.}' */
+@.ETC@>
+ mp->tally=0;
+ switch(info(p)) {
+ case general_macro:mp_print(mp, "->"); break;
+@.->@>
+ case primary_macro: case secondary_macro: case tertiary_macro:
+ mp_print_char(mp, '<');
+ mp_print_cmd_mod(mp, param_type,info(p));
+ mp_print(mp, ">->");
+ break;
+ case expr_macro:mp_print(mp, "<expr>->"); break;
+ case of_macro:mp_print(mp, "<expr>of<primary>->"); break;
+ case suffix_macro:mp_print(mp, "<suffix>->"); break;
+ case text_macro:mp_print(mp, "<text>->"); break;
+ } /* there are no other cases */
+ mp_show_token_list(mp, link(p),q,l-mp->tally,0);
+}
+
+@* \[15] Data structures for variables.
+The variables of \MP\ programs can be simple, like `\.x', or they can
+combine the structural properties of arrays and records, like `\.{x20a.b}'.
+A \MP\ user assigns a type to a variable like \.{x20a.b} by saying, for
+example, `\.{boolean} \.{x[]a.b}'. It's time for us to study how such
+things are represented inside of the computer.
+
+Each variable value occupies two consecutive words, either in a two-word
+node called a value node, or as a two-word subfield of a larger node. One
+of those two words is called the |value| field; it is an integer,
+containing either a |scaled| numeric value or the representation of some
+other type of quantity. (It might also be subdivided into halfwords, in
+which case it is referred to by other names instead of |value|.) The other
+word is broken into subfields called |type|, |name_type|, and |link|. The
+|type| field is a quarterword that specifies the variable's type, and
+|name_type| is a quarterword from which \MP\ can reconstruct the
+variable's name (sometimes by using the |link| field as well). Thus, only
+1.25 words are actually devoted to the value itself; the other
+three-quarters of a word are overhead, but they aren't wasted because they
+allow \MP\ to deal with sparse arrays and to provide meaningful diagnostics.
+
+In this section we shall be concerned only with the structural aspects of
+variables, not their values. Later parts of the program will change the
+|type| and |value| fields, but we shall treat those fields as black boxes
+whose contents should not be touched.
+
+However, if the |type| field is |mp_structured|, there is no |value| field,
+and the second word is broken into two pointer fields called |attr_head|
+and |subscr_head|. Those fields point to additional nodes that
+contain structural information, as we shall see.
+
+@d subscr_head_loc(A) (A)+1 /* where |value|, |subscr_head| and |attr_head| are */
+@d attr_head(A) info(subscr_head_loc((A))) /* pointer to attribute info */
+@d subscr_head(A) link(subscr_head_loc((A))) /* pointer to subscript info */
+@d value_node_size 2 /* the number of words in a value node */
+
+@ An attribute node is three words long. Two of these words contain |type|
+and |value| fields as described above, and the third word contains
+additional information: There is an |attr_loc| field, which contains the
+hash address of the token that names this attribute; and there's also a
+|parent| field, which points to the value node of |mp_structured| type at the
+next higher level (i.e., at the level to which this attribute is
+subsidiary). The |name_type| in an attribute node is `|attr|'. The
+|link| field points to the next attribute with the same parent; these are
+arranged in increasing order, so that |attr_loc(link(p))>attr_loc(p)|. The
+final attribute node links to the constant |end_attr|, whose |attr_loc|
+field is greater than any legal hash address. The |attr_head| in the
+parent points to a node whose |name_type| is |mp_structured_root|; this
+node represents the null attribute, i.e., the variable that is relevant
+when no attributes are attached to the parent. The |attr_head| node
+has the fields of either
+a value node, a subscript node, or an attribute node, depending on what
+the parent would be if it were not structured; but the subscript and
+attribute fields are ignored, so it effectively contains only the data of
+a value node. The |link| field in this special node points to an attribute
+node whose |attr_loc| field is zero; the latter node represents a collective
+subscript `\.{[]}' attached to the parent, and its |link| field points to
+the first non-special attribute node (or to |end_attr| if there are none).
+
+A subscript node likewise occupies three words, with |type| and |value| fields
+plus extra information; its |name_type| is |subscr|. In this case the
+third word is called the |subscript| field, which is a |scaled| integer.
+The |link| field points to the subscript node with the next larger
+subscript, if any; otherwise the |link| points to the attribute node
+for collective subscripts at this level. We have seen that the latter node
+contains an upward pointer, so that the parent can be deduced.
+
+The |name_type| in a parent-less value node is |root|, and the |link|
+is the hash address of the token that names this value.
+
+In other words, variables have a hierarchical structure that includes
+enough threads running around so that the program is able to move easily
+between siblings, parents, and children. An example should be helpful:
+(The reader is advised to draw a picture while reading the following
+description, since that will help to firm up the ideas.)
+Suppose that `\.x' and `\.{x.a}' and `\.{x[]b}' and `\.{x5}'
+and `\.{x20b}' have been mentioned in a user's program, where
+\.{x[]b} has been declared to be of \&{boolean} type. Let |h(x)|, |h(a)|,
+and |h(b)| be the hash addresses of \.x, \.a, and~\.b. Then
+|eq_type(h(x))=name| and |equiv(h(x))=p|, where |p|~is a two-word value
+node with |name_type(p)=root| and |link(p)=h(x)|. We have |type(p)=mp_structured|,
+|attr_head(p)=q|, and |subscr_head(p)=r|, where |q| points to a value
+node and |r| to a subscript node. (Are you still following this? Use
+a pencil to draw a diagram.) The lone variable `\.x' is represented by
+|type(q)| and |value(q)|; furthermore
+|name_type(q)=mp_structured_root| and |link(q)=q1|, where |q1| points
+to an attribute node representing `\.{x[]}'. Thus |name_type(q1)=attr|,
+|attr_loc(q1)=collective_subscript=0|, |parent(q1)=p|,
+|type(q1)=mp_structured|, |attr_head(q1)=qq|, and |subscr_head(q1)=qq1|;
+|qq| is a three-word ``attribute-as-value'' node with |type(qq)=numeric_type|
+(assuming that \.{x5} is numeric, because |qq| represents `\.{x[]}'
+with no further attributes), |name_type(qq)=structured_root|,
+|attr_loc(qq)=0|, |parent(qq)=p|, and
+|link(qq)=qq1|. (Now pay attention to the next part.) Node |qq1| is
+an attribute node representing `\.{x[][]}', which has never yet
+occurred; its |type| field is |undefined|, and its |value| field is
+undefined. We have |name_type(qq1)=attr|, |attr_loc(qq1)=collective_subscript|,
+|parent(qq1)=q1|, and |link(qq1)=qq2|. Since |qq2| represents
+`\.{x[]b}', |type(qq2)=mp_unknown_boolean|; also |attr_loc(qq2)=h(b)|,
+|parent(qq2)=q1|, |name_type(qq2)=attr|, |link(qq2)=end_attr|.
+(Maybe colored lines will help untangle your picture.)
+ Node |r| is a subscript node with |type| and |value|
+representing `\.{x5}'; |name_type(r)=subscr|, |subscript(r)=5.0|,
+and |link(r)=r1| is another subscript node. To complete the picture,
+see if you can guess what |link(r1)| is; give up? It's~|q1|.
+Furthermore |subscript(r1)=20.0|, |name_type(r1)=subscr|,
+|type(r1)=mp_structured|, |attr_head(r1)=qqq|, |subscr_head(r1)=qqq1|,
+and we finish things off with three more nodes
+|qqq|, |qqq1|, and |qqq2| hung onto~|r1|. (Perhaps you should start again
+with a larger sheet of paper.) The value of variable \.{x20b}
+appears in node~|qqq2|, as you can well imagine.
+
+If the example in the previous paragraph doesn't make things crystal
+clear, a glance at some of the simpler subroutines below will reveal how
+things work out in practice.
+
+The only really unusual thing about these conventions is the use of
+collective subscript attributes. The idea is to avoid repeating a lot of
+type information when many elements of an array are identical macros
+(for which distinct values need not be stored) or when they don't have
+all of the possible attributes. Branches of the structure below collective
+subscript attributes do not carry actual values except for macro identifiers;
+branches of the structure below subscript nodes do not carry significant
+information in their collective subscript attributes.
+
+@d attr_loc_loc(A) ((A)+2) /* where the |attr_loc| and |parent| fields are */
+@d attr_loc(A) info(attr_loc_loc((A))) /* hash address of this attribute */
+@d parent(A) link(attr_loc_loc((A))) /* pointer to |mp_structured| variable */
+@d subscript_loc(A) ((A)+2) /* where the |subscript| field lives */
+@d subscript(A) mp->mem[subscript_loc((A))].sc /* subscript of this variable */
+@d attr_node_size 3 /* the number of words in an attribute node */
+@d subscr_node_size 3 /* the number of words in a subscript node */
+@d collective_subscript 0 /* code for the attribute `\.{[]}' */
+
+@<Initialize table...@>=
+attr_loc(end_attr)=hash_end+1; parent(end_attr)=null;
+
+@ Variables of type \&{pair} will have values that point to four-word
+nodes containing two numeric values. The first of these values has
+|name_type=mp_x_part_sector| and the second has |name_type=mp_y_part_sector|;
+the |link| in the first points back to the node whose |value| points
+to this four-word node.
+
+Variables of type \&{transform} are similar, but in this case their
+|value| points to a 12-word node containing six values, identified by
+|x_part_sector|, |y_part_sector|, |mp_xx_part_sector|, |mp_xy_part_sector|,
+|mp_yx_part_sector|, and |mp_yy_part_sector|.
+Finally, variables of type \&{color} have 3~values in 6~words
+identified by |mp_red_part_sector|, |mp_green_part_sector|, and |mp_blue_part_sector|.
+
+When an entire structured variable is saved, the |root| indication
+is temporarily replaced by |saved_root|.
+
+Some variables have no name; they just are used for temporary storage
+while expressions are being evaluated. We call them {\sl capsules}.
+
+@d x_part_loc(A) (A) /* where the \&{xpart} is found in a pair or transform node */
+@d y_part_loc(A) ((A)+2) /* where the \&{ypart} is found in a pair or transform node */
+@d xx_part_loc(A) ((A)+4) /* where the \&{xxpart} is found in a transform node */
+@d xy_part_loc(A) ((A)+6) /* where the \&{xypart} is found in a transform node */
+@d yx_part_loc(A) ((A)+8) /* where the \&{yxpart} is found in a transform node */
+@d yy_part_loc(A) ((A)+10) /* where the \&{yypart} is found in a transform node */
+@d red_part_loc(A) (A) /* where the \&{redpart} is found in a color node */
+@d green_part_loc(A) ((A)+2) /* where the \&{greenpart} is found in a color node */
+@d blue_part_loc(A) ((A)+4) /* where the \&{bluepart} is found in a color node */
+@d cyan_part_loc(A) (A) /* where the \&{cyanpart} is found in a color node */
+@d magenta_part_loc(A) ((A)+2) /* where the \&{magentapart} is found in a color node */
+@d yellow_part_loc(A) ((A)+4) /* where the \&{yellowpart} is found in a color node */
+@d black_part_loc(A) ((A)+6) /* where the \&{blackpart} is found in a color node */
+@d grey_part_loc(A) (A) /* where the \&{greypart} is found in a color node */
+@#
+@d pair_node_size 4 /* the number of words in a pair node */
+@d transform_node_size 12 /* the number of words in a transform node */
+@d color_node_size 6 /* the number of words in a color node */
+@d cmykcolor_node_size 8 /* the number of words in a color node */
+
+@<Glob...@>=
+small_number big_node_size[mp_pair_type+1];
+small_number sector0[mp_pair_type+1];
+small_number sector_offset[mp_black_part_sector+1];
+
+@ The |sector0| array gives for each big node type, |name_type| values
+for its first subfield; the |sector_offset| array gives for each
+|name_type| value, the offset from the first subfield in words;
+and the |big_node_size| array gives the size in words for each type of
+big node.
+
+@<Set init...@>=
+mp->big_node_size[mp_transform_type]=transform_node_size;
+mp->big_node_size[mp_pair_type]=pair_node_size;
+mp->big_node_size[mp_color_type]=color_node_size;
+mp->big_node_size[mp_cmykcolor_type]=cmykcolor_node_size;
+mp->sector0[mp_transform_type]=mp_x_part_sector;
+mp->sector0[mp_pair_type]=mp_x_part_sector;
+mp->sector0[mp_color_type]=mp_red_part_sector;
+mp->sector0[mp_cmykcolor_type]=mp_cyan_part_sector;
+for (k=mp_x_part_sector;k<= mp_yy_part_sector;k++ ) {
+ mp->sector_offset[k]=2*(k-mp_x_part_sector);
+}
+for (k=mp_red_part_sector;k<= mp_blue_part_sector ; k++) {
+ mp->sector_offset[k]=2*(k-mp_red_part_sector);
+}
+for (k=mp_cyan_part_sector;k<= mp_black_part_sector;k++ ) {
+ mp->sector_offset[k]=2*(k-mp_cyan_part_sector);
+}
+
+@ If |type(p)=mp_pair_type| or |mp_transform_type| and if |value(p)=null|, the
+procedure call |init_big_node(p)| will allocate a pair or transform node
+for~|p|. The individual parts of such nodes are initially of type
+|mp_independent|.
+
+@c
+void mp_init_big_node (MP mp,pointer p) {
+ pointer q; /* the new node */
+ small_number s; /* its size */
+ s=mp->big_node_size[type(p)]; q=mp_get_node(mp, s);
+ do {
+ s=s-2;
+ @<Make variable |q+s| newly independent@>;
+ name_type(q+s)=halfp(s)+mp->sector0[type(p)];
+ link(q+s)=null;
+ } while (s!=0);
+ link(q)=p; value(p)=q;
+}
+
+@ The |id_transform| function creates a capsule for the
+identity transformation.
+
+@c
+pointer mp_id_transform (MP mp) {
+ pointer p,q,r; /* list manipulation registers */
+ p=mp_get_node(mp, value_node_size); type(p)=mp_transform_type;
+ name_type(p)=mp_capsule; value(p)=null; mp_init_big_node(mp, p); q=value(p);
+ r=q+transform_node_size;
+ do {
+ r=r-2;
+ type(r)=mp_known; value(r)=0;
+ } while (r!=q);
+ value(xx_part_loc(q))=unity;
+ value(yy_part_loc(q))=unity;
+ return p;
+}
+
+@ Tokens are of type |tag_token| when they first appear, but they point
+to |null| until they are first used as the root of a variable.
+The following subroutine establishes the root node on such grand occasions.
+
+@c
+void mp_new_root (MP mp,pointer x) {
+ pointer p; /* the new node */
+ p=mp_get_node(mp, value_node_size); type(p)=undefined; name_type(p)=mp_root;
+ link(p)=x; equiv(x)=p;
+}
+
+@ These conventions for variable representation are illustrated by the
+|print_variable_name| routine, which displays the full name of a
+variable given only a pointer to its two-word value packet.
+
+@<Declarations@>=
+void mp_print_variable_name (MP mp, pointer p);
+
+@ @c
+void mp_print_variable_name (MP mp, pointer p) {
+ pointer q; /* a token list that will name the variable's suffix */
+ pointer r; /* temporary for token list creation */
+ while ( name_type(p)>=mp_x_part_sector ) {
+ @<Preface the output with a part specifier; |return| in the
+ case of a capsule@>;
+ }
+ q=null;
+ while ( name_type(p)>mp_saved_root ) {
+ @<Ascend one level, pushing a token onto list |q|
+ and replacing |p| by its parent@>;
+ }
+ r=mp_get_avail(mp); info(r)=link(p); link(r)=q;
+ if ( name_type(p)==mp_saved_root ) mp_print(mp, "(SAVED)");
+@.SAVED@>
+ mp_show_token_list(mp, r,null,el_gordo,mp->tally);
+ mp_flush_token_list(mp, r);
+}
+
+@ @<Ascend one level, pushing a token onto list |q|...@>=
+{
+ if ( name_type(p)==mp_subscr ) {
+ r=mp_new_num_tok(mp, subscript(p));
+ do {
+ p=link(p);
+ } while (name_type(p)!=mp_attr);
+ } else if ( name_type(p)==mp_structured_root ) {
+ p=link(p); goto FOUND;
+ } else {
+ if ( name_type(p)!=mp_attr ) mp_confusion(mp, "var");
+@:this can't happen var}{\quad var@>
+ r=mp_get_avail(mp); info(r)=attr_loc(p);
+ }
+ link(r)=q; q=r;
+FOUND:
+ p=parent(p);
+}
+
+@ @<Preface the output with a part specifier...@>=
+{ switch (name_type(p)) {
+ case mp_x_part_sector: mp_print_char(mp, 'x'); break;
+ case mp_y_part_sector: mp_print_char(mp, 'y'); break;
+ case mp_xx_part_sector: mp_print(mp, "xx"); break;
+ case mp_xy_part_sector: mp_print(mp, "xy"); break;
+ case mp_yx_part_sector: mp_print(mp, "yx"); break;
+ case mp_yy_part_sector: mp_print(mp, "yy"); break;
+ case mp_red_part_sector: mp_print(mp, "red"); break;
+ case mp_green_part_sector: mp_print(mp, "green"); break;
+ case mp_blue_part_sector: mp_print(mp, "blue"); break;
+ case mp_cyan_part_sector: mp_print(mp, "cyan"); break;
+ case mp_magenta_part_sector: mp_print(mp, "magenta"); break;
+ case mp_yellow_part_sector: mp_print(mp, "yellow"); break;
+ case mp_black_part_sector: mp_print(mp, "black"); break;
+ case mp_grey_part_sector: mp_print(mp, "grey"); break;
+ case mp_capsule:
+ mp_print(mp, "%CAPSULE"); mp_print_int(mp, p-null); return;
+ break;
+@.CAPSULE@>
+ } /* there are no other cases */
+ mp_print(mp, "part ");
+ p=link(p-mp->sector_offset[name_type(p)]);
+}
+
+@ The |interesting| function returns |true| if a given variable is not
+in a capsule, or if the user wants to trace capsules.
+
+@c
+boolean mp_interesting (MP mp,pointer p) {
+ small_number t; /* a |name_type| */
+ if ( mp->internal[mp_tracing_capsules]>0 ) {
+ return true;
+ } else {
+ t=name_type(p);
+ if ( t>=mp_x_part_sector ) if ( t!=mp_capsule )
+ t=name_type(link(p-mp->sector_offset[t]));
+ return (t!=mp_capsule);
+ }
+}
+
+@ Now here is a subroutine that converts an unstructured type into an
+equivalent structured type, by inserting a |mp_structured| node that is
+capable of growing. This operation is done only when |name_type(p)=root|,
+|subscr|, or |attr|.
+
+The procedure returns a pointer to the new node that has taken node~|p|'s
+place in the structure. Node~|p| itself does not move, nor are its
+|value| or |type| fields changed in any way.
+
+@c
+pointer mp_new_structure (MP mp,pointer p) {
+ pointer q,r=0; /* list manipulation registers */
+ switch (name_type(p)) {
+ case mp_root:
+ q=link(p); r=mp_get_node(mp, value_node_size); equiv(q)=r;
+ break;
+ case mp_subscr:
+ @<Link a new subscript node |r| in place of node |p|@>;
+ break;
+ case mp_attr:
+ @<Link a new attribute node |r| in place of node |p|@>;
+ break;
+ default:
+ mp_confusion(mp, "struct");
+@:this can't happen struct}{\quad struct@>
+ break;
+ }
+ link(r)=link(p); type(r)=mp_structured; name_type(r)=name_type(p);
+ attr_head(r)=p; name_type(p)=mp_structured_root;
+ q=mp_get_node(mp, attr_node_size); link(p)=q; subscr_head(r)=q;
+ parent(q)=r; type(q)=undefined; name_type(q)=mp_attr; link(q)=end_attr;
+ attr_loc(q)=collective_subscript;
+ return r;
+}
+
+@ @<Link a new subscript node |r| in place of node |p|@>=
+{
+ q=p;
+ do {
+ q=link(q);
+ } while (name_type(q)!=mp_attr);
+ q=parent(q); r=subscr_head_loc(q); /* |link(r)=subscr_head(q)| */
+ do {
+ q=r; r=link(r);
+ } while (r!=p);
+ r=mp_get_node(mp, subscr_node_size);
+ link(q)=r; subscript(r)=subscript(p);
+}
+
+@ If the attribute is |collective_subscript|, there are two pointers to
+node~|p|, so we must change both of them.
+
+@<Link a new attribute node |r| in place of node |p|@>=
+{
+ q=parent(p); r=attr_head(q);
+ do {
+ q=r; r=link(r);
+ } while (r!=p);
+ r=mp_get_node(mp, attr_node_size); link(q)=r;
+ mp->mem[attr_loc_loc(r)]=mp->mem[attr_loc_loc(p)]; /* copy |attr_loc| and |parent| */
+ if ( attr_loc(p)==collective_subscript ) {
+ q=subscr_head_loc(parent(p));
+ while ( link(q)!=p ) q=link(q);
+ link(q)=r;
+ }
+}
+
+@ The |find_variable| routine is given a pointer~|t| to a nonempty token
+list of suffixes; it returns a pointer to the corresponding two-word
+value. For example, if |t| points to token \.x followed by a numeric
+token containing the value~7, |find_variable| finds where the value of
+\.{x7} is stored in memory. This may seem a simple task, and it
+usually is, except when \.{x7} has never been referenced before.
+Indeed, \.x may never have even been subscripted before; complexities
+arise with respect to updating the collective subscript information.
+
+If a macro type is detected anywhere along path~|t|, or if the first
+item on |t| isn't a |tag_token|, the value |null| is returned.
+Otherwise |p| will be a non-null pointer to a node such that
+|undefined<type(p)<mp_structured|.
+
+@d abort_find { return null; }
+
+@c
+pointer mp_find_variable (MP mp,pointer t) {
+ pointer p,q,r,s; /* nodes in the ``value'' line */
+ pointer pp,qq,rr,ss; /* nodes in the ``collective'' line */
+ integer n; /* subscript or attribute */
+ memory_word save_word; /* temporary storage for a word of |mem| */
+@^inner loop@>
+ p=info(t); t=link(t);
+ if ( (eq_type(p) % outer_tag) != tag_token ) abort_find;
+ if ( equiv(p)==null ) mp_new_root(mp, p);
+ p=equiv(p); pp=p;
+ while ( t!=null ) {
+ @<Make sure that both nodes |p| and |pp| are of |mp_structured| type@>;
+ if ( t<mp->hi_mem_min ) {
+ @<Descend one level for the subscript |value(t)|@>
+ } else {
+ @<Descend one level for the attribute |info(t)|@>;
+ }
+ t=link(t);
+ }
+ if ( type(pp)>=mp_structured ) {
+ if ( type(pp)==mp_structured ) pp=attr_head(pp); else abort_find;
+ }
+ if ( type(p)==mp_structured ) p=attr_head(p);
+ if ( type(p)==undefined ) {
+ if ( type(pp)==undefined ) { type(pp)=mp_numeric_type; value(pp)=null; };
+ type(p)=type(pp); value(p)=null;
+ };
+ return p;
+}
+
+@ Although |pp| and |p| begin together, they diverge when a subscript occurs;
+|pp|~stays in the collective line while |p|~goes through actual subscript
+values.
+
+@<Make sure that both nodes |p| and |pp|...@>=
+if ( type(pp)!=mp_structured ) {
+ if ( type(pp)>mp_structured ) abort_find;
+ ss=mp_new_structure(mp, pp);
+ if ( p==pp ) p=ss;
+ pp=ss;
+}; /* now |type(pp)=mp_structured| */
+if ( type(p)!=mp_structured ) /* it cannot be |>mp_structured| */
+ p=mp_new_structure(mp, p) /* now |type(p)=mp_structured| */
+
+@ We want this part of the program to be reasonably fast, in case there are
+@^inner loop@>
+lots of subscripts at the same level of the data structure. Therefore
+we store an ``infinite'' value in the word that appears at the end of the
+subscript list, even though that word isn't part of a subscript node.
+
+@<Descend one level for the subscript |value(t)|@>=
+{
+ n=value(t);
+ pp=link(attr_head(pp)); /* now |attr_loc(pp)=collective_subscript| */
+ q=link(attr_head(p)); save_word=mp->mem[subscript_loc(q)];
+ subscript(q)=el_gordo; s=subscr_head_loc(p); /* |link(s)=subscr_head(p)| */
+ do {
+ r=s; s=link(s);
+ } while (n>subscript(s));
+ if ( n==subscript(s) ) {
+ p=s;
+ } else {
+ p=mp_get_node(mp, subscr_node_size); link(r)=p; link(p)=s;
+ subscript(p)=n; name_type(p)=mp_subscr; type(p)=undefined;
+ }
+ mp->mem[subscript_loc(q)]=save_word;
+}
+
+@ @<Descend one level for the attribute |info(t)|@>=
+{
+ n=info(t);
+ ss=attr_head(pp);
+ do {
+ rr=ss; ss=link(ss);
+ } while (n>attr_loc(ss));
+ if ( n<attr_loc(ss) ) {
+ qq=mp_get_node(mp, attr_node_size); link(rr)=qq; link(qq)=ss;
+ attr_loc(qq)=n; name_type(qq)=mp_attr; type(qq)=undefined;
+ parent(qq)=pp; ss=qq;
+ }
+ if ( p==pp ) {
+ p=ss; pp=ss;
+ } else {
+ pp=ss; s=attr_head(p);
+ do {
+ r=s; s=link(s);
+ } while (n>attr_loc(s));
+ if ( n==attr_loc(s) ) {
+ p=s;
+ } else {
+ q=mp_get_node(mp, attr_node_size); link(r)=q; link(q)=s;
+ attr_loc(q)=n; name_type(q)=mp_attr; type(q)=undefined;
+ parent(q)=p; p=q;
+ }
+ }
+}
+
+@ Variables lose their former values when they appear in a type declaration,
+or when they are defined to be macros or \&{let} equal to something else.
+A subroutine will be defined later that recycles the storage associated
+with any particular |type| or |value|; our goal now is to study a higher
+level process called |flush_variable|, which selectively frees parts of a
+variable structure.
+
+This routine has some complexity because of examples such as
+`\hbox{\tt numeric x[]a[]b}'
+which recycles all variables of the form \.{x[i]a[j]b} (and no others), while
+`\hbox{\tt vardef x[]a[]=...}'
+discards all variables of the form \.{x[i]a[j]} followed by an arbitrary
+suffix, except for the collective node \.{x[]a[]} itself. The obvious way
+to handle such examples is to use recursion; so that's what we~do.
+@^recursion@>
+
+Parameter |p| points to the root information of the variable;
+parameter |t| points to a list of one-word nodes that represent
+suffixes, with |info=collective_subscript| for subscripts.
+
+@<Declarations@>=
+@<Declare subroutines for printing expressions@>
+@<Declare basic dependency-list subroutines@>
+@<Declare the recycling subroutines@>
+void mp_flush_cur_exp (MP mp,scaled v) ;
+@<Declare the procedure called |flush_below_variable|@>
+
+@ @c
+void mp_flush_variable (MP mp,pointer p, pointer t, boolean discard_suffixes) {
+ pointer q,r; /* list manipulation */
+ halfword n; /* attribute to match */
+ while ( t!=null ) {
+ if ( type(p)!=mp_structured ) return;
+ n=info(t); t=link(t);
+ if ( n==collective_subscript ) {
+ r=subscr_head_loc(p); q=link(r); /* |q=subscr_head(p)| */
+ while ( name_type(q)==mp_subscr ){
+ mp_flush_variable(mp, q,t,discard_suffixes);
+ if ( t==null ) {
+ if ( type(q)==mp_structured ) r=q;
+ else { link(r)=link(q); mp_free_node(mp, q,subscr_node_size); }
+ } else {
+ r=q;
+ }
+ q=link(r);
+ }
+ }
+ p=attr_head(p);
+ do {
+ r=p; p=link(p);
+ } while (attr_loc(p)<n);
+ if ( attr_loc(p)!=n ) return;
+ }
+ if ( discard_suffixes ) {
+ mp_flush_below_variable(mp, p);
+ } else {
+ if ( type(p)==mp_structured ) p=attr_head(p);
+ mp_recycle_value(mp, p);
+ }
+}
+
+@ The next procedure is simpler; it wipes out everything but |p| itself,
+which becomes undefined.
+
+@<Declare the procedure called |flush_below_variable|@>=
+void mp_flush_below_variable (MP mp, pointer p);
+
+@ @c
+void mp_flush_below_variable (MP mp,pointer p) {
+ pointer q,r; /* list manipulation registers */
+ if ( type(p)!=mp_structured ) {
+ mp_recycle_value(mp, p); /* this sets |type(p)=undefined| */
+ } else {
+ q=subscr_head(p);
+ while ( name_type(q)==mp_subscr ) {
+ mp_flush_below_variable(mp, q); r=q; q=link(q);
+ mp_free_node(mp, r,subscr_node_size);
+ }
+ r=attr_head(p); q=link(r); mp_recycle_value(mp, r);
+ if ( name_type(p)<=mp_saved_root ) mp_free_node(mp, r,value_node_size);
+ else mp_free_node(mp, r,subscr_node_size);
+ /* we assume that |subscr_node_size=attr_node_size| */
+ do {
+ mp_flush_below_variable(mp, q); r=q; q=link(q); mp_free_node(mp, r,attr_node_size);
+ } while (q!=end_attr);
+ type(p)=undefined;
+ }
+}
+
+@ Just before assigning a new value to a variable, we will recycle the
+old value and make the old value undefined. The |und_type| routine
+determines what type of undefined value should be given, based on
+the current type before recycling.
+
+@c
+small_number mp_und_type (MP mp,pointer p) {
+ switch (type(p)) {
+ case undefined: case mp_vacuous:
+ return undefined;
+ case mp_boolean_type: case mp_unknown_boolean:
+ return mp_unknown_boolean;
+ case mp_string_type: case mp_unknown_string:
+ return mp_unknown_string;
+ case mp_pen_type: case mp_unknown_pen:
+ return mp_unknown_pen;
+ case mp_path_type: case mp_unknown_path:
+ return mp_unknown_path;
+ case mp_picture_type: case mp_unknown_picture:
+ return mp_unknown_picture;
+ case mp_transform_type: case mp_color_type: case mp_cmykcolor_type:
+ case mp_pair_type: case mp_numeric_type:
+ return type(p);
+ case mp_known: case mp_dependent: case mp_proto_dependent: case mp_independent:
+ return mp_numeric_type;
+ } /* there are no other cases */
+ return 0;
+}
+
+@ The |clear_symbol| routine is used when we want to redefine the equivalent
+of a symbolic token. It must remove any variable structure or macro
+definition that is currently attached to that symbol. If the |saving|
+parameter is true, a subsidiary structure is saved instead of destroyed.
+
+@c
+void mp_clear_symbol (MP mp,pointer p, boolean saving) {
+ pointer q; /* |equiv(p)| */
+ q=equiv(p);
+ switch (eq_type(p) % outer_tag) {
+ case defined_macro:
+ case secondary_primary_macro:
+ case tertiary_secondary_macro:
+ case expression_tertiary_macro:
+ if ( ! saving ) mp_delete_mac_ref(mp, q);
+ break;
+ case tag_token:
+ if ( q!=null ) {
+ if ( saving ) {
+ name_type(q)=mp_saved_root;
+ } else {
+ mp_flush_below_variable(mp, q);
+ mp_free_node(mp,q,value_node_size);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ mp->eqtb[p]=mp->eqtb[frozen_undefined];
+}
+
+@* \[16] Saving and restoring equivalents.
+The nested structure given by \&{begingroup} and \&{endgroup}
+allows |eqtb| entries to be saved and restored, so that temporary changes
+can be made without difficulty. When the user requests a current value to
+be saved, \MP\ puts that value into its ``save stack.'' An appearance of
+\&{endgroup} ultimately causes the old values to be removed from the save
+stack and put back in their former places.
+
+The save stack is a linked list containing three kinds of entries,
+distinguished by their |info| fields. If |p| points to a saved item,
+then
+
+\smallskip\hang
+|info(p)=0| stands for a group boundary; each \&{begingroup} contributes
+such an item to the save stack and each \&{endgroup} cuts back the stack
+until the most recent such entry has been removed.
+
+\smallskip\hang
+|info(p)=q|, where |1<=q<=hash_end|, means that |mem[p+1]| holds the former
+contents of |eqtb[q]|. Such save stack entries are generated by \&{save}
+commands.
+
+\smallskip\hang
+|info(p)=hash_end+q|, where |q>0|, means that |value(p)| is a |scaled|
+integer to be restored to internal parameter number~|q|. Such entries
+are generated by \&{interim} commands.
+
+\smallskip\noindent
+The global variable |save_ptr| points to the top item on the save stack.
+
+@d save_node_size 2 /* number of words per non-boundary save-stack node */
+@d saved_equiv(A) mp->mem[(A)+1].hh /* where an |eqtb| entry gets saved */
+@d save_boundary_item(A) { (A)=mp_get_avail(mp); info((A))=0;
+ link((A))=mp->save_ptr; mp->save_ptr=(A);
+ }
+
+@<Glob...@>=
+pointer save_ptr; /* the most recently saved item */
+
+@ @<Set init...@>=mp->save_ptr=null;
+
+@ The |save_variable| routine is given a hash address |q|; it salts this
+address in the save stack, together with its current equivalent,
+then makes token~|q| behave as though it were brand new.
+
+Nothing is stacked when |save_ptr=null|, however; there's no way to remove
+things from the stack when the program is not inside a group, so there's
+no point in wasting the space.
+
+@c void mp_save_variable (MP mp,pointer q) {
+ pointer p; /* temporary register */
+ if ( mp->save_ptr!=null ){
+ p=mp_get_node(mp, save_node_size); info(p)=q; link(p)=mp->save_ptr;
+ saved_equiv(p)=mp->eqtb[q]; mp->save_ptr=p;
+ }
+ mp_clear_symbol(mp, q,(mp->save_ptr!=null));
+}
+
+@ Similarly, |save_internal| is given the location |q| of an internal
+quantity like |mp_tracing_pens|. It creates a save stack entry of the
+third kind.
+
+@c void mp_save_internal (MP mp,halfword q) {
+ pointer p; /* new item for the save stack */
+ if ( mp->save_ptr!=null ){
+ p=mp_get_node(mp, save_node_size); info(p)=hash_end+q;
+ link(p)=mp->save_ptr; value(p)=mp->internal[q]; mp->save_ptr=p;
+ }
+}
+
+@ At the end of a group, the |unsave| routine restores all of the saved
+equivalents in reverse order. This routine will be called only when there
+is at least one boundary item on the save stack.
+
+@c
+void mp_unsave (MP mp) {
+ pointer q; /* index to saved item */
+ pointer p; /* temporary register */
+ while ( info(mp->save_ptr)!=0 ) {
+ q=info(mp->save_ptr);
+ if ( q>hash_end ) {
+ if ( mp->internal[mp_tracing_restores]>0 ) {
+ mp_begin_diagnostic(mp); mp_print_nl(mp, "{restoring ");
+ mp_print(mp, mp->int_name[q-(hash_end)]); mp_print_char(mp, '=');
+ mp_print_scaled(mp, value(mp->save_ptr)); mp_print_char(mp, '}');
+ mp_end_diagnostic(mp, false);
+ }
+ mp->internal[q-(hash_end)]=value(mp->save_ptr);
+ } else {
+ if ( mp->internal[mp_tracing_restores]>0 ) {
+ mp_begin_diagnostic(mp); mp_print_nl(mp, "{restoring ");
+ mp_print_text(q); mp_print_char(mp, '}');
+ mp_end_diagnostic(mp, false);
+ }
+ mp_clear_symbol(mp, q,false);
+ mp->eqtb[q]=saved_equiv(mp->save_ptr);
+ if ( eq_type(q) % outer_tag==tag_token ) {
+ p=equiv(q);
+ if ( p!=null ) name_type(p)=mp_root;
+ }
+ }
+ p=link(mp->save_ptr);
+ mp_free_node(mp, mp->save_ptr,save_node_size); mp->save_ptr=p;
+ }
+ p=link(mp->save_ptr); free_avail(mp->save_ptr); mp->save_ptr=p;
+}
+
+@* \[17] Data structures for paths.
+When a \MP\ user specifies a path, \MP\ will create a list of knots
+and control points for the associated cubic spline curves. If the
+knots are $z_0$, $z_1$, \dots, $z_n$, there are control points
+$z_k^+$ and $z_{k+1}^-$ such that the cubic splines between knots
+$z_k$ and $z_{k+1}$ are defined by B\'ezier's formula
+@:Bezier}{B\'ezier, Pierre Etienne@>
+$$\eqalign{z(t)&=B(z_k,z_k^+,z_{k+1}^-,z_{k+1};t)\cr
+&=(1-t)^3z_k+3(1-t)^2tz_k^++3(1-t)t^2z_{k+1}^-+t^3z_{k+1}\cr}$$
+for |0<=t<=1|.
+
+There is a 8-word node for each knot $z_k$, containing one word of
+control information and six words for the |x| and |y| coordinates of
+$z_k^-$ and $z_k$ and~$z_k^+$. The control information appears in the
+|left_type| and |right_type| fields, which each occupy a quarter of
+the first word in the node; they specify properties of the curve as it
+enters and leaves the knot. There's also a halfword |link| field,
+which points to the following knot, and a final supplementary word (of
+which only a quarter is used).
+
+If the path is a closed contour, knots 0 and |n| are identical;
+i.e., the |link| in knot |n-1| points to knot~0. But if the path
+is not closed, the |left_type| of knot~0 and the |right_type| of knot~|n|
+are equal to |endpoint|. In the latter case the |link| in knot~|n| points
+to knot~0, and the control points $z_0^-$ and $z_n^+$ are not used.
+
+@d left_type(A) mp->mem[(A)].hh.b0 /* characterizes the path entering this knot */
+@d right_type(A) mp->mem[(A)].hh.b1 /* characterizes the path leaving this knot */
+@d x_coord(A) mp->mem[(A)+1].sc /* the |x| coordinate of this knot */
+@d y_coord(A) mp->mem[(A)+2].sc /* the |y| coordinate of this knot */
+@d left_x(A) mp->mem[(A)+3].sc /* the |x| coordinate of previous control point */
+@d left_y(A) mp->mem[(A)+4].sc /* the |y| coordinate of previous control point */
+@d right_x(A) mp->mem[(A)+5].sc /* the |x| coordinate of next control point */
+@d right_y(A) mp->mem[(A)+6].sc /* the |y| coordinate of next control point */
+@d x_loc(A) ((A)+1) /* where the |x| coordinate is stored in a knot */
+@d y_loc(A) ((A)+2) /* where the |y| coordinate is stored in a knot */
+@d knot_coord(A) mp->mem[(A)].sc /* |x| or |y| coordinate given |x_loc| or |y_loc| */
+@d left_coord(A) mp->mem[(A)+2].sc
+ /* coordinate of previous control point given |x_loc| or |y_loc| */
+@d right_coord(A) mp->mem[(A)+4].sc
+ /* coordinate of next control point given |x_loc| or |y_loc| */
+@d knot_node_size 8 /* number of words in a knot node */
+
+@<Types...@>=
+enum mp_knot_type {
+ mp_endpoint=0, /* |left_type| at path beginning and |right_type| at path end */
+ mp_explicit, /* |left_type| or |right_type| when control points are known */
+ mp_given, /* |left_type| or |right_type| when a direction is given */
+ mp_curl, /* |left_type| or |right_type| when a curl is desired */
+ mp_open, /* |left_type| or |right_type| when \MP\ should choose the direction */
+ mp_end_cycle
+};
+
+@ Before the B\'ezier control points have been calculated, the memory
+space they will ultimately occupy is taken up by information that can be
+used to compute them. There are four cases:
+
+\yskip
+\textindent{$\bullet$} If |right_type=mp_open|, the curve should leave
+the knot in the same direction it entered; \MP\ will figure out a
+suitable direction.
+
+\yskip
+\textindent{$\bullet$} If |right_type=mp_curl|, the curve should leave the
+knot in a direction depending on the angle at which it enters the next
+knot and on the curl parameter stored in |right_curl|.
+
+\yskip
+\textindent{$\bullet$} If |right_type=mp_given|, the curve should leave the
+knot in a nonzero direction stored as an |angle| in |right_given|.
+
+\yskip
+\textindent{$\bullet$} If |right_type=mp_explicit|, the B\'ezier control
+point for leaving this knot has already been computed; it is in the
+|right_x| and |right_y| fields.
+
+\yskip\noindent
+The rules for |left_type| are similar, but they refer to the curve entering
+the knot, and to \\{left} fields instead of \\{right} fields.
+
+Non-|explicit| control points will be chosen based on ``tension'' parameters
+in the |left_tension| and |right_tension| fields. The
+`\&{atleast}' option is represented by negative tension values.
+@:at_least_}{\&{atleast} primitive@>
+
+For example, the \MP\ path specification
+$$\.{z0..z1..tension atleast 1..\{curl 2\}z2..z3\{-1,-2\}..tension
+ 3 and 4..p},$$
+where \.p is the path `\.{z4..controls z45 and z54..z5}', will be represented
+by the six knots
+\def\lodash{\hbox to 1.1em{\thinspace\hrulefill\thinspace}}
+$$\vbox{\halign{#\hfil&&\qquad#\hfil\cr
+|left_type|&\\{left} info&|x_coord,y_coord|&|right_type|&\\{right} info\cr
+\noalign{\yskip}
+|endpoint|&\lodash$,\,$\lodash&$x_0,y_0$&|curl|&$1.0,1.0$\cr
+|open|&\lodash$,1.0$&$x_1,y_1$&|open|&\lodash$,-1.0$\cr
+|curl|&$2.0,-1.0$&$x_2,y_2$&|curl|&$2.0,1.0$\cr
+|given|&$d,1.0$&$x_3,y_3$&|given|&$d,3.0$\cr
+|open|&\lodash$,4.0$&$x_4,y_4$&|explicit|&$x_{45},y_{45}$\cr
+|explicit|&$x_{54},y_{54}$&$x_5,y_5$&|endpoint|&\lodash$,\,$\lodash\cr}}$$
+Here |d| is the |angle| obtained by calling |n_arg(-unity,-two)|.
+Of course, this example is more complicated than anything a normal user
+would ever write.
+
+These types must satisfy certain restrictions because of the form of \MP's
+path syntax:
+(i)~|open| type never appears in the same node together with |endpoint|,
+|given|, or |curl|.
+(ii)~The |right_type| of a node is |explicit| if and only if the
+|left_type| of the following node is |explicit|.
+(iii)~|endpoint| types occur only at the ends, as mentioned above.
+
+@d left_curl left_x /* curl information when entering this knot */
+@d left_given left_x /* given direction when entering this knot */
+@d left_tension left_y /* tension information when entering this knot */
+@d right_curl right_x /* curl information when leaving this knot */
+@d right_given right_x /* given direction when leaving this knot */
+@d right_tension right_y /* tension information when leaving this knot */
+
+@ Knots can be user-supplied, or they can be created by program code,
+like the |split_cubic| function, or |copy_path|. The distinction is
+needed for the cleanup routine that runs after |split_cubic|, because
+it should only delete knots it has previously inserted, and never
+anything that was user-supplied. In order to be able to differentiate
+one knot from another, we will set |originator(p):=mp_metapost_user| when
+it appeared in the actual metapost program, and
+|originator(p):=mp_program_code| in all other cases.
+
+@d originator(A) mp->mem[(A)+7].hh.b0 /* the creator of this knot */
+
+@<Types...@>=
+enum {
+ mp_program_code=0, /* not created by a user */
+ mp_metapost_user /* created by a user */
+};
+
+@ Here is a routine that prints a given knot list
+in symbolic form. It illustrates the conventions discussed above,
+and checks for anomalies that might arise while \MP\ is being debugged.
+
+@<Declare subroutines for printing expressions@>=
+void mp_pr_path (MP mp,pointer h);
+
+@ @c
+void mp_pr_path (MP mp,pointer h) {
+ pointer p,q; /* for list traversal */
+ p=h;
+ do {
+ q=link(p);
+ if ( (p==null)||(q==null) ) {
+ mp_print_nl(mp, "???"); return; /* this won't happen */
+@.???@>
+ }
+ @<Print information for adjacent knots |p| and |q|@>;
+ DONE1:
+ p=q;
+ if ( (p!=h)||(left_type(h)!=mp_endpoint) ) {
+ @<Print two dots, followed by |given| or |curl| if present@>;
+ }
+ } while (p!=h);
+ if ( left_type(h)!=mp_endpoint )
+ mp_print(mp, "cycle");
+}
+
+@ @<Print information for adjacent knots...@>=
+mp_print_two(mp, x_coord(p),y_coord(p));
+switch (right_type(p)) {
+case mp_endpoint:
+ if ( left_type(p)==mp_open ) mp_print(mp, "{open?}"); /* can't happen */
+@.open?@>
+ if ( (left_type(q)!=mp_endpoint)||(q!=h) ) q=null; /* force an error */
+ goto DONE1;
+ break;
+case mp_explicit:
+ @<Print control points between |p| and |q|, then |goto done1|@>;
+ break;
+case mp_open:
+ @<Print information for a curve that begins |open|@>;
+ break;
+case mp_curl:
+case mp_given:
+ @<Print information for a curve that begins |curl| or |given|@>;
+ break;
+default:
+ mp_print(mp, "???"); /* can't happen */
+@.???@>
+ break;
+}
+if ( left_type(q)<=mp_explicit ) {
+ mp_print(mp, "..control?"); /* can't happen */
+@.control?@>
+} else if ( (right_tension(p)!=unity)||(left_tension(q)!=unity) ) {
+ @<Print tension between |p| and |q|@>;
+}
+
+@ Since |n_sin_cos| produces |fraction| results, which we will print as if they
+were |scaled|, the magnitude of a |given| direction vector will be~4096.
+
+@<Print two dots...@>=
+{
+ mp_print_nl(mp, " ..");
+ if ( left_type(p)==mp_given ) {
+ mp_n_sin_cos(mp, left_given(p)); mp_print_char(mp, '{');
+ mp_print_scaled(mp, mp->n_cos); mp_print_char(mp, ',');
+ mp_print_scaled(mp, mp->n_sin); mp_print_char(mp, '}');
+ } else if ( left_type(p)==mp_curl ){
+ mp_print(mp, "{curl ");
+ mp_print_scaled(mp, left_curl(p)); mp_print_char(mp, '}');
+ }
+}
+
+@ @<Print tension between |p| and |q|@>=
+{
+ mp_print(mp, "..tension ");
+ if ( right_tension(p)<0 ) mp_print(mp, "atleast");
+ mp_print_scaled(mp, abs(right_tension(p)));
+ if ( right_tension(p)!=left_tension(q) ){
+ mp_print(mp, " and ");
+ if ( left_tension(q)<0 ) mp_print(mp, "atleast");
+ mp_print_scaled(mp, abs(left_tension(q)));
+ }
+}
+
+@ @<Print control points between |p| and |q|, then |goto done1|@>=
+{
+ mp_print(mp, "..controls ");
+ mp_print_two(mp, right_x(p),right_y(p));
+ mp_print(mp, " and ");
+ if ( left_type(q)!=mp_explicit ) {
+ mp_print(mp, "??"); /* can't happen */
+@.??@>
+ } else {
+ mp_print_two(mp, left_x(q),left_y(q));
+ }
+ goto DONE1;
+}
+
+@ @<Print information for a curve that begins |open|@>=
+if ( (left_type(p)!=mp_explicit)&&(left_type(p)!=mp_open) ) {
+ mp_print(mp, "{open?}"); /* can't happen */
+@.open?@>
+}
+
+@ A curl of 1 is shown explicitly, so that the user sees clearly that
+\MP's default curl is present.
+
+@<Print information for a curve that begins |curl|...@>=
+{
+ if ( left_type(p)==mp_open )
+ mp_print(mp, "??"); /* can't happen */
+@.??@>
+ if ( right_type(p)==mp_curl ) {
+ mp_print(mp, "{curl "); mp_print_scaled(mp, right_curl(p));
+ } else {
+ mp_n_sin_cos(mp, right_given(p)); mp_print_char(mp, '{');
+ mp_print_scaled(mp, mp->n_cos); mp_print_char(mp, ',');
+ mp_print_scaled(mp, mp->n_sin);
+ }
+ mp_print_char(mp, '}');
+}
+
+@ It is convenient to have another version of |pr_path| that prints the path
+as a diagnostic message.
+
+@<Declare subroutines for printing expressions@>=
+void mp_print_path (MP mp,pointer h, const char *s, boolean nuline) {
+ mp_print_diagnostic(mp, "Path", s, nuline); mp_print_ln(mp);
+@.Path at line...@>
+ mp_pr_path(mp, h);
+ mp_end_diagnostic(mp, true);
+}
+
+@ If we want to duplicate a knot node, we can say |copy_knot|:
+
+@c
+pointer mp_copy_knot (MP mp,pointer p) {
+ pointer q; /* the copy */
+ int k; /* runs through the words of a knot node */
+ q=mp_get_node(mp, knot_node_size);
+ for (k=0;k<knot_node_size;k++) {
+ mp->mem[q+k]=mp->mem[p+k];
+ }
+ originator(q)=originator(p);
+ return q;
+}
+
+@ The |copy_path| routine makes a clone of a given path.
+
+@c
+pointer mp_copy_path (MP mp, pointer p) {
+ pointer q,pp,qq; /* for list manipulation */
+ q=mp_copy_knot(mp, p);
+ qq=q; pp=link(p);
+ while ( pp!=p ) {
+ link(qq)=mp_copy_knot(mp, pp);
+ qq=link(qq);
+ pp=link(pp);
+ }
+ link(qq)=q;
+ return q;
+}
+
+
+@ Just before |ship_out|, knot lists are exported for printing.
+
+The |gr_XXXX| macros are defined in |mppsout.h|.
+
+@c
+mp_knot *mp_export_knot (MP mp,pointer p) {
+ mp_knot *q; /* the copy */
+ if (p==null)
+ return NULL;
+ q = mp_xmalloc(mp, 1, sizeof (mp_knot));
+ memset(q,0,sizeof (mp_knot));
+ gr_left_type(q) = left_type(p);
+ gr_right_type(q) = right_type(p);
+ gr_x_coord(q) = x_coord(p);
+ gr_y_coord(q) = y_coord(p);
+ gr_left_x(q) = left_x(p);
+ gr_left_y(q) = left_y(p);
+ gr_right_x(q) = right_x(p);
+ gr_right_y(q) = right_y(p);
+ gr_originator(q) = originator(p);
+ return q;
+}
+
+@ The |export_knot_list| routine therefore also makes a clone
+of a given path.
+
+@c
+mp_knot *mp_export_knot_list (MP mp, pointer p) {
+ mp_knot *q, *qq; /* for list manipulation */
+ pointer pp; /* for list manipulation */
+ if (p==null)
+ return NULL;
+ q=mp_export_knot(mp, p);
+ qq=q; pp=link(p);
+ while ( pp!=p ) {
+ gr_next_knot(qq)=mp_export_knot(mp, pp);
+ qq=gr_next_knot(qq);
+ pp=link(pp);
+ }
+ gr_next_knot(qq)=q;
+ return q;
+}
+
+
+@ Similarly, there's a way to copy the {\sl reverse\/} of a path. This procedure
+returns a pointer to the first node of the copy, if the path is a cycle,
+but to the final node of a non-cyclic copy. The global
+variable |path_tail| will point to the final node of the original path;
+this trick makes it easier to implement `\&{doublepath}'.
+
+All node types are assumed to be |endpoint| or |explicit| only.
+
+@c
+pointer mp_htap_ypoc (MP mp,pointer p) {
+ pointer q,pp,qq,rr; /* for list manipulation */
+ q=mp_get_node(mp, knot_node_size); /* this will correspond to |p| */
+ qq=q; pp=p;
+ while (1) {
+ right_type(qq)=left_type(pp); left_type(qq)=right_type(pp);
+ x_coord(qq)=x_coord(pp); y_coord(qq)=y_coord(pp);
+ right_x(qq)=left_x(pp); right_y(qq)=left_y(pp);
+ left_x(qq)=right_x(pp); left_y(qq)=right_y(pp);
+ originator(qq)=originator(pp);
+ if ( link(pp)==p ) {
+ link(q)=qq; mp->path_tail=pp; return q;
+ }
+ rr=mp_get_node(mp, knot_node_size); link(rr)=qq; qq=rr; pp=link(pp);
+ }
+}
+
+@ @<Glob...@>=
+pointer path_tail; /* the node that links to the beginning of a path */
+
+@ When a cyclic list of knot nodes is no longer needed, it can be recycled by
+calling the following subroutine.
+
+@<Declare the recycling subroutines@>=
+void mp_toss_knot_list (MP mp,pointer p) ;
+
+@ @c
+void mp_toss_knot_list (MP mp,pointer p) {
+ pointer q; /* the node being freed */
+ pointer r; /* the next node */
+ q=p;
+ do {
+ r=link(q);
+ mp_free_node(mp, q,knot_node_size); q=r;
+ } while (q!=p);
+}
+
+@* \[18] Choosing control points.
+Now we must actually delve into one of \MP's more difficult routines,
+the |make_choices| procedure that chooses angles and control points for
+the splines of a curve when the user has not specified them explicitly.
+The parameter to |make_choices| points to a list of knots and
+path information, as described above.
+
+A path decomposes into independent segments at ``breakpoint'' knots,
+which are knots whose left and right angles are both prespecified in
+some way (i.e., their |left_type| and |right_type| aren't both open).
+
+@c
+@<Declare the procedure called |solve_choices|@>
+void mp_make_choices (MP mp,pointer knots) {
+ pointer h; /* the first breakpoint */
+ pointer p,q; /* consecutive breakpoints being processed */
+ @<Other local variables for |make_choices|@>;
+ check_arith; /* make sure that |arith_error=false| */
+ if ( mp->internal[mp_tracing_choices]>0 )
+ mp_print_path(mp, knots,", before choices",true);
+ @<If consecutive knots are equal, join them explicitly@>;
+ @<Find the first breakpoint, |h|, on the path;
+ insert an artificial breakpoint if the path is an unbroken cycle@>;
+ p=h;
+ do {
+ @<Fill in the control points between |p| and the next breakpoint,
+ then advance |p| to that breakpoint@>;
+ } while (p!=h);
+ if ( mp->internal[mp_tracing_choices]>0 )
+ mp_print_path(mp, knots,", after choices",true);
+ if ( mp->arith_error ) {
+ @<Report an unexpected problem during the choice-making@>;
+ }
+}
+
+@ @<Report an unexpected problem during the choice...@>=
+{
+ print_err("Some number got too big");
+@.Some number got too big@>
+ help2("The path that I just computed is out of range.")
+ ("So it will probably look funny. Proceed, for a laugh.");
+ mp_put_get_error(mp); mp->arith_error=false;
+}
+
+@ Two knots in a row with the same coordinates will always be joined
+by an explicit ``curve'' whose control points are identical with the
+knots.
+
+@<If consecutive knots are equal, join them explicitly@>=
+p=knots;
+do {
+ q=link(p);
+ if ( x_coord(p)==x_coord(q) && y_coord(p)==y_coord(q) && right_type(p)>mp_explicit ) {
+ right_type(p)=mp_explicit;
+ if ( left_type(p)==mp_open ) {
+ left_type(p)=mp_curl; left_curl(p)=unity;
+ }
+ left_type(q)=mp_explicit;
+ if ( right_type(q)==mp_open ) {
+ right_type(q)=mp_curl; right_curl(q)=unity;
+ }
+ right_x(p)=x_coord(p); left_x(q)=x_coord(p);
+ right_y(p)=y_coord(p); left_y(q)=y_coord(p);
+ }
+ p=q;
+} while (p!=knots)
+
+@ If there are no breakpoints, it is necessary to compute the direction
+angles around an entire cycle. In this case the |left_type| of the first
+node is temporarily changed to |end_cycle|.
+
+@<Find the first breakpoint, |h|, on the path...@>=
+h=knots;
+while (1) {
+ if ( left_type(h)!=mp_open ) break;
+ if ( right_type(h)!=mp_open ) break;
+ h=link(h);
+ if ( h==knots ) {
+ left_type(h)=mp_end_cycle; break;
+ }
+}
+
+@ If |right_type(p)<given| and |q=link(p)|, we must have
+|right_type(p)=left_type(q)=mp_explicit| or |endpoint|.
+
+@<Fill in the control points between |p| and the next breakpoint...@>=
+q=link(p);
+if ( right_type(p)>=mp_given ) {
+ while ( (left_type(q)==mp_open)&&(right_type(q)==mp_open) ) q=link(q);
+ @<Fill in the control information between
+ consecutive breakpoints |p| and |q|@>;
+} else if ( right_type(p)==mp_endpoint ) {
+ @<Give reasonable values for the unused control points between |p| and~|q|@>;
+}
+p=q
+
+@ This step makes it possible to transform an explicitly computed path without
+checking the |left_type| and |right_type| fields.
+
+@<Give reasonable values for the unused control points between |p| and~|q|@>=
+{
+ right_x(p)=x_coord(p); right_y(p)=y_coord(p);
+ left_x(q)=x_coord(q); left_y(q)=y_coord(q);
+}
+
+@ Before we can go further into the way choices are made, we need to
+consider the underlying theory. The basic ideas implemented in |make_choices|
+are due to John Hobby, who introduced the notion of ``mock curvature''
+@^Hobby, John Douglas@>
+at a knot. Angles are chosen so that they preserve mock curvature when
+a knot is passed, and this has been found to produce excellent results.
+
+It is convenient to introduce some notations that simplify the necessary
+formulas. Let $d_{k,k+1}=\vert z\k-z_k\vert$ be the (nonzero) distance
+between knots |k| and |k+1|; and let
+$${z\k-z_k\over z_k-z_{k-1}}={d_{k,k+1}\over d_{k-1,k}}e^{i\psi_k}$$
+so that a polygonal line from $z_{k-1}$ to $z_k$ to $z\k$ turns left
+through an angle of~$\psi_k$. We assume that $\vert\psi_k\vert\L180^\circ$.
+The control points for the spline from $z_k$ to $z\k$ will be denoted by
+$$\eqalign{z_k^+&=z_k+
+ \textstyle{1\over3}\rho_k e^{i\theta_k}(z\k-z_k),\cr
+ z\k^-&=z\k-
+ \textstyle{1\over3}\sigma\k e^{-i\phi\k}(z\k-z_k),\cr}$$
+where $\rho_k$ and $\sigma\k$ are nonnegative ``velocity ratios'' at the
+beginning and end of the curve, while $\theta_k$ and $\phi\k$ are the
+corresponding ``offset angles.'' These angles satisfy the condition
+$$\theta_k+\phi_k+\psi_k=0,\eqno(*)$$
+whenever the curve leaves an intermediate knot~|k| in the direction that
+it enters.
+
+@ Let $\alpha_k$ and $\beta\k$ be the reciprocals of the ``tension'' of
+the curve at its beginning and ending points. This means that
+$\rho_k=\alpha_k f(\theta_k,\phi\k)$ and $\sigma\k=\beta\k f(\phi\k,\theta_k)$,
+where $f(\theta,\phi)$ is \MP's standard velocity function defined in
+the |velocity| subroutine. The cubic spline $B(z_k^{\phantom+},z_k^+,
+z\k^-,z\k^{\phantom+};t)$
+has curvature
+@^curvature@>
+$${2\sigma\k\sin(\theta_k+\phi\k)-6\sin\theta_k\over\rho_k^2d_{k,k+1}}
+\qquad{\rm and}\qquad
+{2\rho_k\sin(\theta_k+\phi\k)-6\sin\phi\k\over\sigma\k^2d_{k,k+1}}$$
+at |t=0| and |t=1|, respectively. The mock curvature is the linear
+@^mock curvature@>
+approximation to this true curvature that arises in the limit for
+small $\theta_k$ and~$\phi\k$, if second-order terms are discarded.
+The standard velocity function satisfies
+$$f(\theta,\phi)=1+O(\theta^2+\theta\phi+\phi^2);$$
+hence the mock curvatures are respectively
+$${2\beta\k(\theta_k+\phi\k)-6\theta_k\over\alpha_k^2d_{k,k+1}}
+\qquad{\rm and}\qquad
+{2\alpha_k(\theta_k+\phi\k)-6\phi\k\over\beta\k^2d_{k,k+1}}.\eqno(**)$$
+
+@ The turning angles $\psi_k$ are given, and equation $(*)$ above
+determines $\phi_k$ when $\theta_k$ is known, so the task of
+angle selection is essentially to choose appropriate values for each
+$\theta_k$. When equation~$(*)$ is used to eliminate $\phi$~variables
+from $(**)$, we obtain a system of linear equations of the form
+$$A_k\theta_{k-1}+(B_k+C_k)\theta_k+D_k\theta\k=-B_k\psi_k-D_k\psi\k,$$
+where
+$$A_k={\alpha_{k-1}\over\beta_k^2d_{k-1,k}},
+\qquad B_k={3-\alpha_{k-1}\over\beta_k^2d_{k-1,k}},
+\qquad C_k={3-\beta\k\over\alpha_k^2d_{k,k+1}},
+\qquad D_k={\beta\k\over\alpha_k^2d_{k,k+1}}.$$
+The tensions are always $3\over4$ or more, hence each $\alpha$ and~$\beta$
+will be at most $4\over3$. It follows that $B_k\G{5\over4}A_k$ and
+$C_k\G{5\over4}D_k$; hence the equations are diagonally dominant;
+hence they have a unique solution. Moreover, in most cases the tensions
+are equal to~1, so that $B_k=2A_k$ and $C_k=2D_k$. This makes the
+solution numerically stable, and there is an exponential damping
+effect: The data at knot $k\pm j$ affects the angle at knot~$k$ by
+a factor of~$O(2^{-j})$.
+
+@ However, we still must consider the angles at the starting and ending
+knots of a non-cyclic path. These angles might be given explicitly, or
+they might be specified implicitly in terms of an amount of ``curl.''
+
+Let's assume that angles need to be determined for a non-cyclic path
+starting at $z_0$ and ending at~$z_n$. Then equations of the form
+$$A_k\theta_{k-1}+(B_k+C_k)\theta_k+D_k\theta_{k+1}=R_k$$
+have been given for $0<k<n$, and it will be convenient to introduce
+equations of the same form for $k=0$ and $k=n$, where
+$$A_0=B_0=C_n=D_n=0.$$
+If $\theta_0$ is supposed to have a given value $E_0$, we simply
+define $C_0=1$, $D_0=0$, and $R_0=E_0$. Otherwise a curl
+parameter, $\gamma_0$, has been specified at~$z_0$; this means
+that the mock curvature at $z_0$ should be $\gamma_0$ times the
+mock curvature at $z_1$; i.e.,
+$${2\beta_1(\theta_0+\phi_1)-6\theta_0\over\alpha_0^2d_{01}}
+=\gamma_0{2\alpha_0(\theta_0+\phi_1)-6\phi_1\over\beta_1^2d_{01}}.$$
+This equation simplifies to
+$$(\alpha_0\chi_0+3-\beta_1)\theta_0+
+ \bigl((3-\alpha_0)\chi_0+\beta_1\bigr)\theta_1=
+ -\bigl((3-\alpha_0)\chi_0+\beta_1\bigr)\psi_1,$$
+where $\chi_0=\alpha_0^2\gamma_0/\beta_1^2$; so we can set $C_0=
+\chi_0\alpha_0+3-\beta_1$, $D_0=(3-\alpha_0)\chi_0+\beta_1$, $R_0=-D_0\psi_1$.
+It can be shown that $C_0>0$ and $C_0B_1-A_1D_0>0$ when $\gamma_0\G0$,
+hence the linear equations remain nonsingular.
+
+Similar considerations apply at the right end, when the final angle $\phi_n$
+may or may not need to be determined. It is convenient to let $\psi_n=0$,
+hence $\theta_n=-\phi_n$. We either have an explicit equation $\theta_n=E_n$,
+or we have
+$$\bigl((3-\beta_n)\chi_n+\alpha_{n-1}\bigr)\theta_{n-1}+
+(\beta_n\chi_n+3-\alpha_{n-1})\theta_n=0,\qquad
+ \chi_n={\beta_n^2\gamma_n\over\alpha_{n-1}^2}.$$
+
+When |make_choices| chooses angles, it must compute the coefficients of
+these linear equations, then solve the equations. To compute the coefficients,
+it is necessary to compute arctangents of the given turning angles~$\psi_k$.
+When the equations are solved, the chosen directions $\theta_k$ are put
+back into the form of control points by essentially computing sines and
+cosines.
+
+@ OK, we are ready to make the hard choices of |make_choices|.
+Most of the work is relegated to an auxiliary procedure
+called |solve_choices|, which has been introduced to keep
+|make_choices| from being extremely long.
+
+@<Fill in the control information between...@>=
+@<Calculate the turning angles $\psi_k$ and the distances $d_{k,k+1}$;
+ set $n$ to the length of the path@>;
+@<Remove |open| types at the breakpoints@>;
+mp_solve_choices(mp, p,q,n)
+
+@ It's convenient to precompute quantities that will be needed several
+times later. The values of |delta_x[k]| and |delta_y[k]| will be the
+coordinates of $z\k-z_k$, and the magnitude of this vector will be
+|delta[k]=@t$d_{k,k+1}$@>|. The path angle $\psi_k$ between $z_k-z_{k-1}$
+and $z\k-z_k$ will be stored in |psi[k]|.
+
+@<Glob...@>=
+int path_size; /* maximum number of knots between breakpoints of a path */
+scaled *delta_x;
+scaled *delta_y;
+scaled *delta; /* knot differences */
+angle *psi; /* turning angles */
+
+@ @<Allocate or initialize ...@>=
+mp->delta_x = NULL;
+mp->delta_y = NULL;
+mp->delta = NULL;
+mp->psi = NULL;
+
+@ @<Dealloc variables@>=
+xfree(mp->delta_x);
+xfree(mp->delta_y);
+xfree(mp->delta);
+xfree(mp->psi);
+
+@ @<Other local variables for |make_choices|@>=
+ int k,n; /* current and final knot numbers */
+ pointer s,t; /* registers for list traversal */
+ scaled delx,dely; /* directions where |open| meets |explicit| */
+ fraction sine,cosine; /* trig functions of various angles */
+
+@ @<Calculate the turning angles...@>=
+{
+RESTART:
+ k=0; s=p; n=mp->path_size;
+ do {
+ t=link(s);
+ mp->delta_x[k]=x_coord(t)-x_coord(s);
+ mp->delta_y[k]=y_coord(t)-y_coord(s);
+ mp->delta[k]=mp_pyth_add(mp, mp->delta_x[k],mp->delta_y[k]);
+ if ( k>0 ) {
+ sine=mp_make_fraction(mp, mp->delta_y[k-1],mp->delta[k-1]);
+ cosine=mp_make_fraction(mp, mp->delta_x[k-1],mp->delta[k-1]);
+ mp->psi[k]=mp_n_arg(mp, mp_take_fraction(mp, mp->delta_x[k],cosine)+
+ mp_take_fraction(mp, mp->delta_y[k],sine),
+ mp_take_fraction(mp, mp->delta_y[k],cosine)-
+ mp_take_fraction(mp, mp->delta_x[k],sine));
+ }
+ incr(k); s=t;
+ if ( k==mp->path_size ) {
+ mp_reallocate_paths(mp, mp->path_size+(mp->path_size>>2));
+ goto RESTART; /* retry, loop size has changed */
+ }
+ if ( s==q ) n=k;
+ } while (!((k>=n)&&(left_type(s)!=mp_end_cycle)));
+ if ( k==n ) mp->psi[n]=0; else mp->psi[k]=mp->psi[1];
+}
+
+@ When we get to this point of the code, |right_type(p)| is either
+|given| or |curl| or |open|. If it is |open|, we must have
+|left_type(p)=mp_end_cycle| or |left_type(p)=mp_explicit|. In the latter
+case, the |open| type is converted to |given|; however, if the
+velocity coming into this knot is zero, the |open| type is
+converted to a |curl|, since we don't know the incoming direction.
+
+Similarly, |left_type(q)| is either |given| or |curl| or |open| or
+|mp_end_cycle|. The |open| possibility is reduced either to |given| or to |curl|.
+
+@<Remove |open| types at the breakpoints@>=
+if ( left_type(q)==mp_open ) {
+ delx=right_x(q)-x_coord(q); dely=right_y(q)-y_coord(q);
+ if ( (delx==0)&&(dely==0) ) {
+ left_type(q)=mp_curl; left_curl(q)=unity;
+ } else {
+ left_type(q)=mp_given; left_given(q)=mp_n_arg(mp, delx,dely);
+ }
+}
+if ( (right_type(p)==mp_open)&&(left_type(p)==mp_explicit) ) {
+ delx=x_coord(p)-left_x(p); dely=y_coord(p)-left_y(p);
+ if ( (delx==0)&&(dely==0) ) {
+ right_type(p)=mp_curl; right_curl(p)=unity;
+ } else {
+ right_type(p)=mp_given; right_given(p)=mp_n_arg(mp, delx,dely);
+ }
+}
+
+@ Linear equations need to be solved whenever |n>1|; and also when |n=1|
+and exactly one of the breakpoints involves a curl. The simplest case occurs
+when |n=1| and there is a curl at both breakpoints; then we simply draw
+a straight line.
+
+But before coding up the simple cases, we might as well face the general case,
+since we must deal with it sooner or later, and since the general case
+is likely to give some insight into the way simple cases can be handled best.
+
+When there is no cycle, the linear equations to be solved form a tridiagonal
+system, and we can apply the standard technique of Gaussian elimination
+to convert that system to a sequence of equations of the form
+$$\theta_0+u_0\theta_1=v_0,\quad
+\theta_1+u_1\theta_2=v_1,\quad\ldots,\quad
+\theta_{n-1}+u_{n-1}\theta_n=v_{n-1},\quad
+\theta_n=v_n.$$
+It is possible to do this diagonalization while generating the equations.
+Once $\theta_n$ is known, it is easy to determine $\theta_{n-1}$, \dots,
+$\theta_1$, $\theta_0$; thus, the equations will be solved.
+
+The procedure is slightly more complex when there is a cycle, but the
+basic idea will be nearly the same. In the cyclic case the right-hand
+sides will be $v_k+w_k\theta_0$ instead of simply $v_k$, and we will start
+the process off with $u_0=v_0=0$, $w_0=1$. The final equation will be not
+$\theta_n=v_n$ but $\theta_n+u_n\theta_1=v_n+w_n\theta_0$; an appropriate
+ending routine will take account of the fact that $\theta_n=\theta_0$ and
+eliminate the $w$'s from the system, after which the solution can be
+obtained as before.
+
+When $u_k$, $v_k$, and $w_k$ are being computed, the three pointer
+variables |r|, |s|,~|t| will point respectively to knots |k-1|, |k|,
+and~|k+1|. The $u$'s and $w$'s are scaled by $2^{28}$, i.e., they are
+of type |fraction|; the $\theta$'s and $v$'s are of type |angle|.
+
+@<Glob...@>=
+angle *theta; /* values of $\theta_k$ */
+fraction *uu; /* values of $u_k$ */
+angle *vv; /* values of $v_k$ */
+fraction *ww; /* values of $w_k$ */
+
+@ @<Allocate or initialize ...@>=
+mp->theta = NULL;
+mp->uu = NULL;
+mp->vv = NULL;
+mp->ww = NULL;
+
+@ @<Dealloc variables@>=
+xfree(mp->theta);
+xfree(mp->uu);
+xfree(mp->vv);
+xfree(mp->ww);
+
+@ @<Declare |mp_reallocate| functions@>=
+void mp_reallocate_paths (MP mp, int l);
+
+@ @c
+void mp_reallocate_paths (MP mp, int l) {
+ XREALLOC (mp->delta_x, l, scaled);
+ XREALLOC (mp->delta_y, l, scaled);
+ XREALLOC (mp->delta, l, scaled);
+ XREALLOC (mp->psi, l, angle);
+ XREALLOC (mp->theta, l, angle);
+ XREALLOC (mp->uu, l, fraction);
+ XREALLOC (mp->vv, l, angle);
+ XREALLOC (mp->ww, l, fraction);
+ mp->path_size = l;
+}
+
+@ Our immediate problem is to get the ball rolling by setting up the
+first equation or by realizing that no equations are needed, and to fit
+this initialization into a framework suitable for the overall computation.
+
+@<Declare the procedure called |solve_choices|@>=
+@<Declare subroutines needed by |solve_choices|@>
+void mp_solve_choices (MP mp,pointer p, pointer q, halfword n) {
+ int k; /* current knot number */
+ pointer r,s,t; /* registers for list traversal */
+ @<Other local variables for |solve_choices|@>;
+ k=0; s=p; r=0;
+ while (1) {
+ t=link(s);
+ if ( k==0 ) {
+ @<Get the linear equations started; or |return|
+ with the control points in place, if linear equations
+ needn't be solved@>
+ } else {
+ switch (left_type(s)) {
+ case mp_end_cycle: case mp_open:
+ @<Set up equation to match mock curvatures
+ at $z_k$; then |goto found| with $\theta_n$
+ adjusted to equal $\theta_0$, if a cycle has ended@>;
+ break;
+ case mp_curl:
+ @<Set up equation for a curl at $\theta_n$
+ and |goto found|@>;
+ break;
+ case mp_given:
+ @<Calculate the given value of $\theta_n$
+ and |goto found|@>;
+ break;
+ } /* there are no other cases */
+ }
+ r=s; s=t; incr(k);
+ }
+FOUND:
+ @<Finish choosing angles and assigning control points@>;
+}
+
+@ On the first time through the loop, we have |k=0| and |r| is not yet
+defined. The first linear equation, if any, will have $A_0=B_0=0$.
+
+@<Get the linear equations started...@>=
+switch (right_type(s)) {
+case mp_given:
+ if ( left_type(t)==mp_given ) {
+ @<Reduce to simple case of two givens and |return|@>
+ } else {
+ @<Set up the equation for a given value of $\theta_0$@>;
+ }
+ break;
+case mp_curl:
+ if ( left_type(t)==mp_curl ) {
+ @<Reduce to simple case of straight line and |return|@>
+ } else {
+ @<Set up the equation for a curl at $\theta_0$@>;
+ }
+ break;
+case mp_open:
+ mp->uu[0]=0; mp->vv[0]=0; mp->ww[0]=fraction_one;
+ /* this begins a cycle */
+ break;
+} /* there are no other cases */
+
+@ The general equation that specifies equality of mock curvature at $z_k$ is
+$$A_k\theta_{k-1}+(B_k+C_k)\theta_k+D_k\theta\k=-B_k\psi_k-D_k\psi\k,$$
+as derived above. We want to combine this with the already-derived equation
+$\theta_{k-1}+u_{k-1}\theta_k=v_{k-1}+w_{k-1}\theta_0$ in order to obtain
+a new equation
+$\theta_k+u_k\theta\k=v_k+w_k\theta_0$. This can be done by dividing the
+equation
+$$(B_k-u_{k-1}A_k+C_k)\theta_k+D_k\theta\k=-B_k\psi_k-D_k\psi\k-A_kv_{k-1}
+ -A_kw_{k-1}\theta_0$$
+by $B_k-u_{k-1}A_k+C_k$. The trick is to do this carefully with
+fixed-point arithmetic, avoiding the chance of overflow while retaining
+suitable precision.
+
+The calculations will be performed in several registers that
+provide temporary storage for intermediate quantities.
+
+@<Other local variables for |solve_choices|@>=
+fraction aa,bb,cc,ff,acc; /* temporary registers */
+scaled dd,ee; /* likewise, but |scaled| */
+scaled lt,rt; /* tension values */
+
+@ @<Set up equation to match mock curvatures...@>=
+{ @<Calculate the values $\\{aa}=A_k/B_k$, $\\{bb}=D_k/C_k$,
+ $\\{dd}=(3-\alpha_{k-1})d_{k,k+1}$, $\\{ee}=(3-\beta\k)d_{k-1,k}$,
+ and $\\{cc}=(B_k-u_{k-1}A_k)/B_k$@>;
+ @<Calculate the ratio $\\{ff}=C_k/(C_k+B_k-u_{k-1}A_k)$@>;
+ mp->uu[k]=mp_take_fraction(mp, ff,bb);
+ @<Calculate the values of $v_k$ and $w_k$@>;
+ if ( left_type(s)==mp_end_cycle ) {
+ @<Adjust $\theta_n$ to equal $\theta_0$ and |goto found|@>;
+ }
+}
+
+@ Since tension values are never less than 3/4, the values |aa| and
+|bb| computed here are never more than 4/5.
+
+@<Calculate the values $\\{aa}=...@>=
+if ( abs(right_tension(r))==unity) {
+ aa=fraction_half; dd=2*mp->delta[k];
+} else {
+ aa=mp_make_fraction(mp, unity,3*abs(right_tension(r))-unity);
+ dd=mp_take_fraction(mp, mp->delta[k],
+ fraction_three-mp_make_fraction(mp, unity,abs(right_tension(r))));
+}
+if ( abs(left_tension(t))==unity ){
+ bb=fraction_half; ee=2*mp->delta[k-1];
+} else {
+ bb=mp_make_fraction(mp, unity,3*abs(left_tension(t))-unity);
+ ee=mp_take_fraction(mp, mp->delta[k-1],
+ fraction_three-mp_make_fraction(mp, unity,abs(left_tension(t))));
+}
+cc=fraction_one-mp_take_fraction(mp, mp->uu[k-1],aa)
+
+@ The ratio to be calculated in this step can be written in the form
+$$\beta_k^2\cdot\\{ee}\over\beta_k^2\cdot\\{ee}+\alpha_k^2\cdot
+ \\{cc}\cdot\\{dd},$$
+because of the quantities just calculated. The values of |dd| and |ee|
+will not be needed after this step has been performed.
+
+@<Calculate the ratio $\\{ff}=C_k/(C_k+B_k-u_{k-1}A_k)$@>=
+dd=mp_take_fraction(mp, dd,cc); lt=abs(left_tension(s)); rt=abs(right_tension(s));
+if ( lt!=rt ) { /* $\beta_k^{-1}\ne\alpha_k^{-1}$ */
+ if ( lt<rt ) {
+ ff=mp_make_fraction(mp, lt,rt);
+ ff=mp_take_fraction(mp, ff,ff); /* $\alpha_k^2/\beta_k^2$ */
+ dd=mp_take_fraction(mp, dd,ff);
+ } else {
+ ff=mp_make_fraction(mp, rt,lt);
+ ff=mp_take_fraction(mp, ff,ff); /* $\beta_k^2/\alpha_k^2$ */
+ ee=mp_take_fraction(mp, ee,ff);
+ }
+}
+ff=mp_make_fraction(mp, ee,ee+dd)
+
+@ The value of $u_{k-1}$ will be |<=1| except when $k=1$ and the previous
+equation was specified by a curl. In that case we must use a special
+method of computation to prevent overflow.
+
+Fortunately, the calculations turn out to be even simpler in this ``hard''
+case. The curl equation makes $w_0=0$ and $v_0=-u_0\psi_1$, hence
+$-B_1\psi_1-A_1v_0=-(B_1-u_0A_1)\psi_1=-\\{cc}\cdot B_1\psi_1$.
+
+@<Calculate the values of $v_k$ and $w_k$@>=
+acc=-mp_take_fraction(mp, mp->psi[k+1],mp->uu[k]);
+if ( right_type(r)==mp_curl ) {
+ mp->ww[k]=0;
+ mp->vv[k]=acc-mp_take_fraction(mp, mp->psi[1],fraction_one-ff);
+} else {
+ ff=mp_make_fraction(mp, fraction_one-ff,cc); /* this is
+ $B_k/(C_k+B_k-u_{k-1}A_k)<5$ */
+ acc=acc-mp_take_fraction(mp, mp->psi[k],ff);
+ ff=mp_take_fraction(mp, ff,aa); /* this is $A_k/(C_k+B_k-u_{k-1}A_k)$ */
+ mp->vv[k]=acc-mp_take_fraction(mp, mp->vv[k-1],ff);
+ if ( mp->ww[k-1]==0 ) mp->ww[k]=0;
+ else mp->ww[k]=-mp_take_fraction(mp, mp->ww[k-1],ff);
+}
+
+@ When a complete cycle has been traversed, we have $\theta_k+u_k\theta\k=
+v_k+w_k\theta_0$, for |1<=k<=n|. We would like to determine the value of
+$\theta_n$ and reduce the system to the form $\theta_k+u_k\theta\k=v_k$
+for |0<=k<n|, so that the cyclic case can be finished up just as if there
+were no cycle.
+
+The idea in the following code is to observe that
+$$\eqalign{\theta_n&=v_n+w_n\theta_0-u_n\theta_1=\cdots\cr
+&=v_n+w_n\theta_0-u_n\bigl(v_1+w_1\theta_0-u_1(v_2+\cdots
+ -u_{n-2}(v_{n-1}+w_{n-1}\theta_0-u_{n-1}\theta_0))\bigr),\cr}$$
+so we can solve for $\theta_n=\theta_0$.
+
+@<Adjust $\theta_n$ to equal $\theta_0$ and |goto found|@>=
+{
+aa=0; bb=fraction_one; /* we have |k=n| */
+do { decr(k);
+if ( k==0 ) k=n;
+ aa=mp->vv[k]-mp_take_fraction(mp, aa,mp->uu[k]);
+ bb=mp->ww[k]-mp_take_fraction(mp, bb,mp->uu[k]);
+} while (k!=n); /* now $\theta_n=\\{aa}+\\{bb}\cdot\theta_n$ */
+aa=mp_make_fraction(mp, aa,fraction_one-bb);
+mp->theta[n]=aa; mp->vv[0]=aa;
+for (k=1;k<=n-1;k++) {
+ mp->vv[k]=mp->vv[k]+mp_take_fraction(mp, aa,mp->ww[k]);
+}
+goto FOUND;
+}
+
+@ @d reduce_angle(A) if ( abs((A))>one_eighty_deg ) {
+ if ( (A)>0 ) (A)=(A)-three_sixty_deg; else (A)=(A)+three_sixty_deg; }
+
+@<Calculate the given value of $\theta_n$...@>=
+{
+ mp->theta[n]=left_given(s)-mp_n_arg(mp, mp->delta_x[n-1],mp->delta_y[n-1]);
+ reduce_angle(mp->theta[n]);
+ goto FOUND;
+}
+
+@ @<Set up the equation for a given value of $\theta_0$@>=
+{
+ mp->vv[0]=right_given(s)-mp_n_arg(mp, mp->delta_x[0],mp->delta_y[0]);
+ reduce_angle(mp->vv[0]);
+ mp->uu[0]=0; mp->ww[0]=0;
+}
+
+@ @<Set up the equation for a curl at $\theta_0$@>=
+{ cc=right_curl(s); lt=abs(left_tension(t)); rt=abs(right_tension(s));
+ if ( (rt==unity)&&(lt==unity) )
+ mp->uu[0]=mp_make_fraction(mp, cc+cc+unity,cc+two);
+ else
+ mp->uu[0]=mp_curl_ratio(mp, cc,rt,lt);
+ mp->vv[0]=-mp_take_fraction(mp, mp->psi[1],mp->uu[0]); mp->ww[0]=0;
+}
+
+@ @<Set up equation for a curl at $\theta_n$...@>=
+{ cc=left_curl(s); lt=abs(left_tension(s)); rt=abs(right_tension(r));
+ if ( (rt==unity)&&(lt==unity) )
+ ff=mp_make_fraction(mp, cc+cc+unity,cc+two);
+ else
+ ff=mp_curl_ratio(mp, cc,lt,rt);
+ mp->theta[n]=-mp_make_fraction(mp, mp_take_fraction(mp, mp->vv[n-1],ff),
+ fraction_one-mp_take_fraction(mp, ff,mp->uu[n-1]));
+ goto FOUND;
+}
+
+@ The |curl_ratio| subroutine has three arguments, which our previous notation
+encourages us to call $\gamma$, $\alpha^{-1}$, and $\beta^{-1}$. It is
+a somewhat tedious program to calculate
+$${(3-\alpha)\alpha^2\gamma+\beta^3\over
+ \alpha^3\gamma+(3-\beta)\beta^2},$$
+with the result reduced to 4 if it exceeds 4. (This reduction of curl
+is necessary only if the curl and tension are both large.)
+The values of $\alpha$ and $\beta$ will be at most~4/3.
+
+@<Declare subroutines needed by |solve_choices|@>=
+fraction mp_curl_ratio (MP mp,scaled gamma, scaled a_tension,
+ scaled b_tension) {
+ fraction alpha,beta,num,denom,ff; /* registers */
+ alpha=mp_make_fraction(mp, unity,a_tension);
+ beta=mp_make_fraction(mp, unity,b_tension);
+ if ( alpha<=beta ) {
+ ff=mp_make_fraction(mp, alpha,beta); ff=mp_take_fraction(mp, ff,ff);
+ gamma=mp_take_fraction(mp, gamma,ff);
+ beta=beta / 010000; /* convert |fraction| to |scaled| */
+ denom=mp_take_fraction(mp, gamma,alpha)+three-beta;
+ num=mp_take_fraction(mp, gamma,fraction_three-alpha)+beta;
+ } else {
+ ff=mp_make_fraction(mp, beta,alpha); ff=mp_take_fraction(mp, ff,ff);
+ beta=mp_take_fraction(mp, beta,ff) / 010000; /* convert |fraction| to |scaled| */
+ denom=mp_take_fraction(mp, gamma,alpha)+(ff / 1365)-beta;
+ /* $1365\approx 2^{12}/3$ */
+ num=mp_take_fraction(mp, gamma,fraction_three-alpha)+beta;
+ }
+ if ( num>=denom+denom+denom+denom ) return fraction_four;
+ else return mp_make_fraction(mp, num,denom);
+}
+
+@ We're in the home stretch now.
+
+@<Finish choosing angles and assigning control points@>=
+for (k=n-1;k>=0;k--) {
+ mp->theta[k]=mp->vv[k]-mp_take_fraction(mp,mp->theta[k+1],mp->uu[k]);
+}
+s=p; k=0;
+do {
+ t=link(s);
+ mp_n_sin_cos(mp, mp->theta[k]); mp->st=mp->n_sin; mp->ct=mp->n_cos;
+ mp_n_sin_cos(mp, -mp->psi[k+1]-mp->theta[k+1]); mp->sf=mp->n_sin; mp->cf=mp->n_cos;
+ mp_set_controls(mp, s,t,k);
+ incr(k); s=t;
+} while (k!=n)
+
+@ The |set_controls| routine actually puts the control points into
+a pair of consecutive nodes |p| and~|q|. Global variables are used to
+record the values of $\sin\theta$, $\cos\theta$, $\sin\phi$, and
+$\cos\phi$ needed in this calculation.
+
+@<Glob...@>=
+fraction st;
+fraction ct;
+fraction sf;
+fraction cf; /* sines and cosines */
+
+@ @<Declare subroutines needed by |solve_choices|@>=
+void mp_set_controls (MP mp,pointer p, pointer q, integer k) {
+ fraction rr,ss; /* velocities, divided by thrice the tension */
+ scaled lt,rt; /* tensions */
+ fraction sine; /* $\sin(\theta+\phi)$ */
+ lt=abs(left_tension(q)); rt=abs(right_tension(p));
+ rr=mp_velocity(mp, mp->st,mp->ct,mp->sf,mp->cf,rt);
+ ss=mp_velocity(mp, mp->sf,mp->cf,mp->st,mp->ct,lt);
+ if ( (right_tension(p)<0)||(left_tension(q)<0) ) {
+ @<Decrease the velocities,
+ if necessary, to stay inside the bounding triangle@>;
+ }
+ right_x(p)=x_coord(p)+mp_take_fraction(mp,
+ mp_take_fraction(mp, mp->delta_x[k],mp->ct)-
+ mp_take_fraction(mp, mp->delta_y[k],mp->st),rr);
+ right_y(p)=y_coord(p)+mp_take_fraction(mp,
+ mp_take_fraction(mp, mp->delta_y[k],mp->ct)+
+ mp_take_fraction(mp, mp->delta_x[k],mp->st),rr);
+ left_x(q)=x_coord(q)-mp_take_fraction(mp,
+ mp_take_fraction(mp, mp->delta_x[k],mp->cf)+
+ mp_take_fraction(mp, mp->delta_y[k],mp->sf),ss);
+ left_y(q)=y_coord(q)-mp_take_fraction(mp,
+ mp_take_fraction(mp, mp->delta_y[k],mp->cf)-
+ mp_take_fraction(mp, mp->delta_x[k],mp->sf),ss);
+ right_type(p)=mp_explicit; left_type(q)=mp_explicit;
+}
+
+@ The boundedness conditions $\\{rr}\L\sin\phi\,/\sin(\theta+\phi)$ and
+$\\{ss}\L\sin\theta\,/\sin(\theta+\phi)$ are to be enforced if $\sin\theta$,
+$\sin\phi$, and $\sin(\theta+\phi)$ all have the same sign. Otherwise
+there is no ``bounding triangle.''
+
+@<Decrease the velocities, if necessary...@>=
+if (((mp->st>=0)&&(mp->sf>=0))||((mp->st<=0)&&(mp->sf<=0)) ) {
+ sine=mp_take_fraction(mp, abs(mp->st),mp->cf)+
+ mp_take_fraction(mp, abs(mp->sf),mp->ct);
+ if ( sine>0 ) {
+ sine=mp_take_fraction(mp, sine,fraction_one+unity); /* safety factor */
+ if ( right_tension(p)<0 )
+ if ( mp_ab_vs_cd(mp, abs(mp->sf),fraction_one,rr,sine)<0 )
+ rr=mp_make_fraction(mp, abs(mp->sf),sine);
+ if ( left_tension(q)<0 )
+ if ( mp_ab_vs_cd(mp, abs(mp->st),fraction_one,ss,sine)<0 )
+ ss=mp_make_fraction(mp, abs(mp->st),sine);
+ }
+}
+
+@ Only the simple cases remain to be handled.
+
+@<Reduce to simple case of two givens and |return|@>=
+{
+ aa=mp_n_arg(mp, mp->delta_x[0],mp->delta_y[0]);
+ mp_n_sin_cos(mp, right_given(p)-aa); mp->ct=mp->n_cos; mp->st=mp->n_sin;
+ mp_n_sin_cos(mp, left_given(q)-aa); mp->cf=mp->n_cos; mp->sf=-mp->n_sin;
+ mp_set_controls(mp, p,q,0); return;
+}
+
+@ @<Reduce to simple case of straight line and |return|@>=
+{
+ right_type(p)=mp_explicit; left_type(q)=mp_explicit;
+ lt=abs(left_tension(q)); rt=abs(right_tension(p));
+ if ( rt==unity ) {
+ if ( mp->delta_x[0]>=0 ) right_x(p)=x_coord(p)+((mp->delta_x[0]+1) / 3);
+ else right_x(p)=x_coord(p)+((mp->delta_x[0]-1) / 3);
+ if ( mp->delta_y[0]>=0 ) right_y(p)=y_coord(p)+((mp->delta_y[0]+1) / 3);
+ else right_y(p)=y_coord(p)+((mp->delta_y[0]-1) / 3);
+ } else {
+ ff=mp_make_fraction(mp, unity,3*rt); /* $\alpha/3$ */
+ right_x(p)=x_coord(p)+mp_take_fraction(mp, mp->delta_x[0],ff);
+ right_y(p)=y_coord(p)+mp_take_fraction(mp, mp->delta_y[0],ff);
+ }
+ if ( lt==unity ) {
+ if ( mp->delta_x[0]>=0 ) left_x(q)=x_coord(q)-((mp->delta_x[0]+1) / 3);
+ else left_x(q)=x_coord(q)-((mp->delta_x[0]-1) / 3);
+ if ( mp->delta_y[0]>=0 ) left_y(q)=y_coord(q)-((mp->delta_y[0]+1) / 3);
+ else left_y(q)=y_coord(q)-((mp->delta_y[0]-1) / 3);
+ } else {
+ ff=mp_make_fraction(mp, unity,3*lt); /* $\beta/3$ */
+ left_x(q)=x_coord(q)-mp_take_fraction(mp, mp->delta_x[0],ff);
+ left_y(q)=y_coord(q)-mp_take_fraction(mp, mp->delta_y[0],ff);
+ }
+ return;
+}
+
+@* \[19] Measuring paths.
+\MP's \&{llcorner}, \&{lrcorner}, \&{ulcorner}, and \&{urcorner} operators
+allow the user to measure the bounding box of anything that can go into a
+picture. It's easy to get rough bounds on the $x$ and $y$ extent of a path
+by just finding the bounding box of the knots and the control points. We
+need a more accurate version of the bounding box, but we can still use the
+easy estimate to save time by focusing on the interesting parts of the path.
+
+@ Computing an accurate bounding box involves a theme that will come up again
+and again. Given a Bernshte{\u\i}n polynomial
+@^Bernshte{\u\i}n, Serge{\u\i} Natanovich@>
+$$B(z_0,z_1,\ldots,z_n;t)=\sum_k{n\choose k}t^k(1-t)^{n-k}z_k,$$
+we can conveniently bisect its range as follows:
+
+\smallskip
+\textindent{1)} Let $z_k^{(0)}=z_k$, for |0<=k<=n|.
+
+\smallskip
+\textindent{2)} Let $z_k^{(j+1)}={1\over2}(z_k^{(j)}+z\k^{(j)})$, for
+|0<=k<n-j|, for |0<=j<n|.
+
+\smallskip\noindent
+Then
+$$B(z_0,z_1,\ldots,z_n;t)=B(z_0^{(0)},z_0^{(1)},\ldots,z_0^{(n)};2t)
+ =B(z_0^{(n)},z_1^{(n-1)},\ldots,z_n^{(0)};2t-1).$$
+This formula gives us the coefficients of polynomials to use over the ranges
+$0\L t\L{1\over2}$ and ${1\over2}\L t\L1$.
+
+@ Now here's a subroutine that's handy for all sorts of path computations:
+Given a quadratic polynomial $B(a,b,c;t)$, the |crossing_point| function
+returns the unique |fraction| value |t| between 0 and~1 at which
+$B(a,b,c;t)$ changes from positive to negative, or returns
+|t=fraction_one+1| if no such value exists. If |a<0| (so that $B(a,b,c;t)$
+is already negative at |t=0|), |crossing_point| returns the value zero.
+
+@d no_crossing { return (fraction_one+1); }
+@d one_crossing { return fraction_one; }
+@d zero_crossing { return 0; }
+@d mp_crossing_point(M,A,B,C) mp_do_crossing_point(A,B,C)
+
+@c fraction mp_do_crossing_point (integer a, integer b, integer c) {
+ integer d; /* recursive counter */
+ integer x,xx,x0,x1,x2; /* temporary registers for bisection */
+ if ( a<0 ) zero_crossing;
+ if ( c>=0 ) {
+ if ( b>=0 ) {
+ if ( c>0 ) { no_crossing; }
+ else if ( (a==0)&&(b==0) ) { no_crossing;}
+ else { one_crossing; }
+ }
+ if ( a==0 ) zero_crossing;
+ } else if ( a==0 ) {
+ if ( b<=0 ) zero_crossing;
+ }
+ @<Use bisection to find the crossing point, if one exists@>;
+}
+
+@ The general bisection method is quite simple when $n=2$, hence
+|crossing_point| does not take much time. At each stage in the
+recursion we have a subinterval defined by |l| and~|j| such that
+$B(a,b,c;2^{-l}(j+t))=B(x_0,x_1,x_2;t)$, and we want to ``zero in'' on
+the subinterval where $x_0\G0$ and $\min(x_1,x_2)<0$.
+
+It is convenient for purposes of calculation to combine the values
+of |l| and~|j| in a single variable $d=2^l+j$, because the operation
+of bisection then corresponds simply to doubling $d$ and possibly
+adding~1. Furthermore it proves to be convenient to modify
+our previous conventions for bisection slightly, maintaining the
+variables $X_0=2^lx_0$, $X_1=2^l(x_0-x_1)$, and $X_2=2^l(x_1-x_2)$.
+With these variables the conditions $x_0\ge0$ and $\min(x_1,x_2)<0$ are
+equivalent to $\max(X_1,X_1+X_2)>X_0\ge0$.
+
+The following code maintains the invariant relations
+$0\L|x0|<\max(|x1|,|x1|+|x2|)$,
+$\vert|x1|\vert<2^{30}$, $\vert|x2|\vert<2^{30}$;
+it has been constructed in such a way that no arithmetic overflow
+will occur if the inputs satisfy
+$a<2^{30}$, $\vert a-b\vert<2^{30}$, and $\vert b-c\vert<2^{30}$.
+
+@<Use bisection to find the crossing point...@>=
+d=1; x0=a; x1=a-b; x2=b-c;
+do {
+ x=half(x1+x2);
+ if ( x1-x0>x0 ) {
+ x2=x; x0+=x0; d+=d;
+ } else {
+ xx=x1+x-x0;
+ if ( xx>x0 ) {
+ x2=x; x0+=x0; d+=d;
+ } else {
+ x0=x0-xx;
+ if ( x<=x0 ) { if ( x+x2<=x0 ) no_crossing; }
+ x1=x; d=d+d+1;
+ }
+ }
+} while (d<fraction_one);
+return (d-fraction_one)
+
+@ Here is a routine that computes the $x$ or $y$ coordinate of the point on
+a cubic corresponding to the |fraction| value~|t|.
+
+It is convenient to define a \.{WEB} macro |t_of_the_way| such that
+|t_of_the_way(a,b)| expands to |a-(a-b)*t|, i.e., to |t[a,b]|.
+
+@d t_of_the_way(A,B) ((A)-mp_take_fraction(mp,((A)-(B)),t))
+
+@c scaled mp_eval_cubic (MP mp,pointer p, pointer q, fraction t) {
+ scaled x1,x2,x3; /* intermediate values */
+ x1=t_of_the_way(knot_coord(p),right_coord(p));
+ x2=t_of_the_way(right_coord(p),left_coord(q));
+ x3=t_of_the_way(left_coord(q),knot_coord(q));
+ x1=t_of_the_way(x1,x2);
+ x2=t_of_the_way(x2,x3);
+ return t_of_the_way(x1,x2);
+}
+
+@ The actual bounding box information is stored in global variables.
+Since it is convenient to address the $x$ and $y$ information
+separately, we define arrays indexed by |x_code..y_code| and use
+macros to give them more convenient names.
+
+@<Types...@>=
+enum mp_bb_code {
+ mp_x_code=0, /* index for |minx| and |maxx| */
+ mp_y_code /* index for |miny| and |maxy| */
+} ;
+
+@
+@d minx mp->bbmin[mp_x_code]
+@d maxx mp->bbmax[mp_x_code]
+@d miny mp->bbmin[mp_y_code]
+@d maxy mp->bbmax[mp_y_code]
+
+@<Glob...@>=
+scaled bbmin[mp_y_code+1];
+scaled bbmax[mp_y_code+1];
+/* the result of procedures that compute bounding box information */
+
+@ Now we're ready for the key part of the bounding box computation.
+The |bound_cubic| procedure updates |bbmin[c]| and |bbmax[c]| based on
+$$B(\hbox{|knot_coord(p)|}, \hbox{|right_coord(p)|},
+ \hbox{|left_coord(q)|}, \hbox{|knot_coord(q)|};t)
+$$
+for $0<t\le1$. In other words, the procedure adjusts the bounds to
+accommodate |knot_coord(q)| and any extremes over the range $0<t<1$.
+The |c| parameter is |x_code| or |y_code|.
+
+@c void mp_bound_cubic (MP mp,pointer p, pointer q, small_number c) {
+ boolean wavy; /* whether we need to look for extremes */
+ scaled del1,del2,del3,del,dmax; /* proportional to the control
+ points of a quadratic derived from a cubic */
+ fraction t,tt; /* where a quadratic crosses zero */
+ scaled x; /* a value that |bbmin[c]| and |bbmax[c]| must accommodate */
+ x=knot_coord(q);
+ @<Adjust |bbmin[c]| and |bbmax[c]| to accommodate |x|@>;
+ @<Check the control points against the bounding box and set |wavy:=true|
+ if any of them lie outside@>;
+ if ( wavy ) {
+ del1=right_coord(p)-knot_coord(p);
+ del2=left_coord(q)-right_coord(p);
+ del3=knot_coord(q)-left_coord(q);
+ @<Scale up |del1|, |del2|, and |del3| for greater accuracy;
+ also set |del| to the first nonzero element of |(del1,del2,del3)|@>;
+ if ( del<0 ) {
+ negate(del1); negate(del2); negate(del3);
+ };
+ t=mp_crossing_point(mp, del1,del2,del3);
+ if ( t<fraction_one ) {
+ @<Test the extremes of the cubic against the bounding box@>;
+ }
+ }
+}
+
+@ @<Adjust |bbmin[c]| and |bbmax[c]| to accommodate |x|@>=
+if ( x<mp->bbmin[c] ) mp->bbmin[c]=x;
+if ( x>mp->bbmax[c] ) mp->bbmax[c]=x
+
+@ @<Check the control points against the bounding box and set...@>=
+wavy=true;
+if ( mp->bbmin[c]<=right_coord(p) )
+ if ( right_coord(p)<=mp->bbmax[c] )
+ if ( mp->bbmin[c]<=left_coord(q) )
+ if ( left_coord(q)<=mp->bbmax[c] )
+ wavy=false
+
+@ If |del1=del2=del3=0|, it's impossible to obey the title of this
+section. We just set |del=0| in that case.
+
+@<Scale up |del1|, |del2|, and |del3| for greater accuracy...@>=
+if ( del1!=0 ) del=del1;
+else if ( del2!=0 ) del=del2;
+else del=del3;
+if ( del!=0 ) {
+ dmax=abs(del1);
+ if ( abs(del2)>dmax ) dmax=abs(del2);
+ if ( abs(del3)>dmax ) dmax=abs(del3);
+ while ( dmax<fraction_half ) {
+ dmax+=dmax; del1+=del1; del2+=del2; del3+=del3;
+ }
+}
+
+@ Since |crossing_point| has tried to choose |t| so that
+$B(|del1|,|del2|,|del3|;\tau)$ crosses zero at $\tau=|t|$ with negative
+slope, the value of |del2| computed below should not be positive.
+But rounding error could make it slightly positive in which case we
+must cut it to zero to avoid confusion.
+
+@<Test the extremes of the cubic against the bounding box@>=
+{
+ x=mp_eval_cubic(mp, p,q,t);
+ @<Adjust |bbmin[c]| and |bbmax[c]| to accommodate |x|@>;
+ del2=t_of_the_way(del2,del3);
+ /* now |0,del2,del3| represent the derivative on the remaining interval */
+ if ( del2>0 ) del2=0;
+ tt=mp_crossing_point(mp, 0,-del2,-del3);
+ if ( tt<fraction_one ) {
+ @<Test the second extreme against the bounding box@>;
+ }
+}
+
+@ @<Test the second extreme against the bounding box@>=
+{
+ x=mp_eval_cubic(mp, p,q,t_of_the_way(tt,fraction_one));
+ @<Adjust |bbmin[c]| and |bbmax[c]| to accommodate |x|@>;
+}
+
+@ Finding the bounding box of a path is basically a matter of applying
+|bound_cubic| twice for each pair of adjacent knots.
+
+@c void mp_path_bbox (MP mp,pointer h) {
+ pointer p,q; /* a pair of adjacent knots */
+ minx=x_coord(h); miny=y_coord(h);
+ maxx=minx; maxy=miny;
+ p=h;
+ do {
+ if ( right_type(p)==mp_endpoint ) return;
+ q=link(p);
+ mp_bound_cubic(mp, x_loc(p),x_loc(q),mp_x_code);
+ mp_bound_cubic(mp, y_loc(p),y_loc(q),mp_y_code);
+ p=q;
+ } while (p!=h);
+}
+
+@ Another important way to measure a path is to find its arc length. This
+is best done by using the general bisection algorithm to subdivide the path
+until obtaining ``well behaved'' subpaths whose arc lengths can be approximated
+by simple means.
+
+Since the arc length is the integral with respect to time of the magnitude of
+the velocity, it is natural to use Simpson's rule for the approximation.
+@^Simpson's rule@>
+If $\dot B(t)$ is the spline velocity, Simpson's rule gives
+$$ \vb\dot B(0)\vb + 4\vb\dot B({1\over2})\vb + \vb\dot B(1)\vb \over 6 $$
+for the arc length of a path of length~1. For a cubic spline
+$B(z_0,z_1,z_2,z_3;t)$, the time derivative $\dot B(t)$ is
+$3B(dz_0,dz_1,dz_2;t)$, where $dz_i=z_{i+1}-z_i$. Hence the arc length
+approximation is
+$$ {\vb dz_0\vb \over 2} + 2\vb dz_{02}\vb + {\vb dz_2\vb \over 2}, $$
+where
+$$ dz_{02}={1\over2}\left({dz_0+dz_1\over 2}+{dz_1+dz_2\over 2}\right)$$
+is the result of the bisection algorithm.
+
+@ The remaining problem is how to decide when a subpath is ``well behaved.''
+This could be done via the theoretical error bound for Simpson's rule,
+@^Simpson's rule@>
+but this is impractical because it requires an estimate of the fourth
+derivative of the quantity being integrated. It is much easier to just perform
+a bisection step and see how much the arc length estimate changes. Since the
+error for Simpson's rule is proportional to the fourth power of the sample
+spacing, the remaining error is typically about $1\over16$ of the amount of
+the change. We say ``typically'' because the error has a pseudo-random behavior
+that could cause the two estimates to agree when each contain large errors.
+
+To protect against disasters such as undetected cusps, the bisection process
+should always continue until all the $dz_i$ vectors belong to a single
+$90^\circ$ sector. This ensures that no point on the spline can have velocity
+less than 70\% of the minimum of $\vb dz_0\vb$, $\vb dz_1\vb$ and $\vb dz_2\vb$.
+If such a spline happens to produce an erroneous arc length estimate that
+is little changed by bisection, the amount of the error is likely to be fairly
+small. We will try to arrange things so that freak accidents of this type do
+not destroy the inverse relationship between the \&{arclength} and
+\&{arctime} operations.
+@:arclength_}{\&{arclength} primitive@>
+@:arctime_}{\&{arctime} primitive@>
+
+@ The \&{arclength} and \&{arctime} operations are both based on a recursive
+@^recursion@>
+function that finds the arc length of a cubic spline given $dz_0$, $dz_1$,
+$dz_2$. This |arc_test| routine also takes an arc length goal |a_goal| and
+returns the time when the arc length reaches |a_goal| if there is such a time.
+Thus the return value is either an arc length less than |a_goal| or, if the
+arc length would be at least |a_goal|, it returns a time value decreased by
+|two|. This allows the caller to use the sign of the result to distinguish
+between arc lengths and time values. On certain types of overflow, it is
+possible for |a_goal| and the result of |arc_test| both to be |el_gordo|.
+Otherwise, the result is always less than |a_goal|.
+
+Rather than halving the control point coordinates on each recursive call to
+|arc_test|, it is better to keep them proportional to velocity on the original
+curve and halve the results instead. This means that recursive calls can
+potentially use larger error tolerances in their arc length estimates. How
+much larger depends on to what extent the errors behave as though they are
+independent of each other. To save computing time, we use optimistic assumptions
+and increase the tolerance by a factor of about $\sqrt2$ for each recursive
+call.
+
+In addition to the tolerance parameter, |arc_test| should also have parameters
+for ${1\over3}\vb\dot B(0)\vb$, ${2\over3}\vb\dot B({1\over2})\vb$, and
+${1\over3}\vb\dot B(1)\vb$. These quantities are relatively expensive to compute
+and they are needed in different instances of |arc_test|.
+
+@c @<Declare subroutines needed by |arc_test|@>
+scaled mp_arc_test (MP mp, scaled dx0, scaled dy0, scaled dx1, scaled dy1,
+ scaled dx2, scaled dy2, scaled v0, scaled v02,
+ scaled v2, scaled a_goal, scaled tol) {
+ boolean simple; /* are the control points confined to a $90^\circ$ sector? */
+ scaled dx01, dy01, dx12, dy12, dx02, dy02; /* bisection results */
+ scaled v002, v022;
+ /* twice the velocity magnitudes at $t={1\over4}$ and $t={3\over4}$ */
+ scaled arc; /* best arc length estimate before recursion */
+ @<Other local variables in |arc_test|@>;
+ @<Bisect the B\'ezier quadratic given by |dx0|, |dy0|, |dx1|, |dy1|,
+ |dx2|, |dy2|@>;
+ @<Initialize |v002|, |v022|, and the arc length estimate |arc|; if it overflows
+ set |arc_test| and |return|@>;
+ @<Test if the control points are confined to one quadrant or rotating them
+ $45^\circ$ would put them in one quadrant. Then set |simple| appropriately@>;
+ if ( simple && (abs(arc-v02-halfp(v0+v2)) <= tol) ) {
+ if ( arc < a_goal ) {
+ return arc;
+ } else {
+ @<Estimate when the arc length reaches |a_goal| and set |arc_test| to
+ that time minus |two|@>;
+ }
+ } else {
+ @<Use one or two recursive calls to compute the |arc_test| function@>;
+ }
+}
+
+@ The |tol| value should by multiplied by $\sqrt 2$ before making recursive
+calls, but $1.5$ is an adequate approximation. It is best to avoid using
+|make_fraction| in this inner loop.
+@^inner loop@>
+
+@<Use one or two recursive calls to compute the |arc_test| function@>=
+{
+ @<Set |a_new| and |a_aux| so their sum is |2*a_goal| and |a_new| is as
+ large as possible@>;
+ tol = tol + halfp(tol);
+ a = mp_arc_test(mp, dx0,dy0, dx01,dy01, dx02,dy02, v0, v002,
+ halfp(v02), a_new, tol);
+ if ( a<0 ) {
+ return (-halfp(two-a));
+ } else {
+ @<Update |a_new| to reduce |a_new+a_aux| by |a|@>;
+ b = mp_arc_test(mp, dx02,dy02, dx12,dy12, dx2,dy2,
+ halfp(v02), v022, v2, a_new, tol);
+ if ( b<0 )
+ return (-halfp(-b) - half_unit);
+ else
+ return (a + half(b-a));
+ }
+}
+
+@ @<Other local variables in |arc_test|@>=
+scaled a,b; /* results of recursive calls */
+scaled a_new,a_aux; /* the sum of these gives the |a_goal| */
+
+@ @<Set |a_new| and |a_aux| so their sum is |2*a_goal| and |a_new| is...@>=
+a_aux = el_gordo - a_goal;
+if ( a_goal > a_aux ) {
+ a_aux = a_goal - a_aux;
+ a_new = el_gordo;
+} else {
+ a_new = a_goal + a_goal;
+ a_aux = 0;
+}
+
+@ There is no need to maintain |a_aux| at this point so we use it as a temporary
+to force the additions and subtractions to be done in an order that avoids
+overflow.
+
+@<Update |a_new| to reduce |a_new+a_aux| by |a|@>=
+if ( a > a_aux ) {
+ a_aux = a_aux - a;
+ a_new = a_new + a_aux;
+}
+
+@ This code assumes all {\it dx} and {\it dy} variables have magnitude less than
+|fraction_four|. To simplify the rest of the |arc_test| routine, we strengthen
+this assumption by requiring the norm of each $({\it dx},{\it dy})$ pair to obey
+this bound. Note that recursive calls will maintain this invariant.
+
+@<Bisect the B\'ezier quadratic given by |dx0|, |dy0|, |dx1|, |dy1|,...@>=
+dx01 = half(dx0 + dx1);
+dx12 = half(dx1 + dx2);
+dx02 = half(dx01 + dx12);
+dy01 = half(dy0 + dy1);
+dy12 = half(dy1 + dy2);
+dy02 = half(dy01 + dy12)
+
+@ We should be careful to keep |arc<el_gordo| so that calling |arc_test| with
+|a_goal=el_gordo| is guaranteed to yield the arc length.
+
+@<Initialize |v002|, |v022|, and the arc length estimate |arc|;...@>=
+v002 = mp_pyth_add(mp, dx01+half(dx0+dx02), dy01+half(dy0+dy02));
+v022 = mp_pyth_add(mp, dx12+half(dx02+dx2), dy12+half(dy02+dy2));
+tmp = halfp(v02+2);
+arc1 = v002 + half(halfp(v0+tmp) - v002);
+arc = v022 + half(halfp(v2+tmp) - v022);
+if ( (arc < el_gordo-arc1) ) {
+ arc = arc+arc1;
+} else {
+ mp->arith_error = true;
+ if ( a_goal==el_gordo ) return (el_gordo);
+ else return (-two);
+}
+
+@ @<Other local variables in |arc_test|@>=
+scaled tmp, tmp2; /* all purpose temporary registers */
+scaled arc1; /* arc length estimate for the first half */
+
+@ @<Test if the control points are confined to one quadrant or rotating...@>=
+simple = ((dx0>=0) && (dx1>=0) && (dx2>=0)) ||
+ ((dx0<=0) && (dx1<=0) && (dx2<=0));
+if ( simple )
+ simple = ((dy0>=0) && (dy1>=0) && (dy2>=0)) ||
+ ((dy0<=0) && (dy1<=0) && (dy2<=0));
+if ( ! simple ) {
+ simple = ((dx0>=dy0) && (dx1>=dy1) && (dx2>=dy2)) ||
+ ((dx0<=dy0) && (dx1<=dy1) && (dx2<=dy2));
+ if ( simple )
+ simple = ((-dx0>=dy0) && (-dx1>=dy1) && (-dx2>=dy2)) ||
+ ((-dx0<=dy0) && (-dx1<=dy1) && (-dx2<=dy2));
+}
+
+@ Since Simpson's rule is based on approximating the integrand by a parabola,
+@^Simpson's rule@>
+it is appropriate to use the same approximation to decide when the integral
+reaches the intermediate value |a_goal|. At this point
+$$\eqalign{
+ {\vb\dot B(0)\vb\over 3} &= \hbox{|v0|}, \qquad
+ {\vb\dot B({1\over4})\vb\over 3} = {\hbox{|v002|}\over 2}, \qquad
+ {\vb\dot B({1\over2})\vb\over 3} = {\hbox{|v02|}\over 2}, \cr
+ {\vb\dot B({3\over4})\vb\over 3} &= {\hbox{|v022|}\over 2}, \qquad
+ {\vb\dot B(1)\vb\over 3} = \hbox{|v2|} \cr
+}
+$$
+and
+$$ {\vb\dot B(t)\vb\over 3} \approx
+ \cases{B\left(\hbox{|v0|},
+ \hbox{|v002|}-{1\over 2}\hbox{|v0|}-{1\over 4}\hbox{|v02|},
+ {1\over 2}\hbox{|v02|}; 2t \right)&
+ if $t\le{1\over 2}$\cr
+ B\left({1\over 2}\hbox{|v02|},
+ \hbox{|v022|}-{1\over 4}\hbox{|v02|}-{1\over 2}\hbox{|v2|},
+ \hbox{|v2|}; 2t-1 \right)&
+ if $t\ge{1\over 2}$.\cr}
+ \eqno (*)
+$$
+We can integrate $\vb\dot B(t)\vb$ by using
+$$\int 3B(a,b,c;\tau)\,dt =
+ {B(0,a,a+b,a+b+c;\tau) + {\rm constant} \over {d\tau\over dt}}.
+$$
+
+This construction allows us to find the time when the arc length reaches
+|a_goal| by solving a cubic equation of the form
+$$ B(0,a,a+b,a+b+c;\tau) = x, $$
+where $\tau$ is $2t$ or $2t+1$, $x$ is |a_goal| or |a_goal-arc1|, and $a$, $b$,
+and $c$ are the Bernshte{\u\i}n coefficients from $(*)$ divided by
+@^Bernshte{\u\i}n, Serge{\u\i} Natanovich@>
+$d\tau\over dt$. We shall define a function |solve_rising_cubic| that finds
+$\tau$ given $a$, $b$, $c$, and $x$.
+
+@<Estimate when the arc length reaches |a_goal| and set |arc_test| to...@>=
+{
+ tmp = (v02 + 2) / 4;
+ if ( a_goal<=arc1 ) {
+ tmp2 = halfp(v0);
+ return
+ (halfp(mp_solve_rising_cubic(mp, tmp2, arc1-tmp2-tmp, tmp, a_goal))- two);
+ } else {
+ tmp2 = halfp(v2);
+ return ((half_unit - two) +
+ halfp(mp_solve_rising_cubic(mp, tmp, arc-arc1-tmp-tmp2, tmp2, a_goal-arc1)));
+ }
+}
+
+@ Here is the |solve_rising_cubic| routine that finds the time~$t$ when
+$$ B(0, a, a+b, a+b+c; t) = x. $$
+This routine is based on |crossing_point| but is simplified by the
+assumptions that $B(a,b,c;t)\ge0$ for $0\le t\le1$ and that |0<=x<=a+b+c|.
+If rounding error causes this condition to be violated slightly, we just ignore
+it and proceed with binary search. This finds a time when the function value
+reaches |x| and the slope is positive.
+
+@<Declare subroutines needed by |arc_test|@>=
+scaled mp_solve_rising_cubic (MP mp,scaled a, scaled b, scaled c, scaled x) {
+ scaled ab, bc, ac; /* bisection results */
+ integer t; /* $2^k+q$ where unscaled answer is in $[q2^{-k},(q+1)2^{-k})$ */
+ integer xx; /* temporary for updating |x| */
+ if ( (a<0) || (c<0) ) mp_confusion(mp, "rising?");
+@:this can't happen rising?}{\quad rising?@>
+ if ( x<=0 ) {
+ return 0;
+ } else if ( x >= a+b+c ) {
+ return unity;
+ } else {
+ t = 1;
+ @<Rescale if necessary to make sure |a|, |b|, and |c| are all less than
+ |el_gordo div 3|@>;
+ do {
+ t+=t;
+ @<Subdivide the B\'ezier quadratic defined by |a|, |b|, |c|@>;
+ xx = x - a - ab - ac;
+ if ( xx < -x ) { x+=x; b=ab; c=ac; }
+ else { x = x + xx; a=ac; b=bc; t = t+1; };
+ } while (t < unity);
+ return (t - unity);
+ }
+}
+
+@ @<Subdivide the B\'ezier quadratic defined by |a|, |b|, |c|@>=
+ab = half(a+b);
+bc = half(b+c);
+ac = half(ab+bc)
+
+@ @d one_third_el_gordo 05252525252 /* upper bound on |a|, |b|, and |c| */
+
+@<Rescale if necessary to make sure |a|, |b|, and |c| are all less than...@>=
+while ((a>one_third_el_gordo)||(b>one_third_el_gordo)||(c>one_third_el_gordo)) {
+ a = halfp(a);
+ b = half(b);
+ c = halfp(c);
+ x = halfp(x);
+}
+
+@ It is convenient to have a simpler interface to |arc_test| that requires no
+unnecessary arguments and ensures that each $({\it dx},{\it dy})$ pair has
+length less than |fraction_four|.
+
+@d arc_tol 16 /* quit when change in arc length estimate reaches this */
+
+@c scaled mp_do_arc_test (MP mp,scaled dx0, scaled dy0, scaled dx1,
+ scaled dy1, scaled dx2, scaled dy2, scaled a_goal) {
+ scaled v0,v1,v2; /* length of each $({\it dx},{\it dy})$ pair */
+ scaled v02; /* twice the norm of the quadratic at $t={1\over2}$ */
+ v0 = mp_pyth_add(mp, dx0,dy0);
+ v1 = mp_pyth_add(mp, dx1,dy1);
+ v2 = mp_pyth_add(mp, dx2,dy2);
+ if ( (v0>=fraction_four) || (v1>=fraction_four) || (v2>=fraction_four) ) {
+ mp->arith_error = true;
+ if ( a_goal==el_gordo ) return el_gordo;
+ else return (-two);
+ } else {
+ v02 = mp_pyth_add(mp, dx1+half(dx0+dx2), dy1+half(dy0+dy2));
+ return (mp_arc_test(mp, dx0,dy0, dx1,dy1, dx2,dy2,
+ v0, v02, v2, a_goal, arc_tol));
+ }
+}
+
+@ Now it is easy to find the arc length of an entire path.
+
+@c scaled mp_get_arc_length (MP mp,pointer h) {
+ pointer p,q; /* for traversing the path */
+ scaled a,a_tot; /* current and total arc lengths */
+ a_tot = 0;
+ p = h;
+ while ( right_type(p)!=mp_endpoint ){
+ q = link(p);
+ a = mp_do_arc_test(mp, right_x(p)-x_coord(p), right_y(p)-y_coord(p),
+ left_x(q)-right_x(p), left_y(q)-right_y(p),
+ x_coord(q)-left_x(q), y_coord(q)-left_y(q), el_gordo);
+ a_tot = mp_slow_add(mp, a, a_tot);
+ if ( q==h ) break; else p=q;
+ }
+ check_arith;
+ return a_tot;
+}
+
+@ The inverse operation of finding the time on a path~|h| when the arc length
+reaches some value |arc0| can also be accomplished via |do_arc_test|. Some care
+is required to handle very large times or negative times on cyclic paths. For
+non-cyclic paths, |arc0| values that are negative or too large cause
+|get_arc_time| to return 0 or the length of path~|h|.
+
+If |arc0| is greater than the arc length of a cyclic path~|h|, the result is a
+time value greater than the length of the path. Since it could be much greater,
+we must be prepared to compute the arc length of path~|h| and divide this into
+|arc0| to find how many multiples of the length of path~|h| to add.
+
+@c scaled mp_get_arc_time (MP mp,pointer h, scaled arc0) {
+ pointer p,q; /* for traversing the path */
+ scaled t_tot; /* accumulator for the result */
+ scaled t; /* the result of |do_arc_test| */
+ scaled arc; /* portion of |arc0| not used up so far */
+ integer n; /* number of extra times to go around the cycle */
+ if ( arc0<0 ) {
+ @<Deal with a negative |arc0| value and |return|@>;
+ }
+ if ( arc0==el_gordo ) decr(arc0);
+ t_tot = 0;
+ arc = arc0;
+ p = h;
+ while ( (right_type(p)!=mp_endpoint) && (arc>0) ) {
+ q = link(p);
+ t = mp_do_arc_test(mp, right_x(p)-x_coord(p), right_y(p)-y_coord(p),
+ left_x(q)-right_x(p), left_y(q)-right_y(p),
+ x_coord(q)-left_x(q), y_coord(q)-left_y(q), arc);
+ @<Update |arc| and |t_tot| after |do_arc_test| has just returned |t|@>;
+ if ( q==h ) {
+ @<Update |t_tot| and |arc| to avoid going around the cyclic
+ path too many times but set |arith_error:=true| and |goto done| on
+ overflow@>;
+ }
+ p = q;
+ }
+ check_arith;
+ return t_tot;
+}
+
+@ @<Update |arc| and |t_tot| after |do_arc_test| has just returned |t|@>=
+if ( t<0 ) { t_tot = t_tot + t + two; arc = 0; }
+else { t_tot = t_tot + unity; arc = arc - t; }
+
+@ @<Deal with a negative |arc0| value and |return|@>=
+{
+ if ( left_type(h)==mp_endpoint ) {
+ t_tot=0;
+ } else {
+ p = mp_htap_ypoc(mp, h);
+ t_tot = -mp_get_arc_time(mp, p, -arc0);
+ mp_toss_knot_list(mp, p);
+ }
+ check_arith;
+ return t_tot;
+}
+
+@ @<Update |t_tot| and |arc| to avoid going around the cyclic...@>=
+if ( arc>0 ) {
+ n = arc / (arc0 - arc);
+ arc = arc - n*(arc0 - arc);
+ if ( t_tot > (el_gordo / (n+1)) ) {
+ return el_gordo;
+ }
+ t_tot = (n + 1)*t_tot;
+}
+
+@* \[20] Data structures for pens.
+A Pen in \MP\ can be either elliptical or polygonal. Elliptical pens result
+in \ps\ \&{stroke} commands, while anything drawn with a polygonal pen is
+@:stroke}{\&{stroke} command@>
+converted into an area fill as described in the next part of this program.
+The mathematics behind this process is based on simple aspects of the theory
+of tracings developed by Leo Guibas, Lyle Ramshaw, and Jorge Stolfi
+[``A kinematic framework for computational geometry,'' Proc.\ IEEE Symp.\
+Foundations of Computer Science {\bf 24} (1983), 100--111].
+
+Polygonal pens are created from paths via \MP's \&{makepen} primitive.
+@:makepen_}{\&{makepen} primitive@>
+This path representation is almost sufficient for our purposes except that
+a pen path should always be a convex polygon with the vertices in
+counter-clockwise order.
+Since we will need to scan pen polygons both forward and backward, a pen
+should be represented as a doubly linked ring of knot nodes. There is
+room for the extra back pointer because we do not need the
+|left_type| or |right_type| fields. In fact, we don't need the |left_x|,
+|left_y|, |right_x|, or |right_y| fields either but we leave these alone
+so that certain procedures can operate on both pens and paths. In particular,
+pens can be copied using |copy_path| and recycled using |toss_knot_list|.
+
+@d knil info
+ /* this replaces the |left_type| and |right_type| fields in a pen knot */
+
+@ The |make_pen| procedure turns a path into a pen by initializing
+the |knil| pointers and making sure the knots form a convex polygon.
+Thus each cubic in the given path becomes a straight line and the control
+points are ignored. If the path is not cyclic, the ends are connected by a
+straight line.
+
+@d copy_pen(A) mp_make_pen(mp, mp_copy_path(mp, (A)),false)
+
+@c @<Declare a function called |convex_hull|@>
+pointer mp_make_pen (MP mp,pointer h, boolean need_hull) {
+ pointer p,q; /* two consecutive knots */
+ q=h;
+ do {
+ p=q; q=link(q);
+ knil(q)=p;
+ } while (q!=h);
+ if ( need_hull ){
+ h=mp_convex_hull(mp, h);
+ @<Make sure |h| isn't confused with an elliptical pen@>;
+ }
+ return h;
+}
+
+@ The only information required about an elliptical pen is the overall
+transformation that has been applied to the original \&{pencircle}.
+@:pencircle_}{\&{pencircle} primitive@>
+Since it suffices to keep track of how the three points $(0,0)$, $(1,0)$,
+and $(0,1)$ are transformed, an elliptical pen can be stored in a single
+knot node and transformed as if it were a path.
+
+@d pen_is_elliptical(A) ((A)==link((A)))
+
+@c pointer mp_get_pen_circle (MP mp,scaled diam) {
+ pointer h; /* the knot node to return */
+ h=mp_get_node(mp, knot_node_size);
+ link(h)=h; knil(h)=h;
+ originator(h)=mp_program_code;
+ x_coord(h)=0; y_coord(h)=0;
+ left_x(h)=diam; left_y(h)=0;
+ right_x(h)=0; right_y(h)=diam;
+ return h;
+}
+
+@ If the polygon being returned by |make_pen| has only one vertex, it will
+be interpreted as an elliptical pen. This is no problem since a degenerate
+polygon can equally well be thought of as a degenerate ellipse. We need only
+initialize the |left_x|, |left_y|, |right_x|, and |right_y| fields.
+
+@<Make sure |h| isn't confused with an elliptical pen@>=
+if ( pen_is_elliptical( h) ){
+ left_x(h)=x_coord(h); left_y(h)=y_coord(h);
+ right_x(h)=x_coord(h); right_y(h)=y_coord(h);
+}
+
+@ We have to cheat a little here but most operations on pens only use
+the first three words in each knot node.
+@^data structure assumptions@>
+
+@<Initialize a pen at |test_pen| so that it fits in nine words@>=
+x_coord(test_pen)=-half_unit;
+y_coord(test_pen)=0;
+x_coord(test_pen+3)=half_unit;
+y_coord(test_pen+3)=0;
+x_coord(test_pen+6)=0;
+y_coord(test_pen+6)=unity;
+link(test_pen)=test_pen+3;
+link(test_pen+3)=test_pen+6;
+link(test_pen+6)=test_pen;
+knil(test_pen)=test_pen+6;
+knil(test_pen+3)=test_pen;
+knil(test_pen+6)=test_pen+3
+
+@ Printing a polygonal pen is very much like printing a path
+
+@<Declare subroutines for printing expressions@>=
+void mp_pr_pen (MP mp,pointer h) {
+ pointer p,q; /* for list traversal */
+ if ( pen_is_elliptical(h) ) {
+ @<Print the elliptical pen |h|@>;
+ } else {
+ p=h;
+ do {
+ mp_print_two(mp, x_coord(p),y_coord(p));
+ mp_print_nl(mp, " .. ");
+ @<Advance |p| making sure the links are OK and |return| if there is
+ a problem@>;
+ } while (p!=h);
+ mp_print(mp, "cycle");
+ }
+}
+
+@ @<Advance |p| making sure the links are OK and |return| if there is...@>=
+q=link(p);
+if ( (q==null) || (knil(q)!=p) ) {
+ mp_print_nl(mp, "???"); return; /* this won't happen */
+@.???@>
+}
+p=q
+
+@ @<Print the elliptical pen |h|@>=
+{
+mp_print(mp, "pencircle transformed (");
+mp_print_scaled(mp, x_coord(h));
+mp_print_char(mp, ',');
+mp_print_scaled(mp, y_coord(h));
+mp_print_char(mp, ',');
+mp_print_scaled(mp, left_x(h)-x_coord(h));
+mp_print_char(mp, ',');
+mp_print_scaled(mp, right_x(h)-x_coord(h));
+mp_print_char(mp, ',');
+mp_print_scaled(mp, left_y(h)-y_coord(h));
+mp_print_char(mp, ',');
+mp_print_scaled(mp, right_y(h)-y_coord(h));
+mp_print_char(mp, ')');
+}
+
+@ Here us another version of |pr_pen| that prints the pen as a diagnostic
+message.
+
+@<Declare subroutines for printing expressions@>=
+void mp_print_pen (MP mp,pointer h, const char *s, boolean nuline) {
+ mp_print_diagnostic(mp, "Pen",s,nuline); mp_print_ln(mp);
+@.Pen at line...@>
+ mp_pr_pen(mp, h);
+ mp_end_diagnostic(mp, true);
+}
+
+@ Making a polygonal pen into a path involves restoring the |left_type| and
+|right_type| fields and setting the control points so as to make a polygonal
+path.
+
+@c
+void mp_make_path (MP mp,pointer h) {
+ pointer p; /* for traversing the knot list */
+ small_number k; /* a loop counter */
+ @<Other local variables in |make_path|@>;
+ if ( pen_is_elliptical(h) ) {
+ @<Make the elliptical pen |h| into a path@>;
+ } else {
+ p=h;
+ do {
+ left_type(p)=mp_explicit;
+ right_type(p)=mp_explicit;
+ @<copy the coordinates of knot |p| into its control points@>;
+ p=link(p);
+ } while (p!=h);
+ }
+}
+
+@ @<copy the coordinates of knot |p| into its control points@>=
+left_x(p)=x_coord(p);
+left_y(p)=y_coord(p);
+right_x(p)=x_coord(p);
+right_y(p)=y_coord(p)
+
+@ We need an eight knot path to get a good approximation to an ellipse.
+
+@<Make the elliptical pen |h| into a path@>=
+{
+ @<Extract the transformation parameters from the elliptical pen~|h|@>;
+ p=h;
+ for (k=0;k<=7;k++ ) {
+ @<Initialize |p| as the |k|th knot of a circle of unit diameter,
+ transforming it appropriately@>;
+ if ( k==7 ) link(p)=h; else link(p)=mp_get_node(mp, knot_node_size);
+ p=link(p);
+ }
+}
+
+@ @<Extract the transformation parameters from the elliptical pen~|h|@>=
+center_x=x_coord(h);
+center_y=y_coord(h);
+width_x=left_x(h)-center_x;
+width_y=left_y(h)-center_y;
+height_x=right_x(h)-center_x;
+height_y=right_y(h)-center_y
+
+@ @<Other local variables in |make_path|@>=
+scaled center_x,center_y; /* translation parameters for an elliptical pen */
+scaled width_x,width_y; /* the effect of a unit change in $x$ */
+scaled height_x,height_y; /* the effect of a unit change in $y$ */
+scaled dx,dy; /* the vector from knot |p| to its right control point */
+integer kk;
+ /* |k| advanced $270^\circ$ around the ring (cf. $\sin\theta=\cos(\theta+270)$) */
+
+@ The only tricky thing here are the tables |half_cos| and |d_cos| used to
+find the point $k/8$ of the way around the circle and the direction vector
+to use there.
+
+@<Initialize |p| as the |k|th knot of a circle of unit diameter,...@>=
+kk=(k+6)% 8;
+x_coord(p)=center_x+mp_take_fraction(mp, mp->half_cos[k],width_x)
+ +mp_take_fraction(mp, mp->half_cos[kk],height_x);
+y_coord(p)=center_y+mp_take_fraction(mp, mp->half_cos[k],width_y)
+ +mp_take_fraction(mp, mp->half_cos[kk],height_y);
+dx=-mp_take_fraction(mp, mp->d_cos[kk],width_x)
+ +mp_take_fraction(mp, mp->d_cos[k],height_x);
+dy=-mp_take_fraction(mp, mp->d_cos[kk],width_y)
+ +mp_take_fraction(mp, mp->d_cos[k],height_y);
+right_x(p)=x_coord(p)+dx;
+right_y(p)=y_coord(p)+dy;
+left_x(p)=x_coord(p)-dx;
+left_y(p)=y_coord(p)-dy;
+left_type(p)=mp_explicit;
+right_type(p)=mp_explicit;
+originator(p)=mp_program_code
+
+@ @<Glob...@>=
+fraction half_cos[8]; /* ${1\over2}\cos(45k)$ */
+fraction d_cos[8]; /* a magic constant times $\cos(45k)$ */
+
+@ The magic constant for |d_cos| is the distance between $({1\over2},0)$ and
+$({1\over4}\sqrt2,{1\over4}\sqrt2)$ times the result of the |velocity|
+function for $\theta=\phi=22.5^\circ$. This comes out to be
+$$ d = {\sqrt{2-\sqrt2}\over 3+3\cos22.5^\circ}
+ \approx 0.132608244919772.
+$$
+
+@<Set init...@>=
+mp->half_cos[0]=fraction_half;
+mp->half_cos[1]=94906266; /* $2^{26}\sqrt2\approx94906265.62$ */
+mp->half_cos[2]=0;
+mp->d_cos[0]=35596755; /* $2^{28}d\approx35596754.69$ */
+mp->d_cos[1]=25170707; /* $2^{27}\sqrt2\,d\approx25170706.63$ */
+mp->d_cos[2]=0;
+for (k=3;k<= 4;k++ ) {
+ mp->half_cos[k]=-mp->half_cos[4-k];
+ mp->d_cos[k]=-mp->d_cos[4-k];
+}
+for (k=5;k<= 7;k++ ) {
+ mp->half_cos[k]=mp->half_cos[8-k];
+ mp->d_cos[k]=mp->d_cos[8-k];
+}
+
+@ The |convex_hull| function forces a pen polygon to be convex when it is
+returned by |make_pen| and after any subsequent transformation where rounding
+error might allow the convexity to be lost.
+The convex hull algorithm used here is described by F.~P. Preparata and
+M.~I. Shamos [{\sl Computational Geometry}, Springer-Verlag, 1985].
+
+@<Declare a function called |convex_hull|@>=
+@<Declare a procedure called |move_knot|@>
+pointer mp_convex_hull (MP mp,pointer h) { /* Make a polygonal pen convex */
+ pointer l,r; /* the leftmost and rightmost knots */
+ pointer p,q; /* knots being scanned */
+ pointer s; /* the starting point for an upcoming scan */
+ scaled dx,dy; /* a temporary pointer */
+ if ( pen_is_elliptical(h) ) {
+ return h;
+ } else {
+ @<Set |l| to the leftmost knot in polygon~|h|@>;
+ @<Set |r| to the rightmost knot in polygon~|h|@>;
+ if ( l!=r ) {
+ s=link(r);
+ @<Find any knots on the path from |l| to |r| above the |l|-|r| line and
+ move them past~|r|@>;
+ @<Find any knots on the path from |s| to |l| below the |l|-|r| line and
+ move them past~|l|@>;
+ @<Sort the path from |l| to |r| by increasing $x$@>;
+ @<Sort the path from |r| to |l| by decreasing $x$@>;
+ }
+ if ( l!=link(l) ) {
+ @<Do a Gramm scan and remove vertices where there is no left turn@>;
+ }
+ return l;
+ }
+}
+
+@ All comparisons are done primarily on $x$ and secondarily on $y$.
+
+@<Set |l| to the leftmost knot in polygon~|h|@>=
+l=h;
+p=link(h);
+while ( p!=h ) {
+ if ( x_coord(p)<=x_coord(l) )
+ if ( (x_coord(p)<x_coord(l)) || (y_coord(p)<y_coord(l)) )
+ l=p;
+ p=link(p);
+}
+
+@ @<Set |r| to the rightmost knot in polygon~|h|@>=
+r=h;
+p=link(h);
+while ( p!=h ) {
+ if ( x_coord(p)>=x_coord(r) )
+ if ( (x_coord(p)>x_coord(r)) || (y_coord(p)>y_coord(r)) )
+ r=p;
+ p=link(p);
+}
+
+@ @<Find any knots on the path from |l| to |r| above the |l|-|r| line...@>=
+dx=x_coord(r)-x_coord(l);
+dy=y_coord(r)-y_coord(l);
+p=link(l);
+while ( p!=r ) {
+ q=link(p);
+ if ( mp_ab_vs_cd(mp, dx,y_coord(p)-y_coord(l),dy,x_coord(p)-x_coord(l))>0 )
+ mp_move_knot(mp, p, r);
+ p=q;
+}
+
+@ The |move_knot| procedure removes |p| from a doubly linked list and inserts
+it after |q|.
+
+@ @<Declare a procedure called |move_knot|@>=
+void mp_move_knot (MP mp,pointer p, pointer q) {
+ link(knil(p))=link(p);
+ knil(link(p))=knil(p);
+ knil(p)=q;
+ link(p)=link(q);
+ link(q)=p;
+ knil(link(p))=p;
+}
+
+@ @<Find any knots on the path from |s| to |l| below the |l|-|r| line...@>=
+p=s;
+while ( p!=l ) {
+ q=link(p);
+ if ( mp_ab_vs_cd(mp, dx,y_coord(p)-y_coord(l),dy,x_coord(p)-x_coord(l))<0 )
+ mp_move_knot(mp, p,l);
+ p=q;
+}
+
+@ The list is likely to be in order already so we just do linear insertions.
+Secondary comparisons on $y$ ensure that the sort is consistent with the
+choice of |l| and |r|.
+
+@<Sort the path from |l| to |r| by increasing $x$@>=
+p=link(l);
+while ( p!=r ) {
+ q=knil(p);
+ while ( x_coord(q)>x_coord(p) ) q=knil(q);
+ while ( x_coord(q)==x_coord(p) ) {
+ if ( y_coord(q)>y_coord(p) ) q=knil(q); else break;
+ }
+ if ( q==knil(p) ) p=link(p);
+ else { p=link(p); mp_move_knot(mp, knil(p),q); };
+}
+
+@ @<Sort the path from |r| to |l| by decreasing $x$@>=
+p=link(r);
+while ( p!=l ){
+ q=knil(p);
+ while ( x_coord(q)<x_coord(p) ) q=knil(q);
+ while ( x_coord(q)==x_coord(p) ) {
+ if ( y_coord(q)<y_coord(p) ) q=knil(q); else break;
+ }
+ if ( q==knil(p) ) p=link(p);
+ else { p=link(p); mp_move_knot(mp, knil(p),q); };
+}
+
+@ The condition involving |ab_vs_cd| tests if there is not a left turn
+at knot |q|. There usually will be a left turn so we streamline the case
+where the |then| clause is not executed.
+
+@<Do a Gramm scan and remove vertices where there...@>=
+{
+p=l; q=link(l);
+while (1) {
+ dx=x_coord(q)-x_coord(p);
+ dy=y_coord(q)-y_coord(p);
+ p=q; q=link(q);
+ if ( p==l ) break;
+ if ( p!=r )
+ if ( mp_ab_vs_cd(mp, dx,y_coord(q)-y_coord(p),dy,x_coord(q)-x_coord(p))<=0 ) {
+ @<Remove knot |p| and back up |p| and |q| but don't go past |l|@>;
+ }
+ }
+}
+
+@ @<Remove knot |p| and back up |p| and |q| but don't go past |l|@>=
+{
+s=knil(p);
+mp_free_node(mp, p,knot_node_size);
+link(s)=q; knil(q)=s;
+if ( s==l ) p=s;
+else { p=knil(s); q=s; };
+}
+
+@ The |find_offset| procedure sets global variables |(cur_x,cur_y)| to the
+offset associated with the given direction |(x,y)|. If two different offsets
+apply, it chooses one of them.
+
+@c
+void mp_find_offset (MP mp,scaled x, scaled y, pointer h) {
+ pointer p,q; /* consecutive knots */
+ scaled wx,wy,hx,hy;
+ /* the transformation matrix for an elliptical pen */
+ fraction xx,yy; /* untransformed offset for an elliptical pen */
+ fraction d; /* a temporary register */
+ if ( pen_is_elliptical(h) ) {
+ @<Find the offset for |(x,y)| on the elliptical pen~|h|@>
+ } else {
+ q=h;
+ do {
+ p=q; q=link(q);
+ } while (!(mp_ab_vs_cd(mp, x_coord(q)-x_coord(p),y, y_coord(q)-y_coord(p),x)>=0));
+ do {
+ p=q; q=link(q);
+ } while (!(mp_ab_vs_cd(mp, x_coord(q)-x_coord(p),y, y_coord(q)-y_coord(p),x)<=0));
+ mp->cur_x=x_coord(p);
+ mp->cur_y=y_coord(p);
+ }
+}
+
+@ @<Glob...@>=
+scaled cur_x;
+scaled cur_y; /* all-purpose return value registers */
+
+@ @<Find the offset for |(x,y)| on the elliptical pen~|h|@>=
+if ( (x==0) && (y==0) ) {
+ mp->cur_x=x_coord(h); mp->cur_y=y_coord(h);
+} else {
+ @<Find the non-constant part of the transformation for |h|@>;
+ while ( (abs(x)<fraction_half) && (abs(y)<fraction_half) ){
+ x+=x; y+=y;
+ };
+ @<Make |(xx,yy)| the offset on the untransformed \&{pencircle} for the
+ untransformed version of |(x,y)|@>;
+ mp->cur_x=x_coord(h)+mp_take_fraction(mp, xx,wx)+mp_take_fraction(mp, yy,hx);
+ mp->cur_y=y_coord(h)+mp_take_fraction(mp, xx,wy)+mp_take_fraction(mp, yy,hy);
+}
+
+@ @<Find the non-constant part of the transformation for |h|@>=
+wx=left_x(h)-x_coord(h);
+wy=left_y(h)-y_coord(h);
+hx=right_x(h)-x_coord(h);
+hy=right_y(h)-y_coord(h)
+
+@ @<Make |(xx,yy)| the offset on the untransformed \&{pencircle} for the...@>=
+yy=-(mp_take_fraction(mp, x,hy)+mp_take_fraction(mp, y,-hx));
+xx=mp_take_fraction(mp, x,-wy)+mp_take_fraction(mp, y,wx);
+d=mp_pyth_add(mp, xx,yy);
+if ( d>0 ) {
+ xx=half(mp_make_fraction(mp, xx,d));
+ yy=half(mp_make_fraction(mp, yy,d));
+}
+
+@ Finding the bounding box of a pen is easy except if the pen is elliptical.
+But we can handle that case by just calling |find_offset| twice. The answer
+is stored in the global variables |minx|, |maxx|, |miny|, and |maxy|.
+
+@c
+void mp_pen_bbox (MP mp,pointer h) {
+ pointer p; /* for scanning the knot list */
+ if ( pen_is_elliptical(h) ) {
+ @<Find the bounding box of an elliptical pen@>;
+ } else {
+ minx=x_coord(h); maxx=minx;
+ miny=y_coord(h); maxy=miny;
+ p=link(h);
+ while ( p!=h ) {
+ if ( x_coord(p)<minx ) minx=x_coord(p);
+ if ( y_coord(p)<miny ) miny=y_coord(p);
+ if ( x_coord(p)>maxx ) maxx=x_coord(p);
+ if ( y_coord(p)>maxy ) maxy=y_coord(p);
+ p=link(p);
+ }
+ }
+}
+
+@ @<Find the bounding box of an elliptical pen@>=
+{
+mp_find_offset(mp, 0,fraction_one,h);
+maxx=mp->cur_x;
+minx=2*x_coord(h)-mp->cur_x;
+mp_find_offset(mp, -fraction_one,0,h);
+maxy=mp->cur_y;
+miny=2*y_coord(h)-mp->cur_y;
+}
+
+@* \[21] Edge structures.
+Now we come to \MP's internal scheme for representing pictures.
+The representation is very different from \MF's edge structures
+because \MP\ pictures contain \ps\ graphics objects instead of pixel
+images. However, the basic idea is somewhat similar in that shapes
+are represented via their boundaries.
+
+The main purpose of edge structures is to keep track of graphical objects
+until it is time to translate them into \ps. Since \MP\ does not need to
+know anything about an edge structure other than how to translate it into
+\ps\ and how to find its bounding box, edge structures can be just linked
+lists of graphical objects. \MP\ has no easy way to determine whether
+two such objects overlap, but it suffices to draw the first one first and
+let the second one overwrite it if necessary.
+
+@<Types...@>=
+enum mp_graphical_object_code {
+ @<Graphical object codes@>
+ mp_final_graphic
+};
+
+@ Let's consider the types of graphical objects one at a time.
+First of all, a filled contour is represented by a eight-word node. The first
+word contains |type| and |link| fields, and the next six words contain a
+pointer to a cyclic path and the value to use for \ps' \&{currentrgbcolor}
+parameter. If a pen is used for filling |pen_p|, |ljoin_val| and |miterlim_val|
+give the relevant information.
+
+@d path_p(A) link((A)+1)
+ /* a pointer to the path that needs filling */
+@d pen_p(A) info((A)+1)
+ /* a pointer to the pen to fill or stroke with */
+@d color_model(A) type((A)+2) /* the color model */
+@d obj_red_loc(A) ((A)+3) /* the first of three locations for the color */
+@d obj_cyan_loc obj_red_loc /* the first of four locations for the color */
+@d obj_grey_loc obj_red_loc /* the location for the color */
+@d red_val(A) mp->mem[(A)+3].sc
+ /* the red component of the color in the range $0\ldots1$ */
+@d cyan_val red_val
+@d grey_val red_val
+@d green_val(A) mp->mem[(A)+4].sc
+ /* the green component of the color in the range $0\ldots1$ */
+@d magenta_val green_val
+@d blue_val(A) mp->mem[(A)+5].sc
+ /* the blue component of the color in the range $0\ldots1$ */
+@d yellow_val blue_val
+@d black_val(A) mp->mem[(A)+6].sc
+ /* the blue component of the color in the range $0\ldots1$ */
+@d ljoin_val(A) name_type((A)) /* the value of \&{linejoin} */
+@:mp_linejoin_}{\&{linejoin} primitive@>
+@d miterlim_val(A) mp->mem[(A)+7].sc /* the value of \&{miterlimit} */
+@:mp_miterlimit_}{\&{miterlimit} primitive@>
+@d obj_color_part(A) mp->mem[(A)+3-red_part].sc
+ /* interpret an object pointer that has been offset by |red_part..blue_part| */
+@d pre_script(A) mp->mem[(A)+8].hh.lh
+@d post_script(A) mp->mem[(A)+8].hh.rh
+@d fill_node_size 9
+
+@ @<Graphical object codes@>=
+mp_fill_code=1,
+
+@ @c
+pointer mp_new_fill_node (MP mp,pointer p) {
+ /* make a fill node for cyclic path |p| and color black */
+ pointer t; /* the new node */
+ t=mp_get_node(mp, fill_node_size);
+ type(t)=mp_fill_code;
+ path_p(t)=p;
+ pen_p(t)=null; /* |null| means don't use a pen */
+ red_val(t)=0;
+ green_val(t)=0;
+ blue_val(t)=0;
+ black_val(t)=0;
+ color_model(t)=mp_uninitialized_model;
+ pre_script(t)=null;
+ post_script(t)=null;
+ @<Set the |ljoin_val| and |miterlim_val| fields in object |t|@>;
+ return t;
+}
+
+@ @<Set the |ljoin_val| and |miterlim_val| fields in object |t|@>=
+if ( mp->internal[mp_linejoin]>unity ) ljoin_val(t)=2;
+else if ( mp->internal[mp_linejoin]>0 ) ljoin_val(t)=1;
+else ljoin_val(t)=0;
+if ( mp->internal[mp_miterlimit]<unity )
+ miterlim_val(t)=unity;
+else
+ miterlim_val(t)=mp->internal[mp_miterlimit]
+
+@ A stroked path is represented by an eight-word node that is like a filled
+contour node except that it contains the current \&{linecap} value, a scale
+factor for the dash pattern, and a pointer that is non-null if the stroke
+is to be dashed. The purpose of the scale factor is to allow a picture to
+be transformed without touching the picture that |dash_p| points to.
+
+@d dash_p(A) link((A)+9)
+ /* a pointer to the edge structure that gives the dash pattern */
+@d lcap_val(A) type((A)+9)
+ /* the value of \&{linecap} */
+@:mp_linecap_}{\&{linecap} primitive@>
+@d dash_scale(A) mp->mem[(A)+10].sc /* dash lengths are scaled by this factor */
+@d stroked_node_size 11
+
+@ @<Graphical object codes@>=
+mp_stroked_code=2,
+
+@ @c
+pointer mp_new_stroked_node (MP mp,pointer p) {
+ /* make a stroked node for path |p| with |pen_p(p)| temporarily |null| */
+ pointer t; /* the new node */
+ t=mp_get_node(mp, stroked_node_size);
+ type(t)=mp_stroked_code;
+ path_p(t)=p; pen_p(t)=null;
+ dash_p(t)=null;
+ dash_scale(t)=unity;
+ red_val(t)=0;
+ green_val(t)=0;
+ blue_val(t)=0;
+ black_val(t)=0;
+ color_model(t)=mp_uninitialized_model;
+ pre_script(t)=null;
+ post_script(t)=null;
+ @<Set the |ljoin_val| and |miterlim_val| fields in object |t|@>;
+ if ( mp->internal[mp_linecap]>unity ) lcap_val(t)=2;
+ else if ( mp->internal[mp_linecap]>0 ) lcap_val(t)=1;
+ else lcap_val(t)=0;
+ return t;
+}
+
+@ When a dashed line is computed in a transformed coordinate system, the dash
+lengths get scaled like the pen shape and we need to compensate for this. Since
+there is no unique scale factor for an arbitrary transformation, we use the
+the square root of the determinant. The properties of the determinant make it
+easier to maintain the |dash_scale|. The computation is fairly straight-forward
+except for the initialization of the scale factor |s|. The factor of 64 is
+needed because |square_rt| scales its result by $2^8$ while we need $2^{14}$
+to counteract the effect of |take_fraction|.
+
+@<Declare subroutines needed by |print_edges|@>=
+scaled mp_sqrt_det (MP mp,scaled a, scaled b, scaled c, scaled d) {
+ scaled maxabs; /* $max(|a|,|b|,|c|,|d|)$ */
+ integer s; /* amount by which the result of |square_rt| needs to be scaled */
+ @<Initialize |maxabs|@>;
+ s=64;
+ while ( (maxabs<fraction_one) && (s>1) ){
+ a+=a; b+=b; c+=c; d+=d;
+ maxabs+=maxabs; s=halfp(s);
+ }
+ return s*mp_square_rt(mp, abs(mp_take_fraction(mp, a,d)-mp_take_fraction(mp, b,c)));
+}
+@#
+scaled mp_get_pen_scale (MP mp,pointer p) {
+ return mp_sqrt_det(mp,
+ left_x(p)-x_coord(p), right_x(p)-x_coord(p),
+ left_y(p)-y_coord(p), right_y(p)-y_coord(p));
+}
+
+@ @<Internal library ...@>=
+scaled mp_sqrt_det (MP mp,scaled a, scaled b, scaled c, scaled d) ;
+
+
+@ @<Initialize |maxabs|@>=
+maxabs=abs(a);
+if ( abs(b)>maxabs ) maxabs=abs(b);
+if ( abs(c)>maxabs ) maxabs=abs(c);
+if ( abs(d)>maxabs ) maxabs=abs(d)
+
+@ When a picture contains text, this is represented by a fourteen-word node
+where the color information and |type| and |link| fields are augmented by
+additional fields that describe the text and how it is transformed.
+The |path_p| and |pen_p| pointers are replaced by a number that identifies
+the font and a string number that gives the text to be displayed.
+The |width|, |height|, and |depth| fields
+give the dimensions of the text at its design size, and the remaining six
+words give a transformation to be applied to the text. The |new_text_node|
+function initializes everything to default values so that the text comes out
+black with its reference point at the origin.
+
+@d text_p(A) link((A)+1) /* a string pointer for the text to display */
+@d font_n(A) info((A)+1) /* the font number */
+@d width_val(A) mp->mem[(A)+7].sc /* unscaled width of the text */
+@d height_val(A) mp->mem[(A)+9].sc /* unscaled height of the text */
+@d depth_val(A) mp->mem[(A)+10].sc /* unscaled depth of the text */
+@d text_tx_loc(A) ((A)+11)
+ /* the first of six locations for transformation parameters */
+@d tx_val(A) mp->mem[(A)+11].sc /* $x$ shift amount */
+@d ty_val(A) mp->mem[(A)+12].sc /* $y$ shift amount */
+@d txx_val(A) mp->mem[(A)+13].sc /* |txx| transformation parameter */
+@d txy_val(A) mp->mem[(A)+14].sc /* |txy| transformation parameter */
+@d tyx_val(A) mp->mem[(A)+15].sc /* |tyx| transformation parameter */
+@d tyy_val(A) mp->mem[(A)+16].sc /* |tyy| transformation parameter */
+@d text_trans_part(A) mp->mem[(A)+11-x_part].sc
+ /* interpret a text node pointer that has been offset by |x_part..yy_part| */
+@d text_node_size 17
+
+@ @<Graphical object codes@>=
+mp_text_code=3,
+
+@ @c @<Declare text measuring subroutines@>
+pointer mp_new_text_node (MP mp,char *f,str_number s) {
+ /* make a text node for font |f| and text string |s| */
+ pointer t; /* the new node */
+ t=mp_get_node(mp, text_node_size);
+ type(t)=mp_text_code;
+ text_p(t)=s;
+ font_n(t)=mp_find_font(mp, f); /* this identifies the font */
+ red_val(t)=0;
+ green_val(t)=0;
+ blue_val(t)=0;
+ black_val(t)=0;
+ color_model(t)=mp_uninitialized_model;
+ pre_script(t)=null;
+ post_script(t)=null;
+ tx_val(t)=0; ty_val(t)=0;
+ txx_val(t)=unity; txy_val(t)=0;
+ tyx_val(t)=0; tyy_val(t)=unity;
+ mp_set_text_box(mp, t); /* this finds the bounding box */
+ return t;
+}
+
+@ The last two types of graphical objects that can occur in an edge structure
+are clipping paths and \&{setbounds} paths. These are slightly more difficult
+@:set_bounds_}{\&{setbounds} primitive@>
+to implement because we must keep track of exactly what is being clipped or
+bounded when pictures get merged together. For this reason, each clipping or
+\&{setbounds} operation is represented by a pair of nodes: first comes a
+two-word node whose |path_p| gives the relevant path, then there is the list
+of objects to clip or bound followed by a two-word node whose second word is
+unused.
+
+Using at least two words for each graphical object node allows them all to be
+allocated and deallocated similarly with a global array |gr_object_size| to
+give the size in words for each object type.
+
+@d start_clip_size 2
+@d start_bounds_size 2
+@d stop_clip_size 2 /* the second word is not used here */
+@d stop_bounds_size 2 /* the second word is not used here */
+@#
+@d stop_type(A) ((A)+2)
+ /* matching |type| for |start_clip_code| or |start_bounds_code| */
+@d has_color(A) (type((A))<mp_start_clip_code)
+ /* does a graphical object have color fields? */
+@d has_pen(A) (type((A))<mp_text_code)
+ /* does a graphical object have a |pen_p| field? */
+@d is_start_or_stop(A) (type((A))>=mp_start_clip_code)
+@d is_stop(A) (type((A))>=mp_stop_clip_code)
+
+@ @<Graphical object codes@>=
+mp_start_clip_code=4, /* |type| of a node that starts clipping */
+mp_start_bounds_code=5, /* |type| of a node that gives a \&{setbounds} path */
+mp_stop_clip_code=6, /* |type| of a node that stops clipping */
+mp_stop_bounds_code=7, /* |type| of a node that stops \&{setbounds} */
+
+@ @c
+pointer mp_new_bounds_node (MP mp,pointer p, small_number c) {
+ /* make a node of type |c| where |p| is the clipping or \&{setbounds} path */
+ pointer t; /* the new node */
+ t=mp_get_node(mp, mp->gr_object_size[c]);
+ type(t)=c;
+ path_p(t)=p;
+ return t;
+}
+
+@ We need an array to keep track of the sizes of graphical objects.
+
+@<Glob...@>=
+small_number gr_object_size[mp_stop_bounds_code+1];
+
+@ @<Set init...@>=
+mp->gr_object_size[mp_fill_code]=fill_node_size;
+mp->gr_object_size[mp_stroked_code]=stroked_node_size;
+mp->gr_object_size[mp_text_code]=text_node_size;
+mp->gr_object_size[mp_start_clip_code]=start_clip_size;
+mp->gr_object_size[mp_stop_clip_code]=stop_clip_size;
+mp->gr_object_size[mp_start_bounds_code]=start_bounds_size;
+mp->gr_object_size[mp_stop_bounds_code]=stop_bounds_size;
+
+@ All the essential information in an edge structure is encoded as a linked list
+of graphical objects as we have just seen, but it is helpful to add some
+redundant information. A single edge structure might be used as a dash pattern
+many times, and it would be nice to avoid scanning the same structure
+repeatedly. Thus, an edge structure known to be a suitable dash pattern
+has a header that gives a list of dashes in a sorted order designed for rapid
+translation into \ps.
+
+Each dash is represented by a three-word node containing the initial and final
+$x$~coordinates as well as the usual |link| field. The |link| fields points to
+the dash node with the next higher $x$-coordinates and the final link points
+to a special location called |null_dash|. (There should be no overlap between
+dashes). Since the $y$~coordinate of the dash pattern is needed to determine
+the period of repetition, this needs to be stored in the edge header along
+with a pointer to the list of dash nodes.
+
+@d start_x(A) mp->mem[(A)+1].sc /* the starting $x$~coordinate in a dash node */
+@d stop_x(A) mp->mem[(A)+2].sc /* the ending $x$~coordinate in a dash node */
+@d dash_node_size 3
+@d dash_list link
+ /* in an edge header this points to the first dash node */
+@d dash_y(A) mp->mem[(A)+1].sc /* $y$ value for the dash list in an edge header */
+
+@ It is also convenient for an edge header to contain the bounding
+box information needed by the \&{llcorner} and \&{urcorner} operators
+so that this does not have to be recomputed unnecessarily. This is done by
+adding fields for the $x$~and $y$ extremes as well as a pointer that indicates
+how far the bounding box computation has gotten. Thus if the user asks for
+the bounding box and then adds some more text to the picture before asking
+for more bounding box information, the second computation need only look at
+the additional text.
+
+When the bounding box has not been computed, the |bblast| pointer points
+to a dummy link at the head of the graphical object list while the |minx_val|
+and |miny_val| fields contain |el_gordo| and the |maxx_val| and |maxy_val|
+fields contain |-el_gordo|.
+
+Since the bounding box of pictures containing objects of type
+|mp_start_bounds_code| depends on the value of \&{truecorners}, the bounding box
+@:mp_true_corners_}{\&{truecorners} primitive@>
+data might not be valid for all values of this parameter. Hence, the |bbtype|
+field is needed to keep track of this.
+
+@d minx_val(A) mp->mem[(A)+2].sc
+@d miny_val(A) mp->mem[(A)+3].sc
+@d maxx_val(A) mp->mem[(A)+4].sc
+@d maxy_val(A) mp->mem[(A)+5].sc
+@d bblast(A) link((A)+6) /* last item considered in bounding box computation */
+@d bbtype(A) info((A)+6) /* tells how bounding box data depends on \&{truecorners} */
+@d dummy_loc(A) ((A)+7) /* where the object list begins in an edge header */
+@d no_bounds 0
+ /* |bbtype| value when bounding box data is valid for all \&{truecorners} values */
+@d bounds_set 1
+ /* |bbtype| value when bounding box data is for \&{truecorners}${}\le 0$ */
+@d bounds_unset 2
+ /* |bbtype| value when bounding box data is for \&{truecorners}${}>0$ */
+
+@c
+void mp_init_bbox (MP mp,pointer h) {
+ /* Initialize the bounding box information in edge structure |h| */
+ bblast(h)=dummy_loc(h);
+ bbtype(h)=no_bounds;
+ minx_val(h)=el_gordo;
+ miny_val(h)=el_gordo;
+ maxx_val(h)=-el_gordo;
+ maxy_val(h)=-el_gordo;
+}
+
+@ The only other entries in an edge header are a reference count in the first
+word and a pointer to the tail of the object list in the last word.
+
+@d obj_tail(A) info((A)+7) /* points to the last entry in the object list */
+@d edge_header_size 8
+
+@c
+void mp_init_edges (MP mp,pointer h) {
+ /* initialize an edge header to null values */
+ dash_list(h)=null_dash;
+ obj_tail(h)=dummy_loc(h);
+ link(dummy_loc(h))=null;
+ ref_count(h)=null;
+ mp_init_bbox(mp, h);
+}
+
+@ Here is how edge structures are deleted. The process can be recursive because
+of the need to dereference edge structures that are used as dash patterns.
+@^recursion@>
+
+@d add_edge_ref(A) incr(ref_count(A))
+@d delete_edge_ref(A) {
+ if ( ref_count((A))==null )
+ mp_toss_edges(mp, A);
+ else
+ decr(ref_count(A));
+ }
+
+@<Declare the recycling subroutines@>=
+void mp_flush_dash_list (MP mp,pointer h);
+pointer mp_toss_gr_object (MP mp,pointer p) ;
+void mp_toss_edges (MP mp,pointer h) ;
+
+@ @c void mp_toss_edges (MP mp,pointer h) {
+ pointer p,q; /* pointers that scan the list being recycled */
+ pointer r; /* an edge structure that object |p| refers to */
+ mp_flush_dash_list(mp, h);
+ q=link(dummy_loc(h));
+ while ( (q!=null) ) {
+ p=q; q=link(q);
+ r=mp_toss_gr_object(mp, p);
+ if ( r!=null ) delete_edge_ref(r);
+ }
+ mp_free_node(mp, h,edge_header_size);
+}
+void mp_flush_dash_list (MP mp,pointer h) {
+ pointer p,q; /* pointers that scan the list being recycled */
+ q=dash_list(h);
+ while ( q!=null_dash ) {
+ p=q; q=link(q);
+ mp_free_node(mp, p,dash_node_size);
+ }
+ dash_list(h)=null_dash;
+}
+pointer mp_toss_gr_object (MP mp,pointer p) {
+ /* returns an edge structure that needs to be dereferenced */
+ pointer e; /* the edge structure to return */
+ e=null;
+ @<Prepare to recycle graphical object |p|@>;
+ mp_free_node(mp, p,mp->gr_object_size[type(p)]);
+ return e;
+}
+
+@ @<Prepare to recycle graphical object |p|@>=
+switch (type(p)) {
+case mp_fill_code:
+ mp_toss_knot_list(mp, path_p(p));
+ if ( pen_p(p)!=null ) mp_toss_knot_list(mp, pen_p(p));
+ if ( pre_script(p)!=null ) delete_str_ref(pre_script(p));
+ if ( post_script(p)!=null ) delete_str_ref(post_script(p));
+ break;
+case mp_stroked_code:
+ mp_toss_knot_list(mp, path_p(p));
+ if ( pen_p(p)!=null ) mp_toss_knot_list(mp, pen_p(p));
+ if ( pre_script(p)!=null ) delete_str_ref(pre_script(p));
+ if ( post_script(p)!=null ) delete_str_ref(post_script(p));
+ e=dash_p(p);
+ break;
+case mp_text_code:
+ delete_str_ref(text_p(p));
+ if ( pre_script(p)!=null ) delete_str_ref(pre_script(p));
+ if ( post_script(p)!=null ) delete_str_ref(post_script(p));
+ break;
+case mp_start_clip_code:
+case mp_start_bounds_code:
+ mp_toss_knot_list(mp, path_p(p));
+ break;
+case mp_stop_clip_code:
+case mp_stop_bounds_code:
+ break;
+} /* there are no other cases */
+
+@ If we use |add_edge_ref| to ``copy'' edge structures, the real copying needs
+to be done before making a significant change to an edge structure. Much of
+the work is done in a separate routine |copy_objects| that copies a list of
+graphical objects into a new edge header.
+
+@c @<Declare a function called |copy_objects|@>
+pointer mp_private_edges (MP mp,pointer h) {
+ /* make a private copy of the edge structure headed by |h| */
+ pointer hh; /* the edge header for the new copy */
+ pointer p,pp; /* pointers for copying the dash list */
+ if ( ref_count(h)==null ) {
+ return h;
+ } else {
+ decr(ref_count(h));
+ hh=mp_copy_objects(mp, link(dummy_loc(h)),null);
+ @<Copy the dash list from |h| to |hh|@>;
+ @<Copy the bounding box information from |h| to |hh| and make |bblast(hh)|
+ point into the new object list@>;
+ return hh;
+ }
+}
+
+@ Here we use the fact that |dash_list(hh)=link(hh)|.
+@^data structure assumptions@>
+
+@<Copy the dash list from |h| to |hh|@>=
+pp=hh; p=dash_list(h);
+while ( (p!=null_dash) ) {
+ link(pp)=mp_get_node(mp, dash_node_size);
+ pp=link(pp);
+ start_x(pp)=start_x(p);
+ stop_x(pp)=stop_x(p);
+ p=link(p);
+}
+link(pp)=null_dash;
+dash_y(hh)=dash_y(h)
+
+
+@ |h| is an edge structure
+
+@c
+mp_dash_object *mp_export_dashes (MP mp, pointer h) {
+ mp_dash_object *d;
+ pointer p;
+ scaled *dashes = NULL;
+ int num_dashes = 1;
+ if (h==null || dash_list(h)==null_dash)
+ return NULL;
+ p = dash_list(h);
+ d = mp_xmalloc(mp,1,sizeof(mp_dash_object));
+ start_x(null_dash)=start_x(p)+dash_y(h);
+ while (p != null_dash) {
+ dashes = mp_xrealloc(mp, dashes, num_dashes+2, sizeof(scaled));
+ dashes[(num_dashes-1)] = (stop_x(p)-start_x(p));
+ dashes[(num_dashes)] = (start_x(link(p))-stop_x(p));
+ dashes[(num_dashes+1)] = -1; /* terminus */
+ num_dashes+=2;
+ p=link(p);
+ }
+ d->array_field = dashes;
+ d->offset_field = mp_dash_offset(mp, h);
+ d->scale_field = dash_scale(h);
+ return d;
+}
+
+
+
+@ @<Copy the bounding box information from |h| to |hh|...@>=
+minx_val(hh)=minx_val(h);
+miny_val(hh)=miny_val(h);
+maxx_val(hh)=maxx_val(h);
+maxy_val(hh)=maxy_val(h);
+bbtype(hh)=bbtype(h);
+p=dummy_loc(h); pp=dummy_loc(hh);
+while ((p!=bblast(h)) ) {
+ if ( p==null ) mp_confusion(mp, "bblast");
+@:this can't happen bblast}{\quad bblast@>
+ p=link(p); pp=link(pp);
+}
+bblast(hh)=pp
+
+@ Here is the promised routine for copying graphical objects into a new edge
+structure. It starts copying at object~|p| and stops just before object~|q|.
+If |q| is null, it copies the entire sublist headed at |p|. The resulting edge
+structure requires further initialization by |init_bbox|.
+
+@<Declare a function called |copy_objects|@>=
+pointer mp_copy_objects (MP mp, pointer p, pointer q) {
+ pointer hh; /* the new edge header */
+ pointer pp; /* the last newly copied object */
+ small_number k; /* temporary register */
+ hh=mp_get_node(mp, edge_header_size);
+ dash_list(hh)=null_dash;
+ ref_count(hh)=null;
+ pp=dummy_loc(hh);
+ while ( (p!=q) ) {
+ @<Make |link(pp)| point to a copy of object |p|, and update |p| and |pp|@>;
+ }
+ obj_tail(hh)=pp;
+ link(pp)=null;
+ return hh;
+}
+
+@ @<Make |link(pp)| point to a copy of object |p|, and update |p| and |pp|@>=
+{ k=mp->gr_object_size[type(p)];
+ link(pp)=mp_get_node(mp, k);
+ pp=link(pp);
+ while ( (k>0) ) { decr(k); mp->mem[pp+k]=mp->mem[p+k]; };
+ @<Fix anything in graphical object |pp| that should differ from the
+ corresponding field in |p|@>;
+ p=link(p);
+}
+
+@ @<Fix anything in graphical object |pp| that should differ from the...@>=
+if ( pre_script(p)!=null ) add_str_ref(pre_script(p));
+if ( post_script(p)!=null ) add_str_ref(post_script(p));
+switch (type(p)) {
+case mp_start_clip_code:
+case mp_start_bounds_code:
+ path_p(pp)=mp_copy_path(mp, path_p(p));
+ break;
+case mp_fill_code:
+ path_p(pp)=mp_copy_path(mp, path_p(p));
+ if ( pen_p(p)!=null ) pen_p(pp)=copy_pen(pen_p(p));
+ break;
+case mp_stroked_code:
+ path_p(pp)=mp_copy_path(mp, path_p(p));
+ pen_p(pp)=copy_pen(pen_p(p));
+ if ( dash_p(p)!=null ) add_edge_ref(dash_p(pp));
+ break;
+case mp_text_code:
+ add_str_ref(text_p(pp));
+ break;
+case mp_stop_clip_code:
+case mp_stop_bounds_code:
+ break;
+} /* there are no other cases */
+
+@ Here is one way to find an acceptable value for the second argument to
+|copy_objects|. Given a non-null graphical object list, |skip_1component|
+skips past one picture component, where a ``picture component'' is a single
+graphical object, or a start bounds or start clip object and everything up
+through the matching stop bounds or stop clip object. The macro version avoids
+procedure call overhead and error handling: |skip_component(p)(e)| advances |p|
+unless |p| points to a stop bounds or stop clip node, in which case it executes
+|e| instead.
+
+@d skip_component(A)
+ if ( ! is_start_or_stop((A)) ) (A)=link((A));
+ else if ( ! is_stop((A)) ) (A)=mp_skip_1component(mp, (A));
+ else
+
+@c
+pointer mp_skip_1component (MP mp,pointer p) {
+ integer lev; /* current nesting level */
+ lev=0;
+ do {
+ if ( is_start_or_stop(p) ) {
+ if ( is_stop(p) ) decr(lev); else incr(lev);
+ }
+ p=link(p);
+ } while (lev!=0);
+ return p;
+}
+
+@ Here is a diagnostic routine for printing an edge structure in symbolic form.
+
+@<Declare subroutines for printing expressions@>=
+@<Declare subroutines needed by |print_edges|@>
+void mp_print_edges (MP mp,pointer h, const char *s, boolean nuline) {
+ pointer p; /* a graphical object to be printed */
+ pointer hh,pp; /* temporary pointers */
+ scaled scf; /* a scale factor for the dash pattern */
+ boolean ok_to_dash; /* |false| for polygonal pen strokes */
+ mp_print_diagnostic(mp, "Edge structure",s,nuline);
+ p=dummy_loc(h);
+ while ( link(p)!=null ) {
+ p=link(p);
+ mp_print_ln(mp);
+ switch (type(p)) {
+ @<Cases for printing graphical object node |p|@>;
+ default:
+ mp_print(mp, "[unknown object type!]");
+ break;
+ }
+ }
+ mp_print_nl(mp, "End edges");
+ if ( p!=obj_tail(h) ) mp_print(mp, "?");
+@.End edges?@>
+ mp_end_diagnostic(mp, true);
+}
+
+@ @<Cases for printing graphical object node |p|@>=
+case mp_fill_code:
+ mp_print(mp, "Filled contour ");
+ mp_print_obj_color(mp, p);
+ mp_print_char(mp, ':'); mp_print_ln(mp);
+ mp_pr_path(mp, path_p(p)); mp_print_ln(mp);
+ if ( (pen_p(p)!=null) ) {
+ @<Print join type for graphical object |p|@>;
+ mp_print(mp, " with pen"); mp_print_ln(mp);
+ mp_pr_pen(mp, pen_p(p));
+ }
+ break;
+
+@ @<Print join type for graphical object |p|@>=
+switch (ljoin_val(p)) {
+case 0:
+ mp_print(mp, "mitered joins limited ");
+ mp_print_scaled(mp, miterlim_val(p));
+ break;
+case 1:
+ mp_print(mp, "round joins");
+ break;
+case 2:
+ mp_print(mp, "beveled joins");
+ break;
+default:
+ mp_print(mp, "?? joins");
+@.??@>
+ break;
+}
+
+@ For stroked nodes, we need to print |lcap_val(p)| as well.
+
+@<Print join and cap types for stroked node |p|@>=
+switch (lcap_val(p)) {
+case 0:mp_print(mp, "butt"); break;
+case 1:mp_print(mp, "round"); break;
+case 2:mp_print(mp, "square"); break;
+default: mp_print(mp, "??"); break;
+@.??@>
+}
+mp_print(mp, " ends, ");
+@<Print join type for graphical object |p|@>
+
+@ Here is a routine that prints the color of a graphical object if it isn't
+black (the default color).
+
+@<Declare subroutines needed by |print_edges|@>=
+@<Declare a procedure called |print_compact_node|@>
+void mp_print_obj_color (MP mp,pointer p) {
+ if ( color_model(p)==mp_grey_model ) {
+ if ( grey_val(p)>0 ) {
+ mp_print(mp, "greyed ");
+ mp_print_compact_node(mp, obj_grey_loc(p),1);
+ };
+ } else if ( color_model(p)==mp_cmyk_model ) {
+ if ( (cyan_val(p)>0) || (magenta_val(p)>0) ||
+ (yellow_val(p)>0) || (black_val(p)>0) ) {
+ mp_print(mp, "processcolored ");
+ mp_print_compact_node(mp, obj_cyan_loc(p),4);
+ };
+ } else if ( color_model(p)==mp_rgb_model ) {
+ if ( (red_val(p)>0) || (green_val(p)>0) || (blue_val(p)>0) ) {
+ mp_print(mp, "colored ");
+ mp_print_compact_node(mp, obj_red_loc(p),3);
+ };
+ }
+}
+
+@ We also need a procedure for printing consecutive scaled values as if they
+were a known big node.
+
+@<Declare a procedure called |print_compact_node|@>=
+void mp_print_compact_node (MP mp,pointer p, small_number k) {
+ pointer q; /* last location to print */
+ q=p+k-1;
+ mp_print_char(mp, '(');
+ while ( p<=q ){
+ mp_print_scaled(mp, mp->mem[p].sc);
+ if ( p<q ) mp_print_char(mp, ',');
+ incr(p);
+ }
+ mp_print_char(mp, ')');
+}
+
+@ @<Cases for printing graphical object node |p|@>=
+case mp_stroked_code:
+ mp_print(mp, "Filled pen stroke ");
+ mp_print_obj_color(mp, p);
+ mp_print_char(mp, ':'); mp_print_ln(mp);
+ mp_pr_path(mp, path_p(p));
+ if ( dash_p(p)!=null ) {
+ mp_print_nl(mp, "dashed (");
+ @<Finish printing the dash pattern that |p| refers to@>;
+ }
+ mp_print_ln(mp);
+ @<Print join and cap types for stroked node |p|@>;
+ mp_print(mp, " with pen"); mp_print_ln(mp);
+ if ( pen_p(p)==null ) mp_print(mp, "???"); /* shouldn't happen */
+@.???@>
+ else mp_pr_pen(mp, pen_p(p));
+ break;
+
+@ Normally, the |dash_list| field in an edge header is set to |null_dash|
+when it is not known to define a suitable dash pattern. This is disallowed
+here because the |dash_p| field should never point to such an edge header.
+Note that memory is allocated for |start_x(null_dash)| and we are free to
+give it any convenient value.
+
+@<Finish printing the dash pattern that |p| refers to@>=
+ok_to_dash=pen_is_elliptical(pen_p(p));
+if ( ! ok_to_dash ) scf=unity; else scf=dash_scale(p);
+hh=dash_p(p);
+pp=dash_list(hh);
+if ( (pp==null_dash) || (dash_y(hh)<0) ) {
+ mp_print(mp, " ??");
+} else { start_x(null_dash)=start_x(pp)+dash_y(hh);
+ while ( pp!=null_dash ) {
+ mp_print(mp, "on ");
+ mp_print_scaled(mp, mp_take_scaled(mp, stop_x(pp)-start_x(pp),scf));
+ mp_print(mp, " off ");
+ mp_print_scaled(mp, mp_take_scaled(mp, start_x(link(pp))-stop_x(pp),scf));
+ pp = link(pp);
+ if ( pp!=null_dash ) mp_print_char(mp, ' ');
+ }
+ mp_print(mp, ") shifted ");
+ mp_print_scaled(mp, -mp_take_scaled(mp, mp_dash_offset(mp, hh),scf));
+ if ( ! ok_to_dash || (dash_y(hh)==0) ) mp_print(mp, " (this will be ignored)");
+}
+
+@ @<Declare subroutines needed by |print_edges|@>=
+scaled mp_dash_offset (MP mp,pointer h) {
+ scaled x; /* the answer */
+ if (dash_list(h)==null_dash || dash_y(h)<0) mp_confusion(mp, "dash0");
+@:this can't happen dash0}{\quad dash0@>
+ if ( dash_y(h)==0 ) {
+ x=0;
+ } else {
+ x=-(start_x(dash_list(h)) % dash_y(h));
+ if ( x<0 ) x=x+dash_y(h);
+ }
+ return x;
+}
+
+@ @<Cases for printing graphical object node |p|@>=
+case mp_text_code:
+ mp_print_char(mp, '"'); mp_print_str(mp,text_p(p));
+ mp_print(mp, "\" infont \""); mp_print(mp, mp->font_name[font_n(p)]);
+ mp_print_char(mp, '"'); mp_print_ln(mp);
+ mp_print_obj_color(mp, p);
+ mp_print(mp, "transformed ");
+ mp_print_compact_node(mp, text_tx_loc(p),6);
+ break;
+
+@ @<Cases for printing graphical object node |p|@>=
+case mp_start_clip_code:
+ mp_print(mp, "clipping path:");
+ mp_print_ln(mp);
+ mp_pr_path(mp, path_p(p));
+ break;
+case mp_stop_clip_code:
+ mp_print(mp, "stop clipping");
+ break;
+
+@ @<Cases for printing graphical object node |p|@>=
+case mp_start_bounds_code:
+ mp_print(mp, "setbounds path:");
+ mp_print_ln(mp);
+ mp_pr_path(mp, path_p(p));
+ break;
+case mp_stop_bounds_code:
+ mp_print(mp, "end of setbounds");
+ break;
+
+@ To initialize the |dash_list| field in an edge header~|h|, we need a
+subroutine that scans an edge structure and tries to interpret it as a dash
+pattern. This can only be done when there are no filled regions or clipping
+paths and all the pen strokes have the same color. The first step is to let
+$y_0$ be the initial $y$~coordinate of the first pen stroke. Then we implicitly
+project all the pen stroke paths onto the line $y=y_0$ and require that there
+be no retracing. If the resulting paths cover a range of $x$~coordinates of
+length $\Delta x$, we set |dash_y(h)| to the length of the dash pattern by
+finding the maximum of $\Delta x$ and the absolute value of~$y_0$.
+
+@c @<Declare a procedure called |x_retrace_error|@>
+pointer mp_make_dashes (MP mp,pointer h) { /* returns |h| or |null| */
+ pointer p; /* this scans the stroked nodes in the object list */
+ pointer p0; /* if not |null| this points to the first stroked node */
+ pointer pp,qq,rr; /* pointers into |path_p(p)| */
+ pointer d,dd; /* pointers used to create the dash list */
+ scaled y0;
+ @<Other local variables in |make_dashes|@>;
+ y0=0; /* the initial $y$ coordinate */
+ if ( dash_list(h)!=null_dash )
+ return h;
+ p0=null;
+ p=link(dummy_loc(h));
+ while ( p!=null ) {
+ if ( type(p)!=mp_stroked_code ) {
+ @<Compain that the edge structure contains a node of the wrong type
+ and |goto not_found|@>;
+ }
+ pp=path_p(p);
+ if ( p0==null ){ p0=p; y0=y_coord(pp); };
+ @<Make |d| point to a new dash node created from stroke |p| and path |pp|
+ or |goto not_found| if there is an error@>;
+ @<Insert |d| into the dash list and |goto not_found| if there is an error@>;
+ p=link(p);
+ }
+ if ( dash_list(h)==null_dash )
+ goto NOT_FOUND; /* No error message */
+ @<Scan |dash_list(h)| and deal with any dashes that are themselves dashed@>;
+ @<Set |dash_y(h)| and merge the first and last dashes if necessary@>;
+ return h;
+NOT_FOUND:
+ @<Flush the dash list, recycle |h| and return |null|@>;
+}
+
+@ @<Compain that the edge structure contains a node of the wrong type...@>=
+{
+print_err("Picture is too complicated to use as a dash pattern");
+help3("When you say `dashed p', picture p should not contain any")
+ ("text, filled regions, or clipping paths. This time it did")
+ ("so I'll just make it a solid line instead.");
+mp_put_get_error(mp);
+goto NOT_FOUND;
+}
+
+@ A similar error occurs when monotonicity fails.
+
+@<Declare a procedure called |x_retrace_error|@>=
+void mp_x_retrace_error (MP mp) {
+print_err("Picture is too complicated to use as a dash pattern");
+help3("When you say `dashed p', every path in p should be monotone")
+ ("in x and there must be no overlapping. This failed")
+ ("so I'll just make it a solid line instead.");
+mp_put_get_error(mp);
+}
+
+@ We stash |p| in |info(d)| if |dash_p(p)<>0| so that subsequent processing can
+handle the case where the pen stroke |p| is itself dashed.
+
+@<Make |d| point to a new dash node created from stroke |p| and path...@>=
+@<Make sure |p| and |p0| are the same color and |goto not_found| if there is
+ an error@>;
+rr=pp;
+if ( link(pp)!=pp ) {
+ do {
+ qq=rr; rr=link(rr);
+ @<Check for retracing between knots |qq| and |rr| and |goto not_found|
+ if there is a problem@>;
+ } while (right_type(rr)!=mp_endpoint);
+}
+d=mp_get_node(mp, dash_node_size);
+if ( dash_p(p)==0 ) info(d)=0; else info(d)=p;
+if ( x_coord(pp)<x_coord(rr) ) {
+ start_x(d)=x_coord(pp);
+ stop_x(d)=x_coord(rr);
+} else {
+ start_x(d)=x_coord(rr);
+ stop_x(d)=x_coord(pp);
+}
+
+@ We also need to check for the case where the segment from |qq| to |rr| is
+monotone in $x$ but is reversed relative to the path from |pp| to |qq|.
+
+@<Check for retracing between knots |qq| and |rr| and |goto not_found|...@>=
+x0=x_coord(qq);
+x1=right_x(qq);
+x2=left_x(rr);
+x3=x_coord(rr);
+if ( (x0>x1) || (x1>x2) || (x2>x3) ) {
+ if ( (x0<x1) || (x1<x2) || (x2<x3) ) {
+ if ( mp_ab_vs_cd(mp, x2-x1,x2-x1,x1-x0,x3-x2)>0 ) {
+ mp_x_retrace_error(mp); goto NOT_FOUND;
+ }
+ }
+}
+if ( (x_coord(pp)>x0) || (x0>x3) ) {
+ if ( (x_coord(pp)<x0) || (x0<x3) ) {
+ mp_x_retrace_error(mp); goto NOT_FOUND;
+ }
+}
+
+@ @<Other local variables in |make_dashes|@>=
+ scaled x0,x1,x2,x3; /* $x$ coordinates of the segment from |qq| to |rr| */
+
+@ @<Make sure |p| and |p0| are the same color and |goto not_found|...@>=
+if ( (red_val(p)!=red_val(p0)) || (black_val(p)!=black_val(p0)) ||
+ (green_val(p)!=green_val(p0)) || (blue_val(p)!=blue_val(p0)) ) {
+ print_err("Picture is too complicated to use as a dash pattern");
+ help3("When you say `dashed p', everything in picture p should")
+ ("be the same color. I can\'t handle your color changes")
+ ("so I'll just make it a solid line instead.");
+ mp_put_get_error(mp);
+ goto NOT_FOUND;
+}
+
+@ @<Insert |d| into the dash list and |goto not_found| if there is an error@>=
+start_x(null_dash)=stop_x(d);
+dd=h; /* this makes |link(dd)=dash_list(h)| */
+while ( start_x(link(dd))<stop_x(d) )
+ dd=link(dd);
+if ( dd!=h ) {
+ if ( (stop_x(dd)>start_x(d)) )
+ { mp_x_retrace_error(mp); goto NOT_FOUND; };
+}
+link(d)=link(dd);
+link(dd)=d
+
+@ @<Set |dash_y(h)| and merge the first and last dashes if necessary@>=
+d=dash_list(h);
+while ( (link(d)!=null_dash) )
+ d=link(d);
+dd=dash_list(h);
+dash_y(h)=stop_x(d)-start_x(dd);
+if ( abs(y0)>dash_y(h) ) {
+ dash_y(h)=abs(y0);
+} else if ( d!=dd ) {
+ dash_list(h)=link(dd);
+ stop_x(d)=stop_x(dd)+dash_y(h);
+ mp_free_node(mp, dd,dash_node_size);
+}
+
+@ We get here when the argument is a null picture or when there is an error.
+Recovering from an error involves making |dash_list(h)| empty to indicate
+that |h| is not known to be a valid dash pattern. We also dereference |h|
+since it is not being used for the return value.
+
+@<Flush the dash list, recycle |h| and return |null|@>=
+mp_flush_dash_list(mp, h);
+delete_edge_ref(h);
+return null
+
+@ Having carefully saved the dashed stroked nodes in the
+corresponding dash nodes, we must be prepared to break up these dashes into
+smaller dashes.
+
+@<Scan |dash_list(h)| and deal with any dashes that are themselves dashed@>=
+d=h; /* now |link(d)=dash_list(h)| */
+while ( link(d)!=null_dash ) {
+ ds=info(link(d));
+ if ( ds==null ) {
+ d=link(d);
+ } else {
+ hh=dash_p(ds);
+ hsf=dash_scale(ds);
+ if ( (hh==null) ) mp_confusion(mp, "dash1");
+@:this can't happen dash0}{\quad dash1@>
+ if ( dash_y(hh)==0 ) {
+ d=link(d);
+ } else {
+ if ( dash_list(hh)==null ) mp_confusion(mp, "dash1");
+@:this can't happen dash0}{\quad dash1@>
+ @<Replace |link(d)| by a dashed version as determined by edge header
+ |hh| and scale factor |ds|@>;
+ }
+ }
+}
+
+@ @<Other local variables in |make_dashes|@>=
+pointer dln; /* |link(d)| */
+pointer hh; /* an edge header that tells how to break up |dln| */
+scaled hsf; /* the dash pattern from |hh| gets scaled by this */
+pointer ds; /* the stroked node from which |hh| and |hsf| are derived */
+scaled xoff; /* added to $x$ values in |dash_list(hh)| to match |dln| */
+
+@ @<Replace |link(d)| by a dashed version as determined by edge header...@>=
+dln=link(d);
+dd=dash_list(hh);
+xoff=start_x(dln)-mp_take_scaled(mp, hsf,start_x(dd))-
+ mp_take_scaled(mp, hsf,mp_dash_offset(mp, hh));
+start_x(null_dash)=mp_take_scaled(mp, hsf,start_x(dd))
+ +mp_take_scaled(mp, hsf,dash_y(hh));
+stop_x(null_dash)=start_x(null_dash);
+@<Advance |dd| until finding the first dash that overlaps |dln| when
+ offset by |xoff|@>;
+while ( start_x(dln)<=stop_x(dln) ) {
+ @<If |dd| has `fallen off the end', back up to the beginning and fix |xoff|@>;
+ @<Insert a dash between |d| and |dln| for the overlap with the offset version
+ of |dd|@>;
+ dd=link(dd);
+ start_x(dln)=xoff+mp_take_scaled(mp, hsf,start_x(dd));
+}
+link(d)=link(dln);
+mp_free_node(mp, dln,dash_node_size)
+
+@ The name of this module is a bit of a lie because we just find the
+first |dd| where |take_scaled (hsf, stop_x(dd))| is large enough to make an
+overlap possible. It could be that the unoffset version of dash |dln| falls
+in the gap between |dd| and its predecessor.
+
+@<Advance |dd| until finding the first dash that overlaps |dln| when...@>=
+while ( xoff+mp_take_scaled(mp, hsf,stop_x(dd))<start_x(dln) ) {
+ dd=link(dd);
+}
+
+@ @<If |dd| has `fallen off the end', back up to the beginning and fix...@>=
+if ( dd==null_dash ) {
+ dd=dash_list(hh);
+ xoff=xoff+mp_take_scaled(mp, hsf,dash_y(hh));
+}
+
+@ At this point we already know that
+|start_x(dln)<=xoff+take_scaled(hsf,stop_x(dd))|.
+
+@<Insert a dash between |d| and |dln| for the overlap with the offset...@>=
+if ( (xoff+mp_take_scaled(mp, hsf,start_x(dd)))<=stop_x(dln) ) {
+ link(d)=mp_get_node(mp, dash_node_size);
+ d=link(d);
+ link(d)=dln;
+ if ( start_x(dln)>(xoff+mp_take_scaled(mp, hsf,start_x(dd))))
+ start_x(d)=start_x(dln);
+ else
+ start_x(d)=xoff+mp_take_scaled(mp, hsf,start_x(dd));
+ if ( stop_x(dln)<(xoff+mp_take_scaled(mp, hsf,stop_x(dd))))
+ stop_x(d)=stop_x(dln);
+ else
+ stop_x(d)=xoff+mp_take_scaled(mp, hsf,stop_x(dd));
+}
+
+@ The next major task is to update the bounding box information in an edge
+header~|h|. This is done via a procedure |adjust_bbox| that enlarges an edge
+header's bounding box to accommodate the box computed by |path_bbox| or
+|pen_bbox|. (This is stored in global variables |minx|, |miny|, |maxx|, and
+|maxy|.)
+
+@c void mp_adjust_bbox (MP mp,pointer h) {
+ if ( minx<minx_val(h) ) minx_val(h)=minx;
+ if ( miny<miny_val(h) ) miny_val(h)=miny;
+ if ( maxx>maxx_val(h) ) maxx_val(h)=maxx;
+ if ( maxy>maxy_val(h) ) maxy_val(h)=maxy;
+}
+
+@ Here is a special routine for updating the bounding box information in
+edge header~|h| to account for the squared-off ends of a non-cyclic path~|p|
+that is to be stroked with the pen~|pp|.
+
+@c void mp_box_ends (MP mp, pointer p, pointer pp, pointer h) {
+ pointer q; /* a knot node adjacent to knot |p| */
+ fraction dx,dy; /* a unit vector in the direction out of the path at~|p| */
+ scaled d; /* a factor for adjusting the length of |(dx,dy)| */
+ scaled z; /* a coordinate being tested against the bounding box */
+ scaled xx,yy; /* the extreme pen vertex in the |(dx,dy)| direction */
+ integer i; /* a loop counter */
+ if ( right_type(p)!=mp_endpoint ) {
+ q=link(p);
+ while (1) {
+ @<Make |(dx,dy)| the final direction for the path segment from
+ |q| to~|p|; set~|d|@>;
+ d=mp_pyth_add(mp, dx,dy);
+ if ( d>0 ) {
+ @<Normalize the direction |(dx,dy)| and find the pen offset |(xx,yy)|@>;
+ for (i=1;i<= 2;i++) {
+ @<Use |(dx,dy)| to generate a vertex of the square end cap and
+ update the bounding box to accommodate it@>;
+ dx=-dx; dy=-dy;
+ }
+ }
+ if ( right_type(p)==mp_endpoint ) {
+ return;
+ } else {
+ @<Advance |p| to the end of the path and make |q| the previous knot@>;
+ }
+ }
+ }
+}
+
+@ @<Make |(dx,dy)| the final direction for the path segment from...@>=
+if ( q==link(p) ) {
+ dx=x_coord(p)-right_x(p);
+ dy=y_coord(p)-right_y(p);
+ if ( (dx==0)&&(dy==0) ) {
+ dx=x_coord(p)-left_x(q);
+ dy=y_coord(p)-left_y(q);
+ }
+} else {
+ dx=x_coord(p)-left_x(p);
+ dy=y_coord(p)-left_y(p);
+ if ( (dx==0)&&(dy==0) ) {
+ dx=x_coord(p)-right_x(q);
+ dy=y_coord(p)-right_y(q);
+ }
+}
+dx=x_coord(p)-x_coord(q);
+dy=y_coord(p)-y_coord(q)
+
+@ @<Normalize the direction |(dx,dy)| and find the pen offset |(xx,yy)|@>=
+dx=mp_make_fraction(mp, dx,d);
+dy=mp_make_fraction(mp, dy,d);
+mp_find_offset(mp, -dy,dx,pp);
+xx=mp->cur_x; yy=mp->cur_y
+
+@ @<Use |(dx,dy)| to generate a vertex of the square end cap and...@>=
+mp_find_offset(mp, dx,dy,pp);
+d=mp_take_fraction(mp, xx-mp->cur_x,dx)+mp_take_fraction(mp, yy-mp->cur_y,dy);
+if ( ((d<0)&&(i==1)) || ((d>0)&&(i==2)))
+ mp_confusion(mp, "box_ends");
+@:this can't happen box ends}{\quad\\{box\_ends}@>
+z=x_coord(p)+mp->cur_x+mp_take_fraction(mp, d,dx);
+if ( z<minx_val(h) ) minx_val(h)=z;
+if ( z>maxx_val(h) ) maxx_val(h)=z;
+z=y_coord(p)+mp->cur_y+mp_take_fraction(mp, d,dy);
+if ( z<miny_val(h) ) miny_val(h)=z;
+if ( z>maxy_val(h) ) maxy_val(h)=z
+
+@ @<Advance |p| to the end of the path and make |q| the previous knot@>=
+do {
+ q=p;
+ p=link(p);
+} while (right_type(p)!=mp_endpoint)
+
+@ The major difficulty in finding the bounding box of an edge structure is the
+effect of clipping paths. We treat them conservatively by only clipping to the
+clipping path's bounding box, but this still
+requires recursive calls to |set_bbox| in order to find the bounding box of
+@^recursion@>
+the objects to be clipped. Such calls are distinguished by the fact that the
+boolean parameter |top_level| is false.
+
+@c void mp_set_bbox (MP mp,pointer h, boolean top_level) {
+ pointer p; /* a graphical object being considered */
+ scaled sminx,sminy,smaxx,smaxy;
+ /* for saving the bounding box during recursive calls */
+ scaled x0,x1,y0,y1; /* temporary registers */
+ integer lev; /* nesting level for |mp_start_bounds_code| nodes */
+ @<Wipe out any existing bounding box information if |bbtype(h)| is
+ incompatible with |internal[mp_true_corners]|@>;
+ while ( link(bblast(h))!=null ) {
+ p=link(bblast(h));
+ bblast(h)=p;
+ switch (type(p)) {
+ case mp_stop_clip_code:
+ if ( top_level ) mp_confusion(mp, "bbox"); else return;
+@:this can't happen bbox}{\quad bbox@>
+ break;
+ @<Other cases for updating the bounding box based on the type of object |p|@>;
+ } /* all cases are enumerated above */
+ }
+ if ( ! top_level ) mp_confusion(mp, "bbox");
+}
+
+@ @<Internal library declarations@>=
+void mp_set_bbox (MP mp,pointer h, boolean top_level);
+
+@ @<Wipe out any existing bounding box information if |bbtype(h)| is...@>=
+switch (bbtype(h)) {
+case no_bounds:
+ break;
+case bounds_set:
+ if ( mp->internal[mp_true_corners]>0 ) mp_init_bbox(mp, h);
+ break;
+case bounds_unset:
+ if ( mp->internal[mp_true_corners]<=0 ) mp_init_bbox(mp, h);
+ break;
+} /* there are no other cases */
+
+@ @<Other cases for updating the bounding box...@>=
+case mp_fill_code:
+ mp_path_bbox(mp, path_p(p));
+ if ( pen_p(p)!=null ) {
+ x0=minx; y0=miny;
+ x1=maxx; y1=maxy;
+ mp_pen_bbox(mp, pen_p(p));
+ minx=minx+x0;
+ miny=miny+y0;
+ maxx=maxx+x1;
+ maxy=maxy+y1;
+ }
+ mp_adjust_bbox(mp, h);
+ break;
+
+@ @<Other cases for updating the bounding box...@>=
+case mp_start_bounds_code:
+ if ( mp->internal[mp_true_corners]>0 ) {
+ bbtype(h)=bounds_unset;
+ } else {
+ bbtype(h)=bounds_set;
+ mp_path_bbox(mp, path_p(p));
+ mp_adjust_bbox(mp, h);
+ @<Scan to the matching |mp_stop_bounds_code| node and update |p| and
+ |bblast(h)|@>;
+ }
+ break;
+case mp_stop_bounds_code:
+ if ( mp->internal[mp_true_corners]<=0 ) mp_confusion(mp, "bbox2");
+@:this can't happen bbox2}{\quad bbox2@>
+ break;
+
+@ @<Scan to the matching |mp_stop_bounds_code| node and update |p| and...@>=
+lev=1;
+while ( lev!=0 ) {
+ if ( link(p)==null ) mp_confusion(mp, "bbox2");
+@:this can't happen bbox2}{\quad bbox2@>
+ p=link(p);
+ if ( type(p)==mp_start_bounds_code ) incr(lev);
+ else if ( type(p)==mp_stop_bounds_code ) decr(lev);
+}
+bblast(h)=p
+
+@ It saves a lot of grief here to be slightly conservative and not account for
+omitted parts of dashed lines. We also don't worry about the material omitted
+when using butt end caps. The basic computation is for round end caps and
+|box_ends| augments it for square end caps.
+
+@<Other cases for updating the bounding box...@>=
+case mp_stroked_code:
+ mp_path_bbox(mp, path_p(p));
+ x0=minx; y0=miny;
+ x1=maxx; y1=maxy;
+ mp_pen_bbox(mp, pen_p(p));
+ minx=minx+x0;
+ miny=miny+y0;
+ maxx=maxx+x1;
+ maxy=maxy+y1;
+ mp_adjust_bbox(mp, h);
+ if ( (left_type(path_p(p))==mp_endpoint)&&(lcap_val(p)==2) )
+ mp_box_ends(mp, path_p(p), pen_p(p), h);
+ break;
+
+@ The height width and depth information stored in a text node determines a
+rectangle that needs to be transformed according to the transformation
+parameters stored in the text node.
+
+@<Other cases for updating the bounding box...@>=
+case mp_text_code:
+ x1=mp_take_scaled(mp, txx_val(p),width_val(p));
+ y0=mp_take_scaled(mp, txy_val(p),-depth_val(p));
+ y1=mp_take_scaled(mp, txy_val(p),height_val(p));
+ minx=tx_val(p);
+ maxx=minx;
+ if ( y0<y1 ) { minx=minx+y0; maxx=maxx+y1; }
+ else { minx=minx+y1; maxx=maxx+y0; }
+ if ( x1<0 ) minx=minx+x1; else maxx=maxx+x1;
+ x1=mp_take_scaled(mp, tyx_val(p),width_val(p));
+ y0=mp_take_scaled(mp, tyy_val(p),-depth_val(p));
+ y1=mp_take_scaled(mp, tyy_val(p),height_val(p));
+ miny=ty_val(p);
+ maxy=miny;
+ if ( y0<y1 ) { miny=miny+y0; maxy=maxy+y1; }
+ else { miny=miny+y1; maxy=maxy+y0; }
+ if ( x1<0 ) miny=miny+x1; else maxy=maxy+x1;
+ mp_adjust_bbox(mp, h);
+ break;
+
+@ This case involves a recursive call that advances |bblast(h)| to the node of
+type |mp_stop_clip_code| that matches |p|.
+
+@<Other cases for updating the bounding box...@>=
+case mp_start_clip_code:
+ mp_path_bbox(mp, path_p(p));
+ x0=minx; y0=miny;
+ x1=maxx; y1=maxy;
+ sminx=minx_val(h); sminy=miny_val(h);
+ smaxx=maxx_val(h); smaxy=maxy_val(h);
+ @<Reinitialize the bounding box in header |h| and call |set_bbox| recursively
+ starting at |link(p)|@>;
+ @<Clip the bounding box in |h| to the rectangle given by |x0|, |x1|,
+ |y0|, |y1|@>;
+ minx=sminx; miny=sminy;
+ maxx=smaxx; maxy=smaxy;
+ mp_adjust_bbox(mp, h);
+ break;
+
+@ @<Reinitialize the bounding box in header |h| and call |set_bbox|...@>=
+minx_val(h)=el_gordo;
+miny_val(h)=el_gordo;
+maxx_val(h)=-el_gordo;
+maxy_val(h)=-el_gordo;
+mp_set_bbox(mp, h,false)
+
+@ @<Clip the bounding box in |h| to the rectangle given by |x0|, |x1|,...@>=
+if ( minx_val(h)<x0 ) minx_val(h)=x0;
+if ( miny_val(h)<y0 ) miny_val(h)=y0;
+if ( maxx_val(h)>x1 ) maxx_val(h)=x1;
+if ( maxy_val(h)>y1 ) maxy_val(h)=y1
+
+@* \[22] Finding an envelope.
+When \MP\ has a path and a polygonal pen, it needs to express the desired
+shape in terms of things \ps\ can understand. The present task is to compute
+a new path that describes the region to be filled. It is convenient to
+define this as a two step process where the first step is determining what
+offset to use for each segment of the path.
+
+@ Given a pointer |c| to a cyclic path,
+and a pointer~|h| to the first knot of a pen polygon,
+the |offset_prep| routine changes the path into cubics that are
+associated with particular pen offsets. Thus if the cubic between |p|
+and~|q| is associated with the |k|th offset and the cubic between |q| and~|r|
+has offset |l| then |info(q)=zero_off+l-k|. (The constant |zero_off| is added
+to because |l-k| could be negative.)
+
+After overwriting the type information with offset differences, we no longer
+have a true path so we refer to the knot list returned by |offset_prep| as an
+``envelope spec.''
+@^envelope spec@>
+Since an envelope spec only determines relative changes in pen offsets,
+|offset_prep| sets a global variable |spec_offset| to the relative change from
+|h| to the first offset.
+
+@d zero_off 16384 /* added to offset changes to make them positive */
+
+@<Glob...@>=
+integer spec_offset; /* number of pen edges between |h| and the initial offset */
+
+@ @c @<Declare subroutines needed by |offset_prep|@>
+pointer mp_offset_prep (MP mp,pointer c, pointer h) {
+ halfword n; /* the number of vertices in the pen polygon */
+ pointer p,q,q0,r,w, ww; /* for list manipulation */
+ integer k_needed; /* amount to be added to |info(p)| when it is computed */
+ pointer w0; /* a pointer to pen offset to use just before |p| */
+ scaled dxin,dyin; /* the direction into knot |p| */
+ integer turn_amt; /* change in pen offsets for the current cubic */
+ @<Other local variables for |offset_prep|@>;
+ dx0=0; dy0=0;
+ @<Initialize the pen size~|n|@>;
+ @<Initialize the incoming direction and pen offset at |c|@>;
+ p=c; k_needed=0;
+ do {
+ q=link(p);
+ @<Split the cubic between |p| and |q|, if necessary, into cubics
+ associated with single offsets, after which |q| should
+ point to the end of the final such cubic@>;
+ NOT_FOUND:
+ @<Advance |p| to node |q|, removing any ``dead'' cubics that
+ might have been introduced by the splitting process@>;
+ } while (q!=c);
+ @<Fix the offset change in |info(c)| and set |c| to the return value of
+ |offset_prep|@>;
+ return c;
+}
+
+@ We shall want to keep track of where certain knots on the cyclic path
+wind up in the envelope spec. It doesn't suffice just to keep pointers to
+knot nodes because some nodes are deleted while removing dead cubics. Thus
+|offset_prep| updates the following pointers
+
+@<Glob...@>=
+pointer spec_p1;
+pointer spec_p2; /* pointers to distinguished knots */
+
+@ @<Set init...@>=
+mp->spec_p1=null; mp->spec_p2=null;
+
+@ @<Initialize the pen size~|n|@>=
+n=0; p=h;
+do {
+ incr(n);
+ p=link(p);
+} while (p!=h)
+
+@ Since the true incoming direction isn't known yet, we just pick a direction
+consistent with the pen offset~|h|. If this is wrong, it can be corrected
+later.
+
+@<Initialize the incoming direction and pen offset at |c|@>=
+dxin=x_coord(link(h))-x_coord(knil(h));
+dyin=y_coord(link(h))-y_coord(knil(h));
+if ( (dxin==0)&&(dyin==0) ) {
+ dxin=y_coord(knil(h))-y_coord(h);
+ dyin=x_coord(h)-x_coord(knil(h));
+}
+w0=h
+
+@ We must be careful not to remove the only cubic in a cycle.
+
+But we must also be careful for another reason. If the user-supplied
+path starts with a set of degenerate cubics, the target node |q| can
+be collapsed to the initial node |p| which might be the same as the
+initial node |c| of the curve. This would cause the |offset_prep| routine
+to bail out too early, causing distress later on. (See for example
+the testcase reported by Bogus\l{}aw Jackowski in tracker id 267, case 52c
+on Sarovar.)
+
+@<Advance |p| to node |q|, removing any ``dead'' cubics...@>=
+q0=q;
+do {
+ r=link(p);
+ if ( x_coord(p)==right_x(p) && y_coord(p)==right_y(p) &&
+ x_coord(p)==left_x(r) && y_coord(p)==left_y(r) &&
+ x_coord(p)==x_coord(r) && y_coord(p)==y_coord(r) &&
+ r!=p ) {
+ @<Remove the cubic following |p| and update the data structures
+ to merge |r| into |p|@>;
+ }
+ p=r;
+} while (p!=q);
+/* Check if we removed too much */
+if(q!=q0)
+ q = link(q)
+
+@ @<Remove the cubic following |p| and update the data structures...@>=
+{ k_needed=info(p)-zero_off;
+ if ( r==q ) {
+ q=p;
+ } else {
+ info(p)=k_needed+info(r);
+ k_needed=0;
+ };
+ if ( r==c ) { info(p)=info(c); c=p; };
+ if ( r==mp->spec_p1 ) mp->spec_p1=p;
+ if ( r==mp->spec_p2 ) mp->spec_p2=p;
+ r=p; mp_remove_cubic(mp, p);
+}
+
+@ Not setting the |info| field of the newly created knot allows the splitting
+routine to work for paths.
+
+@<Declare subroutines needed by |offset_prep|@>=
+void mp_split_cubic (MP mp,pointer p, fraction t) { /* splits the cubic after |p| */
+ scaled v; /* an intermediate value */
+ pointer q,r; /* for list manipulation */
+ q=link(p); r=mp_get_node(mp, knot_node_size); link(p)=r; link(r)=q;
+ originator(r)=mp_program_code;
+ left_type(r)=mp_explicit; right_type(r)=mp_explicit;
+ v=t_of_the_way(right_x(p),left_x(q));
+ right_x(p)=t_of_the_way(x_coord(p),right_x(p));
+ left_x(q)=t_of_the_way(left_x(q),x_coord(q));
+ left_x(r)=t_of_the_way(right_x(p),v);
+ right_x(r)=t_of_the_way(v,left_x(q));
+ x_coord(r)=t_of_the_way(left_x(r),right_x(r));
+ v=t_of_the_way(right_y(p),left_y(q));
+ right_y(p)=t_of_the_way(y_coord(p),right_y(p));
+ left_y(q)=t_of_the_way(left_y(q),y_coord(q));
+ left_y(r)=t_of_the_way(right_y(p),v);
+ right_y(r)=t_of_the_way(v,left_y(q));
+ y_coord(r)=t_of_the_way(left_y(r),right_y(r));
+}
+
+@ This does not set |info(p)| or |right_type(p)|.
+
+@<Declare subroutines needed by |offset_prep|@>=
+void mp_remove_cubic (MP mp,pointer p) { /* removes the dead cubic following~|p| */
+ pointer q; /* the node that disappears */
+ q=link(p); link(p)=link(q);
+ right_x(p)=right_x(q); right_y(p)=right_y(q);
+ mp_free_node(mp, q,knot_node_size);
+}
+
+@ Let $d\prec d'$ mean that the counter-clockwise angle from $d$ to~$d'$ is
+strictly between zero and $180^\circ$. Then we can define $d\preceq d'$ to
+mean that the angle could be zero or $180^\circ$. If $w_k=(u_k,v_k)$ is the
+$k$th pen offset, the $k$th pen edge direction is defined by the formula
+$$d_k=(u\k-u_k,\,v\k-v_k).$$
+When listed by increasing $k$, these directions occur in counter-clockwise
+order so that $d_k\preceq d\k$ for all~$k$.
+The goal of |offset_prep| is to find an offset index~|k| to associate with
+each cubic, such that the direction $d(t)$ of the cubic satisfies
+$$d_{k-1}\preceq d(t)\preceq d_k\qquad\hbox{for $0\le t\le 1$.}\eqno(*)$$
+We may have to split a cubic into many pieces before each
+piece corresponds to a unique offset.
+
+@<Split the cubic between |p| and |q|, if necessary, into cubics...@>=
+info(p)=zero_off+k_needed;
+k_needed=0;
+@<Prepare for derivative computations;
+ |goto not_found| if the current cubic is dead@>;
+@<Find the initial direction |(dx,dy)|@>;
+@<Update |info(p)| and find the offset $w_k$ such that
+ $d_{k-1}\preceq(\\{dx},\\{dy})\prec d_k$; also advance |w0| for
+ the direction change at |p|@>;
+@<Find the final direction |(dxin,dyin)|@>;
+@<Decide on the net change in pen offsets and set |turn_amt|@>;
+@<Complete the offset splitting process@>;
+w0=mp_pen_walk(mp, w0,turn_amt)
+
+@ @<Declare subroutines needed by |offset_prep|@>=
+pointer mp_pen_walk (MP mp,pointer w, integer k) {
+ /* walk |k| steps around a pen from |w| */
+ while ( k>0 ) { w=link(w); decr(k); };
+ while ( k<0 ) { w=knil(w); incr(k); };
+ return w;
+}
+
+@ The direction of a cubic $B(z_0,z_1,z_2,z_3;t)=\bigl(x(t),y(t)\bigr)$ can be
+calculated from the quadratic polynomials
+${1\over3}x'(t)=B(x_1-x_0,x_2-x_1,x_3-x_2;t)$ and
+${1\over3}y'(t)=B(y_1-y_0,y_2-y_1,y_3-y_2;t)$.
+Since we may be calculating directions from several cubics
+split from the current one, it is desirable to do these calculations
+without losing too much precision. ``Scaled up'' values of the
+derivatives, which will be less tainted by accumulated errors than
+derivatives found from the cubics themselves, are maintained in
+local variables |x0|, |x1|, and |x2|, representing $X_0=2^l(x_1-x_0)$,
+$X_1=2^l(x_2-x_1)$, and $X_2=2^l(x_3-x_2)$; similarly |y0|, |y1|, and~|y2|
+represent $Y_0=2^l(y_1-y_0)$, $Y_1=2^l(y_2-y_1)$, and $Y_2=2^l(y_3-y_2)$.
+
+@<Other local variables for |offset_prep|@>=
+integer x0,x1,x2,y0,y1,y2; /* representatives of derivatives */
+integer t0,t1,t2; /* coefficients of polynomial for slope testing */
+integer du,dv,dx,dy; /* for directions of the pen and the curve */
+integer dx0,dy0; /* initial direction for the first cubic in the curve */
+integer max_coef; /* used while scaling */
+integer x0a,x1a,x2a,y0a,y1a,y2a; /* intermediate values */
+fraction t; /* where the derivative passes through zero */
+fraction s; /* a temporary value */
+
+@ @<Prepare for derivative computations...@>=
+x0=right_x(p)-x_coord(p);
+x2=x_coord(q)-left_x(q);
+x1=left_x(q)-right_x(p);
+y0=right_y(p)-y_coord(p); y2=y_coord(q)-left_y(q);
+y1=left_y(q)-right_y(p);
+max_coef=abs(x0);
+if ( abs(x1)>max_coef ) max_coef=abs(x1);
+if ( abs(x2)>max_coef ) max_coef=abs(x2);
+if ( abs(y0)>max_coef ) max_coef=abs(y0);
+if ( abs(y1)>max_coef ) max_coef=abs(y1);
+if ( abs(y2)>max_coef ) max_coef=abs(y2);
+if ( max_coef==0 ) goto NOT_FOUND;
+while ( max_coef<fraction_half ) {
+ double(max_coef);
+ double(x0); double(x1); double(x2);
+ double(y0); double(y1); double(y2);
+}
+
+@ Let us first solve a special case of the problem: Suppose we
+know an index~$k$ such that either (i)~$d(t)\succeq d_{k-1}$ for all~$t$
+and $d(0)\prec d_k$, or (ii)~$d(t)\preceq d_k$ for all~$t$ and
+$d(0)\succ d_{k-1}$.
+Then, in a sense, we're halfway done, since one of the two relations
+in $(*)$ is satisfied, and the other couldn't be satisfied for
+any other value of~|k|.
+
+Actually, the conditions can be relaxed somewhat since a relation such as
+$d(t)\succeq d_{k-1}$ restricts $d(t)$ to a half plane when all that really
+matters is whether $d(t)$ crosses the ray in the $d_{k-1}$ direction from
+the origin. The condition for case~(i) becomes $d_{k-1}\preceq d(0)\prec d_k$
+and $d(t)$ never crosses the $d_{k-1}$ ray in the clockwise direction.
+Case~(ii) is similar except $d(t)$ cannot cross the $d_k$ ray in the
+counterclockwise direction.
+
+The |fin_offset_prep| subroutine solves the stated subproblem.
+It has a parameter called |rise| that is |1| in
+case~(i), |-1| in case~(ii). Parameters |x0| through |y2| represent
+the derivative of the cubic following |p|.
+The |w| parameter should point to offset~$w_k$ and |info(p)| should already
+be set properly. The |turn_amt| parameter gives the absolute value of the
+overall net change in pen offsets.
+
+@<Declare subroutines needed by |offset_prep|@>=
+void mp_fin_offset_prep (MP mp,pointer p, pointer w, integer
+ x0,integer x1, integer x2, integer y0, integer y1, integer y2,
+ integer rise, integer turn_amt) {
+ pointer ww; /* for list manipulation */
+ scaled du,dv; /* for slope calculation */
+ integer t0,t1,t2; /* test coefficients */
+ fraction t; /* place where the derivative passes a critical slope */
+ fraction s; /* slope or reciprocal slope */
+ integer v; /* intermediate value for updating |x0..y2| */
+ pointer q; /* original |link(p)| */
+ q=link(p);
+ while (1) {
+ if ( rise>0 ) ww=link(w); /* a pointer to $w\k$ */
+ else ww=knil(w); /* a pointer to $w_{k-1}$ */
+ @<Compute test coefficients |(t0,t1,t2)|
+ for $d(t)$ versus $d_k$ or $d_{k-1}$@>;
+ t=mp_crossing_point(mp, t0,t1,t2);
+ if ( t>=fraction_one ) {
+ if ( turn_amt>0 ) t=fraction_one; else return;
+ }
+ @<Split the cubic at $t$,
+ and split off another cubic if the derivative crosses back@>;
+ w=ww;
+ }
+}
+
+@ We want $B(\\{t0},\\{t1},\\{t2};t)$ to be the dot product of $d(t)$ with a
+$-90^\circ$ rotation of the vector from |w| to |ww|. This makes the resulting
+function cross from positive to negative when $d_{k-1}\preceq d(t)\preceq d_k$
+begins to fail.
+
+@<Compute test coefficients |(t0,t1,t2)| for $d(t)$ versus...@>=
+du=x_coord(ww)-x_coord(w); dv=y_coord(ww)-y_coord(w);
+if ( abs(du)>=abs(dv) ) {
+ s=mp_make_fraction(mp, dv,du);
+ t0=mp_take_fraction(mp, x0,s)-y0;
+ t1=mp_take_fraction(mp, x1,s)-y1;
+ t2=mp_take_fraction(mp, x2,s)-y2;
+ if ( du<0 ) { negate(t0); negate(t1); negate(t2); }
+} else {
+ s=mp_make_fraction(mp, du,dv);
+ t0=x0-mp_take_fraction(mp, y0,s);
+ t1=x1-mp_take_fraction(mp, y1,s);
+ t2=x2-mp_take_fraction(mp, y2,s);
+ if ( dv<0 ) { negate(t0); negate(t1); negate(t2); }
+}
+if ( t0<0 ) t0=0 /* should be positive without rounding error */
+
+@ The curve has crossed $d_k$ or $d_{k-1}$; its initial segment satisfies
+$(*)$, and it might cross again and return towards $s_{k-1}$ or $s_k$,
+respectively, yielding another solution of $(*)$.
+
+@<Split the cubic at $t$, and split off another...@>=
+{
+mp_split_cubic(mp, p,t); p=link(p); info(p)=zero_off+rise;
+decr(turn_amt);
+v=t_of_the_way(x0,x1); x1=t_of_the_way(x1,x2);
+x0=t_of_the_way(v,x1);
+v=t_of_the_way(y0,y1); y1=t_of_the_way(y1,y2);
+y0=t_of_the_way(v,y1);
+if ( turn_amt<0 ) {
+ t1=t_of_the_way(t1,t2);
+ if ( t1>0 ) t1=0; /* without rounding error, |t1| would be |<=0| */
+ t=mp_crossing_point(mp, 0,-t1,-t2);
+ if ( t>fraction_one ) t=fraction_one;
+ incr(turn_amt);
+ if ( (t==fraction_one)&&(link(p)!=q) ) {
+ info(link(p))=info(link(p))-rise;
+ } else {
+ mp_split_cubic(mp, p,t); info(link(p))=zero_off-rise;
+ v=t_of_the_way(x1,x2); x1=t_of_the_way(x0,x1);
+ x2=t_of_the_way(x1,v);
+ v=t_of_the_way(y1,y2); y1=t_of_the_way(y0,y1);
+ y2=t_of_the_way(y1,v);
+ }
+}
+}
+
+@ Now we must consider the general problem of |offset_prep|, when
+nothing is known about a given cubic. We start by finding its
+direction in the vicinity of |t=0|.
+
+If $z'(t)=0$, the given cubic is numerically unstable but |offset_prep|
+has not yet introduced any more numerical errors. Thus we can compute
+the true initial direction for the given cubic, even if it is almost
+degenerate.
+
+@<Find the initial direction |(dx,dy)|@>=
+dx=x0; dy=y0;
+if ( dx==0 && dy==0 ) {
+ dx=x1; dy=y1;
+ if ( dx==0 && dy==0 ) {
+ dx=x2; dy=y2;
+ }
+}
+if ( p==c ) { dx0=dx; dy0=dy; }
+
+@ @<Find the final direction |(dxin,dyin)|@>=
+dxin=x2; dyin=y2;
+if ( dxin==0 && dyin==0 ) {
+ dxin=x1; dyin=y1;
+ if ( dxin==0 && dyin==0 ) {
+ dxin=x0; dyin=y0;
+ }
+}
+
+@ The next step is to bracket the initial direction between consecutive
+edges of the pen polygon. We must be careful to turn clockwise only if
+this makes the turn less than $180^\circ$. (A $180^\circ$ turn must be
+counter-clockwise in order to make \&{doublepath} envelopes come out
+@:double_path_}{\&{doublepath} primitive@>
+right.) This code depends on |w0| being the offset for |(dxin,dyin)|.
+
+@<Update |info(p)| and find the offset $w_k$ such that...@>=
+turn_amt=mp_get_turn_amt(mp,w0,dx,dy,(mp_ab_vs_cd(mp, dy,dxin,dx,dyin)>=0));
+w=mp_pen_walk(mp, w0, turn_amt);
+w0=w;
+info(p)=info(p)+turn_amt
+
+@ Decide how many pen offsets to go away from |w| in order to find the offset
+for |(dx,dy)|, going counterclockwise if |ccw| is |true|. This assumes that
+|w| is the offset for some direction $(x',y')$ from which the angle to |(dx,dy)|
+in the sense determined by |ccw| is less than or equal to $180^\circ$.
+
+If the pen polygon has only two edges, they could both be parallel
+to |(dx,dy)|. In this case, we must be careful to stop after crossing the first
+such edge in order to avoid an infinite loop.
+
+@<Declare subroutines needed by |offset_prep|@>=
+integer mp_get_turn_amt (MP mp,pointer w, scaled dx,
+ scaled dy, boolean ccw) {
+ pointer ww; /* a neighbor of knot~|w| */
+ integer s; /* turn amount so far */
+ integer t; /* |ab_vs_cd| result */
+ s=0;
+ if ( ccw ) {
+ ww=link(w);
+ do {
+ t=mp_ab_vs_cd(mp, dy,(x_coord(ww)-x_coord(w)),
+ dx,(y_coord(ww)-y_coord(w)));
+ if ( t<0 ) break;
+ incr(s);
+ w=ww; ww=link(ww);
+ } while (t>0);
+ } else {
+ ww=knil(w);
+ while ( mp_ab_vs_cd(mp, dy,(x_coord(w)-x_coord(ww)),
+ dx,(y_coord(w)-y_coord(ww))) < 0) {
+ decr(s);
+ w=ww; ww=knil(ww);
+ }
+ }
+ return s;
+}
+
+@ When we're all done, the final offset is |w0| and the final curve direction
+is |(dxin,dyin)|. With this knowledge of the incoming direction at |c|, we
+can correct |info(c)| which was erroneously based on an incoming offset
+of~|h|.
+
+@d fix_by(A) info(c)=info(c)+(A)
+
+@<Fix the offset change in |info(c)| and set |c| to the return value of...@>=
+mp->spec_offset=info(c)-zero_off;
+if ( link(c)==c ) {
+ info(c)=zero_off+n;
+} else {
+ fix_by(k_needed);
+ while ( w0!=h ) { fix_by(1); w0=link(w0); };
+ while ( info(c)<=zero_off-n ) fix_by(n);
+ while ( info(c)>zero_off ) fix_by(-n);
+ if ( (info(c)!=zero_off)&&(mp_ab_vs_cd(mp, dy0,dxin,dx0,dyin)>=0) ) fix_by(n);
+}
+
+@ Finally we want to reduce the general problem to situations that
+|fin_offset_prep| can handle. We split the cubic into at most three parts
+with respect to $d_{k-1}$, and apply |fin_offset_prep| to each part.
+
+@<Complete the offset splitting process@>=
+ww=knil(w);
+@<Compute test coeff...@>;
+@<Find the first |t| where $d(t)$ crosses $d_{k-1}$ or set
+ |t:=fraction_one+1|@>;
+if ( t>fraction_one ) {
+ mp_fin_offset_prep(mp, p,w,x0,x1,x2,y0,y1,y2,1,turn_amt);
+} else {
+ mp_split_cubic(mp, p,t); r=link(p);
+ x1a=t_of_the_way(x0,x1); x1=t_of_the_way(x1,x2);
+ x2a=t_of_the_way(x1a,x1);
+ y1a=t_of_the_way(y0,y1); y1=t_of_the_way(y1,y2);
+ y2a=t_of_the_way(y1a,y1);
+ mp_fin_offset_prep(mp, p,w,x0,x1a,x2a,y0,y1a,y2a,1,0); x0=x2a; y0=y2a;
+ info(r)=zero_off-1;
+ if ( turn_amt>=0 ) {
+ t1=t_of_the_way(t1,t2);
+ if ( t1>0 ) t1=0;
+ t=mp_crossing_point(mp, 0,-t1,-t2);
+ if ( t>fraction_one ) t=fraction_one;
+ @<Split off another rising cubic for |fin_offset_prep|@>;
+ mp_fin_offset_prep(mp, r,ww,x0,x1,x2,y0,y1,y2,-1,0);
+ } else {
+ mp_fin_offset_prep(mp, r,ww,x0,x1,x2,y0,y1,y2,-1,(-1-turn_amt));
+ }
+}
+
+@ @<Split off another rising cubic for |fin_offset_prep|@>=
+mp_split_cubic(mp, r,t); info(link(r))=zero_off+1;
+x1a=t_of_the_way(x1,x2); x1=t_of_the_way(x0,x1);
+x0a=t_of_the_way(x1,x1a);
+y1a=t_of_the_way(y1,y2); y1=t_of_the_way(y0,y1);
+y0a=t_of_the_way(y1,y1a);
+mp_fin_offset_prep(mp, link(r),w,x0a,x1a,x2,y0a,y1a,y2,1,turn_amt);
+x2=x0a; y2=y0a
+
+@ At this point, the direction of the incoming pen edge is |(-du,-dv)|.
+When the component of $d(t)$ perpendicular to |(-du,-dv)| crosses zero, we
+need to decide whether the directions are parallel or antiparallel. We
+can test this by finding the dot product of $d(t)$ and |(-du,-dv)|, but this
+should be avoided when the value of |turn_amt| already determines the
+answer. If |t2<0|, there is one crossing and it is antiparallel only if
+|turn_amt>=0|. If |turn_amt<0|, there should always be at least one
+crossing and the first crossing cannot be antiparallel.
+
+@<Find the first |t| where $d(t)$ crosses $d_{k-1}$ or set...@>=
+t=mp_crossing_point(mp, t0,t1,t2);
+if ( turn_amt>=0 ) {
+ if ( t2<0 ) {
+ t=fraction_one+1;
+ } else {
+ u0=t_of_the_way(x0,x1);
+ u1=t_of_the_way(x1,x2);
+ ss=mp_take_fraction(mp, -du,t_of_the_way(u0,u1));
+ v0=t_of_the_way(y0,y1);
+ v1=t_of_the_way(y1,y2);
+ ss=ss+mp_take_fraction(mp, -dv,t_of_the_way(v0,v1));
+ if ( ss<0 ) t=fraction_one+1;
+ }
+} else if ( t>fraction_one ) {
+ t=fraction_one;
+}
+
+@ @<Other local variables for |offset_prep|@>=
+integer u0,u1,v0,v1; /* intermediate values for $d(t)$ calculation */
+integer ss = 0; /* the part of the dot product computed so far */
+int d_sign; /* sign of overall change in direction for this cubic */
+
+@ If the cubic almost has a cusp, it is a numerically ill-conditioned
+problem to decide which way it loops around but that's OK as long we're
+consistent. To make \&{doublepath} envelopes work properly, reversing
+the path should always change the sign of |turn_amt|.
+
+@<Decide on the net change in pen offsets and set |turn_amt|@>=
+d_sign=mp_ab_vs_cd(mp, dx,dyin, dxin,dy);
+if ( d_sign==0 ) {
+ @<Check rotation direction based on node position@>
+}
+if ( d_sign==0 ) {
+ if ( dx==0 ) {
+ if ( dy>0 ) d_sign=1; else d_sign=-1;
+ } else {
+ if ( dx>0 ) d_sign=1; else d_sign=-1;
+ }
+}
+@<Make |ss| negative if and only if the total change in direction is
+ more than $180^\circ$@>;
+turn_amt=mp_get_turn_amt(mp, w, dxin, dyin, (d_sign>0));
+if ( ss<0 ) turn_amt=turn_amt-d_sign*n
+
+@ We check rotation direction by looking at the vector connecting the current
+node with the next. If its angle with incoming and outgoing tangents has the
+same sign, we pick this as |d_sign|, since it means we have a flex, not a cusp.
+Otherwise we proceed to the cusp code.
+
+@<Check rotation direction based on node position@>=
+u0=x_coord(q)-x_coord(p);
+u1=y_coord(q)-y_coord(p);
+d_sign = half(mp_ab_vs_cd(mp, dx, u1, u0, dy)+
+ mp_ab_vs_cd(mp, u0, dyin, dxin, u1));
+
+@ In order to be invariant under path reversal, the result of this computation
+should not change when |x0|, |y0|, $\ldots$ are all negated and |(x0,y0)| is
+then swapped with |(x2,y2)|. We make use of the identities
+|take_fraction(-a,-b)=take_fraction(a,b)| and
+|t_of_the_way(-a,-b)=-(t_of_the_way(a,b))|.
+
+@<Make |ss| negative if and only if the total change in direction is...@>=
+t0=half(mp_take_fraction(mp, x0,y2))-half(mp_take_fraction(mp, x2,y0));
+t1=half(mp_take_fraction(mp, x1,(y0+y2)))-half(mp_take_fraction(mp, y1,(x0+x2)));
+if ( t0==0 ) t0=d_sign; /* path reversal always negates |d_sign| */
+if ( t0>0 ) {
+ t=mp_crossing_point(mp, t0,t1,-t0);
+ u0=t_of_the_way(x0,x1);
+ u1=t_of_the_way(x1,x2);
+ v0=t_of_the_way(y0,y1);
+ v1=t_of_the_way(y1,y2);
+} else {
+ t=mp_crossing_point(mp, -t0,t1,t0);
+ u0=t_of_the_way(x2,x1);
+ u1=t_of_the_way(x1,x0);
+ v0=t_of_the_way(y2,y1);
+ v1=t_of_the_way(y1,y0);
+}
+ss=mp_take_fraction(mp, (x0+x2),t_of_the_way(u0,u1))+
+ mp_take_fraction(mp, (y0+y2),t_of_the_way(v0,v1))
+
+@ Here's a routine that prints an envelope spec in symbolic form. It assumes
+that the |cur_pen| has not been walked around to the first offset.
+
+@c
+void mp_print_spec (MP mp,pointer cur_spec, pointer cur_pen, const char *s) {
+ pointer p,q; /* list traversal */
+ pointer w; /* the current pen offset */
+ mp_print_diagnostic(mp, "Envelope spec",s,true);
+ p=cur_spec; w=mp_pen_walk(mp, cur_pen,mp->spec_offset);
+ mp_print_ln(mp);
+ mp_print_two(mp, x_coord(cur_spec),y_coord(cur_spec));
+ mp_print(mp, " % beginning with offset ");
+ mp_print_two(mp, x_coord(w),y_coord(w));
+ do {
+ while (1) {
+ q=link(p);
+ @<Print the cubic between |p| and |q|@>;
+ p=q;
+ if ((p==cur_spec) || (info(p)!=zero_off))
+ break;
+ }
+ if ( info(p)!=zero_off ) {
+ @<Update |w| as indicated by |info(p)| and print an explanation@>;
+ }
+ } while (p!=cur_spec);
+ mp_print_nl(mp, " & cycle");
+ mp_end_diagnostic(mp, true);
+}
+
+@ @<Update |w| as indicated by |info(p)| and print an explanation@>=
+{
+ w=mp_pen_walk(mp, w, (info(p)-zero_off));
+ mp_print(mp, " % ");
+ if ( info(p)>zero_off ) mp_print(mp, "counter");
+ mp_print(mp, "clockwise to offset ");
+ mp_print_two(mp, x_coord(w),y_coord(w));
+}
+
+@ @<Print the cubic between |p| and |q|@>=
+{
+ mp_print_nl(mp, " ..controls ");
+ mp_print_two(mp, right_x(p),right_y(p));
+ mp_print(mp, " and ");
+ mp_print_two(mp, left_x(q),left_y(q));
+ mp_print_nl(mp, " ..");
+ mp_print_two(mp, x_coord(q),y_coord(q));
+}
+
+@ Once we have an envelope spec, the remaining task to construct the actual
+envelope by offsetting each cubic as determined by the |info| fields in
+the knots. First we use |offset_prep| to convert the |c| into an envelope
+spec. Then we add the offsets so that |c| becomes a cyclic path that represents
+the envelope.
+
+The |ljoin| and |miterlim| parameters control the treatment of points where the
+pen offset changes, and |lcap| controls the endpoints of a \&{doublepath}.
+The endpoints are easily located because |c| is given in undoubled form
+and then doubled in this procedure. We use |spec_p1| and |spec_p2| to keep
+track of the endpoints and treat them like very sharp corners.
+Butt end caps are treated like beveled joins; round end caps are treated like
+round joins; and square end caps are achieved by setting |join_type:=3|.
+
+None of these parameters apply to inside joins where the convolution tracing
+has retrograde lines. In such cases we use a simple connect-the-endpoints
+approach that is achieved by setting |join_type:=2|.
+
+@c @<Declare a function called |insert_knot|@>
+pointer mp_make_envelope (MP mp,pointer c, pointer h, small_number ljoin,
+ small_number lcap, scaled miterlim) {
+ pointer p,q,r,q0; /* for manipulating the path */
+ int join_type=0; /* codes |0..3| for mitered, round, beveled, or square */
+ pointer w,w0; /* the pen knot for the current offset */
+ scaled qx,qy; /* unshifted coordinates of |q| */
+ halfword k,k0; /* controls pen edge insertion */
+ @<Other local variables for |make_envelope|@>;
+ dxin=0; dyin=0; dxout=0; dyout=0;
+ mp->spec_p1=null; mp->spec_p2=null;
+ @<If endpoint, double the path |c|, and set |spec_p1| and |spec_p2|@>;
+ @<Use |offset_prep| to compute the envelope spec then walk |h| around to
+ the initial offset@>;
+ w=h;
+ p=c;
+ do {
+ q=link(p); q0=q;
+ qx=x_coord(q); qy=y_coord(q);
+ k=info(q);
+ k0=k; w0=w;
+ if ( k!=zero_off ) {
+ @<Set |join_type| to indicate how to handle offset changes at~|q|@>;
+ }
+ @<Add offset |w| to the cubic from |p| to |q|@>;
+ while ( k!=zero_off ) {
+ @<Step |w| and move |k| one step closer to |zero_off|@>;
+ if ( (join_type==1)||(k==zero_off) )
+ q=mp_insert_knot(mp, q,qx+x_coord(w),qy+y_coord(w));
+ };
+ if ( q!=link(p) ) {
+ @<Set |p=link(p)| and add knots between |p| and |q| as
+ required by |join_type|@>;
+ }
+ p=q;
+ } while (q0!=c);
+ return c;
+}
+
+@ @<Use |offset_prep| to compute the envelope spec then walk |h| around to...@>=
+c=mp_offset_prep(mp, c,h);
+if ( mp->internal[mp_tracing_specs]>0 )
+ mp_print_spec(mp, c,h,"");
+h=mp_pen_walk(mp, h,mp->spec_offset)
+
+@ Mitered and squared-off joins depend on path directions that are difficult to
+compute for degenerate cubics. The envelope spec computed by |offset_prep| can
+have degenerate cubics only if the entire cycle collapses to a single
+degenerate cubic. Setting |join_type:=2| in this case makes the computed
+envelope degenerate as well.
+
+@<Set |join_type| to indicate how to handle offset changes at~|q|@>=
+if ( k<zero_off ) {
+ join_type=2;
+} else {
+ if ( (q!=mp->spec_p1)&&(q!=mp->spec_p2) ) join_type=ljoin;
+ else if ( lcap==2 ) join_type=3;
+ else join_type=2-lcap;
+ if ( (join_type==0)||(join_type==3) ) {
+ @<Set the incoming and outgoing directions at |q|; in case of
+ degeneracy set |join_type:=2|@>;
+ if ( join_type==0 ) {
+ @<If |miterlim| is less than the secant of half the angle at |q|
+ then set |join_type:=2|@>;
+ }
+ }
+}
+
+@ @<If |miterlim| is less than the secant of half the angle at |q|...@>=
+{
+ tmp=mp_take_fraction(mp, miterlim,fraction_half+
+ half(mp_take_fraction(mp, dxin,dxout)+mp_take_fraction(mp, dyin,dyout)));
+ if ( tmp<unity )
+ if ( mp_take_scaled(mp, miterlim,tmp)<unity ) join_type=2;
+}
+
+@ @<Other local variables for |make_envelope|@>=
+fraction dxin,dyin,dxout,dyout; /* directions at |q| when square or mitered */
+scaled tmp; /* a temporary value */
+
+@ The coordinates of |p| have already been shifted unless |p| is the first
+knot in which case they get shifted at the very end.
+
+@<Add offset |w| to the cubic from |p| to |q|@>=
+right_x(p)=right_x(p)+x_coord(w);
+right_y(p)=right_y(p)+y_coord(w);
+left_x(q)=left_x(q)+x_coord(w);
+left_y(q)=left_y(q)+y_coord(w);
+x_coord(q)=x_coord(q)+x_coord(w);
+y_coord(q)=y_coord(q)+y_coord(w);
+left_type(q)=mp_explicit;
+right_type(q)=mp_explicit
+
+@ @<Step |w| and move |k| one step closer to |zero_off|@>=
+if ( k>zero_off ){ w=link(w); decr(k); }
+else { w=knil(w); incr(k); }
+
+@ The cubic from |q| to the new knot at |(x,y)| becomes a line segment and
+the |right_x| and |right_y| fields of |r| are set from |q|. This is done in
+case the cubic containing these control points is ``yet to be examined.''
+
+@<Declare a function called |insert_knot|@>=
+pointer mp_insert_knot (MP mp,pointer q, scaled x, scaled y) {
+ /* returns the inserted knot */
+ pointer r; /* the new knot */
+ r=mp_get_node(mp, knot_node_size);
+ link(r)=link(q); link(q)=r;
+ right_x(r)=right_x(q);
+ right_y(r)=right_y(q);
+ x_coord(r)=x;
+ y_coord(r)=y;
+ right_x(q)=x_coord(q);
+ right_y(q)=y_coord(q);
+ left_x(r)=x_coord(r);
+ left_y(r)=y_coord(r);
+ left_type(r)=mp_explicit;
+ right_type(r)=mp_explicit;
+ originator(r)=mp_program_code;
+ return r;
+}
+
+@ After setting |p:=link(p)|, either |join_type=1| or |q=link(p)|.
+
+@<Set |p=link(p)| and add knots between |p| and |q| as...@>=
+{
+ p=link(p);
+ if ( (join_type==0)||(join_type==3) ) {
+ if ( join_type==0 ) {
+ @<Insert a new knot |r| between |p| and |q| as required for a mitered join@>
+ } else {
+ @<Make |r| the last of two knots inserted between |p| and |q| to form a
+ squared join@>;
+ }
+ if ( r!=null ) {
+ right_x(r)=x_coord(r);
+ right_y(r)=y_coord(r);
+ }
+ }
+}
+
+@ For very small angles, adding a knot is unnecessary and would cause numerical
+problems, so we just set |r:=null| in that case.
+
+@<Insert a new knot |r| between |p| and |q| as required for a mitered join@>=
+{
+ det=mp_take_fraction(mp, dyout,dxin)-mp_take_fraction(mp, dxout,dyin);
+ if ( abs(det)<26844 ) {
+ r=null; /* sine $<10^{-4}$ */
+ } else {
+ tmp=mp_take_fraction(mp, x_coord(q)-x_coord(p),dyout)-
+ mp_take_fraction(mp, y_coord(q)-y_coord(p),dxout);
+ tmp=mp_make_fraction(mp, tmp,det);
+ r=mp_insert_knot(mp, p,x_coord(p)+mp_take_fraction(mp, tmp,dxin),
+ y_coord(p)+mp_take_fraction(mp, tmp,dyin));
+ }
+}
+
+@ @<Other local variables for |make_envelope|@>=
+fraction det; /* a determinant used for mitered join calculations */
+
+@ @<Make |r| the last of two knots inserted between |p| and |q| to form a...@>=
+{
+ ht_x=y_coord(w)-y_coord(w0);
+ ht_y=x_coord(w0)-x_coord(w);
+ while ( (abs(ht_x)<fraction_half)&&(abs(ht_y)<fraction_half) ) {
+ ht_x+=ht_x; ht_y+=ht_y;
+ }
+ @<Scan the pen polygon between |w0| and |w| and make |max_ht| the range dot
+ product with |(ht_x,ht_y)|@>;
+ tmp=mp_make_fraction(mp, max_ht,mp_take_fraction(mp, dxin,ht_x)+
+ mp_take_fraction(mp, dyin,ht_y));
+ r=mp_insert_knot(mp, p,x_coord(p)+mp_take_fraction(mp, tmp,dxin),
+ y_coord(p)+mp_take_fraction(mp, tmp,dyin));
+ tmp=mp_make_fraction(mp, max_ht,mp_take_fraction(mp, dxout,ht_x)+
+ mp_take_fraction(mp, dyout,ht_y));
+ r=mp_insert_knot(mp, r,x_coord(q)+mp_take_fraction(mp, tmp,dxout),
+ y_coord(q)+mp_take_fraction(mp, tmp,dyout));
+}
+
+@ @<Other local variables for |make_envelope|@>=
+fraction ht_x,ht_y; /* perpendicular to the segment from |p| to |q| */
+scaled max_ht; /* maximum height of the pen polygon above the |w0|-|w| line */
+halfword kk; /* keeps track of the pen vertices being scanned */
+pointer ww; /* the pen vertex being tested */
+
+@ The dot product of the vector from |w0| to |ww| with |(ht_x,ht_y)| ranges
+from zero to |max_ht|.
+
+@<Scan the pen polygon between |w0| and |w| and make |max_ht| the range...@>=
+max_ht=0;
+kk=zero_off;
+ww=w;
+while (1) {
+ @<Step |ww| and move |kk| one step closer to |k0|@>;
+ if ( kk==k0 ) break;
+ tmp=mp_take_fraction(mp, (x_coord(ww)-x_coord(w0)),ht_x)+
+ mp_take_fraction(mp, (y_coord(ww)-y_coord(w0)),ht_y);
+ if ( tmp>max_ht ) max_ht=tmp;
+}
+
+
+@ @<Step |ww| and move |kk| one step closer to |k0|@>=
+if ( kk>k0 ) { ww=link(ww); decr(kk); }
+else { ww=knil(ww); incr(kk); }
+
+@ @<If endpoint, double the path |c|, and set |spec_p1| and |spec_p2|@>=
+if ( left_type(c)==mp_endpoint ) {
+ mp->spec_p1=mp_htap_ypoc(mp, c);
+ mp->spec_p2=mp->path_tail;
+ originator(mp->spec_p1)=mp_program_code;
+ link(mp->spec_p2)=link(mp->spec_p1);
+ link(mp->spec_p1)=c;
+ mp_remove_cubic(mp, mp->spec_p1);
+ c=mp->spec_p1;
+ if ( c!=link(c) ) {
+ originator(mp->spec_p2)=mp_program_code;
+ mp_remove_cubic(mp, mp->spec_p2);
+ } else {
+ @<Make |c| look like a cycle of length one@>;
+ }
+}
+
+@ @<Make |c| look like a cycle of length one@>=
+{
+ left_type(c)=mp_explicit; right_type(c)=mp_explicit;
+ left_x(c)=x_coord(c); left_y(c)=y_coord(c);
+ right_x(c)=x_coord(c); right_y(c)=y_coord(c);
+}
+
+@ In degenerate situations we might have to look at the knot preceding~|q|.
+That knot is |p| but if |p<>c|, its coordinates have already been offset by |w|.
+
+@<Set the incoming and outgoing directions at |q|; in case of...@>=
+dxin=x_coord(q)-left_x(q);
+dyin=y_coord(q)-left_y(q);
+if ( (dxin==0)&&(dyin==0) ) {
+ dxin=x_coord(q)-right_x(p);
+ dyin=y_coord(q)-right_y(p);
+ if ( (dxin==0)&&(dyin==0) ) {
+ dxin=x_coord(q)-x_coord(p);
+ dyin=y_coord(q)-y_coord(p);
+ if ( p!=c ) { /* the coordinates of |p| have been offset by |w| */
+ dxin=dxin+x_coord(w);
+ dyin=dyin+y_coord(w);
+ }
+ }
+}
+tmp=mp_pyth_add(mp, dxin,dyin);
+if ( tmp==0 ) {
+ join_type=2;
+} else {
+ dxin=mp_make_fraction(mp, dxin,tmp);
+ dyin=mp_make_fraction(mp, dyin,tmp);
+ @<Set the outgoing direction at |q|@>;
+}
+
+@ If |q=c| then the coordinates of |r| and the control points between |q|
+and~|r| have already been offset by |h|.
+
+@<Set the outgoing direction at |q|@>=
+dxout=right_x(q)-x_coord(q);
+dyout=right_y(q)-y_coord(q);
+if ( (dxout==0)&&(dyout==0) ) {
+ r=link(q);
+ dxout=left_x(r)-x_coord(q);
+ dyout=left_y(r)-y_coord(q);
+ if ( (dxout==0)&&(dyout==0) ) {
+ dxout=x_coord(r)-x_coord(q);
+ dyout=y_coord(r)-y_coord(q);
+ }
+}
+if ( q==c ) {
+ dxout=dxout-x_coord(h);
+ dyout=dyout-y_coord(h);
+}
+tmp=mp_pyth_add(mp, dxout,dyout);
+if ( tmp==0 ) mp_confusion(mp, "degenerate spec");
+@:this can't happen degerate spec}{\quad degenerate spec@>
+dxout=mp_make_fraction(mp, dxout,tmp);
+dyout=mp_make_fraction(mp, dyout,tmp)
+
+@* \[23] Direction and intersection times.
+A path of length $n$ is defined parametrically by functions $x(t)$ and
+$y(t)$, for |0<=t<=n|; we can regard $t$ as the ``time'' at which the path
+reaches the point $\bigl(x(t),y(t)\bigr)$. In this section of the program
+we shall consider operations that determine special times associated with
+given paths: the first time that a path travels in a given direction, and
+a pair of times at which two paths cross each other.
+
+@ Let's start with the easier task. The function |find_direction_time| is
+given a direction |(x,y)| and a path starting at~|h|. If the path never
+travels in direction |(x,y)|, the direction time will be~|-1|; otherwise
+it will be nonnegative.
+
+Certain anomalous cases can arise: If |(x,y)=(0,0)|, so that the given
+direction is undefined, the direction time will be~0. If $\bigl(x'(t),
+y'(t)\bigr)=(0,0)$, so that the path direction is undefined, it will be
+assumed to match any given direction at time~|t|.
+
+The routine solves this problem in nondegenerate cases by rotating the path
+and the given direction so that |(x,y)=(1,0)|; i.e., the main task will be
+to find when a given path first travels ``due east.''
+
+@c
+scaled mp_find_direction_time (MP mp,scaled x, scaled y, pointer h) {
+ scaled max; /* $\max\bigl(\vert x\vert,\vert y\vert\bigr)$ */
+ pointer p,q; /* for list traversal */
+ scaled n; /* the direction time at knot |p| */
+ scaled tt; /* the direction time within a cubic */
+ @<Other local variables for |find_direction_time|@>;
+ @<Normalize the given direction for better accuracy;
+ but |return| with zero result if it's zero@>;
+ n=0; p=h; phi=0;
+ while (1) {
+ if ( right_type(p)==mp_endpoint ) break;
+ q=link(p);
+ @<Rotate the cubic between |p| and |q|; then
+ |goto found| if the rotated cubic travels due east at some time |tt|;
+ but |break| if an entire cyclic path has been traversed@>;
+ p=q; n=n+unity;
+ }
+ return (-unity);
+FOUND:
+ return (n+tt);
+}
+
+@ @<Normalize the given direction for better accuracy...@>=
+if ( abs(x)<abs(y) ) {
+ x=mp_make_fraction(mp, x,abs(y));
+ if ( y>0 ) y=fraction_one; else y=-fraction_one;
+} else if ( x==0 ) {
+ return 0;
+} else {
+ y=mp_make_fraction(mp, y,abs(x));
+ if ( x>0 ) x=fraction_one; else x=-fraction_one;
+}
+
+@ Since we're interested in the tangent directions, we work with the
+derivative $${1\over3}B'(x_0,x_1,x_2,x_3;t)=
+B(x_1-x_0,x_2-x_1,x_3-x_2;t)$$ instead of
+$B(x_0,x_1,x_2,x_3;t)$ itself. The derived coefficients are also scaled up
+in order to achieve better accuracy.
+
+The given path may turn abruptly at a knot, and it might pass the critical
+tangent direction at such a time. Therefore we remember the direction |phi|
+in which the previous rotated cubic was traveling. (The value of |phi| will be
+undefined on the first cubic, i.e., when |n=0|.)
+
+@<Rotate the cubic between |p| and |q|; then...@>=
+tt=0;
+@<Set local variables |x1,x2,x3| and |y1,y2,y3| to multiples of the control
+ points of the rotated derivatives@>;
+if ( y1==0 ) if ( x1>=0 ) goto FOUND;
+if ( n>0 ) {
+ @<Exit to |found| if an eastward direction occurs at knot |p|@>;
+ if ( p==h ) break;
+ };
+if ( (x3!=0)||(y3!=0) ) phi=mp_n_arg(mp, x3,y3);
+@<Exit to |found| if the curve whose derivatives are specified by
+ |x1,x2,x3,y1,y2,y3| travels eastward at some time~|tt|@>
+
+@ @<Other local variables for |find_direction_time|@>=
+scaled x1,x2,x3,y1,y2,y3; /* multiples of rotated derivatives */
+angle theta,phi; /* angles of exit and entry at a knot */
+fraction t; /* temp storage */
+
+@ @<Set local variables |x1,x2,x3| and |y1,y2,y3| to multiples...@>=
+x1=right_x(p)-x_coord(p); x2=left_x(q)-right_x(p);
+x3=x_coord(q)-left_x(q);
+y1=right_y(p)-y_coord(p); y2=left_y(q)-right_y(p);
+y3=y_coord(q)-left_y(q);
+max=abs(x1);
+if ( abs(x2)>max ) max=abs(x2);
+if ( abs(x3)>max ) max=abs(x3);
+if ( abs(y1)>max ) max=abs(y1);
+if ( abs(y2)>max ) max=abs(y2);
+if ( abs(y3)>max ) max=abs(y3);
+if ( max==0 ) goto FOUND;
+while ( max<fraction_half ){
+ max+=max; x1+=x1; x2+=x2; x3+=x3;
+ y1+=y1; y2+=y2; y3+=y3;
+}
+t=x1; x1=mp_take_fraction(mp, x1,x)+mp_take_fraction(mp, y1,y);
+y1=mp_take_fraction(mp, y1,x)-mp_take_fraction(mp, t,y);
+t=x2; x2=mp_take_fraction(mp, x2,x)+mp_take_fraction(mp, y2,y);
+y2=mp_take_fraction(mp, y2,x)-mp_take_fraction(mp, t,y);
+t=x3; x3=mp_take_fraction(mp, x3,x)+mp_take_fraction(mp, y3,y);
+y3=mp_take_fraction(mp, y3,x)-mp_take_fraction(mp, t,y)
+
+@ @<Exit to |found| if an eastward direction occurs at knot |p|@>=
+theta=mp_n_arg(mp, x1,y1);
+if ( theta>=0 ) if ( phi<=0 ) if ( phi>=theta-one_eighty_deg ) goto FOUND;
+if ( theta<=0 ) if ( phi>=0 ) if ( phi<=theta+one_eighty_deg ) goto FOUND
+
+@ In this step we want to use the |crossing_point| routine to find the
+roots of the quadratic equation $B(y_1,y_2,y_3;t)=0$.
+Several complications arise: If the quadratic equation has a double root,
+the curve never crosses zero, and |crossing_point| will find nothing;
+this case occurs iff $y_1y_3=y_2^2$ and $y_1y_2<0$. If the quadratic
+equation has simple roots, or only one root, we may have to negate it
+so that $B(y_1,y_2,y_3;t)$ crosses from positive to negative at its first root.
+And finally, we need to do special things if $B(y_1,y_2,y_3;t)$ is
+identically zero.
+
+@ @<Exit to |found| if the curve whose derivatives are specified by...@>=
+if ( x1<0 ) if ( x2<0 ) if ( x3<0 ) goto DONE;
+if ( mp_ab_vs_cd(mp, y1,y3,y2,y2)==0 ) {
+ @<Handle the test for eastward directions when $y_1y_3=y_2^2$;
+ either |goto found| or |goto done|@>;
+}
+if ( y1<=0 ) {
+ if ( y1<0 ) { y1=-y1; y2=-y2; y3=-y3; }
+ else if ( y2>0 ){ y2=-y2; y3=-y3; };
+}
+@<Check the places where $B(y_1,y_2,y_3;t)=0$ to see if
+ $B(x_1,x_2,x_3;t)\ge0$@>;
+DONE:
+
+@ The quadratic polynomial $B(y_1,y_2,y_3;t)$ begins |>=0| and has at most
+two roots, because we know that it isn't identically zero.
+
+It must be admitted that the |crossing_point| routine is not perfectly accurate;
+rounding errors might cause it to find a root when $y_1y_3>y_2^2$, or to
+miss the roots when $y_1y_3<y_2^2$. The rotation process is itself
+subject to rounding errors. Yet this code optimistically tries to
+do the right thing.
+
+@d we_found_it { tt=(t+04000) / 010000; goto FOUND; }
+
+@<Check the places where $B(y_1,y_2,y_3;t)=0$...@>=
+t=mp_crossing_point(mp, y1,y2,y3);
+if ( t>fraction_one ) goto DONE;
+y2=t_of_the_way(y2,y3);
+x1=t_of_the_way(x1,x2);
+x2=t_of_the_way(x2,x3);
+x1=t_of_the_way(x1,x2);
+if ( x1>=0 ) we_found_it;
+if ( y2>0 ) y2=0;
+tt=t; t=mp_crossing_point(mp, 0,-y2,-y3);
+if ( t>fraction_one ) goto DONE;
+x1=t_of_the_way(x1,x2);
+x2=t_of_the_way(x2,x3);
+if ( t_of_the_way(x1,x2)>=0 ) {
+ t=t_of_the_way(tt,fraction_one); we_found_it;
+}
+
+@ @<Handle the test for eastward directions when $y_1y_3=y_2^2$;
+ either |goto found| or |goto done|@>=
+{
+ if ( mp_ab_vs_cd(mp, y1,y2,0,0)<0 ) {
+ t=mp_make_fraction(mp, y1,y1-y2);
+ x1=t_of_the_way(x1,x2);
+ x2=t_of_the_way(x2,x3);
+ if ( t_of_the_way(x1,x2)>=0 ) we_found_it;
+ } else if ( y3==0 ) {
+ if ( y1==0 ) {
+ @<Exit to |found| if the derivative $B(x_1,x_2,x_3;t)$ becomes |>=0|@>;
+ } else if ( x3>=0 ) {
+ tt=unity; goto FOUND;
+ }
+ }
+ goto DONE;
+}
+
+@ At this point we know that the derivative of |y(t)| is identically zero,
+and that |x1<0|; but either |x2>=0| or |x3>=0|, so there's some hope of
+traveling east.
+
+@<Exit to |found| if the derivative $B(x_1,x_2,x_3;t)$ becomes |>=0|...@>=
+{
+ t=mp_crossing_point(mp, -x1,-x2,-x3);
+ if ( t<=fraction_one ) we_found_it;
+ if ( mp_ab_vs_cd(mp, x1,x3,x2,x2)<=0 ) {
+ t=mp_make_fraction(mp, x1,x1-x2); we_found_it;
+ }
+}
+
+@ The intersection of two cubics can be found by an interesting variant
+of the general bisection scheme described in the introduction to
+|crossing_point|.\
+Given $w(t)=B(w_0,w_1,w_2,w_3;t)$ and $z(t)=B(z_0,z_1,z_2,z_3;t)$,
+we wish to find a pair of times $(t_1,t_2)$ such that $w(t_1)=z(t_2)$,
+if an intersection exists. First we find the smallest rectangle that
+encloses the points $\{w_0,w_1,w_2,w_3\}$ and check that it overlaps
+the smallest rectangle that encloses
+$\{z_0,z_1,z_2,z_3\}$; if not, the cubics certainly don't intersect.
+But if the rectangles do overlap, we bisect the intervals, getting
+new cubics $w'$ and~$w''$, $z'$~and~$z''$; the intersection routine first
+tries for an intersection between $w'$ and~$z'$, then (if unsuccessful)
+between $w'$ and~$z''$, then (if still unsuccessful) between $w''$ and~$z'$,
+finally (if thrice unsuccessful) between $w''$ and~$z''$. After $l$~successful
+levels of bisection we will have determined the intersection times $t_1$
+and~$t_2$ to $l$~bits of accuracy.
+
+\def\submin{_{\rm min}} \def\submax{_{\rm max}}
+As before, it is better to work with the numbers $W_k=2^l(w_k-w_{k-1})$
+and $Z_k=2^l(z_k-z_{k-1})$ rather than the coefficients $w_k$ and $z_k$
+themselves. We also need one other quantity, $\Delta=2^l(w_0-z_0)$,
+to determine when the enclosing rectangles overlap. Here's why:
+The $x$~coordinates of~$w(t)$ are between $u\submin$ and $u\submax$,
+and the $x$~coordinates of~$z(t)$ are between $x\submin$ and $x\submax$,
+if we write $w_k=(u_k,v_k)$ and $z_k=(x_k,y_k)$ and $u\submin=
+\min(u_0,u_1,u_2,u_3)$, etc. These intervals of $x$~coordinates
+overlap if and only if $u\submin\L x\submax$ and
+$x\submin\L u\submax$. Letting
+$$U\submin=\min(0,U_1,U_1+U_2,U_1+U_2+U_3),\;
+ U\submax=\max(0,U_1,U_1+U_2,U_1+U_2+U_3),$$
+we have $2^lu\submin=2^lu_0+U\submin$, etc.; the condition for overlap
+reduces to
+$$X\submin-U\submax\L 2^l(u_0-x_0)\L X\submax-U\submin.$$
+Thus we want to maintain the quantity $2^l(u_0-x_0)$; similarly,
+the quantity $2^l(v_0-y_0)$ accounts for the $y$~coordinates. The
+coordinates of $\Delta=2^l(w_0-z_0)$ must stay bounded as $l$ increases,
+because of the overlap condition; i.e., we know that $X\submin$,
+$X\submax$, and their relatives are bounded, hence $X\submax-
+U\submin$ and $X\submin-U\submax$ are bounded.
+
+@ Incidentally, if the given cubics intersect more than once, the process
+just sketched will not necessarily find the lexicographically smallest pair
+$(t_1,t_2)$. The solution actually obtained will be smallest in ``shuffled
+order''; i.e., if $t_1=(.a_1a_2\ldots a_{16})_2$ and
+$t_2=(.b_1b_2\ldots b_{16})_2$, then we will minimize
+$a_1b_1a_2b_2\ldots a_{16}b_{16}$, not
+$a_1a_2\ldots a_{16}b_1b_2\ldots b_{16}$.
+Shuffled order agrees with lexicographic order if all pairs of solutions
+$(t_1,t_2)$ and $(t_1',t_2')$ have the property that $t_1<t_1'$ iff
+$t_2<t_2'$; but in general, lexicographic order can be quite different,
+and the bisection algorithm would be substantially less efficient if it were
+constrained by lexicographic order.
+
+For example, suppose that an overlap has been found for $l=3$ and
+$(t_1,t_2)= (.101,.011)$ in binary, but that no overlap is produced by
+either of the alternatives $(.1010,.0110)$, $(.1010,.0111)$ at level~4.
+Then there is probably an intersection in one of the subintervals
+$(.1011,.011x)$; but lexicographic order would require us to explore
+$(.1010,.1xxx)$ and $(.1011,.00xx)$ and $(.1011,.010x)$ first. We wouldn't
+want to store all of the subdivision data for the second path, so the
+subdivisions would have to be regenerated many times. Such inefficiencies
+would be associated with every `1' in the binary representation of~$t_1$.
+
+@ The subdivision process introduces rounding errors, hence we need to
+make a more liberal test for overlap. It is not hard to show that the
+computed values of $U_i$ differ from the truth by at most~$l$, on
+level~$l$, hence $U\submin$ and $U\submax$ will be at most $3l$ in error.
+If $\beta$ is an upper bound on the absolute error in the computed
+components of $\Delta=(|delx|,|dely|)$ on level~$l$, we will replace
+the test `$X\submin-U\submax\L|delx|$' by the more liberal test
+`$X\submin-U\submax\L|delx|+|tol|$', where $|tol|=6l+\beta$.
+
+More accuracy is obtained if we try the algorithm first with |tol=0|;
+the more liberal tolerance is used only if an exact approach fails.
+It is convenient to do this double-take by letting `3' in the preceding
+paragraph be a parameter, which is first 0, then 3.
+
+@<Glob...@>=
+unsigned int tol_step; /* either 0 or 3, usually */
+
+@ We shall use an explicit stack to implement the recursive bisection
+method described above. The |bisect_stack| array will contain numerous 5-word
+packets like $(U_1,U_2,U_3,U\submin,U\submax)$, as well as 20-word packets
+comprising the 5-word packets for $U$, $V$, $X$, and~$Y$.
+
+The following macros define the allocation of stack positions to
+the quantities needed for bisection-intersection.
+
+@d stack_1(A) mp->bisect_stack[(A)] /* $U_1$, $V_1$, $X_1$, or $Y_1$ */
+@d stack_2(A) mp->bisect_stack[(A)+1] /* $U_2$, $V_2$, $X_2$, or $Y_2$ */
+@d stack_3(A) mp->bisect_stack[(A)+2] /* $U_3$, $V_3$, $X_3$, or $Y_3$ */
+@d stack_min(A) mp->bisect_stack[(A)+3]
+ /* $U\submin$, $V\submin$, $X\submin$, or $Y\submin$ */
+@d stack_max(A) mp->bisect_stack[(A)+4]
+ /* $U\submax$, $V\submax$, $X\submax$, or $Y\submax$ */
+@d int_packets 20 /* number of words to represent $U_k$, $V_k$, $X_k$, and $Y_k$ */
+@#
+@d u_packet(A) ((A)-5)
+@d v_packet(A) ((A)-10)
+@d x_packet(A) ((A)-15)
+@d y_packet(A) ((A)-20)
+@d l_packets (mp->bisect_ptr-int_packets)
+@d r_packets mp->bisect_ptr
+@d ul_packet u_packet(l_packets) /* base of $U'_k$ variables */
+@d vl_packet v_packet(l_packets) /* base of $V'_k$ variables */
+@d xl_packet x_packet(l_packets) /* base of $X'_k$ variables */
+@d yl_packet y_packet(l_packets) /* base of $Y'_k$ variables */
+@d ur_packet u_packet(r_packets) /* base of $U''_k$ variables */
+@d vr_packet v_packet(r_packets) /* base of $V''_k$ variables */
+@d xr_packet x_packet(r_packets) /* base of $X''_k$ variables */
+@d yr_packet y_packet(r_packets) /* base of $Y''_k$ variables */
+@#
+@d u1l stack_1(ul_packet) /* $U'_1$ */
+@d u2l stack_2(ul_packet) /* $U'_2$ */
+@d u3l stack_3(ul_packet) /* $U'_3$ */
+@d v1l stack_1(vl_packet) /* $V'_1$ */
+@d v2l stack_2(vl_packet) /* $V'_2$ */
+@d v3l stack_3(vl_packet) /* $V'_3$ */
+@d x1l stack_1(xl_packet) /* $X'_1$ */
+@d x2l stack_2(xl_packet) /* $X'_2$ */
+@d x3l stack_3(xl_packet) /* $X'_3$ */
+@d y1l stack_1(yl_packet) /* $Y'_1$ */
+@d y2l stack_2(yl_packet) /* $Y'_2$ */
+@d y3l stack_3(yl_packet) /* $Y'_3$ */
+@d u1r stack_1(ur_packet) /* $U''_1$ */
+@d u2r stack_2(ur_packet) /* $U''_2$ */
+@d u3r stack_3(ur_packet) /* $U''_3$ */
+@d v1r stack_1(vr_packet) /* $V''_1$ */
+@d v2r stack_2(vr_packet) /* $V''_2$ */
+@d v3r stack_3(vr_packet) /* $V''_3$ */
+@d x1r stack_1(xr_packet) /* $X''_1$ */
+@d x2r stack_2(xr_packet) /* $X''_2$ */
+@d x3r stack_3(xr_packet) /* $X''_3$ */
+@d y1r stack_1(yr_packet) /* $Y''_1$ */
+@d y2r stack_2(yr_packet) /* $Y''_2$ */
+@d y3r stack_3(yr_packet) /* $Y''_3$ */
+@#
+@d stack_dx mp->bisect_stack[mp->bisect_ptr] /* stacked value of |delx| */
+@d stack_dy mp->bisect_stack[mp->bisect_ptr+1] /* stacked value of |dely| */
+@d stack_tol mp->bisect_stack[mp->bisect_ptr+2] /* stacked value of |tol| */
+@d stack_uv mp->bisect_stack[mp->bisect_ptr+3] /* stacked value of |uv| */
+@d stack_xy mp->bisect_stack[mp->bisect_ptr+4] /* stacked value of |xy| */
+@d int_increment (int_packets+int_packets+5) /* number of stack words per level */
+
+@<Glob...@>=
+integer *bisect_stack;
+unsigned int bisect_ptr;
+
+@ @<Allocate or initialize ...@>=
+mp->bisect_stack = xmalloc((bistack_size+1),sizeof(integer));
+
+@ @<Dealloc variables@>=
+xfree(mp->bisect_stack);
+
+@ @<Check the ``constant''...@>=
+if ( int_packets+17*int_increment>bistack_size ) mp->bad=19;
+
+@ Computation of the min and max is a tedious but fairly fast sequence of
+instructions; exactly four comparisons are made in each branch.
+
+@d set_min_max(A)
+ if ( stack_1((A))<0 ) {
+ if ( stack_3((A))>=0 ) {
+ if ( stack_2((A))<0 ) stack_min((A))=stack_1((A))+stack_2((A));
+ else stack_min((A))=stack_1((A));
+ stack_max((A))=stack_1((A))+stack_2((A))+stack_3((A));
+ if ( stack_max((A))<0 ) stack_max((A))=0;
+ } else {
+ stack_min((A))=stack_1((A))+stack_2((A))+stack_3((A));
+ if ( stack_min((A))>stack_1((A)) ) stack_min((A))=stack_1((A));
+ stack_max((A))=stack_1((A))+stack_2((A));
+ if ( stack_max((A))<0 ) stack_max((A))=0;
+ }
+ } else if ( stack_3((A))<=0 ) {
+ if ( stack_2((A))>0 ) stack_max((A))=stack_1((A))+stack_2((A));
+ else stack_max((A))=stack_1((A));
+ stack_min((A))=stack_1((A))+stack_2((A))+stack_3((A));
+ if ( stack_min((A))>0 ) stack_min((A))=0;
+ } else {
+ stack_max((A))=stack_1((A))+stack_2((A))+stack_3((A));
+ if ( stack_max((A))<stack_1((A)) ) stack_max((A))=stack_1((A));
+ stack_min((A))=stack_1((A))+stack_2((A));
+ if ( stack_min((A))>0 ) stack_min((A))=0;
+ }
+
+@ It's convenient to keep the current values of $l$, $t_1$, and $t_2$ in
+the integer form $2^l+2^lt_1$ and $2^l+2^lt_2$. The |cubic_intersection|
+routine uses global variables |cur_t| and |cur_tt| for this purpose;
+after successful completion, |cur_t| and |cur_tt| will contain |unity|
+plus the |scaled| values of $t_1$ and~$t_2$.
+
+The values of |cur_t| and |cur_tt| will be set to zero if |cubic_intersection|
+finds no intersection. The routine gives up and gives an approximate answer
+if it has backtracked
+more than 5000 times (otherwise there are cases where several minutes
+of fruitless computation would be possible).
+
+@d max_patience 5000
+
+@<Glob...@>=
+integer cur_t;integer cur_tt; /* controls and results of |cubic_intersection| */
+integer time_to_go; /* this many backtracks before giving up */
+integer max_t; /* maximum of $2^{l+1}$ so far achieved */
+
+@ The given cubics $B(w_0,w_1,w_2,w_3;t)$ and
+$B(z_0,z_1,z_2,z_3;t)$ are specified in adjacent knot nodes |(p,link(p))|
+and |(pp,link(pp))|, respectively.
+
+@c void mp_cubic_intersection (MP mp,pointer p, pointer pp) {
+ pointer q,qq; /* |link(p)|, |link(pp)| */
+ mp->time_to_go=max_patience; mp->max_t=2;
+ @<Initialize for intersections at level zero@>;
+CONTINUE:
+ while (1) {
+ if ( mp->delx-mp->tol<=stack_max(x_packet(mp->xy))-stack_min(u_packet(mp->uv)))
+ if ( mp->delx+mp->tol>=stack_min(x_packet(mp->xy))-stack_max(u_packet(mp->uv)))
+ if ( mp->dely-mp->tol<=stack_max(y_packet(mp->xy))-stack_min(v_packet(mp->uv)))
+ if ( mp->dely+mp->tol>=stack_min(y_packet(mp->xy))-stack_max(v_packet(mp->uv)))
+ {
+ if ( mp->cur_t>=mp->max_t ){
+ if ( mp->max_t==two ) { /* we've done 17 bisections */
+ mp->cur_t=halfp(mp->cur_t+1);
+ mp->cur_tt=halfp(mp->cur_tt+1);
+ return;
+ }
+ mp->max_t+=mp->max_t; mp->appr_t=mp->cur_t; mp->appr_tt=mp->cur_tt;
+ }
+ @<Subdivide for a new level of intersection@>;
+ goto CONTINUE;
+ }
+ if ( mp->time_to_go>0 ) {
+ decr(mp->time_to_go);
+ } else {
+ while ( mp->appr_t<unity ) {
+ mp->appr_t+=mp->appr_t; mp->appr_tt+=mp->appr_tt;
+ }
+ mp->cur_t=mp->appr_t; mp->cur_tt=mp->appr_tt; return;
+ }
+ @<Advance to the next pair |(cur_t,cur_tt)|@>;
+ }
+}
+
+@ The following variables are global, although they are used only by
+|cubic_intersection|, because it is necessary on some machines to
+split |cubic_intersection| up into two procedures.
+
+@<Glob...@>=
+integer delx;integer dely; /* the components of $\Delta=2^l(w_0-z_0)$ */
+integer tol; /* bound on the uncertainty in the overlap test */
+unsigned int uv;
+unsigned int xy; /* pointers to the current packets of interest */
+integer three_l; /* |tol_step| times the bisection level */
+integer appr_t;integer appr_tt; /* best approximations known to the answers */
+
+@ We shall assume that the coordinates are sufficiently non-extreme that
+integer overflow will not occur.
+@^overflow in arithmetic@>
+
+@<Initialize for intersections at level zero@>=
+q=link(p); qq=link(pp); mp->bisect_ptr=int_packets;
+u1r=right_x(p)-x_coord(p); u2r=left_x(q)-right_x(p);
+u3r=x_coord(q)-left_x(q); set_min_max(ur_packet);
+v1r=right_y(p)-y_coord(p); v2r=left_y(q)-right_y(p);
+v3r=y_coord(q)-left_y(q); set_min_max(vr_packet);
+x1r=right_x(pp)-x_coord(pp); x2r=left_x(qq)-right_x(pp);
+x3r=x_coord(qq)-left_x(qq); set_min_max(xr_packet);
+y1r=right_y(pp)-y_coord(pp); y2r=left_y(qq)-right_y(pp);
+y3r=y_coord(qq)-left_y(qq); set_min_max(yr_packet);
+mp->delx=x_coord(p)-x_coord(pp); mp->dely=y_coord(p)-y_coord(pp);
+mp->tol=0; mp->uv=r_packets; mp->xy=r_packets;
+mp->three_l=0; mp->cur_t=1; mp->cur_tt=1
+
+@ @<Subdivide for a new level of intersection@>=
+stack_dx=mp->delx; stack_dy=mp->dely; stack_tol=mp->tol;
+stack_uv=mp->uv; stack_xy=mp->xy;
+mp->bisect_ptr=mp->bisect_ptr+int_increment;
+mp->cur_t+=mp->cur_t; mp->cur_tt+=mp->cur_tt;
+u1l=stack_1(u_packet(mp->uv)); u3r=stack_3(u_packet(mp->uv));
+u2l=half(u1l+stack_2(u_packet(mp->uv)));
+u2r=half(u3r+stack_2(u_packet(mp->uv)));
+u3l=half(u2l+u2r); u1r=u3l;
+set_min_max(ul_packet); set_min_max(ur_packet);
+v1l=stack_1(v_packet(mp->uv)); v3r=stack_3(v_packet(mp->uv));
+v2l=half(v1l+stack_2(v_packet(mp->uv)));
+v2r=half(v3r+stack_2(v_packet(mp->uv)));
+v3l=half(v2l+v2r); v1r=v3l;
+set_min_max(vl_packet); set_min_max(vr_packet);
+x1l=stack_1(x_packet(mp->xy)); x3r=stack_3(x_packet(mp->xy));
+x2l=half(x1l+stack_2(x_packet(mp->xy)));
+x2r=half(x3r+stack_2(x_packet(mp->xy)));
+x3l=half(x2l+x2r); x1r=x3l;
+set_min_max(xl_packet); set_min_max(xr_packet);
+y1l=stack_1(y_packet(mp->xy)); y3r=stack_3(y_packet(mp->xy));
+y2l=half(y1l+stack_2(y_packet(mp->xy)));
+y2r=half(y3r+stack_2(y_packet(mp->xy)));
+y3l=half(y2l+y2r); y1r=y3l;
+set_min_max(yl_packet); set_min_max(yr_packet);
+mp->uv=l_packets; mp->xy=l_packets;
+mp->delx+=mp->delx; mp->dely+=mp->dely;
+mp->tol=mp->tol-mp->three_l+mp->tol_step;
+mp->tol+=mp->tol; mp->three_l=mp->three_l+mp->tol_step
+
+@ @<Advance to the next pair |(cur_t,cur_tt)|@>=
+NOT_FOUND:
+if ( odd(mp->cur_tt) ) {
+ if ( odd(mp->cur_t) ) {
+ @<Descend to the previous level and |goto not_found|@>;
+ } else {
+ incr(mp->cur_t);
+ mp->delx=mp->delx+stack_1(u_packet(mp->uv))+stack_2(u_packet(mp->uv))
+ +stack_3(u_packet(mp->uv));
+ mp->dely=mp->dely+stack_1(v_packet(mp->uv))+stack_2(v_packet(mp->uv))
+ +stack_3(v_packet(mp->uv));
+ mp->uv=mp->uv+int_packets; /* switch from |l_packets| to |r_packets| */
+ decr(mp->cur_tt); mp->xy=mp->xy-int_packets;
+ /* switch from |r_packets| to |l_packets| */
+ mp->delx=mp->delx+stack_1(x_packet(mp->xy))+stack_2(x_packet(mp->xy))
+ +stack_3(x_packet(mp->xy));
+ mp->dely=mp->dely+stack_1(y_packet(mp->xy))+stack_2(y_packet(mp->xy))
+ +stack_3(y_packet(mp->xy));
+ }
+} else {
+ incr(mp->cur_tt); mp->tol=mp->tol+mp->three_l;
+ mp->delx=mp->delx-stack_1(x_packet(mp->xy))-stack_2(x_packet(mp->xy))
+ -stack_3(x_packet(mp->xy));
+ mp->dely=mp->dely-stack_1(y_packet(mp->xy))-stack_2(y_packet(mp->xy))
+ -stack_3(y_packet(mp->xy));
+ mp->xy=mp->xy+int_packets; /* switch from |l_packets| to |r_packets| */
+}
+
+@ @<Descend to the previous level...@>=
+{
+ mp->cur_t=halfp(mp->cur_t); mp->cur_tt=halfp(mp->cur_tt);
+ if ( mp->cur_t==0 ) return;
+ mp->bisect_ptr=mp->bisect_ptr-int_increment;
+ mp->three_l=mp->three_l-mp->tol_step;
+ mp->delx=stack_dx; mp->dely=stack_dy; mp->tol=stack_tol;
+ mp->uv=stack_uv; mp->xy=stack_xy;
+ goto NOT_FOUND;
+}
+
+@ The |path_intersection| procedure is much simpler.
+It invokes |cubic_intersection| in lexicographic order until finding a
+pair of cubics that intersect. The final intersection times are placed in
+|cur_t| and~|cur_tt|.
+
+@c void mp_path_intersection (MP mp,pointer h, pointer hh) {
+ pointer p,pp; /* link registers that traverse the given paths */
+ integer n,nn; /* integer parts of intersection times, minus |unity| */
+ @<Change one-point paths into dead cycles@>;
+ mp->tol_step=0;
+ do {
+ n=-unity; p=h;
+ do {
+ if ( right_type(p)!=mp_endpoint ) {
+ nn=-unity; pp=hh;
+ do {
+ if ( right_type(pp)!=mp_endpoint ) {
+ mp_cubic_intersection(mp, p,pp);
+ if ( mp->cur_t>0 ) {
+ mp->cur_t=mp->cur_t+n; mp->cur_tt=mp->cur_tt+nn;
+ return;
+ }
+ }
+ nn=nn+unity; pp=link(pp);
+ } while (pp!=hh);
+ }
+ n=n+unity; p=link(p);
+ } while (p!=h);
+ mp->tol_step=mp->tol_step+3;
+ } while (mp->tol_step<=3);
+ mp->cur_t=-unity; mp->cur_tt=-unity;
+}
+
+@ @<Change one-point paths...@>=
+if ( right_type(h)==mp_endpoint ) {
+ right_x(h)=x_coord(h); left_x(h)=x_coord(h);
+ right_y(h)=y_coord(h); left_y(h)=y_coord(h); right_type(h)=mp_explicit;
+}
+if ( right_type(hh)==mp_endpoint ) {
+ right_x(hh)=x_coord(hh); left_x(hh)=x_coord(hh);
+ right_y(hh)=y_coord(hh); left_y(hh)=y_coord(hh); right_type(hh)=mp_explicit;
+}
+
+@* \[24] Dynamic linear equations.
+\MP\ users define variables implicitly by stating equations that should be
+satisfied; the computer is supposed to be smart enough to solve those equations.
+And indeed, the computer tries valiantly to do so, by distinguishing five
+different types of numeric values:
+
+\smallskip\hang
+|type(p)=mp_known| is the nice case, when |value(p)| is the |scaled| value
+of the variable whose address is~|p|.
+
+\smallskip\hang
+|type(p)=mp_dependent| means that |value(p)| is not present, but |dep_list(p)|
+points to a {\sl dependency list\/} that expresses the value of variable~|p|
+as a |scaled| number plus a sum of independent variables with |fraction|
+coefficients.
+
+\smallskip\hang
+|type(p)=mp_independent| means that |value(p)=64s+m|, where |s>0| is a ``serial
+number'' reflecting the time this variable was first used in an equation;
+also |0<=m<64|, and each dependent variable
+that refers to this one is actually referring to the future value of
+this variable times~$2^m$. (Usually |m=0|, but higher degrees of
+scaling are sometimes needed to keep the coefficients in dependency lists
+from getting too large. The value of~|m| will always be even.)
+
+\smallskip\hang
+|type(p)=mp_numeric_type| means that variable |p| hasn't appeared in an
+equation before, but it has been explicitly declared to be numeric.
+
+\smallskip\hang
+|type(p)=undefined| means that variable |p| hasn't appeared before.
+
+\smallskip\noindent
+We have actually discussed these five types in the reverse order of their
+history during a computation: Once |known|, a variable never again
+becomes |dependent|; once |dependent|, it almost never again becomes
+|mp_independent|; once |mp_independent|, it never again becomes |mp_numeric_type|;
+and once |mp_numeric_type|, it never again becomes |undefined| (except
+of course when the user specifically decides to scrap the old value
+and start again). A backward step may, however, take place: Sometimes
+a |dependent| variable becomes |mp_independent| again, when one of the
+independent variables it depends on is reverting to |undefined|.
+
+
+The next patch detects overflow of independent-variable serial
+numbers. Diagnosed and patched by Thorsten Dahlheimer.
+
+@d s_scale 64 /* the serial numbers are multiplied by this factor */
+@d new_indep(A) /* create a new independent variable */
+ { if ( mp->serial_no>el_gordo-s_scale )
+ mp_fatal_error(mp, "variable instance identifiers exhausted");
+ type((A))=mp_independent; mp->serial_no=mp->serial_no+s_scale;
+ value((A))=mp->serial_no;
+ }
+
+@<Glob...@>=
+integer serial_no; /* the most recent serial number, times |s_scale| */
+
+@ @<Make variable |q+s| newly independent@>=new_indep(q+s)
+
+@ But how are dependency lists represented? It's simple: The linear combination
+$\alpha_1v_1+\cdots+\alpha_kv_k+\beta$ appears in |k+1| value nodes. If
+|q=dep_list(p)| points to this list, and if |k>0|, then |value(q)=
+@t$\alpha_1$@>| (which is a |fraction|); |info(q)| points to the location
+of $\alpha_1$; and |link(p)| points to the dependency list
+$\alpha_2v_2+\cdots+\alpha_kv_k+\beta$. On the other hand if |k=0|,
+then |value(q)=@t$\beta$@>| (which is |scaled|) and |info(q)=null|.
+The independent variables $v_1$, \dots,~$v_k$ have been sorted so that
+they appear in decreasing order of their |value| fields (i.e., of
+their serial numbers). \ (It is convenient to use decreasing order,
+since |value(null)=0|. If the independent variables were not sorted by
+serial number but by some other criterion, such as their location in |mem|,
+the equation-solving mechanism would be too system-dependent, because
+the ordering can affect the computed results.)
+
+The |link| field in the node that contains the constant term $\beta$ is
+called the {\sl final link\/} of the dependency list. \MP\ maintains
+a doubly-linked master list of all dependency lists, in terms of a permanently
+allocated node
+in |mem| called |dep_head|. If there are no dependencies, we have
+|link(dep_head)=dep_head| and |prev_dep(dep_head)=dep_head|;
+otherwise |link(dep_head)| points to the first dependent variable, say~|p|,
+and |prev_dep(p)=dep_head|. We have |type(p)=mp_dependent|, and |dep_list(p)|
+points to its dependency list. If the final link of that dependency list
+occurs in location~|q|, then |link(q)| points to the next dependent
+variable (say~|r|); and we have |prev_dep(r)=q|, etc.
+
+@d dep_list(A) link(value_loc((A)))
+ /* half of the |value| field in a |dependent| variable */
+@d prev_dep(A) info(value_loc((A)))
+ /* the other half; makes a doubly linked list */
+@d dep_node_size 2 /* the number of words per dependency node */
+
+@<Initialize table entries...@>= mp->serial_no=0;
+link(dep_head)=dep_head; prev_dep(dep_head)=dep_head;
+info(dep_head)=null; dep_list(dep_head)=null;
+
+@ Actually the description above contains a little white lie. There's
+another kind of variable called |mp_proto_dependent|, which is
+just like a |dependent| one except that the $\alpha$ coefficients
+in its dependency list are |scaled| instead of being fractions.
+Proto-dependency lists are mixed with dependency lists in the
+nodes reachable from |dep_head|.
+
+@ Here is a procedure that prints a dependency list in symbolic form.
+The second parameter should be either |dependent| or |mp_proto_dependent|,
+to indicate the scaling of the coefficients.
+
+@<Declare subroutines for printing expressions@>=
+void mp_print_dependency (MP mp,pointer p, small_number t) {
+ integer v; /* a coefficient */
+ pointer pp,q; /* for list manipulation */
+ pp=p;
+ while (1) {
+ v=abs(value(p)); q=info(p);
+ if ( q==null ) { /* the constant term */
+ if ( (v!=0)||(p==pp) ) {
+ if ( value(p)>0 ) if ( p!=pp ) mp_print_char(mp, '+');
+ mp_print_scaled(mp, value(p));
+ }
+ return;
+ }
+ @<Print the coefficient, unless it's $\pm1.0$@>;
+ if ( type(q)!=mp_independent ) mp_confusion(mp, "dep");
+@:this can't happen dep}{\quad dep@>
+ mp_print_variable_name(mp, q); v=value(q) % s_scale;
+ while ( v>0 ) { mp_print(mp, "*4"); v=v-2; }
+ p=link(p);
+ }
+}
+
+@ @<Print the coefficient, unless it's $\pm1.0$@>=
+if ( value(p)<0 ) mp_print_char(mp, '-');
+else if ( p!=pp ) mp_print_char(mp, '+');
+if ( t==mp_dependent ) v=mp_round_fraction(mp, v);
+if ( v!=unity ) mp_print_scaled(mp, v)
+
+@ The maximum absolute value of a coefficient in a given dependency list
+is returned by the following simple function.
+
+@c fraction mp_max_coef (MP mp,pointer p) {
+ fraction x; /* the maximum so far */
+ x=0;
+ while ( info(p)!=null ) {
+ if ( abs(value(p))>x ) x=abs(value(p));
+ p=link(p);
+ }
+ return x;
+}
+
+@ One of the main operations needed on dependency lists is to add a multiple
+of one list to the other; we call this |p_plus_fq|, where |p| and~|q| point
+to dependency lists and |f| is a fraction.
+
+If the coefficient of any independent variable becomes |coef_bound| or
+more, in absolute value, this procedure changes the type of that variable
+to `|independent_needing_fix|', and sets the global variable |fix_needed|
+to~|true|. The value of $|coef_bound|=\mu$ is chosen so that
+$\mu^2+\mu<8$; this means that the numbers we deal with won't
+get too large. (Instead of the ``optimum'' $\mu=(\sqrt{33}-1)/2\approx
+2.3723$, the safer value 7/3 is taken as the threshold.)
+
+The changes mentioned in the preceding paragraph are actually done only if
+the global variable |watch_coefs| is |true|. But it usually is; in fact,
+it is |false| only when \MP\ is making a dependency list that will soon
+be equated to zero.
+
+Several procedures that act on dependency lists, including |p_plus_fq|,
+set the global variable |dep_final| to the final (constant term) node of
+the dependency list that they produce.
+
+@d coef_bound 04525252525 /* |fraction| approximation to 7/3 */
+@d independent_needing_fix 0
+
+@<Glob...@>=
+boolean fix_needed; /* does at least one |independent| variable need scaling? */
+boolean watch_coefs; /* should we scale coefficients that exceed |coef_bound|? */
+pointer dep_final; /* location of the constant term and final link */
+
+@ @<Set init...@>=
+mp->fix_needed=false; mp->watch_coefs=true;
+
+@ The |p_plus_fq| procedure has a fourth parameter, |t|, that should be
+set to |mp_proto_dependent| if |p| is a proto-dependency list. In this
+case |f| will be |scaled|, not a |fraction|. Similarly, the fifth parameter~|tt|
+should be |mp_proto_dependent| if |q| is a proto-dependency list.
+
+List |q| is unchanged by the operation; but list |p| is totally destroyed.
+
+The final link of the dependency list or proto-dependency list returned
+by |p_plus_fq| is the same as the original final link of~|p|. Indeed, the
+constant term of the result will be located in the same |mem| location
+as the original constant term of~|p|.
+
+Coefficients of the result are assumed to be zero if they are less than
+a certain threshold. This compensates for inevitable rounding errors,
+and tends to make more variables `|known|'. The threshold is approximately
+$10^{-5}$ in the case of normal dependency lists, $10^{-4}$ for
+proto-dependencies.
+
+@d fraction_threshold 2685 /* a |fraction| coefficient less than this is zeroed */
+@d half_fraction_threshold 1342 /* half of |fraction_threshold| */
+@d scaled_threshold 8 /* a |scaled| coefficient less than this is zeroed */
+@d half_scaled_threshold 4 /* half of |scaled_threshold| */
+
+@<Declare basic dependency-list subroutines@>=
+pointer mp_p_plus_fq ( MP mp, pointer p, integer f,
+ pointer q, small_number t, small_number tt) ;
+
+@ @c
+pointer mp_p_plus_fq ( MP mp, pointer p, integer f,
+ pointer q, small_number t, small_number tt) {
+ pointer pp,qq; /* |info(p)| and |info(q)|, respectively */
+ pointer r,s; /* for list manipulation */
+ integer threshold; /* defines a neighborhood of zero */
+ integer v; /* temporary register */
+ if ( t==mp_dependent ) threshold=fraction_threshold;
+ else threshold=scaled_threshold;
+ r=temp_head; pp=info(p); qq=info(q);
+ while (1) {
+ if ( pp==qq ) {
+ if ( pp==null ) {
+ break;
+ } else {
+ @<Contribute a term from |p|, plus |f| times the
+ corresponding term from |q|@>
+ }
+ } else if ( value(pp)<value(qq) ) {
+ @<Contribute a term from |q|, multiplied by~|f|@>
+ } else {
+ link(r)=p; r=p; p=link(p); pp=info(p);
+ }
+ }
+ if ( t==mp_dependent )
+ value(p)=mp_slow_add(mp, value(p),mp_take_fraction(mp, value(q),f));
+ else
+ value(p)=mp_slow_add(mp, value(p),mp_take_scaled(mp, value(q),f));
+ link(r)=p; mp->dep_final=p;
+ return link(temp_head);
+}
+
+@ @<Contribute a term from |p|, plus |f|...@>=
+{
+ if ( tt==mp_dependent ) v=value(p)+mp_take_fraction(mp, f,value(q));
+ else v=value(p)+mp_take_scaled(mp, f,value(q));
+ value(p)=v; s=p; p=link(p);
+ if ( abs(v)<threshold ) {
+ mp_free_node(mp, s,dep_node_size);
+ } else {
+ if ( (abs(v)>=coef_bound) && mp->watch_coefs ) {
+ type(qq)=independent_needing_fix; mp->fix_needed=true;
+ }
+ link(r)=s; r=s;
+ };
+ pp=info(p); q=link(q); qq=info(q);
+}
+
+@ @<Contribute a term from |q|, multiplied by~|f|@>=
+{
+ if ( tt==mp_dependent ) v=mp_take_fraction(mp, f,value(q));
+ else v=mp_take_scaled(mp, f,value(q));
+ if ( abs(v)>halfp(threshold) ) {
+ s=mp_get_node(mp, dep_node_size); info(s)=qq; value(s)=v;
+ if ( (abs(v)>=coef_bound) && mp->watch_coefs ) {
+ type(qq)=independent_needing_fix; mp->fix_needed=true;
+ }
+ link(r)=s; r=s;
+ }
+ q=link(q); qq=info(q);
+}
+
+@ It is convenient to have another subroutine for the special case
+of |p_plus_fq| when |f=1.0|. In this routine lists |p| and |q| are
+both of the same type~|t| (either |dependent| or |mp_proto_dependent|).
+
+@c pointer mp_p_plus_q (MP mp,pointer p, pointer q, small_number t) {
+ pointer pp,qq; /* |info(p)| and |info(q)|, respectively */
+ pointer r,s; /* for list manipulation */
+ integer threshold; /* defines a neighborhood of zero */
+ integer v; /* temporary register */
+ if ( t==mp_dependent ) threshold=fraction_threshold;
+ else threshold=scaled_threshold;
+ r=temp_head; pp=info(p); qq=info(q);
+ while (1) {
+ if ( pp==qq ) {
+ if ( pp==null ) {
+ break;
+ } else {
+ @<Contribute a term from |p|, plus the
+ corresponding term from |q|@>
+ }
+ } else {
+ if ( value(pp)<value(qq) ) {
+ s=mp_get_node(mp, dep_node_size); info(s)=qq; value(s)=value(q);
+ q=link(q); qq=info(q); link(r)=s; r=s;
+ } else {
+ link(r)=p; r=p; p=link(p); pp=info(p);
+ }
+ }
+ }
+ value(p)=mp_slow_add(mp, value(p),value(q));
+ link(r)=p; mp->dep_final=p;
+ return link(temp_head);
+}
+
+@ @<Contribute a term from |p|, plus the...@>=
+{
+ v=value(p)+value(q);
+ value(p)=v; s=p; p=link(p); pp=info(p);
+ if ( abs(v)<threshold ) {
+ mp_free_node(mp, s,dep_node_size);
+ } else {
+ if ( (abs(v)>=coef_bound ) && mp->watch_coefs ) {
+ type(qq)=independent_needing_fix; mp->fix_needed=true;
+ }
+ link(r)=s; r=s;
+ }
+ q=link(q); qq=info(q);
+}
+
+@ A somewhat simpler routine will multiply a dependency list
+by a given constant~|v|. The constant is either a |fraction| less than
+|fraction_one|, or it is |scaled|. In the latter case we might be forced to
+convert a dependency list to a proto-dependency list.
+Parameters |t0| and |t1| are the list types before and after;
+they should agree unless |t0=mp_dependent| and |t1=mp_proto_dependent|
+and |v_is_scaled=true|.
+
+@c pointer mp_p_times_v (MP mp,pointer p, integer v, small_number t0,
+ small_number t1, boolean v_is_scaled) {
+ pointer r,s; /* for list manipulation */
+ integer w; /* tentative coefficient */
+ integer threshold;
+ boolean scaling_down;
+ if ( t0!=t1 ) scaling_down=true; else scaling_down=(!v_is_scaled);
+ if ( t1==mp_dependent ) threshold=half_fraction_threshold;
+ else threshold=half_scaled_threshold;
+ r=temp_head;
+ while ( info(p)!=null ) {
+ if ( scaling_down ) w=mp_take_fraction(mp, v,value(p));
+ else w=mp_take_scaled(mp, v,value(p));
+ if ( abs(w)<=threshold ) {
+ s=link(p); mp_free_node(mp, p,dep_node_size); p=s;
+ } else {
+ if ( abs(w)>=coef_bound ) {
+ mp->fix_needed=true; type(info(p))=independent_needing_fix;
+ }
+ link(r)=p; r=p; value(p)=w; p=link(p);
+ }
+ }
+ link(r)=p;
+ if ( v_is_scaled ) value(p)=mp_take_scaled(mp, value(p),v);
+ else value(p)=mp_take_fraction(mp, value(p),v);
+ return link(temp_head);
+}
+
+@ Similarly, we sometimes need to divide a dependency list
+by a given |scaled| constant.
+
+@<Declare basic dependency-list subroutines@>=
+pointer mp_p_over_v (MP mp,pointer p, scaled v, small_number
+ t0, small_number t1) ;
+
+@ @c
+pointer mp_p_over_v (MP mp,pointer p, scaled v, small_number
+ t0, small_number t1) {
+ pointer r,s; /* for list manipulation */
+ integer w; /* tentative coefficient */
+ integer threshold;
+ boolean scaling_down;
+ if ( t0!=t1 ) scaling_down=true; else scaling_down=false;
+ if ( t1==mp_dependent ) threshold=half_fraction_threshold;
+ else threshold=half_scaled_threshold;
+ r=temp_head;
+ while ( info( p)!=null ) {
+ if ( scaling_down ) {
+ if ( abs(v)<02000000 ) w=mp_make_scaled(mp, value(p),v*010000);
+ else w=mp_make_scaled(mp, mp_round_fraction(mp, value(p)),v);
+ } else {
+ w=mp_make_scaled(mp, value(p),v);
+ }
+ if ( abs(w)<=threshold ) {
+ s=link(p); mp_free_node(mp, p,dep_node_size); p=s;
+ } else {
+ if ( abs(w)>=coef_bound ) {
+ mp->fix_needed=true; type(info(p))=independent_needing_fix;
+ }
+ link(r)=p; r=p; value(p)=w; p=link(p);
+ }
+ }
+ link(r)=p; value(p)=mp_make_scaled(mp, value(p),v);
+ return link(temp_head);
+}
+
+@ Here's another utility routine for dependency lists. When an independent
+variable becomes dependent, we want to remove it from all existing
+dependencies. The |p_with_x_becoming_q| function computes the
+dependency list of~|p| after variable~|x| has been replaced by~|q|.
+
+This procedure has basically the same calling conventions as |p_plus_fq|:
+List~|q| is unchanged; list~|p| is destroyed; the constant node and the
+final link are inherited from~|p|; and the fourth parameter tells whether
+or not |p| is |mp_proto_dependent|. However, the global variable |dep_final|
+is not altered if |x| does not occur in list~|p|.
+
+@c pointer mp_p_with_x_becoming_q (MP mp,pointer p,
+ pointer x, pointer q, small_number t) {
+ pointer r,s; /* for list manipulation */
+ integer v; /* coefficient of |x| */
+ integer sx; /* serial number of |x| */
+ s=p; r=temp_head; sx=value(x);
+ while ( value(info(s))>sx ) { r=s; s=link(s); };
+ if ( info(s)!=x ) {
+ return p;
+ } else {
+ link(temp_head)=p; link(r)=link(s); v=value(s);
+ mp_free_node(mp, s,dep_node_size);
+ return mp_p_plus_fq(mp, link(temp_head),v,q,t,mp_dependent);
+ }
+}
+
+@ Here's a simple procedure that reports an error when a variable
+has just received a known value that's out of the required range.
+
+@<Declare basic dependency-list subroutines@>=
+void mp_val_too_big (MP mp,scaled x) ;
+
+@ @c void mp_val_too_big (MP mp,scaled x) {
+ if ( mp->internal[mp_warning_check]>0 ) {
+ print_err("Value is too large ("); mp_print_scaled(mp, x); mp_print_char(mp, ')');
+@.Value is too large@>
+ help4("The equation I just processed has given some variable")
+ ("a value of 4096 or more. Continue and I'll try to cope")
+ ("with that big value; but it might be dangerous.")
+ ("(Set warningcheck:=0 to suppress this message.)");
+ mp_error(mp);
+ }
+}
+
+@ When a dependent variable becomes known, the following routine
+removes its dependency list. Here |p| points to the variable, and
+|q| points to the dependency list (which is one node long).
+
+@<Declare basic dependency-list subroutines@>=
+void mp_make_known (MP mp,pointer p, pointer q) ;
+
+@ @c void mp_make_known (MP mp,pointer p, pointer q) {
+ int t; /* the previous type */
+ prev_dep(link(q))=prev_dep(p);
+ link(prev_dep(p))=link(q); t=type(p);
+ type(p)=mp_known; value(p)=value(q); mp_free_node(mp, q,dep_node_size);
+ if ( abs(value(p))>=fraction_one ) mp_val_too_big(mp, value(p));
+ if (( mp->internal[mp_tracing_equations]>0) && mp_interesting(mp, p) ) {
+ mp_begin_diagnostic(mp); mp_print_nl(mp, "#### ");
+@:]]]\#\#\#\#_}{\.{\#\#\#\#}@>
+ mp_print_variable_name(mp, p);
+ mp_print_char(mp, '='); mp_print_scaled(mp, value(p));
+ mp_end_diagnostic(mp, false);
+ }
+ if (( mp->cur_exp==p ) && mp->cur_type==t ) {
+ mp->cur_type=mp_known; mp->cur_exp=value(p);
+ mp_free_node(mp, p,value_node_size);
+ }
+}
+
+@ The |fix_dependencies| routine is called into action when |fix_needed|
+has been triggered. The program keeps a list~|s| of independent variables
+whose coefficients must be divided by~4.
+
+In unusual cases, this fixup process might reduce one or more coefficients
+to zero, so that a variable will become known more or less by default.
+
+@<Declare basic dependency-list subroutines@>=
+void mp_fix_dependencies (MP mp);
+
+@ @c void mp_fix_dependencies (MP mp) {
+ pointer p,q,r,s,t; /* list manipulation registers */
+ pointer x; /* an independent variable */
+ r=link(dep_head); s=null;
+ while ( r!=dep_head ){
+ t=r;
+ @<Run through the dependency list for variable |t|, fixing
+ all nodes, and ending with final link~|q|@>;
+ r=link(q);
+ if ( q==dep_list(t) ) mp_make_known(mp, t,q);
+ }
+ while ( s!=null ) {
+ p=link(s); x=info(s); free_avail(s); s=p;
+ type(x)=mp_independent; value(x)=value(x)+2;
+ }
+ mp->fix_needed=false;
+}
+
+@ @d independent_being_fixed 1 /* this variable already appears in |s| */
+
+@<Run through the dependency list for variable |t|...@>=
+r=value_loc(t); /* |link(r)=dep_list(t)| */
+while (1) {
+ q=link(r); x=info(q);
+ if ( x==null ) break;
+ if ( type(x)<=independent_being_fixed ) {
+ if ( type(x)<independent_being_fixed ) {
+ p=mp_get_avail(mp); link(p)=s; s=p;
+ info(s)=x; type(x)=independent_being_fixed;
+ }
+ value(q)=value(q) / 4;
+ if ( value(q)==0 ) {
+ link(r)=link(q); mp_free_node(mp, q,dep_node_size); q=r;
+ }
+ }
+ r=q;
+}
+
+
+@ The |new_dep| routine installs a dependency list~|p| into the value node~|q|,
+linking it into the list of all known dependencies. We assume that
+|dep_final| points to the final node of list~|p|.
+
+@c void mp_new_dep (MP mp,pointer q, pointer p) {
+ pointer r; /* what used to be the first dependency */
+ dep_list(q)=p; prev_dep(q)=dep_head;
+ r=link(dep_head); link(mp->dep_final)=r; prev_dep(r)=mp->dep_final;
+ link(dep_head)=q;
+}
+
+@ Here is one of the ways a dependency list gets started.
+The |const_dependency| routine produces a list that has nothing but
+a constant term.
+
+@c pointer mp_const_dependency (MP mp, scaled v) {
+ mp->dep_final=mp_get_node(mp, dep_node_size);
+ value(mp->dep_final)=v; info(mp->dep_final)=null;
+ return mp->dep_final;
+}
+
+@ And here's a more interesting way to start a dependency list from scratch:
+The parameter to |single_dependency| is the location of an
+independent variable~|x|, and the result is the simple dependency list
+`|x+0|'.
+
+In the unlikely event that the given independent variable has been doubled so
+often that we can't refer to it with a nonzero coefficient,
+|single_dependency| returns the simple list `0'. This case can be
+recognized by testing that the returned list pointer is equal to
+|dep_final|.
+
+@c pointer mp_single_dependency (MP mp,pointer p) {
+ pointer q; /* the new dependency list */
+ integer m; /* the number of doublings */
+ m=value(p) % s_scale;
+ if ( m>28 ) {
+ return mp_const_dependency(mp, 0);
+ } else {
+ q=mp_get_node(mp, dep_node_size);
+ value(q)=two_to_the(28-m); info(q)=p;
+ link(q)=mp_const_dependency(mp, 0);
+ return q;
+ }
+}
+
+@ We sometimes need to make an exact copy of a dependency list.
+
+@c pointer mp_copy_dep_list (MP mp,pointer p) {
+ pointer q; /* the new dependency list */
+ q=mp_get_node(mp, dep_node_size); mp->dep_final=q;
+ while (1) {
+ info(mp->dep_final)=info(p); value(mp->dep_final)=value(p);
+ if ( info(mp->dep_final)==null ) break;
+ link(mp->dep_final)=mp_get_node(mp, dep_node_size);
+ mp->dep_final=link(mp->dep_final); p=link(p);
+ }
+ return q;
+}
+
+@ But how do variables normally become known? Ah, now we get to the heart of the
+equation-solving mechanism. The |linear_eq| procedure is given a |dependent|
+or |mp_proto_dependent| list,~|p|, in which at least one independent variable
+appears. It equates this list to zero, by choosing an independent variable
+with the largest coefficient and making it dependent on the others. The
+newly dependent variable is eliminated from all current dependencies,
+thereby possibly making other dependent variables known.
+
+The given list |p| is, of course, totally destroyed by all this processing.
+
+@c void mp_linear_eq (MP mp, pointer p, small_number t) {
+ pointer q,r,s; /* for link manipulation */
+ pointer x; /* the variable that loses its independence */
+ integer n; /* the number of times |x| had been halved */
+ integer v; /* the coefficient of |x| in list |p| */
+ pointer prev_r; /* lags one step behind |r| */
+ pointer final_node; /* the constant term of the new dependency list */
+ integer w; /* a tentative coefficient */
+ @<Find a node |q| in list |p| whose coefficient |v| is largest@>;
+ x=info(q); n=value(x) % s_scale;
+ @<Divide list |p| by |-v|, removing node |q|@>;
+ if ( mp->internal[mp_tracing_equations]>0 ) {
+ @<Display the new dependency@>;
+ }
+ @<Simplify all existing dependencies by substituting for |x|@>;
+ @<Change variable |x| from |independent| to |dependent| or |known|@>;
+ if ( mp->fix_needed ) mp_fix_dependencies(mp);
+}
+
+@ @<Find a node |q| in list |p| whose coefficient |v| is largest@>=
+q=p; r=link(p); v=value(q);
+while ( info(r)!=null ) {
+ if ( abs(value(r))>abs(v) ) { q=r; v=value(r); };
+ r=link(r);
+}
+
+@ Here we want to change the coefficients from |scaled| to |fraction|,
+except in the constant term. In the common case of a trivial equation
+like `\.{x=3.14}', we will have |v=-fraction_one|, |q=p|, and |t=mp_dependent|.
+
+@<Divide list |p| by |-v|, removing node |q|@>=
+s=temp_head; link(s)=p; r=p;
+do {
+ if ( r==q ) {
+ link(s)=link(r); mp_free_node(mp, r,dep_node_size);
+ } else {
+ w=mp_make_fraction(mp, value(r),v);
+ if ( abs(w)<=half_fraction_threshold ) {
+ link(s)=link(r); mp_free_node(mp, r,dep_node_size);
+ } else {
+ value(r)=-w; s=r;
+ }
+ }
+ r=link(s);
+} while (info(r)!=null);
+if ( t==mp_proto_dependent ) {
+ value(r)=-mp_make_scaled(mp, value(r),v);
+} else if ( v!=-fraction_one ) {
+ value(r)=-mp_make_fraction(mp, value(r),v);
+}
+final_node=r; p=link(temp_head)
+
+@ @<Display the new dependency@>=
+if ( mp_interesting(mp, x) ) {
+ mp_begin_diagnostic(mp); mp_print_nl(mp, "## ");
+ mp_print_variable_name(mp, x);
+@:]]]\#\#_}{\.{\#\#}@>
+ w=n;
+ while ( w>0 ) { mp_print(mp, "*4"); w=w-2; };
+ mp_print_char(mp, '='); mp_print_dependency(mp, p,mp_dependent);
+ mp_end_diagnostic(mp, false);
+}
+
+@ @<Simplify all existing dependencies by substituting for |x|@>=
+prev_r=dep_head; r=link(dep_head);
+while ( r!=dep_head ) {
+ s=dep_list(r); q=mp_p_with_x_becoming_q(mp, s,x,p,type(r));
+ if ( info(q)==null ) {
+ mp_make_known(mp, r,q);
+ } else {
+ dep_list(r)=q;
+ do { q=link(q); } while (info(q)!=null);
+ prev_r=q;
+ }
+ r=link(prev_r);
+}
+
+@ @<Change variable |x| from |independent| to |dependent| or |known|@>=
+if ( n>0 ) @<Divide list |p| by $2^n$@>;
+if ( info(p)==null ) {
+ type(x)=mp_known;
+ value(x)=value(p);
+ if ( abs(value(x))>=fraction_one ) mp_val_too_big(mp, value(x));
+ mp_free_node(mp, p,dep_node_size);
+ if ( mp->cur_exp==x ) if ( mp->cur_type==mp_independent ) {
+ mp->cur_exp=value(x); mp->cur_type=mp_known;
+ mp_free_node(mp, x,value_node_size);
+ }
+} else {
+ type(x)=mp_dependent; mp->dep_final=final_node; mp_new_dep(mp, x,p);
+ if ( mp->cur_exp==x ) if ( mp->cur_type==mp_independent ) mp->cur_type=mp_dependent;
+}
+
+@ @<Divide list |p| by $2^n$@>=
+{
+ s=temp_head; link(temp_head)=p; r=p;
+ do {
+ if ( n>30 ) w=0;
+ else w=value(r) / two_to_the(n);
+ if ( (abs(w)<=half_fraction_threshold)&&(info(r)!=null) ) {
+ link(s)=link(r);
+ mp_free_node(mp, r,dep_node_size);
+ } else {
+ value(r)=w; s=r;
+ }
+ r=link(s);
+ } while (info(s)!=null);
+ p=link(temp_head);
+}
+
+@ The |check_mem| procedure, which is used only when \MP\ is being
+debugged, makes sure that the current dependency lists are well formed.
+
+@<Check the list of linear dependencies@>=
+q=dep_head; p=link(q);
+while ( p!=dep_head ) {
+ if ( prev_dep(p)!=q ) {
+ mp_print_nl(mp, "Bad PREVDEP at "); mp_print_int(mp, p);
+@.Bad PREVDEP...@>
+ }
+ p=dep_list(p);
+ while (1) {
+ r=info(p); q=p; p=link(q);
+ if ( r==null ) break;
+ if ( value(info(p))>=value(r) ) {
+ mp_print_nl(mp, "Out of order at "); mp_print_int(mp, p);
+@.Out of order...@>
+ }
+ }
+}
+
+@* \[25] Dynamic nonlinear equations.
+Variables of numeric type are maintained by the general scheme of
+independent, dependent, and known values that we have just studied;
+and the components of pair and transform variables are handled in the
+same way. But \MP\ also has five other types of values: \&{boolean},
+\&{string}, \&{pen}, \&{path}, and \&{picture}; what about them?
+
+Equations are allowed between nonlinear quantities, but only in a
+simple form. Two variables that haven't yet been assigned values are
+either equal to each other, or they're not.
+
+Before a boolean variable has received a value, its type is |mp_unknown_boolean|;
+similarly, there are variables whose type is |mp_unknown_string|, |mp_unknown_pen|,
+|mp_unknown_path|, and |mp_unknown_picture|. In such cases the value is either
+|null| (which means that no other variables are equivalent to this one), or
+it points to another variable of the same undefined type. The pointers in the
+latter case form a cycle of nodes, which we shall call a ``ring.''
+Rings of undefined variables may include capsules, which arise as
+intermediate results within expressions or as \&{expr} parameters to macros.
+
+When one member of a ring receives a value, the same value is given to
+all the other members. In the case of paths and pictures, this implies
+making separate copies of a potentially large data structure; users should
+restrain their enthusiasm for such generality, unless they have lots and
+lots of memory space.
+
+@ The following procedure is called when a capsule node is being
+added to a ring (e.g., when an unknown variable is mentioned in an expression).
+
+@c pointer mp_new_ring_entry (MP mp,pointer p) {
+ pointer q; /* the new capsule node */
+ q=mp_get_node(mp, value_node_size); name_type(q)=mp_capsule;
+ type(q)=type(p);
+ if ( value(p)==null ) value(q)=p; else value(q)=value(p);
+ value(p)=q;
+ return q;
+}
+
+@ Conversely, we might delete a capsule or a variable before it becomes known.
+The following procedure simply detaches a quantity from its ring,
+without recycling the storage.
+
+@<Declare the recycling subroutines@>=
+void mp_ring_delete (MP mp,pointer p) {
+ pointer q;
+ q=value(p);
+ if ( q!=null ) if ( q!=p ){
+ while ( value(q)!=p ) q=value(q);
+ value(q)=value(p);
+ }
+}
+
+@ Eventually there might be an equation that assigns values to all of the
+variables in a ring. The |nonlinear_eq| subroutine does the necessary
+propagation of values.
+
+If the parameter |flush_p| is |true|, node |p| itself needn't receive a
+value, it will soon be recycled.
+
+@c void mp_nonlinear_eq (MP mp,integer v, pointer p, boolean flush_p) {
+ small_number t; /* the type of ring |p| */
+ pointer q,r; /* link manipulation registers */
+ t=type(p)-unknown_tag; q=value(p);
+ if ( flush_p ) type(p)=mp_vacuous; else p=q;
+ do {
+ r=value(q); type(q)=t;
+ switch (t) {
+ case mp_boolean_type: value(q)=v; break;
+ case mp_string_type: value(q)=v; add_str_ref(v); break;
+ case mp_pen_type: value(q)=copy_pen(v); break;
+ case mp_path_type: value(q)=mp_copy_path(mp, v); break;
+ case mp_picture_type: value(q)=v; add_edge_ref(v); break;
+ } /* there ain't no more cases */
+ q=r;
+ } while (q!=p);
+}
+
+@ If two members of rings are equated, and if they have the same type,
+the |ring_merge| procedure is called on to make them equivalent.
+
+@c void mp_ring_merge (MP mp,pointer p, pointer q) {
+ pointer r; /* traverses one list */
+ r=value(p);
+ while ( r!=p ) {
+ if ( r==q ) {
+ @<Exclaim about a redundant equation@>;
+ return;
+ };
+ r=value(r);
+ }
+ r=value(p); value(p)=value(q); value(q)=r;
+}
+
+@ @<Exclaim about a redundant equation@>=
+{
+ print_err("Redundant equation");
+@.Redundant equation@>
+ help2("I already knew that this equation was true.")
+ ("But perhaps no harm has been done; let's continue.");
+ mp_put_get_error(mp);
+}
+
+@* \[26] Introduction to the syntactic routines.
+Let's pause a moment now and try to look at the Big Picture.
+The \MP\ program consists of three main parts: syntactic routines,
+semantic routines, and output routines. The chief purpose of the
+syntactic routines is to deliver the user's input to the semantic routines,
+while parsing expressions and locating operators and operands. The
+semantic routines act as an interpreter responding to these operators,
+which may be regarded as commands. And the output routines are
+periodically called on to produce compact font descriptions that can be
+used for typesetting or for making interim proof drawings. We have
+discussed the basic data structures and many of the details of semantic
+operations, so we are good and ready to plunge into the part of \MP\ that
+actually controls the activities.
+
+Our current goal is to come to grips with the |get_next| procedure,
+which is the keystone of \MP's input mechanism. Each call of |get_next|
+sets the value of three variables |cur_cmd|, |cur_mod|, and |cur_sym|,
+representing the next input token.
+$$\vbox{\halign{#\hfil\cr
+ \hbox{|cur_cmd| denotes a command code from the long list of codes
+ given earlier;}\cr
+ \hbox{|cur_mod| denotes a modifier of the command code;}\cr
+ \hbox{|cur_sym| is the hash address of the symbolic token that was
+ just scanned,}\cr
+ \hbox{\qquad or zero in the case of a numeric or string
+ or capsule token.}\cr}}$$
+Underlying this external behavior of |get_next| is all the machinery
+necessary to convert from character files to tokens. At a given time we
+may be only partially finished with the reading of several files (for
+which \&{input} was specified), and partially finished with the expansion
+of some user-defined macros and/or some macro parameters, and partially
+finished reading some text that the user has inserted online,
+and so on. When reading a character file, the characters must be
+converted to tokens; comments and blank spaces must
+be removed, numeric and string tokens must be evaluated.
+
+To handle these situations, which might all be present simultaneously,
+\MP\ uses various stacks that hold information about the incomplete
+activities, and there is a finite state control for each level of the
+input mechanism. These stacks record the current state of an implicitly
+recursive process, but the |get_next| procedure is not recursive.
+
+@<Glob...@>=
+eight_bits cur_cmd; /* current command set by |get_next| */
+integer cur_mod; /* operand of current command */
+halfword cur_sym; /* hash address of current symbol */
+
+@ The |print_cmd_mod| routine prints a symbolic interpretation of a
+command code and its modifier.
+It consists of a rather tedious sequence of print
+commands, and most of it is essentially an inverse to the |primitive|
+routine that enters a \MP\ primitive into |hash| and |eqtb|. Therefore almost
+all of this procedure appears elsewhere in the program, together with the
+corresponding |primitive| calls.
+
+@<Declare the procedure called |print_cmd_mod|@>=
+void mp_print_cmd_mod (MP mp,integer c, integer m) {
+ switch (c) {
+ @<Cases of |print_cmd_mod| for symbolic printing of primitives@>
+ default: mp_print(mp, "[unknown command code!]"); break;
+ }
+}
+
+@ Here is a procedure that displays a given command in braces, in the
+user's transcript file.
+
+@d show_cur_cmd_mod mp_show_cmd_mod(mp, mp->cur_cmd,mp->cur_mod)
+
+@c
+void mp_show_cmd_mod (MP mp,integer c, integer m) {
+ mp_begin_diagnostic(mp); mp_print_nl(mp, "{");
+ mp_print_cmd_mod(mp, c,m); mp_print_char(mp, '}');
+ mp_end_diagnostic(mp, false);
+}
+
+@* \[27] Input stacks and states.
+The state of \MP's input mechanism appears in the input stack, whose
+entries are records with five fields, called |index|, |start|, |loc|,
+|limit|, and |name|. The top element of this stack is maintained in a
+global variable for which no subscripting needs to be done; the other
+elements of the stack appear in an array. Hence the stack is declared thus:
+
+@<Types...@>=
+typedef struct {
+ quarterword index_field;
+ halfword start_field, loc_field, limit_field, name_field;
+} in_state_record;
+
+@ @<Glob...@>=
+in_state_record *input_stack;
+integer input_ptr; /* first unused location of |input_stack| */
+integer max_in_stack; /* largest value of |input_ptr| when pushing */
+in_state_record cur_input; /* the ``top'' input state */
+int stack_size; /* maximum number of simultaneous input sources */
+
+@ @<Allocate or initialize ...@>=
+mp->stack_size = 300;
+mp->input_stack = xmalloc((mp->stack_size+1),sizeof(in_state_record));
+
+@ @<Dealloc variables@>=
+xfree(mp->input_stack);
+
+@ We've already defined the special variable |loc==cur_input.loc_field|
+in our discussion of basic input-output routines. The other components of
+|cur_input| are defined in the same way:
+
+@d index mp->cur_input.index_field /* reference for buffer information */
+@d start mp->cur_input.start_field /* starting position in |buffer| */
+@d limit mp->cur_input.limit_field /* end of current line in |buffer| */
+@d name mp->cur_input.name_field /* name of the current file */
+
+@ Let's look more closely now at the five control variables
+(|index|,~|start|,~|loc|,~|limit|,~|name|),
+assuming that \MP\ is reading a line of characters that have been input
+from some file or from the user's terminal. There is an array called
+|buffer| that acts as a stack of all lines of characters that are
+currently being read from files, including all lines on subsidiary
+levels of the input stack that are not yet completed. \MP\ will return to
+the other lines when it is finished with the present input file.
+
+(Incidentally, on a machine with byte-oriented addressing, it would be
+appropriate to combine |buffer| with the |str_pool| array,
+letting the buffer entries grow downward from the top of the string pool
+and checking that these two tables don't bump into each other.)
+
+The line we are currently working on begins in position |start| of the
+buffer; the next character we are about to read is |buffer[loc]|; and
+|limit| is the location of the last character present. We always have
+|loc<=limit|. For convenience, |buffer[limit]| has been set to |"%"|, so
+that the end of a line is easily sensed.
+
+The |name| variable is a string number that designates the name of
+the current file, if we are reading an ordinary text file. Special codes
+|is_term..max_spec_src| indicate other sources of input text.
+
+@d is_term 0 /* |name| value when reading from the terminal for normal input */
+@d is_read 1 /* |name| value when executing a \&{readstring} or \&{readfrom} */
+@d is_scantok 2 /* |name| value when reading text generated by \&{scantokens} */
+@d max_spec_src is_scantok
+
+@ Additional information about the current line is available via the
+|index| variable, which counts how many lines of characters are present
+in the buffer below the current level. We have |index=0| when reading
+from the terminal and prompting the user for each line; then if the user types,
+e.g., `\.{input figs}', we will have |index=1| while reading
+the file \.{figs.mp}. However, it does not follow that |index| is the
+same as the input stack pointer, since many of the levels on the input
+stack may come from token lists and some |index| values may correspond
+to \.{MPX} files that are not currently on the stack.
+
+The global variable |in_open| is equal to the highest |index| value counting
+\.{MPX} files but excluding token-list input levels. Thus, the number of
+partially read lines in the buffer is |in_open+1| and we have |in_open>=index|
+when we are not reading a token list.
+
+If we are not currently reading from the terminal,
+we are reading from the file variable |input_file[index]|. We use
+the notation |terminal_input| as a convenient abbreviation for |name=is_term|,
+and |cur_file| as an abbreviation for |input_file[index]|.
+
+When \MP\ is not reading from the terminal, the global variable |line| contains
+the line number in the current file, for use in error messages. More precisely,
+|line| is a macro for |line_stack[index]| and the |line_stack| array gives
+the line number for each file in the |input_file| array.
+
+When an \.{MPX} file is opened the file name is stored in the |mpx_name|
+array so that the name doesn't get lost when the file is temporarily removed
+from the input stack.
+Thus when |input_file[k]| is an \.{MPX} file, its name is |mpx_name[k]|
+and it contains translated \TeX\ pictures for |input_file[k-1]|.
+Since this is not an \.{MPX} file, we have
+$$ \hbox{|mpx_name[k-1]<=absent|}. $$
+This |name| field is set to |finished| when |input_file[k]| is completely
+read.
+
+If more information about the input state is needed, it can be
+included in small arrays like those shown here. For example,
+the current page or segment number in the input file might be put
+into a variable |page|, that is really a macro for the current entry
+in `\ignorespaces|page_stack:array[0..max_in_open] of integer|\unskip'
+by analogy with |line_stack|.
+@^system dependencies@>
+
+@d terminal_input (name==is_term) /* are we reading from the terminal? */
+@d cur_file mp->input_file[index] /* the current |void *| variable */
+@d line mp->line_stack[index] /* current line number in the current source file */
+@d in_name mp->iname_stack[index] /* a string used to construct \.{MPX} file names */
+@d in_area mp->iarea_stack[index] /* another string for naming \.{MPX} files */
+@d absent 1 /* |name_field| value for unused |mpx_in_stack| entries */
+@d mpx_reading (mp->mpx_name[index]>absent)
+ /* when reading a file, is it an \.{MPX} file? */
+@d finished 0
+ /* |name_field| value when the corresponding \.{MPX} file is finished */
+
+@<Glob...@>=
+integer in_open; /* the number of lines in the buffer, less one */
+unsigned int open_parens; /* the number of open text files */
+void * *input_file ;
+integer *line_stack ; /* the line number for each file */
+char * *iname_stack; /* used for naming \.{MPX} files */
+char * *iarea_stack; /* used for naming \.{MPX} files */
+halfword*mpx_name ;
+
+@ @<Allocate or ...@>=
+mp->input_file = xmalloc((mp->max_in_open+1),sizeof(void *));
+mp->line_stack = xmalloc((mp->max_in_open+1),sizeof(integer));
+mp->iname_stack = xmalloc((mp->max_in_open+1),sizeof(char *));
+mp->iarea_stack = xmalloc((mp->max_in_open+1),sizeof(char *));
+mp->mpx_name = xmalloc((mp->max_in_open+1),sizeof(halfword));
+{
+ int k;
+ for (k=0;k<=mp->max_in_open;k++) {
+ mp->iname_stack[k] =NULL;
+ mp->iarea_stack[k] =NULL;
+ }
+}
+
+@ @<Dealloc variables@>=
+{
+ int l;
+ for (l=0;l<=mp->max_in_open;l++) {
+ xfree(mp->iname_stack[l]);
+ xfree(mp->iarea_stack[l]);
+ }
+}
+xfree(mp->input_file);
+xfree(mp->line_stack);
+xfree(mp->iname_stack);
+xfree(mp->iarea_stack);
+xfree(mp->mpx_name);
+
+
+@ However, all this discussion about input state really applies only to the
+case that we are inputting from a file. There is another important case,
+namely when we are currently getting input from a token list. In this case
+|index>max_in_open|, and the conventions about the other state variables
+are different:
+
+\yskip\hang|loc| is a pointer to the current node in the token list, i.e.,
+the node that will be read next. If |loc=null|, the token list has been
+fully read.
+
+\yskip\hang|start| points to the first node of the token list; this node
+may or may not contain a reference count, depending on the type of token
+list involved.
+
+\yskip\hang|token_type|, which takes the place of |index| in the
+discussion above, is a code number that explains what kind of token list
+is being scanned.
+
+\yskip\hang|name| points to the |eqtb| address of the control sequence
+being expanded, if the current token list is a macro not defined by
+\&{vardef}. Macros defined by \&{vardef} have |name=null|; their name
+can be deduced by looking at their first two parameters.
+
+\yskip\hang|param_start|, which takes the place of |limit|, tells where
+the parameters of the current macro or loop text begin in the |param_stack|.
+
+\yskip\noindent The |token_type| can take several values, depending on
+where the current token list came from:
+
+\yskip
+\indent|forever_text|, if the token list being scanned is the body of
+a \&{forever} loop;
+
+\indent|loop_text|, if the token list being scanned is the body of
+a \&{for} or \&{forsuffixes} loop;
+
+\indent|parameter|, if a \&{text} or \&{suffix} parameter is being scanned;
+
+\indent|backed_up|, if the token list being scanned has been inserted as
+`to be read again'.
+
+\indent|inserted|, if the token list being scanned has been inserted as
+part of error recovery;
+
+\indent|macro|, if the expansion of a user-defined symbolic token is being
+scanned.
+
+\yskip\noindent
+The token list begins with a reference count if and only if |token_type=
+macro|.
+@^reference counts@>
+
+@d token_type index /* type of current token list */
+@d token_state (index>(int)mp->max_in_open) /* are we scanning a token list? */
+@d file_state (index<=(int)mp->max_in_open) /* are we scanning a file line? */
+@d param_start limit /* base of macro parameters in |param_stack| */
+@d forever_text (mp->max_in_open+1) /* |token_type| code for loop texts */
+@d loop_text (mp->max_in_open+2) /* |token_type| code for loop texts */
+@d parameter (mp->max_in_open+3) /* |token_type| code for parameter texts */
+@d backed_up (mp->max_in_open+4) /* |token_type| code for texts to be reread */
+@d inserted (mp->max_in_open+5) /* |token_type| code for inserted texts */
+@d macro (mp->max_in_open+6) /* |token_type| code for macro replacement texts */
+
+@ The |param_stack| is an auxiliary array used to hold pointers to the token
+lists for parameters at the current level and subsidiary levels of input.
+This stack grows at a different rate from the others.
+
+@<Glob...@>=
+pointer *param_stack; /* token list pointers for parameters */
+integer param_ptr; /* first unused entry in |param_stack| */
+integer max_param_stack; /* largest value of |param_ptr| */
+
+@ @<Allocate or initialize ...@>=
+mp->param_stack = xmalloc((mp->param_size+1),sizeof(pointer));
+
+@ @<Dealloc variables@>=
+xfree(mp->param_stack);
+
+@ Notice that the |line| isn't valid when |token_state| is true because it
+depends on |index|. If we really need to know the line number for the
+topmost file in the index stack we use the following function. If a page
+number or other information is needed, this routine should be modified to
+compute it as well.
+@^system dependencies@>
+
+@<Declare a function called |true_line|@>=
+integer mp_true_line (MP mp) {
+ int k; /* an index into the input stack */
+ if ( file_state && (name>max_spec_src) ) {
+ return line;
+ } else {
+ k=mp->input_ptr;
+ while ((k>0) &&
+ ((mp->input_stack[(k-1)].index_field>mp->max_in_open)||
+ (mp->input_stack[(k-1)].name_field<=max_spec_src))) {
+ decr(k);
+ }
+ return (k>0 ? mp->line_stack[(k-1)] : 0 );
+ }
+}
+
+@ Thus, the ``current input state'' can be very complicated indeed; there
+can be many levels and each level can arise in a variety of ways. The
+|show_context| procedure, which is used by \MP's error-reporting routine to
+print out the current input state on all levels down to the most recent
+line of characters from an input file, illustrates most of these conventions.
+The global variable |file_ptr| contains the lowest level that was
+displayed by this procedure.
+
+@<Glob...@>=
+integer file_ptr; /* shallowest level shown by |show_context| */
+
+@ The status at each level is indicated by printing two lines, where the first
+line indicates what was read so far and the second line shows what remains
+to be read. The context is cropped, if necessary, so that the first line
+contains at most |half_error_line| characters, and the second contains
+at most |error_line|. Non-current input levels whose |token_type| is
+`|backed_up|' are shown only if they have not been fully read.
+
+@c void mp_show_context (MP mp) { /* prints where the scanner is */
+ int old_setting; /* saved |selector| setting */
+ @<Local variables for formatting calculations@>
+ mp->file_ptr=mp->input_ptr; mp->input_stack[mp->file_ptr]=mp->cur_input;
+ /* store current state */
+ while (1) {
+ mp->cur_input=mp->input_stack[mp->file_ptr]; /* enter into the context */
+ @<Display the current context@>;
+ if ( file_state )
+ if ( (name>max_spec_src) || (mp->file_ptr==0) ) break;
+ decr(mp->file_ptr);
+ }
+ mp->cur_input=mp->input_stack[mp->input_ptr]; /* restore original state */
+}
+
+@ @<Display the current context@>=
+if ( (mp->file_ptr==mp->input_ptr) || file_state ||
+ (token_type!=backed_up) || (loc!=null) ) {
+ /* we omit backed-up token lists that have already been read */
+ mp->tally=0; /* get ready to count characters */
+ old_setting=mp->selector;
+ if ( file_state ) {
+ @<Print location of current line@>;
+ @<Pseudoprint the line@>;
+ } else {
+ @<Print type of token list@>;
+ @<Pseudoprint the token list@>;
+ }
+ mp->selector=old_setting; /* stop pseudoprinting */
+ @<Print two lines using the tricky pseudoprinted information@>;
+}
+
+@ This routine should be changed, if necessary, to give the best possible
+indication of where the current line resides in the input file.
+For example, on some systems it is best to print both a page and line number.
+@^system dependencies@>
+
+@<Print location of current line@>=
+if ( name>max_spec_src ) {
+ mp_print_nl(mp, "l."); mp_print_int(mp, mp_true_line(mp));
+} else if ( terminal_input ) {
+ if ( mp->file_ptr==0 ) mp_print_nl(mp, "<*>");
+ else mp_print_nl(mp, "<insert>");
+} else if ( name==is_scantok ) {
+ mp_print_nl(mp, "<scantokens>");
+} else {
+ mp_print_nl(mp, "<read>");
+}
+mp_print_char(mp, ' ')
+
+@ Can't use case statement here because the |token_type| is not
+a constant expression.
+
+@<Print type of token list@>=
+{
+ if(token_type==forever_text) {
+ mp_print_nl(mp, "<forever> ");
+ } else if (token_type==loop_text) {
+ @<Print the current loop value@>;
+ } else if (token_type==parameter) {
+ mp_print_nl(mp, "<argument> ");
+ } else if (token_type==backed_up) {
+ if ( loc==null ) mp_print_nl(mp, "<recently read> ");
+ else mp_print_nl(mp, "<to be read again> ");
+ } else if (token_type==inserted) {
+ mp_print_nl(mp, "<inserted text> ");
+ } else if (token_type==macro) {
+ mp_print_ln(mp);
+ if ( name!=null ) mp_print_text(name);
+ else @<Print the name of a \&{vardef}'d macro@>;
+ mp_print(mp, "->");
+ } else {
+ mp_print_nl(mp, "?");/* this should never happen */
+@.?\relax@>
+ }
+}
+
+@ The parameter that corresponds to a loop text is either a token list
+(in the case of \&{forsuffixes}) or a ``capsule'' (in the case of \&{for}).
+We'll discuss capsules later; for now, all we need to know is that
+the |link| field in a capsule parameter is |void| and that
+|print_exp(p,0)| displays the value of capsule~|p| in abbreviated form.
+
+@<Print the current loop value@>=
+{ mp_print_nl(mp, "<for("); p=mp->param_stack[param_start];
+ if ( p!=null ) {
+ if ( link(p)==mp_void ) mp_print_exp(mp, p,0); /* we're in a \&{for} loop */
+ else mp_show_token_list(mp, p,null,20,mp->tally);
+ }
+ mp_print(mp, ")> ");
+}
+
+@ The first two parameters of a macro defined by \&{vardef} will be token
+lists representing the macro's prefix and ``at point.'' By putting these
+together, we get the macro's full name.
+
+@<Print the name of a \&{vardef}'d macro@>=
+{ p=mp->param_stack[param_start];
+ if ( p==null ) {
+ mp_show_token_list(mp, mp->param_stack[param_start+1],null,20,mp->tally);
+ } else {
+ q=p;
+ while ( link(q)!=null ) q=link(q);
+ link(q)=mp->param_stack[param_start+1];
+ mp_show_token_list(mp, p,null,20,mp->tally);
+ link(q)=null;
+ }
+}
+
+@ Now it is necessary to explain a little trick. We don't want to store a long
+string that corresponds to a token list, because that string might take up
+lots of memory; and we are printing during a time when an error message is
+being given, so we dare not do anything that might overflow one of \MP's
+tables. So `pseudoprinting' is the answer: We enter a mode of printing
+that stores characters into a buffer of length |error_line|, where character
+$k+1$ is placed into \hbox{|trick_buf[k mod error_line]|} if
+|k<trick_count|, otherwise character |k| is dropped. Initially we set
+|tally:=0| and |trick_count:=1000000|; then when we reach the
+point where transition from line 1 to line 2 should occur, we
+set |first_count:=tally| and |trick_count:=@tmax@>(error_line,
+tally+1+error_line-half_error_line)|. At the end of the
+pseudoprinting, the values of |first_count|, |tally|, and
+|trick_count| give us all the information we need to print the two lines,
+and all of the necessary text is in |trick_buf|.
+
+Namely, let |l| be the length of the descriptive information that appears
+on the first line. The length of the context information gathered for that
+line is |k=first_count|, and the length of the context information
+gathered for line~2 is $m=\min(|tally|, |trick_count|)-k$. If |l+k<=h|,
+where |h=half_error_line|, we print |trick_buf[0..k-1]| after the
+descriptive information on line~1, and set |n:=l+k|; here |n| is the
+length of line~1. If $l+k>h$, some cropping is necessary, so we set |n:=h|
+and print `\.{...}' followed by
+$$\hbox{|trick_buf[(l+k-h+3)..k-1]|,}$$
+where subscripts of |trick_buf| are circular modulo |error_line|. The
+second line consists of |n|~spaces followed by |trick_buf[k..(k+m-1)]|,
+unless |n+m>error_line|; in the latter case, further cropping is done.
+This is easier to program than to explain.
+
+@<Local variables for formatting...@>=
+int i; /* index into |buffer| */
+integer l; /* length of descriptive information on line 1 */
+integer m; /* context information gathered for line 2 */
+int n; /* length of line 1 */
+integer p; /* starting or ending place in |trick_buf| */
+integer q; /* temporary index */
+
+@ The following code tells the print routines to gather
+the desired information.
+
+@d begin_pseudoprint {
+ l=mp->tally; mp->tally=0; mp->selector=pseudo;
+ mp->trick_count=1000000;
+}
+@d set_trick_count {
+ mp->first_count=mp->tally;
+ mp->trick_count=mp->tally+1+mp->error_line-mp->half_error_line;
+ if ( mp->trick_count<mp->error_line ) mp->trick_count=mp->error_line;
+}
+
+@ And the following code uses the information after it has been gathered.
+
+@<Print two lines using the tricky pseudoprinted information@>=
+if ( mp->trick_count==1000000 ) set_trick_count;
+ /* |set_trick_count| must be performed */
+if ( mp->tally<mp->trick_count ) m=mp->tally-mp->first_count;
+else m=mp->trick_count-mp->first_count; /* context on line 2 */
+if ( l+mp->first_count<=mp->half_error_line ) {
+ p=0; n=l+mp->first_count;
+} else {
+ mp_print(mp, "..."); p=l+mp->first_count-mp->half_error_line+3;
+ n=mp->half_error_line;
+}
+for (q=p;q<=mp->first_count-1;q++) {
+ mp_print_char(mp, mp->trick_buf[q % mp->error_line]);
+}
+mp_print_ln(mp);
+for (q=1;q<=n;q++) {
+ mp_print_char(mp, ' '); /* print |n| spaces to begin line~2 */
+}
+if ( m+n<=mp->error_line ) p=mp->first_count+m;
+else p=mp->first_count+(mp->error_line-n-3);
+for (q=mp->first_count;q<=p-1;q++) {
+ mp_print_char(mp, mp->trick_buf[q % mp->error_line]);
+}
+if ( m+n>mp->error_line ) mp_print(mp, "...")
+
+@ But the trick is distracting us from our current goal, which is to
+understand the input state. So let's concentrate on the data structures that
+are being pseudoprinted as we finish up the |show_context| procedure.
+
+@<Pseudoprint the line@>=
+begin_pseudoprint;
+if ( limit>0 ) {
+ for (i=start;i<=limit-1;i++) {
+ if ( i==loc ) set_trick_count;
+ mp_print_str(mp, mp->buffer[i]);
+ }
+}
+
+@ @<Pseudoprint the token list@>=
+begin_pseudoprint;
+if ( token_type!=macro ) mp_show_token_list(mp, start,loc,100000,0);
+else mp_show_macro(mp, start,loc,100000)
+
+@ Here is the missing piece of |show_token_list| that is activated when the
+token beginning line~2 is about to be shown:
+
+@<Do magic computation@>=set_trick_count
+
+@* \[28] Maintaining the input stacks.
+The following subroutines change the input status in commonly needed ways.
+
+First comes |push_input|, which stores the current state and creates a
+new level (having, initially, the same properties as the old).
+
+@d push_input { /* enter a new input level, save the old */
+ if ( mp->input_ptr>mp->max_in_stack ) {
+ mp->max_in_stack=mp->input_ptr;
+ if ( mp->input_ptr==mp->stack_size ) {
+ int l = (mp->stack_size+(mp->stack_size>>2));
+ XREALLOC(mp->input_stack, l, in_state_record);
+ mp->stack_size = l;
+ }
+ }
+ mp->input_stack[mp->input_ptr]=mp->cur_input; /* stack the record */
+ incr(mp->input_ptr);
+}
+
+@ And of course what goes up must come down.
+
+@d pop_input { /* leave an input level, re-enter the old */
+ decr(mp->input_ptr); mp->cur_input=mp->input_stack[mp->input_ptr];
+ }
+
+@ Here is a procedure that starts a new level of token-list input, given
+a token list |p| and its type |t|. If |t=macro|, the calling routine should
+set |name|, reset~|loc|, and increase the macro's reference count.
+
+@d back_list(A) mp_begin_token_list(mp, (A),backed_up) /* backs up a simple token list */
+
+@c void mp_begin_token_list (MP mp,pointer p, quarterword t) {
+ push_input; start=p; token_type=t;
+ param_start=mp->param_ptr; loc=p;
+}
+
+@ When a token list has been fully scanned, the following computations
+should be done as we leave that level of input.
+@^inner loop@>
+
+@c void mp_end_token_list (MP mp) { /* leave a token-list input level */
+ pointer p; /* temporary register */
+ if ( token_type>=backed_up ) { /* token list to be deleted */
+ if ( token_type<=inserted ) {
+ mp_flush_token_list(mp, start); goto DONE;
+ } else {
+ mp_delete_mac_ref(mp, start); /* update reference count */
+ }
+ }
+ while ( mp->param_ptr>param_start ) { /* parameters must be flushed */
+ decr(mp->param_ptr);
+ p=mp->param_stack[mp->param_ptr];
+ if ( p!=null ) {
+ if ( link(p)==mp_void ) { /* it's an \&{expr} parameter */
+ mp_recycle_value(mp, p); mp_free_node(mp, p,value_node_size);
+ } else {
+ mp_flush_token_list(mp, p); /* it's a \&{suffix} or \&{text} parameter */
+ }
+ }
+ }
+DONE:
+ pop_input; check_interrupt;
+}
+
+@ The contents of |cur_cmd,cur_mod,cur_sym| are placed into an equivalent
+token by the |cur_tok| routine.
+@^inner loop@>
+
+@c @<Declare the procedure called |make_exp_copy|@>
+pointer mp_cur_tok (MP mp) {
+ pointer p; /* a new token node */
+ small_number save_type; /* |cur_type| to be restored */
+ integer save_exp; /* |cur_exp| to be restored */
+ if ( mp->cur_sym==0 ) {
+ if ( mp->cur_cmd==capsule_token ) {
+ save_type=mp->cur_type; save_exp=mp->cur_exp;
+ mp_make_exp_copy(mp, mp->cur_mod); p=mp_stash_cur_exp(mp); link(p)=null;
+ mp->cur_type=save_type; mp->cur_exp=save_exp;
+ } else {
+ p=mp_get_node(mp, token_node_size);
+ value(p)=mp->cur_mod; name_type(p)=mp_token;
+ if ( mp->cur_cmd==numeric_token ) type(p)=mp_known;
+ else type(p)=mp_string_type;
+ }
+ } else {
+ fast_get_avail(p); info(p)=mp->cur_sym;
+ }
+ return p;
+}
+
+@ Sometimes \MP\ has read too far and wants to ``unscan'' what it has
+seen. The |back_input| procedure takes care of this by putting the token
+just scanned back into the input stream, ready to be read again.
+If |cur_sym<>0|, the values of |cur_cmd| and |cur_mod| are irrelevant.
+
+@<Declarations@>=
+void mp_back_input (MP mp);
+
+@ @c void mp_back_input (MP mp) {/* undoes one token of input */
+ pointer p; /* a token list of length one */
+ p=mp_cur_tok(mp);
+ while ( token_state &&(loc==null) )
+ mp_end_token_list(mp); /* conserve stack space */
+ back_list(p);
+}
+
+@ The |back_error| routine is used when we want to restore or replace an
+offending token just before issuing an error message. We disable interrupts
+during the call of |back_input| so that the help message won't be lost.
+
+@<Declarations@>=
+void mp_error (MP mp);
+void mp_back_error (MP mp);
+
+@ @c void mp_back_error (MP mp) { /* back up one token and call |error| */
+ mp->OK_to_interrupt=false;
+ mp_back_input(mp);
+ mp->OK_to_interrupt=true; mp_error(mp);
+}
+void mp_ins_error (MP mp) { /* back up one inserted token and call |error| */
+ mp->OK_to_interrupt=false;
+ mp_back_input(mp); token_type=inserted;
+ mp->OK_to_interrupt=true; mp_error(mp);
+}
+
+@ The |begin_file_reading| procedure starts a new level of input for lines
+of characters to be read from a file, or as an insertion from the
+terminal. It does not take care of opening the file, nor does it set |loc|
+or |limit| or |line|.
+@^system dependencies@>
+
+@c void mp_begin_file_reading (MP mp) {
+ if ( mp->in_open==mp->max_in_open )
+ mp_overflow(mp, "text input levels",mp->max_in_open);
+@:MetaPost capacity exceeded text input levels}{\quad text input levels@>
+ if ( mp->first==mp->buf_size )
+ mp_reallocate_buffer(mp,(mp->buf_size+(mp->buf_size>>2)));
+ incr(mp->in_open); push_input; index=mp->in_open;
+ mp->mpx_name[index]=absent;
+ start=mp->first;
+ name=is_term; /* |terminal_input| is now |true| */
+}
+
+@ Conversely, the variables must be downdated when such a level of input
+is finished. Any associated \.{MPX} file must also be closed and popped
+off the file stack.
+
+@c void mp_end_file_reading (MP mp) {
+ if ( mp->in_open>index ) {
+ if ( (mp->mpx_name[mp->in_open]==absent)||(name<=max_spec_src) ) {
+ mp_confusion(mp, "endinput");
+@:this can't happen endinput}{\quad endinput@>
+ } else {
+ (mp->close_file)(mp,mp->input_file[mp->in_open]); /* close an \.{MPX} file */
+ delete_str_ref(mp->mpx_name[mp->in_open]);
+ decr(mp->in_open);
+ }
+ }
+ mp->first=start;
+ if ( index!=mp->in_open ) mp_confusion(mp, "endinput");
+ if ( name>max_spec_src ) {
+ (mp->close_file)(mp,cur_file);
+ delete_str_ref(name);
+ xfree(in_name);
+ xfree(in_area);
+ }
+ pop_input; decr(mp->in_open);
+}
+
+@ Here is a function that tries to resume input from an \.{MPX} file already
+associated with the current input file. It returns |false| if this doesn't
+work.
+
+@c boolean mp_begin_mpx_reading (MP mp) {
+ if ( mp->in_open!=index+1 ) {
+ return false;
+ } else {
+ if ( mp->mpx_name[mp->in_open]<=absent ) mp_confusion(mp, "mpx");
+@:this can't happen mpx}{\quad mpx@>
+ if ( mp->first==mp->buf_size )
+ mp_reallocate_buffer(mp,(mp->buf_size+(mp->buf_size>>2)));
+ push_input; index=mp->in_open;
+ start=mp->first;
+ name=mp->mpx_name[mp->in_open]; add_str_ref(name);
+ @<Put an empty line in the input buffer@>;
+ return true;
+ }
+}
+
+@ This procedure temporarily stops reading an \.{MPX} file.
+
+@c void mp_end_mpx_reading (MP mp) {
+ if ( mp->in_open!=index ) mp_confusion(mp, "mpx");
+@:this can't happen mpx}{\quad mpx@>
+ if ( loc<limit ) {
+ @<Complain that we are not at the end of a line in the \.{MPX} file@>;
+ }
+ mp->first=start;
+ pop_input;
+}
+
+@ Here we enforce a restriction that simplifies the input stacks considerably.
+This should not inconvenience the user because \.{MPX} files are generated
+by an auxiliary program called \.{DVItoMP}.
+
+@ @<Complain that we are not at the end of a line in the \.{MPX} file@>=
+{
+print_err("`mpxbreak' must be at the end of a line");
+help4("This file contains picture expressions for btex...etex")
+ ("blocks. Such files are normally generated automatically")
+ ("but this one seems to be messed up. I'm going to ignore")
+ ("the rest of this line.");
+mp_error(mp);
+}
+
+@ In order to keep the stack from overflowing during a long sequence of
+inserted `\.{show}' commands, the following routine removes completed
+error-inserted lines from memory.
+
+@c void mp_clear_for_error_prompt (MP mp) {
+ while ( file_state && terminal_input &&
+ (mp->input_ptr>0)&&(loc==limit) ) mp_end_file_reading(mp);
+ mp_print_ln(mp); clear_terminal;
+}
+
+@ To get \MP's whole input mechanism going, we perform the following
+actions.
+
+@<Initialize the input routines@>=
+{ mp->input_ptr=0; mp->max_in_stack=0;
+ mp->in_open=0; mp->open_parens=0; mp->max_buf_stack=0;
+ mp->param_ptr=0; mp->max_param_stack=0;
+ mp->first=1;
+ start=1; index=0; line=0; name=is_term;
+ mp->mpx_name[0]=absent;
+ mp->force_eof=false;
+ if ( ! mp_init_terminal(mp) ) mp_jump_out(mp);
+ limit=mp->last; mp->first=mp->last+1;
+ /* |init_terminal| has set |loc| and |last| */
+}
+
+@* \[29] Getting the next token.
+The heart of \MP's input mechanism is the |get_next| procedure, which
+we shall develop in the next few sections of the program. Perhaps we
+shouldn't actually call it the ``heart,'' however; it really acts as \MP's
+eyes and mouth, reading the source files and gobbling them up. And it also
+helps \MP\ to regurgitate stored token lists that are to be processed again.
+
+The main duty of |get_next| is to input one token and to set |cur_cmd|
+and |cur_mod| to that token's command code and modifier. Furthermore, if
+the input token is a symbolic token, that token's |hash| address
+is stored in |cur_sym|; otherwise |cur_sym| is set to zero.
+
+Underlying this simple description is a certain amount of complexity
+because of all the cases that need to be handled.
+However, the inner loop of |get_next| is reasonably short and fast.
+
+@ Before getting into |get_next|, we need to consider a mechanism by which
+\MP\ helps keep errors from propagating too far. Whenever the program goes
+into a mode where it keeps calling |get_next| repeatedly until a certain
+condition is met, it sets |scanner_status| to some value other than |normal|.
+Then if an input file ends, or if an `\&{outer}' symbol appears,
+an appropriate error recovery will be possible.
+
+The global variable |warning_info| helps in this error recovery by providing
+additional information. For example, |warning_info| might indicate the
+name of a macro whose replacement text is being scanned.
+
+@d normal 0 /* |scanner_status| at ``quiet times'' */
+@d skipping 1 /* |scanner_status| when false conditional text is being skipped */
+@d flushing 2 /* |scanner_status| when junk after a statement is being ignored */
+@d absorbing 3 /* |scanner_status| when a \&{text} parameter is being scanned */
+@d var_defining 4 /* |scanner_status| when a \&{vardef} is being scanned */
+@d op_defining 5 /* |scanner_status| when a macro \&{def} is being scanned */
+@d loop_defining 6 /* |scanner_status| when a \&{for} loop is being scanned */
+@d tex_flushing 7 /* |scanner_status| when skipping \TeX\ material */
+
+@<Glob...@>=
+integer scanner_status; /* are we scanning at high speed? */
+integer warning_info; /* if so, what else do we need to know,
+ in case an error occurs? */
+
+@ @<Initialize the input routines@>=
+mp->scanner_status=normal;
+
+@ The following subroutine
+is called when an `\&{outer}' symbolic token has been scanned or
+when the end of a file has been reached. These two cases are distinguished
+by |cur_sym|, which is zero at the end of a file.
+
+@c boolean mp_check_outer_validity (MP mp) {
+ pointer p; /* points to inserted token list */
+ if ( mp->scanner_status==normal ) {
+ return true;
+ } else if ( mp->scanner_status==tex_flushing ) {
+ @<Check if the file has ended while flushing \TeX\ material and set the
+ result value for |check_outer_validity|@>;
+ } else {
+ mp->deletions_allowed=false;
+ @<Back up an outer symbolic token so that it can be reread@>;
+ if ( mp->scanner_status>skipping ) {
+ @<Tell the user what has run away and try to recover@>;
+ } else {
+ print_err("Incomplete if; all text was ignored after line ");
+@.Incomplete if...@>
+ mp_print_int(mp, mp->warning_info);
+ help3("A forbidden `outer' token occurred in skipped text.")
+ ("This kind of error happens when you say `if...' and forget")
+ ("the matching `fi'. I've inserted a `fi'; this might work.");
+ if ( mp->cur_sym==0 )
+ mp->help_line[2]="The file ended while I was skipping conditional text.";
+ mp->cur_sym=frozen_fi; mp_ins_error(mp);
+ }
+ mp->deletions_allowed=true;
+ return false;
+ }
+}
+
+@ @<Check if the file has ended while flushing \TeX\ material and set...@>=
+if ( mp->cur_sym!=0 ) {
+ return true;
+} else {
+ mp->deletions_allowed=false;
+ print_err("TeX mode didn't end; all text was ignored after line ");
+ mp_print_int(mp, mp->warning_info);
+ help2("The file ended while I was looking for the `etex' to")
+ ("finish this TeX material. I've inserted `etex' now.");
+ mp->cur_sym = frozen_etex;
+ mp_ins_error(mp);
+ mp->deletions_allowed=true;
+ return false;
+}
+
+@ @<Back up an outer symbolic token so that it can be reread@>=
+if ( mp->cur_sym!=0 ) {
+ p=mp_get_avail(mp); info(p)=mp->cur_sym;
+ back_list(p); /* prepare to read the symbolic token again */
+}
+
+@ @<Tell the user what has run away...@>=
+{
+ mp_runaway(mp); /* print the definition-so-far */
+ if ( mp->cur_sym==0 ) {
+ print_err("File ended");
+@.File ended while scanning...@>
+ } else {
+ print_err("Forbidden token found");
+@.Forbidden token found...@>
+ }
+ mp_print(mp, " while scanning ");
+ help4("I suspect you have forgotten an `enddef',")
+ ("causing me to read past where you wanted me to stop.")
+ ("I'll try to recover; but if the error is serious,")
+ ("you'd better type `E' or `X' now and fix your file.");
+ switch (mp->scanner_status) {
+ @<Complete the error message,
+ and set |cur_sym| to a token that might help recover from the error@>
+ } /* there are no other cases */
+ mp_ins_error(mp);
+}
+
+@ As we consider various kinds of errors, it is also appropriate to
+change the first line of the help message just given; |help_line[3]|
+points to the string that might be changed.
+
+@<Complete the error message,...@>=
+case flushing:
+ mp_print(mp, "to the end of the statement");
+ mp->help_line[3]="A previous error seems to have propagated,";
+ mp->cur_sym=frozen_semicolon;
+ break;
+case absorbing:
+ mp_print(mp, "a text argument");
+ mp->help_line[3]="It seems that a right delimiter was left out,";
+ if ( mp->warning_info==0 ) {
+ mp->cur_sym=frozen_end_group;
+ } else {
+ mp->cur_sym=frozen_right_delimiter;
+ equiv(frozen_right_delimiter)=mp->warning_info;
+ }
+ break;
+case var_defining:
+case op_defining:
+ mp_print(mp, "the definition of ");
+ if ( mp->scanner_status==op_defining )
+ mp_print_text(mp->warning_info);
+ else
+ mp_print_variable_name(mp, mp->warning_info);
+ mp->cur_sym=frozen_end_def;
+ break;
+case loop_defining:
+ mp_print(mp, "the text of a ");
+ mp_print_text(mp->warning_info);
+ mp_print(mp, " loop");
+ mp->help_line[3]="I suspect you have forgotten an `endfor',";
+ mp->cur_sym=frozen_end_for;
+ break;
+
+@ The |runaway| procedure displays the first part of the text that occurred
+when \MP\ began its special |scanner_status|, if that text has been saved.
+
+@<Declare the procedure called |runaway|@>=
+void mp_runaway (MP mp) {
+ if ( mp->scanner_status>flushing ) {
+ mp_print_nl(mp, "Runaway ");
+ switch (mp->scanner_status) {
+ case absorbing: mp_print(mp, "text?"); break;
+ case var_defining:
+ case op_defining: mp_print(mp,"definition?"); break;
+ case loop_defining: mp_print(mp, "loop?"); break;
+ } /* there are no other cases */
+ mp_print_ln(mp);
+ mp_show_token_list(mp, link(hold_head),null,mp->error_line-10,0);
+ }
+}
+
+@ We need to mention a procedure that may be called by |get_next|.
+
+@<Declarations@>=
+void mp_firm_up_the_line (MP mp);
+
+@ And now we're ready to take the plunge into |get_next| itself.
+Note that the behavior depends on the |scanner_status| because percent signs
+and double quotes need to be passed over when skipping TeX material.
+
+@c
+void mp_get_next (MP mp) {
+ /* sets |cur_cmd|, |cur_mod|, |cur_sym| to next token */
+@^inner loop@>
+ /*restart*/ /* go here to get the next input token */
+ /*exit*/ /* go here when the next input token has been got */
+ /*|common_ending|*/ /* go here to finish getting a symbolic token */
+ /*found*/ /* go here when the end of a symbolic token has been found */
+ /*switch*/ /* go here to branch on the class of an input character */
+ /*|start_numeric_token|,|start_decimal_token|,|fin_numeric_token|,|done|*/
+ /* go here at crucial stages when scanning a number */
+ int k; /* an index into |buffer| */
+ ASCII_code c; /* the current character in the buffer */
+ ASCII_code class; /* its class number */
+ integer n,f; /* registers for decimal-to-binary conversion */
+RESTART:
+ mp->cur_sym=0;
+ if ( file_state ) {
+ @<Input from external file; |goto restart| if no input found,
+ or |return| if a non-symbolic token is found@>;
+ } else {
+ @<Input from token list; |goto restart| if end of list or
+ if a parameter needs to be expanded,
+ or |return| if a non-symbolic token is found@>;
+ }
+COMMON_ENDING:
+ @<Finish getting the symbolic token in |cur_sym|;
+ |goto restart| if it is illegal@>;
+}
+
+@ When a symbolic token is declared to be `\&{outer}', its command code
+is increased by |outer_tag|.
+@^inner loop@>
+
+@<Finish getting the symbolic token in |cur_sym|...@>=
+mp->cur_cmd=eq_type(mp->cur_sym); mp->cur_mod=equiv(mp->cur_sym);
+if ( mp->cur_cmd>=outer_tag ) {
+ if ( mp_check_outer_validity(mp) )
+ mp->cur_cmd=mp->cur_cmd-outer_tag;
+ else
+ goto RESTART;
+}
+
+@ A percent sign appears in |buffer[limit]|; this makes it unnecessary
+to have a special test for end-of-line.
+@^inner loop@>
+
+@<Input from external file;...@>=
+{
+SWITCH:
+ c=mp->buffer[loc]; incr(loc); class=mp->char_class[c];
+ switch (class) {
+ case digit_class: goto START_NUMERIC_TOKEN; break;
+ case period_class:
+ class=mp->char_class[mp->buffer[loc]];
+ if ( class>period_class ) {
+ goto SWITCH;
+ } else if ( class<period_class ) { /* |class=digit_class| */
+ n=0; goto START_DECIMAL_TOKEN;
+ }
+@:. }{\..\ token@>
+ break;
+ case space_class: goto SWITCH; break;
+ case percent_class:
+ if ( mp->scanner_status==tex_flushing ) {
+ if ( loc<limit ) goto SWITCH;
+ }
+ @<Move to next line of file, or |goto restart| if there is no next line@>;
+ check_interrupt;
+ goto SWITCH;
+ break;
+ case string_class:
+ if ( mp->scanner_status==tex_flushing ) goto SWITCH;
+ else @<Get a string token and |return|@>;
+ break;
+ case isolated_classes:
+ k=loc-1; goto FOUND; break;
+ case invalid_class:
+ if ( mp->scanner_status==tex_flushing ) goto SWITCH;
+ else @<Decry the invalid character and |goto restart|@>;
+ break;
+ default: break; /* letters, etc. */
+ }
+ k=loc-1;
+ while ( mp->char_class[mp->buffer[loc]]==class ) incr(loc);
+ goto FOUND;
+START_NUMERIC_TOKEN:
+ @<Get the integer part |n| of a numeric token;
+ set |f:=0| and |goto fin_numeric_token| if there is no decimal point@>;
+START_DECIMAL_TOKEN:
+ @<Get the fraction part |f| of a numeric token@>;
+FIN_NUMERIC_TOKEN:
+ @<Pack the numeric and fraction parts of a numeric token
+ and |return|@>;
+FOUND:
+ mp->cur_sym=mp_id_lookup(mp, k,loc-k);
+}
+
+@ We go to |restart| instead of to |SWITCH|, because we might enter
+|token_state| after the error has been dealt with
+(cf.\ |clear_for_error_prompt|).
+
+@<Decry the invalid...@>=
+{
+ print_err("Text line contains an invalid character");
+@.Text line contains...@>
+ help2("A funny symbol that I can\'t read has just been input.")
+ ("Continue, and I'll forget that it ever happened.");
+ mp->deletions_allowed=false; mp_error(mp); mp->deletions_allowed=true;
+ goto RESTART;
+}
+
+@ @<Get a string token and |return|@>=
+{
+ if ( mp->buffer[loc]=='"' ) {
+ mp->cur_mod=rts("");
+ } else {
+ k=loc; mp->buffer[limit+1]='"';
+ do {
+ incr(loc);
+ } while (mp->buffer[loc]!='"');
+ if ( loc>limit ) {
+ @<Decry the missing string delimiter and |goto restart|@>;
+ }
+ if ( loc==k+1 ) {
+ mp->cur_mod=mp->buffer[k];
+ } else {
+ str_room(loc-k);
+ do {
+ append_char(mp->buffer[k]); incr(k);
+ } while (k!=loc);
+ mp->cur_mod=mp_make_string(mp);
+ }
+ }
+ incr(loc); mp->cur_cmd=string_token;
+ return;
+}
+
+@ We go to |restart| after this error message, not to |SWITCH|,
+because the |clear_for_error_prompt| routine might have reinstated
+|token_state| after |error| has finished.
+
+@<Decry the missing string delimiter and |goto restart|@>=
+{
+ loc=limit; /* the next character to be read on this line will be |"%"| */
+ print_err("Incomplete string token has been flushed");
+@.Incomplete string token...@>
+ help3("Strings should finish on the same line as they began.")
+ ("I've deleted the partial string; you might want to")
+ ("insert another by typing, e.g., `I\"new string\"'.");
+ mp->deletions_allowed=false; mp_error(mp);
+ mp->deletions_allowed=true;
+ goto RESTART;
+}
+
+@ @<Get the integer part |n| of a numeric token...@>=
+n=c-'0';
+while ( mp->char_class[mp->buffer[loc]]==digit_class ) {
+ if ( n<32768 ) n=10*n+mp->buffer[loc]-'0';
+ incr(loc);
+}
+if ( mp->buffer[loc]=='.' )
+ if ( mp->char_class[mp->buffer[loc+1]]==digit_class )
+ goto DONE;
+f=0;
+goto FIN_NUMERIC_TOKEN;
+DONE: incr(loc)
+
+@ @<Get the fraction part |f| of a numeric token@>=
+k=0;
+do {
+ if ( k<17 ) { /* digits for |k>=17| cannot affect the result */
+ mp->dig[k]=mp->buffer[loc]-'0'; incr(k);
+ }
+ incr(loc);
+} while (mp->char_class[mp->buffer[loc]]==digit_class);
+f=mp_round_decimals(mp, k);
+if ( f==unity ) {
+ incr(n); f=0;
+}
+
+@ @<Pack the numeric and fraction parts of a numeric token and |return|@>=
+if ( n<32768 ) {
+ @<Set |cur_mod:=n*unity+f| and check if it is uncomfortably large@>;
+} else if ( mp->scanner_status!=tex_flushing ) {
+ print_err("Enormous number has been reduced");
+@.Enormous number...@>
+ help2("I can\'t handle numbers bigger than 32767.99998;")
+ ("so I've changed your constant to that maximum amount.");
+ mp->deletions_allowed=false; mp_error(mp); mp->deletions_allowed=true;
+ mp->cur_mod=el_gordo;
+}
+mp->cur_cmd=numeric_token; return
+
+@ @<Set |cur_mod:=n*unity+f| and check if it is uncomfortably large@>=
+{
+ mp->cur_mod=n*unity+f;
+ if ( mp->cur_mod>=fraction_one ) {
+ if ( (mp->internal[mp_warning_check]>0) &&
+ (mp->scanner_status!=tex_flushing) ) {
+ print_err("Number is too large (");
+ mp_print_scaled(mp, mp->cur_mod);
+ mp_print_char(mp, ')');
+ help3("It is at least 4096. Continue and I'll try to cope")
+ ("with that big value; but it might be dangerous.")
+ ("(Set warningcheck:=0 to suppress this message.)");
+ mp_error(mp);
+ }
+ }
+}
+
+@ Let's consider now what happens when |get_next| is looking at a token list.
+@^inner loop@>
+
+@<Input from token list;...@>=
+if ( loc>=mp->hi_mem_min ) { /* one-word token */
+ mp->cur_sym=info(loc); loc=link(loc); /* move to next */
+ if ( mp->cur_sym>=expr_base ) {
+ if ( mp->cur_sym>=suffix_base ) {
+ @<Insert a suffix or text parameter and |goto restart|@>;
+ } else {
+ mp->cur_cmd=capsule_token;
+ mp->cur_mod=mp->param_stack[param_start+mp->cur_sym-(expr_base)];
+ mp->cur_sym=0; return;
+ }
+ }
+} else if ( loc>null ) {
+ @<Get a stored numeric or string or capsule token and |return|@>
+} else { /* we are done with this token list */
+ mp_end_token_list(mp); goto RESTART; /* resume previous level */
+}
+
+@ @<Insert a suffix or text parameter...@>=
+{
+ if ( mp->cur_sym>=text_base ) mp->cur_sym=mp->cur_sym-mp->param_size;
+ /* |param_size=text_base-suffix_base| */
+ mp_begin_token_list(mp,
+ mp->param_stack[param_start+mp->cur_sym-(suffix_base)],
+ parameter);
+ goto RESTART;
+}
+
+@ @<Get a stored numeric or string or capsule token...@>=
+{
+ if ( name_type(loc)==mp_token ) {
+ mp->cur_mod=value(loc);
+ if ( type(loc)==mp_known ) {
+ mp->cur_cmd=numeric_token;
+ } else {
+ mp->cur_cmd=string_token; add_str_ref(mp->cur_mod);
+ }
+ } else {
+ mp->cur_mod=loc; mp->cur_cmd=capsule_token;
+ };
+ loc=link(loc); return;
+}
+
+@ All of the easy branches of |get_next| have now been taken care of.
+There is one more branch.
+
+@<Move to next line of file, or |goto restart|...@>=
+if ( name>max_spec_src ) {
+ @<Read next line of file into |buffer|, or
+ |goto restart| if the file has ended@>;
+} else {
+ if ( mp->input_ptr>0 ) {
+ /* text was inserted during error recovery or by \&{scantokens} */
+ mp_end_file_reading(mp); goto RESTART; /* resume previous level */
+ }
+ if ( mp->selector<log_only || mp->selector>=write_file) mp_open_log_file(mp);
+ if ( mp->interaction>mp_nonstop_mode ) {
+ if ( limit==start ) /* previous line was empty */
+ mp_print_nl(mp, "(Please type a command or say `end')");
+@.Please type...@>
+ mp_print_ln(mp); mp->first=start;
+ prompt_input("*"); /* input on-line into |buffer| */
+@.*\relax@>
+ limit=mp->last; mp->buffer[limit]='%';
+ mp->first=limit+1; loc=start;
+ } else {
+ mp_fatal_error(mp, "*** (job aborted, no legal end found)");
+@.job aborted@>
+ /* nonstop mode, which is intended for overnight batch processing,
+ never waits for on-line input */
+ }
+}
+
+@ The global variable |force_eof| is normally |false|; it is set |true|
+by an \&{endinput} command.
+
+@<Glob...@>=
+boolean force_eof; /* should the next \&{input} be aborted early? */
+
+@ We must decrement |loc| in order to leave the buffer in a valid state
+when an error condition causes us to |goto restart| without calling
+|end_file_reading|.
+
+@<Read next line of file into |buffer|, or
+ |goto restart| if the file has ended@>=
+{
+ incr(line); mp->first=start;
+ if ( ! mp->force_eof ) {
+ if ( mp_input_ln(mp, cur_file ) ) /* not end of file */
+ mp_firm_up_the_line(mp); /* this sets |limit| */
+ else
+ mp->force_eof=true;
+ };
+ if ( mp->force_eof ) {
+ mp->force_eof=false;
+ decr(loc);
+ if ( mpx_reading ) {
+ @<Complain that the \.{MPX} file ended unexpectly; then set
+ |cur_sym:=frozen_mpx_break| and |goto comon_ending|@>;
+ } else {
+ mp_print_char(mp, ')'); decr(mp->open_parens);
+ update_terminal; /* show user that file has been read */
+ mp_end_file_reading(mp); /* resume previous level */
+ if ( mp_check_outer_validity(mp) ) goto RESTART;
+ else goto RESTART;
+ }
+ }
+ mp->buffer[limit]='%'; mp->first=limit+1; loc=start; /* ready to read */
+}
+
+@ We should never actually come to the end of an \.{MPX} file because such
+files should have an \&{mpxbreak} after the translation of the last
+\&{btex}$\,\ldots\,$\&{etex} block.
+
+@<Complain that the \.{MPX} file ended unexpectly; then set...@>=
+{
+ mp->mpx_name[index]=finished;
+ print_err("mpx file ended unexpectedly");
+ help4("The file had too few picture expressions for btex...etex")
+ ("blocks. Such files are normally generated automatically")
+ ("but this one got messed up. You might want to insert a")
+ ("picture expression now.");
+ mp->deletions_allowed=false; mp_error(mp); mp->deletions_allowed=true;
+ mp->cur_sym=frozen_mpx_break; goto COMMON_ENDING;
+}
+
+@ Sometimes we want to make it look as though we have just read a blank line
+without really doing so.
+
+@<Put an empty line in the input buffer@>=
+mp->last=mp->first; limit=mp->last; /* simulate |input_ln| and |firm_up_the_line| */
+mp->buffer[limit]='%'; mp->first=limit+1; loc=start
+
+@ If the user has set the |mp_pausing| parameter to some positive value,
+and if nonstop mode has not been selected, each line of input is displayed
+on the terminal and the transcript file, followed by `\.{=>}'.
+\MP\ waits for a response. If the response is null (i.e., if nothing is
+typed except perhaps a few blank spaces), the original
+line is accepted as it stands; otherwise the line typed is
+used instead of the line in the file.
+
+@c void mp_firm_up_the_line (MP mp) {
+ size_t k; /* an index into |buffer| */
+ limit=mp->last;
+ if ( mp->internal[mp_pausing]>0) if ( mp->interaction>mp_nonstop_mode ) {
+ wake_up_terminal; mp_print_ln(mp);
+ if ( start<limit ) {
+ for (k=(size_t)start;k<=(size_t)(limit-1);k++) {
+ mp_print_str(mp, mp->buffer[k]);
+ }
+ }
+ mp->first=limit; prompt_input("=>"); /* wait for user response */
+@.=>@>
+ if ( mp->last>mp->first ) {
+ for (k=mp->first;k<=mp->last-1;k++) { /* move line down in buffer */
+ mp->buffer[k+start-mp->first]=mp->buffer[k];
+ }
+ limit=start+mp->last-mp->first;
+ }
+ }
+}
+
+@* \[30] Dealing with \TeX\ material.
+The \&{btex}$\,\ldots\,$\&{etex} and \&{verbatimtex}$\,\ldots\,$\&{etex}
+features need to be implemented at a low level in the scanning process
+so that \MP\ can stay in synch with the a preprocessor that treats
+blocks of \TeX\ material as they occur in the input file without trying
+to expand \MP\ macros. Thus we need a special version of |get_next|
+that does not expand macros and such but does handle \&{btex},
+\&{verbatimtex}, etc.
+
+The special version of |get_next| is called |get_t_next|. It works by flushing
+\&{btex}$\,\ldots\,$\&{etex} and \&{verbatimtex}\allowbreak
+$\,\ldots\,$\&{etex} blocks, switching to the \.{MPX} file when it sees
+\&{btex}, and switching back when it sees \&{mpxbreak}.
+
+@d btex_code 0
+@d verbatim_code 1
+
+@ @<Put each...@>=
+mp_primitive(mp, "btex",start_tex,btex_code);
+@:btex_}{\&{btex} primitive@>
+mp_primitive(mp, "verbatimtex",start_tex,verbatim_code);
+@:verbatimtex_}{\&{verbatimtex} primitive@>
+mp_primitive(mp, "etex",etex_marker,0); mp->eqtb[frozen_etex]=mp->eqtb[mp->cur_sym];
+@:etex_}{\&{etex} primitive@>
+mp_primitive(mp, "mpxbreak",mpx_break,0); mp->eqtb[frozen_mpx_break]=mp->eqtb[mp->cur_sym];
+@:mpx_break_}{\&{mpxbreak} primitive@>
+
+@ @<Cases of |print_cmd...@>=
+case start_tex: if ( m==btex_code ) mp_print(mp, "btex");
+ else mp_print(mp, "verbatimtex"); break;
+case etex_marker: mp_print(mp, "etex"); break;
+case mpx_break: mp_print(mp, "mpxbreak"); break;
+
+@ Actually, |get_t_next| is a macro that avoids procedure overhead except
+in the unusual case where \&{btex}, \&{verbatimtex}, \&{etex}, or \&{mpxbreak}
+is encountered.
+
+@d get_t_next {mp_get_next(mp); if ( mp->cur_cmd<=max_pre_command ) mp_t_next(mp); }
+
+@<Declarations@>=
+void mp_start_mpx_input (MP mp);
+
+@ @c
+void mp_t_next (MP mp) {
+ int old_status; /* saves the |scanner_status| */
+ integer old_info; /* saves the |warning_info| */
+ while ( mp->cur_cmd<=max_pre_command ) {
+ if ( mp->cur_cmd==mpx_break ) {
+ if ( ! file_state || (mp->mpx_name[index]==absent) ) {
+ @<Complain about a misplaced \&{mpxbreak}@>;
+ } else {
+ mp_end_mpx_reading(mp);
+ goto TEX_FLUSH;
+ }
+ } else if ( mp->cur_cmd==start_tex ) {
+ if ( token_state || (name<=max_spec_src) ) {
+ @<Complain that we are not reading a file@>;
+ } else if ( mpx_reading ) {
+ @<Complain that \.{MPX} files cannot contain \TeX\ material@>;
+ } else if ( (mp->cur_mod!=verbatim_code)&&
+ (mp->mpx_name[index]!=finished) ) {
+ if ( ! mp_begin_mpx_reading(mp) ) mp_start_mpx_input(mp);
+ } else {
+ goto TEX_FLUSH;
+ }
+ } else {
+ @<Complain about a misplaced \&{etex}@>;
+ }
+ goto COMMON_ENDING;
+ TEX_FLUSH:
+ @<Flush the \TeX\ material@>;
+ COMMON_ENDING:
+ mp_get_next(mp);
+ }
+}
+
+@ We could be in the middle of an operation such as skipping false conditional
+text when \TeX\ material is encountered, so we must be careful to save the
+|scanner_status|.
+
+@<Flush the \TeX\ material@>=
+old_status=mp->scanner_status;
+old_info=mp->warning_info;
+mp->scanner_status=tex_flushing;
+mp->warning_info=line;
+do { mp_get_next(mp); } while (mp->cur_cmd!=etex_marker);
+mp->scanner_status=old_status;
+mp->warning_info=old_info
+
+@ @<Complain that \.{MPX} files cannot contain \TeX\ material@>=
+{ print_err("An mpx file cannot contain btex or verbatimtex blocks");
+help4("This file contains picture expressions for btex...etex")
+ ("blocks. Such files are normally generated automatically")
+ ("but this one seems to be messed up. I'll just keep going")
+ ("and hope for the best.");
+mp_error(mp);
+}
+
+@ @<Complain that we are not reading a file@>=
+{ print_err("You can only use `btex' or `verbatimtex' in a file");
+help3("I'll have to ignore this preprocessor command because it")
+ ("only works when there is a file to preprocess. You might")
+ ("want to delete everything up to the next `etex`.");
+mp_error(mp);
+}
+
+@ @<Complain about a misplaced \&{mpxbreak}@>=
+{ print_err("Misplaced mpxbreak");
+help2("I'll ignore this preprocessor command because it")
+ ("doesn't belong here");
+mp_error(mp);
+}
+
+@ @<Complain about a misplaced \&{etex}@>=
+{ print_err("Extra etex will be ignored");
+help1("There is no btex or verbatimtex for this to match");
+mp_error(mp);
+}
+
+@* \[31] Scanning macro definitions.
+\MP\ has a variety of ways to tuck tokens away into token lists for later
+use: Macros can be defined with \&{def}, \&{vardef}, \&{primarydef}, etc.;
+repeatable code can be defined with \&{for}, \&{forever}, \&{forsuffixes}.
+All such operations are handled by the routines in this part of the program.
+
+The modifier part of each command code is zero for the ``ending delimiters''
+like \&{enddef} and \&{endfor}.
+
+@d start_def 1 /* command modifier for \&{def} */
+@d var_def 2 /* command modifier for \&{vardef} */
+@d end_def 0 /* command modifier for \&{enddef} */
+@d start_forever 1 /* command modifier for \&{forever} */
+@d end_for 0 /* command modifier for \&{endfor} */
+
+@<Put each...@>=
+mp_primitive(mp, "def",macro_def,start_def);
+@:def_}{\&{def} primitive@>
+mp_primitive(mp, "vardef",macro_def,var_def);
+@:var_def_}{\&{vardef} primitive@>
+mp_primitive(mp, "primarydef",macro_def,secondary_primary_macro);
+@:primary_def_}{\&{primarydef} primitive@>
+mp_primitive(mp, "secondarydef",macro_def,tertiary_secondary_macro);
+@:secondary_def_}{\&{secondarydef} primitive@>
+mp_primitive(mp, "tertiarydef",macro_def,expression_tertiary_macro);
+@:tertiary_def_}{\&{tertiarydef} primitive@>
+mp_primitive(mp, "enddef",macro_def,end_def); mp->eqtb[frozen_end_def]=mp->eqtb[mp->cur_sym];
+@:end_def_}{\&{enddef} primitive@>
+@#
+mp_primitive(mp, "for",iteration,expr_base);
+@:for_}{\&{for} primitive@>
+mp_primitive(mp, "forsuffixes",iteration,suffix_base);
+@:for_suffixes_}{\&{forsuffixes} primitive@>
+mp_primitive(mp, "forever",iteration,start_forever);
+@:forever_}{\&{forever} primitive@>
+mp_primitive(mp, "endfor",iteration,end_for); mp->eqtb[frozen_end_for]=mp->eqtb[mp->cur_sym];
+@:end_for_}{\&{endfor} primitive@>
+
+@ @<Cases of |print_cmd...@>=
+case macro_def:
+ if ( m<=var_def ) {
+ if ( m==start_def ) mp_print(mp, "def");
+ else if ( m<start_def ) mp_print(mp, "enddef");
+ else mp_print(mp, "vardef");
+ } else if ( m==secondary_primary_macro ) {
+ mp_print(mp, "primarydef");
+ } else if ( m==tertiary_secondary_macro ) {
+ mp_print(mp, "secondarydef");
+ } else {
+ mp_print(mp, "tertiarydef");
+ }
+ break;
+case iteration:
+ if ( m<=start_forever ) {
+ if ( m==start_forever ) mp_print(mp, "forever");
+ else mp_print(mp, "endfor");
+ } else if ( m==expr_base ) {
+ mp_print(mp, "for");
+ } else {
+ mp_print(mp, "forsuffixes");
+ }
+ break;
+
+@ Different macro-absorbing operations have different syntaxes, but they
+also have a lot in common. There is a list of special symbols that are to
+be replaced by parameter tokens; there is a special command code that
+ends the definition; the quotation conventions are identical. Therefore
+it makes sense to have most of the work done by a single subroutine. That
+subroutine is called |scan_toks|.
+
+The first parameter to |scan_toks| is the command code that will
+terminate scanning (either |macro_def| or |iteration|).
+
+The second parameter, |subst_list|, points to a (possibly empty) list
+of two-word nodes whose |info| and |value| fields specify symbol tokens
+before and after replacement. The list will be returned to free storage
+by |scan_toks|.
+
+The third parameter is simply appended to the token list that is built.
+And the final parameter tells how many of the special operations
+\.{\#\AT!}, \.{\AT!}, and \.{\AT!\#} are to be replaced by suffix parameters.
+When such parameters are present, they are called \.{(SUFFIX0)},
+\.{(SUFFIX1)}, and \.{(SUFFIX2)}.
+
+@c pointer mp_scan_toks (MP mp,command_code terminator, pointer
+ subst_list, pointer tail_end, small_number suffix_count) {
+ pointer p; /* tail of the token list being built */
+ pointer q; /* temporary for link management */
+ integer balance; /* left delimiters minus right delimiters */
+ p=hold_head; balance=1; link(hold_head)=null;
+ while (1) {
+ get_t_next;
+ if ( mp->cur_sym>0 ) {
+ @<Substitute for |cur_sym|, if it's on the |subst_list|@>;
+ if ( mp->cur_cmd==terminator ) {
+ @<Adjust the balance; |break| if it's zero@>;
+ } else if ( mp->cur_cmd==macro_special ) {
+ @<Handle quoted symbols, \.{\#\AT!}, \.{\AT!}, or \.{\AT!\#}@>;
+ }
+ }
+ link(p)=mp_cur_tok(mp); p=link(p);
+ }
+ link(p)=tail_end; mp_flush_node_list(mp, subst_list);
+ return link(hold_head);
+}
+
+@ @<Substitute for |cur_sym|...@>=
+{
+ q=subst_list;
+ while ( q!=null ) {
+ if ( info(q)==mp->cur_sym ) {
+ mp->cur_sym=value(q); mp->cur_cmd=relax; break;
+ }
+ q=link(q);
+ }
+}
+
+@ @<Adjust the balance; |break| if it's zero@>=
+if ( mp->cur_mod>0 ) {
+ incr(balance);
+} else {
+ decr(balance);
+ if ( balance==0 )
+ break;
+}
+
+@ Four commands are intended to be used only within macro texts: \&{quote},
+\.{\#\AT!}, \.{\AT!}, and \.{\AT!\#}. They are variants of a single command
+code called |macro_special|.
+
+@d quote 0 /* |macro_special| modifier for \&{quote} */
+@d macro_prefix 1 /* |macro_special| modifier for \.{\#\AT!} */
+@d macro_at 2 /* |macro_special| modifier for \.{\AT!} */
+@d macro_suffix 3 /* |macro_special| modifier for \.{\AT!\#} */
+
+@<Put each...@>=
+mp_primitive(mp, "quote",macro_special,quote);
+@:quote_}{\&{quote} primitive@>
+mp_primitive(mp, "#@@",macro_special,macro_prefix);
+@:]]]\#\AT!_}{\.{\#\AT!} primitive@>
+mp_primitive(mp, "@@",macro_special,macro_at);
+@:]]]\AT!_}{\.{\AT!} primitive@>
+mp_primitive(mp, "@@#",macro_special,macro_suffix);
+@:]]]\AT!\#_}{\.{\AT!\#} primitive@>
+
+@ @<Cases of |print_cmd...@>=
+case macro_special:
+ switch (m) {
+ case macro_prefix: mp_print(mp, "#@@"); break;
+ case macro_at: mp_print_char(mp, '@@'); break;
+ case macro_suffix: mp_print(mp, "@@#"); break;
+ default: mp_print(mp, "quote"); break;
+ }
+ break;
+
+@ @<Handle quoted...@>=
+{
+ if ( mp->cur_mod==quote ) { get_t_next; }
+ else if ( mp->cur_mod<=suffix_count )
+ mp->cur_sym=suffix_base-1+mp->cur_mod;
+}
+
+@ Here is a routine that's used whenever a token will be redefined. If
+the user's token is unredefinable, the `|frozen_inaccessible|' token is
+substituted; the latter is redefinable but essentially impossible to use,
+hence \MP's tables won't get fouled up.
+
+@c void mp_get_symbol (MP mp) { /* sets |cur_sym| to a safe symbol */
+RESTART:
+ get_t_next;
+ if ( (mp->cur_sym==0)||(mp->cur_sym>frozen_inaccessible) ) {
+ print_err("Missing symbolic token inserted");
+@.Missing symbolic token...@>
+ help3("Sorry: You can\'t redefine a number, string, or expr.")
+ ("I've inserted an inaccessible symbol so that your")
+ ("definition will be completed without mixing me up too badly.");
+ if ( mp->cur_sym>0 )
+ mp->help_line[2]="Sorry: You can\'t redefine my error-recovery tokens.";
+ else if ( mp->cur_cmd==string_token )
+ delete_str_ref(mp->cur_mod);
+ mp->cur_sym=frozen_inaccessible; mp_ins_error(mp); goto RESTART;
+ }
+}
+
+@ Before we actually redefine a symbolic token, we need to clear away its
+former value, if it was a variable. The following stronger version of
+|get_symbol| does that.
+
+@c void mp_get_clear_symbol (MP mp) {
+ mp_get_symbol(mp); mp_clear_symbol(mp, mp->cur_sym,false);
+}
+
+@ Here's another little subroutine; it checks that an equals sign
+or assignment sign comes along at the proper place in a macro definition.
+
+@c void mp_check_equals (MP mp) {
+ if ( mp->cur_cmd!=equals ) if ( mp->cur_cmd!=assignment ) {
+ mp_missing_err(mp, "=");
+@.Missing `='@>
+ help5("The next thing in this `def' should have been `=',")
+ ("because I've already looked at the definition heading.")
+ ("But don't worry; I'll pretend that an equals sign")
+ ("was present. Everything from here to `enddef'")
+ ("will be the replacement text of this macro.");
+ mp_back_error(mp);
+ }
+}
+
+@ A \&{primarydef}, \&{secondarydef}, or \&{tertiarydef} is rather easily
+handled now that we have |scan_toks|. In this case there are
+two parameters, which will be \.{EXPR0} and \.{EXPR1} (i.e.,
+|expr_base| and |expr_base+1|).
+
+@c void mp_make_op_def (MP mp) {
+ command_code m; /* the type of definition */
+ pointer p,q,r; /* for list manipulation */
+ m=mp->cur_mod;
+ mp_get_symbol(mp); q=mp_get_node(mp, token_node_size);
+ info(q)=mp->cur_sym; value(q)=expr_base;
+ mp_get_clear_symbol(mp); mp->warning_info=mp->cur_sym;
+ mp_get_symbol(mp); p=mp_get_node(mp, token_node_size);
+ info(p)=mp->cur_sym; value(p)=expr_base+1; link(p)=q;
+ get_t_next; mp_check_equals(mp);
+ mp->scanner_status=op_defining; q=mp_get_avail(mp); ref_count(q)=null;
+ r=mp_get_avail(mp); link(q)=r; info(r)=general_macro;
+ link(r)=mp_scan_toks(mp, macro_def,p,null,0);
+ mp->scanner_status=normal; eq_type(mp->warning_info)=m;
+ equiv(mp->warning_info)=q; mp_get_x_next(mp);
+}
+
+@ Parameters to macros are introduced by the keywords \&{expr},
+\&{suffix}, \&{text}, \&{primary}, \&{secondary}, and \&{tertiary}.
+
+@<Put each...@>=
+mp_primitive(mp, "expr",param_type,expr_base);
+@:expr_}{\&{expr} primitive@>
+mp_primitive(mp, "suffix",param_type,suffix_base);
+@:suffix_}{\&{suffix} primitive@>
+mp_primitive(mp, "text",param_type,text_base);
+@:text_}{\&{text} primitive@>
+mp_primitive(mp, "primary",param_type,primary_macro);
+@:primary_}{\&{primary} primitive@>
+mp_primitive(mp, "secondary",param_type,secondary_macro);
+@:secondary_}{\&{secondary} primitive@>
+mp_primitive(mp, "tertiary",param_type,tertiary_macro);
+@:tertiary_}{\&{tertiary} primitive@>
+
+@ @<Cases of |print_cmd...@>=
+case param_type:
+ if ( m>=expr_base ) {
+ if ( m==expr_base ) mp_print(mp, "expr");
+ else if ( m==suffix_base ) mp_print(mp, "suffix");
+ else mp_print(mp, "text");
+ } else if ( m<secondary_macro ) {
+ mp_print(mp, "primary");
+ } else if ( m==secondary_macro ) {
+ mp_print(mp, "secondary");
+ } else {
+ mp_print(mp, "tertiary");
+ }
+ break;
+
+@ Let's turn next to the more complex processing associated with \&{def}
+and \&{vardef}. When the following procedure is called, |cur_mod|
+should be either |start_def| or |var_def|.
+
+@c @<Declare the procedure called |check_delimiter|@>
+@<Declare the function called |scan_declared_variable|@>
+void mp_scan_def (MP mp) {
+ int m; /* the type of definition */
+ int n; /* the number of special suffix parameters */
+ int k; /* the total number of parameters */
+ int c; /* the kind of macro we're defining */
+ pointer r; /* parameter-substitution list */
+ pointer q; /* tail of the macro token list */
+ pointer p; /* temporary storage */
+ halfword base; /* |expr_base|, |suffix_base|, or |text_base| */
+ pointer l_delim,r_delim; /* matching delimiters */
+ m=mp->cur_mod; c=general_macro; link(hold_head)=null;
+ q=mp_get_avail(mp); ref_count(q)=null; r=null;
+ @<Scan the token or variable to be defined;
+ set |n|, |scanner_status|, and |warning_info|@>;
+ k=n;
+ if ( mp->cur_cmd==left_delimiter ) {
+ @<Absorb delimited parameters, putting them into lists |q| and |r|@>;
+ }
+ if ( mp->cur_cmd==param_type ) {
+ @<Absorb undelimited parameters, putting them into list |r|@>;
+ }
+ mp_check_equals(mp);
+ p=mp_get_avail(mp); info(p)=c; link(q)=p;
+ @<Attach the replacement text to the tail of node |p|@>;
+ mp->scanner_status=normal; mp_get_x_next(mp);
+}
+
+@ We don't put `|frozen_end_group|' into the replacement text of
+a \&{vardef}, because the user may want to redefine `\.{endgroup}'.
+
+@<Attach the replacement text to the tail of node |p|@>=
+if ( m==start_def ) {
+ link(p)=mp_scan_toks(mp, macro_def,r,null,n);
+} else {
+ q=mp_get_avail(mp); info(q)=mp->bg_loc; link(p)=q;
+ p=mp_get_avail(mp); info(p)=mp->eg_loc;
+ link(q)=mp_scan_toks(mp, macro_def,r,p,n);
+}
+if ( mp->warning_info==bad_vardef )
+ mp_flush_token_list(mp, value(bad_vardef))
+
+@ @<Glob...@>=
+int bg_loc;
+int eg_loc; /* hash addresses of `\.{begingroup}' and `\.{endgroup}' */
+
+@ @<Scan the token or variable to be defined;...@>=
+if ( m==start_def ) {
+ mp_get_clear_symbol(mp); mp->warning_info=mp->cur_sym; get_t_next;
+ mp->scanner_status=op_defining; n=0;
+ eq_type(mp->warning_info)=defined_macro; equiv(mp->warning_info)=q;
+} else {
+ p=mp_scan_declared_variable(mp);
+ mp_flush_variable(mp, equiv(info(p)),link(p),true);
+ mp->warning_info=mp_find_variable(mp, p); mp_flush_list(mp, p);
+ if ( mp->warning_info==null ) @<Change to `\.{a bad variable}'@>;
+ mp->scanner_status=var_defining; n=2;
+ if ( mp->cur_cmd==macro_special ) if ( mp->cur_mod==macro_suffix ) {/* \.{\AT!\#} */
+ n=3; get_t_next;
+ }
+ type(mp->warning_info)=mp_unsuffixed_macro-2+n; value(mp->warning_info)=q;
+} /* |mp_suffixed_macro=mp_unsuffixed_macro+1| */
+
+@ @<Change to `\.{a bad variable}'@>=
+{
+ print_err("This variable already starts with a macro");
+@.This variable already...@>
+ help2("After `vardef a' you can\'t say `vardef a.b'.")
+ ("So I'll have to discard this definition.");
+ mp_error(mp); mp->warning_info=bad_vardef;
+}
+
+@ @<Initialize table entries...@>=
+name_type(bad_vardef)=mp_root; link(bad_vardef)=frozen_bad_vardef;
+equiv(frozen_bad_vardef)=bad_vardef; eq_type(frozen_bad_vardef)=tag_token;
+
+@ @<Absorb delimited parameters, putting them into lists |q| and |r|@>=
+do {
+ l_delim=mp->cur_sym; r_delim=mp->cur_mod; get_t_next;
+ if ( (mp->cur_cmd==param_type)&&(mp->cur_mod>=expr_base) ) {
+ base=mp->cur_mod;
+ } else {
+ print_err("Missing parameter type; `expr' will be assumed");
+@.Missing parameter type@>
+ help1("You should've had `expr' or `suffix' or `text' here.");
+ mp_back_error(mp); base=expr_base;
+ }
+ @<Absorb parameter tokens for type |base|@>;
+ mp_check_delimiter(mp, l_delim,r_delim);
+ get_t_next;
+} while (mp->cur_cmd==left_delimiter)
+
+@ @<Absorb parameter tokens for type |base|@>=
+do {
+ link(q)=mp_get_avail(mp); q=link(q); info(q)=base+k;
+ mp_get_symbol(mp); p=mp_get_node(mp, token_node_size);
+ value(p)=base+k; info(p)=mp->cur_sym;
+ if ( k==mp->param_size ) mp_overflow(mp, "parameter stack size",mp->param_size);
+@:MetaPost capacity exceeded parameter stack size}{\quad parameter stack size@>
+ incr(k); link(p)=r; r=p; get_t_next;
+} while (mp->cur_cmd==comma)
+
+@ @<Absorb undelimited parameters, putting them into list |r|@>=
+{
+ p=mp_get_node(mp, token_node_size);
+ if ( mp->cur_mod<expr_base ) {
+ c=mp->cur_mod; value(p)=expr_base+k;
+ } else {
+ value(p)=mp->cur_mod+k;
+ if ( mp->cur_mod==expr_base ) c=expr_macro;
+ else if ( mp->cur_mod==suffix_base ) c=suffix_macro;
+ else c=text_macro;
+ }
+ if ( k==mp->param_size ) mp_overflow(mp, "parameter stack size",mp->param_size);
+ incr(k); mp_get_symbol(mp); info(p)=mp->cur_sym; link(p)=r; r=p; get_t_next;
+ if ( c==expr_macro ) if ( mp->cur_cmd==of_token ) {
+ c=of_macro; p=mp_get_node(mp, token_node_size);
+ if ( k==mp->param_size ) mp_overflow(mp, "parameter stack size",mp->param_size);
+ value(p)=expr_base+k; mp_get_symbol(mp); info(p)=mp->cur_sym;
+ link(p)=r; r=p; get_t_next;
+ }
+}
+
+@* \[32] Expanding the next token.
+Only a few command codes |<min_command| can possibly be returned by
+|get_t_next|; in increasing order, they are
+|if_test|, |fi_or_else|, |input|, |iteration|, |repeat_loop|,
+|exit_test|, |relax|, |scan_tokens|, |expand_after|, and |defined_macro|.
+
+\MP\ usually gets the next token of input by saying |get_x_next|. This is
+like |get_t_next| except that it keeps getting more tokens until
+finding |cur_cmd>=min_command|. In other words, |get_x_next| expands
+macros and removes conditionals or iterations or input instructions that
+might be present.
+
+It follows that |get_x_next| might invoke itself recursively. In fact,
+there is massive recursion, since macro expansion can involve the
+scanning of arbitrarily complex expressions, which in turn involve
+macro expansion and conditionals, etc.
+@^recursion@>
+
+Therefore it's necessary to declare a whole bunch of |forward|
+procedures at this point, and to insert some other procedures
+that will be invoked by |get_x_next|.
+
+@<Declarations@>=
+void mp_scan_primary (MP mp);
+void mp_scan_secondary (MP mp);
+void mp_scan_tertiary (MP mp);
+void mp_scan_expression (MP mp);
+void mp_scan_suffix (MP mp);
+@<Declare the procedure called |macro_call|@>
+void mp_get_boolean (MP mp);
+void mp_pass_text (MP mp);
+void mp_conditional (MP mp);
+void mp_start_input (MP mp);
+void mp_begin_iteration (MP mp);
+void mp_resume_iteration (MP mp);
+void mp_stop_iteration (MP mp);
+
+@ An auxiliary subroutine called |expand| is used by |get_x_next|
+when it has to do exotic expansion commands.
+
+@c void mp_expand (MP mp) {
+ pointer p; /* for list manipulation */
+ size_t k; /* something that we hope is |<=buf_size| */
+ pool_pointer j; /* index into |str_pool| */
+ if ( mp->internal[mp_tracing_commands]>unity )
+ if ( mp->cur_cmd!=defined_macro )
+ show_cur_cmd_mod;
+ switch (mp->cur_cmd) {
+ case if_test:
+ mp_conditional(mp); /* this procedure is discussed in Part 36 below */
+ break;
+ case fi_or_else:
+ @<Terminate the current conditional and skip to \&{fi}@>;
+ break;
+ case input:
+ @<Initiate or terminate input from a file@>;
+ break;
+ case iteration:
+ if ( mp->cur_mod==end_for ) {
+ @<Scold the user for having an extra \&{endfor}@>;
+ } else {
+ mp_begin_iteration(mp); /* this procedure is discussed in Part 37 below */
+ }
+ break;
+ case repeat_loop:
+ @<Repeat a loop@>;
+ break;
+ case exit_test:
+ @<Exit a loop if the proper time has come@>;
+ break;
+ case relax:
+ break;
+ case expand_after:
+ @<Expand the token after the next token@>;
+ break;
+ case scan_tokens:
+ @<Put a string into the input buffer@>;
+ break;
+ case defined_macro:
+ mp_macro_call(mp, mp->cur_mod,null,mp->cur_sym);
+ break;
+ }; /* there are no other cases */
+}
+
+@ @<Scold the user...@>=
+{
+ print_err("Extra `endfor'");
+@.Extra `endfor'@>
+ help2("I'm not currently working on a for loop,")
+ ("so I had better not try to end anything.");
+ mp_error(mp);
+}
+
+@ The processing of \&{input} involves the |start_input| subroutine,
+which will be declared later; the processing of \&{endinput} is trivial.
+
+@<Put each...@>=
+mp_primitive(mp, "input",input,0);
+@:input_}{\&{input} primitive@>
+mp_primitive(mp, "endinput",input,1);
+@:end_input_}{\&{endinput} primitive@>
+
+@ @<Cases of |print_cmd_mod|...@>=
+case input:
+ if ( m==0 ) mp_print(mp, "input");
+ else mp_print(mp, "endinput");
+ break;
+
+@ @<Initiate or terminate input...@>=
+if ( mp->cur_mod>0 ) mp->force_eof=true;
+else mp_start_input(mp)
+
+@ We'll discuss the complicated parts of loop operations later. For now
+it suffices to know that there's a global variable called |loop_ptr|
+that will be |null| if no loop is in progress.
+
+@<Repeat a loop@>=
+{ while ( token_state &&(loc==null) )
+ mp_end_token_list(mp); /* conserve stack space */
+ if ( mp->loop_ptr==null ) {
+ print_err("Lost loop");
+@.Lost loop@>
+ help2("I'm confused; after exiting from a loop, I still seem")
+ ("to want to repeat it. I'll try to forget the problem.");
+ mp_error(mp);
+ } else {
+ mp_resume_iteration(mp); /* this procedure is in Part 37 below */
+ }
+}
+
+@ @<Exit a loop if the proper time has come@>=
+{ mp_get_boolean(mp);
+ if ( mp->internal[mp_tracing_commands]>unity )
+ mp_show_cmd_mod(mp, nullary,mp->cur_exp);
+ if ( mp->cur_exp==true_code ) {
+ if ( mp->loop_ptr==null ) {
+ print_err("No loop is in progress");
+@.No loop is in progress@>
+ help1("Why say `exitif' when there's nothing to exit from?");
+ if ( mp->cur_cmd==semicolon ) mp_error(mp); else mp_back_error(mp);
+ } else {
+ @<Exit prematurely from an iteration@>;
+ }
+ } else if ( mp->cur_cmd!=semicolon ) {
+ mp_missing_err(mp, ";");
+@.Missing `;'@>
+ help2("After `exitif <boolean exp>' I expect to see a semicolon.")
+ ("I shall pretend that one was there."); mp_back_error(mp);
+ }
+}
+
+@ Here we use the fact that |forever_text| is the only |token_type| that
+is less than |loop_text|.
+
+@<Exit prematurely...@>=
+{ p=null;
+ do {
+ if ( file_state ) {
+ mp_end_file_reading(mp);
+ } else {
+ if ( token_type<=loop_text ) p=start;
+ mp_end_token_list(mp);
+ }
+ } while (p==null);
+ if ( p!=info(mp->loop_ptr) ) mp_fatal_error(mp, "*** (loop confusion)");
+@.loop confusion@>
+ mp_stop_iteration(mp); /* this procedure is in Part 34 below */
+}
+
+@ @<Expand the token after the next token@>=
+{ get_t_next;
+ p=mp_cur_tok(mp); get_t_next;
+ if ( mp->cur_cmd<min_command ) mp_expand(mp);
+ else mp_back_input(mp);
+ back_list(p);
+}
+
+@ @<Put a string into the input buffer@>=
+{ mp_get_x_next(mp); mp_scan_primary(mp);
+ if ( mp->cur_type!=mp_string_type ) {
+ mp_disp_err(mp, null,"Not a string");
+@.Not a string@>
+ help2("I'm going to flush this expression, since")
+ ("scantokens should be followed by a known string.");
+ mp_put_get_flush_error(mp, 0);
+ } else {
+ mp_back_input(mp);
+ if ( length(mp->cur_exp)>0 )
+ @<Pretend we're reading a new one-line file@>;
+ }
+}
+
+@ @<Pretend we're reading a new one-line file@>=
+{ mp_begin_file_reading(mp); name=is_scantok;
+ k=mp->first+length(mp->cur_exp);
+ if ( k>=mp->max_buf_stack ) {
+ while ( k>=mp->buf_size ) {
+ mp_reallocate_buffer(mp,(mp->buf_size+(mp->buf_size>>2)));
+ }
+ mp->max_buf_stack=k+1;
+ }
+ j=mp->str_start[mp->cur_exp]; limit=k;
+ while ( mp->first<(size_t)limit ) {
+ mp->buffer[mp->first]=mp->str_pool[j]; incr(j); incr(mp->first);
+ }
+ mp->buffer[limit]='%'; mp->first=limit+1; loc=start;
+ mp_flush_cur_exp(mp, 0);
+}
+
+@ Here finally is |get_x_next|.
+
+The expression scanning routines to be considered later
+communicate via the global quantities |cur_type| and |cur_exp|;
+we must be very careful to save and restore these quantities while
+macros are being expanded.
+@^inner loop@>
+
+@<Declarations@>=
+void mp_get_x_next (MP mp);
+
+@ @c void mp_get_x_next (MP mp) {
+ pointer save_exp; /* a capsule to save |cur_type| and |cur_exp| */
+ get_t_next;
+ if ( mp->cur_cmd<min_command ) {
+ save_exp=mp_stash_cur_exp(mp);
+ do {
+ if ( mp->cur_cmd==defined_macro )
+ mp_macro_call(mp, mp->cur_mod,null,mp->cur_sym);
+ else
+ mp_expand(mp);
+ get_t_next;
+ } while (mp->cur_cmd<min_command);
+ mp_unstash_cur_exp(mp, save_exp); /* that restores |cur_type| and |cur_exp| */
+ }
+}
+
+@ Now let's consider the |macro_call| procedure, which is used to start up
+all user-defined macros. Since the arguments to a macro might be expressions,
+|macro_call| is recursive.
+@^recursion@>
+
+The first parameter to |macro_call| points to the reference count of the
+token list that defines the macro. The second parameter contains any
+arguments that have already been parsed (see below). The third parameter
+points to the symbolic token that names the macro. If the third parameter
+is |null|, the macro was defined by \&{vardef}, so its name can be
+reconstructed from the prefix and ``at'' arguments found within the
+second parameter.
+
+What is this second parameter? It's simply a linked list of one-word items,
+whose |info| fields point to the arguments. In other words, if |arg_list=null|,
+no arguments have been scanned yet; otherwise |info(arg_list)| points to
+the first scanned argument, and |link(arg_list)| points to the list of
+further arguments (if any).
+
+Arguments of type \&{expr} are so-called capsules, which we will
+discuss later when we concentrate on expressions; they can be
+recognized easily because their |link| field is |void|. Arguments of type
+\&{suffix} and \&{text} are token lists without reference counts.
+
+@ After argument scanning is complete, the arguments are moved to the
+|param_stack|. (They can't be put on that stack any sooner, because
+the stack is growing and shrinking in unpredictable ways as more arguments
+are being acquired.) Then the macro body is fed to the scanner; i.e.,
+the replacement text of the macro is placed at the top of the \MP's
+input stack, so that |get_t_next| will proceed to read it next.
+
+@<Declare the procedure called |macro_call|@>=
+@<Declare the procedure called |print_macro_name|@>
+@<Declare the procedure called |print_arg|@>
+@<Declare the procedure called |scan_text_arg|@>
+void mp_macro_call (MP mp,pointer def_ref, pointer arg_list,
+ pointer macro_name) ;
+
+@ @c
+void mp_macro_call (MP mp,pointer def_ref, pointer arg_list,
+ pointer macro_name) {
+ /* invokes a user-defined control sequence */
+ pointer r; /* current node in the macro's token list */
+ pointer p,q; /* for list manipulation */
+ integer n; /* the number of arguments */
+ pointer tail = 0; /* tail of the argument list */
+ pointer l_delim=0,r_delim=0; /* a delimiter pair */
+ r=link(def_ref); add_mac_ref(def_ref);
+ if ( arg_list==null ) {
+ n=0;
+ } else {
+ @<Determine the number |n| of arguments already supplied,
+ and set |tail| to the tail of |arg_list|@>;
+ }
+ if ( mp->internal[mp_tracing_macros]>0 ) {
+ @<Show the text of the macro being expanded, and the existing arguments@>;
+ }
+ @<Scan the remaining arguments, if any; set |r| to the first token
+ of the replacement text@>;
+ @<Feed the arguments and replacement text to the scanner@>;
+}
+
+@ @<Show the text of the macro...@>=
+mp_begin_diagnostic(mp); mp_print_ln(mp);
+mp_print_macro_name(mp, arg_list,macro_name);
+if ( n==3 ) mp_print(mp, "@@#"); /* indicate a suffixed macro */
+mp_show_macro(mp, def_ref,null,100000);
+if ( arg_list!=null ) {
+ n=0; p=arg_list;
+ do {
+ q=info(p);
+ mp_print_arg(mp, q,n,0);
+ incr(n); p=link(p);
+ } while (p!=null);
+}
+mp_end_diagnostic(mp, false)
+
+
+@ @<Declare the procedure called |print_macro_name|@>=
+void mp_print_macro_name (MP mp,pointer a, pointer n);
+
+@ @c
+void mp_print_macro_name (MP mp,pointer a, pointer n) {
+ pointer p,q; /* they traverse the first part of |a| */
+ if ( n!=null ) {
+ mp_print_text(n);
+ } else {
+ p=info(a);
+ if ( p==null ) {
+ mp_print_text(info(info(link(a))));
+ } else {
+ q=p;
+ while ( link(q)!=null ) q=link(q);
+ link(q)=info(link(a));
+ mp_show_token_list(mp, p,null,1000,0);
+ link(q)=null;
+ }
+ }
+}
+
+@ @<Declare the procedure called |print_arg|@>=
+void mp_print_arg (MP mp,pointer q, integer n, pointer b) ;
+
+@ @c
+void mp_print_arg (MP mp,pointer q, integer n, pointer b) {
+ if ( link(q)==mp_void ) mp_print_nl(mp, "(EXPR");
+ else if ( (b<text_base)&&(b!=text_macro) ) mp_print_nl(mp, "(SUFFIX");
+ else mp_print_nl(mp, "(TEXT");
+ mp_print_int(mp, n); mp_print(mp, ")<-");
+ if ( link(q)==mp_void ) mp_print_exp(mp, q,1);
+ else mp_show_token_list(mp, q,null,1000,0);
+}
+
+@ @<Determine the number |n| of arguments already supplied...@>=
+{
+ n=1; tail=arg_list;
+ while ( link(tail)!=null ) {
+ incr(n); tail=link(tail);
+ }
+}
+
+@ @<Scan the remaining arguments, if any; set |r|...@>=
+mp->cur_cmd=comma+1; /* anything |<>comma| will do */
+while ( info(r)>=expr_base ) {
+ @<Scan the delimited argument represented by |info(r)|@>;
+ r=link(r);
+}
+if ( mp->cur_cmd==comma ) {
+ print_err("Too many arguments to ");
+@.Too many arguments...@>
+ mp_print_macro_name(mp, arg_list,macro_name); mp_print_char(mp, ';');
+ mp_print_nl(mp, " Missing `"); mp_print_text(r_delim);
+@.Missing `)'...@>
+ mp_print(mp, "' has been inserted");
+ help3("I'm going to assume that the comma I just read was a")
+ ("right delimiter, and then I'll begin expanding the macro.")
+ ("You might want to delete some tokens before continuing.");
+ mp_error(mp);
+}
+if ( info(r)!=general_macro ) {
+ @<Scan undelimited argument(s)@>;
+}
+r=link(r)
+
+@ At this point, the reader will find it advisable to review the explanation
+of token list format that was presented earlier, paying special attention to
+the conventions that apply only at the beginning of a macro's token list.
+
+On the other hand, the reader will have to take the expression-parsing
+aspects of the following program on faith; we will explain |cur_type|
+and |cur_exp| later. (Several things in this program depend on each other,
+and it's necessary to jump into the circle somewhere.)
+
+@<Scan the delimited argument represented by |info(r)|@>=
+if ( mp->cur_cmd!=comma ) {
+ mp_get_x_next(mp);
+ if ( mp->cur_cmd!=left_delimiter ) {
+ print_err("Missing argument to ");
+@.Missing argument...@>
+ mp_print_macro_name(mp, arg_list,macro_name);
+ help3("That macro has more parameters than you thought.")
+ ("I'll continue by pretending that each missing argument")
+ ("is either zero or null.");
+ if ( info(r)>=suffix_base ) {
+ mp->cur_exp=null; mp->cur_type=mp_token_list;
+ } else {
+ mp->cur_exp=0; mp->cur_type=mp_known;
+ }
+ mp_back_error(mp); mp->cur_cmd=right_delimiter;
+ goto FOUND;
+ }
+ l_delim=mp->cur_sym; r_delim=mp->cur_mod;
+}
+@<Scan the argument represented by |info(r)|@>;
+if ( mp->cur_cmd!=comma )
+ @<Check that the proper right delimiter was present@>;
+FOUND:
+@<Append the current expression to |arg_list|@>
+
+@ @<Check that the proper right delim...@>=
+if ( (mp->cur_cmd!=right_delimiter)||(mp->cur_mod!=l_delim) ) {
+ if ( info(link(r))>=expr_base ) {
+ mp_missing_err(mp, ",");
+@.Missing `,'@>
+ help3("I've finished reading a macro argument and am about to")
+ ("read another; the arguments weren't delimited correctly.")
+ ("You might want to delete some tokens before continuing.");
+ mp_back_error(mp); mp->cur_cmd=comma;
+ } else {
+ mp_missing_err(mp, str(text(r_delim)));
+@.Missing `)'@>
+ help2("I've gotten to the end of the macro parameter list.")
+ ("You might want to delete some tokens before continuing.");
+ mp_back_error(mp);
+ }
+}
+
+@ A \&{suffix} or \&{text} parameter will have been scanned as
+a token list pointed to by |cur_exp|, in which case we will have
+|cur_type=token_list|.
+
+@<Append the current expression to |arg_list|@>=
+{
+ p=mp_get_avail(mp);
+ if ( mp->cur_type==mp_token_list ) info(p)=mp->cur_exp;
+ else info(p)=mp_stash_cur_exp(mp);
+ if ( mp->internal[mp_tracing_macros]>0 ) {
+ mp_begin_diagnostic(mp); mp_print_arg(mp, info(p),n,info(r));
+ mp_end_diagnostic(mp, false);
+ }
+ if ( arg_list==null ) arg_list=p;
+ else link(tail)=p;
+ tail=p; incr(n);
+}
+
+@ @<Scan the argument represented by |info(r)|@>=
+if ( info(r)>=text_base ) {
+ mp_scan_text_arg(mp, l_delim,r_delim);
+} else {
+ mp_get_x_next(mp);
+ if ( info(r)>=suffix_base ) mp_scan_suffix(mp);
+ else mp_scan_expression(mp);
+}
+
+@ The parameters to |scan_text_arg| are either a pair of delimiters
+or zero; the latter case is for undelimited text arguments, which
+end with the first semicolon or \&{endgroup} or \&{end} that is not
+contained in a group.
+
+@<Declare the procedure called |scan_text_arg|@>=
+void mp_scan_text_arg (MP mp,pointer l_delim, pointer r_delim) ;
+
+@ @c
+void mp_scan_text_arg (MP mp,pointer l_delim, pointer r_delim) {
+ integer balance; /* excess of |l_delim| over |r_delim| */
+ pointer p; /* list tail */
+ mp->warning_info=l_delim; mp->scanner_status=absorbing;
+ p=hold_head; balance=1; link(hold_head)=null;
+ while (1) {
+ get_t_next;
+ if ( l_delim==0 ) {
+ @<Adjust the balance for an undelimited argument; |break| if done@>;
+ } else {
+ @<Adjust the balance for a delimited argument; |break| if done@>;
+ }
+ link(p)=mp_cur_tok(mp); p=link(p);
+ }
+ mp->cur_exp=link(hold_head); mp->cur_type=mp_token_list;
+ mp->scanner_status=normal;
+}
+
+@ @<Adjust the balance for a delimited argument...@>=
+if ( mp->cur_cmd==right_delimiter ) {
+ if ( mp->cur_mod==l_delim ) {
+ decr(balance);
+ if ( balance==0 ) break;
+ }
+} else if ( mp->cur_cmd==left_delimiter ) {
+ if ( mp->cur_mod==r_delim ) incr(balance);
+}
+
+@ @<Adjust the balance for an undelimited...@>=
+if ( end_of_statement ) { /* |cur_cmd=semicolon|, |end_group|, or |stop| */
+ if ( balance==1 ) { break; }
+ else { if ( mp->cur_cmd==end_group ) decr(balance); }
+} else if ( mp->cur_cmd==begin_group ) {
+ incr(balance);
+}
+
+@ @<Scan undelimited argument(s)@>=
+{
+ if ( info(r)<text_macro ) {
+ mp_get_x_next(mp);
+ if ( info(r)!=suffix_macro ) {
+ if ( (mp->cur_cmd==equals)||(mp->cur_cmd==assignment) ) mp_get_x_next(mp);
+ }
+ }
+ switch (info(r)) {
+ case primary_macro:mp_scan_primary(mp); break;
+ case secondary_macro:mp_scan_secondary(mp); break;
+ case tertiary_macro:mp_scan_tertiary(mp); break;
+ case expr_macro:mp_scan_expression(mp); break;
+ case of_macro:
+ @<Scan an expression followed by `\&{of} $\langle$primary$\rangle$'@>;
+ break;
+ case suffix_macro:
+ @<Scan a suffix with optional delimiters@>;
+ break;
+ case text_macro:mp_scan_text_arg(mp, 0,0); break;
+ } /* there are no other cases */
+ mp_back_input(mp);
+ @<Append the current expression to |arg_list|@>;
+}
+
+@ @<Scan an expression followed by `\&{of} $\langle$primary$\rangle$'@>=
+{
+ mp_scan_expression(mp); p=mp_get_avail(mp); info(p)=mp_stash_cur_exp(mp);
+ if ( mp->internal[mp_tracing_macros]>0 ) {
+ mp_begin_diagnostic(mp); mp_print_arg(mp, info(p),n,0);
+ mp_end_diagnostic(mp, false);
+ }
+ if ( arg_list==null ) arg_list=p; else link(tail)=p;
+ tail=p;incr(n);
+ if ( mp->cur_cmd!=of_token ) {
+ mp_missing_err(mp, "of"); mp_print(mp, " for ");
+@.Missing `of'@>
+ mp_print_macro_name(mp, arg_list,macro_name);
+ help1("I've got the first argument; will look now for the other.");
+ mp_back_error(mp);
+ }
+ mp_get_x_next(mp); mp_scan_primary(mp);
+}
+
+@ @<Scan a suffix with optional delimiters@>=
+{
+ if ( mp->cur_cmd!=left_delimiter ) {
+ l_delim=null;
+ } else {
+ l_delim=mp->cur_sym; r_delim=mp->cur_mod; mp_get_x_next(mp);
+ };
+ mp_scan_suffix(mp);
+ if ( l_delim!=null ) {
+ if ((mp->cur_cmd!=right_delimiter)||(mp->cur_mod!=l_delim) ) {
+ mp_missing_err(mp, str(text(r_delim)));
+@.Missing `)'@>
+ help2("I've gotten to the end of the macro parameter list.")
+ ("You might want to delete some tokens before continuing.");
+ mp_back_error(mp);
+ }
+ mp_get_x_next(mp);
+ }
+}
+
+@ Before we put a new token list on the input stack, it is wise to clean off
+all token lists that have recently been depleted. Then a user macro that ends
+with a call to itself will not require unbounded stack space.
+
+@<Feed the arguments and replacement text to the scanner@>=
+while ( token_state &&(loc==null) ) mp_end_token_list(mp); /* conserve stack space */
+if ( mp->param_ptr+n>mp->max_param_stack ) {
+ mp->max_param_stack=mp->param_ptr+n;
+ if ( mp->max_param_stack>mp->param_size )
+ mp_overflow(mp, "parameter stack size",mp->param_size);
+@:MetaPost capacity exceeded parameter stack size}{\quad parameter stack size@>
+}
+mp_begin_token_list(mp, def_ref,macro); name=macro_name; loc=r;
+if ( n>0 ) {
+ p=arg_list;
+ do {
+ mp->param_stack[mp->param_ptr]=info(p); incr(mp->param_ptr); p=link(p);
+ } while (p!=null);
+ mp_flush_list(mp, arg_list);
+}
+
+@ It's sometimes necessary to put a single argument onto |param_stack|.
+The |stack_argument| subroutine does this.
+
+@c void mp_stack_argument (MP mp,pointer p) {
+ if ( mp->param_ptr==mp->max_param_stack ) {
+ incr(mp->max_param_stack);
+ if ( mp->max_param_stack>mp->param_size )
+ mp_overflow(mp, "parameter stack size",mp->param_size);
+@:MetaPost capacity exceeded parameter stack size}{\quad parameter stack size@>
+ }
+ mp->param_stack[mp->param_ptr]=p; incr(mp->param_ptr);
+}
+
+@* \[33] Conditional processing.
+Let's consider now the way \&{if} commands are handled.
+
+Conditions can be inside conditions, and this nesting has a stack
+that is independent of other stacks.
+Four global variables represent the top of the condition stack:
+|cond_ptr| points to pushed-down entries, if~any; |cur_if| tells whether
+we are processing \&{if} or \&{elseif}; |if_limit| specifies
+the largest code of a |fi_or_else| command that is syntactically legal;
+and |if_line| is the line number at which the current conditional began.
+
+If no conditions are currently in progress, the condition stack has the
+special state |cond_ptr=null|, |if_limit=normal|, |cur_if=0|, |if_line=0|.
+Otherwise |cond_ptr| points to a two-word node; the |type|, |name_type|, and
+|link| fields of the first word contain |if_limit|, |cur_if|, and
+|cond_ptr| at the next level, and the second word contains the
+corresponding |if_line|.
+
+@d if_node_size 2 /* number of words in stack entry for conditionals */
+@d if_line_field(A) mp->mem[(A)+1].cint
+@d if_code 1 /* code for \&{if} being evaluated */
+@d fi_code 2 /* code for \&{fi} */
+@d else_code 3 /* code for \&{else} */
+@d else_if_code 4 /* code for \&{elseif} */
+
+@<Glob...@>=
+pointer cond_ptr; /* top of the condition stack */
+integer if_limit; /* upper bound on |fi_or_else| codes */
+small_number cur_if; /* type of conditional being worked on */
+integer if_line; /* line where that conditional began */
+
+@ @<Set init...@>=
+mp->cond_ptr=null; mp->if_limit=normal; mp->cur_if=0; mp->if_line=0;
+
+@ @<Put each...@>=
+mp_primitive(mp, "if",if_test,if_code);
+@:if_}{\&{if} primitive@>
+mp_primitive(mp, "fi",fi_or_else,fi_code); mp->eqtb[frozen_fi]=mp->eqtb[mp->cur_sym];
+@:fi_}{\&{fi} primitive@>
+mp_primitive(mp, "else",fi_or_else,else_code);
+@:else_}{\&{else} primitive@>
+mp_primitive(mp, "elseif",fi_or_else,else_if_code);
+@:else_if_}{\&{elseif} primitive@>
+
+@ @<Cases of |print_cmd_mod|...@>=
+case if_test:
+case fi_or_else:
+ switch (m) {
+ case if_code:mp_print(mp, "if"); break;
+ case fi_code:mp_print(mp, "fi"); break;
+ case else_code:mp_print(mp, "else"); break;
+ default: mp_print(mp, "elseif"); break;
+ }
+ break;
+
+@ Here is a procedure that ignores text until coming to an \&{elseif},
+\&{else}, or \&{fi} at level zero of $\&{if}\ldots\&{fi}$
+nesting. After it has acted, |cur_mod| will indicate the token that
+was found.
+
+\MP's smallest two command codes are |if_test| and |fi_or_else|; this
+makes the skipping process a bit simpler.
+
+@c
+void mp_pass_text (MP mp) {
+ integer l = 0;
+ mp->scanner_status=skipping;
+ mp->warning_info=mp_true_line(mp);
+ while (1) {
+ get_t_next;
+ if ( mp->cur_cmd<=fi_or_else ) {
+ if ( mp->cur_cmd<fi_or_else ) {
+ incr(l);
+ } else {
+ if ( l==0 ) break;
+ if ( mp->cur_mod==fi_code ) decr(l);
+ }
+ } else {
+ @<Decrease the string reference count,
+ if the current token is a string@>;
+ }
+ }
+ mp->scanner_status=normal;
+}
+
+@ @<Decrease the string reference count...@>=
+if ( mp->cur_cmd==string_token ) { delete_str_ref(mp->cur_mod); }
+
+@ When we begin to process a new \&{if}, we set |if_limit:=if_code|; then
+if \&{elseif} or \&{else} or \&{fi} occurs before the current \&{if}
+condition has been evaluated, a colon will be inserted.
+A construction like `\.{if fi}' would otherwise get \MP\ confused.
+
+@<Push the condition stack@>=
+{ p=mp_get_node(mp, if_node_size); link(p)=mp->cond_ptr; type(p)=mp->if_limit;
+ name_type(p)=mp->cur_if; if_line_field(p)=mp->if_line;
+ mp->cond_ptr=p; mp->if_limit=if_code; mp->if_line=mp_true_line(mp);
+ mp->cur_if=if_code;
+}
+
+@ @<Pop the condition stack@>=
+{ p=mp->cond_ptr; mp->if_line=if_line_field(p);
+ mp->cur_if=name_type(p); mp->if_limit=type(p); mp->cond_ptr=link(p);
+ mp_free_node(mp, p,if_node_size);
+}
+
+@ Here's a procedure that changes the |if_limit| code corresponding to
+a given value of |cond_ptr|.
+
+@c void mp_change_if_limit (MP mp,small_number l, pointer p) {
+ pointer q;
+ if ( p==mp->cond_ptr ) {
+ mp->if_limit=l; /* that's the easy case */
+ } else {
+ q=mp->cond_ptr;
+ while (1) {
+ if ( q==null ) mp_confusion(mp, "if");
+@:this can't happen if}{\quad if@>
+ if ( link(q)==p ) {
+ type(q)=l; return;
+ }
+ q=link(q);
+ }
+ }
+}
+
+@ The user is supposed to put colons into the proper parts of conditional
+statements. Therefore, \MP\ has to check for their presence.
+
+@c
+void mp_check_colon (MP mp) {
+ if ( mp->cur_cmd!=colon ) {
+ mp_missing_err(mp, ":");
+@.Missing `:'@>
+ help2("There should've been a colon after the condition.")
+ ("I shall pretend that one was there.");;
+ mp_back_error(mp);
+ }
+}
+
+@ A condition is started when the |get_x_next| procedure encounters
+an |if_test| command; in that case |get_x_next| calls |conditional|,
+which is a recursive procedure.
+@^recursion@>
+
+@c void mp_conditional (MP mp) {
+ pointer save_cond_ptr; /* |cond_ptr| corresponding to this conditional */
+ int new_if_limit; /* future value of |if_limit| */
+ pointer p; /* temporary register */
+ @<Push the condition stack@>;
+ save_cond_ptr=mp->cond_ptr;
+RESWITCH:
+ mp_get_boolean(mp); new_if_limit=else_if_code;
+ if ( mp->internal[mp_tracing_commands]>unity ) {
+ @<Display the boolean value of |cur_exp|@>;
+ }
+FOUND:
+ mp_check_colon(mp);
+ if ( mp->cur_exp==true_code ) {
+ mp_change_if_limit(mp, new_if_limit,save_cond_ptr);
+ return; /* wait for \&{elseif}, \&{else}, or \&{fi} */
+ };
+ @<Skip to \&{elseif} or \&{else} or \&{fi}, then |goto done|@>;
+DONE:
+ mp->cur_if=mp->cur_mod; mp->if_line=mp_true_line(mp);
+ if ( mp->cur_mod==fi_code ) {
+ @<Pop the condition stack@>
+ } else if ( mp->cur_mod==else_if_code ) {
+ goto RESWITCH;
+ } else {
+ mp->cur_exp=true_code; new_if_limit=fi_code; mp_get_x_next(mp);
+ goto FOUND;
+ }
+}
+
+@ In a construction like `\&{if} \&{if} \&{true}: $0=1$: \\{foo}
+\&{else}: \\{bar} \&{fi}', the first \&{else}
+that we come to after learning that the \&{if} is false is not the
+\&{else} we're looking for. Hence the following curious logic is needed.
+
+@<Skip to \&{elseif}...@>=
+while (1) {
+ mp_pass_text(mp);
+ if ( mp->cond_ptr==save_cond_ptr ) goto DONE;
+ else if ( mp->cur_mod==fi_code ) @<Pop the condition stack@>;
+}
+
+
+@ @<Display the boolean value...@>=
+{ mp_begin_diagnostic(mp);
+ if ( mp->cur_exp==true_code ) mp_print(mp, "{true}");
+ else mp_print(mp, "{false}");
+ mp_end_diagnostic(mp, false);
+}
+
+@ The processing of conditionals is complete except for the following
+code, which is actually part of |get_x_next|. It comes into play when
+\&{elseif}, \&{else}, or \&{fi} is scanned.
+
+@<Terminate the current conditional and skip to \&{fi}@>=
+if ( mp->cur_mod>mp->if_limit ) {
+ if ( mp->if_limit==if_code ) { /* condition not yet evaluated */
+ mp_missing_err(mp, ":");
+@.Missing `:'@>
+ mp_back_input(mp); mp->cur_sym=frozen_colon; mp_ins_error(mp);
+ } else {
+ print_err("Extra "); mp_print_cmd_mod(mp, fi_or_else,mp->cur_mod);
+@.Extra else@>
+@.Extra elseif@>
+@.Extra fi@>
+ help1("I'm ignoring this; it doesn't match any if.");
+ mp_error(mp);
+ }
+} else {
+ while ( mp->cur_mod!=fi_code ) mp_pass_text(mp); /* skip to \&{fi} */
+ @<Pop the condition stack@>;
+}
+
+@* \[34] Iterations.
+To bring our treatment of |get_x_next| to a close, we need to consider what
+\MP\ does when it sees \&{for}, \&{forsuffixes}, and \&{forever}.
+
+There's a global variable |loop_ptr| that keeps track of the \&{for} loops
+that are currently active. If |loop_ptr=null|, no loops are in progress;
+otherwise |info(loop_ptr)| points to the iterative text of the current
+(innermost) loop, and |link(loop_ptr)| points to the data for any other
+loops that enclose the current one.
+
+A loop-control node also has two other fields, called |loop_type| and
+|loop_list|, whose contents depend on the type of loop:
+
+\yskip\indent|loop_type(loop_ptr)=null| means that |loop_list(loop_ptr)|
+points to a list of one-word nodes whose |info| fields point to the
+remaining argument values of a suffix list and expression list.
+
+\yskip\indent|loop_type(loop_ptr)=mp_void| means that the current loop is
+`\&{forever}'.
+
+\yskip\indent|loop_type(loop_ptr)=progression_flag| means that
+|p=loop_list(loop_ptr)| points to a ``progression node'' and |value(p)|,
+|step_size(p)|, and |final_value(p)| contain the data for an arithmetic
+progression.
+
+\yskip\indent|loop_type(loop_ptr)=p>mp_void| means that |p| points to an edge
+header and |loop_list(loop_ptr)| points into the graphical object list for
+that edge header.
+
+\yskip\noindent In the case of a progression node, the first word is not used
+because the link field of words in the dynamic memory area cannot be arbitrary.
+
+@d loop_list_loc(A) ((A)+1) /* where the |loop_list| field resides */
+@d loop_type(A) info(loop_list_loc((A))) /* the type of \&{for} loop */
+@d loop_list(A) link(loop_list_loc((A))) /* the remaining list elements */
+@d loop_node_size 2 /* the number of words in a loop control node */
+@d progression_node_size 4 /* the number of words in a progression node */
+@d step_size(A) mp->mem[(A)+2].sc /* the step size in an arithmetic progression */
+@d final_value(A) mp->mem[(A)+3].sc /* the final value in an arithmetic progression */
+@d progression_flag (null+2)
+ /* |loop_type| value when |loop_list| points to a progression node */
+
+@<Glob...@>=
+pointer loop_ptr; /* top of the loop-control-node stack */
+
+@ @<Set init...@>=
+mp->loop_ptr=null;
+
+@ If the expressions that define an arithmetic progression in
+a \&{for} loop don't have known numeric values, the |bad_for|
+subroutine screams at the user.
+
+@c void mp_bad_for (MP mp, const char * s) {
+ mp_disp_err(mp, null,"Improper "); /* show the bad expression above the message */
+@.Improper...replaced by 0@>
+ mp_print(mp, s); mp_print(mp, " has been replaced by 0");
+ help4("When you say `for x=a step b until c',")
+ ("the initial value `a' and the step size `b'")
+ ("and the final value `c' must have known numeric values.")
+ ("I'm zeroing this one. Proceed, with fingers crossed.");
+ mp_put_get_flush_error(mp, 0);
+}
+
+@ Here's what \MP\ does when \&{for}, \&{forsuffixes}, or \&{forever}
+has just been scanned. (This code requires slight familiarity with
+expression-parsing routines that we have not yet discussed; but it seems
+to belong in the present part of the program, even though the original author
+didn't write it until later. The reader may wish to come back to it.)
+
+@c void mp_begin_iteration (MP mp) {
+ halfword m; /* |expr_base| (\&{for}) or |suffix_base| (\&{forsuffixes}) */
+ halfword n; /* hash address of the current symbol */
+ pointer s; /* the new loop-control node */
+ pointer p; /* substitution list for |scan_toks| */
+ pointer q; /* link manipulation register */
+ pointer pp; /* a new progression node */
+ m=mp->cur_mod; n=mp->cur_sym; s=mp_get_node(mp, loop_node_size);
+ if ( m==start_forever ){
+ loop_type(s)=mp_void; p=null; mp_get_x_next(mp);
+ } else {
+ mp_get_symbol(mp); p=mp_get_node(mp, token_node_size);
+ info(p)=mp->cur_sym; value(p)=m;
+ mp_get_x_next(mp);
+ if ( mp->cur_cmd==within_token ) {
+ @<Set up a picture iteration@>;
+ } else {
+ @<Check for the |"="| or |":="| in a loop header@>;
+ @<Scan the values to be used in the loop@>;
+ }
+ }
+ @<Check for the presence of a colon@>;
+ @<Scan the loop text and put it on the loop control stack@>;
+ mp_resume_iteration(mp);
+}
+
+@ @<Check for the |"="| or |":="| in a loop header@>=
+if ( (mp->cur_cmd!=equals)&&(mp->cur_cmd!=assignment) ) {
+ mp_missing_err(mp, "=");
+@.Missing `='@>
+ help3("The next thing in this loop should have been `=' or `:='.")
+ ("But don't worry; I'll pretend that an equals sign")
+ ("was present, and I'll look for the values next.");
+ mp_back_error(mp);
+}
+
+@ @<Check for the presence of a colon@>=
+if ( mp->cur_cmd!=colon ) {
+ mp_missing_err(mp, ":");
+@.Missing `:'@>
+ help3("The next thing in this loop should have been a `:'.")
+ ("So I'll pretend that a colon was present;")
+ ("everything from here to `endfor' will be iterated.");
+ mp_back_error(mp);
+}
+
+@ We append a special |frozen_repeat_loop| token in place of the
+`\&{endfor}' at the end of the loop. This will come through \MP's scanner
+at the proper time to cause the loop to be repeated.
+
+(If the user tries some shenanigan like `\&{for} $\ldots$ \&{let} \&{endfor}',
+he will be foiled by the |get_symbol| routine, which keeps frozen
+tokens unchanged. Furthermore the |frozen_repeat_loop| is an \&{outer}
+token, so it won't be lost accidentally.)
+
+@ @<Scan the loop text...@>=
+q=mp_get_avail(mp); info(q)=frozen_repeat_loop;
+mp->scanner_status=loop_defining; mp->warning_info=n;
+info(s)=mp_scan_toks(mp, iteration,p,q,0); mp->scanner_status=normal;
+link(s)=mp->loop_ptr; mp->loop_ptr=s
+
+@ @<Initialize table...@>=
+eq_type(frozen_repeat_loop)=repeat_loop+outer_tag;
+text(frozen_repeat_loop)=intern(" ENDFOR");
+
+@ The loop text is inserted into \MP's scanning apparatus by the
+|resume_iteration| routine.
+
+@c void mp_resume_iteration (MP mp) {
+ pointer p,q; /* link registers */
+ p=loop_type(mp->loop_ptr);
+ if ( p==progression_flag ) {
+ p=loop_list(mp->loop_ptr); /* now |p| points to a progression node */
+ mp->cur_exp=value(p);
+ if ( @<The arithmetic progression has ended@> ) {
+ mp_stop_iteration(mp);
+ return;
+ }
+ mp->cur_type=mp_known; q=mp_stash_cur_exp(mp); /* make |q| an \&{expr} argument */
+ value(p)=mp->cur_exp+step_size(p); /* set |value(p)| for the next iteration */
+ } else if ( p==null ) {
+ p=loop_list(mp->loop_ptr);
+ if ( p==null ) {
+ mp_stop_iteration(mp);
+ return;
+ }
+ loop_list(mp->loop_ptr)=link(p); q=info(p); free_avail(p);
+ } else if ( p==mp_void ) {
+ mp_begin_token_list(mp, info(mp->loop_ptr),forever_text); return;
+ } else {
+ @<Make |q| a capsule containing the next picture component from
+ |loop_list(loop_ptr)| or |goto not_found|@>;
+ }
+ mp_begin_token_list(mp, info(mp->loop_ptr),loop_text);
+ mp_stack_argument(mp, q);
+ if ( mp->internal[mp_tracing_commands]>unity ) {
+ @<Trace the start of a loop@>;
+ }
+ return;
+NOT_FOUND:
+ mp_stop_iteration(mp);
+}
+
+@ @<The arithmetic progression has ended@>=
+((step_size(p)>0)&&(mp->cur_exp>final_value(p)))||
+ ((step_size(p)<0)&&(mp->cur_exp<final_value(p)))
+
+@ @<Trace the start of a loop@>=
+{
+ mp_begin_diagnostic(mp); mp_print_nl(mp, "{loop value=");
+@.loop value=n@>
+ if ( (q!=null)&&(link(q)==mp_void) ) mp_print_exp(mp, q,1);
+ else mp_show_token_list(mp, q,null,50,0);
+ mp_print_char(mp, '}'); mp_end_diagnostic(mp, false);
+}
+
+@ @<Make |q| a capsule containing the next picture component from...@>=
+{ q=loop_list(mp->loop_ptr);
+ if ( q==null ) goto NOT_FOUND;
+ skip_component(q) goto NOT_FOUND;
+ mp->cur_exp=mp_copy_objects(mp, loop_list(mp->loop_ptr),q);
+ mp_init_bbox(mp, mp->cur_exp);
+ mp->cur_type=mp_picture_type;
+ loop_list(mp->loop_ptr)=q;
+ q=mp_stash_cur_exp(mp);
+}
+
+@ A level of loop control disappears when |resume_iteration| has decided
+not to resume, or when an \&{exitif} construction has removed the loop text
+from the input stack.
+
+@c void mp_stop_iteration (MP mp) {
+ pointer p,q; /* the usual */
+ p=loop_type(mp->loop_ptr);
+ if ( p==progression_flag ) {
+ mp_free_node(mp, loop_list(mp->loop_ptr),progression_node_size);
+ } else if ( p==null ){
+ q=loop_list(mp->loop_ptr);
+ while ( q!=null ) {
+ p=info(q);
+ if ( p!=null ) {
+ if ( link(p)==mp_void ) { /* it's an \&{expr} parameter */
+ mp_recycle_value(mp, p); mp_free_node(mp, p,value_node_size);
+ } else {
+ mp_flush_token_list(mp, p); /* it's a \&{suffix} or \&{text} parameter */
+ }
+ }
+ p=q; q=link(q); free_avail(p);
+ }
+ } else if ( p>progression_flag ) {
+ delete_edge_ref(p);
+ }
+ p=mp->loop_ptr; mp->loop_ptr=link(p); mp_flush_token_list(mp, info(p));
+ mp_free_node(mp, p,loop_node_size);
+}
+
+@ Now that we know all about loop control, we can finish up
+the missing portion of |begin_iteration| and we'll be done.
+
+The following code is performed after the `\.=' has been scanned in
+a \&{for} construction (if |m=expr_base|) or a \&{forsuffixes} construction
+(if |m=suffix_base|).
+
+@<Scan the values to be used in the loop@>=
+loop_type(s)=null; q=loop_list_loc(s); link(q)=null; /* |link(q)=loop_list(s)| */
+do {
+ mp_get_x_next(mp);
+ if ( m!=expr_base ) {
+ mp_scan_suffix(mp);
+ } else {
+ if ( mp->cur_cmd>=colon ) if ( mp->cur_cmd<=comma )
+ goto CONTINUE;
+ mp_scan_expression(mp);
+ if ( mp->cur_cmd==step_token ) if ( q==loop_list_loc(s) ) {
+ @<Prepare for step-until construction and |break|@>;
+ }
+ mp->cur_exp=mp_stash_cur_exp(mp);
+ }
+ link(q)=mp_get_avail(mp); q=link(q);
+ info(q)=mp->cur_exp; mp->cur_type=mp_vacuous;
+CONTINUE:
+ ;
+} while (mp->cur_cmd==comma)
+
+@ @<Prepare for step-until construction and |break|@>=
+{
+ if ( mp->cur_type!=mp_known ) mp_bad_for(mp, "initial value");
+ pp=mp_get_node(mp, progression_node_size); value(pp)=mp->cur_exp;
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type!=mp_known ) mp_bad_for(mp, "step size");
+ step_size(pp)=mp->cur_exp;
+ if ( mp->cur_cmd!=until_token ) {
+ mp_missing_err(mp, "until");
+@.Missing `until'@>
+ help2("I assume you meant to say `until' after `step'.")
+ ("So I'll look for the final value and colon next.");
+ mp_back_error(mp);
+ }
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type!=mp_known ) mp_bad_for(mp, "final value");
+ final_value(pp)=mp->cur_exp; loop_list(s)=pp;
+ loop_type(s)=progression_flag;
+ break;
+}
+
+@ The last case is when we have just seen ``\&{within}'', and we need to
+parse a picture expression and prepare to iterate over it.
+
+@<Set up a picture iteration@>=
+{ mp_get_x_next(mp);
+ mp_scan_expression(mp);
+ @<Make sure the current expression is a known picture@>;
+ loop_type(s)=mp->cur_exp; mp->cur_type=mp_vacuous;
+ q=link(dummy_loc(mp->cur_exp));
+ if ( q!= null )
+ if ( is_start_or_stop(q) )
+ if ( mp_skip_1component(mp, q)==null ) q=link(q);
+ loop_list(s)=q;
+}
+
+@ @<Make sure the current expression is a known picture@>=
+if ( mp->cur_type!=mp_picture_type ) {
+ mp_disp_err(mp, null,"Improper iteration spec has been replaced by nullpicture");
+ help1("When you say `for x in p', p must be a known picture.");
+ mp_put_get_flush_error(mp, mp_get_node(mp, edge_header_size));
+ mp_init_edges(mp, mp->cur_exp); mp->cur_type=mp_picture_type;
+}
+
+@* \[35] File names.
+It's time now to fret about file names. Besides the fact that different
+operating systems treat files in different ways, we must cope with the
+fact that completely different naming conventions are used by different
+groups of people. The following programs show what is required for one
+particular operating system; similar routines for other systems are not
+difficult to devise.
+@^system dependencies@>
+
+\MP\ assumes that a file name has three parts: the name proper; its
+``extension''; and a ``file area'' where it is found in an external file
+system. The extension of an input file is assumed to be
+`\.{.mp}' unless otherwise specified; it is `\.{.log}' on the
+transcript file that records each run of \MP; it is `\.{.tfm}' on the font
+metric files that describe characters in any fonts created by \MP; it is
+`\.{.ps}' or `.{\it nnn}' for some number {\it nnn} on the \ps\ output files;
+and it is `\.{.mem}' on the mem files written by \.{INIMP} to initialize \MP.
+The file area can be arbitrary on input files, but files are usually
+output to the user's current area. If an input file cannot be
+found on the specified area, \MP\ will look for it on a special system
+area; this special area is intended for commonly used input files.
+
+Simple uses of \MP\ refer only to file names that have no explicit
+extension or area. For example, a person usually says `\.{input} \.{cmr10}'
+instead of `\.{input} \.{cmr10.new}'. Simple file
+names are best, because they make the \MP\ source files portable;
+whenever a file name consists entirely of letters and digits, it should be
+treated in the same way by all implementations of \MP. However, users
+need the ability to refer to other files in their environment, especially
+when responding to error messages concerning unopenable files; therefore
+we want to let them use the syntax that appears in their favorite
+operating system.
+
+@ \MP\ uses the same conventions that have proved to be satisfactory for
+\TeX\ and \MF. In order to isolate the system-dependent aspects of file names,
+@^system dependencies@>
+the system-independent parts of \MP\ are expressed in terms
+of three system-dependent
+procedures called |begin_name|, |more_name|, and |end_name|. In
+essence, if the user-specified characters of the file name are $c_1\ldots c_n$,
+the system-independent driver program does the operations
+$$|begin_name|;\,|more_name|(c_1);\,\ldots\,;\,|more_name|(c_n);
+\,|end_name|.$$
+These three procedures communicate with each other via global variables.
+Afterwards the file name will appear in the string pool as three strings
+called |cur_name|\penalty10000\hskip-.05em,
+|cur_area|, and |cur_ext|; the latter two are null (i.e.,
+|""|), unless they were explicitly specified by the user.
+
+Actually the situation is slightly more complicated, because \MP\ needs
+to know when the file name ends. The |more_name| routine is a function
+(with side effects) that returns |true| on the calls |more_name|$(c_1)$,
+\dots, |more_name|$(c_{n-1})$. The final call |more_name|$(c_n)$
+returns |false|; or, it returns |true| and $c_n$ is the last character
+on the current input line. In other words,
+|more_name| is supposed to return |true| unless it is sure that the
+file name has been completely scanned; and |end_name| is supposed to be able
+to finish the assembly of |cur_name|, |cur_area|, and |cur_ext| regardless of
+whether $|more_name|(c_n)$ returned |true| or |false|.
+
+@<Glob...@>=
+char * cur_name; /* name of file just scanned */
+char * cur_area; /* file area just scanned, or \.{""} */
+char * cur_ext; /* file extension just scanned, or \.{""} */
+
+@ It is easier to maintain reference counts if we assign initial values.
+
+@<Set init...@>=
+mp->cur_name=xstrdup("");
+mp->cur_area=xstrdup("");
+mp->cur_ext=xstrdup("");
+
+@ @<Dealloc variables@>=
+xfree(mp->cur_area);
+xfree(mp->cur_name);
+xfree(mp->cur_ext);
+
+@ The file names we shall deal with for illustrative purposes have the
+following structure: If the name contains `\.>' or `\.:', the file area
+consists of all characters up to and including the final such character;
+otherwise the file area is null. If the remaining file name contains
+`\..', the file extension consists of all such characters from the first
+remaining `\..' to the end, otherwise the file extension is null.
+@^system dependencies@>
+
+We can scan such file names easily by using two global variables that keep track
+of the occurrences of area and extension delimiters. Note that these variables
+cannot be of type |pool_pointer| because a string pool compaction could occur
+while scanning a file name.
+
+@<Glob...@>=
+integer area_delimiter;
+ /* most recent `\.>' or `\.:' relative to |str_start[str_ptr]| */
+integer ext_delimiter; /* the relevant `\..', if any */
+
+@ Here now is the first of the system-dependent routines for file name scanning.
+@^system dependencies@>
+
+@<Declare subroutines for parsing file names@>=
+void mp_begin_name (MP mp) {
+ xfree(mp->cur_name);
+ xfree(mp->cur_area);
+ xfree(mp->cur_ext);
+ mp->area_delimiter=-1;
+ mp->ext_delimiter=-1;
+}
+
+@ And here's the second.
+@^system dependencies@>
+
+@<Declare subroutines for parsing file names@>=
+boolean mp_more_name (MP mp, ASCII_code c) {
+ if (c==' ') {
+ return false;
+ } else {
+ if ( (c=='>')||(c==':') ) {
+ mp->area_delimiter=mp->pool_ptr;
+ mp->ext_delimiter=-1;
+ } else if ( (c=='.')&&(mp->ext_delimiter<0) ) {
+ mp->ext_delimiter=mp->pool_ptr;
+ }
+ str_room(1); append_char(c); /* contribute |c| to the current string */
+ return true;
+ }
+}
+
+@ The third.
+@^system dependencies@>
+
+@d copy_pool_segment(A,B,C) {
+ A = xmalloc(C+1,sizeof(char));
+ strncpy(A,(char *)(mp->str_pool+B),C);
+ A[C] = 0;}
+
+@<Declare subroutines for parsing file names@>=
+void mp_end_name (MP mp) {
+ pool_pointer s; /* length of area, name, and extension */
+ unsigned int len;
+ /* "my/w.mp" */
+ s = mp->str_start[mp->str_ptr];
+ if ( mp->area_delimiter<0 ) {
+ mp->cur_area=xstrdup("");
+ } else {
+ len = mp->area_delimiter-s;
+ copy_pool_segment(mp->cur_area,s,len);
+ s += len+1;
+ }
+ if ( mp->ext_delimiter<0 ) {
+ mp->cur_ext=xstrdup("");
+ len = mp->pool_ptr-s;
+ } else {
+ copy_pool_segment(mp->cur_ext,mp->ext_delimiter,(mp->pool_ptr-mp->ext_delimiter));
+ len = mp->ext_delimiter-s;
+ }
+ copy_pool_segment(mp->cur_name,s,len);
+ mp->pool_ptr=s; /* don't need this partial string */
+}
+
+@ Conversely, here is a routine that takes three strings and prints a file
+name that might have produced them. (The routine is system dependent, because
+some operating systems put the file area last instead of first.)
+@^system dependencies@>
+
+@<Basic printing...@>=
+void mp_print_file_name (MP mp, char * n, char * a, char * e) {
+ mp_print(mp, a); mp_print(mp, n); mp_print(mp, e);
+}
+
+@ Another system-dependent routine is needed to convert three internal
+\MP\ strings
+to the |name_of_file| value that is used to open files. The present code
+allows both lowercase and uppercase letters in the file name.
+@^system dependencies@>
+
+@d append_to_name(A) { c=(A);
+ if ( k<file_name_size ) {
+ mp->name_of_file[k]=xchr(c);
+ incr(k);
+ }
+}
+
+@<Declare subroutines for parsing file names@>=
+void mp_pack_file_name (MP mp, const char *n, const char *a, const char *e) {
+ integer k; /* number of positions filled in |name_of_file| */
+ ASCII_code c; /* character being packed */
+ const char *j; /* a character index */
+ k=0;
+ assert(n);
+ if (a!=NULL) {
+ for (j=a;*j;j++) { append_to_name(*j); }
+ }
+ for (j=n;*j;j++) { append_to_name(*j); }
+ if (e!=NULL) {
+ for (j=e;*j;j++) { append_to_name(*j); }
+ }
+ mp->name_of_file[k]=0;
+ mp->name_length=k;
+}
+
+@ @<Internal library declarations@>=
+void mp_pack_file_name (MP mp, const char *n, const char *a, const char *e) ;
+
+@ A messier routine is also needed, since mem file names must be scanned
+before \MP's string mechanism has been initialized. We shall use the
+global variable |MP_mem_default| to supply the text for default system areas
+and extensions related to mem files.
+@^system dependencies@>
+
+@d mem_default_length 9 /* length of the |MP_mem_default| string */
+@d mem_ext_length 4 /* length of its `\.{.mem}' part */
+@d mem_extension ".mem" /* the extension, as a \.{WEB} constant */
+
+@<Glob...@>=
+char *MP_mem_default;
+
+@ @<Option variables@>=
+char *mem_name; /* for commandline */
+
+@ @<Allocate or initialize ...@>=
+mp->MP_mem_default = xstrdup("plain.mem");
+mp->mem_name = xstrdup(opt->mem_name);
+@.plain@>
+@^system dependencies@>
+
+@ @<Dealloc variables@>=
+xfree(mp->MP_mem_default);
+xfree(mp->mem_name);
+
+@ @<Check the ``constant'' values for consistency@>=
+if ( mem_default_length>file_name_size ) mp->bad=20;
+
+@ Here is the messy routine that was just mentioned. It sets |name_of_file|
+from the first |n| characters of |MP_mem_default|, followed by
+|buffer[a..b-1]|, followed by the last |mem_ext_length| characters of
+|MP_mem_default|.
+
+We dare not give error messages here, since \MP\ calls this routine before
+the |error| routine is ready to roll. Instead, we simply drop excess characters,
+since the error will be detected in another way when a strange file name
+isn't found.
+@^system dependencies@>
+
+@c void mp_pack_buffered_name (MP mp,small_number n, integer a,
+ integer b) {
+ integer k; /* number of positions filled in |name_of_file| */
+ ASCII_code c; /* character being packed */
+ integer j; /* index into |buffer| or |MP_mem_default| */
+ if ( n+b-a+1+mem_ext_length>file_name_size )
+ b=a+file_name_size-n-1-mem_ext_length;
+ k=0;
+ for (j=0;j<n;j++) {
+ append_to_name(xord((int)mp->MP_mem_default[j]));
+ }
+ for (j=a;j<b;j++) {
+ append_to_name(mp->buffer[j]);
+ }
+ for (j=mem_default_length-mem_ext_length;
+ j<mem_default_length;j++) {
+ append_to_name(xord((int)mp->MP_mem_default[j]));
+ }
+ mp->name_of_file[k]=0;
+ mp->name_length=k;
+}
+
+@ Here is the only place we use |pack_buffered_name|. This part of the program
+becomes active when a ``virgin'' \MP\ is trying to get going, just after
+the preliminary initialization, or when the user is substituting another
+mem file by typing `\.\&' after the initial `\.{**}' prompt. The buffer
+contains the first line of input in |buffer[loc..(last-1)]|, where
+|loc<last| and |buffer[loc]<>" "|.
+
+@<Declarations@>=
+boolean mp_open_mem_file (MP mp) ;
+
+@ @c
+boolean mp_open_mem_file (MP mp) {
+ int j; /* the first space after the file name */
+ if (mp->mem_name!=NULL) {
+ mp->mem_file = (mp->open_file)(mp,mp->mem_name, "r", mp_filetype_memfile);
+ if ( mp->mem_file ) return true;
+ }
+ j=loc;
+ if ( mp->buffer[loc]=='&' ) {
+ incr(loc); j=loc; mp->buffer[mp->last]=' ';
+ while ( mp->buffer[j]!=' ' ) incr(j);
+ mp_pack_buffered_name(mp, 0,loc,j); /* try first without the system file area */
+ if ( mp_w_open_in(mp, &mp->mem_file) ) goto FOUND;
+ wake_up_terminal;
+ wterm_ln("Sorry, I can\'t find that mem file; will try PLAIN.");
+@.Sorry, I can't find...@>
+ update_terminal;
+ }
+ /* now pull out all the stops: try for the system \.{plain} file */
+ mp_pack_buffered_name(mp, mem_default_length-mem_ext_length,0,0);
+ if ( ! mp_w_open_in(mp, &mp->mem_file) ) {
+ wake_up_terminal;
+ wterm_ln("I can\'t find the PLAIN mem file!\n");
+@.I can't find PLAIN...@>
+@.plain@>
+ return false;
+ }
+FOUND:
+ loc=j; return true;
+}
+
+@ Operating systems often make it possible to determine the exact name (and
+possible version number) of a file that has been opened. The following routine,
+which simply makes a \MP\ string from the value of |name_of_file|, should
+ideally be changed to deduce the full name of file~|f|, which is the file
+most recently opened, if it is possible to do this.
+@^system dependencies@>
+
+@<Declarations@>=
+#define mp_a_make_name_string(A,B) mp_make_name_string(A)
+#define mp_b_make_name_string(A,B) mp_make_name_string(A)
+#define mp_w_make_name_string(A,B) mp_make_name_string(A)
+
+@ @c
+str_number mp_make_name_string (MP mp) {
+ int k; /* index into |name_of_file| */
+ str_room(mp->name_length);
+ for (k=0;k<mp->name_length;k++) {
+ append_char(xord((int)mp->name_of_file[k]));
+ }
+ return mp_make_string(mp);
+}
+
+@ Now let's consider the ``driver''
+routines by which \MP\ deals with file names
+in a system-independent manner. First comes a procedure that looks for a
+file name in the input by taking the information from the input buffer.
+(We can't use |get_next|, because the conversion to tokens would
+destroy necessary information.)
+
+This procedure doesn't allow semicolons or percent signs to be part of
+file names, because of other conventions of \MP.
+{\sl The {\logos METAFONT\/}book} doesn't
+use semicolons or percents immediately after file names, but some users
+no doubt will find it natural to do so; therefore system-dependent
+changes to allow such characters in file names should probably
+be made with reluctance, and only when an entire file name that
+includes special characters is ``quoted'' somehow.
+@^system dependencies@>
+
+@c void mp_scan_file_name (MP mp) {
+ mp_begin_name(mp);
+ while ( mp->buffer[loc]==' ' ) incr(loc);
+ while (1) {
+ if ( (mp->buffer[loc]==';')||(mp->buffer[loc]=='%') ) break;
+ if ( ! mp_more_name(mp, mp->buffer[loc]) ) break;
+ incr(loc);
+ }
+ mp_end_name(mp);
+}
+
+@ Here is another version that takes its input from a string.
+
+@<Declare subroutines for parsing file names@>=
+void mp_str_scan_file (MP mp, str_number s) {
+ pool_pointer p,q; /* current position and stopping point */
+ mp_begin_name(mp);
+ p=mp->str_start[s]; q=str_stop(s);
+ while ( p<q ){
+ if ( ! mp_more_name(mp, mp->str_pool[p]) ) break;
+ incr(p);
+ }
+ mp_end_name(mp);
+}
+
+@ And one that reads from a |char*|.
+
+@<Declare subroutines for parsing file names@>=
+void mp_ptr_scan_file (MP mp, char *s) {
+ char *p, *q; /* current position and stopping point */
+ mp_begin_name(mp);
+ p=s; q=p+strlen(s);
+ while ( p<q ){
+ if ( ! mp_more_name(mp, *p)) break;
+ p++;
+ }
+ mp_end_name(mp);
+}
+
+
+@ The global variable |job_name| contains the file name that was first
+\&{input} by the user. This name is extended by `\.{.log}' and `\.{ps}' and
+`\.{.mem}' and `\.{.tfm}' in order to make the names of \MP's output files.
+
+@<Glob...@>=
+boolean log_opened; /* has the transcript file been opened? */
+char *log_name; /* full name of the log file */
+
+@ @<Option variables@>=
+char *job_name; /* principal file name */
+
+@ Initially |job_name=NULL|; it becomes nonzero as soon as the true name is known.
+We have |job_name=NULL| if and only if the `\.{log}' file has not been opened,
+except of course for a short time just after |job_name| has become nonzero.
+
+@<Allocate or ...@>=
+mp->job_name=mp_xstrdup(mp, opt->job_name);
+mp->log_opened=false;
+
+@ @<Dealloc variables@>=
+xfree(mp->job_name);
+
+@ Here is a routine that manufactures the output file names, assuming that
+|job_name<>0|. It ignores and changes the current settings of |cur_area|
+and |cur_ext|.
+
+@d pack_cur_name mp_pack_file_name(mp, mp->cur_name,mp->cur_area,mp->cur_ext)
+
+@<Declarations@>=
+void mp_pack_job_name (MP mp, const char *s) ;
+
+@ @c
+void mp_pack_job_name (MP mp, const char *s) { /* |s = ".log"|, |".mem"|, |".ps"|, or .\\{nnn} */
+ xfree(mp->cur_name); mp->cur_name=xstrdup(mp->job_name);
+ xfree(mp->cur_area); mp->cur_area=xstrdup("");
+ xfree(mp->cur_ext); mp->cur_ext=xstrdup(s);
+ pack_cur_name;
+}
+
+@ If some trouble arises when \MP\ tries to open a file, the following
+routine calls upon the user to supply another file name. Parameter~|s|
+is used in the error message to identify the type of file; parameter~|e|
+is the default extension if none is given. Upon exit from the routine,
+variables |cur_name|, |cur_area|, |cur_ext|, and |name_of_file| are
+ready for another attempt at file opening.
+
+@<Declarations@>=
+void mp_prompt_file_name (MP mp, const char * s, const char * e) ;
+
+@ @c void mp_prompt_file_name (MP mp, const char * s, const char * e) {
+ size_t k; /* index into |buffer| */
+ char * saved_cur_name;
+ if ( mp->interaction==mp_scroll_mode )
+ wake_up_terminal;
+ if (strcmp(s,"input file name")==0) {
+ print_err("I can\'t find file `");
+@.I can't find file x@>
+ } else {
+ print_err("I can\'t write on file `");
+ }
+@.I can't write on file x@>
+ mp_print_file_name(mp, mp->cur_name,mp->cur_area,mp->cur_ext);
+ mp_print(mp, "'.");
+ if (strcmp(e,"")==0)
+ mp_show_context(mp);
+ mp_print_nl(mp, "Please type another "); mp_print(mp, s);
+@.Please type...@>
+ if ( mp->interaction<mp_scroll_mode )
+ mp_fatal_error(mp, "*** (job aborted, file error in nonstop mode)");
+@.job aborted, file error...@>
+ saved_cur_name = xstrdup(mp->cur_name);
+ clear_terminal; prompt_input(": "); @<Scan file name in the buffer@>;
+ if (strcmp(mp->cur_ext,"")==0)
+ mp->cur_ext=xstrdup(e);
+ if (strlen(mp->cur_name)==0) {
+ mp->cur_name=saved_cur_name;
+ } else {
+ xfree(saved_cur_name);
+ }
+ pack_cur_name;
+}
+
+@ @<Scan file name in the buffer@>=
+{
+ mp_begin_name(mp); k=mp->first;
+ while ( (mp->buffer[k]==' ')&&(k<mp->last) ) incr(k);
+ while (1) {
+ if ( k==mp->last ) break;
+ if ( ! mp_more_name(mp, mp->buffer[k]) ) break;
+ incr(k);
+ }
+ mp_end_name(mp);
+}
+
+@ The |open_log_file| routine is used to open the transcript file and to help
+it catch up to what has previously been printed on the terminal.
+
+@c void mp_open_log_file (MP mp) {
+ int old_setting; /* previous |selector| setting */
+ int k; /* index into |months| and |buffer| */
+ int l; /* end of first input line */
+ integer m; /* the current month */
+ const char *months="JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
+ /* abbreviations of month names */
+ old_setting=mp->selector;
+ if ( mp->job_name==NULL ) {
+ mp->job_name=xstrdup("mpout");
+ }
+ mp_pack_job_name(mp,".log");
+ while ( ! mp_a_open_out(mp, &mp->log_file, mp_filetype_log) ) {
+ @<Try to get a different log file name@>;
+ }
+ mp->log_name=xstrdup(mp->name_of_file);
+ mp->selector=log_only; mp->log_opened=true;
+ @<Print the banner line, including the date and time@>;
+ mp->input_stack[mp->input_ptr]=mp->cur_input;
+ /* make sure bottom level is in memory */
+@.**@>
+ if (!mp->noninteractive) {
+ mp_print_nl(mp, "**");
+ l=mp->input_stack[0].limit_field-1; /* last position of first line */
+ for (k=0;k<=l;k++) mp_print_str(mp, mp->buffer[k]);
+ mp_print_ln(mp); /* now the transcript file contains the first line of input */
+ }
+ mp->selector=old_setting+2; /* |log_only| or |term_and_log| */
+}
+
+@ @<Dealloc variables@>=
+xfree(mp->log_name);
+
+@ Sometimes |open_log_file| is called at awkward moments when \MP\ is
+unable to print error messages or even to |show_context|.
+The |prompt_file_name| routine can result in a |fatal_error|, but the |error|
+routine will not be invoked because |log_opened| will be false.
+
+The normal idea of |mp_batch_mode| is that nothing at all should be written
+on the terminal. However, in the unusual case that
+no log file could be opened, we make an exception and allow
+an explanatory message to be seen.
+
+Incidentally, the program always refers to the log file as a `\.{transcript
+file}', because some systems cannot use the extension `\.{.log}' for
+this file.
+
+@<Try to get a different log file name@>=
+{
+ mp->selector=term_only;
+ mp_prompt_file_name(mp, "transcript file name",".log");
+}
+
+@ @<Print the banner...@>=
+{
+ wlog(banner);
+ mp_print(mp, mp->mem_ident); mp_print(mp, " ");
+ mp_print_int(mp, mp_round_unscaled(mp, mp->internal[mp_day]));
+ mp_print_char(mp, ' ');
+ m=mp_round_unscaled(mp, mp->internal[mp_month]);
+ for (k=3*m-3;k<3*m;k++) { wlog_chr(months[k]); }
+ mp_print_char(mp, ' ');
+ mp_print_int(mp, mp_round_unscaled(mp, mp->internal[mp_year]));
+ mp_print_char(mp, ' ');
+ m=mp_round_unscaled(mp, mp->internal[mp_time]);
+ mp_print_dd(mp, m / 60); mp_print_char(mp, ':'); mp_print_dd(mp, m % 60);
+}
+
+@ The |try_extension| function tries to open an input file determined by
+|cur_name|, |cur_area|, and the argument |ext|. It returns |false| if it
+can't find the file in |cur_area| or the appropriate system area.
+
+@c boolean mp_try_extension (MP mp, const char *ext) {
+ mp_pack_file_name(mp, mp->cur_name,mp->cur_area, ext);
+ in_name=xstrdup(mp->cur_name);
+ in_area=xstrdup(mp->cur_area);
+ if ( mp_a_open_in(mp, &cur_file, mp_filetype_program) ) {
+ return true;
+ } else {
+ mp_pack_file_name(mp, mp->cur_name,NULL,ext);
+ return mp_a_open_in(mp, &cur_file, mp_filetype_program);
+ }
+}
+
+@ Let's turn now to the procedure that is used to initiate file reading
+when an `\.{input}' command is being processed.
+
+@c void mp_start_input (MP mp) { /* \MP\ will \.{input} something */
+ char *fname = NULL;
+ @<Put the desired file name in |(cur_name,cur_ext,cur_area)|@>;
+ while (1) {
+ mp_begin_file_reading(mp); /* set up |cur_file| and new level of input */
+ if ( strlen(mp->cur_ext)==0 ) {
+ if ( mp_try_extension(mp, ".mp") ) break;
+ else if ( mp_try_extension(mp, "") ) break;
+ else if ( mp_try_extension(mp, ".mf") ) break;
+ /* |else do_nothing; | */
+ } else if ( mp_try_extension(mp, mp->cur_ext) ) {
+ break;
+ }
+ mp_end_file_reading(mp); /* remove the level that didn't work */
+ mp_prompt_file_name(mp, "input file name","");
+ }
+ name=mp_a_make_name_string(mp, cur_file);
+ fname = xstrdup(mp->name_of_file);
+ if ( mp->job_name==NULL ) {
+ mp->job_name=xstrdup(mp->cur_name);
+ mp_open_log_file(mp);
+ } /* |open_log_file| doesn't |show_context|, so |limit|
+ and |loc| needn't be set to meaningful values yet */
+ if ( ((int)mp->term_offset+(int)strlen(fname)) > (mp->max_print_line-2)) mp_print_ln(mp);
+ else if ( (mp->term_offset>0)||(mp->file_offset>0) ) mp_print_char(mp, ' ');
+ mp_print_char(mp, '('); incr(mp->open_parens); mp_print(mp, fname);
+ xfree(fname);
+ update_terminal;
+ @<Flush |name| and replace it with |cur_name| if it won't be needed@>;
+ @<Read the first line of the new file@>;
+}
+
+@ This code should be omitted if |a_make_name_string| returns something other
+than just a copy of its argument and the full file name is needed for opening
+\.{MPX} files or implementing the switch-to-editor option.
+@^system dependencies@>
+
+@<Flush |name| and replace it with |cur_name| if it won't be needed@>=
+mp_flush_string(mp, name); name=rts(mp->cur_name); xfree(mp->cur_name)
+
+@ If the file is empty, it is considered to contain a single blank line,
+so there is no need to test the return value.
+
+@<Read the first line...@>=
+{
+ line=1;
+ (void)mp_input_ln(mp, cur_file );
+ mp_firm_up_the_line(mp);
+ mp->buffer[limit]='%'; mp->first=limit+1; loc=start;
+}
+
+@ @<Put the desired file name in |(cur_name,cur_ext,cur_area)|@>=
+while ( token_state &&(loc==null) ) mp_end_token_list(mp);
+if ( token_state ) {
+ print_err("File names can't appear within macros");
+@.File names can't...@>
+ help3("Sorry...I've converted what follows to tokens,")
+ ("possibly garbaging the name you gave.")
+ ("Please delete the tokens and insert the name again.");
+ mp_error(mp);
+}
+if ( file_state ) {
+ mp_scan_file_name(mp);
+} else {
+ xfree(mp->cur_name); mp->cur_name=xstrdup("");
+ xfree(mp->cur_ext); mp->cur_ext =xstrdup("");
+ xfree(mp->cur_area); mp->cur_area=xstrdup("");
+}
+
+@ The following simple routine starts reading the \.{MPX} file associated
+with the current input file.
+
+@c void mp_start_mpx_input (MP mp) {
+ char *origname = NULL; /* a copy of nameoffile */
+ mp_pack_file_name(mp, in_name, in_area, ".mpx");
+ @<Try to make sure |name_of_file| refers to a valid \.{MPX} file and
+ |goto not_found| if there is a problem@>;
+ mp_begin_file_reading(mp);
+ if ( ! mp_a_open_in(mp, &cur_file, mp_filetype_program) ) {
+ mp_end_file_reading(mp);
+ goto NOT_FOUND;
+ }
+ name=mp_a_make_name_string(mp, cur_file);
+ mp->mpx_name[index]=name; add_str_ref(name);
+ @<Read the first line of the new file@>;
+ return;
+NOT_FOUND:
+ @<Explain that the \.{MPX} file can't be read and |succumb|@>;
+ xfree(origname);
+}
+
+@ This should ideally be changed to do whatever is necessary to create the
+\.{MPX} file given by |name_of_file| if it does not exist or if it is out
+of date. This requires invoking \.{MPtoTeX} on the |origname| and passing
+the results through \TeX\ and \.{DVItoMP}. (It is possible to use a
+completely different typesetting program if suitable postprocessor is
+available to perform the function of \.{DVItoMP}.)
+@^system dependencies@>
+
+@ @<Exported types@>=
+typedef int (*mp_run_make_mpx_command)(MP mp, char *origname, char *mtxname);
+
+@ @<Option variables@>=
+mp_run_make_mpx_command run_make_mpx;
+
+@ @<Allocate or initialize ...@>=
+set_callback_option(run_make_mpx);
+
+@ @<Internal library declarations@>=
+int mp_run_make_mpx (MP mp, char *origname, char *mtxname);
+
+@ The default does nothing.
+@c
+int mp_run_make_mpx (MP mp, char *origname, char *mtxname) {
+ (void)mp;
+ (void)origname;
+ (void)mtxname;
+ return false;
+}
+
+@ @<Try to make sure |name_of_file| refers to a valid \.{MPX} file and
+ |goto not_found| if there is a problem@>=
+origname = mp_xstrdup(mp,mp->name_of_file);
+*(origname+strlen(origname)-1)=0; /* drop the x */
+if (!(mp->run_make_mpx)(mp, origname, mp->name_of_file))
+ goto NOT_FOUND
+
+@ @<Explain that the \.{MPX} file can't be read and |succumb|@>=
+if ( mp->interaction==mp_error_stop_mode ) wake_up_terminal;
+mp_print_nl(mp, ">> ");
+mp_print(mp, origname);
+mp_print_nl(mp, ">> ");
+mp_print(mp, mp->name_of_file);
+mp_print_nl(mp, "! Unable to make mpx file");
+help4("The two files given above are one of your source files")
+ ("and an auxiliary file I need to read to find out what your")
+ ("btex..etex blocks mean. If you don't know why I had trouble,")
+ ("try running it manually through MPtoTeX, TeX, and DVItoMP");
+succumb;
+
+@ The last file-opening commands are for files accessed via the \&{readfrom}
+@:read_from_}{\&{readfrom} primitive@>
+operator and the \&{write} command. Such files are stored in separate arrays.
+@:write_}{\&{write} primitive@>
+
+@<Types in the outer block@>=
+typedef unsigned int readf_index; /* |0..max_read_files| */
+typedef unsigned int write_index; /* |0..max_write_files| */
+
+@ @<Glob...@>=
+readf_index max_read_files; /* maximum number of simultaneously open \&{readfrom} files */
+void ** rd_file; /* \&{readfrom} files */
+char ** rd_fname; /* corresponding file name or 0 if file not open */
+readf_index read_files; /* number of valid entries in the above arrays */
+write_index max_write_files; /* maximum number of simultaneously open \&{write} */
+void ** wr_file; /* \&{write} files */
+char ** wr_fname; /* corresponding file name or 0 if file not open */
+write_index write_files; /* number of valid entries in the above arrays */
+
+@ @<Allocate or initialize ...@>=
+mp->max_read_files=8;
+mp->rd_file = xmalloc((mp->max_read_files+1),sizeof(void *));
+mp->rd_fname = xmalloc((mp->max_read_files+1),sizeof(char *));
+memset(mp->rd_fname, 0, sizeof(char *)*(mp->max_read_files+1));
+mp->read_files=0;
+mp->max_write_files=8;
+mp->wr_file = xmalloc((mp->max_write_files+1),sizeof(void *));
+mp->wr_fname = xmalloc((mp->max_write_files+1),sizeof(char *));
+memset(mp->wr_fname, 0, sizeof(char *)*(mp->max_write_files+1));
+mp->write_files=0;
+
+
+@ This routine starts reading the file named by string~|s| without setting
+|loc|, |limit|, or |name|. It returns |false| if the file is empty or cannot
+be opened. Otherwise it updates |rd_file[n]| and |rd_fname[n]|.
+
+@c boolean mp_start_read_input (MP mp,char *s, readf_index n) {
+ mp_ptr_scan_file(mp, s);
+ pack_cur_name;
+ mp_begin_file_reading(mp);
+ if ( ! mp_a_open_in(mp, &mp->rd_file[n], (mp_filetype_text+n)) )
+ goto NOT_FOUND;
+ if ( ! mp_input_ln(mp, mp->rd_file[n] ) ) {
+ (mp->close_file)(mp,mp->rd_file[n]);
+ goto NOT_FOUND;
+ }
+ mp->rd_fname[n]=xstrdup(mp->name_of_file);
+ return true;
+NOT_FOUND:
+ mp_end_file_reading(mp);
+ return false;
+}
+
+@ Open |wr_file[n]| using file name~|s| and update |wr_fname[n]|.
+
+@<Declarations@>=
+void mp_open_write_file (MP mp, char *s, readf_index n) ;
+
+@ @c void mp_open_write_file (MP mp,char *s, readf_index n) {
+ mp_ptr_scan_file(mp, s);
+ pack_cur_name;
+ while ( ! mp_a_open_out(mp, &mp->wr_file[n], (mp_filetype_text+n)) )
+ mp_prompt_file_name(mp, "file name for write output","");
+ mp->wr_fname[n]=xstrdup(mp->name_of_file);
+}
+
+
+@* \[36] Introduction to the parsing routines.
+We come now to the central nervous system that sparks many of \MP's activities.
+By evaluating expressions, from their primary constituents to ever larger
+subexpressions, \MP\ builds the structures that ultimately define complete
+pictures or fonts of type.
+
+Four mutually recursive subroutines are involved in this process: We call them
+$$\hbox{|scan_primary|, |scan_secondary|, |scan_tertiary|,
+and |scan_expression|.}$$
+@^recursion@>
+Each of them is parameterless and begins with the first token to be scanned
+already represented in |cur_cmd|, |cur_mod|, and |cur_sym|. After execution,
+the value of the primary or secondary or tertiary or expression that was
+found will appear in the global variables |cur_type| and |cur_exp|. The
+token following the expression will be represented in |cur_cmd|, |cur_mod|,
+and |cur_sym|.
+
+Technically speaking, the parsing algorithms are ``LL(1),'' more or less;
+backup mechanisms have been added in order to provide reasonable error
+recovery.
+
+@<Glob...@>=
+small_number cur_type; /* the type of the expression just found */
+integer cur_exp; /* the value of the expression just found */
+
+@ @<Set init...@>=
+mp->cur_exp=0;
+
+@ Many different kinds of expressions are possible, so it is wise to have
+precise descriptions of what |cur_type| and |cur_exp| mean in all cases:
+
+\smallskip\hang
+|cur_type=mp_vacuous| means that this expression didn't turn out to have a
+value at all, because it arose from a \&{begingroup}$\,\ldots\,$\&{endgroup}
+construction in which there was no expression before the \&{endgroup}.
+In this case |cur_exp| has some irrelevant value.
+
+\smallskip\hang
+|cur_type=mp_boolean_type| means that |cur_exp| is either |true_code|
+or |false_code|.
+
+\smallskip\hang
+|cur_type=mp_unknown_boolean| means that |cur_exp| points to a capsule
+node that is in
+a ring of equivalent booleans whose value has not yet been defined.
+
+\smallskip\hang
+|cur_type=mp_string_type| means that |cur_exp| is a string number (i.e., an
+integer in the range |0<=cur_exp<str_ptr|). That string's reference count
+includes this particular reference.
+
+\smallskip\hang
+|cur_type=mp_unknown_string| means that |cur_exp| points to a capsule
+node that is in
+a ring of equivalent strings whose value has not yet been defined.
+
+\smallskip\hang
+|cur_type=mp_pen_type| means that |cur_exp| points to a node in a pen. Nobody
+else points to any of the nodes in this pen. The pen may be polygonal or
+elliptical.
+
+\smallskip\hang
+|cur_type=mp_unknown_pen| means that |cur_exp| points to a capsule
+node that is in
+a ring of equivalent pens whose value has not yet been defined.
+
+\smallskip\hang
+|cur_type=mp_path_type| means that |cur_exp| points to a the first node of
+a path; nobody else points to this particular path. The control points of
+the path will have been chosen.
+
+\smallskip\hang
+|cur_type=mp_unknown_path| means that |cur_exp| points to a capsule
+node that is in
+a ring of equivalent paths whose value has not yet been defined.
+
+\smallskip\hang
+|cur_type=mp_picture_type| means that |cur_exp| points to an edge header node.
+There may be other pointers to this particular set of edges. The header node
+contains a reference count that includes this particular reference.
+
+\smallskip\hang
+|cur_type=mp_unknown_picture| means that |cur_exp| points to a capsule
+node that is in
+a ring of equivalent pictures whose value has not yet been defined.
+
+\smallskip\hang
+|cur_type=mp_transform_type| means that |cur_exp| points to a |mp_transform_type|
+capsule node. The |value| part of this capsule
+points to a transform node that contains six numeric values,
+each of which is |independent|, |dependent|, |mp_proto_dependent|, or |known|.
+
+\smallskip\hang
+|cur_type=mp_color_type| means that |cur_exp| points to a |color_type|
+capsule node. The |value| part of this capsule
+points to a color node that contains three numeric values,
+each of which is |independent|, |dependent|, |mp_proto_dependent|, or |known|.
+
+\smallskip\hang
+|cur_type=mp_cmykcolor_type| means that |cur_exp| points to a |mp_cmykcolor_type|
+capsule node. The |value| part of this capsule
+points to a color node that contains four numeric values,
+each of which is |independent|, |dependent|, |mp_proto_dependent|, or |known|.
+
+\smallskip\hang
+|cur_type=mp_pair_type| means that |cur_exp| points to a capsule
+node whose type is |mp_pair_type|. The |value| part of this capsule
+points to a pair node that contains two numeric values,
+each of which is |independent|, |dependent|, |mp_proto_dependent|, or |known|.
+
+\smallskip\hang
+|cur_type=mp_known| means that |cur_exp| is a |scaled| value.
+
+\smallskip\hang
+|cur_type=mp_dependent| means that |cur_exp| points to a capsule node whose type
+is |dependent|. The |dep_list| field in this capsule points to the associated
+dependency list.
+
+\smallskip\hang
+|cur_type=mp_proto_dependent| means that |cur_exp| points to a |mp_proto_dependent|
+capsule node. The |dep_list| field in this capsule
+points to the associated dependency list.
+
+\smallskip\hang
+|cur_type=independent| means that |cur_exp| points to a capsule node
+whose type is |independent|. This somewhat unusual case can arise, for
+example, in the expression
+`$x+\&{begingroup}\penalty0\,\&{string}\,x; 0\,\&{endgroup}$'.
+
+\smallskip\hang
+|cur_type=mp_token_list| means that |cur_exp| points to a linked list of
+tokens.
+
+\smallskip\noindent
+The possible settings of |cur_type| have been listed here in increasing
+numerical order. Notice that |cur_type| will never be |mp_numeric_type| or
+|suffixed_macro| or |mp_unsuffixed_macro|, although variables of those types
+are allowed. Conversely, \MP\ has no variables of type |mp_vacuous| or
+|token_list|.
+
+@ Capsules are two-word nodes that have a similar meaning
+to |cur_type| and |cur_exp|. Such nodes have |name_type=capsule|,
+and their |type| field is one of the possibilities for |cur_type| listed above.
+Also |link<=void| in capsules that aren't part of a token list.
+
+The |value| field of a capsule is, in most cases, the value that
+corresponds to its |type|, as |cur_exp| corresponds to |cur_type|.
+However, when |cur_exp| would point to a capsule,
+no extra layer of indirection is present; the |value|
+field is what would have been called |value(cur_exp)| if it had not been
+encapsulated. Furthermore, if the type is |dependent| or
+|mp_proto_dependent|, the |value| field of a capsule is replaced by
+|dep_list| and |prev_dep| fields, since dependency lists in capsules are
+always part of the general |dep_list| structure.
+
+The |get_x_next| routine is careful not to change the values of |cur_type|
+and |cur_exp| when it gets an expanded token. However, |get_x_next| might
+call a macro, which might parse an expression, which might execute lots of
+commands in a group; hence it's possible that |cur_type| might change
+from, say, |mp_unknown_boolean| to |mp_boolean_type|, or from |dependent| to
+|known| or |independent|, during the time |get_x_next| is called. The
+programs below are careful to stash sensitive intermediate results in
+capsules, so that \MP's generality doesn't cause trouble.
+
+Here's a procedure that illustrates these conventions. It takes
+the contents of $(|cur_type|\kern-.3pt,|cur_exp|\kern-.3pt)$
+and stashes them away in a
+capsule. It is not used when |cur_type=mp_token_list|.
+After the operation, |cur_type=mp_vacuous|; hence there is no need to
+copy path lists or to update reference counts, etc.
+
+The special link |mp_void| is put on the capsule returned by
+|stash_cur_exp|, because this procedure is used to store macro parameters
+that must be easily distinguishable from token lists.
+
+@<Declare the stashing/unstashing routines@>=
+pointer mp_stash_cur_exp (MP mp) {
+ pointer p; /* the capsule that will be returned */
+ switch (mp->cur_type) {
+ case unknown_types:
+ case mp_transform_type:
+ case mp_color_type:
+ case mp_pair_type:
+ case mp_dependent:
+ case mp_proto_dependent:
+ case mp_independent:
+ case mp_cmykcolor_type:
+ p=mp->cur_exp;
+ break;
+ default:
+ p=mp_get_node(mp, value_node_size); name_type(p)=mp_capsule;
+ type(p)=mp->cur_type; value(p)=mp->cur_exp;
+ break;
+ }
+ mp->cur_type=mp_vacuous; link(p)=mp_void;
+ return p;
+}
+
+@ The inverse of |stash_cur_exp| is the following procedure, which
+deletes an unnecessary capsule and puts its contents into |cur_type|
+and |cur_exp|.
+
+The program steps of \MP\ can be divided into two categories: those in
+which |cur_type| and |cur_exp| are ``alive'' and those in which they are
+``dead,'' in the sense that |cur_type| and |cur_exp| contain relevant
+information or not. It's important not to ignore them when they're alive,
+and it's important not to pay attention to them when they're dead.
+
+There's also an intermediate category: If |cur_type=mp_vacuous|, then
+|cur_exp| is irrelevant, hence we can proceed without caring if |cur_type|
+and |cur_exp| are alive or dead. In such cases we say that |cur_type|
+and |cur_exp| are {\sl dormant}. It is permissible to call |get_x_next|
+only when they are alive or dormant.
+
+The \\{stash} procedure above assumes that |cur_type| and |cur_exp|
+are alive or dormant. The \\{unstash} procedure assumes that they are
+dead or dormant; it resuscitates them.
+
+@<Declare the stashing/unstashing...@>=
+void mp_unstash_cur_exp (MP mp,pointer p) ;
+
+@ @c
+void mp_unstash_cur_exp (MP mp,pointer p) {
+ mp->cur_type=type(p);
+ switch (mp->cur_type) {
+ case unknown_types:
+ case mp_transform_type:
+ case mp_color_type:
+ case mp_pair_type:
+ case mp_dependent:
+ case mp_proto_dependent:
+ case mp_independent:
+ case mp_cmykcolor_type:
+ mp->cur_exp=p;
+ break;
+ default:
+ mp->cur_exp=value(p);
+ mp_free_node(mp, p,value_node_size);
+ break;
+ }
+}
+
+@ The following procedure prints the values of expressions in an
+abbreviated format. If its first parameter |p| is null, the value of
+|(cur_type,cur_exp)| is displayed; otherwise |p| should be a capsule
+containing the desired value. The second parameter controls the amount of
+output. If it is~0, dependency lists will be abbreviated to
+`\.{linearform}' unless they consist of a single term. If it is greater
+than~1, complicated structures (pens, pictures, and paths) will be displayed
+in full.
+@.linearform@>
+
+@<Declare subroutines for printing expressions@>=
+@<Declare the procedure called |print_dp|@>
+@<Declare the stashing/unstashing routines@>
+void mp_print_exp (MP mp,pointer p, small_number verbosity) {
+ boolean restore_cur_exp; /* should |cur_exp| be restored? */
+ small_number t; /* the type of the expression */
+ pointer q; /* a big node being displayed */
+ integer v=0; /* the value of the expression */
+ if ( p!=null ) {
+ restore_cur_exp=false;
+ } else {
+ p=mp_stash_cur_exp(mp); restore_cur_exp=true;
+ }
+ t=type(p);
+ if ( t<mp_dependent ) v=value(p); else if ( t<mp_independent ) v=dep_list(p);
+ @<Print an abbreviated value of |v| with format depending on |t|@>;
+ if ( restore_cur_exp ) mp_unstash_cur_exp(mp, p);
+}
+
+@ @<Print an abbreviated value of |v| with format depending on |t|@>=
+switch (t) {
+case mp_vacuous:mp_print(mp, "mp_vacuous"); break;
+case mp_boolean_type:
+ if ( v==true_code ) mp_print(mp, "true"); else mp_print(mp, "false");
+ break;
+case unknown_types: case mp_numeric_type:
+ @<Display a variable that's been declared but not defined@>;
+ break;
+case mp_string_type:
+ mp_print_char(mp, '"'); mp_print_str(mp, v); mp_print_char(mp, '"');
+ break;
+case mp_pen_type: case mp_path_type: case mp_picture_type:
+ @<Display a complex type@>;
+ break;
+case mp_transform_type: case mp_color_type: case mp_pair_type: case mp_cmykcolor_type:
+ if ( v==null ) mp_print_type(mp, t);
+ else @<Display a big node@>;
+ break;
+case mp_known:mp_print_scaled(mp, v); break;
+case mp_dependent: case mp_proto_dependent:
+ mp_print_dp(mp, t,v,verbosity);
+ break;
+case mp_independent:mp_print_variable_name(mp, p); break;
+default: mp_confusion(mp, "exp"); break;
+@:this can't happen exp}{\quad exp@>
+}
+
+@ @<Display a big node@>=
+{
+ mp_print_char(mp, '('); q=v+mp->big_node_size[t];
+ do {
+ if ( type(v)==mp_known ) mp_print_scaled(mp, value(v));
+ else if ( type(v)==mp_independent ) mp_print_variable_name(mp, v);
+ else mp_print_dp(mp, type(v),dep_list(v),verbosity);
+ v=v+2;
+ if ( v!=q ) mp_print_char(mp, ',');
+ } while (v!=q);
+ mp_print_char(mp, ')');
+}
+
+@ Values of type \&{picture}, \&{path}, and \&{pen} are displayed verbosely
+in the log file only, unless the user has given a positive value to
+\\{tracingonline}.
+
+@<Display a complex type@>=
+if ( verbosity<=1 ) {
+ mp_print_type(mp, t);
+} else {
+ if ( mp->selector==term_and_log )
+ if ( mp->internal[mp_tracing_online]<=0 ) {
+ mp->selector=term_only;
+ mp_print_type(mp, t); mp_print(mp, " (see the transcript file)");
+ mp->selector=term_and_log;
+ };
+ switch (t) {
+ case mp_pen_type:mp_print_pen(mp, v,"",false); break;
+ case mp_path_type:mp_print_path(mp, v,"",false); break;
+ case mp_picture_type:mp_print_edges(mp, v,"",false); break;
+ } /* there are no other cases */
+}
+
+@ @<Declare the procedure called |print_dp|@>=
+void mp_print_dp (MP mp,small_number t, pointer p,
+ small_number verbosity) {
+ pointer q; /* the node following |p| */
+ q=link(p);
+ if ( (info(q)==null) || (verbosity>0) ) mp_print_dependency(mp, p,t);
+ else mp_print(mp, "linearform");
+}
+
+@ The displayed name of a variable in a ring will not be a capsule unless
+the ring consists entirely of capsules.
+
+@<Display a variable that's been declared but not defined@>=
+{ mp_print_type(mp, t);
+if ( v!=null )
+ { mp_print_char(mp, ' ');
+ while ( (name_type(v)==mp_capsule) && (v!=p) ) v=value(v);
+ mp_print_variable_name(mp, v);
+ };
+}
+
+@ When errors are detected during parsing, it is often helpful to
+display an expression just above the error message, using |exp_err|
+or |disp_err| instead of |print_err|.
+
+@d exp_err(A) mp_disp_err(mp, null,(A)) /* displays the current expression */
+
+@<Declare subroutines for printing expressions@>=
+void mp_disp_err (MP mp,pointer p, const char *s) {
+ if ( mp->interaction==mp_error_stop_mode ) wake_up_terminal;
+ mp_print_nl(mp, ">> ");
+@.>>@>
+ mp_print_exp(mp, p,1); /* ``medium verbose'' printing of the expression */
+ if (strlen(s)) {
+ mp_print_nl(mp, "! "); mp_print(mp, s);
+@.!\relax@>
+ }
+}
+
+@ If |cur_type| and |cur_exp| contain relevant information that should
+be recycled, we will use the following procedure, which changes |cur_type|
+to |known| and stores a given value in |cur_exp|. We can think of |cur_type|
+and |cur_exp| as either alive or dormant after this has been done,
+because |cur_exp| will not contain a pointer value.
+
+@ @c void mp_flush_cur_exp (MP mp,scaled v) {
+ switch (mp->cur_type) {
+ case unknown_types: case mp_transform_type: case mp_color_type: case mp_pair_type:
+ case mp_dependent: case mp_proto_dependent: case mp_independent: case mp_cmykcolor_type:
+ mp_recycle_value(mp, mp->cur_exp);
+ mp_free_node(mp, mp->cur_exp,value_node_size);
+ break;
+ case mp_string_type:
+ delete_str_ref(mp->cur_exp); break;
+ case mp_pen_type: case mp_path_type:
+ mp_toss_knot_list(mp, mp->cur_exp); break;
+ case mp_picture_type:
+ delete_edge_ref(mp->cur_exp); break;
+ default:
+ break;
+ }
+ mp->cur_type=mp_known; mp->cur_exp=v;
+}
+
+@ There's a much more general procedure that is capable of releasing
+the storage associated with any two-word value packet.
+
+@<Declare the recycling subroutines@>=
+void mp_recycle_value (MP mp,pointer p) ;
+
+@ @c void mp_recycle_value (MP mp,pointer p) {
+ small_number t; /* a type code */
+ integer vv; /* another value */
+ pointer q,r,s,pp; /* link manipulation registers */
+ integer v=0; /* a value */
+ t=type(p);
+ if ( t<mp_dependent ) v=value(p);
+ switch (t) {
+ case undefined: case mp_vacuous: case mp_boolean_type: case mp_known:
+ case mp_numeric_type:
+ break;
+ case unknown_types:
+ mp_ring_delete(mp, p); break;
+ case mp_string_type:
+ delete_str_ref(v); break;
+ case mp_path_type: case mp_pen_type:
+ mp_toss_knot_list(mp, v); break;
+ case mp_picture_type:
+ delete_edge_ref(v); break;
+ case mp_cmykcolor_type: case mp_pair_type: case mp_color_type:
+ case mp_transform_type:
+ @<Recycle a big node@>; break;
+ case mp_dependent: case mp_proto_dependent:
+ @<Recycle a dependency list@>; break;
+ case mp_independent:
+ @<Recycle an independent variable@>; break;
+ case mp_token_list: case mp_structured:
+ mp_confusion(mp, "recycle"); break;
+@:this can't happen recycle}{\quad recycle@>
+ case mp_unsuffixed_macro: case mp_suffixed_macro:
+ mp_delete_mac_ref(mp, value(p)); break;
+ } /* there are no other cases */
+ type(p)=undefined;
+}
+
+@ @<Recycle a big node@>=
+if ( v!=null ){
+ q=v+mp->big_node_size[t];
+ do {
+ q=q-2; mp_recycle_value(mp, q);
+ } while (q!=v);
+ mp_free_node(mp, v,mp->big_node_size[t]);
+}
+
+@ @<Recycle a dependency list@>=
+{
+ q=dep_list(p);
+ while ( info(q)!=null ) q=link(q);
+ link(prev_dep(p))=link(q);
+ prev_dep(link(q))=prev_dep(p);
+ link(q)=null; mp_flush_node_list(mp, dep_list(p));
+}
+
+@ When an independent variable disappears, it simply fades away, unless
+something depends on it. In the latter case, a dependent variable whose
+coefficient of dependence is maximal will take its place.
+The relevant algorithm is due to Ignacio~A. Zabala, who implemented it
+as part of his Ph.D. thesis (Stanford University, December 1982).
+@^Zabala Salelles, Ignacio Andr\'es@>
+
+For example, suppose that variable $x$ is being recycled, and that the
+only variables depending on~$x$ are $y=2x+a$ and $z=x+b$. In this case
+we want to make $y$ independent and $z=.5y-.5a+b$; no other variables
+will depend on~$y$. If $\\{tracingequations}>0$ in this situation,
+we will print `\.{\#\#\# -2x=-y+a}'.
+
+There's a slight complication, however: An independent variable $x$
+can occur both in dependency lists and in proto-dependency lists.
+This makes it necessary to be careful when deciding which coefficient
+is maximal.
+
+Furthermore, this complication is not so slight when
+a proto-dependent variable is chosen to become independent. For example,
+suppose that $y=2x+100a$ is proto-dependent while $z=x+b$ is dependent;
+then we must change $z=.5y-50a+b$ to a proto-dependency, because of the
+large coefficient `50'.
+
+In order to deal with these complications without wasting too much time,
+we shall link together the occurrences of~$x$ among all the linear
+dependencies, maintaining separate lists for the dependent and
+proto-dependent cases.
+
+@<Recycle an independent variable@>=
+{
+ mp->max_c[mp_dependent]=0; mp->max_c[mp_proto_dependent]=0;
+ mp->max_link[mp_dependent]=null; mp->max_link[mp_proto_dependent]=null;
+ q=link(dep_head);
+ while ( q!=dep_head ) {
+ s=value_loc(q); /* now |link(s)=dep_list(q)| */
+ while (1) {
+ r=link(s);
+ if ( info(r)==null ) break;
+ if ( info(r)!=p ) {
+ s=r;
+ } else {
+ t=type(q); link(s)=link(r); info(r)=q;
+ if ( abs(value(r))>mp->max_c[t] ) {
+ @<Record a new maximum coefficient of type |t|@>;
+ } else {
+ link(r)=mp->max_link[t]; mp->max_link[t]=r;
+ }
+ }
+ }
+ q=link(r);
+ }
+ if ( (mp->max_c[mp_dependent]>0)||(mp->max_c[mp_proto_dependent]>0) ) {
+ @<Choose a dependent variable to take the place of the disappearing
+ independent variable, and change all remaining dependencies
+ accordingly@>;
+ }
+}
+
+@ The code for independency removal makes use of three two-word arrays.
+
+@<Glob...@>=
+integer max_c[mp_proto_dependent+1]; /* max coefficient magnitude */
+pointer max_ptr[mp_proto_dependent+1]; /* where |p| occurs with |max_c| */
+pointer max_link[mp_proto_dependent+1]; /* other occurrences of |p| */
+
+@ @<Record a new maximum coefficient...@>=
+{
+ if ( mp->max_c[t]>0 ) {
+ link(mp->max_ptr[t])=mp->max_link[t]; mp->max_link[t]=mp->max_ptr[t];
+ }
+ mp->max_c[t]=abs(value(r)); mp->max_ptr[t]=r;
+}
+
+@ @<Choose a dependent...@>=
+{
+ if ( (mp->max_c[mp_dependent] / 010000) >= mp->max_c[mp_proto_dependent] )
+ t=mp_dependent;
+ else
+ t=mp_proto_dependent;
+ @<Determine the dependency list |s| to substitute for the independent
+ variable~|p|@>;
+ t=mp_dependent+mp_proto_dependent-t; /* complement |t| */
+ if ( mp->max_c[t]>0 ) { /* we need to pick up an unchosen dependency */
+ link(mp->max_ptr[t])=mp->max_link[t]; mp->max_link[t]=mp->max_ptr[t];
+ }
+ if ( t!=mp_dependent ) { @<Substitute new dependencies in place of |p|@>; }
+ else { @<Substitute new proto-dependencies in place of |p|@>;}
+ mp_flush_node_list(mp, s);
+ if ( mp->fix_needed ) mp_fix_dependencies(mp);
+ check_arith;
+}
+
+@ Let |s=max_ptr[t]|. At this point we have $|value|(s)=\pm|max_c|[t]$,
+and |info(s)| points to the dependent variable~|pp| of type~|t| from
+whose dependency list we have removed node~|s|. We must reinsert
+node~|s| into the dependency list, with coefficient $-1.0$, and with
+|pp| as the new independent variable. Since |pp| will have a larger serial
+number than any other variable, we can put node |s| at the head of the
+list.
+
+@<Determine the dep...@>=
+s=mp->max_ptr[t]; pp=info(s); v=value(s);
+if ( t==mp_dependent ) value(s)=-fraction_one; else value(s)=-unity;
+r=dep_list(pp); link(s)=r;
+while ( info(r)!=null ) r=link(r);
+q=link(r); link(r)=null;
+prev_dep(q)=prev_dep(pp); link(prev_dep(pp))=q;
+new_indep(pp);
+if ( mp->cur_exp==pp ) if ( mp->cur_type==t ) mp->cur_type=mp_independent;
+if ( mp->internal[mp_tracing_equations]>0 ) {
+ @<Show the transformed dependency@>;
+}
+
+@ Now $(-v)$ times the formerly independent variable~|p| is being replaced
+by the dependency list~|s|.
+
+@<Show the transformed...@>=
+if ( mp_interesting(mp, p) ) {
+ mp_begin_diagnostic(mp); mp_print_nl(mp, "### ");
+@:]]]\#\#\#_}{\.{\#\#\#}@>
+ if ( v>0 ) mp_print_char(mp, '-');
+ if ( t==mp_dependent ) vv=mp_round_fraction(mp, mp->max_c[mp_dependent]);
+ else vv=mp->max_c[mp_proto_dependent];
+ if ( vv!=unity ) mp_print_scaled(mp, vv);
+ mp_print_variable_name(mp, p);
+ while ( value(p) % s_scale>0 ) {
+ mp_print(mp, "*4"); value(p)=value(p)-2;
+ }
+ if ( t==mp_dependent ) mp_print_char(mp, '='); else mp_print(mp, " = ");
+ mp_print_dependency(mp, s,t);
+ mp_end_diagnostic(mp, false);
+}
+
+@ Finally, there are dependent and proto-dependent variables whose
+dependency lists must be brought up to date.
+
+@<Substitute new dependencies...@>=
+for (t=mp_dependent;t<=mp_proto_dependent;t++){
+ r=mp->max_link[t];
+ while ( r!=null ) {
+ q=info(r);
+ dep_list(q)=mp_p_plus_fq(mp, dep_list(q),
+ mp_make_fraction(mp, value(r),-v),s,t,mp_dependent);
+ if ( dep_list(q)==mp->dep_final ) mp_make_known(mp, q,mp->dep_final);
+ q=r; r=link(r); mp_free_node(mp, q,dep_node_size);
+ }
+}
+
+@ @<Substitute new proto...@>=
+for (t=mp_dependent;t<=mp_proto_dependent;t++) {
+ r=mp->max_link[t];
+ while ( r!=null ) {
+ q=info(r);
+ if ( t==mp_dependent ) { /* for safety's sake, we change |q| to |mp_proto_dependent| */
+ if ( mp->cur_exp==q ) if ( mp->cur_type==mp_dependent )
+ mp->cur_type=mp_proto_dependent;
+ dep_list(q)=mp_p_over_v(mp, dep_list(q),unity,
+ mp_dependent,mp_proto_dependent);
+ type(q)=mp_proto_dependent;
+ value(r)=mp_round_fraction(mp, value(r));
+ }
+ dep_list(q)=mp_p_plus_fq(mp, dep_list(q),
+ mp_make_scaled(mp, value(r),-v),s,
+ mp_proto_dependent,mp_proto_dependent);
+ if ( dep_list(q)==mp->dep_final )
+ mp_make_known(mp, q,mp->dep_final);
+ q=r; r=link(r); mp_free_node(mp, q,dep_node_size);
+ }
+}
+
+@ Here are some routines that provide handy combinations of actions
+that are often needed during error recovery. For example,
+`|flush_error|' flushes the current expression, replaces it by
+a given value, and calls |error|.
+
+Errors often are detected after an extra token has already been scanned.
+The `\\{put\_get}' routines put that token back before calling |error|;
+then they get it back again. (Or perhaps they get another token, if
+the user has changed things.)
+
+@<Declarations@>=
+void mp_flush_error (MP mp,scaled v);
+void mp_put_get_error (MP mp);
+void mp_put_get_flush_error (MP mp,scaled v) ;
+
+@ @c
+void mp_flush_error (MP mp,scaled v) {
+ mp_error(mp); mp_flush_cur_exp(mp, v);
+}
+void mp_put_get_error (MP mp) {
+ mp_back_error(mp); mp_get_x_next(mp);
+}
+void mp_put_get_flush_error (MP mp,scaled v) {
+ mp_put_get_error(mp);
+ mp_flush_cur_exp(mp, v);
+}
+
+@ A global variable |var_flag| is set to a special command code
+just before \MP\ calls |scan_expression|, if the expression should be
+treated as a variable when this command code immediately follows. For
+example, |var_flag| is set to |assignment| at the beginning of a
+statement, because we want to know the {\sl location\/} of a variable at
+the left of `\.{:=}', not the {\sl value\/} of that variable.
+
+The |scan_expression| subroutine calls |scan_tertiary|,
+which calls |scan_secondary|, which calls |scan_primary|, which sets
+|var_flag:=0|. In this way each of the scanning routines ``knows''
+when it has been called with a special |var_flag|, but |var_flag| is
+usually zero.
+
+A variable preceding a command that equals |var_flag| is converted to a
+token list rather than a value. Furthermore, an `\.{=}' sign following an
+expression with |var_flag=assignment| is not considered to be a relation
+that produces boolean expressions.
+
+
+@<Glob...@>=
+int var_flag; /* command that wants a variable */
+
+@ @<Set init...@>=
+mp->var_flag=0;
+
+@* \[37] Parsing primary expressions.
+The first parsing routine, |scan_primary|, is also the most complicated one,
+since it involves so many different cases. But each case---with one
+exception---is fairly simple by itself.
+
+When |scan_primary| begins, the first token of the primary to be scanned
+should already appear in |cur_cmd|, |cur_mod|, and |cur_sym|. The values
+of |cur_type| and |cur_exp| should be either dead or dormant, as explained
+earlier. If |cur_cmd| is not between |min_primary_command| and
+|max_primary_command|, inclusive, a syntax error will be signaled.
+
+@<Declare the basic parsing subroutines@>=
+void mp_scan_primary (MP mp) {
+ pointer p,q,r; /* for list manipulation */
+ quarterword c; /* a primitive operation code */
+ int my_var_flag; /* initial value of |my_var_flag| */
+ pointer l_delim,r_delim; /* hash addresses of a delimiter pair */
+ @<Other local variables for |scan_primary|@>;
+ my_var_flag=mp->var_flag; mp->var_flag=0;
+RESTART:
+ check_arith;
+ @<Supply diagnostic information, if requested@>;
+ switch (mp->cur_cmd) {
+ case left_delimiter:
+ @<Scan a delimited primary@>; break;
+ case begin_group:
+ @<Scan a grouped primary@>; break;
+ case string_token:
+ @<Scan a string constant@>; break;
+ case numeric_token:
+ @<Scan a primary that starts with a numeric token@>; break;
+ case nullary:
+ @<Scan a nullary operation@>; break;
+ case unary: case type_name: case cycle: case plus_or_minus:
+ @<Scan a unary operation@>; break;
+ case primary_binary:
+ @<Scan a binary operation with `\&{of}' between its operands@>; break;
+ case str_op:
+ @<Convert a suffix to a string@>; break;
+ case internal_quantity:
+ @<Scan an internal numeric quantity@>; break;
+ case capsule_token:
+ mp_make_exp_copy(mp, mp->cur_mod); break;
+ case tag_token:
+ @<Scan a variable primary; |goto restart| if it turns out to be a macro@>; break;
+ default:
+ mp_bad_exp(mp, "A primary"); goto RESTART; break;
+@.A primary expression...@>
+ }
+ mp_get_x_next(mp); /* the routines |goto done| if they don't want this */
+DONE:
+ if ( mp->cur_cmd==left_bracket ) {
+ if ( mp->cur_type>=mp_known ) {
+ @<Scan a mediation construction@>;
+ }
+ }
+}
+
+
+
+@ Errors at the beginning of expressions are flagged by |bad_exp|.
+
+@c void mp_bad_exp (MP mp, const char * s) {
+ int save_flag;
+ print_err(s); mp_print(mp, " expression can't begin with `");
+ mp_print_cmd_mod(mp, mp->cur_cmd,mp->cur_mod);
+ mp_print_char(mp, '\'');
+ help4("I'm afraid I need some sort of value in order to continue,")
+ ("so I've tentatively inserted `0'. You may want to")
+ ("delete this zero and insert something else;")
+ ("see Chapter 27 of The METAFONTbook for an example.");
+@:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
+ mp_back_input(mp); mp->cur_sym=0; mp->cur_cmd=numeric_token;
+ mp->cur_mod=0; mp_ins_error(mp);
+ save_flag=mp->var_flag; mp->var_flag=0; mp_get_x_next(mp);
+ mp->var_flag=save_flag;
+}
+
+@ @<Supply diagnostic information, if requested@>=
+#ifdef DEBUG
+if ( mp->panicking ) mp_check_mem(mp, false);
+#endif
+if ( mp->interrupt!=0 ) if ( mp->OK_to_interrupt ) {
+ mp_back_input(mp); check_interrupt; mp_get_x_next(mp);
+}
+
+@ @<Scan a delimited primary@>=
+{
+ l_delim=mp->cur_sym; r_delim=mp->cur_mod;
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( (mp->cur_cmd==comma) && (mp->cur_type>=mp_known) ) {
+ @<Scan the rest of a delimited set of numerics@>;
+ } else {
+ mp_check_delimiter(mp, l_delim,r_delim);
+ }
+}
+
+@ The |stash_in| subroutine puts the current (numeric) expression into a field
+within a ``big node.''
+
+@c void mp_stash_in (MP mp,pointer p) {
+ pointer q; /* temporary register */
+ type(p)=mp->cur_type;
+ if ( mp->cur_type==mp_known ) {
+ value(p)=mp->cur_exp;
+ } else {
+ if ( mp->cur_type==mp_independent ) {
+ @<Stash an independent |cur_exp| into a big node@>;
+ } else {
+ mp->mem[value_loc(p)]=mp->mem[value_loc(mp->cur_exp)];
+ /* |dep_list(p):=dep_list(cur_exp)| and |prev_dep(p):=prev_dep(cur_exp)| */
+ link(prev_dep(p))=p;
+ }
+ mp_free_node(mp, mp->cur_exp,value_node_size);
+ }
+ mp->cur_type=mp_vacuous;
+}
+
+@ In rare cases the current expression can become |independent|. There
+may be many dependency lists pointing to such an independent capsule,
+so we can't simply move it into place within a big node. Instead,
+we copy it, then recycle it.
+
+@ @<Stash an independent |cur_exp|...@>=
+{
+ q=mp_single_dependency(mp, mp->cur_exp);
+ if ( q==mp->dep_final ){
+ type(p)=mp_known; value(p)=0; mp_free_node(mp, q,dep_node_size);
+ } else {
+ type(p)=mp_dependent; mp_new_dep(mp, p,q);
+ }
+ mp_recycle_value(mp, mp->cur_exp);
+}
+
+@ This code uses the fact that |red_part_loc| and |green_part_loc|
+are synonymous with |x_part_loc| and |y_part_loc|.
+
+@<Scan the rest of a delimited set of numerics@>=
+{
+p=mp_stash_cur_exp(mp);
+mp_get_x_next(mp); mp_scan_expression(mp);
+@<Make sure the second part of a pair or color has a numeric type@>;
+q=mp_get_node(mp, value_node_size); name_type(q)=mp_capsule;
+if ( mp->cur_cmd==comma ) type(q)=mp_color_type;
+else type(q)=mp_pair_type;
+mp_init_big_node(mp, q); r=value(q);
+mp_stash_in(mp, y_part_loc(r));
+mp_unstash_cur_exp(mp, p);
+mp_stash_in(mp, x_part_loc(r));
+if ( mp->cur_cmd==comma ) {
+ @<Scan the last of a triplet of numerics@>;
+}
+if ( mp->cur_cmd==comma ) {
+ type(q)=mp_cmykcolor_type;
+ mp_init_big_node(mp, q); t=value(q);
+ mp->mem[cyan_part_loc(t)]=mp->mem[red_part_loc(r)];
+ value(cyan_part_loc(t))=value(red_part_loc(r));
+ mp->mem[magenta_part_loc(t)]=mp->mem[green_part_loc(r)];
+ value(magenta_part_loc(t))=value(green_part_loc(r));
+ mp->mem[yellow_part_loc(t)]=mp->mem[blue_part_loc(r)];
+ value(yellow_part_loc(t))=value(blue_part_loc(r));
+ mp_recycle_value(mp, r);
+ r=t;
+ @<Scan the last of a quartet of numerics@>;
+}
+mp_check_delimiter(mp, l_delim,r_delim);
+mp->cur_type=type(q);
+mp->cur_exp=q;
+}
+
+@ @<Make sure the second part of a pair or color has a numeric type@>=
+if ( mp->cur_type<mp_known ) {
+ exp_err("Nonnumeric ypart has been replaced by 0");
+@.Nonnumeric...replaced by 0@>
+ help4("I've started to scan a pair `(a,b)' or a color `(a,b,c)';")
+ ("but after finding a nice `a' I found a `b' that isn't")
+ ("of numeric type. So I've changed that part to zero.")
+ ("(The b that I didn't like appears above the error message.)");
+ mp_put_get_flush_error(mp, 0);
+}
+
+@ @<Scan the last of a triplet of numerics@>=
+{
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type<mp_known ) {
+ exp_err("Nonnumeric third part has been replaced by 0");
+@.Nonnumeric...replaced by 0@>
+ help3("I've just scanned a color `(a,b,c)' or cmykcolor(a,b,c,d); but the `c'")
+ ("isn't of numeric type. So I've changed that part to zero.")
+ ("(The c that I didn't like appears above the error message.)");
+ mp_put_get_flush_error(mp, 0);
+ }
+ mp_stash_in(mp, blue_part_loc(r));
+}
+
+@ @<Scan the last of a quartet of numerics@>=
+{
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type<mp_known ) {
+ exp_err("Nonnumeric blackpart has been replaced by 0");
+@.Nonnumeric...replaced by 0@>
+ help3("I've just scanned a cmykcolor `(c,m,y,k)'; but the `k' isn't")
+ ("of numeric type. So I've changed that part to zero.")
+ ("(The k that I didn't like appears above the error message.)");
+ mp_put_get_flush_error(mp, 0);
+ }
+ mp_stash_in(mp, black_part_loc(r));
+}
+
+@ The local variable |group_line| keeps track of the line
+where a \&{begingroup} command occurred; this will be useful
+in an error message if the group doesn't actually end.
+
+@<Other local variables for |scan_primary|@>=
+integer group_line; /* where a group began */
+
+@ @<Scan a grouped primary@>=
+{
+ group_line=mp_true_line(mp);
+ if ( mp->internal[mp_tracing_commands]>0 ) show_cur_cmd_mod;
+ save_boundary_item(p);
+ do {
+ mp_do_statement(mp); /* ends with |cur_cmd>=semicolon| */
+ } while (mp->cur_cmd==semicolon);
+ if ( mp->cur_cmd!=end_group ) {
+ print_err("A group begun on line ");
+@.A group...never ended@>
+ mp_print_int(mp, group_line);
+ mp_print(mp, " never ended");
+ help2("I saw a `begingroup' back there that hasn't been matched")
+ ("by `endgroup'. So I've inserted `endgroup' now.");
+ mp_back_error(mp); mp->cur_cmd=end_group;
+ }
+ mp_unsave(mp);
+ /* this might change |cur_type|, if independent variables are recycled */
+ if ( mp->internal[mp_tracing_commands]>0 ) show_cur_cmd_mod;
+}
+
+@ @<Scan a string constant@>=
+{
+ mp->cur_type=mp_string_type; mp->cur_exp=mp->cur_mod;
+}
+
+@ Later we'll come to procedures that perform actual operations like
+addition, square root, and so on; our purpose now is to do the parsing.
+But we might as well mention those future procedures now, so that the
+suspense won't be too bad:
+
+\smallskip
+|do_nullary(c)| does primitive operations that have no operands (e.g.,
+`\&{true}' or `\&{pencircle}');
+
+\smallskip
+|do_unary(c)| applies a primitive operation to the current expression;
+
+\smallskip
+|do_binary(p,c)| applies a primitive operation to the capsule~|p|
+and the current expression.
+
+@<Scan a nullary operation@>=mp_do_nullary(mp, mp->cur_mod)
+
+@ @<Scan a unary operation@>=
+{
+ c=mp->cur_mod; mp_get_x_next(mp); mp_scan_primary(mp);
+ mp_do_unary(mp, c); goto DONE;
+}
+
+@ A numeric token might be a primary by itself, or it might be the
+numerator of a fraction composed solely of numeric tokens, or it might
+multiply the primary that follows (provided that the primary doesn't begin
+with a plus sign or a minus sign). The code here uses the facts that
+|max_primary_command=plus_or_minus| and
+|max_primary_command-1=numeric_token|. If a fraction is found that is less
+than unity, we try to retain higher precision when we use it in scalar
+multiplication.
+
+@<Other local variables for |scan_primary|@>=
+scaled num,denom; /* for primaries that are fractions, like `1/2' */
+
+@ @<Scan a primary that starts with a numeric token@>=
+{
+ mp->cur_exp=mp->cur_mod; mp->cur_type=mp_known; mp_get_x_next(mp);
+ if ( mp->cur_cmd!=slash ) {
+ num=0; denom=0;
+ } else {
+ mp_get_x_next(mp);
+ if ( mp->cur_cmd!=numeric_token ) {
+ mp_back_input(mp);
+ mp->cur_cmd=slash; mp->cur_mod=over; mp->cur_sym=frozen_slash;
+ goto DONE;
+ }
+ num=mp->cur_exp; denom=mp->cur_mod;
+ if ( denom==0 ) { @<Protest division by zero@>; }
+ else { mp->cur_exp=mp_make_scaled(mp, num,denom); }
+ check_arith; mp_get_x_next(mp);
+ }
+ if ( mp->cur_cmd>=min_primary_command ) {
+ if ( mp->cur_cmd<numeric_token ) { /* in particular, |cur_cmd<>plus_or_minus| */
+ p=mp_stash_cur_exp(mp); mp_scan_primary(mp);
+ if ( (abs(num)>=abs(denom))||(mp->cur_type<mp_color_type) ) {
+ mp_do_binary(mp, p,times);
+ } else {
+ mp_frac_mult(mp, num,denom);
+ mp_free_node(mp, p,value_node_size);
+ }
+ }
+ }
+ goto DONE;
+}
+
+@ @<Protest division...@>=
+{
+ print_err("Division by zero");
+@.Division by zero@>
+ help1("I'll pretend that you meant to divide by 1."); mp_error(mp);
+}
+
+@ @<Scan a binary operation with `\&{of}' between its operands@>=
+{
+ c=mp->cur_mod; mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_cmd!=of_token ) {
+ mp_missing_err(mp, "of"); mp_print(mp, " for ");
+ mp_print_cmd_mod(mp, primary_binary,c);
+@.Missing `of'@>
+ help1("I've got the first argument; will look now for the other.");
+ mp_back_error(mp);
+ }
+ p=mp_stash_cur_exp(mp); mp_get_x_next(mp); mp_scan_primary(mp);
+ mp_do_binary(mp, p,c); goto DONE;
+}
+
+@ @<Convert a suffix to a string@>=
+{
+ mp_get_x_next(mp); mp_scan_suffix(mp);
+ mp->old_setting=mp->selector; mp->selector=new_string;
+ mp_show_token_list(mp, mp->cur_exp,null,100000,0);
+ mp_flush_token_list(mp, mp->cur_exp);
+ mp->cur_exp=mp_make_string(mp); mp->selector=mp->old_setting;
+ mp->cur_type=mp_string_type;
+ goto DONE;
+}
+
+@ If an internal quantity appears all by itself on the left of an
+assignment, we return a token list of length one, containing the address
+of the internal quantity plus |hash_end|. (This accords with the conventions
+of the save stack, as described earlier.)
+
+@<Scan an internal...@>=
+{
+ q=mp->cur_mod;
+ if ( my_var_flag==assignment ) {
+ mp_get_x_next(mp);
+ if ( mp->cur_cmd==assignment ) {
+ mp->cur_exp=mp_get_avail(mp);
+ info(mp->cur_exp)=q+hash_end; mp->cur_type=mp_token_list;
+ goto DONE;
+ }
+ mp_back_input(mp);
+ }
+ mp->cur_type=mp_known; mp->cur_exp=mp->internal[q];
+}
+
+@ The most difficult part of |scan_primary| has been saved for last, since
+it was necessary to build up some confidence first. We can now face the task
+of scanning a variable.
+
+As we scan a variable, we build a token list containing the relevant
+names and subscript values, simultaneously following along in the
+``collective'' structure to see if we are actually dealing with a macro
+instead of a value.
+
+The local variables |pre_head| and |post_head| will point to the beginning
+of the prefix and suffix lists; |tail| will point to the end of the list
+that is currently growing.
+
+Another local variable, |tt|, contains partial information about the
+declared type of the variable-so-far. If |tt>=mp_unsuffixed_macro|, the
+relation |tt=type(q)| will always hold. If |tt=undefined|, the routine
+doesn't bother to update its information about type. And if
+|undefined<tt<mp_unsuffixed_macro|, the precise value of |tt| isn't critical.
+
+@ @<Other local variables for |scan_primary|@>=
+pointer pre_head,post_head,tail;
+ /* prefix and suffix list variables */
+small_number tt; /* approximation to the type of the variable-so-far */
+pointer t; /* a token */
+pointer macro_ref = 0; /* reference count for a suffixed macro */
+
+@ @<Scan a variable primary...@>=
+{
+ fast_get_avail(pre_head); tail=pre_head; post_head=null; tt=mp_vacuous;
+ while (1) {
+ t=mp_cur_tok(mp); link(tail)=t;
+ if ( tt!=undefined ) {
+ @<Find the approximate type |tt| and corresponding~|q|@>;
+ if ( tt>=mp_unsuffixed_macro ) {
+ @<Either begin an unsuffixed macro call or
+ prepare for a suffixed one@>;
+ }
+ }
+ mp_get_x_next(mp); tail=t;
+ if ( mp->cur_cmd==left_bracket ) {
+ @<Scan for a subscript; replace |cur_cmd| by |numeric_token| if found@>;
+ }
+ if ( mp->cur_cmd>max_suffix_token ) break;
+ if ( mp->cur_cmd<min_suffix_token ) break;
+ } /* now |cur_cmd| is |internal_quantity|, |tag_token|, or |numeric_token| */
+ @<Handle unusual cases that masquerade as variables, and |goto restart|
+ or |goto done| if appropriate;
+ otherwise make a copy of the variable and |goto done|@>;
+}
+
+@ @<Either begin an unsuffixed macro call or...@>=
+{
+ link(tail)=null;
+ if ( tt>mp_unsuffixed_macro ) { /* |tt=mp_suffixed_macro| */
+ post_head=mp_get_avail(mp); tail=post_head; link(tail)=t;
+ tt=undefined; macro_ref=value(q); add_mac_ref(macro_ref);
+ } else {
+ @<Set up unsuffixed macro call and |goto restart|@>;
+ }
+}
+
+@ @<Scan for a subscript; replace |cur_cmd| by |numeric_token| if found@>=
+{
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_cmd!=right_bracket ) {
+ @<Put the left bracket and the expression back to be rescanned@>;
+ } else {
+ if ( mp->cur_type!=mp_known ) mp_bad_subscript(mp);
+ mp->cur_cmd=numeric_token; mp->cur_mod=mp->cur_exp; mp->cur_sym=0;
+ }
+}
+
+@ The left bracket that we thought was introducing a subscript might have
+actually been the left bracket in a mediation construction like `\.{x[a,b]}'.
+So we don't issue an error message at this point; but we do want to back up
+so as to avoid any embarrassment about our incorrect assumption.
+
+@<Put the left bracket and the expression back to be rescanned@>=
+{
+ mp_back_input(mp); /* that was the token following the current expression */
+ mp_back_expr(mp); mp->cur_cmd=left_bracket;
+ mp->cur_mod=0; mp->cur_sym=frozen_left_bracket;
+}
+
+@ Here's a routine that puts the current expression back to be read again.
+
+@c void mp_back_expr (MP mp) {
+ pointer p; /* capsule token */
+ p=mp_stash_cur_exp(mp); link(p)=null; back_list(p);
+}
+
+@ Unknown subscripts lead to the following error message.
+
+@c void mp_bad_subscript (MP mp) {
+ exp_err("Improper subscript has been replaced by zero");
+@.Improper subscript...@>
+ help3("A bracketed subscript must have a known numeric value;")
+ ("unfortunately, what I found was the value that appears just")
+ ("above this error message. So I'll try a zero subscript.");
+ mp_flush_error(mp, 0);
+}
+
+@ Every time we call |get_x_next|, there's a chance that the variable we've
+been looking at will disappear. Thus, we cannot safely keep |q| pointing
+into the variable structure; we need to start searching from the root each time.
+
+@<Find the approximate type |tt| and corresponding~|q|@>=
+@^inner loop@>
+{
+ p=link(pre_head); q=info(p); tt=undefined;
+ if ( eq_type(q) % outer_tag==tag_token ) {
+ q=equiv(q);
+ if ( q==null ) goto DONE2;
+ while (1) {
+ p=link(p);
+ if ( p==null ) {
+ tt=type(q); goto DONE2;
+ };
+ if ( type(q)!=mp_structured ) goto DONE2;
+ q=link(attr_head(q)); /* the |collective_subscript| attribute */
+ if ( p>=mp->hi_mem_min ) { /* it's not a subscript */
+ do { q=link(q); } while (! (attr_loc(q)>=info(p)));
+ if ( attr_loc(q)>info(p) ) goto DONE2;
+ }
+ }
+ }
+DONE2:
+ ;
+}
+
+@ How do things stand now? Well, we have scanned an entire variable name,
+including possible subscripts and/or attributes; |cur_cmd|, |cur_mod|, and
+|cur_sym| represent the token that follows. If |post_head=null|, a
+token list for this variable name starts at |link(pre_head)|, with all
+subscripts evaluated. But if |post_head<>null|, the variable turned out
+to be a suffixed macro; |pre_head| is the head of the prefix list, while
+|post_head| is the head of a token list containing both `\.{\AT!}' and
+the suffix.
+
+Our immediate problem is to see if this variable still exists. (Variable
+structures can change drastically whenever we call |get_x_next|; users
+aren't supposed to do this, but the fact that it is possible means that
+we must be cautious.)
+
+The following procedure prints an error message when a variable
+unexpectedly disappears. Its help message isn't quite right for
+our present purposes, but we'll be able to fix that up.
+
+@c
+void mp_obliterated (MP mp,pointer q) {
+ print_err("Variable "); mp_show_token_list(mp, q,null,1000,0);
+ mp_print(mp, " has been obliterated");
+@.Variable...obliterated@>
+ help5("It seems you did a nasty thing---probably by accident,")
+ ("but nevertheless you nearly hornswoggled me...")
+ ("While I was evaluating the right-hand side of this")
+ ("command, something happened, and the left-hand side")
+ ("is no longer a variable! So I won't change anything.");
+}
+
+@ If the variable does exist, we also need to check
+for a few other special cases before deciding that a plain old ordinary
+variable has, indeed, been scanned.
+
+@<Handle unusual cases that masquerade as variables...@>=
+if ( post_head!=null ) {
+ @<Set up suffixed macro call and |goto restart|@>;
+}
+q=link(pre_head); free_avail(pre_head);
+if ( mp->cur_cmd==my_var_flag ) {
+ mp->cur_type=mp_token_list; mp->cur_exp=q; goto DONE;
+}
+p=mp_find_variable(mp, q);
+if ( p!=null ) {
+ mp_make_exp_copy(mp, p);
+} else {
+ mp_obliterated(mp, q);
+ mp->help_line[2]="While I was evaluating the suffix of this variable,";
+ mp->help_line[1]="something was redefined, and it's no longer a variable!";
+ mp->help_line[0]="In order to get back on my feet, I've inserted `0' instead.";
+ mp_put_get_flush_error(mp, 0);
+}
+mp_flush_node_list(mp, q);
+goto DONE
+
+@ The only complication associated with macro calling is that the prefix
+and ``at'' parameters must be packaged in an appropriate list of lists.
+
+@<Set up unsuffixed macro call and |goto restart|@>=
+{
+ p=mp_get_avail(mp); info(pre_head)=link(pre_head); link(pre_head)=p;
+ info(p)=t; mp_macro_call(mp, value(q),pre_head,null);
+ mp_get_x_next(mp);
+ goto RESTART;
+}
+
+@ If the ``variable'' that turned out to be a suffixed macro no longer exists,
+we don't care, because we have reserved a pointer (|macro_ref|) to its
+token list.
+
+@<Set up suffixed macro call and |goto restart|@>=
+{
+ mp_back_input(mp); p=mp_get_avail(mp); q=link(post_head);
+ info(pre_head)=link(pre_head); link(pre_head)=post_head;
+ info(post_head)=q; link(post_head)=p; info(p)=link(q); link(q)=null;
+ mp_macro_call(mp, macro_ref,pre_head,null); decr(ref_count(macro_ref));
+ mp_get_x_next(mp); goto RESTART;
+}
+
+@ Our remaining job is simply to make a copy of the value that has been
+found. Some cases are harder than others, but complexity arises solely
+because of the multiplicity of possible cases.
+
+@<Declare the procedure called |make_exp_copy|@>=
+@<Declare subroutines needed by |make_exp_copy|@>
+void mp_make_exp_copy (MP mp,pointer p) {
+ pointer q,r,t; /* registers for list manipulation */
+RESTART:
+ mp->cur_type=type(p);
+ switch (mp->cur_type) {
+ case mp_vacuous: case mp_boolean_type: case mp_known:
+ mp->cur_exp=value(p); break;
+ case unknown_types:
+ mp->cur_exp=mp_new_ring_entry(mp, p);
+ break;
+ case mp_string_type:
+ mp->cur_exp=value(p); add_str_ref(mp->cur_exp);
+ break;
+ case mp_picture_type:
+ mp->cur_exp=value(p);add_edge_ref(mp->cur_exp);
+ break;
+ case mp_pen_type:
+ mp->cur_exp=copy_pen(value(p));
+ break;
+ case mp_path_type:
+ mp->cur_exp=mp_copy_path(mp, value(p));
+ break;
+ case mp_transform_type: case mp_color_type:
+ case mp_cmykcolor_type: case mp_pair_type:
+ @<Copy the big node |p|@>;
+ break;
+ case mp_dependent: case mp_proto_dependent:
+ mp_encapsulate(mp, mp_copy_dep_list(mp, dep_list(p)));
+ break;
+ case mp_numeric_type:
+ new_indep(p); goto RESTART;
+ break;
+ case mp_independent:
+ q=mp_single_dependency(mp, p);
+ if ( q==mp->dep_final ){
+ mp->cur_type=mp_known; mp->cur_exp=0; mp_free_node(mp, q,dep_node_size);
+ } else {
+ mp->cur_type=mp_dependent; mp_encapsulate(mp, q);
+ }
+ break;
+ default:
+ mp_confusion(mp, "copy");
+@:this can't happen copy}{\quad copy@>
+ break;
+ }
+}
+
+@ The |encapsulate| subroutine assumes that |dep_final| is the
+tail of dependency list~|p|.
+
+@<Declare subroutines needed by |make_exp_copy|@>=
+void mp_encapsulate (MP mp,pointer p) {
+ mp->cur_exp=mp_get_node(mp, value_node_size); type(mp->cur_exp)=mp->cur_type;
+ name_type(mp->cur_exp)=mp_capsule; mp_new_dep(mp, mp->cur_exp,p);
+}
+
+@ The most tedious case arises when the user refers to a
+\&{pair}, \&{color}, or \&{transform} variable; we must copy several fields,
+each of which can be |independent|, |dependent|, |mp_proto_dependent|,
+or |known|.
+
+@<Copy the big node |p|@>=
+{
+ if ( value(p)==null )
+ mp_init_big_node(mp, p);
+ t=mp_get_node(mp, value_node_size); name_type(t)=mp_capsule; type(t)=mp->cur_type;
+ mp_init_big_node(mp, t);
+ q=value(p)+mp->big_node_size[mp->cur_type];
+ r=value(t)+mp->big_node_size[mp->cur_type];
+ do {
+ q=q-2; r=r-2; mp_install(mp, r,q);
+ } while (q!=value(p));
+ mp->cur_exp=t;
+}
+
+@ The |install| procedure copies a numeric field~|q| into field~|r| of
+a big node that will be part of a capsule.
+
+@<Declare subroutines needed by |make_exp_copy|@>=
+void mp_install (MP mp,pointer r, pointer q) {
+ pointer p; /* temporary register */
+ if ( type(q)==mp_known ){
+ value(r)=value(q); type(r)=mp_known;
+ } else if ( type(q)==mp_independent ) {
+ p=mp_single_dependency(mp, q);
+ if ( p==mp->dep_final ) {
+ type(r)=mp_known; value(r)=0; mp_free_node(mp, p,dep_node_size);
+ } else {
+ type(r)=mp_dependent; mp_new_dep(mp, r,p);
+ }
+ } else {
+ type(r)=type(q); mp_new_dep(mp, r,mp_copy_dep_list(mp, dep_list(q)));
+ }
+}
+
+@ Expressions of the form `\.{a[b,c]}' are converted into
+`\.{b+a*(c-b)}', without checking the types of \.b~or~\.c,
+provided that \.a is numeric.
+
+@<Scan a mediation...@>=
+{
+ p=mp_stash_cur_exp(mp); mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_cmd!=comma ) {
+ @<Put the left bracket and the expression back...@>;
+ mp_unstash_cur_exp(mp, p);
+ } else {
+ q=mp_stash_cur_exp(mp); mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_cmd!=right_bracket ) {
+ mp_missing_err(mp, "]");
+@.Missing `]'@>
+ help3("I've scanned an expression of the form `a[b,c',")
+ ("so a right bracket should have come next.")
+ ("I shall pretend that one was there.");
+ mp_back_error(mp);
+ }
+ r=mp_stash_cur_exp(mp); mp_make_exp_copy(mp, q);
+ mp_do_binary(mp, r,minus); mp_do_binary(mp, p,times);
+ mp_do_binary(mp, q,plus); mp_get_x_next(mp);
+ }
+}
+
+@ Here is a comparatively simple routine that is used to scan the
+\&{suffix} parameters of a macro.
+
+@<Declare the basic parsing subroutines@>=
+void mp_scan_suffix (MP mp) {
+ pointer h,t; /* head and tail of the list being built */
+ pointer p; /* temporary register */
+ h=mp_get_avail(mp); t=h;
+ while (1) {
+ if ( mp->cur_cmd==left_bracket ) {
+ @<Scan a bracketed subscript and set |cur_cmd:=numeric_token|@>;
+ }
+ if ( mp->cur_cmd==numeric_token ) {
+ p=mp_new_num_tok(mp, mp->cur_mod);
+ } else if ((mp->cur_cmd==tag_token)||(mp->cur_cmd==internal_quantity) ) {
+ p=mp_get_avail(mp); info(p)=mp->cur_sym;
+ } else {
+ break;
+ }
+ link(t)=p; t=p; mp_get_x_next(mp);
+ }
+ mp->cur_exp=link(h); free_avail(h); mp->cur_type=mp_token_list;
+}
+
+@ @<Scan a bracketed subscript and set |cur_cmd:=numeric_token|@>=
+{
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type!=mp_known ) mp_bad_subscript(mp);
+ if ( mp->cur_cmd!=right_bracket ) {
+ mp_missing_err(mp, "]");
+@.Missing `]'@>
+ help3("I've seen a `[' and a subscript value, in a suffix,")
+ ("so a right bracket should have come next.")
+ ("I shall pretend that one was there.");
+ mp_back_error(mp);
+ }
+ mp->cur_cmd=numeric_token; mp->cur_mod=mp->cur_exp;
+}
+
+@* \[38] Parsing secondary and higher expressions.
+
+After the intricacies of |scan_primary|\kern-1pt,
+the |scan_secondary| routine is
+refreshingly simple. It's not trivial, but the operations are relatively
+straightforward; the main difficulty is, again, that expressions and data
+structures might change drastically every time we call |get_x_next|, so a
+cautious approach is mandatory. For example, a macro defined by
+\&{primarydef} might have disappeared by the time its second argument has
+been scanned; we solve this by increasing the reference count of its token
+list, so that the macro can be called even after it has been clobbered.
+
+@<Declare the basic parsing subroutines@>=
+void mp_scan_secondary (MP mp) {
+ pointer p; /* for list manipulation */
+ halfword c,d; /* operation codes or modifiers */
+ pointer mac_name; /* token defined with \&{primarydef} */
+RESTART:
+ if ((mp->cur_cmd<min_primary_command)||
+ (mp->cur_cmd>max_primary_command) )
+ mp_bad_exp(mp, "A secondary");
+@.A secondary expression...@>
+ mp_scan_primary(mp);
+CONTINUE:
+ if ( mp->cur_cmd<=max_secondary_command &&
+ mp->cur_cmd>=min_secondary_command ) {
+ p=mp_stash_cur_exp(mp);
+ c=mp->cur_mod; d=mp->cur_cmd;
+ if ( d==secondary_primary_macro ) {
+ mac_name=mp->cur_sym;
+ add_mac_ref(c);
+ }
+ mp_get_x_next(mp);
+ mp_scan_primary(mp);
+ if ( d!=secondary_primary_macro ) {
+ mp_do_binary(mp, p,c);
+ } else {
+ mp_back_input(mp);
+ mp_binary_mac(mp, p,c,mac_name);
+ decr(ref_count(c));
+ mp_get_x_next(mp);
+ goto RESTART;
+ }
+ goto CONTINUE;
+ }
+}
+
+@ The following procedure calls a macro that has two parameters,
+|p| and |cur_exp|.
+
+@c void mp_binary_mac (MP mp,pointer p, pointer c, pointer n) {
+ pointer q,r; /* nodes in the parameter list */
+ q=mp_get_avail(mp); r=mp_get_avail(mp); link(q)=r;
+ info(q)=p; info(r)=mp_stash_cur_exp(mp);
+ mp_macro_call(mp, c,q,n);
+}
+
+@ The next procedure, |scan_tertiary|, is pretty much the same deal.
+
+@<Declare the basic parsing subroutines@>=
+void mp_scan_tertiary (MP mp) {
+ pointer p; /* for list manipulation */
+ halfword c,d; /* operation codes or modifiers */
+ pointer mac_name; /* token defined with \&{secondarydef} */
+RESTART:
+ if ((mp->cur_cmd<min_primary_command)||
+ (mp->cur_cmd>max_primary_command) )
+ mp_bad_exp(mp, "A tertiary");
+@.A tertiary expression...@>
+ mp_scan_secondary(mp);
+CONTINUE:
+ if ( mp->cur_cmd<=max_tertiary_command ) {
+ if ( mp->cur_cmd>=min_tertiary_command ) {
+ p=mp_stash_cur_exp(mp); c=mp->cur_mod; d=mp->cur_cmd;
+ if ( d==tertiary_secondary_macro ) {
+ mac_name=mp->cur_sym; add_mac_ref(c);
+ };
+ mp_get_x_next(mp); mp_scan_secondary(mp);
+ if ( d!=tertiary_secondary_macro ) {
+ mp_do_binary(mp, p,c);
+ } else {
+ mp_back_input(mp); mp_binary_mac(mp, p,c,mac_name);
+ decr(ref_count(c)); mp_get_x_next(mp);
+ goto RESTART;
+ }
+ goto CONTINUE;
+ }
+ }
+}
+
+@ Finally we reach the deepest level in our quartet of parsing routines.
+This one is much like the others; but it has an extra complication from
+paths, which materialize here.
+
+@d continue_path 25 /* a label inside of |scan_expression| */
+@d finish_path 26 /* another */
+
+@<Declare the basic parsing subroutines@>=
+void mp_scan_expression (MP mp) {
+ pointer p,q,r,pp,qq; /* for list manipulation */
+ halfword c,d; /* operation codes or modifiers */
+ int my_var_flag; /* initial value of |var_flag| */
+ pointer mac_name; /* token defined with \&{tertiarydef} */
+ boolean cycle_hit; /* did a path expression just end with `\&{cycle}'? */
+ scaled x,y; /* explicit coordinates or tension at a path join */
+ int t; /* knot type following a path join */
+ t=0; y=0; x=0;
+ my_var_flag=mp->var_flag; mac_name=null;
+RESTART:
+ if ((mp->cur_cmd<min_primary_command)||
+ (mp->cur_cmd>max_primary_command) )
+ mp_bad_exp(mp, "An");
+@.An expression...@>
+ mp_scan_tertiary(mp);
+CONTINUE:
+ if ( mp->cur_cmd<=max_expression_command )
+ if ( mp->cur_cmd>=min_expression_command ) {
+ if ( (mp->cur_cmd!=equals)||(my_var_flag!=assignment) ) {
+ p=mp_stash_cur_exp(mp); c=mp->cur_mod; d=mp->cur_cmd;
+ if ( d==expression_tertiary_macro ) {
+ mac_name=mp->cur_sym; add_mac_ref(c);
+ }
+ if ( (d<ampersand)||((d==ampersand)&&
+ ((type(p)==mp_pair_type)||(type(p)==mp_path_type))) ) {
+ @<Scan a path construction operation;
+ but |return| if |p| has the wrong type@>;
+ } else {
+ mp_get_x_next(mp); mp_scan_tertiary(mp);
+ if ( d!=expression_tertiary_macro ) {
+ mp_do_binary(mp, p,c);
+ } else {
+ mp_back_input(mp); mp_binary_mac(mp, p,c,mac_name);
+ decr(ref_count(c)); mp_get_x_next(mp);
+ goto RESTART;
+ }
+ }
+ goto CONTINUE;
+ }
+ }
+}
+
+@ The reader should review the data structure conventions for paths before
+hoping to understand the next part of this code.
+
+@<Scan a path construction operation...@>=
+{
+ cycle_hit=false;
+ @<Convert the left operand, |p|, into a partial path ending at~|q|;
+ but |return| if |p| doesn't have a suitable type@>;
+CONTINUE_PATH:
+ @<Determine the path join parameters;
+ but |goto finish_path| if there's only a direction specifier@>;
+ if ( mp->cur_cmd==cycle ) {
+ @<Get ready to close a cycle@>;
+ } else {
+ mp_scan_tertiary(mp);
+ @<Convert the right operand, |cur_exp|,
+ into a partial path from |pp| to~|qq|@>;
+ }
+ @<Join the partial paths and reset |p| and |q| to the head and tail
+ of the result@>;
+ if ( mp->cur_cmd>=min_expression_command )
+ if ( mp->cur_cmd<=ampersand ) if ( ! cycle_hit ) goto CONTINUE_PATH;
+FINISH_PATH:
+ @<Choose control points for the path and put the result into |cur_exp|@>;
+}
+
+@ @<Convert the left operand, |p|, into a partial path ending at~|q|...@>=
+{
+ mp_unstash_cur_exp(mp, p);
+ if ( mp->cur_type==mp_pair_type ) p=mp_new_knot(mp);
+ else if ( mp->cur_type==mp_path_type ) p=mp->cur_exp;
+ else return;
+ q=p;
+ while ( link(q)!=p ) q=link(q);
+ if ( left_type(p)!=mp_endpoint ) { /* open up a cycle */
+ r=mp_copy_knot(mp, p); link(q)=r; q=r;
+ }
+ left_type(p)=mp_open; right_type(q)=mp_open;
+}
+
+@ A pair of numeric values is changed into a knot node for a one-point path
+when \MP\ discovers that the pair is part of a path.
+
+@c @<Declare the procedure called |known_pair|@>
+pointer mp_new_knot (MP mp) { /* convert a pair to a knot with two endpoints */
+ pointer q; /* the new node */
+ q=mp_get_node(mp, knot_node_size); left_type(q)=mp_endpoint;
+ right_type(q)=mp_endpoint; originator(q)=mp_metapost_user; link(q)=q;
+ mp_known_pair(mp); x_coord(q)=mp->cur_x; y_coord(q)=mp->cur_y;
+ return q;
+}
+
+@ The |known_pair| subroutine sets |cur_x| and |cur_y| to the components
+of the current expression, assuming that the current expression is a
+pair of known numerics. Unknown components are zeroed, and the
+current expression is flushed.
+
+@<Declare the procedure called |known_pair|@>=
+void mp_known_pair (MP mp) {
+ pointer p; /* the pair node */
+ if ( mp->cur_type!=mp_pair_type ) {
+ exp_err("Undefined coordinates have been replaced by (0,0)");
+@.Undefined coordinates...@>
+ help5("I need x and y numbers for this part of the path.")
+ ("The value I found (see above) was no good;")
+ ("so I'll try to keep going by using zero instead.")
+ ("(Chapter 27 of The METAFONTbook explains that")
+@:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
+ ("you might want to type `I ??" "?' now.)");
+ mp_put_get_flush_error(mp, 0); mp->cur_x=0; mp->cur_y=0;
+ } else {
+ p=value(mp->cur_exp);
+ @<Make sure that both |x| and |y| parts of |p| are known;
+ copy them into |cur_x| and |cur_y|@>;
+ mp_flush_cur_exp(mp, 0);
+ }
+}
+
+@ @<Make sure that both |x| and |y| parts of |p| are known...@>=
+if ( type(x_part_loc(p))==mp_known ) {
+ mp->cur_x=value(x_part_loc(p));
+} else {
+ mp_disp_err(mp, x_part_loc(p),
+ "Undefined x coordinate has been replaced by 0");
+@.Undefined coordinates...@>
+ help5("I need a `known' x value for this part of the path.")
+ ("The value I found (see above) was no good;")
+ ("so I'll try to keep going by using zero instead.")
+ ("(Chapter 27 of The METAFONTbook explains that")
+@:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
+ ("you might want to type `I ??" "?' now.)");
+ mp_put_get_error(mp); mp_recycle_value(mp, x_part_loc(p)); mp->cur_x=0;
+}
+if ( type(y_part_loc(p))==mp_known ) {
+ mp->cur_y=value(y_part_loc(p));
+} else {
+ mp_disp_err(mp, y_part_loc(p),
+ "Undefined y coordinate has been replaced by 0");
+ help5("I need a `known' y value for this part of the path.")
+ ("The value I found (see above) was no good;")
+ ("so I'll try to keep going by using zero instead.")
+ ("(Chapter 27 of The METAFONTbook explains that")
+ ("you might want to type `I ??" "?' now.)");
+ mp_put_get_error(mp); mp_recycle_value(mp, y_part_loc(p)); mp->cur_y=0;
+}
+
+@ At this point |cur_cmd| is either |ampersand|, |left_brace|, or |path_join|.
+
+@<Determine the path join parameters...@>=
+if ( mp->cur_cmd==left_brace ) {
+ @<Put the pre-join direction information into node |q|@>;
+}
+d=mp->cur_cmd;
+if ( d==path_join ) {
+ @<Determine the tension and/or control points@>;
+} else if ( d!=ampersand ) {
+ goto FINISH_PATH;
+}
+mp_get_x_next(mp);
+if ( mp->cur_cmd==left_brace ) {
+ @<Put the post-join direction information into |x| and |t|@>;
+} else if ( right_type(q)!=mp_explicit ) {
+ t=mp_open; x=0;
+}
+
+@ The |scan_direction| subroutine looks at the directional information
+that is enclosed in braces, and also scans ahead to the following character.
+A type code is returned, either |open| (if the direction was $(0,0)$),
+or |curl| (if the direction was a curl of known value |cur_exp|), or
+|given| (if the direction is given by the |angle| value that now
+appears in |cur_exp|).
+
+There's nothing difficult about this subroutine, but the program is rather
+lengthy because a variety of potential errors need to be nipped in the bud.
+
+@c small_number mp_scan_direction (MP mp) {
+ int t; /* the type of information found */
+ scaled x; /* an |x| coordinate */
+ mp_get_x_next(mp);
+ if ( mp->cur_cmd==curl_command ) {
+ @<Scan a curl specification@>;
+ } else {
+ @<Scan a given direction@>;
+ }
+ if ( mp->cur_cmd!=right_brace ) {
+ mp_missing_err(mp, "}");
+@.Missing `\char`\}'@>
+ help3("I've scanned a direction spec for part of a path,")
+ ("so a right brace should have come next.")
+ ("I shall pretend that one was there.");
+ mp_back_error(mp);
+ }
+ mp_get_x_next(mp);
+ return t;
+}
+
+@ @<Scan a curl specification@>=
+{ mp_get_x_next(mp); mp_scan_expression(mp);
+if ( (mp->cur_type!=mp_known)||(mp->cur_exp<0) ){
+ exp_err("Improper curl has been replaced by 1");
+@.Improper curl@>
+ help1("A curl must be a known, nonnegative number.");
+ mp_put_get_flush_error(mp, unity);
+}
+t=mp_curl;
+}
+
+@ @<Scan a given direction@>=
+{ mp_scan_expression(mp);
+ if ( mp->cur_type>mp_pair_type ) {
+ @<Get given directions separated by commas@>;
+ } else {
+ mp_known_pair(mp);
+ }
+ if ( (mp->cur_x==0)&&(mp->cur_y==0) ) t=mp_open;
+ else { t=mp_given; mp->cur_exp=mp_n_arg(mp, mp->cur_x,mp->cur_y);}
+}
+
+@ @<Get given directions separated by commas@>=
+{
+ if ( mp->cur_type!=mp_known ) {
+ exp_err("Undefined x coordinate has been replaced by 0");
+@.Undefined coordinates...@>
+ help5("I need a `known' x value for this part of the path.")
+ ("The value I found (see above) was no good;")
+ ("so I'll try to keep going by using zero instead.")
+ ("(Chapter 27 of The METAFONTbook explains that")
+@:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
+ ("you might want to type `I ??" "?' now.)");
+ mp_put_get_flush_error(mp, 0);
+ }
+ x=mp->cur_exp;
+ if ( mp->cur_cmd!=comma ) {
+ mp_missing_err(mp, ",");
+@.Missing `,'@>
+ help2("I've got the x coordinate of a path direction;")
+ ("will look for the y coordinate next.");
+ mp_back_error(mp);
+ }
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type!=mp_known ) {
+ exp_err("Undefined y coordinate has been replaced by 0");
+ help5("I need a `known' y value for this part of the path.")
+ ("The value I found (see above) was no good;")
+ ("so I'll try to keep going by using zero instead.")
+ ("(Chapter 27 of The METAFONTbook explains that")
+ ("you might want to type `I ??" "?' now.)");
+ mp_put_get_flush_error(mp, 0);
+ }
+ mp->cur_y=mp->cur_exp; mp->cur_x=x;
+}
+
+@ At this point |right_type(q)| is usually |open|, but it may have been
+set to some other value by a previous operation. We must maintain
+the value of |right_type(q)| in cases such as
+`\.{..\{curl2\}z\{0,0\}..}'.
+
+@<Put the pre-join...@>=
+{
+ t=mp_scan_direction(mp);
+ if ( t!=mp_open ) {
+ right_type(q)=t; right_given(q)=mp->cur_exp;
+ if ( left_type(q)==mp_open ) {
+ left_type(q)=t; left_given(q)=mp->cur_exp;
+ } /* note that |left_given(q)=left_curl(q)| */
+ }
+}
+
+@ Since |left_tension| and |left_y| share the same position in knot nodes,
+and since |left_given| is similarly equivalent to |left_x|, we use
+|x| and |y| to hold the given direction and tension information when
+there are no explicit control points.
+
+@<Put the post-join...@>=
+{
+ t=mp_scan_direction(mp);
+ if ( right_type(q)!=mp_explicit ) x=mp->cur_exp;
+ else t=mp_explicit; /* the direction information is superfluous */
+}
+
+@ @<Determine the tension and/or...@>=
+{
+ mp_get_x_next(mp);
+ if ( mp->cur_cmd==tension ) {
+ @<Set explicit tensions@>;
+ } else if ( mp->cur_cmd==controls ) {
+ @<Set explicit control points@>;
+ } else {
+ right_tension(q)=unity; y=unity; mp_back_input(mp); /* default tension */
+ goto DONE;
+ };
+ if ( mp->cur_cmd!=path_join ) {
+ mp_missing_err(mp, "..");
+@.Missing `..'@>
+ help1("A path join command should end with two dots.");
+ mp_back_error(mp);
+ }
+DONE:
+ ;
+}
+
+@ @<Set explicit tensions@>=
+{
+ mp_get_x_next(mp); y=mp->cur_cmd;
+ if ( mp->cur_cmd==at_least ) mp_get_x_next(mp);
+ mp_scan_primary(mp);
+ @<Make sure that the current expression is a valid tension setting@>;
+ if ( y==at_least ) negate(mp->cur_exp);
+ right_tension(q)=mp->cur_exp;
+ if ( mp->cur_cmd==and_command ) {
+ mp_get_x_next(mp); y=mp->cur_cmd;
+ if ( mp->cur_cmd==at_least ) mp_get_x_next(mp);
+ mp_scan_primary(mp);
+ @<Make sure that the current expression is a valid tension setting@>;
+ if ( y==at_least ) negate(mp->cur_exp);
+ }
+ y=mp->cur_exp;
+}
+
+@ @d min_tension three_quarter_unit
+
+@<Make sure that the current expression is a valid tension setting@>=
+if ( (mp->cur_type!=mp_known)||(mp->cur_exp<min_tension) ) {
+ exp_err("Improper tension has been set to 1");
+@.Improper tension@>
+ help1("The expression above should have been a number >=3/4.");
+ mp_put_get_flush_error(mp, unity);
+}
+
+@ @<Set explicit control points@>=
+{
+ right_type(q)=mp_explicit; t=mp_explicit; mp_get_x_next(mp); mp_scan_primary(mp);
+ mp_known_pair(mp); right_x(q)=mp->cur_x; right_y(q)=mp->cur_y;
+ if ( mp->cur_cmd!=and_command ) {
+ x=right_x(q); y=right_y(q);
+ } else {
+ mp_get_x_next(mp); mp_scan_primary(mp);
+ mp_known_pair(mp); x=mp->cur_x; y=mp->cur_y;
+ }
+}
+
+@ @<Convert the right operand, |cur_exp|, into a partial path...@>=
+{
+ if ( mp->cur_type!=mp_path_type ) pp=mp_new_knot(mp);
+ else pp=mp->cur_exp;
+ qq=pp;
+ while ( link(qq)!=pp ) qq=link(qq);
+ if ( left_type(pp)!=mp_endpoint ) { /* open up a cycle */
+ r=mp_copy_knot(mp, pp); link(qq)=r; qq=r;
+ }
+ left_type(pp)=mp_open; right_type(qq)=mp_open;
+}
+
+@ If a person tries to define an entire path by saying `\.{(x,y)\&cycle}',
+we silently change the specification to `\.{(x,y)..cycle}', since a cycle
+shouldn't have length zero.
+
+@<Get ready to close a cycle@>=
+{
+ cycle_hit=true; mp_get_x_next(mp); pp=p; qq=p;
+ if ( d==ampersand ) if ( p==q ) {
+ d=path_join; right_tension(q)=unity; y=unity;
+ }
+}
+
+@ @<Join the partial paths and reset |p| and |q|...@>=
+{
+if ( d==ampersand ) {
+ if ( (x_coord(q)!=x_coord(pp))||(y_coord(q)!=y_coord(pp)) ) {
+ print_err("Paths don't touch; `&' will be changed to `..'");
+@.Paths don't touch@>
+ help3("When you join paths `p&q', the ending point of p")
+ ("must be exactly equal to the starting point of q.")
+ ("So I'm going to pretend that you said `p..q' instead.");
+ mp_put_get_error(mp); d=path_join; right_tension(q)=unity; y=unity;
+ }
+}
+@<Plug an opening in |right_type(pp)|, if possible@>;
+if ( d==ampersand ) {
+ @<Splice independent paths together@>;
+} else {
+ @<Plug an opening in |right_type(q)|, if possible@>;
+ link(q)=pp; left_y(pp)=y;
+ if ( t!=mp_open ) { left_x(pp)=x; left_type(pp)=t; };
+}
+q=qq;
+}
+
+@ @<Plug an opening in |right_type(q)|...@>=
+if ( right_type(q)==mp_open ) {
+ if ( (left_type(q)==mp_curl)||(left_type(q)==mp_given) ) {
+ right_type(q)=left_type(q); right_given(q)=left_given(q);
+ }
+}
+
+@ @<Plug an opening in |right_type(pp)|...@>=
+if ( right_type(pp)==mp_open ) {
+ if ( (t==mp_curl)||(t==mp_given) ) {
+ right_type(pp)=t; right_given(pp)=x;
+ }
+}
+
+@ @<Splice independent paths together@>=
+{
+ if ( left_type(q)==mp_open ) if ( right_type(q)==mp_open ) {
+ left_type(q)=mp_curl; left_curl(q)=unity;
+ }
+ if ( right_type(pp)==mp_open ) if ( t==mp_open ) {
+ right_type(pp)=mp_curl; right_curl(pp)=unity;
+ }
+ right_type(q)=right_type(pp); link(q)=link(pp);
+ right_x(q)=right_x(pp); right_y(q)=right_y(pp);
+ mp_free_node(mp, pp,knot_node_size);
+ if ( qq==pp ) qq=q;
+}
+
+@ @<Choose control points for the path...@>=
+if ( cycle_hit ) {
+ if ( d==ampersand ) p=q;
+} else {
+ left_type(p)=mp_endpoint;
+ if ( right_type(p)==mp_open ) {
+ right_type(p)=mp_curl; right_curl(p)=unity;
+ }
+ right_type(q)=mp_endpoint;
+ if ( left_type(q)==mp_open ) {
+ left_type(q)=mp_curl; left_curl(q)=unity;
+ }
+ link(q)=p;
+}
+mp_make_choices(mp, p);
+mp->cur_type=mp_path_type; mp->cur_exp=p
+
+@ Finally, we sometimes need to scan an expression whose value is
+supposed to be either |true_code| or |false_code|.
+
+@<Declare the basic parsing subroutines@>=
+void mp_get_boolean (MP mp) {
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type!=mp_boolean_type ) {
+ exp_err("Undefined condition will be treated as `false'");
+@.Undefined condition...@>
+ help2("The expression shown above should have had a definite")
+ ("true-or-false value. I'm changing it to `false'.");
+ mp_put_get_flush_error(mp, false_code); mp->cur_type=mp_boolean_type;
+ }
+}
+
+@* \[39] Doing the operations.
+The purpose of parsing is primarily to permit people to avoid piles of
+parentheses. But the real work is done after the structure of an expression
+has been recognized; that's when new expressions are generated. We
+turn now to the guts of \MP, which handles individual operators that
+have come through the parsing mechanism.
+
+We'll start with the easy ones that take no operands, then work our way
+up to operators with one and ultimately two arguments. In other words,
+we will write the three procedures |do_nullary|, |do_unary|, and |do_binary|
+that are invoked periodically by the expression scanners.
+
+First let's make sure that all of the primitive operators are in the
+hash table. Although |scan_primary| and its relatives made use of the
+\\{cmd} code for these operators, the \\{do} routines base everything
+on the \\{mod} code. For example, |do_binary| doesn't care whether the
+operation it performs is a |primary_binary| or |secondary_binary|, etc.
+
+@<Put each...@>=
+mp_primitive(mp, "true",nullary,true_code);
+@:true_}{\&{true} primitive@>
+mp_primitive(mp, "false",nullary,false_code);
+@:false_}{\&{false} primitive@>
+mp_primitive(mp, "nullpicture",nullary,null_picture_code);
+@:null_picture_}{\&{nullpicture} primitive@>
+mp_primitive(mp, "nullpen",nullary,null_pen_code);
+@:null_pen_}{\&{nullpen} primitive@>
+mp_primitive(mp, "jobname",nullary,job_name_op);
+@:job_name_}{\&{jobname} primitive@>
+mp_primitive(mp, "readstring",nullary,read_string_op);
+@:read_string_}{\&{readstring} primitive@>
+mp_primitive(mp, "pencircle",nullary,pen_circle);
+@:pen_circle_}{\&{pencircle} primitive@>
+mp_primitive(mp, "normaldeviate",nullary,normal_deviate);
+@:normal_deviate_}{\&{normaldeviate} primitive@>
+mp_primitive(mp, "readfrom",unary,read_from_op);
+@:read_from_}{\&{readfrom} primitive@>
+mp_primitive(mp, "closefrom",unary,close_from_op);
+@:close_from_}{\&{closefrom} primitive@>
+mp_primitive(mp, "odd",unary,odd_op);
+@:odd_}{\&{odd} primitive@>
+mp_primitive(mp, "known",unary,known_op);
+@:known_}{\&{known} primitive@>
+mp_primitive(mp, "unknown",unary,unknown_op);
+@:unknown_}{\&{unknown} primitive@>
+mp_primitive(mp, "not",unary,not_op);
+@:not_}{\&{not} primitive@>
+mp_primitive(mp, "decimal",unary,decimal);
+@:decimal_}{\&{decimal} primitive@>
+mp_primitive(mp, "reverse",unary,reverse);
+@:reverse_}{\&{reverse} primitive@>
+mp_primitive(mp, "makepath",unary,make_path_op);
+@:make_path_}{\&{makepath} primitive@>
+mp_primitive(mp, "makepen",unary,make_pen_op);
+@:make_pen_}{\&{makepen} primitive@>
+mp_primitive(mp, "oct",unary,oct_op);
+@:oct_}{\&{oct} primitive@>
+mp_primitive(mp, "hex",unary,hex_op);
+@:hex_}{\&{hex} primitive@>
+mp_primitive(mp, "ASCII",unary,ASCII_op);
+@:ASCII_}{\&{ASCII} primitive@>
+mp_primitive(mp, "char",unary,char_op);
+@:char_}{\&{char} primitive@>
+mp_primitive(mp, "length",unary,length_op);
+@:length_}{\&{length} primitive@>
+mp_primitive(mp, "turningnumber",unary,turning_op);
+@:turning_number_}{\&{turningnumber} primitive@>
+mp_primitive(mp, "xpart",unary,x_part);
+@:x_part_}{\&{xpart} primitive@>
+mp_primitive(mp, "ypart",unary,y_part);
+@:y_part_}{\&{ypart} primitive@>
+mp_primitive(mp, "xxpart",unary,xx_part);
+@:xx_part_}{\&{xxpart} primitive@>
+mp_primitive(mp, "xypart",unary,xy_part);
+@:xy_part_}{\&{xypart} primitive@>
+mp_primitive(mp, "yxpart",unary,yx_part);
+@:yx_part_}{\&{yxpart} primitive@>
+mp_primitive(mp, "yypart",unary,yy_part);
+@:yy_part_}{\&{yypart} primitive@>
+mp_primitive(mp, "redpart",unary,red_part);
+@:red_part_}{\&{redpart} primitive@>
+mp_primitive(mp, "greenpart",unary,green_part);
+@:green_part_}{\&{greenpart} primitive@>
+mp_primitive(mp, "bluepart",unary,blue_part);
+@:blue_part_}{\&{bluepart} primitive@>
+mp_primitive(mp, "cyanpart",unary,cyan_part);
+@:cyan_part_}{\&{cyanpart} primitive@>
+mp_primitive(mp, "magentapart",unary,magenta_part);
+@:magenta_part_}{\&{magentapart} primitive@>
+mp_primitive(mp, "yellowpart",unary,yellow_part);
+@:yellow_part_}{\&{yellowpart} primitive@>
+mp_primitive(mp, "blackpart",unary,black_part);
+@:black_part_}{\&{blackpart} primitive@>
+mp_primitive(mp, "greypart",unary,grey_part);
+@:grey_part_}{\&{greypart} primitive@>
+mp_primitive(mp, "colormodel",unary,color_model_part);
+@:color_model_part_}{\&{colormodel} primitive@>
+mp_primitive(mp, "fontpart",unary,font_part);
+@:font_part_}{\&{fontpart} primitive@>
+mp_primitive(mp, "textpart",unary,text_part);
+@:text_part_}{\&{textpart} primitive@>
+mp_primitive(mp, "pathpart",unary,path_part);
+@:path_part_}{\&{pathpart} primitive@>
+mp_primitive(mp, "penpart",unary,pen_part);
+@:pen_part_}{\&{penpart} primitive@>
+mp_primitive(mp, "dashpart",unary,dash_part);
+@:dash_part_}{\&{dashpart} primitive@>
+mp_primitive(mp, "sqrt",unary,sqrt_op);
+@:sqrt_}{\&{sqrt} primitive@>
+mp_primitive(mp, "mexp",unary,m_exp_op);
+@:m_exp_}{\&{mexp} primitive@>
+mp_primitive(mp, "mlog",unary,m_log_op);
+@:m_log_}{\&{mlog} primitive@>
+mp_primitive(mp, "sind",unary,sin_d_op);
+@:sin_d_}{\&{sind} primitive@>
+mp_primitive(mp, "cosd",unary,cos_d_op);
+@:cos_d_}{\&{cosd} primitive@>
+mp_primitive(mp, "floor",unary,floor_op);
+@:floor_}{\&{floor} primitive@>
+mp_primitive(mp, "uniformdeviate",unary,uniform_deviate);
+@:uniform_deviate_}{\&{uniformdeviate} primitive@>
+mp_primitive(mp, "charexists",unary,char_exists_op);
+@:char_exists_}{\&{charexists} primitive@>
+mp_primitive(mp, "fontsize",unary,font_size);
+@:font_size_}{\&{fontsize} primitive@>
+mp_primitive(mp, "llcorner",unary,ll_corner_op);
+@:ll_corner_}{\&{llcorner} primitive@>
+mp_primitive(mp, "lrcorner",unary,lr_corner_op);
+@:lr_corner_}{\&{lrcorner} primitive@>
+mp_primitive(mp, "ulcorner",unary,ul_corner_op);
+@:ul_corner_}{\&{ulcorner} primitive@>
+mp_primitive(mp, "urcorner",unary,ur_corner_op);
+@:ur_corner_}{\&{urcorner} primitive@>
+mp_primitive(mp, "arclength",unary,arc_length);
+@:arc_length_}{\&{arclength} primitive@>
+mp_primitive(mp, "angle",unary,angle_op);
+@:angle_}{\&{angle} primitive@>
+mp_primitive(mp, "cycle",cycle,cycle_op);
+@:cycle_}{\&{cycle} primitive@>
+mp_primitive(mp, "stroked",unary,stroked_op);
+@:stroked_}{\&{stroked} primitive@>
+mp_primitive(mp, "filled",unary,filled_op);
+@:filled_}{\&{filled} primitive@>
+mp_primitive(mp, "textual",unary,textual_op);
+@:textual_}{\&{textual} primitive@>
+mp_primitive(mp, "clipped",unary,clipped_op);
+@:clipped_}{\&{clipped} primitive@>
+mp_primitive(mp, "bounded",unary,bounded_op);
+@:bounded_}{\&{bounded} primitive@>
+mp_primitive(mp, "+",plus_or_minus,plus);
+@:+ }{\.{+} primitive@>
+mp_primitive(mp, "-",plus_or_minus,minus);
+@:- }{\.{-} primitive@>
+mp_primitive(mp, "*",secondary_binary,times);
+@:* }{\.{*} primitive@>
+mp_primitive(mp, "/",slash,over); mp->eqtb[frozen_slash]=mp->eqtb[mp->cur_sym];
+@:/ }{\.{/} primitive@>
+mp_primitive(mp, "++",tertiary_binary,pythag_add);
+@:++_}{\.{++} primitive@>
+mp_primitive(mp, "+-+",tertiary_binary,pythag_sub);
+@:+-+_}{\.{+-+} primitive@>
+mp_primitive(mp, "or",tertiary_binary,or_op);
+@:or_}{\&{or} primitive@>
+mp_primitive(mp, "and",and_command,and_op);
+@:and_}{\&{and} primitive@>
+mp_primitive(mp, "<",expression_binary,less_than);
+@:< }{\.{<} primitive@>
+mp_primitive(mp, "<=",expression_binary,less_or_equal);
+@:<=_}{\.{<=} primitive@>
+mp_primitive(mp, ">",expression_binary,greater_than);
+@:> }{\.{>} primitive@>
+mp_primitive(mp, ">=",expression_binary,greater_or_equal);
+@:>=_}{\.{>=} primitive@>
+mp_primitive(mp, "=",equals,equal_to);
+@:= }{\.{=} primitive@>
+mp_primitive(mp, "<>",expression_binary,unequal_to);
+@:<>_}{\.{<>} primitive@>
+mp_primitive(mp, "substring",primary_binary,substring_of);
+@:substring_}{\&{substring} primitive@>
+mp_primitive(mp, "subpath",primary_binary,subpath_of);
+@:subpath_}{\&{subpath} primitive@>
+mp_primitive(mp, "directiontime",primary_binary,direction_time_of);
+@:direction_time_}{\&{directiontime} primitive@>
+mp_primitive(mp, "point",primary_binary,point_of);
+@:point_}{\&{point} primitive@>
+mp_primitive(mp, "precontrol",primary_binary,precontrol_of);
+@:precontrol_}{\&{precontrol} primitive@>
+mp_primitive(mp, "postcontrol",primary_binary,postcontrol_of);
+@:postcontrol_}{\&{postcontrol} primitive@>
+mp_primitive(mp, "penoffset",primary_binary,pen_offset_of);
+@:pen_offset_}{\&{penoffset} primitive@>
+mp_primitive(mp, "arctime",primary_binary,arc_time_of);
+@:arc_time_of_}{\&{arctime} primitive@>
+mp_primitive(mp, "mpversion",nullary,mp_version);
+@:mp_verison_}{\&{mpversion} primitive@>
+mp_primitive(mp, "&",ampersand,concatenate);
+@:!!!}{\.{\&} primitive@>
+mp_primitive(mp, "rotated",secondary_binary,rotated_by);
+@:rotated_}{\&{rotated} primitive@>
+mp_primitive(mp, "slanted",secondary_binary,slanted_by);
+@:slanted_}{\&{slanted} primitive@>
+mp_primitive(mp, "scaled",secondary_binary,scaled_by);
+@:scaled_}{\&{scaled} primitive@>
+mp_primitive(mp, "shifted",secondary_binary,shifted_by);
+@:shifted_}{\&{shifted} primitive@>
+mp_primitive(mp, "transformed",secondary_binary,transformed_by);
+@:transformed_}{\&{transformed} primitive@>
+mp_primitive(mp, "xscaled",secondary_binary,x_scaled);
+@:x_scaled_}{\&{xscaled} primitive@>
+mp_primitive(mp, "yscaled",secondary_binary,y_scaled);
+@:y_scaled_}{\&{yscaled} primitive@>
+mp_primitive(mp, "zscaled",secondary_binary,z_scaled);
+@:z_scaled_}{\&{zscaled} primitive@>
+mp_primitive(mp, "infont",secondary_binary,in_font);
+@:in_font_}{\&{infont} primitive@>
+mp_primitive(mp, "intersectiontimes",tertiary_binary,intersect);
+@:intersection_times_}{\&{intersectiontimes} primitive@>
+mp_primitive(mp, "envelope",primary_binary,envelope_of);
+@:envelope_}{\&{envelope} primitive@>
+
+@ @<Cases of |print_cmd...@>=
+case nullary:
+case unary:
+case primary_binary:
+case secondary_binary:
+case tertiary_binary:
+case expression_binary:
+case cycle:
+case plus_or_minus:
+case slash:
+case ampersand:
+case equals:
+case and_command:
+ mp_print_op(mp, m);
+ break;
+
+@ OK, let's look at the simplest \\{do} procedure first.
+
+@c @<Declare nullary action procedure@>
+void mp_do_nullary (MP mp,quarterword c) {
+ check_arith;
+ if ( mp->internal[mp_tracing_commands]>two )
+ mp_show_cmd_mod(mp, nullary,c);
+ switch (c) {
+ case true_code: case false_code:
+ mp->cur_type=mp_boolean_type; mp->cur_exp=c;
+ break;
+ case null_picture_code:
+ mp->cur_type=mp_picture_type;
+ mp->cur_exp=mp_get_node(mp, edge_header_size);
+ mp_init_edges(mp, mp->cur_exp);
+ break;
+ case null_pen_code:
+ mp->cur_type=mp_pen_type; mp->cur_exp=mp_get_pen_circle(mp, 0);
+ break;
+ case normal_deviate:
+ mp->cur_type=mp_known; mp->cur_exp=mp_norm_rand(mp);
+ break;
+ case pen_circle:
+ mp->cur_type=mp_pen_type; mp->cur_exp=mp_get_pen_circle(mp, unity);
+ break;
+ case job_name_op:
+ if ( mp->job_name==NULL ) mp_open_log_file(mp);
+ mp->cur_type=mp_string_type; mp->cur_exp=rts(mp->job_name);
+ break;
+ case mp_version:
+ mp->cur_type=mp_string_type;
+ mp->cur_exp=intern(metapost_version) ;
+ break;
+ case read_string_op:
+ @<Read a string from the terminal@>;
+ break;
+ } /* there are no other cases */
+ check_arith;
+}
+
+@ @<Read a string...@>=
+{
+ if ( mp->interaction<=mp_nonstop_mode )
+ mp_fatal_error(mp, "*** (cannot readstring in nonstop modes)");
+ mp_begin_file_reading(mp); name=is_read;
+ limit=start; prompt_input("");
+ mp_finish_read(mp);
+}
+
+@ @<Declare nullary action procedure@>=
+void mp_finish_read (MP mp) { /* copy |buffer| line to |cur_exp| */
+ size_t k;
+ str_room((int)mp->last-start);
+ for (k=start;k<=mp->last-1;k++) {
+ append_char(mp->buffer[k]);
+ }
+ mp_end_file_reading(mp); mp->cur_type=mp_string_type;
+ mp->cur_exp=mp_make_string(mp);
+}
+
+@ Things get a bit more interesting when there's an operand. The
+operand to |do_unary| appears in |cur_type| and |cur_exp|.
+
+@c @<Declare unary action procedures@>
+void mp_do_unary (MP mp,quarterword c) {
+ pointer p,q,r; /* for list manipulation */
+ integer x; /* a temporary register */
+ check_arith;
+ if ( mp->internal[mp_tracing_commands]>two )
+ @<Trace the current unary operation@>;
+ switch (c) {
+ case plus:
+ if ( mp->cur_type<mp_color_type ) mp_bad_unary(mp, plus);
+ break;
+ case minus:
+ @<Negate the current expression@>;
+ break;
+ @<Additional cases of unary operators@>;
+ } /* there are no other cases */
+ check_arith;
+}
+
+@ The |nice_pair| function returns |true| if both components of a pair
+are known.
+
+@<Declare unary action procedures@>=
+boolean mp_nice_pair (MP mp,integer p, quarterword t) {
+ if ( t==mp_pair_type ) {
+ p=value(p);
+ if ( type(x_part_loc(p))==mp_known )
+ if ( type(y_part_loc(p))==mp_known )
+ return true;
+ }
+ return false;
+}
+
+@ The |nice_color_or_pair| function is analogous except that it also accepts
+fully known colors.
+
+@<Declare unary action procedures@>=
+boolean mp_nice_color_or_pair (MP mp,integer p, quarterword t) {
+ pointer q,r; /* for scanning the big node */
+ if ( (t!=mp_pair_type)&&(t!=mp_color_type)&&(t!=mp_cmykcolor_type) ) {
+ return false;
+ } else {
+ q=value(p);
+ r=q+mp->big_node_size[type(p)];
+ do {
+ r=r-2;
+ if ( type(r)!=mp_known )
+ return false;
+ } while (r!=q);
+ return true;
+ }
+}
+
+@ @<Declare unary action...@>=
+void mp_print_known_or_unknown_type (MP mp,small_number t, integer v) {
+ mp_print_char(mp, '(');
+ if ( t>mp_known ) mp_print(mp, "unknown numeric");
+ else { if ( (t==mp_pair_type)||(t==mp_color_type)||(t==mp_cmykcolor_type) )
+ if ( ! mp_nice_color_or_pair(mp, v,t) ) mp_print(mp, "unknown ");
+ mp_print_type(mp, t);
+ }
+ mp_print_char(mp, ')');
+}
+
+@ @<Declare unary action...@>=
+void mp_bad_unary (MP mp,quarterword c) {
+ exp_err("Not implemented: "); mp_print_op(mp, c);
+@.Not implemented...@>
+ mp_print_known_or_unknown_type(mp, mp->cur_type,mp->cur_exp);
+ help3("I'm afraid I don't know how to apply that operation to that")
+ ("particular type. Continue, and I'll simply return the")
+ ("argument (shown above) as the result of the operation.");
+ mp_put_get_error(mp);
+}
+
+@ @<Trace the current unary operation@>=
+{
+ mp_begin_diagnostic(mp); mp_print_nl(mp, "{");
+ mp_print_op(mp, c); mp_print_char(mp, '(');
+ mp_print_exp(mp, null,0); /* show the operand, but not verbosely */
+ mp_print(mp, ")}"); mp_end_diagnostic(mp, false);
+}
+
+@ Negation is easy except when the current expression
+is of type |independent|, or when it is a pair with one or more
+|independent| components.
+
+It is tempting to argue that the negative of an independent variable
+is an independent variable, hence we don't have to do anything when
+negating it. The fallacy is that other dependent variables pointing
+to the current expression must change the sign of their
+coefficients if we make no change to the current expression.
+
+Instead, we work around the problem by copying the current expression
+and recycling it afterwards (cf.~the |stash_in| routine).
+
+@<Negate the current expression@>=
+switch (mp->cur_type) {
+case mp_color_type:
+case mp_cmykcolor_type:
+case mp_pair_type:
+case mp_independent:
+ q=mp->cur_exp; mp_make_exp_copy(mp, q);
+ if ( mp->cur_type==mp_dependent ) {
+ mp_negate_dep_list(mp, dep_list(mp->cur_exp));
+ } else if ( mp->cur_type<=mp_pair_type ) { /* |mp_color_type| or |mp_pair_type| */
+ p=value(mp->cur_exp);
+ r=p+mp->big_node_size[mp->cur_type];
+ do {
+ r=r-2;
+ if ( type(r)==mp_known ) negate(value(r));
+ else mp_negate_dep_list(mp, dep_list(r));
+ } while (r!=p);
+ } /* if |cur_type=mp_known| then |cur_exp=0| */
+ mp_recycle_value(mp, q); mp_free_node(mp, q,value_node_size);
+ break;
+case mp_dependent:
+case mp_proto_dependent:
+ mp_negate_dep_list(mp, dep_list(mp->cur_exp));
+ break;
+case mp_known:
+ negate(mp->cur_exp);
+ break;
+default:
+ mp_bad_unary(mp, minus);
+ break;
+}
+
+@ @<Declare unary action...@>=
+void mp_negate_dep_list (MP mp,pointer p) {
+ while (1) {
+ negate(value(p));
+ if ( info(p)==null ) return;
+ p=link(p);
+ }
+}
+
+@ @<Additional cases of unary operators@>=
+case not_op:
+ if ( mp->cur_type!=mp_boolean_type ) mp_bad_unary(mp, not_op);
+ else mp->cur_exp=true_code+false_code-mp->cur_exp;
+ break;
+
+@ @d three_sixty_units 23592960 /* that's |360*unity| */
+@d boolean_reset(A) if ( (A) ) mp->cur_exp=true_code; else mp->cur_exp=false_code
+
+@<Additional cases of unary operators@>=
+case sqrt_op:
+case m_exp_op:
+case m_log_op:
+case sin_d_op:
+case cos_d_op:
+case floor_op:
+case uniform_deviate:
+case odd_op:
+case char_exists_op:
+ if ( mp->cur_type!=mp_known ) {
+ mp_bad_unary(mp, c);
+ } else {
+ switch (c) {
+ case sqrt_op:mp->cur_exp=mp_square_rt(mp, mp->cur_exp);break;
+ case m_exp_op:mp->cur_exp=mp_m_exp(mp, mp->cur_exp);break;
+ case m_log_op:mp->cur_exp=mp_m_log(mp, mp->cur_exp);break;
+ case sin_d_op:
+ case cos_d_op:
+ mp_n_sin_cos(mp, (mp->cur_exp % three_sixty_units)*16);
+ if ( c==sin_d_op ) mp->cur_exp=mp_round_fraction(mp, mp->n_sin);
+ else mp->cur_exp=mp_round_fraction(mp, mp->n_cos);
+ break;
+ case floor_op:mp->cur_exp=mp_floor_scaled(mp, mp->cur_exp);break;
+ case uniform_deviate:mp->cur_exp=mp_unif_rand(mp, mp->cur_exp);break;
+ case odd_op:
+ boolean_reset(odd(mp_round_unscaled(mp, mp->cur_exp)));
+ mp->cur_type=mp_boolean_type;
+ break;
+ case char_exists_op:
+ @<Determine if a character has been shipped out@>;
+ break;
+ } /* there are no other cases */
+ }
+ break;
+
+@ @<Additional cases of unary operators@>=
+case angle_op:
+ if ( mp_nice_pair(mp, mp->cur_exp,mp->cur_type) ) {
+ p=value(mp->cur_exp);
+ x=mp_n_arg(mp, value(x_part_loc(p)),value(y_part_loc(p)));
+ if ( x>=0 ) mp_flush_cur_exp(mp, (x+8)/ 16);
+ else mp_flush_cur_exp(mp, -((-x+8)/ 16));
+ } else {
+ mp_bad_unary(mp, angle_op);
+ }
+ break;
+
+@ If the current expression is a pair, but the context wants it to
+be a path, we call |pair_to_path|.
+
+@<Declare unary action...@>=
+void mp_pair_to_path (MP mp) {
+ mp->cur_exp=mp_new_knot(mp);
+ mp->cur_type=mp_path_type;
+}
+
+@
+@d pict_color_type(A) ((link(dummy_loc(mp->cur_exp))!=null) &&
+ (has_color(link(dummy_loc(mp->cur_exp)))) &&
+ (color_model(link(dummy_loc(mp->cur_exp)))==A))
+
+@<Additional cases of unary operators@>=
+case x_part:
+case y_part:
+ if ( (mp->cur_type==mp_pair_type)||(mp->cur_type==mp_transform_type) )
+ mp_take_part(mp, c);
+ else if ( mp->cur_type==mp_picture_type ) mp_take_pict_part(mp, c);
+ else mp_bad_unary(mp, c);
+ break;
+case xx_part:
+case xy_part:
+case yx_part:
+case yy_part:
+ if ( mp->cur_type==mp_transform_type ) mp_take_part(mp, c);
+ else if ( mp->cur_type==mp_picture_type ) mp_take_pict_part(mp, c);
+ else mp_bad_unary(mp, c);
+ break;
+case red_part:
+case green_part:
+case blue_part:
+ if ( mp->cur_type==mp_color_type ) mp_take_part(mp, c);
+ else if ( mp->cur_type==mp_picture_type ) {
+ if pict_color_type(mp_rgb_model) mp_take_pict_part(mp, c);
+ else mp_bad_color_part(mp, c);
+ }
+ else mp_bad_unary(mp, c);
+ break;
+case cyan_part:
+case magenta_part:
+case yellow_part:
+case black_part:
+ if ( mp->cur_type==mp_cmykcolor_type) mp_take_part(mp, c);
+ else if ( mp->cur_type==mp_picture_type ) {
+ if pict_color_type(mp_cmyk_model) mp_take_pict_part(mp, c);
+ else mp_bad_color_part(mp, c);
+ }
+ else mp_bad_unary(mp, c);
+ break;
+case grey_part:
+ if ( mp->cur_type==mp_known ) mp->cur_exp=value(c);
+ else if ( mp->cur_type==mp_picture_type ) {
+ if pict_color_type(mp_grey_model) mp_take_pict_part(mp, c);
+ else mp_bad_color_part(mp, c);
+ }
+ else mp_bad_unary(mp, c);
+ break;
+case color_model_part:
+ if ( mp->cur_type==mp_picture_type ) mp_take_pict_part(mp, c);
+ else mp_bad_unary(mp, c);
+ break;
+
+@ @<Declarations@>=
+void mp_bad_color_part(MP mp, quarterword c);
+
+@ @c
+void mp_bad_color_part(MP mp, quarterword c) {
+ pointer p; /* the big node */
+ p=link(dummy_loc(mp->cur_exp));
+ exp_err("Wrong picture color model: "); mp_print_op(mp, c);
+@.Wrong picture color model...@>
+ if (color_model(p)==mp_grey_model)
+ mp_print(mp, " of grey object");
+ else if (color_model(p)==mp_cmyk_model)
+ mp_print(mp, " of cmyk object");
+ else if (color_model(p)==mp_rgb_model)
+ mp_print(mp, " of rgb object");
+ else if (color_model(p)==mp_no_model)
+ mp_print(mp, " of marking object");
+ else
+ mp_print(mp," of defaulted object");
+ help3("You can only ask for the redpart, greenpart, bluepart of a rgb object,")
+ ("the cyanpart, magentapart, yellowpart or blackpart of a cmyk object, ")
+ ("or the greypart of a grey object. No mixing and matching, please.");
+ mp_error(mp);
+ if (c==black_part)
+ mp_flush_cur_exp(mp,unity);
+ else
+ mp_flush_cur_exp(mp,0);
+}
+
+@ In the following procedure, |cur_exp| points to a capsule, which points to
+a big node. We want to delete all but one part of the big node.
+
+@<Declare unary action...@>=
+void mp_take_part (MP mp,quarterword c) {
+ pointer p; /* the big node */
+ p=value(mp->cur_exp); value(temp_val)=p; type(temp_val)=mp->cur_type;
+ link(p)=temp_val; mp_free_node(mp, mp->cur_exp,value_node_size);
+ mp_make_exp_copy(mp, p+mp->sector_offset[c+mp_x_part_sector-x_part]);
+ mp_recycle_value(mp, temp_val);
+}
+
+@ @<Initialize table entries...@>=
+name_type(temp_val)=mp_capsule;
+
+@ @<Additional cases of unary operators@>=
+case font_part:
+case text_part:
+case path_part:
+case pen_part:
+case dash_part:
+ if ( mp->cur_type==mp_picture_type ) mp_take_pict_part(mp, c);
+ else mp_bad_unary(mp, c);
+ break;
+
+@ @<Declarations@>=
+void mp_scale_edges (MP mp);
+
+@ @<Declare unary action...@>=
+void mp_take_pict_part (MP mp,quarterword c) {
+ pointer p; /* first graphical object in |cur_exp| */
+ p=link(dummy_loc(mp->cur_exp));
+ if ( p!=null ) {
+ switch (c) {
+ case x_part: case y_part: case xx_part:
+ case xy_part: case yx_part: case yy_part:
+ if ( type(p)==mp_text_code ) mp_flush_cur_exp(mp, text_trans_part(p+c));
+ else goto NOT_FOUND;
+ break;
+ case red_part: case green_part: case blue_part:
+ if ( has_color(p) ) mp_flush_cur_exp(mp, obj_color_part(p+c));
+ else goto NOT_FOUND;
+ break;
+ case cyan_part: case magenta_part: case yellow_part:
+ case black_part:
+ if ( has_color(p) ) {
+ if ( color_model(p)==mp_uninitialized_model )
+ mp_flush_cur_exp(mp, unity);
+ else
+ mp_flush_cur_exp(mp, obj_color_part(p+c+(red_part-cyan_part)));
+ } else goto NOT_FOUND;
+ break;
+ case grey_part:
+ if ( has_color(p) )
+ mp_flush_cur_exp(mp, obj_color_part(p+c+(red_part-grey_part)));
+ else goto NOT_FOUND;
+ break;
+ case color_model_part:
+ if ( has_color(p) ) {
+ if ( color_model(p)==mp_uninitialized_model )
+ mp_flush_cur_exp(mp, mp->internal[mp_default_color_model]);
+ else
+ mp_flush_cur_exp(mp, color_model(p)*unity);
+ } else goto NOT_FOUND;
+ break;
+ @<Handle other cases in |take_pict_part| or |goto not_found|@>;
+ } /* all cases have been enumerated */
+ return;
+ };
+NOT_FOUND:
+ @<Convert the current expression to a null value appropriate
+ for |c|@>;
+}
+
+@ @<Handle other cases in |take_pict_part| or |goto not_found|@>=
+case text_part:
+ if ( type(p)!=mp_text_code ) goto NOT_FOUND;
+ else {
+ mp_flush_cur_exp(mp, text_p(p));
+ add_str_ref(mp->cur_exp);
+ mp->cur_type=mp_string_type;
+ };
+ break;
+case font_part:
+ if ( type(p)!=mp_text_code ) goto NOT_FOUND;
+ else {
+ mp_flush_cur_exp(mp, rts(mp->font_name[font_n(p)]));
+ add_str_ref(mp->cur_exp);
+ mp->cur_type=mp_string_type;
+ };
+ break;
+case path_part:
+ if ( type(p)==mp_text_code ) goto NOT_FOUND;
+ else if ( is_stop(p) ) mp_confusion(mp, "pict");
+@:this can't happen pict}{\quad pict@>
+ else {
+ mp_flush_cur_exp(mp, mp_copy_path(mp, path_p(p)));
+ mp->cur_type=mp_path_type;
+ }
+ break;
+case pen_part:
+ if ( ! has_pen(p) ) goto NOT_FOUND;
+ else {
+ if ( pen_p(p)==null ) goto NOT_FOUND;
+ else { mp_flush_cur_exp(mp, copy_pen(pen_p(p)));
+ mp->cur_type=mp_pen_type;
+ };
+ }
+ break;
+case dash_part:
+ if ( type(p)!=mp_stroked_code ) goto NOT_FOUND;
+ else { if ( dash_p(p)==null ) goto NOT_FOUND;
+ else { add_edge_ref(dash_p(p));
+ mp->se_sf=dash_scale(p);
+ mp->se_pic=dash_p(p);
+ mp_scale_edges(mp);
+ mp_flush_cur_exp(mp, mp->se_pic);
+ mp->cur_type=mp_picture_type;
+ };
+ }
+ break;
+
+@ Since |scale_edges| had to be declared |forward|, it had to be declared as a
+parameterless procedure even though it really takes two arguments and updates
+one of them. Hence the following globals are needed.
+
+@<Global...@>=
+pointer se_pic; /* edge header used and updated by |scale_edges| */
+scaled se_sf; /* the scale factor argument to |scale_edges| */
+
+@ @<Convert the current expression to a null value appropriate...@>=
+switch (c) {
+case text_part: case font_part:
+ mp_flush_cur_exp(mp, rts(""));
+ mp->cur_type=mp_string_type;
+ break;
+case path_part:
+ mp_flush_cur_exp(mp, mp_get_node(mp, knot_node_size));
+ left_type(mp->cur_exp)=mp_endpoint;
+ right_type(mp->cur_exp)=mp_endpoint;
+ link(mp->cur_exp)=mp->cur_exp;
+ x_coord(mp->cur_exp)=0;
+ y_coord(mp->cur_exp)=0;
+ originator(mp->cur_exp)=mp_metapost_user;
+ mp->cur_type=mp_path_type;
+ break;
+case pen_part:
+ mp_flush_cur_exp(mp, mp_get_pen_circle(mp, 0));
+ mp->cur_type=mp_pen_type;
+ break;
+case dash_part:
+ mp_flush_cur_exp(mp, mp_get_node(mp, edge_header_size));
+ mp_init_edges(mp, mp->cur_exp);
+ mp->cur_type=mp_picture_type;
+ break;
+default:
+ mp_flush_cur_exp(mp, 0);
+ break;
+}
+
+@ @<Additional cases of unary...@>=
+case char_op:
+ if ( mp->cur_type!=mp_known ) {
+ mp_bad_unary(mp, char_op);
+ } else {
+ mp->cur_exp=mp_round_unscaled(mp, mp->cur_exp) % 256;
+ mp->cur_type=mp_string_type;
+ if ( mp->cur_exp<0 ) mp->cur_exp=mp->cur_exp+256;
+ }
+ break;
+case decimal:
+ if ( mp->cur_type!=mp_known ) {
+ mp_bad_unary(mp, decimal);
+ } else {
+ mp->old_setting=mp->selector; mp->selector=new_string;
+ mp_print_scaled(mp, mp->cur_exp); mp->cur_exp=mp_make_string(mp);
+ mp->selector=mp->old_setting; mp->cur_type=mp_string_type;
+ }
+ break;
+case oct_op:
+case hex_op:
+case ASCII_op:
+ if ( mp->cur_type!=mp_string_type ) mp_bad_unary(mp, c);
+ else mp_str_to_num(mp, c);
+ break;
+case font_size:
+ if ( mp->cur_type!=mp_string_type ) mp_bad_unary(mp, font_size);
+ else @<Find the design size of the font whose name is |cur_exp|@>;
+ break;
+
+@ @<Declare unary action...@>=
+void mp_str_to_num (MP mp,quarterword c) { /* converts a string to a number */
+ integer n; /* accumulator */
+ ASCII_code m; /* current character */
+ pool_pointer k; /* index into |str_pool| */
+ int b; /* radix of conversion */
+ boolean bad_char; /* did the string contain an invalid digit? */
+ if ( c==ASCII_op ) {
+ if ( length(mp->cur_exp)==0 ) n=-1;
+ else n=mp->str_pool[mp->str_start[mp->cur_exp]];
+ } else {
+ if ( c==oct_op ) b=8; else b=16;
+ n=0; bad_char=false;
+ for (k=mp->str_start[mp->cur_exp];k<=str_stop(mp->cur_exp)-1;k++) {
+ m=mp->str_pool[k];
+ if ( (m>='0')&&(m<='9') ) m=m-'0';
+ else if ( (m>='A')&&(m<='F') ) m=m-'A'+10;
+ else if ( (m>='a')&&(m<='f') ) m=m-'a'+10;
+ else { bad_char=true; m=0; };
+ if ( m>=b ) { bad_char=true; m=0; };
+ if ( n<32768 / b ) n=n*b+m; else n=32767;
+ }
+ @<Give error messages if |bad_char| or |n>=4096|@>;
+ }
+ mp_flush_cur_exp(mp, n*unity);
+}
+
+@ @<Give error messages if |bad_char|...@>=
+if ( bad_char ) {
+ exp_err("String contains illegal digits");
+@.String contains illegal digits@>
+ if ( c==oct_op ) {
+ help1("I zeroed out characters that weren't in the range 0..7.");
+ } else {
+ help1("I zeroed out characters that weren't hex digits.");
+ }
+ mp_put_get_error(mp);
+}
+if ( (n>4095) ) {
+ if ( mp->internal[mp_warning_check]>0 ) {
+ print_err("Number too large (");
+ mp_print_int(mp, n); mp_print_char(mp, ')');
+@.Number too large@>
+ help2("I have trouble with numbers greater than 4095; watch out.")
+ ("(Set warningcheck:=0 to suppress this message.)");
+ mp_put_get_error(mp);
+ }
+}
+
+@ The length operation is somewhat unusual in that it applies to a variety
+of different types of operands.
+
+@<Additional cases of unary...@>=
+case length_op:
+ switch (mp->cur_type) {
+ case mp_string_type: mp_flush_cur_exp(mp, length(mp->cur_exp)*unity); break;
+ case mp_path_type: mp_flush_cur_exp(mp, mp_path_length(mp)); break;
+ case mp_known: mp->cur_exp=abs(mp->cur_exp); break;
+ case mp_picture_type: mp_flush_cur_exp(mp, mp_pict_length(mp)); break;
+ default:
+ if ( mp_nice_pair(mp, mp->cur_exp,mp->cur_type) )
+ mp_flush_cur_exp(mp, mp_pyth_add(mp,
+ value(x_part_loc(value(mp->cur_exp))),
+ value(y_part_loc(value(mp->cur_exp)))));
+ else mp_bad_unary(mp, c);
+ break;
+ }
+ break;
+
+@ @<Declare unary action...@>=
+scaled mp_path_length (MP mp) { /* computes the length of the current path */
+ scaled n; /* the path length so far */
+ pointer p; /* traverser */
+ p=mp->cur_exp;
+ if ( left_type(p)==mp_endpoint ) n=-unity; else n=0;
+ do { p=link(p); n=n+unity; } while (p!=mp->cur_exp);
+ return n;
+}
+
+@ @<Declare unary action...@>=
+scaled mp_pict_length (MP mp) {
+ /* counts interior components in picture |cur_exp| */
+ scaled n; /* the count so far */
+ pointer p; /* traverser */
+ n=0;
+ p=link(dummy_loc(mp->cur_exp));
+ if ( p!=null ) {
+ if ( is_start_or_stop(p) )
+ if ( mp_skip_1component(mp, p)==null ) p=link(p);
+ while ( p!=null ) {
+ skip_component(p) return n;
+ n=n+unity;
+ }
+ }
+ return n;
+}
+
+@ Implement |turningnumber|
+
+@<Additional cases of unary...@>=
+case turning_op:
+ if ( mp->cur_type==mp_pair_type ) mp_flush_cur_exp(mp, 0);
+ else if ( mp->cur_type!=mp_path_type ) mp_bad_unary(mp, turning_op);
+ else if ( left_type(mp->cur_exp)==mp_endpoint )
+ mp_flush_cur_exp(mp, 0); /* not a cyclic path */
+ else
+ mp_flush_cur_exp(mp, mp_turn_cycles_wrapper(mp, mp->cur_exp));
+ break;
+
+@ The function |an_angle| returns the value of the |angle| primitive, or $0$ if the
+argument is |origin|.
+
+@<Declare unary action...@>=
+angle mp_an_angle (MP mp,scaled xpar, scaled ypar) {
+ if ( (! ((xpar==0) && (ypar==0))) )
+ return mp_n_arg(mp, xpar,ypar);
+ return 0;
+}
+
+
+@ The actual turning number is (for the moment) computed in a C function
+that receives eight integers corresponding to the four controlling points,
+and returns a single angle. Besides those, we have to account for discrete
+moves at the actual points.
+
+@d floor(a) (a>=0 ? a : -(int)(-a))
+@d bezier_error (720<<20)+1
+@d sign(v) ((v)>0 ? 1 : ((v)<0 ? -1 : 0 ))
+@d print_roots(a)
+@d out ((double)(xo>>20))
+@d mid ((double)(xm>>20))
+@d in ((double)(xi>>20))
+@d divisor (256*256)
+@d double2angle(a) (int)floor(a*256.0*256.0*16.0)
+
+@<Declare unary action...@>=
+angle mp_bezier_slope(MP mp, integer AX,integer AY,integer BX,integer BY,
+ integer CX,integer CY,integer DX,integer DY);
+
+@ @c
+angle mp_bezier_slope(MP mp, integer AX,integer AY,integer BX,integer BY,
+ integer CX,integer CY,integer DX,integer DY) {
+ double a, b, c;
+ integer deltax,deltay;
+ double ax,ay,bx,by,cx,cy,dx,dy;
+ angle xi = 0, xo = 0, xm = 0;
+ double res = 0;
+ ax=AX/divisor; ay=AY/divisor;
+ bx=BX/divisor; by=BY/divisor;
+ cx=CX/divisor; cy=CY/divisor;
+ dx=DX/divisor; dy=DY/divisor;
+
+ deltax = (BX-AX); deltay = (BY-AY);
+ if (deltax==0 && deltay == 0) { deltax=(CX-AX); deltay=(CY-AY); }
+ if (deltax==0 && deltay == 0) { deltax=(DX-AX); deltay=(DY-AY); }
+ xi = mp_an_angle(mp,deltax,deltay);
+
+ deltax = (CX-BX); deltay = (CY-BY);
+ xm = mp_an_angle(mp,deltax,deltay);
+
+ deltax = (DX-CX); deltay = (DY-CY);
+ if (deltax==0 && deltay == 0) { deltax=(DX-BX); deltay=(DY-BY); }
+ if (deltax==0 && deltay == 0) { deltax=(DX-AX); deltay=(DY-AY); }
+ xo = mp_an_angle(mp,deltax,deltay);
+
+ a = (bx-ax)*(cy-by) - (cx-bx)*(by-ay); /* a = (bp-ap)x(cp-bp); */
+ b = (bx-ax)*(dy-cy) - (by-ay)*(dx-cx);; /* b = (bp-ap)x(dp-cp);*/
+ c = (cx-bx)*(dy-cy) - (dx-cx)*(cy-by); /* c = (cp-bp)x(dp-cp);*/
+
+ if ((a==0)&&(c==0)) {
+ res = (b==0 ? 0 : (out-in));
+ print_roots("no roots (a)");
+ } else if ((a==0)||(c==0)) {
+ if ((sign(b) == sign(a)) || (sign(b) == sign(c))) {
+ res = out-in; /* ? */
+ if (res<-180.0)
+ res += 360.0;
+ else if (res>180.0)
+ res -= 360.0;
+ print_roots("no roots (b)");
+ } else {
+ res = out-in; /* ? */
+ print_roots("one root (a)");
+ }
+ } else if ((sign(a)*sign(c))<0) {
+ res = out-in; /* ? */
+ if (res<-180.0)
+ res += 360.0;
+ else if (res>180.0)
+ res -= 360.0;
+ print_roots("one root (b)");
+ } else {
+ if (sign(a) == sign(b)) {
+ res = out-in; /* ? */
+ if (res<-180.0)
+ res += 360.0;
+ else if (res>180.0)
+ res -= 360.0;
+ print_roots("no roots (d)");
+ } else {
+ if ((b*b) == (4*a*c)) {
+ res = bezier_error;
+ print_roots("double root"); /* cusp */
+ } else if ((b*b) < (4*a*c)) {
+ res = out-in; /* ? */
+ if (res<=0.0 &&res>-180.0)
+ res += 360.0;
+ else if (res>=0.0 && res<180.0)
+ res -= 360.0;
+ print_roots("no roots (e)");
+ } else {
+ res = out-in;
+ if (res<-180.0)
+ res += 360.0;
+ else if (res>180.0)
+ res -= 360.0;
+ print_roots("two roots"); /* two inflections */
+ }
+ }
+ }
+ return double2angle(res);
+}
+
+@
+@d p_nextnext link(link(p))
+@d p_next link(p)
+@d seven_twenty_deg 05500000000 /* $720\cdot2^{20}$, represents $720^\circ$ */
+
+@<Declare unary action...@>=
+scaled mp_new_turn_cycles (MP mp,pointer c) {
+ angle res,ang; /* the angles of intermediate results */
+ scaled turns; /* the turn counter */
+ pointer p; /* for running around the path */
+ integer xp,yp; /* coordinates of next point */
+ integer x,y; /* helper coordinates */
+ angle in_angle,out_angle; /* helper angles */
+ int old_setting; /* saved |selector| setting */
+ res=0;
+ turns= 0;
+ p=c;
+ old_setting = mp->selector; mp->selector=term_only;
+ if ( mp->internal[mp_tracing_commands]>unity ) {
+ mp_begin_diagnostic(mp);
+ mp_print_nl(mp, "");
+ mp_end_diagnostic(mp, false);
+ }
+ do {
+ xp = x_coord(p_next); yp = y_coord(p_next);
+ ang = mp_bezier_slope(mp,x_coord(p), y_coord(p), right_x(p), right_y(p),
+ left_x(p_next), left_y(p_next), xp, yp);
+ if ( ang>seven_twenty_deg ) {
+ print_err("Strange path");
+ mp_error(mp);
+ mp->selector=old_setting;
+ return 0;
+ }
+ res = res + ang;
+ if ( res > one_eighty_deg ) {
+ res = res - three_sixty_deg;
+ turns = turns + unity;
+ }
+ if ( res <= -one_eighty_deg ) {
+ res = res + three_sixty_deg;
+ turns = turns - unity;
+ }
+ /* incoming angle at next point */
+ x = left_x(p_next); y = left_y(p_next);
+ if ( (xp==x)&&(yp==y) ) { x = right_x(p); y = right_y(p); };
+ if ( (xp==x)&&(yp==y) ) { x = x_coord(p); y = y_coord(p); };
+ in_angle = mp_an_angle(mp, xp - x, yp - y);
+ /* outgoing angle at next point */
+ x = right_x(p_next); y = right_y(p_next);
+ if ( (xp==x)&&(yp==y) ) { x = left_x(p_nextnext); y = left_y(p_nextnext); };
+ if ( (xp==x)&&(yp==y) ) { x = x_coord(p_nextnext); y = y_coord(p_nextnext); };
+ out_angle = mp_an_angle(mp, x - xp, y- yp);
+ ang = (out_angle - in_angle);
+ reduce_angle(ang);
+ if ( ang!=0 ) {
+ res = res + ang;
+ if ( res >= one_eighty_deg ) {
+ res = res - three_sixty_deg;
+ turns = turns + unity;
+ };
+ if ( res <= -one_eighty_deg ) {
+ res = res + three_sixty_deg;
+ turns = turns - unity;
+ };
+ };
+ p = link(p);
+ } while (p!=c);
+ mp->selector=old_setting;
+ return turns;
+}
+
+
+@ This code is based on Bogus\l{}av Jackowski's
+|emergency_turningnumber| macro, with some minor changes by Taco
+Hoekwater. The macro code looked more like this:
+{\obeylines
+vardef turning\_number primary p =
+~~save res, ang, turns;
+~~res := 0;
+~~if length p <= 2:
+~~~~if Angle ((point 0 of p) - (postcontrol 0 of p)) >= 0: 1 else: -1 fi
+~~else:
+~~~~for t = 0 upto length p-1 :
+~~~~~~angc := Angle ((point t+1 of p) - (point t of p))
+~~~~~~~~- Angle ((point t of p) - (point t-1 of p));
+~~~~~~if angc > 180: angc := angc - 360; fi;
+~~~~~~if angc < -180: angc := angc + 360; fi;
+~~~~~~res := res + angc;
+~~~~endfor;
+~~res/360
+~~fi
+enddef;}
+The general idea is to calculate only the sum of the angles of
+straight lines between the points, of a path, not worrying about cusps
+or self-intersections in the segments at all. If the segment is not
+well-behaved, the result is not necesarily correct. But the old code
+was not always correct either, and worse, it sometimes failed for
+well-behaved paths as well. All known bugs that were triggered by the
+original code no longer occur with this code, and it runs roughly 3
+times as fast because the algorithm is much simpler.
+
+@ It is possible to overflow the return value of the |turn_cycles|
+function when the path is sufficiently long and winding, but I am not
+going to bother testing for that. In any case, it would only return
+the looped result value, which is not a big problem.
+
+The macro code for the repeat loop was a bit nicer to look
+at than the pascal code, because it could use |point -1 of p|. In
+pascal, the fastest way to loop around the path is not to look
+backward once, but forward twice. These defines help hide the trick.
+
+@d p_to link(link(p))
+@d p_here link(p)
+@d p_from p
+
+@<Declare unary action...@>=
+scaled mp_turn_cycles (MP mp,pointer c) {
+ angle res,ang; /* the angles of intermediate results */
+ scaled turns; /* the turn counter */
+ pointer p; /* for running around the path */
+ res=0; turns= 0; p=c;
+ do {
+ ang = mp_an_angle (mp, x_coord(p_to) - x_coord(p_here),
+ y_coord(p_to) - y_coord(p_here))
+ - mp_an_angle (mp, x_coord(p_here) - x_coord(p_from),
+ y_coord(p_here) - y_coord(p_from));
+ reduce_angle(ang);
+ res = res + ang;
+ if ( res >= three_sixty_deg ) {
+ res = res - three_sixty_deg;
+ turns = turns + unity;
+ };
+ if ( res <= -three_sixty_deg ) {
+ res = res + three_sixty_deg;
+ turns = turns - unity;
+ };
+ p = link(p);
+ } while (p!=c);
+ return turns;
+}
+
+@ @<Declare unary action...@>=
+scaled mp_turn_cycles_wrapper (MP mp,pointer c) {
+ scaled nval,oval;
+ scaled saved_t_o; /* tracing\_online saved */
+ if ( (link(c)==c)||(link(link(c))==c) ) {
+ if ( mp_an_angle (mp, x_coord(c) - right_x(c), y_coord(c) - right_y(c)) > 0 )
+ return unity;
+ else
+ return -unity;
+ } else {
+ nval = mp_new_turn_cycles(mp, c);
+ oval = mp_turn_cycles(mp, c);
+ if ( nval!=oval ) {
+ saved_t_o=mp->internal[mp_tracing_online];
+ mp->internal[mp_tracing_online]=unity;
+ mp_begin_diagnostic(mp);
+ mp_print_nl (mp, "Warning: the turningnumber algorithms do not agree."
+ " The current computed value is ");
+ mp_print_scaled(mp, nval);
+ mp_print(mp, ", but the 'connect-the-dots' algorithm returned ");
+ mp_print_scaled(mp, oval);
+ mp_end_diagnostic(mp, false);
+ mp->internal[mp_tracing_online]=saved_t_o;
+ }
+ return nval;
+ }
+}
+
+@ @<Declare unary action...@>=
+scaled mp_count_turns (MP mp,pointer c) {
+ pointer p; /* a knot in envelope spec |c| */
+ integer t; /* total pen offset changes counted */
+ t=0; p=c;
+ do {
+ t=t+info(p)-zero_off;
+ p=link(p);
+ } while (p!=c);
+ return ((t / 3)*unity);
+}
+
+@ @d type_range(A,B) {
+ if ( (mp->cur_type>=(A)) && (mp->cur_type<=(B)) )
+ mp_flush_cur_exp(mp, true_code);
+ else mp_flush_cur_exp(mp, false_code);
+ mp->cur_type=mp_boolean_type;
+ }
+@d type_test(A) {
+ if ( mp->cur_type==(A) ) mp_flush_cur_exp(mp, true_code);
+ else mp_flush_cur_exp(mp, false_code);
+ mp->cur_type=mp_boolean_type;
+ }
+
+@<Additional cases of unary operators@>=
+case mp_boolean_type:
+ type_range(mp_boolean_type,mp_unknown_boolean); break;
+case mp_string_type:
+ type_range(mp_string_type,mp_unknown_string); break;
+case mp_pen_type:
+ type_range(mp_pen_type,mp_unknown_pen); break;
+case mp_path_type:
+ type_range(mp_path_type,mp_unknown_path); break;
+case mp_picture_type:
+ type_range(mp_picture_type,mp_unknown_picture); break;
+case mp_transform_type: case mp_color_type: case mp_cmykcolor_type:
+case mp_pair_type:
+ type_test(c); break;
+case mp_numeric_type:
+ type_range(mp_known,mp_independent); break;
+case known_op: case unknown_op:
+ mp_test_known(mp, c); break;
+
+@ @<Declare unary action procedures@>=
+void mp_test_known (MP mp,quarterword c) {
+ int b; /* is the current expression known? */
+ pointer p,q; /* locations in a big node */
+ b=false_code;
+ switch (mp->cur_type) {
+ case mp_vacuous: case mp_boolean_type: case mp_string_type:
+ case mp_pen_type: case mp_path_type: case mp_picture_type:
+ case mp_known:
+ b=true_code;
+ break;
+ case mp_transform_type:
+ case mp_color_type: case mp_cmykcolor_type: case mp_pair_type:
+ p=value(mp->cur_exp);
+ q=p+mp->big_node_size[mp->cur_type];
+ do {
+ q=q-2;
+ if ( type(q)!=mp_known )
+ goto DONE;
+ } while (q!=p);
+ b=true_code;
+ DONE:
+ break;
+ default:
+ break;
+ }
+ if ( c==known_op ) mp_flush_cur_exp(mp, b);
+ else mp_flush_cur_exp(mp, true_code+false_code-b);
+ mp->cur_type=mp_boolean_type;
+}
+
+@ @<Additional cases of unary operators@>=
+case cycle_op:
+ if ( mp->cur_type!=mp_path_type ) mp_flush_cur_exp(mp, false_code);
+ else if ( left_type(mp->cur_exp)!=mp_endpoint ) mp_flush_cur_exp(mp, true_code);
+ else mp_flush_cur_exp(mp, false_code);
+ mp->cur_type=mp_boolean_type;
+ break;
+
+@ @<Additional cases of unary operators@>=
+case arc_length:
+ if ( mp->cur_type==mp_pair_type ) mp_pair_to_path(mp);
+ if ( mp->cur_type!=mp_path_type ) mp_bad_unary(mp, arc_length);
+ else mp_flush_cur_exp(mp, mp_get_arc_length(mp, mp->cur_exp));
+ break;
+
+@ Here we use the fact that |c-filled_op+fill_code| is the desired graphical
+object |type|.
+@^data structure assumptions@>
+
+@<Additional cases of unary operators@>=
+case filled_op:
+case stroked_op:
+case textual_op:
+case clipped_op:
+case bounded_op:
+ if ( mp->cur_type!=mp_picture_type ) mp_flush_cur_exp(mp, false_code);
+ else if ( link(dummy_loc(mp->cur_exp))==null ) mp_flush_cur_exp(mp, false_code);
+ else if ( type(link(dummy_loc(mp->cur_exp)))==c+mp_fill_code-filled_op )
+ mp_flush_cur_exp(mp, true_code);
+ else mp_flush_cur_exp(mp, false_code);
+ mp->cur_type=mp_boolean_type;
+ break;
+
+@ @<Additional cases of unary operators@>=
+case make_pen_op:
+ if ( mp->cur_type==mp_pair_type ) mp_pair_to_path(mp);
+ if ( mp->cur_type!=mp_path_type ) mp_bad_unary(mp, make_pen_op);
+ else {
+ mp->cur_type=mp_pen_type;
+ mp->cur_exp=mp_make_pen(mp, mp->cur_exp,true);
+ };
+ break;
+case make_path_op:
+ if ( mp->cur_type!=mp_pen_type ) mp_bad_unary(mp, make_path_op);
+ else {
+ mp->cur_type=mp_path_type;
+ mp_make_path(mp, mp->cur_exp);
+ };
+ break;
+case reverse:
+ if ( mp->cur_type==mp_path_type ) {
+ p=mp_htap_ypoc(mp, mp->cur_exp);
+ if ( right_type(p)==mp_endpoint ) p=link(p);
+ mp_toss_knot_list(mp, mp->cur_exp); mp->cur_exp=p;
+ } else if ( mp->cur_type==mp_pair_type ) mp_pair_to_path(mp);
+ else mp_bad_unary(mp, reverse);
+ break;
+
+@ The |pair_value| routine changes the current expression to a
+given ordered pair of values.
+
+@<Declare unary action procedures@>=
+void mp_pair_value (MP mp,scaled x, scaled y) {
+ pointer p; /* a pair node */
+ p=mp_get_node(mp, value_node_size);
+ mp_flush_cur_exp(mp, p); mp->cur_type=mp_pair_type;
+ type(p)=mp_pair_type; name_type(p)=mp_capsule; mp_init_big_node(mp, p);
+ p=value(p);
+ type(x_part_loc(p))=mp_known; value(x_part_loc(p))=x;
+ type(y_part_loc(p))=mp_known; value(y_part_loc(p))=y;
+}
+
+@ @<Additional cases of unary operators@>=
+case ll_corner_op:
+ if ( ! mp_get_cur_bbox(mp) ) mp_bad_unary(mp, ll_corner_op);
+ else mp_pair_value(mp, minx,miny);
+ break;
+case lr_corner_op:
+ if ( ! mp_get_cur_bbox(mp) ) mp_bad_unary(mp, lr_corner_op);
+ else mp_pair_value(mp, maxx,miny);
+ break;
+case ul_corner_op:
+ if ( ! mp_get_cur_bbox(mp) ) mp_bad_unary(mp, ul_corner_op);
+ else mp_pair_value(mp, minx,maxy);
+ break;
+case ur_corner_op:
+ if ( ! mp_get_cur_bbox(mp) ) mp_bad_unary(mp, ur_corner_op);
+ else mp_pair_value(mp, maxx,maxy);
+ break;
+
+@ Here is a function that sets |minx|, |maxx|, |miny|, |maxy| to the bounding
+box of the current expression. The boolean result is |false| if the expression
+has the wrong type.
+
+@<Declare unary action procedures@>=
+boolean mp_get_cur_bbox (MP mp) {
+ switch (mp->cur_type) {
+ case mp_picture_type:
+ mp_set_bbox(mp, mp->cur_exp,true);
+ if ( minx_val(mp->cur_exp)>maxx_val(mp->cur_exp) ) {
+ minx=0; maxx=0; miny=0; maxy=0;
+ } else {
+ minx=minx_val(mp->cur_exp);
+ maxx=maxx_val(mp->cur_exp);
+ miny=miny_val(mp->cur_exp);
+ maxy=maxy_val(mp->cur_exp);
+ }
+ break;
+ case mp_path_type:
+ mp_path_bbox(mp, mp->cur_exp);
+ break;
+ case mp_pen_type:
+ mp_pen_bbox(mp, mp->cur_exp);
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+@ @<Additional cases of unary operators@>=
+case read_from_op:
+case close_from_op:
+ if ( mp->cur_type!=mp_string_type ) mp_bad_unary(mp, c);
+ else mp_do_read_or_close(mp,c);
+ break;
+
+@ Here is a routine that interprets |cur_exp| as a file name and tries to read
+a line from the file or to close the file.
+
+@<Declare unary action procedures@>=
+void mp_do_read_or_close (MP mp,quarterword c) {
+ readf_index n,n0; /* indices for searching |rd_fname| */
+ @<Find the |n| where |rd_fname[n]=cur_exp|; if |cur_exp| must be inserted,
+ call |start_read_input| and |goto found| or |not_found|@>;
+ mp_begin_file_reading(mp);
+ name=is_read;
+ if ( mp_input_ln(mp, mp->rd_file[n] ) )
+ goto FOUND;
+ mp_end_file_reading(mp);
+NOT_FOUND:
+ @<Record the end of file and set |cur_exp| to a dummy value@>;
+ return;
+CLOSE_FILE:
+ mp_flush_cur_exp(mp, 0); mp->cur_type=mp_vacuous;
+ return;
+FOUND:
+ mp_flush_cur_exp(mp, 0);
+ mp_finish_read(mp);
+}
+
+@ Free slots in the |rd_file| and |rd_fname| arrays are marked with NULL's in
+|rd_fname|.
+
+@<Find the |n| where |rd_fname[n]=cur_exp|...@>=
+{
+ char *fn;
+ n=mp->read_files;
+ n0=mp->read_files;
+ fn = str(mp->cur_exp);
+ while (mp_xstrcmp(fn,mp->rd_fname[n])!=0) {
+ if ( n>0 ) {
+ decr(n);
+ } else if ( c==close_from_op ) {
+ goto CLOSE_FILE;
+ } else {
+ if ( n0==mp->read_files ) {
+ if ( mp->read_files<mp->max_read_files ) {
+ incr(mp->read_files);
+ } else {
+ void **rd_file;
+ char **rd_fname;
+ readf_index l,k;
+ l = mp->max_read_files + (mp->max_read_files>>2);
+ rd_file = xmalloc((l+1), sizeof(void *));
+ rd_fname = xmalloc((l+1), sizeof(char *));
+ for (k=0;k<=l;k++) {
+ if (k<=mp->max_read_files) {
+ rd_file[k]=mp->rd_file[k];
+ rd_fname[k]=mp->rd_fname[k];
+ } else {
+ rd_file[k]=0;
+ rd_fname[k]=NULL;
+ }
+ }
+ xfree(mp->rd_file); xfree(mp->rd_fname);
+ mp->max_read_files = l;
+ mp->rd_file = rd_file;
+ mp->rd_fname = rd_fname;
+ }
+ }
+ n=n0;
+ if ( mp_start_read_input(mp,fn,n) )
+ goto FOUND;
+ else
+ goto NOT_FOUND;
+ }
+ if ( mp->rd_fname[n]==NULL ) { n0=n; }
+ }
+ if ( c==close_from_op ) {
+ (mp->close_file)(mp,mp->rd_file[n]);
+ goto NOT_FOUND;
+ }
+}
+
+@ @<Record the end of file and set |cur_exp| to a dummy value@>=
+xfree(mp->rd_fname[n]);
+mp->rd_fname[n]=NULL;
+if ( n==mp->read_files-1 ) mp->read_files=n;
+if ( c==close_from_op )
+ goto CLOSE_FILE;
+mp_flush_cur_exp(mp, mp->eof_line);
+mp->cur_type=mp_string_type
+
+@ The string denoting end-of-file is a one-byte string at position zero, by definition
+
+@<Glob...@>=
+str_number eof_line;
+
+@ @<Set init...@>=
+mp->eof_line=0;
+
+@ Finally, we have the operations that combine a capsule~|p|
+with the current expression.
+
+@d binary_return { mp_finish_binary(mp, old_p, old_exp); return; }
+
+@c @<Declare binary action procedures@>
+void mp_finish_binary (MP mp, pointer old_p, pointer old_exp ){
+ check_arith;
+ @<Recycle any sidestepped |independent| capsules@>;
+}
+void mp_do_binary (MP mp,pointer p, quarterword c) {
+ pointer q,r,rr; /* for list manipulation */
+ pointer old_p,old_exp; /* capsules to recycle */
+ integer v; /* for numeric manipulation */
+ check_arith;
+ if ( mp->internal[mp_tracing_commands]>two ) {
+ @<Trace the current binary operation@>;
+ }
+ @<Sidestep |independent| cases in capsule |p|@>;
+ @<Sidestep |independent| cases in the current expression@>;
+ switch (c) {
+ case plus: case minus:
+ @<Add or subtract the current expression from |p|@>;
+ break;
+ @<Additional cases of binary operators@>;
+ }; /* there are no other cases */
+ mp_recycle_value(mp, p);
+ mp_free_node(mp, p,value_node_size); /* |return| to avoid this */
+ mp_finish_binary(mp, old_p, old_exp);
+}
+
+@ @<Declare binary action...@>=
+void mp_bad_binary (MP mp,pointer p, quarterword c) {
+ mp_disp_err(mp, p,"");
+ exp_err("Not implemented: ");
+@.Not implemented...@>
+ if ( c>=min_of ) mp_print_op(mp, c);
+ mp_print_known_or_unknown_type(mp, type(p),p);
+ if ( c>=min_of ) mp_print(mp, "of"); else mp_print_op(mp, c);
+ mp_print_known_or_unknown_type(mp, mp->cur_type,mp->cur_exp);
+ help3("I'm afraid I don't know how to apply that operation to that")
+ ("combination of types. Continue, and I'll return the second")
+ ("argument (see above) as the result of the operation.");
+ mp_put_get_error(mp);
+}
+void mp_bad_envelope_pen (MP mp) {
+ mp_disp_err(mp, null,"");
+ exp_err("Not implemented: envelope(elliptical pen)of(path)");
+@.Not implemented...@>
+ help3("I'm afraid I don't know how to apply that operation to that")
+ ("combination of types. Continue, and I'll return the second")
+ ("argument (see above) as the result of the operation.");
+ mp_put_get_error(mp);
+}
+
+@ @<Trace the current binary operation@>=
+{
+ mp_begin_diagnostic(mp); mp_print_nl(mp, "{(");
+ mp_print_exp(mp,p,0); /* show the operand, but not verbosely */
+ mp_print_char(mp,')'); mp_print_op(mp,c); mp_print_char(mp,'(');
+ mp_print_exp(mp,null,0); mp_print(mp,")}");
+ mp_end_diagnostic(mp, false);
+}
+
+@ Several of the binary operations are potentially complicated by the
+fact that |independent| values can sneak into capsules. For example,
+we've seen an instance of this difficulty in the unary operation
+of negation. In order to reduce the number of cases that need to be
+handled, we first change the two operands (if necessary)
+to rid them of |independent| components. The original operands are
+put into capsules called |old_p| and |old_exp|, which will be
+recycled after the binary operation has been safely carried out.
+
+@<Recycle any sidestepped |independent| capsules@>=
+if ( old_p!=null ) {
+ mp_recycle_value(mp, old_p); mp_free_node(mp, old_p,value_node_size);
+}
+if ( old_exp!=null ) {
+ mp_recycle_value(mp, old_exp); mp_free_node(mp, old_exp,value_node_size);
+}
+
+@ A big node is considered to be ``tarnished'' if it contains at least one
+independent component. We will define a simple function called `|tarnished|'
+that returns |null| if and only if its argument is not tarnished.
+
+@<Sidestep |independent| cases in capsule |p|@>=
+switch (type(p)) {
+case mp_transform_type:
+case mp_color_type:
+case mp_cmykcolor_type:
+case mp_pair_type:
+ old_p=mp_tarnished(mp, p);
+ break;
+case mp_independent: old_p=mp_void; break;
+default: old_p=null; break;
+}
+if ( old_p!=null ) {
+ q=mp_stash_cur_exp(mp); old_p=p; mp_make_exp_copy(mp, old_p);
+ p=mp_stash_cur_exp(mp); mp_unstash_cur_exp(mp, q);
+}
+
+@ @<Sidestep |independent| cases in the current expression@>=
+switch (mp->cur_type) {
+case mp_transform_type:
+case mp_color_type:
+case mp_cmykcolor_type:
+case mp_pair_type:
+ old_exp=mp_tarnished(mp, mp->cur_exp);
+ break;
+case mp_independent:old_exp=mp_void; break;
+default: old_exp=null; break;
+}
+if ( old_exp!=null ) {
+ old_exp=mp->cur_exp; mp_make_exp_copy(mp, old_exp);
+}
+
+@ @<Declare binary action...@>=
+pointer mp_tarnished (MP mp,pointer p) {
+ pointer q; /* beginning of the big node */
+ pointer r; /* current position in the big node */
+ q=value(p); r=q+mp->big_node_size[type(p)];
+ do {
+ r=r-2;
+ if ( type(r)==mp_independent ) return mp_void;
+ } while (r!=q);
+ return null;
+}
+
+@ @<Add or subtract the current expression from |p|@>=
+if ( (mp->cur_type<mp_color_type)||(type(p)<mp_color_type) ) {
+ mp_bad_binary(mp, p,c);
+} else {
+ if ((mp->cur_type>mp_pair_type)&&(type(p)>mp_pair_type) ) {
+ mp_add_or_subtract(mp, p,null,c);
+ } else {
+ if ( mp->cur_type!=type(p) ) {
+ mp_bad_binary(mp, p,c);
+ } else {
+ q=value(p); r=value(mp->cur_exp);
+ rr=r+mp->big_node_size[mp->cur_type];
+ while ( r<rr ) {
+ mp_add_or_subtract(mp, q,r,c);
+ q=q+2; r=r+2;
+ }
+ }
+ }
+}
+
+@ The first argument to |add_or_subtract| is the location of a value node
+in a capsule or pair node that will soon be recycled. The second argument
+is either a location within a pair or transform node of |cur_exp|,
+or it is null (which means that |cur_exp| itself should be the second
+argument). The third argument is either |plus| or |minus|.
+
+The sum or difference of the numeric quantities will replace the second
+operand. Arithmetic overflow may go undetected; users aren't supposed to
+be monkeying around with really big values.
+@^overflow in arithmetic@>
+
+@<Declare binary action...@>=
+@<Declare the procedure called |dep_finish|@>
+void mp_add_or_subtract (MP mp,pointer p, pointer q, quarterword c) {
+ small_number s,t; /* operand types */
+ pointer r; /* list traverser */
+ integer v; /* second operand value */
+ if ( q==null ) {
+ t=mp->cur_type;
+ if ( t<mp_dependent ) v=mp->cur_exp; else v=dep_list(mp->cur_exp);
+ } else {
+ t=type(q);
+ if ( t<mp_dependent ) v=value(q); else v=dep_list(q);
+ }
+ if ( t==mp_known ) {
+ if ( c==minus ) negate(v);
+ if ( type(p)==mp_known ) {
+ v=mp_slow_add(mp, value(p),v);
+ if ( q==null ) mp->cur_exp=v; else value(q)=v;
+ return;
+ }
+ @<Add a known value to the constant term of |dep_list(p)|@>;
+ } else {
+ if ( c==minus ) mp_negate_dep_list(mp, v);
+ @<Add operand |p| to the dependency list |v|@>;
+ }
+}
+
+@ @<Add a known value to the constant term of |dep_list(p)|@>=
+r=dep_list(p);
+while ( info(r)!=null ) r=link(r);
+value(r)=mp_slow_add(mp, value(r),v);
+if ( q==null ) {
+ q=mp_get_node(mp, value_node_size); mp->cur_exp=q; mp->cur_type=type(p);
+ name_type(q)=mp_capsule;
+}
+dep_list(q)=dep_list(p); type(q)=type(p);
+prev_dep(q)=prev_dep(p); link(prev_dep(p))=q;
+type(p)=mp_known; /* this will keep the recycler from collecting non-garbage */
+
+@ We prefer |dependent| lists to |mp_proto_dependent| ones, because it is
+nice to retain the extra accuracy of |fraction| coefficients.
+But we have to handle both kinds, and mixtures too.
+
+@<Add operand |p| to the dependency list |v|@>=
+if ( type(p)==mp_known ) {
+ @<Add the known |value(p)| to the constant term of |v|@>;
+} else {
+ s=type(p); r=dep_list(p);
+ if ( t==mp_dependent ) {
+ if ( s==mp_dependent ) {
+ if ( mp_max_coef(mp, r)+mp_max_coef(mp, v)<coef_bound )
+ v=mp_p_plus_q(mp, v,r,mp_dependent); goto DONE;
+ } /* |fix_needed| will necessarily be false */
+ t=mp_proto_dependent;
+ v=mp_p_over_v(mp, v,unity,mp_dependent,mp_proto_dependent);
+ }
+ if ( s==mp_proto_dependent ) v=mp_p_plus_q(mp, v,r,mp_proto_dependent);
+ else v=mp_p_plus_fq(mp, v,unity,r,mp_proto_dependent,mp_dependent);
+ DONE:
+ @<Output the answer, |v| (which might have become |known|)@>;
+ }
+
+@ @<Add the known |value(p)| to the constant term of |v|@>=
+{
+ while ( info(v)!=null ) v=link(v);
+ value(v)=mp_slow_add(mp, value(p),value(v));
+}
+
+@ @<Output the answer, |v| (which might have become |known|)@>=
+if ( q!=null ) mp_dep_finish(mp, v,q,t);
+else { mp->cur_type=t; mp_dep_finish(mp, v,null,t); }
+
+@ Here's the current situation: The dependency list |v| of type |t|
+should either be put into the current expression (if |q=null|) or
+into location |q| within a pair node (otherwise). The destination (|cur_exp|
+or |q|) formerly held a dependency list with the same
+final pointer as the list |v|.
+
+@<Declare the procedure called |dep_finish|@>=
+void mp_dep_finish (MP mp, pointer v, pointer q, small_number t) {
+ pointer p; /* the destination */
+ scaled vv; /* the value, if it is |known| */
+ if ( q==null ) p=mp->cur_exp; else p=q;
+ dep_list(p)=v; type(p)=t;
+ if ( info(v)==null ) {
+ vv=value(v);
+ if ( q==null ) {
+ mp_flush_cur_exp(mp, vv);
+ } else {
+ mp_recycle_value(mp, p); type(q)=mp_known; value(q)=vv;
+ }
+ } else if ( q==null ) {
+ mp->cur_type=t;
+ }
+ if ( mp->fix_needed ) mp_fix_dependencies(mp);
+}
+
+@ Let's turn now to the six basic relations of comparison.
+
+@<Additional cases of binary operators@>=
+case less_than: case less_or_equal: case greater_than:
+case greater_or_equal: case equal_to: case unequal_to:
+ check_arith; /* at this point |arith_error| should be |false|? */
+ if ( (mp->cur_type>mp_pair_type)&&(type(p)>mp_pair_type) ) {
+ mp_add_or_subtract(mp, p,null,minus); /* |cur_exp:=(p)-cur_exp| */
+ } else if ( mp->cur_type!=type(p) ) {
+ mp_bad_binary(mp, p,c); goto DONE;
+ } else if ( mp->cur_type==mp_string_type ) {
+ mp_flush_cur_exp(mp, mp_str_vs_str(mp, value(p),mp->cur_exp));
+ } else if ((mp->cur_type==mp_unknown_string)||
+ (mp->cur_type==mp_unknown_boolean) ) {
+ @<Check if unknowns have been equated@>;
+ } else if ( (mp->cur_type<=mp_pair_type)&&(mp->cur_type>=mp_transform_type)) {
+ @<Reduce comparison of big nodes to comparison of scalars@>;
+ } else if ( mp->cur_type==mp_boolean_type ) {
+ mp_flush_cur_exp(mp, mp->cur_exp-value(p));
+ } else {
+ mp_bad_binary(mp, p,c); goto DONE;
+ }
+ @<Compare the current expression with zero@>;
+DONE:
+ mp->arith_error=false; /* ignore overflow in comparisons */
+ break;
+
+@ @<Compare the current expression with zero@>=
+if ( mp->cur_type!=mp_known ) {
+ if ( mp->cur_type<mp_known ) {
+ mp_disp_err(mp, p,"");
+ help1("The quantities shown above have not been equated.")
+ } else {
+ help2("Oh dear. I can\'t decide if the expression above is positive,")
+ ("negative, or zero. So this comparison test won't be `true'.");
+ }
+ exp_err("Unknown relation will be considered false");
+@.Unknown relation...@>
+ mp_put_get_flush_error(mp, false_code);
+} else {
+ switch (c) {
+ case less_than: boolean_reset(mp->cur_exp<0); break;
+ case less_or_equal: boolean_reset(mp->cur_exp<=0); break;
+ case greater_than: boolean_reset(mp->cur_exp>0); break;
+ case greater_or_equal: boolean_reset(mp->cur_exp>=0); break;
+ case equal_to: boolean_reset(mp->cur_exp==0); break;
+ case unequal_to: boolean_reset(mp->cur_exp!=0); break;
+ }; /* there are no other cases */
+}
+mp->cur_type=mp_boolean_type
+
+@ When two unknown strings are in the same ring, we know that they are
+equal. Otherwise, we don't know whether they are equal or not, so we
+make no change.
+
+@<Check if unknowns have been equated@>=
+{
+ q=value(mp->cur_exp);
+ while ( (q!=mp->cur_exp)&&(q!=p) ) q=value(q);
+ if ( q==p ) mp_flush_cur_exp(mp, 0);
+}
+
+@ @<Reduce comparison of big nodes to comparison of scalars@>=
+{
+ q=value(p); r=value(mp->cur_exp);
+ rr=r+mp->big_node_size[mp->cur_type]-2;
+ while (1) { mp_add_or_subtract(mp, q,r,minus);
+ if ( type(r)!=mp_known ) break;
+ if ( value(r)!=0 ) break;
+ if ( r==rr ) break;
+ q=q+2; r=r+2;
+ }
+ mp_take_part(mp, name_type(r)+x_part-mp_x_part_sector);
+}
+
+@ Here we use the sneaky fact that |and_op-false_code=or_op-true_code|.
+
+@<Additional cases of binary operators@>=
+case and_op:
+case or_op:
+ if ( (type(p)!=mp_boolean_type)||(mp->cur_type!=mp_boolean_type) )
+ mp_bad_binary(mp, p,c);
+ else if ( value(p)==c+false_code-and_op ) mp->cur_exp=value(p);
+ break;
+
+@ @<Additional cases of binary operators@>=
+case times:
+ if ( (mp->cur_type<mp_color_type)||(type(p)<mp_color_type) ) {
+ mp_bad_binary(mp, p,times);
+ } else if ( (mp->cur_type==mp_known)||(type(p)==mp_known) ) {
+ @<Multiply when at least one operand is known@>;
+ } else if ( (mp_nice_color_or_pair(mp, p,type(p))&&(mp->cur_type>mp_pair_type))
+ ||(mp_nice_color_or_pair(mp, mp->cur_exp,mp->cur_type)&&
+ (type(p)>mp_pair_type)) ) {
+ mp_hard_times(mp, p);
+ binary_return;
+ } else {
+ mp_bad_binary(mp, p,times);
+ }
+ break;
+
+@ @<Multiply when at least one operand is known@>=
+{
+ if ( type(p)==mp_known ) {
+ v=value(p); mp_free_node(mp, p,value_node_size);
+ } else {
+ v=mp->cur_exp; mp_unstash_cur_exp(mp, p);
+ }
+ if ( mp->cur_type==mp_known ) {
+ mp->cur_exp=mp_take_scaled(mp, mp->cur_exp,v);
+ } else if ( (mp->cur_type==mp_pair_type)||
+ (mp->cur_type==mp_color_type)||
+ (mp->cur_type==mp_cmykcolor_type) ) {
+ p=value(mp->cur_exp)+mp->big_node_size[mp->cur_type];
+ do {
+ p=p-2; mp_dep_mult(mp, p,v,true);
+ } while (p!=value(mp->cur_exp));
+ } else {
+ mp_dep_mult(mp, null,v,true);
+ }
+ binary_return;
+}
+
+@ @<Declare binary action...@>=
+void mp_dep_mult (MP mp,pointer p, integer v, boolean v_is_scaled) {
+ pointer q; /* the dependency list being multiplied by |v| */
+ small_number s,t; /* its type, before and after */
+ if ( p==null ) {
+ q=mp->cur_exp;
+ } else if ( type(p)!=mp_known ) {
+ q=p;
+ } else {
+ if ( v_is_scaled ) value(p)=mp_take_scaled(mp, value(p),v);
+ else value(p)=mp_take_fraction(mp, value(p),v);
+ return;
+ };
+ t=type(q); q=dep_list(q); s=t;
+ if ( t==mp_dependent ) if ( v_is_scaled )
+ if (mp_ab_vs_cd(mp, mp_max_coef(mp,q),abs(v),coef_bound-1,unity)>=0 )
+ t=mp_proto_dependent;
+ q=mp_p_times_v(mp, q,v,s,t,v_is_scaled);
+ mp_dep_finish(mp, q,p,t);
+}
+
+@ Here is a routine that is similar to |times|; but it is invoked only
+internally, when |v| is a |fraction| whose magnitude is at most~1,
+and when |cur_type>=mp_color_type|.
+
+@c void mp_frac_mult (MP mp,scaled n, scaled d) {
+ /* multiplies |cur_exp| by |n/d| */
+ pointer p; /* a pair node */
+ pointer old_exp; /* a capsule to recycle */
+ fraction v; /* |n/d| */
+ if ( mp->internal[mp_tracing_commands]>two ) {
+ @<Trace the fraction multiplication@>;
+ }
+ switch (mp->cur_type) {
+ case mp_transform_type:
+ case mp_color_type:
+ case mp_cmykcolor_type:
+ case mp_pair_type:
+ old_exp=mp_tarnished(mp, mp->cur_exp);
+ break;
+ case mp_independent: old_exp=mp_void; break;
+ default: old_exp=null; break;
+ }
+ if ( old_exp!=null ) {
+ old_exp=mp->cur_exp; mp_make_exp_copy(mp, old_exp);
+ }
+ v=mp_make_fraction(mp, n,d);
+ if ( mp->cur_type==mp_known ) {
+ mp->cur_exp=mp_take_fraction(mp, mp->cur_exp,v);
+ } else if ( mp->cur_type<=mp_pair_type ) {
+ p=value(mp->cur_exp)+mp->big_node_size[mp->cur_type];
+ do {
+ p=p-2;
+ mp_dep_mult(mp, p,v,false);
+ } while (p!=value(mp->cur_exp));
+ } else {
+ mp_dep_mult(mp, null,v,false);
+ }
+ if ( old_exp!=null ) {
+ mp_recycle_value(mp, old_exp);
+ mp_free_node(mp, old_exp,value_node_size);
+ }
+}
+
+@ @<Trace the fraction multiplication@>=
+{
+ mp_begin_diagnostic(mp);
+ mp_print_nl(mp, "{("); mp_print_scaled(mp,n); mp_print_char(mp,'/');
+ mp_print_scaled(mp,d); mp_print(mp,")*("); mp_print_exp(mp,null,0);
+ mp_print(mp,")}");
+ mp_end_diagnostic(mp, false);
+}
+
+@ The |hard_times| routine multiplies a nice color or pair by a dependency list.
+
+@<Declare binary action procedures@>=
+void mp_hard_times (MP mp,pointer p) {
+ pointer q; /* a copy of the dependent variable |p| */
+ pointer r; /* a component of the big node for the nice color or pair */
+ scaled v; /* the known value for |r| */
+ if ( type(p)<=mp_pair_type ) {
+ q=mp_stash_cur_exp(mp); mp_unstash_cur_exp(mp, p); p=q;
+ }; /* now |cur_type=mp_pair_type| or |cur_type=mp_color_type| */
+ r=value(mp->cur_exp)+mp->big_node_size[mp->cur_type];
+ while (1) {
+ r=r-2;
+ v=value(r);
+ type(r)=type(p);
+ if ( r==value(mp->cur_exp) )
+ break;
+ mp_new_dep(mp, r,mp_copy_dep_list(mp, dep_list(p)));
+ mp_dep_mult(mp, r,v,true);
+ }
+ mp->mem[value_loc(r)]=mp->mem[value_loc(p)];
+ link(prev_dep(p))=r;
+ mp_free_node(mp, p,value_node_size);
+ mp_dep_mult(mp, r,v,true);
+}
+
+@ @<Additional cases of binary operators@>=
+case over:
+ if ( (mp->cur_type!=mp_known)||(type(p)<mp_color_type) ) {
+ mp_bad_binary(mp, p,over);
+ } else {
+ v=mp->cur_exp; mp_unstash_cur_exp(mp, p);
+ if ( v==0 ) {
+ @<Squeal about division by zero@>;
+ } else {
+ if ( mp->cur_type==mp_known ) {
+ mp->cur_exp=mp_make_scaled(mp, mp->cur_exp,v);
+ } else if ( mp->cur_type<=mp_pair_type ) {
+ p=value(mp->cur_exp)+mp->big_node_size[mp->cur_type];
+ do {
+ p=p-2; mp_dep_div(mp, p,v);
+ } while (p!=value(mp->cur_exp));
+ } else {
+ mp_dep_div(mp, null,v);
+ }
+ }
+ binary_return;
+ }
+ break;
+
+@ @<Declare binary action...@>=
+void mp_dep_div (MP mp,pointer p, scaled v) {
+ pointer q; /* the dependency list being divided by |v| */
+ small_number s,t; /* its type, before and after */
+ if ( p==null ) q=mp->cur_exp;
+ else if ( type(p)!=mp_known ) q=p;
+ else { value(p)=mp_make_scaled(mp, value(p),v); return; };
+ t=type(q); q=dep_list(q); s=t;
+ if ( t==mp_dependent )
+ if ( mp_ab_vs_cd(mp, mp_max_coef(mp,q),unity,coef_bound-1,abs(v))>=0 )
+ t=mp_proto_dependent;
+ q=mp_p_over_v(mp, q,v,s,t);
+ mp_dep_finish(mp, q,p,t);
+}
+
+@ @<Squeal about division by zero@>=
+{
+ exp_err("Division by zero");
+@.Division by zero@>
+ help2("You're trying to divide the quantity shown above the error")
+ ("message by zero. I'm going to divide it by one instead.");
+ mp_put_get_error(mp);
+}
+
+@ @<Additional cases of binary operators@>=
+case pythag_add:
+case pythag_sub:
+ if ( (mp->cur_type==mp_known)&&(type(p)==mp_known) ) {
+ if ( c==pythag_add ) mp->cur_exp=mp_pyth_add(mp, value(p),mp->cur_exp);
+ else mp->cur_exp=mp_pyth_sub(mp, value(p),mp->cur_exp);
+ } else mp_bad_binary(mp, p,c);
+ break;
+
+@ The next few sections of the program deal with affine transformations
+of coordinate data.
+
+@<Additional cases of binary operators@>=
+case rotated_by: case slanted_by:
+case scaled_by: case shifted_by: case transformed_by:
+case x_scaled: case y_scaled: case z_scaled:
+ if ( type(p)==mp_path_type ) {
+ path_trans(c,p); binary_return;
+ } else if ( type(p)==mp_pen_type ) {
+ pen_trans(c,p);
+ mp->cur_exp=mp_convex_hull(mp, mp->cur_exp);
+ /* rounding error could destroy convexity */
+ binary_return;
+ } else if ( (type(p)==mp_pair_type)||(type(p)==mp_transform_type) ) {
+ mp_big_trans(mp, p,c);
+ } else if ( type(p)==mp_picture_type ) {
+ mp_do_edges_trans(mp, p,c); binary_return;
+ } else {
+ mp_bad_binary(mp, p,c);
+ }
+ break;
+
+@ Let |c| be one of the eight transform operators. The procedure call
+|set_up_trans(c)| first changes |cur_exp| to a transform that corresponds to
+|c| and the original value of |cur_exp|. (In particular, |cur_exp| doesn't
+change at all if |c=transformed_by|.)
+
+Then, if all components of the resulting transform are |known|, they are
+moved to the global variables |txx|, |txy|, |tyx|, |tyy|, |tx|, |ty|;
+and |cur_exp| is changed to the known value zero.
+
+@<Declare binary action...@>=
+void mp_set_up_trans (MP mp,quarterword c) {
+ pointer p,q,r; /* list manipulation registers */
+ if ( (c!=transformed_by)||(mp->cur_type!=mp_transform_type) ) {
+ @<Put the current transform into |cur_exp|@>;
+ }
+ @<If the current transform is entirely known, stash it in global variables;
+ otherwise |return|@>;
+}
+
+@ @<Glob...@>=
+scaled txx;
+scaled txy;
+scaled tyx;
+scaled tyy;
+scaled tx;
+scaled ty; /* current transform coefficients */
+
+@ @<Put the current transform...@>=
+{
+ p=mp_stash_cur_exp(mp);
+ mp->cur_exp=mp_id_transform(mp);
+ mp->cur_type=mp_transform_type;
+ q=value(mp->cur_exp);
+ switch (c) {
+ @<For each of the eight cases, change the relevant fields of |cur_exp|
+ and |goto done|;
+ but do nothing if capsule |p| doesn't have the appropriate type@>;
+ }; /* there are no other cases */
+ mp_disp_err(mp, p,"Improper transformation argument");
+@.Improper transformation argument@>
+ help3("The expression shown above has the wrong type,")
+ ("so I can\'t transform anything using it.")
+ ("Proceed, and I'll omit the transformation.");
+ mp_put_get_error(mp);
+DONE:
+ mp_recycle_value(mp, p);
+ mp_free_node(mp, p,value_node_size);
+}
+
+@ @<If the current transform is entirely known, ...@>=
+q=value(mp->cur_exp); r=q+transform_node_size;
+do {
+ r=r-2;
+ if ( type(r)!=mp_known ) return;
+} while (r!=q);
+mp->txx=value(xx_part_loc(q));
+mp->txy=value(xy_part_loc(q));
+mp->tyx=value(yx_part_loc(q));
+mp->tyy=value(yy_part_loc(q));
+mp->tx=value(x_part_loc(q));
+mp->ty=value(y_part_loc(q));
+mp_flush_cur_exp(mp, 0)
+
+@ @<For each of the eight cases...@>=
+case rotated_by:
+ if ( type(p)==mp_known )
+ @<Install sines and cosines, then |goto done|@>;
+ break;
+case slanted_by:
+ if ( type(p)>mp_pair_type ) {
+ mp_install(mp, xy_part_loc(q),p); goto DONE;
+ };
+ break;
+case scaled_by:
+ if ( type(p)>mp_pair_type ) {
+ mp_install(mp, xx_part_loc(q),p); mp_install(mp, yy_part_loc(q),p);
+ goto DONE;
+ };
+ break;
+case shifted_by:
+ if ( type(p)==mp_pair_type ) {
+ r=value(p); mp_install(mp, x_part_loc(q),x_part_loc(r));
+ mp_install(mp, y_part_loc(q),y_part_loc(r)); goto DONE;
+ };
+ break;
+case x_scaled:
+ if ( type(p)>mp_pair_type ) {
+ mp_install(mp, xx_part_loc(q),p); goto DONE;
+ };
+ break;
+case y_scaled:
+ if ( type(p)>mp_pair_type ) {
+ mp_install(mp, yy_part_loc(q),p); goto DONE;
+ };
+ break;
+case z_scaled:
+ if ( type(p)==mp_pair_type )
+ @<Install a complex multiplier, then |goto done|@>;
+ break;
+case transformed_by:
+ break;
+
+
+@ @<Install sines and cosines, then |goto done|@>=
+{ mp_n_sin_cos(mp, (value(p) % three_sixty_units)*16);
+ value(xx_part_loc(q))=mp_round_fraction(mp, mp->n_cos);
+ value(yx_part_loc(q))=mp_round_fraction(mp, mp->n_sin);
+ value(xy_part_loc(q))=-value(yx_part_loc(q));
+ value(yy_part_loc(q))=value(xx_part_loc(q));
+ goto DONE;
+}
+
+@ @<Install a complex multiplier, then |goto done|@>=
+{
+ r=value(p);
+ mp_install(mp, xx_part_loc(q),x_part_loc(r));
+ mp_install(mp, yy_part_loc(q),x_part_loc(r));
+ mp_install(mp, yx_part_loc(q),y_part_loc(r));
+ if ( type(y_part_loc(r))==mp_known ) negate(value(y_part_loc(r)));
+ else mp_negate_dep_list(mp, dep_list(y_part_loc(r)));
+ mp_install(mp, xy_part_loc(q),y_part_loc(r));
+ goto DONE;
+}
+
+@ Procedure |set_up_known_trans| is like |set_up_trans|, but it
+insists that the transformation be entirely known.
+
+@<Declare binary action...@>=
+void mp_set_up_known_trans (MP mp,quarterword c) {
+ mp_set_up_trans(mp, c);
+ if ( mp->cur_type!=mp_known ) {
+ exp_err("Transform components aren't all known");
+@.Transform components...@>
+ help3("I'm unable to apply a partially specified transformation")
+ ("except to a fully known pair or transform.")
+ ("Proceed, and I'll omit the transformation.");
+ mp_put_get_flush_error(mp, 0);
+ mp->txx=unity; mp->txy=0; mp->tyx=0; mp->tyy=unity;
+ mp->tx=0; mp->ty=0;
+ }
+}
+
+@ Here's a procedure that applies the transform |txx..ty| to a pair of
+coordinates in locations |p| and~|q|.
+
+@<Declare binary action...@>=
+void mp_trans (MP mp,pointer p, pointer q) {
+ scaled v; /* the new |x| value */
+ v=mp_take_scaled(mp, mp->mem[p].sc,mp->txx)+
+ mp_take_scaled(mp, mp->mem[q].sc,mp->txy)+mp->tx;
+ mp->mem[q].sc=mp_take_scaled(mp, mp->mem[p].sc,mp->tyx)+
+ mp_take_scaled(mp, mp->mem[q].sc,mp->tyy)+mp->ty;
+ mp->mem[p].sc=v;
+}
+
+@ The simplest transformation procedure applies a transform to all
+coordinates of a path. The |path_trans(c)(p)| macro applies
+a transformation defined by |cur_exp| and the transform operator |c|
+to the path~|p|.
+
+@d path_trans(A,B) { mp_set_up_known_trans(mp, (A));
+ mp_unstash_cur_exp(mp, (B));
+ mp_do_path_trans(mp, mp->cur_exp); }
+
+@<Declare binary action...@>=
+void mp_do_path_trans (MP mp,pointer p) {
+ pointer q; /* list traverser */
+ q=p;
+ do {
+ if ( left_type(q)!=mp_endpoint )
+ mp_trans(mp, q+3,q+4); /* that's |left_x| and |left_y| */
+ mp_trans(mp, q+1,q+2); /* that's |x_coord| and |y_coord| */
+ if ( right_type(q)!=mp_endpoint )
+ mp_trans(mp, q+5,q+6); /* that's |right_x| and |right_y| */
+@^data structure assumptions@>
+ q=link(q);
+ } while (q!=p);
+}
+
+@ Transforming a pen is very similar, except that there are no |left_type|
+and |right_type| fields.
+
+@d pen_trans(A,B) { mp_set_up_known_trans(mp, (A));
+ mp_unstash_cur_exp(mp, (B));
+ mp_do_pen_trans(mp, mp->cur_exp); }
+
+@<Declare binary action...@>=
+void mp_do_pen_trans (MP mp,pointer p) {
+ pointer q; /* list traverser */
+ if ( pen_is_elliptical(p) ) {
+ mp_trans(mp, p+3,p+4); /* that's |left_x| and |left_y| */
+ mp_trans(mp, p+5,p+6); /* that's |right_x| and |right_y| */
+ };
+ q=p;
+ do {
+ mp_trans(mp, q+1,q+2); /* that's |x_coord| and |y_coord| */
+@^data structure assumptions@>
+ q=link(q);
+ } while (q!=p);
+}
+
+@ The next transformation procedure applies to edge structures. It will do
+any transformation, but the results may be substandard if the picture contains
+text that uses downloaded bitmap fonts. The binary action procedure is
+|do_edges_trans|, but we also need a function that just scales a picture.
+That routine is |scale_edges|. Both it and the underlying routine |edges_trans|
+should be thought of as procedures that update an edge structure |h|, except
+that they have to return a (possibly new) structure because of the need to call
+|private_edges|.
+
+@<Declare binary action...@>=
+pointer mp_edges_trans (MP mp, pointer h) {
+ pointer q; /* the object being transformed */
+ pointer r,s; /* for list manipulation */
+ scaled sx,sy; /* saved transformation parameters */
+ scaled sqdet; /* square root of determinant for |dash_scale| */
+ integer sgndet; /* sign of the determinant */
+ scaled v; /* a temporary value */
+ h=mp_private_edges(mp, h);
+ sqdet=mp_sqrt_det(mp, mp->txx,mp->txy,mp->tyx,mp->tyy);
+ sgndet=mp_ab_vs_cd(mp, mp->txx,mp->tyy,mp->txy,mp->tyx);
+ if ( dash_list(h)!=null_dash ) {
+ @<Try to transform the dash list of |h|@>;
+ }
+ @<Make the bounding box of |h| unknown if it can't be updated properly
+ without scanning the whole structure@>;
+ q=link(dummy_loc(h));
+ while ( q!=null ) {
+ @<Transform graphical object |q|@>;
+ q=link(q);
+ }
+ return h;
+}
+void mp_do_edges_trans (MP mp,pointer p, quarterword c) {
+ mp_set_up_known_trans(mp, c);
+ value(p)=mp_edges_trans(mp, value(p));
+ mp_unstash_cur_exp(mp, p);
+}
+void mp_scale_edges (MP mp) {
+ mp->txx=mp->se_sf; mp->tyy=mp->se_sf;
+ mp->txy=0; mp->tyx=0; mp->tx=0; mp->ty=0;
+ mp->se_pic=mp_edges_trans(mp, mp->se_pic);
+}
+
+@ @<Try to transform the dash list of |h|@>=
+if ( (mp->txy!=0)||(mp->tyx!=0)||
+ (mp->ty!=0)||(abs(mp->txx)!=abs(mp->tyy))) {
+ mp_flush_dash_list(mp, h);
+} else {
+ if ( mp->txx<0 ) { @<Reverse the dash list of |h|@>; }
+ @<Scale the dash list by |txx| and shift it by |tx|@>;
+ dash_y(h)=mp_take_scaled(mp, dash_y(h),abs(mp->tyy));
+}
+
+@ @<Reverse the dash list of |h|@>=
+{
+ r=dash_list(h);
+ dash_list(h)=null_dash;
+ while ( r!=null_dash ) {
+ s=r; r=link(r);
+ v=start_x(s); start_x(s)=stop_x(s); stop_x(s)=v;
+ link(s)=dash_list(h);
+ dash_list(h)=s;
+ }
+}
+
+@ @<Scale the dash list by |txx| and shift it by |tx|@>=
+r=dash_list(h);
+while ( r!=null_dash ) {
+ start_x(r)=mp_take_scaled(mp, start_x(r),mp->txx)+mp->tx;
+ stop_x(r)=mp_take_scaled(mp, stop_x(r),mp->txx)+mp->tx;
+ r=link(r);
+}
+
+@ @<Make the bounding box of |h| unknown if it can't be updated properly...@>=
+if ( (mp->txx==0)&&(mp->tyy==0) ) {
+ @<Swap the $x$ and $y$ parameters in the bounding box of |h|@>;
+} else if ( (mp->txy!=0)||(mp->tyx!=0) ) {
+ mp_init_bbox(mp, h);
+ goto DONE1;
+}
+if ( minx_val(h)<=maxx_val(h) ) {
+ @<Scale the bounding box by |txx+txy| and |tyx+tyy|; then shift by
+ |(tx,ty)|@>;
+}
+DONE1:
+
+
+
+@ @<Swap the $x$ and $y$ parameters in the bounding box of |h|@>=
+{
+ v=minx_val(h); minx_val(h)=miny_val(h); miny_val(h)=v;
+ v=maxx_val(h); maxx_val(h)=maxy_val(h); maxy_val(h)=v;
+}
+
+@ The sum ``|txx+txy|'' is whichever of |txx| or |txy| is nonzero. The other
+sum is similar.
+
+@<Scale the bounding box by |txx+txy| and |tyx+tyy|; then shift...@>=
+{
+ minx_val(h)=mp_take_scaled(mp, minx_val(h),mp->txx+mp->txy)+mp->tx;
+ maxx_val(h)=mp_take_scaled(mp, maxx_val(h),mp->txx+mp->txy)+mp->tx;
+ miny_val(h)=mp_take_scaled(mp, miny_val(h),mp->tyx+mp->tyy)+mp->ty;
+ maxy_val(h)=mp_take_scaled(mp, maxy_val(h),mp->tyx+mp->tyy)+mp->ty;
+ if ( mp->txx+mp->txy<0 ) {
+ v=minx_val(h); minx_val(h)=maxx_val(h); maxx_val(h)=v;
+ }
+ if ( mp->tyx+mp->tyy<0 ) {
+ v=miny_val(h); miny_val(h)=maxy_val(h); maxy_val(h)=v;
+ }
+}
+
+@ Now we ready for the main task of transforming the graphical objects in edge
+structure~|h|.
+
+@<Transform graphical object |q|@>=
+switch (type(q)) {
+case mp_fill_code: case mp_stroked_code:
+ mp_do_path_trans(mp, path_p(q));
+ @<Transform |pen_p(q)|, making sure polygonal pens stay counter-clockwise@>;
+ break;
+case mp_start_clip_code: case mp_start_bounds_code:
+ mp_do_path_trans(mp, path_p(q));
+ break;
+case mp_text_code:
+ r=text_tx_loc(q);
+ @<Transform the compact transformation starting at |r|@>;
+ break;
+case mp_stop_clip_code: case mp_stop_bounds_code:
+ break;
+} /* there are no other cases */
+
+@ Note that the shift parameters |(tx,ty)| apply only to the path being stroked.
+The |dash_scale| has to be adjusted to scale the dash lengths in |dash_p(q)|
+since the \ps\ output procedures will try to compensate for the transformation
+we are applying to |pen_p(q)|. Since this compensation is based on the square
+root of the determinant, |sqdet| is the appropriate factor.
+
+@<Transform |pen_p(q)|, making sure...@>=
+if ( pen_p(q)!=null ) {
+ sx=mp->tx; sy=mp->ty;
+ mp->tx=0; mp->ty=0;
+ mp_do_pen_trans(mp, pen_p(q));
+ if ( ((type(q)==mp_stroked_code)&&(dash_p(q)!=null)) )
+ dash_scale(q)=mp_take_scaled(mp, dash_scale(q),sqdet);
+ if ( ! pen_is_elliptical(pen_p(q)) )
+ if ( sgndet<0 )
+ pen_p(q)=mp_make_pen(mp, mp_copy_path(mp, pen_p(q)),true);
+ /* this unreverses the pen */
+ mp->tx=sx; mp->ty=sy;
+}
+
+@ This uses the fact that transformations are stored in the order
+|(tx,ty,txx,txy,tyx,tyy)|.
+@^data structure assumptions@>
+
+@<Transform the compact transformation starting at |r|@>=
+mp_trans(mp, r,r+1);
+sx=mp->tx; sy=mp->ty;
+mp->tx=0; mp->ty=0;
+mp_trans(mp, r+2,r+4);
+mp_trans(mp, r+3,r+5);
+mp->tx=sx; mp->ty=sy
+
+@ The hard cases of transformation occur when big nodes are involved,
+and when some of their components are unknown.
+
+@<Declare binary action...@>=
+@<Declare subroutines needed by |big_trans|@>
+void mp_big_trans (MP mp,pointer p, quarterword c) {
+ pointer q,r,pp,qq; /* list manipulation registers */
+ small_number s; /* size of a big node */
+ s=mp->big_node_size[type(p)]; q=value(p); r=q+s;
+ do {
+ r=r-2;
+ if ( type(r)!=mp_known ) {
+ @<Transform an unknown big node and |return|@>;
+ }
+ } while (r!=q);
+ @<Transform a known big node@>;
+} /* node |p| will now be recycled by |do_binary| */
+
+@ @<Transform an unknown big node and |return|@>=
+{
+ mp_set_up_known_trans(mp, c); mp_make_exp_copy(mp, p);
+ r=value(mp->cur_exp);
+ if ( mp->cur_type==mp_transform_type ) {
+ mp_bilin1(mp, yy_part_loc(r),mp->tyy,xy_part_loc(q),mp->tyx,0);
+ mp_bilin1(mp, yx_part_loc(r),mp->tyy,xx_part_loc(q),mp->tyx,0);
+ mp_bilin1(mp, xy_part_loc(r),mp->txx,yy_part_loc(q),mp->txy,0);
+ mp_bilin1(mp, xx_part_loc(r),mp->txx,yx_part_loc(q),mp->txy,0);
+ }
+ mp_bilin1(mp, y_part_loc(r),mp->tyy,x_part_loc(q),mp->tyx,mp->ty);
+ mp_bilin1(mp, x_part_loc(r),mp->txx,y_part_loc(q),mp->txy,mp->tx);
+ return;
+}
+
+@ Let |p| point to a two-word value field inside a big node of |cur_exp|,
+and let |q| point to a another value field. The |bilin1| procedure
+replaces |p| by $p\cdot t+q\cdot u+\delta$.
+
+@<Declare subroutines needed by |big_trans|@>=
+void mp_bilin1 (MP mp, pointer p, scaled t, pointer q,
+ scaled u, scaled delta) {
+ pointer r; /* list traverser */
+ if ( t!=unity ) mp_dep_mult(mp, p,t,true);
+ if ( u!=0 ) {
+ if ( type(q)==mp_known ) {
+ delta+=mp_take_scaled(mp, value(q),u);
+ } else {
+ @<Ensure that |type(p)=mp_proto_dependent|@>;
+ dep_list(p)=mp_p_plus_fq(mp, dep_list(p),u,dep_list(q),
+ mp_proto_dependent,type(q));
+ }
+ }
+ if ( type(p)==mp_known ) {
+ value(p)+=delta;
+ } else {
+ r=dep_list(p);
+ while ( info(r)!=null ) r=link(r);
+ delta+=value(r);
+ if ( r!=dep_list(p) ) value(r)=delta;
+ else { mp_recycle_value(mp, p); type(p)=mp_known; value(p)=delta; };
+ }
+ if ( mp->fix_needed ) mp_fix_dependencies(mp);
+}
+
+@ @<Ensure that |type(p)=mp_proto_dependent|@>=
+if ( type(p)!=mp_proto_dependent ) {
+ if ( type(p)==mp_known )
+ mp_new_dep(mp, p,mp_const_dependency(mp, value(p)));
+ else
+ dep_list(p)=mp_p_times_v(mp, dep_list(p),unity,mp_dependent,
+ mp_proto_dependent,true);
+ type(p)=mp_proto_dependent;
+}
+
+@ @<Transform a known big node@>=
+mp_set_up_trans(mp, c);
+if ( mp->cur_type==mp_known ) {
+ @<Transform known by known@>;
+} else {
+ pp=mp_stash_cur_exp(mp); qq=value(pp);
+ mp_make_exp_copy(mp, p); r=value(mp->cur_exp);
+ if ( mp->cur_type==mp_transform_type ) {
+ mp_bilin2(mp, yy_part_loc(r),yy_part_loc(qq),
+ value(xy_part_loc(q)),yx_part_loc(qq),null);
+ mp_bilin2(mp, yx_part_loc(r),yy_part_loc(qq),
+ value(xx_part_loc(q)),yx_part_loc(qq),null);
+ mp_bilin2(mp, xy_part_loc(r),xx_part_loc(qq),
+ value(yy_part_loc(q)),xy_part_loc(qq),null);
+ mp_bilin2(mp, xx_part_loc(r),xx_part_loc(qq),
+ value(yx_part_loc(q)),xy_part_loc(qq),null);
+ };
+ mp_bilin2(mp, y_part_loc(r),yy_part_loc(qq),
+ value(x_part_loc(q)),yx_part_loc(qq),y_part_loc(qq));
+ mp_bilin2(mp, x_part_loc(r),xx_part_loc(qq),
+ value(y_part_loc(q)),xy_part_loc(qq),x_part_loc(qq));
+ mp_recycle_value(mp, pp); mp_free_node(mp, pp,value_node_size);
+}
+
+@ Let |p| be a |mp_proto_dependent| value whose dependency list ends
+at |dep_final|. The following procedure adds |v| times another
+numeric quantity to~|p|.
+
+@<Declare subroutines needed by |big_trans|@>=
+void mp_add_mult_dep (MP mp,pointer p, scaled v, pointer r) {
+ if ( type(r)==mp_known ) {
+ value(mp->dep_final)+=mp_take_scaled(mp, value(r),v);
+ } else {
+ dep_list(p)=mp_p_plus_fq(mp, dep_list(p),v,dep_list(r),
+ mp_proto_dependent,type(r));
+ if ( mp->fix_needed ) mp_fix_dependencies(mp);
+ }
+}
+
+@ The |bilin2| procedure is something like |bilin1|, but with known
+and unknown quantities reversed. Parameter |p| points to a value field
+within the big node for |cur_exp|; and |type(p)=mp_known|. Parameters
+|t| and~|u| point to value fields elsewhere; so does parameter~|q|,
+unless it is |null| (which stands for zero). Location~|p| will be
+replaced by $p\cdot t+v\cdot u+q$.
+
+@<Declare subroutines needed by |big_trans|@>=
+void mp_bilin2 (MP mp,pointer p, pointer t, scaled v,
+ pointer u, pointer q) {
+ scaled vv; /* temporary storage for |value(p)| */
+ vv=value(p); type(p)=mp_proto_dependent;
+ mp_new_dep(mp, p,mp_const_dependency(mp, 0)); /* this sets |dep_final| */
+ if ( vv!=0 )
+ mp_add_mult_dep(mp, p,vv,t); /* |dep_final| doesn't change */
+ if ( v!=0 ) mp_add_mult_dep(mp, p,v,u);
+ if ( q!=null ) mp_add_mult_dep(mp, p,unity,q);
+ if ( dep_list(p)==mp->dep_final ) {
+ vv=value(mp->dep_final); mp_recycle_value(mp, p);
+ type(p)=mp_known; value(p)=vv;
+ }
+}
+
+@ @<Transform known by known@>=
+{
+ mp_make_exp_copy(mp, p); r=value(mp->cur_exp);
+ if ( mp->cur_type==mp_transform_type ) {
+ mp_bilin3(mp, yy_part_loc(r),mp->tyy,value(xy_part_loc(q)),mp->tyx,0);
+ mp_bilin3(mp, yx_part_loc(r),mp->tyy,value(xx_part_loc(q)),mp->tyx,0);
+ mp_bilin3(mp, xy_part_loc(r),mp->txx,value(yy_part_loc(q)),mp->txy,0);
+ mp_bilin3(mp, xx_part_loc(r),mp->txx,value(yx_part_loc(q)),mp->txy,0);
+ }
+ mp_bilin3(mp, y_part_loc(r),mp->tyy,value(x_part_loc(q)),mp->tyx,mp->ty);
+ mp_bilin3(mp, x_part_loc(r),mp->txx,value(y_part_loc(q)),mp->txy,mp->tx);
+}
+
+@ Finally, in |bilin3| everything is |known|.
+
+@<Declare subroutines needed by |big_trans|@>=
+void mp_bilin3 (MP mp,pointer p, scaled t,
+ scaled v, scaled u, scaled delta) {
+ if ( t!=unity )
+ delta+=mp_take_scaled(mp, value(p),t);
+ else
+ delta+=value(p);
+ if ( u!=0 ) value(p)=delta+mp_take_scaled(mp, v,u);
+ else value(p)=delta;
+}
+
+@ @<Additional cases of binary operators@>=
+case concatenate:
+ if ( (mp->cur_type==mp_string_type)&&(type(p)==mp_string_type) ) mp_cat(mp, p);
+ else mp_bad_binary(mp, p,concatenate);
+ break;
+case substring_of:
+ if ( mp_nice_pair(mp, p,type(p))&&(mp->cur_type==mp_string_type) )
+ mp_chop_string(mp, value(p));
+ else mp_bad_binary(mp, p,substring_of);
+ break;
+case subpath_of:
+ if ( mp->cur_type==mp_pair_type ) mp_pair_to_path(mp);
+ if ( mp_nice_pair(mp, p,type(p))&&(mp->cur_type==mp_path_type) )
+ mp_chop_path(mp, value(p));
+ else mp_bad_binary(mp, p,subpath_of);
+ break;
+
+@ @<Declare binary action...@>=
+void mp_cat (MP mp,pointer p) {
+ str_number a,b; /* the strings being concatenated */
+ pool_pointer k; /* index into |str_pool| */
+ a=value(p); b=mp->cur_exp; str_room(length(a)+length(b));
+ for (k=mp->str_start[a];k<=str_stop(a)-1;k++) {
+ append_char(mp->str_pool[k]);
+ }
+ for (k=mp->str_start[b];k<=str_stop(b)-1;k++) {
+ append_char(mp->str_pool[k]);
+ }
+ mp->cur_exp=mp_make_string(mp); delete_str_ref(b);
+}
+
+@ @<Declare binary action...@>=
+void mp_chop_string (MP mp,pointer p) {
+ integer a, b; /* start and stop points */
+ integer l; /* length of the original string */
+ integer k; /* runs from |a| to |b| */
+ str_number s; /* the original string */
+ boolean reversed; /* was |a>b|? */
+ a=mp_round_unscaled(mp, value(x_part_loc(p)));
+ b=mp_round_unscaled(mp, value(y_part_loc(p)));
+ if ( a<=b ) reversed=false;
+ else { reversed=true; k=a; a=b; b=k; };
+ s=mp->cur_exp; l=length(s);
+ if ( a<0 ) {
+ a=0;
+ if ( b<0 ) b=0;
+ }
+ if ( b>l ) {
+ b=l;
+ if ( a>l ) a=l;
+ }
+ str_room(b-a);
+ if ( reversed ) {
+ for (k=mp->str_start[s]+b-1;k>=mp->str_start[s]+a;k--) {
+ append_char(mp->str_pool[k]);
+ }
+ } else {
+ for (k=mp->str_start[s]+a;k<=mp->str_start[s]+b-1;k++) {
+ append_char(mp->str_pool[k]);
+ }
+ }
+ mp->cur_exp=mp_make_string(mp); delete_str_ref(s);
+}
+
+@ @<Declare binary action...@>=
+void mp_chop_path (MP mp,pointer p) {
+ pointer q; /* a knot in the original path */
+ pointer pp,qq,rr,ss; /* link variables for copies of path nodes */
+ scaled a,b,k,l; /* indices for chopping */
+ boolean reversed; /* was |a>b|? */
+ l=mp_path_length(mp); a=value(x_part_loc(p)); b=value(y_part_loc(p));
+ if ( a<=b ) reversed=false;
+ else { reversed=true; k=a; a=b; b=k; };
+ @<Dispense with the cases |a<0| and/or |b>l|@>;
+ q=mp->cur_exp;
+ while ( a>=unity ) {
+ q=link(q); a=a-unity; b=b-unity;
+ }
+ if ( b==a ) {
+ @<Construct a path from |pp| to |qq| of length zero@>;
+ } else {
+ @<Construct a path from |pp| to |qq| of length $\lceil b\rceil$@>;
+ }
+ left_type(pp)=mp_endpoint; right_type(qq)=mp_endpoint; link(qq)=pp;
+ mp_toss_knot_list(mp, mp->cur_exp);
+ if ( reversed ) {
+ mp->cur_exp=link(mp_htap_ypoc(mp, pp)); mp_toss_knot_list(mp, pp);
+ } else {
+ mp->cur_exp=pp;
+ }
+}
+
+@ @<Dispense with the cases |a<0| and/or |b>l|@>=
+if ( a<0 ) {
+ if ( left_type(mp->cur_exp)==mp_endpoint ) {
+ a=0; if ( b<0 ) b=0;
+ } else {
+ do { a=a+l; b=b+l; } while (a<0); /* a cycle always has length |l>0| */
+ }
+}
+if ( b>l ) {
+ if ( left_type(mp->cur_exp)==mp_endpoint ) {
+ b=l; if ( a>l ) a=l;
+ } else {
+ while ( a>=l ) {
+ a=a-l; b=b-l;
+ }
+ }
+}
+
+@ @<Construct a path from |pp| to |qq| of length $\lceil b\rceil$@>=
+{
+ pp=mp_copy_knot(mp, q); qq=pp;
+ do {
+ q=link(q); rr=qq; qq=mp_copy_knot(mp, q); link(rr)=qq; b=b-unity;
+ } while (b>0);
+ if ( a>0 ) {
+ ss=pp; pp=link(pp);
+ mp_split_cubic(mp, ss,a*010000); pp=link(ss);
+ mp_free_node(mp, ss,knot_node_size);
+ if ( rr==ss ) {
+ b=mp_make_scaled(mp, b,unity-a); rr=pp;
+ }
+ }
+ if ( b<0 ) {
+ mp_split_cubic(mp, rr,(b+unity)*010000);
+ mp_free_node(mp, qq,knot_node_size);
+ qq=link(rr);
+ }
+}
+
+@ @<Construct a path from |pp| to |qq| of length zero@>=
+{
+ if ( a>0 ) { mp_split_cubic(mp, q,a*010000); q=link(q); };
+ pp=mp_copy_knot(mp, q); qq=pp;
+}
+
+@ @<Additional cases of binary operators@>=
+case point_of: case precontrol_of: case postcontrol_of:
+ if ( mp->cur_type==mp_pair_type )
+ mp_pair_to_path(mp);
+ if ( (mp->cur_type==mp_path_type)&&(type(p)==mp_known) )
+ mp_find_point(mp, value(p),c);
+ else
+ mp_bad_binary(mp, p,c);
+ break;
+case pen_offset_of:
+ if ( (mp->cur_type==mp_pen_type)&& mp_nice_pair(mp, p,type(p)) )
+ mp_set_up_offset(mp, value(p));
+ else
+ mp_bad_binary(mp, p,pen_offset_of);
+ break;
+case direction_time_of:
+ if ( mp->cur_type==mp_pair_type ) mp_pair_to_path(mp);
+ if ( (mp->cur_type==mp_path_type)&& mp_nice_pair(mp, p,type(p)) )
+ mp_set_up_direction_time(mp, value(p));
+ else
+ mp_bad_binary(mp, p,direction_time_of);
+ break;
+case envelope_of:
+ if ( (type(p) != mp_pen_type) || (mp->cur_type != mp_path_type) )
+ mp_bad_binary(mp, p,envelope_of);
+ else
+ mp_set_up_envelope(mp, p);
+ break;
+
+@ @<Declare binary action...@>=
+void mp_set_up_offset (MP mp,pointer p) {
+ mp_find_offset(mp, value(x_part_loc(p)),value(y_part_loc(p)),mp->cur_exp);
+ mp_pair_value(mp, mp->cur_x,mp->cur_y);
+}
+void mp_set_up_direction_time (MP mp,pointer p) {
+ mp_flush_cur_exp(mp, mp_find_direction_time(mp, value(x_part_loc(p)),
+ value(y_part_loc(p)),mp->cur_exp));
+}
+void mp_set_up_envelope (MP mp,pointer p) {
+ small_number ljoin, lcap;
+ scaled miterlim;
+ pointer q = mp_copy_path(mp, mp->cur_exp); /* the original path */
+ /* TODO: accept elliptical pens for straight paths */
+ if (pen_is_elliptical(value(p))) {
+ mp_bad_envelope_pen(mp);
+ mp->cur_exp = q;
+ mp->cur_type = mp_path_type;
+ return;
+ }
+ if ( mp->internal[mp_linejoin]>unity ) ljoin=2;
+ else if ( mp->internal[mp_linejoin]>0 ) ljoin=1;
+ else ljoin=0;
+ if ( mp->internal[mp_linecap]>unity ) lcap=2;
+ else if ( mp->internal[mp_linecap]>0 ) lcap=1;
+ else lcap=0;
+ if ( mp->internal[mp_miterlimit]<unity )
+ miterlim=unity;
+ else
+ miterlim=mp->internal[mp_miterlimit];
+ mp->cur_exp = mp_make_envelope(mp, q, value(p), ljoin,lcap,miterlim);
+ mp->cur_type = mp_path_type;
+}
+
+@ @<Declare binary action...@>=
+void mp_find_point (MP mp,scaled v, quarterword c) {
+ pointer p; /* the path */
+ scaled n; /* its length */
+ p=mp->cur_exp;
+ if ( left_type(p)==mp_endpoint ) n=-unity; else n=0;
+ do { p=link(p); n=n+unity; } while (p!=mp->cur_exp);
+ if ( n==0 ) {
+ v=0;
+ } else if ( v<0 ) {
+ if ( left_type(p)==mp_endpoint ) v=0;
+ else v=n-1-((-v-1) % n);
+ } else if ( v>n ) {
+ if ( left_type(p)==mp_endpoint ) v=n;
+ else v=v % n;
+ }
+ p=mp->cur_exp;
+ while ( v>=unity ) { p=link(p); v=v-unity; };
+ if ( v!=0 ) {
+ @<Insert a fractional node by splitting the cubic@>;
+ }
+ @<Set the current expression to the desired path coordinates@>;
+}
+
+@ @<Insert a fractional node...@>=
+{ mp_split_cubic(mp, p,v*010000); p=link(p); }
+
+@ @<Set the current expression to the desired path coordinates...@>=
+switch (c) {
+case point_of:
+ mp_pair_value(mp, x_coord(p),y_coord(p));
+ break;
+case precontrol_of:
+ if ( left_type(p)==mp_endpoint ) mp_pair_value(mp, x_coord(p),y_coord(p));
+ else mp_pair_value(mp, left_x(p),left_y(p));
+ break;
+case postcontrol_of:
+ if ( right_type(p)==mp_endpoint ) mp_pair_value(mp, x_coord(p),y_coord(p));
+ else mp_pair_value(mp, right_x(p),right_y(p));
+ break;
+} /* there are no other cases */
+
+@ @<Additional cases of binary operators@>=
+case arc_time_of:
+ if ( mp->cur_type==mp_pair_type )
+ mp_pair_to_path(mp);
+ if ( (mp->cur_type==mp_path_type)&&(type(p)==mp_known) )
+ mp_flush_cur_exp(mp, mp_get_arc_time(mp, mp->cur_exp,value(p)));
+ else
+ mp_bad_binary(mp, p,c);
+ break;
+
+@ @<Additional cases of bin...@>=
+case intersect:
+ if ( type(p)==mp_pair_type ) {
+ q=mp_stash_cur_exp(mp); mp_unstash_cur_exp(mp, p);
+ mp_pair_to_path(mp); p=mp_stash_cur_exp(mp); mp_unstash_cur_exp(mp, q);
+ };
+ if ( mp->cur_type==mp_pair_type ) mp_pair_to_path(mp);
+ if ( (mp->cur_type==mp_path_type)&&(type(p)==mp_path_type) ) {
+ mp_path_intersection(mp, value(p),mp->cur_exp);
+ mp_pair_value(mp, mp->cur_t,mp->cur_tt);
+ } else {
+ mp_bad_binary(mp, p,intersect);
+ }
+ break;
+
+@ @<Additional cases of bin...@>=
+case in_font:
+ if ( (mp->cur_type!=mp_string_type)||(type(p)!=mp_string_type))
+ mp_bad_binary(mp, p,in_font);
+ else { mp_do_infont(mp, p); binary_return; }
+ break;
+
+@ Function |new_text_node| owns the reference count for its second argument
+(the text string) but not its first (the font name).
+
+@<Declare binary action...@>=
+void mp_do_infont (MP mp,pointer p) {
+ pointer q;
+ q=mp_get_node(mp, edge_header_size);
+ mp_init_edges(mp, q);
+ link(obj_tail(q))=mp_new_text_node(mp,str(mp->cur_exp),value(p));
+ obj_tail(q)=link(obj_tail(q));
+ mp_free_node(mp, p,value_node_size);
+ mp_flush_cur_exp(mp, q);
+ mp->cur_type=mp_picture_type;
+}
+
+@* \[40] Statements and commands.
+The chief executive of \MP\ is the |do_statement| routine, which
+contains the master switch that causes all the various pieces of \MP\
+to do their things, in the right order.
+
+In a sense, this is the grand climax of the program: It applies all the
+tools that we have worked so hard to construct. In another sense, this is
+the messiest part of the program: It necessarily refers to other pieces
+of code all over the place, so that a person can't fully understand what is
+going on without paging back and forth to be reminded of conventions that
+are defined elsewhere. We are now at the hub of the web.
+
+The structure of |do_statement| itself is quite simple. The first token
+of the statement is fetched using |get_x_next|. If it can be the first
+token of an expression, we look for an equation, an assignment, or a
+title. Otherwise we use a \&{case} construction to branch at high speed to
+the appropriate routine for various and sundry other types of commands,
+each of which has an ``action procedure'' that does the necessary work.
+
+The program uses the fact that
+$$\hbox{|min_primary_command=max_statement_command=type_name|}$$
+to interpret a statement that starts with, e.g., `\&{string}',
+as a type declaration rather than a boolean expression.
+
+@c void mp_do_statement (MP mp) { /* governs \MP's activities */
+ mp->cur_type=mp_vacuous; mp_get_x_next(mp);
+ if ( mp->cur_cmd>max_primary_command ) {
+ @<Worry about bad statement@>;
+ } else if ( mp->cur_cmd>max_statement_command ) {
+ @<Do an equation, assignment, title, or
+ `$\langle\,$expression$\,\rangle\,$\&{endgroup}'@>;
+ } else {
+ @<Do a statement that doesn't begin with an expression@>;
+ }
+ if ( mp->cur_cmd<semicolon )
+ @<Flush unparsable junk that was found after the statement@>;
+ mp->error_count=0;
+}
+
+@ @<Declarations@>=
+@<Declare action procedures for use by |do_statement|@>
+
+@ The only command codes |>max_primary_command| that can be present
+at the beginning of a statement are |semicolon| and higher; these
+occur when the statement is null.
+
+@<Worry about bad statement@>=
+{
+ if ( mp->cur_cmd<semicolon ) {
+ print_err("A statement can't begin with `");
+@.A statement can't begin with x@>
+ mp_print_cmd_mod(mp, mp->cur_cmd,mp->cur_mod); mp_print_char(mp, '\'');
+ help5("I was looking for the beginning of a new statement.")
+ ("If you just proceed without changing anything, I'll ignore")
+ ("everything up to the next `;'. Please insert a semicolon")
+ ("now in front of anything that you don't want me to delete.")
+ ("(See Chapter 27 of The METAFONTbook for an example.)");
+@:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
+ mp_back_error(mp); mp_get_x_next(mp);
+ }
+}
+
+@ The help message printed here says that everything is flushed up to
+a semicolon, but actually the commands |end_group| and |stop| will
+also terminate a statement.
+
+@<Flush unparsable junk that was found after the statement@>=
+{
+ print_err("Extra tokens will be flushed");
+@.Extra tokens will be flushed@>
+ help6("I've just read as much of that statement as I could fathom,")
+ ("so a semicolon should have been next. It's very puzzling...")
+ ("but I'll try to get myself back together, by ignoring")
+ ("everything up to the next `;'. Please insert a semicolon")
+ ("now in front of anything that you don't want me to delete.")
+ ("(See Chapter 27 of The METAFONTbook for an example.)");
+@:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
+ mp_back_error(mp); mp->scanner_status=flushing;
+ do {
+ get_t_next;
+ @<Decrease the string reference count...@>;
+ } while (! end_of_statement); /* |cur_cmd=semicolon|, |end_group|, or |stop| */
+ mp->scanner_status=normal;
+}
+
+@ If |do_statement| ends with |cur_cmd=end_group|, we should have
+|cur_type=mp_vacuous| unless the statement was simply an expression;
+in the latter case, |cur_type| and |cur_exp| should represent that
+expression.
+
+@<Do a statement that doesn't...@>=
+{
+ if ( mp->internal[mp_tracing_commands]>0 )
+ show_cur_cmd_mod;
+ switch (mp->cur_cmd ) {
+ case type_name:mp_do_type_declaration(mp); break;
+ case macro_def:
+ if ( mp->cur_mod>var_def ) mp_make_op_def(mp);
+ else if ( mp->cur_mod>end_def ) mp_scan_def(mp);
+ break;
+ @<Cases of |do_statement| that invoke particular commands@>;
+ } /* there are no other cases */
+ mp->cur_type=mp_vacuous;
+}
+
+@ The most important statements begin with expressions.
+
+@<Do an equation, assignment, title, or...@>=
+{
+ mp->var_flag=assignment; mp_scan_expression(mp);
+ if ( mp->cur_cmd<end_group ) {
+ if ( mp->cur_cmd==equals ) mp_do_equation(mp);
+ else if ( mp->cur_cmd==assignment ) mp_do_assignment(mp);
+ else if ( mp->cur_type==mp_string_type ) {@<Do a title@> ; }
+ else if ( mp->cur_type!=mp_vacuous ){
+ exp_err("Isolated expression");
+@.Isolated expression@>
+ help3("I couldn't find an `=' or `:=' after the")
+ ("expression that is shown above this error message,")
+ ("so I guess I'll just ignore it and carry on.");
+ mp_put_get_error(mp);
+ }
+ mp_flush_cur_exp(mp, 0); mp->cur_type=mp_vacuous;
+ }
+}
+
+@ @<Do a title@>=
+{
+ if ( mp->internal[mp_tracing_titles]>0 ) {
+ mp_print_nl(mp, ""); mp_print_str(mp, mp->cur_exp); update_terminal;
+ }
+}
+
+@ Equations and assignments are performed by the pair of mutually recursive
+@^recursion@>
+routines |do_equation| and |do_assignment|. These routines are called when
+|cur_cmd=equals| and when |cur_cmd=assignment|, respectively; the left-hand
+side is in |cur_type| and |cur_exp|, while the right-hand side is yet
+to be scanned. After the routines are finished, |cur_type| and |cur_exp|
+will be equal to the right-hand side (which will normally be equal
+to the left-hand side).
+
+@<Declare action procedures for use by |do_statement|@>=
+@<Declare the procedure called |try_eq|@>
+@<Declare the procedure called |make_eq|@>
+void mp_do_equation (MP mp) ;
+
+@ @c
+void mp_do_equation (MP mp) {
+ pointer lhs; /* capsule for the left-hand side */
+ pointer p; /* temporary register */
+ lhs=mp_stash_cur_exp(mp); mp_get_x_next(mp);
+ mp->var_flag=assignment; mp_scan_expression(mp);
+ if ( mp->cur_cmd==equals ) mp_do_equation(mp);
+ else if ( mp->cur_cmd==assignment ) mp_do_assignment(mp);
+ if ( mp->internal[mp_tracing_commands]>two )
+ @<Trace the current equation@>;
+ if ( mp->cur_type==mp_unknown_path ) if ( type(lhs)==mp_pair_type ) {
+ p=mp_stash_cur_exp(mp); mp_unstash_cur_exp(mp, lhs); lhs=p;
+ }; /* in this case |make_eq| will change the pair to a path */
+ mp_make_eq(mp, lhs); /* equate |lhs| to |(cur_type,cur_exp)| */
+}
+
+@ And |do_assignment| is similar to |do_equation|:
+
+@<Declarations@>=
+void mp_do_assignment (MP mp);
+
+@ @<Declare action procedures for use by |do_statement|@>=
+void mp_do_assignment (MP mp) ;
+
+@ @c
+void mp_do_assignment (MP mp) {
+ pointer lhs; /* token list for the left-hand side */
+ pointer p; /* where the left-hand value is stored */
+ pointer q; /* temporary capsule for the right-hand value */
+ if ( mp->cur_type!=mp_token_list ) {
+ exp_err("Improper `:=' will be changed to `='");
+@.Improper `:='@>
+ help2("I didn't find a variable name at the left of the `:=',")
+ ("so I'm going to pretend that you said `=' instead.");
+ mp_error(mp); mp_do_equation(mp);
+ } else {
+ lhs=mp->cur_exp; mp->cur_type=mp_vacuous;
+ mp_get_x_next(mp); mp->var_flag=assignment; mp_scan_expression(mp);
+ if ( mp->cur_cmd==equals ) mp_do_equation(mp);
+ else if ( mp->cur_cmd==assignment ) mp_do_assignment(mp);
+ if ( mp->internal[mp_tracing_commands]>two )
+ @<Trace the current assignment@>;
+ if ( info(lhs)>hash_end ) {
+ @<Assign the current expression to an internal variable@>;
+ } else {
+ @<Assign the current expression to the variable |lhs|@>;
+ }
+ mp_flush_node_list(mp, lhs);
+ }
+}
+
+@ @<Trace the current equation@>=
+{
+ mp_begin_diagnostic(mp); mp_print_nl(mp, "{("); mp_print_exp(mp,lhs,0);
+ mp_print(mp,")=("); mp_print_exp(mp,null,0);
+ mp_print(mp,")}"); mp_end_diagnostic(mp, false);
+}
+
+@ @<Trace the current assignment@>=
+{
+ mp_begin_diagnostic(mp); mp_print_nl(mp, "{");
+ if ( info(lhs)>hash_end )
+ mp_print(mp, mp->int_name[info(lhs)-(hash_end)]);
+ else
+ mp_show_token_list(mp, lhs,null,1000,0);
+ mp_print(mp, ":="); mp_print_exp(mp, null,0);
+ mp_print_char(mp, '}'); mp_end_diagnostic(mp, false);
+}
+
+@ @<Assign the current expression to an internal variable@>=
+if ( mp->cur_type==mp_known ) {
+ mp->internal[info(lhs)-(hash_end)]=mp->cur_exp;
+} else {
+ exp_err("Internal quantity `");
+@.Internal quantity...@>
+ mp_print(mp, mp->int_name[info(lhs)-(hash_end)]);
+ mp_print(mp, "' must receive a known value");
+ help2("I can\'t set an internal quantity to anything but a known")
+ ("numeric value, so I'll have to ignore this assignment.");
+ mp_put_get_error(mp);
+}
+
+@ @<Assign the current expression to the variable |lhs|@>=
+{
+ p=mp_find_variable(mp, lhs);
+ if ( p!=null ) {
+ q=mp_stash_cur_exp(mp); mp->cur_type=mp_und_type(mp, p);
+ mp_recycle_value(mp, p);
+ type(p)=mp->cur_type; value(p)=null; mp_make_exp_copy(mp, p);
+ p=mp_stash_cur_exp(mp); mp_unstash_cur_exp(mp, q); mp_make_eq(mp, p);
+ } else {
+ mp_obliterated(mp, lhs); mp_put_get_error(mp);
+ }
+}
+
+
+@ And now we get to the nitty-gritty. The |make_eq| procedure is given
+a pointer to a capsule that is to be equated to the current expression.
+
+@<Declare the procedure called |make_eq|@>=
+void mp_make_eq (MP mp,pointer lhs) ;
+
+
+@
+@c void mp_make_eq (MP mp,pointer lhs) {
+ small_number t; /* type of the left-hand side */
+ pointer p,q; /* pointers inside of big nodes */
+ integer v=0; /* value of the left-hand side */
+RESTART:
+ t=type(lhs);
+ if ( t<=mp_pair_type ) v=value(lhs);
+ switch (t) {
+ @<For each type |t|, make an equation and |goto done| unless |cur_type|
+ is incompatible with~|t|@>;
+ } /* all cases have been listed */
+ @<Announce that the equation cannot be performed@>;
+DONE:
+ check_arith; mp_recycle_value(mp, lhs);
+ mp_free_node(mp, lhs,value_node_size);
+}
+
+@ @<Announce that the equation cannot be performed@>=
+mp_disp_err(mp, lhs,"");
+exp_err("Equation cannot be performed (");
+@.Equation cannot be performed@>
+if ( type(lhs)<=mp_pair_type ) mp_print_type(mp, type(lhs));
+else mp_print(mp, "numeric");
+mp_print_char(mp, '=');
+if ( mp->cur_type<=mp_pair_type ) mp_print_type(mp, mp->cur_type);
+else mp_print(mp, "numeric");
+mp_print_char(mp, ')');
+help2("I'm sorry, but I don't know how to make such things equal.")
+ ("(See the two expressions just above the error message.)");
+mp_put_get_error(mp)
+
+@ @<For each type |t|, make an equation and |goto done| unless...@>=
+case mp_boolean_type: case mp_string_type: case mp_pen_type:
+case mp_path_type: case mp_picture_type:
+ if ( mp->cur_type==t+unknown_tag ) {
+ mp_nonlinear_eq(mp, v,mp->cur_exp,false);
+ mp_unstash_cur_exp(mp, mp->cur_exp); goto DONE;
+ } else if ( mp->cur_type==t ) {
+ @<Report redundant or inconsistent equation and |goto done|@>;
+ }
+ break;
+case unknown_types:
+ if ( mp->cur_type==t-unknown_tag ) {
+ mp_nonlinear_eq(mp, mp->cur_exp,lhs,true); goto DONE;
+ } else if ( mp->cur_type==t ) {
+ mp_ring_merge(mp, lhs,mp->cur_exp); goto DONE;
+ } else if ( mp->cur_type==mp_pair_type ) {
+ if ( t==mp_unknown_path ) {
+ mp_pair_to_path(mp); goto RESTART;
+ };
+ }
+ break;
+case mp_transform_type: case mp_color_type:
+case mp_cmykcolor_type: case mp_pair_type:
+ if ( mp->cur_type==t ) {
+ @<Do multiple equations and |goto done|@>;
+ }
+ break;
+case mp_known: case mp_dependent:
+case mp_proto_dependent: case mp_independent:
+ if ( mp->cur_type>=mp_known ) {
+ mp_try_eq(mp, lhs,null); goto DONE;
+ };
+ break;
+case mp_vacuous:
+ break;
+
+@ @<Report redundant or inconsistent equation and |goto done|@>=
+{
+ if ( mp->cur_type<=mp_string_type ) {
+ if ( mp->cur_type==mp_string_type ) {
+ if ( mp_str_vs_str(mp, v,mp->cur_exp)!=0 ) {
+ goto NOT_FOUND;
+ }
+ } else if ( v!=mp->cur_exp ) {
+ goto NOT_FOUND;
+ }
+ @<Exclaim about a redundant equation@>; goto DONE;
+ }
+ print_err("Redundant or inconsistent equation");
+@.Redundant or inconsistent equation@>
+ help2("An equation between already-known quantities can't help.")
+ ("But don't worry; continue and I'll just ignore it.");
+ mp_put_get_error(mp); goto DONE;
+NOT_FOUND:
+ print_err("Inconsistent equation");
+@.Inconsistent equation@>
+ help2("The equation I just read contradicts what was said before.")
+ ("But don't worry; continue and I'll just ignore it.");
+ mp_put_get_error(mp); goto DONE;
+}
+
+@ @<Do multiple equations and |goto done|@>=
+{
+ p=v+mp->big_node_size[t];
+ q=value(mp->cur_exp)+mp->big_node_size[t];
+ do {
+ p=p-2; q=q-2; mp_try_eq(mp, p,q);
+ } while (p!=v);
+ goto DONE;
+}
+
+@ The first argument to |try_eq| is the location of a value node
+in a capsule that will soon be recycled. The second argument is
+either a location within a pair or transform node pointed to by
+|cur_exp|, or it is |null| (which means that |cur_exp| itself
+serves as the second argument). The idea is to leave |cur_exp| unchanged,
+but to equate the two operands.
+
+@<Declare the procedure called |try_eq|@>=
+void mp_try_eq (MP mp,pointer l, pointer r) ;
+
+@
+@c void mp_try_eq (MP mp,pointer l, pointer r) {
+ pointer p; /* dependency list for right operand minus left operand */
+ int t; /* the type of list |p| */
+ pointer q; /* the constant term of |p| is here */
+ pointer pp; /* dependency list for right operand */
+ int tt; /* the type of list |pp| */
+ boolean copied; /* have we copied a list that ought to be recycled? */
+ @<Remove the left operand from its container, negate it, and
+ put it into dependency list~|p| with constant term~|q|@>;
+ @<Add the right operand to list |p|@>;
+ if ( info(p)==null ) {
+ @<Deal with redundant or inconsistent equation@>;
+ } else {
+ mp_linear_eq(mp, p,t);
+ if ( r==null ) if ( mp->cur_type!=mp_known ) {
+ if ( type(mp->cur_exp)==mp_known ) {
+ pp=mp->cur_exp; mp->cur_exp=value(mp->cur_exp); mp->cur_type=mp_known;
+ mp_free_node(mp, pp,value_node_size);
+ }
+ }
+ }
+}
+
+@ @<Remove the left operand from its container, negate it, and...@>=
+t=type(l);
+if ( t==mp_known ) {
+ t=mp_dependent; p=mp_const_dependency(mp, -value(l)); q=p;
+} else if ( t==mp_independent ) {
+ t=mp_dependent; p=mp_single_dependency(mp, l); negate(value(p));
+ q=mp->dep_final;
+} else {
+ p=dep_list(l); q=p;
+ while (1) {
+ negate(value(q));
+ if ( info(q)==null ) break;
+ q=link(q);
+ }
+ link(prev_dep(l))=link(q); prev_dep(link(q))=prev_dep(l);
+ type(l)=mp_known;
+}
+
+@ @<Deal with redundant or inconsistent equation@>=
+{
+ if ( abs(value(p))>64 ) { /* off by .001 or more */
+ print_err("Inconsistent equation");
+@.Inconsistent equation@>
+ mp_print(mp, " (off by "); mp_print_scaled(mp, value(p));
+ mp_print_char(mp, ')');
+ help2("The equation I just read contradicts what was said before.")
+ ("But don't worry; continue and I'll just ignore it.");
+ mp_put_get_error(mp);
+ } else if ( r==null ) {
+ @<Exclaim about a redundant equation@>;
+ }
+ mp_free_node(mp, p,dep_node_size);
+}
+
+@ @<Add the right operand to list |p|@>=
+if ( r==null ) {
+ if ( mp->cur_type==mp_known ) {
+ value(q)=value(q)+mp->cur_exp; goto DONE1;
+ } else {
+ tt=mp->cur_type;
+ if ( tt==mp_independent ) pp=mp_single_dependency(mp, mp->cur_exp);
+ else pp=dep_list(mp->cur_exp);
+ }
+} else {
+ if ( type(r)==mp_known ) {
+ value(q)=value(q)+value(r); goto DONE1;
+ } else {
+ tt=type(r);
+ if ( tt==mp_independent ) pp=mp_single_dependency(mp, r);
+ else pp=dep_list(r);
+ }
+}
+if ( tt!=mp_independent ) copied=false;
+else { copied=true; tt=mp_dependent; };
+@<Add dependency list |pp| of type |tt| to dependency list~|p| of type~|t|@>;
+if ( copied ) mp_flush_node_list(mp, pp);
+DONE1:
+
+@ @<Add dependency list |pp| of type |tt| to dependency list~|p| of type~|t|@>=
+mp->watch_coefs=false;
+if ( t==tt ) {
+ p=mp_p_plus_q(mp, p,pp,t);
+} else if ( t==mp_proto_dependent ) {
+ p=mp_p_plus_fq(mp, p,unity,pp,mp_proto_dependent,mp_dependent);
+} else {
+ q=p;
+ while ( info(q)!=null ) {
+ value(q)=mp_round_fraction(mp, value(q)); q=link(q);
+ }
+ t=mp_proto_dependent; p=mp_p_plus_q(mp, p,pp,t);
+}
+mp->watch_coefs=true;
+
+@ Our next goal is to process type declarations. For this purpose it's
+convenient to have a procedure that scans a $\langle\,$declared
+variable$\,\rangle$ and returns the corresponding token list. After the
+following procedure has acted, the token after the declared variable
+will have been scanned, so it will appear in |cur_cmd|, |cur_mod|,
+and~|cur_sym|.
+
+@<Declare the function called |scan_declared_variable|@>=
+pointer mp_scan_declared_variable (MP mp) {
+ pointer x; /* hash address of the variable's root */
+ pointer h,t; /* head and tail of the token list to be returned */
+ pointer l; /* hash address of left bracket */
+ mp_get_symbol(mp); x=mp->cur_sym;
+ if ( mp->cur_cmd!=tag_token ) mp_clear_symbol(mp, x,false);
+ h=mp_get_avail(mp); info(h)=x; t=h;
+ while (1) {
+ mp_get_x_next(mp);
+ if ( mp->cur_sym==0 ) break;
+ if ( mp->cur_cmd!=tag_token ) if ( mp->cur_cmd!=internal_quantity) {
+ if ( mp->cur_cmd==left_bracket ) {
+ @<Descend past a collective subscript@>;
+ } else {
+ break;
+ }
+ }
+ link(t)=mp_get_avail(mp); t=link(t); info(t)=mp->cur_sym;
+ }
+ if ( (eq_type(x)%outer_tag)!=tag_token ) mp_clear_symbol(mp, x,false);
+ if ( equiv(x)==null ) mp_new_root(mp, x);
+ return h;
+}
+
+@ If the subscript isn't collective, we don't accept it as part of the
+declared variable.
+
+@<Descend past a collective subscript@>=
+{
+ l=mp->cur_sym; mp_get_x_next(mp);
+ if ( mp->cur_cmd!=right_bracket ) {
+ mp_back_input(mp); mp->cur_sym=l; mp->cur_cmd=left_bracket; break;
+ } else {
+ mp->cur_sym=collective_subscript;
+ }
+}
+
+@ Type declarations are introduced by the following primitive operations.
+
+@<Put each...@>=
+mp_primitive(mp, "numeric",type_name,mp_numeric_type);
+@:numeric_}{\&{numeric} primitive@>
+mp_primitive(mp, "string",type_name,mp_string_type);
+@:string_}{\&{string} primitive@>
+mp_primitive(mp, "boolean",type_name,mp_boolean_type);
+@:boolean_}{\&{boolean} primitive@>
+mp_primitive(mp, "path",type_name,mp_path_type);
+@:path_}{\&{path} primitive@>
+mp_primitive(mp, "pen",type_name,mp_pen_type);
+@:pen_}{\&{pen} primitive@>
+mp_primitive(mp, "picture",type_name,mp_picture_type);
+@:picture_}{\&{picture} primitive@>
+mp_primitive(mp, "transform",type_name,mp_transform_type);
+@:transform_}{\&{transform} primitive@>
+mp_primitive(mp, "color",type_name,mp_color_type);
+@:color_}{\&{color} primitive@>
+mp_primitive(mp, "rgbcolor",type_name,mp_color_type);
+@:color_}{\&{rgbcolor} primitive@>
+mp_primitive(mp, "cmykcolor",type_name,mp_cmykcolor_type);
+@:color_}{\&{cmykcolor} primitive@>
+mp_primitive(mp, "pair",type_name,mp_pair_type);
+@:pair_}{\&{pair} primitive@>
+
+@ @<Cases of |print_cmd...@>=
+case type_name: mp_print_type(mp, m); break;
+
+@ Now we are ready to handle type declarations, assuming that a
+|type_name| has just been scanned.
+
+@<Declare action procedures for use by |do_statement|@>=
+void mp_do_type_declaration (MP mp) ;
+
+@ @c
+void mp_do_type_declaration (MP mp) {
+ small_number t; /* the type being declared */
+ pointer p; /* token list for a declared variable */
+ pointer q; /* value node for the variable */
+ if ( mp->cur_mod>=mp_transform_type )
+ t=mp->cur_mod;
+ else
+ t=mp->cur_mod+unknown_tag;
+ do {
+ p=mp_scan_declared_variable(mp);
+ mp_flush_variable(mp, equiv(info(p)),link(p),false);
+ q=mp_find_variable(mp, p);
+ if ( q!=null ) {
+ type(q)=t; value(q)=null;
+ } else {
+ print_err("Declared variable conflicts with previous vardef");
+@.Declared variable conflicts...@>
+ help2("You can't use, e.g., `numeric foo[]' after `vardef foo'.")
+ ("Proceed, and I'll ignore the illegal redeclaration.");
+ mp_put_get_error(mp);
+ }
+ mp_flush_list(mp, p);
+ if ( mp->cur_cmd<comma ) {
+ @<Flush spurious symbols after the declared variable@>;
+ }
+ } while (! end_of_statement);
+}
+
+@ @<Flush spurious symbols after the declared variable@>=
+{
+ print_err("Illegal suffix of declared variable will be flushed");
+@.Illegal suffix...flushed@>
+ help5("Variables in declarations must consist entirely of")
+ ("names and collective subscripts, e.g., `x[]a'.")
+ ("Are you trying to use a reserved word in a variable name?")
+ ("I'm going to discard the junk I found here,")
+ ("up to the next comma or the end of the declaration.");
+ if ( mp->cur_cmd==numeric_token )
+ mp->help_line[2]="Explicit subscripts like `x15a' aren't permitted.";
+ mp_put_get_error(mp); mp->scanner_status=flushing;
+ do {
+ get_t_next;
+ @<Decrease the string reference count...@>;
+ } while (mp->cur_cmd<comma); /* either |end_of_statement| or |cur_cmd=comma| */
+ mp->scanner_status=normal;
+}
+
+@ \MP's |main_control| procedure just calls |do_statement| repeatedly
+until coming to the end of the user's program.
+Each execution of |do_statement| concludes with
+|cur_cmd=semicolon|, |end_group|, or |stop|.
+
+@c void mp_main_control (MP mp) {
+ do {
+ mp_do_statement(mp);
+ if ( mp->cur_cmd==end_group ) {
+ print_err("Extra `endgroup'");
+@.Extra `endgroup'@>
+ help2("I'm not currently working on a `begingroup',")
+ ("so I had better not try to end anything.");
+ mp_flush_error(mp, 0);
+ }
+ } while (mp->cur_cmd!=stop);
+}
+int __attribute__((noinline))
+mp_run (MP mp) {
+ if (mp->history < mp_fatal_error_stop ) {
+ @<Install and test the non-local jump buffer@>;
+ mp_main_control(mp); /* come to life */
+ mp_final_cleanup(mp); /* prepare for death */
+ mp_close_files_and_terminate(mp);
+ }
+ return mp->history;
+}
+int __attribute__((noinline))
+mp_execute (MP mp) {
+ if (mp->history < mp_fatal_error_stop ) {
+ mp->history = mp_spotless;
+ mp->file_offset = 0;
+ mp->term_offset = 0;
+ mp->tally = 0;
+ @<Install and test the non-local jump buffer@>;
+ if (mp->run_state==0) {
+ mp->run_state = 1;
+ } else {
+ mp_input_ln(mp,mp->term_in);
+ mp_firm_up_the_line(mp);
+ mp->buffer[limit]='%';
+ mp->first=limit+1;
+ loc=start;
+ }
+ do {
+ mp_do_statement(mp);
+ } while (mp->cur_cmd!=stop);
+ }
+ return mp->history;
+}
+int __attribute__((noinline))
+mp_finish (MP mp) {
+ if (mp->history < mp_fatal_error_stop ) {
+ @<Install and test the non-local jump buffer@>;
+ mp_final_cleanup(mp); /* prepare for death */
+ mp_close_files_and_terminate(mp);
+ }
+ return mp->history;
+}
+const char * mp_mplib_version (MP mp) {
+ (void)mp;
+ return mplib_version;
+}
+const char * mp_metapost_version (MP mp) {
+ (void)mp;
+ return metapost_version;
+}
+
+@ @<Exported function headers@>=
+int mp_run (MP mp);
+int mp_execute (MP mp);
+int mp_finish (MP mp);
+const char * mp_mplib_version (MP mp);
+const char * mp_metapost_version (MP mp);
+
+@ @<Put each...@>=
+mp_primitive(mp, "end",stop,0);
+@:end_}{\&{end} primitive@>
+mp_primitive(mp, "dump",stop,1);
+@:dump_}{\&{dump} primitive@>
+
+@ @<Cases of |print_cmd...@>=
+case stop:
+ if ( m==0 ) mp_print(mp, "end");
+ else mp_print(mp, "dump");
+ break;
+
+@* \[41] Commands.
+Let's turn now to statements that are classified as ``commands'' because
+of their imperative nature. We'll begin with simple ones, so that it
+will be clear how to hook command processing into the |do_statement| routine;
+then we'll tackle the tougher commands.
+
+Here's one of the simplest:
+
+@<Cases of |do_statement|...@>=
+case mp_random_seed: mp_do_random_seed(mp); break;
+
+@ @<Declare action procedures for use by |do_statement|@>=
+void mp_do_random_seed (MP mp) ;
+
+@ @c void mp_do_random_seed (MP mp) {
+ mp_get_x_next(mp);
+ if ( mp->cur_cmd!=assignment ) {
+ mp_missing_err(mp, ":=");
+@.Missing `:='@>
+ help1("Always say `randomseed:=<numeric expression>'.");
+ mp_back_error(mp);
+ };
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type!=mp_known ) {
+ exp_err("Unknown value will be ignored");
+@.Unknown value...ignored@>
+ help2("Your expression was too random for me to handle,")
+ ("so I won't change the random seed just now.");
+ mp_put_get_flush_error(mp, 0);
+ } else {
+ @<Initialize the random seed to |cur_exp|@>;
+ }
+}
+
+@ @<Initialize the random seed to |cur_exp|@>=
+{
+ mp_init_randoms(mp, mp->cur_exp);
+ if ( mp->selector>=log_only && mp->selector<write_file) {
+ mp->old_setting=mp->selector; mp->selector=log_only;
+ mp_print_nl(mp, "{randomseed:=");
+ mp_print_scaled(mp, mp->cur_exp);
+ mp_print_char(mp, '}');
+ mp_print_nl(mp, ""); mp->selector=mp->old_setting;
+ }
+}
+
+@ And here's another simple one (somewhat different in flavor):
+
+@<Cases of |do_statement|...@>=
+case mode_command:
+ mp_print_ln(mp); mp->interaction=mp->cur_mod;
+ @<Initialize the print |selector| based on |interaction|@>;
+ if ( mp->log_opened ) mp->selector=mp->selector+2;
+ mp_get_x_next(mp);
+ break;
+
+@ @<Put each...@>=
+mp_primitive(mp, "batchmode",mode_command,mp_batch_mode);
+@:mp_batch_mode_}{\&{batchmode} primitive@>
+mp_primitive(mp, "nonstopmode",mode_command,mp_nonstop_mode);
+@:mp_nonstop_mode_}{\&{nonstopmode} primitive@>
+mp_primitive(mp, "scrollmode",mode_command,mp_scroll_mode);
+@:mp_scroll_mode_}{\&{scrollmode} primitive@>
+mp_primitive(mp, "errorstopmode",mode_command,mp_error_stop_mode);
+@:mp_error_stop_mode_}{\&{errorstopmode} primitive@>
+
+@ @<Cases of |print_cmd_mod|...@>=
+case mode_command:
+ switch (m) {
+ case mp_batch_mode: mp_print(mp, "batchmode"); break;
+ case mp_nonstop_mode: mp_print(mp, "nonstopmode"); break;
+ case mp_scroll_mode: mp_print(mp, "scrollmode"); break;
+ default: mp_print(mp, "errorstopmode"); break;
+ }
+ break;
+
+@ The `\&{inner}' and `\&{outer}' commands are only slightly harder.
+
+@<Cases of |do_statement|...@>=
+case protection_command: mp_do_protection(mp); break;
+
+@ @<Put each...@>=
+mp_primitive(mp, "inner",protection_command,0);
+@:inner_}{\&{inner} primitive@>
+mp_primitive(mp, "outer",protection_command,1);
+@:outer_}{\&{outer} primitive@>
+
+@ @<Cases of |print_cmd...@>=
+case protection_command:
+ if ( m==0 ) mp_print(mp, "inner");
+ else mp_print(mp, "outer");
+ break;
+
+@ @<Declare action procedures for use by |do_statement|@>=
+void mp_do_protection (MP mp) ;
+
+@ @c void mp_do_protection (MP mp) {
+ int m; /* 0 to unprotect, 1 to protect */
+ halfword t; /* the |eq_type| before we change it */
+ m=mp->cur_mod;
+ do {
+ mp_get_symbol(mp); t=eq_type(mp->cur_sym);
+ if ( m==0 ) {
+ if ( t>=outer_tag )
+ eq_type(mp->cur_sym)=t-outer_tag;
+ } else if ( t<outer_tag ) {
+ eq_type(mp->cur_sym)=t+outer_tag;
+ }
+ mp_get_x_next(mp);
+ } while (mp->cur_cmd==comma);
+}
+
+@ \MP\ never defines the tokens `\.(' and `\.)' to be primitives, but
+plain \MP\ begins with the declaration `\&{delimiters} \.{()}'. Such a
+declaration assigns the command code |left_delimiter| to `\.{(}' and
+|right_delimiter| to `\.{)}'; the |equiv| of each delimiter is the
+hash address of its mate.
+
+@<Cases of |do_statement|...@>=
+case delimiters: mp_def_delims(mp); break;
+
+@ @<Declare action procedures for use by |do_statement|@>=
+void mp_def_delims (MP mp) ;
+
+@ @c void mp_def_delims (MP mp) {
+ pointer l_delim,r_delim; /* the new delimiter pair */
+ mp_get_clear_symbol(mp); l_delim=mp->cur_sym;
+ mp_get_clear_symbol(mp); r_delim=mp->cur_sym;
+ eq_type(l_delim)=left_delimiter; equiv(l_delim)=r_delim;
+ eq_type(r_delim)=right_delimiter; equiv(r_delim)=l_delim;
+ mp_get_x_next(mp);
+}
+
+@ Here is a procedure that is called when \MP\ has reached a point
+where some right delimiter is mandatory.
+
+@<Declare the procedure called |check_delimiter|@>=
+void mp_check_delimiter (MP mp,pointer l_delim, pointer r_delim) {
+ if ( mp->cur_cmd==right_delimiter )
+ if ( mp->cur_mod==l_delim )
+ return;
+ if ( mp->cur_sym!=r_delim ) {
+ mp_missing_err(mp, str(text(r_delim)));
+@.Missing `)'@>
+ help2("I found no right delimiter to match a left one. So I've")
+ ("put one in, behind the scenes; this may fix the problem.");
+ mp_back_error(mp);
+ } else {
+ print_err("The token `"); mp_print_text(r_delim);
+@.The token...delimiter@>
+ mp_print(mp, "' is no longer a right delimiter");
+ help3("Strange: This token has lost its former meaning!")
+ ("I'll read it as a right delimiter this time;")
+ ("but watch out, I'll probably miss it later.");
+ mp_error(mp);
+ }
+}
+
+@ The next four commands save or change the values associated with tokens.
+
+@<Cases of |do_statement|...@>=
+case save_command:
+ do {
+ mp_get_symbol(mp); mp_save_variable(mp, mp->cur_sym); mp_get_x_next(mp);
+ } while (mp->cur_cmd==comma);
+ break;
+case interim_command: mp_do_interim(mp); break;
+case let_command: mp_do_let(mp); break;
+case new_internal: mp_do_new_internal(mp); break;
+
+@ @<Declare action procedures for use by |do_statement|@>=
+void mp_do_statement (MP mp);
+void mp_do_interim (MP mp);
+
+@ @c void mp_do_interim (MP mp) {
+ mp_get_x_next(mp);
+ if ( mp->cur_cmd!=internal_quantity ) {
+ print_err("The token `");
+@.The token...quantity@>
+ if ( mp->cur_sym==0 ) mp_print(mp, "(%CAPSULE)");
+ else mp_print_text(mp->cur_sym);
+ mp_print(mp, "' isn't an internal quantity");
+ help1("Something like `tracingonline' should follow `interim'.");
+ mp_back_error(mp);
+ } else {
+ mp_save_internal(mp, mp->cur_mod); mp_back_input(mp);
+ }
+ mp_do_statement(mp);
+}
+
+@ The following procedure is careful not to undefine the left-hand symbol
+too soon, lest commands like `{\tt let x=x}' have a surprising effect.
+
+@<Declare action procedures for use by |do_statement|@>=
+void mp_do_let (MP mp) ;
+
+@ @c void mp_do_let (MP mp) {
+ pointer l; /* hash location of the left-hand symbol */
+ mp_get_symbol(mp); l=mp->cur_sym; mp_get_x_next(mp);
+ if ( mp->cur_cmd!=equals ) if ( mp->cur_cmd!=assignment ) {
+ mp_missing_err(mp, "=");
+@.Missing `='@>
+ help3("You should have said `let symbol = something'.")
+ ("But don't worry; I'll pretend that an equals sign")
+ ("was present. The next token I read will be `something'.");
+ mp_back_error(mp);
+ }
+ mp_get_symbol(mp);
+ switch (mp->cur_cmd) {
+ case defined_macro: case secondary_primary_macro:
+ case tertiary_secondary_macro: case expression_tertiary_macro:
+ add_mac_ref(mp->cur_mod);
+ break;
+ default:
+ break;
+ }
+ mp_clear_symbol(mp, l,false); eq_type(l)=mp->cur_cmd;
+ if ( mp->cur_cmd==tag_token ) equiv(l)=null;
+ else equiv(l)=mp->cur_mod;
+ mp_get_x_next(mp);
+}
+
+@ @<Declarations@>=
+void mp_grow_internals (MP mp, int l);
+void mp_do_new_internal (MP mp) ;
+
+@ @c
+void mp_grow_internals (MP mp, int l) {
+ scaled *internal;
+ char * *int_name;
+ int k;
+ if ( hash_end+l>max_halfword ) {
+ mp_confusion(mp, "out of memory space"); /* can't be reached */
+ }
+ int_name = xmalloc ((l+1),sizeof(char *));
+ internal = xmalloc ((l+1),sizeof(scaled));
+ for (k=0;k<=l; k++ ) {
+ if (k<=mp->max_internal) {
+ internal[k]=mp->internal[k];
+ int_name[k]=mp->int_name[k];
+ } else {
+ internal[k]=0;
+ int_name[k]=NULL;
+ }
+ }
+ xfree(mp->internal); xfree(mp->int_name);
+ mp->int_name = int_name;
+ mp->internal = internal;
+ mp->max_internal = l;
+}
+
+
+void mp_do_new_internal (MP mp) {
+ do {
+ if ( mp->int_ptr==mp->max_internal ) {
+ mp_grow_internals(mp, (mp->max_internal + (mp->max_internal>>2)));
+ }
+ mp_get_clear_symbol(mp); incr(mp->int_ptr);
+ eq_type(mp->cur_sym)=internal_quantity;
+ equiv(mp->cur_sym)=mp->int_ptr;
+ if(mp->int_name[mp->int_ptr]!=NULL)
+ xfree(mp->int_name[mp->int_ptr]);
+ mp->int_name[mp->int_ptr]=str(text(mp->cur_sym));
+ mp->internal[mp->int_ptr]=0;
+ mp_get_x_next(mp);
+ } while (mp->cur_cmd==comma);
+}
+
+@ @<Dealloc variables@>=
+for (k=0;k<=mp->max_internal;k++) {
+ xfree(mp->int_name[k]);
+}
+xfree(mp->internal);
+xfree(mp->int_name);
+
+
+@ The various `\&{show}' commands are distinguished by modifier fields
+in the usual way.
+
+@d show_token_code 0 /* show the meaning of a single token */
+@d show_stats_code 1 /* show current memory and string usage */
+@d show_code 2 /* show a list of expressions */
+@d show_var_code 3 /* show a variable and its descendents */
+@d show_dependencies_code 4 /* show dependent variables in terms of independents */
+
+@<Put each...@>=
+mp_primitive(mp, "showtoken",show_command,show_token_code);
+@:show_token_}{\&{showtoken} primitive@>
+mp_primitive(mp, "showstats",show_command,show_stats_code);
+@:show_stats_}{\&{showstats} primitive@>
+mp_primitive(mp, "show",show_command,show_code);
+@:show_}{\&{show} primitive@>
+mp_primitive(mp, "showvariable",show_command,show_var_code);
+@:show_var_}{\&{showvariable} primitive@>
+mp_primitive(mp, "showdependencies",show_command,show_dependencies_code);
+@:show_dependencies_}{\&{showdependencies} primitive@>
+
+@ @<Cases of |print_cmd...@>=
+case show_command:
+ switch (m) {
+ case show_token_code:mp_print(mp, "showtoken"); break;
+ case show_stats_code:mp_print(mp, "showstats"); break;
+ case show_code:mp_print(mp, "show"); break;
+ case show_var_code:mp_print(mp, "showvariable"); break;
+ default: mp_print(mp, "showdependencies"); break;
+ }
+ break;
+
+@ @<Cases of |do_statement|...@>=
+case show_command:mp_do_show_whatever(mp); break;
+
+@ The value of |cur_mod| controls the |verbosity| in the |print_exp| routine:
+if it's |show_code|, complicated structures are abbreviated, otherwise
+they aren't.
+
+@<Declare action procedures for use by |do_statement|@>=
+void mp_do_show (MP mp) ;
+
+@ @c void mp_do_show (MP mp) {
+ do {
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ mp_print_nl(mp, ">> ");
+@.>>@>
+ mp_print_exp(mp, null,2); mp_flush_cur_exp(mp, 0);
+ } while (mp->cur_cmd==comma);
+}
+
+@ @<Declare action procedures for use by |do_statement|@>=
+void mp_disp_token (MP mp) ;
+
+@ @c void mp_disp_token (MP mp) {
+ mp_print_nl(mp, "> ");
+@.>\relax@>
+ if ( mp->cur_sym==0 ) {
+ @<Show a numeric or string or capsule token@>;
+ } else {
+ mp_print_text(mp->cur_sym); mp_print_char(mp, '=');
+ if ( eq_type(mp->cur_sym)>=outer_tag ) mp_print(mp, "(outer) ");
+ mp_print_cmd_mod(mp, mp->cur_cmd,mp->cur_mod);
+ if ( mp->cur_cmd==defined_macro ) {
+ mp_print_ln(mp); mp_show_macro(mp, mp->cur_mod,null,100000);
+ } /* this avoids recursion between |show_macro| and |print_cmd_mod| */
+@^recursion@>
+ }
+}
+
+@ @<Show a numeric or string or capsule token@>=
+{
+ if ( mp->cur_cmd==numeric_token ) {
+ mp_print_scaled(mp, mp->cur_mod);
+ } else if ( mp->cur_cmd==capsule_token ) {
+ mp_print_capsule(mp,mp->cur_mod);
+ } else {
+ mp_print_char(mp, '"');
+ mp_print_str(mp, mp->cur_mod); mp_print_char(mp, '"');
+ delete_str_ref(mp->cur_mod);
+ }
+}
+
+@ The following cases of |print_cmd_mod| might arise in connection
+with |disp_token|, although they don't necessarily correspond to
+primitive tokens.
+
+@<Cases of |print_cmd_...@>=
+case left_delimiter:
+case right_delimiter:
+ if ( c==left_delimiter ) mp_print(mp, "left");
+ else mp_print(mp, "right");
+ mp_print(mp, " delimiter that matches ");
+ mp_print_text(m);
+ break;
+case tag_token:
+ if ( m==null ) mp_print(mp, "tag");
+ else mp_print(mp, "variable");
+ break;
+case defined_macro:
+ mp_print(mp, "macro:");
+ break;
+case secondary_primary_macro:
+case tertiary_secondary_macro:
+case expression_tertiary_macro:
+ mp_print_cmd_mod(mp, macro_def,c);
+ mp_print(mp, "'d macro:");
+ mp_print_ln(mp); mp_show_token_list(mp, link(link(m)),null,1000,0);
+ break;
+case repeat_loop:
+ mp_print(mp, "[repeat the loop]");
+ break;
+case internal_quantity:
+ mp_print(mp, mp->int_name[m]);
+ break;
+
+@ @<Declare action procedures for use by |do_statement|@>=
+void mp_do_show_token (MP mp) ;
+
+@ @c void mp_do_show_token (MP mp) {
+ do {
+ get_t_next; mp_disp_token(mp);
+ mp_get_x_next(mp);
+ } while (mp->cur_cmd==comma);
+}
+
+@ @<Declare action procedures for use by |do_statement|@>=
+void mp_do_show_stats (MP mp) ;
+
+@ @c void mp_do_show_stats (MP mp) {
+ mp_print_nl(mp, "Memory usage ");
+@.Memory usage...@>
+ mp_print_int(mp, mp->var_used); mp_print_char(mp, '&'); mp_print_int(mp, mp->dyn_used);
+ mp_print(mp, " ("); mp_print_int(mp, mp->hi_mem_min-mp->lo_mem_max-1);
+ mp_print(mp, " still untouched)"); mp_print_ln(mp);
+ mp_print_nl(mp, "String usage ");
+ mp_print_int(mp, mp->strs_in_use-mp->init_str_use);
+ mp_print_char(mp, '&'); mp_print_int(mp, mp->pool_in_use-mp->init_pool_ptr);
+ mp_print(mp, " (");
+ mp_print_int(mp, mp->max_strings-1-mp->strs_used_up); mp_print_char(mp, '&');
+ mp_print_int(mp, mp->pool_size-mp->pool_ptr);
+ mp_print(mp, " now untouched)"); mp_print_ln(mp);
+ mp_get_x_next(mp);
+}
+
+@ Here's a recursive procedure that gives an abbreviated account
+of a variable, for use by |do_show_var|.
+
+@<Declare action procedures for use by |do_statement|@>=
+void mp_disp_var (MP mp,pointer p) ;
+
+@ @c void mp_disp_var (MP mp,pointer p) {
+ pointer q; /* traverses attributes and subscripts */
+ int n; /* amount of macro text to show */
+ if ( type(p)==mp_structured ) {
+ @<Descend the structure@>;
+ } else if ( type(p)>=mp_unsuffixed_macro ) {
+ @<Display a variable macro@>;
+ } else if ( type(p)!=undefined ){
+ mp_print_nl(mp, ""); mp_print_variable_name(mp, p);
+ mp_print_char(mp, '=');
+ mp_print_exp(mp, p,0);
+ }
+}
+
+@ @<Descend the structure@>=
+{
+ q=attr_head(p);
+ do { mp_disp_var(mp, q); q=link(q); } while (q!=end_attr);
+ q=subscr_head(p);
+ while ( name_type(q)==mp_subscr ) {
+ mp_disp_var(mp, q); q=link(q);
+ }
+}
+
+@ @<Display a variable macro@>=
+{
+ mp_print_nl(mp, ""); mp_print_variable_name(mp, p);
+ if ( type(p)>mp_unsuffixed_macro )
+ mp_print(mp, "@@#"); /* |suffixed_macro| */
+ mp_print(mp, "=macro:");
+ if ( (int)mp->file_offset>=mp->max_print_line-20 ) n=5;
+ else n=mp->max_print_line-mp->file_offset-15;
+ mp_show_macro(mp, value(p),null,n);
+}
+
+@ @<Declare action procedures for use by |do_statement|@>=
+void mp_do_show_var (MP mp) ;
+
+@ @c void mp_do_show_var (MP mp) {
+ do {
+ get_t_next;
+ if ( mp->cur_sym>0 ) if ( mp->cur_sym<=hash_end )
+ if ( mp->cur_cmd==tag_token ) if ( mp->cur_mod!=null ) {
+ mp_disp_var(mp, mp->cur_mod); goto DONE;
+ }
+ mp_disp_token(mp);
+ DONE:
+ mp_get_x_next(mp);
+ } while (mp->cur_cmd==comma);
+}
+
+@ @<Declare action procedures for use by |do_statement|@>=
+void mp_do_show_dependencies (MP mp) ;
+
+@ @c void mp_do_show_dependencies (MP mp) {
+ pointer p; /* link that runs through all dependencies */
+ p=link(dep_head);
+ while ( p!=dep_head ) {
+ if ( mp_interesting(mp, p) ) {
+ mp_print_nl(mp, ""); mp_print_variable_name(mp, p);
+ if ( type(p)==mp_dependent ) mp_print_char(mp, '=');
+ else mp_print(mp, " = "); /* extra spaces imply proto-dependency */
+ mp_print_dependency(mp, dep_list(p),type(p));
+ }
+ p=dep_list(p);
+ while ( info(p)!=null ) p=link(p);
+ p=link(p);
+ }
+ mp_get_x_next(mp);
+}
+
+@ Finally we are ready for the procedure that governs all of the
+show commands.
+
+@<Declare action procedures for use by |do_statement|@>=
+void mp_do_show_whatever (MP mp) ;
+
+@ @c void mp_do_show_whatever (MP mp) {
+ if ( mp->interaction==mp_error_stop_mode ) wake_up_terminal;
+ switch (mp->cur_mod) {
+ case show_token_code:mp_do_show_token(mp); break;
+ case show_stats_code:mp_do_show_stats(mp); break;
+ case show_code:mp_do_show(mp); break;
+ case show_var_code:mp_do_show_var(mp); break;
+ case show_dependencies_code:mp_do_show_dependencies(mp); break;
+ } /* there are no other cases */
+ if ( mp->internal[mp_showstopping]>0 ){
+ print_err("OK");
+@.OK@>
+ if ( mp->interaction<mp_error_stop_mode ) {
+ help0; decr(mp->error_count);
+ } else {
+ help1("This isn't an error message; I'm just showing something.");
+ }
+ if ( mp->cur_cmd==semicolon ) mp_error(mp);
+ else mp_put_get_error(mp);
+ }
+}
+
+@ The `\&{addto}' command needs the following additional primitives:
+
+@d double_path_code 0 /* command modifier for `\&{doublepath}' */
+@d contour_code 1 /* command modifier for `\&{contour}' */
+@d also_code 2 /* command modifier for `\&{also}' */
+
+@ Pre and postscripts need two new identifiers:
+
+@d with_pre_script 11
+@d with_post_script 13
+
+@<Put each...@>=
+mp_primitive(mp, "doublepath",thing_to_add,double_path_code);
+@:double_path_}{\&{doublepath} primitive@>
+mp_primitive(mp, "contour",thing_to_add,contour_code);
+@:contour_}{\&{contour} primitive@>
+mp_primitive(mp, "also",thing_to_add,also_code);
+@:also_}{\&{also} primitive@>
+mp_primitive(mp, "withpen",with_option,mp_pen_type);
+@:with_pen_}{\&{withpen} primitive@>
+mp_primitive(mp, "dashed",with_option,mp_picture_type);
+@:dashed_}{\&{dashed} primitive@>
+mp_primitive(mp, "withprescript",with_option,with_pre_script);
+@:with_pre_script_}{\&{withprescript} primitive@>
+mp_primitive(mp, "withpostscript",with_option,with_post_script);
+@:with_post_script_}{\&{withpostscript} primitive@>
+mp_primitive(mp, "withoutcolor",with_option,mp_no_model);
+@:with_color_}{\&{withoutcolor} primitive@>
+mp_primitive(mp, "withgreyscale",with_option,mp_grey_model);
+@:with_color_}{\&{withgreyscale} primitive@>
+mp_primitive(mp, "withcolor",with_option,mp_uninitialized_model);
+@:with_color_}{\&{withcolor} primitive@>
+/* \&{withrgbcolor} is an alias for \&{withcolor} */
+mp_primitive(mp, "withrgbcolor",with_option,mp_rgb_model);
+@:with_color_}{\&{withrgbcolor} primitive@>
+mp_primitive(mp, "withcmykcolor",with_option,mp_cmyk_model);
+@:with_color_}{\&{withcmykcolor} primitive@>
+
+@ @<Cases of |print_cmd...@>=
+case thing_to_add:
+ if ( m==contour_code ) mp_print(mp, "contour");
+ else if ( m==double_path_code ) mp_print(mp, "doublepath");
+ else mp_print(mp, "also");
+ break;
+case with_option:
+ if ( m==mp_pen_type ) mp_print(mp, "withpen");
+ else if ( m==with_pre_script ) mp_print(mp, "withprescript");
+ else if ( m==with_post_script ) mp_print(mp, "withpostscript");
+ else if ( m==mp_no_model ) mp_print(mp, "withoutcolor");
+ else if ( m==mp_rgb_model ) mp_print(mp, "withrgbcolor");
+ else if ( m==mp_uninitialized_model ) mp_print(mp, "withcolor");
+ else if ( m==mp_cmyk_model ) mp_print(mp, "withcmykcolor");
+ else if ( m==mp_grey_model ) mp_print(mp, "withgreyscale");
+ else mp_print(mp, "dashed");
+ break;
+
+@ The |scan_with_list| procedure parses a $\langle$with list$\rangle$ and
+updates the list of graphical objects starting at |p|. Each $\langle$with
+clause$\rangle$ updates all graphical objects whose |type| is compatible.
+Other objects are ignored.
+
+@<Declare action procedures for use by |do_statement|@>=
+void mp_scan_with_list (MP mp,pointer p) ;
+
+@ @c void mp_scan_with_list (MP mp,pointer p) {
+ small_number t; /* |cur_mod| of the |with_option| (should match |cur_type|) */
+ pointer q; /* for list manipulation */
+ int old_setting; /* saved |selector| setting */
+ pointer k; /* for finding the near-last item in a list */
+ str_number s; /* for string cleanup after combining */
+ pointer cp,pp,dp,ap,bp;
+ /* objects being updated; |void| initially; |null| to suppress update */
+ cp=mp_void; pp=mp_void; dp=mp_void; ap=mp_void; bp=mp_void;
+ k=0;
+ while ( mp->cur_cmd==with_option ){
+ t=mp->cur_mod;
+ mp_get_x_next(mp);
+ if ( t!=mp_no_model ) mp_scan_expression(mp);
+ if (((t==with_pre_script)&&(mp->cur_type!=mp_string_type))||
+ ((t==with_post_script)&&(mp->cur_type!=mp_string_type))||
+ ((t==mp_uninitialized_model)&&
+ ((mp->cur_type!=mp_cmykcolor_type)&&(mp->cur_type!=mp_color_type)
+ &&(mp->cur_type!=mp_known)&&(mp->cur_type!=mp_boolean_type)))||
+ ((t==mp_cmyk_model)&&(mp->cur_type!=mp_cmykcolor_type))||
+ ((t==mp_rgb_model)&&(mp->cur_type!=mp_color_type))||
+ ((t==mp_grey_model)&&(mp->cur_type!=mp_known))||
+ ((t==mp_pen_type)&&(mp->cur_type!=t))||
+ ((t==mp_picture_type)&&(mp->cur_type!=t)) ) {
+ @<Complain about improper type@>;
+ } else if ( t==mp_uninitialized_model ) {
+ if ( cp==mp_void ) @<Make |cp| a colored object in object list~|p|@>;
+ if ( cp!=null )
+ @<Transfer a color from the current expression to object~|cp|@>;
+ mp_flush_cur_exp(mp, 0);
+ } else if ( t==mp_rgb_model ) {
+ if ( cp==mp_void ) @<Make |cp| a colored object in object list~|p|@>;
+ if ( cp!=null )
+ @<Transfer a rgbcolor from the current expression to object~|cp|@>;
+ mp_flush_cur_exp(mp, 0);
+ } else if ( t==mp_cmyk_model ) {
+ if ( cp==mp_void ) @<Make |cp| a colored object in object list~|p|@>;
+ if ( cp!=null )
+ @<Transfer a cmykcolor from the current expression to object~|cp|@>;
+ mp_flush_cur_exp(mp, 0);
+ } else if ( t==mp_grey_model ) {
+ if ( cp==mp_void ) @<Make |cp| a colored object in object list~|p|@>;
+ if ( cp!=null )
+ @<Transfer a greyscale from the current expression to object~|cp|@>;
+ mp_flush_cur_exp(mp, 0);
+ } else if ( t==mp_no_model ) {
+ if ( cp==mp_void ) @<Make |cp| a colored object in object list~|p|@>;
+ if ( cp!=null )
+ @<Transfer a noncolor from the current expression to object~|cp|@>;
+ } else if ( t==mp_pen_type ) {
+ if ( pp==mp_void ) @<Make |pp| an object in list~|p| that needs a pen@>;
+ if ( pp!=null ) {
+ if ( pen_p(pp)!=null ) mp_toss_knot_list(mp, pen_p(pp));
+ pen_p(pp)=mp->cur_exp; mp->cur_type=mp_vacuous;
+ }
+ } else if ( t==with_pre_script ) {
+ if ( ap==mp_void )
+ ap=p;
+ while ( (ap!=null)&&(! has_color(ap)) )
+ ap=link(ap);
+ if ( ap!=null ) {
+ if ( pre_script(ap)!=null ) { /* build a new,combined string */
+ s=pre_script(ap);
+ old_setting=mp->selector;
+ mp->selector=new_string;
+ str_room(length(pre_script(ap))+length(mp->cur_exp)+2);
+ mp_print_str(mp, mp->cur_exp);
+ append_char(13); /* a forced \ps\ newline */
+ mp_print_str(mp, pre_script(ap));
+ pre_script(ap)=mp_make_string(mp);
+ delete_str_ref(s);
+ mp->selector=old_setting;
+ } else {
+ pre_script(ap)=mp->cur_exp;
+ }
+ mp->cur_type=mp_vacuous;
+ }
+ } else if ( t==with_post_script ) {
+ if ( bp==mp_void )
+ k=p;
+ bp=k;
+ while ( link(k)!=null ) {
+ k=link(k);
+ if ( has_color(k) ) bp=k;
+ }
+ if ( bp!=null ) {
+ if ( post_script(bp)!=null ) {
+ s=post_script(bp);
+ old_setting=mp->selector;
+ mp->selector=new_string;
+ str_room(length(post_script(bp))+length(mp->cur_exp)+2);
+ mp_print_str(mp, post_script(bp));
+ append_char(13); /* a forced \ps\ newline */
+ mp_print_str(mp, mp->cur_exp);
+ post_script(bp)=mp_make_string(mp);
+ delete_str_ref(s);
+ mp->selector=old_setting;
+ } else {
+ post_script(bp)=mp->cur_exp;
+ }
+ mp->cur_type=mp_vacuous;
+ }
+ } else {
+ if ( dp==mp_void ) {
+ @<Make |dp| a stroked node in list~|p|@>;
+ }
+ if ( dp!=null ) {
+ if ( dash_p(dp)!=null ) delete_edge_ref(dash_p(dp));
+ dash_p(dp)=mp_make_dashes(mp, mp->cur_exp);
+ dash_scale(dp)=unity;
+ mp->cur_type=mp_vacuous;
+ }
+ }
+ }
+ @<Copy the information from objects |cp|, |pp|, and |dp| into the rest
+ of the list@>;
+}
+
+@ @<Complain about improper type@>=
+{ exp_err("Improper type");
+@.Improper type@>
+help2("Next time say `withpen <known pen expression>';")
+ ("I'll ignore the bad `with' clause and look for another.");
+if ( t==with_pre_script )
+ mp->help_line[1]="Next time say `withprescript <known string expression>';";
+else if ( t==with_post_script )
+ mp->help_line[1]="Next time say `withpostscript <known string expression>';";
+else if ( t==mp_picture_type )
+ mp->help_line[1]="Next time say `dashed <known picture expression>';";
+else if ( t==mp_uninitialized_model )
+ mp->help_line[1]="Next time say `withcolor <known color expression>';";
+else if ( t==mp_rgb_model )
+ mp->help_line[1]="Next time say `withrgbcolor <known color expression>';";
+else if ( t==mp_cmyk_model )
+ mp->help_line[1]="Next time say `withcmykcolor <known cmykcolor expression>';";
+else if ( t==mp_grey_model )
+ mp->help_line[1]="Next time say `withgreyscale <known numeric expression>';";;
+mp_put_get_flush_error(mp, 0);
+}
+
+@ Forcing the color to be between |0| and |unity| here guarantees that no
+picture will ever contain a color outside the legal range for \ps\ graphics.
+
+@<Transfer a color from the current expression to object~|cp|@>=
+{ if ( mp->cur_type==mp_color_type )
+ @<Transfer a rgbcolor from the current expression to object~|cp|@>
+else if ( mp->cur_type==mp_cmykcolor_type )
+ @<Transfer a cmykcolor from the current expression to object~|cp|@>
+else if ( mp->cur_type==mp_known )
+ @<Transfer a greyscale from the current expression to object~|cp|@>
+else if ( mp->cur_exp==false_code )
+ @<Transfer a noncolor from the current expression to object~|cp|@>;
+}
+
+@ @<Transfer a rgbcolor from the current expression to object~|cp|@>=
+{ q=value(mp->cur_exp);
+cyan_val(cp)=0;
+magenta_val(cp)=0;
+yellow_val(cp)=0;
+black_val(cp)=0;
+red_val(cp)=value(red_part_loc(q));
+green_val(cp)=value(green_part_loc(q));
+blue_val(cp)=value(blue_part_loc(q));
+color_model(cp)=mp_rgb_model;
+if ( red_val(cp)<0 ) red_val(cp)=0;
+if ( green_val(cp)<0 ) green_val(cp)=0;
+if ( blue_val(cp)<0 ) blue_val(cp)=0;
+if ( red_val(cp)>unity ) red_val(cp)=unity;
+if ( green_val(cp)>unity ) green_val(cp)=unity;
+if ( blue_val(cp)>unity ) blue_val(cp)=unity;
+}
+
+@ @<Transfer a cmykcolor from the current expression to object~|cp|@>=
+{ q=value(mp->cur_exp);
+cyan_val(cp)=value(cyan_part_loc(q));
+magenta_val(cp)=value(magenta_part_loc(q));
+yellow_val(cp)=value(yellow_part_loc(q));
+black_val(cp)=value(black_part_loc(q));
+color_model(cp)=mp_cmyk_model;
+if ( cyan_val(cp)<0 ) cyan_val(cp)=0;
+if ( magenta_val(cp)<0 ) magenta_val(cp)=0;
+if ( yellow_val(cp)<0 ) yellow_val(cp)=0;
+if ( black_val(cp)<0 ) black_val(cp)=0;
+if ( cyan_val(cp)>unity ) cyan_val(cp)=unity;
+if ( magenta_val(cp)>unity ) magenta_val(cp)=unity;
+if ( yellow_val(cp)>unity ) yellow_val(cp)=unity;
+if ( black_val(cp)>unity ) black_val(cp)=unity;
+}
+
+@ @<Transfer a greyscale from the current expression to object~|cp|@>=
+{ q=mp->cur_exp;
+cyan_val(cp)=0;
+magenta_val(cp)=0;
+yellow_val(cp)=0;
+black_val(cp)=0;
+grey_val(cp)=q;
+color_model(cp)=mp_grey_model;
+if ( grey_val(cp)<0 ) grey_val(cp)=0;
+if ( grey_val(cp)>unity ) grey_val(cp)=unity;
+}
+
+@ @<Transfer a noncolor from the current expression to object~|cp|@>=
+{
+cyan_val(cp)=0;
+magenta_val(cp)=0;
+yellow_val(cp)=0;
+black_val(cp)=0;
+grey_val(cp)=0;
+color_model(cp)=mp_no_model;
+}
+
+@ @<Make |cp| a colored object in object list~|p|@>=
+{ cp=p;
+ while ( cp!=null ){
+ if ( has_color(cp) ) break;
+ cp=link(cp);
+ }
+}
+
+@ @<Make |pp| an object in list~|p| that needs a pen@>=
+{ pp=p;
+ while ( pp!=null ) {
+ if ( has_pen(pp) ) break;
+ pp=link(pp);
+ }
+}
+
+@ @<Make |dp| a stroked node in list~|p|@>=
+{ dp=p;
+ while ( dp!=null ) {
+ if ( type(dp)==mp_stroked_code ) break;
+ dp=link(dp);
+ }
+}
+
+@ @<Copy the information from objects |cp|, |pp|, and |dp| into...@>=
+@<Copy |cp|'s color into the colored objects linked to~|cp|@>;
+if ( pp>mp_void ) {
+ @<Copy |pen_p(pp)| into stroked and filled nodes linked to |pp|@>;
+}
+if ( dp>mp_void ) {
+ @<Make stroked nodes linked to |dp| refer to |dash_p(dp)|@>;
+}
+
+
+@ @<Copy |cp|'s color into the colored objects linked to~|cp|@>=
+{ q=link(cp);
+ while ( q!=null ) {
+ if ( has_color(q) ) {
+ red_val(q)=red_val(cp);
+ green_val(q)=green_val(cp);
+ blue_val(q)=blue_val(cp);
+ black_val(q)=black_val(cp);
+ color_model(q)=color_model(cp);
+ }
+ q=link(q);
+ }
+}
+
+@ @<Copy |pen_p(pp)| into stroked and filled nodes linked to |pp|@>=
+{ q=link(pp);
+ while ( q!=null ) {
+ if ( has_pen(q) ) {
+ if ( pen_p(q)!=null ) mp_toss_knot_list(mp, pen_p(q));
+ pen_p(q)=copy_pen(pen_p(pp));
+ }
+ q=link(q);
+ }
+}
+
+@ @<Make stroked nodes linked to |dp| refer to |dash_p(dp)|@>=
+{ q=link(dp);
+ while ( q!=null ) {
+ if ( type(q)==mp_stroked_code ) {
+ if ( dash_p(q)!=null ) delete_edge_ref(dash_p(q));
+ dash_p(q)=dash_p(dp);
+ dash_scale(q)=unity;
+ if ( dash_p(q)!=null ) add_edge_ref(dash_p(q));
+ }
+ q=link(q);
+ }
+}
+
+@ One of the things we need to do when we've parsed an \&{addto} or
+similar command is find the header of a supposed \&{picture} variable, given
+a token list for that variable. Since the edge structure is about to be
+updated, we use |private_edges| to make sure that this is possible.
+
+@<Declare action procedures for use by |do_statement|@>=
+pointer mp_find_edges_var (MP mp, pointer t) ;
+
+@ @c pointer mp_find_edges_var (MP mp, pointer t) {
+ pointer p;
+ pointer cur_edges; /* the return value */
+ p=mp_find_variable(mp, t); cur_edges=null;
+ if ( p==null ) {
+ mp_obliterated(mp, t); mp_put_get_error(mp);
+ } else if ( type(p)!=mp_picture_type ) {
+ print_err("Variable "); mp_show_token_list(mp, t,null,1000,0);
+@.Variable x is the wrong type@>
+ mp_print(mp, " is the wrong type (");
+ mp_print_type(mp, type(p)); mp_print_char(mp, ')');
+ help2("I was looking for a \"known\" picture variable.")
+ ("So I'll not change anything just now.");
+ mp_put_get_error(mp);
+ } else {
+ value(p)=mp_private_edges(mp, value(p));
+ cur_edges=value(p);
+ }
+ mp_flush_node_list(mp, t);
+ return cur_edges;
+}
+
+@ @<Cases of |do_statement|...@>=
+case add_to_command: mp_do_add_to(mp); break;
+case bounds_command:mp_do_bounds(mp); break;
+
+@ @<Put each...@>=
+mp_primitive(mp, "clip",bounds_command,mp_start_clip_code);
+@:clip_}{\&{clip} primitive@>
+mp_primitive(mp, "setbounds",bounds_command,mp_start_bounds_code);
+@:set_bounds_}{\&{setbounds} primitive@>
+
+@ @<Cases of |print_cmd...@>=
+case bounds_command:
+ if ( m==mp_start_clip_code ) mp_print(mp, "clip");
+ else mp_print(mp, "setbounds");
+ break;
+
+@ The following function parses the beginning of an \&{addto} or \&{clip}
+command: it expects a variable name followed by a token with |cur_cmd=sep|
+and then an expression. The function returns the token list for the variable
+and stores the command modifier for the separator token in the global variable
+|last_add_type|. We must be careful because this variable might get overwritten
+any time we call |get_x_next|.
+
+@<Glob...@>=
+quarterword last_add_type;
+ /* command modifier that identifies the last \&{addto} command */
+
+@ @<Declare action procedures for use by |do_statement|@>=
+pointer mp_start_draw_cmd (MP mp,quarterword sep) ;
+
+@ @c pointer mp_start_draw_cmd (MP mp,quarterword sep) {
+ pointer lhv; /* variable to add to left */
+ quarterword add_type=0; /* value to be returned in |last_add_type| */
+ lhv=null;
+ mp_get_x_next(mp); mp->var_flag=sep; mp_scan_primary(mp);
+ if ( mp->cur_type!=mp_token_list ) {
+ @<Abandon edges command because there's no variable@>;
+ } else {
+ lhv=mp->cur_exp; add_type=mp->cur_mod;
+ mp->cur_type=mp_vacuous; mp_get_x_next(mp); mp_scan_expression(mp);
+ }
+ mp->last_add_type=add_type;
+ return lhv;
+}
+
+@ @<Abandon edges command because there's no variable@>=
+{ exp_err("Not a suitable variable");
+@.Not a suitable variable@>
+ help4("At this point I needed to see the name of a picture variable.")
+ ("(Or perhaps you have indeed presented me with one; I might")
+ ("have missed it, if it wasn't followed by the proper token.)")
+ ("So I'll not change anything just now.");
+ mp_put_get_flush_error(mp, 0);
+}
+
+@ Here is an example of how to use |start_draw_cmd|.
+
+@<Declare action procedures for use by |do_statement|@>=
+void mp_do_bounds (MP mp) ;
+
+@ @c void mp_do_bounds (MP mp) {
+ pointer lhv,lhe; /* variable on left, the corresponding edge structure */
+ pointer p; /* for list manipulation */
+ integer m; /* initial value of |cur_mod| */
+ m=mp->cur_mod;
+ lhv=mp_start_draw_cmd(mp, to_token);
+ if ( lhv!=null ) {
+ lhe=mp_find_edges_var(mp, lhv);
+ if ( lhe==null ) {
+ mp_flush_cur_exp(mp, 0);
+ } else if ( mp->cur_type!=mp_path_type ) {
+ exp_err("Improper `clip'");
+@.Improper `addto'@>
+ help2("This expression should have specified a known path.")
+ ("So I'll not change anything just now.");
+ mp_put_get_flush_error(mp, 0);
+ } else if ( left_type(mp->cur_exp)==mp_endpoint ) {
+ @<Complain about a non-cycle@>;
+ } else {
+ @<Make |cur_exp| into a \&{setbounds} or clipping path and add it to |lhe|@>;
+ }
+ }
+}
+
+@ @<Complain about a non-cycle@>=
+{ print_err("Not a cycle");
+@.Not a cycle@>
+ help2("That contour should have ended with `..cycle' or `&cycle'.")
+ ("So I'll not change anything just now."); mp_put_get_error(mp);
+}
+
+@ @<Make |cur_exp| into a \&{setbounds} or clipping path and add...@>=
+{ p=mp_new_bounds_node(mp, mp->cur_exp,m);
+ link(p)=link(dummy_loc(lhe));
+ link(dummy_loc(lhe))=p;
+ if ( obj_tail(lhe)==dummy_loc(lhe) ) obj_tail(lhe)=p;
+ p=mp_get_node(mp, mp->gr_object_size[stop_type(m)]);
+ type(p)=stop_type(m);
+ link(obj_tail(lhe))=p;
+ obj_tail(lhe)=p;
+ mp_init_bbox(mp, lhe);
+}
+
+@ The |do_add_to| procedure is a little like |do_clip| but there are a lot more
+cases to deal with.
+
+@<Declare action procedures for use by |do_statement|@>=
+void mp_do_add_to (MP mp) ;
+
+@ @c void mp_do_add_to (MP mp) {
+ pointer lhv,lhe; /* variable on left, the corresponding edge structure */
+ pointer p; /* the graphical object or list for |scan_with_list| to update */
+ pointer e; /* an edge structure to be merged */
+ quarterword add_type; /* |also_code|, |contour_code|, or |double_path_code| */
+ lhv=mp_start_draw_cmd(mp, thing_to_add); add_type=mp->last_add_type;
+ if ( lhv!=null ) {
+ if ( add_type==also_code ) {
+ @<Make sure the current expression is a suitable picture and set |e| and |p|
+ appropriately@>;
+ } else {
+ @<Create a graphical object |p| based on |add_type| and the current
+ expression@>;
+ }
+ mp_scan_with_list(mp, p);
+ @<Use |p|, |e|, and |add_type| to augment |lhv| as requested@>;
+ }
+}
+
+@ Setting |p:=null| causes the $\langle$with list$\rangle$ to be ignored;
+setting |e:=null| prevents anything from being added to |lhe|.
+
+@ @<Make sure the current expression is a suitable picture and set |e|...@>=
+{
+ p=null; e=null;
+ if ( mp->cur_type!=mp_picture_type ) {
+ exp_err("Improper `addto'");
+@.Improper `addto'@>
+ help2("This expression should have specified a known picture.")
+ ("So I'll not change anything just now."); mp_put_get_flush_error(mp, 0);
+ } else {
+ e=mp_private_edges(mp, mp->cur_exp); mp->cur_type=mp_vacuous;
+ p=link(dummy_loc(e));
+ }
+}
+
+@ In this case |add_type<>also_code| so setting |p:=null| suppresses future
+attempts to add to the edge structure.
+
+@<Create a graphical object |p| based on |add_type| and the current...@>=
+{ e=null; p=null;
+ if ( mp->cur_type==mp_pair_type ) mp_pair_to_path(mp);
+ if ( mp->cur_type!=mp_path_type ) {
+ exp_err("Improper `addto'");
+@.Improper `addto'@>
+ help2("This expression should have specified a known path.")
+ ("So I'll not change anything just now.");
+ mp_put_get_flush_error(mp, 0);
+ } else if ( add_type==contour_code ) {
+ if ( left_type(mp->cur_exp)==mp_endpoint ) {
+ @<Complain about a non-cycle@>;
+ } else {
+ p=mp_new_fill_node(mp, mp->cur_exp);
+ mp->cur_type=mp_vacuous;
+ }
+ } else {
+ p=mp_new_stroked_node(mp, mp->cur_exp);
+ mp->cur_type=mp_vacuous;
+ }
+}
+
+@ @<Use |p|, |e|, and |add_type| to augment |lhv| as requested@>=
+lhe=mp_find_edges_var(mp, lhv);
+if ( lhe==null ) {
+ if ( (e==null)&&(p!=null) ) e=mp_toss_gr_object(mp, p);
+ if ( e!=null ) delete_edge_ref(e);
+} else if ( add_type==also_code ) {
+ if ( e!=null ) {
+ @<Merge |e| into |lhe| and delete |e|@>;
+ } else {
+ do_nothing;
+ }
+} else if ( p!=null ) {
+ link(obj_tail(lhe))=p;
+ obj_tail(lhe)=p;
+ if ( add_type==double_path_code )
+ if ( pen_p(p)==null )
+ pen_p(p)=mp_get_pen_circle(mp, 0);
+}
+
+@ @<Merge |e| into |lhe| and delete |e|@>=
+{ if ( link(dummy_loc(e))!=null ) {
+ link(obj_tail(lhe))=link(dummy_loc(e));
+ obj_tail(lhe)=obj_tail(e);
+ obj_tail(e)=dummy_loc(e);
+ link(dummy_loc(e))=null;
+ mp_flush_dash_list(mp, lhe);
+ }
+ mp_toss_edges(mp, e);
+}
+
+@ @<Cases of |do_statement|...@>=
+case ship_out_command: mp_do_ship_out(mp); break;
+
+@ @<Declare action procedures for use by |do_statement|@>=
+@<Declare the function called |tfm_check|@>
+@<Declare the \ps\ output procedures@>
+void mp_do_ship_out (MP mp) ;
+
+@ @c void mp_do_ship_out (MP mp) {
+ integer c; /* the character code */
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type!=mp_picture_type ) {
+ @<Complain that it's not a known picture@>;
+ } else {
+ c=mp_round_unscaled(mp, mp->internal[mp_char_code]) % 256;
+ if ( c<0 ) c=c+256;
+ @<Store the width information for character code~|c|@>;
+ mp_ship_out(mp, mp->cur_exp);
+ mp_flush_cur_exp(mp, 0);
+ }
+}
+
+@ @<Complain that it's not a known picture@>=
+{
+ exp_err("Not a known picture");
+ help1("I can only output known pictures.");
+ mp_put_get_flush_error(mp, 0);
+}
+
+@ The \&{everyjob} command simply assigns a nonzero value to the global variable
+|start_sym|.
+
+@<Cases of |do_statement|...@>=
+case every_job_command:
+ mp_get_symbol(mp); mp->start_sym=mp->cur_sym; mp_get_x_next(mp);
+ break;
+
+@ @<Glob...@>=
+halfword start_sym; /* a symbolic token to insert at beginning of job */
+
+@ @<Set init...@>=
+mp->start_sym=0;
+
+@ Finally, we have only the ``message'' commands remaining.
+
+@d message_code 0
+@d err_message_code 1
+@d err_help_code 2
+@d filename_template_code 3
+@d print_with_leading_zeroes(A) g = mp->pool_ptr;
+ mp_print_int(mp, (A)); g = mp->pool_ptr-g;
+ if ( f>g ) {
+ mp->pool_ptr = mp->pool_ptr - g;
+ while ( f>g ) {
+ mp_print_char(mp, '0');
+ decr(f);
+ };
+ mp_print_int(mp, (A));
+ };
+ f = 0
+
+@<Put each...@>=
+mp_primitive(mp, "message",message_command,message_code);
+@:message_}{\&{message} primitive@>
+mp_primitive(mp, "errmessage",message_command,err_message_code);
+@:err_message_}{\&{errmessage} primitive@>
+mp_primitive(mp, "errhelp",message_command,err_help_code);
+@:err_help_}{\&{errhelp} primitive@>
+mp_primitive(mp, "filenametemplate",message_command,filename_template_code);
+@:filename_template_}{\&{filenametemplate} primitive@>
+
+@ @<Cases of |print_cmd...@>=
+case message_command:
+ if ( m<err_message_code ) mp_print(mp, "message");
+ else if ( m==err_message_code ) mp_print(mp, "errmessage");
+ else if ( m==filename_template_code ) mp_print(mp, "filenametemplate");
+ else mp_print(mp, "errhelp");
+ break;
+
+@ @<Cases of |do_statement|...@>=
+case message_command: mp_do_message(mp); break;
+
+@ @<Declare action procedures for use by |do_statement|@>=
+@<Declare a procedure called |no_string_err|@>
+void mp_do_message (MP mp) ;
+
+@
+@c void mp_do_message (MP mp) {
+ int m; /* the type of message */
+ m=mp->cur_mod; mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type!=mp_string_type )
+ mp_no_string_err(mp, "A message should be a known string expression.");
+ else {
+ switch (m) {
+ case message_code:
+ mp_print_nl(mp, ""); mp_print_str(mp, mp->cur_exp);
+ break;
+ case err_message_code:
+ @<Print string |cur_exp| as an error message@>;
+ break;
+ case err_help_code:
+ @<Save string |cur_exp| as the |err_help|@>;
+ break;
+ case filename_template_code:
+ @<Save the filename template@>;
+ break;
+ } /* there are no other cases */
+ }
+ mp_flush_cur_exp(mp, 0);
+}
+
+@ @<Declare a procedure called |no_string_err|@>=
+void mp_no_string_err (MP mp, const char *s) {
+ exp_err("Not a string");
+@.Not a string@>
+ help1(s);
+ mp_put_get_error(mp);
+}
+
+@ The global variable |err_help| is zero when the user has most recently
+given an empty help string, or if none has ever been given.
+
+@<Save string |cur_exp| as the |err_help|@>=
+{
+ if ( mp->err_help!=0 ) delete_str_ref(mp->err_help);
+ if ( length(mp->cur_exp)==0 ) mp->err_help=0;
+ else { mp->err_help=mp->cur_exp; add_str_ref(mp->err_help); }
+}
+
+@ If \&{errmessage} occurs often in |mp_scroll_mode|, without user-defined
+\&{errhelp}, we don't want to give a long help message each time. So we
+give a verbose explanation only once.
+
+@<Glob...@>=
+boolean long_help_seen; /* has the long \.{\\errmessage} help been used? */
+
+@ @<Set init...@>=mp->long_help_seen=false;
+
+@ @<Print string |cur_exp| as an error message@>=
+{
+ print_err(""); mp_print_str(mp, mp->cur_exp);
+ if ( mp->err_help!=0 ) {
+ mp->use_err_help=true;
+ } else if ( mp->long_help_seen ) {
+ help1("(That was another `errmessage'.)") ;
+ } else {
+ if ( mp->interaction<mp_error_stop_mode ) mp->long_help_seen=true;
+ help4("This error message was generated by an `errmessage'")
+ ("command, so I can\'t give any explicit help.")
+ ("Pretend that you're Miss Marple: Examine all clues,")
+@^Marple, Jane@>
+ ("and deduce the truth by inspired guesses.");
+ }
+ mp_put_get_error(mp); mp->use_err_help=false;
+}
+
+@ @<Cases of |do_statement|...@>=
+case write_command: mp_do_write(mp); break;
+
+@ @<Declare action procedures for use by |do_statement|@>=
+void mp_do_write (MP mp) ;
+
+@ @c void mp_do_write (MP mp) {
+ str_number t; /* the line of text to be written */
+ write_index n,n0; /* for searching |wr_fname| and |wr_file| arrays */
+ int old_setting; /* for saving |selector| during output */
+ mp_get_x_next(mp);
+ mp_scan_expression(mp);
+ if ( mp->cur_type!=mp_string_type ) {
+ mp_no_string_err(mp, "The text to be written should be a known string expression");
+ } else if ( mp->cur_cmd!=to_token ) {
+ print_err("Missing `to' clause");
+ help1("A write command should end with `to <filename>'");
+ mp_put_get_error(mp);
+ } else {
+ t=mp->cur_exp; mp->cur_type=mp_vacuous;
+ mp_get_x_next(mp);
+ mp_scan_expression(mp);
+ if ( mp->cur_type!=mp_string_type )
+ mp_no_string_err(mp, "I can\'t write to that file name. It isn't a known string");
+ else {
+ @<Write |t| to the file named by |cur_exp|@>;
+ }
+ delete_str_ref(t);
+ }
+ mp_flush_cur_exp(mp, 0);
+}
+
+@ @<Write |t| to the file named by |cur_exp|@>=
+{
+ @<Find |n| where |wr_fname[n]=cur_exp| and call |open_write_file| if
+ |cur_exp| must be inserted@>;
+ if ( mp_str_vs_str(mp, t,mp->eof_line)==0 ) {
+ @<Record the end of file on |wr_file[n]|@>;
+ } else {
+ old_setting=mp->selector;
+ mp->selector=n+write_file;
+ mp_print_str(mp, t); mp_print_ln(mp);
+ mp->selector = old_setting;
+ }
+}
+
+@ @<Find |n| where |wr_fname[n]=cur_exp| and call |open_write_file| if...@>=
+{
+ char *fn = str(mp->cur_exp);
+ n=mp->write_files;
+ n0=mp->write_files;
+ while (mp_xstrcmp(fn,mp->wr_fname[n])!=0) {
+ if ( n==0 ) { /* bottom reached */
+ if ( n0==mp->write_files ) {
+ if ( mp->write_files<mp->max_write_files ) {
+ incr(mp->write_files);
+ } else {
+ void **wr_file;
+ char **wr_fname;
+ write_index l,k;
+ l = mp->max_write_files + (mp->max_write_files>>2);
+ wr_file = xmalloc((l+1),sizeof(void *));
+ wr_fname = xmalloc((l+1),sizeof(char *));
+ for (k=0;k<=l;k++) {
+ if (k<=mp->max_write_files) {
+ wr_file[k]=mp->wr_file[k];
+ wr_fname[k]=mp->wr_fname[k];
+ } else {
+ wr_file[k]=0;
+ wr_fname[k]=NULL;
+ }
+ }
+ xfree(mp->wr_file); xfree(mp->wr_fname);
+ mp->max_write_files = l;
+ mp->wr_file = wr_file;
+ mp->wr_fname = wr_fname;
+ }
+ }
+ n=n0;
+ mp_open_write_file(mp, fn ,n);
+ } else {
+ decr(n);
+ if ( mp->wr_fname[n]==NULL ) n0=n;
+ }
+ }
+}
+
+@ @<Record the end of file on |wr_file[n]|@>=
+{ (mp->close_file)(mp,mp->wr_file[n]);
+ xfree(mp->wr_fname[n]);
+ mp->wr_fname[n]=NULL;
+ if ( n==mp->write_files-1 ) mp->write_files=n;
+}
+
+
+@* \[42] Writing font metric data.
+\TeX\ gets its knowledge about fonts from font metric files, also called
+\.{TFM} files; the `\.T' in `\.{TFM}' stands for \TeX,
+but other programs know about them too. One of \MP's duties is to
+write \.{TFM} files so that the user's fonts can readily be
+applied to typesetting.
+@:TFM files}{\.{TFM} files@>
+@^font metric files@>
+
+The information in a \.{TFM} file appears in a sequence of 8-bit bytes.
+Since the number of bytes is always a multiple of~4, we could
+also regard the file as a sequence of 32-bit words, but \MP\ uses the
+byte interpretation. The format of \.{TFM} files was designed by
+Lyle Ramshaw in 1980. The intent is to convey a lot of different kinds
+@^Ramshaw, Lyle Harold@>
+of information in a compact but useful form.
+
+@<Glob...@>=
+void * tfm_file; /* the font metric output goes here */
+char * metric_file_name; /* full name of the font metric file */
+
+@ The first 24 bytes (6 words) of a \.{TFM} file contain twelve 16-bit
+integers that give the lengths of the various subsequent portions
+of the file. These twelve integers are, in order:
+$$\vbox{\halign{\hfil#&$\null=\null$#\hfil\cr
+|lf|&length of the entire file, in words;\cr
+|lh|&length of the header data, in words;\cr
+|bc|&smallest character code in the font;\cr
+|ec|&largest character code in the font;\cr
+|nw|&number of words in the width table;\cr
+|nh|&number of words in the height table;\cr
+|nd|&number of words in the depth table;\cr
+|ni|&number of words in the italic correction table;\cr
+|nl|&number of words in the lig/kern table;\cr
+|nk|&number of words in the kern table;\cr
+|ne|&number of words in the extensible character table;\cr
+|np|&number of font parameter words.\cr}}$$
+They are all nonnegative and less than $2^{15}$. We must have |bc-1<=ec<=255|,
+|ne<=256|, and
+$$\hbox{|lf=6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np|.}$$
+Note that a font may contain as many as 256 characters (if |bc=0| and |ec=255|),
+and as few as 0 characters (if |bc=ec+1|).
+
+Incidentally, when two or more 8-bit bytes are combined to form an integer of
+16 or more bits, the most significant bytes appear first in the file.
+This is called BigEndian order.
+@^BigEndian order@>
+
+@ The rest of the \.{TFM} file may be regarded as a sequence of ten data
+arrays.
+
+The most important data type used here is a |fix_word|, which is
+a 32-bit representation of a binary fraction. A |fix_word| is a signed
+quantity, with the two's complement of the entire word used to represent
+negation. Of the 32 bits in a |fix_word|, exactly 12 are to the left of the
+binary point; thus, the largest |fix_word| value is $2048-2^{-20}$, and
+the smallest is $-2048$. We will see below, however, that all but two of
+the |fix_word| values must lie between $-16$ and $+16$.
+
+@ The first data array is a block of header information, which contains
+general facts about the font. The header must contain at least two words,
+|header[0]| and |header[1]|, whose meaning is explained below. Additional
+header information of use to other software routines might also be
+included, and \MP\ will generate it if the \.{headerbyte} command occurs.
+For example, 16 more words of header information are in use at the Xerox
+Palo Alto Research Center; the first ten specify the character coding
+scheme used (e.g., `\.{XEROX TEXT}' or `\.{TEX MATHSY}'), the next five
+give the font family name (e.g., `\.{HELVETICA}' or `\.{CMSY}'), and the
+last gives the ``face byte.''
+
+\yskip\hang|header[0]| is a 32-bit check sum that \MP\ will copy into
+the \.{GF} output file. This helps ensure consistency between files,
+since \TeX\ records the check sums from the \.{TFM}'s it reads, and these
+should match the check sums on actual fonts that are used. The actual
+relation between this check sum and the rest of the \.{TFM} file is not
+important; the check sum is simply an identification number with the
+property that incompatible fonts almost always have distinct check sums.
+@^check sum@>
+
+\yskip\hang|header[1]| is a |fix_word| containing the design size of the
+font, in units of \TeX\ points. This number must be at least 1.0; it is
+fairly arbitrary, but usually the design size is 10.0 for a ``10 point''
+font, i.e., a font that was designed to look best at a 10-point size,
+whatever that really means. When a \TeX\ user asks for a font `\.{at}
+$\delta$ \.{pt}', the effect is to override the design size and replace it
+by $\delta$, and to multiply the $x$ and~$y$ coordinates of the points in
+the font image by a factor of $\delta$ divided by the design size. {\sl
+All other dimensions in the\/ \.{TFM} file are |fix_word|\kern-1pt\
+numbers in design-size units.} Thus, for example, the value of |param[6]|,
+which defines the \.{em} unit, is often the |fix_word| value $2^{20}=1.0$,
+since many fonts have a design size equal to one em. The other dimensions
+must be less than 16 design-size units in absolute value; thus,
+|header[1]| and |param[1]| are the only |fix_word| entries in the whole
+\.{TFM} file whose first byte might be something besides 0 or 255.
+@^design size@>
+
+@ Next comes the |char_info| array, which contains one |char_info_word|
+per character. Each word in this part of the file contains six fields
+packed into four bytes as follows.
+
+\yskip\hang first byte: |width_index| (8 bits)\par
+\hang second byte: |height_index| (4 bits) times 16, plus |depth_index|
+ (4~bits)\par
+\hang third byte: |italic_index| (6 bits) times 4, plus |tag|
+ (2~bits)\par
+\hang fourth byte: |remainder| (8 bits)\par
+\yskip\noindent
+The actual width of a character is \\{width}|[width_index]|, in design-size
+units; this is a device for compressing information, since many characters
+have the same width. Since it is quite common for many characters
+to have the same height, depth, or italic correction, the \.{TFM} format
+imposes a limit of 16 different heights, 16 different depths, and
+64 different italic corrections.
+
+Incidentally, the relation $\\{width}[0]=\\{height}[0]=\\{depth}[0]=
+\\{italic}[0]=0$ should always hold, so that an index of zero implies a
+value of zero. The |width_index| should never be zero unless the
+character does not exist in the font, since a character is valid if and
+only if it lies between |bc| and |ec| and has a nonzero |width_index|.
+
+@ The |tag| field in a |char_info_word| has four values that explain how to
+interpret the |remainder| field.
+
+\yskip\hang|tag=0| (|no_tag|) means that |remainder| is unused.\par
+\hang|tag=1| (|lig_tag|) means that this character has a ligature/kerning
+program starting at location |remainder| in the |lig_kern| array.\par
+\hang|tag=2| (|list_tag|) means that this character is part of a chain of
+characters of ascending sizes, and not the largest in the chain. The
+|remainder| field gives the character code of the next larger character.\par
+\hang|tag=3| (|ext_tag|) means that this character code represents an
+extensible character, i.e., a character that is built up of smaller pieces
+so that it can be made arbitrarily large. The pieces are specified in
+|exten[remainder]|.\par
+\yskip\noindent
+Characters with |tag=2| and |tag=3| are treated as characters with |tag=0|
+unless they are used in special circumstances in math formulas. For example,
+\TeX's \.{\\sum} operation looks for a |list_tag|, and the \.{\\left}
+operation looks for both |list_tag| and |ext_tag|.
+
+@d no_tag 0 /* vanilla character */
+@d lig_tag 1 /* character has a ligature/kerning program */
+@d list_tag 2 /* character has a successor in a charlist */
+@d ext_tag 3 /* character is extensible */
+
+@ The |lig_kern| array contains instructions in a simple programming language
+that explains what to do for special letter pairs. Each word in this array is a
+|lig_kern_command| of four bytes.
+
+\yskip\hang first byte: |skip_byte|, indicates that this is the final program
+ step if the byte is 128 or more, otherwise the next step is obtained by
+ skipping this number of intervening steps.\par
+\hang second byte: |next_char|, ``if |next_char| follows the current character,
+ then perform the operation and stop, otherwise continue.''\par
+\hang third byte: |op_byte|, indicates a ligature step if less than~128,
+ a kern step otherwise.\par
+\hang fourth byte: |remainder|.\par
+\yskip\noindent
+In a kern step, an
+additional space equal to |kern[256*(op_byte-128)+remainder]| is inserted
+between the current character and |next_char|. This amount is
+often negative, so that the characters are brought closer together
+by kerning; but it might be positive.
+
+There are eight kinds of ligature steps, having |op_byte| codes $4a+2b+c$ where
+$0\le a\le b+c$ and $0\le b,c\le1$. The character whose code is
+|remainder| is inserted between the current character and |next_char|;
+then the current character is deleted if $b=0$, and |next_char| is
+deleted if $c=0$; then we pass over $a$~characters to reach the next
+current character (which may have a ligature/kerning program of its own).
+
+If the very first instruction of the |lig_kern| array has |skip_byte=255|,
+the |next_char| byte is the so-called right boundary character of this font;
+the value of |next_char| need not lie between |bc| and~|ec|.
+If the very last instruction of the |lig_kern| array has |skip_byte=255|,
+there is a special ligature/kerning program for a left boundary character,
+beginning at location |256*op_byte+remainder|.
+The interpretation is that \TeX\ puts implicit boundary characters
+before and after each consecutive string of characters from the same font.
+These implicit characters do not appear in the output, but they can affect
+ligatures and kerning.
+
+If the very first instruction of a character's |lig_kern| program has
+|skip_byte>128|, the program actually begins in location
+|256*op_byte+remainder|. This feature allows access to large |lig_kern|
+arrays, because the first instruction must otherwise
+appear in a location |<=255|.
+
+Any instruction with |skip_byte>128| in the |lig_kern| array must satisfy
+the condition
+$$\hbox{|256*op_byte+remainder<nl|.}$$
+If such an instruction is encountered during
+normal program execution, it denotes an unconditional halt; no ligature
+command is performed.
+
+@d stop_flag (128)
+ /* value indicating `\.{STOP}' in a lig/kern program */
+@d kern_flag (128) /* op code for a kern step */
+@d skip_byte(A) mp->lig_kern[(A)].b0
+@d next_char(A) mp->lig_kern[(A)].b1
+@d op_byte(A) mp->lig_kern[(A)].b2
+@d rem_byte(A) mp->lig_kern[(A)].b3
+
+@ Extensible characters are specified by an |extensible_recipe|, which
+consists of four bytes called |top|, |mid|, |bot|, and |rep| (in this
+order). These bytes are the character codes of individual pieces used to
+build up a large symbol. If |top|, |mid|, or |bot| are zero, they are not
+present in the built-up result. For example, an extensible vertical line is
+like an extensible bracket, except that the top and bottom pieces are missing.
+
+Let $T$, $M$, $B$, and $R$ denote the respective pieces, or an empty box
+if the piece isn't present. Then the extensible characters have the form
+$TR^kMR^kB$ from top to bottom, for some |k>=0|, unless $M$ is absent;
+in the latter case we can have $TR^kB$ for both even and odd values of~|k|.
+The width of the extensible character is the width of $R$; and the
+height-plus-depth is the sum of the individual height-plus-depths of the
+components used, since the pieces are butted together in a vertical list.
+
+@d ext_top(A) mp->exten[(A)].b0 /* |top| piece in a recipe */
+@d ext_mid(A) mp->exten[(A)].b1 /* |mid| piece in a recipe */
+@d ext_bot(A) mp->exten[(A)].b2 /* |bot| piece in a recipe */
+@d ext_rep(A) mp->exten[(A)].b3 /* |rep| piece in a recipe */
+
+@ The final portion of a \.{TFM} file is the |param| array, which is another
+sequence of |fix_word| values.
+
+\yskip\hang|param[1]=slant| is the amount of italic slant, which is used
+to help position accents. For example, |slant=.25| means that when you go
+up one unit, you also go .25 units to the right. The |slant| is a pure
+number; it is the only |fix_word| other than the design size itself that is
+not scaled by the design size.
+@^design size@>
+
+\hang|param[2]=space| is the normal spacing between words in text.
+Note that character 040 in the font need not have anything to do with
+blank spaces.
+
+\hang|param[3]=space_stretch| is the amount of glue stretching between words.
+
+\hang|param[4]=space_shrink| is the amount of glue shrinking between words.
+
+\hang|param[5]=x_height| is the size of one ex in the font; it is also
+the height of letters for which accents don't have to be raised or lowered.
+
+\hang|param[6]=quad| is the size of one em in the font.
+
+\hang|param[7]=extra_space| is the amount added to |param[2]| at the
+ends of sentences.
+
+\yskip\noindent
+If fewer than seven parameters are present, \TeX\ sets the missing parameters
+to zero.
+
+@d slant_code 1
+@d space_code 2
+@d space_stretch_code 3
+@d space_shrink_code 4
+@d x_height_code 5
+@d quad_code 6
+@d extra_space_code 7
+
+@ So that is what \.{TFM} files hold. One of \MP's duties is to output such
+information, and it does this all at once at the end of a job.
+In order to prepare for such frenetic activity, it squirrels away the
+necessary facts in various arrays as information becomes available.
+
+Character dimensions (\&{charwd}, \&{charht}, \&{chardp}, and \&{charic})
+are stored respectively in |tfm_width|, |tfm_height|, |tfm_depth|, and
+|tfm_ital_corr|. Other information about a character (e.g., about
+its ligatures or successors) is accessible via the |char_tag| and
+|char_remainder| arrays. Other information about the font as a whole
+is kept in additional arrays called |header_byte|, |lig_kern|,
+|kern|, |exten|, and |param|.
+
+@d max_tfm_int 32510
+@d undefined_label max_tfm_int /* an undefined local label */
+
+@<Glob...@>=
+#define TFM_ITEMS 257
+eight_bits bc;
+eight_bits ec; /* smallest and largest character codes shipped out */
+scaled tfm_width[TFM_ITEMS]; /* \&{charwd} values */
+scaled tfm_height[TFM_ITEMS]; /* \&{charht} values */
+scaled tfm_depth[TFM_ITEMS]; /* \&{chardp} values */
+scaled tfm_ital_corr[TFM_ITEMS]; /* \&{charic} values */
+boolean char_exists[TFM_ITEMS]; /* has this code been shipped out? */
+int char_tag[TFM_ITEMS]; /* |remainder| category */
+int char_remainder[TFM_ITEMS]; /* the |remainder| byte */
+char *header_byte; /* bytes of the \.{TFM} header */
+int header_last; /* last initialized \.{TFM} header byte */
+int header_size; /* size of the \.{TFM} header */
+four_quarters *lig_kern; /* the ligature/kern table */
+short nl; /* the number of ligature/kern steps so far */
+scaled *kern; /* distinct kerning amounts */
+short nk; /* the number of distinct kerns so far */
+four_quarters exten[TFM_ITEMS]; /* extensible character recipes */
+short ne; /* the number of extensible characters so far */
+scaled *param; /* \&{fontinfo} parameters */
+short np; /* the largest \&{fontinfo} parameter specified so far */
+short nw;short nh;short nd;short ni; /* sizes of \.{TFM} subtables */
+short skip_table[TFM_ITEMS]; /* local label status */
+boolean lk_started; /* has there been a lig/kern step in this command yet? */
+integer bchar; /* right boundary character */
+short bch_label; /* left boundary starting location */
+short ll;short lll; /* registers used for lig/kern processing */
+short label_loc[257]; /* lig/kern starting addresses */
+eight_bits label_char[257]; /* characters for |label_loc| */
+short label_ptr; /* highest position occupied in |label_loc| */
+
+@ @<Allocate or initialize ...@>=
+mp->header_last = 0; mp->header_size = 128; /* just for init */
+mp->header_byte = xmalloc(mp->header_size, sizeof(char));
+mp->lig_kern = NULL; /* allocated when needed */
+mp->kern = NULL; /* allocated when needed */
+mp->param = NULL; /* allocated when needed */
+
+@ @<Dealloc variables@>=
+xfree(mp->header_byte);
+xfree(mp->lig_kern);
+xfree(mp->kern);
+xfree(mp->param);
+
+@ @<Set init...@>=
+for (k=0;k<= 255;k++ ) {
+ mp->tfm_width[k]=0; mp->tfm_height[k]=0; mp->tfm_depth[k]=0; mp->tfm_ital_corr[k]=0;
+ mp->char_exists[k]=false; mp->char_tag[k]=no_tag; mp->char_remainder[k]=0;
+ mp->skip_table[k]=undefined_label;
+}
+memset(mp->header_byte,0,mp->header_size);
+mp->bc=255; mp->ec=0; mp->nl=0; mp->nk=0; mp->ne=0; mp->np=0;
+mp->internal[mp_boundary_char]=-unity;
+mp->bch_label=undefined_label;
+mp->label_loc[0]=-1; mp->label_ptr=0;
+
+@ @<Declarations@>=
+scaled mp_tfm_check (MP mp,small_number m) ;
+
+@ @<Declare the function called |tfm_check|@>=
+scaled mp_tfm_check (MP mp,small_number m) {
+ if ( abs(mp->internal[m])>=fraction_half ) {
+ print_err("Enormous "); mp_print(mp, mp->int_name[m]);
+@.Enormous charwd...@>
+@.Enormous chardp...@>
+@.Enormous charht...@>
+@.Enormous charic...@>
+@.Enormous designsize...@>
+ mp_print(mp, " has been reduced");
+ help1("Font metric dimensions must be less than 2048pt.");
+ mp_put_get_error(mp);
+ if ( mp->internal[m]>0 ) return (fraction_half-1);
+ else return (1-fraction_half);
+ } else {
+ return mp->internal[m];
+ }
+}
+
+@ @<Store the width information for character code~|c|@>=
+if ( c<mp->bc ) mp->bc=c;
+if ( c>mp->ec ) mp->ec=c;
+mp->char_exists[c]=true;
+mp->tfm_width[c]=mp_tfm_check(mp, mp_char_wd);
+mp->tfm_height[c]=mp_tfm_check(mp, mp_char_ht);
+mp->tfm_depth[c]=mp_tfm_check(mp, mp_char_dp);
+mp->tfm_ital_corr[c]=mp_tfm_check(mp, mp_char_ic)
+
+@ Now let's consider \MP's special \.{TFM}-oriented commands.
+
+@<Cases of |do_statement|...@>=
+case tfm_command: mp_do_tfm_command(mp); break;
+
+@ @d char_list_code 0
+@d lig_table_code 1
+@d extensible_code 2
+@d header_byte_code 3
+@d font_dimen_code 4
+
+@<Put each...@>=
+mp_primitive(mp, "charlist",tfm_command,char_list_code);
+@:char_list_}{\&{charlist} primitive@>
+mp_primitive(mp, "ligtable",tfm_command,lig_table_code);
+@:lig_table_}{\&{ligtable} primitive@>
+mp_primitive(mp, "extensible",tfm_command,extensible_code);
+@:extensible_}{\&{extensible} primitive@>
+mp_primitive(mp, "headerbyte",tfm_command,header_byte_code);
+@:header_byte_}{\&{headerbyte} primitive@>
+mp_primitive(mp, "fontdimen",tfm_command,font_dimen_code);
+@:font_dimen_}{\&{fontdimen} primitive@>
+
+@ @<Cases of |print_cmd...@>=
+case tfm_command:
+ switch (m) {
+ case char_list_code:mp_print(mp, "charlist"); break;
+ case lig_table_code:mp_print(mp, "ligtable"); break;
+ case extensible_code:mp_print(mp, "extensible"); break;
+ case header_byte_code:mp_print(mp, "headerbyte"); break;
+ default: mp_print(mp, "fontdimen"); break;
+ }
+ break;
+
+@ @<Declare action procedures for use by |do_statement|@>=
+eight_bits mp_get_code (MP mp) ;
+
+@ @c eight_bits mp_get_code (MP mp) { /* scans a character code value */
+ integer c; /* the code value found */
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type==mp_known ) {
+ c=mp_round_unscaled(mp, mp->cur_exp);
+ if ( c>=0 ) if ( c<256 ) return c;
+ } else if ( mp->cur_type==mp_string_type ) {
+ if ( length(mp->cur_exp)==1 ) {
+ c=mp->str_pool[mp->str_start[mp->cur_exp]];
+ return c;
+ }
+ }
+ exp_err("Invalid code has been replaced by 0");
+@.Invalid code...@>
+ help2("I was looking for a number between 0 and 255, or for a")
+ ("string of length 1. Didn't find it; will use 0 instead.");
+ mp_put_get_flush_error(mp, 0); c=0;
+ return c;
+}
+
+@ @<Declare action procedures for use by |do_statement|@>=
+void mp_set_tag (MP mp,halfword c, small_number t, halfword r) ;
+
+@ @c void mp_set_tag (MP mp,halfword c, small_number t, halfword r) {
+ if ( mp->char_tag[c]==no_tag ) {
+ mp->char_tag[c]=t; mp->char_remainder[c]=r;
+ if ( t==lig_tag ){
+ incr(mp->label_ptr); mp->label_loc[mp->label_ptr]=r;
+ mp->label_char[mp->label_ptr]=c;
+ }
+ } else {
+ @<Complain about a character tag conflict@>;
+ }
+}
+
+@ @<Complain about a character tag conflict@>=
+{
+ print_err("Character ");
+ if ( (c>' ')&&(c<127) ) mp_print_char(mp,c);
+ else if ( c==256 ) mp_print(mp, "||");
+ else { mp_print(mp, "code "); mp_print_int(mp, c); };
+ mp_print(mp, " is already ");
+@.Character c is already...@>
+ switch (mp->char_tag[c]) {
+ case lig_tag: mp_print(mp, "in a ligtable"); break;
+ case list_tag: mp_print(mp, "in a charlist"); break;
+ case ext_tag: mp_print(mp, "extensible"); break;
+ } /* there are no other cases */
+ help2("It's not legal to label a character more than once.")
+ ("So I'll not change anything just now.");
+ mp_put_get_error(mp);
+}
+
+@ @<Declare action procedures for use by |do_statement|@>=
+void mp_do_tfm_command (MP mp) ;
+
+@ @c void mp_do_tfm_command (MP mp) {
+ int c,cc; /* character codes */
+ int k; /* index into the |kern| array */
+ int j; /* index into |header_byte| or |param| */
+ switch (mp->cur_mod) {
+ case char_list_code:
+ c=mp_get_code(mp);
+ /* we will store a list of character successors */
+ while ( mp->cur_cmd==colon ) {
+ cc=mp_get_code(mp); mp_set_tag(mp, c,list_tag,cc); c=cc;
+ };
+ break;
+ case lig_table_code:
+ if (mp->lig_kern==NULL)
+ mp->lig_kern = xmalloc((max_tfm_int+1),sizeof(four_quarters));
+ if (mp->kern==NULL)
+ mp->kern = xmalloc((max_tfm_int+1),sizeof(scaled));
+ @<Store a list of ligature/kern steps@>;
+ break;
+ case extensible_code:
+ @<Define an extensible recipe@>;
+ break;
+ case header_byte_code:
+ case font_dimen_code:
+ c=mp->cur_mod; mp_get_x_next(mp);
+ mp_scan_expression(mp);
+ if ( (mp->cur_type!=mp_known)||(mp->cur_exp<half_unit) ) {
+ exp_err("Improper location");
+@.Improper location@>
+ help2("I was looking for a known, positive number.")
+ ("For safety's sake I'll ignore the present command.");
+ mp_put_get_error(mp);
+ } else {
+ j=mp_round_unscaled(mp, mp->cur_exp);
+ if ( mp->cur_cmd!=colon ) {
+ mp_missing_err(mp, ":");
+@.Missing `:'@>
+ help1("A colon should follow a headerbyte or fontinfo location.");
+ mp_back_error(mp);
+ }
+ if ( c==header_byte_code ) {
+ @<Store a list of header bytes@>;
+ } else {
+ if (mp->param==NULL)
+ mp->param = xmalloc((max_tfm_int+1),sizeof(scaled));
+ @<Store a list of font dimensions@>;
+ }
+ }
+ break;
+ } /* there are no other cases */
+}
+
+@ @<Store a list of ligature/kern steps@>=
+{
+ mp->lk_started=false;
+CONTINUE:
+ mp_get_x_next(mp);
+ if ((mp->cur_cmd==skip_to)&& mp->lk_started )
+ @<Process a |skip_to| command and |goto done|@>;
+ if ( mp->cur_cmd==bchar_label ) { c=256; mp->cur_cmd=colon; }
+ else { mp_back_input(mp); c=mp_get_code(mp); };
+ if ((mp->cur_cmd==colon)||(mp->cur_cmd==double_colon)) {
+ @<Record a label in a lig/kern subprogram and |goto continue|@>;
+ }
+ if ( mp->cur_cmd==lig_kern_token ) {
+ @<Compile a ligature/kern command@>;
+ } else {
+ print_err("Illegal ligtable step");
+@.Illegal ligtable step@>
+ help1("I was looking for `=:' or `kern' here.");
+ mp_back_error(mp); next_char(mp->nl)=qi(0);
+ op_byte(mp->nl)=qi(0); rem_byte(mp->nl)=qi(0);
+ skip_byte(mp->nl)=stop_flag+1; /* this specifies an unconditional stop */
+ }
+ if ( mp->nl==max_tfm_int) mp_fatal_error(mp, "ligtable too large");
+ incr(mp->nl);
+ if ( mp->cur_cmd==comma ) goto CONTINUE;
+ if ( skip_byte(mp->nl-1)<stop_flag ) skip_byte(mp->nl-1)=stop_flag;
+}
+DONE:
+
+@ @<Put each...@>=
+mp_primitive(mp, "=:",lig_kern_token,0);
+@:=:_}{\.{=:} primitive@>
+mp_primitive(mp, "=:|",lig_kern_token,1);
+@:=:/_}{\.{=:\char'174} primitive@>
+mp_primitive(mp, "=:|>",lig_kern_token,5);
+@:=:/>_}{\.{=:\char'174>} primitive@>
+mp_primitive(mp, "|=:",lig_kern_token,2);
+@:=:/_}{\.{\char'174=:} primitive@>
+mp_primitive(mp, "|=:>",lig_kern_token,6);
+@:=:/>_}{\.{\char'174=:>} primitive@>
+mp_primitive(mp, "|=:|",lig_kern_token,3);
+@:=:/_}{\.{\char'174=:\char'174} primitive@>
+mp_primitive(mp, "|=:|>",lig_kern_token,7);
+@:=:/>_}{\.{\char'174=:\char'174>} primitive@>
+mp_primitive(mp, "|=:|>>",lig_kern_token,11);
+@:=:/>_}{\.{\char'174=:\char'174>>} primitive@>
+mp_primitive(mp, "kern",lig_kern_token,128);
+@:kern_}{\&{kern} primitive@>
+
+@ @<Cases of |print_cmd...@>=
+case lig_kern_token:
+ switch (m) {
+ case 0:mp_print(mp, "=:"); break;
+ case 1:mp_print(mp, "=:|"); break;
+ case 2:mp_print(mp, "|=:"); break;
+ case 3:mp_print(mp, "|=:|"); break;
+ case 5:mp_print(mp, "=:|>"); break;
+ case 6:mp_print(mp, "|=:>"); break;
+ case 7:mp_print(mp, "|=:|>"); break;
+ case 11:mp_print(mp, "|=:|>>"); break;
+ default: mp_print(mp, "kern"); break;
+ }
+ break;
+
+@ Local labels are implemented by maintaining the |skip_table| array,
+where |skip_table[c]| is either |undefined_label| or the address of the
+most recent lig/kern instruction that skips to local label~|c|. In the
+latter case, the |skip_byte| in that instruction will (temporarily)
+be zero if there were no prior skips to this label, or it will be the
+distance to the prior skip.
+
+We may need to cancel skips that span more than 127 lig/kern steps.
+
+@d cancel_skips(A) mp->ll=(A);
+ do {
+ mp->lll=qo(skip_byte(mp->ll));
+ skip_byte(mp->ll)=stop_flag; mp->ll=mp->ll-mp->lll;
+ } while (mp->lll!=0)
+@d skip_error(A) { print_err("Too far to skip");
+@.Too far to skip@>
+ help1("At most 127 lig/kern steps can separate skipto1 from 1::.");
+ mp_error(mp); cancel_skips((A));
+ }
+
+@<Process a |skip_to| command and |goto done|@>=
+{
+ c=mp_get_code(mp);
+ if ( mp->nl-mp->skip_table[c]>128 ) {
+ skip_error(mp->skip_table[c]); mp->skip_table[c]=undefined_label;
+ }
+ if ( mp->skip_table[c]==undefined_label ) skip_byte(mp->nl-1)=qi(0);
+ else skip_byte(mp->nl-1)=qi(mp->nl-mp->skip_table[c]-1);
+ mp->skip_table[c]=mp->nl-1; goto DONE;
+}
+
+@ @<Record a label in a lig/kern subprogram and |goto continue|@>=
+{
+ if ( mp->cur_cmd==colon ) {
+ if ( c==256 ) mp->bch_label=mp->nl;
+ else mp_set_tag(mp, c,lig_tag,mp->nl);
+ } else if ( mp->skip_table[c]<undefined_label ) {
+ mp->ll=mp->skip_table[c]; mp->skip_table[c]=undefined_label;
+ do {
+ mp->lll=qo(skip_byte(mp->ll));
+ if ( mp->nl-mp->ll>128 ) {
+ skip_error(mp->ll); goto CONTINUE;
+ }
+ skip_byte(mp->ll)=qi(mp->nl-mp->ll-1); mp->ll=mp->ll-mp->lll;
+ } while (mp->lll!=0);
+ }
+ goto CONTINUE;
+}
+
+@ @<Compile a ligature/kern...@>=
+{
+ next_char(mp->nl)=qi(c); skip_byte(mp->nl)=qi(0);
+ if ( mp->cur_mod<128 ) { /* ligature op */
+ op_byte(mp->nl)=qi(mp->cur_mod); rem_byte(mp->nl)=qi(mp_get_code(mp));
+ } else {
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type!=mp_known ) {
+ exp_err("Improper kern");
+@.Improper kern@>
+ help2("The amount of kern should be a known numeric value.")
+ ("I'm zeroing this one. Proceed, with fingers crossed.");
+ mp_put_get_flush_error(mp, 0);
+ }
+ mp->kern[mp->nk]=mp->cur_exp;
+ k=0;
+ while ( mp->kern[k]!=mp->cur_exp ) incr(k);
+ if ( k==mp->nk ) {
+ if ( mp->nk==max_tfm_int ) mp_fatal_error(mp, "too many TFM kerns");
+ incr(mp->nk);
+ }
+ op_byte(mp->nl)=kern_flag+(k / 256);
+ rem_byte(mp->nl)=qi((k % 256));
+ }
+ mp->lk_started=true;
+}
+
+@ @d missing_extensible_punctuation(A)
+ { mp_missing_err(mp, (A));
+@.Missing `\char`\#'@>
+ help1("I'm processing `extensible c: t,m,b,r'."); mp_back_error(mp);
+ }
+
+@<Define an extensible recipe@>=
+{
+ if ( mp->ne==256 ) mp_fatal_error(mp, "too many extensible recipies");
+ c=mp_get_code(mp); mp_set_tag(mp, c,ext_tag,mp->ne);
+ if ( mp->cur_cmd!=colon ) missing_extensible_punctuation(":");
+ ext_top(mp->ne)=qi(mp_get_code(mp));
+ if ( mp->cur_cmd!=comma ) missing_extensible_punctuation(",");
+ ext_mid(mp->ne)=qi(mp_get_code(mp));
+ if ( mp->cur_cmd!=comma ) missing_extensible_punctuation(",");
+ ext_bot(mp->ne)=qi(mp_get_code(mp));
+ if ( mp->cur_cmd!=comma ) missing_extensible_punctuation(",");
+ ext_rep(mp->ne)=qi(mp_get_code(mp));
+ incr(mp->ne);
+}
+
+@ The header could contain ASCII zeroes, so can't use |strdup|.
+
+@<Store a list of header bytes@>=
+do {
+ if ( j>=mp->header_size ) {
+ int l = mp->header_size + (mp->header_size >> 2);
+ char *t = xmalloc(l,sizeof(char));
+ memset(t,0,l);
+ memcpy(t,mp->header_byte,mp->header_size);
+ xfree (mp->header_byte);
+ mp->header_byte = t;
+ mp->header_size = l;
+ }
+ mp->header_byte[j]=mp_get_code(mp);
+ incr(j); incr(mp->header_last);
+} while (mp->cur_cmd==comma)
+
+@ @<Store a list of font dimensions@>=
+do {
+ if ( j>max_tfm_int ) mp_fatal_error(mp, "too many fontdimens");
+ while ( j>mp->np ) { incr(mp->np); mp->param[mp->np]=0; };
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type!=mp_known ){
+ exp_err("Improper font parameter");
+@.Improper font parameter@>
+ help1("I'm zeroing this one. Proceed, with fingers crossed.");
+ mp_put_get_flush_error(mp, 0);
+ }
+ mp->param[j]=mp->cur_exp; incr(j);
+} while (mp->cur_cmd==comma)
+
+@ OK: We've stored all the data that is needed for the \.{TFM} file.
+All that remains is to output it in the correct format.
+
+An interesting problem needs to be solved in this connection, because
+the \.{TFM} format allows at most 256~widths, 16~heights, 16~depths,
+and 64~italic corrections. If the data has more distinct values than
+this, we want to meet the necessary restrictions by perturbing the
+given values as little as possible.
+
+\MP\ solves this problem in two steps. First the values of a given
+kind (widths, heights, depths, or italic corrections) are sorted;
+then the list of sorted values is perturbed, if necessary.
+
+The sorting operation is facilitated by having a special node of
+essentially infinite |value| at the end of the current list.
+
+@<Initialize table entries...@>=
+value(inf_val)=fraction_four;
+
+@ Straight linear insertion is good enough for sorting, since the lists
+are usually not terribly long. As we work on the data, the current list
+will start at |link(temp_head)| and end at |inf_val|; the nodes in this
+list will be in increasing order of their |value| fields.
+
+Given such a list, the |sort_in| function takes a value and returns a pointer
+to where that value can be found in the list. The value is inserted in
+the proper place, if necessary.
+
+At the time we need to do these operations, most of \MP's work has been
+completed, so we will have plenty of memory to play with. The value nodes
+that are allocated for sorting will never be returned to free storage.
+
+@d clear_the_list link(temp_head)=inf_val
+
+@c pointer mp_sort_in (MP mp,scaled v) {
+ pointer p,q,r; /* list manipulation registers */
+ p=temp_head;
+ while (1) {
+ q=link(p);
+ if ( v<=value(q) ) break;
+ p=q;
+ }
+ if ( v<value(q) ) {
+ r=mp_get_node(mp, value_node_size); value(r)=v; link(r)=q; link(p)=r;
+ }
+ return link(p);
+}
+
+@ Now we come to the interesting part, where we reduce the list if necessary
+until it has the required size. The |min_cover| routine is basic to this
+process; it computes the minimum number~|m| such that the values of the
+current sorted list can be covered by |m|~intervals of width~|d|. It
+also sets the global value |perturbation| to the smallest value $d'>d$
+such that the covering found by this algorithm would be different.
+
+In particular, |min_cover(0)| returns the number of distinct values in the
+current list and sets |perturbation| to the minimum distance between
+adjacent values.
+
+@c integer mp_min_cover (MP mp,scaled d) {
+ pointer p; /* runs through the current list */
+ scaled l; /* the least element covered by the current interval */
+ integer m; /* lower bound on the size of the minimum cover */
+ m=0; p=link(temp_head); mp->perturbation=el_gordo;
+ while ( p!=inf_val ){
+ incr(m); l=value(p);
+ do { p=link(p); } while (value(p)<=l+d);
+ if ( value(p)-l<mp->perturbation )
+ mp->perturbation=value(p)-l;
+ }
+ return m;
+}
+
+@ @<Glob...@>=
+scaled perturbation; /* quantity related to \.{TFM} rounding */
+integer excess; /* the list is this much too long */
+
+@ The smallest |d| such that a given list can be covered with |m| intervals
+is determined by the |threshold| routine, which is sort of an inverse
+to |min_cover|. The idea is to increase the interval size rapidly until
+finding the range, then to go sequentially until the exact borderline has
+been discovered.
+
+@c scaled mp_threshold (MP mp,integer m) {
+ scaled d; /* lower bound on the smallest interval size */
+ mp->excess=mp_min_cover(mp, 0)-m;
+ if ( mp->excess<=0 ) {
+ return 0;
+ } else {
+ do {
+ d=mp->perturbation;
+ } while (mp_min_cover(mp, d+d)>m);
+ while ( mp_min_cover(mp, d)>m )
+ d=mp->perturbation;
+ return d;
+ }
+}
+
+@ The |skimp| procedure reduces the current list to at most |m| entries,
+by changing values if necessary. It also sets |info(p):=k| if |value(p)|
+is the |k|th distinct value on the resulting list, and it sets
+|perturbation| to the maximum amount by which a |value| field has
+been changed. The size of the resulting list is returned as the
+value of |skimp|.
+
+@c integer mp_skimp (MP mp,integer m) {
+ scaled d; /* the size of intervals being coalesced */
+ pointer p,q,r; /* list manipulation registers */
+ scaled l; /* the least value in the current interval */
+ scaled v; /* a compromise value */
+ d=mp_threshold(mp, m); mp->perturbation=0;
+ q=temp_head; m=0; p=link(temp_head);
+ while ( p!=inf_val ) {
+ incr(m); l=value(p); info(p)=m;
+ if ( value(link(p))<=l+d ) {
+ @<Replace an interval of values by its midpoint@>;
+ }
+ q=p; p=link(p);
+ }
+ return m;
+}
+
+@ @<Replace an interval...@>=
+{
+ do {
+ p=link(p); info(p)=m;
+ decr(mp->excess); if ( mp->excess==0 ) d=0;
+ } while (value(link(p))<=l+d);
+ v=l+halfp(value(p)-l);
+ if ( value(p)-v>mp->perturbation )
+ mp->perturbation=value(p)-v;
+ r=q;
+ do {
+ r=link(r); value(r)=v;
+ } while (r!=p);
+ link(q)=p; /* remove duplicate values from the current list */
+}
+
+@ A warning message is issued whenever something is perturbed by
+more than 1/16\thinspace pt.
+
+@c void mp_tfm_warning (MP mp,small_number m) {
+ mp_print_nl(mp, "(some ");
+ mp_print(mp, mp->int_name[m]);
+@.some charwds...@>
+@.some chardps...@>
+@.some charhts...@>
+@.some charics...@>
+ mp_print(mp, " values had to be adjusted by as much as ");
+ mp_print_scaled(mp, mp->perturbation); mp_print(mp, "pt)");
+}
+
+@ Here's an example of how we use these routines.
+The width data needs to be perturbed only if there are 256 distinct
+widths, but \MP\ must check for this case even though it is
+highly unusual.
+
+An integer variable |k| will be defined when we use this code.
+The |dimen_head| array will contain pointers to the sorted
+lists of dimensions.
+
+@<Massage the \.{TFM} widths@>=
+clear_the_list;
+for (k=mp->bc;k<=mp->ec;k++) {
+ if ( mp->char_exists[k] )
+ mp->tfm_width[k]=mp_sort_in(mp, mp->tfm_width[k]);
+}
+mp->nw=mp_skimp(mp, 255)+1; mp->dimen_head[1]=link(temp_head);
+if ( mp->perturbation>=010000 ) mp_tfm_warning(mp, mp_char_wd)
+
+@ @<Glob...@>=
+pointer dimen_head[5]; /* lists of \.{TFM} dimensions */
+
+@ Heights, depths, and italic corrections are different from widths
+not only because their list length is more severely restricted, but
+also because zero values do not need to be put into the lists.
+
+@<Massage the \.{TFM} heights, depths, and italic corrections@>=
+clear_the_list;
+for (k=mp->bc;k<=mp->ec;k++) {
+ if ( mp->char_exists[k] ) {
+ if ( mp->tfm_height[k]==0 ) mp->tfm_height[k]=zero_val;
+ else mp->tfm_height[k]=mp_sort_in(mp, mp->tfm_height[k]);
+ }
+}
+mp->nh=mp_skimp(mp, 15)+1; mp->dimen_head[2]=link(temp_head);
+if ( mp->perturbation>=010000 ) mp_tfm_warning(mp, mp_char_ht);
+clear_the_list;
+for (k=mp->bc;k<=mp->ec;k++) {
+ if ( mp->char_exists[k] ) {
+ if ( mp->tfm_depth[k]==0 ) mp->tfm_depth[k]=zero_val;
+ else mp->tfm_depth[k]=mp_sort_in(mp, mp->tfm_depth[k]);
+ }
+}
+mp->nd=mp_skimp(mp, 15)+1; mp->dimen_head[3]=link(temp_head);
+if ( mp->perturbation>=010000 ) mp_tfm_warning(mp, mp_char_dp);
+clear_the_list;
+for (k=mp->bc;k<=mp->ec;k++) {
+ if ( mp->char_exists[k] ) {
+ if ( mp->tfm_ital_corr[k]==0 ) mp->tfm_ital_corr[k]=zero_val;
+ else mp->tfm_ital_corr[k]=mp_sort_in(mp, mp->tfm_ital_corr[k]);
+ }
+}
+mp->ni=mp_skimp(mp, 63)+1; mp->dimen_head[4]=link(temp_head);
+if ( mp->perturbation>=010000 ) mp_tfm_warning(mp, mp_char_ic)
+
+@ @<Initialize table entries...@>=
+value(zero_val)=0; info(zero_val)=0;
+
+@ Bytes 5--8 of the header are set to the design size, unless the user has
+some crazy reason for specifying them differently.
+@^design size@>
+
+Error messages are not allowed at the time this procedure is called,
+so a warning is printed instead.
+
+The value of |max_tfm_dimen| is calculated so that
+$$\hbox{|make_scaled(16*max_tfm_dimen,internal[mp_design_size])|}
+ < \\{three\_bytes}.$$
+
+@d three_bytes 0100000000 /* $2^{24}$ */
+
+@c
+void mp_fix_design_size (MP mp) {
+ scaled d; /* the design size */
+ d=mp->internal[mp_design_size];
+ if ( (d<unity)||(d>=fraction_half) ) {
+ if ( d!=0 )
+ mp_print_nl(mp, "(illegal design size has been changed to 128pt)");
+@.illegal design size...@>
+ d=040000000; mp->internal[mp_design_size]=d;
+ }
+ if ( mp->header_byte[4]<0 ) if ( mp->header_byte[5]<0 )
+ if ( mp->header_byte[6]<0 ) if ( mp->header_byte[7]<0 ) {
+ mp->header_byte[4]=d / 04000000;
+ mp->header_byte[5]=(d / 4096) % 256;
+ mp->header_byte[6]=(d / 16) % 256;
+ mp->header_byte[7]=(d % 16)*16;
+ };
+ mp->max_tfm_dimen=16*mp->internal[mp_design_size]-1-mp->internal[mp_design_size] / 010000000;
+ if ( mp->max_tfm_dimen>=fraction_half ) mp->max_tfm_dimen=fraction_half-1;
+}
+
+@ The |dimen_out| procedure computes a |fix_word| relative to the
+design size. If the data was out of range, it is corrected and the
+global variable |tfm_changed| is increased by~one.
+
+@c integer mp_dimen_out (MP mp,scaled x) {
+ if ( abs(x)>mp->max_tfm_dimen ) {
+ incr(mp->tfm_changed);
+ if ( x>0 ) x=mp->max_tfm_dimen; else x=-mp->max_tfm_dimen;
+ }
+ x=mp_make_scaled(mp, x*16,mp->internal[mp_design_size]);
+ return x;
+}
+
+@ @<Glob...@>=
+scaled max_tfm_dimen; /* bound on widths, heights, kerns, etc. */
+integer tfm_changed; /* the number of data entries that were out of bounds */
+
+@ If the user has not specified any of the first four header bytes,
+the |fix_check_sum| procedure replaces them by a ``check sum'' computed
+from the |tfm_width| data relative to the design size.
+@^check sum@>
+
+@c void mp_fix_check_sum (MP mp) {
+ eight_bits k; /* runs through character codes */
+ eight_bits B1,B2,B3,B4; /* bytes of the check sum */
+ integer x; /* hash value used in check sum computation */
+ if ( mp->header_byte[0]==0 && mp->header_byte[1]==0 &&
+ mp->header_byte[2]==0 && mp->header_byte[3]==0 ) {
+ @<Compute a check sum in |(b1,b2,b3,b4)|@>;
+ mp->header_byte[0]=B1; mp->header_byte[1]=B2;
+ mp->header_byte[2]=B3; mp->header_byte[3]=B4;
+ return;
+ }
+}
+
+@ @<Compute a check sum in |(b1,b2,b3,b4)|@>=
+B1=mp->bc; B2=mp->ec; B3=mp->bc; B4=mp->ec; mp->tfm_changed=0;
+for (k=mp->bc;k<=mp->ec;k++) {
+ if ( mp->char_exists[k] ) {
+ x=mp_dimen_out(mp, value(mp->tfm_width[k]))+(k+4)*020000000; /* this is positive */
+ B1=(B1+B1+x) % 255;
+ B2=(B2+B2+x) % 253;
+ B3=(B3+B3+x) % 251;
+ B4=(B4+B4+x) % 247;
+ }
+}
+
+@ Finally we're ready to actually write the \.{TFM} information.
+Here are some utility routines for this purpose.
+
+@d tfm_out(A) do { /* output one byte to |tfm_file| */
+ unsigned char s=(A);
+ (mp->write_binary_file)(mp,mp->tfm_file,(void *)&s,1);
+ } while (0)
+
+@c void mp_tfm_two (MP mp,integer x) { /* output two bytes to |tfm_file| */
+ tfm_out(x / 256); tfm_out(x % 256);
+}
+void mp_tfm_four (MP mp,integer x) { /* output four bytes to |tfm_file| */
+ if ( x>=0 ) tfm_out(x / three_bytes);
+ else {
+ x=x+010000000000; /* use two's complement for negative values */
+ x=x+010000000000;
+ tfm_out((x / three_bytes) + 128);
+ };
+ x=x % three_bytes; tfm_out(x / unity);
+ x=x % unity; tfm_out(x / 0400);
+ tfm_out(x % 0400);
+}
+void mp_tfm_qqqq (MP mp,four_quarters x) { /* output four quarterwords to |tfm_file| */
+ tfm_out(qo(x.b0)); tfm_out(qo(x.b1));
+ tfm_out(qo(x.b2)); tfm_out(qo(x.b3));
+}
+
+@ @<Finish the \.{TFM} file@>=
+if ( mp->job_name==NULL ) mp_open_log_file(mp);
+mp_pack_job_name(mp, ".tfm");
+while ( ! mp_b_open_out(mp, &mp->tfm_file, mp_filetype_metrics) )
+ mp_prompt_file_name(mp, "file name for font metrics",".tfm");
+mp->metric_file_name=xstrdup(mp->name_of_file);
+@<Output the subfile sizes and header bytes@>;
+@<Output the character information bytes, then
+ output the dimensions themselves@>;
+@<Output the ligature/kern program@>;
+@<Output the extensible character recipes and the font metric parameters@>;
+ if ( mp->internal[mp_tracing_stats]>0 )
+ @<Log the subfile sizes of the \.{TFM} file@>;
+mp_print_nl(mp, "Font metrics written on ");
+mp_print(mp, mp->metric_file_name); mp_print_char(mp, '.');
+@.Font metrics written...@>
+(mp->close_file)(mp,mp->tfm_file)
+
+@ Integer variables |lh|, |k|, and |lk_offset| will be defined when we use
+this code.
+
+@<Output the subfile sizes and header bytes@>=
+k=mp->header_last;
+LH=(k+3) / 4; /* this is the number of header words */
+if ( mp->bc>mp->ec ) mp->bc=1; /* if there are no characters, |ec=0| and |bc=1| */
+@<Compute the ligature/kern program offset and implant the
+ left boundary label@>;
+mp_tfm_two(mp,6+LH+(mp->ec-mp->bc+1)+mp->nw+mp->nh+mp->nd+mp->ni+mp->nl
+ +lk_offset+mp->nk+mp->ne+mp->np);
+ /* this is the total number of file words that will be output */
+mp_tfm_two(mp, LH); mp_tfm_two(mp, mp->bc); mp_tfm_two(mp, mp->ec);
+mp_tfm_two(mp, mp->nw); mp_tfm_two(mp, mp->nh);
+mp_tfm_two(mp, mp->nd); mp_tfm_two(mp, mp->ni); mp_tfm_two(mp, mp->nl+lk_offset);
+mp_tfm_two(mp, mp->nk); mp_tfm_two(mp, mp->ne);
+mp_tfm_two(mp, mp->np);
+for (k=0;k< 4*LH;k++) {
+ tfm_out(mp->header_byte[k]);
+}
+
+@ @<Output the character information bytes...@>=
+for (k=mp->bc;k<=mp->ec;k++) {
+ if ( ! mp->char_exists[k] ) {
+ mp_tfm_four(mp, 0);
+ } else {
+ tfm_out(info(mp->tfm_width[k])); /* the width index */
+ tfm_out((info(mp->tfm_height[k]))*16+info(mp->tfm_depth[k]));
+ tfm_out((info(mp->tfm_ital_corr[k]))*4+mp->char_tag[k]);
+ tfm_out(mp->char_remainder[k]);
+ };
+}
+mp->tfm_changed=0;
+for (k=1;k<=4;k++) {
+ mp_tfm_four(mp, 0); p=mp->dimen_head[k];
+ while ( p!=inf_val ) {
+ mp_tfm_four(mp, mp_dimen_out(mp, value(p))); p=link(p);
+ }
+}
+
+
+@ We need to output special instructions at the beginning of the
+|lig_kern| array in order to specify the right boundary character
+and/or to handle starting addresses that exceed 255. The |label_loc|
+and |label_char| arrays have been set up to record all the
+starting addresses; we have $-1=|label_loc|[0]<|label_loc|[1]\le\cdots
+\le|label_loc|[|label_ptr]|$.
+
+@<Compute the ligature/kern program offset...@>=
+mp->bchar=mp_round_unscaled(mp, mp->internal[mp_boundary_char]);
+if ((mp->bchar<0)||(mp->bchar>255))
+ { mp->bchar=-1; mp->lk_started=false; lk_offset=0; }
+else { mp->lk_started=true; lk_offset=1; };
+@<Find the minimum |lk_offset| and adjust all remainders@>;
+if ( mp->bch_label<undefined_label )
+ { skip_byte(mp->nl)=qi(255); next_char(mp->nl)=qi(0);
+ op_byte(mp->nl)=qi(((mp->bch_label+lk_offset)/ 256));
+ rem_byte(mp->nl)=qi(((mp->bch_label+lk_offset)% 256));
+ incr(mp->nl); /* possibly |nl=lig_table_size+1| */
+ }
+
+@ @<Find the minimum |lk_offset|...@>=
+k=mp->label_ptr; /* pointer to the largest unallocated label */
+if ( mp->label_loc[k]+lk_offset>255 ) {
+ lk_offset=0; mp->lk_started=false; /* location 0 can do double duty */
+ do {
+ mp->char_remainder[mp->label_char[k]]=lk_offset;
+ while ( mp->label_loc[k-1]==mp->label_loc[k] ) {
+ decr(k); mp->char_remainder[mp->label_char[k]]=lk_offset;
+ }
+ incr(lk_offset); decr(k);
+ } while (! (lk_offset+mp->label_loc[k]<256));
+ /* N.B.: |lk_offset=256| satisfies this when |k=0| */
+}
+if ( lk_offset>0 ) {
+ while ( k>0 ) {
+ mp->char_remainder[mp->label_char[k]]
+ =mp->char_remainder[mp->label_char[k]]+lk_offset;
+ decr(k);
+ }
+}
+
+@ @<Output the ligature/kern program@>=
+for (k=0;k<= 255;k++ ) {
+ if ( mp->skip_table[k]<undefined_label ) {
+ mp_print_nl(mp, "(local label "); mp_print_int(mp, k); mp_print(mp, ":: was missing)");
+@.local label l:: was missing@>
+ cancel_skips(mp->skip_table[k]);
+ }
+}
+if ( mp->lk_started ) { /* |lk_offset=1| for the special |bchar| */
+ tfm_out(255); tfm_out(mp->bchar); mp_tfm_two(mp, 0);
+} else {
+ for (k=1;k<=lk_offset;k++) {/* output the redirection specs */
+ mp->ll=mp->label_loc[mp->label_ptr];
+ if ( mp->bchar<0 ) { tfm_out(254); tfm_out(0); }
+ else { tfm_out(255); tfm_out(mp->bchar); };
+ mp_tfm_two(mp, mp->ll+lk_offset);
+ do {
+ decr(mp->label_ptr);
+ } while (! (mp->label_loc[mp->label_ptr]<mp->ll));
+ }
+}
+for (k=0;k<=mp->nl-1;k++) mp_tfm_qqqq(mp, mp->lig_kern[k]);
+for (k=0;k<=mp->nk-1;k++) mp_tfm_four(mp, mp_dimen_out(mp, mp->kern[k]))
+
+@ @<Output the extensible character recipes...@>=
+for (k=0;k<=mp->ne-1;k++)
+ mp_tfm_qqqq(mp, mp->exten[k]);
+for (k=1;k<=mp->np;k++) {
+ if ( k==1 ) {
+ if ( abs(mp->param[1])<fraction_half ) {
+ mp_tfm_four(mp, mp->param[1]*16);
+ } else {
+ incr(mp->tfm_changed);
+ if ( mp->param[1]>0 ) mp_tfm_four(mp, el_gordo);
+ else mp_tfm_four(mp, -el_gordo);
+ }
+ } else {
+ mp_tfm_four(mp, mp_dimen_out(mp, mp->param[k]));
+ }
+}
+if ( mp->tfm_changed>0 ) {
+ if ( mp->tfm_changed==1 ) mp_print_nl(mp, "(a font metric dimension");
+@.a font metric dimension...@>
+ else {
+ mp_print_nl(mp, "("); mp_print_int(mp, mp->tfm_changed);
+@.font metric dimensions...@>
+ mp_print(mp, " font metric dimensions");
+ }
+ mp_print(mp, " had to be decreased)");
+}
+
+@ @<Log the subfile sizes of the \.{TFM} file@>=
+{
+ char s[200];
+ wlog_ln(" ");
+ if ( mp->bch_label<undefined_label ) decr(mp->nl);
+ snprintf(s,128,"(You used %iw,%ih,%id,%ii,%il,%ik,%ie,%ip metric file positions)",
+ mp->nw, mp->nh, mp->nd, mp->ni, mp->nl, mp->nk, mp->ne,mp->np);
+ wlog_ln(s);
+}
+
+@* \[43] Reading font metric data.
+
+\MP\ isn't a typesetting program but it does need to find the bounding box
+of a sequence of typeset characters. Thus it needs to read \.{TFM} files as
+well as write them.
+
+@<Glob...@>=
+void * tfm_infile;
+
+@ All the width, height, and depth information is stored in an array called
+|font_info|. This array is allocated sequentially and each font is stored
+as a series of |char_info| words followed by the width, height, and depth
+tables. Since |font_name| entries are permanent, their |str_ref| values are
+set to |max_str_ref|.
+
+@<Types...@>=
+typedef unsigned int font_number; /* |0..font_max| */
+
+@ The |font_info| array is indexed via a group directory arrays.
+For example, the |char_info| data for character~|c| in font~|f| will be
+in |font_info[char_base[f]+c].qqqq|.
+
+@<Glob...@>=
+font_number font_max; /* maximum font number for included text fonts */
+size_t font_mem_size; /* number of words for \.{TFM} information for text fonts */
+memory_word *font_info; /* height, width, and depth data */
+char **font_enc_name; /* encoding names, if any */
+boolean *font_ps_name_fixed; /* are the postscript names fixed already? */
+int next_fmem; /* next unused entry in |font_info| */
+font_number last_fnum; /* last font number used so far */
+scaled *font_dsize; /* 16 times the ``design'' size in \ps\ points */
+char **font_name; /* name as specified in the \&{infont} command */
+char **font_ps_name; /* PostScript name for use when |internal[mp_prologues]>0| */
+font_number last_ps_fnum; /* last valid |font_ps_name| index */
+eight_bits *font_bc;
+eight_bits *font_ec; /* first and last character code */
+int *char_base; /* base address for |char_info| */
+int *width_base; /* index for zeroth character width */
+int *height_base; /* index for zeroth character height */
+int *depth_base; /* index for zeroth character depth */
+pointer *font_sizes;
+
+@ @<Allocate or initialize ...@>=
+mp->font_mem_size = 10000;
+mp->font_info = xmalloc ((mp->font_mem_size+1),sizeof(memory_word));
+memset (mp->font_info,0,sizeof(memory_word)*(mp->font_mem_size+1));
+mp->font_enc_name = NULL;
+mp->font_ps_name_fixed = NULL;
+mp->font_dsize = NULL;
+mp->font_name = NULL;
+mp->font_ps_name = NULL;
+mp->font_bc = NULL;
+mp->font_ec = NULL;
+mp->last_fnum = null_font;
+mp->char_base = NULL;
+mp->width_base = NULL;
+mp->height_base = NULL;
+mp->depth_base = NULL;
+mp->font_sizes = null;
+
+@ @<Dealloc variables@>=
+for (k=1;k<=(int)mp->last_fnum;k++) {
+ xfree(mp->font_enc_name[k]);
+ xfree(mp->font_name[k]);
+ xfree(mp->font_ps_name[k]);
+}
+xfree(mp->font_info);
+xfree(mp->font_enc_name);
+xfree(mp->font_ps_name_fixed);
+xfree(mp->font_dsize);
+xfree(mp->font_name);
+xfree(mp->font_ps_name);
+xfree(mp->font_bc);
+xfree(mp->font_ec);
+xfree(mp->char_base);
+xfree(mp->width_base);
+xfree(mp->height_base);
+xfree(mp->depth_base);
+xfree(mp->font_sizes);
+
+@
+@c
+void mp_reallocate_fonts (MP mp, font_number l) {
+ font_number f;
+ XREALLOC(mp->font_enc_name, l, char *);
+ XREALLOC(mp->font_ps_name_fixed, l, boolean);
+ XREALLOC(mp->font_dsize, l, scaled);
+ XREALLOC(mp->font_name, l, char *);
+ XREALLOC(mp->font_ps_name, l, char *);
+ XREALLOC(mp->font_bc, l, eight_bits);
+ XREALLOC(mp->font_ec, l, eight_bits);
+ XREALLOC(mp->char_base, l, int);
+ XREALLOC(mp->width_base, l, int);
+ XREALLOC(mp->height_base, l, int);
+ XREALLOC(mp->depth_base, l, int);
+ XREALLOC(mp->font_sizes, l, pointer);
+ for (f=(mp->last_fnum+1);f<=l;f++) {
+ mp->font_enc_name[f]=NULL;
+ mp->font_ps_name_fixed[f] = false;
+ mp->font_name[f]=NULL;
+ mp->font_ps_name[f]=NULL;
+ mp->font_sizes[f]=null;
+ }
+ mp->font_max = l;
+}
+
+@ @<Declare |mp_reallocate| functions@>=
+void mp_reallocate_fonts (MP mp, font_number l);
+
+
+@ A |null_font| containing no characters is useful for error recovery. Its
+|font_name| entry starts out empty but is reset each time an erroneous font is
+found. This helps to cut down on the number of duplicate error messages without
+wasting a lot of space.
+
+@d null_font 0 /* the |font_number| for an empty font */
+
+@<Set initial...@>=
+mp->font_dsize[null_font]=0;
+mp->font_bc[null_font]=1;
+mp->font_ec[null_font]=0;
+mp->char_base[null_font]=0;
+mp->width_base[null_font]=0;
+mp->height_base[null_font]=0;
+mp->depth_base[null_font]=0;
+mp->next_fmem=0;
+mp->last_fnum=null_font;
+mp->last_ps_fnum=null_font;
+mp->font_name[null_font]=(char *)"nullfont";
+mp->font_ps_name[null_font]=(char *)"";
+mp->font_ps_name_fixed[null_font] = false;
+mp->font_enc_name[null_font]=NULL;
+mp->font_sizes[null_font]=null;
+
+@ Each |char_info| word is of type |four_quarters|. The |b0| field contains
+the |width index|; the |b1| field contains the height
+index; the |b2| fields contains the depth index, and the |b3| field used only
+for temporary storage. (It is used to keep track of which characters occur in
+an edge structure that is being shipped out.)
+The corresponding words in the width, height, and depth tables are stored as
+|scaled| values in units of \ps\ points.
+
+With the macros below, the |char_info| word for character~|c| in font~|f| is
+|char_info(f)(c)| and the width is
+$$\hbox{|char_width(f)(char_info(f)(c)).sc|.}$$
+
+@d char_info_end(A) (A)].qqqq
+@d char_info(A) mp->font_info[mp->char_base[(A)]+char_info_end
+@d char_width_end(A) (A).b0].sc
+@d char_width(A) mp->font_info[mp->width_base[(A)]+char_width_end
+@d char_height_end(A) (A).b1].sc
+@d char_height(A) mp->font_info[mp->height_base[(A)]+char_height_end
+@d char_depth_end(A) (A).b2].sc
+@d char_depth(A) mp->font_info[mp->depth_base[(A)]+char_depth_end
+@d ichar_exists(A) ((A).b0>0)
+
+@ The |font_ps_name| for a built-in font should be what PostScript expects.
+A preliminary name is obtained here from the \.{TFM} name as given in the
+|fname| argument. This gets updated later from an external table if necessary.
+
+@<Declare text measuring subroutines@>=
+@<Declare subroutines for parsing file names@>
+font_number mp_read_font_info (MP mp, char *fname) {
+ boolean file_opened; /* has |tfm_infile| been opened? */
+ font_number n; /* the number to return */
+ halfword lf,tfm_lh,bc,ec,nw,nh,nd; /* subfile size parameters */
+ size_t whd_size; /* words needed for heights, widths, and depths */
+ int i,ii; /* |font_info| indices */
+ int jj; /* counts bytes to be ignored */
+ scaled z; /* used to compute the design size */
+ fraction d;
+ /* height, width, or depth as a fraction of design size times $2^{-8}$ */
+ eight_bits h_and_d; /* height and depth indices being unpacked */
+ unsigned char tfbyte; /* a byte read from the file */
+ n=null_font;
+ @<Open |tfm_infile| for input@>;
+ @<Read data from |tfm_infile|; if there is no room, say so and |goto done|;
+ otherwise |goto bad_tfm| or |goto done| as appropriate@>;
+BAD_TFM:
+ @<Complain that the \.{TFM} file is bad@>;
+DONE:
+ if ( file_opened ) (mp->close_file)(mp,mp->tfm_infile);
+ if ( n!=null_font ) {
+ mp->font_ps_name[n]=mp_xstrdup(mp,fname);
+ mp->font_name[n]=mp_xstrdup(mp,fname);
+ }
+ return n;
+}
+
+@ \MP\ doesn't bother to check the entire \.{TFM} file for errors or explain
+precisely what is wrong if it does find a problem. Programs called \.{TFtoPL}
+@.TFtoPL@> @.PLtoTF@>
+and \.{PLtoTF} can be used to debug \.{TFM} files.
+
+@<Complain that the \.{TFM} file is bad@>=
+print_err("Font ");
+mp_print(mp, fname);
+if ( file_opened ) mp_print(mp, " not usable: TFM file is bad");
+else mp_print(mp, " not usable: TFM file not found");
+help3("I wasn't able to read the size data for this font so this")
+ ("`infont' operation won't produce anything. If the font name")
+ ("is right, you might ask an expert to make a TFM file");
+if ( file_opened )
+ mp->help_line[0]="is right, try asking an expert to fix the TFM file";
+mp_error(mp)
+
+@ @<Read data from |tfm_infile|; if there is no room, say so...@>=
+@<Read the \.{TFM} size fields@>;
+@<Use the size fields to allocate space in |font_info|@>;
+@<Read the \.{TFM} header@>;
+@<Read the character data and the width, height, and depth tables and
+ |goto done|@>
+
+@ A bad \.{TFM} file can be shorter than it claims to be. The code given here
+might try to read past the end of the file if this happens. Changes will be
+needed if it causes a system error to refer to |tfm_infile^| or call
+|get_tfm_infile| when |eof(tfm_infile)| is true. For example, the definition
+@^system dependencies@>
+of |tfget| could be changed to
+``|begin get(tfm_infile); if eof(tfm_infile) then goto bad_tfm; end|.''
+
+@d tfget do {
+ size_t wanted=1;
+ void *tfbyte_ptr = &tfbyte;
+ (mp->read_binary_file)(mp,mp->tfm_infile,&tfbyte_ptr,&wanted);
+ if (wanted==0) goto BAD_TFM;
+} while (0)
+@d read_two(A) { (A)=tfbyte;
+ if ( (A)>127 ) goto BAD_TFM;
+ tfget; (A)=(A)*0400+tfbyte;
+}
+@d tf_ignore(A) { for (jj=(A);jj>=1;jj--) tfget; }
+
+@<Read the \.{TFM} size fields@>=
+tfget; read_two(lf);
+tfget; read_two(tfm_lh);
+tfget; read_two(bc);
+tfget; read_two(ec);
+if ( (bc>1+ec)||(ec>255) ) goto BAD_TFM;
+tfget; read_two(nw);
+tfget; read_two(nh);
+tfget; read_two(nd);
+whd_size=(ec+1-bc)+nw+nh+nd;
+if ( lf<(int)(6+tfm_lh+whd_size) ) goto BAD_TFM;
+tf_ignore(10)
+
+@ Offsets are added to |char_base[n]| and |width_base[n]| so that is not
+necessary to apply the |so| and |qo| macros when looking up the width of a
+character in the string pool. In order to ensure nonnegative |char_base|
+values when |bc>0|, it may be necessary to reserve a few unused |font_info|
+elements.
+
+@<Use the size fields to allocate space in |font_info|@>=
+if ( mp->next_fmem<bc) mp->next_fmem=bc; /* ensure nonnegative |char_base| */
+if (mp->last_fnum==mp->font_max)
+ mp_reallocate_fonts(mp,(mp->font_max+(mp->font_max>>2)));
+while (mp->next_fmem+whd_size>=mp->font_mem_size) {
+ size_t l = mp->font_mem_size+(mp->font_mem_size>>2);
+ memory_word *font_info;
+ font_info = xmalloc ((l+1),sizeof(memory_word));
+ memset (font_info,0,sizeof(memory_word)*(l+1));
+ memcpy (font_info,mp->font_info,sizeof(memory_word)*(mp->font_mem_size+1));
+ xfree(mp->font_info);
+ mp->font_info = font_info;
+ mp->font_mem_size = l;
+}
+incr(mp->last_fnum);
+n=mp->last_fnum;
+mp->font_bc[n]=bc;
+mp->font_ec[n]=ec;
+mp->char_base[n]=mp->next_fmem-bc;
+mp->width_base[n]=mp->next_fmem+ec-bc+1;
+mp->height_base[n]=mp->width_base[n]+nw;
+mp->depth_base[n]=mp->height_base[n]+nh;
+mp->next_fmem=mp->next_fmem+whd_size;
+
+
+@ @<Read the \.{TFM} header@>=
+if ( tfm_lh<2 ) goto BAD_TFM;
+tf_ignore(4);
+tfget; read_two(z);
+tfget; z=z*0400+tfbyte;
+tfget; z=z*0400+tfbyte; /* now |z| is 16 times the design size */
+mp->font_dsize[n]=mp_take_fraction(mp, z,267432584);
+ /* times ${72\over72.27}2^{28}$ to convert from \TeX\ points */
+tf_ignore(4*(tfm_lh-2))
+
+@ @<Read the character data and the width, height, and depth tables...@>=
+ii=mp->width_base[n];
+i=mp->char_base[n]+bc;
+while ( i<ii ) {
+ tfget; mp->font_info[i].qqqq.b0=qi(tfbyte);
+ tfget; h_and_d=tfbyte;
+ mp->font_info[i].qqqq.b1=h_and_d / 16;
+ mp->font_info[i].qqqq.b2=h_and_d % 16;
+ tfget; tfget;
+ incr(i);
+}
+while ( i<mp->next_fmem ) {
+ @<Read a four byte dimension, scale it by the design size, store it in
+ |font_info[i]|, and increment |i|@>;
+}
+goto DONE
+
+@ The raw dimension read into |d| should have magnitude at most $2^{24}$ when
+interpreted as an integer, and this includes a scale factor of $2^{20}$. Thus
+we can multiply it by sixteen and think of it as a |fraction| that has been
+divided by sixteen. This cancels the extra scale factor contained in
+|font_dsize[n|.
+
+@<Read a four byte dimension, scale it by the design size, store it in...@>=
+{
+tfget; d=tfbyte;
+if ( d>=0200 ) d=d-0400;
+tfget; d=d*0400+tfbyte;
+tfget; d=d*0400+tfbyte;
+tfget; d=d*0400+tfbyte;
+mp->font_info[i].sc=mp_take_fraction(mp, d*16,mp->font_dsize[n]);
+incr(i);
+}
+
+@ This function does no longer use the file name parser, because |fname| is
+a C string already.
+@<Open |tfm_infile| for input@>=
+file_opened=false;
+mp_ptr_scan_file(mp, fname);
+if ( strlen(mp->cur_area)==0 ) { xfree(mp->cur_area); }
+if ( strlen(mp->cur_ext)==0 ) { xfree(mp->cur_ext); mp->cur_ext=xstrdup(".tfm"); }
+pack_cur_name;
+mp->tfm_infile = (mp->open_file)(mp, mp->name_of_file, "r",mp_filetype_metrics);
+if ( !mp->tfm_infile ) goto BAD_TFM;
+file_opened=true
+
+@ When we have a font name and we don't know whether it has been loaded yet,
+we scan the |font_name| array before calling |read_font_info|.
+
+@<Declare text measuring subroutines@>=
+font_number mp_find_font (MP mp, char *f) {
+ font_number n;
+ for (n=0;n<=mp->last_fnum;n++) {
+ if (mp_xstrcmp(f,mp->font_name[n])==0 ) {
+ mp_xfree(f);
+ return n;
+ }
+ }
+ n = mp_read_font_info(mp, f);
+ mp_xfree(f);
+ return n;
+}
+
+@ One simple application of |find_font| is the implementation of the |font_size|
+operator that gets the design size for a given font name.
+
+@<Find the design size of the font whose name is |cur_exp|@>=
+mp_flush_cur_exp(mp, (mp->font_dsize[mp_find_font(mp, str(mp->cur_exp))]+8) / 16)
+
+@ If we discover that the font doesn't have a requested character, we omit it
+from the bounding box computation and expect the \ps\ interpreter to drop it.
+This routine issues a warning message if the user has asked for it.
+
+@<Declare text measuring subroutines@>=
+void mp_lost_warning (MP mp,font_number f, pool_pointer k) {
+ if ( mp->internal[mp_tracing_lost_chars]>0 ) {
+ mp_begin_diagnostic(mp);
+ if ( mp->selector==log_only ) incr(mp->selector);
+ mp_print_nl(mp, "Missing character: There is no ");
+@.Missing character@>
+ mp_print_str(mp, mp->str_pool[k]);
+ mp_print(mp, " in font ");
+ mp_print(mp, mp->font_name[f]); mp_print_char(mp, '!');
+ mp_end_diagnostic(mp, false);
+ }
+}
+
+@ The whole purpose of saving the height, width, and depth information is to be
+able to find the bounding box of an item of text in an edge structure. The
+|set_text_box| procedure takes a text node and adds this information.
+
+@<Declare text measuring subroutines@>=
+void mp_set_text_box (MP mp,pointer p) {
+ font_number f; /* |font_n(p)| */
+ ASCII_code bc,ec; /* range of valid characters for font |f| */
+ pool_pointer k,kk; /* current character and character to stop at */
+ four_quarters cc; /* the |char_info| for the current character */
+ scaled h,d; /* dimensions of the current character */
+ width_val(p)=0;
+ height_val(p)=-el_gordo;
+ depth_val(p)=-el_gordo;
+ f=font_n(p);
+ bc=mp->font_bc[f];
+ ec=mp->font_ec[f];
+ kk=str_stop(text_p(p));
+ k=mp->str_start[text_p(p)];
+ while ( k<kk ) {
+ @<Adjust |p|'s bounding box to contain |str_pool[k]|; advance |k|@>;
+ }
+ @<Set the height and depth to zero if the bounding box is empty@>;
+}
+
+@ @<Adjust |p|'s bounding box to contain |str_pool[k]|; advance |k|@>=
+{
+ if ( (mp->str_pool[k]<bc)||(mp->str_pool[k]>ec) ) {
+ mp_lost_warning(mp, f,k);
+ } else {
+ cc=char_info(f)(mp->str_pool[k]);
+ if ( ! ichar_exists(cc) ) {
+ mp_lost_warning(mp, f,k);
+ } else {
+ width_val(p)=width_val(p)+char_width(f)(cc);
+ h=char_height(f)(cc);
+ d=char_depth(f)(cc);
+ if ( h>height_val(p) ) height_val(p)=h;
+ if ( d>depth_val(p) ) depth_val(p)=d;
+ }
+ }
+ incr(k);
+}
+
+@ Let's hope modern compilers do comparisons correctly when the difference would
+overflow.
+
+@<Set the height and depth to zero if the bounding box is empty@>=
+if ( height_val(p)<-depth_val(p) ) {
+ height_val(p)=0;
+ depth_val(p)=0;
+}
+
+@ The new primitives fontmapfile and fontmapline.
+
+@<Declare action procedures for use by |do_statement|@>=
+void mp_do_mapfile (MP mp) ;
+void mp_do_mapline (MP mp) ;
+
+@ @c void mp_do_mapfile (MP mp) {
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type!=mp_string_type ) {
+ @<Complain about improper map operation@>;
+ } else {
+ mp_map_file(mp,mp->cur_exp);
+ }
+}
+void mp_do_mapline (MP mp) {
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type!=mp_string_type ) {
+ @<Complain about improper map operation@>;
+ } else {
+ mp_map_line(mp,mp->cur_exp);
+ }
+}
+
+@ @<Complain about improper map operation@>=
+{
+ exp_err("Unsuitable expression");
+ help1("Only known strings can be map files or map lines.");
+ mp_put_get_error(mp);
+}
+
+@ To print |scaled| value to PDF output we need some subroutines to ensure
+accurary.
+
+@d max_integer 0x7FFFFFFF /* $2^{31}-1$ */
+
+@<Glob...@>=
+scaled one_bp; /* scaled value corresponds to 1bp */
+scaled one_hundred_bp; /* scaled value corresponds to 100bp */
+scaled one_hundred_inch; /* scaled value corresponds to 100in */
+integer ten_pow[10]; /* $10^0..10^9$ */
+integer scaled_out; /* amount of |scaled| that was taken out in |divide_scaled| */
+
+@ @<Set init...@>=
+mp->one_bp = 65782; /* 65781.76 */
+mp->one_hundred_bp = 6578176;
+mp->one_hundred_inch = 473628672;
+mp->ten_pow[0] = 1;
+for (i = 1;i<= 9; i++ ) {
+ mp->ten_pow[i] = 10*mp->ten_pow[i - 1];
+}
+
+@ The following function divides |s| by |m|. |dd| is number of decimal digits.
+
+@c scaled mp_divide_scaled (MP mp,scaled s, scaled m, integer dd) {
+ scaled q,r;
+ integer sign,i;
+ sign = 1;
+ if ( s < 0 ) { sign = -sign; s = -s; }
+ if ( m < 0 ) { sign = -sign; m = -m; }
+ if ( m == 0 )
+ mp_confusion(mp, "arithmetic: divided by zero");
+ else if ( m >= (max_integer / 10) )
+ mp_confusion(mp, "arithmetic: number too big");
+ q = s / m;
+ r = s % m;
+ for (i = 1;i<=dd;i++) {
+ q = 10*q + (10*r) / m;
+ r = (10*r) % m;
+ }
+ if ( 2*r >= m ) { incr(q); r = r - m; }
+ mp->scaled_out = sign*(s - (r / mp->ten_pow[dd]));
+ return (sign*q);
+}
+
+@* \[44] Shipping pictures out.
+The |ship_out| procedure, to be described below, is given a pointer to
+an edge structure. Its mission is to output a file containing the \ps\
+description of an edge structure.
+
+@ Each time an edge structure is shipped out we write a new \ps\ output
+file named according to the current \&{charcode}.
+@:char_code_}{\&{charcode} primitive@>
+
+This is the only backend function that remains in the main |mpost.w| file.
+There are just too many variable accesses needed for status reporting
+etcetera to make it worthwile to move the code to |psout.w|.
+
+@<Internal library declarations@>=
+void mp_open_output_file (MP mp) ;
+
+@ @c
+char *mp_set_output_file_name (MP mp, integer c) {
+ char *ss = NULL; /* filename extension proposal */
+ int old_setting; /* previous |selector| setting */
+ pool_pointer i; /* indexes into |filename_template| */
+ integer cc; /* a temporary integer for template building */
+ integer f,g=0; /* field widths */
+ if ( mp->job_name==NULL ) mp_open_log_file(mp);
+ if ( mp->filename_template==0 ) {
+ char *s; /* a file extension derived from |c| */
+ if ( c<0 )
+ s=xstrdup(".ps");
+ else
+ @<Use |c| to compute the file extension |s|@>;
+ mp_pack_job_name(mp, s);
+ ss = s ;
+ } else { /* initializations */
+ str_number s, n; /* a file extension derived from |c| */
+ old_setting=mp->selector;
+ mp->selector=new_string;
+ f = 0;
+ i = mp->str_start[mp->filename_template];
+ n = rts(""); /* initialize */
+ while ( i<str_stop(mp->filename_template) ) {
+ if ( mp->str_pool[i]=='%' ) {
+ CONTINUE:
+ incr(i);
+ if ( i<str_stop(mp->filename_template) ) {
+ if ( mp->str_pool[i]=='j' ) {
+ mp_print(mp, mp->job_name);
+ } else if ( mp->str_pool[i]=='d' ) {
+ cc= mp_round_unscaled(mp, mp->internal[mp_day]);
+ print_with_leading_zeroes(cc);
+ } else if ( mp->str_pool[i]=='m' ) {
+ cc= mp_round_unscaled(mp, mp->internal[mp_month]);
+ print_with_leading_zeroes(cc);
+ } else if ( mp->str_pool[i]=='y' ) {
+ cc= mp_round_unscaled(mp, mp->internal[mp_year]);
+ print_with_leading_zeroes(cc);
+ } else if ( mp->str_pool[i]=='H' ) {
+ cc= mp_round_unscaled(mp, mp->internal[mp_time]) / 60;
+ print_with_leading_zeroes(cc);
+ } else if ( mp->str_pool[i]=='M' ) {
+ cc= mp_round_unscaled(mp, mp->internal[mp_time]) % 60;
+ print_with_leading_zeroes(cc);
+ } else if ( mp->str_pool[i]=='c' ) {
+ if ( c<0 ) mp_print(mp, "ps");
+ else print_with_leading_zeroes(c);
+ } else if ( (mp->str_pool[i]>='0') &&
+ (mp->str_pool[i]<='9') ) {
+ if ( (f<10) )
+ f = (f*10) + mp->str_pool[i]-'0';
+ goto CONTINUE;
+ } else {
+ mp_print_str(mp, mp->str_pool[i]);
+ }
+ }
+ } else {
+ if ( mp->str_pool[i]=='.' )
+ if (length(n)==0)
+ n = mp_make_string(mp);
+ mp_print_str(mp, mp->str_pool[i]);
+ };
+ incr(i);
+ };
+ s = mp_make_string(mp);
+ mp->selector= old_setting;
+ if (length(n)==0) {
+ n=s;
+ s=rts("");
+ };
+ mp_pack_file_name(mp, str(n),"",str(s));
+ delete_str_ref(n);
+ ss = str(s);
+ delete_str_ref(s);
+ }
+ return ss;
+}
+
+char * mp_get_output_file_name (MP mp) {
+ char *fname; /* return value */
+ char *saved_name; /* saved |name_of_file| */
+ saved_name = mp_xstrdup(mp, mp->name_of_file);
+ (void)mp_set_output_file_name(mp, mp_round_unscaled(mp, mp->internal[mp_char_code]));
+ fname = mp_xstrdup(mp, mp->name_of_file);
+ mp_pack_file_name(mp, saved_name,NULL,NULL);
+ return fname;
+}
+
+void mp_open_output_file (MP mp) {
+ char *ss; /* filename extension proposal */
+ integer c; /* \&{charcode} rounded to the nearest integer */
+ c=mp_round_unscaled(mp, mp->internal[mp_char_code]);
+ ss = mp_set_output_file_name(mp, c);
+ while ( ! mp_a_open_out(mp, (void *)&mp->ps_file, mp_filetype_postscript) )
+ mp_prompt_file_name(mp, "file name for output",ss);
+ xfree(ss);
+ @<Store the true output file name if appropriate@>;
+}
+
+@ The file extension created here could be up to five characters long in
+extreme cases so it may have to be shortened on some systems.
+@^system dependencies@>
+
+@<Use |c| to compute the file extension |s|@>=
+{
+ s = xmalloc(7,1);
+ snprintf(s,7,".%i",(int)c);
+}
+
+@ The user won't want to see all the output file names so we only save the
+first and last ones and a count of how many there were. For this purpose
+files are ordered primarily by \&{charcode} and secondarily by order of
+creation.
+@:char_code_}{\&{charcode} primitive@>
+
+@<Store the true output file name if appropriate@>=
+if ((c<mp->first_output_code)&&(mp->first_output_code>=0)) {
+ mp->first_output_code=c;
+ xfree(mp->first_file_name);
+ mp->first_file_name=xstrdup(mp->name_of_file);
+}
+if ( c>=mp->last_output_code ) {
+ mp->last_output_code=c;
+ xfree(mp->last_file_name);
+ mp->last_file_name=xstrdup(mp->name_of_file);
+}
+
+@ @<Glob...@>=
+char * first_file_name;
+char * last_file_name; /* full file names */
+integer first_output_code;integer last_output_code; /* rounded \&{charcode} values */
+@:char_code_}{\&{charcode} primitive@>
+integer total_shipped; /* total number of |ship_out| operations completed */
+
+@ @<Set init...@>=
+mp->first_file_name=xstrdup("");
+mp->last_file_name=xstrdup("");
+mp->first_output_code=32768;
+mp->last_output_code=-32768;
+mp->total_shipped=0;
+
+@ @<Dealloc variables@>=
+xfree(mp->first_file_name);
+xfree(mp->last_file_name);
+
+@ @<Begin the progress report for the output of picture~|c|@>=
+if ( (int)mp->term_offset>mp->max_print_line-6 ) mp_print_ln(mp);
+else if ( (mp->term_offset>0)||(mp->file_offset>0) ) mp_print_char(mp, ' ');
+mp_print_char(mp, '[');
+if ( c>=0 ) mp_print_int(mp, c)
+
+@ @<End progress report@>=
+mp_print_char(mp, ']');
+update_terminal;
+incr(mp->total_shipped)
+
+@ @<Explain what output files were written@>=
+if ( mp->total_shipped>0 ) {
+ mp_print_nl(mp, "");
+ mp_print_int(mp, mp->total_shipped);
+ mp_print(mp, " output file");
+ if ( mp->total_shipped>1 ) mp_print_char(mp, 's');
+ mp_print(mp, " written: ");
+ mp_print(mp, mp->first_file_name);
+ if ( mp->total_shipped>1 ) {
+ if ( 31+strlen(mp->first_file_name)+
+ strlen(mp->last_file_name)> (unsigned)mp->max_print_line)
+ mp_print_ln(mp);
+ mp_print(mp, " .. ");
+ mp_print(mp, mp->last_file_name);
+ }
+}
+
+@ @<Internal library declarations@>=
+boolean mp_has_font_size(MP mp, font_number f );
+
+@ @c
+boolean mp_has_font_size(MP mp, font_number f ) {
+ return (mp->font_sizes[f]!=null);
+}
+
+@ The \&{special} command saves up lines of text to be printed during the next
+|ship_out| operation. The saved items are stored as a list of capsule tokens.
+
+@<Glob...@>=
+pointer last_pending; /* the last token in a list of pending specials */
+
+@ @<Set init...@>=
+mp->last_pending=spec_head;
+
+@ @<Cases of |do_statement|...@>=
+case special_command:
+ if ( mp->cur_mod==0 ) mp_do_special(mp); else
+ if ( mp->cur_mod==1 ) mp_do_mapfile(mp); else
+ mp_do_mapline(mp);
+ break;
+
+@ @<Declare action procedures for use by |do_statement|@>=
+void mp_do_special (MP mp) ;
+
+@ @c void mp_do_special (MP mp) {
+ mp_get_x_next(mp); mp_scan_expression(mp);
+ if ( mp->cur_type!=mp_string_type ) {
+ @<Complain about improper special operation@>;
+ } else {
+ link(mp->last_pending)=mp_stash_cur_exp(mp);
+ mp->last_pending=link(mp->last_pending);
+ link(mp->last_pending)=null;
+ }
+}
+
+@ @<Complain about improper special operation@>=
+{
+ exp_err("Unsuitable expression");
+ help1("Only known strings are allowed for output as specials.");
+ mp_put_get_error(mp);
+}
+
+@ On the export side, we need an extra object type for special strings.
+
+@<Graphical object codes@>=
+mp_special_code=8,
+
+@ @<Export pending specials@>=
+p=link(spec_head);
+while ( p!=null ) {
+ mp_special_object *tp;
+ tp = (mp_special_object *)mp_new_graphic_object(mp,mp_special_code);
+ gr_pre_script(tp) = str(value(p));
+ if (hh->body==NULL) hh->body = (mp_graphic_object *)tp;
+ else gr_link(hp) = (mp_graphic_object *)tp;
+ hp = (mp_graphic_object *)tp;
+ p=link(p);
+}
+mp_flush_token_list(mp, link(spec_head));
+link(spec_head)=null;
+mp->last_pending=spec_head
+
+@ We are now ready for the main output procedure. Note that the |selector|
+setting is saved in a global variable so that |begin_diagnostic| can access it.
+
+@<Declare the \ps\ output procedures@>=
+void mp_ship_out (MP mp, pointer h) ;
+
+@ Once again, the |gr_XXXX| macros are defined in |mppsout.h|
+
+@d export_color(q,p)
+ if ( color_model(p)==mp_uninitialized_model ) {
+ gr_color_model(q) = (mp->internal[mp_default_color_model]>>16);
+ gr_cyan_val(q) = 0;
+ gr_magenta_val(q) = 0;
+ gr_yellow_val(q) = 0;
+ gr_black_val(q) = (gr_color_model(q)==mp_cmyk_model ? unity : 0);
+ } else {
+ gr_color_model(q) = color_model(p);
+ gr_cyan_val(q) = cyan_val(p);
+ gr_magenta_val(q) = magenta_val(p);
+ gr_yellow_val(q) = yellow_val(p);
+ gr_black_val(q) = black_val(p);
+ }
+
+@d export_scripts(q,p)
+ if (pre_script(p)!=null) gr_pre_script(q) = str(pre_script(p));
+ if (post_script(p)!=null) gr_post_script(q) = str(post_script(p));
+
+@c
+struct mp_edge_object *mp_gr_export(MP mp, pointer h) {
+ pointer p; /* the current graphical object */
+ integer t; /* a temporary value */
+ mp_edge_object *hh; /* the first graphical object */
+ struct mp_graphic_object *hq; /* something |hp| points to */
+ struct mp_text_object *tt;
+ struct mp_fill_object *tf;
+ struct mp_stroked_object *ts;
+ struct mp_clip_object *tc;
+ struct mp_bounds_object *tb;
+ struct mp_graphic_object *hp = NULL; /* the current graphical object */
+ mp_set_bbox(mp, h, true);
+ hh = mp_xmalloc(mp,1,sizeof(mp_edge_object));
+ hh->body = NULL;
+ hh->_next = NULL;
+ hh->_parent = mp;
+ hh->_minx = minx_val(h);
+ hh->_miny = miny_val(h);
+ hh->_maxx = maxx_val(h);
+ hh->_maxy = maxy_val(h);
+ hh->_filename = mp_get_output_file_name(mp);
+ @<Export pending specials@>;
+ p=link(dummy_loc(h));
+ while ( p!=null ) {
+ hq = mp_new_graphic_object(mp,type(p));
+ switch (type(p)) {
+ case mp_fill_code:
+ tf = (mp_fill_object *)hq;
+ gr_pen_p(tf) = mp_export_knot_list(mp,pen_p(p));
+ if ((pen_p(p)==null) || pen_is_elliptical(pen_p(p))) {
+ gr_path_p(tf) = mp_export_knot_list(mp,path_p(p));
+ } else {
+ pointer pc, pp;
+ pc = mp_copy_path(mp, path_p(p));
+ pp = mp_make_envelope(mp, pc, pen_p(p),ljoin_val(p),0,miterlim_val(p));
+ gr_path_p(tf) = mp_export_knot_list(mp,pp);
+ mp_toss_knot_list(mp, pp);
+ pc = mp_htap_ypoc(mp, path_p(p));
+ pp = mp_make_envelope(mp, pc, pen_p(p),ljoin_val(p),0,miterlim_val(p));
+ gr_htap_p(tf) = mp_export_knot_list(mp,pp);
+ mp_toss_knot_list(mp, pp);
+ }
+ export_color(tf,p) ;
+ export_scripts(tf,p);
+ gr_ljoin_val(tf) = ljoin_val(p);
+ gr_miterlim_val(tf) = miterlim_val(p);
+ break;
+ case mp_stroked_code:
+ ts = (mp_stroked_object *)hq;
+ gr_pen_p(ts) = mp_export_knot_list(mp,pen_p(p));
+ if (pen_is_elliptical(pen_p(p))) {
+ gr_path_p(ts) = mp_export_knot_list(mp,path_p(p));
+ } else {
+ pointer pc;
+ pc=mp_copy_path(mp, path_p(p));
+ t=lcap_val(p);
+ if ( left_type(pc)!=mp_endpoint ) {
+ left_type(mp_insert_knot(mp, pc,x_coord(pc),y_coord(pc)))=mp_endpoint;
+ right_type(pc)=mp_endpoint;
+ pc=link(pc);
+ t=1;
+ }
+ pc=mp_make_envelope(mp,pc,pen_p(p),ljoin_val(p),t,miterlim_val(p));
+ gr_path_p(ts) = mp_export_knot_list(mp,pc);
+ mp_toss_knot_list(mp, pc);
+ }
+ export_color(ts,p) ;
+ export_scripts(ts,p);
+ gr_ljoin_val(ts) = ljoin_val(p);
+ gr_miterlim_val(ts) = miterlim_val(p);
+ gr_lcap_val(ts) = lcap_val(p);
+ gr_dash_p(ts) = mp_export_dashes(mp,dash_p(p));
+ break;
+ case mp_text_code:
+ tt = (mp_text_object *)hq;
+ gr_text_p(tt) = str(text_p(p));
+ gr_font_n(tt) = font_n(p);
+ gr_font_name(tt) = mp_xstrdup(mp,mp->font_name[font_n(p)]);
+ gr_font_dsize(tt) = mp->font_dsize[font_n(p)];
+ export_color(tt,p) ;
+ export_scripts(tt,p);
+ gr_width_val(tt) = width_val(p);
+ gr_height_val(tt) = height_val(p);
+ gr_depth_val(tt) = depth_val(p);
+ gr_tx_val(tt) = tx_val(p);
+ gr_ty_val(tt) = ty_val(p);
+ gr_txx_val(tt) = txx_val(p);
+ gr_txy_val(tt) = txy_val(p);
+ gr_tyx_val(tt) = tyx_val(p);
+ gr_tyy_val(tt) = tyy_val(p);
+ break;
+ case mp_start_clip_code:
+ tc = (mp_clip_object *)hq;
+ gr_path_p(tc) = mp_export_knot_list(mp,path_p(p));
+ break;
+ case mp_start_bounds_code:
+ tb = (mp_bounds_object *)hq;
+ gr_path_p(tb) = mp_export_knot_list(mp,path_p(p));
+ break;
+ case mp_stop_clip_code:
+ case mp_stop_bounds_code:
+ /* nothing to do here */
+ break;
+ }
+ if (hh->body==NULL) hh->body=hq; else gr_link(hp) = hq;
+ hp = hq;
+ p=link(p);
+ }
+ return hh;
+}
+
+@ @<Exported function ...@>=
+struct mp_edge_object *mp_gr_export(MP mp, int h);
+
+@ This function is now nearly trivial.
+
+@c
+void mp_ship_out (MP mp, pointer h) { /* output edge structure |h| */
+ integer c; /* \&{charcode} rounded to the nearest integer */
+ c=mp_round_unscaled(mp, mp->internal[mp_char_code]);
+ @<Begin the progress report for the output of picture~|c|@>;
+ (mp->shipout_backend) (mp, h);
+ @<End progress report@>;
+ if ( mp->internal[mp_tracing_output]>0 )
+ mp_print_edges(mp, h," (just shipped out)",true);
+}
+
+@ @<Declarations@>=
+void mp_shipout_backend (MP mp, pointer h);
+
+@ @c
+void mp_shipout_backend (MP mp, pointer h) {
+ mp_edge_object *hh; /* the first graphical object */
+ hh = mp_gr_export(mp,h);
+ mp_gr_ship_out (hh,
+ (mp->internal[mp_prologues]>>16),
+ (mp->internal[mp_procset]>>16));
+ mp_gr_toss_objects(hh);
+}
+
+@ @<Exported types@>=
+typedef void (*mp_backend_writer)(MP, int);
+
+@ @<Option variables@>=
+mp_backend_writer shipout_backend;
+
+@ @<Allocate or initialize ...@>=
+set_callback_option(shipout_backend);
+
+@ Now that we've finished |ship_out|, let's look at the other commands
+by which a user can send things to the \.{GF} file.
+
+@ @<Determine if a character has been shipped out@>=
+{
+ mp->cur_exp=mp_round_unscaled(mp, mp->cur_exp) % 256;
+ if ( mp->cur_exp<0 ) mp->cur_exp=mp->cur_exp+256;
+ boolean_reset(mp->char_exists[mp->cur_exp]);
+ mp->cur_type=mp_boolean_type;
+}
+
+@ @<Glob...@>=
+psout_data ps;
+
+@ @<Allocate or initialize ...@>=
+mp_backend_initialize(mp);
+
+@ @<Dealloc...@>=
+mp_backend_free(mp);
+
+
+@* \[45] Dumping and undumping the tables.
+After \.{INIMP} has seen a collection of macros, it
+can write all the necessary information on an auxiliary file so
+that production versions of \MP\ are able to initialize their
+memory at high speed. The present section of the program takes
+care of such output and input. We shall consider simultaneously
+the processes of storing and restoring,
+so that the inverse relation between them is clear.
+@.INIMP@>
+
+The global variable |mem_ident| is a string that is printed right
+after the |banner| line when \MP\ is ready to start. For \.{INIMP} this
+string says simply `\.{(INIMP)}'; for other versions of \MP\ it says,
+for example, `\.{(mem=plain 1990.4.14)}', showing the year,
+month, and day that the mem file was created. We have |mem_ident=0|
+before \MP's tables are loaded.
+
+@<Glob...@>=
+char * mem_ident;
+
+@ @<Set init...@>=
+mp->mem_ident=NULL;
+
+@ @<Initialize table entries...@>=
+mp->mem_ident=xstrdup(" (INIMP)");
+
+@ @<Declare act...@>=
+void mp_store_mem_file (MP mp) ;
+
+@ @c void mp_store_mem_file (MP mp) {
+ integer k; /* all-purpose index */
+ pointer p,q; /* all-purpose pointers */
+ integer x; /* something to dump */
+ four_quarters w; /* four ASCII codes */
+ memory_word WW;
+ @<Create the |mem_ident|, open the mem file,
+ and inform the user that dumping has begun@>;
+ @<Dump constants for consistency check@>;
+ @<Dump the string pool@>;
+ @<Dump the dynamic memory@>;
+ @<Dump the table of equivalents and the hash table@>;
+ @<Dump a few more things and the closing check word@>;
+ @<Close the mem file@>;
+}
+
+@ Corresponding to the procedure that dumps a mem file, we also have a function
+that reads~one~in. The function returns |false| if the dumped mem is
+incompatible with the present \MP\ table sizes, etc.
+
+@d off_base 6666 /* go here if the mem file is unacceptable */
+@d too_small(A) { wake_up_terminal;
+ wterm_ln("---! Must increase the "); wterm((A));
+@.Must increase the x@>
+ goto OFF_BASE;
+ }
+
+@c
+boolean mp_load_mem_file (MP mp) {
+ integer k; /* all-purpose index */
+ pointer p,q; /* all-purpose pointers */
+ integer x; /* something undumped */
+ str_number s; /* some temporary string */
+ four_quarters w; /* four ASCII codes */
+ memory_word WW;
+ @<Undump constants for consistency check@>;
+ @<Undump the string pool@>;
+ @<Undump the dynamic memory@>;
+ @<Undump the table of equivalents and the hash table@>;
+ @<Undump a few more things and the closing check word@>;
+ return true; /* it worked! */
+OFF_BASE:
+ wake_up_terminal;
+ wterm_ln("(Fatal mem file error; I'm stymied)\n");
+@.Fatal mem file error@>
+ return false;
+}
+
+@ @<Declarations@>=
+boolean mp_load_mem_file (MP mp) ;
+
+@ Mem files consist of |memory_word| items, and we use the following
+macros to dump words of different types:
+
+@d dump_wd(A) { WW=(A); (mp->write_binary_file)(mp,mp->mem_file,&WW,sizeof(WW)); }
+@d dump_int(A) { int cint=(A); (mp->write_binary_file)(mp,mp->mem_file,&cint,sizeof(cint)); }
+@d dump_hh(A) { WW.hh=(A); (mp->write_binary_file)(mp,mp->mem_file,&WW,sizeof(WW)); }
+@d dump_qqqq(A) { WW.qqqq=(A); (mp->write_binary_file)(mp,mp->mem_file,&WW,sizeof(WW)); }
+@d dump_string(A) { dump_int(strlen(A)+1);
+ (mp->write_binary_file)(mp,mp->mem_file,A,strlen(A)+1); }
+
+@<Glob...@>=
+void * mem_file; /* for input or output of mem information */
+
+@ The inverse macros are slightly more complicated, since we need to check
+the range of the values we are reading in. We say `|undump(a)(b)(x)|' to
+read an integer value |x| that is supposed to be in the range |a<=x<=b|.
+
+@d mgeti(A) do {
+ size_t wanted = sizeof(A);
+ void *A_ptr = &A;
+ (mp->read_binary_file)(mp, mp->mem_file,&A_ptr,&wanted);
+ if (wanted!=sizeof(A)) goto OFF_BASE;
+} while (0)
+
+@d mgetw(A) do {
+ size_t wanted = sizeof(A);
+ void *A_ptr = &A;
+ (mp->read_binary_file)(mp, mp->mem_file,&A_ptr,&wanted);
+ if (wanted!=sizeof(A)) goto OFF_BASE;
+} while (0)
+
+@d undump_wd(A) { mgetw(WW); A=WW; }
+@d undump_int(A) { int cint; mgeti(cint); A=cint; }
+@d undump_hh(A) { mgetw(WW); A=WW.hh; }
+@d undump_qqqq(A) { mgetw(WW); A=WW.qqqq; }
+@d undump_strings(A,B,C) {
+ undump_int(x); if ( (x<(A)) || (x>(B)) ) goto OFF_BASE; else C=str(x); }
+@d undump(A,B,C) { undump_int(x); if ( (x<(A)) || (x>(int)(B)) ) goto OFF_BASE; else C=x; }
+@d undump_size(A,B,C,D) { undump_int(x);
+ if (x<(A)) goto OFF_BASE;
+ if (x>(B)) { too_small((C)); } else { D=x;} }
+@d undump_string(A) do {
+ size_t the_wanted;
+ void *the_string;
+ integer XX=0;
+ undump_int(XX);
+ the_wanted = XX;
+ the_string = xmalloc(XX,sizeof(char));
+ (mp->read_binary_file)(mp,mp->mem_file,&the_string,&the_wanted);
+ A = (char *)the_string;
+ if (the_wanted!=(size_t)XX) goto OFF_BASE;
+} while (0)
+
+@ The next few sections of the program should make it clear how we use the
+dump/undump macros.
+
+@<Dump constants for consistency check@>=
+dump_int(mp->mem_top);
+dump_int(mp->hash_size);
+dump_int(mp->hash_prime)
+dump_int(mp->param_size);
+dump_int(mp->max_in_open);
+
+@ Sections of a \.{WEB} program that are ``commented out'' still contribute
+strings to the string pool; therefore \.{INIMP} and \MP\ will have
+the same strings. (And it is, of course, a good thing that they do.)
+@.WEB@>
+@^string pool@>
+
+@<Undump constants for consistency check@>=
+undump_int(x); mp->mem_top = x;
+undump_int(x); if (mp->hash_size != x) goto OFF_BASE;
+undump_int(x); if (mp->hash_prime != x) goto OFF_BASE;
+undump_int(x); if (mp->param_size != x) goto OFF_BASE;
+undump_int(x); if (mp->max_in_open != x) goto OFF_BASE
+
+@ We do string pool compaction to avoid dumping unused strings.
+
+@d dump_four_ASCII
+ w.b0=qi(mp->str_pool[k]); w.b1=qi(mp->str_pool[k+1]);
+ w.b2=qi(mp->str_pool[k+2]); w.b3=qi(mp->str_pool[k+3]);
+ dump_qqqq(w)
+
+@<Dump the string pool@>=
+mp_do_compaction(mp, mp->pool_size);
+dump_int(mp->pool_ptr);
+dump_int(mp->max_str_ptr);
+dump_int(mp->str_ptr);
+k=0;
+while ( (mp->next_str[k]==k+1) && (k<=mp->max_str_ptr) )
+ incr(k);
+dump_int(k);
+while ( k<=mp->max_str_ptr ) {
+ dump_int(mp->next_str[k]); incr(k);
+}
+k=0;
+while (1) {
+ dump_int(mp->str_start[k]); /* TODO: valgrind warning here */
+ if ( k==mp->str_ptr ) {
+ break;
+ } else {
+ k=mp->next_str[k];
+ }
+}
+k=0;
+while (k+4<mp->pool_ptr ) {
+ dump_four_ASCII; k=k+4;
+}
+k=mp->pool_ptr-4; dump_four_ASCII;
+mp_print_ln(mp); mp_print(mp, "at most "); mp_print_int(mp, mp->max_str_ptr);
+mp_print(mp, " strings of total length ");
+mp_print_int(mp, mp->pool_ptr)
+
+@ @d undump_four_ASCII
+ undump_qqqq(w);
+ mp->str_pool[k]=qo(w.b0); mp->str_pool[k+1]=qo(w.b1);
+ mp->str_pool[k+2]=qo(w.b2); mp->str_pool[k+3]=qo(w.b3)
+
+@<Undump the string pool@>=
+undump_int(mp->pool_ptr);
+mp_reallocate_pool(mp, mp->pool_ptr) ;
+undump_int(mp->max_str_ptr);
+mp_reallocate_strings (mp,mp->max_str_ptr) ;
+undump(0,mp->max_str_ptr,mp->str_ptr);
+undump(0,mp->max_str_ptr+1,s);
+for (k=0;k<=s-1;k++)
+ mp->next_str[k]=k+1;
+for (k=s;k<=mp->max_str_ptr;k++)
+ undump(s+1,mp->max_str_ptr+1,mp->next_str[k]);
+mp->fixed_str_use=0;
+k=0;
+while (1) {
+ undump(0,mp->pool_ptr,mp->str_start[k]);
+ if ( k==mp->str_ptr ) break;
+ mp->str_ref[k]=max_str_ref;
+ incr(mp->fixed_str_use);
+ mp->last_fixed_str=k; k=mp->next_str[k];
+}
+k=0;
+while ( k+4<mp->pool_ptr ) {
+ undump_four_ASCII; k=k+4;
+}
+k=mp->pool_ptr-4; undump_four_ASCII;
+mp->init_str_use=mp->fixed_str_use; mp->init_pool_ptr=mp->pool_ptr;
+mp->max_pool_ptr=mp->pool_ptr;
+mp->strs_used_up=mp->fixed_str_use;
+mp->pool_in_use=mp->str_start[mp->str_ptr]; mp->strs_in_use=mp->fixed_str_use;
+mp->max_pl_used=mp->pool_in_use; mp->max_strs_used=mp->strs_in_use;
+mp->pact_count=0; mp->pact_chars=0; mp->pact_strs=0;
+
+@ By sorting the list of available spaces in the variable-size portion of
+|mem|, we are usually able to get by without having to dump very much
+of the dynamic memory.
+
+We recompute |var_used| and |dyn_used|, so that \.{INIMP} dumps valid
+information even when it has not been gathering statistics.
+
+@<Dump the dynamic memory@>=
+mp_sort_avail(mp); mp->var_used=0;
+dump_int(mp->lo_mem_max); dump_int(mp->rover);
+p=0; q=mp->rover; x=0;
+do {
+ for (k=p;k<= q+1;k++)
+ dump_wd(mp->mem[k]);
+ x=x+q+2-p; mp->var_used=mp->var_used+q-p;
+ p=q+node_size(q); q=rlink(q);
+} while (q!=mp->rover);
+mp->var_used=mp->var_used+mp->lo_mem_max-p;
+mp->dyn_used=mp->mem_end+1-mp->hi_mem_min;
+for (k=p;k<= mp->lo_mem_max;k++ )
+ dump_wd(mp->mem[k]);
+x=x+mp->lo_mem_max+1-p;
+dump_int(mp->hi_mem_min); dump_int(mp->avail);
+for (k=mp->hi_mem_min;k<=mp->mem_end;k++ )
+ dump_wd(mp->mem[k]);
+x=x+mp->mem_end+1-mp->hi_mem_min;
+p=mp->avail;
+while ( p!=null ) {
+ decr(mp->dyn_used); p=link(p);
+}
+dump_int(mp->var_used); dump_int(mp->dyn_used);
+mp_print_ln(mp); mp_print_int(mp, x);
+mp_print(mp, " memory locations dumped; current usage is ");
+mp_print_int(mp, mp->var_used); mp_print_char(mp, '&'); mp_print_int(mp, mp->dyn_used)
+
+@ @<Undump the dynamic memory@>=
+undump(lo_mem_stat_max+1000,hi_mem_stat_min-1,mp->lo_mem_max);
+undump(lo_mem_stat_max+1,mp->lo_mem_max,mp->rover);
+p=0; q=mp->rover;
+do {
+ for (k=p;k<= q+1; k++)
+ undump_wd(mp->mem[k]);
+ p=q+node_size(q);
+ if ( (p>mp->lo_mem_max)||((q>=rlink(q))&&(rlink(q)!=mp->rover)) )
+ goto OFF_BASE;
+ q=rlink(q);
+} while (q!=mp->rover);
+for (k=p;k<=mp->lo_mem_max;k++ )
+ undump_wd(mp->mem[k]);
+undump(mp->lo_mem_max+1,hi_mem_stat_min,mp->hi_mem_min);
+undump(null,mp->mem_top,mp->avail); mp->mem_end=mp->mem_top;
+for (k=mp->hi_mem_min;k<= mp->mem_end;k++)
+ undump_wd(mp->mem[k]);
+undump_int(mp->var_used); undump_int(mp->dyn_used)
+
+@ A different scheme is used to compress the hash table, since its lower region
+is usually sparse. When |text(p)<>0| for |p<=hash_used|, we output three
+words: |p|, |hash[p]|, and |eqtb[p]|. The hash table is, of course, densely
+packed for |p>=hash_used|, so the remaining entries are output in~a~block.
+
+@<Dump the table of equivalents and the hash table@>=
+dump_int(mp->hash_used);
+mp->st_count=frozen_inaccessible-1-mp->hash_used;
+for (p=1;p<=mp->hash_used;p++) {
+ if ( text(p)!=0 ) {
+ dump_int(p); dump_hh(mp->hash[p]); dump_hh(mp->eqtb[p]); incr(mp->st_count);
+ }
+}
+for (p=mp->hash_used+1;p<=(int)hash_end;p++) {
+ dump_hh(mp->hash[p]); dump_hh(mp->eqtb[p]);
+}
+dump_int(mp->st_count);
+mp_print_ln(mp); mp_print_int(mp, mp->st_count); mp_print(mp, " symbolic tokens")
+
+@ @<Undump the table of equivalents and the hash table@>=
+undump(1,frozen_inaccessible,mp->hash_used);
+p=0;
+do {
+ undump(p+1,mp->hash_used,p);
+ undump_hh(mp->hash[p]); undump_hh(mp->eqtb[p]);
+} while (p!=mp->hash_used);
+for (p=mp->hash_used+1;p<=(int)hash_end;p++ ) {
+ undump_hh(mp->hash[p]); undump_hh(mp->eqtb[p]);
+}
+undump_int(mp->st_count)
+
+@ We have already printed a lot of statistics, so we set |mp_tracing_stats:=0|
+to prevent them appearing again.
+
+@<Dump a few more things and the closing check word@>=
+dump_int(mp->max_internal);
+dump_int(mp->int_ptr);
+for (k=1;k<= mp->int_ptr;k++ ) {
+ dump_int(mp->internal[k]);
+ dump_string(mp->int_name[k]);
+}
+dump_int(mp->start_sym);
+dump_int(mp->interaction);
+dump_string(mp->mem_ident);
+dump_int(mp->bg_loc); dump_int(mp->eg_loc); dump_int(mp->serial_no); dump_int(69073);
+mp->internal[mp_tracing_stats]=0
+
+@ @<Undump a few more things and the closing check word@>=
+undump_int(x);
+if (x>mp->max_internal) mp_grow_internals(mp,x);
+undump_int(mp->int_ptr);
+for (k=1;k<= mp->int_ptr;k++) {
+ undump_int(mp->internal[k]);
+ undump_string(mp->int_name[k]);
+}
+undump(0,frozen_inaccessible,mp->start_sym);
+if (mp->interaction==mp_unspecified_mode) {
+ undump(mp_unspecified_mode,mp_error_stop_mode,mp->interaction);
+} else {
+ undump(mp_unspecified_mode,mp_error_stop_mode,x);
+}
+undump_string(mp->mem_ident);
+undump(1,hash_end,mp->bg_loc);
+undump(1,hash_end,mp->eg_loc);
+undump_int(mp->serial_no);
+undump_int(x);
+if (x!=69073) goto OFF_BASE
+
+@ @<Create the |mem_ident|...@>=
+{
+ xfree(mp->mem_ident);
+ mp->mem_ident = xmalloc(256,1);
+ snprintf(mp->mem_ident,256," (mem=%s %i.%i.%i)",
+ mp->job_name,
+ (int)(mp_round_unscaled(mp, mp->internal[mp_year]) % 100),
+ (int)mp_round_unscaled(mp, mp->internal[mp_month]),
+ (int)mp_round_unscaled(mp, mp->internal[mp_day]));
+ mp_pack_job_name(mp, mem_extension);
+ while (! mp_w_open_out(mp, &mp->mem_file) )
+ mp_prompt_file_name(mp, "mem file name", mem_extension);
+ mp_print_nl(mp, "Beginning to dump on file ");
+@.Beginning to dump...@>
+ mp_print(mp, mp->name_of_file);
+ mp_print_nl(mp, mp->mem_ident);
+}
+
+@ @<Dealloc variables@>=
+xfree(mp->mem_ident);
+
+@ @<Close the mem file@>=
+(mp->close_file)(mp,mp->mem_file)
+
+@* \[46] The main program.
+This is it: the part of \MP\ that executes all those procedures we have
+written.
+
+Well---almost. We haven't put the parsing subroutines into the
+program yet; and we'd better leave space for a few more routines that may
+have been forgotten.
+
+@c @<Declare the basic parsing subroutines@>
+@<Declare miscellaneous procedures that were declared |forward|@>
+@<Last-minute procedures@>
+
+@ We've noted that there are two versions of \MP. One, called \.{INIMP},
+@.INIMP@>
+has to be run first; it initializes everything from scratch, without
+reading a mem file, and it has the capability of dumping a mem file.
+The other one is called `\.{VIRMP}'; it is a ``virgin'' program that needs
+@.VIRMP@>
+to input a mem file in order to get started. \.{VIRMP} typically has
+a bit more memory capacity than \.{INIMP}, because it does not need the
+space consumed by the dumping/undumping routines and the numerous calls on
+|primitive|, etc.
+
+The \.{VIRMP} program cannot read a mem file instantaneously, of course;
+the best implementations therefore allow for production versions of \MP\ that
+not only avoid the loading routine for object code, they also have
+a mem file pre-loaded.
+
+@ @<Option variables@>=
+int ini_version; /* are we iniMP? */
+
+@ @<Set |ini_version|@>=
+mp->ini_version = (opt->ini_version ? true : false);
+
+@ Here we do whatever is needed to complete \MP's job gracefully on the
+local operating system. The code here might come into play after a fatal
+error; it must therefore consist entirely of ``safe'' operations that
+cannot produce error messages. For example, it would be a mistake to call
+|str_room| or |make_string| at this time, because a call on |overflow|
+might lead to an infinite loop.
+@^system dependencies@>
+
+This program doesn't bother to close the input files that may still be open.
+
+@<Last-minute...@>=
+void mp_close_files_and_terminate (MP mp) {
+ integer k; /* all-purpose index */
+ integer LH; /* the length of the \.{TFM} header, in words */
+ int lk_offset; /* extra words inserted at beginning of |lig_kern| array */
+ pointer p; /* runs through a list of \.{TFM} dimensions */
+ @<Close all open files in the |rd_file| and |wr_file| arrays@>;
+ if ( mp->internal[mp_tracing_stats]>0 )
+ @<Output statistics about this job@>;
+ wake_up_terminal;
+ @<Do all the finishing work on the \.{TFM} file@>;
+ @<Explain what output files were written@>;
+ if ( mp->log_opened ){
+ wlog_cr;
+ (mp->close_file)(mp,mp->log_file);
+ mp->selector=mp->selector-2;
+ if ( mp->selector==term_only ) {
+ mp_print_nl(mp, "Transcript written on ");
+@.Transcript written...@>
+ mp_print(mp, mp->log_name); mp_print_char(mp, '.');
+ }
+ }
+ mp_print_ln(mp);
+ t_close_out;
+ t_close_in;
+}
+
+@ @<Declarations@>=
+void mp_close_files_and_terminate (MP mp) ;
+
+@ @<Close all open files in the |rd_file| and |wr_file| arrays@>=
+if (mp->rd_fname!=NULL) {
+ for (k=0;k<=(int)mp->read_files-1;k++ ) {
+ if ( mp->rd_fname[k]!=NULL ) {
+ (mp->close_file)(mp,mp->rd_file[k]);
+ }
+ }
+}
+if (mp->wr_fname!=NULL) {
+ for (k=0;k<=(int)mp->write_files-1;k++) {
+ if ( mp->wr_fname[k]!=NULL ) {
+ (mp->close_file)(mp,mp->wr_file[k]);
+ }
+ }
+}
+
+@ @<Dealloc ...@>=
+for (k=0;k<(int)mp->max_read_files;k++ ) {
+ if ( mp->rd_fname[k]!=NULL ) {
+ (mp->close_file)(mp,mp->rd_file[k]);
+ mp_xfree(mp->rd_fname[k]);
+ }
+}
+mp_xfree(mp->rd_file);
+mp_xfree(mp->rd_fname);
+for (k=0;k<(int)mp->max_write_files;k++) {
+ if ( mp->wr_fname[k]!=NULL ) {
+ (mp->close_file)(mp,mp->wr_file[k]);
+ mp_xfree(mp->wr_fname[k]);
+ }
+}
+mp_xfree(mp->wr_file);
+mp_xfree(mp->wr_fname);
+
+
+@ We want to produce a \.{TFM} file if and only if |mp_fontmaking| is positive.
+
+We reclaim all of the variable-size memory at this point, so that
+there is no chance of another memory overflow after the memory capacity
+has already been exceeded.
+
+@<Do all the finishing work on the \.{TFM} file@>=
+if ( mp->internal[mp_fontmaking]>0 ) {
+ @<Make the dynamic memory into one big available node@>;
+ @<Massage the \.{TFM} widths@>;
+ mp_fix_design_size(mp); mp_fix_check_sum(mp);
+ @<Massage the \.{TFM} heights, depths, and italic corrections@>;
+ mp->internal[mp_fontmaking]=0; /* avoid loop in case of fatal error */
+ @<Finish the \.{TFM} file@>;
+}
+
+@ @<Make the dynamic memory into one big available node@>=
+mp->rover=lo_mem_stat_max+1; link(mp->rover)=empty_flag; mp->lo_mem_max=mp->hi_mem_min-1;
+if ( mp->lo_mem_max-mp->rover>max_halfword ) mp->lo_mem_max=max_halfword+mp->rover;
+node_size(mp->rover)=mp->lo_mem_max-mp->rover;
+llink(mp->rover)=mp->rover; rlink(mp->rover)=mp->rover;
+link(mp->lo_mem_max)=null; info(mp->lo_mem_max)=null
+
+@ The present section goes directly to the log file instead of using
+|print| commands, because there's no need for these strings to take
+up |str_pool| memory when a non-{\bf stat} version of \MP\ is being used.
+
+@<Output statistics...@>=
+if ( mp->log_opened ) {
+ char s[128];
+ wlog_ln(" ");
+ wlog_ln("Here is how much of MetaPost's memory you used:");
+@.Here is how much...@>
+ snprintf(s,128," %i string%s out of %i",(int)mp->max_strs_used-mp->init_str_use,
+ (mp->max_strs_used!=mp->init_str_use+1 ? "s" : ""),
+ (int)(mp->max_strings-1-mp->init_str_use));
+ wlog_ln(s);
+ snprintf(s,128," %i string characters out of %i",
+ (int)mp->max_pl_used-mp->init_pool_ptr,
+ (int)mp->pool_size-mp->init_pool_ptr);
+ wlog_ln(s);
+ snprintf(s,128," %i words of memory out of %i",
+ (int)mp->lo_mem_max+mp->mem_end-mp->hi_mem_min+2,
+ (int)mp->mem_end);
+ wlog_ln(s);
+ snprintf(s,128," %i symbolic tokens out of %i", (int)mp->st_count, (int)mp->hash_size);
+ wlog_ln(s);
+ snprintf(s,128," %ii,%in,%ip,%ib stack positions out of %ii,%in,%ip,%ib",
+ (int)mp->max_in_stack,(int)mp->int_ptr,
+ (int)mp->max_param_stack,(int)mp->max_buf_stack+1,
+ (int)mp->stack_size,(int)mp->max_internal,(int)mp->param_size,(int)mp->buf_size);
+ wlog_ln(s);
+ snprintf(s,128," %i string compactions (moved %i characters, %i strings)",
+ (int)mp->pact_count,(int)mp->pact_chars,(int)mp->pact_strs);
+ wlog_ln(s);
+}
+
+@ It is nice to have have some of the stats available from the API.
+
+@<Exported function ...@>=
+int mp_memory_usage (MP mp );
+int mp_hash_usage (MP mp );
+int mp_param_usage (MP mp );
+int mp_open_usage (MP mp );
+
+@ @c
+int mp_memory_usage (MP mp ) {
+ return (int)mp->lo_mem_max+mp->mem_end-mp->hi_mem_min+2;
+}
+int mp_hash_usage (MP mp ) {
+ return (int)mp->st_count;
+}
+int mp_param_usage (MP mp ) {
+ return (int)mp->max_param_stack;
+}
+int mp_open_usage (MP mp ) {
+ return (int)mp->max_in_stack;
+}
+
+@ We get to the |final_cleanup| routine when \&{end} or \&{dump} has
+been scanned.
+
+@<Last-minute...@>=
+void mp_final_cleanup (MP mp) {
+ small_number c; /* 0 for \&{end}, 1 for \&{dump} */
+ c=mp->cur_mod;
+ if ( mp->job_name==NULL ) mp_open_log_file(mp);
+ while ( mp->input_ptr>0 ) {
+ if ( token_state ) mp_end_token_list(mp);
+ else mp_end_file_reading(mp);
+ }
+ while ( mp->loop_ptr!=null ) mp_stop_iteration(mp);
+ while ( mp->open_parens>0 ) {
+ mp_print(mp, " )"); decr(mp->open_parens);
+ };
+ while ( mp->cond_ptr!=null ) {
+ mp_print_nl(mp, "(end occurred when ");
+@.end occurred...@>
+ mp_print_cmd_mod(mp, fi_or_else,mp->cur_if);
+ /* `\.{if}' or `\.{elseif}' or `\.{else}' */
+ if ( mp->if_line!=0 ) {
+ mp_print(mp, " on line "); mp_print_int(mp, mp->if_line);
+ }
+ mp_print(mp, " was incomplete)");
+ mp->if_line=if_line_field(mp->cond_ptr);
+ mp->cur_if=name_type(mp->cond_ptr); mp->cond_ptr=link(mp->cond_ptr);
+ }
+ if ( mp->history!=mp_spotless )
+ if ( ((mp->history==mp_warning_issued)||(mp->interaction<mp_error_stop_mode)) )
+ if ( mp->selector==term_and_log ) {
+ mp->selector=term_only;
+ mp_print_nl(mp, "(see the transcript file for additional information)");
+@.see the transcript file...@>
+ mp->selector=term_and_log;
+ }
+ if ( c==1 ) {
+ if (mp->ini_version) {
+ mp_store_mem_file(mp); return;
+ }
+ mp_print_nl(mp, "(dump is performed only by INIMP)"); return;
+@.dump...only by INIMP@>
+ }
+}
+
+@ @<Declarations@>=
+void mp_final_cleanup (MP mp) ;
+void mp_init_prim (MP mp) ;
+void mp_init_tab (MP mp) ;
+
+@ @<Last-minute...@>=
+void mp_init_prim (MP mp) { /* initialize all the primitives */
+ @<Put each...@>;
+}
+@#
+void mp_init_tab (MP mp) { /* initialize other tables */
+ integer k; /* all-purpose index */
+ @<Initialize table entries (done by \.{INIMP} only)@>;
+}
+
+
+@ When we begin the following code, \MP's tables may still contain garbage;
+the strings might not even be present. Thus we must proceed cautiously to get
+bootstrapped in.
+
+But when we finish this part of the program, \MP\ is ready to call on the
+|main_control| routine to do its work.
+
+@<Get the first line...@>=
+{
+ @<Initialize the input routines@>;
+ if ( (mp->mem_ident==NULL)||(mp->buffer[loc]=='&') ) {
+ if ( mp->mem_ident!=NULL ) {
+ mp_do_initialize(mp); /* erase preloaded mem */
+ }
+ if ( ! mp_open_mem_file(mp) ) return mp_fatal_error_stop;
+ if ( ! mp_load_mem_file(mp) ) {
+ (mp->close_file)(mp, mp->mem_file);
+ return mp_fatal_error_stop;
+ }
+ (mp->close_file)(mp, mp->mem_file);
+ while ( (loc<limit)&&(mp->buffer[loc]==' ') ) incr(loc);
+ }
+ mp->buffer[limit]='%';
+ mp_fix_date_and_time(mp);
+ if (mp->random_seed==0)
+ mp->random_seed = (mp->internal[mp_time] / unity)+mp->internal[mp_day];
+ mp_init_randoms(mp, mp->random_seed);
+ @<Initialize the print |selector|...@>;
+ if ( loc<limit ) if ( mp->buffer[loc]!='\\' )
+ mp_start_input(mp); /* \&{input} assumed */
+}
+
+@ @<Run inimpost commands@>=
+{
+ mp_get_strings_started(mp);
+ mp_init_tab(mp); /* initialize the tables */
+ mp_init_prim(mp); /* call |primitive| for each primitive */
+ mp->init_str_use=mp->str_ptr; mp->init_pool_ptr=mp->pool_ptr;
+ mp->max_str_ptr=mp->str_ptr; mp->max_pool_ptr=mp->pool_ptr;
+ mp_fix_date_and_time(mp);
+}
+
+
+@* \[47] Debugging.
+Once \MP\ is working, you should be able to diagnose most errors with
+the \.{show} commands and other diagnostic features. But for the initial
+stages of debugging, and for the revelation of really deep mysteries, you
+can compile \MP\ with a few more aids. An additional routine called |debug_help|
+will also come into play when you type `\.D' after an error message;
+|debug_help| also occurs just before a fatal error causes \MP\ to succumb.
+@^debugging@>
+@^system dependencies@>
+
+The interface to |debug_help| is primitive, but it is good enough when used
+with a debugger that allows you to set breakpoints and to read
+variables and change their values. After getting the prompt `\.{debug \#}', you
+type either a negative number (this exits |debug_help|), or zero (this
+goes to a location where you can set a breakpoint, thereby entering into
+dialog with the debugger), or a positive number |m| followed by
+an argument |n|. The meaning of |m| and |n| will be clear from the
+program below. (If |m=13|, there is an additional argument, |l|.)
+@.debug \#@>
+
+@<Last-minute...@>=
+void mp_debug_help (MP mp) { /* routine to display various things */
+ integer k;
+ int l,m,n;
+ char *aline;
+ size_t len;
+ while (1) {
+ wake_up_terminal;
+ mp_print_nl(mp, "debug # (-1 to exit):"); update_terminal;
+@.debug \#@>
+ m = 0;
+ aline = (mp->read_ascii_file)(mp,mp->term_in, &len);
+ if (len) { sscanf(aline,"%i",&m); xfree(aline); }
+ if ( m<=0 )
+ return;
+ n = 0 ;
+ aline = (mp->read_ascii_file)(mp,mp->term_in, &len);
+ if (len) { sscanf(aline,"%i",&n); xfree(aline); }
+ switch (m) {
+ @<Numbered cases for |debug_help|@>;
+ default: mp_print(mp, "?"); break;
+ }
+ }
+}
+
+@ @<Numbered cases...@>=
+case 1: mp_print_word(mp, mp->mem[n]); /* display |mem[n]| in all forms */
+ break;
+case 2: mp_print_int(mp, info(n));
+ break;
+case 3: mp_print_int(mp, link(n));
+ break;
+case 4: mp_print_int(mp, eq_type(n)); mp_print_char(mp, ':'); mp_print_int(mp, equiv(n));
+ break;
+case 5: mp_print_variable_name(mp, n);
+ break;
+case 6: mp_print_int(mp, mp->internal[n]);
+ break;
+case 7: mp_do_show_dependencies(mp);
+ break;
+case 9: mp_show_token_list(mp, n,null,100000,0);
+ break;
+case 10: mp_print_str(mp, n);
+ break;
+case 11: mp_check_mem(mp, n>0); /* check wellformedness; print new busy locations if |n>0| */
+ break;
+case 12: mp_search_mem(mp, n); /* look for pointers to |n| */
+ break;
+case 13:
+ l = 0;
+ aline = (mp->read_ascii_file)(mp,mp->term_in, &len);
+ if (len) { sscanf(aline,"%i",&l); xfree(aline); }
+ mp_print_cmd_mod(mp, n,l);
+ break;
+case 14: for (k=0;k<=n;k++) mp_print_str(mp, mp->buffer[k]);
+ break;
+case 15: mp->panicking=! mp->panicking;
+ break;
+
+
+@ Saving the filename template
+
+@<Save the filename template@>=
+{
+ if ( mp->filename_template!=0 ) delete_str_ref(mp->filename_template);
+ if ( length(mp->cur_exp)==0 ) mp->filename_template=0;
+ else {
+ mp->filename_template=mp->cur_exp; add_str_ref(mp->filename_template);
+ }
+}
+
+@* \[48] System-dependent changes.
+This section should be replaced, if necessary, by any special
+modification of the program
+that are necessary to make \MP\ work at a particular installation.
+It is usually best to design your change file so that all changes to
+previous sections preserve the section numbering; then everybody's version
+will be consistent with the published program. More extensive changes,
+which introduce new sections, can be inserted here; then only the index
+itself will get a new section number.
+@^system dependencies@>
+
+@* \[49] Index.
+Here is where you can find all uses of each identifier in the program,
+with underlined entries pointing to where the identifier was defined.
+If the identifier is only one letter long, however, you get to see only
+the underlined entries. {\sl All references are to section numbers instead of
+page numbers.}
+
+This index also lists error messages and other aspects of the program
+that you might want to look up some day. For example, the entry
+for ``system dependencies'' lists all sections that should receive
+special attention from people who are installing \MP\ in a new
+operating environment. A list of various things that can't happen appears
+under ``this can't happen''.
+Approximately 25 sections are listed under ``inner loop''; these account
+for more than 60\pct! of \MP's running time, exclusive of input and output.
diff --git a/Build/source/texk/web2c/luatexdir/lua/psout.w b/Build/source/texk/web2c/luatexdir/lua/psout.w
new file mode 100644
index 00000000000..4a3f588ef7f
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/psout.w
@@ -0,0 +1,5697 @@
+% $Id: mp.web,v 1.8 2005/08/24 10:54:02 taco Exp $
+% MetaPost, by John Hobby. Public domain.
+
+% Much of this program was copied with permission from MF.web Version 1.9
+% It interprets a language very similar to D.E. Knuth's METAFONT, but with
+% changes designed to make it more suitable for PostScript output.
+
+% TeX is a trademark of the American Mathematical Society.
+% METAFONT is a trademark of Addison-Wesley Publishing Company.
+% PostScript is a trademark of Adobe Systems Incorporated.
+
+% Here is TeX material that gets inserted after \input webmac
+\def\hang{\hangindent 3em\noindent\ignorespaces}
+\def\textindent#1{\hangindent2.5em\noindent\hbox to2.5em{\hss#1 }\ignorespaces}
+\def\PASCAL{Pascal}
+\def\ps{PostScript}
+\def\ph{\hbox{Pascal-H}}
+\def\psqrt#1{\sqrt{\mathstrut#1}}
+\def\k{_{k+1}}
+\def\pct!{{\char`\%}} % percent sign in ordinary text
+\font\tenlogo=logo10 % font used for the METAFONT logo
+\font\logos=logosl10
+\def\MF{{\tenlogo META}\-{\tenlogo FONT}}
+\def\MP{{\tenlogo META}\-{\tenlogo POST}}
+\def\<#1>{$\langle#1\rangle$}
+\def\section{\mathhexbox278}
+\let\swap=\leftrightarrow
+\def\round{\mathop{\rm round}\nolimits}
+\mathchardef\vb="026A % synonym for `\|'
+\def\[#1]{} % from pascal web
+\def\(#1){} % this is used to make section names sort themselves better
+\def\9#1{} % this is used for sort keys in the index via @@:sort key}{entry@@>
+
+\let\?=\relax % we want to be able to \write a \?
+
+\def\title{MetaPost \ps\ output}
+\def\topofcontents{\hsize 5.5in
+ \vglue -30pt plus 1fil minus 1.5in
+ \def\?##1]{\hbox to 1in{\hfil##1.\ }}
+ }
+\def\botofcontents{\vskip 0pt plus 1fil minus 1.5in}
+\pdfoutput=1
+\pageno=3
+
+@
+@d true 1
+@d false 0
+@d null_font 0
+@d null 0
+@d unity 0200000 /* $2^{16}$, represents 1.00000 */
+@d el_gordo 017777777777 /* $2^{31}-1$, the largest value that \MP\ likes */
+@d incr(A) (A)=(A)+1 /* increase a variable by unity */
+@d decr(A) (A)=(A)-1 /* decrease a variable by unity */
+@d negate(A) (A)=-(A) /* change the sign of a variable */
+@d odd(A) ((A)%2==1)
+@d half(A) ((A)/2)
+@d print_err(A) mp_print_err(mp,(A))
+@d max_quarterword 0x3FFF /* largest allowable value in a |quarterword| */
+
+@c
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <assert.h>
+#include "avl.h"
+#include "mplib.h"
+#include "mpmp.h" /* internal header */
+#include "mppsout.h" /* internal header */
+@h
+@<Declarations@>
+@<Static variables in the outer block@>
+
+@ There is a small bit of code from the backend that bleads through
+to the frontend because I do not know how to set up the includes
+properly. Those are the definitions of |struct libavl_allocator|
+and |typedef struct psout_data_struct * psout_data|.
+
+The |libavl_allocator| is a trick that makes sure that frontends
+do not need |avl.h|, and the |psout_data| is needed for the backend
+data structure.
+
+@ @(mppsout.h@>=
+@<Types...@>
+typedef struct psout_data_struct {
+ @<Globals@>
+} psout_data_struct ;
+@<Exported function headers@>
+
+@ @<Exported function headers@>=
+void mp_backend_initialize (MP mp) ;
+void mp_backend_free (MP mp) ;
+
+@
+@c void mp_backend_initialize (MP mp) {
+ mp->ps = mp_xmalloc(mp,1,sizeof(psout_data_struct));
+ @<Set initial values@>;
+}
+void mp_backend_free (MP mp) {
+ @<Dealloc variables@>;
+ enc_free(mp);
+ t1_free(mp);
+ fm_free(mp);
+ mp_xfree(mp->ps);
+ mp->ps = NULL;
+}
+
+@ Writing to ps files
+
+@<Globals@>=
+integer ps_offset;
+ /* the number of characters on the current \ps\ file line */
+
+@ @<Set initial values@>=
+mp->ps->ps_offset = 0;
+
+@
+
+@d wps(A) (mp->write_ascii_file)(mp,mp->ps_file,(A))
+@d wps_chr(A) do {
+ char ss[2];
+ ss[0]=(A); ss[1]=0;
+ (mp->write_ascii_file)(mp,mp->ps_file,(char *)ss);
+} while (0)
+@d wps_cr (mp->write_ascii_file)(mp,mp->ps_file,"\n")
+@d wps_ln(A) { wterm_cr; (mp->write_ascii_file)(mp,mp->ps_file,(A)); }
+
+@c
+void mp_ps_print_ln (MP mp) { /* prints an end-of-line */
+ wps_cr;
+ mp->ps->ps_offset=0;
+}
+
+@ @c
+void mp_ps_print_char (MP mp, ASCII_code s) { /* prints a single character */
+ if ( s==13 ) {
+ wps_cr; mp->ps->ps_offset=0;
+ } else {
+ wps_chr(s); incr(mp->ps->ps_offset);
+ }
+}
+
+@ @c
+void mp_ps_do_print (MP mp, const char *ss, unsigned int len) { /* prints string |s| */
+ unsigned int j = 0;
+ while ( j<len ){
+ mp_ps_print_char(mp, ss[j]); incr(j);
+ }
+}
+
+@ Deciding where to break the ps output line.
+
+@d ps_room(A) if ( (mp->ps->ps_offset+(int)(A))>mp->max_print_line ) {
+ mp_ps_print_ln(mp); /* optional line break */
+}
+
+@c
+void mp_ps_print (MP mp, const char *ss) {
+ ps_room(strlen(ss));
+ mp_ps_do_print(mp, ss, strlen(ss));
+}
+
+@ The procedure |print_nl| is like |print|, but it makes sure that the
+string appears at the beginning of a new line.
+
+@c
+void mp_ps_print_nl (MP mp, const char *s) { /* prints string |s| at beginning of line */
+ if ( mp->ps->ps_offset>0 ) mp_ps_print_ln(mp);
+ mp_ps_print(mp, s);
+}
+
+@ An array of digits in the range |0..9| is printed by |print_the_digs|.
+
+@c
+void mp_ps_print_the_digs (MP mp, eight_bits k) {
+ /* prints |dig[k-1]|$\,\ldots\,$|dig[0]| */
+ while ( k-->0 ){
+ mp_ps_print_char(mp, '0'+mp->dig[k]);
+ }
+}
+
+@ The following procedure, which prints out the decimal representation of a
+given integer |n|, has been written carefully so that it works properly
+if |n=0| or if |(-n)| would cause overflow. It does not apply |mod| or |div|
+to negative arguments, since such operations are not implemented consistently
+by all \PASCAL\ compilers.
+
+@c
+void mp_ps_print_int (MP mp,integer n) { /* prints an integer in decimal form */
+ integer m; /* used to negate |n| in possibly dangerous cases */
+ int k = 0; /* index to current digit; we assume that $|n|<10^{23}$ */
+ if ( n<0 ) {
+ mp_ps_print_char(mp, '-');
+ if ( n>-100000000 ) {
+ negate(n);
+ } else {
+ m=-1-n; n=m / 10; m=(m % 10)+1; k=1;
+ if ( m<10 ) {
+ mp->dig[0]=m;
+ } else {
+ mp->dig[0]=0; incr(n);
+ }
+ }
+ }
+ do {
+ mp->dig[k]=n % 10; n=n / 10; incr(k);
+ } while (n!=0);
+ mp_ps_print_the_digs(mp, k);
+}
+
+@ @<Internal ...@>=
+void mp_ps_print_int (MP mp,integer n);
+
+@ \MP\ also makes use of a trivial procedure to print two digits. The
+following subroutine is usually called with a parameter in the range |0<=n<=99|.
+
+@c
+void mp_ps_print_dd (MP mp,integer n) { /* prints two least significant digits */
+ n=abs(n) % 100;
+ mp_ps_print_char(mp, '0'+(n / 10));
+ mp_ps_print_char(mp, '0'+(n % 10));
+}
+
+@ Conversely, here is a procedure analogous to |print_int|. If the output
+of this procedure is subsequently read by \MP\ and converted by the
+|round_decimals| routine above, it turns out that the original value will
+be reproduced exactly. A decimal point is printed only if the value is
+not an integer. If there is more than one way to print the result with
+the optimum number of digits following the decimal point, the closest
+possible value is given.
+
+The invariant relation in the \&{repeat} loop is that a sequence of
+decimal digits yet to be printed will yield the original number if and only if
+they form a fraction~$f$ in the range $s-\delta\L10\cdot2^{16}f<s$.
+We can stop if and only if $f=0$ satisfies this condition; the loop will
+terminate before $s$ can possibly become zero.
+
+@c
+void mp_ps_print_scaled (MP mp,scaled s) {
+ scaled delta; /* amount of allowable inaccuracy */
+ if ( s<0 ) {
+ mp_ps_print_char(mp, '-');
+ negate(s); /* print the sign, if negative */
+ }
+ mp_ps_print_int(mp, s / unity); /* print the integer part */
+ s=10*(s % unity)+5;
+ if ( s!=5 ) {
+ delta=10;
+ mp_ps_print_char(mp, '.');
+ do {
+ if ( delta>unity )
+ s=s+0100000-(delta / 2); /* round the final digit */
+ mp_ps_print_char(mp, '0'+(s / unity));
+ s=10*(s % unity);
+ delta=delta*10;
+ } while (s>delta);
+ }
+}
+
+
+@* \[44a] Dealing with font encodings.
+
+First, here are a few helpers for parsing files
+
+@d check_buf(size, buf_size)
+ if ((unsigned)(size) > (unsigned)(buf_size)) {
+ char S[128];
+ snprintf(S,128,"buffer overflow: (%d,%d) at file %s, line %d",
+ size,buf_size, __FILE__, __LINE__ );
+ mp_fatal_error(mp,S);
+ }
+
+@d append_char_to_buf(c, p, buf, buf_size) do {
+ if (c == 9)
+ c = 32;
+ if (c == 13 || c == EOF)
+ c = 10;
+ if (c != ' ' || (p > buf && p[-1] != 32)) {
+ check_buf(p - buf + 1, (buf_size));
+ *p++ = c;
+ }
+} while (0)
+
+@d append_eol(p, buf, buf_size) do {
+ check_buf(p - buf + 2, (buf_size));
+ if (p - buf > 1 && p[-1] != 10)
+ *p++ = 10;
+ if (p - buf > 2 && p[-2] == 32) {
+ p[-2] = 10;
+ p--;
+ }
+ *p = 0;
+} while (0)
+
+@d remove_eol(p, buf) do {
+ p = strend(buf) - 1;
+ if (*p == 10)
+ *p = 0;
+} while (0)
+
+@d skip(p, c) if (*p == c) p++
+@d strend(s) strchr(s, 0)
+@d str_prefix(s1, s2) (strncmp((s1), (s2), strlen(s2)) == 0)
+
+
+@ @<Types...@>=
+typedef struct {
+ boolean loaded; /* the encoding has been loaded? */
+ char *file_name; /* encoding file name */
+ char *enc_name; /* encoding true name */
+ integer objnum; /* object number */
+ char **glyph_names;
+ integer tounicode; /* object number of associated ToUnicode entry */
+} enc_entry;
+
+
+@
+
+@d ENC_STANDARD 0
+@d ENC_BUILTIN 1
+
+@<Glob...@>=
+#define ENC_BUF_SIZE 0x1000
+char enc_line[ENC_BUF_SIZE];
+void * enc_file;
+
+@
+@d enc_eof() (mp->eof_file)(mp,mp->ps->enc_file)
+@d enc_close() (mp->close_file)(mp,mp->ps->enc_file)
+
+@c
+int enc_getchar(MP mp) {
+ size_t len = 1;
+ unsigned char abyte=0;
+ void *byte_ptr = &abyte;
+ (mp->read_binary_file)(mp,mp->ps->enc_file,&byte_ptr,&len);
+ return abyte;
+}
+
+@ @c
+static boolean mp_enc_open (MP mp, char *n) {
+ mp->ps->enc_file=(mp->open_file)(mp,n, "r", mp_filetype_encoding);
+ if (mp->ps->enc_file!=NULL)
+ return true;
+ else
+ return false;
+}
+static void mp_enc_getline (MP mp) {
+ char *p;
+ int c;
+RESTART:
+ if (enc_eof ()) {
+ print_err("unexpected end of file");
+ mp_error(mp);
+ }
+ p = mp->ps->enc_line;
+ do {
+ c = enc_getchar (mp);
+ append_char_to_buf (c, p, mp->ps->enc_line, ENC_BUF_SIZE);
+ } while (c != 10);
+ append_eol (p, mp->ps->enc_line, ENC_BUF_SIZE);
+ if (p - mp->ps->enc_line < 2 || *mp->ps->enc_line == '%')
+ goto RESTART;
+}
+static void mp_load_enc (MP mp, char *enc_name,
+ char **enc_encname, char **glyph_names){
+ char buf[ENC_BUF_SIZE], *p, *r;
+ int names_count;
+ char *myname;
+ int save_selector = mp->selector;
+ if (!mp_enc_open (mp,enc_name)) {
+ mp_print (mp,"cannot open encoding file for reading");
+ return;
+ }
+ mp_normalize_selector(mp);
+ mp_print (mp,"{");
+ mp_print (mp, enc_name);
+ mp_enc_getline (mp);
+ if (*mp->ps->enc_line != '/' || (r = strchr (mp->ps->enc_line, '[')) == NULL) {
+ remove_eol (r, mp->ps->enc_line);
+ print_err ("invalid encoding vector (a name or `[' missing): `");
+ mp_print(mp,mp->ps->enc_line);
+ mp_print(mp,"'");
+ mp_error(mp);
+ }
+ while (*(r-1)==' ') r--; /* strip trailing spaces from encoding name */
+ myname = mp_xmalloc(mp,r-mp->ps->enc_line,1);
+ memcpy(myname,mp->ps->enc_line+1,(r-mp->ps->enc_line)-1);
+ *(myname+(r-mp->ps->enc_line-1))=0;
+ *enc_encname = myname;
+ while (*r!='[') r++;
+ r++; /* skip '[' */
+ names_count = 0;
+ skip (r, ' ');
+ for (;;) {
+ while (*r == '/') {
+ for (p = buf, r++;
+ *r != ' ' && *r != 10 && *r != ']' && *r != '/'; *p++ = *r++);
+ *p = 0;
+ skip (r, ' ');
+ if (names_count > 256) {
+ print_err ("encoding vector contains more than 256 names");
+ mp_error(mp);
+ }
+ if (mp_xstrcmp (buf, notdef) != 0)
+ glyph_names[names_count] = mp_xstrdup (mp,buf);
+ names_count++;
+ }
+ if (*r != 10 && *r != '%') {
+ if (str_prefix (r, "] def"))
+ goto DONE;
+ else {
+ remove_eol (r, mp->ps->enc_line);
+ print_err
+ ("invalid encoding vector: a name or `] def' expected: `");
+ mp_print(mp,mp->ps->enc_line);
+ mp_print(mp,"'");
+ mp_error(mp);
+ }
+ }
+ mp_enc_getline (mp);
+ r = mp->ps->enc_line;
+ }
+DONE:
+ enc_close ();
+ mp_print (mp,"}");
+ mp->selector = save_selector;
+}
+static void mp_read_enc (MP mp, enc_entry * e) {
+ if (e->loaded)
+ return;
+ e->enc_name = NULL;
+ mp_load_enc (mp,e->file_name, &e->enc_name, e->glyph_names);
+ e->loaded = true;
+}
+
+@ |write_enc| is used to write either external encoding (given in map file) or
+ internal encoding (read from the font file);
+ the 2nd argument is a pointer to the encoding entry;
+
+@c
+static void mp_write_enc (MP mp, enc_entry * e) {
+ int i;
+ int s;
+ int foffset;
+ char **g;
+ if (e->objnum != 0) /* the encoding has been written already */
+ return;
+ e->objnum = 1;
+ g = e->glyph_names;
+
+ mp_ps_print(mp,"\n%%%%BeginResource: encoding ");
+ mp_ps_print(mp, e->enc_name);
+ mp_ps_print_nl(mp, "/");
+ mp_ps_print(mp, e->enc_name);
+ mp_ps_print(mp, " [ ");
+ foffset = strlen(e->file_name)+3;
+ for (i = 0; i < 256; i++) {
+ s = strlen(g[i]);
+ if (s+1+foffset>=80) {
+ mp_ps_print_ln (mp);
+ foffset = 0;
+ }
+ foffset += s+2;
+ mp_ps_print_char(mp,'/');
+ mp_ps_print(mp, g[i]);
+ mp_ps_print_char(mp,' ');
+ }
+ if (foffset>75)
+ mp_ps_print_ln (mp);
+ mp_ps_print_nl (mp,"] def\n");
+ mp_ps_print(mp,"%%%%EndResource");
+}
+
+
+@ All encoding entries go into AVL tree for fast search by name.
+
+@<Glob...@>=
+struct avl_table *enc_tree;
+
+@ Memory management functions for avl
+
+@<Static variables in the outer block@>=
+static const char notdef[] = ".notdef";
+
+@ @<Declarations@>=
+static void *avl_xmalloc (struct libavl_allocator *allocator, size_t size);
+static void avl_xfree (struct libavl_allocator *allocator, void *block);
+
+@ @c
+static void *avl_xmalloc (struct libavl_allocator *allocator, size_t size) {
+ (void)allocator;
+ return malloc (size);
+}
+static void avl_xfree (struct libavl_allocator *allocator, void *block) {
+ (void)allocator;
+ free (block);
+}
+
+@ @<Glob...@>=
+struct libavl_allocator avl_xallocator;
+
+@ @<Set initial...@>=
+mp->ps->avl_xallocator.libavl_malloc=avl_xmalloc;
+mp->ps->avl_xallocator.libavl_free= avl_xfree;
+mp->ps->enc_tree = NULL;
+
+@ @c
+static int comp_enc_entry (const void *pa, const void *pb, void *p) {
+ (void)p;
+ return strcmp (((const enc_entry *) pa)->file_name,
+ ((const enc_entry *) pb)->file_name);
+}
+static enc_entry * mp_add_enc (MP mp, char *s) {
+ int i;
+ enc_entry tmp, *p;
+ void **aa;
+ if (mp->ps->enc_tree == NULL) {
+ mp->ps->enc_tree = avl_create (comp_enc_entry, NULL, &mp->ps->avl_xallocator);
+ }
+ tmp.file_name = s;
+ p = (enc_entry *) avl_find (mp->ps->enc_tree, &tmp);
+ if (p != NULL) /* encoding already registered */
+ return p;
+ p = mp_xmalloc (mp,1,sizeof (enc_entry));
+ p->loaded = false;
+ p->file_name = mp_xstrdup (mp,s);
+ p->objnum = 0;
+ p->tounicode = 0;
+ p->glyph_names = mp_xmalloc (mp,256,sizeof (char *));
+ for (i = 0; i < 256; i++)
+ p->glyph_names[i] = (char *) notdef;
+ aa = avl_probe (mp->ps->enc_tree, p);
+ return p;
+}
+
+@ cleaning up...
+
+@c
+static void mp_destroy_enc_entry (void *pa, void *pb) {
+ enc_entry *p;
+ int i;
+ p = (enc_entry *) pa;
+ (void)pb;
+ mp_xfree (p->file_name);
+ if (p->glyph_names != NULL)
+ for (i = 0; i < 256; i++)
+ if (p->glyph_names[i] != notdef)
+ mp_xfree (p->glyph_names[i]);
+ mp_xfree (p->glyph_names);
+ mp_xfree (p);
+}
+
+@ @<Declarations@>=
+static void enc_free (MP mp);
+
+@ @c static void enc_free (MP mp) {
+ if (mp->ps->enc_tree != NULL)
+ avl_destroy (mp->ps->enc_tree, mp_destroy_enc_entry);
+}
+
+@ @<Exported function headers@>=
+void mp_reload_encodings (MP mp) ;
+
+@ @<Declarations@>=
+static void mp_font_encodings (MP mp, int lastfnum, int encodings_only) ;
+
+@ @c void mp_reload_encodings (MP mp) {
+ int f;
+ enc_entry *e;
+ fm_entry *fm_cur;
+ int lastfnum = mp->last_fnum;
+ for (f=null_font+1;f<=lastfnum;f++) {
+ if (mp->font_enc_name[f]!=NULL ) {
+ mp_xfree(mp->font_enc_name[f]);
+ mp->font_enc_name[f]=NULL;
+ }
+ if (mp_has_fm_entry (mp,f,&fm_cur)) {
+ if (fm_cur != NULL && fm_cur->ps_name != NULL &&is_reencoded (fm_cur)) {
+ e = fm_cur->encoding;
+ mp_read_enc (mp,e);
+ }
+ }
+ }
+}
+static void mp_font_encodings (MP mp, int lastfnum, int encodings_only) {
+ int f;
+ enc_entry *e;
+ fm_entry *fm;
+ for (f=null_font+1;f<=lastfnum;f++) {
+ if (mp_has_font_size(mp,f) && mp_has_fm_entry (mp,f, &fm)) {
+ if (fm != NULL && (fm->ps_name != NULL)) {
+ if (is_reencoded (fm)) {
+ if (encodings_only || (!is_subsetted (fm))) {
+ e = fm->encoding;
+ mp_write_enc (mp, e);
+ /* clear for next run */
+ e->objnum = 0;
+ }
+ }
+ }
+ }
+ }
+}
+
+@* \[44b] Parsing font map files.
+
+@d FM_BUF_SIZE 1024
+
+@<Glob...@>=
+void * fm_file;
+
+@
+@d fm_close() (mp->close_file)(mp,mp->ps->fm_file)
+@d fm_eof() (mp->eof_file)(mp,mp->ps->fm_file)
+
+@c
+int fm_getchar(MP mp) {
+ size_t len = 1;
+ unsigned char abyte=0;
+ void *byte_ptr = &abyte;
+ (mp->read_binary_file)(mp,mp->ps->fm_file,&byte_ptr,&len);
+ if (len==0)
+ return EOF;
+ return abyte;
+}
+
+
+@ @<Types...@>=
+enum _mode { FM_DUPIGNORE, FM_REPLACE, FM_DELETE };
+enum _ltype { MAPFILE, MAPLINE };
+enum _tfmavail { TFM_UNCHECKED, TFM_FOUND, TFM_NOTFOUND };
+typedef struct mitem {
+ int mode; /* |FM_DUPIGNORE| or |FM_REPLACE| or |FM_DELETE| */
+ int type; /* map file or map line */
+ char *map_line; /* pointer to map file name or map line */
+ int lineno; /* line number in map file */
+} mapitem;
+
+@ @<Glob...@>=
+mapitem *mitem;
+fm_entry *fm_cur;
+fm_entry *loaded_tfm_found;
+fm_entry *avail_tfm_found;
+fm_entry *non_tfm_found;
+fm_entry *not_avail_tfm_found;
+
+@ @<Set initial...@>=
+mp->ps->mitem = NULL;
+
+@ @<Declarations@>=
+static const char nontfm[] = "<nontfm>";
+
+@
+@d read_field(r, q, buf) do {
+ q = buf;
+ while (*r != ' ' && *r != '\0')
+ *q++ = *r++;
+ *q = '\0';
+ skip (r, ' ');
+} while (0)
+
+@d set_field(F) do {
+ if (q > buf)
+ fm->F = mp_xstrdup(mp,buf);
+ if (*r == '\0')
+ goto DONE;
+} while (0)
+
+@d cmp_return(a, b)
+ if (a > b)
+ return 1;
+ if (a < b)
+ return -1
+
+@c
+static fm_entry *new_fm_entry (MP mp) {
+ fm_entry *fm;
+ fm = mp_xmalloc (mp,1,sizeof(fm_entry));
+ fm->tfm_name = NULL;
+ fm->ps_name = NULL;
+ fm->flags = 4;
+ fm->ff_name = NULL;
+ fm->subset_tag = NULL;
+ fm->encoding = NULL;
+ fm->tfm_num = null_font;
+ fm->tfm_avail = TFM_UNCHECKED;
+ fm->type = 0;
+ fm->slant = 0;
+ fm->extend = 0;
+ fm->ff_objnum = 0;
+ fm->fn_objnum = 0;
+ fm->fd_objnum = 0;
+ fm->charset = NULL;
+ fm->all_glyphs = false;
+ fm->links = 0;
+ fm->pid = -1;
+ fm->eid = -1;
+ return fm;
+}
+
+static void delete_fm_entry (fm_entry * fm) {
+ mp_xfree (fm->tfm_name);
+ mp_xfree (fm->ps_name);
+ mp_xfree (fm->ff_name);
+ mp_xfree (fm->subset_tag);
+ mp_xfree (fm->charset);
+ mp_xfree (fm);
+}
+
+static ff_entry *new_ff_entry (MP mp) {
+ ff_entry *ff;
+ ff = mp_xmalloc (mp,1,sizeof(ff_entry));
+ ff->ff_name = NULL;
+ ff->ff_path = NULL;
+ return ff;
+}
+
+static void delete_ff_entry (ff_entry * ff) {
+ mp_xfree (ff->ff_name);
+ mp_xfree (ff->ff_path);
+ mp_xfree (ff);
+}
+
+static char *mk_base_tfm (MP mp, char *tfmname, int *i) {
+ static char buf[SMALL_BUF_SIZE];
+ char *p = tfmname, *r = strend (p) - 1, *q = r;
+ while (q > p && isdigit (*q))
+ --q;
+ if (!(q > p) || q == r || (*q != '+' && *q != '-'))
+ return NULL;
+ check_buf (q - p + 1, SMALL_BUF_SIZE);
+ strncpy (buf, p, (size_t) (q - p));
+ buf[q - p] = '\0';
+ *i = atoi (q);
+ return buf;
+}
+
+@ @<Exported function headers@>=
+boolean mp_has_fm_entry (MP mp,font_number f, fm_entry **fm);
+
+@ @c
+boolean mp_has_fm_entry (MP mp,font_number f, fm_entry **fm) {
+ fm_entry *res = NULL;
+ res = mp_fm_lookup (mp, f);
+ if (fm != NULL) {
+ *fm =res;
+ }
+ return (res != NULL);
+}
+
+@ @<Glob...@>=
+struct avl_table *tfm_tree;
+struct avl_table *ps_tree;
+struct avl_table *ff_tree;
+
+@ @<Set initial...@>=
+mp->ps->tfm_tree = NULL;
+mp->ps->ps_tree = NULL;
+mp->ps->ff_tree = NULL;
+
+@ AVL sort |fm_entry| into |tfm_tree| by |tfm_name |
+
+@c
+static int comp_fm_entry_tfm (const void *pa, const void *pb, void *p) {
+ (void)p;
+ return strcmp (((const fm_entry *) pa)->tfm_name,
+ ((const fm_entry *) pb)->tfm_name);
+}
+
+@ AVL sort |fm_entry| into |ps_tree| by |ps_name|, |slant|, and |extend|
+
+@c static int comp_fm_entry_ps (const void *pa, const void *pb, void *p) {
+ int i;
+ const fm_entry *p1 = (const fm_entry *) pa;
+ const fm_entry *p2 = (const fm_entry *) pb;
+ (void)p;
+ assert (p1->ps_name != NULL && p2->ps_name != NULL);
+ if ((i = strcmp (p1->ps_name, p2->ps_name)))
+ return i;
+ cmp_return (p1->slant, p2->slant);
+ cmp_return (p1->extend, p2->extend);
+ if (p1->tfm_name != NULL && p2->tfm_name != NULL &&
+ (i = strcmp (p1->tfm_name, p2->tfm_name)))
+ return i;
+ return 0;
+}
+
+@ AVL sort |ff_entry| into |ff_tree| by |ff_name|
+
+@c static int comp_ff_entry (const void *pa, const void *pb, void *p) {
+ (void)p;
+ return strcmp (((const ff_entry *) pa)->ff_name,
+ ((const ff_entry *) pb)->ff_name);
+}
+
+@ @c static void create_avl_trees (MP mp) {
+ if (mp->ps->tfm_tree == NULL) {
+ mp->ps->tfm_tree = avl_create (comp_fm_entry_tfm, NULL, &mp->ps->avl_xallocator);
+ assert (mp->ps->tfm_tree != NULL);
+ }
+ if (mp->ps->ps_tree == NULL) {
+ mp->ps->ps_tree = avl_create (comp_fm_entry_ps, NULL, &mp->ps->avl_xallocator);
+ assert (mp->ps->ps_tree != NULL);
+ }
+ if (mp->ps->ff_tree == NULL) {
+ mp->ps->ff_tree = avl_create (comp_ff_entry, NULL, &mp->ps->avl_xallocator);
+ assert (mp->ps->ff_tree != NULL);
+ }
+}
+
+@ The function |avl_do_entry| is not completely symmetrical with regards
+to |tfm_name| and |ps_name handling|, e. g. a duplicate |tfm_name| gives a
+|goto exit|, and no |ps_name| link is tried. This is to keep it compatible
+with the original version.
+
+@d LINK_TFM 0x01
+@d LINK_PS 0x02
+@d set_tfmlink(fm) ((fm)->links |= LINK_TFM)
+@d set_pslink(fm) ((fm)->links |= LINK_PS)
+@d unset_tfmlink(fm) ((fm)->links &= ~LINK_TFM)
+@d unset_pslink(fm) ((fm)->links &= ~LINK_PS)
+@d has_tfmlink(fm) ((fm)->links & LINK_TFM)
+@d has_pslink(fm) ((fm)->links & LINK_PS)
+
+@c
+static int avl_do_entry (MP mp, fm_entry * fp, int mode) {
+ fm_entry *p;
+ void *a;
+ void **aa;
+ char s[128];
+
+ /* handle |tfm_name| link */
+
+ if (strcmp (fp->tfm_name, nontfm)) {
+ p = (fm_entry *) avl_find (mp->ps->tfm_tree, fp);
+ if (p != NULL) {
+ if (mode == FM_DUPIGNORE) {
+ snprintf(s,128,"fontmap entry for `%s' already exists, duplicates ignored",
+ fp->tfm_name);
+ mp_warn(mp,s);
+ goto exit;
+ } else { /* mode == |FM_REPLACE| / |FM_DELETE| */
+ if (mp_has_font_size(mp,p->tfm_num)) {
+ snprintf(s,128,
+ "fontmap entry for `%s' has been used, replace/delete not allowed",
+ fp->tfm_name);
+ mp_warn(mp,s);
+ goto exit;
+ }
+ a = avl_delete (mp->ps->tfm_tree, p);
+ assert (a != NULL);
+ unset_tfmlink (p);
+ if (!has_pslink (p))
+ delete_fm_entry (p);
+ }
+ }
+ if (mode != FM_DELETE) {
+ aa = avl_probe (mp->ps->tfm_tree, fp);
+ assert (aa != NULL);
+ set_tfmlink (fp);
+ }
+ }
+
+ /* handle |ps_name| link */
+
+ if (fp->ps_name != NULL) {
+ assert (fp->tfm_name != NULL);
+ p = (fm_entry *) avl_find (mp->ps->ps_tree, fp);
+ if (p != NULL) {
+ if (mode == FM_DUPIGNORE) {
+ snprintf(s,128,
+ "ps_name entry for `%s' already exists, duplicates ignored",
+ fp->ps_name);
+ mp_warn(mp,s);
+ goto exit;
+ } else { /* mode == |FM_REPLACE| / |FM_DELETE| */
+ if (mp_has_font_size(mp,p->tfm_num)) {
+ /* REPLACE/DELETE not allowed */
+ snprintf(s,128,
+ "fontmap entry for `%s' has been used, replace/delete not allowed",
+ p->tfm_name);
+ mp_warn(mp,s);
+ goto exit;
+ }
+ a = avl_delete (mp->ps->ps_tree, p);
+ assert (a != NULL);
+ unset_pslink (p);
+ if (!has_tfmlink (p))
+ delete_fm_entry (p);
+ }
+ }
+ if (mode != FM_DELETE) {
+ aa = avl_probe (mp->ps->ps_tree, fp);
+ assert (aa != NULL);
+ set_pslink (fp);
+ }
+ }
+ exit:
+ if (!has_tfmlink (fp) && !has_pslink (fp)) /* e. g. after |FM_DELETE| */
+ return 1; /* deallocation of |fm_entry| structure required */
+ else
+ return 0;
+}
+
+@ consistency check for map entry, with warn flag
+
+@c
+static int check_fm_entry (MP mp, fm_entry * fm, boolean warn) {
+ int a = 0;
+ char s[128];
+ assert (fm != NULL);
+ if (fm->ps_name != NULL) {
+ if (is_basefont (fm)) {
+ if (is_fontfile (fm) && !is_included (fm)) {
+ if (warn) {
+ snprintf(s,128, "invalid entry for `%s': "
+ "font file must be included or omitted for base fonts",
+ fm->tfm_name);
+ mp_warn(mp,s);
+ }
+ a += 1;
+ }
+ } else { /* not a base font */
+ /* if no font file given, drop this entry */
+ /* |if (!is_fontfile (fm)) {
+ if (warn) {
+ snprintf(s,128,
+ "invalid entry for `%s': font file missing",
+ fm->tfm_name);
+ mp_warn(mp,s);
+ }
+ a += 2;
+ }|
+ */
+ }
+ }
+ if (is_truetype (fm) && is_reencoded (fm) && !is_subsetted (fm)) {
+ if (warn) {
+ snprintf(s,128,
+ "invalid entry for `%s': only subsetted TrueType font can be reencoded",
+ fm->tfm_name);
+ mp_warn(mp,s);
+ }
+ a += 4;
+ }
+ if ((fm->slant != 0 || fm->extend != 0) &&
+ (is_truetype (fm))) {
+ if (warn) {
+ snprintf(s,128,
+ "invalid entry for `%s': "
+ "SlantFont/ExtendFont can be used only with embedded T1 fonts",
+ fm->tfm_name);
+ mp_warn(mp,s);
+ }
+ a += 8;
+ }
+ if (abs (fm->slant) > 1000) {
+ if (warn) {
+ snprintf(s,128,
+ "invalid entry for `%s': too big value of SlantFont (%g)",
+ fm->tfm_name, fm->slant / 1000.0);
+ mp_warn(mp,s);
+ }
+ a += 16;
+ }
+ if (abs (fm->extend) > 2000) {
+ if (warn) {
+ snprintf(s,128,
+ "invalid entry for `%s': too big value of ExtendFont (%g)",
+ fm->tfm_name, fm->extend / 1000.0);
+ mp_warn(mp,s);
+ }
+ a += 32;
+ }
+ if (fm->pid != -1 &&
+ !(is_truetype (fm) && is_included (fm) &&
+ is_subsetted (fm) && !is_reencoded (fm))) {
+ if (warn) {
+ snprintf(s,128,
+ "invalid entry for `%s': "
+ "PidEid can be used only with subsetted non-reencoded TrueType fonts",
+ fm->tfm_name);
+ mp_warn(mp,s);
+ }
+ a += 64;
+ }
+ return a;
+}
+
+@ returns true if s is one of the 14 std. font names; speed-trimmed.
+
+@c static boolean check_basefont (char *s) {
+ static const char *basefont_names[] = {
+ "Courier", /* 0:7 */
+ "Courier-Bold", /* 1:12 */
+ "Courier-Oblique", /* 2:15 */
+ "Courier-BoldOblique", /* 3:19 */
+ "Helvetica", /* 4:9 */
+ "Helvetica-Bold", /* 5:14 */
+ "Helvetica-Oblique", /* 6:17 */
+ "Helvetica-BoldOblique", /* 7:21 */
+ "Symbol", /* 8:6 */
+ "Times-Roman", /* 9:11 */
+ "Times-Bold", /* 10:10 */
+ "Times-Italic", /* 11:12 */
+ "Times-BoldItalic", /* 12:16 */
+ "ZapfDingbats" /* 13:12 */
+ };
+ static const int Index[] =
+ { -1, -1, -1, -1, -1, -1, 8, 0, -1, 4, 10, 9, -1, -1, 5, 2, 12, 6,
+ -1, 3, -1, 7
+ };
+ const size_t n = strlen (s);
+ int k = -1;
+ if (n > 21)
+ return false;
+ if (n == 12) { /* three names have length 12 */
+ switch (*s) {
+ case 'C':
+ k = 1; /* Courier-Bold */
+ break;
+ case 'T':
+ k = 11; /* Times-Italic */
+ break;
+ case 'Z':
+ k = 13; /* ZapfDingbats */
+ break;
+ default:
+ return false;
+ }
+ } else
+ k = Index[n];
+ if (k > -1 && !strcmp (basefont_names[k], s))
+ return true;
+ return false;
+}
+
+@
+@d is_cfg_comment(c) (c == 10 || c == '*' || c == '#' || c == ';' || c == '%')
+
+@c static void fm_scan_line (MP mp) {
+ int a, b, c, j, u = 0, v = 0;
+ float d;
+ fm_entry *fm;
+ char fm_line[FM_BUF_SIZE], buf[FM_BUF_SIZE];
+ char *p, *q, *r, *s;
+ char warn_s[128];
+ switch (mp->ps->mitem->type) {
+ case MAPFILE:
+ p = fm_line;
+ do {
+ c = fm_getchar (mp);
+ append_char_to_buf (c, p, fm_line, FM_BUF_SIZE);
+ } while (c != 10);
+ *(--p) = '\0';
+ r = fm_line;
+ break;
+ case MAPLINE:
+ r = mp->ps->mitem->map_line;
+ break;
+ default:
+ assert (0);
+ }
+ if (*r == '\0' || is_cfg_comment (*r))
+ return;
+ fm = new_fm_entry (mp);
+ read_field (r, q, buf);
+ set_field (tfm_name);
+ p = r;
+ read_field (r, q, buf);
+ if (*buf != '<' && *buf != '"')
+ set_field (ps_name);
+ else
+ r = p; /* unget the field */
+ if (isdigit (*r)) { /* font flags given */
+ fm->flags = atoi (r);
+ while (isdigit (*r))
+ r++;
+ }
+ while (1) { /* loop through "specials", encoding, font file */
+ skip (r, ' ');
+ switch (*r) {
+ case '\0':
+ goto DONE;
+ case '"': /* opening quote */
+ r++;
+ u = v = 0;
+ do {
+ skip (r, ' ');
+ if (sscanf (r, "%f %n", &d, &j) > 0) {
+ s = r + j; /* jump behind number, eat also blanks, if any */
+ if (*(s - 1) == 'E' || *(s - 1) == 'e')
+ s--; /* e. g. 0.5ExtendFont: \%f = 0.5E */
+ if (str_prefix (s, "SlantFont")) {
+ d *= 1000.0; /* correct rounding also for neg. numbers */
+ fm->slant = (integer) (d > 0 ? d + 0.5 : d - 0.5);
+ r = s + strlen ("SlantFont");
+ } else if (str_prefix (s, "ExtendFont")) {
+ d *= 1000.0;
+ fm->extend = (integer) (d > 0 ? d + 0.5 : d - 0.5);
+ if (fm->extend == 1000)
+ fm->extend = 0;
+ r = s + strlen ("ExtendFont");
+ } else { /* unknown name */
+ for (r = s;
+ *r != ' ' && *r != '"' && *r != '\0';
+ r++); /* jump over name */
+ c = *r; /* remember char for temporary end of string */
+ *r = '\0';
+ snprintf(warn_s,128,
+ "invalid entry for `%s': unknown name `%s' ignored",
+ fm->tfm_name, s);
+ mp_warn(mp,warn_s);
+ *r = c;
+ }
+ } else
+ for (; *r != ' ' && *r != '"' && *r != '\0'; r++);
+ }
+ while (*r == ' ');
+ if (*r == '"') /* closing quote */
+ r++;
+ else {
+ snprintf(warn_s,128,
+ "invalid entry for `%s': closing quote missing",
+ fm->tfm_name);
+ mp_warn(mp,warn_s);
+ goto bad_line;
+ }
+ break;
+ case 'P': /* handle cases for subfonts like 'PidEid=3,1' */
+ if (sscanf (r, "PidEid=%i, %i %n", &a, &b, &c) >= 2) {
+ fm->pid = a;
+ fm->eid = b;
+ r += c;
+ break;
+ }
+ default: /* encoding or font file specification */
+ a = b = 0;
+ if (*r == '<') {
+ a = *r++;
+ if (*r == '<' || *r == '[')
+ b = *r++;
+ }
+ read_field (r, q, buf);
+ /* encoding, formats: '8r.enc' or '<8r.enc' or '<[8r.enc' */
+ if (strlen (buf) > 4 && strcasecmp (strend (buf) - 4, ".enc") == 0) {
+ fm->encoding = mp_add_enc (mp, buf);
+ u = v = 0; /* u, v used if intervening blank: "<< foo" */
+ } else if (strlen (buf) > 0) { /* file name given */
+ /* font file, formats:
+ * subsetting: '<cmr10.pfa'
+ * no subsetting: '<<cmr10.pfa'
+ * no embedding: 'cmr10.pfa'
+ */
+ if (a == '<' || u == '<') {
+ set_included (fm);
+ if ((a == '<' && b == 0) || (a == 0 && v == 0))
+ set_subsetted (fm);
+ /* otherwise b == '<' (or '[') => no subsetting */
+ }
+ set_field (ff_name);
+ u = v = 0;
+ } else {
+ u = a;
+ v = b;
+ }
+ }
+ }
+ DONE:
+ if (fm->ps_name != NULL && check_basefont (fm->ps_name))
+ set_basefont (fm);
+ if (is_fontfile (fm)
+ && strcasecmp (strend (fm_fontfile (fm)) - 4, ".ttf") == 0)
+ set_truetype (fm);
+ if (check_fm_entry (mp,fm, true) != 0)
+ goto bad_line;
+ /*
+ Until here the map line has been completely scanned without errors;
+ fm points to a valid, freshly filled-out |fm_entry| structure.
+ Now follows the actual work of registering/deleting.
+ */
+ if (avl_do_entry (mp, fm, mp->ps->mitem->mode) == 0) /* if success */
+ return;
+ bad_line:
+ delete_fm_entry (fm);
+}
+
+@
+@c static void fm_read_info (MP mp) {
+ char *n;
+ char s[256];
+ if (mp->ps->tfm_tree == NULL)
+ create_avl_trees (mp);
+ if (mp->ps->mitem->map_line == NULL) /* nothing to do */
+ return;
+ mp->ps->mitem->lineno = 1;
+ switch (mp->ps->mitem->type) {
+ case MAPFILE:
+ n = mp->ps->mitem->map_line;
+ mp->ps->fm_file = (mp->open_file)(mp, n, "r", mp_filetype_fontmap);
+ if (!mp->ps->fm_file) {
+ snprintf(s,256,"cannot open font map file %s",n);
+ mp_warn(mp,s);
+ } else {
+ int save_selector = mp->selector;
+ mp_normalize_selector(mp);
+ mp_print (mp, "{");
+ mp_print (mp, n);
+ while (!fm_eof ()) {
+ fm_scan_line (mp);
+ mp->ps->mitem->lineno++;
+ }
+ fm_close ();
+ mp_print (mp,"}");
+ mp->selector = save_selector;
+ mp->ps->fm_file = NULL;
+ }
+ mp_xfree(n);
+ break;
+ case MAPLINE:
+ fm_scan_line (mp);
+ break;
+ default:
+ assert (0);
+ }
+ mp->ps->mitem->map_line = NULL; /* done with this line */
+ return;
+}
+
+@ @c static void init_fm (fm_entry * fm, font_number f) {
+ if (fm->tfm_num == null_font ) {
+ fm->tfm_num = f;
+ fm->tfm_avail = TFM_FOUND;
+ }
+}
+
+@ @<Declarations@>=
+static fm_entry * mp_fm_lookup (MP mp, font_number f);
+
+@ @c
+static fm_entry * mp_fm_lookup (MP mp, font_number f) {
+ char *tfm;
+ fm_entry *fm;
+ fm_entry tmp;
+ int e;
+ if (mp->ps->tfm_tree == NULL)
+ fm_read_info (mp); /* only to read default map file */
+ tfm = mp->font_name[f];
+ assert (strcmp (tfm, nontfm));
+ /* Look up for full <tfmname>[+-]<expand> */
+ tmp.tfm_name = tfm;
+ fm = (fm_entry *) avl_find (mp->ps->tfm_tree, &tmp);
+ if (fm != NULL) {
+ init_fm (fm, f);
+ return (fm_entry *) fm;
+ }
+ tfm = mk_base_tfm (mp, mp->font_name[f], &e);
+ if (tfm == NULL) /* not an expanded font, nothing to do */
+ return NULL;
+
+ tmp.tfm_name = tfm;
+ fm = (fm_entry *) avl_find (mp->ps->tfm_tree, &tmp);
+ if (fm != NULL) { /* found an entry with the base tfm name, e.g. cmr10 */
+ return (fm_entry *) fm; /* font expansion uses the base font */
+ }
+ return NULL;
+}
+
+@ Early check whether a font file exists. Used e. g. for replacing fonts
+ of embedded PDF files: Without font file, the font within the embedded
+ PDF-file is used. Search tree |ff_tree| is used in 1st instance, as it
+ may be faster than the |kpse_find_file()|, and |kpse_find_file()| is called
+ only once per font file name + expansion parameter. This might help
+ keeping speed, if many PDF pages with same fonts are to be embedded.
+
+ The |ff_tree| contains only font files, which are actually needed,
+ so this tree typically is much smaller than the |tfm_tree| or |ps_tree|.
+
+@c
+static ff_entry *check_ff_exist (MP mp, fm_entry * fm) {
+ ff_entry *ff;
+ ff_entry tmp;
+ void **aa;
+
+ assert (fm->ff_name != NULL);
+ tmp.ff_name = fm->ff_name;
+ ff = (ff_entry *) avl_find (mp->ps->ff_tree, &tmp);
+ if (ff == NULL) { /* not yet in database */
+ ff = new_ff_entry (mp);
+ ff->ff_name = mp_xstrdup (mp,fm->ff_name);
+ ff->ff_path = mp_xstrdup (mp,fm->ff_name);
+ aa = avl_probe (mp->ps->ff_tree, ff);
+ assert (aa != NULL);
+ }
+ return ff;
+}
+
+@ Process map file given by its name or map line contents. Items not
+beginning with [+-=] flush default map file, if it has not yet been
+read. Leading blanks and blanks immediately following [+-=] are ignored.
+
+
+@c static void mp_process_map_item (MP mp, char *s, int type) {
+ char *p;
+ int mode;
+ if (*s == ' ')
+ s++; /* ignore leading blank */
+ switch (*s) {
+ case '+': /* +mapfile.map, +mapline */
+ mode = FM_DUPIGNORE; /* insert entry, if it is not duplicate */
+ s++;
+ break;
+ case '=': /* =mapfile.map, =mapline */
+ mode = FM_REPLACE; /* try to replace earlier entry */
+ s++;
+ break;
+ case '-': /* -mapfile.map, -mapline */
+ mode = FM_DELETE; /* try to delete entry */
+ s++;
+ break;
+ default:
+ mode = FM_DUPIGNORE; /* like +, but also: */
+ mp_xfree(mp->ps->mitem->map_line);
+ mp->ps->mitem->map_line = NULL; /* flush default map file name */
+ }
+ if (*s == ' ')
+ s++; /* ignore blank after [+-=] */
+ p = s; /* map item starts here */
+ switch (type) {
+ case MAPFILE: /* remove blank at end */
+ while (*p != '\0' && *p != ' ')
+ p++;
+ *p = '\0';
+ break;
+ case MAPLINE: /* blank at end allowed */
+ break;
+ default:
+ assert (0);
+ }
+ if (mp->ps->mitem->map_line != NULL) /* read default map file first */
+ fm_read_info (mp);
+ if (*s != '\0') { /* only if real item to process */
+ mp->ps->mitem->mode = mode;
+ mp->ps->mitem->type = type;
+ mp->ps->mitem->map_line = s;
+ fm_read_info (mp);
+ }
+}
+
+@ @<Exported function headers@>=
+void mp_map_file (MP mp, str_number t);
+void mp_map_line (MP mp, str_number t);
+void mp_init_map_file (MP mp, int is_troff);
+
+@ @c
+void mp_map_file (MP mp, str_number t) {
+ char *s = mp_xstrdup(mp,mp_str (mp,t));
+ mp_process_map_item (mp, s, MAPFILE);
+ mp_xfree (s);
+}
+void mp_map_line (MP mp, str_number t) {
+ char *s = mp_xstrdup(mp,mp_str (mp,t));
+ mp_process_map_item (mp, s, MAPLINE);
+ mp_xfree (s);
+}
+
+@
+@c void mp_init_map_file (MP mp, int is_troff) {
+ char *r;
+ mp->ps->mitem = mp_xmalloc (mp,1,sizeof(mapitem));
+ mp->ps->mitem->mode = FM_DUPIGNORE;
+ mp->ps->mitem->type = MAPFILE;
+ mp->ps->mitem->map_line = NULL;
+ r = (mp->find_file)(mp,"mpost.map", "r", mp_filetype_fontmap);
+ if (r != NULL) {
+ mp_xfree(r);
+ mp->ps->mitem->map_line = mp_xstrdup (mp,"mpost.map");
+ } else {
+ if (is_troff) {
+ mp->ps->mitem->map_line = mp_xstrdup (mp,"troff.map");
+ } else {
+ mp->ps->mitem->map_line = mp_xstrdup (mp,"pdftex.map");
+ }
+ }
+}
+
+@ @<Dealloc variables@>=
+if (mp->ps->mitem!=NULL) {
+ mp_xfree(mp->ps->mitem->map_line);
+ mp_xfree(mp->ps->mitem);
+}
+
+@ cleaning up...
+
+@c
+static void destroy_fm_entry_tfm (void *pa, void *pb) {
+ fm_entry *fm;
+ (void)pb;
+ fm = (fm_entry *) pa;
+ if (!has_pslink (fm))
+ delete_fm_entry (fm);
+ else
+ unset_tfmlink (fm);
+}
+static void destroy_fm_entry_ps (void *pa, void *pb) {
+ fm_entry *fm;
+ (void)pb;
+ fm = (fm_entry *) pa;
+ if (!has_tfmlink (fm))
+ delete_fm_entry (fm);
+ else
+ unset_pslink (fm);
+}
+static void destroy_ff_entry (void *pa, void *pb) {
+ ff_entry *ff;
+ (void)pb;
+ ff = (ff_entry *) pa;
+ delete_ff_entry (ff);
+}
+
+@ @<Declarations@>=
+static void fm_free (MP mp);
+
+@ @c
+static void fm_free (MP mp) {
+ if (mp->ps->tfm_tree != NULL)
+ avl_destroy (mp->ps->tfm_tree, destroy_fm_entry_tfm);
+ if (mp->ps->ps_tree != NULL)
+ avl_destroy (mp->ps->ps_tree, destroy_fm_entry_ps);
+ if (mp->ps->ff_tree != NULL)
+ avl_destroy (mp->ps->ff_tree, destroy_ff_entry);
+}
+
+@ The file |ps_tab_file| gives a table of \TeX\ font names and corresponding
+PostScript names for fonts that do not have to be downloaded, i.e., fonts that
+can be used when |internal[prologues]>0|. Each line consists of a \TeX\ name,
+one or more spaces, a PostScript name, and possibly a space and some other junk.
+This routine reads the table, updates |font_ps_name| entries starting after
+|last_ps_fnum|, and sets |last_ps_fnum:=last_fnum|.
+
+@d ps_tab_name "psfonts.map" /* locates font name translation table */
+
+@<Declarations@>=
+static void mp_read_psname_table (MP mp) ;
+
+@ @c
+static void mp_read_psname_table (MP mp) {
+ font_number k;
+ if (mp->ps->mitem == NULL) {
+ mp->ps->mitem = mp_xmalloc (mp,1,sizeof(mapitem));
+ mp->ps->mitem->mode = FM_DUPIGNORE;
+ mp->ps->mitem->type = MAPFILE;
+ mp->ps->mitem->map_line = NULL;
+ }
+ mp->ps->mitem->map_line = mp_xstrdup (mp,ps_tab_name);
+ fm_read_info (mp);
+ for (k=mp->last_ps_fnum+1;k<=mp->last_fnum;k++) {
+ if (mp_has_fm_entry(mp, k, NULL)) {
+ mp->font_ps_name[k] = mp_fm_font_name(mp,k);
+ }
+ }
+ mp->last_ps_fnum=mp->last_fnum;
+}
+
+
+@ The traditional function is a lot shorter now.
+
+
+
+@* \[44c] Helper functions for Type1 fonts.
+
+@<Types...@>=
+typedef char char_entry;
+typedef unsigned char Byte;
+typedef Byte Bytef;
+
+@ @<Glob...@>=
+char_entry *char_ptr, *char_array;
+size_t char_limit;
+char *job_id_string;
+
+@ @<Set initial...@>=
+mp->ps->char_array = NULL;
+mp->ps->job_id_string = NULL;
+
+@
+@d SMALL_ARRAY_SIZE 256
+@d Z_NULL 0
+
+@c
+void mp_set_job_id (MP mp) {
+ char *name_string, *format_string, *s;
+ size_t slen;
+ int i;
+ if (mp->ps->job_id_string != NULL)
+ return;
+ if ( mp->job_name==NULL )
+ mp->job_name = mp_xstrdup(mp,"mpout");
+ name_string = mp_xstrdup (mp,mp->job_name);
+ format_string = mp_xstrdup (mp,mp->mem_ident);
+ slen = SMALL_BUF_SIZE +
+ strlen (name_string) +
+ strlen (format_string);
+ s = mp_xmalloc (mp,slen, sizeof (char));
+ i = snprintf (s, slen,
+ "%.4d/%.2d/%.2d %.2d:%.2d %s %s",
+ (mp->internal[mp_year]>>16),
+ (mp->internal[mp_month]>>16),
+ (mp->internal[mp_day]>>16),
+ (mp->internal[mp_time]>>16) / 60,
+ (mp->internal[mp_time]>>16) % 60,
+ name_string, format_string);
+ mp->ps->job_id_string = mp_xstrdup (mp,s);
+ mp_xfree (s);
+ mp_xfree (name_string);
+ mp_xfree (format_string);
+}
+static void fnstr_append (MP mp, const char *s) {
+ size_t l = strlen (s) + 1;
+ alloc_array (char, l, SMALL_ARRAY_SIZE);
+ strcat (mp->ps->char_ptr, s);
+ mp->ps->char_ptr = strend (mp->ps->char_ptr);
+}
+
+@ @<Exported function headers@>=
+void mp_set_job_id (MP mp) ;
+
+@ @<Dealloc variables@>=
+mp_xfree(mp->ps->job_id_string);
+
+@ this is not really a true crc32, but it should be just enough to keep
+ subsets prefixes somewhat disjunct
+
+@c
+static unsigned long crc32 (int oldcrc, const Byte *buf, int len) {
+ unsigned long ret = 0;
+ int i;
+ if (oldcrc==0)
+ ret = (23<<24)+(45<<16)+(67<<8)+89;
+ else
+ for (i=0;i<len;i++)
+ ret = (ret<<2)+buf[i];
+ return ret;
+}
+static boolean mp_char_marked (MP mp,font_number f, eight_bits c) {
+ integer b; /* |char_base[f]| */
+ b=mp->char_base[f];
+ if ( (c>=mp->font_bc[f])&&(c<=mp->font_ec[f])&&(mp->font_info[b+c].qqqq.b3!=0) )
+ return true;
+ else
+ return false;
+}
+
+static void make_subset_tag (MP mp, fm_entry * fm_cur, char **glyph_names, int tex_font)
+{
+ char tag[7];
+ unsigned long crc;
+ int i;
+ size_t l ;
+ if (mp->ps->job_id_string ==NULL)
+ mp_fatal_error(mp, "no job id!");
+ l = strlen (mp->ps->job_id_string) + 1;
+
+ alloc_array (char, l, SMALL_ARRAY_SIZE);
+ strcpy (mp->ps->char_array, mp->ps->job_id_string);
+ mp->ps->char_ptr = strend (mp->ps->char_array);
+ if (fm_cur->tfm_name != NULL) {
+ fnstr_append (mp," TFM name: ");
+ fnstr_append (mp,fm_cur->tfm_name);
+ }
+ fnstr_append (mp," PS name: ");
+ if (fm_cur->ps_name != NULL)
+ fnstr_append (mp,fm_cur->ps_name);
+ fnstr_append (mp," Encoding: ");
+ if (fm_cur->encoding != NULL && (fm_cur->encoding)->file_name != NULL)
+ fnstr_append (mp,(fm_cur->encoding)->file_name);
+ else
+ fnstr_append (mp,"built-in");
+ fnstr_append (mp," CharSet: ");
+ for (i = 0; i < 256; i++)
+ if (mp_char_marked (mp,tex_font, i) && glyph_names[i] != notdef) {
+ if (glyph_names[i]!=NULL) {
+ fnstr_append (mp,"/");
+ fnstr_append (mp,glyph_names[i]);
+ }
+ }
+ if (fm_cur->charset != NULL) {
+ fnstr_append (mp," Extra CharSet: ");
+ fnstr_append (mp, fm_cur->charset);
+ }
+ crc = crc32 (0L, Z_NULL, 0);
+ crc = crc32 (crc, (Bytef *) mp->ps->char_array, strlen (mp->ps->char_array));
+ /* we need to fit a 32-bit number into a string of 6 uppercase chars long;
+ * there are 26 uppercase chars ==> each char represents a number in range
+ * |0..25|. The maximal number that can be represented by the tag is
+ * $26^6 - 1$, which is a number between $2^28$ and $2^29$. Thus the bits |29..31|
+ * of the CRC must be dropped out.
+ */
+ for (i = 0; i < 6; i++) {
+ tag[i] = 'A' + crc % 26;
+ crc /= 26;
+ }
+ tag[6] = 0;
+ fm_cur->subset_tag = mp_xstrdup (mp,tag);
+}
+
+
+
+@
+@d external_enc() (fm_cur->encoding)->glyph_names
+@d is_used_char(c) mp_char_marked (mp, tex_font, c)
+@d end_last_eexec_line()
+ mp->ps->hexline_length = HEXLINE_WIDTH;
+ end_hexline(mp);
+ mp->ps->t1_eexec_encrypt = false
+@d t1_log(s) mp_print(mp,(char *)s)
+@d t1_putchar(c) wps_chr(c)
+@d embed_all_glyphs(tex_font) false
+@d t1_char(c) c
+@d extra_charset() mp->ps->dvips_extra_charset
+@d update_subset_tag()
+@d fixedcontent true
+
+@<Glob...@>=
+#define PRINTF_BUF_SIZE 1024
+char *dvips_extra_charset;
+char *cur_enc_name;
+unsigned char *grid;
+char *ext_glyph_names[256];
+char print_buf[PRINTF_BUF_SIZE];
+int t1_byte_waiting;
+
+@ @<Set initial ...@>=
+mp->ps->dvips_extra_charset=NULL;
+mp->ps->t1_byte_waiting=0;
+
+@
+@d t1_ungetchar(A) mp->ps->t1_byte_waiting=A
+@d t1_eof() (mp->eof_file)(mp,mp->ps->t1_file)
+@d t1_close() (mp->close_file)(mp,mp->ps->t1_file)
+@d valid_code(c) (c >= 0 && c < 256)
+
+@c
+int t1_getchar (MP mp) {
+ size_t len = 1;
+ unsigned char abyte=0;
+ void *byte_ptr = &abyte;
+ if (mp->ps->t1_byte_waiting) {
+ abyte = mp->ps->t1_byte_waiting;
+ mp->ps->t1_byte_waiting = 0;
+ } else {
+ (mp->read_binary_file)(mp,mp->ps->t1_file,&byte_ptr,&len);
+ }
+ return abyte;
+}
+
+@ @<Static variables in the outer block@>=
+static const char *standard_glyph_names[256] =
+ { notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ "space", "exclam", "quotedbl", "numbersign",
+ "dollar", "percent", "ampersand", "quoteright", "parenleft",
+ "parenright", "asterisk", "plus", "comma", "hyphen", "period",
+ "slash", "zero", "one", "two", "three", "four", "five", "six", "seven",
+ "eight", "nine", "colon", "semicolon", "less",
+ "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F",
+ "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
+ "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft",
+ "backslash", "bracketright", "asciicircum", "underscore",
+ "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
+ "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
+ "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde",
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, "exclamdown", "cent",
+ "sterling", "fraction", "yen", "florin", "section", "currency",
+ "quotesingle", "quotedblleft", "guillemotleft",
+ "guilsinglleft", "guilsinglright", "fi", "fl", notdef, "endash",
+ "dagger", "daggerdbl", "periodcentered", notdef,
+ "paragraph", "bullet", "quotesinglbase", "quotedblbase",
+ "quotedblright", "guillemotright", "ellipsis", "perthousand",
+ notdef, "questiondown", notdef, "grave", "acute", "circumflex",
+ "tilde", "macron", "breve", "dotaccent", "dieresis", notdef,
+ "ring", "cedilla", notdef, "hungarumlaut", "ogonek", "caron", "emdash",
+ notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, "AE", notdef, "ordfeminine", notdef, notdef,
+ notdef, notdef, "Lslash", "Oslash", "OE", "ordmasculine", notdef,
+ notdef, notdef, notdef, notdef, "ae", notdef, notdef,
+ notdef, "dotlessi", notdef, notdef, "lslash", "oslash", "oe",
+ "germandbls", notdef, notdef, notdef, notdef };
+static const char charstringname[] = "/CharStrings";
+
+@ @<Glob...@>=
+char **t1_glyph_names;
+char *t1_builtin_glyph_names[256];
+char charsetstr[0x4000];
+boolean read_encoding_only;
+int t1_encoding;
+
+@ @c
+#define T1_BUF_SIZE 0x10
+
+#define CS_HSTEM 1
+#define CS_VSTEM 3
+#define CS_VMOVETO 4
+#define CS_RLINETO 5
+#define CS_HLINETO 6
+#define CS_VLINETO 7
+#define CS_RRCURVETO 8
+#define CS_CLOSEPATH 9
+#define CS_CALLSUBR 10
+#define CS_RETURN 11
+#define CS_ESCAPE 12
+#define CS_HSBW 13
+#define CS_ENDCHAR 14
+#define CS_RMOVETO 21
+#define CS_HMOVETO 22
+#define CS_VHCURVETO 30
+#define CS_HVCURVETO 31
+#define CS_1BYTE_MAX (CS_HVCURVETO + 1)
+
+#define CS_DOTSECTION CS_1BYTE_MAX + 0
+#define CS_VSTEM3 CS_1BYTE_MAX + 1
+#define CS_HSTEM3 CS_1BYTE_MAX + 2
+#define CS_SEAC CS_1BYTE_MAX + 6
+#define CS_SBW CS_1BYTE_MAX + 7
+#define CS_DIV CS_1BYTE_MAX + 12
+#define CS_CALLOTHERSUBR CS_1BYTE_MAX + 16
+#define CS_POP CS_1BYTE_MAX + 17
+#define CS_SETCURRENTPOINT CS_1BYTE_MAX + 33
+#define CS_2BYTE_MAX (CS_SETCURRENTPOINT + 1)
+#define CS_MAX CS_2BYTE_MAX
+
+@ @<Types...@>=
+typedef unsigned char byte;
+typedef struct {
+ byte nargs; /* number of arguments */
+ boolean bottom; /* take arguments from bottom of stack? */
+ boolean clear; /* clear stack? */
+ boolean valid;
+} cc_entry; /* CharString Command */
+typedef struct {
+ char *glyph_name; /* glyph name (or notdef for Subrs entry) */
+ byte *data;
+ unsigned short len; /* length of the whole string */
+ unsigned short cslen; /* length of the encoded part of the string */
+ boolean is_used;
+ boolean valid;
+} cs_entry;
+
+@ @<Glob...@>=
+unsigned short t1_dr, t1_er;
+unsigned short t1_c1, t1_c2;
+unsigned short t1_cslen;
+short t1_lenIV;
+
+@ @<Set initial...@>=
+mp->ps->t1_c1 = 52845;
+mp->ps->t1_c2 = 22719;
+
+@ @<Types...@>=
+typedef char t1_line_entry;
+typedef char t1_buf_entry;
+
+@ @<Glob...@>=
+t1_line_entry *t1_line_ptr, *t1_line_array;
+size_t t1_line_limit;
+t1_buf_entry *t1_buf_ptr, *t1_buf_array;
+size_t t1_buf_limit;
+int cs_start;
+cs_entry *cs_tab, *cs_ptr, *cs_notdef;
+char *cs_dict_start, *cs_dict_end;
+int cs_count, cs_size, cs_size_pos;
+cs_entry *subr_tab;
+char *subr_array_start, *subr_array_end;
+int subr_max, subr_size, subr_size_pos;
+
+@ @<Set initial...@>=
+mp->ps->t1_line_array = NULL;
+mp->ps->t1_buf_array = NULL;
+
+@
+ This list contains the begin/end tokens commonly used in the
+ /Subrs array of a Type 1 font.
+
+@<Static variables in the outer block@>=
+static const char *cs_token_pairs_list[][2] = {
+ {" RD", "NP"},
+ {" -|", "|"},
+ {" RD", "noaccess put"},
+ {" -|", "noaccess put"},
+ {NULL, NULL}
+};
+
+@ @<Glob...@>=
+const char **cs_token_pair;
+boolean t1_pfa, t1_cs, t1_scan, t1_eexec_encrypt, t1_synthetic;
+int t1_in_eexec; /* 0 before eexec-encrypted, 1 during, 2 after */
+long t1_block_length;
+int last_hexbyte;
+void *t1_file;
+int hexline_length;
+
+@
+@d HEXLINE_WIDTH 64
+
+@<Set initial ...@>=
+mp->ps->hexline_length = 0;
+
+@
+@d t1_prefix(s) str_prefix(mp->ps->t1_line_array, s)
+@d t1_buf_prefix(s) str_prefix(mp->ps->t1_buf_array, s)
+@d t1_suffix(s) str_suffix(mp->ps->t1_line_array, mp->ps->t1_line_ptr, s)
+@d t1_buf_suffix(s) str_suffix(mp->ps->t1_buf_array, mp->ps->t1_buf_ptr, s)
+@d t1_charstrings() strstr(mp->ps->t1_line_array, charstringname)
+@d t1_subrs() t1_prefix("/Subrs")
+@d t1_end_eexec() t1_suffix("mark currentfile closefile")
+@d t1_cleartomark() t1_prefix("cleartomark")
+
+@d isdigit(A) ((A)>='0'&&(A)<='9')
+
+@c
+static void end_hexline (MP mp) {
+ if (mp->ps->hexline_length >= HEXLINE_WIDTH) {
+ wps_cr;
+ mp->ps->hexline_length = 0;
+ }
+}
+static void t1_check_pfa (MP mp) {
+ const int c = t1_getchar (mp);
+ mp->ps->t1_pfa = (c != 128) ? true : false;
+ t1_ungetchar (c);
+}
+static int t1_getbyte (MP mp)
+{
+ int c = t1_getchar (mp);
+ if (mp->ps->t1_pfa)
+ return c;
+ if (mp->ps->t1_block_length == 0) {
+ if (c != 128)
+ mp_fatal_error (mp, "invalid marker");
+ c = t1_getchar (mp);
+ if (c == 3) {
+ while (!t1_eof ())
+ t1_getchar (mp);
+ return EOF;
+ }
+ mp->ps->t1_block_length = t1_getchar (mp) & 0xff;
+ mp->ps->t1_block_length |= (t1_getchar (mp) & 0xff) << 8;
+ mp->ps->t1_block_length |= (t1_getchar (mp) & 0xff) << 16;
+ mp->ps->t1_block_length |= (t1_getchar (mp) & 0xff) << 24;
+ c = t1_getchar (mp);
+ }
+ mp->ps->t1_block_length--;
+ return c;
+}
+static int hexval (int c) {
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ else if (c >= '0' && c <= '9')
+ return c - '0';
+ else
+ return -1;
+}
+static byte edecrypt (MP mp, byte cipher) {
+ byte plain;
+ if (mp->ps->t1_pfa) {
+ while (cipher == 10 || cipher == 13)
+ cipher = t1_getbyte (mp);
+ mp->ps->last_hexbyte = cipher = (hexval (cipher) << 4) + hexval (t1_getbyte (mp));
+ }
+ plain = (cipher ^ (mp->ps->t1_dr >> 8));
+ mp->ps->t1_dr = (cipher + mp->ps->t1_dr) * mp->ps->t1_c1 + mp->ps->t1_c2;
+ return plain;
+}
+static byte cdecrypt (MP mp, byte cipher, unsigned short *cr)
+{
+ const byte plain = (cipher ^ (*cr >> 8));
+ *cr = (cipher + *cr) * mp->ps->t1_c1 + mp->ps->t1_c2;
+ return plain;
+}
+static byte eencrypt (MP mp, byte plain)
+{
+ const byte cipher = (plain ^ (mp->ps->t1_er >> 8));
+ mp->ps->t1_er = (cipher + mp->ps->t1_er) * mp->ps->t1_c1 + mp->ps->t1_c2;
+ return cipher;
+}
+
+static byte cencrypt (MP mp, byte plain, unsigned short *cr)
+{
+ const byte cipher = (plain ^ (*cr >> 8));
+ *cr = (cipher + *cr) * mp->ps->t1_c1 + mp->ps->t1_c2;
+ return cipher;
+}
+
+static char *eol (char *s) {
+ char *p = strend (s);
+ if (p - s > 1 && p[-1] != 10) {
+ *p++ = 10;
+ *p = 0;
+ }
+ return p;
+}
+static float t1_scan_num (MP mp, char *p, char **r)
+{
+ float f;
+ char s[128];
+ skip (p, ' ');
+ if (sscanf (p, "%g", &f) != 1) {
+ remove_eol (p, mp->ps->t1_line_array);
+ snprintf(s,128, "a number expected: `%s'", mp->ps->t1_line_array);
+ mp_fatal_error(mp,s);
+ }
+ if (r != NULL) {
+ for (; isdigit (*p) || *p == '.' ||
+ *p == 'e' || *p == 'E' || *p == '+' || *p == '-'; p++);
+ *r = p;
+ }
+ return f;
+}
+
+static boolean str_suffix (const char *begin_buf, const char *end_buf,
+ const char *s)
+{
+ const char *s1 = end_buf - 1, *s2 = strend (s) - 1;
+ if (*s1 == 10)
+ s1--;
+ while (s1 >= begin_buf && s2 >= s) {
+ if (*s1-- != *s2--)
+ return false;
+ }
+ return s2 < s;
+}
+
+@
+
+@d alloc_array(T, n, s) do {
+ if (mp->ps->T##_array == NULL) {
+ mp->ps->T##_limit = (s);
+ if ((unsigned)(n) > mp->ps->T##_limit)
+ mp->ps->T##_limit = (n);
+ mp->ps->T##_array = mp_xmalloc (mp,mp->ps->T##_limit,sizeof(T##_entry));
+ mp->ps->T##_ptr = mp->ps->T##_array;
+ }
+ else if ((unsigned)(mp->ps->T##_ptr - mp->ps->T##_array + (n)) > mp->ps->T##_limit) {
+ size_t last_ptr_index;
+ last_ptr_index = mp->ps->T##_ptr - mp->ps->T##_array;
+ mp->ps->T##_limit *= 2;
+ if ((unsigned)(mp->ps->T##_ptr - mp->ps->T##_array + (n)) > mp->ps->T##_limit)
+ mp->ps->T##_limit = mp->ps->T##_ptr - mp->ps->T##_array + (n);
+ mp->ps->T##_array = mp_xrealloc(mp,mp->ps->T##_array,mp->ps->T##_limit, sizeof(T##_entry));
+ mp->ps->T##_ptr = mp->ps->T##_array + last_ptr_index;
+ }
+} while (0)
+
+@d out_eexec_char(A) t1_outhex(mp,(A))
+
+@c
+static void t1_outhex (MP mp, byte b)
+{
+ static const char *hexdigits = "0123456789ABCDEF";
+ t1_putchar (hexdigits[b / 16]);
+ t1_putchar (hexdigits[b % 16]);
+ mp->ps->hexline_length += 2;
+ end_hexline (mp);
+}
+static void t1_getline (MP mp) {
+ int c, l, eexec_scan;
+ char *p;
+ static const char eexec_str[] = "currentfile eexec";
+ static int eexec_len = 17; /* |strlen(eexec_str)| */
+ RESTART:
+ if (t1_eof ())
+ mp_fatal_error (mp,"unexpected end of file");
+ mp->ps->t1_line_ptr = mp->ps->t1_line_array;
+ alloc_array (t1_line, 1, T1_BUF_SIZE);
+ mp->ps->t1_cslen = 0;
+ eexec_scan = 0;
+ c = t1_getbyte (mp);
+ if (c == EOF)
+ goto EXIT;
+ while (!t1_eof ()) {
+ if (mp->ps->t1_in_eexec == 1)
+ c = edecrypt (mp,c);
+ alloc_array (t1_line, 1, T1_BUF_SIZE);
+ append_char_to_buf (c, mp->ps->t1_line_ptr, mp->ps->t1_line_array, mp->ps->t1_line_limit);
+ if (mp->ps->t1_in_eexec == 0 && eexec_scan >= 0 && eexec_scan < eexec_len) {
+ if (mp->ps->t1_line_array[eexec_scan] == eexec_str[eexec_scan])
+ eexec_scan++;
+ else
+ eexec_scan = -1;
+ }
+ if (c == 10 || (mp->ps->t1_pfa && eexec_scan == eexec_len && c == 32))
+ break;
+ if (mp->ps->t1_cs && mp->ps->t1_cslen == 0 &&
+ (mp->ps->t1_line_ptr - mp->ps->t1_line_array > 4) &&
+ (t1_suffix (" RD ") || t1_suffix (" -| "))) {
+ p = mp->ps->t1_line_ptr - 5;
+ while (*p != ' ')
+ p--;
+ mp->ps->t1_cslen = l = t1_scan_num (mp, p + 1, 0);
+ mp->ps->cs_start = mp->ps->t1_line_ptr - mp->ps->t1_line_array;
+ /* |mp->ps->cs_start| is an index now */
+ alloc_array (t1_line, l, T1_BUF_SIZE);
+ while (l-- > 0)
+ *mp->ps->t1_line_ptr++ = edecrypt (mp,t1_getbyte (mp));
+ }
+ c = t1_getbyte (mp);
+ }
+ alloc_array (t1_line, 2, T1_BUF_SIZE); /* |append_eol| can append 2 chars */
+ append_eol (mp->ps->t1_line_ptr, mp->ps->t1_line_array, mp->ps->t1_line_limit);
+ if (mp->ps->t1_line_ptr - mp->ps->t1_line_array < 2)
+ goto RESTART;
+ if (eexec_scan == eexec_len)
+ mp->ps->t1_in_eexec = 1;
+ EXIT:
+ /* ensure that |mp->ps->t1_buf_array| has as much room as |t1_line_array| */
+ mp->ps->t1_buf_ptr = mp->ps->t1_buf_array;
+ alloc_array (t1_buf, mp->ps->t1_line_limit, mp->ps->t1_line_limit);
+}
+
+static void t1_putline (MP mp)
+{
+ char *p = mp->ps->t1_line_array;
+ if (mp->ps->t1_line_ptr - mp->ps->t1_line_array <= 1)
+ return;
+ if (mp->ps->t1_eexec_encrypt) {
+ while (p < mp->ps->t1_line_ptr)
+ out_eexec_char (eencrypt (mp,*p++));
+ } else {
+ while (p < mp->ps->t1_line_ptr)
+ t1_putchar (*p++);
+ }
+}
+
+static void t1_puts (MP mp, const char *s)
+{
+ if (s != mp->ps->t1_line_array)
+ strcpy (mp->ps->t1_line_array, s);
+ mp->ps->t1_line_ptr = strend (mp->ps->t1_line_array);
+ t1_putline (mp);
+}
+
+static void t1_printf (MP mp, const char *fmt, ...)
+{
+ va_list args;
+ va_start (args, fmt);
+ vsprintf (mp->ps->t1_line_array, fmt, args);
+ t1_puts (mp,mp->ps->t1_line_array);
+ va_end (args);
+}
+
+static void t1_init_params (MP mp, char *open_name_prefix,
+ char *cur_file_name) {
+ if ((open_name_prefix != NULL) && strlen(open_name_prefix)) {
+ t1_log (open_name_prefix);
+ t1_log (cur_file_name);
+ }
+ mp->ps->t1_lenIV = 4;
+ mp->ps->t1_dr = 55665;
+ mp->ps->t1_er = 55665;
+ mp->ps->t1_in_eexec = 0;
+ mp->ps->t1_cs = false;
+ mp->ps->t1_scan = true;
+ mp->ps->t1_synthetic = false;
+ mp->ps->t1_eexec_encrypt = false;
+ mp->ps->t1_block_length = 0;
+ t1_check_pfa (mp);
+}
+static void t1_close_font_file (MP mp, const char *close_name_suffix) {
+ if ((close_name_suffix != NULL) && strlen(close_name_suffix)) {
+ t1_log (close_name_suffix);
+ }
+ t1_close ();
+}
+
+static void t1_check_block_len (MP mp, boolean decrypt) {
+ int l, c;
+ char s[128];
+ if (mp->ps->t1_block_length == 0)
+ return;
+ c = t1_getbyte (mp);
+ if (decrypt)
+ c = edecrypt (mp,c);
+ l = mp->ps->t1_block_length;
+ if (!(l == 0 && (c == 10 || c == 13))) {
+ snprintf(s,128,"%i bytes more than expected were ignored", l+ 1);
+ mp_warn(mp,s);
+ while (l-- > 0)
+ t1_getbyte (mp);
+ }
+}
+static void t1_start_eexec (MP mp, fm_entry *fm_cur) {
+ int i;
+ if (!mp->ps->t1_pfa)
+ t1_check_block_len (mp, false);
+ for (mp->ps->t1_line_ptr = mp->ps->t1_line_array, i = 0; i < 4; i++) {
+ edecrypt (mp, t1_getbyte (mp));
+ *mp->ps->t1_line_ptr++ = 0;
+ }
+ mp->ps->t1_eexec_encrypt = true;
+ if (!mp->ps->read_encoding_only)
+ if (is_included (fm_cur))
+ t1_putline (mp); /* to put the first four bytes */
+}
+static void t1_stop_eexec (MP mp) {
+ int c;
+ end_last_eexec_line ();
+ if (!mp->ps->t1_pfa)
+ t1_check_block_len (mp,true);
+ else {
+ c = edecrypt (mp, t1_getbyte (mp));
+ if (!(c == 10 || c == 13)) {
+ if (mp->ps->last_hexbyte == 0)
+ t1_puts (mp,"00");
+ else
+ mp_warn (mp,"unexpected data after eexec");
+ }
+ }
+ mp->ps->t1_cs = false;
+ mp->ps->t1_in_eexec = 2;
+}
+static void t1_modify_fm (MP mp) {
+ mp->ps->t1_line_ptr = eol (mp->ps->t1_line_array);
+}
+
+static void t1_modify_italic (MP mp) {
+ mp->ps->t1_line_ptr = eol (mp->ps->t1_line_array);
+}
+
+@ @<Types...@>=
+typedef struct {
+ const char *pdfname;
+ const char *t1name;
+ float value;
+ boolean valid;
+} key_entry;
+
+@
+@d FONT_KEYS_NUM 11
+
+@<Declarations@>=
+static key_entry font_keys[FONT_KEYS_NUM] = {
+ {"Ascent", "Ascender", 0, false},
+ {"CapHeight", "CapHeight", 0, false},
+ {"Descent", "Descender", 0, false},
+ {"FontName", "FontName", 0, false},
+ {"ItalicAngle", "ItalicAngle", 0, false},
+ {"StemV", "StdVW", 0, false},
+ {"XHeight", "XHeight", 0, false},
+ {"FontBBox", "FontBBox", 0, false},
+ {"", "", 0, false},
+ {"", "", 0, false},
+ {"", "", 0, false}
+};
+
+
+@
+@d ASCENT_CODE 0
+@d CAPHEIGHT_CODE 1
+@d DESCENT_CODE 2
+@d FONTNAME_CODE 3
+@d ITALIC_ANGLE_CODE 4
+@d STEMV_CODE 5
+@d XHEIGHT_CODE 6
+@d FONTBBOX1_CODE 7
+@d FONTBBOX2_CODE 8
+@d FONTBBOX3_CODE 9
+@d FONTBBOX4_CODE 10
+@d MAX_KEY_CODE (FONTBBOX1_CODE + 1)
+
+@c
+static void t1_scan_keys (MP mp, int tex_font,fm_entry *fm_cur) {
+ int i, k;
+ char *p, *r;
+ key_entry *key;
+ if (fm_extend (fm_cur) != 0 || fm_slant (fm_cur) != 0) {
+ if (t1_prefix ("/FontMatrix")) {
+ t1_modify_fm (mp);
+ return;
+ }
+ if (t1_prefix ("/ItalicAngle")) {
+ t1_modify_italic (mp);
+ return;
+ }
+ }
+ if (t1_prefix ("/FontType")) {
+ p = mp->ps->t1_line_array + strlen ("FontType") + 1;
+ if ((i = t1_scan_num (mp,p, 0)) != 1) {
+ char s[128];
+ snprintf(s,125,"Type%d fonts unsupported by metapost", i);
+ mp_fatal_error(mp,s);
+ }
+ return;
+ }
+ for (key = font_keys; key - font_keys < MAX_KEY_CODE; key++)
+ if (str_prefix (mp->ps->t1_line_array + 1, key->t1name))
+ break;
+ if (key - font_keys == MAX_KEY_CODE)
+ return;
+ key->valid = true;
+ p = mp->ps->t1_line_array + strlen (key->t1name) + 1;
+ skip (p, ' ');
+ if ((k = key - font_keys) == FONTNAME_CODE) {
+ if (*p != '/') {
+ char s[128];
+ remove_eol (p, mp->ps->t1_line_array);
+ snprintf(s,128,"a name expected: `%s'", mp->ps->t1_line_array);
+ mp_fatal_error(mp,s);
+ }
+ r = ++p; /* skip the slash */
+ if (is_included (fm_cur)) {
+ /* save the fontname */
+ strncpy (mp->ps->fontname_buf, p, FONTNAME_BUF_SIZE);
+ for (i=0; mp->ps->fontname_buf[i] != 10; i++);
+ mp->ps->fontname_buf[i]=0;
+
+ if(is_subsetted (fm_cur)) {
+ if (fm_cur->encoding!=NULL && fm_cur->encoding->glyph_names!=NULL)
+ make_subset_tag (mp,fm_cur, fm_cur->encoding->glyph_names, tex_font);
+ else
+ make_subset_tag (mp,fm_cur, mp->ps->t1_builtin_glyph_names, tex_font);
+
+ alloc_array (t1_line, (r-mp->ps->t1_line_array+6+1+strlen(mp->ps->fontname_buf)+1),
+ T1_BUF_SIZE);
+ strncpy (r, fm_cur->subset_tag , 6);
+ *(r+6) = '-';
+ strncpy (r+7, mp->ps->fontname_buf, strlen(mp->ps->fontname_buf)+1);
+ mp->ps->t1_line_ptr = eol (r);
+ } else {
+ /* |for (q = p; *q != ' ' && *q != 10; *q++);|*/
+ /*|*q = 0;|*/
+ mp->ps->t1_line_ptr = eol (r);
+ }
+ }
+ return;
+ }
+ if ((k == STEMV_CODE || k == FONTBBOX1_CODE)
+ && (*p == '[' || *p == '{'))
+ p++;
+ if (k == FONTBBOX1_CODE) {
+ for (i = 0; i < 4; i++) {
+ key[i].value = t1_scan_num (mp, p, &r);
+ p = r;
+ }
+ return;
+ }
+ key->value = t1_scan_num (mp, p, 0);
+}
+static void t1_scan_param (MP mp, int tex_font,fm_entry *fm_cur)
+{
+ static const char *lenIV = "/lenIV";
+ if (!mp->ps->t1_scan || *mp->ps->t1_line_array != '/')
+ return;
+ if (t1_prefix (lenIV)) {
+ mp->ps->t1_lenIV = t1_scan_num (mp,mp->ps->t1_line_array + strlen (lenIV), 0);
+ return;
+ }
+ t1_scan_keys (mp, tex_font,fm_cur);
+}
+static void copy_glyph_names (MP mp, char **glyph_names, int a, int b) {
+ if (glyph_names[b] != notdef) {
+ mp_xfree (glyph_names[b]);
+ glyph_names[b] = (char *) notdef;
+ }
+ if (glyph_names[a] != notdef) {
+ glyph_names[b] = mp_xstrdup (mp,glyph_names[a]);
+ }
+}
+static void t1_builtin_enc (MP mp) {
+ int i, a, b, c, counter = 0;
+ char *r, *p;
+ /*
+ * At this moment "/Encoding" is the prefix of |mp->ps->t1_line_array|
+ */
+ if (t1_suffix ("def")) { /* predefined encoding */
+ sscanf (mp->ps->t1_line_array + strlen ("/Encoding"), "%256s", mp->ps->t1_buf_array);
+ if (strcmp (mp->ps->t1_buf_array, "StandardEncoding") == 0) {
+ for (i = 0; i < 256; i++)
+ if (standard_glyph_names[i] == notdef)
+ mp->ps->t1_builtin_glyph_names[i] = (char *) notdef;
+ else
+ mp->ps->t1_builtin_glyph_names[i] =
+ mp_xstrdup (mp,standard_glyph_names[i]);
+ mp->ps->t1_encoding = ENC_STANDARD;
+ } else {
+ char s[128];
+ snprintf(s,128, "cannot subset font (unknown predefined encoding `%s')",
+ mp->ps->t1_buf_array);
+ mp_fatal_error(mp,s);
+ }
+ return;
+ } else
+ mp->ps->t1_encoding = ENC_BUILTIN;
+ /*
+ * At this moment "/Encoding" is the prefix of |mp->ps->t1_line_array|, and the encoding is
+ * not a predefined encoding
+ *
+ * We have two possible forms of Encoding vector. The first case is
+ *
+ * /Encoding [/a /b /c...] readonly def
+ *
+ * and the second case can look like
+ *
+ * /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for
+ * dup 0 /x put
+ * dup 1 /y put
+ * ...
+ * readonly def
+ */
+ for (i = 0; i < 256; i++)
+ mp->ps->t1_builtin_glyph_names[i] = (char *) notdef;
+ if (t1_prefix ("/Encoding [") || t1_prefix ("/Encoding[")) { /* the first case */
+ r = strchr (mp->ps->t1_line_array, '[') + 1;
+ skip (r, ' ');
+ for (;;) {
+ while (*r == '/') {
+ for (p = mp->ps->t1_buf_array, r++;
+ *r != 32 && *r != 10 && *r != ']' && *r != '/';
+ *p++ = *r++);
+ *p = 0;
+ skip (r, ' ');
+ if (counter > 255) {
+ mp_fatal_error
+ (mp, "encoding vector contains more than 256 names");
+ }
+ if (strcmp (mp->ps->t1_buf_array, notdef) != 0)
+ mp->ps->t1_builtin_glyph_names[counter] = mp_xstrdup (mp,mp->ps->t1_buf_array);
+ counter++;
+ }
+ if (*r != 10 && *r != '%') {
+ if (str_prefix (r, "] def")
+ || str_prefix (r, "] readonly def"))
+ break;
+ else {
+ char s[128];
+ remove_eol (r, mp->ps->t1_line_array);
+ snprintf(s,128,"a name or `] def' or `] readonly def' expected: `%s'",
+ mp->ps->t1_line_array);
+ mp_fatal_error(mp,s);
+ }
+ }
+ t1_getline (mp);
+ r = mp->ps->t1_line_array;
+ }
+ } else { /* the second case */
+ p = strchr (mp->ps->t1_line_array, 10);
+ for (;;) {
+ if (*p == 10) {
+ t1_getline (mp);
+ p = mp->ps->t1_line_array;
+ }
+ /*
+ check for `dup <index> <glyph> put'
+ */
+ if (sscanf (p, "dup %i%256s put", &i, mp->ps->t1_buf_array) == 2 &&
+ *mp->ps->t1_buf_array == '/' && valid_code (i)) {
+ if (strcmp (mp->ps->t1_buf_array + 1, notdef) != 0)
+ mp->ps->t1_builtin_glyph_names[i] =
+ mp_xstrdup (mp,mp->ps->t1_buf_array + 1);
+ p = strstr (p, " put") + strlen (" put");
+ skip (p, ' ');
+ }
+ /*
+ check for `dup dup <to> exch <from> get put'
+ */
+ else if (sscanf (p, "dup dup %i exch %i get put", &b, &a) == 2
+ && valid_code (a) && valid_code (b)) {
+ copy_glyph_names (mp,mp->ps->t1_builtin_glyph_names, a, b);
+ p = strstr (p, " get put") + strlen (" get put");
+ skip (p, ' ');
+ }
+ /*
+ check for `dup dup <from> <size> getinterval <to> exch putinterval'
+ */
+ else if (sscanf
+ (p, "dup dup %i %i getinterval %i exch putinterval",
+ &a, &c, &b) == 3 && valid_code (a) && valid_code (b)
+ && valid_code (c)) {
+ for (i = 0; i < c; i++)
+ copy_glyph_names (mp,mp->ps->t1_builtin_glyph_names, a + i, b + i);
+ p = strstr (p, " putinterval") + strlen (" putinterval");
+ skip (p, ' ');
+ }
+ /*
+ check for `def' or `readonly def'
+ */
+ else if ((p == mp->ps->t1_line_array || (p > mp->ps->t1_line_array && p[-1] == ' '))
+ && strcmp (p, "def\n") == 0)
+ return;
+ /*
+ skip an unrecognizable word
+ */
+ else {
+ while (*p != ' ' && *p != 10)
+ p++;
+ skip (p, ' ');
+ }
+ }
+ }
+}
+
+static void t1_check_end (MP mp) {
+ if (t1_eof ())
+ return;
+ t1_getline (mp);
+ if (t1_prefix ("{restore}"))
+ t1_putline (mp);
+}
+
+@ @<Types...@>=
+typedef struct {
+ char *ff_name; /* base name of font file */
+ char *ff_path; /* full path to font file */
+} ff_entry;
+
+@ @c
+static boolean t1_open_fontfile (MP mp, fm_entry *fm_cur,const char *open_name_prefix) {
+ ff_entry *ff;
+ ff = check_ff_exist (mp, fm_cur);
+ if (ff->ff_path != NULL) {
+ mp->ps->t1_file = (mp->open_file)(mp,ff->ff_path, "r", mp_filetype_font);
+ } else {
+ mp_warn (mp, "cannot open Type 1 font file for reading");
+ return false;
+ }
+ t1_init_params (mp,(char *)open_name_prefix,fm_cur->ff_name);
+ mp->ps->fontfile_found = true;
+ return true;
+}
+
+static void t1_scan_only (MP mp, int tex_font, fm_entry *fm_cur) {
+ do {
+ t1_getline (mp);
+ t1_scan_param (mp,tex_font, fm_cur);
+ }
+ while (mp->ps->t1_in_eexec == 0);
+ t1_start_eexec (mp,fm_cur);
+ do {
+ t1_getline (mp);
+ t1_scan_param (mp,tex_font, fm_cur);
+ }
+ while (!(t1_charstrings () || t1_subrs ()));
+}
+
+static void t1_include (MP mp, int tex_font, fm_entry *fm_cur) {
+ do {
+ t1_getline (mp);
+ t1_scan_param (mp,tex_font, fm_cur);
+ t1_putline (mp);
+ }
+ while (mp->ps->t1_in_eexec == 0);
+ t1_start_eexec (mp,fm_cur);
+ do {
+ t1_getline (mp);
+ t1_scan_param (mp,tex_font, fm_cur);
+ t1_putline (mp);
+ }
+ while (!(t1_charstrings () || t1_subrs ()));
+ mp->ps->t1_cs = true;
+ do {
+ t1_getline (mp);
+ t1_putline (mp);
+ }
+ while (!t1_end_eexec ());
+ t1_stop_eexec (mp);
+ if (fixedcontent) { /* copy 512 zeros (not needed for PDF) */
+ do {
+ t1_getline (mp);
+ t1_putline (mp);
+ }
+ while (!t1_cleartomark ());
+ t1_check_end (mp); /* write "{restore}if" if found */
+ }
+}
+
+@
+@d check_subr(SUBR) if (SUBR >= mp->ps->subr_size || SUBR < 0) {
+ char s[128];
+ snprintf(s,128,"Subrs array: entry index out of range (%i)",SUBR);
+ mp_fatal_error(mp,s);
+ }
+
+@c
+static const char **check_cs_token_pair (MP mp) {
+ const char **p = (const char **) cs_token_pairs_list;
+ for (; p[0] != NULL; ++p)
+ if (t1_buf_prefix (p[0]) && t1_buf_suffix (p[1]))
+ return p;
+ return NULL;
+}
+
+static void cs_store (MP mp, boolean is_subr) {
+ char *p;
+ cs_entry *ptr;
+ int subr;
+ for (p = mp->ps->t1_line_array, mp->ps->t1_buf_ptr = mp->ps->t1_buf_array; *p != ' ';
+ *mp->ps->t1_buf_ptr++ = *p++);
+ *mp->ps->t1_buf_ptr = 0;
+ if (is_subr) {
+ subr = t1_scan_num (mp, p + 1, 0);
+ check_subr (subr);
+ ptr = mp->ps->subr_tab + subr;
+ } else {
+ ptr = mp->ps->cs_ptr++;
+ if (mp->ps->cs_ptr - mp->ps->cs_tab > mp->ps->cs_size) {
+ char s[128];
+ snprintf(s,128,"CharStrings dict: more entries than dict size (%i)",mp->ps->cs_size);
+ mp_fatal_error(mp,s);
+ }
+ if (strcmp (mp->ps->t1_buf_array + 1, notdef) == 0) /* skip the slash */
+ ptr->glyph_name = (char *) notdef;
+ else
+ ptr->glyph_name = mp_xstrdup (mp,mp->ps->t1_buf_array + 1);
+ }
+ /* copy " RD " + cs data to |mp->ps->t1_buf_array| */
+ memcpy (mp->ps->t1_buf_array, mp->ps->t1_line_array + mp->ps->cs_start - 4,
+ (unsigned) (mp->ps->t1_cslen + 4));
+ /* copy the end of cs data to |mp->ps->t1_buf_array| */
+ for (p = mp->ps->t1_line_array + mp->ps->cs_start + mp->ps->t1_cslen, mp->ps->t1_buf_ptr =
+ mp->ps->t1_buf_array + mp->ps->t1_cslen + 4; *p != 10; *mp->ps->t1_buf_ptr++ = *p++);
+ *mp->ps->t1_buf_ptr++ = 10;
+ if (is_subr && mp->ps->cs_token_pair == NULL)
+ mp->ps->cs_token_pair = check_cs_token_pair (mp);
+ ptr->len = mp->ps->t1_buf_ptr - mp->ps->t1_buf_array;
+ ptr->cslen = mp->ps->t1_cslen;
+ ptr->data = mp_xmalloc (mp,ptr->len , sizeof (byte));
+ memcpy (ptr->data, mp->ps->t1_buf_array, ptr->len);
+ ptr->valid = true;
+}
+
+#define store_subr(mp) cs_store(mp,true)
+#define store_cs(mp) cs_store(mp,false)
+
+#define CC_STACK_SIZE 24
+
+static integer cc_stack[CC_STACK_SIZE], *stack_ptr = cc_stack;
+static cc_entry cc_tab[CS_MAX];
+static boolean is_cc_init = false;
+
+
+#define cc_pop(N) \
+ if (stack_ptr - cc_stack < (N)) \
+ stack_error(N); \
+ stack_ptr -= N
+
+#define stack_error(N) { \
+ char s[256]; \
+ snprintf(s,255,"CharString: invalid access (%i) to stack (%i entries)", \
+ (int) N, (int)(stack_ptr - cc_stack)); \
+ mp_warn(mp,s); \
+ goto cs_error; \
+}
+
+
+#define cc_get(N) ((N) < 0 ? *(stack_ptr + (N)) : *(cc_stack + (N)))
+
+#define cc_push(V) *stack_ptr++ = V
+#define cc_clear() stack_ptr = cc_stack
+
+#define set_cc(N, B, A, C) \
+ cc_tab[N].nargs = A; \
+ cc_tab[N].bottom = B; \
+ cc_tab[N].clear = C; \
+ cc_tab[N].valid = true
+
+static void cc_init (void) {
+ int i;
+ if (is_cc_init)
+ return;
+ for (i = 0; i < CS_MAX; i++)
+ cc_tab[i].valid = false;
+ set_cc (CS_HSTEM, true, 2, true);
+ set_cc (CS_VSTEM, true, 2, true);
+ set_cc (CS_VMOVETO, true, 1, true);
+ set_cc (CS_RLINETO, true, 2, true);
+ set_cc (CS_HLINETO, true, 1, true);
+ set_cc (CS_VLINETO, true, 1, true);
+ set_cc (CS_RRCURVETO, true, 6, true);
+ set_cc (CS_CLOSEPATH, false, 0, true);
+ set_cc (CS_CALLSUBR, false, 1, false);
+ set_cc (CS_RETURN, false, 0, false);
+ /*
+ |set_cc(CS_ESCAPE, false, 0, false);|
+ */
+ set_cc (CS_HSBW, true, 2, true);
+ set_cc (CS_ENDCHAR, false, 0, true);
+ set_cc (CS_RMOVETO, true, 2, true);
+ set_cc (CS_HMOVETO, true, 1, true);
+ set_cc (CS_VHCURVETO, true, 4, true);
+ set_cc (CS_HVCURVETO, true, 4, true);
+ set_cc (CS_DOTSECTION, false, 0, true);
+ set_cc (CS_VSTEM3, true, 6, true);
+ set_cc (CS_HSTEM3, true, 6, true);
+ set_cc (CS_SEAC, true, 5, true);
+ set_cc (CS_SBW, true, 4, true);
+ set_cc (CS_DIV, false, 2, false);
+ set_cc (CS_CALLOTHERSUBR, false, 0, false);
+ set_cc (CS_POP, false, 0, false);
+ set_cc (CS_SETCURRENTPOINT, true, 2, true);
+ is_cc_init = true;
+}
+
+@
+
+@d cs_getchar(mp) cdecrypt(mp,*data++, &cr)
+
+@d mark_subr(mp,n) cs_mark(mp,0, n)
+@d mark_cs(mp,s) cs_mark(mp,s, 0)
+@d SMALL_BUF_SIZE 256
+
+@c
+static void cs_warn (MP mp, const char *cs_name, int subr, const char *fmt, ...) {
+ char buf[SMALL_BUF_SIZE];
+ char s[300];
+ va_list args;
+ va_start (args, fmt);
+ vsprintf (buf, fmt, args);
+ va_end (args);
+ if (cs_name == NULL) {
+ snprintf(s,299,"Subr (%i): %s", (int) subr, buf);
+ } else {
+ snprintf(s,299,"CharString (/%s): %s", cs_name, buf);
+ }
+ mp_warn(mp,s);
+}
+
+static void cs_mark (MP mp, const char *cs_name, int subr)
+{
+ byte *data;
+ int i, b, cs_len;
+ integer a, a1, a2;
+ unsigned short cr;
+ static integer lastargOtherSubr3 = 3; /* the argument of last call to
+ OtherSubrs[3] */
+ cs_entry *ptr;
+ cc_entry *cc;
+ if (cs_name == NULL) {
+ check_subr (subr);
+ ptr = mp->ps->subr_tab + subr;
+ if (!ptr->valid)
+ return;
+ } else {
+ if (mp->ps->cs_notdef != NULL &&
+ (cs_name == notdef || strcmp (cs_name, notdef) == 0))
+ ptr = mp->ps->cs_notdef;
+ else {
+ for (ptr = mp->ps->cs_tab; ptr < mp->ps->cs_ptr; ptr++)
+ if (strcmp (ptr->glyph_name, cs_name) == 0)
+ break;
+ if (ptr == mp->ps->cs_ptr) {
+ char s[128];
+ snprintf (s,128,"glyph `%s' undefined", cs_name);
+ mp_warn(mp,s);
+ return;
+ }
+ if (ptr->glyph_name == notdef)
+ mp->ps->cs_notdef = ptr;
+ }
+ }
+ /* only marked CharString entries and invalid entries can be skipped;
+ valid marked subrs must be parsed to keep the stack in sync */
+ if (!ptr->valid || (ptr->is_used && cs_name != NULL))
+ return;
+ ptr->is_used = true;
+ cr = 4330;
+ cs_len = ptr->cslen;
+ data = ptr->data + 4;
+ for (i = 0; i < mp->ps->t1_lenIV; i++, cs_len--)
+ cs_getchar (mp);
+ while (cs_len > 0) {
+ --cs_len;
+ b = cs_getchar (mp);
+ if (b >= 32) {
+ if (b <= 246)
+ a = b - 139;
+ else if (b <= 250) {
+ --cs_len;
+ a = ((b - 247) << 8) + 108 + cs_getchar (mp);
+ } else if (b <= 254) {
+ --cs_len;
+ a = -((b - 251) << 8) - 108 - cs_getchar (mp);
+ } else {
+ cs_len -= 4;
+ a = (cs_getchar (mp) & 0xff) << 24;
+ a |= (cs_getchar (mp) & 0xff) << 16;
+ a |= (cs_getchar (mp) & 0xff) << 8;
+ a |= (cs_getchar (mp) & 0xff) << 0;
+ if (sizeof (integer) > 4 && (a & 0x80000000))
+ a |= ~0x7FFFFFFF;
+ }
+ cc_push (a);
+ } else {
+ if (b == CS_ESCAPE) {
+ b = cs_getchar (mp) + CS_1BYTE_MAX;
+ cs_len--;
+ }
+ if (b >= CS_MAX) {
+ cs_warn (mp,cs_name, subr, "command value out of range: %i",
+ (int) b);
+ goto cs_error;
+ }
+ cc = cc_tab + b;
+ if (!cc->valid) {
+ cs_warn (mp,cs_name, subr, "command not valid: %i", (int) b);
+ goto cs_error;
+ }
+ if (cc->bottom) {
+ if (stack_ptr - cc_stack < cc->nargs)
+ cs_warn (mp,cs_name, subr,
+ "less arguments on stack (%i) than required (%i)",
+ (int) (stack_ptr - cc_stack), (int) cc->nargs);
+ else if (stack_ptr - cc_stack > cc->nargs)
+ cs_warn (mp,cs_name, subr,
+ "more arguments on stack (%i) than required (%i)",
+ (int) (stack_ptr - cc_stack), (int) cc->nargs);
+ }
+ switch (cc - cc_tab) {
+ case CS_CALLSUBR:
+ a1 = cc_get (-1);
+ cc_pop (1);
+ mark_subr (mp,a1);
+ if (!mp->ps->subr_tab[a1].valid) {
+ cs_warn (mp,cs_name, subr, "cannot call subr (%i)", (int) a1);
+ goto cs_error;
+ }
+ break;
+ case CS_DIV:
+ cc_pop (2);
+ cc_push (0);
+ break;
+ case CS_CALLOTHERSUBR:
+ if (cc_get (-1) == 3)
+ lastargOtherSubr3 = cc_get (-3);
+ a1 = cc_get (-2) + 2;
+ cc_pop (a1);
+ break;
+ case CS_POP:
+ cc_push (lastargOtherSubr3);
+ /* the only case when we care about the value being pushed onto
+ stack is when POP follows CALLOTHERSUBR (changing hints by
+ OtherSubrs[3])
+ */
+ break;
+ case CS_SEAC:
+ a1 = cc_get (3);
+ a2 = cc_get (4);
+ cc_clear ();
+ mark_cs (mp,standard_glyph_names[a1]);
+ mark_cs (mp,standard_glyph_names[a2]);
+ break;
+ default:
+ if (cc->clear)
+ cc_clear ();
+ }
+ }
+ }
+ return;
+ cs_error: /* an error occured during parsing */
+ cc_clear ();
+ ptr->valid = false;
+ ptr->is_used = false;
+}
+
+static void t1_subset_ascii_part (MP mp, int tex_font, fm_entry *fm_cur)
+{
+ int i, j;
+ t1_getline (mp);
+ while (!t1_prefix ("/Encoding")) {
+ t1_scan_param (mp,tex_font, fm_cur);
+ t1_putline (mp);
+ t1_getline (mp);
+ }
+ t1_builtin_enc (mp);
+ if (is_reencoded (fm_cur))
+ mp->ps->t1_glyph_names = external_enc ();
+ else
+ mp->ps->t1_glyph_names = mp->ps->t1_builtin_glyph_names;
+ /*
+ |if (is_included (fm_cur) && is_subsetted (fm_cur)) {
+ make_subset_tag (fm_cur, t1_glyph_names, tex_font);
+ update_subset_tag ();
+ }|
+ */
+ if ((!is_subsetted (fm_cur)) && mp->ps->t1_encoding == ENC_STANDARD)
+ t1_puts (mp,"/Encoding StandardEncoding def\n");
+ else {
+ t1_puts
+ (mp,"/Encoding 256 array\n0 1 255 {1 index exch /.notdef put} for\n");
+ for (i = 0, j = 0; i < 256; i++) {
+ if (is_used_char (i) && mp->ps->t1_glyph_names[i] != notdef) {
+ j++;
+ t1_printf (mp,"dup %i /%s put\n", (int) t1_char (i),
+ mp->ps->t1_glyph_names[i]);
+ }
+ }
+ /* We didn't mark anything for the Encoding array. */
+ /* We add "dup 0 /.notdef put" for compatibility */
+ /* with Acrobat 5.0. */
+ if (j == 0)
+ t1_puts (mp,"dup 0 /.notdef put\n");
+ t1_puts (mp,"readonly def\n");
+ }
+ do {
+ t1_getline (mp);
+ t1_scan_param (mp,tex_font, fm_cur);
+ if (!t1_prefix ("/UniqueID")) /* ignore UniqueID for subsetted fonts */
+ t1_putline (mp);
+ }
+ while (mp->ps->t1_in_eexec == 0);
+}
+
+#define t1_subr_flush(mp) t1_flush_cs(mp,true)
+#define t1_cs_flush(mp) t1_flush_cs(mp,false)
+
+static void cs_init (MP mp) {
+ mp->ps->cs_ptr = mp->ps->cs_tab = NULL;
+ mp->ps->cs_dict_start = mp->ps->cs_dict_end = NULL;
+ mp->ps->cs_count = mp->ps->cs_size = mp->ps->cs_size_pos = 0;
+ mp->ps->cs_token_pair = NULL;
+ mp->ps->subr_tab = NULL;
+ mp->ps->subr_array_start = mp->ps->subr_array_end = NULL;
+ mp->ps->subr_max = mp->ps->subr_size = mp->ps->subr_size_pos = 0;
+}
+
+static void init_cs_entry ( cs_entry * cs) {
+ cs->data = NULL;
+ cs->glyph_name = NULL;
+ cs->len = 0;
+ cs->cslen = 0;
+ cs->is_used = false;
+ cs->valid = false;
+}
+
+static void t1_mark_glyphs (MP mp, int tex_font);
+
+static void t1_read_subrs (MP mp, int tex_font, fm_entry *fm_cur)
+{
+ int i, s;
+ cs_entry *ptr;
+ t1_getline (mp);
+ while (!(t1_charstrings () || t1_subrs ())) {
+ t1_scan_param (mp,tex_font, fm_cur);
+ t1_putline (mp);
+ t1_getline (mp);
+ }
+ FOUND:
+ mp->ps->t1_cs = true;
+ mp->ps->t1_scan = false;
+ if (!t1_subrs ())
+ return;
+ mp->ps->subr_size_pos = strlen ("/Subrs") + 1;
+ /* |subr_size_pos| points to the number indicating dict size after "/Subrs" */
+ mp->ps->subr_size = t1_scan_num (mp,mp->ps->t1_line_array + mp->ps->subr_size_pos, 0);
+ if (mp->ps->subr_size == 0) {
+ while (!t1_charstrings ())
+ t1_getline (mp);
+ return;
+ }
+ /* |subr_tab = xtalloc (subr_size, cs_entry);| */
+ mp->ps->subr_tab = (cs_entry *)mp_xmalloc (mp,mp->ps->subr_size, sizeof (cs_entry));
+ for (ptr = mp->ps->subr_tab; ptr - mp->ps->subr_tab < mp->ps->subr_size; ptr++)
+ init_cs_entry (ptr);
+ mp->ps->subr_array_start = mp_xstrdup (mp,mp->ps->t1_line_array);
+ t1_getline (mp);
+ while (mp->ps->t1_cslen) {
+ store_subr (mp);
+ t1_getline (mp);
+ }
+ /* mark the first four entries without parsing */
+ for (i = 0; i < mp->ps->subr_size && i < 4; i++)
+ mp->ps->subr_tab[i].is_used = true;
+ /* the end of the Subrs array might have more than one line so we need to
+ concatnate them to |subr_array_end|. Unfortunately some fonts don't have
+ the Subrs array followed by the CharStrings dict immediately (synthetic
+ fonts). If we cannot find CharStrings in next |POST_SUBRS_SCAN| lines then
+ we will treat the font as synthetic and ignore everything until next
+ Subrs is found
+ */
+#define POST_SUBRS_SCAN 5
+ s = 0;
+ *mp->ps->t1_buf_array = 0;
+ for (i = 0; i < POST_SUBRS_SCAN; i++) {
+ if (t1_charstrings ())
+ break;
+ s += mp->ps->t1_line_ptr - mp->ps->t1_line_array;
+ alloc_array (t1_buf, s, T1_BUF_SIZE);
+ strcat (mp->ps->t1_buf_array, mp->ps->t1_line_array);
+ t1_getline (mp);
+ }
+ mp->ps->subr_array_end = mp_xstrdup (mp,mp->ps->t1_buf_array);
+ if (i == POST_SUBRS_SCAN) { /* CharStrings not found;
+ suppose synthetic font */
+ for (ptr = mp->ps->subr_tab; ptr - mp->ps->subr_tab < mp->ps->subr_size; ptr++)
+ if (ptr->valid)
+ mp_xfree (ptr->data);
+ mp_xfree (mp->ps->subr_tab);
+ mp_xfree (mp->ps->subr_array_start);
+ mp_xfree (mp->ps->subr_array_end);
+ cs_init (mp);
+ mp->ps->t1_cs = false;
+ mp->ps->t1_synthetic = true;
+ while (!(t1_charstrings () || t1_subrs ()))
+ t1_getline (mp);
+ goto FOUND;
+ }
+}
+
+@ @c
+static void t1_flush_cs (MP mp, boolean is_subr)
+{
+ char *p;
+ byte *r, *return_cs = NULL;
+ cs_entry *tab, *end_tab, *ptr;
+ char *start_line, *line_end;
+ int count, size_pos;
+ unsigned short cr, cs_len = 0; /* to avoid warning about uninitialized use of |cs_len| */
+ if (is_subr) {
+ start_line = mp->ps->subr_array_start;
+ line_end = mp->ps->subr_array_end;
+ size_pos = mp->ps->subr_size_pos;
+ tab = mp->ps->subr_tab;
+ count = mp->ps->subr_max + 1;
+ end_tab = mp->ps->subr_tab + count;
+ } else {
+ start_line = mp->ps->cs_dict_start;
+ line_end = mp->ps->cs_dict_end;
+ size_pos = mp->ps->cs_size_pos;
+ tab = mp->ps->cs_tab;
+ end_tab = mp->ps->cs_ptr;
+ count = mp->ps->cs_count;
+ }
+ mp->ps->t1_line_ptr = mp->ps->t1_line_array;
+ for (p = start_line; p - start_line < size_pos;)
+ *mp->ps->t1_line_ptr++ = *p++;
+ while (isdigit (*p))
+ p++;
+ sprintf (mp->ps->t1_line_ptr, "%u", count);
+ strcat (mp->ps->t1_line_ptr, p);
+ mp->ps->t1_line_ptr = eol (mp->ps->t1_line_array);
+ t1_putline (mp);
+
+ /* create |return_cs| to replace unsused subr's */
+ if (is_subr) {
+ cr = 4330;
+ cs_len = 0;
+ return_cs = mp_xmalloc (mp, (mp->ps->t1_lenIV + 1) , sizeof(byte));
+ if ( mp->ps->t1_lenIV > 0) {
+ for (cs_len = 0, r = return_cs; cs_len < mp->ps->t1_lenIV; cs_len++, r++)
+ *r = cencrypt (mp,0x00, &cr);
+ *r = cencrypt (mp,CS_RETURN, &cr);
+ } else {
+ *return_cs = CS_RETURN;
+ }
+ cs_len++;
+ }
+
+ for (ptr = tab; ptr < end_tab; ptr++) {
+ if (ptr->is_used) {
+ if (is_subr)
+ sprintf (mp->ps->t1_line_array, "dup %i %u", (int) (ptr - tab),
+ ptr->cslen);
+ else
+ sprintf (mp->ps->t1_line_array, "/%s %u", ptr->glyph_name, ptr->cslen);
+ p = strend (mp->ps->t1_line_array);
+ memcpy (p, ptr->data, ptr->len);
+ mp->ps->t1_line_ptr = p + ptr->len;
+ t1_putline (mp);
+ } else {
+ /* replace unsused subr's by |return_cs| */
+ if (is_subr) {
+ sprintf (mp->ps->t1_line_array, "dup %i %u%s ", (int) (ptr - tab),
+ cs_len, mp->ps->cs_token_pair[0]);
+ p = strend (mp->ps->t1_line_array);
+ memcpy (p, return_cs, cs_len);
+ mp->ps->t1_line_ptr = p + cs_len;
+ t1_putline (mp);
+ sprintf (mp->ps->t1_line_array, " %s", mp->ps->cs_token_pair[1]);
+ mp->ps->t1_line_ptr = eol (mp->ps->t1_line_array);
+ t1_putline (mp);
+ }
+ }
+ mp_xfree (ptr->data);
+ if (ptr->glyph_name != notdef)
+ mp_xfree (ptr->glyph_name);
+ }
+ sprintf (mp->ps->t1_line_array, "%s", line_end);
+ mp->ps->t1_line_ptr = eol (mp->ps->t1_line_array);
+ t1_putline (mp);
+ if (is_subr)
+ mp_xfree (return_cs);
+ mp_xfree (tab);
+ mp_xfree (start_line);
+ mp_xfree (line_end);
+}
+
+static void t1_mark_glyphs (MP mp, int tex_font)
+{
+ int i;
+ char *charset = extra_charset ();
+ char *g, *s, *r;
+ cs_entry *ptr;
+ if (mp->ps->t1_synthetic || embed_all_glyphs (tex_font)) { /* mark everything */
+ if (mp->ps->cs_tab != NULL)
+ for (ptr = mp->ps->cs_tab; ptr < mp->ps->cs_ptr; ptr++)
+ if (ptr->valid)
+ ptr->is_used = true;
+ if (mp->ps->subr_tab != NULL) {
+ for (ptr = mp->ps->subr_tab; ptr - mp->ps->subr_tab < mp->ps->subr_size; ptr++)
+ if (ptr->valid)
+ ptr->is_used = true;
+ mp->ps->subr_max = mp->ps->subr_size - 1;
+ }
+ return;
+ }
+ mark_cs (mp,notdef);
+ for (i = 0; i < 256; i++)
+ if (is_used_char (i)) {
+ if (mp->ps->t1_glyph_names[i] == notdef) {
+ char S[128];
+ snprintf(S,128, "character %i is mapped to %s", i, notdef);
+ mp_warn(mp,S);
+ } else
+ mark_cs (mp,mp->ps->t1_glyph_names[i]);
+ }
+ if (charset == NULL)
+ goto SET_SUBR_MAX;
+ g = s = charset + 1; /* skip the first '/' */
+ r = strend (g);
+ while (g < r) {
+ while (*s != '/' && s < r)
+ s++;
+ *s = 0; /* terminate g by rewriting '/' to 0 */
+ mark_cs (mp,g);
+ g = s + 1;
+ }
+ SET_SUBR_MAX:
+ if (mp->ps->subr_tab != NULL)
+ for (mp->ps->subr_max = -1, ptr = mp->ps->subr_tab;
+ ptr - mp->ps->subr_tab < mp->ps->subr_size;
+ ptr++)
+ if (ptr->is_used && ptr - mp->ps->subr_tab > mp->ps->subr_max)
+ mp->ps->subr_max = ptr - mp->ps->subr_tab;
+}
+
+static void t1_subset_charstrings (MP mp, int tex_font)
+{
+ cs_entry *ptr;
+ mp->ps->cs_size_pos =
+ strstr (mp->ps->t1_line_array, charstringname) + strlen (charstringname)
+ - mp->ps->t1_line_array + 1;
+ /* |cs_size_pos| points to the number indicating
+ dict size after "/CharStrings" */
+ mp->ps->cs_size = t1_scan_num (mp,mp->ps->t1_line_array + mp->ps->cs_size_pos, 0);
+ mp->ps->cs_ptr = mp->ps->cs_tab = mp_xmalloc (mp,mp->ps->cs_size, sizeof(cs_entry));
+ for (ptr = mp->ps->cs_tab; ptr - mp->ps->cs_tab < mp->ps->cs_size; ptr++)
+ init_cs_entry (ptr);
+ mp->ps->cs_notdef = NULL;
+ mp->ps->cs_dict_start = mp_xstrdup (mp,mp->ps->t1_line_array);
+ t1_getline (mp);
+ while (mp->ps->t1_cslen) {
+ store_cs (mp);
+ t1_getline (mp);
+ }
+ mp->ps->cs_dict_end = mp_xstrdup (mp,mp->ps->t1_line_array);
+ t1_mark_glyphs (mp,tex_font);
+ if (mp->ps->subr_tab != NULL) {
+ if (mp->ps->cs_token_pair == NULL)
+ mp_fatal_error
+ (mp, "This Type 1 font uses mismatched subroutine begin/end token pairs.");
+ t1_subr_flush (mp);
+ }
+ for (mp->ps->cs_count = 0, ptr = mp->ps->cs_tab; ptr < mp->ps->cs_ptr; ptr++)
+ if (ptr->is_used)
+ mp->ps->cs_count++;
+ t1_cs_flush (mp);
+}
+
+static void t1_subset_end (MP mp)
+{
+ if (mp->ps->t1_synthetic) { /* copy to "dup /FontName get exch definefont pop" */
+ while (!strstr (mp->ps->t1_line_array, "definefont")) {
+ t1_getline (mp);
+ t1_putline (mp);
+ }
+ while (!t1_end_eexec ())
+ t1_getline (mp); /* ignore the rest */
+ t1_putline (mp); /* write "mark currentfile closefile" */
+ } else
+ while (!t1_end_eexec ()) { /* copy to "mark currentfile closefile" */
+ t1_getline (mp);
+ t1_putline (mp);
+ }
+ t1_stop_eexec (mp);
+ if (fixedcontent) { /* copy 512 zeros (not needed for PDF) */
+ while (!t1_cleartomark ()) {
+ t1_getline (mp);
+ t1_putline (mp);
+ }
+ if (!mp->ps->t1_synthetic) /* don't check "{restore}if" for synthetic fonts */
+ t1_check_end (mp); /* write "{restore}if" if found */
+ }
+}
+
+static int t1_updatefm (MP mp, int f, fm_entry *fm)
+{
+ char *s, *p;
+ mp->ps->read_encoding_only = true;
+ if (!t1_open_fontfile (mp,fm,NULL)) {
+ return 0;
+ }
+ t1_scan_only (mp,f, fm);
+ s = mp_xstrdup(mp,mp->ps->fontname_buf);
+ p = s;
+ while (*p != ' ' && *p != 0)
+ p++;
+ *p=0;
+ fm->ps_name = s;
+ t1_close_font_file (mp,"");
+ return 1;
+}
+
+
+static void writet1 (MP mp, int tex_font, fm_entry *fm_cur) {
+ int save_selector = mp->selector;
+ mp_normalize_selector(mp);
+ mp->ps->read_encoding_only = false;
+ if (!is_included (fm_cur)) { /* scan parameters from font file */
+ if (!t1_open_fontfile (mp,fm_cur,"{"))
+ return;
+ t1_scan_only (mp,tex_font, fm_cur);
+ t1_close_font_file (mp,"}");
+ return;
+ }
+ if (!is_subsetted (fm_cur)) { /* include entire font */
+ if (!t1_open_fontfile (mp,fm_cur,"<<"))
+ return;
+ t1_include (mp,tex_font,fm_cur);
+ t1_close_font_file (mp,">>");
+ return;
+ }
+ /* partial downloading */
+ if (!t1_open_fontfile (mp,fm_cur,"<"))
+ return;
+ t1_subset_ascii_part (mp,tex_font,fm_cur);
+ t1_start_eexec (mp,fm_cur);
+ cc_init ();
+ cs_init (mp);
+ t1_read_subrs (mp,tex_font, fm_cur);
+ t1_subset_charstrings (mp,tex_font);
+ t1_subset_end (mp);
+ t1_close_font_file (mp,">");
+ mp->selector = save_selector;
+}
+
+@ @<Declarations@>=
+static void t1_free (MP mp);
+
+@ @c
+static void t1_free (MP mp) {
+ mp_xfree (mp->ps->t1_line_array);
+ mp_xfree (mp->ps->t1_buf_array);
+}
+
+
+@* \[44d] Embedding fonts.
+
+@ The |tfm_num| is officially of type |font_number|, but that
+type does not exist yet at this point in the output order.
+
+@<Types...@>=
+typedef struct {
+ char *tfm_name; /* TFM file name */
+ char *ps_name; /* PostScript name */
+ integer flags; /* font flags */
+ char *ff_name; /* font file name */
+ char *subset_tag; /* pseudoUniqueTag for subsetted font */
+ enc_entry *encoding; /* pointer to corresponding encoding */
+ unsigned int tfm_num; /* number of the TFM refering this entry */
+ unsigned short type; /* font type (T1/TTF/...) */
+ short slant; /* SlantFont */
+ short extend; /* ExtendFont */
+ integer ff_objnum; /* FontFile object number */
+ integer fn_objnum; /* FontName/BaseName object number */
+ integer fd_objnum; /* FontDescriptor object number */
+ char *charset; /* string containing used glyphs */
+ boolean all_glyphs; /* embed all glyphs? */
+ unsigned short links; /* link flags from |tfm_tree| and |ps_tree| */
+ short tfm_avail; /* flags whether a tfm is available */
+ short pid; /* Pid for truetype fonts */
+ short eid; /* Eid for truetype fonts */
+} fm_entry;
+
+
+@
+@<Glob...@>=
+#define FONTNAME_BUF_SIZE 128
+boolean fontfile_found;
+boolean is_otf_font;
+char fontname_buf[FONTNAME_BUF_SIZE];
+
+@
+@d F_INCLUDED 0x01
+@d F_SUBSETTED 0x02
+@d F_TRUETYPE 0x04
+@d F_BASEFONT 0x08
+
+@d set_included(fm) ((fm)->type |= F_INCLUDED)
+@d set_subsetted(fm) ((fm)->type |= F_SUBSETTED)
+@d set_truetype(fm) ((fm)->type |= F_TRUETYPE)
+@d set_basefont(fm) ((fm)->type |= F_BASEFONT)
+
+@d is_included(fm) ((fm)->type & F_INCLUDED)
+@d is_subsetted(fm) ((fm)->type & F_SUBSETTED)
+@d is_truetype(fm) ((fm)->type & F_TRUETYPE)
+@d is_basefont(fm) ((fm)->type & F_BASEFONT)
+@d is_reencoded(fm) ((fm)->encoding != NULL)
+@d is_fontfile(fm) (fm_fontfile(fm) != NULL)
+@d is_t1fontfile(fm) (is_fontfile(fm) && !is_truetype(fm))
+
+@d fm_slant(fm) (fm)->slant
+@d fm_extend(fm) (fm)->extend
+@d fm_fontfile(fm) (fm)->ff_name
+
+@<Declarations@>=
+static boolean mp_font_is_reencoded (MP mp, int f);
+static boolean mp_font_is_included (MP mp, int f);
+static boolean mp_font_is_subsetted (MP mp, int f);
+
+@ @c
+static boolean mp_font_is_reencoded (MP mp, int f) {
+ fm_entry *fm;
+ if (mp_has_font_size(mp,f) && mp_has_fm_entry (mp, f, &fm)) {
+ if (fm != NULL
+ && (fm->ps_name != NULL)
+ && is_reencoded (fm))
+ return 1;
+ }
+ return 0;
+}
+static boolean mp_font_is_included (MP mp, int f) {
+ fm_entry *fm;
+ if (mp_has_font_size(mp,f) && mp_has_fm_entry (mp, f, &fm)) {
+ if (fm != NULL
+ && (fm->ps_name != NULL && fm->ff_name != NULL)
+ && is_included (fm))
+ return 1;
+ }
+ return 0;
+}
+static boolean mp_font_is_subsetted (MP mp, int f) {
+ fm_entry *fm;
+ if (mp_has_font_size(mp,f) && mp_has_fm_entry (mp, f,&fm)) {
+ if (fm != NULL
+ && (fm->ps_name != NULL && fm->ff_name != NULL)
+ && is_included (fm) && is_subsetted (fm))
+ return 1;
+ }
+ return 0;
+}
+
+@ @<Exported function headers@>=
+char * mp_fm_encoding_name (MP mp, int f);
+char * mp_fm_font_name (MP mp, int f);
+
+@ @<Declarations@>=
+static char * mp_fm_font_subset_name (MP mp, int f);
+
+@
+@c char * mp_fm_encoding_name (MP mp, int f) {
+ enc_entry *e;
+ fm_entry *fm;
+ if (mp_has_fm_entry (mp, f, &fm)) {
+ if (fm != NULL && (fm->ps_name != NULL)) {
+ if (is_reencoded (fm)) {
+ e = fm->encoding;
+ if (e->enc_name!=NULL)
+ return mp_xstrdup(mp,e->enc_name);
+ } else {
+ return NULL;
+ }
+ }
+ }
+ print_err ("fontmap encoding problems for font ");
+ mp_print(mp,mp->font_name[f]);
+ mp_error(mp);
+ return NULL;
+}
+char * mp_fm_font_name (MP mp, int f) {
+ fm_entry *fm;
+ if (mp_has_fm_entry (mp, f,&fm)) {
+ if (fm != NULL && (fm->ps_name != NULL)) {
+ if (mp_font_is_included(mp, f) && !mp->font_ps_name_fixed[f]) {
+ /* find the real fontname, and update |ps_name| and |subset_tag| if needed */
+ if (t1_updatefm(mp,f,fm)) {
+ mp->font_ps_name_fixed[f] = true;
+ } else {
+ print_err ("font loading problems for font ");
+ mp_print(mp,mp->font_name[f]);
+ mp_error(mp);
+ }
+ }
+ return mp_xstrdup(mp,fm->ps_name);
+ }
+ }
+ print_err ("fontmap name problems for font ");
+ mp_print(mp,mp->font_name[f]);
+ mp_error(mp);
+ return NULL;
+}
+
+static char * mp_fm_font_subset_name (MP mp, int f) {
+ fm_entry *fm;
+ if (mp_has_fm_entry (mp, f, &fm)) {
+ if (fm != NULL && (fm->ps_name != NULL)) {
+ if (is_subsetted(fm)) {
+ char *s = mp_xmalloc(mp,strlen(fm->ps_name)+8,1);
+ snprintf(s,strlen(fm->ps_name)+8,"%s-%s",fm->subset_tag,fm->ps_name);
+ return s;
+ } else {
+ return mp_xstrdup(mp,fm->ps_name);
+ }
+ }
+ }
+ print_err ("fontmap name problems for font ");
+ mp_print(mp,mp->font_name[f]);
+ mp_error(mp);
+ return NULL;
+}
+
+@ @<Declarations@>=
+static integer mp_fm_font_slant (MP mp, int f);
+static integer mp_fm_font_extend (MP mp, int f);
+
+@
+@c static integer mp_fm_font_slant (MP mp, int f) {
+ fm_entry *fm;
+ if (mp_has_fm_entry (mp, f, &fm)) {
+ if (fm != NULL && (fm->ps_name != NULL)) {
+ return fm->slant;
+ }
+ }
+ return 0;
+}
+static integer mp_fm_font_extend (MP mp, int f) {
+ fm_entry *fm;
+ if (mp_has_fm_entry (mp, f, &fm)) {
+ if (fm != NULL && (fm->ps_name != NULL)) {
+ return fm->extend;
+ }
+ }
+ return 0;
+}
+
+@ @<Declarations@>=
+static boolean mp_do_ps_font (MP mp, font_number f);
+
+@ @c static boolean mp_do_ps_font (MP mp, font_number f) {
+ fm_entry *fm_cur;
+ (void)mp_has_fm_entry (mp, f, &fm_cur); /* for side effects */
+ if (fm_cur == NULL)
+ return 1;
+ if (is_truetype(fm_cur) ||
+ (fm_cur->ps_name == NULL && fm_cur->ff_name == NULL)) {
+ return 0;
+ }
+ if (is_included(fm_cur)) {
+ mp_ps_print_nl(mp,"%%BeginResource: font ");
+ if (is_subsetted(fm_cur)) {
+ mp_ps_print(mp, fm_cur->subset_tag);
+ mp_ps_print_char(mp,'-');
+ }
+ mp_ps_print(mp, fm_cur->ps_name);
+ mp_ps_print_ln(mp);
+ writet1 (mp,f,fm_cur);
+ mp_ps_print_nl(mp,"%%EndResource");
+ mp_ps_print_ln(mp);
+ }
+ return 1;
+}
+
+@ Included subset fonts do not need and encoding vector, make
+sure we skip that case.
+
+@<Declarations@>=
+static void mp_list_used_resources (MP mp, int prologues, int procset);
+
+@ @c static void mp_list_used_resources (MP mp, int prologues, int procset) {
+ font_number f; /* fonts used in a text node or as loop counters */
+ int ff; /* a loop counter */
+ font_number ldf; /* the last \.{DocumentFont} listed (otherwise |null_font|) */
+ boolean firstitem;
+ if ( procset>0 )
+ mp_ps_print_nl(mp, "%%DocumentResources: procset mpost");
+ else
+ mp_ps_print_nl(mp, "%%DocumentResources: procset mpost-minimal");
+ ldf=null_font;
+ firstitem=true;
+ for (f=null_font+1;f<=mp->last_fnum;f++) {
+ if ( (mp_has_font_size(mp,f))&&(mp_font_is_reencoded(mp,f)) ) {
+ for (ff=ldf;ff>=null_font;ff--) {
+ if ( mp_has_font_size(mp,ff) )
+ if ( mp_xstrcmp(mp->font_enc_name[f],mp->font_enc_name[ff])==0 )
+ goto FOUND;
+ }
+ if ( mp_font_is_subsetted(mp,f) )
+ goto FOUND;
+ if ( mp->ps->ps_offset+1+strlen(mp->font_enc_name[f])>
+ (unsigned)mp->max_print_line )
+ mp_ps_print_nl(mp, "%%+ encoding");
+ if ( firstitem ) {
+ firstitem=false;
+ mp_ps_print_nl(mp, "%%+ encoding");
+ }
+ mp_ps_print_char(mp, ' ');
+ mp_ps_print(mp, mp->font_enc_name[f]);
+ ldf=f;
+ }
+ FOUND:
+ ;
+ }
+ ldf=null_font;
+ firstitem=true;
+ for (f=null_font+1;f<=mp->last_fnum;f++) {
+ if ( mp_has_font_size(mp,f) ) {
+ for (ff=ldf;ff>=null_font;ff--) {
+ if ( mp_has_font_size(mp,ff) )
+ if ( mp_xstrcmp(mp->font_name[f],mp->font_name[ff])==0 )
+ goto FOUND2;
+ }
+ if ( mp->ps->ps_offset+1+strlen(mp->font_ps_name[f])>
+ (unsigned)mp->max_print_line )
+ mp_ps_print_nl(mp, "%%+ font");
+ if ( firstitem ) {
+ firstitem=false;
+ mp_ps_print_nl(mp, "%%+ font");
+ }
+ mp_ps_print_char(mp, ' ');
+ if ( (prologues==3)&&
+ (mp_font_is_subsetted(mp,f)) )
+ mp_ps_print(mp, mp_fm_font_subset_name(mp,f));
+ else
+ mp_ps_print(mp, mp->font_ps_name[f]);
+ ldf=f;
+ }
+ FOUND2:
+ ;
+ }
+ mp_ps_print_ln(mp);
+}
+
+@ @<Declarations@>=
+static void mp_list_supplied_resources (MP mp, int prologues, int procset);
+
+@ @c static void mp_list_supplied_resources (MP mp, int prologues, int procset) {
+ font_number f; /* fonts used in a text node or as loop counters */
+ int ff; /* a loop counter */
+ font_number ldf; /* the last \.{DocumentFont} listed (otherwise |null_font|) */
+ boolean firstitem;
+ if ( procset>0 )
+ mp_ps_print_nl(mp, "%%DocumentSuppliedResources: procset mpost");
+ else
+ mp_ps_print_nl(mp, "%%DocumentSuppliedResources: procset mpost-minimal");
+ ldf=null_font;
+ firstitem=true;
+ for (f=null_font+1;f<=mp->last_fnum;f++) {
+ if ( (mp_has_font_size(mp,f))&&(mp_font_is_reencoded(mp,f)) ) {
+ for (ff=ldf;ff>= null_font;ff++) {
+ if ( mp_has_font_size(mp,ff) )
+ if ( mp_xstrcmp(mp->font_enc_name[f],mp->font_enc_name[ff])==0 )
+ goto FOUND;
+ }
+ if ( (prologues==3)&&(mp_font_is_subsetted(mp,f)))
+ goto FOUND;
+ if ( mp->ps->ps_offset+1+strlen(mp->font_enc_name[f])>(unsigned)mp->max_print_line )
+ mp_ps_print_nl(mp, "%%+ encoding");
+ if ( firstitem ) {
+ firstitem=false;
+ mp_ps_print_nl(mp, "%%+ encoding");
+ }
+ mp_ps_print_char(mp, ' ');
+ mp_ps_print(mp, mp->font_enc_name[f]);
+ ldf=f;
+ }
+ FOUND:
+ ;
+ }
+ ldf=null_font;
+ firstitem=true;
+ if (prologues==3) {
+ for (f=null_font+1;f<=mp->last_fnum;f++) {
+ if ( mp_has_font_size(mp,f) ) {
+ for (ff=ldf;ff>= null_font;ff--) {
+ if ( mp_has_font_size(mp,ff) )
+ if ( mp_xstrcmp(mp->font_name[f],mp->font_name[ff])==0 )
+ goto FOUND2;
+ }
+ if ( ! mp_font_is_included(mp,f) )
+ goto FOUND2;
+ if ( mp->ps->ps_offset+1+strlen(mp->font_ps_name[f])>(unsigned)mp->max_print_line )
+ mp_ps_print_nl(mp, "%%+ font");
+ if ( firstitem ) {
+ firstitem=false;
+ mp_ps_print_nl(mp, "%%+ font");
+ }
+ mp_ps_print_char(mp, ' ');
+ if ( mp_font_is_subsetted(mp,f) )
+ mp_ps_print(mp, mp_fm_font_subset_name(mp,f));
+ else
+ mp_ps_print(mp, mp->font_ps_name[f]);
+ ldf=f;
+ }
+ FOUND2:
+ ;
+ }
+ mp_ps_print_ln(mp);
+ }
+}
+
+@ @<Declarations...@>=
+static void mp_list_needed_resources (MP mp, int prologues);
+
+@ @c static void mp_list_needed_resources (MP mp, int prologues) {
+ font_number f; /* fonts used in a text node or as loop counters */
+ int ff; /* a loop counter */
+ font_number ldf; /* the last \.{DocumentFont} listed (otherwise |null_font|) */
+ boolean firstitem;
+ ldf=null_font;
+ firstitem=true;
+ for (f=null_font+1;f<=mp->last_fnum;f++ ) {
+ if ( mp_has_font_size(mp,f)) {
+ for (ff=ldf;ff>=null_font;ff--) {
+ if ( mp_has_font_size(mp,ff) )
+ if ( mp_xstrcmp(mp->font_name[f],mp->font_name[ff])==0 )
+ goto FOUND;
+ };
+ if ((prologues==3)&&(mp_font_is_included(mp,f)) )
+ goto FOUND;
+ if ( mp->ps->ps_offset+1+strlen(mp->font_ps_name[f])>(unsigned)mp->max_print_line )
+ mp_ps_print_nl(mp, "%%+ font");
+ if ( firstitem ) {
+ firstitem=false;
+ mp_ps_print_nl(mp, "%%DocumentNeededResources: font");
+ }
+ mp_ps_print_char(mp, ' ');
+ mp_ps_print(mp, mp->font_ps_name[f]);
+ ldf=f;
+ }
+ FOUND:
+ ;
+ }
+ if ( ! firstitem ) {
+ mp_ps_print_ln(mp);
+ ldf=null_font;
+ firstitem=true;
+ for (f=null_font+1;f<= mp->last_fnum;f++) {
+ if ( mp_has_font_size(mp,f) ) {
+ for (ff=ldf;ff>=null_font;ff-- ) {
+ if ( mp_has_font_size(mp,ff) )
+ if ( mp_xstrcmp(mp->font_name[f],mp->font_name[ff])==0 )
+ goto FOUND2;
+ }
+ if ((prologues==3)&&(mp_font_is_included(mp,f)) )
+ goto FOUND2;
+ mp_ps_print(mp, "%%IncludeResource: font ");
+ mp_ps_print(mp, mp->font_ps_name[f]);
+ mp_ps_print_ln(mp);
+ ldf=f;
+ }
+ FOUND2:
+ ;
+ }
+ }
+}
+
+@ @<Declarations@>=
+static void mp_write_font_definition (MP mp, font_number f, int prologues);
+
+@
+
+@d applied_reencoding(A) ((mp_font_is_reencoded(mp,(A)))&&
+ ((! mp_font_is_subsetted(mp,(A)))||(prologues==2)))
+
+@c static void mp_write_font_definition(MP mp, font_number f, int prologues) {
+ if ( (applied_reencoding(f))||(mp_fm_font_slant(mp,f)!=0)||
+ (mp_fm_font_extend(mp,f)!=0)||
+ (mp_xstrcmp(mp->font_name[f],"psyrgo")==0)||
+ (mp_xstrcmp(mp->font_name[f],"zpzdr-reversed")==0) ) {
+ if ( (mp_font_is_subsetted(mp,f))&&
+ (mp_font_is_included(mp,f))&&(prologues==3))
+ mp_ps_name_out(mp, mp_fm_font_subset_name(mp,f),true);
+ else
+ mp_ps_name_out(mp, mp->font_ps_name[f],true);
+ mp_ps_print(mp, " fcp");
+ mp_ps_print_ln(mp);
+ if ( applied_reencoding(f) ) {
+ mp_ps_print(mp, "/Encoding ");
+ mp_ps_print(mp, mp->font_enc_name[f]);
+ mp_ps_print(mp, " def ");
+ };
+ if ( mp_fm_font_slant(mp,f)!=0 ) {
+ mp_ps_print_int(mp, mp_fm_font_slant(mp,f));
+ mp_ps_print(mp, " SlantFont ");
+ };
+ if ( mp_fm_font_extend(mp,f)!=0 ) {
+ mp_ps_print_int(mp, mp_fm_font_extend(mp,f));
+ mp_ps_print(mp, " ExtendFont ");
+ };
+ if ( mp_xstrcmp(mp->font_name[f],"psyrgo")==0 ) {
+ mp_ps_print(mp, " 890 ScaleFont ");
+ mp_ps_print(mp, " 277 SlantFont ");
+ };
+ if ( mp_xstrcmp(mp->font_name[f],"zpzdr-reversed")==0 ) {
+ mp_ps_print(mp, " FontMatrix [-1 0 0 1 0 0] matrix concatmatrix /FontMatrix exch def ");
+ mp_ps_print(mp, "/Metrics 2 dict dup begin ");
+ mp_ps_print(mp, "/space[0 -278]def ");
+ mp_ps_print(mp, "/a12[-904 -939]def ");
+ mp_ps_print(mp, "end def ");
+ };
+ mp_ps_print(mp, "currentdict end");
+ mp_ps_print_ln(mp);
+ mp_ps_print_defined_name(mp,f,prologues);
+ mp_ps_print(mp, " exch definefont pop");
+ mp_ps_print_ln(mp);
+ }
+}
+
+@ @<Declarations@>=
+static void mp_ps_print_defined_name (MP mp, font_number f, int prologues);
+
+@
+@c static void mp_ps_print_defined_name(MP mp, font_number A, int prologues) {
+ mp_ps_print(mp, " /");
+ if ((mp_font_is_subsetted(mp,(A)))&&
+ (mp_font_is_included(mp,(A)))&&(prologues==3))
+ mp_ps_print(mp, mp_fm_font_subset_name(mp,(A)));
+ else
+ mp_ps_print(mp, mp->font_ps_name[(A)]);
+ if ( mp_xstrcmp(mp->font_name[(A)],"psyrgo")==0 )
+ mp_ps_print(mp, "-Slanted");
+ if ( mp_xstrcmp(mp->font_name[(A)],"zpzdr-reversed")==0 )
+ mp_ps_print(mp, "-Reverse");
+ if ( applied_reencoding((A)) ) {
+ mp_ps_print(mp, "-");
+ mp_ps_print(mp, mp->font_enc_name[(A)]);
+ }
+ if ( mp_fm_font_slant(mp,(A))!=0 ) {
+ mp_ps_print(mp, "-Slant_"); mp_ps_print_int(mp, mp_fm_font_slant(mp,(A))) ;
+ }
+ if ( mp_fm_font_extend(mp,(A))!=0 ) {
+ mp_ps_print(mp, "-Extend_"); mp_ps_print_int(mp, mp_fm_font_extend(mp,(A)));
+ }
+}
+
+@ @<Include encodings and fonts for edge structure~|h|@>=
+mp_font_encodings(mp,mp->last_fnum,(prologues==2));
+@<Embed fonts that are available@>
+
+@ @<Embed fonts that are available@>=
+{
+next_size=0;
+@<Make |cur_fsize| a copy of the |font_sizes| array@>;
+do {
+ done_fonts=true;
+ for (f=null_font+1;f<=mp->last_fnum;f++) {
+ if ( cur_fsize[f]!=null ) {
+ if (prologues==3 ) {
+ if ( ! mp_do_ps_font(mp,f) ) {
+ if ( mp_has_fm_entry(mp,f, NULL) ) {
+ print_err("Font embedding failed");
+ mp_error(mp);
+ }
+ }
+ }
+ cur_fsize[f]=link(cur_fsize[f]);
+ if ( cur_fsize[f]!=null ) { mp_unmark_font(mp, f); done_fonts=false; }
+ }
+ }
+ if ( ! done_fonts )
+ @<Increment |next_size| and apply |mark_string_chars| to all text nodes with
+ that size index@>;
+} while (! done_fonts);
+}
+
+@ @<Increment |next_size| and apply |mark_string_chars| to all text nodes...@>=
+{
+ next_size++;
+ mp_apply_mark_string_chars(mp, h, next_size);
+}
+
+@ We also need to keep track of which characters are used in text nodes
+in the edge structure that is being shipped out. This is done by procedures
+that use the left-over |b3| field in the |char_info| words; i.e.,
+|char_info(f)(c).b3| gives the status of character |c| in font |f|.
+
+@<Types...@>=
+enum mp_char_mark_state {mp_unused=0, mp_used};
+
+@ @<Exported...@>=
+void mp_mark_string_chars (MP mp,font_number f, char *s) ;
+
+@ @c
+void mp_mark_string_chars (MP mp,font_number f, char *s) {
+ integer b; /* |char_base[f]| */
+ ASCII_code bc,ec; /* only characters between these bounds are marked */
+ char *k; /* an index into string |s| */
+ b=mp->char_base[f];
+ bc=mp->font_bc[f];
+ ec=mp->font_ec[f];
+ k=s; /* str_stop */
+ while (*k){
+ if ( (*k>=bc)&&(*k<=ec) )
+ mp->font_info[b+*k].qqqq.b3=mp_used;
+ k++;
+ }
+}
+
+
+@ @<Exported ...@>=
+void mp_unmark_font (MP mp,font_number f) ;
+
+@ @c
+void mp_unmark_font (MP mp,font_number f) {
+ int k; /* an index into |font_info| */
+ for (k= mp->char_base[f]+mp->font_bc[f];
+ k<=mp->char_base[f]+mp->font_ec[f];
+ k++)
+ mp->font_info[k].qqqq.b3=mp_unused;
+}
+
+
+@ @<Exported...@>=
+void mp_print_improved_prologue (MP mp, mp_edge_object *h, int prologues, int procset) ;
+
+@ @c
+void mp_print_improved_prologue (MP mp, mp_edge_object *h, int prologues, int procset) {
+ quarterword next_size; /* the size index for fonts being listed */
+ pointer *cur_fsize; /* current positions in |font_sizes| */
+ boolean done_fonts; /* have we finished listing the fonts in the header? */
+ font_number f; /* a font number for loops */
+ cur_fsize = mp_xmalloc(mp,(mp->font_max+1),sizeof(pointer));
+ mp_list_used_resources(mp, prologues, procset);
+ mp_list_supplied_resources(mp, prologues, procset);
+ mp_list_needed_resources(mp, prologues);
+ mp_ps_print_nl(mp, "%%EndComments");
+ mp_ps_print_nl(mp, "%%BeginProlog");
+ if ( procset>0 )
+ mp_ps_print_nl(mp, "%%BeginResource: procset mpost");
+ else
+ mp_ps_print_nl(mp, "%%BeginResource: procset mpost-minimal");
+ mp_ps_print_nl(mp, "/bd{bind def}bind def"
+ "/fshow {exch findfont exch scalefont setfont show}bd");
+ if ( procset>0 ) @<Print the procset@>;
+ mp_ps_print_nl(mp, "/fcp{findfont dup length dict begin"
+ "{1 index/FID ne{def}{pop pop}ifelse}forall}bd");
+ mp_ps_print_nl(mp, "/fmc{FontMatrix dup length array copy dup dup}bd"
+ "/fmd{/FontMatrix exch def}bd");
+ mp_ps_print_nl(mp, "/Amul{4 -1 roll exch mul 1000 div}bd"
+ "/ExtendFont{fmc 0 get Amul 0 exch put fmd}bd");
+ mp_ps_print_nl(mp, "/ScaleFont{dup fmc 0 get"
+ " Amul 0 exch put dup dup 3 get Amul 3 exch put fmd}bd");
+ mp_ps_print_nl(mp, "/SlantFont{fmc 2 get dup 0 eq{pop 1}if"
+ " Amul FontMatrix 0 get mul 2 exch put fmd}bd");
+ mp_ps_print_nl(mp, "%%EndResource");
+ @<Include encodings and fonts for edge structure~|h|@>;
+ mp_ps_print_nl(mp, "%%EndProlog");
+ mp_ps_print_nl(mp, "%%BeginSetup");
+ mp_ps_print_ln(mp);
+ for (f=null_font+1;f<=mp->last_fnum;f++) {
+ if ( mp_has_font_size(mp,f) ) {
+ if ( mp_has_fm_entry(mp,f,NULL) ) {
+ mp_write_font_definition(mp,f, prologues);
+ mp_ps_name_out(mp, mp->font_name[f],true);
+ mp_ps_print_defined_name(mp,f, prologues);
+ mp_ps_print(mp, " def");
+ } else {
+ char s[256];
+ snprintf(s,256,"font %s cannot be found in any fontmapfile!", mp->font_name[f]);
+ mp_warn(mp,s);
+ mp_ps_name_out(mp, mp->font_name[f],true);
+ mp_ps_name_out(mp, mp->font_name[f],true);
+ mp_ps_print(mp, " def");
+ }
+ mp_ps_print_ln(mp);
+ }
+ }
+ mp_ps_print_nl(mp, "%%EndSetup");
+ mp_ps_print_nl(mp, "%%Page: 1 1");
+ mp_ps_print_ln(mp);
+ mp_xfree(cur_fsize);
+}
+
+@ @<Declarations@>=
+static font_number mp_print_font_comments (MP mp , mp_edge_object *h, int prologues);
+
+
+@
+@c
+static font_number mp_print_font_comments (MP mp , mp_edge_object *h, int prologues) {
+ quarterword next_size; /* the size index for fonts being listed */
+ pointer *cur_fsize; /* current positions in |font_sizes| */
+ int ff; /* a loop counter */
+ boolean done_fonts; /* have we finished listing the fonts in the header? */
+ font_number f; /* a font number for loops */
+ scaled ds; /* design size and scale factor for a text node */
+ font_number ldf=0; /* the last \.{DocumentFont} listed (otherwise |null_font|) */
+ cur_fsize = mp_xmalloc(mp,(mp->font_max+1),sizeof(pointer));
+ if ( prologues>0 ) {
+ @<Give a \.{DocumentFonts} comment listing all fonts with non-null
+ |font_sizes| and eliminate duplicates@>;
+ } else {
+ next_size=0;
+ @<Make |cur_fsize| a copy of the |font_sizes| array@>;
+ do { done_fonts=true;
+ for (f=null_font+1;f<=mp->last_fnum;f++) {
+ if ( cur_fsize[f]!=null ) {
+ @<Print the \.{\%*Font} comment for font |f| and advance |cur_fsize[f]|@>;
+ }
+ if ( cur_fsize[f]!=null ) { mp_unmark_font(mp, f); done_fonts=false; };
+ }
+ if ( ! done_fonts ) {
+ @<Increment |next_size| and apply |mark_string_chars| to all text nodes with
+ that size index@>;
+ }
+ } while (! done_fonts);
+ }
+ mp_xfree(cur_fsize);
+ return ldf;
+}
+
+@ @<Make |cur_fsize| a copy of the |font_sizes| array@>=
+for (f=null_font+1;f<= mp->last_fnum;f++)
+ cur_fsize[f]=mp->font_sizes[f]
+
+@ It's not a good idea to make any assumptions about the |font_ps_name| entries,
+so we carefully remove duplicates. There is no harm in using a slow, brute-force
+search.
+
+@<Give a \.{DocumentFonts} comment listing all fonts with non-null...@>=
+{
+ ldf=null_font;
+ for (f=null_font+1;f<= mp->last_fnum;f++) {
+ if ( mp->font_sizes[f]!=null ) {
+ if ( ldf==null_font )
+ mp_ps_print_nl(mp, "%%DocumentFonts:");
+ for (ff=ldf;ff>=null_font;ff--) {
+ if ( mp->font_sizes[ff]!=null )
+ if ( mp_xstrcmp(mp->font_ps_name[f],mp->font_ps_name[ff])==0 )
+ goto FOUND;
+ }
+ if ( mp->ps->ps_offset+1+strlen(mp->font_ps_name[f])>(unsigned)mp->max_print_line )
+ mp_ps_print_nl(mp, "%%+");
+ mp_ps_print_char(mp, ' ');
+ mp_ps_print(mp, mp->font_ps_name[f]);
+ ldf=f;
+ FOUND:
+ ;
+ }
+ }
+}
+
+@ @c
+static void mp_hex_digit_out (MP mp,small_number d) {
+ if ( d<10 ) mp_ps_print_char(mp, d+'0');
+ else mp_ps_print_char(mp, d+'a'-10);
+}
+
+@ We output the marks as a hexadecimal bit string starting at |c| or
+|font_bc[f]|, whichever is greater. If the output has to be truncated
+to avoid exceeding |emergency_line_length| the return value says where to
+start scanning next time.
+
+@<Declarations@>=
+static halfword mp_ps_marks_out (MP mp,font_number f, eight_bits c);
+
+@
+@d emergency_line_length 255
+ /* \ps\ output lines can be this long in unusual circumstances */
+
+@c
+static halfword mp_ps_marks_out (MP mp,font_number f, eight_bits c) {
+ eight_bits bc,ec; /* only encode characters between these bounds */
+ integer lim; /* the maximum number of marks to encode before truncating */
+ int p; /* |font_info| index for the current character */
+ int d,b; /* used to construct a hexadecimal digit */
+ lim=4*(emergency_line_length-mp->ps->ps_offset-4);
+ bc=mp->font_bc[f];
+ ec=mp->font_ec[f];
+ if ( c>bc ) bc=c;
+ @<Restrict the range |bc..ec| so that it contains no unused characters
+ at either end and has length at most |lim|@>;
+ @<Print the initial label indicating that the bitmap starts at |bc|@>;
+ @<Print a hexadecimal encoding of the marks for characters |bc..ec|@>;
+ while ( (ec<mp->font_ec[f])&&(mp->font_info[p].qqqq.b3==mp_unused) ) {
+ p++; ec++;
+ }
+ return (ec+1);
+}
+
+@ We could save time by setting the return value before the loop that
+decrements |ec|, but there is no point in being so tricky.
+
+@<Restrict the range |bc..ec| so that it contains no unused characters...@>=
+p=mp->char_base[f]+bc;
+while ( (mp->font_info[p].qqqq.b3==mp_unused)&&(bc<ec) ) {
+ p++; bc++;
+}
+if ( ec>=bc+lim ) ec=bc+lim-1;
+p=mp->char_base[f]+ec;
+while ( (mp->font_info[p].qqqq.b3==mp_unused)&&(bc<ec) ) {
+ p--; ec--;
+}
+
+@ @<Print the initial label indicating that the bitmap starts at |bc|@>=
+mp_ps_print_char(mp, ' ');
+mp_hex_digit_out(mp, bc / 16);
+mp_hex_digit_out(mp, bc % 16);
+mp_ps_print_char(mp, ':')
+
+@
+
+@<Print a hexadecimal encoding of the marks for characters |bc..ec|@>=
+b=8; d=0;
+for (p=mp->char_base[f]+bc;p<=mp->char_base[f]+ec;p++) {
+ if ( b==0 ) {
+ mp_hex_digit_out(mp, d);
+ d=0; b=8;
+ }
+ if ( mp->font_info[p].qqqq.b3!=mp_unused ) d=d+b;
+ b=b>>1;
+}
+mp_hex_digit_out(mp, d)
+
+
+@ Here is a simple function that determines whether there are any marked
+characters in font~|f| with character code at least~|c|.
+
+@<Declarations@>=
+static boolean mp_check_ps_marks (MP mp,font_number f, integer c) ;
+
+@ @c
+static boolean mp_check_ps_marks (MP mp,font_number f, integer c) {
+ int p; /* |font_info| index for the current character */
+ for (p=mp->char_base[f]+c;p<=mp->char_base[f]+mp->font_ec[f];p++) {
+ if ( mp->font_info[p].qqqq.b3==mp_used )
+ return true;
+ }
+ return false;
+}
+
+
+@ If the file name is so long that it can't be printed without exceeding
+|emergency_line_length| then there will be missing items in the \.{\%*Font:}
+line. We might have to repeat line in order to get the character usage
+information to fit within |emergency_line_length|.
+
+TODO: these two defines are also defined in mp.w!
+
+@d link(A) mp->mem[(A)].hh.rh /* the |link| field of a memory word */
+@d sc_factor(A) mp->mem[(A)+1].cint /* the scale factor stored in a font size node */
+
+@<Print the \.{\%*Font} comment for font |f| and advance |cur_fsize[f]|@>=
+{ integer t=0;
+ while ( mp_check_ps_marks(mp, f,t) ) {
+ mp_ps_print_nl(mp, "%*Font: ");
+ if ( mp->ps->ps_offset+strlen(mp->font_name[f])+12>emergency_line_length )
+ break;
+ mp_ps_print(mp, mp->font_name[f]);
+ mp_ps_print_char(mp, ' ');
+ ds=(mp->font_dsize[f] + 8) / 16;
+ mp_ps_print_scaled(mp, mp_take_scaled(mp, ds,sc_factor(cur_fsize[f])));
+ if ( mp->ps->ps_offset+12>emergency_line_length ) break;
+ mp_ps_print_char(mp, ' ');
+ mp_ps_print_scaled(mp, ds);
+ if ( mp->ps->ps_offset+5>emergency_line_length ) break;
+ t=mp_ps_marks_out(mp, f,t);
+ }
+ cur_fsize[f]=link(cur_fsize[f]);
+}
+
+@ @<Print the procset@>=
+{
+ mp_ps_print_nl(mp, "/hlw{0 dtransform exch truncate exch idtransform pop setlinewidth}bd");
+ mp_ps_print_nl(mp, "/vlw{0 exch dtransform truncate idtransform setlinewidth pop}bd");
+ mp_ps_print_nl(mp, "/l{lineto}bd/r{rlineto}bd/c{curveto}bd/m{moveto}bd"
+ "/p{closepath}bd/n{newpath}bd");
+ mp_ps_print_nl(mp, "/C{setcmykcolor}bd/G{setgray}bd/R{setrgbcolor}bd"
+ "/lj{setlinejoin}bd/ml{setmiterlimit}bd");
+ mp_ps_print_nl(mp, "/lc{setlinecap}bd/S{stroke}bd/F{fill}bd/q{gsave}bd"
+ "/Q{grestore}bd/s{scale}bd/t{concat}bd");
+ mp_ps_print_nl(mp, "/sd{setdash}bd/rd{[] 0 setdash}bd/P{showpage}bd/B{q F Q}bd/W{clip}bd");
+}
+
+
+@ The prologue defines \.{fshow} and corrects for the fact that \.{fshow}
+arguments use |font_name| instead of |font_ps_name|. Downloaded bitmap fonts
+might not have reasonable |font_ps_name| entries, but we just charge ahead
+anyway. The user should not make \&{prologues} positive if this will cause
+trouble.
+@:prologues_}{\&{prologues} primitive@>
+
+@<Exported...@>=
+void mp_print_prologue (MP mp, mp_edge_object *h, int prologues, int procset);
+
+@ @c
+void mp_print_prologue (MP mp, mp_edge_object *h, int prologues, int procset) {
+ font_number f;
+ font_number ldf ;
+ ldf = mp_print_font_comments (mp, h, prologues);
+ mp_ps_print_ln(mp);
+ if ( (prologues==1) && (mp->last_ps_fnum<mp->last_fnum) )
+ mp_read_psname_table(mp);
+ mp_ps_print(mp, "%%BeginProlog"); mp_ps_print_ln(mp);
+ if ( (prologues>0)||(procset>0) ) {
+ if ( ldf!=null_font ) {
+ if ( prologues>0 ) {
+ for (f=null_font+1;f<=mp->last_fnum;f++) {
+ if ( mp_has_font_size(mp,f) ) {
+ mp_ps_name_out(mp, mp->font_name[f],true);
+ mp_ps_name_out(mp, mp->font_ps_name[f],true);
+ mp_ps_print(mp, " def");
+ mp_ps_print_ln(mp);
+ }
+ }
+ if ( procset==0 ) {
+ mp_ps_print(mp, "/fshow {exch findfont exch scalefont setfont show}bind def");
+ mp_ps_print_ln(mp);
+ }
+ }
+ }
+ if (procset>0 ) {
+ mp_ps_print_nl(mp, "%%BeginResource: procset mpost");
+ if ( (prologues>0)&&(ldf!=null_font) )
+ mp_ps_print_nl(mp,
+ "/bd{bind def}bind def/fshow {exch findfont exch scalefont setfont show}bd");
+ else
+ mp_ps_print_nl(mp, "/bd{bind def}bind def");
+ @<Print the procset@>;
+ mp_ps_print_nl(mp, "%%EndResource");
+ mp_ps_print_ln(mp);
+ }
+ }
+ mp_ps_print(mp, "%%EndProlog");
+ mp_ps_print_nl(mp, "%%Page: 1 1"); mp_ps_print_ln(mp);
+}
+
+@ \MP\ used to have one single routine to print to both `write' files
+and the PostScript output. Web2c redefines ``Character |k| cannot be
+printed'', and that resulted in some bugs where 8-bit characters were
+written to the PostScript file (reported by Wlodek Bzyl).
+
+Also, Hans Hagen requested spaces to be output as "\\040" instead of
+a plain space, since that makes it easier to parse the result file
+for postprocessing.
+
+@<Character |k| is not allowed in PostScript output@>=
+ (k<=' ')||(k>'~')
+
+@ We often need to print a pair of coordinates.
+
+@c
+void mp_ps_pair_out (MP mp,scaled x, scaled y) {
+ ps_room(26);
+ mp_ps_print_scaled(mp, x); mp_ps_print_char(mp, ' ');
+ mp_ps_print_scaled(mp, y); mp_ps_print_char(mp, ' ');
+}
+
+@ @<Exported...@>=
+void mp_ps_pair_out (MP mp,scaled x, scaled y) ;
+
+@ @c
+void mp_ps_print_cmd (MP mp, const char *l, const char *s) {
+ if ( mp->internal[mp_procset]>0 ) { ps_room(strlen(s)); mp_ps_print(mp,s); }
+ else { ps_room(strlen(l)); mp_ps_print(mp, l); };
+}
+
+@ @<Exported...@>=
+void mp_ps_print_cmd (MP mp, const char *l, const char *s) ;
+
+@ @c
+void mp_ps_string_out (MP mp, const char *s) {
+ ASCII_code k; /* bits to be converted to octal */
+ mp_ps_print(mp, "(");
+ while ((k=*s++)) {
+ if ( mp->ps->ps_offset+5>mp->max_print_line ) {
+ mp_ps_print_char(mp, '\\');
+ mp_ps_print_ln(mp);
+ }
+ if ( (@<Character |k| is not allowed in PostScript output@>) ) {
+ mp_ps_print_char(mp, '\\');
+ mp_ps_print_char(mp, '0'+(k / 64));
+ mp_ps_print_char(mp, '0'+((k / 8) % 8));
+ mp_ps_print_char(mp, '0'+(k % 8));
+ } else {
+ if ( (k=='(')||(k==')')||(k=='\\') )
+ mp_ps_print_char(mp, '\\');
+ mp_ps_print_char(mp, k);
+ }
+ }
+ mp_ps_print_char(mp, ')');
+}
+
+@ @<Exported...@>=
+void mp_ps_string_out (MP mp, const char *s) ;
+
+@ This is a define because the function does not use its |mp| argument.
+
+@d mp_is_ps_name(M,A) mp_do_is_ps_name(A)
+
+@c
+static boolean mp_do_is_ps_name (char *s) {
+ ASCII_code k; /* the character being checked */
+ while ((k=*s++)) {
+ if ( (k<=' ')||(k>'~') ) return false;
+ if ( (k=='(')||(k==')')||(k=='<')||(k=='>')||
+ (k=='{')||(k=='}')||(k=='/')||(k=='%') ) return false;
+ }
+ return true;
+}
+
+@ @<Exported...@>=
+void mp_ps_name_out (MP mp, char *s, boolean lit) ;
+
+@ @c
+void mp_ps_name_out (MP mp, char *s, boolean lit) {
+ ps_room(strlen(s)+2);
+ mp_ps_print_char(mp, ' ');
+ if ( mp_is_ps_name(mp, s) ) {
+ if ( lit ) mp_ps_print_char(mp, '/');
+ mp_ps_print(mp, s);
+ } else {
+ mp_ps_string_out(mp, s);
+ if ( ! lit ) mp_ps_print(mp, "cvx ");
+ mp_ps_print(mp, "cvn");
+ }
+}
+
+
+@ These special comments described in the {\sl PostScript Language Reference
+Manual}, 2nd.~edition are understood by some \ps-reading programs.
+We can't normally output ``conforming'' \ps\ because
+the structuring conventions don't allow us to say ``Please make sure the
+following characters are downloaded and define the \.{fshow} macro to access
+them.''
+
+The exact bounding box is written out if |mp_prologues<0|, although this
+is not standard \ps, since it allows \TeX\ to calculate the box dimensions
+accurately. (Overfull boxes are avoided if an illustration is made to
+match a given \.{\char`\\hsize}.)
+
+@<Exported...@>=
+void mp_print_initial_comment(MP mp,mp_edge_object *hh, int prologues);
+
+@ @c
+void mp_print_initial_comment(MP mp,mp_edge_object *hh, int prologues) {
+ scaled t;
+ mp_ps_print(mp, "%!PS");
+ if ( prologues>0 )
+ mp_ps_print(mp, "-Adobe-3.0 EPSF-3.0");
+ mp_ps_print_nl(mp, "%%BoundingBox: ");
+ if ( hh->_minx>hh->_maxx) {
+ mp_ps_print(mp, "0 0 0 0");
+ } else if ( prologues<0 ) {
+ mp_ps_pair_out(mp, hh->_minx,hh->_miny);
+ mp_ps_pair_out(mp, hh->_maxx,hh->_maxy);
+ } else {
+ mp_ps_pair_out(mp, mp_floor_scaled(mp, hh->_minx),mp_floor_scaled(mp, hh->_miny));
+ mp_ps_pair_out(mp, -mp_floor_scaled(mp, -hh->_maxx),-mp_floor_scaled(mp, -hh->_maxy));
+ }
+ mp_ps_print_nl(mp, "%%HiResBoundingBox: ");
+ if ( hh->_minx>hh->_maxx ) {
+ mp_ps_print(mp, "0 0 0 0");
+ } else {
+ mp_ps_pair_out(mp, hh->_minx,hh->_miny);
+ mp_ps_pair_out(mp, hh->_maxx,hh->_maxy);
+ }
+ mp_ps_print_nl(mp, "%%Creator: MetaPost ");
+ mp_ps_print(mp, mp_metapost_version(mp));
+ mp_ps_print_nl(mp, "%%CreationDate: ");
+ mp_ps_print_int(mp, mp_round_unscaled(mp, mp->internal[mp_year]));
+ mp_ps_print_char(mp, '.');
+ mp_ps_print_dd(mp, mp_round_unscaled(mp, mp->internal[mp_month]));
+ mp_ps_print_char(mp, '.');
+ mp_ps_print_dd(mp, mp_round_unscaled(mp, mp->internal[mp_day]));
+ mp_ps_print_char(mp, ':');
+ t=mp_round_unscaled(mp, mp->internal[mp_time]);
+ mp_ps_print_dd(mp, t / 60);
+ mp_ps_print_dd(mp, t % 60);
+ mp_ps_print_nl(mp, "%%Pages: 1");
+}
+
+@ The most important output procedure is the one that gives the \ps\ version of
+a \MP\ path.
+
+@<Types...@>=
+#define gr_left_type(A) (A)->left_type_field
+#define gr_right_type(A) (A)->right_type_field
+#define gr_x_coord(A) (A)->x_coord_field
+#define gr_y_coord(A) (A)->y_coord_field
+#define gr_left_x(A) (A)->left_x_field
+#define gr_left_y(A) (A)->left_y_field
+#define gr_right_x(A) (A)->right_x_field
+#define gr_right_y(A) (A)->right_y_field
+#define gr_next_knot(A) (A)->next_field
+#define gr_originator(A) (A)->originator_field
+typedef struct mp_knot {
+ unsigned short left_type_field;
+ unsigned short right_type_field;
+ scaled x_coord_field;
+ scaled y_coord_field;
+ scaled left_x_field;
+ scaled left_y_field;
+ scaled right_x_field;
+ scaled right_y_field;
+ struct mp_knot * next_field;
+ quarterword originator_field;
+} mp_knot;
+
+@ @c
+mp_knot * mp_gr_insert_knot (MP mp, mp_knot *q, scaled x, scaled y) {
+ /* returns the inserted knot */
+ mp_knot *r; /* the new knot */
+ r= mp_xmalloc(mp, 1, sizeof (mp_knot));
+ gr_next_knot(r)=gr_next_knot(q); gr_next_knot(q)=r;
+ gr_right_x(r)=gr_right_x(q);
+ gr_right_y(r)=gr_right_y(q);
+ gr_x_coord(r)=x;
+ gr_y_coord(r)=y;
+ gr_right_x(q)=gr_x_coord(q);
+ gr_right_y(q)=gr_y_coord(q);
+ gr_left_x(r)=gr_x_coord(r);
+ gr_left_y(r)=gr_y_coord(r);
+ gr_left_type(r)=mp_explicit;
+ gr_right_type(r)=mp_explicit;
+ gr_originator(r)=mp_program_code;
+ return r;
+}
+
+
+@ If we want to duplicate a knot node, we can say |copy_knot|:
+
+@c
+mp_knot *mp_gr_copy_knot (MP mp, mp_knot *p) {
+ mp_knot *q; /* the copy */
+ q = mp_xmalloc(mp, 1, sizeof (mp_knot));
+ memcpy(q,p,sizeof (mp_knot));
+ gr_next_knot(q)=NULL;
+ return q;
+}
+
+@ The |copy_path| routine makes a clone of a given path.
+
+@c
+mp_knot *mp_gr_copy_path (MP mp, mp_knot *p) {
+ mp_knot *q, *pp, *qq; /* for list manipulation */
+ if (p==NULL)
+ return NULL;
+ q=mp_gr_copy_knot(mp, p);
+ qq=q;
+ pp=gr_next_knot(p);
+ while ( pp!=p ) {
+ gr_next_knot(qq)=mp_gr_copy_knot(mp, pp);
+ qq=gr_next_knot(qq);
+ pp=gr_next_knot(pp);
+ }
+ gr_next_knot(qq)=q;
+ return q;
+}
+
+@ Similarly, there's a way to copy the {\sl reverse\/} of a path. This procedure
+returns a pointer to the first node of the copy, if the path is a cycle,
+but to the final node of a non-cyclic copy. The global
+variable |path_tail| will point to the final node of the original path;
+this trick makes it easier to implement `\&{doublepath}'.
+
+All node types are assumed to be |endpoint| or |explicit| only.
+
+This function is currenly unused.
+
+@c
+mp_knot * mp_gr_htap_ypoc (MP mp, mp_knot *p) {
+ mp_knot *q, *pp, *qq, *rr; /* for list manipulation */
+ q=mp_xmalloc(mp, 1, sizeof (mp_knot)); /* this will correspond to |p| */
+ qq=q; pp=p;
+ while (1) {
+ gr_right_type(qq)=gr_left_type(pp);
+ gr_left_type(qq)=gr_right_type(pp);
+ gr_x_coord(qq)=gr_x_coord(pp);
+ gr_y_coord(qq)=gr_y_coord(pp);
+ gr_right_x(qq)=gr_left_x(pp);
+ gr_right_y(qq)=gr_left_y(pp);
+ gr_left_x(qq)=gr_right_x(pp);
+ gr_left_y(qq)=gr_right_y(pp);
+ gr_originator(qq)=gr_originator(pp);
+ if ( gr_next_knot(pp)==p ) {
+ gr_next_knot(q)=qq;
+ /* mp->path_tail=pp; */ /* ? */
+ return q;
+ }
+ rr=mp_xmalloc(mp, 1, sizeof (mp_knot));
+ gr_next_knot(rr)=qq;
+ qq=rr;
+ pp=gr_next_knot(pp);
+ }
+}
+
+@ When a cyclic list of knot nodes is no longer needed, it can be recycled by
+calling the following subroutine.
+
+@<Declarations@>=
+void mp_do_gr_toss_knot_list (mp_knot *p) ;
+
+@
+@d mp_gr_toss_knot_list(B,A) mp_do_gr_toss_knot_list(A)
+
+@c
+void mp_do_gr_toss_knot_list (mp_knot * p) {
+ mp_knot *q; /* the node being freed */
+ mp_knot *r; /* the next node */
+ if (p==NULL)
+ return;
+ q=p;
+ do {
+ r=gr_next_knot(q);
+ mp_xfree(q); q=r;
+ } while (q!=p);
+}
+
+
+
+@ @c
+void mp_gr_ps_path_out (MP mp, mp_knot *h) {
+ mp_knot *p, *q; /* for scanning the path */
+ scaled d; /* a temporary value */
+ boolean curved; /* |true| unless the cubic is almost straight */
+ ps_room(40);
+ mp_ps_print_cmd(mp, "newpath ","n ");
+ mp_ps_pair_out(mp, gr_x_coord(h),gr_y_coord(h));
+ mp_ps_print_cmd(mp, "moveto","m");
+ p=h;
+ do {
+ if ( gr_right_type(p)==mp_endpoint ) {
+ if ( p==h ) mp_ps_print_cmd(mp, " 0 0 rlineto"," 0 0 r");
+ return;
+ }
+ q=gr_next_knot(p);
+ @<Start a new line and print the \ps\ commands for the curve from
+ |p| to~|q|@>;
+ p=q;
+ } while (p!=h);
+ mp_ps_print_cmd(mp, " closepath"," p");
+}
+
+@ @<Start a new line and print the \ps\ commands for the curve from...@>=
+curved=true;
+@<Set |curved:=false| if the cubic from |p| to |q| is almost straight@>;
+mp_ps_print_ln(mp);
+if ( curved ){
+ mp_ps_pair_out(mp, gr_right_x(p),gr_right_y(p));
+ mp_ps_pair_out(mp, gr_left_x(q),gr_left_y(q));
+ mp_ps_pair_out(mp, gr_x_coord(q),gr_y_coord(q));
+ mp_ps_print_cmd(mp, "curveto","c");
+} else if ( q!=h ){
+ mp_ps_pair_out(mp, gr_x_coord(q),gr_y_coord(q));
+ mp_ps_print_cmd(mp, "lineto","l");
+}
+
+@ Two types of straight lines come up often in \MP\ paths:
+cubics with zero initial and final velocity as created by |make_path| or
+|make_envelope|, and cubics with control points uniformly spaced on a line
+as created by |make_choices|.
+
+@d bend_tolerance 131 /* allow rounding error of $2\cdot10^{-3}$ */
+
+@<Set |curved:=false| if the cubic from |p| to |q| is almost straight@>=
+if ( gr_right_x(p)==gr_x_coord(p) )
+ if ( gr_right_y(p)==gr_y_coord(p) )
+ if ( gr_left_x(q)==gr_x_coord(q) )
+ if ( gr_left_y(q)==gr_y_coord(q) ) curved=false;
+d=gr_left_x(q)-gr_right_x(p);
+if ( abs(gr_right_x(p)-gr_x_coord(p)-d)<=bend_tolerance )
+ if ( abs(gr_x_coord(q)-gr_left_x(q)-d)<=bend_tolerance )
+ { d=gr_left_y(q)-gr_right_y(p);
+ if ( abs(gr_right_y(p)-gr_y_coord(p)-d)<=bend_tolerance )
+ if ( abs(gr_y_coord(q)-gr_left_y(q)-d)<=bend_tolerance ) curved=false;
+ }
+
+@ The colored objects use a struct with anonymous fields to express the color parts:
+
+@<Types...@>=
+typedef struct {
+ scaled _a_val, _b_val, _c_val, _d_val;
+} mp_color;
+
+@ The exported form of a dash pattern is simpler than the internal
+format, it is closely modelled to the PostScript model. The array of
+dashes is ended by a single negative value, because this is not
+allowed in PostScript.
+
+@d gr_dash_scale(A) (gr_dash_p(A))->scale_field
+
+@<Types...@>=
+typedef struct {
+ scaled offset_field;
+ scaled scale_field;
+ scaled *array_field;
+} mp_dash_object ;
+
+
+@
+@d mp_gr_toss_dashes(A,B) mp_do_gr_toss_dashes(B)
+
+@<Declarations@>=
+void mp_do_gr_toss_dashes(mp_dash_object *dl);
+
+@ @c
+void mp_do_gr_toss_dashes(mp_dash_object *dl) {
+ if (dl==NULL)
+ return;
+ mp_xfree(dl->array_field);
+ mp_xfree(dl);
+}
+
+
+@ @c
+mp_dash_object *mp_gr_copy_dashes(MP mp, mp_dash_object *dl) {
+ mp_dash_object *q = NULL;
+ (void)mp;
+ if (dl==NULL)
+ return NULL;
+ q = mp_xmalloc(mp, 1, sizeof (mp_dash_object));
+ memcpy (q,dl,sizeof(mp_dash_object));
+ if (dl->array_field != NULL) {
+ int i = 0;
+ while (*(dl->array_field+i) != -1) i++;
+ q->array_field = mp_xmalloc(mp, i, sizeof (scaled));
+ memcpy(q->array_field,dl->array_field, (i*sizeof(scaled)));
+ }
+ return q;
+}
+
+
+@ Now for outputting the actual graphic objects. First, set up some
+structures and access macros.
+
+@d gr_has_color(A) (gr_type((A))<mp_start_clip_code)
+
+@<Types...@>=
+#define gr_type(A) (A)->_type_field
+#define gr_link(A) (A)->_link_field
+#define gr_color_model(A) (A)->color_model_field
+#define gr_red_val(A) (A)->color_field._a_val
+#define gr_green_val(A) (A)->color_field._b_val
+#define gr_blue_val(A) (A)->color_field._c_val
+#define gr_cyan_val(A) (A)->color_field._a_val
+#define gr_magenta_val(A) (A)->color_field._b_val
+#define gr_yellow_val(A) (A)->color_field._c_val
+#define gr_black_val(A) (A)->color_field._d_val
+#define gr_grey_val(A) (A)->color_field._a_val
+#define gr_path_p(A) (A)->path_p_field
+#define gr_htap_p(A) ((mp_fill_object *)A)->htap_p_field
+#define gr_pen_p(A) (A)->pen_p_field
+#define gr_ljoin_val(A) (A)->ljoin_field
+#define gr_lcap_val(A) ((mp_stroked_object *)A)->lcap_field
+#define gr_miterlim_val(A) (A)->miterlim_field
+#define gr_pre_script(A) (A)->pre_script_field
+#define gr_post_script(A) (A)->post_script_field
+#define gr_dash_p(A) ((mp_stroked_object *)A)->dash_p_field
+#define gr_name_type(A) ((mp_text_object *)A)->name_type_field
+#define gr_text_p(A) ((mp_text_object *)A)->text_p_field
+#define gr_font_n(A) ((mp_text_object *)A)->font_n_field
+#define gr_font_name(A) ((mp_text_object *)A)->font_name_field
+#define gr_font_dsize(A) ((mp_text_object *)A)->font_dsize_field
+#define gr_width_val(A) ((mp_text_object *)A)->width_field
+#define gr_height_val(A) ((mp_text_object *)A)->height_field
+#define gr_depth_val(A) ((mp_text_object *)A)->depth_field
+#define gr_tx_val(A) ((mp_text_object *)A)->tx_field
+#define gr_ty_val(A) ((mp_text_object *)A)->ty_field
+#define gr_txx_val(A) ((mp_text_object *)A)->txx_field
+#define gr_txy_val(A) ((mp_text_object *)A)->txy_field
+#define gr_tyx_val(A) ((mp_text_object *)A)->tyx_field
+#define gr_tyy_val(A) ((mp_text_object *)A)->tyy_field
+
+#define GRAPHIC_BODY \
+ halfword _type_field; \
+ struct mp_graphic_object * _link_field
+
+typedef struct mp_graphic_object {
+ GRAPHIC_BODY;
+} mp_graphic_object;
+
+typedef struct mp_text_object {
+ GRAPHIC_BODY;
+ char *pre_script_field;
+ char *post_script_field;
+ mp_color color_field;
+ quarterword color_model_field;
+ quarterword name_type_field;
+ char *text_p_field;
+ char *font_name_field ;
+ scaled font_dsize_field ;
+ font_number font_n_field ;
+ scaled width_field ;
+ scaled height_field ;
+ scaled depth_field ;
+ scaled tx_field ;
+ scaled ty_field ;
+ scaled txx_field ;
+ scaled txy_field ;
+ scaled tyx_field ;
+ scaled tyy_field ;
+} mp_text_object;
+
+typedef struct mp_fill_object {
+ GRAPHIC_BODY;
+ char *pre_script_field;
+ char *post_script_field;
+ mp_color color_field;
+ quarterword color_model_field;
+ quarterword ljoin_field ;
+ mp_knot * path_p_field;
+ mp_knot * htap_p_field;
+ mp_knot * pen_p_field;
+ scaled miterlim_field ;
+} mp_fill_object;
+
+typedef struct mp_stroked_object {
+ GRAPHIC_BODY;
+ char *pre_script_field;
+ char *post_script_field;
+ mp_color color_field;
+ quarterword color_model_field;
+ quarterword ljoin_field ;
+ quarterword lcap_field ;
+ mp_knot * path_p_field;
+ mp_knot * pen_p_field;
+ scaled miterlim_field ;
+ mp_dash_object *dash_p_field;
+} mp_stroked_object;
+
+typedef struct mp_clip_object {
+ GRAPHIC_BODY;
+ mp_knot * path_p_field;
+} mp_clip_object;
+
+typedef struct mp_bounds_object {
+ GRAPHIC_BODY;
+ mp_knot * path_p_field;
+} mp_bounds_object;
+
+typedef struct mp_special_object {
+ GRAPHIC_BODY;
+ char *pre_script_field;
+} mp_special_object ;
+
+typedef struct mp_edge_object {
+ struct mp_graphic_object * body;
+ struct mp_edge_object * _next;
+ char * _filename;
+ MP _parent;
+ scaled _minx, _miny, _maxx, _maxy;
+} mp_edge_object;
+
+@ @<Exported function headers@>=
+mp_graphic_object *mp_new_graphic_object(MP mp, int type);
+
+@ @c
+mp_graphic_object *mp_new_graphic_object (MP mp, int type) {
+ mp_graphic_object *p;
+ int size ;
+ switch (type) {
+ case mp_fill_code: size = sizeof(mp_fill_object); break;
+ case mp_stroked_code: size = sizeof(mp_stroked_object); break;
+ case mp_text_code: size = sizeof(mp_text_object); break;
+ case mp_start_clip_code: size = sizeof(mp_clip_object); break;
+ case mp_start_bounds_code: size = sizeof(mp_bounds_object); break;
+ case mp_special_code: size = sizeof(mp_special_object); break;
+ default: size = sizeof(mp_graphic_object); break;
+ }
+ p = (mp_graphic_object *)mp_xmalloc(mp,1,size);
+ memset(p,0,size);
+ gr_type(p) = type;
+ return p;
+}
+
+@ We need to keep track of several parameters from the \ps\ graphics state.
+@^graphics state@>
+This allows us to be sure that \ps\ has the correct values when they are
+needed without wasting time and space setting them unnecessarily.
+
+@d gs_red mp->ps->gs_state->red_field
+@d gs_green mp->ps->gs_state->green_field
+@d gs_blue mp->ps->gs_state->blue_field
+@d gs_black mp->ps->gs_state->black_field
+@d gs_colormodel mp->ps->gs_state->colormodel_field
+@d gs_ljoin mp->ps->gs_state->ljoin_field
+@d gs_lcap mp->ps->gs_state->lcap_field
+@d gs_adj_wx mp->ps->gs_state->adj_wx_field
+@d gs_miterlim mp->ps->gs_state->miterlim_field
+@d gs_dash_p mp->ps->gs_state->dash_p_field
+@d gs_dash_init_done mp->ps->gs_state->dash_done_field
+@d gs_previous mp->ps->gs_state->previous_field
+@d gs_width mp->ps->gs_state->width_field
+
+@<Types...@>=
+typedef struct _gs_state {
+ scaled red_field ;
+ scaled green_field ;
+ scaled blue_field ;
+ scaled black_field ;
+ /* color from the last \&{setcmykcolor} or \&{setrgbcolor} or \&{setgray} command */
+ quarterword colormodel_field ;
+ /* the current colormodel */
+ quarterword ljoin_field ;
+ quarterword lcap_field ;
+ /* values from the last \&{setlinejoin} and \&{setlinecap} commands */
+ quarterword adj_wx_field ;
+ /* what resolution-dependent adjustment applies to the width */
+ scaled miterlim_field ;
+ /* the value from the last \&{setmiterlimit} command */
+ mp_dash_object * dash_p_field ;
+ /* edge structure for last \&{setdash} command */
+ boolean dash_done_field ; /* to test for initial \&{setdash} */
+ struct _gs_state * previous_field ;
+ /* backlink to the previous |_gs_state| structure */
+ scaled width_field ;
+ /* width setting or $-1$ if no \&{setlinewidth} command so far */
+} _gs_state;
+
+
+@ @<Glob...@>=
+struct _gs_state * gs_state;
+
+@ @<Set init...@>=
+mp->ps->gs_state=NULL;
+
+@ @<Dealloc variables@>=
+mp_xfree(mp->ps->gs_state);
+
+@ To avoid making undue assumptions about the initial graphics state, these
+parameters are given special values that are guaranteed not to match anything
+in the edge structure being shipped out. On the other hand, the initial color
+should be black so that the translation of an all-black picture will have no
+\&{setcolor} commands. (These would be undesirable in a font application.)
+Hence we use |c=0| when initializing the graphics state and we use |c<0|
+to recover from a situation where we have lost track of the graphics state.
+
+@c
+void mp_gs_unknown_graphics_state (MP mp,scaled c) ;
+
+@
+@d mp_void (null+1) /* a null pointer different from |null| */
+
+@c void mp_gs_unknown_graphics_state (MP mp,scaled c) {
+ struct _gs_state *p; /* to shift graphic states around */
+ if ( (c==0)||(c==-1) ) {
+ if ( mp->ps->gs_state==NULL ) {
+ mp->ps->gs_state = mp_xmalloc(mp,1,sizeof(struct _gs_state));
+ gs_previous=NULL;
+ } else {
+ while ( gs_previous!=NULL ) {
+ p = gs_previous;
+ mp_xfree(mp->ps->gs_state);
+ mp->ps->gs_state=p;
+ }
+ }
+ gs_red=c; gs_green=c; gs_blue=c; gs_black=c;
+ gs_colormodel=mp_uninitialized_model;
+ gs_ljoin=3;
+ gs_lcap=3;
+ gs_miterlim=0;
+ gs_dash_p=NULL;
+ gs_dash_init_done=false;
+ gs_width=-1;
+ } else if ( c==1 ) {
+ p= mp->ps->gs_state;
+ mp->ps->gs_state = mp_xmalloc(mp,1,sizeof(struct _gs_state));
+ memcpy(mp->ps->gs_state,p,sizeof(struct _gs_state));
+ gs_previous = p;
+ } else if ( c==2 ) {
+ p = gs_previous;
+ mp_xfree(mp->ps->gs_state);
+ mp->ps->gs_state=p;
+ }
+}
+
+
+@ When it is time to output a graphical object, |fix_graphics_state| ensures
+that \ps's idea of the graphics state agrees with what is stored in the object.
+
+@<Declarations@>=
+void mp_gr_fix_graphics_state (MP mp, mp_graphic_object *p) ;
+
+@ @c
+void mp_gr_fix_graphics_state (MP mp, mp_graphic_object *p) {
+ /* get ready to output graphical object |p| */
+ mp_knot *pp, *path_p; /* for list manipulation */
+ mp_dash_object *hh;
+ scaled wx,wy,ww; /* dimensions of pen bounding box */
+ boolean adj_wx; /* whether pixel rounding should be based on |wx| or |wy| */
+ integer tx,ty; /* temporaries for computing |adj_wx| */
+ scaled scf; /* a scale factor for the dash pattern */
+ if ( gr_has_color(p) )
+ @<Make sure \ps\ will use the right color for object~|p|@>;
+ if ( (gr_type(p)==mp_fill_code)||(gr_type(p)==mp_stroked_code) ) {
+ if (gr_type(p)==mp_fill_code) {
+ pp = gr_pen_p((mp_fill_object *)p);
+ path_p = gr_path_p((mp_fill_object *)p);
+ } else {
+ pp = gr_pen_p((mp_stroked_object *)p);
+ path_p = gr_path_p((mp_stroked_object *)p);
+ }
+ if ( pp!=NULL )
+ if ( pen_is_elliptical(pp) ) {
+ @<Generate \ps\ code that sets the stroke width to the
+ appropriate rounded value@>;
+ @<Make sure \ps\ will use the right dash pattern for |dash_p(p)|@>;
+ @<Decide whether the line cap parameter matters and set it if necessary@>;
+ @<Set the other numeric parameters as needed for object~|p|@>;
+ }
+ }
+ if ( mp->ps->ps_offset>0 ) mp_ps_print_ln(mp);
+}
+
+@ @<Decide whether the line cap parameter matters and set it if necessary@>=
+if ( gr_type(p)==mp_stroked_code ) {
+ mp_stroked_object *ts = (mp_stroked_object *)p;
+ if ( (gr_left_type(gr_path_p(ts))==mp_endpoint)||(gr_dash_p(ts)!=NULL) )
+ if ( gs_lcap!=gr_lcap_val(ts) ) {
+ ps_room(13);
+ mp_ps_print_char(mp, ' ');
+ mp_ps_print_char(mp, '0'+gr_lcap_val(ts));
+ mp_ps_print_cmd(mp, " setlinecap"," lc");
+ gs_lcap=gr_lcap_val(ts);
+ }
+}
+
+@
+@d set_ljoin_miterlim(p)
+ if ( gs_ljoin!=gr_ljoin_val(p) ) {
+ ps_room(14);
+ mp_ps_print_char(mp, ' ');
+ mp_ps_print_char(mp, '0'+gr_ljoin_val(p));
+ mp_ps_print_cmd(mp, " setlinejoin"," lj");
+ gs_ljoin=gr_ljoin_val(p);
+ }
+ if ( gs_miterlim!=gr_miterlim_val(p) ) {
+ ps_room(27);
+ mp_ps_print_char(mp, ' ');
+ mp_ps_print_scaled(mp, gr_miterlim_val(p));
+ mp_ps_print_cmd(mp, " setmiterlimit"," ml");
+ gs_miterlim=gr_miterlim_val(p);
+ }
+
+@<Set the other numeric parameters as needed for object~|p|@>=
+if ( gr_type(p)==mp_stroked_code ) {
+ mp_stroked_object *ts = (mp_stroked_object *)p;
+ set_ljoin_miterlim(ts);
+} else {
+ mp_fill_object *ts = (mp_fill_object *)p;
+ set_ljoin_miterlim(ts);
+}
+
+@
+@d set_color_objects(pq)
+ object_color_model = pq->color_model_field;
+ object_color_a = pq->color_field._a_val;
+ object_color_b = pq->color_field._b_val;
+ object_color_c = pq->color_field._c_val;
+ object_color_d = pq->color_field._d_val;
+
+@<Make sure \ps\ will use the right color for object~|p|@>=
+{
+ int object_color_model;
+ int object_color_a, object_color_b, object_color_c, object_color_d ;
+ if (gr_type(p) == mp_fill_code) {
+ mp_fill_object *pq = (mp_fill_object *)p;
+ set_color_objects(pq);
+ } else if (gr_type(p) == mp_stroked_code) {
+ mp_stroked_object *pq = (mp_stroked_object *)p;
+ set_color_objects(pq);
+ } else {
+ mp_text_object *pq = (mp_text_object *)p;
+ set_color_objects(pq);
+ }
+
+ if ( object_color_model==mp_rgb_model) {
+ if ( (gs_colormodel!=mp_rgb_model)||(gs_red!=object_color_a)||
+ (gs_green!=object_color_b)||(gs_blue!=object_color_c) ) {
+ gs_red = object_color_a;
+ gs_green = object_color_b;
+ gs_blue = object_color_c;
+ gs_black = -1;
+ gs_colormodel=mp_rgb_model;
+ { ps_room(36);
+ mp_ps_print_char(mp, ' ');
+ mp_ps_print_scaled(mp, gs_red); mp_ps_print_char(mp, ' ');
+ mp_ps_print_scaled(mp, gs_green); mp_ps_print_char(mp, ' ');
+ mp_ps_print_scaled(mp, gs_blue);
+ mp_ps_print_cmd(mp, " setrgbcolor", " R");
+ }
+ }
+ } else if ( object_color_model==mp_cmyk_model) {
+ if ( (gs_red!=object_color_a)||(gs_green!=object_color_b)||
+ (gs_blue!=object_color_c)||(gs_black!=object_color_d)||
+ (gs_colormodel!=mp_cmyk_model) ) {
+ gs_red = object_color_a;
+ gs_green = object_color_b;
+ gs_blue = object_color_c;
+ gs_black = object_color_d;
+ gs_colormodel=mp_cmyk_model;
+ { ps_room(45);
+ mp_ps_print_char(mp, ' ');
+ mp_ps_print_scaled(mp, gs_red);
+ mp_ps_print_char(mp, ' ');
+ mp_ps_print_scaled(mp, gs_green);
+ mp_ps_print_char(mp, ' ');
+ mp_ps_print_scaled(mp, gs_blue);
+ mp_ps_print_char(mp, ' ');
+ mp_ps_print_scaled(mp, gs_black);
+ mp_ps_print_cmd(mp, " setcmykcolor"," C");
+ }
+ }
+ } else if ( object_color_model==mp_grey_model ) {
+ if ( (gs_red!=object_color_a)||(gs_colormodel!=mp_grey_model) ) {
+ gs_red = object_color_a;
+ gs_green = -1;
+ gs_blue = -1;
+ gs_black = -1;
+ gs_colormodel=mp_grey_model;
+ { ps_room(16);
+ mp_ps_print_char(mp, ' ');
+ mp_ps_print_scaled(mp, gs_red);
+ mp_ps_print_cmd(mp, " setgray"," G");
+ }
+ }
+ } else if ( object_color_model==mp_no_model ) {
+ gs_colormodel=mp_no_model;
+ }
+}
+
+@ In order to get consistent widths for horizontal and vertical pen strokes, we
+want \ps\ to use an integer number of pixels for the \&{setwidth} parameter.
+@:setwidth}{\&{setwidth}command@>
+We set |gs_width| to the ideal horizontal or vertical stroke width and then
+generate \ps\ code that computes the rounded value. For non-circular pens, the
+pen shape will be rescaled so that horizontal or vertical parts of the stroke
+have the computed width.
+
+Rounding the width to whole pixels is not likely to improve the appearance of
+diagonal or curved strokes, but we do it anyway for consistency. The
+\&{truncate} command generated here tends to make all the strokes a little
+@:truncate}{\&{truncate} command@>
+thinner, but this is appropriate for \ps's scan-conversion rules. Even with
+truncation, an ideal with of $w$~pixels gets mapped into $\lfloor w\rfloor+1$.
+It would be better to have $\lceil w\rceil$ but that is ridiculously expensive
+to compute in \ps.
+
+@<Generate \ps\ code that sets the stroke width...@>=
+@<Set |wx| and |wy| to the width and height of the bounding box for
+ |pen_p(p)|@>;
+@<Use |pen_p(p)| and |path_p(p)| to decide whether |wx| or |wy| is more
+ important and set |adj_wx| and |ww| accordingly@>;
+if ( (ww!=gs_width) || (adj_wx!=gs_adj_wx) ) {
+ if ( adj_wx ) {
+ ps_room(13);
+ mp_ps_print_char(mp, ' '); mp_ps_print_scaled(mp, ww);
+ mp_ps_print_cmd(mp,
+ " 0 dtransform exch truncate exch idtransform pop setlinewidth"," hlw");
+ } else {
+ if ( mp->internal[mp_procset]>0 ) {
+ ps_room(13);
+ mp_ps_print_char(mp, ' ');
+ mp_ps_print_scaled(mp, ww);
+ mp_ps_print(mp, " vlw");
+ } else {
+ ps_room(15);
+ mp_ps_print(mp, " 0 "); mp_ps_print_scaled(mp, ww);
+ mp_ps_print(mp, " dtransform truncate idtransform setlinewidth pop");
+ }
+ }
+ gs_width = ww;
+ gs_adj_wx = adj_wx;
+}
+
+@ @<Set |wx| and |wy| to the width and height of the bounding box for...@>=
+if ( (gr_right_x(pp)==gr_x_coord(pp)) && (gr_left_y(pp)==gr_y_coord(pp)) ) {
+ wx = abs(gr_left_x(pp) - gr_x_coord(pp));
+ wy = abs(gr_right_y(pp) - gr_y_coord(pp));
+} else {
+ wx = mp_pyth_add(mp, gr_left_x(pp)-gr_x_coord(pp), gr_right_x(pp)-gr_x_coord(pp));
+ wy = mp_pyth_add(mp, gr_left_y(pp)-gr_y_coord(pp), gr_right_y(pp)-gr_y_coord(pp));
+}
+
+@ The path is considered ``essentially horizontal'' if its range of
+$y$~coordinates is less than the $y$~range |wy| for the pen. ``Essentially
+vertical'' paths are detected similarly. This code ensures that no component
+of the pen transformation is more that |aspect_bound*(ww+1)|.
+
+@d aspect_bound 10 /* ``less important'' of |wx|, |wy| cannot exceed the other by
+ more than this factor */
+
+@d do_x_loc 1
+@d do_y_loc 2
+
+@<Use |pen_p(p)| and |path_p(p)| to decide whether |wx| or |wy| is more...@>=
+tx=1; ty=1;
+if ( mp_gr_coord_rangeOK(path_p, do_y_loc, wy) ) tx=aspect_bound;
+else if ( mp_gr_coord_rangeOK(path_p, do_x_loc, wx) ) ty=aspect_bound;
+if ( wy / ty>=wx / tx ) { ww=wy; adj_wx=false; }
+else { ww=wx; adj_wx=true; }
+
+@ This routine quickly tests if path |h| is ``essentially horizontal'' or
+``essentially vertical,'' where |zoff| is |x_loc(0)| or |y_loc(0)| and |dz| is
+allowable range for $x$ or~$y$. We do not need and cannot afford a full
+bounding-box computation.
+
+@<Declarations@>=
+boolean mp_gr_coord_rangeOK (mp_knot *h,
+ small_number zoff, scaled dz);
+
+@ @c
+boolean mp_gr_coord_rangeOK (mp_knot *h,
+ small_number zoff, scaled dz) {
+ mp_knot *p; /* for scanning the path form |h| */
+ scaled zlo,zhi; /* coordinate range so far */
+ scaled z; /* coordinate currently being tested */
+ if (zoff==do_x_loc) {
+ zlo=gr_x_coord(h);
+ zhi=zlo;
+ p=h;
+ while ( gr_right_type(p)!=mp_endpoint ) {
+ z=gr_right_x(p);
+ @<Make |zlo..zhi| include |z| and |return false| if |zhi-zlo>dz|@>;
+ p=gr_next_knot(p); z=gr_left_x(p);
+ @<Make |zlo..zhi| include |z| and |return false| if |zhi-zlo>dz|@>;
+ z=gr_x_coord(p);
+ @<Make |zlo..zhi| include |z| and |return false| if |zhi-zlo>dz|@>;
+ if ( p==h ) break;
+ }
+ } else {
+ zlo=gr_y_coord(h);
+ zhi=zlo;
+ p=h;
+ while ( gr_right_type(p)!=mp_endpoint ) {
+ z=gr_right_y(p);
+ @<Make |zlo..zhi| include |z| and |return false| if |zhi-zlo>dz|@>;
+ p=gr_next_knot(p); z=gr_left_y(p);
+ @<Make |zlo..zhi| include |z| and |return false| if |zhi-zlo>dz|@>;
+ z=gr_y_coord(p);
+ @<Make |zlo..zhi| include |z| and |return false| if |zhi-zlo>dz|@>;
+ if ( p==h ) break;
+ }
+ }
+ return true;
+}
+
+@ @<Make |zlo..zhi| include |z| and |return false| if |zhi-zlo>dz|@>=
+if ( z<zlo ) zlo=z;
+else if ( z>zhi ) zhi=z;
+if ( zhi-zlo>dz ) return false
+
+@ Filling with an elliptical pen is implemented via a combination of \&{stroke}
+and \&{fill} commands and a nontrivial dash pattern would interfere with this.
+@:stroke}{\&{stroke} command@>
+@:fill}{\&{fill} command@>
+Note that we don't use |delete_edge_ref| because |gs_dash_p| is not counted as
+a reference.
+
+@<Make sure \ps\ will use the right dash pattern for |dash_p(p)|@>=
+if ( gr_type(p)==mp_fill_code || gr_dash_p(p) == NULL) {
+ hh=NULL;
+} else {
+ hh=gr_dash_p(p);
+ scf=mp_gr_get_pen_scale(mp, gr_pen_p((mp_fill_object *)p));
+ if ( scf==0 ) {
+ if ( gs_width==0 ) scf=hh->scale_field; else hh=NULL;
+ } else {
+ scf=mp_make_scaled(mp, gs_width,scf);
+ scf=mp_take_scaled(mp, scf, (hh == NULL ? unity : gr_dash_scale(p)));
+ }
+}
+if ( hh==NULL ) {
+ if ( gs_dash_p!=NULL || gs_dash_init_done == false) {
+ mp_ps_print_cmd(mp, " [] 0 setdash"," rd");
+ gs_dash_p=NULL;
+ gs_dash_init_done=true;
+ }
+} else if ( ! mp_gr_same_dashes(gs_dash_p,hh) ) {
+ @<Set the dash pattern from |dash_list(hh)| scaled by |scf|@>;
+}
+
+@ @<Declarations@>=
+scaled mp_gr_get_pen_scale (MP mp, mp_knot *p) ;
+
+
+@ @c
+scaled mp_gr_get_pen_scale (MP mp, mp_knot *p) {
+ return mp_sqrt_det(mp,
+ gr_left_x(p)-gr_x_coord(p), gr_right_x(p)-gr_x_coord(p),
+ gr_left_y(p)-gr_y_coord(p), gr_right_y(p)-gr_y_coord(p));
+}
+
+
+@ The original code had a check here to ensure that the result from
+|mp_take_scaled| did not go out of bounds.
+
+@<Set the dash pattern from |dash_list(hh)| scaled by |scf|@>=
+{ gs_dash_p=hh;
+ if ( (gr_dash_p(p)==NULL) || (hh==NULL) || (hh->array_field==NULL)) {
+ mp_ps_print_cmd(mp, " [] 0 setdash"," rd");
+ } else {
+ int i;
+ ps_room(28);
+ mp_ps_print(mp, " [");
+ for (i=0; *(hh->array_field+i) != -1;i++) {
+ ps_room(13);
+ mp_ps_print_scaled(mp, *(hh->array_field+i));
+ mp_ps_print_char(mp, ' ') ;
+ }
+ ps_room(22);
+ mp_ps_print(mp, "] ");
+ mp_ps_print_scaled(mp, hh->offset_field);
+ mp_ps_print_cmd(mp, " setdash"," sd");
+ }
+}
+
+@ @<Declarations@>=
+boolean mp_gr_same_dashes (mp_dash_object *h, mp_dash_object *hh) ;
+
+@ This function test if |h| and |hh| represent the same dash pattern.
+
+The |scale_field| is ignored in this test because it is not really
+a property of the PostScript format of a dash pattern.
+
+@c
+boolean mp_gr_same_dashes (mp_dash_object *h, mp_dash_object *hh) {
+ boolean ret=false;
+ int i = 0;
+ if ( h==hh ) ret=true;
+ else if ( (h==NULL)||(hh==NULL) ) ret=false;
+ else if ( h->offset_field!=hh->offset_field ) ret=false;
+ else if ( h->array_field == hh->array_field) ret=true;
+ else if ( h->array_field == NULL || hh->array_field == NULL) ret=false;
+ else { @<Compare |dash_list(h)| and |dash_list(hh)|@>; }
+ return ret;
+}
+
+@ @<Compare |dash_list(h)| and |dash_list(hh)|@>=
+{
+ while (*(h->array_field+i)!=-1 &&
+ *(hh->array_field+i)!=-1 &&
+ *(h->array_field+i) == *(hh->array_field+i)) i++;
+ if (i>0) {
+ if (*(h->array_field+(i))==-1 && *(hh->array_field+(i)) == -1)
+ ret=true;
+ }
+}
+
+@ When stroking a path with an elliptical pen, it is necessary to transform
+the coordinate system so that a unit circular pen will have the desired shape.
+To keep this transformation local, we enclose it in a
+$$\&{gsave}\ldots\&{grestore}$$
+block. Any translation component must be applied to the path being stroked
+while the rest of the transformation must apply only to the pen.
+If |fill_also=true|, the path is to be filled as well as stroked so we must
+insert commands to do this after giving the path.
+
+@<Declarations@>=
+void mp_gr_stroke_ellipse (MP mp, mp_graphic_object *h, boolean fill_also) ;
+
+@
+@c void mp_gr_stroke_ellipse (MP mp, mp_graphic_object *h, boolean fill_also) {
+ /* generate an elliptical pen stroke from object |h| */
+ scaled txx,txy,tyx,tyy; /* transformation parameters */
+ mp_knot *p; /* the pen to stroke with */
+ scaled d1,det; /* for tweaking transformation parameters */
+ integer s; /* also for tweaking transformation paramters */
+ boolean transformed; /* keeps track of whether gsave/grestore are needed */
+ transformed=false;
+ @<Use |pen_p(h)| to set the transformation parameters and give the initial
+ translation@>;
+ @<Tweak the transformation parameters so the transformation is nonsingular@>;
+ if (gr_type(h)==mp_fill_code) {
+ mp_gr_ps_path_out(mp, gr_path_p((mp_fill_object *)h));
+ } else {
+ mp_gr_ps_path_out(mp, gr_path_p((mp_stroked_object *)h));
+ }
+ if ( mp->internal[mp_procset]==0 ) {
+ if ( fill_also ) mp_ps_print_nl(mp, "gsave fill grestore");
+ @<Issue \ps\ commands to transform the coordinate system@>;
+ mp_ps_print(mp, " stroke");
+ if ( transformed ) mp_ps_print(mp, " grestore");
+ } else {
+ if ( fill_also ) mp_ps_print_nl(mp, "B"); else mp_ps_print_ln(mp);
+ if ( (txy!=0)||(tyx!=0) ) {
+ mp_ps_print(mp, " [");
+ mp_ps_pair_out(mp, txx,tyx);
+ mp_ps_pair_out(mp, txy,tyy);
+ mp_ps_print(mp, "0 0] t");
+ } else if ((txx!=unity)||(tyy!=unity) ) {
+ mp_ps_pair_out(mp,txx,tyy);
+ mp_ps_print(mp, " s");
+ };
+ mp_ps_print(mp, " S");
+ if ( transformed ) mp_ps_print(mp, " Q");
+ }
+ mp_ps_print_ln(mp);
+}
+
+@ @<Use |pen_p(h)| to set the transformation parameters and give the...@>=
+if (gr_type(h)==mp_fill_code) {
+ p=gr_pen_p((mp_fill_object *)h);
+} else {
+ p=gr_pen_p((mp_stroked_object *)h);
+}
+txx=gr_left_x(p);
+tyx=gr_left_y(p);
+txy=gr_right_x(p);
+tyy=gr_right_y(p);
+if ( (gr_x_coord(p)!=0)||(gr_y_coord(p)!=0) ) {
+ mp_ps_print_nl(mp, "");
+ mp_ps_print_cmd(mp, "gsave ","q ");
+ mp_ps_pair_out(mp, gr_x_coord(p), gr_y_coord(p));
+ mp_ps_print(mp, "translate ");
+ txx-=gr_x_coord(p);
+ tyx-=gr_y_coord(p);
+ txy-=gr_x_coord(p);
+ tyy-=gr_y_coord(p);
+ transformed=true;
+} else {
+ mp_ps_print_nl(mp, "");
+}
+@<Adjust the transformation to account for |gs_width| and output the
+ initial \&{gsave} if |transformed| should be |true|@>
+
+@ @<Adjust the transformation to account for |gs_width| and output the...@>=
+if ( gs_width!=unity ) {
+ if ( gs_width==0 ) {
+ txx=unity; tyy=unity;
+ } else {
+ txx=mp_make_scaled(mp, txx,gs_width);
+ txy=mp_make_scaled(mp, txy,gs_width);
+ tyx=mp_make_scaled(mp, tyx,gs_width);
+ tyy=mp_make_scaled(mp, tyy,gs_width);
+ };
+}
+if ( (txy!=0)||(tyx!=0)||(txx!=unity)||(tyy!=unity) ) {
+ if ( (! transformed) ){
+ mp_ps_print_cmd(mp, "gsave ","q ");
+ transformed=true;
+ }
+}
+
+@ @<Issue \ps\ commands to transform the coordinate system@>=
+if ( (txy!=0)||(tyx!=0) ){
+ mp_ps_print_ln(mp);
+ mp_ps_print_char(mp, '[');
+ mp_ps_pair_out(mp, txx,tyx);
+ mp_ps_pair_out(mp, txy,tyy);
+ mp_ps_print(mp, "0 0] concat");
+} else if ( (txx!=unity)||(tyy!=unity) ){
+ mp_ps_print_ln(mp);
+ mp_ps_pair_out(mp, txx,tyy);
+ mp_ps_print(mp, "scale");
+}
+
+@ The \ps\ interpreter will probably abort if it encounters a singular
+transformation matrix. The determinant must be large enough to ensure that
+the printed representation will be nonsingular. Since the printed
+representation is always within $2^{-17}$ of the internal |scaled| value, the
+total error is at most $4T_{\rm max}2^{-17}$, where $T_{\rm max}$ is a bound on
+the magnitudes of |txx/65536|, |txy/65536|, etc.
+
+The |aspect_bound*(gs_width+1)| bound on the components of the pen
+transformation allows $T_{\rm max}$ to be at most |2*aspect_bound|.
+
+@<Tweak the transformation parameters so the transformation is nonsingular@>=
+det=mp_take_scaled(mp, txx,tyy) - mp_take_scaled(mp, txy,tyx);
+d1=4*aspect_bound+1;
+if ( abs(det)<d1 ) {
+ if ( det>=0 ) { d1=d1-det; s=1; }
+ else { d1=-d1-det; s=-1; };
+ d1=d1*unity;
+ if ( abs(txx)+abs(tyy)>=abs(txy)+abs(tyy) ) {
+ if ( abs(txx)>abs(tyy) ) tyy=tyy+(d1+s*abs(txx)) / txx;
+ else txx=txx+(d1+s*abs(tyy)) / tyy;
+ } else {
+ if ( abs(txy)>abs(tyx) ) tyx=tyx+(d1+s*abs(txy)) / txy;
+ else txy=txy+(d1+s*abs(tyx)) / tyx;
+ }
+}
+
+@ Here is a simple routine that just fills a cycle.
+
+@<Declarations@>=
+void mp_gr_ps_fill_out (MP mp, mp_knot *p);
+
+@ @c
+void mp_gr_ps_fill_out (MP mp, mp_knot *p) { /* fill cyclic path~|p| */
+ mp_gr_ps_path_out(mp, p);
+ mp_ps_print_cmd(mp, " fill"," F");
+ mp_ps_print_ln(mp);
+}
+
+@ A text node may specify an arbitrary transformation but the usual case
+involves only shifting, scaling, and occasionally rotation. The purpose
+of |choose_scale| is to select a scale factor so that the remaining
+transformation is as ``nice'' as possible. The definition of ``nice''
+is somewhat arbitrary but shifting and $90^\circ$ rotation are especially
+nice because they work out well for bitmap fonts. The code here selects
+a scale factor equal to $1/\sqrt2$ times the Frobenius norm of the
+non-shifting part of the transformation matrix. It is careful to avoid
+additions that might cause undetected overflow.
+
+@<Declarations@>=
+scaled mp_gr_choose_scale (MP mp, mp_graphic_object *p) ;
+
+@ @c scaled mp_gr_choose_scale (MP mp, mp_graphic_object *p) {
+ /* |p| should point to a text node */
+ scaled a,b,c,d,ad,bc; /* temporary values */
+ a=gr_txx_val(p);
+ b=gr_txy_val(p);
+ c=gr_tyx_val(p);
+ d=gr_tyy_val(p);
+ if ( a<0 ) negate(a);
+ if ( b<0 ) negate(b);
+ if ( c<0 ) negate(c);
+ if ( d<0 ) negate(d);
+ ad=half(a-d);
+ bc=half(b-c);
+ return mp_pyth_add(mp, mp_pyth_add(mp, d+ad,ad), mp_pyth_add(mp, c+bc,bc));
+}
+
+@ The potential overflow here is caused by the fact the returned value
+has to fit in a |name_type|, which is a quarterword.
+
+@d fscale_tolerance 65 /* that's $.001\times2^{16}$ */
+
+@<Declarations@>=
+quarterword mp_size_index (MP mp, font_number f, scaled s) ;
+
+@ @c
+quarterword mp_size_index (MP mp, font_number f, scaled s) {
+ pointer p,q; /* the previous and current font size nodes */
+ quarterword i; /* the size index for |q| */
+ q=mp->font_sizes[f];
+ i=0;
+ while ( q!=null ) {
+ if ( abs(s-sc_factor(q))<=fscale_tolerance )
+ return i;
+ else
+ { p=q; q=link(q); incr(i); };
+ if ( i==max_quarterword )
+ mp_overflow(mp, "sizes per font",max_quarterword);
+@:MetaPost capacity exceeded sizes per font}{\quad sizes per font@>
+ }
+ q=mp_get_node(mp, font_size_size);
+ sc_factor(q)=s;
+ if ( i==0 ) mp->font_sizes[f]=q; else link(p)=q;
+ return i;
+}
+
+@ @<Declarations@>=
+scaled mp_indexed_size (MP mp,font_number f, quarterword j);
+
+@ @c
+scaled mp_indexed_size (MP mp,font_number f, quarterword j) {
+ pointer p; /* a font size node */
+ quarterword i; /* the size index for |p| */
+ p=mp->font_sizes[f];
+ i=0;
+ if ( p==null ) mp_confusion(mp, "size");
+ while ( (i!=j) ) {
+ incr(i); p=link(p);
+ if ( p==null ) mp_confusion(mp, "size");
+ }
+ return sc_factor(p);
+}
+
+@ @<Declarations@>=
+void mp_clear_sizes (MP mp) ;
+
+@ @c void mp_clear_sizes (MP mp) {
+ font_number f; /* the font whose size list is being cleared */
+ pointer p; /* current font size nodes */
+ for (f=null_font+1;f<=mp->last_fnum;f++) {
+ while ( mp->font_sizes[f]!=null ) {
+ p=mp->font_sizes[f];
+ mp->font_sizes[f]=link(p);
+ mp_free_node(mp, p,font_size_size);
+ }
+ }
+}
+
+@ A text node may specify an arbitrary transformation but the usual case
+involves only shifting, scaling, and occasionally rotation. The purpose
+of |choose_scale| is to select a scale factor so that the remaining
+transformation is as ``nice'' as possible. The definition of ``nice''
+is somewhat arbitrary but shifting and $90^\circ$ rotation are especially
+nice because they work out well for bitmap fonts. The code here selects
+a scale factor equal to $1/\sqrt2$ times the Frobenius norm of the
+non-shifting part of the transformation matrix. It is careful to avoid
+additions that might cause undetected overflow.
+
+@<Declare the \ps\ output procedures@>=
+scaled mp_choose_scale (MP mp, mp_graphic_object *p) ;
+
+@ @c scaled mp_choose_scale (MP mp, mp_graphic_object *p) {
+ /* |p| should point to a text node */
+ scaled a,b,c,d,ad,bc; /* temporary values */
+ a=gr_txx_val(p);
+ b=gr_txy_val(p);
+ c=gr_tyx_val(p);
+ d=gr_tyy_val(p);
+ if ( (a<0) ) negate(a);
+ if ( (b<0) ) negate(b);
+ if ( (c<0) ) negate(c);
+ if ( (d<0) ) negate(d);
+ ad=half(a-d);
+ bc=half(b-c);
+ return mp_pyth_add(mp, mp_pyth_add(mp, d+ad,ad), mp_pyth_add(mp, c+bc,bc));
+}
+
+@ There may be many sizes of one font and we need to keep track of the
+characters used for each size. This is done by keeping a linked list of
+sizes for each font with a counter in each text node giving the appropriate
+position in the size list for its font.
+
+@d font_size_size 2 /* size of a font size node */
+
+
+@ @<Declarations@>=
+void mp_apply_mark_string_chars(MP mp, mp_edge_object *h, int next_size);
+
+@ @c
+void mp_apply_mark_string_chars(MP mp, mp_edge_object *h, int next_size) {
+ mp_graphic_object * p;
+ p=h->body;
+ while ( p!= NULL ) {
+ if ( gr_type(p)==mp_text_code ) {
+ if ( gr_font_n(p)!=null_font ) {
+ if ( gr_name_type(p)==next_size )
+ mp_mark_string_chars(mp, gr_font_n(p),gr_text_p(p));
+ }
+ }
+ p=gr_link(p);
+ }
+}
+
+@ @<Unmark all marked characters@>=
+for (f=null_font+1;f<=mp->last_fnum;f++) {
+ if ( mp->font_sizes[f]!=null ) {
+ mp_unmark_font(mp, f);
+ mp->font_sizes[f]=null;
+ }
+}
+
+@ @<Scan all the text nodes and mark the used ...@>=
+p=hh->body;
+while ( p!=null ) {
+ if ( gr_type(p)==mp_text_code ) {
+ f = gr_font_n(p);
+ if (f!=null_font ) {
+ switch (prologues) {
+ case 2:
+ case 3:
+ mp->font_sizes[f] = mp_void;
+ mp_mark_string_chars(mp, f, gr_text_p(p));
+ if (mp_has_fm_entry(mp,f,NULL) ) {
+ if (mp->font_enc_name[f]==NULL )
+ mp->font_enc_name[f] = mp_fm_encoding_name(mp,f);
+ mp->font_ps_name[f] = mp_fm_font_name(mp,f);
+ }
+ break;
+ case 1:
+ mp->font_sizes[f]=mp_void;
+ break;
+ default:
+ gr_name_type(p)=mp_size_index(mp, f,mp_choose_scale(mp, p));
+ if ( gr_name_type(p)==0 )
+ mp_mark_string_chars(mp, f, gr_text_p(p));
+ }
+ }
+ }
+ p=gr_link(p);
+}
+
+
+@
+@d pen_is_elliptical(A) ((A)==gr_next_knot((A)))
+
+@<Exported function headers@>=
+void mp_gr_ship_out (mp_edge_object *hh, int prologues, int procset) ;
+
+@ @c
+void mp_gr_ship_out (mp_edge_object *hh, int prologues, int procset) {
+ mp_graphic_object *p;
+ scaled ds,scf; /* design size and scale factor for a text node */
+ font_number f; /* for loops over fonts while (un)marking characters */
+ boolean transformed; /* is the coordinate system being transformed? */
+ MP mp = hh->_parent;
+ if (mp->history >= mp_fatal_error_stop ) return;
+ if (prologues<0)
+ prologues = (mp->internal[mp_prologues]>>16);
+ if (procset<0)
+ procset = (mp->internal[mp_procset]>>16);
+ mp_open_output_file(mp);
+ mp_print_initial_comment(mp, hh, prologues);
+ p = hh->body;
+ @<Unmark all marked characters@>;
+ if ( prologues==2 || prologues==3 ) {
+ mp_reload_encodings(mp);
+ }
+ @<Scan all the text nodes and mark the used characters@>;
+ if ( prologues==2 || prologues==3 ) {
+ mp_print_improved_prologue(mp, hh, prologues, procset);
+ } else {
+ mp_print_prologue(mp, hh, prologues, procset);
+ }
+ mp_gs_unknown_graphics_state(mp, 0);
+ p = hh->body;
+ while ( p!=NULL ) {
+ if ( gr_has_color(p) ) {
+ @<Write |pre_script| of |p|@>;
+ }
+ mp_gr_fix_graphics_state(mp, p);
+ switch (gr_type(p)) {
+ case mp_fill_code:
+ if ( gr_pen_p((mp_fill_object *)p)==NULL ) {
+ mp_gr_ps_fill_out(mp, gr_path_p((mp_fill_object *)p));
+ } else if ( pen_is_elliptical(gr_pen_p((mp_fill_object *)p)) ) {
+ mp_gr_stroke_ellipse(mp, p,true);
+ } else {
+ mp_gr_ps_fill_out(mp, gr_path_p((mp_fill_object *)p));
+ mp_gr_ps_fill_out(mp, gr_htap_p(p));
+ }
+ if ( gr_post_script((mp_fill_object *)p)!=NULL ) {
+ mp_ps_print_nl (mp, gr_post_script((mp_fill_object *)p));
+ mp_ps_print_ln(mp);
+ }
+ break;
+ case mp_stroked_code:
+ if ( pen_is_elliptical(gr_pen_p((mp_stroked_object *)p)) )
+ mp_gr_stroke_ellipse(mp, p,false);
+ else {
+ mp_gr_ps_fill_out(mp, gr_path_p((mp_stroked_object *)p));
+ }
+ if ( gr_post_script((mp_stroked_object *)p)!=NULL ) {
+ mp_ps_print_nl (mp, gr_post_script((mp_stroked_object *)p));
+ mp_ps_print_ln(mp);
+ }
+ break;
+ case mp_text_code:
+ if ( (gr_font_n(p)!=null_font) && (strlen(gr_text_p(p))>0) ) {
+ if ( prologues>0 )
+ scf=mp_gr_choose_scale(mp, p);
+ else
+ scf=mp_indexed_size(mp, gr_font_n(p), gr_name_type(p));
+ @<Shift or transform as necessary before outputting text node~|p| at scale
+ factor~|scf|; set |transformed:=true| if the original transformation must
+ be restored@>;
+ mp_ps_string_out(mp, gr_text_p(p));
+ mp_ps_name_out(mp, mp->font_name[gr_font_n(p)],false);
+ @<Print the size information and \ps\ commands for text node~|p|@>;
+ mp_ps_print_ln(mp);
+ }
+ if ( gr_post_script((mp_text_object *)p)!=NULL ) {
+ mp_ps_print_nl (mp, gr_post_script((mp_text_object *)p)); mp_ps_print_ln(mp);
+ }
+ break;
+ case mp_start_clip_code:
+ mp_ps_print_nl(mp, ""); mp_ps_print_cmd(mp, "gsave ","q ");
+ mp_gr_ps_path_out(mp, gr_path_p((mp_clip_object *)p));
+ mp_ps_print_cmd(mp, " clip"," W");
+ mp_ps_print_ln(mp);
+ if ( mp->internal[mp_restore_clip_color]>0 )
+ mp_gs_unknown_graphics_state(mp, 1);
+ break;
+ case mp_stop_clip_code:
+ mp_ps_print_nl(mp, ""); mp_ps_print_cmd(mp, "grestore","Q");
+ mp_ps_print_ln(mp);
+ if ( mp->internal[mp_restore_clip_color]>0 )
+ mp_gs_unknown_graphics_state(mp, 2);
+ else
+ mp_gs_unknown_graphics_state(mp, -1);
+ break;
+ case mp_start_bounds_code:
+ case mp_stop_bounds_code:
+ break;
+ case mp_special_code:
+ mp_ps_print_nl (mp, gr_pre_script((mp_special_object *)p));
+ mp_ps_print_ln (mp);
+ break;
+ } /* all cases are enumerated */
+ p=gr_link(p);
+ }
+ mp_ps_print_cmd(mp, "showpage","P"); mp_ps_print_ln(mp);
+ mp_ps_print(mp, "%%EOF"); mp_ps_print_ln(mp);
+ (mp->close_file)(mp,mp->ps_file);
+ if ( prologues<=0 )
+ mp_clear_sizes(mp);
+}
+
+@
+@d do_write_prescript(a,b) {
+ if ( (gr_pre_script((b *)a))!=NULL ) {
+ mp_ps_print_nl (mp, gr_pre_script((b *)a));
+ mp_ps_print_ln(mp);
+ }
+}
+
+@<Write |pre_script| of |p|@>=
+{
+ if (gr_type(p)==mp_fill_code) { do_write_prescript(p,mp_fill_object); }
+ else if (gr_type(p)==mp_stroked_code) { do_write_prescript(p,mp_stroked_object); }
+ else if (gr_type(p)==mp_text_code) { do_write_prescript(p,mp_text_object); }
+}
+
+@ The envelope of a cyclic path~|q| could be computed by calling
+|make_envelope| once for |q| and once for its reversal. We don't do this
+because it would fail color regions that are covered by the pen regardless
+of where it is placed on~|q|.
+
+@<Break the cycle and set |t:=1| if path |q| is cyclic@>=
+if ( gr_left_type(q)!=mp_endpoint ) {
+ gr_left_type(mp_gr_insert_knot(mp, q,gr_x_coord(q),gr_y_coord(q)))=mp_endpoint;
+ gr_right_type(q)=mp_endpoint;
+ q=gr_next_knot(q);
+ t=1;
+}
+
+@ @<Print the size information and \ps\ commands for text node~|p|@>=
+ps_room(18);
+mp_ps_print_char(mp, ' ');
+ds=(mp->font_dsize[gr_font_n(p)]+8) / 16;
+mp_ps_print_scaled(mp, mp_take_scaled(mp, ds,scf));
+mp_ps_print(mp, " fshow");
+if ( transformed )
+ mp_ps_print_cmd(mp, " grestore"," Q")
+
+
+
+@ @<Shift or transform as necessary before outputting text node~|p| at...@>=
+transformed=(gr_txx_val(p)!=scf)||(gr_tyy_val(p)!=scf)||
+ (gr_txy_val(p)!=0)||(gr_tyx_val(p)!=0);
+if ( transformed ) {
+ mp_ps_print_cmd(mp, "gsave [", "q [");
+ mp_ps_pair_out(mp, mp_make_scaled(mp, gr_txx_val(p),scf),
+ mp_make_scaled(mp, gr_tyx_val(p),scf));
+ mp_ps_pair_out(mp, mp_make_scaled(mp, gr_txy_val(p),scf),
+ mp_make_scaled(mp, gr_tyy_val(p),scf));
+ mp_ps_pair_out(mp, gr_tx_val(p),gr_ty_val(p));
+ mp_ps_print_cmd(mp, "] concat 0 0 moveto","] t 0 0 m");
+} else {
+ mp_ps_pair_out(mp, gr_tx_val(p),gr_ty_val(p));
+ mp_ps_print_cmd(mp, "moveto","m");
+}
+mp_ps_print_ln(mp)
+
+
+@ @<Exported function headers@>=
+void mp_gr_toss_objects ( mp_edge_object *hh) ;
+void mp_gr_toss_object (mp_graphic_object *p) ;
+
+@ @c
+void mp_gr_toss_object (mp_graphic_object *p) {
+ mp_fill_object *tf;
+ mp_stroked_object *ts;
+ mp_text_object *tt;
+ switch (gr_type(p)) {
+ case mp_fill_code:
+ tf = (mp_fill_object *)p;
+ mp_xfree(gr_pre_script(tf));
+ mp_xfree(gr_post_script(tf));
+ mp_gr_toss_knot_list(mp,gr_pen_p(tf));
+ mp_gr_toss_knot_list(mp,gr_path_p(tf));
+ mp_gr_toss_knot_list(mp,gr_htap_p(p));
+ break;
+ case mp_stroked_code:
+ ts = (mp_stroked_object *)p;
+ mp_xfree(gr_pre_script(ts));
+ mp_xfree(gr_post_script(ts));
+ mp_gr_toss_knot_list(mp,gr_pen_p(ts));
+ mp_gr_toss_knot_list(mp,gr_path_p(ts));
+ if (gr_dash_p(p)!=NULL)
+ mp_gr_toss_dashes (mp,gr_dash_p(p));
+ break;
+ case mp_text_code:
+ tt = (mp_text_object *)p;
+ mp_xfree(gr_pre_script(tt));
+ mp_xfree(gr_post_script(tt));
+ mp_xfree(gr_text_p(p));
+ mp_xfree(gr_font_name(p));
+ break;
+ case mp_start_clip_code:
+ mp_gr_toss_knot_list(mp,gr_path_p((mp_clip_object *)p));
+ break;
+ case mp_start_bounds_code:
+ mp_gr_toss_knot_list(mp,gr_path_p((mp_bounds_object *)p));
+ break;
+ case mp_stop_clip_code:
+ case mp_stop_bounds_code:
+ break;
+ case mp_special_code:
+ mp_xfree(gr_pre_script((mp_special_object *)p));
+ break;
+ } /* all cases are enumerated */
+ mp_xfree(p);
+}
+
+
+@ @c
+void mp_gr_toss_objects (mp_edge_object *hh) {
+ mp_graphic_object *p, *q;
+ p = hh->body;
+ while ( p!=NULL ) {
+ q = gr_link(p);
+ mp_gr_toss_object(p);
+ p=q;
+ }
+ mp_xfree(hh);
+}
+
+@ @<Exported function headers@>=
+mp_graphic_object *mp_gr_copy_object (MP mp, mp_graphic_object *p) ;
+
+@ @c
+mp_graphic_object *
+mp_gr_copy_object (MP mp, mp_graphic_object *p) {
+ mp_fill_object *tf;
+ mp_stroked_object *ts;
+ mp_text_object *tt;
+ mp_clip_object *tc;
+ mp_bounds_object *tb;
+ mp_special_object *tp;
+ mp_graphic_object *q = NULL;
+ switch (gr_type(p)) {
+ case mp_fill_code:
+ tf = (mp_fill_object *)mp_new_graphic_object(mp, mp_fill_code);
+ gr_pre_script(tf) = mp_xstrdup(mp, gr_pre_script((mp_fill_object *)p));
+ gr_post_script(tf) = mp_xstrdup(mp, gr_post_script((mp_fill_object *)p));
+ gr_path_p(tf) = mp_gr_copy_path(mp,gr_path_p((mp_fill_object *)p));
+ gr_htap_p(tf) = mp_gr_copy_path(mp,gr_htap_p(p));
+ gr_pen_p(tf) = mp_gr_copy_path(mp,gr_pen_p((mp_fill_object *)p));
+ q = (mp_graphic_object *)tf;
+ break;
+ case mp_stroked_code:
+ ts = (mp_stroked_object *)mp_new_graphic_object(mp, mp_stroked_code);
+ gr_pre_script(ts) = mp_xstrdup(mp, gr_pre_script((mp_stroked_object *)p));
+ gr_post_script(ts) = mp_xstrdup(mp, gr_post_script((mp_stroked_object *)p));
+ gr_path_p(ts) = mp_gr_copy_path(mp,gr_path_p((mp_stroked_object *)p));
+ gr_pen_p(ts) = mp_gr_copy_path(mp,gr_pen_p((mp_stroked_object *)p));
+ gr_dash_p(ts) = mp_gr_copy_dashes(mp,gr_dash_p(p));
+ q = (mp_graphic_object *)ts;
+ break;
+ case mp_text_code:
+ tt = (mp_text_object *)mp_new_graphic_object(mp, mp_text_code);
+ gr_pre_script(tt) = mp_xstrdup(mp, gr_pre_script((mp_text_object *)p));
+ gr_post_script(tt) = mp_xstrdup(mp, gr_post_script((mp_text_object *)p));
+ gr_text_p(tt) = mp_xstrdup(mp, gr_text_p(p));
+ gr_font_name(tt) = mp_xstrdup(mp, gr_font_name(p));
+ q = (mp_graphic_object *)tt;
+ break;
+ case mp_start_clip_code:
+ tc = (mp_clip_object *)mp_new_graphic_object(mp, mp_start_clip_code);
+ gr_path_p(tc) = mp_gr_copy_path(mp,gr_path_p((mp_clip_object *)p));
+ q = (mp_graphic_object *)tc;
+ break;
+ case mp_start_bounds_code:
+ tb = (mp_bounds_object *)mp_new_graphic_object(mp, mp_start_bounds_code);
+ gr_path_p(tb) = mp_gr_copy_path(mp,gr_path_p((mp_bounds_object *)p));
+ q = (mp_graphic_object *)tb;
+ break;
+ case mp_special_code:
+ tp = (mp_special_object *)mp_new_graphic_object(mp, mp_special_code);
+ gr_pre_script(tp) = mp_xstrdup(mp, gr_pre_script((mp_special_object *)p));
+ q = (mp_graphic_object *)tp;
+ break;
+ case mp_stop_clip_code:
+ q = mp_new_graphic_object(mp, mp_stop_clip_code);
+ break;
+ case mp_stop_bounds_code:
+ q = mp_new_graphic_object(mp, mp_stop_bounds_code);
+ break;
+ } /* all cases are enumerated */
+ return q;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/lua/texluac.c b/Build/source/texk/web2c/luatexdir/lua/texluac.c
new file mode 100644
index 00000000000..4bc13458d13
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/texluac.c
@@ -0,0 +1,199 @@
+/*
+** $Id: texluac.c 1013 2008-02-14 00:09:02Z oneiros $
+** Lua compiler (saves bytecodes to files; also list bytecodes)
+** See Copyright Notice in lua.h
+*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define luac_c
+#define LUA_CORE
+
+#include <../lua51/lua.h>
+#include <../lua51/lauxlib.h>
+
+#include <../lua51/ldo.h>
+#include <../lua51/lfunc.h>
+#include <../lua51/lmem.h>
+#include <../lua51/lobject.h>
+#include <../lua51/lopcodes.h>
+#include <../lua51/lstring.h>
+#include <../lua51/lundump.h>
+
+#define PROGNAME "texluac" /* default program name */
+#define OUTPUT PROGNAME ".out" /* default output file */
+
+static int dumping=1; /* dump bytecodes? */
+static int stripping=0; /* strip debug information? */
+static char Output[]={ OUTPUT }; /* default output file name */
+static const char* output=Output; /* actual output file name */
+static const char* progname=PROGNAME; /* actual program name */
+
+static void fatal(const char* message)
+{
+ fprintf(stderr,"%s: %s\n",progname,message);
+ exit(EXIT_FAILURE);
+}
+
+static void cannot(const char* what)
+{
+ fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno));
+ exit(EXIT_FAILURE);
+}
+
+static void usage(const char* message)
+{
+ if (*message=='-')
+ fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message);
+ else
+ fprintf(stderr,"%s: %s\n",progname,message);
+ fprintf(stderr,
+ "usage: %s [options] [filenames].\n"
+ "Available options are:\n"
+ " - process stdin\n"
+ " -o name output to file " LUA_QL("name") " (default is \"%s\")\n"
+ " -p parse only\n"
+ " -s strip debug information\n"
+ " -v show version information\n"
+ " -- stop handling options\n",
+ progname,Output);
+ exit(EXIT_FAILURE);
+}
+
+#define IS(s) (strcmp(argv[i],s)==0)
+
+static int doargs(int argc, char* argv[])
+{
+ int i;
+ int version=0;
+ if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0];
+ for (i=1; i<argc; i++)
+ {
+ if (*argv[i]!='-') /* end of options; keep it */
+ break;
+ else if (IS("--")) /* end of options; skip it */
+ {
+ ++i;
+ if (version) ++version;
+ break;
+ }
+ else if (IS("-")) /* end of options; use stdin */
+ break;
+ else if (IS("-o")) /* output file */
+ {
+ output=argv[++i];
+ if (output==NULL || *output==0) usage(LUA_QL("-o") " needs argument");
+ if (IS("-")) output=NULL;
+ }
+ else if (IS("-p")) /* parse only */
+ dumping=0;
+ else if (IS("-s")) /* strip debug information */
+ stripping=1;
+ else if (IS("-v")) /* show version */
+ ++version;
+ else if (IS("--luaconly")) /* ignore */
+ ;
+ else if (IS("--luac")) /* ignore */
+ ;
+ else /* unknown option */
+ usage(argv[i]);
+ }
+ if (i==argc && (!dumping))
+ {
+ dumping=0;
+ argv[--i]=Output;
+ }
+ if (version)
+ {
+ printf("%s %s\n",LUA_RELEASE,LUA_COPYRIGHT);
+ if (version==argc-1) exit(EXIT_SUCCESS);
+ }
+ return i;
+}
+
+#define toproto(L,i) (clvalue(L->top+(i))->l.p)
+
+static const Proto* combine(lua_State* L, int n)
+{
+ if (n==1)
+ return toproto(L,-1);
+ else
+ {
+ int i,pc;
+ Proto* f=luaF_newproto(L);
+ setptvalue2s(L,L->top,f); incr_top(L);
+ f->source=luaS_newliteral(L,"=(" PROGNAME ")");
+ f->maxstacksize=1;
+ pc=2*n+1;
+ f->code=luaM_newvector(L,pc,Instruction);
+ f->sizecode=pc;
+ f->p=luaM_newvector(L,n,Proto*);
+ f->sizep=n;
+ pc=0;
+ for (i=0; i<n; i++)
+ {
+ f->p[i]=toproto(L,i-n-1);
+ f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i);
+ f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1);
+ }
+ f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0);
+ return f;
+ }
+}
+
+static int writer(lua_State* L, const void* p, size_t size, void* u)
+{
+ UNUSED(L);
+ return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);
+}
+
+struct Smain {
+ int argc;
+ char** argv;
+};
+
+static int pmain(lua_State* L)
+{
+ struct Smain* s = (struct Smain*)lua_touserdata(L, 1);
+ int argc=s->argc;
+ char** argv=s->argv;
+ const Proto* f;
+ int i;
+ if (!lua_checkstack(L,argc)) fatal("too many input files");
+ for (i=0; i<argc; i++)
+ {
+ const char* filename=IS("-") ? NULL : argv[i];
+ if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1));
+ }
+ f=combine(L,argc);
+ if (dumping)
+ {
+ FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
+ if (D==NULL) cannot("open");
+ lua_lock(L);
+ luaU_dump(L,f,writer,D,stripping);
+ lua_unlock(L);
+ if (ferror(D)) cannot("write");
+ if (fclose(D)) cannot("close");
+ }
+ return 0;
+}
+
+int luac_main(int argc, char* argv[])
+{
+ lua_State* L;
+ struct Smain s;
+ int i=doargs(argc,argv);
+ argc-=i; argv+=i;
+ if (argc<=0) usage("no input files given");
+ L=lua_open();
+ if (L==NULL) fatal("not enough memory for state");
+ s.argc=argc;
+ s.argv=argv;
+ if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1));
+ lua_close(L);
+ return EXIT_SUCCESS;
+}
diff --git a/Build/source/texk/web2c/luatexdir/luatangle.ch b/Build/source/texk/web2c/luatexdir/luatangle.ch
new file mode 100644
index 00000000000..578238d722a
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luatangle.ch
@@ -0,0 +1,492 @@
+% otangle.ch: web2c changes to file tangle.ch
+%
+% This file is part of the Omega project, which
+% is based in the web2c distribution of TeX.
+%
+% Copyright (c) 1994--1998 John Plaice and Yannis Haralambous
+% applies only to the changes to the original tangle.ch.
+%
+% otangle.ch for C compilation with web2c.
+%
+% 10/9/82 (HT) Original version
+% 11/29 (HT) New version, with conversion to lowercase handled properly
+% Also, new control sequence:
+% @=...text...@> Put ...text... verbatim on a line
+% by itself in the Pascal output.
+% (argument must fit on one line)
+% This control sequence facilitates putting #include "gcons.h"
+% (for example) in files meant for the pc compiler.
+% Also, changed command line usage, so that the absence of a
+% change file implies no change file, rather than one with the
+% same name as the web file, with .ch at the end.
+% 1/15/83 (HT) Changed to work with version 1.2, which incorporates the
+% above change (though unbundling the output line breaking),
+% so mainly had to remove stuff.
+% 2/17 (HT) Fixed bug that caused 0-9 in identifiers to be converted to
+% Q-Y on output.
+% 3/18 (HT) Brought up to work with Version 1.5. Added -r command line
+% flag to cause a .rpl file to be written with all the lines
+% of the .web file that were replaced because of the .ch file
+% (useful for comparing with previous .rpl files, to see if a
+% change file will still work with a new version of a .web file)
+% Also, made it write a newline just before exit.
+% 4/12 (PC) Merged with Pavel's version, including adding a call to exit()
+% at the end depending upon the value of history.
+% 4/16 (PC) Brought up to date with version 1.5 released April, 1983.
+% 6/28 (HWT) Brought up to date with version 1.7 released June, 1983.
+% With new change file format, the -r option is now unnecessary.
+% 7/17 (HWT) Brought up to date with version 2.0 released July, 1983.
+% 12/18/83 (ETM) Brought up to date with version 2.5 released November, 1983.
+% 11/07/84 (ETM) Brought up to date with version 2.6.
+% 12/15/85 (ETM) Brought up to date with version 2.8.
+% 03/07/88 (ETM) Converted for use with WEB2C
+% 01/02/89 (PAM) Cosmetic upgrade to version 2.9
+% 11/30/89 (KB) Version 4.
+% (more recent changes in the ChangeLog)
+
+@x [0] Print only changes.
+\pageno=\contentspagenumber \advance\pageno by 1
+@y
+\pageno=\contentspagenumber \advance\pageno by 1
+\let\maybe=\iffalse
+\def\title{TANGLE changes for C}
+@z
+
+@x [?] Define and call parse_arguments.
+procedure initialize;
+ var @<Local variables for initialization@>@/
+ begin @<Set initial values@>@/
+@y
+@<Define |parse_arguments|@>
+procedure initialize;
+ var @<Local variables for initialization@>@/
+ begin
+ kpse_set_progname (argv[0]);
+ parse_arguments;
+ @<Set initial values@>@/
+@z
+
+@x [8] Constants: increase id lengths, for TeX--XeT and tex2pdf.
+@!buf_size=100; {maximum length of input line}
+@y
+@!buf_size=3000; {maximum length of input line}
+@z
+@x
+@!max_names=10239; {number of identifiers, strings, module names;
+ must be less than 10240}
+@!max_texts=10239; {number of replacement texts, must be less than 10240}
+@y
+@!max_names=10239; {number of identifiers, strings, module names;
+ must be less than 10240}
+@!max_texts=10239; {number of replacement texts, must be less than 10240}
+@z
+
+@x
+@!stack_size=50; {number of simultaneous levels of macro expansion}
+@!max_id_length=12; {long identifiers are chopped to this length, which must
+ not exceed |line_length|}
+@!unambig_length=7; {identifiers must be unique if chopped to this length}
+ {note that 7 is more strict than \PASCAL's 8, but this can be varied}
+@y
+@!stack_size=100; {number of simultaneous levels of macro expansion}
+@!max_id_length=64; {long identifiers are chopped to this length, which must
+ not exceed |line_length|}
+@!unambig_length=64; {identifiers must be unique if chopped to this length}
+@z
+
+% [??] The text_char type is used as an array index into xord. The
+% default type `char' produces signed integers, which are bad array
+% indices in C.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@d text_char == char {the data type of characters in text files}
+@y
+@d text_char == ASCII_code {the data type of characters in text files}
+@z
+
+@x [17] enable maximum character set
+for i:=1 to @'37 do xchr[i]:=' ';
+for i:=@'200 to @'377 do xchr[i]:=' ';
+@y
+for i:=1 to @'37 do xchr[i]:=chr(i);
+for i:=@'200 to @'377 do xchr[i]:=chr(i);
+@z
+
+@x [20] terminal output: use standard i/o
+@d print(#)==write(term_out,#) {`|print|' means write on the terminal}
+@y
+@d term_out==stdout
+@d print(#)==write(term_out,#) {`|print|' means write on the terminal}
+@z
+
+@x
+@<Globals...@>=
+@!term_out:text_file; {the terminal as an output file}
+@y
+@z
+
+@x [21] init terminal
+@ Different systems have different ways of specifying that the output on a
+certain file will appear on the user's terminal. Here is one way to do this
+on the \PASCAL\ system that was used in \.{TANGLE}'s initial development:
+@^system dependencies@>
+
+@<Set init...@>=
+rewrite(term_out,'TTY:'); {send |term_out| output to the terminal}
+@y
+@ Different systems have different ways of specifying that the output on a
+certain file will appear on the user's terminal.
+@^system dependencies@>
+
+@<Set init...@>=
+ {Nothing need be done for C.}
+@z
+
+@x [22] flush terminal buffer
+@d update_terminal == break(term_out) {empty the terminal output buffer}
+@y
+@d update_terminal == fflush(term_out) {empty the terminal output buffer}
+@z
+
+@x [24] open input files
+begin reset(web_file); reset(change_file);
+@y
+begin reset(web_file, web_name);
+if chg_name then reset(change_file, chg_name);
+@z
+
+@x [26] Open output files (except for the pool file).
+rewrite(Pascal_file); rewrite(pool);
+@y
+rewrite (Pascal_file, pascal_name);
+@z
+
+@x [28] Fix f^.
+ begin buffer[limit]:=xord[f^]; get(f);
+ incr(limit);
+ if buffer[limit-1]<>" " then final_limit:=limit;
+ if limit=buf_size then
+ begin while not eoln(f) do get(f);
+@y
+ begin buffer[limit]:=xord[getc(f)];
+ incr(limit);
+ if buffer[limit-1]<>" " then final_limit:=limit;
+ if limit=buf_size then
+ begin while not eoln(f) do vgetc(f);
+@z
+
+@x [??] Fix `jump_out'.
+@d fatal_error(#)==begin new_line; print(#); error; mark_fatal; jump_out;
+ end
+
+@<Error handling...@>=
+procedure jump_out;
+begin goto end_of_TANGLE;
+end;
+@y
+@d jump_out==uexit(1)
+@d fatal_error(#)==begin new_line; write(stderr, #);
+ error; mark_fatal; uexit(1);
+ end
+@z
+
+@x [38] Provide for a larger `byte_mem' and `tok_mem'. Extra capacity:
+@d ww=2 {we multiply the byte capacity by approximately this amount}
+@d zz=3 {we multiply the token capacity by approximately this amount}
+@y
+@d ww=3 {we multiply the byte capacity by approximately this amount}
+@d zz=5 {we multiply the token capacity by approximately this amount}
+@z
+
+@x [58] Case smashing options/strict checking.
+ begin if buffer[i]<>"_" then
+ begin if buffer[i]>="a" then chopped_id[s]:=buffer[i]-@'40
+ else chopped_id[s]:=buffer[i];
+@y
+ begin if (buffer[i]<>"_") or (allow_underlines) then
+ begin chopped_id[s]:=buffer[i];
+@z
+
+@x [63] Case smashing options/strict checking.
+ if c<>"_" then
+ begin if c>="a" then c:=c-@'40; {merge lowercase with uppercase}
+@y
+ if c<>"_" or (allow_underlines) then
+ begin
+@z
+
+@x [64] Delayed pool file opening.
+@<Define and output a new string...@>=
+begin ilk[p]:=numeric; {strings are like numeric macros}
+if l-double_chars=2 then {this string is for a single character}
+ equiv[p]:=buffer[id_first+1]+1073741824
+else begin equiv[p]:=string_ptr+1073741824;
+ l:=l-double_chars-1;
+@y
+@<Define and output a new string...@>=
+begin ilk[p]:=numeric; {strings are like numeric macros}
+if l-double_chars=2 then {this string is for a single character}
+ equiv[p]:=buffer[id_first+1]+1073741824
+else begin
+ {Avoid creating empty pool files.}
+ if string_ptr = 2097152 then begin
+ {Change |".web"| to |".pool"| and use the current directory.}
+ pool_name := basename_change_suffix (web_name, '.web', '.pool');
+ rewrite (pool, pool_name);
+ end;
+ equiv[p]:=string_ptr+1073741824;
+ l:=l-double_chars-1;
+@z
+
+@x [105] Accept DIV, div, MOD, and mod
+ (((out_contrib[1]="D")and(out_contrib[2]="I")and(out_contrib[3]="V")) or@|
+ ((out_contrib[1]="M")and(out_contrib[2]="O")and(out_contrib[3]="D")) ))or@|
+@^uppercase@>
+@y
+ (((out_contrib[1]="D")and(out_contrib[2]="I")and(out_contrib[3]="V")) or@|
+ ((out_contrib[1]="d")and(out_contrib[2]="i")and(out_contrib[3]="v")) or@|
+ ((out_contrib[1]="M")and(out_contrib[2]="O")and(out_contrib[3]="D")) or@|
+ ((out_contrib[1]="m")and(out_contrib[2]="o")and(out_contrib[3]="d")) ))or@|
+@z
+
+@x [110] lowercase ids
+@^uppercase@>
+ if ((out_buf[out_ptr-3]="D")and(out_buf[out_ptr-2]="I")and
+ (out_buf[out_ptr-1]="V"))or @/
+ ((out_buf[out_ptr-3]="M")and(out_buf[out_ptr-2]="O")and
+ (out_buf[out_ptr-1]="D")) then@/ goto bad_case
+@y
+ if ((out_buf[out_ptr-3]="D")and(out_buf[out_ptr-2]="I")and
+ (out_buf[out_ptr-1]="V"))or @/
+ ((out_buf[out_ptr-3]="d")and(out_buf[out_ptr-2]="i")and
+ (out_buf[out_ptr-1]="v"))or @/
+ ((out_buf[out_ptr-3]="M")and(out_buf[out_ptr-2]="O")and
+ (out_buf[out_ptr-1]="D"))or @/
+ ((out_buf[out_ptr-3]="m")and(out_buf[out_ptr-2]="o")and
+ (out_buf[out_ptr-1]="d")) then@/ goto bad_case
+@z
+
+@x [114] lowercase operators (`and', `or', etc.)
+and_sign: begin out_contrib[1]:="A"; out_contrib[2]:="N"; out_contrib[3]:="D";
+@^uppercase@>
+ send_out(ident,3);
+ end;
+not_sign: begin out_contrib[1]:="N"; out_contrib[2]:="O"; out_contrib[3]:="T";
+ send_out(ident,3);
+ end;
+set_element_sign: begin out_contrib[1]:="I"; out_contrib[2]:="N";
+ send_out(ident,2);
+ end;
+or_sign: begin out_contrib[1]:="O"; out_contrib[2]:="R"; send_out(ident,2);
+@y
+and_sign: begin out_contrib[1]:="a"; out_contrib[2]:="n"; out_contrib[3]:="d";
+ send_out(ident,3);
+ end;
+not_sign: begin out_contrib[1]:="n"; out_contrib[2]:="o"; out_contrib[3]:="t";
+ send_out(ident,3);
+ end;
+set_element_sign: begin out_contrib[1]:="i"; out_contrib[2]:="n";
+ send_out(ident,2);
+ end;
+or_sign: begin out_contrib[1]:="o"; out_contrib[2]:="r"; send_out(ident,2);
+@z
+
+@x [116] Remove conversion to uppercase
+@ Single-character identifiers represent themselves, while longer ones
+appear in |byte_mem|. All must be converted to uppercase,
+with underlines removed. Extremely long identifiers must be chopped.
+
+(Some \PASCAL\ compilers work with lowercase letters instead of
+uppercase. If this module of \.{TANGLE} is changed, it's also necessary
+to change from uppercase to lowercase in the modules that are
+listed in the index under ``uppercase''.)
+@^system dependencies@>
+@^uppercase@>
+
+@d up_to(#)==#-24,#-23,#-22,#-21,#-20,#-19,#-18,#-17,#-16,#-15,#-14,
+ #-13,#-12,#-11,#-10,#-9,#-8,#-7,#-6,#-5,#-4,#-3,#-2,#-1,#
+
+@<Cases related to identifiers@>=
+"A",up_to("Z"): begin out_contrib[1]:=cur_char; send_out(ident,1);
+ end;
+"a",up_to("z"): begin out_contrib[1]:=cur_char-@'40; send_out(ident,1);
+ end;
+identifier: begin k:=0; j:=byte_start[cur_val]; w:=cur_val mod ww;
+ while (k<max_id_length)and(j<byte_start[cur_val+ww]) do
+ begin incr(k); out_contrib[k]:=byte_mem[w,j]; incr(j);
+ if out_contrib[k]>="a" then out_contrib[k]:=out_contrib[k]-@'40
+ else if out_contrib[k]="_" then decr(k);
+ end;
+ send_out(ident,k);
+ end;
+@y
+@ Single-character identifiers represent themselves, while longer ones
+appear in |byte_mem|. All must be converted to lowercase,
+with underlines removed. Extremely long identifiers must be chopped.
+@^system dependencies@>
+
+@d up_to(#)==#-24,#-23,#-22,#-21,#-20,#-19,#-18,#-17,#-16,#-15,#-14,
+ #-13,#-12,#-11,#-10,#-9,#-8,#-7,#-6,#-5,#-4,#-3,#-2,#-1,#
+
+@<Cases related to identifiers@>=
+"A",up_to("Z"),
+"a",up_to("z"): begin out_contrib[1]:=cur_char; send_out(ident,1);
+ end;
+identifier: begin k:=0; j:=byte_start[cur_val]; w:=cur_val mod ww;
+ while (k<max_id_length)and(j<byte_start[cur_val+ww]) do
+ begin incr(k); out_contrib[k]:=byte_mem[w,j]; incr(j);
+ if not allow_underlines and (out_contrib[k]="_") then decr(k);
+ end;
+ send_out(ident,k);
+ end;
+@z
+
+@x [??] Fix casting bug
+@d add_in(#)==begin accumulator:=accumulator+next_sign*(#); next_sign:=+1;
+ end
+@y
+@d add_in(#)==begin accumulator:=accumulator+next_sign*intcast(#); next_sign:=+1;
+ end
+@z
+
+@x [179] make term_in = input
+any error stop will set |debug_cycle| to zero.
+@y
+any error stop will set |debug_cycle| to zero.
+
+@d term_in==stdin
+@z
+
+@x
+@!term_in:text_file; {the user's terminal as an input file}
+@y
+@z
+
+@x [180] remove term_in reset
+reset(term_in,'TTY:','/I'); {open |term_in| as the terminal, don't do a |get|}
+@y
+@z
+
+@x [182] write newline just before exit; use value of |history|
+print_ln(banner); {print a ``banner line''}
+@y
+print (banner); {print a ``banner line''}
+print_ln (version_string);
+@z
+
+@x
+@<Print the job |history|@>;
+@y
+@<Print the job |history|@>;
+new_line;
+if (history <> spotless) and (history <> harmless_message)
+then uexit (1)
+else uexit (0);
+@z
+
+@x [188] System-dependent changes.
+This module should be replaced, if necessary, by changes to the program
+that are necessary to make \.{TANGLE} work at a particular installation.
+It is usually best to design your change file so that all changes to
+previous modules preserve the module numbering; then everybody's version
+will be consistent with the printed program. More extensive changes,
+which introduce new modules, can be inserted here; then only the index
+itself will get a new module number.
+@^system dependencies@>
+@y
+Parse a Unix-style command line.
+
+@d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0)
+
+@<Define |parse_arguments|@> =
+procedure parse_arguments;
+const n_options = 4; {Pascal won't count array lengths for us.}
+var @!long_options: array[0..n_options] of getopt_struct;
+ @!getopt_return_val: integer;
+ @!option_index: c_int_type;
+ @!current_option: 0..n_options;
+begin
+ @<Define the option table@>;
+ repeat
+ getopt_return_val := getopt_long_only (argc, argv, '', long_options,
+ address_of (option_index));
+ if getopt_return_val = -1 then begin
+ {End of arguments; we exit the loop below.} ;
+
+ end else if getopt_return_val = "?" then begin
+ usage ('luatangle');
+
+ end else if argument_is ('underlines') then begin
+ allow_underlines := true;
+
+ end else if argument_is ('help') then begin
+ usage_help (LUATANGLE_HELP, nil);
+
+ end else if argument_is ('version') then begin
+ print_version_and_exit
+ (banner, nil, 'J. Plaice, Y. Haralambous, D.E. Knuth', nil);
+
+ end; {Else it was a flag; |getopt| has already done the assignment.}
+ until getopt_return_val = -1;
+
+ {Now |optind| is the index of first non-option on the command line.}
+ if (optind + 1 <> argc) and (optind + 2 <> argc) then begin
+ write_ln (stderr, 'otangle: Need one or two file arguments.');
+ usage ('otangle');
+ end;
+
+ {Supply |".web"| and |".ch"| extensions if necessary.}
+ web_name := extend_filename (cmdline (optind), 'web');
+ if optind + 2 = argc then begin
+ chg_name := extend_filename (cmdline (optind + 1), 'ch');
+ end;
+
+ {Change |".web"| to |".p"| and use the current directory.}
+ pascal_name := basename_change_suffix (web_name, '.web', '.p');
+end;
+
+@ Here are the options we allow. The first is one of the standard GNU options.
+@.-help@>
+
+@<Define the option...@> =
+current_option := 0;
+long_options[current_option].name := 'help';
+long_options[current_option].has_arg := 0;
+long_options[current_option].flag := 0;
+long_options[current_option].val := 0;
+incr (current_option);
+
+@ Another of the standard options.
+@.-version@>
+
+@<Define the option...@> =
+long_options[current_option].name := 'version';
+long_options[current_option].has_arg := 0;
+long_options[current_option].flag := 0;
+long_options[current_option].val := 0;
+incr (current_option);
+
+@ Allow underlines.
+@.-underlines@>
+
+@<Define the option...@> =
+long_options[current_option].name := 'underlines';
+long_options[current_option].has_arg := 0;
+long_options[current_option].flag := 0;
+long_options[current_option].val := 0;
+incr (current_option);
+
+@ An element with all zeros always ends the list.
+
+@<Define the option...@> =
+long_options[current_option].name := 0;
+long_options[current_option].has_arg := 0;
+long_options[current_option].flag := 0;
+long_options[current_option].val := 0;
+
+@ Global filenames.
+
+@<Globals...@>=
+@!web_name,@!chg_name,@!pascal_name,@!pool_name:c_string;
+@!@!allow_underlines:boolean;
+@z
diff --git a/Build/source/texk/web2c/luatexdir/luatangle.web b/Build/source/texk/web2c/luatexdir/luatangle.web
new file mode 100644
index 00000000000..0cc3e8416c6
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luatangle.web
@@ -0,0 +1,3328 @@
+% otangle.web: Omega version of file tangle.web
+%
+% This file is part of the Omega project, which
+% is based in the web2c distribution of TeX.
+%
+% Copyright (c) 1994--1998 John Plaice and Yannis Haralambous
+% applies only to the changes to the original tangle.web.
+%
+% This program by D. E. Knuth is not copyrighted and can be used freely.
+% Version 0 was released in December, 1981.
+% Version 1 was released in September, 1982, with version 0 of TeX.
+% Slight changes were made in October, 1982, for version 0.6 of TeX.
+% Version 1.2 introduced {:nnn} comments, added @@= and @@\ (December, 1982).
+% Version 1.4 added "history" (February, 1983).
+% Version 1.5 conformed to TeX version 0.96 and fixed @@\ (March, 1983).
+% Version 1.7 introduced the new change file format (June, 1983).
+% Version 2.0 was released in July, 1983, with version 0.999 of TeX.
+% Version 2.5 was released in November, 1983, with version 1.0 of TeX.
+% Version 2.6 fixed a bug: force-line-break after a constant (August, 1984).
+% Version 2.7 fixed the definition of check_sum_prime (May, 1985).
+% Version 2.8 fixed a bug in change_buffer movement (August, 1985).
+% Version 2.9 allows nonnumeric macros before their def (December, 1988).
+% Version 3, for Sewell's book, fixed long-line bug in input_ln (March, 1989).
+% Version 4 was major change to allow 8-bit input (September, 1989).
+% Version 4.1 conforms to ANSI standard for-loop rules (September, 1990).
+% Version 4.2 fixes stat report if phase one dies (March, 1991).
+% Version 4.3 fixes @@ bug in verbatim, catches extra } (September, 1991).
+% Version 4.4 activates debug_help on errors as advertised (February, 1993).
+
+% Here is TeX material that gets inserted after \input webmac
+\def\hang{\hangindent 3em\indent\ignorespaces}
+\font\ninerm=cmr9
+\let\mc=\ninerm % medium caps for names like SAIL
+\def\PASCAL{Pascal}
+\def\pb{$\.|\ldots\.|$} % Pascal brackets (|...|)
+\def\v{\.{\char'174}} % vertical (|) in typewriter font
+\mathchardef\BA="3224 % double arrow
+\def\({} % kludge for alphabetizing certain module names
+
+\def\title{OTANGLE}
+\def\contentspagenumber{123} % should be odd
+\def\topofcontents{\null\vfill
+ \titlefalse % include headline on the contents page
+ \def\rheader{\mainfont Appendix E\hfil \contentspagenumber}
+ \centerline{\titlefont The {\ttitlefont OTANGLE} processor}
+ \vskip 15pt
+ \centerline{(Version 4.4)}
+ \vfill}
+\pageno=\contentspagenumber \advance\pageno by 1
+
+@* Introduction.
+This program converts a \.{WEB} file to a \PASCAL\ file. It was written
+by D. E. Knuth in September, 1981; a somewhat similar {\mc SAIL} program had
+been developed in March, 1979. Since this program describes itself, a
+bootstrapping process involving hand-translation had to be used to get started.
+
+For large \.{WEB} files one should have a large memory, since \.{TANGLE} keeps
+all the \PASCAL\ text in memory (in an abbreviated form). The program uses
+a few features of the local \PASCAL\ compiler that may need to be changed in
+other installations:
+
+\yskip\item{1)} Case statements have a default.
+\item{2)} Input-output routines may need to be adapted for use with a particular
+character set and/or for printing messages on the user's terminal.
+
+\yskip\noindent
+These features are also present in the \PASCAL\ version of \TeX, where they
+are used in a similar (but more complex) way. System-dependent portions
+of \.{TANGLE} can be identified by looking at the entries for `system
+dependencies' in the index below.
+@!@^system dependencies@>
+
+The ``banner line'' defined here should be changed whenever \.{TANGLE}
+is modified.
+
+@d banner=='This is OTANGLE, Version 4.4'
+
+@ The program begins with a fairly normal header, made up of pieces that
+@^system dependencies@>
+will mostly be filled in later. The \.{WEB} input comes from files |web_file|
+and |change_file|, the \PASCAL\ output goes to file |Pascal_file|,
+and the string pool output goes to file |pool|.
+
+If it is necessary to abort the job because of a fatal error, the program
+calls the `|jump_out|' procedure, which goes to the label |end_of_TANGLE|.
+
+@d end_of_TANGLE = 9999 {go here to wrap it up}
+
+@p @t\4@>@<Compiler directives@>@/
+program OTANGLE(@!web_file,@!change_file,@!Pascal_file,@!pool);
+label end_of_TANGLE; {go here to finish}
+const @<Constants in the outer block@>@/
+type @<Types in the outer block@>@/
+var @<Globals in the outer block@>@/
+@<Error handling procedures@>@/
+procedure initialize;
+ var @<Local variables for initialization@>@/
+ begin @<Set initial values@>@/
+ end;
+
+@ Some of this code is optional for use when debugging only;
+such material is enclosed between the delimiters |debug| and $|gubed|$.
+Other parts, delimited by |stat| and $|tats|$, are optionally included if
+statistics about \.{TANGLE}'s memory usage are desired.
+
+@d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging}
+@d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging}
+@f debug==begin
+@f gubed==end
+@#
+@d stat==@{ {change this to `$\\{stat}\equiv\null$'
+ when gathering usage statistics}
+@d tats==@t@>@} {change this to `$\\{tats}\equiv\null$'
+ when gathering usage statistics}
+@f stat==begin
+@f tats==end
+
+@ The \PASCAL\ compiler used to develop this system has ``compiler
+directives'' that can appear in comments whose first character is a dollar sign.
+In production versions of \.{TANGLE} these directives tell the compiler that
+@^system dependencies@>
+it is safe to avoid range checks and to leave out the extra code it inserts
+for the \PASCAL\ debugger's benefit, although interrupts will occur if
+there is arithmetic overflow.
+
+@<Compiler directives@>=
+@{@&$C-,A+,D-@} {no range check, catch arithmetic overflow, no debug overhead}
+@!debug @{@&$C+,D+@}@+ gubed {but turn everything on when debugging}
+
+@ Labels are given symbolic names by the following definitions. We insert
+the label `|exit|:' just before the `\ignorespaces|end|\unskip' of a
+procedure in which we have used the `|return|' statement defined below;
+the label `|restart|' is occasionally used at the very beginning of a
+procedure; and the label `|reswitch|' is occasionally used just prior to
+a \&{case} statement in which some cases change the conditions and we wish to
+branch to the newly applicable case.
+Loops that are set up with the \&{loop} construction defined below are
+commonly exited by going to `|done|' or to `|found|' or to `|not_found|',
+and they are sometimes repeated by going to `|continue|'.
+
+@d exit=10 {go here to leave a procedure}
+@d restart=20 {go here to start a procedure again}
+@d reswitch=21 {go here to start a case statement again}
+@d continue=22 {go here to resume a loop}
+@d done=30 {go here to exit a loop}
+@d found=31 {go here when you've found it}
+@d not_found=32 {go here when you've found something else}
+
+@ Here are some macros for common programming idioms.
+
+@d incr(#) == #:=#+1 {increase a variable by unity}
+@d decr(#) == #:=#-1 {decrease a variable by unity}
+@d loop == @+ while true do@+ {repeat over and over until a |goto| happens}
+@d do_nothing == {empty statement}
+@d return == goto exit {terminate a procedure call}
+@f return == nil
+@f loop == xclause
+
+@ We assume that |case| statements may include a default case that applies
+if no matching label is found. Thus, we shall use constructions like
+@^system dependencies@>
+$$\vbox{\halign{#\hfil\cr
+|case x of|\cr
+1: $\langle\,$code for $x=1\,\rangle$;\cr
+3: $\langle\,$code for $x=3\,\rangle$;\cr
+|othercases| $\langle\,$code for |x<>1| and |x<>3|$\,\rangle$\cr
+|endcases|\cr}}$$
+since most \PASCAL\ compilers have plugged this hole in the language by
+incorporating some sort of default mechanism. For example, the compiler
+used to develop \.{WEB} and \TeX\ allows `|others|:' as a default label,
+and other \PASCAL s allow syntaxes like `\ignorespaces|else|\unskip' or
+`\&{otherwise}' or `\\{otherwise}:', etc. The definitions of |othercases|
+and |endcases| should be changed to agree with local conventions. (Of
+course, if no default mechanism is available, the |case| statements of
+this program must be extended by listing all remaining cases. The author
+would have taken the trouble to modify \.{TANGLE} so that such extensions
+were done automatically, if he had not wanted to encourage \PASCAL\
+compiler writers to make this important change in \PASCAL, where it belongs.)
+
+@d othercases == others: {default for cases not listed explicitly}
+@d endcases == @+end {follows the default case in an extended |case| statement}
+@f othercases == else
+@f endcases == end
+
+@ The following parameters are set big enough to handle \TeX, so they
+should be sufficient for most applications of \.{TANGLE}.
+
+@<Constants...@>=
+@!buf_size=100; {maximum length of input line}
+@!max_bytes=65535; {|1/ww| times the number of bytes in identifiers,
+ strings, and module names; must be less than 65536}
+@!max_toks=65535; {|1/zz| times the number of bytes in compressed \PASCAL\ code;
+ must be less than 65536}
+@!max_names=10239; {number of identifiers, strings, module names;
+ must be less than 10240}
+@!max_texts=10239; {number of replacement texts, must be less than 10240}
+@!hash_size=353; {should be prime}
+@!longest_name=400; {module names shouldn't be longer than this}
+@!line_length=72; {lines of \PASCAL\ output have at most this many characters}
+@!out_buf_size=144; {length of output buffer, should be twice |line_length|}
+@!stack_size=50; {number of simultaneous levels of macro expansion}
+@!max_id_length=12; {long identifiers are chopped to this length, which must
+ not exceed |line_length|}
+@!unambig_length=7; {identifiers must be unique if chopped to this length}
+ {note that 7 is more strict than \PASCAL's 8, but this can be varied}
+
+@ A global variable called |history| will contain one of four values
+at the end of every run: |spotless| means that no unusual messages were
+printed; |harmless_message| means that a message of possible interest
+was printed but no serious errors were detected; |error_message| means that
+at least one error was found; |fatal_message| means that the program
+terminated abnormally. The value of |history| does not influence the
+behavior of the program; it is simply computed for the convenience
+of systems that might want to use such information.
+
+@d spotless=0 {|history| value for normal jobs}
+@d harmless_message=1 {|history| value when non-serious info was printed}
+@d error_message=2 {|history| value when an error was noted}
+@d fatal_message=3 {|history| value when we had to stop prematurely}
+@#
+@d mark_harmless==@t@>@+if history=spotless then history:=harmless_message
+@d mark_error==history:=error_message
+@d mark_fatal==history:=fatal_message
+@d biggest_char=2097151
+@d number_chars=2097152
+
+@<Glob...@>=@!history:spotless..fatal_message; {how bad was this run?}
+
+@ @<Set init...@>=history:=spotless;
+
+@* The character set.
+One of the main goals in the design of \.{WEB} has been to make it readily
+portable between a wide variety of computers. Yet \.{WEB} by its very
+nature must use a greater variety of characters than most computer
+programs deal with, and character encoding is one of the areas in which
+existing machines differ most widely from each other.
+
+To resolve this problem, all input to \.{WEAVE} and \.{TANGLE} is converted
+to an internal eight-bit code that is essentially standard ASCII, the ``American
+Standard Code for Information Interchange.'' The conversion is done
+immediately when each character is read in. Conversely, characters are
+converted from ASCII to the user's external representation just before
+they are output. (The original ASCII code was seven bits only; \.{WEB} now
+allows eight bits in an attempt to keep up with modern times.)
+
+Such an internal code is relevant to users of \.{WEB} only because it is
+the code used for preprocessed constants like \.{"A"}. If you are writing
+a program in \.{WEB} that makes use of such one-character constants, you
+should convert your input to ASCII form, like \.{WEAVE} and \.{TANGLE} do.
+Otherwise \.{WEB}'s internal coding scheme does not affect you.
+@^ASCII code@>
+
+Here is a table of the standard visible ASCII codes:
+$$\def\:{\char\count255\global\advance\count255 by 1}
+\count255='40
+\vbox{
+\hbox{\hbox to 40pt{\it\hfill0\/\hfill}%
+\hbox to 40pt{\it\hfill1\/\hfill}%
+\hbox to 40pt{\it\hfill2\/\hfill}%
+\hbox to 40pt{\it\hfill3\/\hfill}%
+\hbox to 40pt{\it\hfill4\/\hfill}%
+\hbox to 40pt{\it\hfill5\/\hfill}%
+\hbox to 40pt{\it\hfill6\/\hfill}%
+\hbox to 40pt{\it\hfill7\/\hfill}}
+\vskip 4pt
+\hrule
+\def\^{\vrule height 10.5pt depth 4.5pt}
+\halign{\hbox to 0pt{\hskip -24pt\O{#0}\hfill}&\^
+\hbox to 40pt{\tt\hfill#\hfill\^}&
+&\hbox to 40pt{\tt\hfill#\hfill\^}\cr
+04&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+05&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+06&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+07&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+10&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+11&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+12&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+13&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+14&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+15&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+16&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+17&\:&\:&\:&\:&\:&\:&\:\cr}
+\hrule width 280pt}$$
+(Actually, of course, code @'040 is an invisible blank space.) Code @'136
+was once an upward arrow (\.{\char'13}), and code @'137 was
+once a left arrow (\.^^X), in olden times when the first draft
+of ASCII code was prepared; but \.{WEB} works with today's standard
+ASCII in which those codes represent circumflex and underline as shown.
+
+@<Types...@>=
+@!ASCII_code=0..255; {eight-bit numbers, a subrange of the integers}
+
+@ The original \PASCAL\ compiler was designed in the late 60s, when six-bit
+character sets were common, so it did not make provision for lowercase
+letters. Nowadays, of course, we need to deal with both capital and small
+letters in a convenient way, so \.{WEB} assumes that it is being used
+with a \PASCAL\ whose character set contains at least the characters of
+standard ASCII as listed above. Some \PASCAL\ compilers use the original
+name |char| for the data type associated with the characters in text files,
+while other \PASCAL s consider |char| to be a 64-element subrange of a larger
+data type that has some other name.
+
+In order to accommodate this difference, we shall use the name |text_char|
+to stand for the data type of the characters in the input and output
+files. We shall also assume that |text_char| consists of the elements
+|chr(first_text_char)| through |chr(last_text_char)|, inclusive. The
+following definitions should be adjusted if necessary.
+@^system dependencies@>
+
+@d text_char == char {the data type of characters in text files}
+@d first_text_char=0 {ordinal number of the smallest element of |text_char|}
+@d last_text_char=255 {ordinal number of the largest element of |text_char|}
+
+@<Types...@>=
+@!text_file=packed file of text_char;
+
+@ The \.{WEAVE} and \.{TANGLE} processors convert between ASCII code and
+the user's external character set by means of arrays |xord| and |xchr|
+that are analogous to \PASCAL's |ord| and |chr| functions.
+
+@<Globals...@>=
+@!xord: array [text_char] of ASCII_code;
+ {specifies conversion of input characters}
+@!xchr: array [ASCII_code] of text_char;
+ {specifies conversion of output characters}
+
+@ If we assume that every system using \.{WEB} is able to read and write the
+visible characters of standard ASCII (although not necessarily using the
+ASCII codes to represent them), the following assignment statements initialize
+most of the |xchr| array properly, without needing any system-dependent
+changes. For example, the statement \.{xchr[@@\'101]:=\'A\'} that appears
+in the present \.{WEB} file might be encoded in, say, {\mc EBCDIC} code
+on the external medium on which it resides, but \.{TANGLE} will convert from
+this external code to ASCII and back again. Therefore the assignment
+statement \.{XCHR[65]:=\'A\'} will appear in the corresponding \PASCAL\ file,
+and \PASCAL\ will compile this statement so that |xchr[65]| receives the
+character \.A in the external (|char|) code. Note that it would be quite
+incorrect to say \.{xchr[@@\'101]:="A"}, because |"A"| is a constant of
+type |integer|, not |char|, and because we have $|"A"|=65$ regardless of
+the external character set.
+
+@<Set init...@>=
+xchr[@'40]:=' ';
+xchr[@'41]:='!';
+xchr[@'42]:='"';
+xchr[@'43]:='#';
+xchr[@'44]:='$';
+xchr[@'45]:='%';
+xchr[@'46]:='&';
+xchr[@'47]:='''';@/
+xchr[@'50]:='(';
+xchr[@'51]:=')';
+xchr[@'52]:='*';
+xchr[@'53]:='+';
+xchr[@'54]:=',';
+xchr[@'55]:='-';
+xchr[@'56]:='.';
+xchr[@'57]:='/';@/
+xchr[@'60]:='0';
+xchr[@'61]:='1';
+xchr[@'62]:='2';
+xchr[@'63]:='3';
+xchr[@'64]:='4';
+xchr[@'65]:='5';
+xchr[@'66]:='6';
+xchr[@'67]:='7';@/
+xchr[@'70]:='8';
+xchr[@'71]:='9';
+xchr[@'72]:=':';
+xchr[@'73]:=';';
+xchr[@'74]:='<';
+xchr[@'75]:='=';
+xchr[@'76]:='>';
+xchr[@'77]:='?';@/
+xchr[@'100]:='@@';
+xchr[@'101]:='A';
+xchr[@'102]:='B';
+xchr[@'103]:='C';
+xchr[@'104]:='D';
+xchr[@'105]:='E';
+xchr[@'106]:='F';
+xchr[@'107]:='G';@/
+xchr[@'110]:='H';
+xchr[@'111]:='I';
+xchr[@'112]:='J';
+xchr[@'113]:='K';
+xchr[@'114]:='L';
+xchr[@'115]:='M';
+xchr[@'116]:='N';
+xchr[@'117]:='O';@/
+xchr[@'120]:='P';
+xchr[@'121]:='Q';
+xchr[@'122]:='R';
+xchr[@'123]:='S';
+xchr[@'124]:='T';
+xchr[@'125]:='U';
+xchr[@'126]:='V';
+xchr[@'127]:='W';@/
+xchr[@'130]:='X';
+xchr[@'131]:='Y';
+xchr[@'132]:='Z';
+xchr[@'133]:='[';
+xchr[@'134]:='\';
+xchr[@'135]:=']';
+xchr[@'136]:='^';
+xchr[@'137]:='_';@/
+xchr[@'140]:='`';
+xchr[@'141]:='a';
+xchr[@'142]:='b';
+xchr[@'143]:='c';
+xchr[@'144]:='d';
+xchr[@'145]:='e';
+xchr[@'146]:='f';
+xchr[@'147]:='g';@/
+xchr[@'150]:='h';
+xchr[@'151]:='i';
+xchr[@'152]:='j';
+xchr[@'153]:='k';
+xchr[@'154]:='l';
+xchr[@'155]:='m';
+xchr[@'156]:='n';
+xchr[@'157]:='o';@/
+xchr[@'160]:='p';
+xchr[@'161]:='q';
+xchr[@'162]:='r';
+xchr[@'163]:='s';
+xchr[@'164]:='t';
+xchr[@'165]:='u';
+xchr[@'166]:='v';
+xchr[@'167]:='w';@/
+xchr[@'170]:='x';
+xchr[@'171]:='y';
+xchr[@'172]:='z';
+xchr[@'173]:='{';
+xchr[@'174]:='|';
+xchr[@'175]:='}';
+xchr[@'176]:='~';@/
+xchr[0]:=' '; xchr[@'177]:=' '; {these ASCII codes are not used}
+
+@ Some of the ASCII codes below @'40 have been given symbolic names in
+\.{WEAVE} and \.{TANGLE} because they are used with a special meaning.
+
+@d and_sign=@'4 {equivalent to `\.{and}'}
+@d not_sign=@'5 {equivalent to `\.{not}'}
+@d set_element_sign=@'6 {equivalent to `\.{in}'}
+@d tab_mark=@'11 {ASCII code used as tab-skip}
+@d line_feed=@'12 {ASCII code thrown away at end of line}
+@d form_feed=@'14 {ASCII code used at end of page}
+@d carriage_return=@'15 {ASCII code used at end of line}
+@d left_arrow=@'30 {equivalent to `\.{:=}'}
+@d not_equal=@'32 {equivalent to `\.{<>}'}
+@d less_or_equal=@'34 {equivalent to `\.{<=}'}
+@d greater_or_equal=@'35 {equivalent to `\.{>=}'}
+@d equivalence_sign=@'36 {equivalent to `\.{==}'}
+@d or_sign=@'37 {equivalent to `\.{or}'}
+
+@ When we initialize the |xord| array and the remaining parts of |xchr|,
+it will be convenient to make use of an index variable, |i|.
+
+@<Local variables for init...@>=
+@!i:0..255;
+
+@ Here now is the system-dependent part of the character set.
+If \.{WEB} is being implemented on a garden-variety \PASCAL\ for which
+only standard ASCII codes will appear in the input and output files, you
+don't need to make any changes here. But if you have, for example, an extended
+character set like the one in Appendix~C of {\sl The \TeX book}, the first
+line of code in this module should be changed to
+$$\hbox{|for i:=1 to @'37 do xchr[i]:=chr(i);|}$$
+\.{WEB}'s character set is essentially identical to \TeX's, even with respect to
+characters less than @'40.
+@^system dependencies@>
+
+Changes to the present module will make \.{WEB} more friendly on computers
+that have an extended character set, so that one can type things like
+\.^^Z\ instead of \.{<>}. If you have an extended set of characters that
+are easily incorporated into text files, you can assign codes arbitrarily
+here, giving an |xchr| equivalent to whatever characters the users of
+\.{WEB} are allowed to have in their input files, provided that unsuitable
+characters do not correspond to special codes like |carriage_return|
+that are listed above.
+
+(The present file \.{TANGLE.WEB} does not contain any of the non-ASCII
+characters, because it is intended to be used with all implementations of
+\.{WEB}. It was originally created on a Stanford system that has a
+convenient extended character set, then ``sanitized'' by applying another
+program that transliterated all of the non-standard characters into
+standard equivalents.)
+
+@<Set init...@>=
+for i:=1 to @'37 do xchr[i]:=' ';
+for i:=@'200 to @'377 do xchr[i]:=' ';
+
+@ The following system-independent code makes the |xord| array contain a
+suitable inverse to the information in |xchr|.
+
+@<Set init...@>=
+for i:=first_text_char to last_text_char do xord[chr(i)]:=" ";
+for i:=1 to @'377 do xord[xchr[i]]:=i;
+xord[' ']:=" ";
+
+@* Input and output.
+The input conventions of this program are intended to be very much like those
+of \TeX\ (except, of course, that they are much simpler, because much less
+needs to be done). Furthermore they are identical to those of \.{WEAVE}.
+Therefore people who need to make modifications to all three systems
+should be able to do so without too many headaches.
+
+We use the standard \PASCAL\ input/output procedures in several places that
+\TeX\ cannot, since \.{TANGLE} does not have to deal with files that are named
+dynamically by the user, and since there is no input from the terminal.
+
+@ Terminal output is done by writing on file |term_out|, which is assumed to
+consist of characters of type |text_char|:
+@^system dependencies@>
+
+@d print(#)==write(term_out,#) {`|print|' means write on the terminal}
+@d print_ln(#)==write_ln(term_out,#) {`|print|' and then start new line}
+@d new_line==write_ln(term_out) {start new line}
+@d print_nl(#)== {print information starting on a new line}
+ begin new_line; print(#);
+ end
+
+@<Globals...@>=
+@!term_out:text_file; {the terminal as an output file}
+
+@ Different systems have different ways of specifying that the output on a
+certain file will appear on the user's terminal. Here is one way to do this
+on the \PASCAL\ system that was used in \.{TANGLE}'s initial development:
+@^system dependencies@>
+
+@<Set init...@>=
+rewrite(term_out,'TTY:'); {send |term_out| output to the terminal}
+
+@ The |update_terminal| procedure is called when we want
+to make sure that everything we have output to the terminal so far has
+actually left the computer's internal buffers and been sent.
+@^system dependencies@>
+
+@d update_terminal == break(term_out) {empty the terminal output buffer}
+
+@ The main input comes from |web_file|; this input may be overridden
+by changes in |change_file|. (If |change_file| is empty, there are no changes.)
+
+@<Globals...@>=
+@!web_file:text_file; {primary input}
+@!change_file:text_file; {updates}
+
+@ The following code opens the input files. Since these files were listed
+in the program header, we assume that the \PASCAL\ runtime system has
+already checked that suitable file names have been given; therefore no
+additional error checking needs to be done.
+@^system dependencies@>
+
+@p procedure open_input; {prepare to read |web_file| and |change_file|}
+begin reset(web_file); reset(change_file);
+end;
+
+@ The main output goes to |Pascal_file|, and string pool constants are
+written to the |pool| file.
+
+@<Globals...@>=
+@!Pascal_file: text_file;
+@!pool: text_file;
+
+@ The following code opens |Pascal_file| and |pool|.
+Since these files were listed in the program header, we assume that the
+\PASCAL\ runtime system has checked that suitable external file names have
+been given.
+@^system dependencies@>
+
+@<Set init...@>=
+rewrite(Pascal_file); rewrite(pool);
+
+@ Input goes into an array called |buffer|.
+
+@<Globals...@>=@!buffer: array[0..buf_size] of ASCII_code;
+
+@ The |input_ln| procedure brings the next line of input from the specified
+file into the |buffer| array and returns the value |true|, unless the file has
+already been entirely read, in which case it returns |false|. The conventions
+of \TeX\ are followed; i.e., |ASCII_code| numbers representing the next line
+of the file are input into |buffer[0]|, |buffer[1]|, \dots,
+|buffer[limit-1]|; trailing blanks are ignored;
+and the global variable |limit| is set to the length of the
+@^system dependencies@>
+line. The value of |limit| must be strictly less than |buf_size|.
+
+We assume that none of the |ASCII_code| values
+of |buffer[j]| for |0<=j<limit| is equal to 0, @'177, |line_feed|, |form_feed|,
+or |carriage_return|.
+
+@p function input_ln(var f:text_file):boolean;
+ {inputs a line or returns |false|}
+var final_limit:0..buf_size; {|limit| without trailing blanks}
+begin limit:=0; final_limit:=0;
+if eof(f) then input_ln:=false
+else begin while not eoln(f) do
+ begin buffer[limit]:=xord[f^]; get(f);
+ incr(limit);
+ if buffer[limit-1]<>" " then final_limit:=limit;
+ if limit=buf_size then
+ begin while not eoln(f) do get(f);
+ decr(limit); {keep |buffer[buf_size]| empty}
+ if final_limit>limit then final_limit:=limit;
+ print_nl('! Input line too long'); loc:=0; error;
+@.Input line too long@>
+ end;
+ end;
+ read_ln(f); limit:=final_limit; input_ln:=true;
+ end;
+end;
+
+@* Reporting errors to the user.
+The \.{TANGLE} processor operates in two phases: first it inputs the source
+file and stores a compressed representation of the program, then it produces
+the \PASCAL\ output from the compressed representation.
+
+The global variable |phase_one| tells whether we are in Phase I or not.
+
+@<Globals...@>=
+@!phase_one: boolean; {|true| in Phase I, |false| in Phase II}
+
+@ If an error is detected while we are debugging,
+we usually want to look at the contents of memory.
+A special procedure will be declared later for this purpose.
+
+@<Error handling...@>=
+@!debug @+ procedure debug_help; forward;@+ gubed
+
+@ During the first phase, syntax errors are reported to the user by saying
+$$\hbox{`|err_print('! Error message')|'},$$
+followed by `|jump_out|' if no recovery from the error is provided.
+This will print the error message followed by an indication of where the error
+was spotted in the source file. Note that no period follows the error message,
+since the error routine will automatically supply a period.
+
+Errors that are noticed during the second phase are reported to the user
+in the same fashion, but the error message will be
+followed by an indication of where the error was spotted in the output file.
+
+The actual error indications are provided by a procedure called |error|.
+
+@d err_print(#)==begin new_line; print(#); error;
+ end
+
+@<Error handling...@>=
+procedure error; {prints '\..' and location of error message}
+var j: 0..out_buf_size; {index into |out_buf|}
+@!k,@!l: 0..buf_size; {indices into |buffer|}
+begin if phase_one then @<Print error location based on input buffer@>
+else @<Print error location based on output buffer@>;
+update_terminal; mark_error;
+@!debug debug_skipped:=debug_cycle; debug_help;@+gubed
+end;
+
+@ The error locations during Phase I can be indicated by using the global
+variables |loc|, |line|, and |changing|, which tell respectively the first
+unlooked-at position in |buffer|, the current line number, and whether or not
+the current line is from |change_file| or |web_file|.
+This routine should be modified on systems whose standard text editor
+has special line-numbering conventions.
+@^system dependencies@>
+
+@<Print error location based on input buffer@>=
+begin if changing then print('. (change file ')@+else print('. (');
+print_ln('l.', line:1, ')');
+if loc>=limit then l:=limit else l:=loc;
+for k:=1 to l do
+ if buffer[k-1]=tab_mark then print(' ')
+ else print(xchr[buffer[k-1]]); {print the characters already read}
+new_line;
+for k:=1 to l do print(' '); {space out the next line}
+for k:=l+1 to limit do print(xchr[buffer[k-1]]); {print the part not yet read}
+print(' '); {this space separates the message from future asterisks}
+end
+
+@ The position of errors detected during the second phase can be indicated
+by outputting the partially-filled output buffer, which contains |out_ptr|
+entries.
+
+@<Print error location based on output...@>=
+begin print_ln('. (l.',line:1,')');
+for j:=1 to out_ptr do print(xchr[out_buf[j-1]]); {print current partial line}
+print('... '); {indicate that this information is partial}
+end
+
+@ The |jump_out| procedure just cuts across all active procedure levels
+and jumps out of the program. This is the only non-local |goto| statement
+in \.{TANGLE}. It is used when no recovery from a particular error has
+been provided.
+
+Some \PASCAL\ compilers do not implement non-local |goto| statements.
+@^system dependencies@>
+In such cases the code that appears at label |end_of_TANGLE| should be
+copied into the |jump_out| procedure, followed by a call to a system procedure
+that terminates the program.
+
+@d fatal_error(#)==begin new_line; print(#); error; mark_fatal; jump_out;
+ end
+
+@<Error handling...@>=
+procedure jump_out;
+begin goto end_of_TANGLE;
+end;
+
+@ Sometimes the program's behavior is far different from what it should be,
+and \.{TANGLE} prints an error message that is really for the \.{TANGLE}
+maintenance person, not the user. In such cases the program says
+|confusion('indication of where we are')|.
+
+@d confusion(#)==fatal_error('! This can''t happen (',#,')')
+@.This can't happen@>
+
+@ An overflow stop occurs if \.{TANGLE}'s tables aren't large enough.
+
+@d overflow(#)==fatal_error('! Sorry, ',#,' capacity exceeded')
+@.Sorry, x capacity exceeded@>
+
+
+@* Data structures.
+Most of the user's \PASCAL\ code is packed into eight-bit integers
+in two large arrays called |byte_mem| and |tok_mem|.
+The |byte_mem| array holds the names of identifiers, strings, and modules;
+the |tok_mem| array holds the replacement texts
+for macros and modules. Allocation is sequential, since things are deleted only
+during Phase II, and only in a last-in-first-out manner.
+
+Auxiliary arrays |byte_start| and |tok_start| are used as directories to
+|byte_mem| and |tok_mem|, and the |link|, |ilk|, |equiv|, and |text_link|
+arrays give further information about names. These auxiliary arrays
+consist of sixteen-bit items.
+
+@<Types...@>=
+@!eight_bits=0..255; {unsigned one-byte quantity}
+@!sixteen_bits=integer; {not quite a two-byte quantity}
+
+@ \.{TANGLE} has been designed to avoid the need for indices that are more
+than sixteen bits wide, so that it can be used on most computers. But
+there are programs that need more than 65536 tokens, and some programs
+even need more than 65536 bytes; \TeX\ is one of these. To get around
+this problem, a slight complication has been added to the data structures:
+|byte_mem| and |tok_mem| are two-dimensional arrays, whose first index is
+either 0 or 1. (For generality, the first index is actually allowed to run
+between 0 and |ww-1| in |byte_mem|, or between 0 and |zz-1| in |tok_mem|,
+where |ww| and |zz| are set to 2 and~3; the program will work for any
+positive values of |ww| and |zz|, and it can be simplified in obvious ways
+if |ww=1| or |zz=1|.)
+
+@d ww=2 {we multiply the byte capacity by approximately this amount}
+@d zz=3 {we multiply the token capacity by approximately this amount}
+
+@<Globals...@>=
+@!byte_mem: packed array [0..ww-1,0..max_bytes] of ASCII_code;
+ {characters of names}
+@!tok_mem: packed array [0..zz-1,0..max_toks] of eight_bits; {tokens}
+@!byte_start: array [0..max_names] of sixteen_bits; {directory into |byte_mem|}
+@!tok_start: array [0..max_texts] of sixteen_bits; {directory into |tok_mem|}
+@!link: array [0..max_names] of sixteen_bits; {hash table or tree links}
+@!ilk: array [0..max_names] of sixteen_bits; {type codes or tree links}
+@!equiv: array [0..max_names] of sixteen_bits; {info corresponding to names}
+@!text_link: array [0..max_texts] of sixteen_bits; {relates replacement texts}
+
+@ The names of identifiers are found by computing a hash address |h| and
+then looking at strings of bytes signified by |hash[h]|, |link[hash[h]]|,
+|link[link[hash[h]]]|, \dots, until either finding the desired name
+or encountering a zero.
+
+A `|name_pointer|' variable, which signifies a name, is an index into
+|byte_start|. The actual sequence of characters in the name pointed to by
+|p| appears in positions |byte_start[p]| to |byte_start[p+ww]-1|, inclusive,
+in the segment of |byte_mem| whose first index is |p mod ww|. Thus, when
+|ww=2| the even-numbered name bytes appear in |byte_mem[0,@t$*$@>]|
+and the odd-numbered ones appear in |byte_mem[1,@t$*$@>]|.
+The pointer 0 is used for undefined module names; we don't
+want to use it for the names of identifiers, since 0 stands for a null
+pointer in a linked list.
+
+Strings are treated like identifiers; the first character (a double-quote)
+distinguishes a string from an alphabetic name, but for \.{TANGLE}'s purposes
+strings behave like numeric macros. (A `string' here refers to the
+strings delimited by double-quotes that \.{TANGLE} processes. \PASCAL\
+string constants delimited by single-quote marks are not given such special
+treatment; they simply appear as sequences of characters in the \PASCAL\
+texts.) The total number of strings in the string
+pool is called |string_ptr|, and the total number of names in |byte_mem|
+is called |name_ptr|. The total number of bytes occupied in
+|byte_mem[w,@t$*$@>]| is called |byte_ptr[w]|.
+
+We usually have |byte_start[name_ptr+w]=byte_ptr[(name_ptr+w) mod ww]|
+for |0<=w<ww|, since these are the starting positions for the next |ww|
+names to be stored in |byte_mem|.
+
+@d length(#)==byte_start[#+ww]-byte_start[#] {the length of a name}
+
+@<Types...@>=
+@!name_pointer=0..max_names; {identifies a name}
+
+@ @<Global...@>=
+@!name_ptr:name_pointer; {first unused position in |byte_start|}
+@!string_ptr:name_pointer; {next number to be given to a string of length |<>1|}
+@!byte_ptr:array [0..ww-1] of 0..max_bytes;
+ {first unused position in |byte_mem|}
+@!pool_check_sum:integer; {sort of a hash for the whole string pool}
+
+@ @<Local variables for init...@>=
+@!wi: 0..ww-1; {to initialize the |byte_mem| indices}
+
+@ @<Set init...@>=
+for wi:=0 to ww-1 do
+ begin byte_start[wi]:=0; byte_ptr[wi]:=0;
+ end;
+byte_start[ww]:=0; {this makes name 0 of length zero}
+name_ptr:=1; string_ptr:=number_chars; pool_check_sum:=271828;
+
+@ Replacement texts are stored in |tok_mem|, using similar conventions.
+A `|text_pointer|' variable is an index into |tok_start|, and the
+replacement text that corresponds to |p| runs from positions
+|tok_start[p]| to |tok_start[p+zz]-1|, inclusive, in the segment of
+|tok_mem| whose first index is |p mod zz|. Thus, when |zz=2| the
+even-numbered replacement texts appear in |tok_mem[0,@t$*$@>]| and the
+odd-numbered ones appear in |tok_mem[1,@t$*$@>]|. Furthermore,
+|text_link[p]| is used to connect pieces of text that have the same name,
+as we shall see later. The pointer 0 is used for undefined replacement
+texts.
+
+The first position of |tok_mem[z,@t$*$@>]| that is unoccupied by
+replacement text is called |tok_ptr[z]|, and the first unused location of
+|tok_start| is called |text_ptr|. We usually have the identity
+|tok_start[text_ptr+z]=tok_ptr[(text_ptr+z) mod zz]|, for |0<=z<zz|, since
+these are the starting positions for the next |zz| replacement texts to
+be stored in |tok_mem|.
+
+@<Types...@>=
+@!text_pointer=0..max_texts; {identifies a replacement text}
+
+@ It is convenient to maintain a variable |z| that is equal to |text_ptr
+mod zz|, so that we always insert tokens into segment |z| of |tok_mem|.
+
+@<Glob...@>=
+@t\hskip1em@>@!text_ptr:text_pointer; {first unused position in |tok_start|}
+@t\hskip1em@>@!tok_ptr:array[0..zz-1] of 0..max_toks;
+ {first unused position in a given segment of |tok_mem|}
+@t\hskip1em@>@!z:0..zz-1; {current segment of |tok_mem|}
+stat @!max_tok_ptr:array[0..zz-1] of 0..max_toks;
+ {largest values assumed by |tok_ptr|}
+tats
+
+@ @<Local variables for init...@>=
+@!zi:0..zz-1; {to initialize the |tok_mem| indices}
+
+@ @<Set init...@>=
+for zi:=0 to zz-1 do
+ begin tok_start[zi]:=0; tok_ptr[zi]:=0;
+ end;
+tok_start[zz]:=0; {this makes replacement text 0 of length zero}
+text_ptr:=1; z:=1 mod zz;
+
+@ Four types of identifiers are distinguished by their |ilk|:
+
+\yskip\hang |normal| identifiers will appear in the \PASCAL\ program as
+ordinary identifiers since they have not been defined to be macros; the
+corresponding value in the |equiv| array
+for such identifiers is a link in a secondary hash table that
+is used to check whether any two of them agree in their first |unambig_length|
+characters after underline symbols are removed and lowercase letters are
+changed to uppercase.
+
+\yskip\hang |numeric| identifiers have been defined to be numeric macros;
+their |equiv| value contains the corresponding numeric value plus $2^{15}$.
+Strings are treated as numeric macros.
+
+\yskip\hang |simple| identifiers have been defined to be simple macros;
+their |equiv| value points to the corresponding replacement text.
+
+\yskip\hang |parametric| identifiers have been defined to be parametric macros;
+like simple identifiers, their |equiv| value points to the replacement text.
+
+@d normal=0 {ordinary identifiers have |normal| ilk}
+@d numeric=1 {numeric macros and strings have |numeric| ilk}
+@d simple=2 {simple macros have |simple| ilk}
+@d parametric=3 {parametric macros have |parametric| ilk}
+
+@ The names of modules are stored in |byte_mem| together
+with the identifier names, but a hash table is not used for them because
+\.{TANGLE} needs to be able to recognize a module name when given a prefix of
+that name. A conventional binary seach tree is used to retrieve module names,
+with fields called |llink| and |rlink| in place of |link| and |ilk|. The
+root of this tree is |rlink[0]|. If |p| is a pointer to a module name,
+|equiv[p]| points to its replacement text, just as in simple and parametric
+macros, unless this replacement text has not yet been defined (in which case
+|equiv[p]=0|).
+
+@d llink==link {left link in binary search tree for module names}
+@d rlink==ilk {right link in binary search tree for module names}
+
+@<Set init...@>=
+rlink[0]:=0; {the binary search tree starts out with nothing in it}
+equiv[0]:=0; {the undefined module has no replacement text}
+
+@ Here is a little procedure that prints the text of a given name.
+
+@p procedure print_id(@!p:name_pointer); {print identifier or module name}
+var k:0..max_bytes; {index into |byte_mem|}
+@!w:0..ww-1; {segment of |byte_mem|}
+begin if p>=name_ptr then print('IMPOSSIBLE')
+else begin w:=p mod ww;
+ for k:=byte_start[p] to byte_start[p+ww]-1 do print(xchr[byte_mem[w,k]]);
+ end;
+end;
+
+@* Searching for identifiers.
+The hash table described above is updated by the |id_lookup| procedure,
+which finds a given identifier and returns a pointer to its index in
+|byte_start|. If the identifier was not already present, it is inserted with
+a given |ilk| code; and an error message is printed if the identifier is being
+doubly defined.
+
+Because of the way \.{TANGLE}'s scanning mechanism works, it is most convenient
+to let |id_lookup| search for an identifier that is present in the |buffer|
+array. Two other global variables specify its position in the buffer: the
+first character is |buffer[id_first]|, and the last is |buffer[id_loc-1]|.
+Furthermore, if the identifier is really a string, the global variable
+|double_chars| tells how many of the characters in the buffer appear
+twice (namely \.{@@@@} and \.{""}), since this additional information makes
+it easy to calculate the true length of the string. The final double-quote
+of the string is not included in its ``identifier,'' but the first one is,
+so the string length is |id_loc-id_first-double_chars-1|.
+
+We have mentioned that |normal| identifiers belong to two hash tables,
+one for their true names as they appear in the \.{WEB} file and the other
+when they have been reduced to their first |unambig_length| characters.
+The hash tables are kept by the method of simple chaining, where the
+heads of the individual lists appear in the |hash| and |chop_hash| arrays.
+If |h| is a hash code, the primary hash table list starts at |hash[h]| and
+proceeds through |link| pointers; the secondary hash table list starts at
+|chop_hash[h]| and proceeds through |equiv| pointers. Of course, the same
+identifier will probably have two different values of |h|.
+
+The |id_lookup| procedure uses an auxiliary array called |chopped_id| to
+contain up to |unambig_length| characters of the current identifier, if
+it is necessary to compute the secondary hash code. (This array could be
+declared local to |id_lookup|, but in general we are making all array
+declarations global in this program, because some compilers and some machine
+architectures make dynamic array allocation inefficient.)
+
+@<Glob...@>=
+@!id_first:0..buf_size; {where the current identifier begins in the buffer}
+@!id_loc:0..buf_size; {just after the current identifier in the buffer}
+@!double_chars:0..buf_size; {correction to length in case of strings}
+@#
+@!hash,@!chop_hash:array [0..hash_size] of sixteen_bits; {heads of hash lists}
+@!chopped_id:array [0..unambig_length] of ASCII_code; {chopped identifier}
+
+@ Initially all the hash lists are empty.
+
+@<Local variables for init...@>=
+@!h:0..hash_size; {index into hash-head arrays}
+
+@ @<Set init...@>=
+for h:=0 to hash_size-1 do
+ begin hash[h]:=0; chop_hash[h]:=0;
+ end;
+
+@ Here now is the main procedure for finding identifiers (and strings).
+The parameter |t| is set to |normal| except when the identifier is
+a macro name that is just being defined; in the latter case, |t| will be
+|numeric|, |simple|, or |parametric|.
+
+@p function id_lookup(@!t:eight_bits):name_pointer; {finds current identifier}
+label found, not_found;
+var c:eight_bits; {byte being chopped}
+@!i:0..buf_size; {index into |buffer|}
+@!h:0..hash_size; {hash code}
+@!k:0..max_bytes; {index into |byte_mem|}
+@!w:0..ww-1; {segment of |byte_mem|}
+@!l:0..buf_size; {length of the given identifier}
+@!p,@!q:name_pointer; {where the identifier is being sought}
+@!s:0..unambig_length; {index into |chopped_id|}
+begin l:=id_loc-id_first; {compute the length}
+@<Compute the hash code |h|@>;
+@<Compute the name location |p|@>;
+if (p=name_ptr)or(t<>normal) then
+ @<Update the tables and check for possible errors@>;
+id_lookup:=p;
+end;
+
+@ A simple hash code is used: If the sequence of
+ASCII codes is $c_1c_2\ldots c_m$, its hash value will be
+$$(2^{n-1}c_1+2^{n-2}c_2+\cdots+c_n)\,\bmod\,|hash_size|.$$
+
+@<Compute the hash...@>=
+h:=buffer[id_first]; i:=id_first+1;
+while i<id_loc do
+ begin h:=(h+h+buffer[i]) mod hash_size; incr(i);
+ end
+
+@ If the identifier is new, it will be placed in position |p=name_ptr|,
+otherwise |p| will point to its existing location.
+
+@<Compute the name location...@>=
+p:=hash[h];
+while p<>0 do
+ begin if length(p)=l then
+ @<Compare name |p| with current identifier, |goto found| if equal@>;
+ p:=link[p];
+ end;
+p:=name_ptr; {the current identifier is new}
+link[p]:=hash[h]; hash[h]:=p; {insert |p| at beginning of hash list}
+found:
+
+@ @<Compare name |p|...@>=
+begin i:=id_first; k:=byte_start[p]; w:=p mod ww;
+while (i<id_loc)and(buffer[i]=byte_mem[w,k]) do
+ begin incr(i); incr(k);
+ end;
+if i=id_loc then goto found; {all characters agree}
+end
+
+@ @<Update the tables...@>=
+begin if ((p<>name_ptr)and(t<>normal)and(ilk[p]=normal)) or
+ ((p=name_ptr)and(t=normal)and(buffer[id_first]<>"""")) then
+ @<Compute the secondary hash code |h| and put the first characters
+ into the auxiliary array |chopped_id|@>;
+if p<>name_ptr then
+ @<Give double-definition error, if necessary, and change |p| to type |t|@>
+else @<Enter a new identifier into the table at position |p|@>;
+end
+
+@ The following routine, which is called into play when it is necessary to
+look at the secondary hash table, computes the same hash function as before
+(but on the chopped data), and places a zero after the chopped identifier
+in |chopped_id| to serve as a convenient sentinel.
+
+@<Compute the secondary...@>=
+begin i:=id_first; s:=0; h:=0;
+while (i<id_loc)and(s<unambig_length) do
+ begin if buffer[i]<>"_" then
+ begin if buffer[i]>="a" then chopped_id[s]:=buffer[i]-@'40
+ else chopped_id[s]:=buffer[i];
+ h:=(h+h+chopped_id[s]) mod hash_size; incr(s);
+ end;
+ incr(i);
+ end;
+chopped_id[s]:=0;
+end
+
+@ If a nonnumeric macro has appeared before it was defined, \.{TANGLE}
+will still work all right; after all, such behavior is typical of the
+replacement texts for modules, which act very much like macros.
+However, an undefined numeric macro may not be used on the right-hand
+side of another numeric macro definition, so \.{TANGLE} finds it
+simplest to make a blanket rule that numeric macros should be defined
+before they are used. The following routine gives an error message and
+also fixes up any damage that may have been caused.
+
+@<Give double...@>= {now |p<>name_ptr| and |t<>normal|}
+begin if ilk[p]=normal then
+ begin if t=numeric then err_print('! This identifier has already appeared');
+@.This identifier has already...@>
+ @<Remove |p| from secondary hash table@>;
+ end
+else err_print('! This identifier was defined before');
+@.This identifier was defined...@>
+ilk[p]:=t;
+end
+
+@ When we have to remove a secondary hash entry, because a |normal| identifier
+is changing to another |ilk|, the hash code |h| and chopped identifier have
+already been computed.
+
+@<Remove |p| from secondary...@>=
+q:=chop_hash[h];
+if q=p then chop_hash[h]:=equiv[p]
+else begin while equiv[q]<>p do q:=equiv[q];
+ equiv[q]:=equiv[p];
+ end
+
+@ The following routine could make good use of a generalized |pack| procedure
+that puts items into just part of a packed array instead of the whole thing.
+
+@<Enter a new identifier...@>=
+begin if (t=normal)and(buffer[id_first]<>"""") then
+ @<Check for ambiguity and update secondary hash@>;
+w:=name_ptr mod ww; k:=byte_ptr[w];
+if k+l>max_bytes then overflow('byte memory');
+if name_ptr>max_names-ww then overflow('name');
+i:=id_first; {get ready to move the identifier into |byte_mem|}
+while i<id_loc do
+ begin byte_mem[w,k]:=buffer[i]; incr(k); incr(i);
+ end;
+byte_ptr[w]:=k; byte_start[name_ptr+ww]:=k; incr(name_ptr);
+if buffer[id_first]<>"""" then ilk[p]:=t
+else @<Define and output a new string of the pool@>;
+end
+
+@ @<Check for ambig...@>=
+begin q:=chop_hash[h];
+while q<>0 do
+ begin @<Check if |q| conflicts with |p|@>;
+ q:=equiv[q];
+ end;
+equiv[p]:=chop_hash[h]; chop_hash[h]:=p; {put |p| at front of secondary list}
+end
+
+@ @<Check if |q| conflicts...@>=
+begin k:=byte_start[q]; s:=0; w:=q mod ww;
+while (k<byte_start[q+ww]) and (s<unambig_length) do
+ begin c:=byte_mem[w,k];
+ if c<>"_" then
+ begin if c>="a" then c:=c-@'40; {merge lowercase with uppercase}
+ if chopped_id[s]<>c then goto not_found;
+ incr(s);
+ end;
+ incr(k);
+ end;
+if (k=byte_start[q+ww])and(chopped_id[s]<>0) then goto not_found;
+print_nl('! Identifier conflict with ');
+@.Identifier conflict...@>
+for k:=byte_start[q] to byte_start[q+ww]-1 do print(xchr[byte_mem[w,k]]);
+error; q:=0; {only one conflict will be printed, since |equiv[0]=0|}
+not_found:
+end
+
+@ We compute the string pool check sum by working modulo a prime number
+that is large but not so large that overflow might occur.
+
+@d check_sum_prime==@'3777777667 {$2^{29}-73$}
+@^preprocessed strings@>
+
+@<Define and output a new string...@>=
+begin ilk[p]:=numeric; {strings are like numeric macros}
+if l-double_chars=2 then {this string is for a single character}
+ equiv[p]:=buffer[id_first+1]+1073741824
+else begin equiv[p]:=string_ptr+1073741824;
+ l:=l-double_chars-1;
+ if l>99 then err_print('! Preprocessed string is too long');
+@.Preprocessed string is too long@>
+ incr(string_ptr);
+ write(pool,xchr["0"+l div 10],xchr["0"+l mod 10]); {output the length}
+ pool_check_sum:=pool_check_sum+pool_check_sum+l;
+ while pool_check_sum>check_sum_prime do
+ pool_check_sum:=pool_check_sum-check_sum_prime;
+ i:=id_first+1;
+ while i<id_loc do
+ begin write(pool,xchr[buffer[i]]); {output characters of string}
+ pool_check_sum:=pool_check_sum+pool_check_sum+buffer[i];
+ while pool_check_sum>check_sum_prime do
+ pool_check_sum:=pool_check_sum-check_sum_prime;
+ if (buffer[i]="""") or (buffer[i]="@@") then
+ i:=i+2 {omit second appearance of doubled character}
+ else incr(i);
+ end;
+ write_ln(pool);
+ end;
+end
+
+@* Searching for module names.
+The |mod_lookup| procedure finds the module name |mod_text[1..l]| in the
+search tree, after inserting it if necessary, and returns a pointer to
+where it was found.
+
+@<Glob...@>=
+@!mod_text:array [0..longest_name] of ASCII_code; {name being sought for}
+
+@ According to the rules of \.{WEB}, no module name
+should be a proper prefix of another, so a ``clean'' comparison should
+occur between any two names. The result of |mod_lookup| is 0 if this
+prefix condition is violated. An error message is printed when such violations
+are detected during phase two of \.{WEAVE}.
+
+@d less=0 {the first name is lexicographically less than the second}
+@d equal=1 {the first name is equal to the second}
+@d greater=2 {the first name is lexicographically greater than the second}
+@d prefix=3 {the first name is a proper prefix of the second}
+@d extension=4 {the first name is a proper extension of the second}
+
+@p function mod_lookup(@!l:sixteen_bits):name_pointer; {finds module name}
+label found;
+var c:less..extension; {comparison between two names}
+@!j:0..longest_name; {index into |mod_text|}
+@!k:0..max_bytes; {index into |byte_mem|}
+@!w:0..ww-1; {segment of |byte_mem|}
+@!p:name_pointer; {current node of the search tree}
+@!q:name_pointer; {father of node |p|}
+begin c:=greater; q:=0; p:=rlink[0]; {|rlink[0]| is the root of the tree}
+while p<>0 do
+ begin @<Set \(|c| to the result of comparing the given name to
+ name |p|@>;
+ q:=p;
+ if c=less then p:=llink[q]
+ else if c=greater then p:=rlink[q]
+ else goto found;
+ end;
+@<Enter a new module name into the tree@>;
+found: if c<>equal then
+ begin err_print('! Incompatible section names'); p:=0;
+@.Incompatible module names@>
+ end;
+mod_lookup:=p;
+end;
+
+@ @<Enter a new module name...@>=
+w:=name_ptr mod ww; k:=byte_ptr[w];
+if k+l>max_bytes then overflow('byte memory');
+if name_ptr>max_names-ww then overflow('name');
+p:=name_ptr;
+if c=less then llink[q]:=p else rlink[q]:=p;
+llink[p]:=0; rlink[p]:=0; c:=equal; equiv[p]:=0;
+for j:=1 to l do byte_mem[w,k+j-1]:=mod_text[j];
+byte_ptr[w]:=k+l; byte_start[name_ptr+ww]:=k+l; incr(name_ptr);
+
+@ @<Set \(|c|...@>=
+begin k:=byte_start[p]; w:=p mod ww; c:=equal; j:=1;
+while (k<byte_start[p+ww]) and (j<=l) and (mod_text[j]=byte_mem[w,k]) do
+ begin incr(k); incr(j);
+ end;
+if k=byte_start[p+ww] then
+ if j>l then c:=equal
+ else c:=extension
+else if j>l then c:=prefix
+else if mod_text[j]<byte_mem[w,k] then c:=less
+else c:=greater;
+end
+
+@ The |prefix_lookup| procedure is supposed to find exactly one module
+name that has |mod_text[1..l]| as a prefix. Actually the algorithm silently
+accepts also the situation that some module name is a prefix of
+|mod_text[1..l]|, because the user who painstakingly typed in more than
+necessary probably doesn't want to be told about the wasted effort.
+
+@p function prefix_lookup(@!l:sixteen_bits):name_pointer; {finds name extension}
+var c:less..extension; {comparison between two names}
+@!count:0..max_names; {the number of hits}
+@!j:0..longest_name; {index into |mod_text|}
+@!k:0..max_bytes; {index into |byte_mem|}
+@!w:0..ww-1; {segment of |byte_mem|}
+@!p:name_pointer; {current node of the search tree}
+@!q:name_pointer; {another place to resume the search after one branch is done}
+@!r:name_pointer; {extension found}
+begin q:=0; p:=rlink[0]; count:=0; r:=0; {begin search at root of tree}
+while p<>0 do
+ begin @<Set \(|c|...@>;
+ if c=less then p:=llink[p]
+ else if c=greater then p:=rlink[p]
+ else begin r:=p; incr(count); q:=rlink[p]; p:=llink[p];
+ end;
+ if p=0 then
+ begin p:=q; q:=0;
+ end;
+ end;
+if count<>1 then
+ if count=0 then err_print('! Name does not match')
+@.Name does not match@>
+ else err_print('! Ambiguous prefix');
+@.Ambiguous prefix@>
+prefix_lookup:=r; {the result will be 0 if there was no match}
+end;
+
+@* Tokens.
+Replacement texts, which represent \PASCAL\ code in a compressed format,
+appear in |tok_mem| as mentioned above. The codes in
+these texts are called `tokens'; some tokens occupy two consecutive
+eight-bit byte positions, and the others take just one byte.
+
+If $p>0$ points to a replacement text, |tok_start[p]| is the |tok_mem| position
+of the first eight-bit code of that text. If |text_link[p]=0|,
+this is the replacement text for a macro, otherwise it is the replacement
+text for a module. In the latter case |text_link[p]| is either equal to
+|module_flag|, which means that there is no further text for this module, or
+|text_link[p]| points to a
+continuation of this replacement text; such links are created when
+several modules have \PASCAL\ texts with the same name, and they also
+tie together all the \PASCAL\ texts of unnamed modules.
+The replacement text pointer for the first unnamed module
+appears in |text_link[0]|, and the most recent such pointer is |last_unnamed|.
+
+@d module_flag==max_texts {final |text_link| in module replacement texts}
+
+@<Glob...@>=
+@!last_unnamed:text_pointer; {most recent replacement text of unnamed module}
+
+@ @<Set init...@>= last_unnamed:=0; text_link[0]:=0;
+
+@ If the first byte of a token is less than @'200, the token occupies a
+single byte. Otherwise we make a sixteen-bit token by combining two consecutive
+bytes |a| and |b|. If |@'200<=a<@'250|, then $(a-@'200)\times2^8+b$ points
+to an identifier; if |@'250<=a<@'320|, then
+$(a-@'250)\times2^8+b$ points to a module name; otherwise, i.e., if
+|@'320<=a<@'400|, then $(a-@'320)\times2^8+b$ is the number of the module
+in which the current replacement text appears.
+
+Codes less than @'200 are 7-bit ASCII codes that represent themselves.
+In particular, a single-character identifier like `|x|' will be a one-byte
+token, while all longer identifiers will occupy two bytes.
+
+Some of the 7-bit ASCII codes will not be present, however, so we can
+use them for special purposes. The following symbolic names are used:
+
+\yskip\hang |param| denotes insertion of a parameter. This occurs only in
+the replacement texts of parametric macros, outside of single-quoted strings
+in those texts.
+
+\hang |begin_comment| denotes \.{@@\{}, which will become either
+\.{\{} or \.{[}.
+
+\hang |end_comment| denotes \.{@@\}}, which will become either
+\.{\}} or \.{]}.
+
+\hang |octal| denotes the \.{@@\'} that precedes an octal constant.
+
+\hang |hex| denotes the \.{@@"} that precedes a hexadecimal constant.
+
+\hang |check_sum| denotes the \.{@@\char'44} that denotes the string pool
+check sum.
+
+\hang |join| denotes the concatenation of adjacent items with no
+space or line breaks allowed between them (the \.{@@\&} operation of \.{WEB}).
+
+\hang |double_dot| denotes `\.{..}' in \PASCAL.
+
+\hang |verbatim| denotes the \.{@@=} that begins a verbatim \PASCAL\ string.
+It is also used for the end of the string.
+
+\hang |force_line| denotes the \.{@@\\} that forces a new line in the
+\PASCAL\ output.
+@^ASCII code@>
+
+@d param=0 {ASCII null code will not appear}
+@d verbatim=@'2 {extended ASCII alpha should not appear}
+@d force_line=@'3 {extended ASCII beta should not appear}
+@d begin_comment=@'11 {ASCII tab mark will not appear}
+@d end_comment=@'12 {ASCII line feed will not appear}
+@d octal=@'14 {ASCII form feed will not appear}
+@d hex=@'15 {ASCII carriage return will not appear}
+@d double_dot=@'40 {ASCII space will not appear except in strings}
+@d check_sum=@'175 {will not be confused with right brace}
+@d join=@'177 {ASCII delete will not appear}
+
+@ The following procedure is used to enter a two-byte value into
+|tok_mem| when a replacement text is being generated.
+
+@p procedure store_two_bytes(@!x:sixteen_bits);
+ {stores high byte, then low byte}
+begin if tok_ptr[z]+2>max_toks then overflow('token');
+tok_mem[z,tok_ptr[z]]:=x div@'400; {this could be done by a shift command}
+tok_mem[z,tok_ptr[z]+1]:=x mod@'400; {this could be done by a logical and}
+tok_ptr[z]:=tok_ptr[z]+2;
+end;
+
+@ When \.{TANGLE} is being operated in debug mode, it has a procedure to display
+a replacement text in symbolic form. This procedure has not been spruced up to
+generate a real great format, but at least the results are not as bad as
+a memory dump.
+
+@p @!debug procedure print_repl(@!p:text_pointer);
+var k:0..max_toks; {index into |tok_mem|}
+@!a: sixteen_bits; {current byte(s)}
+@!zp: 0..zz-1; {segment of |tok_mem| being accessed}
+begin if p>=text_ptr then print('BAD')
+else begin k:=tok_start[p]; zp:=p mod zz;
+ while k<tok_start[p+zz] do
+ begin a:=tok_mem[zp,k];
+ if a>=@'200 then @<Display two-byte token starting with |a|@>
+ else @<Display one-byte token |a|@>;
+ incr(k);
+ end;
+ end;
+end;
+gubed
+
+@ @<Display two-byte...@>=
+begin incr(k);
+if a<@'250 then {identifier or string}
+ begin a:=(a-@'200)*@'400+tok_mem[zp,k]; print_id(a);
+ if byte_mem[a mod ww,byte_start[a]]="""" then print('"')
+ else print(' ');
+ end
+else if a<@'320 then {module name}
+ begin print('@@<'); print_id((a-@'250)*@'400+tok_mem[zp,k]);
+ print('@@>');
+ end
+else begin a:=(a-@'320)*@'400+tok_mem[zp,k]; {module number}
+ print('@@',xchr["{"],a:1,'@@',xchr["}"]); {can't use right brace
+ between \&{debug} and \&{gubed}}
+ end;
+end
+
+@ @<Display one-byte...@>=
+case a of
+begin_comment: print('@@',xchr["{"]);
+end_comment: print('@@',xchr["}"]); {can't use right brace
+ between \&{debug} and \&{gubed}}
+octal: print('@@''');
+hex: print('@@"');
+check_sum: print('@@$');
+param: print('#');
+"@@": print('@@@@');
+verbatim: print('@@=');
+force_line: print('@@\');
+othercases print(xchr[a])
+endcases
+
+@* Stacks for output.
+Let's make sure that our data structures contain enough information to
+produce the entire \PASCAL\ program as desired, by working next on the
+algorithms that actually do produce that program.
+
+@ The output process uses a stack to keep track of what is going on at
+different ``levels'' as the macros are being expanded.
+Entries on this stack have five parts:
+
+\yskip\hang |end_field| is the |tok_mem| location where the replacement
+text of a particular level will end;
+
+\hang |byte_field| is the |tok_mem| location from which the next token
+on a particular level will be read;
+
+\hang |name_field| points to the name corresponding to a particular level;
+
+\hang |repl_field| points to the replacement text currently being read
+at a particular level;
+
+\hang |mod_field| is the module number, or zero if this is a macro.
+
+\yskip\noindent The current values of these five quantities are referred to
+quite frequently, so they are stored in a separate place instead of in
+the |stack| array. We call the current values |cur_end|, |cur_byte|,
+|cur_name|, |cur_repl|, and |cur_mod|.
+
+The global variable |stack_ptr| tells how many levels of output are
+currently in progress. The end of all output occurs when the stack is
+empty, i.e., when |stack_ptr=0|.
+
+@<Types...@>=
+@t\4@>@!output_state=record
+ @!end_field: sixteen_bits; {ending location of replacement text}
+ @!byte_field: sixteen_bits; {present location within replacement text}
+ @!name_field: name_pointer; {|byte_start| index for text being output}
+ @!repl_field: text_pointer; {|tok_start| index for text being output}
+ @!mod_field: 0..@'27777; {module number or zero if not a module}
+ end;
+
+@ @d cur_end==cur_state.end_field {current ending location in |tok_mem|}
+@d cur_byte==cur_state.byte_field {location of next output byte in |tok_mem|}
+@d cur_name==cur_state.name_field {pointer to current name being expanded}
+@d cur_repl==cur_state.repl_field {pointer to current replacement text}
+@d cur_mod==cur_state.mod_field {current module number being expanded}
+
+@<Globals...@>=
+@!cur_state : output_state; {|cur_end|, |cur_byte|, |cur_name|,
+ |cur_repl|, |cur_mod|}
+@!stack : array [1..stack_size] of output_state; {info for non-current levels}
+@!stack_ptr: 0..stack_size; {first unused location in the output state stack}
+
+@ It is convenient to keep a global variable |zo| equal to |cur_repl mod zz|.
+
+@<Glob...@>=
+@!zo:0..zz-1; {the segment of |tok_mem| from which output is coming}
+
+@ Parameters must also be stacked. They are placed in
+|tok_mem| just above the other replacement texts, and dummy parameter
+`names' are placed in |byte_start| just after the other names.
+The variables |text_ptr| and |tok_ptr[z]| essentially serve as parameter
+stack pointers during the output phase, so there is no need for a separate
+data structure to handle this problem.
+
+@ There is an implicit stack corresponding to meta-comments that are output
+via \.{@@\{} and \.{@@\}}. But this stack need not be represented in detail,
+because we only need to know whether it is empty or not. A global variable
+|brace_level| tells how many items would be on this stack if it were present.
+
+@<Globals...@>=
+@!brace_level: eight_bits; {current depth of $\.{@@\{}\ldots\.{@@\}}$ nesting}
+
+@ To get the output process started, we will perform the following
+initialization steps. We may assume that |text_link[0]| is nonzero, since it
+points to the \PASCAL\ text in the first unnamed module that generates
+code; if there are no such modules, there is nothing to output, and an
+error message will have been generated before we do any of the initialization.
+
+@<Initialize the output stacks@>=
+stack_ptr:=1; brace_level:=0; cur_name:=0; cur_repl:=text_link[0];
+zo:=cur_repl mod zz; cur_byte:=tok_start[cur_repl];
+cur_end:=tok_start[cur_repl+zz]; cur_mod:=0;
+
+@ When the replacement text for name |p| is to be inserted into the output,
+the following subroutine is called to save the old level of output and get
+the new one going.
+
+@p procedure push_level(@!p:name_pointer); {suspends the current level}
+begin if stack_ptr=stack_size then overflow('stack')
+else begin stack[stack_ptr]:=cur_state; {save |cur_end|, |cur_byte|, etc.}
+ incr(stack_ptr);
+ cur_name:=p; cur_repl:=equiv[p]; zo:=cur_repl mod zz;
+ cur_byte:=tok_start[cur_repl]; cur_end:=tok_start[cur_repl+zz];
+ cur_mod:=0;
+ end;
+end;
+
+@ When we come to the end of a replacement text, the |pop_level| subroutine
+does the right thing: It either moves to the continuation of this replacement
+text or returns the state to the most recently stacked level. Part of this
+subroutine, which updates the parameter stack, will be given later when we
+study the parameter stack in more detail.
+
+@p procedure pop_level; {do this when |cur_byte| reaches |cur_end|}
+label exit;
+begin if text_link[cur_repl]=0 then {end of macro expansion}
+ begin if ilk[cur_name]=parametric then
+ @<Remove a parameter from the parameter stack@>;
+ end
+else if text_link[cur_repl]<module_flag then {link to a continuation}
+ begin cur_repl:=text_link[cur_repl]; {we will stay on the same level}
+ zo:=cur_repl mod zz;
+ cur_byte:=tok_start[cur_repl]; cur_end:=tok_start[cur_repl+zz];
+ return;
+ end;
+decr(stack_ptr); {we will go down to the previous level}
+if stack_ptr>0 then
+ begin cur_state:=stack[stack_ptr]; zo:=cur_repl mod zz;
+ end;
+exit: end;
+
+@ The heart of the output procedure is the |get_output| routine, which produces
+the next token of output that is not a reference to a macro. This procedure
+handles all the stacking and unstacking that is necessary. It returns the
+value |number| if the next output has a numeric value (the value of a
+numeric macro or string), in which case |cur_val| has been set to the
+number in question. The procedure also returns the value |module_number|
+if the next output begins or ends the replacement text of some module,
+in which case |cur_val| is that module's number (if beginning) or the
+negative of that value (if ending). And it returns the value |identifier|
+if the next output is an identifier of length two or more, in which case
+|cur_val| points to that identifier name.
+
+@d number=@'200 {code returned by |get_output| when next output is numeric}
+@d module_number=@'201 {code returned by |get_output| for module numbers}
+@d identifier=@'202 {code returned by |get_output| for identifiers}
+
+@<Globals...@>=
+@!cur_val:integer; {additional information corresponding to output token}
+
+@ If |get_output| finds that no more output remains, it returns the value zero.
+
+@p function get_output:sixteen_bits; {returns next token after macro expansion}
+label restart, done, found;
+var a:sixteen_bits; {value of current byte}
+@!b:eight_bits; {byte being copied}
+@!bal:sixteen_bits; {excess of \.( versus \.) while copying a parameter}
+@!k:0..max_bytes; {index into |byte_mem|}
+@!w:0..ww-1; {segment of |byte_mem|}
+begin restart: if stack_ptr=0 then
+ begin a:=0; goto found;
+ end;
+if cur_byte=cur_end then
+ begin cur_val:=-cur_mod; pop_level;
+ if cur_val=0 then goto restart;
+ a:=module_number; goto found;
+ end;
+a:=tok_mem[zo,cur_byte]; incr(cur_byte);
+if a<@'200 then {one-byte token}
+ if a=param then
+ @<Start scanning current macro parameter, |goto restart|@>
+ else goto found;
+a:=(a-@'200)*@'400+tok_mem[zo,cur_byte]; incr(cur_byte);
+if a<@'24000 then {|@'24000=(@'250-@'200)*@'400|}
+ @<Expand macro |a| and |goto found|, or |goto restart| if no output found@>;
+if a<@'50000 then {|@'50000=(@'320-@'200)*@'400|}
+ @<Expand module |a-@'24000|, |goto restart|@>;
+cur_val:=a-@'50000; a:=module_number; cur_mod:=cur_val;
+found:
+@!debug if trouble_shooting then debug_help;@;@+gubed@/
+get_output:=a;
+end;
+
+@ The user may have forgotten to give any \PASCAL\ text for a module name,
+or the \PASCAL\ text may have been associated with a different name by mistake.
+
+@<Expand module |a-...@>=
+begin a:=a-@'24000;
+if equiv[a]<>0 then push_level(a)
+else if a<>0 then
+ begin print_nl('! Not present: <'); print_id(a); print('>'); error;
+@.Not present: <section name>@>
+ end;
+goto restart;
+end
+
+@ @<Expand macro ...@>=
+begin case ilk[a] of
+normal: begin cur_val:=a; a:=identifier;
+ end;
+numeric: begin cur_val:=equiv[a]-1073741824; a:=number;
+ end;
+simple: begin push_level(a); goto restart;
+ end;
+parametric: begin @<Put a parameter on the parameter stack,
+ or |goto restart| if error occurs@>;
+ push_level(a); goto restart;
+ end;
+othercases confusion('output')
+endcases;@/
+goto found;
+end
+
+@ We come now to the interesting part, the job of putting a parameter on
+the parameter stack. First we pop the stack if necessary until getting to
+a level that hasn't ended. Then the next character must be a `\.(';
+and since parentheses are balanced on each level, the entire parameter must
+be present, so we can copy it without difficulty.
+
+@<Put a parameter...@>=
+while (cur_byte=cur_end)and(stack_ptr>0) do pop_level;
+if (stack_ptr=0)or(tok_mem[zo,cur_byte]<>"(") then
+ begin print_nl('! No parameter given for '); print_id(a); error;
+@.No parameter given for macro@>
+ goto restart;
+ end;
+@<Copy the parameter into |tok_mem|@>;
+equiv[name_ptr]:=text_ptr; ilk[name_ptr]:=simple; w:=name_ptr mod ww;
+k:=byte_ptr[w];
+@!debug if k=max_bytes then overflow('byte memory');
+byte_mem[w,k]:="#"; incr(k); byte_ptr[w]:=k;
+gubed {this code has set the parameter identifier for debugging printouts}
+if name_ptr>max_names-ww then overflow('name');
+byte_start[name_ptr+ww]:=k; incr(name_ptr);
+if text_ptr>max_texts-zz then overflow('text');
+text_link[text_ptr]:=0; tok_start[text_ptr+zz]:=tok_ptr[z];
+incr(text_ptr);
+z:=text_ptr mod zz
+
+@ The |pop_level| routine undoes the effect of parameter-pushing when
+a parameter macro is finished:
+
+@<Remove a parameter...@>=
+begin decr(name_ptr); decr(text_ptr);
+z:=text_ptr mod zz;
+stat if tok_ptr[z]>max_tok_ptr[z] then max_tok_ptr[z]:=tok_ptr[z];
+tats {the maximum value of |tok_ptr| occurs just before parameter popping}
+tok_ptr[z]:=tok_start[text_ptr];
+@!debug decr(byte_ptr[name_ptr mod ww]);@+gubed
+end
+
+@ When a parameter occurs in a replacement text, we treat it as a simple
+macro in position (|name_ptr-1|):
+
+@<Start scanning...@>=
+begin push_level(name_ptr-1); goto restart;
+end
+
+@ Similarly, a |param| token encountered as we copy a parameter is converted
+into a simple macro call for |name_ptr-1|.
+Some care is needed to handle cases like \\{macro}|(#; print('#)'))|; the
+\.{\#} token will have been changed to |param| outside of strings, but we
+still must distinguish `real' parentheses from those in strings.
+
+@d app_repl(#)==begin if tok_ptr[z]=max_toks then overflow('token');
+ tok_mem[z,tok_ptr[z]]:=#; incr(tok_ptr[z]); end
+
+@<Copy the parameter...@>=
+bal:=1; incr(cur_byte); {skip the opening `\.('}
+loop@+ begin b:=tok_mem[zo,cur_byte]; incr(cur_byte);
+ if b=param then store_two_bytes(name_ptr+@'77777)
+ else begin if b>=@'200 then
+ begin app_repl(b);
+ b:=tok_mem[zo,cur_byte]; incr(cur_byte);
+ end
+ else case b of
+ "(": incr(bal);
+ ")": begin decr(bal);
+ if bal=0 then goto done;
+ end;
+ "'": repeat app_repl(b);
+ b:=tok_mem[zo,cur_byte]; incr(cur_byte);
+ until b="'"; {copy string, don't change |bal|}
+ othercases do_nothing
+ endcases;
+ app_repl(b);
+ end;
+ end;
+done:
+
+@* Producing the output.
+The |get_output| routine above handles most of the complexity of output
+generation, but there are two further considerations that have a nontrivial
+effect on \.{TANGLE}'s algorithms.
+
+First, we want to make sure that the output is broken into lines not
+exceeding |line_length| characters per line, where these breaks occur at
+valid places (e.g., not in the middle of a string or a constant or an
+identifier, not between `\.<' and `\.>', not at a `\.{@@\&}' position
+where quantities are being joined together). Therefore we assemble the
+output into a buffer before deciding where the line breaks will appear.
+However, we make very little attempt to make ``logical'' line breaks that
+would enhance the readability of the output; people are supposed to read
+the input of \.{TANGLE} or the \TeX ed output of \.{WEAVE}, but not the
+tangled-up output. The only concession to readability is that a break after
+a semicolon will be made if possible, since commonly used ``pretty
+printing'' routines give better results in such cases.
+
+Second, we want to decimalize non-decimal constants, and to combine integer
+quantities that are added or subtracted, because \PASCAL\ doesn't allow
+constant expressions in subrange types or in case labels. This means we
+want to have a procedure that treats a construction like \.{(E-15+17)}
+as equivalent to `\.{(E+2)}', while also leaving `\.{(1E-15+17)}' and
+`\.{(E-15+17*y)}' untouched. Consider also `\.{-15+17.5}' versus
+`\.{-15+17..5}'. We shall not combine integers preceding or following
+\.*, \./, \.{div}, \.{mod}, or \.{@@\&}. Note that if |y| has been defined
+to equal $-2$, we must expand `\.{x*y}' into `\.{x*(-2)}'; but `\.{x-y}'
+can expand into `\.{x+2}' and we can even change `\.{x - y mod z}' to
+@^mod@>
+`\.{x + 2 mod z}' because \PASCAL\ has a nonstandard \&{mod} operation!
+
+The following solution to these problems has been adopted: An array
+|out_buf| contains characters that have been generated but not yet output,
+and there are three pointers into this array. One of these, |out_ptr|, is
+the number of characters currently in the buffer, and we will have
+|1<=out_ptr<=line_length| most of the time. The second is |break_ptr|,
+which is the largest value |<=out_ptr| such that we are definitely entitled
+to end a line by outputting the characters |out_buf[1..(break_ptr-1)]|;
+we will always have |break_ptr<=line_length|. Finally, |semi_ptr| is either
+zero or the largest known value of a legal break after a semicolon or comment
+on the current line; we will always have |semi_ptr<=break_ptr|.
+
+@<Globals...@>=
+@!out_buf: array [0..out_buf_size] of ASCII_code; {assembled characters}
+@!out_ptr: 0..out_buf_size; {first available place in |out_buf|}
+@!break_ptr: 0..out_buf_size; {last breaking place in |out_buf|}
+@!semi_ptr: 0..out_buf_size; {last semicolon breaking place in |out_buf|}
+
+@ Besides having those three pointers,
+the output process is in one of several states:
+
+\yskip\hang |num_or_id| means that the last item in the buffer is a number or
+identifier, hence a blank space or line break must be inserted if the next
+item is also a number or identifier.
+
+\yskip\hang |unbreakable| means that the last item in the buffer was followed
+by the \.{@@\&} operation that inhibits spaces between it and the next item.
+
+\yskip\hang |sign| means that the last item in the buffer is to be followed
+by \.+ or \.-, depending on whether |out_app| is positive or negative.
+
+\yskip\hang |sign_val| means that the decimal equivalent of
+$\vert|out_val|\vert$ should be appended to the buffer. If |out_val<0|,
+or if |out_val=0| and |last_sign<0|, the number should be preceded by a minus
+sign. Otherwise it should be preceded by the character |out_sign| unless
+|out_sign=0|; the |out_sign| variable is either 0 or \.{"\ "} or \.{"+"}.
+
+\yskip\hang |sign_val_sign| is like |sign_val|, but also append \.+ or \.-
+afterwards, depending on whether |out_app| is positive or negative.
+
+\yskip\hang |sign_val_val| is like |sign_val|, but also append the decimal
+equivalent of |out_app| including its sign, using |last_sign| in case
+|out_app=0|.
+
+\yskip\hang |misc| means none of the above.
+
+\yskip\noindent
+For example, the output buffer and output state run through the following
+sequence as we generate characters from `\.{(x-15+19-2)}':
+$$\vbox{\halign{$\hfil#\hfil$\quad&#\hfil&\quad\hfil#\hfil&\quad
+\hfil#\hfil&\quad\hfil#\hfil&\quad\hfil#\hfil\quad&\hfil#\hfil\cr
+output&|out_buf|&|out_state|&|out_sign|&|out_val|&|out_app|&|last_sign|\cr
+\noalign{\vskip 3pt}
+(&\.(&|misc|\cr
+x&\.{(x}&|num_or_id|\cr
+-&\.{(x}&|sign|&&&$-1$&$-1$\cr
+15&\.{(x}&|sign_val|&\.{"+"}&$-15$&&$-15$\cr
++&\.{(x}&|sign_val_sign|&\.{"+"}&$-15$&$+1$&$+1$\cr
+19&\.{(x}&|sign_val_val|&\.{"+"}&$-15$&$+19$&$+1$\cr
+-&\.{(x}&|sign_val_sign|&\.{"+"}&$+4$&$-1$&$-1$\cr
+2&\.{(x}&|sign_val_val|&\.{"+"}&$+4$&$-2$&$-2$\cr
+)&\.{(x+2)}&|misc|\cr}}$$
+At each stage we have put as much into the buffer as possible without
+knowing what is coming next. Examples like `\.{x-0.1}' indicate why
+|last_sign| is needed to associate the proper sign with an output of zero.
+
+In states |num_or_id|, |unbreakable|, and |misc| the last item in the buffer
+lies between |break_ptr| and |out_ptr-1|, inclusive; in the other states we
+have |break_ptr=out_ptr|.
+
+The numeric values assigned to |num_or_id|, etc., have been chosen to
+shorten some of the program logic; for example, the program makes use of
+the fact that |sign+2=sign_val_sign|.
+
+@d misc=0 {state associated with special characters}
+@d num_or_id=1 {state associated with numbers and identifiers}
+@d sign=2 {state associated with pending \.+ or \.-}
+@d sign_val=num_or_id+2 {state associated with pending sign and value}
+@d sign_val_sign=sign+2 {|sign_val| followed by another pending sign}
+@d sign_val_val=sign_val+2 {|sign_val| followed by another pending value}
+@d unbreakable=sign_val_val+1 {state associated with \.{@@\&}}
+
+@<Globals...@>=
+@!out_state:eight_bits; {current status of partial output}
+@!out_val,@!out_app:integer; {pending values}
+@!out_sign:ASCII_code; {sign to use if appending |out_val>=0|}
+@!last_sign:-1..+1; {sign to use if appending a zero}
+
+@ During the output process, |line| will equal the number of the next line
+to be output.
+
+@<Initialize the output buffer@>=
+out_state:=misc; out_ptr:=0; break_ptr:=0; semi_ptr:=0; out_buf[0]:=0; line:=1;
+
+@ Here is a routine that is invoked when |out_ptr>line_length|
+or when it is time to flush out the final line. The |flush_buffer| procedure
+often writes out the line up to the current |break_ptr| position, then moves the
+remaining information to the front of |out_buf|. However, it prefers to
+write only up to |semi_ptr|, if the residual line won't be too long.
+
+@d check_break==if out_ptr>line_length then flush_buffer
+
+@p procedure flush_buffer; {writes one line to output file}
+var k:0..out_buf_size; {index into |out_buf|}
+@!b:0..out_buf_size; {value of |break_ptr| upon entry}
+begin b:=break_ptr;
+if (semi_ptr<>0)and(out_ptr-semi_ptr<=line_length) then break_ptr:=semi_ptr;
+for k:=1 to break_ptr do write(Pascal_file,xchr[out_buf[k-1]]);
+write_ln(Pascal_file); incr(line);
+if line mod 100 = 0 then
+ begin print('.');
+ if line mod 500 = 0 then print(line:1);
+ update_terminal; {progress report}
+ end;
+if break_ptr<out_ptr then
+ begin if out_buf[break_ptr]=" " then
+ begin incr(break_ptr); {drop space at break}
+ if break_ptr>b then b:=break_ptr;
+ end;
+ for k:=break_ptr to out_ptr-1 do out_buf[k-break_ptr]:=out_buf[k];
+ end;
+out_ptr:=out_ptr-break_ptr; break_ptr:=b-break_ptr; semi_ptr:=0;
+if out_ptr>line_length then
+ begin err_print('! Long line must be truncated'); out_ptr:=line_length;
+@.Long line must be truncated@>
+ end;
+end;
+
+@ @<Empty the last line from the buffer@>=
+break_ptr:=out_ptr; semi_ptr:=0; flush_buffer;
+if brace_level<>0 then
+ err_print('! Program ended at brace level ',brace_level:1);
+@.Program ended at brace level n@>
+
+@ Another simple and useful routine appends the decimal equivalent of
+a nonnegative integer to the output buffer.
+
+@d app(#)==begin out_buf[out_ptr]:=#; incr(out_ptr); {append a single character}
+ end
+
+@p procedure app_val(@!v:integer); {puts |v| into buffer, assumes |v>=0|}
+var k:0..out_buf_size; {index into |out_buf|}
+begin k:=out_buf_size; {first we put the digits at the very end of |out_buf|}
+repeat out_buf[k]:=v mod 10; v:=v div 10; decr(k);
+until v=0;
+repeat incr(k); app(out_buf[k]+"0");
+until k=out_buf_size; {then we append them, most significant first}
+end;
+
+@ The output states are kept up to date by the output routines, which are
+called |send_out|, |send_val|, and |send_sign|. The |send_out| procedure
+has two parameters: |t| tells the type of information being sent and
+|v| contains the information proper. Some information may also be passed
+in the array |out_contrib|.
+
+\yskip\hang If |t=misc| then |v| is a character to be output.
+
+\hang If |t=str| then |v| is the length of a string or something like `\.{<>}'
+in |out_contrib|.
+
+\hang If |t=ident| then |v| is the length of an identifier in |out_contrib|.
+
+\hang If |t=frac| then |v| is the length of a fraction and/or exponent in
+|out_contrib|.
+
+@d str=1 {|send_out| code for a string}
+@d ident=2 {|send_out| code for an identifier}
+@d frac=3 {|send_out| code for a fraction}
+
+@<Glob...@>=
+@!out_contrib:array[1..line_length] of ASCII_code; {a contribution to |out_buf|}
+
+@ A slightly subtle point in the following code is that the user may ask
+for a |join| operation (i.e., \.{@@\&}) following whatever is being sent
+out. We will see later that |join| is implemented in part by calling
+|send_out(frac,0)|.
+
+@p procedure send_out(@!t:eight_bits; @!v:sixteen_bits);
+ {outputs |v| of type |t|}
+label restart;
+var k: 0..line_length; {index into |out_contrib|}
+begin @<Get the buffer ready for appending the new information@>;
+if t<>misc then for k:=1 to v do app(out_contrib[k])
+else app(v);
+check_break;
+if (t=misc)and((v=";")or(v="}")) then
+ begin semi_ptr:=out_ptr; break_ptr:=out_ptr;
+ end;
+if t>=ident then out_state:=num_or_id {|t=ident| or |frac|}
+else out_state:=misc {|t=str| or |misc|}
+end;
+
+@ Here is where the buffer states for signs and values collapse into simpler
+states, because we are about to append something that doesn't combine with
+the previous integer constants.
+
+We use an ASCII-code trick: Since |","-1="+"| and |","+1="-"|, we have
+|","-c=@t sign of $c$@>|, when $\vert c\vert=1$.
+
+@<Get the buffer ready...@>=
+restart: case out_state of
+num_or_id: if t<>frac then
+ begin break_ptr:=out_ptr;
+ if t=ident then app(" ");
+ end;
+sign: begin app(","-out_app); check_break; break_ptr:=out_ptr;
+ end;
+sign_val,sign_val_sign: begin @<Append \(|out_val| to buffer@>;
+ out_state:=out_state-2; goto restart;
+ end;
+sign_val_val: @<Reduce |sign_val_val| to |sign_val| and |goto restart|@>;
+misc: if t<>frac then break_ptr:=out_ptr;@/
+othercases do_nothing {this is for |unbreakable| state}
+endcases
+
+@ @<Append \(|out_val|...@>=
+if (out_val<0)or((out_val=0)and(last_sign<0)) then app("-")
+else if out_sign>0 then app(out_sign);
+app_val(abs(out_val)); check_break;
+
+@ @<Reduce |sign_val_val|...@>=
+begin if (t=frac)or(@<Contribution is \.* or \./ or \.{DIV} or \.{MOD}@>) then
+ begin @<Append \(|out_val| to buffer@>;
+ out_sign:="+"; out_val:=out_app;
+ end
+else out_val:=out_val+out_app;
+out_state:=sign_val; goto restart;
+end
+
+@ @<Contribution is \.*...@>=
+((t=ident)and(v=3)and@|
+ (((out_contrib[1]="D")and(out_contrib[2]="I")and(out_contrib[3]="V")) or@|
+ ((out_contrib[1]="M")and(out_contrib[2]="O")and(out_contrib[3]="D")) ))or@|
+@^uppercase@>
+ ((t=misc)and((v="*")or(v="/")))
+
+@ The following routine is called with $v=\pm1$ when a plus or minus sign is
+appended to the output. It extends \PASCAL\ to allow repeated signs
+(e.g., `\.{--}' is equivalent to `\.+'), rather than to give an error message.
+The signs following `\.E' in real constants are treated as part of a fraction,
+so they are not seen by this routine.
+
+@p procedure send_sign(@!v:integer);
+begin case out_state of
+sign, sign_val_sign: out_app:=out_app*v;
+sign_val:begin out_app:=v; out_state:=sign_val_sign;
+ end;
+sign_val_val: begin out_val:=out_val+out_app; out_app:=v;
+ out_state:=sign_val_sign;
+ end;
+othercases begin break_ptr:=out_ptr; out_app:=v; out_state:=sign;
+ end
+endcases;@/
+last_sign:=out_app;
+end;
+
+@ When a (signed) integer value is to be output, we call |send_val|.
+
+@d bad_case=666 {this is a label used below}
+
+@p procedure send_val(@!v:integer); {output the (signed) value |v|}
+label bad_case, {go here if we can't keep |v| in the output state}
+ exit;
+begin case out_state of
+num_or_id: begin @<If previous output was \.{DIV} or \.{MOD}, |goto bad_case|@>;
+ out_sign:=" "; out_state:=sign_val; out_val:=v; break_ptr:=out_ptr;
+ last_sign:=+1;
+ end;
+misc: begin @<If previous output was \.* or \./, |goto bad_case|@>;
+ out_sign:=0; out_state:=sign_val; out_val:=v; break_ptr:=out_ptr;
+ last_sign:=+1;
+ end;
+@t\4@>@<Handle cases of |send_val| when |out_state| contains a sign@>@;
+othercases goto bad_case
+endcases;@/
+return;
+bad_case: @<Append the decimal value of |v|, with parentheses if negative@>;
+exit: end;
+
+@ @<Handle cases of |send_val|...@>=
+sign: begin out_sign:="+"; out_state:=sign_val; out_val:=out_app*v;
+ end;
+sign_val: begin out_state:=sign_val_val; out_app:=v;
+ err_print('! Two numbers occurred without a sign between them');
+ end;
+sign_val_sign: begin out_state:=sign_val_val; out_app:=out_app*v;
+ end;
+sign_val_val: begin out_val:=out_val+out_app; out_app:=v;
+ err_print('! Two numbers occurred without a sign between them');
+@.Two numbers occurred...@>
+ end;
+
+@ @<If previous output was \.*...@>=
+if (out_ptr=break_ptr+1)and((out_buf[break_ptr]="*")or(out_buf[break_ptr]="/"))
+ then goto bad_case
+
+@ @<If previous output was \.{DIV}...@>=
+if (out_ptr=break_ptr+3)or
+ ((out_ptr=break_ptr+4)and(out_buf[break_ptr]=" ")) then
+@^uppercase@>
+ if ((out_buf[out_ptr-3]="D")and(out_buf[out_ptr-2]="I")and
+ (out_buf[out_ptr-1]="V"))or @/
+ ((out_buf[out_ptr-3]="M")and(out_buf[out_ptr-2]="O")and
+ (out_buf[out_ptr-1]="D")) then@/ goto bad_case
+
+@ @<Append the decimal value...@>=
+if v>=0 then
+ begin if out_state=num_or_id then
+ begin break_ptr:=out_ptr; app(" ");
+ end;
+ app_val(v); check_break; out_state:=num_or_id;
+ end
+else begin app("("); app("-"); app_val(-v); app(")"); check_break;
+ out_state:=misc;
+ end
+
+@* The big output switch.
+To complete the output process, we need a routine that takes the results
+of |get_output| and feeds them to |send_out|, |send_val|, or |send_sign|.
+This procedure `|send_the_output|' will be invoked just once, as follows:
+
+@<Phase II: Output the contents of the compressed tables@>=
+if text_link[0]=0 then
+ begin print_nl('! No output was specified.'); mark_harmless;
+@.No output was specified@>
+ end
+else begin print_nl('Writing the output file'); update_terminal;@/
+ @<Initialize the output stacks@>;
+ @<Initialize the output buffer@>;
+ send_the_output;@/
+ @<Empty the last line...@>;
+ print_nl('Done.');
+ end
+
+@ A many-way switch is used to send the output:
+
+@d get_fraction=2 {this label is used below}
+
+@p procedure send_the_output;
+label get_fraction, {go here to finish scanning a real constant}
+ reswitch, continue;
+var cur_char:eight_bits; {the latest character received}
+ @!k:0..line_length; {index into |out_contrib|}
+ @!j:0..max_bytes; {index into |byte_mem|}
+ @!w:0..ww-1; {segment of |byte_mem|}
+ @!n:integer; {number being scanned}
+begin while stack_ptr>0 do
+ begin cur_char:=get_output;
+ reswitch: case cur_char of
+ 0: do_nothing; {this case might arise if output ends unexpectedly}
+ @t\4@>@<Cases related to identifiers@>@;
+ @t\4@>@<Cases related to constants, possibly leading to
+ |get_fraction| or |reswitch|@>@;
+ "+","-": send_sign(","-cur_char);
+ @t\4@>@<Cases like \.{<>} and \.{:=}@>@;
+ "'": @<Send a string, |goto reswitch|@>;
+ @<Other printable characters@>: send_out(misc,cur_char);
+ @t\4@>@<Cases involving \.{@@\{} and \.{@@\}}@>@;
+ join: begin send_out(frac,0); out_state:=unbreakable;
+ end;
+ verbatim: @<Send verbatim string@>;
+ force_line: @<Force a line break@>;
+ othercases err_print('! Can''t output ASCII code ',cur_char:1)
+@.Can't output ASCII code n@>
+ endcases;@/
+ goto continue;
+ get_fraction: @<Special code to finish real constants@>;
+ continue: end;
+end;
+
+@ @<Cases like \.{<>}...@>=
+and_sign: begin out_contrib[1]:="A"; out_contrib[2]:="N"; out_contrib[3]:="D";
+@^uppercase@>
+ send_out(ident,3);
+ end;
+not_sign: begin out_contrib[1]:="N"; out_contrib[2]:="O"; out_contrib[3]:="T";
+ send_out(ident,3);
+ end;
+set_element_sign: begin out_contrib[1]:="I"; out_contrib[2]:="N";
+ send_out(ident,2);
+ end;
+or_sign: begin out_contrib[1]:="O"; out_contrib[2]:="R"; send_out(ident,2);
+ end;
+left_arrow: begin out_contrib[1]:=":"; out_contrib[2]:="="; send_out(str,2);
+ end;
+not_equal: begin out_contrib[1]:="<"; out_contrib[2]:=">"; send_out(str,2);
+ end;
+less_or_equal: begin out_contrib[1]:="<"; out_contrib[2]:="="; send_out(str,2);
+ end;
+greater_or_equal: begin out_contrib[1]:=">"; out_contrib[2]:="=";
+ send_out(str,2);
+ end;
+equivalence_sign: begin out_contrib[1]:="="; out_contrib[2]:="=";
+ send_out(str,2);
+ end;
+double_dot: begin out_contrib[1]:="."; out_contrib[2]:="."; send_out(str,2);
+ end;
+
+@ Please don't ask how all of the following characters can actually get
+through \.{TANGLE} outside of strings. It seems that |""""| and |"{"|
+cannot actually occur at this point of the program, but they have
+been included just in case \.{TANGLE} changes.
+
+If \.{TANGLE} is producing code for a \PASCAL\ compiler that uses `\.{(.}'
+and `\.{.)}' instead of square brackets (e.g., on machines with {\mc EBCDIC}
+code), one should remove |"["| and |"]"| from this list and put them into
+the preceding module in the appropriate way. Similarly, some compilers
+want `\.\^' to be converted to `\.{@@}'.
+@^system dependencies@>@^EBCDIC@>
+
+@<Other printable characters@>=
+"!","""","#","$","%","&","(",")","*",",","/",":",";","<","=",">","?",
+"@@","[","\","]","^","_","`","{","|"
+
+@ Single-character identifiers represent themselves, while longer ones
+appear in |byte_mem|. All must be converted to uppercase,
+with underlines removed. Extremely long identifiers must be chopped.
+
+(Some \PASCAL\ compilers work with lowercase letters instead of
+uppercase. If this module of \.{TANGLE} is changed, it's also necessary
+to change from uppercase to lowercase in the modules that are
+listed in the index under ``uppercase''.)
+@^system dependencies@>
+@^uppercase@>
+
+@d up_to(#)==#-24,#-23,#-22,#-21,#-20,#-19,#-18,#-17,#-16,#-15,#-14,
+ #-13,#-12,#-11,#-10,#-9,#-8,#-7,#-6,#-5,#-4,#-3,#-2,#-1,#
+
+@<Cases related to identifiers@>=
+"A",up_to("Z"): begin out_contrib[1]:=cur_char; send_out(ident,1);
+ end;
+"a",up_to("z"): begin out_contrib[1]:=cur_char-@'40; send_out(ident,1);
+ end;
+identifier: begin k:=0; j:=byte_start[cur_val]; w:=cur_val mod ww;
+ while (k<max_id_length)and(j<byte_start[cur_val+ww]) do
+ begin incr(k); out_contrib[k]:=byte_mem[w,j]; incr(j);
+ if out_contrib[k]>="a" then out_contrib[k]:=out_contrib[k]-@'40
+ else if out_contrib[k]="_" then decr(k);
+ end;
+ send_out(ident,k);
+ end;
+
+@ After sending a string, we need to look ahead at the next character, in order
+to see if there were two consecutive single-quote marks. Afterwards we go to
+|reswitch| to process the next character.
+
+@<Send a string...@>=
+begin k:=1; out_contrib[1]:="'";
+repeat if k<line_length then incr(k);
+out_contrib[k]:=get_output;
+until (out_contrib[k]="'")or(stack_ptr=0);
+if k=line_length then err_print('! String too long');
+@.String too long@>
+send_out(str,k); cur_char:=get_output;
+if cur_char="'" then out_state:=unbreakable;
+goto reswitch;
+end
+
+@ Sending a verbatim string is similar, but we don't have to look ahead.
+
+@<Send verbatim string@>=
+begin k:=0;
+repeat if k<line_length then incr(k);
+out_contrib[k]:=get_output;
+until (out_contrib[k]=verbatim)or(stack_ptr=0);
+if k=line_length then err_print('! Verbatim string too long');
+@.Verbatim string too long@>
+send_out(str,k-1);
+end
+
+@ In order to encourage portable software, \.{TANGLE} complains
+if the constants get dangerously close to the largest value representable
+on a 32-bit computer ($2^{31}-1$).
+
+@d digits=="0","1","2","3","4","5","6","7","8","9"
+
+@<Cases related to constants...@>=
+digits: begin n:=0;
+ repeat cur_char:=cur_char-"0";
+ if n>=@'1463146314 then err_print('! Constant too big')
+@.Constant too big@>
+ else n:=10*n+cur_char;
+ cur_char:=get_output;
+ until (cur_char>"9")or(cur_char<"0");
+ send_val(n); k:=0;
+ if cur_char="e" then cur_char:="E";
+@^uppercase@>
+ if cur_char="E" then goto get_fraction
+ else goto reswitch;
+ end;
+check_sum: send_val(pool_check_sum);
+octal: begin n:=0; cur_char:="0";
+ repeat cur_char:=cur_char-"0";
+ if n>=@'2000000000 then err_print('! Constant too big')
+ else n:=8*n+cur_char;
+ cur_char:=get_output;
+ until (cur_char>"7")or(cur_char<"0");
+ send_val(n); goto reswitch;
+ end;
+hex: begin n:=0; cur_char:="0";
+ repeat if cur_char>="A" then cur_char:=cur_char+10-"A"
+ else cur_char:=cur_char-"0";
+ if n>=@"8000000 then err_print('! Constant too big')
+ else n:=16*n+cur_char;
+ cur_char:=get_output;
+ until (cur_char>"F")or(cur_char<"0")or@|
+ ((cur_char>"9")and(cur_char<"A"));
+ send_val(n); goto reswitch;
+ end;
+number: send_val(cur_val);
+".": begin k:=1; out_contrib[1]:="."; cur_char:=get_output;
+ if cur_char="." then
+ begin out_contrib[2]:="."; send_out(str,2);
+ end
+ else if (cur_char>="0")and(cur_char<="9") then goto get_fraction
+ else begin send_out(misc,"."); goto reswitch;
+ end;
+ end;
+
+@ The following code appears at label `|get_fraction|', when we want to
+scan to the end of a real constant. The first |k| characters of a fraction
+have already been placed in |out_contrib|, and |cur_char| is the next character.
+
+@<Special code...@>=
+repeat if k<line_length then incr(k);
+out_contrib[k]:=cur_char; cur_char:=get_output;
+if (out_contrib[k]="E")and((cur_char="+")or(cur_char="-")) then
+@^uppercase@>
+ begin if k<line_length then incr(k);
+ out_contrib[k]:=cur_char; cur_char:=get_output;
+ end
+else if cur_char="e" then cur_char:="E";
+until (cur_char<>"E")and((cur_char<"0")or(cur_char>"9"));
+if k=line_length then err_print('! Fraction too long');
+@.Fraction too long@>
+send_out(frac,k); goto reswitch
+
+@ Some \PASCAL\ compilers do not recognize comments in braces, so the
+comments must be delimited by `\.{(*}' and `\.{*)}'.
+@^system dependencies@>
+In such cases the statement `|send_out(misc,"{")|' that appears here should
+be replaced by `\ignorespaces|begin out_contrib[1]:="("; out_contrib[2]:="*";
+send_out(str,2); end|', and a similar change should be made to
+`|send_out(misc,"}")|'.
+
+@<Cases involving \.{@@\{} and \.{@@\}}@>=
+begin_comment: begin if brace_level=0 then send_out(misc,"{")
+ else send_out(misc,"[");
+ incr(brace_level);
+ end;
+end_comment: if brace_level>0 then
+ begin decr(brace_level);
+ if brace_level=0 then send_out(misc,"}")
+ else send_out(misc,"]");
+ end
+ else err_print('! Extra @@}');
+@.Extra \AT!\}@>
+module_number: begin if brace_level=0 then send_out(misc,"{")
+ else send_out(misc,"[");
+ if cur_val<0 then
+ begin send_out(misc,":"); send_val(-cur_val);
+ end
+ else begin send_val(cur_val); send_out(misc,":");
+ end;
+ if brace_level=0 then send_out(misc,"}")
+ else send_out(misc,"]");
+ end;
+
+@ @<Force a line break@>=
+begin send_out(str,0); {normalize the buffer}
+while out_ptr>0 do
+ begin if out_ptr<=line_length then break_ptr:=out_ptr;
+ flush_buffer;
+ end;
+out_state:=misc;
+end
+
+@* Introduction to the input phase.
+We have now seen that \.{TANGLE} will be able to output the full
+\PASCAL\ program, if we can only get that program into the byte memory in
+the proper format. The input process is something like the output process
+in reverse, since we compress the text as we read it in and we expand it
+as we write it out.
+
+There are three main input routines. The most interesting is the one that gets
+the next token of a \PASCAL\ text; the other two are used to scan rapidly past
+\TeX\ text in the \.{WEB} source code. One of the latter routines will jump to
+the next token that starts with `\.{@@}', and the other skips to the end
+of a \PASCAL\ comment.
+
+@ But first we need to consider the low-level routine |get_line|
+that takes care of merging |change_file| into |web_file|. The |get_line|
+procedure also updates the line numbers for error messages.
+
+@<Globals...@>=
+@!ii:integer; {general purpose |for| loop variable in the outer block}
+@!line:integer; {the number of the current line in the current file}
+@!other_line:integer; {the number of the current line in the input file that
+ is not currently being read}
+@!temp_line:integer; {used when interchanging |line| with |other_line|}
+@!limit:0..buf_size; {the last character position occupied in the buffer}
+@!loc:0..buf_size; {the next character position to be read from the buffer}
+@!input_has_ended: boolean; {if |true|, there is no more input}
+@!changing: boolean; {if |true|, the current line is from |change_file|}
+
+@ As we change |changing| from |true| to |false| and back again, we must
+remember to swap the values of |line| and |other_line| so that the |err_print|
+routine will be sure to report the correct line number.
+
+@d change_changing==
+ changing := not changing;
+ temp_line:=other_line; other_line:=line; line:=temp_line
+ {|line @t$\null\BA\null$@> other_line|}
+
+@ When |changing| is |false|, the next line of |change_file| is kept in
+|change_buffer[0..change_limit]|, for purposes of comparison with the next
+line of |web_file|. After the change file has been completely input, we
+set |change_limit:=0|, so that no further matches will be made.
+
+@<Globals...@>=
+@!change_buffer:array[0..buf_size] of ASCII_code;
+@!change_limit:0..buf_size; {the last position occupied in |change_buffer|}
+
+@ Here's a simple function that checks if the two buffers are different.
+
+@p function lines_dont_match:boolean;
+label exit;
+var k:0..buf_size; {index into the buffers}
+begin lines_dont_match:=true;
+if change_limit<>limit then return;
+if limit>0 then
+ for k:=0 to limit-1 do if change_buffer[k]<>buffer[k] then return;
+lines_dont_match:=false;
+exit: end;
+
+@ Procedure |prime_the_change_buffer| sets |change_buffer| in preparation
+for the next matching operation. Since blank lines in the change file are
+not used for matching, we have |(change_limit=0)and not changing| if and
+only if the change file is exhausted. This procedure is called only
+when |changing| is true; hence error messages will be reported correctly.
+
+@p procedure prime_the_change_buffer;
+label continue, done, exit;
+var k:0..buf_size; {index into the buffers}
+begin change_limit:=0; {this value will be used if the change file ends}
+@<Skip over comment lines in the change file; |return| if end of file@>;
+@<Skip to the next nonblank line; |return| if end of file@>;
+@<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>;
+exit: end;
+
+@ While looking for a line that begins with \.{@@x} in the change file,
+we allow lines that begin with \.{@@}, as long as they don't begin with
+\.{@@y} or \.{@@z} (which would probably indicate that the change file is
+fouled up).
+
+@<Skip over comment lines in the change file...@>=
+loop@+ begin incr(line);
+ if not input_ln(change_file) then return;
+ if limit<2 then goto continue;
+ if buffer[0]<>"@@" then goto continue;
+ if (buffer[1]>="X")and(buffer[1]<="Z") then
+ buffer[1]:=buffer[1]+"z"-"Z"; {lowercasify}
+ if buffer[1]="x" then goto done;
+ if (buffer[1]="y")or(buffer[1]="z") then
+ begin loc:=2; err_print('! Where is the matching @@x?');
+@.Where is the match...@>
+ end;
+continue: end;
+done:
+
+@ Here we are looking at lines following the \.{@@x}.
+
+@<Skip to the next nonblank line...@>=
+repeat incr(line);
+ if not input_ln(change_file) then
+ begin err_print('! Change file ended after @@x');
+@.Change file ended...@>
+ return;
+ end;
+until limit>0;
+
+@ @<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>=
+begin change_limit:=limit;
+if limit>0 then for k:=0 to limit-1 do change_buffer[k]:=buffer[k];
+end
+
+@ The following procedure is used to see if the next change entry should
+go into effect; it is called only when |changing| is false.
+The idea is to test whether or not the current
+contents of |buffer| matches the current contents of |change_buffer|.
+If not, there's nothing more to do; but if so, a change is called for:
+All of the text down to the \.{@@y} is supposed to match. An error
+message is issued if any discrepancy is found. Then the procedure
+prepares to read the next line from |change_file|.
+
+@p procedure check_change; {switches to |change_file| if the buffers match}
+label exit;
+var n:integer; {the number of discrepancies found}
+@!k:0..buf_size; {index into the buffers}
+begin if lines_dont_match then return;
+n:=0;
+loop@+ begin change_changing; {now it's |true|}
+ incr(line);
+ if not input_ln(change_file) then
+ begin err_print('! Change file ended before @@y');
+@.Change file ended...@>
+ change_limit:=0; change_changing; {|false| again}
+ return;
+ end;
+ @<If the current line starts with \.{@@y},
+ report any discrepancies and |return|@>;
+ @<Move |buffer| and |limit|...@>;
+ change_changing; {now it's |false|}
+ incr(line);
+ if not input_ln(web_file) then
+ begin err_print('! WEB file ended during a change');
+@.WEB file ended...@>
+ input_has_ended:=true; return;
+ end;
+ if lines_dont_match then incr(n);
+ end;
+exit: end;
+
+@ @<If the current line starts with \.{@@y}...@>=
+if limit>1 then if buffer[0]="@@" then
+ begin if (buffer[1]>="X")and(buffer[1]<="Z") then
+ buffer[1]:=buffer[1]+"z"-"Z"; {lowercasify}
+ if (buffer[1]="x")or(buffer[1]="z") then
+ begin loc:=2; err_print('! Where is the matching @@y?');
+@.Where is the match...@>
+ end
+ else if buffer[1]="y" then
+ begin if n>0 then
+ begin loc:=2; err_print('! Hmm... ',n:1,
+ ' of the preceding lines failed to match');
+@.Hmm... n of the preceding...@>
+ end;
+ return;
+ end;
+ end
+
+@ @<Initialize the input system@>=
+open_input; line:=0; other_line:=0;@/
+changing:=true; prime_the_change_buffer; change_changing;@/
+limit:=0; loc:=1; buffer[0]:=" "; input_has_ended:=false;
+
+@ The |get_line| procedure is called when |loc>limit|; it puts the next
+line of merged input into the buffer and updates the other variables
+appropriately. A space is placed at the right end of the line.
+
+@p procedure get_line; {inputs the next line}
+label restart;
+begin restart: if changing then
+ @<Read from |change_file| and maybe turn off |changing|@>;
+if not changing then
+ begin @<Read from |web_file| and maybe turn on |changing|@>;
+ if changing then goto restart;
+ end;
+loc:=0; buffer[limit]:=" ";
+end;
+
+@ @<Read from |web_file|...@>=
+begin incr(line);
+if not input_ln(web_file) then input_has_ended:=true
+else if limit=change_limit then
+ if buffer[0]=change_buffer[0] then
+ if change_limit>0 then check_change;
+end
+
+@ @<Read from |change_file|...@>=
+begin incr(line);
+if not input_ln(change_file) then
+ begin err_print('! Change file ended without @@z');
+@.Change file ended...@>
+ buffer[0]:="@@"; buffer[1]:="z"; limit:=2;
+ end;
+if limit>1 then {check if the change has ended}
+ if buffer[0]="@@" then
+ begin if (buffer[1]>="X")and(buffer[1]<="Z") then
+ buffer[1]:=buffer[1]+"z"-"Z"; {lowercasify}
+ if (buffer[1]="x")or(buffer[1]="y") then
+ begin loc:=2; err_print('! Where is the matching @@z?');
+@.Where is the match...@>
+ end
+ else if buffer[1]="z" then
+ begin prime_the_change_buffer; change_changing;
+ end;
+ end;
+end
+
+@ At the end of the program, we will tell the user if the change file
+had a line that didn't match any relevant line in |web_file|.
+
+@<Check that all changes have been read@>=
+if change_limit<>0 then {|changing| is false}
+ begin for ii:=0 to change_limit do buffer[ii]:=change_buffer[ii];
+ limit:=change_limit; changing:=true; line:=other_line; loc:=change_limit;
+ err_print('! Change file entry did not match');
+@.Change file entry did not match@>
+ end
+
+@ Important milestones are reached during the input phase when certain
+control codes are sensed.
+
+Control codes in \.{WEB} begin with `\.{@@}', and the next character
+identifies the code. Some of these are of interest only to \.{WEAVE},
+so \.{TANGLE} ignores them; the others are converted by \.{TANGLE} into
+internal code numbers by the |control_code| function below. The ordering
+of these internal code numbers has been chosen to simplify the program logic;
+larger numbers are given to the control codes that denote more significant
+milestones.
+
+@d ignore=0 {control code of no interest to \.{TANGLE}}
+@d control_text=@'203 {control code for `\.{@@t}', `\.{@@\^}', etc.}
+@d format=@'204 {control code for `\.{@@f}'}
+@d definition=@'205 {control code for `\.{@@d}'}
+@d begin_Pascal=@'206 {control code for `\.{@@p}'}
+@d module_name=@'207 {control code for `\.{@@<}'}
+@d new_module=@'210 {control code for `\.{@@\ }' and `\.{@@*}'}
+
+@p function control_code(@!c:ASCII_code):eight_bits; {convert |c| after \.{@@}}
+begin case c of
+"@@": control_code:="@@"; {`quoted' at sign}
+"'": control_code:=octal; {precedes octal constant}
+"""": control_code:=hex; {precedes hexadecimal constant}
+"$": control_code:=check_sum; {string pool check sum}
+" ",tab_mark: control_code:=new_module; {beginning of a new module}
+"*": begin print('*',module_count+1:1);
+ update_terminal; {print a progress report}
+ control_code:=new_module; {beginning of a new module}
+ end;
+"D","d": control_code:=definition; {macro definition}
+"F","f": control_code:=format; {format definition}
+"{": control_code:=begin_comment; {begin-comment delimiter}
+"}": control_code:=end_comment; {end-comment delimiter}
+"P","p": control_code:=begin_Pascal; {\PASCAL\ text in unnamed module}
+"T","t","^",".",":": control_code:=control_text; {control text to be ignored}
+"&": control_code:=join; {concatenate two tokens}
+"<": control_code:=module_name; {beginning of a module name}
+"=": control_code:=verbatim; {beginning of \PASCAL\ verbatim mode}
+"\": control_code:=force_line; {force a new line in \PASCAL\ output}
+othercases control_code:=ignore {ignore all other cases}
+endcases;
+end;
+
+@ The |skip_ahead| procedure reads through the input at fairly high speed
+until finding the next non-ignorable control code, which it returns.
+
+@p function skip_ahead:eight_bits; {skip to next control code}
+label done;
+var c:eight_bits; {control code found}
+begin loop begin if loc>limit then
+ begin get_line;
+ if input_has_ended then
+ begin c:=new_module; goto done;
+ end;
+ end;
+ buffer[limit+1]:="@@";
+ while buffer[loc]<>"@@" do incr(loc);
+ if loc<=limit then
+ begin loc:=loc+2; c:=control_code(buffer[loc-1]);
+ if (c<>ignore)or(buffer[loc-1]=">") then goto done;
+ end;
+ end;
+done: skip_ahead:=c;
+end;
+
+@ The |skip_comment| procedure reads through the input at somewhat high speed
+until finding the first unmatched right brace or until coming to the end
+of the file. It ignores characters following `\.\\' characters, since all
+braces that aren't nested are supposed to be hidden in that way. For
+example, consider the process of skipping the first comment below,
+where the string containing the right brace has been typed as \.{\`\\.\\\}\'}
+in the \.{WEB} file.
+
+@p procedure skip_comment; {skips to next unmatched `\.\}'}
+label exit;
+var bal:eight_bits; {excess of left braces}
+@!c:ASCII_code; {current character}
+begin bal:=0;
+loop@+ begin if loc>limit then
+ begin get_line;
+ if input_has_ended then
+ begin err_print('! Input ended in mid-comment');
+@.Input ended in mid-comment@>
+ return;
+ end;
+ end;
+ c:=buffer[loc]; incr(loc);
+ @<Do special things when |c="@@", "\", "{", "}"|; |return| at end@>;
+ end;
+exit:end;
+
+@ @<Do special things when |c="@@"...@>=
+if c="@@" then
+ begin c:=buffer[loc];
+ if (c<>" ")and(c<>tab_mark)and(c<>"*")and(c<>"z")and(c<>"Z") then incr(loc)
+ else begin err_print('! Section ended in mid-comment');
+@.Section ended in mid-comment@>
+ decr(loc); return;
+ end
+ end
+else if (c="\")and(buffer[loc]<>"@@") then incr(loc)
+else if c="{" then incr(bal)
+else if c="}" then
+ begin if bal=0 then return;
+ decr(bal);
+ end
+
+@* Inputting the next token.
+As stated above, \.{TANGLE}'s most interesting input procedure is the
+|get_next| routine that inputs the next token. However, the procedure
+isn't especially difficult.
+
+In most cases the tokens output by |get_next| have the form used in
+replacement texts, except that two-byte tokens are not produced.
+An identifier that isn't one letter long is represented by the
+output `|identifier|', and in such a case the global variables
+|id_first| and |id_loc| will have been set to the appropriate values
+needed by the |id_lookup| procedure. A string that begins with a
+double-quote is also considered an |identifier|, and in such a case
+the global variable |double_chars| will also have been set appropriately.
+Control codes produce the corresponding output of the |control_code|
+function above; and if that code is |module_name|, the value of |cur_module|
+will point to the |byte_start| entry for that module name.
+
+Another global variable, |scanning_hex|, is |true| during the time that
+the letters \.A through \.F should be treated as if they were digits.
+
+@<Globals...@>=
+@!cur_module: name_pointer; {name of module just scanned}
+@!scanning_hex: boolean; {are we scanning a hexadecimal constant?}
+
+@ @<Set init...@>=
+scanning_hex:=false;
+
+@ At the top level, |get_next| is a multi-way switch based on the next
+character in the input buffer. A |new_module| code is inserted at the
+very end of the input file.
+
+@p function get_next:eight_bits; {produces the next input token}
+label restart,done,found;
+var c:eight_bits; {the current character}
+@!d:eight_bits; {the next character}
+@!j,@!k:0..longest_name; {indices into |mod_text|}
+begin restart: if loc>limit then
+ begin get_line;
+ if input_has_ended then
+ begin c:=new_module; goto found;
+ end;
+ end;
+c:=buffer[loc]; incr(loc);
+if scanning_hex then @<Go to |found| if |c| is a hexadecimal digit,
+ otherwise set |scanning_hex:=false|@>;
+case c of
+"A",up_to("Z"),"a",up_to("z"): @<Get an identifier@>;
+"""": @<Get a preprocessed string@>;
+"@@": @<Get control code and possible module name@>;
+@t\4@>@<Compress two-symbol combinations like `\.{:=}'@>@;
+" ",tab_mark: goto restart; {ignore spaces and tabs}
+"{": begin skip_comment; goto restart;
+ end;
+"}": begin err_print('! Extra }'); goto restart;
+@.Extra \}@>
+ end;
+othercases if c>=128 then goto restart {ignore nonstandard characters}
+ else do_nothing
+endcases;
+found:@!debug if trouble_shooting then debug_help;@;@+gubed@/
+get_next:=c;
+end;
+
+@ @<Go to |found| if |c| is a hexadecimal digit...@>=
+if ((c>="0")and(c<="9"))or((c>="A")and(c<="F")) then goto found
+else scanning_hex:=false
+
+@ Note that the following code substitutes \.{@@\{} and \.{@@\}} for the
+respective combinations `\.{(*}' and `\.{*)}'. Explicit braces should be used
+for \TeX\ comments in \PASCAL\ text.
+
+@d compress(#)==begin if loc<=limit then begin c:=#; incr(loc); end; end
+
+@<Compress two-symbol...@>=
+".": if buffer[loc]="." then compress(double_dot)
+ else if buffer[loc]=")" then compress("]");
+":": if buffer[loc]="=" then compress(left_arrow);
+"=": if buffer[loc]="=" then compress(equivalence_sign);
+">": if buffer[loc]="=" then compress(greater_or_equal);
+"<": if buffer[loc]="=" then compress(less_or_equal)
+ else if buffer[loc]=">" then compress(not_equal);
+"(": if buffer[loc]="*" then compress(begin_comment)
+ else if buffer[loc]="." then compress("[");
+"*": if buffer[loc]=")" then compress(end_comment);
+
+@ We have to look at the preceding character to make sure this isn't part
+of a real constant, before trying to find an identifier starting with
+`\.e' or `\.E'.
+
+@<Get an identifier@>=
+begin if ((c="e")or(c="E"))and(loc>1) then
+ if (buffer[loc-2]<="9")and(buffer[loc-2]>="0") then c:=0;
+if c<>0 then
+ begin decr(loc); id_first:=loc;
+ repeat incr(loc); d:=buffer[loc];
+ until ((d<"0")or((d>"9")and(d<"A"))or((d>"Z")and(d<"a"))or(d>"z")) and
+ (d<>"_");
+ if loc>id_first+1 then
+ begin c:=identifier; id_loc:=loc;
+ end;
+ end
+else c:="E"; {exponent of a real constant}
+end
+
+@ A string that starts and ends with double-quote marks is converted into
+an identifier that behaves like a numeric macro by means of the following
+piece of the program.
+@^preprocessed strings@>
+
+@<Get a preprocessed string@>=
+begin double_chars:=0; id_first:=loc-1;
+repeat d:=buffer[loc]; incr(loc);
+ if (d="""")or(d="@@") then
+ if buffer[loc]=d then
+ begin incr(loc); d:=0; incr(double_chars);
+ end
+ else begin if d="@@" then err_print('! Double @@ sign missing')
+@.Double \AT! sign missing@>
+ end
+ else if loc>limit then
+ begin err_print('! String constant didn''t end'); d:="""";
+@.String constant didn't end@>
+ end;
+until d="""";
+id_loc:=loc-1; c:=identifier;
+end
+
+@ After an \.{@@} sign has been scanned, the next character tells us
+whether there is more work to do.
+
+@<Get control code and possible module name@>=
+begin c:=control_code(buffer[loc]); incr(loc);
+if c=ignore then goto restart
+else if c=hex then scanning_hex:=true
+else if c=module_name then
+ @<Scan the \(module name and make |cur_module| point to it@>
+else if c=control_text then
+ begin repeat c:=skip_ahead;
+ until c<>"@@";
+ if buffer[loc-1]<>">" then
+ err_print('! Improper @@ within control text');
+@.Improper \AT! within control text@>
+ goto restart;
+ end;
+end
+
+@ @<Scan the \(module name...@>=
+begin @<Put module name into |mod_text[1..k]|@>;
+if k>3 then
+ begin if (mod_text[k]=".")and(mod_text[k-1]=".")and(mod_text[k-2]=".") then
+ cur_module:=prefix_lookup(k-3)
+ else cur_module:=mod_lookup(k);
+ end
+else cur_module:=mod_lookup(k);
+end
+
+@ Module names are placed into the |mod_text| array with consecutive spaces,
+tabs, and carriage-returns replaced by single spaces. There will be no
+spaces at the beginning or the end. (We set |mod_text[0]:=" "| to facilitate
+this, since the |mod_lookup| routine uses |mod_text[1]| as the first
+character of the name.)
+
+@<Set init...@>=mod_text[0]:=" ";
+
+@ @<Put module name...@>=
+k:=0;
+loop@+ begin if loc>limit then
+ begin get_line;
+ if input_has_ended then
+ begin err_print('! Input ended in section name');
+@.Input ended in section name@>
+ goto done;
+ end;
+ end;
+ d:=buffer[loc];
+ @<If end of name, |goto done|@>;
+ incr(loc); if k<longest_name-1 then incr(k);
+ if (d=" ")or(d=tab_mark) then
+ begin d:=" "; if mod_text[k-1]=" " then decr(k);
+ end;
+ mod_text[k]:=d;
+ end;
+done: @<Check for overlong name@>;
+if (mod_text[k]=" ")and(k>0) then decr(k);
+
+@ @<If end of name,...@>=
+if d="@@" then
+ begin d:=buffer[loc+1];
+ if d=">" then
+ begin loc:=loc+2; goto done;
+ end;
+ if (d=" ")or(d=tab_mark)or(d="*") then
+ begin err_print('! Section name didn''t end'); goto done;
+@.Section name didn't end@>
+ end;
+ incr(k); mod_text[k]:="@@"; incr(loc); {now |d=buffer[loc]| again}
+ end
+
+@ @<Check for overlong name@>=
+if k>=longest_name-2 then
+ begin print_nl('! Section name too long: ');
+@.Section name too long@>
+ for j:=1 to 25 do print(xchr[mod_text[j]]);
+ print('...'); mark_harmless;
+ end
+
+@* Scanning a numeric definition.
+When \.{TANGLE} looks at the \PASCAL\ text following the `\.=' of a numeric
+macro definition, it calls on the precedure |scan_numeric(p)|, where |p|
+points to the name that is to be defined. This procedure evaluates the
+right-hand side, which must consist entirely of integer constants and
+defined numeric macros connected with \.+ and \.- signs (no parentheses).
+It also sets the global variable |next_control| to the control code that
+terminated this definition.
+
+A definition ends with the control codes |definition|, |format|, |module_name|,
+|begin_Pascal|, and |new_module|, all of which can be recognized
+by the fact that they are the largest values |get_next| can return.
+
+@d end_of_definition(#)==(#>=format)
+ {is |#| a control code ending a definition?}
+
+@<Global...@>=
+@!next_control:eight_bits; {control code waiting to be acted upon}
+
+@ The evaluation of a numeric expression makes use of two variables called the
+|accumulator| and the |next_sign|. At the beginning, |accumulator| is zero and
+|next_sign| is $+1$. When a \.+ or \.- is scanned, |next_sign| is multiplied
+by the value of that sign. When a numeric value is scanned, it is multiplied by
+|next_sign| and added to the |accumulator|, then |next_sign| is reset to $+1$.
+
+@d add_in(#)==begin accumulator:=accumulator+next_sign*(#); next_sign:=+1;
+ end
+
+@p procedure scan_numeric(@!p:name_pointer); {defines numeric macros}
+label reswitch, done;
+var accumulator:integer; {accumulates sums}
+@!next_sign:-1..+1; {sign to attach to next value}
+@!q:name_pointer; {points to identifiers being evaluated}
+@!val:integer; {constants being evaluated}
+begin @<Set \(|accumulator| to the value of the right-hand side@>;
+if abs(accumulator)>=1073741824 then
+ begin err_print('! Value too big: ',accumulator:1); accumulator:=0;
+@.Value too big@>
+ end;
+equiv[p]:=accumulator+1073741824;
+ {name |p| now is defined to equal |accumulator|}
+end;
+
+@ @<Set \(|accumulator| to the value of the right-hand side@>=
+accumulator:=0; next_sign:=+1;
+loop@+ begin next_control:=get_next;
+ reswitch: case next_control of
+ digits: begin @<Set |val| to value of decimal constant, and
+ set |next_control| to the following token@>;
+ add_in(val); goto reswitch;
+ end;
+ octal: begin @<Set |val| to value of octal constant, and
+ set |next_control| to the following token@>;
+ add_in(val); goto reswitch;
+ end;
+ hex: begin @<Set |val| to value of hexadecimal constant, and
+ set |next_control| to the following token@>;
+ add_in(val); goto reswitch;
+ end;
+ identifier: begin q:=id_lookup(normal);
+ if ilk[q]<>numeric then
+ begin next_control:="*"; goto reswitch; {leads to error}
+ end;
+ add_in(equiv[q]-1073741824);
+ end;
+ "+": do_nothing;
+ "-": next_sign:=-next_sign;
+ format, definition, module_name, begin_Pascal, new_module: goto done;
+ ";": err_print('! Omit semicolon in numeric definition');
+@.Omit semicolon in numeric def...@>
+ othercases @<Signal error, flush rest of the definition@>
+ endcases;
+ end;
+done:
+
+@ @<Signal error, flush rest...@>=
+begin err_print('! Improper numeric definition will be flushed');
+@.Improper numeric definition...@>
+repeat next_control:=skip_ahead
+until end_of_definition(next_control);
+if next_control=module_name then
+ begin {we want to scan the module name too}
+ loc:=loc-2; next_control:=get_next;
+ end;
+accumulator:=0; goto done;
+end
+
+@ @<Set |val| to value of decimal...@>=
+val:=0;
+repeat val:=10*val+next_control-"0"; next_control:=get_next;
+until (next_control>"9")or(next_control<"0")
+
+@ @<Set |val| to value of octal...@>=
+val:=0; next_control:="0";
+repeat val:=8*val+next_control-"0"; next_control:=get_next;
+until (next_control>"7")or(next_control<"0")
+
+@ @<Set |val| to value of hex...@>=
+val:=0; next_control:="0";
+repeat if next_control>="A" then next_control:=next_control+"0"+10-"A";
+val:=16*val+next_control-"0"; next_control:=get_next;
+until (next_control>"F")or(next_control<"0")or@|
+ ((next_control>"9")and(next_control<"A"))
+
+@* Scanning a macro definition.
+The rules for generating the replacement texts corresponding to simple
+macros, parametric macros, and \PASCAL\ texts of a module are almost
+identical, so a single procedure is used for all three cases. The
+differences are that
+
+\yskip\item{a)} The sign |#| denotes a parameter only when it appears
+outside of strings in a parametric macro; otherwise it stands for the
+ASCII character |#|. (This is not used in standard \PASCAL, but some
+\PASCAL s allow, for example, `\.{/\#}' after a certain kind of file name.)
+
+\item{b)}Module names are not allowed in simple macros or parametric macros;
+in fact, the appearance of a module name terminates such macros and denotes
+the name of the current module.
+
+\item{c)}The symbols \.{@@d} and \.{@@f} and \.{@@p} are not allowed after
+module names, while they terminate macro definitions.
+
+@ Therefore there is a procedure |scan_repl| whose parameter |t| specifies
+either |simple| or |parametric| or |module_name|. After |scan_repl| has
+acted, |cur_repl_text| will point to the replacement text just generated, and
+|next_control| will contain the control code that terminated the activity.
+
+@<Globals...@>=
+@!cur_repl_text:text_pointer; {replacement text formed by |scan_repl|}
+
+@ @p procedure scan_repl(@!t:eight_bits); {creates a replacement text}
+label continue, done, found, reswitch;
+var a:sixteen_bits; {the current token}
+@!b:ASCII_code; {a character from the buffer}
+@!bal:eight_bits; {left parentheses minus right parentheses}
+begin bal:=0;
+loop@+ begin continue: a:=get_next;
+ case a of
+ "(": incr(bal);
+ ")": if bal=0 then err_print('! Extra )')
+@.Extra )@>
+ else decr(bal);
+ "'": @<Copy a string from the buffer to |tok_mem|@>;
+ "#": if t=parametric then a:=param;
+ @t\4@>@<In cases that |a| is a non-ASCII token (|identifier|,
+ |module_name|, etc.), either process it and change |a| to a byte
+ that should be stored, or |goto continue| if |a| should be ignored,
+ or |goto done| if |a| signals the end of this replacement text@>@;
+ othercases do_nothing
+ endcases;@/
+ app_repl(a); {store |a| in |tok_mem|}
+ end;
+done: next_control:=a;
+@<Make sure the parentheses balance@>;
+if text_ptr>max_texts-zz then overflow('text');
+cur_repl_text:=text_ptr; tok_start[text_ptr+zz]:=tok_ptr[z];
+incr(text_ptr);
+if z=zz-1 then z:=0@+else incr(z);
+end;
+
+@ @<Make sure the parentheses balance@>=
+if bal>0 then
+ begin if bal=1 then err_print('! Missing )')
+ else err_print('! Missing ',bal:1,' )''s');
+@.Missing n )@>
+ while bal>0 do
+ begin app_repl(")"); decr(bal);
+ end;
+ end
+
+@ @<In cases that |a| is...@>=
+identifier: begin a:=id_lookup(normal); app_repl((a div @'400)+@'200);
+ a:=a mod @'400;
+ end;
+module_name: if t<>module_name then goto done
+ else begin app_repl((cur_module div @'400)+@'250);
+ a:=cur_module mod @'400;
+ end;
+verbatim: @<Copy verbatim string from the buffer to |tok_mem|@>;
+definition, format, begin_Pascal: if t<>module_name then goto done
+ else begin err_print('! @@',xchr[buffer[loc-1]],
+@.\AT!p is ignored in Pascal text@>
+@.\AT!d is ignored in Pascal text@>
+@.\AT!f is ignored in Pascal text@>
+ ' is ignored in Pascal text'); goto continue;
+ end;
+new_module: goto done;
+
+@ @<Copy a string...@>=
+begin b:="'";
+loop@+ begin app_repl(b);
+ if b="@@" then
+ if buffer[loc]="@@" then incr(loc) {store only one \.{@@}}
+ else err_print('! You should double @@ signs in strings');
+@.You should double \AT! signs@>
+ if loc=limit then
+ begin err_print('! String didn''t end');
+@.String didn't end@>
+ buffer[loc]:="'"; buffer[loc+1]:=0;
+ end;
+ b:=buffer[loc]; incr(loc);
+ if b="'" then
+ begin if buffer[loc]<>"'" then goto found
+ else begin incr(loc); app_repl("'");
+ end;
+ end;
+ end;
+found: end {now |a| holds the final |"'"| that will be stored}
+
+@ @<Copy verbatim string...@>=
+begin app_repl(verbatim);
+buffer[limit+1]:="@@";
+reswitch: if buffer[loc]="@@" then
+ begin if loc<limit then if buffer[loc+1]="@@" then
+ begin app_repl("@@");
+ loc:=loc+2;
+ goto reswitch;
+ end;
+ end
+else begin app_repl(buffer[loc]);
+ incr(loc);
+ goto reswitch;
+ end;
+if loc>=limit then err_print('! Verbatim string didn''t end')
+@.Verbatim string didn't end@>
+else if buffer[loc+1]<>">" then
+ err_print('! You should double @@ signs in verbatim strings');
+@.You should double \AT! signs@>
+loc:=loc+2;
+end {another |verbatim| byte will be stored, since |a=verbatim|}
+
+@ The following procedure is used to define a simple or parametric macro,
+just after the `\.{==}' of its definition has been scanned.
+
+@p procedure define_macro(@!t:eight_bits);
+var p:name_pointer; {the identifier being defined}
+begin p:=id_lookup(t); scan_repl(t);@/
+equiv[p]:=cur_repl_text; text_link[cur_repl_text]:=0;
+end;
+
+@* Scanning a module.
+The |scan_module| procedure starts when `\.{@@\ }' or `\.{@@*}' has been
+sensed in the input, and it proceeds until the end of that module. It
+uses |module_count| to keep track of the current module number; with luck,
+\.{WEAVE} and \.{TANGLE} will both assign the same numbers to modules.
+
+@<Globals...@>=
+@!module_count:0..@'27777; {the current module number}
+
+@ The top level of |scan_module| is trivial.
+@p procedure scan_module;
+label continue, done, exit;
+var p:name_pointer; {module name for the current module}
+begin incr(module_count);
+@<Scan the \(definition part of the current module@>;
+@<Scan the \PASCAL\ part of the current module@>;
+exit: end;
+
+@ @<Scan the \(definition part...@>=
+next_control:=0;
+loop@+ begin continue: while next_control<=format do
+ begin next_control:=skip_ahead;
+ if next_control=module_name then
+ begin {we want to scan the module name too}
+ loc:=loc-2; next_control:=get_next;
+ end;
+ end;
+ if next_control<>definition then goto done;
+ next_control:=get_next; {get identifier name}
+ if next_control<>identifier then
+ begin err_print('! Definition flushed, must start with ',
+@.Definition flushed...@>
+ 'identifier of length > 1'); goto continue;
+ end;
+ next_control:=get_next; {get token after the identifier}
+ if next_control="=" then
+ begin scan_numeric(id_lookup(numeric)); goto continue;
+ end
+ else if next_control=equivalence_sign then
+ begin define_macro(simple); goto continue;
+ end
+ else @<If the next text is `|(#)==|', call |define_macro|
+ and |goto continue|@>;
+ err_print('! Definition flushed since it starts badly');
+@.Definition flushed...@>
+ end;
+done:
+
+@ @<If the next text is `|(#)==|'...@>=
+if next_control="(" then
+ begin next_control:=get_next;
+ if next_control="#" then
+ begin next_control:=get_next;
+ if next_control=")" then
+ begin next_control:=get_next;
+ if next_control="=" then
+ begin err_print('! Use == for macros');
+@.Use == for macros@>
+ next_control:=equivalence_sign;
+ end;
+ if next_control=equivalence_sign then
+ begin define_macro(parametric); goto continue;
+ end;
+ end;
+ end;
+ end;
+
+@ @<Scan the \PASCAL...@>=
+case next_control of
+begin_Pascal:p:=0;
+module_name: begin p:=cur_module;
+ @<Check that |=| or |==| follows this module name, otherwise |return|@>;
+ end;
+othercases return
+endcases;@/
+@<Insert the module number into |tok_mem|@>;
+scan_repl(module_name); {now |cur_repl_text| points to the replacement text}
+@<Update the data structure so that the replacement text is accessible@>;
+
+@ @<Check that |=|...@>=
+repeat next_control:=get_next;
+until next_control<>"+"; {allow optional `\.{+=}'}
+if (next_control<>"=")and(next_control<>equivalence_sign) then
+ begin err_print('! Pascal text flushed, = sign is missing');
+@.Pascal text flushed...@>
+ repeat next_control:=skip_ahead;
+ until next_control=new_module;
+ return;
+ end
+
+@ @<Insert the module number...@>=
+store_two_bytes(@'150000+module_count); {|@'150000=@'320*@'400|}
+
+@ @<Update the data...@>=
+if p=0 then {unnamed module}
+ begin text_link[last_unnamed]:=cur_repl_text; last_unnamed:=cur_repl_text;
+ end
+else if equiv[p]=0 then equiv[p]:=cur_repl_text {first module of this name}
+else begin p:=equiv[p];
+ while text_link[p]<module_flag do p:=text_link[p]; {find end of list}
+ text_link[p]:=cur_repl_text;
+ end;
+text_link[cur_repl_text]:=module_flag;
+ {mark this replacement text as a nonmacro}
+
+@* Debugging.
+The \PASCAL\ debugger with which \.{TANGLE} was developed allows breakpoints
+to be set, and variables can be read and changed, but procedures cannot be
+executed. Therefore a `|debug_help|' procedure has been inserted in the main
+loops of each phase of the program; when |ddt| and |dd| are set to appropriate
+values, symbolic printouts of various tables will appear.
+
+The idea is to set a breakpoint inside the |debug_help| routine, at the
+place of `\ignorespaces|breakpoint:|\unskip' below. Then when
+|debug_help| is to be activated, set |trouble_shooting| equal to |true|.
+The |debug_help| routine will prompt you for values of |ddt| and |dd|,
+discontinuing this when |ddt<=0|; thus you type $2n+1$ integers, ending
+with zero or a negative number. Then control either passes to the
+breakpoint, allowing you to look at and/or change variables (if you typed
+zero), or to exit the routine (if you typed a negative value).
+
+Another global variable, |debug_cycle|, can be used to skip silently
+past calls on |debug_help|. If you set |debug_cycle>1|, the program stops
+only every |debug_cycle| times |debug_help| is called; however,
+any error stop will set |debug_cycle| to zero.
+
+@<Globals...@>=
+@!debug@!trouble_shooting:boolean; {is |debug_help| wanted?}
+@!ddt:integer; {operation code for the |debug_help| routine}
+@!dd:integer; {operand in procedures performed by |debug_help|}
+@!debug_cycle:integer; {threshold for |debug_help| stopping}
+@!debug_skipped:integer; {we have skipped this many |debug_help| calls}
+@!term_in:text_file; {the user's terminal as an input file}
+gubed
+
+@ The debugging routine needs to read from the user's terminal.
+@^system dependencies@>
+@<Set init...@>=
+@!debug trouble_shooting:=true; debug_cycle:=1; debug_skipped:=0;@/
+trouble_shooting:=false; debug_cycle:=99999; {use these when it almost works}
+reset(term_in,'TTY:','/I'); {open |term_in| as the terminal, don't do a |get|}
+gubed
+
+@ @d breakpoint=888 {place where a breakpoint is desirable}
+@^system dependencies@>
+
+@p @!debug procedure debug_help; {routine to display various things}
+label breakpoint,exit;
+var k:integer; {index into various arrays}
+begin incr(debug_skipped);
+if debug_skipped<debug_cycle then return;
+debug_skipped:=0;
+loop@+ begin write(term_out,'#'); update_terminal; {prompt}
+ read(term_in,ddt); {read a list of integers}
+ if ddt<0 then return
+ else if ddt=0 then
+ begin goto breakpoint;@\ {go to every label at least once}
+ breakpoint: ddt:=0;@\
+ end
+ else begin read(term_in,dd);
+ case ddt of
+ 1: print_id(dd);
+ 2: print_repl(dd);
+ 3: for k:=1 to dd do print(xchr[buffer[k]]);
+ 4: for k:=1 to dd do print(xchr[mod_text[k]]);
+ 5: for k:=1 to out_ptr do print(xchr[out_buf[k]]);
+ 6: for k:=1 to dd do print(xchr[out_contrib[k]]);
+ othercases print('?')
+ endcases;
+ end;
+ end;
+exit:end;
+gubed
+
+@* The main program.
+We have defined plenty of procedures, and it is time to put the last
+pieces of the puzzle in place. Here is where \.{TANGLE} starts, and where
+it ends.
+@^system dependencies@>
+
+@p begin initialize;
+@<Initialize the input system@>;
+print_ln(banner); {print a ``banner line''}
+@<Phase I: Read all the user's text and compress it into |tok_mem|@>;
+stat for ii:=0 to zz-1 do max_tok_ptr[ii]:=tok_ptr[ii];@+tats@;@/
+@<Phase II:...@>;
+end_of_TANGLE:
+if string_ptr>number_chars then @<Finish off the string pool file@>;
+stat @<Print statistics about memory usage@>;@+tats@;@/
+@t\4\4@>{here files should be closed if the operating system requires it}
+@<Print the job |history|@>;
+end.
+
+@ @<Phase I:...@>=
+phase_one:=true;
+module_count:=0;
+repeat next_control:=skip_ahead;
+until next_control=new_module;
+while not input_has_ended do scan_module;
+@<Check that all changes have been read@>;
+phase_one:=false;
+
+@ @<Finish off the string pool file@>=
+begin print_nl(string_ptr-number_chars:1,
+ ' strings written to string pool file.');
+write(pool,'*');
+for ii:=1 to 9 do
+ begin out_buf[ii]:=pool_check_sum mod 10;
+ pool_check_sum:=pool_check_sum div 10;
+ end;
+for ii:=9 downto 1 do write(pool,xchr["0"+out_buf[ii]]);
+write_ln(pool);
+end
+
+@ @<Glob...@>=
+stat @!wo:0..ww-1; {segment of memory for which statistics are being printed}
+tats
+
+@ @<Print statistics about memory usage@>=
+print_nl('Memory usage statistics:');
+print_nl(name_ptr:1, ' names, ', text_ptr:1, ' replacement texts;');
+print_nl(byte_ptr[0]:1);
+for wo:=1 to ww-1 do print('+',byte_ptr[wo]:1);
+if phase_one then
+ for ii:=0 to zz-1 do max_tok_ptr[ii]:=tok_ptr[ii];
+print(' bytes, ', max_tok_ptr[0]:1);
+for ii:=1 to zz-1 do print('+',max_tok_ptr[ii]:1);
+print(' tokens.');
+
+@ Some implementations may wish to pass the |history| value to the
+operating system so that it can be used to govern whether or not other
+programs are started. Here we simply report the history to the user.
+@^system dependencies@>
+
+@<Print the job |history|@>=
+case history of
+spotless: print_nl('(No errors were found.)');
+harmless_message: print_nl('(Did you see the warning message above?)');
+error_message: print_nl('(Pardon me, but I think I spotted something wrong.)');
+fatal_message: print_nl('(That was a fatal error, my friend.)');
+end {there are no other cases}
+
+@* System-dependent changes.
+This module should be replaced, if necessary, by changes to the program
+that are necessary to make \.{TANGLE} work at a particular installation.
+It is usually best to design your change file so that all changes to
+previous modules preserve the module numbering; then everybody's version
+will be consistent with the printed program. More extensive changes,
+which introduce new modules, can be inserted here; then only the index
+itself will get a new module number.
+@^system dependencies@>
+
+@* Index.
+Here is a cross-reference table for the \.{TANGLE} processor.
+All modules in which an identifier is
+used are listed with that identifier, except that reserved words are
+indexed only when they appear in format definitions, and the appearances
+of identifiers in module names are not indexed. Underlined entries
+correspond to where the identifier was declared. Error messages and
+a few other things like ``ASCII code'' are indexed here too.
diff --git a/Build/source/texk/web2c/luatexdir/luatex-api.h b/Build/source/texk/web2c/luatexdir/luatex-api.h
new file mode 100644
index 00000000000..3585e01dea7
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luatex-api.h
@@ -0,0 +1,104 @@
+/* $Id */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <../lua51/lua.h>
+#include <../lua51/lauxlib.h>
+#include <../lua51/lualib.h>
+
+
+typedef struct LoadS {
+ const char *s;
+ size_t size;
+} LoadS;
+
+extern lua_State *Luas[];
+
+extern void make_table (lua_State *L, char *tab, char *getfunc, char*setfunc);
+
+extern int luac_main (int argc, char* argv[]);
+
+extern int luaopen_tex (lua_State *L);
+
+extern int luaopen_pdf (lua_State *L);
+
+#define LUA_TEXFILEHANDLE "TEXFILE*"
+
+extern int luaopen_texio (lua_State *L);
+
+extern int luaopen_lang (lua_State *L);
+
+extern void luatex_load_init (int s, LoadS *ls);
+
+extern lua_State *luatex_error (lua_State *L, int fatal);
+
+extern int luaopen_unicode (lua_State *L);
+extern int luaopen_zip (lua_State *L);
+extern int luaopen_lfs (lua_State *L);
+extern int luaopen_lpeg (lua_State *L);
+extern int luaopen_md5 (lua_State *L);
+extern int luaopen_zlib (lua_State *L);
+extern int luaopen_gzip (lua_State *L);
+extern int luaopen_ff (lua_State *L);
+
+extern int luaopen_img (lua_State *L);
+extern int luaopen_mp (lua_State *L);
+
+extern void open_oslibext (lua_State *L, int safer_option);
+
+extern void initfilecallbackids (int max);
+extern void setinputfilecallbackid (int n, int i) ;
+extern void setreadfilecallbackid (int n, int i) ;
+extern int getinputfilecallbackid (int n);
+extern int getreadfilecallbackid (int n);
+
+extern void lua_initialize (int ac, char **av);
+
+extern int luaopen_kpse (lua_State *L);
+
+extern int luaopen_callback (lua_State *L);
+
+extern int luaopen_lua (lua_State *L, int n, char *fname);
+
+extern int luaopen_stats (lua_State *L);
+
+extern int luaopen_font (lua_State *L);
+extern int font_to_lua (lua_State *L, int f) ;
+extern int font_from_lua (lua_State *L, int f) ; /* return is boolean */
+
+extern int luaopen_token (lua_State *L);
+extern char *tokenlist_to_cstring (int p , int inhibit_par, int *siz);
+extern void tokenlist_to_lua(lua_State *L, int p);
+extern void tokenlist_to_luastring(lua_State *L, int p) ;
+extern int tokenlist_from_lua(lua_State *L);
+
+extern void lua_nodelib_push (lua_State *L) ;
+extern int luaopen_node (lua_State *L);
+extern void nodelist_to_lua (lua_State *L, int n) ;
+extern int nodelist_from_lua (lua_State *L);
+
+extern int dimen_to_number (lua_State *L, char *s);
+
+extern void dump_luac_registers (void);
+
+extern void undump_luac_registers (void);
+
+
+extern void unhide_lua_table(lua_State *lua, char *name, int r);
+extern int hide_lua_table (lua_State *lua, char *name);
+
+extern void unhide_lua_value(lua_State *lua, char *name, char *item, int r);
+extern int hide_lua_value (lua_State *lua, char *name, char *item);
+
+typedef struct command_item_ {
+ char *cmd_name;
+ int command_offset;
+ char **commands;
+} command_item;
+
+extern command_item command_names[];
+extern int callback_callbacks_id;
+
+void luainterpreter (int n) ;
+
diff --git a/Build/source/texk/web2c/luatexdir/luatex.ch b/Build/source/texk/web2c/luatexdir/luatex.ch
new file mode 100644
index 00000000000..dd1c17e44af
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luatex.ch
@@ -0,0 +1,2623 @@
+@x
+ \def\?##1]{\hbox to 1in{\hfil##1.\ }}
+ }
+@y
+ \def\?##1]{\hbox{Changes to \hbox to 1em{\hfil##1}.\ }}
+ }
+\let\maybe=\iftrue
+@z
+
+@x
+@d banner==luaTeX_banner
+@y
+@d luaTeXk_banner=='This is luaTeXk, Version ',luatex_version_string
+@#
+@d banner==luaTeX_banner
+@d banner_k==luaTeXk_banner
+@z
+
+@x
+Actually the heading shown here is not quite normal: The |program| line
+does not mention any |output| file, because \ph\ would ask the \TeX\ user
+to specify a file name if |output| were specified here.
+@^system dependencies@>
+@y
+@z
+
+@x
+program TEX; {all file names are defined dynamically}
+label @<Labels in the outer block@>@/
+@y
+program TEX; {all file names are defined dynamically}
+@z
+
+@x
+@ Three labels must be declared in the main program, so we give them
+symbolic names.
+
+@d start_of_TEX=1 {go here when \TeX's variables are initialized}
+@d end_of_TEX=9998 {go here to close files and terminate gracefully}
+@d final_end=9999 {this label marks the ending of the program}
+
+@<Labels in the out...@>=
+start_of_TEX@t\hskip-2pt@>, end_of_TEX@t\hskip-2pt@>,@,final_end;
+ {key control points}
+@y
+@ For Web2c, labels are not declared in the main program, but
+we still have to declare the symbolic names.
+
+@d start_of_TEX=1 {go here when \TeX's variables are initialized}
+@d final_end=9999 {this label marks the ending of the program}
+@z
+
+@x
+@d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging}
+@d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging}
+@y
+@d debug== ifdef('TEXMF_DEBUG')
+@d gubed== endif('TEXMF_DEBUG')
+@z
+
+@x
+@d stat==@{ {change this to `$\\{stat}\equiv\null$' when gathering
+ usage statistics}
+@d tats==@t@>@} {change this to `$\\{tats}\equiv\null$' when gathering
+ usage statistics}
+@y
+@d stat==ifdef('STAT')
+@d tats==endif('STAT')
+@z
+
+@x
+the codewords `$|init|\ldots|tini|$'.
+
+@d init== {change this to `$\\{init}\equiv\.{@@\{}$' in the production version}
+@d tini== {change this to `$\\{tini}\equiv\.{@@\}}$' in the production version}
+@y
+the codewords `$|init|\ldots|tini|$' for declarations and by the codewords
+`$|Init|\ldots|Tini|$' for executable code. This distinction is helpful for
+implementations where a run-time switch differentiates between the two
+versions of the program.
+
+@d init==ifdef('INITEX')
+@d tini==endif('INITEX')
+@d Init==init if ini_version then begin
+@d Tini==end;@+tini
+@f Init==begin
+@f Tini==end
+@z
+
+@x
+@!init @<Initialize table entries (done by \.{INITEX} only)@>@;@+tini
+@y
+@!Init @<Initialize table entries (done by \.{INITEX} only)@>@;@+Tini
+@z
+
+@x
+@<Constants...@>=
+@!buf_size=500; {maximum number of characters simultaneously present in
+ current lines of open files and in control sequences between
+ \.{\\csname} and \.{\\endcsname}; must not exceed |max_halfword|}
+@!error_line=72; {width of context lines on terminal error messages}
+@!half_error_line=42; {width of first lines of contexts in terminal
+ error messages; should be between 30 and |error_line-15|}
+@!max_print_line=79; {width of longest text lines output; should be at least 60}
+@!stack_size=200; {maximum number of simultaneous input sources}
+@!max_in_open=6; {maximum number of input files and error insertions that
+ can be going on simultaneously}
+@!param_size=60; {maximum number of simultaneous macro parameters}
+@!nest_size=40; {maximum number of semantic levels simultaneously active}
+@!max_strings=3000; {maximum number of strings; must not exceed |max_halfword|}
+@!string_vacancies=8000; {the minimum number of characters that should be
+ available for the user's control sequences and font names,
+ after \TeX's own error messages are stored}
+@!pool_size=32000; {maximum number of characters in strings, including all
+ error messages and help texts, and the names of all fonts and
+ control sequences; must exceed |string_vacancies| by the total
+ length of \TeX's own strings, which is currently about 23000}
+@!save_size=600; {space for saving values outside of current group; must be
+ at most |max_halfword|}
+@!dvi_buf_size=800; {size of the output buffer; must be a multiple of 8}
+@!expand_depth=10000; {limits recursive calls of the |expand| procedure}
+@!file_name_size=40; {file names shouldn't be longer than this}
+@!pool_name='TeXformats:TEX.POOL ';
+ {string of length |file_name_size|; tells where the string pool appears}
+@y
+@d file_name_size == max_halfword-1 { has to be big enough to force namelength into integer }
+@d ssup_error_line = 255
+@d ssup_max_strings == 262143
+{Larger values than 65536 cause the arrays consume much more memory.}
+
+@<Constants...@>=
+@!hash_offset=514; {smallest index in hash array, i.e., |hash_base| }
+ {Use |hash_offset=0| for compilers which cannot decrement pointers.}
+@!engine_name='luatex'; {the name of this engine}
+@#
+
+@!inf_main_memory = 2000000;
+@!sup_main_memory = 32000000;
+
+@!inf_max_strings = 100000;
+@!sup_max_strings = ssup_max_strings;
+@!inf_strings_free = 100;
+@!sup_strings_free = sup_max_strings;
+
+@!inf_buf_size = 500;
+@!sup_buf_size = 100000000;
+
+@!inf_nest_size = 40;
+@!sup_nest_size = 4000;
+
+@!inf_max_in_open = 6;
+@!sup_max_in_open = 127;
+
+@!inf_param_size = 60;
+@!sup_param_size = 6000;
+
+@!inf_save_size = 600;
+@!sup_save_size = 80000;
+
+@!inf_stack_size = 200;
+@!sup_stack_size = 30000;
+
+@!inf_dvi_buf_size = 800;
+@!sup_dvi_buf_size = 65536;
+
+@!inf_pool_size = 128000;
+@!sup_pool_size = 40000000;
+@!inf_pool_free = 1000;
+@!sup_pool_free = sup_pool_size;
+@!inf_string_vacancies = 8000;
+@!sup_string_vacancies = sup_pool_size - 23000;
+
+@!sup_hash_extra = sup_max_strings;
+@!inf_hash_extra = 0;
+
+@!sup_ocp_list_size = 1000000;
+@!inf_ocp_list_size = 1000;
+@!sup_ocp_buf_size = 100000000;
+@!inf_ocp_buf_size = 1000;
+@!sup_ocp_stack_size = 1000000;
+@!inf_ocp_stack_size = 1000;
+
+@!inf_expand_depth = 100;
+@!sup_expand_depth = 1000000;
+@z
+
+@x
+@d font_base=0 {smallest internal font number; must not be less
+ than |min_quarterword|}
+@d hash_size=2100 {maximum number of control sequences; it should be at most
+ about |(fix_mem_max-fix_mem_min)/10|}
+@d hash_prime=1777 {a prime number equal to about 85\pct! of |hash_size|}
+@y
+@d font_base=0 {smallest internal font number; must not be less
+ than |min_quarterword|}
+@d hash_size=65536 {maximum number of control sequences; it should be at most
+ about |(mem_max-mem_min)/10|}
+@d hash_prime=55711 {a prime number equal to about 85\pct! of |hash_size|}
+@z
+
+@x
+@d incr(#) == #:=#+1 {increase a variable by unity}
+@d decr(#) == #:=#-1 {decrease a variable by unity}
+@y
+@z
+
+@x
+@d text_char == char {the data type of characters in text files}
+@y
+@d text_char == ASCII_code {the data type of characters in text files}
+@z
+
+@x
+@!nameoffile:packed array[1..file_name_size] of char;@;@/
+ {on some systems this may be a \&{record} variable}
+@y
+@!nameoffile:^packed_ASCII_code;
+@z
+
+@x
+@ The \ph\ compiler with which the present version of \TeX\ was prepared has
+extended the rules of \PASCAL\ in a very convenient way. To open file~|f|,
+we can write
+$$\vbox{\halign{#\hfil\qquad&#\hfil\cr
+|reset(f,@t\\{name}@>,'/O')|&for input;\cr
+|rewrite(f,@t\\{name}@>,'/O')|&for output.\cr}}$$
+The `\\{name}' parameter, which is of type `{\bf packed array
+$[\langle\\{any}\rangle]$ of \\{char}}', stands for the name of
+the external file that is being opened for input or output.
+Blank spaces that might appear in \\{name} are ignored.
+
+The `\.{/O}' parameter tells the operating system not to issue its own
+error messages if something goes wrong. If a file of the specified name
+cannot be found, or if such a file cannot be opened for some other reason
+(e.g., someone may already be trying to write the same file), we will have
+|@!erstat(f)<>0| after an unsuccessful |reset| or |rewrite|. This allows
+\TeX\ to undertake appropriate corrective action.
+@:PASCAL H}{\ph@>
+@^system dependencies@>
+
+\TeX's file-opening procedures return |false| if no file identified by
+|nameoffile| could be opened.
+
+@d reset_OK(#)==erstat(#)=0
+@d rewrite_OK(#)==erstat(#)=0
+
+@p function a_open_in(var f:alpha_file):boolean;
+ {open a text file for input}
+begin reset(f,nameoffile,'/O'); a_open_in:=reset_OK(f);
+end;
+@#
+function a_open_out(var f:alpha_file):boolean;
+ {open a text file for output}
+begin rewrite(f,nameoffile,'/O'); a_open_out:=rewrite_OK(f);
+end;
+@#
+function b_open_in(var f:byte_file):boolean;
+ {open a binary file for input}
+begin reset(f,nameoffile,'/O'); b_open_in:=reset_OK(f);
+end;
+@#
+function b_open_out(var f:byte_file):boolean;
+ {open a binary file for output}
+begin rewrite(f,nameoffile,'/O'); b_open_out:=rewrite_OK(f);
+end;
+@#
+function w_open_in(var f:word_file):boolean;
+ {open a word file for input}
+begin reset(f,nameoffile,'/O'); w_open_in:=reset_OK(f);
+end;
+@#
+function w_open_out(var f:word_file):boolean;
+ {open a word file for output}
+begin rewrite(f,nameoffile,'/O'); w_open_out:=rewrite_OK(f);
+end;
+@y
+@ All of the file opening functions are defined in C.
+@z
+
+@x
+@ Files can be closed with the \ph\ routine `|close(f)|', which
+@^system dependencies@>
+should be used when all input or output with respect to |f| has been completed.
+This makes |f| available to be opened again, if desired; and if |f| was used for
+output, the |close| operation makes the corresponding external file appear
+on the user's area, ready to be read.
+
+These procedures should not generate error messages if a file is
+being closed before it has been successfully opened.
+
+@p procedure a_close(var f:alpha_file); {close a text file}
+begin close(f);
+end;
+@#
+procedure b_close(var f:byte_file); {close a binary file}
+begin close(f);
+end;
+@#
+procedure w_close(var f:word_file); {close a word file}
+begin close(f);
+end;
+@y
+@ And all the file closing routines as well.
+@z
+
+@x
+@!buffer:array[0..buf_size] of packed_ASCII_code; {lines of characters being read}
+@y
+@!buffer:^packed_ASCII_code; {lines of characters being read}
+@z
+
+@x
+@p function input_ln(var f:alpha_file;@!bypass_eoln:boolean):boolean;
+ {inputs the next line or returns |false|}
+var last_nonblank:0..buf_size; {|last| with trailing blanks removed}
+begin if bypass_eoln then if not eof(f) then get(f);
+ {input the first character of the line into |f^|}
+last:=first; {cf.\ Matthew 19\thinspace:\thinspace30}
+if eof(f) then input_ln:=false
+else begin last_nonblank:=first;
+ while not eoln(f) do
+ begin if last>=max_buf_stack then
+ begin max_buf_stack:=last+1;
+ if max_buf_stack=buf_size then
+ @<Report overflow of the input buffer, and abort@>;
+ end;
+ buffer[last]:=f^; get(f); incr(last);
+ if buffer[last-1]<>" " then last_nonblank:=last;
+ end;
+ last:=last_nonblank; input_ln:=true;
+ end;
+end;
+@y
+We define |input_ln| in C, for efficiency. Nevertheless we quote the module
+`Report overflow of the input buffer, and abort' here in order to make
+\.{WEAVE} happy, since part of that module is needed by e-TeX.
+
+@p @{ @<Report overflow of the input buffer, and abort@> @}
+@z
+
+@x
+@<Glob...@>=
+@!term_in:alpha_file; {the terminal as an input file}
+@!term_out:alpha_file; {the terminal as an output file}
+@y
+@d term_in==stdin {the terminal as an input file}
+@d term_out==stdout {the terminal as an output file}
+
+@<Glob...@>=
+@!init
+@!ini_version:boolean; {are we \.{INITEX}?}
+@!dump_option:boolean; {was the dump name option used?}
+@!dump_line:boolean; {was a \.{\%\AM format} line seen?}
+tini@/
+@#
+@!bound_default:integer; {temporary for setup}
+@!bound_name:^char; {temporary for setup}
+@#
+@!error_line:integer; {width of context lines on terminal error messages}
+@!half_error_line:integer; {width of first lines of contexts in terminal
+ error messages; should be between 30 and |error_line-15|}
+@!max_print_line:integer;
+ {width of longest text lines output; should be at least 60}
+@!ocp_list_size:integer;
+@!ocp_buf_size:integer;
+@!ocp_stack_size:integer;
+@!max_strings:integer; {maximum number of strings; must not exceed |max_halfword|}
+@!strings_free:integer; {strings available after format loaded}
+@!string_vacancies:integer; {the minimum number of characters that should be
+ available for the user's control sequences and font names,
+ after \TeX's own error messages are stored}
+@!pool_size:integer; {maximum number of characters in strings, including all
+ error messages and help texts, and the names of all fonts and
+ control sequences; must exceed |string_vacancies| by the total
+ length of \TeX's own strings, which is currently about 23000}
+@!pool_free:integer;{pool space free after format loaded}
+@!font_k:integer; {loop variable for initialization}
+@!buf_size:integer; {maximum number of characters simultaneously present in
+ current lines of open files and in control sequences between
+ \.{\\csname} and \.{\\endcsname}; must not exceed |max_halfword|}
+@!stack_size:integer; {maximum number of simultaneous input sources}
+@!max_in_open:integer; {maximum number of input files and error insertions that
+ can be going on simultaneously}
+@!param_size:integer; {maximum number of simultaneous macro parameters}
+@!nest_size:integer; {maximum number of semantic levels simultaneously active}
+@!save_size:integer; {space for saving values outside of current group; must be
+ at most |max_halfword|}
+@!dvi_buf_size:integer; {size of the output buffer; must be a multiple of 8}
+@!expand_depth:integer; {limits recursive calls of the |expand| procedure}
+@!parsefirstlinep:cinttype; {parse the first line for options}
+@!filelineerrorstylep:cinttype; {format messages as file:line:error}
+@!haltonerrorp:cinttype; {stop at first error}
+@!quoted_filename:boolean; {current filename is quoted}
+{Variables for source specials}
+@!srcspecialsp : boolean;{Whether |src_specials| are enabled at all}
+@!insertsrcspecialauto : boolean;
+@!insertsrcspecialeverypar : boolean;
+@!insertsrcspecialeveryparend : boolean;
+@!insertsrcspecialeverycr : boolean;
+@!insertsrcspecialeverymath : boolean;
+@!insertsrcspecialeveryhbox : boolean;
+@!insertsrcspecialeveryvbox : boolean;
+@!insertsrcspecialeverydisplay : boolean;
+@z
+
+@x
+@ Here is how to open the terminal files
+in \ph. The `\.{/I}' switch suppresses the first |get|.
+@^system dependencies@>
+
+@d t_open_in==reset(term_in,'TTY:','/O/I') {open the terminal for text input}
+@d t_open_out==rewrite(term_out,'TTY:','/O') {open the terminal for text output}
+@y
+@ Here is how to open the terminal files. |t_open_out| does nothing.
+|t_open_in|, on the other hand, does the work of ``rescanning,'' or getting
+any command line arguments the user has provided. It's defined in C.
+
+@d t_open_out == {output already open for text output}
+@z
+
+@x
+these operations can be specified in \ph:
+@^system dependencies@>
+
+@d update_terminal == break(term_out) {empty the terminal output buffer}
+@d clear_terminal == break_in(term_in,true) {clear the terminal input buffer}
+@y
+these operations can be specified with {\mc UNIX}. |update_terminal|
+does an |fflush|. |clear_terminal| is redefined
+to do nothing, since the user should control the terminal.
+@^system dependencies@>
+
+@d update_terminal == fflush (term_out)
+@d clear_terminal == do_nothing
+@z
+
+@x
+@<Report overflow of the input buffer, and abort@>=
+if format_ident=0 then
+ begin writeln(term_out,'Buffer size exceeded!'); goto final_end;
+@.Buffer size exceeded@>
+ end
+else
+ check_buffer_overflow(buf_size+10) { need a little bit more}
+@y
+@<Report overflow of the input buffer, and abort@>=
+ check_buffer_overflow(buf_size+10) { need a little bit more}
+@z
+
+@x
+@ The following program does the required initialization
+without retrieving a possible command line.
+It should be clear how to modify this routine to deal with command lines,
+if the system permits them.
+@^system dependencies@>
+
+@p function init_terminal:boolean; {gets the terminal input started}
+label exit;
+begin t_open_in;
+@y
+@ The following program does the required initialization.
+Iff anything has been specified on the command line, then |t_open_in|
+will return with |last > first|.
+@^system dependencies@>
+
+@p function init_terminal:boolean; {gets the terminal input started}
+label exit;
+begin t_open_in;
+if last > first then
+ begin loc := first;
+ while (loc < last) and (buffer[loc]=' ') do incr(loc);
+ if loc < last then
+ begin init_terminal := true; goto exit;
+ end;
+ end;
+@z
+
+@x
+ write(term_out,'! End of file on the terminal... why?');
+@y
+ writeln(term_out,'! End of file on the terminal... why?');
+@z
+
+@x
+@!str_pool:packed array[pool_pointer] of packed_ASCII_code; {the characters}
+@!str_start : array[str_number] of pool_pointer; {the starting pointers}
+@y
+@!str_pool: ^packed_ASCII_code; {the characters}
+@!str_start : ^pool_pointer; {the starting pointers}
+@z
+
+@x
+@p @!init function get_strings_started:boolean; {initializes the string pool,
+@y
+@p @t\4@>@<Declare additional routines for string recycling@>@/
+
+@!init function get_strings_started:boolean; {initializes the string pool,
+@z
+
+@x
+would like string @'32 to be the single character @'32 instead of the
+@y
+would like string @'32 to be printed as the single character @'32
+instead of the
+@z
+
+@x
+@!trick_buf:array[0..error_line] of packed_ASCII_code; {circular buffer for
+@y
+@!trick_buf:array[0..ssup_error_line] of packed_ASCII_code; {circular buffer for
+@z
+
+@x
+@d error_stop_mode=3 {stops at every opportunity to interact}
+@y
+@d error_stop_mode=3 {stops at every opportunity to interact}
+@d unspecified_mode=4 {extra value for command-line switch}
+@z
+
+@x
+ print_nl("! "); print(#);
+@y
+ if filelineerrorstylep then print_file_line
+ else print_nl("! ");
+ print(#);
+@z
+
+@x
+@!interaction:batch_mode..error_stop_mode; {current level of interaction}
+@y
+@!interaction:batch_mode..error_stop_mode; {current level of interaction}
+@!interactionoption:batch_mode..unspecified_mode; {set from command line}
+@z
+
+@x
+@ @<Set init...@>=interaction:=error_stop_mode;
+@y
+@ @<Set init...@>=if interactionoption=unspecified_mode then
+ interaction:=error_stop_mode
+else
+ interaction:=interactionoption;
+@z
+
+@x
+@<Error hand...@>=
+procedure jump_out;
+begin goto end_of_TEX;
+end;
+@y
+@d do_final_end==begin
+ update_terminal;
+ ready_already:=0;
+ if (history <> spotless) and (history <> warning_issued) then
+ uexit(1)
+ else
+ uexit(0);
+ end
+
+@<Error hand...@>=
+procedure jump_out;
+begin
+close_files_and_terminate;
+do_final_end;
+end;
+@z
+
+@x
+show_context;
+@y
+show_context;
+if (haltonerrorp) then begin
+ history:=fatal_error_stop; jump_out;
+end;
+@z
+
+@x
+line ready to be edited. But such an extension requires some system
+wizardry, so the present implementation simply types out the name of the
+file that should be
+edited and the relevant line number.
+@^system dependencies@>
+
+There is a secret `\.D' option available when the debugging routines haven't
+been commented~out.
+@^debugging@>
+@y
+line ready to be edited.
+We do this by calling the external procedure |calledit| with a pointer to
+the filename, its length, and the line number.
+However, here we just set up the variables that will be used as arguments,
+since we don't want to do the switch-to-editor until after TeX has closed
+its files.
+@^system dependencies@>
+
+There is a secret `\.D' option available when the debugging routines haven't
+been commented~out.
+@^debugging@>
+@d edit_file==input_stack[base_ptr]
+@z
+
+@x
+"E": if base_ptr>0 then
+ begin print_nl("You want to edit file ");
+@.You want to edit file x@>
+ slow_print(input_stack[base_ptr].name_field);
+ print(" at line "); print_int(line);
+ interaction:=scroll_mode; jump_out;
+@y
+"E": if base_ptr>0 then
+ begin edit_name_start:=str_start_macro(edit_file.name_field);
+ edit_name_length:=str_start_macro(edit_file.name_field+1) -
+ str_start_macro(edit_file.name_field);
+ edit_line:=line;
+ jump_out;
+@z
+
+@x
+|remainder|, holds the remainder after a division.
+
+@<Glob...@>=
+@y
+|remainder|, holds the remainder after a division.
+
+@d remainder==tex_remainder
+
+@<Glob...@>=
+@z
+
+@x
+@!glue_ratio=real; {one-word representation of a glue expansion factor}
+@y
+@z
+
+@x
+macros are simplified in the obvious way when |min_quarterword=0|.
+@^inner loop@>@^system dependencies@>
+
+@d qi(#)==#+min_quarterword
+ {to put an |eight_bits| item into a quarterword}
+@d qo(#)==#-min_quarterword
+ {to take an |eight_bits| item out of a quarterword}
+@d hi(#)==#+min_halfword
+ {to put a sixteen-bit item into a halfword}
+@d ho(#)==#-min_halfword
+ {to take a sixteen-bit item from a halfword}
+@y
+macros are simplified in the obvious way when |min_quarterword=0|.
+So they have been simplified here in the obvious way.
+@^inner loop@>@^system dependencies@>
+
+@d qi(#)==# {to put an |eight_bits| item into a quarterword}
+@d qo(#)==# {to take an |eight_bits| item from a quarterword}
+@d hi(#)==# {to put a sixteen-bit item into a halfword}
+@d ho(#)==# {to take a sixteen-bit item from a halfword}
+@z
+
+@x
+@!quarterword = min_quarterword..max_quarterword; {1/4 of a word}
+@!halfword=min_halfword..max_halfword; {1/2 of a word}
+@!two_choices = 1..2; {used when there are two variants in a record}
+@!four_choices = 1..4; {used when there are four variants in a record}
+@!two_halves = packed record@;@/
+ @!rh:halfword;
+ case two_choices of
+ 1: (@!lh:halfword);
+ 2: (@!b0:quarterword; @!b1:quarterword);
+ end;
+@!four_quarters = packed record@;@/
+ @!b0:quarterword;
+ @!b1:quarterword;
+ @!b2:quarterword;
+ @!b3:quarterword;
+ end;
+@!memory_word = record@;@/
+ case four_choices of
+ 1: (@!int:integer);
+ 2: (@!gr:glue_ratio);
+ 3: (@!hh:two_halves);
+ 4: (@!qqqq:four_quarters);
+ end;
+@y
+@!quarterword = min_quarterword..max_quarterword;
+@!halfword = min_halfword..max_halfword;
+@!two_choices = 1..2; {used when there are two variants in a record}
+@!four_choices = 1..4; {used when there are four variants in a record}
+@=#include "texmfmem.h";@>
+@z
+
+@x
+ if abs(vmem(p+glue_offset).int)<@'4000000 then print("?.?")
+ else if abs(g)>float_constant(20000) then
+@y
+ { The Unix |pc| folks removed this restriction with a remark that
+ invalid bit patterns were vanishingly improbable, so we follow
+ their example without really understanding it.
+ |if abs(vmem(p+glue_offset).int)<@'4000000 then print('?.?')|
+ |else| }
+ if fabs(g)>float_constant(20000) then
+@z
+
+@x
+begin if m>0 then
+ case m div (max_command+1) of
+ 0:print("vertical");
+ 1:print("horizontal");
+ 2:print("display math");
+ end
+else if m=0 then print("no")
+else case (-m) div (max_command+1) of
+ 0:print("internal vertical");
+ 1:print("restricted horizontal");
+ 2:print("math");
+ end;
+print(" mode");
+end;
+@y
+begin if m>0 then
+ case m div (max_command+1) of
+ 0:print("vertical mode");
+ 1:print("horizontal mode");
+ 2:print("display math mode");
+ end
+else if m=0 then print("no mode")
+else case (-m) div (max_command+1) of
+ 0:print("internal vertical mode");
+ 1:print("restricted horizontal mode");
+ 2:print("math mode");
+ end;
+end;
+
+procedure print_in_mode(@!m:integer); {prints the mode represented by |m|}
+begin if m>0 then
+ case m div (max_command+1) of
+ 0:print("' in vertical mode");
+ 1:print("' in horizontal mode");
+ 2:print("' in display math mode");
+ end
+else if m=0 then print("' in no mode")
+else case (-m) div (max_command+1) of
+ 0:print("' in internal vertical mode");
+ 1:print("' in restricted horizontal mode");
+ 2:print("' in math mode");
+ end;
+end;
+@z
+
+@x
+@!nest:array[0..nest_size] of list_state_record;
+@y
+@!nest:^list_state_record;
+@z
+
+@x
+local_par:=null; local_par_bool:=false;
+@<Start a new current page@>;
+@y
+local_par:=null; local_par_bool:=false;
+@/{The following piece of code is a copy of module 991:}
+page_contents:=empty; page_tail:=page_head; {|link(page_head):=null;|}@/
+last_glue:=max_halfword; last_penalty:=0; last_kern:=0;
+page_depth:=0; page_max_depth:=0;
+@z
+
+@x
+ print_int(nest[p].pg_field); print(" line");
+ if nest[p].pg_field<>1 then print_char("s");
+@y
+ print_int(nest[p].pg_field);
+ if nest[p].pg_field<>1 then print(" lines")
+ else print(" line");
+@z
+
+@x
+@d frozen_null_font=frozen_control_sequence+12
+ {permanent `\.{\\nullfont}'}
+@y
+@d frozen_special=frozen_control_sequence+12
+ {permanent `\.{\\special}'}
+@d frozen_null_font=frozen_control_sequence+13
+ {permanent `\.{\\nullfont}'}
+@z
+
+@x
+for k:=active_base to undefined_control_sequence-1 do
+ eqtb[k]:=eqtb[undefined_control_sequence];
+@y
+for k:=active_base to eqtb_top do
+ eqtb[k]:=eqtb[undefined_control_sequence];
+@z
+
+@x
+@ The following procedure, which is called just before \TeX\ initializes its
+input and output, establishes the initial values of the date and time.
+@^system dependencies@>
+Since standard \PASCAL\ cannot provide such information, something special
+is needed. The program here simply specifies July 4, 1776, at noon; but
+users probably want a better approximation to the truth.
+
+@p procedure fix_date_and_time;
+begin time:=12*60; {minutes since midnight}
+day:=4; {fourth day of the month}
+month:=7; {seventh month of the year}
+year:=1776; {Anno Domini}
+end;
+@y
+@ The following procedure, which is called just before \TeX\ initializes its
+input and output, establishes the initial values of the date and time.
+It calls a macro-defined |date_and_time| routine. |date_and_time|
+in turn is a C macro, which calls |get_date_and_time|, passing
+it the addresses of the day, month, etc., so they can be set by the
+routine. |get_date_and_time| also sets up interrupt catching if that
+is conditionally compiled in the C code.
+@^system dependencies@>
+
+@d fix_date_and_time==dateandtime(time,day,month,year)
+@z
+
+@x
+else if n<glue_base then @<Show equivalent |n|, in region 1 or 2@>
+@y
+else if (n<glue_base) or ((n>eqtb_size)and(n<=eqtb_top)) then
+ @<Show equivalent |n|, in region 1 or 2@>
+@z
+
+@x
+@!eqtb:array[active_base..eqtb_size] of memory_word;
+@y
+@!zeqtb:^memory_word;
+@z
+
+@x
+@!hash: array[hash_base..undefined_control_sequence-1] of two_halves;
+ {the hash table}
+@!hash_used:pointer; {allocation pointer for |hash|}
+@y
+@!hash: ^two_halves; {the hash table}
+@!yhash: ^two_halves; {auxiliary pointer for freeing hash}
+@!hash_used:pointer; {allocation pointer for |hash|}
+@!hash_extra:pointer; {|hash_extra=hash| above |eqtb_size|}
+@!hash_top:pointer; {maximum of the hash array}
+@!eqtb_top:pointer; {maximum of the |eqtb|}
+@!hash_high:pointer; {pointer to next high hash location}
+@z
+
+@x
+next(hash_base):=0; text(hash_base):=0;
+for k:=hash_base+1 to undefined_control_sequence-1 do hash[k]:=hash[hash_base];
+@y
+@z
+
+@x
+hash_used:=frozen_control_sequence; {nothing is used}
+@y
+hash_used:=frozen_control_sequence; {nothing is used}
+hash_high:=0;
+@z
+
+@x
+@ @<Insert a new control...@>=
+begin if text(p)>0 then
+ begin repeat if hash_is_full then overflow("hash size",hash_size);
+@:TeX capacity exceeded hash size}{\quad hash size@>
+ decr(hash_used);
+ until text(hash_used)=0; {search for an empty location in |hash|}
+ next(p):=hash_used; p:=hash_used;
+ end;
+@y
+@ @<Insert a new control...@>=
+begin if text(p)>0 then
+ begin if hash_high<hash_extra then
+ begin incr(hash_high);
+ next(p):=hash_high+eqtb_size; p:=hash_high+eqtb_size;
+ end
+ else begin
+ repeat if hash_is_full then overflow("hash size",hash_size+hash_extra);
+@:TeX capacity exceeded hash size}{\quad hash size@>
+ decr(hash_used);
+ until text(hash_used)=0; {search for an empty location in |hash|}
+ next(p):=hash_used; p:=hash_used;
+ end;
+ end;
+@z
+
+@x
+else if p>=undefined_control_sequence then print_esc("IMPOSSIBLE.")
+@y
+else if ((p>=undefined_control_sequence)and(p<=eqtb_size))or(p>eqtb_top) then
+ print_esc("IMPOSSIBLE.")
+@z
+
+@x
+else if (text(p)<0)or(text(p)>=str_ptr) then print_esc("NONEXISTENT.")
+@y
+else if (text(p)>=str_ptr) then print_esc("NONEXISTENT.")
+@z
+
+@x
+@!save_stack : array[0..save_size] of memory_word;
+@y
+@!save_stack : ^memory_word;
+@z
+
+@x
+if p<int_base then
+@y
+if (p<int_base)or(p>eqtb_size) then
+@z
+
+@x
+if cs_token_flag+undefined_control_sequence>max_halfword then bad:=21;
+@y
+if cs_token_flag+eqtb_size+hash_extra>max_halfword then bad:=21;
+if (hash_offset<0)or(hash_offset>hash_base) then bad:=42;
+@z
+
+@x
+@!input_stack : array[0..stack_size] of in_state_record;
+@y
+@!input_stack : ^in_state_record;
+@z
+
+@x
+@!input_file : array[1..max_in_open] of alpha_file;
+@!line : integer; {current line number in the current source file}
+@!line_stack : array[1..max_in_open] of integer;
+@y
+@!input_file : ^alpha_file;
+@!line : integer; {current line number in the current source file}
+@!line_stack : ^integer;
+@!source_filename_stack : ^str_number;
+@!full_source_filename_stack : ^str_number;
+@z
+
+@x
+ begin print_nl("Runaway ");
+@.Runaway...@>
+ case scanner_status of
+ defining: begin print("definition"); p:=def_ref;
+ end;
+ matching: begin print("argument"); p:=temp_token_head;
+ end;
+ aligning: begin print("preamble"); p:=hold_token_head;
+ end;
+ absorbing: begin print("text"); p:=def_ref;
+ end;
+ end; {there are no other cases}
+@y
+ begin
+@.Runaway...@>
+ case scanner_status of
+ defining: begin print_nl("Runaway definition"); p:=def_ref;
+ end;
+ matching: begin print_nl("Runaway argument"); p:=temp_token_head;
+ end;
+ aligning: begin print_nl("Runaway preamble"); p:=hold_token_head;
+ end;
+ absorbing: begin print_nl("Runaway text"); p:=def_ref;
+ end;
+ end; {there are no other cases}
+@z
+
+@x
+@!param_stack:array [0..param_size] of pointer;
+ {token list pointers for parameters}
+@y
+@!param_stack: ^pointer;
+ {token list pointers for parameters}
+@z
+
+@x
+incr(in_open); push_input; index:=in_open;
+@y
+incr(in_open); push_input; index:=in_open;
+source_filename_stack[index]:=0;full_source_filename_stack[index]:=0;
+@z
+
+@x
+begin input_ptr:=0; max_in_stack:=0;
+@y
+begin input_ptr:=0; max_in_stack:=0;
+source_filename_stack[0]:=0;full_source_filename_stack[0]:=0;
+@z
+
+@x
+if_eof_code: begin scan_four_bit_int; b:=(read_open[cur_val]=closed);
+ end;
+@y
+if_eof_code: begin scan_four_bit_int_or_18;
+ if cur_val=18 then b:=not shellenabledp
+ else b:=(read_open[cur_val]=closed);
+ end;
+@z
+
+@x
+@ The file names we shall deal with for illustrative purposes have the
+following structure: If the name contains `\.>' or `\.:', the file area
+consists of all characters up to and including the final such character;
+otherwise the file area is null. If the remaining file name contains
+`\..', the file extension consists of all such characters from the first
+remaining `\..' to the end, otherwise the file extension is null.
+@y
+@ The file names we shall deal with have the
+following structure: If the name contains `\./' or `\.:'
+(for Amiga only), the file area
+consists of all characters up to and including the final such character;
+otherwise the file area is null. If the remaining file name contains
+`\..', the file extension consists of all such characters from the last
+`\..' to the end, otherwise the file extension is null.
+@z
+
+@x
+@!area_delimiter:pool_pointer; {the most recent `\.>' or `\.:', if any}
+@!ext_delimiter:pool_pointer; {the relevant `\..', if any}
+@y
+@!area_delimiter:pool_pointer; {the most recent `\./', if any}
+@!ext_delimiter:pool_pointer; {the most recent `\..', if any}
+@z
+
+@x
+@d TEX_area=="TeXinputs:"
+@.TeXinputs@>
+@d TEX_font_area=="TeXfonts:"
+@.TeXfonts@>
+@y
+In C, the default paths are specified separately.
+@z
+
+@x
+begin area_delimiter:=0; ext_delimiter:=0;
+@y
+begin area_delimiter:=0; ext_delimiter:=0; quoted_filename:=false;
+@z
+
+@x
+begin if c=" " then more_name:=false
+@y
+begin if (c=" ") and stop_at_space and (not quoted_filename) then
+ more_name:=false
+else if c="""" then begin
+ quoted_filename:=not quoted_filename;
+ more_name:=true;
+ end
+@z
+
+@x
+ if (c=">")or(c=":") then
+@y
+ if ISDIRSEP(c) then
+@z
+
+@x
+ else if (c=".")and(ext_delimiter=0) then ext_delimiter:=cur_length;
+@y
+ else if c="." then ext_delimiter:=cur_length;
+@z
+
+@x
+@ The third.
+@^system dependencies@>
+
+@p procedure end_name;
+@y
+@ The third.
+@^system dependencies@>
+If a string is already in the string pool, the function
+|slow_make_string| does not create a new string but returns this string
+number, thus saving string space. Because of this new property of the
+returned string number it is not possible to apply |flush_string| to
+these strings.
+
+@p procedure end_name;
+var temp_str: str_number; {result of file name cache lookups}
+@!j,@!s,@!t: pool_pointer; {running indices}
+@!must_quote:boolean; {whether we need to quote a string}
+@z
+
+@x
+@:TeX capacity exceeded number of strings}{\quad number of strings@>
+@y
+@:TeX capacity exceeded number of strings}{\quad number of strings@>
+str_room(6); {Room for quotes, if needed.}
+{add quotes if needed}
+if area_delimiter<>0 then begin
+ {maybe quote |cur_area|}
+ must_quote:=false;
+ s:=str_start_macro(str_ptr);
+ t:=str_start_macro(str_ptr)+area_delimiter;
+ j:=s;
+ while (not must_quote) and (j<t) do begin
+ must_quote:=str_pool[j]=" "; incr(j);
+ end;
+ if must_quote then begin
+ for j:=pool_ptr-1 downto t do str_pool[j+2]:=str_pool[j];
+ str_pool[t+1]:="""";
+ for j:=t-1 downto s do str_pool[j+1]:=str_pool[j];
+ str_pool[s]:="""";
+ if ext_delimiter<>0 then ext_delimiter:=ext_delimiter+2;
+ area_delimiter:=area_delimiter+2;
+ pool_ptr:=pool_ptr+2;
+ end;
+ end;
+{maybe quote |cur_name|}
+s:=str_start_macro(str_ptr)+area_delimiter;
+if ext_delimiter=0 then t:=pool_ptr else t:=str_start_macro(str_ptr)+ext_delimiter-1;
+must_quote:=false;
+j:=s;
+while (not must_quote) and (j<t) do begin
+ must_quote:=str_pool[j]=" "; incr(j);
+ end;
+if must_quote then begin
+ for j:=pool_ptr-1 downto t do str_pool[j+2]:=str_pool[j];
+ str_pool[t+1]:="""";
+ for j:=t-1 downto s do str_pool[j+1]:=str_pool[j];
+ str_pool[s]:="""";
+ if ext_delimiter<>0 then ext_delimiter:=ext_delimiter+2;
+ pool_ptr:=pool_ptr+2;
+ end;
+if ext_delimiter<>0 then begin
+ {maybe quote |cur_ext|}
+ s:=str_start_macro(str_ptr)+ext_delimiter-1;
+ t:=pool_ptr;
+ must_quote:=false;
+ j:=s;
+ while (not must_quote) and (j<t) do begin
+ must_quote:=str_pool[j]=" "; incr(j);
+ end;
+ if must_quote then begin
+ str_pool[t+1]:="""";
+ for j:=t-1 downto s do str_pool[j+1]:=str_pool[j];
+ str_pool[s]:="""";
+ pool_ptr:=pool_ptr+2;
+ end;
+ end;
+@z
+
+@x
+ str_start_macro(str_ptr+1):=str_start_macro(str_ptr)+area_delimiter; incr(str_ptr);
+ end;
+if ext_delimiter=0 then
+ begin cur_ext:=""; cur_name:=make_string;
+@y
+ str_start_macro(str_ptr+1):=str_start_macro(str_ptr)+area_delimiter; incr(str_ptr);
+ temp_str:=search_string(cur_area);
+ if temp_str>0 then
+ begin cur_area:=temp_str;
+ decr(str_ptr); {no |flush_string|, |pool_ptr| will be wrong!}
+ for j:=str_start_macro(str_ptr+1) to pool_ptr-1 do
+ begin str_pool[j-area_delimiter]:=str_pool[j];
+ end;
+ pool_ptr:=pool_ptr-area_delimiter; {update |pool_ptr|}
+ end;
+ end;
+if ext_delimiter=0 then
+ begin cur_ext:=""; cur_name:=slow_make_string;
+@z
+
+@x
+else begin cur_name:=str_ptr;
+ str_start_macro(str_ptr+1):=str_start_macro(str_ptr)+ext_delimiter-area_delimiter-1;
+ incr(str_ptr); cur_ext:=make_string;
+@y
+else begin cur_name:=str_ptr;
+ str_start_macro(str_ptr+1):=str_start_macro(str_ptr)+ext_delimiter-area_delimiter-1;
+ incr(str_ptr); cur_ext:=make_string;
+ decr(str_ptr); {undo extension string to look at name part}
+ temp_str:=search_string(cur_name);
+ if temp_str>0 then
+ begin cur_name:=temp_str;
+ decr(str_ptr); {no |flush_string|, |pool_ptr| will be wrong!}
+ for j:=str_start_macro(str_ptr+1) to pool_ptr-1 do
+ begin str_pool[j-ext_delimiter+area_delimiter+1]:=str_pool[j];
+ end;
+ pool_ptr:=pool_ptr-ext_delimiter+area_delimiter+1; {update |pool_ptr|}
+ end;
+ cur_ext:=slow_make_string; {remake extension string}
+@z
+
+@x
+begin slow_print(a); slow_print(n); slow_print(e);
+@y
+var must_quote: boolean; {whether to quote the filename}
+@!j:pool_pointer; {index into |str_pool|}
+begin
+must_quote:=false;
+if a<>0 then begin
+ j:=str_start_macro(a);
+ while (not must_quote) and (j<str_start_macro(a+1)) do begin
+ must_quote:=str_pool[j]=" "; incr(j);
+ end;
+end;
+if n<>0 then begin
+ j:=str_start_macro(n);
+ while (not must_quote) and (j<str_start_macro(n+1)) do begin
+ must_quote:=str_pool[j]=" "; incr(j);
+ end;
+end;
+if e<>0 then begin
+ j:=str_start_macro(e);
+ while (not must_quote) and (j<str_start_macro(e+1)) do begin
+ must_quote:=str_pool[j]=" "; incr(j);
+ end;
+end;
+{FIXME: Alternative is to assume that any filename that has to be quoted has
+ at least one quoted component...if we pick this, a number of insertions
+ of |print_file_name| should go away.
+|must_quote|:=((|a|<>0)and(|str_pool|[|str_start|[|a|]]=""""))or
+ ((|n|<>0)and(|str_pool|[|str_start|[|n|]]=""""))or
+ ((|e|<>0)and(|str_pool|[|str_start|[|e|]]=""""));}
+if must_quote then print_char("""");
+if a<>0 then
+ for j:=str_start_macro(a) to str_start_macro(a+1)-1 do
+ if so(str_pool[j])<>"""" then
+ print(so(str_pool[j]));
+if n<>0 then
+ for j:=str_start_macro(n) to str_start_macro(n+1)-1 do
+ if so(str_pool[j])<>"""" then
+ print(so(str_pool[j]));
+if e<>0 then
+ for j:=str_start_macro(e) to str_start_macro(e+1)-1 do
+ if so(str_pool[j])<>"""" then
+ print(so(str_pool[j]));
+if must_quote then print_char("""");
+@z
+
+@x
+@d append_to_name(#)==begin c:=#; incr(k);
+ if k<=file_name_size then nameoffile[k]:=xchr[c];
+ end
+@y
+@d append_to_name(#)==begin c:=#; if not (c="""") then begin incr(k);
+ if k<=file_name_size then nameoffile[k]:=xchr[c];
+ end end
+@z
+
+@x
+for j:=str_start_macro(a) to str_start_macro(a+1)-1 do append_to_name(so(str_pool[j]));
+@y
+if nameoffile then libcfree (nameoffile);
+nameoffile:= xmallocarray (packed_ASCII_code, length(a)+length(n)+length(e)+1);
+for j:=str_start_macro(a) to str_start_macro(a+1)-1 do append_to_name(so(str_pool[j]));
+@z
+
+@x
+for k:=namelength+1 to file_name_size do nameoffile[k]:=' ';
+@y
+nameoffile[namelength+1]:=0;
+@z
+
+@x
+@d format_default_length=20 {length of the |TEX_format_default| string}
+@d format_area_length=11 {length of its area part}
+@d format_ext_length=4 {length of its `\.{.fmt}' part}
+@y
+Under {\mc UNIX} we don't give the area part, instead depending
+on the path searching that will happen during file opening. Also, the
+length will be set in the main program.
+
+@d format_area_length=0 {length of its area part}
+@d format_ext_length=4 {length of its `\.{.fmt}' part}
+@z
+
+@x
+@!TEX_format_default:packed array[1..format_default_length] of char;
+
+@ @<Set init...@>=
+TEX_format_default:='TeXformats:plain.fmt';
+@y
+@!format_default_length: integer;
+@!TEX_format_default: ^char;
+
+@ We set the name of the default format file and the length of that name
+in C, instead of Pascal, since we want them to depend on the name of the
+program.
+@z
+
+@x
+for j:=1 to n do append_to_name(TEX_format_default[j]);
+@y
+if nameoffile then libcfree (nameoffile);
+nameoffile := xmallocarray (packed_ASCII_code, n+(b-a+1)+format_ext_length+1);
+for j:=1 to n do append_to_name(TEX_format_default[j]);
+@z
+
+@x
+for k:=namelength+1 to file_name_size do nameoffile[k]:=' ';
+@y
+nameoffile[namelength+1]:=0;
+@z
+
+@x
+ pack_buffered_name(0,loc,j-1); {try first without the system file area}
+ if w_open_in(fmt_file) then goto found;
+ pack_buffered_name(format_area_length,loc,j-1);
+ {now try the system format file area}
+ if w_open_in(fmt_file) then goto found;
+@y
+ pack_buffered_name(0,loc,j-1); {Kpathsea does everything}
+ if w_open_in(fmt_file) then goto found;
+@z
+
+@x
+ wterm_ln('Sorry, I can''t find that format;',' will try PLAIN.');
+@y
+ wterm ('Sorry, I can''t find the format `');
+ fputs (stringcast(nameoffile + 1), stdout);
+ wterm ('''; will try `');
+ fputs (TEX_format_default + 1, stdout);
+ wterm_ln ('''.');
+@z
+
+@x
+ wterm_ln('I can''t find the PLAIN format file!');
+@.I can't find PLAIN...@>
+@y
+ wterm ('I can''t find the format file `');
+ fputs (TEX_format_default + 1, stdout);
+ wterm_ln ('''!');
+@.I can't find the format...@>
+@z
+
+@x
+@p function make_name_string:str_number;
+var k:1..file_name_size; {index into |nameoffile|}
+begin if (pool_ptr+namelength>pool_size)or(str_ptr=max_strings)or
+ (cur_length>0) then
+ make_name_string:="?"
+else begin for k:=1 to namelength do append_char(nameoffile[k]);
+ make_name_string:=make_string;
+ end;
+@y
+@p function make_name_string:str_number;
+var k:1..file_name_size; {index into |nameoffile|}
+save_area_delimiter, save_ext_delimiter: pool_pointer;
+save_name_in_progress, save_stop_at_space: boolean;
+begin if (pool_ptr+namelength>pool_size)or(str_ptr=max_strings)or
+ (cur_length>0) then
+ make_name_string:="?"
+else begin for k:=1 to namelength do append_char(nameoffile[k]);
+ make_name_string:=make_string;
+ {At this point we also set |cur_name|, |cur_ext|, and |cur_area| to
+ match the contents of |nameoffile|.}
+ save_area_delimiter:=area_delimiter;
+ save_ext_delimiter:=ext_delimiter;
+ save_name_in_progress:=name_in_progress;
+ save_stop_at_space:=stop_at_space;
+ name_in_progress:=true;
+ begin_name;
+ stop_at_space:=false;
+ k:=1;
+ while (k<=namelength)and(more_name(nameoffile[k])) do
+ incr(k);
+ stop_at_space:=save_stop_at_space;
+ end_name;
+ name_in_progress:=save_name_in_progress;
+ area_delimiter:=save_area_delimiter;
+ ext_delimiter:=save_ext_delimiter;
+ end;
+@z
+
+@x
+ if not more_name(cur_chr) then goto done;
+@y
+ {If |cur_chr| is a space and we're not scanning a token list, check
+ whether we're at the end of the buffer. Otherwise we end up adding
+ spurious spaces to file names in some cases.}
+ if (cur_chr=" ") and (state<>token_list) and (loc>limit) then goto done;
+ if not more_name(cur_chr) then goto done;
+@z
+
+@x
+var k:0..buf_size; {index into |buffer|}
+@y
+var k:0..buf_size; {index into |buffer|}
+@!saved_cur_name:str_number; {to catch empty terminal input}
+@z
+
+@x
+if e=".tex" then show_context;
+@y
+if (e=".tex") or (e="") then show_context;
+@z
+
+@x
+clear_terminal; prompt_input(": "); @<Scan file name in the buffer@>;
+if cur_ext="" then cur_ext:=e;
+@y
+saved_cur_name:=cur_name;
+clear_terminal; prompt_input(": "); @<Scan file name in the buffer@>;
+if cur_ext="" then cur_ext:=e;
+if length(cur_name)=0 then cur_name:=saved_cur_name;
+@z
+
+@x
+@d ensure_dvi_open==if output_file_name=0 then
+@y
+@d log_name == texmf_log_name
+@d ensure_dvi_open==if output_file_name=0 then
+@z
+
+@x
+@!months:packed array [1..36] of char; {abbreviations of month names}
+@y
+@!months:^char;
+@z
+
+@x
+if job_name=0 then job_name:="texput";
+@.texput@>
+@y
+if job_name=0 then job_name:=getjobname("texput");
+@.texput@>
+pack_job_name(".fls");
+recorder_change_filename(stringcast(nameoffile+1));
+@z
+
+@x
+begin wlog(banner);
+@y
+begin if srcspecialsp or filelineerrorstylep or parsefirstlinep
+then
+ wlog(banner_k)
+else
+ wlog(banner);
+@z
+
+@x
+slow_print(format_ident); print(" ");
+@y
+wlog(versionstring);
+slow_print(format_ident); print(" ");
+@z
+
+@x
+months:='JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC';
+@y
+months := ' JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC';
+@z
+
+@x
+end
+@y
+if shellenabledp then begin
+ wlog_cr;
+ wlog('\write18 enabled.')
+ end;
+if srcspecialsp then begin
+ wlog_cr;
+ wlog(' Source specials enabled.')
+ end;
+if filelineerrorstylep then begin
+ wlog_cr;
+ wlog(' file:line:error style messages enabled.')
+ end;
+if parsefirstlinep then begin
+ wlog_cr;
+ wlog(' %&-line parsing enabled.');
+ end;
+end
+@z
+
+@x
+ prompt_file_name("input file name",".tex");
+@y
+ prompt_file_name("input file name","");
+@z
+
+@x
+name:=a_make_name_string(cur_file);
+@y
+name:=a_make_name_string(cur_file);
+source_filename_stack[in_open]:=name;
+full_source_filename_stack[in_open]:=makefullnamestring;
+if name=str_ptr-1 then {we can try to conserve string pool space now}
+ begin temp_str:=search_string(name);
+ if temp_str>0 then
+ begin name:=temp_str; flush_string;
+ end;
+ end;
+@z
+
+@x
+ begin job_name:=cur_name; open_log_file;
+@y
+ begin job_name:=getjobname(cur_name); open_log_file;
+@z
+
+@x
+if name=str_ptr-1 then {we can conserve string pool space now}
+ begin flush_string; name:=cur_name;
+ end;
+@y
+@z
+
+@x
+@!ocp_list_info:array[ocp_list_index] of memory_word;
+ {the big collection of ocp list data}
+@!ocp_listmem_ptr:ocp_list_index; {first unused word of |ocp_list_info|}
+@!ocp_listmem_run_ptr:ocp_list_index; {temp unused word of |ocp_list_info|}
+@!ocp_lstack_info:array[ocp_lstack_index] of memory_word;
+ {the big collection of ocp lstack data}
+@!ocp_lstackmem_ptr:ocp_lstack_index; {first unused word of |ocp_lstack_info|}
+@!ocp_lstackmem_run_ptr:ocp_lstack_index; {temp unused word of |ocp_lstack_info|}
+@!ocp_list_ptr:internal_ocp_list_number; {largest internal ocp list number in use}
+@!ocp_list_list:array[internal_ocp_list_number] of ocp_list_index;
+@y
+@!ocp_list_info:^memory_word;
+ {the big collection of ocp list data}
+@!ocp_listmem_ptr:ocp_list_index; {first unused word of |ocp_list_info|}
+@!ocp_listmem_run_ptr:ocp_list_index; {temp unused word of |ocp_list_info|}
+@!ocp_lstack_info:^memory_word;
+ {the big collection of ocp lstack data}
+@!ocp_lstackmem_ptr:ocp_lstack_index; {first unused word of |ocp_lstack_info|}
+@!ocp_lstackmem_run_ptr:ocp_lstack_index; {temp unused word of |ocp_lstack_info|}
+@!ocp_list_ptr:internal_ocp_list_number; {largest internal ocp list number in use}
+@!ocp_list_list:^ocp_list_index;
+@z
+
+@x
+@!dvi_buf:array[dvi_index] of real_eight_bits; {buffer for \.{DVI} output}
+@!half_buf:dvi_index; {half of |dvi_buf_size|}
+@!dvi_limit:dvi_index; {end of the current half buffer}
+@!dvi_ptr:dvi_index; {the next available buffer address}
+@y
+@!dvi_buf:^real_eight_bits; {buffer for \.{DVI} output}
+@!half_buf:integer; {half of |dvi_buf_size|}
+@!dvi_limit:integer; {end of the current half buffer}
+@!dvi_ptr:integer; {the next available buffer address}
+@z
+
+@x
+@p procedure write_dvi(@!a,@!b:dvi_index);
+var k:dvi_index;
+begin for k:=a to b do write(dvi_file,dvi_buf[k]);
+end;
+@y
+In C, we use a macro to call |fwrite| or |write| directly, writing all
+the bytes in one shot. Much better even than writing four
+bytes at a time.
+@z
+
+@x
+ old_setting:=selector; selector:=new_string;
+@y
+if output_comment then
+ begin l:=strlen(output_comment); dvi_out(l);
+ for s:=0 to l-1 do dvi_out(output_comment[s]);
+ end
+else begin {the default code is unchanged}
+ old_setting:=selector; selector:=new_string;
+@z
+
+@x
+ pool_ptr:=str_start_macro(str_ptr); {flush the current string}
+@y
+ pool_ptr:=str_start_macro(str_ptr); {flush the current string}
+end;
+@z
+
+@x
+dvi_out(eop); incr(total_pages); cur_s:=-1;
+@y
+dvi_out(eop); incr(total_pages); cur_s:=-1;
+ifdef ('IPC')
+if ipcon>0 then
+ begin if dvi_limit=half_buf then
+ begin write_dvi(half_buf, dvi_buf_size-1);
+ flush_dvi;
+ dvi_gone:=dvi_gone+half_buf;
+ end;
+ if dvi_ptr>0 then
+ begin write_dvi(0, dvi_ptr-1);
+ flush_dvi;
+ dvi_offset:=dvi_offset+dvi_ptr; dvi_gone:=dvi_gone+dvi_ptr;
+ end;
+ dvi_ptr:=0; dvi_limit:=dvi_buf_size;
+ ipcpage(dvi_gone);
+ end;
+endif ('IPC');
+@z
+
+@x
+ k:=4+((dvi_buf_size-dvi_ptr) mod 4); {the number of 223's}
+@y
+ifdef ('IPC')
+ k:=7-((3+dvi_offset+dvi_ptr) mod 4); {the number of 223's}
+endif ('IPC')
+ifndef ('IPC')
+ k:=4+((dvi_buf_size-dvi_ptr) mod 4); {the number of 223's}
+endifn ('IPC')
+@z
+
+@x
+ print_nl("Output written on "); slow_print(output_file_name);
+@y
+ print_nl("Output written on "); print_file_name(0, output_file_name, 0);
+@z
+
+@x
+ print(" ("); print_int(total_pages); print(" page");
+ if total_pages<>1 then print_char("s");
+@y
+ print(" ("); print_int(total_pages);
+ if total_pages<>1 then print(" pages")
+ else print(" page");
+@z
+
+@x
+@<Append character |cur_chr|...@>=
+continue: adjust_space_factor;@/
+@y
+@<Append character |cur_chr|...@>=
+if ((head=tail) and (mode>0)) then begin
+ if (insertsrcspecialauto) then append_src_special;
+end;
+continue: adjust_space_factor;@/
+@z
+
+@x
+print("' in "); print_mode(mode);
+@y
+print_in_mode(mode);
+@z
+
+@x
+if indented then begin
+ p:=new_null_box; box_dir(p):=par_direction;
+ width(p):=par_indent;@+
+ tail_append(p);
+@y
+if indented then begin
+ p:=new_null_box; box_dir(p):=par_direction;
+ width(p):=par_indent;@+
+ tail_append(p);
+ if (insertsrcspecialeverypar) then insert_src_special;@+
+@z
+
+@x
+begin print_err("Extra "); print_esc("endcsname");
+@.Extra \\endcsname@>
+help1("I'm ignoring this, since I wasn't doing a \csname.");
+@y
+begin
+if cur_chr = 10 then
+begin
+ print_err("Extra "); print_esc("endmubyte");
+@.Extra \\endmubyte@>
+ help1("I'm ignoring this, since I wasn't doing a \mubyte.");
+end else begin
+ print_err("Extra "); print_esc("endcsname");
+@.Extra \\endcsname@>
+ help1("I'm ignoring this, since I wasn't doing a \csname.");
+end;
+@z
+
+@x
+if every_math<>null then begin_token_list(every_math,every_math_text);
+@y
+if (insertsrcspecialeverymath) then insert_src_special;
+if every_math<>null then begin_token_list(every_math,every_math_text);
+@z
+
+@x
+ if every_vbox<>null then begin_token_list(every_vbox,every_vbox_text);
+@y
+ if (insertsrcspecialeveryvbox) then insert_src_special;
+ if every_vbox<>null then begin_token_list(every_vbox,every_vbox_text);
+@z
+
+@x
+if (cur_cs=0)or(cur_cs>frozen_control_sequence) then
+@y
+if (cur_cs=0)or(cur_cs>eqtb_top)or
+ ((cur_cs>frozen_control_sequence)and(cur_cs<=eqtb_size)) then
+@z
+
+@x
+@!flushable_string:str_number; {string not yet referenced}
+@y
+@z
+
+@x
+interaction:=cur_chr;
+@y
+interaction:=cur_chr;
+if interaction = batch_mode
+then kpsemaketexdiscarderrors := 1
+else kpsemaketexdiscarderrors := 0;
+@z
+
+@x
+slow_print(s); update_terminal;
+@y
+print(s); update_terminal;
+@z
+
+@x
+begin print_err(""); slow_print(s);
+@y
+begin print_err(""); print(s);
+@z
+
+@x
+format_ident:=" (INITEX)";
+@y
+if ini_version then format_ident:=" (INITEX)";
+@z
+
+@x
+@!w: four_quarters; {four ASCII codes}
+@y
+@!format_engine: ^packed_ASCII_code;
+@z
+
+@x
+@!w: four_quarters; {four ASCII codes}
+@y
+@!format_engine: ^packed_ASCII_code;
+@z
+
+@x
+@d dump_wd(#)==begin fmt_file^:=#; put(fmt_file);@+end
+@d dump_int(#)==begin fmt_file^.int:=#; put(fmt_file);@+end
+@d dump_hh(#)==begin fmt_file^.hh:=#; put(fmt_file);@+end
+@d dump_qqqq(#)==begin fmt_file^.qqqq:=#; put(fmt_file);@+end
+@y
+@z
+
+@x
+@d undump_wd(#)==begin get(fmt_file); #:=fmt_file^;@+end
+@d undump_int(#)==begin get(fmt_file); #:=fmt_file^.int;@+end
+@d undump_hh(#)==begin get(fmt_file); #:=fmt_file^.hh;@+end
+@d undump_qqqq(#)==begin get(fmt_file); #:=fmt_file^.qqqq;@+end
+@y
+@z
+
+@x
+@d undump_size_end_end(#)==too_small(#)@+else undump_end_end
+@y
+@d format_debug_end(#)==
+ writeln (stderr, ' = ', #);
+ end;
+@d format_debug(#)==
+ if debug_format_file then begin
+ write (stderr, 'fmtdebug:', #);
+ format_debug_end
+@d undump_size_end_end(#)==
+ too_small(#)@+else format_debug (#)(x); undump_end_end
+@z
+
+@x
+dump_int(@$);@/
+@y
+dump_int(@"57325458); {Web2C \TeX's magic constant: "W2TX"}
+{Align engine to 4 bytes with one or more trailing NUL}
+x:=strlen(engine_name);
+format_engine:=xmallocarray(packed_ASCII_code,x+4);
+strcpy(stringcast(format_engine), stringcast(engine_name));
+for k:=x to x+3 do format_engine[k]:=0;
+x:=x+4-(x mod 4);
+dump_int(x);dump_things(format_engine[0], x);
+libcfree(format_engine);@/
+dump_int(@$);@/
+dump_int(max_halfword);@/
+dump_int(hash_high);
+@z
+
+@x
+x:=fmt_file^.int;
+if x<>@$ then goto bad_fmt; {check that strings are the same}
+@y
+@+Init
+libcfree(str_pool); libcfree(str_start);
+libcfree(yhash); libcfree(zeqtb); libcfree(fixmem); libcfree(varmem);
+@+Tini
+undump_int(x);
+format_debug('format magic number')(x);
+if x<>@"57325458 then goto bad_fmt; {not a format file}
+undump_int(x);
+format_debug('engine name size')(x);
+if (x<0) or (x>256) then goto bad_fmt; {corrupted format file}
+format_engine:=xmallocarray(packed_ASCII_code, x);
+undump_things(format_engine[0], x);
+format_engine[x-1]:=0; {force string termination, just in case}
+if strcmp(stringcast(engine_name), stringcast(format_engine)) then
+ begin wake_up_terminal;
+ wterm_ln('---! ', stringcast(nameoffile+1), ' was written by ', format_engine);
+ libcfree(format_engine);
+ goto bad_fmt;
+end;
+libcfree(format_engine);
+undump_int(x);
+format_debug('string pool checksum')(x);
+if x<>@$ then begin {check that strings are the same}
+ wake_up_terminal;
+ wterm_ln('---! ', stringcast(nameoffile+1), ' was written by an older version');
+ goto bad_fmt;
+end;
+undump_int(x);
+if x<>max_halfword then goto bad_fmt; {check |max_halfword|}
+undump_int(hash_high);
+ if (hash_high<0)or(hash_high>sup_hash_extra) then goto bad_fmt;
+ if hash_extra<hash_high then hash_extra:=hash_high;
+ eqtb_top:=eqtb_size+hash_extra;
+ if hash_extra=0 then hash_top:=undefined_control_sequence else
+ hash_top:=eqtb_top;
+ yhash:=xmallocarray(two_halves,1+hash_top-hash_offset);
+ hash:=yhash - hash_offset;
+ next(hash_base):=0; text(hash_base):=0;
+ for x:=hash_base+1 to hash_top do hash[x]:=hash[hash_base];
+ zeqtb:=xmallocarray (memory_word,eqtb_top+1);
+ eqtb:=zeqtb;
+
+ eq_type(undefined_control_sequence):=undefined_cs;
+ equiv(undefined_control_sequence):=null;
+ eq_level(undefined_control_sequence):=level_zero;
+ for x:=eqtb_size+1 to eqtb_top do
+ eqtb[x]:=eqtb[undefined_control_sequence];
+@z
+
+@x
+dump_int(str_ptr);
+for k:=string_offset to str_ptr do dump_int(str_start_macro(k));
+k:=0;
+while k+4<pool_ptr do
+ begin dump_four_ASCII; k:=k+4;
+ end;
+k:=pool_ptr-4; dump_four_ASCII;
+@y
+dump_int((str_ptr-string_offset));
+dump_things(str_start[0], (str_ptr-string_offset)+1);
+dump_things(str_pool[0], pool_ptr);
+@z
+
+@x
+undump_size(0)(pool_size)('string pool size')(pool_ptr);
+undump_size(0)(max_strings)('max strings')(str_ptr);
+for k:=string_offset to str_ptr do undump(0)(pool_ptr)(str_start_macro(k));
+k:=0;
+while k+4<pool_ptr do
+ begin undump_four_ASCII; k:=k+4;
+ end;
+k:=pool_ptr-4; undump_four_ASCII;
+@y
+undump_size(0)(sup_pool_size-pool_free)('string pool size')(pool_ptr);
+if pool_size<pool_ptr+pool_free then
+ pool_size:=pool_ptr+pool_free;
+undump_size(0)(sup_max_strings-strings_free)('sup strings')(str_ptr);@/
+if max_strings<str_ptr+strings_free then
+ max_strings:=str_ptr+strings_free;
+str_start:=xmallocarray(pool_pointer, max_strings);
+str_ptr:=str_ptr + string_offset;
+undump_checked_things(0, pool_ptr, str_start[0], (str_ptr-string_offset)+1);@/
+str_pool:=xmallocarray(packed_ASCII_code, pool_size);
+undump_things(str_pool[0], pool_ptr);
+@z
+
+@x
+for k:=fix_mem_min to fix_mem_end do dump_wd(mem(k));
+@y
+dump_things(mem(fix_mem_min), fix_mem_end-fix_mem_min+1);
+@z
+
+@x
+for k:=fix_mem_min to fix_mem_end do undump_wd(mem(k));
+@y
+undump_things (mem(fix_mem_min), fix_mem_end-fix_mem_min+1);
+@z
+
+@x
+undump(hash_base)(frozen_control_sequence)(par_loc);
+par_token:=cs_token_flag+par_loc;@/
+undump(hash_base)(frozen_control_sequence)(write_loc);@/
+@y
+undump(hash_base)(hash_top)(par_loc);
+par_token:=cs_token_flag+par_loc;@/
+undump(hash_base)(hash_top)(write_loc);@/
+@z
+
+@x
+while k<l do
+ begin dump_wd(eqtb[k]); incr(k);
+ end;
+@y
+dump_things(eqtb[k], l-k);
+@z
+
+@x
+while k<l do
+ begin dump_wd(eqtb[k]); incr(k);
+ end;
+@y
+dump_things(eqtb[k], l-k);
+@z
+
+@x
+k:=j+1; dump_int(k-l);
+until k>eqtb_size
+@y
+k:=j+1; dump_int(k-l);
+until k>eqtb_size;
+if hash_high>0 then dump_things(eqtb[eqtb_size+1],hash_high);
+ {dump |hash_extra| part}
+@z
+
+@x
+for j:=k to k+x-1 do undump_wd(eqtb[j]);
+@y
+undump_things(eqtb[k], x);
+@z
+
+@x
+until k>eqtb_size
+@y
+until k>eqtb_size;
+if hash_high>0 then undump_things(eqtb[eqtb_size+1],hash_high);
+ {undump |hash_extra| part}
+@z
+
+@x
+dump_int(hash_used); cs_count:=frozen_control_sequence-1-hash_used;
+@y
+dump_int(hash_used); cs_count:=frozen_control_sequence-1-hash_used+hash_high;
+@z
+
+@x
+for p:=hash_used+1 to undefined_control_sequence-1 do dump_hh(hash[p]);
+@y
+dump_things(hash[hash_used+1], undefined_control_sequence-1-hash_used);
+if hash_high>0 then dump_things(hash[eqtb_size+1], hash_high);
+@z
+
+@x
+for p:=hash_used+1 to undefined_control_sequence-1 do undump_hh(hash[p]);
+@y
+undump_things (hash[hash_used+1], undefined_control_sequence-1-hash_used);
+if debug_format_file then begin
+ print_csnames (hash_base, undefined_control_sequence - 1);
+end;
+if hash_high > 0 then begin
+ undump_things (hash[eqtb_size+1], hash_high);
+ if debug_format_file then begin
+ print_csnames (eqtb_size + 1, hash_high - (eqtb_size + 1));
+ end;
+end;
+@z
+
+@x
+@ @<Undump the array info for internal font number |k|@>=
+begin undump_font(k);@/
+end
+@y
+@ @<Undump the array info for internal font number |k|@>=
+begin undump_font(k);@/
+end;
+make_pdftex_banner
+@z
+
+@x
+for k:=0 to active_max_ptr-1 do dump_wd(active_info[k]);
+if active_max_ptr>0 then begin
+ print_ln; print_int(active_max_ptr); print(" words of active ocps");
+ end;
+
+@ @<Undump the active ocp information@>=
+undump_size(0)(active_mem_size)('active start point')(active_min_ptr);
+undump_size(0)(active_mem_size)('active mem size')(active_max_ptr);
+for k:=0 to active_max_ptr-1 do undump_wd(active_info[k]);
+@y
+if active_max_ptr>0 then
+ dump_things(active_info[0], active_max_ptr);
+if active_max_ptr>0 then begin
+ print_ln; print_int(active_max_ptr); print(" words of active ocps");
+ end;
+
+@ @<Undump the active ocp information@>=
+undump_size(0)(active_mem_size)('active start point')(active_min_ptr);
+undump_size(0)(active_mem_size)('active mem size')(active_max_ptr);
+if active_max_ptr>0 then
+ undump_things(active_info[0], active_max_ptr);
+@z
+
+@x
+@ @<Dump the ocp list information@>=
+dump_int(ocp_listmem_ptr);
+for k:=0 to ocp_listmem_ptr-1 do dump_wd(ocp_list_info[k]);
+dump_int(ocp_list_ptr);
+for k:=null_ocp_list to ocp_list_ptr do begin
+ dump_int(ocp_list_list[k]);
+ if null_ocp_list<>ocp_list_ptr then begin
+ print_nl("\ocplist");
+ print_esc(ocp_list_id_text(k));
+ print_char("=");
+ print_ocp_list(ocp_list_list[k]);
+ end;
+ end;
+dump_int(ocp_lstackmem_ptr);
+for k:=0 to ocp_lstackmem_ptr-1 do dump_wd(ocp_lstack_info[k])
+@y
+@ @<Dump the ocp list information@>=
+dump_int(ocp_listmem_ptr);
+dump_things(ocp_list_info[0], ocp_listmem_ptr);
+dump_int(ocp_list_ptr);
+dump_things(ocp_list_list[null_ocp_list], ocp_list_ptr+1-null_ocp_list);
+for k:=null_ocp_list to ocp_list_ptr do begin
+ if null_ocp_list<>ocp_list_ptr then begin
+ print_nl("\ocplist");
+ print_esc(ocp_list_id_text(k));
+ print_char("=");
+ print_ocp_list(ocp_list_list[k]);
+ end;
+ end;
+dump_int(ocp_lstackmem_ptr);
+dump_things(ocp_lstack_info[0], ocp_lstackmem_ptr)
+@z
+
+@x
+@ @<Undump the ocp list information@>=
+undump_size(1)(1000000)('ocp list mem size')(ocp_listmem_ptr);
+for k:=0 to ocp_listmem_ptr-1 do undump_wd(ocp_list_info[k]);
+undump_size(ocp_list_base)(ocp_list_biggest)('ocp list max')(ocp_list_ptr);
+for k:=null_ocp_list to ocp_list_ptr do
+ undump_int(ocp_list_list[k]);
+undump_size(1)(1000000)('ocp lstack mem size')(ocp_lstackmem_ptr);
+for k:=0 to ocp_lstackmem_ptr-1 do undump_wd(ocp_lstack_info[k])
+@y
+@ @<Undump the ocp list information@>=
+undump_size(1)(1000000)('ocp list mem size')(ocp_listmem_ptr);
+undump_things(ocp_list_info[0], ocp_listmem_ptr);
+undump_size(0)(1000000)('ocp list max')(ocp_list_ptr);
+undump_things(ocp_list_list[null_ocp_list], ocp_list_ptr+1-null_ocp_list);
+undump_size(0)(1000000)('ocp lstack mem size')(ocp_lstackmem_ptr);
+undump_things(ocp_lstack_info[0], ocp_lstackmem_ptr)
+@z
+
+@x
+undump(batch_mode)(error_stop_mode)(interaction);
+@y
+undump(batch_mode)(error_stop_mode)(interaction);
+if interactionoption<>unspecified_mode then interaction:=interactionoption;
+@z
+
+@x
+if (x<>69069)or eof(fmt_file) then goto bad_fmt
+@y
+if x<>69069 then goto bad_fmt
+@z
+
+@x
+print(" (preloaded format="); print(job_name); print_char(" ");
+@y
+print(" (format="); print(job_name); print_char(" ");
+@z
+
+@x
+@p begin @!{|start_here|}
+@y
+@d const_chk(#)==begin if # < inf_@&# then # := inf_@&# else
+ if # > sup_@&# then # := sup_@&# end
+
+{|setup_bound_var| stuff duplicated in \.{mf.ch}.}
+@d setup_bound_var(#)==bound_default:=#; setup_bound_var_end
+@d setup_bound_var_end(#)==bound_name:=#; setup_bound_var_end_end
+@d setup_bound_var_end_end(#)==if luainit>0 then begin
+ get_lua_number('texconfig',bound_name,addressof(#));
+ if #=0 then #:=bound_default;
+ end
+ else
+ setupboundvariable(addressof(#), bound_name, bound_default);
+
+@p procedure main_body;
+begin @!{|start_here|}
+
+{Bounds that may be set from the configuration file. We want the user to
+ be able to specify the names with underscores, but \.{TANGLE} removes
+ underscores, so we're stuck giving the names twice, once as a string,
+ once as the identifier. How ugly.}
+
+ setup_bound_var (100000)('pool_size')(pool_size);
+ setup_bound_var (75000)('string_vacancies')(string_vacancies);
+ setup_bound_var (5000)('pool_free')(pool_free); {min pool avail after fmt}
+ setup_bound_var (15000)('max_strings')(max_strings);
+ setup_bound_var (100)('strings_free')(strings_free);
+ setup_bound_var (3000)('buf_size')(buf_size);
+ setup_bound_var (50)('nest_size')(nest_size);
+ setup_bound_var (15)('max_in_open')(max_in_open);
+ setup_bound_var (60)('param_size')(param_size);
+ setup_bound_var (4000)('save_size')(save_size);
+ setup_bound_var (300)('stack_size')(stack_size);
+ setup_bound_var (16384)('dvi_buf_size')(dvi_buf_size);
+ setup_bound_var (79)('error_line')(error_line);
+ setup_bound_var (50)('half_error_line')(half_error_line);
+ setup_bound_var (79)('max_print_line')(max_print_line);
+ setup_bound_var(1000)('ocp_list_size')(ocp_list_size);
+ setup_bound_var(1000)('ocp_buf_size')(ocp_buf_size);
+ setup_bound_var(1000)('ocp_stack_size')(ocp_stack_size);
+ setup_bound_var (0)('hash_extra')(hash_extra);
+ setup_bound_var (72)('pk_dpi')(pk_dpi);
+ setup_bound_var (10000)('expand_depth')(expand_depth);
+
+ {Check other constants against their sup and inf.}
+ const_chk (buf_size);
+ const_chk (nest_size);
+ const_chk (max_in_open);
+ const_chk (param_size);
+ const_chk (save_size);
+ const_chk (stack_size);
+ const_chk (dvi_buf_size);
+ const_chk (pool_size);
+ const_chk (string_vacancies);
+ const_chk (pool_free);
+ const_chk (max_strings);
+ const_chk (strings_free);
+ const_chk (hash_extra);
+ const_chk (obj_tab_size);
+ const_chk (pdf_mem_size);
+ const_chk (dest_names_size);
+ const_chk (pk_dpi);
+ if error_line > ssup_error_line then error_line := ssup_error_line;
+
+ {array memory allocation}
+ buffer:=xmallocarray (packed_ASCII_code, buf_size);
+ nest:=xmallocarray (list_state_record, nest_size);
+ save_stack:=xmallocarray (memory_word, save_size);
+ input_stack:=xmallocarray (in_state_record, stack_size);
+ input_file:=xmallocarray (alpha_file, max_in_open);
+ input_file_callback_id:=xmallocarray (integer, max_in_open);
+ line_stack:=xmallocarray (integer, max_in_open);
+ eof_seen:=xmallocarray (boolean, max_in_open);
+ grp_stack:=xmallocarray (save_pointer, max_in_open);
+ if_stack:=xmallocarray (pointer, max_in_open);
+ source_filename_stack:=xmallocarray (str_number, max_in_open);
+ full_source_filename_stack:=xmallocarray (str_number, max_in_open);
+ param_stack:=xmallocarray (halfword, param_size);
+ dvi_buf:=xmallocarray (real_eight_bits, dvi_buf_size);
+ ocp_list_info:=xmallocarray (memory_word, ocp_list_size);
+ memset(ocp_list_info,0,sizeof(memory_word)* ocp_list_size);
+ ocp_lstack_info:=xmallocarray (memory_word, ocp_list_size);
+ memset(ocp_lstack_info,0,sizeof(memory_word)* ocp_list_size);
+ ocp_list_list:=xmallocarray (ocp_list_index, ocp_list_size);
+ otp_init_input_buf:=xmallocarray (quarterword, ocp_buf_size);
+ otp_input_buf:=xmallocarray (quarterword, ocp_buf_size);
+ otp_output_buf:=xmallocarray (quarterword, ocp_buf_size);
+ otp_stack_buf:=xmallocarray (quarterword, ocp_stack_size);
+ otp_calcs:=xmallocarray (halfword, ocp_stack_size);
+ otp_states:=xmallocarray (halfword, ocp_stack_size);
+ obj_tab:=xmallocarray (obj_entry, inf_obj_tab_size); {will grow dynamically}
+ obj_offset(0):=0;
+ pdf_mem:=xmallocarray (integer, inf_pdf_mem_size); {will grow dynamically}
+ dest_names:=xmallocarray (dest_name_entry, inf_dest_names_size); {will grow dynamically}
+ pdf_op_buf:=xmallocarray (real_eight_bits, pdf_op_buf_size);
+ pdf_os_buf:=xmallocarray (real_eight_bits, inf_pdf_os_buf_size); {will grow dynamically}
+ pdf_os_objnum:=xmallocarray (integer, pdf_os_max_objs);
+ pdf_os_objoff:=xmallocarray (integer, pdf_os_max_objs);
+@+Init
+ fixmem:=xmallocarray (smemory_word, fix_mem_init+1);
+ memset (voidcast(fixmem), 0, (fix_mem_init+1)*sizeof(smemory_word));
+ fix_mem_min:=0;
+ fix_mem_max:=fix_mem_init;
+
+ eqtb_top := eqtb_size+hash_extra;
+ if hash_extra=0 then hash_top:=undefined_control_sequence else
+ hash_top:=eqtb_top;
+ yhash:=xmallocarray (two_halves,1+hash_top-hash_offset);
+ hash:=yhash - hash_offset; {Some compilers require |hash_offset=0|}
+ next(hash_base):=0; text(hash_base):=0;
+ for hash_used:=hash_base+1 to hash_top do hash[hash_used]:=hash[hash_base];
+ zeqtb:=xmallocarray (memory_word, eqtb_top);
+ eqtb:=zeqtb;
+
+ str_start:=xmallocarray (pool_pointer, max_strings);
+ str_pool:=xmallocarray (packed_ASCII_code, pool_size);
+@+Tini
+@z
+
+@x
+@!init if not get_strings_started then goto final_end;
+init_prim; {call |primitive| for each primitive}
+init_str_ptr:=str_ptr; init_pool_ptr:=pool_ptr; fix_date_and_time;
+tini@/
+@y
+@!Init if not get_strings_started then goto final_end;
+init_prim; {call |primitive| for each primitive}
+init_str_ptr:=str_ptr; init_pool_ptr:=pool_ptr; fix_date_and_time;
+Tini@/
+@z
+
+@x
+end_of_TEX: close_files_and_terminate;
+final_end: ready_already:=0;
+end.
+@y
+close_files_and_terminate;
+final_end: do_final_end;
+end {|main_body|};
+@z
+
+@x
+ wterm(banner);
+@y
+ if srcspecialsp or filelineerrorstylep or parsefirstlinep then
+ wterm(banner_k)
+ else
+ wterm(banner);
+@z
+
+@x
+ if format_ident=0 then wterm_ln(' (no format preloaded)')
+ else begin slow_print(format_ident); print_ln;
+ end;
+@y
+ wterm(versionstring);
+ if format_ident>0 then slow_print(format_ident);
+ print_ln;
+ if shellenabledp then begin
+ wterm_ln(' \write18 enabled.')
+ end;
+ if srcspecialsp then begin
+ wterm_ln(' Source specials enabled.')
+ end;
+ if filelineerrorstylep then begin
+ wterm_ln(' file:line:error style messages enabled.')
+ end;
+ if parsefirstlinep then begin
+ wterm_ln(' %&-line parsing enabled.')
+ end;
+@z
+
+
+
+@x
+ slow_print(log_name); print_char(".");
+@y
+ print_file_name(0, log_name, 0); print_char(".");
+@z
+
+@x
+ end;
+@y
+ end;
+print_ln;
+if (edit_name_start<>0) and (interaction>batch_mode) then
+ calledit(str_pool,edit_name_start,edit_name_length,edit_line);
+@z
+
+@x
+ wlog_ln(' ',cs_count:1,' multiletter control sequences out of ',
+ hash_size:1);@/
+@y
+ wlog_ln(' ',cs_count:1,' multiletter control sequences out of ',
+ hash_size:1, '+', hash_extra:1);@/
+@z
+
+@x
+ begin @!init for i:=0 to biggest_used_mark do begin
+@y
+ begin @!Init for i:=0 to biggest_used_mark do begin
+@z
+
+@x
+ store_fmt_file; return;@+tini@/
+@y
+ store_fmt_file; return;@+Tini@/
+@z
+
+@x
+if (format_ident=0)or(buffer[loc]="&") then
+@y
+if (format_ident=0)or(buffer[loc]="&")or dump_line then
+@z
+
+@x
+ w_close(fmt_file);
+@y
+ w_close(fmt_file);
+ eqtb:=zeqtb;
+@z
+
+@x
+fix_date_and_time;@/
+@y
+fix_date_and_time;@/
+@!init
+make_pdftex_banner;
+tini@/
+@z
+
+@x
+ begin goto breakpoint;@\ {go to every label at least once}
+ breakpoint: m:=0; @{'BREAKPOINT'@}@\
+ end
+@y
+ abort {do something to cause a core dump}
+@z
+
+@x
+primitive("special",extension,special_node);@/
+@y
+primitive("special",extension,special_node);@/
+text(frozen_special):="special"; eqtb[frozen_special]:=eqtb[cur_val];@/
+@z
+
+@x
+ else if cur_val>15 then cur_val:=16;
+@y
+ else if (cur_val>15) and (cur_val <> 18) then cur_val:=16;
+@z
+
+@x
+begin @<Expand macros in the token list
+@y
+@!d:integer; {number of characters in incomplete current string}
+@!clobbered:boolean; {system string is ok?}
+begin @<Expand macros in the token list
+@z
+
+@x
+if write_open[j] then selector:=j
+@y
+if j=18 then selector := new_string
+else if write_open[j] then selector:=j
+@z
+
+@x
+flush_list(def_ref); selector:=old_setting;
+@y
+flush_list(def_ref);
+if j=18 then
+ begin if (tracing_online<=0) then
+ selector:=log_only {Show what we're doing in the log file.}
+ else selector:=term_and_log; {Show what we're doing.}
+ {If the log file isn't open yet, we can only send output to the terminal.
+ Calling |open_log_file| from here seems to result in bad data in the log.}
+ if not log_opened then selector:=term_only;
+ print_nl("system(");
+ for d:=0 to cur_length-1 do
+ begin {|print| gives up if passed |str_ptr|, so do it by hand.}
+ print(so(str_pool[str_start_macro(str_ptr)+d])); {N.B.: not |print_char|}
+ end;
+ print(")...");
+ if shellenabledp then
+ begin str_room(1); append_char(0); {Append a null byte to the expansion.}
+ clobbered:=false;
+ for d:=0 to cur_length-1 do {Convert to external character set.}
+ begin str_pool[str_start_macro(str_ptr)+d]:=xchr[str_pool[str_start_macro(str_ptr)+d]];
+ if (str_pool[str_start_macro(str_ptr)+d]=null_code)
+ and (d<cur_length-1) then clobbered:=true;
+ {minimal checking: NUL not allowed in argument string of |system|()}
+ end;
+ if clobbered then print("clobbered")
+ else begin {We have the string; run system(3). We don't have anything
+ reasonable to do with the return status, unfortunately discard it.}
+ system(stringcast(addressof(str_pool[str_start_macro(str_ptr)])));
+ print("executed");
+ end;
+ end
+ else begin print("disabled");
+ end;
+ print_char("."); print_nl(""); print_ln;
+ pool_ptr:=str_start_macro(str_ptr); {erase the string}
+end;
+selector:=old_setting;
+@z
+
+@x
+@!eof_seen : array[1..max_in_open] of boolean; {has eof been seen?}
+@y
+@!eof_seen : ^boolean; {has eof been seen?}
+@z
+
+@x
+@!grp_stack : array[0..max_in_open] of save_pointer; {initial |cur_boundary|}
+@!if_stack : array[0..max_in_open] of pointer; {initial |cond_ptr|}
+@y
+@!grp_stack : ^save_pointer; {initial |cur_boundary|}
+@!if_stack : ^pointer; {initial |cond_ptr|}
+@z
+
+@x
+@!otp_init_input_buf:array[0..20000] of quarterword;
+
+@!otp_input_start:halfword;
+@!otp_input_last:halfword;
+@!otp_input_end:halfword;
+@!otp_input_buf:array[0..20000] of quarterword;
+
+@!otp_output_end:halfword;
+@!otp_output_buf:array[0..20000] of quarterword;
+
+@!otp_stack_used:halfword;
+@!otp_stack_last:halfword;
+@!otp_stack_new:halfword;
+@!otp_stack_buf:array[0..1000] of quarterword;
+
+@!otp_pc:halfword;
+
+@!otp_calc_ptr:halfword;
+@!otp_calcs:array[0..1000] of halfword;
+@!otp_state_ptr:halfword;
+@!otp_states:array[0..1000] of halfword;
+@y
+@!otp_init_input_buf:^quarterword;
+
+@!otp_input_start:halfword;
+@!otp_input_last:halfword;
+@!otp_input_end:halfword;
+@!otp_input_buf:^quarterword;
+
+@!otp_output_end:halfword;
+@!otp_output_buf:^quarterword;
+
+@!otp_stack_used:halfword;
+@!otp_stack_last:halfword;
+@!otp_stack_new:halfword;
+@!otp_stack_buf:^quarterword;
+
+@!otp_pc:halfword;
+
+@!otp_calc_ptr:halfword;
+@!otp_calcs:^halfword;
+@!otp_state_ptr:halfword;
+@!otp_states:^halfword;
+@z
+
+@x
+@* \[54] System-dependent changes.
+@y
+@* \[54/web2c] System-dependent changes for Web2c.
+Here are extra variables for Web2c. (This numbering of the
+system-dependent section allows easy integration of Web2c and e-\TeX, etc.)
+@^<system dependencies@>
+
+@<Glob...@>=
+@!edit_name_start: pool_pointer; {where the filename to switch to starts}
+@!edit_name_length,@!edit_line: integer; {what line to start editing at}
+@!ipcon: cinttype; {level of IPC action, 0 for none [default]}
+@!stop_at_space: boolean; {whether |more_name| returns false for space}
+
+@ The |edit_name_start| will be set to point into |str_pool| somewhere after
+its beginning if \TeX\ is supposed to switch to an editor on exit.
+
+@<Set init...@>=
+edit_name_start:=0;
+stop_at_space:=true;
+
+@ These are used when we regenerate the representation of the first 256
+strings.
+
+@<Global...@> =
+@!save_str_ptr: str_number;
+@!save_pool_ptr: pool_pointer;
+@!shellenabledp: cinttype;
+@!output_comment: ^char;
+@!k,l: 0..255; {used by `Make the first 256 strings', etc.}
+
+@ When debugging a macro package, it can be useful to see the exact
+control sequence names in the format file. For example, if ten new
+csnames appear, it's nice to know what they are, to help pinpoint where
+they came from. (This isn't a truly ``basic'' printing procedure, but
+that's a convenient module in which to put it.)
+
+@<Basic printing procedures@> =
+procedure print_csnames (hstart:integer; hfinish:integer);
+var c,h:integer;
+begin
+ writeln(stderr, 'fmtdebug:csnames from ', hstart, ' to ', hfinish, ':');
+ for h := hstart to hfinish do begin
+ if text(h) > 0 then begin {if have anything at this position}
+ for c := str_start_macro(text(h)) to str_start_macro(text(h) + 1) - 1
+ do begin
+ putbyte(str_pool[c], stderr); {print the characters}
+ end;
+ writeln(stderr, '|');
+ end;
+ end;
+end;
+
+@ Are we printing extra info as we read the format file?
+
+@<Glob...@> =
+@!debug_format_file: boolean;
+
+
+@ A helper for printing file:line:error style messages. Look for a
+filename in |full_source_filename_stack|, and if we fail to find
+one fall back on the non-file:line:error style.
+
+@<Basic print...@>=
+procedure print_file_line;
+var level: 0..max_in_open;
+begin
+ level:=in_open;
+ while (level>0) and (full_source_filename_stack[level]=0) do
+ decr(level);
+ if level=0 then
+ print_nl("! ")
+ else begin
+ print_nl (""); print (full_source_filename_stack[level]); print (":");
+ if level=in_open then print_int (line)
+ else print_int (line_stack[index+1-(in_open-level)]);
+ print (": ");
+ end;
+end;
+
+@ To be able to determine whether \.{\\write18} is enabled from within
+\TeX\ we also implement \.{\\eof18}. We sort of cheat by having an
+additional route |scan_four_bit_int_or_18| which is the same as
+|scan_four_bit_int| except it also accepts the value 18.
+
+@<Declare procedures that scan restricted classes of integers@>=
+procedure scan_four_bit_int_or_18;
+begin scan_int;
+if (cur_val<0)or((cur_val>15)and(cur_val<>18)) then
+ begin print_err("Bad number");
+@.Bad number@>
+ help2("Since I expected to read a number between 0 and 15,")@/
+ ("I changed this one to zero."); int_error(cur_val); cur_val:=0;
+ end;
+end;
+
+@* \[54/web2c-string] The string recycling routines. \TeX{} uses 2
+upto 4 {\it new\/} strings when scanning a filename in an \.{\\input},
+\.{\\openin}, or \.{\\openout} operation. These strings are normally
+lost because the reference to them are not saved after finishing the
+operation. |search_string| searches through the string pool for the
+given string and returns either 0 or the found string number.
+
+@<Declare additional routines for string recycling@>=
+function search_string(@!search:str_number):str_number;
+label found;
+var result: str_number;
+@!s: str_number; {running index}
+@!len: integer; {length of searched string}
+begin result:=0; len:=length(search);
+if len=0 then {trivial case}
+ begin result:=""; goto found;
+ end
+else begin s:=search-1; {start search with newest string below |s|; |search>1|!}
+ while s>=string_offset do {first |string_offset| strings depend on implementation!!}
+ begin if length(s)=len then
+ if str_eq_str(s,search) then
+ begin result:=s; goto found;
+ end;
+ decr(s);
+ end;
+ end;
+found:search_string:=result;
+end;
+
+@ The following routine is a variant of |make_string|. It searches
+the whole string pool for a string equal to the string currently built
+and returns a found string. Otherwise a new string is created and
+returned. Be cautious, you can not apply |flush_string| to a replaced
+string!
+
+@<Declare additional routines for string recycling@>=
+function slow_make_string : str_number;
+label exit;
+var s: str_number; {result of |search_string|}
+@!t: str_number; {new string}
+begin t:=make_string; s:=search_string(t);
+if s>0 then
+ begin flush_string; slow_make_string:=s; return;
+ end;
+slow_make_string:=t;
+exit:end;
+
+
+@* \[54] System-dependent changes.
+@z
+
+
+@x
+@* \[55] Index.
+@y
+
+@ @<Declare action procedures for use by |main_control|@>=
+
+procedure insert_src_special;
+var toklist, p, q,r : pointer;
+begin
+ if (source_filename_stack[in_open] > 0 and isnewsource (source_filename_stack[in_open]
+, line)) then begin
+ toklist := get_avail;
+ p := toklist;
+ info(p) := cs_token_flag+frozen_special;
+ r := get_avail; link(p):=r; p := link(p);
+ info(p) := left_brace_token+"{";
+ q := str_toks (makesrcspecial (source_filename_stack[in_open], line));
+ link(p) := link(temp_token_head);
+ p := q;
+ r := get_avail; link(p):=r; p := link(p);
+ info(p) := right_brace_token+"}";
+ ins_list (toklist);
+ remembersourceinfo (source_filename_stack[in_open], line);
+ end;
+end;
+
+procedure append_src_special;
+var q : pointer;
+begin
+ if (source_filename_stack[in_open] > 0 and isnewsource (source_filename_stack[in_open]
+, line)) then begin
+ new_whatsit (special_node);
+ write_stream(tail) := 0;
+ q:=get_avail; def_ref := q;
+ token_ref_count(def_ref) := null;
+ q := str_toks (makesrcspecial (source_filename_stack[in_open], line));
+ link(def_ref) := link(temp_head);
+ write_tokens(tail) := def_ref;
+ remembersourceinfo (source_filename_stack[in_open], line);
+ end;
+end;
+
+@ This function used to be in pdftex, but is useful in tex too.
+
+@p function get_nullstr: str_number;
+begin
+ get_nullstr := "";
+end;
+
+@* \[55] Index.
+@z
+
diff --git a/Build/source/texk/web2c/luatexdir/luatex.defines b/Build/source/texk/web2c/luatexdir/luatex.defines
new file mode 100644
index 00000000000..b2d296671dc
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luatex.defines
@@ -0,0 +1,560 @@
+{
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id $
+}
+
+{ luatex.defines: additions for luaTeX }
+
+@define function new_node();
+@define function new_glyph_node;
+@define procedure flush_node();
+@define function copy_node();
+@define procedure couple_nodes();
+@define function copy_node_list();
+@define procedure flush_node_list();
+@define function string_to_pseudo();
+@define function do_set_attribute();
+@define function copy_attribute_list();
+@define procedure add_node_attr_ref();
+@define procedure replace_attribute_list();
+@define procedure update_attribute_cache;
+
+@define function new_span_node();
+
+@define function sizeof();
+@define procedure memset();
+@define function realloc();
+@define function malloc();
+@define function voidcast();
+@define function fixmemcast();
+@define function varmemcast();
+@define type void;
+@define procedure init_node_mem();
+@define procedure print_node_mem_stats();
+@define procedure dump_node_mem;
+@define procedure undump_node_mem;
+@define function visible_last_node_type();
+@define var NULL;
+@define var varmem;
+@define var var_mem_max;
+@define procedure check_buffer_overflow();
+@define procedure check_pool_overflow();
+
+@define function new_ligkern();
+@define function make_lang_data();
+@define procedure ext_do_line_break();
+@define procedure initialize_active;
+@define var active_node_size;
+@define var prev_char_p;
+@define function cur_break();
+@define function break_node();
+
+@define function divide_scaled();
+@define function divide_scaled_n();
+
+@define procedure new_hyphenation();
+@define procedure load_tex_hyphenation();
+@define procedure load_tex_patterns();
+@define procedure dump_language_data;
+@define procedure undump_language_data;
+@define function insert_discretionary();
+@define procedure set_pre_hyphen_char();
+@define procedure set_post_hyphen_char();
+@define function get_pre_hyphen_char();
+@define function get_post_hyphen_char();
+
+{ macros from luatex.h }
+@define function pdf_char_marked();
+@define function tex_b_open_in();
+@define function vf_b_open_in ();
+@define procedure pdf_mark_char();
+@define procedure writepdf();
+@define procedure pdfassert();
+
+@define procedure luacall();
+@define procedure luatokencall();
+@define procedure closelua();
+
+@define function luacstring_input;
+@define function luacstring_penultimate;
+@define function luacstring_detokenized;
+@define function luacstring_cattable;
+@define function luacstring_defaultcattable;
+@define function luacstring_simple;
+@define procedure luacstring_close();
+@define procedure luacstring_start();
+
+{ for callbacks }
+
+@define function run_callback();
+@define function run_and_save_callback();
+@define function run_saved_callback();
+@define procedure destroy_saved_callback();
+@define function callback_defined();
+@define function callbackluaid();
+@define var find_write_file_callback;
+@define var find_output_file_callback;
+@define var find_image_file_callback;
+@define var find_format_file_callback;
+@define var find_read_file_callback;
+@define var open_read_file_callback;
+@define var find_ocp_file_callback;
+@define var read_ocp_file_callback;
+@define var find_vf_file_callback;
+@define var read_vf_file_callback;
+@define var find_data_file_callback;
+@define var read_data_file_callback;
+@define var find_font_file_callback;
+@define var read_font_file_callback;
+@define var find_map_file_callback;
+@define var read_map_file_callback;
+@define var find_enc_file_callback;
+@define var read_enc_file_callback;
+@define var find_type1_file_callback;
+@define var read_type1_file_callback;
+@define var find_truetype_file_callback;
+@define var read_truetype_file_callback;
+@define var find_opentype_file_callback;
+@define var read_opentype_file_callback;
+@define var find_sfd_file_callback;
+@define var read_sfd_file_callback;
+@define var find_pk_file_callback;
+@define var read_pk_file_callback;
+@define var show_error_hook_callback;
+@define var process_input_buffer_callback;
+@define var start_page_number_callback;
+@define var stop_page_number_callback;
+@define var start_run_callback;
+@define var stop_run_callback;
+@define var define_font_callback;
+@define var token_filter_callback;
+@define var pre_linebreak_filter_callback;
+@define var post_linebreak_filter_callback;
+@define var buildpage_filter_callback;
+@define var hyphenate_callback;
+
+@define function lua_hyphenate_callback();
+
+@define procedure get_saved_lua_boolean();
+@define procedure get_saved_lua_number();
+@define procedure get_saved_lua_string();
+@define procedure get_lua_boolean();
+@define procedure get_lua_number();
+@define procedure get_lua_string();
+
+@define procedure get_token_lua;
+@define procedure lua_node_filter();
+@define procedure lua_node_filter_s();
+@define function lua_hpack_filter();
+@define function lua_vpack_filter();
+
+{ bits for extended char code access }
+
+@define function get_math_code();
+@define procedure set_math_code();
+@define function get_del_code_a();
+@define function get_del_code_b();
+@define procedure set_del_code();
+
+@define procedure unsave_math_codes ();
+@define procedure initialize_math_codes;
+@define procedure dump_math_codes;
+@define procedure undump_math_codes;
+
+@define function get_lc_code();
+@define procedure set_lc_code();
+
+@define function get_uc_code();
+@define procedure set_uc_code();
+
+@define function get_sf_code();
+@define procedure set_sf_code();
+
+@define function get_cat_code();
+@define procedure set_cat_code();
+
+@define function valid_catcode_table ();
+@define procedure clear_catcode_stack ();
+@define procedure copy_cat_codes ();
+@define procedure initex_cat_codes ();
+@define procedure unsave_cat_codes ();
+@define procedure unsave_text_codes ();
+@define procedure initializetextcodes;
+@define procedure dumptextcodes;
+@define procedure undumptextcodes;
+
+@define procedure dumpluacregisters;
+@define procedure undumpluacregisters;
+
+@define function do_a_open_out();
+@define function do_b_open_out();
+
+@define procedure flush_loggable_info;
+
+@define var extra_version_info;
+
+{ bits and pieces from aleph }
+
+@define procedure btestin ;
+
+@define function readtfmfile();
+@define function next_vf_byte;
+@define function read_vf_file();
+@define function read_ocp_file();
+@define function read_data_file();
+
+@define var ocp_tables;
+
+@define procedure allocate_ocp_table ();
+@define procedure dump_ocp_table ();
+@define procedure undump_ocp_table ();
+@define procedure run_external_ocp ();
+
+@define function loadpoolstrings();
+
+{ 'texfont' library definitions }
+
+@define procedure dump_font ();
+@define procedure undump_font ();
+@define function is_valid_font();
+@define function copy_font();
+@define function scale_font();
+@define function max_font_id;
+@define procedure set_max_font_id();
+
+@define function font_name();
+@define function font_area();
+@define function get_font_name();
+@define function get_font_area();
+@define function font_bc();
+@define function font_ec();
+
+@define function tex_font_name();
+@define function tex_font_area();
+@define procedure set_tex_font_name();
+
+@define procedure set_pdf_font_size();
+@define procedure set_pdf_font_num();
+@define procedure set_pdf_font_blink();
+@define procedure set_pdf_font_elink();
+@define procedure set_pdf_font_expand_ratio();
+@define procedure set_pdf_font_shrink();
+@define procedure set_pdf_font_stretch();
+@define procedure set_pdf_font_step();
+@define procedure set_pdf_font_auto_expand();
+@define procedure set_pdf_font_attr();
+
+@define function pdf_font_size();
+@define function pdf_font_num();
+@define function pdf_font_blink();
+@define function pdf_font_elink();
+@define function pdf_font_expand_ratio();
+@define function pdf_font_shrink();
+@define function pdf_font_stretch();
+@define function pdf_font_step();
+@define function pdf_font_auto_expand();
+@define function pdf_font_attr();
+
+@define function cmp_font_area();
+@define function cmp_font_name();
+@define function font_shareable();
+
+@define function fontglue();
+@define procedure setfontglue();
+
+@define function font_check_0();
+@define function font_check_1();
+@define function font_check_2();
+@define function font_check_3();
+
+@define function font_size();
+@define function font_slant();
+@define function font_extend();
+@define function font_used();
+@define procedure set_font_used();
+@define function font_touched();
+@define procedure set_font_touched();
+
+@define function font_dsize();
+@define function font_natural_dir();
+
+@define function font_params();
+@define function font_param();
+@define procedure set_font_params();
+@define procedure set_font_param();
+@define function slant();
+@define function quad();
+@define function x_height();
+@define function space();
+@define function extra_space();
+@define function space_stretch();
+@define function space_shrink();
+
+@define function font_kerns();
+@define function font_kern_sc();
+@define procedure adjust_font_kern();
+
+@define function font_italics();
+@define function font_italic();
+@define procedure set_font_italic();
+
+@define function has_lig();
+@define function has_kern();
+
+@define type liginfo;
+
+@define function get_ligature();
+@define function is_valid_ligature();
+@define function lig_type();
+@define function lig_replacement();
+
+@define function is_ligature();
+@define function is_leftboundary();
+@define function is_rightboundary();
+
+@define procedure set_to_character();
+@define procedure set_to_glyph();
+@define procedure set_is_leftghost();
+@define procedure set_is_rightghost();
+
+@define var non_boundarychar;
+
+@define function ext_top();
+@define function ext_mid();
+@define function ext_bot();
+@define function ext_rep();
+
+@define var ext_tag;
+@define var list_tag;
+
+@define var virtual_font_type;
+@define function font_type();
+
+@define function font_format();
+@define function char_index();
+@define function font_cidregistry();
+@define function font_encodingbytes();
+
+@define function font_map();
+@define procedure set_font_map();
+
+
+@define function hyphen_char();
+@define function skew_char();
+@define procedure set_hyphen_char();
+@define procedure set_skew_char();
+@define function char_exists();
+
+@define function char_used();
+@define function char_name();
+@define function char_width();
+@define function char_height();
+@define function char_depth();
+@define function char_italic();
+@define function char_tag();
+@define procedure set_char_tag();
+@define function char_remainder();
+
+@define function char_info_short();
+
+@define function has_packet();
+@define procedure do_vf_packet();
+@define function expand_font_name();
+@define function auto_expand_font();
+@define procedure vf_expand_local_fonts();
+@define function letter_space_font();
+@define function read_font_info();
+
+@define function get_tag_code();
+@define function get_lp_code();
+@define function get_rp_code();
+@define function get_ef_code();
+@define procedure set_tag_code();
+@define procedure set_lp_code();
+@define procedure set_rp_code();
+@define procedure set_ef_code();
+
+@define function test_no_ligatures();
+@define procedure set_no_ligatures();
+
+@define function get_kern();
+@define function charkern();
+
+{ functions from mapfile.c }
+@define function hasfmentry();
+@define procedure checkextfm();
+@define procedure pdfmapfile();
+@define procedure pdfmapline();
+@define procedure pdf_init_map_file();
+
+@define procedure writefontstuff;
+
+{ functions from utils.c }
+@define procedure escapehex();
+@define procedure escapename();
+@define procedure escapestring();
+@define function ext_xn_over_d();
+@define procedure getcreationdate;
+@define function get_resname_prefix;
+@define function makecstring();
+
+@define procedure append_string();
+@define procedure matchstrings();
+@define procedure libpdffinish;
+@define procedure makepdftexbanner;
+@define procedure printcreationdate;
+@define procedure printmoddate;
+@define procedure print_ID();
+@define procedure set_job_id();
+@define procedure unescapehex();
+@define procedure write_stream_length();
+@define procedure removepdffile;
+@define procedure garbagewarning;
+@define function newcolorstack();
+@define function colorstackset();
+@define function colorstackpush();
+@define function colorstackpop();
+@define function colorstackcurrent();
+@define function colorstackused;
+@define function colorstackskippagestart();
+@define procedure checkpdfsave();
+@define procedure checkpdfrestore();
+@define procedure pdfshipoutbegin();
+@define procedure pdfshipoutend();
+@define procedure pdfsetmatrix();
+@define procedure matrixtransformpoint();
+@define procedure matrixtransformrect();
+@define function matrixused;
+@define procedure matrixrecalculate();
+@define function getllx;
+@define function getlly;
+@define function geturx;
+@define function getury;
+
+{functions from texpdf.c }
+
+@define procedure pdf_print_char();
+@define procedure pdf_print();
+@define procedure pdf_print_int();
+@define procedure pdf_print_real();
+@define procedure pdf_print_str();
+
+{functions from textoken.c }
+
+@define function get_next;
+
+{ functions from vfpacket.c }
+@define function new_vf_packet();
+@define function packet_byte;
+@define procedure start_packet();
+@define procedure store_packet();
+
+{ functions from writefont.c }
+@define procedure do_pdf_font();
+
+{ functions from writeimg.c }
+@define function check_image_b();
+@define function check_image_c();
+@define function check_image_i();
+@define function epdf_orig_x();
+@define function epdf_orig_y();
+@define function image_pages();
+@define function image_colordepth();
+@define function image_index();
+@define function image_width();
+@define function image_height();
+@define function image_depth();
+@define function image_objnum();
+@define function image_imgnum();
+@define function is_pdf_image();
+@define function read_image();
+@define function new_image_entry;
+@define procedure update_image_procset();
+@define procedure write_image();
+@define procedure scale_image();
+@define procedure set_image_dimensions();
+@define procedure set_image_index();
+@define procedure out_image();
+
+{ functions from limglib.c }
+@define procedure lua_setximage();
+
+{ functions from writet3.c }
+@define function get_pk_char_width();
+
+{ functions from writezip.c }
+@define procedure write_zip();
+
+{ functions from avlstuff.c }
+@define procedure avl_put_obj();
+@define function avl_find_obj();
+
+{ functions from tounicode.c }
+@define procedure def_tounicode();
+
+{ end of luatex.defines }
+
+{texmf.defines}
+
+@define type two_halves;
+@define type four_quarters;
+
+@define function input_ln ();
+@define function is_new_source ();
+@define function get_job_name ();
+@define function make_full_name_string;
+
+@define procedure seconds_and_micros ();
+@define function ocp_open_in ();
+@define function open_in_name_ok ();
+@define function open_out_name_ok ();
+
+@define function w_open_in ();
+@define function w_open_out ();
+
+@define procedure dump_hh ();
+@define procedure dump_int ();
+@define procedure dump_things ();
+@define procedure dump_wd ();
+
+@define procedure undump_hh ();
+@define procedure undump_int ();
+@define procedure undump_qqqq ();
+@define procedure undump_things ();
+@define procedure undump_checked_things ();
+@define procedure undump_upper_check_things ();
+@define procedure undump_wd ();
+@define procedure w_close ();
+
+{common.defines}
+
+@define type memory_word; {for gftodvi, TeX, and Metafont}
+
+@define function a_open_in ();
+@define procedure a_close ();
+@define procedure b_close ();
+@define function a_open_out ();
+@define function b_open_out ();
+
+@define procedure write_dvi ();
+@define procedure write_pdf ();
+@define procedure write_ln ();
+
+@define procedure recorder_change_filename ();
diff --git a/Build/source/texk/web2c/luatexdir/luatex.h b/Build/source/texk/web2c/luatexdir/luatex.h
new file mode 100644
index 00000000000..aef2f355396
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luatex.h
@@ -0,0 +1,173 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id $
+*/
+
+/* some code array functions */
+
+extern void set_math_code (integer n, halfword v, quarterword grouplevel);
+extern halfword get_math_code (integer n);
+
+extern void set_del_code (integer n, halfword v, halfword w, quarterword grouplevel);
+extern halfword get_del_code_a (integer n);
+extern halfword get_del_code_b (integer n);
+
+extern void unsavemathcodes (quarterword grouplevel);
+extern void initializemathcodes ();
+extern void dumpmathcodes ();
+extern void undumpmathcodes ();
+
+extern void set_lc_code (integer n, halfword v, quarterword grouplevel);
+extern halfword get_lc_code (integer n);
+extern void set_uc_code (integer n, halfword v, quarterword grouplevel);
+extern halfword get_uc_code (integer n);
+extern void set_sf_code (integer n, halfword v, quarterword grouplevel);
+extern halfword get_sf_code (integer n);
+extern void set_cat_code (integer h, integer n, halfword v, quarterword grouplevel);
+extern halfword get_cat_code (integer h, integer n);
+
+extern void unsavetextcodes (quarterword grouplevel);
+extern void unsavecatcodes (integer h,quarterword grouplevel);
+extern void copy_cat_codes (int from, int to);
+extern void initex_cat_codes (int h);
+extern void clearcatcodestack (integer h);
+extern boolean validcatcodetable (int h);
+
+extern void initializetextcodes ();
+extern void dumptextcodes ();
+extern void undumptextcodes ();
+
+typedef enum {
+ escape, left_brace, right_brace, math_shift,
+ tab_mark, car_ret, mac_param, sup_mark,
+ sub_mark, ignore, spacer, letter,
+ other_char, active_char, comment, invalid_char } cat_codes;
+
+
+extern void do_vf(internal_font_number tmp_f);
+
+extern int readbinfile(FILE *f, unsigned char **b, integer *s);
+
+#define read_tfm_file readbinfile
+#define read_vf_file readbinfile
+#define read_ocp_file readbinfile
+#define read_data_file readbinfile
+
+extern int **ocp_tables;
+
+extern void allocate_ocp_table();
+extern void dump_ocp_table();
+extern void undump_ocp_table();
+
+extern void run_external_ocp();
+extern void b_test_in();
+
+/* Additions to texmfmp.h for pdfTeX */
+
+/* mark a char in font */
+#define pdf_mark_char(f,c) set_char_used(f,c,true)
+
+/* test whether a char in font is marked */
+#define pdf_char_marked char_used
+
+/* writepdf() always writes by fwrite() */
+#define write_pdf(a, b) \
+ (void) fwrite ((char *) &pdf_buf[a], sizeof (pdf_buf[a]), \
+ (int) ((b) - (a) + 1), pdf_file)
+
+#define tex_b_open_in(f) \
+ open_input (&(f), kpse_tex_format, FOPEN_RBIN_MODE)
+#define ovf_b_open_in(f) \
+ open_input (&(f), kpse_ovf_format, FOPEN_RBIN_MODE)
+#define vf_b_open_in(f) \
+ open_input (&(f), kpse_vf_format, FOPEN_RBIN_MODE)
+
+extern int open_outfile(FILE **f, char *name, char *mode);
+
+#define do_a_open_out(f) open_outfile(&(f),(char *)(nameoffile+1),FOPEN_W_MODE)
+#define do_b_open_out(f) open_outfile(&(f),(char *)(nameoffile+1),FOPEN_WBIN_MODE)
+
+#define pdfassert assert
+#define voidcast(a) (void *)(a)
+#define varmemcast(a) (memory_word *)(a)
+#define fixmemcast(a) (smemory_word *)(a)
+extern volatile memory_word *varmem;
+extern halfword var_mem_min;
+extern halfword var_mem_max;
+extern halfword get_node (integer s);
+extern void free_node (halfword p, integer s) ;
+extern void init_node_mem (integer r, integer s) ;
+extern void dump_node_mem (void) ;
+extern void undump_node_mem (void);
+
+
+typedef enum {
+ find_write_file_callback = 1,
+ find_output_file_callback,
+ find_image_file_callback,
+ find_format_file_callback,
+ find_read_file_callback, open_read_file_callback,
+ find_ocp_file_callback, read_ocp_file_callback,
+ find_vf_file_callback, read_vf_file_callback,
+ find_data_file_callback, read_data_file_callback,
+ find_font_file_callback, read_font_file_callback,
+ find_map_file_callback, read_map_file_callback,
+ find_enc_file_callback, read_enc_file_callback,
+ find_type1_file_callback, read_type1_file_callback,
+ find_truetype_file_callback, read_truetype_file_callback,
+ find_opentype_file_callback, read_opentype_file_callback,
+ find_sfd_file_callback, read_sfd_file_callback,
+ find_pk_file_callback, read_pk_file_callback,
+ show_error_hook_callback,
+ process_input_buffer_callback,
+ start_page_number_callback, stop_page_number_callback,
+ start_run_callback, stop_run_callback,
+ define_font_callback,
+ token_filter_callback,
+ pre_output_filter_callback,
+ buildpage_filter_callback,
+ hpack_filter_callback, vpack_filter_callback,
+ char_exists_callback,
+ hyphenate_callback,
+ ligaturing_callback,
+ kerning_callback,
+ pre_linebreak_filter_callback,
+ linebreak_filter_callback,
+ post_linebreak_filter_callback,
+ total_callbacks } callback_callback_types;
+
+extern int callback_set[];
+
+#define callback_defined(a) callback_set[a]
+
+extern int run_callback (int i, char *values, ...);
+extern int run_saved_callback (int i, char *name, char *values, ...);
+extern int run_and_save_callback (int i, char *values, ...);
+extern void destroy_saved_callback (int i);
+
+extern void get_saved_lua_boolean (int i, char *name, boolean *target);
+extern void get_saved_lua_number (int i, char *name, integer *target);
+extern void get_saved_lua_string (int i, char *name, char **target);
+
+extern void get_lua_boolean (char *table, char *name, boolean *target);
+extern void get_lua_number (char *table, char *name, integer *target);
+extern void get_lua_string (char *table, char *name, char **target);
+
+#include <luatexdir/ptexlib.h>
diff --git a/Build/source/texk/web2c/luatexdir/luatex.mk b/Build/source/texk/web2c/luatexdir/luatex.mk
new file mode 100644
index 00000000000..ed745cd261d
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luatex.mk
@@ -0,0 +1,170 @@
+# Makefile fragment for pdfeTeX and web2c. --infovore@xs4all.nl. Public domain.
+# This fragment contains the parts of the makefile that are most likely to
+# differ between releases of pdfeTeX.
+
+# We build luatex
+luatex = @LTEX@ luatex
+luatexdir = luatexdir
+
+# libz
+ZLIBDIR=../../libs/zlib
+ZLIBSRCDIR=$(srcdir)/$(ZLIBDIR)
+# libpng
+LIBPNGDIR=../../libs/libpng
+LIBPNGSRCDIR=$(srcdir)/$(LIBPNGDIR)
+# libxpdf
+LIBXPDFDIR=../../libs/xpdf
+LIBXPDFSRCDIR=$(srcdir)/$(LIBXPDFDIR)
+# libobsdcompa
+LIBOBSDCOMPATDIR=../../libs/obsdcompat
+LIBOBSDCOMPATFSRCDIR=$(srcdir)/$(LIBOBSDCOMPATDIR)
+
+XCPPFLAGS=-I$(LIBOBSDCOMPATDIR) -I$(LIBOBSDCOMPATDIR)/.. -I$(LIBOBSDCOMPATFSRCDIR) -I$(LIBOBSDCOMPATFSRCDIR)/.. -I$(ZLIBSRCDIR) -I$(LIBPNGSRCDIR) -I$(LIBXPDFSRCDIR) -Dextra_version_info=`date +-%Y%m%d%H`
+
+Makefile: $(srcdir)/$(luatexdir)/luatex.mk
+
+# luatex_bin = luatex ttf2afm pdftosrc
+luatex_bin = luatex
+linux_build_dir = $(HOME)/luatex/build/linux/texk/web2c
+
+
+# Extract luatex version
+$(luatexdir)/luatex.version: $(srcdir)/$(luatexdir)/luatex.web
+ test -d $(luatexdir) || mkdir $(luatexdir)
+ grep '^@d luatex_version_string==' $(srcdir)/$(luatexdir)/luatex.web \
+ | sed "s/^.*=='//;s/' .*$$//" \
+ >$(luatexdir)/luatex.version
+
+# The C sources.
+luatex_c = luatexini.c luatex0.c luatex1.c luatex2.c luatex3.c
+luatex_o = luatexini.o luatex0.o luatex1.o luatex2.o luatex3.o luatexextra.o loadpool.o
+
+# Making luatex
+luatex: luatexd.h $(luatex_o) $(luatexextra_o) $(luatexlibsdep)
+ @CXXHACKLINK@ $(luatex_o) $(luatexextra_o) $(luatexlibs) $(socketlibs) @CXXHACKLDLIBS@ @CXXLDEXTRA@
+
+# C file dependencies.
+$(luatex_c) luatexcoerce.h luatexd.h: luatex.p $(web2c_texmf) $(srcdir)/$(luatexdir)/luatex.defines $(srcdir)/$(luatexdir)/luatex.h
+ $(web2c) luatex
+luatexextra.c: $(luatexdir)/luatexextra.h lib/texmfmp.c
+ test -d $(luatexdir) || mkdir $(luatexdir)
+ sed s/TEX-OR-MF-OR-MP/luatex/ $(srcdir)/lib/texmfmp.c >$@
+$(luatexdir)/luatexextra.h: $(luatexdir)/luatexextra.in $(luatexdir)/luatex.version
+ test -d $(luatexdir) || mkdir $(luatexdir)
+ sed -e s/LUATEX-VERSION/`cat $(luatexdir)/luatex.version`/ \
+ $(srcdir)/$(luatexdir)/luatexextra.in >$@
+loadpool.c: luatex.pool $(luatexdir)/makecpool
+ $(native)/$(luatexdir)/makecpool luatex.pool luatexdir/ptexlib.h > loadpool.c
+
+# luatangle we need a private version of tangle
+
+luatangle: luatangle.o
+ $(kpathsea_link) luatangle.o $(LOADLIBES)
+
+luatangle.c luatangle.h: luatangle.p
+ $(web2c) luatangle
+
+luatangle.p: tangle $(srcdir)/$(luatexdir)/luatangle.web $(srcdir)/$(luatexdir)/luatangle.ch
+ $(TANGLE) $(srcdir)/$(luatexdir)/luatangle.web $(srcdir)/$(luatexdir)/luatangle.ch
+
+# Tangling
+luatex.p luatex.pool: luatangle $(srcdir)/$(luatexdir)/luatex.web $(srcdir)/$(luatexdir)/luatex.ch
+ $(native)/luatangle --underlines $(srcdir)/$(luatexdir)/luatex.web $(srcdir)/$(luatexdir)/luatex.ch
+
+# Sources for luatex.ch:
+#luatex_ch_srcs = $(srcdir)/$(luatexdir)/luatex.web \
+# $(srcdir)/$(luatexdir)/lua.ch \
+# $(srcdir)/$(luatexdir)/lua.ch0
+
+# Rules:
+#luatex.ch: $(TIE) $(luatex_ch_srcs)
+# $(TIE) -c luatex.ch $(luatex_ch_srcs)
+
+# for developing only
+#luatex-org.web: $(TIE) $(luatex_ch_srcs_org)
+# $(TIE) -m $@ $(luatex_ch_srcs_org)
+#luatex-all.web: $(TIE) $(srcdir)/$(luatexdir)/luatex.web luatex.ch
+# $(TIE) -m $@ $(srcdir)/$(luatexdir)/luatex.web luatex.ch
+#luatex-all.tex: luatex-all.web
+# $(WEAVE) luatex-all.web
+# echo -e '1s/ webmac/ pdfwebmac/\nw\nq' | ed $@ >/dev/null 2>&1
+#luatex-all.pdf: luatex-all.tex
+# $(luatex) luatex-all.tex
+
+check: @PETEX@ luatex-check
+luatex-check: luatex luatex.fmt
+
+clean:: luatex-clean
+luatex-clean:
+ $(LIBTOOL) --mode=clean $(RM) luatex
+ rm -f $(luatex_o) $(luatex_c) luatexextra.c luatexcoerce.h
+ rm -f $(luatexdir)/luatexextra.h
+ rm -f luatexd.h luatex.p luatex.pool luatex.ch strpool.c
+ rm -f luatex.fmt luatex.log
+
+# Dumps
+all_luafmts = @FMU@ luatex.fmt $(luafmts)
+
+dumps: @LTEX@ luafmts
+luafmts: $(all_luafmts)
+
+luafmtdir = $(web2cdir)/luatex
+$(luafmtdir)::
+ $(SHELL) $(top_srcdir)/../mkinstalldirs $(luafmtdir)
+
+luatex.fmt: luatex
+ $(dumpenv) $(MAKE) progname=luatex files="etex.src plain.tex cmr10.tfm" prereq-check
+ $(dumpenv) ./luatex --progname=luatex --jobname=luatex --ini \*\\pdfoutput=1\\input etex.src \\dump </dev/null
+
+#
+# Installation.
+install-luatex: install-luatex-exec
+install-luatex-exec: install-luatex-links
+
+# The actual binary executables and pool files.
+install-programs: @PETEX@ install-luatex-programs
+install-luatex-programs: $(luatex) $(bindir)
+ for p in luatex; do $(INSTALL_LIBTOOL_PROG) $$p $(bindir); done
+
+install-links: @PETEX@ install-luatex-links
+install-luatex-links: install-luatex-programs
+ #cd $(bindir) && (rm -f luainitex luavirtex; \
+ # $(LN) luatex luainitex; $(LN) luatex luavirtex)
+
+install-fmts: @PETEX@ install-luatex-fmts
+install-luatex-fmts: luafmts $(luafmtdir)
+ luafmts="$(all_luafmts)"; \
+ for f in $$luafmts; do $(INSTALL_DATA) $$f $(luafmtdir)/$$f; done
+ luafmts="$(luafmts)"; \
+ for f in $$luafmts; do base=`basename $$f .fmt`; \
+ (cd $(bindir) && (rm -f $$base; $(LN) luatex $$base)); done
+
+#
+# luatex binaries archive
+luatexbin:
+ $(MAKE) $(luatex_bin)
+
+luatex-cross:
+ $(MAKE) web2c-cross
+ $(MAKE) luatexbin
+
+web2c-cross: $(web2c_programs)
+ @if test ! -x $(linux_build_dir)/luatangle; then echo Error: linux_build_dir not ready; exit -1; fi
+ rm -f web2c/fixwrites web2c/splitup web2c/web2c
+ cp -f $(linux_build_dir)/web2c/fixwrites web2c
+ cp -f $(linux_build_dir)/web2c/splitup web2c
+ cp -f $(linux_build_dir)/web2c/web2c web2c
+ touch web2c/fixwrites web2c/splitup web2c/web2c
+ $(MAKE) tangleboot && rm -f tangleboot && \
+ cp -f $(linux_build_dir)/tangleboot . && touch tangleboot
+ $(MAKE) ctangleboot && rm -f ctangleboot && \
+ cp -f $(linux_build_dir)/ctangleboot . && touch ctangleboot
+ $(MAKE) ctangle && rm -f ctangle && \
+ cp -f $(linux_build_dir)/ctangle . && touch ctangle
+ $(MAKE) tie && rm -f tie && \
+ cp -f $(linux_build_dir)/tie . && touch tie
+ $(MAKE) luatangle && rm -f luatangle && \
+ cp -f $(linux_build_dir)/luatangle . && touch luatangle
+
+# vim: set noexpandtab
+# end of luatex.mk
diff --git a/Build/source/texk/web2c/luatexdir/luatex.web b/Build/source/texk/web2c/luatexdir/luatex.web
new file mode 100644
index 00000000000..b1c977706ff
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luatex.web
@@ -0,0 +1,35760 @@
+% Copyright (c) 2007 Hartmut Henkel, Taco Hoekwater
+
+% This file is part of luaTeX.
+
+% luaTeX is free software; you can redistribute it and/or modify it under the
+% terms of the GNU General Public License as published by the Free Software
+% Foundation; either version 2 of the License, or (at your option) any later
+% version.
+
+% luaTeX is distributed in the hope that it will be useful, but WITHOUT ANY
+% WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+% A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+% You should have received a copy of the GNU General Public License
+% along with luaTeX; if not, write to the Free Software Foundation, Inc.,
+% 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+% pdfTeX is copyright (C) 1996-2006 Han The Thanh, <thanh@@pdftex.org>.
+% e-TeX is copyright (C) 1994,98 by Peter Breitenlohner.
+
+% This program is directly derived from Donald E. Knuth's TeX;
+% the change history which follows and the reward offered for finders of
+% bugs refer specifically to TeX; they should not be taken as referring
+% to e-TeX, although the change history is relevant in that it
+% demonstrates the evolutionary path followed. This program is not TeX;
+% that name is reserved strictly for the program which is the creation
+% and sole responsibility of Professor Knuth.
+
+% Version 0 was released in September 1982 after it passed a variety of tests.
+% Version 1 was released in November 1983 after thorough testing.
+% Version 1.1 fixed ``disappearing font identifiers'' et alia (July 1984).
+% Version 1.2 allowed `0' in response to an error, et alia (October 1984).
+% Version 1.3 made memory allocation more flexible and local (November 1984).
+% Version 1.4 fixed accents right after line breaks, et alia (April 1985).
+% Version 1.5 fixed \the\toks after other expansion in \edefs (August 1985).
+% Version 2.0 (almost identical to 1.5) corresponds to "Volume B" (April 1986).
+% Version 2.1 corrected anomalies in discretionary breaks (January 1987).
+% Version 2.2 corrected "(Please type...)" with null \endlinechar (April 1987).
+% Version 2.3 avoided incomplete page in premature termination (August 1987).
+% Version 2.4 fixed \noaligned rules in indented displays (August 1987).
+% Version 2.5 saved cur_order when expanding tokens (September 1987).
+% Version 2.6 added 10sp slop when shipping leaders (November 1987).
+% Version 2.7 improved rounding of negative-width characters (November 1987).
+% Version 2.8 fixed weird bug if no \patterns are used (December 1987).
+% Version 2.9 made \csname\endcsname's "relax" local (December 1987).
+% Version 2.91 fixed \outer\def\a0{}\a\a bug (April 1988).
+% Version 2.92 fixed \patterns, also file names with complex macros (May 1988).
+% Version 2.93 fixed negative halving in allocator when mem_min<0 (June 1988).
+% Version 2.94 kept open_log_file from calling fatal_error (November 1988).
+% Version 2.95 solved that problem a better way (December 1988).
+% Version 2.96 corrected bug in "Infinite shrinkage" recovery (January 1989).
+% Version 2.97 corrected blunder in creating 2.95 (February 1989).
+% Version 2.98 omitted save_for_after at outer level (March 1989).
+% Version 2.99 caught $$\begingroup\halign..$$ (June 1989).
+% Version 2.991 caught .5\ifdim.6... (June 1989).
+% Version 2.992 introduced major changes for 8-bit extensions (September 1989).
+% Version 2.993 fixed a save_stack synchronization bug et alia (December 1989).
+% Version 3.0 fixed unusual displays; was more \output robust (March 1990).
+% Version 3.1 fixed nullfont, disabled \write{\the\prevgraf} (September 1990).
+% Version 3.14 fixed unprintable font names and corrected typos (March 1991).
+% Version 3.141 more of same; reconstituted ligatures better (March 1992).
+% Version 3.1415 preserved nonexplicit kerns, tidied up (February 1993).
+% Version 3.14159 allowed fontmemsize to change; bulletproofing (March 1995).
+% Version 3.141592 fixed \xleaders, glueset, weird alignments (December 2002).
+
+
+% Although considerable effort has been expended to make the luaTeX program
+% correct and reliable, no warranty is implied; the authors disclaim any
+% obligation or liability for damages, including but not limited to
+% special, indirect, or consequential damages arising out of or in
+% connection with the use or performance of this software. This work has
+% been a ``labor of love'' and the authors hope that users enjoy it.
+
+% Here is TeX material that gets inserted after \input webmac
+\def\hang{\hangindent 3em\noindent\ignorespaces}
+\def\hangg#1 {\hang\hbox{#1 }}
+\def\textindent#1{\hangindent2.5em\noindent\hbox to2.5em{\hss#1 }\ignorespaces}
+\font\ninerm=cmr9
+\let\mc=\ninerm % medium caps for names like SAIL
+\def\PASCAL{Pascal}
+\def\pdfTeX{pdf\TeX}
+\def\pdfeTeX{pdf\eTeX}
+\def\PDF{PDF}
+\def\Aleph{Aleph}
+\def\eTeX{e\TeX}
+\def\LuaTeX{Lua\TeX}
+\def\THANH{H\`an Th\^e\llap{\raise 0.5ex\hbox{\'{}}} Th\`anh}
+\def\ph{\hbox{Pascal-H}}
+\def\pct!{{\char`\%}} % percent sign in ordinary text
+\def\grp{\.{\char'173...\char'175}}
+\font\logo=logo10 % font used for the METAFONT logo
+\def\MF{{\logo META}\-{\logo FONT}}
+\def\<#1>{$\langle#1\rangle$}
+\def\section{\mathhexbox278}
+
+\def\(#1){} % this is used to make section names sort themselves better
+\def\9#1{} % this is used for sort keys in the index via @@:sort key}{entry@@>
+
+\outer\def\N#1. \[#2]#3.{\MN#1.\vfil\eject % begin starred section
+ \def\rhead{PART #2:\uppercase{#3}} % define running headline
+ \message{*\modno} % progress report
+ \edef\next{\write\cont{\Z{\?#2]#3}{\modno}{\the\pageno}}}\next
+ \ifon\startsection{\bf\ignorespaces#3.\quad}\ignorespaces}
+\let\?=\relax % we want to be able to \write a \?
+
+\def\title{LuaTeX}
+\let\maybe=\iffalse % print only changed modules
+\def\topofcontents{\hsize 5.5in
+ \vglue 0pt plus 1fil minus 1.5in
+ \def\?##1]{\hbox to 1in{\hfil##1.\ }}
+ }
+\def\botofcontents{\vskip 0pt plus 1fil minus 1.5in}
+\pageno=3
+\def\glob{13} % this should be the section number of "<Global...>"
+\def\gglob{20, 26} % this should be the next two sections of "<Global...>"
+
+@* \[1] Introduction.
+
+This is LuaTeX, a continuation of $\pdfTeX$ and $\Aleph$. LuaTeX is a
+document compiler intended to simplify high-quality typesetting for
+many of the world's languages. It is an extension of D. E. Knuth's
+\TeX, which was designed essentially for the typesetting of languages
+using the Latin alphabet.
+
+The $\Aleph$ subsystem loosens many of the restrictions imposed by~\TeX:
+register numbers are no longer limited to 8~bits; fonts may have more
+than 256~characters; more than 256~fonts may be used; etc.
+
+The \PASCAL\ program that follows is the definition of \TeX82, a standard
+@:PASCAL}{\PASCAL@>
+@!@:TeX82}{\TeX82@>
+version of \TeX\ that is designed to be highly portable so that
+identical output will be obtainable on a great variety of computers.
+
+The main purpose of the following program is to explain the algorithms of \TeX\
+as clearly as possible. As a result, the program will not necessarily be very
+efficient when a particular \PASCAL\ compiler has translated it into a
+particular machine language. However, the program has been written so that it
+can be tuned to run efficiently in a wide variety of operating environments
+by making comparatively few changes. Such flexibility is possible because
+the documentation that follows is written in the \.{WEB} language, which is
+at a higher level than \PASCAL; the preprocessing step that converts \.{WEB}
+to \PASCAL\ is able to introduce most of the necessary refinements.
+Semi-automatic translation to other languages is also feasible, because the
+program below does not make extensive use of features that are peculiar to
+\PASCAL.
+
+A large piece of software like \TeX\ has inherent complexity that cannot
+be reduced below a certain level of difficulty, although each individual
+part is fairly simple by itself. The \.{WEB} language is intended to make
+the algorithms as readable as possible, by reflecting the way the
+individual program pieces fit together and by providing the
+cross-references that connect different parts. Detailed comments about
+what is going on, and about why things were done in certain ways, have
+been liberally sprinkled throughout the program. These comments explain
+features of the implementation, but they rarely attempt to explain the
+\TeX\ language itself, since the reader is supposed to be familiar with
+{\sl The \TeX book}.
+@.WEB@>
+@:TeXbook}{\sl The \TeX book@>
+
+@ The present implementation has a long ancestry, beginning in the summer
+of~1977, when Michael~F. Plass and Frank~M. Liang designed and coded
+a prototype
+@^Plass, Michael Frederick@>
+@^Liang, Franklin Mark@>
+@^Knuth, Donald Ervin@>
+based on some specifications that the author had made in May of that year.
+This original proto\TeX\ included macro definitions and elementary
+manipulations on boxes and glue, but it did not have line-breaking,
+page-breaking, mathematical formulas, alignment routines, error recovery,
+or the present semantic nest; furthermore,
+it used character lists instead of token lists, so that a control sequence
+like \.{\\halign} was represented by a list of seven characters. A
+complete version of \TeX\ was designed and coded by the author in late
+1977 and early 1978; that program, like its prototype, was written in the
+{\mc SAIL} language, for which an excellent debugging system was
+available. Preliminary plans to convert the {\mc SAIL} code into a form
+somewhat like the present ``web'' were developed by Luis Trabb~Pardo and
+the author at the beginning of 1979, and a complete implementation was
+created by Ignacio~A. Zabala in 1979 and 1980. The \TeX82 program, which
+@^Zabala Salelles, Ignacio Andr\'es@>
+was written by the author during the latter part of 1981 and the early
+part of 1982, also incorporates ideas from the 1979 implementation of
+@^Guibas, Leonidas Ioannis@>
+@^Sedgewick, Robert@>
+@^Wyatt, Douglas Kirk@>
+\TeX\ in {\mc MESA} that was written by Leonidas Guibas, Robert Sedgewick,
+and Douglas Wyatt at the Xerox Palo Alto Research Center. Several hundred
+refinements were introduced into \TeX82 based on the experiences gained with
+the original implementations, so that essentially every part of the system
+has been substantially improved. After the appearance of ``Version 0'' in
+September 1982, this program benefited greatly from the comments of
+many other people, notably David~R. Fuchs and Howard~W. Trickey.
+A final revision in September 1989 extended the input character set to
+eight-bit codes and introduced the ability to hyphenate words from
+different languages, based on some ideas of Michael~J. Ferguson.
+@^Fuchs, David Raymond@>
+@^Trickey, Howard Wellington@>
+@^Ferguson, Michael John@>
+
+No doubt there still is plenty of room for improvement, but the author
+is firmly committed to keeping \TeX82 ``frozen'' from now on; stability
+and reliability are to be its main virtues.
+
+On the other hand, the \.{WEB} description can be extended without changing
+the core of \TeX82 itself, and the program has been designed so that such
+extensions are not extremely difficult to make.
+The |banner| string defined here should be changed whenever \TeX\
+undergoes any modifications, so that it will be clear which version of
+\TeX\ might be the guilty party when a problem arises.
+@^extensions to \TeX@>
+@^system dependencies@>
+
+This program contains code for various features extending \TeX,
+therefore this program is called `\eTeX' and not
+`\TeX'; the official name `\TeX' by itself is reserved
+for software systems that are fully compatible with each other.
+A special test suite called the ``\.{TRIP} test'' is available for
+helping to determine whether a particular implementation deserves to be
+known as `\TeX' [cf.~Stanford Computer Science report CS1027,
+November 1984].
+
+A similar test suite called the ``\.{e-TRIP} test'' is available for
+helping to determine whether a particular implementation deserves to be
+known as `\eTeX'.
+
+@d eTeX_version_string=="2.2" {current \eTeX\ version}
+@d Omega_version_string=="1.15" { \.{\\OmegaVersion} }
+@d Aleph_version_string=="0.0" { \.{\\AlephVersion} }
+@d eTeX_version=2 { \.{\\eTeXversion} }
+@d Omega_version=1 { \.{\\Omegaversion} }
+@d Aleph_version=0 { \.{\\Alephversion} }
+@d eTeX_minor_version=1 { \.{\\eTeXminorversion} }
+@d Omega_minor_version=15 { \.{\\Omegaminorversion} }
+@d Aleph_minor_version=0 { \.{\\Alephminorversion} }
+@d eTeX_revision==".2" { \.{\\eTeXrevision} }
+@d Omega_revision==".15" { \.{\\Omegarevision} }
+@d Aleph_revision==".0" { \.{\\Alephrevision} }
+@#
+@d pdftex_version==200 { \.{\\pdftexversion} }
+@d pdftex_revision=="0" { \.{\\pdftexrevision} }
+@d pdftex_version_string=='-2.00.0' {current \pdfTeX\ version}
+@#
+@d luatex_version==25 { \.{\\luatexversion} }
+@d luatex_revision=="1" { \.{\\luatexrevision} }
+@d luatex_version_string=='snapshot-0.25.1' {current \LuaTeX\ version}
+@d luatex_date_info==-extra_version_info { the compile date is negated }
+@#
+@d luaTeX_banner=='This is LuaTeX, Version ',luatex_version_string,extra_version_info
+ {printed when \LuaTeX\ starts}
+@#
+@d banner==luaTeX_banner
+@#
+@d TEX==ETEX {change program name into |ETEX|}
+
+@ Different \PASCAL s have slightly different conventions, and the present
+@!@:PASCAL H}{\ph@>
+program expresses \TeX\ in terms of the \PASCAL\ that was
+available to the author in 1982. Constructions that apply to
+this particular compiler, which we shall call \ph, should help the
+reader see how to make an appropriate interface for other systems
+if necessary. (\ph\ is Charles Hedrick's modification of a compiler
+@^Hedrick, Charles Locke@>
+for the DECsystem-10 that was originally developed at the University of
+Hamburg; cf.\ {\sl SOFTWARE---Practice \AM\ Experience \bf6} (1976),
+29--42. The \TeX\ program below is intended to be adaptable, without
+extensive changes, to most other versions of \PASCAL, so it does not fully
+use the admirable features of \ph. Indeed, a conscious effort has been
+made here to avoid using several idiosyncratic features of standard
+\PASCAL\ itself, so that most of the code can be translated mechanically
+into other high-level languages. For example, the `\&{with}' and `\\{new}'
+features are not used, nor are pointer types, set types, or enumerated
+scalar types; there are no `\&{var}' parameters, except in the case of files
+--- \eTeX, however, does use `\&{var}' parameters for the |reverse| function;
+there are no tag fields on variant records; there are no assignments
+|real:=integer|; no procedures are declared local to other procedures.)
+
+The portions of this program that involve system-dependent code, where
+changes might be necessary because of differences between \PASCAL\ compilers
+and/or differences between
+operating systems, can be identified by looking at the sections whose
+numbers are listed under `system dependencies' in the index. Furthermore,
+the index entries for `dirty \PASCAL' list all places where the restrictions
+of \PASCAL\ have not been followed perfectly, for one reason or another.
+@!@^system dependencies@>
+@!@^dirty \PASCAL@>
+
+Incidentally, \PASCAL's standard |round| function can be problematical,
+because it disagrees with the IEEE floating-point standard.
+Many implementors have
+therefore chosen to substitute their own home-grown rounding procedure.
+
+@ The program begins with a normal \PASCAL\ program heading, whose
+components will be filled in later, using the conventions of \.{WEB}.
+@.WEB@>
+For example, the portion of the program called `\X\glob:Global
+variables\X' below will be replaced by a sequence of variable declarations
+that starts in $\section\glob$ of this documentation. In this way, we are able
+to define each individual global variable when we are prepared to
+understand what it means; we do not have to define all of the globals at
+once. Cross references in $\section\glob$, where it says ``See also
+sections \gglob, \dots,'' also make it possible to look at the set of
+all global variables, if desired. Similar remarks apply to the other
+portions of the program heading.
+
+Actually the heading shown here is not quite normal: The |program| line
+does not mention any |output| file, because \ph\ would ask the \TeX\ user
+to specify a file name if |output| were specified here.
+@^system dependencies@>
+
+@d mtype==t@&y@&p@&e {this is a \.{WEB} coding trick:}
+@f mtype==type {`\&{mtype}' will be equivalent to `\&{type}'}
+@f type==true {but `|type|' will not be treated as a reserved word}
+
+@p @t\4@>@<Compiler directives@>@/
+program TEX; {all file names are defined dynamically}
+label @<Labels in the outer block@>@/
+const @<Constants in the outer block@>@/
+mtype @<Types in the outer block@>@/
+var @<Global variables@>@/
+@#
+procedure initialize; {this procedure gets things started properly}
+ var @<Local variables for initialization@>@/
+ begin @<Initialize whatever \TeX\ might access@>@;
+ end;@#
+@t\4@>@<Basic printing procedures@>@/
+@t\4@>@<Error handling procedures@>@/
+
+@ The overall \TeX\ program begins with the heading just shown, after which
+comes a bunch of procedure declarations and function declarations.
+Finally we will get to the main program, which begins with the
+comment `|start_here|'. If you want to skip down to the
+main program now, you can look up `|start_here|' in the index.
+But the author suggests that the best way to understand this program
+is to follow pretty much the order of \TeX's components as they appear in the
+\.{WEB} description you are now reading, since the present ordering is
+intended to combine the advantages of the ``bottom up'' and ``top down''
+approaches to the problem of understanding a somewhat complicated system.
+
+@ Three labels must be declared in the main program, so we give them
+symbolic names.
+
+@d start_of_TEX=1 {go here when \TeX's variables are initialized}
+@d end_of_TEX=9998 {go here to close files and terminate gracefully}
+@d final_end=9999 {this label marks the ending of the program}
+
+@<Labels in the out...@>=
+start_of_TEX@t\hskip-2pt@>, end_of_TEX@t\hskip-2pt@>,@,final_end;
+ {key control points}
+
+@ Some of the code below is intended to be used only when diagnosing the
+strange behavior that sometimes occurs when \TeX\ is being installed or
+when system wizards are fooling around with \TeX\ without quite knowing
+what they are doing. Such code will not normally be compiled; it is
+delimited by the codewords `$|debug|\ldots|gubed|$', with apologies
+to people who wish to preserve the purity of English.
+
+Similarly, there is some conditional code delimited by
+`$|stat|\ldots|tats|$' that is intended for use when statistics are to be
+kept about \TeX's memory usage. The |stat| $\ldots$ |tats| code also
+implements diagnostic information for \.{\\tracingparagraphs} and
+\.{\\tracingpages}.
+@^debugging@>
+
+@d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging}
+@d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging}
+@f debug==begin
+@f gubed==end
+@#
+@d stat==@{ {change this to `$\\{stat}\equiv\null$' when gathering
+ usage statistics}
+@d tats==@t@>@} {change this to `$\\{tats}\equiv\null$' when gathering
+ usage statistics}
+@f stat==begin
+@f tats==end
+
+@ This program has two important variations: (1) There is a long and slow
+version called \.{INITEX}, which does the extra calculations needed to
+@.INITEX@>
+initialize \TeX's internal tables; and (2)~there is a shorter and faster
+production version, which cuts the initialization to a bare minimum.
+Parts of the program that are needed in (1) but not in (2) are delimited by
+the codewords `$|init|\ldots|tini|$'.
+
+@d init== {change this to `$\\{init}\equiv\.{@@\{}$' in the production version}
+@d tini== {change this to `$\\{tini}\equiv\.{@@\}}$' in the production version}
+@f init==begin
+@f tini==end
+
+@<Initialize whatever...@>=
+@<Set initial values of key variables@>@/
+@!init @<Initialize table entries (done by \.{INITEX} only)@>@;@+tini
+
+@ If the first character of a \PASCAL\ comment is a dollar sign,
+\ph\ treats the comment as a list of ``compiler directives'' that will
+affect the translation of this program into machine language. The
+directives shown below specify full checking and inclusion of the \PASCAL\
+debugger when \TeX\ is being debugged, but they cause range checking and other
+redundant code to be eliminated when the production system is being generated.
+Arithmetic overflow will be detected in all cases.
+@^system dependencies@>
+@^Overflow in arithmetic@>
+
+@<Compiler directives@>=
+@{@&$C-,A+,D-@} {no range check, catch arithmetic overflow, no debug overhead}
+@!debug @{@&$C+,D+@}@+ gubed {but turn everything on when debugging}
+
+@ This \TeX\ implementation conforms to the rules of the {\sl Pascal User
+@:PASCAL}{\PASCAL@>
+@^system dependencies@>
+Manual} published by Jensen and Wirth in 1975, except where system-dependent
+@^Wirth, Niklaus@>
+@^Jensen, Kathleen@>
+code is necessary to make a useful system program, and except in another
+respect where such conformity would unnecessarily obscure the meaning
+and clutter up the code: We assume that |case| statements may include a
+default case that applies if no matching label is found. Thus, we shall use
+constructions like
+$$\vbox{\halign{\ignorespaces#\hfil\cr
+|case x of|\cr
+1: $\langle\,$code for $x=1\,\rangle$;\cr
+3: $\langle\,$code for $x=3\,\rangle$;\cr
+|othercases| $\langle\,$code for |x<>1| and |x<>3|$\,\rangle$\cr
+|endcases|\cr}}$$
+since most \PASCAL\ compilers have plugged this hole in the language by
+incorporating some sort of default mechanism. For example, the \ph\
+compiler allows `|others|:' as a default label, and other \PASCAL s allow
+syntaxes like `\&{else}' or `\&{otherwise}' or `\\{otherwise}:', etc. The
+definitions of |othercases| and |endcases| should be changed to agree with
+local conventions. Note that no semicolon appears before |endcases| in
+this program, so the definition of |endcases| should include a semicolon
+if the compiler wants one. (Of course, if no default mechanism is
+available, the |case| statements of \TeX\ will have to be laboriously
+extended by listing all remaining cases. People who are stuck with such
+\PASCAL s have, in fact, done this, successfully but not happily!)
+
+@d othercases == others: {default for cases not listed explicitly}
+@d endcases == @+end {follows the default case in an extended |case| statement}
+@f othercases == else
+@f endcases == end
+
+@ The following parameters can be changed at compile time to extend or
+reduce \TeX's capacity. They may have different values in \.{INITEX} and
+in production versions of \TeX.
+@.INITEX@>
+@^system dependencies@>
+
+@<Constants...@>=
+@!buf_size=500; {maximum number of characters simultaneously present in
+ current lines of open files and in control sequences between
+ \.{\\csname} and \.{\\endcsname}; must not exceed |max_halfword|}
+@!error_line=72; {width of context lines on terminal error messages}
+@!half_error_line=42; {width of first lines of contexts in terminal
+ error messages; should be between 30 and |error_line-15|}
+@!max_print_line=79; {width of longest text lines output; should be at least 60}
+@!stack_size=200; {maximum number of simultaneous input sources}
+@!max_in_open=6; {maximum number of input files and error insertions that
+ can be going on simultaneously}
+@!param_size=60; {maximum number of simultaneous macro parameters}
+@!nest_size=40; {maximum number of semantic levels simultaneously active}
+@!max_strings=3000; {maximum number of strings; must not exceed |max_halfword|}
+@!string_vacancies=8000; {the minimum number of characters that should be
+ available for the user's control sequences and font names,
+ after \TeX's own error messages are stored}
+@!pool_size=32000; {maximum number of characters in strings, including all
+ error messages and help texts, and the names of all fonts and
+ control sequences; must exceed |string_vacancies| by the total
+ length of \TeX's own strings, which is currently about 23000}
+@!save_size=600; {space for saving values outside of current group; must be
+ at most |max_halfword|}
+@!dvi_buf_size=800; {size of the output buffer; must be a multiple of 8}
+@!expand_depth=10000; {limits recursive calls of the |expand| procedure}
+@!file_name_size=40; {file names shouldn't be longer than this}
+@!pool_name='TeXformats:TEX.POOL ';
+ {string of length |file_name_size|; tells where the string pool appears}
+@.TeXformats@>
+@!active_mem_size=50000; {number of words of |active_info| for active ocps}
+@!ocp_maxint=@"10000000;
+
+
+@ Like the preceding parameters, the following quantities can be changed
+at compile time to extend or reduce \TeX's capacity. But if they are changed,
+it is necessary to rerun the initialization program \.{INITEX}
+@.INITEX@>
+to generate new tables for the production \TeX\ program.
+One can't simply make helter-skelter changes to the following constants,
+since certain rather complex initialization
+numbers are computed from them. They are defined here using
+\.{WEB} macros, instead of being put into \PASCAL's |const| list, in order to
+emphasize this distinction.
+
+@d font_base=0 {smallest internal font number; must not be less
+ than |min_quarterword|}
+@d hash_size=2100 {maximum number of control sequences; it should be at most
+ about |(fix_mem_max-fix_mem_min)/10|}
+@d hash_prime=1777 {a prime number equal to about 85\pct! of |hash_size|}
+@d ocp_base=0 {smallest internal ocp number; must not be less
+ than |min_quarterword|}
+@d ocp_biggest=32767 {the real biggest ocp}
+@d number_ocps=ocp_biggest-ocp_base+1
+@d ocp_list_base=0 {smallest internal ocp list number; must not be less
+ than |min_quarterword|}
+@d ocp_list_biggest=32727 {the real biggest ocp list}
+@d number_ocp_lists=ocp_list_biggest-ocp_list_base+1
+@d max_active_ocp_lists=32768
+@d biggest_reg=65535 {the largest allowed register number; must be |<=max_quarterword|}
+@d number_regs=65536 {|biggest_reg+1|}
+@d number_attrs=65536 {total numbeer of attributes}
+@d biggest_mark=65535 {the largest allowed marks class; must be |<=max_quarterword|}
+@d number_marks=65536 {|biggest_mark+1|}
+{using |2^20+2^16| characters instead of |2^21| saves 286MB on the virtual memory size
+ of the running executable}
+@d biggest_char=1114111 {2097151} {the largest allowed character number; must be |<=max_halfword|}
+@d too_big_char=1114112 {2097152} {|biggest_char+1|}
+@d special_char=1114113 {2097153} {|biggest_char+2|}
+@d number_chars=1114112 {2097152} {|biggest_char+1|}
+@d number_active_chars=65536+65536 {to reduce the memory req. only two planes }
+@d string_offset=2097152
+@d font_biggest=5535 {the real biggest font}
+@d number_fonts=font_biggest-font_base+1
+@d number_math_fonts=768
+@d math_font_biggest=767
+@d biggest_lang=32767
+@d too_big_lang=32768
+@d text_size=0 {size code for the largest size in a family}
+@d script_size=256 {size code for the medium size in a family}
+@d script_script_size=512 {size code for the smallest size in a family}
+
+
+@ In case somebody has inadvertently made bad settings of the ``constants,''
+\TeX\ checks them using a global variable called |bad|.
+
+This is the first of many sections of \TeX\ where global variables are
+defined.
+
+@<Glob...@>=
+@!bad:integer; {is some ``constant'' wrong?}
+@!luainit:boolean; {are we using lua for initializations }
+@!tracefilenames:boolean; { print file open-close info? }
+
+@ Later on we will say `\ignorespaces|if X>=max_halfword then bad:=14|',
+or something similar. (We can't do that until |max_halfword| has been defined.)
+
+@<Check the ``constant'' values for consistency@>=
+bad:=0;
+if not luainit then tracefilenames:=true;
+if (half_error_line<30)or(half_error_line>error_line-15) then bad:=1;
+if max_print_line<60 then bad:=2;
+if dvi_buf_size mod 8<>0 then bad:=3;
+if hash_prime>hash_size then bad:=5;
+if max_in_open>=128 then bad:=6;
+{ |if null_list<256 then bad:=7;| } {we will want |null_list>255|}
+
+@ Labels are given symbolic names by the following definitions, so that
+occasional |goto| statements will be meaningful. We insert the label
+`|exit|' just before the `\ignorespaces|end|\unskip' of a procedure in
+which we have used the `|return|' statement defined below; the label
+`|restart|' is occasionally used at the very beginning of a procedure; and
+the label `|reswitch|' is occasionally used just prior to a |case|
+statement in which some cases change the conditions and we wish to branch
+to the newly applicable case. Loops that are set up with the |loop|
+construction defined below are commonly exited by going to `|done|' or to
+`|found|' or to `|not_found|', and they are sometimes repeated by going to
+`|continue|'. If two or more parts of a subroutine start differently but
+end up the same, the shared code may be gathered together at
+`|common_ending|'.
+
+Incidentally, this program never declares a label that isn't actually used,
+because some fussy \PASCAL\ compilers will complain about redundant labels.
+
+@d exit=10 {go here to leave a procedure}
+@d restart=20 {go here to start a procedure again}
+@d reswitch=21 {go here to start a case statement again}
+@d continue=22 {go here to resume a loop}
+@d done=30 {go here to exit a loop}
+@d done1=31 {like |done|, when there is more than one loop}
+@d done2=32 {for exiting the second loop in a long block}
+@d done3=33 {for exiting the third loop in a very long block}
+@d done4=34 {for exiting the fourth loop in an extremely long block}
+@d done5=35 {for exiting the fifth loop in an immense block}
+@d done6=36 {for exiting the sixth loop in a block}
+@d found=40 {go here when you've found it}
+@d found1=41 {like |found|, when there's more than one per routine}
+@d found2=42 {like |found|, when there's more than two per routine}
+@d not_found=45 {go here when you've found nothing}
+@d not_found1=46 {like |not_found|, when there's more than one}
+@d not_found2=47 {like |not_found|, when there's more than two}
+@d not_found3=48 {like |not_found|, when there's more than three}
+@d not_found4=49 {like |not_found|, when there's more than four}
+@d common_ending=50 {go here when you want to merge with another branch}
+
+@ Here are some macros for common programming idioms.
+
+@d incr(#) == #:=#+1 {increase a variable by unity}
+@d decr(#) == #:=#-1 {decrease a variable by unity}
+@d negate(#) == #:=-# {change the sign of a variable}
+@d loop == @+ while true do@+ {repeat over and over until a |goto| happens}
+@f loop == xclause
+ {\.{WEB}'s |xclause| acts like `\ignorespaces|while true do|\unskip'}
+@d do_nothing == pdfassert(1) {empty statement}
+@d return == goto exit {terminate a procedure call}
+@f return == nil
+@d empty=0 {symbolic name for a null constant}
+
+@* \[2] The character set.
+In order to make \TeX\ readily portable to a wide variety of
+computers, all of its input text is converted to an internal
+twenty-one-bit code that covers all of unicode, including ASCII, the
+``American Standard Code for Information Interchange.'' This
+conversion is done immediately when each character is read
+in. Conversely, characters are converted from ASCII to the user's
+external representation just before they are output to a text file.
+
+Such an internal code is relevant to users of \TeX\ primarily because it
+governs the positions of characters in the fonts. For example, the
+character `\.A' has ASCII code $65=@'101$, and when \TeX\ typesets
+this letter it specifies character number 65 in the current font.
+If that font actually has `\.A' in a different position, \TeX\ doesn't
+know what the real position is; the program that does the actual printing from
+\TeX's device-independent files is responsible for converting from ASCII to
+a particular font encoding.
+@^ASCII code@>
+
+\TeX's internal code also defines the value of constants
+that begin with a reverse apostrophe; and it provides an index to the
+\.{\\catcode}, \.{\\mathcode}, \.{\\uccode}, \.{\\lccode}, and \.{\\delcode}
+tables.
+
+@ Characters of text that have been converted to \TeX's internal form
+are said to be of type |ASCII_code|, which is a subrange of the integers.
+
+@<Types...@>=
+@!ASCII_code=0..biggest_char; {eight-bit numbers}
+@!BMP_code=0..65535; {sixteen-bit numbers}
+
+@ The original \PASCAL\ compiler was designed in the late 60s, when six-bit
+character sets were common, so it did not make provision for lowercase
+letters. Nowadays, of course, we need to deal with both capital and small
+letters in a convenient way, especially in a program for typesetting;
+so the present specification of \TeX\ has been written under the assumption
+that the \PASCAL\ compiler and run-time system permit the use of text files
+with more than 64 distinguishable characters. More precisely, we assume that
+the character set contains at least the letters and symbols associated
+with ASCII codes @'40 through @'176; all of these characters are now
+available on most computer terminals.
+
+Since we are dealing with more characters than were present in the first
+\PASCAL\ compilers, we have to decide what to call the associated data
+type. Some \PASCAL s use the original name |char| for the
+characters in text files, even though there now are more than 64 such
+characters, while other \PASCAL s consider |char| to be a 64-element
+subrange of a larger data type that has some other name.
+
+In order to accommodate this difference, we shall use the name |text_char|
+to stand for the data type of the characters that are converted to and
+from |ASCII_code| when they are input and output. We shall also assume
+that |text_char| consists of the elements |chr(first_text_char)| through
+|chr(last_text_char)|, inclusive. The following definitions should be
+adjusted if necessary.
+@^system dependencies@>
+
+@d text_char == char {the data type of characters in text files}
+@d first_text_char=0 {ordinal number of the smallest element of |text_char|}
+@d last_text_char=255 {ordinal number of the largest element of |text_char|}
+
+@<Local variables for init...@>=
+@!i:integer;
+
+@ The \TeX\ processor converts between ASCII code and
+the user's external character set by means of arrays |xord| and |xchr|
+that are analogous to \PASCAL's |ord| and |chr| functions.
+
+@<Glob...@>=
+@!xchr: array [ASCII_code] of text_char;
+ {specifies conversion of output characters}
+
+@ Since we are assuming that our \PASCAL\ system is able to read and
+write the visible characters of standard ASCII (although not
+necessarily using the ASCII codes to represent them), the following
+assignment statements initialize the standard part of the |xchr| array
+properly, without needing any system-dependent changes. On the other
+hand, it is possible to implement \TeX\ with less complete character
+sets, and in such cases it will be necessary to change something here.
+@^system dependencies@>
+
+@<Set init...@>=
+xchr[@'40]:=' ';
+xchr[@'41]:='!';
+xchr[@'42]:='"';
+xchr[@'43]:='#';
+xchr[@'44]:='$';
+xchr[@'45]:='%';
+xchr[@'46]:='&';
+xchr[@'47]:='''';@/
+xchr[@'50]:='(';
+xchr[@'51]:=')';
+xchr[@'52]:='*';
+xchr[@'53]:='+';
+xchr[@'54]:=',';
+xchr[@'55]:='-';
+xchr[@'56]:='.';
+xchr[@'57]:='/';@/
+xchr[@'60]:='0';
+xchr[@'61]:='1';
+xchr[@'62]:='2';
+xchr[@'63]:='3';
+xchr[@'64]:='4';
+xchr[@'65]:='5';
+xchr[@'66]:='6';
+xchr[@'67]:='7';@/
+xchr[@'70]:='8';
+xchr[@'71]:='9';
+xchr[@'72]:=':';
+xchr[@'73]:=';';
+xchr[@'74]:='<';
+xchr[@'75]:='=';
+xchr[@'76]:='>';
+xchr[@'77]:='?';@/
+xchr[@'100]:='@@';
+xchr[@'101]:='A';
+xchr[@'102]:='B';
+xchr[@'103]:='C';
+xchr[@'104]:='D';
+xchr[@'105]:='E';
+xchr[@'106]:='F';
+xchr[@'107]:='G';@/
+xchr[@'110]:='H';
+xchr[@'111]:='I';
+xchr[@'112]:='J';
+xchr[@'113]:='K';
+xchr[@'114]:='L';
+xchr[@'115]:='M';
+xchr[@'116]:='N';
+xchr[@'117]:='O';@/
+xchr[@'120]:='P';
+xchr[@'121]:='Q';
+xchr[@'122]:='R';
+xchr[@'123]:='S';
+xchr[@'124]:='T';
+xchr[@'125]:='U';
+xchr[@'126]:='V';
+xchr[@'127]:='W';@/
+xchr[@'130]:='X';
+xchr[@'131]:='Y';
+xchr[@'132]:='Z';
+xchr[@'133]:='[';
+xchr[@'134]:='\';
+xchr[@'135]:=']';
+xchr[@'136]:='^';
+xchr[@'137]:='_';@/
+xchr[@'140]:='`';
+xchr[@'141]:='a';
+xchr[@'142]:='b';
+xchr[@'143]:='c';
+xchr[@'144]:='d';
+xchr[@'145]:='e';
+xchr[@'146]:='f';
+xchr[@'147]:='g';@/
+xchr[@'150]:='h';
+xchr[@'151]:='i';
+xchr[@'152]:='j';
+xchr[@'153]:='k';
+xchr[@'154]:='l';
+xchr[@'155]:='m';
+xchr[@'156]:='n';
+xchr[@'157]:='o';@/
+xchr[@'160]:='p';
+xchr[@'161]:='q';
+xchr[@'162]:='r';
+xchr[@'163]:='s';
+xchr[@'164]:='t';
+xchr[@'165]:='u';
+xchr[@'166]:='v';
+xchr[@'167]:='w';@/
+xchr[@'170]:='x';
+xchr[@'171]:='y';
+xchr[@'172]:='z';
+xchr[@'173]:='{';
+xchr[@'174]:='|';
+xchr[@'175]:='}';
+xchr[@'176]:='~';@/
+
+@ Some of the ASCII codes without visible characters have been given symbolic
+names in this program because they are used with a special meaning.
+
+@d null_code=@'0 {ASCII code that might disappear}
+@d carriage_return=@'15 {ASCII code used at end of line}
+@d invalid_code=@'177 {ASCII code that many systems prohibit in text files}
+
+@ The ASCII code is ``standard'' only to a certain extent, since many
+computer installations have found it advantageous to have ready access
+to more than 94 printing characters. Appendix~C of {\sl The \TeX book\/}
+gives a complete specification of the intended correspondence between
+characters and \TeX's internal representation.
+@:TeXbook}{\sl The \TeX book@>
+
+If \TeX\ is being used
+on a garden-variety \PASCAL\ for which only standard ASCII
+codes will appear in the input and output files, it doesn't really matter
+what codes are specified in |xchr[0..@'37]|, but the safest policy is to
+blank everything out by using the code shown below.
+
+However, other settings of |xchr| will make \TeX\ more friendly on
+computers that have an extended character set, so that users can type things
+like `\.^^Z' instead of `\.{\\ne}'. People with extended character sets can
+assign codes arbitrarily, giving an |xchr| equivalent to whatever
+characters the users of \TeX\ are allowed to have in their input files.
+It is best to make the codes correspond to the intended interpretations as
+shown in Appendix~C whenever possible; but this is not necessary. For
+example, in countries with an alphabet of more than 26 letters, it is
+usually best to map the additional letters into codes less than~@'40.
+To get the most ``permissive'' character set, change |' '| on the
+right of these assignment statements to |chr(i)|.
+@^character set dependencies@>
+@^system dependencies@>
+
+@<Set init...@>=
+for i:=0 to biggest_char do xchr[i]:=i;
+
+@ The following system-independent code makes the |xord| array contain a
+suitable inverse to the information in |xchr|. Note that if |xchr[i]=xchr[j]|
+where |i<j<@'177|, the value of |xord[xchr[i]]| will turn out to be
+|j| or more; hence, standard ASCII code numbers will be used instead of
+codes below @'40 in case there is a coincidence.
+
+@<Set init...@>=
+
+@* \[3] Input and output.
+The bane of portability is the fact that different operating systems treat
+input and output quite differently, perhaps because computer scientists
+have not given sufficient attention to this problem. People have felt somehow
+that input and output are not part of ``real'' programming. Well, it is true
+that some kinds of programming are more fun than others. With existing
+input/output conventions being so diverse and so messy, the only sources of
+joy in such parts of the code are the rare occasions when one can find a
+way to make the program a little less bad than it might have been. We have
+two choices, either to attack I/O now and get it over with, or to postpone
+I/O until near the end. Neither prospect is very attractive, so let's
+get it over with.
+
+The basic operations we need to do are (1)~inputting and outputting of
+text, to or from a file or the user's terminal; (2)~inputting and
+outputting of eight-bit bytes, to or from a file; (3)~instructing the
+operating system to initiate (``open'') or to terminate (``close'') input or
+output from a specified file; (4)~testing whether the end of an input
+file has been reached.
+
+\TeX\ needs to deal with two kinds of files.
+We shall use the term |alpha_file| for a file that contains textual data,
+and the term |byte_file| for a file that contains eight-bit binary information.
+These two types turn out to be the same on many computers, but
+sometimes there is a significant distinction, so we shall be careful to
+distinguish between them. Standard protocols for transferring
+such files from computer to computer, via high-speed networks, are
+now becoming available to more and more communities of users.
+
+The program actually makes use also of a third kind of file, called a
+|word_file|, when dumping and reloading base information for its own
+initialization. We shall define a word file later; but it will be possible
+for us to specify simple operations on word files before they are defined.
+
+@<Types...@>=
+@!eight_bits=0..65535; {unsigned one-byte quantity}
+@!real_eight_bits=0..255; {unsigned one-byte quantity}
+@!alpha_file=packed file of text_char; {files that contain textual data}
+@!byte_file=packed file of real_eight_bits; {files that contain binary data}
+
+@ Most of what we need to do with respect to input and output can be handled
+by the I/O facilities that are standard in \PASCAL, i.e., the routines
+called |get|, |put|, |eof|, and so on. But
+standard \PASCAL\ does not allow file variables to be associated with file
+names that are determined at run time, so it cannot be used to implement
+\TeX; some sort of extension to \PASCAL's ordinary |reset| and |rewrite|
+is crucial for our purposes. We shall assume that |nameoffile| is a variable
+of an appropriate type such that the \PASCAL\ run-time system being used to
+implement \TeX\ can open a file whose external name is specified by
+|nameoffile|.
+@^system dependencies@>
+
+@<Glob...@>=
+@!nameoffile:packed array[1..file_name_size] of char;@;@/
+ {on some systems this may be a \&{record} variable}
+@!namelength:0..file_name_size;@/{this many characters are actually
+ relevant in |nameoffile| (the rest are blank)}
+@!name_file_pointer:alpha_file;
+
+@ The \ph\ compiler with which the present version of \TeX\ was prepared has
+extended the rules of \PASCAL\ in a very convenient way. To open file~|f|,
+we can write
+$$\vbox{\halign{#\hfil\qquad&#\hfil\cr
+|reset(f,@t\\{name}@>,'/O')|&for input;\cr
+|rewrite(f,@t\\{name}@>,'/O')|&for output.\cr}}$$
+The `\\{name}' parameter, which is of type `{\bf packed array
+$[\langle\\{any}\rangle]$ of \\{char}}', stands for the name of
+the external file that is being opened for input or output.
+Blank spaces that might appear in \\{name} are ignored.
+
+The `\.{/O}' parameter tells the operating system not to issue its own
+error messages if something goes wrong. If a file of the specified name
+cannot be found, or if such a file cannot be opened for some other reason
+(e.g., someone may already be trying to write the same file), we will have
+|@!erstat(f)<>0| after an unsuccessful |reset| or |rewrite|. This allows
+\TeX\ to undertake appropriate corrective action.
+@:PASCAL H}{\ph@>
+@^system dependencies@>
+
+\TeX's file-opening procedures return |false| if no file identified by
+|nameoffile| could be opened.
+
+@d reset_OK(#)==erstat(#)=0
+@d rewrite_OK(#)==erstat(#)=0
+
+@p function a_open_in(var f:alpha_file):boolean;
+ {open a text file for input}
+begin reset(f,nameoffile,'/O'); a_open_in:=reset_OK(f);
+end;
+@#
+function a_open_out(var f:alpha_file):boolean;
+ {open a text file for output}
+begin rewrite(f,nameoffile,'/O'); a_open_out:=rewrite_OK(f);
+end;
+@#
+function b_open_in(var f:byte_file):boolean;
+ {open a binary file for input}
+begin reset(f,nameoffile,'/O'); b_open_in:=reset_OK(f);
+end;
+@#
+function b_open_out(var f:byte_file):boolean;
+ {open a binary file for output}
+begin rewrite(f,nameoffile,'/O'); b_open_out:=rewrite_OK(f);
+end;
+@#
+function w_open_in(var f:word_file):boolean;
+ {open a word file for input}
+begin reset(f,nameoffile,'/O'); w_open_in:=reset_OK(f);
+end;
+@#
+function w_open_out(var f:word_file):boolean;
+ {open a word file for output}
+begin rewrite(f,nameoffile,'/O'); w_open_out:=rewrite_OK(f);
+end;
+
+@ When input files are opened via a callback, they will also be read using
+callbacks. for that purpose, the |open_read_file_callback| returns an
+integer to uniquely identify a callback table. This id replaces the file
+point |f| in this case, because the input does not have to be a file
+in the traditional sense.
+
+Signalling this fact is achieved by having two arrays of integers.
+
+@<Glob...@>=
+@!input_file_callback_id : ^integer;
+@!read_file_callback_id : array[0..16] of integer;
+
+@
+@p function lua_a_open_in(var f:alpha_file; n:quarterword):boolean;
+var k:integer; { a temporary value }
+ fnam:str_number; { string returned by find callback }
+ callback_id:integer;
+ file_ok:boolean; { the status so far }
+begin
+ file_ok:=true;
+ if n=0 then begin
+ texinputtype := 1; {Tell |open_input| we are \.{\\input}.}
+ input_file_callback_id[index] := 0;
+ end
+ else begin
+ texinputtype:=0;
+ read_file_callback_id[n] := 0;
+ end;
+ callback_id:=callback_defined(find_read_file_callback);
+ if callback_id>0 then begin
+ fnam:=0;
+ file_ok:=run_callback(callback_id,'dS->s',n,stringcast(nameoffile+1),addressof(fnam));
+ if (file_ok)and(fnam<>0)and(length(fnam)>0) then begin
+ @<Fixup |nameoffile| after callback@>;
+ end
+ else
+ file_ok:=false; {file not found}
+ end;
+ if file_ok then begin
+ callback_id:=callback_defined(open_read_file_callback);
+ if callback_id>0 then begin
+ k := run_and_save_callback(callback_id,'S->',stringcast(nameoffile+1));
+ if k>0 then begin
+ lua_a_open_in := true;
+ if n=0 then
+ input_file_callback_id[index] := k
+ else
+ read_file_callback_id[n] := k;
+ end
+ else
+ file_ok:=false; {read failed}
+ end
+ else begin {no read callback}
+ if openinnameok(stringcast(nameoffile+1)) then begin
+ lua_a_open_in := a_open_in(f,kpsetexformat);
+ name_file_pointer := f;
+ end
+ else
+ file_ok:=false; {open failed}
+ end;
+ end;
+ if not file_ok then begin
+ lua_a_open_in := false;
+ name_file_pointer := 0;
+ end;
+end;
+@#
+function lua_a_open_out(var f:alpha_file; n:quarterword):boolean;
+var test:boolean;
+ k:integer;
+ fnam:str_number;
+ callback_id:integer;
+begin
+ name_file_pointer := 0;
+ callback_id:=callback_defined(find_write_file_callback);
+ if callback_id>0 then begin
+ fnam:=0;
+ test:=run_callback(callback_id,'dS->s',n,stringcast(nameoffile+1),addressof(fnam));
+ if (test)and(fnam<>0)and(length(fnam)>0) then begin
+ @<Fixup |nameoffile| after callback@>;
+ lua_a_open_out := do_a_open_out(f);
+ name_file_pointer := f;
+ end
+ else
+ lua_a_open_out := false;
+ end
+ else begin
+ if openoutnameok(stringcast(nameoffile+1)) then begin
+ lua_a_open_out := a_open_out(f);
+ name_file_pointer := f;
+ end
+ else
+ lua_a_open_out := false;
+ end;
+end;
+function lua_b_open_out(var f:alpha_file):boolean;
+var test:boolean;
+ k:integer;
+ fnam:str_number;
+ callback_id:integer;
+begin
+ name_file_pointer := 0;
+ callback_id:=callback_defined(find_output_file_callback);
+ if callback_id>0 then begin
+ fnam:=0;
+ test:=run_callback(callback_id,'S->s',stringcast(nameoffile+1),addressof(fnam));
+ if (test)and(fnam<>0)and(length(fnam)>0) then begin
+ @<Fixup |nameoffile| after callback@>;
+ lua_b_open_out := do_b_open_out(f);
+ name_file_pointer := f;
+ end
+ else
+ lua_b_open_out := false;
+ end
+ else begin
+ if openoutnameok(stringcast(nameoffile+1)) then begin
+ lua_b_open_out := b_open_out(f);
+ name_file_pointer := f;
+ end
+ else
+ lua_b_open_out := false;
+ end;
+end;
+
+@
+@<Fixup |nameoffile| after callback@>=
+libcfree (nameoffile);
+nameoffile := xmallocarray (packed_ASCII_code, length(fnam)+2);
+for k:=str_start_macro(fnam) to str_start_macro(fnam+1)-1 do
+ nameoffile[k-str_start_macro(fnam)+1] := str_pool[k];
+nameoffile[length(fnam)+1]:=0;
+namelength := length(fnam);
+flush_string
+
+@ Files can be closed with the \ph\ routine `|close(f)|', which
+@^system dependencies@>
+should be used when all input or output with respect to |f| has been completed.
+This makes |f| available to be opened again, if desired; and if |f| was used for
+output, the |close| operation makes the corresponding external file appear
+on the user's area, ready to be read.
+
+These procedures should not generate error messages if a file is
+being closed before it has been successfully opened.
+
+@p procedure a_close(var f:alpha_file); {close a text file}
+begin close(f);
+end;
+@#
+procedure b_close(var f:byte_file); {close a binary file}
+begin close(f);
+end;
+@#
+procedure w_close(var f:word_file); {close a word file}
+begin close(f);
+end;
+
+
+@
+
+@p procedure lua_a_close_in(var f:alpha_file; n:quarterword); {close a text file}
+var ret:boolean;
+ callback_id:integer;
+begin
+if n=0 then
+ callback_id:=input_file_callback_id[index]
+else
+ callback_id:=read_file_callback_id[n];
+if callback_id>0 then begin
+ ret:=run_saved_callback(callback_id,'close','->');
+ destroy_saved_callback(callback_id);
+ if n=0 then
+ input_file_callback_id[index] := 0
+ else
+ read_file_callback_id[n] := 0;
+ end
+else
+ a_close(f);
+end;
+@#
+procedure lua_a_close_out(var f:alpha_file); {close a text file}
+begin
+ a_close(f);
+end;
+
+
+@ Binary input and output are done with \PASCAL's ordinary |get| and |put|
+procedures, so we don't have to make any other special arrangements for
+binary~I/O. Text output is also easy to do with standard \PASCAL\ routines.
+The treatment of text input is more difficult, however, because
+of the necessary translation to |ASCII_code| values.
+\TeX's conventions should be efficient, and they should
+blend nicely with the user's operating environment.
+
+@ Input from text files is read one line at a time, using a routine called
+|lua_input_ln|. This function is defined in terms of global variables called
+|buffer|, |first|, and |last| that will be described in detail later; for
+now, it suffices for us to know that |buffer| is an array of |ASCII_code|
+values, and that |first| and |last| are indices into this array
+representing the beginning and ending of a line of text.
+
+@<Glob...@>=
+@!buffer:array[0..buf_size] of packed_ASCII_code; {lines of characters being read}
+@!first:0..buf_size; {the first unused position in |buffer|}
+@!last:0..buf_size; {end of the line just input to |buffer|}
+@!max_buf_stack:0..buf_size; {largest index used in |buffer|}
+
+@ The |lua_input_ln| function brings the next line of input from the specified
+file into available positions of the buffer array and returns the value
+|true|, unless the file has already been entirely read, in which case it
+returns |false| and sets |last:=first|. In general, the |ASCII_code|
+numbers that represent the next line of the file are input into
+|buffer[first]|, |buffer[first+1]|, \dots, |buffer[last-1]|; and the
+global variable |last| is set equal to |first| plus the length of the
+line. Trailing blanks are removed from the line; thus, either |last=first|
+(in which case the line was entirely blank) or |buffer[last-1]<>" "|.
+
+An overflow error is given, however, if the normal actions of |lua_input_ln|
+would make |last>=buf_size|; this is done so that other parts of \TeX\
+can safely look at the contents of |buffer[last+1]| without overstepping
+the bounds of the |buffer| array. Upon entry to |lua_input_ln|, the condition
+|first<buf_size| will always hold, so that there is always room for an
+``empty'' line.
+
+The variable |max_buf_stack|, which is used to keep track of how large
+the |buf_size| parameter must be to accommodate the present job, is
+also kept up to date by |lua_input_ln|.
+
+If the |bypass_eoln| parameter is |true|, |lua_input_ln| will do a |get|
+before looking at the first character of the line; this skips over
+an |eoln| that was in |f^|. The procedure does not do a |get| when it
+reaches the end of the line; therefore it can be used to acquire input
+from the user's terminal as well as from ordinary text files.
+
+Standard \PASCAL\ says that a file should have |eoln| immediately
+before |eof|, but \TeX\ needs only a weaker restriction: If |eof|
+occurs in the middle of a line, the system function |eoln| should return
+a |true| result (even though |f^| will be undefined).
+
+Since the inner loop of |lua_input_ln| is part of \TeX's ``inner loop''---each
+character of input comes in at this place---it is wise to reduce system
+overhead by making use of special routines that read in an entire array
+of characters at once, if such routines are available. The following
+code uses standard \PASCAL\ to illustrate what needs to be done, but
+finer tuning is often possible at well-developed \PASCAL\ sites.
+@^inner loop@>
+
+@p function input_ln(var f:alpha_file;@!bypass_eoln:boolean):boolean;
+ {inputs the next line or returns |false|}
+var last_nonblank:0..buf_size; {|last| with trailing blanks removed}
+begin if bypass_eoln then if not eof(f) then get(f);
+ {input the first character of the line into |f^|}
+last:=first; {cf.\ Matthew 19\thinspace:\thinspace30}
+if eof(f) then input_ln:=false
+else begin last_nonblank:=first;
+ while not eoln(f) do
+ begin if last>=max_buf_stack then
+ begin max_buf_stack:=last+1;
+ if max_buf_stack=buf_size then
+ @<Report overflow of the input buffer, and abort@>;
+ end;
+ buffer[last]:=f^; get(f); incr(last);
+ if buffer[last-1]<>" " then last_nonblank:=last;
+ end;
+ last:=last_nonblank; input_ln:=true;
+ end;
+end;
+
+function lua_input_ln(var f:alpha_file;n:quarterword;@!bypass_eoln:boolean):boolean;
+var lua_result:boolean;
+ last_ptr:integer;
+ callback_id:integer;
+ bypass_p:boolean;
+begin
+if n=0 then
+ callback_id:=input_file_callback_id[index]
+else
+ callback_id:=read_file_callback_id[n];
+if callback_id>0 then begin
+ last:=first;
+ last_ptr := first;
+ lua_result := run_saved_callback(callback_id,'reader','->l', addressof(last_ptr));
+ if (lua_result=true)and(last_ptr<>0) then begin
+ last := last_ptr;
+ if last>max_buf_stack then max_buf_stack:=last;
+ lua_input_ln := true;
+ @<Fix up the input buffer using callbacks@>;
+ end
+ else
+ lua_input_ln := false;
+ end
+ else begin
+ bypass_p := bypass_eoln; {this is for -Wextra}
+ lua_result := input_ln(f,bypass_p);
+ if lua_result=true then begin
+ lua_input_ln := true;
+ @<Fix up the input buffer using callbacks@>;
+ end
+ else
+ lua_input_ln := false;
+ end
+end;
+
+@
+@<Fix up the input buffer using callbacks@>=
+if last>=first then begin
+ callback_id := callback_defined(process_input_buffer_callback);
+ if callback_id>0 then begin
+ last_ptr := first;
+ lua_result := run_callback(callback_id, 'l->l', (last-first), addressof(last_ptr));
+ if (lua_result=true)and(last_ptr<>0) then begin
+ last := last_ptr;
+ if last>max_buf_stack then max_buf_stack:=last;
+ end;
+ end;
+ end
+
+
+
+@ The user's terminal acts essentially like other files of text, except
+that it is used both for input and for output. When the terminal is
+considered an input file, the file variable is called |term_in|, and when it
+is considered an output file the file variable is |term_out|.
+@^system dependencies@>
+
+@<Glob...@>=
+@!term_in:alpha_file; {the terminal as an input file}
+@!term_out:alpha_file; {the terminal as an output file}
+
+@ Here is how to open the terminal files
+in \ph. The `\.{/I}' switch suppresses the first |get|.
+@^system dependencies@>
+
+@d t_open_in==reset(term_in,'TTY:','/O/I') {open the terminal for text input}
+@d t_open_out==rewrite(term_out,'TTY:','/O') {open the terminal for text output}
+
+@ Sometimes it is necessary to synchronize the input/output mixture that
+happens on the user's terminal, and three system-dependent
+procedures are used for this
+purpose. The first of these, |update_terminal|, is called when we want
+to make sure that everything we have output to the terminal so far has
+actually left the computer's internal buffers and been sent.
+The second, |clear_terminal|, is called when we wish to cancel any
+input that the user may have typed ahead (since we are about to
+issue an unexpected error message). The third, |wake_up_terminal|,
+is supposed to revive the terminal if the user has disabled it by
+some instruction to the operating system. The following macros show how
+these operations can be specified in \ph:
+@^system dependencies@>
+
+@d update_terminal == break(term_out) {empty the terminal output buffer}
+@d clear_terminal == break_in(term_in,true) {clear the terminal input buffer}
+@d wake_up_terminal == do_nothing {cancel the user's cancellation of output}
+
+@ We need a special routine to read the first line of \TeX\ input from
+the user's terminal. This line is different because it is read before we
+have opened the transcript file; there is sort of a ``chicken and
+egg'' problem here. If the user types `\.{\\input paper}' on the first
+line, or if some macro invoked by that line does such an \.{\\input},
+the transcript file will be named `\.{paper.log}'; but if no \.{\\input}
+commands are performed during the first line of terminal input, the transcript
+file will acquire its default name `\.{texput.log}'. (The transcript file
+will not contain error messages generated by the first line before the
+first \.{\\input} command.)
+@.texput@>
+
+The first line is even more special if we are lucky enough to have an operating
+system that treats \TeX\ differently from a run-of-the-mill \PASCAL\ object
+program. It's nice to let the user start running a \TeX\ job by typing
+a command line like `\.{tex paper}'; in such a case, \TeX\ will operate
+as if the first line of input were `\.{paper}', i.e., the first line will
+consist of the remainder of the command line, after the part that invoked
+\TeX.
+
+The first line is special also because it may be read before \TeX\ has
+input a format file. In such cases, normal error messages cannot yet
+be given. The following code uses concepts that will be explained later.
+(If the \PASCAL\ compiler does not support non-local |@!goto|\unskip, the
+@^system dependencies@>
+statement `|goto final_end|' should be replaced by something that
+quietly terminates the program.)
+
+@<Report overflow of the input buffer, and abort@>=
+if format_ident=0 then
+ begin writeln(term_out,'Buffer size exceeded!'); goto final_end;
+@.Buffer size exceeded@>
+ end
+else
+ check_buffer_overflow(buf_size+10) { need a little bit more}
+
+@ Different systems have different ways to get started. But regardless of
+what conventions are adopted, the routine that initializes the terminal
+should satisfy the following specifications:
+
+\yskip\textindent{1)}It should open file |term_in| for input from the
+ terminal. (The file |term_out| will already be open for output to the
+ terminal.)
+
+\textindent{2)}If the user has given a command line, this line should be
+ considered the first line of terminal input. Otherwise the
+ user should be prompted with `\.{**}', and the first line of input
+ should be whatever is typed in response.
+
+\textindent{3)}The first line of input, which might or might not be a
+ command line, should appear in locations |first| to |last-1| of the
+ |buffer| array.
+
+\textindent{4)}The global variable |loc| should be set so that the
+ character to be read next by \TeX\ is in |buffer[loc]|. This
+ character should not be blank, and we should have |loc<last|.
+
+\yskip\noindent(It may be necessary to prompt the user several times
+before a non-blank line comes in. The prompt is `\.{**}' instead of the
+later `\.*' because the meaning is slightly different: `\.{\\input}' need
+not be typed immediately after~`\.{**}'.)
+
+@d loc==cur_input.loc_field {location of first unread character in |buffer|}
+
+@ The following program does the required initialization
+without retrieving a possible command line.
+It should be clear how to modify this routine to deal with command lines,
+if the system permits them.
+@^system dependencies@>
+
+@p function init_terminal:boolean; {gets the terminal input started}
+label exit;
+begin t_open_in;
+loop@+begin wake_up_terminal; write(term_out,'**'); update_terminal;
+@.**@>
+ if not input_ln(term_in,true)
+then {this shouldn't happen}
+ begin writeln(term_out);
+ write(term_out,'! End of file on the terminal... why?');
+@.End of file on the terminal@>
+ init_terminal:=false; return;
+ end;
+ loc:=first;
+ while (loc<last)and(buffer[loc]=" ") do incr(loc);
+ if loc<last then
+ begin init_terminal:=true;
+ return; {return unless the line was all blank}
+ end;
+ writeln(term_out,'Please type the name of your input file.');
+ end;
+exit:end;
+
+@* \[4] String handling.
+Control sequence names and diagnostic messages are variable-length strings
+of eight-bit characters. Since \PASCAL\ does not have a well-developed string
+mechanism, \TeX\ does all of its string processing by homegrown methods.
+
+Elaborate facilities for dynamic strings are not needed, so all of the
+necessary operations can be handled with a simple data structure.
+The array |str_pool| contains all of the (eight-bit) ASCII codes in all
+of the strings, and the array |str_start| contains indices of the starting
+points of each string. Strings are referred to by integer numbers, so that
+string number |s| comprises the characters |str_pool[j]| for
+|str_start_macro(s)<=j<str_start_macro(s+1)|. Additional integer variables
+|pool_ptr| and |str_ptr| indicate the number of entries used so far
+in |str_pool| and |str_start|, respectively; locations
+|str_pool[pool_ptr]| and |str_start_macro(str_ptr)| are
+ready for the next string to be allocated.
+
+String numbers 0 to |biggest_char| are reserved for strings that correspond to single
+UNICODE characters. This is in accordance with the conventions of \.{WEB},
+@.WEB@>
+which converts single-character strings into the ASCII code number of the
+single character involved, while it converts other strings into integers
+and builds a string pool file. Thus, when the string constant \.{"."} appears
+in the program below, \.{WEB} converts it into the integer 46, which is the
+ASCII code for a period, while \.{WEB} will convert a string like \.{"hello"}
+into some integer greater than~|biggest_char|.
+
+Some \PASCAL\ compilers won't pack integers into a single byte unless the
+integers lie in the range |-128..127|. To accommodate such systems
+we access the string pool only via macros that can easily be redefined.
+
+@d si(#) == # {convert from |ASCII_code| to |packed_ASCII_code|}
+@d so(#) == # {convert from |packed_ASCII_code| to |ASCII_code|}
+@d str_start_macro(#) == str_start[(#) - string_offset]
+
+@<Types...@>=
+@!pool_pointer = integer; {for variables that point into |str_pool|}
+@!str_number = integer; {for variables that point into |str_start|}
+@!packed_ASCII_code = 0..255; {elements of |str_pool| array}
+
+@ @<Glob...@>=
+@!str_pool:packed array[pool_pointer] of packed_ASCII_code; {the characters}
+@!str_start : array[str_number] of pool_pointer; {the starting pointers}
+@!pool_ptr : pool_pointer; {first unused position in |str_pool|}
+@!str_ptr : str_number; {number of the current string being created}
+@!init_pool_ptr : pool_pointer; {the starting value of |pool_ptr|}
+@!init_str_ptr : str_number; {the starting value of |str_ptr|}
+
+@ Several of the elementary string operations are performed using \.{WEB}
+macros instead of \PASCAL\ procedures, because many of the
+operations are done quite frequently and we want to avoid the
+overhead of procedure calls. For example, here is
+a simple macro that computes the length of a string.
+@.WEB@>
+
+@d length(#)==(str_start_macro(#+1)-str_start_macro(#)) {the number of characters
+ in string number \#}
+
+@ The length of the current string is called |cur_length|:
+
+@d cur_length == (pool_ptr - str_start_macro(str_ptr))
+
+@ Strings are created by appending character codes to |str_pool|.
+The |append_char| macro, defined here, does not check to see if the
+value of |pool_ptr| has gotten too high; this test is supposed to be
+made before |append_char| is used. There is also a |flush_char|
+macro, which erases the last character appended.
+
+To test if there is room to append |l| more characters to |str_pool|,
+we shall write |str_room(l)|, which aborts \TeX\ and gives an
+apologetic error message if there isn't enough room.
+
+@d append_char(#) == {put |ASCII_code| \# at the end of |str_pool|}
+begin str_pool[pool_ptr]:=si(#); incr(pool_ptr);
+end
+@d flush_char == decr(pool_ptr) {forget the last character in the pool}
+@d str_room(#) == check_pool_overflow((pool_ptr+#)) {test or grow the pool}
+
+@p procedure string_room(t:integer);
+begin
+ str_room(t);
+end;
+@#
+procedure append_pool_char(c:ASCII_code);
+begin
+ append_char(c);
+end;
+
+
+@ Once a sequence of characters has been appended to |str_pool|, it
+officially becomes a string when the function |make_string| is called.
+This function returns the identification number of the new string as its
+value.
+
+@p function make_string : str_number; {current string enters the pool}
+begin if str_ptr=(max_strings+string_offset) then
+ overflow("number of strings",max_strings-init_str_ptr);
+@:TeX capacity exceeded number of strings}{\quad number of strings@>
+incr(str_ptr); str_start_macro(str_ptr):=pool_ptr;
+make_string:=str_ptr-1;
+end;
+
+@ To destroy the most recently made string, we say |flush_string|.
+
+The helper routines reads one utf sequence from the pool resp. the
+buffer, and returns its character value.
+
+@d flush_string==begin decr(str_ptr); pool_ptr:=str_start_macro(str_ptr);
+ end
+@d test_sequence_byte(#)==if (#<@"80) or (#>=@"C0) then begin
+ print_err("Text line contains an invalid utf-8 sequence");
+@.Text line contains...@>
+ help2("A funny symbol that I can't read has just been input.")@/
+ ("Just continue, I'll change it to 0xFFFD.");@/
+ deletions_allowed:=false; error; deletions_allowed:=true;
+{the assigment before return is needed because web2c generates incorrect code}
+ a:=@"FFFD; buffer_to_unichar:=a; return; end
+
+
+@p function buffer_to_unichar(@!k:integer):integer;
+label exit;
+var a:@!integer; {a utf char}
+b:@!integer; { a utf nibble}
+begin
+ b := buffer[k];
+ if b<@"80 then
+ a := b
+ else if b>=@"F0 then begin
+ a := (b-@"F0) * 64;
+ b := buffer[k+1];
+ test_sequence_byte(b);
+ a := (a + (b-128)) * 64;
+ b := buffer[k+2];
+ test_sequence_byte(b);
+ a := (a + (b-128)) * 64;
+ b := buffer[k+3];
+ test_sequence_byte(b);
+ a := a + (b-128);
+ end
+ else if b>=@"E0 then begin
+ a := (b-@"E0) * 64;
+ b := buffer[k+1];
+ test_sequence_byte(b);
+ a := (a + (b-128)) * 64;
+ b := buffer[k+2];
+ test_sequence_byte(b);
+ a := a + (b-128);
+ end
+ else if b>=@"C0 then begin
+ a := (b-@"C0) * 64;
+ b := buffer[k+1];
+ test_sequence_byte(b);
+ a := a + (b-128);
+ end
+ else begin { NI: this is an encoding error }
+ print_err("Buffer contains an invalid utf-8 sequence");
+@.Text line contains...@>
+ help2("A funny symbol somehow ended up in the input buffer.")@/
+ ("Just continue, I'll change it to 0xFFFD.");@/
+ deletions_allowed:=false; error; deletions_allowed:=true;
+ a:=@"FFFD;
+ end;
+exit:
+ buffer_to_unichar := a;
+end ;
+
+
+
+@ The following subroutine compares string |s| with another string of the
+same length that appears in |buffer| starting at position |k|;
+the result is |true| if and only if the strings are equal.
+Empirical tests indicate that |str_eq_buf| is used in such a way that
+it tends to return |true| about 80 percent of the time.
+
+@p function str_eq_buf(@!s:str_number;@!k:integer):boolean;
+ {test equality of strings}
+label not_found; {loop exit}
+var j: pool_pointer; {running index}
+a: ASCII_code; {a unicode character }
+@!result: boolean; {result of comparison}
+begin result:=false;
+if s<string_offset then begin
+ a := buffer_to_unichar(k);
+ if a<>s then goto not_found;
+ end
+else begin
+j:=str_start_macro(s);
+while j<str_start_macro(s+1) do
+ begin if so(str_pool[j])<>buffer[k] then
+ begin goto not_found;
+ end;
+ incr(j); incr(k);
+ end;
+end;
+result:=true;
+not_found: str_eq_buf:=result;
+end;
+
+@ Here is a similar routine, but it compares two strings in the string pool,
+and it does not assume that they have the same length.
+
+@p function str_eq_str(@!s,@!t:str_number):boolean;
+ {test equality of strings}
+label found,not_found; {loop exit}
+var j,@!k: pool_pointer; {running indices}
+a: ASCII_code; {a utf char}
+@!result: boolean; {result of comparison}
+begin result:=false;
+a:= 0;
+if s<string_offset then begin
+ if t>=string_offset then begin
+ if s<=@"7F then
+ if length(t)=1 then
+ if str_pool[str_start_macro(t)]=s then
+ goto found;
+ a := pool_to_unichar(str_start_macro(t));
+ if a<>s then goto not_found;
+ end
+ else
+ if t<>s then goto not_found;
+ end
+else if t<string_offset then begin
+ if t<=@"7F then
+ if length(s)=1 then
+ if str_pool[str_start_macro(s)]=t then
+ goto found;
+ a := pool_to_unichar(str_start_macro(s));
+ if a<>t then goto not_found;
+ end
+else begin
+ if length(s)<>length(t) then goto not_found;
+ j:=str_start_macro(s); k:=str_start_macro(t);
+ while j<str_start_macro(s+1) do
+ begin if str_pool[j]<>str_pool[k] then goto not_found;
+ incr(j); incr(k);
+ end;
+ end;
+found: result:=true;
+not_found: str_eq_str:=result;
+end;
+
+@ The initial values of |str_pool|, |str_start|, |pool_ptr|,
+and |str_ptr| are computed by the \.{INITEX} program, based in part
+on the information that \.{WEB} has output while processing \TeX.
+@.INITEX@>
+@^string pool@>
+
+The first |string_offset| strings are single-characters strings matching
+Unicode. There is no point in generating all of these. But |str_ptr| has
+initialized properly, otherwise |print_char| cannot see the difference
+between characters and strings.
+
+@p @!init function get_strings_started:boolean; {initializes the string pool,
+ but returns |false| if something goes wrong}
+label done,exit;
+var @!g:str_number; {garbage}
+begin pool_ptr:=0; str_ptr:=string_offset; str_start[0]:=0;
+@<Read the other strings from the \.{TEX.POOL} file and return |true|,
+ or give an error message and return |false|@>;
+exit:end;
+tini
+
+@ @d app_lc_hex(#)==l:=#;
+ if l<10 then append_char(l+"0")@+else append_char(l-10+"a")
+
+@ The first 128 strings will contain 95 standard ASCII characters, and the
+other 33 characters will be printed in three-symbol form like `\.{\^\^A}'
+unless a system-dependent change is made here. Installations that have
+an extended character set, where for example |xchr[@'32]=@t\.{\'^^Z\'}@>|,
+would like string @'32 to be the single character @'32 instead of the
+three characters @'136, @'136, @'132 (\.{\^\^Z}). On the other hand,
+even people with an extended character set will want to represent string
+@'15 by \.{\^\^M}, since @'15 is |carriage_return|; the idea is to
+produce visible strings instead of tabs or line-feeds or carriage-returns
+or bell-rings or characters that are treated anomalously in text files.
+
+Unprintable characters of codes 128--255 are, similarly, rendered
+\.{\^\^80}--\.{\^\^ff}.
+
+Unprintable characters of codes 256--|65535| are, similarly, rendered
+\.{\^\^\^\^0100}--\.{\^\^\^\^ffff}.
+
+The boolean expression defined here should be |true| unless \TeX\
+internal code number~|k| corresponds to a non-troublesome visible
+symbol in the local character set. An appropriate formula for the
+extended character set recommended in {\sl The \TeX book\/} would, for
+example, be `|k in [0,@'10..@'12,@'14,@'15,@'33,@'177..@'377]|'.
+If character |k| cannot be printed, and |k<@'200|, then character |k+@'100| or
+|k-@'100| must be printable; moreover, ASCII codes |[@'41..@'46,
+@'60..@'71, @'141..@'146, @'160..@'171]| must be printable.
+Thus, at least 80 printable characters are needed.
+@:TeXbook}{\sl The \TeX book@>
+@^character set dependencies@>
+@^system dependencies@>
+
+@ @<Read the other strings...@>=
+ g := loadpoolstrings((pool_size-string_vacancies));
+ if g=0 then begin
+ wake_up_terminal; writeln(term_out,'! You have to increase POOLSIZE.');
+ get_strings_started:=false;
+ return;
+ end;
+ get_strings_started:=true;
+
+@* \[5] On-line and off-line printing.
+Messages that are sent to a user's terminal and to the transcript-log file
+are produced by several `|print|' procedures. These procedures will
+direct their output to a variety of places, based on the setting of
+the global variable |selector|, which has the following possible
+values:
+
+\yskip
+\hang |term_and_log|, the normal setting, prints on the terminal and on the
+ transcript file.
+
+\hang |log_only|, prints only on the transcript file.
+
+\hang |term_only|, prints only on the terminal.
+
+\hang |no_print|, doesn't print at all. This is used only in rare cases
+ before the transcript file is open.
+
+\hang |pseudo|, puts output into a cyclic buffer that is used
+ by the |show_context| routine; when we get to that routine we shall discuss
+ the reasoning behind this curious mode.
+
+\hang |new_string|, appends the output to the current string in the
+ string pool.
+
+\hang 0 to 15, prints on one of the sixteen files for \.{\\write} output.
+
+\yskip
+\noindent The symbolic names `|term_and_log|', etc., have been assigned
+numeric codes that satisfy the convenient relations |no_print+1=term_only|,
+|no_print+2=log_only|, |term_only+2=log_only+1=term_and_log|.
+
+Three additional global variables, |tally| and |term_offset| and
+|file_offset|, record the number of characters that have been printed
+since they were most recently cleared to zero. We use |tally| to record
+the length of (possibly very long) stretches of printing; |term_offset|
+and |file_offset|, on the other hand, keep track of how many characters
+have appeared so far on the current line that has been output to the
+terminal or to the transcript file, respectively.
+
+@d no_print=16 {|selector| setting that makes data disappear}
+@d term_only=17 {printing is destined for the terminal only}
+@d log_only=18 {printing is destined for the transcript file only}
+@d term_and_log=19 {normal |selector| setting}
+@d pseudo=20 {special |selector| setting for |show_context|}
+@d new_string=21 {printing is deflected to the string pool}
+@d max_selector=21 {highest selector setting}
+
+@<Glob...@>=
+@!log_file : alpha_file; {transcript of \TeX\ session}
+@!term_out_mode:halfword;
+@!term_out_translation:halfword;
+@!selector : 0..max_selector; {where to print a message}
+@!dig : array[0..22] of 0..15; {digits in a number being output}
+@!tally : integer; {the number of characters recently printed}
+@!term_offset : 0..max_print_line;
+ {the number of characters on the current terminal line}
+@!file_offset : 0..max_print_line;
+ {the number of characters on the current file line}
+@!trick_buf:array[0..error_line] of packed_ASCII_code; {circular buffer for
+ pseudoprinting}
+@!trick_count: integer; {threshold for pseudoprinting, explained later}
+@!first_count: integer; {another variable for pseudoprinting}
+@!inhibit_par_tokens:boolean; { for minor adjustments to |show_token_list| }
+
+@ @<Initialize the output routines@>=
+selector:=term_only; tally:=0; term_offset:=0; file_offset:=0;
+inhibit_par_tokens:=false;
+
+@ Macro abbreviations for output to the terminal and to the log file are
+defined here for convenience. Some systems need special conventions
+for terminal output, and it is possible to adhere to those conventions
+by changing |wterm|, |wterm_ln|, and |wterm_cr| in this section.
+@^system dependencies@>
+
+@d wterm(#)==write(term_out,#)
+@d wterm_ln(#)==writeln(term_out,#)
+@d wterm_cr==writeln(term_out)
+@d wlog(#)==write(log_file,#)
+@d wlog_ln(#)==writeln(log_file,#)
+@d wlog_cr==writeln(log_file)
+
+@ To end a line of text output, we call |print_ln|.
+
+@<Basic print...@>=
+procedure print_ln; {prints an end-of-line}
+begin case selector of
+term_and_log: begin wterm_cr; wlog_cr;
+ term_offset:=0; file_offset:=0;
+ end;
+log_only: begin wlog_cr; file_offset:=0;
+ end;
+term_only: begin wterm_cr; term_offset:=0;
+ end;
+no_print,pseudo,new_string: do_nothing;
+othercases writeln(write_file[selector])
+endcases;@/
+end; {|tally| is not affected}
+
+@ The |print_char| procedure sends one character to the desired destination,
+using the |xchr| array to map it into an external character compatible with
+|lua_input_ln|. All printing comes through |print_ln| or |print_char|.
+
+@d wterm_char(#)==begin if (#>=@"20)or(#=@"0A)or(#=@"0D)or(#=@"09) then wterm(xchr[#])
+ else begin if term_offset+2>=max_print_line then begin
+ wterm_cr; term_offset:=0;
+ end;
+ incr(term_offset); wterm('^'); incr(term_offset); wterm('^');
+ wterm(xchr[#+64]);
+ end; end
+@d fix_term_offset(#)==
+ if ((#>=@"C0) and (#<=@"DF) and (term_offset+2>=max_print_line)) or
+ ((#>=@"E0) and (#<=@"EF) and (term_offset+3>=max_print_line)) or
+ ((#>=@"F0) and (term_offset+4>=max_print_line)) then begin
+ wterm_cr; term_offset:=0;
+ end
+@d fix_log_offset(#)==
+ if ((#>=@"C0) and (#<=@"DF) and (file_offset+2>=max_print_line)) or
+ ((#>=@"E0) and (#<=@"EF) and (file_offset+3>=max_print_line)) or
+ ((#>=@"F0) and (file_offset+4>=max_print_line)) then begin
+ wlog_cr; file_offset:=0;
+ end
+
+@<Basic print...@>=
+procedure print_char(@!s:ASCII_code); {prints a single character}
+label exit;
+begin if @<Character |s| is the current new-line character@> then
+ if selector<pseudo then
+ begin print_ln; return;
+ end;
+case selector of
+term_and_log: begin
+ fix_term_offset(s); fix_log_offset(s);
+ wterm_char(s); wlog(xchr[s]);
+ incr(term_offset); incr(file_offset);
+ if term_offset=max_print_line then
+ begin wterm_cr; term_offset:=0;
+ end;
+ if file_offset=max_print_line then
+ begin wlog_cr; file_offset:=0;
+ end;
+ end;
+log_only: begin
+ fix_log_offset(s);
+ wlog(xchr[s]); incr(file_offset);
+ if file_offset=max_print_line then print_ln;
+ end;
+term_only: begin
+ fix_term_offset(s);
+ wterm_char(s); incr(term_offset);
+ if term_offset=max_print_line then print_ln;
+ end;
+no_print: do_nothing;
+pseudo: if tally<trick_count then trick_buf[tally mod error_line]:=s;
+new_string: begin if pool_ptr<pool_size then append_char(s);
+ end; {we drop characters if the string space is full}
+othercases write(write_file[selector],xchr[s])
+endcases;@/
+incr(tally);
+exit:end;
+
+@ An entire string is output by calling |print|. Note that if we are outputting
+the single standard ASCII character \.c, we could call |print("c")|, since
+|"c"=99| is the number of a single-character string, as explained above. But
+|print_char("c")| is quicker, so \TeX\ goes directly to the |print_char|
+routine when it knows that this is safe. (The present implementation
+assumes that it is always safe to print a visible ASCII character.)
+@^system dependencies@>
+
+The first 256 entries above the 17th unicode plane are used for a
+special trick: when \TeX\ has to print items in that range, it will
+instead print the character that results from substracting @"110000
+from that value. This allows byte-oriented output to things like
+\.{\\specials} and \.{\\pdfliterals}. Todo: Perhaps it would be useful
+to do the same substraction while typesetting.
+
+@d print_lc_hex(#)==l:=#;
+ if l<10 then print_char(l+"0") else print_char(l-10+"a");
+
+@<Basic print...@>=
+function pool_to_unichar(@!t:pool_pointer):ASCII_code;
+var a,result:@!ASCII_code; {a utf char}
+b:@!quarterword; { a utf nibble}
+begin
+ b := str_pool[t];
+ if b<=@"7F then
+ a := b
+ else if b>=@"F0 then begin
+ a := (b-@"F0) * 64;
+ b := str_pool[t+1];
+ a := (a + (b-128)) * 64;
+ b := str_pool[t+2];
+ a := (a + (b-128)) * 64;
+ b := str_pool[t+3];
+ a := a + (b-128);
+ end
+ else if b>=@"E0 then begin
+ a := (b-@"E0) * 64;
+ b := str_pool[t+1];
+ a := (a + (b-128)) * 64;
+ b := str_pool[t+2];
+ a := a + (b-128);
+ end
+ else if b>=@"C0 then begin
+ a := (b-@"C0) * 64;
+ b := str_pool[t+1];
+ a := a + (b-128);
+ end
+ else begin { NI: this is an encoding error }
+ wlog_ln('! Pool contains an invalid utf-8 sequence');
+ wterm_ln('! Pool contains an invalid utf-8 sequence');
+@.Text line contains...@>
+ help2("A funny symbol somehow ended up in the string pool.")@/
+ ("Just continue, I'll change it to 0xFFFD.");@/
+ deletions_allowed:=false; error; deletions_allowed:=true;
+ a:=@"FFFD;
+ end;
+result := a;
+pool_to_unichar := result;
+end ;
+
+procedure print(@!s:integer); {prints string |s|}
+label exit;
+var j:pool_pointer; {current character code position}
+@!v:integer; { a unicode char }
+begin if s>=str_ptr then s:="???" {this can't happen}
+@.???@>
+else if s<string_offset then
+ if s<0 then s:="???" {can't happen}
+ else begin
+ {TH not sure about this, disabled for now!}
+ if (false)and(selector>pseudo) then
+ begin print_char(s); return; {internal strings are not expanded}
+ end;
+ if (@<Character |s| is the current new-line character@>) then
+ if selector<pseudo then
+ begin print_ln; return;
+ end;
+ if s<=@"7F then
+ print_char(s)
+ else if s<=@"7FF then begin
+ print_char(@"C0 + (s div @"40));
+ print_char(@"80 + (s mod @"40));
+ end
+ else if s<=@"FFFF then begin
+ print_char(@"E0 + (s div @"1000));
+ print_char(@"80 + ((s mod @"1000) div @"40));
+ print_char(@"80 + ((s mod @"1000) mod @"40));
+ end
+ else begin
+ if s>=@"110000 then
+ print_char(s-@"110000)
+ else begin
+ print_char(@"F0 + (s div @"40000));
+ print_char(@"80 + ((s mod @"40000) div @"1000));
+ print_char(@"80 + (((s mod @"40000) mod @"1000) div @"40));
+ print_char(@"80 + (((s mod @"40000) mod @"1000) mod @"40));
+ end;
+ end;
+ return;
+ end;
+j:=str_start_macro(s);
+while j<str_start_macro(s+1) do
+ begin { 0x110000 in utf=8: 0xF4 0x90 0x80 0x80 }
+ if (str_pool[j]=@"F4)and(j<str_start_macro(s+4))and(str_pool[j+1]=@"90) then begin
+ v := (((7*64+63)*64)+ (str_pool[j+2]-128))*64 +(str_pool[j+3]-128);
+ print_char(v-@"110000); j := j+4;
+ end
+ else begin
+ print_char(str_pool[j]); incr(j);
+ end;
+ end;
+exit:end;
+
+procedure print_nl(@!s:str_number); {prints string |s| at beginning of line}
+begin if ((term_offset>0)and(odd(selector)))or@|
+ ((file_offset>0)and(selector>=log_only)) then print_ln;
+print(s);
+end;
+
+procedure print_nlp; {move to beginning of a line}
+begin if ((term_offset>0)and(odd(selector)))or@|
+ ((file_offset>0)and(selector>=log_only)) then print_ln;
+end;
+
+@ Control sequence names, file names, and strings constructed with
+\.{\\string} might contain |ASCII_code| values that can't
+be printed using |print_char|. Therefore we use |slow_print| for them:
+
+@<Basic print...@>=
+procedure slow_print(@!s:integer); {prints string |s|}
+var j:pool_pointer; {current character code position}
+begin if (s>=str_ptr) or (s<string_offset) then print(s)
+else begin j:=str_start_macro(s);
+ while j<str_start_macro(s+1) do
+ begin print(so(str_pool[j])); incr(j);
+ end;
+ end;
+end;
+
+@ Here is the very first thing that \TeX\ prints: a headline that identifies
+the version number and format package. The |term_offset| variable is temporarily
+incorrect, but the discrepancy is not serious since we assume that the banner
+and format identifier together will occupy at most |max_print_line|
+character positions.
+
+@<Initialize the output...@>=
+print_banner;
+
+@ The procedure |print_nl| is like |print|, but it makes sure that the
+string appears at the beginning of a new line. (moved)
+
+@<Basic print...@>=
+
+@ The procedure |print_esc| prints a string that is preceded by
+the user's escape character (which is usually a backslash).
+
+@<Basic print...@>=
+procedure print_esc(@!s:str_number); {prints escape character, then |s|}
+var c:integer; {the escape character code}
+begin @<Set variable |c| to the current escape character@>;
+if c>=0 then if c<string_offset then print(c);
+slow_print(s);
+end;
+
+@ An array of digits in the range |0..15| is printed by |print_the_digs|.
+
+@<Basic print...@>=
+procedure print_the_digs(@!k:eight_bits);
+ {prints |dig[k-1]|$\,\ldots\,$|dig[0]|}
+begin while k>0 do
+ begin decr(k);
+ if dig[k]<10 then print_char("0"+dig[k])
+ else print_char("A"-10+dig[k]);
+ end;
+end;
+
+@ The following procedure, which prints out the decimal representation of a
+given integer |n|, has been written carefully so that it works properly
+if |n=0| or if |(-n)| would cause overflow. It does not apply |mod| or |div|
+to negative arguments, since such operations are not implemented consistently
+by all \PASCAL\ compilers.
+
+@<Basic print...@>=
+procedure print_int(@!n:integer); {prints an integer in decimal form}
+var k:0..23; {index to current digit; we assume that $|n|<10^{23}$}
+@!m:integer; {used to negate |n| in possibly dangerous cases}
+begin k:=0;
+if n<0 then
+ begin print_char("-");
+ if n>-100000000 then negate(n)
+ else begin m:=-1-n; n:=m div 10; m:=(m mod 10)+1; k:=1;
+ if m<10 then dig[0]:=m
+ else begin dig[0]:=0; incr(n);
+ end;
+ end;
+ end;
+repeat dig[k]:=n mod 10; n:=n div 10; incr(k);
+until n=0;
+print_the_digs(k);
+end;
+
+@ Here is a trivial procedure to print two digits; it is usually called with
+a parameter in the range |0<=n<=99|.
+
+@p procedure print_two(@!n:integer); {prints two least significant digits}
+begin n:=abs(n) mod 100; print_char("0"+(n div 10));
+print_char("0"+(n mod 10));
+end;
+
+@ Hexadecimal printing of nonnegative integers is accomplished by |print_hex|.
+
+@p procedure print_hex(@!n:integer);
+ {prints a positive integer in hexadecimal form}
+var k:0..22; {index to current digit; we assume that $0\L n<16^{22}$}
+begin k:=0; print_char("""");
+repeat dig[k]:=n mod 16; n:=n div 16; incr(k);
+until n=0;
+print_the_digs(k);
+end;
+
+@ Old versions of \TeX\ needed a procedure called |print_ASCII| whose function
+is now subsumed by |print|. We retain the old name here as a possible aid to
+future software arch\ae ologists.
+
+@d print_ASCII == print
+@d print_font_name(#)==begin print(tex_font_name(#)); flush_string; end
+
+@ Roman numerals are produced by the |print_roman_int| routine. Readers
+who like puzzles might enjoy trying to figure out how this tricky code
+works; therefore no explanation will be given. Notice that 1990 yields
+\.{mcmxc}, not \.{mxm}.
+
+@p procedure print_roman_int(@!n:integer);
+label exit;
+var j,@!k: pool_pointer; {mysterious indices into |str_pool|}
+@!u,@!v: nonnegative_integer; {mysterious numbers}
+begin j:=str_start_macro("m2d5c2l5x2v5i"); v:=1000;
+loop@+ begin while n>=v do
+ begin print_char(so(str_pool[j])); n:=n-v;
+ end;
+ if n<=0 then return; {nonpositive input produces no output}
+ k:=j+2; u:=v div (so(str_pool[k-1])-"0");
+ if str_pool[k-1]=si("2") then
+ begin k:=k+2; u:=u div (so(str_pool[k-1])-"0");
+ end;
+ if n+u>=v then
+ begin print_char(so(str_pool[k])); n:=n+u;
+ end
+ else begin j:=j+2; v:=v div (so(str_pool[j-1])-"0");
+ end;
+ end;
+exit:end;
+
+@ The |print| subroutine will not print a string that is still being
+created. The following procedure will.
+
+@p procedure print_current_string; {prints a yet-unmade string}
+var j:pool_pointer; {points to current character code}
+begin j:=str_start_macro(str_ptr);
+while j<pool_ptr do
+ begin print_char(so(str_pool[j])); incr(j);
+ end;
+end;
+
+@ Here is a procedure that asks the user to type a line of input,
+assuming that the |selector| setting is either |term_only| or |term_and_log|.
+The input is placed into locations |first| through |last-1| of the
+|buffer| array, and echoed on the transcript file if appropriate.
+
+This procedure is never called when |interaction<scroll_mode|.
+
+@<Basic print...@>=
+procedure prompt_input(s:str_number);
+begin wake_up_terminal; print(s); term_input;
+end;
+
+@
+@p procedure term_input; {gets a line from the terminal}
+var k:0..buf_size; {index into |buffer|}
+begin update_terminal; {now the user sees the prompt for sure}
+if not input_ln(term_in,true)
+then fatal_error("End of file on the terminal!");
+@.End of file on the terminal@>
+term_offset:=0; {the user's line ended with \<\rm return>}
+decr(selector); {prepare to echo the input}
+if last<>first then for k:=first to last-1 do print(buffer[k]);
+print_ln; incr(selector); {restore previous status}
+end;
+
+@* \[6] Reporting errors.
+When something anomalous is detected, \TeX\ typically does something like this:
+$$\vbox{\halign{#\hfil\cr
+|print_err("Something anomalous has been detected");|\cr
+|help3("This is the first line of my offer to help.")|\cr
+|("This is the second line. I'm trying to")|\cr
+|("explain the best way for you to proceed.");|\cr
+|error;|\cr}}$$
+A two-line help message would be given using |help2|, etc.; these informal
+helps should use simple vocabulary that complements the words used in the
+official error message that was printed. (Outside the U.S.A., the help
+messages should preferably be translated into the local vernacular. Each
+line of help is at most 60 characters long, in the present implementation,
+so that |max_print_line| will not be exceeded.)
+
+The |print_err| procedure supplies a `\.!' before the official message,
+and makes sure that the terminal is awake if a stop is going to occur.
+The |error| procedure supplies a `\..' after the official message, then it
+shows the location of the error; and if |interaction=error_stop_mode|,
+it also enters into a dialog with the user, during which time the help
+message may be printed.
+@^system dependencies@>
+
+@ The global variable |interaction| has four settings, representing increasing
+amounts of user interaction:
+
+@d batch_mode=0 {omits all stops and omits terminal output}
+@d nonstop_mode=1 {omits all stops}
+@d scroll_mode=2 {omits error stops}
+@d error_stop_mode=3 {stops at every opportunity to interact}
+@d print_err(#)==begin if interaction=error_stop_mode then wake_up_terminal;
+ print_nl("! "); print(#);
+ last_error:=#; end
+@d print_warn(#)==begin if interaction=error_stop_mode then wake_up_terminal;
+ if prepend_nl then begin print_nl(""); print_ln end;
+ print_nl(#);
+ end
+
+@<Glob...@>=
+@!interaction:batch_mode..error_stop_mode; {current level of interaction}
+@!last_error:str_number;
+
+@ @<Set init...@>=interaction:=error_stop_mode;
+
+@ \TeX\ is careful not to call |error| when the print |selector| setting
+might be unusual. The only possible values of |selector| at the time of
+error messages are
+
+\yskip\hang|no_print| (when |interaction=batch_mode|
+ and |log_file| not yet open);
+
+\hang|term_only| (when |interaction>batch_mode| and |log_file| not yet open);
+
+\hang|log_only| (when |interaction=batch_mode| and |log_file| is open);
+
+\hang|term_and_log| (when |interaction>batch_mode| and |log_file| is open).
+
+@<Initialize the print |selector| based on |interaction|@>=
+if interaction=batch_mode then selector:=no_print@+else selector:=term_only
+
+@ A global variable |deletions_allowed| is set |false| if the |get_next|
+routine is active when |error| is called; this ensures that |get_next|
+and related routines like |get_token| will never be called recursively.
+A similar interlock is provided by |set_box_allowed|.
+@^recursion@>
+
+The global variable |history| records the worst level of error that
+has been detected. It has four possible values: |spotless|, |warning_issued|,
+|error_message_issued|, and |fatal_error_stop|.
+
+Another global variable, |error_count|, is increased by one when an
+|error| occurs without an interactive dialog, and it is reset to zero at
+the end of every paragraph. If |error_count| reaches 100, \TeX\ decides
+that there is no point in continuing further.
+
+@d spotless=0 {|history| value when nothing has been amiss yet}
+@d warning_issued=1 {|history| value when |begin_diagnostic| has been called}
+@d error_message_issued=2 {|history| value when |error| has been called}
+@d fatal_error_stop=3 {|history| value when termination was premature}
+
+@<Glob...@>=
+@!deletions_allowed:boolean; {is it safe for |error| to call |get_token|?}
+@!set_box_allowed:boolean; {is it safe to do a \.{\\setbox} assignment?}
+@!history:spotless..fatal_error_stop; {has the source input been clean so far?}
+@!error_count:-1..100; {the number of scrolled errors since the
+ last paragraph ended}
+
+@ The value of |history| is initially |fatal_error_stop|, but it will
+be changed to |spotless| if \TeX\ survives the initialization process.
+
+@<Set init...@>=
+deletions_allowed:=true; set_box_allowed:=true;
+error_count:=0; {|history| is initialized elsewhere}
+
+@ Since errors can be detected almost anywhere in \TeX, we want to declare the
+error procedures near the beginning of the program. But the error procedures
+in turn use some other procedures, which need to be declared |forward|
+before we get to |error| itself.
+
+It is possible for |error| to be called recursively if some error arises
+when |get_token| is being used to delete a token, and/or if some fatal error
+occurs while \TeX\ is trying to fix a non-fatal one. But such recursion
+@^recursion@>
+is never more than two levels deep.
+
+@<Error handling...@>=
+procedure@?normalize_selector; forward;@t\2@>@/
+procedure@?get_token; forward;@t\2@>@/
+procedure@?term_input; forward;@t\2@>@/
+procedure@?show_context; forward;@t\2@>@/
+procedure@?begin_file_reading; forward;@t\2@>@/
+procedure@?open_log_file; forward;@t\2@>@/
+procedure@?close_files_and_terminate; forward;@t\2@>@/
+procedure@?clear_for_error_prompt; forward;@t\2@>@/
+procedure@?give_err_help; forward;@t\2@>@/
+@t\4\hskip-\fontdimen2\font@>@;@+@!debug@+procedure@?debug_help;
+ forward;@;@+gubed
+
+@ Individual lines of help are recorded in the array |help_line|, which
+contains entries in positions |0..(help_ptr-1)|. They should be printed
+in reverse order, i.e., with |help_line[0]| appearing last.
+
+@d hlp1(#)==help_line[0]:=#;@+end
+@d hlp2(#)==help_line[1]:=#; hlp1
+@d hlp3(#)==help_line[2]:=#; hlp2
+@d hlp4(#)==help_line[3]:=#; hlp3
+@d hlp5(#)==help_line[4]:=#; hlp4
+@d hlp6(#)==help_line[5]:=#; hlp5
+@d help0==help_ptr:=0 {sometimes there might be no help}
+@d help1==@+begin help_ptr:=1; hlp1 {use this with one help line}
+@d help2==@+begin help_ptr:=2; hlp2 {use this with two help lines}
+@d help3==@+begin help_ptr:=3; hlp3 {use this with three help lines}
+@d help4==@+begin help_ptr:=4; hlp4 {use this with four help lines}
+@d help5==@+begin help_ptr:=5; hlp5 {use this with five help lines}
+@d help6==@+begin help_ptr:=6; hlp6 {use this with six help lines}
+
+@p
+procedure dohelp5 (@!a,b,c,d,e:str_number);
+begin
+ help5(a)(b)(c)(d)(e);
+end;
+@#
+procedure dohelp4 (@!a,b,c,d:str_number);
+begin
+ help4(a)(b)(c)(d);
+end;
+@#
+procedure dohelp3 (@!a,b,c:str_number);
+begin
+ help3(a)(b)(c);
+end;
+@#
+procedure dohelp2 (@!a,b:str_number);
+begin
+ help2(a)(b);
+end;
+@#
+procedure dohelp1 (@!a:str_number);
+begin
+ help1(a);
+end;
+@#
+procedure do_print_err (s:str_number);
+begin
+ print_err(s);
+end;
+
+@ @<Glob...@>=
+@!help_line:array[0..5] of str_number; {helps for the next |error|}
+@!help_ptr:0..6; {the number of help lines present}
+@!use_err_help:boolean; {should the |err_help| list be shown?}
+
+@ @<Set init...@>=
+help_ptr:=0; use_err_help:=false;
+
+@ The |jump_out| procedure just cuts across all active procedure levels and
+goes to |end_of_TEX|. This is the only nontrivial |@!goto| statement in the
+whole program. It is used when there is no recovery from a particular error.
+
+Some \PASCAL\ compilers do not implement non-local |goto| statements.
+@^system dependencies@>
+In such cases the body of |jump_out| should simply be
+`|close_files_and_terminate|;\thinspace' followed by a call on some system
+procedure that quietly terminates the program.
+
+@<Error hand...@>=
+procedure jump_out;
+begin goto end_of_TEX;
+end;
+
+@ Here now is the general |error| routine.
+
+@<Error hand...@>=
+procedure error; {completes the job of error reporting}
+label continue,exit;
+var c:ASCII_code; {what the user types}
+callback_id:integer;
+@!s1,@!s2,@!s3,@!s4:integer;
+ {used to save global variables when deleting tokens}
+@!t:boolean;
+begin if history<error_message_issued then history:=error_message_issued;
+print_char(".");
+callback_id := callback_defined(show_error_hook_callback) ;
+if callback_id>0 then t := run_callback(callback_id,'->');
+show_context;
+if interaction=error_stop_mode then @<Get user's advice and |return|@>;
+incr(error_count);
+if error_count=100 then
+ begin print_nl("(That makes 100 errors; please try again.)");
+@.That makes 100 errors...@>
+ history:=fatal_error_stop; jump_out;
+ end;
+@<Put help message on the transcript file@>;
+exit:end;
+
+@ @<Get user's advice...@>=
+loop@+begin continue: clear_for_error_prompt; prompt_input("? ");
+@.?\relax@>
+ if last=first then return;
+ c:=buffer[first];
+ if c>="a" then c:=c+"A"-"a"; {convert to uppercase}
+ @<Interpret code |c| and |return| if done@>;
+ end
+
+@ It is desirable to provide an `\.E' option here that gives the user
+an easy way to return from \TeX\ to the system editor, with the offending
+line ready to be edited. But such an extension requires some system
+wizardry, so the present implementation simply types out the name of the
+file that should be
+edited and the relevant line number.
+@^system dependencies@>
+
+There is a secret `\.D' option available when the debugging routines haven't
+been commented~out.
+@^debugging@>
+
+@<Interpret code |c| and |return| if done@>=
+case c of
+"0","1","2","3","4","5","6","7","8","9": if deletions_allowed then
+ @<Delete \(c)|c-"0"| tokens and |goto continue|@>;
+@t\4\4@>@;@+@!debug "D": begin debug_help; goto continue;@+end;@+gubed@/
+"E": if base_ptr>0 then
+ begin print_nl("You want to edit file ");
+@.You want to edit file x@>
+ slow_print(input_stack[base_ptr].name_field);
+ print(" at line "); print_int(line);
+ interaction:=scroll_mode; jump_out;
+ end;
+"H": @<Print the help information and |goto continue|@>;
+"I":@<Introduce new material from the terminal and |return|@>;
+"Q","R","S":@<Change the interaction level and |return|@>;
+"X":begin interaction:=scroll_mode; jump_out;
+ end;
+othercases do_nothing
+endcases;@/
+@<Print the menu of available options@>
+
+@ @<Print the menu...@>=
+begin print("Type <return> to proceed, S to scroll future error messages,");@/
+@.Type <return> to proceed...@>
+print_nl("R to run without stopping, Q to run quietly,");@/
+print_nl("I to insert something, ");
+if base_ptr>0 then print("E to edit your file,");
+if deletions_allowed then
+ print_nl("1 or ... or 9 to ignore the next 1 to 9 tokens of input,");
+print_nl("H for help, X to quit.");
+end
+
+@ Here the author of \TeX\ apologizes for making use of the numerical
+relation between |"Q"|, |"R"|, |"S"|, and the desired interaction settings
+|batch_mode|, |nonstop_mode|, |scroll_mode|.
+@^Knuth, Donald Ervin@>
+
+@<Change the interaction...@>=
+begin error_count:=0; interaction:=batch_mode+c-"Q";
+print("OK, entering ");
+case c of
+"Q":begin print_esc("batchmode"); decr(selector);
+ end;
+"R":print_esc("nonstopmode");
+"S":print_esc("scrollmode");
+end; {there are no other cases}
+print("..."); print_ln; update_terminal; return;
+end
+
+@ When the following code is executed, |buffer[(first+1)..(last-1)]| may
+contain the material inserted by the user; otherwise another prompt will
+be given. In order to understand this part of the program fully, you need
+to be familiar with \TeX's input stacks.
+
+@<Introduce new material...@>=
+begin begin_file_reading; {enter a new syntactic level for terminal input}
+{now |state=mid_line|, so an initial blank space will count as a blank}
+if last>first+1 then
+ begin loc:=first+1; buffer[first]:=" ";
+ end
+else begin prompt_input("insert>"); loc:=first;
+@.insert>@>
+ end;
+first:=last;
+cur_input.limit_field:=last-1; {no |end_line_char| ends this line}
+return;
+end
+
+@ We allow deletion of up to 99 tokens at a time.
+
+@<Delete \(c)|c-"0"| tokens...@>=
+begin s1:=cur_tok; s2:=cur_cmd; s3:=cur_chr; s4:=align_state;
+align_state:=1000000; OK_to_interrupt:=false;
+if (last>first+1) and (buffer[first+1]>="0")and(buffer[first+1]<="9") then
+ c:=c*10+buffer[first+1]-"0"*11
+else c:=c-"0";
+while c>0 do
+ begin get_token; {one-level recursive call of |error| is possible}
+ decr(c);
+ end;
+cur_tok:=s1; cur_cmd:=s2; cur_chr:=s3; align_state:=s4; OK_to_interrupt:=true;
+help2("I have just deleted some text, as you asked.")@/
+("You can now delete more, or insert, or whatever.");
+show_context; goto continue;
+end
+
+@ @<Print the help info...@>=
+begin if use_err_help then
+ begin give_err_help; use_err_help:=false;
+ end
+else begin if help_ptr=0 then
+ help2("Sorry, I don't know how to help in this situation.")@/
+ @t\kern1em@>("Maybe you should try asking a human?");
+ repeat decr(help_ptr); print(help_line[help_ptr]); print_ln;
+ until help_ptr=0;
+ end;
+help4("Sorry, I already gave what help I could...")@/
+ ("Maybe you should try asking a human?")@/
+ ("An error might have occurred before I noticed any problems.")@/
+ ("``If all else fails, read the instructions.''");@/
+goto continue;
+end
+
+@ @<Put help message on the transcript file@>=
+if interaction>batch_mode then decr(selector); {avoid terminal output}
+if use_err_help then
+ begin print_ln; give_err_help;
+ end
+else while help_ptr>0 do
+ begin decr(help_ptr); print_nl(help_line[help_ptr]);
+ end;
+print_ln;
+if interaction>batch_mode then incr(selector); {re-enable terminal output}
+print_ln
+
+@ A dozen or so error messages end with a parenthesized integer, so we
+save a teeny bit of program space by declaring the following procedure:
+
+@p procedure int_error(@!n:integer);
+begin print(" ("); print_int(n); print_char(")"); error;
+end;
+
+@ In anomalous cases, the print selector might be in an unknown state;
+the following subroutine is called to fix things just enough to keep
+running a bit longer.
+
+@p procedure normalize_selector;
+begin if log_opened then selector:=term_and_log
+else selector:=term_only;
+if job_name=0 then open_log_file;
+if interaction=batch_mode then decr(selector);
+end;
+
+@ The following procedure prints \TeX's last words before dying.
+
+@d succumb==begin if interaction=error_stop_mode then
+ interaction:=scroll_mode; {no more interaction}
+ if log_opened then error;
+ @!debug if interaction>batch_mode then debug_help;@+gubed@;@/
+ history:=fatal_error_stop; jump_out; {irrecoverable error}
+ end
+
+@<Error hand...@>=
+procedure fatal_error(@!s:str_number); {prints |s|, and that's it}
+begin normalize_selector;@/
+print_err("Emergency stop"); help1(s); succumb;
+@.Emergency stop@>
+end;
+
+@ Here is the most dreaded error message.
+
+@<Error hand...@>=
+procedure lua_norm_error(@!s:str_number); {lua found a problem}
+begin
+print_err("LuaTeX error "); print(s);
+help2("The lua interpreter ran into a problem, so the")@/
+ ("remainder of this lua chunk will be ignored.");
+error;
+end;
+
+procedure lua_fatal_error(@!s:str_number); {lua found a problem}
+begin normalize_selector;
+print_err("LuaTeX fatal error "); print(s);
+succumb;
+end;
+
+procedure overflow(@!s:str_number;@!n:integer); {stop due to finiteness}
+begin normalize_selector;
+print_err("TeX capacity exceeded, sorry [");
+@.TeX capacity exceeded ...@>
+print(s); print_char("="); print_int(n); print_char("]");
+help2("If you really absolutely need more capacity,")@/
+ ("you can ask a wizard to enlarge me.");
+succumb;
+end;
+
+procedure overflow_ocp_buf_size;
+begin
+overflow("ocp_buf_size",ocp_buf_size);
+end;
+
+procedure overflow_ocp_stack_size;
+begin
+overflow("ocp_stack_size",ocp_stack_size);
+end;
+
+
+@ The program might sometime run completely amok, at which point there is
+no choice but to stop. If no previous error has been detected, that's bad
+news; a message is printed that is really intended for the \TeX\
+maintenance person instead of the user (unless the user has been
+particularly diabolical). The index entries for `this can't happen' may
+help to pinpoint the problem.
+@^dry rot@>
+
+@<Error hand...@>=
+procedure confusion(@!s:str_number);
+ {consistency check violated; |s| tells where}
+begin normalize_selector;
+if history<error_message_issued then
+ begin print_err("This can't happen ("); print(s); print_char(")");
+@.This can't happen@>
+ help1("I'm broken. Please show this to someone who can fix can fix");
+ end
+else begin print_err("I can't go on meeting you like this");
+@.I can't go on...@>
+ help2("One of your faux pas seems to have wounded me deeply...")@/
+ ("in fact, I'm barely conscious. Please fix it and try again.");
+ end;
+succumb;
+end;
+
+@ Users occasionally want to interrupt \TeX\ while it's running.
+If the \PASCAL\ runtime system allows this, one can implement
+a routine that sets the global variable |interrupt| to some nonzero value
+when such an interrupt is signalled. Otherwise there is probably at least
+a way to make |interrupt| nonzero using the \PASCAL\ debugger.
+@^system dependencies@>
+@^debugging@>
+
+@<Global...@>=
+@!interrupt:integer; {should \TeX\ pause for instructions?}
+@!OK_to_interrupt:boolean; {should interrupts be observed?}
+@!detokenized_line:boolean; {indicates this is a 'detokenized' input line }
+@!line_catcode_table:integer; {the used catcode table for input lines}
+@!local_catcode_table:boolean; {the used catcode table for input lines}
+@!static_int_base:integer; {C version of |int_base|}
+
+@ @p procedure check_interrupt;
+begin
+if interrupt<>0 then pause_for_instructions;
+end;
+
+
+@ @<Set init...@>=
+interrupt:=0; OK_to_interrupt:=true; detokenized_line:=false;
+line_catcode_table:=0; local_catcode_table:=false;
+
+@ When an interrupt has been detected, the program goes into its
+highest interaction level and lets the user have nearly the full flexibility of
+the |error| routine. \TeX\ checks for interrupts only at times when it is
+safe to do this.
+
+@p procedure pause_for_instructions;
+begin if OK_to_interrupt then
+ begin interaction:=error_stop_mode;
+ if (selector=log_only)or(selector=no_print) then
+ incr(selector);
+ print_err("Interruption");
+@.Interruption@>
+ help3("You rang?")@/
+ ("Try to insert some instructions for me (e.g.,`I\showlists'),")@/
+ ("unless you just want to quit by typing `X'.");
+ deletions_allowed:=false; error; deletions_allowed:=true;
+ interrupt:=0;
+ end;
+end;
+
+@* \[7] Arithmetic with scaled dimensions.
+The principal computations performed by \TeX\ are done entirely in terms of
+integers less than $2^{31}$ in magnitude; and divisions are done only when both
+dividend and divisor are nonnegative. Thus, the arithmetic specified in this
+program can be carried out in exactly the same way on a wide variety of
+computers, including some small ones. Why? Because the arithmetic
+calculations need to be spelled out precisely in order to guarantee that
+\TeX\ will produce identical output on different machines. If some
+quantities were rounded differently in different implementations, we would
+find that line breaks and even page breaks might occur in different places.
+Hence the arithmetic of \TeX\ has been designed with care, and systems that
+claim to be implementations of \TeX82 should follow precisely the
+@:TeX82}{\TeX82@>
+calculations as they appear in the present program.
+
+(Actually there are three places where \TeX\ uses |div| with a possibly negative
+numerator. These are harmless; see |div| in the index. Also if the user
+sets the \.{\\time} or the \.{\\year} to a negative value, some diagnostic
+information will involve negative-numerator division. The same remarks
+apply for |mod| as well as for |div|.)
+
+@ Here is a routine that calculates half of an integer, using an
+unambiguous convention with respect to signed odd numbers.
+
+@p function half(@!x:integer):integer;
+begin if odd(x) then half:=(x+1) div 2
+else half:=x @!div 2;
+end;
+
+@ Fixed-point arithmetic is done on {\sl scaled integers\/} that are multiples
+of $2^{-16}$. In other words, a binary point is assumed to be sixteen bit
+positions from the right end of a binary computer word.
+
+@d unity == @'200000 {$2^{16}$, represents 1.00000}
+@d two == @'400000 {$2^{17}$, represents 2.00000}
+
+@<Types...@>=
+@!scaled = integer; {this type is used for scaled integers}
+@!nonnegative_integer=0..@'17777777777; {$0\L x<2^{31}$}
+@!small_number=0..63; {this type is self-explanatory}
+
+@ The following function is used to create a scaled integer from a given decimal
+fraction $(.d_0d_1\ldots d_{k-1})$, where |0<=k<=17|. The digit $d_i$ is
+given in |dig[i]|, and the calculation produces a correctly rounded result.
+
+@p function round_decimals(@!k:small_number) : scaled;
+ {converts a decimal fraction}
+var a:integer; {the accumulator}
+begin a:=0;
+while k>0 do
+ begin decr(k); a:=(a+dig[k]*two) div 10;
+ end;
+round_decimals:=(a+1) div 2;
+end;
+
+@ Conversely, here is a procedure analogous to |print_int|. If the output
+of this procedure is subsequently read by \TeX\ and converted by the
+|round_decimals| routine above, it turns out that the original value will
+be reproduced exactly; the ``simplest'' such decimal number is output,
+but there is always at least one digit following the decimal point.
+
+The invariant relation in the \&{repeat} loop is that a sequence of
+decimal digits yet to be printed will yield the original number if and only if
+they form a fraction~$f$ in the range $s-\delta\L10\cdot2^{16}f<s$.
+We can stop if and only if $f=0$ satisfies this condition; the loop will
+terminate before $s$ can possibly become zero.
+
+@p procedure print_scaled(@!s:scaled); {prints scaled real, rounded to five
+ digits}
+var delta:scaled; {amount of allowable inaccuracy}
+begin if s<0 then
+ begin print_char("-"); negate(s); {print the sign, if negative}
+ end;
+print_int(s div unity); {print the integer part}
+print_char(".");
+s:=10*(s mod unity)+5; delta:=10;
+repeat if delta>unity then s:=s+@'100000-50000; {round the last digit}
+print_char("0"+(s div unity)); s:=10*(s mod unity); delta:=delta*10;
+until s<=delta;
+end;
+
+@ Physical sizes that a \TeX\ user specifies for portions of documents are
+represented internally as scaled points. Thus, if we define an `sp' (scaled
+@^sp@>
+point) as a unit equal to $2^{-16}$ printer's points, every dimension
+inside of \TeX\ is an integer number of sp. There are exactly
+4,736,286.72 sp per inch. Users are not allowed to specify dimensions
+larger than $2^{30}-1$ sp, which is a distance of about 18.892 feet (5.7583
+meters); two such quantities can be added without overflow on a 32-bit
+computer.
+
+The present implementation of \TeX\ does not check for overflow when
+@^Overflow in arithmetic@>
+dimensions are added or subtracted. This could be done by inserting a
+few dozen tests of the form `\ignorespaces|if x>=@'10000000000 then
+@t\\{report\_overflow}@>|', but the chance of overflow is so remote that
+such tests do not seem worthwhile.
+
+\TeX\ needs to do only a few arithmetic operations on scaled quantities,
+other than addition and subtraction, and the following subroutines do most of
+the work. A single computation might use several subroutine calls, and it is
+desirable to avoid producing multiple error messages in case of arithmetic
+overflow; so the routines set the global variable |arith_error| to |true|
+instead of reporting errors directly to the user. Another global variable,
+|remainder|, holds the remainder after a division.
+
+@<Glob...@>=
+@!arith_error:boolean; {has arithmetic overflow occurred recently?}
+@!remainder:scaled; {amount subtracted to get an exact division}
+
+@ The first arithmetical subroutine we need computes $nx+y$, where |x|
+and~|y| are |scaled| and |n| is an integer. We will also use it to
+multiply integers.
+
+@d nx_plus_y(#)==mult_and_add(#,@'7777777777)
+@d mult_integers(#)==mult_and_add(#,0,@'17777777777)
+
+@p function mult_and_add(@!n:integer;@!x,@!y,@!max_answer:scaled):scaled;
+begin if n<0 then
+ begin negate(x); negate(n);
+ end;
+if n=0 then mult_and_add:=y
+else if ((x<=(max_answer-y) div n)and(-x<=(max_answer+y) div n)) then
+ mult_and_add:=n*x+y
+else begin arith_error:=true; mult_and_add:=0;
+ end;
+end;
+
+@ We also need to divide scaled dimensions by integers.
+
+@p function x_over_n(@!x:scaled;@!n:integer):scaled;
+var negative:boolean; {should |remainder| be negated?}
+begin negative:=false;
+if n=0 then
+ begin arith_error:=true; x_over_n:=0; remainder:=x;
+ end
+else begin if n<0 then
+ begin negate(x); negate(n); negative:=true;
+ end;
+ if x>=0 then
+ begin x_over_n:=x div n; remainder:=x mod n;
+ end
+ else begin x_over_n:=-((-x) div n); remainder:=-((-x) mod n);
+ end;
+ end;
+if negative then negate(remainder);
+end;
+
+@ Then comes the multiplication of a scaled number by a fraction |n/d|,
+where |n| and |d| are nonnegative integers |<=@t$2^{16}$@>| and |d| is
+positive. It would be too dangerous to multiply by~|n| and then divide
+by~|d|, in separate operations, since overflow might well occur; and it
+would be too inaccurate to divide by |d| and then multiply by |n|. Hence
+this subroutine simulates 1.5-precision arithmetic.
+
+@p function xn_over_d(@!x:scaled; @!n,@!d:integer):scaled;
+var positive:boolean; {was |x>=0|?}
+@!t,@!u,@!v:nonnegative_integer; {intermediate quantities}
+begin if x>=0 then positive:=true
+else begin negate(x); positive:=false;
+ end;
+t:=(x mod @'100000)*n;
+u:=(x div @'100000)*n+(t div @'100000);
+v:=(u mod d)*@'100000 + (t mod @'100000);
+if u div d>=@'100000 then arith_error:=true
+else u:=@'100000*(u div d) + (v div d);
+if positive then
+ begin xn_over_d:=u; remainder:=v mod d;
+ end
+else begin xn_over_d:=-u; remainder:=-(v mod d);
+ end;
+end;
+
+@ The next subroutine is used to compute the ``badness'' of glue, when a
+total~|t| is supposed to be made from amounts that sum to~|s|. According
+to {\sl The \TeX book}, the badness of this situation is $100(t/s)^3$;
+however, badness is simply a heuristic, so we need not squeeze out the
+last drop of accuracy when computing it. All we really want is an
+approximation that has similar properties.
+@:TeXbook}{\sl The \TeX book@>
+
+The actual method used to compute the badness is easier to read from the
+program than to describe in words. It produces an integer value that is a
+reasonably close approximation to $100(t/s)^3$, and all implementations
+of \TeX\ should use precisely this method. Any badness of $2^{13}$ or more is
+treated as infinitely bad, and represented by 10000.
+
+It is not difficult to prove that $$\hbox{|badness(t+1,s)>=badness(t,s)
+>=badness(t,s+1)|}.$$ The badness function defined here is capable of
+computing at most 1095 distinct values, but that is plenty.
+
+@d inf_bad = 10000 {infinitely bad value}
+
+@p function badness(@!t,@!s:scaled):halfword; {compute badness, given |t>=0|}
+var r:integer; {approximation to $\alpha t/s$, where $\alpha^3\approx
+ 100\cdot2^{18}$}
+begin if t=0 then badness:=0
+else if s<=0 then badness:=inf_bad
+else begin if t<=7230584 then r:=(t*297) div s {$297^3=99.94\times2^{18}$}
+ else if s>=1663497 then r:=t div (s div 297)
+ else r:=t;
+ if r>1290 then badness:=inf_bad {$1290^3<2^{31}<1291^3$}
+ else badness:=(r*r*r+@'400000) div @'1000000;
+ end; {that was $r^3/2^{18}$, rounded to the nearest integer}
+end;
+
+@ When \TeX\ ``packages'' a list into a box, it needs to calculate the
+proportionality ratio by which the glue inside the box should stretch
+or shrink. This calculation does not affect \TeX's decision making,
+so the precise details of rounding, etc., in the glue calculation are not
+of critical importance for the consistency of results on different computers.
+
+We shall use the type |glue_ratio| for such proportionality ratios.
+A glue ratio should take the same amount of memory as an
+|integer| (usually 32 bits) if it is to blend smoothly with \TeX's
+other data structures. Thus |glue_ratio| should be equivalent to
+|short_real| in some implementations of \PASCAL. Alternatively,
+it is possible to deal with glue ratios using nothing but fixed-point
+arithmetic; see {\sl TUGboat \bf3},1 (March 1982), 10--27. (But the
+routines cited there must be modified to allow negative glue ratios.)
+@^system dependencies@>
+
+@d set_glue_ratio_zero(#) == #:=0.0 {store the representation of zero ratio}
+@d set_glue_ratio_one(#) == #:=1.0 {store the representation of unit ratio}
+@d float(#) == # {convert from |glue_ratio| to type |real|}
+@d unfloat(#) == # {convert from |real| to type |glue_ratio|}
+@d float_constant(#) == #.0 {convert |integer| constant to |real|}
+
+@<Types...@>=
+@!glue_ratio=real; {one-word representation of a glue expansion factor}
+
+@* \[7b] Random numbers.
+
+\font\tenlogo=logo10 % font used for the METAFONT logo
+\def\MP{{\tenlogo META}\-{\tenlogo POST}}
+
+This section is (almost) straight from MetaPost. I had to change
+the types (use |integer| instead of |fraction|), but that should
+not have any influence on the actual calculations (the original
+comments refer to quantities like |fraction_four| ($2^{30}$), and
+that is the same as the numeric representation of |maxdimen|).
+
+I've copied the low-level variables and routines that are needed, but
+only those (e.g. |m_log|), not the accompanying ones like |m_exp|. Most
+of the following low-level numeric routines are only needed within the
+calculation of |norm_rand|. I've been forced to rename |make_fraction|
+to |make_frac| because TeX already has a routine by that name with
+a wholly different function (it creates a |fraction_noad| for math
+typesetting) -- Taco
+
+And now let's complete our collection of numeric utility routines
+by considering random number generation.
+\MP\ generates pseudo-random numbers with the additive scheme recommended
+in Section 3.6 of {\sl The Art of Computer Programming}; however, the
+results are random fractions between 0 and |fraction_one-1|, inclusive.
+
+There's an auxiliary array |randoms| that contains 55 pseudo-random
+fractions. Using the recurrence $x_n=(x_{n-55}-x_{n-31})\bmod 2^{28}$,
+we generate batches of 55 new $x_n$'s at a time by calling |new_randoms|.
+The global variable |j_random| tells which element has most recently
+been consumed.
+
+@<Glob...@>=
+@!randoms:array[0..54] of integer; {the last 55 random values generated}
+@!j_random:0..54; {the number of unused |randoms|}
+@!random_seed:scaled; {the default random seed}
+
+@ A small bit of metafont is needed.
+
+@d fraction_half==@'1000000000 {$2^{27}$, represents 0.50000000}
+@d fraction_one==@'2000000000 {$2^{28}$, represents 1.00000000}
+@d fraction_four==@'10000000000 {$2^{30}$, represents 4.00000000}
+@d el_gordo == @'17777777777 {$2^{31}-1$, the largest value that \MP\ likes}
+@d halfp(#)==(#) div 2
+@d double(#) == #:=#+# {multiply a variable by two}
+
+@ The |make_frac| routine produces the |fraction| equivalent of
+|p/q|, given integers |p| and~|q|; it computes the integer
+$f=\lfloor2^{28}p/q+{1\over2}\rfloor$, when $p$ and $q$ are
+positive. If |p| and |q| are both of the same scaled type |t|,
+the ``type relation'' |make_frac(t,t)=fraction| is valid;
+and it's also possible to use the subroutine ``backwards,'' using
+the relation |make_frac(t,fraction)=t| between scaled types.
+
+If the result would have magnitude $2^{31}$ or more, |make_frac|
+sets |arith_error:=true|. Most of \MP's internal computations have
+been designed to avoid this sort of error.
+
+If this subroutine were programmed in assembly language on a typical
+machine, we could simply compute |(@t$2^{28}$@>*p)div q|, since a
+double-precision product can often be input to a fixed-point division
+instruction. But when we are restricted to \PASCAL\ arithmetic it
+is necessary either to resort to multiple-precision maneuvering
+or to use a simple but slow iteration. The multiple-precision technique
+would be about three times faster than the code adopted here, but it
+would be comparatively long and tricky, involving about sixteen
+additional multiplications and divisions.
+
+This operation is part of \MP's ``inner loop''; indeed, it will
+consume nearly 10\pct! of the running time (exclusive of input and output)
+if the code below is left unchanged. A machine-dependent recoding
+will therefore make \MP\ run faster. The present implementation
+is highly portable, but slow; it avoids multiplication and division
+except in the initial stage. System wizards should be careful to
+replace it with a routine that is guaranteed to produce identical
+results in all cases.
+@^system dependencies@>
+
+As noted below, a few more routines should also be replaced by machine-dependent
+code, for efficiency. But when a procedure is not part of the ``inner loop,''
+such changes aren't advisable; simplicity and robustness are
+preferable to trickery, unless the cost is too high.
+@^inner loop@>
+
+@p function make_frac(@!p,@!q:integer):integer;
+var @!f:integer; {the fraction bits, with a leading 1 bit}
+@!n:integer; {the integer part of $\vert p/q\vert$}
+@!negative:boolean; {should the result be negated?}
+@!be_careful:integer; {disables certain compiler optimizations}
+begin if p>=0 then negative:=false
+else begin negate(p); negative:=true;
+ end;
+if q<=0 then
+ begin debug if q=0 then confusion("/");@;@+gubed@;@/
+@:this can't happen /}{\quad \./@>
+ negate(q); negative:=not negative;
+ end;
+n:=p div q; p:=p mod q;
+if n>=8 then
+ begin arith_error:=true;
+ if negative then make_frac:=-el_gordo@+else make_frac:=el_gordo;
+ end
+else begin n:=(n-1)*fraction_one;
+ @<Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$@>;
+ if negative then make_frac:=-(f+n)@+else make_frac:=f+n;
+ end;
+end;
+
+@ The |repeat| loop here preserves the following invariant relations
+between |f|, |p|, and~|q|:
+(i)~|0<=p<q|; (ii)~$fq+p=2^k(q+p_0)$, where $k$ is an integer and
+$p_0$ is the original value of~$p$.
+
+Notice that the computation specifies
+|(p-q)+p| instead of |(p+p)-q|, because the latter could overflow.
+Let us hope that optimizing compilers do not miss this point; a
+special variable |be_careful| is used to emphasize the necessary
+order of computation. Optimizing compilers should keep |be_careful|
+in a register, not store it in memory.
+@^inner loop@>
+
+@<Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$@>=
+f:=1;
+repeat be_careful:=p-q; p:=be_careful+p;
+if p>=0 then f:=f+f+1
+else begin double(f); p:=p+q;
+ end;
+until f>=fraction_one;
+be_careful:=p-q;
+if be_careful+p>=0 then incr(f)
+
+@
+
+@p function take_frac(@!q:integer;@!f:integer):integer;
+var @!p:integer; {the fraction so far}
+@!negative:boolean; {should the result be negated?}
+@!n:integer; {additional multiple of $q$}
+@!be_careful:integer; {disables certain compiler optimizations}
+begin @<Reduce to the case that |f>=0| and |q>0|@>;
+if f<fraction_one then n:=0
+else begin n:=f div fraction_one; f:=f mod fraction_one;
+ if q<=el_gordo div n then n:=n*q
+ else begin arith_error:=true; n:=el_gordo;
+ end;
+ end;
+f:=f+fraction_one;
+@<Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$@>;
+be_careful:=n-el_gordo;
+if be_careful+p>0 then
+ begin arith_error:=true; n:=el_gordo-p;
+ end;
+if negative then take_frac:=-(n+p)
+else take_frac:=n+p;
+end;
+
+@ @<Reduce to the case that |f>=0| and |q>0|@>=
+if f>=0 then negative:=false
+else begin negate(f); negative:=true;
+ end;
+if q<0 then
+ begin negate(q); negative:=not negative;
+ end;
+
+@ The invariant relations in this case are (i)~$\lfloor(qf+p)/2^k\rfloor
+=\lfloor qf_0/2^{28}+{1\over2}\rfloor$, where $k$ is an integer and
+$f_0$ is the original value of~$f$; (ii)~$2^k\L f<2^{k+1}$.
+@^inner loop@>
+
+@<Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$@>=
+p:=fraction_half; {that's $2^{27}$; the invariants hold now with $k=28$}
+if q<fraction_four then
+ repeat if odd(f) then p:=halfp(p+q)@+else p:=halfp(p);
+ f:=halfp(f);
+ until f=1
+else repeat if odd(f) then p:=p+halfp(q-p)@+else p:=halfp(p);
+ f:=halfp(f);
+ until f=1
+
+@ The subroutines for logarithm and exponential involve two tables.
+The first is simple: |two_to_the[k]| equals $2^k$. The second involves
+a bit more calculation, which the author claims to have done correctly:
+|spec_log[k]| is $2^{27}$ times $\ln\bigl(1/(1-2^{-k})\bigr)=
+2^{-k}+{1\over2}2^{-2k}+{1\over3}2^{-3k}+\cdots\,$, rounded to the
+nearest integer.
+
+@<Glob...@>=
+@!two_to_the:array[0..30] of integer; {powers of two}
+@!spec_log:array[1..28] of integer; {special logarithms}
+
+
+@ @<Set init...@>=
+two_to_the[0]:=1;
+for k:=1 to 30 do two_to_the[k]:=2*two_to_the[k-1];
+spec_log[1]:=93032640;
+spec_log[2]:=38612034;
+spec_log[3]:=17922280;
+spec_log[4]:=8662214;
+spec_log[5]:=4261238;
+spec_log[6]:=2113709;
+spec_log[7]:=1052693;
+spec_log[8]:=525315;
+spec_log[9]:=262400;
+spec_log[10]:=131136;
+spec_log[11]:=65552;
+spec_log[12]:=32772;
+spec_log[13]:=16385;
+for k:=14 to 27 do spec_log[k]:=two_to_the[27-k];
+spec_log[28]:=1;
+
+@
+
+@p function m_log(@!x:integer):integer;
+var @!y,@!z:integer; {auxiliary registers}
+@!k:integer; {iteration counter}
+begin if x<=0 then @<Handle non-positive logarithm@>
+else begin y:=1302456956+4-100; {$14\times2^{27}\ln2\approx1302456956.421063$}
+ z:=27595+6553600; {and $2^{16}\times .421063\approx 27595$}
+ while x<fraction_four do
+ begin double(x); y:=y-93032639; z:=z-48782;
+ end; {$2^{27}\ln2\approx 93032639.74436163$
+ and $2^{16}\times.74436163\approx 48782$}
+ y:=y+(z div unity); k:=2;
+ while x>fraction_four+4 do
+ @<Increase |k| until |x| can be multiplied by a
+ factor of $2^{-k}$, and adjust $y$ accordingly@>;
+ m_log:=y div 8;
+ end;
+end;
+
+@ @<Increase |k| until |x| can...@>=
+begin z:=((x-1) div two_to_the[k])+1; {$z=\lceil x/2^k\rceil$}
+while x<fraction_four+z do
+ begin z:=halfp(z+1); k:=k+1;
+ end;
+y:=y+spec_log[k]; x:=x-z;
+end
+
+@ @<Handle non-positive logarithm@>=
+begin print_err("Logarithm of ");
+@.Logarithm...replaced by 0@>
+print_scaled(x); print(" has been replaced by 0");
+help2("Since I don't take logs of non-positive numbers,")@/
+ ("I'm zeroing this one. Proceed, with fingers crossed.");
+error; m_log:=0;
+end
+
+@ The following somewhat different subroutine tests rigorously if $ab$ is
+greater than, equal to, or less than~$cd$,
+given integers $(a,b,c,d)$. In most cases a quick decision is reached.
+The result is $+1$, 0, or~$-1$ in the three respective cases.
+
+@d return_sign(#)==begin ab_vs_cd:=#; return;
+ end
+
+@p function ab_vs_cd(@!a,b,c,d:integer):integer;
+label exit;
+var @!q,@!r:integer; {temporary registers}
+begin @<Reduce to the case that |a,c>=0|, |b,d>0|@>;
+loop@+ begin q := a div d; r := c div b;
+ if q<>r then
+ if q>r then return_sign(1)@+else return_sign(-1);
+ q := a mod d; r := c mod b;
+ if r=0 then
+ if q=0 then return_sign(0)@+else return_sign(1);
+ if q=0 then return_sign(-1);
+ a:=b; b:=q; c:=d; d:=r;
+ end; {now |a>d>0| and |c>b>0|}
+exit:end;
+
+@ @<Reduce to the case that |a...@>=
+if a<0 then
+ begin negate(a); negate(b);
+ end;
+if c<0 then
+ begin negate(c); negate(d);
+ end;
+if d<=0 then
+ begin if b>=0 then
+ if ((a=0)or(b=0))and((c=0)or(d=0)) then return_sign(0)
+ else return_sign(1);
+ if d=0 then
+ if a=0 then return_sign(0)@+else return_sign(-1);
+ q:=a; a:=c; c:=q; q:=-b; b:=-d; d:=q;
+ end
+else if b<=0 then
+ begin if b<0 then if a>0 then return_sign(-1);
+ if c=0 then return_sign(0) else return_sign(-1);
+ end
+
+@ To consume a random integer, the program below will say `|next_random|'
+and then it will fetch |randoms[j_random]|.
+
+@d next_random==if j_random=0 then new_randoms
+ else decr(j_random)
+
+@p procedure new_randoms;
+var @!k:0..54; {index into |randoms|}
+@!x:integer; {accumulator}
+begin for k:=0 to 23 do
+ begin x:=randoms[k]-randoms[k+31];
+ if x<0 then x:=x+fraction_one;
+ randoms[k]:=x;
+ end;
+for k:=24 to 54 do
+ begin x:=randoms[k]-randoms[k-24];
+ if x<0 then x:=x+fraction_one;
+ randoms[k]:=x;
+ end;
+j_random:=54;
+end;
+
+@ To initialize the |randoms| table, we call the following routine.
+
+@p procedure init_randoms(@!seed:integer);
+var @!j,@!jj,@!k:integer; {more or less random integers}
+@!i:0..54; {index into |randoms|}
+begin j:=abs(seed);
+while j>=fraction_one do j:=halfp(j);
+k:=1;
+for i:=0 to 54 do
+ begin jj:=k; k:=j-k; j:=jj;
+ if k<0 then k:=k+fraction_one;
+ randoms[(i*21)mod 55]:=j;
+ end;
+new_randoms; new_randoms; new_randoms; {``warm up'' the array}
+end;
+
+@ To produce a uniform random number in the range |0<=u<x| or |0>=u>x|
+or |0=u=x|, given a |scaled| value~|x|, we proceed as shown here.
+
+Note that the call of |take_frac| will produce the values 0 and~|x|
+with about half the probability that it will produce any other particular
+values between 0 and~|x|, because it rounds its answers.
+
+@p function unif_rand(@!x:integer):integer;
+var @!y:integer; {trial value}
+begin next_random; y:=take_frac(abs(x),randoms[j_random]);
+if y=abs(x) then unif_rand:=0
+else if x>0 then unif_rand:=y
+else unif_rand:=-y;
+end;
+
+@ Finally, a normal deviate with mean zero and unit standard deviation
+can readily be obtained with the ratio method (Algorithm 3.4.1R in
+{\sl The Art of Computer Programming\/}).
+
+@p function norm_rand:integer;
+var @!x,@!u,@!l:integer; {what the book would call $2^{16}X$, $2^{28}U$,
+ and $-2^{24}\ln U$}
+begin repeat
+ repeat next_random;
+ x:=take_frac(112429,randoms[j_random]-fraction_half);
+ {$2^{16}\sqrt{8/e}\approx 112428.82793$}
+ next_random; u:=randoms[j_random];
+ until abs(x)<u;
+x:=make_frac(x,u);
+l:=139548960-m_log(u); {$2^{24}\cdot12\ln2\approx139548959.6165$}
+until ab_vs_cd(1024,l,x,x)>=0;
+norm_rand:=x;
+end;
+
+@* \[8] Packed data.
+In order to make efficient use of storage space, \TeX\ bases its major data
+structures on a |memory_word|, which contains either a (signed) integer,
+possibly scaled, or a (signed) |glue_ratio|, or a small number of
+fields that are one half or one quarter of the size used for storing
+integers.
+
+If |x| is a variable of type |memory_word|, it contains up to four
+fields that can be referred to as follows:
+$$\vbox{\halign{\hfil#&#\hfil&#\hfil\cr
+|x|&.|int|&(an |integer|)\cr
+|x|&.|sc|\qquad&(a |scaled| integer)\cr
+|x|&.|gr|&(a |glue_ratio|)\cr
+|x.hh.lh|, |x.hh|&.|rh|&(two halfword fields)\cr
+|x.hh.b0|, |x.hh.b1|, |x.hh|&.|rh|&(two quarterword fields, one halfword
+ field)\cr
+|x.qqqq.b0|, |x.qqqq.b1|, |x.qqqq|&.|b2|, |x.qqqq.b3|\hskip-100pt
+ &\qquad\qquad\qquad(four quarterword fields)\cr}}$$
+This is somewhat cumbersome to write, and not very readable either, but
+macros will be used to make the notation shorter and more transparent.
+The \PASCAL\ code below gives a formal definition of |memory_word| and
+its subsidiary types, using packed variant records. \TeX\ makes no
+assumptions about the relative positions of the fields within a word.
+
+We are assuming 32-bit integers, a halfword must contain at least
+32 bits, and a quarterword must contain at least 16 bits.
+@^system dependencies@>
+
+N.B.: Valuable memory space will be dreadfully wasted unless \TeX\ is compiled
+by a \PASCAL\ that packs all of the |memory_word| variants into
+the space of a single integer. This means, for example, that |glue_ratio|
+words should be |short_real| instead of |real| on some computers. Some
+\PASCAL\ compilers will pack an integer whose subrange is `|0..255|' into
+an eight-bit field, but others insist on allocating space for an additional
+sign bit; on such systems you can get 256 values into a quarterword only
+if the subrange is `|-128..127|'.
+
+The present implementation tries to accommodate as many variations as possible,
+so it makes few assumptions. If integers having the subrange
+`|min_quarterword..max_quarterword|' can be packed into a quarterword,
+and if integers having the subrange `|min_halfword..max_halfword|'
+can be packed into a halfword, everything should work satisfactorily.
+
+It is usually most efficient to have |min_quarterword=min_halfword=0|,
+so one should try to achieve this unless it causes a severe problem.
+The values defined here are recommended for most 32-bit computers.
+
+We cannot use the full range of 32 bits in a halfword, because we have
+to allow negative values for potential backend tricks like web2c's
+dynamic allocation, and parshapes pointers have to be able to store at
+least twice the value |max_halfword| (see below). Therefore,
+|max_halfword| is $2^{30}-1$
+
+@d min_quarterword=0 {smallest allowable value in a |quarterword|}
+@d max_quarterword=65535 {largest allowable value in a |quarterword|}
+@d min_halfword==-@"3FFFFFFF {smallest allowable value in a |halfword|}
+@d max_halfword==@"3FFFFFFF {largest allowable value in a |halfword|}
+
+@ Here are the inequalities that the quarterword and halfword values
+must satisfy (or rather, the inequalities that they mustn't satisfy):
+
+@<Check the ``constant''...@>=
+if (min_quarterword>0)or(max_quarterword<@"7FFF) then bad:=11;
+if (min_halfword>0)or(max_halfword<@"3FFFFFFF) then bad:=12;
+if (min_quarterword<min_halfword)or@|
+ (max_quarterword>max_halfword) then bad:=13;
+if font_base<min_quarterword then bad:=15;
+if (save_size>max_halfword)or(max_strings>max_halfword) then bad:=17;
+if buf_size>max_halfword then bad:=18;
+if max_quarterword-min_quarterword<@"FFFF then bad:=19;
+
+@ The operation of adding or subtracting |min_quarterword| occurs quite
+frequently in \TeX, so it is convenient to abbreviate this operation
+by using the macros |qi| and |qo| for input and output to and from
+quarterword format.
+
+The inner loop of \TeX\ will run faster with respect to compilers
+that don't optimize expressions like `|x+0|' and `|x-0|', if these
+macros are simplified in the obvious way when |min_quarterword=0|.
+@^inner loop@>@^system dependencies@>
+
+@d qi(#)==#+min_quarterword
+ {to put an |eight_bits| item into a quarterword}
+@d qo(#)==#-min_quarterword
+ {to take an |eight_bits| item out of a quarterword}
+@d hi(#)==#+min_halfword
+ {to put a sixteen-bit item into a halfword}
+@d ho(#)==#-min_halfword
+ {to take a sixteen-bit item from a halfword}
+
+@ The reader should study the following definitions closely:
+@^system dependencies@>
+
+@d sc==int {|scaled| data is equivalent to |integer|}
+
+@<Types...@>=
+@!quarterword = min_quarterword..max_quarterword; {1/4 of a word}
+@!halfword=min_halfword..max_halfword; {1/2 of a word}
+@!two_choices = 1..2; {used when there are two variants in a record}
+@!four_choices = 1..4; {used when there are four variants in a record}
+@!two_halves = packed record@;@/
+ @!rh:halfword;
+ case two_choices of
+ 1: (@!lh:halfword);
+ 2: (@!b0:quarterword; @!b1:quarterword);
+ end;
+@!four_quarters = packed record@;@/
+ @!b0:quarterword;
+ @!b1:quarterword;
+ @!b2:quarterword;
+ @!b3:quarterword;
+ end;
+@!memory_word = record@;@/
+ case four_choices of
+ 1: (@!int:integer);
+ 2: (@!gr:glue_ratio);
+ 3: (@!hh:two_halves);
+ 4: (@!qqqq:four_quarters);
+ end;
+@!word_file = file of memory_word;
+
+@ When debugging, we may want to print a |memory_word| without knowing
+what type it is; so we print it in all modes.
+@^dirty \PASCAL@>@^debugging@>
+
+@p @!debug procedure print_word(@!w:memory_word);
+ {prints |w| in all ways}
+begin print_int(w.int); print_char(" ");@/
+print_scaled(w.sc); print_char(" ");@/
+print_scaled(round(unity*float(w.gr))); print_ln;@/
+@^real multiplication@>
+print_int(w.hh.lh); print_char("="); print_int(w.hh.b0); print_char(":");
+print_int(w.hh.b1); print_char(";"); print_int(w.hh.rh); print_char(" ");@/
+print_int(w.qqqq.b0); print_char(":"); print_int(w.qqqq.b1); print_char(":");
+print_int(w.qqqq.b2); print_char(":"); print_int(w.qqqq.b3);
+end;
+gubed
+
+@* \[9] Dynamic memory allocation.
+The \TeX\ system does nearly all of its own memory allocation, so that it
+can readily be transported into environments that do not have automatic
+facilities for strings, garbage collection, etc., and so that it can be in
+control of what error messages the user receives. The dynamic storage
+requirements of \TeX\ are handled by providing two large arrays called
+|fixmem| and |varmem| in which consecutive blocks of words are used as
+nodes by the \TeX\ routines.
+
+Pointer variables are indices into this array, or into another array
+called |eqtb| that will be explained later. A pointer variable might
+also be a special flag that lies outside the bounds of |mem|, so we
+allow pointers to assume any |halfword| value. The minimum halfword
+value represents a null pointer. \TeX\ does not assume that |mem[null]| exists.
+
+@d pointer==halfword {a flag or a location in |mem| or |eqtb|}
+@d null==0 {the null pointer}
+
+@<Glob...@>=
+@!temp_ptr:pointer; {a pointer variable for occasional emergency use}
+
+@ @<Types...@>=
+@!smemory_word = packed record@;@/
+ @!hhrh:halfword;
+ @!hhlh:halfword;
+ end;
+
+
+@ The |mem| array is divided into two items that are allocated separately;
+they grow until finding their ``natural'' size in a particular job.
+Locations in |varmem| are used for storing variable-length records
+consisting of two or more words each. This region
+is maintained using an algorithm similar to the one described in exercise
+2.5--19 of {\sl The Art of Computer Programming}. However, no size field
+appears in the allocated nodes; the program is responsible for knowing the
+relevant size when a node is freed. Locations in |fixmem| are used for storing
+one-word records; a conventional \.{AVAIL} stack is used for allocation
+in this array.
+
+Empirical tests show that the present implementation of \TeX\ tends to
+spend about 9\pct! of its running time allocating nodes, and about 6\pct!
+deallocating them after their use.
+
+@d fix_mem_init==10000
+
+@<Glob...@>=
+@!fixmem : ^smemory_word; {the big dynamic storage area}
+@!fix_mem_min : pointer; {the smallest location of one-word memory in use}
+@!fix_mem_max : pointer; {the largest location of one-word memory in use}
+
+@ In order to study the memory requirements of particular applications, it
+is possible to prepare a version of \TeX\ that keeps track of current and
+maximum memory usage. When code between the delimiters |@!stat| $\ldots$
+|tats| is not ``commented out,'' \TeX\ will run a bit slower but it will
+report these statistics when |tracing_stats| is sufficiently large.
+
+@<Glob...@>=
+@!var_used, @!dyn_used : integer; {how much memory is in use}
+
+@ Let's consider the one-word memory region first, since it's the
+simplest. The pointer variable |fix_mem_end| holds the highest-numbered location
+of |mem| that has ever been used. The free locations of |mem| that
+occur between |hi_mem_min| and |fix_mem_end|, inclusive, are of type
+|two_halves|, and we write |info(p)| and |link(p)| for the |lh|
+and |rh| fields of |mem[p]| when it is of this type. The single-word
+free locations form a linked list
+$$|avail|,\;\hbox{|link(avail)|},\;\hbox{|link(link(avail))|},\;\ldots$$
+terminated by |null|.
+
+@d mem(#) == fixmem[#]
+@d link(#) == mem(#).hhrh {the |link| field of a memory word}
+@d info(#) == mem(#).hhlh {the |info| field of a memory word}
+
+@<Glob...@>=
+@!avail : pointer; {head of the list of available one-word nodes}
+@!fix_mem_end : pointer; {the last one-word node used in |mem|}
+
+@ If memory is exhausted, it might mean that the user has forgotten
+a right brace. We will define some procedures later that try to help
+pinpoint the trouble.
+
+@p @<Declare the procedure called |show_token_list|@>@/
+@<Declare the procedure called |runaway|@>
+
+@ The function |get_avail| returns a pointer to a new one-word node whose
+|link| field is null. However, \TeX\ will halt if there is no more room left.
+@^inner loop@>
+
+If the available-space list is empty, i.e., if |avail=null|,
+we try first to increase |fix_mem_end|. If that cannot be done, i.e., if
+|fix_mem_end=fix_mem_max|, we try to reallocate array |fixmem|.
+If, that doesn't work, we have to quit.
+
+@p function get_avail : pointer; {single-word node allocation}
+var p:pointer; {the new node being got}
+t:integer;
+begin p:=avail; {get top location in the |avail| stack}
+if p<>null then avail:=link(avail) {and pop it off}
+else if fix_mem_end<fix_mem_max then {or go into virgin territory}
+ begin incr(fix_mem_end); p:=fix_mem_end;
+ end
+else begin
+ t:=(fix_mem_max/5);
+ fixmem := fixmemcast(realloc(fixmem,sizeof(smemory_word)*(fix_mem_max+t+1)));
+ if fixmem=NULL then
+ begin runaway; {if memory is exhausted, display possible runaway text}
+ overflow("token memory size",fix_mem_max);
+ {quit; all one-word nodes are busy}
+@:TeX capacity exceeded main memory size}{\quad main memory size@>
+ end;
+ memset (voidcast(fixmem+fix_mem_max+1),0,t*sizeof(smemory_word));
+ fix_mem_max:=fix_mem_max+t; incr(fix_mem_end); p:=fix_mem_end;
+ end;
+link(p):=null; {provide an oft-desired initialization of the new node}
+@!stat incr(dyn_used);@+tats@;{maintain statistics}
+get_avail:=p;
+end;
+
+@ Conversely, a one-word node is recycled by calling |free_avail|.
+This routine is part of \TeX's ``inner loop,'' so we want it to be fast.
+@^inner loop@>
+
+@d free_avail(#)== {single-word node liberation}
+ begin link(#):=avail; avail:=#;
+ @!stat decr(dyn_used);@+tats@/
+ end
+
+@ There's also a |fast_get_avail| routine, which saves the procedure-call
+overhead at the expense of extra programming. This routine is used in
+the places that would otherwise account for the most calls of |get_avail|.
+@^inner loop@>
+
+@d fast_get_avail(#)==@t@>@;@/
+ begin #:=avail; {avoid |get_avail| if possible, to save time}
+ if #=null then #:=get_avail
+ else begin avail:=link(#); link(#):=null;
+ @!stat incr(dyn_used);@+tats@/
+ end;
+ end
+
+@ The procedure |flush_list(p)| frees an entire linked list of
+one-word nodes that starts at position |p|.
+@^inner loop@>
+
+@p procedure flush_list(@!p:pointer); {makes list of single-word nodes available}
+var @!q,@!r:pointer; {list traversers}
+begin if p<>null then
+ begin r:=p;
+ repeat q:=r; r:=link(r); @!stat decr(dyn_used);@+tats@/
+ until r=null; {now |q| is the last node on the list}
+ link(q):=avail; avail:=p;
+ end;
+end;
+
+@ The available-space list that keeps track of the variable-size portion
+of |mem| is a nonempty, doubly-linked circular list of empty nodes,
+pointed to by the roving pointer |rover|.
+
+@d temp_node==46
+@d temp_node_size==2
+@d vmem(#) == varmem[#]
+@d vlink(#) == vmem(#).hh.rh {the |link| field of a memory word}
+@d vinfo(#) == vmem(#).hh.lh {the |info| field of a memory word}
+@d alink(#) == vlink(#+1) {backlink in doubly-linked list of empty nodes}
+
+@* \[10] Data structures for boxes and their friends.
+From the computer's standpoint, \TeX's chief mission is to create
+horizontal and vertical lists. We shall now investigate how the elements
+of these lists are represented internally as nodes in the dynamic memory.
+
+A horizontal or vertical list is linked together by |link| fields in
+the first word of each node. Individual nodes represent boxes, glue,
+penalties, or special things like discretionary hyphens; because of this
+variety, some nodes are longer than others, and we must distinguish different
+kinds of nodes. We do this by putting a `|type|' field in the first word,
+together with the link and an optional `|subtype|'.
+
+@d type(#) == vmem(#).hh.b0 {identifies what kind of node this is}
+@d subtype(#) == vmem(#).hh.b1 {secondary identification in some cases}
+
+@ TH: This module section is superceded.
+
+A |@!char_node|, which represents a single character, is the most important
+kind of node because it accounts for the vast majority of all boxes.
+Special precautions are therefore taken to ensure that a |char_node| does
+not take up much memory space. Every such node is one word long, and in fact
+it is identifiable by this property, since other kinds of nodes have at least
+two words, and they appear in |mem| locations less than |hi_mem_min|.
+This makes it possible to omit the |type| field in a |char_node|, leaving
+us room for two bytes that identify a |font| and a |character| within
+that font.
+
+Note that the format of a |char_node| allows for up to 256 different
+fonts and up to 256 characters per font; but most implementations will
+probably limit the total number of fonts to fewer than 75 per job,
+and most fonts will stick to characters whose codes are
+less than 128 (since higher codes
+are more difficult to access on most keyboards).
+
+Extensions of \TeX\ intended for oriental languages will need even more
+than $256\times256$ possible characters, when we consider different sizes
+@^oriental characters@>@^Chinese characters@>@^Japanese characters@>
+and styles of type. It is suggested that Chinese and Japanese fonts be
+handled by representing such characters in two consecutive |char_node|
+entries: The first of these has |font=font_base|, and its |link| points
+to the second;
+the second identifies the font and the character dimensions.
+The saving feature about oriental characters is that most of them have
+the same box dimensions. The |character| field of the first |char_node|
+is a ``\\{charext}'' that distinguishes between graphic symbols whose
+dimensions are identical for typesetting purposes. (See the \MF\ manual.)
+Such an extension of \TeX\ would not be difficult; further details are
+left to the reader.
+
+In order to make sure that the |character| code fits in a quarterword,
+\TeX\ adds the quantity |min_quarterword| to the actual code.
+
+Character nodes appear only in horizontal lists, never in vertical lists.
+
+@ Attribute lists need two extra globals to increase processing efficiency.
+|max_used_attr| limits the test loop that checks for set attributes, and
+|attr_list_cache| contains a pointer to an already created attribute list. It is
+set to the special value |cache_disabled| when the current value can no longer be
+trusted: after an assignment to an attribute register, and after a group has
+ended.
+
+@d cache_disabled==max_halfword
+
+@<Glob...@>=
+max_used_attr:integer; { maximum assigned attribute id }
+attr_list_cache:pointer;
+
+@ @<Set init...@>=
+max_used_attr:=-1; attr_list_cache:=cache_disabled;
+
+@ Attribute lists are maintained in C, but they need access to the current
+attributes in eqtb.
+
+@p function get_attribute(i:halfword):halfword;
+begin
+ get_attribute := attribute(i);
+end;
+
+
+@ An |hlist_node| stands for a box that was made from a horizontal list.
+Each |hlist_node| is seven words long, and contains the following fields
+(in addition to the mandatory |type| and |link|, which we shall not
+mention explicitly when discussing the other node types): The |height| and
+|width| and |depth| are scaled integers denoting the dimensions of the
+box. There is also a |shift_amount| field, a scaled integer indicating
+how much this box should be lowered (if it appears in a horizontal list),
+or how much it should be moved to the right (if it appears in a vertical
+list). There is a |list_ptr| field, which points to the beginning of the
+list from which this box was fabricated; if |list_ptr| is |null|, the box
+is empty. Finally, there are three fields that represent the setting of
+the glue: |glue_set(p)| is a word of type |glue_ratio| that represents
+the proportionality constant for glue setting; |glue_sign(p)| is
+|stretching| or |shrinking| or |normal| depending on whether or not the
+glue should stretch or shrink or remain rigid; and |glue_order(p)|
+specifies the order of infinity to which glue setting applies (|normal|,
+|sfi|, |fil|, |fill|, or |filll|). The |subtype| field is not used.
+
+@d hlist_node=0 {|type| of hlist nodes}
+@d box_node_size=8 {number of words to allocate for a box node}
+@d width_offset=2 {position of |width| field in a box node}
+@d depth_offset=3 {position of |depth| field in a box node}
+@d height_offset=4 {position of |height| field in a box node}
+@d width(#) == vmem(#+width_offset).sc {width of the box, in sp}
+@d depth(#) == vmem(#+depth_offset).sc {depth of the box, in sp}
+@d height(#) == vmem(#+height_offset).sc {height of the box, in sp}
+@d shift_amount(#) == vlink(#+5) {repositioning distance, in sp}
+@d box_dir(#) == vinfo(#+5) {position of |box_dir| in a box node}
+@d list_offset=6 {position of |list_ptr| field in a box node}
+@d list_ptr(#) == vlink(#+list_offset) {beginning of the list inside the box}
+@d glue_order(#) == subtype(#+list_offset) {applicable order of infinity}
+@d glue_sign(#) == type(#+list_offset) {stretching or shrinking}
+@d normal=0 {the most common case when several cases are named}
+@d stretching = 1 {glue setting applies to the stretch components}
+@d shrinking = 2 {glue setting applies to the shrink components}
+@d glue_offset = 7 {position of |glue_set| in a box node}
+@d glue_set(#) == vmem(#+glue_offset).gr
+ {a word of type |glue_ratio| for glue setting}
+
+@ The |new_null_box| function returns a pointer to an |hlist_node| in
+which all subfields have the values corresponding to `\.{\\hbox\{\}}'.
+The |subtype| field is set to |min_quarterword|, since that's the desired
+|span_count| value if this |hlist_node| is changed to an |unset_node|.
+
+@p function new_null_box:pointer; {creates a new box node}
+var p:pointer; {the new node}
+begin p:=new_node(hlist_node,min_quarterword);
+box_dir(p):=text_direction;
+new_null_box:=p;
+end;
+
+@ A |vlist_node| is like an |hlist_node| in all respects except that it
+contains a vertical list.
+
+@d vlist_node=1 {|type| of vlist nodes}
+
+@ A |rule_node| stands for a solid black rectangle; it has |width|,
+|depth|, and |height| fields just as in an |hlist_node|. However, if
+any of these dimensions is $-2^{30}$, the actual value will be determined
+by running the rule up to the boundary of the innermost enclosing box.
+This is called a ``running dimension.'' The |width| is never running in
+an hlist; the |height| and |depth| are never running in a~vlist.
+
+@d rule_node=2 {|type| of rule nodes}
+@d rule_node_size=6 {number of words to allocate for a rule node}
+@d null_flag==-@'10000000000 {$-2^{30}$, signifies a missing item}
+@d is_running(#) == (#=null_flag) {tests for a running dimension}
+@d rule_dir(#)==vlink(#+5)
+
+@ A new rule node is delivered by the |new_rule| function. It
+makes all the dimensions ``running,'' so you have to change the
+ones that are not allowed to run.
+
+@p
+function new_rule:pointer;
+var p:pointer; {the new node}
+begin p:=new_node(rule_node,0); {the |subtype| is not used}
+new_rule:=p;
+end;
+
+
+@ Insertions are represented by |ins_node| records, where the |subtype|
+indicates the corresponding box number. For example, `\.{\\insert 250}'
+leads to an |ins_node| whose |subtype| is |250+min_quarterword|.
+The |height| field of an |ins_node| is slightly misnamed; it actually holds
+the natural height plus depth of the vertical list being inserted.
+The |depth| field holds the |split_max_depth| to be used in case this
+insertion is split, and the |split_top_ptr| points to the corresponding
+|split_top_skip|. The |float_cost| field holds the |floating_penalty| that
+will be used if this insertion floats to a subsequent page after a
+split insertion of the same class. There is one more field, the
+|ins_ptr|, which points to the beginning of the vlist for the insertion.
+
+@d ins_node=3 {|type| of insertion nodes}
+@d ins_node_size=6 {number of words to allocate for an insertion}
+@d float_cost(#)==vmem(#+2).int {the |floating_penalty| to be used}
+@d ins_ptr(#)==vinfo(#+5) {the vertical list to be inserted}
+@d split_top_ptr(#)==vlink(#+5) {the |split_top_skip| to be used}
+
+@ A |mark_node| has a |mark_ptr| field that points to the reference count
+of a token list that contains the user's \.{\\mark} text.
+In addition there is a |mark_class| field that contains the mark class.
+
+@d mark_node=4 {|type| of a mark node}
+@d mark_node_size=3 {number of words to allocate for a mark node}
+@d mark_ptr(#)==vlink(#+2) {head of the token list for a mark}
+@d mark_class(#)==vinfo(#+2) {the mark class}
+
+@ An |adjust_node|, which occurs only in horizontal lists,
+specifies material that will be moved out into the surrounding
+vertical list; i.e., it is used to implement \TeX's `\.{\\vadjust}'
+operation. The |adjust_ptr| field points to the vlist containing this
+material.
+
+@d adjust_node=5 {|type| of an adjust node}
+@d adjust_node_size=3
+@d adjust_pre == subtype {pre-adjustment?}
+@d adjust_ptr(#)==vlink(#+2) {vertical list to be moved out of horizontal list}
+@#{|append_list| is used to append a list to |tail|}
+@d append_list(#) == begin vlink(tail) := vlink(#); append_list_end
+@d append_list_end(#) == tail := #; end
+
+@ A |glyph_node|, which occurs only in horizontal lists, specifies a
+glyph in a particular font, along with its attribute list. Older
+versions of \TeX\ could use token memory for characters, because the
+font,char combination would fit in a single word (both values were
+required to be strictly less than $2^{16}$). In \LuaTeX, room is
+needed for characters that are larger than that, as well as a pointer
+to a potential attribute list, and the two displacement values.
+
+In turn, that made the node so large that it made sense to merge
+ligature glyphs as well, as that requires only one extra pointer. A
+few extra classes of glyph nodes will be introduced later. The
+unification of all those types makes it easier to manipulate lists of
+glyphs. The subtype differentiates various glyph kinds.
+
+First, here is a function that returns a pointer to a glyph node for a given
+glyph in a given font. If that glyph doesn't exist, |null| is returned
+instead. Nodes of this subtype are directly created only for accents
+and their base (through |make_accent|), and math nucleus items (in the
+conversion from |mlist| to |hlist|).
+
+
+@d glyph_node_size=5
+@d glyph_node=33 {|type| of a glyph node}
+@d is_char_node(#) == ((#<>null)and(type(#)=glyph_node))
+@d font(#)==vlink(#+2) {the font code in a |glyph_node|}
+@d character(#)==vinfo(#+2) {the character code in a |glyph_node|}
+@d lig_ptr(#)==vlink(#+3) {the list of characters for ligature replacements }
+@d lang_data(#)==vinfo(#+3) {language information }
+@d x_displace(#)==vinfo(#+4) { horizontal displacement }
+@d y_displace(#)==vlink(#+4) { vertical displacement }
+
+@p function new_glyph(@!f,@!c:integer):pointer;
+var p:pointer; {the new node}
+begin p:=null;
+if (f=0) or (char_exists(f,c)) then begin
+ p:=new_glyph_node;
+ set_to_glyph(p); font(p):=f; character(p):=c;
+ end;
+new_glyph:=p;
+end;
+
+
+@ A subset of the glyphs nodes represent ligatures: characters
+fabricated from the interaction of two or more actual characters. The
+characters that generated the ligature have not been forgotten, since
+they are needed for diagnostic messages; the |lig_ptr| field points to
+a linked list of character nodes for all original characters that have
+been deleted. (This list might be empty if the characters that
+generated the ligature were retained in other nodes.)
+
+The |subtype| field of these |glyph_node|s is 1, plus 2 and/or 1 if
+the original source of the ligature included implicit left and/or
+right boundaries. These nodes are created by the C function |new_ligkern|.
+
+@ A third general type of glyphs could be called a character, as it
+only appears in lists that are not yet processed by the ligaturing and
+kerning steps of the program.
+
+|main_control| inserts these, and they are later converted to
+|subtype_normal| by |new_ligkern|.
+
+@p function norm_min(@!h:integer):quarterword;
+begin if h<=0 then norm_min:=1@+else if h>=255 then norm_min:=255@+
+else norm_min:=h;
+end;
+@#
+function new_char(@!f,@!c:integer):pointer;
+var p:pointer; {the new node}
+begin p:=new_glyph_node;
+set_to_character(p); font(p):=f; character(p):=c;
+lang_data(p):=make_lang_data(uc_hyph,cur_lang,left_hyphen_min,right_hyphen_min);
+new_char:=p;
+end;
+
+@ Left and right ghost glyph nodes are the result of \.{\\leftghost}
+and \.{\\rightghost}, respectively. They are going to be removed by
+|new_ligkern|, at the end of which they are no longer needed.
+
+@ Here are a few handy helpers used by the list output routines.
+
+@p
+function glyph_width(@!p:halfword):pointer;
+var w:integer;
+begin
+ w := char_width(font(p),character(p)); { |+ x_displace(p);| }
+ glyph_width := w;
+end;
+@#
+function glyph_height(@!p:halfword):pointer;
+var w:integer;
+begin
+ w := char_height(font(p),character(p)) + y_displace(p);
+ if w<0 then w:=0;
+ glyph_height := w;
+end;
+@#
+function glyph_depth(@!p:halfword):pointer;
+var w:integer;
+begin
+ w := char_depth(font(p),character(p));
+ if y_displace(p)>0 then w := w - y_displace(p);
+ if w<0 then w:=0;
+ glyph_depth := w;
+end;
+
+
+@ A |disc_node|, which occurs only in horizontal lists, specifies a
+``dis\-cretion\-ary'' line break. If such a break occurs at node |p|, the text
+that starts at |pre_break(p)| will precede the break, the text that starts at
+|post_break(p)| will follow the break, and text that appears in
+|no_break(p)| nodes will be ignored. For example, an ordinary
+discretionary hyphen, indicated by `\.{\\-}', yields a |disc_node| with
+|pre_break| pointing to a |char_node| containing a hyphen, |post_break=null|,
+and |no_break=null|.
+
+{TODO: Knuth said: All three of the discretionary texts must be lists
+that consist entirely of character, kern, box and rule nodes.}
+
+If |subtype(p)=automatic_disc|, the |ex_hyphen_penalty| will be charged for this
+break. Otherwise the |hyphen_penalty| will be charged. The texts will
+actually be substituted into the list by the line-breaking algorithm if it
+decides to make the break, and the discretionary node will disappear at
+that time; thus, the output routine sees only discretionaries that were
+not chosen.
+
+@d disc_node=7 {|type| of a discretionary node}
+@d disc_node_size=10
+@d automatic_disc=2
+@d syllable_disc=3
+@d disc_type==subtype {the kind of discretionary}
+@d pre_break(#)==vinfo(#+2) {text that precedes a discretionary break}
+@d post_break(#)==vlink(#+2) {text that follows a discretionary break}
+@d no_break(#)==vlink(#+3) {text this discretionary break replaces}
+@d pre_break_head(#)==(#+4)
+@d post_break_head(#)==(#+6)
+@d no_break_head(#)==(#+8)
+@d tlink(#)==vinfo(#+1)
+
+@p function new_disc:pointer; {creates an empty |disc_node|}
+var p:pointer; {the new node}
+begin p:=new_node(disc_node,0);
+new_disc:=p;
+end;
+
+@ A |whatsit_node| is a wild card reserved for extensions to \TeX. The
+|subtype| field in its first word says what `\\{whatsit}' it is, and
+implicitly determines the node size (which must be 2 or more) and the
+format of the remaining words. When a |whatsit_node| is encountered
+in a list, special actions are invoked; knowledgeable people who are
+careful not to mess up the rest of \TeX\ are able to make \TeX\ do new
+things by adding code at the end of the program. For example, there
+might be a `\TeX nicolor' extension to specify different colors of ink,
+@^extensions to \TeX@>
+and the whatsit node might contain the desired parameters.
+
+The present implementation of \TeX\ treats the features associated with
+`\.{\\write}' and `\.{\\special}' as if they were extensions, in order to
+illustrate how such routines might be coded. We shall defer further
+discussion of extensions until the end of this program.
+
+@d whatsit_node=8 {|type| of special extension nodes}
+
+@ A |math_node|, which occurs only in horizontal lists, appears before and
+after mathematical formulas. The |subtype| field is |before| before the
+formula and |after| after it. There is a |surround| field, which represents
+the amount of surrounding space inserted by \.{\\mathsurround}.
+
+@d math_node=9 {|type| of a math node}
+@d math_node_size=3
+@d surround(#)==vlink(#+2)
+@d before=0 {|subtype| for math node that introduces a formula}
+@d after=1 {|subtype| for math node that winds up a formula}
+
+@p function new_math(@!w:scaled;@!s:small_number):pointer;
+var p:pointer; {the new node}
+begin p:=new_node(math_node,s);
+surround(p):=w; new_math:=p;
+end;
+
+@ \TeX\ makes use of the fact that |hlist_node|, |vlist_node|,
+|rule_node|, |ins_node|, |mark_node|, |adjust_node|,
+|disc_node|, |whatsit_node|, and |math_node| are at the low end of the
+type codes, by permitting a break at glue in a list if and only if the
+|type| of the previous node is less than |math_node|. Furthermore, a
+node is discarded after a break if its type is |math_node| or~more.
+
+@d precedes_break(#)==(type(#)<math_node)
+@d non_discardable(#)==(type(#)<math_node)
+
+@ A |glue_node| represents glue in a list. However, it is really only
+a pointer to a separate glue specification, since \TeX\ makes use of the
+fact that many essentially identical nodes of glue are usually present.
+If |p| points to a |glue_node|, |glue_ptr(p)| points to
+another packet of words that specify the stretch and shrink components, etc.
+
+Glue nodes also serve to represent leaders; the |subtype| is used to
+distinguish between ordinary glue (which is called |normal|) and the three
+kinds of leaders (which are called |a_leaders|, |c_leaders|, and |x_leaders|).
+The |leader_ptr| field points to a rule node or to a box node containing the
+leaders; it is set to |null| in ordinary glue nodes.
+
+Many kinds of glue are computed from \TeX's ``skip'' parameters, and
+it is helpful to know which parameter has led to a particular glue node.
+Therefore the |subtype| is set to indicate the source of glue, whenever
+it originated as a parameter. We will be defining symbolic names for the
+parameter numbers later (e.g., |line_skip_code=0|, |baseline_skip_code=1|,
+etc.); it suffices for now to say that the |subtype| of parametric glue
+will be the same as the parameter number, plus~one.
+
+In math formulas there are two more possibilities for the |subtype| in a
+glue node: |mu_glue| denotes an \.{\\mskip} (where the units are scaled \.{mu}
+instead of scaled \.{pt}); and |cond_math_glue| denotes the `\.{\\nonscript}'
+feature that cancels the glue node immediately following if it appears
+in a subscript.
+
+@d glue_node=10 {|type| of node that points to a glue specification}
+@d glue_node_size=3
+@d cond_math_glue=98 {special |subtype| to suppress glue in the next node}
+@d mu_glue=99 {|subtype| for math glue}
+@d a_leaders=100 {|subtype| for aligned leaders}
+@d c_leaders=101 {|subtype| for centered leaders}
+@d x_leaders=102 {|subtype| for expanded leaders}
+@d glue_ptr(#)==vinfo(#+2) {pointer to a glue specification}
+@d leader_ptr(#)==vlink(#+2) {pointer to box or rule node for leaders}
+
+@ A glue specification has a halfword reference count in its first word,
+@^reference counts@>
+representing |null| plus the number of glue nodes that point to it (less one).
+Note that the reference count appears in the same position as
+the |link| field in list nodes; this is the field that is initialized
+to |null| when a node is allocated, and it is also the field that is flagged
+by |empty_flag| in empty nodes.
+
+Glue specifications also contain three |scaled| fields, for the |width|,
+|stretch|, and |shrink| dimensions. Finally, there are two one-byte
+fields called |stretch_order| and |shrink_order|; these contain the
+orders of infinity (|normal|, |sfi|, |fil|, |fill|, or |filll|)
+corresponding to the stretch and shrink values.
+
+@d glue_spec_size=4 {number of words to allocate for a glue specification}
+@d glue_spec_node=43
+@d glue_ref_count(#) == vlink(#+3) {reference count of a glue specification}
+@d stretch(#) == vlink(#+1) {the stretchability of this glob of glue}
+@d shrink(#) == vinfo(#+1) {the shrinkability of this glob of glue}
+@d stretch_order(#) == type(#+3) {order of infinity for stretching}
+@d shrink_order(#) == subtype(#+3) {order of infinity for shrinking}
+@d sfi=1 {first-order infinity}
+@d fil=2 {second-order infinity}
+@d fill=3 {third-order infinity}
+@d filll=4 {fourth-order infinity}
+
+@<Types...@>=
+@!glue_ord=normal..filll; {infinity to the 0, 1, 2, 3, or 4 power}
+
+@ Here is a function that returns a pointer to a copy of a glue spec.
+The reference count in the copy is |null|, because there is assumed
+to be exactly one reference to the new specification.
+
+@p function new_spec(@!p:pointer):pointer; {duplicates a glue specification}
+var q:pointer; {the new spec}
+begin q:=copy_node(p);
+glue_ref_count(q):=null;
+new_spec:=q;
+end;
+
+@ And here's a function that creates a glue node for a given parameter
+identified by its code number; for example,
+|new_param_glue(line_skip_code)| returns a pointer to a glue node for the
+current \.{\\lineskip}.
+
+@p function new_param_glue(@!n:small_number):pointer;
+var p:pointer; {the new node}
+@!q:pointer; {the glue specification}
+begin p:=new_node(glue_node,n+1);
+q:=@<Current |mem| equivalent of glue parameter number |n|@>@t@>;
+glue_ptr(p):=q; incr(glue_ref_count(q));
+new_param_glue:=p;
+end;
+
+@ Glue nodes that are more or less anonymous are created by |new_glue|,
+whose argument points to a glue specification.
+
+@p function new_glue(@!q:pointer):pointer;
+var p:pointer; {the new node}
+begin p:=new_node(glue_node,normal);
+glue_ptr(p):=q; incr(glue_ref_count(q));
+new_glue:=p;
+end;
+
+@ Still another subroutine is needed: this one is sort of a combination
+of |new_param_glue| and |new_glue|. It creates a glue node for one of
+the current glue parameters, but it makes a fresh copy of the glue
+specification, since that specification will probably be subject to change,
+while the parameter will stay put. The global variable |temp_ptr| is
+set to the address of the new spec.
+
+@p function new_skip_param(@!n:small_number):pointer;
+var p:pointer; {the new node}
+begin temp_ptr:=new_spec(@<Current |mem| equivalent of glue parameter...@>);
+p:=new_glue(temp_ptr); glue_ref_count(temp_ptr):=null; subtype(p):=n+1;
+new_skip_param:=p;
+end;
+
+@ A |kern_node| has a |width| field to specify a (normally negative)
+amount of spacing. This spacing correction appears in horizontal lists
+between letters like A and V when the font designer said that it looks
+better to move them closer together or further apart. A kern node can
+also appear in a vertical list, when its `|width|' denotes additional
+spacing in the vertical direction. The |subtype| is either |normal| (for
+kerns inserted from font information or math mode calculations) or |explicit|
+(for kerns inserted from \.{\\kern} and \.{\\/} commands) or |acc_kern|
+(for kerns inserted from non-math accents) or |mu_glue| (for kerns
+inserted from \.{\\mkern} specifications in math formulas).
+
+@d kern_node=11 {|type| of a kern node}
+@d kern_node_size=3
+@d explicit=1 {|subtype| of kern nodes from \.{\\kern} and \.{\\/}}
+@d acc_kern=2 {|subtype| of kern nodes from accents}
+
+@# {memory structure for marginal kerns}
+@d margin_kern_node = 32
+@d margin_kern_node_size = 4
+@d margin_char(#) == vlink(#+3)
+
+@# {|subtype| of marginal kerns}
+@d left_side == 0
+@d right_side == 1
+
+@# {base for lp/rp/ef codes starts from 2:
+ 0 for |hyphen_char|,
+ 1 for |skew_char|}
+@d lp_code_base == 2
+@d rp_code_base == 3
+@d ef_code_base == 4
+@d tag_code == 5
+
+@d auto_kern == explicit
+@d no_lig_code == 6
+
+@ The |new_kern| function creates a kern node having a given width.
+
+@p function new_kern(@!w:scaled):pointer;
+var p:pointer; {the new node}
+begin p:=new_node(kern_node,normal);
+width(p):=w;
+new_kern:=p;
+end;
+
+@ A |penalty_node| specifies the penalty associated with line or page
+breaking, in its |penalty| field. This field is a fullword integer, but
+the full range of integer values is not used: Any penalty |>=10000| is
+treated as infinity, and no break will be allowed for such high values.
+Similarly, any penalty |<=-10000| is treated as negative infinity, and a
+break will be forced.
+
+@d penalty_node=12 {|type| of a penalty node}
+@d penalty_node_size=3 {has to be the same as |glue_node_size|}
+@d inf_penalty=inf_bad {``infinite'' penalty value}
+@d eject_penalty=-inf_penalty {``negatively infinite'' penalty value}
+@d penalty(#) == vlink(#+2) {the added cost of breaking a list here}
+
+@ Anyone who has been reading the last few sections of the program will
+be able to guess what comes next.
+
+@p function new_penalty(@!m:integer):pointer;
+var p:pointer; {the new node}
+begin p:=new_node(penalty_node,0); {the |subtype| is not used}
+penalty(p):=m; new_penalty:=p;
+end;
+
+@ You might think that we have introduced enough node types by now. Well,
+almost, but there is one more: An |unset_node| has nearly the same format
+as an |hlist_node| or |vlist_node|; it is used for entries in \.{\\halign}
+or \.{\\valign} that are not yet in their final form, since the box
+dimensions are their ``natural'' sizes before any glue adjustment has been
+made. The |glue_set| word is not present; instead, we have a |glue_stretch|
+field, which contains the total stretch of order |glue_order| that is
+present in the hlist or vlist being boxed.
+Similarly, the |shift_amount| field is replaced by a |glue_shrink| field,
+containing the total shrink of order |glue_sign| that is present.
+The |subtype| field is called |span_count|; an unset box typically
+contains the data for |qo(span_count)+1| columns.
+Unset nodes will be changed to box nodes when alignment is completed.
+
+@d unset_node=13 {|type| for an unset node}
+@d glue_stretch(#)==vmem(#+glue_offset).sc {total stretch in an unset node}
+@d glue_shrink==shift_amount {total shrink in an unset node}
+@d span_count==subtype {indicates the number of spanned columns}
+
+@ In fact, there are still more types coming. When we get to math formula
+processing we will see that a |style_node| has |type=14|; and a number
+of larger type codes will also be defined, for use in math mode only.
+
+@ Warning: If any changes are made to these data structure layouts, such as
+changing any of the node sizes or even reordering the words of nodes,
+the |copy_node_list| procedure and the memory initialization code
+below may have to be changed. Such potentially dangerous parts of the
+program are listed in the index under `data structure assumptions'.
+@!@^data structure assumptions@>
+However, other references to the nodes are made symbolically in terms of
+the \.{WEB} macro definitions above, so that format changes will leave
+\TeX's other algorithms intact.
+@^system dependencies@>
+
+@* \[11] Memory layout.
+Some areas of |mem| are dedicated to fixed usage, since static allocation is
+more efficient than dynamic allocation when we can get away with it. For
+example, |zero_glue| used for glue that is `\.{0pt plus 0pt minus 0pt}'. The
+following macro definitions accomplish the static allocation by giving
+symbolic names to the fixed positions.
+
+@d zero_glue==0 {specification for \.{0pt plus 0pt minus 0pt}}
+@d sfi_glue==zero_glue+glue_spec_size {\.{0pt plus 1fi minus 0pt}}
+@d fil_glue==sfi_glue+glue_spec_size {\.{0pt plus 1fil minus 0pt}}
+@d fill_glue==fil_glue+glue_spec_size {\.{0pt plus 1fill minus 0pt}}
+@d ss_glue==fill_glue+glue_spec_size {\.{0pt plus 1fil minus 1fil}}
+@d fil_neg_glue==ss_glue+glue_spec_size {\.{0pt plus -1fil minus 0pt}}
+@d page_ins_head==fil_neg_glue+glue_spec_size {list of insertion data for current page}
+@d contrib_head==page_ins_head+temp_node_size {list of items not yet on current page}
+@d page_head==contrib_head+temp_node_size {list for current page}
+@d temp_head==page_head+temp_node_size {head of a temporary list of some kind}
+@d hold_head==temp_head+temp_node_size {head of a temporary list of another kind}
+@d adjust_head==hold_head+temp_node_size {head of adjustment list returned by |hpack|}
+@d pre_adjust_head==adjust_head+temp_node_size {head of pre-adjustment list returned by |hpack|}
+@d active==pre_adjust_head+temp_node_size {head of active list in |line_break|}
+@d align_head==active+active_node_size {head of preamble list for alignments}
+@d end_span==align_head+temp_node_size {tail of spanned-width lists}
+@d begin_point==end_span+span_node_size {left-side dot for words in hyphenation}
+@d end_point==begin_point+glyph_node_size {right-side dot for words in hyphenation}
+@d var_mem_stat_max==(end_point+glyph_node_size-1) {largest statically allocated word in the variable-size |mem|}
+
+@<Glob...@>=
+garbage:pointer; {head of a junk list, write only}
+temp_token_head:pointer; {head of a temporary list of some kind}
+hold_token_head:pointer; {head of a temporary list of another kind}
+omit_template:pointer; {a constant token list}
+null_list:pointer; {permanently empty list}
+backup_head:pointer; {head of token list built by |scan_keyword|}
+
+@ The following code gets |mem| off to a good start, when \TeX\ is
+initializing itself the slow~way.
+
+@<Local variables for init...@>=
+@!k:integer; {index into |mem|, |eqtb|, etc.}
+
+@ @<Initialize table entries...@>=
+procedure init_link_heads;forward;
+init_node_mem(var_mem_stat_max,500);
+glue_ref_count(zero_glue):=null+1; width(zero_glue):=0;
+type(zero_glue):=glue_spec_node; vlink(zero_glue):=null;
+stretch(zero_glue):=0; stretch_order(zero_glue):=normal;@/
+shrink(zero_glue):=0; shrink_order(zero_glue):=normal;@/
+glue_ref_count(sfi_glue):=null+1; width(sfi_glue):=0;
+type(sfi_glue):=glue_spec_node; vlink(sfi_glue):=null;
+stretch(sfi_glue):=0; stretch_order(sfi_glue):=sfi;@/
+shrink(sfi_glue):=0; shrink_order(sfi_glue):=normal;@/
+glue_ref_count(fil_glue):=null+1; width(fil_glue):=0;
+type(fil_glue):=glue_spec_node; vlink(fil_glue):=null;
+stretch(fil_glue):=unity; stretch_order(fil_glue):=fil;@/
+shrink(fil_glue):=0; shrink_order(fil_glue):=normal;@/
+glue_ref_count(fill_glue):=null+1; width(fill_glue):=0;
+type(fill_glue):=glue_spec_node; vlink(fill_glue):=null;
+stretch(fill_glue):=unity; stretch_order(fill_glue):=fill;@/
+shrink(fill_glue):=0; shrink_order(fill_glue):=normal;@/
+glue_ref_count(ss_glue):=null+1; width(ss_glue):=0;
+type(ss_glue):=glue_spec_node; vlink(ss_glue):=null;
+stretch(ss_glue):=unity; stretch_order(ss_glue):=fil;@/
+shrink(ss_glue):=unity; shrink_order(ss_glue):=fil;@/
+glue_ref_count(fil_neg_glue):=null+1; width(fil_neg_glue):=0;
+type(fil_neg_glue):=glue_spec_node; vlink(fil_neg_glue):=null;
+stretch(fil_neg_glue):=-unity; stretch_order(fil_neg_glue):=fil;@/
+shrink(fil_neg_glue):=0; shrink_order(fil_neg_glue):=normal;@/
+{initialize node list heads}
+vinfo(page_ins_head):=0; vlink(page_ins_head):=null; alink(page_ins_head):=null;
+vinfo(contrib_head):=0; vlink(contrib_head):=null; alink(contrib_head):=null;
+vinfo(page_head):=0; vlink(page_head):=null; alink(page_head):=null;
+vinfo(temp_head):=0; vlink(temp_head):=null; alink(temp_head):=null;
+vinfo(hold_head):=0; vlink(hold_head):=null; alink(hold_head):=null;
+vinfo(adjust_head):=0; vlink(adjust_head):=null; alink(adjust_head):=null;
+vinfo(pre_adjust_head):=0; vlink(pre_adjust_head):=null; alink(pre_adjust_head):=null;
+vinfo(active):=0; vlink(active):=null; alink(active):=null;
+vinfo(align_head):=0; vlink(align_head):=null; alink(align_head):=null;
+vinfo(end_span):=0; vlink(end_span):=null; alink(end_span):=null;
+type(begin_point):=glyph_node; subtype(begin_point):=0; vlink(begin_point):=null;
+vinfo(begin_point+1):=null; alink(begin_point):=null;
+font(begin_point):=0; character(begin_point):='.';
+vinfo(begin_point+3):=0; vlink(begin_point+3):=0;
+vinfo(begin_point+4):=0; vlink(begin_point+4):=0;
+type(end_point):=glyph_node; subtype(end_point):=0; vlink(end_point):=null;
+vinfo(end_point+1):=null; alink(end_point):=null;
+font(end_point):=0; character(end_point):='.';
+vinfo(end_point+3):=0; vlink(end_point+3):=0;
+vinfo(end_point+4):=0; vlink(end_point+4):=0;
+avail:=null; fix_mem_end:=0;
+init_list_heads;
+@<Initialize the special list heads and constant nodes@>;
+initialize_active;
+dyn_used:=0; {initialize statistics}
+
+@ @p procedure init_list_heads; {initialize token list heads}
+var p:halfword;
+begin
+p:=get_avail; temp_token_head:=p; info(temp_token_head):=0;
+p:=get_avail; hold_token_head:=p; info(hold_token_head):=0;
+p:=get_avail; omit_template:=p; info(omit_template):=0;
+p:=get_avail; null_list:=p; info(null_list):=0;
+p:=get_avail; backup_head:=p; info(backup_head):=0;
+p:=get_avail; garbage:=p; info(garbage):=0;
+end;
+
+@ @p
+@<Declare procedures that need to be declared forward for \pdfTeX@>
+
+@* \[12] Displaying boxes.
+We can reinforce our knowledge of the data structures just introduced
+by considering two procedures that display a list in symbolic form.
+The first of these, called |short_display|, is used in ``overfull box''
+messages to give the top-level description of a list. The other one,
+called |show_node_list|, prints a detailed description of exactly what
+is in the data structure.
+
+The philosophy of |short_display| is to ignore the fine points about exactly
+what is inside boxes, except that ligatures and discretionary breaks are
+expanded. As a result, |short_display| is a recursive procedure, but the
+recursion is never more than one level deep.
+@^recursion@>
+
+A global variable |font_in_short_display| keeps track of the font code that
+is assumed to be present when |short_display| begins; deviations from this
+font will be printed.
+
+@<Glob...@>=
+@!font_in_short_display:integer; {an internal font number}
+
+@ Boxes, rules, inserts, whatsits, marks, and things in general that are
+sort of ``complicated'' are indicated only by printing `\.{[]}'.
+
+@p
+procedure print_font_identifier(f: internal_font_number);
+begin
+ if pdf_font_blink(f) = null_font then
+ print_esc(font_id_text(f))
+ else
+ print_esc(font_id_text(pdf_font_blink(f)));
+ if pdf_tracing_fonts > 0 then begin
+ print(" (");
+ print_font_name(f);
+ if font_size(f) <> font_dsize(f) then begin
+ print("@@");
+ print_scaled(font_size(f));
+ print("pt");
+ end;
+ print(")");
+ end else
+ if pdf_font_expand_ratio(f) <> 0 then begin
+ print(" (");
+ if pdf_font_expand_ratio(f) > 0 then
+ print("+");
+ print_int(pdf_font_expand_ratio(f));
+ print(")");
+ end;
+end;
+
+procedure short_display(@!p:integer); {prints highlights of list |p|}
+begin while p<>null do
+ begin if is_char_node(p) then
+ begin if lig_ptr(p)<>null then
+ short_display(lig_ptr(p))
+ else begin
+ if font(p)<>font_in_short_display then
+ begin if not is_valid_font(font(p)) then
+ print_char("*")
+@.*\relax@>
+ else print_font_identifier(font(p));
+ print_char(" "); font_in_short_display:=font(p);
+ end;
+ print(qo(character(p)));
+ end;
+ end
+ else @<Print a short indication of the contents of node |p|@>;
+ p:=vlink(p);
+ end;
+end;
+
+@ @<Print a short indication of the contents of node |p|@>=
+case type(p) of
+hlist_node,vlist_node,ins_node,whatsit_node,mark_node,adjust_node,
+ unset_node: print("[]");
+rule_node: print_char("|");
+glue_node: if glue_ptr(p)<>zero_glue then print_char(" ");
+math_node: print_char("$");
+disc_node: begin short_display(vlink(pre_break(p)));
+ short_display(vlink(post_break(p)));@/
+ end;
+othercases do_nothing
+endcases
+
+@ The |show_node_list| routine requires some auxiliary subroutines: one to
+print a font-and-character combination, one to print a token list without
+its reference count, and one to print a rule dimension.
+
+@p procedure print_font_and_char(@!p:integer); {prints |char_node| data}
+begin if not is_valid_font(font(p)) then print_char("*")
+@.*\relax@>
+ else print_font_identifier(font(p));
+ print_char(" "); print(character(p));
+end;
+@#
+procedure print_mark(@!p:integer); {prints token list data in braces}
+begin print_char("{");
+if (p<fix_mem_min)or(p>fix_mem_end) then print_esc("CLOBBERED.")
+else show_token_list(link(p),null,max_print_line-10);
+print_char("}");
+end;
+@#
+procedure print_rule_dimen(@!d:scaled); {prints dimension in rule node}
+begin if is_running(d) then print_char("*") else print_scaled(d);
+@.*\relax@>
+end;
+@#
+procedure print_dir(d:integer);
+begin
+print(dir_names[dir_primary[d]]);
+print(dir_names[dir_secondary[d]]);
+print(dir_names[dir_tertiary[d]]);
+end;
+
+
+@ Then there is a subroutine that prints glue stretch and shrink, possibly
+followed by the name of finite units:
+
+@p procedure print_glue(@!d:scaled;@!order:integer;@!s:str_number);
+ {prints a glue component}
+begin print_scaled(d);
+if (order<normal)or(order>filll) then print("foul")
+else if order>normal then
+ begin print("fi");
+ while order>sfi do
+ begin print_char("l"); decr(order);
+ end;
+ end
+else if s<>0 then print(s);
+end;
+
+@ The next subroutine prints a whole glue specification.
+
+@p procedure print_spec(@!p:integer;@!s:str_number);
+ {prints a glue specification}
+begin if p<0 then print_char("*")
+@.*\relax@>
+else begin print_scaled(width(p));
+ if s<>0 then print(s);
+ if stretch(p)<>0 then
+ begin print(" plus "); print_glue(stretch(p),stretch_order(p),s);
+ end;
+ if shrink(p)<>0 then
+ begin print(" minus "); print_glue(shrink(p),shrink_order(p),s);
+ end;
+ end;
+end;
+
+@ We also need to declare some procedures that appear later in this
+documentation.
+
+@p @<Declare procedures needed for displaying the elements of mlists@>@;
+@<Declare the procedure called |print_skip_param|@>
+
+@ Since boxes can be inside of boxes, |show_node_list| is inherently recursive,
+@^recursion@>
+up to a given maximum number of levels. The history of nesting is indicated
+by the current string, which will be printed at the beginning of each line;
+the length of this string, namely |cur_length|, is the depth of nesting.
+
+Recursive calls on |show_node_list| therefore use the following pattern:
+
+@d node_list_display(#)==
+ begin append_char("."); show_node_list(#); flush_char;
+ end {|str_room| need not be checked; see |show_box| below}
+
+@ A global variable called |depth_threshold| is used to record the maximum
+depth of nesting for which |show_node_list| will show information. If we
+have |depth_threshold=0|, for example, only the top level information will
+be given and no sublists will be traversed. Another global variable, called
+|breadth_max|, tells the maximum number of items to show at each level;
+|breadth_max| had better be positive, or you won't see anything.
+
+@<Glob...@>=
+@!depth_threshold : integer; {maximum nesting depth in box displays}
+@!breadth_max : integer; {maximum number of items shown at the same list level}
+
+@ Now we are ready for |show_node_list| itself. This procedure has been
+written to be ``extra robust'' in the sense that it should not crash or get
+into a loop even if the data structures have been messed up by bugs in
+the rest of the program. You can safely call its parent routine
+|show_box(p)| for arbitrary values of |p| when you are debugging \TeX.
+However, in the presence of bad data, the procedure may
+@^dirty \PASCAL@>@^debugging@>
+fetch a |memory_word| whose variant is different from the way it was stored;
+for example, it might try to read |mem[p].hh| when |mem[p]|
+contains a scaled integer, if |p| is a pointer that has been
+clobbered or chosen at random.
+
+@p procedure show_node_list(@!p:integer); {prints a node list symbolically}
+label exit;
+var n:integer; {the number of items already printed at this level}
+@!g:real; {a glue ratio, as a floating point number}
+begin if cur_length>depth_threshold then
+ begin if p>null then print(" []");
+ {indicate that there's been some truncation}
+ return;
+ end;
+n:=0;
+while p<>null do
+ begin print_ln; print_current_string; {display the nesting history}
+ if tracing_online<-2 then print_int(p);
+ incr(n); if n>breadth_max then {time to stop}
+ begin print("etc."); return;
+@.etc@>
+ end;
+ @<Display node |p|@>;
+ p:=vlink(p);
+ end;
+exit:
+end;
+
+@ @<Display node |p|@>=
+if is_char_node(p) then begin
+ print_font_and_char(p);
+ if is_ligature(p) then @<Display ligature |p|@>;
+ end
+else case type(p) of
+ hlist_node,vlist_node,unset_node: @<Display box |p|@>;
+ rule_node: @<Display rule |p|@>;
+ ins_node: @<Display insertion |p|@>;
+ whatsit_node: @<Display the whatsit node |p|@>;
+ glue_node: @<Display glue |p|@>;
+ margin_kern_node: begin
+ print_esc("kern");
+ print_scaled(width(p));
+ if subtype(p) = left_side then
+ print(" (left margin)")
+ else
+ print(" (right margin)");
+ end;
+ kern_node: @<Display kern |p|@>;
+ math_node: @<Display math node |p|@>;
+ penalty_node: @<Display penalty |p|@>;
+ disc_node: @<Display discretionary |p|@>;
+ mark_node: @<Display mark |p|@>;
+ adjust_node: @<Display adjustment |p|@>;
+ @t\4@>@<Cases of |show_node_list| that arise in mlists only@>@;
+ othercases print("Unknown node type!")
+ endcases
+
+@ @<Display box |p|@>=
+begin if type(p)=hlist_node then print_esc("h")
+else if type(p)=vlist_node then print_esc("v")
+else print_esc("unset");
+print("box("); print_scaled(height(p)); print_char("+");
+print_scaled(depth(p)); print(")x"); print_scaled(width(p));
+if type(p)=unset_node then
+ @<Display special fields of the unset node |p|@>
+else begin @<Display the value of |glue_set(p)|@>;
+ if shift_amount(p)<>0 then
+ begin print(", shifted "); print_scaled(shift_amount(p));
+ end;
+ print(", direction "); print_dir(box_dir(p));
+ end;
+{|pdfassert(list_ptr(p)<>0);|}
+node_list_display(list_ptr(p)); {recursive call}
+end
+
+@ @<Display special fields of the unset node |p|@>=
+begin if span_count(p)<>min_quarterword then
+ begin print(" ("); print_int(qo(span_count(p))+1);
+ print(" columns)");
+ end;
+if glue_stretch(p)<>0 then
+ begin print(", stretch "); print_glue(glue_stretch(p),glue_order(p),0);
+ end;
+if glue_shrink(p)<>0 then
+ begin print(", shrink "); print_glue(glue_shrink(p),glue_sign(p),0);
+ end;
+end
+
+@ The code will have to change in this place if |glue_ratio| is
+a structured type instead of an ordinary |real|. Note that this routine
+should avoid arithmetic errors even if the |glue_set| field holds an
+arbitrary random value. The following code assumes that a properly
+formed nonzero |real| number has absolute value $2^{20}$ or more when
+it is regarded as an integer; this precaution was adequate to prevent
+floating point underflow on the author's computer.
+@^system dependencies@>
+@^dirty \PASCAL@>
+
+@<Display the value of |glue_set(p)|@>=
+g:=float(glue_set(p));
+if (g<>float_constant(0))and(glue_sign(p)<>normal) then
+ begin print(", glue set ");
+ if glue_sign(p)=shrinking then print("- ");
+ if abs(vmem(p+glue_offset).int)<@'4000000 then print("?.?")
+ else if abs(g)>float_constant(20000) then
+ begin if g>float_constant(0) then print_char(">")
+ else print("< -");
+ print_glue(20000*unity,glue_order(p),0);
+ end
+ else print_glue(round(unity*g),glue_order(p),0);
+@^real multiplication@>
+ end
+
+@ @<Display rule |p|@>=
+begin print_esc("rule("); print_rule_dimen(height(p)); print_char("+");
+print_rule_dimen(depth(p)); print(")x"); print_rule_dimen(width(p));
+end
+
+@ @<Display insertion |p|@>=
+begin print_esc("insert"); print_int(qo(subtype(p)));
+print(", natural size "); print_scaled(height(p));
+print("; split("); print_spec(split_top_ptr(p),0);
+print_char(","); print_scaled(depth(p));
+print("); float cost "); print_int(float_cost(p));
+node_list_display(ins_ptr(p)); {recursive call}
+end
+
+@ @<Display glue |p|@>=
+if subtype(p)>=a_leaders then @<Display leaders |p|@>
+else begin print_esc("glue");
+ if subtype(p)<>normal then
+ begin print_char("(");
+ if subtype(p)<cond_math_glue then
+ print_skip_param(subtype(p)-1)
+ else if subtype(p)=cond_math_glue then print_esc("nonscript")
+ else print_esc("mskip");
+ print_char(")");
+ end;
+ if subtype(p)<>cond_math_glue then
+ begin print_char(" ");
+ if subtype(p)<cond_math_glue then print_spec(glue_ptr(p),0)
+ else print_spec(glue_ptr(p),"mu");
+ end;
+ end
+
+@ @<Display leaders |p|@>=
+begin print_esc("");
+if subtype(p)=c_leaders then print_char("c")
+else if subtype(p)=x_leaders then print_char("x");
+print("leaders "); print_spec(glue_ptr(p),0);
+node_list_display(leader_ptr(p)); {recursive call}
+end
+
+@ An ``explicit'' kern value is indicated implicitly by an explicit space.
+
+@<Display kern |p|@>=
+if subtype(p)<>mu_glue then
+ begin print_esc("kern");
+ if subtype(p)<>normal then print_char(" ");
+ print_scaled(width(p));
+ if subtype(p)=acc_kern then print(" (for accent)");
+@.for accent@>
+ end
+else begin print_esc("mkern"); print_scaled(width(p)); print("mu");
+ end
+
+@ @<Display math node |p|@>=
+begin print_esc("math");
+if subtype(p)=before then print("on")
+else print("off");
+if width(p)<>0 then
+ begin print(", surrounded "); print_scaled(width(p));
+ end;
+end
+
+@ @<Display ligature |p|@>=
+begin print(" (ligature ");
+if is_leftboundary(p) then print_char("|");
+font_in_short_display:=font(p); short_display(lig_ptr(p));
+if is_rightboundary(p) then print_char("|");
+print_char(")");
+end
+
+@ @<Display penalty |p|@>=
+begin print_esc("penalty "); print_int(penalty(p));
+end
+
+@ The |post_break| list of a discretionary node is indicated by a prefixed
+`\.{\char'174}' instead of the `\..' before the |pre_break| list.
+
+@<Display discretionary |p|@>=
+begin print_esc("discretionary");
+if vlink(no_break(p))<>null then
+ begin print(" replacing "); node_list_display(vlink(no_break(p)));
+ end;
+node_list_display(vlink(pre_break(p))); {recursive call}
+append_char("|"); show_node_list(vlink(post_break(p))); flush_char; {recursive call}
+end
+
+@ @<Display mark |p|@>=
+begin print_esc("mark");
+if mark_class(p)<>0 then
+ begin print_char("s"); print_int(mark_class(p));
+ end;
+print_mark(mark_ptr(p));
+end
+
+@ @<Display adjustment |p|@>=
+begin print_esc("vadjust"); if adjust_pre(p) <> 0 then print(" pre ");
+node_list_display(adjust_ptr(p)); {recursive call}
+end
+
+@ The recursive machinery is started by calling |show_box|.
+@^recursion@>
+
+@p procedure show_box(@!p:pointer);
+begin @<Assign the values |depth_threshold:=show_box_depth| and
+ |breadth_max:=show_box_breadth|@>;
+if breadth_max<=0 then breadth_max:=5;
+if pool_ptr+depth_threshold>=pool_size then
+ depth_threshold:=pool_size-pool_ptr-1;
+ {now there's enough room for prefix string}
+show_node_list(p); {the show starts at |p|}
+print_ln;
+end;
+
+@* \[13] Destroying boxes.
+When we are done with a node list, we are obliged to return it to free
+storage, including all of its sublists. The recursive procedure
+|flush_node_list| does this for us.
+
+@ First, however, we shall consider two non-recursive procedures that do
+simpler tasks. The first of these, |delete_token_ref|, is called when
+a pointer to a token list's reference count is being removed. This means
+that the token list should disappear if the reference count was |null|,
+otherwise the count should be decreased by one.
+@^reference counts@>
+
+@d token_ref_count(#) == info(#) {reference count preceding a token list}
+
+@p procedure delete_token_ref(@!p:pointer); {|p| points to the reference count
+ of a token list that is losing one reference}
+begin pdfassert(token_ref_count(p)>=0);
+if token_ref_count(p)=0 then flush_list(p)
+else decr(token_ref_count(p));
+end;
+
+@ Similarly, |delete_glue_ref| is called when a pointer to a glue
+specification is being withdrawn.
+@^reference counts@>
+@d fast_delete_glue_ref(#)==@t@>@;@/
+ begin if glue_ref_count(#)=null then begin
+ flush_node(#);
+ end
+ else decr(glue_ref_count(#));
+ end
+
+@p procedure delete_glue_ref(@!p:pointer); {|p| points to a glue specification}
+begin
+ pdfassert(type(p)=glue_spec_node);
+ fast_delete_glue_ref(p);
+end;
+
+@ Now we are ready to delete any node list, recursively.
+In practice, the nodes deleted are usually charnodes (about 2/3 of the time),
+and they are glue nodes in about half of the remaining cases.
+@^recursion@>
+
+
+@* \[14] Copying boxes.
+Another recursive operation that acts on boxes is sometimes needed: The
+procedure |copy_node_list| returns a pointer to another node list that has
+the same structure and meaning as the original. Note that since glue
+specifications and token lists have reference counts, we need not make
+copies of them. Reference counts can never get too large to fit in a
+halfword, since each pointer to a node is in a different memory address,
+and the total number of memory addresses fits in a halfword.
+@^recursion@>
+@^reference counts@>
+
+(Well, there actually are also references from outside |mem|; if the
+|save_stack| is made arbitrarily large, it would theoretically be possible
+to break \TeX\ by overflowing a reference count. But who would want to do that?)
+
+@d add_token_ref(#)==incr(token_ref_count(#)) {new reference to a token list}
+@d add_glue_ref(#)==incr(glue_ref_count(#)) {new reference to a glue spec}
+
+@p function tail_of_list (@!p:pointer):pointer;
+var q:pointer;
+begin
+ q:=p;
+ while vlink(q)<>null do q:=vlink(q);
+ tail_of_list:=q;
+end;
+
+@* \[15] The command codes.
+Before we can go any further, we need to define symbolic names for the internal
+code numbers that represent the various commands obeyed by \TeX. These codes
+are somewhat arbitrary, but not completely so. For example, the command
+codes for character types are fixed by the language, since a user says,
+e.g., `\.{\\catcode \`\\\${} = 3}' to make \.{\char'44} a math delimiter,
+and the command code |math_shift| is equal to~3. Some other codes have
+been made adjacent so that |case| statements in the program need not consider
+cases that are widely spaced, or so that |case| statements can be replaced
+by |if| statements.
+
+At any rate, here is the list, for future reference. First come the
+``catcode'' commands, several of which share their numeric codes with
+ordinary commands when the catcode cannot emerge from \TeX's scanning routine.
+
+@d escape=0 {escape delimiter (called \.\\ in {\sl The \TeX book\/})}
+@:TeXbook}{\sl The \TeX book@>
+@d relax=0 {do nothing ( \.{\\relax} )}
+@d left_brace=1 {beginning of a group ( \.\{ )}
+@d right_brace=2 {ending of a group ( \.\} )}
+@d math_shift=3 {mathematics shift character ( \.\$ )}
+@d tab_mark=4 {alignment delimiter ( \.\&, \.{\\span} )}
+@d car_ret=5 {end of line ( |carriage_return|, \.{\\cr}, \.{\\crcr} )}
+@d out_param=5 {output a macro parameter}
+@d mac_param=6 {macro parameter symbol ( \.\# )}
+@d sup_mark=7 {superscript ( \.{\char'136} )}
+@d sub_mark=8 {subscript ( \.{\char'137} )}
+@d ignore=9 {characters to ignore ( \.{\^\^@@} )}
+@d endv=9 {end of \<v_j> list in alignment template}
+@d spacer=10 {characters equivalent to blank space ( \.{\ } )}
+@d letter=11 {characters regarded as letters ( \.{A..Z}, \.{a..z} )}
+@d other_char=12 {none of the special character types}
+@d active_char=13 {characters that invoke macros ( \.{\char`\~} )}
+@d par_end=13 {end of paragraph ( \.{\\par} )}
+@d match=13 {match a macro parameter}
+@d comment=14 {characters that introduce comments ( \.\% )}
+@d end_match=14 {end of parameters to macro}
+@d stop=14 {end of job ( \.{\\end}, \.{\\dump} )}
+@d invalid_char=15 {characters that shouldn't appear ( \.{\^\^?} )}
+@d delim_num=15 {specify delimiter numerically ( \.{\\delimiter} )}
+@d max_char_code=15 {largest catcode for individual characters}
+
+@ Next are the ordinary run-of-the-mill command codes. Codes that are
+|min_internal| or more represent internal quantities that might be
+expanded by `\.{\\the}'.
+
+@d char_num=16 {character specified numerically ( \.{\\char} )}
+@d math_char_num=17 {explicit math code ( \.{\\mathchar} )}
+@d mark=18 {mark definition ( \.{\\mark} )}
+@d xray=19 {peek inside of \TeX\ ( \.{\\show}, \.{\\showbox}, etc.~)}
+@d make_box=20 {make a box ( \.{\\box}, \.{\\copy}, \.{\\hbox}, etc.~)}
+@d hmove=21 {horizontal motion ( \.{\\moveleft}, \.{\\moveright} )}
+@d vmove=22 {vertical motion ( \.{\\raise}, \.{\\lower} )}
+@d un_hbox=23 {unglue a box ( \.{\\unhbox}, \.{\\unhcopy} )}
+@d un_vbox=24 {unglue a box ( \.{\\unvbox}, \.{\\unvcopy} )}
+ {( or \.{\\pagediscards}, \.{\\splitdiscards} )}
+@d remove_item=25 {nullify last item ( \.{\\unpenalty},
+ \.{\\unkern}, \.{\\unskip} )}
+@d hskip=26 {horizontal glue ( \.{\\hskip}, \.{\\hfil}, etc.~)}
+@d vskip=27 {vertical glue ( \.{\\vskip}, \.{\\vfil}, etc.~)}
+@d mskip=28 {math glue ( \.{\\mskip} )}
+@d kern=29 {fixed space ( \.{\\kern})}
+@d mkern=30 {math kern ( \.{\\mkern} )}
+@d leader_ship=31 {use a box ( \.{\\shipout}, \.{\\leaders}, etc.~)}
+@d halign=32 {horizontal table alignment ( \.{\\halign} )}
+@d valign=33 {vertical table alignment ( \.{\\valign} )}
+@d no_align=34 {temporary escape from alignment ( \.{\\noalign} )}
+@d vrule=35 {vertical rule ( \.{\\vrule} )}
+@d hrule=36 {horizontal rule ( \.{\\hrule} )}
+@d insert=37 {vlist inserted in box ( \.{\\insert} )}
+@d vadjust=38 {vlist inserted in enclosing paragraph ( \.{\\vadjust} )}
+@d ignore_spaces=39 {gobble |spacer| tokens ( \.{\\ignorespaces} )}
+@d after_assignment=40 {save till assignment is done ( \.{\\afterassignment} )}
+@d after_group=41 {save till group is done ( \.{\\aftergroup} )}
+@d break_penalty=42 {additional badness ( \.{\\penalty} )}
+@d start_par=43 {begin paragraph ( \.{\\indent}, \.{\\noindent} )}
+@d ital_corr=44 {italic correction ( \.{\\/} )}
+@d accent=45 {attach accent in text ( \.{\\accent} )}
+@d math_accent=46 {attach accent in math ( \.{\\mathaccent} )}
+@d discretionary=47 {discretionary texts ( \.{\\-}, \.{\\discretionary} )}
+@d eq_no=48 {equation number ( \.{\\eqno}, \.{\\leqno} )}
+@d left_right=49 {variable delimiter ( \.{\\left}, \.{\\right} )}
+ {( or \.{\\middle} )}
+@d math_comp=50 {component of formula ( \.{\\mathbin}, etc.~)}
+@d limit_switch=51 {diddle limit conventions ( \.{\\displaylimits}, etc.~)}
+@d above=52 {generalized fraction ( \.{\\above}, \.{\\atop}, etc.~)}
+@d math_style=53 {style specification ( \.{\\displaystyle}, etc.~)}
+@d math_choice=54 {choice specification ( \.{\\mathchoice} )}
+@d non_script=55 {conditional math glue ( \.{\\nonscript} )}
+@d vcenter=56 {vertically center a vbox ( \.{\\vcenter} )}
+@d case_shift=57 {force specific case ( \.{\\lowercase}, \.{\\uppercase}~)}
+@d message=58 {send to user ( \.{\\message}, \.{\\errmessage} )}
+@d extension=59 {extensions to \TeX\ ( \.{\\write}, \.{\\special}, etc.~)}
+@d in_stream=60 {files for reading ( \.{\\openin}, \.{\\closein} )}
+@d begin_group=61 {begin local grouping ( \.{\\begingroup} )}
+@d end_group=62 {end local grouping ( \.{\\endgroup} )}
+@d omit=63 {omit alignment template ( \.{\\omit} )}
+@d ex_space=64 {explicit space ( \.{\\\ } )}
+@d no_boundary=65 {suppress boundary ligatures ( \.{\\noboundary} )}
+@d radical=66 {square root and similar signs ( \.{\\radical} )}
+@d end_cs_name=67 {end control sequence ( \.{\\endcsname} )}
+@d char_ghost=end_cs_name+1
+ {\.{\\ghostleft}, \.{\\ghostright} character for kerning}
+@d assign_local_box=char_ghost+1
+ {box for guillemets \.{\\localleftbox} or \.{\\localrightbox}}
+@d min_internal=assign_local_box+1 {the smallest code that can follow \.{\\the}}
+@d char_given=min_internal {character code defined by \.{\\chardef}}
+@d math_given=char_given+1 {math code defined by \.{\\mathchardef}}
+@d omath_given=math_given+1 {math code defined by \.{\\omathchardef}}
+@d last_item=omath_given+1 {most recent item ( \.{\\lastpenalty},
+ \.{\\lastkern}, \.{\\lastskip} )}
+@d max_non_prefixed_command=last_item
+ {largest command code that can't be \.{\\global}}
+
+@ The next codes are special; they all relate to mode-independent
+assignment of values to \TeX's internal registers or tables.
+Codes that are |max_internal| or less represent internal quantities
+that might be expanded by `\.{\\the}'.
+
+There is no matching primitive to go with |assign_attr|, but even if
+there was no \.{\\attributedef}, a reserved number would still be
+needed because there is an implied correspondence between the
+|assign_xxx| commands and |xxx_val| expression values. That would
+break down otherwise.
+
+@d toks_register=max_non_prefixed_command+1
+ {token list register ( \.{\\toks} )}
+@d assign_toks=toks_register+1
+ {special token list ( \.{\\output}, \.{\\everypar}, etc.~)}
+@d assign_int=assign_toks+1
+ {user-defined integer ( \.{\\tolerance}, \.{\\day}, etc.~)}
+@d assign_attr=assign_int+1 { user-defined attributes }
+@d assign_dimen=assign_attr+1
+ {user-defined length ( \.{\\hsize}, etc.~)}
+@d assign_glue=assign_dimen+1
+ {user-defined glue ( \.{\\baselineskip}, etc.~)}
+@d assign_mu_glue=assign_glue+1
+ {user-defined muglue ( \.{\\thinmuskip}, etc.~)}
+@d assign_font_dimen=assign_mu_glue+1
+ {user-defined font dimension ( \.{\\fontdimen} )}
+@d assign_font_int=assign_font_dimen+1
+ {user-defined font integer ( \.{\\hyphenchar}, \.{\\skewchar} )}
+@d set_aux=assign_font_int+1
+ {specify state info ( \.{\\spacefactor}, \.{\\prevdepth} )}
+@d set_prev_graf=set_aux+1
+ {specify state info ( \.{\\prevgraf} )}
+@d set_page_dimen=set_prev_graf+1
+ {specify state info ( \.{\\pagegoal}, etc.~)}
+@d set_page_int=set_page_dimen+1
+ {specify state info ( \.{\\deadcycles},
+ \.{\\insertpenalties} )}
+@d set_box_dimen=set_page_int+1
+ {change dimension of box ( \.{\\wd}, \.{\\ht}, \.{\\dp} )}
+@d set_shape=set_box_dimen+1
+ {specify fancy paragraph shape ( \.{\\parshape} )}
+@d def_code=set_shape+1
+ {define a character code ( \.{\\catcode}, etc.~)}
+@d extdef_code=def_code+1
+ {define an extended character code ( \.{\\omathcode}, etc.~)}
+@d def_family=extdef_code+1
+ {declare math fonts ( \.{\\textfont}, etc.~)}
+@d set_font=def_family+1
+ {set current font ( font identifiers )}
+@d def_font=set_font+1
+ {define a font file ( \.{\\font} )}
+@d register=def_font+1
+ {internal register ( \.{\\count}, \.{\\dimen}, etc.~)}
+@d assign_box_dir=register+1 {(\.{\\boxdir})}
+@d assign_dir=register+2 {(\.{\\pagedir}, \.{\\textdir})}
+@d max_internal=assign_dir
+ {the largest code that can follow \.{\\the}}
+@d advance=max_internal+1
+ {advance a register or parameter ( \.{\\advance} )}
+@d multiply=advance+1
+ {multiply a register or parameter ( \.{\\multiply} )}
+@d divide=multiply+1
+ {divide a register or parameter ( \.{\\divide} )}
+@d prefix=divide+1
+ {qualify a definition ( \.{\\global}, \.{\\long}, \.{\\outer} )}
+@d let=prefix+1
+ {assign a command code ( \.{\\let}, \.{\\futurelet} )}
+@d shorthand_def=let+1
+ {code definition ( \.{\\chardef}, \.{\\countdef}, etc.~)}
+@d read_to_cs=shorthand_def+1
+ {read into a control sequence ( \.{\\read} )}
+@d def=read_to_cs+1
+ {macro definition ( \.{\\def}, \.{\\gdef}, \.{\\xdef}, \.{\\edef} )}
+@d set_box=def+1
+ {set a box ( \.{\\setbox} )}
+@d hyph_data=set_box+1
+ {hyphenation data ( \.{\\hyphenation}, \.{\\patterns} )}
+@d set_interaction=hyph_data+1
+ {define level of interaction ( \.{\\batchmode}, etc.~)}
+@d letterspace_font=set_interaction+1
+ {letterspace a font ( \.{\\letterspacefont} )}
+@d set_ocp=letterspace_font+1
+ {Place a translation process in the stream}
+@d def_ocp=set_ocp+1
+ {Define and load a translation process}
+@d set_ocp_list=def_ocp+1
+ {Place a list of OCPs in the stream}
+@d def_ocp_list=set_ocp_list+1
+ {Define a list of OCPs}
+@d clear_ocp_lists=def_ocp_list+1
+ {Remove all active OCP lists}
+@d push_ocp_list=clear_ocp_lists+1
+ {Add to the sequence of active OCP lists}
+@d pop_ocp_list=push_ocp_list+1
+ {Remove from the sequence of active OCP lists}
+@d ocp_list_op=pop_ocp_list+1
+ {Operations for building a list of OCPs}
+@d ocp_trace_level=ocp_list_op+1
+ {Tracing of active OCPs, either 0 or 1}
+@d max_command=ocp_trace_level
+ {the largest command code seen at |big_switch|}
+
+@ The remaining command codes are extra special, since they cannot get through
+\TeX's scanner to the main control routine. They have been given values higher
+than |max_command| so that their special nature is easily discernible.
+The ``expandable'' commands come first.
+
+@d undefined_cs=max_command+1 {initial state of most |eq_type| fields}
+@d expand_after=max_command+2 {special expansion ( \.{\\expandafter} )}
+@d no_expand=max_command+3 {special nonexpansion ( \.{\\noexpand} )}
+@d input=max_command+4 {input a source file ( \.{\\input}, \.{\\endinput} )}
+ {( or \.{\\scantokens} or \.{\\scantextokens} )}
+@d if_test=max_command+5 {conditional text ( \.{\\if}, \.{\\ifcase}, etc.~)}
+@d fi_or_else=max_command+6 {delimiters for conditionals ( \.{\\else}, etc.~)}
+@d cs_name=max_command+7 {make a control sequence from tokens ( \.{\\csname} )}
+@d convert=max_command+8 {convert to text ( \.{\\number}, \.{\\string}, etc.~)}
+@d the=max_command+9 {expand an internal quantity ( \.{\\the} )}
+ {( or \.{\\unexpanded}, \.{\\detokenize} )}
+@d top_bot_mark=max_command+10 {inserted mark ( \.{\\topmark}, etc.~)}
+@d call=max_command+11 {non-long, non-outer control sequence}
+@d long_call=max_command+12 {long, non-outer control sequence}
+@d outer_call=max_command+13 {non-long, outer control sequence}
+@d long_outer_call=max_command+14 {long, outer control sequence}
+@d end_template=max_command+15 {end of an alignment template}
+@d dont_expand=max_command+16 {the following token was marked by \.{\\noexpand}}
+@d glue_ref=max_command+17 {the equivalent points to a glue specification}
+@d shape_ref=max_command+18 {the equivalent points to a parshape specification}
+@d box_ref=max_command+19 {the equivalent points to a box node, or is |null|}
+@d data=max_command+20 {the equivalent is simply a halfword number}
+
+@* \[16] The semantic nest.
+\TeX\ is typically in the midst of building many lists at once. For example,
+when a math formula is being processed, \TeX\ is in math mode and
+working on an mlist; this formula has temporarily interrupted \TeX\ from
+being in horizontal mode and building the hlist of a paragraph; and this
+paragraph has temporarily interrupted \TeX\ from being in vertical mode
+and building the vlist for the next page of a document. Similarly, when a
+\.{\\vbox} occurs inside of an \.{\\hbox}, \TeX\ is temporarily
+interrupted from working in restricted horizontal mode, and it enters
+internal vertical mode. The ``semantic nest'' is a stack that
+keeps track of what lists and modes are currently suspended.
+
+At each level of processing we are in one of six modes:
+
+\yskip\hang|vmode| stands for vertical mode (the page builder);
+
+\hang|hmode| stands for horizontal mode (the paragraph builder);
+
+\hang|mmode| stands for displayed formula mode;
+
+\hang|-vmode| stands for internal vertical mode (e.g., in a \.{\\vbox});
+
+\hang|-hmode| stands for restricted horizontal mode (e.g., in an \.{\\hbox});
+
+\hang|-mmode| stands for math formula mode (not displayed).
+
+\yskip\noindent The mode is temporarily set to zero while processing \.{\\write}
+texts in the |ship_out| routine.
+
+Numeric values are assigned to |vmode|, |hmode|, and |mmode| so that
+\TeX's ``big semantic switch'' can select the appropriate thing to
+do by computing the value |abs(mode)+cur_cmd|, where |mode| is the current
+mode and |cur_cmd| is the current command code.
+
+@d vmode=1 {vertical mode}
+@d hmode=vmode+max_command+1 {horizontal mode}
+@d mmode=hmode+max_command+1 {math mode}
+
+@p procedure print_mode(@!m:integer); {prints the mode represented by |m|}
+begin if m>0 then
+ case m div (max_command+1) of
+ 0:print("vertical");
+ 1:print("horizontal");
+ 2:print("display math");
+ end
+else if m=0 then print("no")
+else case (-m) div (max_command+1) of
+ 0:print("internal vertical");
+ 1:print("restricted horizontal");
+ 2:print("math");
+ end;
+print(" mode");
+end;
+function get_mode_id:integer; {returns the mode represented by |m|}
+var m:integer ;
+begin
+ m := mode;
+ if m>0 then
+ case m div (max_command+1) of
+ 0:get_mode_id := "v";
+ 1:get_mode_id := "h";
+ 2:get_mode_id := "m";
+ othercases get_mode_id := "";
+ end
+else if m=0 then get_mode_id := "n"
+else case (-m) div (max_command+1) of
+ 0:get_mode_id := "V";
+ 1:get_mode_id := "H";
+ 2:get_mode_id := "M";
+ othercases get_mode_id := "";
+ end;
+end;
+
+@ The state of affairs at any semantic level can be represented by
+five values:
+
+\yskip\hang|mode| is the number representing the semantic mode, as
+just explained.
+
+\yskip\hang|head| is a |pointer| to a list head for the list being built;
+|link(head)| therefore points to the first element of the list, or
+to |null| if the list is empty.
+
+\yskip\hang|tail| is a |pointer| to the final node of the list being
+built; thus, |tail=head| if and only if the list is empty.
+
+\yskip\hang|prev_graf| is the number of lines of the current paragraph that
+have already been put into the present vertical list.
+
+\yskip\hang|aux| is an auxiliary |memory_word| that gives further information
+that is needed to characterize the situation.
+
+\yskip\noindent
+In vertical mode, |aux| is also known as |prev_depth|; it is the scaled
+value representing the depth of the previous box, for use in baseline
+calculations, or it is |<=-1000|pt if the next box on the vertical list is to
+be exempt from baseline calculations. In horizontal mode, |aux| is also
+known as |space_factor|; it holds the current space factor used in
+spacing calculations. In math mode, |aux| is also known as |incompleat_noad|;
+if not |null|, it points to a record that represents the numerator of a
+generalized fraction for which the denominator is currently being formed
+in the current list.
+
+There is also a sixth quantity, |mode_line|, which correlates
+the semantic nest with the user's input; |mode_line| contains the source
+line number at which the current level of nesting was entered. The negative
+of this line number is the |mode_line| at the level of the
+user's output routine.
+
+A seventh quantity, |eTeX_aux|, is used by the extended features \eTeX.
+In math mode it is known as |delim_ptr| and points to the most
+recent |left_noad| or |middle_noad| of a |math_left_group|.
+
+In horizontal mode, the |prev_graf| field is used for initial language data.
+
+The semantic nest is an array called |nest| that holds the |mode|, |head|,
+|tail|, |prev_graf|, |aux|, and |mode_line| values for all semantic levels
+below the currently active one. Information about the currently active
+level is kept in the global quantities |mode|, |head|, |tail|, |prev_graf|,
+|aux|, and |mode_line|, which live in a \PASCAL\ record that is ready to
+be pushed onto |nest| if necessary.
+
+@d ignore_depth==-65536000 {|prev_depth| value that is ignored}
+
+@<Types...@>=
+@!list_state_record=record@!mode_field:-mmode..mmode;@+
+ @!head_field,@!tail_field: pointer;
+ @!eTeX_aux_field: pointer;
+ @!pg_field,@!ml_field: integer;@+
+ @!aux_field: memory_word;
+ @!dirs_field: halfword;
+ @!math_field: integer;
+ @!local_par_field: pointer;
+ @!local_par_bool_field: boolean;
+ end;
+
+@ @d mode==cur_list.mode_field {current mode}
+@d head==cur_list.head_field {header node of current list}
+@d tail==cur_list.tail_field {final node on current list}
+@d eTeX_aux==cur_list.eTeX_aux_field {auxiliary data for \eTeX}
+@d delim_ptr==eTeX_aux {most recent left or right noad of a math left group}
+@d prev_graf==cur_list.pg_field {number of paragraph lines accumulated}
+@d aux==cur_list.aux_field {auxiliary data about the current list}
+@d prev_depth==aux.sc {the name of |aux| in vertical mode}
+@d space_factor==aux.hh.lh {part of |aux| in horizontal mode}
+@d incompleat_noad==aux.int {the name of |aux| in math mode}
+@d mode_line==cur_list.ml_field {source file line number at beginning of list}
+@d dir_save==cur_list.dirs_field {dir stack when a paragraph is interrupted}
+@d dir_math_save==cur_list.math_field
+ {should begin/end dir nodes be placed around mathematics?}
+@d local_par==cur_list.local_par_field
+ {pointer to whatsit for local stuff}
+@d local_par_bool==cur_list.local_par_bool_field
+ {has local stuff been changed in this group?}
+
+@<Glob...@>=
+@!nest:array[0..nest_size] of list_state_record;
+@!nest_ptr:0..nest_size; {first unused location of |nest|}
+@!max_nest_stack:0..nest_size; {maximum of |nest_ptr| when pushing}
+@!cur_list:list_state_record; {the ``top'' semantic state}
+@!shown_mode:-mmode..mmode; {most recent mode shown by \.{\\tracingcommands}}
+@!save_tail: pointer; {save |tail| so we can examine whether we have an auto
+ kern before a glue}
+
+@ Here is a common way to make the current list grow:
+
+@p
+procedure tail_append(p:pointer);
+begin
+vlink(tail):=p; tail:=vlink(tail);
+end;
+@#
+procedure new_tail_append(p:pointer);
+begin
+couple_nodes(tail,p); tail:=vlink(tail);
+end;
+@#
+function pop_tail:pointer;
+label exit;
+var n,r:pointer;
+begin
+ if tail<>head then begin
+ r:=tail;
+ if vlink(alink(tail))=tail then
+ n:=alink(tail)
+ else begin
+ n:=head;
+ while vlink(n)<>tail do n:=vlink(n);
+ end;
+ flush_node(tail);
+ tail:=n;
+ vlink(n):=null;
+ pop_tail:=r;
+ end
+ else
+ pop_tail:=null;
+exit:end;
+
+
+@ We will see later that the vertical list at the bottom semantic level is split
+into two parts; the ``current page'' runs from |page_head| to |page_tail|,
+and the ``contribution list'' runs from |contrib_head| to |tail| of
+semantic level zero. The idea is that contributions are first formed in
+vertical mode, then ``contributed'' to the current page (during which time
+the page-breaking decisions are made). For now, we don't need to know
+any more details about the page-building process.
+
+@<Set init...@>=
+nest_ptr:=0; max_nest_stack:=0;
+mode:=vmode; head:=contrib_head; tail:=contrib_head;
+eTeX_aux:=null;
+prev_depth:=ignore_depth; mode_line:=0;
+prev_graf:=0; shown_mode:=0;
+dir_save:=null; dir_math_save:=false;
+local_par:=null; local_par_bool:=false;
+@<Start a new current page@>;
+
+@ @p @<LOCAL: Declare |make_local_par_node|@>;
+
+@ @p @<DIR: Declare |new_dir|@>;
+
+@ When \TeX's work on one level is interrupted, the state is saved by
+calling |push_nest|. This routine changes |head| and |tail| so that
+a new (empty) list is begun; it does not change |mode| or |aux|.
+
+@p procedure push_nest; {enter a new semantic level, save the old}
+begin if nest_ptr>max_nest_stack then
+ begin max_nest_stack:=nest_ptr;
+ if nest_ptr=nest_size then overflow("semantic nest size",nest_size);
+@:TeX capacity exceeded semantic nest size}{\quad semantic nest size@>
+ end;
+nest[nest_ptr]:=cur_list; {stack the record}
+incr(nest_ptr); head:=new_node(temp_node,0); tail:=head; prev_graf:=0; mode_line:=line;
+dir_save:=null; dir_math_save:=false;
+local_par:=make_local_par_node; local_par_bool:=false;
+eTeX_aux:=null;
+end;
+
+@ Conversely, when \TeX\ is finished on the current level, the former
+state is restored by calling |pop_nest|. This routine will never be
+called at the lowest semantic level, nor will it be called unless |head|
+is a node that should be returned to free memory.
+
+@p procedure pop_nest; {leave a semantic level, re-enter the old}
+begin
+if local_par<>null then begin
+ if local_par_bool then begin end {|tail_append(local_par)|}
+ else flush_node(local_par);
+ end;
+flush_node(head); decr(nest_ptr); cur_list:=nest[nest_ptr];
+end;
+
+@ Here is a procedure that displays what \TeX\ is working on, at all levels.
+
+@p procedure@?print_totals; forward;@t\2@>
+procedure show_activities;
+var p:0..nest_size; {index into |nest|}
+@!m:-mmode..mmode; {mode}
+@!a:memory_word; {auxiliary}
+@!q,@!r:pointer; {for showing the current page}
+@!t:integer; {ditto}
+begin nest[nest_ptr]:=cur_list; {put the top level into the array}
+print_nl(""); print_ln;
+for p:=nest_ptr downto 0 do
+ begin m:=nest[p].mode_field; a:=nest[p].aux_field;
+ print_nl("### "); print_mode(m);
+ print(" entered at line "); print_int(abs(nest[p].ml_field));
+ if m=hmode then if nest[p].pg_field <> @'40600000 then
+ begin print(" (language"); print_int(nest[p].pg_field mod @'200000);
+ print(":hyphenmin"); print_int(nest[p].pg_field div @'20000000);
+ print_char(","); print_int((nest[p].pg_field div @'200000) mod @'100);
+ print_char(")");
+ end;
+ if nest[p].ml_field<0 then print(" (\output routine)");
+ if p=0 then
+ begin @<Show the status of the current page@>;
+ if vlink(contrib_head)<>null then
+ print_nl("### recent contributions:");
+ end;
+ show_box(vlink(nest[p].head_field));
+ @<Show the auxiliary field, |a|@>;
+ end;
+end;
+
+@ @<Show the auxiliary...@>=
+case abs(m) div (max_command+1) of
+0: begin print_nl("prevdepth ");
+ if a.sc<=ignore_depth then print("ignored")
+ else print_scaled(a.sc);
+ if nest[p].pg_field<>0 then
+ begin print(", prevgraf ");
+ print_int(nest[p].pg_field); print(" line");
+ if nest[p].pg_field<>1 then print_char("s");
+ end;
+ end;
+1: begin print_nl("spacefactor "); print_int(a.hh.lh);
+ if m>0 then@+ if a.hh.rh>0 then
+ begin print(", current language "); print_int(a.hh.rh);@+
+ end;
+ end;
+2: if a.int<>null then
+ begin print("this will be denominator of:"); show_box(a.int);@+
+ end;
+end {there are no other cases}
+
+@* \[17] The table of equivalents.
+Now that we have studied the data structures for \TeX's semantic routines,
+we ought to consider the data structures used by its syntactic routines. In
+other words, our next concern will be
+the tables that \TeX\ looks at when it is scanning
+what the user has written.
+
+The biggest and most important such table is called |eqtb|. It holds the
+current ``equivalents'' of things; i.e., it explains what things mean
+or what their current values are, for all quantities that are subject to
+the nesting structure provided by \TeX's grouping mechanism. There are six
+parts to |eqtb|:
+
+\yskip\hangg 1) |eqtb[active_base..(hash_base-1)]| holds the current
+equivalents of single-character control sequences.
+
+\yskip\hangg 2) |eqtb[hash_base..(glue_base-1)]| holds the current
+equivalents of multiletter control sequences.
+
+\yskip\hangg 3) |eqtb[glue_base..(local_base-1)]| holds the current
+equivalents of glue parameters like the current baselineskip.
+
+\yskip\hangg 4) |eqtb[local_base..(int_base-1)]| holds the current
+equivalents of local halfword quantities like the current box registers,
+the current ``catcodes,'' the current font, and a pointer to the current
+paragraph shape.
+
+\yskip\hangg 5) |eqtb[int_base..(dimen_base-1)]| holds the current
+equivalents of fullword integer parameters like the current hyphenation
+penalty.
+
+\yskip\hangg 6) |eqtb[dimen_base..eqtb_size]| holds the current equivalents
+of fullword dimension parameters like the current hsize or amount of
+hanging indentation.
+
+\yskip\noindent Note that, for example, the current amount of
+baselineskip glue is determined by the setting of a particular location
+in region~3 of |eqtb|, while the current meaning of the control sequence
+`\.{\\baselineskip}' (which might have been changed by \.{\\def} or
+\.{\\let}) appears in region~2.
+
+@ Each entry in |eqtb| is a |memory_word|. Most of these words are of type
+|two_halves|, and subdivided into three fields:
+
+\yskip\hangg 1) The |eq_level| (a quarterword) is the level of grouping at
+which this equivalent was defined. If the level is |level_zero|, the
+equivalent has never been defined; |level_one| refers to the outer level
+(outside of all groups), and this level is also used for global
+definitions that never go away. Higher levels are for equivalents that
+will disappear at the end of their group. @^global definitions@>
+
+\yskip\hangg 2) The |eq_type| (another quarterword) specifies what kind of
+entry this is. There are many types, since each \TeX\ primitive like
+\.{\\hbox}, \.{\\def}, etc., has its own special code. The list of
+command codes above includes all possible settings of the |eq_type| field.
+
+\yskip\hangg 3) The |equiv| (a halfword) is the current equivalent value.
+This may be a font number, a pointer into |mem|, or a variety of other
+things.
+
+@d eq_level_field(#)==#.hh.b1
+@d eq_type_field(#)==#.hh.b0
+@d equiv_field(#)==#.hh.rh
+@d eq_level(#)==eq_level_field(eqtb[#]) {level of definition}
+@d eq_type(#)==eq_type_field(eqtb[#]) {command code for equivalent}
+@d equiv(#)==equiv_field(eqtb[#]) {equivalent value}
+@d level_zero=min_quarterword {level for undefined quantities}
+@d level_one=level_zero+1 {outermost level for defined quantities}
+
+@ Many locations in |eqtb| have symbolic names. The purpose of the next
+paragraphs is to define these names, and to set up the initial values of the
+equivalents.
+
+In the first region we have |number_active_chars| equivalents for ``active
+characters'' that act as control sequences.
+
+Then comes region~2, which corresponds to the hash table that we will
+define later. The maximum address in this region is used for a dummy
+control sequence that is perpetually undefined. There also are several
+locations for control sequences that are perpetually defined
+(since they are used in error recovery).
+
+@d active_base=1 {beginning of region 1, for active character equivalents}
+@d null_cs=active_base+number_active_chars {equivalent of \.{\\csname\\endcsname}}
+@d hash_base=null_cs+1 {beginning of region 2, for the hash table}
+@d frozen_control_sequence=hash_base+hash_size {for error recovery}
+@d frozen_protection=frozen_control_sequence {inaccessible but definable}
+@d frozen_cr=frozen_control_sequence+1 {permanent `\.{\\cr}'}
+@d frozen_end_group=frozen_control_sequence+2 {permanent `\.{\\endgroup}'}
+@d frozen_right=frozen_control_sequence+3 {permanent `\.{\\right}'}
+@d frozen_fi=frozen_control_sequence+4 {permanent `\.{\\fi}'}
+@d frozen_end_template=frozen_control_sequence+5 {permanent `\.{\\endtemplate}'}
+@d frozen_endv=frozen_control_sequence+6 {second permanent `\.{\\endtemplate}'}
+@d frozen_relax=frozen_control_sequence+7 {permanent `\.{\\relax}'}
+@d end_write=frozen_control_sequence+8 {permanent `\.{\\endwrite}'}
+@d frozen_dont_expand=frozen_control_sequence+9
+ {permanent `\.{\\notexpanded:}'}
+@d frozen_primitive=frozen_control_sequence+11
+ {permanent `\.{\\pdfprimitive}'}
+@d frozen_null_font=frozen_control_sequence+12
+ {permanent `\.{\\nullfont}'}
+@d font_id_base=frozen_null_font-font_base
+ {begins table of |number_fonts| permanent font identifiers}
+@d frozen_null_ocp=frozen_null_font+number_fonts
+ {permanent `\.{\\nullocp}'}
+@d ocp_id_base=frozen_null_ocp-ocp_base
+ {begins table of |number_ocps| permanent ocp identifiers}
+@d frozen_null_ocp_list=frozen_null_ocp+number_ocps
+ {permanent `\.{\\nullocplist}'}
+@d ocp_list_id_base=frozen_null_ocp_list-ocp_list_base
+ {begins table of |number_ocp_lists| permanent ocp list identifiers}
+@d undefined_control_sequence=frozen_null_ocp_list+number_ocp_lists
+@d glue_base=undefined_control_sequence+1 {beginning of region 3}
+
+@<Initialize table entries...@>=
+eq_type(undefined_control_sequence):=undefined_cs;
+equiv(undefined_control_sequence):=null;
+eq_level(undefined_control_sequence):=level_zero;
+for k:=active_base to undefined_control_sequence-1 do
+ eqtb[k]:=eqtb[undefined_control_sequence];
+
+@ Here is a routine that displays the current meaning of an |eqtb| entry
+in region 1 or~2. (Similar routines for the other regions will appear
+below.)
+
+@<Show equivalent |n|, in region 1 or 2@>=
+begin sprint_cs(n); print_char("="); print_cmd_chr(eq_type(n),equiv(n));
+if eq_type(n)>=call then
+ begin print_char(":"); show_token_list(link(equiv(n)),null,32);
+ end;
+end
+
+@ Region 3 of |eqtb| contains the |number_regs| \.{\\skip} registers, as well as the
+glue parameters defined here. It is important that the ``muskip''
+parameters have larger numbers than the others.
+
+@d line_skip_code=0 {interline glue if |baseline_skip| is infeasible}
+@d baseline_skip_code=1 {desired glue between baselines}
+@d par_skip_code=2 {extra glue just above a paragraph}
+@d above_display_skip_code=3 {extra glue just above displayed math}
+@d below_display_skip_code=4 {extra glue just below displayed math}
+@d above_display_short_skip_code=5
+ {glue above displayed math following short lines}
+@d below_display_short_skip_code=6
+ {glue below displayed math following short lines}
+@d left_skip_code=7 {glue at left of justified lines}
+@d right_skip_code=8 {glue at right of justified lines}
+@d top_skip_code=9 {glue at top of main pages}
+@d split_top_skip_code=10 {glue at top of split pages}
+@d tab_skip_code=11 {glue between aligned entries}
+@d space_skip_code=12 {glue between words (if not |zero_glue|)}
+@d xspace_skip_code=13 {glue after sentences (if not |zero_glue|)}
+@d par_fill_skip_code=14 {glue on last line of paragraph}
+@d thin_mu_skip_code=15 {thin space in math formula}
+@d med_mu_skip_code=16 {medium space in math formula}
+@d thick_mu_skip_code=17 {thick space in math formula}
+@d glue_pars=18 {total number of glue parameters}
+@d skip_base=glue_base+glue_pars {table of |number_regs| ``skip'' registers}
+@d mu_skip_base=skip_base+number_regs {table of |number_regs| ``muskip'' registers}
+@d local_base=mu_skip_base+number_regs {beginning of region 4}
+@#
+@d skip(#)==equiv(skip_base+#) {|mem| location of glue specification}
+@d mu_skip(#)==equiv(mu_skip_base+#) {|mem| location of math glue spec}
+@d glue_par(#)==equiv(glue_base+#) {|mem| location of glue specification}
+@d line_skip==glue_par(line_skip_code)
+@d baseline_skip==glue_par(baseline_skip_code)
+@d par_skip==glue_par(par_skip_code)
+@d above_display_skip==glue_par(above_display_skip_code)
+@d below_display_skip==glue_par(below_display_skip_code)
+@d above_display_short_skip==glue_par(above_display_short_skip_code)
+@d below_display_short_skip==glue_par(below_display_short_skip_code)
+@d left_skip==glue_par(left_skip_code)
+@d right_skip==glue_par(right_skip_code)
+@d top_skip==glue_par(top_skip_code)
+@d split_top_skip==glue_par(split_top_skip_code)
+@d tab_skip==glue_par(tab_skip_code)
+@d space_skip==glue_par(space_skip_code)
+@d xspace_skip==glue_par(xspace_skip_code)
+@d par_fill_skip==glue_par(par_fill_skip_code)
+@d thin_mu_skip==glue_par(thin_mu_skip_code)
+@d med_mu_skip==glue_par(med_mu_skip_code)
+@d thick_mu_skip==glue_par(thick_mu_skip_code)
+
+@<Current |mem| equivalent of glue parameter number |n|@>=glue_par(n)
+
+@ Sometimes we need to convert \TeX's internal code numbers into symbolic
+form. The |print_skip_param| routine gives the symbolic name of a glue
+parameter.
+
+@<Declare the procedure called |print_skip_param|@>=
+procedure print_skip_param(@!n:integer);
+begin case n of
+line_skip_code: print_esc("lineskip");
+baseline_skip_code: print_esc("baselineskip");
+par_skip_code: print_esc("parskip");
+above_display_skip_code: print_esc("abovedisplayskip");
+below_display_skip_code: print_esc("belowdisplayskip");
+above_display_short_skip_code: print_esc("abovedisplayshortskip");
+below_display_short_skip_code: print_esc("belowdisplayshortskip");
+left_skip_code: print_esc("leftskip");
+right_skip_code: print_esc("rightskip");
+top_skip_code: print_esc("topskip");
+split_top_skip_code: print_esc("splittopskip");
+tab_skip_code: print_esc("tabskip");
+space_skip_code: print_esc("spaceskip");
+xspace_skip_code: print_esc("xspaceskip");
+par_fill_skip_code: print_esc("parfillskip");
+thin_mu_skip_code: print_esc("thinmuskip");
+med_mu_skip_code: print_esc("medmuskip");
+thick_mu_skip_code: print_esc("thickmuskip");
+othercases print("[unknown glue parameter!]")
+endcases;
+end;
+
+@ The symbolic names for glue parameters are put into \TeX's hash table
+by using the routine called |primitive|, defined below. Let us enter them
+now, so that we don't have to list all those parameter names anywhere else.
+
+@<Put each of \TeX's primitives into the hash table@>=
+primitive("lineskip",assign_glue,glue_base+line_skip_code);@/
+@!@:line_skip_}{\.{\\lineskip} primitive@>
+primitive("baselineskip",assign_glue,glue_base+baseline_skip_code);@/
+@!@:baseline_skip_}{\.{\\baselineskip} primitive@>
+primitive("parskip",assign_glue,glue_base+par_skip_code);@/
+@!@:par_skip_}{\.{\\parskip} primitive@>
+primitive("abovedisplayskip",assign_glue,glue_base+above_display_skip_code);@/
+@!@:above_display_skip_}{\.{\\abovedisplayskip} primitive@>
+primitive("belowdisplayskip",assign_glue,glue_base+below_display_skip_code);@/
+@!@:below_display_skip_}{\.{\\belowdisplayskip} primitive@>
+primitive("abovedisplayshortskip",
+ assign_glue,glue_base+above_display_short_skip_code);@/
+@!@:above_display_short_skip_}{\.{\\abovedisplayshortskip} primitive@>
+primitive("belowdisplayshortskip",
+ assign_glue,glue_base+below_display_short_skip_code);@/
+@!@:below_display_short_skip_}{\.{\\belowdisplayshortskip} primitive@>
+primitive("leftskip",assign_glue,glue_base+left_skip_code);@/
+@!@:left_skip_}{\.{\\leftskip} primitive@>
+primitive("rightskip",assign_glue,glue_base+right_skip_code);@/
+@!@:right_skip_}{\.{\\rightskip} primitive@>
+primitive("topskip",assign_glue,glue_base+top_skip_code);@/
+@!@:top_skip_}{\.{\\topskip} primitive@>
+primitive("splittopskip",assign_glue,glue_base+split_top_skip_code);@/
+@!@:split_top_skip_}{\.{\\splittopskip} primitive@>
+primitive("tabskip",assign_glue,glue_base+tab_skip_code);@/
+@!@:tab_skip_}{\.{\\tabskip} primitive@>
+primitive("spaceskip",assign_glue,glue_base+space_skip_code);@/
+@!@:space_skip_}{\.{\\spaceskip} primitive@>
+primitive("xspaceskip",assign_glue,glue_base+xspace_skip_code);@/
+@!@:xspace_skip_}{\.{\\xspaceskip} primitive@>
+primitive("parfillskip",assign_glue,glue_base+par_fill_skip_code);@/
+@!@:par_fill_skip_}{\.{\\parfillskip} primitive@>
+primitive("thinmuskip",assign_mu_glue,glue_base+thin_mu_skip_code);@/
+@!@:thin_mu_skip_}{\.{\\thinmuskip} primitive@>
+primitive("medmuskip",assign_mu_glue,glue_base+med_mu_skip_code);@/
+@!@:med_mu_skip_}{\.{\\medmuskip} primitive@>
+primitive("thickmuskip",assign_mu_glue,glue_base+thick_mu_skip_code);@/
+@!@:thick_mu_skip_}{\.{\\thickmuskip} primitive@>
+
+@ @<Cases of |print_cmd_chr| for symbolic printing of primitives@>=
+assign_glue,assign_mu_glue: if chr_code<skip_base then
+ print_skip_param(chr_code-glue_base)
+ else if chr_code<mu_skip_base then
+ begin print_esc("skip"); print_int(chr_code-skip_base);
+ end
+ else begin print_esc("muskip"); print_int(chr_code-mu_skip_base);
+ end;
+
+@ All glue parameters and registers are initially `\.{0pt plus0pt minus0pt}'.
+
+@<Initialize table entries...@>=
+equiv(glue_base):=zero_glue; eq_level(glue_base):=level_one;
+eq_type(glue_base):=glue_ref;
+for k:=glue_base+1 to local_base-1 do eqtb[k]:=eqtb[glue_base];
+glue_ref_count(zero_glue):=glue_ref_count(zero_glue)+local_base-glue_base;
+
+@ @<Show equivalent |n|, in region 3@>=
+if n<skip_base then
+ begin print_skip_param(n-glue_base); print_char("=");
+ if n<glue_base+thin_mu_skip_code then print_spec(equiv(n),"pt")
+ else print_spec(equiv(n),"mu");
+ end
+else if n<mu_skip_base then
+ begin print_esc("skip"); print_int(n-skip_base); print_char("=");
+ print_spec(equiv(n),"pt");
+ end
+else begin print_esc("muskip"); print_int(n-mu_skip_base); print_char("=");
+ print_spec(equiv(n),"mu");
+ end
+
+@ Region 4 of |eqtb| contains the local quantities defined here. The
+bulk of this region is taken up by five tables that are indexed by eight-bit
+characters; these tables are important to both the syntactic and semantic
+portions of \TeX. There are also a bunch of special things like font and
+token parameters, as well as the tables of \.{\\toks} and \.{\\box}
+registers.
+
+@d par_shape_loc=local_base {specifies paragraph shape}
+@d output_routine_loc=local_base+1 {points to token list for \.{\\output}}
+@d every_par_loc=local_base+2 {points to token list for \.{\\everypar}}
+@d every_math_loc=local_base+3 {points to token list for \.{\\everymath}}
+@d every_display_loc=local_base+4 {points to token list for \.{\\everydisplay}}
+@d every_hbox_loc=local_base+5 {points to token list for \.{\\everyhbox}}
+@d every_vbox_loc=local_base+6 {points to token list for \.{\\everyvbox}}
+@d every_job_loc=local_base+7 {points to token list for \.{\\everyjob}}
+@d every_cr_loc=local_base+8 {points to token list for \.{\\everycr}}
+@d err_help_loc=local_base+9 {points to token list for \.{\\errhelp}}
+@d tex_toks=local_base+10 {end of \TeX's token list parameters}
+@#
+@d pdftex_first_loc = tex_toks {base for \pdfTeX's token list parameters}
+@d pdf_pages_attr_loc = pdftex_first_loc + 0 {points to token list for \.{\\pdfpagesattr}}
+@d pdf_page_attr_loc = pdftex_first_loc + 1 {points to token list for \.{\\pdfpageattr}}
+@d pdf_page_resources_loc = pdftex_first_loc + 2 {points to token list for \.{\\pdfpageresources}}
+@d pdf_pk_mode_loc = pdftex_first_loc + 3 {points to token list for \.{\\pdfpkmode}}
+@d pdf_toks=pdftex_first_loc+4 {end of \pdfTeX's token list parameters}
+@#
+@d etex_toks_base=pdf_toks {base for \eTeX's token list parameters}
+@d every_eof_loc=etex_toks_base {points to token list for \.{\\everyeof}}
+@d etex_toks=etex_toks_base+1 {end of \eTeX's token list parameters}
+@#
+@d ocp_trace_level_base=etex_toks
+@d ocp_active_number_base=ocp_trace_level_base+1
+@d ocp_active_min_ptr_base = ocp_active_number_base+1
+@d ocp_active_max_ptr_base = ocp_active_min_ptr_base+1
+@d ocp_active_base = ocp_active_max_ptr_base+1
+@d toks_base = ocp_active_base+max_active_ocp_lists
+ {table of |number_regs| token list registers}
+@#
+@d etex_pen_base=toks_base+number_regs {start of table of \eTeX's penalties}
+@d inter_line_penalties_loc=etex_pen_base {additional penalties between lines}
+@d club_penalties_loc=etex_pen_base+1 {penalties for creating club lines}
+@d widow_penalties_loc=etex_pen_base+2 {penalties for creating widow lines}
+@d display_widow_penalties_loc=etex_pen_base+3 {ditto, just before a display}
+@d etex_pens=etex_pen_base+4 {end of table of \eTeX's penalties}
+@#
+@d local_left_box_base=etex_pens
+@d local_right_box_base=local_left_box_base+1
+@d box_base=local_right_box_base+1 {table of |number_regs| box registers}
+@d cur_font_loc=box_base+number_regs {internal font number outside math mode}
+@d math_font_base=cur_font_loc+1
+ {table of |number_math_fonts| math font numbers}
+@d cat_code_base=math_font_base+number_math_fonts
+ {table of |number_chars| command codes (the ``catcodes'')}
+@d lc_code_base=cat_code_base+1 {table of |number_chars| lowercase mappings}
+@d uc_code_base=lc_code_base+1 {table of |number_chars| uppercase mappings}
+@d sf_code_base=uc_code_base+1 {table of |number_chars| spacefactor mappings}
+@d math_code_base=sf_code_base+1 {table of |number_chars| math mode mappings}
+@d int_base=math_code_base+1 {beginning of region 5}
+@#
+@d par_shape_ptr==equiv(par_shape_loc)
+@d output_routine==equiv(output_routine_loc)
+@d every_par==equiv(every_par_loc)
+@d every_math==equiv(every_math_loc)
+@d every_display==equiv(every_display_loc)
+@d every_hbox==equiv(every_hbox_loc)
+@d every_vbox==equiv(every_vbox_loc)
+@d every_job==equiv(every_job_loc)
+@d every_cr==equiv(every_cr_loc)
+@d err_help==equiv(err_help_loc)
+@d pdf_pages_attr==equiv(pdf_pages_attr_loc)
+@d pdf_page_attr==equiv(pdf_page_attr_loc)
+@d pdf_page_resources==equiv(pdf_page_resources_loc)
+@d pdf_pk_mode==equiv(pdf_pk_mode_loc)
+@d toks(#)==equiv(toks_base+#)
+@d local_left_box==equiv(local_left_box_base)
+@d local_right_box==equiv(local_right_box_base)
+@d box(#)==equiv(box_base+#)
+@d cur_font==equiv(cur_font_loc)
+@d fam_fnt(#)==equiv(math_font_base+#)
+
+@<Put each...@>=
+primitive("output",assign_toks,output_routine_loc);
+@!@:output_}{\.{\\output} primitive@>
+primitive("everypar",assign_toks,every_par_loc);
+@!@:every_par_}{\.{\\everypar} primitive@>
+primitive("everymath",assign_toks,every_math_loc);
+@!@:every_math_}{\.{\\everymath} primitive@>
+primitive("everydisplay",assign_toks,every_display_loc);
+@!@:every_display_}{\.{\\everydisplay} primitive@>
+primitive("everyhbox",assign_toks,every_hbox_loc);
+@!@:every_hbox_}{\.{\\everyhbox} primitive@>
+primitive("everyvbox",assign_toks,every_vbox_loc);
+@!@:every_vbox_}{\.{\\everyvbox} primitive@>
+primitive("everyjob",assign_toks,every_job_loc);
+@!@:every_job_}{\.{\\everyjob} primitive@>
+primitive("everycr",assign_toks,every_cr_loc);
+@!@:every_cr_}{\.{\\everycr} primitive@>
+primitive("errhelp",assign_toks,err_help_loc);
+@!@:err_help_}{\.{\\errhelp} primitive@>
+primitive("pdfpagesattr",assign_toks,pdf_pages_attr_loc);
+@!@:pdf_pages_attr_}{\.{\\pdfpagesattr} primitive@>
+primitive("pdfpageattr",assign_toks,pdf_page_attr_loc);
+@!@:pdf_page_attr_}{\.{\\pdfpageattr} primitive@>
+primitive("pdfpageresources",assign_toks,pdf_page_resources_loc);
+@!@:pdf_page_resources_}{\.{\\pdfpageresources} primitive@>
+primitive("pdfpkmode",assign_toks,pdf_pk_mode_loc);
+@!@:pdf_pk_mode_}{\.{\\pdfpkmode} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+assign_toks: if chr_code>=toks_base then
+ begin print_esc("toks"); print_int(chr_code-toks_base);
+ end
+else case chr_code of
+ output_routine_loc: print_esc("output");
+ every_par_loc: print_esc("everypar");
+ every_math_loc: print_esc("everymath");
+ every_display_loc: print_esc("everydisplay");
+ every_hbox_loc: print_esc("everyhbox");
+ every_vbox_loc: print_esc("everyvbox");
+ every_job_loc: print_esc("everyjob");
+ every_cr_loc: print_esc("everycr");
+ @/@<Cases of |assign_toks| for |print_cmd_chr|@>@/
+ pdf_pages_attr_loc: print_esc("pdfpagesattr");
+ pdf_page_attr_loc: print_esc("pdfpageattr");
+ pdf_page_resources_loc: print_esc("pdfpageresources");
+ pdf_pk_mode_loc: print_esc("pdfpkmode");
+ othercases print_esc("errhelp")
+ endcases;
+
+@ We initialize most things to null or undefined values. An undefined font
+is represented by the internal code |font_base|.
+
+However, the character code tables are given initial values based on the
+conventional interpretation of ASCII code. These initial values should
+not be changed when \TeX\ is adapted for use with non-English languages;
+all changes to the initialization conventions should be made in format
+packages, not in \TeX\ itself, so that global interchange of formats is
+possible.
+
+@d null_font==font_base
+@d null_ocp==ocp_base
+@d null_ocp_list==ocp_list_base
+@d var_code==@"7000000 {math code meaning ``use the current family''}
+
+@<Initialize table entries...@>=
+par_shape_ptr:=null; eq_type(par_shape_loc):=shape_ref;
+eq_level(par_shape_loc):=level_one;@/
+for k:=etex_pen_base to etex_pens-1 do
+ eqtb[k]:=eqtb[par_shape_loc];
+for k:=output_routine_loc to toks_base+biggest_reg do
+ eqtb[k]:=eqtb[undefined_control_sequence];
+box(0):=null; eq_type(box_base):=box_ref; eq_level(box_base):=level_one;
+for k:=box_base+1 to box_base+biggest_reg do eqtb[k]:=eqtb[box_base];
+cur_font:=null_font; eq_type(cur_font_loc):=data;
+eq_level(cur_font_loc):=level_one;@/
+for k:=math_font_base to math_font_base+47 do eqtb[k]:=eqtb[cur_font_loc];
+equiv(cat_code_base):=0; eq_type(cat_code_base):=data;
+eq_level(cat_code_base):=level_one;@/
+eqtb[lc_code_base] :=eqtb[cat_code_base];
+eqtb[uc_code_base] :=eqtb[cat_code_base];
+eqtb[sf_code_base] :=eqtb[cat_code_base];
+eqtb[math_code_base]:=eqtb[cat_code_base];@/
+cat_code_table:=0;
+initex_cat_codes(0);
+for k:="0" to "9" do set_math_code(k,(hi(k+var_code)),level_one);@/
+for k:="A" to "Z" do begin
+ set_math_code(k,(hi(k+var_code+@"10000)),level_one);
+ set_math_code(k+32,(hi(k+32+var_code+@"10000)),level_one);@/
+ set_lc_code(k,k+32,level_one); set_lc_code(k+32,k+32,level_one);@/
+ set_uc_code(k,k,level_one); set_uc_code(k+32,k,level_one);@/
+ set_sf_code(k,999,level_one);
+ end;
+
+@ @<Set init...@>=
+static_int_base:=int_base;
+initialize_math_codes;
+initialize_text_codes;
+
+@ @<Show equivalent |n|, in region 4@>=
+if (n=par_shape_loc) or ((n>=etex_pen_base) and (n<etex_pens)) then
+ begin print_cmd_chr(set_shape,n); print_char("=");
+ if equiv(n)=null then print_char("0")
+ else if n>par_shape_loc then
+ begin print_int(penalty(equiv(n))); print_char(" ");
+ print_int(penalty(equiv(n)+1));
+ if penalty(equiv(n))>1 then print_esc("ETC.");
+ end
+ else print_int(vinfo(par_shape_ptr));
+ end
+else if n<toks_base then
+ {TH TODO make extra cases for ocps here! }
+ begin print_cmd_chr(assign_toks,n); print_char("=");
+ if equiv(n)<>null then show_token_list(link(equiv(n)),null,32);
+ end
+else if n<box_base then
+ begin print_esc("toks"); print_int(n-toks_base); print_char("=");
+ if equiv(n)<>null then show_token_list(link(equiv(n)),null,32);
+ end
+else if n<cur_font_loc then
+ begin print_esc("box"); print_int(n-box_base); print_char("=");
+ if equiv(n)=null then print("void")
+ else begin depth_threshold:=0; breadth_max:=1; show_node_list(equiv(n));
+ end;
+ end
+else if n<cat_code_base then @<Show the font identifier in |eqtb[n]|@>
+else @<Show the halfword code in |eqtb[n]|@>
+
+@ @<Show the font identifier in |eqtb[n]|@>=
+begin if n=cur_font_loc then print("current font")
+else if n<math_font_base+script_size then
+ begin print_esc("textfont"); print_int(n-math_font_base);
+ end
+else if n<math_font_base+script_script_size then
+ begin print_esc("scriptfont"); print_int(n-math_font_base-script_size);
+ end
+else begin print_esc("scriptscriptfont"); print_int(n-math_font_base-script_script_size);
+ end;
+print_char("=");@/
+print_esc(hash[font_id_base+equiv(n)].rh);
+ {that's |font_id_text(equiv(n))|}
+end
+
+@
+@d is_omath(#)== ((((#) mod @"1000000) div @"10000)>15) or
+ (((#) mod @"10000)>255)
+
+@<Show the halfword code in |eqtb[n]|@>=
+if n<math_code_base then
+ begin if n<lc_code_base then
+ begin print_esc("catcode"); print_int(n-cat_code_base);
+ end
+ else if n<uc_code_base then
+ begin print_esc("lccode"); print_int(n-lc_code_base);
+ end
+ else if n<sf_code_base then
+ begin print_esc("uccode"); print_int(n-uc_code_base);
+ end
+ else begin print_esc("sfcode"); print_int(n-sf_code_base);
+ end;
+ print_char("="); print_int(equiv(n));
+ end
+else begin
+ if is_omath(get_math_code(n-math_code_base)) then
+ print_esc("omathcode")
+ else
+ print_esc("mathcode");
+ print_int(n-math_code_base);
+ print_char("="); print_int(get_math_code(n-math_code_base));
+ end
+
+@ Region 5 of |eqtb| contains the integer parameters and registers defined
+here, as well as the |del_code| table. The latter table differs from the
+|cat_code..math_code| tables that precede it, since delimiter codes are
+fullword integers while the other kinds of codes occupy at most a
+halfword. This is what makes region~5 different from region~4. We will
+store the |eq_level| information in an auxiliary array of quarterwords
+that will be defined later.
+
+@d pretolerance_code=0 {badness tolerance before hyphenation}
+@d tolerance_code=1 {badness tolerance after hyphenation}
+@d line_penalty_code=2 {added to the badness of every line}
+@d hyphen_penalty_code=3 {penalty for break after discretionary hyphen}
+@d ex_hyphen_penalty_code=4 {penalty for break after explicit hyphen}
+@d club_penalty_code=5 {penalty for creating a club line}
+@d widow_penalty_code=6 {penalty for creating a widow line}
+@d display_widow_penalty_code=7 {ditto, just before a display}
+@d broken_penalty_code=8 {penalty for breaking a page at a broken line}
+@d bin_op_penalty_code=9 {penalty for breaking after a binary operation}
+@d rel_penalty_code=10 {penalty for breaking after a relation}
+@d pre_display_penalty_code=11
+ {penalty for breaking just before a displayed formula}
+@d post_display_penalty_code=12
+ {penalty for breaking just after a displayed formula}
+@d inter_line_penalty_code=13 {additional penalty between lines}
+@d double_hyphen_demerits_code=14 {demerits for double hyphen break}
+@d final_hyphen_demerits_code=15 {demerits for final hyphen break}
+@d adj_demerits_code=16 {demerits for adjacent incompatible lines}
+@d mag_code=17 {magnification ratio}
+@d delimiter_factor_code=18 {ratio for variable-size delimiters}
+@d looseness_code=19 {change in number of lines for a paragraph}
+@d time_code=20 {current time of day}
+@d day_code=21 {current day of the month}
+@d month_code=22 {current month of the year}
+@d year_code=23 {current year of our Lord}
+@d show_box_breadth_code=24 {nodes per level in |show_box|}
+@d show_box_depth_code=25 {maximum level in |show_box|}
+@d hbadness_code=26 {hboxes exceeding this badness will be shown by |hpack|}
+@d vbadness_code=27 {vboxes exceeding this badness will be shown by |vpack|}
+@d pausing_code=28 {pause after each line is read from a file}
+@d tracing_online_code=29 {show diagnostic output on terminal}
+@d tracing_macros_code=30 {show macros as they are being expanded}
+@d tracing_stats_code=31 {show memory usage if \TeX\ knows it}
+@d tracing_paragraphs_code=32 {show line-break calculations}
+@d tracing_pages_code=33 {show page-break calculations}
+@d tracing_output_code=34 {show boxes when they are shipped out}
+@d tracing_lost_chars_code=35 {show characters that aren't in the font}
+@d tracing_commands_code=36 {show command codes at |big_switch|}
+@d tracing_restores_code=37 {show equivalents when they are restored}
+@d uc_hyph_code=38 {hyphenate words beginning with a capital letter}
+@d output_penalty_code=39 {penalty found at current page break}
+@d max_dead_cycles_code=40 {bound on consecutive dead cycles of output}
+@d hang_after_code=41 {hanging indentation changes after this many lines}
+@d floating_penalty_code=42 {penalty for insertions heldover after a split}
+@d global_defs_code=43 {override \.{\\global} specifications}
+@d cur_fam_code=44 {current family}
+@d escape_char_code=45 {escape character for token output}
+@d default_hyphen_char_code=46 {value of \.{\\hyphenchar} when a font is loaded}
+@d default_skew_char_code=47 {value of \.{\\skewchar} when a font is loaded}
+@d end_line_char_code=48 {character placed at the right end of the buffer}
+@d new_line_char_code=49 {character that prints as |print_ln|}
+@d language_code=50 {current hyphenation table}
+@d left_hyphen_min_code=51 {minimum left hyphenation fragment size}
+@d right_hyphen_min_code=52 {minimum right hyphenation fragment size}
+@d holding_inserts_code=53 {do not remove insertion nodes from \.{\\box255}}
+@d error_context_lines_code=54 {maximum intermediate line pairs shown}
+@d local_inter_line_penalty_code=55 {local \.{\\interlinepenalty}}
+@d local_broken_penalty_code=56 {local \.{\\brokenpenalty}}
+@d no_local_whatsits_code=57 {counts local whatsits}
+@d no_local_dirs_code=58
+@d level_local_dir_code=59
+@d luastartup_id_code=60
+@d disable_lig_code=61
+@d disable_kern_code=62
+@d cat_code_table_code=63
+@d cur_lang_code=64 {current language id}
+@d ex_hyphen_char_code=65
+@d tex_int_pars=66 {total number of \.{\\TeX} + Aleph integer parameters}
+@#
+@d dir_base=int_base+tex_int_pars
+@d page_direction_code=0
+@d body_direction_code=1
+@d par_direction_code=2
+@d text_direction_code=3
+@d math_direction_code=4
+@d dir_pars=5
+@#
+@d pdftex_first_integer_code = dir_base+dir_pars {base for \pdfTeX's integer parameters}
+@d pdf_output_code = pdftex_first_integer_code + 0 {switch on PDF output if positive}
+@d pdf_compress_level_code = pdftex_first_integer_code + 1 {compress level of streams}
+@d pdf_decimal_digits_code = pdftex_first_integer_code + 2 {digits after the decimal point of numbers}
+@d pdf_move_chars_code = pdftex_first_integer_code + 3 {move chars 0..31 to higher area if possible}
+@d pdf_image_resolution_code = pdftex_first_integer_code + 4 {default image resolution}
+@d pdf_pk_resolution_code = pdftex_first_integer_code + 5 {default resolution of PK font}
+@d pdf_unique_resname_code = pdftex_first_integer_code + 6 {generate unique names for resouces}
+@d pdf_option_always_use_pdfpagebox_code = pdftex_first_integer_code + 7 {if the PDF inclusion should always use a specific PDF page box}
+@d pdf_option_pdf_inclusion_errorlevel_code = pdftex_first_integer_code + 8 {if the PDF inclusion should treat pdfs newer than |pdf_minor_version| as an error}
+@d pdf_minor_version_code = pdftex_first_integer_code + 9 {fractional part of the PDF version produced}
+@d pdf_force_pagebox_code = pdftex_first_integer_code + 10 {if the PDF inclusion should always use a specific PDF page box}
+@d pdf_pagebox_code = pdftex_first_integer_code + 11 {default pagebox to use for PDF inclusion}
+@d pdf_inclusion_errorlevel_code = pdftex_first_integer_code + 12 {if the PDF inclusion should treat pdfs newer than |pdf_minor_version| as an error}
+@d pdf_gamma_code = pdftex_first_integer_code + 13
+@d pdf_image_gamma_code = pdftex_first_integer_code + 14
+@d pdf_image_hicolor_code = pdftex_first_integer_code + 15
+@d pdf_image_apply_gamma_code = pdftex_first_integer_code + 16
+@d pdf_adjust_spacing_code = pdftex_first_integer_code + 17 {level of spacing adjusting}
+@d pdf_protrude_chars_code = pdftex_first_integer_code + 18 {protrude chars at left/right edge of paragraphs}
+@d pdf_tracing_fonts_code = pdftex_first_integer_code + 19 {level of font detail in log}
+@d pdf_objcompresslevel_code = pdftex_first_integer_code + 20 {activate object streams}
+@d pdf_gen_tounicode_code = pdftex_first_integer_code + 24 {generate ToUnicode for fonts?}
+@d pdf_draftmode_code = pdftex_first_integer_code + 25 {switch on draftmode if positive}
+@d pdf_replace_font_code = pdftex_first_integer_code + 26 {generate ToUnicode for fonts?}
+@d pdf_int_pars=pdftex_first_integer_code + 27 {total number of \pdfTeX's integer parameters}
+@#
+@d etex_int_base=pdf_int_pars {base for \eTeX's integer parameters}
+@d tracing_assigns_code=etex_int_base {show assignments}
+@d tracing_groups_code=etex_int_base+1 {show save/restore groups}
+@d tracing_ifs_code=etex_int_base+2 {show conditionals}
+@d tracing_scan_tokens_code=etex_int_base+3 {show pseudo file open and close}
+@d tracing_nesting_code=etex_int_base+4 {show incomplete groups and ifs within files}
+@d pre_display_direction_code=etex_int_base+5 {text direction preceding a display}
+@d last_line_fit_code=etex_int_base+6 {adjustment for last line of paragraph}
+@d saving_vdiscards_code=etex_int_base+7 {save items discarded from vlists}
+@d saving_hyph_codes_code=etex_int_base+8 {save hyphenation codes for languages}
+@d suppress_fontnotfound_error_code=etex_int_base+9 {surpress errors for missing fonts}
+@d etex_int_pars=etex_int_base+10 {total number of \eTeX's integer parameters}
+@#
+@d int_pars=etex_int_pars {total number of integer parameters}
+@d count_base=int_base+int_pars {|number_regs| user \.{\\count} registers}
+@d attribute_base=count_base+number_regs {|number_attrs| user \.{\\attribute} registers}
+@d del_code_base=attribute_base+number_attrs {|number_chars| delimiter code mappings}
+@d dimen_base=del_code_base+1 {beginning of region 6}
+@#
+@d count(#)==eqtb[count_base+#].int
+@d attribute(#)==eqtb[attribute_base+#].int
+@d int_par(#)==eqtb[int_base+#].int {an integer parameter}
+@d pretolerance==int_par(pretolerance_code)
+@d tolerance==int_par(tolerance_code)
+@d line_penalty==int_par(line_penalty_code)
+@d hyphen_penalty==int_par(hyphen_penalty_code)
+@d ex_hyphen_penalty==int_par(ex_hyphen_penalty_code)
+@d club_penalty==int_par(club_penalty_code)
+@d widow_penalty==int_par(widow_penalty_code)
+@d display_widow_penalty==int_par(display_widow_penalty_code)
+@d broken_penalty==int_par(broken_penalty_code)
+@d bin_op_penalty==int_par(bin_op_penalty_code)
+@d rel_penalty==int_par(rel_penalty_code)
+@d pre_display_penalty==int_par(pre_display_penalty_code)
+@d post_display_penalty==int_par(post_display_penalty_code)
+@d inter_line_penalty==int_par(inter_line_penalty_code)
+@d double_hyphen_demerits==int_par(double_hyphen_demerits_code)
+@d final_hyphen_demerits==int_par(final_hyphen_demerits_code)
+@d adj_demerits==int_par(adj_demerits_code)
+@d mag==int_par(mag_code)
+@d delimiter_factor==int_par(delimiter_factor_code)
+@d looseness==int_par(looseness_code)
+@d time==int_par(time_code)
+@d day==int_par(day_code)
+@d month==int_par(month_code)
+@d year==int_par(year_code)
+@d show_box_breadth==int_par(show_box_breadth_code)
+@d show_box_depth==int_par(show_box_depth_code)
+@d hbadness==int_par(hbadness_code)
+@d vbadness==int_par(vbadness_code)
+@d pausing==int_par(pausing_code)
+@d tracing_online==int_par(tracing_online_code)
+@d tracing_macros==int_par(tracing_macros_code)
+@d tracing_stats==int_par(tracing_stats_code)
+@d tracing_paragraphs==int_par(tracing_paragraphs_code)
+@d tracing_pages==int_par(tracing_pages_code)
+@d tracing_output==int_par(tracing_output_code)
+@d tracing_lost_chars==int_par(tracing_lost_chars_code)
+@d tracing_commands==int_par(tracing_commands_code)
+@d tracing_restores==int_par(tracing_restores_code)
+@d uc_hyph==int_par(uc_hyph_code)
+@d output_penalty==int_par(output_penalty_code)
+@d max_dead_cycles==int_par(max_dead_cycles_code)
+@d hang_after==int_par(hang_after_code)
+@d floating_penalty==int_par(floating_penalty_code)
+@d global_defs==int_par(global_defs_code)
+@d cur_fam==int_par(cur_fam_code)
+@d escape_char==int_par(escape_char_code)
+@d default_hyphen_char==int_par(default_hyphen_char_code)
+@d default_skew_char==int_par(default_skew_char_code)
+@d end_line_char==int_par(end_line_char_code)
+@d new_line_char==int_par(new_line_char_code)
+@d local_inter_line_penalty==int_par(local_inter_line_penalty_code)
+@d local_broken_penalty==int_par(local_broken_penalty_code)
+@d no_local_whatsits==int_par(no_local_whatsits_code)
+@d no_local_dirs==int_par(no_local_dirs_code)
+@d level_local_dir==int_par(level_local_dir_code)
+@d dir_par(#)==eqtb[dir_base+#].int {a direction parameter}
+@d page_direction==dir_par(page_direction_code)
+@d body_direction==dir_par(body_direction_code)
+@d par_direction==dir_par(par_direction_code)
+@d text_direction==dir_par(text_direction_code)
+@d math_direction==dir_par(math_direction_code)
+@d language==int_par(language_code)
+@d cur_lang==int_par(cur_lang_code)
+@d ex_hyphen_char==int_par(ex_hyphen_char_code)
+@d left_hyphen_min==int_par(left_hyphen_min_code)
+@d right_hyphen_min==int_par(right_hyphen_min_code)
+@d holding_inserts==int_par(holding_inserts_code)
+@d error_context_lines==int_par(error_context_lines_code)
+@d luastartup_id==int_par(luastartup_id_code)
+@d disable_lig==int_par(disable_lig_code)
+@d disable_kern==int_par(disable_kern_code)
+@d cat_code_table==int_par(cat_code_table_code)
+@#
+@d pdf_adjust_spacing == int_par(pdf_adjust_spacing_code)
+@d pdf_protrude_chars == int_par(pdf_protrude_chars_code)
+@d pdf_tracing_fonts == int_par(pdf_tracing_fonts_code)
+@d pdf_gen_tounicode == int_par(pdf_gen_tounicode_code)
+@d pdf_output == int_par(pdf_output_code)
+@d pdf_compress_level == int_par(pdf_compress_level_code)
+@d pdf_objcompresslevel == int_par(pdf_objcompresslevel_code)
+@d pdf_decimal_digits == int_par(pdf_decimal_digits_code)
+@d pdf_move_chars == int_par(pdf_move_chars_code)
+@d pdf_image_resolution == int_par(pdf_image_resolution_code)
+@d pdf_pk_resolution == int_par(pdf_pk_resolution_code)
+@d pdf_unique_resname == int_par(pdf_unique_resname_code)
+@d pdf_option_always_use_pdfpagebox == int_par(pdf_option_always_use_pdfpagebox_code)
+@d pdf_option_pdf_inclusion_errorlevel == int_par(pdf_option_pdf_inclusion_errorlevel_code)
+@d pdf_minor_version == int_par(pdf_minor_version_code)
+@d pdf_force_pagebox == int_par(pdf_force_pagebox_code)
+@d pdf_pagebox == int_par(pdf_pagebox_code)
+@d pdf_inclusion_errorlevel == int_par(pdf_inclusion_errorlevel_code)
+@d pdf_gamma == int_par(pdf_gamma_code)
+@d pdf_image_gamma == int_par(pdf_image_gamma_code)
+@d pdf_image_hicolor == int_par(pdf_image_hicolor_code)
+@d pdf_image_apply_gamma == int_par(pdf_image_apply_gamma_code)
+@d pdf_draftmode == int_par(pdf_draftmode_code)
+@d pdf_replace_font == int_par(pdf_replace_font_code)
+@#
+@d tracing_assigns==int_par(tracing_assigns_code)
+@d tracing_groups==int_par(tracing_groups_code)
+@d tracing_ifs==int_par(tracing_ifs_code)
+@d tracing_scan_tokens==int_par(tracing_scan_tokens_code)
+@d tracing_nesting==int_par(tracing_nesting_code)
+@d pre_display_direction==int_par(pre_display_direction_code)
+@d last_line_fit==int_par(last_line_fit_code)
+@d saving_vdiscards==int_par(saving_vdiscards_code)
+@d saving_hyph_codes==int_par(saving_hyph_codes_code)
+@d suppress_fontnotfound_error==int_par(suppress_fontnotfound_error_code)
+
+@<Assign the values |depth_threshold:=show_box_depth|...@>=
+depth_threshold:=show_box_depth;
+breadth_max:=show_box_breadth
+
+@ We can print the symbolic name of an integer parameter as follows.
+
+@p procedure print_param(@!n:integer);
+begin case n of
+pretolerance_code:print_esc("pretolerance");
+tolerance_code:print_esc("tolerance");
+line_penalty_code:print_esc("linepenalty");
+hyphen_penalty_code:print_esc("hyphenpenalty");
+ex_hyphen_penalty_code:print_esc("exhyphenpenalty");
+club_penalty_code:print_esc("clubpenalty");
+widow_penalty_code:print_esc("widowpenalty");
+display_widow_penalty_code:print_esc("displaywidowpenalty");
+broken_penalty_code:print_esc("brokenpenalty");
+bin_op_penalty_code:print_esc("binoppenalty");
+rel_penalty_code:print_esc("relpenalty");
+pre_display_penalty_code:print_esc("predisplaypenalty");
+post_display_penalty_code:print_esc("postdisplaypenalty");
+inter_line_penalty_code:print_esc("interlinepenalty");
+double_hyphen_demerits_code:print_esc("doublehyphendemerits");
+final_hyphen_demerits_code:print_esc("finalhyphendemerits");
+adj_demerits_code:print_esc("adjdemerits");
+mag_code:print_esc("mag");
+delimiter_factor_code:print_esc("delimiterfactor");
+looseness_code:print_esc("looseness");
+time_code:print_esc("time");
+day_code:print_esc("day");
+month_code:print_esc("month");
+year_code:print_esc("year");
+show_box_breadth_code:print_esc("showboxbreadth");
+show_box_depth_code:print_esc("showboxdepth");
+hbadness_code:print_esc("hbadness");
+vbadness_code:print_esc("vbadness");
+pausing_code:print_esc("pausing");
+tracing_online_code:print_esc("tracingonline");
+tracing_macros_code:print_esc("tracingmacros");
+tracing_stats_code:print_esc("tracingstats");
+tracing_paragraphs_code:print_esc("tracingparagraphs");
+tracing_pages_code:print_esc("tracingpages");
+tracing_output_code:print_esc("tracingoutput");
+tracing_lost_chars_code:print_esc("tracinglostchars");
+tracing_commands_code:print_esc("tracingcommands");
+tracing_restores_code:print_esc("tracingrestores");
+uc_hyph_code:print_esc("uchyph");
+output_penalty_code:print_esc("outputpenalty");
+max_dead_cycles_code:print_esc("maxdeadcycles");
+hang_after_code:print_esc("hangafter");
+floating_penalty_code:print_esc("floatingpenalty");
+global_defs_code:print_esc("globaldefs");
+cur_fam_code:print_esc("fam");
+escape_char_code:print_esc("escapechar");
+default_hyphen_char_code:print_esc("defaulthyphenchar");
+default_skew_char_code:print_esc("defaultskewchar");
+end_line_char_code:print_esc("endlinechar");
+new_line_char_code:print_esc("newlinechar");
+language_code:print_esc("language");
+cur_lang_code:print_esc("setlanguage");
+ex_hyphen_char_code:print_esc("exhyphenchar");
+left_hyphen_min_code:print_esc("lefthyphenmin");
+right_hyphen_min_code:print_esc("righthyphenmin");
+holding_inserts_code:print_esc("holdinginserts");
+error_context_lines_code:print_esc("errorcontextlines");
+luastartup_id_code:print_esc("luastartup");
+disable_lig_code:print_esc("noligs");
+disable_kern_code:print_esc("nokerns");
+cat_code_table_code:print_esc("catcodetable");
+@#
+local_inter_line_penalty_code: print_esc("localinterlinepenalty");
+local_broken_penalty_code: print_esc("localbrokenpenalty");
+{the next three do not have a matching primitive}
+no_local_whatsits_code: print("[no_local_whatsits]");
+no_local_dirs_code: print("[no_local_dirs]");
+level_local_dir_code: print("[level_local_dir]");
+@#
+pdf_output_code: print_esc("pdfoutput");
+pdf_compress_level_code: print_esc("pdfcompresslevel");
+pdf_objcompresslevel_code: print_esc("pdfobjcompresslevel");
+pdf_decimal_digits_code: print_esc("pdfdecimaldigits");
+pdf_move_chars_code: print_esc("pdfmovechars");
+pdf_image_resolution_code: print_esc("pdfimageresolution");
+pdf_pk_resolution_code: print_esc("pdfpkresolution");
+pdf_unique_resname_code: print_esc("pdfuniqueresname");
+pdf_option_always_use_pdfpagebox_code: print_esc("pdfoptionalwaysusepdfpagebox");
+pdf_option_pdf_inclusion_errorlevel_code: print_esc("pdfoptionpdfinclusionerrorlevel");
+pdf_minor_version_code: print_esc("pdfminorversion");
+pdf_force_pagebox_code: print_esc("pdfforcepagebox");
+pdf_pagebox_code: print_esc("pdfpagebox");
+pdf_inclusion_errorlevel_code: print_esc("pdfinclusionerrorlevel");
+pdf_gamma_code: print_esc("pdfgamma");
+pdf_image_gamma_code: print_esc("pdfimagegamma");
+pdf_image_hicolor_code: print_esc("pdfimagehicolor");
+pdf_image_apply_gamma_code: print_esc("pdfimageapplygamma");
+pdf_adjust_spacing_code: print_esc("pdfadjustspacing");
+pdf_protrude_chars_code: print_esc("pdfprotrudechars");
+pdf_tracing_fonts_code: print_esc("pdftracingfonts");
+pdf_gen_tounicode_code: print_esc("pdfgentounicode");
+pdf_draftmode_code: print_esc("pdfdraftmode");
+pdf_replace_font_code: print_esc("pdfreplacefont");
+@/@<Cases for |print_param|@>@/
+othercases begin print("[unknown integer parameter!]"); end
+endcases;
+end;
+
+@ The integer parameter names must be entered into the hash table.
+
+@<Put each...@>=
+primitive("pretolerance",assign_int,int_base+pretolerance_code);@/
+@!@:pretolerance_}{\.{\\pretolerance} primitive@>
+primitive("tolerance",assign_int,int_base+tolerance_code);@/
+@!@:tolerance_}{\.{\\tolerance} primitive@>
+primitive("linepenalty",assign_int,int_base+line_penalty_code);@/
+@!@:line_penalty_}{\.{\\linepenalty} primitive@>
+primitive("hyphenpenalty",assign_int,int_base+hyphen_penalty_code);@/
+@!@:hyphen_penalty_}{\.{\\hyphenpenalty} primitive@>
+primitive("exhyphenpenalty",assign_int,int_base+ex_hyphen_penalty_code);@/
+@!@:ex_hyphen_penalty_}{\.{\\exhyphenpenalty} primitive@>
+primitive("clubpenalty",assign_int,int_base+club_penalty_code);@/
+@!@:club_penalty_}{\.{\\clubpenalty} primitive@>
+primitive("widowpenalty",assign_int,int_base+widow_penalty_code);@/
+@!@:widow_penalty_}{\.{\\widowpenalty} primitive@>
+primitive("displaywidowpenalty",
+ assign_int,int_base+display_widow_penalty_code);@/
+@!@:display_widow_penalty_}{\.{\\displaywidowpenalty} primitive@>
+primitive("brokenpenalty",assign_int,int_base+broken_penalty_code);@/
+@!@:broken_penalty_}{\.{\\brokenpenalty} primitive@>
+primitive("binoppenalty",assign_int,int_base+bin_op_penalty_code);@/
+@!@:bin_op_penalty_}{\.{\\binoppenalty} primitive@>
+primitive("relpenalty",assign_int,int_base+rel_penalty_code);@/
+@!@:rel_penalty_}{\.{\\relpenalty} primitive@>
+primitive("predisplaypenalty",assign_int,int_base+pre_display_penalty_code);@/
+@!@:pre_display_penalty_}{\.{\\predisplaypenalty} primitive@>
+primitive("postdisplaypenalty",assign_int,int_base+post_display_penalty_code);@/
+@!@:post_display_penalty_}{\.{\\postdisplaypenalty} primitive@>
+primitive("interlinepenalty",assign_int,int_base+inter_line_penalty_code);@/
+@!@:inter_line_penalty_}{\.{\\interlinepenalty} primitive@>
+primitive("doublehyphendemerits",
+ assign_int,int_base+double_hyphen_demerits_code);@/
+@!@:double_hyphen_demerits_}{\.{\\doublehyphendemerits} primitive@>
+primitive("finalhyphendemerits",
+ assign_int,int_base+final_hyphen_demerits_code);@/
+@!@:final_hyphen_demerits_}{\.{\\finalhyphendemerits} primitive@>
+primitive("adjdemerits",assign_int,int_base+adj_demerits_code);@/
+@!@:adj_demerits_}{\.{\\adjdemerits} primitive@>
+primitive("mag",assign_int,int_base+mag_code);@/
+@!@:mag_}{\.{\\mag} primitive@>
+primitive("delimiterfactor",assign_int,int_base+delimiter_factor_code);@/
+@!@:delimiter_factor_}{\.{\\delimiterfactor} primitive@>
+primitive("looseness",assign_int,int_base+looseness_code);@/
+@!@:looseness_}{\.{\\looseness} primitive@>
+primitive("time",assign_int,int_base+time_code);@/
+@!@:time_}{\.{\\time} primitive@>
+primitive("day",assign_int,int_base+day_code);@/
+@!@:day_}{\.{\\day} primitive@>
+primitive("month",assign_int,int_base+month_code);@/
+@!@:month_}{\.{\\month} primitive@>
+primitive("year",assign_int,int_base+year_code);@/
+@!@:year_}{\.{\\year} primitive@>
+primitive("showboxbreadth",assign_int,int_base+show_box_breadth_code);@/
+@!@:show_box_breadth_}{\.{\\showboxbreadth} primitive@>
+primitive("showboxdepth",assign_int,int_base+show_box_depth_code);@/
+@!@:show_box_depth_}{\.{\\showboxdepth} primitive@>
+primitive("hbadness",assign_int,int_base+hbadness_code);@/
+@!@:hbadness_}{\.{\\hbadness} primitive@>
+primitive("vbadness",assign_int,int_base+vbadness_code);@/
+@!@:vbadness_}{\.{\\vbadness} primitive@>
+primitive("pausing",assign_int,int_base+pausing_code);@/
+@!@:pausing_}{\.{\\pausing} primitive@>
+primitive("tracingonline",assign_int,int_base+tracing_online_code);@/
+@!@:tracing_online_}{\.{\\tracingonline} primitive@>
+primitive("tracingmacros",assign_int,int_base+tracing_macros_code);@/
+@!@:tracing_macros_}{\.{\\tracingmacros} primitive@>
+primitive("tracingstats",assign_int,int_base+tracing_stats_code);@/
+@!@:tracing_stats_}{\.{\\tracingstats} primitive@>
+primitive("tracingparagraphs",assign_int,int_base+tracing_paragraphs_code);@/
+@!@:tracing_paragraphs_}{\.{\\tracingparagraphs} primitive@>
+primitive("tracingpages",assign_int,int_base+tracing_pages_code);@/
+@!@:tracing_pages_}{\.{\\tracingpages} primitive@>
+primitive("tracingoutput",assign_int,int_base+tracing_output_code);@/
+@!@:tracing_output_}{\.{\\tracingoutput} primitive@>
+primitive("tracinglostchars",assign_int,int_base+tracing_lost_chars_code);@/
+@!@:tracing_lost_chars_}{\.{\\tracinglostchars} primitive@>
+primitive("tracingcommands",assign_int,int_base+tracing_commands_code);@/
+@!@:tracing_commands_}{\.{\\tracingcommands} primitive@>
+primitive("tracingrestores",assign_int,int_base+tracing_restores_code);@/
+@!@:tracing_restores_}{\.{\\tracingrestores} primitive@>
+primitive("uchyph",assign_int,int_base+uc_hyph_code);@/
+@!@:uc_hyph_}{\.{\\uchyph} primitive@>
+primitive("outputpenalty",assign_int,int_base+output_penalty_code);@/
+@!@:output_penalty_}{\.{\\outputpenalty} primitive@>
+primitive("maxdeadcycles",assign_int,int_base+max_dead_cycles_code);@/
+@!@:max_dead_cycles_}{\.{\\maxdeadcycles} primitive@>
+primitive("hangafter",assign_int,int_base+hang_after_code);@/
+@!@:hang_after_}{\.{\\hangafter} primitive@>
+primitive("floatingpenalty",assign_int,int_base+floating_penalty_code);@/
+@!@:floating_penalty_}{\.{\\floatingpenalty} primitive@>
+primitive("globaldefs",assign_int,int_base+global_defs_code);@/
+@!@:global_defs_}{\.{\\globaldefs} primitive@>
+primitive("fam",assign_int,int_base+cur_fam_code);@/
+@!@:fam_}{\.{\\fam} primitive@>
+primitive("escapechar",assign_int,int_base+escape_char_code);@/
+@!@:escape_char_}{\.{\\escapechar} primitive@>
+primitive("defaulthyphenchar",assign_int,int_base+default_hyphen_char_code);@/
+@!@:default_hyphen_char_}{\.{\\defaulthyphenchar} primitive@>
+primitive("defaultskewchar",assign_int,int_base+default_skew_char_code);@/
+@!@:default_skew_char_}{\.{\\defaultskewchar} primitive@>
+primitive("endlinechar",assign_int,int_base+end_line_char_code);@/
+@!@:end_line_char_}{\.{\\endlinechar} primitive@>
+primitive("newlinechar",assign_int,int_base+new_line_char_code);@/
+@!@:new_line_char_}{\.{\\newlinechar} primitive@>
+primitive("language",assign_int,int_base+language_code);@/
+@!@:language_}{\.{\\language} primitive@>
+primitive("setlanguage",assign_int,int_base+cur_lang_code);@/
+@!@:cur_lang_}{\.{\\setlanguage} primitive@>
+primitive("exhyphenchar",assign_int,int_base+ex_hyphen_char_code);@/
+@!@:ex_hyphen_char_}{\.{\\exhyphenchar} primitive@>
+primitive("lefthyphenmin",assign_int,int_base+left_hyphen_min_code);@/
+@!@:left_hyphen_min_}{\.{\\lefthyphenmin} primitive@>
+primitive("righthyphenmin",assign_int,int_base+right_hyphen_min_code);@/
+@!@:right_hyphen_min_}{\.{\\righthyphenmin} primitive@>
+primitive("holdinginserts",assign_int,int_base+holding_inserts_code);@/
+@!@:holding_inserts_}{\.{\\holdinginserts} primitive@>
+primitive("errorcontextlines",assign_int,int_base+error_context_lines_code);@/
+@!@:error_context_lines_}{\.{\\errorcontextlines} primitive@>
+primitive("luastartup",assign_int,int_base+luastartup_id_code);@/
+@!@:luastartup_id_}{\.{\\luastartup} primitive@>
+primitive("nokerns",assign_int,int_base+disable_kern_code);@/
+@!@:disable_kern_}{\.{\\noligkerns} primitive@>
+primitive("noligs",assign_int,int_base+disable_lig_code);@/
+@!@:disable_lig_}{\.{\\noligs} primitive@>
+primitive("catcodetable",assign_int,int_base+cat_code_table_code);@/
+@!@:cat_code_table_}{\.{\\catcodetable} primitive@>
+primitive("pdfoutput",assign_int,int_base+pdf_output_code);@/
+@!@:pdf_output_}{\.{\\pdfoutput} primitive@>
+primitive("pdfcompresslevel",assign_int,int_base+pdf_compress_level_code);@/
+@!@:pdf_compress_level_}{\.{\\pdfcompresslevel} primitive@>
+primitive("pdfobjcompresslevel",assign_int,int_base+pdf_objcompresslevel_code);@/
+@!@:pdf_objcompresslevel_}{\.{\\pdfobjcompresslevel} primitive@>
+primitive("pdfdecimaldigits",assign_int,int_base+pdf_decimal_digits_code);@/
+@!@:pdf_decimal_digits_}{\.{\\pdfdecimaldigits} primitive@>
+primitive("pdfmovechars",assign_int,int_base+pdf_move_chars_code);@/
+@!@:pdf_move_chars_}{\.{\\pdfmovechars} primitive@>
+primitive("pdfimageresolution",assign_int,int_base+pdf_image_resolution_code);@/
+@!@:pdf_image_resolution_}{\.{\\pdfimageresolution} primitive@>
+primitive("pdfpkresolution",assign_int,int_base+pdf_pk_resolution_code);@/
+@!@:pdf_pk_resolution_}{\.{\\pdfpkresolution} primitive@>
+primitive("pdfuniqueresname",assign_int,int_base+pdf_unique_resname_code);@/
+@!@:pdf_unique_resname_}{\.{\\pdfuniqueresname} primitive@>
+primitive("pdfoptionpdfminorversion",assign_int,int_base+pdf_minor_version_code);@/
+@!@:pdf_minor_version_}{\.{\\pdfoptionpdfminorversion} primitive@>
+primitive("pdfoptionalwaysusepdfpagebox",assign_int,int_base+pdf_option_always_use_pdfpagebox_code);@/
+@!@:pdf_option_always_use_pdfpagebox_}{\.{\\pdfoptionalwaysusepdfpagebox} primitive@>
+primitive("pdfoptionpdfinclusionerrorlevel",assign_int,int_base+pdf_option_pdf_inclusion_errorlevel_code);@/
+@!@:pdf_option_pdf_inclusion_errorlevel_}{\.{\\pdfoptionpdfinclusionerrorlevel} primitive@>
+primitive("pdfminorversion",assign_int,int_base+pdf_minor_version_code);@/
+@!@:pdf_minor_version_}{\.{\\pdfminorversion} primitive@>
+primitive("pdfforcepagebox",assign_int,int_base+pdf_force_pagebox_code);@/
+@!@:pdf_force_pagebox_}{\.{\\pdfforcepagebox} primitive@>
+primitive("pdfpagebox",assign_int,int_base+pdf_pagebox_code);@/
+@!@:pdf_pagebox_}{\.{\\pdfpagebox} primitive@>
+primitive("pdfinclusionerrorlevel",assign_int,int_base+pdf_inclusion_errorlevel_code);@/
+@!@:pdf_inclusion_errorlevel_}{\.{\\pdfinclusionerrorlevel} primitive@>
+primitive("pdfgamma",assign_int,int_base+pdf_gamma_code);@/
+@!@:pdf_gamma_}{\.{\\pdfgamma} primitive@>
+primitive("pdfimagegamma",assign_int,int_base+pdf_image_gamma_code);@/
+@!@:pdf_image_gamma_}{\.{\\pdfimagegamma} primitive@>
+primitive("pdfimagehicolor",assign_int,int_base+pdf_image_hicolor_code);@/
+@!@:pdf_image_hicolor_}{\.{\\pdfimagehicolor} primitive@>
+primitive("pdfimageapplygamma",assign_int,int_base+pdf_image_apply_gamma_code);@/
+@!@:pdf_image_apply_gamma_}{\.{\\pdfimageapplygamma} primitive@>
+primitive("pdfadjustspacing",assign_int,int_base+pdf_adjust_spacing_code);@/
+@!@:pdf_adjust_spacing_}{\.{\\pdfadjustspacing} primitive@>
+primitive("pdfprotrudechars",assign_int,int_base+pdf_protrude_chars_code);@/
+@!@:pdf_protrude_chars_}{\.{\\pdfprotrudechars} primitive@>
+primitive("pdftracingfonts",assign_int,int_base+pdf_tracing_fonts_code);@/
+@!@:pdf_tracing_fonts_}{\.{\\pdftracingfonts} primitive@>
+primitive("pdfgentounicode",assign_int,int_base+pdf_gen_tounicode_code);@/
+@!@:pdf_gen_tounicode_}{\.{\\pdfgentounicode} primitive@>
+primitive("pdfdraftmode",assign_int,int_base+pdf_draftmode_code);@/
+@!@:pdf_draftmode_}{\.{\\pdfdraftmode} primitive@>
+primitive("pdfreplacefont",assign_int,int_base+pdf_replace_font_code);@/
+@!@:pdf_replace_font_}{\.{\\pdfreplacefont} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+assign_int: if chr_code<count_base then print_param(chr_code-int_base)
+ else begin print_esc("count"); print_int(chr_code-count_base);
+ end;
+assign_attr: begin print_esc("attribute"); print_int(chr_code-attribute_base);
+ end;
+
+@ The integer parameters should really be initialized by a macro package;
+the following initialization does the minimum to keep \TeX\ from
+complete failure.
+@^null delimiter@>
+
+@<Initialize table entries...@>=
+for k:=int_base to attribute_base-1 do eqtb[k].int:=0;
+for k:=attribute_base to del_code_base-1 do eqtb[k].int:=-1;
+mag:=1000; tolerance:=10000; hang_after:=1; max_dead_cycles:=25;
+escape_char:="\"; end_line_char:=carriage_return;
+eqtb[int_base+level_local_dir_code].int:=level_one;
+set_del_code(".",0,0,level_one); {this null delimiter is used in error recovery}
+ex_hyphen_char:="-";
+
+@ The following procedure, which is called just before \TeX\ initializes its
+input and output, establishes the initial values of the date and time.
+@^system dependencies@>
+Since standard \PASCAL\ cannot provide such information, something special
+is needed. The program here simply specifies July 4, 1776, at noon; but
+users probably want a better approximation to the truth.
+
+@p procedure fix_date_and_time;
+begin time:=12*60; {minutes since midnight}
+day:=4; {fourth day of the month}
+month:=7; {seventh month of the year}
+year:=1776; {Anno Domini}
+end;
+
+@ @<Show equivalent |n|, in region 5@>=
+begin if n<count_base then begin print_param(n-int_base);
+ print_char("="); print_int(eqtb[n].int);
+ end
+else if n<attribute_base then
+ begin print_esc("count"); print_int(n-count_base);
+ print_char("="); print_int(eqtb[n].int);
+ end
+else if n<del_code_base then
+ begin print_esc("attribute"); print_int(n-attribute_base);
+ print_char("="); print_int(eqtb[n].int);
+ end
+else begin
+ {TH: todo, this stuff doesnt work}
+ print_esc("delcode");
+ end;
+end
+
+@ @<Set variable |c| to the current escape character@>=c:=escape_char
+
+@ @<Character |s| is the current new-line character@>=s=new_line_char
+
+@ \TeX\ is occasionally supposed to print diagnostic information that
+goes only into the transcript file, unless |tracing_online| is positive.
+Here are two routines that adjust the destination of print commands:
+
+@p procedure begin_diagnostic; {prepare to do some tracing}
+begin global_old_setting:=selector;
+if (tracing_online<=0)and(selector=term_and_log) then
+ begin decr(selector);
+ if history=spotless then history:=warning_issued;
+ end;
+end;
+@#
+procedure end_diagnostic(@!blank_line:boolean);
+ {restore proper conditions after tracing}
+begin print_nl("");
+if blank_line then print_ln;
+selector:=global_old_setting;
+end;
+
+@ Of course we had better declare another global variable, if the previous
+routines are going to work.
+
+@<Glob...@>=
+@!global_old_setting:0..max_selector;
+
+@ The final region of |eqtb| contains the dimension parameters defined
+here, and the |number_regs| \.{\\dimen} registers.
+
+@d par_indent_code=0 {indentation of paragraphs}
+@d math_surround_code=1 {space around math in text}
+@d line_skip_limit_code=2 {threshold for |line_skip| instead of |baseline_skip|}
+@d hsize_code=3 {line width in horizontal mode}
+@d vsize_code=4 {page height in vertical mode}
+@d max_depth_code=5 {maximum depth of boxes on main pages}
+@d split_max_depth_code=6 {maximum depth of boxes on split pages}
+@d box_max_depth_code=7 {maximum depth of explicit vboxes}
+@d hfuzz_code=8 {tolerance for overfull hbox messages}
+@d vfuzz_code=9 {tolerance for overfull vbox messages}
+@d delimiter_shortfall_code=10 {maximum amount uncovered by variable delimiters}
+@d null_delimiter_space_code=11 {blank space in null delimiters}
+@d script_space_code=12 {extra space after subscript or superscript}
+@d pre_display_size_code=13 {length of text preceding a display}
+@d display_width_code=14 {length of line for displayed equation}
+@d display_indent_code=15 {indentation of line for displayed equation}
+@d overfull_rule_code=16 {width of rule that identifies overfull hboxes}
+@d hang_indent_code=17 {amount of hanging indentation}
+@d h_offset_code=18 {amount of horizontal offset when shipping pages out}
+@d v_offset_code=19 {amount of vertical offset when shipping pages out}
+@d emergency_stretch_code=20 {reduces badnesses on final pass of line-breaking}
+@d page_right_offset_code=21
+@d page_bottom_offset_code=22
+@d pdftex_first_dimen_code = 23 {first number defined in this section}
+@d pdf_h_origin_code = pdftex_first_dimen_code + 0 {horigin of the PDF output}
+@d pdf_v_origin_code = pdftex_first_dimen_code + 1 {vorigin of the PDF output}
+@d page_width_code = pdftex_first_dimen_code + 2 {page width of the PDF output}
+@d page_height_code = pdftex_first_dimen_code + 3 {page height of the PDF output}
+@d pdf_link_margin_code = pdftex_first_dimen_code + 4 {link margin in the PDF output}
+@d pdf_dest_margin_code = pdftex_first_dimen_code + 5 {dest margin in the PDF output}
+@d pdf_thread_margin_code = pdftex_first_dimen_code + 6 {thread margin in the PDF output}
+@d pdf_first_line_height_code = pdftex_first_dimen_code + 7
+@d pdf_last_line_depth_code = pdftex_first_dimen_code + 8
+@d pdf_each_line_height_code = pdftex_first_dimen_code + 9
+@d pdf_each_line_depth_code = pdftex_first_dimen_code + 10
+@d pdf_px_dimen_code = pdftex_first_dimen_code + 11
+@d pdftex_last_dimen_code = pdftex_first_dimen_code + 11 {last number defined in this section}
+@d dimen_pars = pdftex_last_dimen_code + 1 {total number of dimension parameters}
+@d scaled_base=dimen_base+dimen_pars
+ {table of |number_regs| user-defined \.{\\dimen} registers}
+@d eqtb_size=scaled_base+biggest_reg {largest subscript of |eqtb|}
+@#
+@d dimen(#)==eqtb[scaled_base+#].sc
+@d dimen_par(#)==eqtb[dimen_base+#].sc {a scaled quantity}
+@d par_indent==dimen_par(par_indent_code)
+@d math_surround==dimen_par(math_surround_code)
+@d line_skip_limit==dimen_par(line_skip_limit_code)
+@d hsize==dimen_par(hsize_code)
+@d vsize==dimen_par(vsize_code)
+@d max_depth==dimen_par(max_depth_code)
+@d split_max_depth==dimen_par(split_max_depth_code)
+@d box_max_depth==dimen_par(box_max_depth_code)
+@d hfuzz==dimen_par(hfuzz_code)
+@d vfuzz==dimen_par(vfuzz_code)
+@d delimiter_shortfall==dimen_par(delimiter_shortfall_code)
+@d null_delimiter_space==dimen_par(null_delimiter_space_code)
+@d script_space==dimen_par(script_space_code)
+@d pre_display_size==dimen_par(pre_display_size_code)
+@d display_width==dimen_par(display_width_code)
+@d display_indent==dimen_par(display_indent_code)
+@d overfull_rule==dimen_par(overfull_rule_code)
+@d hang_indent==dimen_par(hang_indent_code)
+@d h_offset==dimen_par(h_offset_code)
+@d v_offset==dimen_par(v_offset_code)
+@d emergency_stretch==dimen_par(emergency_stretch_code)
+@d page_right_offset==dimen_par(page_right_offset_code)
+@d page_bottom_offset==dimen_par(page_bottom_offset_code)
+@d pdf_h_origin == dimen_par(pdf_h_origin_code)
+@d pdf_v_origin == dimen_par(pdf_v_origin_code)
+@d page_width == dimen_par(page_width_code)
+@d page_height == dimen_par(page_height_code)
+@d pdf_link_margin == dimen_par(pdf_link_margin_code)
+@d pdf_dest_margin == dimen_par(pdf_dest_margin_code)
+@d pdf_thread_margin == dimen_par(pdf_thread_margin_code)
+@d pdf_first_line_height == dimen_par(pdf_first_line_height_code)
+@d pdf_last_line_depth == dimen_par(pdf_last_line_depth_code)
+@d pdf_each_line_height == dimen_par(pdf_each_line_height_code)
+@d pdf_each_line_depth == dimen_par(pdf_each_line_depth_code)
+@d pdf_px_dimen == dimen_par(pdf_px_dimen_code)
+
+@p procedure print_length_param(@!n:integer);
+begin case n of
+par_indent_code:print_esc("parindent");
+math_surround_code:print_esc("mathsurround");
+line_skip_limit_code:print_esc("lineskiplimit");
+hsize_code:print_esc("hsize");
+vsize_code:print_esc("vsize");
+max_depth_code:print_esc("maxdepth");
+split_max_depth_code:print_esc("splitmaxdepth");
+box_max_depth_code:print_esc("boxmaxdepth");
+hfuzz_code:print_esc("hfuzz");
+vfuzz_code:print_esc("vfuzz");
+delimiter_shortfall_code:print_esc("delimitershortfall");
+null_delimiter_space_code:print_esc("nulldelimiterspace");
+script_space_code:print_esc("scriptspace");
+pre_display_size_code:print_esc("predisplaysize");
+display_width_code:print_esc("displaywidth");
+display_indent_code:print_esc("displayindent");
+overfull_rule_code:print_esc("overfullrule");
+hang_indent_code:print_esc("hangindent");
+h_offset_code:print_esc("hoffset");
+v_offset_code:print_esc("voffset");
+emergency_stretch_code:print_esc("emergencystretch");
+page_right_offset_code:print_esc("pagerightoffset");
+page_bottom_offset_code:print_esc("pagebottomoffset");
+pdf_h_origin_code: print_esc("pdfhorigin");
+pdf_v_origin_code: print_esc("pdfvorigin");
+page_width_code: print_esc("pagewidth");
+page_height_code: print_esc("pageheight");
+pdf_link_margin_code: print_esc("pdflinkmargin");
+pdf_dest_margin_code: print_esc("pdfdestmargin");
+pdf_thread_margin_code: print_esc("pdfthreadmargin");
+pdf_first_line_height_code: print_esc("pdffirstlineheight");
+pdf_last_line_depth_code: print_esc("pdflastlinedepth");
+pdf_each_line_height_code: print_esc("pdfeachlineheight");
+pdf_each_line_depth_code: print_esc("pdfeachlinedepth");
+pdf_px_dimen_code: print_esc("pdfpxdimen");
+othercases print("[unknown dimen parameter!]")
+endcases;
+end;
+
+@ @<Put each...@>=
+primitive("parindent",assign_dimen,dimen_base+par_indent_code);@/
+@!@:par_indent_}{\.{\\parindent} primitive@>
+primitive("mathsurround",assign_dimen,dimen_base+math_surround_code);@/
+@!@:math_surround_}{\.{\\mathsurround} primitive@>
+primitive("lineskiplimit",assign_dimen,dimen_base+line_skip_limit_code);@/
+@!@:line_skip_limit_}{\.{\\lineskiplimit} primitive@>
+primitive("hsize",assign_dimen,dimen_base+hsize_code);@/
+@!@:hsize_}{\.{\\hsize} primitive@>
+primitive("vsize",assign_dimen,dimen_base+vsize_code);@/
+@!@:vsize_}{\.{\\vsize} primitive@>
+primitive("maxdepth",assign_dimen,dimen_base+max_depth_code);@/
+@!@:max_depth_}{\.{\\maxdepth} primitive@>
+primitive("splitmaxdepth",assign_dimen,dimen_base+split_max_depth_code);@/
+@!@:split_max_depth_}{\.{\\splitmaxdepth} primitive@>
+primitive("boxmaxdepth",assign_dimen,dimen_base+box_max_depth_code);@/
+@!@:box_max_depth_}{\.{\\boxmaxdepth} primitive@>
+primitive("hfuzz",assign_dimen,dimen_base+hfuzz_code);@/
+@!@:hfuzz_}{\.{\\hfuzz} primitive@>
+primitive("vfuzz",assign_dimen,dimen_base+vfuzz_code);@/
+@!@:vfuzz_}{\.{\\vfuzz} primitive@>
+primitive("delimitershortfall",
+ assign_dimen,dimen_base+delimiter_shortfall_code);@/
+@!@:delimiter_shortfall_}{\.{\\delimitershortfall} primitive@>
+primitive("nulldelimiterspace",
+ assign_dimen,dimen_base+null_delimiter_space_code);@/
+@!@:null_delimiter_space_}{\.{\\nulldelimiterspace} primitive@>
+primitive("scriptspace",assign_dimen,dimen_base+script_space_code);@/
+@!@:script_space_}{\.{\\scriptspace} primitive@>
+primitive("predisplaysize",assign_dimen,dimen_base+pre_display_size_code);@/
+@!@:pre_display_size_}{\.{\\predisplaysize} primitive@>
+primitive("displaywidth",assign_dimen,dimen_base+display_width_code);@/
+@!@:display_width_}{\.{\\displaywidth} primitive@>
+primitive("displayindent",assign_dimen,dimen_base+display_indent_code);@/
+@!@:display_indent_}{\.{\\displayindent} primitive@>
+primitive("overfullrule",assign_dimen,dimen_base+overfull_rule_code);@/
+@!@:overfull_rule_}{\.{\\overfullrule} primitive@>
+primitive("hangindent",assign_dimen,dimen_base+hang_indent_code);@/
+@!@:hang_indent_}{\.{\\hangindent} primitive@>
+primitive("hoffset",assign_dimen,dimen_base+h_offset_code);@/
+@!@:h_offset_}{\.{\\hoffset} primitive@>
+primitive("voffset",assign_dimen,dimen_base+v_offset_code);@/
+@!@:v_offset_}{\.{\\voffset} primitive@>
+primitive("emergencystretch",assign_dimen,dimen_base+emergency_stretch_code);@/
+@!@:emergency_stretch_}{\.{\\emergencystretch} primitive@>
+primitive("pdfhorigin",assign_dimen,dimen_base+pdf_h_origin_code);@/
+@!@:pdf_h_origin_}{\.{\\pdfhorigin} primitive@>
+primitive("pdfvorigin",assign_dimen,dimen_base+pdf_v_origin_code);@/
+@!@:pdf_v_origin_}{\.{\\pdfvorigin} primitive@>
+@#
+primitive("pagewidth",assign_dimen,dimen_base+page_width_code);@/
+primitive("pdfpagewidth",assign_dimen,dimen_base+page_width_code);@/
+@!@:page_width_}{\.{\\pdfpagewidth} primitive@>
+primitive("pageheight",assign_dimen,dimen_base+page_height_code);@/
+primitive("pdfpageheight",assign_dimen,dimen_base+page_height_code);@/
+@!@:page_height_}{\.{\\pdfpageheight} primitive@>
+@#
+primitive("pdflinkmargin",assign_dimen,dimen_base+pdf_link_margin_code);@/
+@!@:pdf_link_margin_}{\.{\\pdflinkmargin} primitive@>
+primitive("pdfdestmargin",assign_dimen,dimen_base+pdf_dest_margin_code);@/
+@!@:pdf_dest_margin_}{\.{\\pdfdestmargin} primitive@>
+primitive("pdfthreadmargin",assign_dimen,dimen_base+pdf_thread_margin_code);@/
+@!@:pdf_thread_margin_}{\.{\\pdfthreadmargin} primitive@>
+primitive("pdffirstlineheight",assign_dimen,dimen_base+pdf_first_line_height_code);@/
+@!@:pdf_first_line_height_}{\.{\\pdffirstlineheight} primitive@>
+primitive("pdflastlinedepth",assign_dimen,dimen_base+pdf_last_line_depth_code);@/
+@!@:pdf_last_line_depth_}{\.{\\pdflastlinedepth} primitive@>
+primitive("pdfeachlineheight",assign_dimen,dimen_base+pdf_each_line_height_code);@/
+@!@:pdf_each_line_height_}{\.{\\pdfeachlineheight} primitive@>
+primitive("pdfeachlinedepth",assign_dimen,dimen_base+pdf_each_line_depth_code);@/
+@!@:pdf_each_line_depth_}{\.{\\pdfeachlinedepth} primitive@>
+primitive("pdfpxdimen",assign_dimen,dimen_base+pdf_px_dimen_code);@/
+@!@:pdf_px_dimen_}{\.{\\pdfpxdimen} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+assign_dimen: if chr_code<scaled_base then
+ print_length_param(chr_code-dimen_base)
+ else begin print_esc("dimen"); print_int(chr_code-scaled_base);
+ end;
+
+@ @<Initialize table entries...@>=
+for k:=dimen_base to eqtb_size do eqtb[k].sc:=0;
+
+@ @<Show equivalent |n|, in region 6@>=
+begin if n<scaled_base then print_length_param(n-dimen_base)
+else begin print_esc("dimen"); print_int(n-scaled_base);
+ end;
+print_char("="); print_scaled(eqtb[n].sc); print("pt");
+end
+
+@ Here is a procedure that displays the contents of |eqtb[n]|
+symbolically.
+
+@p@t\4@>@<Declare the procedure called |print_cmd_chr|@>@;@/
+@!stat procedure show_eqtb(@!n:pointer);
+begin if n<active_base then print_char("?") {this can't happen}
+else if n<glue_base then @<Show equivalent |n|, in region 1 or 2@>
+else if n<local_base then @<Show equivalent |n|, in region 3@>
+else if n<int_base then @<Show equivalent |n|, in region 4@>
+else if n<dimen_base then @<Show equivalent |n|, in region 5@>
+else if n<=eqtb_size then @<Show equivalent |n|, in region 6@>
+else print_char("?"); {this can't happen either}
+end;
+tats
+
+@ The last two regions of |eqtb| have fullword values instead of the
+three fields |eq_level|, |eq_type|, and |equiv|. An |eq_type| is unnecessary,
+but \TeX\ needs to store the |eq_level| information in another array
+called |xeq_level|.
+
+@<Glob...@>=
+@!eqtb:array[active_base..eqtb_size] of memory_word;
+@!xeq_level:array[int_base..eqtb_size] of quarterword;
+
+@ @<Set init...@>=
+for k:=int_base to eqtb_size do xeq_level[k]:=level_one;
+
+@* \[18] The hash table.
+Control sequences are stored and retrieved by means of a fairly standard hash
+table algorithm called the method of ``coalescing lists'' (cf.\ Algorithm 6.4C
+in {\sl The Art of Computer Programming\/}). Once a control sequence enters the
+table, it is never removed, because there are complicated situations
+involving \.{\\gdef} where the removal of a control sequence at the end of
+a group would be a mistake preventable only by the introduction of a
+complicated reference-count mechanism.
+
+The actual sequence of letters forming a control sequence identifier is
+stored in the |str_pool| array together with all the other strings. An
+auxiliary array |hash| consists of items with two halfword fields per
+word. The first of these, called |next(p)|, points to the next identifier
+belonging to the same coalesced list as the identifier corresponding to~|p|;
+and the other, called |text(p)|, points to the |str_start| entry for
+|p|'s identifier. If position~|p| of the hash table is empty, we have
+|text(p)=0|; if position |p| is either empty or the end of a coalesced
+hash list, we have |next(p)=0|. An auxiliary pointer variable called
+|hash_used| is maintained in such a way that all locations |p>=hash_used|
+are nonempty. The global variable |cs_count| tells how many multiletter
+control sequences have been defined, if statistics are being kept.
+
+A global boolean variable called |no_new_control_sequence| is set to
+|true| during the time that new hash table entries are forbidden.
+
+@d next(#) == hash[#].lh {link for coalesced lists}
+@d text(#) == hash[#].rh {string number for control sequence name}
+@d hash_is_full == (hash_used=hash_base) {test if all positions are occupied}
+@d font_id_text(#) == text(font_id_base+#) {a frozen font identifier's name}
+@d ocp_id_text(#) == text(ocp_id_base+#) {a frozen ocp identifier's name}
+@d ocp_list_id_text(#) == text(ocp_list_id_base+#)
+ {a frozen ocp list identifier's name}
+
+@<Glob...@>=
+@!hash: array[hash_base..undefined_control_sequence-1] of two_halves;
+ {the hash table}
+@!hash_used:pointer; {allocation pointer for |hash|}
+@!no_new_control_sequence:boolean; {are new identifiers legal?}
+@!cs_count:integer; {total number of known identifiers}
+
+@ Primitive support needs a few extra variables and definitions
+
+@d prim_size=2100 {maximum number of primitives }
+@d prim_prime=1777 {about 85\pct! of |primitive_size|}
+@d prim_base=1
+@d prim_next(#) == prim[#].lh {link for coalesced lists}
+@d prim_text(#) == prim[#].rh {string number for control sequence name}
+@d prim_is_full == (prim_used=prim_base) {test if all positions are occupied}
+@d prim_eq_level_field(#)==#.hh.b1
+@d prim_eq_type_field(#)==#.hh.b0
+@d prim_equiv_field(#)==#.hh.rh
+@d prim_eq_level(#)==prim_eq_level_field(prim_eqtb[#]) {level of definition}
+@d prim_eq_type(#)==prim_eq_type_field(prim_eqtb[#]) {command code for equivalent}
+@d prim_equiv(#)==prim_equiv_field(prim_eqtb[#]) {equivalent value}
+@d undefined_primitive=0
+
+@<Glob...@>=
+@!prim: array [0..prim_size] of two_halves; {the primitives table}
+@!prim_used:pointer; {allocation pointer for |prim|}
+@!prim_eqtb:array[0..prim_size] of memory_word;
+
+@ The extra set of functions make sure we can query the
+primitive meanings of thing s from C code
+
+@p
+function get_char_cat_code(c:integer):quarterword;
+begin
+ if local_catcode_table then
+ get_char_cat_code:=get_cat_code(line_catcode_table,c)
+ else
+ get_char_cat_code:=get_cat_code(cat_code_table,c)
+end;
+function get_prim_eq_level(p:integer):quarterword;
+begin
+ get_prim_eq_level := prim_eq_level(p);
+end;
+function get_prim_eq_type(p:integer):quarterword;
+begin
+ get_prim_eq_type := prim_eq_type(p);
+end;
+function get_prim_equiv(p:integer):halfword;
+begin
+ get_prim_equiv := prim_equiv(p);
+end;
+function get_eq_type(p:integer):quarterword;
+begin
+ get_eq_type := eq_type(p);
+end;
+function get_eq_level(p:integer):quarterword;
+begin
+ get_eq_level := eq_level(p);
+end;
+function is_undefined_cs(cs:integer):boolean;
+begin
+ is_undefined_cs := (cs=undefined_cs);
+end;
+function get_equiv(p:integer):halfword;
+begin
+ get_equiv := equiv(p);
+end;
+function get_cs_text(cs:integer):str_number;
+begin if cs<hash_base then
+ if cs<null_cs then get_cs_text := cs-active_base
+ else get_cs_text := "\csname\endcsname"
+ else if (text(cs)<0)or(text(cs)>=str_ptr) then get_cs_text := ""
+ else get_cs_text := text(cs);
+end;
+function get_max_command:integer;
+begin
+ get_max_command := max_command;
+end;
+function get_count_base:halfword;
+begin
+ get_count_base := count_base;
+end;
+function get_attribute_base:halfword;
+begin
+ get_attribute_base := attribute_base;
+end;
+function get_scaled_base:halfword;
+begin
+ get_scaled_base := scaled_base;
+end;
+function get_int_base:halfword;
+begin
+ get_int_base := int_base;
+end;
+function get_toks_base:halfword;
+begin
+ get_toks_base := toks_base;
+end;
+function get_every_eof:halfword;
+begin
+ get_every_eof := every_eof;
+end;
+function get_suppress_fontnotfound_error:boolean;
+begin
+ get_suppress_fontnotfound_error := suppress_fontnotfound_error;
+end;
+function get_pdf_image_resolution:integer;
+begin
+ get_pdf_image_resolution := pdf_image_resolution;
+end;
+function get_pdf_minor_version:integer;
+begin
+ get_pdf_minor_version := pdf_minor_version;
+end;
+function get_pdf_inclusion_errorlevel:integer;
+begin
+ get_pdf_inclusion_errorlevel := pdf_inclusion_errorlevel;
+end;
+
+@ @<Set init...@>=
+no_new_control_sequence:=true; {new identifiers are usually forbidden}
+prim_next(0):=0; prim_text(0):=0;
+for k:=1 to prim_size do prim[k]:=prim[0];
+prim_eq_level(0) := level_zero;
+prim_eq_type(0) := undefined_cs;
+prim_equiv(0) := null;
+for k:=1 to prim_size do prim_eqtb[k]:=prim_eqtb[0];
+next(hash_base):=0; text(hash_base):=0;
+for k:=hash_base+1 to undefined_control_sequence-1 do hash[k]:=hash[hash_base];
+
+@ @<Initialize table entries...@>=
+prim_used:=prim_size; {nothing is used}
+hash_used:=frozen_control_sequence; {nothing is used}
+cs_count:=0;
+eq_type(frozen_dont_expand):=dont_expand;
+text(frozen_dont_expand):="notexpanded:";
+@.notexpanded:@>
+
+eq_type(frozen_primitive):=ignore_spaces;
+equiv(frozen_primitive):=1;
+eq_level(frozen_primitive):=level_one;
+text(frozen_primitive):="primitive";
+
+@ Here is the subroutine that searches the hash table for an identifier
+that matches a given string of length |l>1| appearing in |buffer[j..
+(j+l-1)]|. If the identifier is found, the corresponding hash table address
+is returned. Otherwise, if the global variable |no_new_control_sequence|
+is |true|, the dummy address |undefined_control_sequence| is returned.
+Otherwise the identifier is inserted into the hash table and its location
+is returned.
+
+@p function id_lookup(@!j,@!l:integer):pointer; {search the hash table}
+label found; {go here if you found it}
+var h:integer; {hash code}
+@!d:integer; {number of characters in incomplete current string}
+@!p:pointer; {index in |hash| array}
+@!k:pointer; {index in |buffer| array}
+begin @<Compute the hash code |h|@>;
+p:=h+hash_base; {we start searching here; note that |0<=h<hash_prime|}
+loop@+begin if text(p)>0 then if length(text(p))=l then
+ if str_eq_buf(text(p),j) then goto found;
+ if next(p)=0 then
+ begin if no_new_control_sequence then
+ p:=undefined_control_sequence
+ else @<Insert a new control sequence after |p|, then make
+ |p| point to it@>;
+ goto found;
+ end;
+ p:=next(p);
+ end;
+found: id_lookup:=p;
+end;
+
+@ @<Insert a new control...@>=
+begin if text(p)>0 then
+ begin repeat if hash_is_full then overflow("hash size",hash_size);
+@:TeX capacity exceeded hash size}{\quad hash size@>
+ decr(hash_used);
+ until text(hash_used)=0; {search for an empty location in |hash|}
+ next(p):=hash_used; p:=hash_used;
+ end;
+str_room(l); d:=cur_length;
+while pool_ptr>str_start_macro(str_ptr) do
+ begin decr(pool_ptr); str_pool[pool_ptr+l]:=str_pool[pool_ptr];
+ end; {move current string up to make room for another}
+for k:=j to j+l-1 do append_char(buffer[k]);
+text(p):=make_string; pool_ptr:=pool_ptr+d;
+@!stat incr(cs_count);@+tats@;@/
+end
+
+@ The value of |hash_prime| should be roughly 85\pct! of |hash_size|, and it
+should be a prime number. The theory of hashing tells us to expect fewer
+than two table probes, on the average, when the search is successful.
+[See J.~S. Vitter, {\sl Journal of the ACM\/ \bf30} (1983), 231--258.]
+@^Vitter, Jeffrey Scott@>
+
+@<Compute the hash code |h|@>=
+h:=buffer[j];
+for k:=j+1 to j+l-1 do
+ begin h:=h+h+buffer[k];
+ while h>=hash_prime do h:=h-hash_prime;
+ end
+
+@ Here is the subroutine that searches the primitive table for an identifier
+
+@p function prim_lookup(@!s:str_number):pointer; {search the primitives table}
+label found; {go here if you found it}
+var h:integer; {hash code}
+@!p:pointer; {index in |hash| array}
+@!k:pointer; {index in string pool}
+@!the_hash_prime:halfword;
+@!j,@!l:integer;
+begin
+the_hash_prime:= prim_prime;
+if s<string_offset then begin
+ p := s;
+ if (p<0) or (get_prim_eq_level(p)<>level_one) then
+ p := undefined_primitive;
+end
+else begin
+ j:=str_start_macro(s);
+ if s = str_ptr then l := cur_length else l := length(s);
+ @<Compute the string hash code |h|@>;
+ p:=h+prim_base; {we start searching here; note that |0<=h<hash_prime|}
+ loop@+begin if prim_text(p)>0 then if length(prim_text(p))=l then
+ if str_eq_str(prim_text(p),s) then goto found;
+ if prim_next(p)=0 then
+ begin if no_new_control_sequence then
+ p:=undefined_primitive
+ else @<Insert a new primitive after |p|, then make
+ |p| point to it@>;
+ goto found;
+ end;
+ p:=prim_next(p);
+ end;
+ end;
+found: prim_lookup:=p;
+end;
+
+function string_lookup(@!s:str_number):pointer; {search the primitives table}
+label found; {go here if you found it}
+var h:integer; {hash code}
+@!p:pointer; {index in |hash| array}
+@!k:pointer; {index in string pool}
+@!the_hash_prime: halfword;
+@!j,@!l:integer;
+begin
+the_hash_prime := hash_prime;
+if s<string_offset then begin
+ p := s;
+ if (p<0) or (eq_level(p)<>level_one) then
+ p := undefined_cs;
+end
+else begin
+ j:=str_start_macro(s);
+ if s = str_ptr then l := cur_length else l := length(s);
+ @<Compute the string hash code |h|@>;
+ p:=h+hash_base; {we start searching here; note that |0<=h<hash_prime|}
+ loop@+begin if text(p)>0 then if length(text(p))=l then
+ if str_eq_str(text(p),s) then goto found;
+ if next(p)=0 then
+ begin
+ p:=undefined_cs ;
+ goto found;
+ end;
+ p:=next(p);
+ end;
+ end;
+found: string_lookup:=p;
+end;
+
+function is_primitive(csname:str_number):boolean;
+ var n,m:integer;
+begin
+ m := prim_lookup(csname);
+ n := string_lookup(csname);
+ is_primitive :=((n<>undefined_cs) and
+ (m<>undefined_primitive) and
+ (eq_type(n)=get_prim_eq_type(m)) and
+ (equiv(n)=get_prim_equiv(m)));
+end;
+
+@ @<Insert a new primitive...@>=
+begin if prim_text(p)>0 then
+ begin repeat if prim_is_full then overflow("primitive size",prim_size);
+@:TeX capacity exceeded primitive size}{\quad primitive size@>
+ decr(prim_used);
+ until prim_text(prim_used)=0; {search for an empty location in |prim|}
+ prim_next(p):=prim_used; p:=prim_used;
+ end;
+prim_text(p):=s;
+end
+
+@ The value of |prim_prime| should be roughly 85\pct! of
+|prim_size|, and it should be a prime number.
+
+@<Compute the string hash code |h|@>=
+h:=str_pool[j];
+for k:=j+1 to j+l-1 do
+ begin h:=h+h+str_pool[k];
+ while h>=the_hash_prime do h:=h-the_hash_prime;
+ end
+
+
+@ The procedure |print_cs| prints the name of a control sequence, given
+a pointer to its address in |eqtb|. A space is printed after the name
+unless it is a single nonletter or an active character. This procedure
+might be invoked with invalid data, so it is ``extra robust.'' The
+individual characters must be printed one at a time using |print|, since
+they may be unprintable.
+
+@d single_letter(#)==(length(#)=1)or
+ ((length(#)=4)and(str_pool[str_start_macro(#)]>=@"F0))or
+ ((length(#)=3)and(str_pool[str_start_macro(#)]>=@"E0))or
+ ((length(#)=2)and(str_pool[str_start_macro(#)]>=@"C0))
+
+@<Basic printing...@>=
+procedure print_cs(@!p:integer); {prints a purported control sequence}
+begin if p<hash_base then {single character}
+ if p=null_cs then
+ begin print_esc("csname"); print_esc("endcsname");
+ end
+ else if p<active_base then print_esc("IMPOSSIBLE.")
+@.IMPOSSIBLE@>
+ else print(p-active_base)
+else if p>=undefined_control_sequence then print_esc("IMPOSSIBLE.")
+else if (text(p)<0)or(text(p)>=str_ptr) then print_esc("NONEXISTENT.")
+@.NONEXISTENT@>
+else begin
+ print_esc(text(p));
+ if single_letter(text(p)) then begin
+ if get_cat_code(cat_code_table,pool_to_unichar(str_start_macro(text(p))))=letter then
+ print_char(" ")
+ else
+ do_nothing;
+ end
+ else
+ print_char(" ");
+ end;
+end;
+
+@ Here is a similar procedure; it avoids the error checks, and it never
+prints a space after the control sequence.
+
+@<Basic printing procedures@>=
+procedure sprint_cs(@!p:pointer); {prints a control sequence}
+begin if p<hash_base then
+ if p<null_cs then print(p-active_base)
+ else begin print_esc("csname"); print_esc("endcsname");
+ end
+else print_esc(text(p));
+end;
+
+@ We need to put \TeX's ``primitive'' control sequences into the hash
+table, together with their command code (which will be the |eq_type|)
+and an operand (which will be the |equiv|). The |primitive| procedure
+does this, in a way that no \TeX\ user can. The global value |cur_val|
+contains the new |eqtb| pointer after |primitive| has acted.
+
+@p @!init procedure primitive(@!ss:str_number;@!c:quarterword;@!o:halfword);
+var k:pool_pointer; {index into |str_pool|}
+@!s:str_number; {actual |str_number| used }
+@!j:0..buf_size; {index into |buffer|}
+@!l:small_number; {length of the string}
+@!prim_val:integer; {needed to fill |prim_eqtb|}
+begin if ss<number_chars then begin
+ if ss>127 then confusion("prim"); { should be ASCII }
+ append_char(ss);
+ s:=make_string;
+ end
+else
+ s:=ss;
+k:=str_start_macro(s); l:=str_start_macro(s+1)-k;
+ {we will move |s| into the (possibly non-empty) |buffer|}
+if first+l>buf_size+1 then
+ check_buffer_overflow(first+l);
+@:TeX capacity exceeded buffer size}{\quad buffer size@>
+for j:=0 to l-1 do buffer[first+j]:=so(str_pool[k+j]);
+cur_val:=id_lookup(first,l); {|no_new_control_sequence| is |false|}
+flush_string; text(cur_val):=s; {we don't want to have the string twice}
+prim_val:=prim_lookup(s);
+eq_level(cur_val):=level_one; eq_type(cur_val):=c; equiv(cur_val):=o;
+prim_eq_level(prim_val) := level_one;
+prim_eq_type(prim_val) := c;
+prim_equiv(prim_val) := o;
+end;
+tini
+
+@ Many of \TeX's primitives need no |equiv|, since they are identifiable
+by their |eq_type| alone. These primitives are loaded into the hash table
+as follows:
+
+@<Put each of \TeX's primitives into the hash table@>=
+primitive(" ",ex_space,0);@/
+@!@:Single-character primitives /}{\quad\.{\\\ }@>
+primitive("/",ital_corr,0);@/
+@!@:Single-character primitives /}{\quad\.{\\/}@>
+primitive("accent",accent,0);@/
+@!@:accent_}{\.{\\accent} primitive@>
+primitive("advance",advance,0);@/
+@!@:advance_}{\.{\\advance} primitive@>
+primitive("afterassignment",after_assignment,0);@/
+@!@:after_assignment_}{\.{\\afterassignment} primitive@>
+primitive("aftergroup",after_group,0);@/
+@!@:after_group_}{\.{\\aftergroup} primitive@>
+primitive("begingroup",begin_group,0);@/
+@!@:begin_group_}{\.{\\begingroup} primitive@>
+primitive("char",char_num,0);@/
+@!@:char_}{\.{\\char} primitive@>
+primitive("csname",cs_name,0);@/
+@!@:cs_name_}{\.{\\csname} primitive@>
+primitive("delimiter",delim_num,0);@/
+@!@:delimiter_}{\.{\\delimiter} primitive@>
+primitive("odelimiter",delim_num,1);@/
+@!@:odelimiter_}{\.{\\odelimiter} primitive@>
+primitive("divide",divide,0);@/
+@!@:divide_}{\.{\\divide} primitive@>
+primitive("endcsname",end_cs_name,0);@/
+@!@:end_cs_name_}{\.{\\endcsname} primitive@>
+primitive("endgroup",end_group,0);
+@!@:end_group_}{\.{\\endgroup} primitive@>
+text(frozen_end_group):="endgroup"; eqtb[frozen_end_group]:=eqtb[cur_val];@/
+primitive("expandafter",expand_after,0);@/
+@!@:expand_after_}{\.{\\expandafter} primitive@>
+primitive("font",def_font,0);@/
+@!@:font_}{\.{\\font} primitive@>
+primitive("letterspacefont",letterspace_font,0);@/
+@!@:letterspace_font_}{\.{\\letterspacefont} primitive@>
+primitive("fontdimen",assign_font_dimen,0);@/
+@!@:font_dimen_}{\.{\\fontdimen} primitive@>
+primitive("halign",halign,0);@/
+@!@:halign_}{\.{\\halign} primitive@>
+primitive("hrule",hrule,0);@/
+@!@:hrule_}{\.{\\hrule} primitive@>
+primitive("ignorespaces",ignore_spaces,0);@/
+@!@:ignore_spaces_}{\.{\\ignorespaces} primitive@>
+primitive("insert",insert,0);@/
+@!@:insert_}{\.{\\insert} primitive@>
+primitive("leftghost",char_ghost,0);@/
+@!@:leftghost_}{\.{\\leftghost} primitive@>
+primitive("mark",mark,0);@/
+@!@:mark_}{\.{\\mark} primitive@>
+primitive("mathaccent",math_accent,0);@/
+@!@:math_accent_}{\.{\\mathaccent} primitive@>
+primitive("mathchar",math_char_num,0);@/
+@!@:math_char_}{\.{\\mathchar} primitive@>
+primitive("omathaccent",math_accent,1);@/
+@!@:math_accent_}{\.{\\omathaccent} primitive@>
+primitive("omathchar",math_char_num,1);@/
+@!@:math_char_}{\.{\\omathchar} primitive@>
+primitive("mathchoice",math_choice,0);@/
+@!@:math_choice_}{\.{\\mathchoice} primitive@>
+primitive("multiply",multiply,0);@/
+@!@:multiply_}{\.{\\multiply} primitive@>
+primitive("noalign",no_align,0);@/
+@!@:no_align_}{\.{\\noalign} primitive@>
+primitive("noboundary",no_boundary,0);@/
+@!@:no_boundary_}{\.{\\noboundary} primitive@>
+primitive("noexpand",no_expand,0);@/
+@!@:no_expand_}{\.{\\noexpand} primitive@>
+primitive("primitive",no_expand,1);@/
+@!@:primitive_}{\.{\\primitive} primitive@>
+primitive("pdfprimitive",no_expand,1);@/
+@!@:pdfprimitive_}{\.{\\pdfprimitive} primitive@>
+primitive("nonscript",non_script,0);@/
+@!@:non_script_}{\.{\\nonscript} primitive@>
+primitive("omit",omit,0);@/
+@!@:omit_}{\.{\\omit} primitive@>
+primitive("parshape",set_shape,par_shape_loc);@/
+@!@:par_shape_}{\.{\\parshape} primitive@>
+primitive("penalty",break_penalty,0);@/
+@!@:penalty_}{\.{\\penalty} primitive@>
+primitive("prevgraf",set_prev_graf,0);@/
+@!@:prev_graf_}{\.{\\prevgraf} primitive@>
+primitive("radical",radical,0);@/
+@!@:radical_}{\.{\\radical} primitive@>
+primitive("oradical",radical,1);@/
+@!@:radical_}{\.{\\oradical} primitive@>
+primitive("read",read_to_cs,0);@/
+@!@:read_}{\.{\\read} primitive@>
+primitive("relax",relax,too_big_char);
+@!@:relax_}{\.{\\relax} primitive@>
+text(frozen_relax):="relax"; eqtb[frozen_relax]:=eqtb[cur_val];@/
+primitive("rightghost",char_ghost,1);@/
+@!@:rightghost_}{\.{\\rightghost} primitive@>
+primitive("setbox",set_box,0);@/
+@!@:set_box_}{\.{\\setbox} primitive@>
+primitive("the",the,0);@/
+@!@:the_}{\.{\\the} primitive@>
+primitive("toks",toks_register,0);@/
+@!@:toks_}{\.{\\toks} primitive@>
+primitive("vadjust",vadjust,0);@/
+@!@:vadjust_}{\.{\\vadjust} primitive@>
+primitive("valign",valign,0);@/
+@!@:valign_}{\.{\\valign} primitive@>
+primitive("vcenter",vcenter,0);@/
+@!@:vcenter_}{\.{\\vcenter} primitive@>
+primitive("vrule",vrule,0);@/
+@!@:vrule_}{\.{\\vrule} primitive@>
+
+@ Each primitive has a corresponding inverse, so that it is possible to
+display the cryptic numeric contents of |eqtb| in symbolic form.
+Every call of |primitive| in this program is therefore accompanied by some
+straightforward code that forms part of the |print_cmd_chr| routine
+below.
+
+@<Cases of |print_cmd_chr|...@>=
+accent: print_esc("accent");
+advance: print_esc("advance");
+after_assignment: print_esc("afterassignment");
+after_group: print_esc("aftergroup");
+assign_font_dimen: print_esc("fontdimen");
+begin_group: print_esc("begingroup");
+break_penalty: print_esc("penalty");
+char_num: print_esc("char");
+char_ghost: if cur_chr=0 then print_esc("leftghost")
+ else print_esc("rightghost");
+cs_name: print_esc("csname");
+def_font: print_esc("font");
+letterspace_font: print_esc("letterspacefont");
+delim_num: if chr_code=0 then print_esc("delimiter") else print_esc("odelimiter") ;
+divide: print_esc("divide");
+end_cs_name: print_esc("endcsname");
+end_group: print_esc("endgroup");
+ex_space: print_esc(" ");
+expand_after: if chr_code=0 then print_esc("expandafter")
+ @<Cases of |expandafter| for |print_cmd_chr|@>;
+halign: print_esc("halign");
+hrule: print_esc("hrule");
+ignore_spaces: if chr_code=0 then print_esc("ignorespaces") else print_esc("primitive");
+insert: print_esc("insert");
+ital_corr: print_esc("/");
+mark: begin
+ if chr_code=0 then print_esc("mark")
+ else if chr_code=1 then print_esc("clearmarks")
+ else print_esc("marks");
+ end;
+math_accent: if chr_code=0 then print_esc("mathaccent") else print_esc("omathaccent");
+math_char_num: if chr_code=0 then print_esc("mathchar") else print_esc("omathchar");
+math_choice: print_esc("mathchoice");
+multiply: print_esc("multiply");
+no_align: print_esc("noalign");
+no_boundary:print_esc("noboundary");
+no_expand: if chr_code=0 then print_esc("noexpand")
+ else print_esc("primitive");
+non_script: print_esc("nonscript");
+omit: print_esc("omit");
+radical: if chr_code=0 then print_esc("radical") else print_esc("oradical");
+read_to_cs: if chr_code=0 then print_esc("read")
+ @<Cases of |read| for |print_cmd_chr|@>;
+relax: print_esc("relax");
+set_box: print_esc("setbox");
+set_prev_graf: print_esc("prevgraf");
+set_shape: case chr_code of
+ par_shape_loc: print_esc("parshape");
+ @<Cases of |set_shape| for |print_cmd_chr|@>@;@/
+ end; {there are no other cases}
+the: if chr_code=0 then print_esc("the")
+ @<Cases of |the| for |print_cmd_chr|@>;
+toks_register: print_esc("toks");
+vadjust: print_esc("vadjust");
+valign: print_esc("valign");
+vcenter: print_esc("vcenter");
+vrule: print_esc("vrule");
+
+@ We will deal with the other primitives later, at some point in the program
+where their |eq_type| and |equiv| values are more meaningful. For example,
+the primitives for math mode will be loaded when we consider the routines
+that deal with formulas. It is easy to find where each particular
+primitive was treated by looking in the index at the end; for example, the
+section where |"radical"| entered |eqtb| is listed under `\.{\\radical}
+primitive'. (Primitives consisting of a single nonalphabetic character,
+@!like `\.{\\/}', are listed under `Single-character primitives'.)
+@!@^Single-character primitives@>
+
+
+@* \[19] Saving and restoring equivalents.
+The nested structure provided by `$\.{\char'173}\ldots\.{\char'175}$' groups
+in \TeX\ means that |eqtb| entries valid in outer groups should be saved
+and restored later if they are overridden inside the braces. When a new |eqtb|
+value is being assigned, the program therefore checks to see if the previous
+entry belongs to an outer level. In such a case, the old value is placed
+on the |save_stack| just before the new value enters |eqtb|. At the
+end of a grouping level, i.e., when the right brace is sensed, the
+|save_stack| is used to restore the outer values, and the inner ones are
+destroyed.
+
+Entries on the |save_stack| are of type |memory_word|. The top item on
+this stack is |save_stack[p]|, where |p=save_ptr-1|; it contains three
+fields called |save_type|, |save_level|, and |save_index|, and it is
+interpreted in one of four ways:
+
+\yskip\hangg 1) If |save_type(p)=restore_old_value|, then
+|save_index(p)| is a location in |eqtb| whose current value should
+be destroyed at the end of the current group and replaced by |save_stack[p-1]|.
+Furthermore if |save_index(p)>=int_base|, then |save_level(p)|
+should replace the corresponding entry in |xeq_level|.
+
+\yskip\hangg 2) If |save_type(p)=restore_zero|, then |save_index(p)|
+is a location in |eqtb| whose current value should be destroyed at the end
+of the current group, when it should be
+replaced by the current value of |eqtb[undefined_control_sequence]|.
+
+\yskip\hangg 3) If |save_type(p)=insert_token|, then |save_index(p)|
+is a token that should be inserted into \TeX's input when the current
+group ends.
+
+\yskip\hangg 4) If |save_type(p)=level_boundary|, then |save_level(p)|
+is a code explaining what kind of group we were previously in, and
+|save_index(p)| points to the level boundary word at the bottom of
+the entries for that group.
+Furthermore, in extended \eTeX\ mode, |save_stack[p-1]| contains the
+source line number at which the current level of grouping was entered.
+
+@d save_type(#)==save_stack[#].hh.b0 {classifies a |save_stack| entry}
+@d save_level(#)==save_stack[#].hh.b1
+ {saved level for regions 5 and 6, or group code}
+@d save_index(#)==save_stack[#].hh.rh
+ {|eqtb| location or |save_stack| location}
+@d restore_old_value=0 {|save_type| when a value should be restored later}
+@d restore_zero=1 {|save_type| when an undefined entry should be restored}
+@d insert_token=2 {|save_type| when a token is being saved for later use}
+@d level_boundary=3 {|save_type| corresponding to beginning of group}
+
+@p@t\4@>@<Declare \eTeX\ procedures for tracing and input@>
+
+@ Here are the group codes that are used to discriminate between different
+kinds of groups. They allow \TeX\ to decide what special actions, if any,
+should be performed when a group ends.
+\def\grp{\.{\char'173...\char'175}}
+
+Some groups are not supposed to be ended by right braces. For example,
+the `\.\$' that begins a math formula causes a |math_shift_group| to
+be started, and this should be terminated by a matching `\.\$'. Similarly,
+a group that starts with \.{\\left} should end with \.{\\right}, and
+one that starts with \.{\\begingroup} should end with \.{\\endgroup}.
+
+@d bottom_level=0 {group code for the outside world}
+@d simple_group=1 {group code for local structure only}
+@d hbox_group=2 {code for `\.{\\hbox}\grp'}
+@d adjusted_hbox_group=3 {code for `\.{\\hbox}\grp' in vertical mode}
+@d vbox_group=4 {code for `\.{\\vbox}\grp'}
+@d vtop_group=5 {code for `\.{\\vtop}\grp'}
+@d align_group=6 {code for `\.{\\halign}\grp', `\.{\\valign}\grp'}
+@d no_align_group=7 {code for `\.{\\noalign}\grp'}
+@d output_group=8 {code for output routine}
+@d math_group=9 {code for, e.g, `\.{\char'136}\grp'}
+@d disc_group=10 {code for `\.{\\discretionary}\grp\grp\grp'}
+@d insert_group=11 {code for `\.{\\insert}\grp', `\.{\\vadjust}\grp'}
+@d vcenter_group=12 {code for `\.{\\vcenter}\grp'}
+@d math_choice_group=13 {code for `\.{\\mathchoice}\grp\grp\grp\grp'}
+@d semi_simple_group=14 {code for `\.{\\begingroup...\\endgroup}'}
+@d math_shift_group=15 {code for `\.{\$...\$}'}
+@d math_left_group=16 {code for `\.{\\left...\\right}'}
+@d local_box_group=17 {code for `\.{\\localleftbox...\\localrightbox}'}
+@d max_group_code=17
+@d split_off_group=18 {box code for the top part of a \.{\\vsplit}}
+@d split_keep_group=19 {box code for the bottom part of a \.{\\vsplit}}
+@d preamble_group=20 {box code for the preamble processing in an alignment}
+@d align_set_group=21 {box code for the final item pass in an alignment}
+@d fin_row_group=22 {box code for a provisory line in an alignment}
+
+@<Types...@>=
+@!group_code=0..max_group_code; {|save_level| for a level boundary}
+
+@ The global variable |cur_group| keeps track of what sort of group we are
+currently in. Another global variable, |cur_boundary|, points to the
+topmost |level_boundary| word. And |cur_level| is the current depth of
+nesting. The routines are designed to preserve the condition that no entry
+in the |save_stack| or in |eqtb| ever has a level greater than |cur_level|.
+
+@ @<Glob...@>=
+@!save_stack : array[0..save_size] of memory_word;
+@!save_ptr : 0..save_size; {first unused entry on |save_stack|}
+@!max_save_stack:0..save_size; {maximum usage of save stack}
+@!cur_level: quarterword; {current nesting level for groups}
+@!cur_group: group_code; {current group type}
+@!cur_boundary: 0..save_size; {where the current level begins}
+
+@ At this time it might be a good idea for the reader to review the introduction
+to |eqtb| that was given above just before the long lists of parameter names.
+Recall that the ``outer level'' of the program is |level_one|, since
+undefined control sequences are assumed to be ``defined'' at |level_zero|.
+
+@<Set init...@>=
+save_ptr:=0; cur_level:=level_one; cur_group:=bottom_level; cur_boundary:=0;
+max_save_stack:=0;
+
+@ The following macro is used to test if there is room for up to eight more
+entries on |save_stack|. By making a conservative test like this, we can
+get by with testing for overflow in only a few places.
+
+@d check_full_save_stack==if save_ptr>max_save_stack then
+ begin max_save_stack:=save_ptr;
+ if max_save_stack>save_size-8 then overflow("save size",save_size);
+@:TeX capacity exceeded save size}{\quad save size@>
+ end
+
+@ Procedure |new_save_level| is called when a group begins. The
+argument is a group identification code like `|hbox_group|'. After
+calling this routine, it is safe to put six more entries on |save_stack|.
+
+In some cases integer-valued items are placed onto the
+|save_stack| just below a |level_boundary| word, because this is a
+convenient place to keep information that is supposed to ``pop up'' just
+when the group has finished.
+For example, when `\.{\\hbox to 100pt}\grp' is being treated, the 100pt
+dimension is stored on |save_stack| just before |new_save_level| is
+called.
+
+We use the notation |saved(k)| to stand for an integer item that
+appears in location |save_ptr+k| of the save stack.
+
+@d saved(#)==save_stack[save_ptr+#].int
+
+@p procedure new_save_level(@!c:group_code); {begin a new level of grouping}
+begin check_full_save_stack;
+saved(0):=line; incr(save_ptr);
+save_type(save_ptr):=level_boundary; save_level(save_ptr):=cur_group;
+save_index(save_ptr):=cur_boundary;
+if cur_level=max_quarterword then overflow("grouping levels",
+@:TeX capacity exceeded grouping levels}{\quad grouping levels@>
+ max_quarterword-min_quarterword);
+ {quit if |(cur_level+1)| is too big to be stored in |eqtb|}
+cur_boundary:=save_ptr; cur_group:=c;
+@!stat if tracing_groups>0 then group_trace(false);@+tats@;@/
+incr(cur_level); incr(save_ptr);
+end;
+
+@ Just before an entry of |eqtb| is changed, the following procedure should
+be called to update the other data structures properly. It is important
+to keep in mind that reference counts in |mem| include references from
+within |save_stack|, so these counts must be handled carefully.
+@^reference counts@>
+
+@p procedure eq_destroy(@!w:memory_word); {gets ready to forget |w|}
+var q:pointer; {|equiv| field of |w|}
+begin case eq_type_field(w) of
+call,long_call,outer_call,long_outer_call: delete_token_ref(equiv_field(w));
+glue_ref: delete_glue_ref(equiv_field(w));
+shape_ref: begin q:=equiv_field(w); {we need to free a \.{\\parshape} block}
+ if q<>null then flush_node(q);
+ end; {such a block is |2n+1| words long, where |n=vinfo(q)|}
+box_ref: flush_node_list(equiv_field(w));
+othercases do_nothing
+endcases;
+end;
+
+@ To save a value of |eqtb[p]| that was established at level |l|, we
+can use the following subroutine.
+
+@p procedure eq_save(@!p:pointer;@!l:quarterword); {saves |eqtb[p]|}
+begin check_full_save_stack;
+if l=level_zero then save_type(save_ptr):=restore_zero
+else begin save_stack[save_ptr]:=eqtb[p]; incr(save_ptr);
+ save_type(save_ptr):=restore_old_value;
+ end;
+save_level(save_ptr):=l; save_index(save_ptr):=p; incr(save_ptr);
+end;
+
+@ The procedure |eq_define| defines an |eqtb| entry having specified
+|eq_type| and |equiv| fields, and saves the former value if appropriate.
+This procedure is used only for entries in the first four regions of |eqtb|,
+i.e., only for entries that have |eq_type| and |equiv| fields.
+After calling this routine, it is safe to put four more entries on
+|save_stack|, provided that there was room for four more entries before
+the call, since |eq_save| makes the necessary test.
+
+@d assign_trace(#)==@!stat if tracing_assigns>0 then restore_trace(#);
+ tats
+
+@p procedure eq_define(@!p:pointer;@!t:quarterword;@!e:halfword);
+ {new data for |eqtb|}
+label exit;
+begin if (eq_type(p)=t)and(equiv(p)=e) then
+ begin assign_trace(p,"reassigning")@;@/
+ eq_destroy(eqtb[p]); return;
+ end;
+assign_trace(p,"changing")@;@/
+if eq_level(p)=cur_level then eq_destroy(eqtb[p])
+else if cur_level>level_one then eq_save(p,eq_level(p));
+eq_level(p):=cur_level; eq_type(p):=t; equiv(p):=e;
+assign_trace(p,"into")@;@/
+exit:end;
+
+@ The counterpart of |eq_define| for the remaining (fullword) positions in
+|eqtb| is called |eq_word_define|. Since |xeq_level[p]>=level_one| for all
+|p|, a `|restore_zero|' will never be used in this case.
+
+@p procedure eq_word_define(@!p:pointer;@!w:integer);
+label exit;
+begin if eqtb[p].int=w then
+ begin assign_trace(p,"reassigning")@;@/
+ return;
+ end;
+assign_trace(p,"changing")@;@/
+if xeq_level[p]<>cur_level then
+ begin eq_save(p,xeq_level[p]); xeq_level[p]:=cur_level;
+ end;
+eqtb[p].int:=w;
+assign_trace(p,"into")@;@/
+exit:end;
+
+@ The |eq_define| and |eq_word_define| routines take care of local definitions.
+@^global definitions@>
+Global definitions are done in almost the same way, but there is no need
+to save old values, and the new value is associated with |level_one|.
+
+@p procedure geq_define(@!p:pointer;@!t:quarterword;@!e:halfword);
+ {global |eq_define|}
+begin assign_trace(p,"globally changing")@;@/
+begin eq_destroy(eqtb[p]);
+eq_level(p):=level_one; eq_type(p):=t; equiv(p):=e;
+end;
+assign_trace(p,"into")@;@/
+end;
+@#
+procedure geq_word_define(@!p:pointer;@!w:integer); {global |eq_word_define|}
+begin assign_trace(p,"globally changing")@;@/
+begin eqtb[p].int:=w; xeq_level[p]:=level_one;
+end;
+assign_trace(p,"into")@;@/
+end;
+
+@ Subroutine |save_for_after| puts a token on the stack for save-keeping.
+
+@p procedure save_for_after(@!t:halfword);
+begin if cur_level>level_one then
+ begin check_full_save_stack;
+ save_type(save_ptr):=insert_token; save_level(save_ptr):=level_zero;
+ save_index(save_ptr):=t; incr(save_ptr);
+ end;
+end;
+
+@ The |unsave| routine goes the other way, taking items off of |save_stack|.
+This routine takes care of restoration when a level ends; everything
+belonging to the topmost group is cleared off of the save stack.
+
+@p
+procedure@?back_input; forward; @t\2@>
+procedure unsave; {pops the top level off the save stack}
+label done;
+var p:pointer; {position to be restored}
+@!l:quarterword; {saved level, if in fullword regions of |eqtb|}
+@!t:halfword; {saved value of |cur_tok|}
+@!a:boolean; {have we already processed an \.{\\aftergroup} ?}
+begin a:=false; l:=level_one; {just in case}
+unsave_math_codes(cur_level);
+unsave_cat_codes (cat_code_table,cur_level);
+unsave_text_codes(cur_level);
+if cur_level>level_one then
+ begin decr(cur_level);
+ @<Clear off top level from |save_stack|@>;
+ end
+else confusion("curlevel"); {|unsave| is not used when |cur_group=bottom_level|}
+@:this can't happen curlevel}{\quad curlevel@>
+attr_list_cache:=cache_disabled;
+end;
+
+@ @<Clear off...@>=
+loop@+begin decr(save_ptr);
+ if save_type(save_ptr)=level_boundary then goto done;
+ p:=save_index(save_ptr);
+ if save_type(save_ptr)=insert_token then
+ @<Insert token |p| into \TeX's input@>
+ else begin if save_type(save_ptr)=restore_old_value then
+ begin l:=save_level(save_ptr); decr(save_ptr);
+ end
+ else save_stack[save_ptr]:=eqtb[undefined_control_sequence];
+ @<Store \(s)|save_stack[save_ptr]| in |eqtb[p]|, unless
+ |eqtb[p]| holds a global value@>;
+ end;
+ end;
+done: @!stat if tracing_groups>0 then group_trace(true);@+tats@;@/
+if grp_stack[in_open]=cur_boundary then group_warning;
+ {groups possibly not properly nested with files}
+cur_group:=save_level(save_ptr); cur_boundary:=save_index(save_ptr);
+decr(save_ptr)
+
+@ A global definition, which sets the level to |level_one|,
+@^global definitions@>
+will not be undone by |unsave|. If at least one global definition of
+|eqtb[p]| has been carried out within the group that just ended, the
+last such definition will therefore survive.
+
+@<Store \(s)|save...@>=
+if p<int_base then
+ if eq_level(p)=level_one then
+ begin eq_destroy(save_stack[save_ptr]); {destroy the saved value}
+ @!stat if tracing_restores>0 then restore_trace(p,"retaining");@+tats@;@/
+ end
+ else begin eq_destroy(eqtb[p]); {destroy the current value}
+ eqtb[p]:=save_stack[save_ptr]; {restore the saved value}
+ @!stat if tracing_restores>0 then restore_trace(p,"restoring");@+tats@;@/
+ end
+else if xeq_level[p]<>level_one then
+ begin eqtb[p]:=save_stack[save_ptr]; xeq_level[p]:=l;
+ @!stat if tracing_restores>0 then restore_trace(p,"restoring");@+tats@;@/
+ end
+else begin
+ @!stat if tracing_restores>0 then restore_trace(p,"retaining");@+tats@;@/
+ end
+
+@ @<Declare \eTeX\ procedures for tr...@>=
+@!stat procedure restore_trace(@!p:pointer;@!s:str_number);
+ {|eqtb[p]| has just been restored or retained}
+begin begin_diagnostic; print_char("{"); print(s); print_char(" ");
+show_eqtb(p); print_char("}");
+end_diagnostic(false);
+end;
+tats
+
+@ Most of the parameters kept in |eqtb| can be changed freely, but there's
+an exception: The magnification should not be used with two different
+values during any \TeX\ job, since a single magnification is applied to an
+entire run. The global variable |mag_set| is set to the current magnification
+whenever it becomes necessary to ``freeze'' it at a particular value.
+
+@<Glob...@>=
+@!mag_set:integer; {if nonzero, this magnification should be used henceforth}
+
+@ @<Set init...@>=
+mag_set:=0;
+
+@ The |prepare_mag| subroutine is called whenever \TeX\ wants to use |mag|
+for magnification.
+
+@p procedure prepare_mag;
+begin if (mag_set>0)and(mag<>mag_set) then
+ begin print_err("Incompatible magnification ("); print_int(mag);
+@.Incompatible magnification@>
+ print(");"); print_nl(" the previous value will be retained");
+ help2("I can handle only one magnification ratio per job. So I've")@/
+ ("reverted to the magnification you used earlier on this run.");@/
+ int_error(mag_set);
+ geq_word_define(int_base+mag_code,mag_set); {|mag:=mag_set|}
+ end;
+if (mag<=0)or(mag>32768) then
+ begin print_err("Illegal magnification has been changed to 1000");@/
+@.Illegal magnification...@>
+ help1("The magnification ratio must be between 1 and 32768.");
+ int_error(mag); geq_word_define(int_base+mag_code,1000);
+ end;
+mag_set:=mag;
+end;
+
+@* \[20] Token lists.
+A \TeX\ token is either a character or a control sequence, and it is
+@^token@>
+represented internally in one of two ways: (1)~A character whose ASCII
+code number is |c| and whose command code is |m| is represented as the
+number $2^{21}m+c$; the command code is in the range |1<=m<=14|. (2)~A control
+sequence whose |eqtb| address is |p| is represented as the number
+|cs_token_flag+p|. Here |cs_token_flag=@t$2^{25}-1$@>| is larger than
+$2^{21}m+c$, yet it is small enough that |cs_token_flag+p< max_halfword|;
+thus, a token fits comfortably in a halfword.
+
+A token |t| represents a |left_brace| command if and only if
+|t<left_brace_limit|; it represents a |right_brace| command if and only if
+we have |left_brace_limit<=t<right_brace_limit|; and it represents a |match| or
+|end_match| command if and only if |match_token<=t<=end_match_token|.
+The following definitions take care of these token-oriented constants
+and a few others.
+
+@d cs_token_flag==@"1FFFFFFF {amount added to the |eqtb| location in a
+ token that stands for a control sequence; is a multiple of~$2^{21}$, less~1}
+@d left_brace_token=@"200000 {$2^{21}\cdot|left_brace|$}
+@d left_brace_limit=@"400000 {$2^{21}\cdot(|left_brace|+1)$}
+@d right_brace_token=@"400000 {$2^{21}\cdot|right_brace|$}
+@d right_brace_limit=@"600000 {$2^{21}\cdot(|right_brace|+1)$}
+@d math_shift_token= @"600000 {$2^{21}\cdot|math_shift|$}
+@d tab_token=@"800000 {$2^{21}\cdot|tab_mark|$}
+@d out_param_token=@"A00000 {$2^{21}\cdot|out_param|$}
+@d space_token=@"1400020 {$2^{21}\cdot|spacer|+|" "|$}
+@d letter_token=@"1600000 {$2^{21}\cdot|letter|$}
+@d other_token=@"1800000 {$2^{21}\cdot|other_char|$}
+@d match_token=@"1A00000 {$2^{21}\cdot|match|$}
+@d end_match_token=@"1C00000 {$2^{21}\cdot|end_match|$}
+@d protected_token=@"1C00001 {$2^{21}\cdot|end_match|+1$}
+
+@ @<Check the ``constant''...@>=
+if cs_token_flag+undefined_control_sequence>max_halfword then bad:=21;
+
+@ A token list is a singly linked list of one-word nodes in |mem|, where
+each word contains a token and a link. Macro definitions, output-routine
+definitions, marks, \.{\\write} texts, and a few other things
+are remembered by \TeX\ in the form
+of token lists, usually preceded by a node with a reference count in its
+|token_ref_count| field. The token stored in location |p| is called
+|info(p)|.
+
+Three special commands appear in the token lists of macro definitions.
+When |m=match|, it means that \TeX\ should scan a parameter
+for the current macro; when |m=end_match|, it means that parameter
+matching should end and \TeX\ should start reading the macro text; and
+when |m=out_param|, it means that \TeX\ should insert parameter
+number |c| into the text at this point.
+
+The enclosing \.{\char'173} and \.{\char'175} characters of a macro
+definition are omitted, but the final right brace of an output routine
+is included at the end of its token list.
+
+Here is an example macro definition that illustrates these conventions.
+After \TeX\ processes the text
+$$\.{\\def\\mac a\#1\#2 \\b \{\#1\\-a \#\#1\#2 \#2\}}$$
+the definition of \.{\\mac} is represented as a token list containing
+$$\def\,{\hskip2pt}
+\vbox{\halign{\hfil#\hfil\cr
+(reference count), |letter|\,\.a, |match|\,\#, |match|\,\#, |spacer|\,\.\ ,
+\.{\\b}, |end_match|,\cr
+|out_param|\,1, \.{\\-}, |letter|\,\.a, |spacer|\,\.\ , |mac_param|\,\#,
+|other_char|\,\.1,\cr
+|out_param|\,2, |spacer|\,\.\ , |out_param|\,2.\cr}}$$
+The procedure |scan_toks| builds such token lists, and |macro_call|
+does the parameter matching.
+@^reference counts@>
+
+Examples such as
+$$\.{\\def\\m\{\\def\\m\{a\}\ b\}}$$
+explain why reference counts would be needed even if \TeX\ had no \.{\\let}
+operation: When the token list for \.{\\m} is being read, the redefinition of
+\.{\\m} changes the |eqtb| entry before the token list has been fully
+consumed, so we dare not simply destroy a token list when its
+control sequence is being redefined.
+
+If the parameter-matching part of a definition ends with `\.{\#\{}',
+the corresponding token list will have `\.\{' just before the `|end_match|'
+and also at the very end. The first `\.\{' is used to delimit the parameter; the
+second one keeps the first from disappearing.
+
+@ The procedure |show_token_list|, which prints a symbolic form of
+the token list that starts at a given node |p|, illustrates these
+conventions. The token list being displayed should not begin with a reference
+count. However, the procedure is intended to be robust, so that if the
+memory links are awry or if |p| is not really a pointer to a token list,
+nothing catastrophic will happen.
+
+An additional parameter |q| is also given; this parameter is either null
+or it points to a node in the token list where a certain magic computation
+takes place that will be explained later. (Basically, |q| is non-null when
+we are printing the two-line context information at the time of an error
+message; |q| marks the place corresponding to where the second line
+should begin.)
+
+For example, if |p| points to the node containing the first \.a in the
+token list above, then |show_token_list| will print the string
+$$\hbox{`\.{a\#1\#2\ \\b\ ->\#1\\-a\ \#\#1\#2\ \#2}';}$$
+and if |q| points to the node containing the second \.a,
+the magic computation will be performed just before the second \.a is printed.
+
+The generation will stop, and `\.{\\ETC.}' will be printed, if the length
+of printing exceeds a given limit~|l|. Anomalous entries are printed in the
+form of control sequences that are not followed by a blank space, e.g.,
+`\.{\\BAD.}'; this cannot be confused with actual control sequences because
+a real control sequence named \.{BAD} would come out `\.{\\BAD\ }'.
+
+@<Declare the procedure called |show_token_list|@>=
+procedure show_token_list(@!p,@!q:integer;@!l:integer);
+label exit;
+var m,@!c:integer; {pieces of a token}
+@!match_chr:ASCII_code; {character used in a `|match|'}
+@!n:ASCII_code; {the highest parameter number, as an ASCII digit}
+begin match_chr:="#"; n:="0"; tally:=0;
+while (p<>null) and (tally<l) do
+ begin if p=q then @<Do magic computation@>;
+ @<Display token |p|, and |return| if there are problems@>;
+ p:=link(p);
+ end;
+if p<>null then print_esc("ETC.");
+@.ETC@>
+exit:
+end;
+
+@ @<Display token |p|...@>=
+if (p<fix_mem_min) or (p>fix_mem_end) then
+ begin print_esc("CLOBBERED."); return;
+@.CLOBBERED@>
+ end;
+if info(p)>=cs_token_flag then begin
+ if not ((inhibit_par_tokens) and (info(p)=par_token)) then
+ print_cs(info(p)-cs_token_flag);
+ end
+else begin m:=info(p) div string_offset; c:=info(p) mod string_offset;
+ if info(p)<0 then print_esc("BAD.")
+@.BAD@>
+ else @<Display the token $(|m|,|c|)$@>;
+ end
+
+@ The procedure usually ``learns'' the character code used for macro
+parameters by seeing one in a |match| command before it runs into any
+|out_param| commands.
+
+@<Display the token ...@>=
+case m of
+left_brace,right_brace,math_shift,tab_mark,sup_mark,sub_mark,spacer,
+ letter,other_char: print(c);
+mac_param: begin print(c); print(c);
+ end;
+out_param: begin print(match_chr);
+ if c<=9 then print_char(c+"0")
+ else begin print_char("!"); return;
+ end;
+ end;
+match: begin match_chr:=c; print(c); incr(n); print_char(n);
+ if n>"9" then return;
+ end;
+end_match: if c=0 then print("->");
+@.->@>
+othercases print_esc("BAD.")
+@.BAD@>
+endcases
+
+@ Here's the way we sometimes want to display a token list, given a pointer
+to its reference count; the pointer may be null.
+
+@p procedure token_show(@!p:pointer);
+begin if p<>null then show_token_list(link(p),null,10000000);
+end;
+
+@ The |print_meaning| subroutine displays |cur_cmd| and |cur_chr| in
+symbolic form, including the expansion of a macro or mark.
+
+@p procedure print_meaning;
+begin print_cmd_chr(cur_cmd,cur_chr);
+if cur_cmd>=call then
+ begin print_char(":"); print_ln; token_show(cur_chr);
+ end
+else @<Show the meaning of a mark node@>;
+end;
+
+@* \[21] Introduction to the syntactic routines.
+Let's pause a moment now and try to look at the Big Picture.
+The \TeX\ program consists of three main parts: syntactic routines,
+semantic routines, and output routines. The chief purpose of the
+syntactic routines is to deliver the user's input to the semantic routines,
+one token at a time. The semantic routines act as an interpreter
+responding to these tokens, which may be regarded as commands. And the
+output routines are periodically called on to convert box-and-glue
+lists into a compact set of instructions that will be sent
+to a typesetter. We have discussed the basic data structures and utility
+routines of \TeX, so we are good and ready to plunge into the real activity by
+considering the syntactic routines.
+
+Our current goal is to come to grips with the |get_next| procedure,
+which is the keystone of \TeX's input mechanism. Each call of |get_next|
+sets the value of three variables |cur_cmd|, |cur_chr|, and |cur_cs|,
+representing the next input token.
+$$\vbox{\halign{#\hfil\cr
+ \hbox{|cur_cmd| denotes a command code from the long list of codes
+ given above;}\cr
+ \hbox{|cur_chr| denotes a character code or other modifier of the command
+ code;}\cr
+ \hbox{|cur_cs| is the |eqtb| location of the current control sequence,}\cr
+ \hbox{\qquad if the current token was a control sequence,
+ otherwise it's zero.}\cr}}$$
+Underlying this external behavior of |get_next| is all the machinery
+necessary to convert from character files to tokens. At a given time we
+may be only partially finished with the reading of several files (for
+which \.{\\input} was specified), and partially finished with the expansion
+of some user-defined macros and/or some macro parameters, and partially
+finished with the generation of some text in a template for \.{\\halign},
+and so on. When reading a character file, special characters must be
+classified as math delimiters, etc.; comments and extra blank spaces must
+be removed, paragraphs must be recognized, and control sequences must be
+found in the hash table. Furthermore there are occasions in which the
+scanning routines have looked ahead for a word like `\.{plus}' but only
+part of that word was found, hence a few characters must be put back
+into the input and scanned again.
+
+To handle these situations, which might all be present simultaneously,
+\TeX\ uses various stacks that hold information about the incomplete
+activities, and there is a finite state control for each level of the
+input mechanism. These stacks record the current state of an implicitly
+recursive process, but the |get_next| procedure is not recursive.
+Therefore it will not be difficult to translate these algorithms into
+low-level languages that do not support recursion.
+
+@<Glob...@>=
+@!cur_cmd: eight_bits; {current command set by |get_next|}
+@!cur_chr: halfword; {operand of current command}
+@!cur_cs: pointer; {control sequence found here, zero if none found}
+@!cur_tok: halfword; {packed representative of |cur_cmd| and |cur_chr|}
+
+@ The |print_cmd_chr| routine prints a symbolic interpretation of a
+command code and its modifier. This is used in certain `\.{You can\'t}'
+error messages, and in the implementation of diagnostic routines like
+\.{\\show}.
+
+The body of |print_cmd_chr| is a rather tedious listing of print
+commands, and most of it is essentially an inverse to the |primitive|
+routine that enters a \TeX\ primitive into |eqtb|. Therefore much of
+this procedure appears elsewhere in the program,
+together with the corresponding |primitive| calls.
+
+@d chr_cmd(#)==begin print(#); print(chr_code);
+ end
+
+@<Declare the procedure called |print_cmd_chr|@>=
+procedure print_cmd_chr(@!cmd:quarterword;@!chr_code:halfword);
+var n:integer; {temp variable}
+begin case cmd of
+left_brace: chr_cmd("begin-group character ");
+right_brace: chr_cmd("end-group character ");
+math_shift: chr_cmd("math shift character ");
+mac_param: chr_cmd("macro parameter character ");
+sup_mark: chr_cmd("superscript character ");
+sub_mark: chr_cmd("subscript character ");
+endv: print("end of alignment template");
+spacer: chr_cmd("blank space ");
+letter: chr_cmd("the letter ");
+other_char: chr_cmd("the character ");
+@t\4@>@<Cases of |print_cmd_chr| for symbolic printing of primitives@>@/
+othercases print("[unknown command code!]")
+endcases;
+end;
+
+@ Here is a procedure that displays the current command.
+
+@p procedure show_cur_cmd_chr;
+var n:integer; {level of \.{\\if...\\fi} nesting}
+@!l:integer; {line where \.{\\if} started}
+@!p:pointer;
+begin begin_diagnostic; print_nl("{");
+if mode<>shown_mode then
+ begin print_mode(mode); print(": "); shown_mode:=mode;
+ end;
+print_cmd_chr(cur_cmd,cur_chr);
+if tracing_ifs>0 then
+ if cur_cmd>=if_test then if cur_cmd<=fi_or_else then
+ begin print(": ");
+ if cur_cmd=fi_or_else then
+ begin print_cmd_chr(if_test,cur_if); print_char(" ");
+ n:=0; l:=if_line;
+ end
+ else begin n:=1; l:=line;
+ end;
+ p:=cond_ptr;
+ while p<>null do
+ begin incr(n); p:=vlink(p);
+ end;
+ print("(level "); print_int(n); print_char(")"); print_if_line(l);
+ end;
+print_char("}");
+end_diagnostic(false);
+end;
+
+@* \[22] Input stacks and states.
+This implementation of
+\TeX\ uses two different conventions for representing sequential stacks.
+@^stack conventions@>@^conventions for representing stacks@>
+
+\yskip\hangg 1) If there is frequent access to the top entry, and if the
+stack is essentially never empty, then the top entry is kept in a global
+variable (even better would be a machine register), and the other entries
+appear in the array $\\{stack}[0\to(\\{ptr}-1)]$. For example, the
+semantic stack described above is handled this way, and so is the input
+stack that we are about to study.
+
+\yskip\hangg 2) If there is infrequent top access, the entire stack contents
+are in the array $\\{stack}[0\to(\\{ptr}-1)]$. For example, the |save_stack|
+is treated this way, as we have seen.
+
+\yskip\noindent
+The state of \TeX's input mechanism appears in the input stack, whose
+entries are records with six fields, called |state|, |index|, |start|, |loc|,
+|limit|, and |name|. This stack is maintained with
+convention~(1), so it is declared in the following way:
+
+@<Types...@>=
+@!in_state_record = record
+ @!state_field, @!index_field: quarterword;
+ @!start_field,@!loc_field, @!limit_field, @!name_field,
+ @!ocp_lstack_field: halfword; {used for omega translation processes}
+ @!ocp_no_field: halfword; {used for omega translation processes}
+ @!nofilter_field: boolean; {used by token filtering}
+ end;
+
+@ @<Glob...@>=
+@!input_stack : array[0..stack_size] of in_state_record;
+@!input_ptr : 0..stack_size; {first unused location of |input_stack|}
+@!max_in_stack: 0..stack_size; {largest value of |input_ptr| when pushing}
+@!cur_input : in_state_record;
+ {the ``top'' input state, according to convention (1)}
+
+@ We've already defined the special variable |loc==cur_input.loc_field|
+in our discussion of basic input-output routines. The other components of
+|cur_input| are defined in the same way:
+
+@d state==cur_input.state_field {current scanner state}
+@d index==cur_input.index_field {reference for buffer information}
+@d start==cur_input.start_field {starting position in |buffer|}
+@d limit==cur_input.limit_field {end of current line in |buffer|}
+@d nofilter==cur_input.nofilter_field {is token filtering explicitly disallowed?}
+@d name==cur_input.name_field {name of the current file}
+@d current_ocp_lstack==cur_input.ocp_lstack_field {name of the current ocp}
+@d current_ocp_no==cur_input.ocp_no_field {name of the current ocp}
+
+@ Let's look more closely now at the control variables
+(|state|,~|index|,~|start|,~|loc|,~|limit|,~|name|),
+assuming that \TeX\ is reading a line of characters that have been input
+from some file or from the user's terminal. There is an array called
+|buffer| that acts as a stack of all lines of characters that are
+currently being read from files, including all lines on subsidiary
+levels of the input stack that are not yet completed. \TeX\ will return to
+the other lines when it is finished with the present input file.
+
+(Incidentally, on a machine with byte-oriented addressing, it might be
+appropriate to combine |buffer| with the |str_pool| array,
+letting the buffer entries grow downward from the top of the string pool
+and checking that these two tables don't bump into each other.)
+
+The line we are currently working on begins in position |start| of the
+buffer; the next character we are about to read is |buffer[loc]|; and
+|limit| is the location of the last character present. If |loc>limit|,
+the line has been completely read. Usually |buffer[limit]| is the
+|end_line_char|, denoting the end of a line, but this is not
+true if the current line is an insertion that was entered on the user's
+terminal in response to an error message.
+
+The |name| variable is a string number that designates the name of
+the current file, if we are reading a text file. It is zero if we
+are reading from the terminal; it is |n+1| if we are reading from
+input stream |n|, where |0<=n<=16|. (Input stream 16 stands for
+an invalid stream number; in such cases the input is actually from
+the terminal, under control of the procedure |read_toks|.)
+Finally |18<=name<=20| indicates that we are reading a pseudo file
+created by the \.{\\scantokens} or \.{\\scantextokens} command.
+
+The |state| variable has one of three values, when we are scanning such
+files:
+$$\baselineskip 15pt\vbox{\halign{#\hfil\cr
+1) |state=mid_line| is the normal state.\cr
+2) |state=skip_blanks| is like |mid_line|, but blanks are ignored.\cr
+3) |state=new_line| is the state at the beginning of a line.\cr}}$$
+These state values are assigned numeric codes so that if we add the state
+code to the next character's command code, we get distinct values. For
+example, `|mid_line+spacer|' stands for the case that a blank
+space character occurs in the middle of a line when it is not being
+ignored; after this case is processed, the next value of |state| will
+be |skip_blanks|.
+
+@d mid_line=1 {|state| code when scanning a line of characters}
+@d skip_blanks=2+max_char_code {|state| code when ignoring blanks}
+@d new_line=3+max_char_code+max_char_code {|state| code at start of line}
+
+@ Additional information about the current line is available via the
+|index| variable, which counts how many lines of characters are present
+in the buffer below the current level. We have |index=0| when reading
+from the terminal and prompting the user for each line; then if the user types,
+e.g., `\.{\\input paper}', we will have |index=1| while reading
+the file \.{paper.tex}. However, it does not follow that |index| is the
+same as the input stack pointer, since many of the levels on the input
+stack may come from token lists. For example, the instruction `\.{\\input
+paper}' might occur in a token list.
+
+The global variable |in_open| is equal to the |index|
+value of the highest non-token-list level. Thus, the number of partially read
+lines in the buffer is |in_open+1|, and we have |in_open=index|
+when we are not reading a token list.
+
+If we are not currently reading from the terminal, or from an input
+stream, we are reading from the file variable |input_file[index]|. We use
+the notation |terminal_input| as a convenient abbreviation for |name=0|,
+and |cur_file| as an abbreviation for |input_file[index]|.
+
+The global variable |line| contains the line number in the topmost
+open file, for use in error messages. If we are not reading from
+the terminal, |line_stack[index]| holds the line number for the
+enclosing level, so that |line| can be restored when the current
+file has been read. Line numbers should never be negative, since the
+negative of the current line number is used to identify the user's output
+routine in the |mode_line| field of the semantic nest entries.
+
+If more information about the input state is needed, it can be
+included in small arrays like those shown here. For example,
+the current page or segment number in the input file might be
+put into a variable |@!page|, maintained for enclosing levels in
+`\ignorespaces|@!page_stack:array[1..max_in_open] of integer|\unskip'
+by analogy with |line_stack|.
+@^system dependencies@>
+
+@d terminal_input==(name=0) {are we reading from the terminal?}
+@d cur_file==input_file[index] {the current |alpha_file| variable}
+
+@<Glob...@>=
+@!in_open : 0..max_in_open; {the number of lines in the buffer, less one}
+@!open_parens : 0..max_in_open; {the number of open text files}
+@!input_file : array[1..max_in_open] of alpha_file;
+@!line : integer; {current line number in the current source file}
+@!line_stack : array[1..max_in_open] of integer;
+
+@ Users of \TeX\ sometimes forget to balance left and right braces properly,
+and one of the ways \TeX\ tries to spot such errors is by considering an
+input file as broken into subfiles by control sequences that
+are declared to be \.{\\outer}.
+
+A variable called |scanner_status| tells \TeX\ whether or not to complain
+when a subfile ends. This variable has six possible values:
+
+\yskip\hang|normal|, means that a subfile can safely end here without incident.
+
+\yskip\hang|skipping|, means that a subfile can safely end here, but not a file,
+because we're reading past some conditional text that was not selected.
+
+\yskip\hang|defining|, means that a subfile shouldn't end now because a
+macro is being defined.
+
+\yskip\hang|matching|, means that a subfile shouldn't end now because a
+macro is being used and we are searching for the end of its arguments.
+
+\yskip\hang|aligning|, means that a subfile shouldn't end now because we are
+not finished with the preamble of an \.{\\halign} or \.{\\valign}.
+
+\yskip\hang|absorbing|, means that a subfile shouldn't end now because we are
+reading a balanced token list for \.{\\message}, \.{\\write}, etc.
+
+\yskip\noindent
+If the |scanner_status| is not |normal|, the variable |warning_index| points
+to the |eqtb| location for the relevant control sequence name to print
+in an error message.
+
+@d skipping=1 {|scanner_status| when passing conditional text}
+@d defining=2 {|scanner_status| when reading a macro definition}
+@d matching=3 {|scanner_status| when reading macro arguments}
+@d aligning=4 {|scanner_status| when reading an alignment preamble}
+@d absorbing=5 {|scanner_status| when reading a balanced text}
+
+@<Glob...@>=
+@!scanner_status : normal..absorbing; {can a subfile end now?}
+@!warning_index : pointer; {identifier relevant to non-|normal| scanner status}
+@!def_ref : pointer; {reference count of token list being defined}
+
+@ Here is a procedure that uses |scanner_status| to print a warning message
+when a subfile has ended, and at certain other crucial times:
+
+@<Declare the procedure called |runaway|@>=
+procedure runaway;
+var p:pointer; {head of runaway list}
+begin p:=null;
+ if scanner_status>skipping then
+ begin print_nl("Runaway ");
+@.Runaway...@>
+ case scanner_status of
+ defining: begin print("definition"); p:=def_ref;
+ end;
+ matching: begin print("argument"); p:=temp_token_head;
+ end;
+ aligning: begin print("preamble"); p:=hold_token_head;
+ end;
+ absorbing: begin print("text"); p:=def_ref;
+ end;
+ end; {there are no other cases}
+ print_char("?");print_ln; show_token_list(link(p),null,error_line-10);
+ end;
+end;
+
+@ However, all this discussion about input state really applies only to the
+case that we are inputting from a file. There is another important case,
+namely when we are currently getting input from a token list. In this case
+|state=token_list|, and the conventions about the other state variables
+are different:
+
+\yskip\hang|loc| is a pointer to the current node in the token list, i.e.,
+the node that will be read next. If |loc=null|, the token list has been
+fully read.
+
+\yskip\hang|start| points to the first node of the token list; this node
+may or may not contain a reference count, depending on the type of token
+list involved.
+
+\yskip\hang|token_type|, which takes the place of |index| in the
+discussion above, is a code number that explains what kind of token list
+is being scanned.
+
+\yskip\hang|name| points to the |eqtb| address of the control sequence
+being expanded, if the current token list is a macro.
+
+\yskip\hang|param_start|, which takes the place of |limit|, tells where
+the parameters of the current macro begin in the |param_stack|, if the
+current token list is a macro.
+
+\yskip\noindent The |token_type| can take several values, depending on
+where the current token list came from:
+
+\yskip\hang|parameter|, if a parameter is being scanned;
+
+\hang|u_template|, if the \<u_j> part of an alignment
+template is being scanned;
+
+\hang|v_template|, if the \<v_j> part of an alignment
+template is being scanned;
+
+\hang|backed_up|, if the token list being scanned has been inserted as
+`to be read again'.
+
+\hang|inserted|, if the token list being scanned has been inserted as
+the text expansion of a \.{\\count} or similar variable;
+
+\hang|macro|, if a user-defined control sequence is being scanned;
+
+\hang|output_text|, if an \.{\\output} routine is being scanned;
+
+\hang|every_par_text|, if the text of \.{\\everypar} is being scanned;
+
+\hang|every_math_text|, if the text of \.{\\everymath} is being scanned;
+
+\hang|every_display_text|, if the text of \.{\\everydisplay} is being scanned;
+
+\hang|every_hbox_text|, if the text of \.{\\everyhbox} is being scanned;
+
+\hang|every_vbox_text|, if the text of \.{\\everyvbox} is being scanned;
+
+\hang|every_job_text|, if the text of \.{\\everyjob} is being scanned;
+
+\hang|every_cr_text|, if the text of \.{\\everycr} is being scanned;
+
+\hang|mark_text|, if the text of a \.{\\mark} is being scanned;
+
+\hang|write_text|, if the text of a \.{\\write} is being scanned.
+
+\yskip\noindent
+The codes for |output_text|, |every_par_text|, etc., are equal to a constant
+plus the corresponding codes for token list parameters |output_routine_loc|,
+|every_par_loc|, etc. The token list begins with a reference count if and
+only if |token_type>=macro|.
+@^reference counts@>
+
+Since \eTeX's additional token list parameters precede |toks_base|, the
+corresponding token types must precede |write_text|.
+
+@d token_list=0 {|state| code when scanning a token list}
+@d token_type==index {type of current token list}
+@d param_start==limit {base of macro parameters in |param_stack|}
+@d parameter=0 {|token_type| code for parameter}
+@d u_template=1 {|token_type| code for \<u_j> template}
+@d v_template=2 {|token_type| code for \<v_j> template}
+@d backed_up=3 {|token_type| code for text to be reread}
+@d inserted=4 {|token_type| code for inserted texts}
+@d macro=5 {|token_type| code for defined control sequences}
+@d output_text=6 {|token_type| code for output routines}
+@d every_par_text=7 {|token_type| code for \.{\\everypar}}
+@d every_math_text=8 {|token_type| code for \.{\\everymath}}
+@d every_display_text=9 {|token_type| code for \.{\\everydisplay}}
+@d every_hbox_text=10 {|token_type| code for \.{\\everyhbox}}
+@d every_vbox_text=11 {|token_type| code for \.{\\everyvbox}}
+@d every_job_text=12 {|token_type| code for \.{\\everyjob}}
+@d every_cr_text=13 {|token_type| code for \.{\\everycr}}
+@d mark_text=14 {|token_type| code for \.{\\topmark}, etc.}
+@#
+@d eTeX_text_offset=output_routine_loc-output_text
+@d every_eof_text=every_eof_loc-eTeX_text_offset
+ {|token_type| code for \.{\\everyeof}}
+@#
+@d write_text=etex_toks-eTeX_text_offset {|token_type| code for \.{\\write}}
+
+@ The |param_stack| is an auxiliary array used to hold pointers to the token
+lists for parameters at the current level and subsidiary levels of input.
+This stack is maintained with convention (2), and it grows at a different
+rate from the others.
+
+@<Glob...@>=
+@!param_stack:array [0..param_size] of pointer;
+ {token list pointers for parameters}
+@!param_ptr:0..param_size; {first unused entry in |param_stack|}
+@!max_param_stack:integer;
+ {largest value of |param_ptr|, will be |<=param_size+9|}
+
+@ The input routines must also interact with the processing of
+\.{\\halign} and \.{\\valign}, since the appearance of tab marks and
+\.{\\cr} in certain places is supposed to trigger the beginning of special
+\<v_j> template text in the scanner. This magic is accomplished by an
+|align_state| variable that is increased by~1 when a `\.{\char'173}' is
+scanned and decreased by~1 when a `\.{\char'175}' is scanned. The |align_state|
+is nonzero during the \<u_j> template, after which it is set to zero; the
+\<v_j> template begins when a tab mark or \.{\\cr} occurs at a time that
+|align_state=0|.
+
+@<Glob...@>=
+@!align_state:integer; {group level with respect to current alignment}
+
+@ Thus, the ``current input state'' can be very complicated indeed; there
+can be many levels and each level can arise in a variety of ways. The
+|show_context| procedure, which is used by \TeX's error-reporting routine to
+print out the current input state on all levels down to the most recent
+line of characters from an input file, illustrates most of these conventions.
+The global variable |base_ptr| contains the lowest level that was
+displayed by this procedure.
+
+@<Glob...@>=
+@!base_ptr:0..stack_size; {shallowest level shown by |show_context|}
+
+@ The status at each level is indicated by printing two lines, where the first
+line indicates what was read so far and the second line shows what remains
+to be read. The context is cropped, if necessary, so that the first line
+contains at most |half_error_line| characters, and the second contains
+at most |error_line|. Non-current input levels whose |token_type| is
+`|backed_up|' are shown only if they have not been fully read.
+
+@p procedure show_context; {prints where the scanner is}
+label done;
+var old_setting:0..max_selector; {saved |selector| setting}
+@!nn:integer; {number of contexts shown so far, less one}
+@!bottom_line:boolean; {have we reached the final context to be shown?}
+@<Local variables for formatting calculations@>@/
+begin base_ptr:=input_ptr; input_stack[base_ptr]:=cur_input;
+ {store current state}
+nn:=-1; bottom_line:=false;
+loop@+begin cur_input:=input_stack[base_ptr]; {enter into the context}
+ if (state<>token_list) then
+ if (name>21) or (base_ptr=0) then bottom_line:=true;
+ if (base_ptr=input_ptr)or bottom_line or(nn<error_context_lines) then
+ @<Display the current context@>
+ else if nn=error_context_lines then
+ begin print_nl("..."); incr(nn); {omitted if |error_context_lines<0|}
+ end;
+ if bottom_line then goto done;
+ decr(base_ptr);
+ end;
+done: cur_input:=input_stack[input_ptr]; {restore original state}
+end;
+
+@ @<Display the current context@>=
+begin if (base_ptr=input_ptr) or (state<>token_list) or
+ (token_type<>backed_up) or (loc<>null) then
+ {we omit backed-up token lists that have already been read}
+ begin tally:=0; {get ready to count characters}
+ old_setting:=selector;
+ if current_ocp_lstack>0 then
+ begin print_nl("OCP stack "); print_scaled(current_ocp_lstack);
+ print(" entry "); print_int(current_ocp_no); print(":");
+ @<Pseudoprint the line@>;
+ end
+ else if state<>token_list then
+ begin @<Print location of current line@>;
+ @<Pseudoprint the line@>;
+ end
+ else begin @<Print type of token list@>;
+ @<Pseudoprint the token list@>;
+ end;
+ selector:=old_setting; {stop pseudoprinting}
+ @<Print two lines using the tricky pseudoprinted information@>;
+ incr(nn);
+ end;
+end
+
+@ This routine should be changed, if necessary, to give the best possible
+indication of where the current line resides in the input file.
+For example, on some systems it is best to print both a page and line number.
+@^system dependencies@>
+
+@<Print location of current line@>=
+if name<=17 then
+ if terminal_input then
+ if base_ptr=0 then print_nl("<*>") else print_nl("<insert> ")
+ else begin print_nl("<read ");
+ if name=17 then print_char("*")@+else print_int(name-1);
+@.*\relax@>
+ print_char(">");
+ end
+else if index<>in_open then {input from a pseudo file}
+ begin print_nl("l."); print_int(line_stack[index+1]);
+ end
+else begin print_nl("l."); print_int(line);
+ end;
+print_char(" ")
+
+@ @<Print type of token list@>=
+case token_type of
+parameter: print_nl("<argument> ");
+u_template,v_template: print_nl("<template> ");
+backed_up: if loc=null then print_nl("<recently read> ")
+ else print_nl("<to be read again> ");
+inserted: print_nl("<inserted text> ");
+macro: begin print_ln; print_cs(name);
+ end;
+output_text: print_nl("<output> ");
+every_par_text: print_nl("<everypar> ");
+every_math_text: print_nl("<everymath> ");
+every_display_text: print_nl("<everydisplay> ");
+every_hbox_text: print_nl("<everyhbox> ");
+every_vbox_text: print_nl("<everyvbox> ");
+every_job_text: print_nl("<everyjob> ");
+every_cr_text: print_nl("<everycr> ");
+mark_text: print_nl("<mark> ");
+every_eof_text: print_nl("<everyeof> ");
+write_text: print_nl("<write> ");
+othercases print_nl("?") {this should never happen}
+endcases
+
+@ Here it is necessary to explain a little trick. We don't want to store a long
+string that corresponds to a token list, because that string might take up
+lots of memory; and we are printing during a time when an error message is
+being given, so we dare not do anything that might overflow one of \TeX's
+tables. So `pseudoprinting' is the answer: We enter a mode of printing
+that stores characters into a buffer of length |error_line|, where character
+$k+1$ is placed into \hbox{|trick_buf[k mod error_line]|} if
+|k<trick_count|, otherwise character |k| is dropped. Initially we set
+|tally:=0| and |trick_count:=1000000|; then when we reach the
+point where transition from line 1 to line 2 should occur, we
+set |first_count:=tally| and |trick_count:=@tmax@>(error_line,
+tally+1+error_line-half_error_line)|. At the end of the
+pseudoprinting, the values of |first_count|, |tally|, and
+|trick_count| give us all the information we need to print the two lines,
+and all of the necessary text is in |trick_buf|.
+
+Namely, let |l| be the length of the descriptive information that appears
+on the first line. The length of the context information gathered for that
+line is |k=first_count|, and the length of the context information
+gathered for line~2 is $m=\min(|tally|, |trick_count|)-k$. If |l+k<=h|,
+where |h=half_error_line|, we print |trick_buf[0..k-1]| after the
+descriptive information on line~1, and set |n:=l+k|; here |n| is the
+length of line~1. If $l+k>h$, some cropping is necessary, so we set |n:=h|
+and print `\.{...}' followed by
+$$\hbox{|trick_buf[(l+k-h+3)..k-1]|,}$$
+where subscripts of |trick_buf| are circular modulo |error_line|. The
+second line consists of |n|~spaces followed by |trick_buf[k..(k+m-1)]|,
+unless |n+m>error_line|; in the latter case, further cropping is done.
+This is easier to program than to explain.
+
+@<Local variables for formatting...@>=
+@!i:0..buf_size; {index into |buffer|}
+@!j:0..buf_size; {end of current line in |buffer|}
+@!l:0..half_error_line; {length of descriptive information on line 1}
+@!m:integer; {context information gathered for line 2}
+@!n:0..error_line; {length of line 1}
+@!p: integer; {starting or ending place in |trick_buf|}
+@!q: integer; {temporary index}
+
+@ The following code sets up the print routines so that they will gather
+the desired information.
+
+@d begin_pseudoprint==
+ begin l:=tally; tally:=0; selector:=pseudo;
+ trick_count:=1000000;
+ end
+@d set_trick_count==
+ begin first_count:=tally;
+ trick_count:=tally+1+error_line-half_error_line;
+ if trick_count<error_line then trick_count:=error_line;
+ end
+
+@ And the following code uses the information after it has been gathered.
+
+@<Print two lines using the tricky pseudoprinted information@>=
+if trick_count=1000000 then set_trick_count;
+ {|set_trick_count| must be performed}
+if tally<trick_count then m:=tally-first_count
+else m:=trick_count-first_count; {context on line 2}
+if l+first_count<=half_error_line then
+ begin p:=0; n:=l+first_count;
+ end
+else begin print("..."); p:=l+first_count-half_error_line+3;
+ n:=half_error_line;
+ end;
+for q:=p to first_count-1 do print_char(trick_buf[q mod error_line]);
+print_ln;
+for q:=1 to n do print_char(" "); {print |n| spaces to begin line~2}
+if m+n<=error_line then p:=first_count+m else p:=first_count+(error_line-n-3);
+for q:=first_count to p-1 do print_char(trick_buf[q mod error_line]);
+if m+n>error_line then print("...")
+
+@ But the trick is distracting us from our current goal, which is to
+understand the input state. So let's concentrate on the data structures that
+are being pseudoprinted as we finish up the |show_context| procedure.
+
+@<Pseudoprint the line@>=
+begin_pseudoprint;
+if buffer[limit]=end_line_char then j:=limit
+else j:=limit+1; {determine the effective end of the line}
+if j>0 then for i:=start to j-1 do
+ begin if i=loc then set_trick_count;
+ print_char(buffer[i]);
+ end
+
+@ @<Pseudoprint the token list@>=
+begin_pseudoprint;
+if token_type<macro then show_token_list(start,loc,100000)
+else show_token_list(link(start),loc,100000) {avoid reference count}
+
+@ Here is the missing piece of |show_token_list| that is activated when the
+token beginning line~2 is about to be shown:
+
+@<Do magic computation@>=set_trick_count
+
+@* \[23] Maintaining the input stacks.
+The following subroutines change the input status in commonly needed ways.
+
+First comes |push_input|, which stores the current state and creates a
+new level (having, initially, the same properties as the old).
+
+@d push_input==@t@> {enter a new input level, save the old}
+ begin if input_ptr>max_in_stack then
+ begin max_in_stack:=input_ptr;
+ if input_ptr=stack_size then overflow("input stack size",stack_size);
+@:TeX capacity exceeded input stack size}{\quad input stack size@>
+ end;
+ input_stack[input_ptr]:=cur_input; {stack the record}
+ nofilter:=false;
+ incr(input_ptr);
+ end
+
+@ And of course what goes up must come down.
+
+@d pop_input==@t@> {leave an input level, re-enter the old}
+ begin decr(input_ptr); cur_input:=input_stack[input_ptr];
+ end
+
+@ Here is a procedure that starts a new level of token-list input, given
+a token list |p| and its type |t|. If |t=macro|, the calling routine should
+set |name| and |loc|.
+
+@d back_list(#)==begin_token_list(#,backed_up) {backs up a simple token list}
+@d ins_list(#)==begin_token_list(#,inserted) {inserts a simple token list}
+
+@p procedure begin_token_list(@!p:pointer;@!t:quarterword);
+begin push_input; state:=token_list; start:=p; token_type:=t;
+if t>=macro then {the token list starts with a reference count}
+ begin add_token_ref(p);
+ if t=macro then param_start:=param_ptr
+ else begin loc:=link(p);
+ if tracing_macros>1 then
+ begin begin_diagnostic; print_nl("");
+ case t of
+ mark_text:print_esc("mark");
+ write_text:print_esc("write");
+ othercases print_cmd_chr(assign_toks,t-output_text+output_routine_loc)
+ endcases;@/
+ print("->"); token_show(p); end_diagnostic(false);
+ end;
+ end;
+ end
+else loc:=p;
+end;
+
+@ When a token list has been fully scanned, the following computations
+should be done as we leave that level of input. The |token_type| tends
+to be equal to either |backed_up| or |inserted| about 2/3 of the time.
+@^inner loop@>
+
+@p procedure end_token_list; {leave a token-list input level}
+begin if token_type>=backed_up then {token list to be deleted}
+ begin if token_type<=inserted then flush_list(start)
+ else begin delete_token_ref(start); {update reference count}
+ if token_type=macro then {parameters must be flushed}
+ while param_ptr>param_start do
+ begin decr(param_ptr);
+ flush_list(param_stack[param_ptr]);
+ end;
+ end;
+ end
+else if token_type=u_template then
+ if align_state>500000 then align_state:=0
+ else fatal_error("(interwoven alignment preambles are not allowed)");
+@.interwoven alignment preambles...@>
+pop_input;
+check_interrupt;
+end;
+
+@ Sometimes \TeX\ has read too far and wants to ``unscan'' what it has
+seen. The |back_input| procedure takes care of this by putting the token
+just scanned back into the input stream, ready to be read again. This
+procedure can be used only if |cur_tok| represents the token to be
+replaced. Some applications of \TeX\ use this procedure a lot,
+so it has been slightly optimized for speed.
+@^inner loop@>
+
+@p procedure back_input; {undoes one token of input}
+var p:pointer; {a token list of length one}
+begin while (state=token_list)and(loc=null)and(token_type<>v_template) do
+ end_token_list; {conserve stack space}
+p:=get_avail; info(p):=cur_tok;
+if cur_tok<right_brace_limit then
+ if cur_tok<left_brace_limit then decr(align_state)
+ else incr(align_state);
+push_input; state:=token_list; start:=p; token_type:=backed_up;
+loc:=p; {that was |back_list(p)|, without procedure overhead}
+end;
+
+@ @<Insert token |p| into \TeX's input@>=
+begin t:=cur_tok; cur_tok:=p;
+if a then
+ begin p:=get_avail; info(p):=cur_tok; link(p):=loc; loc:=p; start:=p;
+ if cur_tok<right_brace_limit then
+ if cur_tok<left_brace_limit then decr(align_state)
+ else incr(align_state);
+ end
+else begin back_input; a:=1; { etex is always on }
+ end;
+cur_tok:=t;
+end
+
+@ The |back_error| routine is used when we want to replace an offending token
+just before issuing an error message. This routine, like |back_input|,
+requires that |cur_tok| has been set. We disable interrupts during the
+call of |back_input| so that the help message won't be lost.
+
+@p procedure back_error; {back up one token and call |error|}
+begin OK_to_interrupt:=false; back_input; OK_to_interrupt:=true; error;
+end;
+@#
+procedure ins_error; {back up one inserted token and call |error|}
+begin OK_to_interrupt:=false; back_input; token_type:=inserted;
+OK_to_interrupt:=true; error;
+end;
+
+@ The |begin_file_reading| procedure starts a new level of input for lines
+of characters to be read from a file, or as an insertion from the
+terminal. It does not take care of opening the file, nor does it set |loc|
+or |limit| or |line|.
+@^system dependencies@>
+
+@p procedure begin_file_reading;
+begin if in_open=max_in_open then overflow("text input levels",max_in_open);
+@:TeX capacity exceeded text input levels}{\quad text input levels@>
+if first=buf_size then check_buffer_overflow(first);
+@:TeX capacity exceeded buffer size}{\quad buffer size@>
+incr(in_open); push_input; index:=in_open;
+eof_seen[index]:=false;
+grp_stack[index]:=cur_boundary; if_stack[index]:=cond_ptr;
+line_stack[index]:=line; start:=first; state:=mid_line;
+name:=0; {|terminal_input| is now |true|}
+end;
+
+@ Conversely, the variables must be downdated when such a level of input
+is finished:
+
+@p procedure end_file_reading;
+begin first:=start; line:=line_stack[index];
+if (name>=18)and(name<=20) then pseudo_close else
+if name=21 then luacstring_close(index) else
+if name>17 then lua_a_close_in(cur_file,0); {forget it}
+pop_input; decr(in_open);
+end;
+
+@ In order to keep the stack from overflowing during a long sequence of
+inserted `\.{\\show}' commands, the following routine removes completed
+error-inserted lines from memory.
+
+@p procedure clear_for_error_prompt;
+begin while (state<>token_list)and terminal_input and@|
+ (input_ptr>0)and(loc>limit) do end_file_reading;
+print_ln; clear_terminal;
+end;
+
+@ To get \TeX's whole input mechanism going, we perform the following
+actions.
+
+@<Initialize the input routines@>=
+begin input_ptr:=0; max_in_stack:=0;
+in_open:=0; open_parens:=0; max_buf_stack:=0;
+grp_stack[0]:=0; if_stack[0]:=null;
+param_ptr:=0; max_param_stack:=0;
+first:=buf_size; repeat buffer[first]:=0; decr(first); until first=0;
+scanner_status:=normal; warning_index:=null; first:=1;
+state:=new_line; start:=1; index:=0; line:=0; name:=0;
+current_ocp_lstack:=0; current_ocp_no:=0; nofilter:=false;
+force_eof:=false; luacstrings :=0;
+align_state:=1000000;@/
+if not init_terminal then goto final_end;
+limit:=last; first:=last+1; {|init_terminal| has set |loc| and |last|}
+end
+
+@* \[24] Getting the next token.
+The heart of \TeX's input mechanism is the |get_next| procedure, which
+we shall develop in the next few sections of the program. Perhaps we
+shouldn't actually call it the ``heart,'' however, because it really acts
+as \TeX's eyes and mouth, reading the source files and gobbling them up.
+And it also helps \TeX\ to regurgitate stored token lists that are to be
+processed again.
+@^eyes and mouth@>
+
+The main duty of |get_next| is to input one token and to set |cur_cmd|
+and |cur_chr| to that token's command code and modifier. Furthermore, if
+the input token is a control sequence, the |eqtb| location of that control
+sequence is stored in |cur_cs|; otherwise |cur_cs| is set to zero.
+
+Underlying this simple description is a certain amount of complexity
+because of all the cases that need to be handled.
+However, the inner loop of |get_next| is reasonably short and fast.
+
+When |get_next| is asked to get the next token of a \.{\\read} line,
+it sets |cur_cmd=cur_chr=cur_cs=0| in the case that no more tokens
+appear on that line. (There might not be any tokens at all, if the
+|end_line_char| has |ignore| as its catcode.)
+
+@ The value of |par_loc| is the |eqtb| address of `\.{\\par}'. This quantity
+is needed because a blank line of input is supposed to be exactly equivalent
+to the appearance of \.{\\par}; we must set |cur_cs:=par_loc|
+when detecting a blank line.
+
+@<Glob...@>=
+@!par_loc:pointer; {location of `\.{\\par}' in |eqtb|}
+@!par_token:halfword; {token representing `\.{\\par}'}
+
+@ @<Put each...@>=
+primitive("par",par_end,too_big_char); {cf. |scan_file_name|}
+@!@:par_}{\.{\\par} primitive@>
+par_loc:=cur_val; par_token:=cs_token_flag+par_loc;
+
+@ @<Cases of |print_cmd_chr|...@>=
+par_end:print_esc("par");
+
+@ The function |get_next| is now defined in |textoken.c|. Parts of
+this routine are executed more often than any other instructions of \TeX.
+@^mastication@>@^inner loop@>
+
+@ The global variable |force_eof| is normally |false|; it is set |true|
+by an \.{\\endinput} command. |luacstrings| is the number of lua print
+statements waiting to be input, it is changed by |luatokencall|.
+
+|no_expand_flag| is a special character value that is inserted by
+|get_next| if it wants to suppress expansion.
+
+@d no_expand_flag==special_char {this characterizes a special variant of |relax|}
+@d end_line_char_inactive==(end_line_char<0)or(end_line_char>127)
+
+
+@<Glob...@>=
+@!force_eof:boolean; {should the next \.{\\input} be aborted early?}
+@!luacstrings:integer; {how many lua strings are waiting to be input?}
+
+@ If the user has set the |pausing| parameter to some positive value,
+and if nonstop mode has not been selected, each line of input is displayed
+on the terminal and the transcript file, followed by `\.{=>}'.
+\TeX\ waits for a response. If the response is simply |carriage_return|, the
+line is accepted as it stands, otherwise the line typed is
+used instead of the line in the file.
+
+@p procedure firm_up_the_line;
+var k:0..buf_size; {an index into |buffer|}
+begin limit:=last;
+if pausing>0 then if interaction>nonstop_mode then
+ begin wake_up_terminal; print_ln;
+ if start<limit then for k:=start to limit-1 do print(buffer[k]);
+ first:=limit; prompt_input("=>"); {wait for user response}
+@.=>@>
+ if last>first then
+ begin for k:=first to last-1 do {move line down in buffer}
+ buffer[k+start-first]:=buffer[k];
+ limit:=start+last-first;
+ end;
+ end;
+end;
+
+@ Since |get_next| is used so frequently in \TeX, it is convenient
+to define three related procedures that do a little more:
+
+\yskip\hang|get_token| not only sets |cur_cmd| and |cur_chr|, it
+also sets |cur_tok|, a packed halfword version of the current token.
+
+\yskip\hang|get_x_token|, meaning ``get an expanded token,'' is like
+|get_token|, but if the current token turns out to be a user-defined
+control sequence (i.e., a macro call), or a conditional,
+or something like \.{\\topmark} or \.{\\expandafter} or \.{\\csname},
+it is eliminated from the input by beginning the expansion of the macro
+or the evaluation of the conditional.
+
+\yskip\hang|x_token| is like |get_x_token| except that it assumes that
+|get_next| has already been called.
+
+\yskip\noindent
+In fact, these three procedures account for {\sl all\/} uses of |get_next|,
+except for two places in the ``inner loop'' when |cur_tok| need not be set,
+and except when the arguments to \.{\\ifx} are being scanned.
+
+@ No new control sequences will be defined except during a call of
+|get_token|, or when \.{\\csname} compresses a token list, because
+|no_new_control_sequence| is always |true| at other times.
+
+@p procedure get_token; {sets |cur_cmd|, |cur_chr|, |cur_tok|}
+begin no_new_control_sequence:=false; get_filtered_next; no_new_control_sequence:=true;
+@^inner loop@>
+if cur_cs=0 then cur_tok:=(cur_cmd*string_offset)+cur_chr
+else cur_tok:=cs_token_flag+cur_cs;
+end;
+
+@* \[25] Expanding the next token.
+Only a dozen or so command codes |>max_command| can possibly be returned by
+|get_next|; in increasing order, they are |undefined_cs|, |expand_after|,
+|no_expand|, |input|, |if_test|, |fi_or_else|, |cs_name|, |convert|, |the|,
+|top_bot_mark|, |call|, |long_call|, |outer_call|, |long_outer_call|, and
+|end_template|.{\emergencystretch=40pt\par}
+
+@ Sometimes, recursive calls to the following |expand| routine may
+cause exhaustion of the run-time calling stack, resulting in
+forced execution stops by the operating system. To diminish the chance
+of this happening, a counter is used to keep track of the recursion
+depth, in conjunction with a constant called |expand_depth|.
+
+Note that this does not catch all possible infinite recursion loops,
+just the ones that exhaust the application calling stack. The
+actual maximum value of |expand_depth| is outside of our control, but
+the initial setting of |100| should be enough to prevent problems.
+@^system dependencies@>
+
+@<Global...@>=
+expand_depth_count:integer;
+
+@ @<Initialize whatever ...@>=
+expand_depth_count:=0;
+
+@ The |expand| subroutine is used when |cur_cmd>max_command|. It removes a
+``call'' or a conditional or one of the other special operations just
+listed. It follows that |expand| might invoke itself recursively. In all
+cases, |expand| destroys the current token, but it sets things up so that
+the next |get_next| will deliver the appropriate next token. The value of
+|cur_tok| need not be known when |expand| is called.
+
+Since several of the basic scanning routines communicate via global variables,
+their values are saved as local variables of |expand| so that
+recursive calls don't invalidate them.
+@^recursion@>
+
+@p@t\4@>@<Declare the procedure called |macro_call|@>@;@/
+@t\4@>@<Declare the procedure called |insert_relax|@>@;@/
+@t\4@>@<Declare \eTeX\ procedures for expanding@>@;@/
+procedure@?pass_text; forward;@t\2@>
+procedure@?start_input; forward;@t\2@>
+procedure@?conditional; forward;@t\2@>
+procedure@?get_x_token; forward;@t\2@>
+procedure@?conv_toks; forward;@t\2@>
+procedure@?ins_the_toks; forward;@t\2@>
+procedure expand;
+label reswitch;
+var t:halfword; {token that is being ``expanded after''}
+@!p,@!q,@!r:pointer; {for list manipulation}
+@!cur_ptr:pointer; { for a local token list pointer }
+@!j:0..buf_size; {index into |buffer|}
+@!s:ASCII_code; { a character }
+@!cv_backup:integer; {to save the global quantity |cur_val|}
+@!cvl_backup,@!radix_backup,@!co_backup:small_number;
+ {to save |cur_val_level|, etc.}
+@!backup_backup:pointer; {to save |link(backup_head)|}
+@!save_scanner_status:small_number; {temporary storage of |scanner_status|}
+begin
+incr(expand_depth_count);
+if expand_depth_count>=expand_depth then overflow("expansion depth",expand_depth);
+cv_backup:=cur_val; cvl_backup:=cur_val_level; radix_backup:=radix;
+co_backup:=cur_order; backup_backup:=link(backup_head);
+reswitch:
+if cur_cmd<call then @<Expand a nonmacro@>
+else if cur_cmd<end_template then macro_call
+else @<Insert a token containing |frozen_endv|@>;
+cur_val:=cv_backup; cur_val_level:=cvl_backup; radix:=radix_backup;
+cur_order:=co_backup; link(backup_head):=backup_backup;
+decr(expand_depth_count);
+end;
+
+@ @<Glob...@>=
+@!is_in_csname: boolean;
+
+@ @<Set init...@>=
+is_in_csname := false;
+
+@ @<Expand a nonmacro@>=
+begin if tracing_commands>1 then show_cur_cmd_chr;
+case cur_cmd of
+top_bot_mark:@<Insert the \(a)appropriate mark text into the scanner@>;
+expand_after:if cur_chr=0 then @<Expand the token after the next token@>
+ else @<Negate a boolean conditional and |goto reswitch|@>;
+no_expand: if cur_chr=0 then @<Suppress expansion of the next token@>
+ else @<Implement \.{\\primitive}@>;
+cs_name:@<Manufacture a control sequence name@>;
+convert:conv_toks; {this procedure is discussed in Part 27 below}
+the:ins_the_toks; {this procedure is discussed in Part 27 below}
+if_test:conditional; {this procedure is discussed in Part 28 below}
+fi_or_else:@<Terminate the current conditional and skip to \.{\\fi}@>;
+input:@<Initiate or terminate input from a file@>;
+othercases @<Complain about an undefined macro@>
+endcases;
+end
+
+@ It takes only a little shuffling to do what \TeX\ calls \.{\\expandafter}.
+
+@<Expand the token after...@>=
+begin get_token; t:=cur_tok; get_token;
+if cur_cmd>max_command then expand@+else back_input;
+cur_tok:=t; back_input;
+end
+
+@ The implementation of \.{\\noexpand} is a bit trickier, because it is
+necessary to insert a special `|dont_expand|' marker into \TeX's reading
+mechanism. This special marker is processed by |get_next|, but it does
+not slow down the inner loop.
+
+Since \.{\\outer} macros might arise here, we must also
+clear the |scanner_status| temporarily.
+
+@<Suppress expansion...@>=
+begin save_scanner_status:=scanner_status; scanner_status:=normal;
+get_token; scanner_status:=save_scanner_status; t:=cur_tok;
+back_input; {now |start| and |loc| point to the backed-up token |t|}
+if t>=cs_token_flag then
+ begin p:=get_avail; info(p):=cs_token_flag+frozen_dont_expand;
+ link(p):=loc; start:=p; loc:=p;
+ end;
+end
+
+@ The \.{\\primitive} handling. If the primitive meaning of the next
+token is an expandable command, it suffices to replace the current
+token with the primitive one and restart |expand|.
+
+Otherwise, the token we just read has to be pushed back, as well
+as a token matching the internal form of \.{\\primitive}, that is
+sneaked in as an alternate form of |ignore_spaces|.
+@!@:primitive_}{\.{\\primitive} primitive (internalized)@>
+
+An implementation problem surfaces: There really is no |cur_cs|
+attached to the inserted primitive command, so it is safer to set
+|cur_cs| to zero. |cur_tok| has a similar problem. And for the
+non-expanded branch, simply pushing back a token that matches the
+correct internal command does not work, because that approach would
+not survive roundtripping to a temporary file or even a token list.
+
+In a next version, it would be smart to create |frozen_| versions of
+all the primitives. Then, this problem would not happen, at the
+expense of a few hundred extra control sequences.
+
+@<Implement \.{\\primitive}@>=
+begin save_scanner_status := scanner_status; scanner_status:=normal;
+get_token; scanner_status:=save_scanner_status;
+cur_cs := prim_lookup(text(cur_cs));
+if cur_cs<>undefined_primitive then begin
+ t:=get_prim_eq_type(cur_cs);
+ if t>max_command then begin
+ cur_cmd := t;
+ cur_chr := get_prim_equiv(cur_cs);
+ cur_tok := (cur_cmd*string_offset)+cur_chr;
+ cur_cs := 0;
+ goto reswitch;
+ end
+ else begin
+ back_input; { now |loc| and |start| point to a one-item list }
+ p:=get_avail; info(p):=cs_token_flag+frozen_primitive;
+ link(p):=loc; loc:=p; start:=p;
+ end;
+ end;
+end
+
+@ @<Complain about an undefined macro@>=
+begin print_err("Undefined control sequence");
+@.Undefined control sequence@>
+help5("The control sequence at the end of the top line")@/
+("of your error message was never \def'ed. If you have")@/
+("misspelled it (e.g., `\hobx'), type `I' and the correct")@/
+("spelling (e.g., `I\hbox'). Otherwise just continue,")@/
+("and I'll forget about whatever was undefined.");
+error;
+end
+
+@ The |expand| procedure and some other routines that construct token
+lists find it convenient to use the following macros, which are valid only if
+the variables |p| and |q| are reserved for token-list building.
+
+@d store_new_token(#)==begin q:=get_avail; link(p):=q; info(q):=#;
+ p:=q; {|link(p)| is |null|}
+ end
+@d fast_store_new_token(#)==begin fast_get_avail(q); link(p):=q; info(q):=#;
+ p:=q; {|link(p)| is |null|}
+ end
+
+@ @<Manufacture a control...@>=
+begin r:=get_avail; p:=r; {head of the list of characters}
+is_in_csname := true;
+repeat get_x_token;
+if cur_cs=0 then store_new_token(cur_tok);
+until cur_cs<>0;
+if cur_cmd<>end_cs_name then @<Complain about missing \.{\\endcsname}@>;
+is_in_csname := false;
+@<Look up the characters of list |r| in the hash table, and set |cur_cs|@>;
+flush_list(r);
+if eq_type(cur_cs)=undefined_cs then
+ begin eq_define(cur_cs,relax,too_big_char); {N.B.: The |save_stack| might change}
+ end; {the control sequence will now match `\.{\\relax}'}
+cur_tok:=cur_cs+cs_token_flag; back_input;
+end
+
+@ @<Complain about missing \.{\\endcsname}@>=
+begin print_err("Missing "); print_esc("endcsname"); print(" inserted");
+@.Missing \\endcsname...@>
+help2("The control sequence marked <to be read again> should")@/
+ ("not appear between \csname and \endcsname.");
+back_error;
+end
+
+@ @<Look up the characters of list |r| in the hash table...@>=
+j:=first; p:=link(r);
+while p<>null do
+ begin if j>=max_buf_stack then
+ begin max_buf_stack:=j+4;
+ if max_buf_stack=buf_size then
+ check_buffer_overflow(max_buf_stack);
+@:TeX capacity exceeded buffer size}{\quad buffer size@>
+ end;
+ s := info(p) mod string_offset;
+ if s <= @"7F then begin
+ buffer[j]:=s; incr(j);
+ end
+ else if s<=@"7FF then begin
+ buffer[j]:=@"C0 + s div @"40; incr(j);
+ buffer[j]:=@"80 + s mod @"40; incr(j);
+ end
+ else if s<=@"FFFF then begin
+ buffer[j]:=@"E0 + s div @"1000; incr(j);
+ buffer[j]:=@"80 + (s mod @"1000) div @"40; incr(j);
+ buffer[j]:=@"80 + (s mod @"1000) mod @"40; incr(j);
+ end
+ else begin
+ buffer[j]:=@"F0 + s div @"40000; incr(j);
+ buffer[j]:=@"80 + (s mod @"40000) div @"1000; incr(j);
+ buffer[j]:=@"80 + ((s mod @"40000) mod @"1000) div @"40; incr(j);
+ buffer[j]:=@"80 + ((s mod @"40000) mod @"1000) mod @"40; incr(j);
+ end;
+ p:=link(p);
+ end;
+if j>first then
+ begin no_new_control_sequence:=false; cur_cs:=id_lookup(first,j-first);
+ no_new_control_sequence:=true;
+ end
+else if j=first then cur_cs:=null_cs {the list is empty}
+
+@ An |end_template| command is effectively changed to an |endv| command
+by the following code. (The reason for this is discussed below; the
+|frozen_end_template| at the end of the template has passed the
+|check_outer_validity| test, so its mission of error detection has been
+accomplished.)
+
+@<Insert a token containing |frozen_endv|@>=
+begin cur_tok:=cs_token_flag+frozen_endv; back_input;
+end
+
+@ The processing of \.{\\input} involves the |start_input| subroutine,
+which will be declared later; the processing of \.{\\endinput} is trivial.
+
+@<Put each...@>=
+primitive("input",input,0);@/
+@!@:input_}{\.{\\input} primitive@>
+primitive("endinput",input,1);@/
+@!@:end_input_}{\.{\\endinput} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+input: if chr_code=0 then print_esc("input")
+ @/@<Cases of |input| for |print_cmd_chr|@>@/
+ else print_esc("endinput");
+
+@ @<Initiate or terminate input...@>=
+if cur_chr=1 then force_eof:=true
+@/@<Cases for |input|@>@/
+else if name_in_progress then insert_relax
+else start_input
+
+@ Sometimes the expansion looks too far ahead, so we want to insert
+a harmless \.{\\relax} into the user's input.
+
+@<Declare the procedure called |insert_relax|@>=
+procedure insert_relax;
+begin cur_tok:=cs_token_flag+cur_cs; back_input;
+cur_tok:=cs_token_flag+frozen_relax; back_input; token_type:=inserted;
+end;
+
+@ Here is a recursive procedure that is \TeX's usual way to get the
+next token of input. It has been slightly optimized to take account of
+common cases.
+
+@p procedure get_x_token; {sets |cur_cmd|, |cur_chr|, |cur_tok|,
+ and expands macros}
+label restart,done;
+begin restart: get_filtered_next;
+@^inner loop@>
+if cur_cmd<=max_command then goto done;
+if cur_cmd>=call then
+ if cur_cmd<end_template then macro_call
+ else begin cur_cs:=frozen_endv; cur_cmd:=endv;
+ goto done; {|cur_chr=null_list|}
+ end
+else expand;
+goto restart;
+done: if cur_cs=0 then cur_tok:=(cur_cmd*string_offset)+cur_chr
+else cur_tok:=cs_token_flag+cur_cs;
+end;
+
+@ The |get_x_token| procedure is equivalent to two consecutive
+procedure calls: |get_next; x_token|.
+
+@p procedure x_token; {|get_x_token| without the initial |get_next|}
+begin while cur_cmd>max_command do
+ begin expand;
+ get_filtered_next;
+ end;
+if cur_cs=0 then cur_tok:=(cur_cmd*string_offset)+cur_chr
+else cur_tok:=cs_token_flag+cur_cs;
+end;
+
+@ The |get_filtered_next| procedure allows Lua code to mutate the
+output of |get_next| before \TeX\ looks at it. The implementation
+is in the C file |luatoken.c|.
+
+@d get_filtered_next==get_token_lua
+
+
+
+@ A control sequence that has been \.{\\def}'ed by the user is expanded by
+\TeX's |macro_call| procedure.
+
+Before we get into the details of |macro_call|, however, let's consider the
+treatment of primitives like \.{\\topmark}, since they are essentially
+macros without parameters. The token lists for such marks are kept in five
+global arrays of pointers; we refer to the individual entries of these
+arrays by symbolic macros |top_mark|, etc. The value of |top_mark(x)|, etc.
+is either |null| or a pointer to the reference count of a token list.
+
+The variable |biggest_used_mark| is an aid to try and keep the code
+somehwat efficient without too much extra work: it registers the
+highest mark class ever instantiated by the user, so the loops
+in |fire_up| and |vsplit| do not have to traverse the full range
+|0..biggest_mark|.
+
+@d top_mark_code=0 {the mark in effect at the previous page break}
+@d first_mark_code=1 {the first mark between |top_mark| and |bot_mark|}
+@d bot_mark_code=2 {the mark in effect at the current page break}
+@d split_first_mark_code=3 {the first mark found by \.{\\vsplit}}
+@d split_bot_mark_code=4 {the last mark found by \.{\\vsplit}}
+@#
+@d top_mark(#)==top_marks_array[#]
+@d first_mark(#)==first_marks_array[#]
+@d bot_mark(#)==bot_marks_array[#]
+@d split_first_mark(#)==split_first_marks_array[#]
+@d split_bot_mark(#)==split_bot_marks_array[#]
+@#
+@d delete_top_mark(#)==begin if top_mark(#)<>null then
+ delete_token_ref(top_mark(#)); top_mark(#):=null; end
+@d delete_bot_mark(#)==begin if bot_mark(#)<>null then
+ delete_token_ref(bot_mark(#)); bot_mark(#):=null; end
+@d delete_first_mark(#)==begin if first_mark(#)<>null then
+ delete_token_ref(first_mark(#)); first_mark(#):=null; end
+@d delete_split_first_mark(#)==begin if split_first_mark(#)<>null then
+ delete_token_ref(split_first_mark(#)); split_first_mark(#):=null; end
+@d delete_split_bot_mark(#)==begin if split_bot_mark(#)<>null then
+ delete_token_ref(split_bot_mark(#)); split_bot_mark(#):=null; end
+@#
+@d clear_marks_code=1
+@d marks_code=5
+@#
+
+@<Glob...@>=
+@!top_marks_array:array[0..biggest_mark] of pointer;
+@!first_marks_array:array[0..biggest_mark] of pointer;
+@!bot_marks_array:array[0..biggest_mark] of pointer;
+@!split_first_marks_array:array[0..biggest_mark] of pointer;
+@!split_bot_marks_array:array[0..biggest_mark] of pointer;
+biggest_used_mark:halfword;
+
+@ @<Set init...@>=
+biggest_used_mark:=0;
+for i:=0 to biggest_mark do begin
+ top_mark(i):=null;
+ first_mark(i):=null;
+ bot_mark(i):=null;
+ split_first_mark(i):=null;
+ split_bot_mark(i):=null;
+end;
+
+@ @<Put each...@>=
+primitive("topmark",top_bot_mark,top_mark_code);
+@!@:top_mark_}{\.{\\topmark} primitive@>
+primitive("firstmark",top_bot_mark,first_mark_code);
+@!@:first_mark_}{\.{\\firstmark} primitive@>
+primitive("botmark",top_bot_mark,bot_mark_code);
+@!@:bot_mark_}{\.{\\botmark} primitive@>
+primitive("splitfirstmark",top_bot_mark,split_first_mark_code);
+@!@:split_first_mark_}{\.{\\splitfirstmark} primitive@>
+primitive("splitbotmark",top_bot_mark,split_bot_mark_code);
+@!@:split_bot_mark_}{\.{\\splitbotmark} primitive@>
+primitive("clearmarks",mark,clear_marks_code);@/
+@!@:clearmarks_}{\.{\\clearmarks} primitive@>
+primitive("marks",mark,marks_code);
+@!@:marks_}{\.{\\marks} primitive@>
+primitive("topmarks",top_bot_mark,top_mark_code+marks_code);
+@!@:top_marks_}{\.{\\topmarks} primitive@>
+primitive("firstmarks",top_bot_mark,first_mark_code+marks_code);
+@!@:first_marks_}{\.{\\firstmarks} primitive@>
+primitive("botmarks",top_bot_mark,bot_mark_code+marks_code);
+@!@:bot_marks_}{\.{\\botmarks} primitive@>
+primitive("splitfirstmarks",top_bot_mark,split_first_mark_code+marks_code);
+@!@:split_first_marks_}{\.{\\splitfirstmarks} primitive@>
+primitive("splitbotmarks",top_bot_mark,split_bot_mark_code+marks_code);
+@!@:split_bot_marks_}{\.{\\splitbotmarks} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+top_bot_mark: begin case (chr_code mod marks_code) of
+ first_mark_code: print_esc("firstmark");
+ bot_mark_code: print_esc("botmark");
+ split_first_mark_code: print_esc("splitfirstmark");
+ split_bot_mark_code: print_esc("splitbotmark");
+ othercases print_esc("topmark")
+ endcases;
+ if chr_code>=marks_code then print_char("s");
+ end;
+
+@ The following code is activated when |cur_cmd=top_bot_mark| and
+when |cur_chr| is a code like |top_mark_code|.
+
+@<Insert the \(a)appropriate mark text into the scanner@>=
+begin t:=cur_chr mod marks_code;
+if cur_chr>=marks_code then scan_mark_num@+else cur_val:=0;
+case t of
+ first_mark_code: cur_ptr:=first_mark(cur_val);
+ bot_mark_code: cur_ptr:=bot_mark(cur_val);
+ split_first_mark_code: cur_ptr:=split_first_mark(cur_val);
+ split_bot_mark_code: cur_ptr:=split_bot_mark(cur_val);
+ othercases cur_ptr:=top_mark(cur_val)
+endcases;
+if cur_ptr<>null then begin_token_list(cur_ptr,mark_text);
+end
+
+@ Now let's consider |macro_call| itself, which is invoked when \TeX\ is
+scanning a control sequence whose |cur_cmd| is either |call|, |long_call|,
+|outer_call|, or |long_outer_call|. The control sequence definition
+appears in the token list whose reference count is in location |cur_chr|
+of |mem|.
+
+The global variable |long_state| will be set to |call| or to |long_call|,
+depending on whether or not the control sequence disallows \.{\\par}
+in its parameters. The |get_next| routine will set |long_state| to
+|outer_call| and emit \.{\\par}, if a file ends or if an \.{\\outer}
+control sequence occurs in the midst of an argument.
+
+@<Glob...@>=
+@!long_state:call..long_outer_call; {governs the acceptance of \.{\\par}}
+
+@ The parameters, if any, must be scanned before the macro is expanded.
+Parameters are token lists without reference counts. They are placed on
+an auxiliary stack called |pstack| while they are being scanned, since
+the |param_stack| may be losing entries during the matching process.
+(Note that |param_stack| can't be gaining entries, since |macro_call| is
+the only routine that puts anything onto |param_stack|, and it
+is not recursive.)
+
+@<Glob...@>=
+@!pstack:array[0..8] of pointer; {arguments supplied to a macro}
+
+@ After parameter scanning is complete, the parameters are moved to the
+|param_stack|. Then the macro body is fed to the scanner; in other words,
+|macro_call| places the defined text of the control sequence at the
+top of\/ \TeX's input stack, so that |get_next| will proceed to read it
+next.
+
+The global variable |cur_cs| contains the |eqtb| address of the control sequence
+being expanded, when |macro_call| begins. If this control sequence has not been
+declared \.{\\long}, i.e., if its command code in the |eq_type| field is
+not |long_call| or |long_outer_call|, its parameters are not allowed to contain
+the control sequence \.{\\par}. If an illegal \.{\\par} appears, the macro
+call is aborted, and the \.{\\par} will be rescanned.
+
+@<Declare the procedure called |macro_call|@>=
+procedure macro_call; {invokes a user-defined control sequence}
+label exit, continue, done, done1, found;
+var r:pointer; {current node in the macro's token list}
+@!p:pointer; {current node in parameter token list being built}
+@!q:pointer; {new node being put into the token list}
+@!s:pointer; {backup pointer for parameter matching}
+@!t:pointer; {cycle pointer for backup recovery}
+@!u,@!v:pointer; {auxiliary pointers for backup recovery}
+@!rbrace_ptr:pointer; {one step before the last |right_brace| token}
+@!n:small_number; {the number of parameters scanned}
+@!unbalance:halfword; {unmatched left braces in current parameter}
+@!m:halfword; {the number of tokens or groups (usually)}
+@!ref_count:pointer; {start of the token list}
+@!save_scanner_status:small_number; {|scanner_status| upon entry}
+@!save_warning_index:pointer; {|warning_index| upon entry}
+@!match_chr:ASCII_code; {character used in parameter}
+begin save_scanner_status:=scanner_status; save_warning_index:=warning_index;
+warning_index:=cur_cs; ref_count:=cur_chr; r:=link(ref_count); n:=0;
+p:=null; m:=0; rbrace_ptr:=null; match_chr:=0;
+if tracing_macros>0 then @<Show the text of the macro being expanded@>;
+if info(r)=protected_token then r:=link(r);
+if info(r)<>end_match_token then
+ @<Scan the parameters and make |link(r)| point to the macro body; but
+ |return| if an illegal \.{\\par} is detected@>;
+@<Feed the macro body and its parameters to the scanner@>;
+exit:scanner_status:=save_scanner_status; warning_index:=save_warning_index;
+end;
+
+@ Before we put a new token list on the input stack, it is wise to clean off
+all token lists that have recently been depleted. Then a user macro that ends
+with a call to itself will not require unbounded stack space.
+
+@<Feed the macro body and its parameters to the scanner@>=
+while (state=token_list)and(loc=null)and(token_type<>v_template) do
+ end_token_list; {conserve stack space}
+begin_token_list(ref_count,macro); name:=warning_index; loc:=link(r);
+if n>0 then
+ begin if param_ptr+n>max_param_stack then
+ begin max_param_stack:=param_ptr+n;
+ if max_param_stack>param_size then
+ overflow("parameter stack size",param_size);
+@:TeX capacity exceeded parameter stack size}{\quad parameter stack size@>
+ end;
+ for m:=0 to n-1 do param_stack[param_ptr+m]:=pstack[m];
+ param_ptr:=param_ptr+n;
+ end
+
+@ At this point, the reader will find it advisable to review the explanation
+of token list format that was presented earlier, since many aspects of that
+format are of importance chiefly in the |macro_call| routine.
+
+The token list might begin with a string of compulsory tokens before the
+first |match| or |end_match|. In that case the macro name is supposed to be
+followed by those tokens; the following program will set |s=null| to
+represent this restriction. Otherwise |s| will be set to the first token of
+a string that will delimit the next parameter.
+
+@<Scan the parameters and make |link(r)| point to the macro body...@>=
+begin scanner_status:=matching; unbalance:=0;
+long_state:=eq_type(cur_cs);
+if long_state>=outer_call then long_state:=long_state-2;
+repeat link(temp_token_head):=null;
+if (info(r)>=end_match_token)or(info(r)<match_token) then s:=null
+else begin match_chr:=info(r)-match_token; s:=link(r); r:=s;
+ p:=temp_token_head; m:=0;
+ end;
+@<Scan a parameter until its delimiter string has been found; or, if |s=null|,
+ simply scan the delimiter string@>;@/
+{now |info(r)| is a token whose command code is either |match| or |end_match|}
+until info(r)=end_match_token;
+end
+
+@ If |info(r)| is a |match| or |end_match| command, it cannot be equal to
+any token found by |get_token|. Therefore an undelimited parameter---i.e.,
+a |match| that is immediately followed by |match| or |end_match|---will
+always fail the test `|cur_tok=info(r)|' in the following algorithm.
+
+@<Scan a parameter until its delimiter string has been found; or, ...@>=
+continue: get_token; {set |cur_tok| to the next token of input}
+if cur_tok=info(r) then
+ @<Advance \(r)|r|; |goto found| if the parameter delimiter has been
+ fully matched, otherwise |goto continue|@>;
+@<Contribute the recently matched tokens to the current parameter, and
+ |goto continue| if a partial match is still in effect;
+ but abort if |s=null|@>;
+if cur_tok=par_token then if long_state<>long_call then
+ @<Report a runaway argument and abort@>;
+if cur_tok<right_brace_limit then
+ if cur_tok<left_brace_limit then
+ @<Contribute an entire group to the current parameter@>
+ else @<Report an extra right brace and |goto continue|@>
+else @<Store the current token, but |goto continue| if it is
+ a blank space that would become an undelimited parameter@>;
+incr(m);
+if info(r)>end_match_token then goto continue;
+if info(r)<match_token then goto continue;
+found: if s<>null then @<Tidy up the parameter just scanned, and tuck it away@>
+
+@ @<Store the current token, but |goto continue| if it is...@>=
+begin if cur_tok=space_token then
+ if info(r)<=end_match_token then
+ if info(r)>=match_token then goto continue;
+store_new_token(cur_tok);
+end
+
+@ A slightly subtle point arises here: When the parameter delimiter ends
+with `\.{\#\{}', the token list will have a left brace both before and
+after the |end_match|\kern-.4pt. Only one of these should affect the
+|align_state|, but both will be scanned, so we must make a correction.
+
+@<Advance \(r)|r|; |goto found| if the parameter delimiter has been fully...@>=
+begin r:=link(r);
+if (info(r)>=match_token)and(info(r)<=end_match_token) then
+ begin if cur_tok<left_brace_limit then decr(align_state);
+ goto found;
+ end
+else goto continue;
+end
+
+@ @<Report an extra right brace and |goto continue|@>=
+begin back_input; print_err("Argument of "); sprint_cs(warning_index);
+@.Argument of \\x has...@>
+print(" has an extra }");
+help6("I've run across a `}' that doesn't seem to match anything.")@/
+ ("For example, `\def\a#1{...}' and `\a}' would produce")@/
+ ("this error. If you simply proceed now, the `\par' that")@/
+ ("I've just inserted will cause me to report a runaway")@/
+ ("argument that might be the root of the problem. But if")@/
+ ("your `}' was spurious, just type `2' and it will go away.");
+incr(align_state); long_state:=call; cur_tok:=par_token; ins_error;
+end {a white lie; the \.{\\par} won't always trigger a runaway}
+
+@ If |long_state=outer_call|, a runaway argument has already been reported.
+
+@<Report a runaway argument and abort@>=
+begin if long_state=call then
+ begin runaway; print_err("Paragraph ended before ");
+@.Paragraph ended before...@>
+ sprint_cs(warning_index); print(" was complete");
+ help3("I suspect you've forgotten a `}', causing me to apply this")@/
+ ("control sequence to too much text. How can we recover?")@/
+ ("My plan is to forget the whole thing and hope for the best.");
+ back_error;
+ end;
+pstack[n]:=link(temp_token_head); align_state:=align_state-unbalance;
+for m:=0 to n do flush_list(pstack[m]);
+return;
+end
+
+@ When the following code becomes active, we have matched tokens from |s| to
+the predecessor of |r|, and we have found that |cur_tok<>info(r)|. An
+interesting situation now presents itself: If the parameter is to be
+delimited by a string such as `\.{ab}', and if we have scanned `\.{aa}',
+we want to contribute one `\.a' to the current parameter and resume
+looking for a `\.b'. The program must account for such partial matches and
+for others that can be quite complex. But most of the time we have |s=r|
+and nothing needs to be done.
+
+Incidentally, it is possible for \.{\\par} tokens to sneak in to certain
+parameters of non-\.{\\long} macros. For example, consider a case like
+`\.{\\def\\a\#1\\par!\{...\}}' where the first \.{\\par} is not followed
+by an exclamation point. In such situations it does not seem appropriate
+to prohibit the \.{\\par}, so \TeX\ keeps quiet about this bending of
+the rules.
+
+@<Contribute the recently matched tokens to the current parameter...@>=
+if s<>r then
+ if s=null then @<Report an improper use of the macro and abort@>
+ else begin t:=s;
+ repeat store_new_token(info(t)); incr(m); u:=link(t); v:=s;
+ loop@+ begin if u=r then
+ if cur_tok<>info(v) then goto done
+ else begin r:=link(v); goto continue;
+ end;
+ if info(u)<>info(v) then goto done;
+ u:=link(u); v:=link(v);
+ end;
+ done: t:=link(t);
+ until t=r;
+ r:=s; {at this point, no tokens are recently matched}
+ end
+
+@ @<Report an improper use...@>=
+begin print_err("Use of "); sprint_cs(warning_index);
+@.Use of x doesn't match...@>
+print(" doesn't match its definition");
+help4("If you say, e.g., `\def\a1{...}', then you must always")@/
+ ("put `1' after `\a', since control sequence names are")@/
+ ("made up of letters only. The macro here has not been")@/
+ ("followed by the required stuff, so I'm ignoring it.");
+error; return;
+end
+
+@ @<Contribute an entire group to the current parameter@>=
+begin unbalance:=1;
+@^inner loop@>
+loop@+ begin fast_store_new_token(cur_tok); get_token;
+ if cur_tok=par_token then if long_state<>long_call then
+ @<Report a runaway argument and abort@>;
+ if cur_tok<right_brace_limit then
+ if cur_tok<left_brace_limit then incr(unbalance)
+ else begin decr(unbalance);
+ if unbalance=0 then goto done1;
+ end;
+ end;
+done1: rbrace_ptr:=p; store_new_token(cur_tok);
+end
+
+@ If the parameter consists of a single group enclosed in braces, we must
+strip off the enclosing braces. That's why |rbrace_ptr| was introduced.
+
+@<Tidy up the parameter just scanned, and tuck it away@>=
+begin if (m=1)and(info(p)<right_brace_limit)and(p<>temp_token_head) then
+ begin link(rbrace_ptr):=null; free_avail(p);
+ p:=link(temp_token_head); pstack[n]:=link(p); free_avail(p);
+ end
+else pstack[n]:=link(temp_token_head);
+incr(n);
+if tracing_macros>0 then
+ begin begin_diagnostic; print_nl(match_chr); print_int(n);
+ print("<-"); show_token_list(pstack[n-1],null,1000);
+ end_diagnostic(false);
+ end;
+end
+
+@ @<Show the text of the macro being expanded@>=
+begin begin_diagnostic; print_ln; print_cs(warning_index);
+token_show(ref_count); end_diagnostic(false);
+end
+
+@* \[26] Basic scanning subroutines.
+Let's turn now to some procedures that \TeX\ calls upon frequently to digest
+certain kinds of patterns in the input. Most of these are quite simple;
+some are quite elaborate. Almost all of the routines call |get_x_token|,
+which can cause them to be invoked recursively.
+@^stomach@>
+@^recursion@>
+
+@ The |scan_left_brace| routine is called when a left brace is supposed to be
+the next non-blank token. (The term ``left brace'' means, more precisely,
+a character whose catcode is |left_brace|.) \TeX\ allows \.{\\relax} to
+appear before the |left_brace|.
+
+@p procedure scan_left_brace; {reads a mandatory |left_brace|}
+begin @<Get the next non-blank non-relax non-call token@>;
+if cur_cmd<>left_brace then
+ begin print_err("Missing { inserted");
+@.Missing \{ inserted@>
+ help4("A left brace was mandatory here, so I've put one in.")@/
+ ("You might want to delete and/or insert some corrections")@/
+ ("so that I will find a matching right brace soon.")@/
+ ("(If you're confused by all this, try typing `I}' now.)");
+ back_error; cur_tok:=left_brace_token+"{"; cur_cmd:=left_brace;
+ cur_chr:="{"; incr(align_state);
+ end;
+end;
+
+@ The |scan_right_brace| routine is called when a right brace is supposed to be
+the next non-blank token. (The term ``right brace'' means, more precisely,
+a character whose catcode is |right_brace|.) \TeX\ allows \.{\\relax} to
+appear before the |right_brace|.
+
+@p procedure scan_right_brace; {reads a mandatory |right_brace|}
+begin @<Get the next non-blank non-relax non-call token@>;
+if cur_cmd<>right_brace then
+ begin print_err("Missing { inserted");
+@.Missing \{ inserted@>
+ help4("A right brace was mandatory here, so I've put one in.")@/
+ ("You might want to delete and/or insert some corrections")@/
+ ("so that I will find a matching right brace soon.")@/
+ ("(If you're confused by all this, try typing `I}' now.)");
+ back_error; cur_tok:=right_brace_token+"}"; cur_cmd:=right_brace;
+ cur_chr:="}"; incr(align_state);
+ end;
+end;
+
+@ @<Get the next non-blank non-relax non-call token@>=
+repeat get_x_token;
+until (cur_cmd<>spacer)and(cur_cmd<>relax)
+
+@ The |scan_optional_equals| routine looks for an optional `\.=' sign preceded
+by optional spaces; `\.{\\relax}' is not ignored here.
+
+@p procedure scan_optional_equals;
+begin @<Get the next non-blank non-call token@>;
+if cur_tok<>other_token+"=" then back_input;
+end;
+
+@ @<Get the next non-blank non-call token@>=
+repeat get_x_token;
+until cur_cmd<>spacer
+
+@ In case you are getting bored, here is a slightly less trivial routine:
+Given a string of lowercase letters, like `\.{pt}' or `\.{plus}' or
+`\.{width}', the |scan_keyword| routine checks to see whether the next
+tokens of input match this string. The match must be exact, except that
+uppercase letters will match their lowercase counterparts; uppercase
+equivalents are determined by subtracting |"a"-"A"|, rather than using the
+|uc_code| table, since \TeX\ uses this routine only for its own limited
+set of keywords.
+
+If a match is found, the characters are effectively removed from the input
+and |true| is returned. Otherwise |false| is returned, and the input
+is left essentially unchanged (except for the fact that some macros
+may have been expanded, etc.).
+@^inner loop@>
+
+@p function scan_keyword(@!s:str_number):boolean; {look for a given string}
+label exit;
+var p:pointer; {tail of the backup list}
+@!q:pointer; {new node being added to the token list via |store_new_token|}
+@!k:pool_pointer; {index into |str_pool|}
+begin
+if s<number_chars then begin
+ @<Get the next non-blank non-call token@>;
+ if (cur_cs=0)and((cur_chr=s)or(cur_chr=s-"a"+"A")) then
+ scan_keyword:=true
+ else
+ begin back_input;
+ scan_keyword:=false; return;
+ end;
+ end
+else begin
+ p:=backup_head; link(p):=null;
+ k:=str_start_macro(s);
+ while k<str_start_macro(s+1) do
+ begin get_x_token; {recursion is possible here}
+@^recursion@>
+ if (cur_cs=0)and@|
+ ((cur_chr=so(str_pool[k]))or(cur_chr=so(str_pool[k])-"a"+"A")) then
+ begin store_new_token(cur_tok); incr(k);
+ end
+ else if (cur_cmd<>spacer)or(p<>backup_head) then
+ begin
+ if p<>backup_head then begin
+ q:=get_avail; info(q):=cur_tok; link(q):=null;
+ link(p) := q;
+ back_list(link(backup_head));
+ end
+ else
+ back_input;
+ scan_keyword:=false; return;
+ end;
+ end;
+ flush_list(link(backup_head)); scan_keyword:=true;
+end;
+exit:end;
+
+@ Here is a procedure that sounds an alarm when mu and non-mu units
+are being switched.
+
+@p procedure mu_error;
+begin print_err("Incompatible glue units");
+@.Incompatible glue units@>
+help1("I'm going to assume that 1mu=1pt when they're mixed.");
+error;
+end;
+
+@ The next routine `|scan_something_internal|' is used to fetch internal
+numeric quantities like `\.{\\hsize}', and also to handle the `\.{\\the}'
+when expanding constructions like `\.{\\the\\toks0}' and
+`\.{\\the\\baselineskip}'. Soon we will be considering the |scan_int|
+procedure, which calls |scan_something_internal|; on the other hand,
+|scan_something_internal| also calls |scan_int|, for constructions like
+`\.{\\catcode\`\\\$}' or `\.{\\fontdimen} \.3 \.{\\ff}'. So we
+have to declare |scan_int| as a |forward| procedure. A few other
+procedures are also declared at this point.
+
+@p procedure@?scan_int; forward; {scans an integer value}
+@t\4\4@>@<Declare procedures that scan restricted classes of integers@>@;
+@t\4\4@>@<Declare \eTeX\ procedures for scanning@>@;
+@t\4\4@>@<Declare procedures that scan font-related stuff@>
+@t\4\4@>@<Declare procedures that scan ocp-related stuff@>
+
+@ \TeX\ doesn't know exactly what to expect when
+|scan_something_internal| begins. For example, an integer or
+dimension or glue value could occur immediately after `\.{\\hskip}';
+and one can even say \.{\\the} with respect to token lists in
+constructions like `\.{\\xdef\\o\{\\the\\output\}}'. On the other
+hand, only integers are allowed after a construction like
+`\.{\\count}'. To handle the various possibilities,
+|scan_something_internal| has a |level| parameter, which tells the
+``highest'' kind of quantity that |scan_something_internal| is allowed
+to produce. Eight levels are distinguished, namely |int_val|,
+|attr_val|, |dimen_val|, |glue_val|, |mu_val|, |dir_val|, |ident_val|,
+and |tok_val|.
+
+The output of |scan_something_internal| (and of the other routines
+|scan_int|, |scan_dimen|, and |scan_glue| below) is put into the global
+variable |cur_val|, and its level is put into |cur_val_level|. The highest
+values of |cur_val_level| are special: |mu_val| is used only when
+|cur_val| points to something in a ``muskip'' register, or to one of the
+three parameters \.{\\thinmuskip}, \.{\\medmuskip}, \.{\\thickmuskip};
+|ident_val| is used only when |cur_val| points to a font identifier;
+|tok_val| is used only when |cur_val| points to |null| or to the reference
+count of a token list. The last two cases are allowed only when
+|scan_something_internal| is called with |level=tok_val|.
+
+If the output is glue, |cur_val| will point to a glue specification, and
+the reference count of that glue will have been updated to reflect this
+reference; if the output is a nonempty token list, |cur_val| will point to
+its reference count, but in this case the count will not have been updated.
+Otherwise |cur_val| will contain the integer or scaled value in question.
+
+@d int_val=0 {integer values}
+@d attr_val=1 {integer values}
+@d dimen_val=2 {dimension values}
+@d glue_val=3 {glue specifications}
+@d mu_val=4 {math glue specifications}
+@d dir_val=5 {directions}
+@d ident_val=6 {font identifier}
+@d tok_val=7 {token lists}
+
+@<Glob...@>=
+@!cur_val:integer; {value returned by numeric scanners}
+@!cur_val1:integer; {delcodes are now 51 digits}
+@!cur_val_level:int_val..tok_val; {the ``level'' of this value}
+
+@ The hash table is initialized with `\.{\\count}', `\.{\\attribute}',
+`\.{\\dimen}', `\.{\\skip}', and `\.{\\muskip}' all having |register|
+as their command code; they are distinguished by the |chr_code|, which
+is either |int_val|, |attr_val|, |dimen_val|, |glue_val|, or |mu_val|.
+
+@<Put each...@>=
+primitive("count",register,int_val);
+@!@:count_}{\.{\\count} primitive@>
+primitive("attribute",register,attr_val);
+@!@:count_}{\.{\\attribute} primitive@>
+primitive("dimen",register,dimen_val);
+@!@:dimen_}{\.{\\dimen} primitive@>
+primitive("skip",register,glue_val);
+@!@:skip_}{\.{\\skip} primitive@>
+primitive("muskip",register,mu_val);
+
+@ @<Cases of |print_cmd_chr|...@>=
+register: if chr_code=int_val then print_esc("count")
+ else if chr_code=attr_val then print_esc("attribute")
+ else if chr_code=dimen_val then print_esc("dimen")
+ else if chr_code=glue_val then print_esc("skip")
+ else print_esc("muskip");
+
+@ OK, we're ready for |scan_something_internal| itself. A second parameter,
+|negative|, is set |true| if the value that is found should be negated.
+It is assumed that |cur_cmd| and |cur_chr| represent the first token of
+the internal quantity to be scanned; an error will be signalled if
+|cur_cmd<min_internal| or |cur_cmd>max_internal|.
+
+@d scanned_result_end(#)==cur_val_level:=#;@+end
+@d scanned_result(#)==@+begin cur_val:=#;scanned_result_end
+
+@p procedure scan_something_internal(@!level:small_number;@!negative:boolean);
+ {fetch an internal parameter}
+label exit;
+var m:halfword; {|chr_code| part of the operand token}
+ n, k: integer; {accumulators}
+@!q:halfword; {general purpose index}
+@!p:0..nest_size; {index into |nest|}
+begin m:=cur_chr;
+case cur_cmd of
+def_code: @<Fetch a character code from some table@>;
+extdef_code: @<Fetch an ext character code from some table@>;
+toks_register,assign_toks,def_family,set_font,def_font,letterspace_font: @<Fetch a token list or
+ font identifier, provided that |level=tok_val|@>;
+assign_int: scanned_result(eqtb[m].int)(int_val);
+assign_attr: scanned_result(eqtb[m].int)(int_val);
+assign_box_dir: begin
+ scan_register_num;
+ m:=cur_val;
+ if box(m)<>null then cur_val:=box_dir(box(m))
+ else cur_val:=0;
+ cur_val_level:=dir_val;
+ end;
+assign_dir: scanned_result(eqtb[m].int)(dir_val);
+assign_dimen: scanned_result(eqtb[m].sc)(dimen_val);
+assign_glue: scanned_result(equiv(m))(glue_val);
+assign_mu_glue: scanned_result(equiv(m))(mu_val);
+set_aux: @<Fetch the |space_factor| or the |prev_depth|@>;
+set_prev_graf: @<Fetch the |prev_graf|@>;
+set_page_int:@<Fetch the |dead_cycles| or the |insert_penalties|@>;
+set_page_dimen: @<Fetch something on the |page_so_far|@>;
+set_shape: @<Fetch the |par_shape| size@>;
+set_box_dimen: @<Fetch a box dimension@>;
+char_given,math_given,omath_given: scanned_result(cur_chr)(int_val);
+assign_font_dimen: @<Fetch a font dimension@>;
+assign_font_int: @<Fetch a font integer@>;
+register: @<Fetch a register@>;
+last_item: @<Fetch an item in the current node, if appropriate@>;
+othercases @<Complain that \.{\\the} can't do this; give zero result@>
+endcases;@/
+while cur_val_level>level do @<Convert \(c)|cur_val| to a lower level@>;
+@<Fix the reference count, if any, and negate |cur_val| if |negative|@>;
+exit:end;
+
+procedure scan_something_simple(@!cmd:halfword;@!subitem:halfword);
+ {fetch an internal parameter}
+label exit;
+var m:halfword; {|chr_code| part of the operand token}
+@!p:0..nest_size; {index into |nest|}
+@!level:small_number; { allowed level}
+begin m:=subitem; level:=tok_val;
+case cmd of
+assign_toks: scanned_result(equiv(m))(tok_val);
+assign_int: scanned_result(eqtb[m].int)(int_val);
+assign_attr: scanned_result(eqtb[m].int)(int_val);
+assign_dir: scanned_result(eqtb[m].int)(dir_val);
+assign_dimen: scanned_result(eqtb[m].sc)(dimen_val);
+assign_glue: scanned_result(equiv(m))(glue_val);
+assign_mu_glue: scanned_result(equiv(m))(mu_val);
+set_aux: @<Fetch the |space_factor| or the |prev_depth|@>;
+set_prev_graf: @<Fetch the |prev_graf|@>;
+set_page_int:@<Fetch the |dead_cycles| or the |insert_penalties|@>;
+set_page_dimen: @<Fetch something on the |page_so_far|@>;
+set_shape: @<Fetch the |par_shape| size@>;
+char_given,math_given,omath_given: scanned_result(m)(int_val); {TH: TODO, doesnt work}
+othercases @<Complain that |texlib| can't do this; give zero result@>
+endcases;@/
+exit:end;
+
+@ @<Fetch a character code from some table@>=
+begin scan_char_num;
+if m=math_code_base then begin
+ cur_val1:=get_math_code(cur_val);
+ if ((cur_val1 div @"1000000)>8) or
+ (((cur_val1 mod @"1000000) div @"10000)>15) or
+ ((cur_val1 mod @"10000)>255) then
+ begin print_err("Extended mathchar used as mathchar");
+@.Bad mathchar@>
+ help2("A mathchar number must be between 0 and ""7FFF.")@/
+ ("I changed this one to zero."); int_error(cur_val1); cur_val1:=0;
+ end;
+ cur_val1:=((cur_val1 div @"1000000)*@"1000) +
+ (((cur_val1 mod @"1000000) div @"10000)*@"100) +
+ (cur_val1 mod @"10000);
+ scanned_result(cur_val1)(int_val);
+ end
+else if m=lc_code_base then begin
+ cur_val1:=get_lc_code(cur_val);
+ scanned_result(cur_val1)(int_val);
+ end
+else if m=uc_code_base then begin
+ cur_val1:=get_uc_code(cur_val);
+ scanned_result(cur_val1)(int_val);
+ end
+else if m=sf_code_base then begin
+ cur_val1:=get_sf_code(cur_val);
+ scanned_result(cur_val1)(int_val);
+ end
+else if m=cat_code_base then begin
+ cur_val1:=get_cat_code(cat_code_table,cur_val);
+ scanned_result(cur_val1)(int_val);
+ end
+else if m<math_code_base then scanned_result(equiv(m+cur_val))(int_val)
+else scanned_result(eqtb[m+cur_val].int)(int_val);
+end
+
+@ @<Fetch an ext character code from some table@>=
+begin scan_char_num;
+if m=math_code_base then scanned_result(get_math_code(cur_val))(int_val)
+{ TH: next two lines should not be possible }
+else if m<math_code_base then scanned_result(equiv(m+cur_val))(int_val)
+else scanned_result(eqtb[m+cur_val].int)(int_val);
+end
+
+@ @<Fetch a token list...@>=
+if level<>tok_val then
+ begin print_err("Missing number, treated as zero");
+@.Missing number...@>
+ help3("A number should have been here; I inserted `0'.")@/
+ ("(If you can't figure out why I needed to see a number,")@/
+ ("look up `weird error' in the index to The TeXbook.)");
+@:TeXbook}{\sl The \TeX book@>
+ back_error; scanned_result(0)(dimen_val);
+ end
+else if cur_cmd<=assign_toks then
+ begin if cur_cmd<assign_toks then {|cur_cmd=toks_register|}
+ begin scan_register_num; m:=toks_base+cur_val;
+ end;
+ scanned_result(equiv(m))(tok_val);
+ end
+else begin back_input; scan_font_ident;
+ scanned_result(font_id_base+cur_val)(ident_val);
+ end
+
+@ Users refer to `\.{\\the\\spacefactor}' only in horizontal
+mode, and to `\.{\\the\\prevdepth}' only in vertical mode; so we put the
+associated mode in the modifier part of the |set_aux| command.
+The |set_page_int| command has modifier 0 or 1, for `\.{\\deadcycles}' and
+`\.{\\insertpenalties}', respectively. The |set_box_dimen| command is
+modified by either |width_offset|, |height_offset|, or |depth_offset|.
+And the |last_item| command is modified by either |int_val|, |dimen_val|,
+|glue_val|, |input_line_no_code|, or |badness_code|.
+\pdfTeX\ adds the codes for its extensions: |pdftex_version_code|, \dots\ .
+\eTeX\ inserts |last_node_type_code| after |glue_val| and adds
+the codes for its extensions: |eTeX_version_code|, \dots\ .
+
+@d last_node_type_code=glue_val+1 {code for \.{\\lastnodetype}}
+@d input_line_no_code=glue_val+2 {code for \.{\\inputlineno}}
+@d badness_code=input_line_no_code+1 {code for \.{\\badness}}
+@#
+@d pdftex_first_rint_code = badness_code + 1 {base for \pdfTeX's command codes}
+@d pdftex_version_code = pdftex_first_rint_code + 0 {code for \.{\\pdftexversion}}
+@d pdf_last_obj_code = pdftex_first_rint_code + 1 {code for \.{\\pdflastobj}}
+@d pdf_last_xform_code = pdftex_first_rint_code + 2 {code for \.{\\pdflastxform}}
+@d pdf_last_ximage_code = pdftex_first_rint_code + 3 {code for \.{\\pdflastximage}}
+@d pdf_last_ximage_pages_code = pdftex_first_rint_code + 4 {code for \.{\\pdflastximagepages}}
+@d pdf_last_annot_code = pdftex_first_rint_code + 5 {code for \.{\\pdflastannot}}
+@d pdf_last_x_pos_code = pdftex_first_rint_code + 6 {code for \.{\\pdflastxpos}}
+@d pdf_last_y_pos_code = pdftex_first_rint_code + 7 {code for \.{\\pdflastypos}}
+@d pdf_retval_code = pdftex_first_rint_code + 8 {global multi-purpose return value}
+@d pdf_last_ximage_colordepth_code = pdftex_first_rint_code + 9 {code for \.{\\pdflastximagecolordepth}}
+@d random_seed_code = pdftex_first_rint_code + 10 {code for \.{\\pdfrandomseed}}
+@d pdf_last_link_code = pdftex_first_rint_code + 11 {code for \.{\\pdflastlink}}
+@d luatex_version_code = pdftex_first_rint_code + 12 {code for \.{\\luatexversion}}
+@d pdftex_last_item_codes = pdftex_first_rint_code + 12 {end of \pdfTeX's command codes}
+@#
+@d Aleph_int=pdftex_last_item_codes+1 {first of \Aleph\ codes for integers}
+@d Aleph_int_num=5 {number of \Aleph\ integers}
+@d eTeX_int=Aleph_int+Aleph_int_num {first of \eTeX\ codes for integers}
+@d eTeX_dim=eTeX_int+8 {first of \eTeX\ codes for dimensions}
+@d eTeX_glue=eTeX_dim+9 {first of \eTeX\ codes for glue}
+@d eTeX_mu=eTeX_glue+1 {first of \eTeX\ codes for muglue}
+@d eTeX_expr=eTeX_mu+1 {first of \eTeX\ codes for expressions}
+
+@<Put each...@>=
+primitive("spacefactor",set_aux,hmode);
+@!@:space_factor_}{\.{\\spacefactor} primitive@>
+primitive("prevdepth",set_aux,vmode);@/
+@!@:prev_depth_}{\.{\\prevdepth} primitive@>
+primitive("deadcycles",set_page_int,0);
+@!@:dead_cycles_}{\.{\\deadcycles} primitive@>
+primitive("insertpenalties",set_page_int,1);
+@!@:insert_penalties_}{\.{\\insertpenalties} primitive@>
+primitive("wd",set_box_dimen,width_offset);
+@!@:wd_}{\.{\\wd} primitive@>
+primitive("ht",set_box_dimen,height_offset);
+@!@:ht_}{\.{\\ht} primitive@>
+primitive("dp",set_box_dimen,depth_offset);
+@!@:dp_}{\.{\\dp} primitive@>
+primitive("lastpenalty",last_item,int_val);
+@!@:last_penalty_}{\.{\\lastpenalty} primitive@>
+primitive("lastkern",last_item,dimen_val);
+@!@:last_kern_}{\.{\\lastkern} primitive@>
+primitive("lastskip",last_item,glue_val);
+@!@:last_skip_}{\.{\\lastskip} primitive@>
+primitive("inputlineno",last_item,input_line_no_code);
+@!@:input_line_no_}{\.{\\inputlineno} primitive@>
+primitive("badness",last_item,badness_code);
+@!@:badness_}{\.{\\badness} primitive@>
+primitive("pdftexversion",last_item,pdftex_version_code);@/
+@!@:pdftex_version_}{\.{\\pdftexversion} primitive@>
+primitive("luatexversion",last_item,luatex_version_code);@/
+@!@:luatex_version_}{\.{\\luatexversion} primitive@>
+primitive("pdflastobj",last_item,pdf_last_obj_code);@/
+@!@:pdf_last_obj_}{\.{\\pdflastobj} primitive@>
+primitive("pdflastxform",last_item,pdf_last_xform_code);@/
+@!@:pdf_last_xform_}{\.{\\pdflastxform} primitive@>
+primitive("pdflastximage",last_item,pdf_last_ximage_code);@/
+@!@:pdf_last_ximage_}{\.{\\pdflastximage} primitive@>
+primitive("pdflastximagepages",last_item,pdf_last_ximage_pages_code);@/
+@!@:pdf_last_ximage_pages_}{\.{\\pdflastximagepages} primitive@>
+primitive("pdflastannot",last_item,pdf_last_annot_code);@/
+@!@:pdf_last_annot_}{\.{\\pdflastannot} primitive@>
+primitive("pdflastxpos",last_item,pdf_last_x_pos_code);@/
+@!@:pdf_last_x_pos_}{\.{\\pdflastxpos} primitive@>
+primitive("pdflastypos",last_item,pdf_last_y_pos_code);@/
+@!@:pdf_last_y_pos_}{\.{\\pdflastypos} primitive@>
+primitive("pdfretval",last_item,pdf_retval_code);@/
+@!@:pdf_retval_}{\.{\\pdfretval} primitive@>
+primitive("pdflastximagecolordepth",last_item,pdf_last_ximage_colordepth_code);@/
+@!@:pdf_last_ximage_colordepth_}{\.{\\pdflastximagecolordepth} primitive@>
+primitive("pdfrandomseed",last_item,random_seed_code);
+@!@:random_seed_}{\.{\\pdfrandomseed} primitive@>
+primitive("pdflastlink",last_item,pdf_last_link_code);@/
+@!@:pdf_last_link_}{\.{\\pdflastlink} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+set_aux: if chr_code=vmode then print_esc("prevdepth")
+@+else print_esc("spacefactor");
+set_page_int: if chr_code=0 then print_esc("deadcycles")
+@/@<Cases of |set_page_int| for |print_cmd_chr|@>@/
+@+else print_esc("insertpenalties");
+set_box_dimen: if chr_code=width_offset then print_esc("wd")
+else if chr_code=height_offset then print_esc("ht")
+else print_esc("dp");
+last_item: case chr_code of
+ int_val: print_esc("lastpenalty");
+ dimen_val: print_esc("lastkern");
+ glue_val: print_esc("lastskip");
+ input_line_no_code: print_esc("inputlineno");
+ @/@<Cases of |last_item| for |print_cmd_chr|@>@/
+ pdftex_version_code: print_esc("pdftexversion");
+ luatex_version_code: print_esc("luatexversion");
+ pdf_last_obj_code: print_esc("pdflastobj");
+ pdf_last_xform_code: print_esc("pdflastxform");
+ pdf_last_ximage_code: print_esc("pdflastximage");
+ pdf_last_ximage_pages_code: print_esc("pdflastximagepages");
+ pdf_last_annot_code: print_esc("pdflastannot");
+ pdf_last_x_pos_code: print_esc("pdflastxpos");
+ pdf_last_y_pos_code: print_esc("pdflastypos");
+ pdf_retval_code: print_esc("pdfretval");
+ pdf_last_ximage_colordepth_code: print_esc("pdflastximagecolordepth");
+ random_seed_code: print_esc("pdfrandomseed");
+ pdf_last_link_code: print_esc("pdflastlink");
+ othercases print_esc("badness")
+ endcases;
+
+@ @<Fetch the |space_factor| or the |prev_depth|@>=
+if abs(mode)<>m then
+ begin print_err("Improper "); print_cmd_chr(set_aux,m);
+@.Improper \\spacefactor@>
+@.Improper \\prevdepth@>
+ help4("You can refer to \spacefactor only in horizontal mode;")@/
+ ("you can refer to \prevdepth only in vertical mode; and")@/
+ ("neither of these is meaningful inside \write. So")@/
+ ("I'm forgetting what you said and using zero instead.");
+ error;
+ if level<>tok_val then scanned_result(0)(dimen_val)
+ else scanned_result(0)(int_val);
+ end
+else if m=vmode then
+ begin cur_val:=prev_depth; cur_val_level:=dimen_val;
+ end
+else begin cur_val:=space_factor; cur_val_level:=int_val;
+ end
+
+@ @<Fetch the |dead_cycles| or the |insert_penalties|@>=
+begin if m=0 then cur_val:=dead_cycles
+@/@<Cases for `Fetch the |dead_cycles| or the |insert_penalties|'@>@/
+else cur_val:=insert_penalties;
+cur_val_level:=int_val;
+end
+
+@ @<Fetch a box dimension@>=
+begin scan_register_num;
+if box(cur_val)=null then cur_val:=0 @+else cur_val:=vmem(box(cur_val)+m).sc;
+cur_val_level:=dimen_val;
+end
+
+@ Inside an \.{\\output} routine, a user may wish to look at the page totals
+that were present at the moment when output was triggered.
+
+@d max_dimen==@'7777777777 {$2^{30}-1$}
+
+@<Fetch something on the |page_so_far|@>=
+begin if (page_contents=empty) and (not output_active) then
+ if m=0 then cur_val:=max_dimen@+else cur_val:=0
+else cur_val:=page_so_far[m];
+cur_val_level:=dimen_val;
+end
+
+@ @<Fetch the |prev_graf|@>=
+if mode=0 then scanned_result(0)(int_val) {|prev_graf=0| within \.{\\write}}
+else begin nest[nest_ptr]:=cur_list; p:=nest_ptr;
+ while abs(nest[p].mode_field)<>vmode do decr(p);
+ scanned_result(nest[p].pg_field)(int_val);
+ end
+
+@ @<Fetch the |par_shape| size@>=
+begin if m>par_shape_loc then @<Fetch a penalties array element@>
+else if par_shape_ptr=null then cur_val:=0
+else cur_val:=vinfo(par_shape_ptr);
+cur_val_level:=int_val;
+end
+
+@ Here is where \.{\\lastpenalty}, \.{\\lastkern}, and \.{\\lastskip} are
+implemented. The reference count for \.{\\lastskip} will be updated later.
+
+We also handle \.{\\inputlineno} and \.{\\badness} here, because they are
+legal in similar contexts.
+
+@<Fetch an item in the current node...@>=
+if m>=input_line_no_code then
+ if m>=eTeX_glue then @<Process an expression and |return|@>@;
+ else if m>=eTeX_dim then
+ begin case m of
+ @/@<Cases for fetching a dimension value@>@/
+ end; {there are no other cases}
+ cur_val_level:=dimen_val;
+ end
+ else begin case m of
+ input_line_no_code: cur_val:=line;
+ badness_code: cur_val:=last_badness;
+ pdftex_version_code: cur_val := pdftex_version;
+ luatex_version_code: cur_val := luatex_version;
+ pdf_last_obj_code: cur_val := pdf_last_obj;
+ pdf_last_xform_code: cur_val := pdf_last_xform;
+ pdf_last_ximage_code: cur_val := pdf_last_ximage;
+ pdf_last_ximage_pages_code: cur_val := pdf_last_ximage_pages;
+ pdf_last_annot_code: cur_val := pdf_last_annot;
+ pdf_last_x_pos_code: cur_val := pdf_last_x_pos;
+ pdf_last_y_pos_code: cur_val := pdf_last_y_pos;
+ pdf_retval_code: cur_val := pdf_retval;
+ pdf_last_ximage_colordepth_code: cur_val := pdf_last_ximage_colordepth;
+ random_seed_code: cur_val := random_seed;
+ pdf_last_link_code: cur_val := pdf_last_link;
+ @/@<Cases for fetching an integer value@>@/
+ end; {there are no other cases}
+ cur_val_level:=int_val;
+ end
+else begin if cur_chr=glue_val then cur_val:=zero_glue@+else cur_val:=0;
+ if cur_chr=last_node_type_code then
+ begin cur_val_level:=int_val;
+ if (tail=head)or(mode=0) then cur_val:=-1;
+ end
+ else cur_val_level:=cur_chr;
+ {TODO: check this thoroughly! The structural change to the
+ |is_char_node| macro was wreaking havoc here, and possibly elsewhere.}
+ if tail<>contrib_head and not is_char_node(tail)and(mode<>0) then
+ case cur_chr of
+ int_val: if type(tail)=penalty_node then cur_val:=penalty(tail);
+ dimen_val: if type(tail)=kern_node then cur_val:=width(tail);
+ glue_val: if type(tail)=glue_node then
+ begin cur_val:=glue_ptr(tail);
+ if subtype(tail)=mu_glue then cur_val_level:=mu_val;
+ end;
+ last_node_type_code:
+ cur_val := visible_last_node_type(tail);
+ end {there are no other cases}
+ else if (mode=vmode)and(tail=head) then
+ case cur_chr of
+ int_val: cur_val:=last_penalty;
+ dimen_val: cur_val:=last_kern;
+ glue_val: if last_glue<>max_halfword then cur_val:=last_glue;
+ last_node_type_code: cur_val:=last_node_type;
+ end; {there are no other cases}
+ end
+
+@ @<Fetch a font dimension@>=
+get_font_dimen
+
+@ @<Fetch a font integer@>=
+begin scan_font_ident;
+if m=0 then scanned_result(hyphen_char(cur_val))(int_val)
+else if m=1 then scanned_result(skew_char(cur_val))(int_val)
+else if m=no_lig_code then scanned_result(test_no_ligatures(cur_val))(int_val)
+else begin
+ n := cur_val;
+ scan_char_num;
+ k := cur_val;
+ case m of
+ lp_code_base: scanned_result(get_lp_code(n, k))(int_val);
+ rp_code_base: scanned_result(get_rp_code(n, k))(int_val);
+ ef_code_base: scanned_result(get_ef_code(n, k))(int_val);
+ tag_code: scanned_result(get_tag_code(n, k))(int_val);
+ end;
+end;
+end
+
+@ @<Fetch a register@>=
+begin scan_register_num;
+case m of
+int_val:cur_val:=count(cur_val);
+attr_val:cur_val:=attribute(cur_val);
+dimen_val:cur_val:=dimen(cur_val);
+glue_val: cur_val:=skip(cur_val);
+mu_val: cur_val:=mu_skip(cur_val);
+end; {there are no other cases}
+cur_val_level:=m;
+end
+
+@ @<Complain that \.{\\the} can't do this; give zero result@>=
+begin print_err("You can't use `"); print_cmd_chr(cur_cmd,cur_chr);
+@.You can't use x after ...@>
+print("' after "); print_esc("the");
+help1("I'm forgetting what you said and using zero instead.");
+error;
+if level<>tok_val then scanned_result(0)(dimen_val)
+else scanned_result(0)(int_val);
+end
+
+@ @<Complain that |texlib| can't do this; give zero result@>=
+begin print_err("You can't use `"); print_cmd_chr(cmd,m);
+print("' as tex library index");
+help1("I'm forgetting what you said and using zero instead.");
+error;
+if level<>tok_val then scanned_result(0)(dimen_val)
+else scanned_result(0)(int_val);
+end
+
+
+@ When a |glue_val| changes to a |dimen_val|, we use the width component
+of the glue; there is no need to decrease the reference count, since it
+has not yet been increased. When a |dimen_val| changes to an |int_val|,
+we use scaled points so that the value doesn't actually change. And when a
+|mu_val| changes to a |glue_val|, the value doesn't change either.
+
+@<Convert \(c)|cur_val| to a lower level@>=
+begin if cur_val_level=glue_val then cur_val:=width(cur_val)
+else if cur_val_level=mu_val then mu_error;
+decr(cur_val_level);
+end
+
+@ If |cur_val| points to a glue specification at this point, the reference
+count for the glue does not yet include the reference by |cur_val|.
+If |negative| is |true|, |cur_val_level| is known to be |<=mu_val|.
+
+@<Fix the reference count, if any, ...@>=
+if negative then
+ if cur_val_level>=glue_val then
+ begin cur_val:=new_spec(cur_val);
+ @<Negate all three glue components of |cur_val|@>;
+ end
+ else negate(cur_val)
+else if (cur_val_level>=glue_val)and(cur_val_level<=mu_val) then
+ add_glue_ref(cur_val)
+
+@ @<Negate all three...@>=
+begin negate(width(cur_val));
+negate(stretch(cur_val));
+negate(shrink(cur_val));
+end
+
+@ Our next goal is to write the |scan_int| procedure, which scans anything that
+\TeX\ treats as an integer. But first we might as well look at some simple
+applications of |scan_int| that have already been made inside of
+|scan_something_internal|.
+
+@
+@d dir_T=0
+@d dir_L=1
+@d dir_B=2
+@d dir_R=3
+@d dir_eq_end(#)==(#)
+@d dir_eq(#)==(#)=dir_eq_end
+@d dir_ne_end(#)==(#)
+@d dir_ne(#)==(#)<>dir_ne_end
+@d dir_opposite_end(#)==((#) mod 4)
+@d dir_opposite(#)==(((#)+2) mod 4)=dir_opposite_end
+@d dir_parallel_end(#)==((#) mod 2)
+@d dir_parallel(#)==((#) mod 2)=dir_parallel_end
+@d dir_orthogonal_end(#)==(# mod 2)
+@d dir_orthogonal(#)==((#) mod 2)<>dir_orthogonal_end
+@d dir_next_end(#)==((#) mod 4)
+@d dir_next(#)==(((#)+3) mod 4)=dir_next_end
+@d dir_prev_end(#)==((#) mod 4)
+@d dir_prev(#)==(((#)+1) mod 4)=dir_prev_end
+
+{box directions}
+@d dir_TL_=0
+@d dir_TR_=1
+@d dir_LT_=2
+@d dir_LB_=3
+@d dir_BL_=4
+@d dir_BR_=5
+@d dir_RT_=6
+@d dir_RB_=7
+
+{font directions}
+@d dir__LT= 0
+@d dir__LL= 1
+@d dir__LB= 2
+@d dir__LR= 3
+@d dir__RT= 4
+@d dir__RL= 5
+@d dir__RB= 6
+@d dir__RR= 7
+@d dir__TT= 8
+@d dir__TL= 9
+@d dir__TB=10
+@d dir__TR=11
+@d dir__BT=12
+@d dir__BL=13
+@d dir__BB=14
+@d dir__BR=15
+
+@d is_mirrored(#)==dir_opposite(dir_primary[#])(dir_tertiary[#])
+@d is_rotated(#)==dir_parallel(dir_secondary[#])(dir_tertiary[#])
+@d font_direction(#)==(# mod 16)
+@d box_direction(#)==(# div 4)
+
+@d scan_single_dir(#)==begin
+if scan_keyword("T") then #:=dir_T
+else if scan_keyword("L") then #:=dir_L
+else if scan_keyword("B") then #:=dir_B
+else if scan_keyword("R") then #:=dir_R
+else begin
+ print_err("Bad direction"); cur_val:=0;
+ goto exit;
+ end
+end
+
+@<Declare procedures that scan restricted classes of integers@>=
+procedure scan_direction;
+var d1,d2,d3: integer;
+begin
+get_x_token;
+if cur_cmd=assign_dir then begin
+ cur_val:=eqtb[cur_chr].int;
+ goto exit;
+ end
+else back_input;
+scan_single_dir(d1);
+scan_single_dir(d2);
+if dir_parallel(d1)(d2) then begin
+ print_err("Bad direction"); cur_val:=0;
+ goto exit;
+ end;
+scan_single_dir(d3);
+cur_val:=d1*8+dir_rearrange[d2]*4+d3;
+exit:
+end;
+
+@ It is nice to have routines that say what they do, so the original
+|scan_eight_bit_int| is superceded by |scan_register_num| and
+|scan_mark_num|. It may become split up even further in the future.
+
+@<Declare procedures that scan restricted classes of integers@>=
+procedure scan_register_num;
+begin scan_int;
+if (cur_val<0)or(cur_val>biggest_reg) then
+ begin print_err("Bad register code");
+@.Bad register code@>
+ help2("A register number must be between 0 and 65535.")@/
+ ("I changed this one to zero."); int_error(cur_val); cur_val:=0;
+ end;
+end;
+procedure scan_mark_num;
+begin scan_int;
+if (cur_val<0)or(cur_val>biggest_mark) then
+ begin print_err("Bad marks code");
+@.Bad marks code@>
+ help2("A marks class must be between 0 and 65535.")@/
+ ("I changed this one to zero."); int_error(cur_val); cur_val:=0;
+ end;
+end;
+
+@ @<Declare procedures that scan restricted classes of integers@>=
+procedure scan_char_num;
+begin scan_int;
+if (cur_val<0)or(cur_val>biggest_char) then
+ begin print_err("Bad character code");
+@.Bad character code@>
+ help2("A character number must be between 0 and biggest_char.")@/
+ ("I changed this one to zero."); int_error(cur_val); cur_val:=0;
+ end;
+end;
+
+@ While we're at it, we might as well deal with similar routines that
+will be needed later.
+
+@<Declare procedures that scan restricted classes of integers@>=
+procedure scan_four_bit_int;
+begin scan_int;
+if (cur_val<0)or(cur_val>15) then
+ begin print_err("Bad number");
+@.Bad number@>
+ help2("Since I expected to read a number between 0 and 15,")@/
+ ("I changed this one to zero."); int_error(cur_val); cur_val:=0;
+ end;
+end;
+procedure scan_math_family_int;
+begin scan_int;
+if (cur_val<0)or(cur_val>255) then
+ begin print_err("Bad number");
+@.Bad number@>
+ help2("Since I expected to read a number between 0 and 255,")@/
+ ("I changed this one to zero."); int_error(cur_val); cur_val:=0;
+ end;
+end;
+
+@ @<Declare procedures that scan restricted classes of integers@>=
+procedure scan_real_fifteen_bit_int;
+begin scan_int;
+if (cur_val<0)or(cur_val>@'77777) then
+ begin print_err("Bad mathchar");
+@.Bad mathchar@>
+ help2("A mathchar number must be between 0 and 32767.")@/
+ ("I changed this one to zero."); int_error(cur_val); cur_val:=0;
+ end;
+end;
+procedure scan_fifteen_bit_int;
+begin scan_int;
+if (cur_val<0)or(cur_val>@'77777) then
+ begin print_err("Bad mathchar");
+@.Bad mathchar@>
+ help2("A mathchar number must be between 0 and 32767.")@/
+ ("I changed this one to zero."); int_error(cur_val); cur_val:=0;
+ end;
+cur_val := ((cur_val div @"1000) * @"1000000) +
+ (((cur_val mod @"1000) div @"100) * @"10000) +
+ (cur_val mod @"100);
+end;
+procedure scan_big_fifteen_bit_int;
+begin scan_int;
+if (cur_val<0)or(cur_val>@"7FFFFFF) then
+ begin print_err("Bad extended mathchar");
+@.Bad mathchar@>
+ help2("An extended mathchar number must be between 0 and ""7FFFFFF.")@/
+ ("I changed this one to zero."); int_error(cur_val); cur_val:=0;
+ end;
+end;
+
+
+@ @<Declare procedures that scan restricted classes of integers@>=
+procedure scan_twenty_seven_bit_int;
+begin scan_int;
+if (cur_val<0)or(cur_val>@'777777777) then
+ begin print_err("Bad delimiter code");
+@.Bad delimiter code@>
+ help2("A numeric delimiter code must be between 0 and 2^{27}-1.")@/
+ ("I changed this one to zero."); int_error(cur_val); cur_val:=0;
+ end;
+cur_val1 := (((cur_val mod @"1000) div @"100) * @"10000) +
+ (cur_val mod @"100);
+cur_val := cur_val div @"1000;
+cur_val := ((cur_val div @"1000) * @"1000000) +
+ (((cur_val mod @"1000) div @"100) * @"10000) +
+ (cur_val mod @"100);
+end;
+
+procedure scan_fifty_one_bit_int;
+var iiii:integer;
+begin scan_int;
+if (cur_val<0)or(cur_val>@'777777777) then
+ begin print_err("Bad delimiter code");
+@.Bad delimiter code@>
+ help2("A numeric delimiter (first part) must be between 0 and 2^{27}-1.")
+ ("I changed this one to zero."); int_error(cur_val); cur_val:=0;
+ end;
+iiii:=cur_val;
+scan_int;
+if (cur_val<0)or(cur_val>@"FFFFFF) then
+ begin print_err("Bad delimiter code");
+@.Bad delimiter code@>
+help2("A numeric delimiter (second part) must be between 0 and 2^{24}-1.")@/
+ ("I changed this one to zero."); int_error(cur_val); cur_val:=0;
+ end;
+cur_val1:=cur_val;
+cur_val:=iiii;
+end;
+
+
+procedure scan_string_argument;
+var s:integer;
+begin
+scan_left_brace;
+get_x_token;
+while (cur_cmd<>right_brace) do
+ begin
+ if (cur_cmd=letter) or (cur_cmd=other_char) then begin
+ str_room(1); append_char(cur_chr);
+ end
+ else if (cur_cmd=spacer) then begin
+ str_room(1); append_char(" ");
+ end
+ else begin
+ print("Bad token appearing in string argument");
+ end;
+ get_x_token;
+ end;
+s:=make_string;
+if str_eq_str("mi",s) then s:="mi";
+if str_eq_str("mo",s) then s:="mo";
+if str_eq_str("mn",s) then s:="mn";
+cur_val:=s;
+end;
+
+@ An integer number can be preceded by any number of spaces and `\.+' or
+`\.-' signs. Then comes either a decimal constant (i.e., radix 10), an
+octal constant (i.e., radix 8, preceded by~\.\'), a hexadecimal constant
+(radix 16, preceded by~\."), an alphabetic constant (preceded by~\.\`), or
+an internal variable. After scanning is complete,
+|cur_val| will contain the answer, which must be at most
+$2^{31}-1=2147483647$ in absolute value. The value of |radix| is set to
+10, 8, or 16 in the cases of decimal, octal, or hexadecimal constants,
+otherwise |radix| is set to zero. An optional space follows a constant.
+
+@d octal_token=other_token+"'" {apostrophe, indicates an octal constant}
+@d hex_token=other_token+"""" {double quote, indicates a hex constant}
+@d alpha_token=other_token+"`" {reverse apostrophe, precedes alpha constants}
+@d point_token=other_token+"." {decimal point}
+@d continental_point_token=other_token+"," {decimal point, Eurostyle}
+
+@<Glob...@>=
+@!radix:small_number; {|scan_int| sets this to 8, 10, 16, or zero}
+
+@ We initialize the following global variables just in case |expand|
+comes into action before any of the basic scanning routines has assigned
+them a value.
+
+@<Set init...@>=
+cur_val:=0; cur_val_level:=int_val; radix:=0; cur_order:=0;
+
+@ The |scan_int| routine is used also to scan the integer part of a
+fraction; for example, the `\.3' in `\.{3.14159}' will be found by
+|scan_int|. The |scan_dimen| routine assumes that |cur_tok=point_token|
+after the integer part of such a fraction has been scanned by |scan_int|,
+and that the decimal point has been backed up to be scanned again.
+
+@p procedure scan_int; {sets |cur_val| to an integer}
+label done;
+var negative:boolean; {should the answer be negated?}
+@!m:integer; {|@t$2^{31}$@> div radix|, the threshold of danger}
+@!d:small_number; {the digit just scanned}
+@!vacuous:boolean; {have no digits appeared?}
+@!OK_so_far:boolean; {has an error message been issued?}
+begin radix:=0; OK_so_far:=true;@/
+@<Get the next non-blank non-sign token; set |negative| appropriately@>;
+if cur_tok=alpha_token then @<Scan an alphabetic character code into |cur_val|@>
+else if (cur_cmd>=min_internal)and(cur_cmd<=max_internal) then
+ scan_something_internal(int_val,false)
+else @<Scan a numeric constant@>;
+if negative then negate(cur_val);
+end;
+
+@ @<Get the next non-blank non-sign token...@>=
+negative:=false;
+repeat @<Get the next non-blank non-call token@>;
+if cur_tok=other_token+"-" then
+ begin negative := not negative; cur_tok:=other_token+"+";
+ end;
+until cur_tok<>other_token+"+"
+
+@ A space is ignored after an alphabetic character constant, so that
+such constants behave like numeric ones.
+
+@<Scan an alphabetic character code into |cur_val|@>=
+begin get_token; {suppress macro expansion}
+if cur_tok<cs_token_flag then
+ begin cur_val:=cur_chr;
+ if cur_cmd<=right_brace then
+ if cur_cmd=right_brace then incr(align_state)
+ else decr(align_state);
+ end
+else if cur_tok<cs_token_flag+null_cs then
+ cur_val:=cur_tok-cs_token_flag-active_base
+else begin {the value of a csname in this context is its name}
+ if single_letter(text(cur_tok-cs_token_flag)) then
+ cur_val:=pool_to_unichar(str_start_macro(text(cur_tok-cs_token_flag)))
+ else
+ cur_val:=too_big_char;
+end;
+if cur_val>biggest_char then
+ begin print_err("Improper alphabetic constant");
+@.Improper alphabetic constant@>
+ help2("A one-character control sequence belongs after a ` mark.")@/
+ ("So I'm essentially inserting \0 here.");
+ cur_val:="0"; back_error;
+ end
+else @<Scan an optional space@>;
+end
+
+@ @<Scan an optional space@>=
+begin get_x_token; if cur_cmd<>spacer then back_input;
+end
+
+@ @<Scan a numeric constant@>=
+begin radix:=10; m:=214748364;
+if cur_tok=octal_token then
+ begin radix:=8; m:=@'2000000000; get_x_token;
+ end
+else if cur_tok=hex_token then
+ begin radix:=16; m:=@'1000000000; get_x_token;
+ end;
+vacuous:=true; cur_val:=0;@/
+@<Accumulate the constant until |cur_tok| is not a suitable digit@>;
+if vacuous then @<Express astonishment that no number was here@>
+else if cur_cmd<>spacer then back_input;
+end
+
+@ @d infinity==@'17777777777 {the largest positive value that \TeX\ knows}
+@d zero_token=other_token+"0" {zero, the smallest digit}
+@d A_token=letter_token+"A" {the smallest special hex digit}
+@d other_A_token=other_token+"A" {special hex digit of type |other_char|}
+
+@<Accumulate the constant...@>=
+loop@+ begin if (cur_tok<zero_token+radix)and(cur_tok>=zero_token)and
+ (cur_tok<=zero_token+9) then d:=cur_tok-zero_token
+ else if radix=16 then
+ if (cur_tok<=A_token+5)and(cur_tok>=A_token) then d:=cur_tok-A_token+10
+ else if (cur_tok<=other_A_token+5)and(cur_tok>=other_A_token) then
+ d:=cur_tok-other_A_token+10
+ else goto done
+ else goto done;
+ vacuous:=false;
+ if (cur_val>=m)and((cur_val>m)or(d>7)or(radix<>10)) then
+ begin if OK_so_far then
+ begin print_err("Number too big");
+@.Number too big@>
+ help2("I can only go up to 2147483647='17777777777=""7FFFFFFF,")@/
+ ("so I'm using that number instead of yours.");
+ error; cur_val:=infinity; OK_so_far:=false;
+ end;
+ end
+ else cur_val:=cur_val*radix+d;
+ get_x_token;
+ end;
+done:
+
+@ @<Express astonishment...@>=
+begin print_err("Missing number, treated as zero");
+@.Missing number...@>
+help3("A number should have been here; I inserted `0'.")@/
+ ("(If you can't figure out why I needed to see a number,")@/
+ ("look up `weird error' in the index to The TeXbook.)");
+@:TeXbook}{\sl The \TeX book@>
+back_error;
+end
+
+@ The |scan_dimen| routine is similar to |scan_int|, but it sets |cur_val| to
+a |scaled| value, i.e., an integral number of sp. One of its main tasks
+is therefore to interpret the abbreviations for various kinds of units and
+to convert measurements to scaled points.
+
+There are three parameters: |mu| is |true| if the finite units must be
+`\.{mu}', while |mu| is |false| if `\.{mu}' units are disallowed;
+|inf| is |true| if the infinite units `\.{fil}', `\.{fill}', `\.{filll}'
+are permitted; and |shortcut| is |true| if |cur_val| already contains
+an integer and only the units need to be considered.
+
+The order of infinity that was found in the case of infinite glue is returned
+in the global variable |cur_order|.
+
+@<Glob...@>=
+@!cur_order:glue_ord; {order of infinity found by |scan_dimen|}
+
+@ Constructions like `\.{-\'77 pt}' are legal dimensions, so |scan_dimen|
+may begin with |scan_int|. This explains why it is convenient to use
+|scan_int| also for the integer part of a decimal fraction.
+
+Several branches of |scan_dimen| work with |cur_val| as an integer and
+with an auxiliary fraction |f|, so that the actual quantity of interest is
+$|cur_val|+|f|/2^{16}$. At the end of the routine, this ``unpacked''
+representation is put into the single word |cur_val|, which suddenly
+switches significance from |integer| to |scaled|.
+
+@d attach_fraction=88 {go here to pack |cur_val| and |f| into |cur_val|}
+@d attach_sign=89 {go here when |cur_val| is correct except perhaps for sign}
+@d scan_normal_dimen==scan_dimen(false,false,false)
+
+@p procedure scan_dimen(@!mu,@!inf,@!shortcut:boolean);
+ {sets |cur_val| to a dimension}
+label done, done1, done2, found, not_found, attach_fraction, attach_sign;
+var negative:boolean; {should the answer be negated?}
+@!f:integer; {numerator of a fraction whose denominator is $2^{16}$}
+@<Local variables for dimension calculations@>@;
+begin f:=0; arith_error:=false; cur_order:=normal; negative:=false;
+if not shortcut then
+ begin @<Get the next non-blank non-sign...@>;
+ if (cur_cmd>=min_internal)and(cur_cmd<=max_internal) then
+ @<Fetch an internal dimension and |goto attach_sign|,
+ or fetch an internal integer@>
+ else begin back_input;
+ if cur_tok=continental_point_token then cur_tok:=point_token;
+ if cur_tok<>point_token then scan_int
+ else begin radix:=10; cur_val:=0;
+ end;
+ if cur_tok=continental_point_token then cur_tok:=point_token;
+ if (radix=10)and(cur_tok=point_token) then @<Scan decimal fraction@>;
+ end;
+ end;
+if cur_val<0 then {in this case |f=0|}
+ begin negative := not negative; negate(cur_val);
+ end;
+@<Scan units and set |cur_val| to $x\cdot(|cur_val|+f/2^{16})$, where there
+ are |x| sp per unit; |goto attach_sign| if the units are internal@>;
+@<Scan an optional space@>;
+attach_sign: if arith_error or(abs(cur_val)>=@'10000000000) then
+ @<Report that this dimension is out of range@>;
+if negative then negate(cur_val);
+end;
+
+@ @<Fetch an internal dimension and |goto attach_sign|...@>=
+if mu then
+ begin scan_something_internal(mu_val,false);
+ @<Coerce glue to a dimension@>;
+ if cur_val_level=mu_val then goto attach_sign;
+ if cur_val_level<>int_val then mu_error;
+ end
+else begin scan_something_internal(dimen_val,false);
+ if cur_val_level=dimen_val then goto attach_sign;
+ end
+
+@ @<Local variables for dimension calculations@>=
+@!num,@!denom:1..65536; {conversion ratio for the scanned units}
+@!k,@!kk:small_number; {number of digits in a decimal fraction}
+@!p,@!q:pointer; {top of decimal digit stack}
+@!v:scaled; {an internal dimension}
+@!save_cur_val:integer; {temporary storage of |cur_val|}
+
+@ The following code is executed when |scan_something_internal| was
+called asking for |mu_val|, when we really wanted a ``mudimen'' instead
+of ``muglue.''
+
+@<Coerce glue to a dimension@>=
+if cur_val_level>=glue_val then
+ begin v:=width(cur_val); delete_glue_ref(cur_val); cur_val:=v;
+ end
+
+@ When the following code is executed, we have |cur_tok=point_token|, but this
+token has been backed up using |back_input|; we must first discard it.
+
+It turns out that a decimal point all by itself is equivalent to `\.{0.0}'.
+Let's hope people don't use that fact.
+
+@<Scan decimal fraction@>=
+begin k:=0; p:=null; get_token; {|point_token| is being re-scanned}
+loop@+ begin get_x_token;
+ if (cur_tok>zero_token+9)or(cur_tok<zero_token) then goto done1;
+ if k<17 then {digits for |k>=17| cannot affect the result}
+ begin q:=get_avail; link(q):=p; info(q):=cur_tok-zero_token;
+ p:=q; incr(k);
+ end;
+ end;
+done1: for kk:=k downto 1 do
+ begin dig[kk-1]:=info(p); q:=p; p:=link(p); free_avail(q);
+ end;
+f:=round_decimals(k);
+if cur_cmd<>spacer then back_input;
+end
+
+@ Now comes the harder part: At this point in the program, |cur_val| is a
+nonnegative integer and $f/2^{16}$ is a nonnegative fraction less than 1;
+we want to multiply the sum of these two quantities by the appropriate
+factor, based on the specified units, in order to produce a |scaled|
+result, and we want to do the calculation with fixed point arithmetic that
+does not overflow.
+
+@<Scan units and set |cur_val| to $x\cdot(|cur_val|+f/2^{16})$...@>=
+if inf then @<Scan for \(f)\.{fil} units; |goto attach_fraction| if found@>;
+@<Scan for \(u)units that are internal dimensions;
+ |goto attach_sign| with |cur_val| set if found@>;
+if mu then @<Scan for \(m)\.{mu} units and |goto attach_fraction|@>;
+if scan_keyword("true") then @<Adjust \(f)for the magnification ratio@>;
+@.true@>
+if scan_keyword("pt") then goto attach_fraction; {the easy case}
+@.pt@>
+@<Scan for \(a)all other units and adjust |cur_val| and |f| accordingly;
+ |goto done| in the case of scaled points@>;
+attach_fraction: if cur_val>=@'40000 then arith_error:=true
+else cur_val:=cur_val*unity+f;
+done:
+
+@ In traditional TeX, a specification like `\.{filllll}' or `\.{fill L L
+L}' will lead to two error messages (one for each additional keyword
+\.{"l"}).
+
+Not so for luatex, it just parses the construct in reverse.
+
+@<Scan for \(f)\.{fil} units...@>=
+if scan_keyword("filll") then begin cur_order:=filll; goto attach_fraction; end
+else if scan_keyword("fill") then begin cur_order:=fill; goto attach_fraction; end
+else if scan_keyword("fil") then begin cur_order:=fil; goto attach_fraction; end
+else if scan_keyword("fi") then begin cur_order:=sfi; goto attach_fraction; end
+
+@ @<Scan for \(u)units that are internal dimensions...@>=
+save_cur_val:=cur_val;
+@<Get the next non-blank non-call...@>;
+if (cur_cmd<min_internal)or(cur_cmd>max_internal) then back_input
+else begin if mu then
+ begin scan_something_internal(mu_val,false); @<Coerce glue...@>;
+ if cur_val_level<>mu_val then mu_error;
+ end
+ else scan_something_internal(dimen_val,false);
+ v:=cur_val; goto found;
+ end;
+if mu then goto not_found;
+if scan_keyword("em") then v:=(@<The em width for |cur_font|@>)
+@.em@>
+else if scan_keyword("ex") then v:=(@<The x-height for |cur_font|@>)
+@.ex@>
+else if scan_keyword("px") then v:=pdf_px_dimen
+@.px@>
+else goto not_found;
+@<Scan an optional space@>;
+found:cur_val:=nx_plus_y(save_cur_val,v,xn_over_d(v,f,@'200000));
+goto attach_sign;
+not_found:
+
+@ @<Scan for \(m)\.{mu} units and |goto attach_fraction|@>=
+if scan_keyword("mu") then goto attach_fraction
+@.mu@>
+else begin print_err("Illegal unit of measure ("); print("mu inserted)");
+@.Illegal unit of measure@>
+ help4("The unit of measurement in math glue must be mu.")@/
+ ("To recover gracefully from this error, it's best to")@/
+ ("delete the erroneous units; e.g., type `2' to delete")@/
+ ("two letters. (See Chapter 27 of The TeXbook.)");
+@:TeXbook}{\sl The \TeX book@>
+ error; goto attach_fraction;
+ end
+
+@ @<Adjust \(f)for the magnification ratio@>=
+begin prepare_mag;
+if mag<>1000 then
+ begin cur_val:=xn_over_d(cur_val,1000,mag);
+ f:=(1000*f+@'200000*remainder) div mag;
+ cur_val:=cur_val+(f div @'200000); f:=f mod @'200000;
+ end;
+end
+
+@ The necessary conversion factors can all be specified exactly as
+fractions whose numerator and denominator add to 32768 or less.
+According to the definitions here, $\rm2660\,dd\approx1000.33297\,mm$;
+this agrees well with the value $\rm1000.333\,mm$ cited by Bosshard
+@^Bosshard, Hans Rudolf@>
+in {\sl Technische Grundlagen zur Satzherstellung\/} (Bern, 1980).
+The Didot point has been newly standardized in 1978;
+it's now exactly $\rm 1\,nd=0.375\,mm$.
+Conversion uses the equation $0.375=21681/20320/72.27\cdot25.4$.
+The new Cicero follows the new Didot point; $\rm 1\,nc=12\,nd$. These
+would lead to the ratios $21681/20320$ and $65043/5080$, respectively.
+The closest approximations supported by the algorithm would be
+$11183/10481$ and $1370/107$. In order to maintain the
+relation $\rm 1\,nc=12\,nd$, we pick the ratio $685/642$ for $\rm nd$,
+however.
+
+@d set_conversion_end(#)== denom:=#; end
+@d set_conversion(#)==@+begin num:=#; set_conversion_end
+
+@<Scan for \(a)all other units and adjust |cur_val| and |f|...@>=
+if scan_keyword("in") then set_conversion(7227)(100)
+@.in@>
+else if scan_keyword("pc") then set_conversion(12)(1)
+@.pc@>
+else if scan_keyword("cm") then set_conversion(7227)(254)
+@.cm@>
+else if scan_keyword("mm") then set_conversion(7227)(2540)
+@.mm@>
+else if scan_keyword("bp") then set_conversion(7227)(7200)
+@.bp@>
+else if scan_keyword("dd") then set_conversion(1238)(1157)
+@.dd@>
+else if scan_keyword("cc") then set_conversion(14856)(1157)
+@.cc@>
+else if scan_keyword("nd") then set_conversion(685)(642)
+@.nd@>
+else if scan_keyword("nc") then set_conversion(1370)(107)
+@.nc@>
+else if scan_keyword("sp") then goto done
+@.sp@>
+else @<Complain about unknown unit and |goto done2|@>;
+cur_val:=xn_over_d(cur_val,num,denom);
+f:=(num*f+@'200000*remainder) div denom;@/
+cur_val:=cur_val+(f div @'200000); f:=f mod @'200000;
+done2:
+
+@ @<Complain about unknown unit...@>=
+begin print_err("Illegal unit of measure ("); print("pt inserted)");
+@.Illegal unit of measure@>
+help6("Dimensions can be in units of em, ex, in, pt, pc,")@/
+ ("cm, mm, dd, cc, nd, nc, bp, or sp; but yours is a new one!")@/
+ ("I'll assume that you meant to say pt, for printer's points.")@/
+ ("To recover gracefully from this error, it's best to")@/
+ ("delete the erroneous units; e.g., type `2' to delete")@/
+ ("two letters. (See Chapter 27 of The TeXbook.)");
+@:TeXbook}{\sl The \TeX book@>
+error; goto done2;
+end
+
+
+@ @<Report that this dimension is out of range@>=
+begin print_err("Dimension too large");
+@.Dimension too large@>
+help2("I can't work with sizes bigger than about 19 feet.")@/
+ ("Continue and I'll use the largest value I can.");@/
+error; cur_val:=max_dimen; arith_error:=false;
+end
+
+@ The final member of \TeX's value-scanning trio is |scan_glue|, which
+makes |cur_val| point to a glue specification. The reference count of that
+glue spec will take account of the fact that |cur_val| is pointing to~it.
+
+The |level| parameter should be either |glue_val| or |mu_val|.
+
+Since |scan_dimen| was so much more complex than |scan_int|, we might expect
+|scan_glue| to be even worse. But fortunately, it is very simple, since
+most of the work has already been done.
+
+@p procedure scan_glue(@!level:small_number);
+ {sets |cur_val| to a glue spec pointer}
+label exit;
+var negative:boolean; {should the answer be negated?}
+@!q:pointer; {new glue specification}
+@!mu:boolean; {does |level=mu_val|?}
+begin mu:=(level=mu_val); @<Get the next non-blank non-sign...@>;
+if (cur_cmd>=min_internal)and(cur_cmd<=max_internal) then
+ begin scan_something_internal(level,negative);
+ if cur_val_level>=glue_val then
+ begin if cur_val_level<>level then mu_error;
+ return;
+ end;
+ if cur_val_level=int_val then scan_dimen(mu,false,true)
+ else if level=mu_val then mu_error;
+ end
+else begin back_input; scan_dimen(mu,false,false);
+ if negative then negate(cur_val);
+ end;
+@<Create a new glue specification whose width is |cur_val|; scan for its
+ stretch and shrink components@>;
+exit:end;
+@#
+@<Declare procedures needed for expressions@>@;
+
+@ @<Create a new glue specification whose width is |cur_val|...@>=
+q:=new_spec(zero_glue); width(q):=cur_val;
+if scan_keyword("plus") then
+@.plus@>
+ begin scan_dimen(mu,true,false);
+ stretch(q):=cur_val; stretch_order(q):=cur_order;
+ end;
+if scan_keyword("minus") then
+@.minus@>
+ begin scan_dimen(mu,true,false);
+ shrink(q):=cur_val; shrink_order(q):=cur_order;
+ end;
+cur_val:=q
+
+@ Here's a similar procedure that returns a pointer to a rule node. This
+routine is called just after \TeX\ has seen \.{\\hrule} or \.{\\vrule};
+therefore |cur_cmd| will be either |hrule| or |vrule|. The idea is to store
+the default rule dimensions in the node, then to override them if
+`\.{height}' or `\.{width}' or `\.{depth}' specifications are
+found (in any order).
+
+@d default_rule=26214 {0.4\thinspace pt}
+
+@p function scan_rule_spec:pointer;
+label reswitch;
+var q:pointer; {the rule node being created}
+begin q:=new_rule; {|width|, |depth|, and |height| all equal |null_flag| now}
+if cur_cmd=vrule then begin
+ width(q):=default_rule;
+ rule_dir(q):=body_direction;
+ end
+else begin
+ height(q):=default_rule; depth(q):=0;
+ rule_dir(q):=text_direction;
+end;
+reswitch: if scan_keyword("width") then
+@.width@>
+ begin scan_normal_dimen; width(q):=cur_val; goto reswitch;
+ end;
+if scan_keyword("height") then
+@.height@>
+ begin scan_normal_dimen; height(q):=cur_val; goto reswitch;
+ end;
+if scan_keyword("depth") then
+@.depth@>
+ begin scan_normal_dimen; depth(q):=cur_val; goto reswitch;
+ end;
+scan_rule_spec:=q;
+end;
+
+@* \[27] Building token lists.
+The token lists for macros and for other things like \.{\\mark} and \.{\\output}
+and \.{\\write} are produced by a procedure called |scan_toks|.
+
+Before we get into the details of |scan_toks|, let's consider a much
+simpler task, that of converting the current string into a token list.
+The |str_toks| function does this; it classifies spaces as type |spacer|
+and everything else as type |other_char|.
+
+The token list created by |str_toks| begins at |link(temp_token_head)| and ends
+at the value |p| that is returned. (If |p=temp_token_head|, the list is empty.)
+
+|lua_str_toks| is almost identical, but it also escapes the three
+symbols that |lua| considers special while scanning a literal string
+
+@d unicode_incr(#)==if str_pool[#]>@"F0 then #:=#+4 else if str_pool[#]>@"E0
+ then #:=#+3 else if str_pool[#]>@"C0 then #:=#+2 else incr(#)
+
+
+@p @t\4@>@<Declare \eTeX\ procedures for token lists@>@;@/
+function lua_str_toks(@!b:pool_pointer):pointer;
+ {changes the string |str_pool[b..pool_ptr]| to a token list}
+var p:pointer; {tail of the token list}
+@!q:pointer; {new node being added to the token list via |store_new_token|}
+@!t:halfword; {token being appended}
+@!k:pool_pointer; {index into |str_pool|}
+begin
+p:=temp_token_head; link(p):=null; k:=b;
+while k<pool_ptr do
+ begin t:=pool_to_unichar(k);
+ if t=" " then t:=space_token
+ else
+ begin
+ if (t="\") or (t="""") or (t="'") or (t=10) or (t=13) then
+ fast_store_new_token(other_token+"\");
+ if (t=10) then
+ t:="n";
+ if (t=13) then
+ t:="r";
+ t:=other_token+t;
+ end;
+ fast_store_new_token(t);
+ unicode_incr(k);
+ end;
+pool_ptr:=b; lua_str_toks:=p;
+end;
+
+function str_toks(@!b:pool_pointer):pointer;
+ {changes the string |str_pool[b..pool_ptr]| to a token list}
+var p:pointer; {tail of the token list}
+@!q:pointer; {new node being added to the token list via |store_new_token|}
+@!t:halfword; {token being appended}
+@!k:pool_pointer; {index into |str_pool|}
+begin
+p:=temp_token_head; link(p):=null; k:=b;
+while k<pool_ptr do
+ begin t:=pool_to_unichar(k);
+ if t=" " then t:=space_token
+ else t:=other_token+t;
+ fast_store_new_token(t);
+ unicode_incr(k);
+ end;
+pool_ptr:=b; str_toks:=p;
+end;
+
+@ The main reason for wanting |str_toks| is the next function,
+|the_toks|, which has similar input/output characteristics.
+
+This procedure is supposed to scan something like `\.{\\skip\\count12}',
+i.e., whatever can follow `\.{\\the}', and it constructs a token list
+containing something like `\.{-3.0pt minus 0.5fill}'.
+
+@p function the_toks:pointer;
+label exit;
+var old_setting:0..max_selector; {holds |selector| setting}
+@!p,@!q,@!r:pointer; {used for copying a token list}
+@!b:pool_pointer; {base of temporary string}
+@!c:small_number; {value of |cur_chr|}
+begin @<Handle \.{\\unexpanded} or \.{\\detokenize} and |return|@>;@/
+get_x_token; scan_something_internal(tok_val,false);
+if cur_val_level>=ident_val then begin
+ @<Copy the token list@>;
+ the_toks:=p;
+ end
+else begin old_setting:=selector; selector:=new_string; b:=pool_ptr;
+ case cur_val_level of
+ int_val:print_int(cur_val);
+ attr_val:print_int(cur_val);
+ dir_val:print_dir(cur_val);
+ dimen_val:begin print_scaled(cur_val); print("pt");
+ end;
+ glue_val: begin print_spec(cur_val,"pt"); delete_glue_ref(cur_val);
+ end;
+ mu_val: begin print_spec(cur_val,"mu"); delete_glue_ref(cur_val);
+ end;
+ end; {there are no other cases}
+ selector:=old_setting; the_toks:=str_toks(b);
+ end;
+exit:end;
+
+function the_scanned_result:str_number;
+var old_setting:0..max_selector; {holds |selector| setting}
+begin
+old_setting:=selector; selector:=new_string;
+if cur_val_level>=ident_val then begin
+ if cur_val<>null then begin
+ show_token_list(link(cur_val),null,pool_size-pool_ptr);
+ the_scanned_result:=make_string;
+ end
+ else
+ the_scanned_result:="";
+ end
+else begin
+ case cur_val_level of
+ int_val:print_int(cur_val);
+ attr_val:print_int(cur_val);
+ dir_val:print_dir(cur_val);
+ dimen_val:begin print_scaled(cur_val); print("pt");
+ end;
+ glue_val: begin print_spec(cur_val,"pt"); delete_glue_ref(cur_val);
+ end;
+ mu_val: begin print_spec(cur_val,"mu"); delete_glue_ref(cur_val);
+ end;
+ end; {there are no other cases}
+ the_scanned_result:=make_string;
+ end;
+selector:=old_setting;
+end;
+
+@ @<Copy the token list@>=
+begin p:=temp_token_head; link(p):=null;
+if cur_val_level=ident_val then store_new_token(cs_token_flag+cur_val)
+else if cur_val<>null then
+ begin r:=link(cur_val); {do not copy the reference count}
+ while r<>null do
+ begin fast_store_new_token(info(r)); r:=link(r);
+ end;
+ end;
+end
+
+@ Here's part of the |expand| subroutine that we are now ready to complete:
+
+@p procedure ins_the_toks;
+var junk:pointer;
+begin junk:=the_toks; ins_list(link(temp_token_head));
+end;
+
+@ The primitives \.{\\number}, \.{\\romannumeral}, \.{\\string}, \.{\\meaning},
+\.{\\fontname}, and \.{\\jobname} are defined as follows.
+
+\eTeX\ adds \.{\\eTeXrevision} such that |job_name_code| remains last.
+
+\pdfTeX\ adds \.{\\eTeXrevision}, \.{\\pdftexrevision}, \.{\\pdftexbanner},
+\.{\\pdffontname}, \.{\\pdffontobjnum}, \.{\\pdffontsize}, and \.{\\pdfpageref}
+such that |job_name_code| remains last.
+
+@d number_code=0 {command code for \.{\\number}}
+@d roman_numeral_code=1 {command code for \.{\\romannumeral}}
+@d string_code=2 {command code for \.{\\string}}
+@d meaning_code=3 {command code for \.{\\meaning}}
+@d font_name_code=4 {command code for \.{\\fontname}}
+@d etex_code=5 {command code for \.{\\eTeXVersion}}
+@d omega_code=6 {command code for \.{\\OmegaVersion}}
+@d aleph_code=7 {command code for \.{\\AlephVersion}}
+@d format_name_code=8 {command code for \.{\\AlephVersion}}
+@d pdftex_first_expand_code = 9 {base for \pdfTeX's command codes}
+@d pdftex_revision_code = pdftex_first_expand_code + 0 {command code for \.{\\pdftexrevision}}
+@d pdftex_banner_code = pdftex_first_expand_code + 1 {command code for \.{\\pdftexbanner}}
+@d pdf_font_name_code = pdftex_first_expand_code + 2 {command code for \.{\\pdffontname}}
+@d pdf_font_objnum_code = pdftex_first_expand_code + 3 {command code for \.{\\pdffontobjnum}}
+@d pdf_font_size_code = pdftex_first_expand_code + 4 {command code for \.{\\pdffontsize}}
+@d pdf_page_ref_code = pdftex_first_expand_code + 5 {command code for \.{\\pdfpageref}}
+@d pdf_xform_name_code = pdftex_first_expand_code + 6 {command code for \.{\\pdfxformname}}
+@d left_margin_kern_code = pdftex_first_expand_code + 7 {command code for \.{\\leftmarginkern}}
+@d right_margin_kern_code = pdftex_first_expand_code + 8 {command code for \.{\\rightmarginkern}}
+@d pdf_creation_date_code = pdftex_first_expand_code + 9 {command code for \.{\\pdfcreationdate}}
+@d uniform_deviate_code = pdftex_first_expand_code + 10 {command code for \.{\\uniformdeviate}}
+@d normal_deviate_code = pdftex_first_expand_code + 11 {command code for \.{\\normaldeviate}}
+@d pdf_insert_ht_code = pdftex_first_expand_code + 12 {command code for \.{\\pdfinsertht}}
+@d pdf_ximage_bbox_code = pdftex_first_expand_code + 13 {command code for \.{\\pdfximagebbox}}
+@d lua_code = pdftex_first_expand_code + 14 {command code for \.{\\directlua}}
+@d lua_escape_string_code = pdftex_first_expand_code + 15 {command code for \.{\\luaescapestring}}
+@d pdf_colorstack_init_code = pdftex_first_expand_code + 16 {command code for \.{\\pdfcolorstackinit}}
+@d luatex_revision_code = pdftex_first_expand_code + 17 {command code for \.{\\luatexrevision}}
+@d luatex_date_code = pdftex_first_expand_code + 18 {command code for \.{\\luatexdate}}
+@d pdftex_convert_codes = pdftex_first_expand_code + 19 {end of \pdfTeX's command codes}
+@d job_name_code=pdftex_convert_codes {command code for \.{\\jobname}}
+
+
+@<Put each...@>=
+primitive("number",convert,number_code);@/
+@!@:number_}{\.{\\number} primitive@>
+primitive("romannumeral",convert,roman_numeral_code);@/
+@!@:roman_numeral_}{\.{\\romannumeral} primitive@>
+primitive("string",convert,string_code);@/
+@!@:string_}{\.{\\string} primitive@>
+primitive("meaning",convert,meaning_code);@/
+@!@:meaning_}{\.{\\meaning} primitive@>
+primitive("eTeXVersion",convert,etex_code);@/
+@!@:omega_version_}{\.{\\OmegaVersion} primitive@>
+primitive("OmegaVersion",convert,omega_code);@/
+@!@:omega_version_}{\.{\\OmegaVersion} primitive@>
+primitive("AlephVersion",convert,aleph_code);@/
+@!@:aleph_version_}{\.{\\AlephVersion} primitive@>
+primitive("fontname",convert,font_name_code);@/
+@!@:font_name_}{\.{\\fontname} primitive@>
+primitive("pdftexrevision",convert,pdftex_revision_code);@/
+@!@:pdftex_revision_}{\.{\\pdftexrevision} primitive@>
+primitive("luatexrevision",convert,luatex_revision_code);@/
+@!@:luatex_revision_}{\.{\\luatexrevision} primitive@>
+primitive("luatexdatestamp",convert,luatex_date_code);@/
+@!@:luatex_date_}{\.{\\luatexdatestamp} primitive@>
+primitive("pdftexbanner",convert,pdftex_banner_code);@/
+@!@:pdftex_banner_}{\.{\\pdftexbanner} primitive@>
+primitive("pdffontname",convert,pdf_font_name_code);@/
+@!@:pdf_font_name_}{\.{\\pdffontname} primitive@>
+primitive("pdffontobjnum",convert,pdf_font_objnum_code);@/
+@!@:pdf_font_objnum_}{\.{\\pdffontobjnum} primitive@>
+primitive("pdffontsize",convert,pdf_font_size_code);@/
+@!@:pdf_font_size_}{\.{\\pdffontsize} primitive@>
+primitive("pdfpageref",convert,pdf_page_ref_code);@/
+@!@:pdf_page_ref_}{\.{\\pdfpageref} primitive@>
+primitive("leftmarginkern",convert,left_margin_kern_code);@/
+@!@:left_margin_kern_}{\.{\\leftmarginkern} primitive@>
+primitive("rightmarginkern",convert,right_margin_kern_code);@/
+@!@:right_margin_kern_}{\.{\\rightmarginkern} primitive@>
+primitive("pdfxformname",convert,pdf_xform_name_code);@/
+@!@:pdf_xform_name_}{\.{\\pdfxformname} primitive@>
+primitive("pdfcreationdate",convert,pdf_creation_date_code);@/
+@!@:pdf_creation_date_}{\.{\\pdfcreationdate} primitive@>
+primitive("pdfuniformdeviate",convert,uniform_deviate_code);@/
+@!@:uniform_deviate_}{\.{\\pdfuniformdeviate} primitive@>
+primitive("pdfcolorstackinit",convert,pdf_colorstack_init_code);@/
+@!@:pdf_colorstack_init_}{\.{\\pdfcolorstackinit} primitive@>
+primitive("pdfnormaldeviate",convert,normal_deviate_code);@/
+@!@:normal_deviate_}{\.{\\pdfnormaldeviate} primitive@>
+primitive("directlua",convert,lua_code);@/
+@!@:lua_}{\.{\\directlua} primitive@>
+primitive("luaescapestring",convert,lua_escape_string_code);@/
+@!@:lua_}{\.{\\luaescapestring} primitive@>
+@#
+primitive("jobname",convert,job_name_code);@/
+@!@:job_name_}{\.{\\jobname} primitive@>
+primitive("formatname",convert,format_name_code);@/
+@!@:format_name_}{\.{\\formatname} primitive@>
+primitive("pdfinsertht",convert,pdf_insert_ht_code);@/
+@!@:pdf_insert_ht_}{\.{\\pdfinsertht} primitive@>
+primitive("pdfximagebbox",convert,pdf_ximage_bbox_code);@/
+@!@:pdf_ximage_bbox_}{\.{\\pdfximagebbox} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+convert: case chr_code of
+ number_code: print_esc("number");
+ roman_numeral_code: print_esc("romannumeral");
+ string_code: print_esc("string");
+ meaning_code: print_esc("meaning");
+ etex_code: print_esc("eTeXVersion");
+ omega_code: print_esc("OmegaVersion");
+ aleph_code: print_esc("AlephVersion");
+ font_name_code: print_esc("fontname");
+ pdftex_revision_code: print_esc("pdftexrevision");
+ luatex_revision_code: print_esc("luatexrevision");
+ luatex_date_code: print_esc("luatexdatestamp");
+ pdftex_banner_code: print_esc("pdftexbanner");
+ pdf_font_name_code: print_esc("pdffontname");
+ pdf_font_objnum_code: print_esc("pdffontobjnum");
+ pdf_font_size_code: print_esc("pdffontsize");
+ pdf_page_ref_code: print_esc("pdfpageref");
+ left_margin_kern_code: print_esc("leftmarginkern");
+ right_margin_kern_code: print_esc("rightmarginkern");
+ pdf_xform_name_code: print_esc("pdfxformname");
+ pdf_creation_date_code: print_esc("pdfcreationdate");
+ pdf_colorstack_init_code: print_esc("pdfcolorstackinit");
+ uniform_deviate_code: print_esc("pdfuniformdeviate");
+ normal_deviate_code: print_esc("pdfnormaldeviate");
+ pdf_insert_ht_code: print_esc("pdfinsertht");
+ pdf_ximage_bbox_code: print_esc("pdfximagebbox");
+ lua_code: print_esc("directlua");
+ lua_escape_string_code: print_esc("luaescapestring");
+ @/@<Cases of |convert| for |print_cmd_chr|@>@/
+ othercases print_esc("jobname")
+ endcases;
+
+@ The procedure |conv_toks| uses |str_toks| to insert the token list
+for |convert| functions into the scanner; `\.{\\outer}' control sequences
+are allowed to follow `\.{\\string}' and `\.{\\meaning}'.
+
+The extra temp string |u| is needed because |pdf_scan_ext_toks| incorporates
+any pending string in its output. In order to save such a pending string,
+we have to create a temporary string that is destroyed immediately after.
+
+@d save_cur_string==if str_start[str_ptr]<pool_ptr then u:=make_string
+@d restore_cur_string==if u<>0 then begin decr(str_ptr); u:=0; end
+
+@p procedure conv_toks;
+label exit;
+var old_setting:0..max_selector; {holds |selector| setting}
+p, q: pointer;
+@!c:number_code..job_name_code; {desired type of conversion}
+@!save_scanner_status:small_number; {|scanner_status| upon entry}
+@!save_def_ref: pointer; {|def_ref| upon entry, important if inside `\.{\\message}'}
+@!save_warning_index: pointer;
+@!bool: boolean; {temp boolean}
+@!i: integer; {first temp integer}
+@!j: integer; {second temp integer}
+@!b:pool_pointer; {base of temporary string}
+@!s: str_number; {first temp string}
+@!u: str_number; {third temp string}
+@!junk: pointer;
+begin
+c:=cur_chr;
+u:=0; { will become non-nil if a string is already being built}
+j:=0; i:=0;
+@<Scan the argument for command |c|@>;
+old_setting:=selector; selector:=new_string; b:=pool_ptr;
+@<Print the result of command |c|@>;
+selector:=old_setting; junk:=str_toks(b); ins_list(link(temp_token_head));
+exit:
+end;
+
+@ @<Scan the argument for command |c|@>=
+case c of
+number_code,roman_numeral_code: scan_int;
+string_code, meaning_code: begin save_scanner_status:=scanner_status;
+ scanner_status:=normal; get_token; scanner_status:=save_scanner_status;
+ end;
+etex_code: do_nothing;
+omega_code: do_nothing;
+aleph_code: do_nothing;
+font_name_code: scan_font_ident;
+pdftex_revision_code: do_nothing;
+luatex_revision_code: do_nothing;
+luatex_date_code: do_nothing;
+pdftex_banner_code: do_nothing;
+pdf_font_name_code, pdf_font_objnum_code, pdf_font_size_code: begin
+ scan_font_ident;
+ if cur_val = null_font then
+ pdf_error("font", "invalid font identifier");
+ if c <> pdf_font_size_code then begin
+ pdf_check_vf_cur_val;
+ if not font_used(cur_val) then
+ pdf_init_font_cur_val;
+ end;
+end;
+pdf_page_ref_code: begin
+ scan_int;
+ if cur_val <= 0 then
+ pdf_error("pageref", "invalid page number");
+end;
+left_margin_kern_code, right_margin_kern_code: begin
+ scan_int;
+ if (box(cur_val) = null) or (type(box(cur_val)) <> hlist_node) then
+ pdf_error("marginkern", "a non-empty hbox expected")
+end;
+pdf_xform_name_code: begin
+ scan_int;
+ pdf_check_obj(obj_type_xform, cur_val);
+end;
+pdf_creation_date_code:
+ begin
+ b := pool_ptr;
+ getcreationdate;
+ junk := str_toks(b);
+ ins_list(link(temp_token_head));
+ return;
+ end;
+job_name_code: if job_name=0 then open_log_file;
+pdf_colorstack_init_code:
+ begin
+ bool := scan_keyword("page");
+ if scan_keyword("direct") then
+ cur_val := direct_always
+ else
+ if scan_keyword("page") then
+ cur_val := direct_page
+ else
+ cur_val := set_origin;
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ save_cur_string;
+ scan_pdf_ext_toks;
+ s := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ cur_val := newcolorstack(s, cur_val, bool);
+ flush_str(s);
+ cur_val_level := int_val;
+ if cur_val < 0 then begin
+ print_err("Too many color stacks");
+@.Too many color stacks@>
+ help2("The number of color stacks is limited to 32768.")@/
+ ("I'll use the default color stack 0 here.");
+ error;
+ cur_val := 0;
+ restore_cur_string;
+ end;
+ end;
+uniform_deviate_code: scan_int;
+normal_deviate_code: do_nothing;
+lua_escape_string_code:
+ begin
+ u:=0;
+ { check if a string is already being built}
+ if str_start_macro(str_ptr)<pool_ptr then u:=make_string;
+ save_scanner_status := scanner_status;
+ save_def_ref := def_ref;
+ save_warning_index := warning_index;
+ scan_pdf_ext_toks;
+ s := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ junk := lua_str_toks(str_start_macro(s));
+ ins_list(link(temp_token_head));
+ flush_str(s);
+ if u<>0 then begin decr(str_ptr); u:=0; end;
+ return;
+ end;
+lua_code:
+ begin
+ u:=0;
+ { check if a string is already being built}
+ if str_start_macro(str_ptr)<pool_ptr then u:=make_string;
+ save_scanner_status := scanner_status;
+ save_def_ref := def_ref;
+ save_warning_index := warning_index;
+ scan_register_num;
+ i := cur_val;
+ scan_pdf_ext_toks;
+ s := def_ref;
+ warning_index := save_warning_index;
+ def_ref := save_def_ref;
+ scanner_status := save_scanner_status;
+ luacstrings:=0;
+ luatokencall(i,s);
+ delete_token_ref(s);
+ if u<>0 then begin
+ if str_ptr=u+1 then
+ decr(str_ptr)
+ else begin {copy old string to the top location}
+ i:=0;
+ str_room(length(u));
+ while i<length(u) do
+ str_pool[pool_ptr+i]:=str_pool[str_start_macro(u)+i];
+ end;
+ end;
+ if luacstrings>0 then
+ lua_string_start;
+ return;
+ end;
+pdf_insert_ht_code: scan_register_num;
+pdf_ximage_bbox_code: begin
+ scan_int;
+ pdf_check_obj(obj_type_ximage, cur_val);
+ i := obj_data_ptr(cur_val);
+ scan_int;
+ j := cur_val;
+ if (j < 1) or (j > 4) then
+ pdf_error("pdfximagebbox", "invalid parameter");
+ end;
+@<Cases of `Scan the argument for command |c|'@>
+end {there are no other cases}
+
+@ @<Print the result of command |c|@>=
+case c of
+number_code: print_int(cur_val);
+roman_numeral_code: print_roman_int(cur_val);
+string_code:if cur_cs<>0 then sprint_cs(cur_cs)
+ else print(cur_chr);
+meaning_code: print_meaning;
+etex_code: print(eTeX_version_string);
+omega_code: print(Omega_version_string);
+aleph_code: print(Aleph_version_string);
+font_name_code: begin
+ append_string(font_name(cur_val));
+ if font_size(cur_val)<>font_dsize(cur_val) then
+ begin print(" at "); print_scaled(font_size(cur_val));
+ print("pt");
+ end;
+ end;
+pdftex_revision_code: print(pdftex_revision);
+luatex_revision_code: print(luatex_revision);
+luatex_date_code: print_int(luatex_date_info);
+pdftex_banner_code: print(pdftex_banner);
+pdf_font_name_code, pdf_font_objnum_code: begin
+ set_ff(cur_val);
+ if c = pdf_font_name_code then
+ print_int(obj_info(pdf_font_num(ff)))
+ else
+ print_int(pdf_font_num(ff));
+end;
+pdf_font_size_code: begin
+ print_scaled(font_size(cur_val));
+ print("pt");
+end;
+pdf_page_ref_code: print_int(get_obj(obj_type_page, cur_val, false));
+left_margin_kern_code: begin
+ p := list_ptr(box(cur_val));
+ if (p <> null) and (not is_char_node(p)) and
+ (type(p) = glue_node) and (subtype(p) = left_skip_code + 1) then
+ p := vlink(p);
+ if (p <> null) and (not is_char_node(p)) and
+ (type(p) = margin_kern_node) and (subtype(p) = left_side) then
+ print_scaled(width(p))
+ else
+ print("0");
+ print("pt");
+end;
+right_margin_kern_code: begin
+ q := list_ptr(box(cur_val));
+ p := null;
+ if q <> null then begin
+ p := prev_rightmost(q, null);
+ if (p <> null) and (not is_char_node(p)) and
+ (type(p) = glue_node) and (subtype(p) = right_skip_code + 1) then
+ p := prev_rightmost(q, p);
+ end;
+ if (p <> null) and (not is_char_node(p)) and
+ (type(p) = margin_kern_node) and (subtype(p) = right_side) then
+ print_scaled(width(p))
+ else
+ print("0");
+ print("pt");
+end;
+pdf_xform_name_code: print_int(obj_info(cur_val));
+pdf_colorstack_init_code: print_int(cur_val);
+uniform_deviate_code: print_int(unif_rand(cur_val));
+normal_deviate_code: print_int(norm_rand);
+pdf_insert_ht_code: begin
+ i := qi(cur_val);
+ p := page_ins_head;
+ while i >= subtype(vlink(p)) do
+ p := vlink(p);
+ if subtype(p) = i then
+ print_scaled(height(p))
+ else
+ print("0");
+ print("pt");
+end;
+pdf_ximage_bbox_code: begin
+ case j of
+ 1: print_scaled(epdf_orig_x(i));
+ 2: print_scaled(epdf_orig_y(i));
+ 3: print_scaled(epdf_orig_x(i) + image_width(i));
+ 4: print_scaled(epdf_orig_y(i) + image_height(i));
+ endcases;
+ print("pt");
+end;
+format_name_code: print(format_name);
+job_name_code: print(job_name);
+@/@<Cases of `Print the result of command |c|'@>@/
+end {there are no other cases}
+
+@
+@p function is_convert(c:halfword):boolean;
+begin
+ is_convert:=(c=convert);
+end;
+
+function the_convert_string (c:halfword):str_number;
+var old_setting:0..max_selector; {saved |selector| setting}
+ is_known:boolean;
+begin
+ old_setting:=selector;
+ selector:=new_string;
+ is_known:=true;
+ case c of
+ etex_code: print(eTeX_version_string);
+ omega_code: print(Omega_version_string);
+ aleph_code: print(Aleph_version_string);
+ pdftex_revision_code: print(pdftex_revision);
+ luatex_revision_code: print(luatex_revision);
+ luatex_date_code: print_int(luatex_date_info);
+ pdftex_banner_code: print(pdftex_banner);
+ normal_deviate_code: print_int(norm_rand);
+ format_name_code: print(format_name);
+ job_name_code: print(job_name);
+@/@<Cases of `Print the result of command |c|'@>@/
+ othercases is_known:=false
+ end;
+ if is_known then
+ the_convert_string := make_string
+ else
+ the_convert_string := 0;
+ selector:=old_setting;
+end;
+
+@ Now we can't postpone the difficulties any longer; we must bravely tackle
+|scan_toks|. This function returns a pointer to the tail of a new token
+list, and it also makes |def_ref| point to the reference count at the
+head of that list.
+
+There are two boolean parameters, |macro_def| and |xpand|. If |macro_def|
+is true, the goal is to create the token list for a macro definition;
+otherwise the goal is to create the token list for some other \TeX\
+primitive: \.{\\mark}, \.{\\output}, \.{\\everypar}, \.{\\lowercase},
+\.{\\uppercase}, \.{\\message}, \.{\\errmessage}, \.{\\write}, or
+\.{\\special}. In the latter cases a left brace must be scanned next; this
+left brace will not be part of the token list, nor will the matching right
+brace that comes at the end. If |xpand| is false, the token list will
+simply be copied from the input using |get_token|. Otherwise all expandable
+tokens will be expanded until unexpandable tokens are left, except that
+the results of expanding `\.{\\the}' are not expanded further.
+If both |macro_def| and |xpand| are true, the expansion applies
+only to the macro body (i.e., to the material following the first
+|left_brace| character).
+
+The value of |cur_cs| when |scan_toks| begins should be the |eqtb|
+address of the control sequence to display in ``runaway'' error
+messages.
+
+@p function scan_toks(@!macro_def,@!xpand:boolean):pointer;
+label found,done,done1,done2;
+var t:halfword; {token representing the highest parameter number}
+@!s:halfword; {saved token}
+@!p:pointer; {tail of the token list being built}
+@!q:pointer; {new node being added to the token list via |store_new_token|}
+@!unbalance:halfword; {number of unmatched left braces}
+@!hash_brace:halfword; {possible `\.{\#\{}' token}
+begin if macro_def then scanner_status:=defining
+@+else scanner_status:=absorbing;
+warning_index:=cur_cs; p:=get_avail; def_ref:=p; token_ref_count(def_ref):=0;
+p:=def_ref; hash_brace:=0; t:=zero_token;
+if macro_def then @<Scan and build the parameter part of the macro definition@>
+else scan_left_brace; {remove the compulsory left brace}
+@<Scan and build the body of the token list; |goto found| when finished@>;
+found: scanner_status:=normal;
+if hash_brace<>0 then store_new_token(hash_brace);
+scan_toks:=p;
+end;
+
+@ @<Scan and build the parameter part...@>=
+begin loop begin get_token; {set |cur_cmd|, |cur_chr|, |cur_tok|}
+ if cur_tok<right_brace_limit then goto done1;
+ if cur_cmd=mac_param then
+ @<If the next character is a parameter number, make |cur_tok|
+ a |match| token; but if it is a left brace, store
+ `|left_brace|, |end_match|', set |hash_brace|, and |goto done|@>;
+ store_new_token(cur_tok);
+ end;
+done1: store_new_token(end_match_token);
+if cur_cmd=right_brace then
+ @<Express shock at the missing left brace; |goto found|@>;
+done: end
+
+@ @<Express shock...@>=
+begin print_err("Missing { inserted"); incr(align_state);
+@.Missing \{ inserted@>
+help2("Where was the left brace? You said something like `\def\a}',")@/
+ ("which I'm going to interpret as `\def\a{}'."); error; goto found;
+end
+
+@ @<If the next character is a parameter number...@>=
+begin s:=match_token+cur_chr; get_token;
+if cur_cmd=left_brace then
+ begin hash_brace:=cur_tok;
+ store_new_token(cur_tok); store_new_token(end_match_token);
+ goto done;
+ end;
+if t=zero_token+9 then
+ begin print_err("You already have nine parameters");
+@.You already have nine...@>
+ help1("I'm going to ignore the # sign you just used."); error;
+ end
+else begin incr(t);
+ if cur_tok<>t then
+ begin print_err("Parameters must be numbered consecutively");
+@.Parameters...consecutively@>
+ help2("I've inserted the digit you should have used after the #.")@/
+ ("Type `1' to delete what you did use."); back_error;
+ end;
+ cur_tok:=s;
+ end;
+end
+
+@ @<Scan and build the body of the token list; |goto found| when finished@>=
+unbalance:=1;
+loop@+ begin if xpand then @<Expand the next part of the input@>
+ else get_token;
+ if cur_tok<right_brace_limit then
+ if cur_cmd<right_brace then incr(unbalance)
+ else begin decr(unbalance);
+ if unbalance=0 then goto found;
+ end
+ else if cur_cmd=mac_param then
+ if macro_def then @<Look for parameter number or \.{\#\#}@>;
+ store_new_token(cur_tok);
+ end
+
+@ Here we insert an entire token list created by |the_toks| without
+expanding it further.
+
+@<Expand the next part of the input@>=
+begin loop begin get_filtered_next;
+ if cur_cmd>=call then
+ if info(link(cur_chr))=protected_token then
+ begin cur_cmd:=relax; cur_chr:=no_expand_flag;
+ end;
+ if cur_cmd<=max_command then goto done2;
+ if cur_cmd<>the then expand
+ else begin q:=the_toks;
+ if link(temp_token_head)<>null then
+ begin link(p):=link(temp_token_head); p:=q;
+ end;
+ end;
+ end;
+done2: x_token
+end
+
+@ @<Look for parameter number...@>=
+begin s:=cur_tok;
+if xpand then get_x_token else get_token;
+if cur_cmd<>mac_param then
+ if (cur_tok<=zero_token)or(cur_tok>t) then
+ begin print_err("Illegal parameter number in definition of ");
+@.Illegal parameter number...@>
+ sprint_cs(warning_index);
+ help3("You meant to type ## instead of #, right?")@/
+ ("Or maybe a } was forgotten somewhere earlier, and things")@/
+ ("are all screwed up? I'm going to assume that you meant ##.");
+ back_error; cur_tok:=s;
+ end
+ else cur_tok:=out_param_token-"0"+cur_chr;
+end
+
+@ Another way to create a token list is via the \.{\\read} command. The
+sixteen files potentially usable for reading appear in the following
+global variables. The value of |read_open[n]| will be |closed| if
+stream number |n| has not been opened or if it has been fully read;
+|just_open| if an \.{\\openin} but not a \.{\\read} has been done;
+and |normal| if it is open and ready to read the next line.
+
+@d closed=2 {not open, or at end of file}
+@d just_open=1 {newly opened, first line not yet read}
+
+@<Glob...@>=
+@!read_file:array[0..15] of alpha_file; {used for \.{\\read}}
+@!read_open:array[0..16] of normal..closed; {state of |read_file[n]|}
+
+@ @<Set init...@>=
+for k:=0 to 16 do begin
+ read_open[k]:=closed;
+end;
+
+@ The |read_toks| procedure constructs a token list like that for any
+macro definition, and makes |cur_val| point to it. Parameter |r| points
+to the control sequence that will receive this token list.
+
+@p procedure read_toks(@!n:integer;@!r:pointer;@!j:halfword);
+label done;
+var p:pointer; {tail of the token list}
+@!q:pointer; {new node being added to the token list via |store_new_token|}
+@!s:integer; {saved value of |align_state|}
+@!m:small_number; {stream number}
+begin scanner_status:=defining; warning_index:=r;
+p:=get_avail; def_ref:=p; token_ref_count(def_ref):=0;
+p:=def_ref; {the reference count}
+store_new_token(end_match_token);
+if (n<0)or(n>15) then m:=16@+else m:=n;
+s:=align_state; align_state:=1000000; {disable tab marks, etc.}
+repeat @<Input and store tokens from the next line of the file@>;
+until align_state=1000000;
+cur_val:=def_ref; scanner_status:=normal; align_state:=s;
+end;
+
+@ @<Input and store tokens from the next line of the file@>=
+begin_file_reading; name:=m+1;
+if read_open[m]=closed then @<Input for \.{\\read} from the terminal@>
+else if read_open[m]=just_open then @<Input the first line of |read_file[m]|@>
+else @<Input the next line of |read_file[m]|@>;
+limit:=last;
+if end_line_char_inactive then decr(limit)
+else buffer[limit]:=end_line_char;
+first:=limit+1; loc:=start; state:=new_line;@/
+@<Handle \.{\\readline} and |goto done|@>;@/
+loop@+ begin get_token;
+ if cur_tok=0 then goto done;
+ {|cur_cmd=cur_chr=0| will occur at the end of the line}
+ if align_state<1000000 then {unmatched `\.\}' aborts the line}
+ begin repeat get_token; until cur_tok=0;
+ align_state:=1000000; goto done;
+ end;
+ store_new_token(cur_tok);
+ end;
+done: end_file_reading
+
+@ Here we input on-line into the |buffer| array, prompting the user explicitly
+if |n>=0|. The value of |n| is set negative so that additional prompts
+will not be given in the case of multi-line input.
+
+@<Input for \.{\\read} from the terminal@>=
+if interaction>nonstop_mode then
+ if n<0 then prompt_input("")
+ else begin wake_up_terminal;
+ print_ln; sprint_cs(r); prompt_input("="); n:=-1;
+ end
+else fatal_error("*** (cannot \read from terminal in nonstop modes)")
+@.cannot \\read@>
+
+@ The first line of a file must be treated specially, since |lua_input_ln|
+must be told not to start with |get|.
+@^system dependencies@>
+
+@<Input the first line of |read_file[m]|@>=
+begin if lua_input_ln(read_file[m],(m+1),false) then read_open[m]:=normal
+else begin lua_a_close_in(read_file[m],(m+1)); read_open[m]:=closed;
+ end;
+end
+
+@ An empty line is appended at the end of a |read_file|.
+@^empty line at end of file@>
+
+@<Input the next line of |read_file[m]|@>=
+begin if not lua_input_ln(read_file[m],(m+1),true) then
+ begin lua_a_close_in(read_file[m],(m+1)); read_open[m]:=closed;
+ if align_state<>1000000 then
+ begin runaway;
+ print_err("File ended within "); print_esc("read");
+@.File ended within \\read@>
+ help1("This \read has unbalanced braces.");
+ align_state:=1000000; error;
+ end;
+ end;
+end
+
+@* \[28] Conditional processing.
+We consider now the way \TeX\ handles various kinds of \.{\\if} commands.
+
+@d unless_code=32 {amount added for `\.{\\unless}' prefix}
+@#
+@d if_char_code=0 { `\.{\\if}' }
+@d if_cat_code=1 { `\.{\\ifcat}' }
+@d if_int_code=2 { `\.{\\ifnum}' }
+@d if_dim_code=3 { `\.{\\ifdim}' }
+@d if_odd_code=4 { `\.{\\ifodd}' }
+@d if_vmode_code=5 { `\.{\\ifvmode}' }
+@d if_hmode_code=6 { `\.{\\ifhmode}' }
+@d if_mmode_code=7 { `\.{\\ifmmode}' }
+@d if_inner_code=8 { `\.{\\ifinner}' }
+@d if_void_code=9 { `\.{\\ifvoid}' }
+@d if_hbox_code=10 { `\.{\\ifhbox}' }
+@d if_vbox_code=11 { `\.{\\ifvbox}' }
+@d ifx_code=12 { `\.{\\ifx}' }
+@d if_eof_code=13 { `\.{\\ifeof}' }
+@d if_true_code=14 { `\.{\\iftrue}' }
+@d if_false_code=15 { `\.{\\iffalse}' }
+@d if_case_code=16 { `\.{\\ifcase}' }
+@d if_primitive_code=21 { `\.{\\ifprimitive}' }
+
+@<Put each...@>=
+primitive("if",if_test,if_char_code);
+@!@:if_char_}{\.{\\if} primitive@>
+primitive("ifcat",if_test,if_cat_code);
+@!@:if_cat_code_}{\.{\\ifcat} primitive@>
+primitive("ifnum",if_test,if_int_code);
+@!@:if_int_}{\.{\\ifnum} primitive@>
+primitive("ifdim",if_test,if_dim_code);
+@!@:if_dim_}{\.{\\ifdim} primitive@>
+primitive("ifodd",if_test,if_odd_code);
+@!@:if_odd_}{\.{\\ifodd} primitive@>
+primitive("ifvmode",if_test,if_vmode_code);
+@!@:if_vmode_}{\.{\\ifvmode} primitive@>
+primitive("ifhmode",if_test,if_hmode_code);
+@!@:if_hmode_}{\.{\\ifhmode} primitive@>
+primitive("ifmmode",if_test,if_mmode_code);
+@!@:if_mmode_}{\.{\\ifmmode} primitive@>
+primitive("ifinner",if_test,if_inner_code);
+@!@:if_inner_}{\.{\\ifinner} primitive@>
+primitive("ifvoid",if_test,if_void_code);
+@!@:if_void_}{\.{\\ifvoid} primitive@>
+primitive("ifhbox",if_test,if_hbox_code);
+@!@:if_hbox_}{\.{\\ifhbox} primitive@>
+primitive("ifvbox",if_test,if_vbox_code);
+@!@:if_vbox_}{\.{\\ifvbox} primitive@>
+primitive("ifx",if_test,ifx_code);
+@!@:ifx_}{\.{\\ifx} primitive@>
+primitive("ifeof",if_test,if_eof_code);
+@!@:if_eof_}{\.{\\ifeof} primitive@>
+primitive("iftrue",if_test,if_true_code);
+@!@:if_true_}{\.{\\iftrue} primitive@>
+primitive("iffalse",if_test,if_false_code);
+@!@:if_false_}{\.{\\iffalse} primitive@>
+primitive("ifcase",if_test,if_case_code);
+@!@:if_case_}{\.{\\ifcase} primitive@>
+primitive("ifprimitive",if_test,if_primitive_code);
+@!@:if_primitive_}{\.{\\ifprimitive} primitive@>
+primitive("ifpdfprimitive",if_test,if_primitive_code);
+@!@:if_primitive_}{\.{\\ifpdfprimitive} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+if_test: begin if chr_code>=unless_code then print_esc("unless");
+case chr_code mod unless_code of
+ if_cat_code:print_esc("ifcat");
+ if_int_code:print_esc("ifnum");
+ if_dim_code:print_esc("ifdim");
+ if_odd_code:print_esc("ifodd");
+ if_vmode_code:print_esc("ifvmode");
+ if_hmode_code:print_esc("ifhmode");
+ if_mmode_code:print_esc("ifmmode");
+ if_inner_code:print_esc("ifinner");
+ if_void_code:print_esc("ifvoid");
+ if_hbox_code:print_esc("ifhbox");
+ if_vbox_code:print_esc("ifvbox");
+ ifx_code:print_esc("ifx");
+ if_eof_code:print_esc("ifeof");
+ if_true_code:print_esc("iftrue");
+ if_false_code:print_esc("iffalse");
+ if_case_code:print_esc("ifcase");
+ if_primitive_code:print_esc("ifprimitive");
+ @/@<Cases of |if_test| for |print_cmd_chr|@>@/
+ othercases print_esc("if")
+ endcases;
+end;
+
+@ Conditions can be inside conditions, and this nesting has a stack
+that is independent of the |save_stack|.
+
+Four global variables represent the top of the condition stack:
+|cond_ptr| points to pushed-down entries, if any; |if_limit| specifies
+the largest code of a |fi_or_else| command that is syntactically legal;
+|cur_if| is the name of the current type of conditional; and |if_line|
+is the line number at which it began.
+
+If no conditions are currently in progress, the condition stack has the
+special state |cond_ptr=null|, |if_limit=normal|, |cur_if=0|, |if_line=0|.
+Otherwise |cond_ptr| points to a two-word node; the |type|, |subtype|, and
+|link| fields of the first word contain |if_limit|, |cur_if|, and
+|cond_ptr| at the next level, and the second word contains the
+corresponding |if_line|.
+
+@d if_node==49
+@d if_node_size=2 {number of words in stack entry for conditionals}
+@d if_limit_subtype(#)==subtype(#+1)
+@d if_limit_type(#)==type(#+1)
+@d if_line_field(#)==vlink(#+1)
+@d if_code=1 {code for \.{\\if...} being evaluated}
+@d fi_code=2 {code for \.{\\fi}}
+@d else_code=3 {code for \.{\\else}}
+@d or_code=4 {code for \.{\\or}}
+
+@<Glob...@>=
+@!cond_ptr:pointer; {top of the condition stack}
+@!if_limit:normal..or_code; {upper bound on |fi_or_else| codes}
+@!cur_if:small_number; {type of conditional being worked on}
+@!if_line:integer; {line where that conditional began}
+
+@ @<Set init...@>=
+cond_ptr:=null; if_limit:=normal; cur_if:=0; if_line:=0;
+
+@ @<Put each...@>=
+primitive("fi",fi_or_else,fi_code);
+@!@:fi_}{\.{\\fi} primitive@>
+text(frozen_fi):="fi"; eqtb[frozen_fi]:=eqtb[cur_val];
+primitive("or",fi_or_else,or_code);
+@!@:or_}{\.{\\or} primitive@>
+primitive("else",fi_or_else,else_code);
+@!@:else_}{\.{\\else} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+fi_or_else: if chr_code=fi_code then print_esc("fi")
+ else if chr_code=or_code then print_esc("or")
+ else print_esc("else");
+
+@ When we skip conditional text, we keep track of the line number
+where skipping began, for use in error messages.
+
+@<Glob...@>=
+@!skip_line:integer; {skipping began here}
+
+@ Here is a procedure that ignores text until coming to an \.{\\or},
+\.{\\else}, or \.{\\fi} at level zero of $\.{\\if}\ldots\.{\\fi}$
+nesting. After it has acted, |cur_chr| will indicate the token that
+was found, but |cur_tok| will not be set (because this makes the
+procedure run faster).
+
+@p procedure pass_text;
+label done;
+var l:integer; {level of $\.{\\if}\ldots\.{\\fi}$ nesting}
+@!save_scanner_status:small_number; {|scanner_status| upon entry}
+begin save_scanner_status:=scanner_status; scanner_status:=skipping; l:=0;
+skip_line:=line;
+loop@+ begin get_filtered_next;
+ if cur_cmd=fi_or_else then
+ begin if l=0 then goto done;
+ if cur_chr=fi_code then decr(l);
+ end
+ else if cur_cmd=if_test then incr(l);
+ end;
+done: scanner_status:=save_scanner_status;
+if tracing_ifs>0 then show_cur_cmd_chr;
+end;
+
+@ When we begin to process a new \.{\\if}, we set |if_limit:=if_code|; then
+if\/ \.{\\or} or \.{\\else} or \.{\\fi} occurs before the current \.{\\if}
+condition has been evaluated, \.{\\relax} will be inserted.
+For example, a sequence of commands like `\.{\\ifvoid1\\else...\\fi}'
+would otherwise require something after the `\.1'.
+
+@<Push the condition stack@>=
+begin p:=new_node(if_node,0); vlink(p):=cond_ptr;
+if_limit_type(p):=if_limit;
+if_limit_subtype(p):=cur_if;
+if_line_field(p):=if_line;
+cond_ptr:=p; cur_if:=cur_chr; if_limit:=if_code; if_line:=line;
+end
+
+@ @<Pop the condition stack@>=
+begin if if_stack[in_open]=cond_ptr then if_warning;
+ {conditionals possibly not properly nested with files}
+p:=cond_ptr;
+if_line:=if_line_field(p);
+cur_if:=if_limit_subtype(p);
+if_limit:=if_limit_type(p);
+cond_ptr:=vlink(p);
+flush_node(p);
+end
+
+@ Here's a procedure that changes the |if_limit| code corresponding to
+a given value of |cond_ptr|.
+
+@p procedure change_if_limit(@!l:small_number;@!p:pointer);
+label exit;
+var q:pointer;
+begin if p=cond_ptr then if_limit:=l {that's the easy case}
+else begin q:=cond_ptr;
+ loop@+ begin if q=null then confusion("if");
+@:this can't happen if}{\quad if@>
+ if vlink(q)=p then
+ begin if_limit_type(q):=l; return;
+ end;
+ q:=vlink(q);
+ end;
+ end;
+exit:end;
+
+@ A condition is started when the |expand| procedure encounters
+an |if_test| command; in that case |expand| reduces to |conditional|,
+which is a recursive procedure.
+@^recursion@>
+
+@p procedure conditional;
+label exit,common_ending;
+var b:boolean; {is the condition true?}
+@!r:"<"..">"; {relation to be evaluated}
+@!m,@!n,@!s:integer; {to be tested against the second operand}
+@!p,@!q:pointer; {for traversing token lists in \.{\\ifx} tests}
+@!save_scanner_status:small_number; {|scanner_status| upon entry}
+@!save_cond_ptr:pointer; {|cond_ptr| corresponding to this conditional}
+@!this_if:small_number; {type of this conditional}
+@!is_unless:boolean; {was this if preceded by `\.{\\unless}' ?}
+begin b:= false; {default is false, just in case}
+if tracing_ifs>0 then if tracing_commands<=1 then show_cur_cmd_chr;
+@<Push the condition stack@>;@+save_cond_ptr:=cond_ptr;
+is_unless:=(cur_chr>=unless_code); this_if:=cur_chr mod unless_code;@/
+@<Either process \.{\\ifcase} or set |b| to the value of a boolean condition@>;
+if is_unless then b:=not b;
+if tracing_commands>1 then @<Display the value of |b|@>;
+if b then
+ begin change_if_limit(else_code,save_cond_ptr);
+ return; {wait for \.{\\else} or \.{\\fi}}
+ end;
+@<Skip to \.{\\else} or \.{\\fi}, then |goto common_ending|@>;
+common_ending: if cur_chr=fi_code then @<Pop the condition stack@>
+else if_limit:=fi_code; {wait for \.{\\fi}}
+exit:end;
+
+@ In a construction like `\.{\\if\\iftrue abc\\else d\\fi}', the first
+\.{\\else} that we come to after learning that the \.{\\if} is false is
+not the \.{\\else} we're looking for. Hence the following curious
+logic is needed.
+
+@ @<Skip to \.{\\else} or \.{\\fi}...@>=
+loop@+ begin pass_text;
+ if cond_ptr=save_cond_ptr then
+ begin if cur_chr<>or_code then goto common_ending;
+ print_err("Extra "); print_esc("or");
+@.Extra \\or@>
+ help1("I'm ignoring this; it doesn't match any \if.");
+ error;
+ end
+ else if cur_chr=fi_code then @<Pop the condition stack@>;
+ end
+
+@ @<Either process \.{\\ifcase} or set |b|...@>=
+case this_if of
+if_char_code, if_cat_code: @<Test if two characters match@>;
+if_int_code, if_dim_code: @<Test relation between integers or dimensions@>;
+if_odd_code: @<Test if an integer is odd@>;
+if_vmode_code: b:=(abs(mode)=vmode);
+if_hmode_code: b:=(abs(mode)=hmode);
+if_mmode_code: b:=(abs(mode)=mmode);
+if_inner_code: b:=(mode<0);
+if_void_code, if_hbox_code, if_vbox_code: @<Test box register status@>;
+ifx_code: @<Test if two tokens match@>;
+if_eof_code: begin scan_four_bit_int; b:=(read_open[cur_val]=closed);
+ end;
+if_true_code: b:=true;
+if_false_code: b:=false;
+@/@<Cases for |conditional|@>@/
+if_case_code: @<Select the appropriate case
+ and |return| or |goto common_ending|@>;
+if_primitive_code: begin
+ save_scanner_status:=scanner_status;
+ scanner_status:=normal;
+ get_filtered_next;
+ scanner_status:=save_scanner_status;
+ m := prim_lookup(text(cur_cs));
+ b :=((cur_cmd<>undefined_cs) and
+ (m<>undefined_primitive) and
+ (cur_cmd=get_prim_eq_type(m)) and
+ (cur_chr=get_prim_equiv(m)));
+ end;
+{there are no other cases, but for -Wall: }
+othercases
+ b:=false;
+endcases
+
+@ @<Display the value of |b|@>=
+begin begin_diagnostic;
+if b then print("{true}")@+else print("{false}");
+end_diagnostic(false);
+end
+
+@ Here we use the fact that |"<"|, |"="|, and |">"| are consecutive ASCII
+codes.
+@^ASCII code@>
+
+@<Test relation between integers or dimensions@>=
+begin if this_if=if_int_code then scan_int@+else scan_normal_dimen;
+n:=cur_val; @<Get the next non-blank non-call...@>;
+if (cur_tok>=other_token+"<")and(cur_tok<=other_token+">") then
+ r:=cur_tok-other_token
+else begin print_err("Missing = inserted for ");
+@.Missing = inserted@>
+ print_cmd_chr(if_test,this_if);
+ help1("I was expecting to see `<', `=', or `>'. Didn't.");
+ back_error; r:="=";
+ end;
+if this_if=if_int_code then scan_int@+else scan_normal_dimen;
+case r of
+"<": b:=(n<cur_val);
+"=": b:=(n=cur_val);
+">": b:=(n>cur_val);
+othercases b:=false; {can't happen}
+end;
+end
+
+@ @<Test if an integer is odd@>=
+begin scan_int; b:=odd(cur_val);
+end
+
+@ @<Test box register status@>=
+begin scan_register_num; p:=box(cur_val);
+if this_if=if_void_code then b:=(p=null)
+else if p=null then b:=false
+else if this_if=if_hbox_code then b:=(type(p)=hlist_node)
+else b:=(type(p)=vlist_node);
+end
+
+@ An active character will be treated as category 13 following
+\.{\\if\\noexpand} or following \.{\\ifcat\\noexpand}. We use the fact that
+active characters have the smallest tokens, among all control sequences.
+
+The |(biggest_char-number_active_chars)| part is needed because only the
+bottom two planes are present as active characters in |eqtb|.
+
+@d get_x_token_or_active_char==@t@>@;
+ begin get_x_token;
+ if cur_cmd=relax then if cur_chr=no_expand_flag then
+ begin cur_cmd:=active_char;
+ cur_chr:=cur_tok-cs_token_flag-active_base+(biggest_char-number_active_chars);
+ end;
+ end
+
+@<Test if two characters match@>=
+begin get_x_token_or_active_char;
+if (cur_cmd>active_char)or(cur_chr>biggest_char) then {not a character}
+ begin m:=relax; n:=too_big_char;
+ end
+else begin m:=cur_cmd; n:=cur_chr;
+ end;
+get_x_token_or_active_char;
+if (cur_cmd>active_char)or(cur_chr>biggest_char) then
+ begin cur_cmd:=relax; cur_chr:=too_big_char;
+ end;
+if this_if=if_char_code then b:=(n=cur_chr)@+else b:=(m=cur_cmd);
+end
+
+@ Note that `\.{\\ifx}' will declare two macros different if one is \\{long}
+or \\{outer} and the other isn't, even though the texts of the macros are
+the same.
+
+We need to reset |scanner_status|, since \.{\\outer} control sequences
+are allowed, but we might be scanning a macro definition or preamble.
+
+@<Test if two tokens match@>=
+begin save_scanner_status:=scanner_status; scanner_status:=normal;
+get_filtered_next; n:=cur_cs; p:=cur_cmd; q:=cur_chr;
+get_filtered_next; if cur_cmd<>p then b:=false
+else if cur_cmd<call then b:=(cur_chr=q)
+else @<Test if two macro texts match@>;
+scanner_status:=save_scanner_status;
+end
+
+@ Note also that `\.{\\ifx}' decides that macros \.{\\a} and \.{\\b} are
+different in examples like this:
+$$\vbox{\halign{\.{#}\hfil&\qquad\.{#}\hfil\cr
+ {}\\def\\a\{\\c\}&
+ {}\\def\\c\{\}\cr
+ {}\\def\\b\{\\d\}&
+ {}\\def\\d\{\}\cr}}$$
+
+@<Test if two macro texts match@>=
+begin p:=link(cur_chr); q:=link(equiv(n)); {omit reference counts}
+if p=q then b:=true
+else begin while (p<>null)and(q<>null) do
+ if info(p)<>info(q) then p:=null
+ else begin p:=link(p); q:=link(q);
+ end;
+ b:=((p=null)and(q=null));
+ end;
+end
+
+@ @<Select the appropriate case and |return| or |goto common_ending|@>=
+begin scan_int; n:=cur_val; {|n| is the number of cases to pass}
+if tracing_commands>1 then
+ begin begin_diagnostic; print("{case "); print_int(n); print_char("}");
+ end_diagnostic(false);
+ end;
+while n<>0 do
+ begin pass_text;
+ if cond_ptr=save_cond_ptr then
+ if cur_chr=or_code then decr(n)
+ else goto common_ending
+ else if cur_chr=fi_code then @<Pop the condition stack@>;
+ end;
+change_if_limit(or_code,save_cond_ptr);
+return; {wait for \.{\\or}, \.{\\else}, or \.{\\fi}}
+end
+
+@ The processing of conditionals is complete except for the following
+code, which is actually part of |expand|. It comes into play when
+\.{\\or}, \.{\\else}, or \.{\\fi} is scanned.
+
+@<Terminate the current conditional and skip to \.{\\fi}@>=
+begin if tracing_ifs>0 then if tracing_commands<=1 then show_cur_cmd_chr;
+if cur_chr>if_limit then
+ if if_limit=if_code then insert_relax {condition not yet evaluated}
+ else begin print_err("Extra "); print_cmd_chr(fi_or_else,cur_chr);
+@.Extra \\or@>
+@.Extra \\else@>
+@.Extra \\fi@>
+ help1("I'm ignoring this; it doesn't match any \if.");
+ error;
+ end
+else begin while cur_chr<>fi_code do pass_text; {skip to \.{\\fi}}
+ @<Pop the condition stack@>;
+ end;
+end
+
+@* \[29] File names.
+It's time now to fret about file names. Besides the fact that different
+operating systems treat files in different ways, we must cope with the
+fact that completely different naming conventions are used by different
+groups of people. The following programs show what is required for one
+particular operating system; similar routines for other systems are not
+difficult to devise.
+@^fingers@>
+@^system dependencies@>
+
+\TeX\ assumes that a file name has three parts: the name proper; its
+``extension''; and a ``file area'' where it is found in an external file
+system. The extension of an input file or a write file is assumed to be
+`\.{.tex}' unless otherwise specified; it is `\.{.log}' on the
+transcript file that records each run of \TeX; it is `\.{.tfm}' on the font
+metric files that describe characters in the fonts \TeX\ uses; it is
+`\.{.dvi}' on the output files that specify typesetting information; and it
+is `\.{.fmt}' on the format files written by \.{INITEX} to initialize \TeX.
+The file area can be arbitrary on input files, but files are usually
+output to the user's current area. If an input file cannot be
+found on the specified area, \TeX\ will look for it on a special system
+area; this special area is intended for commonly used input files like
+\.{webmac.tex}.
+
+Simple uses of \TeX\ refer only to file names that have no explicit
+extension or area. For example, a person usually says `\.{\\input} \.{paper}'
+or `\.{\\font\\tenrm} \.= \.{helvetica}' instead of `\.{\\input}
+\.{paper.new}' or `\.{\\font\\tenrm} \.= \.{<csd.knuth>test}'. Simple file
+names are best, because they make the \TeX\ source files portable;
+whenever a file name consists entirely of letters and digits, it should be
+treated in the same way by all implementations of \TeX. However, users
+need the ability to refer to other files in their environment, especially
+when responding to error messages concerning unopenable files; therefore
+we want to let them use the syntax that appears in their favorite
+operating system.
+
+The following procedures don't allow spaces to be part of
+file names; but some users seem to like names that are spaced-out.
+System-dependent changes to allow such things should probably
+be made with reluctance, and only when an entire file name that
+includes spaces is ``quoted'' somehow.
+
+@ In order to isolate the system-dependent aspects of file names, the
+@^system dependencies@>
+system-independent parts of \TeX\ are expressed in terms
+of three system-dependent
+procedures called |begin_name|, |more_name|, and |end_name|. In
+essence, if the user-specified characters of the file name are $c_1\ldots c_n$,
+the system-independent driver program does the operations
+$$|begin_name|;\,|more_name|(c_1);\,\ldots\,;|more_name|(c_n);
+\,|end_name|.$$
+These three procedures communicate with each other via global variables.
+Afterwards the file name will appear in the string pool as three strings
+called |cur_name|\penalty10000\hskip-.05em,
+|cur_area|, and |cur_ext|; the latter two are null (i.e.,
+|""|), unless they were explicitly specified by the user.
+
+Actually the situation is slightly more complicated, because \TeX\ needs
+to know when the file name ends. The |more_name| routine is a function
+(with side effects) that returns |true| on the calls |more_name|$(c_1)$,
+\dots, |more_name|$(c_{n-1})$. The final call |more_name|$(c_n)$
+returns |false|; or, it returns |true| and the token following $c_n$ is
+something like `\.{\\hbox}' (i.e., not a character). In other words,
+|more_name| is supposed to return |true| unless it is sure that the
+file name has been completely scanned; and |end_name| is supposed to be able
+to finish the assembly of |cur_name|, |cur_area|, and |cur_ext| regardless of
+whether $|more_name|(c_n)$ returned |true| or |false|.
+
+@<Glob...@>=
+@!cur_name:str_number; {name of file just scanned}
+@!cur_area:str_number; {file area just scanned, or \.{""}}
+@!cur_ext:str_number; {file extension just scanned, or \.{""}}
+
+@ The file names we shall deal with for illustrative purposes have the
+following structure: If the name contains `\.>' or `\.:', the file area
+consists of all characters up to and including the final such character;
+otherwise the file area is null. If the remaining file name contains
+`\..', the file extension consists of all such characters from the first
+remaining `\..' to the end, otherwise the file extension is null.
+@^system dependencies@>
+
+We can scan such file names easily by using two global variables that keep track
+of the occurrences of area and extension delimiters:
+
+@<Glob...@>=
+@!area_delimiter:pool_pointer; {the most recent `\.>' or `\.:', if any}
+@!ext_delimiter:pool_pointer; {the relevant `\..', if any}
+
+@ Input files that can't be found in the user's area may appear in a standard
+system area called |TEX_area|. Font metric files whose areas are not given
+explicitly are assumed to appear in a standard system area called
+|TEX_font_area|. $\Omega$'s compiled translation process files whose areas
+are not given explicitly are assumed to appear in a standard system area
+called |OMEGA_ocp_area|. These system area names will, of course, vary
+from place to place.
+@^system dependencies@>
+
+@d TEX_area=="TeXinputs:"
+@.TeXinputs@>
+@d TEX_font_area=="TeXfonts:"
+@.TeXfonts@>
+@d OMEGA_ocp_area=="OmegaOCPs:"
+@.OmegaOCPs@>
+
+@ Here now is the first of the system-dependent routines for file name scanning.
+@^system dependencies@>
+
+@p procedure begin_name;
+begin area_delimiter:=0; ext_delimiter:=0;
+end;
+
+@ And here's the second. The string pool might change as the file name is
+being scanned, since a new \.{\\csname} might be entered; therefore we keep
+|area_delimiter| and |ext_delimiter| relative to the beginning of the current
+string, instead of assigning an absolute address like |pool_ptr| to them.
+@^system dependencies@>
+
+@p function more_name(@!c:ASCII_code):boolean;
+begin if c=" " then more_name:=false
+else begin str_room(1); append_char(c); {contribute |c| to the current string}
+ if (c=">")or(c=":") then
+ begin area_delimiter:=cur_length; ext_delimiter:=0;
+ end
+ else if (c=".")and(ext_delimiter=0) then ext_delimiter:=cur_length;
+ more_name:=true;
+ end;
+end;
+
+@ The third.
+@^system dependencies@>
+
+@p procedure end_name;
+begin if str_ptr+3>(max_strings+string_offset) then
+ overflow("number of strings",max_strings-init_str_ptr);
+@:TeX capacity exceeded number of strings}{\quad number of strings@>
+if area_delimiter=0 then cur_area:=""
+else begin cur_area:=str_ptr;
+ str_start_macro(str_ptr+1):=str_start_macro(str_ptr)+area_delimiter; incr(str_ptr);
+ end;
+if ext_delimiter=0 then
+ begin cur_ext:=""; cur_name:=make_string;
+ end
+else begin cur_name:=str_ptr;
+ str_start_macro(str_ptr+1):=str_start_macro(str_ptr)+ext_delimiter-area_delimiter-1;
+ incr(str_ptr); cur_ext:=make_string;
+ end;
+end;
+
+@ Conversely, here is a routine that takes three strings and prints a file
+name that might have produced them. (The routine is system dependent, because
+some operating systems put the file area last instead of first.)
+@^system dependencies@>
+
+@<Basic printing...@>=
+procedure print_file_name(@!n,@!a,@!e:integer);
+begin slow_print(a); slow_print(n); slow_print(e);
+end;
+
+@ Another system-dependent routine is needed to convert three internal
+\TeX\ strings
+into the |nameoffile| value that is used to open files. The present code
+allows both lowercase and uppercase letters in the file name.
+@^system dependencies@>
+
+@d append_to_name(#)==begin c:=#; incr(k);
+ if k<=file_name_size then nameoffile[k]:=xchr[c];
+ end
+
+@p procedure pack_file_name(@!n,@!a,@!e:str_number);
+var k:integer; {number of positions filled in |nameoffile|}
+@!c: ASCII_code; {character being packed}
+@!j:pool_pointer; {index into |str_pool|}
+begin k:=0;
+for j:=str_start_macro(a) to str_start_macro(a+1)-1 do append_to_name(so(str_pool[j]));
+for j:=str_start_macro(n) to str_start_macro(n+1)-1 do append_to_name(so(str_pool[j]));
+for j:=str_start_macro(e) to str_start_macro(e+1)-1 do append_to_name(so(str_pool[j]));
+if k<=file_name_size then namelength:=k@+else namelength:=file_name_size;
+for k:=namelength+1 to file_name_size do nameoffile[k]:=' ';
+end;
+
+@ A messier routine is also needed, since format file names must be scanned
+before \TeX's string mechanism has been initialized. We shall use the
+global variable |TEX_format_default| to supply the text for default system areas
+and extensions related to format files.
+@^system dependencies@>
+
+@d format_default_length=20 {length of the |TEX_format_default| string}
+@d format_area_length=11 {length of its area part}
+@d format_ext_length=4 {length of its `\.{.fmt}' part}
+@d format_extension=".fmt" {the extension, as a \.{WEB} constant}
+
+@<Glob...@>=
+@!TEX_format_default:packed array[1..format_default_length] of char;
+
+@ @<Set init...@>=
+TEX_format_default:='TeXformats:plain.fmt';
+@.TeXformats@>
+@.plain@>
+@^system dependencies@>
+
+@ @<Check the ``constant'' values for consistency@>=
+if format_default_length>file_name_size then bad:=31;
+
+@ Here is the messy routine that was just mentioned. It sets |nameoffile|
+from the first |n| characters of |TEX_format_default|, followed by
+|buffer[a..b]|, followed by the last |format_ext_length| characters of
+|TEX_format_default|.
+
+We dare not give error messages here, since \TeX\ calls this routine before
+the |error| routine is ready to roll. Instead, we simply drop excess characters,
+since the error will be detected in another way when a strange file name
+isn't found.
+@^system dependencies@>
+
+@p procedure pack_buffered_name(@!n:integer;@!a,@!b:integer);
+var k:integer; {number of positions filled in |nameoffile|}
+@!c: ASCII_code; {character being packed}
+@!j:integer; {index into |buffer| or |TEX_format_default|}
+begin if n+b-a+1+format_ext_length>file_name_size then
+ b:=a+file_name_size-n-1-format_ext_length;
+k:=0;
+for j:=1 to n do append_to_name(TEX_format_default[j]);
+for j:=a to b do append_to_name(buffer[j]);
+for j:=format_default_length-format_ext_length+1 to format_default_length do
+ append_to_name(TEX_format_default[j]);
+if k<=file_name_size then namelength:=k@+else namelength:=file_name_size;
+for k:=namelength+1 to file_name_size do nameoffile[k]:=' ';
+end;
+
+@ Here is the only place we use |pack_buffered_name|. This part of the program
+becomes active when a ``virgin'' \TeX\ is trying to get going, just after
+the preliminary initialization, or when the user is substituting another
+format file by typing `\.\&' after the initial `\.{**}' prompt. The buffer
+contains the first line of input in |buffer[loc..(last-1)]|, where
+|loc<last| and |buffer[loc]<>" "|.
+
+@<Declare the function called |open_fmt_file|@>=
+function open_fmt_file:boolean;
+label found,exit;
+var j:0..buf_size; {the first space after the format file name}
+begin j:=loc;
+if buffer[loc]="&" then
+ begin incr(loc); j:=loc; buffer[last]:=" ";
+ while buffer[j]<>" " do incr(j);
+ pack_buffered_name(0,loc,j-1); {try first without the system file area}
+ if w_open_in(fmt_file) then goto found;
+ pack_buffered_name(format_area_length,loc,j-1);
+ {now try the system format file area}
+ if w_open_in(fmt_file) then goto found;
+ wake_up_terminal;
+ wterm_ln('Sorry, I can''t find that format;',' will try PLAIN.');
+@.Sorry, I can't find...@>
+ update_terminal;
+ end;
+ {now pull out all the stops: try for the system \.{plain} file}
+pack_buffered_name(format_default_length-format_ext_length,1,0);
+if not w_open_in(fmt_file) then
+ begin wake_up_terminal;
+ wterm_ln('I can''t find the PLAIN format file!');
+@.I can't find PLAIN...@>
+@.plain@>
+ open_fmt_file:=false; return;
+ end;
+found:loc:=j; open_fmt_file:=true;
+exit:end;
+
+@ Operating systems often make it possible to determine the exact name (and
+possible version number) of a file that has been opened. The following routine,
+which simply makes a \TeX\ string from the value of |nameoffile|, should
+ideally be changed to deduce the full name of file~|f|, which is the file
+most recently opened, if it is possible to do this in a \PASCAL\ program.
+@^system dependencies@>
+
+This routine might be called after string memory has overflowed, hence
+we dare not use `|str_room|'.
+
+@d a_make_name_string(#)==make_name_string
+@d b_make_name_string(#)==make_name_string
+@d w_make_name_string(#)==make_name_string
+
+@p function make_name_string:str_number;
+var k:1..file_name_size; {index into |nameoffile|}
+begin if (pool_ptr+namelength>pool_size)or(str_ptr=max_strings)or
+ (cur_length>0) then
+ make_name_string:="?"
+else begin for k:=1 to namelength do append_char(nameoffile[k]);
+ make_name_string:=make_string;
+ end;
+end;
+
+@ Now let's consider the ``driver''
+routines by which \TeX\ deals with file names
+in a system-independent manner. First comes a procedure that looks for a
+file name in the input by calling |get_x_token| for the information.
+
+@p procedure scan_file_name;
+label done;
+begin name_in_progress:=true; begin_name;
+@<Get the next non-blank non-call...@>;
+loop@+begin if (cur_cmd>other_char)or(cur_chr>biggest_char) then {not a character}
+ begin back_input; goto done;
+ end;
+ if not more_name(cur_chr) then goto done;
+ get_x_token;
+ end;
+done: end_name; name_in_progress:=false;
+end;
+
+@ The global variable |name_in_progress| is used to prevent recursive
+use of |scan_file_name|, since the |begin_name| and other procedures
+communicate via global variables. Recursion would arise only by
+devious tricks like `\.{\\input\\input f}'; such attempts at sabotage
+must be thwarted. Furthermore, |name_in_progress| prevents \.{\\input}
+@^recursion@>
+from being initiated when a font size specification is being scanned.
+
+Another global variable, |job_name|, contains the file name that was first
+\.{\\input} by the user. This name is extended by `\.{.log}' and `\.{.dvi}'
+and `\.{.fmt}' in the names of \TeX's output files.
+
+@<Glob...@>=
+@!name_in_progress:boolean; {is a file name being scanned?}
+@!job_name:str_number; {principal file name}
+@!log_opened:boolean; {has the transcript file been opened?}
+
+@ Initially |job_name=0|; it becomes nonzero as soon as the true name is known.
+We have |job_name=0| if and only if the `\.{log}' file has not been opened,
+except of course for a short time just after |job_name| has become nonzero.
+
+@<Initialize the output...@>=
+job_name:=0; name_in_progress:=false; log_opened:=false;
+
+@ Here is a routine that manufactures the output file names, assuming that
+|job_name<>0|. It ignores and changes the current settings of |cur_area|
+and |cur_ext|.
+
+@d pack_cur_name==pack_file_name(cur_name,cur_area,cur_ext)
+
+@p procedure pack_job_name(@!s:str_number); {|s = ".log"|, |".dvi"|, or
+ |format_extension|}
+begin cur_area:=""; cur_ext:=s;
+cur_name:=job_name; pack_cur_name;
+end;
+
+@ If some trouble arises when \TeX\ tries to open a file, the following
+routine calls upon the user to supply another file name. Parameter~|s|
+is used in the error message to identify the type of file; parameter~|e|
+is the default extension if none is given. Upon exit from the routine,
+variables |cur_name|, |cur_area|, |cur_ext|, and |nameoffile| are
+ready for another attempt at file opening.
+
+@p procedure prompt_file_name(@!s,@!e:str_number);
+label done;
+var k:0..buf_size; {index into |buffer|}
+begin if interaction=scroll_mode then wake_up_terminal;
+if s="input file name" then print_err("I can't find file `")
+@.I can't find file x@>
+else print_err("I can't write on file `");
+@.I can't write on file x@>
+print_file_name(cur_name,cur_area,cur_ext); print("'.");
+if e=".tex" then show_context;
+print_nl("Please type another "); print(s);
+@.Please type...@>
+if interaction<scroll_mode then
+ fatal_error("*** (job aborted, file error in nonstop mode)");
+@.job aborted, file error...@>
+clear_terminal; prompt_input(": "); @<Scan file name in the buffer@>;
+if cur_ext="" then cur_ext:=e;
+pack_cur_name;
+end;
+
+@ @<Scan file name in the buffer@>=
+begin begin_name; k:=first;
+while (buffer[k]=" ")and(k<last) do incr(k);
+loop@+ begin if k=last then goto done;
+ if not more_name(buffer[k]) then goto done;
+ incr(k);
+ end;
+done:end_name;
+end
+
+@ Here's an example of how these conventions are used. Whenever it is time to
+ship out a box of stuff, we shall use the macro |ensure_dvi_open|.
+
+@d ensure_dvi_open==if output_file_name=0 then
+ begin if job_name=0 then open_log_file;
+ pack_job_name(".dvi");
+ while not lua_b_open_out(dvi_file) do
+ prompt_file_name("file name for output",".dvi");
+ dvi_file:=name_file_pointer ;
+ output_file_name:=b_make_name_string(dvi_file);
+ end
+
+@<Glob...@>=
+@!dvi_file: byte_file; {the device-independent output goes here}
+@!output_file_name: str_number; {full name of the output file}
+@!log_name:str_number; {full name of the log file}
+
+@ @<Initialize the output...@>=output_file_name:=0;
+
+@ The |open_log_file| routine is used to open the transcript file and to help
+it catch up to what has previously been printed on the terminal.
+
+@p procedure open_log_file;
+var old_setting:0..max_selector; {previous |selector| setting}
+@!k:0..buf_size; {index into |months| and |buffer|}
+@!l:0..buf_size; {end of first input line}
+@!months:packed array [1..36] of char; {abbreviations of month names}
+begin old_setting:=selector;
+if job_name=0 then job_name:="texput";
+@.texput@>
+pack_job_name(".log");
+while not lua_a_open_out(addressof(log_file),0) do @<Try to get a different log file name@>;
+log_file := name_file_pointer;
+log_name:=a_make_name_string(log_file);
+selector:=log_only; log_opened:=true;
+if not callback_defined(start_run_callback) then begin
+ @<Print the banner line, including the date and time@>;
+ input_stack[input_ptr]:=cur_input; {make sure bottom level is in memory}
+ print_nl("**");
+@.**@>
+ l:=input_stack[0].limit_field; {last position of first line}
+ if buffer[l]=end_line_char then decr(l); { TODO: multichar endlinechar}
+ for k:=1 to l do print(buffer[k]);
+ print_ln; {now the transcript file contains the first line of input}
+ end
+else begin
+ flush_loggable_info;
+end;
+selector:=old_setting+2; {|log_only| or |term_and_log|}
+end;
+
+@ Sometimes |open_log_file| is called at awkward moments when \TeX\ is
+unable to print error messages or even to |show_context|.
+The |prompt_file_name| routine can result in a |fatal_error|, but the |error|
+routine will not be invoked because |log_opened| will be false.
+
+The normal idea of |batch_mode| is that nothing at all should be written
+on the terminal. However, in the unusual case that
+no log file could be opened, we make an exception and allow
+an explanatory message to be seen.
+
+Incidentally, the program always refers to the log file as a `\.{transcript
+file}', because some systems cannot use the extension `\.{.log}' for
+this file.
+
+@<Try to get a different log file name@>=
+begin selector:=term_only;
+prompt_file_name("transcript file name",".log");
+end
+
+@ @<Print the banner...@>=
+begin wlog(banner);
+slow_print(format_ident); print(" ");
+print_int(day); print_char(" ");
+months:='JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC';
+for k:=3*month-2 to 3*month do wlog(months[k]);
+print_char(" "); print_int(year); print_char(" ");
+print_two(time div 60); print_char(":"); print_two(time mod 60);
+end
+
+@ Let's turn now to the procedure that is used to initiate file reading
+when an `\.{\\input}' command is being processed.
+
+@p procedure start_input; {\TeX\ will \.{\\input} something}
+label done;
+var temp_str:str_number;
+begin scan_file_name; {set |cur_name| to desired file name}
+if cur_ext="" then cur_ext:=".tex";
+pack_cur_name;
+loop@+ begin begin_file_reading; {set up |cur_file| and new level of input}
+ if lua_a_open_in(cur_file,0) then goto done;
+ end_file_reading; {remove the level that didn't work}
+ prompt_file_name("input file name",".tex");
+ end;
+done:
+cur_file := name_file_pointer;
+name:=a_make_name_string(cur_file);
+if job_name=0 then
+ begin job_name:=cur_name; open_log_file;
+ end; {|open_log_file| doesn't |show_context|, so |limit|
+ and |loc| needn't be set to meaningful values yet}
+if tracefilenames then begin
+ if term_offset+length(name)>max_print_line-2 then print_ln
+ else if (term_offset>0)or(file_offset>0) then print_char(" ");
+ print_char("(");
+ slow_print(name);
+end;
+incr(open_parens);
+update_terminal;
+state:=new_line;
+if name=str_ptr-1 then {we can conserve string pool space now}
+ begin flush_string; name:=cur_name;
+ end;
+@<Read the first line of the new file@>;
+end;
+
+@ Here we have to remember to tell the |lua_input_ln| routine not to
+start with a |get|. If the file is empty, it is considered to
+contain a single blank line.
+@^system dependencies@>
+@^empty line at end of file@>
+
+@<Read the first line...@>=
+begin line:=1;
+if lua_input_ln(cur_file,0,false) then do_nothing;
+firm_up_the_line;
+if end_line_char_inactive then decr(limit)
+else buffer[limit]:=end_line_char;
+first:=limit+1; loc:=start;
+end
+
+@* \[30] Font metric data and OCPS.
+\TeX\ gets its knowledge about fonts from font metric files, also called
+\.{TFM} files; the `\.T' in `\.{TFM}' stands for \TeX,
+but other programs know about them too.
+@:TFM files}{\.{TFM} files@>
+@^font metric files@>
+
+@ When the user defines \.{\\font\\f}, say, \TeX\ assigns an internal number
+to the user's font~\.{\\f}. Adding this number to |font_id_base| gives the
+|eqtb| location of a ``frozen'' control sequence that will always select
+the font.
+
+@<Types...@>=
+@!internal_font_number=integer; {|font| in a |char_node|}
+@!font_index=integer; {index into |font_info|}
+
+@ @<Glob...@>=
+@!font_bytes:integer;
+
+@ \TeX\ always knows at least one font, namely the null font. It has no
+characters, and its seven parameters are all equal to zero.
+
+@<Initialize table...@>=
+create_null_font;
+font_bytes:=0;
+
+@ @<Put each...@>=
+primitive("nullfont",set_font,null_font);
+@!@:null_font_}{\.{\\nullfont} primitive@>
+text(frozen_null_font):="nullfont"; eqtb[frozen_null_font]:=eqtb[cur_val];
+
+@ @<The em width for |cur_font|@>=quad(cur_font)
+
+@ @<The x-height for |cur_font|@>=x_height(cur_font)
+
+@ Before we forget about the format of these tables, let's deal with two
+of \TeX's basic scanning routines related to font information.
+
+@<Declare procedures that scan font-related stuff@>=
+procedure scan_font_ident;
+var f:internal_font_number;
+@!m:halfword;
+begin @<Get the next non-blank non-call...@>;
+if (cur_cmd=def_font) or (cur_cmd=letterspace_font) then f:=cur_font
+else if cur_cmd=set_font then begin
+ f:=cur_chr;
+ set_font_touched(f,1);
+ end
+else if cur_cmd=def_family then begin
+ m:=cur_chr; scan_math_family_int; f:=equiv(m+cur_val);
+ set_font_touched(f,1);
+ end
+else begin print_err("Missing font identifier");
+@.Missing font identifier@>
+ help2("I was looking for a control sequence whose")@/
+ ("current meaning has been defined by \font.");
+ back_error; f:=null_font;
+ end;
+cur_val:=f;
+end;
+
+@ The following routine is used to implement `\.{\\fontdimen} |n| |f|'.
+The boolean parameter |writing| is set |true| if the calling program
+intends to change the parameter value.
+
+@<Declare procedures that scan font-related stuff@>=
+procedure set_font_dimen;forward;
+procedure get_font_dimen;forward;
+
+@ @p
+procedure set_font_dimen;
+label exit;
+var f:internal_font_number;
+@!n:integer; {the parameter number}
+begin scan_int; n:=cur_val; scan_font_ident; f:=cur_val;
+ if n<=0 then
+ @<Issue a font parameter error message, and return@>
+ else begin
+ if n>font_params(f) then
+ if font_touched(f) then @<Issue a font parameter error message, and return@>
+ else @<Increase the number of parameters in the font@>;
+ end;
+ scan_optional_equals; scan_normal_dimen;
+ set_font_param(f,n,cur_val);
+exit:
+end;
+@#
+procedure get_font_dimen;
+label exit;
+var f:internal_font_number;
+@!n:integer; {the parameter number}
+begin scan_int; n:=cur_val; scan_font_ident; f:=cur_val;
+ cur_val:=0; { initialize return value }
+ if n<=0 then
+ @<Issue a font parameter error message, and return@>
+ else begin
+ if n>font_params(f) then
+ if font_touched(f) then @<Issue a font parameter error message, and return@>
+ else @<Increase the number of parameters in the font@>;
+ end;
+ cur_val:=font_param(f,n);
+exit:
+ scanned_result(cur_val)(dimen_val);
+end;
+
+@ @<Issue a font parameter error message, and return@>=
+begin print_err("Font "); print_esc(font_id_text(f));
+ print(" has only "); print_int(font_params(f));
+ print(" fontdimen parameters");
+@.Font x has only...@>
+ help2("To increase the number of font parameters, you must")@/
+ ("use \fontdimen immediately after the \font is loaded.");
+ error;
+ return;
+end
+
+@ @<Increase the number of parameters...@>=
+begin repeat
+ set_font_param(f,(font_params(f)+1),0);
+until n=font_params(f);
+end
+
+
+@ When \TeX\ wants to typeset a character that doesn't exist, the
+character node is not created; thus the output routine can assume
+that characters exist when it sees them. The following procedure
+prints a warning message unless the user has suppressed it.
+
+@p procedure char_warning(@!f:internal_font_number;@!c:integer);
+var old_setting: integer; {saved value of |tracing_online|}
+begin if tracing_lost_chars>0 then
+ begin old_setting:=tracing_online;
+ if tracing_lost_chars>1 then tracing_online:=1;
+ begin begin_diagnostic;
+ print_nl("Missing character: There is no ");
+@.Missing character@>
+ print(c); print(" (");
+ print_int(c); print(") in font ");
+ print_font_name(f);
+ print_char("!"); end_diagnostic(false);
+ end;
+ tracing_online:=old_setting;
+ end;
+end;
+
+@
+@<Types...@>=
+@!active_index=0..active_mem_size;
+
+@
+@d active_ocp(#)==active_info[#].hh.b0
+@d active_counter(#)==active_info[#].hh.b1
+@d active_lstack_no(#)==active_info[#+1].sc
+
+@<Glob...@>=
+@!active_info:array[active_index] of memory_word;
+@!active_min_ptr:active_index; {first unused word of |active_info|}
+@!active_max_ptr:active_index; {last unused word of |active_info|}
+@!active_real:active_index;
+@!holding:array[active_index] of ocp_list_index;
+
+@
+@<Initialize table...@>=
+active_min_ptr:=0;
+active_real:=0;
+
+@
+@p
+function is_last_ocp(llstack_no:scaled; counter:integer):integer;
+begin
+active_min_ptr:=equiv(ocp_active_min_ptr_base);
+active_max_ptr:=equiv(ocp_active_max_ptr_base);
+active_real:=active_min_ptr;
+while (active_real < active_max_ptr) and
+ (active_lstack_no(active_real) < llstack_no) do begin
+ active_real:=active_real+2;
+ end;
+while (active_real < active_max_ptr) and
+ (active_lstack_no(active_real) = llstack_no) and
+ (active_counter(active_real) <= counter) do begin
+ active_real:=active_real+2;
+ end;
+is_last_ocp := (active_real=active_max_ptr);
+end;
+
+procedure print_active_ocps;
+var i:integer;
+begin
+print_nl("Active ocps: [");
+i:=active_min_ptr;
+while i<active_max_ptr do begin
+ print("(");
+ print_scaled(active_lstack_no(i));
+ print(",");
+ print_int(active_counter(i));
+ print(",");
+ print_esc(ocp_id_text(active_ocp(i)));
+ print(")");
+ if i<>(active_max_ptr-2) then print(",");
+ i:=i+2;
+ end;
+print("]");
+end;
+
+procedure add_ocp_stack(min_index:integer; min_value:scaled);
+var p:ocp_lstack_index;
+ llstack_no:scaled;
+ counter:integer;
+ m:scaled;
+begin
+m:=min_value; { TH: whatever this is ..}
+p:=ocp_list_lstack(holding[min_index]);
+llstack_no:=ocp_list_lstack_no(holding[min_index]);
+counter:=0;
+while not (is_null_ocp_lstack(p)) do begin
+ active_ocp(active_max_ptr):=ocp_lstack_ocp(p);
+ active_counter(active_max_ptr):=counter;
+ active_lstack_no(active_max_ptr):=llstack_no;
+ p:=ocp_lstack_lnext(p);
+ active_max_ptr:=active_max_ptr+2;
+ incr(counter); {no overflow problem}
+ end;
+end;
+
+procedure active_compile;
+var i:integer;
+ min_index:integer;
+ min_stack_ocp:scaled;
+ old_min:scaled;
+ max_active:integer;
+ stack_value:scaled;
+begin
+active_min_ptr:=active_max_ptr;
+min_stack_ocp:=ocp_maxint;
+max_active:=equiv(ocp_active_number_base)-1;
+min_index:=max_active; {TH I hope ... }
+for i:=max_active downto 0 do begin
+ holding[i]:=ocp_list_list[equiv(ocp_active_base+i)];
+ stack_value:=ocp_list_lstack_no(holding[i]);
+ if stack_value<min_stack_ocp then begin
+ min_index:=i;
+ min_stack_ocp:=stack_value;
+ end;
+ end;
+while min_stack_ocp<ocp_maxint do begin
+ add_ocp_stack(min_index, min_stack_ocp);
+ old_min:=min_stack_ocp;
+ min_stack_ocp:=ocp_maxint;
+ for i:=max_active downto 0 do begin
+ stack_value:=ocp_list_lstack_no(holding[i]);
+ while old_min=stack_value do begin
+ holding[i]:=ocp_list_lnext(holding[i]);
+ stack_value:=ocp_list_lstack_no(holding[i]);
+ end;
+ if stack_value<min_stack_ocp then begin
+ min_index:=i;
+ min_stack_ocp:=stack_value;
+ end;
+ end;
+ end;
+end;
+
+@ Here we begin the \.{OCP} file handling.
+
+@<Glob...@>=
+@!ocp_file:byte_file;
+
+@ So that is what \.{OCP} files hold.
+
+When the user defines \.{\\ocp\\f}, say, \TeX\ assigns an internal number
+to the user's ocp~\.{\\f}. Adding this number to |ocp_id_base| gives the
+|eqtb| location of a ``frozen'' control sequence that will always select
+the ocp.
+
+@<Types...@>=
+@!internal_ocp_number=ocp_base..ocp_biggest;
+@!ocp_index=integer;
+
+@ Here now is the array of ocp arrays.
+
+@<Glob...@>=
+@!ocp_ptr:internal_ocp_number; {largest internal ocp number in use}
+@!ocp_buffer:^real_eight_bits; {byte buffer for ocp files}
+@!ocp_size:integer; {total size of the ocp file}
+@!ocp_cur:integer; {index into |ocp_buffer|}
+
+@ @<Set init...@>=
+ocp_buffer:=0; ocp_size:=0; ocp_cur:=0;
+
+@ Besides the arrays just enumerated, we have two directory arrays that
+make it easy to get at the individual entries in |ocp_info|.
+The beginning of the info for the |j|-th state in the |i|-th ocp is at
+location |ocp_info[ocp_state_base[i]+j]| and the |k|-th entry is in
+location |ocp_info[ocp_info[ocp_state_base[i]+j]+k]|.
+(These formulas assume that |min_quarterword| has already been
+added to |i|, |j| and |k|, since $\Omega$ stores its quarterwords that way.)
+
+@d ocp_info_end(#)==#]
+@d ocp_info(#)==ocp_tables[#,ocp_info_end
+@d offset_ocp_file_size=0
+@d offset_ocp_name=1
+@d offset_ocp_area=offset_ocp_name+1
+@d offset_ocp_external=offset_ocp_area+1
+@d offset_ocp_external_arg=offset_ocp_external+1
+@d offset_ocp_input=offset_ocp_external_arg+1
+@d offset_ocp_output=offset_ocp_input+1
+@d offset_ocp_no_tables=offset_ocp_output+1
+@d offset_ocp_no_states=offset_ocp_no_tables+1
+@d offset_ocp_table_base=offset_ocp_no_states+1
+@d offset_ocp_state_base=offset_ocp_table_base+1
+@d offset_ocp_info=offset_ocp_state_base+1
+@d ocp_file_size(#)==ocp_info(#)(offset_ocp_file_size)
+@d ocp_name(#)==ocp_info(#)(offset_ocp_name)
+@d ocp_area(#)==ocp_info(#)(offset_ocp_area)
+@d ocp_external(#)==ocp_info(#)(offset_ocp_external)
+@d ocp_external_arg(#)==ocp_info(#)(offset_ocp_external_arg)
+@d ocp_input(#)==ocp_info(#)(offset_ocp_input)
+@d ocp_output(#)==ocp_info(#)(offset_ocp_output)
+@d ocp_no_tables(#)==ocp_info(#)(offset_ocp_no_tables)
+@d ocp_no_states(#)==ocp_info(#)(offset_ocp_no_states)
+@d ocp_table_base(#)==ocp_info(#)(offset_ocp_table_base)
+@d ocp_state_base(#)==ocp_info(#)(offset_ocp_state_base)
+
+@ $\Omega$ always knows at least one ocp, namely the null ocp.
+It does nothing.
+
+@<Initialize table...@>=
+ocp_ptr:=null_ocp;
+allocate_ocp_table(null_ocp,17);
+ocp_file_size(null_ocp):=17;
+ocp_name(null_ocp):="nullocp"; ocp_area(null_ocp):="";
+ocp_external(null_ocp):=0; ocp_external_arg(null_ocp):=0;
+ocp_input(null_ocp):=1; ocp_output(null_ocp):=1;
+ocp_no_tables(null_ocp):=0;
+ocp_no_states(null_ocp):=1;
+ocp_table_base(f):=offset_ocp_info;
+ocp_state_base(f):=offset_ocp_info;
+ocp_info(null_ocp)(offset_ocp_info) := offset_ocp_info+2; {number of entries}
+ocp_info(null_ocp)(offset_ocp_info+1) := offset_ocp_info+5; {number of entries}
+ocp_info(null_ocp)(offset_ocp_info+2) := 23; {|OTP_LEFT_START|}
+ocp_info(null_ocp)(offset_ocp_info+3) := 3; {|OTP_RIGHT_CHAR|}
+ocp_info(null_ocp)(offset_ocp_info+4) := 36; {|OTP_STOP|}
+
+
+@ @<Put each...@>=
+primitive("nullocp", set_ocp, null_ocp);
+text(frozen_null_ocp) := "nullocp";
+eqtb[frozen_null_ocp] := eqtb[cur_val];
+geq_define(ocp_active_number_base, data, 0);
+geq_define(ocp_active_min_ptr_base, data, 0);
+geq_define(ocp_active_max_ptr_base, data, 0);
+
+@ Of course we want to define macros that suppress the detail of how ocp
+information is actually packed, so that we don't have to write things like
+$$\hbox{|ocp_info[k+ocp_info[j+ocp_state_base[i]]]|}$$
+too often. The \.{WEB} definitions here make |ocp_state_entry(i)(j)(k)|
+(|ocp_table_entry(i)(j)(k)|) the |k|-th word in the |j|-th state (table)
+of the |i|-th ocp.
+@^inner loop@>
+
+@d ocp_state_end(#)==#]
+@d ocp_state_one(#)==#*2]+ocp_state_end
+@d ocp_state_entry(#)==ocp_tables[#,ocp_tables[#,ocp_state_base(#)+ocp_state_one
+
+@d ocp_state_no_end(#)==#*2+1]
+@d ocp_state_no(#)==ocp_tables[#,ocp_state_base(#)+ocp_state_no_end
+
+@d ocp_table_end(#)==#]
+@d ocp_table_one(#)==#*2]+ocp_table_end
+@d ocp_table_entry(#)==ocp_tables[#,ocp_tables[#,ocp_table_base(#)+ocp_table_one
+
+@d ocp_table_no_end(#)==#*2+1]
+@d ocp_table_no(#)==ocp_tables[#,ocp_table_base(#)+ocp_table_no_end
+
+@ $\Omega$ checks the information of a \.{OCP} file for validity as the
+file is being read in, so that no further checks will be needed when
+typesetting is going on. The somewhat tedious subroutine that does this
+is called |read_ocp_info|. It has three parameters: the user ocp
+identifier~|u|, and the file name and area strings |nom| and |aire|.
+
+The subroutine opens and closes a global file variable called |ocp_file|.
+It returns the value of the internal ocp number that was just loaded.
+If an error is detected, an error message is issued and no ocp
+information is stored; |null_ocp| is returned in this case.
+
+@d bad_ocp=11 {label for |read_ocp_info|}
+@d ocp_abort(#)==begin print("OCP file error (");
+ print(#); print(")"); print_ln; goto bad_ocp end
+ {do this when the \.{OCP} data is wrong}
+
+@p function read_ocp_info(@!u:pointer;@!nom,@!aire,@!ext:str_number;
+ @!external_ocp:boolean)
+ :internal_ocp_number; {input a \.{OCP} file}
+label done,bad_ocp,not_found;
+var
+@!file_opened:boolean; {was |ocp_file| successfully opened?}
+@!k:integer;
+@!res:boolean;
+@!callback_id:integer;
+@!fnam:str_number;
+@!f:internal_ocp_number; {the new ocp's number}
+@!g:internal_ocp_number; {the number to return}
+@!ocpword:integer;
+@!ocpmem_run_ptr:ocp_index;
+@!ocp_length,real_ocp_length:integer; {length of ocp file}
+@!previous_address:ocp_index;
+@!temp_ocp_input:integer;
+@!temp_ocp_output:integer;
+@!temp_ocp_no_tables:integer;
+@!temp_ocp_no_states:integer;
+@!i,new_offset,room_for_tables,room_for_states:integer;
+begin g:=null_ocp; f:=null_ocp;@/
+@<Read and check the ocp data; |ocp_abort| if the \.{OCP} file is
+ malformed; if there's no room for this ocp, say so and |goto
+ done|; otherwise |incr(ocp_ptr)| and |goto done|@>;
+bad_ocp: @<Report that the ocp won't be loaded@>;
+done:
+ocp_name(f):=nom; ocp_area(f):=aire;
+read_ocp_info:=g;
+end;
+
+@ $\Omega$ does not give precise details about why it
+rejects a particular \.{OCP} file.
+
+@d start_ocp_error_message==print_err("Translation process ");
+ sprint_cs(u); print_char("="); print_file_name(nom,aire,"");
+
+@<Report that the ocp won't be loaded@>=
+start_ocp_error_message;
+@.Translation process x=xx not loadable...@>
+if file_opened then print(" not loadable: Bad ocp file")
+else print(" not loadable: ocp file not found");
+help2("I wasn't able to read the data for this ocp,")@/
+("so I will ignore the ocp specification.");
+error
+
+@ @<Read and check the ocp data...@>=
+if external_ocp then
+ @<Check |ocp_file| exists@>
+else begin
+ @<Open |ocp_file| for input@>;
+ @<Read the {\.{OCP}} file@>;
+ end;
+
+@ @<Check |ocp_file| exists@>=
+begin
+file_opened:=false;
+pack_file_name(nom,aire,ext);
+b_test_in;
+if namelength=0 then ocp_abort("opening file");
+f :=ocp_ptr+1;
+allocate_ocp_table(f,13);
+ocp_file_size(f):=13;
+for i:=1 to namelength do begin
+ append_char(nameoffile[i]);
+ end;
+ocp_external(f):=make_string;
+scan_string_argument;
+ocp_external_arg(f):=cur_val;
+ocp_name(f):=""; ocp_area(f):="";
+ocp_state_base(f):=0; ocp_table_base(f):=0;
+ocp_input(f):=1; ocp_output(f):=1;
+ocp_info(f)(offset_ocp_info):=0;
+ocp_ptr:=f; g:=f;
+goto done;
+end
+
+@ @<Open |ocp_file| for input@>=
+file_opened:=false;
+pack_file_name(nom,aire,".ocp");
+if ocp_buffer<>0 then libcfree(ocp_buffer);
+ocp_cur:=0; ocp_buffer:=0; ocp_size:=0;
+callback_id:=callback_defined(find_ocp_file_callback);
+if callback_id>0 then begin
+ res := run_callback(callback_id,'S->s',stringcast(nameoffile+1), addressof(fnam));
+ if (res)and(fnam<>0)and(length(fnam)>0) then begin
+ @<Fixup |nameoffile| after callback@>;
+ end;
+ end;
+callback_id:=callback_defined(read_ocp_file_callback);
+if callback_id>0 then begin
+ res := run_callback(callback_id,'S->bSd',stringcast(nameoffile+1),
+ addressof(file_opened), addressof(ocp_buffer),addressof(ocp_size));
+ if not res then ocp_abort("callback error");
+ if not file_opened then ocp_abort("opening file");
+ if not ocp_size then ocp_abort("checking size");
+ end
+else begin
+ if not ocp_open_in(ocp_file) then ocp_abort("opening file");
+ file_opened:=true;
+ res := read_ocp_file(ocp_file,addressof(ocp_buffer),addressof(ocp_size));
+ b_close(ocp_file);
+ if not ocp_size then ocp_abort("checking size");
+ if not res then ocp_abort("reading file");
+end
+
+
+@ Note: A malformed \.{OCP} file might be shorter than it claims to be;
+thus |eof(ocp_file)| might be true when |read_ocp_info| refers to
+|ocp_file^| or when it says |get(ocp_file)|. If such circumstances
+cause system error messages, you will have to defeat them somehow,
+for example by defining |ocpget| to be `\ignorespaces|begin get(ocp_file);|
+|if eof(ocp_file) then ocp_abort; end|\unskip'.
+@^system dependencies@>
+
+@d add_to_ocp_info(#)==begin ocp_tables[f,ocpmem_run_ptr]:=#;
+ incr(ocpmem_run_ptr);
+ end
+@d ocpget==incr(ocp_cur)
+@d ocpbyte==ocp_buffer[ocp_cur]
+@d ocp_read(#)==begin ocpword:=ocpbyte;
+ if ocpword>127 then ocp_abort("checking first octet");
+ ocpget; ocpword:=ocpword*@'400+ocpbyte;
+ ocpget; ocpword:=ocpword*@'400+ocpbyte;
+ ocpget; ocpword:=ocpword*@'400+ocpbyte;
+ #:=ocpword;
+ end
+@d ocp_read_all(#)==begin ocpget; ocp_read(#); end
+@d ocp_read_info==begin ocp_read_all(ocpword);
+ add_to_ocp_info(ocpword);
+ end
+
+@ @<Read the {\.{OCP}} file@>=
+begin
+f :=ocp_ptr+1;
+ocpmem_run_ptr:=offset_ocp_info;
+ocp_read(ocp_length);
+real_ocp_length:=ocp_length-7;
+ocp_read_all(temp_ocp_input);
+ocp_read_all(temp_ocp_output);
+ocp_read_all(temp_ocp_no_tables);
+ocp_read_all(room_for_tables);
+ocp_read_all(temp_ocp_no_states);
+ocp_read_all(room_for_states);
+if real_ocp_length <>
+ (temp_ocp_no_tables + room_for_tables +
+ temp_ocp_no_states + room_for_states) then
+ ocp_abort("checking size");
+real_ocp_length:=real_ocp_length+12+
+ temp_ocp_no_states+temp_ocp_no_tables;
+allocate_ocp_table(f,real_ocp_length);
+ocp_external(f):=0;
+ocp_external_arg(f):=0;
+ocp_file_size(f):=real_ocp_length;
+ocp_input(f):=temp_ocp_input;
+ocp_output(f):=temp_ocp_output;
+ocp_no_tables(f):=temp_ocp_no_tables;
+ocp_no_states(f):=temp_ocp_no_states;
+ocp_table_base(f):=ocpmem_run_ptr;
+if ocp_no_tables(f) <> 0 then begin
+ previous_address:=ocpmem_run_ptr+2*(ocp_no_tables(f));
+ for i:=1 to ocp_no_tables(f) do begin
+ add_to_ocp_info(previous_address);
+ ocp_read_all(new_offset);
+ add_to_ocp_info(new_offset);
+ previous_address:=previous_address+new_offset;
+ end
+ end;
+if room_for_tables <> 0 then begin
+ for i:=1 to room_for_tables do begin
+ ocp_read_info;
+ end
+ end;
+ocp_state_base(f):=ocpmem_run_ptr;
+if ocp_no_states(f) <> 0 then begin
+ previous_address:=ocpmem_run_ptr+2*(ocp_no_states(f));
+ for i:=1 to ocp_no_states(f) do begin
+ add_to_ocp_info(previous_address);
+ ocp_read_all(new_offset);
+ add_to_ocp_info(new_offset);
+ previous_address:=previous_address+new_offset;
+ end;
+ end;
+if room_for_states <> 0 then begin
+ for i:=1 to room_for_states do begin
+ ocp_read_info;
+ end
+ end;
+ocp_ptr:=f; g:=f;
+goto done;
+end
+
+@ Before we forget about the format of these tables, let's deal with
+$\Omega$'s basic scanning routine related to ocp information.
+
+@<Declare procedures that scan ocp-related stuff@>=
+procedure scan_ocp_ident;
+var f:internal_ocp_number;
+begin @<Get the next non-blank non-call...@>;
+if cur_cmd=set_ocp then f:=cur_chr
+else begin print_err("Missing ocp identifier");
+@.Missing ocp identifier@>
+ help2("I was looking for a control sequence whose")@/
+ ("current meaning has been defined by \ocp.");
+ back_error; f:=null_ocp;
+ end;
+cur_val:=f;
+end;
+
+
+@ Here we begin the \.{OCP} list handling.
+
+
+@<Types...@>=
+@!internal_ocp_list_number=ocp_list_base..ocp_list_biggest;
+@!ocp_list_index=integer; {index into |ocp_list_info|}
+@!ocp_lstack_index=integer; {index into |ocp_lstack_info|}
+
+@ Here now is the array of ocp arrays.
+@d ocp_list_lnext(#)==ocp_list_info[#].hh.b0
+@d ocp_list_lstack(#)==ocp_list_info[#].hh.b1
+@d ocp_list_lstack_no(#)==ocp_list_info[#+1].sc
+@d ocp_lstack_lnext(#)==ocp_lstack_info[#].hh.b0
+@d ocp_lstack_ocp(#)==ocp_lstack_info[#].hh.b1
+@d make_null_ocp_list==make_ocp_list_node(0,ocp_maxint,0)
+@d is_null_ocp_list(#)==ocp_list_lstack_no(#)=ocp_maxint
+@d make_null_ocp_lstack==0
+@d is_null_ocp_lstack(#)==#=0
+@d add_before_op=1
+@d add_after_op=2
+@d remove_before_op=3
+@d remove_after_op=4
+
+@<Glob...@>=
+@!ocp_list_info:array[ocp_list_index] of memory_word;
+ {the big collection of ocp list data}
+@!ocp_listmem_ptr:ocp_list_index; {first unused word of |ocp_list_info|}
+@!ocp_listmem_run_ptr:ocp_list_index; {temp unused word of |ocp_list_info|}
+@!ocp_lstack_info:array[ocp_lstack_index] of memory_word;
+ {the big collection of ocp lstack data}
+@!ocp_lstackmem_ptr:ocp_lstack_index; {first unused word of |ocp_lstack_info|}
+@!ocp_lstackmem_run_ptr:ocp_lstack_index; {temp unused word of |ocp_lstack_info|}
+@!ocp_list_ptr:internal_ocp_list_number; {largest internal ocp list number in use}
+@!ocp_list_list:array[internal_ocp_list_number] of ocp_list_index;
+
+@
+@<Initialize table...@>=
+ocp_listmem_ptr:=2;
+ocp_list_lstack(0):=0;
+ocp_list_lstack_no(0):=ocp_maxint;
+ocp_list_lnext(0):=0;
+ocp_list_ptr:=null_ocp_list;
+ocp_list_list[null_ocp_list]:=0;
+ocp_lstackmem_ptr:=1;
+
+@ $\Omega$ always knows at least one ocp list, namely the null ocp list.
+
+@ @<Put each...@>=
+primitive("nullocplist", set_ocp_list, null_ocp_list);
+text(frozen_null_ocp_list) := "nullocplist";
+eqtb[frozen_null_ocp_list] := eqtb[cur_val];
+
+@ @p function make_ocp_list_node(llstack:ocp_lstack_index;
+ llstack_no:scaled;
+ llnext:ocp_list_index):ocp_list_index;
+var p:ocp_list_index;
+begin
+p:=ocp_listmem_run_ptr;
+ocp_list_lstack(p):=llstack;
+ocp_list_lstack_no(p):=llstack_no;
+ocp_list_lnext(p):=llnext;
+ocp_listmem_run_ptr:=ocp_listmem_run_ptr+2;
+if ocp_listmem_run_ptr>=ocp_list_size then
+ overflow("ocp_list_size",ocp_list_size);
+make_ocp_list_node:=p;
+end;
+
+function make_ocp_lstack_node(locp:internal_ocp_number;
+ llnext:ocp_lstack_index) : ocp_lstack_index;
+var p:ocp_lstack_index;
+begin
+p:=ocp_lstackmem_run_ptr;
+ocp_lstack_ocp(p):=locp;
+ocp_lstack_lnext(p):=llnext;
+incr(ocp_lstackmem_run_ptr);
+if ocp_lstackmem_run_ptr>=ocp_stack_size then
+ overflow("ocp_stack_size",ocp_stack_size);
+make_ocp_lstack_node:=p;
+end;
+
+function copy_ocp_lstack(llstack:ocp_lstack_index):ocp_lstack_index;
+var result:ocp_lstack_index;
+begin
+if is_null_ocp_lstack(llstack) then
+ result:=make_null_ocp_lstack
+else
+ result:=make_ocp_lstack_node(ocp_lstack_ocp(llstack),
+ copy_ocp_lstack(ocp_lstack_lnext(llstack)));
+copy_ocp_lstack:=result;
+end;
+
+function copy_ocp_list(list:ocp_list_index):ocp_list_index;
+var result:ocp_list_index;
+begin
+if is_null_ocp_list(list) then
+ result:=make_null_ocp_list
+else
+ result:=make_ocp_list_node(copy_ocp_lstack(ocp_list_lstack(list)),
+ ocp_list_lstack_no(list),
+ copy_ocp_list(ocp_list_lnext(list)));
+copy_ocp_list:=result;
+end;
+
+function ocp_ensure_lstack(list:ocp_list_index; llstack_no:scaled):
+ ocp_list_index;
+var p:ocp_list_index;
+ q:ocp_list_index;
+begin
+p:=list;
+if is_null_ocp_list(p) then begin
+ ocp_list_lstack_no(p) := llstack_no;
+ ocp_list_lnext(p) := make_null_ocp_list;
+ end
+else if ocp_list_lstack_no(p) > llstack_no then begin
+ ocp_list_lnext(p):=
+ make_ocp_list_node(ocp_list_lstack(p),
+ ocp_list_lstack_no(p),
+ ocp_list_lnext(p));
+ ocp_list_lstack(p):=0;
+ ocp_list_lstack_no(p):=llstack_no;
+ end
+else begin
+ q:=ocp_list_lnext(p);
+ while (not (is_null_ocp_list(q))) and
+ ocp_list_lstack_no(q) <= llstack_no do begin
+ p:=q; q:=ocp_list_lnext(q);
+ end;
+ if ocp_list_lstack_no(p) < llstack_no then begin
+ ocp_list_lnext(p) := make_ocp_list_node(0, llstack_no, q);
+ p := ocp_list_lnext(p);
+ end;
+ end;
+ocp_ensure_lstack := p;
+end;
+
+procedure ocp_apply_add(list_entry:ocp_list_index;
+ lbefore:boolean;
+ locp:internal_ocp_number);
+var p:ocp_lstack_index;
+ q:ocp_lstack_index;
+begin
+p := ocp_list_lstack(list_entry);
+if lbefore or (p=0) then begin
+ ocp_list_lstack(list_entry) := make_ocp_lstack_node(locp, p);
+ end
+else begin
+ q:=ocp_lstack_lnext(p);
+ while q<>0 do begin
+ p:=q; q:=ocp_lstack_lnext(q);
+ end;
+ ocp_lstack_lnext(p):=make_ocp_lstack_node(locp,0);
+ end;
+end;
+
+procedure ocp_apply_remove(list_entry:ocp_list_index;
+ lbefore:boolean);
+var p:ocp_lstack_index;
+ q:ocp_lstack_index;
+ r:ocp_lstack_index;
+begin
+p := ocp_list_lstack(list_entry);
+if p=0 then begin
+ print_err("warning: stack entry already empty"); print_ln
+ end
+else begin
+ q := ocp_lstack_lnext(p);
+ if lbefore or (q=0) then
+ ocp_list_lstack(list_entry) := q
+ else begin
+ r:=ocp_lstack_lnext(q);
+ while r <> 0 do begin
+ p:=q; q:=r; r:=ocp_lstack_lnext(r);
+ end;
+ ocp_lstack_lnext(p) := 0;
+ end
+ end;
+end;
+
+procedure scan_scaled; {sets |cur_val| to a scaled value}
+label done, done1, done2, found, not_found, attach_fraction;
+var negative:boolean; {should the answer be negated?}
+@!f:integer; {numerator of a fraction whose denominator is $2^{16}$}
+@!k,@!kk:small_number; {number of digits in a decimal fraction}
+@!p,@!q:pointer; {top of decimal digit stack}
+begin f:=0; arith_error:=false; negative:=false;
+@<Get the next non-blank non-sign...@>;
+back_input;
+if cur_tok=continental_point_token then cur_tok:=point_token;
+if cur_tok<>point_token then scan_int
+else begin radix:=10; cur_val:=0;
+ end;
+if cur_tok=continental_point_token then cur_tok:=point_token;
+if (radix=10)and(cur_tok=point_token) then @<Scan decimal fraction@>;
+if cur_val<0 then {in this case |f=0|}
+ begin negative := not negative; negate(cur_val);
+ end;
+if cur_val>@'40000 then arith_error:=true
+else cur_val := cur_val*unity +f;
+if arith_error or(abs(cur_val)>=@'10000000000) then
+begin print_err("Stack number too large"); error;
+end;
+if negative then negate(cur_val);
+end;
+
+procedure print_ocp_lstack(lstack_entry:ocp_lstack_index);
+var p:ocp_lstack_index;
+begin
+p:=lstack_entry;
+while (p<>0) do begin
+ print_esc(ocp_id_text(ocp_lstack_ocp(p)));
+ p:=ocp_lstack_lnext(p);
+ if (p<>0) then print(",");
+ end;
+end;
+
+procedure print_ocp_list(list_entry:ocp_list_index);
+var p:ocp_list_index;
+begin
+print("["); p:=list_entry;
+while not (is_null_ocp_list(p)) do begin
+ print("(");
+ print_scaled(ocp_list_lstack_no(p));
+ print(" : ");
+ print_ocp_lstack(ocp_list_lstack(p));
+ print(")");
+ p:=ocp_list_lnext(p);
+ if not (is_null_ocp_list(p)) then print(", ");
+ end;
+print("]");
+end;
+
+function scan_ocp_list: ocp_list_index;
+var llstack_no:scaled;
+ lop:quarterword;
+ lstack_entry:ocp_list_index;
+ other_list:ocp_list_index;
+ ocp_ident:internal_ocp_number;
+ result:ocp_list_index;
+begin
+get_r_token;
+if cur_cmd = set_ocp_list then
+ result := copy_ocp_list(ocp_list_list[cur_chr])
+else if cur_cmd <> ocp_list_op then begin
+ print_err("Bad ocp list specification");
+@.Bad ocp list specification@>
+ help1("I was looking for a ocp list specification.");
+ error;
+ result := make_null_ocp_list;
+ end
+else begin
+ lop:=cur_chr;
+ scan_scaled; llstack_no:=cur_val;
+ if (llstack_no<=0) or (llstack_no>=ocp_maxint) then begin
+ print_err("Stack numbers must be between 0 and 4096 (exclusive)");
+ error;
+ result := make_null_ocp_list;
+ end
+ else begin
+ if lop <= add_after_op then begin
+ scan_ocp_ident; ocp_ident:=cur_val;
+ end;
+ other_list:=scan_ocp_list;
+ lstack_entry:=ocp_ensure_lstack(other_list, llstack_no);
+ if lop <= add_after_op then
+ ocp_apply_add(lstack_entry, (lop=add_before_op), ocp_ident)
+ else
+ ocp_apply_remove(lstack_entry, (lop=remove_before_op));
+ result:=other_list;
+ end;
+ end;
+scan_ocp_list:=result;
+end;
+
+function read_ocp_list: internal_ocp_list_number;
+var f:internal_ocp_list_number;
+ g:internal_ocp_list_number;
+begin
+g:=null_ocp_list;
+f:=ocp_list_ptr+1;
+ocp_listmem_run_ptr:=ocp_listmem_ptr;
+ocp_lstackmem_run_ptr:=ocp_lstackmem_ptr;
+ocp_list_list[f]:=scan_ocp_list;
+ocp_list_ptr:=f;
+ocp_listmem_ptr:=ocp_listmem_run_ptr;
+ocp_lstackmem_ptr:=ocp_lstackmem_run_ptr;
+g:=f;
+read_ocp_list:=g;
+end;
+
+procedure scan_ocp_list_ident;
+var f:internal_ocp_list_number;
+begin @<Get the next non-blank non-call...@>;
+if cur_cmd=set_ocp_list then f:=cur_chr
+else begin print_err("Missing ocp list identifier");
+@.Missing ocp list identifier@>
+ help2("I was looking for a control sequence whose")@/
+ ("current meaning has been defined by \ocplist.");
+ back_error; f:=null_ocp_list;
+ end;
+cur_val:=f;
+end;
+
+
+@* \[31] Device-independent file format.
+The most important output produced by a run of \TeX\ is the ``device
+independent'' (\.{DVI}) file that specifies where characters and rules
+are to appear on printed pages. The form of these files was designed by
+David R. Fuchs in 1979. Almost any reasonable typesetting device can be
+@^Fuchs, David Raymond@>
+@:DVI_files}{\.{DVI} files@>
+driven by a program that takes \.{DVI} files as input, and dozens of such
+\.{DVI}-to-whatever programs have been written. Thus, it is possible to
+print the output of \TeX\ on many different kinds of equipment, using \TeX\
+as a device-independent ``front end.''
+
+A \.{DVI} file is a stream of 8-bit bytes, which may be regarded as a
+series of commands in a machine-like language. The first byte of each command
+is the operation code, and this code is followed by zero or more bytes
+that provide parameters to the command. The parameters themselves may consist
+of several consecutive bytes; for example, the `|set_rule|' command has two
+parameters, each of which is four bytes long. Parameters are usually
+regarded as nonnegative integers; but four-byte-long parameters,
+and shorter parameters that denote distances, can be
+either positive or negative. Such parameters are given in two's complement
+notation. For example, a two-byte-long distance parameter has a value between
+$-2^{15}$ and $2^{15}-1$. As in \.{TFM} files, numbers that occupy
+more than one byte position appear in BigEndian order.
+
+A \.{DVI} file consists of a ``preamble,'' followed by a sequence of one
+or more ``pages,'' followed by a ``postamble.'' The preamble is simply a
+|pre| command, with its parameters that define the dimensions used in the
+file; this must come first. Each ``page'' consists of a |bop| command,
+followed by any number of other commands that tell where characters are to
+be placed on a physical page, followed by an |eop| command. The pages
+appear in the order that \TeX\ generated them. If we ignore |nop| commands
+and \\{fnt\_def} commands (which are allowed between any two commands in
+the file), each |eop| command is immediately followed by a |bop| command,
+or by a |post| command; in the latter case, there are no more pages in the
+file, and the remaining bytes form the postamble. Further details about
+the postamble will be explained later.
+
+Some parameters in \.{DVI} commands are ``pointers.'' These are four-byte
+quantities that give the location number of some other byte in the file;
+the first byte is number~0, then comes number~1, and so on. For example,
+one of the parameters of a |bop| command points to the previous |bop|;
+this makes it feasible to read the pages in backwards order, in case the
+results are being directed to a device that stacks its output face up.
+Suppose the preamble of a \.{DVI} file occupies bytes 0 to 99. Now if the
+first page occupies bytes 100 to 999, say, and if the second
+page occupies bytes 1000 to 1999, then the |bop| that starts in byte 1000
+points to 100 and the |bop| that starts in byte 2000 points to 1000. (The
+very first |bop|, i.e., the one starting in byte 100, has a pointer of~$-1$.)
+
+@ The \.{DVI} format is intended to be both compact and easily interpreted
+by a machine. Compactness is achieved by making most of the information
+implicit instead of explicit. When a \.{DVI}-reading program reads the
+commands for a page, it keeps track of several quantities: (a)~The current
+font |f| is an integer; this value is changed only
+by \\{fnt} and \\{fnt\_num} commands. (b)~The current position on the page
+is given by two numbers called the horizontal and vertical coordinates,
+|h| and |v|. Both coordinates are zero at the upper left corner of the page;
+moving to the right corresponds to increasing the horizontal coordinate, and
+moving down corresponds to increasing the vertical coordinate. Thus, the
+coordinates are essentially Cartesian, except that vertical directions are
+flipped; the Cartesian version of |(h,v)| would be |(h,-v)|. (c)~The
+current spacing amounts are given by four numbers |w|, |x|, |y|, and |z|,
+where |w| and~|x| are used for horizontal spacing and where |y| and~|z|
+are used for vertical spacing. (d)~There is a stack containing
+|(h,v,w,x,y,z)| values; the \.{DVI} commands |push| and |pop| are used to
+change the current level of operation. Note that the current font~|f| is
+not pushed and popped; the stack contains only information about
+positioning.
+
+The values of |h|, |v|, |w|, |x|, |y|, and |z| are signed integers having up
+to 32 bits, including the sign. Since they represent physical distances,
+there is a small unit of measurement such that increasing |h| by~1 means
+moving a certain tiny distance to the right. The actual unit of
+measurement is variable, as explained below; \TeX\ sets things up so that
+its \.{DVI} output is in sp units, i.e., scaled points, in agreement with
+all the |scaled| dimensions in \TeX's data structures.
+
+@ Here is a list of all the commands that may appear in a \.{DVI} file. Each
+command is specified by its symbolic name (e.g., |bop|), its opcode byte
+(e.g., 139), and its parameters (if any). The parameters are followed
+by a bracketed number telling how many bytes they occupy; for example,
+`|p[4]|' means that parameter |p| is four bytes long.
+
+\yskip\hang|set_char_0| 0. Typeset character number~0 from font~|f|
+such that the reference point of the character is at |(h,v)|. Then
+increase |h| by the width of that character. Note that a character may
+have zero or negative width, so one cannot be sure that |h| will advance
+after this command; but |h| usually does increase.
+
+\yskip\hang\\{set\_char\_1} through \\{set\_char\_127} (opcodes 1 to 127).
+Do the operations of |set_char_0|; but use the character whose number
+matches the opcode, instead of character~0.
+
+\yskip\hang|set1| 128 |c[1]|. Same as |set_char_0|, except that character
+number~|c| is typeset. \TeX82 uses this command for characters in the
+range |128<=c<256|.
+
+\yskip\hang|@!set2| 129 |c[2]|. Same as |set1|, except that |c|~is two
+bytes long, so it is in the range |0<=c<65536|. \TeX82 never uses this
+command, but it should come in handy for extensions of \TeX\ that deal
+with oriental languages.
+@^oriental characters@>@^Chinese characters@>@^Japanese characters@>
+
+\yskip\hang|@!set3| 130 |c[3]|. Same as |set1|, except that |c|~is three
+bytes long, so it can be as large as $2^{24}-1$. Not even the Chinese
+language has this many characters, but this command might prove useful
+in some yet unforeseen extension.
+
+\yskip\hang|@!set4| 131 |c[4]|. Same as |set1|, except that |c|~is four
+bytes long. Imagine that.
+
+\yskip\hang|set_rule| 132 |a[4]| |b[4]|. Typeset a solid black rectangle
+of height~|a| and width~|b|, with its bottom left corner at |(h,v)|. Then
+set |h:=h+b|. If either |a<=0| or |b<=0|, nothing should be typeset. Note
+that if |b<0|, the value of |h| will decrease even though nothing else happens.
+See below for details about how to typeset rules so that consistency with
+\MF\ is guaranteed.
+
+\yskip\hang|@!put1| 133 |c[1]|. Typeset character number~|c| from font~|f|
+such that the reference point of the character is at |(h,v)|. (The `put'
+commands are exactly like the `set' commands, except that they simply put out a
+character or a rule without moving the reference point afterwards.)
+
+\yskip\hang|@!put2| 134 |c[2]|. Same as |set2|, except that |h| is not changed.
+
+\yskip\hang|@!put3| 135 |c[3]|. Same as |set3|, except that |h| is not changed.
+
+\yskip\hang|@!put4| 136 |c[4]|. Same as |set4|, except that |h| is not changed.
+
+\yskip\hang|put_rule| 137 |a[4]| |b[4]|. Same as |set_rule|, except that
+|h| is not changed.
+
+\yskip\hang|nop| 138. No operation, do nothing. Any number of |nop|'s
+may occur between \.{DVI} commands, but a |nop| cannot be inserted between
+a command and its parameters or between two parameters.
+
+\yskip\hang|bop| 139 $c_0[4]$ $c_1[4]$ $\ldots$ $c_9[4]$ $p[4]$. Beginning
+of a page: Set |(h,v,w,x,y,z):=(0,0,0,0,0,0)| and set the stack empty. Set
+the current font |f| to an undefined value. The ten $c_i$ parameters hold
+the values of \.{\\count0} $\ldots$ \.{\\count9} in \TeX\ at the time
+\.{\\shipout} was invoked for this page; they can be used to identify
+pages, if a user wants to print only part of a \.{DVI} file. The parameter
+|p| points to the previous |bop| in the file; the first
+|bop| has $p=-1$.
+
+\yskip\hang|eop| 140. End of page: Print what you have read since the
+previous |bop|. At this point the stack should be empty. (The \.{DVI}-reading
+programs that drive most output devices will have kept a buffer of the
+material that appears on the page that has just ended. This material is
+largely, but not entirely, in order by |v| coordinate and (for fixed |v|) by
+|h|~coordinate; so it usually needs to be sorted into some order that is
+appropriate for the device in question.)
+
+\yskip\hang|push| 141. Push the current values of |(h,v,w,x,y,z)| onto the
+top of the stack; do not change any of these values. Note that |f| is
+not pushed.
+
+\yskip\hang|pop| 142. Pop the top six values off of the stack and assign
+them respectively to |(h,v,w,x,y,z)|. The number of pops should never
+exceed the number of pushes, since it would be highly embarrassing if the
+stack were empty at the time of a |pop| command.
+
+\yskip\hang|right1| 143 |b[1]|. Set |h:=h+b|, i.e., move right |b| units.
+The parameter is a signed number in two's complement notation, |-128<=b<128|;
+if |b<0|, the reference point moves left.
+
+\yskip\hang|right2| 144 |b[2]|. Same as |right1|, except that |b| is a
+two-byte quantity in the range |-32768<=b<32768|.
+
+\yskip\hang|right3| 145 |b[3]|. Same as |right1|, except that |b| is a
+three-byte quantity in the range |@t$-2^{23}$@><=b<@t$2^{23}$@>|.
+
+\yskip\hang|right4| 146 |b[4]|. Same as |right1|, except that |b| is a
+four-byte quantity in the range |@t$-2^{31}$@><=b<@t$2^{31}$@>|.
+
+\yskip\hang|w0| 147. Set |h:=h+w|; i.e., move right |w| units. With luck,
+this parameterless command will usually suffice, because the same kind of motion
+will occur several times in succession; the following commands explain how
+|w| gets particular values.
+
+\yskip\hang|w1| 148 |b[1]|. Set |w:=b| and |h:=h+b|. The value of |b| is a
+signed quantity in two's complement notation, |-128<=b<128|. This command
+changes the current |w|~spacing and moves right by |b|.
+
+\yskip\hang|@!w2| 149 |b[2]|. Same as |w1|, but |b| is two bytes long,
+|-32768<=b<32768|.
+
+\yskip\hang|@!w3| 150 |b[3]|. Same as |w1|, but |b| is three bytes long,
+|@t$-2^{23}$@><=b<@t$2^{23}$@>|.
+
+\yskip\hang|@!w4| 151 |b[4]|. Same as |w1|, but |b| is four bytes long,
+|@t$-2^{31}$@><=b<@t$2^{31}$@>|.
+
+\yskip\hang|x0| 152. Set |h:=h+x|; i.e., move right |x| units. The `|x|'
+commands are like the `|w|' commands except that they involve |x| instead
+of |w|.
+
+\yskip\hang|x1| 153 |b[1]|. Set |x:=b| and |h:=h+b|. The value of |b| is a
+signed quantity in two's complement notation, |-128<=b<128|. This command
+changes the current |x|~spacing and moves right by |b|.
+
+\yskip\hang|@!x2| 154 |b[2]|. Same as |x1|, but |b| is two bytes long,
+|-32768<=b<32768|.
+
+\yskip\hang|@!x3| 155 |b[3]|. Same as |x1|, but |b| is three bytes long,
+|@t$-2^{23}$@><=b<@t$2^{23}$@>|.
+
+\yskip\hang|@!x4| 156 |b[4]|. Same as |x1|, but |b| is four bytes long,
+|@t$-2^{31}$@><=b<@t$2^{31}$@>|.
+
+\yskip\hang|down1| 157 |a[1]|. Set |v:=v+a|, i.e., move down |a| units.
+The parameter is a signed number in two's complement notation, |-128<=a<128|;
+if |a<0|, the reference point moves up.
+
+\yskip\hang|@!down2| 158 |a[2]|. Same as |down1|, except that |a| is a
+two-byte quantity in the range |-32768<=a<32768|.
+
+\yskip\hang|@!down3| 159 |a[3]|. Same as |down1|, except that |a| is a
+three-byte quantity in the range |@t$-2^{23}$@><=a<@t$2^{23}$@>|.
+
+\yskip\hang|@!down4| 160 |a[4]|. Same as |down1|, except that |a| is a
+four-byte quantity in the range |@t$-2^{31}$@><=a<@t$2^{31}$@>|.
+
+\yskip\hang|y0| 161. Set |v:=v+y|; i.e., move down |y| units. With luck,
+this parameterless command will usually suffice, because the same kind of motion
+will occur several times in succession; the following commands explain how
+|y| gets particular values.
+
+\yskip\hang|y1| 162 |a[1]|. Set |y:=a| and |v:=v+a|. The value of |a| is a
+signed quantity in two's complement notation, |-128<=a<128|. This command
+changes the current |y|~spacing and moves down by |a|.
+
+\yskip\hang|@!y2| 163 |a[2]|. Same as |y1|, but |a| is two bytes long,
+|-32768<=a<32768|.
+
+\yskip\hang|@!y3| 164 |a[3]|. Same as |y1|, but |a| is three bytes long,
+|@t$-2^{23}$@><=a<@t$2^{23}$@>|.
+
+\yskip\hang|@!y4| 165 |a[4]|. Same as |y1|, but |a| is four bytes long,
+|@t$-2^{31}$@><=a<@t$2^{31}$@>|.
+
+\yskip\hang|z0| 166. Set |v:=v+z|; i.e., move down |z| units. The `|z|' commands
+are like the `|y|' commands except that they involve |z| instead of |y|.
+
+\yskip\hang|z1| 167 |a[1]|. Set |z:=a| and |v:=v+a|. The value of |a| is a
+signed quantity in two's complement notation, |-128<=a<128|. This command
+changes the current |z|~spacing and moves down by |a|.
+
+\yskip\hang|@!z2| 168 |a[2]|. Same as |z1|, but |a| is two bytes long,
+|-32768<=a<32768|.
+
+\yskip\hang|@!z3| 169 |a[3]|. Same as |z1|, but |a| is three bytes long,
+|@t$-2^{23}$@><=a<@t$2^{23}$@>|.
+
+\yskip\hang|@!z4| 170 |a[4]|. Same as |z1|, but |a| is four bytes long,
+|@t$-2^{31}$@><=a<@t$2^{31}$@>|.
+
+\yskip\hang|fnt_num_0| 171. Set |f:=0|. Font 0 must previously have been
+defined by a \\{fnt\_def} instruction, as explained below.
+
+\yskip\hang\\{fnt\_num\_1} through \\{fnt\_num\_63} (opcodes 172 to 234). Set
+|f:=1|, \dots, \hbox{|f:=63|}, respectively.
+
+\yskip\hang|fnt1| 235 |k[1]|. Set |f:=k|. \TeX82 uses this command for font
+numbers in the range |64<=k<256|.
+
+\yskip\hang|@!fnt2| 236 |k[2]|. Same as |fnt1|, except that |k|~is two
+bytes long, so it is in the range |0<=k<65536|. \TeX82 never generates this
+command, but large font numbers may prove useful for specifications of
+color or texture, or they may be used for special fonts that have fixed
+numbers in some external coding scheme.
+
+\yskip\hang|@!fnt3| 237 |k[3]|. Same as |fnt1|, except that |k|~is three
+bytes long, so it can be as large as $2^{24}-1$.
+
+\yskip\hang|@!fnt4| 238 |k[4]|. Same as |fnt1|, except that |k|~is four
+bytes long; this is for the really big font numbers (and for the negative ones).
+
+\yskip\hang|xxx1| 239 |k[1]| |x[k]|. This command is undefined in
+general; it functions as a $(k+2)$-byte |nop| unless special \.{DVI}-reading
+programs are being used. \TeX82 generates |xxx1| when a short enough
+\.{\\special} appears, setting |k| to the number of bytes being sent. It
+is recommended that |x| be a string having the form of a keyword followed
+by possible parameters relevant to that keyword.
+
+\yskip\hang|@!xxx2| 240 |k[2]| |x[k]|. Like |xxx1|, but |0<=k<65536|.
+
+\yskip\hang|@!xxx3| 241 |k[3]| |x[k]|. Like |xxx1|, but |0<=k<@t$2^{24}$@>|.
+
+\yskip\hang|xxx4| 242 |k[4]| |x[k]|. Like |xxx1|, but |k| can be ridiculously
+large. \TeX82 uses |xxx4| when sending a string of length 256 or more.
+
+\yskip\hang|fnt_def1| 243 |k[1]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
+Define font |k|, where |0<=k<256|; font definitions will be explained shortly.
+
+\yskip\hang|@!fnt_def2| 244 |k[2]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
+Define font |k|, where |0<=k<65536|.
+
+\yskip\hang|@!fnt_def3| 245 |k[3]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
+Define font |k|, where |0<=k<@t$2^{24}$@>|.
+
+\yskip\hang|@!fnt_def4| 246 |k[4]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
+Define font |k|, where |@t$-2^{31}$@><=k<@t$2^{31}$@>|.
+
+\yskip\hang|pre| 247 |i[1]| |num[4]| |den[4]| |mag[4]| |k[1]| |x[k]|.
+Beginning of the preamble; this must come at the very beginning of the
+file. Parameters |i|, |num|, |den|, |mag|, |k|, and |x| are explained below.
+
+\yskip\hang|post| 248. Beginning of the postamble, see below.
+
+\yskip\hang|post_post| 249. Ending of the postamble, see below.
+
+\yskip\noindent Commands 250--255 are undefined at the present time.
+
+@ @d set_char_0=0 {typeset character 0 and move right}
+@d set1=128 {typeset a character and move right}
+@d set_rule=132 {typeset a rule and move right}
+@d put1==133 {typeset a character without moving}
+@d put_rule=137 {typeset a rule}
+@d nop=138 {no operation}
+@d bop=139 {beginning of page}
+@d eop=140 {ending of page}
+@d push=141 {save the current positions}
+@d pop=142 {restore previous positions}
+@d right1==143 {move right}
+@d right4==146 {move right, 4 bytes}
+@d w0=147 {move right by |w|}
+@d w1=148 {move right and set |w|}
+@d x0=152 {move right by |x|}
+@d x1=153 {move right and set |x|}
+@d down1=157 {move down}
+@d down4=160 {move down, 4 bytes}
+@d y0=161 {move down by |y|}
+@d y1=162 {move down and set |y|}
+@d z0=166 {move down by |z|}
+@d z1=167 {move down and set |z|}
+@d fnt_num_0=171 {set current font to 0}
+@d fnt1=235 {set current font}
+@d xxx1=239 {extension to \.{DVI} primitives}
+@d xxx4=242 {potentially long extension to \.{DVI} primitives}
+@d fnt_def1=243 {define the meaning of a font number}
+@d pre=247 {preamble}
+@d post=248 {postamble beginning}
+@d post_post=249 {postamble ending}
+
+@ The preamble contains basic information about the file as a whole. As
+stated above, there are six parameters:
+$$\hbox{|@!i[1]| |@!num[4]| |@!den[4]| |@!mag[4]| |@!k[1]| |@!x[k]|.}$$
+The |i| byte identifies \.{DVI} format; currently this byte is always set
+to~2. (The value |i=3| is currently used for an extended format that
+allows a mixture of right-to-left and left-to-right typesetting.
+Some day we will set |i=4|, when \.{DVI} format makes another
+incompatible change---perhaps in the year 2048.)
+
+The next two parameters, |num| and |den|, are positive integers that define
+the units of measurement; they are the numerator and denominator of a
+fraction by which all dimensions in the \.{DVI} file could be multiplied
+in order to get lengths in units of $10^{-7}$ meters. Since $\rm 7227{pt} =
+254{cm}$, and since \TeX\ works with scaled points where there are $2^{16}$
+sp in a point, \TeX\ sets
+$|num|/|den|=(254\cdot10^5)/(7227\cdot2^{16})=25400000/473628672$.
+@^sp@>
+
+The |mag| parameter is what \TeX\ calls \.{\\mag}, i.e., 1000 times the
+desired magnification. The actual fraction by which dimensions are
+multiplied is therefore $|mag|\cdot|num|/1000|den|$. Note that if a \TeX\
+source document does not call for any `\.{true}' dimensions, and if you
+change it only by specifying a different \.{\\mag} setting, the \.{DVI}
+file that \TeX\ creates will be completely unchanged except for the value
+of |mag| in the preamble and postamble. (Fancy \.{DVI}-reading programs allow
+users to override the |mag|~setting when a \.{DVI} file is being printed.)
+
+Finally, |k| and |x| allow the \.{DVI} writer to include a comment, which is not
+interpreted further. The length of comment |x| is |k|, where |0<=k<256|.
+
+@d id_byte=2 {identifies the kind of \.{DVI} files described here}
+
+@ Font definitions for a given font number |k| contain further parameters
+$$\hbox{|c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.}$$
+The four-byte value |c| is the check sum that \TeX\ found in the \.{TFM}
+file for this font; |c| should match the check sum of the font found by
+programs that read this \.{DVI} file.
+@^check sum@>
+
+Parameter |s| contains a fixed-point scale factor that is applied to
+the character widths in font |k|; font dimensions in \.{TFM} files and
+other font files are relative to this quantity, which is called the
+``at size'' elsewhere in this documentation. The value of |s| is
+always positive and less than $2^{27}$. It is given in the same units
+as the other \.{DVI} dimensions, i.e., in sp when \TeX82 has made the
+file. Parameter |d| is similar to |s|; it is the ``design size,'' and
+(like~|s|) it is given in \.{DVI} units. Thus, font |k| is to be used
+at $|mag|\cdot s/1000d$ times its normal size.
+
+The remaining part of a font definition gives the external name of the font,
+which is an ASCII string of length |a+l|. The number |a| is the length
+of the ``area'' or directory, and |l| is the length of the font name itself;
+the standard local system font area is supposed to be used when |a=0|.
+The |n| field contains the area in its first |a| bytes.
+
+Font definitions must appear before the first use of a particular font number.
+Once font |k| is defined, it must not be defined again; however, we
+shall see below that font definitions appear in the postamble as well as
+in the pages, so in this sense each font number is defined exactly twice,
+if at all. Like |nop| commands, font definitions can
+appear before the first |bop|, or between an |eop| and a |bop|.
+
+@ Sometimes it is desirable to make horizontal or vertical rules line up
+precisely with certain features in characters of a font. It is possible to
+guarantee the correct matching between \.{DVI} output and the characters
+generated by \MF\ by adhering to the following principles: (1)~The \MF\
+characters should be positioned so that a bottom edge or left edge that is
+supposed to line up with the bottom or left edge of a rule appears at the
+reference point, i.e., in row~0 and column~0 of the \MF\ raster. This
+ensures that the position of the rule will not be rounded differently when
+the pixel size is not a perfect multiple of the units of measurement in
+the \.{DVI} file. (2)~A typeset rule of height $a>0$ and width $b>0$
+should be equivalent to a \MF-generated character having black pixels in
+precisely those raster positions whose \MF\ coordinates satisfy
+|0<=x<@t$\alpha$@>b| and |0<=y<@t$\alpha$@>a|, where $\alpha$ is the number
+of pixels per \.{DVI} unit.
+@:METAFONT}{\MF@>
+@^alignment of rules with characters@>
+@^rules aligning with characters@>
+
+@ The last page in a \.{DVI} file is followed by `|post|'; this command
+introduces the postamble, which summarizes important facts that \TeX\ has
+accumulated about the file, making it possible to print subsets of the data
+with reasonable efficiency. The postamble has the form
+$$\vbox{\halign{\hbox{#\hfil}\cr
+ |post| |p[4]| |num[4]| |den[4]| |mag[4]| |l[4]| |u[4]| |s[2]| |t[2]|\cr
+ $\langle\,$font definitions$\,\rangle$\cr
+ |post_post| |q[4]| |i[1]| 223's$[{\G}4]$\cr}}$$
+Here |p| is a pointer to the final |bop| in the file. The next three
+parameters, |num|, |den|, and |mag|, are duplicates of the quantities that
+appeared in the preamble.
+
+Parameters |l| and |u| give respectively the height-plus-depth of the tallest
+page and the width of the widest page, in the same units as other dimensions
+of the file. These numbers might be used by a \.{DVI}-reading program to
+position individual ``pages'' on large sheets of film or paper; however,
+the standard convention for output on normal size paper is to position each
+page so that the upper left-hand corner is exactly one inch from the left
+and the top. Experience has shown that it is unwise to design \.{DVI}-to-printer
+software that attempts cleverly to center the output; a fixed position of
+the upper left corner is easiest for users to understand and to work with.
+Therefore |l| and~|u| are often ignored.
+
+Parameter |s| is the maximum stack depth (i.e., the largest excess of
+|push| commands over |pop| commands) needed to process this file. Then
+comes |t|, the total number of pages (|bop| commands) present.
+
+The postamble continues with font definitions, which are any number of
+\\{fnt\_def} commands as described above, possibly interspersed with |nop|
+commands. Each font number that is used in the \.{DVI} file must be defined
+exactly twice: Once before it is first selected by a \\{fnt} command, and once
+in the postamble.
+
+@ The last part of the postamble, following the |post_post| byte that
+signifies the end of the font definitions, contains |q|, a pointer to the
+|post| command that started the postamble. An identification byte, |i|,
+comes next; this currently equals~2, as in the preamble.
+
+The |i| byte is followed by four or more bytes that are all equal to
+the decimal number 223 (i.e., @'337 in octal). \TeX\ puts out four to seven of
+these trailing bytes, until the total length of the file is a multiple of
+four bytes, since this works out best on machines that pack four bytes per
+word; but any number of 223's is allowed, as long as there are at least four
+of them. In effect, 223 is a sort of signature that is added at the very end.
+@^Fuchs, David Raymond@>
+
+This curious way to finish off a \.{DVI} file makes it feasible for
+\.{DVI}-reading programs to find the postamble first, on most computers,
+even though \TeX\ wants to write the postamble last. Most operating
+systems permit random access to individual words or bytes of a file, so
+the \.{DVI} reader can start at the end and skip backwards over the 223's
+until finding the identification byte. Then it can back up four bytes, read
+|q|, and move to byte |q| of the file. This byte should, of course,
+contain the value 248 (|post|); now the postamble can be read, so the
+\.{DVI} reader can discover all the information needed for typesetting the
+pages. Note that it is also possible to skip through the \.{DVI} file at
+reasonably high speed to locate a particular page, if that proves
+desirable. This saves a lot of time, since \.{DVI} files used in production
+jobs tend to be large.
+
+Unfortunately, however, standard \PASCAL\ does not include the ability to
+@^system dependencies@>
+access a random position in a file, or even to determine the length of a file.
+Almost all systems nowadays provide the necessary capabilities, so \.{DVI}
+format has been designed to work most efficiently with modern operating systems.
+But if \.{DVI} files have to be processed under the restrictions of standard
+\PASCAL, one can simply read them from front to back, since the necessary
+header information is present in the preamble and in the font definitions.
+(The |l| and |u| and |s| and |t| parameters, which appear only in the
+postamble, are ``frills'' that are handy but not absolutely necessary.)
+
+@* \[32] Shipping pages out.
+After considering \TeX's eyes and stomach, we come now to the bowels.
+@^bowels@>
+
+The |ship_out| procedure is given a pointer to a box; its mission is
+to describe that box in \.{DVI} form, outputting a ``page'' to |dvi_file|.
+The \.{DVI} coordinates $(h,v)=(0,0)$ should correspond to the upper left
+corner of the box being shipped.
+
+Since boxes can be inside of boxes inside of boxes, the main work of
+|ship_out| is done by two mutually recursive routines, |hlist_out|
+and |vlist_out|, which traverse the hlists and vlists inside of horizontal
+and vertical boxes.
+
+As individual pages are being processed, we need to accumulate
+information about the entire set of pages, since such statistics must be
+reported in the postamble. The global variables |total_pages|, |max_v|,
+|max_h|, |max_push|, and |last_bop| are used to record this information.
+
+The variable |doing_leaders| is |true| while leaders are being output.
+The variable |dead_cycles| contains the number of times an output routine
+has been initiated since the last |ship_out|.
+
+A few additional global variables are also defined here for use in
+|vlist_out| and |hlist_out|. They could have been local variables, but
+that would waste stack space when boxes are deeply nested, since the
+values of these variables are not needed during recursive calls.
+@^recursion@>
+
+@<Glob...@>=
+@!total_pages:integer; {the number of pages that have been shipped out}
+@!max_v:scaled; {maximum height-plus-depth of pages shipped so far}
+@!max_h:scaled; {maximum width of pages shipped so far}
+@!max_push:integer; {deepest nesting of |push| commands encountered so far}
+@!last_bop:integer; {location of previous |bop| in the \.{DVI} output}
+@!dead_cycles:integer; {recent outputs that didn't ship anything out}
+@!doing_leaders:boolean; {are we inside a leader box?}
+@#
+@!c,@!f:integer; {character and font in current |char_node|}
+@!oval,@!ocmd:integer; {used by |out_cmd| for generating
+ |set|, |fnt| and |fnt_def| commands}
+@!rule_ht,@!rule_dp,@!rule_wd:scaled; {size of current rule being output}
+@!g:pointer; {current glue specification}
+@!lq,@!lr:integer; {quantities used in calculations for leaders}
+
+@ @<Set init...@>=
+total_pages:=0; max_v:=0; max_h:=0; max_push:=0; last_bop:=-1;
+doing_leaders:=false; dead_cycles:=0; cur_s:=-1;
+
+@ The \.{DVI} bytes are output to a buffer instead of being written directly
+to the output file. This makes it possible to reduce the overhead of
+subroutine calls, thereby measurably speeding up the computation, since
+output of \.{DVI} bytes is part of \TeX's inner loop. And it has another
+advantage as well, since we can change instructions in the buffer in order to
+make the output more compact. For example, a `|down2|' command can be
+changed to a `|y2|', thereby making a subsequent `|y0|' command possible,
+saving two bytes.
+
+The output buffer is divided into two parts of equal size; the bytes found
+in |dvi_buf[0..half_buf-1]| constitute the first half, and those in
+|dvi_buf[half_buf..dvi_buf_size-1]| constitute the second. The global
+variable |dvi_ptr| points to the position that will receive the next
+output byte. When |dvi_ptr| reaches |dvi_limit|, which is always equal
+to one of the two values |half_buf| or |dvi_buf_size|, the half buffer that
+is about to be invaded next is sent to the output and |dvi_limit| is
+changed to its other value. Thus, there is always at least a half buffer's
+worth of information present, except at the very beginning of the job.
+
+Bytes of the \.{DVI} file are numbered sequentially starting with 0;
+the next byte to be generated will be number |dvi_offset+dvi_ptr|.
+A byte is present in the buffer only if its number is |>=dvi_gone|.
+
+@<Types...@>=
+@!dvi_index=0..dvi_buf_size; {an index into the output buffer}
+
+@ Some systems may find it more efficient to make |dvi_buf| a |packed|
+array, since output of four bytes at once may be facilitated.
+@^system dependencies@>
+
+@<Glob...@>=
+@!dvi_buf:array[dvi_index] of real_eight_bits; {buffer for \.{DVI} output}
+@!half_buf:dvi_index; {half of |dvi_buf_size|}
+@!dvi_limit:dvi_index; {end of the current half buffer}
+@!dvi_ptr:dvi_index; {the next available buffer address}
+@!dvi_offset:integer; {|dvi_buf_size| times the number of times the
+ output buffer has been fully emptied}
+@!dvi_gone:integer; {the number of bytes already output to |dvi_file|}
+
+@ Initially the buffer is all in one piece; we will output half of it only
+after it first fills up.
+
+@<Set init...@>=
+half_buf:=dvi_buf_size div 2; dvi_limit:=dvi_buf_size; dvi_ptr:=0;
+dvi_offset:=0; dvi_gone:=0;
+
+@ The actual output of |dvi_buf[a..b]| to |dvi_file| is performed by calling
+|write_dvi(a,b)|. For best results, this procedure should be optimized to
+run as fast as possible on each particular system, since it is part of
+\TeX's inner loop. It is safe to assume that |a| and |b+1| will both be
+multiples of 4 when |write_dvi(a,b)| is called; therefore it is possible on
+many machines to use efficient methods to pack four bytes per word and to
+output an array of words with one system call.
+@^system dependencies@>
+@^inner loop@>
+@^defecation@>
+
+@p procedure write_dvi(@!a,@!b:dvi_index);
+var k:dvi_index;
+begin for k:=a to b do write(dvi_file,dvi_buf[k]);
+end;
+
+@ To put a byte in the buffer without paying the cost of invoking a procedure
+each time, we use the macro |dvi_out|.
+
+@d dvi_out(#)==@+begin dvi_buf[dvi_ptr]:=#; incr(dvi_ptr);
+ if dvi_ptr=dvi_limit then dvi_swap;
+ end
+
+@p procedure dvi_swap; {outputs half of the buffer}
+begin if dvi_limit=dvi_buf_size then
+ begin write_dvi(0,half_buf-1); dvi_limit:=half_buf;
+ dvi_offset:=dvi_offset+dvi_buf_size; dvi_ptr:=0;
+ end
+else begin write_dvi(half_buf,dvi_buf_size-1); dvi_limit:=dvi_buf_size;
+ end;
+dvi_gone:=dvi_gone+half_buf;
+end;
+
+@ Here is how we clean out the buffer when \TeX\ is all through; |dvi_ptr|
+will be a multiple of~4.
+
+@<Empty the last bytes out of |dvi_buf|@>=
+if dvi_limit=half_buf then write_dvi(half_buf,dvi_buf_size-1);
+if dvi_ptr>0 then write_dvi(0,dvi_ptr-1)
+
+@ The |dvi_four| procedure outputs four bytes in two's complement notation,
+without risking arithmetic overflow.
+
+@p procedure dvi_four(@!x:integer);
+begin if x>=0 then dvi_out(x div @'100000000)
+else begin x:=x+@'10000000000;
+ x:=x+@'10000000000;
+ dvi_out((x div @'100000000) + 128);
+ end;
+x:=x mod @'100000000; dvi_out(x div @'200000);
+x:=x mod @'200000; dvi_out(x div @'400);
+dvi_out(x mod @'400);
+end;
+
+@ A mild optimization of the output is performed by the |dvi_pop|
+routine, which issues a |pop| unless it is possible to cancel a
+`|push| |pop|' pair. The parameter to |dvi_pop| is the byte address
+following the old |push| that matches the new |pop|.
+
+@p procedure dvi_pop(@!l:integer);
+begin if (l=dvi_offset+dvi_ptr)and(dvi_ptr>0) then decr(dvi_ptr)
+else dvi_out(pop);
+end;
+
+@ Here's a procedure that outputs a font definition. $\Omega$ allows
+more than 256 different fonts per job, so the right font definition
+command must be selected.
+
+@d Incr_Decr(#) == #
+@d Incr(#) == #:=#+Incr_Decr {increase a variable}
+@d Decr(#) == #:=#-Incr_Decr {decrease a variable}
+
+@d dvi_debug_out(#)==begin
+dvi_out(#);
+end
+
+@d out_cmd ==
+begin
+if (oval<@"100)and(oval>=0) then begin
+ if (ocmd<>set1)or(oval>127) then
+ if (ocmd=fnt1)and(oval<64) then Incr(oval)(fnt_num_0) @+ else dvi_debug_out(ocmd);
+ end
+else
+ begin if (oval<@"10000)and(oval>=0) then dvi_debug_out(ocmd+1) @+ else @;
+ begin if (oval<@"1000000)and(oval>=0) then dvi_debug_out(ocmd+2) @+ else @;
+ begin dvi_debug_out(ocmd+3);
+ if oval>=0 then dvi_debug_out(oval div @"1000000)
+ else begin Incr(oval)(@"40000000); Incr(oval)(@"40000000);
+ dvi_debug_out((oval div @"1000000) + 128); oval:=oval mod @"1000000;
+ end;
+ dvi_debug_out(oval div @"10000); oval:=oval mod @"10000;
+ end;
+ dvi_debug_out(oval div @"10000); oval:=oval mod @"10000;
+ end;
+ dvi_debug_out(oval div @"100); oval:=oval mod @"100;
+ end;
+dvi_debug_out(oval)
+end
+
+@p procedure dvi_font_def(@!f:internal_font_number);
+var k:pool_pointer; {index into |str_pool|}
+fa:^packed_ASCII_code;
+begin
+oval:=f-font_base-1; ocmd:= fnt_def1; out_cmd;@/
+dvi_out(font_check_0(f));
+dvi_out(font_check_1(f));
+dvi_out(font_check_2(f));
+dvi_out(font_check_3(f));@/
+dvi_four(font_size(f));
+dvi_four(font_dsize(f));@/
+dvi_out(strlen(font_area(f)));
+dvi_out(strlen(font_name(f)));
+@<Output the font name whose internal number is |f|@>;
+end;
+
+@ @<Output the font name whose internal number is |f|@>=
+fa := get_font_name(f); k := 0;
+while fa[k]<>0 do begin dvi_out(fa[k]); incr(k); end;
+fa := get_font_area(f); k := 0;
+while fa[k]<>0 do begin dvi_out(fa[k]); incr(k); end
+
+@ Versions of \TeX\ intended for small computers might well choose to omit
+the ideas in the next few parts of this program, since it is not really
+necessary to optimize the \.{DVI} code by making use of the |w0|, |x0|,
+|y0|, and |z0| commands. Furthermore, the algorithm that we are about to
+describe does not pretend to give an optimum reduction in the length
+of the \.{DVI} code; after all, speed is more important than compactness.
+But the method is surprisingly effective, and it takes comparatively little
+time.
+
+We can best understand the basic idea by first considering a simpler problem
+that has the same essential characteristics. Given a sequence of digits,
+say $3\,1\,4\,1\,5\,9\,2\,6\,5\,3\,5\,8\,9$, we want to assign subscripts
+$d$, $y$, or $z$ to each digit so as to maximize the number of ``$y$-hits''
+and ``$z$-hits''; a $y$-hit is an instance of two appearances of the same
+digit with the subscript $y$, where no $y$'s intervene between the two
+appearances, and a $z$-hit is defined similarly. For example, the sequence
+above could be decorated with subscripts as follows:
+$$3_z\,1_y\,4_d\,1_y\,5_y\,9_d\,2_d\,6_d\,5_y\,3_z\,5_y\,8_d\,9_d.$$
+There are three $y$-hits ($1_y\ldots1_y$ and $5_y\ldots5_y\ldots5_y$) and
+one $z$-hit ($3_z\ldots3_z$); there are no $d$-hits, since the two appearances
+of $9_d$ have $d$'s between them, but we don't count $d$-hits so it doesn't
+matter how many there are. These subscripts are analogous to the \.{DVI}
+commands called \\{down}, $y$, and $z$, and the digits are analogous to
+different amounts of vertical motion; a $y$-hit or $z$-hit corresponds to
+the opportunity to use the one-byte commands |y0| or |z0| in a \.{DVI} file.
+
+\TeX's method of assigning subscripts works like this: Append a new digit,
+say $\delta$, to the right of the sequence. Now look back through the
+sequence until one of the following things happens: (a)~You see
+$\delta_y$ or $\delta_z$, and this was the first time you encountered a
+$y$ or $z$ subscript, respectively. Then assign $y$ or $z$ to the new
+$\delta$; you have scored a hit. (b)~You see $\delta_d$, and no $y$
+subscripts have been encountered so far during this search. Then change
+the previous $\delta_d$ to $\delta_y$ (this corresponds to changing a
+command in the output buffer), and assign $y$ to the new $\delta$; it's
+another hit. (c)~You see $\delta_d$, and a $y$ subscript has been seen
+but not a $z$. Change the previous $\delta_d$ to $\delta_z$ and assign
+$z$ to the new $\delta$. (d)~You encounter both $y$ and $z$ subscripts
+before encountering a suitable $\delta$, or you scan all the way to the
+front of the sequence. Assign $d$ to the new $\delta$; this assignment may
+be changed later.
+
+The subscripts $3_z\,1_y\,4_d\ldots\,$ in the example above were, in fact,
+produced by this procedure, as the reader can verify. (Go ahead and try it.)
+
+@ In order to implement such an idea, \TeX\ maintains a stack of pointers
+to the \\{down}, $y$, and $z$ commands that have been generated for the
+current page. And there is a similar stack for \\{right}, |w|, and |x|
+commands. These stacks are called the down stack and right stack, and their
+top elements are maintained in the variables |down_ptr| and |right_ptr|.
+
+Each entry in these stacks contains four fields: The |width| field is
+the amount of motion down or to the right; the |location| field is the
+byte number of the \.{DVI} command in question (including the appropriate
+|dvi_offset|); the |vlink| field points to the next item below this one
+on the stack; and the |vinfo| field encodes the options for possible change
+in the \.{DVI} command.
+
+@d movement_node=48
+@d movement_node_size=3 {number of words per entry in the down and right stacks}
+@d location(#)==vmem(#+1).int {\.{DVI} byte number for a movement command}
+
+@<Glob...@>=
+@!down_ptr,@!right_ptr:pointer; {heads of the down and right stacks}
+
+@ @<Set init...@>=
+down_ptr:=null; right_ptr:=null;
+
+@ Here is a subroutine that produces a \.{DVI} command for some specified
+downward or rightward motion. It has two parameters: |w| is the amount
+of motion, and |o| is either |down1| or |right1|. We use the fact that
+the command codes have convenient arithmetic properties: |y1-down1=w1-right1|
+and |z1-down1=x1-right1|.
+
+@d dvi_set(#)==oval:=#; ocmd:=set1; out_cmd
+@d dvi_put(#)==oval:=#; ocmd:=put1; out_cmd
+@d dvi_set_rule_end(#)==dvi_four(#)
+@d dvi_set_rule(#)==dvi_out(set_rule); dvi_four(#); dvi_set_rule_end
+@d dvi_put_rule_end(#)==dvi_four(#)
+@d dvi_put_rule(#)==dvi_out(put_rule); dvi_four(#); dvi_put_rule_end
+@d dvi_right(#)==dvi_out(right4); dvi_four(#);
+@d dvi_left(#)==dvi_out(right4); dvi_four(-#);
+@d dvi_down(#)==dvi_out(down4); dvi_four(#);
+@d dvi_up(#)==dvi_out(down4); dvi_four(-#);
+
+@p procedure movement(@!w:scaled;@!o:eight_bits);
+label exit,found,not_found,2,1;
+var mstate:small_number; {have we seen a |y| or |z|?}
+@!p,@!q:pointer; {current and top nodes on the stack}
+@!k:integer; {index into |dvi_buf|, modulo |dvi_buf_size|}
+begin
+case box_direction(dvi_direction) of
+ dir_TL_: begin
+ end;
+ dir_TR_: begin
+ if o=right1 then negate(w);
+ end;
+ dir_LT_: begin
+ if o=right1 then o:=down1
+ else o:=right1;
+ end;
+ dir_LB_: begin
+ if o=right1 then begin
+ o:=down1; negate(w);
+ end
+ else o:=right1;
+ end;
+ dir_BL_: begin
+ if o=down1 then negate(w);
+ end;
+ dir_BR_: begin
+ negate(w);
+ end;
+ dir_RT_: begin
+ if o=right1 then o:=down1
+ else begin o:=right1; negate(w);
+ end;
+ end;
+ dir_RB_: begin
+ if o=right1 then o:=down1 else o:=right1;
+ negate(w);
+ end;
+ end;
+if false then begin
+q:=new_node(movement_node,0); {new node for the top of the stack}
+width(q):=w; location(q):=dvi_offset+dvi_ptr;
+if o=down1 then
+ begin vlink(q):=down_ptr; down_ptr:=q;
+ end
+else begin vlink(q):=right_ptr; right_ptr:=q;
+ end;
+@<Look at the other stack entries until deciding what sort of \.{DVI} command
+ to generate; |goto found| if node |p| is a ``hit''@>;
+end;
+@<Generate a |down| or |right| command for |w| and |return|@>;
+found: @<Generate a |y0| or |z0| command in order to reuse a previous
+ appearance of~|w|@>;
+exit:end;
+
+@ The |vinfo| fields in the entries of the down stack or the right stack
+have six possible settings: |y_here| or |z_here| mean that the \.{DVI}
+command refers to |y| or |z|, respectively (or to |w| or |x|, in the
+case of horizontal motion); |yz_OK| means that the \.{DVI} command is
+\\{down} (or \\{right}) but can be changed to either |y| or |z| (or
+to either |w| or |x|); |y_OK| means that it is \\{down} and can be changed
+to |y| but not |z|; |z_OK| is similar; and |d_fixed| means it must stay
+\\{down}.
+
+The four settings |yz_OK|, |y_OK|, |z_OK|, |d_fixed| would not need to
+be distinguished from each other if we were simply solving the
+digit-subscripting problem mentioned above. But in \TeX's case there is
+a complication because of the nested structure of |push| and |pop|
+commands. Suppose we add parentheses to the digit-subscripting problem,
+redefining hits so that $\delta_y\ldots \delta_y$ is a hit if all $y$'s between
+the $\delta$'s are enclosed in properly nested parentheses, and if the
+parenthesis level of the right-hand $\delta_y$ is deeper than or equal to
+that of the left-hand one. Thus, `(' and `)' correspond to `|push|'
+and `|pop|'. Now if we want to assign a subscript to the final 1 in the
+sequence
+$$2_y\,7_d\,1_d\,(\,8_z\,2_y\,8_z\,)\,1$$
+we cannot change the previous $1_d$ to $1_y$, since that would invalidate
+the $2_y\ldots2_y$ hit. But we can change it to $1_z$, scoring a hit
+since the intervening $8_z$'s are enclosed in parentheses.
+
+The program below removes movement nodes that are introduced after a |push|,
+before it outputs the corresponding |pop|.
+
+@d y_here=1 {|vinfo| when the movement entry points to a |y| command}
+@d z_here=2 {|vinfo| when the movement entry points to a |z| command}
+@d yz_OK=3 {|vinfo| corresponding to an unconstrained \\{down} command}
+@d y_OK=4 {|vinfo| corresponding to a \\{down} that can't become a |z|}
+@d z_OK=5 {|vinfo| corresponding to a \\{down} that can't become a |y|}
+@d d_fixed=6 {|vinfo| corresponding to a \\{down} that can't change}
+
+@ When the |movement| procedure gets to the label |found|, the value of
+|vinfo(p)| will be either |y_here| or |z_here|. If it is, say, |y_here|,
+the procedure generates a |y0| command (or a |w0| command), and marks
+all |vinfo| fields between |q| and |p| so that |y| is not OK in that range.
+
+@<Generate a |y0| or |z0| command...@>=
+vinfo(q):=vinfo(p);
+if vinfo(q)=y_here then
+ begin dvi_out(o+y0-down1); {|y0| or |w0|}
+ while vlink(q)<>p do
+ begin q:=vlink(q);
+ case vinfo(q) of
+ yz_OK: vinfo(q):=z_OK;
+ y_OK: vinfo(q):=d_fixed;
+ othercases do_nothing
+ endcases;
+ end;
+ end
+else begin dvi_out(o+z0-down1); {|z0| or |x0|}
+ while vlink(q)<>p do
+ begin q:=vlink(q);
+ case vinfo(q) of
+ yz_OK: vinfo(q):=y_OK;
+ z_OK: vinfo(q):=d_fixed;
+ othercases do_nothing
+ endcases;
+ end;
+ end
+
+@ @<Generate a |down| or |right|...@>=
+if abs(w)>=@'40000000 then
+ begin dvi_out(o+3); {|down4| or |right4|}
+ dvi_four(w); return;
+ end;
+if abs(w)>=@'100000 then
+ begin dvi_out(o+2); {|down3| or |right3|}
+ if w<0 then w:=w+@'100000000;
+ dvi_out(w div @'200000); w:=w mod @'200000; goto 2;
+ end;
+if abs(w)>=@'200 then
+ begin dvi_out(o+1); {|down2| or |right2|}
+ if w<0 then w:=w+@'200000;
+ goto 2;
+ end;
+dvi_out(o); {|down1| or |right1|}
+if w<0 then w:=w+@'400;
+goto 1;
+2: dvi_out(w div @'400);
+1: dvi_out(w mod @'400); return
+
+@ As we search through the stack, we are in one of three states,
+|y_seen|, |z_seen|, or |none_seen|, depending on whether we have
+encountered |y_here| or |z_here| nodes. These states are encoded as
+multiples of 6, so that they can be added to the |info| fields for quick
+decision-making.
+@^inner loop@>
+
+@d none_seen=0 {no |y_here| or |z_here| nodes have been encountered yet}
+@d y_seen=6 {we have seen |y_here| but not |z_here|}
+@d z_seen=12 {we have seen |z_here| but not |y_here|}
+
+@<Look at the other stack entries until deciding...@>=
+p:=vlink(q); mstate:=none_seen;
+while p<>null do
+ begin if width(p)=w then @<Consider a node with matching width;
+ |goto found| if it's a hit@>
+ else case mstate+vinfo(p) of
+ none_seen+y_here: mstate:=y_seen;
+ none_seen+z_here: mstate:=z_seen;
+ y_seen+z_here,z_seen+y_here: goto not_found;
+ othercases do_nothing
+ endcases;
+ p:=vlink(p);
+ end;
+not_found:
+
+@ We might find a valid hit in a |y| or |z| byte that is already gone
+from the buffer. But we can't change bytes that are gone forever; ``the
+moving finger writes, $\ldots\,\,$.''
+
+@<Consider a node with matching width...@>=
+case mstate+vinfo(p) of
+none_seen+yz_OK,none_seen+y_OK,z_seen+yz_OK,z_seen+y_OK:@t@>@;@/
+ if location(p)<dvi_gone then goto not_found
+ else @<Change buffered instruction to |y| or |w| and |goto found|@>;
+none_seen+z_OK,y_seen+yz_OK,y_seen+z_OK:@t@>@;@/
+ if location(p)<dvi_gone then goto not_found
+ else @<Change buffered instruction to |z| or |x| and |goto found|@>;
+none_seen+y_here,none_seen+z_here,y_seen+z_here,z_seen+y_here: goto found;
+othercases do_nothing
+endcases
+
+@ @<Change buffered instruction to |y| or |w| and |goto found|@>=
+begin k:=location(p)-dvi_offset;
+if k<0 then k:=k+dvi_buf_size;
+dvi_buf[k]:=dvi_buf[k]+y1-down1;
+vinfo(p):=y_here; goto found;
+end
+
+@ @<Change buffered instruction to |z| or |x| and |goto found|@>=
+begin k:=location(p)-dvi_offset;
+if k<0 then k:=k+dvi_buf_size;
+dvi_buf[k]:=dvi_buf[k]+z1-down1;
+vinfo(p):=z_here; goto found;
+end
+
+@ In case you are wondering when all the movement nodes are removed from
+\TeX's memory, the answer is that they are recycled just before
+|hlist_out| and |vlist_out| finish outputting a box. This restores the
+down and right stacks to the state they were in before the box was output,
+except that some |vinfo|'s may have become more restrictive.
+
+@p procedure prune_movements(@!l:integer);
+ {delete movement nodes with |location>=l|}
+label done,exit;
+var p:pointer; {node being deleted}
+begin while down_ptr<>null do
+ begin if location(down_ptr)<l then goto done;
+ p:=down_ptr; down_ptr:=vlink(p); flush_node(p);
+ end;
+done: while right_ptr<>null do
+ begin if location(right_ptr)<l then return;
+ p:=right_ptr; right_ptr:=vlink(p); flush_node(p);
+ end;
+exit:end;
+
+@ The actual distances by which we want to move might be computed as the
+sum of several separate movements. For example, there might be several
+glue nodes in succession, or we might want to move right by the width of
+some box plus some amount of glue. More importantly, the baselineskip
+distances are computed in terms of glue together with the depth and
+height of adjacent boxes, and we want the \.{DVI} file to lump these
+three quantities together into a single motion.
+
+Therefore, \TeX\ maintains two pairs of global variables: |dvi_h| and |dvi_v|
+are the |h| and |v| coordinates corresponding to the commands actually
+output to the \.{DVI} file, while |cur_h| and |cur_v| are the coordinates
+corresponding to the current state of the output routines. Coordinate
+changes will accumulate in |cur_h| and |cur_v| without being reflected
+in the output, until such a change becomes necessary or desirable; we
+can call the |movement| procedure whenever we want to make |dvi_h=cur_h|
+or |dvi_v=cur_v|.
+
+The current font reflected in the \.{DVI} output is called |dvi_f|;
+there is no need for a `\\{cur\_f}' variable.
+
+The depth of nesting of |hlist_out| and |vlist_out| is called |cur_s|;
+this is essentially the depth of |push| commands in the \.{DVI} output.
+
+@d synch_h==if cur_h<>dvi_h then
+ begin movement(cur_h-dvi_h,right1); dvi_h:=cur_h;
+ end
+@d synch_v==if cur_v<>dvi_v then
+ begin movement(cur_v-dvi_v,down1); dvi_v:=cur_v;
+ end
+
+@<Glob...@>=
+@!dvi_h,@!dvi_v:scaled; {a \.{DVI} reader program thinks we are here}
+@!cur_h,@!cur_v:scaled; {\TeX\ thinks we are here}
+@!dvi_f:internal_font_number; {the current font}
+@!cur_s:integer; {current depth of output box nesting, initially $-1$}
+
+@ @<Calculate DVI page dimensions and margins@>=
+if page_width > 0 then
+ cur_page_width := page_width
+else
+ cur_page_width := width(p) + 2*(h_offset + one_inch);
+if page_height > 0 then
+ cur_page_height := page_height
+else
+ cur_page_height := height(p) + depth(p) + 2*(v_offset + one_inch);
+if page_bottom_offset <> 0 then
+ cur_bottom_offset := page_bottom_offset
+else
+ cur_bottom_offset := 2*one_inch;
+if page_right_offset <> 0 then
+ cur_right_offset := page_right_offset
+else
+ cur_right_offset := 2*one_inch
+
+
+@ @<Initialize variables as |ship_out| begins@>=
+dvi_h:=0; dvi_v:=0; cur_h:=0; cur_v:=0; dvi_f:=null_font;
+@<Calculate DVI page dimensions and margins@>;
+ensure_dvi_open;
+if total_pages=0 then
+ begin dvi_out(pre); dvi_out(id_byte); {output the preamble}
+@^preamble of \.{DVI} file@>
+ dvi_four(25400000); dvi_four(473628672); {conversion ratio for sp}
+ prepare_mag; dvi_four(mag); {magnification factor is frozen}
+ old_setting:=selector; selector:=new_string;
+ print(" LuaTeX output "); print_int(year); print_char(".");
+ print_two(month); print_char("."); print_two(day);
+ print_char(":"); print_two(time div 60);
+ print_two(time mod 60);
+ selector:=old_setting; dvi_out(cur_length);
+ for s:=str_start_macro(str_ptr) to pool_ptr-1 do dvi_out(so(str_pool[s]));
+ pool_ptr:=str_start_macro(str_ptr); {flush the current string}
+ end
+
+@ When |hlist_out| is called, its duty is to output the box represented
+by the |hlist_node| pointed to by |temp_ptr|. The reference point of that
+box has coordinates |(cur_h,cur_v)|.
+
+Similarly, when |vlist_out| is called, its duty is to output the box represented
+by the |vlist_node| pointed to by |temp_ptr|. The reference point of that
+box has coordinates |(cur_h,cur_v)|.
+@^recursion@>
+
+@p procedure@?vlist_out; forward; {|hlist_out| and |vlist_out| are mutually
+ recursive}
+
+@ The recursive procedures |hlist_out| and |vlist_out| each have local variables
+|save_h| and |save_v| to hold the values of |dvi_h| and |dvi_v| just before
+entering a new level of recursion. In effect, the values of |save_h| and
+|save_v| on \TeX's run-time stack correspond to the values of |h| and |v|
+that a \.{DVI}-reading program will push onto its coordinate stack.
+
+@d move_past=13 {go to this label when advancing past glue or a rule}
+@d fin_rule=14 {go to this label to finish processing a rule}
+@d next_p=15 {go to this label when finished with node |p|}
+
+@p @t\4@>@<Declare procedures needed in |hlist_out|, |vlist_out|@>@t@>@/
+procedure hlist_out; {output an |hlist_node| box}
+label move_past, fin_rule, next_p;
+var base_line: scaled; {the baseline coordinate for this box}
+c_wd,c_ht,c_dp: scaled;
+ {the real width, height and depth of the character}
+edge_v: scaled;
+edge_h: scaled;
+effective_horizontal: scaled;
+basepoint_horizontal: scaled;
+basepoint_vertical: scaled;
+saving_h: scaled;
+saving_v: scaled;
+save_direction: integer;
+dir_ptr,dir_tmp:pointer;
+dvi_dir_h,dvi_dir_ptr,dvi_temp_ptr:integer;
+@!left_edge: scaled; {the left coordinate for this box}
+@!save_h,@!save_v: scaled; {what |dvi_h| and |dvi_v| should pop to}
+@!this_box: pointer; {pointer to containing box}
+@!g_order: glue_ord; {applicable order of infinity for glue}
+@!g_sign: normal..shrinking; {selects type of glue}
+@!p,q:pointer; {current position in the hlist}
+@!save_loc:integer; {\.{DVI} byte location upon entry}
+@!leader_box:pointer; {the leader box being replicated}
+@!leader_wd:scaled; {width of leader box being replicated}
+@!lx:scaled; {extra space between leader boxes}
+@!outer_doing_leaders:boolean; {were we doing leaders?}
+@!edge:scaled; {right edge of sub-box or leader space}
+@!glue_temp:real; {glue value before rounding}
+@!cur_glue:real; {glue seen so far}
+@!cur_g:scaled; {rounded equivalent of |cur_glue| times the glue ratio}
+begin cur_g:=0; cur_glue:=float_constant(0);
+this_box:=temp_ptr; g_order:=glue_order(this_box);
+g_sign:=glue_sign(this_box); p:=list_ptr(this_box);
+save_direction:=dvi_direction;
+dvi_direction:=box_dir(this_box);
+@<DIR: Initialize |dir_ptr| for |ship_out|@>;
+saving_h:=dvi_h; saving_v:=dvi_v;
+incr(cur_s);
+if cur_s>0 then dvi_out(push);
+if cur_s>max_push then max_push:=cur_s;
+save_loc:=dvi_offset+dvi_ptr; base_line:=cur_v; left_edge:=cur_h;
+while p<>null do @<Output node |p| for |hlist_out| and move to the next node,
+ maintaining the condition |cur_v=base_line|@>;
+cur_h:=saving_h; cur_v:=saving_v;
+synch_h; synch_v;
+prune_movements(save_loc);
+if cur_s>0 then dvi_pop(save_loc);
+decr(cur_s);
+dvi_direction:=save_direction;
+@<DIR: Reset |dir_ptr|@>;
+end;
+
+@ This is a cacheing attempt
+
+@d charinfo_width(#)==#.ci_wd
+@d charinfo_height(#)==#.ci_ht
+@d charinfo_depth(#)==#.ci_dp
+
+@<Types...@>=
+charinfo_short = packed record@;@/
+ @!ci_wd:scaled;
+ @!ci_ht:scaled;
+ @!ci_dp:scaled;
+ end;
+
+@ @<Glob...@>=
+ci:charinfo_short;
+
+@ We ought to give special care to the efficiency of one part of |hlist_out|,
+since it belongs to \TeX's inner loop. When a |char_node| is encountered,
+we save a little time by processing several nodes in succession until
+reaching a non-|char_node|. The program uses the fact that |set_char_0=0|.
+@^inner loop@>
+
+@<Output node |p| for |hlist_out|...@>=
+if is_char_node(p) then
+ begin synch_h; synch_v;
+ repeat f:=font(p); c:=character(p);
+ ci := char_info_short(f,c);
+ if f<>dvi_f then @<Change font |dvi_f| to |f|@>;
+ if is_rotated(dvi_direction) then begin
+ c_ht:=charinfo_width(ci) div 2;
+ c_wd:=charinfo_height(ci)+charinfo_depth(ci);
+ c_dp:=0;
+ end
+ else begin
+ c_ht:=charinfo_height(ci);
+ c_dp:=charinfo_depth(ci);
+ c_wd:=charinfo_width(ci);
+ end;
+ cur_h:=cur_h+c_wd;
+ if (font_natural_dir(f)<>-1) then begin
+ case font_direction(dvi_direction) of
+ dir__LT,dir__LB: begin
+ dvi_set(c);
+ end;
+ dir__RT,dir__RB: begin
+ dvi_put(c);
+ dvi_left(c_wd);
+ end;
+ dir__TL,dir__TR: begin
+ dvi_put(c);
+ dvi_down(c_wd);
+ end;
+ dir__BL,dir__BR: begin
+ dvi_put(c);
+ dvi_up(c_wd);
+ end;
+ dir__LL,dir__LR: begin
+ dvi_put(c);
+ dvi_right(c_wd);
+ end;
+ dir__RL,dir__RR: begin
+ dvi_put(c);
+ dvi_left(c_wd);
+ end;
+ dir__TT,dir__TB: begin
+ dvi_put(c);
+ dvi_down(c_wd);
+ end;
+ dir__BT,dir__BB: begin
+ dvi_put(c);
+ dvi_up(c_wd);
+ end;
+ end;
+ end else begin
+ case font_direction(dvi_direction) of
+ dir__LT: begin
+ dvi_set(c);
+ end;
+ dir__LB: begin
+ dvi_down(c_ht);
+ dvi_set(c);
+ dvi_up(c_ht);
+ end;
+ dir__RT: begin
+ dvi_left(c_wd);
+ dvi_put(c);
+ end;
+ dir__RB: begin
+ dvi_left(c_wd);
+ dvi_down(c_ht);
+ dvi_put(c);
+ dvi_up(c_ht);
+ end;
+ dir__TL: begin
+ dvi_down(c_wd);
+ dvi_left(c_ht);
+ dvi_put(c);
+ dvi_right(c_ht);
+ end;
+ dir__TR: begin
+ dvi_down(c_wd);
+ dvi_left(c_dp);
+ dvi_put(c);
+ dvi_right(c_dp);
+ end;
+ dir__BL: begin
+ dvi_left(c_ht);
+ dvi_put(c);
+ dvi_right(c_ht);
+ dvi_up(c_wd);
+ end;
+ dir__BR: begin
+ dvi_left(c_dp);
+ dvi_put(c);
+ dvi_right(c_dp);
+ dvi_up(c_wd);
+ end;
+ dir__LL,dir__LR: begin
+ dvi_down(c_ht);
+ dvi_put(c);
+ dvi_up(c_ht);
+ dvi_right(c_wd);
+ end;
+ dir__RL,dir__RR: begin
+ dvi_left(c_wd);
+ dvi_down(c_ht);
+ dvi_put(c);
+ dvi_up(c_ht);
+ end;
+ dir__TT,dir__TB: begin
+ dvi_down(c_wd);
+ dvi_left(c_ht);
+ dvi_put(c);
+ dvi_right(c_ht);
+ end;
+ dir__BT,dir__BB: begin
+ dvi_left(c_ht);
+ dvi_put(c);
+ dvi_right(c_ht);
+ dvi_up(c_wd);
+ end;
+ end;
+ end;
+ p:=vlink(p);
+ until not is_char_node(p);
+ dvi_h:=cur_h;
+ end
+else @<Output the non-|char_node| |p| for |hlist_out|
+ and move to the next node@>
+
+@ @<Change font |dvi_f| to |f|@>=
+begin if not font_used(f) then
+ begin dvi_font_def(f); set_font_used(f,true);
+ end;
+oval:=f-font_base-1; ocmd:=fnt1; out_cmd;@/
+dvi_f:=f;
+end
+
+@ @<Output the non-|char_node| |p| for |hlist_out|...@>=
+begin case type(p) of
+hlist_node,vlist_node:@<Output a box in an hlist@>;
+rule_node: begin
+ if not (dir_orthogonal(dir_primary[rule_dir(p)])(dir_primary[dvi_direction]))
+ then begin
+ rule_ht:=height(p); rule_dp:=depth(p); rule_wd:=width(p);
+ end
+ else begin
+ rule_ht:=width(p) div 2;
+ rule_dp:=width(p) div 2;
+ rule_wd:=height(p)+depth(p);
+ end;
+ goto fin_rule;
+ end;
+whatsit_node: @<Output the whatsit node |p| in an hlist@>;
+glue_node: @<Move right or output leaders@>;
+disc_node: if vlink(no_break(p))<>null then begin
+ vlink(tlink(no_break(p))):=vlink(p);
+ q:=vlink(no_break(p));
+ vlink(no_break(p)):=null;
+ vlink(p):=q;
+ end;
+margin_kern_node,kern_node:cur_h:=cur_h+width(p);
+math_node:cur_h:=cur_h+surround(p);
+othercases do_nothing
+endcases;@/
+goto next_p;
+fin_rule: @<Output a rule in an hlist@>;
+move_past: cur_h:=cur_h+rule_wd;
+next_p:p:=vlink(p);
+end
+
+@ @<Output a box in an hlist@>=
+begin
+if not (dir_orthogonal(dir_primary[box_dir(p)])(dir_primary[dvi_direction]))
+ then begin
+ effective_horizontal:=width(p);
+ basepoint_vertical:=0;
+ if dir_opposite(dir_secondary[box_dir(p)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=width(p)
+ else
+ basepoint_horizontal:=0;
+ end
+else begin
+ effective_horizontal:=height(p)+depth(p);
+ if not (is_mirrored(box_dir(p))) then
+ if dir_eq(dir_primary[box_dir(p)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=height(p)
+ else
+ basepoint_horizontal:=depth(p)
+ else
+ if dir_eq(dir_primary[box_dir(p)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=depth(p)
+ else
+ basepoint_horizontal:=height(p);
+ if dir_eq(dir_secondary[box_dir(p)])(dir_primary[dvi_direction]) then
+ basepoint_vertical:= -(width(p) div 2)
+ else
+ basepoint_vertical:= (width(p) div 2);
+ end;
+if not (is_mirrored(dvi_direction)) then
+ basepoint_vertical := basepoint_vertical + shift_amount(p)
+ {shift the box `down'}
+else
+ basepoint_vertical := basepoint_vertical - shift_amount(p);
+ {shift the box `up'}
+if list_ptr(p)=null then cur_h:=cur_h + effective_horizontal
+else begin
+ temp_ptr:=p; edge:=cur_h; cur_h:=cur_h + basepoint_horizontal;
+ edge_v:=cur_v; cur_v:=base_line + basepoint_vertical;
+ synch_h; synch_v; save_h:=dvi_h; save_v:=dvi_v;
+ if type(p)=vlist_node then vlist_out@+else hlist_out;
+ dvi_h:=save_h; dvi_v:=save_v;
+ cur_h:=edge+effective_horizontal; cur_v:=base_line;
+ end
+end
+
+@ @<Output a rule in an hlist@>=
+if is_running(rule_ht) then rule_ht:=height(this_box);
+if is_running(rule_dp) then rule_dp:=depth(this_box);
+rule_ht:=rule_ht+rule_dp; {this is the rule thickness}
+if (rule_ht>0)and(rule_wd>0) then {we don't output empty rules}
+ begin synch_h; cur_v:=base_line+rule_dp; synch_v;
+ case font_direction(dvi_direction) of
+ dir__LT: begin
+ dvi_set_rule(rule_ht)(rule_wd);
+ end;
+ dir__LB: begin
+ dvi_down(rule_ht);
+ dvi_set_rule(rule_ht)(rule_wd);
+ dvi_up(rule_ht);
+ end;
+ dir__RT: begin
+ dvi_left(rule_wd);
+ dvi_put_rule(rule_ht)(rule_wd);
+ end;
+ dir__RB: begin
+ dvi_left(rule_wd);
+ dvi_down(rule_ht);
+ dvi_put_rule(rule_ht)(rule_wd);
+ dvi_up(rule_ht);
+ end;
+ dir__TL: begin
+ dvi_down(rule_wd);
+ dvi_left(rule_ht);
+ dvi_set_rule(rule_wd)(rule_ht);
+ end;
+ dir__TR: begin
+ dvi_down(rule_wd);
+ dvi_put_rule(rule_wd)(rule_ht);
+ end;
+ dir__BL: begin
+ dvi_left(rule_ht);
+ dvi_set_rule(rule_wd)(rule_ht);
+ dvi_up(rule_wd);
+ end;
+ dir__BR: begin
+ dvi_put_rule(rule_wd)(rule_ht);
+ dvi_up(rule_wd);
+ end;
+ end;
+ cur_v:=base_line; dvi_h:=dvi_h+rule_wd;
+ end
+
+@ @d billion==float_constant(1000000000)
+@d vet_glue(#)== glue_temp:=#;
+ if glue_temp>billion then
+ glue_temp:=billion
+ else if glue_temp<-billion then
+ glue_temp:=-billion
+
+@<Move right or output leaders@>=
+begin g:=glue_ptr(p); rule_wd:=width(g)-cur_g;
+if g_sign<>normal then
+ begin if g_sign=stretching then
+ begin if stretch_order(g)=g_order then
+ begin cur_glue:=cur_glue+stretch(g);
+ vet_glue(float(glue_set(this_box))*cur_glue);
+@^real multiplication@>
+ cur_g:=round(glue_temp);
+ end;
+ end
+ else if shrink_order(g)=g_order then
+ begin cur_glue:=cur_glue-shrink(g);
+ vet_glue(float(glue_set(this_box))*cur_glue);
+ cur_g:=round(glue_temp);
+ end;
+ end;
+rule_wd:=rule_wd+cur_g;
+
+if subtype(p)>=a_leaders then
+ @<Output leaders in an hlist, |goto fin_rule| if a rule
+ or to |next_p| if done@>;
+goto move_past;
+end
+
+@ @<Output leaders in an hlist...@>=
+begin leader_box:=leader_ptr(p);
+if type(leader_box)=rule_node then
+ begin rule_ht:=height(leader_box); rule_dp:=depth(leader_box);
+ goto fin_rule;
+ end;
+if not (dir_orthogonal(dir_primary[box_dir(leader_box)])(dir_primary[dvi_direction]))
+ then leader_wd:=width(leader_box)
+else
+ leader_wd:=height(leader_box)+depth(leader_box);
+if (leader_wd>0)and(rule_wd>0) then
+ begin rule_wd:=rule_wd+10; {compensate for floating-point rounding}
+ edge:=cur_h+rule_wd; lx:=0;
+ @<Let |cur_h| be the position of the first box, and set |leader_wd+lx|
+ to the spacing between corresponding parts of boxes@>;
+ while cur_h+leader_wd<=edge do
+ @<Output a leader box at |cur_h|,
+ then advance |cur_h| by |leader_wd+lx|@>;
+ cur_h:=edge-10; goto next_p;
+ end;
+end
+
+@ The calculations related to leaders require a bit of care. First, in the
+case of |a_leaders| (aligned leaders), we want to move |cur_h| to
+|left_edge| plus the smallest multiple of |leader_wd| for which the result
+is not less than the current value of |cur_h|; i.e., |cur_h| should become
+$|left_edge|+|leader_wd|\times\lceil
+(|cur_h|-|left_edge|)/|leader_wd|\rceil$. The program here should work in
+all cases even though some implementations of \PASCAL\ give nonstandard
+results for the |div| operation when |cur_h| is less than |left_edge|.
+
+In the case of |c_leaders| (centered leaders), we want to increase |cur_h|
+by half of the excess space not occupied by the leaders; and in the
+case of |x_leaders| (expanded leaders) we increase |cur_h|
+by $1/(q+1)$ of this excess space, where $q$ is the number of times the
+leader box will be replicated. Slight inaccuracies in the division might
+accumulate; half of this rounding error is placed at each end of the leaders.
+
+@<Let |cur_h| be the position of the first box, ...@>=
+if subtype(p)=a_leaders then
+ begin save_h:=cur_h;
+ cur_h:=left_edge+leader_wd*((cur_h-left_edge)@!div leader_wd);
+ if cur_h<save_h then cur_h:=cur_h+leader_wd;
+ end
+else begin lq:=rule_wd div leader_wd; {the number of box copies}
+ lr:=rule_wd mod leader_wd; {the remaining space}
+ if subtype(p)=c_leaders then cur_h:=cur_h+(lr div 2)
+ else begin lx:=lr div (lq+1);
+ cur_h:=cur_h+((lr-(lq-1)*lx) div 2);
+ end;
+ end
+
+@ The `\\{synch}' operations here are intended to decrease the number of
+bytes needed to specify horizontal and vertical motion in the \.{DVI} output.
+
+@<Output a leader box at |cur_h|, ...@>=
+begin
+if not (dir_orthogonal(dir_primary[box_dir(leader_box)])(dir_primary[dvi_direction]))
+ then begin
+ basepoint_vertical:=0;
+ if dir_opposite(dir_secondary[box_dir(leader_box)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=width(leader_box)
+ else
+ basepoint_horizontal:=0;
+ end
+else begin
+ if not (is_mirrored(box_dir(leader_box))) then
+ if dir_eq(dir_primary[box_dir(leader_box)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=height(leader_box)
+ else
+ basepoint_horizontal:=depth(leader_box)
+ else
+ if dir_eq(dir_primary[box_dir(leader_box)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=depth(leader_box)
+ else
+ basepoint_horizontal:=height(leader_box);
+ if dir_eq(dir_secondary[box_dir(leader_box)])(dir_primary[dvi_direction]) then
+ basepoint_vertical:= -(width(leader_box) div 2)
+ else
+ basepoint_vertical:= (width(leader_box) div 2);
+ end;
+if not (is_mirrored(dvi_direction)) then
+ basepoint_vertical := basepoint_vertical + shift_amount(leader_box)
+ {shift the box `down'}
+else
+ basepoint_vertical := basepoint_vertical - shift_amount(leader_box);
+ {shift the box `up'}
+temp_ptr:=leader_box;
+edge_h:=cur_h; cur_h:=cur_h + basepoint_horizontal;
+edge_v:=cur_v; cur_v:=base_line + basepoint_vertical;
+synch_h; synch_v; save_h:=dvi_h; save_v:=dvi_v;
+outer_doing_leaders:=doing_leaders; doing_leaders:=true;
+if type(leader_box)=vlist_node then vlist_out@+else hlist_out;
+doing_leaders:=outer_doing_leaders;
+dvi_h:=save_h; dvi_v:=save_v;
+cur_h:=edge_h+leader_wd+lx; cur_v:=base_line;
+end
+
+@ The |vlist_out| routine is similar to |hlist_out|, but a bit simpler.
+
+@p procedure vlist_out; {output a |vlist_node| box}
+label move_past, fin_rule, next_p;
+var left_edge: scaled; {the left coordinate for this box}
+@!top_edge: scaled; {the top coordinate for this box}
+@!save_h,@!save_v: scaled; {what |dvi_h| and |dvi_v| should pop to}
+@!this_box: pointer; {pointer to containing box}
+@!g_order: glue_ord; {applicable order of infinity for glue}
+@!g_sign: normal..shrinking; {selects type of glue}
+@!p:pointer; {current position in the vlist}
+@!save_loc:integer; {\.{DVI} byte location upon entry}
+@!leader_box:pointer; {the leader box being replicated}
+@!leader_ht:scaled; {height of leader box being replicated}
+@!lx:scaled; {extra space between leader boxes}
+@!outer_doing_leaders:boolean; {were we doing leaders?}
+@!edge:scaled; {bottom boundary of leader space}
+@!glue_temp:real; {glue value before rounding}
+@!cur_glue:real; {glue seen so far}
+@!cur_g:scaled; {rounded equivalent of |cur_glue| times the glue ratio}
+@!save_direction: integer;
+@!effective_vertical: scaled;
+@!basepoint_horizontal: scaled;
+@!basepoint_vertical: scaled;
+@!edge_v: scaled;
+@!saving_v: scaled;
+@!saving_h: scaled;
+begin cur_g:=0; cur_glue:=float_constant(0);
+this_box:=temp_ptr; g_order:=glue_order(this_box);
+g_sign:=glue_sign(this_box); p:=list_ptr(this_box);
+{pdfassert(p<>0);}
+saving_v:=dvi_v; saving_h:=dvi_h;
+save_direction:=dvi_direction;
+dvi_direction:=box_dir(this_box);
+incr(cur_s);
+if cur_s>0 then dvi_out(push);
+if cur_s>max_push then max_push:=cur_s;
+save_loc:=dvi_offset+dvi_ptr; left_edge:=cur_h; cur_v:=cur_v-height(this_box);
+top_edge:=cur_v;
+while p<>null do @<Output node |p| for |vlist_out| and move to the next node,
+ maintaining the condition |cur_h=left_edge|@>;
+cur_v:=saving_v; cur_h:=saving_h;
+synch_v; synch_h;
+prune_movements(save_loc);
+if cur_s>0 then dvi_pop(save_loc);
+decr(cur_s);
+dvi_direction:=save_direction;
+end;
+
+@ @<Output node |p| for |vlist_out|...@>=
+begin if is_char_node(p) then begin print_font_and_char(p); confusion("vlistout"); end
+@:this can't happen vlistout}{\quad vlistout@>
+else @<Output the non-|char_node| |p| for |vlist_out|@>;
+next_p:p:=vlink(p);
+end
+
+@ @<Output the non-|char_node| |p| for |vlist_out|@>=
+begin case type(p) of
+hlist_node,vlist_node:@<Output a box in a vlist@>;
+rule_node: begin
+ if not (dir_orthogonal(dir_primary[rule_dir(p)])(dir_primary[dvi_direction]))
+ then begin
+ rule_ht:=height(p); rule_dp:=depth(p); rule_wd:=width(p);
+ end
+ else begin
+ rule_ht:=width(p) div 2;
+ rule_dp:=width(p) div 2;
+ rule_wd:=height(p)+depth(p);
+ end;
+ goto fin_rule;
+ end;
+whatsit_node: @<Output the whatsit node |p| in a vlist@>;
+glue_node: @<Move down or output leaders@>;
+kern_node:cur_v:=cur_v+width(p);
+othercases do_nothing
+endcases;@/
+goto next_p;
+fin_rule: @<Output a rule in a vlist, |goto next_p|@>;
+move_past: cur_v:=cur_v+rule_ht;
+end
+
+@ The |synch_v| here allows the \.{DVI} output to use one-byte commands
+for adjusting |v| in most cases, since the baselineskip distance will
+usually be constant.
+
+@<Output a box in a vlist@>=
+begin
+if not (dir_orthogonal(dir_primary[box_dir(p)])(dir_primary[dvi_direction]))
+ then begin
+ effective_vertical:=height(p)+depth(p);
+ if (type(p)=hlist_node) and (is_mirrored(box_dir(p))) then
+ basepoint_vertical:=depth(p)
+ else
+ basepoint_vertical:=height(p);
+ if dir_opposite(dir_secondary[box_dir(p)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=width(p)
+ else
+ basepoint_horizontal:=0;
+ end
+else begin
+ effective_vertical:=width(p);
+ if not (is_mirrored(box_dir(p))) then
+ if dir_eq(dir_primary[box_dir(p)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=height(p)
+ else
+ basepoint_horizontal:=depth(p)
+ else
+ if dir_eq(dir_primary[box_dir(p)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=depth(p)
+ else
+ basepoint_horizontal:=height(p);
+ if dir_eq(dir_secondary[box_dir(p)])(dir_primary[dvi_direction]) then
+ basepoint_vertical:=0
+ else
+ basepoint_vertical:=width(p);
+ end;
+basepoint_horizontal := basepoint_horizontal + shift_amount(p);
+ {shift the box `right'}
+if list_ptr(p)=null then begin
+ cur_v:=cur_v+effective_vertical;
+ end
+else begin
+ synch_h; synch_v; edge_v:=cur_v;
+ cur_h:=left_edge + basepoint_horizontal;
+ cur_v:=cur_v + basepoint_vertical;
+ synch_h; synch_v; save_h:=dvi_h; save_v:=dvi_v;
+ temp_ptr:=p;
+ if type(p)=vlist_node then vlist_out@+else hlist_out;
+ dvi_h:=save_h; dvi_v:=save_v;
+ cur_h:=left_edge; cur_v:=edge_v + effective_vertical;
+ end
+end
+
+@ @<Output a rule in a vlist...@>=
+if is_running(rule_wd) then rule_wd:=width(this_box);
+rule_ht:=rule_ht+rule_dp; {this is the rule thickness}
+cur_v:=cur_v+rule_ht;
+if (rule_ht>0)and(rule_wd>0) then {we don't output empty rules}
+ begin synch_h; synch_v;
+ case font_direction(dvi_direction) of
+ dir__LT: begin
+ dvi_put_rule(rule_ht)(rule_wd);
+ end;
+ dir__LB: begin
+ dvi_down(rule_ht);
+ dvi_put_rule(rule_ht)(rule_wd);
+ dvi_up(rule_ht);
+ end;
+ dir__RT: begin
+ dvi_left(rule_wd);
+ dvi_set_rule(rule_ht)(rule_wd);
+ end;
+ dir__RB: begin
+ dvi_down(rule_ht);
+ dvi_left(rule_wd);
+ dvi_set_rule(rule_ht)(rule_wd);
+ dvi_up(rule_ht);
+ end;
+ dir__TL: begin
+ dvi_down(rule_wd);
+ dvi_left(rule_ht);
+ dvi_set_rule(rule_wd)(rule_ht);
+ dvi_up(rule_wd);
+ end;
+ dir__TR: begin
+ dvi_down(rule_wd);
+ dvi_put_rule(rule_wd)(rule_ht);
+ dvi_up(rule_wd);
+ end;
+ dir__BL: begin
+ dvi_left(rule_ht);
+ dvi_set_rule(rule_wd)(rule_ht);
+ end;
+ dir__BR: begin
+ dvi_put_rule(rule_wd)(rule_ht);
+ end;
+ end;
+ end;
+goto next_p
+
+@ @<Move down or output leaders@>=
+begin g:=glue_ptr(p); rule_ht:=width(g)-cur_g;
+if g_sign<>normal then
+ begin if g_sign=stretching then
+ begin if stretch_order(g)=g_order then
+ begin cur_glue:=cur_glue+stretch(g);
+ vet_glue(float(glue_set(this_box))*cur_glue);
+@^real multiplication@>
+ cur_g:=round(glue_temp);
+ end;
+ end
+ else if shrink_order(g)=g_order then
+ begin cur_glue:=cur_glue-shrink(g);
+ vet_glue(float(glue_set(this_box))*cur_glue);
+ cur_g:=round(glue_temp);
+ end;
+ end;
+rule_ht:=rule_ht+cur_g;
+if subtype(p)>=a_leaders then
+ @<Output leaders in a vlist, |goto fin_rule| if a rule
+ or to |next_p| if done@>;
+goto move_past;
+end
+
+@ @<Output leaders in a vlist...@>=
+begin leader_box:=leader_ptr(p);
+if type(leader_box)=rule_node then
+ begin rule_wd:=width(leader_box); rule_dp:=0;
+ goto fin_rule;
+ end;
+if not (dir_orthogonal(dir_primary[box_dir(leader_box)])(dir_primary[dvi_direction]))
+ then leader_ht:=height(leader_box)+depth(leader_box)
+else
+ leader_ht:=width(leader_box);
+if (leader_ht>0)and(rule_ht>0) then
+ begin rule_ht:=rule_ht+10; {compensate for floating-point rounding}
+ edge:=cur_v+rule_ht; lx:=0;
+ @<Let |cur_v| be the position of the first box, and set |leader_ht+lx|
+ to the spacing between corresponding parts of boxes@>;
+ while cur_v+leader_ht<=edge do
+ @<Output a leader box at |cur_v|,
+ then advance |cur_v| by |leader_ht+lx|@>;
+ cur_v:=edge-10; goto next_p;
+ end;
+end
+
+@ @<Let |cur_v| be the position of the first box, ...@>=
+if subtype(p)=a_leaders then
+ begin save_v:=cur_v;
+ cur_v:=top_edge+leader_ht*((cur_v-top_edge)@!div leader_ht);
+ if cur_v<save_v then cur_v:=cur_v+leader_ht;
+ end
+else begin lq:=rule_ht div leader_ht; {the number of box copies}
+ lr:=rule_ht mod leader_ht; {the remaining space}
+ if subtype(p)=c_leaders then cur_v:=cur_v+(lr div 2)
+ else begin lx:=lr div (lq+1);
+ cur_v:=cur_v+((lr-(lq-1)*lx) div 2);
+ end;
+ end
+
+@ When we reach this part of the program, |cur_v| indicates the top of a
+leader box, not its baseline.
+
+@<Output a leader box at |cur_v|, ...@>=
+begin
+if not (dir_orthogonal(dir_primary[box_dir(leader_box)])(dir_primary[dvi_direction]))
+ then begin
+ effective_vertical:=height(leader_box)+depth(leader_box);
+ if (type(leader_box)=hlist_node) and (is_mirrored(box_dir(leader_box))) then
+ basepoint_vertical:=depth(leader_box)
+ else
+ basepoint_vertical:=height(leader_box);
+ if dir_opposite(dir_secondary[box_dir(leader_box)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=width(leader_box)
+ else
+ basepoint_horizontal:=0;
+ end
+else begin
+ effective_vertical:=width(leader_box);
+ if not (is_mirrored(box_dir(leader_box))) then
+ if dir_eq(dir_primary[box_dir(leader_box)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=height(leader_box)
+ else
+ basepoint_horizontal:=depth(leader_box)
+ else
+ if dir_eq(dir_primary[box_dir(leader_box)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=depth(leader_box)
+ else
+ basepoint_horizontal:=height(leader_box);
+ if dir_eq(dir_secondary[box_dir(leader_box)])(dir_primary[dvi_direction]) then
+ basepoint_vertical:= width(leader_box)
+ else
+ basepoint_vertical:= 0;
+ end;
+basepoint_horizontal := basepoint_horizontal + shift_amount(leader_box);
+ {shift the box `right'}
+temp_ptr:=leader_box;
+cur_h:=left_edge + basepoint_horizontal;
+edge_v:=cur_v ;
+cur_v:=cur_v + basepoint_vertical;
+synch_h; synch_v; save_h:=dvi_h; save_v:=dvi_v;
+outer_doing_leaders:=doing_leaders; doing_leaders:=true;
+if type(leader_box)=vlist_node then vlist_out@+else hlist_out;
+doing_leaders:=outer_doing_leaders;
+dvi_h:=save_h; dvi_v:=save_v;
+cur_h:=left_edge; cur_v:=edge_v+leader_ht+lx;
+end
+
+@ The |hlist_out| and |vlist_out| procedures are now complete, so we are
+ready for the |dvi_ship_out| routine that gets them started in the first place.
+
+@p procedure dvi_ship_out(@!p:pointer); {output the box |p|}
+label done;
+var page_loc:integer; {location of the current |bop|}
+@!j,@!k:0..9; {indices to first ten count registers}
+@!s:pool_pointer; {index into |str_pool|}
+@!old_setting:0..max_selector; {saved |selector| setting}
+pre_callback_id:integer;
+post_callback_id:integer;
+ret:boolean;
+begin
+pre_callback_id:=callback_defined(start_page_number_callback);
+post_callback_id:=callback_defined(stop_page_number_callback);
+if (tracing_output>0)and(pre_callback_id=0) then
+ begin print_nl(""); print_ln;
+ print("Completed box being shipped out");
+@.Completed box...@>
+ end;
+if pre_callback_id>0 then
+ ret:=run_callback(pre_callback_id,'->')
+else begin
+ if term_offset>max_print_line-9 then print_ln
+ else if (term_offset>0)or(file_offset>0) then print_char(" ");
+ print_char("["); j:=9;
+ while (count(j)=0)and(j>0) do decr(j);
+ for k:=0 to j do
+ begin print_int(count(k));
+ if k<j then print_char(".");
+ end;
+ end;
+update_terminal;
+if (tracing_output>0)and(post_callback_id=0) then
+ begin print_char("]");
+ begin_diagnostic; show_box(p); end_diagnostic(true);
+ end;
+@<Ship box |p| out@>;
+if (tracing_output<=0)and(post_callback_id=0) then
+ print_char("]");
+dead_cycles:=0;
+update_terminal; {progress report}
+@<Flush the box from memory, showing statistics if requested@>;
+if post_callback_id>0 then
+ ret:=run_callback(post_callback_id,'->');
+end;
+
+@ @<Flush the box from memory, showing statistics if requested@>=
+@!stat if (tracing_stats>1)and(pre_callback_id=0) then
+ begin print_nl("Memory usage before: ");
+@.Memory usage...@>
+ print_int(var_used); print_char("&");
+ print_int(dyn_used); print_char(";");
+ end;
+tats@/
+flush_node_list(p);
+@!stat if (tracing_stats>1)and(post_callback_id=0) then
+ begin print(" after: ");
+ print_int(var_used); print_char("&");
+ print_int(dyn_used); print_ln;
+ end;
+tats
+
+@ @<Ship box |p| out@>=
+@<Update the values of |max_h| and |max_v|; but if the page is too large,
+ |goto done|@>;
+@<Initialize variables as |ship_out| begins@>;
+page_loc:=dvi_offset+dvi_ptr;
+dvi_out(bop);
+for k:=0 to 9 do dvi_four(count(k));
+dvi_four(last_bop); last_bop:=page_loc;
+dvi_direction:=page_direction;
+case box_direction(dvi_direction) of
+dir_TL_,dir_LT_: begin
+ end;
+dir_TR_,dir_RT_: begin
+ dvi_right(cur_page_width-cur_right_offset);
+ dvi_h:=-cur_right_offset;
+ end;
+dir_RB_,dir_BR_: begin
+ dvi_right(cur_page_width-cur_right_offset);
+ dvi_down(cur_page_height-cur_bottom_offset);
+ dvi_h:=-cur_right_offset;
+ dvi_v:=-cur_bottom_offset;
+ end;
+dir_BL_,dir_LB_: begin
+ dvi_down(cur_page_height-cur_bottom_offset);
+ dvi_v:=-cur_bottom_offset;
+ end;
+end;
+cur_h:=h_offset;
+cur_v:=height(p)+v_offset;
+case box_direction(dvi_direction) of
+dir_TL_: begin
+ dvi_down(cur_v);
+ dvi_right(cur_h);
+ end;
+dir_TR_: begin
+ dvi_down(cur_v);
+ dvi_right(-cur_h);
+ end;
+dir_LT_: begin
+ dvi_right(cur_v);
+ dvi_down(cur_h);
+ end;
+dir_LB_: begin
+ dvi_right(cur_v);
+ dvi_down(-cur_h);
+ end;
+dir_BL_: begin
+ dvi_down(-cur_v);
+ dvi_right(cur_h);
+ end;
+dir_BR_: begin
+ dvi_down(-cur_v);
+ dvi_right(-cur_h);
+ end;
+dir_RT_: begin
+ dvi_right(-cur_v);
+ dvi_down(cur_h);
+ end;
+dir_RB_: begin
+ dvi_right(-cur_v);
+ dvi_down(-cur_h);
+ end;
+end;
+dvi_h:=cur_h;
+dvi_v:=cur_v;
+temp_ptr:=p;
+if type(p)=vlist_node then vlist_out@+else hlist_out;
+dvi_out(eop); incr(total_pages); cur_s:=-1;
+done:
+
+@ Sometimes the user will generate a huge page because other error messages
+are being ignored. Such pages are not output to the \.{dvi} file, since they
+may confuse the printing software.
+
+@<Update the values of |max_h| and |max_v|; but if the page is too large...@>=
+if (height(p)>max_dimen)or@|(depth(p)>max_dimen)or@|
+ (height(p)+depth(p)+v_offset>max_dimen)or@|
+ (width(p)+h_offset>max_dimen) then
+ begin print_err("Huge page cannot be shipped out");
+@.Huge page...@>
+ help2("The page just created is more than 18 feet tall or")@/
+ ("more than 18 feet wide, so I suspect something went wrong.");
+ error;
+ if tracing_output<=0 then
+ begin begin_diagnostic;
+ print_nl("The following box has been deleted:");
+@.The following...deleted@>
+ show_box(p);
+ end_diagnostic(true);
+ end;
+ goto done;
+ end;
+if height(p)+depth(p)+v_offset>max_v then max_v:=height(p)+depth(p)+v_offset;
+if width(p)+h_offset>max_h then max_h:=width(p)+h_offset
+
+@ At the end of the program, we must finish things off by writing the
+post\-amble. If |total_pages=0|, the \.{DVI} file was never opened.
+If |total_pages>=65536|, the \.{DVI} file will lie.
+
+An integer variable |k| will be declared for use by this routine.
+
+@<Finish the \.{DVI} file@>=
+while cur_s>-1 do
+ begin if cur_s>0 then dvi_out(pop)
+ else begin dvi_out(eop); incr(total_pages);
+ end;
+ decr(cur_s);
+ end;
+if total_pages=0 then begin
+ if callback_id=0 then
+ print_nl("No pages of output.")
+ else
+ res:=run_callback(callback_id,'->');
+ end
+@.No pages of output@>
+else begin dvi_out(post); {beginning of the postamble}
+ dvi_four(last_bop); last_bop:=dvi_offset+dvi_ptr-5; {|post| location}
+ dvi_four(25400000); dvi_four(473628672); {conversion ratio for sp}
+ prepare_mag; dvi_four(mag); {magnification factor}
+ dvi_four(max_v); dvi_four(max_h);@/
+ dvi_out(max_push div 256); dvi_out(max_push mod 256);@/
+ dvi_out((total_pages div 256) mod 256); dvi_out(total_pages mod 256);@/
+ @<Output the font definitions for all fonts that were used@>;
+ dvi_out(post_post); dvi_four(last_bop); dvi_out(id_byte);@/
+ k:=4+((dvi_buf_size-dvi_ptr) mod 4); {the number of 223's}
+ while k>0 do
+ begin dvi_out(223); decr(k);
+ end;
+ @<Empty the last bytes out of |dvi_buf|@>;
+ if callback_id=0 then begin
+ print_nl("Output written on "); slow_print(output_file_name);
+@.Output written on x@>
+ print(" ("); print_int(total_pages); print(" page");
+ if total_pages<>1 then print_char("s");
+ print(", "); print_int(dvi_offset+dvi_ptr); print(" bytes).");
+ end
+ else
+ res:=run_callback(callback_id,'->');
+ b_close(dvi_file);
+ end
+
+@ @<Output the font definitions...@>=
+k := max_font_id;
+while k>0 do
+ begin if font_used(k) then dvi_font_def(k);
+ decr(k);
+ end
+
+
+@* \[32a] \pdfTeX\ basic.
+
+Initialize \pdfTeX's parameters to some useful default value.
+Helpful in case one forgets to set them during initex run.
+
+@<Initialize table entries...@>=
+pdf_h_origin := one_inch;
+pdf_v_origin := one_inch;
+pdf_compress_level := 9;
+pdf_objcompresslevel := 0;
+pdf_decimal_digits := 3;
+pdf_image_resolution := 72;
+pdf_minor_version := 4;
+pdf_gamma := 1000;
+pdf_image_gamma := 2200;
+pdf_image_hicolor := 1;
+pdf_image_apply_gamma := 0;
+pdf_px_dimen := one_bp;
+pdf_draftmode := 0;
+
+@ The subroutines define the corresponding macros so we can use them
+in C.
+
+@d flushable(#) == (# = str_ptr - 1)
+
+@d is_valid_char(#) == char_exists(f,#)
+
+@p function get_pdf_compress_level: integer;
+begin
+ get_pdf_compress_level := pdf_compress_level;
+end;
+
+function get_nullfont: internal_font_number;
+begin
+ get_nullfont := null_font;
+end;
+
+function get_escape_char: integer;
+begin
+ get_escape_char := escape_char;
+end;
+
+function get_undefined_control_sequence: integer;
+begin
+ get_undefined_control_sequence := undefined_control_sequence;
+end;
+
+function get_fontbase: internal_font_number;
+begin
+ get_fontbase := font_base;
+end;
+
+function get_nullcs: pointer;
+begin
+ get_nullcs := null_cs;
+end;
+
+function get_nullptr: pointer;
+begin
+ get_nullptr := null;
+end;
+
+function get_tex_int(code: integer): integer;
+begin
+ get_tex_int := int_par(code);
+end;
+
+function get_tex_dimen(code: integer): scaled;
+begin
+ get_tex_dimen := dimen_par(code);
+end;
+
+function get_x_height(f: internal_font_number): scaled;
+begin
+ get_x_height := x_height(f);
+end;
+
+function get_charwidth(f: internal_font_number; c: integer): scaled;
+begin
+ if is_valid_char(c) then
+ get_charwidth := char_width(f,c)
+ else
+ get_charwidth := 0;
+end;
+
+function get_charheight(f: internal_font_number; c: integer): scaled;
+begin
+ if is_valid_char(c) then
+ get_charheight := char_height(f,c)
+ else
+ get_charheight := 0;
+end;
+
+function get_chardepth(f: internal_font_number; c: integer): scaled;
+begin
+ if is_valid_char(c) then
+ get_chardepth := char_depth(f,c)
+ else
+ get_chardepth := 0;
+end;
+
+function get_quad(f: internal_font_number): scaled;
+begin
+ get_quad := quad(f);
+end;
+
+function get_slant(f: internal_font_number): scaled;
+begin
+ get_slant := slant(f);
+end;
+
+function new_dummy_font: internal_font_number;
+begin
+ new_dummy_font := read_font_info(null_cs, "dummy", "", -1000, -1);
+end;
+
+function get_hash_size: integer;
+begin
+ get_hash_size:= hash_size;
+end;
+
+function get_eqtb_size: integer;
+begin
+ get_eqtb_size:= eqtb_size;
+end;
+
+function get_hash_base: integer;
+begin
+ get_hash_base:= hash_base;
+end;
+
+function get_active_base: integer;
+begin
+ get_active_base:= active_base;
+end;
+
+function get_cur_font: internal_font_number;
+begin
+ get_cur_font:= cur_font;
+end;
+
+procedure set_cur_font (f: internal_font_number);
+var a:small_number;
+begin
+ a:=0;
+ define(cur_font_loc,data,f);
+end;
+
+function get_current_name: str_number;
+begin
+ get_current_name:= name;
+end;
+
+
+@ Helper for debugging purposes
+
+@p procedure short_display_n(@!p, m:integer); {prints highlights of list |p|}
+var i: integer;
+begin
+i := 0;
+font_in_short_display:=null_font;
+if p = null then
+ return;
+while p<>null do
+ begin if is_char_node(p) then
+ begin if p<=max_halfword then
+ begin if font(p)<>font_in_short_display then
+ begin if not is_valid_font(font(p)) then
+ print_char("*")
+@.*\relax@>
+ else print_font_identifier(font(p));
+ print_char(" "); font_in_short_display:=font(p);
+ end;
+ print(qo(character(p)));
+ end;
+ end
+ else begin
+ if (type(p) = glue_node) or
+ (type(p) = disc_node) or
+ (type(p) = penalty_node) or
+ ((type(p) = kern_node) and (subtype(p) = explicit)) then
+ incr(i);
+ if i >= m then
+ return;
+ if (type(p) = disc_node) then begin
+ print("|");
+ short_display(vlink(pre_break(p)));
+ print("|");
+ short_display(vlink(post_break(p)));
+ print("|");
+ end
+ else
+ @<Print a short indication of the contents of node |p|@>;
+ end;
+ p:=vlink(p);
+ if p = null then
+ return;
+ end;
+ update_terminal;
+end;
+
+@ Sometimes it is neccesary to allocate memory for PDF output that cannot
+be deallocated then, so we use |pdf_mem| for this purpose.
+
+@<Constants...@>=
+@!inf_pdf_mem_size = 10000; {min size of the |pdf_mem| array}
+@!sup_pdf_mem_size = 10000000; {max size of the |pdf_mem| array}
+
+@ @<Glob...@>=
+@!pdf_mem_size: integer;
+@!pdf_mem: ^integer;
+@!pdf_mem_ptr: integer;
+
+@ @<Set init...@>=
+pdf_mem_ptr := 1; {the first word is not used so we can use zero as a value for testing
+whether a pointer to |pdf_mem| is valid}
+pdf_mem_size := inf_pdf_mem_size; {allocated size of |pdf_mem| array}
+
+@ We use |pdf_get_mem| to allocate memory in |pdf_mem|
+
+@p function pdf_get_mem(s: integer): integer; {allocate |s| words in |pdf_mem|}
+var a: integer;
+begin
+ if s > sup_pdf_mem_size - pdf_mem_ptr then
+ overflow("PDF memory size (pdf_mem_size)", pdf_mem_size);
+ if pdf_mem_ptr + s > pdf_mem_size then begin
+ a := 0.2 * pdf_mem_size;
+ if pdf_mem_ptr + s > pdf_mem_size + a then
+ pdf_mem_size := pdf_mem_ptr + s
+ else if pdf_mem_size < sup_pdf_mem_size - a then
+ pdf_mem_size := pdf_mem_size + a
+ else
+ pdf_mem_size := sup_pdf_mem_size;
+ pdf_mem := xreallocarray(pdf_mem, integer, pdf_mem_size);
+ end;
+ pdf_get_mem := pdf_mem_ptr;
+ pdf_mem_ptr := pdf_mem_ptr + s;
+end;
+
+@* \[32b] \pdfTeX\ output low-level subroutines.
+We use the similiar subroutines to handle the output buffer for
+PDF output. When compress is used, the state of writing to buffer
+is held in |zip_write_state|. We must write the header of PDF
+output file in initialization to ensure that it will be the first
+written bytes.
+
+@<Constants...@>=
+@!pdf_op_buf_size = 16384; {size of the PDF output buffer}
+@!inf_pdf_os_buf_size = 1; {initial value of |pdf_os_buf_size|}
+@!sup_pdf_os_buf_size = 5000000; {arbitrary upper hard limit of |pdf_os_buf_size|}
+@!pdf_os_max_objs = 100; {maximum number of objects in object stream}
+
+@ The following macros are similar as for \.{DVI} buffer handling
+
+@d pdf_offset == (pdf_gone + pdf_ptr) {the file offset of last byte in PDF
+buffer that |pdf_ptr| points to}
+
+@d no_zip == 0 {no \.{ZIP} compression}
+@d zip_writing == 1 {\.{ZIP} compression being used}
+@d zip_finish == 2 {finish \.{ZIP} compression}
+
+@d pdf_quick_out(#) == {output a byte to PDF buffer without checking of
+overflow}
+begin
+ pdf_buf[pdf_ptr] := #;
+ incr(pdf_ptr);
+end
+
+@d pdf_room(#) == {make sure that there are at least |n| bytes free in PDF buffer}
+begin
+ if pdf_os_mode and (# + pdf_ptr > pdf_buf_size) then
+ pdf_os_get_os_buf(#)
+ else if not pdf_os_mode and (# > pdf_buf_size) then
+ overflow("PDF output buffer", pdf_op_buf_size)
+ else if not pdf_os_mode and (# + pdf_ptr > pdf_buf_size) then
+ pdf_flush;
+end
+
+@d pdf_out(#) == {do the same as |pdf_quick_out| and flush the PDF
+buffer if necessary}
+begin
+ pdf_room(1);
+ pdf_quick_out(#);
+end
+
+@<Glob...@>=
+@!pdf_file: byte_file; {the PDF output file}
+@!pdf_buf: ^real_eight_bits; {pointer to the PDF output buffer or PDF object stream buffer}
+@!pdf_buf_size: integer; {end of PDF output buffer or PDF object stream buffer}
+@!pdf_ptr: integer; {pointer to the first unused byte in the PDF buffer or object stream buffer}
+@!pdf_op_buf: ^real_eight_bits; {the PDF output buffer}
+@!pdf_os_buf: ^real_eight_bits; {the PDF object stream buffer}
+@!pdf_os_buf_size: integer; {current size of the PDF object stream buffer, grows dynamically}
+@!pdf_os_objnum: ^integer; {array of object numbers within object stream}
+@!pdf_os_objoff: ^integer; {array of object offsets within object stream}
+@!pdf_os_objidx: pointer; {pointer into |pdf_os_objnum| and |pdf_os_objoff|}
+@!pdf_os_cntr: integer; {counter for object stream objects}
+@!pdf_op_ptr: integer; {store for PDF buffer |pdf_ptr| while inside object streams}
+@!pdf_os_ptr: integer; {store for object stream |pdf_ptr| while outside object streams}
+@!pdf_os_mode: boolean; {true if producing object stream}
+@!pdf_os_enable: boolean; {true if object streams are globally enabled}
+@!pdf_os_cur_objnum: integer; {number of current object stream object}
+@!pdf_gone: integer; {number of bytes that were flushed to output}
+@!pdf_save_offset: integer; {to save |pdf_offset|}
+@!zip_write_state: integer; {which state of compression we are in}
+@!fixed_pdf_minor_version: integer; {fixed minor part of the PDF version}
+@!fixed_pdf_objcompresslevel: integer; {fixed level for activating PDF object streams}
+@!pdf_minor_version_written: boolean; {flag if the PDF version has been written}
+@!fixed_pdfoutput: integer; {fixed output format}
+@!fixed_pdfoutput_set: boolean; {|fixed_pdfoutput| has been set?}
+@!fixed_gamma: integer;
+@!fixed_image_gamma: integer;
+@!fixed_image_hicolor: boolean;
+@!fixed_image_apply_gamma: integer;
+@!epochseconds: integer;
+@!microseconds: integer;
+@!fixed_pdf_draftmode: integer; {fixed \\pdfdraftmode}
+@!fixed_pdf_draftmode_set: boolean; {|fixed_pdf_draftmode| has been set?}
+
+
+@ @<Set init...@>=
+pdf_gone := 0;
+pdf_os_mode := false;
+pdf_ptr := 0;
+pdf_op_ptr := 0;
+pdf_os_ptr := 0;
+pdf_os_cur_objnum := 0;
+pdf_os_cntr := 0;
+pdf_buf_size := pdf_op_buf_size;
+pdf_os_buf_size := inf_pdf_os_buf_size;
+pdf_buf := pdf_op_buf;
+pdf_seek_write_length := false;
+zip_write_state := no_zip;
+pdf_minor_version_written := false;
+fixed_pdfoutput_set := false;
+fixed_pdf_draftmode_set := false;
+
+@ @p
+function fix_int(val, min, max: integer): integer;
+begin
+ if val < min then
+ fix_int := min
+ else if val > max then
+ fix_int := max
+ else
+ fix_int := val;
+end;
+
+@ This ensures that |pdfminorversion| is set only before any bytes have
+been written to the generated PDF file. Here also the PDF file is opened
+by |ensure_pdf_open| and the PDF header is written.
+
+@p procedure check_pdfminorversion;
+begin
+ if not pdf_minor_version_written then begin
+ pdf_minor_version_written := true;
+ if (pdf_minor_version < 0) or (pdf_minor_version > 9) then begin
+ print_err("pdfTeX error (illegal pdfminorversion)");
+ print_ln;
+ help2 ("The pdfminorversion must be between 0 and 9.")@/
+ ("I changed this to 4.");
+ int_error (pdf_minor_version);
+ pdf_minor_version := 4;
+ end;
+ fixed_pdf_minor_version := pdf_minor_version;
+ fixed_gamma := fix_int(pdf_gamma, 0, 1000000);
+ fixed_image_gamma := fix_int(pdf_image_gamma, 0, 1000000);
+ fixed_image_hicolor := fix_int(pdf_image_hicolor, 0, 1);
+ fixed_image_apply_gamma := fix_int(pdf_image_apply_gamma, 0, 1);
+ fixed_pdf_objcompresslevel := fix_int(pdf_objcompresslevel, 0, 3);
+ fixed_pdf_draftmode := fix_int(pdf_draftmode, 0, 1);
+ fixed_replace_font := fix_int(pdf_replace_font, 0, 1);
+ if (fixed_pdf_minor_version >= 5) and (fixed_pdf_objcompresslevel > 0) then
+ pdf_os_enable := true
+ else begin
+ if fixed_pdf_objcompresslevel > 0 then begin
+ pdf_warning("Object streams", "\pdfobjcompresslevel > 0 requires \pdfminorversion > 4. Object streams disabled now.", true, true);
+ fixed_pdf_objcompresslevel := 0;
+ end;
+ pdf_os_enable := false;
+ end;
+ ensure_pdf_open;
+ fix_pdfoutput;
+ pdf_print("%PDF-1.");
+ pdf_print_int_ln(fixed_pdf_minor_version);
+ pdf_print("%");
+ pdf_out(208); {'P' + 128}
+ pdf_out(212); {'T' + 128}
+ pdf_out(197); {'E' + 128}
+ pdf_out(216); {'X' + 128}
+ pdf_print_nl;
+ end
+ else begin
+ if fixed_pdf_minor_version <> pdf_minor_version then
+ pdf_error("setup",
+ "\pdfminorversion cannot be changed after data is written to the PDF file");
+ end;
+end;
+
+@ Checks that we have a name for the generated PDF file and that it's open.
+
+@p procedure ensure_pdf_open;
+begin
+ if output_file_name <> 0 then
+ return;
+ if job_name = 0 then
+ open_log_file;
+ pack_job_name(".pdf");
+ if fixed_pdf_draftmode = 0 then
+ while not lua_b_open_out(pdf_file) do
+ prompt_file_name("file name for output",".pdf");
+ pdf_file:=name_file_pointer;
+ output_file_name := b_make_name_string(pdf_file);
+end;
+
+@ The PDF buffer is flushed by calling |pdf_flush|, which checks the
+variable |zip_write_state| and will compress the buffer before flushing if
+neccesary. We call |pdf_begin_stream| to begin a stream and |pdf_end_stream|
+to finish it. The stream contents will be compressed if compression is turn on.
+
+@p procedure pdf_flush; {flush out the |pdf_buf|}
+begin
+ if not pdf_os_mode then begin
+ case zip_write_state of
+ no_zip: if pdf_ptr > 0 then begin
+ if fixed_pdf_draftmode = 0 then write_pdf(0, pdf_ptr - 1);
+ pdf_gone := pdf_gone + pdf_ptr;
+ pdf_last_byte := pdf_buf[pdf_ptr - 1];
+ end;
+ zip_writing:
+ if fixed_pdf_draftmode = 0 then write_zip(false);
+ zip_finish: begin
+ if fixed_pdf_draftmode = 0 then write_zip(true);
+ zip_write_state := no_zip;
+ end;
+ end;
+ pdf_ptr := 0;
+ end;
+end;
+
+procedure pdf_begin_stream; {begin a stream}
+begin
+ pdf_print_ln("/Length ");
+ pdf_seek_write_length := true; {fill in length at |pdf_end_stream| call}
+ pdf_stream_length_offset := pdf_offset - 11;
+ pdf_stream_length := 0;
+ if pdf_compress_level > 0 then begin
+ pdf_print_ln("/Filter /FlateDecode");
+ pdf_print_ln(">>");
+ pdf_print_ln("stream");
+ pdf_flush;
+ zip_write_state := zip_writing;
+ end
+ else begin
+ pdf_print_ln(">>");
+ pdf_print_ln("stream");
+ pdf_save_offset := pdf_offset;
+ end;
+end;
+
+procedure pdf_end_stream; {end a stream}
+begin
+ if zip_write_state = zip_writing then
+ zip_write_state := zip_finish
+ else
+ pdf_stream_length := pdf_offset - pdf_save_offset;
+ pdf_flush;
+ if pdf_seek_write_length then
+ write_stream_length(pdf_stream_length, pdf_stream_length_offset);
+ pdf_seek_write_length := false;
+ if pdf_last_byte <> pdf_new_line_char then
+ pdf_out(pdf_new_line_char);
+ pdf_print_ln("endstream");
+ pdf_end_obj;
+end;
+
+@ Basic printing procedures for PDF output are very similiar to \TeX\ basic
+printing ones but the output is going to PDF buffer. Subroutines with
+suffix |_ln| append a new-line character to the PDF output.
+
+@d pdf_new_line_char == 10 {new-line character for UNIX platforms}
+
+@d pdf_print_nl == {output a new-line character to PDF buffer}
+pdf_out(pdf_new_line_char)
+
+@d pdf_print_ln(#) == {print out a string to PDF buffer followed by
+a new-line character}
+begin
+ pdf_print(#);
+ pdf_print_nl;
+end
+
+@d pdf_print_int_ln(#) == {print out an integer to PDF buffer followed by
+a new-line character}
+begin
+ pdf_print_int(#);
+ pdf_print_nl;
+end
+
+@<Declare procedures that need to be declared forward for \pdfTeX@>=
+procedure pdf_error(t, p: str_number);
+begin
+ normalize_selector;
+ print_err("pdfTeX error");
+ if t <> 0 then begin
+ print(" (");
+ print(t);
+ print(")");
+ end;
+ print(": "); print(p);
+ succumb;
+end;
+
+procedure pdf_warning(t, p: str_number; prepend_nl, append_nl: boolean);
+begin
+ if interaction = error_stop_mode then
+ wake_up_terminal;
+ if prepend_nl then
+ print_ln;
+ print("pdfTeX warning");
+ if t <> 0 then begin
+ print(" (");
+ print(t);
+ print(")");
+ end;
+ print(": "); print(p);
+ if append_nl then
+ print_ln;
+ if history=spotless then history:=warning_issued;
+end;
+
+procedure pdf_os_get_os_buf(s: integer); {check that |s| bytes more
+fit into |pdf_os_buf|; increase it if required}
+var a: integer;
+begin
+ if s > sup_pdf_os_buf_size - pdf_ptr then
+ overflow("PDF object stream buffer", pdf_os_buf_size);
+ if pdf_ptr + s > pdf_os_buf_size then begin
+ a := 0.2 * pdf_os_buf_size;
+ if pdf_ptr + s > pdf_os_buf_size + a then
+ pdf_os_buf_size := pdf_ptr + s
+ else if pdf_os_buf_size < sup_pdf_os_buf_size - a then
+ pdf_os_buf_size := pdf_os_buf_size + a
+ else
+ pdf_os_buf_size := sup_pdf_os_buf_size;
+ pdf_os_buf := xreallocarray(pdf_os_buf, real_eight_bits, pdf_os_buf_size);
+ pdf_buf := pdf_os_buf;
+ pdf_buf_size := pdf_os_buf_size;
+ end;
+end;
+
+procedure remove_last_space;
+begin
+ if (pdf_ptr > 0) and (pdf_buf[pdf_ptr - 1] = 32) then
+ decr(pdf_ptr);
+end;
+
+function str_in_str(s, r: str_number; i: integer): boolean;
+ {test equality of strings}
+label not_found; {loop exit}
+var j, k: pool_pointer; {running indices}
+begin
+ str_in_str := false;
+ if length(s) < i + length(r) then
+ return;
+ j := i + str_start_macro(s);
+ k := str_start_macro(r);
+ while (j < str_start_macro(s + 1)) and (k < str_start_macro(r + 1)) do begin
+ if str_pool[j] <> str_pool[k] then
+ return;
+ incr(j);
+ incr(k);
+ end;
+ str_in_str := true;
+end;
+
+function tokens_to_string(p: pointer): str_number; {return a string from tokens
+list}
+var old_setting:integer;
+begin
+ if selector = new_string then
+ pdf_error("tokens", "tokens_to_string() called while selector = new_string");
+ old_setting:=selector; selector:=new_string;
+ show_token_list(link(p),null,pool_size-pool_ptr);
+ selector:=old_setting;
+ last_tokens_string := make_string;
+ tokens_to_string := last_tokens_string;
+end;
+
+
+@ To print |scaled| value to PDF output we need some subroutines to ensure
+accurary.
+
+@d max_integer == @"7FFFFFFF {$2^{31}-1$}
+@d call_func(#) == begin if # <> 0 then do_nothing end
+
+
+@<Glob...@>=
+@!one_hundred_inch: scaled; {scaled value corresponds to 100in}
+@!one_inch: scaled; {scaled value corresponds to 1in (rounded!)}
+@!one_hundred_bp: scaled; {scaled value corresponds to 100bp}
+@!one_bp: scaled; {scaled value corresponds to 1bp (rounded!)}
+@!ten_pow: array[0..9] of integer; {$10^0..10^9$}
+@!scaled_out: integer; {amount of |scaled| that was taken out in
+|divide_scaled|}
+@!init_pdf_output: boolean;
+
+@ @<Set init...@>=
+one_hundred_inch := 7227 * 65536; {exact, 473628672}
+one_inch := (one_hundred_inch + 50) div 100; {rounded to 4736287}
+one_hundred_bp := one_hundred_inch div 72; {exact, 6578176}
+one_bp := (one_hundred_bp + 50) div 100; {rounded to 65782}
+ten_pow[0] := 1;
+for i := 1 to 9 do
+ ten_pow[i] := 10*ten_pow[i - 1];
+init_pdf_output := false;
+
+
+@ The function |divide_scaled| divides |s| by |m| using |dd| decimal
+digits of precision. It is defined in C because it is a good candidate
+for optimizations that are not possible in pascal.
+
+@<Declare procedures that need to be declared forward for \pdfTeX@>=
+function round_xn_over_d(@!x:scaled; @!n,@!d:integer):scaled;
+var positive:boolean; {was |x>=0|?}
+@!t,@!u,@!v:nonnegative_integer; {intermediate quantities}
+begin if x>=0 then positive:=true
+else begin negate(x); positive:=false;
+ end;
+t:=(x mod @'100000)*n;
+u:=(x div @'100000)*n+(t div @'100000);
+v:=(u mod d)*@'100000 + (t mod @'100000);
+if u div d>=@'100000 then arith_error:=true
+else u:=@'100000*(u div d) + (v div d);
+v := v mod d;
+if 2*v >= d then
+ incr(u);
+if positive then
+ round_xn_over_d := u
+else
+ round_xn_over_d := -u;
+end;
+
+@ Next subroutines are needed for controling spacing in PDF page description.
+For a given character |c| from a font |f|,
+the procedure |adv_char_width| advances |pdf_h|
+by {\it about\/} the amount |w|, which is the character width.
+But we cannot simply add |w| to |pdf_h|.
+Instead we have to bring the required shift into the same raster,
+on which also the \.{/Widths} array values,
+as they appear in the PDF file, are based.
+The |scaled_out| value is the |w| value moved into this raster.
+The \.{/Widths} values are used by the PDF reader independently
+to update its positions.
+So one has to be sure, that calculations are properly synchronized.
+Currently the \.{/Widths} array values are output
+with one digit after the decimal point,
+therefore the raster on which |adv_char_width| is operating
+is $1/10000$ of the |pdf_font_size|.
+
+For PK fonts things are more complicated,
+as we have to deal with scaling bitmaps as well.
+
+@p
+procedure adv_char_width(f: internal_font_number; c: integer); {update |pdf_h|
+by character width |w| from font |f|}
+var w, s_out: scaled;
+ s: integer;
+begin
+ w := char_width(f,c);
+ if hasfmentry(f) then begin
+ if pdf_cur_Tm_a = 0 then begin
+ call_func(divide_scaled_n(w, pdf_font_size(f),10000.0));
+ pdf_delta_h := pdf_delta_h + scaled_out;
+ end
+ else begin
+ s := divide_scaled_n(round_xn_over_d(w, 1000, 1000 + pdf_cur_Tm_a),
+ pdf_font_size(f),10000.0);
+ s_out := round_xn_over_d(round_xn_over_d(pdf_font_size(f), abs(s), 10000),
+ 1000 + pdf_cur_Tm_a, 1000);
+ if s < 0 then
+ s_out := -s_out;
+ pdf_delta_h := pdf_delta_h + s_out;
+ end;
+ end else
+ pdf_delta_h := pdf_delta_h + get_pk_char_width(f, w);
+end;
+
+procedure pdf_print_bp(s: scaled); {print scaled as |bp|}
+begin
+ pdf_print_real(divide_scaled(s, one_hundred_bp, fixed_decimal_digits + 2),
+ fixed_decimal_digits);
+end;
+
+procedure pdf_print_mag_bp(s: scaled); {take |mag| into account}
+begin
+ prepare_mag;
+ if mag <> 1000 then
+ s := round_xn_over_d(s, mag, 1000);
+ pdf_print_bp(s);
+end;
+
+@* \[32c] PDF page description.
+
+@d pdf_h_offset == (h_offset + pdf_h_origin)
+@d pdf_v_offset == (v_offset + pdf_v_origin)
+@d pdf_x(#) == ((#) - pdf_h_offset + one_inch) {convert $x$-coordinate from \.{DVI} to PDF}
+@d pdf_y(#) == (cur_page_height - (#) - pdf_v_offset + one_inch) {convert $y$-coordinate from \.{DVI} to PDF}
+
+@<Glob...@>=
+@!pdf_f: internal_font_number; {the current font in PDF output page}
+@!pdf_h: scaled; {current horizontal coordinate in PDF output page}
+@!pdf_v: scaled; {current vertical coordinate in PDF output page}
+@!pdf_tj_start_h: scaled; {horizontal coordinate in PDF output page just before \.{TJ} array start}
+@!cur_delta_h: scaled; {horizontal |cur_h| offset from |pdf_tj_start_h|}
+@!pdf_delta_h: scaled; {horizontal offset from |pdf_tj_start_h|}
+@!pdf_origin_h: scaled; {current horizontal origin in PDF output page}
+@!pdf_origin_v: scaled; {current vertical origin in PDF output page}
+@!pdf_doing_string: boolean; {we are writing string to PDF file?}
+@!pdf_doing_text: boolean; {we are writing text section to PDF file?}
+@!min_bp_val: scaled;
+@!min_font_val: scaled; {(TJ array system)}
+@!fixed_pk_resolution: integer;
+@!fixed_decimal_digits: integer;
+@!fixed_gen_tounicode: integer;
+@!fixed_replace_font: integer;
+@!pk_scale_factor: integer;
+@!pdf_output_option: integer;
+@!pdf_output_value: integer;
+@!pdf_draftmode_option: integer;
+@!pdf_draftmode_value: integer;
+@!pdf_cur_Tm_a: integer; {|a| value of the current text matrix, ie the current
+ horizontal scaling factor}
+@!pdf_last_f: internal_font_number; {last font in PDF output page}
+@!pdf_last_fs: internal_font_number; {last font size in PDF output page}
+
+
+@ Following procedures implement low-level subroutines to convert \TeX{}
+internal structures to PDF page description.
+
+@p procedure pdf_set_origin(h, v: scaled); {set the origin to |h|, |v|}
+begin
+ if (abs(h - pdf_origin_h) >= min_bp_val) or
+ (abs(v - pdf_origin_v) >= min_bp_val) then begin
+ pdf_print("1 0 0 1 ");
+ pdf_print_bp(h - pdf_origin_h);
+ pdf_origin_h := pdf_origin_h + scaled_out;
+ pdf_out(" ");
+ pdf_print_bp(pdf_origin_v - v);
+ pdf_origin_v := pdf_origin_v - scaled_out;
+ pdf_print_ln(" cm");
+ end;
+ pdf_h := pdf_origin_h;
+ pdf_tj_start_h := pdf_h;
+ pdf_v := pdf_origin_v;
+end;
+
+procedure pdf_set_origin_temp(h, v: scaled); {set the origin to |h|, |v| inside group}
+begin
+ if (abs(h - pdf_origin_h) >= min_bp_val) or
+ (abs(v - pdf_origin_v) >= min_bp_val) then begin
+ pdf_print("1 0 0 1 ");
+ pdf_print_bp(h - pdf_origin_h);
+ pdf_out(" ");
+ pdf_print_bp(pdf_origin_v - v);
+ pdf_print_ln(" cm");
+ end;
+end;
+
+procedure pdf_end_string; {end the current string}
+begin
+ if pdf_doing_string then begin
+ pdf_print(")]TJ");
+ pdf_doing_string := false;
+ end;
+end;
+
+procedure pdf_end_string_nl; {end the current string, with new-line}
+begin
+ if pdf_doing_string then begin
+ pdf_print_ln(")]TJ");
+ pdf_doing_string := false;
+ end;
+end;
+
+procedure pdf_set_textmatrix(v, v_out: scaled; f: internal_font_number);
+{set the next starting point to |cur_h|, |cur_v|}
+var pdf_new_Tm_a: integer; {|a| value of the new text matrix}
+begin
+ pdf_out(" ");
+ if f = pdf_f then
+ pdf_new_Tm_a := pdf_cur_Tm_a
+ else if not pdf_font_auto_expand(f) then
+ pdf_new_Tm_a := 0
+ else
+ pdf_new_Tm_a := pdf_font_expand_ratio(f);
+ if (pdf_new_Tm_a <> 0) or
+ ((pdf_new_Tm_a = 0) and (pdf_cur_Tm_a <> 0)) then begin
+ pdf_print_real(1000 + pdf_new_Tm_a, 3);
+ pdf_print(" 0 0 1 ");
+ pdf_print_bp(cur_h - pdf_origin_h);
+ pdf_h := pdf_origin_h + scaled_out;
+ pdf_out(" ");
+ pdf_print_bp(pdf_origin_v - cur_v);
+ pdf_v := pdf_origin_v - scaled_out;
+ pdf_print(" Tm");
+ pdf_cur_Tm_a := pdf_new_Tm_a;
+ pdfassert(pdf_cur_Tm_a > -1000);
+ end else begin
+ pdf_print_bp(cur_h - pdf_tj_start_h); {works only for unexpanded fonts}
+ pdf_h := pdf_tj_start_h + scaled_out;
+ pdf_out(" ");
+ pdf_print_real(v, fixed_decimal_digits); {use |v| and |v_out| to avoid duplicate calculation}
+ pdf_v := pdf_v - v_out;
+ pdf_print(" Td");
+ end;
+ pdf_tj_start_h := pdf_h;
+ pdf_delta_h := 0;
+end;
+
+procedure pdf_use_font(f: internal_font_number; fontnum: integer);
+{mark |f| as a used font; set |font_used(f)|, |pdf_font_size(f)| and |pdf_font_num(f)|}
+begin
+ call_func(divide_scaled(font_size(f), one_hundred_bp, 6));
+ set_pdf_font_size(f,scaled_out);
+ set_font_used(f,true);
+ pdfassert((fontnum > 0) or ((fontnum < 0) and (pdf_font_num(-fontnum) > 0)));
+ set_pdf_font_num(f,fontnum);
+ if pdf_move_chars > 0 then begin
+ pdf_warning(0,"Primitive \pdfmovechars is obsolete.",true, true);
+ pdf_move_chars := 0; {warn only once}
+ end;
+end;
+
+@ To set PDF font we need to find out fonts with the same name, because \TeX\
+can load the same font several times for various sizes. For such fonts we
+define only one font resource. The array |pdf_font_num| holds the object
+number of font resource. A negative value of an entry of |pdf_font_num|
+indicates that the corresponding font shares the font resource with the font
+
+@d pdf_print_resname_prefix ==
+if pdf_resname_prefix <> 0 then
+ pdf_print(pdf_resname_prefix)
+
+@p procedure pdf_init_font(f: internal_font_number);
+{create a font object}
+var k, b: internal_font_number;
+ i: integer;
+begin
+ pdfassert(not font_used(f));
+
+ {if |f| is auto expanded then ensure the base font is initialized}
+ if pdf_font_auto_expand(f) and (pdf_font_blink(f) <> null_font) then begin
+ b := pdf_font_blink(f);
+ {TODO: reinstate this check. disabled because wide fonts font have fmentries}
+ if false and (not hasfmentry(b)) then
+ pdf_error("font expansion", "auto expansion is only possible with scalable fonts");
+ if not font_used(b) then
+ pdf_init_font(b);
+ set_font_map(f,font_map(b));
+ end;
+
+ {check whether |f| can share the font object with some |k|: we have 2 cases
+ here: 1) |f| and |k| have the same tfm name (so they have been loaded at
+ different sizes, eg 'cmr10' and 'cmr10 at 11pt'); 2) |f| has been auto
+ expanded from |k|}
+ if hasfmentry(f) or true then begin
+ i := head_tab[obj_type_font];
+ while i <> 0 do begin
+ k := obj_info(i);
+ if font_shareable(f,k) then
+ begin
+ pdfassert(pdf_font_num(k) <> 0);
+ if pdf_font_num(k) < 0 then
+ pdf_use_font(f, pdf_font_num(k))
+ else
+ pdf_use_font(f, -k);
+ return;
+ end;
+ i := obj_link(i);
+ end;
+ end;
+
+ {create a new font object for |f|}
+ pdf_create_obj(obj_type_font, f);
+ pdf_use_font(f, obj_ptr);
+end;
+
+procedure pdf_init_font_cur_val;
+begin
+ pdf_init_font(cur_val);
+end;
+
+procedure pdf_set_font(f: internal_font_number);
+{set the actual font on PDF page}
+label found, found1;
+var p: pointer;
+ k: internal_font_number;
+begin
+ if not font_used(f) then
+ pdf_init_font(f);
+ set_ff(f); {set |ff| to the tfm number of the font sharing the font object
+ with |f|; |ff| is either |f| or some font with the same tfm name
+ at different size and/or expansion}
+ k := ff;
+ p := pdf_font_list;
+ while p <> null do begin
+ set_ff(info(p));
+ if ff = k then
+ goto found;
+ p := link(p);
+ end;
+ pdf_append_list(f)(pdf_font_list); {|f| not found in |pdf_font_list|, append it now}
+found:
+ if (k = pdf_last_f) and (font_size(f) = pdf_last_fs) then
+ return;
+ pdf_print("/F");
+ pdf_print_int(k);
+ pdf_print_resname_prefix;
+ pdf_out(" ");
+ pdf_print_real(divide_scaled(font_size(f), one_hundred_bp, 6), 4);
+ pdf_print(" Tf");
+ pdf_last_f := k;
+ pdf_last_fs := font_size(f);
+end;
+
+procedure pdf_begin_text; {begin a text section}
+begin
+ pdf_set_origin(0, cur_page_height);
+ pdf_print_ln("BT");
+ pdf_doing_text := true;
+ pdf_f := null_font;
+ pdf_last_f := null_font;
+ pdf_last_fs := 0;
+ pdf_doing_string := false;
+ pdf_cur_Tm_a := 0;
+end;
+
+@ @p
+procedure pdf_begin_string(f: internal_font_number); {begin to draw a string}
+var s_out, v, v_out: scaled;
+ s: integer;
+begin s_out:=0;
+ if not pdf_doing_text then
+ pdf_begin_text;
+ if f <> pdf_f then begin
+ pdf_end_string;
+ pdf_set_font(f);
+ end;
+ if pdf_cur_Tm_a = 0 then begin
+ s := divide_scaled_n(cur_h - (pdf_tj_start_h + pdf_delta_h), pdf_font_size(f),1000.0);
+ s_out := scaled_out;
+ end
+ else begin
+ s := divide_scaled_n(round_xn_over_d(cur_h - (pdf_tj_start_h + pdf_delta_h), 1000,
+ 1000 + pdf_cur_Tm_a),
+ pdf_font_size(f),
+ 1000.0);
+ if abs(s) < @'100000 then begin
+ s_out := round_xn_over_d(round_xn_over_d(pdf_font_size(f), abs(s), 1000),
+ 1000 + pdf_cur_Tm_a, 1000);
+ if s < 0 then
+ s_out := -s_out;
+ end;
+ {no need to calculate |s_out| when |abs(s) >= @'100000|, since the text
+ matrix will be reset below}
+ end;
+ if abs(cur_v - pdf_v) >= min_bp_val then begin
+ v := divide_scaled(pdf_v - cur_v, one_hundred_bp,
+ fixed_decimal_digits + 2);
+ v_out := scaled_out;
+ end
+ else begin
+ v := 0;
+ v_out := 0;
+ end;
+ if (f <> pdf_f) or (v <> 0) or (abs(s) >= @'100000) then begin
+ pdf_end_string;
+ pdf_set_textmatrix(v, v_out, f);
+ pdf_f := f;
+ s := 0;
+ end;
+ if not pdf_doing_string then begin
+ pdf_print(" [");
+ if s = 0 then
+ pdf_out("(");
+ end;
+ if s <> 0 then begin
+ if pdf_doing_string then
+ pdf_out(")");
+ pdf_print_int(-s);
+ pdf_out("(");
+ pdf_delta_h := pdf_delta_h + s_out;
+ end;
+ pdf_doing_string := true;
+end;
+
+procedure pdf_end_text; {end a text section}
+begin
+ if pdf_doing_text then begin
+ pdf_end_string_nl;
+ pdf_print_ln("ET");
+ pdf_doing_text := false;
+ end;
+end;
+
+procedure pdf_set_rule(x, y, w, h: scaled); {draw a rule}
+begin
+ pdf_end_text;
+ pdf_print_ln("q");
+ if h <= one_bp then begin
+ pdf_set_origin_temp(x, y - (h + 1)/2);
+ pdf_print("[]0 d 0 J ");
+ pdf_print_bp(h); pdf_print(" w 0 0 m ");
+ pdf_print_bp(w); pdf_print_ln(" 0 l S");
+ end
+ else if w <= one_bp then begin
+ pdf_set_origin_temp(x + (w + 1)/2, cur_v);
+ pdf_print("[]0 d 0 J ");
+ pdf_print_bp(w); pdf_print(" w 0 0 m 0 ");
+ pdf_print_bp(h); pdf_print_ln(" l S");
+ end
+ else begin
+ pdf_set_origin_temp(x, y);
+ pdf_print("0 0 ");
+ pdf_print_bp(w); pdf_out(" ");
+ pdf_print_bp(h); pdf_print_ln(" re f");
+ end;
+ pdf_print_ln("Q");
+end;
+
+procedure pdf_rectangle(left, top, right, bottom: scaled); {output a
+rectangle specification to PDF file}
+begin
+ prepare_mag;
+ pdf_print("/Rect [");
+ pdf_print_mag_bp(pdf_x(left)); pdf_out(" ");
+ pdf_print_mag_bp(pdf_y(bottom)); pdf_out(" ");
+ pdf_print_mag_bp(pdf_x(right)); pdf_out(" ");
+ pdf_print_mag_bp(pdf_y(top));
+ pdf_print_ln("]");
+end;
+
+procedure literal(s: str_number; literal_mode: integer; warn: boolean);
+var j: pool_pointer; {current character code position}
+begin
+ j:=str_start_macro(s);
+ if literal_mode = scan_special then begin
+ if not (str_in_str(s, "PDF:", 0) or str_in_str(s, "pdf:", 0)) then begin
+ if warn and not (str_in_str(s, "SRC:", 0)
+ or str_in_str(s, "src:", 0)
+ or (length(s) = 0)) then
+ print_nl("Non-PDF special ignored!");
+ return;
+ end;
+ j := j + length("PDF:");
+ if str_in_str(s, "direct:", length("PDF:")) then begin
+ j := j + length("direct:");
+ literal_mode := direct_always; end
+ else if str_in_str(s, "page:", length("PDF:")) then begin
+ j := j + length("page:");
+ literal_mode := direct_page; end
+ else
+ literal_mode := set_origin;
+ end;
+ case literal_mode of
+ set_origin: begin
+ pdf_end_text;
+ pdf_set_origin(cur_h, cur_v);
+ end;
+ direct_page:
+ pdf_end_text;
+ direct_always:
+ pdf_end_string_nl;
+ othercases confusion("literal1")
+ endcases;
+ while j<str_start_macro(s+1) do begin
+ pdf_out(str_pool[j]);
+ incr(j);
+ end;
+ pdf_print_nl;
+end;
+
+procedure latelua(lua_id: quarterword; s: str_number);
+var b, j: pool_pointer; {current character code position}
+begin
+ j:=str_start_macro(s);
+ b := pool_ptr;
+ luacall(lua_id,(s-string_offset));
+ while b<pool_ptr do begin
+ pdf_out(str_pool[b]);
+ incr(b);
+ end;
+ pdf_print_nl;
+end;
+
+@* \[32d] The cross-reference table.
+
+The cross-reference table |obj_tab| is an array of |obj_tab_size| of
+|tab_entry|. Each entry contains five integer fields and represents an object
+in PDF file whose object number is the index of this entry in |obj_tab|.
+Objects in |obj_tab| maybe linked into list; objects in such a linked list have
+the same type.
+
+@<Types...@>=
+@!obj_entry = record@;@/
+ int0, int1, int2, int3, int4: integer;
+end;
+
+@ The first field contains information representing identifier of this object.
+It is usally a number for most of object types, but it may be a string number
+for named destination or named thread.
+
+The second field of |obj_entry| contains link to the next
+object in |obj_tab| if this object is linked in a list.
+
+The third field holds the byte offset of the object in the output PDF file,
+or its byte offset within an object stream.
+Objects that have been not written yet have this field set to zero. However
+sometimes we have to use this field to store some info before the object is
+written out.
+
+The fourth field holds the object number of the object stream, into which
+the object is included.
+
+The last field usually represents the pointer to some auxiliary data
+structure depending on the object type; however it may be used as a counter as
+well.
+
+@d obj_info(#) == obj_tab[#].int0 {information representing identifier of this object}
+@d obj_link(#) == obj_tab[#].int1 {link to the next entry in linked list}
+@d obj_offset(#) == obj_tab[#].int2 {byte offset for this object in PDF output file, or object stream number for this object}
+@d obj_os_idx(#) == obj_tab[#].int3 {index of this object in object stream}
+@d obj_aux(#) == obj_tab[#].int4 {auxiliary pointer}
+@d is_obj_written(#) == (obj_offset(#) <> 0)
+
+@# {types of objects}
+@d obj_type_others == 0 {objects which are not linked in any list}
+@d obj_type_page == 1 {index of linked list of Page objects}
+@d obj_type_pages == 2 {index of linked list of Pages objects}
+@d obj_type_font == 3 {index of linked list of Fonts objects}
+@d obj_type_outline == 4 {index of linked list of outline objects}
+@d obj_type_dest == 5 {index of linked list of destination objects}
+@d obj_type_obj == 6 {index of linked list of raw objects}
+@d obj_type_xform == 7 {index of linked list of XObject forms}
+@d obj_type_ximage == 8 {index of linked list of XObject image}
+@d obj_type_thread == 9 {index of linked list of num article threads}
+@d head_tab_max == obj_type_thread {max index of |head_tab|}
+
+@# {max number of kids for balanced trees}
+@d pages_tree_kids_max == 6 {max number of kids of Pages tree node}
+@d name_tree_kids_max == 6 {max number of kids of node of name tree for
+name destinations}
+
+@# {when a whatsit node representing annotation is created, words |1..3| are
+width, height and depth of this annotation; after shipping out words |1..4|
+are rectangle specification of annotation. For whatsit node representing
+destination |pdf_left| and |pdf_top| are used for some types of destinations}
+
+@# {coordinates of destinations/threads/annotations (in whatsit node)}
+@d pdf_left(#) == vmem(# + 2).sc
+@d pdf_top(#) == vmem(# + 3).sc
+@d pdf_right(#) == vmem(# + 4).sc
+@d pdf_bottom(#) == vmem(# + 5).sc
+
+@# {dimension of destinations/threads/annotations (in whatsit node)}
+@d pdf_width(#) == vmem(# + 2).sc
+@d pdf_height(#) == vmem(# + 3).sc
+@d pdf_depth(#) == vmem(# + 4).sc
+
+@# {data structure for \.{\\pdfliteral}}
+@d pdf_literal_data(#) == vlink(#+2) {data}
+@d pdf_literal_mode(#) == vinfo(#+2) {mode of resetting the text matrix
+ while writing data to the page stream}
+@# {modes of setting the current transformation matrix (CTM)}
+@d set_origin == 0 {end text (ET) if needed, set CTM to current point}
+@d direct_page == 1 {end text (ET) if needed, but don't change the CTM}
+@d direct_always == 2 {don't end text, don't change the CTM}
+@d scan_special == 3 {look into special text}
+
+@# {data structure for \.{\\pdfcolorstack}}
+@d pdf_colorstack_node_size == 4
+@d pdf_colorstack_stack(#) == vlink(#+2) {stack number}
+@d pdf_colorstack_cmd(#) == vinfo(#+2) {command: set, push, pop, current}
+@d pdf_colorstack_data(#) == vlink(#+3) {data}
+
+@# {color stack commands}
+@d colorstack_set == 0
+@d colorstack_push == 1
+@d colorstack_data == 1 { last value where data field is set }
+@d colorstack_pop == 2
+@d colorstack_current == 3
+
+@# {data structure for \.{\\pdfsetmatrix}}
+@d pdf_setmatrix_node_size == 3
+@d pdf_setmatrix_data(#) == vlink(#+2) {data}
+
+@# {data structure for \.{\\pdsave}}
+@d pdf_save_node_size == 3
+
+@# {data structure for \.{\\pdfrestore}}
+@d pdf_restore_node_size == 3
+
+
+@# {data structure for \.{\\latelua}}
+@d late_lua_data(#) == vlink(#+2) {data}
+@d late_lua_reg(#) == vinfo(#+2) {register id}
+
+@# {data structure for \.{\\pdfobj} and \.{\\pdfrefobj}}
+@d pdf_refobj_node_size == 3 {size of whatsit node representing the raw object}
+@d pdf_obj_objnum(#) == vinfo(# + 2) {number of the raw object}
+@d obj_data_ptr == obj_aux {pointer to |pdf_mem|}
+@d pdfmem_obj_size == 4 {size of memory in |pdf_mem| which |obj_data_ptr| holds}
+@d obj_obj_data(#) == pdf_mem[obj_data_ptr(#) + 0] {object data}
+@d obj_obj_is_stream(#) == pdf_mem[obj_data_ptr(#) + 1] {will this object
+ be written as a stream instead of a dictionary?}
+@d obj_obj_stream_attr(#) == pdf_mem[obj_data_ptr(#) + 2] {additional
+ object attributes for streams}
+@d obj_obj_is_file(#) == pdf_mem[obj_data_ptr(#) + 3] {data should be
+ read from an external file?}
+
+@# {data structure for \.{\\pdfxform} and \.{\\pdfrefxform}}
+@d pdf_refxform_node_size == 6 {size of whatsit node for xform; words 1..3 are
+ form dimensions}
+@d pdf_xform_objnum(#) == vinfo(# + 4) {object number}
+@d pdfmem_xform_size == 6 {size of memory in |pdf_mem| which
+ |obj_data_ptr| holds}
+@d obj_xform_width(#) == pdf_mem[obj_data_ptr(#) + 0]
+@d obj_xform_height(#) == pdf_mem[obj_data_ptr(#) + 1]
+@d obj_xform_depth(#) == pdf_mem[obj_data_ptr(#) + 2]
+@d obj_xform_box(#) == pdf_mem[obj_data_ptr(#) + 3] {this field holds
+ pointer to the corresponding box}
+@d obj_xform_attr(#) == pdf_mem[obj_data_ptr(#) + 4] {additional xform
+ attributes}
+@d obj_xform_resources(#) == pdf_mem[obj_data_ptr(#) + 5] {additional xform
+ Resources}
+
+@# {data structure for \.{\\pdfximage} and \.{\\pdfrefximage}}
+@d pdf_refximage_node_size == 6 {size of whatsit node for ximage; words 2..4
+ are image dimensions}
+@d pdf_ximage_ref(#) == vinfo(# + 5) {image reference number}
+
+@# {data structure of annotations; words 1..4 represent the coordinates of
+ the annotation}
+@d obj_annot_ptr == obj_aux {pointer to corresponding whatsit node}
+@d pdf_annot_node_size == 8 {size of whatsit node representing annotation}
+@d pdf_annot_data(#) == vinfo(# + 6) {raw data of general annotations}
+@d pdf_link_attr(#) == vinfo(# + 6) {attributes of link annotations}
+@d pdf_link_action(#) == vlink(# + 6) {pointer to action structure}
+@d pdf_annot_objnum(#) == vmem(# + 7).int {object number of corresponding object}
+@d pdf_link_objnum(#) == vmem(# + 7).int {object number of corresponding object}
+
+@# {types of actions}
+@d pdf_action_page == 0 {GoTo action}
+@d pdf_action_goto == 1 {GoTo action}
+@d pdf_action_thread == 2 {Thread action}
+@d pdf_action_user == 3 {user-defined action}
+
+@# {data structure of actions}
+@d pdf_action_size == 4 {size of action structure in |mem|}
+@d action_node == 45
+@d pdf_action_type(#) == type(#+1) {action type}
+@d pdf_action_named_id(#) == subtype(#+1) {identifier is type of name}
+@d pdf_action_id(#) == vlink(#+1) {destination/thread name identifier}
+@d pdf_action_file(#) == vinfo(# + 2) {file name for external action}
+@d pdf_action_new_window(#) == vlink(# + 2) {open a new window?}
+@d pdf_action_tokens(#) == vinfo(# + 3) {specification of GoTo page or user action}
+@d pdf_action_refcount(#) == vlink(# + 3) {counter of references to this action}
+
+@# {data structure of outlines; it's not able to write out outline entries
+before all outline entries are defined, so memory allocated for outline
+entries can't not be deallocated and will stay in memory. For this reason we
+will store data of outline entries in |pdf_mem| instead of |mem|}
+
+@d pdfmem_outline_size == 8 {size of memory in |pdf_mem| which
+|obj_outline_ptr| points to}
+@d obj_outline_count == obj_info{count of all opened children}
+@d obj_outline_ptr == obj_aux {pointer to |pdf_mem|}
+@d obj_outline_title(#) == pdf_mem[obj_outline_ptr(#)]
+@d obj_outline_parent(#) == pdf_mem[obj_outline_ptr(#) + 1]
+@d obj_outline_prev(#) == pdf_mem[obj_outline_ptr(#) + 2]
+@d obj_outline_next(#) == pdf_mem[obj_outline_ptr(#) + 3]
+@d obj_outline_first(#) == pdf_mem[obj_outline_ptr(#) + 4]
+@d obj_outline_last(#) == pdf_mem[obj_outline_ptr(#) + 5]
+@d obj_outline_action_objnum(#) == pdf_mem[obj_outline_ptr(#) + 6] {object number of
+action}
+@d obj_outline_attr(#) == pdf_mem[obj_outline_ptr(#) + 7]
+
+@# {types of destinations}
+@d pdf_dest_xyz == 0
+@d pdf_dest_fit == 1
+@d pdf_dest_fith == 2
+@d pdf_dest_fitv == 3
+@d pdf_dest_fitb == 4
+@d pdf_dest_fitbh == 5
+@d pdf_dest_fitbv == 6
+@d pdf_dest_fitr == 7
+
+@# {data structure of destinations}
+@d obj_dest_ptr == obj_aux {pointer to |pdf_dest_node|}
+@d pdf_dest_node_size == 8 {size of whatsit node for destination;
+words |1..4| hold dest dimensions, word |6| identifier type, subtype
+and identifier of destination, word |6| the corresponding object number}
+@d pdf_dest_type(#) == type(# + 6) {type of destination}
+@d pdf_dest_named_id(#) == subtype(# + 6) {is named identifier?}
+@d pdf_dest_id(#) == vlink(# + 6) {destination identifier}
+@d pdf_dest_xyz_zoom(#) == vinfo(# + 7) {zoom factor for |destxyz| destination}
+@d pdf_dest_objnum(#) == vlink(# + 7) {object number of corresponding
+object}
+
+@# {data structure of threads; words 1..4 represent the coordinates of the
+ corners}
+@d pdf_thread_node_size == 8
+@d pdf_thread_named_id(#) == subtype(# + 6) {is a named identifier}
+@d pdf_thread_id(#) == vlink(# + 6) {thread identifier}
+@d pdf_thread_attr(#) == vinfo(# + 7) {attributes of thread}
+@d obj_thread_first == obj_aux {pointer to the first bead}
+
+@# {data structure of beads}
+@d pdfmem_bead_size == 5 {size of memory in |pdf_mem| which
+ |obj_bead_ptr| points to}
+@d obj_bead_ptr == obj_aux {pointer to |pdf_mem|}
+@d obj_bead_rect(#) == pdf_mem[obj_bead_ptr(#)]
+@d obj_bead_page(#) == pdf_mem[obj_bead_ptr(#) + 1]
+@d obj_bead_next(#) == pdf_mem[obj_bead_ptr(#) + 2]
+@d obj_bead_prev(#) == pdf_mem[obj_bead_ptr(#) + 3]
+@d obj_bead_attr(#) == pdf_mem[obj_bead_ptr(#) + 4]
+@d obj_bead_data == obj_bead_rect {pointer to the corresponding
+whatsit node; |obj_bead_rect| is needed only when the bead rectangle has
+been written out and after that |obj_bead_data| is not needed any more
+so we can use this field for both}
+
+@<Constants...@>=
+@!inf_obj_tab_size = 1000; {min size of the cross-reference table for PDF output}
+@!sup_obj_tab_size = 8388607; {max size of the cross-reference table for PDF output}
+@!inf_dest_names_size = 1000; {min size of the destination names table for PDF output}
+@!sup_dest_names_size = 131072; {max size of the destination names table for PDF output}
+@!inf_pk_dpi = 72; {min PK pixel density value from \.{texmf.cnf}}
+@!sup_pk_dpi = 8000; {max PK pixel density value from \.{texmf.cnf}}
+@!pdf_objtype_max = head_tab_max;
+
+@ @<Glob...@>=
+@!obj_tab_size:integer;
+@!obj_tab:^obj_entry;
+@!head_tab: array[1..head_tab_max] of integer;
+@!pages_tail: integer;
+@!obj_ptr: integer; {user objects counter}
+@!sys_obj_ptr: integer; {system objects counter, including object streams}
+@!pdf_last_pages: integer; {pointer to most recently generated pages object}
+@!pdf_last_page: integer; {pointer to most recently generated page object}
+@!pdf_last_stream: integer; {pointer to most recently generated stream}
+@!pdf_stream_length: integer; {length of most recently generated stream}
+@!pdf_stream_length_offset: integer; {file offset of the last stream length}
+@!pdf_seek_write_length: boolean; {flag whether to seek back and write \.{/Length}}
+@!pdf_last_byte: integer; {byte most recently written to PDF file; for \.{endstream} in new line}
+@!pdf_append_list_arg: integer; {for use with |pdf_append_list|}
+@!ff: integer; {for use with |set_ff|}
+@!pdf_box_spec_media: integer;
+@!pdf_box_spec_crop: integer;
+@!pdf_box_spec_bleed: integer;
+@!pdf_box_spec_trim: integer;
+@!pdf_box_spec_art: integer;
+
+@ @<Set init...@>=
+obj_ptr := 0;
+sys_obj_ptr := 0;
+obj_tab_size := inf_obj_tab_size; {allocated size of |obj_tab| array}
+dest_names_size := inf_dest_names_size; {allocated size of |dest_names| array}
+for k := 1 to head_tab_max do
+ head_tab[k] := 0;
+pdf_box_spec_media := 1;
+pdf_box_spec_crop := 2;
+pdf_box_spec_bleed := 3;
+pdf_box_spec_trim := 4;
+pdf_box_spec_art := 5;
+
+@ Here we implement subroutines for work with objects and related things.
+Some of them are used in former parts too, so we need to declare them
+forward.
+
+@d pdf_append_list_end(#) == # := append_ptr(#, pdf_append_list_arg); end
+@d pdf_append_list(#) == begin pdf_append_list_arg := #; pdf_append_list_end
+@d set_ff(#) == begin
+ if pdf_font_num(#) < 0 then
+ ff := -pdf_font_num(#)
+ else
+ ff := #;
+end
+
+@<Declare procedures that need to be declared forward for \pdfTeX@>=
+procedure append_dest_name(s: str_number; n: integer);
+var a: integer;
+begin
+ if pdf_dest_names_ptr = sup_dest_names_size then
+ overflow("number of destination names (dest_names_size)", dest_names_size);
+ if pdf_dest_names_ptr = dest_names_size then begin
+ a := 0.2 * dest_names_size;
+ if dest_names_size < sup_dest_names_size - a then
+ dest_names_size := dest_names_size + a
+ else
+ dest_names_size := sup_dest_names_size;
+ dest_names := xreallocarray(dest_names, dest_name_entry, dest_names_size);
+ end;
+ dest_names[pdf_dest_names_ptr].objname := s;
+ dest_names[pdf_dest_names_ptr].objnum := n;
+ incr(pdf_dest_names_ptr);
+end;
+
+procedure pdf_create_obj(t, i: integer); {create an object with type |t| and
+identifier |i|}
+label done;
+var a, p, q: integer;
+begin
+ if sys_obj_ptr = sup_obj_tab_size then
+ overflow("indirect objects table size", obj_tab_size);
+ if sys_obj_ptr = obj_tab_size then begin
+ a := 0.2 * obj_tab_size;
+ if obj_tab_size < sup_obj_tab_size - a then
+ obj_tab_size := obj_tab_size + a
+ else
+ obj_tab_size := sup_obj_tab_size;
+ obj_tab := xreallocarray(obj_tab, obj_entry, obj_tab_size);
+ end;
+ incr(sys_obj_ptr);
+ obj_ptr := sys_obj_ptr;
+ obj_info(obj_ptr) := i;
+ obj_offset(obj_ptr) := 0;
+ obj_aux(obj_ptr) := 0;
+ avl_put_obj(obj_ptr, t);
+ if t = obj_type_page then begin
+ p := head_tab[t];
+ {find the right position to insert newly created object}@/
+ if (p = 0) or (obj_info(p) < i) then begin
+ obj_link(obj_ptr) := p;
+ head_tab[t] := obj_ptr;
+ end
+ else begin
+ while p <> 0 do begin
+ if obj_info(p) < i then
+ goto done;
+ q := p;
+ p := obj_link(p);
+ end;
+done:
+ obj_link(q) := obj_ptr;
+ obj_link(obj_ptr) := p;
+ end;
+ end
+ else if t <> obj_type_others then begin
+ obj_link(obj_ptr) := head_tab[t];
+ head_tab[t] := obj_ptr;
+ if (t = obj_type_dest) and (i < 0) then
+ append_dest_name(-obj_info(obj_ptr), obj_ptr);
+ end;
+end;
+
+function pdf_new_objnum: integer; {create a new object and return its number}
+begin
+ pdf_create_obj(obj_type_others, 0);
+ pdf_new_objnum := obj_ptr;
+end;
+
+procedure pdf_os_switch(pdf_os: boolean); {switch between PDF stream and object stream mode}
+begin
+ if pdf_os and pdf_os_enable then begin
+ if not pdf_os_mode then begin {back up PDF stream variables}
+ pdf_op_ptr := pdf_ptr;
+ pdf_ptr := pdf_os_ptr;
+ pdf_buf := pdf_os_buf;
+ pdf_buf_size := pdf_os_buf_size;
+ pdf_os_mode := true; {switch to object stream}
+ end;
+ end else begin
+ if pdf_os_mode then begin {back up object stream variables}
+ pdf_os_ptr := pdf_ptr;
+ pdf_ptr := pdf_op_ptr;
+ pdf_buf := pdf_op_buf;
+ pdf_buf_size := pdf_op_buf_size;
+ pdf_os_mode := false; {switch to PDF stream}
+ end;
+ end;
+end;
+
+procedure pdf_os_prepare_obj(i: integer; pdf_os_level: integer); {create new \.{/ObjStm} object
+if required, and set up cross reference info}
+begin
+ pdf_os_switch((pdf_os_level > 0) and (fixed_pdf_objcompresslevel >= pdf_os_level));
+ if pdf_os_mode then begin
+ if pdf_os_cur_objnum = 0 then begin
+ pdf_os_cur_objnum := pdf_new_objnum;
+ decr(obj_ptr); {object stream is not accessible to user}
+ incr(pdf_os_cntr); {only for statistics}
+ pdf_os_objidx := 0;
+ pdf_ptr := 0; {start fresh object stream}
+ end else
+ incr(pdf_os_objidx);
+ obj_os_idx(i) := pdf_os_objidx;
+ obj_offset(i) := pdf_os_cur_objnum;
+ pdf_os_objnum[pdf_os_objidx] := i;
+ pdf_os_objoff[pdf_os_objidx] := pdf_ptr;
+ end else begin
+ obj_offset(i) := pdf_offset;
+ obj_os_idx(i) := -1; {mark it as not included in object stream}
+ end;
+end;
+
+procedure pdf_begin_obj(i: integer; pdf_os_level: integer); {begin a PDF object}
+begin
+ check_pdfminorversion;
+ pdf_os_prepare_obj(i, pdf_os_level);
+ if not pdf_os_mode then begin
+ pdf_print_int(i);
+ pdf_print_ln(" 0 obj");
+ end else if pdf_compress_level = 0 then begin
+ pdf_print("% "); {debugging help}
+ pdf_print_int(i);
+ pdf_print_ln(" 0 obj");
+ end;
+end;
+
+procedure pdf_new_obj(t, i: integer; pdf_os: integer); {begin a new PDF object}
+begin
+ pdf_create_obj(t, i);
+ pdf_begin_obj(obj_ptr, pdf_os);
+end;
+
+procedure pdf_end_obj; {end a PDF object}
+begin
+ if pdf_os_mode then begin
+ if pdf_os_objidx = pdf_os_max_objs - 1 then
+ pdf_os_write_objstream;
+ end else
+ pdf_print_ln("endobj"); {end a PDF object}
+end;
+
+procedure pdf_begin_dict(i: integer; pdf_os_level: integer); {begin a PDF dictionary object}
+begin
+ check_pdfminorversion;
+ pdf_os_prepare_obj(i, pdf_os_level);
+ if not pdf_os_mode then begin
+ pdf_print_int(i);
+ pdf_print(" 0 obj ");
+ end else if pdf_compress_level = 0 then begin
+ pdf_print("% "); {debugging help}
+ pdf_print_int(i);
+ pdf_print_ln(" 0 obj");
+ end;
+ pdf_print_ln("<<");
+end;
+
+procedure pdf_new_dict(t, i: integer; pdf_os: integer); {begin a new PDF dictionary object}
+begin
+ pdf_create_obj(t, i);
+ pdf_begin_dict(obj_ptr, pdf_os);
+end;
+
+procedure pdf_end_dict; {end a PDF dictionary object}
+begin
+ if pdf_os_mode then begin
+ pdf_print_ln(">>");
+ if pdf_os_objidx = pdf_os_max_objs - 1 then
+ pdf_os_write_objstream;
+ end else
+ pdf_print_ln(">> endobj");
+end;
+
+@ Write out an accumulated object stream.
+First the object number and byte offset pairs are generated
+and appended to the ready buffered object stream.
+By this the value of \.{/First} can be calculated.
+Then a new \.{/ObjStm} object is generated, and everything is
+copied to the PDF output buffer, where also compression is done.
+When calling this procedure, |pdf_os_mode| must be |true|.
+
+@<Declare procedures that need to be declared forward for \pdfTeX@>=
+procedure pdf_os_write_objstream;
+var i, j, p, q: pointer;
+begin
+ if pdf_os_cur_objnum = 0 then {no object stream started}
+ return;
+ p := pdf_ptr;
+ i := 0;
+ j := 0;
+ while i <= pdf_os_objidx do begin {assemble object number and byte offset pairs}
+ pdf_print_int(pdf_os_objnum[i]);
+ pdf_print(" ");
+ pdf_print_int(pdf_os_objoff[i]);
+ if j = 9 then begin {print out in groups of ten for better readability}
+ pdf_out(pdf_new_line_char);
+ j := 0;
+ end else begin
+ pdf_print(" ");
+ incr(j);
+ end;
+ incr(i);
+ end;
+ pdf_buf[pdf_ptr - 1] := pdf_new_line_char; {no risk of flush, as we are in |pdf_os_mode|}
+ q := pdf_ptr;
+ pdf_begin_dict(pdf_os_cur_objnum, 0); {switch to PDF stream writing}
+ pdf_print_ln("/Type /ObjStm");
+ pdf_print("/N ");
+ pdf_print_int_ln(pdf_os_objidx + 1);
+ pdf_print("/First ");
+ pdf_print_int_ln(q - p);
+ pdf_begin_stream;
+ pdf_room(q - p); {should always fit into the PDF output buffer}
+ i := p;
+ while i < q do begin {write object number and byte offset pairs}
+ pdf_quick_out(pdf_os_buf[i]);
+ incr(i);
+ end;
+ i := 0;
+ while i < p do begin
+ q := i + pdf_buf_size;
+ if q > p then q := p;
+ pdf_room(q - i);
+ while i < q do begin {write the buffered objects}
+ pdf_quick_out(pdf_os_buf[i]);
+ incr(i);
+ end;
+ end;
+ pdf_end_stream;
+ pdf_os_cur_objnum := 0; {to force object stream generation next time}
+end;
+
+@ @<Declare procedures that need to be declared forward for \pdfTeX@>=
+function append_ptr(p: pointer; i: integer): pointer; {appends a pointer with
+info |i| to the end of linked list with head |p|}
+var q: pointer;
+begin
+ append_ptr := p;
+ fast_get_avail(q);
+ info(q) := i;
+ link(q) := null;
+ if p = null then begin
+ append_ptr := q;
+ return;
+ end;
+ while link(p) <> null do
+ p := link(p);
+ link(p) := q;
+end;
+
+function pdf_lookup_list(p: pointer; i: integer): pointer; {looks up for pointer
+with info |i| in list |p|}
+begin
+ pdf_lookup_list := null;
+ while p <> null do begin
+ if info(p) = i then begin
+ pdf_lookup_list := p;
+ return;
+ end;
+ p := link(p);
+ end;
+end;
+
+@ @<Glob...@>=
+@!pdf_image_procset: integer; {collection of image types used in current page/form}
+@!pdf_text_procset: boolean; {mask of used ProcSet's in the current page/form}
+
+@ Subroutines to print out various PDF objects
+
+@p procedure pdf_print_fw_int(n, w: integer); {print out an integer with
+fixed width; used for outputting cross-reference table}
+var k: integer; {$0\le k\le23$}
+begin
+ k := 0;
+ repeat dig[k] := n mod 10; n := n div 10; incr(k);
+ until k = w;
+ pdf_room(k);
+ while k > 0 do begin
+ decr(k);
+ pdf_quick_out("0" + dig[k]);
+ end;
+end;
+
+procedure pdf_out_bytes(n, w: integer); {print out an integer as
+a number of bytes; used for outputting \.{/XRef} cross-reference stream}
+var k: integer;
+byte: array[0..3] of integer; {digits in a number being output}
+begin
+ k := 0;
+ repeat byte[k] := n mod 256; n := n div 256; incr(k);
+ until k = w;
+ pdf_room(k);
+ while k > 0 do begin
+ decr(k);
+ pdf_quick_out(byte[k]);
+ end;
+end;
+
+procedure pdf_int_entry(s: str_number; v: integer); {print out an entry in
+dictionary with integer value to PDF buffer}
+begin
+ pdf_out("/");
+ pdf_print(s);
+ pdf_out(" ");
+ pdf_print_int(v);
+end;
+
+procedure pdf_int_entry_ln(s: str_number; v: integer);
+begin
+ pdf_int_entry(s, v);
+ pdf_print_nl;
+end;
+
+procedure pdf_indirect(s: str_number; o: integer); {print out an indirect
+entry in dictionary}
+begin
+ pdf_out("/");
+ pdf_print(s);
+ pdf_out(" ");
+ pdf_print_int(o);
+ pdf_print(" 0 R");
+end;
+
+procedure pdf_indirect_ln(s: str_number; o: integer);
+begin
+ pdf_indirect(s, o);
+ pdf_print_nl;
+end;
+
+procedure pdf_print_str_ln(s: str_number); {print out |s| as string in PDF
+output}
+begin
+ pdf_print_str(s);
+ pdf_print_nl;
+end;
+
+procedure pdf_str_entry(s, v: str_number); {print out an entry in
+dictionary with string value to PDF buffer}
+begin
+ if v = 0 then
+ return;
+ pdf_out("/");
+ pdf_print(s);
+ pdf_out(" ");
+ pdf_print_str(v);
+end;
+
+procedure pdf_str_entry_ln(s, v: str_number);
+begin
+ if v = 0 then
+ return;
+ pdf_str_entry(s, v);
+ pdf_print_nl;
+end;
+
+@* \[32e] Font processing.
+
+As \pdfTeX{} should also act as a back-end driver, it needs to support virtual
+fonts too. Information about virtual fonts can be found in the source of some
+\.{DVI}-related programs.
+
+Whenever we want to write out a character in a font to PDF output, we
+should check whether the used character is a virtual or read character.
+The |has_packet()| C macro checks for this condition.
+
+@ The following code typesets a character to PDF output.
+
+@p procedure output_one_char(ffi:internal_font_number;c:integer);
+begin
+ if has_packet(ffi,c) then
+ do_vf_packet(ffi, c)
+ else begin
+ pdf_begin_string(ffi);
+ pdf_print_char(ffi, c);
+ adv_char_width(ffi, c);
+ end;
+end;
+
+@ @<Declare procedures that need to be declared forward for \pdfTeX@>=
+procedure pdf_check_vf_cur_val; forward;
+procedure pdf_create_font_obj; forward;
+procedure pdf_init_font_cur_val; forward;
+procedure scan_pdf_ext_toks; forward;
+
+@ Here come some subroutines to deal with expanded fonts for HZ-algorithm.
+
+@d set_char_and_font(#) ==
+if is_char_node(#) then begin
+ c := character(#);
+ f := font(#);
+end
+
+@p
+function get_default_hyphen_char:integer;
+begin
+ get_default_hyphen_char:=default_hyphen_char;
+end;
+@#
+function get_default_skew_char:integer;
+begin
+ get_default_skew_char:=default_skew_char;
+end;
+@#
+
+procedure copy_expand_params(k, f: internal_font_number; e: integer);
+{set expansion-related parameters for an expanded font |k|, based on the base
+font |f| and the expansion amount |e|}
+begin
+ set_pdf_font_expand_ratio(k,e);
+ set_pdf_font_step(k,pdf_font_step(f));
+ set_pdf_font_auto_expand(k, pdf_font_auto_expand(f));
+ set_pdf_font_blink(k,f);
+end;
+
+function tfm_lookup(s: str_number; fs: scaled): internal_font_number;
+{looks up for a TFM with name |s| loaded at |fs| size; if found then flushes |s|}
+label exit;
+var k: internal_font_number;
+begin
+ if fs <> 0 then begin
+ for k := 1 to max_font_id do
+ if cmp_font_name(k, s) and (font_size(k) = fs) then begin
+ flush_str(s);
+ tfm_lookup := k;
+ return;
+ end;
+ end
+ else begin
+ for k := 1 to max_font_id do
+ if cmp_font_name(k, s) then begin
+ flush_string; {|font_name|}
+ flush_str(s);
+ tfm_lookup := k;
+ return;
+ end else flush_string;
+ end;
+ tfm_lookup := null_font;
+exit:
+end;
+
+function load_expand_font(f: internal_font_number; e: integer): internal_font_number;
+{loads font |f| expanded by |e| thousandths into font memory; |e| is nonzero
+and is a multiple of |pdf_font_step(f)|}
+label found;
+var s: str_number; {font name}
+ k: internal_font_number;
+begin
+ s := expand_font_name(f, e);
+ k := tfm_lookup(s, font_size(f));
+ if k = null_font then begin
+ if pdf_font_auto_expand(f) then begin
+ k := auto_expand_font(f, e);
+ font_id_text(k) := font_id_text(f);
+ end
+ else
+ k := read_font_info(null_cs, s, "", font_size(f), font_natural_dir(f));
+ end;
+ copy_expand_params(k, f, e);
+ load_expand_font := k;
+end;
+
+function fix_expand_value(f: internal_font_number; e: integer): integer;
+{return the multiple of |pdf_font_step(f)| that is nearest to |e|}
+var step: integer;
+ max_expand: integer;
+ neg: boolean;
+begin
+ fix_expand_value := 0;
+ if e = 0 then
+ return;
+ if e < 0 then begin
+ e := -e;
+ neg := true;
+ max_expand := -pdf_font_expand_ratio(pdf_font_shrink(f));
+ end
+ else begin
+ neg := false;
+ max_expand := pdf_font_expand_ratio(pdf_font_stretch(f));
+ end;
+ if e > max_expand then
+ e := max_expand
+ else begin
+ step := pdf_font_step(f);
+ if e mod step > 0 then
+ e := step*round_xn_over_d(e, 1, step);
+ end;
+ if neg then
+ e := -e;
+ fix_expand_value := e;
+end;
+
+function get_expand_font(f: internal_font_number; e: integer): internal_font_number;
+{look up and create if not found an expanded version of |f|; |f| is an
+expandable font; |e| is nonzero and is a multiple of |pdf_font_step(f)|}
+var k: internal_font_number;
+begin
+ k := pdf_font_elink(f);
+ while k <> null_font do begin
+ if pdf_font_expand_ratio(k) = e then begin
+ get_expand_font := k;
+ return;
+ end;
+ k := pdf_font_elink(k);
+ end;
+ k := load_expand_font(f, e);
+ set_pdf_font_elink(k,pdf_font_elink(f));
+ set_pdf_font_elink(f,k);
+ {|wterm_ln('get_expand_font ', e:1, ': ',f:1, ' became ', k:1);|}
+ get_expand_font := k;
+end;
+
+function expand_font(f: internal_font_number; e: integer): internal_font_number;
+{looks up for font |f| expanded by |e| thousandths, |e| is an arbitrary value
+between max stretch and max shrink of |f|; if not found then creates it}
+begin
+ expand_font := f;
+ if e = 0 then
+ return;
+ e := fix_expand_value(f, e);
+ if e = 0 then
+ return;
+ if pdf_font_elink(f) = null_font then
+ pdf_error("font expansion", "uninitialized pdf_font_elink");
+ expand_font := get_expand_font(f, e);
+end;
+
+procedure set_expand_params(f: internal_font_number; auto_expand: boolean;
+ font_stretch, font_shrink, font_step, expand_ratio: integer);
+{expand a font with given parameters}
+begin
+ set_pdf_font_step(f, font_step);
+ set_pdf_font_auto_expand(f, auto_expand);
+ if font_stretch > 0 then
+ set_pdf_font_stretch(f,get_expand_font(f, font_stretch));
+ if font_shrink > 0 then
+ set_pdf_font_shrink(f, get_expand_font(f, -font_shrink));
+ if expand_ratio <> 0 then
+ set_pdf_font_expand_ratio(f,expand_ratio);
+end;
+
+procedure read_expand_font; {read font expansion spec and load expanded font}
+var font_shrink, font_stretch, font_step: integer;
+ f: internal_font_number;
+ auto_expand: boolean;
+begin
+ {read font expansion parameters}
+ scan_font_ident;
+ f := cur_val;
+ if f = null_font then
+ pdf_error("font expansion", "invalid font identifier");
+ if pdf_font_blink(f) <> null_font then
+ pdf_error("font expansion", "\pdffontexpand cannot be used this way (the base font has been expanded or letter-spaced)");
+ scan_optional_equals;
+ scan_int;
+ font_stretch := fix_int(cur_val, 0, 1000);
+ scan_int;
+ font_shrink := fix_int(cur_val, 0, 500);
+ scan_int;
+ font_step := fix_int(cur_val, 0, 100);
+ if font_step = 0 then
+ pdf_error("font expansion", "invalid step");
+ font_stretch := font_stretch - font_stretch mod font_step;
+ if font_stretch < 0 then
+ font_stretch := 0;
+ font_shrink := font_shrink - font_shrink mod font_step;
+ if font_shrink < 0 then
+ font_shrink := 0;
+ if (font_stretch = 0) and (font_shrink = 0) then
+ pdf_error("font expansion", "invalid limit(s)");
+ auto_expand := false;
+ if scan_keyword("autoexpand") then begin
+ auto_expand := true;
+ @<Scan an optional space@>;
+ end;
+
+ {check if the font can be expanded}
+ if (pdf_font_expand_ratio(f) <> 0) then
+ pdf_error("font expansion", "this font has been expanded by another font so it cannot be used now");
+ if (pdf_font_step(f) <> 0) then
+ {this font has been expanded, ensure the expansion parameters are identical}
+ begin
+ if (pdf_font_step(f) <> font_step) or
+ ((pdf_font_stretch(f) = null_font) and (font_stretch <> 0)) or
+ ((pdf_font_stretch(f) <> null_font) and
+ (pdf_font_expand_ratio(pdf_font_stretch(f)) <> font_stretch)) or
+ ((pdf_font_shrink(f) = null_font) and (font_shrink <> 0)) or
+ ((pdf_font_shrink(f) <> null_font) and
+ (pdf_font_expand_ratio(pdf_font_shrink(f)) <> -font_shrink)) or
+ (pdf_font_auto_expand(f) <> auto_expand)
+ then
+ pdf_error("font expansion", "font has been expanded with different parameters");
+ end
+ else begin
+ if font_used(f) then
+ pdf_warning("font expansion", "font should be expanded before its first use",
+ true, true);
+ set_expand_params(f, auto_expand, font_stretch, font_shrink, font_step, 0);
+ if font_type(f) = virtual_font_type then
+ vf_expand_local_fonts(f);
+ end;
+end;
+
+procedure new_letterspaced_font(a: small_number);
+{letter-space a font by creating a virtual font}
+var u:pointer; {user's font identifier}
+@!t:str_number; {name for the frozen font identifier}
+@!old_setting:0..max_selector; {holds |selector| setting}
+@!f, k:internal_font_number;
+begin
+ get_r_token; u:=cur_cs;
+ if u>=hash_base then t:=text(u)
+ else if u=null_cs then t:="FONT"
+ else begin old_setting:=selector; selector:=new_string;
+ print("FONT"); print(u-active_base); selector:=old_setting;
+ @.FONTx@>
+ str_room(1); t:=make_string;
+ end;
+ define(u,set_font,null_font); scan_optional_equals; scan_font_ident;
+ k := cur_val;
+ scan_int;
+ f := letter_space_font(u, k, fix_int(cur_val, -1000, 1000));
+ equiv(u):=f; eqtb[font_id_base+f]:=eqtb[u]; font_id_text(f):=t;
+end;
+
+@ We need to hold information about used characters in each font for partial
+downloading.
+
+@<Types...@>=
+char_map_array = array[0..32] of eight_bits; {move chars in range 0..32}
+fm_entry_ptr = ^integer;
+
+@ @<Glob...@>=
+@!pdf_font_list: pointer; {list of used fonts in current page}
+@!pdf_resname_prefix: str_number; {global prefix of resources name}
+@!last_tokens_string: str_number; {the number of the most recently string
+created by |tokens_to_string|}
+
+@ @<Set init...@>=
+pdf_resname_prefix := 0;
+last_tokens_string := 0;
+
+@ Reading VF files is done in C, using the procedure |do_vf()|
+
+@* \[32f] PDF shipping out.
+To ship out a \TeX\ box to PDF page description we need to implement
+|pdf_hlist_out|, |pdf_vlist_out| and |pdf_ship_out|, which are equivalent to
+the \TeX' original |hlist_out|, |vlist_out| and |ship_out| resp. But first we
+need to declare some procedures needed in |pdf_hlist_out| and |pdf_vlist_out|.
+
+@<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure pdf_out_literal(p:pointer);
+var old_setting:0..max_selector; {holds print |selector|}
+ s: str_number;
+begin
+ old_setting:=selector; selector:=new_string;
+ show_token_list(link(pdf_literal_data(p)),null,pool_size-pool_ptr);
+ selector:=old_setting;
+ s := make_string;
+ literal(s, pdf_literal_mode(p), false);
+ flush_str(s);
+end;
+
+procedure pdf_out_colorstack(p:pointer);
+var old_setting: 0..max_selector; {holds print |selector|}
+ s: str_number;
+ cmd: integer;
+ stack_no: integer;
+ literal_mode: integer;
+begin
+ cmd := pdf_colorstack_cmd(p);
+ stack_no := pdf_colorstack_stack(p);
+ literal_mode := 0;
+ if stack_no >= colorstackused then begin
+ print_nl("");
+ print("Color stack ");
+ print_int(stack_no);
+ print(" is not initialized for use!");
+ print_nl("");
+ return;
+ end;
+ case cmd of
+ colorstack_set, colorstack_push: begin
+ old_setting:=selector; selector:=new_string;
+ show_token_list(link(pdf_colorstack_data(p)),null,pool_size-pool_ptr);
+ selector:=old_setting;
+ s := make_string;
+ if cmd = colorstack_set then
+ literal_mode := colorstackset(stack_no, s)
+ else
+ literal_mode := colorstackpush(stack_no, s);
+ if length(s) > 0 then
+ literal(s, literal_mode, false);
+ flush_str(s);
+ return;
+ end;
+ colorstack_pop: literal_mode := colorstackpop(stack_no);
+ colorstack_current: literal_mode := colorstackcurrent(stack_no);
+ othercases do_nothing
+ endcases;
+ if cur_length > 0 then begin
+ s := make_string;
+ literal(s, literal_mode, false);
+ flush_str(s);
+ end
+end;
+
+procedure pdf_out_colorstack_startpage;
+var i: integer;
+ max: integer;
+ start_status: integer;
+ literal_mode: integer;
+ s: str_number;
+begin
+ i := 0;
+ max := colorstackused;
+ while i < max do begin
+ start_status := colorstackskippagestart(i);
+ if start_status = 0 then begin
+ literal_mode := colorstackcurrent(i);
+ if cur_length > 0 then begin
+ s := make_string;
+ literal(s, literal_mode, false);
+ flush_str(s);
+ end;
+ end;
+ incr(i);
+ end;
+end;
+
+procedure pdf_out_setmatrix(p:pointer);
+var old_setting:0..max_selector; {holds print |selector|}
+ s: str_number;
+begin
+ old_setting:=selector; selector:=new_string;
+ show_token_list(link(pdf_setmatrix_data(p)),null,pool_size-pool_ptr);
+ selector:=old_setting;
+ str_room(7);
+ str_pool[pool_ptr] := 0; { make C string for pdfsetmatrix }
+ pdfsetmatrix(str_start[str_ptr], cur_h, cur_page_height - cur_v);
+ str_room(7);
+ append_char(" ");
+ append_char("0");
+ append_char(" ");
+ append_char("0");
+ append_char(" ");
+ append_char("c");
+ append_char("m");
+ s := make_string;
+ literal(s, set_origin, false);
+ flush_str(s);
+end;
+
+procedure pdf_out_save;
+begin
+ checkpdfsave(cur_h, cur_v);
+ literal("q", set_origin, false);
+end;
+
+procedure pdf_out_restore;
+begin
+ checkpdfrestore(cur_h, cur_v);
+ literal("Q", set_origin, false);
+end;
+
+procedure pdf_special(p: pointer);
+var old_setting:0..max_selector; {holds print |selector|}
+ s: str_number;
+begin
+ old_setting:=selector; selector:=new_string;
+ show_token_list(link(write_tokens(p)),null,pool_size-pool_ptr);
+ selector:=old_setting;
+ s := make_string;
+ literal(s, scan_special, true);
+ flush_str(s);
+end;
+
+procedure do_late_lua(p: pointer);
+var old_setting:0..max_selector; {holds print |selector|}
+ s: str_number;
+begin
+ old_setting:=selector; selector:=new_string;
+ show_token_list(link(late_lua_data(p)),null,pool_size-pool_ptr);
+ selector:=old_setting;
+ s := make_string;
+ latelua(late_lua_reg(p), s);
+ flush_str(s);
+end;
+
+procedure pdf_print_toks(p: pointer); {print tokens list |p|}
+var s: str_number;
+begin
+ s := tokens_to_string(p);
+ if length(s) > 0 then
+ pdf_print(s);
+ flush_str(s);
+end;
+
+procedure pdf_print_toks_ln(p: pointer); {print tokens list |p|}
+var s: str_number;
+begin
+ s := tokens_to_string(p);
+ if length(s) > 0 then begin
+ pdf_print_ln(s);
+ end;
+ flush_str(s);
+end;
+
+@ Similiar to |vlist_out|, |pdf_vlist_out| needs to be declared forward
+
+@p procedure@?pdf_vlist_out; forward;
+
+@ The implementation of procedure |pdf_hlist_out| is similiar to |hlist_out|
+
+@p @t\4@>@<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>@t@>@/
+
+procedure pdf_hlist_out; {output an |hlist_node| box}
+label move_past, fin_rule, next_p;
+var base_line: scaled; {the baseline coordinate for this box}
+c_wd,c_ht,c_dp: scaled;
+ {the real width, height and depth of the character}
+w: scaled; { temporary value for directional width calculation }
+dir_nest: integer; { for tracking nested direction nodes }
+edge_v: scaled;
+edge_h: scaled;
+effective_horizontal: scaled;
+basepoint_horizontal: scaled;
+basepoint_vertical: scaled;
+saving_h: scaled;
+saving_v: scaled;
+save_direction: integer;
+dvi_ptr,dir_ptr,dir_tmp:pointer;
+@!left_edge: scaled; {the left coordinate for this box}
+@!save_h: scaled; {what |cur_h| should pop to}
+@!this_box: pointer; {pointer to containing box}
+@!g_order: glue_ord; {applicable order of infinity for glue}
+@!g_sign: normal..shrinking; {selects type of glue}
+@!p,q:pointer; {current position in the hlist}
+@!leader_box:pointer; {the leader box being replicated}
+@!leader_wd:scaled; {width of leader box being replicated}
+@!lx:scaled; {extra space between leader boxes}
+@!outer_doing_leaders:boolean; {were we doing leaders?}
+@!edge:scaled; {right edge of sub-box or leader space}
+@!prev_p:pointer; {one step behind |p|}
+@!glue_temp:real; {glue value before rounding}
+@!cur_glue:real; {glue seen so far}
+@!save_cur_glue:real; { saved version, for direction switch }
+@!cur_g:scaled; {rounded equivalent of |cur_glue| times the glue ratio}
+@!save_cur_g:scaled; { saved version, for direction switch }
+@!i: small_number; {index to scan |pdf_link_stack|}
+begin cur_g:=0; cur_glue:=float_constant(0);
+this_box:=temp_ptr; g_order:=glue_order(this_box);
+g_sign:=glue_sign(this_box); p:=list_ptr(this_box);
+save_direction:=dvi_direction;
+dvi_direction:=box_dir(this_box);
+dvi_ptr:=0; lx:=0;
+@<DIR: Initialize |dir_ptr| for |ship_out|@>;
+saving_h:=cur_h; saving_v:=cur_v;
+incr(cur_s);
+base_line:=cur_v;
+left_edge:=cur_h;
+prev_p:=this_box+list_offset;
+@<Create link annotations for the current hbox if needed@>;
+while p<>null do
+ @<Output node |p| for |pdf_hlist_out| and move to the next node,
+ maintaining the condition |cur_v=base_line|@>;
+cur_h:=saving_h; cur_v:=saving_v;
+decr(cur_s);
+dvi_direction:=save_direction;
+@<DIR: Reset |dir_ptr|@>;
+end;
+
+@ @<Create link annotations for the current hbox if needed@>=
+for i := 1 to pdf_link_stack_ptr do begin
+ pdfassert(is_running(pdf_width(pdf_link_stack[i].link_node)));
+ if (pdf_link_stack[i].nesting_level = cur_s) then
+ append_link(this_box, left_edge, base_line, i);
+end
+
+@
+
+@d pdf_dvicmd_set(#)==output_one_char(f,#)
+@d pdf_dvicmd_put(#)==output_one_char(f,#); cur_h:=cur_h-c_wd
+@d pdf_dvicmd_right(#)==cur_h := cur_h + #
+@d pdf_dvicmd_left(#)== cur_h := cur_h - #
+@d pdf_dvicmd_down(#)== cur_v := cur_v - #
+@d pdf_dvicmd_up(#)== cur_v := cur_v + #
+@d pdf_dvicmd_h(#)==case box_direction(dvi_direction) of
+ dir_TL_: begin cur_h := cur_h + #; end;
+ dir_TR_: begin cur_h := cur_h - #; end;
+ dir_LT_: begin do_nothing; {if o=right1 then o:=down1 else o:=right1;} end;
+ dir_LB_: begin do_nothing; {if o=right1 then begin o:=down1; negate(w); end else o:=right1;} end;
+ dir_BL_: begin do_nothing; {if o=down1 then negate(w); } end;
+ dir_BR_: begin do_nothing; { negate(w);} end;
+ dir_RT_: begin do_nothing; {if o=right1 then o:=down1 else begin o:=right1; negate(w); end;} end;
+ dir_RB_: begin do_nothing; {if o=right1 then o:=down1 else o:=right1; negate(w);} end;
+ end
+
+
+@<Output node |p| for |pdf_hlist_out|...@>=
+begin
+if is_char_node(p) then
+ begin
+ repeat f:=font(p); c:=character(p);
+ ci := char_info_short (f,c);
+ {|writeln('hlist_out: a char node ', c:1 , ' in font ',f:1);|}
+ if is_valid_char(c) then begin
+ if is_rotated(dvi_direction) then begin
+ c_ht:=charinfo_width(ci) div 2;
+ c_dp:=0;
+ c_wd:=charinfo_height(ci)+charinfo_depth(ci);
+ end
+ else begin
+ c_ht:=charinfo_height(ci);
+ c_dp:=charinfo_depth(ci);
+ c_wd:=charinfo_width(ci);
+ end;
+ if (font_natural_dir(f)<>-1) then
+ case font_direction(dvi_direction) of
+ dir__LT,dir__LB: begin
+ if x_displace(p)<>0 then pdf_dvicmd_right(x_displace(p));
+ if y_displace(p)<>0 then pdf_dvicmd_up(-y_displace(p));
+ pdf_dvicmd_set(c);
+ if x_displace(p)<>0 then pdf_dvicmd_left(x_displace(p));
+ if y_displace(p)<>0 then pdf_dvicmd_down(-y_displace(p));
+ end;
+ dir__RT,dir__RB: begin
+ if x_displace(p)<>0 then pdf_dvicmd_left(x_displace(p));
+ if y_displace(p)<>0 then pdf_dvicmd_up(-y_displace(p));
+ pdf_dvicmd_left(c_wd);
+ pdf_dvicmd_put(c);
+ if x_displace(p)<>0 then pdf_dvicmd_right(x_displace(p));
+ if y_displace(p)<>0 then pdf_dvicmd_down(-y_displace(p));
+ end;
+ dir__TL,dir__TR: begin
+ pdf_dvicmd_put(c);
+ pdf_dvicmd_down(c_wd);
+ end;
+ dir__BL,dir__BR: begin
+ pdf_dvicmd_put(c);
+ pdf_dvicmd_up(c_wd);
+ end;
+ dir__LL,dir__LR: begin
+ pdf_dvicmd_put(c);
+ pdf_dvicmd_right(c_wd);
+ end;
+ dir__RL,dir__RR: begin
+ pdf_dvicmd_put(c);
+ pdf_dvicmd_left(c_wd);
+ end;
+ dir__TT,dir__TB: begin
+ pdf_dvicmd_put(c);
+ pdf_dvicmd_down(c_wd);
+ end;
+ dir__BT,dir__BB: begin
+ pdf_dvicmd_put(c);
+ pdf_dvicmd_up(c_wd);
+ end;
+ end
+ else
+ case font_direction(dvi_direction) of
+ dir__LT: begin
+ if x_displace(p)<>0 then pdf_dvicmd_right(x_displace(p));
+ if y_displace(p)<>0 then pdf_dvicmd_up(-y_displace(p));
+ pdf_dvicmd_set(c);
+ if x_displace(p)<>0 then pdf_dvicmd_left(x_displace(p));
+ if y_displace(p)<>0 then pdf_dvicmd_down(-y_displace(p));
+ end;
+ dir__LB: begin
+ pdf_dvicmd_down(c_ht);
+ pdf_dvicmd_set(c);
+ pdf_dvicmd_up(c_ht);
+ end;
+ dir__RT: begin
+ if x_displace(p)<>0 then pdf_dvicmd_left(x_displace(p));
+ if y_displace(p)<>0 then pdf_dvicmd_up(-y_displace(p));
+ pdf_dvicmd_left(c_wd);
+ pdf_dvicmd_put(c);
+ if x_displace(p)<>0 then pdf_dvicmd_right(x_displace(p));
+ if y_displace(p)<>0 then pdf_dvicmd_down(-y_displace(p));
+ end;
+ dir__RB: begin
+ pdf_dvicmd_left(c_wd);
+ pdf_dvicmd_down(c_ht);
+ pdf_dvicmd_put(c);
+ pdf_dvicmd_up(c_ht);
+ end;
+ dir__TL: begin
+ pdf_dvicmd_down(c_wd);
+ pdf_dvicmd_left(c_ht);
+ pdf_dvicmd_put(c);
+ pdf_dvicmd_right(c_ht);
+ end;
+ dir__TR: begin
+ pdf_dvicmd_down(c_wd);
+ pdf_dvicmd_left(c_dp);
+ pdf_dvicmd_put(c);
+ pdf_dvicmd_right(c_dp);
+ end;
+ dir__BL: begin
+ pdf_dvicmd_left(c_ht);
+ pdf_dvicmd_put(c);
+ pdf_dvicmd_right(c_ht);
+ pdf_dvicmd_up(c_wd);
+ end;
+ dir__BR: begin
+ pdf_dvicmd_left(c_dp);
+ pdf_dvicmd_put(c);
+ pdf_dvicmd_right(c_dp);
+ pdf_dvicmd_up(c_wd);
+ end;
+ dir__LL,dir__LR: begin
+ pdf_dvicmd_down(c_ht);
+ pdf_dvicmd_put(c);
+ pdf_dvicmd_up(c_ht);
+ pdf_dvicmd_right(c_wd);
+ end;
+ dir__RL,dir__RR: begin
+ pdf_dvicmd_left(c_wd);
+ pdf_dvicmd_down(c_ht);
+ pdf_dvicmd_put(c);
+ pdf_dvicmd_up(c_ht);
+ end;
+ dir__TT,dir__TB: begin
+ pdf_dvicmd_down(c_wd);
+ pdf_dvicmd_left(c_ht);
+ pdf_dvicmd_put(c);
+ pdf_dvicmd_right(c_ht);
+ end;
+ dir__BT,dir__BB: begin
+ pdf_dvicmd_left(c_ht);
+ pdf_dvicmd_put(c);
+ pdf_dvicmd_right(c_ht);
+ pdf_dvicmd_up(c_wd);
+ end;
+ end;
+ cur_h:=cur_h+c_wd;
+ end
+ else
+ char_warning(f, c);
+ prev_p:=p;
+ p:=vlink(p);
+ until not is_char_node(p);
+ end
+else @<Output the non-|char_node| |p| for |pdf_hlist_out|
+ and move to the next node@>;
+end
+
+@ @<Output the non-|char_node| |p| for |pdf_hlist_out|...@>=
+begin case type(p) of
+hlist_node,vlist_node:@<(\pdfTeX) Output a box in an hlist@>;
+disc_node: if vlink(no_break(p))<>null then begin
+ q:=tail_of_list (vlink(no_break(p))); {TODO, this should be a tlink}
+ vlink(q):=vlink(p);
+ q:=vlink(no_break(p));
+ vlink(no_break(p)):=null;
+ vlink(p):=q;
+ end;
+rule_node: begin
+ if not (dir_orthogonal(dir_primary[rule_dir(p)])(dir_primary[dvi_direction]))
+ then begin
+ rule_ht:=height(p); rule_dp:=depth(p); rule_wd:=width(p);
+ end
+ else begin
+ rule_ht:=width(p) div 2;
+ rule_dp:=width(p) div 2;
+ rule_wd:=height(p)+depth(p);
+ end;
+ goto fin_rule;
+ end;
+whatsit_node: @<Output the whatsit node |p| in |pdf_hlist_out|@>;
+glue_node: @<(\pdfTeX) Move right or output leaders@>;
+margin_kern_node,kern_node: pdf_dvicmd_h(width(p));
+math_node: pdf_dvicmd_h(surround(p));
+othercases do_nothing
+endcases;@/
+goto next_p;
+fin_rule: @<(\pdfTeX) Output a rule in an hlist@>;
+move_past: pdf_dvicmd_h(rule_wd);
+next_p:prev_p:=p; p:=vlink(p);
+end
+
+@ @<(\pdfTeX) Output a box in an hlist@>=
+begin
+if not (dir_orthogonal(dir_primary[box_dir(p)])(dir_primary[dvi_direction]))
+ then begin
+ effective_horizontal:=width(p);
+ basepoint_vertical:=0;
+ if dir_opposite(dir_secondary[box_dir(p)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=width(p)
+ else
+ basepoint_horizontal:=0;
+ end
+else begin
+ effective_horizontal:=height(p)+depth(p);
+ if not (is_mirrored(box_dir(p))) then
+ if dir_eq(dir_primary[box_dir(p)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=height(p)
+ else
+ basepoint_horizontal:=depth(p)
+ else
+ if dir_eq(dir_primary[box_dir(p)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=depth(p)
+ else
+ basepoint_horizontal:=height(p);
+ if dir_eq(dir_secondary[box_dir(p)])(dir_primary[dvi_direction]) then
+ basepoint_vertical:= -(width(p) div 2)
+ else
+ basepoint_vertical:= (width(p) div 2);
+ end;
+if not (is_mirrored(dvi_direction)) then
+ basepoint_vertical := basepoint_vertical + shift_amount(p)
+ {shift the box `down'}
+else
+ basepoint_vertical := basepoint_vertical - shift_amount(p);
+ {shift the box `up'}
+if list_ptr(p)=null then begin pdf_dvicmd_h(effective_horizontal); end
+else begin
+ temp_ptr:=p;
+ edge:=cur_h; pdf_dvicmd_h(basepoint_horizontal);
+ edge_v:=cur_v; cur_v:=base_line + basepoint_vertical;
+ if type(p)=vlist_node then pdf_vlist_out@+else pdf_hlist_out;
+ cur_h:=edge; pdf_dvicmd_h(effective_horizontal);
+ cur_v:=base_line;
+ end
+end
+
+@ @<(\pdfTeX) Output a rule in an hlist@>=
+if is_running(rule_ht) then rule_ht:=height(this_box);
+if is_running(rule_dp) then rule_dp:=depth(this_box);
+rule_ht:=rule_ht+rule_dp; {this is the rule thickness}
+if (rule_ht>0)and(rule_wd>0) then {we don't output empty rules}
+ begin cur_v:=base_line+rule_dp;
+ case font_direction(dvi_direction) of
+ dir__LT: begin
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ end;
+ dir__LB: begin
+ pdf_dvicmd_down(rule_ht);
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ pdf_dvicmd_up(rule_ht);
+ end;
+ dir__RT: begin
+ pdf_dvicmd_left(rule_wd);
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ pdf_dvicmd_right(rule_wd);
+ end;
+ dir__RB: begin
+ pdf_dvicmd_left(rule_wd);
+ pdf_dvicmd_down(rule_ht);
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ pdf_dvicmd_left(rule_wd);
+ pdf_dvicmd_up(rule_ht);
+ end;
+ dir__TL: begin
+ pdf_dvicmd_down(rule_wd);
+ pdf_dvicmd_left(rule_ht);
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ end;
+ dir__TR: begin
+ pdf_dvicmd_down(rule_wd);
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ pdf_dvicmd_left(rule_ht);
+ end;
+ dir__BL: begin
+ pdf_dvicmd_left(rule_ht);
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ pdf_dvicmd_up(rule_wd);
+ end;
+ dir__BR: begin
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ pdf_dvicmd_left(rule_ht);
+ pdf_dvicmd_up(rule_wd);
+ end;
+ end;
+ {|cur_h:=cur_h+rule_wd;|}{|dir__RT| is corrected elsewhere}
+ cur_v:=base_line;
+ end
+
+@ @<(\pdfTeX) Move right or output leaders@>=
+begin g:=glue_ptr(p); rule_wd:=width(g)-cur_g;
+if g_sign<>normal then
+ begin if g_sign=stretching then
+ begin if stretch_order(g)=g_order then
+ begin cur_glue:=cur_glue+stretch(g);
+ vet_glue(float(glue_set(this_box))*cur_glue);
+@^real multiplication@>
+ cur_g:=round(glue_temp);
+ end;
+ end
+ else if shrink_order(g)=g_order then
+ begin cur_glue:=cur_glue-shrink(g);
+ vet_glue(float(glue_set(this_box))*cur_glue);
+ cur_g:=round(glue_temp);
+ end;
+ end;
+rule_wd:=rule_wd+cur_g;
+if subtype(p)>=a_leaders then
+ @<(\pdfTeX) Output leaders in an hlist, |goto fin_rule| if a rule
+ or to |next_p| if done@>;
+goto move_past;
+end
+
+@ @<(\pdfTeX) Output leaders in an hlist...@>=
+begin leader_box:=leader_ptr(p);
+if type(leader_box)=rule_node then
+ begin rule_ht:=height(leader_box); rule_dp:=depth(leader_box);
+ goto fin_rule;
+ end;
+if not (dir_orthogonal(dir_primary[box_dir(leader_box)])(dir_primary[dvi_direction]))
+ then leader_wd:=width(leader_box)
+else
+ leader_wd:=height(leader_box)+depth(leader_box);
+if (leader_wd>0)and(rule_wd>0) then
+ begin
+ edge:=cur_h+rule_wd;
+ {TODO this double |case| is a hack, and not quite the proper
+ solution, but it produces the correct output for |xleaders|
+ in TRT mode, which is important for KASHIDAH fills.}
+ case box_direction(dvi_direction) of
+ dir_TR_,dir_RT_: begin
+ edge:=cur_h;
+ cur_h:=cur_h-rule_wd;
+ end;
+ end;
+ @<Let |cur_h| be the position of the first box, and set |leader_wd+lx|
+ to the spacing between corresponding parts of boxes@>;
+ while cur_h+leader_wd<=edge do
+ @<(\pdfTeX) Output a leader box at |cur_h|,
+ then advance |cur_h| by |leader_wd+lx|@>;
+ case box_direction(dvi_direction) of
+ dir_TR_,dir_RT_: cur_h:=cur_h-rule_wd;
+ end;
+ goto next_p;
+ end;
+end
+
+@ @<(\pdfTeX) Output a leader box at |cur_h|, ...@>=
+begin
+if not (dir_orthogonal(dir_primary[box_dir(leader_box)])(dir_primary[dvi_direction]))
+ then begin
+ basepoint_vertical:=0;
+ if dir_opposite(dir_secondary[box_dir(leader_box)])(dir_secondary[dvi_direction]) then begin
+ basepoint_horizontal:=width(leader_box)
+ end
+ else
+ basepoint_horizontal:=0;
+ end
+else begin
+ if not (is_mirrored(box_dir(leader_box))) then
+ if dir_eq(dir_primary[box_dir(leader_box)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=height(leader_box)
+ else
+ basepoint_horizontal:=depth(leader_box)
+ else
+ if dir_eq(dir_primary[box_dir(leader_box)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=depth(leader_box)
+ else
+ basepoint_horizontal:=height(leader_box);
+ if dir_eq(dir_secondary[box_dir(leader_box)])(dir_primary[dvi_direction]) then
+ basepoint_vertical:= -(width(leader_box) div 2)
+ else
+ basepoint_vertical:= (width(leader_box) div 2);
+ end;
+if not (is_mirrored(dvi_direction)) then
+ basepoint_vertical := basepoint_vertical + shift_amount(leader_box)
+ {shift the box `down'}
+else
+ basepoint_vertical := basepoint_vertical - shift_amount(leader_box);
+ {shift the box `up'}
+temp_ptr:=leader_box;
+edge_h:=cur_h; cur_h:=cur_h + basepoint_horizontal;
+edge_v:=cur_v; cur_v:=base_line + basepoint_vertical;
+outer_doing_leaders:=doing_leaders; doing_leaders:=true;
+if type(leader_box)=vlist_node then pdf_vlist_out@+else pdf_hlist_out;
+doing_leaders:=outer_doing_leaders;
+cur_h:=edge_h+leader_wd+lx; cur_v:=base_line;
+end
+
+@ The |pdf_vlist_out| routine is similar to |pdf_hlist_out|, but a bit simpler.
+@p procedure pdf_vlist_out; {output a |pdf_vlist_node| box}
+label move_past, fin_rule, next_p;
+var left_edge: scaled; {the left coordinate for this box}
+@!top_edge: scaled; {the top coordinate for this box}
+@!save_v: scaled; {what |cur_v| should pop to}
+@!this_box: pointer; {pointer to containing box}
+@!g_order: glue_ord; {applicable order of infinity for glue}
+@!g_sign: normal..shrinking; {selects type of glue}
+@!p:pointer; {current position in the vlist}
+@!leader_box:pointer; {the leader box being replicated}
+@!leader_ht:scaled; {height of leader box being replicated}
+@!lx:scaled; {extra space between leader boxes}
+@!outer_doing_leaders:boolean; {were we doing leaders?}
+@!edge:scaled; {bottom boundary of leader space}
+@!glue_temp:real; {glue value before rounding}
+@!cur_glue:real; {glue seen so far}
+@!cur_g:scaled; {rounded equivalent of |cur_glue| times the glue ratio}
+@!save_direction: integer;
+@!effective_vertical: scaled;
+@!basepoint_horizontal: scaled;
+@!basepoint_vertical: scaled;
+@!edge_v: scaled;
+@!saving_v: scaled;
+@!saving_h: scaled;
+begin cur_g:=0; cur_glue:=float_constant(0);
+this_box:=temp_ptr; g_order:=glue_order(this_box);
+g_sign:=glue_sign(this_box); p:=list_ptr(this_box);
+{pdfassert(p<>0);}
+saving_v:=cur_v; saving_h:=cur_h;
+{|writeln(''); writeln('vlist_out: left edge: ', cur_h:1 , '');|}
+save_direction:=dvi_direction;
+dvi_direction:=box_dir(this_box);
+incr(cur_s);
+left_edge:=cur_h; cur_v:=cur_v-height(this_box); top_edge:=cur_v;
+@<Create thread for the current vbox if needed@>;
+while p<>null do
+ @<Output node |p| for |pdf_vlist_out| and move to the next node,
+ maintaining the condition |cur_h=left_edge|@>;
+cur_v:=saving_v; cur_h:=saving_h;
+decr(cur_s);
+dvi_direction:=save_direction;
+end;
+
+@ @<Create thread for the current vbox if needed@>=
+if (last_thread <> null) and is_running(pdf_thread_dp) and
+ (pdf_thread_level = cur_s) then
+ append_thread(this_box, left_edge, top_edge + height(this_box))
+
+@ @<Output node |p| for |pdf_vlist_out|...@>=
+begin if is_char_node(p) then confusion("pdfvlistout")
+@:this can't happen pdfvlistout}{\quad pdfvlistout@>
+else @<Output the non-|char_node| |p| for |pdf_vlist_out|@>;
+next_p:p:=vlink(p);
+end
+
+@ @<Output the non-|char_node| |p| for |pdf_vlist_out|@>=
+begin case type(p) of
+hlist_node,vlist_node:@<(\pdfTeX) Output a box in a vlist@>;
+rule_node: begin
+ if not (dir_orthogonal(dir_primary[rule_dir(p)])(dir_primary[dvi_direction]))
+ then begin
+ rule_ht:=height(p); rule_dp:=depth(p); rule_wd:=width(p);
+ end
+ else begin
+ rule_ht:=width(p) div 2;
+ rule_dp:=width(p) div 2;
+ rule_wd:=height(p)+depth(p);
+ end;
+ goto fin_rule;
+ end;
+whatsit_node: @<Output the whatsit node |p| in |pdf_vlist_out|@>;
+glue_node: @<(\pdfTeX) Move down or output leaders@>;
+kern_node:cur_v:=cur_v+width(p);
+othercases do_nothing
+endcases;@/
+goto next_p;
+fin_rule: @<(\pdfTeX) Output a rule in a vlist, |goto next_p|@>;
+move_past: cur_v:=cur_v+rule_ht;
+end
+
+@ TODO: the direct test to switch between |width(p)| and |-width(p)|
+is definately wrong, because it does not nest properly. But at least
+it fixes a very obvious problem that otherwise occured with
+\.{\\pardir TLT} in a document with \.{\\bodydir TRT}, and so it
+will have to do for now.
+
+@<(\pdfTeX) Output a box in a vlist@>=
+begin
+if not (dir_orthogonal(dir_primary[box_dir(p)])(dir_primary[dvi_direction]))
+ then begin
+ effective_vertical:=height(p)+depth(p);
+ if (type(p)=hlist_node) and (is_mirrored(box_dir(p))) then
+ basepoint_vertical:=depth(p)
+ else
+ basepoint_vertical:=height(p);
+ if dir_opposite(dir_secondary[box_dir(p)])(dir_secondary[dvi_direction]) then begin
+ if dvi_direction=dir_TL_ then
+ basepoint_horizontal:=width(p)
+ else
+ basepoint_horizontal:=-width(p);
+ end
+ else
+ basepoint_horizontal:=0;
+ end
+else begin
+ effective_vertical:=width(p);
+ if not (is_mirrored(box_dir(p))) then
+ if dir_eq(dir_primary[box_dir(p)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=height(p)
+ else
+ basepoint_horizontal:=depth(p)
+ else
+ if dir_eq(dir_primary[box_dir(p)])(dir_secondary[dvi_direction]) then
+ basepoint_horizontal:=depth(p)
+ else
+ basepoint_horizontal:=height(p);
+ if dir_eq(dir_secondary[box_dir(p)])(dir_primary[dvi_direction]) then
+ basepoint_vertical:=0
+ else
+ basepoint_vertical:=width(p);
+ end;
+basepoint_horizontal := basepoint_horizontal + shift_amount(p);
+if list_ptr(p)=null then begin
+ cur_v:=cur_v+effective_vertical;
+ end
+else begin
+ edge_v:=cur_v;
+ cur_h:=left_edge + basepoint_horizontal;
+ cur_v:=cur_v + basepoint_vertical;
+ temp_ptr:=p;
+ if type(p)=vlist_node then pdf_vlist_out@+else pdf_hlist_out;
+ cur_h:=left_edge; cur_v:=edge_v + effective_vertical;
+ end
+end
+
+@ @<(\pdfTeX) Output a rule in a vlist...@>=
+if is_running(rule_wd) then rule_wd:=width(this_box);
+rule_ht:=rule_ht+rule_dp; {this is the rule thickness}
+cur_v:=cur_v+rule_ht;
+if (rule_ht>0)and(rule_wd>0) then {we don't output empty rules}
+ begin
+ case font_direction(dvi_direction) of
+ dir__LT: begin
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ {|pdf_dvicmd_left(rule_wd);|}
+ end;
+ dir__LB: begin
+ pdf_dvicmd_down(rule_ht);
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ pdf_dvicmd_left(rule_wd);
+ pdf_dvicmd_up(rule_ht);
+ end;
+ dir__RT: begin
+ pdf_dvicmd_left(rule_wd);
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ pdf_dvicmd_left(rule_wd);
+ end;
+ dir__RB: begin
+ pdf_dvicmd_down(rule_ht);
+ pdf_dvicmd_left(rule_wd);
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ pdf_dvicmd_up(rule_ht);
+ end;
+ dir__TL: begin
+ pdf_dvicmd_down(rule_wd);
+ pdf_dvicmd_left(rule_ht);
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ pdf_dvicmd_up(rule_wd);
+ end;
+ dir__TR: begin
+ pdf_dvicmd_down(rule_wd);
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ pdf_dvicmd_left(rule_wd);
+ pdf_dvicmd_up(rule_wd);
+ end;
+ dir__BL: begin
+ pdf_dvicmd_left(rule_ht);
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ end;
+ dir__BR: begin
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ pdf_dvicmd_left(rule_wd);
+ end;
+ end;
+ end;
+goto next_p
+
+@ @<(\pdfTeX) Move down or output leaders@>=
+begin g:=glue_ptr(p); rule_ht:=width(g)-cur_g;
+if g_sign<>normal then
+ begin if g_sign=stretching then
+ begin if stretch_order(g)=g_order then
+ begin cur_glue:=cur_glue+stretch(g);
+ vet_glue(float(glue_set(this_box))*cur_glue);
+@^real multiplication@>
+ cur_g:=round(glue_temp);
+ end;
+ end
+ else if shrink_order(g)=g_order then
+ begin cur_glue:=cur_glue-shrink(g);
+ vet_glue(float(glue_set(this_box))*cur_glue);
+ cur_g:=round(glue_temp);
+ end;
+ end;
+rule_ht:=rule_ht+cur_g;
+if subtype(p)>=a_leaders then
+ @<(\pdfTeX) Output leaders in a vlist, |goto fin_rule| if a rule
+ or to |next_p| if done@>;
+goto move_past;
+end
+
+@ @<(\pdfTeX) Output leaders in a vlist...@>=
+begin leader_box:=leader_ptr(p);
+if type(leader_box)=rule_node then
+ begin rule_wd:=width(leader_box); rule_dp:=0;
+ goto fin_rule;
+ end;
+leader_ht:=height(leader_box)+depth(leader_box);
+if (leader_ht>0)and(rule_ht>0) then
+ begin rule_ht:=rule_ht+10; {compensate for floating-point rounding}
+ edge:=cur_v+rule_ht; lx:=0;
+ @<Let |cur_v| be the position of the first box, and set |leader_ht+lx|
+ to the spacing between corresponding parts of boxes@>;
+ while cur_v+leader_ht<=edge do
+ @<(\pdfTeX) Output a leader box at |cur_v|,
+ then advance |cur_v| by |leader_ht+lx|@>;
+ cur_v:=edge-10; goto next_p;
+ end;
+end
+
+@ @<(\pdfTeX) Output a leader box at |cur_v|, ...@>=
+begin cur_h:=left_edge+shift_amount(leader_box);
+cur_v:=cur_v+height(leader_box); save_v:=cur_v;
+temp_ptr:=leader_box;
+outer_doing_leaders:=doing_leaders; doing_leaders:=true;
+if type(leader_box)=vlist_node then pdf_vlist_out@+else pdf_hlist_out;
+doing_leaders:=outer_doing_leaders;
+cur_h:=left_edge;
+cur_v:=save_v-height(leader_box)+leader_ht+lx;
+end
+
+@ |fix_pdfoutput| freezes |pdfoutput| when something has been written to
+the output.
+
+@p procedure fix_pdfoutput;
+begin
+ if not fixed_pdfoutput_set then begin
+ fixed_pdfoutput := pdf_output;
+ fixed_pdfoutput_set := true;
+ end
+ else if fixed_pdfoutput <> pdf_output then
+ pdf_error("setup",
+ "\pdfoutput can only be changed before anything is written to the output");
+ if fixed_pdfoutput_set then fix_pdf_draftmode;
+end;
+
+@ |fix_pdf_draftmode| freezes |pdfdraftmode| when something has been written to
+the output and also switches somes things off when draftmode is on.
+@p procedure fix_pdf_draftmode;
+begin
+ if not fixed_pdf_draftmode_set then begin
+ fixed_pdf_draftmode := pdf_draftmode;
+ fixed_pdf_draftmode_set := true;
+ end
+ else if fixed_pdf_draftmode <> pdf_draftmode then
+ pdf_error("setup",
+ "\pdfdraftmode can only be changed before anything is written to the output");
+ if fixed_pdf_draftmode_set and fixed_pdf_draftmode > 0 then begin
+ fixed_pdf_draftmode_set := true;
+ pdf_compress_level := 0;
+ fixed_pdf_objcompresslevel := 0;
+ end;
+end;
+
+@ |pdf_ship_out| is used instead of |ship_out| to shipout a box to PDF
+output. If |shipping_page| is not set then the output will be a Form object,
+otherwise it will be a Page object.
+
+@p procedure pdf_ship_out(p: pointer; shipping_page: boolean); {output the box |p|}
+label done, done1;
+var i,j,k:integer; {general purpose accumulators}
+save_font_list: pointer; {to save |pdf_font_list| during flushing pending forms}
+save_obj_list: pointer; {to save |pdf_obj_list|}
+save_ximage_list: pointer; {to save |pdf_ximage_list|}
+save_xform_list: pointer; {to save |pdf_xform_list|}
+save_image_procset: integer; {to save |pdf_image_procset|}
+save_text_procset: integer; {to save |pdf_text_procset|}
+save_cur_page_height: scaled; {to save |cur_page_height| during flushing pending forms}
+pdf_last_resources: integer; {pointer to most recently generated Resources object}
+pre_callback_id:integer;
+post_callback_id:integer;
+ret:boolean;
+begin
+pre_callback_id:=callback_defined(start_page_number_callback);
+post_callback_id:=callback_defined(stop_page_number_callback);
+if (tracing_output>0)and(pre_callback_id=0) then
+ begin print_nl(""); print_ln;
+ print("Completed box being shipped out");
+@.Completed box...@>
+ end;
+if not init_pdf_output then begin
+ @<Initialize variables for \.{PDF} output@>;
+ init_pdf_output := true;
+end;
+is_shipping_page := shipping_page;
+if shipping_page then begin
+ if pre_callback_id>0 then
+ ret:=run_callback(pre_callback_id,'->')
+ else begin
+ if term_offset>max_print_line-9 then print_ln
+ else if (term_offset>0)or(file_offset>0) then print_char(" ");
+ print_char("["); j:=9;
+ while (count(j)=0)and(j>0) do decr(j);
+ for k:=0 to j do
+ begin print_int(count(k));
+ if k<j then print_char(".");
+ end;
+ end;
+ update_terminal;
+end;
+if (tracing_output>0)and(post_callback_id=0) then
+ begin if shipping_page then print_char("]");
+ begin_diagnostic; show_box(p); end_diagnostic(true);
+ end;
+@<(\pdfTeX) Ship box |p| out@>;
+if (tracing_output<=0)and(post_callback_id=0) and shipping_page then
+ print_char("]");
+dead_cycles:=0;
+update_terminal; {progress report}
+@<Flush the box from memory, showing statistics if requested@>;
+if post_callback_id>0 then
+ ret:=run_callback(post_callback_id,'->');
+end;
+
+@ @<(\pdfTeX) Ship box |p| out@>=
+@<Update the values of |max_h| and |max_v|; but if the page is too large,
+ |goto done|@>;
+@<Initialize variables as |pdf_ship_out| begins@>;
+if type(p)=vlist_node then pdf_vlist_out@+else pdf_hlist_out;
+if shipping_page then
+ incr(total_pages);
+cur_s:=-1;
+@<Finish shipping@>;
+done:
+
+@ @<Initialize variables as |pdf_ship_out| begins@>=
+fix_pdfoutput;
+temp_ptr:=p;
+prepare_mag;
+pdf_last_resources := pdf_new_objnum;
+@<Reset resource lists@>;
+dvi_direction:=page_direction;
+@<Calculate PDF page dimensions and margins@>;
+if not shipping_page then begin
+ pdf_begin_dict(pdf_cur_form, 0);
+ pdf_last_stream := pdf_cur_form;
+ @<Write out Form stream header@>;
+end
+else begin
+ pdf_last_page := get_obj(obj_type_page, total_pages + 1, 0);
+ obj_aux(pdf_last_page) := 1; {mark that this page has beed created}
+ pdf_new_dict(obj_type_others, 0, 0);
+ pdf_last_stream := obj_ptr;
+ @<Reset PDF mark lists@>;
+end;
+@<Start stream of page/form contents@>
+
+@ @<Reset resource lists@>=
+pdf_font_list := null;
+pdf_obj_list := null;
+pdf_xform_list := null;
+pdf_ximage_list := null;
+pdf_text_procset := false;
+pdf_image_procset := 0
+
+@ @<Reset PDF mark lists@>=
+pdf_annot_list := null;
+pdf_link_list := null;
+pdf_dest_list := null;
+pdf_bead_list := null;
+last_thread := null
+
+@ @<Calculate PDF page dimensions and margins@>=
+if is_shipping_page then begin
+ if page_width > 0 then
+ cur_page_width := page_width
+ else
+ cur_page_width := width(p) + 2 * pdf_h_offset;
+ if page_height > 0 then
+ cur_page_height := page_height
+ else
+ cur_page_height := height(p) + depth(p) + 2 * pdf_v_offset;
+ if page_bottom_offset <> 0 then
+ cur_bottom_offset := page_bottom_offset
+ else
+ cur_bottom_offset := one_inch;
+ if page_right_offset <> 0 then
+ cur_right_offset := page_right_offset
+ else
+ cur_right_offset := one_inch;
+ cur_h := pdf_h_offset;
+ cur_v := height(p) + pdf_v_offset;
+ case box_direction(dvi_direction) of
+ dir_TL_,dir_LT_: begin end;
+ dir_TR_,dir_RT_: begin cur_h:=cur_page_width-cur_right_offset; end;
+ dir_RB_,dir_BR_: begin cur_h:=cur_page_width-cur_right_offset; cur_v:=-cur_bottom_offset; end;
+ dir_BL_,dir_LB_: begin cur_v:=-cur_bottom_offset; end;
+ end;
+end
+else begin
+ cur_page_width := width(p);
+ cur_page_height := height(p) + depth(p);
+ cur_h := 0;
+ cur_v := height(p);
+end;
+pdf_origin_h := 0;
+pdf_origin_v := cur_page_height;
+
+@ Here we write out the header for Form.
+
+@<Write out Form stream header@>=
+pdf_print_ln("/Type /XObject");
+pdf_print_ln("/Subtype /Form");
+if obj_xform_attr(pdf_cur_form) <> null then begin
+ pdf_print_toks_ln(obj_xform_attr(pdf_cur_form));
+ delete_toks(obj_xform_attr(pdf_cur_form));
+end;
+pdf_print("/BBox [");
+pdf_print("0 0 ");
+pdf_print_bp(cur_page_width); pdf_out(" ");
+pdf_print_bp(cur_page_height); pdf_print_ln("]");
+pdf_print_ln("/FormType 1");
+pdf_print_ln("/Matrix [1 0 0 1 0 0]");
+pdf_indirect_ln("Resources", pdf_last_resources)
+
+@ @<Start stream of page/form contents@>=
+pdf_begin_stream;
+if shipping_page then begin
+ @<Adjust transformation matrix for the magnification ratio@>;
+end;
+pdfshipoutbegin(shipping_page);
+if shipping_page then
+ pdf_out_colorstack_startpage;
+
+
+@ @<Adjust transformation matrix for the magnification ratio@>=
+prepare_mag;
+if mag <> 1000 then begin
+ pdf_print_real(mag, 3);
+ pdf_print(" 0 0 ");
+ pdf_print_real(mag, 3);
+ pdf_print_ln(" 0 0 cm");
+end
+
+@ @<Finish shipping@>=
+@<Finish stream of page/form contents@>;
+if shipping_page then begin
+ @<Write out page object@>;
+end;
+@<Write out resource lists@>;
+if shipping_page then begin
+ @<Write out pending PDF marks@>;
+end;
+@<Write out resources dictionary@>;
+@<Flush resource lists@>;
+if shipping_page then begin
+ @<Flush PDF mark lists@>;
+end
+
+@ @<Finish stream of page/form contents@>=
+pdf_end_text;
+pdfshipoutend(shipping_page);
+pdf_end_stream
+
+@ @<Write out resource lists@>=
+@<Write out pending raw objects@>;
+@<Write out pending forms@>;
+@<Write out pending images@>
+
+@ @<Write out resources dictionary@>=
+pdf_begin_dict(pdf_last_resources, 1);
+@<Print additional resources@>;
+@<Generate font resources@>;
+@<Generate XObject resources@>;
+@<Generate ProcSet@>;
+pdf_end_dict
+
+@ @<Print additional resources@>=
+if shipping_page then begin
+ if pdf_page_resources <> null then
+ pdf_print_toks_ln(pdf_page_resources);
+end
+else begin
+ if obj_xform_resources(pdf_cur_form) <> null then begin
+ pdf_print_toks_ln(obj_xform_resources(pdf_cur_form));
+ delete_toks(obj_xform_resources(pdf_cur_form));
+ end;
+end
+
+@ In the end of shipping out a page we reset all the lists holding objects
+have been created during the page shipping.
+
+@d delete_toks(#) == begin delete_token_ref(#); # := null; end
+
+@<Flush resource lists@>=
+flush_list(pdf_font_list);
+flush_list(pdf_obj_list);
+flush_list(pdf_xform_list);
+flush_list(pdf_ximage_list)
+
+@ @<Flush PDF mark lists@>=
+flush_list(pdf_annot_list);
+flush_list(pdf_link_list);
+flush_list(pdf_dest_list);
+flush_list(pdf_bead_list)
+
+@ @<Generate font resources@>=
+if pdf_font_list <> null then begin
+ pdf_print("/Font << ");
+ k := pdf_font_list;
+ while k <> null do begin
+ pdf_print("/F");
+ set_ff(info(k));
+ pdf_print_int(ff);
+ pdf_print_resname_prefix;
+ pdf_out(" ");
+ pdf_print_int(pdf_font_num(ff));
+ pdf_print(" 0 R ");
+ k := link(k);
+ end;
+ pdf_print_ln(">>");
+ pdf_text_procset := true;
+end
+
+@ @<Generate XObject resources@>=
+if (pdf_xform_list <> null) or (pdf_ximage_list <> null) then begin
+ pdf_print("/XObject << ");
+ k := pdf_xform_list;
+ while k <> null do begin
+ pdf_print("/Fm");
+ pdf_print_int(obj_info(info(k)));
+ pdf_print_resname_prefix;
+ pdf_out(" ");
+ pdf_print_int(info(k));
+ pdf_print(" 0 R ");
+ k := link(k);
+ end;
+ k := pdf_ximage_list;
+ while k <> null do begin
+ pdf_print("/Im");
+ pdf_print_int(image_index(obj_data_ptr(info(k))));
+ pdf_print_resname_prefix;
+ pdf_out(" ");
+ pdf_print_int(info(k));
+ pdf_print(" 0 R ");
+ update_image_procset(obj_data_ptr(info(k)));
+ k := link(k);
+ end;
+ pdf_print_ln(">>");
+end
+
+@ @<Generate ProcSet@>=
+pdf_print("/ProcSet [ /PDF");
+if pdf_text_procset then
+ pdf_print(" /Text");
+if check_image_b(pdf_image_procset) then
+ pdf_print(" /ImageB");
+if check_image_c(pdf_image_procset) then
+ pdf_print(" /ImageC");
+if check_image_i(pdf_image_procset) then
+ pdf_print(" /ImageI");
+pdf_print_ln(" ]")
+
+@ @<Write out page object@>=
+pdf_begin_dict(pdf_last_page, 1);
+pdf_print_ln("/Type /Page");
+pdf_indirect_ln("Contents", pdf_last_stream);
+pdf_indirect_ln("Resources", pdf_last_resources);
+pdf_print("/MediaBox [0 0 ");
+pdf_print_mag_bp(cur_page_width); pdf_out(" ");
+pdf_print_mag_bp(cur_page_height);
+pdf_print_ln("]");
+if pdf_page_attr <> null then
+ pdf_print_toks_ln(pdf_page_attr);
+@<Generate parent pages object@>;
+@<Generate array of annotations or beads in page@>;
+pdf_end_dict
+
+@ @<Generate parent pages object@>=
+if total_pages mod pages_tree_kids_max = 1 then begin
+ pdf_create_obj(obj_type_pages, pages_tree_kids_max);
+ pdf_last_pages := obj_ptr;
+end;
+pdf_indirect_ln("Parent", pdf_last_pages)
+
+@ @<Generate array of annotations or beads in page@>=
+if (pdf_annot_list <> null) or (pdf_link_list <> null) then begin
+ pdf_print("/Annots [ ");
+ k := pdf_annot_list;
+ while k <> null do begin
+ pdf_print_int(info(k));
+ pdf_print(" 0 R ");
+ k := link(k);
+ end;
+ k := pdf_link_list;
+ while k <> null do begin
+ pdf_print_int(info(k));
+ pdf_print(" 0 R ");
+ k := link(k);
+ end;
+ pdf_print_ln("]");
+end;
+if pdf_bead_list <> null then begin
+ k := pdf_bead_list;
+ pdf_print("/B [ ");
+ while k <> null do begin
+ pdf_print_int(info(k));
+ pdf_print(" 0 R ");
+ k := link(k);
+ end;
+ pdf_print_ln("]");
+end
+
+@ @<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure pdf_write_obj(n: integer); {write a raw PDF object}
+var s: str_number;
+ f: byte_file;
+ data_size:integer; {total size of the data file}
+ data_cur:integer; {index into |data_buffer|}
+ data_buffer:^real_eight_bits; {byte buffer for data files}
+ file_opened:boolean;
+ k:integer;
+ res:boolean;
+ fnam: str_number;
+ callback_id:integer;
+begin
+ s := tokens_to_string(obj_obj_data(n));
+ delete_toks(obj_obj_data(n));
+ if obj_obj_is_stream(n) > 0 then begin
+ pdf_begin_dict(n, 0);
+ if obj_obj_stream_attr(n) <> null then begin
+ pdf_print_toks_ln(obj_obj_stream_attr(n));
+ delete_toks(obj_obj_stream_attr(n));
+ end;
+ pdf_begin_stream;
+ end
+ else
+ pdf_begin_obj(n, 1);
+ if obj_obj_is_file(n) > 0 then begin
+ data_size:=0; data_cur:=0; data_buffer:=0;
+ pack_file_name(s,"","");
+ callback_id:=callback_defined(find_data_file_callback);
+ if callback_id>0 then begin
+ res := run_callback(callback_id,'S->s',stringcast(nameoffile+1),addressof(fnam));
+ if (res)and(fnam<>0)and(length(fnam)>0) then begin
+ @<Fixup |nameoffile| after callback@>;
+ end;
+ end;
+ callback_id:=callback_defined(read_data_file_callback);
+ if callback_id>0 then begin
+ file_opened := false;
+ res := run_callback(callback_id,'S->bSd',stringcast(nameoffile+1),
+ addressof(file_opened), addressof(data_buffer),addressof(data_size));
+ if not file_opened then pdf_error("ext5", "cannot open file for embedding");
+ end
+ else begin
+ if not tex_b_open_in(f) then
+ pdf_error("ext5", "cannot open file for embedding");
+ res := read_data_file(f,addressof(data_buffer),addressof(data_size));
+ b_close(f);
+ end;
+ if not data_size then pdf_error("ext5", "empty file for embedding");
+ if not res then pdf_error("ext5", "error reading file for embedding");
+ print("<<");
+ print(s);
+ while data_cur<data_size do begin
+ pdf_out(data_buffer[data_cur]);
+ incr(data_cur);
+ end;
+ if data_buffer<>0 then libcfree(data_buffer);
+ print(">>");
+ end
+ else if obj_obj_is_stream(n) > 0 then
+ pdf_print(s)
+ else
+ pdf_print_ln(s);
+ if obj_obj_is_stream(n) > 0 then
+ pdf_end_stream
+ else
+ pdf_end_obj;
+ flush_str(s);
+end;
+
+@ @<Write out pending raw objects@>=
+if pdf_obj_list <> null then begin
+ k := pdf_obj_list;
+ while k <> null do begin
+ if not is_obj_written(info(k)) then
+ pdf_write_obj(info(k));
+ k := link(k);
+ end;
+end
+
+@ When flushing pending forms we need to save and restore resource lists
+(|pdf_font_list|, |pdf_obj_list|, |pdf_xform_list| and |pdf_ximage_list|),
+which are also used by page shipping.
+Saving and restoring |cur_page_height| is needed for proper
+writing out pending PDF marks.
+
+@<Write out pending forms@>=
+if pdf_xform_list <> null then begin
+ k := pdf_xform_list;
+ while k <> null do begin
+ if not is_obj_written(info(k)) then begin
+ pdf_cur_form := info(k);
+ @<Save resource lists@>;
+ @<Reset resource lists@>;
+ save_cur_page_height := cur_page_height;
+ pdf_ship_out(obj_xform_box(pdf_cur_form), false);
+ cur_page_height := save_cur_page_height;
+ @<Restore resource lists@>;
+ end;
+ k := link(k);
+ end;
+end
+
+@ @<Save resource lists@>=
+save_font_list := pdf_font_list;
+save_obj_list := pdf_obj_list;
+save_xform_list := pdf_xform_list;
+save_ximage_list := pdf_ximage_list;
+save_text_procset := pdf_text_procset;
+save_image_procset := pdf_image_procset
+
+@ @<Restore resource lists@>=
+pdf_font_list := save_font_list;
+pdf_obj_list := save_obj_list;
+pdf_xform_list := save_xform_list;
+pdf_ximage_list := save_ximage_list;
+pdf_text_procset := save_text_procset;
+pdf_image_procset := save_image_procset
+
+@ @<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure pdf_write_image(n: integer); {write an image}
+begin
+ pdf_begin_dict(n, 0);
+ if fixed_pdf_draftmode = 0 then write_image(obj_data_ptr(n));
+end;
+
+@ @<Write out pending images@>=
+if pdf_ximage_list <> null then begin
+ k := pdf_ximage_list;
+ while k <> null do begin
+ if not is_obj_written(info(k)) then
+ pdf_write_image(info(k));
+ k := link(k);
+ end;
+end
+
+@ @<Write out pending PDF marks@>=
+pdf_origin_h := 0;
+pdf_origin_v := cur_page_height;
+@<Write out PDF annotations@>;
+@<Write out PDF link annotations@>;
+@<Write out PDF mark destinations@>;
+@<Write out PDF bead rectangle specifications@>
+
+@ @<Write out PDF annotations@>=
+if pdf_annot_list <> null then begin
+ k := pdf_annot_list;
+ while k <> null do begin
+ i := obj_annot_ptr(info(k)); {|i| points to |pdf_annot_node|}
+ pdf_begin_dict(info(k), 1);
+ pdf_print_ln("/Type /Annot");
+ pdf_print_toks_ln(pdf_annot_data(i));
+ pdf_rectangle(pdf_left(i), pdf_top(i), pdf_right(i), pdf_bottom(i));
+ pdf_end_dict;
+ k := link(k);
+ end;
+end
+
+@ @<Write out PDF link annotations@>=
+if pdf_link_list <> null then begin
+k := pdf_link_list;
+while k <> null do begin
+ i := obj_annot_ptr(info(k));
+ pdf_begin_dict(info(k), 1);
+ pdf_print_ln("/Type /Annot");
+ if pdf_link_attr(i) <> null then
+ pdf_print_toks_ln(pdf_link_attr(i));
+ pdf_rectangle(pdf_left(i), pdf_top(i), pdf_right(i), pdf_bottom(i));
+ if pdf_action_type(pdf_link_action(i)) <> pdf_action_user
+ then begin
+ pdf_print_ln("/Subtype /Link");
+ pdf_print("/A ");
+ end;
+ write_action(pdf_link_action(i));
+ pdf_end_dict;
+ k := link(k);
+ end;
+ @<Flush |pdf_start_link_node|'s created by |append_link|@>;
+end
+
+@ @<Flush |pdf_start_link_node|'s created by |append_link|@>=
+k := pdf_link_list;
+while k <> null do begin
+ i := obj_annot_ptr(info(k));
+ {nodes with |subtype = pdf_link_data_node| were created by |append_link| and
+ must be flushed here, as they are not linked in any list}
+ if subtype(i) = pdf_link_data_node then
+ flush_node(i);
+ k := link(k);
+end
+
+@ @<Write out PDF mark destinations@>=
+if pdf_dest_list <> null then begin
+ k := pdf_dest_list;
+ while k <> null do begin
+ if is_obj_written(info(k)) then
+ pdf_error("ext5",
+ "destination has been already written (this shouldn't happen)")
+ else begin
+ i := obj_dest_ptr(info(k));
+ if pdf_dest_named_id(i) > 0 then begin
+ pdf_begin_dict(info(k), 1);
+ pdf_print("/D ");
+ end
+ else
+ pdf_begin_obj(info(k), 1);
+ pdf_out("["); pdf_print_int(pdf_last_page); pdf_print(" 0 R ");
+ case pdf_dest_type(i) of
+ pdf_dest_xyz: begin
+ pdf_print("/XYZ ");
+ pdf_print_mag_bp(pdf_x(pdf_left(i))); pdf_out(" ");
+ pdf_print_mag_bp(pdf_y(pdf_top(i))); pdf_out(" ");
+ if pdf_dest_xyz_zoom(i) = null then
+ pdf_print("null")
+ else begin
+ pdf_print_int(pdf_dest_xyz_zoom(i) div 1000);
+ pdf_out(".");
+ pdf_print_int((pdf_dest_xyz_zoom(i) mod 1000));
+ end;
+ end;
+ pdf_dest_fit:
+ pdf_print("/Fit");
+ pdf_dest_fith: begin
+ pdf_print("/FitH ");
+ pdf_print_mag_bp(pdf_y(pdf_top(i)));
+ end;
+ pdf_dest_fitv: begin
+ pdf_print("/FitV ");
+ pdf_print_mag_bp(pdf_x(pdf_left(i)));
+ end;
+ pdf_dest_fitb:
+ pdf_print("/FitB");
+ pdf_dest_fitbh: begin
+ pdf_print("/FitBH ");
+ pdf_print_mag_bp(pdf_y(pdf_top(i)));
+ end;
+ pdf_dest_fitbv: begin
+ pdf_print("/FitBV ");
+ pdf_print_mag_bp(pdf_x(pdf_left(i)));
+ end;
+ pdf_dest_fitr: begin
+ pdf_print("/FitR ");
+ pdf_print_rect_spec(i);
+ end;
+ othercases pdf_error("ext5", "unknown dest type");
+ endcases;
+ pdf_print_ln("]");
+ if pdf_dest_named_id(i) > 0 then
+ pdf_end_dict
+ else
+ pdf_end_obj;
+ end;
+ k := link(k);
+ end;
+end
+
+@ @<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure pdf_print_rect_spec(r: pointer); {prints a rect spec}
+begin
+ pdf_print_mag_bp(pdf_x(pdf_left(r)));
+ pdf_out(" ");
+ pdf_print_mag_bp(pdf_y(pdf_bottom(r)));
+ pdf_out(" ");
+ pdf_print_mag_bp(pdf_x(pdf_right(r)));
+ pdf_out(" ");
+ pdf_print_mag_bp(pdf_y(pdf_top(r)));
+end;
+
+@ @<Write out PDF bead rectangle specifications@>=
+if pdf_bead_list <> null then begin
+ k := pdf_bead_list;
+ while k <> null do begin
+ pdf_new_obj(obj_type_others, 0, 1);
+ pdf_out("[");
+ i := obj_bead_data(info(k)); {pointer to a whatsit or whatsit-like node}
+ pdf_print_rect_spec(i);
+ if subtype(i) = pdf_thread_data_node then {thanh says it mis be destroyed here}
+ flush_node(i);
+ pdf_print_ln("]");
+ obj_bead_rect(info(k)) := obj_ptr; {rewrite |obj_bead_data|}
+ pdf_end_obj;
+ k := link(k);
+ end;
+end
+
+@ In the end we must flush PDF objects that cannot be written out
+immediately after shipping out pages.
+
+@ @<Output outlines@>=
+if pdf_first_outline <> 0 then begin
+ pdf_new_dict(obj_type_others, 0, 1);
+ outlines := obj_ptr;
+ l := pdf_first_outline; k := 0;
+ repeat
+ incr(k);
+ a := open_subentries(l);
+ if obj_outline_count(l) > 0 then
+ k := k + a;
+ obj_outline_parent(l) := obj_ptr;
+ l := obj_outline_next(l);
+ until l = 0;
+ pdf_print_ln("/Type /Outlines");
+ pdf_indirect_ln("First", pdf_first_outline);
+ pdf_indirect_ln("Last", pdf_last_outline);
+ pdf_int_entry_ln("Count", k);
+ pdf_end_dict;
+ @<Output PDF outline entries@>;
+end
+else
+ outlines := 0
+
+@ @<Output PDF outline entries@>=
+k := head_tab[obj_type_outline];
+while k <> 0 do begin
+ if obj_outline_parent(k) = pdf_parent_outline then begin
+ if obj_outline_prev(k) = 0 then
+ pdf_first_outline := k;
+ if obj_outline_next(k) = 0 then
+ pdf_last_outline := k;
+ end;
+ pdf_begin_dict(k, 1);
+ pdf_indirect_ln("Title", obj_outline_title(k));
+ pdf_indirect_ln("A", obj_outline_action_objnum(k));
+ if obj_outline_parent(k) <> 0 then
+ pdf_indirect_ln("Parent", obj_outline_parent(k));
+ if obj_outline_prev(k) <> 0 then
+ pdf_indirect_ln("Prev", obj_outline_prev(k));
+ if obj_outline_next(k) <> 0 then
+ pdf_indirect_ln("Next", obj_outline_next(k));
+ if obj_outline_first(k) <> 0 then
+ pdf_indirect_ln("First", obj_outline_first(k));
+ if obj_outline_last(k) <> 0 then
+ pdf_indirect_ln("Last", obj_outline_last(k));
+ if obj_outline_count(k) <> 0 then
+ pdf_int_entry_ln("Count", obj_outline_count(k));
+ if obj_outline_attr(k) <> 0 then begin
+ pdf_print_toks_ln(obj_outline_attr(k));
+ delete_toks(obj_outline_attr(k));
+ end;
+ pdf_end_dict;
+ k := obj_link(k);
+end
+
+@ @<Output article threads@>=
+if head_tab[obj_type_thread] <> 0 then begin
+ pdf_new_obj(obj_type_others, 0, 1);
+ threads := obj_ptr;
+ pdf_out("[");
+ k := head_tab[obj_type_thread];
+ while k <> 0 do begin
+ pdf_print_int(k);
+ pdf_print(" 0 R ");
+ k := obj_link(k);
+ end;
+ remove_last_space;
+ pdf_print_ln("]");
+ pdf_end_obj;
+ k := head_tab[obj_type_thread];
+ while k <> 0 do begin
+ out_thread(k);
+ k := obj_link(k);
+ end;
+end
+else
+ threads := 0
+
+@ Now we are ready to declare our new procedure |ship_out|. It will call
+|pdf_ship_out| if the integer parameter |pdf_output| is positive; otherwise it
+will call |dvi_ship_out|, which is the \TeX\ original |ship_out|.
+
+@p procedure ship_out(p:pointer); {output the box |p|}
+begin
+ fix_pdfoutput;
+ if pdf_output > 0 then
+ pdf_ship_out(p, true)
+ else
+ dvi_ship_out(p);
+end;
+
+@ @<Initialize variables for \.{PDF} output@>=
+check_pdfminorversion;
+prepare_mag;
+fixed_decimal_digits := fix_int(pdf_decimal_digits, 0, 4);
+min_bp_val :=
+ divide_scaled(one_hundred_bp, ten_pow[fixed_decimal_digits + 2], 0);
+if pdf_pk_resolution = 0 then {if not set from format file or by user}
+ pdf_pk_resolution := pk_dpi; {take it from \.{texmf.cnf}}
+fixed_pk_resolution := fix_int(pdf_pk_resolution, 72, 8000);
+pk_scale_factor :=
+ divide_scaled(72, fixed_pk_resolution, 5 + fixed_decimal_digits);
+if not callback_defined(read_pk_file_callback) then begin
+ if pdf_pk_mode <> null then begin
+ kpseinitprog('PDFTEX', fixed_pk_resolution,
+ makecstring(tokens_to_string(pdf_pk_mode)), nil);
+ flush_string;
+ end else
+ kpseinitprog('PDFTEX', fixed_pk_resolution, nil, nil);
+ if not kpsevarvalue('MKTEXPK') then
+ kpsesetprogramenabled (kpsepkformat, 1, kpsesrccmdline);
+ end;
+set_job_id(year, month, day, time);
+if (pdf_unique_resname > 0) and (pdf_resname_prefix = 0) then
+ pdf_resname_prefix := get_resname_prefix
+
+@ Finishing the PDF output file.
+
+The following procedures sort the table of destination names
+@p function str_less_str(s1, s2: str_number): boolean; {compare two strings}
+var c1, c2: pool_pointer;
+ l, i: integer;
+begin
+ c1 := str_start_macro(s1);
+ c2 := str_start_macro(s2);
+ if length(s1) < length(s2) then
+ l := length(s1)
+ else
+ l := length(s2);
+ i := 0;
+ while (i < l) and (str_pool[c1 + i] = str_pool[c2 + i]) do
+ incr(i);
+ if ((i < l) and (str_pool[c1 + i] < str_pool[c2 + i])) or
+ ((i = l) and (length(s1) < length(s2))) then
+ str_less_str := true
+ else
+ str_less_str := false;
+end;
+
+procedure sort_dest_names(l, r: integer); {sorts |dest_names| by names}
+var i, j: integer;
+ s: str_number;
+ e: dest_name_entry;
+begin
+ i := l;
+ j := r;
+ s := dest_names[(l + r) div 2].objname;
+ repeat
+ while str_less_str(dest_names[i].objname, s) do
+ incr(i);
+ while str_less_str(s, dest_names[j].objname) do
+ decr(j);
+ if i <= j then begin
+ e := dest_names[i];
+ dest_names[i] := dest_names[j];
+ dest_names[j] := e;
+ incr(i);
+ decr(j);
+ end;
+ until i > j;
+ if l < j then
+ sort_dest_names(l, j);
+ if i < r then
+ sort_dest_names(i, r);
+end;
+
+@ Now the finish of PDF output file. At this moment all Page objects
+are already written completely to PDF output file.
+
+@<Finish the PDF file@>=
+if total_pages=0 then begin
+ if callback_id=0 then
+ print_nl("No pages of output.")
+ else
+ res:=run_callback(callback_id,'->');
+ @.No pages of output@>
+ if pdf_gone > 0 then
+ garbage_warning;
+end
+else begin
+ if fixed_pdf_draftmode = 0 then begin
+ pdf_flush; {to make sure that the output file name has been already
+ created}
+ if total_pages mod pages_tree_kids_max <> 0 then
+ obj_info(pdf_last_pages) := total_pages mod pages_tree_kids_max;
+ {last pages object may have less than |pages_tree_kids_max| children}
+ flush_jbig2_page0_objects; {flush page 0 objects from JBIG2 images, if any}
+ @<Check for non-existing pages@>;
+ @<Reverse the linked list of Page and Pages objects@>;
+ @<Check for non-existing destinations@>;
+ @<Output fonts definition@>;
+ @<Output pages tree@>;
+ @<Output outlines@>;
+ @<Output name tree@>;
+ @<Output article threads@>;
+ @<Output the catalog object@>;
+ pdf_print_info; {last candidate for object stream}
+ if pdf_os_enable then begin
+ pdf_os_switch(true);
+ pdf_os_write_objstream;
+ pdf_flush;
+ pdf_os_switch(false);
+ @<Output the cross-reference stream dictionary@>;
+ pdf_flush;
+ end else begin
+ @<Output the |obj_tab|@>;
+ end;
+ @<Output the trailer@>;
+ pdf_flush;
+ if callback_id=0 then begin
+ print_nl("Output written on "); print_file_name(0, output_file_name, 0);
+ @.Output written on x@>
+ print(" ("); print_int(total_pages); print(" page");
+ if total_pages<>1 then print_char("s");
+ print(", "); print_int(pdf_offset); print(" bytes).");
+ end
+ else
+ res:=run_callback(callback_id,'->');
+ end;
+ libpdffinish;
+ if fixed_pdf_draftmode = 0 then b_close(pdf_file)
+ else pdf_warning(0, "\pdfdraftmode enabled, not changing output pdf", true, true)
+end
+
+@ Destinations that have been referenced but don't exists have
+|obj_dest_ptr=null|. Leaving them undefined might cause troubles for
+PDF browsers, so we need to fix them.
+
+@p procedure pdf_fix_dest(k: integer);
+begin
+ if obj_dest_ptr(k) <> null then
+ return;
+ pdf_warning("dest", "", false, false);
+ if obj_info(k) < 0 then begin
+ print("name{");
+ print(-obj_info(k));
+ print("}");
+ end
+ else begin
+ print("num");
+ print_int(obj_info(k));
+ end;
+ print(" has been referenced but does not exist, replaced by a fixed one");
+ print_ln; print_ln;
+ pdf_begin_obj(k, 1);
+ pdf_out("[");
+ pdf_print_int(head_tab[obj_type_page]);
+ pdf_print_ln(" 0 R /Fit]");
+ pdf_end_obj;
+end;
+
+@ @<Check for non-existing destinations@>=
+k := head_tab[obj_type_dest];
+while k <> 0 do begin
+ pdf_fix_dest(k);
+ k := obj_link(k);
+end
+
+@ @<Check for non-existing pages@>=
+k := head_tab[obj_type_page];
+while obj_aux(k) = 0 do begin
+ pdf_warning("dest", "Page ", false, false);
+ print_int(obj_info(k));
+ print(" has been referenced but does not exist!");
+ print_ln; print_ln;
+ k := obj_link(k);
+end;
+head_tab[obj_type_page] := k
+
+@ @<Reverse the linked list of Page and Pages objects@>=
+k := head_tab[obj_type_page];
+l := 0;
+repeat
+ i := obj_link(k);
+ obj_link(k) := l;
+ l := k;
+ k := i;
+until k = 0;
+head_tab[obj_type_page] := l;
+k := head_tab[obj_type_pages];
+pages_tail := k;
+l := 0;
+repeat
+ i := obj_link(k);
+ obj_link(k) := l;
+ l := k;
+ k := i;
+until k = 0;
+head_tab[obj_type_pages] := l
+
+@ @<Output fonts definition@>=
+for k := 1 to max_font_id do
+ if font_used(k) and (pdf_font_num(k) < 0) then begin
+ i := -pdf_font_num(k);
+ pdfassert(pdf_font_num(i) > 0);
+ for j := font_bc(k) to font_ec(k) do
+ if pdf_char_marked(k, j) then
+ pdf_mark_char(i, j);
+ if (pdf_font_attr(i) = 0) and (pdf_font_attr(k) <> 0) then
+ set_pdf_font_attr(i, pdf_font_attr(k))
+ else if (pdf_font_attr(k) = 0) and (pdf_font_attr(i) <> 0) then
+ set_pdf_font_attr(k,pdf_font_attr(i))
+ else if (pdf_font_attr(i) <> 0) and (pdf_font_attr(k) <> 0) and
+ not str_eq_str(pdf_font_attr(i), pdf_font_attr(k)) then begin
+ pdf_warning("\pdffontattr", "fonts ", false, false);
+ print_font_identifier(i);
+ print(" and ");
+ print_font_identifier(k);
+ print(" has conflicting attributes"); print_ln; print_ln;
+ end;
+ end;
+fixed_gen_tounicode := pdf_gen_tounicode;
+k := head_tab[obj_type_font];
+while k <> 0 do begin
+ f := obj_info(k);
+ pdfassert(pdf_font_num(f) > 0);
+ do_pdf_font(k, f);
+ k := obj_link(k);
+end;
+write_fontstuff
+
+@ We will generate in each single step the parents of all Pages/Page objects in
+the previous level. These new generated Pages object will create a new level of
+Pages tree. We will repeat this until search only one Pages object. This one
+will be the Root object.
+
+@<Output pages tree@>=
+a := sys_obj_ptr + 1; {all Pages objects whose children are not Page objects
+ should have index greater than |a|}
+l := head_tab[obj_type_pages]; {|l| is the index of current Pages object
+ which is being output}
+k := head_tab[obj_type_page]; {|k| is the index of current child of |l|}
+b := 0;
+repeat
+ i := 0; {counter of Pages object in current level}
+ c := 0; {first Pages object in previous level}
+ if obj_link(l) = 0 then
+ is_root := true {only Pages object; total pages is
+ not greater than |pages_tree_kids_max|}
+ else
+ is_root := false;
+ repeat
+ if not is_root then begin
+ if i mod pages_tree_kids_max = 0 then begin {create a new Pages object
+ for next level}
+ pdf_last_pages := pdf_new_objnum;
+ if c = 0 then
+ c := pdf_last_pages;
+ obj_link(pages_tail) := pdf_last_pages;
+ pages_tail := pdf_last_pages;
+ obj_link(pdf_last_pages) := 0;
+ obj_info(pdf_last_pages) := obj_info(l);
+ end
+ else
+ obj_info(pdf_last_pages) := obj_info(pdf_last_pages) +
+ obj_info(l);
+ end;
+ @<Output the current Pages object in this level@>;
+ incr(i);
+ l := obj_link(l);
+ until (l = c);
+ b := c;
+ if l = 0 then
+ goto done;
+until false;
+done:
+
+@ @<Output the current Pages object in this level@>=
+pdf_begin_dict(l, 1);
+pdf_print_ln("/Type /Pages");
+pdf_int_entry_ln("Count", obj_info(l));
+if not is_root then
+ pdf_indirect_ln("Parent", pdf_last_pages);
+pdf_print("/Kids [");
+j := 0;
+repeat
+ pdf_print_int(k);
+ pdf_print(" 0 R ");
+ k := obj_link(k);
+ incr(j);
+until ((l < a) and (j = obj_info(l))) or
+ (k = 0) or ((k = b) and (b <> 0)) or
+ (j = pages_tree_kids_max);
+remove_last_space;
+pdf_print_ln("]");
+if k = 0 then begin
+ k := head_tab[obj_type_pages];
+ head_tab[obj_type_pages] := 0;
+end;
+if is_root and (pdf_pages_attr <> null) then
+ pdf_print_toks_ln(pdf_pages_attr);
+pdf_end_dict;
+
+@ The name tree is very similiar to Pages tree so its construction should be
+certain from Pages tree construction. For intermediate node |obj_info| will be
+the first name and |obj_link| will be the last name in \.{\\Limits} array.
+Note that |pdf_dest_names_ptr| will be less than |obj_ptr|, so we test if
+|k < pdf_dest_names_ptr| then |k| is index of leaf in |dest_names|; else
+|k| will be index in |obj_tab| of some intermediate node.
+
+@<Output name tree@>=
+if pdf_dest_names_ptr = 0 then begin
+ dests := 0;
+ goto done1;
+end;
+sort_dest_names(0, pdf_dest_names_ptr - 1);
+names_head := 0;
+names_tail := 0;
+k := 0; {index of current child of |l|; if |k < pdf_dest_names_ptr|
+ then this is pointer to |dest_names| array;
+ otherwise it is the pointer to |obj_tab| (object number)}
+is_names := true; {flag whether Names or Kids}
+b := 0;
+repeat
+ repeat
+ pdf_create_obj(obj_type_others, 0); {create a new node}
+ l := obj_ptr;
+ if b = 0 then
+ b := l; {first in this level}
+ if names_head = 0 then begin
+ names_head := l;
+ names_tail := l;
+ end else begin
+ obj_link(names_tail) := l;
+ names_tail := l;
+ end;
+ obj_link(names_tail) := 0;
+ @<Output the current node in this level@>;
+ until b = 0;
+ if k = l then begin
+ dests := l;
+ goto done1;
+ end;
+until false;
+done1:
+if (dests <> 0) or (pdf_names_toks <> null) then begin
+ pdf_new_dict(obj_type_others, 0, 1);
+ if (dests <> 0) then
+ pdf_indirect_ln("Dests", dests);
+ if pdf_names_toks <> null then begin
+ pdf_print_toks_ln(pdf_names_toks);
+ delete_toks(pdf_names_toks);
+ end;
+ pdf_end_dict;
+ names_tree := obj_ptr;
+end
+else
+ names_tree := 0
+
+@ @<Output the current node in this level@>=
+pdf_begin_dict(l, 1);
+j := 0;
+if is_names then begin
+ obj_info(l) := dest_names[k].objname;
+ pdf_print("/Names [");
+ repeat
+ pdf_print_str(dest_names[k].objname);
+ pdf_out(" ");
+ pdf_print_int(dest_names[k].objnum);
+ pdf_print(" 0 R ");
+ incr(j);
+ incr(k);
+ until (j = name_tree_kids_max) or (k = pdf_dest_names_ptr);
+ remove_last_space;
+ pdf_print_ln("]");
+ obj_aux(l) := dest_names[k - 1].objname;
+ if k = pdf_dest_names_ptr then begin
+ is_names := false;
+ k := names_head;
+ b := 0;
+ end;
+end
+else begin
+ obj_info(l) := obj_info(k);
+ pdf_print("/Kids [");
+ repeat
+ pdf_print_int(k);
+ pdf_print(" 0 R ");
+ incr(j);
+ obj_aux(l) := obj_aux(k);
+ k := obj_link(k);
+ until (j = name_tree_kids_max) or (k = b) or (obj_link(k) = 0);
+ remove_last_space;
+ pdf_print_ln("]");
+ if k = b then
+ b := 0;
+end;
+pdf_print("/Limits [");
+pdf_print_str(obj_info(l));
+pdf_out(" ");
+pdf_print_str(obj_aux(l));
+pdf_print_ln("]");
+pdf_end_dict;
+
+@ @<Output the catalog object@>=
+pdf_new_dict(obj_type_others, 0, 1);
+root := obj_ptr;
+pdf_print_ln("/Type /Catalog");
+pdf_indirect_ln("Pages", pdf_last_pages);
+if threads <> 0 then
+ pdf_indirect_ln("Threads", threads);
+if outlines <> 0 then
+ pdf_indirect_ln("Outlines", outlines);
+if names_tree <> 0 then
+ pdf_indirect_ln("Names", names_tree);
+if pdf_catalog_toks <> null then begin
+ pdf_print_toks_ln(pdf_catalog_toks);
+ delete_toks(pdf_catalog_toks);
+end;
+if pdf_catalog_openaction <> 0 then
+ pdf_indirect_ln("OpenAction", pdf_catalog_openaction);
+pdf_end_dict
+
+@ If the same keys in a dictionary are given several times, then it is not
+defined which value is choosen by an application. Therefore the keys
+|/Producer| and |/Creator| are only set if the token list
+|pdf_info_toks| converted to a string does not contain these key strings.
+
+@p function substr_of_str(s, t: str_number):boolean;
+label continue,exit;
+var j, k, kk: pool_pointer; {running indices}
+begin
+ k:=str_start_macro(t);
+ while (k < str_start_macro(t+1) - length(s)) do begin
+ j:=str_start_macro(s);
+ kk:=k;
+ while (j < str_start_macro(s+1)) do begin
+ if str_pool[j] <> str_pool[kk] then
+ goto continue;
+ incr(j);
+ incr(kk);
+ end;
+ substr_of_str:=true;
+ return;
+ continue: incr(k);
+ end;
+ substr_of_str:=false;
+end;
+
+procedure pdf_print_info; {print info object}
+var s: str_number;
+ creator_given, producer_given, creationdate_given, moddate_given, trapped_given: boolean;
+begin
+ s:="";
+ pdf_new_dict(obj_type_others, 0, 3); {keep Info readable unless explicitely forced}
+ creator_given:=false;
+ producer_given:=false;
+ creationdate_given:=false;
+ moddate_given:=false;
+ trapped_given:=false;
+ if pdf_info_toks <> null then begin
+ s:=tokens_to_string(pdf_info_toks);
+ creator_given:=substr_of_str("/Creator", s);
+ producer_given:=substr_of_str("/Producer", s);
+ creationdate_given:=substr_of_str("/CreationDate", s);
+ moddate_given:=substr_of_str("/ModDate", s);
+ trapped_given:=substr_of_str("/Trapped", s);
+ end;
+ if not producer_given then begin
+ @<Print the Producer key@>;
+ end;
+ if pdf_info_toks <> null then begin
+ if length(s) > 0 then begin
+ pdf_print_ln(s);
+ end;
+ flush_str(s);
+ delete_toks(pdf_info_toks);
+ end;
+ if not creator_given then
+ pdf_str_entry_ln("Creator", "TeX");
+ if not creationdate_given then begin
+ @<Print the CreationDate key@>;
+ end;
+ if not moddate_given then begin
+ @<Print the ModDate key@>;
+ end;
+ if not trapped_given then begin
+ pdf_print_ln("/Trapped /False");
+ end;
+ pdf_str_entry_ln("PTEX.Fullbanner", pdftex_banner);
+ pdf_end_dict;
+end;
+
+@ @<Print the Producer key@>=
+pdf_print("/Producer (luaTeX-");
+pdf_print_int(luatex_version div 100);
+pdf_out(".");
+pdf_print_int(luatex_version mod 100);
+pdf_out(".");
+pdf_print(luatex_revision);
+pdf_print_ln(")")
+
+@ @<Print the CreationDate key@>=
+print_creation_date;
+
+@ @<Print the ModDate key@>=
+print_mod_date;
+
+@ @<Glob...@>=
+@!pdftex_banner: str_number; {the complete banner}
+
+@ @<Output the |obj_tab|@>=
+l := 0;
+for k := 1 to sys_obj_ptr do
+ if obj_offset(k) = 0 then begin
+ obj_link(l) := k;
+ l := k;
+ end;
+obj_link(l) := 0;
+pdf_save_offset := pdf_offset;
+pdf_print_ln("xref");
+pdf_print("0 "); pdf_print_int_ln(obj_ptr + 1);
+pdf_print_fw_int(obj_link(0), 10);
+pdf_print_ln(" 65535 f ");
+for k := 1 to obj_ptr do begin
+ if obj_offset(k) = 0 then begin
+ pdf_print_fw_int(obj_link(k), 10);
+ pdf_print_ln(" 00000 f ");
+ end
+ else begin
+ pdf_print_fw_int(obj_offset(k), 10);
+ pdf_print_ln(" 00000 n ");
+ end;
+end
+
+@ @<Output the cross-reference stream dictionary@>=
+pdf_new_dict(obj_type_others, 0, 0);
+if obj_offset(sys_obj_ptr) > 16777215 then
+ xref_offset_width := 4
+else if obj_offset(sys_obj_ptr) > 65535 then
+ xref_offset_width := 3
+else if obj_offset(sys_obj_ptr) > 255 then
+ xref_offset_width := 2
+else
+ xref_offset_width := 1;
+l := 0;
+for k := 1 to sys_obj_ptr do
+ if obj_offset(k) = 0 then begin
+ obj_link(l) := k;
+ l := k;
+ end;
+obj_link(l) := 0;
+pdf_print_ln("/Type /XRef");
+pdf_print("/Index [0 ");
+pdf_print_int(obj_ptr);
+pdf_print_ln("]");
+pdf_int_entry_ln("Size", obj_ptr);
+pdf_print("/W [1 ");
+pdf_print_int(xref_offset_width);
+pdf_print_ln(" 1]");
+pdf_indirect_ln("Root", root);
+pdf_indirect_ln("Info", obj_ptr - 1);
+if pdf_trailer_toks <> null then begin
+ pdf_print_toks_ln(pdf_trailer_toks);
+ delete_toks(pdf_trailer_toks);
+end;
+print_ID(output_file_name);
+pdf_print_nl;
+pdf_begin_stream;
+for k := 0 to sys_obj_ptr do begin
+ if obj_offset(k) = 0 then begin {a free object}
+ pdf_out(0);
+ pdf_out_bytes(obj_link(k), xref_offset_width);
+ pdf_out(255);
+ end else begin
+ if obj_os_idx(k) = -1 then begin {object not in object stream}
+ pdf_out(1);
+ pdf_out_bytes(obj_offset(k), xref_offset_width);
+ pdf_out(0);
+ end else begin {object in object stream}
+ pdf_out(2);
+ pdf_out_bytes(obj_offset(k), xref_offset_width);
+ pdf_out(obj_os_idx(k));
+ end;
+ end;
+end;
+pdf_end_stream;
+
+@ @<Output the trailer@>=
+if not pdf_os_enable then begin
+ pdf_print_ln("trailer");
+ pdf_print("<< ");
+ pdf_int_entry_ln("Size", sys_obj_ptr + 1);
+ pdf_indirect_ln("Root", root);
+ pdf_indirect_ln("Info", sys_obj_ptr);
+ if pdf_trailer_toks <> null then begin
+ pdf_print_toks_ln(pdf_trailer_toks);
+ delete_toks(pdf_trailer_toks);
+ end;
+ print_ID(output_file_name);
+ pdf_print_ln(" >>");
+end;
+pdf_print_ln("startxref");
+if pdf_os_enable then
+ pdf_print_int_ln(obj_offset(sys_obj_ptr))
+else
+ pdf_print_int_ln(pdf_save_offset);
+pdf_print_ln("%%EOF")
+
+@* \[33] Packaging.
+We're essentially done with the parts of \TeX\ that are concerned with
+the input (|get_next|) and the output (|ship_out|). So it's time to
+get heavily into the remaining part, which does the real work of typesetting.
+
+After lists are constructed, \TeX\ wraps them up and puts them into boxes.
+Two major subroutines are given the responsibility for this task: |hpack|
+applies to horizontal lists (hlists) and |vpack| applies to vertical lists
+(vlists). The main duty of |hpack| and |vpack| is to compute the dimensions
+of the resulting boxes, and to adjust the glue if one of those dimensions
+is pre-specified. The computed sizes normally enclose all of the material
+inside the new box; but some items may stick out if negative glue is used,
+if the box is overfull, or if a \.{\\vbox} includes other boxes that have
+been shifted left.
+
+The subroutine call |hpack(p,w,m)| returns a pointer to an |hlist_node|
+for a box containing the hlist that starts at |p|. Parameter |w| specifies
+a width; and parameter |m| is either `|exactly|' or `|additional|'. Thus,
+|hpack(p,w,exactly)| produces a box whose width is exactly |w|, while
+|hpack(p,w,additional)| yields a box whose width is the natural width plus
+|w|. It is convenient to define a macro called `|natural|' to cover the
+most common case, so that we can say |hpack(p,natural)| to get a box that
+has the natural width of list |p|.
+
+Similarly, |vpack(p,w,m)| returns a pointer to a |vlist_node| for a
+box containing the vlist that starts at |p|. In this case |w| represents
+a height instead of a width; the parameter |m| is interpreted as in |hpack|.
+
+@d exactly=0 {a box dimension is pre-specified}
+@d additional=1 {a box dimension is increased from the natural one}
+@d natural==0,additional {shorthand for parameters to |hpack| and |vpack|}
+
+@<Glob...@>=
+pack_direction:integer;
+spec_direction:integer;
+
+@ The parameters to |hpack| and |vpack| correspond to \TeX's primitives
+like `\.{\\hbox} \.{to} \.{300pt}', `\.{\\hbox} \.{spread} \.{10pt}'; note
+that `\.{\\hbox}' with no dimension following it is equivalent to
+`\.{\\hbox} \.{spread} \.{0pt}'. The |scan_spec| subroutine scans such
+constructions in the user's input, including the mandatory left brace that
+follows them, and it puts the specification onto |save_stack| so that the
+desired box can later be obtained by executing the following code:
+$$\vbox{\halign{#\hfil\cr
+|save_ptr:=save_ptr-2;|\cr
+|hpack(p,saved(1),saved(0)).|\cr}}$$
+Special care is necessary to ensure that the special |save_stack| codes
+are placed just below the new group code, because scanning can change
+|save_stack| when \.{\\csname} appears.
+
+@p procedure scan_spec(@!c:group_code;@!three_codes:boolean);
+ {scans a box specification and left brace}
+label found, continue;
+var @!s:integer; {temporarily saved value}
+i:integer; v:integer;
+@!spec_code:exactly..additional;
+attr_list:halfword;
+begin s:=0;
+if attr_list_cache=cache_disabled then update_attribute_cache;
+attr_list:=attr_list_cache;
+if three_codes then begin
+ s:=saved(0);
+continue:
+ if scan_keyword("attr") then begin
+ scan_register_num; i:=cur_val;
+ scan_optional_equals;
+ scan_int; v:=cur_val;
+ if (attr_list<>null) and (attr_list=attr_list_cache) then begin
+ attr_list:=copy_attribute_list(attr_list_cache);
+ add_node_attr_ref(attr_list); {will be used once}
+ end;
+ attr_list:=do_set_attribute(attr_list,i,v);
+ goto continue;
+ end;
+ if scan_keyword("dir") then begin
+ scan_direction; spec_direction:=cur_val;
+ goto continue;
+ end;
+ end;
+if attr_list=attr_list_cache then begin add_node_attr_ref(attr_list); end;
+if scan_keyword("to") then spec_code:=exactly
+@.to@>
+else if scan_keyword("spread") then spec_code:=additional
+@.spread@>
+else begin spec_code:=additional; cur_val:=0;
+ goto found;
+ end;
+scan_normal_dimen;
+found: if three_codes then begin
+ saved(0):=s;
+ saved(1):=spec_code;
+ saved(2):=cur_val;
+ saved(3):=spec_direction;
+ @<DIR: Adjust |text_dir_ptr| for |scan_spec|@>;
+ saved(5):=attr_list;
+ save_ptr:=save_ptr+6;
+ new_save_level(c); scan_left_brace;
+ eq_word_define(dir_base+body_direction_code,spec_direction);
+ eq_word_define(dir_base+par_direction_code,spec_direction);
+ eq_word_define(dir_base+text_direction_code,spec_direction);
+ eq_word_define(int_base+level_local_dir_code,cur_level);
+ end
+ else begin
+ saved(0):=spec_code;
+ saved(1):=cur_val;
+ save_ptr:=save_ptr+2;
+ new_save_level(c); scan_left_brace;
+ end;
+spec_direction:=-1;
+end;
+
+@ To figure out the glue setting, |hpack| and |vpack| determine how much
+stretchability and shrinkability are present, considering all four orders
+of infinity. The highest order of infinity that has a nonzero coefficient
+is then used as if no other orders were present.
+
+For example, suppose that the given list contains six glue nodes with
+the respective stretchabilities 3pt, 8fill, 5fil, 6pt, $-3$fil, $-8$fill.
+Then the total is essentially 2fil; and if a total additional space of 6pt
+is to be achieved by stretching, the actual amounts of stretch will be
+0pt, 0pt, 15pt, 0pt, $-9$pt, and 0pt, since only `fil' glue will be
+considered. (The `fill' glue is therefore not really stretching infinitely
+with respect to `fil'; nobody would actually want that to happen.)
+
+The arrays |total_stretch| and |total_shrink| are used to determine how much
+glue of each kind is present. A global variable |last_badness| is used
+to implement \.{\\badness}.
+
+@<Glob...@>=
+@!total_stretch, @!total_shrink: array[glue_ord] of scaled;
+ {glue found by |hpack| or |vpack|}
+@!last_badness:integer; {badness of the most recently packaged box}
+
+@ If the global variable |adjust_tail| is non-null, the |hpack| routine
+also removes all occurrences of |ins_node|, |mark_node|, and |adjust_node|
+items and appends the resulting material onto the list that ends at
+location |adjust_tail|.
+
+@< Glob...@>=
+@!adjust_tail:pointer; {tail of adjustment list}
+
+@ @<Set init...@>=adjust_tail:=null; last_badness:=0;
+
+@ @<Glob...@>=
+@!font_expand_ratio: integer; {current expansion ratio}
+@!last_leftmost_char: pointer;
+@!last_rightmost_char: pointer;
+
+@ @d cal_margin_kern_var(#) ==
+begin
+ character(cp) := character(#);
+ font(cp) := font(#);
+ do_subst_font(cp, 1000);
+ if font(cp) <> font(#) then
+ margin_kern_stretch := margin_kern_stretch + left_pw(#) - left_pw(cp);
+ font(cp) := font(#);
+ do_subst_font(cp, -1000);
+ if font(cp) <> font(#) then
+ margin_kern_shrink := margin_kern_shrink + left_pw(cp) - left_pw(#);
+end
+
+@ @<Glob...@>=
+next_char_p:pointer; {pointer to the next char of an implicit kern}
+prev_char_p:pointer; {pointer to the previous char of an implicit kern}
+
+@ This procedure is called repeatedly from inside the line break algorithm.
+
+@p procedure set_prev_char_p(p:pointer);
+begin prev_char_p:=p;
+end;
+
+@ Here is |hpack|, which is place where we do font substituting when
+font expansion is being used. We define some constants used when calling
+|hpack| to deal with font expansion.
+
+@d cal_expand_ratio == 2 {calculate amount for font expansion after breaking
+ paragraph into lines}
+@d subst_ex_font == 3 {substitute fonts}
+
+@d substituted = 3 {|subtype| of kern nodes that should be substituted}
+
+@d left_pw(#) == char_pw(#, left_side)
+@d right_pw(#) == char_pw(#, right_side)
+
+@p function char_stretch(p:halfword): scaled;
+var k: internal_font_number;
+ dw: scaled;
+ ef: integer;
+ f: internal_font_number;
+ c: integer;
+begin
+ f := font(p);
+ c := character(p);
+ char_stretch := 0;
+ k := pdf_font_stretch(f);
+ ef := get_ef_code(f, c);
+ if (k <> null_font) and (ef > 0) then begin
+ dw := char_width(k,c) - char_width(f,c);
+ if dw > 0 then
+ char_stretch := round_xn_over_d(dw, ef, 1000);
+ end;
+end;
+
+function char_shrink(p:halfword): scaled;
+var k: internal_font_number;
+ dw: scaled;
+ ef: integer;
+ f: internal_font_number;
+ c: integer;
+begin
+ f := font(p);
+ c := character(p);
+ char_shrink := 0;
+ k := pdf_font_shrink(f);
+ ef := get_ef_code(f, c);
+ if (k <> null_font) and (ef > 0) then begin
+ dw := char_width(f,c) - char_width(k,c);
+ if dw > 0 then
+ char_shrink := round_xn_over_d(dw, ef, 1000);
+ end;
+end;
+
+function kern_stretch(p: pointer): scaled;
+var l, r: pointer;
+ d: scaled;
+begin
+ kern_stretch := 0;
+ if (prev_char_p = null) or (vlink(prev_char_p) <> p) or (vlink(p) = null)
+ then
+ return;
+ l := prev_char_p;
+ r := vlink(p);
+ if not (is_char_node(l) and is_char_node(r) and
+ (font(l) = font(r)) and
+ (pdf_font_stretch(font(l)) <> null_font))
+ then
+ return;
+ d := get_kern(pdf_font_stretch(font(l)), character(l), character(r));
+ kern_stretch := round_xn_over_d(d - width(p),
+ get_ef_code(font(l), character(l)), 1000);
+end;
+
+function kern_shrink(p: pointer): scaled;
+var l, r: pointer;
+ d: scaled;
+begin
+ kern_shrink := 0;
+ if (prev_char_p = null) or (vlink(prev_char_p) <> p) or (vlink(p) = null)
+ then
+ return;
+ l := prev_char_p;
+ r := vlink(p);
+ if not (is_char_node(l) and is_char_node(r) and
+ (font(l) = font(r)) and
+ (pdf_font_shrink(font(l)) <> null_font))
+ then
+ return;
+ d := get_kern(pdf_font_shrink(font(l)), character(l), character(r));
+ kern_shrink := round_xn_over_d(width(p) - d,
+ get_ef_code(font(l), character(l)), 1000);
+end;
+
+procedure do_subst_font(p: pointer; ex_ratio: integer);
+var f, k: internal_font_number;
+ r: pointer;
+ ef: integer;
+begin
+ if not is_char_node(p) and (type(p) = disc_node) then begin
+ r := vlink(pre_break(p));
+ while r <> null do begin
+ if is_char_node(r) then
+ do_subst_font(r, ex_ratio);
+ r := vlink(r);
+ end;
+ r := vlink(post_break(p));
+ while r <> null do begin
+ if is_char_node(r) then
+ do_subst_font(r, ex_ratio);
+ r := vlink(r);
+ end;
+ r := vlink(no_break(p));
+ while r <> null do begin
+ if is_char_node(r) then
+ do_subst_font(r, ex_ratio);
+ r := vlink(r);
+ end;
+ return;
+ end;
+ if is_char_node(p) then
+ r := p
+ else begin
+ {|short_display_n(p, 5);|}
+ pdf_error("font expansion", "invalid node type");
+ return;
+ end;
+ f := font(r);
+ ef := get_ef_code(f, character(r));
+ if ef = 0 then
+ return;
+ if (pdf_font_expand_ratio(f)=0) and
+ (pdf_font_stretch(f) <> null_font) and
+ (ex_ratio > 0) then
+ k := expand_font(f, ext_xn_over_d(ex_ratio*ef,
+ pdf_font_expand_ratio(pdf_font_stretch(f)),
+ 1000000))
+ else if (pdf_font_expand_ratio(f)=0) and
+ (pdf_font_shrink(f) <> null_font) and (ex_ratio < 0) then
+ k := expand_font(f, ext_xn_over_d(ex_ratio*ef,
+ -pdf_font_expand_ratio(pdf_font_shrink(f)),
+ 1000000))
+ else
+ k := f;
+ if k <> f then begin
+ font(r) := k;
+ if not is_char_node(p) then begin
+ r := lig_ptr(p);
+ while r <> null do begin
+ font(r) := k;
+ r := vlink(r);
+ end;
+ end;
+ end;
+end;
+
+function char_pw(p: pointer; side: small_number): scaled;
+var f: internal_font_number;
+ c: integer;
+begin
+ char_pw := 0;
+ if side = left_side then
+ last_leftmost_char := null
+ else
+ last_rightmost_char := null;
+ if p = null then
+ return;
+ if not is_char_node(p) then
+ return;
+ f := font(p);
+ if side = left_side then begin
+ c := get_lp_code(f, character(p));
+ last_leftmost_char := p;
+ end
+ else begin
+ c := get_rp_code(f, character(p));
+ last_rightmost_char := p;
+ end;
+ if c = 0 then
+ return;
+ char_pw :=
+ round_xn_over_d(quad(f), c, 1000);
+end;
+
+function new_margin_kern(w: scaled; p: pointer; side: small_number): pointer;
+var k,q: pointer;
+begin
+ k := new_node(margin_kern_node,side);
+ width(k) := w;
+ if p = null then
+ pdf_error("margin kerning", "invalid pointer to marginal char node");
+ q := new_char(font(p), character(p)); margin_char(k):=q;
+ new_margin_kern := k;
+end;
+
+function hpack(@!p:pointer;@!w:scaled;@!m:small_number):pointer;
+label reswitch,common_ending,exit;
+var r:pointer; {the box node that will be returned}
+@!q:pointer; {trails behind |p|}
+@!h,@!d,@!x:scaled; {height, depth, and natural width}
+@!s:scaled; {shift amount}
+@!g:pointer; {points to a glue specification}
+@!o:glue_ord; {order of infinity}
+@!f:internal_font_number; {the font in a |char_node|}
+@!dir_tmp,dir_ptr:pointer; {for managing the direction stack}
+@!hpack_dir:integer; {the current direction}
+@!disc_level:integer;
+pack_interrupt:array[0..255] of halfword;
+font_stretch: scaled;
+font_shrink: scaled;
+k: scaled;
+begin last_badness:=0; r:=new_node(hlist_node,min_quarterword);
+if pack_direction=-1 then
+ box_dir(r):=text_direction
+else begin
+ box_dir(r):=pack_direction; pack_direction:=-1;
+ end;
+hpack_dir:=box_dir(r);
+dir_ptr:=null;
+push_dir(hpack_dir);
+q:=r+list_offset; vlink(q):=p;@/
+if m = cal_expand_ratio then begin
+ prev_char_p := null;
+ font_stretch := 0;
+ font_shrink := 0;
+ font_expand_ratio := 0;
+end;
+@{
+if m = subst_ex_font then begin
+ wterm_ln('replacing ', font_expand_ratio:1);
+end;
+@}
+h:=0; @<Clear dimensions to zero@>;
+disc_level:=0;
+reswitch:
+while (p<>null)or(disc_level>0) do begin
+ if p=null then begin
+ decr(disc_level);
+ p:=pack_interrupt[disc_level];
+ goto reswitch;
+ end;
+ @<Examine node |p| in the hlist, taking account of its effect
+ on the dimensions of the new box, or moving it to the adjustment list;
+ then advance |p| to the next node@>;
+ end;
+if adjust_tail<>null then vlink(adjust_tail):=null;
+if pre_adjust_tail<>null then vlink(pre_adjust_tail):=null;
+height(r):=h; depth(r):=d;@/
+@<Determine the value of |width(r)| and the appropriate glue setting;
+ then |return| or |goto common_ending|@>;
+common_ending: @<Finish issuing a diagnostic message
+ for an overfull or underfull hbox@>;
+exit:
+if (m = cal_expand_ratio) and (font_expand_ratio <> 0) then begin
+ font_expand_ratio := fix_int(font_expand_ratio, -1000, 1000);
+ q := list_ptr(r);
+ list_ptr(r):=null; flush_node(r);
+ r:=hpack(q, w, subst_ex_font);
+end;
+while dir_ptr<>null do pop_dir_node;
+hpack:=r;
+end;
+
+function filtered_hpack(@!p:pointer;@!qt:pointer;@!w:scaled;@!m:small_number;@!grp:integer):pointer;
+var q:pointer;
+ d:integer; { a direction }
+begin
+ new_hyphenation(p,qt);
+ call_func(new_ligkern(p,qt)); {don't care about the tail in this case}
+ q:=vlink(p);
+ q:=lua_hpack_filter(q,w,m,grp);
+ filtered_hpack:=hpack(q,w,m);
+end;
+
+@ @<Clear dimensions to zero@>=
+d:=0; x:=0;
+total_stretch[normal]:=0; total_shrink[normal]:=0;
+total_stretch[sfi]:=0; total_shrink[sfi]:=0;
+total_stretch[fil]:=0; total_shrink[fil]:=0;
+total_stretch[fill]:=0; total_shrink[fill]:=0;
+total_stretch[filll]:=0; total_shrink[filll]:=0
+
+@ @<Examine node |p| in the hlist, taking account of its effect...@>=
+@^inner loop@>
+begin while is_char_node(p) do
+ @<Incorporate character dimensions into the dimensions of
+ the hbox that will contain~it, then move to the next node@>;
+if p<>null then
+ begin case type(p) of
+ hlist_node,vlist_node,rule_node,unset_node:
+ @<Incorporate box dimensions into the dimensions of
+ the hbox that will contain~it@>;
+ ins_node,mark_node,adjust_node: begin if adjust_tail<>null then
+ @<Transfer node |p| to the adjustment list@>; end;
+ whatsit_node:@<Incorporate a whatsit node into an hbox@>;
+ glue_node:@<Incorporate glue into the horizontal totals@>;
+ margin_kern_node: begin
+ if m = cal_expand_ratio then begin
+ f := font(margin_char(p));
+ do_subst_font(margin_char(p), 1000);
+ if f <> font(margin_char(p)) then
+ font_stretch := font_stretch - width(p) -
+ char_pw(margin_char(p), subtype(p));
+ font(margin_char(p)) := f;
+ do_subst_font(margin_char(p), -1000);
+ if f <> font(margin_char(p)) then
+ font_shrink := font_shrink - width(p) -
+ char_pw(margin_char(p), subtype(p));
+ font(margin_char(p)) := f;
+ end
+ else if m = subst_ex_font then begin
+ do_subst_font(margin_char(p), font_expand_ratio);
+ width(p) := -char_pw(margin_char(p), subtype(p));
+ end;
+ x := x + width(p);
+ end;
+ kern_node: begin
+ if subtype(p) = normal then begin
+ if m = cal_expand_ratio then begin
+ font_stretch := font_stretch + kern_stretch(p);
+ font_shrink := font_shrink + kern_shrink(p);
+ end
+ else if m = subst_ex_font then begin
+ if font_expand_ratio > 0 then
+ k := kern_stretch(p)
+ else if font_expand_ratio < 0 then
+ k := kern_shrink(p)
+ else
+ pdfassert(0);
+ if k <> 0 then
+ width(p) := get_kern(font(prev_char_p),
+ character(prev_char_p),
+ character(vlink(p)))
+ end;
+ end;
+ x := x + width(p);
+ end;
+ math_node: x:=x+surround(p);
+ disc_node:
+ begin
+ if m = subst_ex_font then do_subst_font(p, font_expand_ratio);
+ if vlink(no_break(p))<>null then begin
+ pack_interrupt[disc_level]:=vlink(p);
+ incr(disc_level);
+ p:=no_break(p);
+ end;
+ end;
+ othercases do_nothing
+ endcases;@/
+ p:=vlink(p);
+ end;
+end
+
+
+@ The code here implicitly uses the fact that running dimensions are
+indicated by |null_flag|, which will be ignored in the calculations
+because it is a highly negative number.
+
+@<Incorporate box dimensions into the dimensions of the hbox...@>=
+begin
+if (type(p)=hlist_node) or (type(p)=vlist_node) then begin
+ if dir_orthogonal(dir_primary[box_dir(p)])(dir_primary[hpack_dir]) then begin
+ x:=x+height(p)+depth(p);
+ s:=shift_amount(p);
+ if (width(p) div 2)-s>h then h:=(width(p) div 2)-s;
+ if (width(p) div 2)+s>d then d:=(width(p) div 2)+s;
+ end
+ else if (type(p)=hlist_node) and (is_mirrored(hpack_dir)) then begin
+ x:=x+width(p);
+ s:=shift_amount(p);
+ if depth(p)-s>h then h:=depth(p)-s;
+ if height(p)+s>d then d:=height(p)+s;
+ end
+ else begin
+ x:=x+width(p);
+ s:=shift_amount(p);
+ if height(p)-s>h then h:=height(p)-s;
+ if depth(p)+s>d then d:=depth(p)+s;
+ end
+ end
+else begin
+ x:=x+width(p);
+ if type(p)>=rule_node then s:=0 @+else s:=shift_amount(p);
+ if height(p)-s>h then h:=height(p)-s;
+ if depth(p)+s>d then d:=depth(p)+s;
+ end;
+end
+
+@ The following code is part of \TeX's inner loop; i.e., adding another
+character of text to the user's input will cause each of these instructions
+to be exercised one more time.
+@^inner loop@>
+
+@d add_char_stretch_end(#) == char_stretch(#)
+@d add_char_stretch(#) == # := # + add_char_stretch_end
+
+@d add_char_shrink_end(#) == char_shrink(#)
+@d add_char_shrink(#) == # := # + add_char_shrink_end
+
+@<Incorporate character dimensions into the dimensions of the hbox...@>=
+begin
+if m >= cal_expand_ratio then begin
+ prev_char_p := p;
+ case m of
+ cal_expand_ratio: begin
+ add_char_stretch(font_stretch)(p);
+ add_char_shrink(font_shrink)(p);
+ end;
+ subst_ex_font:
+ do_subst_font(p, font_expand_ratio);
+ endcases;
+end;
+f:=font(p);
+if is_rotated(hpack_dir) then begin
+ x:=x+glyph_height(p)+glyph_depth(p);@/
+ s:=glyph_width(p) div 2;@+if s>h then h:=s;@+if s>d then d:=s;
+ end
+else if dir_opposite(dir_tertiary[hpack_dir])(dir_tertiary[box_dir(r)])
+ then begin
+ x:=x+glyph_width(p);@/
+ s:=glyph_depth(p);@+if s>h then h:=s;
+ s:=glyph_height(p);@+if s>d then d:=s;
+ end
+else begin
+ x:=x+glyph_width(p);@/
+ s:=glyph_height(p);@+if s>h then h:=s;
+ s:=glyph_depth(p);@+if s>d then d:=s;
+ end;
+p:=vlink(p);
+end
+
+@ Although node |q| is not necessarily the immediate predecessor of node |p|,
+it always points to some node in the list preceding |p|. Thus, we can delete
+nodes by moving |q| when necessary. The algorithm takes linear time, and the
+extra computation does not intrude on the inner loop unless it is necessary
+to make a deletion.
+@^inner loop@>
+
+@<Glob...@>=
+@!pre_adjust_tail: pointer;
+
+@ @<Set init...@>=
+pre_adjust_tail := null;
+
+@ Materials in \.{\\vadjust} used with \.{pre} keyword will be appended to
+|pre_adjust_tail| instead of |adjust_tail|.
+
+@d update_adjust_list(#) == begin
+ vlink(#) := adjust_ptr(p);
+ while vlink(#) <> null do
+ # := vlink(#);
+end
+
+@<Transfer node |p| to the adjustment list@>=
+begin while vlink(q)<>p do q:=vlink(q);
+ if type(p) = adjust_node then begin
+ if adjust_pre(p) <> 0 then
+ update_adjust_list(pre_adjust_tail)
+ else
+ update_adjust_list(adjust_tail);
+ p := vlink(p);
+ adjust_ptr(vlink(q)):=null; flush_node(vlink(q));
+ end
+else begin vlink(adjust_tail):=p; adjust_tail:=p; p:=vlink(p);
+ end;
+vlink(q):=p; p:=q;
+end
+
+@ @<Incorporate glue into the horizontal totals@>=
+begin g:=glue_ptr(p); x:=x+width(g);@/
+o:=stretch_order(g); total_stretch[o]:=total_stretch[o]+stretch(g);
+o:=shrink_order(g); total_shrink[o]:=total_shrink[o]+shrink(g);
+if subtype(p)>=a_leaders then
+ begin g:=leader_ptr(p);
+ if height(g)>h then h:=height(g);
+ if depth(g)>d then d:=depth(g);
+ end;
+end
+
+@ When we get to the present part of the program, |x| is the natural width
+of the box being packaged.
+
+@<Determine the value of |width(r)| and the appropriate glue setting...@>=
+if m=additional then w:=x+w;
+width(r):=w; x:=w-x; {now |x| is the excess to be made up}
+if x=0 then
+ begin glue_sign(r):=normal; glue_order(r):=normal;
+ set_glue_ratio_zero(glue_set(r));
+ return;
+ end
+else if x>0 then @<Determine horizontal glue stretch setting, then |return|
+ or \hbox{|goto common_ending|}@>
+else @<Determine horizontal glue shrink setting, then |return|
+ or \hbox{|goto common_ending|}@>
+
+@ If |hpack| is called with |m=cal_expand_ratio| we calculate
+|font_expand_ratio| and return without checking for overfull or underfull box.
+
+@<Determine horizontal glue stretch setting...@>=
+begin @<Determine the stretch order@>;
+if (m = cal_expand_ratio) and (o = normal) and (font_stretch > 0) then begin
+ font_expand_ratio := divide_scaled_n(x, font_stretch, 1000.0);
+ return;
+end;
+glue_order(r):=o; glue_sign(r):=stretching;
+if total_stretch[o]<>0 then glue_set(r):=unfloat(x/total_stretch[o])
+@^real division@>
+else begin glue_sign(r):=normal;
+ set_glue_ratio_zero(glue_set(r)); {there's nothing to stretch}
+ end;
+if o=normal then if list_ptr(r)<>null then
+ @<Report an underfull hbox and |goto common_ending|, if this box
+ is sufficiently bad@>;
+return;
+end
+
+@ @<Determine the stretch order@>=
+if total_stretch[filll]<>0 then o:=filll
+else if total_stretch[fill]<>0 then o:=fill
+else if total_stretch[fil]<>0 then o:=fil
+else if total_stretch[sfi]<>0 then o:=sfi
+else o:=normal
+
+@ @<Report an underfull hbox and |goto common_ending|, if...@>=
+begin last_badness:=badness(x,total_stretch[normal]);
+if last_badness>hbadness then
+ begin print_ln;
+ if last_badness>100 then print_nl("Underfull")@+else print_nl("Loose");
+ print(" \hbox (badness "); print_int(last_badness);
+@.Underfull \\hbox...@>
+@.Loose \\hbox...@>
+ goto common_ending;
+ end;
+end
+
+@ In order to provide a decent indication of where an overfull or underfull
+box originated, we use a global variable |pack_begin_line| that is
+set nonzero only when |hpack| is being called by the paragraph builder
+or the alignment finishing routine.
+
+@<Glob...@>=
+@!pack_begin_line:integer; {source file line where the current paragraph
+ or alignment began; a negative value denotes alignment}
+
+@ @<Set init...@>=
+pack_begin_line:=0;
+
+@ @<Finish issuing a diagnostic message for an overfull or underfull hbox@>=
+if output_active then print(") has occurred while \output is active")
+else begin if pack_begin_line<>0 then
+ begin if pack_begin_line>0 then print(") in paragraph at lines ")
+ else print(") in alignment at lines ");
+ print_int(abs(pack_begin_line));
+ print("--");
+ end
+ else print(") detected at line ");
+ print_int(line);
+ end;
+print_ln;@/
+font_in_short_display:=null_font; short_display(list_ptr(r)); print_ln;@/
+begin_diagnostic; show_box(r); end_diagnostic(true)
+
+@ @<Determine horizontal glue shrink setting...@>=
+begin @<Determine the shrink order@>;
+if (m = cal_expand_ratio) and (o = normal) and (font_shrink > 0) then begin
+ font_expand_ratio := divide_scaled_n(x, font_shrink, 1000.0);
+ return;
+end;
+glue_order(r):=o; glue_sign(r):=shrinking;
+if total_shrink[o]<>0 then glue_set(r):=unfloat((-x)/total_shrink[o])
+@^real division@>
+else begin glue_sign(r):=normal;
+ set_glue_ratio_zero(glue_set(r)); {there's nothing to shrink}
+ end;
+if (total_shrink[o]<-x)and(o=normal)and(list_ptr(r)<>null) then
+ begin last_badness:=1000000;
+ set_glue_ratio_one(glue_set(r)); {use the maximum shrinkage}
+ @<Report an overfull hbox and |goto common_ending|, if this box
+ is sufficiently bad@>;
+ end
+else if o=normal then if list_ptr(r)<>null then
+ @<Report a tight hbox and |goto common_ending|, if this box
+ is sufficiently bad@>;
+return;
+end
+
+@ @<Determine the shrink order@>=
+if total_shrink[filll]<>0 then o:=filll
+else if total_shrink[fill]<>0 then o:=fill
+else if total_shrink[fil]<>0 then o:=fil
+else if total_shrink[sfi]<>0 then o:=sfi
+else o:=normal
+
+@ @<Report an overfull hbox and |goto common_ending|, if...@>=
+if (-x-total_shrink[normal]>hfuzz)or(hbadness<100) then
+ begin if (overfull_rule>0)and(-x-total_shrink[normal]>hfuzz) then
+ begin while vlink(q)<>null do q:=vlink(q);
+ vlink(q):=new_rule; rule_dir(vlink(q)):=box_dir(r);
+ width(vlink(q)):=overfull_rule;
+ end;
+ print_ln; print_nl("Overfull \hbox (");
+@.Overfull \\hbox...@>
+ print_scaled(-x-total_shrink[normal]); print("pt too wide");
+ goto common_ending;
+ end
+
+@ @<Report a tight hbox and |goto common_ending|, if...@>=
+begin last_badness:=badness(-x,total_shrink[normal]);
+if last_badness>hbadness then
+ begin print_ln; print_nl("Tight \hbox (badness "); print_int(last_badness);
+@.Tight \\hbox...@>
+ goto common_ending;
+ end;
+end
+
+@ The |vpack| subroutine is actually a special case of a slightly more
+general routine called |vpackage|, which has four parameters. The fourth
+parameter, which is |max_dimen| in the case of |vpack|, specifies the
+maximum depth of the page box that is constructed. The depth is first
+computed by the normal rules; if it exceeds this limit, the reference
+point is simply moved down until the limiting depth is attained.
+
+@d vpack(#)==vpackage(#,max_dimen) {special case of unconstrained depth}
+
+@p function vpackage(@!p:pointer;@!h:scaled;@!m:small_number;@!l:scaled):
+ pointer;
+label common_ending, exit;
+var r:pointer; {the box node that will be returned}
+@!w,@!d,@!x:scaled; {width, depth, and natural height}
+@!s:scaled; {shift amount}
+@!g:pointer; {points to a glue specification}
+@!o:glue_ord; {order of infinity}
+begin last_badness:=0;
+{pdfassert(p<>0);}
+r:=new_node(vlist_node,0);
+if pack_direction=-1 then
+ box_dir(r):=body_direction
+else begin
+ box_dir(r):=pack_direction; pack_direction:=-1;
+ end;
+subtype(r):=min_quarterword; shift_amount(r):=0;
+list_ptr(r):=p;@/
+w:=0; @<Clear dimensions to zero@>;
+while p<>null do @<Examine node |p| in the vlist, taking account of its effect
+ on the dimensions of the new box; then advance |p| to the next node@>;
+width(r):=w;
+if d>l then
+ begin x:=x+d-l; depth(r):=l;
+ end
+else depth(r):=d;
+@<Determine the value of |height(r)| and the appropriate glue setting;
+ then |return| or |goto common_ending|@>;
+common_ending: @<Finish issuing a diagnostic message
+ for an overfull or underfull vbox@>;
+exit: vpackage:=r;
+end;
+
+function filtered_vpackage(@!p:pointer;@!h:scaled;@!m:small_number;@!l:scaled;@!grp:integer):pointer;
+var q:pointer;
+begin
+ q:=p;
+ q:=lua_vpack_filter(q,h,m,l,grp);
+ filtered_vpackage:=vpackage(q,h,m,l);
+end;
+
+@ @<Examine node |p| in the vlist, taking account of its effect...@>=
+begin if is_char_node(p) then confusion("vpack")
+@:this can't happen vpack}{\quad vpack@>
+else case type(p) of
+ hlist_node,vlist_node,rule_node,unset_node:
+ @<Incorporate box dimensions into the dimensions of
+ the vbox that will contain~it@>;
+ whatsit_node:@<Incorporate a whatsit node into a vbox@>;
+ glue_node: @<Incorporate glue into the vertical totals@>;
+ kern_node: begin x:=x+d+width(p); d:=0;
+ end;
+ othercases do_nothing
+ endcases;
+p:=vlink(p);
+end
+
+@ @<Incorporate box dimensions into the dimensions of the vbox...@>=
+begin
+if (type(p)=hlist_node) or (type(p)=vlist_node) then begin
+ if dir_orthogonal(dir_primary[box_dir(p)])(dir_primary[box_dir(r)]) then begin
+ x:=x+d+(width(p) div 2); d:=width(p) div 2;
+ s:=shift_amount(p);
+ if depth(p)+height(p)+s>w then w:=depth(p)+height(p)+s;
+ end
+ else if (type(p)=hlist_node) and (is_mirrored(box_dir(p))) then begin
+ x:=x+d+depth(p); d:=height(p);
+ s:=shift_amount(p);
+ if width(p)+s>w then w:=width(p)+s;
+ end
+ else begin
+ x:=x+d+height(p); d:=depth(p);
+ s:=shift_amount(p);
+ if width(p)+s>w then w:=width(p)+s;
+ end
+ end
+else
+ begin x:=x+d+height(p); d:=depth(p);
+ if type(p)>=rule_node then s:=0 @+else s:=shift_amount(p);
+ if width(p)+s>w then w:=width(p)+s;
+ end;
+end
+
+@ @<Incorporate glue into the vertical totals@>=
+begin x:=x+d; d:=0;@/
+g:=glue_ptr(p); x:=x+width(g);@/
+o:=stretch_order(g); total_stretch[o]:=total_stretch[o]+stretch(g);
+o:=shrink_order(g); total_shrink[o]:=total_shrink[o]+shrink(g);
+if subtype(p)>=a_leaders then
+ begin g:=leader_ptr(p);
+ if width(g)>w then w:=width(g);
+ end;
+end
+
+@ When we get to the present part of the program, |x| is the natural height
+of the box being packaged.
+
+@<Determine the value of |height(r)| and the appropriate glue setting...@>=
+if m=additional then h:=x+h;
+height(r):=h; x:=h-x; {now |x| is the excess to be made up}
+if x=0 then
+ begin glue_sign(r):=normal; glue_order(r):=normal;
+ set_glue_ratio_zero(glue_set(r));
+ return;
+ end
+else if x>0 then @<Determine vertical glue stretch setting, then |return|
+ or \hbox{|goto common_ending|}@>
+else @<Determine vertical glue shrink setting, then |return|
+ or \hbox{|goto common_ending|}@>
+
+@ @<Determine vertical glue stretch setting...@>=
+begin @<Determine the stretch order@>;
+glue_order(r):=o; glue_sign(r):=stretching;
+if total_stretch[o]<>0 then glue_set(r):=unfloat(x/total_stretch[o])
+@^real division@>
+else begin glue_sign(r):=normal;
+ set_glue_ratio_zero(glue_set(r)); {there's nothing to stretch}
+ end;
+if o=normal then if list_ptr(r)<>null then
+ @<Report an underfull vbox and |goto common_ending|, if this box
+ is sufficiently bad@>;
+return;
+end
+
+@ @<Report an underfull vbox and |goto common_ending|, if...@>=
+begin last_badness:=badness(x,total_stretch[normal]);
+if last_badness>vbadness then
+ begin print_ln;
+ if last_badness>100 then print_nl("Underfull")@+else print_nl("Loose");
+ print(" \vbox (badness "); print_int(last_badness);
+@.Underfull \\vbox...@>
+@.Loose \\vbox...@>
+ goto common_ending;
+ end;
+end
+
+@ @<Finish issuing a diagnostic message for an overfull or underfull vbox@>=
+if output_active then print(") has occurred while \output is active")
+else begin if pack_begin_line<>0 then {it's actually negative}
+ begin print(") in alignment at lines ");
+ print_int(abs(pack_begin_line));
+ print("--");
+ end
+ else print(") detected at line ");
+ print_int(line);
+ print_ln;@/
+ end;
+begin_diagnostic; show_box(r); end_diagnostic(true)
+
+@ @<Determine vertical glue shrink setting...@>=
+begin @<Determine the shrink order@>;
+glue_order(r):=o; glue_sign(r):=shrinking;
+if total_shrink[o]<>0 then glue_set(r):=unfloat((-x)/total_shrink[o])
+@^real division@>
+else begin glue_sign(r):=normal;
+ set_glue_ratio_zero(glue_set(r)); {there's nothing to shrink}
+ end;
+if (total_shrink[o]<-x)and(o=normal)and(list_ptr(r)<>null) then
+ begin last_badness:=1000000;
+ set_glue_ratio_one(glue_set(r)); {use the maximum shrinkage}
+ @<Report an overfull vbox and |goto common_ending|, if this box
+ is sufficiently bad@>;
+ end
+else if o=normal then if list_ptr(r)<>null then
+ @<Report a tight vbox and |goto common_ending|, if this box
+ is sufficiently bad@>;
+return;
+end
+
+@ @<Report an overfull vbox and |goto common_ending|, if...@>=
+if (-x-total_shrink[normal]>vfuzz)or(vbadness<100) then
+ begin print_ln; print_nl("Overfull \vbox (");
+@.Overfull \\vbox...@>
+ print_scaled(-x-total_shrink[normal]); print("pt too high");
+ goto common_ending;
+ end
+
+@ @<Report a tight vbox and |goto common_ending|, if...@>=
+begin last_badness:=badness(-x,total_shrink[normal]);
+if last_badness>vbadness then
+ begin print_ln; print_nl("Tight \vbox (badness "); print_int(last_badness);
+@.Tight \\vbox...@>
+ goto common_ending;
+ end;
+end
+
+@ When a box is being appended to the current vertical list, the
+baselineskip calculation is handled by the |append_to_vlist| routine.
+
+@p procedure append_to_vlist(@!b:pointer);
+var d:scaled; {deficiency of space between baselines}
+@!p:pointer; {a new glue specification}
+begin if prev_depth>ignore_depth then
+ begin
+ if (type(b)=hlist_node) and (is_mirrored(box_dir(b))) then
+ d:=width(baseline_skip)-prev_depth-depth(b)
+ else
+ d:=width(baseline_skip)-prev_depth-height(b);
+ if d<line_skip_limit then p:=new_param_glue(line_skip_code)
+ else begin p:=new_skip_param(baseline_skip_code);
+ width(temp_ptr):=d; {|temp_ptr=glue_ptr(p)|}
+ end;
+ vlink(tail):=p; tail:=p;
+ end;
+vlink(tail):=b; tail:=b;
+if (type(b)=hlist_node) and (is_mirrored(box_dir(b))) then
+ prev_depth:=height(b)
+else
+ prev_depth:=depth(b);
+end;
+
+@* \[34] Data structures for math mode.
+When \TeX\ reads a formula that is enclosed between \.\$'s, it constructs an
+{\sl mlist}, which is essentially a tree structure representing that
+formula. An mlist is a linear sequence of items, but we can regard it as
+a tree structure because mlists can appear within mlists. For example, many
+of the entries can be subscripted or superscripted, and such ``scripts''
+are mlists in their own right.
+
+An entire formula is parsed into such a tree before any of the actual
+typesetting is done, because the current style of type is usually not
+known until the formula has been fully scanned. For example, when the
+formula `\.{\$a+b \\over c+d\$}' is being read, there is no way to tell
+that `\.{a+b}' will be in script size until `\.{\\over}' has appeared.
+
+During the scanning process, each element of the mlist being built is
+classified as a relation, a binary operator, an open parenthesis, etc.,
+or as a construct like `\.{\\sqrt}' that must be built up. This classification
+appears in the mlist data structure.
+
+After a formula has been fully scanned, the mlist is converted to an hlist
+so that it can be incorporated into the surrounding text. This conversion is
+controlled by a recursive procedure that decides all of the appropriate
+styles by a ``top-down'' process starting at the outermost level and working
+in towards the subformulas. The formula is ultimately pasted together using
+combinations of horizontal and vertical boxes, with glue and penalty nodes
+inserted as necessary.
+
+An mlist is represented internally as a linked list consisting chiefly
+of ``noads'' (pronounced ``no-adds''), to distinguish them from the somewhat
+similar ``nodes'' in hlists and vlists. Certain kinds of ordinary nodes are
+allowed to appear in mlists together with the noads; \TeX\ tells the difference
+by means of the |type| field, since a noad's |type| is always greater than
+that of a node. An mlist does not contain character nodes, hlist nodes, vlist
+nodes, math nodes or unset nodes; in particular, each mlist item appears in the
+variable-size part of |mem|, so the |type| field is always present.
+
+@ Each noad is five or more words long. The first word contains the
+|type| and |subtype| and |link| fields that are already so familiar to
+us; the second contains the attribute list pointer, and the third,
+fourth an fifth words are called the noad's |nucleus|, |subscr|, and
+|supscr| fields. (This use of a combined attribute list is temporary.
+Eventually, each of fields need their own list)
+
+Consider, for example, the simple formula `\.{\$x\^2\$}', which would be
+parsed into an mlist containing a single element called an |ord_noad|.
+The |nucleus| of this noad is a representation of `\.x', the |subscr| is
+empty, and the |supscr| is a representation of `\.2'.
+
+The |nucleus|, |subscr|, and |supscr| fields are further broken into
+subfields. If |p| points to a noad, and if |q| is one of its principal
+fields (e.g., |q=subscr(p)|), there are several possibilities for the
+subfields, depending on the |math_type| of |q|.
+
+\yskip\hang|math_type(q)=math_char| means that |fam(q)| refers to one of
+the sixteen font families, and |character(q)| is the number of a character
+within a font of that family, as in a character node.
+
+\yskip\hang|math_type(q)=math_text_char| is similar, but the character is
+unsubscripted and unsuperscripted and it is followed immediately by another
+character from the same font. (This |math_type| setting appears only
+briefly during the processing; it is used to suppress unwanted italic
+corrections.)
+
+\yskip\hang|math_type(q)=empty| indicates a field with no value (the
+corresponding attribute of noad |p| is not present).
+
+\yskip\hang|math_type(q)=sub_box| means that |vinfo(q)| points to a box
+node (either an |hlist_node| or a |vlist_node|) that should be used as the
+value of the field. The |shift_amount| in the subsidiary box node is the
+amount by which that box will be shifted downward.
+
+\yskip\hang|math_type(q)=sub_mlist| means that |vinfo(q)| points to
+an mlist; the mlist must be converted to an hlist in order to obtain
+the value of this field.
+
+\yskip\noindent In the latter case, we might have |vinfo(q)=null|. This
+is not the same as |math_type(q)=empty|; for example, `\.{\$P\_\{\}\$}'
+and `\.{\$P\$}' produce different results (the former will not have the
+``italic correction'' added to the width of |P|, but the ``script skip''
+will be added).
+
+The definitions of subfields given here are a little wasteful of space,
+since a quarterword is being used for the |math_type| although only three
+bits would be needed. However, there are hardly ever many noads present at
+once, since they are soon converted to nodes that take up even more space,
+so we can afford to represent them in whatever way simplifies the
+programming.
+
+I tried exchanging |mcharacter()| and |math_type()| so that a character
+could use the full Unicode range, but for some reason that does not work
+properly. TH
+
+@d noad_size=5 {number of words in a normal noad}
+@d nucleus(#)==#+2 {the |nucleus| field of a noad}
+@d supscr(#)==#+3 {the |supscr| field of a noad}
+@d subscr(#)==#+4 {the |subscr| field of a noad}
+@d math_type==vlink {a |quarterword| in |mem|}
+@d fam(#)==type(#) {a |quarterword| in |mem|}
+@d mcharacter(#)==subtype(#)
+@d math_char=1 {|math_type| when the attribute is simple}
+@d sub_box=2 {|math_type| when the attribute is a box}
+@d sub_mlist=3 {|math_type| when the attribute is a formula}
+@d math_text_char=4 {|math_type| when italic correction is dubious}
+
+@ Each portion of a formula is classified as Ord, Op, Bin, Rel, Ope,
+Clo, Pun, or Inn, for purposes of spacing and line breaking. An
+|ord_noad|, |op_noad|, |bin_noad|, |rel_noad|, |open_noad|, |close_noad|,
+|punct_noad|, or |inner_noad| is used to represent portions of the various
+types. For example, an `\.=' sign in a formula leads to the creation of a
+|rel_noad| whose |nucleus| field is a representation of an equals sign
+(usually |fam=0|, |character=@'75|). A formula preceded by \.{\\mathrel}
+also results in a |rel_noad|. When a |rel_noad| is followed by an
+|op_noad|, say, and possibly separated by one or more ordinary nodes (not
+noads), \TeX\ will insert a penalty node (with the current |rel_penalty|)
+just after the formula that corresponds to the |rel_noad|, unless there
+already was a penalty immediately following; and a ``thick space'' will be
+inserted just before the formula that corresponds to the |op_noad|.
+
+A noad of type |ord_noad|, |op_noad|, \dots, |inner_noad| usually
+has a |subtype=normal|. The only exception is that an |op_noad| might
+have |subtype=limits| or |no_limits|, if the normal positioning of
+limits has been overridden for this operator.
+
+@d ord_noad=unset_node+3 {|type| of a noad classified Ord}
+@d op_noad=ord_noad+1 {|type| of a noad classified Op}
+@d bin_noad=ord_noad+2 {|type| of a noad classified Bin}
+@d rel_noad=ord_noad+3 {|type| of a noad classified Rel}
+@d open_noad=ord_noad+4 {|type| of a noad classified Ope}
+@d close_noad=ord_noad+5 {|type| of a noad classified Clo}
+@d punct_noad=ord_noad+6 {|type| of a noad classified Pun}
+@d inner_noad=ord_noad+7 {|type| of a noad classified Inn}
+@d limits=1 {|subtype| of |op_noad| whose scripts are to be above, below}
+@d no_limits=2 {|subtype| of |op_noad| whose scripts are to be normal}
+
+@ A |radical_noad| is five words long; the fifth word is the |left_delimiter|
+field, which usually represents a square root sign.
+
+A |fraction_noad| is six words long; it has a |right_delimiter| field
+as well as a |left_delimiter|.
+
+Delimiter fields are of type |four_quarters|, and they have four subfields
+called |small_fam|, |small_char|, |large_fam|, |large_char|. These subfields
+represent variable-size delimiters by giving the ``small'' and ``large''
+starting characters, as explained in Chapter~17 of {\sl The \TeX book}.
+@:TeXbook}{\sl The \TeX book@>
+
+A |fraction_noad| is actually quite different from all other noads. Not
+only does it have six words, it has |thickness|, |denominator|, and
+|numerator| fields instead of |nucleus|, |subscr|, and |supscr|. The
+|thickness| is a scaled value that tells how thick to make a fraction
+rule; however, the special value |default_code| is used to stand for the
+|default_rule_thickness| of the current size. The |numerator| and
+|denominator| point to mlists that define a fraction; we always have
+$$\hbox{|math_type(numerator)=math_type(denominator)=sub_mlist|}.$$ The
+|left_delimiter| and |right_delimiter| fields specify delimiters that will
+be placed at the left and right of the fraction. In this way, a
+|fraction_noad| is able to represent all of \TeX's operators \.{\\over},
+\.{\\atop}, \.{\\above}, \.{\\overwithdelims}, \.{\\atopwithdelims}, and
+ \.{\\abovewithdelims}.
+
+@d left_delimiter(#)==#+5 {first delimiter field of a noad}
+@d right_delimiter(#)==#+6 {second delimiter field of a fraction noad}
+@d radical_noad=inner_noad+1 {|type| of a noad for square roots}
+@d radical_noad_size=6 {number of |mem| words in a radical noad}
+@d fraction_noad=radical_noad+1 {|type| of a noad for generalized fractions}
+@d fraction_noad_size=7 {number of |mem| words in a fraction noad}
+@d small_fam(#)==vmem(#).qqqq.b0 {|fam| for ``small'' delimiter}
+@d small_char(#)==vmem(#).qqqq.b1 {|character| for ``small'' delimiter}
+@d large_fam(#)==vmem(#).qqqq.b2 {|fam| for ``large'' delimiter}
+@d large_char(#)==vmem(#).qqqq.b3 {|character| for ``large'' delimiter}
+@d thickness(#)==vmem(#+2).sc {|thickness| field in a fraction noad}
+@d default_code==@'10000000000 {denotes |default_rule_thickness|}
+@d numerator==supscr {|numerator| field in a fraction noad}
+@d denominator==subscr {|denominator| field in a fraction noad}
+
+@ The global variable |empty_field| is set up for initialization of empty
+fields in new noads. Similarly, |null_delimiter| is for the initialization
+of delimiter fields.
+
+@<Glob...@>=
+@!empty_field:two_halves;
+@!null_delimiter:four_quarters;
+
+@ @<Set init...@>=
+empty_field.rh:=empty; empty_field.lh:=null;@/
+null_delimiter.b0:=0; null_delimiter.b1:=min_quarterword;@/
+null_delimiter.b2:=0; null_delimiter.b3:=min_quarterword;
+
+@ The |new_noad| function creates an |ord_noad| that is completely null.
+
+@p function new_noad:pointer;
+var p:pointer;
+begin p:=new_node(ord_noad,normal);
+vmem(nucleus(p)).hh:=empty_field;
+vmem(subscr(p)).hh:=empty_field;
+vmem(supscr(p)).hh:=empty_field;
+new_noad:=p;
+end;
+
+@ A few more kinds of noads will complete the set: An |under_noad| has its
+nucleus underlined; an |over_noad| has it overlined. An |accent_noad| places
+an accent over its nucleus; the accent character appears as
+|fam(accent_chr(p))| and |mcharacter(accent_chr(p))|. A |vcenter_noad|
+centers its nucleus vertically with respect to the axis of the formula;
+in such noads we always have |math_type(nucleus(p))=sub_box|.
+
+And finally, we have |left_noad| and |right_noad| types, to implement
+\TeX's \.{\\left} and \.{\\right} as well as \eTeX's \.{\\middle}.
+The |nucleus| of such noads is
+replaced by a |delimiter| field; thus, for example, `\.{\\left(}' produces
+a |left_noad| such that |delimiter(p)| holds the family and character
+codes for all left parentheses. A |left_noad| never appears in an mlist
+except as the first element, and a |right_noad| never appears in an mlist
+except as the last element; furthermore, we either have both a |left_noad|
+and a |right_noad|, or neither one is present. The |subscr| and |supscr|
+fields are always |empty| in a |left_noad| and a |right_noad|.
+
+@d under_noad=fraction_noad+1 {|type| of a noad for underlining}
+@d over_noad=under_noad+1 {|type| of a noad for overlining}
+@d accent_noad=over_noad+1 {|type| of a noad for accented subformulas}
+@d accent_noad_size=6 {number of |mem| words in an accent noad}
+@d accent_chr(#)==#+5 {the |accent_chr| field of an accent noad}
+@d vcenter_noad=accent_noad+1 {|type| of a noad for \.{\\vcenter}}
+@d left_noad=vcenter_noad+1 {|type| of a noad for \.{\\left}}
+@d right_noad=left_noad+1 {|type| of a noad for \.{\\right}}
+@d delimiter==nucleus {|delimiter| field in left and right noads}
+@d middle_noad==1 {|subtype| of right noad representing \.{\\middle}}
+@d scripts_allowed(#)==(type(#)>=ord_noad)and(type(#)<left_noad)
+
+@ Math formulas can also contain instructions like \.{\\textstyle} that
+override \TeX's normal style rules. A |style_node| is inserted into the
+data structure to record such instructions; it is three words long, so it
+is considered a node instead of a noad. The |subtype| is either |display_style|
+or |text_style| or |script_style| or |script_script_style|. The
+second and third words of a |style_node| are not used, but they are
+present because a |choice_node| is converted to a |style_node|.
+
+\TeX\ uses even numbers 0, 2, 4, 6 to encode the basic styles
+|display_style|, \dots, |script_script_style|, and adds~1 to get the
+``cramped'' versions of these styles. This gives a numerical order that
+is backwards from the convention of Appendix~G in {\sl The \TeX book\/};
+i.e., a smaller style has a larger numerical value.
+@:TeXbook}{\sl The \TeX book@>
+
+@d style_node=unset_node+1 {|type| of a style node}
+@d style_node_size=4 {number of words in a style node}
+@d display_style=0 {|subtype| for \.{\\displaystyle}}
+@d text_style=2 {|subtype| for \.{\\textstyle}}
+@d script_style=4 {|subtype| for \.{\\scriptstyle}}
+@d script_script_style=6 {|subtype| for \.{\\scriptscriptstyle}}
+@d cramped=1 {add this to an uncramped style if you want to cramp it}
+
+@p function new_style(@!s:small_number):pointer; {create a style node}
+var p:pointer; {the new node}
+begin p:=new_node(style_node,s);
+new_style:=p;
+end;
+
+@ Finally, the \.{\\mathchoice} primitive creates a |choice_node|, which
+has special subfields |display_mlist|, |text_mlist|, |script_mlist|,
+and |script_script_mlist| pointing to the mlists for each style.
+
+@d choice_node=unset_node+2 {|type| of a choice node}
+@d display_mlist(#)==vinfo(#+2) {mlist to be used in display style}
+@d text_mlist(#)==vlink(#+2) {mlist to be used in text style}
+@d script_mlist(#)==vinfo(#+3) {mlist to be used in script style}
+@d script_script_mlist(#)==vlink(#+3) {mlist to be used in scriptscript style}
+
+@p function new_choice:pointer; {create a choice node}
+var p:pointer; {the new node}
+begin p:=new_node(choice_node,0); {the |subtype| is not used}
+new_choice:=p;
+end;
+
+@ Let's consider now the previously unwritten part of |show_node_list|
+that displays the things that can only be present in mlists; this
+program illustrates how to access the data structures just defined.
+
+In the context of the following program, |p| points to a node or noad that
+should be displayed, and the current string contains the ``recursion history''
+that leads to this point. The recursion history consists of a dot for each
+outer level in which |p| is subsidiary to some node, or in which |p| is
+subsidiary to the |nucleus| field of some noad; the dot is replaced by
+`\.\_' or `\.\^' or `\./' or `\.\\' if |p| is descended from the |subscr|
+or |supscr| or |denominator| or |numerator| fields of noads. For example,
+the current string would be `\.{.\^.\_/}' if |p| points to the |ord_noad| for
+|x| in the (ridiculous) formula
+`\.{\$\\sqrt\{a\^\{\\mathinner\{b\_\{c\\over x+y\}\}\}\}\$}'.
+
+@<Cases of |show_node_list| that arise...@>=
+style_node:print_style(subtype(p));
+choice_node:@<Display choice node |p|@>;
+ord_noad,op_noad,bin_noad,rel_noad,open_noad,close_noad,punct_noad,inner_noad,
+ radical_noad,over_noad,under_noad,vcenter_noad,accent_noad,
+ left_noad,right_noad:@<Display normal noad |p|@>;
+fraction_noad:@<Display fraction noad |p|@>;
+
+@ Here are some simple routines used in the display of noads.
+
+@<Declare procedures needed for displaying the elements of mlists@>=
+procedure print_fam_and_char(@!p:pointer); {prints family and character}
+begin print_esc("fam"); print_int(fam(p)); print_char(" ");
+print(qo(mcharacter(p)));
+end;
+@#
+procedure print_delimiter(@!p:pointer); {prints a delimiter as 24-bit hex value}
+{TH: FIX to do: print 48-bit integer where needed!}
+var a:integer; {accumulator}
+begin a:=small_fam(p)*256+qo(small_char(p));
+a:=a*@"1000+large_fam(p)*256+qo(large_char(p));
+if a<0 then print_int(a) {this should never happen}
+else print_hex(a);
+end;
+
+@ The next subroutine will descend to another level of recursion when a
+subsidiary mlist needs to be displayed. The parameter |c| indicates what
+character is to become part of the recursion history. An empty mlist is
+distinguished from a field with |math_type(p)=empty|, because these are
+not equivalent (as explained above).
+@^recursion@>
+
+@<Declare procedures needed for displaying...@>=
+procedure@?show_info; forward;@t\2@>@?{|show_node_list(vinfo(temp_ptr))|}
+procedure print_subsidiary_data(@!p:pointer;@!c:ASCII_code);
+ {display a noad field}
+begin if cur_length>=depth_threshold then
+ begin if math_type(p)<>empty then print(" []");
+ end
+else begin append_char(c); {include |c| in the recursion history}
+ temp_ptr:=p; {prepare for |show_info| if recursion is needed}
+ case math_type(p) of
+ math_char: begin print_ln; print_current_string; print_fam_and_char(p);
+ end;
+ sub_box: show_info; {recursive call}
+ sub_mlist: if vinfo(p)=null then
+ begin print_ln; print_current_string; print("{}");
+ end
+ else show_info; {recursive call}
+ othercases do_nothing {|empty|}
+ endcases;@/
+ flush_char; {remove |c| from the recursion history}
+ end;
+end;
+
+@ The inelegant introduction of |show_info| in the code above seems better
+than the alternative of using \PASCAL's strange |forward| declaration for a
+procedure with parameters. The \PASCAL\ convention about dropping parameters
+from a post-|forward| procedure is, frankly, so intolerable to the author
+of \TeX\ that he would rather stoop to communication via a global temporary
+variable. (A similar stoopidity occurred with respect to |hlist_out| and
+|vlist_out| above, and it will occur with respect to |mlist_to_hlist| below.)
+@^Knuth, Donald Ervin@>
+@:PASCAL}{\PASCAL@>
+
+@p procedure show_info; {the reader will kindly forgive this}
+begin show_node_list(vinfo(temp_ptr));
+end;
+
+@ @<Declare procedures needed for displaying...@>=
+procedure print_style(@!c:integer);
+begin case c div 2 of
+0: print_esc("displaystyle"); {|display_style=0|}
+1: print_esc("textstyle"); {|text_style=2|}
+2: print_esc("scriptstyle"); {|script_style=4|}
+3: print_esc("scriptscriptstyle"); {|script_script_style=6|}
+othercases print("Unknown style!")
+endcases;
+end;
+
+@ @<Display choice node |p|@>=
+begin print_esc("mathchoice");
+append_char("D"); show_node_list(display_mlist(p)); flush_char;
+append_char("T"); show_node_list(text_mlist(p)); flush_char;
+append_char("S"); show_node_list(script_mlist(p)); flush_char;
+append_char("s"); show_node_list(script_script_mlist(p)); flush_char;
+end
+
+@ @<Display normal noad |p|@>=
+begin case type(p) of
+ord_noad: print_esc("mathord");
+op_noad: print_esc("mathop");
+bin_noad: print_esc("mathbin");
+rel_noad: print_esc("mathrel");
+open_noad: print_esc("mathopen");
+close_noad: print_esc("mathclose");
+punct_noad: print_esc("mathpunct");
+inner_noad: print_esc("mathinner");
+over_noad: print_esc("overline");
+under_noad: print_esc("underline");
+vcenter_noad: print_esc("vcenter");
+radical_noad: begin
+ {TH: TODO print oradical where needed and fix otherwise}
+ print_esc("radical"); print_delimiter(left_delimiter(p));
+ end;
+accent_noad: begin print_esc("accent"); print_fam_and_char(accent_chr(p));
+ end;
+left_noad: begin print_esc("left"); print_delimiter(nucleus(p));
+ end;
+right_noad: begin if subtype(p)=normal then print_esc("right")
+ else print_esc("middle");
+ print_delimiter(nucleus(p));
+ end;
+end;
+if type(p)<left_noad then
+ begin if subtype(p)<>normal then
+ if subtype(p)=limits then print_esc("limits")
+ else print_esc("nolimits");
+ print_subsidiary_data(nucleus(p),".");
+ end;
+print_subsidiary_data(supscr(p),"^");
+print_subsidiary_data(subscr(p),"_");
+end
+
+@ @<Display fraction noad |p|@>=
+begin print_esc("fraction, thickness ");
+if thickness(p)=default_code then print("= default")
+else print_scaled(thickness(p));
+if (small_fam(left_delimiter(p))<>0)or@+
+ (small_char(left_delimiter(p))<>min_quarterword)or@|
+ (large_fam(left_delimiter(p))<>0)or@|
+ (large_char(left_delimiter(p))<>min_quarterword) then
+ begin print(", left-delimiter "); print_delimiter(left_delimiter(p));
+ end;
+if (small_fam(right_delimiter(p))<>0)or@|
+ (small_char(right_delimiter(p))<>min_quarterword)or@|
+ (large_fam(right_delimiter(p))<>0)or@|
+ (large_char(right_delimiter(p))<>min_quarterword) then
+ begin print(", right-delimiter "); print_delimiter(right_delimiter(p));
+ end;
+print_subsidiary_data(numerator(p),"\");
+print_subsidiary_data(denominator(p),"/");
+end
+
+@* \[35] Subroutines for math mode.
+In order to convert mlists to hlists, i.e., noads to nodes, we need several
+subroutines that are conveniently dealt with now.
+
+Let us first introduce the macros that make it easy to get at the parameters and
+other font information. A size code, which is a multiple of 16, is added to a
+family number to get an index into the table of internal font numbers
+for each combination of family and size. (Be alert: Size codes get
+larger as the type gets smaller.)
+
+@<Basic printing procedures@>=
+procedure print_size(@!s:integer);
+begin if s=0 then print_esc("textfont")
+else if s=script_size then print_esc("scriptfont")
+else print_esc("scriptscriptfont");
+end;
+
+@ Before an mlist is converted to an hlist, \TeX\ makes sure that
+the fonts in family~2 have enough parameters to be math-symbol
+fonts, and that the fonts in family~3 have enough parameters to be
+math-extension fonts. The math-symbol parameters are referred to by using the
+following macros, which take a size code as their parameter; for example,
+|num1(cur_size)| gives the value of the |num1| parameter for the current size.
+@^parameters for symbols@>
+@^font parameters@>
+
+@d mathsy_end(#)==
+@d mathsy(#)==font_param(fam_fnt(2+cur_size),#) mathsy_end
+@d math_x_height==mathsy(5) {height of `\.x'}
+@d math_quad==mathsy(6) {\.{18mu}}
+@d num1==mathsy(8) {numerator shift-up in display styles}
+@d num2==mathsy(9) {numerator shift-up in non-display, non-\.{\\atop}}
+@d num3==mathsy(10) {numerator shift-up in non-display \.{\\atop}}
+@d denom1==mathsy(11) {denominator shift-down in display styles}
+@d denom2==mathsy(12) {denominator shift-down in non-display styles}
+@d sup1==mathsy(13) {superscript shift-up in uncramped display style}
+@d sup2==mathsy(14) {superscript shift-up in uncramped non-display}
+@d sup3==mathsy(15) {superscript shift-up in cramped styles}
+@d sub1==mathsy(16) {subscript shift-down if superscript is absent}
+@d sub2==mathsy(17) {subscript shift-down if superscript is present}
+@d sup_drop==mathsy(18) {superscript baseline below top of large box}
+@d sub_drop==mathsy(19) {subscript baseline below bottom of large box}
+@d delim1==mathsy(20) {size of \.{\\atopwithdelims} delimiters
+ in display styles}
+@d delim2==mathsy(21) {size of \.{\\atopwithdelims} delimiters in non-displays}
+@d axis_height==mathsy(22) {height of fraction lines above the baseline}
+@d total_mathsy_params=22
+
+@ The math-extension parameters have similar macros, but the size code is
+omitted (since it is always |cur_size| when we refer to such parameters).
+@^parameters for symbols@>
+@^font parameters@>
+
+@d mathex(#)==font_param(fam_fnt(3+cur_size),#)
+@d default_rule_thickness==mathex(8) {thickness of \.{\\over} bars}
+@d big_op_spacing1==mathex(9) {minimum clearance above a displayed op}
+@d big_op_spacing2==mathex(10) {minimum clearance below a displayed op}
+@d big_op_spacing3==mathex(11) {minimum baselineskip above displayed op}
+@d big_op_spacing4==mathex(12) {minimum baselineskip below displayed op}
+@d big_op_spacing5==mathex(13) {padding above and below displayed limits}
+@d total_mathex_params=13
+
+@ We also need to compute the change in style between mlists and their
+subsidiaries. The following macros define the subsidiary style for
+an overlined nucleus (|cramped_style|), for a subscript or a superscript
+(|sub_style| or |sup_style|), or for a numerator or denominator (|num_style|
+or |denom_style|).
+
+@d cramped_style(#)==2*(# div 2)+cramped {cramp the style}
+@d sub_style(#)==2*(# div 4)+script_style+cramped {smaller and cramped}
+@d sup_style(#)==2*(# div 4)+script_style+(# mod 2) {smaller}
+@d num_style(#)==#+2-2*(# div 6) {smaller unless already script-script}
+@d denom_style(#)==2*(# div 2)+cramped+2-2*(# div 6) {smaller, cramped}
+
+@ When the style changes, the following piece of program computes associated
+information:
+
+@<Set up the values of |cur_size| and |cur_mu|, based on |cur_style|@>=
+begin if cur_style<script_style then cur_size:=text_size
+else cur_size:=script_size*((cur_style-text_style) div 2);
+cur_mu:=x_over_n(math_quad(cur_size),18);
+end
+
+@ Here is a function that returns a pointer to a rule node having a given
+thickness |t|. The rule will extend horizontally to the boundary of the vlist
+that eventually contains it.
+
+@p function fraction_rule(@!t:scaled):pointer;
+ {construct the bar for a fraction}
+var p:pointer; {the new node}
+begin p:=new_rule; rule_dir(p):=math_direction;
+height(p):=t; depth(p):=0; fraction_rule:=p;
+end;
+
+@ The |overbar| function returns a pointer to a vlist box that consists of
+a given box |b|, above which has been placed a kern of height |k| under a
+fraction rule of thickness |t| under additional space of height |t|.
+
+@p function overbar(@!b:pointer;@!k,@!t:scaled):pointer;
+var p,@!q:pointer; {nodes being constructed}
+begin p:=new_kern(k); vlink(p):=b; q:=fraction_rule(t); vlink(q):=p;
+p:=new_kern(t); vlink(p):=q;
+pack_direction:=math_direction; overbar:=vpack(p,natural);
+end;
+
+@ The |var_delimiter| function, which finds or constructs a sufficiently
+large delimiter, is the most interesting of the auxiliary functions that
+currently concern us. Given a pointer |d| to a delimiter field in some noad,
+together with a size code |s| and a vertical distance |v|, this function
+returns a pointer to a box that contains the smallest variant of |d| whose
+height plus depth is |v| or more. (And if no variant is large enough, it
+returns the largest available variant.) In particular, this routine will
+construct arbitrarily large delimiters from extensible components, if
+|d| leads to such characters.
+
+The value returned is a box whose |shift_amount| has been set so that
+the box is vertically centered with respect to the axis in the given size.
+If a built-up symbol is returned, the height of the box before shifting
+will be the height of its topmost component.
+
+@p@t\4@>@<Declare subprocedures for |var_delimiter|@>
+function var_delimiter(@!d:pointer;@!s:integer;@!v:scaled):pointer;
+label found,continue;
+var b:pointer; {the box that will be constructed}
+@!f,@!g: internal_font_number; {best-so-far and tentative font codes}
+@!c,@!x,@!y: integer; {best-so-far and tentative character codes}
+@!cc: integer; { a temporary character code for extensibles }
+@!m,@!n: integer; {the number of extensible pieces}
+@!u: scaled; {height-plus-depth of a tentative character}
+@!w: scaled; {largest height-plus-depth so far}
+@!z: integer; {runs through font family members}
+@!large_attempt: boolean; {are we trying the ``large'' variant?}
+begin f:=null_font; c:=0; w:=0; large_attempt:=false;
+z:=small_fam(d); x:=small_char(d);
+loop@+ begin @<Look at the variants of |(z,x)|; set |f| and |c| whenever
+ a better character is found; |goto found| as soon as a
+ large enough variant is encountered@>;
+ if large_attempt then goto found; {there were none large enough}
+ large_attempt:=true; z:=large_fam(d); x:=large_char(d);
+ end;
+found: if f<>null_font then
+ @<Make variable |b| point to a box for |(f,c)|@>
+else begin b:=new_null_box;
+ width(b):=null_delimiter_space; {use this width if no delimiter was found}
+ end;
+z:=cur_size; cur_size:=s;
+shift_amount(b):=half(height(b)-depth(b)) - axis_height(cur_size);
+cur_size:=z;
+var_delimiter:=b;
+end;
+
+@ The search process is complicated slightly by the facts that some of the
+characters might not be present in some of the fonts, and they might not
+be probed in increasing order of height.
+
+@<Look at the variants of |(z,x)|; set |f| and |c|...@>=
+if (z<>0)or(x<>min_quarterword) then
+ begin z:=z+s+script_size;
+ repeat z:=z-script_size; g:=fam_fnt(z);
+ if g<>null_font then
+ @<Look at the list of characters starting with |x| in
+ font |g|; set |f| and |c| whenever
+ a better character is found; |goto found| as soon as a
+ large enough variant is encountered@>;
+ until z<script_size;
+ end
+
+@ @<Look at the list of characters starting with |x|...@>=
+begin y:=x;
+if (y>=font_bc(g))and(y<=font_ec(g)) then
+ begin continue:
+ if char_exists(g,y) then
+ begin if char_tag(g,y)=ext_tag then
+ begin f:=g; c:=y; goto found;
+ end;
+ u:=char_height(g,y)+char_depth(g,y);
+ if u>w then
+ begin f:=g; c:=y; w:=u;
+ if u>=v then goto found;
+ end;
+ if char_tag(g,y)=list_tag then
+ begin y:=char_remainder(g,y); goto continue;
+ end;
+ end;
+ end;
+end
+
+@ Here is a subroutine that creates a new box, whose list contains a
+single character, and whose width includes the italic correction for
+that character. The height or depth of the box will be negative, if
+the height or depth of the character is negative; thus, this routine
+may deliver a slightly different result than |hpack| would produce.
+
+@<Declare subprocedures for |var_delimiter|@>=
+function char_box(@!f:internal_font_number;@!c:quarterword):pointer;
+var @!b,@!p:pointer; {the new box and its character node}
+begin
+b:=new_null_box; ci:=char_info_short(f,c);
+width(b):=charinfo_width(ci)+char_italic(f,c);
+height(b):=charinfo_height(ci); depth(b):=charinfo_depth(ci);
+p:=new_char(f,c); list_ptr(b):=p; char_box:=b;
+end;
+
+@ When the following code is executed, |char_tag(q)| will be equal to
+|ext_tag| if and only if a built-up symbol is supposed to be returned.
+
+@<Make variable |b| point to a box for |(f,c)|@>=
+if char_tag(f,c)=ext_tag then
+ @<Construct an extensible character in a new box |b|,
+ using recipe |rem_byte(q)| and font |f|@>
+else b:=char_box(f,c)
+
+@ When we build an extensible character, it's handy to have the
+following subroutine, which puts a given character on top
+of the characters already in box |b|:
+
+@<Declare subprocedures for |var_delimiter|@>=
+procedure stack_into_box(@!b:pointer;@!f:internal_font_number;
+ @!c:quarterword);
+var p:pointer; {new node placed into |b|}
+begin p:=char_box(f,c); vlink(p):=list_ptr(b); list_ptr(b):=p;
+height(b):=height(p);
+end;
+
+@ Another handy subroutine computes the height plus depth of
+a given character:
+
+@<Declare subprocedures for |var_delimiter|@>=
+function height_plus_depth(@!f:internal_font_number;@!c:quarterword):scaled;
+begin
+height_plus_depth:=char_height(f,c)+char_depth(f,c);
+end;
+
+@ @<Construct an extensible...@>=
+begin b:=new_null_box;
+type(b):=vlist_node;
+@<Compute the minimum suitable height, |w|, and the corresponding
+ number of extension steps, |n|; also set |width(b)|@>;
+cc:=ext_bot(f,c);
+if cc<>min_quarterword then stack_into_box(b,f,cc);
+cc:=ext_rep(f,c);
+for m:=1 to n do stack_into_box(b,f,cc);
+cc:=ext_mid(f,c);
+if cc<>min_quarterword then
+ begin stack_into_box(b,f,cc); cc:=ext_rep(f,c);
+ for m:=1 to n do stack_into_box(b,f,cc);
+ end;
+cc:=ext_top(f,c);
+if cc<>min_quarterword then stack_into_box(b,f,cc);
+depth(b):=w-height(b);
+end
+
+@ The width of an extensible character is the width of the repeatable
+module. If this module does not have positive height plus depth,
+we don't use any copies of it, otherwise we use as few as possible
+(in groups of two if there is a middle part).
+
+@<Compute the minimum suitable height, |w|, and...@>=
+cc:=ext_rep(f,c); u:=height_plus_depth(f,cc);
+w:=0; width(b):=char_width(f,cc)+char_italic(f,cc);@/
+cc:=ext_bot(f,c);@+if cc<>min_quarterword then w:=w+height_plus_depth(f,cc);
+cc:=ext_mid(f,c);@+if cc<>min_quarterword then w:=w+height_plus_depth(f,cc);
+cc:=ext_top(f,c);@+if cc<>min_quarterword then w:=w+height_plus_depth(f,cc);
+n:=0;
+if u>0 then while w<v do
+ begin w:=w+u; incr(n);
+ if (ext_mid(f,c))<>min_quarterword then w:=w+u;
+ end
+
+@ The next subroutine is much simpler; it is used for numerators and
+denominators of fractions as well as for displayed operators and
+their limits above and below. It takes a given box~|b| and
+changes it so that the new box is centered in a box of width~|w|.
+The centering is done by putting \.{\\hss} glue at the left and right
+of the list inside |b|, then packaging the new box; thus, the
+actual box might not really be centered, if it already contains
+infinite glue.
+
+The given box might contain a single character whose italic correction
+has been added to the width of the box; in this case a compensating
+kern is inserted.
+
+@p function rebox(@!b:pointer;@!w:scaled):pointer;
+var p,q:pointer; {temporary registers for list manipulation}
+@!f:internal_font_number; {font in a one-character box}
+@!v:scaled; {width of a character without italic correction}
+begin if (width(b)<>w)and(list_ptr(b)<>null) then
+ begin if type(b)=vlist_node then b:=hpack(b,natural);
+ p:=list_ptr(b);
+ if (is_char_node(p))and(vlink(p)=null) then
+ begin f:=font(p); v:=char_width(f,character(p));
+ if v<>width(b) then begin
+ q:=new_kern(width(b)-v); vlink(p):=q;
+ end;
+ end;
+ list_ptr(b):=null; flush_node(b);
+ b:=new_glue(ss_glue); vlink(b):=p;
+ while vlink(p)<>null do p:=vlink(p);
+ q:=new_glue(ss_glue); vlink(p):=q;
+ rebox:=hpack(b,w,exactly);
+ end
+else begin width(b):=w; rebox:=b;
+ end;
+end;
+
+@ Here is a subroutine that creates a new glue specification from another
+one that is expressed in `\.{mu}', given the value of the math unit.
+
+@d mu_mult(#)==nx_plus_y(n,#,xn_over_d(#,f,@'200000))
+
+@p function math_glue(@!g:pointer;@!m:scaled):pointer;
+var p:pointer; {the new glue specification}
+@!n:integer; {integer part of |m|}
+@!f:scaled; {fraction part of |m|}
+begin n:=x_over_n(m,@'200000); f:=remainder;@/
+if f<0 then
+ begin decr(n); f:=f+@'200000;
+ end;
+p:=new_node(glue_spec_node,0);
+width(p):=mu_mult(width(g)); {convert \.{mu} to \.{pt}}
+stretch_order(p):=stretch_order(g);
+if stretch_order(p)=normal then stretch(p):=mu_mult(stretch(g))
+else stretch(p):=stretch(g);
+shrink_order(p):=shrink_order(g);
+if shrink_order(p)=normal then shrink(p):=mu_mult(shrink(g))
+else shrink(p):=shrink(g);
+math_glue:=p;
+end;
+
+@ The |math_kern| subroutine removes |mu_glue| from a kern node, given
+the value of the math unit.
+
+@p procedure math_kern(@!p:pointer;@!m:scaled);
+var @!n:integer; {integer part of |m|}
+@!f:scaled; {fraction part of |m|}
+begin if subtype(p)=mu_glue then
+ begin n:=x_over_n(m,@'200000); f:=remainder;@/
+ if f<0 then
+ begin decr(n); f:=f+@'200000;
+ end;
+ width(p):=mu_mult(width(p)); subtype(p):=explicit;
+ end;
+end;
+
+@ Sometimes it is necessary to destroy an mlist. The following
+subroutine empties the current list, assuming that |abs(mode)=mmode|.
+
+@p procedure flush_math;
+begin flush_node_list(vlink(head)); flush_node_list(incompleat_noad);
+vlink(head):=null; tail:=head; incompleat_noad:=null;
+end;
+
+@* \[36] Typesetting math formulas.
+\TeX's most important routine for dealing with formulas is called
+|mlist_to_hlist|. After a formula has been scanned and represented as an
+mlist, this routine converts it to an hlist that can be placed into a box
+or incorporated into the text of a paragraph. There are three implicit
+parameters, passed in global variables: |cur_mlist| points to the first
+node or noad in the given mlist (and it might be |null|); |cur_style| is a
+style code; and |mlist_penalties| is |true| if penalty nodes for potential
+line breaks are to be inserted into the resulting hlist. After
+|mlist_to_hlist| has acted, |vlink(temp_head)| points to the translated hlist.
+
+Since mlists can be inside mlists, the procedure is recursive. And since this
+is not part of \TeX's inner loop, the program has been written in a manner
+that stresses compactness over efficiency.
+@^recursion@>
+
+@<Glob...@>=
+@!cur_mlist:pointer; {beginning of mlist to be translated}
+@!cur_style:integer; {style code at current place in the list}
+@!cur_size:integer; {size code corresponding to |cur_style|}
+@!cur_mu:scaled; {the math unit width corresponding to |cur_size|}
+@!mlist_penalties:boolean; {should |mlist_to_hlist| insert penalties?}
+
+@ The recursion in |mlist_to_hlist| is due primarily to a subroutine
+called |clean_box| that puts a given noad field into a box using a given
+math style; |mlist_to_hlist| can call |clean_box|, which can call
+|mlist_to_hlist|.
+@^recursion@>
+
+The box returned by |clean_box| is ``clean'' in the
+sense that its |shift_amount| is zero.
+
+@p procedure@?mlist_to_hlist; forward;@t\2@>@/
+function clean_box(@!p:pointer;@!s:integer):pointer;
+label found;
+var q:pointer; {beginning of a list to be boxed}
+@!save_style:integer; {|cur_style| to be restored}
+@!x:pointer; {box to be returned}
+@!r:pointer; {temporary pointer}
+begin
+case math_type(p) of
+math_char: begin cur_mlist:=new_noad; vmem(nucleus(cur_mlist)):=vmem(p);
+ end;
+sub_box: begin q:=vinfo(p); goto found;
+ end;
+sub_mlist: cur_mlist:=vinfo(p);
+othercases begin q:=new_null_box; goto found;
+ end
+endcases;@/
+save_style:=cur_style; cur_style:=s; mlist_penalties:=false;@/
+mlist_to_hlist; q:=vlink(temp_head); {recursive call}
+cur_style:=save_style; {restore the style}
+@<Set up the values of |cur_size| and |cur_mu|, based on |cur_style|@>;
+found: if is_char_node(q)or(q=null) then x:=hpack(q,natural)
+ else if (vlink(q)=null)and(type(q)<=vlist_node)and(shift_amount(q)=0) then
+ x:=q {it's already clean}
+ else x:=hpack(q,natural);
+@<Simplify a trivial box@>;
+clean_box:=x;
+end;
+
+@ Here we save memory space in a common case.
+
+@<Simplify a trivial box@>=
+q:=list_ptr(x);
+if is_char_node(q) then
+ begin r:=vlink(q);
+ if r<>null then if vlink(r)=null then if not is_char_node(r) then
+ if type(r)=kern_node then {unneeded italic correction}
+ begin flush_node(r); vlink(q):=null;
+ end;
+ end
+
+@ It is convenient to have a procedure that converts a |math_char|
+field to an ``unpacked'' form. The |fetch| routine sets |cur_f| and |cur_c|
+to the font code and character code of a given noad field.
+It also takes care of issuing error messages for
+nonexistent characters; in such cases, |char_exists(cur_f,cur_c)| will be |false|
+after |fetch| has acted, and the field will also have been reset to |empty|.
+
+@p procedure fetch(@!a:pointer); {unpack the |math_char| field |a|}
+begin cur_c:=mcharacter(a); cur_f:=fam_fnt(fam(a)+cur_size);
+if cur_f=null_font then
+ @<Complain about an undefined family@>
+else begin
+ if not(char_exists(cur_f,cur_c)) then
+ begin char_warning(cur_f,qo(cur_c));
+ math_type(a):=empty;
+ end;
+ end;
+end;
+
+@ @<Complain about an undefined family@>=
+begin print_err(""); print_size(cur_size); print_char(" ");
+print_int(fam(a)); print(" is undefined (character ");
+print(qo(cur_c)); print_char(")");
+help4("Somewhere in the math formula just ended, you used the")@/
+("stated character from an undefined font family. For example,")@/
+("plain TeX doesn't allow \it or \sl in subscripts. Proceed,")@/
+("and I'll try to forget that I needed that character.");
+error; math_type(a):=empty;
+end
+
+@ The outputs of |fetch| are placed in global variables.
+
+@<Glob...@>=
+@!cur_f:internal_font_number; {the |font| field of a |math_char|}
+@!cur_c:quarterword; {the |character| field of a |math_char|}
+
+@ We need to do a lot of different things, so |mlist_to_hlist| makes two
+passes over the given mlist.
+
+The first pass does most of the processing: It removes ``mu'' spacing from
+glue, it recursively evaluates all subsidiary mlists so that only the
+top-level mlist remains to be handled, it puts fractions and square roots
+and such things into boxes, it attaches subscripts and superscripts, and
+it computes the overall height and depth of the top-level mlist so that
+the size of delimiters for a |left_noad| and a |right_noad| will be known.
+The hlist resulting from each noad is recorded in that noad's |new_hlist|
+field, an integer field that replaces the |nucleus| or |thickness|.
+@^recursion@>
+
+The second pass eliminates all noads and inserts the correct glue and
+penalties between nodes.
+
+@d new_hlist(#)==vmem(nucleus(#)).int {the translation of an mlist}
+
+@ Here is the overall plan of |mlist_to_hlist|, and the list of its
+local variables.
+
+@d done_with_noad=80 {go here when a noad has been fully translated}
+@d done_with_node=81 {go here when a node has been fully converted}
+@d check_dimensions=82 {go here to update |max_h| and |max_d|}
+@d delete_q=83 {go here to delete |q| and move to the next node}
+
+@p@t\4@>@<Declare math construction procedures@>
+procedure mlist_to_hlist;
+label reswitch, check_dimensions, done_with_noad, done_with_node, delete_q,
+ done;
+var mlist:pointer; {beginning of the given list}
+@!penalties:boolean; {should penalty nodes be inserted?}
+@!style:integer; {the given style}
+@!save_style:integer; {holds |cur_style| during recursion}
+@!q:pointer; {runs through the mlist}
+@!r:pointer; {the most recent noad preceding |q|}
+@!r_type:integer; {the |type| of noad |r|, or |op_noad| if |r=null|}
+@!t:integer; {the effective |type| of noad |q| during the second pass}
+@!p,@!x,@!y,@!z: pointer; {temporary registers for list construction}
+@!pen:integer; {a penalty to be inserted}
+@!s:integer; {the size of a noad to be deleted}
+@!max_hl,@!max_d:scaled; {maximum height and depth of the list translated so far}
+@!delta:scaled; {offset between subscript and superscript}
+begin mlist:=cur_mlist; penalties:=mlist_penalties;
+style:=cur_style; {tuck global parameters away as local variables}
+q:=mlist; r:=null; r_type:=op_noad; max_hl:=0; max_d:=0; x:=null; p:=null;
+@<Set up the values of |cur_size| and |cur_mu|, based on |cur_style|@>;
+while q<>null do @<Process node-or-noad |q| as much as possible in preparation
+ for the second pass of |mlist_to_hlist|, then move to the next
+ item in the mlist@>;
+@<Convert \(a)a final |bin_noad| to an |ord_noad|@>;
+@<Make a second pass over the mlist, removing all noads and inserting the
+ proper spacing and penalties@>;
+end;
+
+@ We use the fact that no character nodes appear in an mlist, hence
+the field |type(q)| is always present.
+
+@<Process node-or-noad...@>=
+begin @<Do first-pass processing based on |type(q)|; |goto done_with_noad|
+ if a noad has been fully processed, |goto check_dimensions| if it
+ has been translated into |new_hlist(q)|, or |goto done_with_node|
+ if a node has been fully processed@>;
+check_dimensions: z:=hpack(new_hlist(q),natural);
+if height(z)>max_hl then max_hl:=height(z);
+if depth(z)>max_d then max_d:=depth(z);
+list_ptr(z):=null; flush_node(z);
+done_with_noad: r:=q; r_type:=type(r);
+if r_type=right_noad then
+ begin r_type:=left_noad; cur_style:=style; @<Set up the values...@>;
+ end;
+done_with_node: q:=vlink(q);
+end
+
+@ One of the things we must do on the first pass is change a |bin_noad| to
+an |ord_noad| if the |bin_noad| is not in the context of a binary operator.
+The values of |r| and |r_type| make this fairly easy.
+
+@<Do first-pass processing...@>=
+reswitch: delta:=0;
+case type(q) of
+bin_noad: case r_type of
+ bin_noad,op_noad,rel_noad,open_noad,punct_noad,left_noad:
+ begin type(q):=ord_noad; goto reswitch;
+ end;
+ othercases do_nothing
+ endcases;
+rel_noad,close_noad,punct_noad,right_noad: begin@t@>@;@/
+ @<Convert \(a)a final |bin_noad| to an |ord_noad|@>;
+ if type(q)=right_noad then goto done_with_noad;
+ end;
+@t\4@>@<Cases for noads that can follow a |bin_noad|@>@;
+@t\4@>@<Cases for nodes that can appear in an mlist, after which we
+ |goto done_with_node|@>@;
+othercases confusion("mlist1")
+@:this can't happen mlist1}{\quad mlist1@>
+endcases;@/
+@<Convert \(n)|nucleus(q)| to an hlist and attach the sub/superscripts@>
+
+@ @<Convert \(a)a final |bin_noad| to an |ord_noad|@>=
+if r_type=bin_noad then type(r):=ord_noad
+
+@ @<Cases for nodes that can appear in an mlist...@>=
+style_node: begin cur_style:=subtype(q);
+ @<Set up the values of |cur_size| and |cur_mu|, based on |cur_style|@>;
+ goto done_with_node;
+ end;
+choice_node: @<Change this node to a style node followed by the correct choice,
+ then |goto done_with_node|@>;
+ins_node,mark_node,adjust_node,
+ whatsit_node,penalty_node,disc_node: goto done_with_node;
+rule_node: begin if height(q)>max_hl then max_hl:=height(q);
+ if depth(q)>max_d then max_d:=depth(q); goto done_with_node;
+ end;
+glue_node: begin @<Convert \(m)math glue to ordinary glue@>;
+ goto done_with_node;
+ end;
+kern_node: begin math_kern(q,cur_mu); goto done_with_node;
+ end;
+
+@ @d choose_mlist(#)==begin p:=#(q); #(q):=null;@+end
+
+@<Change this node to a style node...@>=
+begin case cur_style div 2 of
+0: choose_mlist(display_mlist); {|display_style=0|}
+1: choose_mlist(text_mlist); {|text_style=2|}
+2: choose_mlist(script_mlist); {|script_style=4|}
+3: choose_mlist(script_script_mlist); {|script_script_style=6|}
+end; {there are no other cases}
+flush_node_list(display_mlist(q));
+flush_node_list(text_mlist(q));
+flush_node_list(script_mlist(q));
+flush_node_list(script_script_mlist(q));@/
+type(q):=style_node; subtype(q):=cur_style; width(q):=0; depth(q):=0;
+if p<>null then
+ begin z:=vlink(q); vlink(q):=p;
+ while vlink(p)<>null do p:=vlink(p);
+ vlink(p):=z;
+ end;
+goto done_with_node;
+end
+
+@ Conditional math glue (`\.{\\nonscript}') results in a |glue_node|
+pointing to |zero_glue|, with |subtype(q)=cond_math_glue|; in such a case
+the node following will be eliminated if it is a glue or kern node and if the
+current size is different from |text_size|. Unconditional math glue
+(`\.{\\muskip}') is converted to normal glue by multiplying the dimensions
+by |cur_mu|.
+@!@:non_script_}{\.{\\nonscript} primitive@>
+
+@<Convert \(m)math glue to ordinary glue@>=
+if subtype(q)=mu_glue then
+ begin x:=glue_ptr(q);
+ y:=math_glue(x,cur_mu); delete_glue_ref(x); glue_ptr(q):=y;
+ subtype(q):=normal;
+ end
+else if (cur_size<>text_size)and(subtype(q)=cond_math_glue) then
+ begin p:=vlink(q);
+ if p<>null then if (type(p)=glue_node)or(type(p)=kern_node) then
+ begin vlink(q):=vlink(p); vlink(p):=null; flush_node_list(p);
+ end;
+ end
+
+@ @<Cases for noads that can follow a |bin_noad|@>=
+left_noad: goto done_with_noad;
+fraction_noad: begin make_fraction(q); goto check_dimensions;
+ end;
+op_noad: begin delta:=make_op(q);
+ if subtype(q)=limits then goto check_dimensions;
+ end;
+ord_noad: make_ord(q);
+open_noad,inner_noad: do_nothing;
+radical_noad: make_radical(q);
+over_noad: make_over(q);
+under_noad: make_under(q);
+accent_noad: make_math_accent(q);
+vcenter_noad: make_vcenter(q);
+
+@ Most of the actual construction work of |mlist_to_hlist| is done
+by procedures with names
+like |make_fraction|, |make_radical|, etc. To illustrate
+the general setup of such procedures, let's begin with a couple of
+simple ones.
+
+@<Declare math...@>=
+procedure make_over(@!q:pointer);
+var p:pointer;
+begin p:=overbar(clean_box(nucleus(q),cramped_style(cur_style)),@|
+ 3*default_rule_thickness,default_rule_thickness);
+vinfo(nucleus(q)):=p;
+math_type(nucleus(q)):=sub_box;
+end;
+
+@ @<Declare math...@>=
+procedure make_under(@!q:pointer);
+var p,@!x,@!y,@!r: pointer; {temporary registers for box construction}
+@!delta:scaled; {overall height plus depth}
+begin x:=clean_box(nucleus(q),cur_style);
+p:=new_kern(3*default_rule_thickness); vlink(x):=p;
+r:=fraction_rule(default_rule_thickness); vlink(p):=r;
+pack_direction:=math_direction; y:=vpack(x,natural);
+delta:=height(y)+depth(y)+default_rule_thickness;
+height(y):=height(x); depth(y):=delta-height(y);
+vinfo(nucleus(q)):=y; math_type(nucleus(q)):=sub_box;
+end;
+
+@ @<Declare math...@>=
+procedure make_vcenter(@!q:pointer);
+var v:pointer; {the box that should be centered vertically}
+@!delta:scaled; {its height plus depth}
+begin v:=vinfo(nucleus(q));
+if type(v)<>vlist_node then confusion("vcenter");
+@:this can't happen vcenter}{\quad vcenter@>
+delta:=height(v)+depth(v);
+height(v):=axis_height(cur_size)+half(delta);
+depth(v):=delta-height(v);
+end;
+
+@ According to the rules in the \.{DVI} file specifications, we ensure alignment
+@^square roots@>
+between a square root sign and the rule above its nucleus by assuming that the
+baseline of the square-root symbol is the same as the bottom of the rule. The
+height of the square-root symbol will be the thickness of the rule, and the
+depth of the square-root symbol should exceed or equal the height-plus-depth
+of the nucleus plus a certain minimum clearance~|clr|. The symbol will be
+placed so that the actual clearance is |clr| plus half the excess.
+
+@<Declare math...@>=
+procedure make_radical(@!q:pointer);
+var x,@!y,@!p:pointer; {temporary registers for box construction}
+@!delta,@!clr:scaled; {dimensions involved in the calculation}
+begin x:=clean_box(nucleus(q),cramped_style(cur_style));
+if cur_style<text_style then {display style}
+ clr:=default_rule_thickness+(abs(math_x_height(cur_size)) div 4)
+else begin clr:=default_rule_thickness; clr:=clr + (abs(clr) div 4);
+ end;
+y:=var_delimiter(left_delimiter(q),cur_size,height(x)+depth(x)+clr+
+ default_rule_thickness);
+delta:=depth(y)-(height(x)+depth(x)+clr);
+if delta>0 then clr:=clr+half(delta); {increase the actual clearance}
+shift_amount(y):=-(height(x)+clr);
+p:=overbar(x,clr,height(y)); vlink(y):=p;
+p:=hpack(y,natural); vinfo(nucleus(q)):=p;
+math_type(nucleus(q)):=sub_box;
+end;
+
+@ Slants are not considered when placing accents in math mode. The accenter is
+centered over the accentee, and the accent width is treated as zero with
+respect to the size of the final box.
+
+@<Declare math...@>=
+procedure make_math_accent(@!q:pointer);
+label done;
+var p,@!x,@!y:pointer; {temporary registers for box construction}
+@!c:quarterword; {accent character}
+@!f:internal_font_number; {its font}
+@!s:scaled; {amount to skew the accent to the right}
+@!h:scaled; {height of character being accented}
+@!delta:scaled; {space to remove between accent and accentee}
+@!w:scaled; {width of the accentee, not including sub/superscripts}
+begin fetch(accent_chr(q));
+if char_exists(cur_f,cur_c) then
+ begin c:=cur_c; f:=cur_f;@/
+ @<Compute the amount of skew@>;
+ x:=clean_box(nucleus(q),cramped_style(cur_style)); w:=width(x); h:=height(x);
+ @<Switch to a larger accent if available and appropriate@>;
+ if h<x_height(f) then delta:=h@+else delta:=x_height(f);
+ if (math_type(supscr(q))<>empty)or(math_type(subscr(q))<>empty) then
+ if math_type(nucleus(q))=math_char then
+ @<Swap the subscript and superscript into box |x|@>;
+ y:=char_box(f,c);
+ shift_amount(y):=s+half(w-width(y));
+ width(y):=0; p:=new_kern(-delta); vlink(p):=x; vlink(y):=p;
+ pack_direction:=math_direction;
+ y:=vpack(y,natural); width(y):=width(x);
+ if height(y)<h then @<Make the height of box |y| equal to |h|@>;
+ vinfo(nucleus(q)):=y;
+ math_type(nucleus(q)):=sub_box;
+ end;
+end;
+
+@ @<Make the height of box |y|...@>=
+begin p:=new_kern(h-height(y)); vlink(p):=list_ptr(y); list_ptr(y):=p;
+height(y):=h;
+end
+
+@ @<Switch to a larger accent if available and appropriate@>=
+loop@+ begin if char_tag(f,c)<>list_tag then goto done;
+ y:=char_remainder(f,c);
+ if not char_exists(f,y) then goto done;
+ if char_width(f,y)>w then goto done;
+ c:=y;
+ end;
+done:
+
+@ @<Compute the amount of skew@>=
+s:=0;
+if math_type(nucleus(q))=math_char then
+ begin fetch(nucleus(q));
+ s := get_kern(cur_f,cur_c,skew_char(cur_f));
+ end
+
+@ @<Swap the subscript and superscript into box |x|@>=
+begin flush_node_list(x); x:=new_noad;
+vmem(nucleus(x)):=vmem(nucleus(q));
+vmem(supscr(x)):=vmem(supscr(q));
+vmem(subscr(x)):=vmem(subscr(q));@/
+vmem(supscr(q)).hh:=empty_field;
+vmem(subscr(q)).hh:=empty_field;@/
+math_type(nucleus(q)):=sub_mlist; vinfo(nucleus(q)):=x;
+x:=clean_box(nucleus(q),cur_style); delta:=delta+height(x)-h; h:=height(x);
+end
+
+@ The |make_fraction| procedure is a bit different because it sets
+|new_hlist(q)| directly rather than making a sub-box.
+
+@<Declare math...@>=
+procedure make_fraction(@!q:pointer);
+var p,@!v,@!x,@!y,@!z:pointer; {temporary registers for box construction}
+@!delta,@!delta1,@!delta2,@!shift_up,@!shift_down,@!clr:scaled;
+ {dimensions for box calculations}
+begin if thickness(q)=default_code then thickness(q):=default_rule_thickness;
+@<Create equal-width boxes |x| and |z| for the numerator and denominator,
+ and compute the default amounts |shift_up| and |shift_down| by which they
+ are displaced from the baseline@>;
+if thickness(q)=0 then @<Adjust \(s)|shift_up| and |shift_down| for the case
+ of no fraction line@>
+else @<Adjust \(s)|shift_up| and |shift_down| for the case of a fraction line@>;
+@<Construct a vlist box for the fraction, according to |shift_up| and
+ |shift_down|@>;
+@<Put the \(f)fraction into a box with its delimiters, and make |new_hlist(q)|
+ point to it@>;
+end;
+
+@ @<Create equal-width boxes |x| and |z| for the numerator and denom...@>=
+x:=clean_box(numerator(q),num_style(cur_style));
+z:=clean_box(denominator(q),denom_style(cur_style));
+vinfo(numerator(q)):=null;
+vinfo(denominator(q)):=null;
+if width(x)<width(z) then x:=rebox(x,width(z))
+else z:=rebox(z,width(x));
+if cur_style<text_style then {display style}
+ begin shift_up:=num1(cur_size); shift_down:=denom1(cur_size);
+ end
+else begin shift_down:=denom2(cur_size);
+ if thickness(q)<>0 then shift_up:=num2(cur_size)
+ else shift_up:=num3(cur_size);
+ end
+
+@ The numerator and denominator must be separated by a certain minimum
+clearance, called |clr| in the following program. The difference between
+|clr| and the actual clearance is |2delta|.
+
+@<Adjust \(s)|shift_up| and |shift_down| for the case of no fraction line@>=
+begin if cur_style<text_style then clr:=7*default_rule_thickness
+else clr:=3*default_rule_thickness;
+delta:=half(clr-((shift_up-depth(x))-(height(z)-shift_down)));
+if delta>0 then
+ begin shift_up:=shift_up+delta;
+ shift_down:=shift_down+delta;
+ end;
+end
+
+@ In the case of a fraction line, the minimum clearance depends on the actual
+thickness of the line.
+
+@<Adjust \(s)|shift_up| and |shift_down| for the case of a fraction line@>=
+begin if cur_style<text_style then clr:=3*thickness(q)
+else clr:=thickness(q);
+delta:=half(thickness(q));
+delta1:=clr-((shift_up-depth(x))-(axis_height(cur_size)+delta));
+delta2:=clr-((axis_height(cur_size)-delta)-(height(z)-shift_down));
+if delta1>0 then shift_up:=shift_up+delta1;
+if delta2>0 then shift_down:=shift_down+delta2;
+end
+
+@ @<Construct a vlist box for the fraction...@>=
+v:=new_null_box; type(v):=vlist_node;
+height(v):=shift_up+height(x); depth(v):=depth(z)+shift_down;
+width(v):=width(x); {this also equals |width(z)|}
+if thickness(q)=0 then
+ begin p:=new_kern((shift_up-depth(x))-(height(z)-shift_down));
+ vlink(p):=z;
+ end
+else begin y:=fraction_rule(thickness(q));@/
+ p:=new_kern((axis_height(cur_size)-delta)-@|(height(z)-shift_down));@/
+ vlink(y):=p; vlink(p):=z;@/
+ p:=new_kern((shift_up-depth(x))-(axis_height(cur_size)+delta));
+ vlink(p):=y;
+ end;
+vlink(x):=p; list_ptr(v):=x
+
+@ @<Put the \(f)fraction into a box with its delimiters...@>=
+if cur_style<text_style then delta:=delim1(cur_size)
+else delta:=delim2(cur_size);
+x:=var_delimiter(left_delimiter(q), cur_size, delta); vlink(x):=v;@/
+z:=var_delimiter(right_delimiter(q), cur_size, delta); vlink(v):=z;@/
+y:=hpack(x,natural);
+new_hlist(q):=y
+
+@ If the nucleus of an |op_noad| is a single character, it is to be
+centered vertically with respect to the axis, after first being enlarged
+(via a character list in the font) if we are in display style. The normal
+convention for placing displayed limits is to put them above and below the
+operator in display style.
+
+The italic correction is removed from the character if there is a subscript
+and the limits are not being displayed. The |make_op|
+routine returns the value that should be used as an offset between
+subscript and superscript.
+
+After |make_op| has acted, |subtype(q)| will be |limits| if and only if
+the limits have been set above and below the operator. In that case,
+|new_hlist(q)| will already contain the desired final box.
+
+@<Declare math...@>=
+function make_op(@!q:pointer):scaled;
+var delta:scaled; {offset between subscript and superscript}
+@!p,@!v,@!x,@!y,@!z:pointer; {temporary registers for box construction}
+@!c:quarterword; {register for character examination}
+@!shift_up,@!shift_down:scaled; {dimensions for box calculation}
+begin if (subtype(q)=normal)and(cur_style<text_style) then
+ subtype(q):=limits;
+if math_type(nucleus(q))=math_char then
+ begin fetch(nucleus(q));
+ if (cur_style<text_style)and(char_tag(cur_f,cur_c)=list_tag) then {make it larger}
+ begin c:=char_remainder(cur_f,cur_c);
+ if char_exists(cur_f,c) then
+ begin cur_c:=c; mcharacter(nucleus(q)):=c;
+ end;
+ end;
+ delta:=char_italic(cur_f,cur_c); x:=clean_box(nucleus(q),cur_style);
+ if (math_type(subscr(q))<>empty)and(subtype(q)<>limits) then
+ width(x):=width(x)-delta; {remove italic correction}
+ shift_amount(x):=half(height(x)-depth(x)) - axis_height(cur_size);
+ {center vertically}
+ math_type(nucleus(q)):=sub_box; vinfo(nucleus(q)):=x;
+ end
+else delta:=0;
+if subtype(q)=limits then
+ @<Construct a box with limits above and below it, skewed by |delta|@>;
+make_op:=delta;
+end;
+
+@ The following program builds a vlist box |v| for displayed limits. The
+width of the box is not affected by the fact that the limits may be skewed.
+
+@<Construct a box with limits above and below it...@>=
+begin x:=clean_box(supscr(q),sup_style(cur_style));
+y:=clean_box(nucleus(q),cur_style);
+z:=clean_box(subscr(q),sub_style(cur_style));
+v:=new_null_box; type(v):=vlist_node; width(v):=width(y);
+if width(x)>width(v) then width(v):=width(x);
+if width(z)>width(v) then width(v):=width(z);
+x:=rebox(x,width(v)); y:=rebox(y,width(v)); z:=rebox(z,width(v));@/
+shift_amount(x):=half(delta); shift_amount(z):=-shift_amount(x);
+height(v):=height(y); depth(v):=depth(y);
+@<Attach the limits to |y| and adjust |height(v)|, |depth(v)| to
+ account for their presence@>;
+new_hlist(q):=v;
+end
+
+@ We use |shift_up| and |shift_down| in the following program for the
+amount of glue between the displayed operator |y| and its limits |x| and
+|z|. The vlist inside box |v| will consist of |x| followed by |y| followed
+by |z|, with kern nodes for the spaces between and around them.
+
+@<Attach the limits to |y| and adjust |height(v)|, |depth(v)|...@>=
+if math_type(supscr(q))=empty then
+ begin list_ptr(x):=null; flush_node(x); list_ptr(v):=y;
+ end
+else begin shift_up:=big_op_spacing3-depth(x);
+ if shift_up<big_op_spacing1 then shift_up:=big_op_spacing1;
+ p:=new_kern(shift_up); vlink(p):=y; vlink(x):=p;@/
+ p:=new_kern(big_op_spacing5); vlink(p):=x; list_ptr(v):=p;
+ height(v):=height(v)+big_op_spacing5+height(x)+depth(x)+shift_up;
+ end;
+if math_type(subscr(q))=empty then begin list_ptr(z):=null; flush_node(z); end
+else begin shift_down:=big_op_spacing4-height(z);
+ if shift_down<big_op_spacing2 then shift_down:=big_op_spacing2;
+ p:=new_kern(shift_down); vlink(y):=p; vlink(p):=z;@/
+ p:=new_kern(big_op_spacing5); vlink(z):=p;
+ depth(v):=depth(v)+big_op_spacing5+height(z)+depth(z)+shift_down;
+ end
+
+@ A ligature found in a math formula does not create a ligature, because
+there is no question of hyphenation afterwards; the ligature will simply be
+stored in an ordinary |glyph_node|, after residing in an |ord_noad|.
+
+The |math_type| is converted to |math_text_char| here if we would not want to
+apply an italic correction to the current character unless it belongs
+to a math font (i.e., a font with |space=0|).
+
+No boundary characters enter into these ligatures.
+
+@<Declare math...@>=
+procedure make_ord(@!q:pointer);
+label restart,exit;
+var a:integer; { the left-side character for lig/kern testing }
+@!p,@!r:pointer; {temporary registers for list manipulation}
+k:scaled; { a kern }
+lig:liginfo; { a ligature }
+begin restart:@t@>@;@/
+if math_type(subscr(q))=empty then if math_type(supscr(q))=empty then
+ if math_type(nucleus(q))=math_char then
+ begin p:=vlink(q);
+ if p<>null then if (type(p)>=ord_noad)and(type(p)<=punct_noad) then
+ if math_type(nucleus(p))=math_char then
+ if fam(nucleus(p))=fam(nucleus(q)) then
+ begin math_type(nucleus(q)):=math_text_char;
+ fetch(nucleus(q)); a:=cur_c;
+ if (has_kern(cur_f,a))or(has_lig(cur_f,a)) then
+ begin cur_c:=mcharacter(nucleus(p));
+ @<If character |a| has a kern with |cur_c|, attach
+ the kern after~|q|; or if it has a ligature with |cur_c|, combine
+ noads |q| and~|p| appropriately; then |return| if the cursor has
+ moved past a noad, or |goto restart|@>;
+ end;
+ end;
+ end;
+exit:end;
+
+@ Note that a ligature between an |ord_noad| and another kind of noad
+is replaced by an |ord_noad|, when the two noads collapse into one.
+But we could make a parenthesis (say) change shape when it follows
+certain letters. Presumably a font designer will define such
+ligatures only when this convention makes sense.
+
+\chardef\?='174 % vertical line to indicate character retention
+
+@<If character |a| has a kern with |cur_c|, ...@>=
+begin
+if disable_lig=0 and has_lig(cur_f,a) then begin
+ lig:=get_ligature(cur_f,a,cur_c);
+ if is_valid_ligature(lig) then begin
+ check_interrupt; {allow a way out of infinite ligature loop}
+ case lig_type(lig) of
+ qi(1),qi(5): mcharacter(nucleus(q)):=lig_replacement(lig); {\.{=:\?}, \.{=:\?>}}
+ qi(2),qi(6): mcharacter(nucleus(p)):=lig_replacement(lig); {\.{\?=:}, \.{\?=:>}}
+ qi(3),qi(7),qi(11):begin r:=new_noad; {\.{\?=:\?}, \.{\?=:\?>}, \.{\?=:\?>>}}
+ mcharacter(nucleus(r)):=lig_replacement(lig);
+ fam(nucleus(r)):=fam(nucleus(q));@/
+ vlink(q):=r; vlink(r):=p;
+ if lig_type(lig)<qi(11) then math_type(nucleus(r)):=math_char
+ else math_type(nucleus(r)):=math_text_char; {prevent combination}
+ end;
+ othercases begin vlink(q):=vlink(p);
+ mcharacter(nucleus(q)):=lig_replacement(lig); {\.{=:}}
+ vmem(subscr(q)):=vmem(subscr(p)); vmem(supscr(q)):=vmem(supscr(p));@/
+ flush_node(p);
+ end
+ endcases;
+ if lig_type(lig)>qi(3) then return;
+ math_type(nucleus(q)):=math_char; goto restart;
+ end;
+ end;
+if disable_kern=0 and has_kern(cur_f,a) then begin
+ k:=get_kern(cur_f,a,cur_c);
+ if k<>0 then begin
+ p:=new_kern(k); vlink(p):=vlink(q); vlink(q):=p; return;
+ end;
+ end;
+end
+
+@ When we get to the following part of the program, we have ``fallen through''
+from cases that did not lead to |check_dimensions| or |done_with_noad| or
+|done_with_node|. Thus, |q|~points to a noad whose nucleus may need to be
+converted to an hlist, and whose subscripts and superscripts need to be
+appended if they are present.
+
+If |nucleus(q)| is not a |math_char|, the variable |delta| is the amount
+by which a superscript should be moved right with respect to a subscript
+when both are present.
+@^subscripts@>
+@^superscripts@>
+
+@<Convert \(n)|nucleus(q)| to an hlist and attach the sub/superscripts@>=
+case math_type(nucleus(q)) of
+math_char, math_text_char:
+ @<Create a character node |p| for |nucleus(q)|, possibly followed
+ by a kern node for the italic correction, and set |delta| to the
+ italic correction if a subscript is present@>;
+empty: p:=null;
+sub_box: p:=vinfo(nucleus(q));
+sub_mlist: begin cur_mlist:=vinfo(nucleus(q)); save_style:=cur_style;
+ mlist_penalties:=false; mlist_to_hlist; {recursive call}
+@^recursion@>
+ cur_style:=save_style; @<Set up the values...@>;
+ p:=hpack(vlink(temp_head),natural);
+ end;
+othercases confusion("mlist2")
+@:this can't happen mlist2}{\quad mlist2@>
+endcases;@/
+new_hlist(q):=p;
+if (math_type(subscr(q))=empty)and(math_type(supscr(q))=empty) then
+ goto check_dimensions;
+make_scripts(q,delta)
+
+@ @<Create a character node |p| for |nucleus(q)|...@>=
+begin fetch(nucleus(q));
+if char_exists(cur_f,cur_c) then
+ begin delta:=char_italic(cur_f,cur_c); p:=new_glyph(cur_f,cur_c);
+ if (math_type(nucleus(q))=math_text_char)and(space(cur_f)<>0) then
+ delta:=0; {no italic correction in mid-word of text font}
+ if (math_type(subscr(q))=empty)and(delta<>0) then
+ begin x:=new_kern(delta); vlink(p):=x; delta:=0;
+ end;
+ end
+else p:=null;
+end
+
+@ The purpose of |make_scripts(q,delta)| is to attach the subscript and/or
+superscript of noad |q| to the list that starts at |new_hlist(q)|,
+given that subscript and superscript aren't both empty. The superscript
+will appear to the right of the subscript by a given distance |delta|.
+
+We set |shift_down| and |shift_up| to the minimum amounts to shift the
+baseline of subscripts and superscripts based on the given nucleus.
+
+@<Declare math...@>=
+procedure make_scripts(@!q:pointer;@!delta:scaled);
+var p,@!x,@!y,@!z:pointer; {temporary registers for box construction}
+@!shift_up,@!shift_down,@!clr:scaled; {dimensions in the calculation}
+@!t:integer; {subsidiary size code}
+begin p:=new_hlist(q);
+if is_char_node(p) then
+ begin shift_up:=0; shift_down:=0;
+ end
+else begin z:=hpack(p,natural);
+ t:=cur_size;
+ if cur_style<script_style
+ then cur_size:=script_size@+else cur_size:=script_script_size;
+ shift_up:=height(z)-sup_drop(cur_size);
+ shift_down:=depth(z)+sub_drop(cur_size);
+ cur_size:=t;
+ list_ptr(z):=null; flush_node(z);
+ end;
+if math_type(supscr(q))=empty then
+ @<Construct a subscript box |x| when there is no superscript@>
+else begin @<Construct a superscript box |x|@>;
+ if math_type(subscr(q))=empty then shift_amount(x):=-shift_up
+ else @<Construct a sub/superscript combination box |x|, with the
+ superscript offset by |delta|@>;
+ end;
+if new_hlist(q)=null then new_hlist(q):=x
+else begin p:=new_hlist(q);
+ while vlink(p)<>null do p:=vlink(p);
+ vlink(p):=x;
+ end;
+end;
+
+@ When there is a subscript without a superscript, the top of the subscript
+should not exceed the baseline plus four-fifths of the x-height.
+
+@<Construct a subscript box |x| when there is no superscript@>=
+begin x:=clean_box(subscr(q),sub_style(cur_style));
+width(x):=width(x)+script_space;
+if shift_down<sub1(cur_size) then shift_down:=sub1(cur_size);
+clr:=height(x)-(abs(math_x_height(cur_size)*4) div 5);
+if shift_down<clr then shift_down:=clr;
+shift_amount(x):=shift_down;
+end
+
+@ The bottom of a superscript should never descend below the baseline plus
+one-fourth of the x-height.
+
+@<Construct a superscript box |x|@>=
+begin x:=clean_box(supscr(q),sup_style(cur_style));
+width(x):=width(x)+script_space;
+if odd(cur_style) then clr:=sup3(cur_size)
+else if cur_style<text_style then clr:=sup1(cur_size)
+else clr:=sup2(cur_size);
+if shift_up<clr then shift_up:=clr;
+clr:=depth(x)+(abs(math_x_height(cur_size)) div 4);
+if shift_up<clr then shift_up:=clr;
+end
+
+@ When both subscript and superscript are present, the subscript must be
+separated from the superscript by at least four times |default_rule_thickness|.
+If this condition would be violated, the subscript moves down, after which
+both subscript and superscript move up so that the bottom of the superscript
+is at least as high as the baseline plus four-fifths of the x-height.
+
+@<Construct a sub/superscript combination box |x|...@>=
+begin y:=clean_box(subscr(q),sub_style(cur_style));
+width(y):=width(y)+script_space;
+if shift_down<sub2(cur_size) then shift_down:=sub2(cur_size);
+clr:=4*default_rule_thickness-
+ ((shift_up-depth(x))-(height(y)-shift_down));
+if clr>0 then
+ begin shift_down:=shift_down+clr;
+ clr:=(abs(math_x_height(cur_size)*4) div 5)-(shift_up-depth(x));
+ if clr>0 then
+ begin shift_up:=shift_up+clr;
+ shift_down:=shift_down-clr;
+ end;
+ end;
+shift_amount(x):=delta; {superscript is |delta| to the right of the subscript}
+p:=new_kern((shift_up-depth(x))-(height(y)-shift_down)); vlink(x):=p; vlink(p):=y;
+pack_direction:=math_direction;
+x:=vpack(x,natural); shift_amount(x):=shift_down;
+end
+
+@ We have now tied up all the loose ends of the first pass of |mlist_to_hlist|.
+The second pass simply goes through and hooks everything together with the
+proper glue and penalties. It also handles the |left_noad| and |right_noad| that
+might be present, since |max_hl| and |max_d| are now known. Variable |p| points
+to a node at the current end of the final hlist.
+
+@<Make a second pass over the mlist, ...@>=
+p:=temp_head; vlink(p):=null; q:=mlist; r_type:=0; cur_style:=style;
+@<Set up the values of |cur_size| and |cur_mu|, based on |cur_style|@>;
+while q<>null do
+ begin @<If node |q| is a style node, change the style and |goto delete_q|;
+ otherwise if it is not a noad, put it into the hlist,
+ advance |q|, and |goto done|; otherwise set |s| to the size
+ of noad |q|, set |t| to the associated type (|ord_noad..
+ inner_noad|), and set |pen| to the associated penalty@>;
+ @<Append inter-element spacing based on |r_type| and |t|@>;
+ @<Append any |new_hlist| entries for |q|, and any appropriate penalties@>;
+ if type(q)=right_noad then t:=open_noad;
+ r_type:=t;
+ delete_q: r:=q; q:=vlink(q);
+ flush_node(r); {|r| had better be a noad-like thing }
+ done: end
+
+@ Just before doing the big |case| switch in the second pass, the program
+sets up default values so that most of the branches are short.
+
+@<If node |q| is a style node, change the style...@>=
+t:=ord_noad; s:=noad_size; pen:=inf_penalty;
+case type(q) of
+op_noad,open_noad,close_noad,punct_noad,inner_noad: t:=type(q);
+bin_noad: begin t:=bin_noad; pen:=bin_op_penalty;
+ end;
+rel_noad: begin t:=rel_noad; pen:=rel_penalty;
+ end;
+ord_noad,vcenter_noad,over_noad,under_noad: do_nothing;
+radical_noad: s:=radical_noad_size;
+accent_noad: s:=accent_noad_size;
+fraction_noad: begin t:=inner_noad; s:=fraction_noad_size;
+ end;
+left_noad,right_noad: t:=make_left_right(q,style,max_d,max_hl);
+style_node: @<Change the current style and |goto delete_q|@>;
+whatsit_node,penalty_node,rule_node,disc_node,adjust_node,ins_node,mark_node,
+ glue_node,kern_node:@t@>@;@/
+ begin vlink(p):=q; p:=q; q:=vlink(q); vlink(p):=null; goto done;
+ end;
+othercases confusion("mlist3")
+@:this can't happen mlist3}{\quad mlist3@>
+endcases
+
+@ The |make_left_right| function constructs a left or right delimiter of
+the required size and returns the value |open_noad| or |close_noad|. The
+|right_noad| and |left_noad| will both be based on the original |style|,
+so they will have consistent sizes.
+
+We use the fact that |right_noad-left_noad=close_noad-open_noad|.
+
+@<Declare math...@>=
+function make_left_right(@!q:pointer;@!style:integer;
+ @!max_d,@!max_hv:scaled):small_number;
+var delta,@!delta1,@!delta2:scaled; {dimensions used in the calculation}
+tmp:pointer;
+begin cur_style:=style; @<Set up the values...@>;
+delta2:=max_d+axis_height(cur_size);
+delta1:=max_hv+max_d-delta2;
+if delta2>delta1 then delta1:=delta2; {|delta1| is max distance from axis}
+delta:=(delta1 div 500)*delimiter_factor;
+delta2:=delta1+delta1-delimiter_shortfall;
+if delta<delta2 then delta:=delta2;
+tmp:=var_delimiter(delimiter(q),cur_size,delta);
+new_hlist(q):=tmp;
+make_left_right:=type(q)-(left_noad-open_noad); {|open_noad| or |close_noad|}
+end;
+
+@ @<Change the current style and |goto delete_q|@>=
+begin cur_style:=subtype(q); s:=style_node_size;
+@<Set up the values of |cur_size| and |cur_mu|, based on |cur_style|@>;
+goto delete_q;
+end
+
+@ The inter-element spacing in math formulas depends on a $8\times8$ table that
+\TeX\ preloads as a 64-digit string. The elements of this string have the
+following significance:
+$$\vbox{\halign{#\hfil\cr
+\.0 means no space;\cr
+\.1 means a conditional thin space (\.{\\nonscript\\mskip\\thinmuskip});\cr
+\.2 means a thin space (\.{\\mskip\\thinmuskip});\cr
+\.3 means a conditional medium space
+ (\.{\\nonscript\\mskip\\medmuskip});\cr
+\.4 means a conditional thick space
+ (\.{\\nonscript\\mskip\\thickmuskip});\cr
+\.* means an impossible case.\cr}}$$
+This is all pretty cryptic, but {\sl The \TeX book\/} explains what is
+supposed to happen, and the string makes it happen.
+@:TeXbook}{\sl The \TeX book@>
+
+A global variable |magic_offset| is computed so that if |a| and |b| are
+in the range |ord_noad..inner_noad|, then |str_pool[a*8+b+magic_offset]|
+is the digit for spacing between noad types |a| and |b|.
+
+If \PASCAL\ had provided a good way to preload constant arrays, this part of
+the program would not have been so strange.
+@:PASCAL}{\PASCAL@>
+
+@d math_spacing=@;@/
+@t\hskip-35pt@>
+"0234000122*4000133**3**344*0400400*000000234000111*1111112341011"
+@t$ \hskip-35pt$@>
+
+@<Glob...@>=
+@!magic_offset:integer; {used to find inter-element spacing}
+
+@ @<Compute the magic offset@>=
+magic_offset:=str_start_macro(math_spacing)-9*ord_noad
+
+@ @<Append inter-element spacing based on |r_type| and |t|@>=
+if r_type>0 then {not the first noad}
+ begin case so(str_pool[r_type*8+t+magic_offset]) of
+ "0": x:=0;
+ "1": if cur_style<script_style then x:=thin_mu_skip_code@+else x:=0;
+ "2": x:=thin_mu_skip_code;
+ "3": if cur_style<script_style then x:=med_mu_skip_code@+else x:=0;
+ "4": if cur_style<script_style then x:=thick_mu_skip_code@+else x:=0;
+ othercases confusion("mlist4")
+@:this can't happen mlist4}{\quad mlist4@>
+ endcases;
+ if x<>0 then
+ begin y:=math_glue(glue_par(x),cur_mu);
+ z:=new_glue(y); glue_ref_count(y):=null; vlink(p):=z; p:=z;@/
+ subtype(z):=x+1; {store a symbolic subtype}
+ end;
+ end
+
+@ We insert a penalty node after the hlist entries of noad |q| if |pen|
+is not an ``infinite'' penalty, and if the node immediately following |q|
+is not a penalty node or a |rel_noad| or absent entirely.
+
+@<Append any |new_hlist| entries for |q|, and any appropriate penalties@>=
+if new_hlist(q)<>null then
+ begin vlink(p):=new_hlist(q);
+ repeat p:=vlink(p);
+ until vlink(p)=null;
+ end;
+if penalties then if vlink(q)<>null then if pen<inf_penalty then
+ begin r_type:=type(vlink(q));
+ if r_type<>penalty_node then if r_type<>rel_noad then
+ begin z:=new_penalty(pen); vlink(p):=z; p:=z;
+ end;
+ end
+
+@* \[37] Alignment.
+It's sort of a miracle whenever \.{\\halign} and \.{\\valign} work, because
+they cut across so many of the control structures of \TeX.
+
+Therefore the
+present page is probably not the best place for a beginner to start reading
+this program; it is better to master everything else first.
+
+Let us focus our thoughts on an example of what the input might be, in order
+to get some idea about how the alignment miracle happens. The example doesn't
+do anything useful, but it is sufficiently general to indicate all of the
+special cases that must be dealt with; please do not be disturbed by its
+apparent complexity and meaninglessness.
+$$\vbox{\halign{\.{#}\hfil\cr
+{}\\tabskip 2pt plus 3pt\cr
+{}\\halign to 300pt\{u1\#v1\&\cr
+\hskip 50pt\\tabskip 1pt plus 1fil u2\#v2\&\cr
+\hskip 50pt u3\#v3\\cr\cr
+\hskip 25pt a1\&\\omit a2\&\\vrule\\cr\cr
+\hskip 25pt \\noalign\{\\vskip 3pt\}\cr
+\hskip 25pt b1\\span b2\\cr\cr
+\hskip 25pt \\omit\&c2\\span\\omit\\cr\}\cr}}$$
+Here's what happens:
+
+\yskip
+(0) When `\.{\\halign to 300pt\{}' is scanned, the |scan_spec| routine
+places the 300pt dimension onto the |save_stack|, and an |align_group|
+code is placed above it. This will make it possible to complete the alignment
+when the matching `\.\}' is found.
+
+(1) The preamble is scanned next. Macros in the preamble are not expanded,
+@^preamble@>
+except as part of a tabskip specification. For example, if \.{u2} had been
+a macro in the preamble above, it would have been expanded, since \TeX\
+must look for `\.{minus...}' as part of the tabskip glue. A ``preamble list''
+is constructed based on the user's preamble; in our case it contains the
+following seven items:
+$$\vbox{\halign{\.{#}\hfil\qquad&(#)\hfil\cr
+{}\\glue 2pt plus 3pt&the tabskip preceding column 1\cr
+{}\\alignrecord, width $-\infty$&preamble info for column 1\cr
+{}\\glue 2pt plus 3pt&the tabskip between columns 1 and 2\cr
+{}\\alignrecord, width $-\infty$&preamble info for column 2\cr
+{}\\glue 1pt plus 1fil&the tabskip between columns 2 and 3\cr
+{}\\alignrecord, width $-\infty$&preamble info for column 3\cr
+{}\\glue 1pt plus 1fil&the tabskip following column 3\cr}}$$
+These ``alignrecord'' entries have the same size as an |unset_node|,
+since they will later be converted into such nodes. These alignrecord
+nodes have no |depth| field; this is split into |u_part| and |v_part|,
+and they point to token lists for the templates of the alignment. For
+example, the |u_part| field in the first alignrecord points to the
+token list `\.{u1}', i.e., the template preceding the `\.\#' for
+column~1. Furthermore, They have a |span_ptr| instead of a |node_attr|
+field, and these |span_ptr| fields are initially set to the value
+|end_span|, for reasons explained below.
+
+(2) \TeX\ now looks at what follows the \.{\\cr} that ended the preamble.
+It is not `\.{\\noalign}' or `\.{\\omit}', so this input is put back to
+be read again, and the template `\.{u1}' is fed to the scanner. Just
+before reading `\.{u1}', \TeX\ goes into restricted horizontal mode.
+Just after reading `\.{u1}', \TeX\ will see `\.{a1}', and then (when the
+{\.\&} is sensed) \TeX\ will see `\.{v1}'. Then \TeX\ scans an |endv|
+token, indicating the end of a column. At this point an |unset_node| is
+created, containing the contents of the current hlist (i.e., `\.{u1a1v1}').
+The natural width of this unset node replaces the |width| field of the
+alignrecord for column~1; in general, the alignrecords will record the
+maximum natural width that has occurred so far in a given column.
+
+(3) Since `\.{\\omit}' follows the `\.\&', the templates for column~2
+are now bypassed. Again \TeX\ goes into restricted horizontal mode and
+makes an |unset_node| from the resulting hlist; but this time the
+hlist contains simply `\.{a2}'. The natural width of the new unset box
+is remembered in the |width| field of the alignrecord for column~2.
+
+(4) A third |unset_node| is created for column 3, using essentially the
+mechanism that worked for column~1; this unset box contains `\.{u3\\vrule
+v3}'. The vertical rule in this case has running dimensions that will later
+extend to the height and depth of the whole first row, since each |unset_node|
+in a row will eventually inherit the height and depth of its enclosing box.
+
+(5) The first row has now ended; it is made into a single unset box
+comprising the following seven items:
+$$\vbox{\halign{\hbox to 325pt{\qquad\.{#}\hfil}\cr
+{}\\glue 2pt plus 3pt\cr
+{}\\unsetbox for 1 column: u1a1v1\cr
+{}\\glue 2pt plus 3pt\cr
+{}\\unsetbox for 1 column: a2\cr
+{}\\glue 1pt plus 1fil\cr
+{}\\unsetbox for 1 column: u3\\vrule v3\cr
+{}\\glue 1pt plus 1fil\cr}}$$
+The width of this unset row is unimportant, but it has the correct height
+and depth, so the correct baselineskip glue will be computed as the row
+is inserted into a vertical list.
+
+(6) Since `\.{\\noalign}' follows the current \.{\\cr}, \TeX\ appends
+additional material (in this case \.{\\vskip 3pt}) to the vertical list.
+While processing this material, \TeX\ will be in internal vertical
+mode, and |no_align_group| will be on |save_stack|.
+
+(7) The next row produces an unset box that looks like this:
+$$\vbox{\halign{\hbox to 325pt{\qquad\.{#}\hfil}\cr
+{}\\glue 2pt plus 3pt\cr
+{}\\unsetbox for 2 columns: u1b1v1u2b2v2\cr
+{}\\glue 1pt plus 1fil\cr
+{}\\unsetbox for 1 column: {\rm(empty)}\cr
+{}\\glue 1pt plus 1fil\cr}}$$
+The natural width of the unset box that spans columns 1~and~2 is stored
+in a ``span node,'' which we will explain later; the |span_ptr| field of the
+alignrecord for column~1 now points to the new span node, and the |span_ptr|
+of the span node points to |end_span|.
+
+(8) The final row produces the unset box
+$$\vbox{\halign{\hbox to 325pt{\qquad\.{#}\hfil}\cr
+{}\\glue 2pt plus 3pt\cr
+{}\\unsetbox for 1 column: {\rm(empty)}\cr
+{}\\glue 2pt plus 3pt\cr
+{}\\unsetbox for 2 columns: u2c2v2\cr
+{}\\glue 1pt plus 1fil\cr}}$$
+A new span node is attached to the alignrecord for column 2.
+
+(9) The last step is to compute the true column widths and to change all the
+unset boxes to hboxes, appending the whole works to the vertical list that
+encloses the \.{\\halign}. The rules for deciding on the final widths of
+each unset column box will be explained below.
+
+\yskip\noindent
+Note that as \.{\\halign} is being processed, we fearlessly give up control
+to the rest of \TeX. At critical junctures, an alignment routine is
+called upon to step in and do some little action, but most of the time
+these routines just lurk in the background. It's something like
+post-hypnotic suggestion.
+
+@ We have mentioned that alignrecords contain no |height| or |depth| fields.
+Their |glue_sign| and |glue_order| are pre-empted as well, since it
+is necessary to store information about what to do when a template ends.
+This information is called the |extra_info| field.
+
+@d align_record_node=34
+@d u_part(#)==vlink(#+depth_offset) {pointer to \<u_j> token list}
+@d v_part(#)==vinfo(#+depth_offset) {pointer to \<v_j> token list}
+@d span_ptr(#)==vinfo(#+1) {column spanning list}
+@d extra_info(#)==vinfo(#+list_offset) {info to remember during template}
+
+@ Alignments can occur within alignments, so a small stack is used to access
+the alignrecord information. At each level we have a |preamble| pointer,
+indicating the beginning of the preamble list; a |cur_align| pointer,
+indicating the current position in the preamble list; a |cur_span| pointer,
+indicating the value of |cur_align| at the beginning of a sequence of
+spanned columns; a |cur_loop| pointer, indicating the tabskip glue before
+an alignrecord that should be copied next if the current list is extended;
+and the |align_state| variable, which indicates the nesting of braces so
+that \.{\\cr} and \.{\\span} and tab marks are properly intercepted.
+There also are pointers |cur_head| and |cur_tail| to the head and tail
+of a list of adjustments being moved out from horizontal mode to
+vertical~mode, and alike |cur_pre_head| and |cur_pre_tail| for pre-adjust
+lists.
+
+The current values of these nine quantities appear in global variables;
+when they have to be pushed down, they are stored in 6-word nodes, and
+|align_ptr| points to the topmost such node.
+
+@d preamble==vlink(align_head) {the current preamble list}
+@d align_stack_node=47
+
+@<Glob...@>=
+@!cur_align:pointer; {current position in preamble list}
+@!cur_span:pointer; {start of currently spanned columns in preamble list}
+@!cur_loop:pointer; {place to copy when extending a periodic preamble}
+@!align_ptr:pointer; {most recently pushed-down alignment stack node}
+@!cur_head,@!cur_tail:pointer; {adjustment list pointers}
+@!cur_pre_head,@!cur_pre_tail:pointer; {pre-adjustment list pointers}
+
+@ The |align_state| and |preamble| variables are initialized elsewhere.
+
+@<Set init...@>=
+align_ptr:=null; cur_align:=null; cur_span:=null; cur_loop:=null;
+cur_head:=null; cur_tail:=null;
+cur_pre_head:=null; cur_pre_tail:=null;
+
+@ Alignment stack maintenance is handled by a pair of trivial routines
+called |push_alignment| and |pop_alignment|.
+
+@p procedure push_alignment;
+var p:pointer; {the new alignment stack node}
+begin p:=new_node(align_stack_node,0);
+vinfo(p+1):=align_ptr; vlink(p+1):=cur_align;
+vinfo(p+2):=preamble; vlink(p+2):=cur_span;
+vinfo(p+3):=cur_loop; vlink(p+3):=align_state;
+vinfo(p+4):=cur_head; vlink(p+4):=cur_tail;
+vinfo(p+5):=cur_pre_head; vlink(p+5):=cur_pre_tail;
+align_ptr:=p;
+cur_head:=new_node(temp_node,0);
+end;
+@#
+procedure pop_alignment;
+var p:pointer; {the top alignment stack node}
+begin flush_node(cur_head);
+p:=align_ptr;
+cur_pre_tail:=vlink(p+5); cur_pre_head:=vinfo(p+5);
+cur_tail :=vlink(p+4); cur_head :=vinfo(p+4);
+align_state :=vlink(p+3); cur_loop :=vinfo(p+3);
+cur_span :=vlink(p+2); preamble :=vinfo(p+2);
+cur_align :=vlink(p+1); align_ptr :=vinfo(p+1);
+flush_node(p);
+end;
+
+@ \TeX\ has eight procedures that govern alignments: |init_align| and
+|fin_align| are used at the very beginning and the very end; |init_row| and
+|fin_row| are used at the beginning and end of individual rows; |init_span|
+is used at the beginning of a sequence of spanned columns (possibly involving
+only one column); |init_col| and |fin_col| are used at the beginning and
+end of individual columns; and |align_peek| is used after \.{\\cr} to see
+whether the next item is \.{\\noalign}.
+
+We shall consider these routines in the order they are first used during
+the course of a complete \.{\\halign}, namely |init_align|, |align_peek|,
+|init_row|, |init_span|, |init_col|, |fin_col|, |fin_row|, |fin_align|.
+
+@ When \.{\\halign} or \.{\\valign} has been scanned in an appropriate
+mode, \TeX\ calls |init_align|, whose task is to get everything off to a
+good start. This mostly involves scanning the preamble and putting its
+information into the preamble list.
+@^preamble@>
+
+@p @t\4@>@<Declare the procedure called |get_preamble_token|@>@t@>@/
+procedure@?align_peek; forward;@t\2@>@/
+procedure@?normal_paragraph; forward;@t\2@>@/
+procedure init_align;
+label done, done1, done2, continue;
+var save_cs_ptr:pointer; {|warning_index| value for error messages}
+@!p,r:pointer; {for short-term temporary use}
+begin save_cs_ptr:=cur_cs; {\.{\\halign} or \.{\\valign}, usually}
+push_alignment; align_state:=-1000000; {enter a new alignment level}
+@<Check for improper alignment in displayed math@>;
+push_nest; {enter a new semantic level}
+@<Change current mode to |-vmode| for \.{\\halign}, |-hmode| for \.{\\valign}@>;
+scan_spec(align_group,false);@/
+@<Scan the preamble and record it in the |preamble| list@>;
+new_save_level(align_group);
+if every_cr<>null then begin_token_list(every_cr,every_cr_text);
+align_peek; {look for \.{\\noalign} or \.{\\omit}}
+end;
+
+@ In vertical modes, |prev_depth| already has the correct value. But
+if we are in |mmode| (displayed formula mode), we reach out to the
+enclosing vertical mode for the |prev_depth| value that produces the
+correct baseline calculations.
+
+@<Change current mode...@>=
+if mode=mmode then
+ begin mode:=-vmode; prev_depth:=nest[nest_ptr-2].aux_field.sc;
+ end
+else if mode>0 then negate(mode)
+
+@ When \.{\\halign} is used as a displayed formula, there should be
+no other pieces of mlists present.
+
+@<Check for improper alignment in displayed math@>=
+if (mode=mmode)and((tail<>head)or(incompleat_noad<>null)) then
+ begin print_err("Improper "); print_esc("halign"); print(" inside $$'s");
+@.Improper \\halign...@>
+ help3("Displays can use special alignments (like \eqalignno)")@/
+ ("only if nothing but the alignment itself is between $$'s.")@/
+ ("So I've deleted the formulas that preceded this alignment.");
+ error; flush_math;
+ end
+
+@ @<Scan the preamble and record it in the |preamble| list@>=
+preamble:=null; cur_align:=align_head; cur_loop:=null; scanner_status:=aligning;
+warning_index:=save_cs_ptr; align_state:=-1000000;
+ {at this point, |cur_cmd=left_brace|}
+loop@+ begin @<Append the current tabskip glue to the preamble list@>;
+ if cur_cmd=car_ret then goto done; {\.{\\cr} ends the preamble}
+ @<Scan preamble text until |cur_cmd| is |tab_mark| or |car_ret|,
+ looking for changes in the tabskip glue; append an
+ alignrecord to the preamble list@>;
+ end;
+done: scanner_status:=normal
+
+@ @<Append the current tabskip glue to the preamble list@>=
+r:=new_param_glue(tab_skip_code); vlink(cur_align):=r;
+cur_align:=vlink(cur_align)
+
+@ @<Scan preamble text until |cur_cmd| is |tab_mark| or |car_ret|...@>=
+@<Scan the template \<u_j>, putting the resulting token list in |hold_token_head|@>;
+r:=new_node(align_record_node,0); vlink(cur_align):=r;
+cur_align:=vlink(cur_align); {a new alignrecord}
+span_ptr(cur_align):=end_span; width(cur_align):=null_flag;
+u_part(cur_align):=link(hold_token_head);
+@<Scan the template \<v_j>, putting the resulting token list in |hold_token_head|@>;
+v_part(cur_align):=link(hold_token_head)
+
+@ We enter `\.{\\span}' into |eqtb| with |tab_mark| as its command code,
+and with |span_code| as the command modifier. This makes \TeX\ interpret it
+essentially the same as an alignment delimiter like `\.\&', yet it is
+recognizably different when we need to distinguish it from a normal delimiter.
+It also turns out to be useful to give a special |cr_code| to `\.{\\cr}',
+and an even larger |cr_cr_code| to `\.{\\crcr}'.
+
+The end of a template is represented by two ``frozen'' control sequences
+called \.{\\endtemplate}. The first has the command code |end_template|, which
+is |>outer_call|, so it will not easily disappear in the presence of errors.
+The |get_x_token| routine converts the first into the second, which has |endv|
+as its command code.
+
+@d span_code=special_char {distinct from any character}
+@d cr_code=span_code+1 {distinct from |span_code| and from any character}
+@d cr_cr_code=cr_code+1 {this distinguishes \.{\\crcr} from \.{\\cr}}
+@d end_template_token==cs_token_flag+frozen_end_template
+
+@<Put each of \TeX's primitives into the hash table@>=
+primitive("span",tab_mark,span_code);@/
+@!@:span_}{\.{\\span} primitive@>
+primitive("cr",car_ret,cr_code);
+@!@:cr_}{\.{\\cr} primitive@>
+text(frozen_cr):="cr"; eqtb[frozen_cr]:=eqtb[cur_val];@/
+primitive("crcr",car_ret,cr_cr_code);
+@!@:cr_cr_}{\.{\\crcr} primitive@>
+text(frozen_end_template):="endtemplate"; text(frozen_endv):="endtemplate";
+eq_type(frozen_endv):=endv; equiv(frozen_endv):=null_list;
+eq_level(frozen_endv):=level_one;@/
+eqtb[frozen_end_template]:=eqtb[frozen_endv];
+eq_type(frozen_end_template):=end_template;
+
+@ @<Cases of |print_cmd_chr|...@>=
+tab_mark: if chr_code=span_code then print_esc("span")
+ else chr_cmd("alignment tab character ");
+car_ret: if chr_code=cr_code then print_esc("cr")
+ else print_esc("crcr");
+
+@ The preamble is copied directly, except that \.{\\tabskip} causes a change
+to the tabskip glue, thereby possibly expanding macros that immediately
+follow it. An appearance of \.{\\span} also causes such an expansion.
+
+Note that if the preamble contains `\.{\\global\\tabskip}', the `\.{\\global}'
+token survives in the preamble and the `\.{\\tabskip}' defines new
+tabskip glue (locally).
+
+@<Declare the procedure called |get_preamble_token|@>=
+procedure get_preamble_token;
+label restart;
+begin restart: get_token;
+while (cur_chr=span_code)and(cur_cmd=tab_mark) do
+ begin get_token; {this token will be expanded once}
+ if cur_cmd>max_command then
+ begin expand; get_token;
+ end;
+ end;
+if cur_cmd=endv then
+ fatal_error("(interwoven alignment preambles are not allowed)");
+@.interwoven alignment preambles...@>
+if (cur_cmd=assign_glue)and(cur_chr=glue_base+tab_skip_code) then
+ begin scan_optional_equals; scan_glue(glue_val);
+ if global_defs>0 then geq_define(glue_base+tab_skip_code,glue_ref,cur_val)
+ else eq_define(glue_base+tab_skip_code,glue_ref,cur_val);
+ goto restart;
+ end;
+end;
+
+@ Spaces are eliminated from the beginning of a template.
+
+@<Scan the template \<u_j>...@>=
+p:=hold_token_head; link(p):=null;
+loop@+ begin get_preamble_token;
+ if cur_cmd=mac_param then goto done1;
+ if (cur_cmd<=car_ret)and(cur_cmd>=tab_mark)and(align_state=-1000000) then
+ if (p=hold_token_head)and(cur_loop=null)and(cur_cmd=tab_mark)
+ then cur_loop:=cur_align
+ else begin print_err("Missing # inserted in alignment preamble");
+@.Missing \# inserted...@>
+ help3("There should be exactly one # between &'s, when an")@/
+ ("\halign or \valign is being set up. In this case you had")@/
+ ("none, so I've put one in; maybe that will work.");
+ back_error; goto done1;
+ end
+ else if (cur_cmd<>spacer)or(p<>hold_token_head) then
+ begin r:=get_avail; link(p):=r; p:=link(p); info(p):=cur_tok;
+ end;
+ end;
+done1:
+
+@ @<Scan the template \<v_j>...@>=
+p:=hold_token_head; link(p):=null;
+loop@+ begin continue: get_preamble_token;
+ if (cur_cmd<=car_ret)and(cur_cmd>=tab_mark)and(align_state=-1000000) then
+ goto done2;
+ if cur_cmd=mac_param then
+ begin print_err("Only one # is allowed per tab");
+@.Only one \# is allowed...@>
+ help3("There should be exactly one # between &'s, when an")@/
+ ("\halign or \valign is being set up. In this case you had")@/
+ ("more than one, so I'm ignoring all but the first.");
+ error; goto continue;
+ end;
+ r:=get_avail; link(p):=r; p:=link(p); info(p):=cur_tok;
+ end;
+done2: r:=get_avail; link(p):=r; p:=link(p);
+info(p):=end_template_token {put \.{\\endtemplate} at the end}
+
+@ The tricky part about alignments is getting the templates into the
+scanner at the right time, and recovering control when a row or column
+is finished.
+
+We usually begin a row after each \.{\\cr} has been sensed, unless that
+\.{\\cr} is followed by \.{\\noalign} or by the right brace that terminates
+the alignment. The |align_peek| routine is used to look ahead and do
+the right thing; it either gets a new row started, or gets a \.{\\noalign}
+started, or finishes off the alignment.
+
+@<Declare the procedure called |align_peek|@>=
+procedure align_peek;
+label restart;
+begin restart: align_state:=1000000;
+repeat get_x_or_protected;
+until cur_cmd<>spacer;
+if cur_cmd=no_align then
+ begin scan_left_brace; new_save_level(no_align_group);
+ if mode=-vmode then normal_paragraph;
+ end
+else if cur_cmd=right_brace then fin_align
+else if (cur_cmd=car_ret)and(cur_chr=cr_cr_code) then
+ goto restart {ignore \.{\\crcr}}
+else begin init_row; {start a new row}
+ init_col; {start a new column and replace what we peeked at}
+ end;
+end;
+
+@ To start a row (i.e., a `row' that rhymes with `dough' but not with `bough'),
+we enter a new semantic level, copy the first tabskip glue, and change
+from internal vertical mode to restricted horizontal mode or vice versa.
+The |space_factor| and |prev_depth| are not used on this semantic level,
+but we clear them to zero just to be tidy.
+
+@p @t\4@>@<Declare the procedure called |init_span|@>@t@>@/
+procedure init_row;
+begin push_nest; mode:=(-hmode-vmode)-mode;
+if mode=-hmode then space_factor:=0 @+else prev_depth:=0;
+tail_append(new_glue(glue_ptr(preamble)));
+subtype(tail):=tab_skip_code+1;@/
+cur_align:=vlink(preamble); cur_tail:=cur_head; cur_pre_tail:=cur_pre_head;
+init_span(cur_align);
+end;
+
+@ The parameter to |init_span| is a pointer to the alignrecord where the
+next column or group of columns will begin. A new semantic level is
+entered, so that the columns will generate a list for subsequent packaging.
+
+@<Declare the procedure called |init_span|@>=
+procedure init_span(@!p:pointer);
+begin push_nest;
+if mode=-hmode then space_factor:=1000
+else begin prev_depth:=ignore_depth; normal_paragraph;
+ end;
+cur_span:=p;
+end;
+
+@ When a column begins, we assume that |cur_cmd| is either |omit| or else
+the current token should be put back into the input until the \<u_j>
+template has been scanned. (Note that |cur_cmd| might be |tab_mark| or
+|car_ret|.) We also assume that |align_state| is approximately 1000000 at
+this time. We remain in the same mode, and start the template if it is
+called for.
+
+@p procedure init_col;
+begin extra_info(cur_align):=cur_cmd;
+if cur_cmd=omit then align_state:=0
+else begin back_input; begin_token_list(u_part(cur_align),u_template);
+ end; {now |align_state=1000000|}
+end;
+
+@ The scanner sets |align_state| to zero when the \<u_j> template ends. When
+a subsequent \.{\\cr} or \.{\\span} or tab mark occurs with |align_state=0|,
+the scanner activates the following code, which fires up the \<v_j> template.
+We need to remember the |cur_chr|, which is either |cr_cr_code|, |cr_code|,
+|span_code|, or a character code, depending on how the column text has ended.
+
+This part of the program had better not be activated when the preamble
+to another alignment is being scanned, or when no alignment preamble is active.
+
+@p procedure insert_vj_template;
+begin if (scanner_status=aligning) or (cur_align=null) then
+ fatal_error("(interwoven alignment preambles are not allowed)");
+@.interwoven alignment preambles...@>
+cur_cmd:=extra_info(cur_align); extra_info(cur_align):=cur_chr;
+if cur_cmd=omit then begin_token_list(omit_template,v_template)
+else begin_token_list(v_part(cur_align),v_template);
+align_state:=1000000;
+end;
+
+@ The token list |omit_template| just referred to is a constant token
+list that contains the special control sequence \.{\\endtemplate} only.
+
+@<Initialize the special...@>=
+info(omit_template):=end_template_token; {|link(omit_template)=null|}
+
+@ When the |endv| command at the end of a \<v_j> template comes through the
+scanner, things really start to happen; and it is the |fin_col| routine
+that makes them happen. This routine returns |true| if a row as well as a
+column has been finished.
+
+@p function fin_col:boolean;
+label exit;
+var p:pointer; {the alignrecord after the current one}
+@!q,@!r:pointer; {temporary pointers for list manipulation}
+@!s:pointer; {a new span node}
+@!u:pointer; {a new unset box}
+@!w:scaled; {natural width}
+@!o:glue_ord; {order of infinity}
+@!n:halfword; {span counter}
+begin if cur_align=null then confusion("endv");
+q:=vlink(cur_align);@+if q=null then confusion("endv");
+@:this can't happen endv}{\quad endv@>
+if align_state<500000 then
+ fatal_error("(interwoven alignment preambles are not allowed)");
+@.interwoven alignment preambles...@>
+p:=vlink(q);
+@<If the preamble list has been traversed, check that the row has ended@>;
+if extra_info(cur_align)<>span_code then
+ begin unsave; new_save_level(align_group);@/
+ @<Package an unset box for the current column and record its width@>;
+ @<Copy the tabskip glue between columns@>;
+ if extra_info(cur_align)>=cr_code then
+ begin fin_col:=true; return;
+ end;
+ init_span(p);
+ end;
+align_state:=1000000;
+repeat get_x_or_protected;
+until cur_cmd<>spacer;
+cur_align:=p;
+init_col; fin_col:=false;
+exit: end;
+
+@ @<If the preamble list has been traversed, check that the row has ended@>=
+if (p=null)and(extra_info(cur_align)<cr_code) then
+ if cur_loop<>null then @<Lengthen the preamble periodically@>
+ else begin print_err("Extra alignment tab has been changed to ");
+@.Extra alignment tab...@>
+ print_esc("cr");
+ help3("You have given more \span or & marks than there were")@/
+ ("in the preamble to the \halign or \valign now in progress.")@/
+ ("So I'll assume that you meant to type \cr instead.");
+ extra_info(cur_align):=cr_code; error;
+ end
+
+@ @<Lengthen the preamble...@>=
+begin r:=new_node(align_record_node,0); vlink(q):=r; p:=vlink(q); {a new alignrecord}
+span_ptr(p):=end_span; width(p):=null_flag; cur_loop:=vlink(cur_loop);
+@<Copy the templates from node |cur_loop| into node |p|@>;
+cur_loop:=vlink(cur_loop);
+r:=new_glue(glue_ptr(cur_loop)); vlink(p):=r;
+end
+
+@ @<Copy the templates from node |cur_loop| into node |p|@>=
+q:=hold_token_head; r:=u_part(cur_loop);
+while r<>null do
+ begin s:=get_avail; link(q):=s; q:=link(q); info(q):=info(r); r:=link(r);
+ end;
+link(q):=null; u_part(p):=link(hold_token_head);
+q:=hold_token_head; r:=v_part(cur_loop);
+while r<>null do
+ begin s:=get_avail; link(q):=s; q:=link(q); info(q):=info(r); r:=link(r);
+ end;
+link(q):=null; v_part(p):=link(hold_token_head)
+
+@ @<Copy the tabskip glue...@>=
+tail_append(new_glue(glue_ptr(vlink(cur_align))));
+subtype(tail):=tab_skip_code+1
+
+@ @<Package an unset...@>=
+begin if mode=-hmode then
+ begin adjust_tail:=cur_tail; pre_adjust_tail:=cur_pre_tail;
+ u:=filtered_hpack(head,tail,natural,align_set_group); w:=width(u);
+ cur_tail:=adjust_tail; adjust_tail:=null;
+ cur_pre_tail:=pre_adjust_tail; pre_adjust_tail:=null;
+ end
+else begin u:=filtered_vpackage(vlink(head),natural,0,align_set_group); w:=height(u);
+ end;
+n:=min_quarterword; {this represents a span count of 1}
+if cur_span<>cur_align then @<Update width entry for spanned columns@>
+else if w>width(cur_align) then width(cur_align):=w;
+type(u):=unset_node; span_count(u):=n;@/
+@<Determine the stretch order@>;
+glue_order(u):=o; glue_stretch(u):=total_stretch[o];@/
+@<Determine the shrink order@>;
+glue_sign(u):=o; glue_shrink(u):=total_shrink[o];@/
+pop_nest; vlink(tail):=u; tail:=u;
+end
+
+@ A span node is a 3-word record containing |width|, |span_span|, and
+|span_ptr| fields. The |span_span| field indicates the number of
+spanned columns; the |span_ptr| field points to a span node for the same
+starting column, having a greater extent of spanning, or to
+|end_span|, which has the largest possible |span_span| field; the |width|
+field holds the largest natural width corresponding to a particular
+set of spanned columns.
+
+A list of the maximum widths so far, for spanned columns starting at a
+given column, begins with the |span_ptr| field of the alignrecord for
+that column. The code has to make sure that there is room for
+|span_ptr| in both the alignrecord and the span nodes, which is why
+|span_ptr| replaces |node_attr|.
+@^data structure assumptions@>
+
+The |new_span_node| function is defined in |texnodes.c|.
+
+@d span_node==41
+@d span_node_size==3 {number of |mem| words for a span node}
+@d span_span(#)==vlink(#+1) {that is normally |alink| }
+
+@<Initialize the special list heads...@>=
+span_span(end_span):=max_quarterword+1; span_ptr(end_span):=null;
+
+@ @<Update width entry for spanned columns@>=
+begin q:=cur_span;
+repeat incr(n); q:=vlink(vlink(q));
+until q=cur_align;
+if n>max_quarterword then confusion("too many spans"); {this can happen, but won't}
+@^system dependencies@>
+@:this can't happen too many spans}{\quad too many spans@>
+q:=cur_span;
+while span_span(span_ptr(q))<n do begin
+ q:=span_ptr(q);
+ end;
+if span_span(span_ptr(q))>n then begin
+ s:=new_span_node(span_ptr(q),n,w);
+ span_ptr(q):=s;
+ end
+else if width(span_ptr(q))<w then width(span_ptr(q)):=w;
+end
+
+@ At the end of a row, we append an unset box to the current vlist (for
+\.{\\halign}) or the current hlist (for \.{\\valign}). This unset box
+contains the unset boxes for the columns, separated by the tabskip glue.
+Everything will be set later.
+
+@p procedure fin_row;
+var p:pointer; {the new unset box}
+begin if mode=-hmode then
+ begin p:=filtered_hpack(head,tail,natural,fin_row_group);
+ pop_nest;
+ if cur_pre_head <> cur_pre_tail then
+ append_list(cur_pre_head)(cur_pre_tail);
+ append_to_vlist(p);
+ if cur_head <> cur_tail then
+ append_list(cur_head)(cur_tail);
+ end
+else begin p:=filtered_vpackage(vlink(head),natural,max_depth,fin_row_group);
+ pop_nest; vlink(tail):=p; tail:=p; space_factor:=1000;
+ end;
+type(p):=unset_node; glue_stretch(p):=0;
+if every_cr<>null then begin_token_list(every_cr,every_cr_text);
+align_peek;
+end; {note that |glue_shrink(p)=0| since |glue_shrink==shift_amount|}
+
+@ Finally, we will reach the end of the alignment, and we can breathe a
+sigh of relief that memory hasn't overflowed. All the unset boxes will now be
+set so that the columns line up, taking due account of spanned columns.
+
+@p procedure@?do_assignments; forward;@t\2@>@/
+procedure@?resume_after_display; forward;@t\2@>@/
+procedure@?build_page; forward;@t\2@>@/
+procedure fin_align;
+var @!p,@!q,@!r,@!s,@!u,@!v,@!rr: pointer; {registers for the list operations}
+@!t,@!w:scaled; {width of column}
+@!o:scaled; {shift offset for unset boxes}
+@!n:halfword; {matching span amount}
+@!rule_save:scaled; {temporary storage for |overfull_rule|}
+@!aux_save:memory_word; {temporary storage for |aux|}
+begin if cur_group<>align_group then confusion("align1");
+@:this can't happen align}{\quad align@>
+unsave; {that |align_group| was for individual entries}
+if cur_group<>align_group then confusion("align0");
+unsave; {that |align_group| was for the whole alignment}
+if nest[nest_ptr-1].mode_field=mmode then o:=display_indent
+ else o:=0;
+@<Go through the preamble list, determining the column widths and
+ changing the alignrecords to dummy unset boxes@>;
+@<Package the preamble list, to determine the actual tabskip glue amounts,
+ and let |p| point to this prototype box@>;
+@<Set the glue in all the unset boxes of the current list@>;
+flush_node_list(p); pop_alignment;
+@<Insert the \(c)current list into its environment@>;
+end;@/
+@t\4@>@<Declare the procedure called |align_peek|@>
+
+@ It's time now to dismantle the preamble list and to compute the column
+widths. Let $w_{ij}$ be the maximum of the natural widths of all entries
+that span columns $i$ through $j$, inclusive. The alignrecord for column~$i$
+contains $w_{ii}$ in its |width| field, and there is also a linked list of
+the nonzero $w_{ij}$ for increasing $j$, accessible via the |info| field;
+these span nodes contain the value $j-i-1+|min_quarterword|$ in their
+|link| fields. The values of $w_{ii}$ were initialized to |null_flag|, which
+we regard as $-\infty$.
+
+The final column widths are defined by the formula
+$$w_j=\max_{1\L i\L j}\biggl( w_{ij}-\sum_{i\L k<j}(t_k+w_k)\biggr),$$
+where $t_k$ is the natural width of the tabskip glue between columns
+$k$ and~$k+1$. However, if $w_{ij}=-\infty$ for all |i| in the range
+|1<=i<=j| (i.e., if every entry that involved column~|j| also involved
+column~|j+1|), we let $w_j=0$, and we zero out the tabskip glue after
+column~|j|.
+
+\TeX\ computes these values by using the following scheme: First $w_1=w_{11}$.
+Then replace $w_{2j}$ by $\max(w_{2j},w_{1j}-t_1-w_1)$, for all $j>1$.
+Then $w_2=w_{22}$. Then replace $w_{3j}$ by $\max(w_{3j},w_{2j}-t_2-w_2)$
+for all $j>2$; and so on. If any $w_j$ turns out to be $-\infty$, its
+value is changed to zero and so is the next tabskip.
+
+@<Go through the preamble list,...@>=
+q:=vlink(preamble);
+repeat flush_list(u_part(q)); flush_list(v_part(q));
+p:=vlink(vlink(q));
+if width(q)=null_flag then
+ @<Nullify |width(q)| and the tabskip glue following this column@>;
+if span_ptr(q)<>end_span then
+ @<Merge the widths in the span nodes of |q| with those of |p|,
+ destroying the span nodes of |q|@>;
+type(q):=unset_node; span_count(q):=min_quarterword; height(q):=0;
+depth(q):=0; glue_order(q):=normal; glue_sign(q):=normal;
+glue_stretch(q):=0; glue_shrink(q):=0; q:=p;
+until q=null
+
+@ @<Nullify |width(q)| and the tabskip glue following this column@>=
+begin width(q):=0; r:=vlink(q); s:=glue_ptr(r);
+if s<>zero_glue then
+ begin add_glue_ref(zero_glue); delete_glue_ref(s);
+ glue_ptr(r):=zero_glue;
+ end;
+end
+
+@ Merging of two span-node lists is a typical exercise in the manipulation of
+linearly linked data structures. The essential invariant in the following
+|repeat| loop is that we want to dispense with node |r|, in |q|'s list,
+and |u| is its successor; all nodes of |p|'s list up to and including |s|
+have been processed, and the successor of |s| matches |r| or precedes |r|
+or follows |r|, according as |link(r)=n| or |link(r)>n| or |link(r)<n|.
+
+@<Merge the widths...@>=
+begin t:=width(q)+width(glue_ptr(vlink(q)));
+r:=span_ptr(q); s:=end_span; span_ptr(s):=p; n:=min_quarterword+1;
+repeat width(r):=width(r)-t; u:=span_ptr(r);
+while span_span(r)>n do
+ begin s:=span_ptr(s); n:=span_span(span_ptr(s))+1;
+ end;
+if span_span(r)<n then
+ begin span_ptr(r):=span_ptr(s); span_ptr(s):=r; decr(span_span(r)); s:=r;
+ end
+else begin if width(r)>width(span_ptr(s)) then width(span_ptr(s)):=width(r);
+ flush_node(r);
+ end;
+r:=u;
+until r=end_span;
+end
+
+@ Now the preamble list has been converted to a list of alternating unset
+boxes and tabskip glue, where the box widths are equal to the final
+column sizes. In case of \.{\\valign}, we change the widths to heights,
+so that a correct error message will be produced if the alignment is
+overfull or underfull.
+
+@<Package the preamble list...@>=
+save_ptr:=save_ptr-2; pack_begin_line:=-mode_line;
+if mode=-vmode then
+ begin rule_save:=overfull_rule;
+ overfull_rule:=0; {prevent rule from being packaged}
+ p:=hpack(preamble,saved(1),saved(0));
+ overfull_rule:=rule_save;
+ end
+else begin q:=vlink(preamble);
+ repeat height(q):=width(q); width(q):=0; q:=vlink(vlink(q));
+ until q=null;
+ p:=filtered_vpackage(preamble,saved(1),saved(0),max_depth,preamble_group);
+ q:=vlink(preamble);
+ repeat width(q):=height(q); height(q):=0; q:=vlink(vlink(q));
+ until q=null;
+ end;
+pack_begin_line:=0
+
+@ @<Set the glue in all the unset...@>=
+q:=vlink(head); s:=head;
+while q<>null do
+ begin if not is_char_node(q) then
+ if type(q)=unset_node then
+ @<Set the unset box |q| and the unset boxes in it@>
+ else if type(q)=rule_node then
+ @<Make the running dimensions in rule |q| extend to the
+ boundaries of the alignment@>;
+ s:=q; q:=vlink(q);
+ end
+
+@ @<Make the running dimensions in rule |q| extend...@>=
+begin if is_running(width(q)) then width(q):=width(p);
+if is_running(height(q)) then height(q):=height(p);
+if is_running(depth(q)) then depth(q):=depth(p);
+if o<>0 then
+ begin r:=vlink(q); vlink(q):=null; q:=hpack(q,natural);
+ shift_amount(q):=o; vlink(q):=r; vlink(s):=q;
+ end;
+end
+
+@ The unset box |q| represents a row that contains one or more unset boxes,
+depending on how soon \.{\\cr} occurred in that row.
+
+@<Set the unset box |q| and the unset boxes in it@>=
+begin if mode=-vmode then
+ begin type(q):=hlist_node; width(q):=width(p);
+ end
+else begin type(q):=vlist_node; height(q):=height(p);
+ end;
+glue_order(q):=glue_order(p); glue_sign(q):=glue_sign(p);
+glue_set(q):=glue_set(p); shift_amount(q):=o;
+r:=vlink(list_ptr(q)); s:=vlink(list_ptr(p));
+repeat @<Set the glue in node |r| and change it from an unset node@>;
+r:=vlink(vlink(r)); s:=vlink(vlink(s));
+until r=null;
+end
+
+@ A box made from spanned columns will be followed by tabskip glue nodes and
+by empty boxes as if there were no spanning. This permits perfect alignment
+of subsequent entries, and it prevents values that depend on floating point
+arithmetic from entering into the dimensions of any boxes.
+
+@<Set the glue in node |r|...@>=
+n:=span_count(r); t:=width(s); w:=t; u:=hold_head;
+while n>min_quarterword do
+ begin decr(n);
+ @<Append tabskip glue and an empty box to list |u|,
+ and update |s| and |t| as the prototype nodes are passed@>;
+ end;
+if mode=-vmode then
+ @<Make the unset node |r| into an |hlist_node| of width |w|,
+ setting the glue as if the width were |t|@>
+else @<Make the unset node |r| into a |vlist_node| of height |w|,
+ setting the glue as if the height were |t|@>;
+shift_amount(r):=0;
+if u<>hold_head then {append blank boxes to account for spanned nodes}
+ begin vlink(u):=vlink(r); vlink(r):=vlink(hold_head); r:=u;
+ end
+
+@ @<Append tabskip glue and an empty box to list |u|...@>=
+s:=vlink(s); v:=glue_ptr(s); vlink(u):=new_glue(v); u:=vlink(u);
+subtype(u):=tab_skip_code+1; t:=t+width(v);
+if glue_sign(p)=stretching then
+ begin if stretch_order(v)=glue_order(p) then
+ t:=t+round(float(glue_set(p))*stretch(v));
+@^real multiplication@>
+ end
+else if glue_sign(p)=shrinking then
+ begin if shrink_order(v)=glue_order(p) then
+ t:=t-round(float(glue_set(p))*shrink(v));
+ end;
+s:=vlink(s); rr:=new_null_box; vlink(u):=rr; u:=vlink(u); t:=t+width(s);
+if mode=-vmode then width(u):=width(s)@+else
+ begin type(u):=vlist_node; height(u):=width(s);
+ end
+
+@ @<Make the unset node |r| into an |hlist_node| of width |w|...@>=
+begin height(r):=height(q); depth(r):=depth(q);
+if t=width(r) then
+ begin glue_sign(r):=normal; glue_order(r):=normal;
+ set_glue_ratio_zero(glue_set(r));
+ end
+else if t>width(r) then
+ begin glue_sign(r):=stretching;
+ if glue_stretch(r)=0 then set_glue_ratio_zero(glue_set(r))
+ else glue_set(r):=unfloat((t-width(r))/glue_stretch(r));
+@^real division@>
+ end
+else begin glue_order(r):=glue_sign(r); glue_sign(r):=shrinking;
+ if glue_shrink(r)=0 then set_glue_ratio_zero(glue_set(r))
+ else if (glue_order(r)=normal)and(width(r)-t>glue_shrink(r)) then
+ set_glue_ratio_one(glue_set(r))
+ else glue_set(r):=unfloat((width(r)-t)/glue_shrink(r));
+ end;
+width(r):=w; type(r):=hlist_node;
+end
+
+@ @<Make the unset node |r| into a |vlist_node| of height |w|...@>=
+begin width(r):=width(q);
+if t=height(r) then
+ begin glue_sign(r):=normal; glue_order(r):=normal;
+ set_glue_ratio_zero(glue_set(r));
+ end
+else if t>height(r) then
+ begin glue_sign(r):=stretching;
+ if glue_stretch(r)=0 then set_glue_ratio_zero(glue_set(r))
+ else glue_set(r):=unfloat((t-height(r))/glue_stretch(r));
+@^real division@>
+ end
+else begin glue_order(r):=glue_sign(r); glue_sign(r):=shrinking;
+ if glue_shrink(r)=0 then set_glue_ratio_zero(glue_set(r))
+ else if (glue_order(r)=normal)and(height(r)-t>glue_shrink(r)) then
+ set_glue_ratio_one(glue_set(r))
+ else glue_set(r):=unfloat((height(r)-t)/glue_shrink(r));
+ end;
+height(r):=w; type(r):=vlist_node;
+end
+
+@ We now have a completed alignment, in the list that starts at |head|
+and ends at |tail|. This list will be merged with the one that encloses
+it. (In case the enclosing mode is |mmode|, for displayed formulas,
+we will need to insert glue before and after the display; that part of the
+program will be deferred until we're more familiar with such operations.)
+
+@<Insert the \(c)current list into its environment@>=
+aux_save:=aux; p:=vlink(head); q:=tail; pop_nest;
+if mode=mmode then @<Finish an alignment in a display@>
+else begin aux:=aux_save; vlink(tail):=p;
+ if p<>null then tail:=q;
+ if mode=vmode then begin check_filter('alignment'); build_page; end;
+ end
+
+@* \[38] Breaking paragraphs into lines.
+We come now to what is probably the most interesting algorithm of \TeX:
+the mechanism for choosing the ``best possible'' breakpoints that yield
+the individual lines of a paragraph. \TeX's line-breaking algorithm takes
+a given horizontal list and converts it to a sequence of boxes that are
+appended to the current vertical list. In the course of doing this, it
+creates a special data structure containing three kinds of records that are
+not used elsewhere in \TeX. Such nodes are created while a paragraph is
+being processed, and they are destroyed afterwards; thus, the other parts
+of \TeX\ do not need to know anything about how line-breaking is done.
+
+The method used here is based on an approach devised by Michael F. Plass and
+@^Plass, Michael Frederick@>
+@^Knuth, Donald Ervin@>
+the author in 1977, subsequently generalized and improved by the same two
+people in 1980. A detailed discussion appears in {\sl SOFTWARE---Practice
+\AM\ Experience \bf11} (1981), 1119--1184, where it is shown that the
+line-breaking problem can be regarded as a special case of the problem of
+computing the shortest path in an acyclic network. The cited paper includes
+numerous examples and describes the history of line breaking as it has been
+practiced by printers through the ages. The present implementation adds two
+new ideas to the algorithm of 1980: memory space requirements are considerably
+reduced by using smaller records for inactive nodes than for active ones,
+and arithmetic overflow is avoided by using ``delta distances'' instead of
+keeping track of the total distance from the beginning of the paragraph to the
+current point.
+
+@ The |line_break| procedure should be invoked only in horizontal mode; it
+leaves that mode and places its output into the current vlist of the
+enclosing vertical mode (or internal vertical mode).
+There is one explicit parameter: |d| is true for partial paragraphs
+preceding display math mode; in this case the amount of additional
+penalty inserted before the final line is |display_widow_penalty|
+instead of |widow_penalty|.
+
+There are also a number of implicit parameters: The hlist to be broken
+starts at |vlink(head)|, and it is nonempty. The value of |prev_graf| in the
+enclosing semantic level tells where the paragraph should begin in the
+sequence of line numbers, in case hanging indentation or \.{\\parshape}
+are in use; |prev_graf| is zero unless this paragraph is being continued
+after a displayed formula. Other implicit parameters, such as the
+|par_shape_ptr| and various penalties to use for hyphenation, etc., appear
+in |eqtb|.
+
+After |line_break| has acted, it will have updated the current vlist and the
+value of |prev_graf|. Furthermore, the global variable |just_box| will
+point to the final box created by |line_break|, so that the width of this
+line can be ascertained when it is necessary to decide whether to use
+|above_display_skip| or |above_display_short_skip| before a displayed formula.
+
+@<Glob...@>=
+@!just_box:pointer; {the |hlist_node| for the last line of the new paragraph}
+@!paragraph_dir:integer; {main direction of paragraph}
+@!line_break_dir:integer; {current direction within paragraph}
+@!line_break_context:integer; {the surrounding state for |line_break| calls}
+@!break_c_htdp:quarterword; {height-depth entry in |char_info|}
+@!temp_no_whatsits:integer; {used when closing group}
+@!temp_no_dirs:integer; {used when closing group}
+@!temporary_dir:integer;
+@!dir_ptr,@!dir_tmp,@!dir_rover:pointer;
+
+@ @<Set init...@>=
+temp_no_whatsits:=0; temp_no_dirs:=0; temporary_dir:=0;
+dir_ptr:=null; dir_tmp:=null; dir_rover:=null;
+line_break_context := bottom_level;
+
+@ In it's complete form, |line_break| is a rather lengthy
+procedure---sort of a small world unto itself---we must build it up
+little by little. Below you see only te general outline.
+
+The main task performed here is to move the list from |head| to
+|temp_head| and go into the enclosing semantic level. We also append
+the \.{\\parfillskip} glue to the end of the paragraph, removing a
+space (or other glue node) if it was there, since spaces usually
+precede blank lines and instances of `\.{\$\$}'. The |par_fill_skip|
+is preceded by an infinite penalty, so it will never be considered as
+a potential breakpoint.
+
+That code assumes that a |glue_node| and a |penalty_node| occupy the
+same number of |mem|~words.
+@^data structure assumptions@>
+
+Most other processing is delegated to external functions.
+
+@p procedure line_break(@!d:boolean);
+var final_par_glue:pointer;
+start_of_par:pointer;
+begin pack_begin_line:=mode_line; {this is for over/underfull box messages}
+vlink(temp_head):=vlink(head);
+new_hyphenation(temp_head, tail);
+if (not is_char_node(vlink(head))) and ((type(vlink(head))=whatsit_node)
+ and (subtype(vlink(head))=local_par_node)) then
+ paragraph_dir:=local_par_dir(vlink(head))
+else
+ paragraph_dir:=0;
+line_break_dir:=paragraph_dir;
+tail:=new_ligkern(temp_head,tail);
+if is_char_node(tail) then new_tail_append(new_penalty(inf_penalty))
+else if type(tail)<>glue_node then new_tail_append(new_penalty(inf_penalty))
+else begin
+ type(tail):=penalty_node;
+ delete_glue_ref(glue_ptr(tail));
+ if leader_ptr(tail)<>null then
+ flush_node_list(leader_ptr(tail));
+ penalty(tail):=inf_penalty;
+ end;
+final_par_glue:=new_param_glue(par_fill_skip_code);
+couple_nodes(tail,final_par_glue);
+if not output_active then
+ lua_node_filter(pre_linebreak_filter_callback,
+ line_break_context,temp_head,addressof(tail));
+last_line_fill:=vlink(tail);
+pop_nest;
+start_of_par:=tail;
+ext_do_line_break(d,pretolerance,tracing_paragraphs,tolerance,emergency_stretch,
+ looseness,hyphen_penalty,ex_hyphen_penalty,
+ pdf_adjust_spacing, par_shape_ptr, adj_demerits,
+ pdf_protrude_chars, line_penalty, last_line_fit,
+ double_hyphen_demerits, final_hyphen_demerits,
+ hang_indent, hsize, hang_after, left_skip, right_skip,
+ pdf_each_line_height,pdf_each_line_depth,
+ pdf_first_line_height, pdf_last_line_depth,
+ inter_line_penalties_ptr, inter_line_penalty,
+ club_penalty, club_penalties_ptr,
+ display_widow_penalties_ptr,widow_penalties_ptr,
+ display_widow_penalty, widow_penalty,
+ broken_penalty, final_par_glue);
+if not output_active then
+ lua_node_filter(post_linebreak_filter_callback,
+ line_break_context,start_of_par,addressof(tail));
+pack_begin_line:=0;
+end;
+@#
+@t\4@>@<Declare \eTeX\ procedures for use by |main_control|@>
+
+@ It is possible that the user wants to interfere at some point.
+
+The choice between |check_head_filter| and |check_contrib_filter| is not
+quite clear to me yet, but it seems that the latter is the better choice.
+
+@d check_head_filter(#)==if (not output_active) and (vlink(head)<>null) then
+lua_node_filter_s(buildpage_filter_callback,#,head,addressof(tail))
+
+@d check_contrib_filter(#)==if (not output_active) and (vlink(contrib_head)<>null) then
+lua_node_filter_s(buildpage_filter_callback,#,contrib_head,addressof(garbage))
+
+@d check_filter==check_head_filter
+
+@* \[39] Breaking paragraphs into lines, continued.
+
+Hyphenation and line breaking are now all handled in C. Only the
+section heads are kept here.
+
+@* \[40] Pre-hyphenation.
+
+@* \[41] Post-hyphenation.
+
+@* \[42] Hyphenation.
+
+@ When \TeX\ has scanned `\.{\\hyphenation}', it calls on a procedure named
+|new_hyph_exceptions| to do the right thing.
+
+@p procedure new_hyph_exceptions; {enters new exceptions}
+var p:halfword; {just to catch the return value of |scan_toks|}
+begin p:=scan_toks(false,true);
+load_tex_hyphenation(language,def_ref);
+flush_list(def_ref);
+end;
+
+@ Similarly, when \TeX\ has scanned `\.{\\patterns}', it calls on a
+procedure named |new_patterns|.
+
+@p procedure new_patterns; {initializes the hyphenation pattern data}
+var p:halfword; {just to catch the return value of |scan_toks|}
+begin p:=scan_toks(false,true);
+load_tex_patterns(language,def_ref);
+flush_list(def_ref);
+end;
+
+@ `\.{\\prehyphenchar}', sets the |pre_break| character, and
+`\.{\\posthyphenchar}' the |post_break| character. Their respective
+defaults are ascii hyphen ("-") and zero (nul).
+
+@p procedure new_pre_hyphen_char;
+begin scan_optional_equals; scan_int;
+ set_pre_hyphen_char(language,cur_val);
+end;
+@#
+procedure new_post_hyphen_char;
+begin scan_optional_equals; scan_int;
+ set_post_hyphen_char(language,cur_val);
+end;
+
+@* \[43] Initializing the hyphenation tables.
+
+None of the trie-related stuff is applicable any more in luatex.
+
+@* \[44] Breaking vertical lists into pages.
+The |vsplit| procedure, which implements \TeX's \.{\\vsplit} operation,
+is considerably simpler than |line_break| because it doesn't have to
+worry about hyphenation, and because its mission is to discover a single
+break instead of an optimum sequence of breakpoints. But before we get
+into the details of |vsplit|, we need to consider a few more basic things.
+
+@ A subroutine called |prune_page_top| takes a pointer to a vlist and
+returns a pointer to a modified vlist in which all glue, kern, and penalty nodes
+have been deleted before the first box or rule node. However, the first
+box or rule is actually preceded by a newly created glue node designed so that
+the topmost baseline will be at distance |split_top_skip| from the top,
+whenever this is possible without backspacing.
+
+When the second argument |s| is |false| the deleted nodes are destroyed,
+otherwise they are collected in a list starting at |split_disc|.
+
+@d discard_or_move = 60
+@p function prune_page_top(@!p:pointer;@!s:boolean):pointer;
+var prev_p:pointer; {lags one step behind |p|}
+@!q,@!r:pointer; {temporary variables for list manipulation}
+begin prev_p:=temp_head; vlink(temp_head):=p; r:=null;
+while p<>null do
+ case type(p) of
+ hlist_node,vlist_node,rule_node:@<Insert glue for |split_top_skip|
+ and set~|p:=null|@>;
+ whatsit_node,mark_node,ins_node: begin
+ prev_p:=p; p:=vlink(prev_p);
+ end;
+ glue_node,kern_node,penalty_node: begin
+ q:=p; p:=vlink(q); vlink(q):=null;
+ vlink(prev_p):=p;
+ if s then
+ begin if split_disc=null then split_disc:=q else vlink(r):=q;
+ r:=q;
+ end
+ else flush_node_list(q);
+ end;
+ othercases confusion("pruning")
+@:this can't happen pruning}{\quad pruning@>
+ endcases;
+prune_page_top:=vlink(temp_head);
+end;
+
+@ @<Insert glue for |split_top_skip|...@>=
+begin q:=new_skip_param(split_top_skip_code); vlink(prev_p):=q; vlink(q):=p;
+ {now |temp_ptr=glue_ptr(q)|}
+if width(temp_ptr)>height(p) then width(temp_ptr):=width(temp_ptr)-height(p)
+else width(temp_ptr):=0;
+p:=null;
+end
+
+@ The next subroutine finds the best place to break a given vertical list
+so as to obtain a box of height~|h|, with maximum depth~|d|.
+A pointer to the beginning of the vertical list is given,
+and a pointer to the optimum breakpoint is returned. The list is effectively
+followed by a forced break, i.e., a penalty node with the |eject_penalty|;
+if the best break occurs at this artificial node, the value |null| is returned.
+
+@<Glob...@>=
+@!active_height:array[1..9] of scaled;
+ {distance from first active node to~|cur_p|}
+
+@ An array of six |scaled| distances is used to keep track of the height
+from the beginning of the list to the current place, just as in |line_break|.
+In fact, we use one of the same arrays, only changing its name to reflect
+its new significance.
+
+@d do_all_six(#)==#(1);#(2);#(3);#(4);#(5);#(6);#(7)
+
+@d cur_height==active_height[1] {the natural height}
+@d set_height_zero(#)==active_height[#]:=0 {initialize the height to zero}
+@#
+@d update_heights=90 {go here to record glue in the |active_height| table}
+@d awful_bad=@'7777777777 { more than a billion demerits }
+
+@p function vert_break(@!p:pointer; @!h,@!d:scaled):pointer;
+ {finds optimum page break}
+label done,not_found,update_heights;
+var prev_p:pointer; {if |p| is a glue node, |type(prev_p)| determines
+ whether |p| is a legal breakpoint}
+@!q,@!r:pointer; {glue specifications}
+@!pi:integer; {penalty value}
+@!b:integer; {badness at a trial breakpoint}
+@!least_cost:integer; {the smallest badness plus penalties found so far}
+@!best_place:pointer; {the most recent break that leads to |least_cost|}
+@!prev_dp:scaled; {depth of previous box in the list}
+@!t:small_number; {|type| of the node following a kern}
+begin prev_p:=p; {an initial glue node is not a legal breakpoint}
+least_cost:=awful_bad; do_all_six(set_height_zero); prev_dp:=0;
+best_place:=null; pi:=0;
+loop@+ begin @<If node |p| is a legal breakpoint, check if this break is
+ the best known, and |goto done| if |p| is null or
+ if the page-so-far is already too full to accept more stuff@>;
+ prev_p:=p; p:=vlink(prev_p);
+ end;
+done: vert_break:=best_place;
+end;
+
+@ A global variable |best_height_plus_depth| will be set to the natural size
+of the box that corresponds to the optimum breakpoint found by |vert_break|.
+(This value is used by the insertion-splitting algorithm of the page builder.)
+
+@<Glob...@>=
+@!best_height_plus_depth:scaled; {height of the best box, without stretching or
+ shrinking}
+
+@ A subtle point to be noted here is that the maximum depth~|d| might be
+negative, so |cur_height| and |prev_dp| might need to be corrected even
+after a glue or kern node.
+
+@<If node |p| is a legal breakpoint, check...@>=
+if p=null then pi:=eject_penalty
+else @<Use node |p| to update the current height and depth measurements;
+ if this node is not a legal breakpoint, |goto not_found|
+ or |update_heights|,
+ otherwise set |pi| to the associated penalty at the break@>;
+@<Check if node |p| is a new champion breakpoint; then \(go)|goto done|
+ if |p| is a forced break or if the page-so-far is already too full@>;
+if (type(p)<glue_node)or(type(p)>kern_node) then goto not_found;
+update_heights: @<Update the current height and depth measurements with
+ respect to a glue or kern node~|p|@>;
+not_found: if prev_dp>d then
+ begin cur_height:=cur_height+prev_dp-d;
+ prev_dp:=d;
+ end;
+
+@ @<Use node |p| to update the current height and depth measurements...@>=
+case type(p) of
+hlist_node,vlist_node,rule_node: begin@t@>@;@/
+ cur_height:=cur_height+prev_dp+height(p); prev_dp:=depth(p);
+ goto not_found;
+ end;
+whatsit_node:@<Process whatsit |p| in |vert_break| loop, |goto not_found|@>;
+glue_node: if precedes_break(prev_p) then pi:=0
+ else goto update_heights;
+kern_node: begin if vlink(p)=null then t:=penalty_node
+ else t:=type(vlink(p));
+ if t=glue_node then pi:=0@+else goto update_heights;
+ end;
+penalty_node: pi:=penalty(p);
+mark_node,ins_node: goto not_found;
+othercases confusion("vertbreak")
+@:this can't happen vertbreak}{\quad vertbreak@>
+endcases
+
+@ @d deplorable==100000 {more than |inf_bad|, but less than |awful_bad|}
+
+@<Check if node |p| is a new champion breakpoint; then \(go)...@>=
+if pi<inf_penalty then
+ begin @<Compute the badness, |b|, using |awful_bad|
+ if the box is too full@>;
+ if b<awful_bad then
+ if pi<=eject_penalty then b:=pi
+ else if b<inf_bad then b:=b+pi
+ else b:=deplorable;
+ if b<=least_cost then
+ begin best_place:=p; least_cost:=b;
+ best_height_plus_depth:=cur_height+prev_dp;
+ end;
+ if (b=awful_bad)or(pi<=eject_penalty) then goto done;
+ end
+
+@ @<Compute the badness, |b|, using |awful_bad| if the box is too full@>=
+if cur_height<h then
+ if (active_height[3]<>0) or (active_height[4]<>0) or
+ (active_height[5]<>0) or (active_height[6]<>0) then b:=0
+ else b:=badness(h-cur_height,active_height[2])
+else if cur_height-h>active_height[7] then b:=awful_bad
+else b:=badness(cur_height-h,active_height[7])
+
+@ Vertical lists that are subject to the |vert_break| procedure should not
+contain infinite shrinkability, since that would permit any amount of
+information to ``fit'' on one page.
+
+@<Update the current height and depth measurements with...@>=
+if type(p)=kern_node then q:=p
+else begin q:=glue_ptr(p);
+ active_height[2+stretch_order(q)]:=@|
+ active_height[2+stretch_order(q)]+stretch(q);@/
+ active_height[7]:=active_height[7]+shrink(q);
+ if (shrink_order(q)<>normal)and(shrink(q)<>0) then
+ begin@t@>@;@/
+ print_err("Infinite glue shrinkage found in box being split");@/
+@.Infinite glue shrinkage...@>
+ help4("The box you are \vsplitting contains some infinitely")@/
+ ("shrinkable glue, e.g., `\vss' or `\vskip 0pt minus 1fil'.")@/
+ ("Such glue doesn't belong there; but you can safely proceed,")@/
+ ("since the offensive shrinkability has been made finite.");
+ error; r:=new_spec(q); shrink_order(r):=normal; delete_glue_ref(q);
+ glue_ptr(p):=r; q:=r;
+ end;
+ end;
+cur_height:=cur_height+prev_dp+width(q); prev_dp:=0
+
+@ Now we are ready to consider |vsplit| itself. Most of
+its work is accomplished by the two subroutines that we have just considered.
+
+Given the number of a vlist box |n|, and given a desired page height |h|,
+the |vsplit| function finds the best initial segment of the vlist and
+returns a box for a page of height~|h|. The remainder of the vlist, if
+any, replaces the original box, after removing glue and penalties and
+adjusting for |split_top_skip|. Mark nodes in the split-off box are used to
+set the values of |split_first_mark| and |split_bot_mark|; we use the
+fact that |split_first_mark(x)=null| if and only if |split_bot_mark(x)=null|.
+
+The original box becomes ``void'' if and only if it has been entirely
+extracted. The extracted box is ``void'' if and only if the original
+box was void (or if it was, erroneously, an hlist box).
+
+@p function vsplit(@!n:halfword; @!h:scaled):pointer;
+ {extracts a page of height |h| from box |n|}
+label exit,done;
+var v:pointer; {the box to be split}
+vdir:integer; {the direction of the box to be split}
+p:pointer; {runs through the vlist}
+q:pointer; {points to where the break occurs}
+i:halfword; {for traversing marks lists}
+begin v:=box(n); vdir:=box_dir(v);
+flush_node_list(split_disc); split_disc:=null;
+for i:=0 to biggest_used_mark do begin
+ delete_split_first_mark(i);
+ delete_split_bot_mark(i);
+end;
+@<Dispense with trivial cases of void or bad boxes@>;
+q:=vert_break(list_ptr(v),h,split_max_depth);
+@<Look at all the marks in nodes before the break, and set the final
+ link to |null| at the break@>;
+q:=prune_page_top(q,saving_vdiscards>0);
+p:=list_ptr(v); list_ptr(v):=null; flush_node(v);
+pack_direction:=vdir;
+if q=null then box(n):=null {the |eq_level| of the box stays the same}
+else box(n):=filtered_vpackage(q,0,additional,max_depth,split_keep_group);
+vsplit:=filtered_vpackage(p,h,exactly,split_max_depth,split_off_group);
+exit: end;
+
+@ @<Dispense with trivial cases of void or bad boxes@>=
+if v=null then
+ begin vsplit:=null; return;
+ end;
+if type(v)<>vlist_node then
+ begin print_err(""); print_esc("vsplit"); print(" needs a ");
+ print_esc("vbox");
+@:vsplit_}{\.{\\vsplit needs a \\vbox}@>
+ help2("The box you are trying to split is an \hbox.")@/
+ ("I can't split such a box, so I'll leave it alone.");
+ error; vsplit:=null; return;
+ end
+
+@ It's possible that the box begins with a penalty node that is the
+``best'' break, so we must be careful to handle this special case correctly.
+
+@<Look at all the marks...@>=
+p:=list_ptr(v);
+if p=q then list_ptr(v):=null
+else loop@+begin if type(p)=mark_node then
+ if split_first_mark(mark_class(p))=null then
+ begin split_first_mark(mark_class(p)):=mark_ptr(p);
+ split_bot_mark(mark_class(p)):=split_first_mark(mark_class(p));
+ token_ref_count(split_first_mark(mark_class(p))):=@|
+ token_ref_count(split_first_mark(mark_class(p)))+2;
+ end
+ else begin delete_token_ref(split_bot_mark(mark_class(p)));
+ split_bot_mark(mark_class(p)):=mark_ptr(p);
+ add_token_ref(split_bot_mark(mark_class(p)));
+ end;
+ if vlink(p)=q then
+ begin vlink(p):=null; goto done;
+ end;
+ p:=vlink(p);
+ end;
+done:
+
+@* \[45] The page builder.
+When \TeX\ appends new material to its main vlist in vertical mode, it uses
+a method something like |vsplit| to decide where a page ends, except that
+the calculations are done ``on line'' as new items come in.
+The main complication in this process is that insertions must be put
+into their boxes and removed from the vlist, in a more-or-less optimum manner.
+
+We shall use the term ``current page'' for that part of the main vlist that
+is being considered as a candidate for being broken off and sent to the
+user's output routine. The current page starts at |vlink(page_head)|, and
+it ends at |page_tail|. We have |page_head=page_tail| if this list is empty.
+@^current page@>
+
+Utter chaos would reign if the user kept changing page specifications
+while a page is being constructed, so the page builder keeps the pertinent
+specifications frozen as soon as the page receives its first box or
+insertion. The global variable |page_contents| is |empty| when the
+current page contains only mark nodes and content-less whatsit nodes; it
+is |inserts_only| if the page contains only insertion nodes in addition to
+marks and whatsits. Glue nodes, kern nodes, and penalty nodes are
+discarded until a box or rule node appears, at which time |page_contents|
+changes to |box_there|. As soon as |page_contents| becomes non-|empty|,
+the current |vsize| and |max_depth| are squirreled away into |page_goal|
+and |page_max_depth|; the latter values will be used until the page has
+been forwarded to the user's output routine. The \.{\\topskip} adjustment
+is made when |page_contents| changes to |box_there|.
+
+Although |page_goal| starts out equal to |vsize|, it is decreased by the
+scaled natural height-plus-depth of the insertions considered so far, and by
+the \.{\\skip} corrections for those insertions. Therefore it represents
+the size into which the non-inserted material should fit, assuming that
+all insertions in the current page have been made.
+
+The global variables |best_page_break| and |least_page_cost| correspond
+respectively to the local variables |best_place| and |least_cost| in the
+|vert_break| routine that we have already studied; i.e., they record the
+location and value of the best place currently known for breaking the
+current page. The value of |page_goal| at the time of the best break is
+stored in |best_size|.
+
+@d inserts_only=1
+ {|page_contents| when an insert node has been contributed, but no boxes}
+@d box_there=2 {|page_contents| when a box or rule has been contributed}
+
+@<Glob...@>=
+@!page_tail:pointer; {the final node on the current page}
+@!page_contents:empty..box_there; {what is on the current page so far?}
+@!page_max_depth:scaled; {maximum box depth on page being built}
+@!best_page_break:pointer; {break here to get the best page known so far}
+@!least_page_cost:integer; {the score for this currently best page}
+@!best_size:scaled; {its |page_goal|}
+
+@ The page builder has another data structure to keep track of insertions.
+This is a list of four-word nodes, starting and ending at |page_ins_head|.
+That is, the first element of the list is node |r@t$_1$@>=vlink(page_ins_head)|;
+node $r_j$ is followed by |r@t$_{j+1}$@>=vlink(r@t$_j$@>)|; and if there are
+|n| items we have |r@t$_{n+1}$@>=page_ins_head|. The |subtype| field of
+each node in this list refers to an insertion number; for example, `\.{\\insert
+250}' would correspond to a node whose |subtype| is |qi(250)|
+(the same as the |subtype| field of the relevant |ins_node|). These |subtype|
+fields are in increasing order, and |subtype(page_ins_head)=
+qi(255)|, so |page_ins_head| serves as a convenient sentinel
+at the end of the list. A record is present for each insertion number that
+appears in the current page.
+
+The |type| field in these nodes distinguishes two possibilities that
+might occur as we look ahead before deciding on the optimum page break.
+If |type(r)=inserting_node|, then |height(r)| contains the total of the
+height-plus-depth dimensions of the box and all its inserts seen so far.
+If |type(r)=split_up_node|, then no more insertions will be made into this box,
+because at least one previous insertion was too big to fit on the current
+page; |broken_ptr(r)| points to the node where that insertion will be
+split, if \TeX\ decides to split it, |broken_ins(r)| points to the
+insertion node that was tentatively split, and |height(r)| includes also the
+natural height plus depth of the part that would be split off.
+
+In both cases, |last_ins_ptr(r)| points to the last |ins_node|
+encountered for box |qo(subtype(r))| that would be at least partially
+inserted on the next page; and |best_ins_ptr(r)| points to the last
+such |ins_node| that should actually be inserted, to get the page with
+minimum badness among all page breaks considered so far. We have
+|best_ins_ptr(r)=null| if and only if no insertion for this box should
+be made to produce this optimum page.
+
+The data structure definitions here use the fact that the |@!height| field
+appears in the fourth word of a box node.
+@^data structure assumptions@>
+
+@d inserting_node=37 {an insertion class that has not yet overflowed}
+@d split_up_node=38 {an overflowed insertion class}
+@d broken_ptr(#)==vlink(#+2)
+ {an insertion for this class will break here if anywhere}
+@d broken_ins(#)==vinfo(#+2) {this insertion might break at |broken_ptr|}
+@d last_ins_ptr(#)==vlink(#+3) {the most recent insertion for this |subtype|}
+@d best_ins_ptr(#)==vinfo(#+3) {the optimum most recent insertion}
+
+@<Initialize the special list heads...@>=
+subtype(page_ins_head):=qi(255);
+type(page_ins_head):=split_up_node; vlink(page_ins_head):=page_ins_head;
+
+@ An array |page_so_far| records the heights and depths of everything
+on the current page. This array contains six |scaled| numbers, like the
+similar arrays already considered in |line_break| and |vert_break|; and it
+also contains |page_goal| and |page_depth|, since these values are
+all accessible to the user via |set_page_dimen| commands. The
+value of |page_so_far[1]| is also called |page_total|. The stretch
+and shrink components of the \.{\\skip} corrections for each insertion are
+included in |page_so_far|, but the natural space components of these
+corrections are not, since they have been subtracted from |page_goal|.
+
+The variable |page_depth| records the depth of the current page; it has been
+adjusted so that it is at most |page_max_depth|. The variable
+|last_glue| points to the glue specification of the most recent node
+contributed from the contribution list, if this was a glue node; otherwise
+|last_glue=max_halfword|. (If the contribution list is nonempty,
+however, the value of |last_glue| is not necessarily accurate.)
+The variables |last_penalty|, |last_kern|, and |last_node_type|
+are similar. And
+finally, |insert_penalties| holds the sum of the penalties associated with
+all split and floating insertions.
+
+@d page_goal==page_so_far[0] {desired height of information on page being built}
+@d page_total==page_so_far[1] {height of the current page}
+@d page_shrink==page_so_far[6] {shrinkability of the current page}
+@d page_depth==page_so_far[7] {depth of the current page}
+
+@<Glob...@>=
+@!page_so_far:array [0..7] of scaled; {height and glue of the current page}
+@!last_glue:pointer; {used to implement \.{\\lastskip}}
+@!last_penalty:integer; {used to implement \.{\\lastpenalty}}
+@!last_kern:scaled; {used to implement \.{\\lastkern}}
+@!last_node_type:integer; {used to implement \.{\\lastnodetype}}
+@!insert_penalties:integer; {sum of the penalties for held-over insertions}
+
+@ @<Put each...@>=
+primitive("pagegoal",set_page_dimen,0);
+@!@:page_goal_}{\.{\\pagegoal} primitive@>
+primitive("pagetotal",set_page_dimen,1);
+@!@:page_total_}{\.{\\pagetotal} primitive@>
+primitive("pagestretch",set_page_dimen,2);
+@!@:page_stretch_}{\.{\\pagestretch} primitive@>
+primitive("pagefilstretch",set_page_dimen,3);
+@!@:page_fil_stretch_}{\.{\\pagefilstretch} primitive@>
+primitive("pagefillstretch",set_page_dimen,4);
+@!@:page_fill_stretch_}{\.{\\pagefillstretch} primitive@>
+primitive("pagefilllstretch",set_page_dimen,5);
+@!@:page_filll_stretch_}{\.{\\pagefilllstretch} primitive@>
+primitive("pageshrink",set_page_dimen,6);
+@!@:page_shrink_}{\.{\\pageshrink} primitive@>
+primitive("pagedepth",set_page_dimen,7);
+@!@:page_depth_}{\.{\\pagedepth} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+set_page_dimen: case chr_code of
+0: print_esc("pagegoal");
+1: print_esc("pagetotal");
+2: print_esc("pagestretch");
+3: print_esc("pagefilstretch");
+4: print_esc("pagefillstretch");
+5: print_esc("pagefilllstretch");
+6: print_esc("pageshrink");
+othercases print_esc("pagedepth")
+endcases;
+
+@ @d print_plus_end(#)==print(#);@+end
+@d print_plus(#)==if page_so_far[#]<>0 then
+ begin print(" plus "); print_scaled(page_so_far[#]); print_plus_end
+
+@p procedure print_totals;
+begin print_scaled(page_total);
+print_plus(2)("");
+print_plus(3)("fil");
+print_plus(4)("fill");
+print_plus(5)("filll");
+if page_shrink<>0 then
+ begin print(" minus "); print_scaled(page_shrink);
+ end;
+end;
+
+@ @<Show the status of the current page@>=
+if page_head<>page_tail then
+ begin print_nl("### current page:");
+ if output_active then print(" (held over for next output)");
+@.held over for next output@>
+ show_box(vlink(page_head));
+ if page_contents>empty then
+ begin print_nl("total height "); print_totals;
+@:total_height}{\.{total height}@>
+ print_nl(" goal height "); print_scaled(page_goal);
+@.goal height@>
+ r:=vlink(page_ins_head);
+ while r<>page_ins_head do
+ begin print_ln; print_esc("insert"); t:=qo(subtype(r));
+ print_int(t); print(" adds ");
+ t:=x_over_n(height(r),1000)*count(t); print_scaled(t);
+ if type(r)=split_up_node then
+ begin q:=page_head; t:=0;
+ repeat q:=vlink(q);
+ if (type(q)=ins_node)and(subtype(q)=subtype(r)) then incr(t);
+ until q=broken_ins(r);
+ print(", #"); print_int(t); print(" might split");
+ end;
+ r:=vlink(r);
+ end;
+ end;
+ end
+
+@ Here is a procedure that is called when the |page_contents| is changing
+from |empty| to |inserts_only| or |box_there|.
+
+@d set_page_so_far_zero(#)==page_so_far[#]:=0
+
+@p procedure freeze_page_specs(@!s:small_number);
+begin page_contents:=s;
+page_goal:=vsize; page_max_depth:=max_depth;
+page_depth:=0; do_all_six(set_page_so_far_zero);
+least_page_cost:=awful_bad;
+@!stat if tracing_pages>0 then
+ begin begin_diagnostic;
+ print_nl("%% goal height="); print_scaled(page_goal);
+@.goal height@>
+ print(", max depth="); print_scaled(page_max_depth);
+ end_diagnostic(false);
+ end;@;@+tats@;@/
+end;
+
+@ Pages are built by appending nodes to the current list in \TeX's
+vertical mode, which is at the outermost level of the semantic nest. This
+vlist is split into two parts; the ``current page'' that we have been
+talking so much about already, and the ``contribution list'' that receives
+new nodes as they are created. The current page contains everything that
+the page builder has accounted for in its data structures, as described
+above, while the contribution list contains other things that have been
+generated by other parts of \TeX\ but have not yet been
+seen by the page builder.
+The contribution list starts at |vlink(contrib_head)|, and it ends at the
+current node in \TeX's vertical mode.
+
+When \TeX\ has appended new material in vertical mode, it calls the procedure
+|build_page|, which tries to catch up by moving nodes from the contribution
+list to the current page. This procedure will succeed in its goal of
+emptying the contribution list, unless a page break is discovered, i.e.,
+unless the current page has grown to the point where the optimum next
+page break has been determined. In the latter case, the nodes after the
+optimum break will go back onto the contribution list, and control will
+effectively pass to the user's output routine.
+
+We make |type(page_head)=glue_node|, so that an initial glue node on
+the current page will not be considered a valid breakpoint.
+
+@<Initialize the special list...@>=
+type(page_head):=glue_node; subtype(page_head):=normal;
+
+@ The global variable |output_active| is true during the time the
+user's output routine is driving \TeX.
+
+@<Glob...@>=
+@!output_active:boolean; {are we in the midst of an output routine?}
+
+@ @<Set init...@>=
+output_active:=false; insert_penalties:=0;
+
+@ The page builder is ready to start a fresh page if we initialize
+the following state variables. (However, the page insertion list is initialized
+elsewhere.)
+
+@<Start a new current page@>=
+page_contents:=empty; page_tail:=page_head; vlink(page_head):=null;@/
+last_glue:=max_halfword; last_penalty:=0; last_kern:=0;
+last_node_type:=-1;
+page_depth:=0; page_max_depth:=0
+
+@ At certain times box 255 is supposed to be void (i.e., |null|),
+or an insertion box is supposed to be ready to accept a vertical list.
+If not, an error message is printed, and the following subroutine
+flushes the unwanted contents, reporting them to the user.
+
+@p procedure box_error(@!n:eight_bits);
+begin error; begin_diagnostic;
+print_nl("The following box has been deleted:");
+@.The following...deleted@>
+show_box(box(n)); end_diagnostic(true);
+flush_node_list(box(n)); box(n):=null;
+end;
+
+@ The following procedure guarantees that a given box register
+does not contain an \.{\\hbox}.
+
+@p procedure ensure_vbox(@!n:eight_bits);
+var p:pointer; {the box register contents}
+begin p:=box(n);
+if p<>null then if type(p)=hlist_node then
+ begin print_err("Insertions can only be added to a vbox");
+@.Insertions can only...@>
+ help3("Tut tut: You're trying to \insert into a")@/
+ ("\box register that now contains an \hbox.")@/
+ ("Proceed, and I'll discard its present contents.");
+ box_error(n);
+ end;
+end;
+
+@ \TeX\ is not always in vertical mode at the time |build_page|
+is called; the current mode reflects what \TeX\ should return to, after
+the contribution list has been emptied. A call on |build_page| should
+be immediately followed by `|goto big_switch|', which is \TeX's central
+control point.
+
+@d contribute=80 {go here to link a node into the current page}
+
+@p @t\4@>@<Declare the procedure called |fire_up|@>@;@/
+procedure build_page; {append contributions to the current page}
+label exit,done,done1,continue,contribute,update_heights;
+var p:pointer; {the node being appended}
+@!q,@!r:pointer; {nodes being examined}
+@!b,@!c:integer; {badness and cost of current page}
+@!pi:integer; {penalty to be added to the badness}
+@!n:min_quarterword..255; {insertion box number}
+@!delta,@!h,@!w:scaled; {sizes used for insertion calculations}
+begin pi:=0;
+if (vlink(contrib_head)=null)or output_active then return;
+repeat continue: p:=vlink(contrib_head);@/
+@<Update the values of |last_glue|, |last_penalty|, and |last_kern|@>;
+@<Move node |p| to the current page; if it is time for a page break,
+ put the nodes following the break back onto the contribution list,
+ and |return| to the user's output routine if there is one@>;
+until vlink(contrib_head)=null;
+@<Make the contribution list empty by setting its tail to |contrib_head|@>;
+exit:end;
+
+@ @d contrib_tail==nest[0].tail_field {tail of the contribution list}
+
+@<Make the contribution list empty...@>=
+if nest_ptr=0 then tail:=contrib_head {vertical mode}
+else contrib_tail:=contrib_head {other modes}
+
+@ @<Update the values of |last_glue|...@>=
+if last_glue<>max_halfword then delete_glue_ref(last_glue);
+last_penalty:=0; last_kern:=0;
+last_node_type:=type(p)+1;
+if type(p)=glue_node then
+ begin last_glue:=glue_ptr(p); add_glue_ref(last_glue);
+ end
+else begin last_glue:=max_halfword;
+ if type(p)=penalty_node then last_penalty:=penalty(p)
+ else if type(p)=kern_node then last_kern:=width(p);
+ end
+
+@ The code here is an example of a many-way switch into routines that
+merge together in different places. Some people call this unstructured
+programming, but the author doesn't see much wrong with it, as long as
+@^Knuth, Donald Ervin@>
+the various labels have a well-understood meaning.
+
+@<Move node |p| to the current page; ...@>=
+@<If the current page is empty and node |p| is to be deleted, |goto done1|;
+ otherwise use node |p| to update the state of the current page;
+ if this node is an insertion, |goto contribute|; otherwise if this node
+ is not a legal breakpoint, |goto contribute| or |update_heights|;
+ otherwise set |pi| to the penalty associated with this breakpoint@>;
+@<Check if node |p| is a new champion breakpoint; then \(if)if it is time for
+ a page break, prepare for output, and either fire up the user's
+ output routine and |return| or ship out the page and |goto done|@>;
+if (type(p)<glue_node)or(type(p)>kern_node) then goto contribute;
+update_heights:@<Update the current page measurements with respect to the
+ glue or kern specified by node~|p|@>;
+contribute: @<Make sure that |page_max_depth| is not exceeded@>;
+@<Link node |p| into the current page and |goto done|@>;
+done1:@<Recycle node |p|@>;
+done:
+
+@ @<Link node |p| into the current page and |goto done|@>=
+vlink(page_tail):=p; page_tail:=p;
+vlink(contrib_head):=vlink(p); vlink(p):=null; goto done
+
+@ @<Recycle node |p|@>=
+vlink(contrib_head):=vlink(p); vlink(p):=null;
+if saving_vdiscards>0 then
+ begin if page_disc=null then page_disc:=p@+else vlink(tail_page_disc):=p;
+ tail_page_disc:=p;
+ end
+else flush_node_list(p)
+
+@ The title of this section is already so long, it seems best to avoid
+making it more accurate but still longer, by mentioning the fact that a
+kern node at the end of the contribution list will not be contributed until
+we know its successor.
+
+@<If the current page is empty...@>=
+case type(p) of
+hlist_node,vlist_node,rule_node: if page_contents<box_there then
+ @<Initialize the current page, insert the \.{\\topskip} glue
+ ahead of |p|, and |goto continue|@>
+ else @<Prepare to move a box or rule node to the current page,
+ then |goto contribute|@>;
+whatsit_node: @<Prepare to move whatsit |p| to the current page,
+ then |goto contribute|@>;
+glue_node: if page_contents<box_there then goto done1
+ else if precedes_break(page_tail) then pi:=0
+ else goto update_heights;
+kern_node: if page_contents<box_there then goto done1
+ else if vlink(p)=null then return
+ else if type(vlink(p))=glue_node then pi:=0
+ else goto update_heights;
+penalty_node: if page_contents<box_there then goto done1@+else pi:=penalty(p);
+mark_node: goto contribute;
+ins_node: @<Append an insertion to the current page and |goto contribute|@>;
+othercases confusion("page")
+@:this can't happen page}{\quad page@>
+endcases
+
+@ @<Initialize the current page, insert the \.{\\topskip} glue...@>=
+begin if page_contents=empty then freeze_page_specs(box_there)
+else page_contents:=box_there;
+q:=new_skip_param(top_skip_code); {now |temp_ptr=glue_ptr(q)|}
+if (type(p)=hlist_node) and (is_mirrored(body_direction)) then begin
+ if width(temp_ptr)>depth(p) then width(temp_ptr):=width(temp_ptr)-depth(p)
+ else width(temp_ptr):=0;
+ end
+else begin
+ if width(temp_ptr)>height(p) then width(temp_ptr):=width(temp_ptr)-height(p)
+ else width(temp_ptr):=0;
+ end;
+vlink(q):=p; vlink(contrib_head):=q; goto continue;
+end
+
+@ @<Prepare to move a box or rule node to the current page...@>=
+begin
+if (type(p)=hlist_node) and (is_mirrored(body_direction)) then begin
+ page_total:=page_total+page_depth+depth(p);
+ page_depth:=height(p);
+ end
+else begin
+ page_total:=page_total+page_depth+height(p);
+ page_depth:=depth(p);
+ end;
+goto contribute;
+end
+
+@ @<Make sure that |page_max_depth| is not exceeded@>=
+if page_depth>page_max_depth then
+ begin page_total:=@|
+ page_total+page_depth-page_max_depth;@/
+ page_depth:=page_max_depth;
+ end;
+
+@ @<Update the current page measurements with respect to the glue...@>=
+if type(p)=kern_node then q:=p
+else begin q:=glue_ptr(p);
+if stretch_order(q)>1 then
+ page_so_far[1+stretch_order(q)]:=@|
+ page_so_far[1+stretch_order(q)]+stretch(q)@/
+else
+ page_so_far[2+stretch_order(q)]:=@|
+ page_so_far[2+stretch_order(q)]+stretch(q);@/
+ page_shrink:=page_shrink+shrink(q);
+ if (shrink_order(q)<>normal)and(shrink(q)<>0) then
+ begin@t@>@;@/
+ print_err("Infinite glue shrinkage found on current page");@/
+@.Infinite glue shrinkage...@>
+ help4("The page about to be output contains some infinitely")@/
+ ("shrinkable glue, e.g., `\vss' or `\vskip 0pt minus 1fil'.")@/
+ ("Such glue doesn't belong there; but you can safely proceed,")@/
+ ("since the offensive shrinkability has been made finite.");
+ error;
+ r:=new_spec(q); shrink_order(r):=normal; delete_glue_ref(q);
+ glue_ptr(p):=r; q:=r;
+ end;
+ end;
+page_total:=page_total+page_depth+width(q); page_depth:=0
+
+@ @<Check if node |p| is a new champion breakpoint; then \(if)...@>=
+if pi<inf_penalty then
+ begin @<Compute the badness, |b|, of the current page,
+ using |awful_bad| if the box is too full@>;
+ if b<awful_bad then
+ if pi<=eject_penalty then c:=pi
+ else if b<inf_bad then c:=b+pi+insert_penalties
+ else c:=deplorable
+ else c:=b;
+ if insert_penalties>=10000 then c:=awful_bad;
+ @!stat if tracing_pages>0 then @<Display the page break cost@>;@+tats@;@/
+ if c<=least_page_cost then
+ begin best_page_break:=p; best_size:=page_goal;
+ least_page_cost:=c;
+ r:=vlink(page_ins_head);
+ while r<>page_ins_head do
+ begin best_ins_ptr(r):=last_ins_ptr(r);
+ r:=vlink(r);
+ end;
+ end;
+ if (c=awful_bad)or(pi<=eject_penalty) then
+ begin fire_up(p); {output the current page at the best place}
+ if output_active then return; {user's output routine will act}
+ goto done; {the page has been shipped out by default output routine}
+ end;
+ end
+
+@ @<Display the page break cost@>=
+begin begin_diagnostic; print_nl("%");
+print(" t="); print_totals;@/
+print(" g="); print_scaled(page_goal);@/
+print(" b=");
+if b=awful_bad then print_char("*")@+else print_int(b);
+@.*\relax@>
+print(" p="); print_int(pi);
+print(" c=");
+if c=awful_bad then print_char("*")@+else print_int(c);
+if c<=least_page_cost then print_char("#");
+end_diagnostic(false);
+end
+
+@ @<Compute the badness, |b|, of the current page...@>=
+if page_total<page_goal then
+ if (page_so_far[3]<>0) or (page_so_far[4]<>0) or@|
+ (page_so_far[5]<>0) then b:=0
+ else b:=badness(page_goal-page_total,page_so_far[2])
+else if page_total-page_goal>page_shrink then b:=awful_bad
+else b:=badness(page_total-page_goal,page_shrink)
+
+@ @<Append an insertion to the current page and |goto contribute|@>=
+begin if page_contents=empty then freeze_page_specs(inserts_only);
+n:=subtype(p); r:=page_ins_head;
+while n>=subtype(vlink(r)) do r:=vlink(r);
+n:=qo(n);
+if subtype(r)<>qi(n) then
+ @<Create a page insertion node with |subtype(r)=qi(n)|, and
+ include the glue correction for box |n| in the
+ current page state@>;
+if type(r)=split_up_node then insert_penalties:=insert_penalties+float_cost(p)
+else begin last_ins_ptr(r):=p;
+ delta:=page_goal-page_total-page_depth+page_shrink;
+ {this much room is left if we shrink the maximum}
+ if count(n)=1000 then h:=height(p)
+ else h:=x_over_n(height(p),1000)*count(n); {this much room is needed}
+ if ((h<=0)or(h<=delta))and(height(p)+height(r)<=dimen(n)) then
+ begin page_goal:=page_goal-h; height(r):=height(r)+height(p);
+ end
+ else @<Find the best way to split the insertion, and change
+ |type(r)| to |split_up_node|@>;
+ end;
+goto contribute;
+end
+
+@ We take note of the value of \.{\\skip} |n| and the height plus depth
+of \.{\\box}~|n| only when the first \.{\\insert}~|n| node is
+encountered for a new page. A user who changes the contents of \.{\\box}~|n|
+after that first \.{\\insert}~|n| had better be either extremely careful
+or extremely lucky, or both.
+
+@<Create a page insertion node...@>=
+begin q:=new_node(inserting_node,n); vlink(q):=vlink(r); vlink(r):=q; r:=q;
+ensure_vbox(n);
+if box(n)=null then height(r):=0
+else height(r):=height(box(n))+depth(box(n));
+best_ins_ptr(r):=null;@/
+q:=skip(n);
+if count(n)=1000 then h:=height(r)
+else h:=x_over_n(height(r),1000)*count(n);
+page_goal:=page_goal-h-width(q);@/
+if stretch_order(q)>1 then
+ page_so_far[1+stretch_order(q)]:=@|page_so_far[1+stretch_order(q)]+stretch(q)@/
+else
+ page_so_far[2+stretch_order(q)]:=@|page_so_far[2+stretch_order(q)]+stretch(q);@/
+page_shrink:=page_shrink+shrink(q);
+if (shrink_order(q)<>normal)and(shrink(q)<>0) then
+ begin print_err("Infinite glue shrinkage inserted from "); print_esc("skip");
+@.Infinite glue shrinkage...@>
+ print_int(n);
+ help3("The correction glue for page breaking with insertions")@/
+ ("must have finite shrinkability. But you may proceed,")@/
+ ("since the offensive shrinkability has been made finite.");
+ error;
+ end;
+end
+
+@ Here is the code that will split a long footnote between pages, in an
+emergency. The current situation deserves to be recapitulated: Node |p|
+is an insertion into box |n|; the insertion will not fit, in its entirety,
+either because it would make the total contents of box |n| greater than
+\.{\\dimen} |n|, or because it would make the incremental amount of growth
+|h| greater than the available space |delta|, or both. (This amount |h| has
+been weighted by the insertion scaling factor, i.e., by \.{\\count} |n|
+over 1000.) Now we will choose the best way to break the vlist of the
+insertion, using the same criteria as in the \.{\\vsplit} operation.
+
+@<Find the best way to split the insertion...@>=
+begin if count(n)<=0 then w:=max_dimen
+else begin w:=page_goal-page_total-page_depth;
+ if count(n)<>1000 then w:=x_over_n(w,count(n))*1000;
+ end;
+if w>dimen(n)-height(r) then w:=dimen(n)-height(r);
+q:=vert_break(ins_ptr(p),w,depth(p));
+height(r):=height(r)+best_height_plus_depth;
+@!stat if tracing_pages>0 then @<Display the insertion split cost@>;@+tats@;@/
+if count(n)<>1000 then
+ best_height_plus_depth:=x_over_n(best_height_plus_depth,1000)*count(n);
+page_goal:=page_goal-best_height_plus_depth;
+type(r):=split_up_node; broken_ptr(r):=q; broken_ins(r):=p;
+if q=null then insert_penalties:=insert_penalties+eject_penalty
+else if type(q)=penalty_node then insert_penalties:=insert_penalties+penalty(q);
+end
+
+@ @<Display the insertion split cost@>=
+begin begin_diagnostic; print_nl("% split"); print_int(n);
+@.split@>
+print(" to "); print_scaled(w);
+print_char(","); print_scaled(best_height_plus_depth);@/
+print(" p=");
+if q=null then print_int(eject_penalty)
+else if type(q)=penalty_node then print_int(penalty(q))
+else print_char("0");
+end_diagnostic(false);
+end
+
+@ When the page builder has looked at as much material as could appear before
+the next page break, it makes its decision. The break that gave minimum
+badness will be used to put a completed ``page'' into box 255, with insertions
+appended to their other boxes.
+
+We also set the values of |top_mark|, |first_mark|, and |bot_mark|. The
+program uses the fact that |bot_mark(x)<>null| implies |first_mark(x)<>null|;
+it also knows that |bot_mark(x)=null| implies |top_mark(x)=first_mark(x)=null|.
+
+The |fire_up| subroutine prepares to output the current page at the best
+place; then it fires up the user's output routine, if there is one,
+or it simply ships out the page. There is one parameter, |c|, which represents
+the node that was being contributed to the page when the decision to
+force an output was made.
+
+@<Declare the procedure called |fire_up|@>=
+procedure fire_up(@!c:pointer);
+label exit;
+var p,@!q,@!r,@!s:pointer; {nodes being examined and/or changed}
+@!prev_p:pointer; {predecessor of |p|}
+@!n:min_quarterword..255; {insertion box number}
+@!wait:boolean; {should the present insertion be held over?}
+@!save_vbadness:integer; {saved value of |vbadness|}
+@!save_vfuzz: scaled; {saved value of |vfuzz|}
+@!save_split_top_skip: pointer; {saved value of |split_top_skip|}
+@!i: halfword; { for looping through the marks}
+begin @<Set the value of |output_penalty|@>;
+for i:=0 to biggest_used_mark do begin
+ if bot_mark(i)<>null then
+ begin if top_mark(i)<>null then delete_token_ref(top_mark(i));
+ top_mark(i):=bot_mark(i); add_token_ref(top_mark(i));
+ delete_first_mark(i);
+ end;
+ end;
+@<Put the \(o)optimal current page into box 255, update |first_mark| and
+ |bot_mark|, append insertions to their boxes, and put the
+ remaining nodes back on the contribution list@>;
+for i:=0 to biggest_used_mark do begin
+ if (top_mark(i)<>null)and(first_mark(i)=null) then
+ begin first_mark(i):=top_mark(i); add_token_ref(top_mark(i));
+ end;
+ end;
+if output_routine<>null then
+ if dead_cycles>=max_dead_cycles then
+ @<Explain that too many dead cycles have occurred in a row@>
+ else @<Fire up the user's output routine and |return|@>;
+@<Perform the default output routine@>;
+exit:end;
+
+@ @<Set the value of |output_penalty|@>=
+if type(best_page_break)=penalty_node then
+ begin geq_word_define(int_base+output_penalty_code,penalty(best_page_break));
+ penalty(best_page_break):=inf_penalty;
+ end
+else geq_word_define(int_base+output_penalty_code,inf_penalty)
+
+@ As the page is finally being prepared for output,
+pointer |p| runs through the vlist, with |prev_p| trailing behind;
+pointer |q| is the tail of a list of insertions that
+are being held over for a subsequent page.
+
+@<Put the \(o)optimal current page into box 255...@>=
+if c=best_page_break then best_page_break:=null; {|c| not yet linked in}
+@<Ensure that box 255 is empty before output@>;
+insert_penalties:=0; {this will count the number of insertions held over}
+save_split_top_skip:=split_top_skip;
+if holding_inserts<=0 then
+ @<Prepare all the boxes involved in insertions to act as queues@>;
+q:=hold_head; vlink(q):=null; prev_p:=page_head; p:=vlink(prev_p);
+while p<>best_page_break do
+ begin if type(p)=ins_node then
+ begin if holding_inserts<=0 then
+ @<Either insert the material specified by node |p| into the
+ appropriate box, or hold it for the next page;
+ also delete node |p| from the current page@>;
+ end
+ else if type(p)=mark_node then @<Update the values of
+ |first_mark| and |bot_mark|@>;
+ prev_p:=p; p:=vlink(prev_p);
+ end;
+split_top_skip:=save_split_top_skip;
+@<Break the current page at node |p|, put it in box~255,
+ and put the remaining nodes on the contribution list@>;
+@<Delete \(t)the page-insertion nodes@>
+
+@ @<Ensure that box 255 is empty before output@>=
+if box(255)<>null then
+ begin print_err(""); print_esc("box"); print("255 is not void");
+@:box255}{\.{\\box255 is not void}@>
+ help2("You shouldn't use \box255 except in \output routines.")@/
+ ("Proceed, and I'll discard its present contents.");
+ box_error(255);
+ end
+
+@ @<Update the values of |first_mark| and |bot_mark|@>=
+begin if first_mark(mark_class(p))=null then
+ begin first_mark(mark_class(p)):=mark_ptr(p);
+ add_token_ref(first_mark(mark_class(p)));
+ end;
+if bot_mark(mark_class(p))<>null then delete_token_ref(bot_mark(mark_class(p)));
+bot_mark(mark_class(p)):=mark_ptr(p); add_token_ref(bot_mark(mark_class(p)));
+end;
+
+@ When the following code is executed, the current page runs from node
+|vlink(page_head)| to node |prev_p|, and the nodes from |p| to |page_tail|
+are to be placed back at the front of the contribution list. Furthermore
+the heldover insertions appear in a list from |vlink(hold_head)| to |q|; we
+will put them into the current page list for safekeeping while the user's
+output routine is active. We might have |q=hold_head|; and |p=null| if
+and only if |prev_p=page_tail|. Error messages are suppressed within
+|vpackage|, since the box might appear to be overfull or underfull simply
+because the stretch and shrink from the \.{\\skip} registers for inserts
+are not actually present in the box.
+
+@<Break the current page at node |p|, put it...@>=
+if p<>null then
+ begin if vlink(contrib_head)=null then
+ if nest_ptr=0 then tail:=page_tail
+ else contrib_tail:=page_tail;
+ vlink(page_tail):=vlink(contrib_head);
+ vlink(contrib_head):=p;
+ vlink(prev_p):=null;
+ end;
+save_vbadness:=vbadness; vbadness:=inf_bad;
+save_vfuzz:=vfuzz; vfuzz:=max_dimen; {inhibit error messages}
+pack_direction:=body_direction;
+box(255):=filtered_vpackage(vlink(page_head),best_size,exactly,page_max_depth,output_group);
+vbadness:=save_vbadness; vfuzz:=save_vfuzz;
+if last_glue<>max_halfword then delete_glue_ref(last_glue);
+@<Start a new current page@>; {this sets |last_glue:=max_halfword|}
+if q<>hold_head then
+ begin vlink(page_head):=vlink(hold_head); page_tail:=q;
+ end
+
+@ If many insertions are supposed to go into the same box, we want to know
+the position of the last node in that box, so that we don't need to waste time
+when linking further information into it. The |last_ins_ptr| fields of the
+page insertion nodes are therefore used for this purpose during the
+packaging phase.
+
+@<Prepare all the boxes involved in insertions to act as queues@>=
+begin r:=vlink(page_ins_head);
+while r<>page_ins_head do
+ begin if best_ins_ptr(r)<>null then
+ begin n:=qo(subtype(r)); ensure_vbox(n);
+ if box(n)=null then box(n):=new_null_box;
+ p:=box(n)+list_offset;
+ while vlink(p)<>null do p:=vlink(p);
+ last_ins_ptr(r):=p;
+ end;
+ r:=vlink(r);
+ end;
+end
+
+@ @<Delete \(t)the page-insertion nodes@>=
+r:=vlink(page_ins_head);
+while r<>page_ins_head do
+ begin q:=vlink(r); flush_node(r); r:=q;
+ end;
+vlink(page_ins_head):=page_ins_head
+
+@ We will set |best_ins_ptr:=null| and package the box corresponding to
+insertion node~|r|, just after making the final insertion into that box.
+If this final insertion is `|split_up_node|', the remainder after splitting
+and pruning (if any) will be carried over to the next page.
+
+@<Either insert the material specified by node |p| into...@>=
+begin r:=vlink(page_ins_head);
+while subtype(r)<>subtype(p) do r:=vlink(r);
+if best_ins_ptr(r)=null then wait:=true
+else begin wait:=false; s:=last_ins_ptr(r); vlink(s):=ins_ptr(p);
+ if best_ins_ptr(r)=p then
+ @<Wrap up the box specified by node |r|, splitting node |p| if
+ called for; set |wait:=true| if node |p| holds a remainder after
+ splitting@>
+ else begin while vlink(s)<>null do s:=vlink(s);
+ last_ins_ptr(r):=s;
+ end;
+ end;
+@<Either append the insertion node |p| after node |q|, and remove it
+ from the current page, or delete |node(p)|@>;
+end
+
+@ @<Wrap up the box specified by node |r|, splitting node |p| if...@>=
+begin if type(r)=split_up_node then
+ if (broken_ins(r)=p)and(broken_ptr(r)<>null) then
+ begin while vlink(s)<>broken_ptr(r) do s:=vlink(s);
+ vlink(s):=null;
+ split_top_skip:=split_top_ptr(p);
+ ins_ptr(p):=prune_page_top(broken_ptr(r),false);
+ if ins_ptr(p)<>null then
+ begin temp_ptr:=vpack(ins_ptr(p),natural);
+ height(p):=height(temp_ptr)+depth(temp_ptr);
+ list_ptr(temp_ptr):=null; flush_node(temp_ptr); wait:=true;
+ end;
+ end;
+best_ins_ptr(r):=null;
+n:=qo(subtype(r));
+temp_ptr:=list_ptr(box(n));
+list_ptr(box(n)):=null; flush_node(box(n));
+pack_direction:=body_direction;
+box(n):=vpack(temp_ptr,natural);
+end
+
+@ @<Either append the insertion node |p|...@>=
+vlink(prev_p):=vlink(p); vlink(p):=null;
+if wait then
+ begin vlink(q):=p; q:=p; incr(insert_penalties);
+ end
+else begin ins_ptr(p):=null; flush_node(p);
+ end;
+p:=prev_p
+
+@ The list of heldover insertions, running from |vlink(page_head)| to
+|page_tail|, must be moved to the contribution list when the user has
+specified no output routine.
+
+@<Perform the default output routine@>=
+begin if vlink(page_head)<>null then
+ begin if vlink(contrib_head)=null then
+ if nest_ptr=0 then tail:=page_tail@+else contrib_tail:=page_tail
+ else vlink(page_tail):=vlink(contrib_head);
+ vlink(contrib_head):=vlink(page_head);
+ vlink(page_head):=null; page_tail:=page_head;
+ end;
+flush_node_list(page_disc); page_disc:=null;
+ship_out(box(255)); box(255):=null;
+end
+
+@ @<Explain that too many dead cycles have occurred in a row@>=
+begin print_err("Output loop---"); print_int(dead_cycles);
+@.Output loop...@>
+print(" consecutive dead cycles");
+help3("I've concluded that your \output is awry; it never does a")@/
+("\shipout, so I'm shipping \box255 out myself. Next time")@/
+("increase \maxdeadcycles if you want me to be more patient!"); error;
+end
+
+@ @<Fire up the user's output routine and |return|@>=
+begin output_active:=true;
+incr(dead_cycles);
+push_nest; mode:=-vmode; prev_depth:=ignore_depth; mode_line:=-line;
+begin_token_list(output_routine,output_text);
+new_save_level(output_group); normal_paragraph;
+scan_left_brace;
+return;
+end
+
+@ When the user's output routine finishes, it has constructed a vlist
+in internal vertical mode, and \TeX\ will do the following:
+
+@<Resume the page builder after an output routine has come to an end@>=
+begin if (loc<>null) or
+ ((token_type<>output_text)and(token_type<>backed_up)) then
+ @<Recover from an unbalanced output routine@>;
+end_token_list; {conserve stack space in case more outputs are triggered}
+end_graf; unsave; output_active:=false; insert_penalties:=0;@/
+@<Ensure that box 255 is empty after output@>;
+if tail<>head then {current list goes after heldover insertions}
+ begin vlink(page_tail):=vlink(head);
+ page_tail:=tail;
+ end;
+if vlink(page_head)<>null then {and both go before heldover contributions}
+ begin if vlink(contrib_head)=null then contrib_tail:=page_tail;
+ vlink(page_tail):=vlink(contrib_head);
+ vlink(contrib_head):=vlink(page_head);
+ vlink(page_head):=null; page_tail:=page_head;
+ end;
+flush_node_list(page_disc); page_disc:=null;
+pop_nest; build_page;
+end
+
+@ @<Recover from an unbalanced output routine@>=
+begin print_err("Unbalanced output routine");
+@.Unbalanced output routine@>
+help2("Your sneaky output routine has problematic {'s and/or }'s.")@/
+("I can't handle that very well; good luck."); error;
+repeat get_token;
+until loc=null;
+end {loops forever if reading from a file, since |null=min_halfword<=0|}
+
+@ @<Ensure that box 255 is empty after output@>=
+if box(255)<>null then
+ begin print_err("Output routine didn't use all of ");
+ print_esc("box"); print_int(255);
+@.Output routine didn't use...@>
+ help3("Your \output commands should empty \box255,")@/
+ ("e.g., by saying `\shipout\box255'.")@/
+ ("Proceed; I'll discard its present contents.");
+ box_error(255);
+ end
+
+@* \[46] The chief executive.
+We come now to the |main_control| routine, which contains the master
+switch that causes all the various pieces of \TeX\ to do their things,
+in the right order.
+
+In a sense, this is the grand climax of the program: It applies all the
+tools that we have worked so hard to construct. In another sense, this is
+the messiest part of the program: It necessarily refers to other pieces
+of code all over the place, so that a person can't fully understand what is
+going on without paging back and forth to be reminded of conventions that
+are defined elsewhere. We are now at the hub of the web, the central nervous
+system that touches most of the other parts and ties them together.
+@^brain@>
+
+The structure of |main_control| itself is quite simple. There's a label
+called |big_switch|, at which point the next token of input is fetched
+using |get_x_token|. Then the program branches at high speed into one of
+about 100 possible directions, based on the value of the current
+mode and the newly fetched command code; the sum |abs(mode)+cur_cmd|
+indicates what to do next. For example, the case `|vmode+letter|' arises
+when a letter occurs in vertical mode (or internal vertical mode); this
+case leads to instructions that initialize a new paragraph and enter
+horizontal mode.
+
+The big |case| statement that contains this multiway switch has been labeled
+|reswitch|, so that the program can |goto reswitch| when the next token
+has already been fetched. Most of the cases are quite short; they call
+an ``action procedure'' that does the work for that case, and then they
+either |goto reswitch| or they ``fall through'' to the end of the |case|
+statement, which returns control back to |big_switch|. Thus, |main_control|
+is not an extremely large procedure, in spite of the multiplicity of things
+it must do; it is small enough to be handled by \PASCAL\ compilers that put
+severe restrictions on procedure size.
+@!@^action procedure@>
+
+One case is singled out for special treatment, because it accounts for most
+of \TeX's activities in typical applications. The process of reading simple
+text and converting it into |char_node| records, while looking for ligatures
+and kerns, is part of \TeX's ``inner loop''; the whole program runs
+efficiently when its inner loop is fast, so this part has been written
+with particular care.
+
+@ We shall concentrate first on the inner loop of |main_control|, deferring
+consideration of the other cases until later.
+@^inner loop@>
+
+@d big_switch=60 {go here to branch on the next token of input}
+
+@p @t\4@>@<Declare action procedures for use by |main_control|@>@;
+@t\4@>@<Declare the procedure called |handle_right_brace|@>@;
+procedure main_control; {governs \TeX's activities}
+label big_switch,reswitch,continue,exit;
+var@!t,k:integer; {general-purpose temporary variables}
+p:pointer; {for whatsit nodes and testing whether an auto kern should be inserted}
+chr_stack:integer; { to temporarily save an |cur_chr| to be appended }
+begin t:=0; {for -Wall}
+chr_stack:=-1;
+if every_job<>null then begin_token_list(every_job,every_job_text);
+big_switch: get_x_token;@/
+reswitch: @<Give diagnostic information, if requested@>;
+case abs(mode)+cur_cmd of
+hmode+letter,hmode+other_char,hmode+char_given,hmode+char_num: begin
+ if abs(mode)+cur_cmd=hmode+char_num then begin
+ scan_char_num; cur_chr:=cur_val;
+ end;
+ if is_last_ocp(current_ocp_lstack,current_ocp_no) then begin
+ @<Append character |cur_chr| and the following characters (if~any)
+ to the current hlist in the current font; |goto reswitch| when
+ a non-character has been fetched@>;
+ end
+ else begin
+ @<Create a buffer with character |cur_chr| and the following
+ characters (if~any) and then apply the current active OCP filter
+ to this buffer@>;
+ end;
+ end;
+hmode+no_boundary: begin @<Append a |cancel_boundary_node| @>;
+ end;
+hmode+char_ghost: begin t:=cur_chr; get_x_token;
+ if (cur_cmd=letter)or(cur_cmd=other_char)or(cur_cmd=char_given)or
+ (cur_cmd=char_num) then begin
+ p:=new_glyph(cur_font,cur_chr);
+ if t=0 then begin set_is_leftghost(p); end
+ else begin set_is_rightghost(p); end;
+ tail_append(p);
+ end;
+ end;
+hmode+spacer,hmode+ex_space,mmode+ex_space:
+if (abs(mode)+cur_cmd=hmode+spacer) and
+ (not (space_factor = 1000)) then
+ app_space
+else begin
+ @<Append a normal inter-word space to the current list@>;
+ end;
+@t\4@>@<Cases of |main_control| that are not part of the inner loop@>@;
+end; {of the big |case| statement}
+goto big_switch;
+exit:end;
+
+@ When a new token has just been fetched at |big_switch|, we have an
+ideal place to monitor \TeX's activity.
+@^debugging@>
+
+@<Give diagnostic information, if requested@>=
+if interrupt<>0 then if OK_to_interrupt then
+ begin back_input; check_interrupt; goto big_switch;
+ end;
+if tracing_commands>0 then show_cur_cmd_chr
+
+@ The following part of the program was first written in a structured
+manner, according to the philosophy that ``premature optimization is
+the root of all evil.'' Then it was rearranged into pieces of
+spaghetti so that the most common actions could proceed with little or
+no redundancy. And finally, it is replaced by a completely standalone
+loop over the node list: luatex does not have a |main+loop| at all.
+@^inner loop@>
+
+@<Glob...@>=
+@!main_p:pointer; {temporary register for list manipulation}
+@!main_s:integer; {space factor value}
+
+@ We leave the |space_factor| unchanged if |sf_code(cur_chr)=0|; otherwise we
+set it equal to |sf_code(cur_chr)|, except that it should never change
+from a value less than 1000 to a value exceeding 1000. The most common
+case is |sf_code(cur_chr)=1000|, so we want that case to be fast.
+
+@d adjust_space_factor==@t@>@;@/
+ main_s:=get_sf_code(cur_chr);
+ if main_s=1000 then space_factor:=1000
+ else if main_s<1000 then
+ begin if main_s>0 then space_factor:=main_s;
+ end
+ else if space_factor<1000 then space_factor:=1000
+ else space_factor:=main_s
+
+@<Append character |cur_chr|...@>=
+continue: adjust_space_factor;@/
+chr_stack:=cur_chr;
+tail_append(new_char(cur_font,chr_stack));
+get_x_token;
+if (cur_cmd=letter)or(cur_cmd=other_char)or
+ (cur_cmd=char_given)or(cur_cmd=char_num) then begin
+ if cur_cmd=char_num then begin
+ scan_char_num; cur_chr:=cur_val;
+ end;
+ if (chr_stack=ex_hyphen_char)and(cur_chr<>ex_hyphen_char)and(mode>0) then begin
+ tail_append(new_disc); subtype(tail):=automatic_disc;
+ end;
+ goto continue;
+ end
+else begin
+ if (chr_stack=ex_hyphen_char) and (mode>0) then begin
+ tail_append(new_disc); subtype(tail):=automatic_disc;
+ end;
+ chr_stack:=-1;
+ goto reswitch;
+ end
+
+@ The occurrence of blank spaces is almost part of \TeX's inner loop,
+@^inner loop@>
+since we usually encounter about one space for every five non-blank characters.
+Therefore |main_control| gives second-highest priority to ordinary spaces.
+
+When a glue parameter like \.{\\spaceskip} is set to `\.{0pt}', we will
+see to it later that the corresponding glue specification is precisely
+|zero_glue|, not merely a pointer to some specification that happens
+to be full of zeroes. Therefore it is simple to test whether a glue parameter
+is zero or~not.
+
+@<Append a normal inter-word space...@>=
+if space_skip=zero_glue then
+ begin @<Find the glue specification, |main_p|, for
+ text spaces in the current font@>;
+ temp_ptr:=new_glue(main_p);
+ end
+else temp_ptr:=new_param_glue(space_skip_code);
+vlink(tail):=temp_ptr; tail:=temp_ptr
+
+
+@ From Knuth: ``Having |font_glue| allocated for each text font saves
+both time and memory.'' That may be true, but it also punches through
+the API wall for fonts, so I removed that -- Taco. But a bit of caching
+is very welcome, which is why I need to have the next two globals:
+
+@<Glob...@>=
+space_spec_font:internal_font_number;
+space_spec_cache:halfword;
+
+@ @<Set init...@>=
+space_spec_font:=0;
+space_spec_cache:=zero_glue;
+
+@ @<Find the glue specification...@>=
+begin
+if cur_font<>space_spec_font then begin
+ if space_spec_cache<>zero_glue then
+ delete_glue_ref(space_spec_cache);
+ space_spec_cache:=new_spec(zero_glue);
+ width(space_spec_cache):=space(cur_font);
+ stretch(space_spec_cache):=space_stretch(cur_font);
+ shrink(space_spec_cache):=space_shrink(cur_font);
+ space_spec_font:=cur_font;
+ end;
+main_p:=space_spec_cache;
+end
+
+@ @<Declare act...@>=
+procedure app_space; {handle spaces when |space_factor<>1000|}
+var@!q:pointer; {glue node}
+begin if (space_factor>=2000)and(xspace_skip<>zero_glue) then
+ q:=new_param_glue(xspace_skip_code)
+else begin if space_skip<>zero_glue then
+ main_p:=new_spec(space_skip)
+ else begin
+ main_p:=new_spec(zero_glue);
+ width(main_p):=space(cur_font);
+ stretch(main_p):=space_stretch(cur_font);
+ shrink(main_p):=space_shrink(cur_font);
+ end;
+ @<Modify the glue specification in |main_p| according to the space factor@>;
+ q:=new_glue(main_p); glue_ref_count(main_p):=null;
+ end;
+vlink(tail):=q; tail:=q;
+end;
+
+@ @<Modify the glue specification in |main_p| according to the space factor@>=
+if space_factor>=2000 then width(main_p):=width(main_p)+extra_space(cur_font);
+stretch(main_p):=xn_over_d(stretch(main_p),space_factor,1000);
+shrink(main_p):=xn_over_d(shrink(main_p),1000,space_factor)
+
+@ Whew---that covers the main loop. We can now proceed at a leisurely
+pace through the other combinations of possibilities.
+
+@d any_mode(#)==vmode+#,hmode+#,mmode+# {for mode-independent commands}
+
+@<Cases of |main_control| that are not part of the inner loop@>=
+any_mode(relax),vmode+spacer,mmode+spacer,mmode+no_boundary:do_nothing;
+any_mode(ignore_spaces): begin
+ if cur_chr = 0 then begin
+ @<Get the next non-blank non-call...@>;
+ goto reswitch;
+ end
+ else begin
+ t:=scanner_status;
+ scanner_status:=normal;
+ get_filtered_next;
+ scanner_status:=t;
+ cur_cs := prim_lookup(text(cur_cs));
+ if cur_cs<>undefined_primitive then begin
+ cur_cmd := get_prim_eq_type(cur_cs);
+ cur_chr := get_prim_equiv(cur_cs);
+ cur_tok := (cur_cmd*string_offset)+cur_chr;
+ goto reswitch;
+ end;
+ end;
+ end;
+vmode+stop: if its_all_over then return; {this is the only way out}
+@t\4@>@<Forbidden cases detected in |main_control|@>@+@,any_mode(mac_param):
+ report_illegal_case;
+@<Math-only cases in non-math modes, or vice versa@>: insert_dollar_sign;
+@t\4@>@<Cases of |main_control| that build boxes and lists@>@;
+@t\4@>@<Cases of |main_control| that don't depend on |mode|@>@;
+@t\4@>@<Cases of |main_control| that are for extensions to \TeX@>@;
+
+@ Here is a list of cases where the user has probably gotten into or out of math
+mode by mistake. \TeX\ will insert a dollar sign and rescan the current token.
+
+@d non_math(#)==vmode+#,hmode+#
+
+@<Math-only cases in non-math modes...@>=
+non_math(sup_mark), non_math(sub_mark), non_math(math_char_num),
+non_math(math_given), non_math(omath_given),
+non_math(math_comp), non_math(delim_num),
+non_math(left_right), non_math(above), non_math(radical),
+non_math(math_style), non_math(math_choice), non_math(vcenter),
+non_math(non_script), non_math(mkern), non_math(limit_switch),
+non_math(mskip), non_math(math_accent),
+mmode+endv, mmode+par_end, mmode+stop, mmode+vskip, mmode+un_vbox,
+mmode+valign, mmode+hrule
+
+@ @<Declare action...@>=
+procedure insert_dollar_sign;
+begin back_input; cur_tok:=math_shift_token+"$";
+print_err("Missing $ inserted");
+@.Missing \$ inserted@>
+help2("I've inserted a begin-math/end-math symbol since I think")@/
+("you left one out. Proceed, with fingers crossed."); ins_error;
+end;
+
+@ When erroneous situations arise, \TeX\ usually issues an error message
+specific to the particular error. For example, `\.{\\noalign}' should
+not appear in any mode, since it is recognized by the |align_peek| routine
+in all of its legitimate appearances; a special error message is given
+when `\.{\\noalign}' occurs elsewhere. But sometimes the most appropriate
+error message is simply that the user is not allowed to do what he or she
+has attempted. For example, `\.{\\moveleft}' is allowed only in vertical mode,
+and `\.{\\lower}' only in non-vertical modes. Such cases are enumerated
+here and in the other sections referred to under `See also \dots.'
+
+@<Forbidden cases...@>=
+vmode+vmove,hmode+hmove,mmode+hmove,any_mode(last_item),
+
+@ The `|you_cant|' procedure prints a line saying that the current command
+is illegal in the current mode; it identifies these things symbolically.
+
+@<Declare action...@>=
+procedure you_cant;
+begin print_err("You can't use `");
+@.You can't use x in y mode@>
+print_cmd_chr(cur_cmd,cur_chr);
+print("' in "); print_mode(mode);
+end;
+
+@ @<Declare act...@>=
+procedure report_illegal_case;
+begin you_cant;
+help4("Sorry, but I'm not programmed to handle this case;")@/
+("I'll just pretend that you didn't ask for it.")@/
+("If you're in the wrong mode, you might be able to")@/
+("return to the right one by typing `I}' or `I$' or `I\par'.");@/
+error;
+end;
+
+@ Some operations are allowed only in privileged modes, i.e., in cases
+that |mode>0|. The |privileged| function is used to detect violations
+of this rule; it issues an error message and returns |false| if the
+current |mode| is negative.
+
+@<Declare act...@>=
+function privileged:boolean;
+begin if mode>0 then privileged:=true
+else begin report_illegal_case; privileged:=false;
+ end;
+end;
+
+@ Either \.{\\dump} or \.{\\end} will cause |main_control| to enter the
+endgame, since both of them have `|stop|' as their command code.
+
+@<Put each...@>=
+primitive("end",stop,0);@/
+@!@:end_}{\.{\\end} primitive@>
+primitive("dump",stop,1);@/
+@!@:dump_}{\.{\\dump} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+stop:if chr_code=1 then print_esc("dump")@+else print_esc("end");
+
+@ We don't want to leave |main_control| immediately when a |stop| command
+is sensed, because it may be necessary to invoke an \.{\\output} routine
+several times before things really grind to a halt. (The output routine
+might even say `\.{\\gdef\\end\{...\}}', to prolong the life of the job.)
+Therefore |its_all_over| is |true| only when the current page
+and contribution list are empty, and when the last output was not a
+``dead cycle.''
+
+@<Declare act...@>=
+function its_all_over:boolean; {do this when \.{\\end} or \.{\\dump} occurs}
+label exit;
+begin if privileged then
+ begin if (page_head=page_tail)and(head=tail)and(dead_cycles=0) then
+ begin its_all_over:=true; return;
+ end;
+ back_input; {we will try to end again after ejecting residual material}
+ tail_append(new_null_box);
+ width(tail):=hsize;
+ tail_append(new_glue(fill_glue));
+ tail_append(new_penalty(-@'10000000000));@/
+ build_page; {append \.{\\hbox to \\hsize\{\}\\vfill\\penalty-'10000000000}}
+ end;
+its_all_over:=false;
+exit:end;
+
+@* \[47] Building boxes and lists.
+The most important parts of |main_control| are concerned with \TeX's
+chief mission of box-making. We need to control the activities that put
+entries on vlists and hlists, as well as the activities that convert
+those lists into boxes. All of the necessary machinery has already been
+developed; it remains for us to ``push the buttons'' at the right times.
+
+@ As an introduction to these routines, let's consider one of the simplest
+cases: What happens when `\.{\\hrule}' occurs in vertical mode, or
+`\.{\\vrule}' in horizontal mode or math mode? The code in |main_control|
+is short, since the |scan_rule_spec| routine already does most of what is
+required; thus, there is no need for a special action procedure.
+
+Note that baselineskip calculations are disabled after a rule in vertical
+mode, by setting |prev_depth:=ignore_depth|.
+
+@<Cases of |main_control| that build...@>=
+vmode+hrule,hmode+vrule,mmode+vrule: begin tail_append(scan_rule_spec);
+ if abs(mode)=vmode then prev_depth:=ignore_depth
+ else if abs(mode)=hmode then space_factor:=1000;
+ end;
+
+@ The processing of things like \.{\\hskip} and \.{\\vskip} is slightly
+more complicated. But the code in |main_control| is very short, since
+it simply calls on the action routine |append_glue|. Similarly, \.{\\kern}
+activates |append_kern|.
+
+@<Cases of |main_control| that build...@>=
+vmode+vskip,hmode+hskip,mmode+hskip,mmode+mskip: append_glue;
+any_mode(kern),mmode+mkern: append_kern;
+
+@ The |hskip| and |vskip| command codes are used for control sequences
+like \.{\\hss} and \.{\\vfil} as well as for \.{\\hskip} and \.{\\vskip}.
+The difference is in the value of |cur_chr|.
+
+@d fil_code=0 {identifies \.{\\hfil} and \.{\\vfil}}
+@d fill_code=1 {identifies \.{\\hfill} and \.{\\vfill}}
+@d ss_code=2 {identifies \.{\\hss} and \.{\\vss}}
+@d fil_neg_code=3 {identifies \.{\\hfilneg} and \.{\\vfilneg}}
+@d skip_code=4 {identifies \.{\\hskip} and \.{\\vskip}}
+@d mskip_code=5 {identifies \.{\\mskip}}
+
+@<Put each...@>=
+primitive("hskip",hskip,skip_code);@/
+@!@:hskip_}{\.{\\hskip} primitive@>
+primitive("hfil",hskip,fil_code);
+@!@:hfil_}{\.{\\hfil} primitive@>
+primitive("hfill",hskip,fill_code);@/
+@!@:hfill_}{\.{\\hfill} primitive@>
+primitive("hss",hskip,ss_code);
+@!@:hss_}{\.{\\hss} primitive@>
+primitive("hfilneg",hskip,fil_neg_code);@/
+@!@:hfil_neg_}{\.{\\hfilneg} primitive@>
+primitive("vskip",vskip,skip_code);@/
+@!@:vskip_}{\.{\\vskip} primitive@>
+primitive("vfil",vskip,fil_code);
+@!@:vfil_}{\.{\\vfil} primitive@>
+primitive("vfill",vskip,fill_code);@/
+@!@:vfill_}{\.{\\vfill} primitive@>
+primitive("vss",vskip,ss_code);
+@!@:vss_}{\.{\\vss} primitive@>
+primitive("vfilneg",vskip,fil_neg_code);@/
+@!@:vfil_neg_}{\.{\\vfilneg} primitive@>
+primitive("mskip",mskip,mskip_code);@/
+@!@:mskip_}{\.{\\mskip} primitive@>
+primitive("kern",kern,explicit);
+@!@:kern_}{\.{\\kern} primitive@>
+primitive("mkern",mkern,mu_glue);@/
+@!@:mkern_}{\.{\\mkern} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+hskip: case chr_code of
+ skip_code:print_esc("hskip");
+ fil_code:print_esc("hfil");
+ fill_code:print_esc("hfill");
+ ss_code:print_esc("hss");
+ othercases print_esc("hfilneg")
+ endcases;
+vskip: case chr_code of
+ skip_code:print_esc("vskip");
+ fil_code:print_esc("vfil");
+ fill_code:print_esc("vfill");
+ ss_code:print_esc("vss");
+ othercases print_esc("vfilneg")
+ endcases;
+mskip: print_esc("mskip");
+kern: print_esc("kern");
+mkern: print_esc("mkern");
+
+@ All the work relating to glue creation has been relegated to the
+following subroutine. It does not call |build_page|, because it is
+used in at least one place where that would be a mistake.
+
+@<Declare action...@>=
+procedure append_glue;
+var s:small_number; {modifier of skip command}
+begin s:=cur_chr;
+case s of
+fil_code: cur_val:=fil_glue;
+fill_code: cur_val:=fill_glue;
+ss_code: cur_val:=ss_glue;
+fil_neg_code: cur_val:=fil_neg_glue;
+skip_code: scan_glue(glue_val);
+mskip_code: scan_glue(mu_val);
+end; {now |cur_val| points to the glue specification}
+tail_append(new_glue(cur_val));
+if s>=skip_code then
+ begin decr(glue_ref_count(cur_val));
+ if s>skip_code then subtype(tail):=mu_glue;
+ end;
+end;
+
+@ @<Declare act...@>=
+procedure append_kern;
+var s:quarterword; {|subtype| of the kern node}
+begin s:=cur_chr; scan_dimen(s=mu_glue,false,false);
+tail_append(new_kern(cur_val)); subtype(tail):=s;
+end;
+
+@ Many of the actions related to box-making are triggered by the appearance
+of braces in the input. For example, when the user says `\.{\\hbox}
+\.{to} \.{100pt\{$\langle\,\hbox{hlist}\,\rangle$\}}' in vertical mode,
+the information about the box size (100pt, |exactly|) is put onto |save_stack|
+with a level boundary word just above it, and |cur_group:=adjusted_hbox_group|;
+\TeX\ enters restricted horizontal mode to process the hlist. The right
+brace eventually causes |save_stack| to be restored to its former state,
+at which time the information about the box size (100pt, |exactly|) is
+available once again; a box is packaged and we leave restricted horizontal
+mode, appending the new box to the current list of the enclosing mode
+(in this case to the current list of vertical mode), followed by any
+vertical adjustments that were removed from the box by |hpack|.
+
+The next few sections of the program are therefore concerned with the
+treatment of left and right curly braces.
+
+@ If a left brace occurs in the middle of a page or paragraph, it simply
+introduces a new level of grouping, and the matching right brace will not have
+such a drastic effect. Such grouping affects neither the mode nor the
+current list.
+
+@<Cases of |main_control| that build...@>=
+non_math(left_brace): begin
+ new_save_level(simple_group);
+ eq_word_define(int_base+no_local_whatsits_code,0);
+ eq_word_define(int_base+no_local_dirs_code,0);
+ end;
+any_mode(begin_group): begin
+ new_save_level(semi_simple_group);
+ eq_word_define(int_base+no_local_whatsits_code,0);
+ eq_word_define(int_base+no_local_dirs_code,0);
+ end;
+any_mode(end_group):
+ if cur_group=semi_simple_group then begin
+ temp_no_whatsits:=no_local_whatsits;
+ temp_no_dirs:=no_local_dirs;
+ temporary_dir:=text_direction;
+ if dir_level(text_dir_ptr)=cur_level then
+ @<DIR: Remove from |text_dir_ptr|@>;
+ unsave;
+ if abs(mode)=hmode then begin
+ if temp_no_dirs<>0 then begin
+ @<DIR: Add local dir node@>;
+ dir_dir(tail):=temporary_dir-64;
+ end;
+ if temp_no_whatsits<>0 then
+ @<LOCAL: Add local paragraph node@>;
+ end
+ end
+ else off_save;
+
+@ We have to deal with errors in which braces and such things are not
+properly nested. Sometimes the user makes an error of commission by
+inserting an extra symbol, but sometimes the user makes an error of omission.
+\TeX\ can't always tell one from the other, so it makes a guess and tries
+to avoid getting into a loop.
+
+The |off_save| routine is called when the current group code is wrong. It tries
+to insert something into the user's input that will help clean off
+the top level.
+
+@<Declare act...@>=
+procedure off_save;
+var p,q:pointer; {inserted token}
+begin if cur_group=bottom_level then
+ @<Drop current token and complain that it was unmatched@>
+else begin back_input; p:=get_avail; link(temp_token_head):=p;
+ print_err("Missing ");
+ @<Prepare to insert a token that matches |cur_group|,
+ and print what it is@>;
+ print(" inserted"); ins_list(link(temp_token_head));
+ help5("I've inserted something that you may have forgotten.")@/
+ ("(See the <inserted text> above.)")@/
+ ("With luck, this will get me unwedged. But if you")@/
+ ("really didn't forget anything, try typing `2' now; then")@/
+ ("my insertion and my current dilemma will both disappear.");
+ error;
+ end;
+end;
+
+@ At this point, |link(temp_token_head)=p|, a pointer to an empty one-word node.
+
+@<Prepare to insert a token that matches |cur_group|...@>=
+case cur_group of
+semi_simple_group: begin info(p):=cs_token_flag+frozen_end_group;
+ print_esc("endgroup");
+@.Missing \\endgroup inserted@>
+ end;
+math_shift_group: begin info(p):=math_shift_token+"$"; print_char("$");
+@.Missing \$ inserted@>
+ end;
+math_left_group: begin info(p):=cs_token_flag+frozen_right; q:=get_avail; link(p):=q;
+ p:=link(p); info(p):=other_token+"."; print_esc("right.");
+@.Missing \\right\hbox{.} inserted@>
+@^null delimiter@>
+ end;
+othercases begin info(p):=right_brace_token+"}"; print_char("}");
+@.Missing \} inserted@>
+ end
+endcases
+
+@ @<Drop current token and complain that it was unmatched@>=
+begin print_err("Extra "); print_cmd_chr(cur_cmd,cur_chr);
+@.Extra x@>
+help1("Things are pretty mixed up, but I think the worst is over.");@/
+error;
+end
+
+@ The routine for a |right_brace| character branches into many subcases,
+since a variety of things may happen, depending on |cur_group|. Some
+types of groups are not supposed to be ended by a right brace; error
+messages are given in hopes of pinpointing the problem. Most branches
+of this routine will be filled in later, when we are ready to understand
+them; meanwhile, we must prepare ourselves to deal with such errors.
+
+@<Cases of |main_control| that build...@>=
+any_mode(right_brace): handle_right_brace;
+
+@ @<Declare the procedure called |handle_right_brace|@>=
+procedure handle_right_brace;
+var p,@!q:pointer; {for short-term use}
+@!d:scaled; {holds |split_max_depth| in |insert_group|}
+@!f:integer; {holds |floating_penalty| in |insert_group|}
+begin case cur_group of
+simple_group: begin
+ temp_no_whatsits:=no_local_whatsits;
+ temp_no_dirs:=no_local_dirs;
+ temporary_dir:=text_direction;
+ if dir_level(text_dir_ptr)=cur_level then
+ @<DIR: Remove from |text_dir_ptr|@>;
+ unsave;
+ if abs(mode)=hmode then begin
+ if temp_no_dirs<>0 then begin
+ @<DIR: Add local dir node@>;
+ dir_dir(tail):=temporary_dir-64;
+ end;
+ if temp_no_whatsits<>0 then
+ @<LOCAL: Add local paragraph node@>;
+ end
+ end;
+bottom_level: begin print_err("Too many }'s");
+@.Too many \}'s@>
+ help2("You've closed more groups than you opened.")@/
+ ("Such booboos are generally harmless, so keep going."); error;
+ end;
+semi_simple_group,math_shift_group,math_left_group: extra_right_brace;
+@t\4@>@<Cases of |handle_right_brace| where a |right_brace| triggers
+ a delayed action@>@;
+othercases confusion("rightbrace")
+@:this can't happen rightbrace}{\quad rightbrace@>
+endcases;
+end;
+
+@ @<Declare act...@>=
+procedure extra_right_brace;
+begin print_err("Extra }, or forgotten ");
+@.Extra \}, or forgotten x@>
+case cur_group of
+semi_simple_group: print_esc("endgroup");
+math_shift_group: print_char("$");
+math_left_group: print_esc("right");
+end;@/
+help5("I've deleted a group-closing symbol because it seems to be")@/
+("spurious, as in `$x}$'. But perhaps the } is legitimate and")@/
+("you forgot something else, as in `\hbox{$x}'. In such cases")@/
+("the way to recover is to insert both the forgotten and the")@/
+("deleted material, e.g., by typing `I$}'."); error;
+incr(align_state);
+end;
+
+@ Here is where we clear the parameters that are supposed to revert to their
+default values after every paragraph and when internal vertical mode is entered.
+
+@<Declare act...@>=
+procedure normal_paragraph;
+begin if looseness<>0 then eq_word_define(int_base+looseness_code,0);
+if hang_indent<>0 then eq_word_define(dimen_base+hang_indent_code,0);
+if hang_after<>1 then eq_word_define(int_base+hang_after_code,1);
+if par_shape_ptr<>null then eq_define(par_shape_loc,shape_ref,null);
+if inter_line_penalties_ptr<>null then
+ eq_define(inter_line_penalties_loc,shape_ref,null);
+end;
+
+@ Now let's turn to the question of how \.{\\hbox} is treated. We actually
+need to consider also a slightly larger context, since constructions like
+`\.{\\setbox3=}\penalty0\.{\\hbox...}' and
+`\.{\\leaders}\penalty0\.{\\hbox...}' and
+`\.{\\lower3.8pt\\hbox...}'
+are supposed to invoke quite
+different actions after the box has been packaged. Conversely,
+constructions like `\.{\\setbox3=}' can be followed by a variety of
+different kinds of boxes, and we would like to encode such things in an
+efficient way.
+
+In other words, there are two problems: To represent the context of a box,
+and to represent its type.
+
+The first problem is solved by putting a ``context code'' on the |save_stack|,
+just below the two entries that give the dimensions produced by |scan_spec|.
+The context code is either a (signed) shift amount, or it is a large
+integer |>=box_flag|, where |box_flag=@t$2^{30}$@>|. Codes |box_flag| through
+|box_flag+biggest_reg| represent `\.{\\setbox0}' through
+`\.{\\setbox}|biggest_reg|'; codes |box_flag+biggest_reg+1| through
+|box_flag+2*biggest_reg| represent `\.{\\global\\setbox0}'
+through `\.{\\global\\setbox}|biggest_reg|'; code |box_flag+2*number_regs|
+represents `\.{\\shipout}'; and codes |box_flag+2*number_regs+1|
+through |box_flag+2*number_regs+3| represent `\.{\\leaders}', `\.{\\cleaders}',
+and `\.{\\xleaders}'.
+
+The second problem is solved by giving the command code |make_box| to all
+control sequences that produce a box, and by using the following |chr_code|
+values to distinguish between them: |box_code|, |copy_code|, |last_box_code|,
+|vsplit_code|, |vtop_code|, |vtop_code+vmode|, and |vtop_code+hmode|,
+where the latter two are used denote \.{\\vbox} and \.{\\hbox}, respectively.
+
+@d box_flag==@'10000000000 {context code for `\.{\\setbox0}'}
+@d global_box_flag==(box_flag+number_regs) {context code for `\.{\\global\\setbox0}'}
+@d max_global_box_flag==(global_box_flag+number_regs)
+@d ship_out_flag==(max_global_box_flag+1) {context code for `\.{\\shipout}'}
+@d leader_flag==ship_out_flag+1 {context code for `\.{\\leaders}'}
+@d box_code=0 {|chr_code| for `\.{\\box}'}
+@d copy_code=1 {|chr_code| for `\.{\\copy}'}
+@d last_box_code=2 {|chr_code| for `\.{\\lastbox}'}
+@d vsplit_code=3 {|chr_code| for `\.{\\vsplit}'}
+@d vtop_code=4 {|chr_code| for `\.{\\vtop}'}
+
+@<Put each...@>=
+primitive("moveleft",hmove,1);
+@!@:move_left_}{\.{\\moveleft} primitive@>
+primitive("moveright",hmove,0);@/
+@!@:move_right_}{\.{\\moveright} primitive@>
+primitive("raise",vmove,1);
+@!@:raise_}{\.{\\raise} primitive@>
+primitive("lower",vmove,0);
+@!@:lower_}{\.{\\lower} primitive@>
+@#
+primitive("box",make_box,box_code);
+@!@:box_}{\.{\\box} primitive@>
+primitive("copy",make_box,copy_code);
+@!@:copy_}{\.{\\copy} primitive@>
+primitive("lastbox",make_box,last_box_code);
+@!@:last_box_}{\.{\\lastbox} primitive@>
+primitive("vsplit",make_box,vsplit_code);
+@!@:vsplit_}{\.{\\vsplit} primitive@>
+primitive("vtop",make_box,vtop_code);@/
+@!@:vtop_}{\.{\\vtop} primitive@>
+primitive("vbox",make_box,vtop_code+vmode);
+@!@:vbox_}{\.{\\vbox} primitive@>
+primitive("hbox",make_box,vtop_code+hmode);@/
+@!@:hbox_}{\.{\\hbox} primitive@>
+primitive("shipout",leader_ship,a_leaders-1); {|ship_out_flag=leader_flag-1|}
+@!@:ship_out_}{\.{\\shipout} primitive@>
+primitive("leaders",leader_ship,a_leaders);
+@!@:leaders_}{\.{\\leaders} primitive@>
+primitive("cleaders",leader_ship,c_leaders);
+@!@:c_leaders_}{\.{\\cleaders} primitive@>
+primitive("xleaders",leader_ship,x_leaders);
+@!@:x_leaders_}{\.{\\xleaders} primitive@>;
+primitive("boxdir",assign_box_dir,0);
+@!@:box_dir}{\.{\\boxdir} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+hmove: if chr_code=1 then print_esc("moveleft")@+else print_esc("moveright");
+vmove: if chr_code=1 then print_esc("raise")@+else print_esc("lower");
+make_box: case chr_code of
+ box_code: print_esc("box");
+ copy_code: print_esc("copy");
+ last_box_code: print_esc("lastbox");
+ vsplit_code: print_esc("vsplit");
+ vtop_code: print_esc("vtop");
+ vtop_code+vmode: print_esc("vbox");
+ othercases print_esc("hbox")
+ endcases;
+leader_ship: if chr_code=a_leaders then print_esc("leaders")
+ else if chr_code=c_leaders then print_esc("cleaders")
+ else if chr_code=x_leaders then print_esc("xleaders")
+ else print_esc("shipout");
+
+@ Constructions that require a box are started by calling |scan_box| with
+a specified context code. The |scan_box| routine verifies
+that a |make_box| command comes next and then it calls |begin_box|.
+
+@<Cases of |main_control| that build...@>=
+vmode+hmove,hmode+vmove,mmode+vmove: begin t:=cur_chr;
+ scan_normal_dimen;
+ if t=0 then scan_box(cur_val)@+else scan_box(-cur_val);
+ end;
+any_mode(leader_ship): scan_box(leader_flag-a_leaders+cur_chr);
+any_mode(make_box): begin_box(0);
+any_mode(assign_box_dir): begin scan_register_num;
+ cur_box:=box(cur_val);
+ scan_optional_equals; scan_direction;
+ if cur_box<>null then box_dir(cur_box):=cur_val;
+ end;
+
+@ The global variable |cur_box| will point to a newly-made box. If the box
+is void, we will have |cur_box=null|. Otherwise we will have
+|type(cur_box)=hlist_node| or |vlist_node| or |rule_node|; the |rule_node|
+case can occur only with leaders.
+
+@<Glob...@>=
+@!cur_box:pointer; {box to be placed into its context}
+
+@ The |box_end| procedure does the right thing with |cur_box|, if
+|box_context| represents the context as explained above.
+
+@<Declare act...@>=
+procedure box_end(@!box_context:integer);
+var p:pointer; {|ord_noad| for new box in math mode}
+begin if box_context<box_flag then @<Append box |cur_box| to the current list,
+ shifted by |box_context|@>
+else if box_context<ship_out_flag then @<Store \(c)|cur_box| in a box register@>
+else if cur_box<>null then
+ if box_context>ship_out_flag then @<Append a new leader node that
+ uses |cur_box|@>
+ else ship_out(cur_box);
+end;
+
+@ The global variable |adjust_tail| will be non-null if and only if the
+current box might include adjustments that should be appended to the
+current vertical list.
+
+@<Append box |cur_box| to the current...@>=
+begin if cur_box<>null then
+ begin shift_amount(cur_box):=box_context;
+ if abs(mode)=vmode then
+ begin
+ if pre_adjust_tail <> null then begin
+ if pre_adjust_head <> pre_adjust_tail then
+ append_list(pre_adjust_head)(pre_adjust_tail);
+ pre_adjust_tail := null;
+ end;
+ append_to_vlist(cur_box);
+ if adjust_tail <> null then begin
+ if adjust_head <> adjust_tail then
+ append_list(adjust_head)(adjust_tail);
+ adjust_tail := null;
+ end;
+ if mode>0 then begin check_filter('box'); build_page; end;
+ end
+ else begin if abs(mode)=hmode then space_factor:=1000
+ else begin p:=new_noad;
+ math_type(nucleus(p)):=sub_box;
+ vinfo(nucleus(p)):=cur_box; cur_box:=p;
+ end;
+ vlink(tail):=cur_box; tail:=cur_box;
+ end;
+ end;
+end
+
+@ @<Store \(c)|cur_box| in a box register@>=
+if box_context<global_box_flag then
+ eq_define(box_base+box_context-box_flag,box_ref,cur_box)
+else geq_define(box_base+box_context-global_box_flag,box_ref,cur_box)
+
+@ @<Append a new leader node ...@>=
+begin @<Get the next non-blank non-relax...@>;
+if ((cur_cmd=hskip)and(abs(mode)<>vmode))or@|
+ ((cur_cmd=vskip)and(abs(mode)=vmode))or@|
+ ((cur_cmd=mskip)and(abs(mode)=mmode)) then
+ begin append_glue; subtype(tail):=box_context-(leader_flag-a_leaders);
+ leader_ptr(tail):=cur_box;
+ end
+else begin print_err("Leaders not followed by proper glue");
+@.Leaders not followed by...@>
+ help3("You should say `\leaders <box or rule><hskip or vskip>'.")@/
+ ("I found the <box or rule>, but there's no suitable")@/
+ ("<hskip or vskip>, so I'm ignoring these leaders."); back_error;
+ flush_node_list(cur_box);
+ end;
+end
+
+@ Now that we can see what eventually happens to boxes, we can consider
+the first steps in their creation. The |begin_box| routine is called when
+|box_context| is a context specification, |cur_chr| specifies the type of
+box desired, and |cur_cmd=make_box|.
+
+@<Declare act...@>=
+procedure begin_box(@!box_context:integer);
+label exit, done;
+var @!p,@!q:pointer; {run through the current list}
+@!k:halfword; {0 or |vmode| or |hmode|}
+@!n:eight_bits; {a box number}
+begin case cur_chr of
+box_code: begin scan_register_num; cur_box:=box(cur_val);
+ box(cur_val):=null; {the box becomes void, at the same level}
+ end;
+copy_code: begin scan_register_num; cur_box:=copy_node_list(box(cur_val));
+ end;
+last_box_code: @<If the current list ends with a box node, delete it from
+ the list and make |cur_box| point to it; otherwise set |cur_box:=null|@>;
+vsplit_code: @<Split off part of a vertical box, make |cur_box| point to it@>;
+othercases @<Initiate the construction of an hbox or vbox, then |return|@>
+endcases;@/
+box_end(box_context); {in simple cases, we use the box immediately}
+exit:end;
+
+@ Note that the condition |not is_char_node(tail)| implies that |head<>tail|,
+since |head| is a one-word node.
+
+@<If the current list ends with a box node, delete it...@>=
+begin cur_box:=null;
+if abs(mode)=mmode then
+ begin you_cant; help1("Sorry; this \lastbox will be void."); error;
+ end
+else if (mode=vmode)and(head=tail) then
+ begin you_cant;
+ help2("Sorry...I usually can't take things from the current page.")@/
+ ("This \lastbox will therefore be void."); error;
+ end
+else begin if not is_char_node(tail) then
+ if (type(tail)=hlist_node)or(type(tail)=vlist_node) then
+ @<Remove the last box, unless it's part of a discretionary@>;
+ end;
+end
+
+@ @<Remove the last box...@>=
+begin q:=head;
+repeat p:=q;
+if not is_char_node(q) then if type(q)=disc_node then
+ begin
+ if p=tail then goto done;
+ end;
+q:=vlink(p);
+until q=tail;
+cur_box:=tail; shift_amount(cur_box):=0;
+tail:=p; vlink(p):=null;
+done:end
+
+@ Here we deal with things like `\.{\\vsplit 13 to 100pt}'.
+
+@<Split off part of a vertical box, make |cur_box| point to it@>=
+begin scan_register_num; n:=cur_val;
+if not scan_keyword("to") then
+@.to@>
+ begin print_err("Missing `to' inserted");
+@.Missing `to' inserted@>
+ help2("I'm working on `\vsplit<box number> to <dimen>';")@/
+ ("will look for the <dimen> next."); error;
+ end;
+scan_normal_dimen;
+cur_box:=vsplit(n,cur_val);
+end
+
+@ Here is where we enter restricted horizontal mode or internal vertical
+mode, in order to make a box.
+
+@<Initiate the construction of an hbox or vbox, then |return|@>=
+begin k:=cur_chr-vtop_code; saved(0):=box_context;
+case abs(mode) of
+vmode: spec_direction:=body_direction;
+hmode: spec_direction:=text_direction;
+mmode: spec_direction:=math_direction;
+end;
+if k=hmode then
+ if (box_context<box_flag)and(abs(mode)=vmode) then
+ scan_spec(adjusted_hbox_group,true)
+ else scan_spec(hbox_group,true)
+else begin if k=vmode then scan_spec(vbox_group,true)
+ else begin scan_spec(vtop_group,true); k:=vmode;
+ end;
+ normal_paragraph;
+ end;
+push_nest; mode:=-k;
+if k=vmode then
+ begin prev_depth:=ignore_depth;
+ if every_vbox<>null then begin_token_list(every_vbox,every_vbox_text);
+ end
+else begin space_factor:=1000;
+ if every_hbox<>null then begin_token_list(every_hbox,every_hbox_text);
+ end;
+return;
+end
+
+@ @<Declare act...@>=
+procedure scan_box(@!box_context:integer);
+ {the next input should specify a box or perhaps a rule}
+begin @<Get the next non-blank non-relax...@>;
+if cur_cmd=make_box then begin_box(box_context)
+else if (box_context>=leader_flag)and((cur_cmd=hrule)or(cur_cmd=vrule)) then
+ begin cur_box:=scan_rule_spec; box_end(box_context);
+ end
+else begin@t@>@;@/
+ print_err("A <box> was supposed to be here");@/
+@.A <box> was supposed to...@>
+ help3("I was expecting to see \hbox or \vbox or \copy or \box or")@/
+ ("something like that. So you might find something missing in")@/
+ ("your output. But keep trying; you can fix this later."); back_error;
+ end;
+end;
+
+@ When the right brace occurs at the end of an \.{\\hbox} or \.{\\vbox} or
+\.{\\vtop} construction, the |package| routine comes into action. We might
+also have to finish a paragraph that hasn't ended.
+
+@<Cases of |handle...@>=
+hbox_group: package(0);
+adjusted_hbox_group: begin adjust_tail:=adjust_head;
+ pre_adjust_tail:=pre_adjust_head; package(0);
+ end;
+vbox_group: begin line_break_context:=vbox_group; end_graf; package(0);
+ end;
+vtop_group: begin line_break_context:=vtop_group; end_graf; package(vtop_code);
+ end;
+
+@ @<Declare action...@>=
+procedure package(@!c:small_number);
+var h:scaled; {height of box}
+@!p:pointer; {first node in a box}
+@!d:scaled; {max depth}
+@!grp:integer;
+begin grp:=cur_group;
+d:=box_max_depth; unsave; save_ptr:=save_ptr-6;
+pack_direction:=saved(3);
+if mode=-hmode then cur_box:=filtered_hpack(head,tail,saved(2),saved(1),grp)
+else begin cur_box:=filtered_vpackage(vlink(head),saved(2),saved(1),d,grp);
+ if c=vtop_code then @<Readjust the height and depth of |cur_box|,
+ for \.{\\vtop}@>;
+ end;
+if saved(4)<>null then
+ @<DIR: Adjust back |text_dir_ptr| for |scan_spec|@>;
+replace_attribute_list(cur_box, saved(5));
+pop_nest; box_end(saved(0));
+end;
+
+@ The height of a `\.{\\vtop}' box is inherited from the first item on its list,
+if that item is an |hlist_node|, |vlist_node|, or |rule_node|; otherwise
+the \.{\\vtop} height is zero.
+
+
+@<Readjust the height...@>=
+begin h:=0; p:=list_ptr(cur_box);
+if p<>null then if type(p)<=rule_node then h:=height(p);
+depth(cur_box):=depth(cur_box)-h+height(cur_box); height(cur_box):=h;
+end
+
+@ Here is a really small patch to add a new primitive called
+\.{\\quitvmode}. In vertical modes, it is identical to \.{\\indent},
+but in horizontal and math modes it is really a no-op (as opposed to
+\.{\\indent}, which executes the |indent_in_hmode| procedure).
+
+A paragraph begins when horizontal-mode material occurs in vertical mode,
+or when the paragraph is explicitly started by `\.{\\quitvmode}',
+`\.{\\indent}' or `\.{\\noindent}'.
+
+@<Put each...@>=
+primitive("indent",start_par,1);
+@!@:indent_}{\.{\\indent} primitive@>
+primitive("noindent",start_par,0);
+@!@:no_indent_}{\.{\\noindent} primitive@>
+primitive("quitvmode",start_par,2);
+@!@:quit_vmode_}{\.{\\quitvmode} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+start_par: if chr_code=0 then print_esc("noindent")@+ else if chr_code=1 then print_esc("indent")@+ else print_esc("quitvmode");
+
+@ @<Cases of |main_control| that build...@>=
+vmode+start_par: new_graf(cur_chr>0);
+vmode+letter,vmode+other_char,vmode+char_num,vmode+char_given,
+ vmode+char_ghost,
+ vmode+math_shift,vmode+un_hbox,vmode+vrule,
+ vmode+accent,vmode+discretionary,vmode+hskip,vmode+valign,
+ vmode+ex_space,vmode+no_boundary:@t@>@;@/
+ begin back_input; new_graf(true);
+ end;
+
+@ @<Declare act...@>=
+procedure new_graf(@!indented:boolean);
+var p,q,dir_graf_tmp:pointer;
+begin prev_graf:=0;
+if (mode=vmode)or(head<>tail) then begin
+ tail_append(new_param_glue(par_skip_code));
+ if nest_ptr=0 then
+ check_filter('begin_of_par');
+ end;
+push_nest; mode:=hmode; space_factor:=1000;
+@<LOCAL: Add local paragraph node@>;
+if indented then begin
+ p:=new_null_box; box_dir(p):=par_direction;
+ width(p):=par_indent;@+
+ tail_append(p);
+ end;
+q:=tail;
+dir_rover:=text_dir_ptr;
+while dir_rover<>null do
+ begin
+ if (vlink(dir_rover)<>null) or (dir_dir(dir_rover)<>par_direction) then
+ begin
+ dir_graf_tmp:=new_dir(dir_dir(dir_rover));
+ vlink(dir_graf_tmp):=vlink(q); vlink(q):=dir_graf_tmp;
+ end;
+ dir_rover:=vlink(dir_rover);
+ end;
+q:=head;
+while vlink(q)<>null do q:=vlink(q);
+tail:=q;
+if every_par<>null then begin_token_list(every_par,every_par_text);
+if nest_ptr=1 then begin
+ build_page; {put |par_skip| glue on current page}
+ end;
+end;
+
+@ @<Cases of |main_control| that build...@>=
+hmode+start_par,mmode+start_par: if cur_chr<>2 then indent_in_hmode;
+
+@ @<Declare act...@>=
+procedure indent_in_hmode;
+var p,@!q:pointer;
+begin if cur_chr>0 then {\.{\\indent}}
+ begin p:=new_null_box; width(p):=par_indent;
+ if abs(mode)=hmode then space_factor:=1000
+ else begin q:=new_noad; math_type(nucleus(q)):=sub_box;
+ vinfo(nucleus(q)):=p; p:=q;
+ end;
+ tail_append(p);
+ end;
+end;
+
+@ A paragraph ends when a |par_end| command is sensed, or when we are in
+horizontal mode when reaching the right brace of vertical-mode routines
+like \.{\\vbox}, \.{\\insert}, or \.{\\output}.
+
+@<Cases of |main_control| that build...@>=
+vmode+par_end: begin normal_paragraph;
+ if mode>0 then begin check_filter('vmode_par'); build_page; end;
+ end;
+hmode+par_end: begin if align_state<0 then off_save; {this tries to
+ recover from an alignment that didn't end properly}
+ if (mode>0) and (nest[(nest_ptr-1)].mode_field=vmode) then
+ line_break_context:=bottom_level;
+ end_graf; {this takes us to the enclosing mode, if |mode>0|}
+ if mode=vmode then begin check_filter('hmode_par'); build_page; end;
+ end;
+hmode+stop,hmode+vskip,hmode+hrule,hmode+un_vbox,hmode+halign: head_for_vmode;
+
+@ @<Declare act...@>=
+procedure head_for_vmode;
+begin if mode<0 then
+ if cur_cmd<>hrule then off_save
+ else begin print_err("You can't use `");
+ print_esc("hrule"); print("' here except with leaders");
+@.You can't use \\hrule...@>
+ help2("To put a horizontal rule in an hbox or an alignment,")@/
+ ("you should use \leaders or \hrulefill (see The TeXbook).");
+ error;
+ end
+else begin back_input; cur_tok:=par_token; back_input; token_type:=inserted;
+ end;
+end;
+
+@ TODO (BUG?): |dir_save| would have been set by |line_break| by means
+of |post_line_break|, but this is not done right now, as it introduces
+pretty heavy memory leaks. This means the current code is probably
+wrong in some way that relates to in-paragraph displays.
+
+@<Declare act...@>=
+procedure end_graf;
+begin if mode=hmode then
+ begin if (head=tail) or (vlink(head)=tail) then pop_nest
+ {null paragraphs are ignored, all contain a |local_paragraph| node}
+ else line_break(false);
+ if dir_save<>null then
+ begin flush_node_list(dir_save); dir_save:=null;
+ end;
+ normal_paragraph;
+ error_count:=0;
+ end;
+end;
+
+@ Insertion and adjustment and mark nodes are constructed by the following
+pieces of the program.
+
+@<Cases of |main_control| that build...@>=
+any_mode(insert),hmode+vadjust,mmode+vadjust: begin_insert_or_adjust;
+any_mode(mark): handle_mark;
+
+@ @<Forbidden...@>=
+vmode+vadjust,
+
+@ @<Declare act...@>=
+procedure begin_insert_or_adjust;
+begin if cur_cmd=vadjust then cur_val:=255
+else begin scan_register_num;
+ if cur_val=255 then
+ begin print_err("You can't "); print_esc("insert"); print_int(255);
+@.You can't \\insert255@>
+ help1("I'm changing to \insert0; box 255 is special.");
+ error; cur_val:=0;
+ end;
+ end;
+saved(0) := cur_val;
+if (cur_cmd = vadjust) and scan_keyword("pre") then
+ saved(1) := 1
+else
+ saved(1) := 0;
+save_ptr := save_ptr + 2;
+new_save_level(insert_group); scan_left_brace; normal_paragraph;
+push_nest; mode:=-vmode; prev_depth:=ignore_depth;
+end;
+
+@ @<Cases of |handle...@>=
+insert_group: begin
+ line_break_context:=insert_group;
+ end_graf; q:=split_top_skip; add_glue_ref(q);
+ d:=split_max_depth; f:=floating_penalty; unsave; save_ptr := save_ptr - 2;
+ {now |saved(0)| is the insertion number, or 255 for |vadjust|}
+ p:=vpack(vlink(head),natural); pop_nest;
+ if saved(0)<>255 then
+ begin tail_append(new_node(ins_node,saved(0)));
+ height(tail):=height(p)+depth(p); ins_ptr(tail):=list_ptr(p);
+ split_top_ptr(tail):=q; depth(tail):=d; float_cost(tail):=f;
+ end
+ else begin tail_append(new_node(adjust_node,saved(1))); {the |subtype| is used for |adjust_pre|}
+ adjust_ptr(tail):=list_ptr(p); delete_glue_ref(q);
+ end;
+ list_ptr(p):=null; flush_node(p);
+ if nest_ptr=0 then begin check_filter('insert'); build_page; end;
+ end;
+output_group: @<Resume the page builder...@>;
+
+@ I've renamed the |make_mark| procedure to this, because if the
+current chr code is 1, then the actual command was \.{\\clearmarks},
+which does not generate a mark node but instead destroys the current
+mark tokenlists.
+
+@<Declare act...@>=
+procedure handle_mark;
+var p:pointer; {new node}
+@!c:halfword; {the mark class}
+begin if cur_chr=clear_marks_code then begin
+ scan_mark_num; c:=cur_val;
+ delete_top_mark(c); delete_bot_mark(c); delete_first_mark(c);
+ delete_split_first_mark(c); delete_split_bot_mark(c);
+ end
+else begin
+if cur_chr=0 then c:=0
+else begin scan_mark_num; c:=cur_val;
+ if c > biggest_used_mark then biggest_used_mark := c;
+ end;
+p:=scan_toks(false,true);
+p:=new_node(mark_node,0); {the |subtype| is not used}
+mark_class(p):=c;
+mark_ptr(p):=def_ref; vlink(tail):=p; tail:=p;
+end;
+end;
+
+@ Penalty nodes get into a list via the |break_penalty| command.
+@^penalties@>
+
+@<Cases of |main_control| that build...@>=
+any_mode(break_penalty): append_penalty;
+
+@ @<Declare action...@>=
+procedure append_penalty;
+begin scan_int; tail_append(new_penalty(cur_val));
+if mode=vmode then begin check_filter('penalty'); build_page; end;
+end;
+
+@ The |remove_item| command removes a penalty, kern, or glue node if it
+appears at the tail of the current list, using a brute-force linear scan.
+Like \.{\\lastbox}, this command is not allowed in vertical mode (except
+internal vertical mode), since the current list in vertical mode is sent
+to the page builder. But if we happen to be able to implement it in
+vertical mode, we do.
+
+@<Cases of |main_control| that build...@>=
+any_mode(remove_item): delete_last;
+
+@ When |delete_last| is called, |cur_chr| is the |type| of node that
+will be deleted, if present.
+
+@<Declare action...@>=
+procedure delete_last;
+label exit;
+var @!p,@!q:pointer; {run through the current list}
+begin if (mode=vmode)and(tail=head) then
+ @<Apologize for inability to do the operation now,
+ unless \.{\\unskip} follows non-glue@>
+else begin if not is_char_node(tail) then if type(tail)=cur_chr then
+ begin q:=head;
+ repeat p:=q;
+ if not is_char_node(q) then if type(q)=disc_node then
+ begin
+ if p=tail then return;
+ end;
+ q:=vlink(p);
+ until q=tail;
+ vlink(p):=null; flush_node_list(tail); tail:=p;
+ end;
+ end;
+exit:end;
+
+@ @<Apologize for inability to do the operation...@>=
+begin if (cur_chr<>glue_node)or(last_glue<>max_halfword) then
+ begin you_cant;
+ help2("Sorry...I usually can't take things from the current page.")@/
+ ("Try `I\vskip-\lastskip' instead.");
+ if cur_chr=kern_node then help_line[0]:=
+ ("Try `I\kern-\lastkern' instead.")
+ else if cur_chr<>glue_node then help_line[0]:=@|
+ ("Perhaps you can make the output routine do it.");
+ error;
+ end;
+end
+
+@ @<Put each...@>=
+primitive("unpenalty",remove_item,penalty_node);@/
+@!@:un_penalty_}{\.{\\unpenalty} primitive@>
+primitive("unkern",remove_item,kern_node);@/
+@!@:un_kern_}{\.{\\unkern} primitive@>
+primitive("unskip",remove_item,glue_node);@/
+@!@:un_skip_}{\.{\\unskip} primitive@>
+primitive("unhbox",un_hbox,box_code);@/
+@!@:un_hbox_}{\.{\\unhbox} primitive@>
+primitive("unhcopy",un_hbox,copy_code);@/
+@!@:un_hcopy_}{\.{\\unhcopy} primitive@>
+primitive("unvbox",un_vbox,box_code);@/
+@!@:un_vbox_}{\.{\\unvbox} primitive@>
+primitive("unvcopy",un_vbox,copy_code);@/
+@!@:un_vcopy_}{\.{\\unvcopy} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+remove_item: if chr_code=glue_node then print_esc("unskip")
+ else if chr_code=kern_node then print_esc("unkern")
+ else print_esc("unpenalty");
+un_hbox: if chr_code=copy_code then print_esc("unhcopy")
+ else print_esc("unhbox");
+un_vbox: if chr_code=copy_code then print_esc("unvcopy")
+ @<Cases of |un_vbox| for |print_cmd_chr|@>@/
+ else print_esc("unvbox");
+
+@ The |un_hbox| and |un_vbox| commands unwrap one of the |number_regs| current boxes.
+
+@<Cases of |main_control| that build...@>=
+vmode+un_vbox,hmode+un_hbox,mmode+un_hbox: unpackage;
+
+@ @<Declare act...@>=
+procedure unpackage;
+label done, exit;
+var p:pointer; {the box}
+ r: pointer; {to remove marginal kern nodes}
+@!c:box_code..copy_code; {should we copy?}
+@!s:pointer; {for varmem assignment }
+begin if cur_chr>copy_code then @<Handle saved items and |goto done|@>;
+c:=cur_chr; scan_register_num; p:=box(cur_val);
+if p=null then return;
+if (abs(mode)=mmode)or((abs(mode)=vmode)and(type(p)<>vlist_node))or@|
+ ((abs(mode)=hmode)and(type(p)<>hlist_node)) then
+ begin print_err("Incompatible list can't be unboxed");
+@.Incompatible list...@>
+ help3("Sorry, Pandora. (You sneaky devil.)")@/
+ ("I refuse to unbox an \hbox in vertical mode or vice versa.")@/
+ ("And I can't open any boxes in math mode.");@/
+ error; return;
+ end;
+if c=copy_code then begin s:=copy_node_list(list_ptr(p)); vlink(tail):=s; end
+else begin vlink(tail):=list_ptr(p); box(cur_val):=null;
+ list_ptr(p):=null; flush_node(p);
+ end;
+done:
+while vlink(tail) <> null do begin
+ r := vlink(tail);
+ if not is_char_node(r) and (type(r) = margin_kern_node) then begin
+ vlink(tail) := vlink(r);
+ flush_node(r);
+ end;
+ tail:=vlink(tail);
+end;
+exit:end;
+
+@ @<Forbidden...@>=vmode+ital_corr,
+
+@ Italic corrections are converted to kern nodes when the |ital_corr| command
+follows a character. In math mode the same effect is achieved by appending
+a kern of zero here, since italic corrections are supplied later.
+
+@<Cases of |main_control| that build...@>=
+hmode+ital_corr: append_italic_correction;
+mmode+ital_corr: tail_append(new_kern(0));
+
+@ @<Declare act...@>=
+procedure append_italic_correction;
+label exit;
+var p:pointer; {|char_node| at the tail of the current list}
+@!f:internal_font_number; {the font in the |char_node|}
+begin if tail<>head then
+ begin if is_char_node(tail) then p:=tail
+ else return;
+ f:=font(p);
+ tail_append(new_kern(char_italic(f,character(p))));
+ subtype(tail):=explicit;
+ end;
+exit:end;
+
+@ Discretionary nodes are easy in the common case `\.{\\-}', but in the
+general case we must process three braces full of items.
+
+There are four subtypes of discretionaries, but only the first two are
+generated by primitive commands.
+
+@d discretionary_disc=0
+@d explicit_disc=1
+
+@<Put each...@>=
+primitive("-",discretionary,explicit_disc);
+@!@:Single-character primitives -}{\quad\.{\\-}@>
+primitive("discretionary",discretionary,discretionary_disc);
+@!@:discretionary_}{\.{\\discretionary} primitive@>
+primitive("localleftbox",assign_local_box,0);
+@!@:assign_local_box}{\.{\\localleftbox} primitive@>
+primitive("localrightbox",assign_local_box,1);
+@!@:assign_local_box}{\.{\\localrightbox} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+discretionary: if chr_code=explicit_disc then
+ print_esc("-")@+else print_esc("discretionary");
+assign_local_box: if chr_code=0 then print_esc("localleftbox")
+ else print_esc("localrightbox");
+
+@ @<Cases of |main_control| that build...@>=
+hmode+discretionary,mmode+discretionary: append_discretionary;
+any_mode(assign_local_box): append_local_box(cur_chr);
+
+@ The space factor does not change when we append a discretionary node,
+but it starts out as 1000 in the subsidiary lists.
+
+@<Declare act...@>=
+procedure append_local_box(kind:integer);
+begin
+incr(save_ptr); saved(-1):=kind; new_save_level(local_box_group);
+scan_left_brace; push_nest; mode:=-hmode; space_factor:=1000;
+end;
+
+procedure append_discretionary;
+var c:integer;
+begin tail_append(new_disc);
+subtype(tail):=cur_chr;
+if cur_chr=explicit_disc then begin
+ c:=get_pre_hyphen_char(cur_lang);
+ if c<>0 then begin
+ vlink(pre_break(tail)):=new_char(cur_font,c);
+ alink(vlink(pre_break(tail))):=pre_break(tail);
+ tlink(pre_break(tail)):=vlink(pre_break(tail));
+ end;
+ c:=get_post_hyphen_char(cur_lang);
+ if c<>0 then begin
+ vlink(post_break(tail)):=new_char(cur_font,c);
+ alink(vlink(post_break(tail))):=post_break(tail);
+ tlink(post_break(tail)):=vlink(post_break(tail));
+ end;
+ end
+else begin incr(save_ptr); saved(-1):=0; new_save_level(disc_group);
+ scan_left_brace; push_nest; mode:=-hmode; space_factor:=1000;
+ end;
+end;
+
+@ The three discretionary lists are constructed somewhat as if they were
+hboxes. A~subroutine called |build_discretionary| handles the transitions.
+(This is sort of fun.)
+
+@<Cases of |handle...@>=
+disc_group: build_discretionary;
+local_box_group: build_local_box;
+
+@ @<Declare act...@>=
+procedure build_local_box;
+var p:pointer;
+ kind:integer;
+begin
+unsave;
+kind:=saved(-1);
+decr(save_ptr);
+p:=vlink(head); pop_nest;
+p:=hpack(p,natural);
+if kind=0 then
+ eq_define(local_left_box_base,box_ref,p)
+else
+ eq_define(local_right_box_base,box_ref,p);
+if abs(mode)=hmode then
+ @<LOCAL: Add local paragraph node@>;
+eq_word_define(int_base+no_local_whatsits_code,no_local_whatsits+1);
+end;
+
+procedure build_discretionary;
+label done,exit;
+var p,@!q:pointer; {for link manipulation}
+@!n:integer; {length of discretionary list}
+begin unsave;
+@<Prune the current list, if necessary, until it contains only
+ |char_node|, |kern_node|, |hlist_node|, |vlist_node| and
+ |rule_node| items; set |n| to the length of the list,
+ and set |q| to the list's tail@>;
+p:=vlink(head); pop_nest;
+case saved(-1) of
+0: if (n>0) then begin
+ vlink(pre_break(tail)):=p;
+ alink(p):=pre_break(tail);
+ tlink(pre_break(tail)):=q;
+ end;
+1: if (n>0) then begin
+ vlink(post_break(tail)):=p;
+ alink(p):=post_break(tail);
+ tlink(post_break(tail)):=q;
+ end;
+2:@<Attach list |p| to the current list, and record its length;
+ then finish up and |return|@>;
+end; {there are no other cases}
+incr(saved(-1)); new_save_level(disc_group); scan_left_brace;
+push_nest; mode:=-hmode; space_factor:=1000;
+exit:end;
+
+@ @<Attach list |p| to the current...@>=
+begin if (n>0)and(abs(mode)=mmode) then
+ begin print_err("Illegal math "); print_esc("discretionary");
+@.Illegal math \\disc...@>
+ help2("Sorry: The third part of a discretionary break must be")@/
+ ("empty, in math formulas. I had to delete your third part.");
+ flush_node_list(p); error;
+ end
+else begin
+ if (n>0) then begin
+ vlink(no_break(tail)):=p;
+ alink(p):=no_break(tail);
+ tlink(no_break(tail)):=q;
+ end;
+ end;
+decr(save_ptr); return;
+end
+
+@ During this loop, |p=vlink(q)| and there are |n| items preceding |p|.
+
+@<Prune the current list, if necessary...@>=
+q:=head; p:=vlink(q); n:=0;
+while p<>null do
+ begin if not is_char_node(p) then if type(p)<>disc_node then
+ if type(p)>rule_node then if type(p)<>kern_node then
+ begin print_err("Improper discretionary list");
+@.Improper discretionary list@>
+ help1("Discretionary lists must contain only boxes and kerns.");@/
+ error;
+ begin_diagnostic;
+ print_nl("The following discretionary sublist has been deleted:");
+@.The following...deleted@>
+ show_box(p);
+ end_diagnostic(true);
+ flush_node_list(p); vlink(q):=null; goto done;
+ end;
+ q:=p; p:=vlink(q); incr(n);
+ end;
+done:
+
+@ We need only one more thing to complete the horizontal mode routines, namely
+the \.{\\accent} primitive.
+
+@<Cases of |main_control| that build...@>=
+hmode+accent: make_accent;
+
+@ The positioning of accents is straightforward but tedious. Given an accent
+of width |a|, designed for characters of height |x| and slant |s|;
+and given a character of width |w|, height |h|, and slant |t|: We will shift
+the accent down by |x-h|, and we will insert kern nodes that have the effect of
+centering the accent over the character and shifting the accent to the
+right by $\delta={1\over2}(w-a)+h\cdot t-x\cdot s$. If either character is
+absent from the font, we will simply use the other, without shifting.
+
+@<Declare act...@>=
+procedure make_accent;
+var s,@!t: real; {amount of slant}
+@!p,@!q,@!r:pointer; {character, box, and kern nodes}
+@!f:internal_font_number; {relevant font}
+@!a,@!h,@!x,@!w,@!delta:scaled; {heights and widths, as explained above}
+begin scan_char_num; f:=cur_font; p:=new_glyph(f,cur_val);
+if p<>null then
+ begin x:=x_height(f); s:=slant(f)/float_constant(65536);
+@^real division@>
+ a:=glyph_width(p);@/
+ do_assignments;@/
+ @<Create a character node |q| for the next character,
+ but set |q:=null| if problems arise@>;
+ if q<>null then @<Append the accent with appropriate kerns,
+ then set |p:=q|@>;
+ vlink(tail):=p; tail:=p; space_factor:=1000;
+ end;
+end;
+
+@ @<Create a character node |q| for the next...@>=
+q:=null; f:=cur_font;
+if (cur_cmd=letter)or(cur_cmd=other_char)or(cur_cmd=char_given) then
+ q:=new_glyph(f,cur_chr)
+else if cur_cmd=char_num then
+ begin scan_char_num; q:=new_glyph(f,cur_val);
+ end
+else back_input
+
+@ The kern nodes appended here must be distinguished from other kerns, lest
+they be wiped away by the hyphenation algorithm or by a previous line break.
+
+The two kerns are computed with (machine-dependent) |real| arithmetic, but
+their sum is machine-independent; the net effect is machine-independent,
+because the user cannot remove these nodes nor access them via \.{\\lastkern}.
+
+@<Append the accent with appropriate kerns...@>=
+begin t:=slant(f)/float_constant(65536);
+@^real division@>
+w:=glyph_width(q);
+h:=glyph_height(q);
+if h<>x then {the accent must be shifted up or down}
+ begin p:=hpack(p,natural); shift_amount(p):=x-h;
+ end;
+delta:=round((w-a)/float_constant(2)+h*t-x*s);
+@^real multiplication@>
+@^real addition@>
+r:=new_kern(delta); subtype(r):=acc_kern; vlink(tail):=r; vlink(r):=p;
+tail:=new_kern(-a-delta); subtype(tail):=acc_kern; vlink(p):=tail; p:=q;
+end
+
+@ When `\.{\\cr}' or `\.{\\span}' or a tab mark comes through the scanner
+into |main_control|, it might be that the user has foolishly inserted
+one of them into something that has nothing to do with alignment. But it is
+far more likely that a left brace or right brace has been omitted, since
+|get_next| takes actions appropriate to alignment only when `\.{\\cr}'
+or `\.{\\span}' or tab marks occur with |align_state=0|. The following
+program attempts to make an appropriate recovery.
+
+@<Cases of |main_control| that build...@>=
+any_mode(car_ret), any_mode(tab_mark): align_error;
+any_mode(no_align): no_align_error;
+any_mode(omit): omit_error;
+
+@ @<Declare act...@>=
+procedure align_error;
+begin if abs(align_state)>2 then
+ @<Express consternation over the fact that no alignment is in progress@>
+else begin back_input;
+ if align_state<0 then
+ begin print_err("Missing { inserted");
+@.Missing \{ inserted@>
+ incr(align_state); cur_tok:=left_brace_token+"{";
+ end
+ else begin print_err("Missing } inserted");
+@.Missing \} inserted@>
+ decr(align_state); cur_tok:=right_brace_token+"}";
+ end;
+ help3("I've put in what seems to be necessary to fix")@/
+ ("the current column of the current alignment.")@/
+ ("Try to go on, since this might almost work."); ins_error;
+ end;
+end;
+
+@ @<Express consternation...@>=
+begin print_err("Misplaced "); print_cmd_chr(cur_cmd,cur_chr);
+@.Misplaced \&@>
+@.Misplaced \\span@>
+@.Misplaced \\cr@>
+if cur_tok=tab_token+"&" then
+ begin help6("I can't figure out why you would want to use a tab mark")@/
+ ("here. If you just want an ampersand, the remedy is")@/
+ ("simple: Just type `I\&' now. But if some right brace")@/
+ ("up above has ended a previous alignment prematurely,")@/
+ ("you're probably due for more error messages, and you")@/
+ ("might try typing `S' now just to see what is salvageable.");
+ end
+else begin help5("I can't figure out why you would want to use a tab mark")@/
+ ("or \cr or \span just now. If something like a right brace")@/
+ ("up above has ended a previous alignment prematurely,")@/
+ ("you're probably due for more error messages, and you")@/
+ ("might try typing `S' now just to see what is salvageable.");
+ end;
+error;
+end
+
+@ The help messages here contain a little white lie, since \.{\\noalign}
+and \.{\\omit} are allowed also after `\.{\\noalign\{...\}}'.
+
+@<Declare act...@>=
+procedure no_align_error;
+begin print_err("Misplaced "); print_esc("noalign");
+@.Misplaced \\noalign@>
+help2("I expect to see \noalign only after the \cr of")@/
+ ("an alignment. Proceed, and I'll ignore this case."); error;
+end;
+procedure omit_error;
+begin print_err("Misplaced "); print_esc("omit");
+@.Misplaced \\omit@>
+help2("I expect to see \omit only after tab marks or the \cr of")@/
+ ("an alignment. Proceed, and I'll ignore this case."); error;
+end;
+
+@ We've now covered most of the abuses of \.{\\halign} and \.{\\valign}.
+Let's take a look at what happens when they are used correctly.
+
+@<Cases of |main_control| that build...@>=
+vmode+halign,hmode+valign:init_align;
+mmode+halign: if privileged then
+ if cur_group=math_shift_group then init_align
+ else off_save;
+vmode+endv,hmode+endv: do_endv;
+
+@ An |align_group| code is supposed to remain on the |save_stack|
+during an entire alignment, until |fin_align| removes it.
+
+A devious user might force an |endv| command to occur just about anywhere;
+we must defeat such hacks.
+
+@<Declare act...@>=
+procedure do_endv;
+begin base_ptr:=input_ptr; input_stack[base_ptr]:=cur_input;
+while (input_stack[base_ptr].index_field<>v_template) and
+ (input_stack[base_ptr].loc_field=null) and
+ (input_stack[base_ptr].state_field=token_list) do decr(base_ptr);
+if (input_stack[base_ptr].index_field<>v_template) or
+ (input_stack[base_ptr].loc_field<>null) or
+ (input_stack[base_ptr].state_field<>token_list) then
+ fatal_error("(interwoven alignment preambles are not allowed)");
+@.interwoven alignment preambles...@>
+ if cur_group=align_group then
+ begin line_break_context:=align_group; end_graf;
+ if fin_col then fin_row;
+ end
+else off_save;
+end;
+
+@ @<Cases of |handle_right_brace|...@>=
+align_group: begin back_input; cur_tok:=cs_token_flag+frozen_cr;
+ print_err("Missing "); print_esc("cr"); print(" inserted");
+@.Missing \\cr inserted@>
+ help1("I'm guessing that you meant to end an alignment here.");
+ ins_error;
+ end;
+
+@ @<Cases of |handle_right_brace|...@>=
+no_align_group: begin line_break_context:=no_align_group; end_graf; unsave; align_peek;
+ end;
+
+@ Finally, \.{\\endcsname} is not supposed to get through to |main_control|.
+
+@<Cases of |main_control| that build...@>=
+any_mode(end_cs_name): cs_error;
+
+@ @<Declare act...@>=
+procedure cs_error;
+begin print_err("Extra "); print_esc("endcsname");
+@.Extra \\endcsname@>
+help1("I'm ignoring this, since I wasn't doing a \csname.");
+error;
+end;
+
+@* \[48] Building math lists.
+The routines that \TeX\ uses to create mlists are similar to those we have
+just seen for the generation of hlists and vlists. But it is necessary to
+make ``noads'' as well as nodes, so the reader should review the
+discussion of math mode data structures before trying to make sense out of
+the following program.
+
+Here is a little routine that needs to be done whenever a subformula
+is about to be processed. The parameter is a code like |math_group|.
+
+@<Declare act...@>=
+procedure push_math(@!c:group_code);
+begin
+if math_direction<>text_direction then dir_math_save:=true;
+push_nest; mode:=-mmode; incompleat_noad:=null;
+@<DIR: |new_save_level| math@>;
+end;
+
+@ We get into math mode from horizontal mode when a `\.\$' (i.e., a
+|math_shift| character) is scanned. We must check to see whether this
+`\.\$' is immediately followed by another, in case display math mode is
+called for.
+
+@<Cases of |main_control| that build...@>=
+hmode+math_shift:init_math;
+
+@ @<Declare act...@>=
+procedure init_math;
+label found,not_found,done;
+var w:scaled; {new or partial |pre_display_size|}
+@!l:scaled; {new |display_width|}
+@!s:scaled; {new |display_indent|}
+@!p:pointer; {current node when calculating |pre_display_size|}
+@!q:pointer; {glue specification when calculating |pre_display_size|}
+@!f:internal_font_number; {font in current |char_node|}
+@!n:integer; {scope of paragraph shape specification}
+@!v:scaled; {|w| plus possible glue amount}
+@!d:scaled; {increment to |v|}
+begin get_token; {|get_x_token| would fail on \.{\\ifmmode}\thinspace!}
+if (cur_cmd=math_shift)and(mode>0) then @<Go into display math mode@>
+else begin back_input; @<Go into ordinary math mode@>;
+ end;
+end;
+
+@ @<Go into ordinary math mode@>=
+begin push_math(math_shift_group); eq_word_define(int_base+cur_fam_code,-1);
+if every_math<>null then begin_token_list(every_math,every_math_text);
+end
+
+@ We get into ordinary math mode from display math mode when `\.{\\eqno}' or
+`\.{\\leqno}' appears. In such cases |cur_chr| will be 0 or~1, respectively;
+the value of |cur_chr| is placed onto |save_stack| for safe keeping.
+
+@<Cases of |main_control| that build...@>=
+mmode+eq_no: if privileged then
+ if cur_group=math_shift_group then start_eq_no
+ else off_save;
+
+@ @<Put each...@>=
+primitive("eqno",eq_no,0);
+@!@:eq_no_}{\.{\\eqno} primitive@>
+primitive("leqno",eq_no,1);
+@!@:leq_no_}{\.{\\leqno} primitive@>
+
+@ When \TeX\ is in display math mode, |cur_group=math_shift_group|,
+so it is not necessary for the |start_eq_no| procedure to test for
+this condition.
+
+@<Declare act...@>=
+procedure start_eq_no;
+begin saved(0):=cur_chr; incr(save_ptr);
+@<Go into ordinary math mode@>;
+end;
+
+@ @<Cases of |print_cmd_chr|...@>=
+eq_no:if chr_code=1 then print_esc("leqno")@+else print_esc("eqno");
+
+@ @<Forbidden...@>=non_math(eq_no),
+
+@ When we enter display math mode, we need to call |line_break| to
+process the partial paragraph that has just been interrupted by the
+display. Then we can set the proper values of |display_width| and
+|display_indent| and |pre_display_size|.
+
+@<Go into display math mode@>=
+begin if head=tail then {`\.{\\noindent\$\$}' or `\.{\$\${ }\$\$}'}
+ begin pop_nest; w:=-max_dimen;
+ end
+else begin
+ line_break(true);@/
+ @<Calculate the natural width, |w|, by which the characters of the
+ final line extend to the right of the reference point,
+ plus two ems; or set |w:=max_dimen| if the non-blank information
+ on that line is affected by stretching or shrinking@>;
+ end;
+{now we are in vertical mode, working on the list that will contain the display}
+@<Calculate the length, |l|, and the shift amount, |s|, of the display lines@>;
+push_math(math_shift_group); mode:=mmode;
+eq_word_define(int_base+cur_fam_code,-1);@/
+eq_word_define(dimen_base+pre_display_size_code,w);
+eq_word_define(dimen_base+display_width_code,l);
+eq_word_define(dimen_base+display_indent_code,s);
+if every_display<>null then begin_token_list(every_display,every_display_text);
+if nest_ptr=1 then begin check_contrib_filter('before_display'); build_page; end;
+end
+
+@ @<Calculate the natural width, |w|, by which...@>=
+v:=shift_amount(just_box)+2*quad(cur_font); w:=-max_dimen;
+p:=list_ptr(just_box);
+while p<>null do
+ begin @<Let |d| be the natural width of node |p|;
+ if the node is ``visible,'' |goto found|;
+ if the node is glue that stretches or shrinks, set |v:=max_dimen|@>;
+ if v<max_dimen then v:=v+d;
+ goto not_found;
+ found: if v<max_dimen then
+ begin v:=v+d; w:=v;
+ end
+ else begin w:=max_dimen; goto done;
+ end;
+ not_found: p:=vlink(p);
+ end;
+done:
+
+@ @<Let |d| be the natural width of node |p|...@>=
+if is_char_node(p) then
+ begin f:=font(p); d:=glyph_width(p);
+ goto found;
+ end;
+case type(p) of
+hlist_node,vlist_node,rule_node: begin d:=width(p); goto found;
+ end;
+margin_kern_node: d:=width(p);
+kern_node: d:=width(p);
+math_node: d:=surround(p);
+glue_node:@<Let |d| be the natural width of this glue; if stretching
+ or shrinking, set |v:=max_dimen|; |goto found| in the case of leaders@>;
+whatsit_node: @<Let |d| be the width of the whatsit |p|@>;
+othercases d:=0
+endcases
+
+@ We need to be careful that |w|, |v|, and |d| do not depend on any |glue_set|
+values, since such values are subject to system-dependent rounding.
+System-dependent numbers are not allowed to infiltrate parameters like
+|pre_display_size|, since \TeX82 is supposed to make the same decisions on all
+machines.
+
+@<Let |d| be the natural width of this glue...@>=
+begin q:=glue_ptr(p); d:=width(q);
+if glue_sign(just_box)=stretching then
+ begin if (glue_order(just_box)=stretch_order(q))and@|
+ (stretch(q)<>0) then
+ v:=max_dimen;
+ end
+else if glue_sign(just_box)=shrinking then
+ begin if (glue_order(just_box)=shrink_order(q))and@|
+ (shrink(q)<>0) then
+ v:=max_dimen;
+ end;
+if subtype(p)>=a_leaders then goto found;
+end
+
+@ A displayed equation is considered to be three lines long, so we
+calculate the length and offset of line number |prev_graf+2|.
+
+@<Calculate the length, |l|, ...@>=
+if par_shape_ptr=null then
+ if (hang_indent<>0)and@|
+ (((hang_after>=0)and(prev_graf+2>hang_after))or@|
+ (prev_graf+1<-hang_after)) then
+ begin l:=hsize-abs(hang_indent);
+ if hang_indent>0 then s:=hang_indent@+else s:=0;
+ end
+ else begin l:=hsize; s:=0;
+ end
+else begin n:=vinfo(par_shape_ptr);
+ if prev_graf+2>=n then p:=par_shape_ptr+2*n
+ else p:=par_shape_ptr+2*(prev_graf+2);
+ s:=vmem(p-1).sc; l:=vmem(p).sc;
+ end
+
+@ Subformulas of math formulas cause a new level of math mode to be entered,
+on the semantic nest as well as the save stack. These subformulas arise in
+several ways: (1)~A left brace by itself indicates the beginning of a
+subformula that will be put into a box, thereby freezing its glue and
+preventing line breaks. (2)~A subscript or superscript is treated as a
+subformula if it is not a single character; the same applies to
+the nucleus of things like \.{\\underline}. (3)~The \.{\\left} primitive
+initiates a subformula that will be terminated by a matching \.{\\right}.
+The group codes placed on |save_stack| in these three cases are
+|math_group|, |math_group|, and |math_left_group|, respectively.
+
+Here is the code that handles case (1); the other cases are not quite as
+trivial, so we shall consider them later.
+
+@<Cases of |main_control| that build...@>=
+mmode+left_brace: begin tail_append(new_noad);
+ back_input; scan_math(nucleus(tail));
+ end;
+
+@ Recall that the |nucleus|, |subscr|, and |supscr| fields in a noad are
+broken down into subfields called |math_type| and either |info| or
+|(fam,character)|. The job of |scan_math| is to figure out what to place
+in one of these principal fields; it looks at the subformula that
+comes next in the input, and places an encoding of that subformula
+into a given word of |mem|.
+
+@d fam_in_range==((cur_fam>=0)and(cur_fam<256))
+
+@<Declare act...@>=
+@t\4@>@<Declare the function called |fin_mlist|@>@t@>@;@/
+
+procedure scan_math(@!p:pointer);
+label restart,reswitch,exit;
+var c:integer; {math character code}
+begin restart:@<Get the next non-blank non-relax...@>;
+reswitch:case cur_cmd of
+letter,other_char,char_given: begin c:=get_math_code(cur_chr);
+ if c=@"8000000 then
+ begin @<Treat |cur_chr| as an active character@>;
+ goto restart;
+ end;
+ end;
+char_num: begin scan_char_num; cur_chr:=cur_val; cur_cmd:=char_given;
+ goto reswitch;
+ end;
+math_char_num: begin
+ if cur_chr=0 then scan_fifteen_bit_int
+ else scan_big_fifteen_bit_int;
+ c:=cur_val;
+ end;
+math_given: begin
+ c := ((cur_chr div @"1000) * @"1000000) +
+ (((cur_chr mod @"1000) div @"100) * @"10000) +
+ (cur_chr mod @"100);
+ end;
+omath_given: begin c:=cur_chr;
+ end;
+delim_num: begin
+ if cur_chr=0 then scan_twenty_seven_bit_int
+ else scan_fifty_one_bit_int;
+ c:=cur_val;
+ end;
+othercases @<Scan a subformula enclosed in braces and |return|@>
+endcases;@/
+math_type(p):=math_char; mcharacter(p):=qi(c mod @"10000);
+if (c>=var_code)and fam_in_range then fam(p):=cur_fam
+else fam(p):=(c div @"10000) mod @"100;
+exit:end;
+
+@ An active character that is an |outer_call| is allowed here.
+
+@<Treat |cur_chr|...@>=
+begin cur_cs:=(cur_chr mod number_active_chars)+active_base;
+cur_cmd:=eq_type(cur_cs); cur_chr:=equiv(cur_cs);
+x_token; back_input;
+end
+
+@ The pointer |p| is placed on |save_stack| while a complex subformula
+is being scanned.
+
+@<Scan a subformula...@>=
+begin back_input; scan_left_brace;@/
+saved(0):=p; incr(save_ptr); push_math(math_group); return;
+end
+
+@ The simplest math formula is, of course, `\.{\${ }\$}', when no noads are
+generated. The next simplest cases involve a single character, e.g.,
+`\.{\$x\$}'. Even though such cases may not seem to be very interesting,
+the reader can perhaps understand how happy the author was when `\.{\$x\$}'
+was first properly typeset by \TeX. The code in this section was used.
+@^Knuth, Donald Ervin@>
+
+@<Cases of |main_control| that build...@>=
+mmode+letter,mmode+other_char,mmode+char_given:
+ set_math_char(get_math_code(cur_chr));
+mmode+char_num: begin scan_char_num; cur_chr:=cur_val;
+ set_math_char(get_math_code(cur_chr));
+ end;
+mmode+math_char_num: begin
+ if cur_chr=0 then scan_fifteen_bit_int
+ else scan_big_fifteen_bit_int;
+ set_math_char(cur_val);
+ end;
+mmode+math_given: begin
+ set_math_char(((cur_chr div @"1000) * @"1000000) +
+ (((cur_chr mod @"1000) div @"100) * @"10000) +
+ (cur_chr mod @"100));
+ end;
+mmode+omath_given: set_math_char(cur_chr);
+mmode+delim_num: begin
+ if cur_chr=0 then scan_twenty_seven_bit_int
+ else scan_fifty_one_bit_int;
+ set_math_char(cur_val);
+ end;
+
+@ The |set_math_char| procedure creates a new noad appropriate to a given
+math code, and appends it to the current mlist. However, if the math code
+is sufficiently large, the |cur_chr| is treated as an active character and
+nothing is appended.
+
+@<Declare act...@>=
+procedure set_math_char(@!c:integer);
+var p:pointer; {the new noad}
+begin if c>=@"8000000 then
+ @<Treat |cur_chr|...@>
+else begin p:=new_noad; math_type(nucleus(p)):=math_char;
+ mcharacter(nucleus(p)):=qi(c mod @"10000);
+ fam(nucleus(p)):=(c div @"10000) mod @"100;
+ if c>=var_code then
+ begin if fam_in_range then fam(nucleus(p)):=cur_fam;
+ type(p):=ord_noad;
+ end
+ else
+ type(p):=ord_noad+(c div @"1000000);
+ vlink(tail):=p; tail:=p;
+ end;
+end;
+
+@ Primitive math operators like \.{\\mathop} and \.{\\underline} are given
+the command code |math_comp|, supplemented by the noad type that they
+generate.
+
+@<Put each...@>=
+primitive("mathord",math_comp,ord_noad);
+@!@:math_ord_}{\.{\\mathord} primitive@>
+primitive("mathop",math_comp,op_noad);
+@!@:math_op_}{\.{\\mathop} primitive@>
+primitive("mathbin",math_comp,bin_noad);
+@!@:math_bin_}{\.{\\mathbin} primitive@>
+primitive("mathrel",math_comp,rel_noad);
+@!@:math_rel_}{\.{\\mathrel} primitive@>
+primitive("mathopen",math_comp,open_noad);
+@!@:math_open_}{\.{\\mathopen} primitive@>
+primitive("mathclose",math_comp,close_noad);
+@!@:math_close_}{\.{\\mathclose} primitive@>
+primitive("mathpunct",math_comp,punct_noad);
+@!@:math_punct_}{\.{\\mathpunct} primitive@>
+primitive("mathinner",math_comp,inner_noad);
+@!@:math_inner_}{\.{\\mathinner} primitive@>
+primitive("underline",math_comp,under_noad);
+@!@:underline_}{\.{\\underline} primitive@>
+primitive("overline",math_comp,over_noad);@/
+@!@:overline_}{\.{\\overline} primitive@>
+primitive("displaylimits",limit_switch,normal);
+@!@:display_limits_}{\.{\\displaylimits} primitive@>
+primitive("limits",limit_switch,limits);
+@!@:limits_}{\.{\\limits} primitive@>
+primitive("nolimits",limit_switch,no_limits);
+@!@:no_limits_}{\.{\\nolimits} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+math_comp: case chr_code of
+ ord_noad: print_esc("mathord");
+ op_noad: print_esc("mathop");
+ bin_noad: print_esc("mathbin");
+ rel_noad: print_esc("mathrel");
+ open_noad: print_esc("mathopen");
+ close_noad: print_esc("mathclose");
+ punct_noad: print_esc("mathpunct");
+ inner_noad: print_esc("mathinner");
+ under_noad: print_esc("underline");
+ othercases print_esc("overline")
+ endcases;
+limit_switch: if chr_code=limits then print_esc("limits")
+ else if chr_code=no_limits then print_esc("nolimits")
+ else print_esc("displaylimits");
+
+@ @<Cases of |main_control| that build...@>=
+mmode+math_comp: begin tail_append(new_noad);
+ type(tail):=cur_chr; scan_math(nucleus(tail));
+ end;
+mmode+limit_switch: math_limit_switch;
+
+@ @<Declare act...@>=
+procedure math_limit_switch;
+label exit;
+begin if head<>tail then if type(tail)=op_noad then
+ begin subtype(tail):=cur_chr; return;
+ end;
+print_err("Limit controls must follow a math operator");
+@.Limit controls must follow...@>
+help1("I'm ignoring this misplaced \limits or \nolimits command."); error;
+exit:end;
+
+@ Delimiter fields of noads are filled in by the |scan_delimiter| routine.
+The first parameter of this procedure is the |mem| address where the
+delimiter is to be placed; the second tells if this delimiter follows
+\.{\\radical} or not.
+
+@<Declare act...@>=
+procedure scan_delimiter(@!p:pointer;@!r:integer);
+begin if r=1 then scan_twenty_seven_bit_int
+else if r=2 then scan_fifty_one_bit_int
+else begin @<Get the next non-blank non-relax...@>;
+ case cur_cmd of
+ letter,other_char: begin
+ cur_val:=get_del_code_a(cur_chr); cur_val1:=get_del_code_b(cur_chr);
+ end;
+ delim_num: if cur_chr=0 then scan_twenty_seven_bit_int
+ else scan_fifty_one_bit_int;
+ othercases begin cur_val:=-1; cur_val1:=-1; end;
+ endcases;
+ end;
+if cur_val<0 then begin @<Report that an invalid delimiter code is being changed
+ to null; set~|cur_val:=0|@>;
+ cur_val1:=0;
+ end;
+small_fam(p):=(cur_val div @"10000) mod @"100;
+small_char(p):=qi(cur_val mod @"10000);
+large_fam(p):=(cur_val1 div @"10000) mod @"100;
+large_char(p):=qi(cur_val1 mod @"10000);
+end;
+
+@ @<Report that an invalid delimiter...@>=
+begin print_err("Missing delimiter (. inserted)");
+@.Missing delimiter...@>
+help6("I was expecting to see something like `(' or `\{' or")@/
+ ("`\}' here. If you typed, e.g., `{' instead of `\{', you")@/
+ ("should probably delete the `{' by typing `1' now, so that")@/
+ ("braces don't get unbalanced. Otherwise just proceed.")@/
+ ("Acceptable delimiters are characters whose \delcode is")@/
+ ("nonnegative, or you can use `\delimiter <delimiter code>'.");
+back_error; cur_val:=0;
+end
+
+@ @<Cases of |main_control| that build...@>=
+mmode+radical:math_radical;
+
+@ @<Declare act...@>=
+procedure math_radical;
+begin tail_append(new_node(radical_noad,normal));
+vmem(nucleus(tail)).hh:=empty_field;
+vmem(subscr(tail)).hh:=empty_field;
+vmem(supscr(tail)).hh:=empty_field;
+scan_delimiter(left_delimiter(tail),cur_chr+1);
+scan_math(nucleus(tail));
+end;
+
+@ @<Cases of |main_control| that build...@>=
+mmode+accent,mmode+math_accent:math_ac;
+
+@ @<Declare act...@>=
+procedure math_ac;
+begin if cur_cmd=accent then
+ @<Complain that the user should have said \.{\\mathaccent}@>;
+tail_append(new_node(accent_noad,normal));
+vmem(nucleus(tail)).hh:=empty_field;
+vmem(subscr(tail)).hh:=empty_field;
+vmem(supscr(tail)).hh:=empty_field;
+math_type(accent_chr(tail)):=math_char;
+if cur_chr=0 then scan_fifteen_bit_int
+else scan_big_fifteen_bit_int;
+mcharacter(accent_chr(tail)):=qi(cur_val mod @"1000);
+if (cur_val>=var_code)and fam_in_range then fam(accent_chr(tail)):=cur_fam
+else fam(accent_chr(tail)):=(cur_val div @"10000) mod @"100;
+scan_math(nucleus(tail));
+end;
+
+@ @<Complain that the user should have said \.{\\mathaccent}@>=
+begin print_err("Please use "); print_esc("mathaccent");
+print(" for accents in math mode");
+@.Please use \\mathaccent...@>
+help2("I'm changing \accent to \mathaccent here; wish me luck.")@/
+ ("(Accents are not the same in formulas as they are in text.)");
+error;
+end
+
+@ @<Cases of |main_control| that build...@>=
+mmode+vcenter: begin scan_spec(vcenter_group,false); normal_paragraph;
+ push_nest; mode:=-vmode; prev_depth:=ignore_depth;
+ if every_vbox<>null then begin_token_list(every_vbox,every_vbox_text);
+ end;
+
+@ @<Cases of |handle...@>=
+vcenter_group: begin line_break_context:=vcenter_group; end_graf; unsave; save_ptr:=save_ptr-2;
+ p:=vpack(vlink(head),saved(1),saved(0)); pop_nest;
+ tail_append(new_noad); type(tail):=vcenter_noad;
+ math_type(nucleus(tail)):=sub_box; vinfo(nucleus(tail)):=p;
+ end;
+
+@ The routine that inserts a |style_node| holds no surprises.
+
+@<Put each...@>=
+primitive("displaystyle",math_style,display_style);
+@!@:display_style_}{\.{\\displaystyle} primitive@>
+primitive("textstyle",math_style,text_style);
+@!@:text_style_}{\.{\\textstyle} primitive@>
+primitive("scriptstyle",math_style,script_style);
+@!@:script_style_}{\.{\\scriptstyle} primitive@>
+primitive("scriptscriptstyle",math_style,script_script_style);
+@!@:script_script_style_}{\.{\\scriptscriptstyle} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+math_style: print_style(chr_code);
+
+@ @<Cases of |main_control| that build...@>=
+mmode+math_style: tail_append(new_style(cur_chr));
+mmode+non_script: begin tail_append(new_glue(zero_glue));
+ subtype(tail):=cond_math_glue;
+ end;
+mmode+math_choice: append_choices;
+
+@ The routine that scans the four mlists of a \.{\\mathchoice} is very
+much like the routine that builds discretionary nodes.
+
+@<Declare act...@>=
+procedure append_choices;
+begin tail_append(new_choice); incr(save_ptr); saved(-1):=0;
+push_math(math_choice_group); scan_left_brace;
+end;
+
+@ @<Cases of |handle_right_brace|...@>=
+math_choice_group: build_choices;
+
+@ @<Declare act...@>=
+procedure build_choices;
+label exit;
+var p:pointer; {the current mlist}
+begin @<DIR: |unsave| math@>; p:=fin_mlist(null);
+case saved(-1) of
+0:display_mlist(tail):=p;
+1:text_mlist(tail):=p;
+2:script_mlist(tail):=p;
+3:begin script_script_mlist(tail):=p; decr(save_ptr); return;
+ end;
+end; {there are no other cases}
+incr(saved(-1)); push_math(math_choice_group); scan_left_brace;
+exit:end;
+
+@ Subscripts and superscripts are attached to the previous nucleus by the
+@^superscripts@>@^subscripts@>
+action procedure called |sub_sup|. We use the facts that |sub_mark=sup_mark+1|
+and |subscr(p)=supscr(p)+1|.
+
+@<Cases of |main_control| that build...@>=
+mmode+sub_mark,mmode+sup_mark: sub_sup;
+
+@ @<Declare act...@>=
+procedure sub_sup;
+var t:small_number; {type of previous sub/superscript}
+@!p:pointer; {field to be filled by |scan_math|}
+begin t:=empty; p:=null;
+if tail<>head then if scripts_allowed(tail) then
+ begin p:=supscr(tail)+cur_cmd-sup_mark; {|supscr| or |subscr|}
+ t:=math_type(p);
+ end;
+if (p=null)or(t<>empty) then @<Insert a dummy noad to be sub/superscripted@>;
+scan_math(p);
+end;
+
+@ @<Insert a dummy...@>=
+begin tail_append(new_noad);
+p:=supscr(tail)+cur_cmd-sup_mark; {|supscr| or |subscr|}
+if t<>empty then
+ begin if cur_cmd=sup_mark then
+ begin print_err("Double superscript");
+@.Double superscript@>
+ help1("I treat `x^1^2' essentially like `x^1{}^2'.");
+ end
+ else begin print_err("Double subscript");
+@.Double subscript@>
+ help1("I treat `x_1_2' essentially like `x_1{}_2'.");
+ end;
+ error;
+ end;
+end
+
+@ An operation like `\.{\\over}' causes the current mlist to go into a
+state of suspended animation: |incompleat_noad| points to a |fraction_noad|
+that contains the mlist-so-far as its numerator, while the denominator
+is yet to come. Finally when the mlist is finished, the denominator will
+go into the incompleat fraction noad, and that noad will become the
+whole formula, unless it is surrounded by `\.{\\left}' and `\.{\\right}'
+delimiters.
+
+@d above_code=0 { `\.{\\above}' }
+@d over_code=1 { `\.{\\over}' }
+@d atop_code=2 { `\.{\\atop}' }
+@d delimited_code=3 { `\.{\\abovewithdelims}', etc.}
+
+@<Put each...@>=
+primitive("above",above,above_code);@/
+@!@:above_}{\.{\\above} primitive@>
+primitive("over",above,over_code);@/
+@!@:over_}{\.{\\over} primitive@>
+primitive("atop",above,atop_code);@/
+@!@:atop_}{\.{\\atop} primitive@>
+primitive("abovewithdelims",above,delimited_code+above_code);@/
+@!@:above_with_delims_}{\.{\\abovewithdelims} primitive@>
+primitive("overwithdelims",above,delimited_code+over_code);@/
+@!@:over_with_delims_}{\.{\\overwithdelims} primitive@>
+primitive("atopwithdelims",above,delimited_code+atop_code);
+@!@:atop_with_delims_}{\.{\\atopwithdelims} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+above: case chr_code of
+ over_code:print_esc("over");
+ atop_code:print_esc("atop");
+ delimited_code+above_code:print_esc("abovewithdelims");
+ delimited_code+over_code:print_esc("overwithdelims");
+ delimited_code+atop_code:print_esc("atopwithdelims");
+ othercases print_esc("above")
+ endcases;
+
+@ @<Cases of |main_control| that build...@>=
+mmode+above: math_fraction;
+
+@ @<Declare act...@>=
+procedure math_fraction;
+var c:small_number; {the type of generalized fraction we are scanning}
+begin c:=cur_chr;
+if incompleat_noad<>null then
+ @<Ignore the fraction operation and complain about this ambiguous case@>
+else begin incompleat_noad:=new_node(fraction_noad,normal);
+ math_type(numerator(incompleat_noad)):=sub_mlist;
+ vinfo(numerator(incompleat_noad)):=vlink(head);
+ vmem(denominator(incompleat_noad)).hh:=empty_field;
+ vmem(left_delimiter(incompleat_noad)).qqqq:=null_delimiter;
+ vmem(right_delimiter(incompleat_noad)).qqqq:=null_delimiter;@/
+ vlink(head):=null; tail:=head;
+ @<Use code |c| to distinguish between generalized fractions@>;
+ end;
+end;
+
+@ @<Use code |c|...@>=
+if c>=delimited_code then
+ begin scan_delimiter(left_delimiter(incompleat_noad),false);
+ scan_delimiter(right_delimiter(incompleat_noad),false);
+ end;
+case c mod delimited_code of
+above_code: begin scan_normal_dimen;
+ thickness(incompleat_noad):=cur_val;
+ end;
+over_code: thickness(incompleat_noad):=default_code;
+atop_code: thickness(incompleat_noad):=0;
+end {there are no other cases}
+
+@ @<Ignore the fraction...@>=
+begin if c>=delimited_code then
+ begin scan_delimiter(garbage,false); scan_delimiter(garbage,false);
+ end;
+if c mod delimited_code=above_code then scan_normal_dimen;
+print_err("Ambiguous; you need another { and }");
+@.Ambiguous...@>
+help3("I'm ignoring this fraction specification, since I don't")@/
+ ("know whether a construction like `x \over y \over z'")@/
+ ("means `{x \over y} \over z' or `x \over {y \over z}'.");
+error;
+end
+
+@ At the end of a math formula or subformula, the |fin_mlist| routine is
+called upon to return a pointer to the newly completed mlist, and to
+pop the nest back to the enclosing semantic level. The parameter to
+|fin_mlist|, if not null, points to a |right_noad| that ends the
+current mlist; this |right_noad| has not yet been appended.
+
+@<Declare the function called |fin_mlist|@>=
+function fin_mlist(@!p:pointer):pointer;
+var q:pointer; {the mlist to return}
+begin if incompleat_noad<>null then @<Compleat the incompleat noad@>
+else begin vlink(tail):=p; q:=vlink(head);
+ end;
+pop_nest; fin_mlist:=q;
+end;
+
+@ @<Compleat...@>=
+begin math_type(denominator(incompleat_noad)):=sub_mlist;
+vinfo(denominator(incompleat_noad)):=vlink(head);
+if p=null then q:=incompleat_noad
+else begin q:=vinfo(numerator(incompleat_noad));
+ if (type(q)<>left_noad)or(delim_ptr=null) then confusion("right");
+@:this can't happen right}{\quad right@>
+ vinfo(numerator(incompleat_noad)):=vlink(delim_ptr);
+ vlink(delim_ptr):=incompleat_noad; vlink(incompleat_noad):=p;
+ end;
+end
+
+@ Now at last we're ready to see what happens when a right brace occurs
+in a math formula. Two special cases are simplified here: Braces are effectively
+removed when they surround a single Ord without sub/superscripts, or when they
+surround an accent that is the nucleus of an Ord atom.
+
+@<Cases of |handle...@>=
+math_group: begin @<DIR: |unsave| math@>; decr(save_ptr);@/
+ math_type(saved(0)):=sub_mlist; p:=fin_mlist(null); vinfo(saved(0)):=p;
+ if p<>null then if vlink(p)=null then
+ if type(p)=ord_noad then
+ begin if math_type(subscr(p))=empty then
+ if math_type(supscr(p))=empty then
+ begin vmem(saved(0)).hh:=vmem(nucleus(p)).hh;
+ flush_node(p);
+ end;
+ end
+ else if type(p)=accent_noad then if saved(0)=nucleus(tail) then
+ if type(tail)=ord_noad then @<Replace the tail of the list by |p|@>;
+ end;
+
+@ @<Replace the tail...@>=
+begin q:=head; while vlink(q)<>tail do q:=vlink(q);
+vlink(q):=p; flush_node(tail); tail:=p;
+end
+
+@ We have dealt with all constructions of math mode except `\.{\\left}' and
+`\.{\\right}', so the picture is completed by the following sections of
+the program.
+
+@<Put each...@>=
+primitive("left",left_right,left_noad);
+@!@:left_}{\.{\\left} primitive@>
+primitive("right",left_right,right_noad);
+@!@:right_}{\.{\\right} primitive@>
+text(frozen_right):="right"; eqtb[frozen_right]:=eqtb[cur_val];
+
+@ @<Cases of |print_cmd_chr|...@>=
+left_right: if chr_code=left_noad then print_esc("left")
+@/@<Cases of |left_right| for |print_cmd_chr|@>@/
+else print_esc("right");
+
+@ @<Cases of |main_control| that build...@>=
+mmode+left_right: math_left_right;
+
+@ @<Declare act...@>=
+procedure math_left_right;
+var t:small_number; {|left_noad| or |right_noad|}
+@!p:pointer; {new noad}
+@!q:pointer; {resulting mlist}
+begin t:=cur_chr;
+if (t<>left_noad)and(cur_group<>math_left_group) then
+ @<Try to recover from mismatched \.{\\right}@>
+else begin p:=new_noad; type(p):=t;
+ scan_delimiter(delimiter(p),false);
+ if t=middle_noad then
+ begin type(p):=right_noad; subtype(p):=middle_noad;
+ end;
+ if t=left_noad then q:=p
+ else begin q:=fin_mlist(p);
+ @<DIR: |unsave| math@>; {end of |math_left_group|}
+ end;
+ if t<>right_noad then
+ begin push_math(math_left_group); vlink(head):=q; tail:=p;
+ delim_ptr:=p;
+ end
+ else begin
+ tail_append(new_noad); type(tail):=inner_noad;
+ math_type(nucleus(tail)):=sub_mlist;
+ vinfo(nucleus(tail)):=q;
+ end;
+ end;
+end;
+
+@ @<Try to recover from mismatch...@>=
+begin if cur_group=math_shift_group then
+ begin scan_delimiter(garbage,false);
+ print_err("Extra ");
+ if t=middle_noad then
+ begin print_esc("middle");
+@.Extra \\middle.@>
+ help1("I'm ignoring a \middle that had no matching \left.");
+ end
+ else begin print_esc("right");
+@.Extra \\right.@>
+ help1("I'm ignoring a \right that had no matching \left.");
+ end;
+ error;
+ end
+else off_save;
+end
+
+@ Here is the only way out of math mode.
+
+@<Cases of |main_control| that build...@>=
+mmode+math_shift: if cur_group=math_shift_group then after_math
+ else off_save;
+
+@ @<Declare act...@>=
+procedure after_math;
+var l:boolean; {`\.{\\leqno}' instead of `\.{\\eqno}'}
+@!danger:boolean; {not enough symbol fonts are present}
+@!m:integer; {|mmode| or |-mmode|}
+@!p:pointer; {the formula}
+@!a:pointer; {box containing equation number}
+@<Local variables for finishing a displayed formula@>@;
+begin danger:=false;
+@<Check that the necessary fonts for math symbols are present;
+ if not, flush the current math lists and set |danger:=true|@>;
+m:=mode; l:=false; p:=fin_mlist(null); {this pops the nest}
+if mode=-m then {end of equation number}
+ begin @<Check that another \.\$ follows@>;
+ cur_mlist:=p; cur_style:=text_style; mlist_penalties:=false;
+ mlist_to_hlist; a:=hpack(vlink(temp_head),natural);
+ @<DIR: |unsave| math@>;
+ decr(save_ptr); {now |cur_group=math_shift_group|}
+ if saved(0)=1 then l:=true;
+ danger:=false;
+ @<Check that the necessary fonts for math symbols are present;
+ if not, flush the current math lists and set |danger:=true|@>;
+ m:=mode; p:=fin_mlist(null);
+ end
+else a:=null;
+if m<0 then @<Finish math in text@>
+else begin if a=null then @<Check that another \.\$ follows@>;
+ @<Finish displayed math@>;
+ end;
+end;
+
+@ @<Check that the necessary fonts...@>=
+if (font_params(fam_fnt(2+text_size))<total_mathsy_params)or@|
+ (font_params(fam_fnt(2+script_size))<total_mathsy_params)or@|
+ (font_params(fam_fnt(2+script_script_size))<total_mathsy_params) then
+ begin print_err("Math formula deleted: Insufficient symbol fonts");@/
+@.Math formula deleted...@>
+ help3("Sorry, but I can't typeset math unless \textfont 2")@/
+ ("and \scriptfont 2 and \scriptscriptfont 2 have all")@/
+ ("the \fontdimen values needed in math symbol fonts.");
+ error; flush_math; danger:=true;
+ end
+else if (font_params(fam_fnt(3+text_size))<total_mathex_params)or@|
+ (font_params(fam_fnt(3+script_size))<total_mathex_params)or@|
+ (font_params(fam_fnt(3+script_script_size))<total_mathex_params) then
+ begin print_err("Math formula deleted: Insufficient extension fonts");@/
+ help3("Sorry, but I can't typeset math unless \textfont 3")@/
+ ("and \scriptfont 3 and \scriptscriptfont 3 have all")@/
+ ("the \fontdimen values needed in math extension fonts.");
+ error; flush_math; danger:=true;
+ end
+
+@ The |unsave| is done after everything else here; hence an appearance of
+`\.{\\mathsurround}' inside of `\.{\$...\$}' affects the spacing at these
+particular \.\$'s. This is consistent with the conventions of
+`\.{\$\$...\$\$}', since `\.{\\abovedisplayskip}' inside a display affects the
+space above that display.
+
+@<Finish math in text@> =
+begin tail_append(new_math(math_surround,before));
+if dir_math_save then
+ @<Append a begin direction to the tail of the current list@>;
+cur_mlist:=p; cur_style:=text_style; mlist_penalties:=(mode>0); mlist_to_hlist;
+vlink(tail):=vlink(temp_head);
+while vlink(tail)<>null do tail:=vlink(tail);
+if dir_math_save then
+ @<Append an end direction to the tail of the current list@>;
+dir_math_save:=false;
+tail_append(new_math(math_surround,after));
+space_factor:=1000;
+@<DIR: |unsave| math@>;
+end
+
+@ \TeX\ gets to the following part of the program when the first `\.\$' ending
+a display has been scanned.
+
+@<Check that another \.\$ follows@>=
+begin get_x_token;
+if cur_cmd<>math_shift then
+ begin print_err("Display math should end with $$");
+@.Display math...with \$\$@>
+ help2("The `$' that I just saw supposedly matches a previous `$$'.")@/
+ ("So I shall assume that you typed `$$' both times.");
+ back_error;
+ end;
+end
+
+@ We have saved the worst for last: The fussiest part of math mode processing
+occurs when a displayed formula is being centered and placed with an optional
+equation number.
+
+@<Local variables for finishing...@>=
+@!b:pointer; {box containing the equation}
+@!w:scaled; {width of the equation}
+@!z:scaled; {width of the line}
+@!e:scaled; {width of equation number}
+@!q:scaled; {width of equation number plus space to separate from equation}
+@!d:scaled; {displacement of equation in the line}
+@!s:scaled; {move the line right this much}
+@!g1,@!g2:small_number; {glue parameter codes for before and after}
+@!r:pointer; {kern node used to position the display}
+@!t:pointer; {tail of adjustment list}
+@!pre_t:pointer; {tail of pre-adjustment list}
+
+@ At this time |p| points to the mlist for the formula; |a| is either
+|null| or it points to a box containing the equation number; and we are in
+vertical mode (or internal vertical mode).
+
+@<Finish displayed math@>=
+cur_mlist:=p; cur_style:=display_style; mlist_penalties:=false;
+mlist_to_hlist; p:=vlink(temp_head);@/
+adjust_tail:=adjust_head; pre_adjust_tail:=pre_adjust_head;
+b:=hpack(p,natural); p:=list_ptr(b);
+t:=adjust_tail; adjust_tail:=null;@/
+pre_t:=pre_adjust_tail; pre_adjust_tail:=null;@/
+w:=width(b); z:=display_width; s:=display_indent;
+if (a=null)or danger then
+ begin e:=0; q:=0;
+ end
+else begin e:=width(a); q:=e+math_quad(text_size);
+ end;
+if w+q>z then
+ @<Squeeze the equation as much as possible; if there is an equation
+ number that should go on a separate line by itself,
+ set~|e:=0|@>;
+@<Determine the displacement, |d|, of the left edge of the equation, with
+ respect to the line size |z|, assuming that |l=false|@>;
+@<Append the glue or equation number preceding the display@>;
+@<Append the display and perhaps also the equation number@>;
+@<Append the glue or equation number following the display@>;
+resume_after_display
+
+@ @<Declare act...@>=
+procedure resume_after_display;
+begin if cur_group<>math_shift_group then confusion("display");
+@:this can't happen display}{\quad display@>
+@<DIR: |unsave| math@>;
+prev_graf:=prev_graf+3;
+push_nest; mode:=hmode; space_factor:=1000;
+@<LOCAL: Add local paragraph node@>;
+@<Scan an optional space@>;
+if nest_ptr=1 then begin check_filter('after_display'); build_page; end;
+end;
+
+@ The user can force the equation number to go on a separate line
+by causing its width to be zero.
+
+@<Squeeze the equation as much as possible...@>=
+begin if (e<>0)and((w-total_shrink[normal]+q<=z)or@|
+ (total_shrink[sfi]<>0)or(total_shrink[fil]<>0)or
+ (total_shrink[fill]<>0)or(total_shrink[filll]<>0)) then
+ begin flush_node(b);
+ b:=hpack(p,z-q,exactly);
+ end
+else begin e:=0;
+ if w>z then
+ begin
+ list_ptr(b):=null; flush_node(b);
+ b:=hpack(p,z,exactly);
+ end;
+ end;
+w:=width(b);
+end
+
+@ We try first to center the display without regard to the existence of
+the equation number. If that would make it too close (where ``too close''
+means that the space between display and equation number is less than the
+width of the equation number), we either center it in the remaining space
+or move it as far from the equation number as possible. The latter alternative
+is taken only if the display begins with glue, since we assume that the
+user put glue there to control the spacing precisely.
+
+@<Determine the displacement, |d|, of the left edge of the equation...@>=
+d:=half(z-w);
+if (e>0)and(d<2*e) then {too close}
+ begin d:=half(z-w-e);
+ if p<>null then if not is_char_node(p) then if type(p)=glue_node then d:=0;
+ end
+
+@ If the equation number is set on a line by itself, either before or
+after the formula, we append an infinite penalty so that no page break will
+separate the display from its number; and we use the same size and
+displacement for all three potential lines of the display, even though
+`\.{\\parshape}' may specify them differently.
+
+@<Append the glue or equation number preceding the display@>=
+tail_append(new_penalty(pre_display_penalty));@/
+if (d+s<=pre_display_size)or l then {not enough clearance}
+ begin g1:=above_display_skip_code; g2:=below_display_skip_code;
+ end
+else begin g1:=above_display_short_skip_code;
+ g2:=below_display_short_skip_code;
+ end;
+if l and(e=0) then {it follows that |type(a)=hlist_node|}
+ begin shift_amount(a):=s; append_to_vlist(a);
+ tail_append(new_penalty(inf_penalty));
+ end
+else tail_append(new_param_glue(g1))
+
+@ @<Append the display and perhaps also the equation number@>=
+if e<>0 then
+ begin r:=new_kern(z-w-e-d);
+ if l then
+ begin vlink(a):=r; vlink(r):=b; b:=a; d:=0;
+ end
+ else begin vlink(b):=r; vlink(r):=a;
+ end;
+ b:=hpack(b,natural);
+ end;
+shift_amount(b):=s+d; append_to_vlist(b)
+
+@ @<Append the glue or equation number following the display@>=
+if (a<>null)and(e=0)and not l then
+ begin tail_append(new_penalty(inf_penalty));
+ shift_amount(a):=s+z-width(a);
+ append_to_vlist(a);
+ g2:=0;
+ end;
+if t<>adjust_head then {migrating material comes after equation number}
+ begin vlink(tail):=vlink(adjust_head); tail:=t;
+ end;
+if pre_t<>pre_adjust_head then
+ begin vlink(tail):=vlink(pre_adjust_head); tail:=pre_t;
+ end;
+tail_append(new_penalty(post_display_penalty));
+if g2>0 then tail_append(new_param_glue(g2))
+
+@ When \.{\\halign} appears in a display, the alignment routines operate
+essentially as they do in vertical mode. Then the following program is
+activated, with |p| and |q| pointing to the beginning and end of the
+resulting list, and with |aux_save| holding the |prev_depth| value.
+
+@<Finish an alignment in a display@>=
+begin do_assignments;
+if cur_cmd<>math_shift then @<Pontificate about improper alignment in display@>
+else @<Check that another \.\$ follows@>;
+pop_nest;
+tail_append(new_penalty(pre_display_penalty));
+tail_append(new_param_glue(above_display_skip_code));
+vlink(tail):=p;
+if p<>null then tail:=q;
+tail_append(new_penalty(post_display_penalty));
+tail_append(new_param_glue(below_display_skip_code));
+prev_depth:=aux_save.sc; resume_after_display;
+end
+
+@ @<Pontificate...@>=
+begin print_err("Missing $$ inserted");
+@.Missing {\$\$} inserted@>
+help2("Displays can use special alignments (like \eqalignno)")@/
+ ("only if nothing but the alignment itself is between $$'s.");
+back_error;
+end
+
+@* \[49] Mode-independent processing.
+The long |main_control| procedure has now been fully specified, except for
+certain activities that are independent of the current mode. These activities
+do not change the current vlist or hlist or mlist; if they change anything,
+it is the value of a parameter or the meaning of a control sequence.
+
+Assignments to values in |eqtb| can be global or local. Furthermore, a
+control sequence can be defined to be `\.{\\long}', `\.{\\protected}',
+or `\.{\\outer}', and it might or might not be expanded. The prefixes
+`\.{\\global}', `\.{\\long}', `\.{\\protected}',
+and `\.{\\outer}' can occur in any order. Therefore we assign binary numeric
+codes, making it possible to accumulate the union of all specified prefixes
+by adding the corresponding codes. (\PASCAL's |set| operations could also
+have been used.)
+
+@<Put each...@>=
+primitive("long",prefix,1);
+@!@:long_}{\.{\\long} primitive@>
+primitive("outer",prefix,2);
+@!@:outer_}{\.{\\outer} primitive@>
+primitive("global",prefix,4);
+@!@:global_}{\.{\\global} primitive@>
+primitive("def",def,0);
+@!@:def_}{\.{\\def} primitive@>
+primitive("gdef",def,1);
+@!@:gdef_}{\.{\\gdef} primitive@>
+primitive("edef",def,2);
+@!@:edef_}{\.{\\edef} primitive@>
+primitive("xdef",def,3);
+@!@:xdef_}{\.{\\xdef} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+prefix: if chr_code=1 then print_esc("long")
+ else if chr_code=2 then print_esc("outer")
+ @/@<Cases of |prefix| for |print_cmd_chr|@>@/
+ else print_esc("global");
+def: if chr_code=0 then print_esc("def")
+ else if chr_code=1 then print_esc("gdef")
+ else if chr_code=2 then print_esc("edef")
+ else print_esc("xdef");
+
+@ Every prefix, and every command code that might or might not be prefixed,
+calls the action procedure |prefixed_command|. This routine accumulates
+a sequence of prefixes until coming to a non-prefix, then it carries out
+the command.
+
+@<Cases of |main_control| that don't...@>=
+any_mode(toks_register),
+any_mode(assign_toks),
+any_mode(assign_int),
+any_mode(assign_attr),
+any_mode(assign_dir),
+any_mode(assign_dimen),
+any_mode(assign_glue),
+any_mode(assign_mu_glue),
+any_mode(assign_font_dimen),
+any_mode(assign_font_int),
+any_mode(set_aux),
+any_mode(set_prev_graf),
+any_mode(set_page_dimen),
+any_mode(set_page_int),
+any_mode(set_box_dimen),
+any_mode(set_shape),
+any_mode(def_code),
+any_mode(extdef_code),
+any_mode(def_family),
+any_mode(set_font),
+any_mode(def_font),
+any_mode(letterspace_font),
+any_mode(register),
+any_mode(advance),
+any_mode(multiply),
+any_mode(divide),
+any_mode(prefix),
+any_mode(let),
+any_mode(shorthand_def),
+any_mode(read_to_cs),
+any_mode(def),
+any_mode(set_box),
+any_mode(hyph_data),
+any_mode(set_interaction),
+any_mode(set_ocp),
+any_mode(def_ocp),
+any_mode(set_ocp_list),
+any_mode(def_ocp_list),
+any_mode(clear_ocp_lists),
+any_mode(push_ocp_list),
+any_mode(pop_ocp_list),
+any_mode(ocp_list_op),
+any_mode(ocp_trace_level) : prefixed_command;
+
+@ If the user says, e.g., `\.{\\global\\global}', the redundancy is
+silently accepted.
+
+@<Declare act...@>=
+@t\4@>@<Declare subprocedures for |prefixed_command|@>@t@>@;@/
+procedure prefixed_command;
+label done,exit;
+var a:small_number; {accumulated prefix codes so far}
+@!f:internal_font_number; {identifies a font}
+@!j:halfword; {index into a \.{\\parshape} specification}
+@!p,@!q:pointer; {for temporary short-term use}
+@!n:integer; {ditto}
+@!e:boolean; {should a definition be expanded? or was \.{\\let} not done?}
+begin a:=0;
+while cur_cmd=prefix do
+ begin if not odd(a div cur_chr) then a:=a+cur_chr;
+ @<Get the next non-blank non-relax...@>;
+ if cur_cmd<=max_non_prefixed_command then
+ @<Discard erroneous prefixes and |return|@>;
+ if tracing_commands>2 then show_cur_cmd_chr;
+ end;
+@<Discard the prefixes \.{\\long} and \.{\\outer} if they are irrelevant@>;
+@<Adjust \(f)for the setting of \.{\\globaldefs}@>;
+case cur_cmd of
+@t\4@>@<Assignments@>@;
+othercases confusion("prefix")
+@:this can't happen prefix}{\quad prefix@>
+endcases;
+done: @<Insert a token saved by \.{\\afterassignment}, if any@>;
+exit:end;
+
+@ @<Discard erroneous...@>=
+begin print_err("You can't use a prefix with `");
+@.You can't use a prefix with x@>
+print_cmd_chr(cur_cmd,cur_chr); print_char("'");
+help1("I'll pretend you didn't say \long or \outer or \global.");
+back_error; return;
+end
+
+@ @<Discard the prefixes...@>=
+if a>=8 then
+ begin j:=protected_token; a:=a-8;
+ end
+else j:=0;
+if (cur_cmd<>def)and((a mod 4<>0)or(j<>0)) then
+ begin print_err("You can't use `"); print_esc("long"); print("' or `");
+ print_esc("outer"); print("' with `");
+@.You can't use \\long...@>
+ print_cmd_chr(cur_cmd,cur_chr); print_char("'");
+ help1("I'll pretend you didn't say \long or \outer here.");
+ error;
+ end
+
+@ The previous routine does not have to adjust |a| so that |a mod 4=0|,
+since the following routines test for the \.{\\global} prefix as follows.
+
+@d global==(a>=4)
+@d define(#)==if global then geq_define(#)@+else eq_define(#)
+@d word_define(#)==if global then geq_word_define(#)@+else eq_word_define(#)
+@d define_math_code(#)==if global
+ then set_math_code(#,level_one)@+else set_math_code(#,cur_level)
+@d define_del_code(#)==if global
+ then set_del_code(#,level_one)@+else set_del_code(#,cur_level)
+@d define_lc_code(#)==if global
+ then set_lc_code(#,level_one)@+else set_lc_code(#,cur_level)
+@d define_uc_code(#)==if global
+ then set_uc_code(#,level_one)@+else set_uc_code(#,cur_level)
+@d define_sf_code(#)==if global
+ then set_sf_code(#,level_one)@+else set_sf_code(#,cur_level)
+@d define_cat_code(#)==if global
+ then set_cat_code(cat_code_table,#,level_one)@+else set_cat_code(cat_code_table,#,cur_level)
+
+@<Adjust \(f)for the setting of \.{\\globaldefs}@>=
+if global_defs<>0 then
+ if global_defs<0 then
+ begin if global then a:=a-4;
+ end
+ else begin if not global then a:=a+4;
+ end
+
+@ When a control sequence is to be defined, by \.{\\def} or \.{\\let} or
+something similar, the |get_r_token| routine will substitute a special
+control sequence for a token that is not redefinable.
+
+@<Declare subprocedures for |prefixed_command|@>=
+procedure get_r_token;
+label restart;
+begin restart: repeat get_token;
+until cur_tok<>space_token;
+if (cur_cs=0)or(cur_cs>frozen_control_sequence) then
+ begin print_err("Missing control sequence inserted");
+@.Missing control...@>
+ help5("Please don't say `\def cs{...}', say `\def\cs{...}'.")@/
+ ("I've inserted an inaccessible control sequence so that your")@/
+ ("definition will be completed without mixing me up too badly.")@/
+ ("You can recover graciously from this error, if you're")@/
+ ("careful; see exercise 27.2 in The TeXbook.");
+@:TeXbook}{\sl The \TeX book@>
+ if cur_cs=0 then back_input;
+ cur_tok:=cs_token_flag+frozen_protection; ins_error; goto restart;
+ end;
+end;
+
+@ @<Initialize table entries...@>=
+text(frozen_protection):="inaccessible";
+
+@ Assignments from Lua need helpers.
+
+@p function is_int_assign(cmd:halfword):boolean;
+begin
+ is_int_assign := (cmd=assign_int);
+end;
+function is_dim_assign(cmd:halfword):boolean;
+begin
+ is_dim_assign := (cmd=assign_dimen);
+end;
+procedure assign_internal_int(cmd:halfword;value:integer);
+var a:small_number;
+begin
+ a:=0;
+ word_define(cmd,value);
+end;
+procedure assign_internal_dim(cmd:halfword;value:integer);
+var a:small_number;
+begin
+ a:=0;
+ word_define(cmd,value);
+end;
+
+
+@ Here's an example of the way many of the following routines operate.
+(Unfortunately, they aren't all as simple as this.)
+
+@<Assignments@>=
+set_font: define(cur_font_loc,data,cur_chr);
+
+@ When a |def| command has been scanned,
+|cur_chr| is odd if the definition is supposed to be global, and
+|cur_chr>=2| if the definition is supposed to be expanded.
+
+@<Assignments@>=
+def: begin if odd(cur_chr)and not global and(global_defs>=0) then a:=a+4;
+ e:=(cur_chr>=2); get_r_token; p:=cur_cs;
+ q:=scan_toks(true,e);
+ if j<>0 then
+ begin q:=get_avail; info(q):=j; link(q):=link(def_ref);
+ link(def_ref):=q;
+ end;
+ define(p,call+(a mod 4),def_ref);
+ end;
+
+@ Both \.{\\let} and \.{\\futurelet} share the command code |let|.
+
+@<Put each...@>=
+primitive("let",let,normal);@/
+@!@:let_}{\.{\\let} primitive@>
+primitive("futurelet",let,normal+1);@/
+@!@:future_let_}{\.{\\futurelet} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+let: if chr_code<>normal then print_esc("futurelet")@+else print_esc("let");
+
+@ @<Assignments@>=
+let: begin n:=cur_chr;
+ get_r_token; p:=cur_cs;
+ if n=normal then
+ begin repeat get_token;
+ until cur_cmd<>spacer;
+ if cur_tok=other_token+"=" then
+ begin get_token;
+ if cur_cmd=spacer then get_token;
+ end;
+ end
+ else begin get_token; q:=cur_tok; get_token; back_input;
+ cur_tok:=q; back_input; {look ahead, then back up}
+ end; {note that |back_input| doesn't affect |cur_cmd|, |cur_chr|}
+ if cur_cmd>=call then add_token_ref(cur_chr);
+ define(p,cur_cmd,cur_chr);
+ end;
+
+@ A \.{\\chardef} creates a control sequence whose |cmd| is |char_given|;
+a \.{\\mathchardef} creates a control sequence whose |cmd| is |math_given|;
+and the corresponding |chr| is the character code or math code. A \.{\\countdef}
+or \.{\\dimendef} or \.{\\skipdef} or \.{\\muskipdef} creates a control
+sequence whose |cmd| is |assign_int| or \dots\ or |assign_mu_glue|, and the
+corresponding |chr| is the |eqtb| location of the internal register in question.
+
+@d char_def_code=0 {|shorthand_def| for \.{\\chardef}}
+@d math_char_def_code=1 {|shorthand_def| for \.{\\mathchardef}}
+@d omath_char_def_code=2 {|shorthand_def| for \.{\\omathchardef}}
+@d count_def_code=3 {|shorthand_def| for \.{\\countdef}}
+@d attribute_def_code=4 {|shorthand_def| for \.{\\attributedef}}
+@d dimen_def_code=5 {|shorthand_def| for \.{\\dimendef}}
+@d skip_def_code=6 {|shorthand_def| for \.{\\skipdef}}
+@d mu_skip_def_code=7 {|shorthand_def| for \.{\\muskipdef}}
+@d toks_def_code=8 {|shorthand_def| for \.{\\toksdef}}
+
+@<Put each...@>=
+primitive("chardef",shorthand_def,char_def_code);@/
+@!@:char_def_}{\.{\\chardef} primitive@>
+primitive("mathchardef",shorthand_def,math_char_def_code);@/
+@!@:math_char_def_}{\.{\\mathchardef} primitive@>
+primitive("omathchardef",shorthand_def,omath_char_def_code);@/
+@!@:math_char_def_}{\.{\\omathchardef} primitive@>
+primitive("countdef",shorthand_def,count_def_code);@/
+@!@:count_def_}{\.{\\countdef} primitive@>
+primitive("attributedef",shorthand_def,attribute_def_code);@/
+@!@:attribute_def_}{\.{\\attributedef} primitive@>
+primitive("dimendef",shorthand_def,dimen_def_code);@/
+@!@:dimen_def_}{\.{\\dimendef} primitive@>
+primitive("skipdef",shorthand_def,skip_def_code);@/
+@!@:skip_def_}{\.{\\skipdef} primitive@>
+primitive("muskipdef",shorthand_def,mu_skip_def_code);@/
+@!@:mu_skip_def_}{\.{\\muskipdef} primitive@>
+primitive("toksdef",shorthand_def,toks_def_code);@/
+@!@:toks_def_}{\.{\\toksdef} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+shorthand_def: case chr_code of
+ char_def_code: print_esc("chardef");
+ math_char_def_code: print_esc("mathchardef");
+ omath_char_def_code: print_esc("omathchardef");
+ count_def_code: print_esc("countdef");
+ attribute_def_code: print_esc("attributedef");
+ dimen_def_code: print_esc("dimendef");
+ skip_def_code: print_esc("skipdef");
+ mu_skip_def_code: print_esc("muskipdef");
+ othercases print_esc("toksdef")
+ endcases;
+char_given: begin print_esc("char"); print_hex(chr_code);
+ end;
+math_given: begin print_esc("mathchar"); print_hex(chr_code);
+ end;
+omath_given: begin print_esc("omathchar"); print_hex(chr_code);
+ end;
+
+@ We temporarily define |p| to be |relax|, so that an occurrence of |p|
+while scanning the definition will simply stop the scanning instead of
+producing an ``undefined control sequence'' error or expanding the
+previous meaning. This allows, for instance, `\.{\\chardef\\foo=123\\foo}'.
+
+@<Assignments@>=
+shorthand_def: begin n:=cur_chr; get_r_token; p:=cur_cs;
+ define(p,relax,too_big_char); scan_optional_equals;
+ case n of
+ char_def_code: begin scan_char_num; define(p,char_given,cur_val);
+ end;
+ math_char_def_code: begin scan_real_fifteen_bit_int;
+ define(p,math_given,cur_val);
+ end;
+ omath_char_def_code: begin scan_big_fifteen_bit_int;
+ define(p,omath_given,cur_val);
+ end;
+ othercases begin scan_register_num;
+ case n of
+ count_def_code: define(p,assign_int,count_base+cur_val);
+ attribute_def_code: define(p,assign_attr,attribute_base+cur_val);
+ dimen_def_code: define(p,assign_dimen,scaled_base+cur_val);
+ skip_def_code: define(p,assign_glue,skip_base+cur_val);
+ mu_skip_def_code: define(p,assign_mu_glue,mu_skip_base+cur_val);
+ toks_def_code: define(p,assign_toks,toks_base+cur_val);
+ end; {there are no other cases}
+ end
+ endcases;
+ end;
+
+@ @<Assignments@>=
+read_to_cs: begin j:=cur_chr; scan_int; n:=cur_val;
+ if not scan_keyword("to") then
+ begin print_err("Missing `to' inserted");
+@.Missing `to'...@>
+ help2("You should have said `\read<number> to \cs'.")@/
+ ("I'm going to look for the \cs now."); error;
+ end;
+ get_r_token;
+ p:=cur_cs; read_toks(n,p,j); define(p,call,cur_val);
+ end;
+
+@ The token-list parameters, \.{\\output} and \.{\\everypar}, etc., receive
+their values in the following way. (For safety's sake, we place an
+enclosing pair of braces around an \.{\\output} list.)
+
+@<Assignments@>=
+toks_register,assign_toks: begin q:=cur_cs;
+ if cur_cmd=toks_register then
+ begin scan_register_num; p:=toks_base+cur_val;
+ end
+ else p:=cur_chr; {|p=every_par_loc| or |output_routine_loc| or \dots}
+ scan_optional_equals;
+ @<Get the next non-blank non-relax non-call token@>;
+ if cur_cmd<>left_brace then @<If the right-hand side is a token parameter
+ or token register, finish the assignment and |goto done|@>;
+ back_input; cur_cs:=q; q:=scan_toks(false,false);
+ if link(def_ref)=null then {empty list: revert to the default}
+ begin define(p,undefined_cs,null); free_avail(def_ref);
+ end
+ else begin if p=output_routine_loc then {enclose in curlies}
+ begin p:=get_avail; link(q):=p; p:=output_routine_loc;
+ q:=link(q);info(q):=right_brace_token+"}";
+ q:=get_avail;
+ info(q):=left_brace_token+"{";
+ link(q):=link(def_ref); link(def_ref):=q;
+ end;
+ define(p,call,def_ref);
+ end;
+ end;
+
+@ @<If the right-hand side is a token parameter...@>=
+begin if cur_cmd=toks_register then
+ begin scan_register_num; cur_cmd:=assign_toks; cur_chr:=toks_base+cur_val;
+ end;
+if cur_cmd=assign_toks then
+ begin q:=equiv(cur_chr);
+ if q=null then define(p,undefined_cs,null)
+ else begin add_token_ref(q); define(p,call,q);
+ end;
+ goto done;
+ end;
+end
+
+@ Similar routines are used to assign values to the numeric parameters.
+
+@<Assignments@>=
+assign_int: begin p:=cur_chr; scan_optional_equals; scan_int;
+ if p=(int_base+cat_code_table_code) then begin
+ if valid_catcode_table(cur_val) then begin
+ if cur_val<>cat_code_table then
+ word_define(p,cur_val);
+ end
+ else begin
+ print_err("Invalid \catcode table");
+ help2("You can only switch to a \catcode table that is initialized")
+ ("using \savecatcodetable or \initcatcodetable, or to table 0");
+ error;
+ end;
+ end
+ else if (p=new_line_char)and(cur_val>127) then begin
+ print_err("Invalid \newlinechar");
+ help1("The value for \newlinechar has to be between 0 and 127.");
+ error;
+ end
+ else if p=end_line_char then begin
+ if (cur_val<0)or(cur_val>biggest_char) then
+ word_define(p,-1)
+ else
+ word_define(p,13);
+ end
+ else
+ word_define(p,cur_val);
+{If we are defining subparagraph penalty levels while we are
+in hmode, then we put out a whatsit immediately, otherwise
+we leave it alone. This mechanism might not be sufficiently
+powerful, and some other algorithm, searching down the stack,
+might be necessary. Good first step.}
+ if (abs(mode)=hmode) and
+ ((p=(int_base+local_inter_line_penalty_code)) or
+ (p=(int_base+local_broken_penalty_code))) then begin
+ @<LOCAL: Add local paragraph node@>;
+ eq_word_define(int_base+no_local_whatsits_code,no_local_whatsits+1);
+ local_par_bool:=true;
+ end;
+ if p=int_base+language_code then word_define(int_base+cur_lang_code,cur_val);
+ end;
+assign_attr: begin p:=cur_chr; scan_optional_equals; scan_int;
+ if (p-attribute_base)>max_used_attr then max_used_attr:=(p-attribute_base);
+ attr_list_cache:=cache_disabled;
+ word_define(p,cur_val); end;
+assign_dir: begin
+ @<DIR: Assign direction codes@>
+ end;
+assign_dimen: begin p:=cur_chr; scan_optional_equals;
+ scan_normal_dimen; word_define(p,cur_val);
+ end;
+assign_glue,assign_mu_glue: begin p:=cur_chr; n:=cur_cmd; scan_optional_equals;
+ if n=assign_mu_glue then scan_glue(mu_val)@+else scan_glue(glue_val);
+ trap_zero_glue;
+ define(p,glue_ref,cur_val);
+ end;
+
+@ When a glue register or parameter becomes zero, it will always point to
+|zero_glue| because of the following procedure. (Exception: The tabskip
+glue isn't trapped while preambles are being scanned.)
+
+@<Declare subprocedures for |prefixed_command|@>=
+procedure trap_zero_glue;
+begin if (width(cur_val)=0)and(stretch(cur_val)=0)and(shrink(cur_val)=0) then
+ begin add_glue_ref(zero_glue);
+ delete_glue_ref(cur_val); cur_val:=zero_glue;
+ end;
+end;
+
+@ The various character code tables are changed by the |def_code| commands,
+and the font families are declared by |def_family|.
+
+@<Put each...@>=
+primitive("catcode",def_code,cat_code_base);
+@!@:cat_code_}{\.{\\catcode} primitive@>
+primitive("mathcode",def_code,math_code_base);
+@!@:math_code_}{\.{\\mathcode} primitive@>
+primitive("lccode",def_code,lc_code_base);
+@!@:lc_code_}{\.{\\lccode} primitive@>
+primitive("uccode",def_code,uc_code_base);
+@!@:uc_code_}{\.{\\uccode} primitive@>
+primitive("sfcode",def_code,sf_code_base);
+@!@:sf_code_}{\.{\\sfcode} primitive@>
+primitive("delcode",def_code,del_code_base);
+@!@:del_code_}{\.{\\delcode} primitive@>
+primitive("textfont",def_family,math_font_base);
+@!@:text_font_}{\.{\\textfont} primitive@>
+primitive("scriptfont",def_family,math_font_base+script_size);
+@!@:script_font_}{\.{\\scriptfont} primitive@>
+primitive("scriptscriptfont",def_family,math_font_base+script_script_size);
+@!@:script_script_font_}{\.{\\scriptscriptfont} primitive@>
+primitive("omathcode",extdef_code,math_code_base);
+@!@:math_code_}{\.{\\omathcode} primitive@>
+primitive("odelcode",extdef_code,del_code_base);
+@!@:del_code_}{\.{\\odelcode} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+def_code: if chr_code=cat_code_base then print_esc("catcode")
+ else if chr_code=math_code_base then print_esc("mathcode")
+ else if chr_code=lc_code_base then print_esc("lccode")
+ else if chr_code=uc_code_base then print_esc("uccode")
+ else if chr_code=sf_code_base then print_esc("sfcode")
+ else print_esc("delcode");
+extdef_code: if chr_code=math_code_base then print_esc("omathcode")
+ else print_esc("odelcode");
+def_family: print_size(chr_code-math_font_base);
+
+@ The different types of code values have different legal ranges; the
+following program is careful to check each case properly.
+
+@d check_def_code(#)== if ((cur_val<0)and(p<#))or(cur_val>n) then
+ begin print_err("Invalid code ("); print_int(cur_val);
+ if p<# then print("), should be in the range 0..")
+ else print("), should be at most ");
+ print_int(n);
+ help1("I'm going to use 0 instead of that illegal code value.");@/
+ error; cur_val:=0;
+ end
+@.Invalid code@>
+
+
+@<Assignments@>=
+def_code: begin @<Let |n| be the largest legal code value, based on |cur_chr|@>;
+ p:=cur_chr;
+ if cur_chr=math_code_base then begin
+ scan_char_num; p:= cur_val;
+ scan_optional_equals;
+ scan_int;
+ check_def_code(math_code_base);
+ if cur_val=@"8000 then cur_val:=@"8000000
+ else cur_val:=((cur_val div @"1000) * @"1000000) +
+ (((cur_val mod @"1000) div @"100) * @"10000) +
+ (cur_val mod @"100);
+ define_math_code(p,cur_val);
+ end
+ else if cur_chr=lc_code_base then begin
+ scan_char_num; p:= cur_val;
+ scan_optional_equals;
+ scan_int;
+ check_def_code(lc_code_base);
+ define_lc_code(p,cur_val);
+ end
+ else if cur_chr=uc_code_base then begin
+ scan_char_num; p:= cur_val;
+ scan_optional_equals;
+ scan_int;
+ check_def_code(uc_code_base);
+ define_uc_code(p,cur_val);
+ end
+ else if cur_chr=sf_code_base then begin
+ scan_char_num; p:= cur_val;
+ scan_optional_equals;
+ scan_int;
+ check_def_code(sf_code_base);
+ define_sf_code(p,cur_val);
+ end
+ else if cur_chr=cat_code_base then begin
+ scan_char_num; p:= cur_val;
+ scan_optional_equals;
+ scan_int;
+ check_def_code(cat_code_base);
+ define_cat_code(p,cur_val);
+ end
+ else if cur_chr=del_code_base then begin
+ scan_char_num; p:= cur_val;
+ scan_optional_equals;
+ scan_int;
+ check_def_code(del_code_base);
+ cur_val1:=cur_val div @"1000;
+ cur_val1:=(cur_val1 div @"100)*@"10000 + (cur_val1 mod @"100);
+ cur_val:=cur_val mod @"1000;
+ cur_val:=(cur_val div @"100)*@"10000 + (cur_val mod @"100);
+ define_del_code(p,cur_val1,cur_val);
+ end;
+ end;
+extdef_code: begin
+ if cur_chr=del_code_base then begin
+ p:=cur_chr; scan_char_num; p:=p+cur_val; scan_optional_equals;
+ scan_int; cur_val1:=cur_val; scan_int; {backwards}
+ if (cur_val1>@"FFFFFF) or (cur_val>@"FFFFFF) then
+ begin print_err("Invalid code ("); print_int(cur_val1); print(" ");
+ print_int(cur_val);
+ print("), should be at most ""FFFFFF ""FFFFFF");
+ help1("I'm going to use 0 instead of that illegal code value.");@/
+ error; cur_val1:=0; cur_val:=0;
+ end;
+ define_del_code(p,cur_val1,cur_val);
+ end
+ else begin
+ p:=cur_chr; scan_char_num; p:=cur_val; scan_optional_equals;
+ scan_int;
+ if (cur_val>@"8000000) then
+ begin print_err("Invalid code ("); print_int(cur_val);
+@.Invalid code@>
+ print("), should be at most "); print_int(@"8000000);
+ help1("I'm going to use 0 instead of that illegal code value.");@/
+ error; cur_val:=0;
+ end;
+ define_math_code(p,cur_val);
+ end;
+ end;
+
+@ @<Let |n| be the largest...@>=
+if cur_chr=cat_code_base then n:=max_char_code
+else if cur_chr=lc_code_base then n:=biggest_char
+else if cur_chr=uc_code_base then n:=biggest_char
+else if cur_chr=math_code_base then n:=@'100000
+else if cur_chr=sf_code_base then n:=@'77777
+else if cur_chr=del_code_base then n:=@'77777777
+else n:=biggest_char
+
+@ @<Assignments@>=
+def_family: begin p:=cur_chr; scan_math_family_int; p:=p+cur_val;
+ scan_optional_equals; scan_font_ident; define(p,data,cur_val);
+ end;
+
+@ Next we consider changes to \TeX's numeric registers.
+
+@<Assignments@>=
+register,advance,multiply,divide: do_register_command(a);
+
+@ We use the fact that |register<advance<multiply<divide|.
+
+@<Declare subprocedures for |prefixed_command|@>=
+procedure do_register_command(@!a:small_number);
+label found,exit;
+var l,@!q,@!r,@!s:pointer; {for list manipulation}
+@!p:int_val..mu_val; {type of register involved}
+begin q:=cur_cmd;
+@<Compute the register location |l| and its type |p|; but |return| if invalid@>;
+if q=register then scan_optional_equals
+else if scan_keyword("by") then do_nothing; {optional `\.{by}'}
+arith_error:=false;
+if q<multiply then @<Compute result of |register| or
+ |advance|, put it in |cur_val|@>
+else @<Compute result of |multiply| or |divide|, put it in |cur_val|@>;
+if arith_error then
+ begin print_err("Arithmetic overflow");
+@.Arithmetic overflow@>
+ help2("I can't carry out that multiplication or division,")@/
+ ("since the result is out of range.");
+ error; return;
+ end;
+if p<glue_val then begin
+ if p=attr_val then begin
+ if (l-attribute_base)>max_used_attr then max_used_attr:=(l-attribute_base);
+ attr_list_cache:=cache_disabled;
+ end;
+ word_define(l,cur_val);
+ end
+else begin trap_zero_glue; define(l,glue_ref,cur_val);
+ end;
+exit: end;
+
+@ Here we use the fact that the consecutive codes |int_val...mu_val| and
+|assign_int..assign_mu_glue| correspond to each other nicely.
+
+@<Compute the register location |l| and its type |p|...@>=
+begin l:=0;
+if q<>register then
+ begin get_x_token;
+ if (cur_cmd>=assign_int)and(cur_cmd<=assign_mu_glue) then
+ begin l:=cur_chr; p:=cur_cmd-assign_int; goto found;
+ end;
+ if cur_cmd<>register then
+ begin print_err("You can't use `"); print_cmd_chr(cur_cmd,cur_chr);
+@.You can't use x after ...@>
+ print("' after "); print_cmd_chr(q,0);
+ help1("I'm forgetting what you said and not changing anything.");
+ error; return;
+ end;
+ end;
+p:=cur_chr; scan_register_num;
+case p of
+int_val: l:=cur_val+count_base;
+attr_val: l:=cur_val+attribute_base;
+dimen_val: l:=cur_val+scaled_base;
+glue_val: l:=cur_val+skip_base;
+mu_val: l:=cur_val+mu_skip_base;
+end; {there are no other cases}
+end;
+found:
+
+@ @<Compute result of |register| or |advance|...@>=
+if p<glue_val then
+ begin if (p=int_val) or (p=attr_val) then scan_int@+else scan_normal_dimen;
+ if q=advance then cur_val:=cur_val+eqtb[l].int;
+ end
+else begin scan_glue(p);
+ if q=advance then @<Compute the sum of two glue specs@>;
+ end
+
+@ @<Compute the sum of two glue specs@>=
+begin q:=new_spec(cur_val); r:=equiv(l);
+delete_glue_ref(cur_val);
+width(q):=width(q)+width(r);
+if stretch(q)=0 then stretch_order(q):=normal;
+if stretch_order(q)=stretch_order(r) then stretch(q):=stretch(q)+stretch(r)
+else if (stretch_order(q)<stretch_order(r))and(stretch(r)<>0) then
+ begin stretch(q):=stretch(r); stretch_order(q):=stretch_order(r);
+ end;
+if shrink(q)=0 then shrink_order(q):=normal;
+if shrink_order(q)=shrink_order(r) then shrink(q):=shrink(q)+shrink(r)
+else if (shrink_order(q)<shrink_order(r))and(shrink(r)<>0) then
+ begin shrink(q):=shrink(r); shrink_order(q):=shrink_order(r);
+ end;
+cur_val:=q;
+end
+
+@ @<Compute result of |multiply| or |divide|...@>=
+begin scan_int;
+if p<glue_val then
+ if q=multiply then
+ if (p=int_val)or(p=attr_val) then cur_val:=mult_integers(eqtb[l].int,cur_val)
+ else cur_val:=nx_plus_y(eqtb[l].int,cur_val,0)
+ else cur_val:=x_over_n(eqtb[l].int,cur_val)
+else begin s:=equiv(l); r:=new_spec(s);
+ if q=multiply then
+ begin width(r):=nx_plus_y(width(s),cur_val,0);
+ stretch(r):=nx_plus_y(stretch(s),cur_val,0);
+ shrink(r):=nx_plus_y(shrink(s),cur_val,0);
+ end
+ else begin width(r):=x_over_n(width(s),cur_val);
+ stretch(r):=x_over_n(stretch(s),cur_val);
+ shrink(r):=x_over_n(shrink(s),cur_val);
+ end;
+ cur_val:=r;
+ end;
+end
+
+@ The processing of boxes is somewhat different, because we may need
+to scan and create an entire box before we actually change the value of the old
+one.
+
+@<Assignments@>=
+set_box: begin scan_register_num;
+ if global then n:=global_box_flag+cur_val@+else n:=box_flag+cur_val;
+ scan_optional_equals;
+ if set_box_allowed then scan_box(n)
+ else begin print_err("Improper "); print_esc("setbox");
+@.Improper \\setbox@>
+ help2("Sorry, \setbox is not allowed after \halign in a display,")@/
+ ("or between \accent and an accented character."); error;
+ end;
+ end;
+
+@ The |space_factor| or |prev_depth| settings are changed when a |set_aux|
+command is sensed. Similarly, |prev_graf| is changed in the presence of
+|set_prev_graf|, and |dead_cycles| or |insert_penalties| in the presence of
+|set_page_int|. These definitions are always global.
+
+When some dimension of a box register is changed, the change isn't exactly
+global; but \TeX\ does not look at the \.{\\global} switch.
+
+@<Assignments@>=
+set_aux:alter_aux;
+set_prev_graf:alter_prev_graf;
+set_page_dimen:alter_page_so_far;
+set_page_int:alter_integer;
+set_box_dimen:alter_box_dimen;
+
+@ @<Declare subprocedures for |prefixed_command|@>=
+procedure alter_aux;
+var c:halfword; {|hmode| or |vmode|}
+begin if cur_chr<>abs(mode) then report_illegal_case
+else begin c:=cur_chr; scan_optional_equals;
+ if c=vmode then
+ begin scan_normal_dimen; prev_depth:=cur_val;
+ end
+ else begin scan_int;
+ if (cur_val<=0)or(cur_val>32767) then
+ begin print_err("Bad space factor");
+@.Bad space factor@>
+ help1("I allow only values in the range 1..32767 here.");
+ int_error(cur_val);
+ end
+ else space_factor:=cur_val;
+ end;
+ end;
+end;
+
+@ @<Declare subprocedures for |prefixed_command|@>=
+procedure alter_prev_graf;
+var p:0..nest_size; {index into |nest|}
+begin nest[nest_ptr]:=cur_list; p:=nest_ptr;
+while abs(nest[p].mode_field)<>vmode do decr(p);
+scan_optional_equals; scan_int;
+if cur_val<0 then
+ begin print_err("Bad "); print_esc("prevgraf");
+@.Bad \\prevgraf@>
+ help1("I allow only nonnegative values here.");
+ int_error(cur_val);
+ end
+else begin nest[p].pg_field:=cur_val; cur_list:=nest[nest_ptr];
+ end;
+end;
+
+@ @<Declare subprocedures for |prefixed_command|@>=
+procedure alter_page_so_far;
+var c:0..7; {index into |page_so_far|}
+begin c:=cur_chr; scan_optional_equals; scan_normal_dimen;
+page_so_far[c]:=cur_val;
+end;
+
+@ @<Declare subprocedures for |prefixed_command|@>=
+procedure alter_integer;
+var c:small_number;
+ {0 for \.{\\deadcycles}, 1 for \.{\\insertpenalties}, etc.}
+begin c:=cur_chr; scan_optional_equals; scan_int;
+if c=0 then dead_cycles:=cur_val
+@/@<Cases for |alter_integer|@>@/
+else insert_penalties:=cur_val;
+end;
+
+@ @<Declare subprocedures for |prefixed_command|@>=
+procedure alter_box_dimen;
+var c:small_number; {|width_offset| or |height_offset| or |depth_offset|}
+@!b:eight_bits; {box number}
+begin c:=cur_chr; scan_register_num; b:=cur_val; scan_optional_equals;
+scan_normal_dimen;
+if box(b)<>null then vmem(box(b)+c).sc:=cur_val;
+end;
+
+@ Paragraph shapes are set up in an obvious way. It needs one word more than in
+\TeX, though.
+
+@d shape_node=54 { storage for shape pointers }
+
+@<Assignments@>=
+set_shape: begin q:=cur_chr; scan_optional_equals; scan_int; n:=cur_val;
+ if n<=0 then p:=null
+ else if q>par_shape_loc then
+ begin n:=(cur_val div 2)+1; p:=new_node(shape_node,2*n+1+1); vinfo(p+1):=n;
+ n:=cur_val; vmem(p+2).int:=n; {number of penalties}
+ for j:=p+3 to p+n+2 do
+ begin scan_int; vmem(j).int:=cur_val; {penalty values}
+ end;
+ if not odd(n) then vmem(p+n+3).int:=0; {unused}
+ end
+ else begin p:=new_node(shape_node,2*(n+1)+1); vinfo(p+1):=n;
+ for j:=1 to n do
+ begin scan_normal_dimen;
+ vmem(p+2*j).sc:=cur_val; {indentation}
+ scan_normal_dimen;
+ vmem(p+2*j+1).sc:=cur_val; {width}
+ end;
+ end;
+ define(q,shape_ref,p);
+ end;
+
+@ New language information data is loaded by the |hyph_data| command.
+
+@<Put each...@>=
+primitive("hyphenation",hyph_data,0);
+@!@:hyphenation_}{\.{\\hyphenation} primitive@>
+primitive("patterns",hyph_data,1);
+@!@:patterns_}{\.{\\patterns} primitive@>
+primitive("prehyphenchar",hyph_data,2);
+@!@:prehyphenchar_}{\.{\\prehyphenchar} primitive@>
+primitive("posthyphenchar",hyph_data,3);
+@!@:posthyphenchar_}{\.{\\posthyphenchar} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+hyph_data: case cur_chr of
+ 0: print_esc("hyphenation");
+ 1: print_esc("patterns");
+ 2: print_esc("prehyphenchar");
+ 3: print_esc("posthyphenchar");
+ endcases;
+
+@ @<Assignments@>=
+hyph_data: begin
+ case cur_chr of
+ 0: new_hyph_exceptions;
+ 1: new_patterns;
+ 2: new_pre_hyphen_char;
+ 3: new_post_hyphen_char;
+ endcases;
+ goto done;
+ end;
+
+@ All of \TeX's parameters are kept in |eqtb| except the font information,
+the interaction mode, and the hyphenation tables; these are strictly global.
+
+@<Assignments@>=
+assign_font_dimen: set_font_dimen;
+assign_font_int: begin
+ n:=cur_chr; scan_font_ident; f:=cur_val;
+ if n = no_lig_code then set_no_ligatures(f)
+ else if n < lp_code_base then begin
+ scan_optional_equals; scan_int;
+ if n=0 then set_hyphen_char(f,cur_val)@+else set_skew_char(f,cur_val);
+ end
+ else begin
+ scan_char_num; p := cur_val;
+ scan_optional_equals; scan_int;
+ case n of
+ lp_code_base: set_lp_code(f, p, cur_val);
+ rp_code_base: set_rp_code(f, p, cur_val);
+ ef_code_base: set_ef_code(f, p, cur_val);
+ tag_code: set_tag_code(f, p, cur_val);
+ end;
+ end;
+end;
+
+@ @<Put each...@>=
+primitive("hyphenchar",assign_font_int,0);
+@!@:hyphen_char_}{\.{\\hyphenchar} primitive@>
+primitive("skewchar",assign_font_int,1);
+@!@:skew_char_}{\.{\\skewchar} primitive@>
+primitive("lpcode",assign_font_int,lp_code_base);
+@!@:lp_code_}{\.{\\lpcode} primitive@>
+primitive("rpcode",assign_font_int,rp_code_base);
+@!@:rp_code_}{\.{\\rpcode} primitive@>
+primitive("efcode",assign_font_int,ef_code_base);
+@!@:ef_code_}{\.{\\efcode} primitive@>
+primitive("tagcode",assign_font_int,tag_code);
+@!@:tag_code_}{\.{\\tagcode} primitive@>
+primitive("pdfnoligatures",assign_font_int,no_lig_code);
+@!@:no_lig_code_}{\.{\\pdfnoligatures} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+assign_font_int: case chr_code of
+0: print_esc("hyphenchar");
+1: print_esc("skewchar");
+lp_code_base: print_esc("lpcode");
+rp_code_base: print_esc("rpcode");
+ef_code_base: print_esc("efcode");
+tag_code: print_esc("tagcode");
+no_lig_code: print_esc("pdfnoligatures");
+endcases;
+
+@ Here is where the information for a new font gets loaded.
+
+@<Assignments@>=
+def_font: def_new_font(a);
+letterspace_font: new_letterspaced_font(a);
+
+@ @<Declare subprocedures for |prefixed_command|@>=
+procedure def_new_font(@!a:small_number);
+var u:pointer; {user's font identifier}
+@!s:scaled; {stated ``at'' size, or negative of scaled magnification}
+@!f:internal_font_number; {runs through existing fonts}
+@!t:str_number; {name for the frozen font identifier}
+@!old_setting:0..max_selector; {holds |selector| setting}
+@!offset:integer;
+@!natural_dir:integer;{the natural direction of the font}
+@!flushable_string:str_number; {string not yet referenced}
+@!junk:pointer;
+begin if job_name=0 then open_log_file;
+ {avoid confusing \.{texput} with the font name}
+@.texput@>
+get_r_token; u:=cur_cs;
+if u>=hash_base then t:=text(u)
+else if u=null_cs then t:="FONT"
+else begin old_setting:=selector; selector:=new_string;
+ print("FONT"); print(u-active_base); selector:=old_setting;
+@.FONTx@>
+ str_room(1); t:=make_string;
+ end;
+define(u,set_font,null_font); scan_optional_equals;
+@<Get the next non-blank non-call token@>;
+if cur_cmd<>left_brace then begin
+ back_input;
+ scan_file_name;
+ end
+else begin
+ back_input;
+ junk:=scan_toks(false,true);
+ old_setting:=selector; selector:=new_string;
+ token_show(def_ref); selector:=old_setting;
+ flush_list(def_ref);
+ str_room(1);
+ cur_name:=make_string;
+ cur_ext:="";
+ cur_area:="";
+ end;
+@<Scan the font size specification@>;
+name_in_progress:=true;
+if scan_keyword("offset") then begin
+ scan_int;
+ offset:=cur_val;
+ if (cur_val<0) then begin
+ print_err("Illegal offset has been changed to 0");
+ help1("The offset must be bigger than 0."); int_error(cur_val);
+ offset:=0;
+ end
+ end
+else offset:=0;
+if scan_keyword("naturaldir") then begin
+ scan_direction;
+ natural_dir:=cur_val;
+ end
+else natural_dir:=-1;
+name_in_progress:=false;
+if cur_area = "" then
+ f:=read_font_info(u,cur_name,"",s,natural_dir)
+else
+ f:=read_font_info(u,cur_name,cur_area,s,natural_dir);
+equiv(u):=f; eqtb[font_id_base+f]:=eqtb[u]; font_id_text(f):=t;
+end;
+
+@ @<Scan the font size specification@>=
+name_in_progress:=true; {this keeps |cur_name| from being changed}
+if scan_keyword("at") then @<Put the \(p)(positive) `at' size into |s|@>
+@.at@>
+else if scan_keyword("scaled") then
+@.scaled@>
+ begin scan_int; s:=-cur_val;
+ if (cur_val<=0)or(cur_val>32768) then
+ begin print_err("Illegal magnification has been changed to 1000");@/
+@.Illegal magnification...@>
+ help1("The magnification ratio must be between 1 and 32768.");
+ int_error(cur_val); s:=-1000;
+ end;
+ end
+else s:=-1000;
+name_in_progress:=false
+
+@ @<Put the \(p)(positive) `at' size into |s|@>=
+begin scan_normal_dimen; s:=cur_val;
+if (s<=0)or(s>=@'1000000000) then
+ begin print_err("Improper `at' size (");
+ print_scaled(s); print("pt), replaced by 10pt");
+@.Improper `at' size...@>
+ help2("I can only handle fonts at positive sizes that are")@/
+ ("less than 2048pt, so I've changed what you said to 10pt.");
+ error; s:=10*unity;
+ end;
+end
+
+
+@ @<Cases of |print_cmd_chr|...@>=
+set_font:begin print("select font "); print_font_name(chr_code);
+ if font_size(chr_code)<>font_dsize(chr_code) then
+ begin print(" at "); print_scaled(font_size(chr_code));
+ print("pt");
+ end;
+ end;
+
+@ @<Put each...@>=
+primitive("batchmode",set_interaction,batch_mode);
+@!@:batch_mode_}{\.{\\batchmode} primitive@>
+primitive("nonstopmode",set_interaction,nonstop_mode);
+@!@:nonstop_mode_}{\.{\\nonstopmode} primitive@>
+primitive("scrollmode",set_interaction,scroll_mode);
+@!@:scroll_mode_}{\.{\\scrollmode} primitive@>
+primitive("errorstopmode",set_interaction,error_stop_mode);
+@!@:error_stop_mode_}{\.{\\errorstopmode} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+set_interaction: case chr_code of
+ batch_mode: print_esc("batchmode");
+ nonstop_mode: print_esc("nonstopmode");
+ scroll_mode: print_esc("scrollmode");
+ othercases print_esc("errorstopmode")
+ endcases;
+
+@ @<Assignments@>=
+set_interaction: new_interaction;
+
+@ @<Declare subprocedures for |prefixed_command|@>=
+procedure new_interaction;
+begin print_ln;
+interaction:=cur_chr;
+@<Initialize the print |selector| based on |interaction|@>;
+if log_opened then selector:=selector+2;
+end;
+
+@ The \.{\\afterassignment} command puts a token into the global
+variable |after_token|. This global variable is examined just after
+every assignment has been performed.
+
+@<Glob...@>=
+@!after_token:halfword; {zero, or a saved token}
+
+@ @<Set init...@>=
+after_token:=0;
+
+@ @<Cases of |main_control| that don't...@>=
+any_mode(after_assignment):begin get_token; after_token:=cur_tok;
+ end;
+
+@ @<Insert a token saved by \.{\\afterassignment}, if any@>=
+if after_token<>0 then
+ begin cur_tok:=after_token; back_input; after_token:=0;
+ end
+
+@ Here is a procedure that might be called `Get the next non-blank non-relax
+non-call non-assignment token'.
+
+@<Declare act...@>=
+procedure do_assignments;
+label exit;
+begin loop begin @<Get the next non-blank non-relax...@>;
+ if cur_cmd<=max_non_prefixed_command then return;
+ set_box_allowed:=false; prefixed_command; set_box_allowed:=true;
+ end;
+exit:end;
+
+@ @<Cases of |main_control| that don't...@>=
+any_mode(after_group):begin get_token; save_for_after(cur_tok);
+ end;
+
+@ Files for \.{\\read} are opened and closed by the |in_stream| command.
+
+@<Put each...@>=
+primitive("openin",in_stream,1);
+@!@:open_in_}{\.{\\openin} primitive@>
+primitive("closein",in_stream,0);
+@!@:close_in_}{\.{\\closein} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+in_stream: if chr_code=0 then print_esc("closein")
+ else print_esc("openin");
+
+@ @<Cases of |main_control| that don't...@>=
+any_mode(in_stream): open_or_close_in;
+
+@ @<Declare act...@>=
+procedure open_or_close_in;
+var c:0..1; {1 for \.{\\openin}, 0 for \.{\\closein}}
+@!n:0..15; {stream number}
+begin c:=cur_chr; scan_four_bit_int; n:=cur_val;
+if read_open[n]<>closed then
+ begin lua_a_close_in(read_file[n],(n+1)); read_open[n]:=closed;
+ end;
+if c<>0 then
+ begin scan_optional_equals; scan_file_name;
+ if cur_ext="" then cur_ext:=".tex";
+ pack_cur_name;
+ if lua_a_open_in(read_file[n],(n+1)) then begin
+ read_file[n]:= name_file_pointer;
+ read_open[n]:=just_open;
+ end;
+ end;
+end;
+
+@ The user can issue messages to the terminal, regardless of the
+current mode.
+
+@<Cases of |main_control| that don't...@>=
+any_mode(message):issue_message;
+
+@ @<Put each...@>=
+primitive("message",message,0);
+@!@:message_}{\.{\\message} primitive@>
+primitive("errmessage",message,1);
+@!@:err_message_}{\.{\\errmessage} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+message: if chr_code=0 then print_esc("message")
+ else print_esc("errmessage");
+
+@ @<Declare act...@>=
+procedure issue_message;
+var old_setting:0..max_selector; {holds |selector| setting}
+junk:pointer;
+@!c:0..1; {identifies \.{\\message} and \.{\\errmessage}}
+@!s:str_number; {the message}
+begin c:=cur_chr; junk:=scan_toks(false,true);
+old_setting:=selector; selector:=new_string;
+token_show(def_ref); selector:=old_setting;
+flush_list(def_ref);
+str_room(1); s:=make_string;
+if c=0 then @<Print string |s| on the terminal@>
+else @<Print string |s| as an error message@>;
+flush_string;
+end;
+
+@ @<Print string |s| on the terminal@>=
+begin if term_offset+length(s)>max_print_line-2 then print_ln
+else if (term_offset>0)or(file_offset>0) then print_char(" ");
+slow_print(s); update_terminal;
+end
+
+@ If \.{\\errmessage} occurs often in |scroll_mode|, without user-defined
+\.{\\errhelp}, we don't want to give a long help message each time. So we
+give a verbose explanation only once.
+
+@<Glob...@>=
+@!long_help_seen:boolean; {has the long \.{\\errmessage} help been used?}
+
+@ @<Set init...@>=long_help_seen:=false;
+
+@ @<Print string |s| as an error message@>=
+begin print_err(""); slow_print(s);
+if err_help<>null then use_err_help:=true
+else if long_help_seen then help1("(That was another \errmessage.)")
+else begin if interaction<error_stop_mode then long_help_seen:=true;
+ help4("This error message was generated by an \errmessage")@/
+ ("command, so I can't give any explicit help.")@/
+ ("Pretend that you're Hercule Poirot: Examine all clues,")@/
+@^Poirot, Hercule@>
+ ("and deduce the truth by order and method.");
+ end;
+error; use_err_help:=false;
+end
+
+@ The |error| routine calls on |give_err_help| if help is requested from
+the |err_help| parameter.
+
+@p procedure give_err_help;
+begin token_show(err_help);
+end;
+
+@ The \.{\\uppercase} and \.{\\lowercase} commands are implemented by
+building a token list and then changing the cases of the letters in it.
+
+@<Cases of |main_control| that don't...@>=
+any_mode(case_shift):shift_case;
+
+@ @<Put each...@>=
+primitive("lowercase",case_shift,lc_code_base);
+@!@:lowercase_}{\.{\\lowercase} primitive@>
+primitive("uppercase",case_shift,uc_code_base);
+@!@:uppercase_}{\.{\\uppercase} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+case_shift:if chr_code=lc_code_base then print_esc("lowercase")
+ else print_esc("uppercase");
+
+@ @<Declare act...@>=
+procedure shift_case;
+var b:pointer; {|lc_code_base| or |uc_code_base|}
+@!p:pointer; {runs through the token list}
+@!t:halfword; {token}
+@!c:halfword; {character code}
+@!i:halfword; {inbetween}
+begin b:=cur_chr; p:=scan_toks(false,false); p:=link(def_ref);
+while p<>null do
+ begin @<Change the case of the token in |p|, if a change is appropriate@>;
+ p:=link(p);
+ end;
+back_list(link(def_ref)); free_avail(def_ref); {omit reference count}
+end;
+
+@ When the case of a |chr_code| changes, we don't change the |cmd|.
+We also change active characters, using the fact that
+|cs_token_flag+active_base| is a multiple of~|string_offset|.
+@^data structure assumptions@>
+
+@<Change the case of the token in |p|, if a change is appropriate@>=
+t:=info(p);
+if t<cs_token_flag+null_cs then
+ begin
+ c:=t mod string_offset;
+ if b=uc_code_base then begin
+ i:=get_uc_code(c);
+ if i<>0 then info(p):=t-c+i;
+ end
+ else
+ begin if get_lc_code(c)<>0 then info(p):=t-c+get_lc_code(c); end;
+ end
+
+@ We come finally to the last pieces missing from |main_control|, namely the
+`\.{\\show}' commands that are useful when debugging.
+
+@<Cases of |main_control| that don't...@>=
+any_mode(xray): show_whatever;
+
+@ @d show_code=0 { \.{\\show} }
+@d show_box_code=1 { \.{\\showbox} }
+@d show_the_code=2 { \.{\\showthe} }
+@d show_lists=3 { \.{\\showlists} }
+
+@<Put each...@>=
+primitive("show",xray,show_code);
+@!@:show_}{\.{\\show} primitive@>
+primitive("showbox",xray,show_box_code);
+@!@:show_box_}{\.{\\showbox} primitive@>
+primitive("showthe",xray,show_the_code);
+@!@:show_the_}{\.{\\showthe} primitive@>
+primitive("showlists",xray,show_lists);
+@!@:show_lists_}{\.{\\showlists} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+xray: case chr_code of
+ show_box_code:print_esc("showbox");
+ show_the_code:print_esc("showthe");
+ show_lists:print_esc("showlists");
+ @<Cases of |xray| for |print_cmd_chr|@>@;@/
+ othercases print_esc("show")
+ endcases;
+
+@ @<Declare act...@>=
+procedure show_whatever;
+label common_ending;
+var p:pointer; {tail of a token list to show}
+@!t:small_number; {type of conditional being shown}
+@!m:normal..or_code; {upper bound on |fi_or_else| codes}
+@!l:integer; {line where that conditional began}
+@!n:integer; {level of \.{\\if...\\fi} nesting}
+begin case cur_chr of
+show_lists: begin begin_diagnostic; show_activities;
+ end;
+show_box_code: @<Show the current contents of a box@>;
+show_code: @<Show the current meaning of a token, then |goto common_ending|@>;
+@<Cases for |show_whatever|@>@;@/
+othercases @<Show the current value of some parameter or register,
+ then |goto common_ending|@>
+endcases;@/
+@<Complete a potentially long \.{\\show} command@>;
+common_ending: if interaction<error_stop_mode then
+ begin help0; decr(error_count);
+ end
+else if tracing_online>0 then
+ begin@t@>@;@/
+ help3("This isn't an error message; I'm just \showing something.")@/
+ ("Type `I\show...' to show more (e.g., \show\cs,")@/
+ ("\showthe\count10, \showbox255, \showlists).");
+ end
+else begin@t@>@;@/
+ help5("This isn't an error message; I'm just \showing something.")@/
+ ("Type `I\show...' to show more (e.g., \show\cs,")@/
+ ("\showthe\count10, \showbox255, \showlists).")@/
+ ("And type `I\tracingonline=1\show...' to show boxes and")@/
+ ("lists on your terminal as well as in the transcript file.");
+ end;
+error;
+end;
+
+@ @<Show the current meaning of a token...@>=
+begin get_token;
+if interaction=error_stop_mode then wake_up_terminal;
+print_nl("> ");
+if cur_cs<>0 then
+ begin sprint_cs(cur_cs); print_char("=");
+ end;
+print_meaning; goto common_ending;
+end
+
+@ @<Cases of |print_cmd_chr|...@>=
+undefined_cs: print("undefined");
+call,long_call,outer_call,long_outer_call: begin n:=cmd-call;
+ if info(link(chr_code))=protected_token then n:=n+4;
+ if odd(n div 4) then print_esc("protected");
+ if odd(n) then print_esc("long");
+ if odd(n div 2) then print_esc("outer");
+ if n>0 then print_char(" ");
+ print("macro");
+ end;
+end_template: print_esc("outer endtemplate");
+
+@ @<Show the current contents of a box@>=
+begin scan_register_num; begin_diagnostic;
+print_nl("> \box"); print_int(cur_val); print_char("=");
+if box(cur_val)=null then print("void")
+else show_box(box(cur_val));
+end
+
+@ @<Show the current value of some parameter...@>=
+begin p:=the_toks;
+if interaction=error_stop_mode then wake_up_terminal;
+print_nl("> "); token_show(temp_token_head);
+flush_list(link(temp_token_head)); goto common_ending;
+end
+
+@ @<Complete a potentially long \.{\\show} command@>=
+end_diagnostic(true); print_err("OK");
+@.OK@>
+if selector=term_and_log then if tracing_online<=0 then
+ begin selector:=term_only; print(" (see the transcript file)");
+ selector:=term_and_log;
+ end
+
+@* \[50] Dumping and undumping the tables.
+After \.{INITEX} has seen a collection of fonts and macros, it
+can write all the necessary information on an auxiliary file so
+that production versions of \TeX\ are able to initialize their
+memory at high speed. The present section of the program takes
+care of such output and input. We shall consider simultaneously
+the processes of storing and restoring,
+so that the inverse relation between them is clear.
+@.INITEX@>
+
+The global variable |format_ident| is a string that is printed right
+after the |banner| line when \TeX\ is ready to start. For \.{INITEX} this
+string says simply `\.{(INITEX)}'; for other versions of \TeX\ it says,
+for example, `\.{(preloaded format=plain 82.11.19)}', showing the year,
+month, and day that the format file was created. We have |format_ident=0|
+before \TeX's tables are loaded.
+
+@<Glob...@>=
+@!format_ident:str_number;
+@!format_name:str_number; {principal file name}
+
+@ @<Set init...@>=
+format_ident:=0;
+format_name:="";
+
+@ @<Initialize table entries...@>=
+format_ident:=" (INITEX)";
+
+@ @<Declare act...@>=
+@!init procedure store_fmt_file;
+label found1,found2,done1,done2;
+var j,@!k,@!l:integer; {all-purpose indices}
+@!p: pointer; {all-purpose pointer}
+@!x: integer; {something to dump}
+@!w: four_quarters; {four ASCII codes}
+begin @<If dumping is not allowed, abort@>;
+@<Create the |format_ident|, open the format file,
+ and inform the user that dumping has begun@>;
+@<Dump constants for consistency check@>;
+@<Dump the string pool@>;
+@<Dump the dynamic memory@>;
+@<Dump the table of equivalents@>;
+@<Dump the font information@>;
+@<Dump the active ocp information@>;
+@<Dump the ocp information@>;
+@<Dump the ocp list information@>;
+@<Dump the hyphenation tables@>;
+@<Dump a couple more things and the closing check word@>;
+@<Dump the lua bytecodes@>;
+@<Close the format file@>;
+end;
+tini
+
+@ Corresponding to the procedure that dumps a format file, we have a function
+that reads one in. The function returns |false| if the dumped format is
+incompatible with the present \TeX\ table sizes, etc.
+
+@d bad_fmt=6666 {go here if the format file is unacceptable}
+@d too_small(#)==begin wake_up_terminal;
+ wterm_ln('---! Must increase the ',#);
+@.Must increase the x@>
+ goto bad_fmt;
+ end
+
+@p @t\4@>@<Declare the function called |open_fmt_file|@>@;
+function load_fmt_file:boolean;
+label bad_fmt,exit;
+var j,@!k:integer; {all-purpose indices}
+@!p: pointer; {all-purpose pointer}
+@!x: integer; {something undumped}
+@!w: four_quarters; {four ASCII codes}
+begin @<Undump constants for consistency check@>;
+@<Undump the string pool@>;
+@<Undump the dynamic memory@>;
+@<Undump the table of equivalents@>;
+@<Undump the font information@>;
+@<Undump the active ocp information@>;
+@<Undump the ocp information@>;
+@<Undump the ocp list information@>;
+@<Undump the hyphenation tables@>;
+@<Undump a couple more things and the closing check word@>;
+@<Undump the lua bytecodes@>;
+load_fmt_file:=true; return; {it worked!}
+bad_fmt: wake_up_terminal;
+ wterm_ln('(Fatal format file error; I''m stymied)');
+@.Fatal format file error@>
+load_fmt_file:=false;
+exit:end;
+
+@ The user is not allowed to dump a format file unless |save_ptr=0|.
+This condition implies that |cur_level=level_one|, hence
+the |xeq_level| array is constant and it need not be dumped.
+
+@<If dumping is not allowed, abort@>=
+if save_ptr<>0 then
+ begin print_err("You can't dump inside a group");
+@.You can't dump...@>
+ help1("`{...\dump}' is a no-no."); succumb;
+ end
+
+@ Format files consist of |memory_word| items, and we use the following
+macros to dump words of different types:
+
+@d dump_wd(#)==begin fmt_file^:=#; put(fmt_file);@+end
+@d dump_int(#)==begin fmt_file^.int:=#; put(fmt_file);@+end
+@d dump_hh(#)==begin fmt_file^.hh:=#; put(fmt_file);@+end
+@d dump_qqqq(#)==begin fmt_file^.qqqq:=#; put(fmt_file);@+end
+
+@<Glob...@>=
+@!fmt_file:word_file; {for input or output of format information}
+
+@ The inverse macros are slightly more complicated, since we need to check
+the range of the values we are reading in. We say `|undump(a)(b)(x)|' to
+read an integer value |x| that is supposed to be in the range |a<=x<=b|.
+
+@d undump_wd(#)==begin get(fmt_file); #:=fmt_file^;@+end
+@d undump_int(#)==begin get(fmt_file); #:=fmt_file^.int;@+end
+@d undump_hh(#)==begin get(fmt_file); #:=fmt_file^.hh;@+end
+@d undump_qqqq(#)==begin get(fmt_file); #:=fmt_file^.qqqq;@+end
+@d undump_end_end(#)==#:=x;@+end
+@d undump_end(#)==(x>#) then goto bad_fmt@+else undump_end_end
+@d undump(#)==begin undump_int(x); if (x<#) or undump_end
+@d undump_size_end_end(#)==too_small(#)@+else undump_end_end
+@d undump_size_end(#)==if x># then undump_size_end_end
+@d undump_size(#)==begin undump_int(x);
+ if x<# then goto bad_fmt; undump_size_end
+
+@ The next few sections of the program should make it clear how we use the
+dump/undump macros.
+
+@<Dump constants for consistency check@>=
+dump_int(@$);@/
+dump_int(eqtb_size);@/
+dump_int(hash_prime)
+
+@ Sections of a \.{WEB} program that are ``commented out'' still contribute
+strings to the string pool; therefore \.{INITEX} and \TeX\ will have
+the same strings. (And it is, of course, a good thing that they do.)
+@.WEB@>
+@^string pool@>
+
+@<Undump constants for consistency check@>=
+x:=fmt_file^.int;
+if x<>@$ then goto bad_fmt; {check that strings are the same}
+undump_int(x);@/
+if x<>eqtb_size then goto bad_fmt;
+undump_int(x);
+if x<>hash_prime then goto bad_fmt
+
+@ @d dump_four_ASCII==
+ w.b0:=qi(so(str_pool[k])); w.b1:=qi(so(str_pool[k+1]));
+ w.b2:=qi(so(str_pool[k+2])); w.b3:=qi(so(str_pool[k+3]));
+ dump_qqqq(w)
+
+@<Dump the string pool@>=
+dump_int(pool_ptr);
+dump_int(str_ptr);
+for k:=string_offset to str_ptr do dump_int(str_start_macro(k));
+k:=0;
+while k+4<pool_ptr do
+ begin dump_four_ASCII; k:=k+4;
+ end;
+k:=pool_ptr-4; dump_four_ASCII;
+print_ln; print_int(str_ptr-string_offset); print(" strings of total length ");
+print_int(pool_ptr)
+
+@ @d undump_four_ASCII==
+ undump_qqqq(w);
+ str_pool[k]:=si(qo(w.b0)); str_pool[k+1]:=si(qo(w.b1));
+ str_pool[k+2]:=si(qo(w.b2)); str_pool[k+3]:=si(qo(w.b3))
+
+@<Undump the string pool@>=
+undump_size(0)(pool_size)('string pool size')(pool_ptr);
+undump_size(0)(max_strings)('max strings')(str_ptr);
+for k:=string_offset to str_ptr do undump(0)(pool_ptr)(str_start_macro(k));
+k:=0;
+while k+4<pool_ptr do
+ begin undump_four_ASCII; k:=k+4;
+ end;
+k:=pool_ptr-4; undump_four_ASCII;
+init_str_ptr:=str_ptr; init_pool_ptr:=pool_ptr
+
+@ By sorting the list of available spaces in the variable-size portion of
+|mem|, we are usually able to get by without having to dump very much
+of the dynamic memory.
+
+We recompute |var_used| and |dyn_used|, so that \.{INITEX} dumps valid
+information even when it has not been gathering statistics.
+
+@<Dump the dynamic memory@>=
+dump_node_mem;
+@#
+dump_int(temp_token_head); dump_int(hold_token_head);
+dump_int(omit_template); dump_int(null_list);
+dump_int(backup_head); dump_int(garbage);
+dump_int(fix_mem_min); dump_int(fix_mem_max);
+dump_int(fix_mem_end);
+dump_int(avail);
+dyn_used:=fix_mem_end+1;
+for k:=fix_mem_min to fix_mem_end do dump_wd(mem(k));
+x:=x+(fix_mem_end+1-fix_mem_min);
+p:=avail;
+while p<>null do
+ begin decr(dyn_used); p:=link(p);
+ end;
+dump_int(dyn_used);
+print_ln; print_int(x);
+print(" memory locations dumped; current usage is ");
+print_int(var_used); print_char("&"); print_int(dyn_used)
+
+@ @<Undump the dynamic memory@>=
+undump_node_mem;
+@#
+undump_int(temp_token_head); undump_int(hold_token_head);
+undump_int(omit_template); undump_int(null_list);
+undump_int(backup_head); undump_int(garbage);
+undump_int(fix_mem_min);undump_int(fix_mem_max);
+fixmem:= xmallocarray (smemory_word, fix_mem_max+1);
+memset (voidcast(fixmem),0,(fix_mem_max+1)*sizeof(smemory_word));
+undump_int(fix_mem_end);
+undump_int(avail);
+for k:=fix_mem_min to fix_mem_end do undump_wd(mem(k));
+undump_int(dyn_used)
+
+@ @<Dump the table of equivalents@>=
+@<Dump regions 1 to 4 of |eqtb|@>;
+@<Dump regions 5 and 6 of |eqtb|@>;
+dump_int(par_loc); dump_int(write_loc);@/
+dump_math_codes;
+dump_text_codes;
+@<Dump the hash table@>
+
+@ @<Undump the table of equivalents@>=
+@<Undump regions 1 to 6 of |eqtb|@>;
+undump(hash_base)(frozen_control_sequence)(par_loc);
+par_token:=cs_token_flag+par_loc;@/
+undump(hash_base)(frozen_control_sequence)(write_loc);@/
+undump_math_codes;
+undump_text_codes;
+@<Undump the hash table@>
+
+@ The table of equivalents usually contains repeated information, so we dump it
+in compressed form: The sequence of $n+2$ values $(n,x_1,\ldots,x_n,m)$ in the
+format file represents $n+m$ consecutive entries of |eqtb|, with |m| extra
+copies of $x_n$, namely $(x_1,\ldots,x_n,x_n,\ldots,x_n)$.
+
+@<Dump regions 1 to 4 of |eqtb|@>=
+k:=active_base;
+repeat j:=k;
+while j<int_base-1 do
+ begin if (equiv(j)=equiv(j+1))and(eq_type(j)=eq_type(j+1))and@|
+ (eq_level(j)=eq_level(j+1)) then goto found1;
+ incr(j);
+ end;
+l:=int_base; goto done1; {|j=int_base-1|}
+found1: incr(j); l:=j;
+while j<int_base-1 do
+ begin if (equiv(j)<>equiv(j+1))or(eq_type(j)<>eq_type(j+1))or@|
+ (eq_level(j)<>eq_level(j+1)) then goto done1;
+ incr(j);
+ end;
+done1:
+dump_int(l-k);
+while k<l do
+ begin dump_wd(eqtb[k]); incr(k);
+ end;
+k:=j+1; dump_int(k-l);
+until k=int_base
+
+@ @<Dump regions 5 and 6 of |eqtb|@>=
+repeat j:=k;
+while j<eqtb_size do
+ begin if eqtb[j].int=eqtb[j+1].int then goto found2;
+ incr(j);
+ end;
+l:=eqtb_size+1; goto done2; {|j=eqtb_size|}
+found2: incr(j); l:=j;
+while j<eqtb_size do
+ begin if eqtb[j].int<>eqtb[j+1].int then goto done2;
+ incr(j);
+ end;
+done2:dump_int(l-k);
+while k<l do
+ begin dump_wd(eqtb[k]); incr(k);
+ end;
+k:=j+1; dump_int(k-l);
+until k>eqtb_size
+
+@ @<Undump regions 1 to 6 of |eqtb|@>=
+k:=active_base;
+repeat undump_int(x);
+if (x<1)or(k+x>eqtb_size+1) then goto bad_fmt;
+for j:=k to k+x-1 do undump_wd(eqtb[j]);
+k:=k+x;
+undump_int(x);
+if (x<0)or(k+x>eqtb_size+1) then goto bad_fmt;
+for j:=k to k+x-1 do eqtb[j]:=eqtb[k-1];
+k:=k+x;
+until k>eqtb_size
+
+@ A different scheme is used to compress the hash table, since its lower
+region is usually sparse. When |text(p)<>0| for |p<=hash_used|, we output
+two words, |p| and |hash[p]|. The hash table is, of course, densely packed
+for |p>=hash_used|, so the remaining entries are output in a~block.
+
+@<Dump the hash table@>=
+for p:=0 to prim_size do dump_hh(prim[p]);
+for p:=0 to prim_size do dump_wd(prim_eqtb[p]);
+dump_int(hash_used); cs_count:=frozen_control_sequence-1-hash_used;
+for p:=hash_base to hash_used do if text(p)<>0 then
+ begin dump_int(p); dump_hh(hash[p]); incr(cs_count);
+ end;
+for p:=hash_used+1 to undefined_control_sequence-1 do dump_hh(hash[p]);
+dump_int(cs_count);@/
+print_ln; print_int(cs_count); print(" multiletter control sequences")
+
+@ @<Undump the hash table@>=
+for p:=0 to prim_size do undump_hh(prim[p]);
+for p:=0 to prim_size do undump_wd(prim_eqtb[p]);
+undump(hash_base)(frozen_control_sequence)(hash_used); p:=hash_base-1;
+repeat undump(p+1)(hash_used)(p); undump_hh(hash[p]);
+until p=hash_used;
+for p:=hash_used+1 to undefined_control_sequence-1 do undump_hh(hash[p]);
+undump_int(cs_count)
+
+@ @<Dump the font information@>=
+dump_int(max_font_id);
+for k:=0 to max_font_id do
+ @<Dump the array info for internal font number |k|@>;
+print_ln; print_int(max_font_id); print(" preloaded font");
+if max_font_id<>1 then print_char("s")
+
+@ @<Undump the font information@>=
+undump_int(x);
+set_max_font_id(x);
+for k:=0 to max_font_id do
+ @<Undump the array info for internal font number |k|@>
+
+@ @<Dump the array info for internal font number |k|@>=
+begin dump_font(k);
+print_nl("\font"); print_esc(font_id_text(k)); print_char("=");
+print_file_name(tex_font_name(k),tex_font_area(k),"");
+flush_string; flush_string;
+if font_size(k)<>font_dsize(k) then
+ begin print(" at "); print_scaled(font_size(k)); print("pt");
+ end;
+end
+
+@ @<Undump the array info for internal font number |k|@>=
+begin undump_font(k);@/
+end
+
+@ @<Dump the active ocp information@>=
+dump_int(active_min_ptr);
+dump_int(active_max_ptr);
+for k:=0 to active_max_ptr-1 do dump_wd(active_info[k]);
+if active_max_ptr>0 then begin
+ print_ln; print_int(active_max_ptr); print(" words of active ocps");
+ end;
+
+@ @<Undump the active ocp information@>=
+undump_size(0)(active_mem_size)('active start point')(active_min_ptr);
+undump_size(0)(active_mem_size)('active mem size')(active_max_ptr);
+for k:=0 to active_max_ptr-1 do undump_wd(active_info[k]);
+
+@ @<Dump the ocp information@>=
+dump_int(ocp_ptr);
+for k:=null_ocp to ocp_ptr do
+ @<Dump the array info for internal ocp number |k|@>;
+if ocp_ptr-ocp_base>0 then begin
+ print_ln; print_int(ocp_ptr-ocp_base); print(" preloaded ocp");
+ if ocp_ptr<>ocp_base+1 then print_char("s");
+ end
+
+@ @<Undump the ocp information@>=
+undump_size(ocp_base)(ocp_biggest)('ocp max')(ocp_ptr);
+for k:=null_ocp to ocp_ptr do
+ @<Undump the array info for internal ocp number |k|@>
+
+@ @<Dump the array info for internal ocp number |k|@>=
+begin dump_ocp_table(k);
+if ocp_ptr-ocp_base>0 then begin
+ print_nl("\ocp"); print_esc(ocp_id_text(k)); print_char("=");
+ print_file_name(ocp_name(k),ocp_area(k),"");
+ end;
+end
+
+@ @<Undump the array info for internal ocp number |k|@>=
+begin undump_ocp_table(k);
+end
+
+@ @<Dump the ocp list information@>=
+dump_int(ocp_listmem_ptr);
+for k:=0 to ocp_listmem_ptr-1 do dump_wd(ocp_list_info[k]);
+dump_int(ocp_list_ptr);
+for k:=null_ocp_list to ocp_list_ptr do begin
+ dump_int(ocp_list_list[k]);
+ if null_ocp_list<>ocp_list_ptr then begin
+ print_nl("\ocplist");
+ print_esc(ocp_list_id_text(k));
+ print_char("=");
+ print_ocp_list(ocp_list_list[k]);
+ end;
+ end;
+dump_int(ocp_lstackmem_ptr);
+for k:=0 to ocp_lstackmem_ptr-1 do dump_wd(ocp_lstack_info[k])
+
+@ @<Undump the ocp list information@>=
+undump_size(1)(1000000)('ocp list mem size')(ocp_listmem_ptr);
+for k:=0 to ocp_listmem_ptr-1 do undump_wd(ocp_list_info[k]);
+undump_size(ocp_list_base)(ocp_list_biggest)('ocp list max')(ocp_list_ptr);
+for k:=null_ocp_list to ocp_list_ptr do
+ undump_int(ocp_list_list[k]);
+undump_size(1)(1000000)('ocp lstack mem size')(ocp_lstackmem_ptr);
+for k:=0 to ocp_lstackmem_ptr-1 do undump_wd(ocp_lstack_info[k])
+
+@ This is done in C
+
+@<Dump the hyphenation tables@>=
+dump_language_data
+
+@ @<Undump the hyphenation tables@>=
+undump_language_data
+
+@ This is also done in C
+
+@<Dump the lua bytecodes@>=
+dump_luac_registers;
+
+@ @<Undump the lua bytecodes@>=
+undump_luac_registers;
+
+@ We have already printed a lot of statistics, so we set |tracing_stats:=0|
+to prevent them from appearing again.
+
+@<Dump a couple more things and the closing check word@>=
+dump_int(interaction); dump_int(format_ident); dump_int(format_name); dump_int(69069);
+tracing_stats:=0
+
+@ @<Undump a couple more things and the closing check word@>=
+undump(batch_mode)(error_stop_mode)(interaction);
+undump(0)(str_ptr)(format_ident);
+undump(0)(str_ptr)(format_name);
+undump_int(x);
+if (x<>69069)or eof(fmt_file) then goto bad_fmt
+
+@ @<Create the |format_ident|...@>=
+selector:=new_string;
+print(" (preloaded format="); print(job_name); print_char(" ");
+print_int(year); print_char(".");
+print_int(month); print_char("."); print_int(day); print_char(")");
+str_room(2);
+format_ident:=make_string;
+print(job_name);
+format_name:=make_string;
+if interaction=batch_mode then selector:=log_only
+else selector:=term_and_log;
+pack_job_name(format_extension);
+while not w_open_out(fmt_file) do
+ prompt_file_name("format file name",format_extension);
+print_nl("Beginning to dump on file ");
+@.Beginning to dump...@>
+slow_print(w_make_name_string(fmt_file)); flush_string;
+print_nl(""); slow_print(format_ident)
+
+@ @<Close the format file@>=
+w_close(fmt_file)
+
+@* \[51] The main program.
+This is it: the part of \TeX\ that executes all those procedures we have
+written.
+
+Well---almost. Let's leave space for a few more routines that we may
+have forgotten.
+
+@p @<Last-minute procedures@>
+
+@ We have noted that there are two versions of \TeX82. One, called \.{INITEX},
+@.INITEX@>
+has to be run first; it initializes everything from scratch, without
+reading a format file, and it has the capability of dumping a format file.
+The other one is called `\.{VIRTEX}'; it is a ``virgin'' program that needs
+@.VIRTEX@>
+to input a format file in order to get started. \.{VIRTEX} typically has
+more memory capacity than \.{INITEX}, because it does not need the space
+consumed by the auxiliary hyphenation tables and the numerous calls on
+|primitive|, etc.
+
+The \.{VIRTEX} program cannot read a format file instantaneously, of course;
+the best implementations therefore allow for production versions of \TeX\ that
+not only avoid the loading routine for \PASCAL\ object code, they also have
+a format file pre-loaded. This is impossible to do if we stick to standard
+\PASCAL; but there is a simple way to fool many systems into avoiding the
+initialization, as follows:\quad(1)~We declare a global integer variable
+called |ready_already|. The probability is negligible that this
+variable holds any particular value like 314159 when \.{VIRTEX} is first
+loaded.\quad(2)~After we have read in a format file and initialized
+everything, we set |ready_already:=314159|.\quad(3)~Soon \.{VIRTEX}
+will print `\.*', waiting for more input; and at this point we
+interrupt the program and save its core image in some form that the
+operating system can reload speedily.\quad(4)~When that core image is
+activated, the program starts again at the beginning; but now
+|ready_already=314159| and all the other global variables have
+their initial values too. The former chastity has vanished!
+
+In other words, if we allow ourselves to test the condition
+|ready_already=314159|, before |ready_already| has been
+assigned a value, we can avoid the lengthy initialization. Dirty tricks
+rarely pay off so handsomely.
+@^dirty \PASCAL@>
+@^system dependencies@>
+
+On systems that allow such preloading, the standard program called \.{TeX}
+should be the one that has \.{plain} format preloaded, since that agrees
+with {\sl The \TeX book}. Other versions, e.g., \.{AmSTeX}, should also
+@:TeXbook}{\sl The \TeX book@>
+@.AmSTeX@>
+@.plain@>
+be provided for commonly used formats.
+
+@<Glob...@>=
+@!ready_already:integer; {a sacrifice of purity for economy}
+
+@ Now this is really it: \TeX\ starts and ends here.
+
+The initial test involving |ready_already| should be deleted if the
+\PASCAL\ runtime system is smart enough to detect such a ``mistake.''
+@^system dependencies@>
+
+@p begin @!{|start_here|}
+history:=fatal_error_stop; {in case we quit during initialization}
+t_open_out; {open the terminal for output}
+if ready_already=314159 then goto start_of_TEX;
+@<Check the ``constant'' values...@>@;
+if bad>0 then
+ begin wterm_ln('Ouch---my internal constants have been clobbered!',
+ '---case ',bad:1);
+@.Ouch...clobbered@>
+ goto final_end;
+ end;
+initialize; {set global variables to their starting values}
+@!init if not get_strings_started then goto final_end;
+init_prim; {call |primitive| for each primitive}
+init_str_ptr:=str_ptr; init_pool_ptr:=pool_ptr; fix_date_and_time;
+tini@/
+ready_already:=314159;
+start_of_TEX: @<Initialize the output routines@>;
+@<Get the first line of input and prepare to start@>;
+history:=spotless; {ready to go!}
+main_control; {come to life}
+final_cleanup; {prepare for death}
+end_of_TEX: close_files_and_terminate;
+final_end: ready_already:=0;
+end.
+
+@ Put this in a function because two extra variables are needed
+for callback testing, and putting those inside the main body is
+ugly
+
+@<Basic print...@>=
+procedure print_banner;
+var res:boolean;
+ callback_id:integer;
+begin
+callback_id:=callback_defined(start_run_callback);
+if callback_id=0 then begin
+ wterm(banner);
+ if format_ident=0 then wterm_ln(' (no format preloaded)')
+ else begin slow_print(format_ident); print_ln;
+ end;
+ end
+else
+ res:= run_callback(callback_id,'->');
+update_terminal;
+end;
+@#
+procedure print_version_banner;
+begin
+wterm(banner);
+end;
+
+
+@ Here we do whatever is needed to complete \TeX's job gracefully on the
+local operating system. The code here might come into play after a fatal
+error; it must therefore consist entirely of ``safe'' operations that
+cannot produce error messages. For example, it would be a mistake to call
+|str_room| or |make_string| at this time, because a call on |overflow|
+might lead to an infinite loop.
+@^system dependencies@>
+
+Actually there's one way to get error messages, via |prepare_mag|;
+but that can't cause infinite recursion.
+@^recursion@>
+
+This program doesn't bother to close the input files that may still be open.
+
+@<Last-minute...@>=
+procedure close_files_and_terminate;
+label done, done1;
+var a, b, c, i, j, k, l: integer; {all-purpose index}
+ is_root: boolean; {|pdf_last_pages| is root of Pages tree?}
+ is_names: boolean; {flag for name tree output: is it Names or Kids?}
+ root, outlines, threads, names_tree, dests: integer;
+ xref_offset_width, names_head, names_tail: integer;
+ callback_id:integer;
+ res:boolean;
+begin
+callback_id:=callback_defined(stop_run_callback);
+@<Finish the extensions@>;
+@!stat if tracing_stats>0 then
+ if callback_id=0 then @<Output statistics about this job@>;@;@+tats@/
+wake_up_terminal;
+if not fixed_pdfoutput_set then
+ fix_pdfoutput;
+if fixed_pdfoutput > 0 then begin
+ if history = fatal_error_stop then begin
+ remove_pdffile;
+ print_err(" ==> Fatal error occurred, no output PDF file produced!")
+ end
+ else begin
+ @<Finish the PDF file@>;
+ if callback_id=0 then begin
+ if log_opened then
+ begin wlog_cr;
+ wlog_ln('PDF statistics:');
+ wlog_ln(' ',obj_ptr:1,' PDF objects out of ',obj_tab_size:1,
+ ' (max. ',sup_obj_tab_size:1,')');
+ if pdf_os_cntr > 0 then begin
+ wlog(' ',((pdf_os_cntr - 1) * pdf_os_max_objs + pdf_os_objidx + 1):1,
+ ' compressed objects within ',pdf_os_cntr:1,' object stream');
+ if pdf_os_cntr > 1 then
+ wlog('s');
+ wlog_cr;
+ end;
+ wlog_ln(' ',pdf_dest_names_ptr:1,' named destinations out of ',dest_names_size:1,
+ ' (max. ',sup_dest_names_size:1,')');
+ wlog_ln(' ',pdf_mem_ptr:1,' words of extra memory for PDF output out of ',pdf_mem_size:1,
+ ' (max. ',sup_pdf_mem_size:1,')');
+ end;
+ end;
+ end;
+end
+else begin
+ @<Finish the \.{DVI} file@>;
+end;
+if log_opened then
+ begin wlog_cr; selector:=selector-2;
+ if (selector=term_only)and(callback_id=0) then begin
+ print_nl("Transcript written on ");
+@.Transcript written...@>
+ slow_print(log_name); print_char(".");
+ end;
+ lua_a_close_out(log_file);
+ end;
+end;
+
+@ The present section goes directly to the log file instead of using
+|print| commands, because there's no need for these strings to take
+up |str_pool| memory when a non-{\bf stat} version of \TeX\ is being used.
+
+@<Output statistics...@>=
+if log_opened then
+ begin wlog_ln(' ');
+ wlog_ln('Here is how much of TeX''s memory',' you used:');
+@.Here is how much...@>
+ wlog(' ',str_ptr-init_str_ptr:1,' string');
+ if str_ptr<>init_str_ptr+1 then wlog('s');
+ wlog_ln(' out of ', max_strings-init_str_ptr+string_offset:1);@/
+ wlog_ln(' ',pool_ptr-init_pool_ptr:1,' string characters out of ',
+ pool_size-init_pool_ptr:1);@/
+ wlog_ln(' ',var_mem_max:1,',',fix_mem_max:1,@|
+ ' words of node,token memory allocated');@/
+ print_node_mem_stats(tracing_stats, tracing_online);
+ wlog_ln(' ',cs_count:1,' multiletter control sequences out of ',
+ hash_size:1);@/
+ wlog(' ',max_font_id,' font');
+ if max_font_id<>1 then wlog('s');
+ wlog_ln(' using ', font_bytes:1, ' bytes');
+ wlog_ln(' ',max_in_stack:1,'i,',max_nest_stack:1,'n,',@|
+ max_param_stack:1,'p,',@|
+ max_buf_stack+1:1,'b,',@|
+ max_save_stack+6:1,'s stack positions out of ',@|
+ stack_size:1,'i,',
+ nest_size:1,'n,',
+ param_size:1,'p,',
+ buf_size:1,'b,',
+ save_size:1,'s');
+ end
+
+@ We get to the |final_cleanup| routine when \.{\\end} or \.{\\dump} has
+been scanned and |its_all_over|\kern-2pt.
+
+@<Last-minute...@>=
+procedure final_cleanup;
+label exit;
+var c:small_number; {0 for \.{\\end}, 1 for \.{\\dump}}
+i:halfword; { for looping marks }
+begin c:=cur_chr;
+if job_name=0 then open_log_file;
+while input_ptr>0 do
+ if state=token_list then end_token_list@+else end_file_reading;
+while open_parens>0 do
+ begin
+ if tracefilenames then print(" )");
+ decr(open_parens);
+ end;
+if cur_level>level_one then
+ begin print_nl("("); print_esc("end occurred ");
+ print("inside a group at level ");
+@:end_}{\.{(\\end occurred...)}@>
+ print_int(cur_level-level_one); print_char(")");
+ show_save_groups;
+ end;
+while cond_ptr<>null do
+ begin print_nl("("); print_esc("end occurred ");
+ print("when "); print_cmd_chr(if_test,cur_if);
+ if if_line<>0 then
+ begin print(" on line "); print_int(if_line);
+ end;
+ print(" was incomplete)");
+ if_line:=if_line_field(cond_ptr);
+ cur_if:=subtype(cond_ptr); temp_ptr:=cond_ptr;
+ cond_ptr:=vlink(cond_ptr); flush_node(temp_ptr);
+ end;
+if not callback_defined(stop_run_callback) then
+ if history<>spotless then
+ if ((history=warning_issued)or(interaction<error_stop_mode)) then
+ if selector=term_and_log then
+ begin selector:=term_only;
+ print_nl("(see the transcript file for additional information)");
+@.see the transcript file...@>
+ selector:=term_and_log;
+ end;
+if c=1 then
+ begin @!init for i:=0 to biggest_used_mark do begin
+ delete_top_mark(i); delete_first_mark(i); delete_bot_mark(i);
+ delete_split_first_mark(i); delete_split_bot_mark(i);
+ end;
+ for c:=last_box_code to vsplit_code do flush_node_list(disc_ptr[c]);
+ @<Close the pseudo files@>;
+ store_fmt_file; return;@+tini@/
+ print_nl("(\dump is performed only by INITEX)"); return;
+@:dump_}{\.{\\dump...only by INITEX}@>
+ end;
+exit:end;
+
+@ @<Last-minute...@>=
+@!init procedure init_prim; {initialize all the primitives}
+begin no_new_control_sequence:=false;
+first:=0;
+@<Put each...@>;
+no_new_control_sequence:=true;
+end;
+tini
+
+@ When we begin the following code, \TeX's tables may still contain garbage;
+the strings might not even be present. Thus we must proceed cautiously to get
+bootstrapped in.
+
+But when we finish this part of the program, \TeX\ is ready to call on the
+|main_control| routine to do its work.
+
+@<Get the first line...@>=
+begin @<Initialize the input routines@>;
+@<Enable \eTeX, if requested@>@;@/
+if (format_ident=0)or(buffer[loc]="&") then
+ begin if format_ident<>0 then initialize; {erase preloaded format}
+ if not open_fmt_file then goto final_end;
+ if not load_fmt_file then
+ begin w_close(fmt_file); goto final_end;
+ end;
+ w_close(fmt_file);
+ while (loc<limit)and(buffer[loc]=" ") do incr(loc);
+ end;
+if (pdf_output_option <> 0) then pdf_output := pdf_output_value;
+if (pdf_draftmode_option <> 0) then pdf_draftmode := pdf_draftmode_value;
+pdf_init_map_file('pdftex.map');
+if false then wterm_ln('entering extended mode');
+if end_line_char_inactive then decr(limit)
+else buffer[limit]:=end_line_char;
+fix_date_and_time;@/
+random_seed :=(microseconds*1000)+(epochseconds mod 1000000);@/
+init_randoms(random_seed);@/
+@<Compute the magic offset@>;
+@<Initialize the print |selector|...@>;
+if (loc<limit)and(get_cat_code(cat_code_table,buffer[loc])<>escape) then start_input;
+ {\.{\\input} assumed}
+@<DIR: Initialize |text_dir_ptr|@>;
+end
+
+@* \[52] Debugging.
+Once \TeX\ is working, you should be able to diagnose most errors with
+the \.{\\show} commands and other diagnostic features. But for the initial
+stages of debugging, and for the revelation of really deep mysteries, you
+can compile \TeX\ with a few more aids, including the \PASCAL\ runtime
+checks and its debugger. An additional routine called |debug_help|
+will also come into play when you type `\.D' after an error message;
+|debug_help| also occurs just before a fatal error causes \TeX\ to succumb.
+@^debugging@>
+@^system dependencies@>
+
+The interface to |debug_help| is primitive, but it is good enough when used
+with a \PASCAL\ debugger that allows you to set breakpoints and to read
+variables and change their values. After getting the prompt `\.{debug \#}', you
+type either a negative number (this exits |debug_help|), or zero (this
+goes to a location where you can set a breakpoint, thereby entering into
+dialog with the \PASCAL\ debugger), or a positive number |m| followed by
+an argument |n|. The meaning of |m| and |n| will be clear from the
+program below. (If |m=13|, there is an additional argument, |l|.)
+@.debug \#@>
+
+@d breakpoint=888 {place where a breakpoint is desirable}
+
+@<Last-minute...@>=
+@!debug procedure debug_help; {routine to display various things}
+label breakpoint,exit;
+var k,@!l,@!m,@!n:integer;
+begin loop begin wake_up_terminal;
+ print_nl("debug # (-1 to exit):"); update_terminal;
+@.debug \#@>
+ read(term_in,m);
+ if m<0 then return
+ else if m=0 then
+ begin goto breakpoint;@\ {go to every label at least once}
+ breakpoint: m:=0; @{'BREAKPOINT'@}@\
+ end
+ else begin read(term_in,n);
+ case m of
+ @t\4@>@<Numbered cases for |debug_help|@>@;
+ othercases print("?")
+ endcases;
+ end;
+ end;
+exit:end;
+gubed
+
+@ @<Numbered cases...@>=
+1: print_word(mem(n)); {display |mem[n]| in all forms}
+2: print_int(info(n));
+3: print_int(link(n));
+4: print_word(eqtb[n]);
+5: ;
+6: print_word(save_stack[n]);
+7: show_box(n);
+ {show a box, abbreviated by |show_box_depth| and |show_box_breadth|}
+8: begin breadth_max:=10000; depth_threshold:=pool_size-pool_ptr-10;
+ show_node_list(n); {show a box in its entirety}
+ end;
+9: show_token_list(n,null,1000);
+10: slow_print(n);
+13: begin read(term_in,l); print_cmd_chr(n,l);
+ end;
+14: for k:=0 to n do print(buffer[k]);
+15: begin font_in_short_display:=null_font; short_display(n);
+ end;
+
+@* \[53] Extensions.
+The program above includes a bunch of ``hooks'' that allow further
+capabilities to be added without upsetting \TeX's basic structure.
+Most of these hooks are concerned with ``whatsit'' nodes, which are
+intended to be used for special purposes; whenever a new extension to
+\TeX\ involves a new kind of whatsit node, a corresponding change needs
+to be made to the routines below that deal with such nodes,
+but it will usually be unnecessary to make many changes to the
+other parts of this program.
+
+In order to demonstrate how extensions can be made, we shall treat
+`\.{\\write}', `\.{\\openout}', `\.{\\closeout}', `\.{\\immediate}',
+and `\.{\\special}' as if they were extensions.
+These commands are actually primitives of \TeX, and they should
+appear in all implementations of the system; but let's try to imagine
+that they aren't. Then the program below illustrates how a person
+could add them.
+
+Sometimes, of course, an extension will require changes to \TeX\ itself;
+no system of hooks could be complete enough for all conceivable extensions.
+The features associated with `\.{\\write}' are almost all confined to the
+following paragraphs, but there are small parts of the |print_ln| and
+|print_char| procedures that were introduced specifically to \.{\\write}
+characters. Furthermore one of the token lists recognized by the scanner
+is a |write_text|; and there are a few other miscellaneous places where we
+have already provided for some aspect of \.{\\write}. The goal of a \TeX\
+extender should be to minimize alterations to the standard parts of the
+program, and to avoid them completely if possible. He or she should also
+be quite sure that there's no easy way to accomplish the desired goals
+with the standard features that \TeX\ already has. ``Think thrice before
+extending,'' because that may save a lot of work, and it will also keep
+incompatible extensions of \TeX\ from proliferating.
+@^system dependencies@>
+@^extensions to \TeX@>
+
+@ First let's consider the format of whatsit nodes that are used to represent
+the data associated with \.{\\write} and its relatives. Recall that a whatsit
+has |type=whatsit_node|, and the |subtype| is supposed to distinguish
+different kinds of whatsits. Each node occupies two or more words; the
+exact number is immaterial, as long as it is readily determined from the
+|subtype| or other data.
+
+We shall introduce five |subtype| values here, corresponding to the
+control sequences \.{\\openout}, \.{\\write}, \.{\\closeout}, and \.{\\special}.
+The second word of I/O whatsits has a |write_stream| field
+that identifies the write-stream number (0 to 15, or 16 for out-of-range and
+positive, or 17 for out-of-range and negative).
+In the case of \.{\\write} and \.{\\special}, there is also a field that
+points to the reference count of a token list that should be sent. In the
+case of \.{\\openout}, we need three words and three auxiliary subfields
+to hold the string numbers for name, area, and extension.
+
+@d open_node=0 {|subtype| in whatsits that represent files to \.{\\openout}}
+@d open_node_size==4 {number of words in an open/whatsit node}
+@d write_node=1 {|subtype| in whatsits that represent things to \.{\\write}}
+@d write_node_size==3 {number of words in a write/whatsit node}
+@d close_node=2 {|subtype| in whatsits that represent streams to \.{\\closeout}}
+@d close_node_size==3 {number of words in a write/whatsit node}
+@d special_node=3 {|subtype| in whatsits that represent \.{\\special} things}
+@d special_node_size==3 {number of words in a write/whatsit node}
+@d dir_node_size=4 {number of words in change direction node}
+@d dir_dir(#)==vinfo(#+2) {keep the direction to be taken}
+@d dir_level(#)==vlink(#+2) {the save level at which the direction was defined}
+@d dir_dvi_ptr(#)==vinfo(#+3) {for reflecting dvi output}
+@d dir_dvi_h(#)==vlink(#+3) {for reflecting dvi output}
+@d what_lang(#)==vlink(#+2) {language number, in the range |0..255|}
+@d what_lhm(#)==type(#+2) {minimum left fragment, in the range |1..63|}
+@d what_rhm(#)==subtype(#+2) {minimum right fragment, in the range |1..63|}
+@d write_tokens(#) == vlink(#+2) {reference count of token list to write}
+@d write_stream(#) == vinfo(#+2) {stream number (0 to 17)}
+@d open_name(#) == vlink(#+2) {string number of file name to open}
+@d open_area(#) == vinfo(#+3) {string number of file area for |open_name|}
+@d open_ext(#) == vlink(#+3) {string number of file extension for |open_name|}
+
+@ The sixteen possible \.{\\write} streams are represented by the |write_file|
+array. The |j|th file is open if and only if |write_open[j]=true|. The last
+two streams are special; |write_open[16]| represents a stream number
+greater than 15, while |write_open[17]| represents a negative stream number,
+and both of these variables are always |false|.
+
+@<Glob...@>=
+@!write_file:array[0..15] of alpha_file;
+@!write_file_mode:array[0..15] of halfword;
+@!write_file_translation:array[0..15] of halfword;
+@!write_open:array[0..17] of boolean;
+@!neg_wd:scaled;
+@!pos_wd:scaled;
+@!neg_ht:scaled;
+@!dvi_direction:integer;
+@!dir_primary:array[0..31] of 0..31;
+@!dir_secondary:array[0..31] of 0..31;
+@!dir_tertiary:array[0..31] of 0..31;
+@!dir_rearrange:array[0..3] of 0..31;
+@!dir_names:array[0..3] of str_number;
+@!text_dir_ptr:pointer;
+@!text_dir_tmp:pointer;
+
+@
+@<Set init...@>=
+for k:=0 to 17 do write_open[k]:=false;
+pack_direction:=-1;
+for k:= 0 to 7 do begin
+ dir_primary [k ]:=dir_T;
+ dir_primary [k+ 8]:=dir_L;
+ dir_primary [k+16]:=dir_B;
+ dir_primary [k+24]:=dir_R;
+ end;
+for k:= 0 to 3 do begin
+ dir_secondary[k ]:=dir_L;
+ dir_secondary[k+ 4]:=dir_R;
+ dir_secondary[k+ 8]:=dir_T;
+ dir_secondary[k+12]:=dir_B;
+
+ dir_secondary[k+16]:=dir_L;
+ dir_secondary[k+20]:=dir_R;
+ dir_secondary[k+24]:=dir_T;
+ dir_secondary[k+28]:=dir_B;
+ end;
+for k:=0 to 7 do begin
+ dir_tertiary[k*4 ]:=dir_T;
+ dir_tertiary[k*4+1]:=dir_L;
+ dir_tertiary[k*4+2]:=dir_B;
+ dir_tertiary[k*4+3]:=dir_R;
+ end;
+dir_rearrange[0]:=0;
+dir_rearrange[1]:=0;
+dir_rearrange[2]:=1;
+dir_rearrange[3]:=1;
+dir_names[0]:="T";
+dir_names[1]:="L";
+dir_names[2]:="B";
+dir_names[3]:="R";
+
+@ Extensions might introduce new command codes; but it's best to use
+|extension| with a modifier, whenever possible, so that |main_control|
+stays the same.
+
+@d immediate_code=4 {command modifier for \.{\\immediate}}
+@d local_par_node==6 {|subtype| in whatsits for local paragraph node}
+{|local_par_node| has to be a macro, not numeric }
+@d dir_node=7 {|subtype| in whatsits for change direction node}
+@d pdftex_first_extension_code = 8
+@d pdf_literal_node == pdftex_first_extension_code + 0
+@d pdf_obj_code == pdftex_first_extension_code + 1
+@d pdf_refobj_node == pdftex_first_extension_code + 2
+@d pdf_xform_code == pdftex_first_extension_code + 3
+@d pdf_refxform_node == pdftex_first_extension_code + 4
+@d pdf_ximage_code == pdftex_first_extension_code + 5
+@d pdf_refximage_node == pdftex_first_extension_code + 6
+@d pdf_annot_node == pdftex_first_extension_code + 7
+@d pdf_start_link_node == pdftex_first_extension_code + 8
+@d pdf_end_link_node == pdftex_first_extension_code + 9
+@d pdf_end_link_node_size==3
+@d pdf_outline_code == pdftex_first_extension_code + 10
+@d pdf_dest_node == pdftex_first_extension_code + 11
+@d pdf_thread_node == pdftex_first_extension_code + 12
+@d pdf_start_thread_node == pdftex_first_extension_code + 13
+@d pdf_end_thread_node == pdftex_first_extension_code + 14
+@d pdf_end_thread_node_size==3
+@d pdf_save_pos_node == pdftex_first_extension_code + 15
+@d pdf_save_pos_node_size==3
+@d pdf_info_code == pdftex_first_extension_code + 16
+@d pdf_thread_data_node == pdftex_first_extension_code + 16
+@d pdf_catalog_code == pdftex_first_extension_code + 17
+@d pdf_link_data_node == pdftex_first_extension_code + 17
+@d pdf_names_code == pdftex_first_extension_code + 18
+@d pdf_font_attr_code == pdftex_first_extension_code + 19
+@d pdf_include_chars_code == pdftex_first_extension_code + 20
+@d pdf_map_file_code == pdftex_first_extension_code + 21
+@d pdf_map_line_code == pdftex_first_extension_code + 22
+@d pdf_trailer_code == pdftex_first_extension_code + 23
+@d pdf_font_expand_code == pdftex_first_extension_code + 24
+@d set_random_seed_code == pdftex_first_extension_code + 25
+@d pdf_glyph_to_unicode_code == pdftex_first_extension_code + 26
+@d late_lua_node == pdftex_first_extension_code + 27
+@d close_lua_node == pdftex_first_extension_code + 28
+@d save_cat_code_table_code == pdftex_first_extension_code + 29
+@d init_cat_code_table_code == pdftex_first_extension_code + 30
+@d pdf_colorstack_node == pdftex_first_extension_code + 31
+@d pdf_setmatrix_node == pdftex_first_extension_code + 32
+@d pdf_save_node == pdftex_first_extension_code + 33
+@d pdf_restore_node == pdftex_first_extension_code + 34
+@d pdftex_last_extension_code == pdftex_first_extension_code + 34
+
+@<Put each...@>=
+primitive("openout",extension,open_node);@/
+@!@:open_out_}{\.{\\openout} primitive@>
+primitive("write",extension,write_node); write_loc:=cur_val;@/
+@!@:write_}{\.{\\write} primitive@>
+primitive("closeout",extension,close_node);@/
+@!@:close_out_}{\.{\\closeout} primitive@>
+primitive("special",extension,special_node);@/
+@!@:special_}{\.{\\special} primitive@>
+primitive("immediate",extension,immediate_code);@/
+@!@:immediate_}{\.{\\immediate} primitive@>
+primitive("localinterlinepenalty",assign_int,local_inter_line_penalty_code);@/
+primitive("localbrokenpenalty",assign_int,local_broken_penalty_code);@/
+primitive("pagedir",assign_dir,dir_base+page_direction_code);@/
+primitive("bodydir",assign_dir,dir_base+body_direction_code);@/
+primitive("pardir",assign_dir,dir_base+par_direction_code);@/
+primitive("textdir",assign_dir,dir_base+text_direction_code);@/
+primitive("mathdir",assign_dir,dir_base+math_direction_code);@/
+primitive("pagerightoffset",assign_dimen,dimen_base+page_right_offset_code);
+primitive("pagebottomoffset",assign_dimen,dimen_base+page_bottom_offset_code);
+primitive("pdfliteral",extension,pdf_literal_node);@/
+@!@:pdf_literal_}{\.{\\pdfliteral} primitive@>
+primitive("pdfcolorstack",extension,pdf_colorstack_node);@/
+@!@:pdf_colorstack_}{\.{\\pdfcolorstack} primitive@>
+primitive("pdfsetmatrix",extension,pdf_setmatrix_node);@/
+@!@:pdf_setmatrix_}{\.{\\pdfsetmatrix} primitive@>
+primitive("pdfsave",extension,pdf_save_node);@/
+@!@:pdf_save_}{\.{\\pdfsave} primitive@>
+primitive("pdfrestore",extension,pdf_restore_node);@/
+@!@:pdf_restore_}{\.{\\pdfrestore} primitive@>
+primitive("pdfobj",extension,pdf_obj_code);@/
+@!@:pdf_obj_}{\.{\\pdfobj} primitive@>
+primitive("pdfrefobj",extension,pdf_refobj_node);@/
+@!@:pdf_refobj_}{\.{\\pdfrefobj} primitive@>
+primitive("pdfxform",extension,pdf_xform_code);@/
+@!@:pdf_xform_}{\.{\\pdfxform} primitive@>
+primitive("pdfrefxform",extension,pdf_refxform_node);@/
+@!@:pdf_refxform_}{\.{\\pdfrefxform} primitive@>
+primitive("pdfximage",extension,pdf_ximage_code);@/
+@!@:pdf_ximage_}{\.{\\pdfximage} primitive@>
+primitive("pdfrefximage",extension,pdf_refximage_node);@/
+@!@:pdf_refximage_}{\.{\\pdfrefximage} primitive@>
+primitive("pdfannot",extension,pdf_annot_node);@/
+@!@:pdf_annot_}{\.{\\pdfannot} primitive@>
+primitive("pdfstartlink",extension,pdf_start_link_node);@/
+@!@:pdf_start_link_}{\.{\\pdfstartlink} primitive@>
+primitive("pdfendlink",extension,pdf_end_link_node);@/
+@!@:pdf_end_link_}{\.{\\pdfendlink} primitive@>
+primitive("pdfoutline",extension,pdf_outline_code);@/
+@!@:pdf_outline_}{\.{\\pdfoutline} primitive@>
+primitive("pdfdest",extension,pdf_dest_node);@/
+@!@:pdf_dest_}{\.{\\pdfdest} primitive@>
+primitive("pdfthread",extension,pdf_thread_node);@/
+@!@:pdf_thread_}{\.{\\pdfthread} primitive@>
+primitive("pdfstartthread",extension,pdf_start_thread_node);@/
+@!@:pdf_start_thread_}{\.{\\pdfstartthread} primitive@>
+primitive("pdfendthread",extension,pdf_end_thread_node);@/
+@!@:pdf_end_thread_}{\.{\\pdfendthread} primitive@>
+primitive("pdfsavepos",extension,pdf_save_pos_node);@/
+@!@:pdf_save_pos_}{\.{\\pdfsavepos} primitive@>
+primitive("pdfinfo",extension,pdf_info_code);@/
+@!@:pdf_info_}{\.{\\pdfinfo} primitive@>
+primitive("pdfcatalog",extension,pdf_catalog_code);@/
+@!@:pdf_catalog_}{\.{\\pdfcatalog} primitive@>
+primitive("pdfnames",extension,pdf_names_code);@/
+@!@:pdf_names_}{\.{\\pdfnames} primitive@>
+primitive("pdfincludechars",extension,pdf_include_chars_code);@/
+@!@:pdf_include_chars_}{\.{\\pdfincludechars} primitive@>
+primitive("pdffontattr",extension,pdf_font_attr_code);@/
+@!@:pdf_font_attr_}{\.{\\pdffontattr} primitive@>
+primitive("pdfmapfile",extension,pdf_map_file_code);@/
+@!@:pdf_map_file_}{\.{\\pdfmapfile} primitive@>
+primitive("pdfmapline",extension,pdf_map_line_code);@/
+@!@:pdf_map_line_}{\.{\\pdfmapline} primitive@>
+primitive("pdftrailer",extension,pdf_trailer_code);@/
+@!@:pdf_trailer_}{\.{\\pdftrailer} primitive@>
+primitive("savecatcodetable",extension,save_cat_code_table_code);@/
+@!@:save_cat_code_table_}{\.{\\savecatcodetable} primitive@>
+primitive("initcatcodetable",extension,init_cat_code_table_code);@/
+@!@:init_cat_code_table_}{\.{\\initcatcodetable} primitive@>
+primitive("pdfsetrandomseed",extension,set_random_seed_code);@/
+@!@:set_random_seed_code}{\.{\\pdfsetrandomseed} primitive@>
+primitive("latelua",extension,late_lua_node);@/
+@!@:late_lua_node_}{\.{\\latelua} primitive@>
+primitive("closelua",extension,close_lua_node);@/
+@!@:close_lua_node_}{\.{\\closelua} primitive@>
+primitive("pdffontexpand",extension,pdf_font_expand_code);@/
+@!@:pdf_font_expand_}{\.{\\pdffontexpand} primitive@>
+primitive("pdfglyphtounicode",extension,pdf_glyph_to_unicode_code);@/
+@!@:pdf_glyph_to_unicode_}{\.{\\pdfglyphtounicode} primitive@>
+
+@ The variable |write_loc| just introduced is used to provide an
+appropriate error message in case of ``runaway'' write texts.
+
+@<Glob...@>=
+@!write_loc:pointer; {|eqtb| address of \.{\\write}}
+
+@ @<Cases of |print_cmd_chr|...@>=
+extension: case chr_code of
+ open_node:print_esc("openout");
+ write_node:print_esc("write");
+ close_node:print_esc("closeout");
+ special_node:print_esc("special");
+ immediate_code:print_esc("immediate");
+ pdf_annot_node: print_esc("pdfannot");
+ pdf_catalog_code: print_esc("pdfcatalog");
+ pdf_dest_node: print_esc("pdfdest");
+ pdf_end_link_node: print_esc("pdfendlink");
+ pdf_end_thread_node: print_esc("pdfendthread");
+ pdf_font_attr_code: print_esc("pdffontattr");
+ pdf_font_expand_code: print_esc("pdffontexpand");
+ pdf_include_chars_code: print_esc("pdfincludechars");
+ pdf_info_code: print_esc("pdfinfo");
+ pdf_literal_node: print_esc("pdfliteral");
+ pdf_colorstack_node: print_esc("pdfcolorstack");
+ pdf_setmatrix_node: print_esc("pdfsetmatrix");
+ pdf_save_node: print_esc("pdfsave");
+ pdf_restore_node: print_esc("pdfrestore");
+ pdf_map_file_code: print_esc("pdfmapfile");
+ pdf_map_line_code: print_esc("pdfmapline");
+ pdf_names_code: print_esc("pdfnames");
+ pdf_obj_code: print_esc("pdfobj");
+ pdf_outline_code: print_esc("pdfoutline");
+ pdf_refobj_node: print_esc("pdfrefobj");
+ pdf_refxform_node: print_esc("pdfrefxform");
+ pdf_refximage_node: print_esc("pdfrefximage");
+ pdf_save_pos_node: print_esc("pdfsavepos");
+ pdf_start_link_node: print_esc("pdfstartlink");
+ pdf_start_thread_node: print_esc("pdfstartthread");
+ pdf_thread_node: print_esc("pdfthread");
+ pdf_trailer_code: print_esc("pdftrailer");
+ pdf_xform_code: print_esc("pdfxform");
+ pdf_ximage_code: print_esc("pdfximage");
+ save_cat_code_table_code: print_esc("savecatcodetable");
+ init_cat_code_table_code: print_esc("initcatcodetable");
+ set_random_seed_code: print_esc("pdfsetrandomseed");
+ pdf_glyph_to_unicode_code: print_esc("pdfglyphtounicode");
+ late_lua_node: print_esc("latelua");
+ close_lua_node: print_esc("closelua");
+ cancel_boundary_node: print_esc("noboundary");
+ othercases print("[unknown extension!]")
+ endcases;
+
+@ When an |extension| command occurs in |main_control|, in any mode,
+the |do_extension| routine is called.
+
+@<Cases of |main_control| that are for extensions...@>=
+any_mode(extension):do_extension;
+
+@ @<Declare act...@>=
+@t\4@>@<Declare procedures needed in |do_extension|@>@;
+procedure do_extension;
+var i,@!j,@!k:integer; {all-purpose integers}
+@!p,@!q,@!r:pointer; {all-purpose pointers}
+begin case cur_chr of
+ open_node:@<Implement \.{\\openout}@>;
+ write_node:@<Implement \.{\\write}@>;
+ close_node:@<Implement \.{\\closeout}@>;
+ special_node:@<Implement \.{\\special}@>;
+ immediate_code:@<Implement \.{\\immediate}@>;
+ pdf_annot_node: @<Implement \.{\\pdfannot}@>;
+ pdf_catalog_code: @<Implement \.{\\pdfcatalog}@>;
+ pdf_dest_node: @<Implement \.{\\pdfdest}@>;
+ pdf_end_link_node: @<Implement \.{\\pdfendlink}@>;
+ pdf_end_thread_node: @<Implement \.{\\pdfendthread}@>;
+ pdf_font_attr_code: @<Implement \.{\\pdffontattr}@>;
+ pdf_font_expand_code: @<Implement \.{\\pdffontexpand}@>;
+ pdf_include_chars_code: @<Implement \.{\\pdfincludechars}@>;
+ pdf_info_code: @<Implement \.{\\pdfinfo}@>;
+ pdf_literal_node: @<Implement \.{\\pdfliteral}@>;
+ pdf_colorstack_node: @<Implement \.{\\pdfcolorstack}@>;
+ pdf_setmatrix_node: @<Implement \.{\\pdfsetmatrix}@>;
+ pdf_save_node: @<Implement \.{\\pdfsave}@>;
+ pdf_restore_node: @<Implement \.{\\pdfrestore}@>;
+ pdf_map_file_code: @<Implement \.{\\pdfmapfile}@>;
+ pdf_map_line_code: @<Implement \.{\\pdfmapline}@>;
+ pdf_names_code: @<Implement \.{\\pdfnames}@>;
+ pdf_obj_code: @<Implement \.{\\pdfobj}@>;
+ pdf_outline_code: @<Implement \.{\\pdfoutline}@>;
+ pdf_refobj_node: @<Implement \.{\\pdfrefobj}@>;
+ pdf_refxform_node: @<Implement \.{\\pdfrefxform}@>;
+ pdf_refximage_node: @<Implement \.{\\pdfrefximage}@>;
+ pdf_save_pos_node: @<Implement \.{\\pdfsavepos}@>;
+ pdf_start_link_node: @<Implement \.{\\pdfstartlink}@>;
+ pdf_start_thread_node: @<Implement \.{\\pdfstartthread}@>;
+ pdf_thread_node: @<Implement \.{\\pdfthread}@>;
+ pdf_trailer_code: @<Implement \.{\\pdftrailer}@>;
+ pdf_xform_code: @<Implement \.{\\pdfxform}@>;
+ pdf_ximage_code: @<Implement \.{\\pdfximage}@>;
+ save_cat_code_table_code: @<Implement \.{\\savecatcodetable}@>;
+ init_cat_code_table_code: @<Implement \.{\\initcatcodetable}@>;
+ set_random_seed_code: @<Implement \.{\\pdfsetrandomseed}@>;
+ pdf_glyph_to_unicode_code: @<Implement \.{\\pdfglyphtounicode}@>;
+ late_lua_node: @<Implement \.{\\latelua}@>;
+ close_lua_node: @<Implement \.{\\closelua}@>;
+othercases confusion("ext1")
+@:this can't happen ext1}{\quad ext1@>
+endcases;
+end;
+
+@ Here is a subroutine that creates a whatsit node having a given |subtype|
+and a given number of words. It initializes only the first word of the whatsit,
+and appends it to the current list.
+
+@<Declare procedures needed in |do_extension|@>=
+procedure new_whatsit(@!s:small_number);
+var p:pointer; {the new node}
+begin p:=new_node(whatsit_node,s);
+vlink(tail):=p; tail:=p;
+end;
+
+@ The next subroutine uses |cur_chr| to decide what sort of whatsit is
+involved, and also inserts a |write_stream| number.
+
+@<Declare procedures needed in |do_ext...@>=
+procedure new_write_whatsit(@!w:small_number);
+begin new_whatsit(cur_chr);
+if w<>write_node_size then scan_four_bit_int
+else begin scan_int;
+ if cur_val<0 then cur_val:=17
+ else if cur_val>15 then cur_val:=16;
+ end;
+write_stream(tail):=cur_val;
+end;
+
+@ @<Implement \.{\\openout}@>=
+begin new_write_whatsit(open_node_size);
+scan_optional_equals; scan_file_name;@/
+open_name(tail):=cur_name; open_area(tail):=cur_area; open_ext(tail):=cur_ext;
+end
+
+@ When `\.{\\write 12\{...\}}' appears, we scan the token list `\.{\{...\}}'
+without expanding its macros; the macros will be expanded later when this
+token list is rescanned.
+
+@<Implement \.{\\write}@>=
+begin k:=cur_cs; new_write_whatsit(write_node_size);@/
+cur_cs:=k; p:=scan_toks(false,false); write_tokens(tail):=def_ref;
+end
+
+@ @<Implement \.{\\closeout}@>=
+begin new_write_whatsit(write_node_size); write_tokens(tail):=null;
+end
+
+@ When `\.{\\special\{...\}}' appears, we expand the macros in the token
+list as in \.{\\xdef} and \.{\\mark}.
+
+@<Implement \.{\\special}@>=
+begin new_whatsit(special_node); write_stream(tail):=null;
+p:=scan_toks(false,true); write_tokens(tail):=def_ref;
+end
+
+@ @<Implement \.{\\pdffontexpand}@>=
+ read_expand_font
+
+@ The following macros are needed for further manipulation with whatsit nodes
+for \pdfTeX{} extensions (copying, destroying etc.)
+
+@d add_action_ref(#) == incr(pdf_action_refcount(#)) {increase count of
+references to this action}
+
+@d delete_action_ref(#) == {decrease count of references to this
+action; free it if there is no reference to this action}
+begin
+ if pdf_action_refcount(#) = null then begin
+ if pdf_action_type(#) = pdf_action_user then
+ delete_token_ref(pdf_action_tokens(#))
+ else begin
+ if pdf_action_file(#) <> null then
+ delete_token_ref(pdf_action_file(#));
+ if pdf_action_type(#) = pdf_action_page then
+ delete_token_ref(pdf_action_tokens(#))
+ else if pdf_action_named_id(#) > 0 then
+ delete_token_ref(pdf_action_id(#));
+ end;
+ flush_node(#);
+ end
+ else
+ decr(pdf_action_refcount(#));
+end
+
+@ We have to check whether \.{\\pdfoutput} is set for using \pdfTeX{}
+ extensions.
+@<Declare procedures needed in |do_ext...@>=
+procedure check_pdfoutput(s: str_number; is_error : boolean);
+begin
+ if pdf_output <= 0 then
+ begin
+ if is_error then
+ pdf_error(s, "not allowed in DVI mode (\pdfoutput <= 0)")
+ else
+ pdf_warning(s, "not allowed in DVI mode (\pdfoutput <= 0); ignoring it", true,true);
+ end
+end;
+
+procedure scan_pdf_ext_toks;
+begin
+ call_func(scan_toks(false, true)); {like \.{\\special}}
+end;
+
+@ @<Implement \.{\\pdfliteral}@>=
+begin
+ check_pdfoutput("\pdfliteral", true);
+ new_whatsit(pdf_literal_node);
+ if scan_keyword("direct") then
+ pdf_literal_mode(tail) := direct_always
+ else if scan_keyword("page") then
+ pdf_literal_mode(tail) := direct_page
+ else
+ pdf_literal_mode(tail) := set_origin;
+ scan_pdf_ext_toks;
+ pdf_literal_data(tail) := def_ref;
+end
+
+@ @<Implement \.{\\pdfcolorstack}@>=
+begin
+ check_pdfoutput("\pdfcolorstack", true);
+ {Scan and check the stack number and store in |cur_val|}
+ scan_int;
+ if cur_val >= colorstackused then begin
+ print_err("Unknown color stack number ");
+ print_int(cur_val);
+@.Unknown color stack@>
+ help3("Allocate and initialize a color stack with \\pdfcolorstackinit.")@/
+ ("I'll use default color stack 0 here.")@/
+ ("Proceed, with fingers crossed.");
+ error;
+ cur_val := 0;
+ end;
+ if cur_val < 0 then begin
+ print_err("Invalid negative color stack number");
+@.Invalid negative color stack number@>
+ help2("I'll use default color stack 0 here.")@/
+ ("Proceed, with fingers corssed.");
+ error;
+ cur_val := 0;
+ end;
+ if scan_keyword("set") then begin
+ i := colorstack_set;
+ end
+ else if scan_keyword("push") then begin
+ i := colorstack_push;
+ end
+ else if scan_keyword("pop") then begin
+ i := colorstack_pop;
+ end
+ else if scan_keyword("current") then begin
+ i := colorstack_current;
+ end
+ else begin
+ i := -1; {error}
+ end;
+ if i >= 0 then begin
+ new_whatsit(pdf_colorstack_node);
+ pdf_colorstack_stack(tail) := cur_val;
+ pdf_colorstack_cmd(tail) := i;
+ pdf_colorstack_data(tail) := null;
+ if i <= colorstack_data then begin
+ scan_pdf_ext_toks;
+ pdf_colorstack_data(tail) := def_ref;
+ end;
+ end
+ else begin
+ print_err("Color stack action is missing");
+@.Color stack action is missing@>
+ help3("The expected actions for \pdfcolorstack:")@/
+ (" set, push, pop, current")@/
+ ("I'll ignore the color stack command.");
+ error;
+ end
+end
+
+@ @<Implement \.{\\pdfsetmatrix}@>=
+begin
+ check_pdfoutput("\pdfsetmatrix", true);
+ new_whatsit(pdf_setmatrix_node);
+ scan_pdf_ext_toks;
+ pdf_setmatrix_data(tail) := def_ref;
+end
+
+@ @<Implement \.{\\pdfsave}@>=
+begin
+ check_pdfoutput("\pdfsave", true);
+ new_whatsit(pdf_save_node);
+end
+
+@ @<Implement \.{\\pdfrestore}@>=
+begin
+ check_pdfoutput("\pdfrestore", true);
+ new_whatsit(pdf_restore_node);
+end
+
+
+@ @<Implement \.{\\latelua}@>=
+begin
+ check_pdfoutput("\latelua", true);
+ new_whatsit(late_lua_node);
+ scan_register_num;
+ late_lua_reg(tail) := cur_val;
+ scan_pdf_ext_toks;
+ late_lua_data(tail) := def_ref;
+end
+
+@ @<Implement \.{\\closelua}@>=
+begin
+ check_pdfoutput("\closelua", true);
+ new_whatsit(close_lua_node);
+ scan_register_num;
+ late_lua_reg(tail) := cur_val;
+end
+
+@ The \.{\\pdfobj} primitive is used to create a ``raw'' object in the PDF
+ output file. The object contents will be hold in memory and will be written
+ out only when the object is referenced by \.{\\pdfrefobj}. When \.{\\pdfobj}
+ is used with \.{\\immediate}, the object contents will be written out
+ immediately. Objects referenced in the current page are appended into
+ |pdf_obj_list|.
+
+@<Glob...@>=
+@!pdf_last_obj: integer;
+
+@ @<Implement \.{\\pdfobj}@>=
+begin
+ check_pdfoutput("\pdfobj", true);
+ if scan_keyword("reserveobjnum") then begin
+ @<Scan an optional space@>;
+ incr(pdf_obj_count);
+ pdf_create_obj(obj_type_obj, pdf_obj_count);
+ pdf_last_obj := obj_ptr;
+ end
+ else begin
+ k := -1;
+ if scan_keyword("useobjnum") then begin
+ scan_int;
+ k := cur_val;
+ if (k <= 0) or (k > obj_ptr) or (obj_data_ptr(k) <> 0) then begin
+ pdf_warning("\pdfobj", "invalid object number being ignored", true, true);
+ pdf_retval := -1; {signal the problem}
+ k := -1; {will be generated again}
+ end;
+ end;
+ if k < 0 then begin
+ incr(pdf_obj_count);
+ pdf_create_obj(obj_type_obj, pdf_obj_count);
+ k := obj_ptr;
+ end;
+ obj_data_ptr(k) := pdf_get_mem(pdfmem_obj_size);
+ if scan_keyword("stream") then begin
+ obj_obj_is_stream(k) := 1;
+ if scan_keyword("attr") then begin
+ scan_pdf_ext_toks;
+ obj_obj_stream_attr(k) := def_ref;
+ end
+ else
+ obj_obj_stream_attr(k) := null;
+ end
+ else
+ obj_obj_is_stream(k) := 0;
+ if scan_keyword("file") then
+ obj_obj_is_file(k) := 1
+ else
+ obj_obj_is_file(k) := 0;
+ scan_pdf_ext_toks;
+ obj_obj_data(k) := def_ref;
+ pdf_last_obj := k;
+ end;
+end
+
+@ We need to check whether the referenced object exists.
+
+@<Declare procedures that need to be declared forward for \pdfTeX@>=
+function prev_rightmost(s, e: pointer): pointer;
+{finds the node preceding the rightmost node |e|; |s| is some node
+before |e|}
+var p: pointer;
+begin
+ prev_rightmost := null;
+ p := s;
+ if p = null then
+ return;
+ while vlink(p) <> e do begin
+ p := vlink(p);
+ if p = null then
+ return;
+ end;
+ prev_rightmost := p;
+end;
+
+procedure pdf_check_obj(t, n: integer);
+var k: integer;
+begin
+ k := head_tab[t];
+ while (k <> 0) and (k <> n) do
+ k := obj_link(k);
+ if k = 0 then
+ pdf_error("ext1", "cannot find referenced object");
+end;
+
+@ @<Implement \.{\\pdfrefobj}@>=
+begin
+ check_pdfoutput("\pdfrefobj", true);
+ scan_int;
+ pdf_check_obj(obj_type_obj, cur_val);
+ new_whatsit(pdf_refobj_node);
+ pdf_obj_objnum(tail) := cur_val;
+end
+
+@ \.{\\pdfxform} and \.{\\pdfrefxform} are similiar to \.{\\pdfobj} and
+ \.{\\pdfrefobj}
+
+@<Glob...@>=
+@!pdf_last_xform: integer;
+
+@ @<Implement \.{\\pdfxform}@>=
+begin
+ check_pdfoutput("\pdfxform", true);
+ incr(pdf_xform_count);
+ pdf_create_obj(obj_type_xform, pdf_xform_count);
+ k := obj_ptr;
+ obj_data_ptr(k) := pdf_get_mem(pdfmem_xform_size);
+ if scan_keyword("attr") then begin
+ scan_pdf_ext_toks;
+ obj_xform_attr(k) := def_ref;
+ end
+ else
+ obj_xform_attr(k) := null;
+ if scan_keyword("resources") then begin
+ scan_pdf_ext_toks;
+ obj_xform_resources(k) := def_ref;
+ end
+ else
+ obj_xform_resources(k) := null;
+ scan_int;
+ p:=box(cur_val);
+ if p = null then
+ pdf_error("ext1", "\pdfxform cannot be used with a void box");
+ obj_xform_width(k) := width(p);
+ obj_xform_height(k) := height(p);
+ obj_xform_depth(k) := depth(p);
+ obj_xform_box(k) := p; {save pointer to the box}
+ box(cur_val):=null;
+ pdf_last_xform := k;
+end
+
+@ @<Implement \.{\\pdfrefxform}@>=
+begin
+ check_pdfoutput("\pdfrefxform", true);
+ scan_int;
+ pdf_check_obj(obj_type_xform, cur_val);
+ new_whatsit(pdf_refxform_node);
+ pdf_xform_objnum(tail) := cur_val;
+ pdf_width(tail) := obj_xform_width(cur_val);
+ pdf_height(tail) := obj_xform_height(cur_val);
+ pdf_depth(tail) := obj_xform_depth(cur_val);
+end
+
+@ \.{\\pdfximage} and \.{\\pdfrefximage} are similiar to \.{\\pdfxform} and
+ \.{\\pdfrefxform}. As we have to scan |<rule spec>| quite often, it is better
+ have a |rule_node| that holds the most recently scanned |<rule spec>|.
+
+@<Glob...@>=
+@!pdf_last_ximage: integer;
+@!pdf_last_ximage_pages: integer;
+@!pdf_last_ximage_colordepth: integer;
+@!alt_rule: pointer;
+@!warn_pdfpagebox: boolean;
+
+@ @<Set init...@>=
+alt_rule := null;
+warn_pdfpagebox := true;
+
+@ @<Declare procedures needed in |do_ext...@>=
+
+function scan_pdf_box_spec: integer; {scans PDF pagebox specification}
+begin
+ scan_pdf_box_spec := 0;
+ if scan_keyword("mediabox") then
+ scan_pdf_box_spec := pdf_box_spec_media
+ else if scan_keyword("cropbox") then
+ scan_pdf_box_spec := pdf_box_spec_crop
+ else if scan_keyword("bleedbox") then
+ scan_pdf_box_spec := pdf_box_spec_bleed
+ else if scan_keyword("trimbox") then
+ scan_pdf_box_spec := pdf_box_spec_trim
+ else if scan_keyword("artbox") then
+ scan_pdf_box_spec := pdf_box_spec_art
+end;
+
+procedure scan_alt_rule; {scans rule spec to |alt_rule|}
+label reswitch;
+begin
+ if alt_rule = null then
+ alt_rule := new_rule;
+ width(alt_rule) := null_flag;
+ height(alt_rule) := null_flag;
+ depth(alt_rule) := null_flag;
+reswitch:
+ if scan_keyword("width") then begin
+ scan_normal_dimen;
+ width(alt_rule) := cur_val;
+ goto reswitch;
+ end;
+ if scan_keyword("height") then begin
+ scan_normal_dimen;
+ height(alt_rule) := cur_val;
+ goto reswitch;
+ end;
+ if scan_keyword("depth") then begin
+ scan_normal_dimen;
+ depth(alt_rule) := cur_val;
+ goto reswitch;
+ end;
+end;
+
+procedure scan_image;
+label reswitch;
+var i, k, img_wd, img_ht, img_dp, ref: integer;
+ named, attr: str_number;
+ s: str_number;
+ page, pagebox, colorspace: integer;
+begin
+ incr(pdf_ximage_count);
+ pdf_create_obj(obj_type_ximage, pdf_ximage_count);
+ k := obj_ptr;
+ scan_alt_rule; {scans |<rule spec>| to |alt_rule|}
+ img_wd := width(alt_rule);
+ img_ht := height(alt_rule);
+ img_dp := depth(alt_rule);
+ attr := 0;
+ named := 0;
+ page := 1;
+ colorspace := 0;
+ if scan_keyword("attr") then begin
+ scan_pdf_ext_toks;
+ attr := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ end;
+ if scan_keyword("named") then begin
+ scan_pdf_ext_toks;
+ named := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ page := 0;
+ end
+ else if scan_keyword("page") then begin
+ scan_int;
+ page := cur_val;
+ end;
+ if scan_keyword("colorspace") then begin
+ scan_int;
+ colorspace := cur_val;
+ end;
+ pagebox := scan_pdf_box_spec;
+ if pagebox = 0 then
+ pagebox := pdf_pagebox;
+ scan_pdf_ext_toks;
+ s := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ if pdf_option_always_use_pdfpagebox <> 0 then begin
+ pdf_warning("PDF inclusion", "Primitive \pdfoptionalwaysusepdfpagebox is obsolete; use \pdfpagebox instead.", true, true);
+ pdf_force_pagebox := pdf_option_always_use_pdfpagebox;
+ pdf_option_always_use_pdfpagebox := 0; {warn once}
+ warn_pdfpagebox := false;
+ end;
+ if pdf_option_pdf_inclusion_errorlevel <> 0 then begin
+ pdf_warning("PDF inclusion", "Primitive \pdfoptionpdfinclusionerrorlevel is obsolete; use \pdfinclusionerrorlevel instead.", true, true);
+ pdf_inclusion_errorlevel := pdf_option_pdf_inclusion_errorlevel;
+ pdf_option_pdf_inclusion_errorlevel := 0; {warn once}
+ end;
+ if pdf_force_pagebox > 0 then begin
+ if warn_pdfpagebox then begin
+ pdf_warning("PDF inclusion", "Primitive \pdfforcepagebox is obsolete; use \pdfpagebox instead.", true, true);
+ warn_pdfpagebox := false;
+ end;
+ pagebox := pdf_force_pagebox;
+ end;
+ if pagebox = 0 then {no pagebox specification given}
+ pagebox := pdf_box_spec_crop;
+ ref := read_image(k, pdf_ximage_count, s, page, named, attr, colorspace, pagebox,
+ pdf_minor_version, pdf_inclusion_errorlevel);
+ flush_str(s);
+ obj_data_ptr(k) := ref;
+ if named <> 0 then flush_str(named);
+ set_image_dimensions(ref, img_wd, img_ht, img_dp);
+ if attr <> 0 then flush_str(attr);
+ scale_image(ref);
+ pdf_last_ximage := k;
+ pdf_last_ximage_pages := image_pages(ref);
+ pdf_last_ximage_colordepth := image_colordepth(ref);
+end;
+
+@ @<Implement \.{\\pdfximage}@>=
+begin
+ check_pdfoutput("\pdfximage", true);
+ check_pdfminorversion;
+ scan_image;
+end
+
+@ @<Implement \.{\\pdfrefximage}@>=
+begin
+ check_pdfoutput("\pdfrefximage", true);
+ scan_int;
+ pdf_check_obj(obj_type_ximage, cur_val);
+ new_whatsit(pdf_refximage_node);
+ j := obj_data_ptr(cur_val);
+ pdf_ximage_ref(tail) := j;
+ pdf_width(tail) := image_width(j);
+ pdf_height(tail) := image_height(j);
+ pdf_depth(tail) := image_depth(j);
+end
+
+@ The following function finds object with identifier |i| and type |t|.
+ |i < 0| indicates that |-i| should be treated as a string number. If no
+ such object exists then it will be created. This function is used mainly to
+ find destination for link annotations and outlines; however it is also used
+ in |pdf_ship_out| (to check whether a Page object already exists) so we need
+ to declare it together with subroutines needed in |pdf_hlist_out| and
+ |pdf_vlist_out|.
+
+@<Declare procedures that need to be declared forward for \pdfTeX@>=
+function find_obj(t, i: integer; byname: boolean): integer;
+begin
+ find_obj := avl_find_obj(t, i, byname);
+end;
+
+procedure flush_str(s: str_number); {flush a string if possible}
+begin
+ if flushable(s) then
+ flush_string;
+end;
+
+function get_obj(t, i: integer; byname: boolean): integer;
+var r: integer;
+ s: str_number;
+begin
+ if byname > 0 then begin
+ s := tokens_to_string(i);
+ r := find_obj(t, s, true);
+ end
+ else begin
+ s := 0;
+ r := find_obj(t, i, false);
+ end;
+ if r = 0 then begin
+ if byname > 0 then begin
+ pdf_create_obj(t, -s);
+ s := 0;
+ end
+ else
+ pdf_create_obj(t, i);
+ r := obj_ptr;
+ if t = obj_type_dest then
+ obj_dest_ptr(r) := null;
+ end;
+ if s <> 0 then
+ flush_str(s);
+ get_obj := r;
+end;
+
+function get_microinterval:integer;
+var s,@!m:integer; {seconds and microseconds}
+begin
+ seconds_and_micros(s,m);
+ if (s-epochseconds)>32767 then
+ get_microinterval := max_integer
+ else if (microseconds>m) then
+ get_microinterval := ((s-1-epochseconds)*65536)+ (((m+1000000-microseconds)/100)*65536)/10000
+ else
+ get_microinterval := ((s-epochseconds)*65536) + (((m-microseconds)/100)*65536)/10000;
+end;
+
+
+@ @<Declare procedures needed in |do_ext...@>=
+function scan_action: pointer; {read an action specification}
+var p: integer;
+begin
+ p := new_node(action_node,0);
+ scan_action := p;
+ if scan_keyword("user") then
+ pdf_action_type(p) := pdf_action_user
+ else if scan_keyword("goto") then
+ pdf_action_type(p) := pdf_action_goto
+ else if scan_keyword("thread") then
+ pdf_action_type(p) := pdf_action_thread
+ else
+ pdf_error("ext1", "action type missing");
+ if pdf_action_type(p) = pdf_action_user then begin
+ scan_pdf_ext_toks;
+ pdf_action_tokens(p) := def_ref;
+ return;
+ end;
+ if scan_keyword("file") then begin
+ scan_pdf_ext_toks;
+ pdf_action_file(p) := def_ref;
+ end;
+ if scan_keyword("page") then begin
+ if pdf_action_type(p) <> pdf_action_goto then
+ pdf_error("ext1", "only GoTo action can be used with `page'");
+ pdf_action_type(p) := pdf_action_page;
+ scan_int;
+ if cur_val <= 0 then
+ pdf_error("ext1", "page number must be positive");
+ pdf_action_id(p) := cur_val;
+ pdf_action_named_id(p) := 0;
+ scan_pdf_ext_toks;
+ pdf_action_tokens(p) := def_ref;
+ end
+ else if scan_keyword("name") then begin
+ scan_pdf_ext_toks;
+ pdf_action_named_id(p) := 1;
+ pdf_action_id(p) := def_ref;
+ end
+ else if scan_keyword("num") then begin
+ if (pdf_action_type(p) = pdf_action_goto) and
+ (pdf_action_file(p) <> null) then
+ pdf_error("ext1",
+ "`goto' option cannot be used with both `file' and `num'");
+ scan_int;
+ if cur_val <= 0 then
+ pdf_error("ext1", "num identifier must be positive");
+ pdf_action_named_id(p) := 0;
+ pdf_action_id(p) := cur_val;
+ end
+ else
+ pdf_error("ext1", "identifier type missing");
+ if scan_keyword("newwindow") then begin
+ pdf_action_new_window(p) := 1;
+ @<Scan an optional space@>; end
+ else if scan_keyword("nonewwindow") then begin
+ pdf_action_new_window(p) := 2;
+ @<Scan an optional space@>; end
+ else
+ pdf_action_new_window(p) := 0;
+ if (pdf_action_new_window(p) > 0) and
+ (((pdf_action_type(p) <> pdf_action_goto) and
+ (pdf_action_type(p) <> pdf_action_page)) or
+ (pdf_action_file(p) = null)) then
+ pdf_error("ext1",
+ "`newwindow'/`nonewwindow' must be used with `goto' and `file' option");
+end;
+
+procedure new_annot_whatsit(w: small_number); {create a new whatsit node for
+annotation}
+begin
+ new_whatsit(w);
+ scan_alt_rule; {scans |<rule spec>| to |alt_rule|}
+ pdf_width(tail) := width(alt_rule);
+ pdf_height(tail) := height(alt_rule);
+ pdf_depth(tail) := depth(alt_rule);
+ if (w = pdf_thread_node) or (w = pdf_start_thread_node) then begin
+ if scan_keyword("attr") then begin
+ scan_pdf_ext_toks;
+ pdf_thread_attr(tail) := def_ref;
+ end
+ else
+ pdf_thread_attr(tail) := null;
+ end;
+end;
+
+@ @<Glob...@>=
+@!pdf_last_annot: integer;
+
+@ @<Implement \.{\\pdfannot}@>=
+begin
+ check_pdfoutput("\pdfannot", true);
+ if scan_keyword("reserveobjnum") then begin
+ pdf_last_annot := pdf_new_objnum;
+ @<Scan an optional space@>; end
+ else begin
+ if scan_keyword("useobjnum") then begin
+ scan_int;
+ k := cur_val;
+ if (k <= 0) or (k > obj_ptr) or (obj_annot_ptr(k) <> 0) then
+ pdf_error("ext1", "invalid object number");
+ end
+ else
+ k := pdf_new_objnum;
+ new_annot_whatsit(pdf_annot_node);
+ pdf_annot_objnum(tail) := k;
+ scan_pdf_ext_toks;
+ pdf_annot_data(tail) := def_ref;
+ pdf_last_annot := k;
+ end
+end
+
+@ pdflastlink needs an extra global variable
+@<Glob...@>=
+@!pdf_last_link: integer;
+
+@ @<Implement \.{\\pdfstartlink}@>=
+begin
+ check_pdfoutput("\pdfstartlink", true);
+ if abs(mode) = vmode then
+ pdf_error("ext1", "\pdfstartlink cannot be used in vertical mode");
+ k := pdf_new_objnum;
+ new_annot_whatsit(pdf_start_link_node);
+ pdf_link_attr(tail) := null;
+ if scan_keyword("attr") then begin
+ scan_pdf_ext_toks;
+ pdf_link_attr(tail) := def_ref;
+ end;
+ r := scan_action; pdf_link_action(tail) := r;
+ pdf_link_objnum(tail) := k;
+ pdf_last_link := k;
+ {N.B.: although it is possible to set |obj_annot_ptr(k) := tail| here, it
+ is not safe if nodes are later copied/destroyed/moved; a better place
+ to do this is inside |do_link|, when the whatsit node is written out}
+end
+
+@ @<Implement \.{\\pdfendlink}@>=
+begin
+ check_pdfoutput("\pdfendlink", true);
+ if abs(mode) = vmode then
+ pdf_error("ext1", "\pdfendlink cannot be used in vertical mode");
+ new_whatsit(pdf_end_link_node);
+end
+
+@ @<Declare procedures needed in |do_ext...@>=
+function outline_list_count(p: pointer): integer; {return number of outline
+entries in the same level with |p|}
+var k: integer;
+begin
+ k := 1;
+ while obj_outline_prev(p) <> 0 do begin
+ incr(k);
+ p := obj_outline_prev(p);
+ end;
+ outline_list_count := k;
+end;
+
+@ @<Implement \.{\\pdfoutline}@>=
+begin
+ check_pdfoutput("\pdfoutline", true);
+ if scan_keyword("attr") then begin
+ scan_pdf_ext_toks;
+ r := def_ref;
+ end
+ else
+ r := 0;
+ p := scan_action;
+ if scan_keyword("count") then begin
+ scan_int;
+ i := cur_val;
+ end
+ else
+ i := 0;
+ scan_pdf_ext_toks;
+ q := def_ref;
+ pdf_new_obj(obj_type_others, 0, 1);
+ j := obj_ptr;
+ write_action(p);
+ pdf_end_obj;
+ delete_action_ref(p);
+ pdf_create_obj(obj_type_outline, 0);
+ k := obj_ptr;
+ obj_outline_ptr(k) := pdf_get_mem(pdfmem_outline_size);
+ obj_outline_action_objnum(k) := j;
+ obj_outline_count(k) := i;
+ pdf_new_obj(obj_type_others, 0, 1);
+ pdf_print_str_ln(tokens_to_string(q));
+ flush_str(last_tokens_string);
+ delete_token_ref(q);
+ pdf_end_obj;
+ obj_outline_title(k) := obj_ptr;
+ obj_outline_prev(k) := 0;
+ obj_outline_next(k) := 0;
+ obj_outline_first(k) := 0;
+ obj_outline_last(k) := 0;
+ obj_outline_parent(k) := pdf_parent_outline;
+ obj_outline_attr(k) := r;
+ if pdf_first_outline = 0 then
+ pdf_first_outline := k;
+ if pdf_last_outline = 0 then begin
+ if pdf_parent_outline <> 0 then
+ obj_outline_first(pdf_parent_outline) := k;
+ end
+ else begin
+ obj_outline_next(pdf_last_outline) := k;
+ obj_outline_prev(k) := pdf_last_outline;
+ end;
+ pdf_last_outline := k;
+ if obj_outline_count(k) <> 0 then begin
+ pdf_parent_outline := k;
+ pdf_last_outline := 0;
+ end
+ else if (pdf_parent_outline <> 0) and
+ (outline_list_count(k) = abs(obj_outline_count(pdf_parent_outline))) then
+ begin
+ j := pdf_last_outline;
+ repeat
+ obj_outline_last(pdf_parent_outline) := j;
+ j := pdf_parent_outline;
+ pdf_parent_outline := obj_outline_parent(pdf_parent_outline);
+ until (pdf_parent_outline = 0) or
+ (outline_list_count(j) < abs(obj_outline_count(pdf_parent_outline)));
+ if pdf_parent_outline = 0 then
+ pdf_last_outline := pdf_first_outline
+ else
+ pdf_last_outline := obj_outline_first(pdf_parent_outline);
+ while obj_outline_next(pdf_last_outline) <> 0 do
+ pdf_last_outline := obj_outline_next(pdf_last_outline);
+ end;
+end
+
+@ When a destination is created we need to check whether another destination
+with the same identifier already exists and give a warning if needed.
+
+@<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure warn_dest_dup(id: integer; byname: small_number; s1, s2: str_number);
+begin
+ pdf_warning(s1, "destination with the same identifier (", false, false);
+ if byname > 0 then begin
+ print("name");
+ print_mark(id);
+ end
+ else begin
+ print("num");
+ print_int(id);
+ end;
+ print(") ");
+ print(s2);
+ print_ln;
+ show_context;
+end;
+
+@ Notice that |scan_keyword| doesn't care if two words have same prefix; so
+we should be careful when scan keywords with same prefix. The main rule: if
+there are two or more keywords with the same prefix, then always test in
+order from the longest one to the shortest one.
+
+@<Implement \.{\\pdfdest}@>=
+begin
+ check_pdfoutput("\pdfdest", true);
+ q := tail;
+ new_whatsit(pdf_dest_node);
+ if scan_keyword("num") then begin
+ scan_int;
+ if cur_val <= 0 then
+ pdf_error("ext1", "num identifier must be positive");
+ if cur_val > max_halfword then
+ pdf_error("ext1", "number too big");
+ pdf_dest_id(tail) := cur_val;
+ pdf_dest_named_id(tail) := 0;
+ end
+ else if scan_keyword("name") then begin
+ scan_pdf_ext_toks;
+ pdf_dest_id(tail) := def_ref;
+ pdf_dest_named_id(tail) := 1;
+ end
+ else
+ pdf_error("ext1", "identifier type missing");
+ if scan_keyword("xyz") then begin
+ pdf_dest_type(tail) := pdf_dest_xyz;
+ if scan_keyword("zoom") then begin
+ scan_int;
+ if cur_val > max_halfword then
+ pdf_error("ext1", "number too big");
+ pdf_dest_xyz_zoom(tail) := cur_val;
+ end
+ else
+ pdf_dest_xyz_zoom(tail) := null;
+ end
+ else if scan_keyword("fitbh") then
+ pdf_dest_type(tail) := pdf_dest_fitbh
+ else if scan_keyword("fitbv") then
+ pdf_dest_type(tail) := pdf_dest_fitbv
+ else if scan_keyword("fitb") then
+ pdf_dest_type(tail) := pdf_dest_fitb
+ else if scan_keyword("fith") then
+ pdf_dest_type(tail) := pdf_dest_fith
+ else if scan_keyword("fitv") then
+ pdf_dest_type(tail) := pdf_dest_fitv
+ else if scan_keyword("fitr") then
+ pdf_dest_type(tail) := pdf_dest_fitr
+ else if scan_keyword("fit") then
+ pdf_dest_type(tail) := pdf_dest_fit
+ else
+ pdf_error("ext1", "destination type missing");
+ @<Scan an optional space@>;
+ if pdf_dest_type(tail) = pdf_dest_fitr then begin
+ scan_alt_rule; {scans |<rule spec>| to |alt_rule|}
+ pdf_width(tail) := width(alt_rule);
+ pdf_height(tail) := height(alt_rule);
+ pdf_depth(tail) := depth(alt_rule);
+ end;
+ if pdf_dest_named_id(tail) <> 0 then begin
+ i := tokens_to_string(pdf_dest_id(tail));
+ k := find_obj(obj_type_dest, i, true);
+ flush_str(i);
+ end
+ else
+ k := find_obj(obj_type_dest, pdf_dest_id(tail), false);
+ if (k <> 0) and (obj_dest_ptr(k) <> null) then begin
+ warn_dest_dup(pdf_dest_id(tail), pdf_dest_named_id(tail),
+ "ext4", "has been already used, duplicate ignored");
+ flush_node_list(tail);
+ tail := q;
+ vlink(q) := null;
+ end;
+end
+
+@ @<Declare procedures needed in |do_ext...@>=
+procedure scan_thread_id;
+begin
+ if scan_keyword("num") then begin
+ scan_int;
+ if cur_val <= 0 then
+ pdf_error("ext1", "num identifier must be positive");
+ if cur_val > max_halfword then
+ pdf_error("ext1", "number too big");
+ pdf_thread_id(tail) := cur_val;
+ pdf_thread_named_id(tail) := 0;
+ end
+ else if scan_keyword("name") then begin
+ scan_pdf_ext_toks;
+ pdf_thread_id(tail) := def_ref;
+ pdf_thread_named_id(tail) := 1;
+ end
+ else
+ pdf_error("ext1", "identifier type missing");
+end;
+
+@ @<Implement \.{\\pdfthread}@>=
+begin
+ check_pdfoutput("\pdfthread", true);
+ new_annot_whatsit(pdf_thread_node);
+ scan_thread_id;
+end
+
+@ @<Implement \.{\\pdfstartthread}@>=
+begin
+ check_pdfoutput("\pdfstartthread", true);
+ new_annot_whatsit(pdf_start_thread_node);
+ scan_thread_id;
+end
+
+@ @<Implement \.{\\pdfendthread}@>=
+begin
+ check_pdfoutput("\pdfendthread", true);
+ new_whatsit(pdf_end_thread_node);
+end
+
+@ @<Glob...@>=
+@!pdf_last_x_pos: integer;
+@!pdf_last_y_pos: integer;
+
+@ @<Implement \.{\\pdfsavepos}@>=
+begin
+ new_whatsit(pdf_save_pos_node);
+end
+
+@ To implement primitives as \.{\\pdfinfo}, \.{\\pdfcatalog} or
+\.{\\pdfnames} we need to concatenate tokens lists.
+
+@<Declare procedures needed in |do_ext...@>=
+function concat_tokens(q, r: pointer): pointer; {concat |q| and |r| and
+returns the result tokens list}
+var p: pointer;
+begin
+ if q = null then begin
+ concat_tokens := r;
+ return;
+ end;
+ p := q;
+ while link(p) <> null do
+ p := link(p);
+ link(p) := link(r);
+ free_avail(r);
+ concat_tokens := q;
+end;
+
+@ @<Implement \.{\\pdfinfo}@>=
+begin
+ check_pdfoutput("\pdfinfo", false);
+ scan_pdf_ext_toks;
+ if pdf_output > 0 then
+ pdf_info_toks := concat_tokens(pdf_info_toks, def_ref);
+end
+
+@ @<Implement \.{\\pdfcatalog}@>=
+begin
+ check_pdfoutput("\pdfcatalog", false);
+ scan_pdf_ext_toks;
+ if pdf_output > 0 then
+ pdf_catalog_toks := concat_tokens(pdf_catalog_toks, def_ref);
+ if scan_keyword("openaction") then begin
+ if pdf_catalog_openaction <> 0 then
+ pdf_error("ext1", "duplicate of openaction")
+ else begin
+ p := scan_action;
+ pdf_new_obj(obj_type_others, 0, 1);
+ if pdf_output > 0 then
+ pdf_catalog_openaction := obj_ptr;
+ write_action(p);
+ pdf_end_obj;
+ delete_action_ref(p);
+ end;
+ end
+end
+
+@ @<Implement \.{\\pdfnames}@>=
+begin
+ check_pdfoutput("\pdfnames", true);
+ scan_pdf_ext_toks;
+ pdf_names_toks := concat_tokens(pdf_names_toks, def_ref);
+end
+
+@ @<Implement \.{\\pdftrailer}@>=
+begin
+ check_pdfoutput("\pdftrailer", false);
+ scan_pdf_ext_toks;
+ if pdf_output > 0 then
+ pdf_trailer_toks := concat_tokens(pdf_trailer_toks, def_ref);
+end
+
+@ @<Glob...@>=
+@!pdf_retval: integer; {global multi-purpose return value}
+
+@ @<Set initial values of key variables@>=
+ seconds_and_micros(epochseconds,microseconds);
+ init_start_time;
+
+@ Negative random seed values are silently converted to positive ones
+
+@<Implement \.{\\pdfsetrandomseed}@>=
+begin
+ scan_int;
+ if cur_val<0 then negate(cur_val);
+ random_seed := cur_val;
+ init_randoms(random_seed);
+end
+
+@ @<Implement \.{\\savecatcodetable}@>=
+begin
+ scan_int;
+ if (cur_val<0)or(cur_val>@"FFFFFFF) then begin
+ print_err("Invalid \catcode table");
+ help1("All \catcode table ids must be between 0 and 0xFFFFFFF");
+ error;
+ end
+ else begin if cur_val=cat_code_table then begin
+ print_err("Invalid \catcode table");
+ help1("You cannot overwrite the current \catcode table");
+ error;
+ end
+ else
+ copy_cat_codes(cat_code_table,cur_val);
+ end;
+end
+
+@ @<Implement \.{\\initcatcodetable}@>=
+begin
+ scan_int;
+ if (cur_val<0)or(cur_val>@"FFFFFFF) then begin
+ print_err("Invalid \catcode table");
+ help1("All \catcode table ids must be between 0 and 0xFFFFFFF");
+ error;
+ end
+ else begin if cur_val=cat_code_table then begin
+ print_err("Invalid \catcode table");
+ help1("You cannot overwrite the current \catcode table");
+ error;
+ end
+ else
+ initex_cat_codes(cur_val);
+ end;
+end
+
+@ The following subroutines are about PDF-specific font issues.
+
+@<Declare procedures needed in |do_ext...@>=
+procedure pdf_include_chars;
+var s: str_number;
+ k: pool_pointer; {running indices}
+ f: internal_font_number;
+begin
+ scan_font_ident;
+ f := cur_val;
+ if f = null_font then
+ pdf_error("font", "invalid font identifier");
+ pdf_check_vf_cur_val;
+ if not font_used(f) then
+ pdf_init_font(f);
+ scan_pdf_ext_toks;
+ s := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ k := str_start_macro(s);
+ while k < str_start_macro(s + 1) do begin
+ pdf_mark_char(f, str_pool[k]);
+ incr(k);
+ end;
+ flush_str(s);
+end;
+
+procedure glyph_to_unicode;
+var s1, s2: str_number;
+begin
+ scan_pdf_ext_toks;
+ s1 := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ scan_pdf_ext_toks;
+ s2 := tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ def_tounicode(s1, s2);
+ flush_str(s2);
+ flush_str(s1);
+end;
+
+@ @<Implement \.{\\pdfincludechars}@>=
+begin
+ check_pdfoutput("\pdfincludechars", true);
+ pdf_include_chars;
+end
+
+@ @<Implement \.{\\pdfglyphtounicode}@>=
+begin
+ glyph_to_unicode;
+end
+
+@ A change from \THANH's original code: the font attributes are simply
+initialized to zero now, this is easier to deal with from C than an
+empty \TeX{} string, and surely nobody will want to set
+\.{\\pdffontattr} to a string containing a single zero, as that
+would be nonsensical in the PDF output.
+
+@<Implement \.{\\pdffontattr}@>=
+begin
+ check_pdfoutput("\pdffontattr", true);
+ scan_font_ident;
+ k := cur_val;
+ if k = null_font then
+ pdf_error("font", "invalid font identifier");
+ scan_pdf_ext_toks;
+ set_pdf_font_attr(k, tokens_to_string(def_ref));
+ if length(pdf_font_attr(k)) = 0 then begin
+ flush_string;
+ set_pdf_font_attr(k,0);
+ end;
+end
+
+@ @<Implement \.{\\pdfmapfile}@>=
+begin
+ check_pdfoutput("\pdfmapfile", true);
+ scan_pdf_ext_toks;
+ pdfmapfile(def_ref);
+ delete_token_ref(def_ref);
+end
+
+@ @<Implement \.{\\pdfmapline}@>=
+begin
+ check_pdfoutput("\pdfmapline", true);
+ scan_pdf_ext_toks;
+ pdfmapline(def_ref);
+ delete_token_ref(def_ref);
+end
+
+@ The following function are needed for outputing article thread.
+
+@<Declare procedures needed in |do_ext...@>=
+procedure thread_title(thread: integer);
+begin
+ pdf_print("/Title (");
+ if obj_info(thread) < 0 then
+ pdf_print(-obj_info(thread))
+ else
+ pdf_print_int(obj_info(thread));
+ pdf_print_ln(")");
+end;
+
+procedure pdf_fix_thread(thread: integer);
+var a: pointer;
+begin
+ pdf_warning("thread", "destination ", false, false);
+ if obj_info(thread) < 0 then begin
+ print("name{");
+ print(-obj_info(thread));
+ print("}");
+ end
+ else begin
+ print("num");
+ print_int(obj_info(thread));
+ end;
+ print(" has been referenced but does not exist, replaced by a fixed one");
+ print_ln; print_ln;
+ pdf_new_dict(obj_type_others, 0, 0);
+ a := obj_ptr;
+ pdf_indirect_ln("T", thread);
+ pdf_indirect_ln("V", a);
+ pdf_indirect_ln("N", a);
+ pdf_indirect_ln("P", head_tab[obj_type_page]);
+ pdf_print("/R [0 0 ");
+ pdf_print_bp(page_width); pdf_out(" ");
+ pdf_print_bp(page_height);
+ pdf_print_ln("]");
+ pdf_end_dict;
+ pdf_begin_dict(thread, 1);
+ pdf_print_ln("/I << ");
+ thread_title(thread);
+ pdf_print_ln(">>");
+ pdf_indirect_ln("F", a);
+ pdf_end_dict;
+end;
+
+procedure out_thread(thread: integer);
+var a, b: pointer;
+ last_attr: integer;
+begin
+ if obj_thread_first(thread) = 0 then begin
+ pdf_fix_thread(thread);
+ return;
+ end;
+ pdf_begin_dict(thread, 1);
+ a := obj_thread_first(thread);
+ b := a;
+ last_attr := 0;
+ repeat
+ if obj_bead_attr(a) <> 0 then
+ last_attr := obj_bead_attr(a);
+ a := obj_bead_next(a);
+ until a = b;
+ if last_attr <> 0 then
+ pdf_print_ln(last_attr)
+ else begin
+ pdf_print_ln("/I << ");
+ thread_title(thread);
+ pdf_print_ln(">>");
+ end;
+ pdf_indirect_ln("F", a);
+ pdf_end_dict;
+ repeat
+ pdf_begin_dict(a, 1);
+ if a = b then
+ pdf_indirect_ln("T", thread);
+ pdf_indirect_ln("V", obj_bead_prev(a));
+ pdf_indirect_ln("N", obj_bead_next(a));
+ pdf_indirect_ln("P", obj_bead_page(a));
+ pdf_indirect_ln("R", obj_bead_rect(a));
+ pdf_end_dict;
+ a := obj_bead_next(a);
+ until a = b;
+end;
+
+@ @<Display <rule spec> for whatsit node created by \pdfTeX@>=
+print("(");
+print_rule_dimen(pdf_height(p));
+print_char("+");
+print_rule_dimen(pdf_depth(p));
+print(")x");
+print_rule_dimen(pdf_width(p))
+
+@ Each new type of node that appears in our data structure must be capable
+of being displayed, copied, destroyed, and so on. The routines that we
+need for write-oriented whatsits are somewhat like those for mark nodes;
+other extensions might, of course, involve more subtlety here.
+
+@<Basic printing...@>=
+procedure print_write_whatsit(@!s:str_number;@!p:pointer);
+begin print_esc(s);
+if write_stream(p)<16 then print_int(write_stream(p))
+else if write_stream(p)=16 then print_char("*")
+@.*\relax@>
+else print_char("-");
+end;
+
+@ Three extra node types carry information from |main_control|.
+
+@ |cancel_boundary_nodes| indicate that the next left boundary be
+ignored. These are created by the \.{\\noboundary} command in
+horizontal mode.
+
+@d cancel_boundary_node==pdf_restore_node+1
+@d cancel_boundary_size==3
+
+@<Append a |cancel_boundary_node| @>=
+begin new_whatsit(cancel_boundary_node);
+end
+
+@ User defined whatsits can be inserted into node lists to pass data
+along from one lua call to anotherb without interference from the
+typesetting engine itself. Each has an id, a type, and a value. The
+type of the value depends on the |user_node_type| field.
+
+@d user_defined_node==cancel_boundary_node+1
+@d user_defined_node_size=4
+@d user_node_id(#)==vlink(#+2)
+@d user_node_type(#)==vinfo(#+2)
+@d user_node_value(#)==vinfo(#+3)
+
+@ @<Display the whatsit...@>=
+case subtype(p) of
+open_node:begin print_write_whatsit("openout",p);
+ print_char("="); print_file_name(open_name(p),open_area(p),open_ext(p));
+ end;
+write_node:begin print_write_whatsit("write",p);
+ print_mark(write_tokens(p));
+ end;
+close_node:print_write_whatsit("closeout",p);
+special_node:begin print_esc("special");
+ print_mark(write_tokens(p));
+ end;
+dir_node:
+ if dir_dir(p)<0 then begin
+ print_esc("enddir"); print(" "); print_dir(dir_dir(p)+64);
+ end
+ else begin
+ print_esc("begindir"); print(" "); print_dir(dir_dir(p));
+ end;
+@<LOCAL: print out |local_paragraph| node@>;
+pdf_literal_node: begin
+ print_esc("pdfliteral");
+ case pdf_literal_mode(p) of
+ set_origin:
+ do_nothing;
+ direct_page:
+ print(" page");
+ direct_always:
+ print(" direct");
+ othercases confusion("literal2")
+ endcases;
+ print_mark(pdf_literal_data(p));
+end;
+pdf_colorstack_node: begin
+ print_esc("pdfcolorstack ");
+ print_int(pdf_colorstack_stack(p));
+ case pdf_colorstack_cmd(p) of
+ colorstack_set:
+ print(" set ");
+ colorstack_push:
+ print(" push ");
+ colorstack_pop:
+ print(" pop");
+ colorstack_current:
+ print(" current");
+ othercases confusion("pdfcolorstack")
+ endcases;
+ if pdf_colorstack_cmd(p) <= colorstack_data then
+ print_mark(pdf_colorstack_data(p));
+end;
+pdf_setmatrix_node: begin
+ print_esc("pdfsetmatrix");
+ print_mark(pdf_setmatrix_data(p));
+end;
+pdf_save_node: begin
+ print_esc("pdfsave");
+end;
+pdf_restore_node: begin
+ print_esc("pdfrestore");
+end;
+cancel_boundary_node: begin
+ print_esc("noboundary");
+end;
+late_lua_node: begin
+ print_esc("latelua");
+ print_int(late_lua_reg(p));
+ print_mark(late_lua_data(p));
+end;
+close_lua_node: begin
+ print_esc("closelua");
+ print_int(late_lua_reg(p));
+end;
+pdf_refobj_node: begin
+ print_esc("pdfrefobj");
+ if obj_obj_is_stream(pdf_obj_objnum(p)) > 0 then begin
+ if obj_obj_stream_attr(pdf_obj_objnum(p)) <> null then begin
+ print(" attr");
+ print_mark(obj_obj_stream_attr(pdf_obj_objnum(p)));
+ end;
+ print(" stream");
+ end;
+ if obj_obj_is_file(pdf_obj_objnum(p)) > 0 then
+ print(" file");
+ print_mark(obj_obj_data(pdf_obj_objnum(p)));
+end;
+pdf_refxform_node: begin
+ print_esc("pdfrefxform");
+ print("(");
+ print_scaled(obj_xform_height(pdf_xform_objnum(p)));
+ print_char("+");
+ print_scaled(obj_xform_depth(pdf_xform_objnum(p)));
+ print(")x");
+ print_scaled(obj_xform_width(pdf_xform_objnum(p)));
+end;
+pdf_refximage_node: begin
+ print_esc("pdfrefximage");
+ print("(");
+ print_scaled(pdf_height(p));
+ print_char("+");
+ print_scaled(pdf_depth(p));
+ print(")x");
+ print_scaled(pdf_width(p));
+end;
+pdf_annot_node: begin
+ print_esc("pdfannot");
+ @<Display <rule spec> for whatsit node created by \pdfTeX@>;
+ print_mark(pdf_annot_data(p));
+end;
+pdf_start_link_node: begin
+ print_esc("pdflink");
+ @<Display <rule spec> for whatsit node created by \pdfTeX@>;
+ if pdf_link_attr(p) <> null then begin
+ print(" attr");
+ print_mark(pdf_link_attr(p));
+ end;
+ print(" action");
+ if pdf_action_type(pdf_link_action(p)) = pdf_action_user then begin
+ print(" user");
+ print_mark(pdf_action_tokens(pdf_link_action(p)));
+ return;
+ end;
+ if pdf_action_file(pdf_link_action(p)) <> null then begin
+ print(" file");
+ print_mark(pdf_action_file(pdf_link_action(p)));
+ end;
+ case pdf_action_type(pdf_link_action(p)) of
+ pdf_action_goto: begin
+ if pdf_action_named_id(pdf_link_action(p)) > 0 then begin
+ print(" goto name");
+ print_mark(pdf_action_id(pdf_link_action(p)));
+ end
+ else begin
+ print(" goto num");
+ print_int(pdf_action_id(pdf_link_action(p)))
+ end;
+ end;
+ pdf_action_page: begin
+ print(" page");
+ print_int(pdf_action_id(pdf_link_action(p)));
+ print_mark(pdf_action_tokens(pdf_link_action(p)));
+ end;
+ pdf_action_thread: begin
+ if pdf_action_named_id(pdf_link_action(p)) > 0 then begin
+ print(" thread name");
+ print_mark(pdf_action_id(pdf_link_action(p)));
+ end
+ else begin
+ print(" thread num");
+ print_int(pdf_action_id(pdf_link_action(p)));
+ end;
+ end;
+ othercases pdf_error("displaying", "unknown action type");
+ endcases;
+end;
+pdf_end_link_node: print_esc("pdfendlink");
+pdf_dest_node: begin
+ print_esc("pdfdest");
+ if pdf_dest_named_id(p) > 0 then begin
+ print(" name");
+ print_mark(pdf_dest_id(p));
+ end
+ else begin
+ print(" num");
+ print_int(pdf_dest_id(p));
+ end;
+ print(" ");
+ case pdf_dest_type(p) of
+ pdf_dest_xyz: begin
+ print("xyz");
+ if pdf_dest_xyz_zoom(p) <> null then begin
+ print(" zoom");
+ print_int(pdf_dest_xyz_zoom(p));
+ end;
+ end;
+ pdf_dest_fitbh: print("fitbh");
+ pdf_dest_fitbv: print("fitbv");
+ pdf_dest_fitb: print("fitb");
+ pdf_dest_fith: print("fith");
+ pdf_dest_fitv: print("fitv");
+ pdf_dest_fitr: begin
+ print("fitr");
+ @<Display <rule spec> for whatsit node created by \pdfTeX@>;
+ end;
+ pdf_dest_fit: print("fit");
+ othercases print("unknown!");
+ endcases;
+end;
+pdf_thread_node,
+pdf_start_thread_node: begin
+ if subtype(p) = pdf_thread_node then
+ print_esc("pdfthread")
+ else
+ print_esc("pdfstartthread");
+ print("("); print_rule_dimen(pdf_height(p)); print_char("+");
+ print_rule_dimen(pdf_depth(p)); print(")x");
+ print_rule_dimen(pdf_width(p));
+ if pdf_thread_attr(p) <> null then begin
+ print(" attr");
+ print_mark(pdf_thread_attr(p));
+ end;
+ if pdf_thread_named_id(p) > 0 then begin
+ print(" name");
+ print_mark(pdf_thread_id(p));
+ end
+ else begin
+ print(" num");
+ print_int(pdf_thread_id(p));
+ end;
+end;
+pdf_end_thread_node: print_esc("pdfendthread");
+pdf_save_pos_node: print_esc("pdfsavepos");
+user_defined_node: begin
+ print_esc("whatsit");
+ print_int(user_node_id(p));
+ print_char("=");
+ case user_node_type(p) of
+ "a": print("<>");
+ "n": begin print("["); show_node_list(user_node_value(p)); print("]"); end;
+ "s": begin print(""""); print(user_node_value(p)); print(""""); end;
+ "t": print_mark(user_node_value(p));
+ othercases { only d }
+ print_int(user_node_value(p));
+ endcases;
+ end;
+othercases print("whatsit?")
+endcases
+
+@ @<Incorporate a whatsit node into a vbox@>=
+if (subtype(p) = pdf_refxform_node) or (subtype(p) = pdf_refximage_node) then
+begin x:=x+d+pdf_height(p); d:=pdf_depth(p);
+s:=0;
+if pdf_width(p)+s>w then w:=pdf_width(p)+s;
+end
+
+@ @<Incorporate a whatsit node into an hbox@>=
+begin
+if subtype(p)=dir_node then
+ begin
+ @<DIR: Adjust the dir stack for the |hpack| routine@>;
+ end
+else begin
+if (subtype(p) = pdf_refxform_node) or (subtype(p) = pdf_refximage_node) then
+begin x:=x+pdf_width(p);
+s:=0;
+if pdf_height(p)-s>h then h:=pdf_height(p)-s;
+if pdf_depth(p)+s>d then d:=pdf_depth(p)+s;
+end;
+end;
+end
+
+@ @<Let |d| be the width of the whatsit |p|@>=
+if (subtype(p) = pdf_refxform_node) or (subtype(p) = pdf_refximage_node) then
+ d := pdf_width(p)
+else
+ d := 0
+
+@ @<Prepare to move whatsit |p| to the current page, then |goto contribute|@>=
+begin
+ if (subtype(p) = pdf_refxform_node) or (subtype(p) = pdf_refximage_node) then
+ begin page_total:=page_total+page_depth+pdf_height(p);
+ page_depth:=pdf_depth(p);
+ end;
+ goto contribute;
+end
+
+@ @<Process whatsit |p| in |vert_break| loop, |goto not_found|@>=
+begin
+ if (subtype(p) = pdf_refxform_node) or (subtype(p) = pdf_refximage_node) then
+ begin cur_height:=cur_height+prev_dp+pdf_height(p); prev_dp:=pdf_depth(p);
+ end;
+ goto not_found;
+end
+
+@ @<Output the whatsit node |p| in a vlist@>=
+out_what(p)
+
+@ @<Output the whatsit node |p| in an hlist@>=
+if subtype(p)<>dir_node then out_what(p)
+else @<Output a reflection instruction if the direction has changed@>
+
+@ After all this preliminary shuffling, we come finally to the routines
+that actually send out the requested data. Let's do \.{\\special} first
+(it's easier).
+
+@<Declare procedures needed in |hlist_out|, |vlist_out|@>=
+procedure special_out(@!p:pointer);
+var old_setting:0..max_selector; {holds print |selector|}
+@!k:pool_pointer; {index into |str_pool|}
+begin synch_h; synch_v;@/
+old_setting:=selector; selector:=new_string;
+show_token_list(link(write_tokens(p)),null,pool_size-pool_ptr);
+selector:=old_setting;
+str_room(1);
+if cur_length<256 then
+ begin dvi_out(xxx1); dvi_out(cur_length);
+ end
+else begin dvi_out(xxx4); dvi_four(cur_length);
+ end;
+for k:=str_start_macro(str_ptr) to pool_ptr-1 do dvi_out(so(str_pool[k]));
+pool_ptr:=str_start_macro(str_ptr); {erase the string}
+end;
+
+@ To write a token list, we must run it through \TeX's scanner, expanding
+macros and \.{\\the} and \.{\\number}, etc. This might cause runaways,
+if a delimited macro parameter isn't matched, and runaways would be
+extremely confusing since we are calling on \TeX's scanner in the middle
+of a \.{\\shipout} command. Therefore we will put a dummy control sequence as
+a ``stopper,'' right after the token list. This control sequence is
+artificially defined to be \.{\\outer}.
+@:end_write_}{\.{\\endwrite}@>
+
+@<Initialize table...@>=
+text(end_write):="endwrite"; eq_level(end_write):=level_one;
+eq_type(end_write):=outer_call; equiv(end_write):=null;
+
+@ @<Declare procedures needed in |hlist_out|, |vlist_out|@>=
+procedure write_out(@!p:pointer);
+var old_setting:0..max_selector; {holds print |selector|}
+@!old_mode:integer; {saved |mode|}
+@!j:small_number; {write stream number}
+@!q,@!r:pointer; {temporary variables for list manipulation}
+begin @<Expand macros in the token list
+ and make |link(def_ref)| point to the result@>;
+old_setting:=selector; j:=write_stream(p);
+if write_open[j] then selector:=j
+else begin {write to the terminal if file isn't open}
+ if (j=17)and(selector=term_and_log) then selector:=log_only;
+ print_nl("");
+ end;
+token_show(def_ref); print_ln;
+flush_list(def_ref); selector:=old_setting;
+end;
+
+@ The final line of this routine is slightly subtle; at least, the author
+didn't think about it until getting burnt! There is a used-up token list
+@^Knuth, Donald Ervin@>
+on the stack, namely the one that contained |end_write_token|. (We
+insert this artificial `\.{\\endwrite}' to prevent runaways, as explained
+above.) If it were not removed, and if there were numerous writes on a
+single page, the stack would overflow.
+
+@d end_write_token==cs_token_flag+end_write
+
+@<Expand macros in the token list and...@>=
+q:=get_avail; info(q):=right_brace_token+"}";@/
+r:=get_avail; link(q):=r; info(r):=end_write_token; ins_list(q);@/
+begin_token_list(write_tokens(p),write_text);@/
+q:=get_avail; info(q):=left_brace_token+"{"; ins_list(q);
+{now we're ready to scan
+ `\.\{$\langle\,$token list$\,\rangle$\.{\} \\endwrite}'}
+old_mode:=mode; mode:=0;
+ {disable \.{\\prevdepth}, \.{\\spacefactor}, \.{\\lastskip}, \.{\\prevgraf}}
+cur_cs:=write_loc; q:=scan_toks(false,true); {expand macros, etc.}
+get_token;@+if cur_tok<>end_write_token then
+ @<Recover from an unbalanced write command@>;
+mode:=old_mode;
+end_token_list {conserve stack space}
+
+@ @<Recover from an unbalanced write command@>=
+begin print_err("Unbalanced write command");
+@.Unbalanced write...@>
+help2("On this page there's a \write with fewer real {'s than }'s.")@/
+("I can't handle that very well; good luck."); error;
+repeat get_token;
+until cur_tok=end_write_token;
+end
+
+@ The |out_what| procedure takes care of outputting whatsit nodes for
+|vlist_out| and |hlist_out|\kern-.3pt.
+
+@<Declare procedures needed in |hlist_out|, |vlist_out|@>=
+procedure out_what(@!p:pointer);
+var j:small_number; {write stream number}
+begin case subtype(p) of
+open_node,write_node,close_node:@<Do some work that has been queued up
+ for \.{\\write}@>;
+special_node:special_out(p);
+pdf_save_pos_node:
+ @<Save current position in DVI mode@>;
+local_par_node:do_nothing;
+cancel_boundary_node: do_nothing;
+othercases confusion("ext4") {TH: those will be pdf extension nodes in dvi mode, most likely}
+@:this can't happen ext4}{\quad ext4@>
+endcases;
+end;
+
+@ @<Save current position in DVI mode@>=
+begin
+ pdf_last_x_pos := cur_h + one_inch;
+ pdf_last_y_pos := cur_page_height - cur_v - one_inch;
+end
+
+@ We don't implement \.{\\write} inside of leaders. (The reason is that
+the number of times a leader box appears might be different in different
+implementations, due to machine-dependent rounding in the glue calculations.)
+@^leaders@>
+
+@<Do some work that has been queued up...@>=
+if not doing_leaders then
+ begin j:=write_stream(p);
+ if subtype(p)=write_node then write_out(p)
+ else begin if write_open[j] then lua_a_close_out(write_file[j]);
+ if subtype(p)=close_node then write_open[j]:=false
+ else if j<16 then
+ begin cur_name:=open_name(p); cur_area:=open_area(p);
+ cur_ext:=open_ext(p);
+ if cur_ext="" then cur_ext:=".tex";
+ pack_cur_name;
+ while not lua_a_open_out(write_file[j],(j+1)) do
+ prompt_file_name("output file name",".tex");
+ write_file[j]:= name_file_pointer;
+ write_open[j]:=true;
+ end;
+ end;
+ end
+
+@ The presence of `\.{\\immediate}' causes the |do_extension| procedure
+to descend to one level of recursion. Nothing happens unless \.{\\immediate}
+is followed by `\.{\\openout}', `\.{\\write}', or `\.{\\closeout}'.
+@^recursion@>
+
+@<Implement \.{\\immediate}@>=
+begin get_x_token;
+if cur_cmd=extension then begin
+ if cur_chr<=close_node then
+ begin p:=tail; do_extension; {append a whatsit node}
+ out_what(tail); {do the action immediately}
+ flush_node_list(tail); tail:=p; vlink(p):=null;
+ end
+ else case cur_chr of
+ close_lua_node: begin
+ scan_register_num;
+ closelua(cur_val);
+ end;
+ pdf_obj_code: begin
+ do_extension; {scan object and set |pdf_last_obj|}
+ if obj_data_ptr(pdf_last_obj) = 0 then {this object has not been initialized yet}
+ pdf_error("ext1", "`\pdfobj reserveobjnum' cannot be used with \immediate");
+ pdf_write_obj(pdf_last_obj);
+ end;
+ pdf_xform_code: begin
+ do_extension; {scan form and set |pdf_last_xform|}
+ pdf_cur_form := pdf_last_xform;
+ pdf_ship_out(obj_xform_box(pdf_last_xform), false);
+ end;
+ pdf_ximage_code: begin
+ do_extension; {scan image and set |pdf_last_ximage|}
+ pdf_write_image(pdf_last_ximage);
+ end;
+ othercases back_input
+ endcases;
+end
+else
+ back_input;
+end
+
+@ @<Finish the extensions@>=
+for k:=0 to 15 do if write_open[k] then lua_a_close_out(write_file[k])
+
+@
+@d local_pen_inter(#)==vinfo(#+2) {\.{\\localinterlinepenalty}}
+@d local_pen_broken(#)==vlink(#+2) {\.{\\localbrokenpenalty}}
+@d local_box_left(#)==vlink(#+3) {\.{\\localleftbox}}
+@d local_box_left_width(#)==vinfo(#+3)
+@d local_box_right(#)==vlink(#+4) {\.{\\localleftbox}}
+@d local_box_right_width(#)==vinfo(#+4)
+@d local_par_dir(#)==vinfo(#+5)
+@d local_par_size==6
+
+@<LOCAL: Declare |make_local_par_node|@>=
+function make_local_par_node:pointer;
+{This function creates a |local_paragraph| node}
+var p,q:pointer;
+begin
+p:=new_node(whatsit_node,local_par_node);
+local_pen_inter(p):=local_inter_line_penalty;
+local_pen_broken(p):=local_broken_penalty;
+if local_left_box<>null then begin
+ q:=copy_node_list(local_left_box); local_box_left(p):=q;
+ local_box_left_width(p):=width(local_left_box);
+ end;
+if local_right_box<>null then begin
+ q:=copy_node_list(local_right_box); local_box_right(p):=q;
+ local_box_right_width(p):=width(local_right_box);
+ end;
+local_par_dir(p):=par_direction;
+make_local_par_node:=p;
+end
+
+@ @<LOCAL: print out |local_paragraph| node@>=
+local_par_node: begin
+ print_esc("whatsit");
+ append_char(".");
+ print_ln; print_current_string;
+ print_esc("localinterlinepenalty"); print("=");
+ print_int(local_pen_inter(p));
+ print_ln; print_current_string;
+ print_esc("localbrokenpenalty"); print("=");
+ print_int(local_pen_broken(p));
+ print_ln; print_current_string;
+ print_esc("localleftbox");
+ if local_box_left(p)=null then print("=null")
+ else begin
+ append_char(".");
+ show_node_list(local_box_left(p));
+ decr(pool_ptr);
+ end;
+ print_ln; print_current_string;
+ print_esc("localrightbox");
+ if local_box_right(p)=null then print("=null")
+ else begin
+ append_char(".");
+ show_node_list(local_box_right(p));
+ decr(pool_ptr);
+ end;
+ decr(pool_ptr);
+ end
+
+@ @<LOCAL: Add local paragraph node@>=
+begin tail_append(make_local_par_node) end
+
+@ @<DIR: Assign direction codes@>=
+case cur_chr of
+dir_base+page_direction_code: begin
+ if its_all_over then begin
+ scan_direction;
+ eq_word_define(dir_base+page_direction_code,cur_val);
+ end;
+ end;
+dir_base+body_direction_code: begin
+ if its_all_over then begin
+ scan_direction;
+ eq_word_define(dir_base+body_direction_code,cur_val);
+ end;
+ end;
+dir_base+par_direction_code: begin
+ scan_direction;
+ eq_word_define(dir_base+par_direction_code,cur_val);
+ end;
+dir_base+text_direction_code: begin scan_direction;
+ if (no_local_dirs>0) and (abs(mode)=hmode) then begin
+ @<DIR: Add local dir node@>;
+ dir_dir(tail):=dir_dir(tail)-64;
+ end;
+ if dir_level(text_dir_ptr)=cur_level then
+ @<DIR: Remove from |text_dir_ptr|@>;
+ eq_word_define(dir_base+text_direction_code,cur_val);
+ @<DIR: Add to |text_dir_ptr|@>;
+ if abs(mode)=hmode then
+ begin
+ @<DIR: Add local dir node@>;
+ dir_level(tail):=cur_level;
+ end;
+ eq_word_define(int_base+no_local_dirs_code,no_local_dirs+1);
+ eq_word_define(int_base+level_local_dir_code,cur_level);
+ end;
+dir_base+math_direction_code: begin scan_direction;
+ eq_word_define(dir_base+math_direction_code,cur_val);
+ end;
+end;
+
+@
+@d push_dir(#)==
+begin dir_tmp:=new_dir(#);
+vlink(dir_tmp):=dir_ptr;
+dir_ptr:=dir_tmp;
+end
+
+@d push_dir_node(#)==
+begin dir_tmp:=copy_node(#);
+vlink(dir_tmp):=dir_ptr;
+dir_ptr:=dir_tmp;
+end
+
+@d pop_dir_node==
+begin dir_tmp:=dir_ptr;
+dir_ptr:=vlink(dir_tmp);
+flush_node(dir_tmp);
+end
+
+@ @<DIR: Declare |new_dir|@>=
+function new_dir(s:small_number): pointer;
+var p:pointer; {the new node}
+begin p:=new_node(whatsit_node,dir_node);
+dir_dir(p):=s; dir_dvi_ptr(p):=-1;
+dir_level(p):=cur_level; new_dir:=p;
+end
+
+@ @<Append a begin direction to the tail of the current list@>=
+tail_append(new_dir(math_direction))
+
+@ @<Append an end direction to the tail of the current list@>=
+tail_append(new_dir(math_direction-64))
+
+@ @<DIR: Add local dir node@>=
+tail_append(new_dir(text_direction))
+
+@ @<DIR: Adjust the dir stack for the |hpack| routine@>=
+begin
+if dir_dir(p)>=0 then begin
+ hpack_dir:=dir_dir(p);
+ push_dir_node(p);
+ end
+else begin
+ pop_dir_node;
+ if dir_ptr<>null then
+ hpack_dir:=dir_dir(dir_ptr);
+ end
+end
+
+@ @<DIR: Reset |dir_ptr|@>=
+begin
+ while dir_ptr<>null do
+ pop_dir_node
+end
+
+@ @<DIR: |unsave| math@>=
+begin
+unsave;
+decr(save_ptr);
+flush_node_list(text_dir_ptr);
+text_dir_ptr:=saved(0);
+end
+
+@ @<DIR: |new_save_level| math@>=
+begin
+saved(0):=text_dir_ptr;
+text_dir_ptr:=new_dir(math_direction);
+incr(save_ptr);
+new_save_level(c);
+eq_word_define(dir_base+body_direction_code,math_direction);
+eq_word_define(dir_base+par_direction_code,math_direction);
+eq_word_define(dir_base+text_direction_code,math_direction);
+eq_word_define(int_base+level_local_dir_code,cur_level);
+end
+
+@ @<DIR: Adjust |text_dir_ptr| for |scan_spec|@>=
+begin
+if spec_direction<>-1 then begin
+ saved(4):=text_dir_ptr;
+ text_dir_ptr:=new_dir(spec_direction);
+ end
+else saved(4):=null;
+end
+
+@ @<DIR: Adjust back |text_dir_ptr| for |scan_spec|@>=
+begin
+flush_node_list(text_dir_ptr);
+text_dir_ptr:=saved(4);
+end
+
+@ @<DIR: Add to |text_dir_ptr|@>=
+begin
+text_dir_tmp:=new_dir(text_direction);
+vlink(text_dir_tmp):=text_dir_ptr;
+text_dir_ptr:=text_dir_tmp;
+end
+
+@ @<DIR: Remove from |text_dir_ptr|@>=
+begin
+text_dir_tmp:=vlink(text_dir_ptr);
+flush_node(text_dir_ptr);
+text_dir_ptr:=text_dir_tmp;
+end
+
+@ @<DIR: Initialize |text_dir_ptr|@>=
+begin
+text_dir_ptr:=new_dir(0);
+end
+
+@ @<DIR: Initialize |dir_ptr| for |ship_out|@>=
+begin dir_ptr:=null; push_dir(dvi_direction);
+dir_dvi_ptr(dir_ptr):=dvi_ptr;
+end
+
+@ @<Output a reflection instruction if the direction has changed@>=
+begin
+if dir_dir(p)>=0 then
+ begin synch_h; synch_v;
+ push_dir_node(p);
+ if dir_opposite(dir_secondary[dir_dir(dir_ptr)])(dir_secondary[dvi_direction])
+ then begin
+ if (dir_secondary[dvi_direction]=0) or
+ (dir_secondary[dvi_direction]=2) then
+ dvi_out(down4)
+ else
+ dvi_out(right4);
+ dir_dvi_ptr(dir_ptr):=dvi_ptr;
+ dir_dvi_h(dir_ptr):=dvi_h;
+ dvi_four(0);
+ cur_h:=0; dvi_h:=0;
+ end
+ else begin
+ dir_dvi_ptr(dir_ptr):=dvi_ptr;
+ dir_dvi_h(dir_ptr):=dvi_h;
+ end;
+ dvi_direction:=dir_dir(dir_ptr);
+ end
+else begin
+ dvi_dir_h:=dir_dvi_h(dir_ptr);
+ dvi_dir_ptr:=dir_dvi_ptr(dir_ptr);
+ pop_dir_node;
+ synch_h; synch_v;
+ if dir_ptr<>null then
+ dvi_direction:=dir_dir(dir_ptr)
+ else
+ dvi_direction:=0;
+ if dir_opposite(dir_secondary[dir_dir(p)+64])(dir_secondary[dvi_direction])
+ then begin
+ dvi_temp_ptr:=dvi_ptr;
+ dvi_ptr:=dvi_dir_ptr;
+ if (dir_secondary[dvi_direction]=0) or
+ (dir_secondary[dvi_direction]=1) then
+ dvi_four(dvi_h)
+ else
+ dvi_four(-dvi_h);
+ dvi_ptr:=dvi_temp_ptr;
+ if (dir_secondary[dvi_direction]=0) or
+ (dir_secondary[dvi_direction]=2) then
+ dvi_out(down4)
+ else
+ dvi_out(right4);
+ if (dir_secondary[dvi_direction]=0) or
+ (dir_secondary[dvi_direction]=1) then
+ dvi_four(dvi_h)
+ else
+ dvi_four(-dvi_h);
+ end;
+ cur_h:=dvi_dir_h+dvi_h; dvi_h:=cur_h;
+ end
+end
+
+@ Many things regarding output work differently in pdf compared to dvi
+output. The easiest way to deal with in-line direction changes in pdf
+mode seems to be to move forward to find the needed width of the
+reversed section, then skip forward (or backward, depending on your
+viewpont) by that distance.
+
+@<(PDF) Output a reflection instruction if the direction has changed@>=
+begin
+if dir_dir(p)>=0 then begin
+ push_dir_node(p);
+ if dir_opposite(dir_secondary[dir_dir(dir_ptr)])(dir_secondary[dvi_direction])
+ then begin
+ @<(PDF) Calculate the needed width to the matching |enddir|, and store it in |w|, as
+ well as in the enddir's |dir_dvi_h|@>;
+ case box_direction(dvi_direction) of
+ dir_TL_,dir_BL_: pdf_dvicmd_right(w);
+ dir_TR_,dir_BR_: pdf_dvicmd_left(w);
+ end;
+ end;
+ dvi_direction:=dir_dir(dir_ptr);
+ end
+else begin
+ pop_dir_node;
+ if dir_ptr<>null then
+ dvi_direction:=dir_dir(dir_ptr)
+ else
+ dvi_direction:=0;
+ case box_direction(dvi_direction) of
+ dir_TL_,dir_BL_: pdf_dvicmd_right(dir_dvi_h(p));
+ dir_TR_,dir_BR_: pdf_dvicmd_left(dir_dvi_h(p));
+ end;
+ end
+end
+
+@ This code scans forward to the ending |dir_node| while keeping
+track of the needed width in |w|. When it finds the node that will end
+this segment, it stores the accumulated with in the |dir_dvi_h| field
+of that end node, so that when that node is found later in the
+processing, the correct glue correction can be applied.
+
+@<(PDF) Calculate the needed width to the matching |enddir|...@>=
+begin
+ q:=p; w:=0;
+ save_cur_g:=cur_g;
+ save_cur_glue:=cur_glue;
+ { to me, it looks like the next is needed. but Aleph doesn't do that,
+ so let us not do it either }
+ {|w:=w-cur_g; cur_glue:=0;|}
+ dir_nest:=1;
+ while (q<>null) and (vlink(q)<>null) do begin
+ q:=vlink(q);
+ if is_char_node(q) then begin
+ w:=w+glyph_width(q); {TODO no vertical support for now}
+ end
+ else begin
+ case type(q) of
+ hlist_node,vlist_node,rule_node,
+ margin_kern_node,kern_node:w:=w+width(q);
+ glue_node: begin
+ g:=glue_ptr(q);
+ w:=w+width(g)-cur_g;
+ if g_sign<>normal then
+ begin if g_sign=stretching then
+ begin if stretch_order(g)=g_order then
+ begin cur_glue:=cur_glue+stretch(g);
+ vet_glue(float(glue_set(this_box))*cur_glue);
+ cur_g:=round(glue_temp);
+ end;
+ end
+ else if shrink_order(g)=g_order then
+ begin cur_glue:=cur_glue-shrink(g);
+ vet_glue(float(glue_set(this_box))*cur_glue);
+ cur_g:=round(glue_temp);
+ end;
+ end;
+ w:=w+cur_g;
+ end;
+ math_node: w:=w+surround(q);
+ whatsit_node: begin
+ if subtype(q)=dir_node then begin
+ if dir_dir(q)>=0 then incr(dir_nest) else decr(dir_nest);
+ if dir_nest=0 then begin
+ dir_dvi_h(q) := w;
+ q:=null;
+ end;
+ end
+ else if (subtype(q) = pdf_refxform_node) or
+ (subtype(q) = pdf_refximage_node) then
+ w:=w+pdf_width(q);
+ end;
+ othercases do_nothing;
+ endcases;
+ end;
+ end;
+ cur_g:=save_cur_g;
+ cur_glue:=save_cur_glue;
+end
+
+
+@ Shipping out PDF marks.
+
+@<Types...@>=
+dest_name_entry = record
+ objname: str_number; {destination name}
+ objnum: integer; {destination object number}
+end;
+
+@ @<Glob...@>=
+@!cur_page_width: scaled; {width of page being shipped}
+@!cur_page_height: scaled; {height of page being shipped}
+@!cur_right_offset: scaled; {horizontal inverted offset of page being shipped}
+@!cur_bottom_offset: scaled; {vertical inverted offset of page being shipped}
+@!pdf_obj_list: pointer; {list of objects in the current page}
+@!pdf_xform_list: pointer; {list of forms in the current page}
+@!pdf_ximage_list: pointer; {list of images in the current page}
+@!last_thread: pointer; {pointer to the last thread}
+@!pdf_thread_ht, pdf_thread_dp, pdf_thread_wd: scaled; {dimensions of the last
+thread}
+@!pdf_last_thread_id: halfword; {identifier of the last thread}
+@!pdf_last_thread_named_id: boolean; {is identifier of the last thread named}
+@!pdf_thread_level: integer; {depth of nesting of box containing the last thread}
+@!pdf_annot_list: pointer; {list of annotations in the current page}
+@!pdf_link_list: pointer; {list of link annotations in the current page}
+@!pdf_dest_list: pointer; {list of destinations in the current page}
+@!pdf_bead_list: pointer; {list of thread beads in the current page}
+@!pdf_obj_count: integer; {counter of objects}
+@!pdf_xform_count: integer; {counter of forms}
+@!pdf_ximage_count: integer; {counter of images}
+@!pdf_cur_form: integer; {the form being output}
+@!pdf_first_outline, pdf_last_outline, pdf_parent_outline: integer;
+@!pdf_info_toks: pointer; {additional keys of Info dictionary}
+@!pdf_catalog_toks: pointer; {additional keys of Catalog dictionary}
+@!pdf_catalog_openaction: integer;
+@!pdf_names_toks: pointer; {additional keys of Names dictionary}
+@!pdf_dest_names_ptr: integer; {first unused position in |dest_names|}
+@!dest_names_size: integer; {maximum number of names in name tree of PDF output file}
+@!dest_names: ^dest_name_entry;
+@!pk_dpi: integer; {PK pixel density value from \.{texmf.cnf}}
+@!image_orig_x, image_orig_y: integer; {origin of cropped PDF images}
+@!pdf_trailer_toks: pointer; {additional keys of Trailer dictionary}
+
+@ @<Set init...@>=
+pdf_first_outline:= 0;
+pdf_last_outline:= 0;
+pdf_parent_outline:= 0;
+pdf_obj_count := 0;
+pdf_xform_count := 0;
+pdf_ximage_count := 0;
+pdf_dest_names_ptr := 0;
+pdf_info_toks := null;
+pdf_catalog_toks := null;
+pdf_names_toks := null;
+pdf_catalog_openaction := 0;
+pdf_trailer_toks := null;
+
+@ The following procedures are needed for outputing whatsit nodes for
+\pdfTeX{}.
+
+@<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure write_action(p: pointer); {write an action specification}
+var s: str_number;
+ d: integer;
+begin d:=0;
+ if pdf_action_type(p) = pdf_action_user then begin
+ pdf_print_toks_ln(pdf_action_tokens(p));
+ return;
+ end;
+ pdf_print("<< ");
+ if pdf_action_file(p) <> null then begin
+ pdf_print("/F ");
+ s := tokens_to_string(pdf_action_file(p));
+ if (str_pool[str_start_macro(s)] = 40) and
+ (str_pool[str_start_macro(s) + length(s) - 1] = 41) then
+ pdf_print(s)
+ else begin
+ pdf_print_str(s);
+ end;
+ flush_str(s);
+ pdf_print(" ");
+ if pdf_action_new_window(p) > 0 then begin
+ pdf_print("/NewWindow ");
+ if pdf_action_new_window(p) = 1 then
+ pdf_print("true ")
+ else
+ pdf_print("false ");
+ end;
+ end;
+ case pdf_action_type(p) of
+ pdf_action_page: begin
+ if pdf_action_file(p) = null then begin
+ pdf_print("/S /GoTo /D [");
+ pdf_print_int(get_obj(obj_type_page, pdf_action_id(p), false));
+ pdf_print(" 0 R");
+ end
+ else begin
+ pdf_print("/S /GoToR /D [");
+ pdf_print_int(pdf_action_id(p) - 1);
+ end;
+ pdf_out(" ");
+ pdf_print(tokens_to_string(pdf_action_tokens(p)));
+ flush_str(last_tokens_string);
+ pdf_out("]");
+ end;
+ pdf_action_goto: begin
+ if pdf_action_file(p) = null then begin
+ pdf_print("/S /GoTo ");
+ d := get_obj(obj_type_dest, pdf_action_id(p),
+ pdf_action_named_id(p));
+ end
+ else
+ pdf_print("/S /GoToR ");
+ if pdf_action_named_id(p) > 0 then begin
+ pdf_str_entry("D", tokens_to_string(pdf_action_id(p)));
+ flush_str(last_tokens_string);
+ end
+ else if pdf_action_file(p) = null then
+ pdf _indirect("D", d)
+ else
+ pdf_error("ext4", "`goto' option cannot be used with both `file' and `num'");
+ end;
+ pdf_action_thread: begin
+ pdf_print("/S /Thread ");
+ if pdf_action_file(p) = null then
+ d := get_obj(obj_type_thread, pdf_action_id(p),
+ pdf_action_named_id(p));
+ if pdf_action_named_id(p) > 0 then begin
+ pdf_str_entry("D", tokens_to_string(pdf_action_id(p)));
+ flush_str(last_tokens_string);
+ end
+ else if pdf_action_file(p) = null then
+ pdf_indirect("D", d)
+ else
+ pdf_int_entry("D", pdf_action_id(p));
+ end;
+ endcases;
+ pdf_print_ln(" >>");
+end;
+
+procedure set_rect_dimens(p, parent_box: pointer; x, y, w, h, d, margin: scaled);
+begin
+ pdf_left(p) := cur_h;
+ if is_running(w) then
+ pdf_right(p) := x + width(parent_box)
+ else
+ pdf_right(p) := cur_h + w;
+ if is_running(h) then
+ pdf_top(p) := y - height(parent_box)
+ else
+ pdf_top(p) := cur_v - h;
+ if is_running(d) then
+ pdf_bottom(p) := y + depth(parent_box)
+ else
+ pdf_bottom(p) := cur_v + d;
+ if is_shipping_page and matrixused then begin
+ matrixtransformrect(pdf_left(p), cur_page_height - pdf_bottom(p),
+ pdf_right(p), cur_page_height - pdf_top(p));
+ pdf_left(p) := getllx;
+ pdf_bottom(p) := cur_page_height - getlly;
+ pdf_right(p) := geturx;
+ pdf_top(p) := cur_page_height - getury;
+ end;
+ pdf_left(p) := pdf_left(p) - margin;
+ pdf_top(p) := pdf_top(p) - margin;
+ pdf_right(p) := pdf_right(p) + margin;
+ pdf_bottom(p) := pdf_bottom(p) + margin;
+end;
+
+procedure do_annot(p, parent_box: pointer; x, y: scaled);
+begin
+ if not is_shipping_page then
+ pdf_error("ext4", "annotations cannot be inside an XForm");
+ if doing_leaders then
+ return;
+ set_rect_dimens(p, parent_box, x, y,
+ pdf_width(p), pdf_height(p), pdf_depth(p), 0);
+ obj_annot_ptr(pdf_annot_objnum(p)) := p;
+ pdf_append_list(pdf_annot_objnum(p))(pdf_annot_list);
+end;
+
+@ To implement nesting link annotations, we need a stack to hold copy of
+|pdf_start_link_node|'s that are being written out, together with their box
+nesting level.
+
+@d pdf_link_stack_top == pdf_link_stack[pdf_link_stack_ptr]
+
+@<Constants...@>=
+@!pdf_max_link_level = 10; {maximum depth of link nesting}
+
+@ @<Types...@>=
+@!pdf_link_stack_record = record
+ nesting_level: small_number;
+ link_node: pointer; {holds a copy of the corresponding |pdf_start_link_node|}
+ ref_link_node: pointer; {points to original |pdf_start_link_node|, or a
+ copy of |link_node| created by |append_link| in
+ case of multi-line link}
+end;
+
+@ @<Glob...@>=
+@!pdf_link_stack: array[1..pdf_max_link_level] of pdf_link_stack_record;
+@!pdf_link_stack_ptr: small_number;
+
+@ @<Set init...@>=
+pdf_link_stack_ptr := 0;
+
+@ @<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure push_link_level(p: pointer);
+begin
+ if pdf_link_stack_ptr >= pdf_max_link_level then
+ overflow("pdf link stack size", pdf_max_link_level);
+ pdfassert((type(p) = whatsit_node) and (subtype(p) = pdf_start_link_node));
+ incr(pdf_link_stack_ptr);
+ pdf_link_stack_top.nesting_level := cur_s;
+ pdf_link_stack_top.link_node := copy_node_list(p);
+ pdf_link_stack_top.ref_link_node := p;
+end;
+
+procedure pop_link_level;
+begin
+ pdfassert(pdf_link_stack_ptr > 0);
+ flush_node_list(pdf_link_stack_top.link_node);
+ decr(pdf_link_stack_ptr);
+end;
+
+procedure do_link(p, parent_box: pointer; x, y: scaled);
+begin
+ if not is_shipping_page then
+ pdf_error("ext4", "link annotations cannot be inside an XForm");
+ pdfassert(type(parent_box) = hlist_node);
+ push_link_level(p);
+ set_rect_dimens(p, parent_box, x, y,
+ pdf_width(p), pdf_height(p), pdf_depth(p),
+ pdf_link_margin);
+ obj_annot_ptr(pdf_link_objnum(p)) := p; {the reference for the pdf annot object
+ must be set here}
+ pdf_append_list(pdf_link_objnum(p))(pdf_link_list);
+end;
+
+procedure end_link;
+var p: pointer;
+begin
+ if pdf_link_stack_ptr < 1 then
+ pdf_error("ext4", "pdf_link_stack empty, \pdfendlink used without \pdfstartlink?");
+ if pdf_link_stack_top.nesting_level <> cur_s then
+ pdf_error("ext4", "\pdfendlink ended up in different nesting level than \pdfstartlink");
+
+ {N.B.: test for running link must be done on |link_node| and not |ref_link_node|,
+ as |ref_link_node| can be set by |do_link| or |append_link| already}
+
+ if is_running(pdf_width(pdf_link_stack_top.link_node)) then begin
+ p := pdf_link_stack_top.ref_link_node;
+ if is_shipping_page and matrixused then begin
+ matrixrecalculate(cur_h + pdf_link_margin);
+ pdf_left(p) := getllx - pdf_link_margin;
+ pdf_top(p) := cur_page_height - getury - pdf_link_margin;
+ pdf_right(p) := geturx + pdf_link_margin;
+ pdf_bottom(p) := cur_page_height - getlly + pdf_link_margin;
+ end
+ else
+ pdf_right(p) := cur_h + pdf_link_margin;
+ end;
+ pop_link_level;
+end;
+
+@ For ``running'' annotations we must append a new node when the end of
+annotation is in other box than its start. The new created node is identical to
+corresponding whatsit node representing the start of annotation, but its
+|info| field is |max_halfword|. We set |info| field just before destroying the
+node, in order to use |flush_node_list| to do the job.
+
+@<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure append_link(parent_box: pointer; x, y: scaled; i: small_number); {append a new
+pdf annot to |pdf_link_list|}
+var p: pointer;
+begin
+ pdfassert(type(parent_box) = hlist_node);
+ p := copy_node(pdf_link_stack[i].link_node);
+ pdf_link_stack[i].ref_link_node := p;
+ subtype(p) := pdf_link_data_node; { this node is not a normal link node}
+ set_rect_dimens(p, parent_box, x, y,
+ pdf_width(p), pdf_height(p), pdf_depth(p),
+ pdf_link_margin);
+ pdf_create_obj(obj_type_others, 0);
+ obj_annot_ptr(obj_ptr) := p;
+ pdf_append_list(obj_ptr)(pdf_link_list);
+end;
+
+@ Threads are handled in similar way as link annotations.
+
+@<Declare procedures needed in |pdf_hlist_out|, |pdf_vlist_out|@>=
+procedure append_bead(p: pointer);
+var a, b, c, t: integer;
+begin
+ if not is_shipping_page then
+ pdf_error("ext4", "threads cannot be inside an XForm");
+ t := get_obj(obj_type_thread, pdf_thread_id(p), pdf_thread_named_id(p));
+ b := pdf_new_objnum;
+ obj_bead_ptr(b) := pdf_get_mem(pdfmem_bead_size);
+ obj_bead_page(b) := pdf_last_page;
+ obj_bead_data(b) := p;
+ if pdf_thread_attr(p) <> null then
+ obj_bead_attr(b) := tokens_to_string(pdf_thread_attr(p))
+ else
+ obj_bead_attr(b) := 0;
+ if obj_thread_first(t) = 0 then begin
+ obj_thread_first(t) := b;
+ obj_bead_next(b) := b;
+ obj_bead_prev(b) := b;
+ end
+ else begin
+ a := obj_thread_first(t);
+ c := obj_bead_prev(a);
+ obj_bead_prev(b) := c;
+ obj_bead_next(b) := a;
+ obj_bead_prev(a) := b;
+ obj_bead_next(c) := b;
+ end;
+ pdf_append_list(b)(pdf_bead_list);
+end;
+
+procedure do_thread(p, parent_box: pointer; x, y: scaled);
+begin
+ if doing_leaders then
+ return;
+ if subtype(p) = pdf_start_thread_node then begin
+ pdf_thread_wd := pdf_width(p);
+ pdf_thread_ht := pdf_height(p);
+ pdf_thread_dp := pdf_depth(p);
+ pdf_last_thread_id := pdf_thread_id(p);
+ pdf_last_thread_named_id := (pdf_thread_named_id(p) > 0);
+ if pdf_last_thread_named_id then
+ add_token_ref(pdf_thread_id(p));
+ pdf_thread_level := cur_s;
+ end;
+ set_rect_dimens(p, parent_box, x, y,
+ pdf_width(p), pdf_height(p), pdf_depth(p),
+ pdf_thread_margin);
+ append_bead(p);
+ last_thread := p;
+end;
+
+procedure append_thread(parent_box: pointer; x, y: scaled);
+var p: pointer;
+begin
+ p := new_node(whatsit_node,pdf_thread_data_node);
+ pdf_width(p) := pdf_thread_wd;
+ pdf_height(p) := pdf_thread_ht;
+ pdf_depth(p) := pdf_thread_dp;
+ pdf_thread_attr(p) := null;
+ pdf_thread_id(p) := pdf_last_thread_id;
+ if pdf_last_thread_named_id then begin
+ add_token_ref(pdf_thread_id(p));
+ pdf_thread_named_id(p) := 1;
+ end
+ else
+ pdf_thread_named_id(p) := 0;
+ set_rect_dimens(p, parent_box, x, y,
+ pdf_width(p), pdf_height(p), pdf_depth(p),
+ pdf_thread_margin);
+ append_bead(p);
+ last_thread := p;
+end;
+
+procedure end_thread;
+begin
+ if pdf_thread_level <> cur_s then
+ pdf_error("ext4", "\pdfendthread ended up in different nesting level than \pdfstartthread");
+ if is_running(pdf_thread_dp) and (last_thread <> null) then
+ pdf_bottom(last_thread) := cur_v + pdf_thread_margin;
+ if pdf_last_thread_named_id then
+ delete_token_ref(pdf_last_thread_id);
+ last_thread := null;
+end;
+
+function open_subentries(p: pointer): integer;
+var k, c: integer;
+ l, r: integer;
+begin
+ k := 0;
+ if obj_outline_first(p) <> 0 then begin
+ l := obj_outline_first(p);
+ repeat
+ incr(k);
+ c := open_subentries(l);
+ if obj_outline_count(l) > 0 then
+ k := k + c;
+ obj_outline_parent(l) := p;
+ r := obj_outline_next(l);
+ if r = 0 then
+ obj_outline_last(p) := l;
+ l := r;
+ until l = 0;
+ end;
+ if obj_outline_count(p) > 0 then
+ obj_outline_count(p) := k
+ else
+ obj_outline_count(p) := -k;
+ open_subentries := k;
+end;
+
+procedure do_dest(p, parent_box: pointer; x, y: scaled);
+var k: integer;
+begin
+ if not is_shipping_page then
+ pdf_error("ext4", "destinations cannot be inside an XForm");
+ if doing_leaders then
+ return;
+ k := get_obj(obj_type_dest, pdf_dest_id(p), pdf_dest_named_id(p));
+ if obj_dest_ptr(k) <> null then begin
+ warn_dest_dup(pdf_dest_id(p), pdf_dest_named_id(p),
+ "ext4", "has been already used, duplicate ignored");
+ return;
+ end;
+ obj_dest_ptr(k) := p;
+ pdf_append_list(k)(pdf_dest_list);
+ case pdf_dest_type(p) of
+ pdf_dest_xyz:
+ if matrixused then
+ set_rect_dimens(p, parent_box, x, y,
+ pdf_width(p), pdf_height(p), pdf_depth(p),
+ pdf_dest_margin)
+ else begin
+ pdf_left(p) := cur_h;
+ pdf_top(p) := cur_v;
+ end;
+ pdf_dest_fith,
+ pdf_dest_fitbh:
+ if matrixused then
+ set_rect_dimens(p, parent_box, x, y,
+ pdf_width(p), pdf_height(p), pdf_depth(p),
+ pdf_dest_margin)
+ else
+ pdf_top(p) := cur_v;
+ pdf_dest_fitv,
+ pdf_dest_fitbv:
+ if matrixused then
+ set_rect_dimens(p, parent_box, x, y,
+ pdf_width(p), pdf_height(p), pdf_depth(p),
+ pdf_dest_margin)
+ else
+ pdf_left(p) := cur_h;
+ pdf_dest_fit,
+ pdf_dest_fitb:
+ do_nothing;
+ pdf_dest_fitr:
+ set_rect_dimens(p, parent_box, x, y,
+ pdf_width(p), pdf_height(p), pdf_depth(p),
+ pdf_dest_margin);
+ endcases;
+end;
+
+procedure out_form(p: pointer);
+var v: scaled;
+begin
+ pdf_end_text;
+ pdf_print_ln("q");
+ if pdf_lookup_list(pdf_xform_list, pdf_xform_objnum(p)) = null then
+ pdf_append_list(pdf_xform_objnum(p))(pdf_xform_list);
+ v := cur_v + obj_xform_depth(pdf_xform_objnum(p));
+ pdf_set_origin_temp(cur_h, v);
+ pdf_print("/Fm");
+ pdf_print_int(obj_info(pdf_xform_objnum(p)));
+ pdf_print_resname_prefix;
+ pdf_print_ln(" Do");
+ pdf_print_ln("Q");
+end;
+
+@ @<Output the whatsit node |p| in |pdf_vlist_out|@>=
+case subtype(p) of
+pdf_literal_node:
+ pdf_out_literal(p);
+pdf_colorstack_node:
+ pdf_out_colorstack(p);
+pdf_setmatrix_node:
+ pdf_out_setmatrix(p);
+pdf_save_node:
+ pdf_out_save;
+pdf_restore_node:
+ pdf_out_restore;
+late_lua_node:
+ do_late_lua(p);
+close_lua_node:
+ closelua(late_lua_reg(p));
+pdf_refobj_node:
+ pdf_append_list(pdf_obj_objnum(p))(pdf_obj_list);
+pdf_refxform_node:
+ @<Output a Form node in a vlist@>;
+pdf_refximage_node:
+ @<Output a Image node in a vlist@>;
+pdf_annot_node:
+ do_annot(p, this_box, left_edge, top_edge + height(this_box));
+pdf_start_link_node:
+ pdf_error("ext4", "\pdfstartlink ended up in vlist");
+pdf_end_link_node:
+ pdf_error("ext4", "\pdfendlink ended up in vlist");
+pdf_dest_node:
+ do_dest(p, this_box, left_edge, top_edge + height(this_box));
+pdf_thread_node,
+pdf_start_thread_node:
+ do_thread(p, this_box, left_edge, top_edge + height(this_box));
+pdf_end_thread_node:
+ end_thread;
+pdf_save_pos_node:
+ @<Save current position to |pdf_last_x_pos|, |pdf_last_y_pos|@>;
+special_node:
+ pdf_special(p);
+othercases out_what(p);
+endcases
+
+@ @<Glob...@>=
+@!is_shipping_page: boolean; {set to |shipping_page| when |pdf_ship_out| starts}
+
+@ @<Save current position to |pdf_last_x_pos|, |pdf_last_y_pos|@>=
+begin
+ pdf_last_x_pos := cur_h;
+ pdf_last_y_pos := cur_page_height - cur_v
+end
+
+@ @<Output a Image node in a vlist@>=
+begin cur_v:=cur_v+pdf_height(p)+pdf_depth(p);
+ cur_h:=left_edge;
+ out_image(pdf_ximage_ref(p), cur_h-pdf_origin_h, pdf_origin_v-cur_v);
+ if pdf_lookup_list(pdf_ximage_list, image_objnum(pdf_ximage_ref(p))) = null then
+ pdf_append_list(image_objnum(pdf_ximage_ref(p)))(pdf_ximage_list);
+end
+
+@ @<Output a Form node in a vlist@>=
+begin cur_v:=cur_v+pdf_height(p);
+ cur_h:=left_edge;
+ out_form(p);
+ cur_v:=cur_v+pdf_depth(p);
+end
+
+@ @<Output the whatsit node |p| in |pdf_hlist_out|@>=
+case subtype(p) of
+pdf_literal_node:
+ pdf_out_literal(p);
+pdf_colorstack_node:
+ pdf_out_colorstack(p);
+pdf_setmatrix_node:
+ pdf_out_setmatrix(p);
+pdf_save_node:
+ pdf_out_save;
+pdf_restore_node:
+ pdf_out_restore;
+late_lua_node:
+ do_late_lua(p);
+close_lua_node:
+ closelua(late_lua_reg(p));
+pdf_refobj_node:
+ pdf_append_list(pdf_obj_objnum(p))(pdf_obj_list);
+pdf_refxform_node:
+ @<Output a Form node in a hlist@>;
+pdf_refximage_node:
+ @<Output a Image node in a hlist@>;
+pdf_annot_node:
+ do_annot(p, this_box, left_edge, base_line);
+pdf_start_link_node:
+ do_link(p, this_box, left_edge, base_line);
+pdf_end_link_node:
+ end_link;
+pdf_dest_node:
+ do_dest(p, this_box, left_edge, base_line);
+pdf_thread_node:
+ do_thread(p, this_box, left_edge, base_line);
+pdf_start_thread_node:
+ pdf_error("ext4", "\pdfstartthread ended up in hlist");
+pdf_end_thread_node:
+ pdf_error("ext4", "\pdfendthread ended up in hlist");
+pdf_save_pos_node:
+ @<Save current position to |pdf_last_x_pos|, |pdf_last_y_pos|@>;
+special_node:
+ pdf_special(p);
+othercases if subtype(p)<>dir_node then out_what(p)
+else @<(PDF) Output a reflection instruction if the direction has changed@>;
+endcases
+
+@ @<Output a Image node in a hlist@>=
+begin
+ cur_v:=base_line+pdf_depth(p);
+ out_image(pdf_ximage_ref(p), cur_h-pdf_origin_h, pdf_origin_v-cur_v);
+ if pdf_lookup_list(pdf_ximage_list, image_objnum(pdf_ximage_ref(p))) = null then
+ pdf_append_list(image_objnum(pdf_ximage_ref(p)))(pdf_ximage_list);
+ edge:=cur_h+pdf_width(p); cur_h:=edge; cur_v:=base_line;
+end
+
+@ @<Output a Form node in a hlist@>=
+begin
+ cur_v:=base_line;
+ out_form(p);
+ edge:=cur_h+pdf_width(p); cur_h:=edge;
+end
+
+@* \[53a] The extended features of \eTeX.
+The program has two modes of operation: (1)~In \TeX\ compatibility mode
+it fully deserves the name \TeX\ and there are neither extended features
+nor additional primitive commands. There are, however, a few
+modifications that would be legitimate in any implementation of \TeX\
+such as, e.g., preventing inadequate results of the glue to \.{DVI}
+unit conversion during |ship_out|. (2)~In extended mode there are
+additional primitive commands and the extended features of \eTeX\ are
+available.
+
+The distinction between these two modes of operation initially takes
+place when a `virgin' \.{eINITEX} starts without reading a format file.
+Later on the values of all \eTeX\ state variables are inherited when
+\.{eVIRTEX} (or \.{eINITEX}) reads a format file.
+
+The code below is designed to work for cases where `$|init|\ldots|tini|$'
+is a run-time switch.
+
+@<Enable \eTeX, if requested@>=
+@!init if format_ident=" (INITEX)" then
+ begin no_new_control_sequence:=false;
+ @<Generate all \eTeX\ primitives@>@;
+ if buffer[loc]="*" then incr(loc);
+ end;
+tini@;@/
+if not no_new_control_sequence then {just entered extended mode ?}
+ no_new_control_sequence:=true@+else
+
+@ The \eTeX\ features available in extended mode are grouped into two
+categories: (1)~Some of them are permanently enabled and have no
+semantic effect as long as none of the additional primitives are
+executed. (2)~The remaining \eTeX\ features are optional and can be
+individually enabled and disabled. For each optional feature there is
+an \eTeX\ state variable named \.{\\...state}; the feature is enabled,
+resp.\ disabled by assigning a positive, resp.\ non-positive value to
+that integer.
+
+
+@d Aleph_version_code=Aleph_int {code for \.{\\Alephversion}}
+@d Omega_version_code=Aleph_int+1 {code for \.{\\Omegaversion}}
+@d Aleph_minor_version_code=Aleph_int+2 {code for \.{\\Alephminorversion}}
+@d Omega_minor_version_code=Aleph_int+3 {code for \.{\\Omegaminorversion}}
+@d eTeX_minor_version_code=Aleph_int+4 {code for \.{\\eTeXminorversion}}
+@d eTeX_version_code=eTeX_int {code for \.{\\eTeXversion}}
+@d Aleph_revision_code=job_name_code+1 {command code for \.{\\Alephrevision}}
+@d Omega_revision_code=job_name_code+2 {command code for \.{\\Omegarevision}}
+@d eTeX_revision_code=job_name_code+3 {command code for \.{\\eTeXrevision}}
+
+@<Generate all \eTeX...@>=
+primitive("lastnodetype",last_item,last_node_type_code);
+@!@:last_node_type_}{\.{\\lastnodetype} primitive@>
+primitive("Alephversion",last_item,Aleph_version_code);
+@!@:eTeX_version_}{\.{\\Alephversion} primitive@>
+primitive("Omegaversion",last_item,Omega_version_code);
+@!@:eTeX_version_}{\.{\\Omegaversion} primitive@>
+primitive("eTeXversion",last_item,eTeX_version_code);
+@!@:eTeX_version_}{\.{\\eTeXversion} primitive@>
+primitive("Alephminorversion",last_item,Aleph_minor_version_code);
+@!@:eTeX_minor_version_}{\.{\\Alephminorversion} primitive@>
+primitive("Omegaminorversion",last_item,Omega_minor_version_code);
+@!@:eTeX_minor_version_}{\.{\\Omegaminorversion} primitive@>
+primitive("eTeXminorversion",last_item,eTeX_minor_version_code);
+@!@:eTeX_minor_version_}{\.{\\eTeXminorversion} primitive@>
+primitive("Alephrevision",convert,Aleph_revision_code);@/
+@!@:eTeX_revision_}{\.{\\Alephrevision} primitive@>
+primitive("Omegarevision",convert,Omega_revision_code);@/
+@!@:eTeX_revision_}{\.{\\Omegarevision} primitive@>
+primitive("eTeXrevision",convert,eTeX_revision_code);@/
+@!@:eTeX_revision_}{\.{\\eTeXrevision} primitive@>
+
+@ @<Cases of |last_item| for |print_cmd_chr|@>=
+last_node_type_code: print_esc("lastnodetype");
+Aleph_version_code: print_esc("Alephversion");
+Omega_version_code: print_esc("Omegaversion");
+eTeX_version_code: print_esc("eTeXversion");
+Aleph_minor_version_code: print_esc("Alephminorversion");
+Omega_minor_version_code: print_esc("Omegaminorversion");
+eTeX_minor_version_code: print_esc("eTeXminorversion");
+
+
+@ @<Cases for fetching an integer value@>=
+Aleph_version_code: cur_val:=Aleph_version;
+Omega_version_code: cur_val:=Omega_version;
+eTeX_version_code: cur_val:=eTeX_version;
+Aleph_minor_version_code: cur_val:=Aleph_minor_version;
+Omega_minor_version_code: cur_val:=Omega_minor_version;
+eTeX_minor_version_code: cur_val:=eTeX_minor_version;
+
+@ @<Cases of |convert| for |print_cmd_chr|@>=
+Aleph_revision_code: print_esc("Alephrevision");
+Omega_revision_code: print_esc("Omegarevision");
+eTeX_revision_code: print_esc("eTeXrevision");
+
+@ @<Cases of `Scan the argument for command |c|'@>=
+Aleph_revision_code: do_nothing;
+Omega_revision_code: do_nothing;
+eTeX_revision_code: do_nothing;
+
+@ @<Cases of `Print the result of command |c|'@>=
+Aleph_revision_code: print(Aleph_revision);
+Omega_revision_code: print(Omega_revision);
+eTeX_revision_code: print(eTeX_revision);
+
+@ First we implement the additional \eTeX\ parameters in the table of
+equivalents.
+
+@<Generate all \eTeX...@>=
+primitive("everyeof",assign_toks,every_eof_loc);
+@!@:every_eof_}{\.{\\everyeof} primitive@>
+primitive("tracingassigns",assign_int,int_base+tracing_assigns_code);@/
+@!@:tracing_assigns_}{\.{\\tracingassigns} primitive@>
+primitive("tracinggroups",assign_int,int_base+tracing_groups_code);@/
+@!@:tracing_groups_}{\.{\\tracinggroups} primitive@>
+primitive("tracingifs",assign_int,int_base+tracing_ifs_code);@/
+@!@:tracing_ifs_}{\.{\\tracingifs} primitive@>
+primitive("tracingscantokens",assign_int,int_base+tracing_scan_tokens_code);@/
+@!@:tracing_scan_tokens_}{\.{\\tracingscantokens} primitive@>
+primitive("tracingnesting",assign_int,int_base+tracing_nesting_code);@/
+@!@:tracing_nesting_}{\.{\\tracingnesting} primitive@>
+primitive("predisplaydirection",
+ assign_int,int_base+pre_display_direction_code);@/
+@!@:pre_display_direction_}{\.{\\predisplaydirection} primitive@>
+primitive("lastlinefit",assign_int,int_base+last_line_fit_code);@/
+@!@:last_line_fit_}{\.{\\lastlinefit} primitive@>
+primitive("savingvdiscards",assign_int,int_base+saving_vdiscards_code);@/
+@!@:saving_vdiscards_}{\.{\\savingvdiscards} primitive@>
+primitive("savinghyphcodes",assign_int,int_base+saving_hyph_codes_code);@/
+@!@:saving_hyph_codes_}{\.{\\savinghyphcodes} primitive@>
+primitive("suppressfontnotfounderror",assign_int,int_base+suppress_fontnotfound_error_code);@/
+@!@:suppress_fontnotfound_error_codes_}{\.{\\suppressfontnotfounderror} primitive@>
+
+@ @d every_eof==equiv(every_eof_loc)
+
+@<Cases of |assign_toks| for |print_cmd_chr|@>=
+every_eof_loc: print_esc("everyeof");
+
+@ @<Cases for |print_param|@>=
+tracing_assigns_code:print_esc("tracingassigns");
+tracing_groups_code:print_esc("tracinggroups");
+tracing_ifs_code:print_esc("tracingifs");
+tracing_scan_tokens_code:print_esc("tracingscantokens");
+tracing_nesting_code:print_esc("tracingnesting");
+pre_display_direction_code:print_esc("predisplaydirection");
+last_line_fit_code:print_esc("lastlinefit");
+saving_vdiscards_code:print_esc("savingvdiscards");
+saving_hyph_codes_code:print_esc("savinghyphcodes");
+suppress_fontnotfound_error_code:print_esc("suppressfontnotfounderror");
+
+@ In order to handle \.{\\everyeof} we need an array |eof_seen| of
+boolean variables.
+
+@<Glob...@>=
+@!eof_seen : array[1..max_in_open] of boolean; {has eof been seen?}
+
+@ The |print_group| procedure prints the current level of grouping and
+the name corresponding to |cur_group|.
+
+@<Declare \eTeX\ procedures for tr...@>=
+procedure print_group(@!e:boolean);
+label exit;
+begin case cur_group of
+ bottom_level: begin print("bottom level"); return;
+ end;
+ simple_group,semi_simple_group:
+ begin if cur_group=semi_simple_group then print("semi ");
+ print("simple");
+ end;
+ hbox_group,adjusted_hbox_group:
+ begin if cur_group=adjusted_hbox_group then print("adjusted ");
+ print("hbox");
+ end;
+ vbox_group: print("vbox");
+ vtop_group: print("vtop");
+ align_group,no_align_group:
+ begin if cur_group=no_align_group then print("no ");
+ print("align");
+ end;
+ output_group: print("output");
+ disc_group: print("disc");
+ insert_group: print("insert");
+ vcenter_group: print("vcenter");
+ math_group,math_choice_group,math_shift_group,math_left_group:
+ begin print("math");
+ if cur_group=math_choice_group then print(" choice")
+ else if cur_group=math_shift_group then print(" shift")
+ else if cur_group=math_left_group then print(" left");
+ end;
+ end; {there are no other cases}
+print(" group (level "); print_int(qo(cur_level)); print_char(")");
+if saved(-1)<>0 then
+ begin if e then print(" entered at line ") else print(" at line ");
+ print_int(saved(-1));
+ end;
+exit:end;
+
+@ The |group_trace| procedure is called when a new level of grouping
+begins (|e=false|) or ends (|e=true|) with |saved(-1)| containing the
+line number.
+
+@<Declare \eTeX\ procedures for tr...@>=
+@!stat procedure group_trace(@!e:boolean);
+begin begin_diagnostic; print_char("{");
+if e then print("leaving ") else print("entering ");
+print_group(e); print_char("}"); end_diagnostic(false);
+end;
+tats
+
+@ The \.{\\currentgrouplevel} and \.{\\currentgrouptype} commands return
+the current level of grouping and the type of the current group
+respectively.
+
+@d current_group_level_code=eTeX_int+1 {code for \.{\\currentgrouplevel}}
+@d current_group_type_code=eTeX_int+2 {code for \.{\\currentgrouptype}}
+
+@<Generate all \eTeX...@>=
+primitive("currentgrouplevel",last_item,current_group_level_code);
+@!@:current_group_level_}{\.{\\currentgrouplevel} primitive@>
+primitive("currentgrouptype",last_item,current_group_type_code);
+@!@:current_group_type_}{\.{\\currentgrouptype} primitive@>
+
+@ @<Cases of |last_item| for |print_cmd_chr|@>=
+current_group_level_code: print_esc("currentgrouplevel");
+current_group_type_code: print_esc("currentgrouptype");
+
+@ @<Cases for fetching an integer value@>=
+current_group_level_code: cur_val:=cur_level-level_one;
+current_group_type_code: cur_val:=cur_group;
+
+@ The \.{\\currentiflevel}, \.{\\currentiftype}, and
+\.{\\currentifbranch} commands return the current level of conditionals
+and the type and branch of the current conditional.
+
+@d current_if_level_code=eTeX_int+3 {code for \.{\\currentiflevel}}
+@d current_if_type_code=eTeX_int+4 {code for \.{\\currentiftype}}
+@d current_if_branch_code=eTeX_int+5 {code for \.{\\currentifbranch}}
+
+@<Generate all \eTeX...@>=
+primitive("currentiflevel",last_item,current_if_level_code);
+@!@:current_if_level_}{\.{\\currentiflevel} primitive@>
+primitive("currentiftype",last_item,current_if_type_code);
+@!@:current_if_type_}{\.{\\currentiftype} primitive@>
+primitive("currentifbranch",last_item,current_if_branch_code);
+@!@:current_if_branch_}{\.{\\currentifbranch} primitive@>
+
+@ @<Cases of |last_item| for |print_cmd_chr|@>=
+current_if_level_code: print_esc("currentiflevel");
+current_if_type_code: print_esc("currentiftype");
+current_if_branch_code: print_esc("currentifbranch");
+
+@ @<Cases for fetching an integer value@>=
+current_if_level_code: begin q:=cond_ptr; cur_val:=0;
+ while q<>null do
+ begin incr(cur_val); q:=vlink(q);
+ end;
+ end;
+current_if_type_code: if cond_ptr=null then cur_val:=0
+ else if cur_if<unless_code then cur_val:=cur_if+1
+ else cur_val:=-(cur_if-unless_code+1);
+current_if_branch_code:
+ if (if_limit=or_code)or(if_limit=else_code) then cur_val:=1
+ else if if_limit=fi_code then cur_val:=-1
+ else cur_val:=0;
+
+@ The \.{\\fontcharwd}, \.{\\fontcharht}, \.{\\fontchardp}, and
+\.{\\fontcharic} commands return information about a character in a
+font.
+
+@d font_char_wd_code=eTeX_dim {code for \.{\\fontcharwd}}
+@d font_char_ht_code=eTeX_dim+1 {code for \.{\\fontcharht}}
+@d font_char_dp_code=eTeX_dim+2 {code for \.{\\fontchardp}}
+@d font_char_ic_code=eTeX_dim+3 {code for \.{\\fontcharic}}
+
+@<Generate all \eTeX...@>=
+primitive("charwd",last_item,font_char_wd_code);
+primitive("fontcharwd",last_item,font_char_wd_code);
+@!@:font_char_wd_}{\.{\\fontcharwd} primitive@>
+primitive("charht",last_item,font_char_ht_code);
+primitive("fontcharht",last_item,font_char_ht_code);
+@!@:font_char_ht_}{\.{\\fontcharht} primitive@>
+primitive("chardp",last_item,font_char_dp_code);
+primitive("fontchardp",last_item,font_char_dp_code);
+@!@:font_char_dp_}{\.{\\fontchardp} primitive@>
+primitive("charic",last_item,font_char_ic_code);
+primitive("fontcharic",last_item,font_char_ic_code);
+@!@:font_char_ic_}{\.{\\fontcharic} primitive@>
+
+@ @<Cases of |last_item| for |print_cmd_chr|@>=
+font_char_wd_code: print_esc("fontcharwd");
+font_char_ht_code: print_esc("fontcharht");
+font_char_dp_code: print_esc("fontchardp");
+font_char_ic_code: print_esc("fontcharic");
+
+@ @<Cases for fetching a dimension value@>=
+font_char_wd_code,
+font_char_ht_code,
+font_char_dp_code,
+font_char_ic_code: begin scan_font_ident; q:=cur_val; scan_char_num;
+ if char_exists(q,cur_val) then
+ begin
+ case m of
+ font_char_wd_code: cur_val:=char_width(q,cur_val);
+ font_char_ht_code: cur_val:=char_height(q,cur_val);
+ font_char_dp_code: cur_val:=char_depth(q,cur_val);
+ font_char_ic_code: cur_val:=char_italic(q,cur_val);
+ end; {there are no other cases}
+ end
+ else cur_val:=0;
+ end;
+
+@ The \.{\\parshapedimen}, \.{\\parshapeindent}, and \.{\\parshapelength}
+commands return the indent and length parameters of the current
+\.{\\parshape} specification.
+
+@d par_shape_length_code=eTeX_dim+4 {code for \.{\\parshapelength}}
+@d par_shape_indent_code=eTeX_dim+5 {code for \.{\\parshapeindent}}
+@d par_shape_dimen_code=eTeX_dim+6 {code for \.{\\parshapedimen}}
+
+@<Generate all \eTeX...@>=
+primitive("parshapelength",last_item,par_shape_length_code);
+@!@:par_shape_length_}{\.{\\parshapelength} primitive@>
+primitive("parshapeindent",last_item,par_shape_indent_code);
+@!@:par_shape_indent_}{\.{\\parshapeindent} primitive@>
+primitive("parshapedimen",last_item,par_shape_dimen_code);
+@!@:par_shape_dimen_}{\.{\\parshapedimen} primitive@>
+
+@ @<Cases of |last_item| for |print_cmd_chr|@>=
+par_shape_length_code: print_esc("parshapelength");
+par_shape_indent_code: print_esc("parshapeindent");
+par_shape_dimen_code: print_esc("parshapedimen");
+
+@ @<Cases for fetching a dimension value@>=
+par_shape_length_code,
+par_shape_indent_code,
+par_shape_dimen_code: begin q:=cur_chr-par_shape_length_code; scan_int;
+ if (par_shape_ptr=null)or(cur_val<=0) then cur_val:=0
+ else begin if q=2 then
+ begin q:=cur_val mod 2; cur_val:=(cur_val+q)div 2;
+ end;
+ if cur_val>vinfo(par_shape_ptr) then cur_val:=vinfo(par_shape_ptr);
+ cur_val:=vmem(par_shape_ptr+2*cur_val-q).sc;
+ end;
+ cur_val_level:=dimen_val;
+ end;
+
+@ The \.{\\showgroups} command displays all currently active grouping
+levels.
+
+@d show_groups=4 { \.{\\showgroups} }
+
+@<Generate all \eTeX...@>=
+primitive("showgroups",xray,show_groups);
+@!@:show_groups_}{\.{\\showgroups} primitive@>
+
+@ @<Cases of |xray| for |print_cmd_chr|@>=
+show_groups:print_esc("showgroups");
+
+@ @<Cases for |show_whatever|@>=
+show_groups: begin begin_diagnostic; show_save_groups;
+ end;
+
+@ @<Types...@>=
+@!save_pointer=0..save_size; {index into |save_stack|}
+
+@ The modifications of \TeX\ required for the display produced by the
+|show_save_groups| procedure were first discussed by Donald~E. Knuth in
+{\sl TUGboat\/} {\bf 11}, 165--170 and 499--511, 1990.
+@^Knuth, Donald Ervin@>
+
+In order to understand a group type we also have to know its mode.
+Since unrestricted horizontal modes are not associated with grouping,
+they are skipped when traversing the semantic nest.
+
+@<Declare \eTeX\ procedures for use...@>=
+procedure show_save_groups;
+label found1,found2,found,done;
+var p:0..nest_size; {index into |nest|}
+@!m:-mmode..mmode; {mode}
+@!v:save_pointer; {saved value of |save_ptr|}
+@!l:quarterword; {saved value of |cur_level|}
+@!c:group_code; {saved value of |cur_group|}
+@!a:-1..1; {to keep track of alignments}
+@!i:integer;
+@!j:quarterword;
+@!s:str_number;
+begin p:=nest_ptr; nest[p]:=cur_list; {put the top level into the array}
+v:=save_ptr; l:=cur_level; c:=cur_group;
+save_ptr:=cur_boundary; decr(cur_level);@/
+a:=1; s:="";
+print_nl(""); print_ln;
+loop@+begin print_nl("### "); print_group(true);
+ if cur_group=bottom_level then goto done;
+ repeat m:=nest[p].mode_field;
+ if p>0 then decr(p) else m:=vmode;
+ until m<>hmode;
+ print(" (");
+ case cur_group of
+ simple_group: begin incr(p); goto found2;
+ end;
+ hbox_group,adjusted_hbox_group: s:="hbox";
+ vbox_group: s:="vbox";
+ vtop_group: s:="vtop";
+ align_group: if a=0 then
+ begin if m=-vmode then s:="halign" else s:="valign";
+ a:=1; goto found1;
+ end
+ else begin if a=1 then print("align entry") else print_esc("cr");
+ if p>=a then p:=p-a;
+ a:=0; goto found;
+ end;
+ no_align_group:
+ begin incr(p); a:=-1; print_esc("noalign"); goto found2;
+ end;
+ output_group:
+ begin print_esc("output"); goto found;
+ end;
+ math_group: goto found2;
+ disc_group,math_choice_group:
+ begin if cur_group=disc_group then print_esc("discretionary")
+ else print_esc("mathchoice");
+ for i:=1 to 3 do if i<=saved(-2) then print("{}");
+ goto found2;
+ end;
+ insert_group:
+ begin if saved(-2)=255 then print_esc("vadjust")
+ else begin print_esc("insert"); print_int(saved(-2));
+ end;
+ goto found2;
+ end;
+ vcenter_group: begin s:="vcenter"; goto found1;
+ end;
+ semi_simple_group: begin incr(p); print_esc("begingroup"); goto found;
+ end;
+ math_shift_group:
+ begin if m=mmode then print_char("$")
+ else if nest[p].mode_field=mmode then
+ begin print_cmd_chr(eq_no,saved(-2)); goto found;
+ end;
+ print_char("$"); goto found;
+ end;
+ math_left_group:
+ begin if type(nest[p+1].eTeX_aux_field)=left_noad then print_esc("left")
+ else print_esc("middle");
+ goto found;
+ end;
+ end; {there are no other cases}
+ @<Show the box context@>;
+ found1: print_esc(s); @<Show the box packaging info@>;
+ found2: print_char("{");
+ found: print_char(")"); decr(cur_level);
+ cur_group:=save_level(save_ptr); save_ptr:=save_index(save_ptr)
+ end;
+done: save_ptr:=v; cur_level:=l; cur_group:=c;
+end;
+
+@ @<Show the box packaging info@>=
+if saved(-2)<>0 then
+ begin print_char(" ");
+ if saved(-3)=exactly then print("to") else print("spread");
+ print_scaled(saved(-2)); print("pt");
+ end
+
+@ @<Show the box context@>=
+i:=saved(-4);
+if i<>0 then
+ if i<box_flag then
+ begin if abs(nest[p].mode_field)=vmode then j:=hmove else j:=vmove;
+ if i>0 then print_cmd_chr(j,0) else print_cmd_chr(j,1);
+ print_scaled(abs(i)); print("pt");
+ end
+ else if i<ship_out_flag then
+ begin if i>=global_box_flag then
+ begin print_esc("global"); i:=i-(global_box_flag-box_flag);
+ end;
+ print_esc("setbox"); print_int(i-box_flag); print_char("=");
+ end
+ else print_cmd_chr(leader_ship,i-(leader_flag-a_leaders))
+
+@ The |scan_general_text| procedure is much like |scan_toks(false,false)|,
+but will be invoked via |expand|, i.e., recursively.
+@^recursion@>
+
+@<Declare \eTeX\ procedures for sc...@>=
+procedure@?scan_general_text; forward;@t\2@>
+
+@ The token list (balanced text) created by |scan_general_text| begins
+at |link(temp_token_head)| and ends at |cur_val|. (If |cur_val=temp_token_head|,
+the list is empty.)
+
+@<Declare \eTeX\ procedures for tok...@>=
+procedure scan_general_text;
+label found;
+var s:normal..absorbing; {to save |scanner_status|}
+@!w:pointer; {to save |warning_index|}
+@!d:pointer; {to save |def_ref|}
+@!p:pointer; {tail of the token list being built}
+@!q:pointer; {new node being added to the token list via |store_new_token|}
+@!unbalance:halfword; {number of unmatched left braces}
+begin s:=scanner_status; w:=warning_index; d:=def_ref;
+scanner_status:=absorbing; warning_index:=cur_cs;
+p:=get_avail; def_ref:=p; token_ref_count(def_ref):=0; p:=def_ref;
+scan_left_brace; {remove the compulsory left brace}
+unbalance:=1;
+loop@+ begin get_token;
+ if cur_tok<right_brace_limit then
+ if cur_cmd<right_brace then incr(unbalance)
+ else begin decr(unbalance);
+ if unbalance=0 then goto found;
+ end;
+ store_new_token(cur_tok);
+ end;
+found: q:=link(def_ref); free_avail(def_ref); {discard reference count}
+if q=null then cur_val:=temp_token_head @+ else cur_val:=p;
+link(temp_token_head):=q;
+scanner_status:=s; warning_index:=w; def_ref:=d;
+end;
+
+@ The \.{\\showtokens} command displays a token list.
+
+@d show_tokens=5 { \.{\\showtokens} , must be odd! }
+
+@<Generate all \eTeX...@>=
+primitive("showtokens",xray,show_tokens);
+@!@:show_tokens_}{\.{\\showtokens} primitive@>
+
+@ @<Cases of |xray| for |print_cmd_chr|@>=
+show_tokens:print_esc("showtokens");
+
+@ The \.{\\unexpanded} primitive prevents expansion of tokens much as
+the result from \.{\\the} applied to a token variable. The
+\.{\\detokenize} primitive converts a token list into a list of
+character tokens much as if the token list were written to a file. We
+use the fact that the command modifiers for \.{\\unexpanded} and
+\.{\\detokenize} are odd whereas those for \.{\\the} and \.{\\showthe}
+are even.
+
+@<Generate all \eTeX...@>=
+primitive("unexpanded",the,1);@/
+@!@:unexpanded_}{\.{\\unexpanded} primitive@>
+primitive("detokenize",the,show_tokens);@/
+@!@:detokenize_}{\.{\\detokenize} primitive@>
+
+@ @<Cases of |the| for |print_cmd_chr|@>=
+else if chr_code=1 then print_esc("unexpanded")
+else print_esc("detokenize")
+
+@ @<Handle \.{\\unexpanded} or \.{\\detokenize} and |return|@>=
+if odd(cur_chr) then
+ begin c:=cur_chr; scan_general_text;
+ if c=1 then the_toks:=cur_val
+ else begin old_setting:=selector; selector:=new_string; b:=pool_ptr;
+ p:=get_avail; link(p):=link(temp_token_head);
+ token_show(p); flush_list(p);
+ selector:=old_setting; the_toks:=str_toks(b);
+ end;
+ return;
+ end
+
+@ The \.{\\showifs} command displays all currently active conditionals.
+
+@d show_ifs=6 { \.{\\showifs} }
+
+@<Generate all \eTeX...@>=
+primitive("showifs",xray,show_ifs);
+@!@:show_ifs_}{\.{\\showifs} primitive@>
+
+@ @<Cases of |xray| for |print_cmd_chr|@>=
+show_ifs:print_esc("showifs");
+
+@
+@d print_if_line(#)==if #<>0 then
+ begin print(" entered on line "); print_int(#);
+ end
+
+@<Cases for |show_whatever|@>=
+show_ifs: begin begin_diagnostic; print_nl(""); print_ln;
+ if cond_ptr=null then
+ begin print_nl("### "); print("no active conditionals");
+ end
+ else begin p:=cond_ptr; n:=0;
+ repeat incr(n); p:=vlink(p);@+until p=null;
+ p:=cond_ptr; t:=cur_if; l:=if_line; m:=if_limit;
+ repeat print_nl("### level "); print_int(n); print(": ");
+ print_cmd_chr(if_test,t);
+ if m=fi_code then print_esc("else");
+ print_if_line(l);
+ decr(n); t:=if_limit_subtype(p); l:=if_line_field(p); m:=if_limit_type(p); p:=vlink(p);
+ until p=null;
+ end;
+ end;
+
+@ The \.{\\interactionmode} primitive allows to query and set the
+interaction mode.
+
+@<Generate all \eTeX...@>=
+primitive("interactionmode",set_page_int,2);
+@!@:interaction_mode_}{\.{\\interactionmode} primitive@>
+
+@ @<Cases of |set_page_int| for |print_cmd_chr|@>=
+else if chr_code=2 then print_esc("interactionmode")
+
+@ @<Cases for `Fetch the |dead_cycles| or the |insert_penalties|'@>=
+else if m=2 then cur_val:=interaction
+
+@ @<Declare \eTeX\ procedures for use...@>=
+procedure@?new_interaction; forward;@t\2@>
+
+@ @<Cases for |alter_integer|@>=
+else if c=2 then
+ begin if (cur_val<batch_mode)or(cur_val>error_stop_mode) then
+ begin print_err("Bad interaction mode");
+@.Bad interaction mode@>
+ help2("Modes are 0=batch, 1=nonstop, 2=scroll, and")@/
+ ("3=errorstop. Proceed, and I'll ignore this case.");
+ int_error(cur_val);
+ end
+ else begin cur_chr:=cur_val; new_interaction;
+ end;
+ end
+
+@ The |middle| feature of \eTeX\ allows one ore several \.{\\middle}
+delimiters to appear between \.{\\left} and \.{\\right}.
+
+@<Generate all \eTeX...@>=
+primitive("middle",left_right,middle_noad);
+@!@:middle_}{\.{\\middle} primitive@>
+
+@ @<Cases of |left_right| for |print_cmd_chr|@>=
+else if chr_code=middle_noad then print_esc("middle")
+
+@ The |scan_tokens| feature of \eTeX\ defines the \.{\\scantokens}
+primitive.
+
+@<Generate all \eTeX...@>=
+primitive("scantokens",input,2);
+@!@:scan_tokens_}{\.{\\scantokens} primitive@>
+primitive("scantextokens",input,3);
+@!@:scan_tex_tokens_}{\.{\\scantextokens} primitive@>
+
+@ @<Cases of |input| for |print_cmd_chr|@>=
+else if chr_code=2 then print_esc("scantokens")
+else if chr_code=3 then print_esc("scantextokens")
+
+@ @<Cases for |input|@>=
+else if cur_chr=2 then pseudo_start
+else if cur_chr=3 then begin pseudo_start; name := 19; end
+
+@ The global variable |pseudo_files| is used to maintain a stack of
+pseudo files. The |pseudo_lines| field of each pseudo file points to
+a linked list of variable size nodes representing lines not yet
+processed: the |subtype| field contains the size of this node,
+all the following words contain ASCII codes.
+
+@<Glob...@>=
+@!pseudo_files:pointer; {stack of pseudo files}
+
+@ @<Set init...@>=
+pseudo_files:=null;
+
+@ The |pseudo_start| procedure initiates reading from a pseudo file.
+
+@<Declare \eTeX\ procedures for ex...@>=
+procedure@?pseudo_start; forward;@t\2@>
+
+@ @<Declare \eTeX\ procedures for tok...@>=
+procedure pseudo_start;
+var old_setting:0..max_selector; {holds |selector| setting}
+@!s:str_number; {string to be converted into a pseudo file}
+@!p:pointer; {for list construction}
+begin scan_general_text;
+old_setting:=selector; selector:=new_string;
+token_show(temp_token_head); selector:=old_setting;
+flush_list(link(temp_token_head));
+str_room(1); s:=make_string;
+@<Convert string |s| into a new pseudo file@>;
+flush_string;
+@<Initiate input from new pseudo file@>;
+end;
+
+procedure pseudo_from_string;
+var @!s:str_number; {string to be converted into a pseudo file}
+@!p:pointer; {for list construction}
+begin
+s:=make_string;
+@<Convert string |s| into a new pseudo file@>;
+flush_string;
+@<Initiate input from new pseudo file@>;
+end;
+
+procedure lua_string_start;
+begin
+begin_file_reading; {set up |cur_file| and new level of input}
+line:=0; limit:=start; loc:=limit+1; {force line read}
+name:=21; luacstring_start(index);
+end;
+
+@ @<Convert string |s| into a new pseudo file@>=
+str_pool[pool_ptr]:=si(" ");
+p:=string_to_pseudo(str_start_macro(s),pool_ptr,new_line_char);
+vlink(p):=pseudo_files; pseudo_files:=p
+
+@ @<Initiate input from new pseudo file@>=
+begin_file_reading; {set up |cur_file| and new level of input}
+line:=0; limit:=start; loc:=limit+1; {force line read}
+if tracing_scan_tokens>0 then
+ begin if term_offset>max_print_line-3 then print_ln
+ else if (term_offset>0)or(file_offset>0) then print_char(" ");
+ name:=20; print("( "); incr(open_parens); update_terminal;
+ end
+else name:=18
+
+@ Here we read a line from the current pseudo file into |buffer|.
+
+@d pseudo_lines(#)==vlink(#+1)
+
+@<Declare \eTeX\ procedures for tr...@>=
+function pseudo_input: boolean; {inputs the next line or returns |false|}
+var p:pointer; {current line from pseudo file}
+@!sz:integer; {size of node |p|}
+@!w:four_quarters; {four ASCII codes}
+@!r:pointer; {loop index}
+begin last:=first; {cf.\ Matthew 19\thinspace:\thinspace30}
+p:=pseudo_lines(pseudo_files);
+if p=null then begin pseudo_input:=false; end
+else begin pseudo_lines(pseudo_files):=vlink(p); sz:=subtype(p);
+ if 4*sz-3>=buf_size-last then
+ check_buffer_overflow(last+4*sz);
+ last:=first;
+ for r:=p+1 to p+sz-1 do
+ begin w:=vmem(r).qqqq;
+ buffer[last]:=w.b0; buffer[last+1]:=w.b1;
+ buffer[last+2]:=w.b2; buffer[last+3]:=w.b3;
+ last:=last+4;
+ end;
+ if last>=max_buf_stack then max_buf_stack:=last+1;
+ while (last>first)and(buffer[last-1]=" ") do decr(last);
+ flush_node(p);
+ pseudo_input:=true;
+ end;
+end;
+
+@ When we are done with a pseudo file we `close' it.
+
+@<Declare \eTeX\ procedures for tr...@>=
+procedure pseudo_close; {close the top level pseudo file}
+var p,@!q: pointer;
+begin p:=vlink(pseudo_files);
+flush_node(pseudo_files);
+pseudo_files:=p;
+end;
+
+@ @<Close the pseudo files@>=
+while pseudo_files<>null do pseudo_close; {flush pseudo files}
+
+@ @<Generate all \eTeX...@>=
+primitive("readline",read_to_cs,1);@/
+@!@:read_line_}{\.{\\readline} primitive@>
+
+@ @<Cases of |read| for |print_cmd_chr|@>=
+else print_esc("readline")
+
+@ @<Handle \.{\\readline} and |goto done|@>=
+if j=1 then
+ begin while loc<=limit do {current line not yet finished}
+ begin cur_chr:=buffer[loc]; incr(loc);
+ if cur_chr=" " then cur_tok:=space_token
+ @+else cur_tok:=cur_chr+other_token;
+ store_new_token(cur_tok);
+ end;
+ goto done;
+ end
+
+@ Here we define the additional conditionals of \eTeX\ as well as the
+\.{\\unless} prefix.
+
+@d if_def_code=17 { `\.{\\ifdefined}' }
+@d if_cs_code=18 { `\.{\\ifcsname}' }
+@d if_font_char_code=19 { `\.{\\iffontchar}' }
+@d if_in_csname_code=20 { `\.{\\ifincsname}' }
+@d if_abs_num_code=22 { `\.{\\ifabsnum}' } { 21 = |if_primitive|}
+@d if_abs_dim_code=23 { `\.{\\ifabsdim}' }
+
+@<Generate all \eTeX...@>=
+primitive("unless",expand_after,1);@/
+@!@:unless_}{\.{\\unless} primitive@>
+primitive("ifdefined",if_test,if_def_code);
+@!@:if_defined_}{\.{\\ifdefined} primitive@>
+primitive("ifcsname",if_test,if_cs_code);
+@!@:if_cs_name_}{\.{\\ifcsname} primitive@>
+primitive("iffontchar",if_test,if_font_char_code);
+@!@:if_font_char_}{\.{\\iffontchar} primitive@>
+primitive("ifincsname",if_test,if_in_csname_code);
+@!@:if_in_csname_}{\.{\\ifincsname} primitive@>
+primitive("ifabsnum",if_test,if_abs_num_code);
+@!@:if_abs_num_}{\.{\\ifabsnum} primitive@>
+primitive("ifabsdim",if_test,if_abs_dim_code);
+@!@:if_abs_dim_}{\.{\\ifabsdim} primitive@>
+primitive("ifpdfabsnum",if_test,if_abs_num_code);
+@!@:if_abs_num_}{\.{\\ifpdfabsnum} primitive@>
+primitive("ifpdfabsdim",if_test,if_abs_dim_code);
+@!@:if_abs_dim_}{\.{\\ifpdfabsdim} primitive@>
+
+@ @<Cases of |expandafter| for |print_cmd_chr|@>=
+else print_esc("unless")
+
+@ @<Cases of |if_test| for |print_cmd_chr|@>=
+if_def_code:print_esc("ifdefined");
+if_cs_code:print_esc("ifcsname");
+if_font_char_code:print_esc("iffontchar");
+if_in_csname_code:print_esc("ifincsname");
+if_abs_num_code:print_esc("ifabsnum");
+if_abs_dim_code:print_esc("ifabsdim");
+
+@ The result of a boolean condition is reversed when the conditional is
+preceded by \.{\\unless}.
+
+@<Negate a boolean conditional and |goto reswitch|@>=
+begin get_token;
+if (cur_cmd=if_test)and(cur_chr<>if_case_code) then
+ begin cur_chr:=cur_chr+unless_code; goto reswitch;
+ end;
+print_err("You can't use `"); print_esc("unless"); print("' before `");
+@.You can't use \\unless...@>
+print_cmd_chr(cur_cmd,cur_chr); print_char("'");
+help1("Continue, and I'll forget that it ever happened.");
+back_error;
+end
+
+@ The conditional \.{\\ifdefined} tests if a control sequence is
+defined.
+
+We need to reset |scanner_status|, since \.{\\outer} control sequences
+are allowed, but we might be scanning a macro definition or preamble.
+
+@<Cases for |conditional|@>=
+if_def_code:begin save_scanner_status:=scanner_status;
+ scanner_status:=normal;
+ get_filtered_next; b:=(cur_cmd<>undefined_cs);
+ scanner_status:=save_scanner_status;
+ end;
+
+@ The conditional \.{\\ifcsname} is equivalent to \.{\{\\expandafter}
+\.{\}\\expandafter} \.{\\ifdefined} \.{\\csname}, except that no new
+control sequence will be entered into the hash table (once all tokens
+preceding the mandatory \.{\\endcsname} have been expanded).
+
+@<Cases for |conditional|@>=
+if_cs_code:begin n:=get_avail; p:=n; {head of the list of characters}
+ b:=false;
+ repeat get_x_token;
+ if cur_cs=0 then store_new_token(cur_tok);
+ until cur_cs<>0;
+ if cur_cmd<>end_cs_name then @<Complain about missing \.{\\endcsname}@>;
+ @<Look up the characters of list |n| in the hash table, and set |cur_cs|@>;
+ flush_list(n);
+ b:=(eq_type(cur_cs)<>undefined_cs);
+ end;
+
+@ @<Look up the characters of list |n| in the hash table...@>=
+m:=first; p:=link(n);
+while p<>null do
+ begin if m>=max_buf_stack then
+ begin max_buf_stack:=m+4;
+ if max_buf_stack=buf_size then
+ check_buffer_overflow(max_buf_stack);
+@:TeX capacity exceeded buffer size}{\quad buffer size@>
+ end;
+ s := info(p) mod string_offset;
+ if s <= @"7F then begin
+ buffer[m]:=s; incr(m);
+ end
+ else if s<=@"7FF then begin
+ buffer[m]:=@"C0 + s div @"40; incr(m);
+ buffer[m]:=@"80 + s mod @"40; incr(m);
+ end
+ else if s<=@"FFFF then begin
+ buffer[m]:=@"E0 + s div @"1000; incr(m);
+ buffer[m]:=@"80 + (s mod @"1000) div @"40; incr(m);
+ buffer[m]:=@"80 + (s mod @"1000) mod @"40; incr(m);
+ end
+ else begin
+ buffer[m]:=@"F0 + s div @"40000; incr(m);
+ buffer[m]:=@"80 + (s mod @"40000) div @"1000; incr(m);
+ buffer[m]:=@"80 + ((s mod @"40000) mod @"1000) div @"40; incr(m);
+ buffer[m]:=@"80 + ((s mod @"40000) mod @"1000) mod @"40; incr(m);
+ end;
+ p:=link(p);
+ end;
+if m>first then
+ cur_cs:=id_lookup(first,m-first) {|no_new_control_sequence| is |true|}
+else if m=first then cur_cs:=null_cs {the list is empty}
+
+@ The conditional \.{\\iffontchar} tests the existence of a character in
+a font.
+
+@<Cases for |conditional|@>=
+if_in_csname_code: b := is_in_csname;
+if_abs_dim_code, if_abs_num_code: begin
+ if this_if=if_abs_num_code then scan_int@+else scan_normal_dimen;
+ n:=cur_val;
+ if n < 0 then negate(n);
+ @<Get the next non-blank non-call...@>;
+ if (cur_tok>=other_token+"<")and(cur_tok<=other_token+">") then
+ r:=cur_tok-other_token
+ else begin print_err("Missing = inserted for ");
+ @.Missing = inserted@>
+ print_cmd_chr(if_test,this_if);
+ help1("I was expecting to see `<', `=', or `>'. Didn't.");
+ back_error; r:="=";
+ end;
+ if this_if=if_abs_num_code then scan_int@+else scan_normal_dimen;
+ if cur_val < 0 then negate(cur_val);
+ case r of
+ "<": b:=(n<cur_val);
+ "=": b:=(n=cur_val);
+ ">": b:=(n>cur_val);
+ end;
+ end;
+if_font_char_code:begin scan_font_ident; n:=cur_val; scan_char_num;
+ b:=char_exists(n,cur_val);
+ end;
+
+@ The |protected| feature of \eTeX\ defines the \.{\\protected} prefix
+command for macro definitions. Such macros are protected against
+expansions when lists of expanded tokens are built, e.g., for \.{\\edef}
+or during \.{\\write}.
+
+@<Generate all \eTeX...@>=
+primitive("protected",prefix,8);
+@!@:protected_}{\.{\\protected} primitive@>
+
+@ @<Cases of |prefix| for |print_cmd_chr|@>=
+else if chr_code=8 then print_esc("protected")
+
+@ The |get_x_or_protected| procedure is like |get_x_token| except that
+protected macros are not expanded.
+
+@<Declare \eTeX\ procedures for sc...@>=
+procedure get_x_or_protected; {sets |cur_cmd|, |cur_chr|, |cur_tok|,
+ and expands non-protected macros}
+label exit;
+begin loop@+begin get_token;
+ if cur_cmd<=max_command then return;
+ if (cur_cmd>=call)and(cur_cmd<end_template) then
+ if info(link(cur_chr))=protected_token then return;
+ expand;
+ end;
+exit:end;
+
+@ A group entered (or a conditional started) in one file may end in a
+different file. Such slight anomalies, although perfectly legitimate,
+may cause errors that are difficult to locate. In order to be able to
+give a warning message when such anomalies occur, \eTeX\ uses the
+|grp_stack| and |if_stack| arrays to record the initial |cur_boundary|
+and |cond_ptr| values for each input file.
+
+@<Glob...@>=
+@!grp_stack : array[0..max_in_open] of save_pointer; {initial |cur_boundary|}
+@!if_stack : array[0..max_in_open] of pointer; {initial |cond_ptr|}
+
+@ When a group ends that was apparently entered in a different input
+file, the |group_warning| procedure is invoked in order to update the
+|grp_stack|. If moreover \.{\\tracingnesting} is positive we want to
+give a warning message. The situation is, however, somewhat complicated
+by two facts: (1)~There may be |grp_stack| elements without a
+corresponding \.{\\input} file or \.{\\scantokens} pseudo file (e.g.,
+error insertions from the terminal); and (2)~the relevant information is
+recorded in the |name_field| of the |input_stack| only loosely
+synchronized with the |in_open| variable indexing |grp_stack|.
+
+@<Declare \eTeX\ procedures for tr...@>=
+procedure group_warning;
+var i:0..max_in_open; {index into |grp_stack|}
+@!w:boolean; {do we need a warning?}
+begin base_ptr:=input_ptr; input_stack[base_ptr]:=cur_input;
+ {store current state}
+i:=in_open; w:=false;
+while (grp_stack[i]=cur_boundary)and(i>0) do
+ begin @<Set variable |w| to indicate if this case should be reported@>;
+ grp_stack[i]:=save_index(save_ptr); decr(i);
+ end;
+if w then
+ begin print_nl("Warning: end of "); print_group(true);
+@.Warning: end of...@>
+ print(" of a different file"); print_ln;
+ if tracing_nesting>1 then show_context;
+ if history=spotless then history:=warning_issued;
+ end;
+end;
+
+@ This code scans the input stack in order to determine the type of the
+current input file.
+
+@<Set variable |w| to...@>=
+if tracing_nesting>0 then
+ begin while (input_stack[base_ptr].state_field=token_list)or@|
+ (input_stack[base_ptr].index_field>i) do decr(base_ptr);
+ if input_stack[base_ptr].name_field>17 then w:=true;
+ end
+
+@ When a conditional ends that was apparently started in a different
+input file, the |if_warning| procedure is invoked in order to update the
+|if_stack|. If moreover \.{\\tracingnesting} is positive we want to
+give a warning message (with the same complications as above).
+
+@<Declare \eTeX\ procedures for tr...@>=
+procedure if_warning;
+var i:0..max_in_open; {index into |if_stack|}
+@!w:boolean; {do we need a warning?}
+begin base_ptr:=input_ptr; input_stack[base_ptr]:=cur_input;
+ {store current state}
+i:=in_open; w:=false;
+while if_stack[i]=cond_ptr do
+ begin @<Set variable |w| to...@>;
+ if_stack[i]:=vlink(cond_ptr); decr(i);
+ end;
+if w then
+ begin print_nl("Warning: end of "); print_cmd_chr(if_test,cur_if);
+@.Warning: end of...@>
+ print_if_line(if_line); print(" of a different file"); print_ln;
+ if tracing_nesting>1 then show_context;
+ if history=spotless then history:=warning_issued;
+ end;
+end;
+
+@ Conversely, the |file_warning| procedure is invoked when a file ends
+and some groups entered or conditionals started while reading from that
+file are still incomplete.
+
+@<Declare \eTeX\ procedures for tr...@>=
+procedure file_warning;
+var p:pointer; {saved value of |save_ptr| or |cond_ptr|}
+@!l:quarterword; {saved value of |cur_level| or |if_limit|}
+@!c:quarterword; {saved value of |cur_group| or |cur_if|}
+@!i:integer; {saved value of |if_line|}
+begin
+p:=save_ptr; l:=cur_level; c:=cur_group; save_ptr:=cur_boundary;
+while grp_stack[in_open]<>save_ptr do
+ begin decr(cur_level);
+ print_nl("Warning: end of file when ");
+@.Warning: end of file when...@>
+ print_group(true); print(" is incomplete");@/
+ cur_group:=save_level(save_ptr); save_ptr:=save_index(save_ptr)
+ end;
+save_ptr:=p; cur_level:=l; cur_group:=c; {restore old values}
+p:=cond_ptr; l:=if_limit; c:=cur_if; i:=if_line;
+while if_stack[in_open]<>cond_ptr do
+ begin print_nl("Warning: end of file when ");
+@.Warning: end of file when...@>
+ print_cmd_chr(if_test,cur_if);
+ if if_limit=fi_code then print_esc("else");
+ print_if_line(if_line); print(" is incomplete");@/
+ if_line:=if_line_field(cond_ptr); cur_if:=if_limit_subtype(cond_ptr);
+ if_limit:=if_limit_type(cond_ptr); cond_ptr:=vlink(cond_ptr);
+ end;
+cond_ptr:=p; if_limit:=l; cur_if:=c; if_line:=i; {restore old values}
+print_ln;
+if tracing_nesting>1 then show_context;
+if history=spotless then history:=warning_issued;
+end;
+
+@ Here are the additional \eTeX\ primitives for expressions.
+
+@<Generate all \eTeX...@>=
+primitive("numexpr",last_item,eTeX_expr-int_val+int_val);
+@!@:num_expr_}{\.{\\numexpr} primitive@>
+primitive("dimexpr",last_item,eTeX_expr-int_val+dimen_val);
+@!@:dim_expr_}{\.{\\dimexpr} primitive@>
+primitive("glueexpr",last_item,eTeX_expr-int_val+glue_val);
+@!@:glue_expr_}{\.{\\glueexpr} primitive@>
+primitive("muexpr",last_item,eTeX_expr-int_val+mu_val);
+@!@:mu_expr_}{\.{\\muexpr} primitive@>
+
+@ @<Cases of |last_item| for |print_cmd_chr|@>=
+eTeX_expr-int_val+int_val: print_esc("numexpr");
+eTeX_expr-int_val+dimen_val: print_esc("dimexpr");
+eTeX_expr-int_val+glue_val: print_esc("glueexpr");
+eTeX_expr-int_val+mu_val: print_esc("muexpr");
+
+@ This code for reducing |cur_val_level| and\slash or negating the
+result is similar to the one for all the other cases of
+|scan_something_internal|, with the difference that |scan_expr| has
+already increased the reference count of a glue specification.
+
+@<Process an expression and |return|@>=
+begin if m<eTeX_mu then
+ begin case m of
+ @/@<Cases for fetching a glue value@>@/
+ end; {there are no other cases}
+ cur_val_level:=glue_val;
+ end
+else if m<eTeX_expr then
+ begin case m of
+ @/@<Cases for fetching a mu value@>@/
+ end; {there are no other cases}
+ cur_val_level:=mu_val;
+ end
+else begin cur_val_level:=m-eTeX_expr+int_val; scan_expr;
+ end;
+while cur_val_level>level do
+ begin if cur_val_level=glue_val then
+ begin m:=cur_val; cur_val:=width(m); delete_glue_ref(m);
+ end
+ else if cur_val_level=mu_val then mu_error;
+ decr(cur_val_level);
+ end;
+if negative then
+ if cur_val_level>=glue_val then
+ begin m:=cur_val; cur_val:=new_spec(m); delete_glue_ref(m);
+ @<Negate all three glue components of |cur_val|@>;
+ end
+ else negate(cur_val);
+return;
+end
+
+@ @<Declare \eTeX\ procedures for sc...@>=
+procedure@?scan_expr; forward;@t\2@>
+
+@ The |scan_expr| procedure scans and evaluates an expression.
+
+@<Declare procedures needed for expressions@>=
+@t\4@>@<Declare subprocedures for |scan_expr|@>
+procedure scan_expr; {scans and evaluates an expression}
+label restart, continue, found;
+var a,@!b:boolean; {saved values of |arith_error|}
+@!l:small_number; {type of expression}
+@!r:small_number; {state of expression so far}
+@!s:small_number; {state of term so far}
+@!o:small_number; {next operation or type of next factor}
+@!e:integer; {expression so far}
+@!t:integer; {term so far}
+@!f:integer; {current factor}
+@!n:integer; {numerator of combined multiplication and division}
+@!p:pointer; {top of expression stack}
+@!q:pointer; {for stack manipulations}
+begin l:=cur_val_level; a:=arith_error; b:=false; p:=null;
+@<Scan and evaluate an expression |e| of type |l|@>;
+if b then
+ begin print_err("Arithmetic overflow");
+@.Arithmetic overflow@>
+ help2("I can't evaluate this expression,")@/
+ ("since the result is out of range.");
+ error;
+ if l>=glue_val then
+ begin delete_glue_ref(e); e:=zero_glue; add_glue_ref(e);
+ end
+ else e:=0;
+ end;
+arith_error:=a; cur_val:=e; cur_val_level:=l;
+end;
+
+@ Evaluating an expression is a recursive process: When the left
+parenthesis of a subexpression is scanned we descend to the next level
+of recursion; the previous level is resumed with the matching right
+parenthesis.
+
+@d expr_none=0 {\.( seen, or \.( $\langle\it expr\rangle$ \.) seen}
+@d expr_add=1 {\.( $\langle\it expr\rangle$ \.+ seen}
+@d expr_sub=2 {\.( $\langle\it expr\rangle$ \.- seen}
+@d expr_mult=3 {$\langle\it term\rangle$ \.* seen}
+@d expr_div=4 {$\langle\it term\rangle$ \./ seen}
+@d expr_scale=5 {$\langle\it term\rangle$ \.*
+ $\langle\it factor\rangle$ \./ seen}
+
+@<Scan and eval...@>=
+restart: r:=expr_none; e:=0; s:=expr_none; t:=0; n:=0;
+continue: if s=expr_none then o:=l@+else o:=int_val;
+@<Scan a factor |f| of type |o| or start a subexpression@>;
+found: @<Scan the next operator and set |o|@>;
+arith_error:=b;
+@<Make sure that |f| is in the proper range@>;
+case s of @<Cases for evaluation of the current term@>@;
+end; {there are no other cases}
+if o>expr_sub then s:=o@+else @<Evaluate the current expression@>;
+b:=arith_error;
+if o<>expr_none then goto continue;
+if p<>null then @<Pop the expression stack and |goto found|@>
+
+@ @<Scan the next op...@>=
+@<Get the next non-blank non-call token@>;
+if cur_tok=other_token+"+" then o:=expr_add
+else if cur_tok=other_token+"-" then o:=expr_sub
+else if cur_tok=other_token+"*" then o:=expr_mult
+else if cur_tok=other_token+"/" then o:=expr_div
+else begin o:=expr_none;
+ if p=null then
+ begin if cur_cmd<>relax then back_input;
+ end
+ else if cur_tok<>other_token+")" then
+ begin print_err("Missing ) inserted for expression");
+@.Missing ) inserted@>
+ help1("I was expecting to see `+', `-', `*', `/', or `)'. Didn't.");
+ back_error;
+ end;
+ end
+
+@ @<Scan a factor...@>=
+@<Get the next non-blank non-call token@>;
+if cur_tok=other_token+"(" then
+ @<Push the expression stack and |goto restart|@>;
+back_input;
+if (o=int_val)or(o=attr_val) then scan_int
+else if o=dimen_val then scan_normal_dimen
+else if o=glue_val then scan_normal_glue
+else scan_mu_glue;
+f:=cur_val
+
+@ @<Declare \eTeX\ procedures for sc...@>=
+procedure@?scan_normal_glue; forward;@t\2@>@/
+procedure@?scan_mu_glue; forward;@t\2@>
+
+@ Here we declare to trivial procedures in order to avoid mutually
+recursive procedures with parameters.
+
+@<Declare procedures needed for expressions@>=
+procedure scan_normal_glue;
+begin scan_glue(glue_val);
+end;
+@#
+procedure scan_mu_glue;
+begin scan_glue(mu_val);
+end;
+
+@ Parenthesized subexpressions can be inside expressions, and this
+nesting has a stack. Seven local variables represent the top of the
+expression stack: |p| points to pushed-down entries, if any; |l|
+specifies the type of expression currently beeing evaluated; |e| is the
+expression so far and |r| is the state of its evaluation; |t| is the
+term so far and |s| is the state of its evaluation; finally |n| is the
+numerator for a combined multiplication and division, if any.
+
+@d expr_node=39 { stack entry for subexpressions}
+@d expr_type(#)==type(#+1)
+@d expr_state(#)==subtype(#+1)
+@d expr_e_field(#)==vlink(#+1) {saved expression so far}
+@d expr_t_field(#)==vlink(#+2) {saved term so far}
+@d expr_n_field(#)==vinfo(#+2) {saved numerator}
+
+@<Push the expression...@>=
+begin q:=new_node(expr_node,0); vlink(q):=p;
+expr_type(q):=l; expr_state(q):=4*s+r;
+expr_e_field(q):=e; expr_t_field(q):=t; expr_n_field(q):=n;
+p:=q; l:=o; goto restart;
+end
+
+@ @<Pop the expression...@>=
+begin f:=e; q:=p;
+e:=expr_e_field(q); t:=expr_t_field(q); n:=expr_n_field(q);
+s:=expr_state(q) div 4; r:=expr_state(q) mod 4;
+l:=expr_type(q); p:=vlink(q); flush_node(q);
+goto found;
+end
+
+@ We want to make sure that each term and (intermediate) result is in
+the proper range. Integer values must not exceed |infinity|
+($2^{31}-1$) in absolute value, dimensions must not exceed |max_dimen|
+($2^{30}-1$). We avoid the absolute value of an integer, because this
+might fail for the value $-2^{31}$ using 32-bit arithmetic.
+
+@d num_error(#)== {clear a number or dimension and set |arith_error|}
+ begin arith_error:=true; #:=0;
+ end
+@d glue_error(#)== {clear a glue spec and set |arith_error|}
+ begin arith_error:=true; delete_glue_ref(#); #:=new_spec(zero_glue);
+ end
+
+@<Make sure that |f|...@>=
+if ((l=int_val)or(l=attr_val))or(s>expr_sub) then
+ begin if (f>infinity)or(f<-infinity) then num_error(f);
+ end
+else if l=dimen_val then
+ begin if abs(f)>max_dimen then num_error(f);
+ end
+else begin if (abs(width(f))>max_dimen)or@|
+ (abs(stretch(f))>max_dimen)or@|
+ (abs(shrink(f))>max_dimen) then glue_error(f);
+ end
+
+@ Applying the factor |f| to the partial term |t| (with the operator
+|s|) is delayed until the next operator |o| has been scanned. Here we
+handle the first factor of a partial term. A glue spec has to be copied
+unless the next operator is a right parenthesis; this allows us later on
+to simply modify the glue components.
+
+@d normalize_glue(#)==
+ if stretch(#)=0 then stretch_order(#):=normal;
+ if shrink(#)=0 then shrink_order(#):=normal
+
+@<Cases for evaluation of the current term@>=
+expr_none: if (l>=glue_val)and(o<>expr_none) then
+ begin t:=new_spec(f); delete_glue_ref(f); normalize_glue(t);
+ end
+ else t:=f;
+
+@ When a term |t| has been completed it is copied to, added to, or
+subtracted from the expression |e|.
+
+@d expr_add_sub(#)==add_or_sub(#,r=expr_sub)
+@d expr_a(#)==expr_add_sub(#,max_dimen)
+
+@<Evaluate the current expression@>=
+begin s:=expr_none;
+if r=expr_none then e:=t
+else if (l=int_val)or(l=attr_val) then e:=expr_add_sub(e,t,infinity)
+else if l=dimen_val then e:=expr_a(e,t)
+else @<Compute the sum or difference of two glue specs@>;
+r:=o;
+end
+
+@ The function |add_or_sub(x,y,max_answer,negative)| computes the sum
+(for |negative=false|) or difference (for |negative=true|) of |x| and
+|y|, provided the absolute value of the result does not exceed
+|max_answer|.
+
+@<Declare subprocedures for |scan_expr|@>=
+function add_or_sub(@!x,@!y,@!max_answer:integer;@!negative:boolean):integer;
+var a:integer; {the answer}
+begin if negative then negate(y);
+if x>=0 then
+ if y<=max_answer-x then a:=x+y@+else num_error(a)
+else if y>=-max_answer-x then a:=x+y@+else num_error(a);
+add_or_sub:=a;
+end;
+
+@ We know that |stretch_order(e)>normal| implies |stretch(e)<>0| and
+|shrink_order(e)>normal| implies |shrink(e)<>0|.
+
+@<Compute the sum or diff...@>=
+begin width(e):=expr_a(width(e),width(t));
+if stretch_order(e)=stretch_order(t) then
+ stretch(e):=expr_a(stretch(e),stretch(t))
+else if (stretch_order(e)<stretch_order(t))and(stretch(t)<>0) then
+ begin stretch(e):=stretch(t); stretch_order(e):=stretch_order(t);
+ end;
+if shrink_order(e)=shrink_order(t) then
+ shrink(e):=expr_a(shrink(e),shrink(t))
+else if (shrink_order(e)<shrink_order(t))and(shrink(t)<>0) then
+ begin shrink(e):=shrink(t); shrink_order(e):=shrink_order(t);
+ end;
+delete_glue_ref(t); normalize_glue(e);
+end
+
+@ If a multiplication is followed by a division, the two operations are
+combined into a `scaling' operation. Otherwise the term |t| is
+multiplied by the factor |f|.
+
+@d expr_m(#)==#:=nx_plus_y(#,f,0)
+
+@<Cases for evaluation of the current term@>=
+expr_mult: if o=expr_div then
+ begin n:=f; o:=expr_scale;
+ end
+ else if (l=int_val)or(l=attr_val) then t:=mult_integers(t,f)
+ else if l=dimen_val then expr_m(t)
+ else begin expr_m(width(t)); expr_m(stretch(t)); expr_m(shrink(t));
+ end;
+
+@ Here we divide the term |t| by the factor |f|.
+
+@d expr_d(#)==#:=quotient(#,f)
+
+@<Cases for evaluation of the current term@>=
+expr_div: if l<glue_val then expr_d(t)
+ else begin expr_d(width(t)); expr_d(stretch(t)); expr_d(shrink(t));
+ end;
+
+@ The function |quotient(n,d)| computes the rounded quotient
+$q=\lfloor n/d+{1\over2}\rfloor$, when $n$ and $d$ are positive.
+
+@<Declare subprocedures for |scan_expr|@>=
+function quotient(@!n,@!d:integer):integer;
+var negative:boolean; {should the answer be negated?}
+@!a:integer; {the answer}
+begin if d=0 then num_error(a)
+else begin if d>0 then negative:=false
+ else begin negate(d); negative:=true;
+ end;
+ if n<0 then
+ begin negate(n); negative:=not negative;
+ end;
+ a:=n div d; n:=n-a*d; d:=n-d; {avoid certain compiler optimizations!}
+ if d+n>=0 then incr(a);
+ if negative then negate(a);
+ end;
+quotient:=a;
+end;
+
+@ Here the term |t| is multiplied by the quotient $n/f$.
+
+@d expr_s(#)==#:=fract(#,n,f,max_dimen)
+
+@<Cases for evaluation of the current term@>=
+expr_scale: if (l=int_val)or(l=attr_val) then t:=fract(t,n,f,infinity)
+ else if l=dimen_val then expr_s(t)
+ else begin expr_s(width(t)); expr_s(stretch(t)); expr_s(shrink(t));
+ end;
+
+@ Finally, the function |fract(x,n,d,max_answer)| computes the integer
+$q=\lfloor xn/d+{1\over2}\rfloor$, when $x$, $n$, and $d$ are positive
+and the result does not exceed |max_answer|. We can't use floating
+point arithmetic since the routine must produce identical results in all
+cases; and it would be too dangerous to multiply by~|n| and then divide
+by~|d|, in separate operations, since overflow might well occur. Hence
+this subroutine simulates double precision arithmetic, somewhat
+analogous to \MF's |make_fraction| and |take_fraction| routines.
+
+@d too_big=88 {go here when the result is too big}
+
+@<Declare subprocedures for |scan_expr|@>=
+function fract(@!x,@!n,@!d,@!max_answer:integer):integer;
+label found, found1, too_big, done;
+var negative:boolean; {should the answer be negated?}
+@!a:integer; {the answer}
+@!f:integer; {a proper fraction}
+@!h:integer; {smallest integer such that |2*h>=d|}
+@!r:integer; {intermediate remainder}
+@!t:integer; {temp variable}
+begin if d=0 then goto too_big;
+a:=0;
+if d>0 then negative:=false
+else begin negate(d); negative:=true;
+ end;
+if x<0 then
+ begin negate(x); negative:=not negative;
+ end
+else if x=0 then goto done;
+if n<0 then
+ begin negate(n); negative:=not negative;
+ end;
+t:=n div d;
+if t>max_answer div x then goto too_big;
+a:=t*x; n:=n-t*d;
+if n=0 then goto found;
+t:=x div d;
+if t>(max_answer-a) div n then goto too_big;
+a:=a+t*n; x:=x-t*d;
+if x=0 then goto found;
+if x<n then
+ begin t:=x; x:=n; n:=t;
+ end; {now |0<n<=x<d|}
+@<Compute \(f)$f=\lfloor xn/d+{1\over2}\rfloor$@>@;
+if f>(max_answer-a) then goto too_big;
+a:=a+f;
+found: if negative then negate(a);
+goto done;
+too_big: num_error(a);
+done: fract:=a;
+end;
+
+@ The loop here preserves the following invariant relations
+between |f|, |x|, |n|, and~|r|:
+(i)~$f+\lfloor(xn+(r+d))/d\rfloor=\lfloor x_0n_0/d+{1\over2}\rfloor$;
+(ii)~|-d<=r<0<n<=x<d|, where $x_0$, $n_0$ are the original values of~$x$
+and $n$.
+
+Notice that the computation specifies |(x-d)+x| instead of |(x+x)-d|,
+because the latter could overflow.
+
+@<Compute \(f)$f=\lfloor xn/d+{1\over2}\rfloor$@>=
+f:=0; r:=(d div 2)-d; h:=-r;
+loop@+begin if odd(n) then
+ begin r:=r+x;
+ if r>=0 then
+ begin r:=r-d; incr(f);
+ end;
+ end;
+ n:=n div 2;
+ if n=0 then goto found1;
+ if x<h then x:=x+x
+ else begin t:=x-d; x:=t+x; f:=f+n;
+ if x<n then
+ begin if x=0 then goto found1;
+ t:=x; x:=n; n:=t;
+ end;
+ end;
+ end;
+found1:
+
+@ The \.{\\gluestretch}, \.{\\glueshrink}, \.{\\gluestretchorder}, and
+\.{\\glueshrinkorder} commands return the stretch and shrink components
+and their orders of ``infinity'' of a glue specification.
+
+@d glue_stretch_order_code=eTeX_int+6 {code for \.{\\gluestretchorder}}
+@d glue_shrink_order_code=eTeX_int+7 {code for \.{\\glueshrinkorder}}
+@d glue_stretch_code=eTeX_dim+7 {code for \.{\\gluestretch}}
+@d glue_shrink_code=eTeX_dim+8 {code for \.{\\glueshrink}}
+
+@<Generate all \eTeX...@>=
+primitive("gluestretchorder",last_item,glue_stretch_order_code);
+@!@:glue_stretch_order_}{\.{\\gluestretchorder} primitive@>
+primitive("glueshrinkorder",last_item,glue_shrink_order_code);
+@!@:glue_shrink_order_}{\.{\\glueshrinkorder} primitive@>
+primitive("gluestretch",last_item,glue_stretch_code);
+@!@:glue_stretch_}{\.{\\gluestretch} primitive@>
+primitive("glueshrink",last_item,glue_shrink_code);
+@!@:glue_shrink_}{\.{\\glueshrink} primitive@>
+
+@ @<Cases of |last_item| for |print_cmd_chr|@>=
+glue_stretch_order_code: print_esc("gluestretchorder");
+glue_shrink_order_code: print_esc("glueshrinkorder");
+glue_stretch_code: print_esc("gluestretch");
+glue_shrink_code: print_esc("glueshrink");
+
+@ @<Cases for fetching an integer value@>=
+glue_stretch_order_code, glue_shrink_order_code:
+ begin scan_normal_glue; q:=cur_val;
+ if m=glue_stretch_order_code then cur_val:=stretch_order(q)
+ else cur_val:=shrink_order(q);
+ delete_glue_ref(q);
+ end;
+
+@ @<Cases for fetching a dimension value@>=
+glue_stretch_code, glue_shrink_code:
+ begin scan_normal_glue; q:=cur_val;
+ if m=glue_stretch_code then cur_val:=stretch(q)
+ else cur_val:=shrink(q);
+ delete_glue_ref(q);
+ end;
+
+@ The \.{\\mutoglue} and \.{\\gluetomu} commands convert ``math'' glue
+into normal glue and vice versa; they allow to manipulate math glue with
+\.{\\gluestretch} etc.
+
+@d mu_to_glue_code=eTeX_glue {code for \.{\\mutoglue}}
+@d glue_to_mu_code=eTeX_mu {code for \.{\\gluetomu}}
+
+@<Generate all \eTeX...@>=
+primitive("mutoglue",last_item,mu_to_glue_code);
+@!@:mu_to_glue_}{\.{\\mutoglue} primitive@>
+primitive("gluetomu",last_item,glue_to_mu_code);
+@!@:glue_to_mu_}{\.{\\gluetomu} primitive@>
+
+@ @<Cases of |last_item| for |print_cmd_chr|@>=
+mu_to_glue_code: print_esc("mutoglue");
+glue_to_mu_code: print_esc("gluetomu");
+
+@ @<Cases for fetching a glue value@>=
+mu_to_glue_code: scan_mu_glue;
+
+@ @<Cases for fetching a mu value@>=
+glue_to_mu_code: scan_normal_glue;
+
+@ @<Glob...@>=
+@!last_line_fill:pointer; {the |par_fill_skip| glue node of the new paragraph}
+
+@ When |saving_vdiscards| is positive then the glue, kern, and penalty
+nodes removed by the page builder or by \.{\\vsplit} from the top of a
+vertical list are saved in special lists instead of being discarded.
+
+@d tail_page_disc==disc_ptr[copy_code] {last item removed by page builder}
+@d page_disc==disc_ptr[last_box_code] {first item removed by page builder}
+@d split_disc==disc_ptr[vsplit_code] {first item removed by \.{\\vsplit}}
+
+@<Glob...@>=
+@!disc_ptr:array[copy_code..vsplit_code] of pointer; {list pointers}
+
+@ @<Set init...@>=
+page_disc:=null; split_disc:=null;
+
+@ The \.{\\pagediscards} and \.{\\splitdiscards} commands share the
+command code |un_vbox| with \.{\\unvbox} and \.{\\unvcopy}, they are
+distinguished by their |chr_code| values |last_box_code| and
+|vsplit_code|. These |chr_code| values are larger than |box_code| and
+|copy_code|.
+
+@<Generate all \eTeX...@>=
+primitive("pagediscards",un_vbox,last_box_code);@/
+@!@:page_discards_}{\.{\\pagediscards} primitive@>
+primitive("splitdiscards",un_vbox,vsplit_code);@/
+@!@:split_discards_}{\.{\\splitdiscards} primitive@>
+
+@ @<Cases of |un_vbox| for |print_cmd_chr|@>=
+else if chr_code=last_box_code then print_esc("pagediscards")
+else if chr_code=vsplit_code then print_esc("splitdiscards")
+
+@ @<Handle saved items and |goto done|@>=
+begin vlink(tail):=disc_ptr[cur_chr]; disc_ptr[cur_chr]:=null;
+goto done;
+end
+
+@ The \.{\\interlinepenalties}, \.{\\clubpenalties}, \.{\\widowpenalties},
+and \.{\\displaywidowpenalties} commands allow to define arrays of
+penalty values to be used instead of the corresponding single values.
+
+@d inter_line_penalties_ptr==equiv(inter_line_penalties_loc)
+@d club_penalties_ptr==equiv(club_penalties_loc)
+@d widow_penalties_ptr==equiv(widow_penalties_loc)
+@d display_widow_penalties_ptr==equiv(display_widow_penalties_loc)
+
+@<Generate all \eTeX...@>=
+primitive("interlinepenalties",set_shape,inter_line_penalties_loc);@/
+@!@:inter_line_penalties_}{\.{\\interlinepenalties} primitive@>
+primitive("clubpenalties",set_shape,club_penalties_loc);@/
+@!@:club_penalties_}{\.{\\clubpenalties} primitive@>
+primitive("widowpenalties",set_shape,widow_penalties_loc);@/
+@!@:widow_penalties_}{\.{\\widowpenalties} primitive@>
+primitive("displaywidowpenalties",set_shape,display_widow_penalties_loc);@/
+@!@:display_widow_penalties_}{\.{\\displaywidowpenalties} primitive@>
+
+@ @<Cases of |set_shape| for |print_cmd_chr|@>=
+inter_line_penalties_loc: print_esc("interlinepenalties");
+club_penalties_loc: print_esc("clubpenalties");
+widow_penalties_loc: print_esc("widowpenalties");
+display_widow_penalties_loc: print_esc("displaywidowpenalties");
+
+@ @<Fetch a penalties array element@>=
+begin scan_int;
+if (equiv(m)=null)or(cur_val<0) then cur_val:=0
+else begin if cur_val>penalty(equiv(m)) then cur_val:=penalty(equiv(m));
+ cur_val:=penalty(equiv(m)+cur_val);
+ end;
+end
+
+@ This is needed to get the relative order of the marks code correct
+
+@<Show the meaning of a mark node@>=
+if (cur_cmd=top_bot_mark)and(cur_chr<marks_code) then
+ begin print_char(":"); print_ln;
+ case cur_chr of
+ first_mark_code: token_show(first_mark(0));
+ bot_mark_code: token_show(bot_mark(0));
+ split_first_mark_code: token_show(split_first_mark(0));
+ split_bot_mark_code: token_show(split_bot_mark(0));
+ othercases token_show(top_mark(0));
+ endcases;
+end
+
+
+@ The lua interface needs some extra pascal functions. The functions
+themselves are quite boring, but they are handy because otherwise this
+internal stuff has to be accessed from C directly, where lots of the
+pascal defines are not available.
+
+@p function get_tex_dimen_register (j:integer):scaled;
+begin
+ get_tex_dimen_register := dimen(j);
+end;
+
+function set_tex_dimen_register (j:integer;v:scaled):integer;
+var a:small_number;
+begin {return non-nil for error}
+a:=0;
+word_define(j+scaled_base,v);
+set_tex_dimen_register := 0;
+end;
+
+function get_tex_count_register (j:integer):scaled;
+begin
+ get_tex_count_register := count(j);
+end;
+
+function set_tex_count_register (j:integer;v:scaled):integer;
+var a:small_number;
+begin {return non-nil for error}
+a:=0;
+word_define(j+count_base,v);
+set_tex_count_register := 0;
+end;
+
+function get_tex_attribute_register (j:integer):scaled;
+begin
+ get_tex_attribute_register := attribute(j);
+end;
+
+function set_tex_attribute_register (j:integer;v:scaled):integer;
+var a:small_number;
+begin {return non-nil for error}
+a:=0;
+word_define(j+attribute_base,v);
+set_tex_attribute_register := 0;
+end;
+
+function get_tex_toks_register (j:integer):str_number;
+var s:str_number;
+begin
+ s:="";
+ if toks(j) <> min_halfword then begin
+ s := tokens_to_string(toks(j));
+ end;
+ get_tex_toks_register := s;
+end;
+
+function set_tex_toks_register (j:integer;s:str_number):integer;
+var s_pool_ptr:pool_pointer;
+ ref:pointer;
+ a:small_number;
+ junk:pointer;
+begin
+ set_tex_toks_register := 0;
+ s_pool_ptr := pool_ptr;
+ pool_ptr := str_start_macro(s+1);
+ ref := get_avail;
+ junk := str_toks(str_start_macro(s));
+ pool_ptr := s_pool_ptr;
+ token_ref_count(ref) := 0;
+ link(ref) := link(temp_token_head);
+ a:=0;
+ define(j+toks_base,call,ref);
+ flush_str(s);
+end;
+
+function get_tex_box_register (j:integer):integer;
+begin
+ get_tex_box_register := box(j);
+end;
+
+function set_tex_box_register (j:integer;v:scaled):integer;
+var a:small_number;
+begin {return non-nil for error}
+a:=0;
+eq_define(j+box_base,box_ref,v);
+set_tex_box_register := 0;
+end;
+
+
+function get_tex_box_width (j:integer):scaled;
+var q:pointer;
+begin
+ q := box(j);
+ get_tex_box_width := 0;
+ if q <> min_halfword then
+ get_tex_box_width := width(q);
+end;
+
+function set_tex_box_width (j:integer;v:scaled):integer;
+var q:pointer;
+begin
+ q := box(j);
+ set_tex_box_width := 0;
+ if q <> min_halfword then
+ width(q) := v
+ else
+ set_tex_box_width := 1;
+end;
+
+function get_tex_box_height (j:integer):scaled;
+var q:pointer;
+begin
+ q := box(j);
+ get_tex_box_height := 0;
+ if q <> min_halfword then
+ get_tex_box_height := height(q);
+end;
+
+function set_tex_box_height (j:integer;v:scaled):integer;
+var q:pointer;
+begin
+ q := box(j);
+ set_tex_box_height := 0;
+ if q <> min_halfword then
+ height(q) := v
+ else
+ set_tex_box_height := 1;
+end;
+
+function get_tex_box_depth (j:integer):scaled;
+var q:pointer;
+begin
+ q := box(j);
+ get_tex_box_depth := 0;
+ if q <> min_halfword then
+ get_tex_box_depth := depth(q);
+end;
+
+function set_tex_box_depth (j:integer;v:scaled):integer;
+var q:pointer;
+begin
+ q := box(j);
+ set_tex_box_depth := 0;
+ if q <> min_halfword then
+ depth(q) := v
+ else
+ set_tex_box_depth := 1;
+end;
+
+function get_cur_v: integer;
+begin
+ get_cur_v := cur_page_height - cur_v;
+end;
+
+function get_cur_h: integer;
+begin
+ get_cur_h := cur_h;
+end;
+
+@* \[54] $\Omega$ changes.
+
+@ Here we do the main work required for reading and interpreting
+ $\Omega$ Compiled Translation Processes.
+
+@ Here are all the instructions in our mini-assembler.
+@d otp_right_output=1
+@d otp_right_num=2
+@d otp_right_char=3
+@d otp_right_lchar=4
+@d otp_right_some=5
+
+@d otp_pback_output=6
+@d otp_pback_num=7
+@d otp_pback_char=8
+@d otp_pback_lchar=9
+@d otp_pback_some=10
+
+@d otp_add=11
+@d otp_sub=12
+@d otp_mult=13
+@d otp_div=14
+@d otp_mod=15
+@d otp_lookup=16
+@d otp_push_num=17
+@d otp_push_char=18
+@d otp_push_lchar=19
+
+@d otp_state_change=20
+@d otp_state_push=21
+@d otp_state_pop=22
+
+@d otp_left_start=23
+@d otp_left_return=24
+@d otp_left_backup=25
+
+@d otp_goto=26
+@d otp_goto_ne=27
+@d otp_goto_eq=28
+@d otp_goto_lt=29
+@d otp_goto_le=30
+@d otp_goto_gt=31
+@d otp_goto_ge=32
+@d otp_goto_no_advance=33
+@d otp_goto_beg=34
+@d otp_goto_end=35
+
+@d otp_stop=36
+
+@
+@<Glob...@>=
+@!otp_init_input_start:halfword;
+@!otp_init_input_last:halfword;
+@!otp_init_input_end:halfword;
+@!otp_i:halfword;
+@!otp_init_input_buf:array[0..20000] of quarterword;
+
+@!otp_input_start:halfword;
+@!otp_input_last:halfword;
+@!otp_input_end:halfword;
+@!otp_input_buf:array[0..20000] of quarterword;
+
+@!otp_output_end:halfword;
+@!otp_output_buf:array[0..20000] of quarterword;
+
+@!otp_stack_used:halfword;
+@!otp_stack_last:halfword;
+@!otp_stack_new:halfword;
+@!otp_stack_buf:array[0..1000] of quarterword;
+
+@!otp_pc:halfword;
+
+@!otp_calc_ptr:halfword;
+@!otp_calcs:array[0..1000] of halfword;
+@!otp_state_ptr:halfword;
+@!otp_states:array[0..1000] of halfword;
+
+@!otp_input_char:halfword;
+@!otp_calculated_char:halfword;
+@!otp_no_input_chars:halfword;
+
+@!otp_instruction:halfword;
+@!otp_instr:halfword;
+@!otp_arg:halfword;
+@!otp_first_arg:halfword;
+@!otp_second_arg:halfword;
+
+@!otp_input_ocp:halfword;
+@!otp_counter:halfword;
+
+@!otp_finished:boolean;
+@!otp_ext_str:integer;
+@!otp_ext_str_arg:integer;
+@!otp_ext_i:integer;
+
+@
+@<Initialize table...@>=
+
+@
+@<Create a buffer with character |cur_chr| and the following
+ characters (if~any) and then apply the current active OCP filter
+ to this buffer@>=
+begin
+@<Read in the buffer for treatment@>;
+@<Apply the OCP to the input buffer@>;
+@<Place the output buffer back on the stream@>;
+goto big_switch;
+end;
+
+@ The OTP input buffer is an array of 16-bit values.
+In the future, the range |@"D800| \dots |@"DFFF| will be used for
+surrogate pairs, so it cannot be used for simple 16-bit values
+like it is in Omega, so a future incompatibility with Aleph is
+unavoidable.
+
+@<Read in the buffer for treatment@>=
+begin
+otp_init_input_end:=0;
+while (cur_cmd=letter) or (cur_cmd=other_char) or
+ (cur_cmd=char_given) or (cur_cmd=spacer) do begin
+ incr(otp_init_input_end);
+ if otp_init_input_end >ocp_buf_size then
+ overflow_ocp_buf_size;
+ { |cur_chr| can cover the full range |0..0x10FFFF| }
+ if cur_chr<@"10000 then
+ otp_init_input_buf[otp_init_input_end]:=cur_chr
+ else begin
+ otp_init_input_buf[otp_init_input_end]:=((cur_chr - @"10000) div @"400) + @"D800;
+ incr(otp_init_input_end);
+ if otp_init_input_end >ocp_buf_size then
+ overflow_ocp_buf_size;
+ otp_init_input_buf[otp_init_input_end]:=((cur_chr - @"10000) mod @"400) + @"DC00;
+ end;
+ get_token;
+ if (cur_cmd<>letter) and (cur_cmd<>other_char) and
+ (cur_cmd<>char_given) then begin
+ x_token;
+ if (cur_cmd=char_num) then begin
+ scan_char_num; cur_cmd:=other_char; cur_chr:=cur_val;
+ end;
+ end;
+ end;
+back_input;
+otp_input_end:=otp_init_input_end;
+for otp_i:=0 to otp_init_input_end do begin
+ otp_input_buf[otp_i]:=otp_init_input_buf[otp_i];
+ end;
+end
+
+@
+@<Apply the OCP to the input buffer@>=
+begin
+otp_input_ocp:=active_ocp(active_real);
+if otp_input_ocp=0 then begin
+ print_err("Null ocp being used: all input lost");
+ error;
+ otp_output_end:=0;
+ end
+else if ocp_external(otp_input_ocp)=0 then begin
+ otp_input_start:=0;
+ otp_input_last:=0;
+ otp_stack_used:=0;
+ otp_stack_last:=0;
+ otp_stack_new:=0;
+ otp_output_end:=0;
+ otp_pc:=0;
+ otp_finished:=false;
+ otp_calc_ptr:=0;
+ otp_calcs[otp_calc_ptr]:=0;
+ otp_state_ptr:=0;
+ otp_states[otp_state_ptr]:=0;
+ while not otp_finished do
+ @<Run the OTP program@>;
+ end
+else begin
+ k:=0;
+ if nameoffile then libcfree (nameoffile);
+ otp_ext_str:=ocp_external(otp_input_ocp);
+ otp_ext_str_arg:=ocp_external_arg(otp_input_ocp);
+ nameoffile := xmalloc (4 + length(otp_ext_str) + length(otp_ext_str_arg));
+ for otp_ext_i:=str_start_macro(otp_ext_str) to
+ str_start_macro(otp_ext_str)+length(otp_ext_str)-1 do
+ append_to_name(str_pool[otp_ext_i]);
+ append_to_name(" ");
+ for otp_ext_i:=str_start_macro(otp_ext_str_arg) to
+ str_start_macro(otp_ext_str_arg)+length(otp_ext_str_arg)-1 do
+ append_to_name(str_pool[otp_ext_i]);
+ nameoffile[length(otp_ext_str)+length(otp_ext_str_arg)+2]:=0;
+ run_external_ocp(nameoffile);
+ end
+end
+
+@ The OTP output buffer is an array of 16-bit values. To convert back
+to the |buffer| it has to be re-encoded into UTF-8. An incompatibility
+with Aleph is unavoidable here: The range |@"D800| \dots |@"DFFF| is
+used for surrogate pairs, not for simple 16-bit values.
+
+@<Place the output buffer back on the stream@>=
+begin
+if (first+otp_output_end)>=ocp_buf_size then
+ overflow_ocp_buf_size;
+push_input;
+current_ocp_lstack:=active_lstack_no(active_real);
+current_ocp_no:=active_counter(active_real);
+state:=mid_line;
+start:=first;
+last:=start;
+loc:=start;
+for otp_counter:=1 to otp_output_end do begin
+ { convert back to utf-8 }
+ t := otp_output_buf[otp_counter];
+ if otp_counter < otp_output_end then
+ if ((t>=@"D800) and (t<@"DC00)) then
+ if (otp_output_buf[otp_counter+1]>=@"DC00)
+ and (otp_output_buf[otp_counter+1]<@"E000) then begin
+ incr(otp_counter);
+ t := (t-@"D800) * @"400 + (otp_output_buf[otp_counter]-@"DC00) + @"10000;
+ end
+ else if ((t>=@"DC00) and (t<@"E000)) then
+ if (otp_output_buf[otp_counter+1]>=@"D800)
+ and (otp_output_buf[otp_counter+1]<@"DC00) then begin
+ incr(otp_counter);
+ t := (otp_output_buf[otp_counter]-@"D800) * @"400 + (t-@"DC00) + @"10000;
+ end;
+ if t <= @"7F then
+ buffer[last]:= t
+ else if t<=@"7FF then begin
+ buffer[last]:=@"C0 + t div @"40;
+ incr(last);
+ if last=buf_size-2 then
+ @<Report overflow of the input buffer, and abort@>;
+ buffer[last]:=@"80 + t mod @"40;
+ end
+ else if t<=@"FFFF then begin
+ buffer[last]:=@"E0 + t div @"1000;
+ incr(last);
+ if last=buf_size-2 then
+ @<Report overflow of the input buffer, and abort@>;
+ buffer[last]:=@"80 + (t mod @"1000) div @"40;
+ incr(last);
+ if last=buf_size-2 then
+ @<Report overflow of the input buffer, and abort@>;
+ buffer[last]:=@"80 + (t mod @"1000) mod @"40;
+ end
+ else begin
+ buffer[last]:=@"F0 + t div @"40000;
+ incr(last);
+ if last=buf_size-2 then
+ @<Report overflow of the input buffer, and abort@>;
+ buffer[last]:=@"80 + (t mod @"40000) div @"1000;
+ incr(last);
+ if last=buf_size-2 then
+ @<Report overflow of the input buffer, and abort@>;
+ buffer[last]:=@"80 + ((t mod @"40000) mod @"1000) div @"40;
+ incr(last);
+ if last=buf_size-2 then
+ @<Report overflow of the input buffer, and abort@>;
+ buffer[last]:=@"80 + ((t mod @"40000) mod @"1000) mod @"40;
+ end;
+ incr(last);
+ if last=buf_size-2 then
+ @<Report overflow of the input buffer, and abort@>;
+ end;
+limit:=last-1;
+if (t>@"FFFF) then decr(limit);
+if (t>@"7FF) then decr(limit);
+if (t>@"7F) then decr(limit);
+first:=last;
+end
+
+@
+@d otp_cur_state==otp_states[otp_state_ptr]
+@d otp_set_instruction==begin
+if otp_pc>=ocp_state_no(otp_input_ocp)(otp_cur_state) then begin
+ print_err("bad OCP program -- PC not valid");
+ succumb;
+ end;
+otp_instruction:=ocp_state_entry(otp_input_ocp)(otp_cur_state)(otp_pc);
+otp_instr:=otp_instruction div @"1000000;
+otp_arg:=otp_instruction mod @"1000000;
+end
+
+@<Run the OTP program@>=
+begin
+otp_set_instruction;
+case otp_instr of
+ @<Run the |otp_right| instructions@>;
+ @<Run the |otp_pback| instructions@>;
+ @<Run the arithmetic instructions@>;
+ @<Run the |otp_state| instructions@>;
+ @<Run the |otp_left| instructions@>;
+ @<Run the |otp_goto| instructions@>;
+ @<Run the |otp_stop| instruction@>;
+ othercases begin
+ print_err("bad OCP program -- unknown instruction");
+ succumb;
+ end
+ endcases;
+end
+
+@
+
+@d otp_check_char(#)==
+if (1>#) or (#>otp_no_input_chars) then begin
+ print_err("right hand side of OCP expression is bad");
+ succumb;
+ end
+
+@d otp_get_char(#)==begin
+otp_check_char(#);
+if #>otp_stack_last then begin
+ otp_calculated_char:=otp_input_buf[otp_input_start+#-otp_stack_last];
+ end
+else begin
+ otp_calculated_char:=otp_stack_buf[#];
+ end;
+end
+
+@<Run the |otp_right| instructions@>=
+ otp_right_output: begin
+ incr(otp_output_end);
+ if otp_output_end >ocp_buf_size then
+ overflow_ocp_buf_size;
+ otp_output_buf[otp_output_end]:=otp_calcs[otp_calc_ptr];
+ decr(otp_calc_ptr);
+ incr(otp_pc);
+ end;
+ otp_right_num: begin
+ incr(otp_output_end);
+ if otp_output_end >ocp_buf_size then
+ overflow_ocp_buf_size;
+ otp_output_buf[otp_output_end]:=otp_arg;
+ incr(otp_pc);
+ end;
+ otp_right_char: begin
+ otp_get_char(otp_arg);
+ incr(otp_output_end);
+ if otp_output_end >ocp_buf_size then
+ overflow_ocp_buf_size;
+ otp_output_buf[otp_output_end]:=otp_calculated_char;
+ incr(otp_pc);
+ end;
+ otp_right_lchar: begin
+ otp_get_char(otp_no_input_chars-otp_arg);
+ incr(otp_output_end);
+ if otp_output_end >ocp_buf_size then
+ overflow_ocp_buf_size;
+ otp_output_buf[otp_output_end]:=otp_calculated_char;
+ incr(otp_pc);
+ end;
+ otp_right_some: begin
+ otp_first_arg:=otp_arg+1;
+ incr(otp_pc);
+ otp_set_instruction;
+ otp_second_arg:=otp_no_input_chars-otp_arg;
+ for otp_counter:=otp_first_arg to otp_second_arg do begin
+ otp_get_char(otp_counter);
+ incr(otp_output_end);
+ if otp_output_end >ocp_buf_size then
+ overflow_ocp_buf_size;
+ otp_output_buf[otp_output_end]:=otp_calculated_char;
+ end;
+ incr(otp_pc);
+ end
+
+@
+@<Run the |otp_pback| instructions@>=
+ otp_pback_output: begin
+ incr(otp_stack_new);
+ if otp_stack_new >= ocp_stack_size then
+ overflow_ocp_stack_size;
+ otp_stack_buf[otp_stack_new]:=otp_calcs[otp_calc_ptr];
+ decr(otp_calc_ptr);
+ incr(otp_pc);
+ end;
+ otp_pback_num: begin
+ incr(otp_stack_new);
+ if otp_stack_new >= ocp_stack_size then
+ overflow_ocp_stack_size;
+ otp_stack_buf[otp_stack_new]:=otp_arg;
+ incr(otp_pc);
+ end;
+ otp_pback_char: begin
+ otp_get_char(otp_arg);
+ incr(otp_stack_new);
+ if otp_stack_new >= ocp_stack_size then
+ overflow_ocp_stack_size;
+ otp_stack_buf[otp_stack_new]:=otp_calculated_char;
+ incr(otp_pc);
+ end;
+ otp_pback_lchar: begin
+ otp_get_char(otp_no_input_chars-otp_arg);
+ incr(otp_stack_new);
+ if otp_stack_new >= ocp_stack_size then
+ overflow_ocp_stack_size;
+ otp_stack_buf[otp_stack_new]:=otp_calculated_char;
+ incr(otp_pc);
+ end;
+ otp_pback_some: begin
+ otp_first_arg:=otp_arg+1;
+ incr(otp_pc);
+ otp_set_instruction;
+ otp_second_arg:=otp_no_input_chars-otp_arg;
+ for otp_counter:=otp_first_arg to otp_second_arg do begin
+ otp_get_char(otp_counter);
+ incr(otp_stack_new);
+ if otp_stack_new >= ocp_stack_size then
+ overflow_ocp_stack_size;
+ otp_stack_buf[otp_stack_new]:=otp_calculated_char;
+ end;
+ incr(otp_pc);
+ end
+
+@
+@<Run the arithmetic instructions@>=
+ otp_add: begin
+ otp_calcs[otp_calc_ptr-1] :=
+ otp_calcs[otp_calc_ptr-1] + otp_calcs[otp_calc_ptr];
+ incr(otp_pc);
+ decr(otp_calc_ptr);
+ end;
+ otp_sub: begin
+ otp_calcs[otp_calc_ptr-1] :=
+ otp_calcs[otp_calc_ptr-1] - otp_calcs[otp_calc_ptr];
+ incr(otp_pc);
+ decr(otp_calc_ptr);
+ end;
+ otp_mult: begin
+ otp_calcs[otp_calc_ptr-1] :=
+ otp_calcs[otp_calc_ptr-1] * otp_calcs[otp_calc_ptr];
+ incr(otp_pc);
+ decr(otp_calc_ptr);
+ end;
+ otp_div: begin
+ otp_calcs[otp_calc_ptr-1] :=
+ otp_calcs[otp_calc_ptr-1] div otp_calcs[otp_calc_ptr];
+ incr(otp_pc);
+ decr(otp_calc_ptr);
+ end;
+ otp_mod: begin
+ otp_calcs[otp_calc_ptr-1] :=
+ otp_calcs[otp_calc_ptr-1] mod otp_calcs[otp_calc_ptr];
+ incr(otp_pc);
+ decr(otp_calc_ptr);
+ end;
+ otp_lookup: begin
+ if otp_calcs[otp_calc_ptr]>=
+ ocp_table_no(otp_input_ocp)(otp_calcs[otp_calc_ptr-1]) then begin
+ print_err("bad OCP program -- table index not valid");
+ succumb;
+ end;
+ otp_calcs[otp_calc_ptr-1]:=
+ ocp_table_entry(otp_input_ocp)(otp_calcs[otp_calc_ptr-1])
+ (otp_calcs[otp_calc_ptr]);
+ incr(otp_pc);
+ decr(otp_calc_ptr);
+ end;
+ otp_push_num: begin
+ incr(otp_calc_ptr);
+ if otp_calc_ptr >= ocp_stack_size then
+ overflow_ocp_stack_size;
+ otp_calcs[otp_calc_ptr]:=otp_arg;
+ incr(otp_pc);
+ end;
+ otp_push_char: begin
+ otp_get_char(otp_arg);
+ incr(otp_calc_ptr);
+ if otp_calc_ptr >= ocp_stack_size then
+ overflow_ocp_stack_size;
+ otp_calcs[otp_calc_ptr]:=otp_calculated_char;
+ incr(otp_pc);
+ end;
+ otp_push_lchar: begin
+ otp_get_char(otp_no_input_chars-otp_arg);
+ incr(otp_calc_ptr);
+ if otp_calc_ptr >= ocp_stack_size then
+ overflow_ocp_stack_size;
+ otp_calcs[otp_calc_ptr]:=otp_calculated_char;
+ incr(otp_pc);
+ end
+
+@
+@<Run the |otp_state| instructions@>=
+ otp_state_change: begin
+ otp_input_start:=otp_input_last;
+ for otp_counter:=1 to (otp_stack_new-otp_stack_used) do begin
+ otp_stack_buf[otp_counter] :=
+ otp_stack_buf[otp_counter+otp_stack_used];
+ end;
+ otp_stack_new:=otp_stack_new-otp_stack_used;
+ otp_stack_last:=otp_stack_new;
+ otp_stack_used:=0;
+ otp_states[otp_state_ptr]:=otp_arg;
+ otp_pc:=0;
+ end;
+ otp_state_push: begin
+ otp_input_start:=otp_input_last;
+ for otp_counter:=1 to (otp_stack_new-otp_stack_used) do begin
+ otp_stack_buf[otp_counter] :=
+ otp_stack_buf[otp_counter+otp_stack_used];
+ end;
+ otp_stack_new:=otp_stack_new-otp_stack_used;
+ otp_stack_last:=otp_stack_new;
+ otp_stack_used:=0;
+ incr(otp_state_ptr);
+ if otp_state_ptr >= ocp_stack_size then
+ overflow_ocp_stack_size;
+ otp_states[otp_state_ptr]:=otp_arg;
+ otp_pc:=0;
+ end;
+ otp_state_pop: begin
+ otp_input_start:=otp_input_last;
+ for otp_counter:=1 to (otp_stack_new-otp_stack_used) do begin
+ otp_stack_buf[otp_counter] :=
+ otp_stack_buf[otp_counter+otp_stack_used];
+ end;
+ otp_stack_new:=otp_stack_new-otp_stack_used;
+ otp_stack_last:=otp_stack_new;
+ otp_stack_used:=0;
+ if otp_state_ptr>0 then decr(otp_state_ptr);
+ otp_pc:=0;
+ end
+
+@
+@<Run the |otp_left| instructions@>=
+ otp_left_start: begin
+ otp_input_start:=otp_input_last;
+ otp_input_last:=otp_input_start;
+ otp_stack_used:=0;
+ if (otp_stack_last=0) and (otp_input_last>=otp_input_end) then
+ otp_finished:=true
+ else if (otp_stack_used < otp_stack_last) then begin
+ incr(otp_stack_used); {no overflow problem}
+ otp_input_char:=otp_stack_buf[otp_stack_used];
+ otp_no_input_chars:=1;
+ incr(otp_pc);
+ end
+ else begin
+ incr(otp_input_last); {no overflow problem}
+ otp_input_char:=otp_input_buf[otp_input_last];
+ otp_no_input_chars:=1;
+ incr(otp_pc);
+ end;
+ end;
+ otp_left_return: begin
+ otp_input_last:=otp_input_start;
+ otp_stack_used:=0;
+ if (otp_stack_used < otp_stack_last) then begin
+ incr(otp_stack_used); {no overflow problem}
+ otp_input_char:=otp_stack_buf[otp_stack_used];
+ otp_no_input_chars:=1;
+ incr(otp_pc);
+ end
+ else begin
+ incr(otp_input_last); {no overflow problem}
+ otp_input_char:=otp_input_buf[otp_input_last];
+ otp_no_input_chars:=1;
+ incr(otp_pc);
+ end;
+ end;
+ otp_left_backup: begin
+ if otp_input_start < otp_input_last then begin
+ decr(otp_input_last); otp_input_char:=otp_input_buf[otp_input_last];
+ end
+ else begin
+ decr(otp_stack_used); otp_input_char:=otp_stack_buf[otp_stack_used];
+ end;
+ decr(otp_no_input_chars);
+ incr(otp_pc);
+ end
+
+@
+@<Run the |otp_goto| instructions@>=
+ otp_goto: begin
+ otp_pc:=otp_arg;
+ end;
+ otp_goto_ne: begin
+ otp_first_arg:=otp_arg;
+ incr(otp_pc);
+ otp_set_instruction;
+ if otp_input_char <> otp_first_arg then begin
+ otp_pc:=otp_arg;
+ end
+ else begin
+ incr(otp_pc);
+ end;
+ end;
+ otp_goto_eq: begin
+ otp_first_arg:=otp_arg;
+ incr(otp_pc);
+ otp_set_instruction;
+ if otp_input_char = otp_first_arg then begin
+ otp_pc:=otp_arg;
+ end
+ else begin
+ incr(otp_pc);
+ end;
+ end;
+ otp_goto_lt: begin
+ otp_first_arg:=otp_arg;
+ incr(otp_pc);
+ otp_set_instruction;
+ if otp_input_char < otp_first_arg then begin
+ otp_pc:=otp_arg;
+ end
+ else begin
+ incr(otp_pc);
+ end;
+ end;
+ otp_goto_le: begin
+ otp_first_arg:=otp_arg;
+ incr(otp_pc);
+ otp_set_instruction;
+ if otp_input_char <= otp_first_arg then begin
+ otp_pc:=otp_arg;
+ end
+ else begin
+ incr(otp_pc);
+ end;
+ end;
+ otp_goto_gt: begin
+ otp_first_arg:=otp_arg;
+ incr(otp_pc);
+ otp_set_instruction;
+ if otp_input_char > otp_first_arg then begin
+ otp_pc:=otp_arg;
+ end
+ else begin
+ incr(otp_pc);
+ end;
+ end;
+ otp_goto_ge: begin
+ otp_first_arg:=otp_arg;
+ incr(otp_pc);
+ otp_set_instruction;
+ if otp_input_char >= otp_first_arg then begin
+ otp_pc:=otp_arg;
+ end
+ else begin
+ incr(otp_pc);
+ end;
+ end;
+ otp_goto_no_advance: begin
+ if (otp_stack_used < otp_stack_last) then begin
+ incr(otp_stack_used); {no overflow problem}
+ otp_input_char:=otp_stack_buf[otp_stack_used];
+ incr(otp_no_input_chars); {no overflow problem}
+ incr(otp_pc);
+ end
+ else if otp_input_last>=otp_input_end then begin
+ otp_pc:=otp_arg;
+ end
+ else begin
+ incr(otp_input_last); {no overflow problem}
+ otp_input_char:=otp_input_buf[otp_input_last];
+ incr(otp_no_input_chars); {no overflow problem}
+ incr(otp_pc);
+ end;
+ end;
+ otp_goto_beg: begin
+ if otp_input_last=0 then begin
+ otp_pc:=otp_arg;
+ end
+ else begin
+ incr(otp_pc);
+ end;
+ end;
+ otp_goto_end: begin
+ if otp_input_last>=otp_input_end then begin
+ otp_pc:=otp_arg;
+ end
+ else begin
+ incr(otp_pc);
+ end;
+ end
+
+@
+@<Run the |otp_stop| instruction@>=
+ otp_stop: begin
+ otp_input_start:=otp_input_last;
+ for otp_counter:=1 to (otp_stack_new-otp_stack_used) do begin
+ otp_stack_buf[otp_counter] :=
+ otp_stack_buf[otp_counter+otp_stack_used];
+ end;
+ otp_stack_new:=otp_stack_new-otp_stack_used;
+ otp_stack_last:=otp_stack_new;
+ otp_stack_used:=0;
+ otp_pc:=0;
+ end
+
+@ @<Put each...@>=
+primitive("ocp", def_ocp, 0);
+primitive("externalocp", def_ocp, 1);
+primitive("ocplist", def_ocp_list, 0);
+primitive("pushocplist", push_ocp_list, 0);
+primitive("popocplist", pop_ocp_list, 0);
+primitive("clearocplists", clear_ocp_lists, 0);
+primitive("addbeforeocplist", ocp_list_op, add_before_op);
+primitive("addafterocplist", ocp_list_op, add_after_op);
+primitive("removebeforeocplist", ocp_list_op, remove_before_op);
+primitive("removeafterocplist", ocp_list_op, remove_after_op);
+primitive("ocptracelevel", ocp_trace_level, 0);
+equiv(ocp_trace_level_base):=0;
+
+@ @<Cases of |print_cmd_chr|...@>=
+set_ocp: begin
+ print("select ocp ");
+ slow_print(ocp_name(chr_code));
+ end;
+def_ocp: if cur_chr=0 then print_esc("ocp")
+ else print_esc("externalocp");
+set_ocp_list: print("select ocp list ");
+def_ocp_list: print_esc("ocplist");
+push_ocp_list: print_esc("pushocplist");
+pop_ocp_list: print_esc("popocplist");
+clear_ocp_lists: print_esc("clearocplists");
+ocp_list_op:
+ if chr_code=add_before_op then print_esc("addbeforeocplist")
+ else if chr_code=add_after_op then print_esc("addafterocplist")
+ else if chr_code=remove_before_op then print_esc("removebeforeocplist")
+ else {|chr_code|=|remove_after_op|} print_esc("removeafterocplist");
+ocp_trace_level: print_esc("ocptracelevel");
+
+@ @<Assignments@>=
+set_ocp: begin
+ print_err("To use ocps, use the "); print_esc("pushocplist");
+ print(" primitive");print_ln
+ end;
+def_ocp: new_ocp(a);
+set_ocp_list: begin
+ print_err("To use ocp lists, use the ");
+ print_esc("pushocplist"); print(" primitive");print_ln
+ end;
+def_ocp_list: new_ocp_list(a);
+push_ocp_list: do_push_ocp_list(a);
+pop_ocp_list: do_pop_ocp_list(a);
+clear_ocp_lists: do_clear_ocp_lists(a);
+ocp_list_op: begin
+ print_err("To build ocp lists, use the ");
+ print_esc("ocplist"); print(" primitive"); print_ln
+ end;
+ocp_trace_level: begin scan_optional_equals; scan_int;
+ if cur_val<>0 then cur_val:=1;
+ define(ocp_trace_level_base, data, cur_val);
+ end;
+
+@ @<Declare subprocedures for |prefixed_command|@>=
+procedure new_ocp(@!a:small_number);
+label common_ending;
+var u:pointer; {user's ocp identifier}
+@!f:internal_ocp_number; {runs through existing ocps}
+@!t:str_number; {name for the frozen ocp identifier}
+@!old_setting:0..max_selector; {holds |selector| setting}
+@!flushable_string:str_number; {string not yet referenced}
+@!external_ocp:boolean; {external binary file}
+begin if job_name=0 then open_log_file;
+ {avoid confusing \.{texput} with the ocp name}
+@.texput@>
+if cur_chr=1 then external_ocp:=true
+else external_ocp:=false;
+get_r_token; u:=cur_cs;
+if u>=hash_base then t:=text(u)
+else if u=null_cs then t:="OCP"
+else begin old_setting:=selector; selector:=new_string;
+ print("OCP"); print(u-active_base); selector:=old_setting;
+@.OCPx@>
+ str_room(1); t:=make_string;
+ end;
+define(u,set_ocp,null_ocp); scan_optional_equals; scan_file_name;
+@<If this ocp has already been loaded, set |f| to the internal
+ ocp number and |goto common_ending|@>;
+f:=read_ocp_info(u,cur_name,cur_area,cur_ext,external_ocp);
+common_ending:
+equiv(u):=f; eqtb[ocp_id_base+f] := eqtb[u];
+text(ocp_id_base+f) := t;
+if equiv(ocp_trace_level_base)=1 then begin
+ print_nl(""); print_esc("ocp"); print_esc(t); print("="); print(cur_name);
+ end;
+end;
+
+@ When the user gives a new identifier to a ocp that was previously loaded,
+the new name becomes the ocp identifier of record. OCP names `\.{xyz}' and
+`\.{XYZ}' are considered to be different.
+
+@<If this ocp has already been loaded...@>=
+flushable_string:=str_ptr-1;
+for f:=ocp_base+1 to ocp_ptr do
+ if str_eq_str(ocp_name(f),cur_name)and str_eq_str(ocp_area(f),cur_area) then
+ begin
+ if cur_name=flushable_string then begin
+ flush_string; cur_name:=ocp_name(f);
+ end;
+ goto common_ending
+ end
+
+@ @<Declare subprocedures for |prefixed_command|@>=
+procedure new_ocp_list(@!a:small_number);
+var u:pointer; {user's ocp list identifier}
+@!f:internal_ocp_list_number; {runs through existing ocp lists}
+@!t:str_number; {name for the frozen ocp list identifier}
+@!old_setting:0..max_selector; {holds |selector| setting}
+begin if job_name=0 then open_log_file;
+ {avoid confusing \.{texput} with the ocp list name}
+@.texput@>
+get_r_token; u:=cur_cs;
+if u>=hash_base then t:=text(u)
+else if u=null_cs then t:="OCPLIST"
+else begin old_setting:=selector; selector:=new_string;
+ print("OCPLIST"); print(u-active_base); selector:=old_setting;
+@.OCPx@>
+ str_room(1); t:=make_string;
+ end;
+define(u,set_ocp_list,null_ocp_list); scan_optional_equals;
+f:=read_ocp_list;
+ equiv(u) := f; eqtb[ocp_list_id_base+f] := eqtb[u];
+ text(ocp_list_id_base+f) := t;
+if equiv(ocp_trace_level_base)=1 then begin
+ print_nl(""); print_esc("ocplist"); print_esc(t); print("=");
+ print_ocp_list(ocp_list_list[f]);
+ end;
+end;
+
+@ @<Declare subprocedures for |prefixed_command|@>=
+procedure do_push_ocp_list(@!a:small_number);
+var ocp_list_no:halfword;
+ old_number:halfword;
+ i:integer;
+begin
+scan_ocp_list_ident; ocp_list_no:=cur_val;
+old_number:=equiv(ocp_active_number_base);
+define(ocp_active_base+old_number, data, ocp_list_no);
+define(ocp_active_number_base, data, (old_number+1));
+
+if equiv(ocp_trace_level_base)=1 then begin
+ print_nl("New active ocp list: {");
+ for i:=old_number downto 0 do begin
+ print_esc(ocp_list_id_text(equiv(ocp_active_base+i)));
+ print("="); print_ocp_list(ocp_list_list[equiv(ocp_active_base+i)]);
+ if i<>0 then print(",");
+ end;
+ print("}");
+ end;
+
+active_compile;
+define(ocp_active_min_ptr_base, data, active_min_ptr);
+define(ocp_active_max_ptr_base, data, active_max_ptr);
+end;
+
+@ @<Declare subprocedures for |prefixed_command|@>=
+procedure do_pop_ocp_list(@!a:small_number);
+var old_number:halfword;
+ i:integer;
+begin
+old_number:=equiv(ocp_active_number_base);
+if old_number=0 then begin
+ print_err("No active ocp lists to be popped");
+ end
+else
+ define(ocp_active_number_base, data, (old_number-1));
+
+if equiv(ocp_trace_level_base)=1 then begin
+ print_nl("New active ocp list: {");
+ for i:=(old_number-2) downto 0 do begin
+ print_esc(ocp_list_id_text(equiv(ocp_active_base+i)));
+ print("="); print_ocp_list(ocp_list_list[equiv(ocp_active_base+i)]);
+ if i<>0 then print(",");
+ end;
+ print("}");
+ end;
+
+active_compile;
+define(ocp_active_min_ptr_base, data, active_min_ptr);
+define(ocp_active_max_ptr_base, data, active_max_ptr);
+end;
+
+@ @<Declare subprocedures for |prefixed_command|@>=
+procedure do_clear_ocp_lists(@!a:small_number);
+begin
+define(ocp_active_number_base, data, 0);
+active_compile;
+define(ocp_active_min_ptr_base, data, active_min_ptr);
+define(ocp_active_max_ptr_base, data, active_max_ptr);
+end;
+
+
+@* \[54] System-dependent changes.
+This section should be replaced, if necessary, by any special
+modifications of the program
+that are necessary to make \TeX\ work at a particular installation.
+It is usually best to design your change file so that all changes to
+previous sections preserve the section numbering; then everybody's version
+will be consistent with the published program. More extensive changes,
+which introduce new sections, can be inserted here; then only the index
+itself will get a new section number.
+@^system dependencies@>
+
+@* \[55] Index.
+Here is where you can find all uses of each identifier in the program,
+with underlined entries pointing to where the identifier was defined.
+If the identifier is only one letter long, however, you get to see only
+the underlined entries. {\sl All references are to section numbers instead of
+page numbers.}
+
+This index also lists error messages and other aspects of the program
+that you might want to look up some day. For example, the entry
+for ``system dependencies'' lists all sections that should receive
+special attention from people who are installing \TeX\ in a new
+operating environment. A list of various things that can't happen appears
+under ``this can't happen''. Approximately 40 sections are listed under
+``inner loop''; these account for about 60\pct! of \TeX's running time,
+exclusive of input and output.
diff --git a/Build/source/texk/web2c/luatexdir/luatexextra.in b/Build/source/texk/web2c/luatexdir/luatexextra.in
new file mode 100644
index 00000000000..ffbd65f3c1c
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luatexextra.in
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 1996-2004 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id$
+*/
+
+/* luatexextra.in: banner etc. for luaTeX.
+
+ This is included by luaTeX, from ../luatexextra.c
+ (generated from ../lib/texmfmp.c).
+*/
+
+#define BANNER "This is luaTeX, Version 3.141592-LUATEX-VERSION-ETEX-VERSION"
+#define COPYRIGHT_HOLDER "Taco Hoekwater"
+#define AUTHOR NULL
+#define PROGRAM_HELP LUATEXHELP
+#define BUG_ADDRESS "dev-luatex@ntg.nl"
+#define DUMP_VAR TEX_format_default
+#define DUMP_LENGTH_VAR format_default_length
+#define DUMP_OPTION "fmt"
+#define DUMP_EXT ".fmt"
+#define INPUT_FORMAT kpse_tex_format
+#define INI_PROGRAM "luainitex"
+#define VIR_PROGRAM "luavirtex"
+#define TEXMFENGINENAME "luatex"
+
diff --git a/Build/source/texk/web2c/luatexdir/luatexlib.mk b/Build/source/texk/web2c/luatexdir/luatexlib.mk
new file mode 100644
index 00000000000..b1239b203ba
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luatexlib.mk
@@ -0,0 +1,214 @@
+## luatexlib.mk - Makefile fragment for libraries used by pdf[ex]tex.
+# $Id$
+# Public domain.
+
+# The pdf*tex programs depend on a number of libraries.
+# Include dependencies to get the built if we don't do make
+# from the top-level directory.
+
+Makefile: luatexdir/luatexlib.mk
+
+# libz
+
+ZLIBDIR=../../libs/zlib
+ZLIBSRCDIR=$(srcdir)/$(ZLIBDIR)
+ZLIBDEP = @ZLIBDEP@
+LDZLIB = @LDZLIB@
+
+$(ZLIBDIR)/libz.a: $(ZLIBSRCDIR)
+ cd $(ZLIBDIR) && $(MAKE) $(common_makeargs) libz.a
+
+# libpng
+
+LIBPNGDIR=../../libs/libpng
+LIBPNGSRCDIR=$(srcdir)/$(LIBPNGDIR)
+LIBPNGDEP = @LIBPNGDEP@
+LDLIBPNG = @LDLIBPNG@
+
+$(LIBPNGDIR)/libpng.a: $(LIBPNGSRCDIR)/*.c
+ cd $(LIBPNGDIR) && $(MAKE) $(common_makeargs) libpng.a
+
+
+# libxpdf
+
+LIBXPDFDIR=../../libs/xpdf
+LIBXPDFSRCDIR=$(srcdir)/$(LIBXPDFDIR)
+LIBXPDFDEP = @LIBXPDFDEP@
+LDLIBXPDF = @LDLIBXPDF@
+
+$(LIBXPDFDIR)/fofi/libfofi.a: $(LIBXPDFSRCDIR)/fofi/*.cc \
+ $(LIBXPDFSRCDIR)/fofi/*.h
+ cd $(LIBXPDFDIR)/fofi; $(MAKE) $(common_makeargs) libfofi.a
+$(LIBXPDFDIR)/goo/libGoo.a: $(LIBXPDFSRCDIR)/goo/*.cc \
+ $(LIBXPDFSRCDIR)/goo/*.c $(LIBXPDFSRCDIR)/goo/*.h
+ cd $(LIBXPDFDIR)/goo; $(MAKE) $(common_makeargs) libGoo.a
+$(LIBXPDFDIR)/xpdf/libxpdf.a: $(LIBXPDFSRCDIR)/xpdf/*.cc \
+ $(LIBXPDFSRCDIR)/xpdf/*.h
+ cd $(LIBXPDFDIR)/xpdf; $(MAKE) $(common_makeargs) libxpdf.a
+
+
+# md5
+
+LIBMD5DIR=../../libs/md5
+LIBMD5SRCDIR=$(srcdir)/$(LIBMD5DIR)
+LIBMD5DEP=$(LIBMD5DIR)/md5.o
+
+$(LIBMD5DEP): $(LIBMD5SRCDIR)/md5.c $(LIBMD5SRCDIR)/md5.h
+clean:: md5lib-clean
+md5lib-clean:
+ rm -f $(LIBMD5DEP)
+
+# obsdcompat
+LIBOBSDDIR=../../libs/obsdcompat
+LIBOBSDSRCDIR=$(srcdir)/$(LIBOBSDCOMPATDIR)
+LIBOBSDDEP=@LIBOBSDDEP@
+LDLIBOBSD=@LDLIBOBSD@
+
+$(LIBOBSDDIR)/libopenbsd-compat.a: $(LIBOBSDSRCDIR)/*.c $(LIBOBSDSRCDIR)/*.h
+# common_makeargs = $(MFLAGS) CC='$(CC)' CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS)' $(XMAKEARGS)
+# CFLAGS setzt libopenbsd-compat selbst, nicht durchreichen!
+ cd $(LIBOBSDDIR); $(MAKE) $(MFLAGS) $(XMAKEARGS) libopenbsd-compat.a
+
+# libpdf itself
+pdflib = luatexdir/libpdf.a
+pdflib_sources = $(srcdir)/luatexdir/*.c $(srcdir)/luatexdir/*.cc \
+ $(srcdir)/luatexdir/*.h
+
+luatexdir/libpdf.a: $(pdflib_sources) luatexdir/luatexextra.h ctangle
+ cd luatexdir && mkdir -p font image lua lang tex && $(MAKE) $(common_makeargs) libpdf.a
+
+# makecpool:
+
+luatexdir/makecpool: luatexdir/makecpool.c
+ cd luatexdir && $(MAKE) $(common_makeargs) makecpool
+
+# lua
+
+LIBLUADIR=../../libs/lua51
+LIBLUASRCDIR=$(srcdir)/$(LIBLUADIR)
+LIBLUADEP=$(LIBLUADIR)/liblua.a
+
+luatarget=posix
+ifeq ($(target),i386-mingw32)
+ ifeq ($(host),i386-linux)
+ luatarget = mingwcross
+ else
+ luatarget = mingw
+ endif
+else
+ifeq ($(target),i386-linux)
+ luatarget = posix
+endif
+endif
+
+
+$(LIBLUADEP):
+ mkdir -p $(LIBLUADIR) && cd $(LIBLUADIR) && cp -f $(LIBLUASRCDIR)/* . && $(MAKE) $(luatarget)
+
+# slnunicode
+SLNUNICODEDIR=../../libs/slnunicode
+SLNUNICODESRCDIR=$(srcdir)/$(SLNUNICODEDIR)
+SLNUNICODEDEP=$(SLNUNICODEDIR)/slnunico.o
+$(SLNUNICODEDEP): $(SLNUNICODEDIR)/slnunico.c $(SLNUNICODEDIR)/slnudata.c
+ mkdir -p $(SLNUNICODEDIR) && cd $(SLNUNICODEDIR) && cp -f $(SLNUNICODESRCDIR)/* . && $(CC) $(CFLAGS) -I$(LIBLUADIR) -o slnunico.o -c slnunico.c
+
+# zziplib
+
+# zziplib is a configuration nightmare, because it is so stubborn
+# about using a pre-installed zlib. configure and make have to
+# be fooled in two different ways.
+# - configure needs to find
+# the subdirs 'include' and 'lib' in the --with-zlib prefix,
+# and these need to contain the proper headers and libraries.
+# - make needs to find the right headers using an -I via CPPFLAGS,
+# because the zlib path is relative and can't be found otherwise.
+#
+# final trickyness: configure writes a Makefile in the source
+# directory. it is needed by anything, so I delete it right away
+
+zzipretarget=
+
+ifeq ($(target),i386-mingw32)
+ zzipretarget=--target=$(target) --build=$(target) --host=$(host)
+endif
+
+
+ZZIPLIBDIR=../../libs/zziplib
+ZZIPLIBSRCDIR=$(srcdir)/$(ZZIPLIBDIR)
+ZZIPLIBDEP = $(ZZIPLIBDIR)/zzip/libzzip.a
+
+$(ZZIPLIBDEP): $(ZZIPLIBSRCDIR)
+ mkdir -p $(ZZIPLIBDIR)/zzip && cd $(ZZIPLIBDIR)/zzip && \
+ cp ../$(ZZIPLIBSRCDIR)/zzip/Makefile . && $(MAKE) $(common_makeargs)
+
+# luazip
+
+LUAZIPDIR=../../libs/luazip
+LUAZIPSRCDIR=$(srcdir)/$(LUAZIPDIR)
+LUAZIPDEP=$(LUAZIPDIR)/src/luazip.o
+LUAZIPINC=-I../../lua51 -I../$(ZZIPLIBSRCDIR) -I../$(ZZIPLIBDIR)
+
+$(LUAZIPDEP): $(LUAZIPDIR)/src/luazip.c
+ mkdir -p $(LUAZIPDIR) && cd $(LUAZIPDIR) && cp -R $(LUAZIPSRCDIR)/* . && \
+ cd src && $(CC) $(CFLAGS) $(LUAZIPINC) -g -o luazip.o -c luazip.c
+
+# luafilesystem
+
+LUAFSDIR=../../libs/luafilesystem
+LUAFSSRCDIR=$(srcdir)/$(LUAFSDIR)
+LUAFSDEP=$(LUAFSDIR)/src/lfs.o
+LUAFSINC=-I../../lua51
+
+$(LUAFSDEP): $(LUAFSDIR)/src/lfs.c $(LUAFSDIR)/src/lfs.h
+ mkdir -p $(LUAFSDIR) && cd $(LUAFSDIR) && cp -R $(LUAFSSRCDIR)/* . && \
+ cd src && $(CC) $(CFLAGS) $(LUAFSINC) -g -o lfs.o -c lfs.c
+
+# luapeg
+LUAPEGDIR=../../libs/luapeg
+LUAPEGSRCDIR=$(srcdir)/$(LUAPEGDIR)
+LUAPEGDEP=$(LUAPEGDIR)/lpeg.o
+$(LUAPEGDEP): $(LUAPEGDIR)/lpeg.c
+ mkdir -p $(LUAPEGDIR) && cd $(LUAPEGDIR) && cp -f $(LUAPEGSRCDIR)/* . && $(CC) $(CFLAGS) -I$(LIBLUADIR) -g -o lpeg.o -c lpeg.c
+
+
+# luamd5
+LUAMDVDIR=../../libs/luamd5
+LUAMDVSRCDIR=$(srcdir)/$(LUAMDVDIR)
+LUAMDVDEP=$(LUAMDVDIR)/md5lib.o $(LUAMDVDIR)/md5.o
+$(LUAMDVDEP): $(LUAMDVDIR)/md5lib.c $(LUAMDVDIR)/md5.h $(LUAMDVDIR)/md5.c
+ mkdir -p $(LUAMDVDIR) && cd $(LUAMDVDIR) && cp -f $(LUAMDVSRCDIR)/* . && $(CC) $(CFLAGS) -I$(LIBLUADIR) -g -o md5.o -c md5.c && $(CC) $(CFLAGS) -I$(LIBLUADIR) -g -o md5lib.o -c md5lib.c
+
+.PHONY: always
+
+# luaff
+LUAFFDIR=../../libs/luafontforge
+LUAFFSRCDIR=$(srcdir)/$(LUAFFDIR)
+LUAFFDEP=$(LUAFFDIR)/libff.a
+$(LUAFFDEP): always
+ mkdir -p $(LUAFFDIR) && cp -f $(LUAFFSRCDIR)/Makefile $(LUAFFDIR)
+ mkdir -p $(LUAFFDIR)/fontforge && cp -f $(LUAFFSRCDIR)/fontforge/fontforge/Makefile $(LUAFFDIR)/fontforge
+ mkdir -p $(LUAFFDIR)/Unicode && cp -f $(LUAFFSRCDIR)/fontforge/Unicode/Makefile $(LUAFFDIR)/Unicode
+ cd $(LUAFFDIR) && $(MAKE)
+
+
+# luazlib
+LUAZLIBDIR=../../libs/luazlib
+LUAZLIBSRCDIR=$(srcdir)/$(LUAZLIBDIR)
+LUAZLIBDEP=$(LUAZLIBDIR)/lgzip.o $(LUAZLIBDIR)/lzlib.o
+LUAZLIBINC=-I$(ZLIBSRCDIR) -I$(LIBLUASRCDIR)
+$(LUAZLIBDEP): $(LUAZLIBDIR)/lgzip.c $(LUAZLIBDIR)/lzlib.c
+ mkdir -p $(LUAZLIBDIR) && cd $(LUAZLIBDIR) && cp -f $(LUAZLIBSRCDIR)/* . && $(CC) $(CFLAGS) $(LUAZLIBINC) -g -o lgzip.o -c lgzip.c && $(CC) $(CFLAGS) $(LUAZLIBINC) -g -o lzlib.o -c lzlib.c
+
+
+# Convenience variables.
+
+luatexlibs = $(pdflib) $(LDLIBPNG) $(LDZLIB) $(LDLIBXPDF) $(LIBMD5DEP) $(LDLIBOBSD) \
+ $(LIBLUADEP) $(SLNUNICODEDEP) $(LUAZIPDEP) $(ZZIPLIBDEP) $(LUAFSDEP) \
+ $(LUAPEGDEP) $(LUAMDVDEP) $(LUAZLIBDEP) $(LUAFFDEP)
+
+luatexlibsdep = $(pdflib) $(LIBPNGDEP) $(ZLIBDEP) $(LIBXPDFDEP) $(LIBMD5DEP) $(LIBOBSDDEP) \
+ $(LIBLUADEP) $(SLNUNICODEDEP) $(ZZIPLIBDEP) $(LUAZIPDEP) $(LUAFSDEP) \
+ $(LUAPEGDEP) $(LUAMDVDEP) $(LUAZLIBDEP) $(LUAFFDEP) $(makecpool)
+
+## end of luatexlib.mk - Makefile fragment for libraries used by pdf[ex]tex.
+
diff --git a/Build/source/texk/web2c/luatexdir/macnames.c b/Build/source/texk/web2c/luatexdir/macnames.c
new file mode 100644
index 00000000000..832e05e052d
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/macnames.c
@@ -0,0 +1,312 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id$
+*/
+
+const char notdef[] = ".notdef";
+
+const char *mac_glyph_names[] = {
+/* 0x00 */
+ notdef,
+ ".null",
+ "CR",
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quotesingle",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+/* 0x10 */
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+/* 0x20 */
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+/* 0x30 */
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+/* 0x40 */
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "grave",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+/* 0x50 */
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+/* 0x60 */
+ "braceright",
+ "asciitilde",
+ "Adieresis",
+ "Aring",
+ "Ccedilla",
+ "Eacute",
+ "Ntilde",
+ "Odieresis",
+ "Udieresis",
+ "aacute",
+ "agrave",
+ "acircumflex",
+ "adieresis",
+ "atilde",
+ "aring",
+ "ccedilla",
+/* 0x70 */
+ "eacute",
+ "egrave",
+ "ecircumflex",
+ "edieresis",
+ "iacute",
+ "igrave",
+ "icircumflex",
+ "idieresis",
+ "ntilde",
+ "oacute",
+ "ograve",
+ "ocircumflex",
+ "odieresis",
+ "otilde",
+ "uacute",
+ "ugrave",
+/* 0x80 */
+ "ucircumflex",
+ "udieresis",
+ "dagger",
+ "degree",
+ "cent",
+ "sterling",
+ "section",
+ "bullet",
+ "paragraph",
+ "germandbls",
+ "registered",
+ "copyright",
+ "trademark",
+ "acute",
+ "dieresis",
+ "notequal",
+/* 0x90 */
+ "AE",
+ "Oslash",
+ "infinity",
+ "plusminus",
+ "lessequal",
+ "greaterequal",
+ "yen",
+ "mu",
+ "partialdiff",
+ "Sigma",
+ "Pi",
+ "pi",
+ "integral",
+ "ordfeminine",
+ "ordmasculine",
+ "Omega",
+/* 0xa0 */
+ "ae",
+ "oslash",
+ "questiondown",
+ "exclamdown",
+ "logicalnot",
+ "radical",
+ "florin",
+ "approxequal",
+ "Delta",
+ "guillemotleft",
+ "guillemotright",
+ "ellipsis",
+ "nbspace",
+ "Agrave",
+ "Atilde",
+ "Otilde",
+/* 0xb0 */
+ "OE",
+ "oe",
+ "endash",
+ "emdash",
+ "quotedblleft",
+ "quotedblright",
+ "quoteleft",
+ "quoteright",
+ "divide",
+ "lozenge",
+ "ydieresis",
+ "Ydieresis",
+ "fraction",
+ "currency",
+ "guilsinglleft",
+ "guilsinglright",
+/* 0xc0 */
+ "fi",
+ "fl",
+ "daggerdbl",
+ "periodcentered",
+ "quotesinglbase",
+ "quotedblbase",
+ "perthousand",
+ "Acircumflex",
+ "Ecircumflex",
+ "Aacute",
+ "Edieresis",
+ "Egrave",
+ "Iacute",
+ "Icircumflex",
+ "Idieresis",
+ "Igrave",
+/* 0xd0 */
+ "Oacute",
+ "Ocircumflex",
+ "applelogo",
+ "Ograve",
+ "Uacute",
+ "Ucircumflex",
+ "Ugrave",
+ "dotlessi",
+ "circumflex",
+ "tilde",
+ "macron",
+ "breve",
+ "dotaccent",
+ "ring",
+ "cedilla",
+ "hungarumlaut",
+/* 0xe0 */
+ "ogonek",
+ "caron",
+ "Lslash",
+ "lslash",
+ "Scaron",
+ "scaron",
+ "Zcaron",
+ "zcaron",
+ "brokenbar",
+ "Eth",
+ "eth",
+ "Yacute",
+ "yacute",
+ "Thorn",
+ "thorn",
+ "minus",
+/* 0xf0 */
+ "multiply",
+ "onesuperior",
+ "twosuperior",
+ "threesuperior",
+ "onehalf",
+ "onequarter",
+ "threequarters",
+ "franc",
+ "Gbreve",
+ "gbreve",
+ "Idot",
+ "Scedilla",
+ "scedilla",
+ "Cacute",
+ "cacute",
+ "Ccaron",
+/* 0x100 */
+ "ccaron",
+ "dmacron"
+};
+
+const char *ambiguous_names[] = {
+ "Delta", /* increment */
+ "Omega", /* Ohm */
+ "Pi", /* product */
+ "Sigma", /* summation */
+ "dmacron", /* dslash */
+ "macron", /* overscore */
+ "periodcentered", /* middot */
+ NULL
+};
diff --git a/Build/source/texk/web2c/luatexdir/makecpool.c b/Build/source/texk/web2c/luatexdir/makecpool.c
new file mode 100644
index 00000000000..162a4848482
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/makecpool.c
@@ -0,0 +1,60 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[]) {
+ if (argc!=3) {
+ puts("Need exactly two arguments: pool_name and header_name");
+ exit(1);
+ }
+ char *filename = argv[1];
+ char *headername = argv[2];
+ FILE *fh = fopen(filename,"r");
+ char data[1024];
+ printf(
+ "/* This file is auto-generated by makecpool */\n"
+ "\n"
+ "#include <stdio.h>\n"
+ "#include \"%s\"\n"
+ "\n"
+ "static char *poolfilearr[] = {\n",headername);
+ while (fgets(data,1024,fh)) {
+ int len = strlen(data);
+ int o = 0; /* skip first o characters*/
+ int i;
+ if (data[len-1]=='\n') { /* chomp;*/
+ data[len-1] = 0;
+ len--;
+ }
+ if (data[0]=='*') break; /* last if !^\*!; */
+ if (data[0]>='0' && data[0]<='9' && data[1]>='0' && data[1]<='9') {
+ o=2; /* $data =~ s/^\d\d//; */
+ }
+ printf(" \"");
+ for (i=o; i<len; i++) {
+ if (data[i]=='"' || data[i]=='\\') putchar('\\');
+ if (data[i]=='?') printf("\" \""); /* suppress trigraphs */
+ putchar(data[i]);
+ } /* $data =~ s/(["\\])/\\$1/g; */
+ printf("\",\n");
+ }
+ fclose(fh);
+ printf(" NULL };\n"
+ "int loadpoolstrings (integer spare_size) {\n"
+ " strnumber g=0;\n"
+ " int i=0,j=0;\n"
+ " char *s;\n"
+ " while ((s = poolfilearr[j++])) {\n"
+ " int l = strlen (s);\n"
+ " i += l;\n"
+ " if (i>=spare_size) return 0;\n"
+ /*" while (l-- > 0) strpool[poolptr++] = *s++;\n"*/
+ " while (l-- > 0) str_pool[pool_ptr++] = *s++;\n"
+ /* " g = makestring();\n"*/
+ " g = make_string();\n"
+ /* " strref[g]= 127;\n"*/
+ " }\n"
+ " return g;\n"
+ "}\n");
+ return 0;
+}
diff --git a/Build/source/texk/web2c/luatexdir/managed-sa.c b/Build/source/texk/web2c/luatexdir/managed-sa.c
new file mode 100644
index 00000000000..cc63d7e75f5
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/managed-sa.c
@@ -0,0 +1,245 @@
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+#include "managed-sa.h"
+
+
+static void
+store_sa_stack (sa_tree a, integer n, integer v, integer gl) {
+ sa_stack_item st;
+ st.code = n;
+ st.value = v;
+ st.level = gl;
+ if (a->stack == NULL) {
+ a->stack = Mxmalloc_array(sa_stack_item,a->stack_size);
+ } else if (((a->stack_ptr)+1)>=a->stack_size) {
+ a->stack_size += a->stack_step;
+ a->stack = Mxrealloc_array(a->stack,sa_stack_item,a->stack_size);
+ }
+ (a->stack_ptr)++;
+ a->stack[a->stack_ptr] = st;
+}
+
+static void
+skip_in_stack (sa_tree a, integer n) {
+ int p = a->stack_ptr;
+ if (a->stack == NULL)
+ return;
+ while (p>0) {
+ if (a->stack[p].code == n && a->stack[p].level > 0) {
+ a->stack[p].level = -(a->stack[p].level);
+ }
+ p--;
+ }
+}
+
+sa_tree_item
+get_sa_item (const sa_tree head, const integer n) {
+ register int h;
+ register int m;
+ if (head->tree != NULL) {
+ h = HIGHPART_PART(n);
+ if (head->tree[h] != NULL) {
+ m = MIDPART_PART(n);
+ if (head->tree[h][m] != NULL) {
+ return head->tree[h][m][LOWPART_PART(n)];
+ }
+ }
+ }
+ return head->dflt;
+}
+
+void
+set_sa_item (sa_tree head, integer n, sa_tree_item v, integer gl) {
+ int h,m,l;
+ int i;
+ h = HIGHPART_PART(n);
+ m = MIDPART_PART(n);
+ l = LOWPART_PART(n);
+ if (head->tree == NULL) {
+ head->tree = (sa_tree_item ***) Mxmalloc_array(sa_tree_item **,HIGHPART);
+ for (i=0; i<HIGHPART; i++) { head->tree[i] = NULL; }
+ }
+ if (head->tree[h] == NULL) {
+ head->tree[h] = (sa_tree_item **) Mxmalloc_array(sa_tree_item *,MIDPART);
+ for (i=0; i<MIDPART; i++) { head->tree[h][i] = NULL; }
+ }
+ if (head->tree[h][m] == NULL) {
+ head->tree[h][m] = (sa_tree_item *) Mxmalloc_array(sa_tree_item,LOWPART);
+ for (i=0; i<LOWPART; i++) { head->tree[h][m][i] = head->dflt; }
+ }
+ if (gl<=1) {
+ skip_in_stack(head,n);
+ } else {
+ store_sa_stack(head,n,head->tree[h][m][l],gl);
+ }
+ head->tree[h][m][l] = v;
+}
+
+static void
+rawset_sa_item (sa_tree head, integer n, integer v) {
+ head->tree[HIGHPART_PART(n)][MIDPART_PART(n)][LOWPART_PART(n)] = v;
+}
+
+void
+clear_sa_stack (sa_tree a) {
+ if (a->stack != NULL) {
+ Mxfree(a->stack);
+ }
+ a->stack = NULL;
+ a->stack_ptr = 0;
+ a->stack_size = a->stack_step;
+}
+
+void
+destroy_sa_tree (sa_tree a) {
+ int h,m;
+ if (a == NULL)
+ return;
+ if (a->tree != NULL) {
+ for (h=0; h<HIGHPART;h++ ) {
+ if (a->tree[h] != NULL) {
+ for (m=0; m<MIDPART; m++ ) {
+ if (a->tree[h][m] != NULL) {
+ Mxfree(a->tree[h][m]);
+ }
+ }
+ Mxfree(a->tree[h]);
+ }
+ }
+ Mxfree(a->tree);
+ }
+ if (a->stack != NULL) {
+ Mxfree(a->stack);
+ }
+ Mxfree(a);
+}
+
+
+sa_tree
+copy_sa_tree(sa_tree b) {
+ int h,m,l;
+ sa_tree a = (sa_tree)Mxmalloc_array(sa_tree_head,1);
+ a->stack_step = b->stack_step;
+ a->stack_size = b->stack_size;
+ a->dflt = b->dflt;
+ a->stack = NULL;
+ a->stack_ptr = 0;
+ a->tree = NULL;
+ if (b->tree !=NULL) {
+ a->tree = (sa_tree_item ***)Mxmalloc_array(void *,HIGHPART);
+ for (h=0; h<HIGHPART;h++ ) {
+ if (b->tree[h] != NULL) {
+ a->tree[h]=(sa_tree_item **)Mxmalloc_array(void *,MIDPART);
+ for (m=0; m<MIDPART; m++ ) {
+ if (b->tree[h][m]!=NULL) {
+ a->tree[h][m]=Mxmalloc_array(sa_tree_item,LOWPART);
+ for (l=0; l<LOWPART; l++) {
+ a->tree[h][m][l] = b->tree[h][m][l] ;
+ }
+ } else {
+ a->tree[h][m] = NULL;
+ }
+ }
+ } else {
+ a->tree[h]= NULL;
+ }
+ }
+ }
+ return a;
+}
+
+
+sa_tree
+new_sa_tree (integer size, sa_tree_item dflt) {
+ sa_tree_head *a;
+ a = (sa_tree_head *)xmalloc(sizeof(sa_tree_head));
+ a->dflt = dflt;
+ a->stack = NULL;
+ a->tree = NULL;
+ a->stack_size = size;
+ a->stack_step = size;
+ a->stack_ptr = 0;
+ return (sa_tree)a;
+}
+
+void
+restore_sa_stack (sa_tree head, integer gl) {
+ sa_stack_item st;
+ if (head->stack == NULL)
+ return;
+ while (head->stack_ptr>0 && abs(head->stack[head->stack_ptr].level)>=gl) {
+ st = head->stack[head->stack_ptr];
+ if (st.level>0) {
+ rawset_sa_item (head, st.code, st.value);
+ }
+ (head->stack_ptr)--;
+ }
+}
+
+
+void
+dump_sa_tree (sa_tree a) {
+ boolean f;
+ unsigned int x;
+ int h,m,l;
+ if (a == NULL)
+ return;
+ dump_int(a->stack_step);
+ dump_int(a->dflt);
+ if (a->tree != NULL) {
+ for (h=0; h<HIGHPART;h++ ) {
+ if (a->tree[h] != NULL) {
+ f = 1; dump_qqqq(f);
+ for (m=0; m<MIDPART; m++ ) {
+ if (a->tree[h][m] != NULL) {
+ f = 1; dump_qqqq(f);
+ for (l=0;l<LOWPART;l++) {
+ x = a->tree[h][m][l]; dump_int(x);
+ }
+ } else {
+ f = 0; dump_qqqq(f);
+ }
+ }
+ } else {
+ f = 0; dump_qqqq(f);
+ }
+ }
+ }
+}
+
+
+sa_tree
+undump_sa_tree(void) {
+ unsigned int x;
+ int h,m,l;
+ boolean f;
+ sa_tree a = (sa_tree)Mxmalloc_array(sa_tree_head,1);
+ undump_int(x) ; a->stack_step = x; a->stack_size = x;
+ undump_int(x) ; a->dflt = x;
+ a->stack = Mxmalloc_array(sa_stack_item,a->stack_size);
+ a->stack_ptr = 0;
+ a->tree = (sa_tree_item ***)Mxmalloc_array(void *,HIGHPART);
+ for (h=0; h<HIGHPART;h++ ) {
+ undump_qqqq(f);
+ if (f>0) {
+ a->tree[h]=(sa_tree_item **)Mxmalloc_array(void *,MIDPART);
+ for (m=0; m<MIDPART; m++ ) {
+ undump_qqqq(f);
+ if (f>0) {
+ a->tree[h][m]=Mxmalloc_array(sa_tree_item,LOWPART);
+ for (l=0; l<LOWPART; l++) {
+ undump_int(x); a->tree[h][m][l] = x;
+ }
+ } else {
+ a->tree[h][m] = NULL;
+ }
+ }
+ } else {
+ a->tree[h]= NULL;
+ }
+ }
+ return a;
+}
+
+
diff --git a/Build/source/texk/web2c/luatexdir/managed-sa.h b/Build/source/texk/web2c/luatexdir/managed-sa.h
new file mode 100644
index 00000000000..b73aece81b1
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/managed-sa.h
@@ -0,0 +1,74 @@
+/*
+ Copyright (c) 2007 Taco Hoekwater <taco@luatex.org>
+
+ This file is part of LuaTeX.
+
+ LuaTeX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ LuaTeX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with LuaTeX; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ $Id$ */
+
+#ifndef MANAGED_SA_H
+#define MANAGED_SA_H 1
+
+/* the next two sets of three had better match up exactly, but using bare numbers
+ is easier on the C compiler */
+
+#define HIGHPART 128
+#define MIDPART 128
+#define LOWPART 128
+
+#define HIGHPART_PART(a) ((a>>14)&127)
+#define MIDPART_PART(a) ((a>>7)&127)
+#define LOWPART_PART(a) (a&127)
+
+#define Mxmalloc_array(a,b) xmalloc(b*sizeof(a))
+#define Mxrealloc_array(a,b,c) xrealloc(a,c*sizeof(b))
+#define Mxfree(a) free(a); a=NULL
+
+typedef unsigned int sa_tree_item;
+
+typedef struct {
+ int code;
+ int level;
+ sa_tree_item value;
+} sa_stack_item;
+
+
+typedef struct {
+ int stack_size; /* initial stack size */
+ int stack_step; /* increment stack step */
+ int stack_ptr; /* current stack point */
+ int dflt; /* default item value */
+ sa_tree_item *** tree; /* item tree head */
+ sa_stack_item * stack; /* stack tree head */
+} sa_tree_head;
+
+typedef sa_tree_head *sa_tree;
+
+extern sa_tree_item get_sa_item (const sa_tree head, const integer n) ;
+extern void set_sa_item (sa_tree head, integer n, sa_tree_item v, integer gl) ;
+
+extern sa_tree new_sa_tree (integer size, sa_tree_item dflt);
+
+extern sa_tree copy_sa_tree (sa_tree head);
+extern void destroy_sa_tree (sa_tree head);
+
+extern void dump_sa_tree (sa_tree a);
+extern sa_tree undump_sa_tree (void) ;
+
+extern void restore_sa_stack (sa_tree a, integer gl);
+extern void clear_sa_stack (sa_tree a);
+
+#endif
diff --git a/Build/source/texk/web2c/luatexdir/mathcodes.c b/Build/source/texk/web2c/luatexdir/mathcodes.c
new file mode 100644
index 00000000000..77e15e7c66c
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/mathcodes.c
@@ -0,0 +1,191 @@
+
+/*
+Copyright (c) 2006 Taco Hoekwater, <taco@elvenkind.com>
+
+This file is part of LuaTeX.
+
+LuaTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+LuaTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with LuaTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id $
+*/
+
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+#include "managed-sa.h"
+
+/* the 0xFFFFFFFF is a flag value */
+
+#define MATHCODESTACK 8
+#define MATHCODEDEFAULT 0xFFFFFFFF
+
+static sa_tree mathcode_head = NULL;
+
+typedef struct delcodeval {
+ integer valuea;
+ integer valueb;
+} delcodeval;
+
+/* delcodes are a bit more work */
+
+#define DELCODESTACK 4
+#define DELCODEDEFAULT 0xFFFFFFFF
+
+static sa_tree delcode_head = NULL;
+
+#define DELCODEHEAP 8
+
+static delcodeval * delcode_heap = NULL;
+static int delcode_heapsize = DELCODEHEAP;
+static int delcode_heapptr = 0;
+
+void
+unsavemathcode (quarterword gl) {
+ restore_sa_stack(mathcode_head,gl);
+}
+
+void
+set_math_code (integer n, halfword v, quarterword gl) {
+ set_sa_item(mathcode_head,n,v,gl);
+}
+
+halfword
+get_math_code (integer n) {
+ unsigned int ret;
+ ret = get_sa_item(mathcode_head,n);
+ if (ret==MATHCODEDEFAULT) {
+ return (halfword)n;
+ } else {
+ return (halfword)ret;
+ }
+}
+
+void
+initializemathcode (void) {
+ mathcode_head = new_sa_tree(MATHCODESTACK,MATHCODEDEFAULT);
+}
+
+void
+dumpmathcode (void) {
+ dump_sa_tree(mathcode_head);
+}
+
+void
+undumpmathcode (void) {
+ mathcode_head = undump_sa_tree();
+}
+
+/* TODO: clean up the heap */
+
+void
+unsavedelcode (quarterword gl) {
+ restore_sa_stack(delcode_head,gl);
+}
+
+void
+set_del_code (integer n, halfword v, halfword w, quarterword gl) {
+ delcodeval d;
+ d.valuea = v; d.valueb = w;
+ if (delcode_heapptr==delcode_heapsize) {
+ delcode_heapsize += DELCODEHEAP;
+ delcode_heap = Mxrealloc_array(delcode_heap,delcodeval,delcode_heapsize);
+ }
+ delcode_heap[delcode_heapptr] = d;
+ set_sa_item(delcode_head,n,delcode_heapptr,gl);
+ delcode_heapptr++;
+}
+
+halfword
+get_del_code_a (integer n) {
+ int ret;
+ ret = get_sa_item(delcode_head,n);
+ if (ret==DELCODEDEFAULT) {
+ return (halfword)-1;
+ } else {
+ return (halfword)delcode_heap[ret].valuea;
+ }
+}
+
+halfword
+get_del_code_b (integer n) {
+ unsigned int ret;
+ ret = get_sa_item(delcode_head,n);
+ if (ret==DELCODEDEFAULT) {
+ return (halfword)-1;
+ } else {
+ return (halfword)delcode_heap[ret].valueb;
+ }
+}
+
+void
+initializedelcode (void) {
+ delcode_head = new_sa_tree(DELCODESTACK,DELCODEDEFAULT);
+ delcode_heap = Mxmalloc_array(delcodeval,DELCODEHEAP);
+}
+
+void
+dumpdelcode (void) {
+ int k;
+ delcodeval d;
+ dump_sa_tree(delcode_head);
+ dump_int(delcode_heapsize);
+ dump_int(delcode_heapptr);
+ for (k=0;k<delcode_heapptr;k++) {
+ d = delcode_heap[k];
+ dump_int(d.valuea);
+ dump_int(d.valueb);
+ }
+}
+
+void
+undumpdelcode (void) {
+ int k;
+ delcodeval d;
+ delcode_head = undump_sa_tree();
+ undump_int(delcode_heapsize);
+ undump_int(delcode_heapptr);
+ delcode_heap = Mxmalloc_array(delcodeval,delcode_heapsize);
+ for (k=0;k<delcode_heapptr;k++) {
+ undump_int(d.valuea);
+ undump_int(d.valueb);
+ delcode_heap[k] = d;
+ }
+ d.valuea=0; d.valueb=0;
+ for (k=delcode_heapptr;k<delcode_heapsize;k++) {
+ delcode_heap[k] = d;
+ }
+}
+
+void
+unsave_math_codes (quarterword grouplevel) {
+ unsavemathcode(grouplevel);
+ unsavedelcode(grouplevel);
+}
+
+void initialize_math_codes (void) {
+ initializemathcode();
+ initializedelcode();
+}
+
+void dump_math_codes(void) {
+ dumpmathcode();
+ dumpdelcode();
+}
+
+void undump_math_codes(void) {
+ undumpmathcode();
+ undumpdelcode();
+}
diff --git a/Build/source/texk/web2c/luatexdir/nodes.h b/Build/source/texk/web2c/luatexdir/nodes.h
new file mode 100644
index 00000000000..ba2c09ecc78
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/nodes.h
@@ -0,0 +1,648 @@
+
+#include <stdarg.h>
+
+#ifndef __NODES_H__
+#define __NODES_H__
+
+/* these don't really belong here */
+
+#define token_ref_count(a) info((a)) /* reference count preceding a token list */
+#define add_token_ref(a) token_ref_count(a)++ /* new reference to a token list */
+
+
+/* these are in texlang.c */
+
+#define set_vlink(a,b) vlink(a)=b
+#define get_vlink(a) vlink(a)
+#define get_character(a) character(a)
+
+extern halfword insert_discretionary ( halfword t, halfword pre, halfword post, halfword replace);
+extern halfword insert_syllable_discretionary ( halfword t, lang_variables *lan);
+extern halfword insert_word_discretionary ( halfword t, lang_variables *lan);
+extern halfword insert_complex_discretionary ( halfword t, lang_variables *lan,
+ halfword pre, halfword post, halfword replace);
+extern halfword insert_character ( halfword t, int n);
+extern void set_disc_field (halfword f, halfword t);
+
+
+#define max_halfword 0x3FFFFFFF
+#ifndef null
+#define null 0
+#endif
+#define null_flag -0x40000000
+#define zero_glue 0
+#define normal 0
+
+#define vinfo(a) varmem[(a)].hh.v.LH
+#define vlink(a) varmem[(a)].hh.v.RH
+#define type(a) varmem[(a)].hh.u.B0
+#define subtype(a) varmem[(a)].hh.u.B1
+#define node_attr(a) vinfo((a)+1)
+#define alink(a) vlink((a)+1)
+
+#define node_size(a) varmem[(a)].hh.v.LH
+
+#define rlink(a) vlink((a)+1) /* aka alink() */
+#define llink(a) vinfo((a)+1) /* overlaps with node_attr() */
+
+#define add_glue_ref(a) glue_ref_count(a)++ /* new reference to a glue spec */
+
+/* really special head node pointers that only need links */
+
+#define temp_node_size 2
+
+/* attribute lists */
+
+/* it is convenient to have attribute list nodes and attribute node
+ * be the same size
+ */
+
+#define attribute_node_size 2
+
+#define attr_list_ref(a) vinfo((a)+1) /* the reference count */
+#define attribute_id(a) vinfo((a)+1)
+#define attribute_value(a) vlink((a)+1)
+
+#define cache_disabled max_halfword
+#define add_node_attr_ref(a) { if (a!=null) attr_list_ref((a))++; }
+
+#define replace_attribute_list(a,b) do { \
+ delete_attribute_ref(node_attr(a)); \
+ node_attr(a)=b; \
+ } while (0)
+
+extern void update_attribute_cache (void) ;
+extern halfword copy_attribute_list(halfword n) ;
+extern halfword do_set_attribute(halfword p, int i, int val);
+
+
+/* a glue spec */
+#define glue_spec_size 4
+#define stretch(a) vlink((a)+1)
+/* width == a+2 */
+#define shrink(a) vinfo((a)+1)
+#define stretch_order(a) type((a)+3)
+#define shrink_order(a) subtype((a)+3)
+#define glue_ref_count(a) vlink((a)+3)
+
+/* pdf action spec */
+
+#define pdf_action_size 4
+
+typedef enum {
+ pdf_action_page = 0,
+ pdf_action_goto,
+ pdf_action_thread,
+ pdf_action_user } pdf_action_types;
+
+#define pdf_action_type(a) type((a) + 1)
+#define pdf_action_named_id(a) subtype((a) + 1)
+#define pdf_action_id(a) vlink((a) + 1)
+#define pdf_action_file(a) vinfo((a) + 2)
+#define pdf_action_new_window(a) vlink((a) + 2)
+#define pdf_action_tokens(a) vinfo((a) + 3)
+#define pdf_action_refcount(a) vlink((a) + 3)
+
+/*increase count of references to this action*/
+#define add_action_ref(a) pdf_action_refcount((a))++
+
+/* decrease count of references to this
+ action; free it if there is no reference to this action*/
+
+#define delete_action_ref(a) { \
+ if (pdf_action_refcount(a) == null) { \
+ if (pdf_action_type(a) == pdf_action_user) { \
+ delete_token_ref(pdf_action_tokens(a)); \
+ } else { \
+ if (pdf_action_file(a) != null) \
+ delete_token_ref(pdf_action_file(a)); \
+ if (pdf_action_type(a) == pdf_action_page) \
+ delete_token_ref(pdf_action_tokens(a)); \
+ else if (pdf_action_named_id(a) > 0) \
+ delete_token_ref(pdf_action_id(a)); \
+ } \
+ free_node(a, pdf_action_size); \
+ } else { \
+ decr(pdf_action_refcount(a)); \
+ } \
+ }
+
+
+
+/* normal nodes */
+
+#define inf_bad 10000 /* infinitely bad value */
+#define inf_penalty inf_bad /*``infinite'' penalty value*/
+#define eject_penalty -(inf_penalty) /*``negatively infinite'' penalty value */
+
+#define penalty_node_size 3
+#define penalty(a) vlink((a)+2)
+
+#define glue_node_size 3
+#define glue_ptr(a) vinfo((a)+2)
+#define leader_ptr(a) vlink((a)+2)
+
+/* disc nodes could eventually be smaller, because the indirect
+ pointers are not really needed (8 instead of 10).
+ */
+
+#define disc_node_size 10
+
+typedef enum {
+ discretionary_disc=0,
+ explicit_disc,
+ automatic_disc,
+ syllable_disc } discretionary_types;
+
+#define pre_break_head(a) ((a)+4)
+#define post_break_head(a) ((a)+6)
+#define no_break_head(a) ((a)+8)
+
+#define pre_break(a) vinfo((a)+2)
+#define post_break(a) vlink((a)+2)
+#define no_break(a) vlink((a)+3)
+#define tlink llink
+
+#define vlink_pre_break(a) vlink(pre_break_head(a))
+#define vlink_post_break(a) vlink(post_break_head(a))
+#define vlink_no_break(a) vlink(no_break_head(a))
+
+#define tlink_pre_break(a) tlink(pre_break_head(a))
+#define tlink_post_break(a) tlink(post_break_head(a))
+#define tlink_no_break(a) tlink(no_break_head(a))
+
+#define kern_node_size 3
+#define explicit 1 /*|subtype| of kern nodes from \.{\\kern} and \.{\\/}*/
+#define acc_kern 2 /*|subtype| of kern nodes from accents */
+
+#define box_node_size 8
+#define width(a) varmem[(a+2)].cint
+#define depth(a) varmem[(a+3)].cint
+#define height(a) varmem[(a+4)].cint
+#define shift_amount(a) vlink((a)+5)
+#define box_dir(a) vinfo((a)+5)
+#define list_ptr(a) vlink((a)+6)
+#define glue_order(a) subtype((a)+6)
+#define glue_sign(a) type((a)+6)
+#define glue_set(a) varmem[(a+7)].gr
+
+/* unset nodes */
+#define glue_stretch(a) varmem[(a)+7].cint
+#define glue_shrink shift_amount
+#define span_count subtype
+
+#define rule_node_size 6
+#define rule_dir(a) vlink((a)+5)
+
+#define mark_node_size 3
+#define mark_ptr(a) vlink((a)+2)
+#define mark_class(a) vinfo((a)+2)
+
+#define adjust_node_size 3
+#define adjust_ptr(a) vlink(a+2)
+
+#define glyph_node_size 5
+
+#define character(a) vinfo((a)+2)
+#define font(a) vlink((a)+2)
+#define lang_data(a) vinfo((a)+3)
+#define lig_ptr(a) vlink((a)+3)
+#define x_displace(a) vinfo((a)+4)
+#define y_displace(a) vlink((a)+4)
+#define is_char_node(a) (a!=null && type(a)==glyph_node)
+
+#define char_lang(a) ((const int)(((unsigned)lang_data(a) & 0x7FFF0000)>>16))
+#define char_lhmin(a) ((const int)(((unsigned)lang_data(a) & 0x0000FF00)>>8))
+#define char_rhmin(a) ((const int)(((unsigned)lang_data(a) & 0x000000FF)))
+#define char_uchyph(a) ((const int)(((unsigned)lang_data(a) & 0x80000000)>>31))
+
+#define make_lang_data(a,b,c,d) (a>0 ? (1<<31): 0)+ \
+ (b<<16)+ (((c>0 && c<256) ? c : 1)<<8)+(((d>0 && d<256) ? d : 1))
+
+#define init_lang_data(a) lang_data(a)=256+1
+
+#define set_char_lang(a,b) lang_data(a)=make_lang_data(char_uchyph(a),b,char_lhmin(a),char_rhmin(a))
+#define set_char_lhmin(a,b) lang_data(a)=make_lang_data(char_uchyph(a),char_lang(a),b,char_rhmin(a))
+#define set_char_rhmin(a,b) lang_data(a)=make_lang_data(char_uchyph(a),char_lang(a),char_lhmin(a),b)
+#define set_char_uchyph(a,b) lang_data(a)=make_lang_data(b,char_lang(a),char_lhmin(a),char_rhmin(a))
+
+#define margin_kern_node_size 4
+#define margin_char(a) vlink((a)+3)
+
+/*@# {|subtype| of marginal kerns}*/
+#define left_side 0
+#define right_side 1
+
+#define math_node_size 3
+#define surround(a) vlink((a)+2)
+#define before 0 /*|subtype| for math node that introduces a formula*/
+#define after 1 /*|subtype| for math node that winds up a formula*/
+
+
+
+#define ins_node_size 6
+#define float_cost(a) varmem[(a)+2].cint
+#define ins_ptr(a) vinfo((a)+5)
+#define split_top_ptr(a) vlink((a)+5)
+
+
+#define page_ins_node_size 5
+
+#define broken_ptr(a) vlink((a)+2) /* an insertion for this class will break here if anywhere */
+#define broken_ins(a) vinfo((a)+2) /* this insertion might break at |broken_ptr| */
+#define last_ins_ptr(a) vlink((a)+3) /*the most recent insertion for this |subtype|*/
+#define best_ins_ptr(a) vinfo((a)+3) /*the optimum most recent insertion*/
+/* height = 4 */
+
+typedef enum {
+ hlist_node = 0,
+ vlist_node = 1,
+ rule_node,
+ ins_node,
+ mark_node,
+ adjust_node,
+ /* 6 used to be ligatures */
+ disc_node=7,
+ whatsit_node,
+ math_node,
+ glue_node,
+ kern_node,
+ penalty_node,
+ unset_node, /* 13 */
+ style_node,
+ choice_node,
+ ord_noad,
+ op_noad,
+ bin_noad,
+ rel_noad,
+ open_noad,
+ close_noad,
+ punct_noad,
+ inner_noad,
+ radical_noad,
+ fraction_noad,
+ under_noad,
+ over_noad,
+ accent_noad,
+ vcenter_noad,
+ left_noad,
+ right_noad,
+ margin_kern_node = 32,
+ glyph_node = 33,
+ align_record_node = 34,
+ pseudo_file_node = 35,
+ pseudo_line_node = 36,
+ inserting_node = 37,
+ split_up_node = 38,
+ expr_node = 39,
+ nesting_node = 40,
+ span_node = 41,
+ attribute_node = 42,
+ glue_spec_node = 43,
+ attribute_list_node = 44,
+ action_node = 45,
+ temp_node = 46,
+ align_stack_node = 47,
+ movement_node = 48,
+ if_node = 49,
+ unhyphenated_node = 50,
+ hyphenated_node = 51,
+ delta_node = 52,
+ passive_node = 53,
+ shape_node = 54 } node_types ;
+
+#define last_known_node temp_node /* used by \lastnodetype */
+
+#define movement_node_size 3
+#define expr_node_size 3
+#define if_node_size 2
+#define align_stack_node_size 6
+#define nesting_node_size 2
+
+#define span_node_size 3
+#define span_span(a) vlink((a)+1)
+#define span_link(a) vinfo((a)+1)
+
+#define pseudo_file_node_size 2
+#define pseudo_lines(a) vlink((a)+1)
+
+#define nodetype_has_attributes(t) (((t)<=glyph_node) && ((t)!=unset_node))
+
+#define style_node_size 4 /* number of words in a style node*/
+#define radical_noad_size 6 /*number of |mem| words in a radical noad*/
+#define accent_noad_size 6 /*number of |mem| words in an accent noad*/
+
+
+#define display_mlist(a) vinfo((a)+2) /* mlist to be used in display style*/
+#define text_mlist(a) vlink((a)+2) /* mlist to be used in text style */
+#define script_mlist(a) vinfo((a)+3) /* mlist to be used in script style */
+#define script_script_mlist(a) vlink((a)+3) /* mlist to be used in scriptscript style */
+
+#define noad_size 5 /*number of words in a normal noad*/
+#define nucleus(a) (a)+2 /* the |nucleus| field of a noad */
+#define supscr(a) (a)+3 /* the |supscr| field of a noad */
+#define subscr(a) (a)+4 /* the |subscr| field of a noad */
+#define math_type vlink /* a |quarterword| in |mem| */
+#define fam(a) type((a)) /* a |quarterword| in |mem| */
+
+#define fraction_noad_size 7 /*number of |mem| words in a fraction noad*/
+#define numerator supscr /*|numerator| field in a fraction noad*/
+#define denominator subscr /*|denominator| field in a fraction noad*/
+
+typedef enum {
+ math_char=1, /* |math_type| when the attribute is simple */
+ sub_box, /* |math_type| when the attribute is a box */
+ sub_mlist, /* |math_type| when the attribute is a formula */
+ math_text_char /* |math_type| when italic correction is dubious */
+} math_types;
+
+
+typedef enum {
+ open_node = 0,
+ write_node,
+ close_node,
+ special_node,
+ language_node,
+ set_language_code,
+ local_par_node,
+ dir_node,
+ pdf_literal_node,
+ pdf_obj_code,
+ pdf_refobj_node, /* 10 */
+ pdf_xform_code,
+ pdf_refxform_node,
+ pdf_ximage_code,
+ pdf_refximage_node,
+ pdf_annot_node,
+ pdf_start_link_node,
+ pdf_end_link_node,
+ pdf_outline_code,
+ pdf_dest_node,
+ pdf_thread_node, /* 20 */
+ pdf_start_thread_node,
+ pdf_end_thread_node,
+ pdf_save_pos_node,
+ pdf_thread_data_node,
+ pdf_link_data_node,
+ pdf_names_code,
+ pdf_font_attr_code,
+ pdf_include_chars_code,
+ pdf_map_file_code,
+ pdf_map_line_code, /* 30 */
+ pdf_trailer_code,
+ pdf_font_expand_code,
+ set_random_seed_code,
+ pdf_glyph_to_unicode_code,
+ late_lua_node, /* 35 */
+ close_lua_node,
+ save_cat_code_table_code,
+ init_cat_code_table_code,
+ pdf_colorstack_node,
+ pdf_setmatrix_node, /* 40 */
+ pdf_save_node,
+ pdf_restore_node,
+ cancel_boundary_node,
+ user_defined_node /* 44 */ } whatsit_types ;
+
+#define pdf_info_code pdf_thread_data_node
+#define pdf_catalog_code pdf_link_data_node
+
+
+#define GLYPH_CHARACTER (1 << 0)
+#define GLYPH_LIGATURE (1 << 1)
+#define GLYPH_GHOST (1 << 2)
+#define GLYPH_LEFT (1 << 3)
+#define GLYPH_RIGHT (1 << 4)
+
+#define is_character(p) ((subtype(p)) & GLYPH_CHARACTER)
+#define is_ligature(p) ((subtype(p)) & GLYPH_LIGATURE )
+#define is_ghost(p) ((subtype(p)) & GLYPH_GHOST )
+
+#define is_simple_character(p) (is_character(p) && !is_ligature(p) && !is_ghost(p))
+
+#define is_leftboundary(p) (is_ligature(p) && ((subtype(p)) & GLYPH_LEFT ))
+#define is_rightboundary(p) (is_ligature(p) && ((subtype(p)) & GLYPH_RIGHT ))
+#define is_leftghost(p) (is_ghost(p) && ((subtype(p)) & GLYPH_LEFT ))
+#define is_rightghost(p) (is_ghost(p) && ((subtype(p)) & GLYPH_RIGHT ))
+
+#define set_is_glyph(p) subtype(p) &= ~GLYPH_CHARACTER
+#define set_is_character(p) subtype(p) |= GLYPH_CHARACTER
+#define set_is_ligature(p) subtype(p) |= GLYPH_LIGATURE
+#define set_is_ghost(p) subtype(p) |= GLYPH_GHOST
+
+#define set_to_glyph(p) subtype(p) = (subtype(p) & 0xFF00)
+#define set_to_character(p) subtype(p) = (subtype(p) & 0xFF00) | GLYPH_CHARACTER
+#define set_to_ligature(p) subtype(p) = (subtype(p) & 0xFF00) | GLYPH_LIGATURE
+#define set_to_ghost(p) subtype(p) = (subtype(p) & 0xFF00) | GLYPH_GHOST
+
+#define set_is_leftboundary(p) { set_to_ligature(p); subtype(p) |= GLYPH_LEFT; }
+#define set_is_rightboundary(p) { set_to_ligature(p); subtype(p) |= GLYPH_RIGHT; }
+#define set_is_leftghost(p) { set_to_ghost(p); subtype(p) |= GLYPH_LEFT; }
+#define set_is_rightghost(p) { set_to_ghost(p); subtype(p) |= GLYPH_RIGHT; }
+
+
+#define special_node_size 3
+
+#define dir_node_size 4
+#define dir_dir(a) vinfo((a)+2)
+#define dir_level(a) vlink((a)+2)
+#define dir_dvi_ptr(a) vinfo((a)+3)
+#define dir_dvi_h(a) vlink((a)+3)
+
+#define write_node_size 3
+#define close_node_size 3
+#define write_tokens(a) vlink(a+2)
+#define write_stream(a) vinfo(a+2)
+
+#define open_node_size 4
+#define open_name(a) vlink((a)+2)
+#define open_area(a) vinfo((a)+3)
+#define open_ext(a) vlink((a)+3)
+
+#define late_lua_data(a) vlink((a)+2)
+#define late_lua_reg(a) vinfo((a)+2)
+
+#define local_par_size 6
+
+#define local_pen_inter(a) vinfo((a)+2)
+#define local_pen_broken(a) vlink((a)+2)
+#define local_box_left(a) vlink((a)+3)
+#define local_box_left_width(a) vinfo((a)+3)
+#define local_box_right(a) vlink((a)+4)
+#define local_box_right_width(a) vinfo((a)+4)
+#define local_par_dir(a) vinfo((a)+5)
+
+
+#define pdf_literal_data(a) vlink(a+2)
+#define pdf_literal_mode(a) vinfo(a+2)
+
+#define pdf_refobj_node_size 3
+
+#define pdf_obj_objnum(a) vinfo((a) + 2)
+
+#define pdf_refxform_node_size 6
+#define pdf_refximage_node_size 6
+#define pdf_annot_node_size 8
+#define pdf_dest_node_size 8
+#define pdf_thread_node_size 8
+
+#define pdf_width(a) varmem[(a) + 2].cint
+#define pdf_height(a) varmem[(a) + 3].cint
+#define pdf_depth(a) varmem[(a) + 4].cint
+
+#define pdf_ximage_objnum(a) vinfo((a) + 5) /* this will be removed soon */
+#define pdf_ximage_ref(a) vinfo((a) + 5)
+#define pdf_xform_objnum(a) vinfo((a) + 5)
+
+#define pdf_annot_data(a) vinfo((a) + 6)
+#define pdf_link_attr(a) vinfo((a) + 6)
+#define pdf_link_action(a) vlink((a) + 6)
+#define pdf_annot_objnum(a) varmem[(a) + 7].cint
+#define pdf_link_objnum(a) varmem[(a) + 7].cint
+
+#define pdf_dest_type(a) type((a) + 6)
+#define pdf_dest_named_id(a) subtype((a) + 6)
+#define pdf_dest_id(a) vlink((a) + 6)
+#define pdf_dest_xyz_zoom(a) vinfo((a) + 7)
+#define pdf_dest_objnum(a) vlink((a) + 7)
+
+#define pdf_thread_named_id(a) subtype((a) + 6)
+#define pdf_thread_id(a) vlink((a) + 6)
+#define pdf_thread_attr(a) vinfo((a) + 7)
+
+#define pdf_end_link_node_size 3
+#define pdf_end_thread_node_size 3
+#define pdf_save_pos_node_size 3
+
+#define pdf_colorstack_node_size 4
+#define pdf_setmatrix_node_size 3
+
+#define pdf_colorstack_stack(a) vlink((a)+2)
+#define pdf_colorstack_cmd(a) vinfo((a)+2)
+#define pdf_colorstack_data(a) vlink((a)+3)
+#define pdf_setmatrix_data(a) vlink((a)+2)
+
+#define pdf_save_node_size 3
+#define pdf_restore_node_size 3
+
+typedef enum {
+ colorstack_set=0,
+ colorstack_push,
+ colorstack_pop,
+ colorstack_current } colorstack_commands;
+
+#define colorstack_data colorstack_push /* last value where data field is set */
+
+#define user_defined_node_size 4
+#define user_node_type(a) vinfo((a)+2)
+#define user_node_id(a) vlink((a)+2)
+#define user_node_value(a) vinfo((a)+3)
+
+#define cancel_boundary_size 3
+
+typedef enum {
+ exactly=0, /*a box dimension is pre-specified*/
+ additional, /*a box dimension is increased from the natural one*/
+ cal_expand_ratio, /* calculate amount for font expansion after breaking
+ paragraph into lines*/
+ subst_ex_font /* substitute fonts */
+} hpack_subtypes;
+
+#define active_node_size 4 /*number of words in extended active nodes*/
+#define fitness subtype /*|very_loose_fit..tight_fit| on final line for this break*/
+#define break_node(a) vlink((a)+1) /*pointer to the corresponding passive node */
+#define line_number(a) vinfo((a)+1) /*line that begins at this breakpoint*/
+#define total_demerits(a) varmem[(a)+2].cint /* the quantity that \TeX\ minimizes*/
+#define active_short(a) vinfo(a+3) /* |shortfall| of this line */
+#define active_glue(a) vlink(a+3) /*corresponding glue stretch or shrink*/
+
+#define passive_node_size 7
+#define cur_break(a) vlink((a)+1) /*in passive node, points to position of this breakpoint*/
+#define prev_break(a) vinfo((a)+1) /*points to passive node that should precede this one */
+#define passive_pen_inter(a) vinfo((a)+2)
+#define passive_pen_broken(a) vlink((a)+2)
+#define passive_left_box(a) vlink((a)+3)
+#define passive_left_box_width(a) vinfo((a)+3)
+#define passive_last_left_box(a) vlink((a)+4)
+#define passive_last_left_box_width(a) vinfo((a)+4)
+#define passive_right_box(a) vlink((a)+5)
+#define passive_right_box_width(a) vinfo((a)+5)
+#define serial(a) vlink((a)+6) /* serial number for symbolic identification*/
+
+#define delta_node_size 10 /* 8 fields, stored in a+1..9 */
+
+#define couple_nodes(a,b) {assert(b!=null);vlink(a)=b;alink(b)=a;}
+#define try_couple_nodes(a,b) if (b==null) vlink(a)=b; else {couple_nodes(a,b);}
+#define uncouple_node(a) {assert(a!=null);vlink(a)=null;alink(a)=null;}
+
+#define cache_disabled max_halfword
+
+extern void delete_attribute_ref(halfword b) ;
+extern void build_attribute_list(halfword b) ;
+
+extern int unset_attribute(halfword n, int c, int w);
+extern void set_attribute(halfword n, int c, int w);
+extern int has_attribute(halfword n, int c, int w);
+
+extern halfword new_span_node (halfword n, int c, scaled w);
+extern halfword string_to_pseudo(integer l,integer pool_ptr, integer nl);
+
+/* TH: these two defines still need checking. The node ordering in luatex is not
+ quite the same as in tex82 */
+
+#define precedes_break(a) (type((a))<math_node && (type(a)!=whatsit_node || subtype(a)!=dir_node))
+#define non_discardable(a) (type((a))<math_node)
+
+/* from luanode.c */
+
+typedef struct _node_info {
+ int id;
+ int size;
+ char **fields;
+ char *name;
+} node_info;
+
+extern node_info node_data[];
+extern node_info whatsit_node_data[];
+extern halfword new_node(int i, int j);
+extern void flush_node_list(halfword);
+extern void flush_node(halfword);
+extern halfword copy_node_list(halfword);
+extern halfword copy_node(halfword);
+extern void check_node(halfword);
+extern void check_node_mem (void);
+extern void fix_node_list (halfword);
+extern int fix_node_lists;
+extern char *sprint_node_mem_usage (void) ;
+extern halfword raw_glyph_node(void) ;
+extern halfword new_glyph_node(void);
+extern int valid_node(halfword);
+
+#define unity 0x10000
+typedef enum {
+ normal_g=0,
+ sfi,
+ fil,
+ fill,
+ filll } glue_orders;
+
+#define zero_glue 0
+#define sfi_glue zero_glue+glue_spec_size
+#define fil_glue sfi_glue+glue_spec_size
+#define fill_glue fil_glue+glue_spec_size
+#define ss_glue fill_glue+glue_spec_size
+#define fil_neg_glue ss_glue+glue_spec_size
+#define page_ins_head fil_neg_glue+glue_spec_size
+#define contrib_head page_ins_head+temp_node_size
+#define page_head contrib_head+temp_node_size
+#define temp_head page_head+temp_node_size
+#define hold_head temp_head+temp_node_size
+#define adjust_head hold_head+temp_node_size
+#define pre_adjust_head adjust_head+temp_node_size
+#define active pre_adjust_head+temp_node_size
+#define align_head active+active_node_size
+#define end_span align_head+temp_node_size
+#define begin_point end_span+glyph_node_size
+#define end_point begin_point+glyph_node_size
+
+#endif
diff --git a/Build/source/texk/web2c/luatexdir/pdftosrc.1 b/Build/source/texk/web2c/luatexdir/pdftosrc.1
new file mode 100644
index 00000000000..3ee4b680d6f
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/pdftosrc.1
@@ -0,0 +1,219 @@
+.\" Process this file with
+.\" groff -man -Tascii pdftosrc.1
+.\"
+.\" $Id$
+.\"
+.TH pdftosrc 1 "3 November 2005" "User Manuals"
+.SH NAME
+pdftosrc \- extract source file or stream from PDF file
+.SH SYNOPSIS
+.B pdftosrc
+.I PDF-file
+.R [
+.I stream-object-number
+.R ]
+.SH DESCRIPTION
+If only
+.I PDF-file
+is given as argument,
+.B pdftosrc
+extracts the embedded source file
+from the first found stream object
+with /Type /SourceFile within the
+.I PDF-file
+and writes it to a file with the name /SourceName
+as defined in that PDF stream object
+(see application example below).
+
+If both
+.I PDF-file
+and
+.I stream-object-number
+are given as arguments,
+.B pdftosrc
+extracts and uncompresses the PDF stream of the object
+given by its
+.I stream-object-number
+from the
+.I PDF-file
+and writes it to a file named
+.IR PDF-file . stream-object-number
+with the ending
+.I .pdf
+or
+.I .PDF
+stripped from the original
+.I PDF-file
+name.
+
+In either case
+an existing file with the output file name will be overwritten.
+.SH OPTIONS
+None.
+.SH FILES
+Just the executable
+.BR pdftosrc .
+.SH ENVIRONMENT
+None.
+.SH DIAGNOSTICS
+At success the exit code of
+.B pdftosrc
+is 0, else 1.
+
+All messages go to stderr.
+At program invocation,
+.B pdftosrc
+issues the current version number of the program
+.BR xpdf ,
+on which
+.B pdftosrc
+is based:
+
+.RS
+pdftosrc version 3.00
+
+.RE
+When
+.B pdftosrc
+was successful with the output file writing,
+one of the following messages will be issued:
+
+.RS
+Source file extracted to
+.I source-file-name
+
+.RE
+or
+
+.RS
+Stream object extracted to
+.IR PDF-file . stream-object-number
+
+.RE
+
+.RE
+When the object given by the
+.I stream-object-number
+does not contain a stream,
+.B pdftosrc
+issues the following error message:
+
+.RS
+Not a Stream object
+
+.RE
+When the
+.I PDF-file
+can't be opened, the error message is:
+
+.RS
+Error: Couldn't open file
+.RI ' PDF-file '.
+
+.RE
+When
+.B pdftosrc
+encounters an invalid PDF file,
+the error message (several lines) is:
+
+.RS
+Error: May not be a PDF file (continuing anyway)
+.RE
+.RS
+(more lines)
+.RE
+.RS
+Invalid PDF file
+
+.RE
+There are also more error messages from
+.B pdftosrc
+for various kinds of broken PDF files.
+.SH NOTES
+An embedded source file will be written out unchanged,
+i. e. it will not be uncompressed in this process.
+
+Only the stream of the object will be written,
+i. e. not the dictionary of that object.
+
+Knowing which
+.I stream-object-number
+to query requires information about the PDF file
+that has to be gained elsewhere,
+e. g. by looking into the PDF file with an editor.
+
+The stream extraction capabilities of
+.B pdftosrc
+(e. g. regarding understood PDF versions and filter types)
+follow the capabilities of the underlying
+.B xpdf
+program version.
+
+Currently the generation number of the stream object
+is not supported.
+The default value 0 (zero) is taken.
+
+The wording
+.I stream-object-number
+has nothing to do with the `object streams' introduced
+by the Adobe PDF Reference,
+5th edition, version 1.6.
+.SH EXAMPLES
+When using pdftex or pdfetex,
+a source file can be embedded into some
+.I PDF-file
+by using pdftex primitives,
+as illustrated by the following example:
+
+\\immediate\\pdfobj
+.RE
+ stream attr {/Type /SourceFile /SourceName (myfile.zip)}
+.RS
+.RE
+ file{myfile.zip}
+.RS
+.RE
+\\pdfcatalog{/SourceObject \\the\\pdflastobj\\space 0 R}
+
+Then this zip file can be extracted from the
+.I PDF-file
+by calling
+.B pdftosrc
+.IR PDF-file .
+.SH BUGS
+Not all embedded source files will be extracted,
+only the first found one.
+
+Email bug reports to
+.B pdftex@tug.org.
+.SH SEE ALSO
+.BR xpdf (1),
+.BR pdfimages (1),
+.BR pdftotext (1),
+.BR pdftex (1),
+.BR pdfetex (1).
+.SH AUTHORS
+.B pdftosrc
+written by Han The Thanh, using
+.B xpdf
+functionality from Derek Noonburg.
+
+Man page written by Hartmut Henkel.
+.SH COPYRIGHT
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
diff --git a/Build/source/texk/web2c/luatexdir/pdftosrc.cc b/Build/source/texk/web2c/luatexdir/pdftosrc.cc
new file mode 100644
index 00000000000..64f1a3174bc
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/pdftosrc.cc
@@ -0,0 +1,178 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id$
+*/
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <aconf.h>
+#include <assert.h>
+#include <GString.h>
+#include <gmem.h>
+#include <gfile.h>
+#include "Object.h"
+#include "Stream.h"
+#include "Array.h"
+#include "Dict.h"
+#include "XRef.h"
+#include "Catalog.h"
+#include "Page.h"
+#include "GfxFont.h"
+#include "PDFDoc.h"
+#include "GlobalParams.h"
+#include "Error.h"
+
+static XRef *xref = 0;
+
+int main(int argc, char *argv[])
+{
+ char *p, buf[1024];
+ PDFDoc *doc;
+ GString *fileName;
+ Stream *s;
+ Object srcStream, srcName, catalogDict;
+ FILE *outfile;
+ char *outname;
+ int objnum = 0, objgen = 0;
+ bool extract_xref_table = false;
+ int c;
+ fprintf(stderr, "pdftosrc version %s\n", xpdfVersion);
+ if (argc < 2) {
+ fprintf(stderr,
+ "Usage: pdftosrc <PDF-file> [<stream-object-number>]\n");
+ exit(1);
+ }
+ fileName = new GString(argv[1]);
+ globalParams = new GlobalParams();
+ doc = new PDFDoc(fileName);
+ if (!doc->isOk()) {
+ fprintf(stderr, "Invalid PDF file\n");
+ exit(1);
+ }
+ if (argc >= 3) {
+ objnum = atoi(argv[2]);
+ if (argc >= 4)
+ objgen = atoi(argv[3]);
+ }
+ xref = doc->getXRef();
+ catalogDict.initNull();
+ xref->getCatalog(&catalogDict);
+ if (!catalogDict.isDict("Catalog")) {
+ fprintf(stderr, "No Catalog found\n");
+ exit(1);
+ }
+ srcStream.initNull();
+ if (objnum == 0) {
+ catalogDict.dictLookup("SourceObject", &srcStream);
+ if (!srcStream.isStream("SourceFile")) {
+ fprintf(stderr, "No SourceObject found\n");
+ exit(1);
+ }
+ srcName.initNull();
+ srcStream.getStream()->getDict()->lookup("SourceName", &srcName);
+ if (!srcName.isString()) {
+ fprintf(stderr, "No SourceName found\n");
+ exit(1);
+ }
+ outname = srcName.getString()->getCString();
+ // We cannot free srcName, as objname shares its string.
+ // srcName.free();
+ } else if (objnum > 0) {
+ xref->fetch(objnum, objgen, &srcStream);
+ if (!srcStream.isStream()) {
+ fprintf(stderr, "Not a Stream object\n");
+ exit(1);
+ }
+ sprintf(buf, "%s", fileName->getCString());
+ if ((p = strrchr(buf, '.')) == 0)
+ p = strchr(buf, 0);
+ if (objgen == 0)
+ sprintf(p, ".%i", objnum);
+ else
+ sprintf(p, ".%i+%i", objnum, objgen);
+ outname = buf;
+ } else { // objnum < 0 means we are extracting the XRef table
+ extract_xref_table = true;
+ sprintf(buf, "%s", fileName->getCString());
+ if ((p = strrchr(buf, '.')) == 0)
+ p = strchr(buf, 0);
+ sprintf(p, ".xref");
+ outname = buf;
+ }
+ if (!(outfile = fopen(outname, "wb"))) {
+ fprintf(stderr, "Cannot open file \"%s\" for writing\n", outname);
+ exit(1);
+ }
+ if (extract_xref_table) {
+ int size = xref->getSize();
+ int i;
+ for (i = 0; i < size; i++) {
+ if (xref->getEntry(i)->offset == 0xffffffff)
+ break;
+ }
+ size = i;
+ fprintf(outfile, "xref\n");
+ fprintf(outfile, "0 %i\n", size);
+ for (i = 0; i < size; i++) {
+ XRefEntry *e = xref->getEntry(i);
+ if (e->type != xrefEntryCompressed)
+ fprintf(outfile, "%.10lu %.5i %s\n",
+ (long unsigned) e->offset, e->gen,
+ (e->type == xrefEntryFree ? "f" : "n"));
+ else { // e->offset is the object number of the object stream
+ // e->gen is the local index inside that object stream
+ //int objStrOffset = xref->getEntry(e->offset)->offset;
+ Object tmpObj;
+
+ xref->fetch(i, e->gen, &tmpObj); // to ensure xref->objStr is set
+ ObjectStream *objStr = xref->getObjStr();
+ assert(objStr != NULL);
+ int *localOffsets = objStr->getOffsets();
+ assert(localOffsets != NULL);
+// fprintf(outfile, "%0.10lu %i n\n",
+// (long unsigned) (objStrOffset), e->gen);
+ fprintf(outfile, "%.10lu 00000 n\n",
+ (long unsigned) (objStr->getFirstOffset() +
+ localOffsets[e->gen]));
+// (long unsigned) (objStrOffset + objStr->getStart() + localOffsets[e->gen]));
+ tmpObj.free();
+ }
+ }
+ } else {
+ s = srcStream.getStream();
+ s->reset();
+ while ((c = s->getChar()) != EOF)
+ fputc(c, outfile);
+ srcStream.free();
+ }
+ if (objnum == 0)
+ fprintf(stderr, "Source file extracted to %s\n", outname);
+ else if (objnum > 0)
+ fprintf(stderr, "Stream object extracted to %s\n", outname);
+ else
+ fprintf(stderr, "Cross-reference table extracted to %s\n", outname);
+ fclose(outfile);
+ catalogDict.free();
+ delete doc;
+ delete globalParams;
+}
diff --git a/Build/source/texk/web2c/luatexdir/pdftosrc.rc b/Build/source/texk/web2c/luatexdir/pdftosrc.rc
new file mode 100644
index 00000000000..6929fbade24
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/pdftosrc.rc
@@ -0,0 +1,35 @@
+/* pdftosrc.rc: pdftosrc resources -*- C++ -*-
+
+ Copyright (C) 1996-2003 Fabrice Popineau <fabrice.popineau@supelec.fr>
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this file; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#include <texlive-version.h>
+
+#define VER_FILEVERSION TEXLIVE_MAJOR_VERSION,TEXLIVE_MINOR_VERSION,TEXLIVE_BETA_NUMBER,TEXLIVE_ALPHA_NUMBER
+#define VER_FILEVERSION_STR TEXLIVE_PRODUCTVERSION_STR " pdftosrc 2.01"
+
+#define VER_INTERNALNAME_STR "pdftosrc"
+#define VER_ORIGINALFILENAME_STR "pdftosrc.exe"
+
+#define VER_FILEDESCRIPTION_STR "PDF Source Extractor"
+
+#define VER_COMPANYNAME_STR ""
+#define VER_LEGALCOPYRIGHT_STR ""
+
+#include <texlive.version>
+
+/* pdftosrc.rc ends here */
diff --git a/Build/source/texk/web2c/luatexdir/ptexlib.h b/Build/source/texk/web2c/luatexdir/ptexlib.h
new file mode 100644
index 00000000000..aad25eb4ab2
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/ptexlib.h
@@ -0,0 +1,615 @@
+/*
+ Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of luatex.
+
+luatex is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+luatex is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with luatex; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id$
+*/
+
+#ifndef LUATEXLIB
+# define LUATEXLIB
+
+/* WEB2C macros and prototypes */
+# if !defined(LUATEXCOERCE)
+# ifdef luatex
+# undef luatex /* to avoid warning about redefining luatex in luatexd.h */
+# endif /* luatex */
+# define EXTERN extern
+# include "luatexd.h"
+# endif
+
+/* pdftexlib macros */
+# include "ptexmac.h"
+
+# include "avlstuff.h"
+# include "image/image.h"
+
+# include "openbsd-compat.h"
+
+/* pdftexlib type declarations */
+typedef struct {
+ const char *pdfname;
+ const char *t1name;
+ boolean valid;
+} key_entry;
+
+struct _subfont_entry;
+typedef struct _subfont_entry subfont_entry;
+
+struct _subfont_entry {
+ char *infix; /* infix for this subfont, eg "01" */
+ long charcodes[256]; /* the mapping for this subfont as read from sfd */
+ subfont_entry *next;
+};
+
+typedef struct {
+ char *name; /* sfd name, eg "Unicode" */
+ subfont_entry *subfont; /* linked list of subfonts */
+} sfd_entry;
+
+typedef struct {
+ integer fe_objnum; /* object number */
+ char *name; /* encoding file name */
+ char **glyph_names; /* array of glyph names */
+ struct avl_table *tx_tree; /* tree of encoding positions marked as used by TeX */
+} fe_entry;
+
+typedef struct {
+ char *name; /* glyph name */
+ long code; /* -1 = undefined; -2 = multiple codes, stored
+ as string in unicode_seq; otherwise unicode value */
+ char *unicode_seq; /* multiple unicode sequence */
+} glyph_unicode_entry;
+
+typedef struct {
+ /* parameters scanned from the map file: */
+ char *tfm_name; /* TFM file name (1st field in map line) */
+ char *sfd_name; /* subfont directory name, like @sfd_name@ */
+ char *ps_name; /* PostScript name (optional 2nd field in map line) */
+ integer fd_flags; /* font descriptor /Flags (PDF Ref. section 5.7.1) */
+ integer slant; /* SlantFont */
+ integer extend; /* ExtendFont */
+ char *encname; /* encoding file name */
+ char *ff_name; /* font file name */
+ unsigned short type; /* various flags */
+ short pid; /* Pid for truetype fonts */
+ short eid; /* Eid for truetype fonts */
+ /* parameters NOT scanned from the map file: */
+ subfont_entry *subfont; /* subfont mapping */
+ unsigned short links; /* link flags from tfm_tree and ps_tree */
+ boolean in_use; /* true if this structure has been referenced already */
+} fm_entry;
+
+typedef struct glw_entry_ { /* subset glyphs for inclusion in CID-based fonts */
+ unsigned short id; /* glyph CID */
+ unsigned short wd; /* glyph width in 1/1000 em parts */
+} glw_entry;
+
+
+/**********************************************************************/
+
+typedef struct {
+ int val; /* value */
+ boolean set; /* true if parameter has been set */
+} intparm;
+
+typedef struct fd_entry_ {
+ integer fd_objnum; /* object number of the font descriptor object */
+ char *fontname; /* /FontName (without subset tag) */
+ char *subset_tag; /* 6-character subset tag */
+ boolean ff_found;
+ integer ff_objnum; /* object number of the font program stream */
+ integer fn_objnum; /* font name object number (embedded PDF) */
+ boolean all_glyphs; /* embed all glyphs? */
+ boolean write_ttf_glyph_names;
+ intparm font_dim[FONT_KEYS_NUM];
+ fe_entry *fe; /* pointer to encoding structure */
+ char **builtin_glyph_names; /* builtin encoding as read from the Type1 font file */
+ fm_entry *fm; /* pointer to font map structure */
+ struct avl_table *tx_tree; /* tree of non-reencoded TeX characters marked as used */
+ struct avl_table *gl_tree; /* tree of all marked glyphs */
+} fd_entry;
+
+typedef struct fo_entry_ {
+ integer fo_objnum; /* object number of the font dictionary */
+ internalfontnumber tex_font; /* needed only for \pdffontattr{} */
+ fm_entry *fm; /* pointer to font map structure for this font dictionary */
+ fd_entry *fd; /* pointer to /FontDescriptor object structure */
+ fe_entry *fe; /* pointer to encoding structure */
+ integer cw_objnum; /* object number of the font program object */
+ integer first_char; /* first character used in this font */
+ integer last_char; /* last character used in this font */
+ struct avl_table *tx_tree; /* tree of non-reencoded TeX characters marked as used */
+ integer tounicode_objnum; /* object number of ToUnicode */
+} fo_entry;
+
+/**********************************************************************/
+
+typedef struct {
+ char *ff_name; /* base name of font file */
+ char *ff_path; /* full path to font file */
+} ff_entry;
+
+typedef short shalfword;
+typedef struct {
+ integer charcode, cwidth, cheight, xoff, yoff, xescape, rastersize;
+ halfword *raster;
+} chardesc;
+
+/* pdftexlib variable declarations */
+extern boolean true_dimen;
+extern char **t1_glyph_names, *t1_builtin_glyph_names[];
+extern char *cur_file_name;
+extern const char notdef[];
+extern integer t1_length1, t1_length2, t1_length3;
+extern integer ttf_length;
+extern strnumber last_tex_string;
+extern size_t last_ptr_index;
+
+/* loadpool.c */
+
+int loadpoolstrings(integer spare_size);
+
+/* pdftexlib function prototypes */
+
+/* epdf.c */
+extern integer get_fontfile_num(int);
+extern integer get_fontname_num(int);
+extern void epdf_free(void);
+
+/* mapfile.c */
+extern fm_entry *lookup_fontmap(char *);
+extern boolean hasfmentry(internalfontnumber);
+extern void fm_free(void);
+extern void fm_read_info(void);
+extern ff_entry *check_ff_exist(char *, boolean);
+extern void pdfmapfile(integer);
+extern void pdfmapline(integer);
+extern void pdf_init_map_file(string map_name);
+extern fm_entry *new_fm_entry(void);
+extern void delete_fm_entry(fm_entry *);
+extern int avl_do_entry(fm_entry *, int);
+
+/* papersiz.c */
+extern integer myatodim(char **);
+extern integer myatol(char **);
+
+/* pkin.c */
+extern int readchar(boolean, chardesc *);
+
+/* subfont.c */
+extern void sfd_free(void);
+extern boolean handle_subfont_fm(fm_entry *, int);
+
+/* tounicode.c */
+extern void glyph_unicode_free(void);
+extern void def_tounicode(strnumber, strnumber);
+extern integer write_tounicode(char **, char *);
+
+/* utils.c */
+extern boolean str_eq_cstr(strnumber, char *);
+extern char *makecstring(integer);
+extern char *makeclstring(integer, int *);
+extern void print_string(char *j);
+extern void append_string(char *s);
+extern void getcreationdate(void);
+extern void tconfusion(char *s);
+extern void tprint(char *s);
+extern void tprint_nl(char *s);
+extern void tprint_esc(char *s);
+
+# define overflow_string(a,b) { overflow(maketexstring(a),b); flush_str(last_tex_string); }
+
+extern int xfflush(FILE *);
+extern int xgetc(FILE *);
+extern int xputc(int, FILE *);
+extern scaled ext_xn_over_d(scaled, scaled, scaled);
+extern size_t xfwrite(void *, size_t size, size_t nmemb, FILE *);
+extern strnumber get_resname_prefix(void);
+extern strnumber maketexstring(const char *);
+extern strnumber maketexlstring(const char *, size_t);
+extern integer fb_offset(void);
+extern void fb_flush(void);
+extern void fb_putchar(eight_bits b);
+extern void fb_seek(integer);
+extern void libpdffinish(void);
+extern char *makecfilename(strnumber s);
+extern void make_subset_tag(fd_entry *);
+__attribute__ ((format(printf, 1, 2)))
+extern void pdf_printf(const char *, ...);
+extern void pdf_puts(const char *);
+__attribute__ ((noreturn, format(printf, 1, 2)))
+extern void pdftex_fail(const char *, ...);
+__attribute__ ((format(printf, 1, 2)))
+extern void pdftex_warn(const char *, ...);
+extern void set_job_id(int, int, int, int);
+__attribute__ ((format(printf, 1, 2)))
+extern void tex_printf(const char *, ...);
+extern void write_stream_length(integer, integer);
+extern char *convertStringToPDFString(const char *in, int len);
+extern void print_ID(strnumber);
+extern void print_creation_date();
+extern void print_mod_date();
+extern void escapename(poolpointer in);
+extern void escapestring(poolpointer in);
+extern void escapehex(poolpointer in);
+extern void unescapehex(poolpointer in);
+extern void make_pdftex_banner(void);
+extern void init_start_time();
+extern void remove_pdffile(void);
+extern void garbage_warning(void);
+extern void initversionstring(char **versions);
+extern int newcolorstack(integer s, integer literal_mode, boolean pagestart);
+extern int colorstackused();
+extern integer colorstackset(int colstack_no, integer s);
+extern integer colorstackpush(int colstack_no, integer s);
+extern integer colorstackpop(int colstack_no);
+extern integer colorstackcurrent(int colstack_no);
+extern integer colorstackskippagestart(int colstack_no);
+extern void checkpdfsave(int cur_h, int cur_v);
+extern void checkpdfrestore(int cur_h, int cur_v);
+extern void pdfshipoutbegin(boolean shipping_page);
+extern void pdfshipoutend(boolean shipping_page);
+extern void pdfsetmatrix(poolpointer in, scaled cur_h, scaled cur_v);
+extern void matrixtransformpoint(scaled x, scaled y);
+extern void matrixtransformrect(scaled llx, scaled lly, scaled urx, scaled ury);
+extern boolean matrixused();
+extern void matrixrecalculate(scaled urx);
+extern scaled getllx();
+extern scaled getlly();
+extern scaled geturx();
+extern scaled getury();
+
+/* writeenc.c */
+extern fe_entry *get_fe_entry(char *);
+extern void enc_free(void);
+extern void write_fontencodings(void);
+
+/* writefont.c */
+extern void do_pdf_font(integer, internalfontnumber);
+extern fd_entry *lookup_fd_entry(char *, integer, integer);
+extern fd_entry *new_fd_entry(void);
+extern void write_fontstuff();
+
+/* writeimg.c */
+extern boolean check_image_b(integer);
+extern boolean check_image_c(integer);
+extern boolean check_image_i(integer);
+extern boolean is_pdf_image(integer);
+extern integer epdforigx(integer);
+extern integer epdforigy(integer);
+extern integer image_pages(integer);
+extern integer image_index(integer);
+extern integer image_width(integer);
+extern integer image_height(integer);
+extern integer image_depth(integer);
+extern integer image_objnum(integer);
+extern integer image_imgnum(integer);
+extern integer new_image_entry(void);
+extern integer read_image(integer, integer, strnumber, integer, strnumber,
+ strnumber, integer, integer, integer, integer);
+extern void img_free(void);
+extern void update_image_procset(integer);
+extern void write_image(integer);
+extern integer image_colordepth(integer img);
+extern void scale_image(integer);
+extern void set_image_dimensions(integer, integer, integer, integer);
+extern void set_image_index(integer, integer);
+extern void out_image(integer, scaled, scaled);
+
+/* writejbig2.c */
+extern void flush_jbig2_page0_objects();
+
+/* writet1.c */
+extern boolean t1_subset(char *, char *, unsigned char *);
+extern char **load_enc_file(char *);
+extern void writet1(fd_entry *);
+extern void t1_free(void);
+
+/* writet3.c */
+extern void writet3(int, internalfontnumber);
+extern scaled get_pk_char_width(internalfontnumber, scaled);
+
+/* writettf.c */
+extern void writettf(fd_entry *);
+extern void writeotf(fd_entry *);
+extern void ttf_free(void);
+
+/* writezip.c */
+extern void write_zip(boolean);
+extern void zip_free(void);
+
+/* avlstuff.c */
+extern int comp_int_entry(const void *, const void *, void *);
+extern int comp_string_entry(const void *, const void *, void *);
+extern void avl_put_obj(integer, integer);
+extern integer avl_find_obj(integer, integer, integer);
+
+/**********************************************************************/
+static const key_entry font_key[FONT_KEYS_NUM] = {
+ {"Ascent", "Ascender", 1}
+ , {"CapHeight", "CapHeight", 1}
+ , {"Descent", "Descender", 1}
+ , {"ItalicAngle", "ItalicAngle", 1}
+ , {"StemV", "StdVW", 1}
+ , {"XHeight", "XHeight", 1}
+ , {"FontBBox", "FontBBox", 1}
+ , {"", "", 0}
+ , {"", "", 0}
+ , {"", "", 0}
+ , {"FontName", "FontName", 1}
+};
+
+/**********************************************************************/
+
+typedef enum {
+ no_print = 16,
+ term_only = 17,
+ log_only = 18,
+ term_and_log = 19,
+ pseudo = 20,
+ new_string = 21
+} selector_settings;
+
+
+# include "font/texfont.h"
+
+/* language stuff */
+
+typedef struct _lang_variables {
+ int pre_hyphen_char;
+ int post_hyphen_char;
+} lang_variables;
+
+
+# include "hyphen.h"
+
+struct tex_language {
+ HyphenDict *patterns;
+ int exceptions; /* lua registry pointer, should be replaced */
+ int id;
+ int pre_hyphen_char;
+ int post_hyphen_char;
+};
+
+# define MAX_WORD_LEN 256 /* in chars */
+
+extern struct tex_language *new_language(void);
+extern struct tex_language *get_language(int n);
+extern void load_patterns(struct tex_language *lang, unsigned char *buf);
+extern void load_hyphenation(struct tex_language *lang, unsigned char *buf);
+extern int hyphenate_string(struct tex_language *lang, char *w, char **ret);
+
+extern void new_hyphenation(halfword h, halfword t);
+extern void clear_patterns(struct tex_language *lang);
+extern void clear_hyphenation(struct tex_language *lang);
+extern char *clean_hyphenation(char *buffer, char **cleaned);
+extern void hnj_hyphenation(halfword head, halfword tail);
+
+extern void set_pre_hyphen_char(integer lan, integer val);
+extern void set_post_hyphen_char(integer lan, integer val);
+extern integer get_pre_hyphen_char(integer lan);
+extern integer get_post_hyphen_char(integer lan);
+
+extern halfword new_ligkern(halfword head, halfword tail);
+extern halfword handle_ligaturing(halfword head, halfword tail);
+extern halfword handle_kerning(halfword head, halfword tail);
+
+# define push_dir(a) \
+ { dir_tmp=new_dir((a)); \
+ vlink(dir_tmp)=dir_ptr; dir_ptr=dir_tmp; \
+ dir_ptr=dir_tmp; \
+ }
+
+# define push_dir_node(a) \
+ { dir_tmp=new_node(whatsit_node,dir_node); \
+ dir_dir(dir_tmp)=dir_dir((a)); \
+ dir_level(dir_tmp)=dir_level((a)); \
+ dir_dvi_h(dir_tmp)=dir_dvi_h((a)); \
+ dir_dvi_ptr(dir_tmp)=dir_dvi_ptr((a)); \
+ vlink(dir_tmp)=dir_ptr; dir_ptr=dir_tmp; \
+ }
+
+# define pop_dir_node() \
+ { dir_tmp=dir_ptr; \
+ dir_ptr=vlink(dir_tmp); \
+ flush_node(dir_tmp); \
+ }
+
+
+
+# define dir_parallel(a,b) (((a) % 2)==((b) % 2))
+# define dir_orthogonal(a,b) (((a) % 2)!=((b) % 2))
+
+# define is_rotated(a) dir_parallel(dir_secondary[(a)],dir_tertiary[(a)])
+
+void initialize_active(void);
+
+halfword find_protchar_left(halfword l, boolean d);
+halfword find_protchar_right(halfword l, halfword r);
+
+void ext_do_line_break(boolean d,
+ int pretolerance,
+ int tracing_paragraphs,
+ int tolerance,
+ scaled emergency_stretch,
+ int looseness,
+ int hyphen_penalty,
+ int ex_hyphen_penalty,
+ int pdf_adjust_spacing,
+ halfword par_shape_ptr,
+ int adj_demerits,
+ int pdf_protrude_chars,
+ int line_penalty,
+ int last_line_fit,
+ int double_hyphen_demerits,
+ int final_hyphen_demerits,
+ int hang_indent,
+ int hsize,
+ int hang_after,
+ halfword left_skip,
+ halfword right_skip,
+ int pdf_each_line_height,
+ int pdf_each_line_depth,
+ int pdf_first_line_height,
+ int pdf_last_line_depth,
+ halfword inter_line_penalties_ptr,
+ int inter_line_penalty,
+ int club_penalty,
+ halfword club_penalties_ptr,
+ halfword display_widow_penalties_ptr,
+ halfword widow_penalties_ptr,
+ int display_widow_penalty,
+ int widow_penalty,
+ int broken_penalty, halfword final_par_glue);
+
+void ext_post_line_break(boolean d,
+ int right_skip,
+ int left_skip,
+ int pdf_protrude_chars,
+ halfword par_shape_ptr,
+ int pdf_adjust_spacing,
+ int pdf_each_line_height,
+ int pdf_each_line_depth,
+ int pdf_first_line_height,
+ int pdf_last_line_depth,
+ halfword inter_line_penalties_ptr,
+ int inter_line_penalty,
+ int club_penalty,
+ halfword club_penalties_ptr,
+ halfword display_widow_penalties_ptr,
+ halfword widow_penalties_ptr,
+ int display_widow_penalty,
+ int widow_penalty,
+ int broken_penalty,
+ halfword final_par_glue,
+ halfword best_bet,
+ halfword last_special_line,
+ scaled second_width,
+ scaled second_indent,
+ scaled first_width,
+ scaled first_indent, halfword best_line);
+
+halfword lua_hpack_filter(halfword head_node, scaled size, int pack_type,
+ int extrainfo);
+void lua_node_filter(int filterid, int extrainfo, halfword head_node,
+ halfword * tail_node);
+halfword lua_vpack_filter(halfword head_node, scaled size, int pack_type,
+ scaled maxd, int extrainfo);
+void lua_node_filter_s(int filterid, char *extrainfo, halfword head_node,
+ halfword * tail_node);
+
+void load_tex_patterns(int curlang, halfword head);
+void load_tex_hyphenation(int curlang, halfword head);
+
+/* textcodes.c */
+void set_lc_code(integer n, halfword v, quarterword gl);
+halfword get_lc_code(integer n);
+void set_uc_code(integer n, halfword v, quarterword gl);
+halfword get_uc_code(integer n);
+void set_sf_code(integer n, halfword v, quarterword gl);
+halfword get_sf_code(integer n);
+void set_cat_code(integer h, integer n, halfword v, quarterword gl);
+halfword get_cat_code(integer h, integer n);
+void unsave_cat_codes(integer h, quarterword gl);
+int valid_catcode_table(int h);
+void unsave_text_codes(quarterword grouplevel);
+void initialize_text_codes(void);
+void dump_text_codes(void);
+void undump_text_codes(void);
+
+/* mathcodes.c */
+
+void set_math_code(integer n, halfword v, quarterword gl);
+halfword get_math_code(integer n);
+void set_del_code(integer n, halfword v, halfword w, quarterword gl);
+halfword get_del_code_a(integer n);
+halfword get_del_code_b(integer n);
+void unsave_math_codes(quarterword grouplevel);
+void initialize_math_codes(void);
+void dump_math_codes(void);
+void undump_math_codes(void);
+
+/* texlang.c */
+
+void dump_language_data(void);
+void undump_language_data(void);
+char *exception_strings(struct tex_language *lang);
+
+/* llualib.c */
+
+void dump_luac_registers(void);
+void undump_luac_registers(void);
+
+/* ltexlib.c */
+void luacstring_start(int n);
+void luacstring_close(int n);
+int luacstring_detokenized(void);
+int luacstring_defaultcattable(void);
+integer luacstring_cattable(void);
+int luacstring_simple(void);
+int luacstring_penultimate(void);
+int luacstring_input(void);
+
+
+/* luatoken.c */
+void do_get_token_lua(integer callback_id);
+
+/* luanode.c */
+int visible_last_node_type(int n);
+void print_node_mem_stats(int n, int o);
+
+/* writeimg.c */
+integer epdf_orig_y(integer i);
+integer epdf_orig_x(integer i);
+
+/* limglib.c */
+void lua_setximage(integer i);
+
+/* vfovf.c */
+void vf_expand_local_fonts(internal_font_number f);
+internal_font_number letter_space_font(halfword u, internal_font_number f,
+ integer e);
+internal_font_number auto_expand_font(internal_font_number f, integer e);
+str_number expand_font_name(internal_font_number f, integer e);
+void pdf_check_vf_cur_val(void);
+
+/* ltexiolib.c */
+void flush_loggable_info(void);
+
+/* luastuff.c */
+void closelua(int n);
+void luacall(int n, int s);
+void luatokencall(int n, int p);
+
+void tex_error(char *msg, char **hlp);
+
+scaled divide_scaled(scaled s, scaled m, integer dd);
+scaled divide_scaled_n(double s, double m, double d);
+
+/* texpdf.c */
+void pdf_print_char(internal_font_number f, integer c);
+void pdf_print(str_number n);
+void pdf_print_str(str_number n);
+void pdf_print_int(integer n);
+
+/* textoken.c */
+
+void get_next(void);
+void get_token_lua(void);
+
+#endif /* PDFTEXLIB */
diff --git a/Build/source/texk/web2c/luatexdir/ptexmac.h b/Build/source/texk/web2c/luatexdir/ptexmac.h
new file mode 100644
index 00000000000..2f795ce3e71
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/ptexmac.h
@@ -0,0 +1,236 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id$
+*/
+
+#ifndef PDFTEXMAC
+# define PDFTEXMAC
+
+/* Not all systems define it. */
+# ifndef M_PI
+# define M_PI 3.14159265358979323846
+ /* pi */
+# define M_PI_2 1.5707963267948966192E0
+ /*Hex 2^ 0 * 1.921FB54442D18 */
+# define M_PI_4 7.8539816339744830962E-1
+ /*Hex 2^-1 * 1.921FB54442D18 */
+# endif
+
+# ifdef WIN32
+/* Why relying on gmalloc() ???*/
+# define gmalloc(n) xmalloc(n)
+# define gfree(p) free(p)
+# define inline __inline
+# define srandom(n) srand(n)
+# define random() rand()
+# endif
+
+/* Pascal WEB macros */
+# define maxinteger 0x7FFFFFFF
+# define maxdimen 0x3FFFFFFF
+
+# define objinfo(n) objtab[n].int0
+
+# define pdfroom(n) do { \
+ if ((unsigned)(n + pdf_ptr) > (unsigned)pdf_buf_size) { \
+ if (pdf_os_mode) \
+ zpdf_os_get_os_buf(n); \
+ else { \
+ if ((unsigned)(n) > (unsigned)pdf_buf_size) \
+ pdftex_fail("PDF output buffer overflowed"); \
+ else \
+ pdf_flush(); \
+ } \
+ } \
+} while (0)
+
+# define pdfout(c) do { \
+ pdfroom(1); \
+ pdf_buf[pdf_ptr++] = c; \
+} while (0)
+
+# define pdfoffset() (pdf_gone + pdf_ptr)
+
+# define MAX_CHAR_CODE 255
+# define PRINTF_BUF_SIZE 1024
+# define MAX_CSTRING_LEN 1024 * 1024
+# define MAX_PSTRING_LEN 1024
+# define SMALL_BUF_SIZE 256
+# define SMALL_ARRAY_SIZE 256
+# define FONTNAME_BUF_SIZE 128
+ /* a PDF name can be maximum 127 chars long */
+
+# define pdftex_debug tex_printf
+
+extern void check_buffer_overflow(int wsize);
+extern void check_pool_overflow (int wsize);
+
+# define check_buf(size, buf_size) \
+ if ((unsigned)(size) > (unsigned)(buf_size)) \
+ pdftex_fail("buffer overflow: %d > %d at file %s, line %d", \
+ (int)(size), (int)(buf_size), __FILE__, __LINE__ )
+
+# define append_char_to_buf(c, p, buf, buf_size) do { \
+ if (c == 9) \
+ c = 32; \
+ if (c == 13 || c == EOF) \
+ c = 10; \
+ if (c != ' ' || (p > buf && p[-1] != 32)) { \
+ check_buf(p - buf + 1, (buf_size)); \
+ *p++ = c; \
+ } \
+} while (0)
+
+# define append_eol(p, buf, buf_size) do { \
+ check_buf(p - buf + 2, (buf_size)); \
+ if (p - buf > 1 && p[-1] != 10) \
+ *p++ = 10; \
+ if (p - buf > 2 && p[-2] == 32) { \
+ p[-2] = 10; \
+ p--; \
+ } \
+ *p = 0; \
+} while (0)
+
+# define remove_eol(p, buf) do { \
+ p = strend(buf) - 1; \
+ if (*p == 10) \
+ *p = 0; \
+} while (0)
+
+# define skip(p, c) if (*p == c) p++
+
+# define alloc_array(T, n, s) do { \
+ if (T##_array == NULL) { \
+ T##_limit = (s); \
+ if ((unsigned)(n) > T##_limit) \
+ T##_limit = (n); \
+ T##_array = xtalloc(T##_limit, T##_entry); \
+ T##_ptr = T##_array; \
+ } \
+ else if ((unsigned)(T##_ptr - T##_array + (n)) > T##_limit) { \
+ last_ptr_index = T##_ptr - T##_array; \
+ T##_limit *= 2; \
+ if ((unsigned)(T##_ptr - T##_array + (n)) > T##_limit) \
+ T##_limit = T##_ptr - T##_array + (n); \
+ xretalloc(T##_array, T##_limit, T##_entry); \
+ T##_ptr = T##_array + last_ptr_index; \
+ } \
+} while (0)
+
+# define is_cfg_comment(c) \
+ (c == 10 || c == '*' || c == '#' || c == ';' || c == '%')
+
+# define define_array(T) \
+T##_entry *T##_ptr, *T##_array = NULL; \
+size_t T##_limit
+
+# define xfree(p) do { if (p != NULL) free(p); p = NULL; } while (0)
+# define strend(s) strchr(s, 0)
+# define xtalloc XTALLOC
+# define xretalloc XRETALLOC
+
+# define ASCENT_CODE 0
+# define CAPHEIGHT_CODE 1
+# define DESCENT_CODE 2
+# define ITALIC_ANGLE_CODE 3
+# define STEMV_CODE 4
+# define XHEIGHT_CODE 5
+# define FONTBBOX1_CODE 6
+# define FONTBBOX2_CODE 7
+# define FONTBBOX3_CODE 8
+# define FONTBBOX4_CODE 9
+# define FONTNAME_CODE 10
+# define GEN_KEY_NUM (XHEIGHT_CODE + 1)
+# define MAX_KEY_CODE (FONTBBOX1_CODE + 1)
+# define INT_KEYS_NUM (FONTBBOX4_CODE + 1)
+# define FONT_KEYS_NUM (FONTNAME_CODE + 1)
+
+# define F_INCLUDED 0x01
+# define F_SUBSETTED 0x02
+# define F_STDT1FONT 0x04
+# define F_SUBFONT 0x08
+# define F_TYPE1 0x10
+# define F_TRUETYPE 0x20
+# define F_OTF 0x40
+# define F_CIDKEYED 0x80
+
+# define set_included(fm) ((fm)->type |= F_INCLUDED)
+# define set_subsetted(fm) ((fm)->type |= F_SUBSETTED)
+# define set_std_t1font(fm) ((fm)->type |= F_STDT1FONT)
+# define set_subfont(fm) ((fm)->type |= F_SUBFONT)
+# define set_type1(fm) ((fm)->type |= F_TYPE1)
+# define set_truetype(fm) ((fm)->type |= F_TRUETYPE)
+# define set_opentype(fm) ((fm)->type |= F_OTF)
+# define set_subfont(fm) ((fm)->type |= F_SUBFONT)
+# define set_cidkeyed(fm) ((fm)->type |= F_CIDKEYED)
+
+# define unset_included(fm) ((fm)->type &= ~F_INCLUDED)
+# define unset_subsetted(fm) ((fm)->type &= ~F_SUBSETTED)
+# define unset_std_t1font(fm)((fm)->type &= ~F_STDT1FONT)
+# define unset_subfont(fm) ((fm)->type &= ~F_SUBFONT)
+# define unset_type1(fm) ((fm)->type &= ~F_TYPE1)
+# define unset_truetype(fm) ((fm)->type &= ~F_TRUETYPE)
+# define unset_opentype(fm) ((fm)->type &= ~F_OTF)
+# define unset_subfont(fm) ((fm)->type &= ~F_SUBFONT)
+# define unset_cidkeyed(fm) ((fm)->type &= ~F_CIDKEYED)
+
+# define is_included(fm) (((fm)->type & F_INCLUDED) != 0)
+# define is_subsetted(fm) (((fm)->type & F_SUBSETTED) != 0)
+# define is_std_t1font(fm) (((fm)->type & F_STDT1FONT) != 0)
+# define is_subfont(fm) (((fm)->type & F_SUBFONT) != 0)
+# define is_type1(fm) (((fm)->type & F_TYPE1) != 0)
+# define is_truetype(fm) (((fm)->type & F_TRUETYPE) != 0)
+# define is_opentype(fm) (((fm)->type & F_OTF) != 0)
+# define is_subfont(fm) (((fm)->type & F_SUBFONT) != 0)
+# define is_cidkeyed(fm) (((fm)->type & F_CIDKEYED) != 0)
+
+# define fm_slant(fm) (fm)->slant
+# define fm_extend(fm) (fm)->extend
+# define fm_fontfile(fm) (fm)->ff_name
+
+# define is_reencoded(fm) ((fm)->encname != NULL)
+# define is_fontfile(fm) (fm_fontfile(fm) != NULL)
+# define is_t1fontfile(fm) (is_fontfile(fm) && is_type1(fm))
+# define is_builtin(fm) (!is_fontfile(fm))
+
+# define LINK_TFM 0x01
+# define LINK_PS 0x02
+# define set_tfmlink(fm) ((fm)->links |= LINK_TFM)
+# define set_pslink(fm) ((fm)->links |= LINK_PS)
+# define unset_tfmlink(fm) ((fm)->links &= ~LINK_TFM)
+# define unset_pslink(fm) ((fm)->links &= ~LINK_PS)
+# define has_tfmlink(fm) ((fm)->links & LINK_TFM)
+# define has_pslink(fm) ((fm)->links & LINK_PS)
+
+
+# define set_cur_file_name(s) \
+ cur_file_name = s; \
+ pack_file_name(maketexstring(cur_file_name), get_nullstr(), get_nullstr())
+
+# define cmp_return(a, b) \
+ if ((a) > (b)) \
+ return 1; \
+ if ((a) < (b)) \
+ return -1
+
+# define str_prefix(s1, s2) (strncmp((s1), (s2), strlen(s2)) == 0)
+
+#endif /* PDFTEXMAC */
diff --git a/Build/source/texk/web2c/luatexdir/svnversion.h b/Build/source/texk/web2c/luatexdir/svnversion.h
new file mode 100644
index 00000000000..9a139c2d294
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/svnversion.h
@@ -0,0 +1,3 @@
+#define BUILD_REVISION "$Revision: 915 $"
+#define BUILD_DATE 20071128
+#define BUILD_TIME 1092554
diff --git a/Build/source/texk/web2c/luatexdir/tex/linebreak.c b/Build/source/texk/web2c/luatexdir/tex/linebreak.c
new file mode 100644
index 00000000000..910d26b9f27
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/tex/linebreak.c
@@ -0,0 +1,2095 @@
+/* $Id: linebreak.c 1102 2008-03-11 09:52:54Z taco $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+#include "nodes.h"
+
+/* Glue nodes in a horizontal list that is being paragraphed are not supposed to
+ include ``infinite'' shrinkability; that is why the algorithm maintains
+ four registers for stretching but only one for shrinking. If the user tries to
+ introduce infinite shrinkability, the shrinkability will be reset to finite
+ and an error message will be issued. A boolean variable |no_shrink_error_yet|
+ prevents this error message from appearing more than once per paragraph.
+*/
+
+#define check_shrinkage(a) \
+ if ((shrink_order((a))!=normal)&&(shrink((a))!=0)) \
+ a=finite_shrink((a))
+
+static boolean no_shrink_error_yet; /*have we complained about infinite shrinkage?*/
+
+halfword
+finite_shrink(halfword p) { /* recovers from infinite shrinkage */
+ halfword q; /*new glue specification*/
+ char *hlp[] = {
+ "The paragraph just ended includes some glue that has",
+ "infinite shrinkability, e.g., `\\hskip 0pt minus 1fil'.",
+ "Such glue doesn't belong there---it allows a paragraph",
+ "of any length to fit on one line. But it's safe to proceed,",
+ "since the offensive shrinkability has been made finite.",
+ NULL };
+ if (no_shrink_error_yet) {
+ no_shrink_error_yet=false;
+ tex_error("Infinite glue shrinkage found in a paragraph",hlp);
+ }
+ q=new_spec(p); shrink_order(q)=normal;
+ delete_glue_ref(p);
+ return q;
+}
+
+/* A pointer variable |cur_p| runs through the given horizontal list as we look
+ for breakpoints. This variable is global, since it is used both by |line_break|
+ and by its subprocedure |try_break|.
+
+ Another global variable called |threshold| is used to determine the feasibility
+ of individual lines: breakpoints are feasible if there is a way to reach
+ them without creating lines whose badness exceeds |threshold|. (The
+ badness is compared to |threshold| before penalties are added, so that
+ penalty values do not affect the feasibility of breakpoints, except that
+ no break is allowed when the penalty is 10000 or more.) If |threshold|
+ is 10000 or more, all legal breaks are considered feasible, since the
+ |badness| function specified above never returns a value greater than~10000.
+
+ Up to three passes might be made through the paragraph in an attempt to find at
+ least one set of feasible breakpoints. On the first pass, we have
+ |threshold=pretolerance| and |second_pass=final_pass=false|.
+ If this pass fails to find a
+ feasible solution, |threshold| is set to |tolerance|, |second_pass| is set
+ |true|, and an attempt is made to hyphenate as many words as possible.
+ If that fails too, we add |emergency_stretch| to the background
+ stretchability and set |final_pass=true|.
+*/
+
+static boolean second_pass; /* is this our second attempt to break this paragraph? */
+static boolean final_pass; /*is this our final attempt to break this paragraph? */
+static integer threshold; /* maximum badness on feasible lines */
+
+/* skipable nodes at the margins during character protrusion */
+
+#define cp_skipable(a) ((! is_char_node((a))) && \
+ ((type((a)) == ins_node) \
+ || (type((a)) == mark_node) \
+ || (type((a)) == adjust_node) \
+ || (type((a)) == penalty_node) \
+ || ((type((a)) == whatsit_node) && \
+ (subtype((a)) != pdf_refximage_node) && \
+ (subtype((a)) != pdf_refxform_node)) \
+ /* reference to an image or XObject form */ \
+ || ((type((a)) == disc_node) && \
+ (vlink_pre_break(a) == null) && \
+ (vlink_post_break(a) == null) && \
+ (vlink_no_break(a) == null)) \
+ /* an empty |disc_node| */ \
+ || ((type((a)) == math_node) && \
+ (surround((a)) == 0)) \
+ || ((type((a)) == kern_node) && \
+ ((width((a)) == 0) || \
+ (subtype((a)) == normal))) \
+ || ((type((a)) == glue_node) && \
+ (glue_ptr((a)) == zero_glue)) \
+ || ((type((a)) == hlist_node) && \
+ (width((a)) == 0) && \
+ (height((a)) == 0) && \
+ (depth((a)) == 0) && \
+ (list_ptr((a)) == null)) \
+ ))
+
+/* maximum fill level for |hlist_stack|*/
+#define max_hlist_stack 512 /* maybe good if larger than |2 *
+ max_quarterword|, so that box nesting
+ level would overflow first */
+
+/* stack for |find_protchar_left()| and |find_protchar_right()| */
+static halfword hlist_stack[max_hlist_stack];
+
+/* fill level for |hlist_stack| */
+static short hlist_stack_level = 0;
+
+void push_node(halfword p) {
+ if (hlist_stack_level >= max_hlist_stack)
+ pdf_error("push_node", "stack overflow");
+ hlist_stack[hlist_stack_level++] = p;
+}
+
+halfword pop_node (void) {
+ if (hlist_stack_level <= 0) /* would point to some bug */
+ pdf_error("pop_node", "stack underflow (internal error)");
+ return hlist_stack[--hlist_stack_level];
+}
+
+#define null_font 0
+
+static integer max_stretch_ratio=0; /*maximal stretch ratio of expanded fonts*/
+static integer max_shrink_ratio=0; /*maximal shrink ratio of expanded fonts*/
+static integer cur_font_step=0; /*the current step of expanded fonts*/
+
+
+boolean check_expand_pars(internal_font_number f) {
+ internal_font_number k;
+
+ if ((pdf_font_step(f) == 0) || ((pdf_font_stretch(f) == null_font) &&
+ (pdf_font_shrink(f) == null_font)))
+ return false;
+ if (cur_font_step < 0)
+ cur_font_step = pdf_font_step(f);
+ else if (cur_font_step != pdf_font_step(f))
+ pdf_error("font expansion",
+ "using fonts with different step of expansion in one paragraph is not allowed");
+ k = pdf_font_stretch(f);
+ if( k != null_font) {
+ if (max_stretch_ratio < 0)
+ max_stretch_ratio = pdf_font_expand_ratio(k);
+ else if (max_stretch_ratio != pdf_font_expand_ratio(k))
+ pdf_error("font expansion",
+ "using fonts with different limit of expansion in one paragraph is not allowed");
+ }
+ k = pdf_font_shrink(f);
+ if( k != null_font) {
+ if (max_shrink_ratio < 0)
+ max_shrink_ratio = -pdf_font_expand_ratio(k);
+ else if (max_shrink_ratio != -pdf_font_expand_ratio(k))
+ pdf_error("font expansion",
+ "using fonts with different limit of expansion in one paragraph is not allowed");
+ }
+ return true;
+}
+
+/* searches left to right from list head |l|, returns 1st non-skipable item*/
+/*public*/ halfword find_protchar_left(halfword l, boolean d) {
+ halfword t;
+ boolean run;
+ if ((vlink(l) != null) && (type(l) == hlist_node) && (width(l) == 0)
+ && (height(l) == 0) && (depth(l) == 0) && (list_ptr(l) == null)) {
+ l = vlink(l); /*for paragraph start with \.{\\parindent = 0pt*/
+ } else if (d) {
+ while ((vlink(l) != null) && (!(is_char_node(l) || non_discardable(l)))) {
+ l = vlink(l); /* std.\ discardables at line break, \TeX book, p 95 */
+ }
+ }
+ hlist_stack_level = 0;
+ run = true;
+ do {
+ t = l;
+ while (run && (type(l) == hlist_node) && (list_ptr(l) != null)) {
+ push_node(l);
+ l = list_ptr(l);
+ }
+ while (run && cp_skipable(l)) {
+ while ((vlink(l) == null) && (hlist_stack_level > 0)) {
+ l = pop_node(); /* don't visit this node again */
+ }
+ if (vlink(l) != null)
+ l = vlink(l);
+ else if (hlist_stack_level == 0)
+ run = false;
+ }
+ } while (t != l);
+ return l;
+}
+
+
+/* searches right to left from list tail |r| to head |l|, returns 1st non-skipable item */
+/*public*/ halfword find_protchar_right(halfword l, halfword r) {
+ halfword t;
+ boolean run;
+ if (r == null)
+ return null;
+ hlist_stack_level = 0;
+ run = true;
+ do {
+ t = r;
+ while (run && (type(r) == hlist_node) && (list_ptr(r) != null)) {
+ push_node(l);
+ push_node(r);
+ l = list_ptr(r);
+ r = l;
+ while (vlink(r) != null) {
+ halfword s = r;
+ r = vlink(r);
+ alink(r) = s;
+ }
+ }
+ while (run && cp_skipable(r)) {
+ while ((r == l) && (hlist_stack_level > 0)) {
+ r = pop_node(); /* don't visit this node again */
+ l = pop_node();
+ }
+ if ((r != l) && (r != null) ) {
+ assert(vlink(alink(r))==r);
+ r = alink(r);
+ } else if ((r == l) && (hlist_stack_level == 0))
+ run = false;
+ }
+ } while (t != r);
+ return r;
+}
+
+#define left_pw(a) char_pw((a), left_side)
+#define right_pw(a) char_pw((a), right_side)
+
+#if 0
+/* returns the total width of character protrusion of a line;
+ |cur_break(break_node(q))| and |p| is the leftmost resp. rightmost
+ node in the horizontal list representing the actual line */
+
+scaled total_pw (halfword first_p, halfword q, halfword p) {
+ halfword l, r;
+ l = (break_node(q) == null) ? first_p : cur_break(break_node(q));
+ assert(vlink(alink(p))==p);
+ r = alink(r);
+ /* let's look at the right margin first */
+ if ((p != null) && (type(p) == disc_node) && (vlink(pre_break(p)) != null)) {
+ /* a |disc_node| with non-empty |pre_break|, protrude the last char of |pre_break| */
+ r = vlink(pre_break(p));
+ while (vlink(r) != null)
+ r = vlink(r);
+ } else {
+ r = find_protchar_right(l, r);
+ }
+ /* now the left margin */
+ if ((l != null) && (type(l) == disc_node)) {
+ if (vlink(post_break(l)) != null) {
+ l = vlink(post_break(l)); /* protrude the first char */
+ goto DONE;
+ }
+ }
+ l = find_protchar_left(l, true);
+DONE:
+ return (left_pw(l) + right_pw(r));
+}
+#endif
+
+
+/* When looking for optimal line breaks, \TeX\ creates a ``break node'' for
+ each break that is {\sl feasible}, in the sense that there is a way to end
+ a line at the given place without requiring any line to stretch more than
+ a given tolerance. A break node is characterized by three things: the position
+ of the break (which is a pointer to a |glue_node|, |math_node|, |penalty_node|,
+ or |disc_node|); the ordinal number of the line that will follow this
+ breakpoint; and the fitness classification of the line that has just
+ ended, i.e., |tight_fit|, |decent_fit|, |loose_fit|, or |very_loose_fit|.
+*/
+
+typedef enum {
+ very_loose_fit = 0, /* fitness classification for lines stretching more than
+ their stretchability */
+ loose_fit, /* fitness classification for lines stretching 0.5 to 1.0 of their
+ stretchability */
+ decent_fit, /* fitness classification for all other lines*/
+ tight_fit /* fitness classification for lines shrinking 0.5 to 1.0 of their
+ shrinkability */
+} fitness_value ;
+
+
+/* The algorithm essentially determines the best possible way to achieve
+ each feasible combination of position, line, and fitness. Thus, it answers
+ questions like, ``What is the best way to break the opening part of the
+ paragraph so that the fourth line is a tight line ending at such-and-such
+ a place?'' However, the fact that all lines are to be the same length
+ after a certain point makes it possible to regard all sufficiently large
+ line numbers as equivalent, when the looseness parameter is zero, and this
+ makes it possible for the algorithm to save space and time.
+
+ An ``active node'' and a ``passive node'' are created in |mem| for each
+ feasible breakpoint that needs to be considered. Active nodes are three
+ words long and passive nodes are two words long. We need active nodes only
+ for breakpoints near the place in the paragraph that is currently being
+ examined, so they are recycled within a comparatively short time after
+ they are created.
+*/
+
+/* An active node for a given breakpoint contains six fields:
+
+|vlink| points to the next node in the list of active nodes; the
+last active node has |vlink=active|.
+
+|break_node| points to the passive node associated with this
+breakpoint.
+
+|line_number| is the number of the line that follows this
+breakpoint.
+
+|fitness| is the fitness classification of the line ending at this
+breakpoint.
+
+|type| is either |hyphenated_node| or |unhyphenated_node|, depending on
+whether this breakpoint is a |disc_node|.
+
+|total_demerits| is the minimum possible sum of demerits over all
+lines leading from the beginning of the paragraph to this breakpoint.
+
+The value of |vlink(active)| points to the first active node on a vlinked list
+of all currently active nodes. This list is in order by |line_number|,
+except that nodes with |line_number>easy_line| may be in any order relative
+to each other.
+*/
+
+void
+initialize_active (void) {
+ type(active)=hyphenated_node;
+ line_number(active)=max_halfword;
+ subtype(active)=0; /* the |subtype| is never examined */
+}
+
+/* The passive node for a given breakpoint contains EIGHT fields:
+
+|vlink| points to the passive node created just before this one,
+if any, otherwise it is |null|.
+
+|cur_break| points to the position of this breakpoint in the
+horizontal list for the paragraph being broken.
+
+|prev_break| points to the passive node that should precede this
+one in an optimal path to this breakpoint.
+
+|serial| is equal to |n| if this passive node is the |n|th
+one created during the current pass. (This field is used only when
+printing out detailed statistics about the line-breaking calculations.)
+
+|passive_pen_inter| holds the current \.{\\localinterlinepenalty}
+
+|passive_pen_broken| holds the current \.{\\localbrokenpenalty}
+
+There is a global variable called |passive| that points to the most
+recently created passive node. Another global variable, |printed_node|,
+is used to help print out the paragraph when detailed information about
+the line-breaking computation is being displayed.
+*/
+
+static halfword passive; /* most recent node on passive list */
+static halfword printed_node; /*most recent node that has been printed*/
+static halfword pass_number; /*the number of passive nodes allocated on this pass*/
+
+/*
+@ The active list also contains ``delta'' nodes that help the algorithm
+compute the badness of individual lines. Such nodes appear only between two
+active nodes, and they have |type=delta_node|. If |p| and |r| are active nodes
+and if |q| is a delta node between them, so that |vlink(p)=q| and |vlink(q)=r|,
+then |q| tells the space difference between lines in the horizontal list that
+start after breakpoint |p| and lines that start after breakpoint |r|. In
+other words, if we know the length of the line that starts after |p| and
+ends at our current position, then the corresponding length of the line that
+starts after |r| is obtained by adding the amounts in node~|q|. A delta node
+contains seven scaled numbers, since it must record the net change in glue
+stretchability with respect to all orders of infinity. The natural width
+difference appears in |mem[q+1].sc|; the stretch differences in units of
+pt, sfi, fil, fill, and filll appear in |mem[q+2..q+6].sc|; and the shrink
+difference appears in |mem[q+7].sc|. The |subtype| field of a delta node
+is not used.
+
+Actually, we have two more fields that are used by |pdftex|.
+*/
+
+/* As the algorithm runs, it maintains a set of seven delta-like registers
+for the length of the line following the first active breakpoint to the
+current position in the given hlist. When it makes a pass through the
+active list, it also maintains a similar set of seven registers for the
+length following the active breakpoint of current interest. A third set
+holds the length of an empty line (namely, the sum of \.{\\leftskip} and
+\.{\\rightskip}); and a fourth set is used to create new delta nodes.
+
+When we pass a delta node we want to do operations like
+$$\hbox{\ignorespaces|for
+k:=1 to 7 do cur_active_width[k]:=cur_active_width[k]+mem[q+k].sc|};$$ and we
+want to do this without the overhead of |for| loops. The |do_all_six|
+macro makes such six-tuples convenient.
+*/
+
+#define save_active_width(a) prev_active_width[(a)] = active_width[(a)]
+#define restore_active_width(a) active_width[(a)] = prev_active_width[(a)]
+
+static scaled active_width[10] = {0}; /*distance from first active node to~|cur_p|*/
+static scaled background[10] = {0}; /*length of an ``empty'' line*/
+static scaled break_width[10] = {0}; /*length being computed after current break*/
+
+static boolean auto_breaking; /*make |auto_breaking| accessible out of |line_break|*/
+static boolean try_prev_break; /*force break at the previous legal breakpoint?*/
+static halfword prev_legal; /*the previous legal breakpoint*/
+static halfword rejected_cur_p; /*the last |cur_p| that has been rejected*/
+static boolean before_rejected_cur_p; /*|cur_p| is still before |rejected_cur_p|?*/
+
+/* Let's state the principles of the delta nodes more precisely and concisely,
+ so that the following programs will be less obscure. For each legal
+ breakpoint~|p| in the paragraph, we define two quantities $\alpha(p)$ and
+ $\beta(p)$ such that the length of material in a line from breakpoint~|p|
+ to breakpoint~|q| is $\gamma+\beta(q)-\alpha(p)$, for some fixed $\gamma$.
+ Intuitively, $\alpha(p)$ and $\beta(q)$ are the total length of material from
+ the beginning of the paragraph to a point ``after'' a break at |p| and to a
+ point ``before'' a break at |q|; and $\gamma$ is the width of an empty line,
+ namely the length contributed by \.{\\leftskip} and \.{\\rightskip}.
+
+ Suppose, for example, that the paragraph consists entirely of alternating
+ boxes and glue skips; let the boxes have widths $x_1\ldots x_n$ and
+ let the skips have widths $y_1\ldots y_n$, so that the paragraph can be
+ represented by $x_1y_1\ldots x_ny_n$. Let $p_i$ be the legal breakpoint
+ at $y_i$; then $\alpha(p_i)=x_1+y_1+\cdots+x_i+y_i$, and $\beta(p_i)=
+ x_1+y_1+\cdots+x_i$. To check this, note that the length of material from
+ $p_2$ to $p_5$, say, is $\gamma+x_3+y_3+x_4+y_4+x_5=\gamma+\beta(p_5)
+ -\alpha(p_2)$.
+
+ The quantities $\alpha$, $\beta$, $\gamma$ involve glue stretchability and
+ shrinkability as well as a natural width. If we were to compute $\alpha(p)$
+ and $\beta(p)$ for each |p|, we would need multiple precision arithmetic, and
+ the multiprecise numbers would have to be kept in the active nodes.
+ \TeX\ avoids this problem by working entirely with relative differences
+ or ``deltas.'' Suppose, for example, that the active list contains
+ $a_1\,\delta_1\,a_2\,\delta_2\,a_3$, where the |a|'s are active breakpoints
+ and the $\delta$'s are delta nodes. Then $\delta_1=\alpha(a_1)-\alpha(a_2)$
+ and $\delta_2=\alpha(a_2)-\alpha(a_3)$. If the line breaking algorithm is
+ currently positioned at some other breakpoint |p|, the |active_width| array
+ contains the value $\gamma+\beta(p)-\alpha(a_1)$. If we are scanning through
+ the list of active nodes and considering a tentative line that runs from
+ $a_2$ to~|p|, say, the |cur_active_width| array will contain the value
+ $\gamma+\beta(p)-\alpha(a_2)$. Thus, when we move from $a_2$ to $a_3$,
+ we want to add $\alpha(a_2)-\alpha(a_3)$ to |cur_active_width|; and this
+ is just $\delta_2$, which appears in the active list between $a_2$ and
+ $a_3$. The |background| array contains $\gamma$. The |break_width| array
+ will be used to calculate values of new delta nodes when the active
+ list is being updated.
+*/
+
+/* The heart of the line-breaking procedure is `|try_break|', a subroutine
+ that tests if the current breakpoint |cur_p| is feasible, by running
+ through the active list to see what lines of text can be made from active
+ nodes to~|cur_p|. If feasible breaks are possible, new break nodes are
+ created. If |cur_p| is too far from an active node, that node is
+ deactivated.
+
+ The parameter |pi| to |try_break| is the penalty associated
+ with a break at |cur_p|; we have |pi=eject_penalty| if the break is forced,
+ and |pi=inf_penalty| if the break is illegal.
+
+ The other parameter, |break_type|, is set to |hyphenated_node| or |unhyphenated_node|,
+ depending on whether or not the current break is at a |disc_node|. The
+ end of a paragraph is also regarded as `|hyphenated_node|'; this case is
+ distinguishable by the condition |cur_p=null|.
+*/
+
+
+
+static integer internal_pen_inter; /* running \.{\\localinterlinepenalty} */
+static integer internal_pen_broken; /* running \.{\\localbrokenpenalty} */
+static halfword internal_left_box; /* running \.{\\localleftbox} */
+static integer internal_left_box_width; /* running \.{\\localleftbox} width */
+static halfword init_internal_left_box; /* running \.{\\localleftbox} */
+static integer init_internal_left_box_width; /* running \.{\\localleftbox} width */
+static halfword internal_right_box; /* running \.{\\localrightbox} */
+static integer internal_right_box_width; /* running \.{\\localrightbox} width */
+
+static scaled disc_width [10] = {0}; /* the length of discretionary material preceding a break*/
+
+/* As we consider various ways to end a line at |cur_p|, in a given line number
+ class, we keep track of the best total demerits known, in an array with
+ one entry for each of the fitness classifications. For example,
+ |minimal_demerits[tight_fit]| contains the fewest total demerits of feasible
+ line breaks ending at |cur_p| with a |tight_fit| line; |best_place[tight_fit]|
+ points to the passive node for the break before~|cur_p| that achieves such
+ an optimum; and |best_pl_line[tight_fit]| is the |line_number| field in the
+ active node corresponding to |best_place[tight_fit]|. When no feasible break
+ sequence is known, the |minimal_demerits| entries will be equal to
+ |awful_bad|, which is $2^{30}-1$. Another variable, |minimum_demerits|,
+ keeps track of the smallest value in the |minimal_demerits| array.
+*/
+
+
+static integer minimal_demerits[4]; /* best total demerits known for current
+ line class and position, given the fitness */
+static integer minimum_demerits; /* best total demerits known for current line class
+ and position */
+static halfword best_place[4]; /* how to achieve |minimal_demerits| */
+static halfword best_pl_line[4]; /*corresponding line number*/
+
+
+/*
+ The length of lines depends on whether the user has specified
+\.{\\parshape} or \.{\\hangindent}. If |par_shape_ptr| is not null, it
+points to a $(2n+1)$-word record in |mem|, where the |vinfo| in the first
+word contains the value of |n|, and the other $2n$ words contain the left
+margins and line lengths for the first |n| lines of the paragraph; the
+specifications for line |n| apply to all subsequent lines. If
+|par_shape_ptr=null|, the shape of the paragraph depends on the value of
+|n=hang_after|; if |n>=0|, hanging indentation takes place on lines |n+1|,
+|n+2|, \dots, otherwise it takes place on lines 1, \dots, $\vert
+n\vert$. When hanging indentation is active, the left margin is
+|hang_indent|, if |hang_indent>=0|, else it is 0; the line length is
+$|hsize|-\vert|hang_indent|\vert$. The normal setting is
+|par_shape_ptr=null|, |hang_after=1|, and |hang_indent=0|.
+Note that if |hang_indent=0|, the value of |hang_after| is irrelevant.
+@^length of lines@> @^hanging indentation@>
+*/
+
+static halfword easy_line; /*line numbers |>easy_line| are equivalent in break nodes*/
+static halfword last_special_line; /*line numbers |>last_special_line| all have the same width */
+static scaled first_width; /*the width of all lines |<=last_special_line|, if
+ no \.{\\parshape} has been specified*/
+static scaled second_width; /*the width of all lines |>last_special_line|*/
+static scaled first_indent; /*left margin to go with |first_width|*/
+static scaled second_indent; /*left margin to go with |second_width|*/
+
+static halfword best_bet; /*use this passive node and its predecessors */
+static integer fewest_demerits; /*the demerits associated with |best_bet|*/
+static halfword best_line; /*line number following the last line of the new paragraph*/
+static integer actual_looseness; /*the difference between |line_number(best_bet)|
+ and the optimum |best_line|*/
+static integer line_diff; /*the difference between the current line number and
+ the optimum |best_line|*/
+
+
+
+/* \TeX\ makes use of the fact that |hlist_node|, |vlist_node|,
+ |rule_node|, |ins_node|, |mark_node|, |adjust_node|,
+ |disc_node|, |whatsit_node|, and |math_node| are at the low end of the
+ type codes, by permitting a break at glue in a list if and only if the
+ |type| of the previous node is less than |math_node|. Furthermore, a
+ node is discarded after a break if its type is |math_node| or~more.
+*/
+
+#define do_all_six(a) a(1);a(2);a(3);a(4);a(5);a(6);a(7)
+#define do_seven_eight(a) if (pdf_adjust_spacing > 1) { a(8);a(9); }
+#define do_all_eight(a) do_all_six(a); do_seven_eight(a)
+#define do_one_seven_eight(a) a(1); do_seven_eight(a)
+
+#define store_background(a) {active_width[a]=background[a];}
+
+#define act_width active_width[1] /*length from first active node to current node*/
+
+#define kern_break() { \
+ if ((!is_char_node(vlink(cur_p))) && auto_breaking) \
+ if (type(vlink(cur_p))==glue_node) \
+ ext_try_break(0,unhyphenated_node, pdf_adjust_spacing, \
+ par_shape_ptr, adj_demerits, \
+ tracing_paragraphs, pdf_protrude_chars, \
+ line_penalty, last_line_fit, \
+ double_hyphen_demerits, final_hyphen_demerits,first_p,cur_p); \
+ if (type(cur_p)!=math_node) act_width+=width(cur_p); \
+ else act_width+=surround(cur_p); \
+ }
+
+#define clean_up_the_memory() { \
+ q=vlink(active); \
+ while (q!=active) { \
+ cur_p=vlink(q); \
+ if (type(q)==delta_node) flush_node(q); \
+ else flush_node(q); \
+ q=cur_p; \
+ } \
+ q=passive; \
+ while (q!=null) { \
+ cur_p=vlink(q); \
+ flush_node(q); \
+ q=cur_p; \
+ } \
+ }
+
+#define inf_bad 10000 /* infinitely bad value */
+
+static boolean do_last_line_fit; /* special algorithm for last line of paragraph? */
+static scaled fill_width[4]; /* infinite stretch components of |par_fill_skip| */
+static scaled best_pl_short[4]; /* |shortfall| corresponding to |minimal_demerits| */
+static scaled best_pl_glue[4]; /*corresponding glue stretch or shrink */
+
+#define awful_bad 07777777777 /* more than a billion demerits */
+
+#define before 0 /* |subtype| for math node that introduces a formula */
+#define after 1 /* |subtype| for math node that winds up a formula */
+
+#define reset_disc_width(a) disc_width[(a)] = 0
+
+#define add_disc_width_to_break_width(a) break_width[(a)] += disc_width[(a)]
+#define sub_disc_width_from_active_width(a) active_width[(a)] -= disc_width[(a)]
+
+#define add_char_shrink(a,b) a += char_shrink((b))
+#define add_char_stretch(a,b) a += char_stretch((b))
+#define sub_char_shrink(a,b) a -= char_shrink((b))
+#define sub_char_stretch(a,b) a -= char_stretch((b))
+
+#define add_kern_shrink(a,b) a += kern_shrink((b))
+#define add_kern_stretch(a,b) a += kern_stretch((b))
+#define sub_kern_shrink(a,b) a -= kern_shrink((b))
+#define sub_kern_stretch(a,b) a -= kern_stretch((b))
+
+
+/* When we insert a new active node for a break at |cur_p|, suppose this
+ new node is to be placed just before active node |a|; then we essentially
+ want to insert `$\delta\,|cur_p|\,\delta^\prime$' before |a|, where
+ $\delta=\alpha(a)-\alpha(|cur_p|)$ and $\delta^\prime=\alpha(|cur_p|)-\alpha(a)$
+ in the notation explained above. The |cur_active_width| array now holds
+ $\gamma+\beta(|cur_p|)-\alpha(a)$; so $\delta$ can be obtained by
+ subtracting |cur_active_width| from the quantity $\gamma+\beta(|cur_p|)-
+ \alpha(|cur_p|)$. The latter quantity can be regarded as the length of a
+ line ``from |cur_p| to |cur_p|''; we call it the |break_width| at |cur_p|.
+
+ The |break_width| is usually negative, since it consists of the background
+ (which is normally zero) minus the width of nodes following~|cur_p| that are
+ eliminated after a break. If, for example, node |cur_p| is a glue node, the
+ width of this glue is subtracted from the background; and we also look
+ ahead to eliminate all subsequent glue and penalty and kern and math
+ nodes, subtracting their widths as well.
+
+ Kern nodes do not disappear at a line break unless they are |explicit|.
+*/
+
+/* assigned-to globals:
+ break_width[]
+*/
+/* used globals:
+ disc_width[]
+ line_break_dir
+*/
+static void
+compute_break_width (int break_type, int pdf_adjust_spacing, halfword p
+ /*, halfword s*/) {
+ halfword s; /* glue and other 'whitespace' to be skipped after a break
+ * used if unhyphenated, or post_break==empty */
+ s=p;
+ if (break_type>unhyphenated_node && p!=null) {
+ /*@<Compute the discretionary |break_width| values@>;*/
+ /* When |p| is a discretionary break, the length of a line
+ ``from |p| to |p|'' has to be defined properly so
+ that the other calculations work out. Suppose that the
+ pre-break text at |p| has length $l_0$, the post-break
+ text has length $l_1$, and the replacement text has length
+ |l|. Suppose also that |q| is the node following the
+ replacement text. Then length of a line from |p| to |q|
+ will be computed as $\gamma+\beta(q)-\alpha(|p|)$, where
+ $\beta(q)=\beta(|p|)-l_0+l$. The actual length will be
+ the background plus $l_1$, so the length from |p| to
+ |p| should be $\gamma+l_0+l_1-l$. If the post-break text
+ of the discretionary is empty, a break may also discard~|q|;
+ in that unusual case we subtract the length of~|q| and any
+ other nodes that will be discarded after the discretionary
+ break.
+
+ TH: I don't quite understand the above remarks.
+
+ The value of $l_0$ need not be computed, since |line_break|
+ will put it into the global variable |disc_width| before
+ calling |try_break|.
+ */
+ /* In case of nested discretionaries, we always follow the no_break
+ path, as we are talking about the breaking on _this_ position.
+ */
+
+ halfword v;
+ for (v=vlink_no_break(p); v!=null; v=vlink(v)) {
+ /* @<Subtract the width of node |v| from |break_width|@>; */
+ /* Replacement texts and discretionary texts are supposed to contain
+ only character nodes, kern nodes, and box or rule nodes.*/
+ if (is_char_node(v)) {
+ if (is_rotated(line_break_dir)) {
+ break_width[1] -= (glyph_height(v)+glyph_depth(v));
+ } else {
+ break_width[1] -= glyph_width(v);
+ }
+ if ((pdf_adjust_spacing > 1) && check_expand_pars(font(v))) {
+ set_prev_char_p(v);
+ sub_char_stretch(break_width[8],v);
+ sub_char_shrink(break_width[9],v);
+ }
+ } else {
+ switch (type(v)) {
+ case hlist_node:
+ case vlist_node:
+ if (!(dir_orthogonal(dir_primary[box_dir(v)],
+ dir_primary[line_break_dir])))
+ break_width[1] -= width(v);
+ else
+ break_width[1] -= (depth(v)+height(v));
+ break;
+ case kern_node:
+ if ((pdf_adjust_spacing > 1) && (subtype(v) == normal)) {
+ sub_kern_stretch(break_width[8],v);
+ sub_kern_shrink(break_width[9],v);
+ }
+ /* fall through */
+ case rule_node:
+ break_width[1] -= width(v);
+ break;
+ case disc_node:
+ assert(vlink(v)==null); /* discs are _always_ last */
+ v = no_break(v);
+ break;
+ default:
+ tconfusion("disc1");
+ break;
+ }
+ }
+ }
+
+ for (v=vlink_post_break(p); v!=null; v=vlink(v)) {
+ /* @<Add the width of node |v| to |break_width|@>; */
+ if (is_char_node(v)) {
+ if (is_rotated(line_break_dir))
+ break_width[1] += (glyph_height(v)+glyph_depth(v));
+ else
+ break_width[1] += glyph_width(v);
+ if ((pdf_adjust_spacing > 1) && check_expand_pars(font(v))) {
+ set_prev_char_p(v);
+ add_char_stretch(break_width[8],v);
+ add_char_shrink(break_width[9],v);
+ }
+ } else {
+ switch (type(v)) {
+ case hlist_node:
+ case vlist_node:
+ if (!(dir_orthogonal(dir_primary[box_dir(v)],
+ dir_primary[line_break_dir])))
+ break_width[1] += width(v);
+ else
+ break_width[1] += (depth(v)+height(v));
+ break;
+ case kern_node:
+ if ((pdf_adjust_spacing > 1) && (subtype(v) == normal)) {
+ add_kern_stretch(break_width[8],v);
+ add_kern_shrink(break_width[9],v);
+ }
+ /* fall through */
+ case rule_node:
+ break_width[1] += width(v);
+ break;
+ case disc_node:
+ assert(vlink(v)==null);
+ v = no_break(v);
+ break;
+ default:
+ tconfusion("disc2");
+ }
+ }
+ }
+
+ do_one_seven_eight(add_disc_width_to_break_width);
+ if (vlink_post_break(p)==null) {
+ s=vlink(p); /* no post_break: 'skip' any 'whitespace' following */
+ } else {
+ s=null;
+ }
+ } else {
+ s = p; /* unhyphenated: we need to 'skip' any 'whitespace' following */
+ }
+ while (s!=null) {
+ switch (type(s)) {
+ case glue_node:
+ /*@<Subtract glue from |break_width|@>;*/
+ {halfword v=glue_ptr(s);
+ break_width[1] -= width(v);
+ break_width[2+stretch_order(v)] -= stretch(v);
+ break_width[7] -= shrink(v);
+ }break;
+ case penalty_node:
+ break;
+ case math_node:
+ break_width[1] -= surround(s);
+ break;
+ case kern_node:
+ if (subtype(s)!=explicit)
+ return;
+ else
+ break_width[1] -= width(s);
+ break;
+ default:
+ return;
+ };
+ s=vlink(s);
+ }
+}
+
+
+static void
+print_break_node(halfword q, fitness_value fit_class,
+ quarterword break_type, halfword cur_p) {
+ /* @<Print a symbolic description of the new break node@> */
+ tprint_nl("@@");
+ print_int(serial(passive));
+ tprint(": line ");
+ print_int(line_number(q)-1);
+ print_char('.');
+ print_int(fit_class);
+ if (break_type==hyphenated_node)
+ print_char('-');
+ tprint(" t=");
+ print_int(total_demerits(q));
+ if (do_last_line_fit) {
+ /*@<Print additional data in the new active node@>; */
+ tprint(" s=");
+ print_scaled(active_short(q));
+ if (cur_p==null)
+ tprint(" a=");
+ else
+ tprint(" g=");
+ print_scaled(active_glue(q));
+ }
+ tprint(" -> @@");
+ if (prev_break(passive)==null)
+ print_char('0');
+ else
+ print_int(serial(prev_break(passive)));
+}
+
+
+static void
+print_feasible_break(halfword cur_p, pointer r, halfword b, integer pi,
+ integer d, boolean artificial_demerits) {
+ /* @<Print a symbolic description of this feasible break@>;*/
+ if (printed_node!=cur_p) {
+ /* @<Print the list between |printed_node| and |cur_p|, then
+ set |printed_node:=cur_p|@>;*/
+ tprint_nl("");
+ if (cur_p==null) {
+ short_display(vlink(printed_node));
+ } else {
+ halfword save_link=vlink(cur_p);
+ vlink(cur_p)=null;
+ tprint_nl("");
+ short_display(vlink(printed_node));
+ vlink(cur_p)=save_link;
+ }
+ printed_node=cur_p;
+ }
+ tprint_nl("@");
+ if (cur_p==null) {
+ tprint_esc("par");
+ } else if (type(cur_p)!=glue_node) {
+ if (type(cur_p)==penalty_node) tprint_esc("penalty");
+ else if (type(cur_p)==disc_node) tprint_esc("discretionary");
+ else if (type(cur_p)==kern_node) tprint_esc("kern");
+ else tprint_esc("math");
+ }
+ tprint(" via @@");
+ if (break_node(r)==null)
+ print_char('0');
+ else
+ print_int(serial(break_node(r)));
+ tprint(" b=");
+ if (b>inf_bad)
+ print_char('*');
+ else
+ print_int(b);
+ tprint(" p=");
+ print_int(pi);
+ tprint(" d=");
+ if (artificial_demerits)
+ print_char('*');
+ else
+ print_int(d);
+}
+
+#define add_disc_width_to_active_width(a) active_width[a] += disc_width[a]
+#define update_width(a) cur_active_width[a] += varmem[(r+(a))].cint
+
+#define set_break_width_to_background(a) break_width[a]=background[(a)]
+
+#define convert_to_break_width(a) \
+ varmem[(prev_r+(a))].cint -= (cur_active_width[(a)]+break_width[(a)])
+
+#define store_break_width(a) active_width[(a)]=break_width[(a)]
+
+#define new_delta_to_break_width(a) \
+ varmem[(q+(a))].cint=break_width[(a)]-cur_active_width[(a)]
+
+#define new_delta_from_break_width(a) \
+ varmem[(q+(a))].cint=cur_active_width[(a)]-break_width[(a)]
+
+#define copy_to_cur_active(a) cur_active_width[(a)]=active_width[(a)]
+
+#define combine_two_deltas(a) varmem[(prev_r+(a))].cint += varmem[(r+(a))].cint
+#define downdate_width(a) cur_active_width[(a)] -= varmem[(prev_r+(a))].cint
+#define update_active(a) active_width[(a)]+=varmem[(r+(a))].cint
+
+#define total_font_stretch cur_active_width[8]
+#define total_font_shrink cur_active_width[9]
+
+#define max_dimen 07777777777 /* $2^{30}-1$ */
+
+#define left_side 0
+#define right_side 1
+
+
+#define cal_margin_kern_var(a) { \
+ character(cp) = character((a)); \
+ font(cp) = font((a)); \
+ do_subst_font(cp, 1000); \
+ if (font(cp) != font((a))) \
+ margin_kern_stretch += (left_pw((a)) - left_pw(cp)); \
+ font(cp) = font((a)); \
+ do_subst_font(cp, -1000); \
+ if (font(cp) != font((a))) \
+ margin_kern_shrink += (left_pw(cp) - left_pw((a))); \
+ }
+
+static void
+ext_try_break(integer pi,
+ quarterword break_type,
+ int pdf_adjust_spacing,
+ int par_shape_ptr,
+ int adj_demerits,
+ int tracing_paragraphs,
+ int pdf_protrude_chars,
+ int line_penalty,
+ int last_line_fit,
+ int double_hyphen_demerits,
+ int final_hyphen_demerits,
+ halfword first_p,
+ halfword cur_p) {
+ /* CONTINUE,DEACTIVATE,FOUND,NOT_FOUND; */
+ pointer r; /* runs through the active list */
+ scaled margin_kern_stretch;
+ scaled margin_kern_shrink;
+ halfword lp, rp, cp;
+ halfword prev_r; /* stays a step behind |r| */
+ halfword prev_prev_r; /*a step behind |prev_r|, if |type(prev_r)=delta_node|*/
+ halfword old_l; /* maximum line number in current equivalence class of lines */
+ boolean no_break_yet; /* have we found a feasible break at |cur_p|? */
+ halfword q; /*points to a new node being created*/
+ halfword l; /*line number of current active node*/
+ boolean node_r_stays_active; /*should node |r| remain in the active list?*/
+ scaled line_width; /*the current line will be justified to this width*/
+ fitness_value fit_class; /*possible fitness class of test line*/
+ halfword b; /*badness of test line*/
+ integer d; /*demerits of test line*/
+ boolean artificial_demerits; /*has |d| been forced to zero?*/
+
+ scaled shortfall; /*used in badness calculations*/
+ scaled g; /*glue stretch or shrink of test line, adjustment for last line*/
+ scaled cur_active_width[10] = {0}; /*distance from current active node*/
+
+ line_width=0; g=0; prev_prev_r=null;
+ /*@<Make sure that |pi| is in the proper range@>;*/
+ if (pi>=inf_penalty) {
+ return; /* this breakpoint is inhibited by infinite penalty */
+ } else if (pi<=-inf_penalty) {
+ pi=eject_penalty; /*this breakpoint will be forced*/
+ }
+
+ no_break_yet=true;
+ prev_r=active;
+ old_l=0;
+ do_all_eight(copy_to_cur_active);
+
+ while (1) {
+ r=vlink(prev_r);
+ /* @<If node |r| is of type |delta_node|, update |cur_active_width|,
+ set |prev_r| and |prev_prev_r|, then |goto continue|@>; */
+ /* The following code uses the fact that |type(active)<>delta_node| */
+ if (type(r)==delta_node) {
+ do_all_eight(update_width); /* IMPLICIT ,r */
+ prev_prev_r=prev_r;
+ prev_r=r;
+ continue;
+ }
+ /* @<If a line number class has ended, create new active nodes for
+ the best feasible breaks in that class; then |return|
+ if |r=active|, otherwise compute the new |line_width|@>; */
+ /* The first part of the following code is part of \TeX's inner loop, so
+ we don't want to waste any time. The current active node, namely node |r|,
+ contains the line number that will be considered next. At the end of the
+ list we have arranged the data structure so that |r=active| and
+ |line_number(active)>old_l|.
+ */
+ l=line_number(r);
+ if (l>old_l) { /* now we are no longer in the inner loop */
+ if ((minimum_demerits<awful_bad)&&((old_l!=easy_line)||(r==active))) {
+ /*@<Create new active nodes for the best feasible breaks just found@>*/
+ /* It is not necessary to create new active nodes having |minimal_demerits|
+ greater than
+ |minimum_demerits+abs(adj_demerits)|, since such active nodes will never
+ be chosen in the final paragraph breaks. This observation allows us to
+ omit a substantial number of feasible breakpoints from further consideration.
+ */
+ if (no_break_yet) {
+ no_break_yet=false;
+ do_all_eight(set_break_width_to_background);
+ compute_break_width(break_type, pdf_adjust_spacing, cur_p);
+ }
+ /* @<Insert a delta node to prepare for breaks at |cur_p|@>;*/
+ /* We use the fact that |type(active)<>delta_node|.*/
+ if (type(prev_r)==delta_node) {/* modify an existing delta node */
+ do_all_eight(convert_to_break_width); /* IMPLICIT prev_r */
+ } else if (prev_r==active) { /* no delta node needed at the beginning */
+ do_all_eight(store_break_width);
+ } else {
+ q=new_node(delta_node,0);
+ vlink(q)=r;
+ do_all_eight(new_delta_to_break_width); /* IMPLICIT q */
+ vlink(prev_r)=q;
+ prev_prev_r=prev_r;
+ prev_r=q;
+ }
+
+ if (abs(adj_demerits)>=awful_bad-minimum_demerits)
+ minimum_demerits=awful_bad-1;
+ else
+ minimum_demerits += abs(adj_demerits);
+ for (fit_class=very_loose_fit;fit_class<=tight_fit;fit_class++) {
+ if (minimal_demerits[fit_class]<=minimum_demerits) {
+ /* @<Insert a new active node from |best_place[fit_class]|
+ to |cur_p|@>; */
+ /* When we create an active node, we also create the corresponding
+ passive node.
+ */
+ q=new_node(passive_node,0);
+ vlink(q)=passive;
+ passive=q;
+ cur_break(q)=cur_p;
+ incr(pass_number);
+ serial(q)=pass_number;
+ prev_break(q)=best_place[fit_class];
+ /*Here we keep track of the subparagraph penalties in the break nodes*/
+ passive_pen_inter(q)=internal_pen_inter;
+ passive_pen_broken(q)=internal_pen_broken;
+ passive_last_left_box(q)=internal_left_box;
+ passive_last_left_box_width(q)=internal_left_box_width;
+ if (prev_break(q)!=null) {
+ passive_left_box(q)=passive_last_left_box(prev_break(q));
+ passive_left_box_width(q)=passive_last_left_box_width(prev_break(q));
+ } else {
+ passive_left_box(q)=init_internal_left_box;
+ passive_left_box_width(q)=init_internal_left_box_width;
+ }
+ passive_right_box(q)=internal_right_box;
+ passive_right_box_width(q)=internal_right_box_width;
+ q=new_node(break_type,fit_class);
+ break_node(q)=passive;
+ line_number(q)=best_pl_line[fit_class]+1;
+ total_demerits(q)=minimal_demerits[fit_class];
+ if (do_last_line_fit) {
+ /*@<Store \(a)additional data in the new active node@>*/
+ /* Here we save these data in the active node
+ representing a potential line break.*/
+ active_short(q)=best_pl_short[fit_class];
+ active_glue(q)=best_pl_glue[fit_class];
+ }
+ vlink(q)=r;
+ vlink(prev_r)=q;
+ prev_r=q;
+ if (tracing_paragraphs>0)
+ print_break_node(q,fit_class,break_type,cur_p);
+ }
+ minimal_demerits[fit_class]=awful_bad;
+ }
+ minimum_demerits=awful_bad;
+ /* @<Insert a delta node to prepare for the next active node@>;*/
+ /* When the following code is performed, we will have just inserted at
+ least one active node before |r|, so |type(prev_r)<>delta_node|.
+ */
+ if (r!=active) {
+ q=new_node(delta_node,0);
+ vlink(q)=r;
+ do_all_eight(new_delta_from_break_width); /* IMPLICIT q */
+ vlink(prev_r)=q;
+ prev_prev_r=prev_r;
+ prev_r=q;
+ }
+ }
+ if (r==active)
+ return;
+ /*@<Compute the new line width@>;*/
+ /* When we come to the following code, we have just encountered
+ the first active node~|r| whose |line_number| field contains
+ |l|. Thus we want to compute the length of the $l\mskip1mu$th
+ line of the current paragraph. Furthermore, we want to set
+ |old_l| to the last number in the class of line numbers
+ equivalent to~|l|.
+ */
+ if (l>easy_line) {
+ old_l=max_halfword-1;
+ line_width=second_width;
+ } else {
+ old_l=l;
+ if (l>last_special_line) {
+ line_width=second_width;
+ } else if (par_shape_ptr==null) {
+ line_width=first_width;
+ } else {
+ line_width=varmem[(par_shape_ptr+2*l+1)].cint;
+ }
+ }
+ }
+ /* /If a line number class has ended, create new active nodes for
+ the best feasible breaks in that class; then |return|
+ if |r=active|, otherwise compute the new |line_width|@>; */
+
+ /* @<Consider the demerits for a line from |r| to |cur_p|;
+ deactivate node |r| if it should no longer be active;
+ then |goto continue| if a line from |r| to |cur_p| is infeasible,
+ otherwise record a new feasible break@>; */
+ artificial_demerits=false;
+ shortfall = line_width
+ - cur_active_width[1]
+ -(( break_node(r)==null)
+ ? init_internal_left_box_width
+ : passive_last_left_box_width(break_node(r)))
+ - internal_right_box_width;
+ if (pdf_protrude_chars > 1) {
+ halfword l, o;
+ l = (break_node(r) == null) ? first_p : cur_break(break_node(r));
+ if (cur_p==null) {
+ o = null;
+ } else { /* TODO if (is_character_node(alink(cur_p))) */
+ o = alink(cur_p);
+ assert(vlink(o)==cur_p);
+ }
+ /* let's look at the right margin first */
+ if ((cur_p != null) && (type(cur_p) == disc_node) && (vlink_pre_break(cur_p) != null)) {
+ /* a |disc_node| with non-empty |pre_break|, protrude the last char of |pre_break| */
+ o = tlink_pre_break(cur_p);
+ } else {
+ o = find_protchar_right(l, o);
+ }
+ /* now the left margin */
+ if ((l != null) && (type(l) == disc_node) && (vlink_post_break(l) != null)) {
+ /* FIXME: first 'char' could be a disc! */
+ l = vlink_post_break(l); /* protrude the first char */
+ } else {
+ l = find_protchar_left(l, true);
+ }
+ shortfall += (left_pw(l) + right_pw(o));
+ }
+ if ((shortfall != 0) && (pdf_adjust_spacing > 1)) {
+ margin_kern_stretch = 0;
+ margin_kern_shrink = 0;
+ if (pdf_protrude_chars > 1) {
+ /* @<Calculate variations of marginal kerns@>;*/
+ lp = last_leftmost_char;
+ rp = last_rightmost_char;
+ cp = raw_glyph_node();
+ if (lp != null) {
+ cal_margin_kern_var(lp);
+ }
+ if (rp != null) {
+ cal_margin_kern_var(rp);
+ }
+ flush_node(cp);
+ }
+ if ((shortfall > 0) && ((total_font_stretch + margin_kern_stretch) > 0)) {
+ if ((total_font_stretch + margin_kern_stretch) > shortfall)
+ shortfall = ((total_font_stretch + margin_kern_stretch) /
+ (max_stretch_ratio / cur_font_step)) / 2;
+ else
+ shortfall -= (total_font_stretch + margin_kern_stretch);
+ } else if ((shortfall < 0) && ((total_font_shrink + margin_kern_shrink) > 0)) {
+ if ((total_font_shrink + margin_kern_shrink) > -shortfall)
+ shortfall = -((total_font_shrink + margin_kern_shrink) /
+ (max_shrink_ratio / cur_font_step)) / 2;
+ else
+ shortfall += (total_font_shrink + margin_kern_shrink);
+ }
+ }
+ if (shortfall>0) {
+ /* @<Set the value of |b| to the badness for stretching the line,
+ and compute the corresponding |fit_class|@> */
+
+ /* When a line must stretch, the available stretchability can be
+ found in the subarray |cur_active_width[2..6]|, in units of
+ points, sfi, fil, fill and filll.
+
+ The present section is part of \TeX's inner loop, and it is
+ most often performed when the badness is infinite; therefore
+ it is worth while to make a quick test for large width excess
+ and small stretchability, before calling the |badness|
+ subroutine. @^inner loop@> */
+
+ if ((cur_active_width[3]!=0)||(cur_active_width[4]!=0)||
+ (cur_active_width[5]!=0)||(cur_active_width[6]!=0)) {
+ if (do_last_line_fit) {
+ if (cur_p==null) { /* the last line of a paragraph */
+ /* @<Perform computations for last line and |goto found|@>;*/
+
+ /* Here we compute the adjustment |g| and badness |b| for
+ a line from |r| to the end of the paragraph. When any
+ of the criteria for adjustment is violated we fall
+ through to the normal algorithm.
+
+ The last line must be too short, and have infinite
+ stretch entirely due to |par_fill_skip|.*/
+ if ((active_short(r)==0)||(active_glue(r)<=0))
+ /* previous line was neither stretched nor shrunk, or
+ was infinitely bad*/
+ goto NOT_FOUND;
+ if ((cur_active_width[3]!=fill_width[0])||
+ (cur_active_width[4]!=fill_width[1])||
+ (cur_active_width[5]!=fill_width[2])||
+ (cur_active_width[6]!=fill_width[3]))
+ /* infinite stretch of this line not entirely due to
+ |par_fill_skip| */
+ goto NOT_FOUND;
+ if (active_short(r)>0)
+ g=cur_active_width[2];
+ else
+ g=cur_active_width[7];
+ if (g<=0)
+ /*no finite stretch resp.\ no shrink*/
+ goto NOT_FOUND;
+ arith_error=false;
+ g=fract(g,active_short(r),active_glue(r),max_dimen);
+ if (last_line_fit<1000)
+ g=fract(g,last_line_fit,1000,max_dimen);
+ if (arith_error) {
+ if (active_short(r)>0)
+ g=max_dimen;
+ else
+ g=-max_dimen;
+ }
+ if (g>0) {
+ /*@<Set the value of |b| to the badness of the last line
+ for stretching, compute the corresponding |fit_class,
+ and |goto found||@>*/
+ /* These badness computations are rather similar to
+ those of the standard algorithm, with the adjustment
+ amount |g| replacing the |shortfall|.*/
+ if (g>shortfall)
+ g=shortfall;
+ if (g>7230584) {
+ if (cur_active_width[2]<1663497) {
+ b=inf_bad;
+ fit_class=very_loose_fit;
+ goto FOUND;
+ }
+ }
+ b=badness(g,cur_active_width[2]);
+ if (b>99) { fit_class=very_loose_fit; }
+ else if (b>12) { fit_class=loose_fit; }
+ else { fit_class=decent_fit; }
+ goto FOUND;
+ } else if (g<0) {
+ /*@<Set the value of |b| to the badness of the last line
+ for shrinking, compute the corresponding |fit_class,
+ and |goto found||@>;*/
+ if (-g>cur_active_width[7])
+ g=-cur_active_width[7];
+ b=badness(-g,cur_active_width[7]);
+ if (b>12) fit_class=tight_fit;
+ else fit_class=decent_fit;
+ goto FOUND;
+ }
+ }
+ NOT_FOUND:
+ shortfall=0;
+ }
+ b=0;
+ fit_class=decent_fit; /* infinite stretch */
+ } else {
+ if (shortfall>7230584 && cur_active_width[2]<1663497) {
+ b=inf_bad;
+ fit_class=very_loose_fit;
+ } else {
+ b=badness(shortfall,cur_active_width[2]);
+ if (b>99) { fit_class=very_loose_fit; }
+ else if (b>12) { fit_class=loose_fit; }
+ else { fit_class=decent_fit; }
+ }
+ }
+ } else {
+ /* Set the value of |b| to the badness for shrinking the line,
+ and compute the corresponding |fit_class|@>; */
+ /* Shrinkability is never infinite in a paragraph; we can shrink
+ the line from |r| to |cur_p| by at most
+ |cur_active_width[7]|.*/
+ if (-shortfall>cur_active_width[7])
+ b=inf_bad+1;
+ else
+ b=badness(-shortfall,cur_active_width[7]);
+ if (b>12)
+ fit_class=tight_fit;
+ else
+ fit_class=decent_fit;
+ }
+ if (do_last_line_fit) {
+ /* @<Adjust \(t)the additional data for last line@>; */
+ if (cur_p==null) shortfall=0;
+ if (shortfall>0) { g=cur_active_width[2]; }
+ else if (shortfall<0) { g=cur_active_width[7]; }
+ else { g=0;}
+ }
+ FOUND:
+ if ((b>inf_bad)||(pi==eject_penalty)) {
+ /* @<Prepare to deactivate node~|r|, and |goto deactivate| unless
+ there is a reason to consider lines of text from |r| to |cur_p|@> */
+ /* During the final pass, we dare not lose all active nodes, lest we lose
+ touch with the line breaks already found. The code shown here makes
+ sure that such a catastrophe does not happen, by permitting overfull
+ boxes as a last resort. This particular part of \TeX\ was a source of
+ several subtle bugs before the correct program logic was finally
+ discovered; readers who seek to ``improve'' \TeX\ should therefore
+ think thrice before daring to make any changes here.
+ @^overfull boxes@>
+ */
+ if (final_pass && (minimum_demerits==awful_bad) &&
+ (vlink(r)==active) && (prev_r==active)) {
+ artificial_demerits=true; /* set demerits zero, this break is forced */
+ } else if (b>threshold) {
+ goto DEACTIVATE;
+ }
+ node_r_stays_active=false;
+ } else {
+ prev_r=r;
+ if (b>threshold)
+ continue;
+ node_r_stays_active=true;
+ }
+ /* @<Record a new feasible break@>;*/
+ /* When we get to this part of the code, the line from |r| to |cur_p| is
+ feasible, its badness is~|b|, and its fitness classification is
+ |fit_class|. We don't want to make an active node for this break yet,
+ but we will compute the total demerits and record them in the
+ |minimal_demerits| array, if such a break is the current champion among
+ all ways to get to |cur_p| in a given line-number class and fitness
+ class.
+ */
+ if (artificial_demerits) {
+ d=0;
+ } else {
+ /* @<Compute the demerits, |d|, from |r| to |cur_p|@>;*/
+ d=line_penalty+b;
+ if (abs(d)>=10000) d=100000000; else d=d*d;
+ if (pi!=0) {
+ if (pi>0) {
+ d += (pi*pi);
+ } else if (pi>eject_penalty) {
+ d -= (pi*pi);
+ }
+ }
+ if ((break_type==hyphenated_node)&&(type(r)==hyphenated_node)) {
+ if (cur_p!=null)
+ d += double_hyphen_demerits;
+ else
+ d += final_hyphen_demerits;
+ }
+ if (abs(fit_class-fitness(r))>1) d=d+adj_demerits;
+ }
+ if (tracing_paragraphs>0)
+ print_feasible_break(cur_p, r, b, pi, d, artificial_demerits);
+ d += total_demerits(r); /*this is the minimum total demerits
+ from the beginning to |cur_p| via |r| */
+ if (d<=minimal_demerits[fit_class]) {
+ minimal_demerits[fit_class]=d;
+ best_place[fit_class]=break_node(r);
+ best_pl_line[fit_class]=l;
+ if (do_last_line_fit) {
+ /* Store \(a)additional data for this feasible break@>; */
+ /* For each feasible break we record the shortfall and glue stretch or
+ shrink (or adjustment).*/
+ best_pl_short[fit_class]=shortfall;
+ best_pl_glue[fit_class]=g;
+ }
+ if (d<minimum_demerits)
+ minimum_demerits=d;
+ }
+ /* /Record a new feasible break */
+ if (node_r_stays_active)
+ continue; /*|prev_r| has been set to |r| */
+ DEACTIVATE:
+ /* @<Deactivate node |r|@>; */
+ /* When an active node disappears, we must delete an adjacent delta node if
+ the active node was at the beginning or the end of the active list, or
+ if it was surrounded by delta nodes. We also must preserve the property
+ that |cur_active_width| represents the length of material from
+ |vlink(prev_r)| to~|cur_p|.*/
+
+ vlink(prev_r)=vlink(r);
+ flush_node(r);
+ if (prev_r==active) {
+ /*@<Update the active widths, since the first active node has been
+ deleted@>*/
+ /* The following code uses the fact that |type(active)<>delta_node|.
+ If the active list has just become empty, we do not need to update the
+ |active_width| array, since it will be initialized when an active
+ node is next inserted.
+ */
+ r=vlink(active);
+ if (type(r)==delta_node) {
+ do_all_eight(update_active); /* IMPLICIT r */
+ do_all_eight(copy_to_cur_active);
+ vlink(active)=vlink(r);
+ flush_node(r);
+ }
+ } else if (type(prev_r)==delta_node){
+ r=vlink(prev_r);
+ if (r==active) {
+ do_all_eight(downdate_width); /* IMPLICIT prev_r */
+ vlink(prev_prev_r)=active;
+ flush_node(prev_r);
+ prev_r=prev_prev_r;
+ } else if (type(r)==delta_node) {
+ do_all_eight(update_width); /* IMPLICIT ,r */
+ do_all_eight(combine_two_deltas); /* IMPLICIT r prev_r */
+ vlink(prev_r)=vlink(r);
+ flush_node(r);
+ }
+ }
+ }
+}
+
+
+void
+ext_do_line_break (boolean d,
+ int pretolerance,
+ int tracing_paragraphs,
+ int tolerance,
+ scaled emergency_stretch,
+ int looseness,
+ int hyphen_penalty,
+ int ex_hyphen_penalty,
+ int pdf_adjust_spacing,
+ halfword par_shape_ptr,
+ int adj_demerits,
+ int pdf_protrude_chars,
+ int line_penalty,
+ int last_line_fit,
+ int double_hyphen_demerits,
+ int final_hyphen_demerits,
+ int hang_indent,
+ int hsize,
+ int hang_after,
+ halfword left_skip,
+ halfword right_skip,
+ int pdf_each_line_height,
+ int pdf_each_line_depth,
+ int pdf_first_line_height,
+ int pdf_last_line_depth,
+ halfword inter_line_penalties_ptr,
+ int inter_line_penalty,
+ int club_penalty,
+ halfword club_penalties_ptr,
+ halfword display_widow_penalties_ptr,
+ halfword widow_penalties_ptr,
+ int display_widow_penalty,
+ int widow_penalty,
+ int broken_penalty,
+ halfword final_par_glue) {
+ /* DONE,DONE1,DONE2,DONE3,DONE4,DONE5,CONTINUE;*/
+ halfword cur_p,q,r,s; /* miscellaneous nodes of temporary interest */
+
+ /* Get ready to start ... */
+ minimum_demerits=awful_bad;
+ minimal_demerits[tight_fit]=awful_bad;
+ minimal_demerits[decent_fit]=awful_bad;
+ minimal_demerits[loose_fit]=awful_bad;
+ minimal_demerits[very_loose_fit]=awful_bad;
+
+ /* We compute the values of |easy_line| and the other local variables relating
+ to line length when the |line_break| procedure is initializing itself. */
+ if (par_shape_ptr==null) {
+ if (hang_indent==0) {
+ last_special_line=0;
+ second_width=hsize;
+ second_indent=0;
+ } else {
+ /* @<Set line length parameters in preparation for hanging indentation@>*/
+ /* We compute the values of |easy_line| and the other local variables relating
+ to line length when the |line_break| procedure is initializing itself. */
+ last_special_line=abs(hang_after);
+ if (hang_after<0) {
+ first_width=hsize-abs(hang_indent);
+ if (hang_indent>=0)
+ first_indent=hang_indent;
+ else
+ first_indent=0;
+ second_width=hsize;
+ second_indent=0;
+ } else {
+ first_width=hsize;
+ first_indent=0;
+ second_width=hsize-abs(hang_indent);
+ if (hang_indent>=0)
+ second_indent=hang_indent;
+ else
+ second_indent=0;
+ }
+ }
+ } else {
+ last_special_line=vinfo(par_shape_ptr+1)-1;
+ second_indent=varmem[(par_shape_ptr+(2*last_special_line))].cint;
+ second_width=varmem[(par_shape_ptr+2*(last_special_line+1)+1)].cint;
+ }
+ if (looseness==0)
+ easy_line=last_special_line;
+ else
+ easy_line=max_halfword;
+
+ no_shrink_error_yet=true;
+ check_shrinkage(left_skip);
+ check_shrinkage(right_skip);
+ q=left_skip;
+ r=right_skip;
+ background[1]=width(q)+width(r);
+ background[2]=0;
+ background[3]=0;
+ background[4]=0;
+ background[5]=0;
+ background[6]=0;
+ background[2+stretch_order(q)] = stretch(q);
+ background[2+stretch_order(r)] += stretch(r);
+ background[7]=shrink(q)+shrink(r);
+ if (pdf_adjust_spacing > 1) {
+ background[8] = 0;
+ background[9] = 0;
+ max_stretch_ratio = -1;
+ max_shrink_ratio = -1;
+ cur_font_step = -1;
+ set_prev_char_p(null);
+ }
+ /* @<Check for special treatment of last line of paragraph@>;*/
+ /* The new algorithm for the last line requires that the stretchability
+ |par_fill_skip| is infinite and the stretchability of |left_skip| plus
+ |right_skip| is finite.
+ */
+ do_last_line_fit=false;
+ if (last_line_fit>0) {
+ q=glue_ptr(last_line_fill);
+ if ((stretch(q)>0)&&(stretch_order(q)>normal)) {
+ if ((background[3]==0)&&(background[4]==0)&&
+ (background[5]==0)&&(background[6]==0)) {
+ do_last_line_fit=true;
+ fill_width[0]=0;
+ fill_width[1]=0;
+ fill_width[2]=0;
+ fill_width[3]=0;
+ fill_width[stretch_order(q)-1]=stretch(q);
+ }
+ }
+ }
+ /* @<DIR: Initialize |dir_ptr| for |line_break|@> */
+ if (dir_ptr!=null) {
+ fprintf(stdout,"-dir_node s %d\n",dir_ptr);
+ flush_node_list(dir_ptr);
+ dir_ptr=null;
+ }
+ /*push_dir(paragraph_dir);*/ /* TODO what was the point of this? */
+
+ /* @<Find optimal breakpoints@>;*/
+ threshold=pretolerance;
+ if (threshold>=0) {
+ if (tracing_paragraphs>0) {
+ begin_diagnostic();
+ tprint_nl("@firstpass");
+ }
+ second_pass=false;
+ final_pass=false;
+ } else {
+ threshold=tolerance;
+ second_pass=true;
+ final_pass=(emergency_stretch<=0);
+ if (tracing_paragraphs>0)
+ begin_diagnostic();
+ }
+
+ while (1) {
+ halfword first_p;
+ halfword nest_stack[10];
+ int nest_index = 0;
+ if (threshold>inf_bad)
+ threshold=inf_bad;
+ /* Create an active breakpoint representing the beginning of the paragraph */
+ q=new_node(unhyphenated_node,decent_fit);
+ vlink(q)=active;
+ break_node(q)=null;
+ line_number(q)=cur_list.pg_field+1;
+ total_demerits(q)=0;
+ active_short(q)=0;
+ active_glue(q)=0;
+ vlink(active)=q;
+ do_all_eight(store_background);
+ passive=null;
+ printed_node=temp_head;
+ pass_number=0;
+ font_in_short_display=null_font;
+ /* /Create an active breakpoint representing the beginning of the paragraph */
+ auto_breaking=true;
+ cur_p=vlink(temp_head);
+ assert(alink(cur_p)==temp_head);
+ /* LOCAL: Initialize with first |local_paragraph| node */
+ if ((type(cur_p)==whatsit_node)&&(subtype(cur_p)==local_par_node)) {
+ internal_pen_inter=local_pen_inter(cur_p);
+ internal_pen_broken=local_pen_broken(cur_p);
+ init_internal_left_box=local_box_left(cur_p);
+ init_internal_left_box_width=local_box_left_width(cur_p);
+ internal_left_box=init_internal_left_box;
+ internal_left_box_width=init_internal_left_box_width;
+ internal_right_box=local_box_right(cur_p);
+ internal_right_box_width=local_box_right_width(cur_p);
+ } else {
+ internal_pen_inter=0;
+ internal_pen_broken=0;
+ init_internal_left_box=null;
+ init_internal_left_box_width=0;
+ internal_left_box=init_internal_left_box;
+ internal_left_box_width=init_internal_left_box_width;
+ internal_right_box=null;
+ internal_right_box_width=0;
+ }
+ /* /LOCAL: Initialize with first |local_paragraph| node */
+ set_prev_char_p (null);
+ prev_legal = null;
+ rejected_cur_p = null;
+ try_prev_break = false;
+ before_rejected_cur_p = false;
+ first_p = cur_p;
+ /* to access the first node of paragraph as the first active node
+ has |break_node=null| */
+ while ((cur_p!=null)&&(vlink(active)!=active)) {
+ /* |try_break| if |cur_p| is a legal breakpoint; on the 2nd pass, also look at disc_nodes. */
+
+ while (is_char_node(cur_p)) {
+ /* Advance \(c)|cur_p| to the node following the present string of characters ;*/
+ /* The code that passes over the characters of words in a paragraph is part of
+ \TeX's inner loop, so it has been streamlined for speed. We use the fact that
+ `\.{\\parfillskip}' glue appears at the end of each paragraph; it is therefore
+ unnecessary to check if |vlink(cur_p)=null| when |cur_p| is a character node.
+ */
+ act_width += (is_rotated(line_break_dir))
+ ? (glyph_height(cur_p)+glyph_depth(cur_p))
+ : glyph_width(cur_p);
+ if ((pdf_adjust_spacing > 1) && check_expand_pars(font(cur_p))) {
+ set_prev_char_p (cur_p);
+ add_char_stretch(active_width[8],cur_p);
+ add_char_shrink(active_width[9],cur_p);
+ }
+ cur_p=vlink(cur_p);
+ while (cur_p==null && nest_index>0) {
+ cur_p = nest_stack[--nest_index];
+ /* fprintf(stderr,"Node Pop %d [%d]\n",nest_index,(int)cur_p); */
+ }
+ }
+ if (cur_p==null) { /* TODO */
+ tconfusion("linebreak_tail");
+ }
+ /* Determine legal breaks: As we move through the hlist, we need to keep
+ the |active_width| array up to date, so that the badness of individual
+ lines is readily calculated by |try_break|. It is convenient to use the
+ short name |act_width| for the component of active width that represents
+ real width as opposed to glue. */
+
+ switch (type(cur_p)) {
+
+ case hlist_node:
+ case vlist_node:
+ act_width += (dir_orthogonal(dir_primary[box_dir(cur_p)], dir_primary[line_break_dir]))
+ ? (depth(cur_p)+height(cur_p))
+ : width(cur_p);
+ break;
+ case rule_node:
+ act_width += width(cur_p);
+ break;
+ case whatsit_node:
+ /* @<Advance \(p)past a whatsit node in the \(l)|line_break| loop@>;*/
+ switch (subtype(cur_p)) {
+ case local_par_node: /* @<LOCAL: Advance past a |local_paragraph| node@>;*/
+ internal_pen_inter=local_pen_inter(cur_p);
+ internal_pen_broken=local_pen_broken(cur_p);
+ internal_left_box=local_box_left(cur_p);
+ internal_left_box_width=local_box_left_width(cur_p);
+ internal_right_box=local_box_right(cur_p);
+ internal_right_box_width=local_box_right_width(cur_p);
+ break;
+ case dir_node: /* @<DIR: Adjust the dir stack for the |line_break| routine@>;*/
+ if (dir_dir(cur_p)>=0) {
+ line_break_dir=dir_dir(cur_p);
+ push_dir_node(cur_p);
+ } else {
+ pop_dir_node();
+ if (dir_ptr!=null)
+ line_break_dir=dir_dir(dir_ptr);
+ }
+ break;
+ case pdf_refxform_node:
+ case pdf_refximage_node:
+ act_width += pdf_width(cur_p);
+ }
+ /* / Advance \(p)past a whatsit node in the \(l)|line_break| loop/; */
+ break;
+ case glue_node:
+ /* @<If node |cur_p| is a legal breakpoint, call |try_break|;
+ then update the active widths by including the glue in
+ |glue_ptr(cur_p)|@>; */
+ /* When node |cur_p| is a glue node, we look at the previous to
+ see whether or not a breakpoint is legal at |cur_p|, as
+ explained above. */
+ if (auto_breaking) {
+ halfword prev_p = alink(cur_p);
+ if (prev_p!=temp_head &&
+ (is_char_node(prev_p) ||
+ precedes_break(prev_p)||
+ ((type(prev_p)==kern_node)&&(subtype(prev_p)!=explicit)))) {
+ ext_try_break(0,unhyphenated_node, pdf_adjust_spacing, par_shape_ptr,
+ adj_demerits, tracing_paragraphs, pdf_protrude_chars,
+ line_penalty, last_line_fit, double_hyphen_demerits,
+ final_hyphen_demerits,first_p,cur_p);
+ }
+ }
+ check_shrinkage(glue_ptr(cur_p));
+ q=glue_ptr(cur_p);
+ act_width += width(q);
+ active_width[2+stretch_order(q)] += stretch(q);
+ active_width[7] += shrink(q);
+ break;
+ case kern_node:
+ if (subtype(cur_p)==explicit) {
+ kern_break();
+ } else {
+ act_width += width(cur_p);
+ if ((pdf_adjust_spacing > 1) && (subtype(cur_p) == normal)) {
+ add_kern_stretch(active_width[8],cur_p);
+ add_kern_shrink(active_width[9],cur_p);
+ }
+ }
+ break;
+ case disc_node:
+ /* @<Try to break after a discretionary fragment, then |goto done5|@>;*/
+ /* The following code knows that discretionary texts contain
+ only character nodes, kern nodes, box nodes, and rule
+ nodes. */
+ if (second_pass) {
+ int actual_penalty = hyphen_penalty;
+ if (subtype(cur_p)==automatic_disc)
+ actual_penalty = ex_hyphen_penalty;
+ s=vlink_pre_break(cur_p);
+ do_one_seven_eight(reset_disc_width);
+ if (s==null) { /* trivial pre-break */
+ ext_try_break(actual_penalty,hyphenated_node, pdf_adjust_spacing,
+ par_shape_ptr, adj_demerits, tracing_paragraphs,
+ pdf_protrude_chars, line_penalty, last_line_fit,
+ double_hyphen_demerits, final_hyphen_demerits,first_p,cur_p);
+ } else {
+ do {
+ /* @<Add the width of node |s| to |disc_width|@>;*/
+ if (is_char_node(s)) {
+ if (is_rotated(line_break_dir)) {
+ disc_width[1] += (glyph_height(s)+glyph_depth(s));
+ } else {
+ disc_width[1] += glyph_width(s);
+ }
+ if ((pdf_adjust_spacing > 1) && check_expand_pars(font(s))) {
+ set_prev_char_p (s);
+ add_char_stretch(disc_width[8],s);
+ add_char_shrink(disc_width[9],s);
+ }
+ } else {
+ switch (type(s)) {
+ case hlist_node:
+ case vlist_node:
+ if (!(dir_orthogonal(dir_primary[box_dir(s)],
+ dir_primary[line_break_dir]))) {
+ disc_width[1] += width(s);
+ } else {
+ disc_width[1] += (depth(s)+height(s));
+ }
+ break;
+ case kern_node:
+ if ((pdf_adjust_spacing > 1) && (subtype(s) == normal)) {
+ add_kern_stretch(disc_width[8],s);
+ add_kern_shrink(disc_width[9],s);
+ }
+ /* fall through */
+ case rule_node:
+ disc_width[1] += width(s);
+ break;
+ case disc_node:
+ tconfusion("pre_break_disc");
+ break;
+ default:
+ tconfusion("disc3");
+ }
+ }
+ /* /Add the width of node |s| to |disc_width| */
+ s=vlink(s);
+ } while (s!=null);
+ do_one_seven_eight(add_disc_width_to_active_width);
+ ext_try_break(actual_penalty,hyphenated_node, pdf_adjust_spacing,
+ par_shape_ptr, adj_demerits, tracing_paragraphs,
+ pdf_protrude_chars, line_penalty, last_line_fit,
+ double_hyphen_demerits, final_hyphen_demerits,
+ first_p,cur_p);
+ do_one_seven_eight(sub_disc_width_from_active_width);
+ }
+#define FOO 1
+#if FOO
+#if 0
+ if (vlink(cur_p)!=null) nest_stack[nest_index++] = vlink(cur_p);
+ cur_p = no_break(cur_p);
+#else
+ s=vlink_no_break(cur_p);
+ while (s!=null) {
+ /* @<Add the width of node |s| to |act_width|@>;*/
+ if (is_char_node(s)) {
+ if (is_rotated(line_break_dir)) {
+ act_width += glyph_height(s)+glyph_depth(s);
+ } else {
+ act_width += glyph_width(s);
+ }
+ if ((pdf_adjust_spacing > 1) && check_expand_pars(font(s))) {
+ set_prev_char_p (s);
+ add_char_stretch(active_width[8],s);
+ add_char_shrink(active_width[9],s);
+ };
+ } else {
+ switch (type(s)) {
+ case hlist_node:
+ case vlist_node:
+ if (!(dir_orthogonal(dir_primary[box_dir(s)],
+ dir_primary[line_break_dir])))
+ act_width += width(s);
+ else
+ act_width += (depth(s)+height(s));
+ break;
+ case kern_node:
+ if ((pdf_adjust_spacing > 1) && (subtype(s) == normal)) {
+ add_kern_stretch(active_width[8],s);
+ add_kern_shrink(active_width[9],s);
+ }
+ /* fall through */
+ case rule_node:
+ act_width += width(s);
+ break;
+ case disc_node:
+ /* what now */
+ assert(vlink(s)==null); /* discs are _always_ last */
+ /* NB: temporary solution: not good, but not bad either */
+ s = no_break(s);
+ break;
+ default:
+ tconfusion("disc5");
+ }
+ }
+ /* /Add the width of node |s| to |act_width|;*/
+ s=vlink(s);
+ }
+#endif
+ } else { /* first pass, just take the no_break path */
+#else /* FOO */
+ }
+#endif /* FOO */
+#if 0
+ if (vlink_no_break(cur_p)!=null) {
+ if (vlink(cur_p)!=null) nest_stack[nest_index++] = vlink(cur_p);
+ /* fprintf(stderr,"Node Push %d [%d]->[%d] / [%d]\n",(nest_index-1),(int)cur_p,(int)vlink(cur_p),(int)vlink_no_break(cur_p));*/
+ cur_p = no_break(cur_p);
+ }
+#else
+ s=vlink_no_break(cur_p);
+ while (s!=null) {
+ /* @<Add the width of node |s| to |act_width|@>;*/
+ if (is_char_node(s)) {
+ if (is_rotated(line_break_dir)) {
+ act_width += glyph_height(s)+glyph_depth(s);
+ } else {
+ act_width += glyph_width(s);
+ }
+ if ((pdf_adjust_spacing > 1) && check_expand_pars(font(s))) {
+ set_prev_char_p (s);
+ add_char_stretch(active_width[8],s);
+ add_char_shrink(active_width[9],s);
+ };
+ } else {
+ switch (type(s)) {
+ case hlist_node:
+ case vlist_node:
+ if (!(dir_orthogonal(dir_primary[box_dir(s)],
+ dir_primary[line_break_dir])))
+ act_width += width(s);
+ else
+ act_width += (depth(s)+height(s));
+ break;
+ case kern_node:
+ if ((pdf_adjust_spacing > 1) && (subtype(s) == normal)) {
+ add_kern_stretch(active_width[8],s);
+ add_kern_shrink(active_width[9],s);
+ }
+ /* fall through */
+ case rule_node:
+ act_width += width(s);
+ break;
+ case disc_node:
+ assert(vlink(s)==null); /* discs are _always_ last */
+ s = no_break(s);
+ break;
+ default:
+ tconfusion("disc4");
+ }
+ }
+ /* /Add the width of node |s| to |act_width|;*/
+ s=vlink(s);
+ }
+#endif
+#if FOO
+ }
+#endif /* FOO */
+ break;
+ case math_node:
+ auto_breaking=(subtype(cur_p)==after);
+ kern_break();
+ break;
+ case penalty_node:
+ ext_try_break(penalty(cur_p),unhyphenated_node, pdf_adjust_spacing,
+ par_shape_ptr, adj_demerits, tracing_paragraphs,
+ pdf_protrude_chars, line_penalty, last_line_fit,
+ double_hyphen_demerits, final_hyphen_demerits,first_p,cur_p);
+ break;
+ case mark_node:
+ case ins_node:
+ case adjust_node:
+ break;
+ case glue_spec_node:
+ fprintf(stdout, "\nfound a glue_spec in a paragraph!");
+ break;
+ default:
+ fprintf(stdout, "\ntype=%d",type(cur_p));
+ tconfusion("paragraph") ;
+ }
+ cur_p=vlink(cur_p);
+ while (cur_p==null && nest_index>0) {
+ cur_p = nest_stack[--nest_index];
+ /* fprintf(stderr,"Node Pop %d [%d]\n",nest_index,(int)cur_p);*/
+ }
+ }
+ if (cur_p==null) {
+ /* Try the final line break at the end of the paragraph,
+ and |goto done| if the desired breakpoints have been found */
+
+ /* The forced line break at the paragraph's end will reduce the list of
+ breakpoints so that all active nodes represent breaks at |cur_p=null|.
+ On the first pass, we insist on finding an active node that has the
+ correct ``looseness.'' On the final pass, there will be at least one active
+ node, and we will match the desired looseness as well as we can.
+
+ The global variable |best_bet| will be set to the active node for the best
+ way to break the paragraph, and a few other variables are used to
+ help determine what is best.
+ */
+
+ ext_try_break(eject_penalty,hyphenated_node, pdf_adjust_spacing,
+ par_shape_ptr, adj_demerits, tracing_paragraphs,
+ pdf_protrude_chars,line_penalty, last_line_fit,
+ double_hyphen_demerits, final_hyphen_demerits,first_p,cur_p);
+ if (vlink(active)!=active) {
+ /* @<Find an active node with fewest demerits@>;*/
+ r=vlink(active);
+ fewest_demerits=awful_bad;
+ do {
+ if (type(r)!=delta_node) {
+ if (total_demerits(r)<fewest_demerits) {
+ fewest_demerits=total_demerits(r);
+ best_bet=r;
+ }
+ }
+ r=vlink(r);
+ } while (r!=active);
+ best_line=line_number(best_bet);
+
+ /* /Find an active node with fewest demerits;*/
+ if (looseness==0)
+ goto DONE;
+ /*@<Find the best active node for the desired looseness@>;*/
+
+ /* The adjustment for a desired looseness is a slightly more complicated
+ version of the loop just considered. Note that if a paragraph is broken
+ into segments by displayed equations, each segment will be subject to the
+ looseness calculation, independently of the other segments.
+ */
+ r=vlink(active);
+ actual_looseness=0;
+ do {
+ if (type(r)!=delta_node) {
+ line_diff=line_number(r)-best_line;
+ if (((line_diff<actual_looseness)&&(looseness<=line_diff))||
+ ((line_diff>actual_looseness)&&(looseness>=line_diff))) {
+ best_bet=r;
+ actual_looseness=line_diff;
+ fewest_demerits=total_demerits(r);
+ } else if ((line_diff==actual_looseness)&&
+ (total_demerits(r)<fewest_demerits)) {
+ best_bet=r;
+ fewest_demerits=total_demerits(r);
+ }
+ }
+ r=vlink(r);
+ } while (r!=active);
+ best_line=line_number(best_bet);
+
+ /* /Find the best active node for the desired looseness;*/
+ if ((actual_looseness==looseness)|| final_pass)
+ goto DONE;
+ }
+ }
+
+ /* Clean up the memory by removing the break nodes; */
+ clean_up_the_memory();
+ /* /Clean up the memory by removing the break nodes; */
+
+ if (!second_pass) {
+ if (tracing_paragraphs>0)
+ tprint_nl("@secondpass");
+ threshold=tolerance;
+ second_pass=true;
+ final_pass=(emergency_stretch<=0);
+ } else { /* if at first you do not succeed, \dots */
+ if (tracing_paragraphs>0)
+ tprint_nl("@emergencypass");
+ background[2] += emergency_stretch;
+ final_pass=true;
+ }
+ }
+ DONE:
+ if (tracing_paragraphs>0) {
+ end_diagnostic(true);
+ normalize_selector();
+ }
+ if (do_last_line_fit) {
+ /* Adjust \(t)the final line of the paragraph;*/
+ /* Here we either reset |do_last_line_fit| or adjust the |par_fill_skip| glue.
+ */
+ if (active_short(best_bet)==0) {
+ do_last_line_fit=false;
+ } else {
+ q=new_spec(glue_ptr(last_line_fill));
+ delete_glue_ref(glue_ptr(last_line_fill));
+ width(q) += (active_short(best_bet)-active_glue(best_bet));
+ stretch(q)=0;
+ glue_ptr(last_line_fill)=q;
+ }
+ /* /Adjust \(t)the final line of the paragraph;*/
+ }
+
+ /* @<Break the paragraph at the chosen...@>; */
+ /* Once the best sequence of breakpoints has been found (hurray), we call on the
+ procedure |post_line_break| to finish the remainder of the work.
+ (By introducing this subprocedure, we are able to keep |line_break|
+ from getting extremely long.)
+ */
+ ext_post_line_break(d,
+ right_skip,
+ left_skip,
+ pdf_protrude_chars,
+ par_shape_ptr,
+ pdf_adjust_spacing,
+ pdf_each_line_height,
+ pdf_each_line_depth,
+ pdf_first_line_height,
+ pdf_last_line_depth,
+ inter_line_penalties_ptr,
+ inter_line_penalty,
+ club_penalty,
+ club_penalties_ptr,
+ display_widow_penalties_ptr,
+ widow_penalties_ptr,
+ display_widow_penalty,
+ widow_penalty,
+ broken_penalty,
+ final_par_glue,
+ best_bet,
+ last_special_line,
+ second_width,
+ second_indent,
+ first_width,
+ first_indent,
+ best_line
+ );
+ /* /Break the paragraph at the chosen... */
+ /* Clean up the memory by removing the break nodes; */
+ clean_up_the_memory();
+ /*
+ flush_node_list(dir_ptr);
+ dir_ptr=null;
+ */
+}
+
+
diff --git a/Build/source/texk/web2c/luatexdir/tex/postlinebreak.c b/Build/source/texk/web2c/luatexdir/tex/postlinebreak.c
new file mode 100644
index 00000000000..86b9562c262
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/tex/postlinebreak.c
@@ -0,0 +1,512 @@
+/* $Id: postlinebreak.c 1078 2008-03-05 15:33:46Z taco $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+#include "nodes.h"
+
+/* So far we have gotten a little way into the |line_break| routine, having
+covered its important |try_break| subroutine. Now let's consider the
+rest of the process.
+
+The main loop of |line_break| traverses the given hlist,
+starting at |vlink(temp_head)|, and calls |try_break| at each legal
+breakpoint. A variable called |auto_breaking| is set to true except
+within math formulas, since glue nodes are not legal breakpoints when
+they appear in formulas.
+
+The current node of interest in the hlist is pointed to by |cur_p|. Another
+variable, |prev_p|, is usually one step behind |cur_p|, but the real
+meaning of |prev_p| is this: If |type(cur_p)=glue_node| then |cur_p| is a legal
+breakpoint if and only if |auto_breaking| is true and |prev_p| does not
+point to a glue node, penalty node, explicit kern node, or math node.
+
+*/
+
+static halfword
+do_push_dir_node (halfword p, halfword a ) {
+ halfword n;
+ n = copy_node(a);
+ vlink(n) = p;
+ return n;
+}
+
+static halfword
+do_pop_dir_node ( halfword p ) {
+ halfword n = vlink(p);
+ flush_node(p);
+ return n;
+}
+
+
+/* The total number of lines that will be set by |post_line_break|
+is |best_line-prev_graf-1|. The last breakpoint is specified by
+|break_node(best_bet)|, and this passive node points to the other breakpoints
+via the |prev_break| links. The finishing-up phase starts by linking the
+relevant passive nodes in forward order, changing |prev_break| to
+|next_break|. (The |next_break| fields actually reside in the same memory
+space as the |prev_break| fields did, but we give them a new name because
+of their new significance.) Then the lines are justified, one by one.
+
+The |post_line_break| must also keep an dir stack, so that it can
+output end direction instructions at the ends of lines
+and begin direction instructions at the beginnings of lines.
+
+*/
+
+#define next_break prev_break /*new name for |prev_break| after links are reversed*/
+
+#define append_list(a,b) \
+ { vlink(cur_list.tail_field)=vlink((a)); cur_list.tail_field = b; }
+
+#define left_skip_code 7 /*glue at left of justified lines*/
+#define right_skip_code 8 /*glue at right of justified lines*/
+
+/* the ints are actually halfwords */
+void ext_post_line_break(boolean d,
+ int right_skip,
+ int left_skip,
+ int pdf_protrude_chars,
+ halfword par_shape_ptr,
+ int pdf_adjust_spacing,
+ int pdf_each_line_height,
+ int pdf_each_line_depth,
+ int pdf_first_line_height,
+ int pdf_last_line_depth,
+ halfword inter_line_penalties_ptr,
+ int inter_line_penalty,
+ int club_penalty,
+ halfword club_penalties_ptr,
+ halfword display_widow_penalties_ptr,
+ halfword widow_penalties_ptr,
+ int display_widow_penalty,
+ int widow_penalty,
+ int broken_penalty,
+ halfword final_par_glue,
+ halfword best_bet,
+ halfword last_special_line,
+ scaled second_width,
+ scaled second_indent,
+ scaled first_width,
+ scaled first_indent,
+ halfword best_line ) {
+
+ boolean have_directional = true;
+ halfword q,r,s; /* temporary registers for list manipulation */
+ halfword p, k;
+ scaled w;
+ boolean glue_break; /* was a break at glue? */
+ boolean disc_break; /*was the current break at a discretionary node?*/
+ boolean post_disc_break; /*and did it have a nonempty post-break part?*/
+ scaled cur_width; /*width of line number |cur_line|*/
+ scaled cur_indent; /*left margin of line number |cur_line|*/
+ integer pen; /*use when calculating penalties between lines */
+ halfword cur_p; /* cur_p, but localized */
+ halfword cur_line; /*the current line number being justified*/
+
+ dir_ptr = cur_list.dirs_field;
+ /* @<Reverse the links of the relevant passive nodes, setting |cur_p| to
+ the first breakpoint@>; */
+ /* The job of reversing links in a list is conveniently regarded as the job
+ of taking items off one stack and putting them on another. In this case we
+ take them off a stack pointed to by |q| and having |prev_break| fields;
+ we put them on a stack pointed to by |cur_p| and having |next_break| fields.
+ Node |r| is the passive node being moved from stack to stack.
+ */
+ q=break_node(best_bet);
+ /*used_discs = used_disc(best_bet);*/
+ /*has_direction*/
+ cur_p=null;
+ do {
+ r=q;
+ q=prev_break(q);
+ next_break(r)=cur_p;
+ cur_p=r;
+ } while (q!=null);
+ /* |cur_p| is now the first breakpoint; */
+
+ cur_line=cur_list.pg_field+1; /* prevgraf+1 */
+
+ do {
+ /* @<Justify the line ending at breakpoint |cur_p|, and append it to the
+ current vertical list, together with associated penalties and other
+ insertions@>; */
+ /* The current line to be justified appears in a horizontal list starting
+ at |vlink(temp_head)| and ending at |cur_break(cur_p)|. If |cur_break(cur_p)| is
+ a glue node, we reset the glue to equal the |right_skip| glue; otherwise
+ we append the |right_skip| glue at the right. If |cur_break(cur_p)| is a
+ discretionary node, we modify the list so that the discretionary break
+ is compulsory, and we set |disc_break| to |true|. We also append
+ the |left_skip| glue at the left of the line, unless it is zero. */
+
+#if 0
+ tprint("BEGIN OF LINE ");
+ print_int(cur_break(cur_p));
+ breadth_max=100000;
+ depth_threshold=100000;
+ show_node_list(temp_head);
+#endif
+
+ /* DIR: Insert dir nodes at the beginning of the current line;*/
+ for (q=dir_ptr;q!=null;q=vlink(q)) {
+ halfword tmp = new_dir(dir_dir(q));
+ halfword nxt = vlink(temp_head);
+ couple_nodes(temp_head,tmp);
+ couple_nodes(tmp,nxt);
+ }
+ if (dir_ptr!=null) {
+ flush_node_list(dir_ptr); dir_ptr=null;
+ }
+
+ /* Modify the end of the line to reflect the nature of the break and to
+ include \.{\\rightskip}; also set the proper value of |disc_break|; */
+ /* At the end of the following code, |q| will point to the final node on the
+ list about to be justified. In the meanwhile |r| will point to the
+ node we will use to insert end-of-line stuff after. |q==null| means
+ we use the final position of |r| */
+ r = cur_break(cur_p);
+ q = null;
+ disc_break=false;
+ post_disc_break=false;
+ glue_break = false;
+
+ if (r==null) {
+ for (r=temp_head; vlink(r)!=null; r=vlink(r));
+ if (r==final_par_glue) {
+ /* This should almost always be true... */
+ /* TODO assert ? */
+ q = r;
+ /* |q| refers to the last node of the line (and paragraph) */
+ r = alink(r);
+ }
+ /* |r| refers to the node after which the dir nodes should be closed */
+ } else if (type(r)==glue_node) {
+ delete_glue_ref(glue_ptr(r));
+ glue_ptr(r)=right_skip;
+ subtype(r)=right_skip_code+1;
+ incr(glue_ref_count(right_skip));
+ glue_break = true;
+ /* |q| refers to the last node of the line */
+ q = r;
+ r=alink(r);
+ assert(vlink(r)==q);
+ /* |r| refers to the node after which the dir nodes should be closed */
+ } else if (type(r)==disc_node) {
+ halfword a = alink(r);
+ assert(a!=null);
+ halfword v = vlink(r);
+ if (v==null) { /* nested disc, let's unfold */
+ fprintf(stderr,"Nested disc [%d]<-[%d]->null\n",(int)a,(int)r);
+ do {
+ halfword d;
+ while (alink(a)!=null) a = alink(a);
+ assert(type(a)==nesting_node);
+ assert(subtype(a)=no_break_head(0)); /* No_break */
+ d = a - subtype(a); /* MAGIC subtype is offset of nesting with disc */
+ assert(type(d)==disc_node);
+ v = vlink(d);
+ a = alink(d);
+ fprintf(stderr,"Up to disc [%d]<-[%d]->[%d] & link [%d]\n",(int)a,(int)d,(int)v,(int)vlink_no_break(d));
+ assert(a!=null);
+ couple_nodes(a,vlink_no_break(d));
+ vlink_no_break(d)=null;
+ tlink_no_break(d)=null;
+ flush_node(d);
+ } while (v==null);
+ couple_nodes(r,v);
+ fprintf(stderr,"Close list [%d]<->[%d] a=[%d]\n",(int)r,(int)v,(int)alink(r));
+ a = alink(r);
+ }
+ if (vlink_no_break(r)!=null) {
+ flush_node_list(vlink_no_break(r));
+ vlink_no_break(r)=null;
+ tlink_no_break(r)=null;
+ }
+ if (vlink_pre_break(r)!=null) {
+ couple_nodes(a,vlink_pre_break(r));
+ couple_nodes(tlink_pre_break(r),r);
+ vlink_pre_break(r)=null;
+ tlink_pre_break(r)=null;
+ }
+ if (vlink_post_break(r)!=null) {
+ couple_nodes(r,vlink_post_break(r));
+ couple_nodes(tlink_post_break(r),v);
+ vlink_post_break(r)=null;
+ tlink_post_break(r)=null;
+ post_disc_break = true;
+ }
+ disc_break=true;
+ } else if (type(r)==kern_node) {
+ width(r)=0;
+ } else if (type(r)==math_node) {
+ surround(r)=0;
+ }
+
+ /* DIR: Adjust the dir stack based on dir nodes in this line; */
+ /* TODO what about the previousparagraph ??? */
+ if (have_directional) {
+ halfword e;
+ halfword p;
+ for(e=vlink(temp_head); e!=null && e!=cur_break(cur_p); e=vlink(e)) {
+ if (type(e)!=whatsit_node || subtype(e)!=dir_node)
+ continue;
+ if (dir_dir(e)>=0) {
+ dir_ptr = do_push_dir_node(dir_ptr,e);
+ } else if (dir_ptr!=null && dir_dir(dir_ptr)==(dir_dir(e)+64)) {
+ dir_ptr = do_pop_dir_node(dir_ptr);
+ }
+ }
+ assert(e==cur_break(cur_p));
+
+ /* @<DIR: Insert dir nodes at the end of the current line@>;*/
+ e = vlink(r);
+ for (p=dir_ptr; p!=null; p=vlink(p)) {
+ halfword s=new_dir(dir_dir(p)-64);
+ couple_nodes(r,s);
+ try_couple_nodes(s,e);
+ r=s;
+ }
+ }
+ if (passive_right_box(cur_p)!=null) {
+ /* TODO: CHECK has |s| below a |alink| ? */
+ halfword s = copy_node_list(passive_right_box(cur_p));
+ halfword e = vlink(r);
+ couple_nodes(r,s);
+ try_couple_nodes(s,e);
+ r=s;
+ }
+ if (q==null) {
+ q = r;
+ }
+ /* Now [q] refers to the last node on the line */
+
+ /* FIXME from this point on we no longer keep alink() valid */
+
+ /* at this point |q| is the rightmost breakpoint; the only exception is
+ the case of a discretionary break with non-empty |pre_break|, then |q|
+ has been changed to the last node of the |pre_break| list */
+ /* If the par ends with a \break command, the last line is utterly empty.
+ That is the case of |q==temp_head| */
+ if (q!=temp_head && pdf_protrude_chars > 0) {
+ halfword ptmp;
+ if (disc_break && (is_char_node(q) || (type(q) != disc_node))) {
+ p = q; /* |q| has been reset to the last node of |pre_break| */
+ ptmp = p;
+ } else {
+ p = alink(q); /* get |vlink(p) = q| */
+ assert(vlink(p)==q);
+ ptmp = p;
+ p = find_protchar_right(vlink(temp_head), p);
+ }
+ w = char_pw(p, right_side);
+ if (w!=0) { /* we have found a marginal kern, append it after |ptmp| */
+ k = new_margin_kern(-w, last_rightmost_char, right_side);
+ vlink(k) = vlink(ptmp);
+ vlink(ptmp) = k;
+ if (ptmp == q)
+ q = vlink(q);
+ }
+ }
+ /* if |q| was not a breakpoint at glue and has been reset to |rightskip|
+ then we append |rightskip| after |q| now */
+ if (!glue_break) {
+ /* @<Put the \(r)\.{\\rightskip} glue after node |q|@>;*/
+ halfword r=new_param_glue(right_skip_code);
+ vlink(r)=vlink(q);
+ vlink(q)=r;
+ q=r;
+ }
+
+ /* /Modify the end of the line to reflect the nature of the break and to
+ include \.{\\rightskip}; also set the proper value of |disc_break|; */
+
+ /* Put the \(l)\.{\\leftskip} glue at the left and detach this line;*/
+ /* The following code begins with |q| at the end of the list to be
+ justified. It ends with |q| at the beginning of that list, and with
+ |vlink(temp_head)| pointing to the remainder of the paragraph, if any. */
+ r=vlink(q);
+ vlink(q)=null;
+
+ q=vlink(temp_head);
+ try_couple_nodes(temp_head,r);
+ if (passive_left_box(cur_p)!=null && passive_left_box(cur_p)!=0) {
+ /* omega bits: */
+ r=copy_node_list(passive_left_box(cur_p));
+ s=vlink(q);
+ vlink(r)=q;
+ q=r;
+ if ((cur_line==cur_list.pg_field+1) && (s!=null)) {
+ if (type(s)==hlist_node) {
+ if (list_ptr(s)==null) {
+ q=vlink(q);
+ vlink(r)=vlink(s);
+ vlink(s)=r;
+ }
+ }
+ }
+ }
+ /*at this point |q| is the leftmost node; all discardable nodes have been discarded */
+ if (pdf_protrude_chars > 0) {
+ p = q;
+ p = find_protchar_left(p, false); /* no more discardables */
+ w = char_pw(p, left_side);
+ if (w != 0) {
+ k = new_margin_kern(-w, last_leftmost_char, left_side);
+ vlink(k) = q;
+ q = k;
+ }
+ };
+ if (left_skip!=zero_glue) {
+ r=new_param_glue(left_skip_code);
+ vlink(r)=q;
+ q=r;
+ }
+ /* /Put the \(l)\.{\\leftskip} glue at the left and detach this line;*/
+
+ /* Call the packaging subroutine, setting |just_box| to the justified box;*/
+ /* Now |q| points to the hlist that represents the current line of the
+ paragraph. We need to compute the appropriate line width, pack the
+ line into a box of this size, and shift the box by the appropriate
+ amount of indentation. */
+ if (cur_line>last_special_line) {
+ cur_width=second_width;
+ cur_indent=second_indent;
+ } else if (par_shape_ptr==null) {
+ cur_width=first_width;
+ cur_indent=first_indent;
+ } else {
+ cur_indent=varmem[(par_shape_ptr+2*cur_line)].cint;
+ cur_width=varmem[(par_shape_ptr+2*cur_line+1)].cint;
+ }
+ adjust_tail=adjust_head;
+ pack_direction=paragraph_dir;
+ pre_adjust_tail = pre_adjust_head;
+ if (pdf_adjust_spacing > 0 ) {
+ just_box = hpack(q, cur_width, cal_expand_ratio);
+ } else {
+ just_box = hpack(q, cur_width, exactly);
+ }
+ shift_amount(just_box)=cur_indent;
+ /* /Call the packaging subroutine, setting |just_box| to the justified box;*/
+
+ /* Append the new box to the current vertical list, followed by the list of
+ special nodes taken out of the box by the packager;*/
+ if (pdf_each_line_height!=0)
+ height(just_box) = pdf_each_line_height;
+ if (pdf_each_line_depth != 0)
+ depth(just_box) = pdf_each_line_depth;
+ if ((pdf_first_line_height != 0) && (cur_line == cur_list.pg_field + 1))
+ height(just_box) = pdf_first_line_height;
+ if ((pdf_last_line_depth != 0) && (cur_line + 1 == best_line))
+ depth(just_box) = pdf_last_line_depth;
+
+ if (pre_adjust_head != pre_adjust_tail)
+ append_list(pre_adjust_head,pre_adjust_tail);
+ pre_adjust_tail = null;
+ append_to_vlist(just_box);
+ if (adjust_head != adjust_tail)
+ append_list(adjust_head,adjust_tail);
+ adjust_tail = null;
+
+ /* /Append the new box to the current vertical list, followed by the list of
+ special nodes taken out of the box by the packager;*/
+
+ /* Append a penalty node, if a nonzero penalty is appropriate */
+ /* Penalties between the lines of a paragraph come from club and widow lines,
+ from the |inter_line_penalty| parameter, and from lines that end at
+ discretionary breaks. Breaking between lines of a two-line paragraph gets
+ both club-line and widow-line penalties. The local variable |pen| will
+ be set to the sum of all relevant penalties for the current line, except
+ that the final line is never penalized. */
+ if (cur_line+1!=best_line) {
+ q=inter_line_penalties_ptr;
+ if (q!=null) {
+ r=cur_line;
+ if (r>penalty(q))
+ r=penalty(q);
+ pen=penalty(q+r);
+ } else {
+ if (passive_pen_inter(cur_p)!=0) {
+ pen=passive_pen_inter(cur_p);
+ } else {
+ pen=inter_line_penalty;
+ }
+ }
+ q=club_penalties_ptr;
+ if (q!=null) {
+ r=cur_line-cur_list.pg_field; /* prevgraf */
+ if (r>penalty(q))
+ r=penalty(q);
+ pen += penalty(q+r);
+ } else if (cur_line==cur_list.pg_field+1) { /* prevgraf */
+ pen += club_penalty;
+ }
+ if (d)
+ q = display_widow_penalties_ptr;
+ else
+ q = widow_penalties_ptr;
+ if (q!=null) {
+ r=best_line-cur_line-1;
+ if (r>penalty(q))
+ r=penalty(q);
+ pen += penalty(q+r);
+ } else if (cur_line+2==best_line) {
+ if (d)
+ pen += display_widow_penalty;
+ else
+ pen += widow_penalty;
+ }
+ if (disc_break) {
+ if (passive_pen_broken(cur_p)!=0) {
+ pen += passive_pen_broken(cur_p);
+ } else {
+ pen += broken_penalty;
+ }
+ }
+ if (pen!=0) {
+ r=new_penalty(pen);
+ couple_nodes(cur_list.tail_field,r);
+ cur_list.tail_field=r;
+ }
+ }
+ /* /Append a penalty node, if a nonzero penalty is appropriate */
+
+ /* /Justify the line ending at breakpoint |cur_p|, and append it to the
+ current vertical list, together with associated penalties and other
+ insertions@>; */
+ incr(cur_line);
+ cur_p=next_break(cur_p);
+ if (cur_p!=null && !post_disc_break) {
+ /* @<Prune unwanted nodes at the beginning of the next line@>; */
+ /* Glue and penalty and kern and math nodes are deleted at the
+ beginning of a line, except in the anomalous case that the
+ node to be deleted is actually one of the chosen
+ breakpoints. Otherwise the pruning done here is designed to
+ match the lookahead computation in |try_break|, where the
+ |break_width| values are computed for non-discretionary
+ breakpoints. */
+ r=temp_head;
+ while(1) {
+ q=vlink(r);
+ if (q==cur_break(cur_p) || is_char_node(q))
+ break;
+ if (!((type(q)==whatsit_node)&&(subtype(q)==local_par_node))) {
+ if (non_discardable(q)
+ || (type(q)==kern_node && subtype(q)!=explicit ))
+ break;
+ }
+ r=q;
+ };
+ if (r!=temp_head) {
+ vlink(r)=null;
+ flush_node_list(vlink(temp_head));
+ try_couple_nodes(temp_head,q);
+ }
+ }
+ } while (cur_p!=null);
+ if ((cur_line!=best_line)||(vlink(temp_head)!=null))
+ tconfusion("line breaking");
+ cur_list.pg_field=best_line-1; /* prevgraf */
+ cur_list.dirs_field=dir_ptr; /* dir_save */
+ dir_ptr = null;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/tex/texnodes.c b/Build/source/texk/web2c/luatexdir/tex/texnodes.c
new file mode 100644
index 00000000000..06004160503
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/tex/texnodes.c
@@ -0,0 +1,1694 @@
+/* $Id: texnodes.c 1103 2008-03-11 14:32:50Z taco $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+#include "nodes.h"
+
+#define MAX_CHAIN_SIZE 12
+
+volatile memory_word *varmem = NULL;
+
+#ifndef NDEBUG
+char *varmem_sizes = NULL;
+#endif
+
+halfword var_mem_max = 0;
+halfword rover = 0;
+
+halfword free_chain[MAX_CHAIN_SIZE] = {null};
+
+static int prealloc=0;
+
+int fix_node_lists=1;
+
+int free_error_seen = 0;
+int copy_error_seen = 0;
+
+halfword slow_get_node (integer s) ; /* defined below */
+int copy_error (halfword p) ; /* define below */
+
+#undef link /* defined by cpascal.h */
+#define info(a) fixmem[(a)].hhlh
+#define link(a) fixmem[(a)].hhrh
+
+#define fake_node 100
+#define fake_node_size 2
+#define fake_node_name "fake"
+
+#define variable_node_size 2
+
+
+char * node_fields_list [] = { "attr", "width", "depth", "height", "dir", "shift",
+ "glue_order", "glue_sign", "glue_set" , "list", NULL };
+char * node_fields_rule [] = { "attr", "width", "depth", "height", "dir", NULL };
+char * node_fields_insert [] = { "attr", "cost", "depth", "height", "spec", "list", NULL };
+char * node_fields_mark [] = { "attr", "class", "mark", NULL };
+char * node_fields_adjust [] = { "attr", "list", NULL };
+char * node_fields_disc [] = { "attr", "pre", "post", "replace", NULL };
+char * node_fields_math [] = { "attr", "surround", NULL };
+char * node_fields_glue [] = { "attr", "spec", "leader", NULL };
+char * node_fields_kern [] = { "attr", "kern", NULL };
+char * node_fields_penalty [] = { "attr", "penalty", NULL };
+char * node_fields_unset [] = { "attr", "width", "depth", "height", "dir", "shrink",
+ "glue_order", "glue_sign", "stretch" , "span", "list", NULL };
+char * node_fields_margin_kern [] = { "attr", "width", "glyph", NULL };
+char * node_fields_glyph [] = { "attr", "char", "font", "lang", "left", "right", "uchyph",
+ "components", "xoffset", "yoffset", NULL };
+char * node_fields_style [] = { NULL };
+char * node_fields_choice [] = { NULL };
+char * node_fields_ord [] = { NULL };
+char * node_fields_op [] = { NULL };
+char * node_fields_bin [] = { NULL };
+char * node_fields_rel [] = { NULL };
+char * node_fields_open [] = { NULL };
+char * node_fields_close [] = { NULL };
+char * node_fields_punct [] = { NULL };
+char * node_fields_inner [] = { NULL };
+char * node_fields_radical [] = { NULL };
+char * node_fields_fraction [] = { NULL };
+char * node_fields_under [] = { NULL };
+char * node_fields_over [] = { NULL };
+char * node_fields_accent [] = { NULL };
+char * node_fields_vcenter [] = { NULL };
+char * node_fields_left [] = { NULL };
+char * node_fields_right [] = { NULL };
+
+char * node_fields_inserting [] = { "height", "last_ins_ptr", "best_ins_ptr", NULL};
+
+char * node_fields_splitup [] = { "height", "last_ins_ptr", "best_ins_ptr",
+ "broken_ptr", "broken_ins", NULL};
+
+char * node_fields_action [] = { "action_type", "named_id", "action_id",
+ "file", "new_window", "data", "ref_count", NULL };
+char * node_fields_attribute [] = { "number", "value", NULL };
+char * node_fields_glue_spec [] = { "width", "stretch", "shrink",
+ "stretch_order", "shrink_order", "ref_count", NULL };
+char * node_fields_attribute_list [] = { NULL };
+
+char * node_fields_whatsit_open [] = { "attr", "stream", "name", "area", "ext", NULL };
+char * node_fields_whatsit_write [] = { "attr", "stream", "data", NULL };
+char * node_fields_whatsit_close [] = { "attr", "stream", NULL };
+char * node_fields_whatsit_special [] = { "attr", "data", NULL };
+
+char * node_fields_whatsit_local_par [] = { "attr", "pen_inter", "pen_broken", "dir",
+ "box_left", "box_left_width", "box_right", "box_right_width", NULL };
+char * node_fields_whatsit_dir [] = { "attr", "dir", "level", "dvi_ptr", "dvi_h", NULL };
+
+char * node_fields_whatsit_pdf_literal [] = { "attr", "mode", "data", NULL };
+char * node_fields_whatsit_pdf_refobj [] = { "attr", "objnum", NULL };
+char * node_fields_whatsit_pdf_refxform [] = { "attr", "width", "height", "depth", "objnum", NULL };
+char * node_fields_whatsit_pdf_refximage [] = { "attr", "width", "height", "depth", "objnum", NULL };
+char * node_fields_whatsit_pdf_annot [] = { "attr", "width", "height", "depth", "objnum", "data", NULL };
+char * node_fields_whatsit_pdf_start_link [] = { "attr", "width", "height", "depth",
+ "objnum", "link_attr", "action", NULL };
+char * node_fields_whatsit_pdf_end_link [] = { "attr", NULL };
+char * node_fields_whatsit_pdf_dest [] = { "attr", "width", "height", "depth",
+ "named_id", "dest_id", "dest_type", "xyz_zoom", "objnum", NULL };
+char * node_fields_whatsit_pdf_thread [] = { "attr", "width", "height", "depth",
+ "named_id", "thread_id", "thread_attr", NULL };
+char * node_fields_whatsit_pdf_start_thread [] = { "attr", "width", "height", "depth",
+ "named_id", "thread_id", "thread_attr", NULL };
+char * node_fields_whatsit_pdf_end_thread [] = { "attr", NULL };
+char * node_fields_whatsit_pdf_save_pos [] = { "attr", NULL };
+char * node_fields_whatsit_late_lua [] = { "attr", "reg", "data", NULL };
+char * node_fields_whatsit_close_lua [] = { "attr", "reg", NULL };
+char * node_fields_whatsit_pdf_colorstack [] = { "attr", "stack", "cmd", "data", NULL };
+char * node_fields_whatsit_pdf_setmatrix [] = { "attr", "data", NULL };
+char * node_fields_whatsit_pdf_save [] = { "attr", NULL };
+char * node_fields_whatsit_pdf_restore [] = { "attr", NULL };
+char * node_fields_whatsit_cancel_boundary [] = { "attr", NULL };
+char * node_fields_whatsit_user_defined [] = { "attr", "user_id", "type", "value", NULL };
+
+node_info node_data[] = {
+ { hlist_node, box_node_size, node_fields_list, "hlist" },
+ { vlist_node, box_node_size, node_fields_list, "vlist" },
+ { rule_node, rule_node_size, node_fields_rule, "rule" },
+ { ins_node, ins_node_size, node_fields_insert, "ins" },
+ { mark_node, mark_node_size, node_fields_mark, "mark" },
+ { adjust_node, adjust_node_size, node_fields_adjust, "adjust" },
+ { fake_node, fake_node_size, NULL, fake_node_name }, /* don't touch this! */
+ { disc_node, disc_node_size, node_fields_disc, "disc" },
+ { whatsit_node, -1, NULL, "whatsit" },
+ { math_node, math_node_size, node_fields_math, "math" },
+ { glue_node, glue_node_size, node_fields_glue, "glue" },
+ { kern_node, kern_node_size, node_fields_kern, "kern" },
+ { penalty_node, penalty_node_size, node_fields_penalty, "penalty" },
+ { unset_node, box_node_size, node_fields_unset, "unset" },
+ { style_node, style_node_size, node_fields_style, "style" },
+ { choice_node, style_node_size, node_fields_choice, "choice" },
+ { ord_noad, noad_size, node_fields_ord, "ord" },
+ { op_noad, noad_size, node_fields_op, "op" },
+ { bin_noad, noad_size, node_fields_bin, "bin" },
+ { rel_noad, noad_size, node_fields_rel, "rel" },
+ { open_noad, noad_size, node_fields_open, "open" },
+ { close_noad, noad_size, node_fields_close, "close" },
+ { punct_noad, noad_size, node_fields_punct, "punct" },
+ { inner_noad, noad_size, node_fields_inner, "inner" },
+ { radical_noad, radical_noad_size, node_fields_radical, "radical" },
+ { fraction_noad, fraction_noad_size, node_fields_fraction, "fraction" },
+ { under_noad, noad_size, node_fields_under, "under" },
+ { over_noad, noad_size, node_fields_over, "over" },
+ { accent_noad, accent_noad_size, node_fields_accent, "accent" },
+ { vcenter_noad, noad_size, node_fields_vcenter, "vcenter" },
+ { left_noad, noad_size, node_fields_left, "left" },
+ { right_noad, noad_size, node_fields_right, "right" },
+ { margin_kern_node, margin_kern_node_size, node_fields_margin_kern, "margin_kern" },
+ { glyph_node, glyph_node_size, node_fields_glyph, "glyph" }, /* 33 */
+ { align_record_node, box_node_size, NULL, "align_record" },
+ { pseudo_file_node, pseudo_file_node_size, NULL, "pseudo_file" },
+ { pseudo_line_node, variable_node_size, NULL, "pseudo_line" },
+ { inserting_node, page_ins_node_size, node_fields_inserting, "page_insert" },
+ { split_up_node, page_ins_node_size, node_fields_splitup, "split_insert" },
+ { expr_node, expr_node_size, NULL, "expr_stack" },
+ { nesting_node, nesting_node_size, NULL, "nested_list" }, /* 40 */
+ { span_node, span_node_size, NULL, "span" },
+ { attribute_node, attribute_node_size, node_fields_attribute, "attribute" },
+ { glue_spec_node, glue_spec_size, node_fields_glue_spec, "glue_spec" },
+ { attribute_list_node, attribute_node_size, node_fields_attribute_list,"attribute_list" },
+ { action_node, pdf_action_size, node_fields_action, "action" },
+ { temp_node, temp_node_size, NULL, "temp" },
+ { align_stack_node, align_stack_node_size, NULL, "align_stack" },
+ { movement_node, movement_node_size, NULL, "movement_stack" },
+ { if_node, if_node_size, NULL, "if_stack" },
+ { unhyphenated_node, active_node_size, NULL, "unhyphenated" }, /* 50 */
+ { hyphenated_node, active_node_size, NULL, "hyphenated" },
+ { delta_node, delta_node_size, NULL, "delta" },
+ { passive_node, passive_node_size, NULL, "passive" },
+ { shape_node, variable_node_size, NULL, "shape" },
+ { -1, -1, NULL, NULL }};
+
+#define last_normal_node shape_node
+
+node_info whatsit_node_data[] = {
+ { open_node, open_node_size, node_fields_whatsit_open, "open" },
+ { write_node, write_node_size, node_fields_whatsit_write, "write" },
+ { close_node, close_node_size, node_fields_whatsit_close, "close" },
+ { special_node, special_node_size, node_fields_whatsit_special, "special" },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { local_par_node, local_par_size, node_fields_whatsit_local_par, "local_par" },
+ { dir_node, dir_node_size, node_fields_whatsit_dir, "dir" },
+ { pdf_literal_node, write_node_size, node_fields_whatsit_pdf_literal, "pdf_literal" },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { pdf_refobj_node, pdf_refobj_node_size, node_fields_whatsit_pdf_refobj, "pdf_refobj" },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { pdf_refxform_node, pdf_refxform_node_size, node_fields_whatsit_pdf_refxform, "pdf_refxform" },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { pdf_refximage_node, pdf_refximage_node_size, node_fields_whatsit_pdf_refximage, "pdf_refximage" },
+ { pdf_annot_node, pdf_annot_node_size, node_fields_whatsit_pdf_annot, "pdf_annot" },
+ { pdf_start_link_node, pdf_annot_node_size, node_fields_whatsit_pdf_start_link, "pdf_start_link" },
+ { pdf_end_link_node, pdf_end_link_node_size, node_fields_whatsit_pdf_end_link, "pdf_end_link" },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { pdf_dest_node, pdf_dest_node_size, node_fields_whatsit_pdf_dest, "pdf_dest" },
+ { pdf_thread_node, pdf_thread_node_size, node_fields_whatsit_pdf_thread, "pdf_thread" },
+ { pdf_start_thread_node, pdf_thread_node_size, node_fields_whatsit_pdf_start_thread,"pdf_start_thread"},
+ { pdf_end_thread_node, pdf_end_thread_node_size, node_fields_whatsit_pdf_end_thread, "pdf_end_thread" },
+ { pdf_save_pos_node, pdf_save_pos_node_size, node_fields_whatsit_pdf_save_pos, "pdf_save_pos" },
+ { pdf_thread_data_node, pdf_thread_node_size, NULL, "pdf_thread_data" },
+ { pdf_link_data_node, pdf_annot_node_size, NULL, "pdf_link_data" },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { late_lua_node, write_node_size, node_fields_whatsit_late_lua, "late_lua" },
+ { close_lua_node, write_node_size, node_fields_whatsit_close_lua, "close_lua" },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { fake_node, fake_node_size, NULL, fake_node_name },
+ { pdf_colorstack_node, pdf_colorstack_node_size, node_fields_whatsit_pdf_colorstack, "pdf_colorstack" },
+ { pdf_setmatrix_node, pdf_setmatrix_node_size, node_fields_whatsit_pdf_setmatrix, "pdf_setmatrix" },
+ { pdf_save_node, pdf_save_node_size, node_fields_whatsit_pdf_save, "pdf_save" },
+ { pdf_restore_node, pdf_restore_node_size, node_fields_whatsit_pdf_restore, "pdf_restore" },
+ { cancel_boundary_node, cancel_boundary_size, node_fields_whatsit_cancel_boundary, "cancel_boundary" },
+ { user_defined_node, user_defined_node_size, node_fields_whatsit_user_defined, "user_defined" },
+ { -1, -1, NULL, NULL }};
+
+#define last_whatsit_node user_defined_node
+
+#define get_node_size(i,j) (i!=whatsit_node ? node_data[i].size : whatsit_node_data[j].size)
+#define get_node_name(i,j) (i!=whatsit_node ? node_data[i].name : whatsit_node_data[j].name)
+
+halfword
+new_node(int i, int j) {
+ register int s;
+ register halfword n;
+ s = get_node_size(i,j);
+ n = get_node(s);
+ /* it should be possible to do this memset at free_node() */
+ /* type() and subtype() will be set below, and vlink() is
+ set to null by get_node(), so we can do we clearing one
+ word less than |s| */
+ (void)memset((void *)(varmem+n+1),0, (sizeof(memory_word)*(s-1)));
+ switch (i) {
+ case glyph_node:
+ init_lang_data(n);
+ break;
+ case glue_node:
+ case kern_node:
+ case glue_spec_node:
+ break;
+ case hlist_node:
+ case vlist_node:
+ box_dir(n)=-1;
+ break;
+ case whatsit_node:
+ if (j==open_node) {
+ open_name(n) = get_nullstr();
+ open_area(n) = open_name(n);
+ open_ext(n) = open_name(n);
+ }
+ break;
+ case disc_node:
+ pre_break(n)=pre_break_head(n);
+ type(pre_break(n))= nesting_node;
+ subtype(pre_break(n))=pre_break_head(0);
+ post_break(n)=post_break_head(n);
+ type(post_break(n))= nesting_node;
+ subtype(post_break(n))=post_break_head(0);
+ no_break(n)=no_break_head(n);
+ type(no_break(n))= nesting_node;
+ subtype(no_break(n))=no_break_head(0);
+ break;
+ case rule_node:
+ depth(n)=null_flag;
+ height(n)=null_flag;
+ rule_dir(n)=-1;
+ /* fall through */
+ case unset_node:
+ width(n) = null_flag;
+ break;
+ case pseudo_line_node:
+ case shape_node:
+ /* this is a trick that makes pseudo_files slightly slower,
+ * but the overall allocation faster then an explicit test
+ * at the top of new_node().
+ */
+ free_node(n,variable_node_size);
+ n = slow_get_node(j);
+ (void)memset((void *)(varmem+n+1),0, (sizeof(memory_word)*(j-1)));
+ break;
+ default:
+ break;
+ }
+ if (nodetype_has_attributes(i)) {
+ build_attribute_list(n);
+ }
+ type(n)=i;
+ subtype(n)=j;
+ return n;
+}
+
+halfword
+raw_glyph_node(void) {
+ register halfword n;
+ n = get_node(glyph_node_size);
+ (void)memset((void *)(varmem+n+1),0, (sizeof(memory_word)*(glyph_node_size-1)));
+ type(n)=glyph_node;
+ subtype(n)=0;
+ return n;
+}
+
+halfword
+new_glyph_node(void) {
+ register halfword n;
+ n = get_node(glyph_node_size);
+ (void)memset((void *)(varmem+n+1),0, (sizeof(memory_word)*(glyph_node_size-1)));
+ type(n)=glyph_node;
+ subtype(n)=0;
+ build_attribute_list(n);
+ return n;
+}
+
+
+/* makes a duplicate of the node list that starts at |p| and returns a
+ pointer to the new list */
+
+halfword
+copy_node_list(halfword p) {
+ halfword q; /* previous position in new list */
+ halfword h = null; /* head of the list */
+ copy_error_seen = 0;
+ while (p!=null) {
+ register halfword s = copy_node(p);
+ if (h==null) {
+ h = s;
+ } else {
+ couple_nodes(q,s);
+ }
+ q=s;
+ p=vlink(p);
+ }
+ return h;
+}
+
+ /* make a dupe of a single node */
+halfword
+copy_node(const halfword p) {
+ halfword r; /* current node being fabricated for new list */
+ register halfword s; /* a helper variable for copying into variable mem */
+ register int i;
+ if (copy_error(p)) {
+ r = new_node(temp_node,0);
+ return r;
+ }
+ i = get_node_size(type(p), subtype(p));
+ r = get_node(i);
+ (void)memcpy((void *)(varmem+r),(void *)(varmem+p),(sizeof(memory_word)*i));
+
+ if (nodetype_has_attributes(type(p))) {
+ add_node_attr_ref(node_attr(p));
+ alink(r)=null; /* needs checking */
+ }
+ vlink(r)=null;
+ switch (type(p)) {
+ case glyph_node:
+ s=copy_node_list(lig_ptr(p));
+ lig_ptr(r)=s;
+ break;
+ case glue_node:
+ add_glue_ref(glue_ptr(p));
+ s=copy_node_list(leader_ptr(p));
+ leader_ptr(r)=s;
+ break;
+ case hlist_node:
+ case vlist_node:
+ case unset_node:
+ s=copy_node_list(list_ptr(p));
+ list_ptr(r)=s;
+ break;
+ case ins_node:
+ add_glue_ref(split_top_ptr(p));
+ s=copy_node_list(ins_ptr(p));
+ ins_ptr(r)=s;
+ break;
+ case margin_kern_node:
+ s=copy_node(margin_char(p));
+ margin_char(r)=s;
+ break;
+ case disc_node:
+ pre_break(r)=pre_break_head(r);
+ if (vlink_pre_break(p)!=null) {
+ s=copy_node_list(vlink_pre_break(p));
+ alink(s)=pre_break(r);
+ tlink_pre_break(r)=tail_of_list(s);
+ vlink_pre_break(r)=s;
+ } else {
+ assert(tlink(pre_break(r))==null);
+ }
+ post_break(r)=post_break_head(r);
+ if (vlink_post_break(p)!=null) {
+ s=copy_node_list(vlink_post_break(p));
+ alink(s)=post_break(r);
+ tlink_post_break(r)=tail_of_list(s);
+ vlink_post_break(r)=s;
+ } else {
+ assert(tlink_post_break(r)==null);
+ }
+ no_break(r)=no_break_head(r);
+ if (vlink(no_break(p))!=null) {
+ s=copy_node_list(vlink_no_break(p));
+ alink(s)=no_break(r);
+ tlink_no_break(r)=tail_of_list(s);
+ vlink_no_break(r)=s;
+ } else {
+ assert(tlink_no_break(r)==null);
+ }
+ break;
+ case mark_node:
+ add_token_ref(mark_ptr(p));
+ break;
+ case adjust_node:
+ s=copy_node_list(adjust_ptr(p));
+ adjust_ptr(r)=s;
+ break;
+ case glue_spec_node:
+ glue_ref_count(r)=null;
+ break;
+ case whatsit_node:
+ switch (subtype(p)) {
+ case dir_node:
+ case local_par_node:
+ break;
+ case write_node:
+ case special_node:
+ add_token_ref(write_tokens(p));
+ break;
+ case pdf_literal_node:
+ add_token_ref(pdf_literal_data(p));
+ break;
+ case pdf_colorstack_node:
+ if (pdf_colorstack_cmd(p) <= colorstack_data)
+ add_token_ref(pdf_colorstack_data(p));
+ break;
+ case pdf_setmatrix_node:
+ add_token_ref(pdf_setmatrix_data(p));
+ break;
+ case late_lua_node:
+ add_token_ref(late_lua_data(p));
+ break;
+ case pdf_annot_node:
+ add_token_ref(pdf_annot_data(p));
+ break;
+ case pdf_start_link_node:
+ if (pdf_link_attr(r) != null)
+ add_token_ref(pdf_link_attr(r));
+ add_action_ref(pdf_link_action(r));
+ break;
+ case pdf_dest_node:
+ if (pdf_dest_named_id(p) > 0)
+ add_token_ref(pdf_dest_id(p));
+ break;
+ case pdf_thread_node:
+ case pdf_start_thread_node:
+ if (pdf_thread_named_id(p) > 0)
+ add_token_ref(pdf_thread_id(p));
+ if (pdf_thread_attr(p) != null)
+ add_token_ref(pdf_thread_attr(p));
+ break;
+ case user_defined_node:
+ switch (user_node_type(p)) {
+ case 'a': add_node_attr_ref(user_node_value(p));
+ break;
+ case 't': add_token_ref(user_node_value(p));
+ break;
+ case 'n':
+ s=copy_node_list(user_node_value(p));
+ user_node_value(r)=s;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ return r;
+}
+
+int valid_node (halfword p) {
+ if (p>prealloc) {
+ if (p<var_mem_max) {
+ if (varmem_sizes[p]>0)
+ return 1;
+ }
+ } else {
+ return 1;
+ }
+ return 0;
+}
+
+static void
+do_free_error (halfword p) {
+ char errstr[255]= {0};
+ char *errhlp[] = {"When I tried to free the node mentioned in the error message, it turned",
+ "out it was not (or no longer) actually in use.",
+ "Errors such as these are often caused by Lua node list alteration,",
+ "but could also point to a bug in the executable. It should be safe to continue.",
+ NULL};
+
+ check_node_mem();
+ if (free_error_seen)
+ return;
+
+ halfword r = null;
+ free_error_seen = 1;
+ if (type(p)==glyph_node) {
+ snprintf(errstr,255,"Attempt to double-free glyph (%c) node %d, ignored", (int)character (p), (int)p);
+ } else {
+ snprintf(errstr,255,"Attempt to double-free %s node %d, ignored", get_node_name(type(p),subtype(p)), (int)p);
+ }
+ tex_error(errstr,errhlp);
+ for (r=prealloc+1;r<var_mem_max;r++) {
+ if (vlink(r)==p) {
+ halfword s = r;
+ while (s>prealloc && varmem_sizes[s]==0)
+ s--;
+ if (s!=null
+ && s!=prealloc
+ && s!=var_mem_max
+ && (r-s)<get_node_size(type(s),subtype(s) )
+ && alink(s)!=p ) {
+
+ if (type(s)==disc_node) {
+ fprintf(stdout," pointed to from %s node %d (vlink %d, alink %d): ",
+ get_node_name(type(s),subtype(s)), (int)s, (int)vlink(s), (int)alink(s));
+ fprintf(stdout,"pre_break(%d,%d,%d), ", (int)vlink_pre_break(s), (int)tlink(pre_break(s)), (int)alink(pre_break(s)));
+ fprintf(stdout,"post_break(%d,%d,%d), ", (int)vlink_post_break(s), (int)tlink(post_break(s)), (int)alink(post_break(s)));
+ fprintf(stdout,"no_break(%d,%d,%d)", (int)vlink_no_break(s), (int)tlink(no_break(s)), (int)alink(no_break(s)));
+ fprintf(stdout,"\n");
+ } else {
+ if (vlink(s)==p
+ || (type(s)==glyph_node && lig_ptr(s)==p)
+ || (type(s)==vlist_node && list_ptr(s)==p)
+ || (type(s)==hlist_node && list_ptr(s)==p)
+ || (type(s)==unset_node && list_ptr(s)==p)
+ || (type(s)==ins_node && ins_ptr(s)==p)
+ ) {
+ fprintf(stdout," pointed to from %s node %d (vlink %d, alink %d): ",
+ get_node_name(type(s),subtype(s)), (int)s, (int)vlink(s), (int)alink(s));
+ if (type(s)==glyph_node) {
+ fprintf(stdout,"lig_ptr(%d)", (int)lig_ptr(s));
+ } else if (type(s)==vlist_node || type(s)==hlist_node) {
+ fprintf(stdout,"list_ptr(%d)", (int)list_ptr(s));
+ }
+ fprintf(stdout,"\n");
+ } else {
+ if ((type(s)!=penalty_node)
+ && (type(s)!=math_node)
+ && (type(s)!=kern_node)
+ ) {
+ fprintf(stdout," pointed to from %s node %d\n",get_node_name(type(s),subtype(s)), (int)s);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+int
+free_error (halfword p) {
+ assert(p>prealloc);
+ assert(p<var_mem_max);
+ if (varmem_sizes[p]==0) {
+ do_free_error(p);
+ return 1; /* double free */
+ }
+ return 0;
+}
+
+
+static void
+do_copy_error (halfword p) {
+ char errstr[255]= {0};
+ char *errhlp[] = {"When I tried to copy the node mentioned in the error message, it turned",
+ "out it was not (or no longer) actually in use.",
+ "Errors such as these are often caused by Lua node list alteration,",
+ "but could also point to a bug in the executable. It should be safe to continue.",
+ NULL};
+
+ if (copy_error_seen)
+ return;
+
+ copy_error_seen = 1;
+ if (type(p)==glyph_node) {
+ snprintf(errstr,255,"Attempt to copy free glyph (%c) node %d, ignored", (int)character (p), (int)p);
+ } else {
+ snprintf(errstr,255,"Attempt to copy free %s node %d, ignored", get_node_name(type(p),subtype(p)), (int)p);
+ }
+ tex_error(errstr,errhlp);
+}
+
+
+int
+copy_error (halfword p) {
+ assert(p>=0);
+ assert(p<var_mem_max);
+ if (p>prealloc && varmem_sizes[p]==0) {
+ do_copy_error(p);
+ return 1; /* copy free node */
+ }
+ return 0;
+}
+
+
+
+void
+flush_node (halfword p) {
+
+ if (p==null) /* legal, but no-op */
+ return;
+
+ if (free_error(p))
+ return;
+
+ switch(type(p)) {
+ case glyph_node:
+ flush_node_list(lig_ptr(p));
+ break;
+ case glue_node:
+ delete_glue_ref(glue_ptr(p));
+ flush_node_list(leader_ptr(p));
+ break;
+
+ case attribute_node:
+ case attribute_list_node:
+ case temp_node:
+ case glue_spec_node:
+ case rule_node:
+ case kern_node:
+ case math_node:
+ case penalty_node:
+ break;
+
+ case hlist_node:
+ case vlist_node:
+ case unset_node:
+ flush_node_list(list_ptr(p));
+ break;
+ case whatsit_node:
+ switch (subtype(p)) {
+
+ case dir_node:
+ break;
+ case open_node:
+ case write_node:
+ case close_node:
+ case pdf_save_node:
+ case pdf_restore_node:
+ case cancel_boundary_node:
+ case close_lua_node:
+ case pdf_refobj_node:
+ case pdf_refxform_node:
+ case pdf_refximage_node:
+ case pdf_end_link_node:
+ case pdf_end_thread_node:
+ case pdf_save_pos_node:
+ case local_par_node:
+ break;
+
+ case special_node:
+ delete_token_ref(write_tokens(p));
+ break;
+ case pdf_literal_node:
+ delete_token_ref(pdf_literal_data(p));
+ break;
+ case pdf_colorstack_node:
+ if (pdf_colorstack_cmd(p) <= colorstack_data)
+ delete_token_ref(pdf_colorstack_data(p));
+ break;
+ case pdf_setmatrix_node:
+ delete_token_ref(pdf_setmatrix_data(p));
+ break;
+ case late_lua_node:
+ delete_token_ref(late_lua_data(p));
+ break;
+ case pdf_annot_node:
+ delete_token_ref(pdf_annot_data(p));
+ break;
+
+ case pdf_link_data_node:
+ break;
+
+ case pdf_start_link_node:
+ if (pdf_link_attr(p) != null)
+ delete_token_ref(pdf_link_attr(p));
+ delete_action_ref(pdf_link_action(p));
+ break;
+ case pdf_dest_node:
+ if (pdf_dest_named_id(p) > 0)
+ delete_token_ref(pdf_dest_id(p));
+ break;
+
+ case pdf_thread_data_node:
+ break;
+
+ case pdf_thread_node:
+ case pdf_start_thread_node:
+ if (pdf_thread_named_id(p) > 0 ) delete_token_ref(pdf_thread_id(p));
+ if (pdf_thread_attr(p) != null) delete_token_ref(pdf_thread_attr(p));
+ break;
+ case user_defined_node:
+ switch( user_node_type(p)) {
+ case 'a': delete_attribute_ref(user_node_value(p)); break;
+ case 't': delete_token_ref(user_node_value(p)); break;
+ case 'n': flush_node_list(user_node_value(p)); break;
+ default: tconfusion("extuser"); break;
+ }
+ break;
+
+ default:
+ tconfusion("ext3");
+ return;
+
+ }
+ break;
+ case ins_node:
+ flush_node_list(ins_ptr(p));
+ delete_glue_ref(split_top_ptr(p));
+ break;
+ case margin_kern_node:
+ flush_node(margin_char(p));
+ break;
+ case mark_node:
+ delete_token_ref(mark_ptr(p));
+ break;
+ case disc_node:
+ flush_node_list(vlink(pre_break(p)));
+ flush_node_list(vlink(post_break(p)));
+ flush_node_list(vlink(no_break(p)));
+ break;
+ case adjust_node:
+ flush_node_list(adjust_ptr(p));
+ break;
+ case style_node:
+ break;
+ case choice_node:
+ flush_node_list(display_mlist(p));
+ flush_node_list(text_mlist(p));
+ flush_node_list(script_mlist(p));
+ flush_node_list(script_script_mlist(p));
+ break;
+ case ord_noad:
+ case op_noad:
+ case bin_noad:
+ case rel_noad:
+ case open_noad:
+ case close_noad:
+ case punct_noad:
+ case inner_noad:
+ case radical_noad:
+ case over_noad:
+ case under_noad:
+ case vcenter_noad:
+ case accent_noad:
+
+ /*
+ * if (math_type(nucleus(p))>=sub_box)
+ * flush_node_list(vinfo(nucleus(p)));
+ * if (math_type(supscr(p))>=sub_box)
+ * flush_node_list(vinfo(supscr(p)));
+ * if (math_type(subscr(p))>=sub_box)
+ * flush_node_list(vinfo(subscr(p)));
+ */
+
+ break;
+ case left_noad:
+ case right_noad:
+ break;
+ case fraction_noad:
+ flush_node_list(vinfo(numerator(p)));
+ flush_node_list(vinfo(denominator(p)));
+ break;
+ case pseudo_file_node:
+ flush_node_list(pseudo_lines(p));
+ break;
+ case pseudo_line_node:
+ case shape_node:
+ free_node(p,subtype(p));
+ return;
+ break;
+ case align_stack_node:
+ case span_node:
+ case movement_node:
+ case if_node:
+ case nesting_node:
+ case unhyphenated_node:
+ case hyphenated_node:
+ case delta_node:
+ case passive_node:
+ case action_node:
+ case inserting_node:
+ case split_up_node:
+ case expr_node:
+ break;
+ default:
+ fprintf(stdout,"flush_node: type is %d\n", type(p));
+ return;
+
+ }
+ if (nodetype_has_attributes(type(p)))
+ delete_attribute_ref(node_attr(p));
+ free_node(p,get_node_size(type(p),subtype(p)));
+ return;
+}
+
+void
+flush_node_list(halfword pp) { /* erase list of nodes starting at |p| */
+ register halfword p=pp;
+ free_error_seen = 0;
+ if (p==null) /* legal, but no-op */
+ return;
+ if (free_error(p))
+ return;
+
+ while (p!=null) {
+ register halfword q = vlink(p);
+ flush_node(p);
+ p=q;
+ }
+}
+
+static int test_count = 1;
+
+#define dorangetest(a,b,c) do { \
+ if (!(b>=0 && b<c)) { \
+ fprintf(stdout,"For node p:=%d, 0<=%d<%d (l.%d,r.%d)\n", \
+ (int)a, (int)b, (int)c, __LINE__,test_count); \
+ tconfusion("dorangetest"); \
+ } } while (0)
+
+#define dotest(a,b,c) do { \
+ if (b!=c) { \
+ fprintf(stdout,"For node p:=%d, %d==%d (l.%d,r.%d)\n", \
+ (int)a, (int)b, (int)c, __LINE__,test_count); \
+ tconfusion("dotest"); \
+ } } while (0)
+
+#define check_action_ref(a) { dorangetest(p,a,var_mem_max); }
+#define check_glue_ref(a) { dorangetest(p,a,var_mem_max); }
+#define check_attribute_ref(a) { dorangetest(p,a,var_mem_max); }
+#define check_token_ref(a) assert(1)
+
+void
+check_node (halfword p) {
+
+ switch(type(p)) {
+ case glyph_node:
+ dorangetest(p,lig_ptr(p),var_mem_max);
+ break;
+ case glue_node:
+ check_glue_ref(glue_ptr(p));
+ dorangetest(p,leader_ptr(p),var_mem_max);
+ break;
+ case hlist_node:
+ case vlist_node:
+ case unset_node:
+ case align_record_node:
+ dorangetest(p,list_ptr(p),var_mem_max);
+ break;
+ case ins_node:
+ dorangetest(p,ins_ptr(p),var_mem_max);
+ check_glue_ref(split_top_ptr(p));
+ break;
+ case whatsit_node:
+ switch (subtype(p)) {
+ case special_node:
+ check_token_ref(write_tokens(p));
+ break;
+ case pdf_literal_node:
+ check_token_ref(pdf_literal_data(p));
+ break;
+ case pdf_colorstack_node:
+ if (pdf_colorstack_cmd(p) <= colorstack_data)
+ check_token_ref(pdf_colorstack_data(p));
+ break;
+ case pdf_setmatrix_node:
+ check_token_ref(pdf_setmatrix_data(p));
+ break;
+ case late_lua_node:
+ check_token_ref(late_lua_data(p));
+ break;
+ case pdf_annot_node:
+ check_token_ref(pdf_annot_data(p));
+ break;
+ case pdf_start_link_node:
+ if (pdf_link_attr(p) != null)
+ check_token_ref(pdf_link_attr(p));
+ check_action_ref(pdf_link_action(p));
+ break;
+ case pdf_dest_node:
+ if (pdf_dest_named_id(p) > 0)
+ check_token_ref(pdf_dest_id(p));
+ break;
+ case pdf_thread_node:
+ case pdf_start_thread_node:
+ if (pdf_thread_named_id(p) > 0 ) check_token_ref(pdf_thread_id(p));
+ if (pdf_thread_attr(p) != null) check_token_ref(pdf_thread_attr(p));
+ break;
+ case user_defined_node:
+ switch( user_node_type(p)) {
+ case 'a': check_attribute_ref(user_node_value(p)); break;
+ case 't': check_token_ref(user_node_value(p)); break;
+ case 'n': dorangetest(p,user_node_value(p),var_mem_max); break;
+ default: tconfusion("extuser"); break;
+ }
+ break;
+ case dir_node:
+ case open_node:
+ case write_node:
+ case close_node:
+ case pdf_save_node:
+ case pdf_restore_node:
+ case cancel_boundary_node:
+ case close_lua_node:
+ case pdf_refobj_node:
+ case pdf_refxform_node:
+ case pdf_refximage_node:
+ case pdf_end_link_node:
+ case pdf_end_thread_node:
+ case pdf_save_pos_node:
+ case local_par_node:
+ break;
+ default:
+ tconfusion("ext3");
+ }
+ break;
+ case margin_kern_node:
+ check_node(margin_char(p));
+ break;
+ case disc_node:
+ dorangetest(p,vlink(pre_break(p)),var_mem_max);
+ dorangetest(p,vlink(post_break(p)),var_mem_max);
+ dorangetest(p,vlink(no_break(p)),var_mem_max);
+ break;
+ case adjust_node:
+ dorangetest(p,adjust_ptr(p),var_mem_max);
+ break;
+ case pseudo_file_node:
+ dorangetest(p,pseudo_lines(p),var_mem_max);
+ break;
+ case pseudo_line_node:
+ case shape_node:
+ break;
+ case choice_node:
+ dorangetest(p,display_mlist(p),var_mem_max);
+ dorangetest(p,text_mlist(p),var_mem_max);
+ dorangetest(p,script_mlist(p),var_mem_max);
+ dorangetest(p,script_script_mlist(p),var_mem_max);
+ break;
+ case fraction_noad:
+ dorangetest(p,vinfo(numerator(p)),var_mem_max);
+ dorangetest(p,vinfo(denominator(p)),var_mem_max);
+ break;
+ case rule_node:
+ case kern_node:
+ case math_node:
+ case penalty_node:
+ case mark_node:
+ case style_node:
+ case ord_noad:
+ case op_noad:
+ case bin_noad:
+ case rel_noad:
+ case open_noad:
+ case close_noad:
+ case punct_noad:
+ case inner_noad:
+ case radical_noad:
+ case over_noad:
+ case under_noad:
+ case vcenter_noad:
+ case accent_noad:
+ case left_noad:
+ case right_noad:
+ case attribute_list_node:
+ case attribute_node:
+ case glue_spec_node:
+ case temp_node:
+ case align_stack_node:
+ case movement_node:
+ case if_node:
+ case nesting_node:
+ case span_node:
+ case unhyphenated_node:
+ case hyphenated_node:
+ case delta_node:
+ case passive_node:
+ case expr_node:
+ break;
+ default:
+ fprintf(stdout,"check_node: type is %d\n", type(p));
+ }
+}
+
+void
+check_static_node_mem (void) {
+ dotest(zero_glue,width(zero_glue),0);
+ dotest(zero_glue,type(zero_glue),glue_spec_node);
+ dotest(zero_glue,vlink(zero_glue),null);
+ dotest(zero_glue,stretch(zero_glue),0);
+ dotest(zero_glue,stretch_order(zero_glue),normal);
+ dotest(zero_glue,shrink(zero_glue),0);
+ dotest(zero_glue,shrink_order(zero_glue),normal);
+
+ dotest(sfi_glue,width(sfi_glue),0);
+ dotest(sfi_glue,type(sfi_glue),glue_spec_node);
+ dotest(sfi_glue,vlink(sfi_glue),null);
+ dotest(sfi_glue,stretch(sfi_glue),0);
+ dotest(sfi_glue,stretch_order(sfi_glue),sfi);
+ dotest(sfi_glue,shrink(sfi_glue),0);
+ dotest(sfi_glue,shrink_order(sfi_glue),normal);
+
+ dotest(fil_glue,width(fil_glue),0);
+ dotest(fil_glue,type(fil_glue),glue_spec_node);
+ dotest(fil_glue,vlink(fil_glue),null);
+ dotest(fil_glue,stretch(fil_glue),unity);
+ dotest(fil_glue,stretch_order(fil_glue),fil);
+ dotest(fil_glue,shrink(fil_glue),0);
+ dotest(fil_glue,shrink_order(fil_glue),normal);
+
+ dotest(fill_glue,width(fill_glue),0);
+ dotest(fill_glue,type(fill_glue),glue_spec_node);
+ dotest(fill_glue,vlink(fill_glue),null);
+ dotest(fill_glue,stretch(fill_glue),unity);
+ dotest(fill_glue,stretch_order(fill_glue),fill);
+ dotest(fill_glue,shrink(fill_glue),0);
+ dotest(fill_glue,shrink_order(fill_glue),normal);
+
+ dotest(ss_glue,width(ss_glue),0);
+ dotest(ss_glue,type(ss_glue),glue_spec_node);
+ dotest(ss_glue,vlink(ss_glue),null);
+ dotest(ss_glue,stretch(ss_glue),unity);
+ dotest(ss_glue,stretch_order(ss_glue),fil);
+ dotest(ss_glue,shrink(ss_glue),unity);
+ dotest(ss_glue,shrink_order(ss_glue),fil);
+
+ dotest(fil_neg_glue,width(fil_neg_glue),0);
+ dotest(fil_neg_glue,type(fil_neg_glue),glue_spec_node);
+ dotest(fil_neg_glue,vlink(fil_neg_glue),null);
+ dotest(fil_neg_glue,stretch(fil_neg_glue),-unity);
+ dotest(fil_neg_glue,stretch_order(fil_neg_glue),fil);
+ dotest(fil_neg_glue,shrink(fil_neg_glue),0);
+ dotest(fil_neg_glue,shrink_order(fil_neg_glue),normal);
+}
+
+void
+check_node_mem(void ) {
+ int i;
+ check_static_node_mem();
+
+ for (i=(prealloc+1);i<var_mem_max;i++) {
+ if (varmem_sizes[i]>0) {
+ check_node(i);
+ }
+ }
+ test_count++;
+}
+
+void
+fix_node_list (halfword head) {
+ halfword p,q;
+ if (head==null)
+ return;
+ p = head;
+ q = vlink(p);
+ while (q!=null) {
+ alink(q) = p;
+ p = q;
+ q = vlink(p);
+ }
+}
+
+halfword
+get_node (integer s) {
+ register halfword r;
+
+ /*check_static_node_mem();*/
+ assert(s<MAX_CHAIN_SIZE);
+
+ r = free_chain[s];
+ if (r!=null) {
+ free_chain[s] = vlink(r);
+#ifndef NDEBUG
+ varmem_sizes[r] = s;
+#endif
+ vlink(r)=null;
+ var_used += s; /* maintain usage statistics */
+ return r;
+ }
+ /* this is the end of the 'inner loop' */
+ return slow_get_node(s);
+}
+
+void print_free_chain (int c) {
+ halfword p = free_chain[c];
+ fprintf(stdout, "\nfree chain[%d] =\n ",c);
+ while (p!=null) {
+ fprintf(stdout, "%d,",p);
+ p = vlink(p);
+ }
+ fprintf(stdout, "null;\n");
+}
+
+void
+free_node (halfword p, integer s) {
+
+ if (p<=prealloc) {
+ fprintf(stdout,"node %d (type %d) should not be freed!\n",(int)p, type(p));
+ return;
+ }
+
+#ifndef NDEBUG
+ varmem_sizes[p] = 0;
+#endif
+ if (s<MAX_CHAIN_SIZE) {
+ vlink(p) = free_chain[s];
+ free_chain[s] = p;
+ } else {
+ /* todo ? it is perhaps possible to merge this node with an existing rover */
+ node_size(p)=s;
+ vlink(p) = rover;
+ while (vlink(rover)!=vlink(p)){
+ rover=vlink(rover);
+ }
+ vlink(rover) = p;
+ }
+ var_used -= s; /* maintain statistics */
+}
+
+void
+free_node_chain (halfword q, integer s) {
+ register halfword p = q;
+ while (vlink(p)!=null) {
+#ifndef NDEBUG
+ varmem_sizes[p] = 0;
+#endif
+ var_used -= s;
+ p = vlink(p);
+ }
+ var_used -= s;
+#ifndef NDEBUG
+ varmem_sizes[p] = 0;
+#endif
+ vlink(p) = free_chain[s];
+ free_chain[s] = q;
+}
+
+
+void
+init_node_mem (halfword prealloced, halfword t) {
+ prealloc=prealloced;
+ assert(whatsit_node_data[user_defined_node].id==user_defined_node);
+ assert(node_data[passive_node].id==passive_node);
+
+ varmem = (memory_word *)realloc((void *)varmem,sizeof(memory_word)*t);
+ if (varmem==NULL) {
+ overflow_string("node memory size",var_mem_max);
+ }
+ memset ((void *)(varmem),0,t*sizeof(memory_word));
+
+#ifndef NDEBUG
+ varmem_sizes = (char *)realloc(varmem_sizes,sizeof(char)*t);
+ if (varmem_sizes==NULL) {
+ overflow_string("node memory size",var_mem_max);
+ }
+ memset ((void *)varmem_sizes,0,sizeof(char)*t);
+#endif
+ var_mem_max=t;
+ rover = prealloced+1; vlink(rover) = rover;
+ node_size(rover)=(t-rover);
+ var_used = 0;
+}
+
+void
+dump_node_mem (void) {
+ dump_int(var_mem_max);
+ dump_int(rover);
+ dump_things(varmem[0],var_mem_max);
+#ifndef NDEBUG
+ dump_things(varmem_sizes[0],var_mem_max);
+#endif
+ dump_things(free_chain[0],MAX_CHAIN_SIZE);
+ dump_int(var_used);
+ dump_int(prealloc);
+}
+
+/* it makes sense to enlarge the varmem array immediately */
+
+void
+undump_node_mem (void) {
+ int x;
+ undump_int(x);
+ undump_int(rover);
+ var_mem_max = (x<100000 ? 100000 : x);
+ varmem = xmallocarray (memory_word, var_mem_max);
+ /*memset ((void *)varmem,0,x*sizeof(memory_word));*/
+ undump_things(varmem[0],x);
+#ifndef NDEBUG
+ varmem_sizes = xmallocarray (char, var_mem_max);
+ memset ((void *)varmem_sizes,0,var_mem_max*sizeof(char));
+ undump_things(varmem_sizes[0],x);
+#endif
+ undump_things(free_chain[0],MAX_CHAIN_SIZE);
+ undump_int(var_used);
+ undump_int(prealloc);
+ if (var_mem_max>x) {
+ /* todo ? it is perhaps possible to merge the new node with an existing rover */
+ vlink (x) = rover;
+ node_size(x) = (var_mem_max-x);
+ while(vlink(rover)!=vlink(x)) {rover=vlink(rover);}
+ vlink (rover) = x;
+ }
+}
+
+#if 0
+void test_rovers (char *s) {
+ int q = rover;
+ int r = q;
+ fprintf(stdout,"%s: {rover=%d,size=%d,link=%d}",s,r,node_size(r),vlink(r));
+ while (vlink(r)!=q) {
+ r = vlink(r);
+ fprintf(stdout,",{rover=%d,size=%d,link=%d}",r,node_size(r),vlink(r));
+ }
+ fprintf(stdout,"\n");
+}
+#else
+#define test_rovers(a)
+#endif
+
+halfword
+slow_get_node (integer s) {
+ register int t;
+
+ RETRY:
+ t = node_size(rover);
+ assert(vlink(rover)<var_mem_max);
+ assert(vlink(rover)!=0);
+ test_rovers("entry");
+ if (t>s) {
+ register halfword r;
+ /* allocating from the bottom helps decrease page faults */
+ r = rover;
+ rover += s;
+ vlink(rover)=vlink(r);
+ node_size(rover) = node_size(r) - s;
+ if (vlink(rover)!=r) { /* list is longer than one */
+ halfword q = r;
+ while (vlink(q)!=r) { q=vlink(q);}
+ vlink(q) += s;
+ } else {
+ vlink(rover) += s;
+ }
+ test_rovers("taken");
+ assert(vlink(rover)<var_mem_max);
+#ifndef NDEBUG
+ varmem_sizes[r]=(s>127 ? 127 : s);
+#endif
+ vlink(r)=null;
+ var_used += s; /* maintain usage statistics */
+ return r; /* this is the only exit */
+ } else {
+ int x;
+ /* attempt to keep the free list small */
+ if (vlink(rover)!=rover) {
+ if (t<MAX_CHAIN_SIZE) {
+ halfword l = vlink(rover);
+ vlink(rover) = free_chain[t];
+ free_chain[t] = rover;
+ rover = l;
+ while (vlink(l)!=free_chain[t]) { l=vlink(l); }
+ vlink(l) = rover;
+ test_rovers("outtake");
+ goto RETRY;
+ } else {
+ halfword l = rover;
+ while (vlink(rover)!=l) {
+ if (node_size(rover)>s) {
+ goto RETRY;
+ }
+ rover=vlink(rover);
+ }
+ }
+ }
+ /* if we are still here, it was apparently impossible to get a match */
+ x = (var_mem_max>>2)+s;
+ varmem = (memory_word *)realloc((void *)varmem,sizeof(memory_word)*(var_mem_max+x));
+ if (varmem==NULL) {
+ overflow_string("node memory size",var_mem_max);
+ }
+ memset ((void *)(varmem+var_mem_max),0,x*sizeof(memory_word));
+
+#ifndef NDEBUG
+ varmem_sizes = (char *)realloc(varmem_sizes,sizeof(char)*(var_mem_max+x));
+ if (varmem_sizes==NULL) {
+ overflow_string("node memory size",var_mem_max);
+ }
+ memset ((void *)(varmem_sizes+var_mem_max),0,x*sizeof(char));
+#endif
+
+ /* todo ? it is perhaps possible to merge the new memory with an existing rover */
+ vlink(var_mem_max) = rover;
+ node_size(var_mem_max) = x;
+ while(vlink(rover)!=vlink(var_mem_max)) {rover=vlink(rover);}
+ vlink (rover) = var_mem_max;
+ rover = var_mem_max;
+ test_rovers("realloc");
+ var_mem_max += x;
+ goto RETRY;
+ }
+}
+
+char *
+sprint_node_mem_usage (void) {
+ int i,b;
+
+ char *s, *ss;
+ char msg[256];
+ int node_counts[last_normal_node+last_whatsit_node+2] = {0};
+
+ for (i=(var_mem_max-1);i>prealloc;i--) {
+ if (varmem_sizes[i]>0) {
+ if (type(i)>last_normal_node+last_whatsit_node) {
+ node_counts[last_normal_node+last_whatsit_node+1] ++;
+ } else if (type(i)==whatsit_node){
+ node_counts[(subtype(i)+last_normal_node+1)] ++;
+ } else {
+ node_counts[type(i)] ++;
+ }
+ }
+ }
+ s = strdup("");
+ b=0;
+ for (i=0;i<last_normal_node+last_whatsit_node+2;i++) {
+ if (node_counts[i]>0) {
+ int j = (i>(last_normal_node+1) ? (i-last_normal_node-1) : 0);
+ snprintf(msg,255,"%s%d %s",(b ? ", " : ""),
+ (int)node_counts[i],
+ get_node_name((i>last_normal_node ? whatsit_node : i),j));
+ ss = concat(s,msg);
+ free (s);
+ s = ss;
+ b=1;
+ }
+ }
+ return s;
+}
+
+halfword
+list_node_mem_usage (void) {
+ halfword i, j;
+ halfword p = null,q = null;
+ char *saved_varmem_sizes = xmallocarray (char, var_mem_max);
+ memcpy (saved_varmem_sizes,varmem_sizes,var_mem_max);
+ for (i=prealloc+1;i<(var_mem_max-1);i++) {
+ if (saved_varmem_sizes[i]>0) {
+ j = copy_node(i);
+ if (p==null) {
+ q = j;
+ } else {
+ vlink(p)=j;
+ }
+ p = j;
+ }
+ }
+ free(saved_varmem_sizes);
+ return q;
+}
+
+void
+print_node_mem_stats (int num, int online) {
+ int i,b;
+ halfword j;
+ char msg[256];
+ char *s;
+ integer free_chain_counts[MAX_CHAIN_SIZE] = {0};
+
+ snprintf(msg,255,"node memory in use: %d words out of %d", (int)(var_used+prealloc), (int)var_mem_max);
+ tprint_nl(msg);
+ tprint_nl("rapidly available: ");
+ b=0;
+ for (i=1;i<MAX_CHAIN_SIZE;i++) {
+ for(j = free_chain[i];j!=null;j = vlink(j))
+ free_chain_counts[i] ++;
+ if (free_chain_counts[i]>0) {
+ snprintf(msg,255,"%s%d:%d",(b ? ", " : ""),i, (int)free_chain_counts[i]);
+ tprint(msg);
+ b=1;
+ }
+ }
+ tprint(" nodes");
+ s = sprint_node_mem_usage();
+ tprint_nl("current usage: ");
+ tprint(s); free(s);
+ tprint(" nodes");
+ print_nlp(); /* newline, if needed */
+}
+
+/* this belongs in the web but i couldn't find the correct syntactic place */
+
+halfword
+new_span_node(halfword n, int s, scaled w) {
+ halfword p=new_node(span_node,0);
+ span_link(p)=n;
+ span_span(p)=s;
+ width(p)=w;
+ return p;
+}
+
+halfword
+string_to_pseudo(integer l,integer pool_ptr, integer nl) {
+ halfword i, r, q = null;
+ four_quarters w;
+ int sz;
+ halfword h = new_node(pseudo_file_node,0);
+ while (l<pool_ptr) {
+ int m = l;
+ while ((l<pool_ptr)&&(str_pool[l]!=nl)) l++;
+ sz = (l-m+7) / 4;
+ if (sz==1)
+ sz=2;
+ r = new_node(pseudo_line_node,sz);
+ i = r;
+ while (--sz>1) {
+ w.b0=str_pool[m++];
+ w.b1=str_pool[m++];
+ w.b2=str_pool[m++];
+ w.b3=str_pool[m++];
+ varmem[++i].qqqq=w;
+ }
+ w.b0 = (l>m ? str_pool[m++] : ' ');
+ w.b1 = (l>m ? str_pool[m++] : ' ');
+ w.b2 = (l>m ? str_pool[m++] : ' ');
+ w.b3 = (l>m ? str_pool[m] : ' ');
+ varmem[++i].qqqq=w;
+ if (pseudo_lines(h)==null) {
+ pseudo_lines(h) = r;
+ q = r;
+ } else {
+ couple_nodes(q,r);
+ }
+ q = vlink(q);
+ if (str_pool[l]==nl) l++;
+ }
+ return h;
+}
+
+/* attribute stuff */
+
+static halfword
+new_attribute_node (unsigned int i, int v) {
+ register halfword r = get_node(attribute_node_size);
+ type(r) = attribute_node;
+ attribute_id(r)= i;
+ attribute_value(r)= v;
+ return r;
+}
+
+halfword
+copy_attribute_list(halfword n) {
+ halfword q = get_node(attribute_node_size);
+ register halfword p = q;
+ type(p) = attribute_list_node;
+ attr_list_ref(p)=0;
+ n = vlink(n);
+ while (n!=null) {
+ register halfword r = get_node(attribute_node_size);
+ /* the link will be fixed automatically in the next loop */
+ (void)memcpy((void *)(varmem+r),(void *)(varmem+n),(sizeof(memory_word)*attribute_node_size));
+ vlink(p) = r;
+ p = r;
+ n = vlink(n);
+ }
+ return q;
+}
+
+void
+update_attribute_cache(void) {
+ halfword p;
+ register int i;
+ attr_list_cache=get_node(attribute_node_size);
+ type(attr_list_cache) = attribute_list_node;
+ attr_list_ref(attr_list_cache)=0;
+ p=attr_list_cache;
+ for (i=0;i<=max_used_attr;i++) {
+ register int v = get_attribute(i);
+ if (v>=0) {
+ register halfword r = new_attribute_node(i,v);
+ vlink(p)=r;
+ p=r;
+ }
+ }
+ if (vlink(attr_list_cache)==null) {
+ free_node(attr_list_cache,attribute_node_size);
+ attr_list_cache = null;
+ }
+ return;
+}
+
+void
+build_attribute_list(halfword b) {
+ if (max_used_attr>=0) {
+ if (attr_list_cache==cache_disabled) {
+ update_attribute_cache();
+ if (attr_list_cache == null)
+ return;
+ }
+ attr_list_ref(attr_list_cache)++;
+ node_attr(b)=attr_list_cache;
+ }
+}
+
+void
+delete_attribute_ref(halfword b) {
+ if (b!=null){
+ assert(type(b)==attribute_list_node);
+ attr_list_ref(b)--;
+ if (attr_list_ref(b)==0) {
+ if (b==attr_list_cache)
+ attr_list_cache=cache_disabled;
+ free_node_chain(b,attribute_node_size);
+ }
+ /* maintain sanity */
+ if (attr_list_ref(b)<0)
+ attr_list_ref(b)=0;
+ }
+}
+
+/* |p| is an attr list head, or zero */
+
+halfword
+do_set_attribute (halfword p, int i, int val) {
+ register halfword q;
+ register int j = 0;
+ if (p==null) { /* add a new head & node */
+ q = get_node(attribute_node_size);
+ type(q) = attribute_list_node;
+ attr_list_ref(q)=1;
+ p = new_attribute_node(i,val);
+ vlink(q)=p;
+ return q;
+ }
+
+ assert(vlink(p)!=null);
+ while (vlink(p)!=null) {
+ int t = attribute_id(vlink(p));
+ if (t==i && attribute_value(vlink(p))==val)
+ return q; /* no need to do anything */
+ if (t>=i)
+ break;
+ j++;
+ p = vlink(p);
+ }
+
+ p = q;
+ while (j-->0) p = vlink(p);
+ if (attribute_id(vlink(p))==i) {
+ attribute_value(vlink(p))=val;
+ } else { /* add a new node */
+ halfword r = new_attribute_node(i,val);
+ vlink(r)=vlink(p);
+ vlink(p)=r;
+ }
+ return q;
+}
+
+void
+set_attribute (halfword n, int i, int val) {
+ register halfword p;
+ register int j = 0;
+ if (!nodetype_has_attributes(type(n)))
+ return;
+ p = node_attr(n);
+ if (p==null) { /* add a new head & node */
+ p = get_node(attribute_node_size);
+ type(p) = attribute_list_node;
+ attr_list_ref(p)=1;
+ node_attr(n) = p ;
+ p = new_attribute_node(i,val);
+ vlink(node_attr(n))=p;
+ return;
+ }
+ assert(vlink(p)!=null);
+ while (vlink(p)!=null) {
+ int t = attribute_id(vlink(p));
+ if (t==i && attribute_value(vlink(p))==val)
+ return;
+ if (t>=i)
+ break;
+ j++;
+ p = vlink(p);
+ }
+ p = node_attr(n);
+ if (attr_list_ref(p)!=1) {
+ if (attr_list_ref(p)>1) {
+ p = copy_attribute_list (p);
+ delete_attribute_ref(node_attr(n));
+ node_attr(n) = p;
+ } else {
+ fprintf(stdout,"Node %d has an attribute list that is free already\n",(int)n);
+ }
+ attr_list_ref(p)=1;
+ }
+ while (j-->0) p = vlink(p);
+
+ if (attribute_id(vlink(p))==i) {
+ attribute_value(vlink(p))=val;
+ } else { /* add a new node */
+ halfword r = new_attribute_node(i,val);
+ vlink(r)=vlink(p);
+ vlink(p)=r;
+ }
+ return;
+}
+
+
+int
+unset_attribute (halfword n, int i, int val) {
+ register halfword p;
+ register int t;
+ register int j = 0;
+
+ if (!nodetype_has_attributes(type(n)))
+ return null;
+ p = node_attr(n);
+ if (p==null)
+ return -1;
+ assert (vlink(p)!=null);
+ while (vlink(p)!=null) {
+ t = attribute_id(vlink(p));
+ if (t>i)
+ return -1;
+ if (t==i)
+ break;
+ j++;
+ p = vlink(p);
+ }
+ /* if we are still here, the attribute exists */
+ p = node_attr(n);
+ if (attr_list_ref(p)!=1) {
+ if (attr_list_ref(p)>1) {
+ p = copy_attribute_list (p);
+ delete_attribute_ref(node_attr(n));
+ node_attr(n) = p;
+ } else {
+ fprintf(stdout,"Node %d has an attribute list that is free already\n",(int)n);
+ }
+ attr_list_ref(p)=1;
+ }
+ p = vlink(p);
+ while (j-->0) p = vlink(p);
+ t = attribute_value(p);
+ if (val==-1 || t==val) {
+ attribute_value(p)=-1;
+ }
+ return t;
+}
+
+int
+has_attribute (halfword n,int i, int val) {
+ register halfword p;
+ if (!nodetype_has_attributes(type(n)))
+ return -1;
+ p = node_attr(n);
+ if (p==null || vlink(p)==null)
+ return -1;
+ p = vlink(p);
+ while (p!=null) {
+ if (attribute_id(p)==i) {
+ int ret = attribute_value(p);
+ if (val==-1 || val==ret)
+ return ret;
+ return -1;
+ } else if (attribute_id(p)>i) {
+ return -1;
+ }
+ p=vlink(p);
+ }
+ return -1;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/tex/texpdf.c b/Build/source/texk/web2c/luatexdir/tex/texpdf.c
new file mode 100644
index 00000000000..fbb4c2b7e21
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/tex/texpdf.c
@@ -0,0 +1,169 @@
+/* $Id: texpdf.c 1013 2008-02-14 00:09:02Z oneiros $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+#include <ctype.h>
+
+#define number_chars 1114112
+#define string_offset 2097152
+#define str_start_macro(a) str_start[(a) - string_offset]
+#define str_length(a) (str_start_macro((a)+1)-str_start_macro(a)) /* the number of characters in string number (a) */
+
+#define is_hex_char isxdigit
+
+/* output a byte to PDF buffer without checking of overflow */
+
+#define pdf_quick_out(a) pdf_buf[pdf_ptr++] = a
+
+/* make sure that there are at least |n| bytes free in PDF buffer */
+
+#define pdf_room(a) do { \
+ if ((pdf_os_mode) && ((a) + pdf_ptr > pdf_buf_size)) \
+ pdf_os_get_os_buf(a); \
+ else if ((!pdf_os_mode) && ((a) > pdf_buf_size) ) \
+ overflow("PDF output buffer", pdf_op_buf_size); \
+ else if ((!pdf_os_mode) && ((a) + pdf_ptr > pdf_buf_size)) \
+ pdf_flush(); \
+ } while (0)
+
+/* do the same as |pdf_quick_out| and flush the PDF buffer if necessary */
+
+#define pdf_out(a) do { \
+ pdf_room(1); \
+ pdf_quick_out(a); \
+ } while (0)
+
+
+/* print out a character to PDF buffer; the character will be printed in octal
+ * form in the following cases: chars <= 32, backslash (92), left parenthesis
+ * (40) and right parenthesis (41)
+ */
+
+#define pdf_print_escaped(c) \
+ if ((c)<=32||(c)=='\\'||(c)=='('||(c)==')'||(c)>127) { \
+ pdf_room(4); \
+ pdf_quick_out('\\'); \
+ pdf_quick_out('0' + (((c)>>6) & 0x3)); \
+ pdf_quick_out('0' + (((c)>>3) & 0x7)); \
+ pdf_quick_out('0' + ( (c) & 0x7)); \
+ } else { \
+ pdf_out((c)); \
+ }
+
+void
+pdf_print_char(internal_font_number f, integer cc) {
+ register int c;
+ pdf_mark_char(f, cc);
+ if (font_encodingbytes(f)==2) {
+ register int chari;
+ chari = char_index(f, cc);
+ c = chari >> 8;
+ pdf_print_escaped(c);
+ c = chari & 0xFF;
+ } else {
+ if (cc>255) return;
+ c = cc;
+ }
+ pdf_print_escaped(c);
+}
+
+/* print out a string to PDF buffer */
+
+void
+pdf_print(str_number s) {
+ if (s < number_chars) {
+ assert(s<256);
+ pdf_out(s);
+ } else {
+ register pool_pointer j = str_start_macro(s);
+ while (j < str_start_macro(s + 1)) {
+ pdf_out(str_pool[j++]);
+ }
+ }
+}
+
+/* print out a integer to PDF buffer */
+
+void
+pdf_print_int(integer n) {
+ register integer k = 0; /* current digit; we assume that $|n|<10^{23}$ */
+ if (n<0) {
+ pdf_out('-');
+ if (n<-0x7FFFFFFF) { /* need to negate |n| more carefully */
+ register integer m;
+ k++;
+ m =-1-n; n=m / 10; m= (m % 10)+1;
+ if (m<10) {
+ dig[0]=m ;
+ } else {
+ dig[0]=0; incr(n);
+ }
+ } else {
+ n = -n;
+ }
+ }
+ do {
+ dig[k++] = n % 10;
+ n = n / 10;
+ } while (n!=0);
+ pdf_room(k);
+ while (k-->0) {
+ pdf_quick_out('0'+dig[k]);
+ }
+}
+
+
+/* print $m/10^d$ as real */
+void
+pdf_print_real(integer m, integer d) {
+ if (m < 0) {
+ pdf_out('-');
+ m = -m;
+ };
+ pdf_print_int(m / ten_pow[d]);
+ m = m % ten_pow[d];
+ if (m > 0) {
+ pdf_out('.');
+ d--;
+ while (m < ten_pow[d]) {
+ pdf_out('0');
+ d--;
+ }
+ while (m % 10 == 0)
+ m = m / 10;
+ pdf_print_int(m);
+ }
+}
+
+/* print out |s| as string in PDF output */
+
+void
+pdf_print_str(str_number s) {
+ pool_pointer i, j;
+ i = str_start_macro(s);
+ j = str_start_macro(s+1) - 1;
+ if (i > j) {
+ pdf_room(2);
+ pdf_quick_out('(');
+ pdf_quick_out(')');
+ return;
+ }
+ /* the next is not really safe, the string could be "(a)xx(b)" */
+ if ((str_pool[i] == '(') && (str_pool[j] == ')')) {
+ pdf_print(s);
+ return;
+ }
+ if ((str_pool[i] != '<') || (str_pool[j] != '>') || odd(str_length(s))) {
+ pdf_out('('); pdf_print(s); pdf_out(')');
+ return;
+ }
+ i++;
+ j--;
+ while (i < j) {
+ if (!is_hex_char(str_pool[i++])) {
+ pdf_out('('); pdf_print(s); pdf_out(')');
+ return;
+ }
+ }
+ pdf_print(s); /* it was a hex string after all */
+}
diff --git a/Build/source/texk/web2c/luatexdir/tex/textoken.c b/Build/source/texk/web2c/luatexdir/tex/textoken.c
new file mode 100644
index 00000000000..20c57b9479b
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/tex/textoken.c
@@ -0,0 +1,753 @@
+/* $Id: textoken.c 1013 2008-02-14 00:09:02Z oneiros $ */
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+#include "tokens.h"
+
+/* Integer parameters and other command-related defines. This needs it's own header file! */
+
+#define end_line_char_code 48 /* character placed at the right end of the buffer */
+#define cat_code_table_code 63
+#define tex_int_pars 66 /* total number of \.{\\TeX} + Aleph integer parameters */
+/* this is not what happens in the pascal code! there the values shift from bare numbers to offsets ! */
+#define dir_base tex_int_pars
+#define dir_pars 5
+#define pdftex_first_integer_code dir_base+dir_pars /* base for \pdfTeX's integer parameters */
+#define pdf_int_pars pdftex_first_integer_code+27 /*total number of \pdfTeX's integer parameters*/
+#define etex_int_base pdf_int_pars /*base for \eTeX's integer parameters*/
+#define tracing_nesting_code etex_int_base+4 /*show incomplete groups and ifs within files*/
+
+#define int_par(a) zeqtb[static_int_base+a].cint /* an integer parameter */
+#define cat_code_table int_par(cat_code_table_code)
+#define tracing_nesting int_par(tracing_nesting_code)
+#define end_line_char int_par(end_line_char_code)
+
+#define every_eof get_every_eof()
+
+#define number_active_chars 65536+65536
+#define active_base 1 /* beginning of region 1, for active character equivalents */
+#define null_cs active_base+number_active_chars /* equivalent of \.{\\csname\\endcsname} */
+
+
+#define eq_level(a) zeqtb[a].hh.u.B1
+#define eq_type(a) zeqtb[a].hh.u.B0
+#define equiv(a) zeqtb[a].hh.v.RH
+
+/* leave an input level, re-enter the old */
+#define pop_input() cur_input=input_stack[--input_ptr]
+
+#define nonstop_mode 1
+
+/* command codes */
+#define relax 0
+#define out_param 5
+#define max_command 117 /* fetched from C output */
+#define dont_expand 133 /* fetched from C output */
+
+#define terminal_input (name==0) /* are we reading from the terminal? */
+#define special_char 1114113 /* |biggest_char+2| */
+#define cur_file input_file[index] /* the current |alpha_file| variable */
+
+#define no_expand_flag special_char /*this characterizes a special variant of |relax|*/
+
+extern void insert_vj_template (void);
+
+#define do_get_cat_code(a) do { \
+ if (local_catcode_table) \
+ a=get_cat_code(line_catcode_table,cur_chr); \
+ else \
+ a=get_cat_code(cat_code_table,cur_chr); \
+ } while (0)
+
+
+static void
+invalid_character_error (void) {
+ char *hlp[] = {"A funny symbol that I can't read has just been input.",
+ "Continue, and I'll forget that it ever happened.",
+ NULL};
+ deletions_allowed=false;
+ tex_error("Text line contains an invalid character", hlp);
+ deletions_allowed=true;
+}
+
+/* no longer done */
+
+static boolean process_sup_mark(void); /* below */
+
+static int scan_control_sequence(void); /* below */
+
+typedef enum {next_line_ok, next_line_return, next_line_restart } next_line_retval ;
+
+static next_line_retval next_line(void); /* below */
+
+/* @^inner loop@>*/
+
+static void
+utf_error (void) {
+ char *hlp[] = {"A funny symbol that I can't read has just been input.",
+ "Just continue, I'll change it to 0xFFFD.",
+ NULL };
+ deletions_allowed=false;
+ tex_error("Text line contains an invalid utf-8 sequence", hlp);
+ deletions_allowed=true;
+}
+
+static integer
+qbuffer_to_unichar (integer *k) {
+ register int ch;
+ int val = 0xFFFD;
+ unsigned char *text = buffer+*k;
+ if ( (ch = *text++)<0x80 ) {
+ val = ch;
+ *k+=1;
+ } else if ( ch<=0xbf ) { /* error */
+ *k+=1;
+ } else if ( ch<=0xdf ) {
+ if ( *text>=0x80 && *text<0xc0 )
+ val = ((ch&0x1f)<<6) | (*text++&0x3f);
+ *k+=2;
+ } else if ( ch<=0xef ) {
+ if ( *text>=0x80 && *text<0xc0 && text[1]>=0x80 && text[1]<0xc0 ) {
+ val = ((ch&0xf)<<12) | ((text[0]&0x3f)<<6) | (text[1]&0x3f);
+ *k+=3;
+ }
+ } else {
+ int w = ( ((ch&0x7)<<2) | ((text[0]&0x30)>>4) )-1, w2;
+ w = (w<<6) | ((text[0]&0xf)<<2) | ((text[1]&0x30)>>4);
+ w2 = ((text[1]&0xf)<<6) | (text[2]&0x3f);
+ val = w*0x400 + w2 + 0x10000;
+ if ( *text<0x80 || text[1]<0x80 || text[2]<0x80 ||
+ *text>=0xc0 || text[1]>=0xc0 || text[2]>=0xc0 )
+ val = 0xFFFD;
+ *k+=4;
+ }
+ if (val==0xFFFD)
+ utf_error();
+ return( val );
+}
+
+static boolean
+get_next_file (void) {
+ SWITCH:
+ if (loc<=limit) { /* current line not yet finished */
+ cur_chr = qbuffer_to_unichar(&loc);
+ RESWITCH:
+ if (detokenized_line) {
+ cur_cmd = (cur_chr==' ' ? 10 : 12) ;
+ } else {
+ do_get_cat_code(cur_cmd);
+ }
+ /*
+ @<Change state if necessary, and |goto switch| if the current
+ character should be ignored, or |goto reswitch| if the current
+ character changes to another@>;
+ */
+ /* The following 48-way switch accomplishes the scanning quickly, assuming
+ that a decent \PASCAL\ compiler has translated the code. Note that the numeric
+ values for |mid_line|, |skip_blanks|, and |new_line| are spaced
+ apart from each other by |max_char_code+1|, so we can add a character's
+ command code to the state to get a single number that characterizes both.
+ */
+ switch(state+cur_cmd) {
+ case mid_line + ignore:
+ case skip_blanks + ignore:
+ case new_line + ignore:
+ case skip_blanks + spacer:
+ case new_line + spacer: /* @<Cases where character is ignored@> */
+ goto SWITCH;
+ break;
+ case mid_line + escape:
+ case new_line + escape:
+ case skip_blanks + escape: /* @<Scan a control sequence ...@>;*/
+ state = scan_control_sequence();
+ break;
+ case mid_line + active_char:
+ case new_line + active_char:
+ case skip_blanks + active_char: /* @<Process an active-character */
+ cur_cs=cur_chr+active_base;
+ cur_cmd=eq_type(cur_cs);
+ cur_chr=equiv(cur_cs);
+ state=mid_line;
+ break;
+ case mid_line + sup_mark:
+ case new_line + sup_mark:
+ case skip_blanks + sup_mark: /* @<If this |sup_mark| starts */
+ if (process_sup_mark())
+ goto RESWITCH;
+ else
+ state=mid_line;
+ break;
+ case mid_line + invalid_char:
+ case new_line + invalid_char:
+ case skip_blanks + invalid_char: /* @<Decry the invalid character and |goto restart|@>;*/
+ invalid_character_error();
+ return false; /* because state may be token_list now */
+ break;
+ case mid_line + spacer: /* @<Enter |skip_blanks| state, emit a space@>;*/
+ state=skip_blanks;
+ cur_chr=' ';
+ break;
+ case mid_line + car_ret: /* @<Finish line, emit a space@>;*/
+ /* When a character of type |spacer| gets through, its character code is
+ changed to $\.{"\ "}=@'40$. This means that the ASCII codes for tab and space,
+ and for the space inserted at the end of a line, will
+ be treated alike when macro parameters are being matched. We do this
+ since such characters are indistinguishable on most computer terminal displays.
+ */
+ loc=limit+1;
+ cur_cmd=spacer;
+ cur_chr=' ';
+ break;
+ case skip_blanks + car_ret:
+ case mid_line + comment:
+ case new_line + comment:
+ case skip_blanks + comment: /* @<Finish line, |goto switch|@>;*/
+ loc=limit+1;
+ goto SWITCH;
+ break;
+ case new_line + car_ret: /* @<Finish line, emit a \.{\\par}@>;*/
+ loc=limit+1;
+ cur_cs=par_loc;
+ cur_cmd=eq_type(cur_cs);
+ cur_chr=equiv(cur_cs);
+ break;
+ case skip_blanks + left_brace:
+ case new_line + left_brace:
+ state=mid_line; /* fall through */
+ case mid_line + left_brace:
+ align_state++;
+ break;
+ case skip_blanks + right_brace:
+ case new_line + right_brace:
+ state=mid_line; /* fall through */
+ case mid_line + right_brace:
+ align_state--;
+ break;
+ case mid_line + math_shift:
+ case mid_line + tab_mark:
+ case mid_line + mac_param:
+ case mid_line + sub_mark:
+ case mid_line + letter:
+ case mid_line + other_char:
+ break;
+ default:
+ /*
+ case skip_blanks + math_shift:
+ case skip_blanks + tab_mark:
+ case skip_blanks + mac_param:
+ case skip_blanks + sub_mark:
+ case skip_blanks + letter:
+ case skip_blanks + other_char:
+ case new_line + math_shift:
+ case new_line + tab_mark:
+ case new_line + mac_param:
+ case new_line + sub_mark:
+ case new_line + letter:
+ case new_line + other_char:
+ */
+ state=mid_line;
+ break;
+ }
+ } else {
+ if (current_ocp_lstack>0) {
+ pop_input();
+ return false;
+ }
+ if (name!=21)
+ state=new_line;
+
+ /*
+ @<Move to next line of file,
+ or |goto restart| if there is no next line,
+ or |return| if a \.{\\read} line has finished@>;
+ */
+ do {
+ next_line_retval r = next_line();
+ if (r==next_line_return) {
+ return true;
+ } else if (r==next_line_restart) {
+ return false;
+ }
+ } while (0);
+ check_interrupt();
+ goto SWITCH;
+ }
+ return true;
+}
+
+#define is_hex(a) ((a>='0'&&a<='9')||(a>='a'&&a<='f'))
+
+#define add_nybble(a) do { \
+ if (a<='9') cur_chr=(cur_chr<<4)+a-'0'; \
+ else cur_chr=(cur_chr<<4)+a-'a'+10; \
+ } while (0)
+
+#define hex_to_cur_chr do { \
+ if (c<='9') cur_chr=c-'0'; \
+ else cur_chr=c-'a'+10; \
+ add_nybble(cc); \
+ } while (0)
+
+#define four_hex_to_cur_chr do { \
+ hex_to_cur_chr; \
+ add_nybble(ccc); add_nybble(cccc); \
+ } while (0)
+
+#define five_hex_to_cur_chr do { \
+ four_hex_to_cur_chr; \
+ add_nybble(ccccc); \
+ } while (0)
+
+#define six_hex_to_cur_chr do { \
+ five_hex_to_cur_chr; \
+ add_nybble(cccccc); \
+ } while (0)
+
+
+/* Notice that a code like \.{\^\^8} becomes \.x if not followed by a hex digit.*/
+
+static boolean
+process_sup_mark(void) {
+ if (cur_chr==buffer[loc]) {
+ int c,cc;
+ if (loc<limit) {
+ if ((cur_chr==buffer[loc+1]) && (cur_chr==buffer[loc+2])
+ && (cur_chr==buffer[loc+3]) && (cur_chr==buffer[loc+4])
+ && ((loc+10)<=limit)) {
+ int ccc,cccc,ccccc,cccccc; /* constituents of a possible expanded code */
+ c=buffer[loc+5];
+ cc=buffer[loc+6];
+ ccc=buffer[loc+7];
+ cccc=buffer[loc+8];
+ ccccc=buffer[loc+9];
+ cccccc=buffer[loc+10];
+ if ((is_hex(c)) && (is_hex(cc)) && (is_hex(ccc)) && (is_hex(cccc))
+ && (is_hex(ccccc)) && (is_hex(cccccc))) {
+ loc=loc+11;
+ six_hex_to_cur_chr;
+ return true;
+ }
+ }
+ if ((cur_chr==buffer[loc+1]) && (cur_chr==buffer[loc+2])
+ && (cur_chr==buffer[loc+3]) && ((loc+8)<=limit)) {
+ int ccc,cccc,ccccc; /* constituents of a possible expanded code */
+ c=buffer[loc+4];
+ cc=buffer[loc+5];
+ ccc=buffer[loc+6];
+ cccc=buffer[loc+7];
+ ccccc=buffer[loc+8];
+ if ((is_hex(c)) && (is_hex(cc)) && (is_hex(ccc)) && (is_hex(cccc)) && (is_hex(ccccc))) {
+ loc=loc+9;
+ five_hex_to_cur_chr;
+ return true;
+ }
+ }
+ if ((cur_chr==buffer[loc+1]) && (cur_chr==buffer[loc+2]) && ((loc+6)<=limit)) {
+ int ccc,cccc; /* constituents of a possible expanded code */
+ c=buffer[loc+3];
+ cc=buffer[loc+4];
+ ccc=buffer[loc+5];
+ cccc=buffer[loc+6];
+ if ((is_hex(c)) && (is_hex(cc)) && (is_hex(ccc)) && (is_hex(cccc))) {
+ loc=loc+7;
+ four_hex_to_cur_chr;
+ return true;
+ }
+ }
+ c = buffer[loc+1];
+ if (c<0200) { /* yes we have an expanded char */
+ loc=loc+2;
+ if (is_hex(c) && loc<=limit) {
+ cc=buffer[loc];
+ if (is_hex(cc)){
+ incr(loc);
+ hex_to_cur_chr;
+ return true;
+ }
+ }
+ cur_chr = (c<0100 ? c+0100 : c-0100);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/* Control sequence names are scanned only when they appear in some line of
+ a file; once they have been scanned the first time, their |eqtb| location
+ serves as a unique identification, so \TeX\ doesn't need to refer to the
+ original name any more except when it prints the equivalent in symbolic form.
+
+ The program that scans a control sequence has been written carefully
+ in order to avoid the blowups that might otherwise occur if a malicious
+ user tried something like `\.{\\catcode\'15=0}'. The algorithm might
+ look at |buffer[limit+1]|, but it never looks at |buffer[limit+2]|.
+
+ If expanded characters like `\.{\^\^A}' or `\.{\^\^df}'
+ appear in or just following
+ a control sequence name, they are converted to single characters in the
+ buffer and the process is repeated, slowly but surely.
+*/
+
+static boolean check_expanded_code (integer *kk) ; /* below */
+
+static int scan_control_sequence (void ) {
+ int retval = mid_line;
+ if (loc>limit) {
+ cur_cs=null_cs; /* |state| is irrelevant in this case */
+ } else {
+ register int cat; /* |cat_code(cur_chr)|, usually */
+ while (1) {
+ integer k=loc;
+ cur_chr = qbuffer_to_unichar(&k);
+ do_get_cat_code(cat);
+ if (cat!=letter||k>limit) {
+ retval = (cat==spacer ? skip_blanks : mid_line);
+ if (cat==sup_mark && check_expanded_code(&k)) /* @<If an expanded...@>; */
+ continue;
+ } else {
+ retval=skip_blanks;
+ do {
+ cur_chr = qbuffer_to_unichar(&k);
+ do_get_cat_code(cat);
+ } while (cat==letter&&k<=limit);
+
+ if (cat==sup_mark && check_expanded_code(&k)) /* @<If an expanded...@>; */
+ continue;
+ if (cat!=letter) {
+ decr(k);
+ if (cur_chr>0xFFFF) decr(k);
+ if (cur_chr>0x7FF) decr(k);
+ if (cur_chr>0x7F) decr(k);
+ } /* now |k| points to first nonletter */
+ }
+ cur_cs=id_lookup(loc,k-loc);
+ loc=k;
+ break;
+ }
+ }
+ cur_cmd=eq_type(cur_cs);
+ cur_chr=equiv(cur_cs);
+ return retval;
+}
+
+/* Whenever we reach the following piece of code, we will have
+ |cur_chr=buffer[k-1]| and |k<=limit+1| and |cat=get_cat_code(cat_code_table,cur_chr)|. If an
+ expanded code like \.{\^\^A} or \.{\^\^df} appears in |buffer[(k-1)..(k+1)]|
+ or |buffer[(k-1)..(k+2)]|, we
+ will store the corresponding code in |buffer[k-1]| and shift the rest of
+ the buffer left two or three places.
+*/
+
+static boolean
+check_expanded_code (integer *kk) {
+ int l;
+ int k = *kk;
+ int d =1; /* number of excess characters in an expanded code */
+ int c,cc,ccc,cccc,ccccc,cccccc; /* constituents of a possible expanded code */
+ if (buffer[k]==cur_chr && k<limit) {
+ if ((cur_chr==buffer[k+1]) && (cur_chr==buffer[k+2]) && ((k+6)<=limit)) {
+ d = 4;
+ if ((cur_chr==buffer[k+3]) && ((k+8)<=limit))
+ d = 5;
+ if ((cur_chr==buffer[k+4]) && ((k+10)<=limit))
+ d = 6;
+ c = buffer[k+d-1];
+ cc = buffer[k+d];
+ ccc = buffer[k+d+1];
+ cccc= buffer[k+d+2];
+ if (d==6) {
+ ccccc =buffer[k+d+3];
+ cccccc=buffer[k+d+4];
+ if (is_hex(c) && is_hex(cc) && is_hex(ccc) && is_hex(cccc)
+ && is_hex(ccccc) && is_hex(cccccc))
+ six_hex_to_cur_chr;
+ } else if (d==5) {
+ ccccc=buffer[k+d+3];
+ if (is_hex(c) && is_hex(cc) && is_hex(ccc) && is_hex(cccc) && is_hex(ccccc))
+ five_hex_to_cur_chr;
+ } else {
+ if (is_hex(c) && is_hex(cc) && is_hex(ccc) && is_hex(cccc))
+ four_hex_to_cur_chr;
+ }
+ } else {
+ c=buffer[k+1];
+ if (c<0200) {
+ d=1;
+ if (is_hex(c) && (k+2)<=limit) {
+ cc=buffer[k+2];
+ if (is_hex(c) && is_hex(cc)) {
+ d=2;
+ hex_to_cur_chr;
+ }
+ } else if (c<0100) {
+ cur_chr=c+0100;
+ } else {
+ cur_chr=c-0100;
+ }
+ }
+ }
+ if (d>2)
+ d=2*d-1;
+ else
+ d++;
+ if (cur_chr <= 0x7F) {
+ buffer[k-1]= cur_chr;
+ } else if (cur_chr<=0x7FF) {
+ buffer[k-1]=0xC0 + cur_chr / 0x40;
+ k++; d--;
+ buffer[k-1]=0x80 + cur_chr % 0x40;
+ } else if (cur_chr<=0xFFFF){
+ buffer[k-1]=0xE0 + cur_chr / 0x1000;
+ k++; d--;
+ buffer[k-1]=0x80 + (cur_chr % 0x1000) / 0x40;
+ k++; d--;
+ buffer[k-1]=0x80 + (cur_chr % 0x1000) % 0x40;
+ } else {
+ buffer[k-1]=0xF0 + cur_chr / 0x40000;
+ k++; d--;
+ buffer[k-1]=0x80 + (cur_chr % 0x40000) / 0x1000;
+ k++; d--;
+ buffer[k-1]=0x80 + ((cur_chr % 0x40000) % 0x1000) / 0x40;
+ k++; d--;
+ buffer[k-1]=0x80 + ((cur_chr % 0x40000) % 0x1000) % 0x40;
+ }
+ l = k;
+ limit = limit - d;
+ while (l<=limit) {
+ buffer[l]=buffer[l+d];
+ l++;
+ }
+ *kk =k;
+ return true;
+ }
+ return false;
+}
+
+#define end_line_char_inactive ((end_line_char<0)||(end_line_char>127))
+
+/* The global variable |force_eof| is normally |false|; it is set |true|
+ by an \.{\\endinput} command.
+
+ @<Glob...@>=
+ @!force_eof:boolean; {should the next \.{\\input} be aborted early?}
+
+*/
+
+
+/* All of the easy branches of |get_next| have now been taken care of.
+ There is one more branch.
+*/
+
+static next_line_retval
+next_line (void) {
+ integer tab; /* a category table */
+ boolean inhibit_eol = false; /* a way to end a pseudo file without trailing space */
+ detokenized_line=false;
+ local_catcode_table=false;
+ if (name>17) {
+ /* @<Read next line of file into |buffer|, or |goto restart| if the file has ended@> */
+ incr(line);
+ first=start;
+ if (!force_eof) {
+ if (name<=20) {
+ if (pseudo_input()) { /* not end of file */
+ firm_up_the_line(); /* this sets |limit| */
+ if ((name==19)&&(pseudo_lines(pseudo_files)==null))
+ inhibit_eol=true;
+ } else if ((every_eof!=null)&&!eof_seen[index]) {
+ limit=first-1; eof_seen[index]=true; /* fake one empty line */
+ if (name!=19)
+ begin_token_list(every_eof,every_eof_text);
+ return next_line_restart;
+ } else {
+ force_eof=true;
+ }
+ } else {
+ if (name==21) {
+ if (luacstring_input()) { /* not end of strings */
+ firm_up_the_line();
+ if ((luacstring_penultimate())||(luacstring_simple()))
+ inhibit_eol=true;
+ if (!luacstring_simple())
+ state=new_line;
+ if (luacstring_detokenized()) {
+ inhibit_eol=true;
+ detokenized_line=true;
+ } else {
+ if (! luacstring_defaultcattable()) {
+ tab=luacstring_cattable();
+ if (valid_catcode_table(tab)) {
+ local_catcode_table=true;
+ line_catcode_table=tab;
+ }
+ }
+ }
+ } else {
+ force_eof=true;
+ }
+ } else {
+ if (lua_input_ln(cur_file,0,true)) { /* not end of file */
+ firm_up_the_line(); /* this sets |limit| */
+ } else if ((every_eof!=null)&& (!eof_seen[index])) {
+ limit=first-1; eof_seen[index]=true; /* fake one empty line */
+ begin_token_list(every_eof,every_eof_text);
+ return next_line_restart;
+ } else {
+ force_eof=true;
+ }
+ }
+ }
+ }
+ if (force_eof) {
+ if (tracing_nesting>0)
+ if ((grp_stack[in_open]!=cur_boundary)||(if_stack[in_open]!=cond_ptr))
+ if (!((name==19)||(name=21)))
+ file_warning(); /* give warning for some unfinished groups and/or conditionals */
+ if ((name>21)||(name==20)) {
+ if (tracefilenames)
+ print_char(')');
+ open_parens--;
+ /* update_terminal();*/ /* show user that file has been read */
+ }
+ force_eof=false;
+ end_file_reading();
+ return next_line_restart;
+ }
+ if (inhibit_eol||end_line_char_inactive)
+ limit--;
+ else
+ buffer[limit]=end_line_char;
+ first=limit+1;
+ loc=start; /* ready to read */
+ } else {
+ if (!terminal_input) { /* \.{\\read} line has ended */
+ cur_cmd=0;
+ cur_chr=0;
+ return next_line_return; /* OUTER */
+ }
+ if (input_ptr>0) { /* text was inserted during error recovery */
+ end_file_reading();
+ return next_line_restart; /* resume previous level */
+ }
+ if (selector<log_only)
+ open_log_file();
+ if (interaction>nonstop_mode) {
+ if (end_line_char_inactive)
+ limit++;
+ if (limit==start) { /* previous line was empty */
+ tprint_nl("(Please type a command or say `\\end')");
+ }
+ print_ln();
+ first=start;
+ prompt_input((str_number)'*'); /* input on-line into |buffer| */
+ limit=last;
+ if (end_line_char_inactive)
+ limit--;
+ else
+ buffer[limit]=end_line_char;
+ first=limit+1;
+ loc=start;
+ } else {
+ fatal_error(maketexstring("*** (job aborted, no legal \\end found)"));
+ /* nonstop mode, which is intended for overnight batch processing,
+ never waits for on-line input */
+ }
+ }
+ return next_line_ok;
+}
+
+
+
+
+/* Let's consider now what happens when |get_next| is looking at a token list. */
+
+static boolean
+get_next_tokenlist (void) {
+ register halfword t; /* a token*/
+ t=info(loc);
+ loc=link(loc); /* move to next */
+ if (t>=cs_token_flag) { /* a control sequence token */
+ cur_cs=t-cs_token_flag;
+ cur_cmd=eq_type(cur_cs);
+ if (cur_cmd==dont_expand) { /* @<Get the next token, suppressing expansion@>*/
+ /* The present point in the program is reached only when the |expand|
+ routine has inserted a special marker into the input. In this special
+ case, |info(loc)| is known to be a control sequence token, and |link(loc)=null|.
+ */
+ cur_cs=info(loc)-cs_token_flag;
+ loc=null;
+ cur_cmd=eq_type(cur_cs);
+ if (cur_cmd>max_command) {
+ cur_cmd=relax;
+ cur_chr=no_expand_flag;
+ return true;
+ }
+ }
+ cur_chr=equiv(cur_cs);
+ } else {
+ cur_cmd=t >> string_offset_bits; /* cur_cmd=t / string_offset; */
+ cur_chr=t & (string_offset-1); /* cur_chr=t % string_offset; */
+ switch (cur_cmd) {
+ case left_brace:
+ align_state++;
+ break;
+ case right_brace:
+ align_state--;
+ break;
+ case out_param: /* @<Insert macro parameter and |goto restart|@>; */
+ begin_token_list(param_stack[param_start+cur_chr-1],parameter);
+ return false;
+ break;
+ }
+ }
+ return true;
+}
+
+/* Now we're ready to take the plunge into |get_next| itself. Parts of
+ this routine are executed more often than any other instructions of \TeX.
+ @^mastication@>@^inner loop@>
+*/
+
+/* sets |cur_cmd|, |cur_chr|, |cur_cs| to next token */
+
+void
+get_next (void) {
+ RESTART:
+ cur_cs=0;
+ if (state!=token_list) {
+ /* Input from external file, |goto restart| if no input found */
+ if (!get_next_file())
+ goto RESTART;
+ } else {
+ if (loc==null) {
+ end_token_list();
+ goto RESTART; /* list exhausted, resume previous level */
+ } else if (!get_next_tokenlist()) {
+ goto RESTART; /* parameter needs to be expanded */
+ }
+ }
+ /* @<If an alignment entry has just ended, take appropriate action@> */
+ if ((cur_cmd==tab_mark || cur_cmd==car_ret) && align_state==0) {
+ insert_vj_template();
+ goto RESTART;
+ }
+}
+
+void
+get_token_lua (void) {
+ register int callback_id ;
+ callback_id = callback_defined(token_filter_callback);
+ if (callback_id!=0) {
+ while (state==token_list && loc==null && index!=v_template)
+ end_token_list();
+ /* there is some stuff we don't want to see inside the callback */
+ if (!(state==token_list &&
+ ((nofilter==true) || (index==backed_up && loc!=null)))) {
+ do_get_token_lua(callback_id);
+ return;
+ }
+ }
+ get_next();
+}
diff --git a/Build/source/texk/web2c/luatexdir/textcodes.c b/Build/source/texk/web2c/luatexdir/textcodes.c
new file mode 100644
index 00000000000..05f85b941c4
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/textcodes.c
@@ -0,0 +1,278 @@
+
+/*
+Copyright (c) 2006 Taco Hoekwater, <taco@elvenkind.com>
+
+This file is part of LuaTeX.
+
+LuaTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+LuaTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with LuaTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id $
+*/
+
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+#include <stdarg.h>
+
+#include "managed-sa.h"
+
+#define LCCODESTACK 8
+#define LCCODEDEFAULT 0
+
+static sa_tree lccode_head = NULL;
+
+#define UCCODESTACK 8
+#define UCCODEDEFAULT 0
+
+static sa_tree uccode_head = NULL;
+
+#define SFCODESTACK 8
+#define SFCODEDEFAULT 1000
+
+static sa_tree sfcode_head = NULL;
+
+#define CATCODESTACK 8
+#define CATCODEDEFAULT 12
+
+void set_lc_code (integer n, halfword v, quarterword gl) {
+ set_sa_item(lccode_head,n,v,gl);
+}
+
+halfword get_lc_code (integer n) {
+ return (halfword)get_sa_item(lccode_head,n);
+}
+
+static void unsavelccodes (quarterword gl) {
+ restore_sa_stack(lccode_head,gl);
+}
+
+static void initializelccodes (void) {
+ lccode_head = new_sa_tree(LCCODESTACK,LCCODEDEFAULT);
+}
+
+static void dumplccodes (void) {
+ dump_sa_tree(lccode_head);
+}
+
+static void undumplccodes (void) {
+ lccode_head = undump_sa_tree();
+}
+
+void set_uc_code (integer n, halfword v, quarterword gl) {
+ set_sa_item(uccode_head,n,v,gl);
+}
+
+halfword get_uc_code (integer n) {
+ return (halfword)get_sa_item(uccode_head,n);
+}
+
+static void unsaveuccodes (quarterword gl) {
+ restore_sa_stack(uccode_head,gl);
+}
+
+static void initializeuccodes (void) {
+ uccode_head = new_sa_tree(UCCODESTACK,UCCODEDEFAULT);
+}
+
+static void dumpuccodes (void) {
+ dump_sa_tree(uccode_head);
+}
+
+static void undumpuccodes (void) {
+ uccode_head = undump_sa_tree();
+}
+
+void set_sf_code (integer n, halfword v, quarterword gl) {
+ set_sa_item(sfcode_head,n,v,gl);
+}
+
+halfword get_sf_code (integer n) {
+ return (halfword)get_sa_item(sfcode_head,n);
+}
+
+static void unsavesfcodes (quarterword gl) {
+ restore_sa_stack(sfcode_head,gl);
+}
+
+static void initializesfcodes (void) {
+ sfcode_head = new_sa_tree(SFCODESTACK,SFCODEDEFAULT);
+}
+
+static void dumpsfcodes (void) {
+ dump_sa_tree(sfcode_head);
+}
+
+static void undumpsfcodes (void) {
+ sfcode_head = undump_sa_tree();
+}
+
+
+static sa_tree *catcode_heads = NULL;
+static int catcode_max = 0;
+static unsigned char *catcode_valid = NULL;
+
+void check_catcode_sizes (int h) {
+ int k;
+ if (h < 0)
+ uexit(1);
+ if (h>catcode_max) {
+ catcode_heads = Mxrealloc_array(catcode_heads,sa_tree,(h+1));
+ catcode_valid = Mxrealloc_array(catcode_valid,unsigned char,(h+1));
+ for (k=(catcode_max+1);k<=h;k++) {
+ catcode_heads[k] = NULL;
+ catcode_valid[k] = 0;
+ }
+ catcode_max = h;
+ }
+}
+
+void set_cat_code (integer h, integer n, halfword v, quarterword gl) {
+ check_catcode_sizes(h);
+ if (catcode_heads[h] == NULL) {
+ catcode_heads[h] = new_sa_tree(CATCODESTACK,CATCODEDEFAULT);
+ }
+ set_sa_item(catcode_heads[h],n,v,gl);
+}
+
+halfword get_cat_code (integer h, integer n) {
+ check_catcode_sizes(h);
+ if (catcode_heads[h] == NULL) {
+ catcode_heads[h] = new_sa_tree(CATCODESTACK,CATCODEDEFAULT);
+ }
+ return (halfword)get_sa_item(catcode_heads[h],n);
+}
+
+void unsave_cat_codes (integer h, quarterword gl) {
+ int k;
+ check_catcode_sizes(h);
+ for (k=0;k<=catcode_max;k++) {
+ if (catcode_heads[k] != NULL)
+ restore_sa_stack(catcode_heads[k],gl);
+ }
+}
+
+void clearcatcodestack(integer h) {
+ clear_sa_stack(catcode_heads[h]);
+}
+
+static void initializecatcodes (void) {
+ catcode_max = 0;
+ catcode_heads = Mxmalloc_array(sa_tree,(catcode_max+1));
+ catcode_valid = Mxmalloc_array(unsigned char,(catcode_max+1));
+ catcode_valid[0] = 1;
+ catcode_heads[0] = new_sa_tree(CATCODESTACK,CATCODEDEFAULT);
+}
+
+static void dumpcatcodes (void) {
+ int k,total;
+ dump_int(catcode_max);
+ total = 0;
+ for (k=0;k<=catcode_max;k++) {
+ if (catcode_valid[k]) {
+ total++;
+ }
+ }
+ dump_int(total);
+ for (k=0;k<=catcode_max;k++) {
+ if (catcode_valid[k]) {
+ dump_int(k);
+ dump_sa_tree(catcode_heads[k]);
+ }
+ }
+}
+
+static void undumpcatcodes (void) {
+ int total,h,k;
+ undump_int(catcode_max);
+ catcode_heads = Mxmalloc_array(sa_tree,(catcode_max+1));
+ catcode_valid = Mxmalloc_array(unsigned char,(catcode_max+1));
+ for (k=0;k<=catcode_max;k++) {
+ catcode_heads[k]=NULL;
+ catcode_valid[k]=0;
+ }
+ undump_int(total);
+ for (k=0;k<total;k++) {
+ undump_int(h);
+ catcode_heads[h] = undump_sa_tree();
+ catcode_valid[h] = 1;
+ }
+}
+
+int valid_catcode_table (int h) {
+ if (h<=catcode_max && h>=0 && catcode_valid[h]) {
+ return 1;
+ }
+ return 0;
+}
+
+void copy_cat_codes (int from, int to) {
+ if (from<0 || from>catcode_max || catcode_valid[from] == 0) {
+ uexit(1);
+ }
+ check_catcode_sizes(to);
+ destroy_sa_tree(catcode_heads[to]);
+ catcode_heads[to] = copy_sa_tree(catcode_heads[from]);
+ catcode_valid[to] = 1;
+}
+
+void initex_cat_codes (int h) {
+ int k;
+ check_catcode_sizes(h);
+ destroy_sa_tree(catcode_heads[h]);
+ catcode_heads[h] = NULL;
+ set_cat_code(h,'\r',car_ret,1);
+ set_cat_code(h,' ',spacer,1);
+ set_cat_code(h,'\\',escape,1);
+ set_cat_code(h,'%',comment,1);
+ set_cat_code(h,127,invalid_char,1);
+ set_cat_code(h,0,ignore,1);
+ for (k='A';k<='Z';k++) {
+ set_cat_code(h,k,letter,1);
+ set_cat_code(h,k+'a'-'A',letter,1);
+ }
+ catcode_valid[h] = 1;
+}
+
+void
+unsave_text_codes (quarterword grouplevel) {
+ unsavesfcodes(grouplevel);
+ unsaveuccodes(grouplevel);
+ unsavelccodes(grouplevel);
+}
+
+void
+initialize_text_codes (void) {
+ initializesfcodes();
+ initializeuccodes();
+ initializecatcodes();
+ initializelccodes();
+}
+
+void
+dump_text_codes (void) {
+ dumpsfcodes();
+ dumpuccodes();
+ dumplccodes();
+ dumpcatcodes();
+}
+
+void
+undump_text_codes (void) {
+ undumpsfcodes();
+ undumpuccodes();
+ undumplccodes();
+ undumpcatcodes();
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/tokens.h b/Build/source/texk/web2c/luatexdir/tokens.h
new file mode 100644
index 00000000000..6078644ba22
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/tokens.h
@@ -0,0 +1,68 @@
+/* $Id$ */
+
+
+#define token_list 0
+#define cs_token_flag 0x1FFFFFFF
+#define string_offset 0x200000
+#define string_offset_bits 21
+
+#define token_type index /* type of current token list */
+#define param_start limit /* base of macro parameters in |param_stack| */
+
+typedef enum {
+ parameter=0, /* code for parameter */
+ u_template=1, /* code for \<u_j> template */
+ v_template=2, /* code for \<v_j> template */
+ backed_up=3, /* code for text to be reread */
+ inserted=4, /* code for inserted texts */
+ macro=5, /* code for defined control sequences */
+ output_text=6, /* code for output routines */
+ every_par_text=7, /* code for \.{\\everypar} */
+ every_math_text=8, /* code for \.{\\everymath} */
+ every_display_text=9, /* code for \.{\\everydisplay} */
+ every_hbox_text=10, /* code for \.{\\everyhbox} */
+ every_vbox_text=11, /* code for \.{\\everyvbox} */
+ every_job_text=12, /* code for \.{\\everyjob}/ */
+ every_cr_text=13, /* code for \.{\\everycr} */
+ mark_text=14, /* code for \.{\\topmark}, etc. */
+ every_eof_text=19 /* was calculated, value fetched from the generated C */
+} token_types;
+
+#undef link /* defined by cpascal.h */
+#define info(a) fixmem[(a)].hhlh
+#define link(a) fixmem[(a)].hhrh
+
+#define store_new_token(a) { q=get_avail(); link(p)=q; info(q)=(a); p=q; }
+#define free_avail(a) { link((a))=avail; avail=(a); decr(dyn_used); }
+
+
+#define str_start_macro(a) str_start[(a) - string_offset]
+
+#define length(a) (str_start_macro((a)+1)-str_start_macro(a))
+
+#if defined(index)
+#undef index
+#endif
+
+#define loc cur_input.loc_field /* location of first unread character in |buffer| */
+#define state cur_input.state_field /* current scanner state */
+#define index cur_input.index_field /* reference for buffer information */
+#define start cur_input.start_field /* starting position in |buffer| */
+#define limit cur_input.limit_field /* end of current line in |buffer| */
+#define nofilter cur_input.nofilter_field /* is token filtering explicitly disallowed? */
+#define name cur_input.name_field /* name of the current file */
+#define current_ocp_lstack cur_input.ocp_lstack_field /* name of the current ocp */
+#define current_ocp_no cur_input.ocp_no_field /* name of the current ocp */
+
+#define max_char_code 15 /* largest catcode for individual characters */
+
+typedef enum {
+ mid_line=1, /* |state| code when scanning a line of characters */
+ skip_blanks=2+max_char_code, /* |state| code when ignoring blanks */
+ new_line=3+max_char_code+max_char_code, /* |state| code at start of line */
+} state_codes ;
+
+
+extern void make_token_table (lua_State *L, int cmd, int chr, int cs);
+
+
diff --git a/Build/source/texk/web2c/luatexdir/ttf2afm.c b/Build/source/texk/web2c/luatexdir/ttf2afm.c
new file mode 100644
index 00000000000..45524e658fa
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/ttf2afm.c
@@ -0,0 +1,1053 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id$
+*/
+
+/*
+#include <kpathsea/c-auto.h>
+#include <kpathsea/c-fopen.h>
+#include <kpathsea/c-limits.h>
+#include <kpathsea/c-memstr.h>
+#include <kpathsea/c-proto.h>
+#include <kpathsea/c-std.h>
+#include <kpathsea/c-unistd.h>
+#include <kpathsea/c-vararg.h>
+#include <kpathsea/getopt.h>
+*/
+#include <kpathsea/kpathsea.h>
+#include <time.h>
+#include <libgen.h>
+#include <pdftexdir/ptexmac.h>
+#include <pdftexdir/writettf.h>
+#include <string.h>
+
+/* constants used for print_glyph */
+#define AS_NAME 0
+#define AS_INDEX 1
+#define AS_UNICODE 2
+
+#define VERSION "1.02"
+
+/* FIXME */
+#define NOGLYPH_ASSIGNED_YET USHRT_MAX
+
+#define enc_getchar() xgetc(encfile)
+#define enc_eof() feof(encfile)
+#define pdftex_fail ttf_fail
+
+#define print_str(S) if (S != NULL) fprintf(outfile, #S " %s\n", S)
+#define print_dimen(N) if (N != 0) fprintf(outfile, #N " %i\n", (int)get_ttf_funit(N))
+
+#define get_ttf_funit(n) \
+ (n < 0 ? -((-n/upem)*1000 + ((-n%upem)*1000)/upem) :\
+ ((n/upem)*1000 + ((n%upem)*1000)/upem))
+
+typedef struct _unicode_entry {
+ TTF_USHORT code;
+ struct _unicode_entry *next;
+} unicode_entry;
+
+typedef struct {
+ TTF_ULONG wx;
+ const char *name;
+ TTF_USHORT index;
+ TTF_LONG bbox[4];
+ TTF_LONG offset;
+ char found;
+ unicode_entry *unicode_list;
+} mtx_entry;
+
+typedef struct _kern_entry {
+ TTF_FWORD value;
+ TTF_USHORT adjacent;
+ struct _kern_entry *next;
+} kern_entry;
+
+
+char *FontName = NULL;
+char *FullName = NULL;
+char *FamilyName = NULL;
+char *Notice = NULL;
+char *Version = NULL;
+char *Weight = NULL;
+TTF_LONG ItalicAngle = 0;
+TTF_LONG IsFixedPitch = 0;
+TTF_LONG FontBBox1 = 0;
+TTF_LONG FontBBox2 = 0;
+TTF_LONG FontBBox3 = 0;
+TTF_LONG FontBBox4 = 0;
+TTF_LONG UnderlinePosition = 0;
+TTF_LONG UnderlineThickness = 0;
+TTF_LONG CapHeight = 0;
+TTF_LONG XHeight = 0;
+TTF_LONG Ascender = 0;
+TTF_LONG Descender = 0;
+
+char *cur_file_name = NULL;
+char *bname = NULL;
+FILE *fontfile, *encfile, *outfile = NULL;
+char enc_line[ENC_BUF_SIZE];
+int print_glyph = AS_NAME; /* print glyph as names by default */
+int print_cmap = 0;
+int use_ext_enc = 0; /* use external encoding? */
+int select_unicode = 1; /* use the first unicode mapping by default */
+int printing_enc = 0; /* set to 1 while printing encodings */
+
+
+TTF_USHORT upem;
+TTF_USHORT ntabs;
+int nhmtx;
+int post_format;
+int loca_format;
+int nglyphs;
+int nkernpairs = 0;
+int names_count = 0;
+char *ps_glyphs_buf = NULL;
+dirtab_entry *dir_tab;
+mtx_entry *mtx_tab;
+kern_entry *kern_tab;
+char *enc_names[256];
+
+cmap_entry *cmap_tab;
+TTF_USHORT ncmapsubtabs;
+long cmap_offset;
+
+TTF_USHORT unicode_map[0xFFFF];
+
+#include "macnames.c"
+
+void ttf_fail(char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ fprintf(stderr, "\nError: ttf2afm");
+ if (cur_file_name)
+ fprintf(stderr, " (file %s)", cur_file_name);
+ fprintf(stderr, ": ");
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+ exit(-1);
+}
+
+void ttf_warn(char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ fprintf(stderr, "\nWarning: ttf2afm");
+ if (cur_file_name)
+ fprintf(stderr, " (file %s)", cur_file_name);
+ fprintf(stderr, ": ");
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+}
+
+int xgetc(FILE * stream)
+{
+ int c = getc(stream);
+ if (c < 0 && c != EOF)
+ ttf_fail("getc() failed");
+ return c;
+}
+
+long ttf_getnum(int s)
+{
+ long i = 0;
+ int c;
+ while (s > 0) {
+ if ((c = xgetc(fontfile)) < 0)
+ ttf_fail("unexpected EOF");
+ i = (i << 8) + c;
+ s--;
+ }
+ return i;
+}
+
+dirtab_entry *name_lookup(char *s)
+{
+ dirtab_entry *p;
+ for (p = dir_tab; p - dir_tab < ntabs; p++)
+ if (strncmp(p->tag, s, 4) == 0)
+ break;
+ if (p - dir_tab == ntabs)
+ p = NULL;
+ return p;
+}
+
+void ttf_seek_tab(char *name, TTF_LONG offset)
+{
+ dirtab_entry *p = name_lookup(name);
+ if (p == NULL)
+ ttf_fail("can't find table `%s'", name);
+ if (fseek(fontfile, p->offset + offset, SEEK_SET) < 0)
+ ttf_fail("fseek() failed while reading `%s' table", name);
+}
+
+void ttf_seek_off(char *name, TTF_LONG offset)
+{
+ if (fseek(fontfile, offset, SEEK_SET) < 0)
+ ttf_fail("fseek() failed while reading `%s' table", name);
+}
+
+void store_kern_value(TTF_USHORT i, TTF_USHORT j, TTF_FWORD v)
+{
+ kern_entry *pk;
+ for (pk = kern_tab + i; pk->next != NULL; pk = pk->next);
+ pk->next = xtalloc(1, kern_entry);
+ pk = pk->next;
+ pk->next = NULL;
+ pk->adjacent = j;
+ pk->value = v;
+}
+
+TTF_FWORD get_kern_value(TTF_USHORT i, TTF_USHORT j)
+{
+ kern_entry *pk;
+ for (pk = kern_tab + i; pk->next != NULL; pk = pk->next)
+ if (pk->adjacent == j)
+ return pk->value;
+ return 0;
+}
+
+void free_tabs()
+{
+ int i;
+ kern_entry *p, *q, *r;
+ unicode_entry *u, *v;
+ mtx_entry *pm;
+ xfree(ps_glyphs_buf);
+ xfree(dir_tab);
+ xfree(cmap_tab);
+ for (pm = mtx_tab; pm - mtx_tab < nglyphs; pm++)
+ if (pm->unicode_list != NULL) {
+ for (u = pm->unicode_list; u != NULL; u = v) {
+ v = u->next;
+ xfree(u);
+ }
+ }
+ xfree(mtx_tab);
+ for (i = 0; i < 256; i++)
+ if (enc_names[i] != notdef)
+ free(enc_names[i]);
+ if (kern_tab == NULL)
+ return;
+ for (p = kern_tab; p - kern_tab < nglyphs; p++)
+ if (p->next != NULL) {
+ for (q = p->next; q != NULL; q = r) {
+ r = q->next;
+ xfree(q);
+ }
+ }
+ xfree(kern_tab);
+}
+
+void enc_getline()
+{
+ char *p;
+ int c;
+ restart:
+ if (enc_eof())
+ ttf_fail("unexpected end of file");
+ p = enc_line;
+ do {
+ c = enc_getchar();
+ append_char_to_buf(c, p, enc_line, ENC_BUF_SIZE);
+ } while (c != 10);
+ append_eol(p, enc_line, ENC_BUF_SIZE);
+ if (p - enc_line <= 2 || *enc_line == '%')
+ goto restart;
+}
+
+void read_encoding(char *encname)
+{
+ char buf[ENC_BUF_SIZE], *q, *r;
+ int i;
+ cur_file_name = encname;
+ if ((encfile = kpse_open_file(encname, kpse_enc_format)) == NULL)
+ ttf_fail("can't open encoding file for reading");
+ enc_getline();
+ if (*enc_line != '/' || (r = strchr(enc_line, '[')) == 0)
+ ttf_fail("invalid encoding vector: name or `[' missing:\n%s", enc_line);
+ for (i = 0; i < 256; i++)
+ enc_names[i] = (char *) notdef;
+ if (r[1] == 32)
+ r += 2;
+ else
+ r++;
+ for (;;) {
+ while (*r == '/') {
+ for (q = buf, r++; *r != ' ' && *r != 10 && *r != ']' && *r != '/';
+ *q++ = *r++);
+ *q = 0;
+ if (*r == ' ')
+ r++;
+ if (strcmp(buf, notdef) != 0)
+ enc_names[names_count] = xstrdup(buf);
+ if (++names_count > 256)
+ ttf_fail("encoding vector contains more than 256 names");
+ }
+ if (*r != 10 && *r != '%') {
+ if (str_prefix(r, "] def"))
+ goto done;
+ else
+ ttf_fail
+ ("invalid encoding vector: a name or `] def' expected:\n%s",
+ enc_line);
+ }
+ enc_getline();
+ r = enc_line;
+ }
+ done:
+ xfclose(encfile, cur_file_name);
+ if (names_count != 256)
+ ttf_warn("encoding vector contains only %i names (expected %i)",
+ names_count, 256);
+}
+
+void append_unicode(long glyph_index, TTF_USHORT code)
+{
+ mtx_entry *m;
+ unicode_entry *u, *v;
+ assert(glyph_index >= 0 && glyph_index < nglyphs);
+ u = xtalloc(1, unicode_entry);
+ m = mtx_tab + glyph_index;
+ u->next = NULL;
+ u->code = code;
+ if (m->unicode_list == NULL)
+ m->unicode_list = u;
+ else {
+ for (v = m->unicode_list; v->next != NULL; v = v->next);
+ v->next = u;
+ }
+}
+
+void read_cmap()
+{
+ cmap_entry *e;
+ seg_entry *seg_tab, *s;
+ TTF_USHORT *glyphId, format, segCount;
+ long int n, i, k, length, index;
+ int unicode_map_count = 0;
+ ttf_seek_tab("cmap", TTF_USHORT_SIZE); /* skip the table vesrion number (=0) */
+ ncmapsubtabs = get_ushort();
+ cmap_offset = xftell(fontfile, cur_file_name) - 2 * TTF_USHORT_SIZE;
+ cmap_tab = xtalloc(ncmapsubtabs, cmap_entry);
+ for (e = cmap_tab; e - cmap_tab < ncmapsubtabs; e++) {
+ e->platform_id = get_ushort();
+ e->encoding_id = get_ushort();
+ e->offset = get_ulong();
+ }
+ for (i = 0; i < 0xFFFF; ++i)
+ unicode_map[i] = NOGLYPH_ASSIGNED_YET;
+ for (e = cmap_tab; e - cmap_tab < ncmapsubtabs; e++) {
+ ttf_seek_off("cmap", cmap_offset + e->offset);
+ format = get_ushort();
+ if (is_unicode_mapping(e) && format == 4) {
+ ++unicode_map_count;
+ if (unicode_map_count == select_unicode)
+ goto read_unicode_mapping;
+ }
+ continue;
+ read_unicode_mapping:
+ length = get_ushort(); /* length of subtable */
+ (void) get_ushort(); /* skip the version number */
+ segCount = get_ushort() / 2;
+ (void) get_ushort(); /* skip searchRange */
+ (void) get_ushort(); /* skip entrySelector */
+ (void) get_ushort(); /* skip rangeShift */
+ seg_tab = xtalloc(segCount, seg_entry);
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->endCode = get_ushort();
+ (void) get_ushort(); /* skip reversedPad */
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->startCode = get_ushort();
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->idDelta = get_ushort();
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->idRangeOffset = get_ushort();
+ length -= 8 * TTF_USHORT_SIZE + 4 * segCount * TTF_USHORT_SIZE;
+ n = length / TTF_USHORT_SIZE; /* number of glyphID's */
+ glyphId = xtalloc(n, TTF_USHORT);
+ for (i = 0; i < n; i++)
+ glyphId[i] = get_ushort();
+ for (s = seg_tab; s - seg_tab < segCount; s++) {
+ for (i = s->startCode; i <= s->endCode; i++) {
+ if (i == 0xFFFF)
+ break;
+ if (s->idRangeOffset != 0xFFFF) {
+ if (s->idRangeOffset == 0)
+ index = (s->idDelta + i) & 0xFFFF;
+ else {
+ k = (i - s->startCode) + s->idRangeOffset / 2 +
+ (s - seg_tab) - segCount;
+ assert(k >= 0 && k < n);
+ index = glyphId[k];
+ if (index != 0)
+ index = (index + s->idDelta) & 0xFFFF;
+ }
+ if (index < 0 || index >= nglyphs)
+ ttf_fail("cmap: glyph index out of range [0..%i)",
+ nglyphs);
+ if (unicode_map[i] != NOGLYPH_ASSIGNED_YET)
+ ttf_fail
+ ("cmap: unicode %.4X is mapped to multiple glyphs",
+ i);
+ if (unicode_map[i] == 0)
+ ttf_warn("unicode %.4X is mapped to glyph 0", i);
+ unicode_map[i] = index;
+ append_unicode(index, i);
+ }
+ }
+ }
+ xfree(seg_tab);
+ xfree(glyphId);
+ break;
+ }
+ if (e - cmap_tab == ncmapsubtabs)
+ ttf_fail("Invalid argument `-m %i': out of range [1..%i]",
+ select_unicode, unicode_map_count);
+}
+
+void read_font()
+{
+ long i, j, k, l, n, m, platform_id, encoding_id;
+ TTF_FWORD kern_value;
+ char buf[1024], *p;
+ dirtab_entry *pd;
+ kern_entry *pk;
+ mtx_entry *pm;
+ ttf_skip(TTF_FIXED_SIZE);
+ ntabs = get_ushort();
+ ttf_skip(3 * TTF_USHORT_SIZE);
+ dir_tab = xtalloc(ntabs, dirtab_entry);
+ for (pd = dir_tab; pd - dir_tab < ntabs; pd++) {
+ pd->tag[0] = get_char();
+ pd->tag[1] = get_char();
+ pd->tag[2] = get_char();
+ pd->tag[3] = get_char();
+ ttf_skip(TTF_ULONG_SIZE);
+ pd->offset = get_ulong();
+ pd->length = get_ulong();
+ }
+ ttf_seek_tab("head",
+ 2 * TTF_FIXED_SIZE + 2 * TTF_ULONG_SIZE + TTF_USHORT_SIZE);
+ upem = get_ushort();
+ ttf_skip(16);
+ FontBBox1 = get_fword();
+ FontBBox2 = get_fword();
+ FontBBox3 = get_fword();
+ FontBBox4 = get_fword();
+ ttf_skip(TTF_USHORT_SIZE);
+ ttf_skip(TTF_USHORT_SIZE + TTF_SHORT_SIZE);
+ loca_format = get_short();
+ ttf_seek_tab("maxp", TTF_FIXED_SIZE);
+ nglyphs = get_ushort();
+ mtx_tab = xtalloc(nglyphs + 1, mtx_entry);
+ for (pm = mtx_tab; pm - mtx_tab < nglyphs + 1; pm++) {
+ pm->name = NULL; /* notdef */
+ pm->found = 0;
+ pm->unicode_list = NULL;
+ }
+ ttf_seek_tab("hhea", TTF_FIXED_SIZE);
+ Ascender = get_fword();
+ Descender = get_fword();
+ ttf_skip(TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3 * TTF_FWORD_SIZE +
+ 8 * TTF_SHORT_SIZE);
+ nhmtx = get_ushort();
+ ttf_seek_tab("hmtx", 0);
+ for (pm = mtx_tab; pm - mtx_tab < nhmtx; pm++) {
+ pm->wx = get_ufword();
+ ttf_skip(TTF_FWORD_SIZE);
+ }
+ i = pm[-1].wx;
+ for (; pm - mtx_tab < nglyphs; pm++)
+ pm->wx = i;
+ ttf_seek_tab("post", 0);
+ post_format = get_fixed();
+ ItalicAngle = get_fixed();
+ UnderlinePosition = get_fword();
+ UnderlineThickness = get_fword();
+ IsFixedPitch = get_ulong();
+ ttf_skip(4 * TTF_ULONG_SIZE);
+ switch (post_format) {
+ case 0x00010000:
+ for (pm = mtx_tab; pm - mtx_tab < NMACGLYPHS; pm++)
+ pm->name = (char *) mac_glyph_names[pm - mtx_tab];
+ break;
+ case 0x00020000:
+ l = get_ushort(); /* some fonts have this value different from nglyphs */
+ for (pm = mtx_tab; pm - mtx_tab < l; pm++)
+ pm->index = get_ushort();
+ if ((pd = name_lookup("post")) == NULL)
+ ttf_fail("can't find table `post'");
+ n = pd->length - (xftell(fontfile, cur_file_name) - pd->offset);
+ ps_glyphs_buf = xtalloc(n + 1, char);
+ for (m = 0, p = ps_glyphs_buf; p - ps_glyphs_buf < n;) {
+ for (i = get_byte(); i > 0; i--)
+ *p++ = get_char();
+ *p++ = 0;
+ m++;
+ }
+ for (pm = mtx_tab; pm - mtx_tab < l; pm++) {
+ if (pm->index < NMACGLYPHS)
+ pm->name = (char *) mac_glyph_names[pm->index];
+ else {
+ k = pm->index - NMACGLYPHS;
+ if (k < m) {
+ for (p = ps_glyphs_buf; k > 0; k--)
+ p = (char *) strend(p) + 1;
+ pm->name = p;
+ } else {
+ pm->name = NULL; /* index out of valid range, fix name to notdef */
+ }
+ }
+ }
+ break;
+ case 0x00030000:
+ if (print_glyph == AS_NAME) {
+ ttf_warn
+ ("no names available in `post' table, print glyph names as indices");
+ print_glyph = AS_INDEX;
+ }
+ break;
+ default:
+ ttf_fail("unsupported format (%.8X) of `post' table", post_format);
+ }
+ ttf_seek_tab("loca", 0);
+ for (pm = mtx_tab; pm - mtx_tab < nglyphs + 1; pm++)
+ pm->offset = (loca_format == 1 ? get_ulong() : get_ushort() << 1);
+ if ((pd = name_lookup("glyf")) == NULL)
+ ttf_fail("can't find table `glyf'");
+ for (n = pd->offset, pm = mtx_tab; pm - mtx_tab < nglyphs; pm++) {
+ ttf_seek_off("glyf", n + pm->offset);
+ ttf_skip(TTF_SHORT_SIZE);
+ pm->bbox[0] = get_fword();
+ pm->bbox[1] = get_fword();
+ pm->bbox[2] = get_fword();
+ pm->bbox[3] = get_fword();
+ }
+
+ ttf_seek_tab("name", 0);
+ i = ftell(fontfile);
+ (void) get_ushort(); /* skip Format selector (=0) */
+ n = get_ushort(); /* number of name records */
+ j = get_ushort() + i; /* start of string storage */
+ i += 3 * TTF_USHORT_SIZE; /* update the current offset */
+ while (n-- > 0) {
+ ttf_seek_off("name", i);
+ platform_id = get_ushort();
+ encoding_id = get_ushort();
+ (void) get_ushort(); /* skip language_id */
+ k = get_ushort(); /* name_id */
+ l = get_ushort(); /* string length */
+ if ((platform_id == 1 && encoding_id == 0) &&
+ (k == 0 || k == 1 || k == 4 || k == 5 || k == 6)) {
+ ttf_seek_off("name", j + get_ushort());
+ for (p = buf; l-- > 0; p++)
+ *p = get_char();
+ *p++ = 0;
+ p = xstrdup(buf);
+ switch (k) {
+ case 0:
+ Notice = p;
+ break;
+ case 1:
+ FamilyName = p;
+ break;
+ case 4:
+ FullName = p;
+ break;
+ case 5:
+ Version = p;
+ break;
+ case 6:
+ FontName = p;
+ break;
+ }
+ if (Notice != NULL && FamilyName != NULL &&
+ FullName != NULL && FontName != NULL && Version != NULL)
+ break;
+ }
+ i += 6 * TTF_USHORT_SIZE;
+ }
+ if ((pd = name_lookup("PCLT")) != NULL) {
+ ttf_seek_off("PCLT",
+ pd->offset + TTF_FIXED_SIZE + TTF_ULONG_SIZE +
+ TTF_USHORT_SIZE);
+ XHeight = get_ushort();
+ if (XHeight > FontBBox4) {
+ ttf_warn("XHeight is too big (%i)\n"
+ "This is likely a font bug, so I discarded this parameter.",
+ (int) get_ttf_funit(XHeight));
+ XHeight = 0;
+ }
+ ttf_skip(2 * TTF_USHORT_SIZE);
+ CapHeight = get_ushort();
+ if (CapHeight > FontBBox4) {
+ ttf_warn("CapHeight is too big (%i)\n"
+ "This is likely a font bug, so I discarded this parameter.",
+ (int) get_ttf_funit(CapHeight));
+ CapHeight = 0;
+ }
+ }
+ if ((pd = name_lookup("OS/2")) != NULL) {
+ ttf_seek_off("OS/2", pd->offset + TTF_USHORT_SIZE + TTF_SHORT_SIZE);
+ switch (get_ushort()) {
+ case 100:
+ Weight = xstrdup("Thin");
+ break;
+ case 200:
+ Weight = xstrdup("ExtraLight");
+ break;
+ case 300:
+ Weight = xstrdup("Light");
+ break;
+ case 400:
+ Weight = xstrdup("Normal");
+ break;
+ case 500:
+ Weight = xstrdup("Medium");
+ break;
+ case 600:
+ Weight = xstrdup("SemiBold");
+ break;
+ case 700:
+ Weight = xstrdup("Bold");
+ break;
+ case 800:
+ Weight = xstrdup("ExtraBold");
+ break;
+ case 900:
+ Weight = xstrdup("Black");
+ break;
+ }
+ }
+ read_cmap();
+ if ((pd = name_lookup("kern")) == NULL)
+ return;
+ kern_tab = xtalloc(nglyphs, kern_entry);
+ for (pk = kern_tab; pk - kern_tab < nglyphs; pk++) {
+ pk->next = NULL;
+ pk->value = 0;
+ }
+ ttf_seek_off("kern", pd->offset + TTF_USHORT_SIZE);
+ for (n = get_ushort(); n > 0; n--) {
+ ttf_skip(2 * TTF_USHORT_SIZE);
+ k = get_ushort();
+ if (!(k & 1) || (k & 2) || (k & 4))
+ return;
+ if (k >> 8 != 0) {
+ ttf_warn("warning: only format 0 supported of `kern' \
+ subtables, others are ignored\n");
+ continue;
+ }
+ k = get_ushort();
+ ttf_skip(3 * TTF_USHORT_SIZE);
+ while (k-- > 0) {
+ i = get_ushort();
+ j = get_ushort();
+ kern_value = get_fword();
+ if (kern_value != 0) {
+ store_kern_value(i, j, kern_value);
+ nkernpairs++;
+ }
+ }
+ }
+}
+
+int null_glyph(const char *s)
+{
+ return (s == NULL || s == notdef);
+ /*
+ strcmp(s, ".null") == 0 ||
+ strcmp(s, ".notdef") == 0 ||
+ strcmp(s, "CR") == 0 ||
+ strcmp(s, "nonmarkingreturn") == 0
+ */
+}
+
+void print_glyph_name(FILE * f, long glyph_index, int convention)
+{
+ unicode_entry *u;
+ static char buf[1024];
+ const char *n;
+ assert(glyph_index >= 0 && glyph_index < nglyphs);
+ n = mtx_tab[glyph_index].name;
+ if (printing_enc && (n == notdef || glyph_index == 0)) {
+ fputs(notdef, f);
+ return;
+ }
+ switch (convention) {
+ case AS_NAME:
+ if (!null_glyph(n))
+ fprintf(f, "%s", mtx_tab[glyph_index].name);
+ else if (n == notdef && glyph_index == 0)
+ fputs(notdef, f);
+ else
+ fprintf(f, "%s%li", GLYPH_PREFIX_INDEX, glyph_index);
+ break;
+ case AS_INDEX:
+ fprintf(f, "%s%li", GLYPH_PREFIX_INDEX, glyph_index);
+ break;
+ case AS_UNICODE:
+ u = mtx_tab[glyph_index].unicode_list;
+ if (glyph_index == 0 || u == NULL)
+ fprintf(f, "%s%li", GLYPH_PREFIX_INDEX, glyph_index);
+ else {
+ fprintf(f, "%s%.4X", GLYPH_PREFIX_UNICODE, u->code);
+ if (u->next != NULL) {
+ *buf = 0;
+ for (; u != NULL; u = u->next) {
+ assert(strlen(buf) + strlen(GLYPH_PREFIX_UNICODE) + 4 <
+ sizeof(buf));
+ sprintf(strend(buf), "%s%.4X ", GLYPH_PREFIX_UNICODE,
+ u->code);
+ }
+ ttf_warn
+ ("glyph %li have multiple encodings (the first one being used): %s",
+ glyph_index, buf);
+ }
+ }
+ break;
+ }
+}
+
+void print_char_metric(FILE * f, int charcode, long glyph_index)
+{
+ assert(glyph_index >= 0 && glyph_index < nglyphs);
+ fprintf(f, "C %i ; WX %i ; N ", (int) charcode,
+ (int) get_ttf_funit(mtx_tab[glyph_index].wx));
+ print_glyph_name(f, glyph_index, print_glyph);
+ fprintf(f, " ; B %i %i %i %i ;\n",
+ (int) get_ttf_funit(mtx_tab[glyph_index].bbox[0]),
+ (int) get_ttf_funit(mtx_tab[glyph_index].bbox[1]),
+ (int) get_ttf_funit(mtx_tab[glyph_index].bbox[2]),
+ (int) get_ttf_funit(mtx_tab[glyph_index].bbox[3]));
+}
+
+void print_afm(char *date, char *fontname)
+{
+ int ncharmetrics;
+ mtx_entry *pm;
+ short mtx_index[256], *idx;
+ unsigned int index;
+ char **pe;
+ kern_entry *pk, *qk;
+ fputs("StartFontMetrics 2.0\n", outfile);
+ fprintf(outfile,
+ "Comment Converted at %s by ttf2afm from font file `%s'\n", date,
+ fontname);
+ print_str(FontName);
+ print_str(FullName);
+ print_str(FamilyName);
+ print_str(Weight);
+ fprintf(outfile, "ItalicAngle %i", (int) (ItalicAngle / 0x10000));
+ if (ItalicAngle % 0x10000 > 0)
+ fprintf(outfile, ".%i",
+ (int) ((ItalicAngle % 0x10000) * 1000) / 0x10000);
+ fputs("\n", outfile);
+ fprintf(outfile, "IsFixedPitch %s\n", IsFixedPitch ? "true" : "false");
+ fprintf(outfile, "FontBBox %i %i %i %i\n",
+ (int) get_ttf_funit(FontBBox1),
+ (int) get_ttf_funit(FontBBox2),
+ (int) get_ttf_funit(FontBBox3), (int) get_ttf_funit(FontBBox4));
+ print_dimen(UnderlinePosition);
+ print_dimen(UnderlineThickness);
+ print_str(Version);
+ print_str(Notice);
+ fputs("EncodingScheme FontSpecific\n", outfile);
+ print_dimen(CapHeight);
+ print_dimen(XHeight);
+ print_dimen(Ascender);
+ print_dimen(Descender);
+ ncharmetrics = nglyphs;
+ if (use_ext_enc == 0) { /* external encoding vector not given */
+ fprintf(outfile, "StartCharMetrics %u\n", ncharmetrics);
+ for (pm = mtx_tab; pm - mtx_tab < nglyphs; pm++) {
+ pm->found = 1;
+ print_char_metric(outfile, -1, pm - mtx_tab);
+ }
+ } else { /* external encoding vector given */
+ for (idx = mtx_index; idx - mtx_index < 256; *idx++ = 0);
+ for (pe = enc_names; pe - enc_names < names_count; pe++) {
+ if (*pe == notdef)
+ continue;
+ /* scan form `uniABCD' */
+ if (sscanf(*pe, GLYPH_PREFIX_UNICODE "%4X", &index) == 1) {
+ if (unicode_map[index] != NOGLYPH_ASSIGNED_YET) {
+ pm = mtx_tab + unicode_map[index];
+ mtx_index[pe - enc_names] = pm - mtx_tab;
+ pm->found = 1;
+ } else
+ ttf_warn("`unicode %s%.4X' is not mapped to any glyph",
+ GLYPH_PREFIX_UNICODE, index);
+ continue;
+ }
+ /* scan form `index123' */
+ if (sscanf(*pe, GLYPH_PREFIX_INDEX "%u", &index) == 1) {
+ if (index >= nglyphs)
+ ttf_fail("`%s' out of valid range [0..%i)", *pe, nglyphs);
+ pm = mtx_tab + index;
+ mtx_index[pe - enc_names] = pm - mtx_tab;
+ pm->found = 1;
+ continue;
+ }
+ for (pm = mtx_tab; pm - mtx_tab < nglyphs; pm++)
+ if (pm->name != NULL && strcmp(*pe, pm->name) == 0)
+ break;
+ if (pm - mtx_tab < nglyphs) {
+ mtx_index[pe - enc_names] = pm - mtx_tab;
+ pm->found = 1;
+ continue;
+ } else
+ ttf_warn("glyph `%s' not found", *pe);
+ }
+ fprintf(outfile, "StartCharMetrics %u\n", ncharmetrics);
+ for (idx = mtx_index; idx - mtx_index < 256; idx++) {
+ if (*idx != 0 && mtx_tab[*idx].found == 1)
+ print_char_metric(outfile, idx - mtx_index, *idx);
+ }
+ for (pm = mtx_tab; pm - mtx_tab < nglyphs; pm++) {
+ if (pm->found == 0)
+ print_char_metric(outfile, -1, pm - mtx_tab);
+ }
+ }
+ fputs("EndCharMetrics\n", outfile);
+ if (nkernpairs == 0)
+ goto end_kerns;
+ fprintf(outfile, "StartKernData\nStartKernPairs %i\n", nkernpairs);
+ for (pk = kern_tab; pk - kern_tab < nglyphs; pk++)
+ for (qk = pk; qk != NULL; qk = qk->next)
+ if (qk->value != 0) {
+ fputs("KPX ", outfile);
+ print_glyph_name(outfile, pk - kern_tab, print_glyph);
+ fputs(" ", outfile);
+ print_glyph_name(outfile, qk->adjacent, print_glyph);
+ fprintf(outfile, " %i\n", get_ttf_funit(qk->value));
+ }
+ fputs("EndKernPairs\nEndKernData\n", outfile);
+ end_kerns:
+ fputs("EndFontMetrics\n", outfile);
+}
+
+void print_encoding(char *fontname)
+{
+ long int i, k, first_code, length;
+ FILE *file;
+ TTF_USHORT format;
+ char *enc_name, *end_enc_name;
+ cmap_entry *e;
+ printing_enc = 1;
+ enc_name = xtalloc(strlen(bname) + 20, char);
+ strcpy(enc_name, bname);
+ end_enc_name = strend(enc_name);
+ for (e = cmap_tab; e - cmap_tab < ncmapsubtabs; e++) {
+ ttf_seek_off("cmap", cmap_offset + e->offset);
+ format = get_ushort();
+ if (format != 0 && format != 4 && format != 6) {
+ ttf_warn("format %i of encoding subtable unsupported",
+ (int) format);
+ continue;
+ }
+ sprintf(end_enc_name, ".e%i%i",
+ (int) e->platform_id, (int) e->encoding_id);
+ if ((file = xfopen(enc_name, FOPEN_W_MODE)) == NULL)
+ ttf_fail("cannot open file for writing (%s)\n", enc_name);
+ fprintf(file, "%% Encoding table from font file %s\n", fontname);
+ fprintf(file, "%% Platform ID %i", (int) e->platform_id);
+ switch (e->platform_id) {
+ case 0:
+ fprintf(file, " (Apple Unicode)");
+ break;
+ case 1:
+ fprintf(file, " (Macintosh)");
+ break;
+ case 2:
+ fprintf(file, " (ISO)");
+ break;
+ case 3:
+ fprintf(file, " (Microsoft)");
+ break;
+ }
+ fprintf(file, "\n");
+ fprintf(file, "%% Encoding ID %i", (int) e->encoding_id);
+ if (e->platform_id == 1 && e->encoding_id == 0)
+ fprintf(file, " (Roman)");
+ if (e->platform_id == 3)
+ switch (e->encoding_id) {
+ case 0:
+ fprintf(file, " (Symbol)");
+ break;
+ case 1:
+ fprintf(file, " (Unicode)");
+ break;
+ }
+ fprintf(file, "\n");
+ fprintf(file, "%% Format %i", (int) (format));
+ switch (format) {
+ case 0:
+ fprintf(file, " (byte encoding table)");
+ break;
+ case 4:
+ fprintf(file, " (segment mapping to delta values)");
+ break;
+ case 6:
+ fprintf(file, " (trimmed table mapping)");
+ break;
+ }
+ fprintf(file, "\n");
+ fprintf(file, "/Encoding%i [\n", (int) (e - cmap_tab + 1));
+ switch (format) {
+ case 0:
+ (void) get_ushort(); /* skip length */
+ (void) get_ushort(); /* skip version number */
+ for (i = 0; i < 256; i++) {
+ fputs("/", file);
+ print_glyph_name(file, get_byte(), print_glyph);
+ fputs("\n", file);
+ }
+ break;
+ case 4:
+ for (i = 0; i < nglyphs; ++i) {
+ fprintf(file, "%% Glyph %li -> ", i);
+ print_glyph_name(file, i, AS_UNICODE);
+ fputs("\n", file);
+ }
+ break;
+ case 6:
+ (void) get_ushort(); /* skip table length */
+ (void) get_ushort(); /* skip version number */
+ first_code = get_ushort(); /* first character code */
+ for (i = 0; i < first_code; ++i)
+ fprintf(file, "/%s\n", notdef);
+ length = get_ushort(); /* number of character codes */
+ for (i = first_code; i < first_code + length; i++) {
+ k = get_ushort();
+ if (i > 255)
+ fputs("% ", file);
+ fputs("/", file);
+ print_glyph_name(file, k, print_glyph);
+ fputs("\n", file);
+ }
+ for (i = first_code + length; i < 256; i++)
+ fprintf(file, "/%s\n", notdef);
+ break;
+ default:
+ ttf_warn("format %i of encoding subtable unsupported",
+ (int) format);
+ }
+ fprintf(file, "] def\n");
+ }
+ xfree(enc_name);
+}
+
+void usage()
+{
+ cur_file_name = NULL;
+ fprintf(stderr,
+ "Usage: ttf2afm [-i|-u|-c|-v] [-e enc] [-o filename] [-m NUM] fontfile\n"
+ " -i: force printing glyph names in form 'index123'\n"
+ " -u: force printing glyph names in form 'uniABCD'\n"
+ " -c: print encoding tables to `basename.e<platformID><encodingID>'\n"
+ " -v: print version\n"
+ " -e enc: encode the AFM output using encoding vector from `enc'\n"
+ " -o filename: write output to file `filename' instead of stdout\n"
+ " -m NUM: select unicode mapping (default = 1, ie the first)\n"
+ " fontfile: the TrueType fontfile\n"
+ "\nPlease send bug reports or feature requests to <pdftex@tug.org>\n");
+ _exit(-1);
+}
+
+int main(int argc, char **argv)
+{
+ char date[128], *s;
+ time_t t = time(&t);
+ int c;
+ kpse_set_progname(argv[0]);
+ kpse_init_prog("ttf2afm", 0, 0, 0);
+ while ((c = getopt(argc, argv, "iucve:o:m:")) != -1)
+ switch (c) {
+ case 'i':
+ print_glyph = AS_INDEX;
+ break;
+ case 'u':
+ print_glyph = AS_UNICODE;
+ break;
+ case 'c':
+ print_cmap = 1;
+ break;
+ case 'e':
+ cur_file_name = optarg;
+ read_encoding(cur_file_name);
+ use_ext_enc = 1;
+ break;
+ case 'o':
+ cur_file_name = optarg;
+ outfile = xfopen(cur_file_name, FOPEN_W_MODE);
+ if (outfile == NULL)
+ ttf_fail("cannot open file for writing");
+ break;
+ case 'm':
+ select_unicode = atoi(optarg);
+ break;
+ case 'v':
+ fprintf(stderr,
+ "ttf2afm version " VERSION "\n"
+ "Copyright (C) 1997-2005 Han The Thanh.\n"
+ "There is NO warranty. Redistribution of this software is\n"
+ "covered by the terms of both the pdfTeX copyright and\n"
+ "the GNU General Public License.\n"
+ "For more information about these matters, see the files\n"
+ "named COPYING and the pdfTeX source.\n"
+ "Primary author of ttf2afm: Han The Thanh.\n");
+ _exit(0);
+ default:
+ usage();
+ }
+ if (argc - optind != 1)
+ usage();
+ sprintf(date, "%s\n", ctime(&t));
+ *(char *) strchr(date, '\n') = 0;
+ cur_file_name = argv[optind];
+ if (print_cmap) {
+ bname = xstrdup(xbasename(cur_file_name));
+ if ((s = strrchr(bname, '.')) != NULL)
+ *s = 0;
+ }
+ if ((fontfile =
+ kpse_open_file(cur_file_name, kpse_truetype_format)) == NULL)
+ ttf_fail("can't open font file for reading");
+ read_font();
+ if (outfile == NULL)
+ outfile = stdout;
+ print_afm(date, cur_file_name);
+ if (print_cmap)
+ print_encoding(cur_file_name);
+ xfree(FontName);
+ xfree(FullName);
+ xfree(FamilyName);
+ xfree(Notice);
+ xfree(Version);
+ xfree(Weight);
+ free_tabs();
+ xfclose(fontfile, cur_file_name);
+ return 0;
+}
diff --git a/Build/source/texk/web2c/luatexdir/ttf2afm.rc b/Build/source/texk/web2c/luatexdir/ttf2afm.rc
new file mode 100644
index 00000000000..a63881df7d1
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/ttf2afm.rc
@@ -0,0 +1,35 @@
+/* ttf2afm.rc: ttf2afm -*- C++ -*-
+
+ Copyright (C) 1996-2003 Fabrice Popineau <fabrice.popineau@supelec.fr>
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this file; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#include <texlive-version.h>
+
+#define VER_FILEVERSION TEXLIVE_MAJOR_VERSION,TEXLIVE_MINOR_VERSION,TEXLIVE_BETA_NUMBER,TEXLIVE_ALPHA_NUMBER
+#define VER_FILEVERSION_STR TEXLIVE_PRODUCTVERSION_STR " ttf2afm 1.10a"
+
+#define VER_INTERNALNAME_STR "ttf2afm"
+#define VER_ORIGINALFILENAME_STR "ttf2afm.exe"
+
+#define VER_FILEDESCRIPTION_STR "TTF-to-AFM Converter"
+
+#define VER_COMPANYNAME_STR ""
+#define VER_LEGALCOPYRIGHT_STR "Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>"
+
+#include "texlive.version"
+
+/* ttf2afm.rc ends here */
diff --git a/Build/source/texk/web2c/luatexdir/utils.c b/Build/source/texk/web2c/luatexdir/utils.c
new file mode 100644
index 00000000000..707ac7855f9
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/utils.c
@@ -0,0 +1,1798 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id$
+*/
+
+#include "sys/types.h"
+#ifndef __MINGW32__
+#include "sysexits.h"
+#else
+#define EX_SOFTWARE 70
+#endif
+#include "md5.h"
+#include <kpathsea/c-proto.h>
+#include <kpathsea/c-stat.h>
+#include <kpathsea/c-fopen.h>
+#include <string.h>
+#include <time.h>
+#include <float.h> /* for DBL_EPSILON */
+#include "zlib.h"
+#include "ptexlib.h"
+
+#include "svnversion.h"
+
+#include "openbsd-compat.h"
+#include "png.h"
+#include "xpdf/config.h" /* just to get the xpdf version */
+
+#define check_nprintf(size_get, size_want) \
+ if ((unsigned)(size_get) >= (unsigned)(size_want)) \
+ pdftex_fail ("snprintf failed: file %s, line %d", __FILE__, __LINE__);
+
+char *cur_file_name = NULL;
+strnumber last_tex_string;
+static char print_buf[PRINTF_BUF_SIZE];
+static char *jobname_cstr = NULL;
+static char *job_id_string = NULL;
+extern string ptexbanner; /* from web2c/lib/texmfmp.c */
+extern string versionstring; /* from web2c/lib/version.c */
+extern KPSEDLL string kpathsea_version_string; /* from kpathsea/version.c */
+
+size_t last_ptr_index; /* for use with alloc_array */
+
+/* define fb_ptr, fb_array & fb_limit */
+typedef char fb_entry;
+define_array (fb);
+
+/* define char_ptr, char_array & char_limit */
+typedef char char_entry;
+define_array (char);
+
+integer fb_offset (void)
+{
+ return fb_ptr - fb_array;
+}
+
+void fb_seek (integer offset)
+{
+ fb_ptr = fb_array + offset;
+}
+
+void fb_putchar (eight_bits b)
+{
+ alloc_array (fb, 1, SMALL_ARRAY_SIZE);
+ *fb_ptr++ = b;
+}
+
+void fb_flush (void)
+{
+ fb_entry *p;
+ integer n;
+ for (p = fb_array; p < fb_ptr;) {
+ n = pdf_buf_size - pdf_ptr;
+ if (fb_ptr - p < n)
+ n = fb_ptr - p;
+ memcpy (pdf_buf + pdf_ptr, p, (unsigned) n);
+ pdf_ptr += n;
+ if (pdf_ptr == pdf_buf_size)
+ pdf_flush ();
+ p += n;
+ }
+ fb_ptr = fb_array;
+}
+
+#define SUBSET_TAG_LENGTH 6
+void make_subset_tag(fd_entry * fd)
+{
+ int i, j = 0, a[SUBSET_TAG_LENGTH];
+ md5_state_t pms;
+ char *glyph;
+ glw_entry *glw_glyph;
+ struct avl_traverser t;
+ md5_byte_t digest[16];
+ void **aa;
+ static struct avl_table *st_tree = NULL;
+ if (st_tree == NULL)
+ st_tree = avl_create(comp_string_entry, NULL, &avl_xallocator);
+ assert(fd != NULL);
+ assert(fd->gl_tree != NULL);
+ assert(fd->fontname != NULL);
+ assert(fd->subset_tag == NULL);
+ fd->subset_tag = xtalloc(SUBSET_TAG_LENGTH + 1, char);
+ do {
+ md5_init(&pms);
+ avl_t_init(&t, fd->gl_tree);
+ if (is_cidkeyed(fd->fm)) { /* glw_entry items */
+ for (glw_glyph = (glw_entry *) avl_t_first(&t, fd->gl_tree); glw_glyph != NULL;
+ glw_glyph = (glw_entry *) avl_t_next(&t)) {
+ glyph = malloc(12);
+ sprintf(glyph,"%05u%05u ",glw_glyph->id,glw_glyph->wd);
+ md5_append(&pms, (md5_byte_t *) glyph, strlen(glyph));
+ free(glyph);
+ }
+ } else {
+ for (glyph = (char *) avl_t_first(&t, fd->gl_tree); glyph != NULL;
+ glyph = (char *) avl_t_next(&t)) {
+ md5_append(&pms, (md5_byte_t *) glyph, strlen(glyph));
+ md5_append(&pms, (md5_byte_t *) " ", 1);
+ }
+ }
+ md5_append(&pms, (md5_byte_t *) fd->fontname, strlen(fd->fontname));
+ md5_append(&pms, (md5_byte_t *) & j, sizeof(int)); /* to resolve collision */
+ md5_finish(&pms, digest);
+ for (a[0] = 0, i = 0; i < 13; i++)
+ a[0] += digest[i];
+ for (i = 1; i < SUBSET_TAG_LENGTH; i++)
+ a[i] = a[i - 1] - digest[i - 1] + digest[(i + 12) % 16];
+ for (i = 0; i < SUBSET_TAG_LENGTH; i++)
+ fd->subset_tag[i] = a[i] % 26 + 'A';
+ fd->subset_tag[SUBSET_TAG_LENGTH] = '\0';
+ j++;
+ assert(j < 100);
+ }
+ while ((char *) avl_find(st_tree, fd->subset_tag) != NULL);
+ aa = avl_probe(st_tree, fd->subset_tag);
+ assert(aa != NULL);
+ if (j > 2)
+ pdftex_warn
+ ("\nmake_subset_tag(): subset-tag collision, resolved in round %d.\n",
+ j);
+}
+
+void pdf_puts (const char *s)
+{
+ pdfroom (strlen (s) + 1);
+ while (*s)
+ pdf_buf[pdf_ptr++] = *s++;
+}
+
+__attribute__ ((format (printf, 1, 2)))
+void pdf_printf (const char *fmt, ...)
+{
+ va_list args;
+ va_start (args, fmt);
+ vsnprintf (print_buf, PRINTF_BUF_SIZE, fmt, args);
+ pdf_puts (print_buf);
+ va_end (args);
+}
+
+strnumber maketexstring (const char *s)
+{
+ if (s == NULL || *s == 0)
+ return get_nullstr ();
+ return maketexlstring(s,strlen(s));
+}
+
+strnumber maketexlstring (const char *s, size_t l)
+{
+ if (s == NULL || l == 0)
+ return get_nullstr ();
+ check_pool_overflow (pool_ptr + l);
+ while (l-- > 0)
+ str_pool[pool_ptr++] = *s++;
+ last_tex_string = make_string ();
+ return last_tex_string;
+}
+
+
+/* print a C string through TeX */
+void
+print_string (char *j) {
+ while (*j) {
+ print_char(*j);
+ j++;
+ }
+}
+
+/* append a C string to a TeX string */
+void
+append_string (char *s) {
+ if (s == NULL || *s == 0)
+ return;
+ check_buf (pool_ptr + strlen(s), pool_size);
+ while (*s)
+ str_pool[pool_ptr++] = *s++;
+ return;
+}
+
+__attribute__ ((format (printf, 1, 2)))
+void tex_printf (const char *fmt, ...)
+{
+ va_list args;
+ va_start (args, fmt);
+ vsnprintf (print_buf, PRINTF_BUF_SIZE, fmt, args);
+ print_string (print_buf);
+ xfflush (stdout);
+ va_end (args);
+}
+
+/* Helper for pdftex_fail. */
+static void safe_print (const char *str)
+{
+ const char *c;
+ for (c = str; *c; ++c)
+ print (*c);
+}
+
+void remove_pdffile (void)
+{
+ if (!kpathsea_debug && output_file_name && !fixed_pdf_draftmode) {
+ xfclose (pdf_file, makecstring (output_file_name));
+ remove (makecstring (output_file_name));
+ }
+}
+
+/* pdftex_fail may be called when a buffer overflow has happened/is
+ happening, therefore may not call mktexstring. However, with the
+ current implementation it appears that error messages are misleading,
+ possibly because pool overflows are detected too late.
+
+ The output format of this fuction must be the same as pdf_error in
+ pdftex.web! */
+
+__attribute__ ((noreturn, format (printf, 1, 2)))
+void pdftex_fail (const char *fmt, ...)
+{
+ va_list args;
+ va_start (args, fmt);
+ print_ln ();
+ safe_print ("!luaTeX error");
+ if (cur_file_name) {
+ safe_print (" (file ");
+ safe_print (cur_file_name);
+ safe_print (")");
+ }
+ safe_print (": ");
+ vsnprintf (print_buf, PRINTF_BUF_SIZE, fmt, args);
+ safe_print (print_buf);
+ va_end (args);
+ print_ln ();
+ remove_pdffile();
+ safe_print (" ==> Fatal error occurred, no output PDF file produced!");
+ print_ln ();
+ if (kpathsea_debug) {
+ abort ();
+ } else {
+ exit (EX_SOFTWARE);
+ }
+}
+
+/* The output format of this fuction must be the same as pdf_warn in
+ pdftex.web! */
+
+__attribute__ ((format (printf, 1, 2)))
+void pdftex_warn (const char *fmt, ...)
+{
+ va_list args;
+ va_start (args, fmt);
+ print_ln ();
+ tex_printf ("luaTeX warning");
+ if (cur_file_name)
+ tex_printf (" (file %s)", cur_file_name);
+ tex_printf (": ");
+ vsnprintf (print_buf, PRINTF_BUF_SIZE, fmt, args);
+ print_string (print_buf);
+ va_end (args);
+ print_ln ();
+}
+
+
+void tex_error(char *msg, char **hlp) {
+ strnumber aa = 0,bb = 0,cc = 0,dd = 0,ee = 0;
+ int k = 0;
+ while (hlp[k]!=NULL)
+ k++;
+ if (k>0) aa =maketexstring(hlp[0]);
+ if (k>1) bb =maketexstring(hlp[1]);
+ if (k>2) cc =maketexstring(hlp[2]);
+ if (k>3) dd =maketexstring(hlp[3]);
+ if (k>4) ee =maketexstring(hlp[4]);
+
+ do_print_err(maketexstring(msg));
+ flush_str(last_tex_string);
+
+ switch (k) {
+ case 1: dohelp1(aa); break;
+ case 2: dohelp2(aa,bb); break;
+ case 3: dohelp3(aa,bb,cc); break;
+ case 4: dohelp4(aa,bb,cc,dd); break;
+ case 5: dohelp5(aa,bb,cc,dd,ee); break;
+ }
+ error();
+
+ if (ee) flush_str(ee);
+ if (dd) flush_str(dd);
+ if (cc) flush_str(cc);
+ if (bb) flush_str(bb);
+ if (aa) flush_str(aa);
+}
+
+
+void garbage_warning (void)
+{
+ pdftex_warn ("dangling objects discarded, no output file produced.");
+ remove_pdffile ();
+}
+
+char *makecstring (integer s) {
+ int l;
+ return makeclstring(s,&l);
+}
+
+
+char *makeclstring (integer s, int *len)
+{
+ static char *cstrbuf = NULL;
+ char *p;
+ static int allocsize;
+ int allocgrow, i, l;
+ if (s >=2097152) {
+ s -= 2097152;
+ l = str_start[s + 1] - str_start[s];
+ *len = l;
+ check_buf (l + 1, MAX_CSTRING_LEN);
+ if (cstrbuf == NULL) {
+ allocsize = l + 1;
+ cstrbuf = xmallocarray (char, allocsize);
+ } else if (l + 1 > allocsize) {
+ allocgrow = allocsize * 0.2;
+ if (l + 1 - allocgrow > allocsize)
+ allocsize = l + 1;
+ else if (allocsize < MAX_CSTRING_LEN - allocgrow)
+ allocsize += allocgrow;
+ else
+ allocsize = MAX_CSTRING_LEN;
+ cstrbuf = xreallocarray (cstrbuf, char, allocsize);
+ }
+ p = cstrbuf;
+ for (i = 0; i < l; i++)
+ *p++ = str_pool[i + str_start[s]];
+ *p = 0;
+ } else {
+ if (cstrbuf == NULL) {
+ allocsize = 5;
+ cstrbuf = xmallocarray (char, allocsize);
+ }
+ if (s <= 0x7F) {
+ cstrbuf[0] = s;
+ cstrbuf[1] = 0;
+ *len = 1;
+ } else if (s <= 0x7FF ) {
+ cstrbuf[0] = 0xC0 + (s / 0x40);
+ cstrbuf[1] = 0x80 + (s % 0x40);
+ cstrbuf[2] = 0;
+ *len = 2;
+ } else if (s <= 0xFFFF ) {
+ cstrbuf[0] = 0xE0 + (s / 0x1000);
+ cstrbuf[1] = 0x80 + ((s % 0x1000) / 0x40);
+ cstrbuf[2] = 0x80 + ((s % 0x1000) % 0x40);
+ cstrbuf[3] = 0;
+ *len = 3;
+ } else {
+ if (s >= 0x10FF00) {
+ cstrbuf[0] = s-0x10FF00;
+ cstrbuf[1] = 0;
+ *len = 1;
+ } else {
+ cstrbuf[0] = 0xF0 + (s / 0x40000);
+ cstrbuf[1] = 0x80 + ((s % 0x40000) / 0x1000);
+ cstrbuf[2] = 0x80 + (((s % 0x40000) % 0x1000) / 0x40);
+ cstrbuf[3] = 0x80 + (((s % 0x40000) % 0x1000) % 0x40);
+ cstrbuf[4] = 0;
+ *len = 4;
+ }
+ }
+ }
+ return cstrbuf;
+}
+
+void set_job_id (int year, int month, int day, int time)
+{
+ char *name_string, *format_string, *s;
+ size_t slen;
+ int i;
+
+ if (job_id_string != NULL)
+ return;
+
+ name_string = xstrdup (makecstring (job_name));
+ format_string = xstrdup (makecstring (format_ident));
+ slen = SMALL_BUF_SIZE +
+ strlen (name_string) +
+ strlen (format_string) +
+ strlen (ptexbanner) +
+ strlen (versionstring) + strlen (kpathsea_version_string);
+ s = xtalloc (slen, char);
+ /* The Web2c version string starts with a space. */
+ i = snprintf (s, slen,
+ "%.4d/%.2d/%.2d %.2d:%.2d %s %s %s%s %s",
+ year, month, day, time / 60, time % 60,
+ name_string, format_string, ptexbanner,
+ versionstring, kpathsea_version_string);
+ check_nprintf(i,slen);
+ job_id_string = xstrdup (s);
+ xfree (s);
+ xfree (name_string);
+ xfree (format_string);
+}
+
+int get_build_revision (void) {
+ int revision;
+ if(sscanf (BUILD_REVISION,"$Revision: %d $", &revision)) {
+ return revision;
+ }
+ return 0;
+}
+
+void make_pdftex_banner (void)
+{
+ static boolean pdftexbanner_init = false;
+ char *s;
+ size_t slen;
+ int i;
+
+ if (pdftexbanner_init)
+ return;
+
+ slen = SMALL_BUF_SIZE +
+ strlen (ptexbanner) +
+ strlen (versionstring) + strlen (kpathsea_version_string);
+ s = xtalloc (slen, char);
+ /* The Web2c version string starts with a space. */
+ i = snprintf (s, slen,
+ "%s%s %s", ptexbanner, versionstring, kpathsea_version_string);
+ check_nprintf (i, slen);
+ pdftex_banner = maketexstring (s);
+ xfree (s);
+ pdftexbanner_init = true;
+}
+
+strnumber get_resname_prefix (void)
+{
+/* static char name_str[] = */
+/* "!\"$&'*+,-.0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\" */
+/* "^_`abcdefghijklmnopqrstuvwxyz|~"; */
+ static char name_str[] =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ char prefix[7]; /* make a tag of 6 chars long */
+ unsigned long crc;
+ short i;
+ size_t base = strlen (name_str);
+ crc = crc32 (0L, Z_NULL, 0);
+ crc = crc32 (crc, (Bytef *) job_id_string, strlen (job_id_string));
+ for (i = 0; i < 6; i++) {
+ prefix[i] = name_str[crc % base];
+ crc /= base;
+ }
+ prefix[6] = 0;
+ return maketexstring (prefix);
+}
+
+size_t xfwrite (void *ptr, size_t size, size_t nmemb, FILE * stream)
+{
+ if (fwrite (ptr, size, nmemb, stream) != nmemb)
+ pdftex_fail ("fwrite() failed");
+ return nmemb;
+}
+
+int xfflush (FILE * stream)
+{
+ if (fflush (stream) != 0)
+ pdftex_fail ("fflush() failed");
+ return 0;
+}
+
+int xgetc (FILE * stream)
+{
+ int c = getc (stream);
+ if (c < 0 && c != EOF)
+ pdftex_fail ("getc() failed");
+ return c;
+}
+
+int xputc (int c, FILE * stream)
+{
+ int i = putc (c, stream);
+ if (i < 0)
+ pdftex_fail ("putc() failed");
+ return i;
+}
+
+void write_stream_length (integer length, integer offset)
+{
+ if (jobname_cstr == NULL)
+ jobname_cstr = xstrdup (makecstring (job_name));
+ if (fixed_pdf_draftmode == 0) {
+ xfseek (pdf_file, offset, SEEK_SET, jobname_cstr);
+ fprintf (pdf_file, "%li", (long int) length);
+ xfseek (pdf_file, pdfoffset (), SEEK_SET, jobname_cstr);
+ }
+}
+
+scaled ext_xn_over_d (scaled x, scaled n, scaled d)
+{
+ double r = (((double) x) * ((double) n)) / ((double) d);
+ if (r > DBL_EPSILON)
+ r += 0.5;
+ else
+ r -= 0.5;
+ if (r >= (double) maxinteger || r <= -(double) maxinteger)
+ pdftex_warn ("arithmetic: number too big");
+ return (scaled) r;
+}
+
+void libpdffinish ()
+{
+ xfree (fb_array);
+ xfree (char_array);
+ xfree (job_id_string);
+ fm_free ();
+ t1_free ();
+ enc_free ();
+ epdf_free ();
+ ttf_free ();
+ sfd_free ();
+ glyph_unicode_free ();
+ zip_free ();
+}
+
+/* Converts any string given in in in an allowed PDF string which can be
+ * handled by printf et.al.: \ is escaped to \\, parenthesis are escaped and
+ * control characters are octal encoded.
+ * This assumes that the string does not contain any already escaped
+ * characters!
+ */
+char *convertStringToPDFString (const char *in, int len)
+{
+ static char pstrbuf[MAX_PSTRING_LEN];
+ char *out = pstrbuf;
+ int i, j, k;
+ char buf[5];
+ j = 0;
+ for (i = 0; i < len; i++) {
+ check_buf (j + sizeof (buf), MAX_PSTRING_LEN);
+ if (((unsigned char) in[i] < '!') || ((unsigned char) in[i] > '~')) {
+ /* convert control characters into oct */
+ k = snprintf (buf, sizeof (buf),
+ "\\%03o", (unsigned int) (unsigned char) in[i]);
+ check_nprintf (k, sizeof (buf));
+ out[j++] = buf[0];
+ out[j++] = buf[1];
+ out[j++] = buf[2];
+ out[j++] = buf[3];
+ } else if ((in[i] == '(') || (in[i] == ')')) {
+ /* escape paranthesis */
+ out[j++] = '\\';
+ out[j++] = in[i];
+ } else if (in[i] == '\\') {
+ /* escape backslash */
+ out[j++] = '\\';
+ out[j++] = '\\';
+ } else {
+ /* copy char :-) */
+ out[j++] = in[i];
+ }
+ }
+ out[j] = '\0';
+ return pstrbuf;
+}
+
+
+/* Converts any string given in in in an allowed PDF string which can be
+ * handled by printf et.al.: \ is escaped to \\, parenthesis are escaped and
+ * control characters are octal encoded.
+ * This assumes that the string does not contain any already escaped
+ * characters!
+ *
+ * See escapename for parameter description.
+ */
+void escapestring (poolpointer in)
+{
+ const poolpointer out = pool_ptr;
+ unsigned char ch;
+ int i;
+ while (in < out) {
+ if (pool_ptr + 4 >= pool_size) {
+ pool_ptr = pool_size;
+ /* error by str_toks that calls str_room(1) */
+ return;
+ }
+
+ ch = (unsigned char) str_pool[in++];
+
+ if ((ch < '!') || (ch > '~')) {
+ /* convert control characters into oct */
+ i = snprintf ((char *) &str_pool[pool_ptr], 5,
+ "\\%.3o", (unsigned int) ch);
+ check_nprintf (i, 5);
+ pool_ptr += i;
+ continue;
+ }
+ if ((ch == '(') || (ch == ')') || (ch == '\\')) {
+ /* escape parenthesis and backslash */
+ str_pool[pool_ptr++] = '\\';
+ }
+ /* copy char :-) */
+ str_pool[pool_ptr++] = ch;
+ }
+}
+
+
+/* Convert any given string in a PDF name using escaping mechanism
+ of PDF 1.2. The result does not include the leading slash.
+
+ PDF specification 1.6, section 3.2.6 "Name Objects" explains:
+ <blockquote>
+ Beginning with PDF 1.2, any character except null (character code 0) may
+ be included in a name by writing its 2-digit hexadecimal code, preceded
+ by the number sign character (#); see implementation notes 3 and 4 in
+ Appendix H. This syntax is required to represent any of the delimiter or
+ white-space characters or the number sign character itself; it is
+ recommended but not required for characters whose codes are outside the
+ range 33 (!) to 126 (~).
+ </blockquote>
+ The following table shows the conversion that are done by this
+ function:
+ code result reason
+ -----------------------------------
+ 0 ignored not allowed
+ 1..32 escaped must for white-space:
+ 9 (tab), 10 (lf), 12 (ff), 13 (cr), 32 (space)
+ recommended for the other control characters
+ 35 escaped escape char "#"
+ 37 escaped delimiter "%"
+ 40..41 escaped delimiters "(" and ")"
+ 47 escaped delimiter "/"
+ 60 escaped delimiter "<"
+ 62 escaped delimiter ">"
+ 91 escaped delimiter "["
+ 93 escaped delimiter "]"
+ 123 escaped delimiter "{"
+ 125 escaped delimiter "}"
+ 127..255 escaped recommended
+ else copy regular characters
+
+ Parameter "in" is a pointer into the string pool where
+ the input string is located. The output string is written
+ as temporary string right after the input string.
+ Thus at the begin of the procedure the global variable
+ "pool_ptr" points to the start of the output string and
+ after the end when the procedure returns.
+*/
+void escapename (poolpointer in)
+{
+ const poolpointer out = pool_ptr;
+ unsigned char ch;
+ int i;
+
+ while (in < out) {
+ if (pool_ptr + 3 >= pool_size) {
+ pool_ptr = pool_size;
+ /* error by str_toks that calls str_room(1) */
+ return;
+ }
+
+ ch = (unsigned char) str_pool[in++];
+
+ if ((ch >= 1 && ch <= 32) || ch >= 127) {
+ /* escape */
+ i = snprintf ((char *) &str_pool[pool_ptr], 4,
+ "#%.2X", (unsigned int) ch);
+ check_nprintf (i, 4);
+ pool_ptr += i;
+ continue;
+ }
+ switch (ch) {
+ case 0:
+ /* ignore */
+ break;
+ case 35:
+ case 37:
+ case 40:
+ case 41:
+ case 47:
+ case 60:
+ case 62:
+ case 91:
+ case 93:
+ case 123:
+ case 125:
+ /* escape */
+ i = snprintf ((char *) &str_pool[pool_ptr], 4,
+ "#%.2X", (unsigned int) ch);
+ check_nprintf (i, 4);
+ pool_ptr += i;
+ break;
+ default:
+ /* copy */
+ str_pool[pool_ptr++] = ch;
+ }
+ }
+}
+
+/* Convert any given string in a PDF hexadecimal string. The
+ result does not include the angle brackets.
+
+ This procedure uses uppercase hexadecimal letters.
+
+ See escapename for description of parameters.
+*/
+void escapehex (poolpointer in)
+{
+ const poolpointer out = pool_ptr;
+ unsigned char ch;
+ int i;
+
+ while (in < out) {
+ if (pool_ptr + 2 >= pool_size) {
+ pool_ptr = pool_size;
+ /* error by str_toks that calls str_room(1) */
+ return;
+ }
+
+ ch = (unsigned char) str_pool[in++];
+
+ i = snprintf ((char *) &str_pool[pool_ptr], 3,"%.2X", (unsigned int) ch);
+ check_nprintf (i, 3);
+ pool_ptr += 2;
+ }
+}
+
+/* Unescape any given hexadecimal string.
+
+ Last hex digit can be omitted, it is replaced by zero, see
+ PDF specification.
+
+ Invalid digits are silently ignored.
+
+ See escapename for description of parameters.
+*/
+void unescapehex (poolpointer in)
+{
+ const poolpointer out = pool_ptr;
+ unsigned char ch;
+ boolean first = true;
+ unsigned char a = 0; /* to avoid warning about uninitialized use of a */
+ while (in < out) {
+ if (pool_ptr + 1 >= pool_size) {
+ pool_ptr = pool_size;
+ /* error by str_toks that calls str_room(1) */
+ return;
+ }
+
+ ch = (unsigned char) str_pool[in++];
+
+ if ((ch >= '0') && (ch <= '9')) {
+ ch -= '0';
+ } else if ((ch >= 'A') && (ch <= 'F')) {
+ ch -= 'A' - 10;
+ } else if ((ch >= 'a') && (ch <= 'f')) {
+ ch -= 'a' - 10;
+ } else {
+ continue; /* ignore wrong character */
+ }
+
+ if (first) {
+ a = ch << 4;
+ first = false;
+ continue;
+ }
+
+ str_pool[pool_ptr++] = a + ch;
+ first = true;
+ }
+ if (!first) { /* last hex digit is omitted */
+ str_pool[pool_ptr++] = ch << 4;
+ }
+}
+
+
+/* Converts any string given in in in an allowed PDF string which is
+ * hexadecimal encoded;
+ * sizeof(out) should be at least lin*2+1.
+ */
+static void convertStringToHexString (const char *in, char *out, int lin)
+{
+ int i, j, k;
+ char buf[3];
+ j = 0;
+ for (i = 0; i < lin; i++) {
+ k = snprintf (buf, sizeof (buf),
+ "%02X", (unsigned int) (unsigned char) in[i]);
+ check_nprintf (k, sizeof (buf));
+ out[j++] = buf[0];
+ out[j++] = buf[1];
+ }
+ out[j] = '\0';
+}
+
+/* Compute the ID string as per PDF1.4 9.3:
+ <blockquote>
+ File identifers are defined by the optional ID entry in a PDF file's
+ trailer dictionary (see Section 3.4.4, "File Trailer"; see also
+ implementation note 105 in Appendix H). The value of this entry is an
+ array of two strings. The first string is a permanent identifier based
+ on the contents of the file at the time it was originally created, and
+ does not change when the file is incrementally updated. The second
+ string is a changing identifier based on the file's contents at the
+ time it was last updated. When a file is first written, both
+ identifiers are set to the same value. If both identifiers match when a
+ file reference is resolved, it is very likely that the correct file has
+ been found; if only the first identifier matches, then a different
+ version of the correct file has been found.
+ To help ensure the uniqueness of file identifiers, it is recommend
+ that they be computed using a message digest algorithm such as MD5
+ (described in Internet RFC 1321, The MD5 Message-Digest Algorithm; see
+ the Bibliography), using the following information (see implementation
+ note 106 in Appendix H):
+ - The current time
+ - A string representation of the file's location, usually a pathname
+ - The size of the file in bytes
+ - The values of all entries in the file's document information
+ dictionary (see Section 9.2.1, Document Information Dictionary )
+ </blockquote>
+ This stipulates only that the two IDs must be identical when the file is
+ created and that they should be reasonably unique. Since it's difficult
+ to get the file size at this point in the execution of pdfTeX and
+ scanning the info dict is also difficult, we start with a simpler
+ implementation using just the first two items.
+ */
+void print_ID (strnumber filename)
+{
+ time_t t;
+ size_t size;
+ char time_str[32];
+ md5_state_t state;
+ md5_byte_t digest[16];
+ char id[64];
+ char *file_name;
+ char pwd[4096];
+ /* start md5 */
+ md5_init (&state);
+ /* get the time */
+ t = time (NULL);
+ size =
+ strftime (time_str, sizeof (time_str), "%Y%m%dT%H%M%SZ", gmtime (&t));
+ md5_append (&state, (const md5_byte_t *) time_str, size);
+ /* get the file name */
+ if (getcwd (pwd, sizeof (pwd)) == NULL)
+ pdftex_fail ("getcwd() failed (path too long?)");
+ file_name = makecstring (filename);
+ md5_append (&state, (const md5_byte_t *) pwd, strlen (pwd));
+ md5_append (&state, (const md5_byte_t *) "/", 1);
+ md5_append (&state, (const md5_byte_t *) file_name, strlen (file_name));
+ /* finish md5 */
+ md5_finish (&state, digest);
+ /* write the IDs */
+ convertStringToHexString ((char *) digest, id, 16);
+ pdf_printf ("/ID [<%s> <%s>]", id, id);
+}
+
+/* Print the /CreationDate entry.
+
+ PDF Reference, third edition says about the expected date format:
+ <blockquote>
+ 3.8.2 Dates
+
+ PDF defines a standard date format, which closely follows that of
+ the international standard ASN.1 (Abstract Syntax Notation One),
+ defined in ISO/IEC 8824 (see the Bibliography). A date is a string
+ of the form
+
+ (D:YYYYMMDDHHmmSSOHH'mm')
+
+ where
+
+ YYYY is the year
+ MM is the month
+ DD is the day (01-31)
+ HH is the hour (00-23)
+ mm is the minute (00-59)
+ SS is the second (00-59)
+ O is the relationship of local time to Universal Time (UT),
+ denoted by one of the characters +, -, or Z (see below)
+ HH followed by ' is the absolute value of the offset from UT
+ in hours (00-23)
+ mm followed by ' is the absolute value of the offset from UT
+ in minutes (00-59)
+
+ The apostrophe character (') after HH and mm is part of the syntax.
+ All fields after the year are optional. (The prefix D:, although also
+ optional, is strongly recommended.) The default values for MM and DD
+ are both 01; all other numerical fields default to zero values. A plus
+ sign (+) as the value of the O field signifies that local time is
+ later than UT, a minus sign (-) that local time is earlier than UT,
+ and the letter Z that local time is equal to UT. If no UT information
+ is specified, the relationship of the specified time to UT is
+ considered to be unknown. Whether or not the time zone is known, the
+ rest of the date should be specified in local time.
+
+ For example, December 23, 1998, at 7:52 PM, U.S. Pacific Standard
+ Time, is represented by the string
+
+ D:199812231952-08'00'
+ </blockquote>
+
+ The main difficulty is get the time zone offset. strftime() does this in ISO
+ C99 (e.g. newer glibc) with %z, but we have to work with other systems (e.g.
+ Solaris 2.5).
+*/
+
+static time_t start_time = 0;
+#define TIME_STR_SIZE 30
+static char start_time_str[TIME_STR_SIZE];
+static char time_str[TIME_STR_SIZE];
+ /* minimum size for time_str is 24: "D:YYYYmmddHHMMSS+HH'MM'" */
+
+static void makepdftime (time_t t, char *time_str)
+{
+
+ struct tm lt, gmt;
+ size_t size;
+ int i, off, off_hours, off_mins;
+
+ /* get the time */
+ lt = *localtime (&t);
+ size = strftime (time_str, TIME_STR_SIZE, "D:%Y%m%d%H%M%S", &lt);
+ /* expected format: "YYYYmmddHHMMSS" */
+ if (size == 0) {
+ /* unexpected, contents of time_str is undefined */
+ time_str[0] = '\0';
+ return;
+ }
+
+ /* correction for seconds: %S can be in range 00..61,
+ the PDF reference expects 00..59,
+ therefore we map "60" and "61" to "59" */
+ if (time_str[14] == '6') {
+ time_str[14] = '5';
+ time_str[15] = '9';
+ time_str[16] = '\0'; /* for safety */
+ }
+
+ /* get the time zone offset */
+ gmt = *gmtime (&t);
+
+ /* this calculation method was found in exim's tod.c */
+ off = 60 * (lt.tm_hour - gmt.tm_hour) + lt.tm_min - gmt.tm_min;
+ if (lt.tm_year != gmt.tm_year) {
+ off += (lt.tm_year > gmt.tm_year) ? 1440 : -1440;
+ } else if (lt.tm_yday != gmt.tm_yday) {
+ off += (lt.tm_yday > gmt.tm_yday) ? 1440 : -1440;
+ }
+
+ if (off == 0) {
+ time_str[size++] = 'Z';
+ time_str[size] = 0;
+ } else {
+ off_hours = off / 60;
+ off_mins = abs (off - off_hours * 60);
+ i = snprintf (&time_str[size], 9,
+ "%+03d'%02d'", off_hours, off_mins);
+ check_nprintf (i, 9);
+ }
+}
+
+void init_start_time ()
+{
+ if (start_time == 0) {
+ start_time = time ((time_t *) NULL);
+ makepdftime (start_time, start_time_str);
+ }
+}
+
+void print_creation_date ()
+{
+ init_start_time ();
+ pdf_printf ("/CreationDate (%s)\n", start_time_str);
+}
+
+void print_mod_date ()
+{
+ init_start_time ();
+ pdf_printf ("/ModDate (%s)\n", start_time_str);
+}
+
+void getcreationdate ()
+{
+ /* put creation date on top of string pool and update pool_ptr */
+ size_t len = strlen (start_time_str);
+
+ init_start_time ();
+
+ if ((unsigned)(pool_ptr + len) >= (unsigned)pool_size) {
+ pool_ptr = pool_size;
+ /* error by str_toks that calls str_room(1) */
+ return;
+ }
+
+ memcpy (&str_pool[pool_ptr], start_time_str, len);
+ pool_ptr += len;
+}
+
+/* makecfilename
+ input/ouput same as makecstring:
+ input: string number
+ output: C string with quotes removed.
+ That means, file names that are legal on some operation systems
+ cannot any more be used since pdfTeX version 1.30.4.
+*/
+char *makecfilename (strnumber s)
+{
+ char *name = makecstring (s);
+ char *p = name;
+ char *q = name;
+
+ while (*p) {
+ if (*p != '"')
+ *q++ = *p;
+ p++;
+ }
+ *q = '\0';
+ return name;
+}
+
+/* function strips trailing zeros in string with numbers; */
+/* leading zeros are not stripped (as in real life) */
+char *stripzeros (char *a)
+{
+ enum { NONUM, DOTNONUM, INT, DOT, LEADDOT, FRAC } s = NONUM, t = NONUM;
+ char *p, *q, *r;
+ for (p = q = r = a; *p != '\0';) {
+ switch (s) {
+ case NONUM:
+ if (*p >= '0' && *p <= '9')
+ s = INT;
+ else if (*p == '.')
+ s = LEADDOT;
+ break;
+ case DOTNONUM:
+ if (*p != '.' && (*p < '0' || *p > '9'))
+ s = NONUM;
+ break;
+ case INT:
+ if (*p == '.')
+ s = DOT;
+ else if (*p < '0' || *p > '9')
+ s = NONUM;
+ break;
+ case DOT:
+ case LEADDOT:
+ if (*p >= '0' && *p <= '9')
+ s = FRAC;
+ else if (*p == '.')
+ s = DOTNONUM;
+ else
+ s = NONUM;
+ break;
+ case FRAC:
+ if (*p == '.')
+ s = DOTNONUM;
+ else if (*p < '0' || *p > '9')
+ s = NONUM;
+ break;
+ default:;
+ }
+ switch (s) {
+ case DOT:
+ r = q;
+ break;
+ case LEADDOT:
+ r = q + 1;
+ break;
+ case FRAC:
+ if (*p > '0')
+ r = q + 1;
+ break;
+ case NONUM:
+ if ((t == FRAC || t == DOT) && r != a) {
+ q = r--;
+ if (*r == '.') /* was a LEADDOT */
+ *r = '0';
+ r = a;
+ }
+ break;
+ default:;
+ }
+ *q++ = *p++;
+ t = s;
+ }
+ *q = '\0';
+ return a;
+}
+
+void initversionstring(char **versions)
+{
+ (void) asprintf(versions,
+ "This is build %d, created on %dT%06dZ\n"
+ "Compiled with libpng %s; using libpng %s\n"
+ "Compiled with zlib %s; using zlib %s\n"
+ "Compiled with xpdf version %s\n",
+ get_build_revision(), BUILD_DATE, (BUILD_TIME-1000000),
+ PNG_LIBPNG_VER_STRING, png_libpng_ver,
+ ZLIB_VERSION, zlib_version, xpdfVersion);
+}
+
+
+/*************************************************/
+/* Color Stack and Matrix Transformation Support */
+/*************************************************/
+
+/*
+ In the following array and especially stack data structures are used.
+ They have the following properties:
+ - They automatically grow dynamically.
+ - The size never decreases.
+ - The variable with name ending in "size" contains the number how many
+ entries the data structure can hold.
+ - The variable with name ending in "used" contains the number of
+ actually used entries.
+ - Memory of strings in stack entries must be allocated and
+ freed if the stack is cleared.
+*/
+
+/* Color Stack */
+
+#define STACK_INCREMENT 8
+#define MAX_COLORSTACKS 32768
+/* The colorstack number is stored in two bytes (info field of the node) */
+/* Condition (newcolorstack): MAX_COLORSTACKS mod STACK_INCREMENT = 0 */
+
+#define COLOR_DEFAULT "0 g 0 G"
+/* literal_modes, see pdftex.web */
+#define SET_ORIGIN 0
+#define DIRECT_PAGE 1
+#define DIRECT_ALWAYS 2
+
+/* remember shipout mode: page/form */
+static boolean page_mode;
+
+typedef struct {
+ char **page_stack;
+ char **form_stack;
+ char *page_current;
+ char *form_current;
+ char *form_init;
+ int page_size;
+ int form_size;
+ int page_used;
+ int form_used;
+ int literal_mode;
+ boolean page_start;
+} colstack_type;
+
+static colstack_type *colstacks = NULL;
+static int colstacks_size = 0;
+static int colstacks_used = 0;
+
+/*
+ Initialization is done, if the color stacks are used,
+ init_colorstacks() is defined as macro to avoid unnecessary
+ procedure calls.
+*/
+#define init_colorstacks() if (colstacks_size == 0) colstacks_first_init();
+void colstacks_first_init()
+{
+ colstacks_size = STACK_INCREMENT;
+ colstacks = xtalloc(colstacks_size, colstack_type);
+ colstacks_used = 1;
+ colstacks[0].page_stack = NULL;
+ colstacks[0].form_stack = NULL;
+ colstacks[0].page_size = 0;
+ colstacks[0].form_size = 0;
+ colstacks[0].page_used = 0;
+ colstacks[0].form_used = 0;
+ colstacks[0].page_current = xstrdup(COLOR_DEFAULT);
+ colstacks[0].form_current = xstrdup(COLOR_DEFAULT);
+ colstacks[0].form_init = xstrdup(COLOR_DEFAULT);
+ colstacks[0].literal_mode = DIRECT_ALWAYS;
+ colstacks[0].page_start = true;
+}
+
+int colorstackused()
+{
+ init_colorstacks();
+ return colstacks_used;
+}
+
+/*
+ newcolorstack()
+ A new color stack is setup with the given parameters.
+ The stack number is returned or -1 in case of error (no room).
+*/
+int newcolorstack(integer s, integer literal_mode, boolean page_start)
+{
+ colstack_type *colstack;
+ int colstack_num;
+ char *str;
+
+ init_colorstacks();
+
+ /* make room */
+ if (colstacks_used == MAX_COLORSTACKS) {
+ return -1;
+ }
+ if (colstacks_used == colstacks_size) {
+ colstacks_size += STACK_INCREMENT;
+ /* If (MAX_COLORSTACKS mod STACK_INCREMENT = 0) then we don't
+ need to check the case that size overruns MAX_COLORSTACKS. */
+ colstacks = xreallocarray(colstacks, colstack_type, colstacks_size);
+ }
+ /* claim new color stack */
+ colstack_num = colstacks_used++;
+ colstack = &colstacks[colstack_num];
+ /* configure the new color stack */
+ colstack->page_stack = NULL;
+ colstack->form_stack = NULL;
+ colstack->page_size = 0;
+ colstack->page_used = 0;
+ colstack->form_size = 0;
+ colstack->form_used = 0;
+ colstack->literal_mode = literal_mode;
+ colstack->page_start = page_start;
+ str = makecstring(s);
+ if (*str == 0) {
+ colstack->page_current = NULL;
+ colstack->form_current = NULL;
+ colstack->form_init = NULL;
+ } else {
+ colstack->page_current = xstrdup(str);
+ colstack->form_current = xstrdup(str);
+ colstack->form_init = xstrdup(str);
+ }
+ return colstack_num;
+}
+
+#define get_colstack(n) (&colstacks[n])
+
+/*
+ Puts a string on top of the string pool and updates pool_ptr.
+*/
+void put_cstring_on_str_pool(poolpointer start, char *str)
+{
+ size_t len;
+
+ if (str == NULL || *str == 0) {
+ return;
+ }
+
+ len = strlen(str);
+ pool_ptr = start + len;
+ if (pool_ptr >= pool_size) {
+ pool_ptr = pool_size;
+ /* error by str_toks that calls str_room(1) */
+ return;
+ }
+ memcpy(&str_pool[start], str, len);
+}
+
+integer colorstackset(int colstack_no, integer s)
+{
+ colstack_type *colstack = get_colstack(colstack_no);
+
+ if (page_mode) {
+ xfree(colstack->page_current);
+ colstack->page_current = xstrdup(makecstring(s));
+ } else {
+ xfree(colstack->form_current);
+ colstack->form_current = xstrdup(makecstring(s));
+ }
+ return colstack->literal_mode;
+}
+
+integer colorstackcurrent(int colstack_no)
+{
+ colstack_type *colstack = get_colstack(colstack_no);
+
+ if (page_mode) {
+ put_cstring_on_str_pool(pool_ptr, colstack->page_current);
+ } else {
+ put_cstring_on_str_pool(pool_ptr, colstack->form_current);
+ }
+ return colstack->literal_mode;
+}
+
+integer colorstackpush(int colstack_no, integer s)
+{
+ colstack_type *colstack = get_colstack(colstack_no);
+ char *str;
+
+ if (page_mode) {
+ if (colstack->page_used == colstack->page_size) {
+ colstack->page_size += STACK_INCREMENT;
+ colstack->page_stack = xretalloc(colstack->page_stack,
+ colstack->page_size, char *);
+ }
+ colstack->page_stack[colstack->page_used++] = colstack->page_current;
+ str = makecstring(s);
+ if (*str == 0) {
+ colstack->page_current = NULL;
+ } else {
+ colstack->page_current = xstrdup(str);
+ }
+ } else {
+ if (colstack->form_used == colstack->form_size) {
+ colstack->form_size += STACK_INCREMENT;
+ colstack->form_stack = xretalloc(colstack->form_stack,
+ colstack->form_size, char *);
+ }
+ colstack->form_stack[colstack->form_used++] = colstack->form_current;
+ str = makecstring(s);
+ if (*str == 0) {
+ colstack->form_current = NULL;
+ } else {
+ colstack->form_current = xstrdup(str);
+ }
+ }
+ return colstack->literal_mode;
+}
+
+integer colorstackpop(int colstack_no)
+{
+ colstack_type *colstack = get_colstack(colstack_no);
+
+ if (page_mode) {
+ if (colstack->page_used == 0) {
+ pdftex_warn("pop empty color page stack %u",
+ (unsigned int) colstack_no);
+ return colstack->literal_mode;
+ }
+ xfree(colstack->page_current);
+ colstack->page_current = colstack->page_stack[--colstack->page_used];
+ put_cstring_on_str_pool(pool_ptr, colstack->page_current);
+ } else {
+ if (colstack->form_used == 0) {
+ pdftex_warn("pop empty color form stack %u",
+ (unsigned int) colstack_no);
+ return colstack->literal_mode;
+ }
+ xfree(colstack->form_current);
+ colstack->form_current = colstack->form_stack[--colstack->form_used];
+ put_cstring_on_str_pool(pool_ptr, colstack->form_current);
+ }
+ return colstack->literal_mode;
+}
+
+void colorstackpagestart()
+{
+ int i, j;
+ colstack_type *colstack;
+
+ if (page_mode) {
+ /* see procedure pdf_out_colorstack_startpage */
+ return;
+ }
+
+ for (i = 0; i < colstacks_used; i++) {
+ colstack = &colstacks[i];
+ for (j = 0; j < colstack->form_used; j++) {
+ xfree(colstack->form_stack[j]);
+ }
+ colstack->form_used = 0;
+ xfree(colstack->form_current);
+ if (colstack->form_init == NULL) {
+ colstack->form_current = NULL;
+ } else {
+ colstack->form_current = xstrdup(colstack->form_init);
+ }
+ }
+}
+
+integer colorstackskippagestart(int colstack_no)
+{
+ colstack_type *colstack = get_colstack(colstack_no);
+
+ if (!colstack->page_start) {
+ return 1;
+ }
+ if (strcmp(COLOR_DEFAULT, colstack->page_current) == 0) {
+ return 2;
+ }
+ return 0;
+}
+
+
+/* stack for \pdfsetmatrix */
+
+typedef struct {
+ double a;
+ double b;
+ double c;
+ double d;
+ double e;
+ double f;
+} matrix_entry;
+static matrix_entry *matrix_stack = 0;
+static int matrix_stack_size = 0;
+static int matrix_stack_used = 0;
+
+boolean matrixused()
+{
+ return matrix_stack_used > 0;
+}
+
+/* stack for positions of \pdfsave */
+typedef struct {
+ int pos_h;
+ int pos_v;
+ int matrix_stack;
+} pos_entry;
+static pos_entry *pos_stack = 0; /* the stack */
+static int pos_stack_size = 0; /* initially empty */
+static int pos_stack_used = 0; /* used entries */
+
+void matrix_stack_room()
+{
+ matrix_entry *new_stack;
+
+ if (matrix_stack_used >= matrix_stack_size) {
+ matrix_stack_size += STACK_INCREMENT;
+ new_stack = xtalloc(matrix_stack_size, matrix_entry);
+ memcpy((void *) new_stack, (void *) matrix_stack,
+ matrix_stack_used * sizeof(matrix_entry));
+ xfree(matrix_stack);
+ matrix_stack = new_stack;
+ }
+}
+
+void checkpdfsave(int cur_h, int cur_v)
+{
+ pos_entry *new_stack;
+
+ if (pos_stack_used >= pos_stack_size) {
+ pos_stack_size += STACK_INCREMENT;
+ new_stack = xtalloc(pos_stack_size, pos_entry);
+ memcpy((void *) new_stack, (void *) pos_stack,
+ pos_stack_used * sizeof(pos_entry));
+ xfree(pos_stack);
+ pos_stack = new_stack;
+ }
+ pos_stack[pos_stack_used].pos_h = cur_h;
+ pos_stack[pos_stack_used].pos_v = cur_v;
+ if (page_mode) {
+ pos_stack[pos_stack_used].matrix_stack = matrix_stack_used;
+ }
+ pos_stack_used++;
+}
+
+void checkpdfrestore(int cur_h, int cur_v)
+{
+ int diff_h, diff_v;
+ if (pos_stack_used == 0) {
+ pdftex_warn("%s", "\\pdfrestore: missing \\pdfsave");
+ return;
+ }
+ pos_stack_used--;
+ diff_h = cur_h - pos_stack[pos_stack_used].pos_h;
+ diff_v = cur_v - pos_stack[pos_stack_used].pos_v;
+ if (diff_h != 0 || diff_v != 0) {
+ pdftex_warn("Misplaced \\pdfrestore by (%usp, %usp)", diff_h, diff_v);
+ }
+ if (page_mode) {
+ matrix_stack_used = pos_stack[pos_stack_used].matrix_stack;
+ }
+}
+
+void pdfshipoutbegin(boolean shipping_page)
+{
+ pos_stack_used = 0; /* start with empty stack */
+
+ page_mode = shipping_page;
+ if (shipping_page) {
+ colorstackpagestart();
+ }
+}
+
+void pdfshipoutend(boolean shipping_page)
+{
+ if (pos_stack_used > 0) {
+ pdftex_warn("%u unmatched \\pdfsave after %s shipout",
+ (unsigned int) pos_stack_used,
+ ((shipping_page) ? "page" : "form"));
+ }
+}
+
+/*
+ \pdfsetmatrix{a b c d}
+ e := cur_h
+ f := cur_v
+ M_top: current active matrix at the top of
+ the matrix stack
+
+ The origin of \pdfsetmatrix is the current point.
+ The annotation coordinate system is the original
+ page coordinate system. When pdfTeX calculates
+ annotation rectangles it does not take into
+ account this transformations, it uses the original
+ coordinate system. To get the corrected values,
+ first we go back to the origin, perform the
+ transformation and go back:
+
+ ( 1 0 0 ) ( a b 0 ) ( 1 0 0 )
+ ( 0 1 0 ) x ( c d 0 ) x ( 0 1 0 ) x M_top
+ ( -e -f 1 ) ( 0 0 1 ) ( e f 1 )
+
+ ( 1 0 0 ) ( a b 0 )
+ = ( 0 1 0 ) x ( c d 0 ) x M_top
+ ( e f 1 ) ( -e -f 1 )
+
+ ( a b 0 )
+ = ( c d 0 ) x M_top
+ ( e(1-a)-fc f(1-d)-eb 1 )
+
+*/
+
+void pdfsetmatrix(poolpointer in, scaled cur_h, scaled cur_v)
+{
+ /* Argument of \pdfsetmatrix starts with str_pool[in] and ends
+ before str_pool[pool_ptr]. */
+
+ matrix_entry x, *y, *z;
+
+ if (page_mode) {
+ if (sscanf((const char *) &str_pool[in], " %lf %lf %lf %lf ",
+ &x.a, &x.b, &x.c, &x.d) != 4) {
+ pdftex_warn("Unrecognized format of \\pdfsetmatrix{%s}",
+ &str_pool[pool_ptr]);
+ return;
+ }
+ /* calculate this transformation matrix */
+ x.e = (double) cur_h *(1.0 - x.a) - (double) cur_v *x.c;
+ x.f = (double) cur_v *(1.0 - x.d) - (double) cur_h *x.b;
+ matrix_stack_room();
+ z = &matrix_stack[matrix_stack_used];
+ if (matrix_stack_used > 0) {
+ y = &matrix_stack[matrix_stack_used - 1];
+ z->a = x.a * y->a + x.b * y->c;
+ z->b = x.a * y->b + x.b * y->d;
+ z->c = x.c * y->a + x.d * y->c;
+ z->d = x.c * y->b + x.d * y->d;
+ z->e = x.e * y->a + x.f * y->c + y->e;
+ z->f = x.e * y->b + x.f * y->d + y->f;
+ } else {
+ z->a = x.a;
+ z->b = x.b;
+ z->c = x.c;
+ z->d = x.d;
+ z->e = x.e;
+ z->f = x.f;
+ }
+ matrix_stack_used++;
+ }
+}
+
+/* Apply matrix to point (x,y)
+
+ ( a b 0 )
+ ( x y 1 ) x ( c d 0 ) = ( xa+yc+e xb+yd+f 1 )
+ ( e f 1 )
+
+ If \pdfsetmatrix wasn't used, then return the value unchanged.
+*/
+
+/* Return valeus for matrix tranform functions */
+static scaled ret_llx;
+static scaled ret_lly;
+static scaled ret_urx;
+static scaled ret_ury;
+
+scaled getllx()
+{
+ return ret_llx;
+}
+
+scaled getlly()
+{
+ return ret_lly;
+}
+
+scaled geturx()
+{
+ return ret_urx;
+}
+
+scaled getury()
+{
+ return ret_ury;
+}
+
+static int last_llx;
+static int last_lly;
+static int last_urx;
+static int last_ury;
+
+#define DO_ROUND(x) ((x > 0) ? (x + .5) : (x - .5))
+#define DO_MIN(a, b) ((a < b) ? a : b)
+#define DO_MAX(a, b) ((a > b) ? a : b)
+
+void do_matrixtransform(scaled x, scaled y, scaled * retx, scaled * rety)
+{
+ matrix_entry *m = &matrix_stack[matrix_stack_used - 1];
+ double x_old = x;
+ double y_old = y;
+ double x_new = x_old * m->a + y_old * m->c + m->e;
+ double y_new = x_old * m->b + y_old * m->d + m->f;
+ *retx = (scaled) DO_ROUND(x_new);
+ *rety = (scaled) DO_ROUND(y_new);
+}
+
+void matrixtransformrect(scaled llx, scaled lly, scaled urx, scaled ury)
+{
+ scaled x1, x2, x3, x4, y1, y2, y3, y4;
+
+ if (page_mode && matrix_stack_used > 0) {
+ last_llx = llx;
+ last_lly = lly;
+ last_urx = urx;
+ last_ury = ury;
+ do_matrixtransform(llx, lly, &x1, &y1);
+ do_matrixtransform(llx, ury, &x2, &y2);
+ do_matrixtransform(urx, lly, &x3, &y3);
+ do_matrixtransform(urx, ury, &x4, &y4);
+ ret_llx = DO_MIN(DO_MIN(x1, x2), DO_MIN(x3, x4));
+ ret_lly = DO_MIN(DO_MIN(y1, y2), DO_MIN(y3, y4));
+ ret_urx = DO_MAX(DO_MAX(x1, x2), DO_MAX(x3, x4));
+ ret_ury = DO_MAX(DO_MAX(y1, y2), DO_MAX(y3, y4));
+ } else {
+ ret_llx = llx;
+ ret_lly = lly;
+ ret_urx = urx;
+ ret_ury = ury;
+ }
+}
+
+void matrixtransformpoint(scaled x, scaled y)
+{
+ if (page_mode && matrix_stack_used > 0) {
+ do_matrixtransform(x, y, &ret_llx, &ret_lly);
+ } else {
+ ret_llx = x;
+ ret_lly = y;
+ }
+}
+
+void matrixrecalculate(scaled urx)
+{
+ matrixtransformrect(last_llx, last_lly, urx, last_ury);
+}
+
+void
+check_buffer_overflow (int wsize) {
+ int nsize;
+ if (wsize>buf_size) {
+ nsize = buf_size + buf_size/5+5;
+ if (nsize<wsize) {
+ nsize = wsize+5;
+ }
+ buffer = (unsigned char *)xreallocarray (buffer, char, nsize);
+ buf_size = nsize;
+ }
+}
+
+#define EXTRA_STRING 500
+
+void
+check_pool_overflow (int wsize) {
+ int nsize ;
+ if ((wsize-1)>pool_size) {
+ nsize = pool_size + pool_size/5+EXTRA_STRING;
+ if (nsize<wsize) {
+ nsize = wsize+EXTRA_STRING;
+ }
+ str_pool = (unsigned char *)xreallocarray (str_pool, char, nsize);
+ pool_size = nsize;
+ }
+}
+
+#define max_integer 0x7FFFFFFF
+
+/* the return value is a decimal number with the point |dd| places from the back,
+ |scaled_out| is the number of scaled points corresponding to that.
+*/
+
+scaled divide_scaled (scaled s, scaled m, integer dd) {
+ register scaled q;
+ register scaled r;
+ int i;
+ int sign = 1;
+ if (s < 0) {
+ sign = -sign;
+ s = -s;
+ }
+ if (m < 0) {
+ sign = -sign;
+ m = -m;
+ }
+ if (m == 0) {
+ pdf_error(maketexstring("arithmetic"), maketexstring("divided by zero"));
+ } else if (m >= (max_integer / 10)) {
+ pdf_error(maketexstring("arithmetic"), maketexstring("number too big"));
+ }
+ q = s / m;
+ r = s % m;
+ for (i = 1;i<=(int)dd;i++) {
+ q = 10*q + (10*r) / m;
+ r = (10*r) % m;
+ }
+ /* rounding */
+ if (2*r >= m) {
+ q++;
+ r -= m;
+ }
+ /* set up the value of q, in scaled points */
+ switch(dd) {
+ case 0: scaled_out = sign*(s - r); break;
+ case 1: scaled_out = sign*(s - (r/10)); break;
+ case 2: scaled_out = sign*(s - (r/100)); break;
+ case 3: scaled_out = sign*(s - (r/1000)); break;
+ case 4: scaled_out = sign*(s - (r/10000)); break;
+ case 5: scaled_out = sign*(s - (r/100000)); break;
+ case 6: scaled_out = sign*(s - (r/1000000)); break;
+ case 7: scaled_out = sign*(s - (r/10000000)); break;
+ case 8: scaled_out = sign*(s - (r/100000000)); break;
+ case 9: scaled_out = sign*(s - (r/1000000000)); break;
+ }
+ return sign*q;
+}
+
+
+/* Sometimes there is one sp of difference in |scaled_out|
+ * compared to the 'perfect' answer given above, but this
+ * routine is only used by the pdf backend, not for typesetting.
+ */
+
+scaled
+divide_scaled_n (double sd, double md, double n) {
+ int d = (int)(sd/md*n+0.5);
+ scaled_out = (int)(d/n*md);
+ return d;
+}
+
+
+/* C print interface */
+
+void tprint (char *s) {
+ while (*s)
+ print_char(*s++);
+}
+
+void tprint_nl (char *s) {
+ print_nlp();
+ tprint(s);
+}
+
+#define escape_char_code 45 /* escape character for token output */
+#define int_par(a) zeqtb[static_int_base+(a)].cint /* an integer parameter */
+#define escape_char int_par(escape_char_code)
+
+void tprint_esc(char *s) { /* prints escape character, then |s| */
+ int c=-1; /* the escape character code */
+ if (zeqtb!=NULL) {
+ c=escape_char;
+ if (c>=0)
+ print_char(c);
+ }
+ tprint(s);
+}
+
+void tconfusion(char *s) {
+ confusion(maketexstring(s));
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/writezip.c b/Build/source/texk/web2c/luatexdir/writezip.c
new file mode 100644
index 00000000000..b915413ccfe
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/writezip.c
@@ -0,0 +1,98 @@
+/*
+Copyright (c) 1996-2007 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id $
+*/
+
+#include "ptexlib.h"
+#include "zlib.h"
+#include <assert.h>
+
+#define ZIP_BUF_SIZE 32768
+
+#define check_err(f, fn) \
+ if (f != Z_OK) \
+ pdftex_fail("zlib: %s() failed (error code %d)", fn, f)
+
+static char *zipbuf = NULL;
+static z_stream c_stream; /* compression stream */
+
+void write_zip(boolean finish)
+{
+ int err;
+ static int level_old = 0;
+ int level = get_pdf_compress_level();
+ assert(level > 0);
+ cur_file_name = NULL;
+ if (pdf_stream_length == 0) {
+ if (zipbuf == NULL) {
+ zipbuf = xtalloc(ZIP_BUF_SIZE, char);
+ c_stream.zalloc = (alloc_func) 0;
+ c_stream.zfree = (free_func) 0;
+ c_stream.opaque = (voidpf) 0;
+ check_err(deflateInit(&c_stream, level), "deflateInit");
+ } else {
+ if (level != level_old) { /* \pdfcompresslevel change in mid document */
+ check_err(deflateEnd(&c_stream), "deflateEnd");
+ c_stream.zalloc = (alloc_func) 0; /* these 3 lines no need, just to be safe */
+ c_stream.zfree = (free_func) 0;
+ c_stream.opaque = (voidpf) 0;
+ check_err(deflateInit(&c_stream, level), "deflateInit");
+ } else
+ check_err(deflateReset(&c_stream), "deflateReset");
+ }
+ level_old = level;
+ c_stream.next_out = (Bytef *) zipbuf;
+ c_stream.avail_out = ZIP_BUF_SIZE;
+ }
+ assert(zipbuf != NULL);
+ c_stream.next_in = pdf_buf;
+ c_stream.avail_in = pdf_ptr;
+ for (;;) {
+ if (c_stream.avail_out == 0) {
+ pdf_gone += xfwrite(zipbuf, 1, ZIP_BUF_SIZE, pdf_file);
+ pdf_last_byte = zipbuf[ZIP_BUF_SIZE - 1]; /* not needed */
+ c_stream.next_out = (Bytef *) zipbuf;
+ c_stream.avail_out = ZIP_BUF_SIZE;
+ }
+ err = deflate(&c_stream, finish ? Z_FINISH : Z_NO_FLUSH);
+ if (finish && err == Z_STREAM_END)
+ break;
+ check_err(err, "deflate");
+ if (!finish && c_stream.avail_in == 0)
+ break;
+ }
+ if (finish) {
+ if (c_stream.avail_out < ZIP_BUF_SIZE) { /* at least one byte has been output */
+ pdf_gone +=
+ xfwrite(zipbuf, 1, ZIP_BUF_SIZE - c_stream.avail_out, pdf_file);
+ pdf_last_byte = zipbuf[ZIP_BUF_SIZE - c_stream.avail_out - 1];
+ }
+ xfflush(pdf_file);
+ }
+ pdf_stream_length = c_stream.total_out;
+}
+
+void zip_free(void)
+{
+ if (zipbuf != NULL) {
+ check_err(deflateEnd(&c_stream), "deflateEnd");
+ free(zipbuf);
+ }
+}
diff --git a/Build/source/texk/web2c/web2c/coerce.h b/Build/source/texk/web2c/web2c/coerce.h
index 204fce17767..7f5bfa2cd79 100644
--- a/Build/source/texk/web2c/web2c/coerce.h
+++ b/Build/source/texk/web2c/web2c/coerce.h
@@ -1,5 +1,6 @@
/* Some definitions that get appended to the `coerce.h' file that web2c
outputs. */
+/* $Id$ */
/* The C compiler ignores most unnecessary casts (i.e., casts of
something to its own type). However, for structures, it doesn't.
@@ -49,6 +50,10 @@ extern poolpointer makesrcspecial P2H(strnumber, int);
extern void remembersourceinfo P2H(strnumber, int);
#endif
+#ifdef luaTeX
+#include <luatexdir/luatex.h>
+#endif /* luaTeX */
+
#ifdef pdfTeX
#include <pdftexdir/pdftex.h>
#endif /* pdfTeX */
diff --git a/Build/source/texk/web2c/web2c/splitup.c b/Build/source/texk/web2c/web2c/splitup.c
index bb3c471efac..f92933c52ba 100644
--- a/Build/source/texk/web2c/web2c/splitup.c
+++ b/Build/source/texk/web2c/web2c/splitup.c
@@ -2,6 +2,8 @@
and it produces several .c and .h files in the current directory
as its output.
+ $Id$
+
Tim Morgan September 19, 1987. */
#include "config.h"
@@ -110,6 +112,9 @@ main P2C(int, argc, string *, argv)
} else if (STREQ (output_name, "pdftex")) {
fputs ("#define INITEX\n#define TeX\n#define pdfTeX\n", out);
coerce = "pdftexcoerce.h";
+ } else if (STREQ (output_name, "luatex")) {
+ fputs ("#define INITEX\n#define TeX\n#define luaTeX\n", out);
+ coerce = "luatexcoerce.h";
} else if (STREQ (output_name, "pdfetex")) {
fputs ("#define INITEX\n#define TeX\n#define pdfeTeX\n", out);
coerce = "pdfetexcoerce.h";
@@ -120,7 +125,7 @@ main P2C(int, argc, string *, argv)
fputs ("#define INIMP\n#define MP\n", out);
coerce = "mpcoerce.h";
} else
- FATAL1 ("Can only split mf, mp, tex, etex, omega, eomega, aleph, pdf[e]tex, or xetex,\n not %s", output_name);
+ FATAL1 ("Can only split mf, mp, tex, etex, omega, eomega, aleph, luatex, pdf[e]tex, or xetex,\n not %s", output_name);
coerce_len = strlen (coerce);